From efc4dadb50985ed4a5e8b58da7de95ed20531fd5 Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Tue, 6 Oct 2015 16:10:50 -0500 Subject: [PATCH 001/860] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 7fc9600c..16ed2a55 100644 --- a/README.md +++ b/README.md @@ -162,7 +162,7 @@ The following are defined but incomplete: * bitstring - Implemented, but no pattern matching support yet #### Most of the Standard Library isn't defined yet -A lot of functions in the Kernel module are implemented. The Enum, Atom, List, Tuple, Logger, and Range modules are either fully defined are not complete. The rest still need to be implemented. Some modules like System or File may not be useful or function in the browser and may end up being only useful when using ElixirScript outside of the browser. +A lot of functions in the Kernel module are implemented. The Enum, Atom, List, Tuple, Logger, and Range modules are either fully defined or not complete. The rest still need to be implemented. Some modules like System or File may not be useful or function in the browser and may end up being only useful when using ElixirScript outside of the browser. ### Example projects From 40508fd8669bbb2c2cc38bda890cd7870442d322 Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Wed, 7 Oct 2015 10:53:48 -0500 Subject: [PATCH 002/860] Added signal.js. Added GettingStarted CONTRIBUTING and FAQ --- CONTRIBUTING.md | 179 +++++++++++++++++++++++++++++ FAQ.md | 107 ++++++++++++++++++ GettingStarted.md | 201 +++++++++++++++++++++++++++++++++ priv/javascript/lib/signals.js | 61 ++++++++++ 4 files changed, 548 insertions(+) create mode 100644 CONTRIBUTING.md create mode 100644 FAQ.md create mode 100644 GettingStarted.md create mode 100644 priv/javascript/lib/signals.js diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md new file mode 100644 index 00000000..1b3e61ce --- /dev/null +++ b/CONTRIBUTING.md @@ -0,0 +1,179 @@ +# Contributing to ElixirScript + +This contributing guide is based on the contributing for Elixir with changes suitable for this project. + +## Using the issue tracker + +Use the issues tracker for: + +* [bug reports](#bug-reports) +* [submitting pull requests](#pull-requests) +* [feature requests](#feature-requests) + +## Bug reports + +A bug is a _demonstrable problem_ that is caused by the code in the repository. +Good bug reports are extremely helpful - thank you! + +Guidelines for bug reports: + +1. **Use the GitHub issue search** — [check if the issue has already been + reported](https://github.com/bryanjos/elixirscript/search?type=Issues). + +2. **Check if the issue has been fixed** — try to reproduce it using the + `master` branch in the repository. + +3. **Isolate and report the problem** — ideally create a reduced test + case. + +Please try to be as detailed as possible in your report. Please provide steps to +reproduce the issue as well as the outcome you were expecting! All these details +will help developers to fix any potential bugs. + +Example: + +> Short and descriptive example bug report title +> +> A summary of the issue and the environment in which it occurs. If suitable, +> include the steps required to reproduce the bug. +> +> 1. This is the first step +> 2. This is the second step +> 3. Further steps, etc. +> +> `` - a link to the reduced test case (e.g. a GitHub Gist) +> +> Any other information you want to share that is relevant to the issue being +> reported. This might include the lines of code that you have identified as +> causing the bug, and potential solutions (and your opinions on their +> merits). + +## Feature requests + +Feature requests are welcome. But take a moment to find +out whether your idea fits with the scope and aims of the project. It's up to *you* +to make a strong case to convince the community of the merits of this feature. +Please provide as much detail and context as possible. + +## Contributing + +Contributions to ElixirScript are welcomed! These contributions can be +in the form or code changes, documentation, or ideas of how to implement features +found in Elixir in ElixirScript. + +ElixirScript is broken up into 2 parts: + +* The compiler, written in Elixir +* The runtime, written in JavaScript + +The ElixirScript compiler is in the `lib` folder of the project. +Here is where Elixir code is converted into JavaScript. + +The JavaScript code is in the `priv/javascript`. +This is where features such as pattern matching and the standard library are implemented. + +The ElixirScript tests can be run using `mix test` + +The JavaScript tests can be run using `gulp test` + +Please make sure all tests pass after making changes. Also make sure to include tests for +the changes you made. + +Contributing to the JavaScript code may be the easiest and most rewarding changes. +Don't see a feature, module or function from Elixir in ElixirScript yet? You can implement it +in the JavaScript code. + +## Pull requests + +Good pull requests - patches, improvements, new features - are a fantastic +help. They should remain focused in scope and avoid containing unrelated +commits. + +**NOTE**: Do not send code style changes as pull requests like changing +the indentation of some particular code snippet or how a function is called. +Those will not be accepted as they pollute the repository history with non +functional changes and are often based on personal preferences. + +**IMPORTANT**: By submitting a patch, you agree that your work will be +licensed under the license used by the project. + +If you have any large pull request in mind (e.g. implementing features, +refactoring code, etc), **please ask first** otherwise you risk spending +a lot of time working on something that the project's developers might +not want to merge into the project. + +Please adhere to the coding conventions in the project (indentation, +accurate comments, etc.) and don't forget to add your own tests and +documentation. When working with Git, we recommend the following process +in order to craft an excellent pull request: + +1. [Fork](https://help.github.com/fork-a-repo/) the project, clone your fork, + and configure the remotes: + + ```sh + # Clone your fork of the repo into the current directory + git clone https://github.com//elixirscript + # Navigate to the newly cloned directory + cd elixirscript + # Assign the original repo to a remote called "upstream" + git remote add upstream https://github.com/bryanjos/elixirscript + ``` + +2. If you cloned a while ago, get the latest changes from upstream: + + ```sh + git checkout master + git pull upstream master + ``` + +3. Create a new topic branch (off of `master`) to contain your feature, change, + or fix. + + **IMPORTANT**: Making changes in `master` is discouraged. You should always + keep your local `master` in sync with upstream `master` and make your + changes in topic branches. + + ```sh + git checkout -b + ``` + +4. Commit your changes in logical chunks. Keep your commit messages organized, + with a short description in the first line and more detailed information on + the following lines. Feel free to use Git's + [interactive rebase](https://help.github.com/articles/interactive-rebase) + feature to tidy up your commits before making them public. + +5. Make sure all the tests are still passing. + + ```sh + mix test + gulp test + ``` + + This is needed to ensure your changes can + pass all the tests. + +6. Push your topic branch up to your fork: + + ```sh + git push origin + ``` + +7. [Open a Pull Request](https://help.github.com/articles/using-pull-requests/) + with a clear title and description. + +8. If you haven't updated your pull request for a while, you should consider + rebasing on master and resolving any conflicts. + + **IMPORTANT**: _Never ever_ merge upstream `master` into your branches. You + should always `git rebase` on `master` to bring your changes up to date when + necessary. + + ```sh + git checkout master + git pull upstream master + git checkout + git rebase master + ``` + +Thank you for your contributions! \ No newline at end of file diff --git a/FAQ.md b/FAQ.md new file mode 100644 index 00000000..68da785d --- /dev/null +++ b/FAQ.md @@ -0,0 +1,107 @@ +# FAQ + +## Q. Why the `exjs` file extension instead of `ex` or `exs`? + +### A. Because you may reference JavaScript code in your ElixirScript modules that the Elixir compiler may not know about. + +For instance, if you are writing an ElixirScript module that references JQuery or React. Since the Elixir compiler won't know about the existence of these, you may end up with some compiler errors. The main purpose is to sort of hide it from the Elixir compiler. You can feed normal `.ex` files to the ElixirScript compiler and it can turn them into JavaScript however. + +In the future, the added file extension may not be needed as much as ElixirScript continues to support more of the Elixir standard library. An eventual goal would be to use standard `.ex` files in both Elixir and ElixirScript, while leaving `exjs` files strictly for JavaScript related code. + +# Q. How much is implemented? + +### A. Most of Kernel.SpecialForms as well as some modules in the Standard Library + +The compiler to this point has been focused on translating Kernel.SpecialForms and Kernel. Below is a list of what is complete, incomplete, as well as missing + +#### Kernel.SpecialForms + +* Complete + * `__DIR__` + * `__MODULE__` + * `^var` + * `&expr` + * `for` + * `%{}` + * `{args}` + * `<>` + * `fn [clauses] end` + * `cond(clauses)` + * `__block__` + * `__aliases__` + * `unquote` + * `unquote_splicing` + * `%` + * `left.right` + * `quote` + * `import` + * `case` + * `left = right` + * `require` + * `left :: right` + * `alias` + +* Missing + * `__CALLER__` + * `__ENV__` + * `super(args)` + +* Caveats + * `<>` - not supported in pattern matching yet + * `quote` - ignores `location` and `context` options + * `left = right` does not support full unification yet. + ```elixir + a = 1 # works as expected + + 1 = a # may not work currently, but in some cases it will + ``` + + +#### Completed Modules + + * Tuple + * List + * Atom + * Range + * Logger + +#### Incomplete Modules + + * Kernel + * Enum + * Agent + * Integer + * Keyword + +#### Missing Modules + * Everything else + + +## Q. Can I use it today? + +### A. Yes, but don't expect it to be pretty or idiomatic. Also it is not production ready. + +You **can** use ElixirScript on your front ends and have it work and interoperate with JavaScript modules. The problem is since most of the standard library is incomplete, it will not feel the same. It will feel like some basterdized hybrid of Elixir and JavaScript. That is not the goal of the project. The end goal is to have it look and feel like Elixir code with the added availability of JavaScript modules. + +## Q. Can I use pattern matching? + +### A. Yes, but not for bitstrings (yet) + +## Q. Can I use processes? + +### A. No, but follow [this issue](https://github.com/bryanjos/elixirscript/issues/95). Any ideas or contributions are appreciated. + + + +## Q. Will it be able to do the things that Elm can? + +### A. Maybe, but in an idiomatic fashion. + +One of my demos is an example of using a design similar to redux to accomplish the things that redux does only using the Elixir standard library. Redux is influenced by Elm. The goal is to eventually allow for designs that can be Elm influenced if that is the desire. Similar to the same way the José saya to bring the spirit of projects from other languages to Elixir and not always just a straight port. If processes are added, I believe it will be easier to do those things in an idiomatic Elixir way. + + +## Q. What about OTP? + +### A. Maybe. + +Once processes are added, then we can see about adding OTP similar or specific things to ElixirScript. \ No newline at end of file diff --git a/GettingStarted.md b/GettingStarted.md new file mode 100644 index 00000000..9f9a5f22 --- /dev/null +++ b/GettingStarted.md @@ -0,0 +1,201 @@ +# Getting Started with ElixirScript + + +The intent of this guide is to get you started with ElixirScript. It will give you instructions on using ElixirScript. I will go over the three ways you can use ElixirScript: + +* As an escript +* As a mix task +* As a library in your application + +### Escript + +* Step 1: Get escript + + You can download the elixirscript escript from the [releases page on github](https://github.com/bryanjos/elixirscript/releases). It is a tar file named ex2js.tar.gz. + +* Step 2: Untar + + Next, untar ex2js.tar.gz + + ```bash + tar -xvzf ex2js.tar.gz + ``` + + You will want to put the bin folder from the uncompressed folder into your path. This should allow you to use the ex2js escript. + +* Step 3: Use + + This is the help output of ex2js + + ```bash + usage: ex2js [options] + + path to elixir files or + the elixir code string if the -ex flag is used + + options: + -o --output [path] places output at the given path + -ex --elixir read input as elixir code string + -r --root [path] root path for standard libs + -h --help this message + ``` + + the `` is the elixir code string or file path you want to convert from elixir to javascript. Below is an example of using a code string and turning it into JavaScript + + ```bash + $ ex2js ":atom" -ex + Kernel.SpecialForms.atom('atom') + ``` + + The ex2js escript changed the elixir code, `:atom` into the JavaScript code `Kernel.SpecialForms.atom('atom')`. The `-ex` parameter lets the script know that the input is an Elixir code string instead of a file. + + What if we wanted to give it a file? You would simply do the following: + + ```bash + $ ex2js "example.exjs" + Kernel.SpecialForms.atom('atom') + ``` + + What you will have noticed by now is that it has output everything we've done so far to the terminal. What about if we want to place the output to a path? The next example takes a file as input and outputs the result in another directory. + + ```bash + $ ex2js "example.exjs" -o "dist" + ``` + + If you look in the dist folder, you should see example.js as well as elixir.js. elixir.js is the JavaScript file that contains the Elixir Standard library. In example.js, the first line should be an import statement importing elixir.js for use. + + wildcards are also accepted: + + ```bash + $ ex2js "src/**/*.exjs" -o "dist" + ``` + + The last option we will show is the root option. This option is for defining a root path for the import statements. By default your import statement will not have anything prepended to it. For example, the elixir import will look like this: + + ```javascript + import { Patterns, Kernel, Atom, Enum, Integer, JS, List, Range, Tuple, Agent, Keyword, BitString } from 'elixir'; + ``` + + If we wanted to prepend "js" to the root, we can like this: + + ``` + $ ex2js "example.ex" -o "dist" -r "js" + ``` + + Now the import will look like this: + + ```javascript + import { Patterns, Kernel, Atom, Enum, Integer, JS, List, Range, Tuple, Agent, Keyword, BitString } from 'js/elixir'; + ``` + + That concludes the walkthrough on options, as well as the walkthrough on using the ex2js escript. + +### mix ex2js + +* Step 1: Get dependency + + The first step is getting the dependency. In your mix.exs file for your elixir project, add elixir_script to your deps. + + ```elixir + {:elixir_script, "~> 0.12"} + ``` + +* Step 2: Now download the dep + + ```bash + $ mix deps.get + ``` + + Now you should have the mix task, ex2js. + +* Step 3: Use + ```bash + $ mix ex2js "example.ex" -o "dist" -r "js" + ``` + + What you will notice is that the parameters are exactly the same as the escript. + +### ElixirScript module +* Step 1: Get dependency + + The first step is getting the dependency. In your mix.exs file for your elixir project, add elixir_script to your deps. + + ```elixir + {:elixir_script, "~> 0.12"} + ``` + +* Step 2: Now download the dep + + ```bash + $ mix deps.get + ``` + +* Step 3: Use + Now you will be able to use the ElixirScript module within your code. + + ```elixir + ElixirScript.compile(":atom") + ``` + + The is also compile_path/2 and compile_quoted/2. Each of the functions take an options keyword list. + + * `:root` - a binary path prepended to the path of the standard lib imports if needed + * `:env` - a Macro.env struct to use. This is most useful when using macros. Make sure that the given env has the macros required. Defaults to `__ENV__`. + + You may notice the mention of macros. Using the module in your code allows you to use macros. As long as you pass in an evironment with the macros loaded. By default, it uses the current environment. + + For example, if I have a module with a macro in it + + ```elixir + defmodule ElixirScript.Math do + defmacro squared(x) do + quote do + unquote(x) * unquote(x) + end + end + end + ``` + + If I create a custom env I can pass it to the compile functions: + + ```elixir + def make_custom_env do + require Logger + require ElixirScript.Math + + __ENV__ + end + + ElixirScript.compile("ElixirScript.Math.squared(2)", [env: make_custom_env]) + + #Should return ["2 * 2"] + ``` + + + +### Appendix + +#### Gulp + +I am a gulp user and I use elixirscript with gulp. Here is a snippet of how I my gulpfile looks + + ```javascript + var gulp = require('gulp'); + var exec = require('child_process').exec; + var babel = require('gulp-babel'); + + //Calls out to the escript and places the output in src/js + gulp.task('build-exjs', function(cb) { + exec('/usr/local/ex2js/bin/ex2js "' + exjsSrc + '" -o ' + "src/js", function (err, stdout, stderr) { + cb(err); + }); + }); + + gulp.task('build-js', ['build-exjs'], function() { + return gulp.src(jsSrc) + .pipe(babel({modules: 'system'})) + .pipe(gulp.dest(jsDest)); + }); + ``` + +This is also the setup I use when using ElixirScript with Phoenix. If you are a brunch user, there is n [ElixirScript runch plugin](https://www.npmjs.com/package/elixirscript-brunch) \ No newline at end of file diff --git a/priv/javascript/lib/signals.js b/priv/javascript/lib/signals.js new file mode 100644 index 00000000..076f44f3 --- /dev/null +++ b/priv/javascript/lib/signals.js @@ -0,0 +1,61 @@ +/* @flow */ + +import SpecialForms from './kernel/special_forms'; +import List from './list'; +import Enum from './enum'; + +class Signal { + bindings: Array; + + constructor() { + this.bindings = SpecialForms.list(); + } + + add(listener: Function, context: any = this): void { + this.bindings = List.append(this.bindings, new SignalBinding(this, listener, context)); + } + + remove(listener: Function): void { + this.bindings = Enum.filter(this.bindings, function(binding){ + return binding.listener !== listener; + }); + } + + dispatch(...params: Array): void { + for(let binding of this.bindings){ + binding.execute(...params); + } + } + + dispose(): void { + for(let binding of this.bindings){ + binding.dispose(); + } + + this.bindings = null; + } +} + +class SignalBinding { + listener: Function; + signal: Signal; + context: any; + + constructor(signal: Signal, listener: Function, context: any){ + this.listener = listener; + this.signal = signal; + this.context = context; + } + + execute(...params: Array): void { + this.listener.apply(this.context, params); + } + + dispose(): void { + this.listener = null; + this.signal = null; + this.context = null; + } +} + +export default Signal; \ No newline at end of file From c2a895b2206a275090967ea5a69830a1c797163e Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Wed, 7 Oct 2015 11:04:14 -0500 Subject: [PATCH 003/860] Updated README.md --- GettingStarted.md | 12 +++ README.md | 138 +++-------------------------- gulpfile.js | 2 + mix.exs | 7 +- mix.lock | 2 +- package.json | 4 +- priv/javascript/lib/post_office.js | 74 ++++++++++++---- 7 files changed, 89 insertions(+), 150 deletions(-) diff --git a/GettingStarted.md b/GettingStarted.md index 9f9a5f22..cca3f28c 100644 --- a/GettingStarted.md +++ b/GettingStarted.md @@ -175,6 +175,18 @@ The intent of this guide is to get you started with ElixirScript. It will give y ### Appendix +#### Using JavaScript Modules + +You can use `alias`, `import`, and `require` as you would in Elixir (sans macros). + +For JavaScript modules, use `JS.import` + +```elixir +JS.import A, "a" #translates to "import {default as A} from 'a'" + +JS.import [A, B, C], "a" #translates to "import {A, B, C} from 'a'" +``` + #### Gulp I am a gulp user and I use elixirscript with gulp. Here is a snippet of how I my gulpfile looks diff --git a/README.md b/README.md index 16ed2a55..e656cd9a 100644 --- a/README.md +++ b/README.md @@ -5,26 +5,18 @@ The goal is to convert a subset (or full set) of Elixir code to JavaScript, prov Requirements =========== * Elixir -* Node or io.js (only for development) +* Node (only for development) Usage ======== -ElixirScript can be used in the following ways: +Please check the [Getting Started Guide](GettingStarted.md) for usage -* If using as part of a project, you can add the following to your deps - - ```elixir - {:elixir_script, "~> 0.12"} - ``` - - From there you can either use the ElixirScript module directly or the mix command, `mix ex2js` - -* CLI Client - - You can download the latest release from the [releases](https://github.com/bryanjos/elixirscript/releases) page and use the included `ex2js` escript. +FAQ, Limitations +======== +Please check the [FAQ](FAQ.md) Development @@ -46,129 +38,19 @@ Compile Test mix test + gulp test -Usage -=== - -``` - usage: ex2js [options] - - path to elixir files or - the elixir code string if the -ex flag is used - - options: - -o --output [path] places output at the given path - -ex --elixir read input as elixir code string - -r --root [path] root path for standard libs - -h --help this message -``` - -A note on `-r`. The standard lib modules are included in the output as `elixir.js`. They are by default included by importing them like so - -```javascript -import {...} from 'elixir' -``` - -Depending on your setup that may not work. With `-r` you can specify the root path that will be prepended to the default path. - -Ex. -```bash -mix ex2js "my/elixir/dir/**/*.ex" -r "js" -o my/js/dir -``` - -Will make the standard lib imports look like so -```javascript -import {...} from 'js/elixir' -``` - - -## Examples - - * Using the included mix command, converting a folder of elixir files to JavaScript - ```bash - mix ex2js "my/elixir/dir/**/*.ex" -o my/js/dir - ``` - - * Using the included mix command, if you want to give it some elixir code and output JavaScript in the terminal - ```bash - mix ex2js -ex "[1, 2, 3, 4]" - ``` - - * Using the included the ElixirScript module to turn Elixir code into JavaScript - ```elixir - iex(1)> ElixirScript.compile("[1, 2, 3, 4]") - ["Kernel.SpecialForms.list(1,2,3,4)"] - ``` - -# Macros - -Macros can only be used when using ElixirScript as a library if the Macros are loaded into the current environment or if you give it a custom environment with the `env` option - -```elixir -#module with macro defined -defmodule Math do - defmacro squared(x) do - quote do - unquote(x) * unquote(x) - end - end -end - -#create an env with the module required if not already in the current enviroment -def make_custom_env do - require Logger - require Math - __ENV__ -end - - -#Now pass it to `ElixirScript.compile` -ElixirScript.compile(""" - Math.squared(1) -""", env: make_custom_env) - -# returns ["1 * 1"] -``` - -You should be able to use `use` in modules now as well, but modules that have `__using__` macros must also be require'd so that they can be expanded. - - -# Using JavaScript libraries - -You can use `alias`, `import`, and `require` as you would in Elixir (sans macros). - -For JavaScript modules, use `JS.import` - -```elixir -JS.import A, "a" #translates to "import {default as A} from 'a'" - -JS.import [A, B, C], "a" #translates to "import {A, B, C} from 'a'" -``` - -# Limitations - -#### Not all of the Kernel.SpecialForms module is defined - -The following aren't defined (yet): - -* `__CALLER__` -* `__ENV__` -* super - -The following are defined but incomplete: - -* quote - Currently ignores `:location` and `:context` options -* bitstring - Implemented, but no pattern matching support yet +Contributing +======== -#### Most of the Standard Library isn't defined yet -A lot of functions in the Kernel module are implemented. The Enum, Atom, List, Tuple, Logger, and Range modules are either fully defined or not complete. The rest still need to be implemented. Some modules like System or File may not be useful or function in the browser and may end up being only useful when using ElixirScript outside of the browser. +Please check the [CONTRIBUTING.md](CONTRIBUTING.md) ### Example projects * [phoenix_chat_example](https://github.com/bryanjos/phoenix_chat_example) The Pheonix Chat App using ElixirScript. * [MobileElixir](https://github.com/bryanjos/MobileElixir) Using ElixirScript with React Native -* [color_bar_spike](https://github.com/bryanjos/color_bar_spike) A canvas drawing example using ElixirScript, React and Delorean +* [color_bar_spike](https://github.com/bryanjos/color_bar_spike) A canvas drawing example using ElixirScript, React and a Redux-like design #### Using with Brunch There is a plugin for using ElixirScript in your Brunch project diff --git a/gulpfile.js b/gulpfile.js index 72397e0c..4aec5448 100644 --- a/gulpfile.js +++ b/gulpfile.js @@ -6,6 +6,8 @@ var eslint = require('gulp-eslint'); var rollup = require('gulp-rollup'); var sourcemaps = require('gulp-sourcemaps'); +require("babel/polyfill"); + var path = './priv/javascript'; var stdLibPath = path + '/lib/**/*.js'; diff --git a/mix.exs b/mix.exs index aef7120c..48ae99ab 100644 --- a/mix.exs +++ b/mix.exs @@ -13,7 +13,10 @@ defmodule ElixirScript.Mixfile do source_url: "https://github.com/bryanjos/elixirscript", aliases: aliases, test_coverage: [tool: ExCoveralls], - preferred_cli_env: [coveralls: :test] + preferred_cli_env: [coveralls: :test], + docs: [ + extras: ["README.md"] + ] ] end @@ -29,7 +32,7 @@ defmodule ElixirScript.Mixfile do {:estree, "~> 2.0"}, {:shouldi, only: :test }, {:earmark, "~> 0.1", only: :dev }, - {:ex_doc, "~> 0.9", only: :dev }, + {:ex_doc, "~> 0.10", only: :dev }, {:benchfella, "~> 0.2", only: :test}, {:excoveralls, "~> 0.3", only: :test} ] diff --git a/mix.lock b/mix.lock index 48ef915a..88f3ee4c 100644 --- a/mix.lock +++ b/mix.lock @@ -2,7 +2,7 @@ "dogma": {:hex, :dogma, "0.0.7"}, "earmark": {:hex, :earmark, "0.1.17"}, "estree": {:hex, :estree, "2.0.1"}, - "ex_doc": {:hex, :ex_doc, "0.9.0"}, + "ex_doc": {:hex, :ex_doc, "0.10.0"}, "excoveralls": {:hex, :excoveralls, "0.3.11"}, "exjsx": {:hex, :exjsx, "3.2.0"}, "hackney": {:hex, :hackney, "1.3.2"}, diff --git a/package.json b/package.json index e287b863..624c0209 100644 --- a/package.json +++ b/package.json @@ -18,15 +18,17 @@ "dependencies": {}, "devDependencies": { "acorn": "^2.4.0", + "babel": "^5.8.23", "babel-core": "^5.2.12", "chai": "^2.2.0", "gulp": "^3.8.11", "gulp-babel": "^5.1.0", "gulp-concat": "^2.5.2", "gulp-eslint": "^0.13.2", - "gulp-mocha": "^2.0.1", + "gulp-mocha": "^2.1.3", "gulp-rollup": "^1.0.1", "gulp-sourcemaps": "^1.5.2", + "mocha": "^2.3.3", "rollup": "^0.14.1" } } diff --git a/priv/javascript/lib/post_office.js b/priv/javascript/lib/post_office.js index bd3f741e..84021656 100644 --- a/priv/javascript/lib/post_office.js +++ b/priv/javascript/lib/post_office.js @@ -1,4 +1,6 @@ /* @flow */ +import Signal from './signals'; + function update(map: Map, key: Symbol, value: any): Map { let m = new Map(map); m.set(key, value); @@ -11,49 +13,85 @@ function remove(map: Map, key: Symbol): Map { return m; } +class MailBox { + signal: Signal; + messages: Array; + + constructor(context: any = this){ + this.signal = new Signal(); + this.signal.add((...params) => this.messages = this.messages.concat(params), context); + this.messages = []; + } + + receive(...messages){ + this.signal.dispatch(...messages); + } + + peek(){ + if(this.messages.length === 0){ + return null; + } + + return this.messages[0]; + } + + read(){ + let result = this.messages[0]; + this.messages = this.messages.slice(1); + + return result; + } + + add_subscriber(fn: Function, context: any = this){ + this.signal.add(fn, context); + } + + remove_subscriber(fn: Function){ + this.signal.remove(fn); + } + + dispose(){ + this.signal.dispose(); + this.messages = null; + } +} + + class PostOffice { mailboxes: Map; - subscribers: Map; constructor(){ this.mailboxes = new Map(); - this.subscribers = new Map(); } send(address: Symbol, message: any): void { - this.mailboxes = update(this.mailboxes, address, this.mailboxes.get(address).concat([message])); - - if(this.subscribers.get(address)){ - this.subscribers.get(address)(); - } + this.mailboxes.get(address).receive(message); } receive(address: Symbol): any { - let result = this.mailboxes.get(address)[0]; - - this.mailboxes = update(this.mailboxes, address, this.mailboxes.get(address).slice(1)); - return result; + return this.mailboxes.get(address).read(); } peek(address: Symbol): any { - return this.mailboxes.get(address)[0]; + return this.mailboxes.get(address).peek(); } - add_mailbox(address: Symbol = Symbol()): Symbol { - this.mailboxes = update(this.mailboxes, address, []); + add_mailbox(address: Symbol = Symbol(), context: any = this): Symbol { + this.mailboxes = update(this.mailboxes, address, new MailBox()); return address; } remove_mailbox(address: Symbol): void { + this.mailboxes.get(address).dispose(); this.mailboxes = remove(this.mailboxes, address); } - subscribe(address: Symbol, subscribtion_fn: Function): void { - this.subscribers = update(this.subscribers, address, subscribtion_fn); + subscribe(address: Symbol, subscribtion_fn: Function, context: any = this ): void { + this.mailboxes.get(address).add_subscriber(subscribtion_fn, context); } - unsubscribe(address: Symbol): void { - this.subscribers = remove(this.subscribers, address); + unsubscribe(address: Symbol, subscribtion_fn: Function): void { + this.mailboxes.get(address).remove_subscriber(subscribtion_fn); } } From 8a638ab4df1a27cffdd43b4c2939154b0397e449 Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Wed, 7 Oct 2015 15:15:54 -0500 Subject: [PATCH 004/860] Added stdlibs paramter --- lib/elixir_script.ex | 7 +++++++ lib/elixir_script/cli.ex | 10 ++++++++-- 2 files changed, 15 insertions(+), 2 deletions(-) diff --git a/lib/elixir_script.ex b/lib/elixir_script.ex index eabf0875..6473fed7 100644 --- a/lib/elixir_script.ex +++ b/lib/elixir_script.ex @@ -135,6 +135,13 @@ defmodule ElixirScript do File.cp_r!(operating_path <> "/dist", destination) end + @doc """ + Returns the standard lib js code + """ + def standard_libs() do + File.read!(operating_path <> "/dist/elixir.js") + end + defp convert_to_code(js_ast, root, include_path, env, import_standard_libs \\ true) do js_ast |> process_module(root, env, import_standard_libs) diff --git a/lib/elixir_script/cli.ex b/lib/elixir_script/cli.ex index 54fae872..ecf635e9 100644 --- a/lib/elixir_script/cli.ex +++ b/lib/elixir_script/cli.ex @@ -3,11 +3,11 @@ defmodule ElixirScript.CLI do @switches [ output: :binary, elixir: :boolean, root: :binary, - help: :boolean + help: :boolean, stdlib: :boolean ] @aliases [ - o: :output, ex: :elixir, h: :help, r: :root + o: :output, ex: :elixir, h: :help, r: :root, st: :stdlib ] def main(argv) do @@ -21,6 +21,7 @@ defmodule ElixirScript.CLI do case parse do { [help: true] , _ , _ } -> :help + { [stdlib: true] , _ , _ } -> :stdlib { options , [input], _ } -> { input, options } { [], [], [] } -> :help end @@ -36,10 +37,15 @@ defmodule ElixirScript.CLI do -o --output [path] places output at the given path -ex --elixir read input as elixir code string -r --root [path] root path for standard libs + -st --stdlib outputs the standard lib js file -h --help this message """ end + def process(:stdlib) do + IO.write(ElixirScript.standard_libs) + end + def process({ input, options }) do if options_contains_unknown_values(options) do process(:help) From 0e41d4c7b7bdf7067b62878f49e290e346bb9848 Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Fri, 9 Oct 2015 18:07:10 -0500 Subject: [PATCH 005/860] Added processes modules --- gulpfile.js | 7 + priv/javascript/elixir.js | 2 + priv/javascript/lib/enum.js | 8 +- priv/javascript/lib/processes/mailbox.js | 30 +++ priv/javascript/lib/processes/process.js | 117 +++++++++++ .../lib/processes/process_manager.js | 190 ++++++++++++++++++ priv/javascript/lib/processes/scheduler.js | 103 ++++++++++ priv/javascript/lib/processes/states.js | 13 ++ 8 files changed, 469 insertions(+), 1 deletion(-) create mode 100644 priv/javascript/lib/processes/mailbox.js create mode 100644 priv/javascript/lib/processes/process.js create mode 100644 priv/javascript/lib/processes/process_manager.js create mode 100644 priv/javascript/lib/processes/scheduler.js create mode 100644 priv/javascript/lib/processes/states.js diff --git a/gulpfile.js b/gulpfile.js index 4aec5448..f59e845a 100644 --- a/gulpfile.js +++ b/gulpfile.js @@ -55,5 +55,12 @@ gulp.task('dist_add_source_map', function() { .pipe(gulp.dest('./priv/javascript/dist')); }); +gulp.task('common', function() { + return gulp.src(['./priv/javascript/dist/elixir.js']) + .pipe(babel({sourceMap: false, modules:'common'})) + .pipe(gulp.dest('./priv/javascript/umd')); +}); + + gulp.task('default', ['lint', 'test']); diff --git a/priv/javascript/elixir.js b/priv/javascript/elixir.js index ebdb3eb2..40ce1cfe 100644 --- a/priv/javascript/elixir.js +++ b/priv/javascript/elixir.js @@ -1,7 +1,9 @@ import PostOffice from './lib/post_office'; +import ProcessManager from './lib/processes/process_manager'; self.post_office = self.post_office || new PostOffice(); +self.process_manager = self.process_manager || new ProcessManager(); export { default as Patterns } from './lib/patterns/patterns'; export { default as BitString } from './lib/bit_string'; diff --git a/priv/javascript/lib/enum.js b/priv/javascript/lib/enum.js index 961da97e..47676c73 100644 --- a/priv/javascript/lib/enum.js +++ b/priv/javascript/lib/enum.js @@ -99,7 +99,13 @@ let Enum = { }, map: function(collection, fun){ - return collection.map(fun); + let result = []; + + for(let elem of collection){ + result.push(fun(elem)); + } + + return result; }, map_reduce: function(collection, acc, fun){ diff --git a/priv/javascript/lib/processes/mailbox.js b/priv/javascript/lib/processes/mailbox.js new file mode 100644 index 00000000..10b69f1d --- /dev/null +++ b/priv/javascript/lib/processes/mailbox.js @@ -0,0 +1,30 @@ +"use strict"; + +/* @flow */ + +class Mailbox{ + messages: Array + + constructor(){ + this.messages = []; + } + + deliver(message: any){ + this.messages.push(message); + return message; + } + + get(){ + return this.messages; + } + + isEmpty(){ + return this.messages.length === 0; + } + + removeAt(index){ + this.messages.splice(index, 1); + } +} + +export default Mailbox; \ No newline at end of file diff --git a/priv/javascript/lib/processes/process.js b/priv/javascript/lib/processes/process.js new file mode 100644 index 00000000..95b17acb --- /dev/null +++ b/priv/javascript/lib/processes/process.js @@ -0,0 +1,117 @@ +"use strict"; + +/* @flow */ +import Mailbox from "./mailbox"; +import ProcessManager from "./process_manager"; +import States from "./states"; +import Patterns from "../patterns/patterns"; + +const NOMSG = Symbol(); + +class Process { + pid: Number; + mailbox: Mailbox; + func: Function; + args: Array; + manager: ProcessManager; + status: Symbol; + + constructor(pid: Number, func: Function, args: Array, mailbox: Mailbox, manager: ProcessManager){ + this.pid = pid; + this.func = func; + this.args = args; + this.mailbox = mailbox; + this.manager = manager; + this.status = States.STOPPED; + } + + start(){ + let machine = this.main(); + let step = machine.next(); + + this.status = States.RUNNING; + + this.run(machine, step); + } + + *main() { + let retval = States.NORMAL; + + try { + for(let v of this.func.apply(null, this.args)){ + yield v; + } + } catch(e) { + retval = e; + } + + this.manager.exit(this.pid, retval); + } + + exit(reason){ + this.manager.remove_proc(this.pid, reason); + } + + receive(fun){ + let value = NOMSG; + let messages = this.mailbox.get(); + + for(let i = 0; i < messages.length; i++){ + try{ + value = fun(messages[i]); + this.mailbox.removeAt(i); + }catch(e){ + if(!e instanceof Patterns.MatchError){ + this.exit(e); + } + } + } + + return value; + } + + run(machine, step){ + const function_scope = this; + this.manager.set_current(this); + + if(!step.done){ + let value = step.value; + + if(Array.isArray(value) && (value[0] === States.SLEEP || value[0] === States.RECEIVE)){ + if(value[0] === States.SLEEP){ + + this.manager.delay(function() { + function_scope.run(machine, machine.next()); + }, value[1]); + + }else if(value[0] === States.RECEIVE){ + if(value[2] != null && value[2] < Date.now()){ + let result = value[3](); + + this.manager.queue(function() { + function_scope.run(machine, machine.next(result)); + }); + }else{ + let result = function_scope.receive(value[1]); + + if(result === NOMSG){ + this.manager.suspend(function() { + function_scope.run(machine, step); + }); + }else{ + this.manager.queue(function() { + function_scope.run(machine, machine.next(result)); + }); + } + } + } + }else{ + this.manager.queue(function() { + function_scope.run(machine, machine.next()); + }); + } + } + } +} + +export default Process; \ No newline at end of file diff --git a/priv/javascript/lib/processes/process_manager.js b/priv/javascript/lib/processes/process_manager.js new file mode 100644 index 00000000..03933c10 --- /dev/null +++ b/priv/javascript/lib/processes/process_manager.js @@ -0,0 +1,190 @@ +/* @flow */ +"use strict"; + +import Mailbox from "./mailbox"; +import Process from "./process"; +import States from "./states"; +import Scheduler from "./scheduler"; + +class ProcessManager { + + constructor(){ + this.process_counter = 0; + this.pids = new Map(); + this.mailboxes = new Map(); + this.names = new Map(); + this.links = new Map(); + + this.current_process = null; + this.scheduler = new Scheduler(); + this.suspended = new Map(); + } + + set_current(process){ + this.current_process = process; + this.current_process.status = States.RUNNING; + } + + spawn(fun, ...args){ + return this.add_proc(fun, args, false).pid; + } + + spawn_link(fun, ...args){ + return this.add_proc(fun, args, true).pid; + } + + link(pid){ + this.links.get(this.current_process.pid).add(pid); + this.links.get(pid).add(this.current_process.pid); + } + + unlink(pid){ + this.links.get(this.current_process.pid).delete(pid); + this.links.get(pid).delete(this.current_process.pid); + } + + add_proc(fun, args, linked){ + this.process_counter = this.process_counter + 1; + let newpid = this.process_counter; + let mailbox = new Mailbox(); + let newproc = new Process(newpid, fun, args, mailbox, this); + + this.pids.set(newpid, newproc); + this.mailboxes.set(newpid, mailbox); + this.links.set(newpid, new Set()); + + if(linked){ + link(newpid); + } + + newproc.start(); + return newproc; + } + + remove_proc(pid, exitreason){ + this.pids.delete(pid); + this.unregister(pid); + this.scheduler.removePid(pid); + + for (let linkpid in this.links.get(pid).entries()) { + linkpid = Number(linkpid); + + if (exitreason != Normal) { + this.pids.get(linkpid).deliver({ Signal: States.EXIT, From: pid, Reason: exitreason }); + } + + this.links.get(linkpid).delete(pid); + } + + this.links.delete(pid); + } + + register(name, pid){ + if(!this.names.has(name)){ + this.names.set(name, pid) + }else{ + throw new Error("Name is already registered to another process"); + } + } + + registered(name){ + return this.names.has(name) ? this.names.get(name) : null; + } + + unregister(pid){ + for(let name of this.names.keys()){ + if(this.names.has(name) && this.names.get(name) === pid){ + this.names.delete(name); + } + } + } + + pid(){ + return this.current_process.pid; + } + + pidof(id){ + if (typeof(id) === "number") { + return this.pids.has(id) ? id : null; + } else if (id instanceof Process) { + return id.pid; + } else { + let pid = this.registered(id); + if (pid === null) + throw("Er: Process name not registered: " + + id + " (" + typeof(id) + ")"); + return pid; + } + } + + send(id, msg) { + const pid = this.pidof(id); + + if(pid){ + this.mailboxes.get(pid).deliver(msg); + + if(this.suspended.has(pid)){ + let fun = this.suspended.get(pid); + this.suspended.delete(pid); + this.queue(fun); + } + } + + return msg; + } + + receive(fun, timeout = 0, timeoutFn = () => true ) { + let DateTimeout = null; + + if(timeout === 0 || timeout === Infinity){ + DateTimeout = null; + }else{ + DateTimeout = Date.now() + timeout; + } + + return [ + States.RECEIVE, + fun, + DateTimeout, + timeoutFn + ]; + } + + sleep(duration){ + return [States.SLEEP, duration]; + } + + suspend(fun){ + this.current_process.status = States.SUSPENDED; + this.suspended.set(this.current_process.pid, fun); + } + + delay(fun, time){ + this.current_process.status = States.SLEEPING; + this.scheduler.scheduleFuture(this.current_process.pid, time, fun); + } + + queue(fun){ + this.scheduler.schedule(this.current_process.pid, fun); + } + + exit(...args){ + switch(args.length) { + case 2: + if (args[1] != States.NORMAL) { + this.mailboxes.get(args[0]).deliver({ Signal: States.EXIT, From: this.pid(), Reason: args[1] }); + }else{ + this.remove_proc(args[0], args[1]); + } + break; + case 1: + this.current_process.exit(args[0]); + break; + case 0: + this.current_process.exit(States.Normal); + break; + } + } +} + +export default ProcessManager; \ No newline at end of file diff --git a/priv/javascript/lib/processes/scheduler.js b/priv/javascript/lib/processes/scheduler.js new file mode 100644 index 00000000..b8d0cfcf --- /dev/null +++ b/priv/javascript/lib/processes/scheduler.js @@ -0,0 +1,103 @@ +"use strict"; + +//Scheduler. Borrowed and modified from RxJS's Default Scheduler. +//While it is probably more robust, this should fit the needs for +//this project. + +if (typeof setImmediate === 'function') { + var invokeLater = function (callback) { setImmediate(callback); } +} else if (typeof setTimeout === 'function') { + var invokeLater = function (callback) { setTimeout(callback, 0); } +} + +const NOSTATE = Symbol(); + +class Scheduler { + constructor(){ + this.nextHandle = 1; + this.tasks = {} + this.currentlyRunning = false; + } + + clearMethod(handle){ + delete this.tasks[handle]; + } + + removePid(pid){ + //prevent further execution while removing tasks + //with matching pids + this.currentlyRunning = true; + + for(let handle in Object.keys(this.tasks)){ + if(this.tasks[handle] && this.tasks[handle][0] === pid){ + clearMethod(handle); + } + } + + this.currentlyRunning = false; + } + + runTask(handle){ + if (this.currentlyRunning) { + invokeLater(() => { this.runTask(handle); }); + } else { + if(this.tasks[handle]){ + + let [pid, task] = this.tasks[handle]; + + if (task) { + this.currentlyRunning = true; + + let result; + + try{ + result = task(); + }catch(e){ + result = e; + } + + this.clearMethod(handle); + this.currentlyRunning = false; + + if (result instanceof Error) { + throw result; + } + } + + } + } + } + + scheduleMethod(pid, action) { + let id = this.nextHandle++; + this.tasks[id] = [ pid, action ]; + invokeLater(() => { this.runTask(id); }); + + return id; + }; + + schedule(pid, action, state = NOSTATE){ + this.scheduleMethod(pid, () => { + if(state === NOSTATE){ + action(); + }else{ + action(state); + } + }); + } + + scheduleFuture(pid, dueTime, action, state = NOSTATE){ + if (dueTime === 0) { return this.schedule(pid, state, action); } + + setTimeout(pid, () => { + if(state === NOSTATE){ + action(); + }else{ + action(state); + } + }, dueTime); + } + +} + +export default Scheduler; \ No newline at end of file diff --git a/priv/javascript/lib/processes/states.js b/priv/javascript/lib/processes/states.js new file mode 100644 index 00000000..13352018 --- /dev/null +++ b/priv/javascript/lib/processes/states.js @@ -0,0 +1,13 @@ +export default { + NORMAL: Symbol(), + SUSPEND: Symbol(), + CONTINUE: Symbol(), + RECEIVE: Symbol(), + SEND: Symbol(), + SLEEPING: Symbol(), + RUNNING: Symbol(), + SUSPENDED: Symbol(), + STOPPED: Symbol(), + SLEEP: Symbol(), + EXIT: Symbol() +} \ No newline at end of file From 5449bae626539de775d9f96cb60393ae2df05ce9 Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Fri, 9 Oct 2015 20:35:23 -0500 Subject: [PATCH 006/860] Updated implementations of some of the enum functions --- priv/javascript/lib/enum.js | 46 ++++++++++++++++++++++++++++++++----- 1 file changed, 40 insertions(+), 6 deletions(-) diff --git a/priv/javascript/lib/enum.js b/priv/javascript/lib/enum.js index 47676c73..c176025a 100644 --- a/priv/javascript/lib/enum.js +++ b/priv/javascript/lib/enum.js @@ -3,11 +3,23 @@ import Kernel from './kernel'; let Enum = { all__qmark__: function(collection, fun = (x) => x){ - return collection.every(fun); + for(let elem of collection){ + if(!fun(elem)){ + return false; + } + } + + return true; }, any__qmark__: function(collection, fun = (x) => x){ - return collection.some(fun); + for(let elem of collection){ + if(fun(elem)){ + return true; + } + } + + return false; }, at: function(collection, n, the_default = null){ @@ -83,15 +95,29 @@ let Enum = { }, filter: function(collection, fun){ - return collection.filter(fun); + let result = []; + + for(let elem of collection){ + if(fun(elem)){ + result.push(elem); + } + } + + return result; }, filter_map: function(collection, filter, mapper){ - return collection.filter(filter).map(mapper); + return Enum.map(Enum.filter(collection, filter), mapper); }, find: function(collection, if_none = null, fun){ - return collection.find(fun, null, if_none); + for(let elem of collection){ + if(fun(elem)){ + return elem; + } + } + + return if_none; }, into: function(collection, list){ @@ -127,7 +153,15 @@ let Enum = { }, reduce: function(collection, acc, fun){ - return collection.reduce(fun, acc); + let the_acc = acc; + + for (var i = 0; i < this.count(collection); i++) { + let tuple = fun(collection[i], the_acc); + + the_acc = Kernel.elem(tuple, 1); + } + + return the_acc; }, take: function(collection, count){ From 0c67e23fafa356531efbf3c31b31e36dda499715 Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Sat, 10 Oct 2015 12:04:24 -0500 Subject: [PATCH 007/860] Renamed scheduler to task_queue and process_manager back to scheduler --- priv/javascript/elixir.js | 4 +- priv/javascript/lib/processes/process.js | 25 +- .../lib/processes/process_manager.js | 190 --------------- priv/javascript/lib/processes/scheduler.js | 222 ++++++++++++------ priv/javascript/lib/processes/task_queue.js | 86 +++++++ 5 files changed, 255 insertions(+), 272 deletions(-) delete mode 100644 priv/javascript/lib/processes/process_manager.js create mode 100644 priv/javascript/lib/processes/task_queue.js diff --git a/priv/javascript/elixir.js b/priv/javascript/elixir.js index 40ce1cfe..a9d1efd5 100644 --- a/priv/javascript/elixir.js +++ b/priv/javascript/elixir.js @@ -1,9 +1,9 @@ import PostOffice from './lib/post_office'; -import ProcessManager from './lib/processes/process_manager'; +import Scheduler from './lib/processes/scheduler'; self.post_office = self.post_office || new PostOffice(); -self.process_manager = self.process_manager || new ProcessManager(); +self.scheduler = self.scheduler || new Scheduler(); export { default as Patterns } from './lib/patterns/patterns'; export { default as BitString } from './lib/bit_string'; diff --git a/priv/javascript/lib/processes/process.js b/priv/javascript/lib/processes/process.js index 95b17acb..2de5aa4c 100644 --- a/priv/javascript/lib/processes/process.js +++ b/priv/javascript/lib/processes/process.js @@ -2,9 +2,8 @@ /* @flow */ import Mailbox from "./mailbox"; -import ProcessManager from "./process_manager"; +import Scheduler from "./scheduler"; import States from "./states"; -import Patterns from "../patterns/patterns"; const NOMSG = Symbol(); @@ -13,15 +12,15 @@ class Process { mailbox: Mailbox; func: Function; args: Array; - manager: ProcessManager; + scheduler: Scheduler; status: Symbol; - constructor(pid: Number, func: Function, args: Array, mailbox: Mailbox, manager: ProcessManager){ + constructor(pid: Number, func: Function, args: Array, mailbox: Mailbox, scheduler: Scheduler){ this.pid = pid; this.func = func; this.args = args; this.mailbox = mailbox; - this.manager = manager; + this.scheduler = scheduler; this.status = States.STOPPED; } @@ -45,11 +44,11 @@ class Process { retval = e; } - this.manager.exit(this.pid, retval); + this.scheduler.exit(this.pid, retval); } exit(reason){ - this.manager.remove_proc(this.pid, reason); + this.scheduler.remove_proc(this.pid, reason); } receive(fun){ @@ -72,7 +71,7 @@ class Process { run(machine, step){ const function_scope = this; - this.manager.set_current(this); + this.scheduler.set_current(this); if(!step.done){ let value = step.value; @@ -80,7 +79,7 @@ class Process { if(Array.isArray(value) && (value[0] === States.SLEEP || value[0] === States.RECEIVE)){ if(value[0] === States.SLEEP){ - this.manager.delay(function() { + this.scheduler.delay(function() { function_scope.run(machine, machine.next()); }, value[1]); @@ -88,25 +87,25 @@ class Process { if(value[2] != null && value[2] < Date.now()){ let result = value[3](); - this.manager.queue(function() { + this.scheduler.queue(function() { function_scope.run(machine, machine.next(result)); }); }else{ let result = function_scope.receive(value[1]); if(result === NOMSG){ - this.manager.suspend(function() { + this.scheduler.suspend(function() { function_scope.run(machine, step); }); }else{ - this.manager.queue(function() { + this.scheduler.queue(function() { function_scope.run(machine, machine.next(result)); }); } } } }else{ - this.manager.queue(function() { + this.scheduler.queue(function() { function_scope.run(machine, machine.next()); }); } diff --git a/priv/javascript/lib/processes/process_manager.js b/priv/javascript/lib/processes/process_manager.js deleted file mode 100644 index 03933c10..00000000 --- a/priv/javascript/lib/processes/process_manager.js +++ /dev/null @@ -1,190 +0,0 @@ -/* @flow */ -"use strict"; - -import Mailbox from "./mailbox"; -import Process from "./process"; -import States from "./states"; -import Scheduler from "./scheduler"; - -class ProcessManager { - - constructor(){ - this.process_counter = 0; - this.pids = new Map(); - this.mailboxes = new Map(); - this.names = new Map(); - this.links = new Map(); - - this.current_process = null; - this.scheduler = new Scheduler(); - this.suspended = new Map(); - } - - set_current(process){ - this.current_process = process; - this.current_process.status = States.RUNNING; - } - - spawn(fun, ...args){ - return this.add_proc(fun, args, false).pid; - } - - spawn_link(fun, ...args){ - return this.add_proc(fun, args, true).pid; - } - - link(pid){ - this.links.get(this.current_process.pid).add(pid); - this.links.get(pid).add(this.current_process.pid); - } - - unlink(pid){ - this.links.get(this.current_process.pid).delete(pid); - this.links.get(pid).delete(this.current_process.pid); - } - - add_proc(fun, args, linked){ - this.process_counter = this.process_counter + 1; - let newpid = this.process_counter; - let mailbox = new Mailbox(); - let newproc = new Process(newpid, fun, args, mailbox, this); - - this.pids.set(newpid, newproc); - this.mailboxes.set(newpid, mailbox); - this.links.set(newpid, new Set()); - - if(linked){ - link(newpid); - } - - newproc.start(); - return newproc; - } - - remove_proc(pid, exitreason){ - this.pids.delete(pid); - this.unregister(pid); - this.scheduler.removePid(pid); - - for (let linkpid in this.links.get(pid).entries()) { - linkpid = Number(linkpid); - - if (exitreason != Normal) { - this.pids.get(linkpid).deliver({ Signal: States.EXIT, From: pid, Reason: exitreason }); - } - - this.links.get(linkpid).delete(pid); - } - - this.links.delete(pid); - } - - register(name, pid){ - if(!this.names.has(name)){ - this.names.set(name, pid) - }else{ - throw new Error("Name is already registered to another process"); - } - } - - registered(name){ - return this.names.has(name) ? this.names.get(name) : null; - } - - unregister(pid){ - for(let name of this.names.keys()){ - if(this.names.has(name) && this.names.get(name) === pid){ - this.names.delete(name); - } - } - } - - pid(){ - return this.current_process.pid; - } - - pidof(id){ - if (typeof(id) === "number") { - return this.pids.has(id) ? id : null; - } else if (id instanceof Process) { - return id.pid; - } else { - let pid = this.registered(id); - if (pid === null) - throw("Er: Process name not registered: " + - id + " (" + typeof(id) + ")"); - return pid; - } - } - - send(id, msg) { - const pid = this.pidof(id); - - if(pid){ - this.mailboxes.get(pid).deliver(msg); - - if(this.suspended.has(pid)){ - let fun = this.suspended.get(pid); - this.suspended.delete(pid); - this.queue(fun); - } - } - - return msg; - } - - receive(fun, timeout = 0, timeoutFn = () => true ) { - let DateTimeout = null; - - if(timeout === 0 || timeout === Infinity){ - DateTimeout = null; - }else{ - DateTimeout = Date.now() + timeout; - } - - return [ - States.RECEIVE, - fun, - DateTimeout, - timeoutFn - ]; - } - - sleep(duration){ - return [States.SLEEP, duration]; - } - - suspend(fun){ - this.current_process.status = States.SUSPENDED; - this.suspended.set(this.current_process.pid, fun); - } - - delay(fun, time){ - this.current_process.status = States.SLEEPING; - this.scheduler.scheduleFuture(this.current_process.pid, time, fun); - } - - queue(fun){ - this.scheduler.schedule(this.current_process.pid, fun); - } - - exit(...args){ - switch(args.length) { - case 2: - if (args[1] != States.NORMAL) { - this.mailboxes.get(args[0]).deliver({ Signal: States.EXIT, From: this.pid(), Reason: args[1] }); - }else{ - this.remove_proc(args[0], args[1]); - } - break; - case 1: - this.current_process.exit(args[0]); - break; - case 0: - this.current_process.exit(States.Normal); - break; - } - } -} - -export default ProcessManager; \ No newline at end of file diff --git a/priv/javascript/lib/processes/scheduler.js b/priv/javascript/lib/processes/scheduler.js index b8d0cfcf..f3e44a01 100644 --- a/priv/javascript/lib/processes/scheduler.js +++ b/priv/javascript/lib/processes/scheduler.js @@ -1,103 +1,191 @@ +/* @flow */ "use strict"; -//Scheduler. Borrowed and modified from RxJS's Default Scheduler. -//While it is probably more robust, this should fit the needs for -//this project. - -if (typeof setImmediate === 'function') { - var invokeLater = function (callback) { setImmediate(callback); } -} else if (typeof setTimeout === 'function') { - var invokeLater = function (callback) { setTimeout(callback, 0); } -} - -const NOSTATE = Symbol(); +import Mailbox from "./mailbox"; +import Process from "./process"; +import States from "./states"; +import TaskQueue from "./task_queue"; class Scheduler { + constructor(){ - this.nextHandle = 1; - this.tasks = {} - this.currentlyRunning = false; + this.process_counter = 0; + this.pids = new Map(); + this.mailboxes = new Map(); + this.names = new Map(); + this.links = new Map(); + + const throttle = 10; //ms between queued tasks + this.current_process = null; + this.task_queue = new TaskQueue(throttle); + this.suspended = new Map(); } - clearMethod(handle){ - delete this.tasks[handle]; + set_current(process){ + this.current_process = process; + this.current_process.status = States.RUNNING; } - removePid(pid){ - //prevent further execution while removing tasks - //with matching pids - this.currentlyRunning = true; + spawn(fun, ...args){ + return this.add_proc(fun, args, false).pid; + } - for(let handle in Object.keys(this.tasks)){ - if(this.tasks[handle] && this.tasks[handle][0] === pid){ - clearMethod(handle); - } + spawn_link(fun, ...args){ + return this.add_proc(fun, args, true).pid; + } + + link(pid){ + this.links.get(this.current_process.pid).add(pid); + this.links.get(pid).add(this.current_process.pid); + } + + unlink(pid){ + this.links.get(this.current_process.pid).delete(pid); + this.links.get(pid).delete(this.current_process.pid); + } + + add_proc(fun, args, linked){ + this.process_counter = this.process_counter + 1; + let newpid = this.process_counter; + let mailbox = new Mailbox(); + let newproc = new Process(newpid, fun, args, mailbox, this); + + this.pids.set(newpid, newproc); + this.mailboxes.set(newpid, mailbox); + this.links.set(newpid, new Set()); + + if(linked){ + link(newpid); } - this.currentlyRunning = false; + newproc.start(); + return newproc; } - runTask(handle){ - if (this.currentlyRunning) { - invokeLater(() => { this.runTask(handle); }); - } else { - if(this.tasks[handle]){ + remove_proc(pid, exitreason){ + this.pids.delete(pid); + this.unregister(pid); + this.task_queue.removePid(pid); - let [pid, task] = this.tasks[handle]; + for (let linkpid in this.links.get(pid).entries()) { + linkpid = Number(linkpid); - if (task) { - this.currentlyRunning = true; + if (exitreason != Normal) { + this.pids.get(linkpid).deliver({ Signal: States.EXIT, From: pid, Reason: exitreason }); + } - let result; + this.links.get(linkpid).delete(pid); + } - try{ - result = task(); - }catch(e){ - result = e; - } + this.links.delete(pid); + } - this.clearMethod(handle); - this.currentlyRunning = false; + register(name, pid){ + if(!this.names.has(name)){ + this.names.set(name, pid) + }else{ + throw new Error("Name is already registered to another process"); + } + } - if (result instanceof Error) { - throw result; - } - } + registered(name){ + return this.names.has(name) ? this.names.get(name) : null; + } + unregister(pid){ + for(let name of this.names.keys()){ + if(this.names.has(name) && this.names.get(name) === pid){ + this.names.delete(name); } } } - scheduleMethod(pid, action) { - let id = this.nextHandle++; - this.tasks[id] = [ pid, action ]; - invokeLater(() => { this.runTask(id); }); + pid(){ + return this.current_process.pid; + } - return id; - }; + pidof(id){ + if (typeof(id) === "number") { + return this.pids.has(id) ? id : null; + } else if (id instanceof Process) { + return id.pid; + } else { + let pid = this.registered(id); + if (pid === null) + throw("Er: Process name not registered: " + + id + " (" + typeof(id) + ")"); + return pid; + } + } + + send(id, msg) { + const pid = this.pidof(id); + + if(pid){ + this.mailboxes.get(pid).deliver(msg); - schedule(pid, action, state = NOSTATE){ - this.scheduleMethod(pid, () => { - if(state === NOSTATE){ - action(); - }else{ - action(state); + if(this.suspended.has(pid)){ + let fun = this.suspended.get(pid); + this.suspended.delete(pid); + this.queue(fun); } - }); + } + + return msg; } - scheduleFuture(pid, dueTime, action, state = NOSTATE){ - if (dueTime === 0) { return this.schedule(pid, state, action); } + receive(fun, timeout = 0, timeoutFn = () => true ) { + let DateTimeout = null; - setTimeout(pid, () => { - if(state === NOSTATE){ - action(); - }else{ - action(state); - } - }, dueTime); + if(timeout === 0 || timeout === Infinity){ + DateTimeout = null; + }else{ + DateTimeout = Date.now() + timeout; + } + + return [ + States.RECEIVE, + fun, + DateTimeout, + timeoutFn + ]; } + sleep(duration){ + return [States.SLEEP, duration]; + } + + suspend(fun){ + this.current_process.status = States.SUSPENDED; + this.suspended.set(this.current_process.pid, fun); + } + + delay(fun, time){ + this.current_process.status = States.SLEEPING; + this.task_queue.queueFuture(this.current_process.pid, time, fun); + } + + queue(fun){ + this.task_queue.queue(this.current_process.pid, fun); + } + + exit(...args){ + switch(args.length) { + case 2: + if (args[1] != States.NORMAL) { + this.mailboxes.get(args[0]).deliver({ Signal: States.EXIT, From: this.pid(), Reason: args[1] }); + }else{ + this.remove_proc(args[0], args[1]); + } + break; + case 1: + this.current_process.exit(args[0]); + break; + case 0: + this.current_process.exit(States.Normal); + break; + } + } } export default Scheduler; \ No newline at end of file diff --git a/priv/javascript/lib/processes/task_queue.js b/priv/javascript/lib/processes/task_queue.js new file mode 100644 index 00000000..c08a0404 --- /dev/null +++ b/priv/javascript/lib/processes/task_queue.js @@ -0,0 +1,86 @@ +"use strict"; + +//TaskQueue. Borrowed and modified from RxJS's Default Scheduler. +//While it is probably more robust, this should fit the needs for +//this project. + +class TaskQueue { + constructor(throttle = 0){ + this.nextTaskId = 1; + this.tasks = {} + this.isRunning = false; + this.invokeLater = function (callback) { setTimeout(callback, throttle); } + } + + removeFromTaskQueue(taskId){ + delete this.tasks[taskId]; + } + + removePid(pid){ + //prevent further execution while removing tasks + //with matching pids + this.isRunning = true; + + for(let taskId of Object.keys(this.tasks)){ + if(this.tasks[taskId] && this.tasks[taskId][0] === pid){ + this.removeFromTaskQueue(taskId); + } + } + + this.isRunning = false; + } + + runTask(taskId){ + if (this.isRunning) { + this.invokeLater(() => { this.runTask(taskId); }); + } else { + if(this.tasks[taskId]){ + + let [pid, task] = this.tasks[taskId]; + + if (task) { + this.isRunning = true; + + let result; + + try{ + result = task(); + }catch(e){ + result = e; + } + + this.removeFromTaskQueue(taskId); + this.isRunning = false; + + if (result instanceof Error) { + throw result; + } + } + + } + } + } + + addToTaskQueue(pid, task, dueTime = 0) { + let id = this.nextTaskId ++; + this.tasks[id] = [ pid, task ]; + + if(dueTime === 0){ + this.invokeLater(() => { this.runTask(id); }); + }else{ + setTimeout(() => { this.runTask(id); }, dueTime); + } + + return id; + }; + + queue(pid, task){ + this.addToTaskQueue(pid, () => { task(); }); + } + + queueFuture(pid, dueTime, task){ + this.addToTaskQueue(pid, () => { task(); }, dueTime); + } +} + +export default TaskQueue; \ No newline at end of file From 76b7f011ba16f3147fcbdb4f6582059dfa44f4b0 Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Sat, 10 Oct 2015 15:11:56 -0500 Subject: [PATCH 008/860] Updated Kernel translation to use functions from scheduler. Updated receive to do the same. --- lib/elixir_script/translator/kernel.ex | 77 +++++++++++++++++++++- lib/elixir_script/translator/primitive.ex | 7 ++ lib/elixir_script/translator/receive.ex | 4 +- priv/javascript/lib/processes/scheduler.js | 8 +++ priv/javascript/lib/processes/states.js | 23 +++---- test/translator/receive_test.exs | 4 +- 6 files changed, 106 insertions(+), 17 deletions(-) diff --git a/lib/elixir_script/translator/kernel.ex b/lib/elixir_script/translator/kernel.ex index 7851bc70..e41c72f2 100644 --- a/lib/elixir_script/translator/kernel.ex +++ b/lib/elixir_script/translator/kernel.ex @@ -5,7 +5,6 @@ defmodule ElixirScript.Translator.Kernel do alias ElixirScript.Translator.Map alias ElixirScript.Translator.Function alias ElixirScript.Translator.Expression - alias ElixirScript.Translator.Raise @kernel_definitions Kernel.__info__(:functions) ++ Kernel.__info__(:macros) @@ -98,7 +97,81 @@ defmodule ElixirScript.Translator.Kernel do end defp do_translate({:self, _, []}, _) do - JS.identifier(:self) + JS.call_expression( + JS.member_expression( + JS.identifier(:self), + JS.member_expression( + JS.identifier(:scheduler), + JS.identifier(:pid) + ) + ), + [] + ) + end + + defp do_translate({:spawn, _, [fun]}, env) do + JS.call_expression( + JS.member_expression( + JS.identifier(:self), + JS.member_expression( + JS.identifier(:scheduler), + JS.identifier(:spawn) + ) + ), + [Translator.translate(fun, env)] + ) + end + + defp do_translate({:spawn, _, [module, fun, args]}, env) do + JS.call_expression( + JS.member_expression( + JS.identifier(:self), + JS.member_expression( + JS.identifier(:scheduler), + JS.identifier(:spawn_from_module) + ) + ), + [Translator.translate(module, env), Translator.translate(fun, env), Translator.translate(args, env)] + ) + end + + defp do_translate({:spawn_link, _, [fun]}, env) do + JS.call_expression( + JS.member_expression( + JS.identifier(:self), + JS.member_expression( + JS.identifier(:scheduler), + JS.identifier(:spawn_link) + ) + ), + [Translator.translate(fun, env)] + ) + end + + defp do_translate({:spawn_link, _, [module, fun, args]}, env) do + JS.call_expression( + JS.member_expression( + JS.identifier(:self), + JS.member_expression( + JS.identifier(:scheduler), + JS.identifier(:spawn_link_from_module) + ) + ), + [Translator.translate(module, env), Translator.translate(fun, env), Translator.translate(args, env)] + ) + end + + defp do_translate({:exit, _, [reason]}, env) do + JS.call_expression( + JS.member_expression( + JS.identifier(:self), + JS.member_expression( + JS.identifier(:scheduler), + JS.identifier(:exit) + ) + ), + [Translator.translate(reason, env)] + ) end defp do_translate({:tuple_size, _, [tuple]}, env) do diff --git a/lib/elixir_script/translator/primitive.ex b/lib/elixir_script/translator/primitive.ex index c4021ffe..b6b87021 100644 --- a/lib/elixir_script/translator/primitive.ex +++ b/lib/elixir_script/translator/primitive.ex @@ -12,6 +12,13 @@ defmodule ElixirScript.Translator.Primitive do ) end + def scheduler() do + JS.member_expression( + JS.identifier("self"), + JS.identifier("scheduler") + ) + end + def make_wildcard() do JS.member_expression( JS.identifier("fun"), diff --git a/lib/elixir_script/translator/receive.ex b/lib/elixir_script/translator/receive.ex index a71142d3..dbe467cb 100644 --- a/lib/elixir_script/translator/receive.ex +++ b/lib/elixir_script/translator/receive.ex @@ -7,7 +7,7 @@ defmodule ElixirScript.Translator.Receive do def make_receive([do: clauses], env) do JS.call_expression( JS.member_expression( - Primitive.special_forms(), + Primitive.scheduler(), JS.identifier("receive") ), [ @@ -27,7 +27,7 @@ defmodule ElixirScript.Translator.Receive do def make_receive([do: clauses, after: [{:->, _, [[time], _body]}] = after_clause], env) do JS.call_expression( JS.member_expression( - Primitive.special_forms(), + Primitive.scheduler(), JS.identifier("receive") ), [ diff --git a/priv/javascript/lib/processes/scheduler.js b/priv/javascript/lib/processes/scheduler.js index f3e44a01..574aaf1e 100644 --- a/priv/javascript/lib/processes/scheduler.js +++ b/priv/javascript/lib/processes/scheduler.js @@ -30,10 +30,18 @@ class Scheduler { return this.add_proc(fun, args, false).pid; } + spawn_from_module(module, fun, ...args){ + return this.add_proc(module[fun], args, false).pid; + } + spawn_link(fun, ...args){ return this.add_proc(fun, args, true).pid; } + spawn_link_from_module(module, fun, ...args){ + return this.add_proc(module[fun], args, true).pid; + } + link(pid){ this.links.get(this.current_process.pid).add(pid); this.links.get(pid).add(this.current_process.pid); diff --git a/priv/javascript/lib/processes/states.js b/priv/javascript/lib/processes/states.js index 13352018..cd78be5d 100644 --- a/priv/javascript/lib/processes/states.js +++ b/priv/javascript/lib/processes/states.js @@ -1,13 +1,14 @@ export default { - NORMAL: Symbol(), - SUSPEND: Symbol(), - CONTINUE: Symbol(), - RECEIVE: Symbol(), - SEND: Symbol(), - SLEEPING: Symbol(), - RUNNING: Symbol(), - SUSPENDED: Symbol(), - STOPPED: Symbol(), - SLEEP: Symbol(), - EXIT: Symbol() + NORMAL: Symbol.for("normal"), + SHUTDOWN: Symbol.for("shutdown"), + SUSPEND: Symbol.for("suspend"), + CONTINUE: Symbol.for("continue"), + RECEIVE: Symbol.for("receive"), + SEND: Symbol.for("send"), + SLEEPING: Symbol.for("sleeping"), + RUNNING: Symbol.for("running"), + SUSPENDED: Symbol.for("suspended"), + STOPPED: Symbol.for("stopped"), + SLEEP: Symbol.for("sleep"), + EXIT: Symbol.for("exit") } \ No newline at end of file diff --git a/test/translator/receive_test.exs b/test/translator/receive_test.exs index 7155492e..99add822 100644 --- a/test/translator/receive_test.exs +++ b/test/translator/receive_test.exs @@ -15,7 +15,7 @@ defmodule ElixirScript.Translator.Receive.Test do end js_code = """ - Kernel.SpecialForms.receive(function(message) { + self.scheduler.receive(function(message) { return Patterns.defmatch(Patterns.make_case([Kernel.SpecialForms.atom('ok')],function() { return value; }),Patterns.make_case([Kernel.SpecialForms.atom('error')],function() { @@ -45,7 +45,7 @@ defmodule ElixirScript.Translator.Receive.Test do end js_code = """ - Kernel.SpecialForms.receive(function(message) { + self.scheduler.receive(function(message) { return Patterns.defmatch(Patterns.make_case([Kernel.SpecialForms.atom('ok')],function() { return value; }),Patterns.make_case([Kernel.SpecialForms.atom('error')],function() { From d2c03ff5e8403baa4698e8456bbff299afb2e34c Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Sun, 11 Oct 2015 09:55:09 -0500 Subject: [PATCH 009/860] yielding on receive. Updated dev version --- CHANGELOG.md | 8 ++- lib/elixir_script/translator/receive.ex | 70 ++++++++++++---------- mix.exs | 2 +- priv/javascript/lib/processes/process.js | 1 + priv/javascript/lib/processes/scheduler.js | 21 +++++-- test/translator/receive_test.exs | 4 +- 6 files changed, 62 insertions(+), 44 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 15aab538..6a518599 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,9 @@ +# v0.13.0-dev +* Enhancements + * Introduction of processes + # v0.12.0 -* Enhancement +* Enhancements * Updated tuple implementation. It's now a class. * Replaced pattern matching library with custom one * Added PostOffice. Only thing that current uses it is Agent @@ -8,7 +12,7 @@ * for now works with `into` for lists # v0.11.0 -* Enhancement +* Enhancements * `import` works with all options * Added `JS` module with `new`, `mutate`, `import` macros * All Standard libraries are rolled up into one elixir.js file and imported from that diff --git a/lib/elixir_script/translator/receive.ex b/lib/elixir_script/translator/receive.ex index dbe467cb..e363d3ed 100644 --- a/lib/elixir_script/translator/receive.ex +++ b/lib/elixir_script/translator/receive.ex @@ -5,44 +5,48 @@ defmodule ElixirScript.Translator.Receive do alias ElixirScript.Translator.Primitive def make_receive([do: clauses], env) do - JS.call_expression( - JS.member_expression( - Primitive.scheduler(), - JS.identifier("receive") - ), - [ - JS.function_expression( - [JS.identifier(:message)], - [], - JS.block_statement([ - JS.return_statement( - ElixirScript.Translator.Case.make_case({:__aliases__, [], [:message]}, clauses, env) - ) - ]) - ) - ] + JS.yield_expression( + JS.call_expression( + JS.member_expression( + Primitive.scheduler(), + JS.identifier("receive") + ), + [ + JS.function_expression( + [JS.identifier(:message)], + [], + JS.block_statement([ + JS.return_statement( + ElixirScript.Translator.Case.make_case({:__aliases__, [], [:message]}, clauses, env) + ) + ]) + ) + ] + ) ) end def make_receive([do: clauses, after: [{:->, _, [[time], _body]}] = after_clause], env) do - JS.call_expression( - JS.member_expression( - Primitive.scheduler(), - JS.identifier("receive") - ), - [ - JS.function_expression( - [JS.identifier(:message)], - [], - JS.block_statement([ - JS.return_statement( - ElixirScript.Translator.Case.make_case({:__aliases__, [], [:message]}, clauses, env) - ) - ]) + JS.yield_expression( + JS.call_expression( + JS.member_expression( + Primitive.scheduler(), + JS.identifier("receive") ), - Translator.translate(time, env), - ElixirScript.Translator.Function.make_anonymous_function(after_clause, env) - ] + [ + JS.function_expression( + [JS.identifier(:message)], + [], + JS.block_statement([ + JS.return_statement( + ElixirScript.Translator.Case.make_case({:__aliases__, [], [:message]}, clauses, env) + ) + ]) + ), + Translator.translate(time, env), + ElixirScript.Translator.Function.make_anonymous_function(after_clause, env) + ] + ) ) end end \ No newline at end of file diff --git a/mix.exs b/mix.exs index 48ae99ab..341a2ea1 100644 --- a/mix.exs +++ b/mix.exs @@ -4,7 +4,7 @@ defmodule ElixirScript.Mixfile do def project do [ app: :elixir_script, - version: "0.12.0", + version: "0.13.0-dev", elixir: "~> 1.0", escript: escript_config, deps: deps, diff --git a/priv/javascript/lib/processes/process.js b/priv/javascript/lib/processes/process.js index 2de5aa4c..82345225 100644 --- a/priv/javascript/lib/processes/process.js +++ b/priv/javascript/lib/processes/process.js @@ -4,6 +4,7 @@ import Mailbox from "./mailbox"; import Scheduler from "./scheduler"; import States from "./states"; +import Patterns from "../patterns/patterns"; const NOMSG = Symbol(); diff --git a/priv/javascript/lib/processes/scheduler.js b/priv/javascript/lib/processes/scheduler.js index 574aaf1e..9ea22bc0 100644 --- a/priv/javascript/lib/processes/scheduler.js +++ b/priv/javascript/lib/processes/scheduler.js @@ -6,19 +6,28 @@ import Process from "./process"; import States from "./states"; import TaskQueue from "./task_queue"; + +const throttle = 10; //ms between queued tasks + class Scheduler { constructor(){ - this.process_counter = 0; + this.process_counter = -1; this.pids = new Map(); this.mailboxes = new Map(); this.names = new Map(); this.links = new Map(); - const throttle = 10; //ms between queued tasks this.current_process = null; this.task_queue = new TaskQueue(throttle); this.suspended = new Map(); + + let scheduler_scope = this; + this.main_process = this.spawn(function*(){ + while(true){ + yield scheduler_scope.sleep(10000); + } + }); } set_current(process){ @@ -26,19 +35,19 @@ class Scheduler { this.current_process.status = States.RUNNING; } - spawn(fun, ...args){ + spawn(fun, args){ return this.add_proc(fun, args, false).pid; } - spawn_from_module(module, fun, ...args){ + spawn_from_module(module, fun, args){ return this.add_proc(module[fun], args, false).pid; } - spawn_link(fun, ...args){ + spawn_link(fun, args){ return this.add_proc(fun, args, true).pid; } - spawn_link_from_module(module, fun, ...args){ + spawn_link_from_module(module, fun, args){ return this.add_proc(module[fun], args, true).pid; } diff --git a/test/translator/receive_test.exs b/test/translator/receive_test.exs index 99add822..db1a018b 100644 --- a/test/translator/receive_test.exs +++ b/test/translator/receive_test.exs @@ -15,7 +15,7 @@ defmodule ElixirScript.Translator.Receive.Test do end js_code = """ - self.scheduler.receive(function(message) { + yield self.scheduler.receive(function(message) { return Patterns.defmatch(Patterns.make_case([Kernel.SpecialForms.atom('ok')],function() { return value; }),Patterns.make_case([Kernel.SpecialForms.atom('error')],function() { @@ -45,7 +45,7 @@ defmodule ElixirScript.Translator.Receive.Test do end js_code = """ - self.scheduler.receive(function(message) { + yield self.scheduler.receive(function(message) { return Patterns.defmatch(Patterns.make_case([Kernel.SpecialForms.atom('ok')],function() { return value; }),Patterns.make_case([Kernel.SpecialForms.atom('error')],function() { From ea1ce7cf4b766b79fd5dcfd9bb0b38214bb090b5 Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Fri, 16 Oct 2015 09:09:34 -0500 Subject: [PATCH 010/860] Updated the processes js modules --- lib/elixir_script/translator/primitive.ex | 2 +- priv/javascript/elixir.js | 7 +- priv/javascript/lib/agent.js | 121 +++++++-- priv/javascript/lib/processes/process.js | 117 -------- priv/javascript/lib/processes/processes.js | 4 + .../lib/processes/{ => processes}/mailbox.js | 0 .../processes/processes/otp/application.js | 5 + .../lib/processes/processes/otp/gen_event.js | 38 +++ .../lib/processes/processes/otp/gen_server.js | 74 +++++ .../javascript/lib/processes/processes/pid.js | 18 ++ .../lib/processes/processes/process.js | 147 ++++++++++ .../lib/processes/processes/process_system.js | 257 ++++++++++++++++++ .../lib/processes/processes/scheduler.js | 103 +++++++ .../lib/processes/{ => processes}/states.js | 5 +- priv/javascript/lib/processes/scheduler.js | 208 -------------- priv/javascript/lib/processes/task_queue.js | 86 ------ test/translator/receive_test.exs | 4 +- 17 files changed, 756 insertions(+), 440 deletions(-) delete mode 100644 priv/javascript/lib/processes/process.js create mode 100644 priv/javascript/lib/processes/processes.js rename priv/javascript/lib/processes/{ => processes}/mailbox.js (100%) create mode 100644 priv/javascript/lib/processes/processes/otp/application.js create mode 100644 priv/javascript/lib/processes/processes/otp/gen_event.js create mode 100644 priv/javascript/lib/processes/processes/otp/gen_server.js create mode 100644 priv/javascript/lib/processes/processes/pid.js create mode 100644 priv/javascript/lib/processes/processes/process.js create mode 100644 priv/javascript/lib/processes/processes/process_system.js create mode 100644 priv/javascript/lib/processes/processes/scheduler.js rename priv/javascript/lib/processes/{ => processes}/states.js (79%) delete mode 100644 priv/javascript/lib/processes/scheduler.js delete mode 100644 priv/javascript/lib/processes/task_queue.js diff --git a/lib/elixir_script/translator/primitive.ex b/lib/elixir_script/translator/primitive.ex index b6b87021..4c4b3197 100644 --- a/lib/elixir_script/translator/primitive.ex +++ b/lib/elixir_script/translator/primitive.ex @@ -15,7 +15,7 @@ defmodule ElixirScript.Translator.Primitive do def scheduler() do JS.member_expression( JS.identifier("self"), - JS.identifier("scheduler") + JS.identifier("system") ) end diff --git a/priv/javascript/elixir.js b/priv/javascript/elixir.js index a9d1efd5..da7c4f2e 100644 --- a/priv/javascript/elixir.js +++ b/priv/javascript/elixir.js @@ -1,9 +1,9 @@ import PostOffice from './lib/post_office'; -import Scheduler from './lib/processes/scheduler'; +import { ProcessSystem } from './lib/processes/processes'; self.post_office = self.post_office || new PostOffice(); -self.scheduler = self.scheduler || new Scheduler(); +self.system = self.system || new ProcessSystem(); export { default as Patterns } from './lib/patterns/patterns'; export { default as BitString } from './lib/bit_string'; @@ -16,4 +16,5 @@ export { default as List } from './lib/list'; export { default as Range } from './lib/range'; export { default as Tuple } from './lib/tuple'; export { default as Agent } from './lib/agent'; -export { default as Keyword } from './lib/keyword'; \ No newline at end of file +export { default as Keyword } from './lib/keyword'; +export { GenServer } from './lib/processes/processes'; \ No newline at end of file diff --git a/priv/javascript/lib/agent.js b/priv/javascript/lib/agent.js index 6dc0f40e..e8dfd550 100644 --- a/priv/javascript/lib/agent.js +++ b/priv/javascript/lib/agent.js @@ -1,40 +1,119 @@ import Kernel from './kernel'; import Keyword from './keyword'; -let Agent = {}; +function start(fun, options = []){ + let pid = self.system.spawn(start_process(module, args)); -Agent.start = function(fun, options = []){ - const name = Keyword.has_key__qm__(options, Kernel.SpecialForms.atom("name")) ? Keyword.get(options, Kernel.SpecialForms.atom("name")) : Symbol(); - - self.post_office.add_mailbox(name); - self.post_office.send(name, fun()); + if(Keyword.has_key__qm__(options, Kernel.SpecialForms.atom("name"))){ + let name = Keyword.get(options, Kernel.SpecialForms.atom("name")); - return Kernel.SpecialForms.tuple(Kernel.SpecialForms.atom("ok"), name); + self.system.register(name, pid); + return Kernel.SpecialForms.tuple(Kernel.SpecialForms.atom("ok"), name); + } + + return Kernel.SpecialForms.tuple(Kernel.SpecialForms.atom("ok"), pid); } -Agent.stop = function(agent, timeout = 5000){ - self.post_office.remove_mailbox(agent); - return Kernel.SpecialForms.atom("ok"); +function start_link(fun, options = []){ + let pid = self.system.spawn_link(start_process(module, args)); + + if(Keyword.has_key__qm__(options, Kernel.SpecialForms.atom("name"))){ + let name = Keyword.get(options, Kernel.SpecialForms.atom("name")); + + self.system.register(name, pid); + return Kernel.SpecialForms.tuple(Kernel.SpecialForms.atom("ok"), name); + } + + return Kernel.SpecialForms.tuple(Kernel.SpecialForms.atom("ok"), pid); } -Agent.update = function(agent, fun, timeout = 5000){ +function start_process(fun){ + return function*(){ + yield self.system.put("state", fun.apply(null, [])); + + try{ + while(true){ + yield self.system.receive(function(args){ + let command = args[0]; + + switch(command){ + case "update": + let updateFn = args[1]; + let sender = args[2]; + + let current_state = self.system.get("state"); + let new_state = updateFn(current_state); + + self.system.put("state", new_state); + self.system.send(sender, Symbol.for("ok")); + + break; + case "get": + let getFn = args[1]; + let sender = args[2]; - const current_state = self.post_office.receive(agent); - self.post_office.send(agent, fun(current_state)); + let current_state = self.system.get("state"); + let return_value = getFn(current_state); - return Kernel.SpecialForms.atom("ok"); + self.system.send(sender, return_value); + + break; + case "get_and_update": + let updateFn = args[1]; + let sender = args[2]; + + let current_state = self.system.get("state"); + let get_and_update_tuple = updateFn(current_state); + + self.system.put("state", Kernel.elem(get_and_update_tuple, 1)); + self.system.send(sender, Kernel.elem(get_and_update_tuple, 0)); + + break; + case "stop": + throw "stop"; + } + }); + } + }catch(e){ + if(e !== "stop"){ + throw e; + } + } + } } -Agent.get = function(agent, fun, timeout = 5000){ - return fun(self.post_office.peek(agent)); +function* stop(agent, timeout = 5000){ + self.system.send(agent, ["stop", self.system.pid()]); } -Agent.get_and_update = function(agent, fun, timeout = 5000){ +function* update(agent, fun, timeout = 5000){ + self.system.send(agent, ["update", fun, self.system.pid()]); + + return yield self.system.receive(function(args){ + return args; + }); +} + +function* get(agent, fun, timeout = 5000){ + self.system.send(agent, ["update", fun, self.system.pid()]); + + return yield self.system.receive(function(args){ + return args; + }); +} - const get_and_update_tuple = fun(self.post_office.receive(agent)); - self.post_office.send(agent, Kernel.elem(get_and_update_tuple, 1)); +function* get_and_update(agent, fun, timeout = 5000){ + self.system.send(agent, ["get_and_update", fun, self.system.pid()]); - return Kernel.elem(get_and_update_tuple, 0); + return yield self.system.receive(function(args){ + return args; + }); } -export default Agent; +export default { + start, + stop, + update, + get, + get_and_update +}; diff --git a/priv/javascript/lib/processes/process.js b/priv/javascript/lib/processes/process.js deleted file mode 100644 index 82345225..00000000 --- a/priv/javascript/lib/processes/process.js +++ /dev/null @@ -1,117 +0,0 @@ -"use strict"; - -/* @flow */ -import Mailbox from "./mailbox"; -import Scheduler from "./scheduler"; -import States from "./states"; -import Patterns from "../patterns/patterns"; - -const NOMSG = Symbol(); - -class Process { - pid: Number; - mailbox: Mailbox; - func: Function; - args: Array; - scheduler: Scheduler; - status: Symbol; - - constructor(pid: Number, func: Function, args: Array, mailbox: Mailbox, scheduler: Scheduler){ - this.pid = pid; - this.func = func; - this.args = args; - this.mailbox = mailbox; - this.scheduler = scheduler; - this.status = States.STOPPED; - } - - start(){ - let machine = this.main(); - let step = machine.next(); - - this.status = States.RUNNING; - - this.run(machine, step); - } - - *main() { - let retval = States.NORMAL; - - try { - for(let v of this.func.apply(null, this.args)){ - yield v; - } - } catch(e) { - retval = e; - } - - this.scheduler.exit(this.pid, retval); - } - - exit(reason){ - this.scheduler.remove_proc(this.pid, reason); - } - - receive(fun){ - let value = NOMSG; - let messages = this.mailbox.get(); - - for(let i = 0; i < messages.length; i++){ - try{ - value = fun(messages[i]); - this.mailbox.removeAt(i); - }catch(e){ - if(!e instanceof Patterns.MatchError){ - this.exit(e); - } - } - } - - return value; - } - - run(machine, step){ - const function_scope = this; - this.scheduler.set_current(this); - - if(!step.done){ - let value = step.value; - - if(Array.isArray(value) && (value[0] === States.SLEEP || value[0] === States.RECEIVE)){ - if(value[0] === States.SLEEP){ - - this.scheduler.delay(function() { - function_scope.run(machine, machine.next()); - }, value[1]); - - }else if(value[0] === States.RECEIVE){ - if(value[2] != null && value[2] < Date.now()){ - let result = value[3](); - - this.scheduler.queue(function() { - function_scope.run(machine, machine.next(result)); - }); - }else{ - let result = function_scope.receive(value[1]); - - if(result === NOMSG){ - this.scheduler.suspend(function() { - function_scope.run(machine, step); - }); - }else{ - this.scheduler.queue(function() { - function_scope.run(machine, machine.next(result)); - }); - } - } - } - }else{ - this.scheduler.queue(function() { - function_scope.run(machine, machine.next()); - }); - } - } - } -} - -export default Process; \ No newline at end of file diff --git a/priv/javascript/lib/processes/processes.js b/priv/javascript/lib/processes/processes.js new file mode 100644 index 00000000..ae7f3548 --- /dev/null +++ b/priv/javascript/lib/processes/processes.js @@ -0,0 +1,4 @@ +export { default as ProcessSystem } from "./processes/process_system"; +export { default as GenServer } from "./processes/otp/gen_server"; +export { default as GenEvent } from "./processes/otp/gen_event"; +export { default as Application } from "./processes/otp/application"; diff --git a/priv/javascript/lib/processes/mailbox.js b/priv/javascript/lib/processes/processes/mailbox.js similarity index 100% rename from priv/javascript/lib/processes/mailbox.js rename to priv/javascript/lib/processes/processes/mailbox.js diff --git a/priv/javascript/lib/processes/processes/otp/application.js b/priv/javascript/lib/processes/processes/otp/application.js new file mode 100644 index 00000000..15fdad25 --- /dev/null +++ b/priv/javascript/lib/processes/processes/otp/application.js @@ -0,0 +1,5 @@ +function start(app, type = Symbol.for("temporary")){ + return app.start(type, []); +} + +export default { start }; \ No newline at end of file diff --git a/priv/javascript/lib/processes/processes/otp/gen_event.js b/priv/javascript/lib/processes/processes/otp/gen_event.js new file mode 100644 index 00000000..3f82bb69 --- /dev/null +++ b/priv/javascript/lib/processes/processes/otp/gen_event.js @@ -0,0 +1,38 @@ +function start(options = []){ + return [Symbol.for("ok"), self.system.spawn(start_process())]; +} + +function start_link(options = []){ + return [Symbol.for("ok"), self.system.spawn_link(start_process())]; +} + +function start_process(){ + return function*(){ + while(true){ + yield self.system.receive(function(args){ + switch(args[0]){ + case "add_handler": + break; + case "notify": + break; + case "call": + break; + } + }); + } + } +} + +function* add_handler(manager, handler, args){ + +} + +function* call(manager, handler, request, timeout = 5000){ + +} + +function* notify(manager, event){ + +} + +export default { start, start_link, call, add_handler, notify }; \ No newline at end of file diff --git a/priv/javascript/lib/processes/processes/otp/gen_server.js b/priv/javascript/lib/processes/processes/otp/gen_server.js new file mode 100644 index 00000000..57d73090 --- /dev/null +++ b/priv/javascript/lib/processes/processes/otp/gen_server.js @@ -0,0 +1,74 @@ +function start(module, args){ + return [Symbol.for("ok"), self.system.spawn(start_process(module, args))]; +} + +function start_link(module, args){ + return [Symbol.for("ok"), self.system.spawn_link(start_process(module, args))]; +} + +function start_process(module, args){ + return function*(){ + let [ok, state] = module.init.apply(null, [args]); + yield self.system.put("state", state); + + try{ + while(true){ + yield self.system.receive(function(args){ + let command = args[0]; + + switch(command){ + case "call": + var request = args[1]; + var sender = args[2]; + + var [reply, response, new_state] = module.handle_call(request, sender, self.system.get("state")); + self.system.put("state", new_state); + + self.system.send(sender, response); + break; + + case "cast": + var request = args[1]; + var sender = args[2]; + + var [reply, new_state] = module.handle_cast(request, self.system.get("state")); + + self.system.put("state", new_state); + self.system.send(args[2], Symbol.for("ok")); + + break; + + case "stop": + throw "stop"; + } + }); + } + }catch(e){ + if(e !== "stop"){ + throw e; + } + } + } +} + +function* call(server, request){ + self.system.send(server, ["call", request, self.system.pid()]); + + return yield self.system.receive(function(args){ + return args; + }); +} + +function* cast(server, request){ + self.system.send(server, ["cast", request, self.system.pid()]); + + return yield self.system.receive(function(args){ + return args; + }); +} + +function stop(server){ + self.system.send(server, ["stop"]); +} + +export default { start, start_link, call, cast, stop }; \ No newline at end of file diff --git a/priv/javascript/lib/processes/processes/pid.js b/priv/javascript/lib/processes/processes/pid.js new file mode 100644 index 00000000..da45857c --- /dev/null +++ b/priv/javascript/lib/processes/processes/pid.js @@ -0,0 +1,18 @@ +"use strict"; +/* @flow */ + +let process_counter = -1; + +class PID { + constructor(){ + process_counter = process_counter + 1; + this.id = process_counter; + } + + toString(){ + return "PID#<0." + this.id + ".0>"; + } +} + + +export default PID; \ No newline at end of file diff --git a/priv/javascript/lib/processes/processes/process.js b/priv/javascript/lib/processes/processes/process.js new file mode 100644 index 00000000..007fa730 --- /dev/null +++ b/priv/javascript/lib/processes/processes/process.js @@ -0,0 +1,147 @@ +"use strict"; + +/* @flow */ +import Mailbox from "./mailbox"; +import ProcessSystem from "./process_system"; +import States from "./states"; + +function is_sleep(value){ + return Array.isArray(value) && value[0] === States.SLEEP; +} + +function is_receive(value){ + return Array.isArray(value) && value[0] === States.RECEIVE; +} + +function receive_timed_out(value){ + return value[2] != null && value[2] < Date.now(); +} + +class Process { + pid: Number; + mailbox: Mailbox; + func: Function; + args: Array; + system: ProcessSystem; + status: Symbol; + dict: Object; + flags: Object; + + constructor(pid: Number, func: Function, args: Array, mailbox: Mailbox, system: ProcessSystem){ + this.pid = pid; + this.func = func; + this.args = args; + this.mailbox = mailbox; + this.system = system; + this.status = States.STOPPED; + this.dict = {}; + this.flags = {}; + } + + start(){ + const function_scope = this; + let machine = this.main(); + + this.system.schedule(function() { + function_scope.system.set_current(function_scope.pid); + function_scope.run(machine, machine.next()); + }, this.pid); + } + + *main() { + let retval = States.NORMAL; + + try { + yield* this.func.apply(null, this.args); + } catch(e) { + console.error(e); + retval = e; + } + + this.system.exit(retval); + } + + process_flag(flag, value){ + this.flags[flag] = value; + } + + is_trapping_exits(){ + return this.flags[Symbol.for("trap_exit")] && this.flags[Symbol.for("trap_exit")] == true; + } + + signal(reason){ + if(reason !== States.NORMAL){ + console.error(reason); + } + + this.system.remove_proc(this.pid, reason); + } + + receive(fun){ + let value = States.NOMATCH; + let messages = this.mailbox.get(); + + for(let i = 0; i < messages.length; i++){ + try{ + value = fun(messages[i]); + if(value !== States.NOMATCH){ + this.mailbox.removeAt(i); + break; + } + }catch(e){ + this.exit(e); + } + } + + return value; + } + + run(machine, step){ + const function_scope = this; + + if(!step.done){ + let value = step.value; + + if(is_sleep(value)){ + + this.system.delay(function() { + function_scope.system.set_current(function_scope.pid); + function_scope.run(machine, machine.next()); + }, value[1]); + + }else if(is_receive(value) && receive_timed_out(value)){ + + let result = value[3](); + + this.system.schedule(function() { + function_scope.system.set_current(function_scope.pid); + function_scope.run(machine, machine.next(result)); + }); + + }else if(is_receive(value)){ + + let result = function_scope.receive(value[1]); + + if(result === States.NOMATCH){ + this.system.suspend(function() { + function_scope.system.set_current(function_scope.pid); + function_scope.run(machine, step); + }); + }else{ + this.system.schedule(function() { + function_scope.system.set_current(function_scope.pid); + function_scope.run(machine, machine.next(result)); + }); + } + + }else{ + this.system.schedule(function() { + function_scope.system.set_current(function_scope.pid); + function_scope.run(machine, machine.next(value)); + }); + } + } + } +} + +export default Process; \ No newline at end of file diff --git a/priv/javascript/lib/processes/processes/process_system.js b/priv/javascript/lib/processes/processes/process_system.js new file mode 100644 index 00000000..f67288af --- /dev/null +++ b/priv/javascript/lib/processes/processes/process_system.js @@ -0,0 +1,257 @@ +/* @flow */ +"use strict"; + +import Mailbox from "./mailbox"; +import Process from "./process"; +import States from "./states"; +import Scheduler from "./scheduler"; +import PID from "./pid"; + +class ProcessSystem { + + constructor(){ + this.pids = new Map(); + this.mailboxes = new Map(); + this.names = new Map(); + this.links = new Map(); + + const throttle = 5; //ms between scheduled tasks + this.current_process = null; + this.scheduler = new Scheduler(throttle); + this.suspended = new Map(); + + let process_system_scope = this; + this.main_process_pid = this.spawn(function*(){ + while(true){ + yield process_system_scope.sleep(10000); + } + }); + this.set_current(this.main_process_pid); + } + + static * run(fun, args, context = null){ + if(fun.constructor.name === "GeneratorFunction"){ + return yield* fun.apply(context, args); + }else{ + return fun.apply(context, args); + } + } + + spawn(...args){ + if(args.length === 1){ + let fun = args[0]; + return this.add_proc(fun, [], false).pid; + + }else if(args.length === 3){ + let mod = args[0]; + let fun = args[1]; + let the_args = args[2]; + + return this.add_proc(mod[fun], the_args, false).pid; + } + } + + spawn_link(...args){ + if(args.length === 1){ + let fun = args[0]; + return this.add_proc(fun, [], true).pid; + + }else if(args.length === 3){ + let mod = args[0]; + let fun = args[1]; + let the_args = args[2]; + + return this.add_proc(mod[fun], the_args, true).pid; + } + } + + link(pid){ + this.links.get(this.pid()).add(pid); + this.links.get(pid).add(this.pid()); + } + + unlink(pid){ + this.links.get(this.pid()).delete(pid); + this.links.get(pid).delete(this.pid()); + } + + set_current(id){ + let pid = this.pidof(id); + if(pid !== null){ + this.current_process = this.pids.get(pid); + this.current_process.status = States.RUNNING; + } + } + + add_proc(fun, args, linked){ + let newpid = new PID(); + let mailbox = new Mailbox(); + let newproc = new Process(newpid, fun, args, mailbox, this); + + this.pids.set(newpid, newproc); + this.mailboxes.set(newpid, mailbox); + this.links.set(newpid, new Set()); + + if(linked){ + this.link(newpid); + } + + newproc.start(); + return newproc; + } + + remove_proc(pid, exitreason){ + this.pids.delete(pid); + this.unregister(pid); + this.scheduler.removePid(pid); + + if(this.links.has(pid)){ + for (let linkpid of this.links.get(pid)) { + this.exit(linkpid, exitreason); + this.links.get(linkpid).delete(pid); + } + + this.links.delete(pid); + } + } + + register(name, pid){ + if(!this.names.has(name)){ + this.names.set(name, pid) + }else{ + throw new Error("Name is already registered to another process"); + } + } + + registered(name){ + return this.names.has(name) ? this.names.get(name) : null; + } + + unregister(pid){ + for(let name of this.names.keys()){ + if(this.names.has(name) && this.names.get(name) === pid){ + this.names.delete(name); + } + } + } + + pid(){ + return this.current_process.pid; + } + + pidof(id){ + if (id instanceof PID) { + return this.pids.has(id) ? id : null; + } else if (id instanceof Process) { + return id.pid; + } else { + let pid = this.registered(id); + if (pid === null) + throw("Process name not registered: " + id + " (" + typeof(id) + ")"); + return pid; + } + } + + send(id, msg) { + const pid = this.pidof(id); + + if(pid){ + this.mailboxes.get(pid).deliver(msg); + + if(this.suspended.has(pid)){ + let fun = this.suspended.get(pid); + this.suspended.delete(pid); + this.schedule(fun); + } + } + + return msg; + } + + receive(fun, timeout = 0, timeoutFn = () => true ) { + let DateTimeout = null; + + if(timeout === 0 || timeout === Infinity){ + DateTimeout = null; + }else{ + DateTimeout = Date.now() + timeout; + } + + return [ + States.RECEIVE, + fun, + DateTimeout, + timeoutFn + ]; + } + + sleep(duration){ + return [States.SLEEP, duration]; + } + + suspend(fun){ + this.current_process.status = States.SUSPENDED; + this.suspended.set(this.current_process.pid, fun); + } + + delay(fun, time){ + this.current_process.status = States.SLEEPING; + this.scheduler.scheduleFuture(this.current_process.pid, time, fun); + } + + schedule(fun, pid){ + const the_pid = pid != null ? pid : this.current_process.pid; + this.scheduler.schedule(the_pid, fun); + } + + exit(one, two){ + if(two){ + let pid = one; + let reason = two; + + let process = this.pids.get(this.pidof(pid)); + if((process && process.is_trapping_exits()) || reason === States.KILL || reason === States.NORMAL){ + this.mailboxes.get(process.pid).deliver([States.EXIT, this.pid(), reason ]); + }else{ + process.signal(reason); + } + }else{ + let reason = one; + this.current_process.signal(reason); + } + } + + error(reason){ + this.current_process.signal(reason); + } + + process_flag(flag, value){ + this.current_process.process_flag(flag, value); + } + + put(key, value){ + this.current_process.dict[key] = value; + } + + get(key){ + if(key != null){ + return this.current_process.dict[key]; + }else{ + return this.current_process.dict; + } + } + + get_keys(){ + return Object.keys(this.current_process.dict); + } + + erase(key){ + if(key != null){ + delete this.current_process.dict[key]; + }else{ + this.current_process.dict = {}; + } + } +} + +export default ProcessSystem; \ No newline at end of file diff --git a/priv/javascript/lib/processes/processes/scheduler.js b/priv/javascript/lib/processes/processes/scheduler.js new file mode 100644 index 00000000..c7cec538 --- /dev/null +++ b/priv/javascript/lib/processes/processes/scheduler.js @@ -0,0 +1,103 @@ +"use strict"; + +// A reduction is equal to a function call +const MAX_REDUCTIONS_PER_PROCESS = 8; + +class ProcessQueue { + constructor(pid){ + this.pid = pid; + this.tasks = []; + } + + empty(){ + return this.tasks.length === 0; + } + + add(task){ + this.tasks.push(task); + } + + next(){ + return this.tasks.shift(); + } +} + +class Scheduler { + constructor(throttle = 0){ + this.isRunning = false; + this.invokeLater = function (callback) { setTimeout(callback, throttle); } + this.queues = new Map(); + this.run(); + } + + addToQueue(pid, task){ + if(!this.queues.has(pid)){ + this.queues.set(pid, new ProcessQueue(pid)); + } + + this.queues.get(pid).add(task); + } + + removePid(pid){ + this.isRunning = true; + + this.queues.delete(pid); + + this.isRunning = false; + } + + run(){ + if (this.isRunning) { + this.invokeLater(() => { this.run(); }); + } else { + for(let [pid, queue] of this.queues){ + let reductions = 0; + while(queue && !queue.empty() && reductions < MAX_REDUCTIONS_PER_PROCESS){ + let task = queue.next(); + this.isRunning = true; + + let result; + + try{ + result = task(); + }catch(e){ + console.error(e); + result = e; + } + + this.isRunning = false; + + if (result instanceof Error) { + throw result; + } + + reductions++; + } + } + + this.invokeLater(() => { this.run(); }); + } + } + + addToScheduler(pid, task, dueTime = 0) { + if(dueTime === 0){ + this.invokeLater(() => { + this.addToQueue(pid, task); + }); + }else{ + setTimeout(() => { + this.addToQueue(pid, task); + }, dueTime); + } + }; + + schedule(pid, task){ + this.addToScheduler(pid, () => { task(); }); + } + + scheduleFuture(pid, dueTime, task){ + this.addToScheduler(pid, () => { task(); }, dueTime); + } +} + +export default Scheduler; \ No newline at end of file diff --git a/priv/javascript/lib/processes/states.js b/priv/javascript/lib/processes/processes/states.js similarity index 79% rename from priv/javascript/lib/processes/states.js rename to priv/javascript/lib/processes/processes/states.js index cd78be5d..24294ecd 100644 --- a/priv/javascript/lib/processes/states.js +++ b/priv/javascript/lib/processes/processes/states.js @@ -1,6 +1,6 @@ export default { NORMAL: Symbol.for("normal"), - SHUTDOWN: Symbol.for("shutdown"), + KILL: Symbol.for("kill"), SUSPEND: Symbol.for("suspend"), CONTINUE: Symbol.for("continue"), RECEIVE: Symbol.for("receive"), @@ -10,5 +10,6 @@ export default { SUSPENDED: Symbol.for("suspended"), STOPPED: Symbol.for("stopped"), SLEEP: Symbol.for("sleep"), - EXIT: Symbol.for("exit") + EXIT: Symbol.for("exit"), + NOMATCH: Symbol.for("no_match") } \ No newline at end of file diff --git a/priv/javascript/lib/processes/scheduler.js b/priv/javascript/lib/processes/scheduler.js deleted file mode 100644 index 9ea22bc0..00000000 --- a/priv/javascript/lib/processes/scheduler.js +++ /dev/null @@ -1,208 +0,0 @@ -/* @flow */ -"use strict"; - -import Mailbox from "./mailbox"; -import Process from "./process"; -import States from "./states"; -import TaskQueue from "./task_queue"; - - -const throttle = 10; //ms between queued tasks - -class Scheduler { - - constructor(){ - this.process_counter = -1; - this.pids = new Map(); - this.mailboxes = new Map(); - this.names = new Map(); - this.links = new Map(); - - this.current_process = null; - this.task_queue = new TaskQueue(throttle); - this.suspended = new Map(); - - let scheduler_scope = this; - this.main_process = this.spawn(function*(){ - while(true){ - yield scheduler_scope.sleep(10000); - } - }); - } - - set_current(process){ - this.current_process = process; - this.current_process.status = States.RUNNING; - } - - spawn(fun, args){ - return this.add_proc(fun, args, false).pid; - } - - spawn_from_module(module, fun, args){ - return this.add_proc(module[fun], args, false).pid; - } - - spawn_link(fun, args){ - return this.add_proc(fun, args, true).pid; - } - - spawn_link_from_module(module, fun, args){ - return this.add_proc(module[fun], args, true).pid; - } - - link(pid){ - this.links.get(this.current_process.pid).add(pid); - this.links.get(pid).add(this.current_process.pid); - } - - unlink(pid){ - this.links.get(this.current_process.pid).delete(pid); - this.links.get(pid).delete(this.current_process.pid); - } - - add_proc(fun, args, linked){ - this.process_counter = this.process_counter + 1; - let newpid = this.process_counter; - let mailbox = new Mailbox(); - let newproc = new Process(newpid, fun, args, mailbox, this); - - this.pids.set(newpid, newproc); - this.mailboxes.set(newpid, mailbox); - this.links.set(newpid, new Set()); - - if(linked){ - link(newpid); - } - - newproc.start(); - return newproc; - } - - remove_proc(pid, exitreason){ - this.pids.delete(pid); - this.unregister(pid); - this.task_queue.removePid(pid); - - for (let linkpid in this.links.get(pid).entries()) { - linkpid = Number(linkpid); - - if (exitreason != Normal) { - this.pids.get(linkpid).deliver({ Signal: States.EXIT, From: pid, Reason: exitreason }); - } - - this.links.get(linkpid).delete(pid); - } - - this.links.delete(pid); - } - - register(name, pid){ - if(!this.names.has(name)){ - this.names.set(name, pid) - }else{ - throw new Error("Name is already registered to another process"); - } - } - - registered(name){ - return this.names.has(name) ? this.names.get(name) : null; - } - - unregister(pid){ - for(let name of this.names.keys()){ - if(this.names.has(name) && this.names.get(name) === pid){ - this.names.delete(name); - } - } - } - - pid(){ - return this.current_process.pid; - } - - pidof(id){ - if (typeof(id) === "number") { - return this.pids.has(id) ? id : null; - } else if (id instanceof Process) { - return id.pid; - } else { - let pid = this.registered(id); - if (pid === null) - throw("Er: Process name not registered: " + - id + " (" + typeof(id) + ")"); - return pid; - } - } - - send(id, msg) { - const pid = this.pidof(id); - - if(pid){ - this.mailboxes.get(pid).deliver(msg); - - if(this.suspended.has(pid)){ - let fun = this.suspended.get(pid); - this.suspended.delete(pid); - this.queue(fun); - } - } - - return msg; - } - - receive(fun, timeout = 0, timeoutFn = () => true ) { - let DateTimeout = null; - - if(timeout === 0 || timeout === Infinity){ - DateTimeout = null; - }else{ - DateTimeout = Date.now() + timeout; - } - - return [ - States.RECEIVE, - fun, - DateTimeout, - timeoutFn - ]; - } - - sleep(duration){ - return [States.SLEEP, duration]; - } - - suspend(fun){ - this.current_process.status = States.SUSPENDED; - this.suspended.set(this.current_process.pid, fun); - } - - delay(fun, time){ - this.current_process.status = States.SLEEPING; - this.task_queue.queueFuture(this.current_process.pid, time, fun); - } - - queue(fun){ - this.task_queue.queue(this.current_process.pid, fun); - } - - exit(...args){ - switch(args.length) { - case 2: - if (args[1] != States.NORMAL) { - this.mailboxes.get(args[0]).deliver({ Signal: States.EXIT, From: this.pid(), Reason: args[1] }); - }else{ - this.remove_proc(args[0], args[1]); - } - break; - case 1: - this.current_process.exit(args[0]); - break; - case 0: - this.current_process.exit(States.Normal); - break; - } - } -} - -export default Scheduler; \ No newline at end of file diff --git a/priv/javascript/lib/processes/task_queue.js b/priv/javascript/lib/processes/task_queue.js deleted file mode 100644 index c08a0404..00000000 --- a/priv/javascript/lib/processes/task_queue.js +++ /dev/null @@ -1,86 +0,0 @@ -"use strict"; - -//TaskQueue. Borrowed and modified from RxJS's Default Scheduler. -//While it is probably more robust, this should fit the needs for -//this project. - -class TaskQueue { - constructor(throttle = 0){ - this.nextTaskId = 1; - this.tasks = {} - this.isRunning = false; - this.invokeLater = function (callback) { setTimeout(callback, throttle); } - } - - removeFromTaskQueue(taskId){ - delete this.tasks[taskId]; - } - - removePid(pid){ - //prevent further execution while removing tasks - //with matching pids - this.isRunning = true; - - for(let taskId of Object.keys(this.tasks)){ - if(this.tasks[taskId] && this.tasks[taskId][0] === pid){ - this.removeFromTaskQueue(taskId); - } - } - - this.isRunning = false; - } - - runTask(taskId){ - if (this.isRunning) { - this.invokeLater(() => { this.runTask(taskId); }); - } else { - if(this.tasks[taskId]){ - - let [pid, task] = this.tasks[taskId]; - - if (task) { - this.isRunning = true; - - let result; - - try{ - result = task(); - }catch(e){ - result = e; - } - - this.removeFromTaskQueue(taskId); - this.isRunning = false; - - if (result instanceof Error) { - throw result; - } - } - - } - } - } - - addToTaskQueue(pid, task, dueTime = 0) { - let id = this.nextTaskId ++; - this.tasks[id] = [ pid, task ]; - - if(dueTime === 0){ - this.invokeLater(() => { this.runTask(id); }); - }else{ - setTimeout(() => { this.runTask(id); }, dueTime); - } - - return id; - }; - - queue(pid, task){ - this.addToTaskQueue(pid, () => { task(); }); - } - - queueFuture(pid, dueTime, task){ - this.addToTaskQueue(pid, () => { task(); }, dueTime); - } -} - -export default TaskQueue; \ No newline at end of file diff --git a/test/translator/receive_test.exs b/test/translator/receive_test.exs index db1a018b..46f0f5cb 100644 --- a/test/translator/receive_test.exs +++ b/test/translator/receive_test.exs @@ -15,7 +15,7 @@ defmodule ElixirScript.Translator.Receive.Test do end js_code = """ - yield self.scheduler.receive(function(message) { + yield self.system.receive(function(message) { return Patterns.defmatch(Patterns.make_case([Kernel.SpecialForms.atom('ok')],function() { return value; }),Patterns.make_case([Kernel.SpecialForms.atom('error')],function() { @@ -45,7 +45,7 @@ defmodule ElixirScript.Translator.Receive.Test do end js_code = """ - yield self.scheduler.receive(function(message) { + yield self.system.receive(function(message) { return Patterns.defmatch(Patterns.make_case([Kernel.SpecialForms.atom('ok')],function() { return value; }),Patterns.make_case([Kernel.SpecialForms.atom('error')],function() { From fd8897a2bbe2ba95b210fd6f7493865298540531 Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Fri, 16 Oct 2015 15:28:36 -0500 Subject: [PATCH 011/860] Returned agent to previous implementation. Added some functions from Base and String --- lib/elixir_script/translator/import.ex | 22 +-- mix.exs | 6 +- priv/javascript/elixir.js | 6 +- priv/javascript/lib/agent.js | 121 +++------------- priv/javascript/lib/base.js | 32 ++++ priv/javascript/lib/string.js | 193 +++++++++++++++++++++++++ test/elixir_script_test.exs | 8 +- 7 files changed, 261 insertions(+), 127 deletions(-) create mode 100644 priv/javascript/lib/base.js create mode 100644 priv/javascript/lib/string.js diff --git a/lib/elixir_script/translator/import.ex b/lib/elixir_script/translator/import.ex index f2b4916b..3cf3360f 100644 --- a/lib/elixir_script/translator/import.ex +++ b/lib/elixir_script/translator/import.ex @@ -1,7 +1,6 @@ defmodule ElixirScript.Translator.Import do @moduledoc false alias ESTree.Tools.Builder, as: JS - alias ElixirScript.Translator alias ElixirScript.State def make_alias_import(alias_info, options) do @@ -46,9 +45,7 @@ defmodule ElixirScript.Translator.Import do ) end - def make_import(module_name_list, [], env) do - mod = List.last(module_name_list) |> JS.identifier - + def make_import(module_name_list, [], _) do functions = State.get_module(module_name_list).functions functions = Enum.map(functions, fn @@ -78,9 +75,7 @@ defmodule ElixirScript.Translator.Import do JS.import_declaration(specifiers, JS.identifier(import_path)) end - def make_import(module_name_list, [only: :functions], env) do - mod = List.last(module_name_list) |> JS.identifier - + def make_import(module_name_list, [only: :functions], _) do functions = State.get_module(module_name_list).functions functions = Enum.map(functions, fn @@ -104,9 +99,7 @@ defmodule ElixirScript.Translator.Import do JS.import_declaration(specifiers, JS.identifier(import_path)) end - def make_import(module_name_list, [only: only], env) do - mod = List.last(module_name_list) |> JS.identifier - + def make_import(module_name_list, [only: only], _) do only = Enum.map(only, fn ({name, _arity}) -> name @@ -131,9 +124,7 @@ defmodule ElixirScript.Translator.Import do JS.import_declaration(specifiers, JS.identifier(import_path)) end - def make_import(module_name_list, [except: except], env) do - mod = List.last(module_name_list) |> JS.identifier - + def make_import(module_name_list, [except: except], _) do except = Enum.map(except, fn ({name, _arity}) -> name @@ -181,12 +172,11 @@ defmodule ElixirScript.Translator.Import do Set.difference(Enum.into(module.functions, HashSet.new), Enum.into(except, HashSet.new)) end - - def create_standard_lib_imports(root, env) do + def create_standard_lib_imports(root, _) do module_names = [ :Patterns, :Kernel, :Atom, :Enum, :Integer, :JS, :List, :Range, :Tuple, :Agent, :Keyword, - :BitString + :BitString, :Base, :String ] import_specifiers = Enum.map(module_names, fn(x) -> diff --git a/mix.exs b/mix.exs index 341a2ea1..95907255 100644 --- a/mix.exs +++ b/mix.exs @@ -15,7 +15,7 @@ defmodule ElixirScript.Mixfile do test_coverage: [tool: ExCoveralls], preferred_cli_env: [coveralls: :test], docs: [ - extras: ["README.md"] + extras: ["README.md", "GettingStarted.md", "FAQ.md"] ] ] end @@ -51,9 +51,9 @@ defmodule ElixirScript.Mixfile do defp package do [ files: ["lib", "priv/javascript/dist", "mix.exs", "README*", "readme*", "LICENSE*", "license*", "CHANGELOG*"], - contributors: ["Bryan Joseph"], + maintainers: ["Bryan Joseph"], licenses: ["MIT"], - links: %{ + links: %{ "GitHub" => "https://github.com/bryanjos/elixirscript" }, build_tools: ["mix"] diff --git a/priv/javascript/elixir.js b/priv/javascript/elixir.js index da7c4f2e..403c5198 100644 --- a/priv/javascript/elixir.js +++ b/priv/javascript/elixir.js @@ -1,9 +1,6 @@ import PostOffice from './lib/post_office'; -import { ProcessSystem } from './lib/processes/processes'; - self.post_office = self.post_office || new PostOffice(); -self.system = self.system || new ProcessSystem(); export { default as Patterns } from './lib/patterns/patterns'; export { default as BitString } from './lib/bit_string'; @@ -17,4 +14,5 @@ export { default as Range } from './lib/range'; export { default as Tuple } from './lib/tuple'; export { default as Agent } from './lib/agent'; export { default as Keyword } from './lib/keyword'; -export { GenServer } from './lib/processes/processes'; \ No newline at end of file +export { default as Base } from './lib/base'; +export { default as String } from './lib/string'; \ No newline at end of file diff --git a/priv/javascript/lib/agent.js b/priv/javascript/lib/agent.js index e8dfd550..fe72f2b3 100644 --- a/priv/javascript/lib/agent.js +++ b/priv/javascript/lib/agent.js @@ -1,119 +1,40 @@ import Kernel from './kernel'; import Keyword from './keyword'; -function start(fun, options = []){ - let pid = self.system.spawn(start_process(module, args)); +let Agent = {}; - if(Keyword.has_key__qm__(options, Kernel.SpecialForms.atom("name"))){ - let name = Keyword.get(options, Kernel.SpecialForms.atom("name")); +Agent.start = function(fun, options = []){ + const name = Keyword.has_key__qm__(options, Kernel.SpecialForms.atom("name")) ? Keyword.get(options, Kernel.SpecialForms.atom("name")) : Symbol(); + + self.post_office.add_mailbox(name); + self.post_office.send(name, fun()); - self.system.register(name, pid); - return Kernel.SpecialForms.tuple(Kernel.SpecialForms.atom("ok"), name); - } - - return Kernel.SpecialForms.tuple(Kernel.SpecialForms.atom("ok"), pid); + return Kernel.SpecialForms.tuple(Kernel.SpecialForms.atom("ok"), name); } -function start_link(fun, options = []){ - let pid = self.system.spawn_link(start_process(module, args)); - - if(Keyword.has_key__qm__(options, Kernel.SpecialForms.atom("name"))){ - let name = Keyword.get(options, Kernel.SpecialForms.atom("name")); - - self.system.register(name, pid); - return Kernel.SpecialForms.tuple(Kernel.SpecialForms.atom("ok"), name); - } - - return Kernel.SpecialForms.tuple(Kernel.SpecialForms.atom("ok"), pid); +Agent.stop = function(agent, timeout = 5000){ + self.post_office.remove_mailbox(agent); + return Kernel.SpecialForms.atom("ok"); } -function start_process(fun){ - return function*(){ - yield self.system.put("state", fun.apply(null, [])); - - try{ - while(true){ - yield self.system.receive(function(args){ - let command = args[0]; - - switch(command){ - case "update": - let updateFn = args[1]; - let sender = args[2]; - - let current_state = self.system.get("state"); - let new_state = updateFn(current_state); - - self.system.put("state", new_state); - self.system.send(sender, Symbol.for("ok")); - - break; - case "get": - let getFn = args[1]; - let sender = args[2]; +Agent.update = function(agent, fun, timeout = 5000){ - let current_state = self.system.get("state"); - let return_value = getFn(current_state); + const current_state = self.post_office.receive(agent); + self.post_office.send(agent, fun(current_state)); - self.system.send(sender, return_value); - - break; - case "get_and_update": - let updateFn = args[1]; - let sender = args[2]; - - let current_state = self.system.get("state"); - let get_and_update_tuple = updateFn(current_state); - - self.system.put("state", Kernel.elem(get_and_update_tuple, 1)); - self.system.send(sender, Kernel.elem(get_and_update_tuple, 0)); - - break; - case "stop": - throw "stop"; - } - }); - } - }catch(e){ - if(e !== "stop"){ - throw e; - } - } - } + return Kernel.SpecialForms.atom("ok"); } -function* stop(agent, timeout = 5000){ - self.system.send(agent, ["stop", self.system.pid()]); +Agent.get = function(agent, fun, timeout = 5000){ + return fun(self.post_office.peek(agent)); } -function* update(agent, fun, timeout = 5000){ - self.system.send(agent, ["update", fun, self.system.pid()]); - - return yield self.system.receive(function(args){ - return args; - }); -} - -function* get(agent, fun, timeout = 5000){ - self.system.send(agent, ["update", fun, self.system.pid()]); - - return yield self.system.receive(function(args){ - return args; - }); -} +Agent.get_and_update = function(agent, fun, timeout = 5000){ -function* get_and_update(agent, fun, timeout = 5000){ - self.system.send(agent, ["get_and_update", fun, self.system.pid()]); + const get_and_update_tuple = fun(self.post_office.receive(agent)); + self.post_office.send(agent, Kernel.elem(get_and_update_tuple, 1)); - return yield self.system.receive(function(args){ - return args; - }); + return Kernel.elem(get_and_update_tuple, 0); } -export default { - start, - stop, - update, - get, - get_and_update -}; +export default Agent; \ No newline at end of file diff --git a/priv/javascript/lib/base.js b/priv/javascript/lib/base.js new file mode 100644 index 00000000..440c001c --- /dev/null +++ b/priv/javascript/lib/base.js @@ -0,0 +1,32 @@ +import Kernel from './kernel'; + +//https://developer.mozilla.org/en-US/docs/Web/API/WindowBase64/Base64_encoding_and_decoding#Solution_2_%E2%80%93_rewrite_the_DOMs_atob()_and_btoa()_using_JavaScript's_TypedArrays_and_UTF-8 +function b64EncodeUnicode(str) { + return btoa(encodeURIComponent(str).replace(/%([0-9A-F]{2})/g, function(match, p1) { + return String.fromCharCode('0x' + p1); + })); +} + +function encode64(data){ + return b64EncodeUnicode(data); +} + +function decode64(data){ + try{ + return Kernel.SpecialForms.tuple(Kernel.SpecialForms.atom("ok"), atob(data)); + }catch(e){ + return Kernel.SpecialForms.atom("error"); + } + return btoa(data); +} + +function decode64__em__(data){ + return atob(data); +} + + +export { + encode64, + decode64, + decode64__em__ +} \ No newline at end of file diff --git a/priv/javascript/lib/string.js b/priv/javascript/lib/string.js new file mode 100644 index 00000000..374dc448 --- /dev/null +++ b/priv/javascript/lib/string.js @@ -0,0 +1,193 @@ +import Kernel from './kernel'; + +function to_atom(string){ + return Symbol.for(string); +} + +function to_existing_atom(string){ + return Symbol.for(string); +} + +function to_char_list(string){ + return string.split(''); +} + +function to_float(string){ + return parseFloat(string); +} + +function to_integer(string, base = 10){ + return parseInt(string, base); +} + +function upcase(binary){ + return binary.toUpperCase(); +} + +function downcase(binary){ + return binary.toLowerCase(); +} + +function at(string, position){ + if(position > (string.length - 1)){ + return null; + } + + return string[position]; +} + +function capitalize(string){ + let returnString = ""; + + for(let i = 0; i < string.length; i++){ + if(i === 0){ + returnString = returnString + string[i].toUpperCase(); + }else{ + returnString = returnString + string[i].toLowerCase(); + } + } + + return returnString; +} + + +function codepoints(string){ + return to_char_list(string).map(function(c){ + return c.codePointAt(0); + }); +} + + +function contains__qm__(string, contains){ + if(Array.isArray(contains)){ + return contains.some(function(s){ + return string.indexOf(s) > -1; + }); + } + + return string.indexOf(contains) > -1; +} + +function duplicate(subject, n){ + return subject.repeat(n); +} + +function ends_with__qm__(string, suffixes){ + if(Array.isArray(suffixes)){ + return suffixes.some(function(s){ + return string.endsWith(s); + }); + } + + return string.endsWith(suffixes); +} + +function first(string){ + if(!string){ + return null; + } + + return string[0]; +} + +function graphemes(string){ + return string.split(''); +} + +function last(string){ + if(!string){ + return null; + } + + return string[string.length - 1]; +} + +function length(string){ + return string.length; +} + + +function match__qm__(string, regex){ + return string.match(regex) != null; +} + + +function next_codepoint(string){ + if(!string || string === ""){ + return null; + } + + return Kernel.SpecialForms.tuple(string[0].codePointAt(0), string.substr(1)); +} + + +function next_grapheme(string){ + if(!string || string === ""){ + return null; + } + + return Kernel.SpecialForms.tuple(string[0], string.substr(1)); +} + + +function reverse(string){ + let returnValue = ""; + + for (var i = string.length - 1; i >= 0; i--) { + returnValue = returnValue + string[i]; + }; + + return returnValue; +} + + +function split(string){ + return string.split(); +} + + +function starts_with__qm__(string, prefixes){ + if(Array.isArray(prefixes)){ + return prefixes.some(function(s){ + return string.startsWith(s); + }); + } + + return string.startsWith(prefixes); +} + +function valid_character__qm__(codepoint){ + try{ + return String.fromCodePoint(codepoint) != null; + }catch(e){ + return false; + } +} + + +export default { + at, + capitalize, + codepoints, + contains__qm__, + downcase, + duplicate, + ends_with__qm__, + first, + graphemes, + last, + length, + match__qm__, + next_codepoint, + next_grapheme, + reverse, + split, + starts_with__qm__, + to_atom, + to_char_list, + to_existing_atom, + to_float, + to_integer, + upcase, + valid_character__qm__ +} \ No newline at end of file diff --git a/test/elixir_script_test.exs b/test/elixir_script_test.exs index 4849e865..1814a7d9 100644 --- a/test/elixir_script_test.exs +++ b/test/elixir_script_test.exs @@ -31,7 +31,7 @@ defmodule ElixirScript.Test do """) assert_js_matches """ - import { Patterns, Kernel, Atom, Enum, Integer, JS, List, Range, Tuple, Agent, Keyword, BitString } from 'elixir'; + import { Patterns, Kernel, Atom, Enum, Integer, JS, List, Range, Tuple, Agent, Keyword, BitString, Base, String } from 'elixir'; const __MODULE__ = Kernel.SpecialForms.atom('Elephant'); let something_else = Patterns.defmatch(Patterns.make_case([],function() { return null; @@ -64,7 +64,7 @@ defmodule ElixirScript.Test do """, env: make_custom_env) assert_js_matches """ - import { Patterns, Kernel, Atom, Enum, Integer, JS, List, Range, Tuple, Agent, Keyword, BitString } from 'elixir'; + import { Patterns, Kernel, Atom, Enum, Integer, JS, List, Range, Tuple, Agent, Keyword, BitString, Base, String } from 'elixir'; import * as Elephant from 'animals/elephant'; const __MODULE__ = Kernel.SpecialForms.atom('Animals'); @@ -77,7 +77,7 @@ defmodule ElixirScript.Test do """, hd(js_code) assert_js_matches """ - import { Patterns, Kernel, Atom, Enum, Integer, JS, List, Range, Tuple, Agent, Keyword, BitString } from 'elixir'; + import { Patterns, Kernel, Atom, Enum, Integer, JS, List, Range, Tuple, Agent, Keyword, BitString, Base, String } from 'elixir'; const __MODULE__ = Kernel.SpecialForms.atom('Elephant'); function defstruct(trunk = true) { return Kernel.SpecialForms.map({ @@ -105,7 +105,7 @@ defmodule ElixirScript.Test do """, env: make_custom_env) assert_js_matches """ - import { Patterns, Kernel, Atom, Enum, Integer, JS, List, Range, Tuple, Agent, Keyword, BitString } from 'elixir'; + import { Patterns, Kernel, Atom, Enum, Integer, JS, List, Range, Tuple, Agent, Keyword, BitString, Base, String } from 'elixir'; const __MODULE__ = Kernel.SpecialForms.atom('Animals'); let something_else = Patterns.defmatch(Patterns.make_case([],function() { return 1 * 1; From cbe5c9cb9adb73d5cb0ac6dd9217999e2e0239c3 Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Fri, 16 Oct 2015 15:32:06 -0500 Subject: [PATCH 012/860] Updated CHANGELOG --- CHANGELOG.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 6a518599..f30ab64b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,7 @@ # v0.13.0-dev * Enhancements - * Introduction of processes + * Added Base module with function: encode64, decode64, and decode64! + * Added String module # v0.12.0 * Enhancements From e30290b02aaea21f272869a2c2f0862ae9ff702e Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Fri, 16 Oct 2015 15:41:17 -0500 Subject: [PATCH 013/860] Added Bitwise module --- CHANGELOG.md | 1 + lib/elixir_script/translator/import.ex | 2 +- priv/javascript/elixir.js | 3 ++- priv/javascript/lib/bitwise.js | 32 ++++++++++++++++++++++++++ test/elixir_script_test.exs | 8 +++---- 5 files changed, 40 insertions(+), 6 deletions(-) create mode 100644 priv/javascript/lib/bitwise.js diff --git a/CHANGELOG.md b/CHANGELOG.md index f30ab64b..cc676463 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,7 @@ * Enhancements * Added Base module with function: encode64, decode64, and decode64! * Added String module + * Added Bitwise module # v0.12.0 * Enhancements diff --git a/lib/elixir_script/translator/import.ex b/lib/elixir_script/translator/import.ex index 3cf3360f..de0f5e0a 100644 --- a/lib/elixir_script/translator/import.ex +++ b/lib/elixir_script/translator/import.ex @@ -176,7 +176,7 @@ defmodule ElixirScript.Translator.Import do module_names = [ :Patterns, :Kernel, :Atom, :Enum, :Integer, :JS, :List, :Range, :Tuple, :Agent, :Keyword, - :BitString, :Base, :String + :BitString, :Base, :String, :Bitwise ] import_specifiers = Enum.map(module_names, fn(x) -> diff --git a/priv/javascript/elixir.js b/priv/javascript/elixir.js index 403c5198..f4714aa0 100644 --- a/priv/javascript/elixir.js +++ b/priv/javascript/elixir.js @@ -15,4 +15,5 @@ export { default as Tuple } from './lib/tuple'; export { default as Agent } from './lib/agent'; export { default as Keyword } from './lib/keyword'; export { default as Base } from './lib/base'; -export { default as String } from './lib/string'; \ No newline at end of file +export { default as String } from './lib/string'; +export { default as Bitwise } from './lib/bitwise'; \ No newline at end of file diff --git a/priv/javascript/lib/bitwise.js b/priv/javascript/lib/bitwise.js new file mode 100644 index 00000000..b42ec1e6 --- /dev/null +++ b/priv/javascript/lib/bitwise.js @@ -0,0 +1,32 @@ +function bnot(expr){ + return ~expr; +} + +function band(left, right){ + return left & right; +} + +function bor(left, right){ + return left | right; +} + +function bsl(left, right){ + return left << right; +} + +function bsr(left, right){ + return left >> right; +} + +function bxor(left, right){ + return left ^ right; +} + +export default { + bnot, + band, + bor, + bsl, + bsr, + bxor +} \ No newline at end of file diff --git a/test/elixir_script_test.exs b/test/elixir_script_test.exs index 1814a7d9..d303b3df 100644 --- a/test/elixir_script_test.exs +++ b/test/elixir_script_test.exs @@ -31,7 +31,7 @@ defmodule ElixirScript.Test do """) assert_js_matches """ - import { Patterns, Kernel, Atom, Enum, Integer, JS, List, Range, Tuple, Agent, Keyword, BitString, Base, String } from 'elixir'; + import { Patterns, Kernel, Atom, Enum, Integer, JS, List, Range, Tuple, Agent, Keyword, BitString, Base, String, Bitwise } from 'elixir'; const __MODULE__ = Kernel.SpecialForms.atom('Elephant'); let something_else = Patterns.defmatch(Patterns.make_case([],function() { return null; @@ -64,7 +64,7 @@ defmodule ElixirScript.Test do """, env: make_custom_env) assert_js_matches """ - import { Patterns, Kernel, Atom, Enum, Integer, JS, List, Range, Tuple, Agent, Keyword, BitString, Base, String } from 'elixir'; + import { Patterns, Kernel, Atom, Enum, Integer, JS, List, Range, Tuple, Agent, Keyword, BitString, Base, String, Bitwise } from 'elixir'; import * as Elephant from 'animals/elephant'; const __MODULE__ = Kernel.SpecialForms.atom('Animals'); @@ -77,7 +77,7 @@ defmodule ElixirScript.Test do """, hd(js_code) assert_js_matches """ - import { Patterns, Kernel, Atom, Enum, Integer, JS, List, Range, Tuple, Agent, Keyword, BitString, Base, String } from 'elixir'; + import { Patterns, Kernel, Atom, Enum, Integer, JS, List, Range, Tuple, Agent, Keyword, BitString, Base, String, Bitwise } from 'elixir'; const __MODULE__ = Kernel.SpecialForms.atom('Elephant'); function defstruct(trunk = true) { return Kernel.SpecialForms.map({ @@ -105,7 +105,7 @@ defmodule ElixirScript.Test do """, env: make_custom_env) assert_js_matches """ - import { Patterns, Kernel, Atom, Enum, Integer, JS, List, Range, Tuple, Agent, Keyword, BitString, Base, String } from 'elixir'; + import { Patterns, Kernel, Atom, Enum, Integer, JS, List, Range, Tuple, Agent, Keyword, BitString, Base, String, Bitwise } from 'elixir'; const __MODULE__ = Kernel.SpecialForms.atom('Animals'); let something_else = Patterns.defmatch(Patterns.make_case([],function() { return 1 * 1; From dcaa019fc11456f709ad46be0edf062d8963daec Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Fri, 16 Oct 2015 15:42:10 -0500 Subject: [PATCH 014/860] Updated FAQ --- FAQ.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/FAQ.md b/FAQ.md index 68da785d..b1e385f4 100644 --- a/FAQ.md +++ b/FAQ.md @@ -72,6 +72,9 @@ The compiler to this point has been focused on translating Kernel.SpecialForms a * Agent * Integer * Keyword + * Base + * String + * Bitwise #### Missing Modules * Everything else From ce52bbf089f659cc55ea9e0deebf9663c1a9a8ea Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Sun, 18 Oct 2015 12:21:32 -0500 Subject: [PATCH 015/860] All standard libs are now in the Elixir namespace Turned all named function defintions from let to const Updated defstruct implementation --- lib/elixir_script/pattern_matching/match.ex | 42 +++-- lib/elixir_script/translator.ex | 1 - lib/elixir_script/translator/assignment.ex | 7 +- lib/elixir_script/translator/capture.ex | 4 + lib/elixir_script/translator/function.ex | 60 +++++-- lib/elixir_script/translator/import.ex | 17 +- lib/elixir_script/translator/kernel.ex | 2 +- lib/elixir_script/translator/primitive.ex | 7 +- lib/elixir_script/translator/quote.ex | 7 +- lib/elixir_script/translator/struct.ex | 104 +++++------ mix.lock | 4 +- priv/javascript/elixir.js | 3 +- priv/javascript/lib/js.js | 2 +- priv/javascript/lib/kernel.js | 4 + test/elixir_script_test.exs | 38 ++-- test/lib/js_test.exs | 2 +- test/lib/kernel_test.exs | 2 +- test/pattern_matching/match_test.exs | 2 +- test/test_helper.exs | 2 +- test/translator/access_test.exs | 2 +- test/translator/assignment_test.exs | 26 +-- test/translator/atom_test.exs | 2 +- test/translator/bitstring_test.exs | 24 +-- test/translator/bug_test.exs | 32 ++-- test/translator/capture_test.exs | 28 +-- test/translator/case_test.exs | 58 +++---- test/translator/cond_test.exs | 18 +- test/translator/defmodule_test.exs | 94 +++++----- test/translator/for_test.exs | 46 ++--- test/translator/function_test.exs | 182 ++++++++++---------- test/translator/kernel_test.exs | 6 +- test/translator/list_test.exs | 12 +- test/translator/map_test.exs | 18 +- test/translator/quote_test.exs | 38 ++-- test/translator/receive_test.exs | 14 +- test/translator/string_test.exs | 6 +- test/translator/struct_test.exs | 56 +++--- test/translator/try_test.exs | 56 +++--- test/translator/tuple_test.exs | 10 +- 39 files changed, 556 insertions(+), 482 deletions(-) diff --git a/lib/elixir_script/pattern_matching/match.ex b/lib/elixir_script/pattern_matching/match.ex index 8251f4b6..89e50c5b 100644 --- a/lib/elixir_script/pattern_matching/match.ex +++ b/lib/elixir_script/pattern_matching/match.ex @@ -8,33 +8,51 @@ defmodule ElixirScript.PatternMatching.Match do alias ElixirScript.Translator.Map @wildcard JS.member_expression( - JS.identifier(:Patterns), - JS.identifier(:wildcard) + JS.identifier("Elixir"), + JS.member_expression( + JS.identifier(:Patterns), + JS.identifier(:wildcard) + ) ) @parameter JS.member_expression( - JS.identifier(:Patterns), - JS.identifier(:variable) + JS.identifier("Elixir"), + JS.member_expression( + JS.identifier(:Patterns), + JS.identifier(:variable) + ) ) @head_tail JS.member_expression( - JS.identifier(:Patterns), - JS.identifier(:headTail) + JS.identifier("Elixir"), + JS.member_expression( + JS.identifier(:Patterns), + JS.identifier(:headTail) + ) ) @starts_with JS.member_expression( - JS.identifier(:Patterns), - JS.identifier(:startsWith) + JS.identifier("Elixir"), + JS.member_expression( + JS.identifier(:Patterns), + JS.identifier(:startsWith) + ) ) @capture JS.member_expression( - JS.identifier(:Patterns), - JS.identifier(:capture) + JS.identifier("Elixir"), + JS.member_expression( + JS.identifier(:Patterns), + JS.identifier(:capture) + ) ) @bound JS.member_expression( - JS.identifier(:Patterns), - JS.identifier(:bound) + JS.identifier("Elixir"), + JS.member_expression( + JS.identifier(:Patterns), + JS.identifier(:bound) + ) ) def wildcard() do diff --git a/lib/elixir_script/translator.ex b/lib/elixir_script/translator.ex index 793d5d52..cb5c569d 100644 --- a/lib/elixir_script/translator.ex +++ b/lib/elixir_script/translator.ex @@ -79,7 +79,6 @@ defmodule ElixirScript.Translator do defp do_translate({:%, _, [alias_info, data]}, env) do {_, _, name} = alias_info - {_, _, data} = data Struct.make_struct(name, data, env) end diff --git a/lib/elixir_script/translator/assignment.ex b/lib/elixir_script/translator/assignment.ex index 668e546f..7511d06f 100644 --- a/lib/elixir_script/translator/assignment.ex +++ b/lib/elixir_script/translator/assignment.ex @@ -12,8 +12,11 @@ defmodule ElixirScript.Translator.Assignment do JS.array_pattern(params), JS.call_expression( JS.member_expression( - JS.identifier("Patterns"), - JS.identifier("match") + JS.identifier("Elixir"), + JS.member_expression( + JS.identifier("Patterns"), + JS.identifier("match") + ) ), [hd(patterns), Translator.translate(right, env)] ) diff --git a/lib/elixir_script/translator/capture.ex b/lib/elixir_script/translator/capture.ex index ec7e5313..68cfc72c 100644 --- a/lib/elixir_script/translator/capture.ex +++ b/lib/elixir_script/translator/capture.ex @@ -29,6 +29,10 @@ defmodule ElixirScript.Translator.Capture do def make_capture(module_name, function_name, arity, env) do params = Enum.map(1..arity, fn(x) -> {String.to_atom("__#{x}"), [], ElixirScript.Translator.Capture} end) + if Function.module_in_standard_libs?(module_name) do + module_name = [:Elixir, module_name] + end + { patterns, params } = Match.build_match(params, env) body = JS.block_statement([ diff --git a/lib/elixir_script/translator/function.ex b/lib/elixir_script/translator/function.ex index 9024c0b3..763c398b 100644 --- a/lib/elixir_script/translator/function.ex +++ b/lib/elixir_script/translator/function.ex @@ -7,6 +7,32 @@ defmodule ElixirScript.Translator.Function do alias ElixirScript.Preprocess.Variables alias ElixirScript.Translator.Map + @standard_libs [ + :Patterns, :Kernel, :Atom, :Enum, :Integer, :JS, + :List, :Range, :Tuple, :Agent, :Keyword, :BitString, + :Base, :String, :Bitwise + ] + + def update_alias({:__aliases__, context, [name | rest]}) when name in @standard_libs do + {:__aliases__, context, [:Elixir, name] ++ rest } + end + + def update_alias({:__aliases__, context, [name]}) when name in @standard_libs do + {:__aliases__, context, [:Elixir, name] } + end + + def update_alias({{:., context, [module_name, function_name]}, context2, params }) do + {{:., context, [update_alias(module_name), function_name]}, context2, params } + end + + def update_alias(ast) do + ast + end + + def module_in_standard_libs?(name) do + name in @standard_libs + end + def process_function(name, functions, env) do result = make_anonymous_function(functions, env) @@ -16,7 +42,7 @@ defmodule ElixirScript.Translator.Function do result ) - JS.variable_declaration([declarator], :let) + JS.variable_declaration([declarator], :const) end def make_anonymous_function(functions, env) do @@ -58,8 +84,11 @@ defmodule ElixirScript.Translator.Function do def make_defmatch(clauses) do JS.call_expression( JS.member_expression( - JS.identifier("Patterns"), - JS.identifier("defmatch") + JS.identifier("Elixir"), + JS.member_expression( + JS.identifier("Patterns"), + JS.identifier("defmatch") + ) ), clauses ) @@ -87,8 +116,11 @@ defmodule ElixirScript.Translator.Function do def do_make_function_clause(patterns, params, body, guard_body) do JS.call_expression( JS.member_expression( - JS.identifier("Patterns"), - JS.identifier("make_case") + JS.identifier("Elixir"), + JS.member_expression( + JS.identifier("Patterns"), + JS.identifier("make_case") + ) ), [ JS.array_expression(patterns), @@ -101,8 +133,11 @@ defmodule ElixirScript.Translator.Function do def do_make_function_clause(patterns, params, body) do JS.call_expression( JS.member_expression( - JS.identifier("Patterns"), - JS.identifier("make_case") + JS.identifier("Elixir"), + JS.member_expression( + JS.identifier("Patterns"), + JS.identifier("make_case") + ) ), [ JS.array_expression(patterns), @@ -112,7 +147,7 @@ defmodule ElixirScript.Translator.Function do end def make_function_or_property_call(module_name, function_name, env) do - the_name = case module_name do + the_name = case update_alias(module_name) do {:__aliases__, _, name} -> name {name, _, _} when is_atom(name) -> @@ -130,8 +165,11 @@ defmodule ElixirScript.Translator.Function do JS.call_expression( JS.member_expression( - JS.identifier("JS"), - JS.identifier("get_property_or_call_function") + JS.identifier("Elixir"), + JS.member_expression( + JS.identifier("JS"), + JS.identifier("call_property") + ) ), [ Utils.make_module_expression_tree(the_name, false, env), @@ -149,7 +187,7 @@ defmodule ElixirScript.Translator.Function do end def make_function_call(module_name, function_name, params, env) do - the_name = case module_name do + the_name = case update_alias(module_name) do {:__aliases__, _, name} -> name {name, _, _} when is_atom(name) -> diff --git a/lib/elixir_script/translator/import.ex b/lib/elixir_script/translator/import.ex index de0f5e0a..ae21e319 100644 --- a/lib/elixir_script/translator/import.ex +++ b/lib/elixir_script/translator/import.ex @@ -173,21 +173,12 @@ defmodule ElixirScript.Translator.Import do end def create_standard_lib_imports(root, _) do - module_names = [ - :Patterns, :Kernel, :Atom, :Enum, :Integer, - :JS, :List, :Range, :Tuple, :Agent, :Keyword, - :BitString, :Base, :String, :Bitwise - ] - - import_specifiers = Enum.map(module_names, fn(x) -> - JS.import_specifier( - JS.identifier(x), - JS.identifier(x) - ) - end) + import_specifier = JS.import_namespace_specifier( + JS.identifier(:Elixir) + ) import_declaration = JS.import_declaration( - import_specifiers, + [import_specifier], JS.identifier("'#{root(root) <> "elixir"}'") ) diff --git a/lib/elixir_script/translator/kernel.ex b/lib/elixir_script/translator/kernel.ex index e41c72f2..ee3e203b 100644 --- a/lib/elixir_script/translator/kernel.ex +++ b/lib/elixir_script/translator/kernel.ex @@ -286,7 +286,7 @@ defmodule ElixirScript.Translator.Kernel do end defp do_translate({name, _, params}, env) do - Function.make_function_call(:Kernel, name, params, env) + Function.make_function_call({:__aliases__, [], [:Elixir, :Kernel]}, name, params, env) end end \ No newline at end of file diff --git a/lib/elixir_script/translator/primitive.ex b/lib/elixir_script/translator/primitive.ex index 4c4b3197..f72612a8 100644 --- a/lib/elixir_script/translator/primitive.ex +++ b/lib/elixir_script/translator/primitive.ex @@ -7,8 +7,11 @@ defmodule ElixirScript.Translator.Primitive do def special_forms() do JS.member_expression( - JS.identifier("Kernel"), - JS.identifier("SpecialForms") + JS.identifier("Elixir"), + JS.member_expression( + JS.identifier("Kernel"), + JS.identifier("SpecialForms") + ) ) end diff --git a/lib/elixir_script/translator/quote.ex b/lib/elixir_script/translator/quote.ex index 09bdf4c5..815355c7 100644 --- a/lib/elixir_script/translator/quote.ex +++ b/lib/elixir_script/translator/quote.ex @@ -26,8 +26,11 @@ defmodule ElixirScript.Translator.Quote do JS.call_expression( JS.member_expression( - JS.identifier("Enum"), - JS.identifier("concat") + JS.identifier("Elixir"), + JS.member_expression( + JS.identifier("Enum"), + JS.identifier("concat") + ) ), expr ) diff --git a/lib/elixir_script/translator/struct.ex b/lib/elixir_script/translator/struct.ex index f3c6e8ed..6507459f 100644 --- a/lib/elixir_script/translator/struct.ex +++ b/lib/elixir_script/translator/struct.ex @@ -2,6 +2,7 @@ defmodule ElixirScript.Translator.Struct do @moduledoc false alias ESTree.Tools.Builder, as: JS alias ElixirScript.Translator + alias ElixirScript.Translator.Map def make_struct(module_name, data, env) do JS.call_expression( @@ -9,83 +10,90 @@ defmodule ElixirScript.Translator.Struct do JS.identifier(List.last(module_name)), JS.identifier(:defstruct) ), - Enum.map(data, fn({k, v})-> - JS.assignment_expression( - :=, - JS.identifier(k), - Translator.translate(v, env) - ) - end) + [Translator.translate(data, env)] ) end def make_defstruct(attributes, env) when length(attributes) == 1 do attributes = Enum.flat_map(attributes, fn(x) -> x end) - params = Enum.map(attributes, fn({x,_y}) -> x end) - defaults = Enum.map(attributes, fn({_x,y}) -> y end) + defaults = Enum.map(attributes, fn({x, y}) -> + Map.make_property( + Translator.translate(x, env), + Translator.translate(y, env) + ) + end) + |> JS.object_expression - do_make_defstruct(:defstruct, params, defaults, env) + do_make_defstruct(:defstruct, defaults, env) end def make_defstruct(attributes, env) do - params = Enum.map(attributes, fn(x) -> x end) - defaults = [] - - do_make_defstruct(:defstruct, params, defaults, env) + defaults = Enum.map(attributes, fn(x) -> + Map.make_property( + Translator.translate(x, env), + Translator.translate(nil, env) + ) + end) + |> JS.object_expression + + do_make_defstruct(:defstruct, defaults, env) end def make_defexception(attributes, env) when length(attributes) == 1 do attributes = Enum.flat_map(attributes, fn(x) -> x end) - params = Enum.map(attributes, fn(x) -> - - case x do - a when is_tuple(a) -> - elem(a, 0) - _ -> - x - end - - end) - - defaults = Enum.map(attributes, fn(x) -> - - case x do - a when is_tuple(a) -> - elem(a, 1) - _ -> - nil - end - - end) + defaults = Enum.map(attributes, fn + ({x, y}) -> + Map.make_property( + Translator.translate(x, env), + Translator.translate(y, env) + ) + (x) -> + Map.make_property( + Translator.translate(x, env), + Translator.translate(nil, env) + ) + end) + |> JS.object_expression - do_make_defstruct(:defexception, params, defaults, env) + do_make_defstruct(:defexception, defaults, env) end def make_defexceptions(attributes, env) do - params = Enum.map(attributes, fn(x) -> x end) - defaults = [] + defaults = Enum.map(attributes, fn + (x) -> + Map.make_property( + Translator.translate(x, env), + Translator.translate(nil, env) + ) + end) + |> JS.object_expression - do_make_defstruct(:defexception, params, defaults, env) + do_make_defstruct(:defexception, defaults, env) end - defp do_make_defstruct(name, params, defaults, env) do + defp do_make_defstruct(name, defaults, env) do + struct_name = Map.make_property(Translator.translate(:__struct__, env), JS.identifier(:__MODULE__)) + + defaults = %{ defaults | properties: [struct_name] ++ defaults.properties } + JS.function_declaration( JS.identifier(name), - Enum.map(params, &JS.identifier(&1)), - Enum.map(defaults, &Translator.translate(&1, env)), + [JS.identifier(:values)], + [JS.object_expression([])], JS.block_statement([ JS.return_statement( - ElixirScript.Translator.Map.make_map( - JS.object_expression( - [ElixirScript.Translator.Map.make_property(Translator.translate(:__struct__, env), JS.identifier(:__MODULE__))] ++ - Enum.map(params, fn(x) -> ElixirScript.Translator.Map.make_property(Translator.translate(x, env), JS.identifier(x)) end) - ) + JS.call_expression( + JS.member_expression( + JS.identifier("Kernel"), + JS.identifier("defstruct") + ), + [defaults, JS.identifier(:values)] ) ) ]) ) end -end +end \ No newline at end of file diff --git a/mix.lock b/mix.lock index 88f3ee4c..3b317806 100644 --- a/mix.lock +++ b/mix.lock @@ -1,9 +1,9 @@ %{"benchfella": {:hex, :benchfella, "0.2.1"}, "dogma": {:hex, :dogma, "0.0.7"}, "earmark": {:hex, :earmark, "0.1.17"}, - "estree": {:hex, :estree, "2.0.1"}, + "estree": {:hex, :estree, "2.1.1"}, "ex_doc": {:hex, :ex_doc, "0.10.0"}, - "excoveralls": {:hex, :excoveralls, "0.3.11"}, + "excoveralls": {:hex, :excoveralls, "0.4.0"}, "exjsx": {:hex, :exjsx, "3.2.0"}, "hackney": {:hex, :hackney, "1.3.2"}, "idna": {:hex, :idna, "1.0.2"}, diff --git a/priv/javascript/elixir.js b/priv/javascript/elixir.js index f4714aa0..45722bb2 100644 --- a/priv/javascript/elixir.js +++ b/priv/javascript/elixir.js @@ -16,4 +16,5 @@ export { default as Agent } from './lib/agent'; export { default as Keyword } from './lib/keyword'; export { default as Base } from './lib/base'; export { default as String } from './lib/string'; -export { default as Bitwise } from './lib/bitwise'; \ No newline at end of file +export { default as Bitwise } from './lib/bitwise'; + diff --git a/priv/javascript/lib/js.js b/priv/javascript/lib/js.js index fcf82f63..ad5949cd 100644 --- a/priv/javascript/lib/js.js +++ b/priv/javascript/lib/js.js @@ -1,5 +1,5 @@ let JS = { - get_property_or_call_function: function(item, property){ + call_property: function(item, property){ if(item[property] instanceof Function){ return item[property](); }else{ diff --git a/priv/javascript/lib/kernel.js b/priv/javascript/lib/kernel.js index 2b5a3ae5..3cf128a9 100644 --- a/priv/javascript/lib/kernel.js +++ b/priv/javascript/lib/kernel.js @@ -146,6 +146,10 @@ let Kernel = { match__qmark__: function(pattern, expr, guard = () => true){ return Patterns.match_no_throw(pattern, expr, guard) != null; + }, + + defstruct: function(defaults, values){ + return Kernel.SpecialForms.map_update(defaults, values); } }; diff --git a/test/elixir_script_test.exs b/test/elixir_script_test.exs index d303b3df..4b2c8b01 100644 --- a/test/elixir_script_test.exs +++ b/test/elixir_script_test.exs @@ -12,7 +12,7 @@ defmodule ElixirScript.Test do should "turn javascript ast into javascript code strings" do js_code = ElixirScript.compile(":atom") - assert hd(js_code) == "Kernel.SpecialForms.atom('atom')" + assert hd(js_code) == "Elixir.Kernel.SpecialForms.atom('atom')" end should "parse one module correctly" do @@ -31,12 +31,12 @@ defmodule ElixirScript.Test do """) assert_js_matches """ - import { Patterns, Kernel, Atom, Enum, Integer, JS, List, Range, Tuple, Agent, Keyword, BitString, Base, String, Bitwise } from 'elixir'; - const __MODULE__ = Kernel.SpecialForms.atom('Elephant'); - let something_else = Patterns.defmatch(Patterns.make_case([],function() { + import * as Elixir from 'elixir'; + const __MODULE__ = Elixir.Kernel.SpecialForms.atom('Elephant'); + const something_else = Elixir.Patterns.defmatch(Elixir.Patterns.make_case([],function() { return null; })); - let something = Patterns.defmatch(Patterns.make_case([],function() { + const something = Elixir.Patterns.defmatch(Elixir.Patterns.make_case([],function() { return ul; })); const ul = JQuery('#todo-list'); @@ -64,12 +64,12 @@ defmodule ElixirScript.Test do """, env: make_custom_env) assert_js_matches """ - import { Patterns, Kernel, Atom, Enum, Integer, JS, List, Range, Tuple, Agent, Keyword, BitString, Base, String, Bitwise } from 'elixir'; + import * as Elixir from 'elixir'; import * as Elephant from 'animals/elephant'; - const __MODULE__ = Kernel.SpecialForms.atom('Animals'); - let something = Patterns.defmatch(Patterns.make_case([],function() { - return Elephant.defstruct(); + const __MODULE__ = Elixir.Kernel.SpecialForms.atom('Animals'); + const something = Elixir.Patterns.defmatch(Elixir.Patterns.make_case([],function() { + return Elephant.defstruct(Elixir.Kernel.SpecialForms.map({})); })); export { something @@ -77,12 +77,12 @@ defmodule ElixirScript.Test do """, hd(js_code) assert_js_matches """ - import { Patterns, Kernel, Atom, Enum, Integer, JS, List, Range, Tuple, Agent, Keyword, BitString, Base, String, Bitwise } from 'elixir'; - const __MODULE__ = Kernel.SpecialForms.atom('Elephant'); - function defstruct(trunk = true) { - return Kernel.SpecialForms.map({ - [Kernel.SpecialForms.atom('__struct__')]: __MODULE__, [Kernel.SpecialForms.atom('trunk')]: trunk - }); + import * as Elixir from 'elixir'; + const __MODULE__ = Elixir.Kernel.SpecialForms.atom('Elephant'); + function defstruct(values = {}) { + return Kernel.defstruct({ + [Elixir.Kernel.SpecialForms.atom('__struct__')]: __MODULE__, [Elixir.Kernel.SpecialForms.atom('trunk')]: true + },values); } export { defstruct @@ -105,12 +105,12 @@ defmodule ElixirScript.Test do """, env: make_custom_env) assert_js_matches """ - import { Patterns, Kernel, Atom, Enum, Integer, JS, List, Range, Tuple, Agent, Keyword, BitString, Base, String, Bitwise } from 'elixir'; - const __MODULE__ = Kernel.SpecialForms.atom('Animals'); - let something_else = Patterns.defmatch(Patterns.make_case([],function() { + import * as Elixir from 'elixir'; + const __MODULE__ = Elixir.Kernel.SpecialForms.atom('Animals'); + const something_else = Elixir.Patterns.defmatch(Elixir.Patterns.make_case([],function() { return 1 * 1; })); - let sandwich = Patterns.defmatch(Patterns.make_case([],function() { + const sandwich = Elixir.Patterns.defmatch(Elixir.Patterns.make_case([],function() { return null; })); export { diff --git a/test/lib/js_test.exs b/test/lib/js_test.exs index 09ef6379..3b1d3427 100644 --- a/test/lib/js_test.exs +++ b/test/lib/js_test.exs @@ -30,7 +30,7 @@ defmodule ElixirScript.Lib.JS.Test do end js_code = """ - A['b'] = Kernel.SpecialForms.list(1, 2, 3) + A['b'] = Elixir.Kernel.SpecialForms.list(1, 2, 3) """ assert_translation(ex_ast, js_code) diff --git a/test/lib/kernel_test.exs b/test/lib/kernel_test.exs index 7cdaccb2..73153b70 100644 --- a/test/lib/kernel_test.exs +++ b/test/lib/kernel_test.exs @@ -1,4 +1,4 @@ -defmodule ElixirScript.Lib.Kernel.Test do +defmodule ElixirScript.Lib.Elixir.Kernel.Test do use ShouldI import ElixirScript.TestHelper diff --git a/test/pattern_matching/match_test.exs b/test/pattern_matching/match_test.exs index 453623a0..96aded7e 100644 --- a/test/pattern_matching/match_test.exs +++ b/test/pattern_matching/match_test.exs @@ -45,7 +45,7 @@ defmodule ElixirScript.PatternMatching.Match.Test do end should "match prefix param" do - params = [{:<>, [context: Elixir, import: Kernel], ["Bearer ", {:token, [], Elixir}]}] + params = [{:<>, [context: Elixir, import: Elixir.Kernel], ["Bearer ", {:token, [], Elixir}]}] result = Match.build_match(params, __ENV__) expected_result = { [Match.starts_with("Bearer ")], diff --git a/test/test_helper.exs b/test/test_helper.exs index a9a3cf35..14417b8f 100644 --- a/test/test_helper.exs +++ b/test/test_helper.exs @@ -45,7 +45,7 @@ defmodule ElixirScript.TestHelper do def assert_translation(ex_ast, js_code) do - converted_code = ex_ast_to_js(ex_ast) |> Enum.join("\n\n") + converted_code = ex_ast_to_js(ex_ast) |> Elixir.Enum.join("\n\n") assert converted_code |> strip_spaces == strip_spaces(js_code), """ **Code Does Not Match ** diff --git a/test/translator/access_test.exs b/test/translator/access_test.exs index 3b0eb2aa..ced404ec 100644 --- a/test/translator/access_test.exs +++ b/test/translator/access_test.exs @@ -4,7 +4,7 @@ defmodule ElixirScript.Translator.Access.Test do should "translate access" do ex_ast = quote do: a[:b] - js_code = "a[Kernel.SpecialForms.atom('b')]" + js_code = "a[Elixir.Kernel.SpecialForms.atom('b')]" assert_translation(ex_ast, js_code) diff --git a/test/translator/assignment_test.exs b/test/translator/assignment_test.exs index bd10d8ce..b20d059c 100644 --- a/test/translator/assignment_test.exs +++ b/test/translator/assignment_test.exs @@ -4,12 +4,12 @@ defmodule ElixirScript.Translator.Assignment.Test do should "translate simple assignment" do ex_ast = quote do: a = 1 - js_code = "let [a] = Patterns.match(Patterns.variable(), 1);" + js_code = "let [a] = Elixir.Patterns.match(Elixir.Patterns.variable(), 1);" assert_translation(ex_ast, js_code) ex_ast = quote do: a = :atom - js_code = "let [a] = Patterns.match(Patterns.variable(), Kernel.SpecialForms.atom('atom'));" + js_code = "let [a] = Elixir.Patterns.match(Elixir.Patterns.variable(), Elixir.Kernel.SpecialForms.atom('atom'));" assert_translation(ex_ast, js_code) end @@ -19,16 +19,16 @@ defmodule ElixirScript.Translator.Assignment.Test do {a, b} = {1, 2} end js_code = """ - let [a, b] = Patterns.match(Kernel.SpecialForms.tuple(Patterns.variable(), Patterns.variable()), Kernel.SpecialForms.tuple(1, 2)); - let _ref = Kernel.SpecialForms.tuple(a, b); + let [a, b] = Elixir.Patterns.match(Elixir.Kernel.SpecialForms.tuple(Elixir.Patterns.variable(), Elixir.Patterns.variable()), Elixir.Kernel.SpecialForms.tuple(1, 2)); + let _ref = Elixir.Kernel.SpecialForms.tuple(a, b); """ assert_translation(ex_ast, js_code) ex_ast = quote do: {a, _, c} = {1, 2, 3} js_code = """ - let [a, undefined, c] = Patterns.match(Kernel.SpecialForms.tuple(Patterns.variable(), Patterns.wildcard(), Patterns.variable()), Kernel.SpecialForms.tuple(1, 2, 3)); - let _ref = Kernel.SpecialForms.tuple(a, undefined, c); + let [a, undefined, c] = Elixir.Patterns.match(Elixir.Kernel.SpecialForms.tuple(Elixir.Patterns.variable(), Elixir.Patterns.wildcard(), Elixir.Patterns.variable()), Elixir.Kernel.SpecialForms.tuple(1, 2, 3)); + let _ref = Elixir.Kernel.SpecialForms.tuple(a, undefined, c); """ assert_translation(ex_ast, js_code) @@ -36,8 +36,8 @@ defmodule ElixirScript.Translator.Assignment.Test do ex_ast = quote do: {^a, _, c} = {1, 2, 3} js_code = """ - let [,undefined,c] = Patterns.match(Kernel.SpecialForms.tuple(Patterns.bound(a),Patterns.wildcard(),Patterns.variable()),Kernel.SpecialForms.tuple(1,2,3)); - let _ref = Kernel.SpecialForms.tuple(undefined,undefined,c); + let [,undefined,c] = Elixir.Patterns.match(Elixir.Kernel.SpecialForms.tuple(Elixir.Patterns.bound(a),Elixir.Patterns.wildcard(),Elixir.Patterns.variable()),Elixir.Kernel.SpecialForms.tuple(1,2,3)); + let _ref = Elixir.Kernel.SpecialForms.tuple(undefined,undefined,c); """ assert_translation(ex_ast, js_code) @@ -46,7 +46,7 @@ defmodule ElixirScript.Translator.Assignment.Test do should "translate bound assignment" do ex_ast = quote do: ^a = 1 js_code = """ - let [] = Patterns.match(Patterns.bound(a),1); + let [] = Elixir.Patterns.match(Elixir.Patterns.bound(a),1); """ assert_translation(ex_ast, js_code) @@ -55,8 +55,8 @@ defmodule ElixirScript.Translator.Assignment.Test do should "translate list assignment" do ex_ast = quote do: [a, b] = [1, 2] js_code = """ - let [a, b] = Patterns.match(Kernel.SpecialForms.list(Patterns.variable(), Patterns.variable()), Kernel.SpecialForms.list(1, 2)); - let _ref = Kernel.SpecialForms.list(a, b); + let [a, b] = Elixir.Patterns.match(Elixir.Kernel.SpecialForms.list(Elixir.Patterns.variable(), Elixir.Patterns.variable()), Elixir.Kernel.SpecialForms.list(1, 2)); + let _ref = Elixir.Kernel.SpecialForms.list(a, b); """ assert_translation(ex_ast, js_code) @@ -65,8 +65,8 @@ defmodule ElixirScript.Translator.Assignment.Test do should "translate head/tail assignment" do ex_ast = quote do: [a | b] = [1, 2, 3, 4] js_code = """ - let [a,b] = Patterns.match(Patterns.headTail(),Kernel.SpecialForms.list(1,2,3,4)); - let _ref = Kernel.SpecialForms.list(a,b); + let [a,b] = Elixir.Patterns.match(Elixir.Patterns.headTail(),Elixir.Kernel.SpecialForms.list(1,2,3,4)); + let _ref = Elixir.Kernel.SpecialForms.list(a,b); """ assert_translation(ex_ast, js_code) diff --git a/test/translator/atom_test.exs b/test/translator/atom_test.exs index 5c439a6b..3c323f2d 100644 --- a/test/translator/atom_test.exs +++ b/test/translator/atom_test.exs @@ -4,6 +4,6 @@ defmodule ElixirScript.Translator.Atom.Test do should "translate atom" do ex_ast = quote do: :atom - assert_translation(ex_ast, "Kernel.SpecialForms.atom('atom')") + assert_translation(ex_ast, "Elixir.Kernel.SpecialForms.atom('atom')") end end \ No newline at end of file diff --git a/test/translator/bitstring_test.exs b/test/translator/bitstring_test.exs index b6461910..be7c3e24 100644 --- a/test/translator/bitstring_test.exs +++ b/test/translator/bitstring_test.exs @@ -4,39 +4,39 @@ defmodule ElixirScript.Translator.Bitstring.Test do should "translate bitstring" do ex_ast = quote do: <<1, 2, 3>> - assert_translation(ex_ast, "Kernel.SpecialForms.bitstring(BitString.integer(1), BitString.integer(2), BitString.integer(3))") + assert_translation(ex_ast, "Elixir.Kernel.SpecialForms.bitstring(BitString.integer(1), BitString.integer(2), BitString.integer(3))") ex_ast = quote do: <<1, "foo">> - assert_translation(ex_ast, "Kernel.SpecialForms.bitstring(BitString.integer(1), BitString.binary('foo'))") + assert_translation(ex_ast, "Elixir.Kernel.SpecialForms.bitstring(BitString.integer(1), BitString.binary('foo'))") ex_ast = quote do: <<1, "foo" :: binary>> - assert_translation(ex_ast, "Kernel.SpecialForms.bitstring(BitString.integer(1), BitString.binary('foo'))") + assert_translation(ex_ast, "Elixir.Kernel.SpecialForms.bitstring(BitString.integer(1), BitString.binary('foo'))") ex_ast = quote do: <<1, "foo" :: utf8, "bar" :: utf32>> - assert_translation(ex_ast, "Kernel.SpecialForms.bitstring(BitString.integer(1), BitString.utf8('foo'), BitString.utf32('bar'))") + assert_translation(ex_ast, "Elixir.Kernel.SpecialForms.bitstring(BitString.integer(1), BitString.utf8('foo'), BitString.utf32('bar'))") ex_ast = quote do: <<102 :: integer-native, rest :: binary>> - assert_translation(ex_ast, "Kernel.SpecialForms.bitstring(BitString.native(BitString.integer(102)), BitString.binary(rest))") + assert_translation(ex_ast, "Elixir.Kernel.SpecialForms.bitstring(BitString.native(BitString.integer(102)), BitString.binary(rest))") ex_ast = quote do: <<102 :: unsigned-big-integer, rest :: binary>> - assert_translation(ex_ast, "Kernel.SpecialForms.bitstring(BitString.integer(BitString.big(BitString.unsigned(102))), BitString.binary(rest))") + assert_translation(ex_ast, "Elixir.Kernel.SpecialForms.bitstring(BitString.integer(BitString.big(BitString.unsigned(102))), BitString.binary(rest))") ex_ast = quote do: <<102, _rest :: size(16)>> - assert_translation(ex_ast, "Kernel.SpecialForms.bitstring(BitString.integer(102), BitString.size(_rest, 16))") + assert_translation(ex_ast, "Elixir.Kernel.SpecialForms.bitstring(BitString.integer(102), BitString.size(_rest, 16))") ex_ast = quote do: <<102, _rest :: size(16)-unit(4)>> - assert_translation(ex_ast, "Kernel.SpecialForms.bitstring(BitString.integer(102), BitString.unit(BitString.size(_rest, 16), 4))") + assert_translation(ex_ast, "Elixir.Kernel.SpecialForms.bitstring(BitString.integer(102), BitString.unit(BitString.size(_rest, 16), 4))") ex_ast = quote do: <<102, _rest :: 16 * 4>> - assert_translation(ex_ast, "Kernel.SpecialForms.bitstring(BitString.integer(102), BitString.unit(BitString.size(_rest, 16), 4))") + assert_translation(ex_ast, "Elixir.Kernel.SpecialForms.bitstring(BitString.integer(102), BitString.unit(BitString.size(_rest, 16), 4))") ex_ast = quote do: <<102, _rest :: _ * 4>> - assert_translation(ex_ast, "Kernel.SpecialForms.bitstring(BitString.integer(102), BitString.unit(BitString.size(_rest, undefined), 4))") + assert_translation(ex_ast, "Elixir.Kernel.SpecialForms.bitstring(BitString.integer(102), BitString.unit(BitString.size(_rest, undefined), 4))") ex_ast = quote do: <<102, _rest :: 16>> - assert_translation(ex_ast, "Kernel.SpecialForms.bitstring(BitString.integer(102), BitString.size(_rest, 16))") + assert_translation(ex_ast, "Elixir.Kernel.SpecialForms.bitstring(BitString.integer(102), BitString.size(_rest, 16))") ex_ast = quote do: << 1, <<2>> >> - assert_translation(ex_ast, "Kernel.SpecialForms.bitstring(BitString.integer(1), Kernel.SpecialForms.bitstring(BitString.integer(2)))") + assert_translation(ex_ast, "Elixir.Kernel.SpecialForms.bitstring(BitString.integer(1), Elixir.Kernel.SpecialForms.bitstring(BitString.integer(2)))") end end \ No newline at end of file diff --git a/test/translator/bug_test.exs b/test/translator/bug_test.exs index 58442828..07b40f4a 100644 --- a/test/translator/bug_test.exs +++ b/test/translator/bug_test.exs @@ -12,8 +12,8 @@ defmodule ElixirScript.Translator.Bug.Test do end js_code = """ - React.createElement(React.Text,Kernel.SpecialForms.map({ - style: JS.get_property_or_call_function(styles,'welcome') + React.createElement(React.Text,Elixir.Kernel.SpecialForms.map({ + style: Elixir.JS.call_property(styles,'welcome') }),'Welcome to React Native!') """ @@ -31,9 +31,9 @@ defmodule ElixirScript.Translator.Bug.Test do js_code = """ import { default as JQuery } from 'jquery'; - const __MODULE__ = Kernel.SpecialForms.atom('Todo'); + const __MODULE__ = Elixir.Kernel.SpecialForms.atom('Todo'); - JQuery(JS.get_property_or_call_function(e, 'target')); + JQuery(Elixir.JS.call_property(e, 'target')); export {}; """ @@ -46,7 +46,7 @@ defmodule ElixirScript.Translator.Bug.Test do end js_code = """ - const graphic_store = JS.get_property_or_call_function(App.Stores.GraphicStore, 'create_store'); + const graphic_store = Elixir.JS.call_property(App.Stores.GraphicStore, 'create_store'); """ @@ -55,11 +55,11 @@ defmodule ElixirScript.Translator.Bug.Test do should "replace !" do ex_ast = quote do - Enum.fetch!(data, i) + Elixir.Enum.fetch!(data, i) end js_code = """ - Enum.fetch__emark__(data, i) + Elixir.Enum.fetch__emark__(data, i) """ assert_translation(ex_ast, js_code) @@ -71,7 +71,7 @@ defmodule ElixirScript.Translator.Bug.Test do end js_code = """ - JS.get_property_or_call_function(this, 'getRawCanvas').getContext('2d') + Elixir.JS.call_property(this, 'getRawCanvas').getContext('2d') """ assert_translation(ex_ast, js_code) @@ -102,17 +102,17 @@ defmodule ElixirScript.Translator.Bug.Test do js_code = """ - let getDispatcher = Patterns.defmatch(Patterns.make_case([],function() { - return DeLorean.Flux.createDispatcher(Kernel.SpecialForms.map({ - [Kernel.SpecialForms.atom('startPainting')]: Patterns.defmatch(Patterns.make_case([],function() { + const getDispatcher = Elixir.Patterns.defmatch(Elixir.Patterns.make_case([],function() { + return DeLorean.Flux.createDispatcher(Elixir.Kernel.SpecialForms.map({ + [Elixir.Kernel.SpecialForms.atom('startPainting')]: Elixir.Patterns.defmatch(Elixir.Patterns.make_case([],function() { return this.dispatch('startPainting'); - })), [Kernel.SpecialForms.atom('stopPainting')]: Patterns.defmatch(Patterns.make_case([],function() { + })), [Elixir.Kernel.SpecialForms.atom('stopPainting')]: Elixir.Patterns.defmatch(Elixir.Patterns.make_case([],function() { return this.dispatch('stopPainting'); - })), [Kernel.SpecialForms.atom('addPoint')]: Patterns.defmatch(Patterns.make_case([Patterns.variable()],function(data) { + })), [Elixir.Kernel.SpecialForms.atom('addPoint')]: Elixir.Patterns.defmatch(Elixir.Patterns.make_case([Elixir.Patterns.variable()],function(data) { return this.dispatch('addPoint',data); - })), [Kernel.SpecialForms.atom('getStores')]: Patterns.defmatch(Patterns.make_case([],function() { - return Kernel.SpecialForms.map({ - [Kernel.SpecialForms.atom('graphic')]: GraphicStore + })), [Elixir.Kernel.SpecialForms.atom('getStores')]: Elixir.Patterns.defmatch(Elixir.Patterns.make_case([],function() { + return Elixir.Kernel.SpecialForms.map({ + [Elixir.Kernel.SpecialForms.atom('graphic')]: GraphicStore }); })) })); diff --git a/test/translator/capture_test.exs b/test/translator/capture_test.exs index a21d3f07..add658ca 100644 --- a/test/translator/capture_test.exs +++ b/test/translator/capture_test.exs @@ -4,12 +4,12 @@ defmodule ElixirScript.Translator.Capture.Test do should "translate capture operator with Module, function, and arity" do ex_ast = quote do - fun = &Kernel.is_atom/1 + fun = &Elixir.Kernel.is_atom/1 end js_code = """ - let [fun] = Patterns.match(Patterns.variable(),Patterns.defmatch(Patterns.make_case([Patterns.variable()],function(__1) { - return Kernel.is_atom(__1); + let [fun] = Elixir.Patterns.match(Elixir.Patterns.variable(),Elixir.Patterns.defmatch(Elixir.Patterns.make_case([Elixir.Patterns.variable()],function(__1) { + return Elixir.Kernel.is_atom(__1); }))); """ @@ -24,8 +24,8 @@ defmodule ElixirScript.Translator.Capture.Test do end js_code = """ - let [fun] = Patterns.match(Patterns.variable(),Patterns.defmatch(Patterns.make_case([Patterns.variable()],function(__1) { - return Kernel.is_atom(__1); + let [fun] = Elixir.Patterns.match(Elixir.Patterns.variable(),Elixir.Patterns.defmatch(Elixir.Patterns.make_case([Elixir.Patterns.variable()],function(__1) { + return Elixir.Kernel.is_atom(__1); }))); """ @@ -41,7 +41,7 @@ defmodule ElixirScript.Translator.Capture.Test do end js_code = """ - let [fun] = Patterns.match(Patterns.variable(),Patterns.defmatch(Patterns.make_case([Patterns.variable()],function(__1) { + let [fun] = Elixir.Patterns.match(Elixir.Patterns.variable(),Elixir.Patterns.defmatch(Elixir.Patterns.make_case([Elixir.Patterns.variable()],function(__1) { return local_function(__1); }))); """ @@ -57,7 +57,7 @@ defmodule ElixirScript.Translator.Capture.Test do end js_code = """ - let [fun] = Patterns.match(Patterns.variable(),Patterns.defmatch(Patterns.make_case([Patterns.variable()],function(__1) { + let [fun] = Elixir.Patterns.match(Elixir.Patterns.variable(),Elixir.Patterns.defmatch(Elixir.Patterns.make_case([Elixir.Patterns.variable()],function(__1) { return __1 * 2; }))); """ @@ -73,8 +73,8 @@ defmodule ElixirScript.Translator.Capture.Test do end js_code = """ - let [fun] = Patterns.match(Patterns.variable(),Patterns.defmatch(Patterns.make_case([Patterns.variable(), Patterns.variable()],function(__1,__2) { - return Kernel.SpecialForms.tuple(__1,__2); + let [fun] = Elixir.Patterns.match(Elixir.Patterns.variable(),Elixir.Patterns.defmatch(Elixir.Patterns.make_case([Elixir.Patterns.variable(), Elixir.Patterns.variable()],function(__1,__2) { + return Elixir.Kernel.SpecialForms.tuple(__1,__2); }))); """ @@ -85,8 +85,8 @@ defmodule ElixirScript.Translator.Capture.Test do end js_code = """ - let [fun] = Patterns.match(Patterns.variable(),Patterns.defmatch(Patterns.make_case([Patterns.variable(), Patterns.variable(), Patterns.variable()],function(__1,__2,__3) { - return Kernel.SpecialForms.tuple(__1,__2,__3); + let [fun] = Elixir.Patterns.match(Elixir.Patterns.variable(),Elixir.Patterns.defmatch(Elixir.Patterns.make_case([Elixir.Patterns.variable(), Elixir.Patterns.variable(), Elixir.Patterns.variable()],function(__1,__2,__3) { + return Elixir.Kernel.SpecialForms.tuple(__1,__2,__3); }))); """ @@ -98,11 +98,11 @@ defmodule ElixirScript.Translator.Capture.Test do should "translate capture operator with anonymous functions as parameters" do ex_ast = quote do - Enum.map(items, &process(&1)) + Elixir.Enum.map(items, &process(&1)) end js_code = """ - Enum.map(items,Patterns.defmatch(Patterns.make_case([Patterns.variable()],function(__1) { + Elixir.Enum.map(items,Elixir.Patterns.defmatch(Elixir.Patterns.make_case([Elixir.Patterns.variable()],function(__1) { return process(__1); }))) """ @@ -115,7 +115,7 @@ defmodule ElixirScript.Translator.Capture.Test do end js_code = """ - elem.keypress(Patterns.defmatch(Patterns.make_case([Patterns.variable()],function(__1) { + elem.keypress(Elixir.Patterns.defmatch(Elixir.Patterns.make_case([Elixir.Patterns.variable()],function(__1) { return process_event(__1); }))) """ diff --git a/test/translator/case_test.exs b/test/translator/case_test.exs index 55cb93ff..e0635203 100644 --- a/test/translator/case_test.exs +++ b/test/translator/case_test.exs @@ -12,9 +12,9 @@ defmodule ElixirScript.Translator.Case.Test do end js_code = """ - Patterns.defmatch(Patterns.make_case([Kernel.SpecialForms.atom('ok')],function() { + Elixir.Patterns.defmatch(Elixir.Patterns.make_case([Elixir.Kernel.SpecialForms.atom('ok')],function() { return value; - }),Patterns.make_case([Kernel.SpecialForms.atom('error')],function() { + }),Elixir.Patterns.make_case([Elixir.Kernel.SpecialForms.atom('error')],function() { return null; })).call(this,data) """ @@ -29,10 +29,10 @@ defmodule ElixirScript.Translator.Case.Test do end js_code = """ - Patterns.defmatch(Patterns.make_case([false],function() { - let [value0] = Patterns.match(Patterns.variable(),13); + Elixir.Patterns.defmatch(Elixir.Patterns.make_case([false],function() { + let [value0] = Elixir.Patterns.match(Elixir.Patterns.variable(),13); return value0; - }),Patterns.make_case([true],function() { + }),Elixir.Patterns.make_case([true],function() { return true; })).call(this,data) """ @@ -49,10 +49,10 @@ defmodule ElixirScript.Translator.Case.Test do end js_code = """ - Patterns.defmatch(Patterns.make_case([false],function() { - let [value0] = Patterns.match(Patterns.variable(),13); + Elixir.Patterns.defmatch(Elixir.Patterns.make_case([false],function() { + let [value0] = Elixir.Patterns.match(Elixir.Patterns.variable(),13); return value0; - }),Patterns.make_case([Patterns.wildcard()],function() { + }),Elixir.Patterns.make_case([Elixir.Patterns.wildcard()],function() { return true; })).call(this,data) """ @@ -71,12 +71,12 @@ defmodule ElixirScript.Translator.Case.Test do end js_code = """ - Patterns.defmatch(Patterns.make_case([Patterns.variable()],function(number) { - let [value0] = Patterns.match(Patterns.variable(),13); + Elixir.Patterns.defmatch(Elixir.Patterns.make_case([Elixir.Patterns.variable()],function(number) { + let [value0] = Elixir.Patterns.match(Elixir.Patterns.variable(),13); return value0; },function(number) { - return Kernel.__in__(number,Kernel.SpecialForms.list(1,2,3,4)); - }),Patterns.make_case([Patterns.wildcard()],function() { + return Elixir.Kernel.__in__(number,Elixir.Kernel.SpecialForms.list(1,2,3,4)); + }),Elixir.Patterns.make_case([Elixir.Patterns.wildcard()],function() { return true; })).call(this,data) """ @@ -96,10 +96,10 @@ defmodule ElixirScript.Translator.Case.Test do end js_code = """ - Patterns.defmatch(Patterns.make_case([Kernel.SpecialForms.atom('ok')],function() { + Elixir.Patterns.defmatch(Elixir.Patterns.make_case([Elixir.Kernel.SpecialForms.atom('ok')],function() { console.info('info'); return Todo.add(data); - }),Patterns.make_case([Kernel.SpecialForms.atom('error')],function() { + }),Elixir.Patterns.make_case([Elixir.Kernel.SpecialForms.atom('error')],function() { return null; })).call(this,data) """ @@ -118,9 +118,9 @@ defmodule ElixirScript.Translator.Case.Test do end js_code = """ - Patterns.defmatch(Patterns.make_case([Kernel.SpecialForms.tuple(Patterns.variable(),Patterns.variable())],function(one,two) { + Elixir.Patterns.defmatch(Elixir.Patterns.make_case([Elixir.Kernel.SpecialForms.tuple(Elixir.Patterns.variable(),Elixir.Patterns.variable())],function(one,two) { return console.info(one); - }),Patterns.make_case([Kernel.SpecialForms.atom('error')],function() { + }),Elixir.Patterns.make_case([Elixir.Kernel.SpecialForms.atom('error')],function() { return null; })).call(this,data) """ @@ -139,9 +139,9 @@ defmodule ElixirScript.Translator.Case.Test do end js_code = """ - Patterns.defmatch(Patterns.make_case([Kernel.SpecialForms.tuple(Kernel.SpecialForms.tuple(Patterns.variable(),Patterns.variable()),Patterns.variable())],function(one,two,three) { + Elixir.Patterns.defmatch(Elixir.Patterns.make_case([Elixir.Kernel.SpecialForms.tuple(Elixir.Kernel.SpecialForms.tuple(Elixir.Patterns.variable(),Elixir.Patterns.variable()),Elixir.Patterns.variable())],function(one,two,three) { return console.info(one); - }),Patterns.make_case([Kernel.SpecialForms.atom('error')],function() { + }),Elixir.Patterns.make_case([Elixir.Kernel.SpecialForms.atom('error')],function() { return null; })).call(this,data) """ @@ -158,9 +158,9 @@ defmodule ElixirScript.Translator.Case.Test do end js_code = """ - Patterns.defmatch(Patterns.make_case([Kernel.SpecialForms.tuple(Patterns.variable(),Kernel.SpecialForms.tuple(Patterns.variable(),Patterns.variable()))],function(one,two,three) { + Elixir.Patterns.defmatch(Elixir.Patterns.make_case([Elixir.Kernel.SpecialForms.tuple(Elixir.Patterns.variable(),Elixir.Kernel.SpecialForms.tuple(Elixir.Patterns.variable(),Elixir.Patterns.variable()))],function(one,two,three) { return console.info(one); - }),Patterns.make_case([Kernel.SpecialForms.atom('error')],function() { + }),Elixir.Patterns.make_case([Elixir.Kernel.SpecialForms.atom('error')],function() { return null; })).call(this,data) @@ -179,13 +179,13 @@ defmodule ElixirScript.Translator.Case.Test do end js_code = """ - Patterns.defmatch(Patterns.make_case([{ - [Kernel.SpecialForms.atom('__struct__')]: Kernel.SpecialForms.atom('AStruct'), [Kernel.SpecialForms.atom('key')]: { - [Kernel.SpecialForms.atom('__struct__')]: Kernel.SpecialForms.atom('BStruct'), [Kernel.SpecialForms.atom('key2')]: Patterns.variable() + Elixir.Patterns.defmatch(Elixir.Patterns.make_case([{ + [Elixir.Kernel.SpecialForms.atom('__struct__')]: Elixir.Kernel.SpecialForms.atom('AStruct'), [Elixir.Kernel.SpecialForms.atom('key')]: { + [Elixir.Kernel.SpecialForms.atom('__struct__')]: Elixir.Kernel.SpecialForms.atom('BStruct'), [Elixir.Kernel.SpecialForms.atom('key2')]: Elixir.Patterns.variable() } }],function(value) { return console.info(value); - }),Patterns.make_case([Kernel.SpecialForms.atom('error')],function() { + }),Elixir.Patterns.make_case([Elixir.Kernel.SpecialForms.atom('error')],function() { return null; })).call(this,data) """ @@ -203,15 +203,15 @@ defmodule ElixirScript.Translator.Case.Test do end js_code = """ - Patterns.defmatch(Patterns.make_case([{ - [Kernel.SpecialForms.atom('__struct__')]: Kernel.SpecialForms.atom('AStruct'), [Kernel.SpecialForms.atom('key')]: { - [Kernel.SpecialForms.atom('__struct__')]: Kernel.SpecialForms.atom('BStruct'), [Kernel.SpecialForms.atom('key2')]: Patterns.variable(), [Kernel.SpecialForms.atom('key3')]: { - [Kernel.SpecialForms.atom('__struct__')]: Kernel.SpecialForms.atom('CStruct'), [Kernel.SpecialForms.atom('key4')]: Patterns.variable() + Elixir.Patterns.defmatch(Elixir.Patterns.make_case([{ + [Elixir.Kernel.SpecialForms.atom('__struct__')]: Elixir.Kernel.SpecialForms.atom('AStruct'), [Elixir.Kernel.SpecialForms.atom('key')]: { + [Elixir.Kernel.SpecialForms.atom('__struct__')]: Elixir.Kernel.SpecialForms.atom('BStruct'), [Elixir.Kernel.SpecialForms.atom('key2')]: Elixir.Patterns.variable(), [Elixir.Kernel.SpecialForms.atom('key3')]: { + [Elixir.Kernel.SpecialForms.atom('__struct__')]: Elixir.Kernel.SpecialForms.atom('CStruct'), [Elixir.Kernel.SpecialForms.atom('key4')]: Elixir.Patterns.variable() } } }],function(value,value2) { return console.info(value); - }),Patterns.make_case([Kernel.SpecialForms.atom('error')],function() { + }),Elixir.Patterns.make_case([Elixir.Kernel.SpecialForms.atom('error')],function() { return null; })).call(this,data) """ diff --git a/test/translator/cond_test.exs b/test/translator/cond_test.exs index b95791f1..5fb0815a 100644 --- a/test/translator/cond_test.exs +++ b/test/translator/cond_test.exs @@ -15,11 +15,11 @@ defmodule ElixirScript.Translator.Cond.Test do end js_code = """ - Kernel.SpecialForms.cond(Kernel.SpecialForms.list(1 + 1 == 1,function() { + Elixir.Kernel.SpecialForms.cond(Elixir.Kernel.SpecialForms.list(1 + 1 == 1,function() { return 'This will never match'; - }),Kernel.SpecialForms.list(2 * 2 != 4,function() { + }),Elixir.Kernel.SpecialForms.list(2 * 2 != 4,function() { return 'Nor this'; - }),Kernel.SpecialForms.list(true,function() { + }),Elixir.Kernel.SpecialForms.list(true,function() { return 'This will'; })) """ @@ -41,14 +41,14 @@ defmodule ElixirScript.Translator.Cond.Test do end js_code = """ - Kernel.SpecialForms.cond(Kernel.SpecialForms.list(1 + 1 == 1,function() { - let [a] = Patterns.match(Patterns.variable(),1); + Elixir.Kernel.SpecialForms.cond(Elixir.Kernel.SpecialForms.list(1 + 1 == 1,function() { + let [a] = Elixir.Patterns.match(Elixir.Patterns.variable(),1); return 'This will never match'; - }),Kernel.SpecialForms.list(2 * 2 != 4,function() { - let [a] = Patterns.match(Patterns.variable(),2); + }),Elixir.Kernel.SpecialForms.list(2 * 2 != 4,function() { + let [a] = Elixir.Patterns.match(Elixir.Patterns.variable(),2); return 'Nor this'; - }),Kernel.SpecialForms.list(true,function() { - let [a] = Patterns.match(Patterns.variable(),3); + }),Elixir.Kernel.SpecialForms.list(true,function() { + let [a] = Elixir.Patterns.match(Elixir.Patterns.variable(),3); return 'This will'; })) """ diff --git a/test/translator/defmodule_test.exs b/test/translator/defmodule_test.exs index 27b8a2bc..c1c08aa1 100644 --- a/test/translator/defmodule_test.exs +++ b/test/translator/defmodule_test.exs @@ -9,7 +9,7 @@ defmodule ElixirScript.Translator.Defmodule.Test do end js_code = """ - const __MODULE__ = Kernel.SpecialForms.atom('Elephant'); + const __MODULE__ = Elixir.Kernel.SpecialForms.atom('Elephant'); export {}; """ @@ -31,11 +31,11 @@ defmodule ElixirScript.Translator.Defmodule.Test do end js_code = """ - const __MODULE__ = Kernel.SpecialForms.atom('Elephant'); - let something_else = Patterns.defmatch(Patterns.make_case([],function() { + const __MODULE__ = Elixir.Kernel.SpecialForms.atom('Elephant'); + const something_else = Elixir.Patterns.defmatch(Elixir.Patterns.make_case([],function() { return null; })); - let something = Patterns.defmatch(Patterns.make_case([],function() { + const something = Elixir.Patterns.defmatch(Elixir.Patterns.make_case([],function() { return ul; })); const ul = JQuery('#todo-list'); @@ -60,11 +60,11 @@ defmodule ElixirScript.Translator.Defmodule.Test do js_code = """ import * as Crane from 'icabod/crane'; - const __MODULE__ = Kernel.SpecialForms.atom('Elephant'); - let something_else = Patterns.defmatch(Patterns.make_case([],function() { + const __MODULE__ = Elixir.Kernel.SpecialForms.atom('Elephant'); + const something_else = Elixir.Patterns.defmatch(Elixir.Patterns.make_case([],function() { return null; })); - let something = Patterns.defmatch(Patterns.make_case([],function() { + const something = Elixir.Patterns.defmatch(Elixir.Patterns.make_case([],function() { return null; })); export { @@ -95,23 +95,23 @@ defmodule ElixirScript.Translator.Defmodule.Test do end js_code = """ - const __MODULE__ = Kernel.SpecialForms.atom('Elephant'); - function defstruct(trunk = true) { - return Kernel.SpecialForms.map({ - [Kernel.SpecialForms.atom('__struct__')]: __MODULE__, [Kernel.SpecialForms.atom('trunk')]: trunk - }); + const __MODULE__ = Elixir.Kernel.SpecialForms.atom('Elephant'); + function defstruct(values = {}) { + return Kernel.defstruct({ + [Elixir.Kernel.SpecialForms.atom('__struct__')]: __MODULE__, [Elixir.Kernel.SpecialForms.atom('trunk')]: true + },values); } export { defstruct }; import * as Elephant from 'animals/elephant'; - const __MODULE__ = Kernel.SpecialForms.atom('Animals'); - let something_else = Patterns.defmatch(Patterns.make_case([],function() { + const __MODULE__ = Elixir.Kernel.SpecialForms.atom('Animals'); + const something_else = Elixir.Patterns.defmatch(Elixir.Patterns.make_case([],function() { return null; })); - let something = Patterns.defmatch(Patterns.make_case([],function() { - return Elephant.defstruct(); + const something = Elixir.Patterns.defmatch(Elixir.Patterns.make_case([],function() { + return Elephant.defstruct(Elixir.Kernel.SpecialForms.map({})); })); export { something @@ -147,34 +147,34 @@ defmodule ElixirScript.Translator.Defmodule.Test do end js_code = """ - const __MODULE__ = Kernel.SpecialForms.atom('Bear'); - function defstruct(trunk = true) { - return Kernel.SpecialForms.map({ - [Kernel.SpecialForms.atom('__struct__')]: __MODULE__, [Kernel.SpecialForms.atom('trunk')]: trunk - }); + const __MODULE__ = Elixir.Kernel.SpecialForms.atom('Bear'); + function defstruct(values = {}) { + return Kernel.defstruct({ + [Elixir.Kernel.SpecialForms.atom('__struct__')]: __MODULE__, [Elixir.Kernel.SpecialForms.atom('trunk')]: true + },values); } export { defstruct }; import * as Bear from 'elephant/bear'; - const __MODULE__ = Kernel.SpecialForms.atom('Elephant'); - function defstruct(trunk = true) { - return Kernel.SpecialForms.map({ - [Kernel.SpecialForms.atom('__struct__')]: __MODULE__, [Kernel.SpecialForms.atom('trunk')]: trunk - }); + const __MODULE__ = Elixir.Kernel.SpecialForms.atom('Elephant'); + function defstruct(values = {}) { + return Kernel.defstruct({ + [Elixir.Kernel.SpecialForms.atom('__struct__')]: __MODULE__, [Elixir.Kernel.SpecialForms.atom('trunk')]: true + },values); } export { defstruct }; import * as Elephant from 'animals/elephant'; - const __MODULE__ = Kernel.SpecialForms.atom('Animals'); - let something_else = Patterns.defmatch(Patterns.make_case([],function() { + const __MODULE__ = Elixir.Kernel.SpecialForms.atom('Animals'); + const something_else = Elixir.Patterns.defmatch(Elixir.Patterns.make_case([],function() { return null; })); - let something = Patterns.defmatch(Patterns.make_case([],function() { - return Elephant.defstruct(); + const something = Elixir.Patterns.defmatch(Elixir.Patterns.make_case([],function() { + return Elephant.defstruct(Elixir.Kernel.SpecialForms.map({})); })); export { something @@ -197,12 +197,12 @@ defmodule ElixirScript.Translator.Defmodule.Test do js_code = """ import * as Tigers from 'lions/tigers'; - const __MODULE__ = Kernel.SpecialForms.atom('Animals'); - JS.get_property_or_call_function(Tigers,'oh_my'); + const __MODULE__ = Elixir.Kernel.SpecialForms.atom('Animals'); + Elixir.JS.call_property(Tigers,'oh_my'); export {}; - const __MODULE__ = Kernel.SpecialForms.atom('Tigers'); - JS.get_property_or_call_function(Lions.Tigers.Bears,'oh_my'); + const __MODULE__ = Elixir.Kernel.SpecialForms.atom('Tigers'); + Elixir.JS.call_property(Lions.Tigers.Bears,'oh_my'); export {}; """ @@ -226,18 +226,18 @@ defmodule ElixirScript.Translator.Defmodule.Test do end js_code = """ - const __MODULE__ = Kernel.SpecialForms.atom('Tigers'); - let oh_my = Patterns.defmatch(Patterns.make_case([],function() { + const __MODULE__ = Elixir.Kernel.SpecialForms.atom('Tigers'); + const oh_my = Elixir.Patterns.defmatch(Elixir.Patterns.make_case([],function() { return null; })); - JS.get_property_or_call_function(Lions.Tigers.Bears,'oh_my'); + Elixir.JS.call_property(Lions.Tigers.Bears,'oh_my'); export { oh_my }; import * as Tigers from 'lions/tigers'; - const __MODULE__ = Kernel.SpecialForms.atom('Animals'); - JS.get_property_or_call_function(Tigers,'oh_my'); + const __MODULE__ = Elixir.Kernel.SpecialForms.atom('Animals'); + Elixir.JS.call_property(Tigers,'oh_my'); export {}; """ @@ -263,15 +263,15 @@ defmodule ElixirScript.Translator.Defmodule.Test do js_code = """ import { oh_my } from 'lions/tigers'; - const __MODULE__ = Kernel.SpecialForms.atom('Animals'); + const __MODULE__ = Elixir.Kernel.SpecialForms.atom('Animals'); oh_my(); export {}; - const __MODULE__ = Kernel.SpecialForms.atom('Tigers'); - let oh_my2 = Patterns.defmatch(Patterns.make_case([],function() { + const __MODULE__ = Elixir.Kernel.SpecialForms.atom('Tigers'); + const oh_my2 = Elixir.Patterns.defmatch(Elixir.Patterns.make_case([],function() { return null; })); - let oh_my = Patterns.defmatch(Patterns.make_case([],function() { + const oh_my = Elixir.Patterns.defmatch(Elixir.Patterns.make_case([],function() { return null; })); export { @@ -300,11 +300,11 @@ defmodule ElixirScript.Translator.Defmodule.Test do end js_code = """ - const __MODULE__ = Kernel.SpecialForms.atom('Tigers'); - let oh_my2 = Patterns.defmatch(Patterns.make_case([],function() { + const __MODULE__ = Elixir.Kernel.SpecialForms.atom('Tigers'); + const oh_my2 = Elixir.Patterns.defmatch(Elixir.Patterns.make_case([],function() { return null; })); - let oh_my = Patterns.defmatch(Patterns.make_case([],function() { + const oh_my = Elixir.Patterns.defmatch(Elixir.Patterns.make_case([],function() { return null; })); export { @@ -312,7 +312,7 @@ defmodule ElixirScript.Translator.Defmodule.Test do }; import { oh_my2 } from 'lions/tigers'; - const __MODULE__ = Kernel.SpecialForms.atom('Animals'); + const __MODULE__ = Elixir.Kernel.SpecialForms.atom('Animals'); oh_my2(); export {}; """ diff --git a/test/translator/for_test.exs b/test/translator/for_test.exs index 1f5c6d88..34f4551f 100644 --- a/test/translator/for_test.exs +++ b/test/translator/for_test.exs @@ -8,11 +8,11 @@ defmodule ElixirScript.Translator.For.Test do end js_code = """ - Kernel.SpecialForms._for(Kernel.SpecialForms.list(Kernel.SpecialForms.list(Patterns.variable(),Kernel.SpecialForms.list(1,2,3,4))),function(n) { + Elixir.Kernel.SpecialForms._for(Elixir.Kernel.SpecialForms.list(Elixir.Kernel.SpecialForms.list(Elixir.Patterns.variable(),Elixir.Kernel.SpecialForms.list(1,2,3,4))),function(n) { return n * 2; },function() { return true; - },Kernel.SpecialForms.list()) + },Elixir.Kernel.SpecialForms.list()) """ assert_translation(ex_ast, js_code) @@ -24,11 +24,11 @@ defmodule ElixirScript.Translator.For.Test do end js_code = """ - Kernel.SpecialForms._for(Kernel.SpecialForms.list(Kernel.SpecialForms.list(Patterns.variable(),Kernel.SpecialForms.list(1,2,3,4))),function(n) { + Elixir.Kernel.SpecialForms._for(Elixir.Kernel.SpecialForms.list(Elixir.Kernel.SpecialForms.list(Elixir.Patterns.variable(),Elixir.Kernel.SpecialForms.list(1,2,3,4))),function(n) { return n * 2; },function() { return true; - },Kernel.SpecialForms.list()) + },Elixir.Kernel.SpecialForms.list()) """ assert_translation(ex_ast, js_code) @@ -40,11 +40,11 @@ defmodule ElixirScript.Translator.For.Test do end js_code = """ - Kernel.SpecialForms._for(Kernel.SpecialForms.list(Kernel.SpecialForms.list(Patterns.variable(),'Opera')),function(n) { + Elixir.Kernel.SpecialForms._for(Elixir.Kernel.SpecialForms.list(Elixir.Kernel.SpecialForms.list(Elixir.Patterns.variable(),'Opera')),function(n) { return n; },function() { return true; - },Kernel.SpecialForms.list()) + },Elixir.Kernel.SpecialForms.list()) """ assert_translation(ex_ast, js_code) @@ -56,13 +56,13 @@ defmodule ElixirScript.Translator.For.Test do end js_code = """ - Kernel.SpecialForms._for(Kernel.SpecialForms.list( - Kernel.SpecialForms.list(Patterns.variable(), Kernel.SpecialForms.list(1,2)), - Kernel.SpecialForms.list(Patterns.variable(), Kernel.SpecialForms.list(2,3))), function(x,y) { + Elixir.Kernel.SpecialForms._for(Elixir.Kernel.SpecialForms.list( + Elixir.Kernel.SpecialForms.list(Elixir.Patterns.variable(), Elixir.Kernel.SpecialForms.list(1,2)), + Elixir.Kernel.SpecialForms.list(Elixir.Patterns.variable(), Elixir.Kernel.SpecialForms.list(2,3))), function(x,y) { return x * y; },function() { return true; - },Kernel.SpecialForms.list()) + },Elixir.Kernel.SpecialForms.list()) """ assert_translation(ex_ast, js_code) @@ -76,11 +76,11 @@ defmodule ElixirScript.Translator.For.Test do end js_code = """ - let [r] = Patterns.match(Patterns.variable(),Kernel.SpecialForms._for(Kernel.SpecialForms.list(Kernel.SpecialForms.list(Patterns.variable(),Kernel.SpecialForms.list(1,2)),Kernel.SpecialForms.list(Patterns.variable(),Kernel.SpecialForms.list(2,3))),function(x,y) { + let [r] = Elixir.Patterns.match(Elixir.Patterns.variable(),Elixir.Kernel.SpecialForms._for(Elixir.Kernel.SpecialForms.list(Elixir.Kernel.SpecialForms.list(Elixir.Patterns.variable(),Elixir.Kernel.SpecialForms.list(1,2)),Elixir.Kernel.SpecialForms.list(Elixir.Patterns.variable(),Elixir.Kernel.SpecialForms.list(2,3))),function(x,y) { return x * y; },function() { return true; - },Kernel.SpecialForms.list())); + },Elixir.Kernel.SpecialForms.list())); """ assert_translation(ex_ast, js_code) @@ -92,11 +92,11 @@ defmodule ElixirScript.Translator.For.Test do end js_code = """ - Kernel.SpecialForms._for(Kernel.SpecialForms.list(Kernel.SpecialForms.list(Patterns.variable(),Kernel.SpecialForms.list(1,2,3,4,5,6))),function(n) { + Elixir.Kernel.SpecialForms._for(Elixir.Kernel.SpecialForms.list(Elixir.Kernel.SpecialForms.list(Elixir.Patterns.variable(),Elixir.Kernel.SpecialForms.list(1,2,3,4,5,6))),function(n) { return n; },function(n) { return n % 2 == 0; - },Kernel.SpecialForms.list()) + },Elixir.Kernel.SpecialForms.list()) """ assert_translation(ex_ast, js_code) @@ -110,17 +110,17 @@ defmodule ElixirScript.Translator.For.Test do end js_code = """ - Kernel.SpecialForms._for(Kernel.SpecialForms.list( - Kernel.SpecialForms.list( - Kernel.SpecialForms.tuple(Kernel.SpecialForms.atom('user'),Patterns.variable()), - Kernel.SpecialForms.list( - Kernel.SpecialForms.tuple(Kernel.SpecialForms.atom('user'),'john'), - Kernel.SpecialForms.tuple(Kernel.SpecialForms.atom('admin'),'john'), - Kernel.SpecialForms.tuple(Kernel.SpecialForms.atom('user'),'meg')))),function(name) { - return String.upcase(name); + Elixir.Kernel.SpecialForms._for(Elixir.Kernel.SpecialForms.list( + Elixir.Kernel.SpecialForms.list( + Elixir.Kernel.SpecialForms.tuple(Elixir.Kernel.SpecialForms.atom('user'),Elixir.Patterns.variable()), + Elixir.Kernel.SpecialForms.list( + Elixir.Kernel.SpecialForms.tuple(Elixir.Kernel.SpecialForms.atom('user'),'john'), + Elixir.Kernel.SpecialForms.tuple(Elixir.Kernel.SpecialForms.atom('admin'),'john'), + Elixir.Kernel.SpecialForms.tuple(Elixir.Kernel.SpecialForms.atom('user'),'meg')))),function(name) { + return Elixir.String.upcase(name); },function() { return true; - },Kernel.SpecialForms.list() + },Elixir.Kernel.SpecialForms.list() ) """ diff --git a/test/translator/function_test.exs b/test/translator/function_test.exs index ebbf42b7..bb551d53 100644 --- a/test/translator/function_test.exs +++ b/test/translator/function_test.exs @@ -8,7 +8,7 @@ defmodule ElixirScript.Translator.Function.Test do end js_code = """ - fun(Kernel.SpecialForms.atom('atom')) + fun(Elixir.Kernel.SpecialForms.atom('atom')) """ assert_translation(ex_ast, js_code) @@ -24,7 +24,7 @@ defmodule ElixirScript.Translator.Function.Test do end js_code = """ - let test1 = Patterns.defmatch(Patterns.make_case([],function() { + const test1 = Elixir.Patterns.defmatch(Elixir.Patterns.make_case([],function() { return 1 * 1; })); """ @@ -39,7 +39,7 @@ defmodule ElixirScript.Translator.Function.Test do end js_code = """ - let test1 = Patterns.defmatch(Patterns.make_case([],function() { + const test1 = Elixir.Patterns.defmatch(Elixir.Patterns.make_case([],function() { return null; })); """ @@ -52,7 +52,7 @@ defmodule ElixirScript.Translator.Function.Test do end js_code = """ - let test1 = Patterns.defmatch(Patterns.make_case([Patterns.variable(), Patterns.variable()],function(alpha,beta) { + const test1 = Elixir.Patterns.defmatch(Elixir.Patterns.make_case([Elixir.Patterns.variable(), Elixir.Patterns.variable()],function(alpha,beta) { return null; })); """ @@ -66,8 +66,8 @@ defmodule ElixirScript.Translator.Function.Test do end js_code = """ - let test1 = Patterns.defmatch(Patterns.make_case([Patterns.variable(), Patterns.variable()],function(alpha,beta) { - let [a0] = Patterns.match(Patterns.variable(),alpha); + const test1 = Elixir.Patterns.defmatch(Elixir.Patterns.make_case([Elixir.Patterns.variable(), Elixir.Patterns.variable()],function(alpha,beta) { + let [a0] = Elixir.Patterns.match(Elixir.Patterns.variable(),alpha); return a0; })); """ @@ -85,12 +85,12 @@ defmodule ElixirScript.Translator.Function.Test do end js_code = """ - let test1 = Patterns.defmatch(Patterns.make_case([Patterns.variable(), Patterns.variable()],function(alpha,beta) { - return Patterns.defmatch(Patterns.make_case([Patterns.variable()],function(x) { + const test1 = Elixir.Patterns.defmatch(Elixir.Patterns.make_case([Elixir.Patterns.variable(), Elixir.Patterns.variable()],function(alpha,beta) { + return Elixir.Patterns.defmatch(Elixir.Patterns.make_case([Elixir.Patterns.variable()],function(x) { return 2; },function(x) { - return Kernel.__in__(x,Kernel.SpecialForms.list(false,null)); - }),Patterns.make_case([Patterns.wildcard()],function() { + return Elixir.Kernel.__in__(x,Elixir.Kernel.SpecialForms.list(false,null)); + }),Elixir.Patterns.make_case([Elixir.Patterns.wildcard()],function() { return 1; })).call(this,1 == 1); })); @@ -113,18 +113,18 @@ defmodule ElixirScript.Translator.Function.Test do end js_code = """ - let test1 = Patterns.defmatch(Patterns.make_case([Patterns.variable(), Patterns.variable()],function(alpha,beta) { - return Patterns.defmatch(Patterns.make_case([Patterns.variable()],function(x) { + const test1 = Elixir.Patterns.defmatch(Elixir.Patterns.make_case([Elixir.Patterns.variable(), Elixir.Patterns.variable()],function(alpha,beta) { + return Elixir.Patterns.defmatch(Elixir.Patterns.make_case([Elixir.Patterns.variable()],function(x) { return 2; },function(x) { - return Kernel.__in__(x,Kernel.SpecialForms.list(false,null)); - }),Patterns.make_case([Patterns.wildcard()],function() { - return Patterns.defmatch(Patterns.make_case([Patterns.variable()],function(x) { - let [a000] = Patterns.match(Patterns.variable(),1); + return Elixir.Kernel.__in__(x,Elixir.Kernel.SpecialForms.list(false,null)); + }),Elixir.Patterns.make_case([Elixir.Patterns.wildcard()],function() { + return Elixir.Patterns.defmatch(Elixir.Patterns.make_case([Elixir.Patterns.variable()],function(x) { + let [a000] = Elixir.Patterns.match(Elixir.Patterns.variable(),1); return a000; },function(x) { - return Kernel.__in__(x,Kernel.SpecialForms.list(false,null)); - }),Patterns.make_case([Patterns.wildcard()],function() { + return Elixir.Kernel.__in__(x,Elixir.Kernel.SpecialForms.list(false,null)); + }),Elixir.Patterns.make_case([Elixir.Patterns.wildcard()],function() { return 4; })).call(this,2 == 2); })).call(this,1 == 1); @@ -140,9 +140,9 @@ defmodule ElixirScript.Translator.Function.Test do end js_code = """ - let test1 = Patterns.defmatch(Patterns.make_case([Patterns.variable(), Patterns.variable()],function(alpha,beta) { - let [a0,b0] = Patterns.match(Kernel.SpecialForms.tuple(Patterns.variable(),Patterns.variable()),Kernel.SpecialForms.tuple(1,2)); - let _ref = Kernel.SpecialForms.tuple(a0,b0); + const test1 = Elixir.Patterns.defmatch(Elixir.Patterns.make_case([Elixir.Patterns.variable(), Elixir.Patterns.variable()],function(alpha,beta) { + let [a0,b0] = Elixir.Patterns.match(Elixir.Kernel.SpecialForms.tuple(Elixir.Patterns.variable(),Elixir.Patterns.variable()),Elixir.Kernel.SpecialForms.tuple(1,2)); + let _ref = Elixir.Kernel.SpecialForms.tuple(a0,b0); return _ref; })); """ @@ -179,7 +179,7 @@ defmodule ElixirScript.Translator.Function.Test do Taco.test1() end - js_code = "JS.get_property_or_call_function(Taco, 'test1')" + js_code = "Elixir.JS.call_property(Taco, 'test1')" assert_translation(ex_ast, js_code) @@ -203,11 +203,11 @@ defmodule ElixirScript.Translator.Function.Test do should "translate anonymous functions" do ex_ast = quote do - Enum.map(list, fn(x) -> x * 2 end) + Elixir.Enum.map(list, fn(x) -> x * 2 end) end js_code = """ - Enum.map(list,Patterns.defmatch(Patterns.make_case([Patterns.variable()],function(x) { + Elixir.Enum.map(list,Elixir.Patterns.defmatch(Elixir.Patterns.make_case([Elixir.Patterns.variable()],function(x) { return x * 2; }))) """ @@ -237,16 +237,16 @@ defmodule ElixirScript.Translator.Function.Test do end js_code = """ - const __MODULE__ = Kernel.SpecialForms.atom('Example'); - let example = Patterns.defmatch(Patterns.make_case([],function() { + const __MODULE__ = Elixir.Kernel.SpecialForms.atom('Example'); + const example = Elixir.Patterns.defmatch(Elixir.Patterns.make_case([],function() { return null; - }),Patterns.make_case([Patterns.variable()],function(oneArg) { + }),Elixir.Patterns.make_case([Elixir.Patterns.variable()],function(oneArg) { return null; - }),Patterns.make_case([Patterns.variable(), Patterns.variable()],function(oneArg,twoArg) { + }),Elixir.Patterns.make_case([Elixir.Patterns.variable(), Elixir.Patterns.variable()],function(oneArg,twoArg) { return null; - }),Patterns.make_case([Patterns.variable(), Patterns.variable(), Patterns.variable()],function(oneArg,twoArg,redArg) { + }),Elixir.Patterns.make_case([Elixir.Patterns.variable(), Elixir.Patterns.variable(), Elixir.Patterns.variable()],function(oneArg,twoArg,redArg) { return null; - }),Patterns.make_case([Patterns.variable(), Patterns.variable(), Patterns.variable(), Patterns.variable()],function(oneArg,twoArg,redArg,blueArg) { + }),Elixir.Patterns.make_case([Elixir.Patterns.variable(), Elixir.Patterns.variable(), Elixir.Patterns.variable(), Elixir.Patterns.variable()],function(oneArg,twoArg,redArg,blueArg) { return null; })); export {}; @@ -274,16 +274,16 @@ defmodule ElixirScript.Translator.Function.Test do end js_code = """ - const __MODULE__ = Kernel.SpecialForms.atom('Example'); - let example = Patterns.defmatch(Patterns.make_case([],function() { + const __MODULE__ = Elixir.Kernel.SpecialForms.atom('Example'); + const example = Elixir.Patterns.defmatch(Elixir.Patterns.make_case([],function() { return null; - }),Patterns.make_case([Patterns.variable()],function(oneArg) { + }),Elixir.Patterns.make_case([Elixir.Patterns.variable()],function(oneArg) { return null; - }),Patterns.make_case([Patterns.variable(), Patterns.variable()],function(oneArg,twoArg) { + }),Elixir.Patterns.make_case([Elixir.Patterns.variable(), Elixir.Patterns.variable()],function(oneArg,twoArg) { return null; - }),Patterns.make_case([Patterns.variable(), Patterns.variable(), Patterns.variable()],function(oneArg,twoArg,redArg) { + }),Elixir.Patterns.make_case([Elixir.Patterns.variable(), Elixir.Patterns.variable(), Elixir.Patterns.variable()],function(oneArg,twoArg,redArg) { return null; - }),Patterns.make_case([Patterns.variable(), Patterns.variable(), Patterns.variable(), Patterns.variable()],function(oneArg,twoArg,redArg,blueArg) { + }),Elixir.Patterns.make_case([Elixir.Patterns.variable(), Elixir.Patterns.variable(), Elixir.Patterns.variable(), Elixir.Patterns.variable()],function(oneArg,twoArg,redArg,blueArg) { return null; })); export { @@ -301,8 +301,8 @@ defmodule ElixirScript.Translator.Function.Test do end js_code = """ - const __MODULE__ = Kernel.SpecialForms.atom('Example'); - let example = Patterns.defmatch(Patterns.make_case([Patterns.variable()],function(oneArg) { + const __MODULE__ = Elixir.Kernel.SpecialForms.atom('Example'); + const example = Elixir.Patterns.defmatch(Elixir.Patterns.make_case([Elixir.Patterns.variable()],function(oneArg) { return null; })); export { @@ -332,12 +332,12 @@ defmodule ElixirScript.Translator.Function.Test do end - should "test Kernel function" do + should "test Elixir.Kernel function" do ex_ast = quote do is_atom(:atom) end - js_code = "Kernel.is_atom(Kernel.SpecialForms.atom('atom'))" + js_code = "Elixir.Kernel.is_atom(Elixir.Kernel.SpecialForms.atom('atom'))" assert_translation(ex_ast, js_code) end @@ -350,10 +350,10 @@ defmodule ElixirScript.Translator.Function.Test do js_code = """ - let something = Patterns.defmatch(Patterns.make_case([Patterns.variable()],function(one) { + const something = Elixir.Patterns.defmatch(Elixir.Patterns.make_case([Elixir.Patterns.variable()],function(one) { return null; },function(one) { - return Kernel.is_number(one); + return Elixir.Kernel.is_number(one); })); """ @@ -367,10 +367,10 @@ defmodule ElixirScript.Translator.Function.Test do js_code = """ - let something = Patterns.defmatch(Patterns.make_case([Patterns.variable()],function(one) { + const something = Elixir.Patterns.defmatch(Elixir.Patterns.make_case([Elixir.Patterns.variable()],function(one) { return null; },function(one) { - return Kernel.is_number(one) || Kernel.is_atom(one); + return Elixir.Kernel.is_number(one) || Elixir.Kernel.is_atom(one); })); """ @@ -383,10 +383,10 @@ defmodule ElixirScript.Translator.Function.Test do js_code = """ - let something = Patterns.defmatch(Patterns.make_case([Patterns.variable()],function(one) { + const something = Elixir.Patterns.defmatch(Elixir.Patterns.make_case([Elixir.Patterns.variable()],function(one) { return null; },function(one) { - return Kernel.is_number(one) || Kernel.is_atom(one); + return Elixir.Kernel.is_number(one) || Elixir.Kernel.is_atom(one); })); """ @@ -399,10 +399,10 @@ defmodule ElixirScript.Translator.Function.Test do js_code = """ - let something = Patterns.defmatch(Patterns.make_case([Patterns.variable(), Patterns.variable()],function(one,two) { + const something = Elixir.Patterns.defmatch(Elixir.Patterns.make_case([Elixir.Patterns.variable(), Elixir.Patterns.variable()],function(one,two) { return null; },function(one,two) { - return Kernel.__in__(one,Kernel.SpecialForms.list(1,2,3)); + return Elixir.Kernel.__in__(one,Elixir.Kernel.SpecialForms.list(1,2,3)); })); """ @@ -419,15 +419,15 @@ defmodule ElixirScript.Translator.Function.Test do end js_code = """ - const __MODULE__ = Kernel.SpecialForms.atom('Example'); - let something = Patterns.defmatch(Patterns.make_case([Patterns.variable()],function(one) { + const __MODULE__ = Elixir.Kernel.SpecialForms.atom('Example'); + const something = Elixir.Patterns.defmatch(Elixir.Patterns.make_case([Elixir.Patterns.variable()],function(one) { return null; },function(one) { - return Kernel.__in__(one,Kernel.SpecialForms.list(1,2,3)); - }),Patterns.make_case([Patterns.variable()],function(one) { + return Elixir.Kernel.__in__(one,Elixir.Kernel.SpecialForms.list(1,2,3)); + }),Elixir.Patterns.make_case([Elixir.Patterns.variable()],function(one) { return null; },function(one) { - return Kernel.is_number(one) || Kernel.is_atom(one); + return Elixir.Kernel.is_number(one) || Elixir.Kernel.is_atom(one); })); export { something @@ -445,7 +445,7 @@ defmodule ElixirScript.Translator.Function.Test do js_code = """ - let something = Patterns.defmatch(Patterns.make_case([1],function() { + const something = Elixir.Patterns.defmatch(Elixir.Patterns.make_case([1],function() { return null; })); """ @@ -461,7 +461,7 @@ defmodule ElixirScript.Translator.Function.Test do js_code = """ - let something = Patterns.defmatch(Patterns.make_case([Patterns.headTail()],function(apple,fruits) { + const something = Elixir.Patterns.defmatch(Elixir.Patterns.make_case([Elixir.Patterns.headTail()],function(apple,fruits) { return null; })); """ @@ -477,7 +477,7 @@ defmodule ElixirScript.Translator.Function.Test do js_code = """ - let something = Patterns.defmatch(Patterns.make_case([Kernel.SpecialForms.list(Patterns.variable(),Patterns.variable(),Patterns.variable())],function(apple,pear,banana) { + const something = Elixir.Patterns.defmatch(Elixir.Patterns.make_case([Elixir.Kernel.SpecialForms.list(Elixir.Patterns.variable(),Elixir.Patterns.variable(),Elixir.Patterns.variable())],function(apple,pear,banana) { return null; })); """ @@ -493,7 +493,7 @@ defmodule ElixirScript.Translator.Function.Test do js_code = """ - let something = Patterns.defmatch(Patterns.make_case([Kernel.SpecialForms.tuple(Patterns.variable(),Patterns.variable())],function(apple,fruits) { + const something = Elixir.Patterns.defmatch(Elixir.Patterns.make_case([Elixir.Kernel.SpecialForms.tuple(Elixir.Patterns.variable(),Elixir.Patterns.variable())],function(apple,fruits) { return null; })); """ @@ -509,8 +509,8 @@ defmodule ElixirScript.Translator.Function.Test do js_code = """ - let something = Patterns.defmatch(Patterns.make_case([{ - [Kernel.SpecialForms.atom('__struct__')]: Kernel.SpecialForms.atom('AStruct') + const something = Elixir.Patterns.defmatch(Elixir.Patterns.make_case([{ + [Elixir.Kernel.SpecialForms.atom('__struct__')]: Elixir.Kernel.SpecialForms.atom('AStruct') }],function() { return null; })); @@ -526,8 +526,8 @@ defmodule ElixirScript.Translator.Function.Test do end js_code = """ - let something = Patterns.defmatch(Patterns.make_case([Patterns.capture({ - [Kernel.SpecialForms.atom('__struct__')]: Kernel.SpecialForms.atom('AStruct') + const something = Elixir.Patterns.defmatch(Elixir.Patterns.make_case([Elixir.Patterns.capture({ + [Elixir.Kernel.SpecialForms.atom('__struct__')]: Elixir.Kernel.SpecialForms.atom('AStruct') })],function(a) { return null; })); @@ -542,8 +542,8 @@ defmodule ElixirScript.Translator.Function.Test do end js_code = """ - let something = Patterns.defmatch(Patterns.make_case([Patterns.capture({ - [Kernel.SpecialForms.atom('which')]: 13 + const something = Elixir.Patterns.defmatch(Elixir.Patterns.make_case([Elixir.Patterns.capture({ + [Elixir.Kernel.SpecialForms.atom('which')]: 13 })],function(a) { return null; })); @@ -560,8 +560,8 @@ defmodule ElixirScript.Translator.Function.Test do js_code = """ - let something = Patterns.defmatch(Patterns.make_case([{ - [Kernel.SpecialForms.atom('__struct__')]: Kernel.SpecialForms.atom('AStruct'), [Kernel.SpecialForms.atom('key')]: Patterns.variable(), [Kernel.SpecialForms.atom('key1')]: 2 + const something = Elixir.Patterns.defmatch(Elixir.Patterns.make_case([{ + [Elixir.Kernel.SpecialForms.atom('__struct__')]: Elixir.Kernel.SpecialForms.atom('AStruct'), [Elixir.Kernel.SpecialForms.atom('key')]: Elixir.Patterns.variable(), [Elixir.Kernel.SpecialForms.atom('key1')]: 2 }],function(value) { return null; })); @@ -576,12 +576,12 @@ defmodule ElixirScript.Translator.Function.Test do js_code = """ - let something = Patterns.defmatch(Patterns.make_case([{ - [Kernel.SpecialForms.atom('__struct__')]: Kernel.SpecialForms.atom('AStruct'), [Kernel.SpecialForms.atom('key')]: Patterns.variable(), [Kernel.SpecialForms.atom('key1')]: 2 + const something = Elixir.Patterns.defmatch(Elixir.Patterns.make_case([{ + [Elixir.Kernel.SpecialForms.atom('__struct__')]: Elixir.Kernel.SpecialForms.atom('AStruct'), [Elixir.Kernel.SpecialForms.atom('key')]: Elixir.Patterns.variable(), [Elixir.Kernel.SpecialForms.atom('key1')]: 2 }],function(value) { return null; },function(value) { - return Kernel.is_number(value); + return Elixir.Kernel.is_number(value); })); """ @@ -596,7 +596,7 @@ defmodule ElixirScript.Translator.Function.Test do js_code = """ - let something = Patterns.defmatch(Patterns.make_case([Patterns.startsWith('Bearer ')],function(token) { + const something = Elixir.Patterns.defmatch(Elixir.Patterns.make_case([Elixir.Patterns.startsWith('Bearer ')],function(token) { return null; })); """ @@ -610,7 +610,7 @@ defmodule ElixirScript.Translator.Function.Test do js_code = """ - let something = Patterns.defmatch(Patterns.make_case([Patterns.startsWith('Bearer '), Patterns.variable()],function(token,hotel) { + const something = Elixir.Patterns.defmatch(Elixir.Patterns.make_case([Elixir.Patterns.startsWith('Bearer '), Elixir.Patterns.variable()],function(token,hotel) { return null; })); """ @@ -624,7 +624,7 @@ defmodule ElixirScript.Translator.Function.Test do js_code = """ - let something = Patterns.defmatch(Patterns.make_case([Patterns.startsWith('Bearer '), Patterns.variable(), 1],function(token,hotel) { + const something = Elixir.Patterns.defmatch(Elixir.Patterns.make_case([Elixir.Patterns.startsWith('Bearer '), Elixir.Patterns.variable(), 1],function(token,hotel) { return null; })); """ @@ -652,16 +652,16 @@ defmodule ElixirScript.Translator.Function.Test do js_code = """ - const __MODULE__ = Kernel.SpecialForms.atom('Example'); - let something = Patterns.defmatch(Patterns.make_case([1],function() { + const __MODULE__ = Elixir.Kernel.SpecialForms.atom('Example'); + const something = Elixir.Patterns.defmatch(Elixir.Patterns.make_case([1],function() { return null; - }),Patterns.make_case([2],function() { + }),Elixir.Patterns.make_case([2],function() { return null; - }),Patterns.make_case([Patterns.variable()],function(one) { + }),Elixir.Patterns.make_case([Elixir.Patterns.variable()],function(one) { return null; },function(one) { - return Kernel.is_binary(one); - }),Patterns.make_case([Patterns.variable()],function(one) { + return Elixir.Kernel.is_binary(one); + }),Elixir.Patterns.make_case([Elixir.Patterns.variable()],function(one) { return null; })); export { @@ -682,9 +682,9 @@ defmodule ElixirScript.Translator.Function.Test do end js_code = """ - let test1 = Patterns.defmatch(Patterns.make_case([Patterns.variable(), Patterns.variable()],function(alpha,beta) { - let [a0] = Patterns.match(Patterns.variable(),1); - let [a1] = Patterns.match(Patterns.variable(),2); + const test1 = Elixir.Patterns.defmatch(Elixir.Patterns.make_case([Elixir.Patterns.variable(), Elixir.Patterns.variable()],function(alpha,beta) { + let [a0] = Elixir.Patterns.match(Elixir.Patterns.variable(),1); + let [a1] = Elixir.Patterns.match(Elixir.Patterns.variable(),2); return a1; })); """ @@ -700,10 +700,10 @@ defmodule ElixirScript.Translator.Function.Test do end js_code = """ - let test1 = Patterns.defmatch(Patterns.make_case([Patterns.variable(), Patterns.variable()],function(alpha,beta) { - let [a0] = Patterns.match(Patterns.variable(),1); - let [a1] = Patterns.match(Patterns.variable(),a0); - let [a2] = Patterns.match(Patterns.variable(),2); + const test1 = Elixir.Patterns.defmatch(Elixir.Patterns.make_case([Elixir.Patterns.variable(), Elixir.Patterns.variable()],function(alpha,beta) { + let [a0] = Elixir.Patterns.match(Elixir.Patterns.variable(),1); + let [a1] = Elixir.Patterns.match(Elixir.Patterns.variable(),a0); + let [a2] = Elixir.Patterns.match(Elixir.Patterns.variable(),2); return a2; })); """ @@ -718,10 +718,10 @@ defmodule ElixirScript.Translator.Function.Test do end js_code = """ - let test1 = Patterns.defmatch(Patterns.make_case([Patterns.variable(), Patterns.variable()],function(alpha,beta) { - let [a0] = Patterns.match(Patterns.variable(),1); - let [a1,b0,c0] = Patterns.match(Kernel.SpecialForms.list(Patterns.variable(),Patterns.variable(),Patterns.variable()),Kernel.SpecialForms.list(a0,2,3)); - let _ref = Kernel.SpecialForms.list(a1,b0,c0); + const test1 = Elixir.Patterns.defmatch(Elixir.Patterns.make_case([Elixir.Patterns.variable(), Elixir.Patterns.variable()],function(alpha,beta) { + let [a0] = Elixir.Patterns.match(Elixir.Patterns.variable(),1); + let [a1,b0,c0] = Elixir.Patterns.match(Elixir.Kernel.SpecialForms.list(Elixir.Patterns.variable(),Elixir.Patterns.variable(),Elixir.Patterns.variable()),Elixir.Kernel.SpecialForms.list(a0,2,3)); + let _ref = Elixir.Kernel.SpecialForms.list(a1,b0,c0); return _ref; })); """ @@ -739,9 +739,9 @@ defmodule ElixirScript.Translator.Function.Test do end js_code = """ - let test1 = Patterns.defmatch(Patterns.make_case([Patterns.variable(), Patterns.variable()],function(alpha__qmark__,beta__emark__) { - let [a__qmark__0] = Patterns.match(Patterns.variable(),1); - let [b__emark__0] = Patterns.match(Patterns.variable(),2); + const test1 = Elixir.Patterns.defmatch(Elixir.Patterns.make_case([Elixir.Patterns.variable(), Elixir.Patterns.variable()],function(alpha__qmark__,beta__emark__) { + let [a__qmark__0] = Elixir.Patterns.match(Elixir.Patterns.variable(),1); + let [b__emark__0] = Elixir.Patterns.match(Elixir.Patterns.variable(),2); return b__emark__0; })); """ diff --git a/test/translator/kernel_test.exs b/test/translator/kernel_test.exs index d23e206a..7cc82bf7 100644 --- a/test/translator/kernel_test.exs +++ b/test/translator/kernel_test.exs @@ -34,7 +34,7 @@ defmodule ElixirScript.Translator.Kernel.Test do end js_code = """ - Enum.reverse(1,2,3) + Elixir.Enum.reverse(1,2,3) """ assert_translation(ex_ast, js_code) @@ -47,7 +47,7 @@ defmodule ElixirScript.Translator.Kernel.Test do end js_code = """ - Kernel.SpecialForms.list(1,2,3)[0] + Elixir.Kernel.SpecialForms.list(1,2,3)[0] """ assert_translation(ex_ast, js_code) @@ -60,7 +60,7 @@ defmodule ElixirScript.Translator.Kernel.Test do end js_code = """ - Kernel.SpecialForms.list(1,2,3).slice(1) + Elixir.Kernel.SpecialForms.list(1,2,3).slice(1) """ assert_translation(ex_ast, js_code) diff --git a/test/translator/list_test.exs b/test/translator/list_test.exs index d30db067..698e77d7 100644 --- a/test/translator/list_test.exs +++ b/test/translator/list_test.exs @@ -4,34 +4,34 @@ defmodule ElixirScript.Translator.List.Test do should "translate list" do ex_ast = quote do: [1, 2, 3] - js_code = "Kernel.SpecialForms.list(1, 2, 3)" + js_code = "Elixir.Kernel.SpecialForms.list(1, 2, 3)" assert_translation(ex_ast, js_code) ex_ast = quote do: ["a", "b", "c"] - js_code = "Kernel.SpecialForms.list('a', 'b', 'c')" + js_code = "Elixir.Kernel.SpecialForms.list('a', 'b', 'c')" assert_translation(ex_ast, js_code) ex_ast = quote do: [:a, :b, :c] - js_code = "Kernel.SpecialForms.list(Kernel.SpecialForms.atom('a'), Kernel.SpecialForms.atom('b'), Kernel.SpecialForms.atom('c'))" + js_code = "Elixir.Kernel.SpecialForms.list(Elixir.Kernel.SpecialForms.atom('a'), Elixir.Kernel.SpecialForms.atom('b'), Elixir.Kernel.SpecialForms.atom('c'))" assert_translation(ex_ast, js_code) ex_ast = quote do: [:a, 2, "c"] - js_code = "Kernel.SpecialForms.list(Kernel.SpecialForms.atom('a'), 2, 'c')" + js_code = "Elixir.Kernel.SpecialForms.list(Elixir.Kernel.SpecialForms.atom('a'), 2, 'c')" assert_translation(ex_ast, js_code) end should "concatenate lists" do ex_ast = quote do: [1, 2, 3] ++ [4, 5, 6] - js_code = "Kernel.SpecialForms.list(1,2,3).concat(Kernel.SpecialForms.list(4,5,6))" + js_code = "Elixir.Kernel.SpecialForms.list(1,2,3).concat(Elixir.Kernel.SpecialForms.list(4,5,6))" assert_translation(ex_ast, js_code) ex_ast = quote do: this.list ++ [4, 5, 6] - js_code = "JS.get_property_or_call_function(this,'list').concat(Kernel.SpecialForms.list(4,5,6))" + js_code = "Elixir.JS.call_property(this,'list').concat(Elixir.Kernel.SpecialForms.list(4,5,6))" assert_translation(ex_ast, js_code) end diff --git a/test/translator/map_test.exs b/test/translator/map_test.exs index 618ddafd..00af9105 100644 --- a/test/translator/map_test.exs +++ b/test/translator/map_test.exs @@ -4,14 +4,14 @@ defmodule ElixirScript.Translator.Map.Test do should "translate empty map" do ex_ast = quote do: %{} - js_code = "Kernel.SpecialForms.map({})" + js_code = "Elixir.Kernel.SpecialForms.map({})" assert_translation(ex_ast, js_code) end should "translate map with elements" do ex_ast = quote do: %{one: "one", two: "two"} - js_code = "Kernel.SpecialForms.map({[Kernel.SpecialForms.atom('one')]: 'one', [Kernel.SpecialForms.atom('two')]: 'two'})" + js_code = "Elixir.Kernel.SpecialForms.map({[Elixir.Kernel.SpecialForms.atom('one')]: 'one', [Elixir.Kernel.SpecialForms.atom('two')]: 'two'})" assert_translation(ex_ast, js_code) end @@ -19,10 +19,10 @@ defmodule ElixirScript.Translator.Map.Test do should "translate map within map" do ex_ast = quote do: %{one: "one", two: %{three: "three"}} js_code = """ - Kernel.SpecialForms.map({ - [Kernel.SpecialForms.atom('one')]: 'one', - [Kernel.SpecialForms.atom('two')]: Kernel.SpecialForms.map({ - [Kernel.SpecialForms.atom('three')]: 'three' + Elixir.Kernel.SpecialForms.map({ + [Elixir.Kernel.SpecialForms.atom('one')]: 'one', + [Elixir.Kernel.SpecialForms.atom('two')]: Elixir.Kernel.SpecialForms.map({ + [Elixir.Kernel.SpecialForms.atom('three')]: 'three' }) }) """ @@ -33,7 +33,7 @@ defmodule ElixirScript.Translator.Map.Test do should "translate map with string keys" do ex_ast = quote do: %{"one" => "one", "two" => "two"} js_code = """ - Kernel.SpecialForms.map({ + Elixir.Kernel.SpecialForms.map({ one: 'one', two: 'two' }) """ @@ -45,8 +45,8 @@ defmodule ElixirScript.Translator.Map.Test do should "translate map update" do ex_ast = quote do: %{ map | value: 1 } js_code = """ - Kernel.SpecialForms.map_update(map,{ - [Kernel.SpecialForms.atom('value')]: 1 + Elixir.Kernel.SpecialForms.map_update(map,{ + [Elixir.Kernel.SpecialForms.atom('value')]: 1 }) """ diff --git a/test/translator/quote_test.exs b/test/translator/quote_test.exs index 588fa8fb..cc5f67b9 100644 --- a/test/translator/quote_test.exs +++ b/test/translator/quote_test.exs @@ -17,7 +17,7 @@ defmodule ElixirScript.Translator.Quote.Test do quote do: :time end - js_code = "Kernel.SpecialForms.atom('time')" + js_code = "Elixir.Kernel.SpecialForms.atom('time')" assert_translation(ex_ast, js_code) end @@ -28,7 +28,7 @@ defmodule ElixirScript.Translator.Quote.Test do quote do: {1, 2} end - js_code = "Kernel.SpecialForms.tuple(1, 2)" + js_code = "Elixir.Kernel.SpecialForms.tuple(1, 2)" assert_translation(ex_ast, js_code) end @@ -39,7 +39,7 @@ defmodule ElixirScript.Translator.Quote.Test do quote do: {1, 2, 3} end - js_code = "Kernel.SpecialForms.tuple(Kernel.SpecialForms.atom('{}'), Kernel.SpecialForms.list(), Kernel.SpecialForms.list(1, 2, 3))" + js_code = "Elixir.Kernel.SpecialForms.tuple(Elixir.Kernel.SpecialForms.atom('{}'), Elixir.Kernel.SpecialForms.list(), Elixir.Kernel.SpecialForms.list(1, 2, 3))" assert_translation(ex_ast, js_code) end @@ -50,9 +50,9 @@ defmodule ElixirScript.Translator.Quote.Test do quote do: test(1) end - js_code = "Kernel.SpecialForms.tuple(Kernel.SpecialForms.atom('test'), - Kernel.SpecialForms.list(Kernel.SpecialForms.tuple(Kernel.SpecialForms.atom('context'),Kernel.SpecialForms.atom('Elixir.ElixirScript.Translator.Quote.Test')),Kernel.SpecialForms.tuple(Kernel.SpecialForms.atom('import'),Kernel.SpecialForms.atom('Elixir.ExUnit.Case'))), - Kernel.SpecialForms.list(1))" + js_code = "Elixir.Kernel.SpecialForms.tuple(Elixir.Kernel.SpecialForms.atom('test'), + Elixir.Kernel.SpecialForms.list(Elixir.Kernel.SpecialForms.tuple(Elixir.Kernel.SpecialForms.atom('context'),Elixir.Kernel.SpecialForms.atom('Elixir.ElixirScript.Translator.Quote.Test')),Elixir.Kernel.SpecialForms.tuple(Elixir.Kernel.SpecialForms.atom('import'),Elixir.Kernel.SpecialForms.atom('Elixir.ExUnit.Case'))), + Elixir.Kernel.SpecialForms.list(1))" assert_translation(ex_ast, js_code) end @@ -63,10 +63,10 @@ defmodule ElixirScript.Translator.Quote.Test do quote do: test(x) end - js_code = "Kernel.SpecialForms.tuple( - Kernel.SpecialForms.atom('test'), - Kernel.SpecialForms.list(Kernel.SpecialForms.tuple(Kernel.SpecialForms.atom('context'),Kernel.SpecialForms.atom('Elixir.ElixirScript.Translator.Quote.Test')),Kernel.SpecialForms.tuple(Kernel.SpecialForms.atom('import'),Kernel.SpecialForms.atom('Elixir.ExUnit.Case'))), - Kernel.SpecialForms.list(Kernel.SpecialForms.tuple(Kernel.SpecialForms.atom('x'),Kernel.SpecialForms.list(),Kernel.SpecialForms.atom('Elixir.ElixirScript.Translator.Quote.Test'))) + js_code = "Elixir.Kernel.SpecialForms.tuple( + Elixir.Kernel.SpecialForms.atom('test'), + Elixir.Kernel.SpecialForms.list(Elixir.Kernel.SpecialForms.tuple(Elixir.Kernel.SpecialForms.atom('context'),Elixir.Kernel.SpecialForms.atom('Elixir.ElixirScript.Translator.Quote.Test')),Elixir.Kernel.SpecialForms.tuple(Elixir.Kernel.SpecialForms.atom('import'),Elixir.Kernel.SpecialForms.atom('Elixir.ExUnit.Case'))), + Elixir.Kernel.SpecialForms.list(Elixir.Kernel.SpecialForms.tuple(Elixir.Kernel.SpecialForms.atom('x'),Elixir.Kernel.SpecialForms.list(),Elixir.Kernel.SpecialForms.atom('Elixir.ElixirScript.Translator.Quote.Test'))) )" assert_translation(ex_ast, js_code) @@ -78,10 +78,10 @@ defmodule ElixirScript.Translator.Quote.Test do quote do: test(unquote(x)) end - js_code = "Kernel.SpecialForms.tuple( - Kernel.SpecialForms.atom('test'), - Kernel.SpecialForms.list(Kernel.SpecialForms.tuple(Kernel.SpecialForms.atom('context'),Kernel.SpecialForms.atom('Elixir.ElixirScript.Translator.Quote.Test')),Kernel.SpecialForms.tuple(Kernel.SpecialForms.atom('import'),Kernel.SpecialForms.atom('Elixir.ExUnit.Case'))), - Kernel.SpecialForms.list(x) + js_code = "Elixir.Kernel.SpecialForms.tuple( + Elixir.Kernel.SpecialForms.atom('test'), + Elixir.Kernel.SpecialForms.list(Elixir.Kernel.SpecialForms.tuple(Elixir.Kernel.SpecialForms.atom('context'),Elixir.Kernel.SpecialForms.atom('Elixir.ElixirScript.Translator.Quote.Test')),Elixir.Kernel.SpecialForms.tuple(Elixir.Kernel.SpecialForms.atom('import'),Elixir.Kernel.SpecialForms.atom('Elixir.ExUnit.Case'))), + Elixir.Kernel.SpecialForms.list(x) )" assert_translation(ex_ast, js_code) @@ -93,7 +93,7 @@ defmodule ElixirScript.Translator.Quote.Test do quote do: sum(1, unquote_splicing(values), 5) end - js_code = "Kernel.SpecialForms.tuple(Kernel.SpecialForms.atom('sum'), Kernel.SpecialForms.list(), Enum.concat(Kernel.SpecialForms.list(1), values, Kernel.SpecialForms.list(5)))" + js_code = "Elixir.Kernel.SpecialForms.tuple(Elixir.Kernel.SpecialForms.atom('sum'), Elixir.Kernel.SpecialForms.list(), Elixir.Enum.concat(Elixir.Kernel.SpecialForms.list(1), values, Elixir.Kernel.SpecialForms.list(5)))" assert_translation(ex_ast, js_code) end @@ -105,10 +105,10 @@ defmodule ElixirScript.Translator.Quote.Test do end end - js_code = "Kernel.SpecialForms.tuple( - Kernel.SpecialForms.atom('*'), - Kernel.SpecialForms.list(Kernel.SpecialForms.tuple(Kernel.SpecialForms.atom('context'),Kernel.SpecialForms.atom('Elixir.ElixirScript.Translator.Quote.Test')),Kernel.SpecialForms.tuple(Kernel.SpecialForms.atom('import'),Kernel.SpecialForms.atom('Elixir.Kernel'))), - Kernel.SpecialForms.list(x, x) + js_code = "Elixir.Kernel.SpecialForms.tuple( + Elixir.Kernel.SpecialForms.atom('*'), + Elixir.Kernel.SpecialForms.list(Elixir.Kernel.SpecialForms.tuple(Elixir.Kernel.SpecialForms.atom('context'),Elixir.Kernel.SpecialForms.atom('Elixir.ElixirScript.Translator.Quote.Test')),Elixir.Kernel.SpecialForms.tuple(Elixir.Kernel.SpecialForms.atom('import'),Elixir.Kernel.SpecialForms.atom('Elixir.Kernel'))), + Elixir.Kernel.SpecialForms.list(x, x) )" assert_translation(ex_ast, js_code) diff --git a/test/translator/receive_test.exs b/test/translator/receive_test.exs index 46f0f5cb..1b4da1c3 100644 --- a/test/translator/receive_test.exs +++ b/test/translator/receive_test.exs @@ -16,11 +16,11 @@ defmodule ElixirScript.Translator.Receive.Test do js_code = """ yield self.system.receive(function(message) { - return Patterns.defmatch(Patterns.make_case([Kernel.SpecialForms.atom('ok')],function() { + return Elixir.Patterns.defmatch(Elixir.Patterns.make_case([Elixir.Kernel.SpecialForms.atom('ok')],function() { return value; - }),Patterns.make_case([Kernel.SpecialForms.atom('error')],function() { + }),Elixir.Patterns.make_case([Elixir.Kernel.SpecialForms.atom('error')],function() { return value; - }),Patterns.make_case([Patterns.wildcard()],function() { + }),Elixir.Patterns.make_case([Elixir.Patterns.wildcard()],function() { return IO.puts('Unexpected message received'); })).call(this,message); }) @@ -46,14 +46,14 @@ defmodule ElixirScript.Translator.Receive.Test do js_code = """ yield self.system.receive(function(message) { - return Patterns.defmatch(Patterns.make_case([Kernel.SpecialForms.atom('ok')],function() { + return Elixir.Patterns.defmatch(Elixir.Patterns.make_case([Elixir.Kernel.SpecialForms.atom('ok')],function() { return value; - }),Patterns.make_case([Kernel.SpecialForms.atom('error')],function() { + }),Elixir.Patterns.make_case([Elixir.Kernel.SpecialForms.atom('error')],function() { return value; - }),Patterns.make_case([Patterns.wildcard()],function() { + }),Elixir.Patterns.make_case([Elixir.Patterns.wildcard()],function() { return IO.puts('Unexpected message received'); })).call(this,message); - },5000,Patterns.defmatch(Patterns.make_case([5000],function() { + },5000,Elixir.Patterns.defmatch(Elixir.Patterns.make_case([5000],function() { return IO.puts('No message in 5 seconds'); }))) """ diff --git a/test/translator/string_test.exs b/test/translator/string_test.exs index b2539a5d..df97f579 100644 --- a/test/translator/string_test.exs +++ b/test/translator/string_test.exs @@ -25,19 +25,19 @@ defmodule ElixirScript.Translator.String.Test do assert_translation(ex_ast, "'Hello ' + 'world'") ex_ast = quote do: "Hello #{length([])}" - assert_translation(ex_ast, "'Hello ' + Kernel.to_string(Kernel.SpecialForms.list().length)") + assert_translation(ex_ast, "'Hello ' + Elixir.Kernel.to_string(Elixir.Kernel.SpecialForms.list().length)") end should "translate multiline string interpolation" do ex_ast = quote do: """ Hello #{length([])} """ - assert_translation(ex_ast, "'Hello ' + (Kernel.to_string(Kernel.SpecialForms.list().length) + '\\n')") + assert_translation(ex_ast, "'Hello ' + (Elixir.Kernel.to_string(Elixir.Kernel.SpecialForms.list().length) + '\\n')") ex_ast = quote do: """ Hello #{length([])} How are you, #{length([])}? """ - assert_translation(ex_ast, "'Hello ' + (Kernel.to_string(Kernel.SpecialForms.list().length) + ('\\nHow are you, ' + (Kernel.to_string(Kernel.SpecialForms.list().length) + '?\\n')))") + assert_translation(ex_ast, "'Hello ' + (Elixir.Kernel.to_string(Elixir.Kernel.SpecialForms.list().length) + ('\\nHow are you, ' + (Elixir.Kernel.to_string(Elixir.Kernel.SpecialForms.list().length) + '?\\n')))") end end \ No newline at end of file diff --git a/test/translator/struct_test.exs b/test/translator/struct_test.exs index 0a2dee52..665a1260 100644 --- a/test/translator/struct_test.exs +++ b/test/translator/struct_test.exs @@ -10,11 +10,11 @@ defmodule ElixirScript.Translator.Struct.Test do end js_code = """ - const __MODULE__ = Kernel.SpecialForms.atom('User'); - function defstruct(name = 'john',age = 27) { - return Kernel.SpecialForms.map({ - [Kernel.SpecialForms.atom('__struct__')]: __MODULE__, [Kernel.SpecialForms.atom('name')]: name, [Kernel.SpecialForms.atom('age')]: age - }); + const __MODULE__ = Elixir.Kernel.SpecialForms.atom('User'); + function defstruct(values = {}) { + return Kernel.defstruct({ + [Elixir.Kernel.SpecialForms.atom('__struct__')]: __MODULE__, [Elixir.Kernel.SpecialForms.atom('name')]: 'john', [Elixir.Kernel.SpecialForms.atom('age')]: 27 + },values); } export { defstruct @@ -33,11 +33,11 @@ defmodule ElixirScript.Translator.Struct.Test do end js_code = """ - const __MODULE__ = Kernel.SpecialForms.atom('User'); - function defstruct(name,age) { - return Kernel.SpecialForms.map({ - [Kernel.SpecialForms.atom('__struct__')]: __MODULE__, [Kernel.SpecialForms.atom('name')]: name, [Kernel.SpecialForms.atom('age')]: age - }); + const __MODULE__ = Elixir.Kernel.SpecialForms.atom('User'); + function defstruct(values = {}) { + return Kernel.defstruct({ + [Elixir.Kernel.SpecialForms.atom('__struct__')]: __MODULE__, [Elixir.Kernel.SpecialForms.atom('name')]: null, [Elixir.Kernel.SpecialForms.atom('age')]: null + },values); } export { defstruct @@ -54,7 +54,7 @@ defmodule ElixirScript.Translator.Struct.Test do end js_code = """ - let [user] = Patterns.match(Patterns.variable(),User.defstruct()); + let [user] = Elixir.Patterns.match(Elixir.Patterns.variable(),User.defstruct(Elixir.Kernel.SpecialForms.map({}))); """ assert_translation(ex_ast, js_code) @@ -64,7 +64,9 @@ defmodule ElixirScript.Translator.Struct.Test do end js_code = """ - let [user] = Patterns.match(Patterns.variable(),User.defstruct(name = 'John')); + let [user] = Elixir.Patterns.match(Elixir.Patterns.variable(),User.defstruct(Elixir.Kernel.SpecialForms.map({ + [Elixir.Kernel.SpecialForms.atom('name')]: 'John' + }))); """ assert_translation(ex_ast, js_code) @@ -76,8 +78,8 @@ defmodule ElixirScript.Translator.Struct.Test do end js_code = """ - let [user] = Patterns.match(Patterns.variable(),Kernel.SpecialForms.map_update(map,{ - [Kernel.SpecialForms.atom('key')]: value + let [user] = Elixir.Patterns.match(Elixir.Patterns.variable(),Elixir.Kernel.SpecialForms.map_update(map,{ + [Elixir.Kernel.SpecialForms.atom('key')]: value })); """ @@ -89,8 +91,8 @@ defmodule ElixirScript.Translator.Struct.Test do end js_code = """ - let [user] = Patterns.match(Patterns.variable(),Kernel.SpecialForms.map_update(map,{ - [Kernel.SpecialForms.atom('key')]: value, [Kernel.SpecialForms.atom('key1')]: value1 + let [user] = Elixir.Patterns.match(Elixir.Patterns.variable(),Elixir.Kernel.SpecialForms.map_update(map,{ + [Elixir.Kernel.SpecialForms.atom('key')]: value, [Elixir.Kernel.SpecialForms.atom('key1')]: value1 })); """ @@ -105,11 +107,11 @@ defmodule ElixirScript.Translator.Struct.Test do end js_code = """ - const __MODULE__ = Kernel.SpecialForms.atom('MyAppError'); - function defexception(message = 'This is a message') { - return Kernel.SpecialForms.map({ - [Kernel.SpecialForms.atom('__struct__')]: __MODULE__, [Kernel.SpecialForms.atom('message')]: message - }); + const __MODULE__ = Elixir.Kernel.SpecialForms.atom('MyAppError'); + function defexception(values = {}) { + return Kernel.defstruct({ + [Elixir.Kernel.SpecialForms.atom('__struct__')]: __MODULE__, [Elixir.Kernel.SpecialForms.atom('message')]: 'This is a message' + },values); } export { defexception @@ -125,11 +127,11 @@ defmodule ElixirScript.Translator.Struct.Test do end js_code = """ - const __MODULE__ = Kernel.SpecialForms.atom('MyAppError'); - function defexception(message = null) { - return Kernel.SpecialForms.map({ - [Kernel.SpecialForms.atom('__struct__')]: __MODULE__, [Kernel.SpecialForms.atom('message')]: message - }); + const __MODULE__ = Elixir.Kernel.SpecialForms.atom('MyAppError'); + function defexception(values = {}) { + return Kernel.defstruct({ + [Elixir.Kernel.SpecialForms.atom('__struct__')]: __MODULE__, [Elixir.Kernel.SpecialForms.atom('message')]: null + },values); } export { defexception @@ -158,7 +160,7 @@ defmodule ElixirScript.Translator.Struct.Test do js_code = """ throw { - [Kernel.SpecialForms.atom('__struct__')]: Kernel.SpecialForms.atom('RuntimeError'), [Kernel.SpecialForms.atom('message')]: 'did not get what was expected' + [Elixir.Kernel.SpecialForms.atom('__struct__')]: Elixir.Kernel.SpecialForms.atom('RuntimeError'), [Elixir.Kernel.SpecialForms.atom('message')]: 'did not get what was expected' }; """ diff --git a/test/translator/try_test.exs b/test/translator/try_test.exs index 3ae54cc2..2ee02aa8 100644 --- a/test/translator/try_test.exs +++ b/test/translator/try_test.exs @@ -13,10 +13,10 @@ defmodule ElixirScript.Translator.Try.Test do end js_code = """ - Kernel.SpecialForms._try(function() { + Elixir.Kernel.SpecialForms._try(function() { return do_something_that_may_fail(some_arg); - },Patterns.defmatch(Patterns.make_case([{ - [Kernel.SpecialForms.atom('__struct__')]: Kernel.SpecialForms.atom('ArgumentError') + },Elixir.Patterns.defmatch(Elixir.Patterns.make_case([{ + [Elixir.Kernel.SpecialForms.atom('__struct__')]: Elixir.Kernel.SpecialForms.atom('ArgumentError') }],function() { return IO.puts('Invalid argument given'); })),null,null,null) @@ -36,10 +36,10 @@ defmodule ElixirScript.Translator.Try.Test do end js_code = """ - Kernel.SpecialForms._try(function() { + Elixir.Kernel.SpecialForms._try(function() { return do_something_that_may_fail(some_arg); - },Patterns.defmatch(Patterns.make_case([{ - [Kernel.SpecialForms.atom('__struct__')]: Kernel.SpecialForms.atom('ArgumentError') + },Elixir.Patterns.defmatch(Elixir.Patterns.make_case([{ + [Elixir.Kernel.SpecialForms.atom('__struct__')]: Elixir.Kernel.SpecialForms.atom('ArgumentError') }],function() { return IO.puts('Invalid argument given'); })),null,null,null) @@ -59,12 +59,12 @@ defmodule ElixirScript.Translator.Try.Test do end js_code = """ - Kernel.SpecialForms._try(function() { + Elixir.Kernel.SpecialForms._try(function() { return do_something_that_may_fail(some_arg); - },Patterns.defmatch(Patterns.make_case([Patterns.variable()],function(x) { + },Elixir.Patterns.defmatch(Elixir.Patterns.make_case([Elixir.Patterns.variable()],function(x) { return IO.puts('Invalid argument given'); },function(x) { - return Kernel.__in__(x,Kernel.SpecialForms.list(ArgumentError.defstruct())); + return Elixir.Kernel.__in__(x,Elixir.Kernel.SpecialForms.list(ArgumentError.defstruct(Elixir.Kernel.SpecialForms.map({})))); })),null,null,null) """ @@ -82,9 +82,9 @@ defmodule ElixirScript.Translator.Try.Test do end js_code = """ - Kernel.SpecialForms._try(function() { + Elixir.Kernel.SpecialForms._try(function() { return do_something_that_may_fail(some_arg); - },Patterns.defmatch(Patterns.make_case([Patterns.variable()],function(x) { + },Elixir.Patterns.defmatch(Elixir.Patterns.make_case([Elixir.Patterns.variable()],function(x) { return IO.puts('Invalid argument given'); })),null,null,null) """ @@ -106,13 +106,13 @@ defmodule ElixirScript.Translator.Try.Test do end js_code = """ - Kernel.SpecialForms._try(function() { + Elixir.Kernel.SpecialForms._try(function() { return do_something_that_may_fail(some_arg); - },Patterns.defmatch(Patterns.make_case([{ - [Kernel.SpecialForms.atom('__struct__')]: Kernel.SpecialForms.atom('ArgumentError') + },Elixir.Patterns.defmatch(Elixir.Patterns.make_case([{ + [Elixir.Kernel.SpecialForms.atom('__struct__')]: Elixir.Kernel.SpecialForms.atom('ArgumentError') }],function() { return IO.puts('ArgumentError'); - }),Patterns.make_case([Patterns.variable()],function(x) { + }),Elixir.Patterns.make_case([Elixir.Patterns.variable()],function(x) { return IO.puts('x'); })),null,null,null) """ @@ -133,10 +133,10 @@ defmodule ElixirScript.Translator.Try.Test do end js_code = """ - Kernel.SpecialForms._try(function() { + Elixir.Kernel.SpecialForms._try(function() { return do_something_that_may_fail(some_arg); - },Patterns.defmatch(Patterns.make_case([{ - [Kernel.SpecialForms.atom('__struct__')]: Kernel.SpecialForms.atom('ArgumentError') + },Elixir.Patterns.defmatch(Elixir.Patterns.make_case([{ + [Elixir.Kernel.SpecialForms.atom('__struct__')]: Elixir.Kernel.SpecialForms.atom('ArgumentError') }],function() { return IO.puts('Invalid argument given'); })),null,null,function() { @@ -157,7 +157,7 @@ defmodule ElixirScript.Translator.Try.Test do end js_code = """ - Kernel.SpecialForms._try(function() { + Elixir.Kernel.SpecialForms._try(function() { return do_something_that_may_fail(some_arg); },null,null,null,function() { return IO.puts('This is printed regardless if it failed or succeed'); @@ -180,14 +180,14 @@ defmodule ElixirScript.Translator.Try.Test do end js_code = """ - Kernel.SpecialForms._try(function() { + Elixir.Kernel.SpecialForms._try(function() { return 1 / x; - },null,null,Patterns.defmatch(Patterns.make_case([Patterns.variable()],function(y) { - return Kernel.SpecialForms.atom('small'); + },null,null,Elixir.Patterns.defmatch(Elixir.Patterns.make_case([Elixir.Patterns.variable()],function(y) { + return Elixir.Kernel.SpecialForms.atom('small'); },function(y) { return (y < 1) && (y > -1); - }),Patterns.make_case([Patterns.wildcard()],function() { - return Kernel.SpecialForms.atom('large'); + }),Elixir.Patterns.make_case([Elixir.Patterns.wildcard()],function() { + return Elixir.Kernel.SpecialForms.atom('large'); })),null) """ @@ -208,13 +208,13 @@ defmodule ElixirScript.Translator.Try.Test do end js_code = """ - Kernel.SpecialForms._try(function() { + Elixir.Kernel.SpecialForms._try(function() { return do_something_that_may_fail(some_arg); - },Patterns.defmatch(Patterns.make_case([{ - [Kernel.SpecialForms.atom('__struct__')]: Kernel.SpecialForms.atom('ArgumentError') + },Elixir.Patterns.defmatch(Elixir.Patterns.make_case([{ + [Elixir.Kernel.SpecialForms.atom('__struct__')]: Elixir.Kernel.SpecialForms.atom('ArgumentError') }],function() { return IO.puts('Invalid argument given'); - })),Patterns.defmatch(Patterns.make_case([Kernel.SpecialForms.atom('throw'), Kernel.SpecialForms.atom('Error')],function() { + })),Elixir.Patterns.defmatch(Elixir.Patterns.make_case([Elixir.Kernel.SpecialForms.atom('throw'), Elixir.Kernel.SpecialForms.atom('Error')],function() { return IO.puts('caught error'); })),null,null) """ diff --git a/test/translator/tuple_test.exs b/test/translator/tuple_test.exs index d1903e75..cff51110 100644 --- a/test/translator/tuple_test.exs +++ b/test/translator/tuple_test.exs @@ -4,31 +4,31 @@ defmodule ElixirScript.Translator.Tuple.Test do should "translate 2 item tuple" do ex_ast = quote do: {1, 2} - js_code = "Kernel.SpecialForms.tuple(1, 2)" + js_code = "Elixir.Kernel.SpecialForms.tuple(1, 2)" assert_translation(ex_ast, js_code) end should "translate multiple item tuple" do ex_ast = quote do: {1, 2, 3, 4, 5} - js_code = "Kernel.SpecialForms.tuple(1, 2, 3, 4, 5)" + js_code = "Elixir.Kernel.SpecialForms.tuple(1, 2, 3, 4, 5)" assert_translation(ex_ast, js_code) end should "translate tuples of different typed items" do ex_ast = quote do: {"a", "b", "c"} - js_code = "Kernel.SpecialForms.tuple('a', 'b', 'c')" + js_code = "Elixir.Kernel.SpecialForms.tuple('a', 'b', 'c')" assert_translation(ex_ast, js_code) ex_ast = quote do: {:a, :b, :c} - js_code = "Kernel.SpecialForms.tuple(Kernel.SpecialForms.atom('a'), Kernel.SpecialForms.atom('b'), Kernel.SpecialForms.atom('c'))" + js_code = "Elixir.Kernel.SpecialForms.tuple(Elixir.Kernel.SpecialForms.atom('a'), Elixir.Kernel.SpecialForms.atom('b'), Elixir.Kernel.SpecialForms.atom('c'))" assert_translation(ex_ast, js_code) ex_ast = quote do: {:a, 2, "c"} - js_code = "Kernel.SpecialForms.tuple(Kernel.SpecialForms.atom('a'), 2, 'c')" + js_code = "Elixir.Kernel.SpecialForms.tuple(Elixir.Kernel.SpecialForms.atom('a'), 2, 'c')" assert_translation(ex_ast, js_code) end From b361bb531a0078299f3aa496497a759ac4d6e0ff Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Sun, 18 Oct 2015 12:36:54 -0500 Subject: [PATCH 016/860] Updated .travis.yml --- .travis.yml | 7 ++++++- priv/javascript/lib/base.js | 2 +- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index 18001dc9..e743ec45 100644 --- a/.travis.yml +++ b/.travis.yml @@ -3,4 +3,9 @@ language: elixir elixir: - 1.1.0 otp_release: - - 18.0 \ No newline at end of file + - 18.0 +before_script: + - npm install +script: + - mix test + - gulp test \ No newline at end of file diff --git a/priv/javascript/lib/base.js b/priv/javascript/lib/base.js index 440c001c..efd92d88 100644 --- a/priv/javascript/lib/base.js +++ b/priv/javascript/lib/base.js @@ -25,7 +25,7 @@ function decode64__em__(data){ } -export { +export default { encode64, decode64, decode64__em__ From f8d8591cb06f904c199c652b19bb05e8e9d208c4 Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Sun, 18 Oct 2015 21:04:46 -0500 Subject: [PATCH 017/860] Began working on adding protocols --- lib/elixir_script/env.ex | 2 +- lib/elixir_script/preprocess/aliases.ex | 22 +-- lib/elixir_script/preprocess/modules.ex | 9 +- lib/elixir_script/state.ex | 34 ++++ lib/elixir_script/translator.ex | 16 ++ lib/elixir_script/translator/protocol.ex | 165 ++++++++++++++++++ priv/javascript/lib/kernel.js | 8 +- .../lib/patterns/patterns/checks.js | 4 + priv/javascript/lib/protocol.js | 52 ++++++ 9 files changed, 295 insertions(+), 17 deletions(-) create mode 100644 lib/elixir_script/translator/protocol.ex create mode 100644 priv/javascript/lib/protocol.js diff --git a/lib/elixir_script/env.ex b/lib/elixir_script/env.ex index c212be2d..7c319880 100644 --- a/lib/elixir_script/env.ex +++ b/lib/elixir_script/env.ex @@ -1,5 +1,5 @@ defmodule ElixirScript.Env do @moduledoc false - defstruct env: __ENV__, modules: HashSet.new, root: "" + defstruct env: __ENV__, modules: HashSet.new, root: "", protocols: HashDict.new end \ No newline at end of file diff --git a/lib/elixir_script/preprocess/aliases.ex b/lib/elixir_script/preprocess/aliases.ex index a3df468e..8e816764 100644 --- a/lib/elixir_script/preprocess/aliases.ex +++ b/lib/elixir_script/preprocess/aliases.ex @@ -33,24 +33,18 @@ defmodule ElixirScript.Preprocess.Aliases do end def process_aliases({{:., meta1, [{:__aliases__, meta2, aliases}, function]}, meta3, params} = ast, state, env) do - expanded_ast = Macro.expand(ast, env) + if ElixirScript.State.module_listed?(aliases) do + new_ast = {{:., meta1, [{:__aliases__, meta2, List.last(aliases) |> List.wrap }, function]}, meta3, params} - if expanded_ast == ast do - if ElixirScript.State.module_listed?(aliases) do - new_ast = {{:., meta1, [{:__aliases__, meta2, List.last(aliases) |> List.wrap }, function]}, meta3, params} - - new_state = if !HashSet.member?(state.defined, List.last(aliases)) do - %{ state | add: HashSet.put(state.add, aliases) } - else - state - end - - { new_ast, new_state } + new_state = if !HashSet.member?(state.defined, List.last(aliases)) do + %{ state | add: HashSet.put(state.add, aliases) } else - { ast, state } + state end + + { new_ast, new_state } else - process_aliases(expanded_ast, state, env) + { ast, state } end end diff --git a/lib/elixir_script/preprocess/modules.ex b/lib/elixir_script/preprocess/modules.ex index b12a7f0b..27fd016d 100644 --- a/lib/elixir_script/preprocess/modules.ex +++ b/lib/elixir_script/preprocess/modules.ex @@ -12,13 +12,20 @@ defmodule ElixirScript.Preprocess.Modules do end defp do_get_info({:defmodule, _, [{:__aliases__, meta, module_name_list}, [do: body]]} = ast) do - #TODO: expand macro here - body = Macro.expand(body, State.get().env) body = make_inner_module_aliases(module_name_list, body) functions = get_functions_from_module(body) macros = get_macros_from_module(body) + + body = case body do + {:__block__, _, _ } -> + Macro.expand(body, State.get().env) + _ -> + body + end mod = %ElixirScript.Module{ name: module_name_list , body: body, functions: functions, macros: macros } + State.add_module(mod) ast diff --git a/lib/elixir_script/state.ex b/lib/elixir_script/state.ex index 594ee565..99c1c613 100644 --- a/lib/elixir_script/state.ex +++ b/lib/elixir_script/state.ex @@ -29,6 +29,40 @@ defmodule ElixirScript.State do end) end + def add_protocol(name, spec) do + Agent.update(__MODULE__, fn(state) -> + proto = Dict.get(state.protocols, name) + + if proto == nil do + proto = %{name: name, spec: spec, impls: HashDict.new } + else + proto = %{ proto | spec: spec } + end + + %{ state | protocols: Dict.put(state.protocols, name, proto) } + end) + end + + def add_protocol_impl(protocol, type, impl) when is_list(type) do + Enum.each(type, fn(x) -> + add_protocol_impl(protocol, x, impl) + end) + end + + def add_protocol_impl(protocol, type, impl) do + Agent.update(__MODULE__, fn(state) -> + proto = Dict.get(state.protocols, protocol) + + if proto == nil do + proto = %{name: protocol, spec: nil, impls: HashDict.new } + end + + proto = %{ proto | impls: Dict.put(proto.impls, type, impl) } + + %{ state | protocols: Dict.put(state.protocols, protocol, proto) } + end) + end + def get() do Agent.get(__MODULE__, fn(state) -> state diff --git a/lib/elixir_script/translator.ex b/lib/elixir_script/translator.ex index cb5c569d..d564359a 100644 --- a/lib/elixir_script/translator.ex +++ b/lib/elixir_script/translator.ex @@ -285,6 +285,22 @@ defmodule ElixirScript.Translator do Module.make_module(module_name_list, body, env) end + defp do_translate({:defprotocol, _, [name, [do: {:__block__, _, spec}]]}) do + ElixirScript.State.add_protocol(name, spec) + end + + defp do_translate({:defprotocol, _, [name, [do: spec]]}) do + ElixirScript.State.add_protocol(name, [spec]) + end + + defp do_translate({:defimpl, _, protocol, [ [for: type], [do: {:__block__, _, spec}] ]}) do + ElixirScript.State.add_protocol_impl(name, type, spec) + end + + defp do_translate({:defimpl, _, protocol, [ [for: type], [do: spec] ]}) do + ElixirScript.State.add_protocol_impl(name, type, [spec]) + end + defp do_translate({name, metadata, params} = ast, env) when is_list(params) do if KernelLib.is_defined_in_kernel(name, length(params)) do KernelLib.translate_kernel_function(name, params, env) diff --git a/lib/elixir_script/translator/protocol.ex b/lib/elixir_script/translator/protocol.ex new file mode 100644 index 00000000..fc9425a0 --- /dev/null +++ b/lib/elixir_script/translator/protocol.ex @@ -0,0 +1,165 @@ +defmodule ElixirScript.Translator.Protocol do + @moduledoc false + + alias ESTree.Tools.Builder, as: JS + +#defprotocol ElixirScript.String.Chars do +# def to_string(thing) +#end +# +#defprotocol ElixirScript.List.Chars do +# def to_char_list(thing) +#end +# +#defprotocol ElixirScript.Inspect do +# def inspect(thing, opts) +#end +# +#defprotocol ElixirScript.Enumerable do +# def count(collection) +# +# def member?(collection, value) +# +# def reduce(collection, acc, fun) +#end +# +#defprotocol ElixirScript.Collectable do +# def into(collectable) +#end + + + @doc """ + import * as Elixir from "elixir"; + + const __MODULE__ = [Elixir.Kernel.SpecialForms.atom("Collectable")]; + + Collectable = Elixir.Protocol.defprotocol({ + into: function(collectable){} + }); + + Collectable.impl(Array, { + into: function(collectable){ + return collectable.push(a); + } + }); + + export Collectable; + """ + def consolidate(protocol) do + name = protocol.name + spec = protocol.spec + impls = protocol.impls + end + + + @doc """ + Used to map Protocol types from Elixir to + a function used by the protocol implementation + in JavaScript + """ + def map_to_js({:__aliases__, _, [:Integer]}) do + quoted = quote do + &Kernel.is_integer/1 + end + + Translator.translate(quoted, ElixirScript.State.get().env) + end + + def map_to_js({:__aliases__, _, [:Tuple]}) do + quoted = quote do + &Kernel.is_tuple/1 + end + + Translator.translate(quoted, ElixirScript.State.get().env) + end + + def map_to_js({:__aliases__, _, [:Atom]}) do + quoted = quote do + &Kernel.is_atom/1 + end + + Translator.translate(quoted, ElixirScript.State.get().env) + end + + def map_to_js({:__aliases__, _, [:List]}) do + quoted = quote do + &Kernel.is_list/1 + end + + Translator.translate(quoted, ElixirScript.State.get().env) + end + + def map_to_js({:__aliases__, _, [:BitString]}) do + quoted = quote do + &Kernel.is_bitstring/1 + end + + Translator.translate(quoted, ElixirScript.State.get().env) + end + + def map_to_js({:__aliases__, _, [:Float]}) do + quoted = quote do + &Kernel.is_float/1 + end + + Translator.translate(quoted, ElixirScript.State.get().env) + end + + def map_to_js({:__aliases__, _, [:Function]}) do + quoted = quote do + &Kernel.is_function/1 + end + + Translator.translate(quoted, ElixirScript.State.get().env) + end + + def map_to_js({:__aliases__, _, [:PID]}) do + quoted = quote do + &Kernel.is_pid/1 + end + + Translator.translate(quoted, ElixirScript.State.get().env) + end + + def map_to_js({:__aliases__, _, [:Port]}) do + quoted = quote do + &Kernel.is_port/1 + end + + Translator.translate(quoted, ElixirScript.State.get().env) + end + + def map_to_js({:__aliases__, _, [:Reference]}) do + quoted = quote do + &Kernel.is_reference/1 + end + + Translator.translate(quoted, ElixirScript.State.get().env) + end + + def map_to_js({:__aliases__, _, [:Map]}) do + quoted = quote do + &Kernel.is_map/1 + end + + Translator.translate(quoted, ElixirScript.State.get().env) + end + + def map_to_js({:__aliases__, _, [:Any]}) do + quoted = quote do + nil + end + + Translator.translate(quoted, ElixirScript.State.get().env) + end + + + def map_to_js({:__aliases__, _, struct}) do + quoted = quote do + Kernel.is_struct_fn(unquote(List.last(struct))) + end + + Translator.translate(quoted, ElixirScript.State.get().env) + end + +end \ No newline at end of file diff --git a/priv/javascript/lib/kernel.js b/priv/javascript/lib/kernel.js index 3cf128a9..27218cef 100644 --- a/priv/javascript/lib/kernel.js +++ b/priv/javascript/lib/kernel.js @@ -150,7 +150,13 @@ let Kernel = { defstruct: function(defaults, values){ return Kernel.SpecialForms.map_update(defaults, values); - } + }, + + is_struct_fn: function(__struct__){ + return function(x){ + return Kernel.is_map && x[Kernel.SpecialForms.atom("__struct__")] === __struct__; + } + }, }; export default Kernel; diff --git a/priv/javascript/lib/patterns/patterns/checks.js b/priv/javascript/lib/patterns/patterns/checks.js index 72a96485..50e67f33 100644 --- a/priv/javascript/lib/patterns/patterns/checks.js +++ b/priv/javascript/lib/patterns/patterns/checks.js @@ -71,6 +71,10 @@ function is_array(value: any): boolean { return Array.isArray(value); } +function is_struct(__struct__: Symbol, value: any): boolean { + return is_object(value) && value[Symbol.for("__struct__")] === __struct__; +} + export default { is_number, is_string, diff --git a/priv/javascript/lib/protocol.js b/priv/javascript/lib/protocol.js new file mode 100644 index 00000000..6d3d5b0f --- /dev/null +++ b/priv/javascript/lib/protocol.js @@ -0,0 +1,52 @@ +//https://github.com/airportyh/protomorphism +class Protocol{ + constructor(spec){ + this.registry = []; + this.fallback = null; + + for (let funName in spec){ + this[funName] = createFun(funName).bind(this); + } + + function createFun(funName){ + + return function(...args) { + let thing = args[0]; + + for([check, implementation] of this.registry){ + if(check(thing)){ + let fun = implementation[funName]; + let retval = fun.apply(this, args); + return retval; + } + } + + if(this.fallback){ + let fun = fallback; + let retval = fun.apply(this, args); + return retval; + } + + throw new Error("No implementation found for " + thing); + } + } + } + + implementation(type, implementation){ + if(type === null){ + this.fallback = implementation; + }else{ + this.registry.push([type, implementation]); + } + } +} + + +function defprotocol(spec){ + return new Protocol(spec); +} + + +export default { + defprotocol +} \ No newline at end of file From 3b37cc1b37fd4253264a08ba0322832b2add069a Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Sun, 18 Oct 2015 21:28:39 -0500 Subject: [PATCH 018/860] translating modules in their own processes --- lib/elixir_script.ex | 18 +++++++++++++----- lib/elixir_script/preprocess/modules.ex | 16 ++++++++++++++++ lib/elixir_script/translator.ex | 16 ---------------- 3 files changed, 29 insertions(+), 21 deletions(-) diff --git a/lib/elixir_script.ex b/lib/elixir_script.ex index 6473fed7..8d714031 100644 --- a/lib/elixir_script.ex +++ b/lib/elixir_script.ex @@ -114,13 +114,21 @@ defmodule ElixirScript do defp create_code(include_path, import_standard_libs?) do state = ElixirScript.State.get() - result = Enum.map(state.modules, fn(x) -> - ElixirScript.Translator.Module.make_module(x.name, x.body, state.env) - end) - |> List.flatten + current = self + + result = state.modules |> Enum.map(fn(x) -> - convert_to_code(x, state.root, include_path, state.env, import_standard_libs?) + result = ElixirScript.Translator.Module.make_module(x.name, x.body, state.env) + |> Enum.map(fn(x) -> + convert_to_code(x, state.root, include_path, state.env, import_standard_libs?) + end) + + spawn_link fn -> (send current, { self, result }) end + end) + |> Enum.map(fn (pid) -> + receive do { ^pid, x } -> x end end) + |> List.flatten ElixirScript.State.stop diff --git a/lib/elixir_script/preprocess/modules.ex b/lib/elixir_script/preprocess/modules.ex index 27fd016d..f35b98d1 100644 --- a/lib/elixir_script/preprocess/modules.ex +++ b/lib/elixir_script/preprocess/modules.ex @@ -11,6 +11,22 @@ defmodule ElixirScript.Preprocess.Modules do end) end + defp do_get_info({:defprotocol, _, [name, [do: {:__block__, _, spec}]]}) do + State.add_protocol(name, spec) + end + + defp do_get_info({:defprotocol, _, [name, [do: spec]]}) do + State.add_protocol(name, [spec]) + end + + defp do_get_info({:defimpl, _, protocol, [ [for: type], [do: {:__block__, _, spec}] ]}) do + State.add_protocol_impl(protocol, type, spec) + end + + defp do_get_info({:defimpl, _, protocol, [ [for: type], [do: spec] ]}) do + State.add_protocol_impl(protocol, type, [spec]) + end + defp do_get_info({:defmodule, _, [{:__aliases__, meta, module_name_list}, [do: body]]} = ast) do body = make_inner_module_aliases(module_name_list, body) diff --git a/lib/elixir_script/translator.ex b/lib/elixir_script/translator.ex index d564359a..cb5c569d 100644 --- a/lib/elixir_script/translator.ex +++ b/lib/elixir_script/translator.ex @@ -285,22 +285,6 @@ defmodule ElixirScript.Translator do Module.make_module(module_name_list, body, env) end - defp do_translate({:defprotocol, _, [name, [do: {:__block__, _, spec}]]}) do - ElixirScript.State.add_protocol(name, spec) - end - - defp do_translate({:defprotocol, _, [name, [do: spec]]}) do - ElixirScript.State.add_protocol(name, [spec]) - end - - defp do_translate({:defimpl, _, protocol, [ [for: type], [do: {:__block__, _, spec}] ]}) do - ElixirScript.State.add_protocol_impl(name, type, spec) - end - - defp do_translate({:defimpl, _, protocol, [ [for: type], [do: spec] ]}) do - ElixirScript.State.add_protocol_impl(name, type, [spec]) - end - defp do_translate({name, metadata, params} = ast, env) when is_list(params) do if KernelLib.is_defined_in_kernel(name, length(params)) do KernelLib.translate_kernel_function(name, params, env) From a94e490c4e967f205656ff8edea98e6f21dc44bf Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Tue, 20 Oct 2015 17:59:29 -0500 Subject: [PATCH 019/860] Got protocols translating --- lib/elixir_script.ex | 27 ++- lib/elixir_script/preprocess/modules.ex | 20 +- lib/elixir_script/state.ex | 3 +- lib/elixir_script/translator.ex | 8 + lib/elixir_script/translator/function.ex | 5 + lib/elixir_script/translator/module.ex | 23 ++- lib/elixir_script/translator/protocol.ex | 245 +++++++++++++++++++++-- priv/javascript/lib/kernel.js | 9 + priv/javascript/lib/protocol.js | 9 +- test/elixir_script_test.exs | 4 +- test/test_helper.exs | 2 +- test/translator/bug_test.exs | 2 +- test/translator/defmodule_test.exs | 14 +- test/translator/protocol_test.exs | 102 ++++++++++ 14 files changed, 411 insertions(+), 62 deletions(-) create mode 100644 test/translator/protocol_test.exs diff --git a/lib/elixir_script.ex b/lib/elixir_script.ex index 8d714031..5840ef0e 100644 --- a/lib/elixir_script.ex +++ b/lib/elixir_script.ex @@ -43,13 +43,16 @@ defmodule ElixirScript do root = Dict.get(opts, :root) env = Dict.get(opts, :env, custom_env) import_standard_libs? = Dict.get(opts, :import_standard_libs, true) + use_default_protocols? = Dict.get(opts, :use_default_protocols, true) ElixirScript.State.start_link(root, env) build_environment([quoted]) - if Set.size(ElixirScript.State.get().modules) > 0 do - create_code(include_path, import_standard_libs?) + state = ElixirScript.State.get() + + if Set.size(state.modules) > 0 || Dict.size(state.protocols) > 0 do + create_code(include_path, import_standard_libs?, use_default_protocols?) else result = case Translator.translate(quoted, env) do modules when is_list(modules) -> @@ -97,12 +100,12 @@ defmodule ElixirScript do |> build_environment - create_code(include_path, true) + create_code(include_path, true, true) end defp build_environment(code_list) do code_list - |> ElixirScript.Preprocess.Modules.get_info + |> ElixirScript.Preprocess.Modules.get_info end defp custom_env() do @@ -111,7 +114,12 @@ defmodule ElixirScript do __ENV__ end - defp create_code(include_path, import_standard_libs?) do + defp create_code(include_path, import_standard_libs?, use_default_protocols?) do + + if use_default_protocols? do + ElixirScript.Translator.Protocol.add_default_protocols() + end + state = ElixirScript.State.get() current = self @@ -130,9 +138,16 @@ defmodule ElixirScript do end) |> List.flatten + protocol_result = state.protocols |> Dict.to_list + |> ElixirScript.Translator.Protocol.consolidate(state.env) + |> Enum.map(fn(x) -> + convert_to_code(x, state.root, include_path, state.env, import_standard_libs?) + end) + |> List.flatten + ElixirScript.State.stop - result + result ++ protocol_result end @doc """ diff --git a/lib/elixir_script/preprocess/modules.ex b/lib/elixir_script/preprocess/modules.ex index f35b98d1..31eda4f9 100644 --- a/lib/elixir_script/preprocess/modules.ex +++ b/lib/elixir_script/preprocess/modules.ex @@ -11,23 +11,23 @@ defmodule ElixirScript.Preprocess.Modules do end) end - defp do_get_info({:defprotocol, _, [name, [do: {:__block__, _, spec}]]}) do - State.add_protocol(name, spec) + def do_get_info({:defprotocol, _, [name, [do: {:__block__, context, spec}]]}) do + ElixirScript.State.add_protocol(name, {:__block__, context, spec}) end - defp do_get_info({:defprotocol, _, [name, [do: spec]]}) do - State.add_protocol(name, [spec]) + def do_get_info({:defprotocol, _, [name, [do: spec]]}) do + ElixirScript.State.add_protocol(name, {:__block__, [], [spec]}) end - defp do_get_info({:defimpl, _, protocol, [ [for: type], [do: {:__block__, _, spec}] ]}) do - State.add_protocol_impl(protocol, type, spec) + def do_get_info({:defimpl, _, [ protocol, [for: type], [do: {:__block__, context, spec}] ]}) do + ElixirScript.State.add_protocol_impl(protocol, type, {:__block__, context, spec}) end - defp do_get_info({:defimpl, _, protocol, [ [for: type], [do: spec] ]}) do - State.add_protocol_impl(protocol, type, [spec]) + def do_get_info({:defimpl, _, [ protocol, [for: type], [do: spec] ]}) do + ElixirScript.State.add_protocol_impl(protocol, type, {:__block__, [], [spec]}) end - defp do_get_info({:defmodule, _, [{:__aliases__, meta, module_name_list}, [do: body]]} = ast) do + def do_get_info({:defmodule, _, [{:__aliases__, meta, module_name_list}, [do: body]]} = ast) do body = make_inner_module_aliases(module_name_list, body) functions = get_functions_from_module(body) @@ -47,7 +47,7 @@ defmodule ElixirScript.Preprocess.Modules do ast end - defp do_get_info(ast) do + def do_get_info(ast) do ast end diff --git a/lib/elixir_script/state.ex b/lib/elixir_script/state.ex index 99c1c613..06362787 100644 --- a/lib/elixir_script/state.ex +++ b/lib/elixir_script/state.ex @@ -25,7 +25,8 @@ defmodule ElixirScript.State do def module_listed?(module_name) do Agent.get(__MODULE__, fn(state) -> - Enum.any?(state.modules, fn(x) -> x.name == module_name end) + Enum.any?(state.modules, fn(x) -> x.name == module_name end) || + Enum.any?(state.protocols, fn({key, value}) -> key == module_name end) end) end diff --git a/lib/elixir_script/translator.ex b/lib/elixir_script/translator.ex index cb5c569d..27093a22 100644 --- a/lib/elixir_script/translator.ex +++ b/lib/elixir_script/translator.ex @@ -285,6 +285,14 @@ defmodule ElixirScript.Translator do Module.make_module(module_name_list, body, env) end + defp do_translate({:defprotocol, _, _}) do + %ElixirScript.Translator.Group{} + end + + defp do_translate({:defimpl, _, _}) do + %ElixirScript.Translator.Group{} + end + defp do_translate({name, metadata, params} = ast, env) when is_list(params) do if KernelLib.is_defined_in_kernel(name, length(params)) do KernelLib.translate_kernel_function(name, params, env) diff --git a/lib/elixir_script/translator/function.ex b/lib/elixir_script/translator/function.ex index 763c398b..236608ed 100644 --- a/lib/elixir_script/translator/function.ex +++ b/lib/elixir_script/translator/function.ex @@ -75,6 +75,11 @@ defmodule ElixirScript.Translator.Function do body = make_function_body(body, env) do_make_function_clause(patterns, params, body) + ({_, _, [{_, _, params}]}) -> + { patterns, params } = Match.build_match(params, env) + params = make_params(params) + body = make_function_body([], env) + do_make_function_clause(patterns, params, body) end) |> Enum.to_list diff --git a/lib/elixir_script/translator/module.ex b/lib/elixir_script/translator/module.ex index 0c50784f..9fdbaa07 100644 --- a/lib/elixir_script/translator/module.ex +++ b/lib/elixir_script/translator/module.ex @@ -7,6 +7,7 @@ defmodule ElixirScript.Translator.Module do alias ElixirScript.Preprocess.Aliases alias ElixirScript.Preprocess.Using alias ElixirScript.Translator.Function + alias ElixirScript.Translator.Primitive def make_module(module_name_list, nil, env) do [%JSModule{ name: module_name_list, body: List.wrap(create__module__(module_name_list, env)) }] @@ -82,7 +83,7 @@ defmodule ElixirScript.Translator.Module do result end - defp extract_functions_from_module({:__block__, meta, body_list}) do + def extract_functions_from_module({:__block__, meta, body_list}) do { body_list, functions } = Enum.map_reduce(body_list, %{exported: HashDict.new(), private: HashDict.new()}, fn ({:def, _, [{:when, _, [{name, _, _} | _guards] }, _] } = function, state) -> @@ -104,7 +105,7 @@ defmodule ElixirScript.Translator.Module do { nil, %{ state | private: HashDict.put(state.private, name, HashDict.get(state.private, name, []) ++ [function]) } - } + } (x, state) -> { x, state } end) @@ -115,11 +116,11 @@ defmodule ElixirScript.Translator.Module do { body, functions } end - defp extract_functions_from_module(body) do + def extract_functions_from_module(body) do extract_functions_from_module({:__block__, [], List.wrap(body)}) end - defp extract_imports_from_body(body) do + def extract_imports_from_body(body) do Enum.partition(body, fn(x) -> case x do %ESTree.ImportDeclaration{} -> @@ -130,7 +131,7 @@ defmodule ElixirScript.Translator.Module do end) end - defp extract_structs_from_body(body) do + def extract_structs_from_body(body) do Enum.partition(body, fn(x) -> case x do %ESTree.FunctionDeclaration{} -> @@ -154,7 +155,7 @@ defmodule ElixirScript.Translator.Module do end end - defp process_imports(imports, aliases) do + def process_imports(imports, aliases) do imports ++ make_imports(aliases) |> Enum.reduce(HashSet.new, fn(x, acc)-> HashSet.put(acc, x) @@ -180,7 +181,7 @@ defmodule ElixirScript.Translator.Module do end) end - defp process_functions(%{ exported: exported, private: private }, env) do + def process_functions(%{ exported: exported, private: private }, env) do exported_functions = Enum.map(Dict.keys(exported), fn(key) -> functions = Dict.get(exported, key) { key, Function.process_function(key, functions, env) } @@ -203,10 +204,14 @@ defmodule ElixirScript.Translator.Module do JS.variable_declaration([declarator], :const) end - defp create__module__(module_name_list, env) do + def create__module__(module_name_list, env) do + module_name = Enum.map(module_name_list, &Atom.to_string(&1)) + |> Enum.join(".") + |> String.to_atom + declarator = JS.variable_declarator( JS.identifier(:__MODULE__), - ElixirScript.Translator.translate(List.last(module_name_list), env) + Primitive.make_atom(module_name) ) JS.variable_declaration([declarator], :const) diff --git a/lib/elixir_script/translator/protocol.ex b/lib/elixir_script/translator/protocol.ex index fc9425a0..0e1d6207 100644 --- a/lib/elixir_script/translator/protocol.ex +++ b/lib/elixir_script/translator/protocol.ex @@ -1,7 +1,67 @@ defmodule ElixirScript.Translator.Protocol do @moduledoc false - alias ESTree.Tools.Builder, as: JS +alias ESTree.Tools.Builder, as: JS +alias ElixirScript.Translator +alias ElixirScript.Translator.Module +alias ElixirScript.Preprocess.Aliases +alias ElixirScript.Translator.JSModule +alias ElixirScript.Translator.Map +alias ElixirScript.Translator.Function +alias ElixirScript.Translator.Utils + + +def add_default_protocols() do + quoted = quote do + defprotocol ElixirScript.String.Chars do + def to_string(thing) + end + end + + ElixirScript.Preprocess.Modules.do_get_info(quoted) + + quoted = quote do + defprotocol ElixirScript.List.Chars do + def to_char_list(thing) + end + end + + ElixirScript.Preprocess.Modules.do_get_info(quoted) + + quoted = quote do + defprotocol ElixirScript.Inspect do + def inspect(thing, opts) + end + end + + ElixirScript.Preprocess.Modules.do_get_info(quoted) + + quoted = quote do + defprotocol ElixirScript.Enumerable do + def count(collection) + + def member?(collection, value) + + def reduce(collection, acc, fun) + end + end + + ElixirScript.Preprocess.Modules.do_get_info(quoted) + + quoted = quote do + defprotocol ElixirScript.Collectable do + def into(collectable) + end + end + + ElixirScript.Preprocess.Modules.do_get_info(quoted) +end + +def consolidate(protocols, env) when is_list(protocols) do + Enum.map(protocols, fn({_, protocol}) -> + do_consolidate(protocol, env) + end) +end #defprotocol ElixirScript.String.Chars do # def to_string(thing) @@ -44,11 +104,162 @@ defmodule ElixirScript.Translator.Protocol do }); export Collectable; + { body, aliases } = Aliases.process(body, env) """ - def consolidate(protocol) do - name = protocol.name + defp do_consolidate(protocol, env) do + {:__aliases__, _, name} = protocol.name spec = protocol.spec - impls = protocol.impls + impls = protocol.impls |> Dict.to_list + + {spec_imports, spec_body, spec} = define_spec(name, spec, env) + {impl_imports, impl_body, impls} = define_impls(name, impls, env) + + body = spec_body ++ impl_body + imports = spec_imports ++ impl_imports + + create_module(name, spec, impls, imports, body, env) + end + + defp define_spec(name, spec, env) do + + { body, aliases } = Aliases.process(spec, env) + + { body, functions } = extract_function_from_spec(body) + + { exported_functions, private_functions } = process_functions(functions, env) + + body = Translator.translate(body, env) + + body = case body do + [%ESTree.BlockStatement{ body: body }] -> + body + %ESTree.BlockStatement{ body: body } -> + body + _ -> + List.wrap(body) + end + + {imports, body} = Module.extract_imports_from_body(body) + + imports = Module.process_imports(imports, aliases) + imports = imports.imports + + object = Enum.map(exported_functions, fn({key, value}) -> + Map.make_property(JS.identifier(Utils.filter_name(key)), value) + end) + |> JS.object_expression + + declarator = JS.variable_declarator( + JS.identifier(List.last(name)), + JS.call_expression( + JS.member_expression( + JS.identifier(:Elixir), + JS.member_expression( + JS.identifier(:Kernel), + JS.identifier(:defprotocol) + ) + ), + [object] + ) + ) + + {imports, body, [JS.variable_declaration([declarator], :let)]} + end + + defp define_impls(_, [], _) do + { [], [], [] } + end + + defp define_impls(name, impls, env) do + Enum.map(impls, fn({type, impl}) -> + type = map_to_js(type) + { body, aliases } = Aliases.process(impl, env) + { body, functions } = Module.extract_functions_from_module(body) + { exported_functions, private_functions } = process_functions(functions, env) + + body = Translator.translate(body, env) + + body = case body do + [%ESTree.BlockStatement{ body: body }] -> + body + %ESTree.BlockStatement{ body: body } -> + body + _ -> + List.wrap(body) + end + + {imports, body} = Module.extract_imports_from_body(body) + + imports = Module.process_imports(imports, aliases) + imports = imports.imports + + object = Enum.map(exported_functions, fn({key, value}) -> + Map.make_property(JS.identifier(Utils.filter_name(key)), value) + end) + |> JS.object_expression + + impl = JS.call_expression( + JS.member_expression( + JS.identifier(:Elixir), + JS.member_expression( + JS.identifier(:Kernel), + JS.identifier(:defimpl) + ) + ), + [JS.identifier(List.last(name)), type, object] + ) + + {imports, body, [impl]} + + end) + |> Enum.reduce({[], [], []}, fn({impl_imports, impl_body, impl}, acc) -> + { + elem(acc, 0) ++ impl_imports, + elem(acc, 1) ++ impl_body, + elem(acc, 2) ++ impl + } + end) + end + + defp create_module(name, spec, impls, imports, body, env) do + default = JS.export_named_declaration(JS.identifier(List.last(name))) + + %JSModule{ + name: name, + body: imports ++ List.wrap(Module.create__module__(name, env)) ++ body ++ spec ++ impls ++ [default] + } + end + + defp extract_function_from_spec({:__block__, meta, body_list}) do + { body_list, functions } = Enum.map_reduce(body_list, + %{exported: HashDict.new(), private: HashDict.new()}, fn + ({:def, _, [{name, _, _}]} = function, state) -> + { + nil, + %{ state | exported: HashDict.put(state.exported, name, HashDict.get(state.exported, name, []) ++ [function]) } + } + (x, state) -> + { x, state } + end) + + body_list = Enum.filter(body_list, fn(x) -> !is_nil(x) end) + body = {:__block__, meta, body_list} + + { body, functions } + end + + defp process_functions(%{ exported: exported, private: private }, env) do + exported_functions = Enum.map(Dict.keys(exported), fn(key) -> + functions = Dict.get(exported, key) + { key, Function.make_anonymous_function(functions, env) } + end) + + private_functions = Enum.map(Dict.keys(private), fn(key) -> + functions = Dict.get(private, key) + { key, Function.make_anonymous_function(functions, env) } + end) + + { exported_functions, private_functions } end @@ -57,7 +268,7 @@ defmodule ElixirScript.Translator.Protocol do a function used by the protocol implementation in JavaScript """ - def map_to_js({:__aliases__, _, [:Integer]}) do + defp map_to_js({:__aliases__, _, [:Integer]}) do quoted = quote do &Kernel.is_integer/1 end @@ -65,7 +276,7 @@ defmodule ElixirScript.Translator.Protocol do Translator.translate(quoted, ElixirScript.State.get().env) end - def map_to_js({:__aliases__, _, [:Tuple]}) do + defp map_to_js({:__aliases__, _, [:Tuple]}) do quoted = quote do &Kernel.is_tuple/1 end @@ -73,7 +284,7 @@ defmodule ElixirScript.Translator.Protocol do Translator.translate(quoted, ElixirScript.State.get().env) end - def map_to_js({:__aliases__, _, [:Atom]}) do + defp map_to_js({:__aliases__, _, [:Atom]}) do quoted = quote do &Kernel.is_atom/1 end @@ -81,7 +292,7 @@ defmodule ElixirScript.Translator.Protocol do Translator.translate(quoted, ElixirScript.State.get().env) end - def map_to_js({:__aliases__, _, [:List]}) do + defp map_to_js({:__aliases__, _, [:List]}) do quoted = quote do &Kernel.is_list/1 end @@ -89,7 +300,7 @@ defmodule ElixirScript.Translator.Protocol do Translator.translate(quoted, ElixirScript.State.get().env) end - def map_to_js({:__aliases__, _, [:BitString]}) do + defp map_to_js({:__aliases__, _, [:BitString]}) do quoted = quote do &Kernel.is_bitstring/1 end @@ -97,7 +308,7 @@ defmodule ElixirScript.Translator.Protocol do Translator.translate(quoted, ElixirScript.State.get().env) end - def map_to_js({:__aliases__, _, [:Float]}) do + defp map_to_js({:__aliases__, _, [:Float]}) do quoted = quote do &Kernel.is_float/1 end @@ -105,7 +316,7 @@ defmodule ElixirScript.Translator.Protocol do Translator.translate(quoted, ElixirScript.State.get().env) end - def map_to_js({:__aliases__, _, [:Function]}) do + defp map_to_js({:__aliases__, _, [:Function]}) do quoted = quote do &Kernel.is_function/1 end @@ -113,7 +324,7 @@ defmodule ElixirScript.Translator.Protocol do Translator.translate(quoted, ElixirScript.State.get().env) end - def map_to_js({:__aliases__, _, [:PID]}) do + defp map_to_js({:__aliases__, _, [:PID]}) do quoted = quote do &Kernel.is_pid/1 end @@ -121,7 +332,7 @@ defmodule ElixirScript.Translator.Protocol do Translator.translate(quoted, ElixirScript.State.get().env) end - def map_to_js({:__aliases__, _, [:Port]}) do + defp map_to_js({:__aliases__, _, [:Port]}) do quoted = quote do &Kernel.is_port/1 end @@ -129,7 +340,7 @@ defmodule ElixirScript.Translator.Protocol do Translator.translate(quoted, ElixirScript.State.get().env) end - def map_to_js({:__aliases__, _, [:Reference]}) do + defp map_to_js({:__aliases__, _, [:Reference]}) do quoted = quote do &Kernel.is_reference/1 end @@ -137,7 +348,7 @@ defmodule ElixirScript.Translator.Protocol do Translator.translate(quoted, ElixirScript.State.get().env) end - def map_to_js({:__aliases__, _, [:Map]}) do + defp map_to_js({:__aliases__, _, [:Map]}) do quoted = quote do &Kernel.is_map/1 end @@ -145,7 +356,7 @@ defmodule ElixirScript.Translator.Protocol do Translator.translate(quoted, ElixirScript.State.get().env) end - def map_to_js({:__aliases__, _, [:Any]}) do + defp map_to_js({:__aliases__, _, [:Any]}) do quoted = quote do nil end @@ -154,7 +365,7 @@ defmodule ElixirScript.Translator.Protocol do end - def map_to_js({:__aliases__, _, struct}) do + defp map_to_js({:__aliases__, _, struct}) do quoted = quote do Kernel.is_struct_fn(unquote(List.last(struct))) end diff --git a/priv/javascript/lib/kernel.js b/priv/javascript/lib/kernel.js index 27218cef..292d295a 100644 --- a/priv/javascript/lib/kernel.js +++ b/priv/javascript/lib/kernel.js @@ -1,6 +1,7 @@ import SpecialForms from './kernel/special_forms'; import Patterns from './patterns/patterns'; import Tuple from './tuple'; +import Protocol from './protocol'; let Kernel = { SpecialForms: SpecialForms, @@ -157,6 +158,14 @@ let Kernel = { return Kernel.is_map && x[Kernel.SpecialForms.atom("__struct__")] === __struct__; } }, + + defprotocol: function(spec){ + return new Protocol(spec); + }, + + defimpl: function(protocol, type, impl){ + protocol.implementation(type, impl); + } }; export default Kernel; diff --git a/priv/javascript/lib/protocol.js b/priv/javascript/lib/protocol.js index 6d3d5b0f..d44fcbbe 100644 --- a/priv/javascript/lib/protocol.js +++ b/priv/javascript/lib/protocol.js @@ -42,11 +42,4 @@ class Protocol{ } -function defprotocol(spec){ - return new Protocol(spec); -} - - -export default { - defprotocol -} \ No newline at end of file +export default Protocol; \ No newline at end of file diff --git a/test/elixir_script_test.exs b/test/elixir_script_test.exs index 4b2c8b01..994ddffa 100644 --- a/test/elixir_script_test.exs +++ b/test/elixir_script_test.exs @@ -78,7 +78,7 @@ defmodule ElixirScript.Test do assert_js_matches """ import * as Elixir from 'elixir'; - const __MODULE__ = Elixir.Kernel.SpecialForms.atom('Elephant'); + const __MODULE__ = Elixir.Kernel.SpecialForms.atom('Animals.Elephant'); function defstruct(values = {}) { return Kernel.defstruct({ [Elixir.Kernel.SpecialForms.atom('__struct__')]: __MODULE__, [Elixir.Kernel.SpecialForms.atom('trunk')]: true @@ -87,7 +87,7 @@ defmodule ElixirScript.Test do export { defstruct }; - """, List.last(js_code) + """, Enum.fetch!(js_code, 1) end diff --git a/test/test_helper.exs b/test/test_helper.exs index 14417b8f..7c74cc10 100644 --- a/test/test_helper.exs +++ b/test/test_helper.exs @@ -32,7 +32,7 @@ defmodule ElixirScript.TestHelper do end def ex_ast_to_js(ex_ast) do - ElixirScript.compile_quoted(ex_ast, [env: make_custom_env, import_standard_libs: false]) + ElixirScript.compile_quoted(ex_ast, [env: make_custom_env, import_standard_libs: false, use_default_protocols: false]) end def strip_spaces(js) do diff --git a/test/translator/bug_test.exs b/test/translator/bug_test.exs index 07b40f4a..856b4aeb 100644 --- a/test/translator/bug_test.exs +++ b/test/translator/bug_test.exs @@ -31,7 +31,7 @@ defmodule ElixirScript.Translator.Bug.Test do js_code = """ import { default as JQuery } from 'jquery'; - const __MODULE__ = Elixir.Kernel.SpecialForms.atom('Todo'); + const __MODULE__ = Elixir.Kernel.SpecialForms.atom('App.Todo'); JQuery(Elixir.JS.call_property(e, 'target')); export {}; diff --git a/test/translator/defmodule_test.exs b/test/translator/defmodule_test.exs index c1c08aa1..7fc635a7 100644 --- a/test/translator/defmodule_test.exs +++ b/test/translator/defmodule_test.exs @@ -95,7 +95,7 @@ defmodule ElixirScript.Translator.Defmodule.Test do end js_code = """ - const __MODULE__ = Elixir.Kernel.SpecialForms.atom('Elephant'); + const __MODULE__ = Elixir.Kernel.SpecialForms.atom('Animals.Elephant'); function defstruct(values = {}) { return Kernel.defstruct({ [Elixir.Kernel.SpecialForms.atom('__struct__')]: __MODULE__, [Elixir.Kernel.SpecialForms.atom('trunk')]: true @@ -147,7 +147,7 @@ defmodule ElixirScript.Translator.Defmodule.Test do end js_code = """ - const __MODULE__ = Elixir.Kernel.SpecialForms.atom('Bear'); + const __MODULE__ = Elixir.Kernel.SpecialForms.atom('Elephant.Bear'); function defstruct(values = {}) { return Kernel.defstruct({ [Elixir.Kernel.SpecialForms.atom('__struct__')]: __MODULE__, [Elixir.Kernel.SpecialForms.atom('trunk')]: true @@ -158,7 +158,7 @@ defmodule ElixirScript.Translator.Defmodule.Test do }; import * as Bear from 'elephant/bear'; - const __MODULE__ = Elixir.Kernel.SpecialForms.atom('Elephant'); + const __MODULE__ = Elixir.Kernel.SpecialForms.atom('Animals.Elephant'); function defstruct(values = {}) { return Kernel.defstruct({ [Elixir.Kernel.SpecialForms.atom('__struct__')]: __MODULE__, [Elixir.Kernel.SpecialForms.atom('trunk')]: true @@ -201,7 +201,7 @@ defmodule ElixirScript.Translator.Defmodule.Test do Elixir.JS.call_property(Tigers,'oh_my'); export {}; - const __MODULE__ = Elixir.Kernel.SpecialForms.atom('Tigers'); + const __MODULE__ = Elixir.Kernel.SpecialForms.atom('Lions.Tigers'); Elixir.JS.call_property(Lions.Tigers.Bears,'oh_my'); export {}; """ @@ -226,7 +226,7 @@ defmodule ElixirScript.Translator.Defmodule.Test do end js_code = """ - const __MODULE__ = Elixir.Kernel.SpecialForms.atom('Tigers'); + const __MODULE__ = Elixir.Kernel.SpecialForms.atom('Lions.Tigers'); const oh_my = Elixir.Patterns.defmatch(Elixir.Patterns.make_case([],function() { return null; })); @@ -267,7 +267,7 @@ defmodule ElixirScript.Translator.Defmodule.Test do oh_my(); export {}; - const __MODULE__ = Elixir.Kernel.SpecialForms.atom('Tigers'); + const __MODULE__ = Elixir.Kernel.SpecialForms.atom('Lions.Tigers'); const oh_my2 = Elixir.Patterns.defmatch(Elixir.Patterns.make_case([],function() { return null; })); @@ -300,7 +300,7 @@ defmodule ElixirScript.Translator.Defmodule.Test do end js_code = """ - const __MODULE__ = Elixir.Kernel.SpecialForms.atom('Tigers'); + const __MODULE__ = Elixir.Kernel.SpecialForms.atom('Lions.Tigers'); const oh_my2 = Elixir.Patterns.defmatch(Elixir.Patterns.make_case([],function() { return null; })); diff --git a/test/translator/protocol_test.exs b/test/translator/protocol_test.exs new file mode 100644 index 00000000..eaafc5d6 --- /dev/null +++ b/test/translator/protocol_test.exs @@ -0,0 +1,102 @@ +defmodule ElixirScript.Translator.Protocol.Test do + use ShouldI + import ElixirScript.TestHelper + + test "parse protocol spec" do + ex_ast = quote do + defprotocol ElixirScript.Collectable do + def into(collectable) + end + end + + js_code = """ + const __MODULE__ = Elixir.Kernel.SpecialForms.atom('ElixirScript.Collectable'); + + let Collectable = Elixir.Kernel.defprotocol({ + into: Elixir.Patterns.defmatch( + Elixir.Patterns.make_case([Elixir.Patterns.variable()], function(collectable){ + return null; + }) + ) + }); + + export Collectable; + """ + + assert_translation(ex_ast, js_code) + end + + + test "parse protocol spec with implementations" do + ex_ast = quote do + defprotocol Blank do + def blank?(data) + end + + defimpl Blank, for: Integer do + def blank?(number), do: false + end + + defimpl Blank, for: List do + def blank?([]), do: true + def blank?(_), do: false + end + + defimpl Blank, for: Atom do + def blank?(false), do: true + def blank?(nil), do: true + def blank?(_), do: false + end + end + + js_code = """ + const __MODULE__ = Elixir.Kernel.SpecialForms.atom('Blank'); + + let Blank = Elixir.Kernel.defprotocol({ + blank__qmark__: Elixir.Patterns.defmatch( + Elixir.Patterns.make_case([Elixir.Patterns.variable()],function(data){ + return null; + }) + ) + }); + + Elixir.Kernel.defimpl(Blank, Elixir.Patterns.defmatch(Elixir.Patterns.make_case([Elixir.Patterns.variable()],function(__1) { + return Elixir.Kernel.is_list(__1); + })),{ + blank__qmark__: Elixir.Patterns.defmatch(Elixir.Patterns.make_case([Elixir.Kernel.SpecialForms.list()],function() { + return true; + }),Elixir.Patterns.make_case([Elixir.Patterns.wildcard()],function() { + return false; + })) + }) + + + Elixir.Kernel.defimpl(Blank, Elixir.Patterns.defmatch(Elixir.Patterns.make_case([Elixir.Patterns.variable()],function(__1) { + return Elixir.Kernel.is_atom(__1); + })),{ + blank__qmark__: Elixir.Patterns.defmatch(Elixir.Patterns.make_case([false],function() { + return true; + }),Elixir.Patterns.make_case([null],function() { + return true; + }),Elixir.Patterns.make_case([Elixir.Patterns.wildcard()],function() { + return false; + })) + }) + + + Elixir.Kernel.defimpl(Blank, Elixir.Patterns.defmatch(Elixir.Patterns.make_case([Elixir.Patterns.variable()],function(__1) { + return Elixir.Kernel.is_integer(__1); + })),{ + blank__qmark__: Elixir.Patterns.defmatch(Elixir.Patterns.make_case([Elixir.Patterns.variable()],function(number) { + return false; + })) + }) + + + export Blank; + """ + + assert_translation(ex_ast, js_code) + end + +end \ No newline at end of file From 2d16ebdf8ba472f6ce0a0539b87cbfd939a7f7e4 Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Tue, 20 Oct 2015 21:26:57 -0500 Subject: [PATCH 020/860] Protocols are default exports. Updated imports to check if protocol so that a default export is created --- lib/elixir_script/preprocess/aliases.ex | 8 ++ lib/elixir_script/preprocess/modules.ex | 8 +- lib/elixir_script/state.ex | 6 + lib/elixir_script/translator/function.ex | 8 ++ lib/elixir_script/translator/import.ex | 7 + lib/elixir_script/translator/map.ex | 4 + lib/elixir_script/translator/module.ex | 25 ++-- lib/elixir_script/translator/protocol.ex | 165 +++++++---------------- test/translator/protocol_test.exs | 4 +- 9 files changed, 105 insertions(+), 130 deletions(-) diff --git a/lib/elixir_script/preprocess/aliases.ex b/lib/elixir_script/preprocess/aliases.ex index 8e816764..6822267e 100644 --- a/lib/elixir_script/preprocess/aliases.ex +++ b/lib/elixir_script/preprocess/aliases.ex @@ -32,6 +32,14 @@ defmodule ElixirScript.Preprocess.Aliases do { ast, %{state | defined: HashSet.put(state.defined, List.last(name)) } } end + def process_aliases({{:., meta1, [{:__aliases__, meta2, aliases}, function]}, meta3, params} = ast, state, env) when aliases in [[:Collectable], [:Enumerable], [:Inspect], [:List, :Chars], [:String, :Chars]] do + new_ast = {{:., meta1, [{:__aliases__, meta2, List.last(aliases) |> List.wrap }, function]}, meta3, params} + + new_state = %{ state | add: HashSet.put(state.add, [:Elixir] ++ aliases) } + { new_ast, new_state } + end + + def process_aliases({{:., meta1, [{:__aliases__, meta2, aliases}, function]}, meta3, params} = ast, state, env) do if ElixirScript.State.module_listed?(aliases) do new_ast = {{:., meta1, [{:__aliases__, meta2, List.last(aliases) |> List.wrap }, function]}, meta3, params} diff --git a/lib/elixir_script/preprocess/modules.ex b/lib/elixir_script/preprocess/modules.ex index 31eda4f9..41579727 100644 --- a/lib/elixir_script/preprocess/modules.ex +++ b/lib/elixir_script/preprocess/modules.ex @@ -11,19 +11,19 @@ defmodule ElixirScript.Preprocess.Modules do end) end - def do_get_info({:defprotocol, _, [name, [do: {:__block__, context, spec}]]}) do + def do_get_info({:defprotocol, _, [{:__aliases__, _, name}, [do: {:__block__, context, spec}]]}) do ElixirScript.State.add_protocol(name, {:__block__, context, spec}) end - def do_get_info({:defprotocol, _, [name, [do: spec]]}) do + def do_get_info({:defprotocol, _, [{:__aliases__, _, name}, [do: spec]]}) do ElixirScript.State.add_protocol(name, {:__block__, [], [spec]}) end - def do_get_info({:defimpl, _, [ protocol, [for: type], [do: {:__block__, context, spec}] ]}) do + def do_get_info({:defimpl, _, [ {:__aliases__, _, protocol}, [for: type], [do: {:__block__, context, spec}] ]}) do ElixirScript.State.add_protocol_impl(protocol, type, {:__block__, context, spec}) end - def do_get_info({:defimpl, _, [ protocol, [for: type], [do: spec] ]}) do + def do_get_info({:defimpl, _, [ {:__aliases__, _, protocol}, [for: type], [do: spec] ]}) do ElixirScript.State.add_protocol_impl(protocol, type, {:__block__, [], [spec]}) end diff --git a/lib/elixir_script/state.ex b/lib/elixir_script/state.ex index 06362787..a2db37d3 100644 --- a/lib/elixir_script/state.ex +++ b/lib/elixir_script/state.ex @@ -30,6 +30,12 @@ defmodule ElixirScript.State do end) end + def protocol_listed?(module_name) do + Agent.get(__MODULE__, fn(state) -> + Enum.any?(state.protocols, fn({key, value}) -> key == module_name end) + end) + end + def add_protocol(name, spec) do Agent.update(__MODULE__, fn(state) -> proto = Dict.get(state.protocols, name) diff --git a/lib/elixir_script/translator/function.ex b/lib/elixir_script/translator/function.ex index 236608ed..1e28153c 100644 --- a/lib/elixir_script/translator/function.ex +++ b/lib/elixir_script/translator/function.ex @@ -13,6 +13,14 @@ defmodule ElixirScript.Translator.Function do :Base, :String, :Bitwise ] + def update_alias({:__aliases__, context, [:List, :Chars]} = ast) do + ast + end + + def update_alias({:__aliases__, context, [:String, :Chars]} = ast) do + ast + end + def update_alias({:__aliases__, context, [name | rest]}) when name in @standard_libs do {:__aliases__, context, [:Elixir, name] ++ rest } end diff --git a/lib/elixir_script/translator/import.ex b/lib/elixir_script/translator/import.ex index ae21e319..731bfb08 100644 --- a/lib/elixir_script/translator/import.ex +++ b/lib/elixir_script/translator/import.ex @@ -8,6 +8,13 @@ defmodule ElixirScript.Translator.Import do default = Dict.get(options, :default, false) + if State.protocol_listed?(name) do + default = true + + if name in [[:Collectable], [:Enumerable], [:Inspect], [:List, :Chars], [:String, :Chars]] do + name = [:Elixir] ++ name + end + end import_specifier = if default == false do if options[:as] do diff --git a/lib/elixir_script/translator/map.ex b/lib/elixir_script/translator/map.ex index 75fcd613..2c86e200 100644 --- a/lib/elixir_script/translator/map.ex +++ b/lib/elixir_script/translator/map.ex @@ -45,6 +45,10 @@ defmodule ElixirScript.Translator.Map do JS.property(key, value, :init, false, false, true) end + def make_shorthand_property(%ESTree.Identifier{} = key) do + JS.property(key, key, :init, true) + end + def make_map_update(map, data, env) do map = Translator.translate(map, env) diff --git a/lib/elixir_script/translator/module.ex b/lib/elixir_script/translator/module.ex index 9fdbaa07..b7d4e170 100644 --- a/lib/elixir_script/translator/module.ex +++ b/lib/elixir_script/translator/module.ex @@ -20,17 +20,7 @@ defmodule ElixirScript.Translator.Module do { body, functions } = extract_functions_from_module(body) { exported_functions, private_functions } = process_functions(functions, env) - #Translate body - body = Translator.translate(body, env) - - body = case body do - [%ESTree.BlockStatement{ body: body }] -> - body - %ESTree.BlockStatement{ body: body } -> - body - _ -> - List.wrap(body) - end + body = translate_body(body, env) {imports, body} = extract_imports_from_body(body) {structs, body} = extract_structs_from_body(body) @@ -83,6 +73,19 @@ defmodule ElixirScript.Translator.Module do result end + def translate_body(body, env) do + body = Translator.translate(body, env) + + body = case body do + [%ESTree.BlockStatement{ body: body }] -> + body + %ESTree.BlockStatement{ body: body } -> + body + _ -> + List.wrap(body) + end + end + def extract_functions_from_module({:__block__, meta, body_list}) do { body_list, functions } = Enum.map_reduce(body_list, %{exported: HashDict.new(), private: HashDict.new()}, fn diff --git a/lib/elixir_script/translator/protocol.ex b/lib/elixir_script/translator/protocol.ex index 0e1d6207..1e92ee6e 100644 --- a/lib/elixir_script/translator/protocol.ex +++ b/lib/elixir_script/translator/protocol.ex @@ -1,113 +1,70 @@ defmodule ElixirScript.Translator.Protocol do @moduledoc false -alias ESTree.Tools.Builder, as: JS -alias ElixirScript.Translator -alias ElixirScript.Translator.Module -alias ElixirScript.Preprocess.Aliases -alias ElixirScript.Translator.JSModule -alias ElixirScript.Translator.Map -alias ElixirScript.Translator.Function -alias ElixirScript.Translator.Utils - - -def add_default_protocols() do - quoted = quote do - defprotocol ElixirScript.String.Chars do - def to_string(thing) - end - end + alias ESTree.Tools.Builder, as: JS + alias ElixirScript.Translator + alias ElixirScript.Translator.Module + alias ElixirScript.Preprocess.Aliases + alias ElixirScript.Translator.JSModule + alias ElixirScript.Translator.Map + alias ElixirScript.Translator.Function + alias ElixirScript.Translator.Utils - ElixirScript.Preprocess.Modules.do_get_info(quoted) - quoted = quote do - defprotocol ElixirScript.List.Chars do - def to_char_list(thing) + def add_default_protocols() do + quoted = quote do + defprotocol Elixir.String.Chars do + def to_string(thing) + end end - end - ElixirScript.Preprocess.Modules.do_get_info(quoted) - - quoted = quote do - defprotocol ElixirScript.Inspect do - def inspect(thing, opts) + ElixirScript.Preprocess.Modules.do_get_info(quoted) + + quoted = quote do + defprotocol Elixir.List.Chars do + def to_char_list(thing) + end end - end - ElixirScript.Preprocess.Modules.do_get_info(quoted) - - quoted = quote do - defprotocol ElixirScript.Enumerable do - def count(collection) - - def member?(collection, value) + ElixirScript.Preprocess.Modules.do_get_info(quoted) - def reduce(collection, acc, fun) + quoted = quote do + defprotocol Elixir.Inspect do + def inspect(thing, opts) + end end - end - ElixirScript.Preprocess.Modules.do_get_info(quoted) - - quoted = quote do - defprotocol ElixirScript.Collectable do - def into(collectable) + ElixirScript.Preprocess.Modules.do_get_info(quoted) + + quoted = quote do + defprotocol Elixir.Enumerable do + def count(collection) + + def member?(collection, value) + + def reduce(collection, acc, fun) + end end - end - - ElixirScript.Preprocess.Modules.do_get_info(quoted) -end - -def consolidate(protocols, env) when is_list(protocols) do - Enum.map(protocols, fn({_, protocol}) -> - do_consolidate(protocol, env) - end) -end - -#defprotocol ElixirScript.String.Chars do -# def to_string(thing) -#end -# -#defprotocol ElixirScript.List.Chars do -# def to_char_list(thing) -#end -# -#defprotocol ElixirScript.Inspect do -# def inspect(thing, opts) -#end -# -#defprotocol ElixirScript.Enumerable do -# def count(collection) -# -# def member?(collection, value) -# -# def reduce(collection, acc, fun) -#end -# -#defprotocol ElixirScript.Collectable do -# def into(collectable) -#end + ElixirScript.Preprocess.Modules.do_get_info(quoted) + + quoted = quote do + defprotocol Elixir.Collectable do + def into(collectable) + end + end - @doc """ - import * as Elixir from "elixir"; - - const __MODULE__ = [Elixir.Kernel.SpecialForms.atom("Collectable")]; - - Collectable = Elixir.Protocol.defprotocol({ - into: function(collectable){} - }); + ElixirScript.Preprocess.Modules.do_get_info(quoted) + end - Collectable.impl(Array, { - into: function(collectable){ - return collectable.push(a); - } - }); + def consolidate(protocols, env) when is_list(protocols) do + Enum.map(protocols, fn({_, protocol}) -> + do_consolidate(protocol, env) + end) + end - export Collectable; - { body, aliases } = Aliases.process(body, env) - """ defp do_consolidate(protocol, env) do - {:__aliases__, _, name} = protocol.name + name = protocol.name spec = protocol.spec impls = protocol.impls |> Dict.to_list @@ -128,16 +85,7 @@ end { exported_functions, private_functions } = process_functions(functions, env) - body = Translator.translate(body, env) - - body = case body do - [%ESTree.BlockStatement{ body: body }] -> - body - %ESTree.BlockStatement{ body: body } -> - body - _ -> - List.wrap(body) - end + body = Module.translate_body(body, env) {imports, body} = Module.extract_imports_from_body(body) @@ -177,16 +125,7 @@ end { body, functions } = Module.extract_functions_from_module(body) { exported_functions, private_functions } = process_functions(functions, env) - body = Translator.translate(body, env) - - body = case body do - [%ESTree.BlockStatement{ body: body }] -> - body - %ESTree.BlockStatement{ body: body } -> - body - _ -> - List.wrap(body) - end + body = Module.translate_body(body, env) {imports, body} = Module.extract_imports_from_body(body) @@ -222,7 +161,7 @@ end end defp create_module(name, spec, impls, imports, body, env) do - default = JS.export_named_declaration(JS.identifier(List.last(name))) + default = JS.export_default_declaration(JS.identifier(List.last(name))) %JSModule{ name: name, diff --git a/test/translator/protocol_test.exs b/test/translator/protocol_test.exs index eaafc5d6..0f77d24d 100644 --- a/test/translator/protocol_test.exs +++ b/test/translator/protocol_test.exs @@ -20,7 +20,7 @@ defmodule ElixirScript.Translator.Protocol.Test do ) }); - export Collectable; + export default Collectable; """ assert_translation(ex_ast, js_code) @@ -93,7 +93,7 @@ defmodule ElixirScript.Translator.Protocol.Test do }) - export Blank; + export default Blank; """ assert_translation(ex_ast, js_code) From 530a2a7cfb83d4717c39c08311f295b1f9fc064a Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Wed, 21 Oct 2015 18:03:53 -0500 Subject: [PATCH 021/860] Added js versions of standard lib protocols --- lib/elixir_script.ex | 11 +- lib/elixir_script/translator/function.ex | 11 +- lib/elixir_script/translator/import.ex | 4 - lib/elixir_script/translator/kernel.ex | 5 +- lib/elixir_script/translator/protocol.ex | 185 +++++++++------------ priv/javascript/elixir.js | 3 + priv/javascript/lib/collectable.js | 63 +++++++ priv/javascript/lib/enumerable.js | 9 + priv/javascript/lib/inspect.js | 13 ++ priv/javascript/lib/kernel.js | 14 +- priv/javascript/lib/list.js | 3 + priv/javascript/lib/list/chars.js | 40 +++++ priv/javascript/lib/processes/processes.js | 1 + priv/javascript/lib/protocol.js | 3 +- priv/javascript/lib/string.js | 4 +- priv/javascript/lib/string/chars.js | 55 ++++++ priv/javascript/tests/string.chars.spec.js | 14 ++ test/elixir_script_test.exs | 3 +- test/test_helper.exs | 2 +- test/translator/protocol_test.exs | 72 ++++---- test/translator/string_test.exs | 6 +- 21 files changed, 342 insertions(+), 179 deletions(-) create mode 100644 priv/javascript/lib/collectable.js create mode 100644 priv/javascript/lib/enumerable.js create mode 100644 priv/javascript/lib/inspect.js create mode 100644 priv/javascript/lib/list/chars.js create mode 100644 priv/javascript/lib/string/chars.js create mode 100644 priv/javascript/tests/string.chars.spec.js diff --git a/lib/elixir_script.ex b/lib/elixir_script.ex index 5840ef0e..38ea5d30 100644 --- a/lib/elixir_script.ex +++ b/lib/elixir_script.ex @@ -43,7 +43,6 @@ defmodule ElixirScript do root = Dict.get(opts, :root) env = Dict.get(opts, :env, custom_env) import_standard_libs? = Dict.get(opts, :import_standard_libs, true) - use_default_protocols? = Dict.get(opts, :use_default_protocols, true) ElixirScript.State.start_link(root, env) @@ -52,7 +51,7 @@ defmodule ElixirScript do state = ElixirScript.State.get() if Set.size(state.modules) > 0 || Dict.size(state.protocols) > 0 do - create_code(include_path, import_standard_libs?, use_default_protocols?) + create_code(include_path, import_standard_libs?) else result = case Translator.translate(quoted, env) do modules when is_list(modules) -> @@ -100,7 +99,7 @@ defmodule ElixirScript do |> build_environment - create_code(include_path, true, true) + create_code(include_path, true) end defp build_environment(code_list) do @@ -114,11 +113,7 @@ defmodule ElixirScript do __ENV__ end - defp create_code(include_path, import_standard_libs?, use_default_protocols?) do - - if use_default_protocols? do - ElixirScript.Translator.Protocol.add_default_protocols() - end + defp create_code(include_path, import_standard_libs?) do state = ElixirScript.State.get() diff --git a/lib/elixir_script/translator/function.ex b/lib/elixir_script/translator/function.ex index 1e28153c..0ce5141a 100644 --- a/lib/elixir_script/translator/function.ex +++ b/lib/elixir_script/translator/function.ex @@ -10,15 +10,16 @@ defmodule ElixirScript.Translator.Function do @standard_libs [ :Patterns, :Kernel, :Atom, :Enum, :Integer, :JS, :List, :Range, :Tuple, :Agent, :Keyword, :BitString, - :Base, :String, :Bitwise + :Base, :String, :Bitwise, :Collectable, :Enumerable, + :Inspect ] - def update_alias({:__aliases__, context, [:List, :Chars]} = ast) do - ast + def update_alias({:__aliases__, context, [:List, :Chars]}) do + {:__aliases__, context, [:Elixir] ++ [:List, :Chars] } end - def update_alias({:__aliases__, context, [:String, :Chars]} = ast) do - ast + def update_alias({:__aliases__, context, [:String, :Chars]}) do + {:__aliases__, context, [:Elixir] ++ [:String, :Chars] } end def update_alias({:__aliases__, context, [name | rest]}) when name in @standard_libs do diff --git a/lib/elixir_script/translator/import.ex b/lib/elixir_script/translator/import.ex index 731bfb08..c2faed66 100644 --- a/lib/elixir_script/translator/import.ex +++ b/lib/elixir_script/translator/import.ex @@ -10,10 +10,6 @@ defmodule ElixirScript.Translator.Import do if State.protocol_listed?(name) do default = true - - if name in [[:Collectable], [:Enumerable], [:Inspect], [:List, :Chars], [:String, :Chars]] do - name = [:Elixir] ++ name - end end import_specifier = if default == false do diff --git a/lib/elixir_script/translator/kernel.ex b/lib/elixir_script/translator/kernel.ex index ee3e203b..147af9dc 100644 --- a/lib/elixir_script/translator/kernel.ex +++ b/lib/elixir_script/translator/kernel.ex @@ -281,8 +281,9 @@ defmodule ElixirScript.Translator.Kernel do ) end - defp do_translate({:to_string, _, [param]}, env) when is_binary(param) do - Translator.translate(param, env) + defp do_translate({:to_string, _, _} = ast, env) do + Macro.expand(ast, env) + |> Translator.translate(env) end defp do_translate({name, _, params}, env) do diff --git a/lib/elixir_script/translator/protocol.ex b/lib/elixir_script/translator/protocol.ex index 1e92ee6e..be14b6c1 100644 --- a/lib/elixir_script/translator/protocol.ex +++ b/lib/elixir_script/translator/protocol.ex @@ -10,53 +10,6 @@ defmodule ElixirScript.Translator.Protocol do alias ElixirScript.Translator.Function alias ElixirScript.Translator.Utils - - def add_default_protocols() do - quoted = quote do - defprotocol Elixir.String.Chars do - def to_string(thing) - end - end - - ElixirScript.Preprocess.Modules.do_get_info(quoted) - - quoted = quote do - defprotocol Elixir.List.Chars do - def to_char_list(thing) - end - end - - ElixirScript.Preprocess.Modules.do_get_info(quoted) - - quoted = quote do - defprotocol Elixir.Inspect do - def inspect(thing, opts) - end - end - - ElixirScript.Preprocess.Modules.do_get_info(quoted) - - quoted = quote do - defprotocol Elixir.Enumerable do - def count(collection) - - def member?(collection, value) - - def reduce(collection, acc, fun) - end - end - - ElixirScript.Preprocess.Modules.do_get_info(quoted) - - quoted = quote do - defprotocol Elixir.Collectable do - def into(collectable) - end - end - - ElixirScript.Preprocess.Modules.do_get_info(quoted) - end - def consolidate(protocols, env) when is_list(protocols) do Enum.map(protocols, fn({_, protocol}) -> do_consolidate(protocol, env) @@ -208,91 +161,113 @@ defmodule ElixirScript.Translator.Protocol do in JavaScript """ defp map_to_js({:__aliases__, _, [:Integer]}) do - quoted = quote do - &Kernel.is_integer/1 - end - - Translator.translate(quoted, ElixirScript.State.get().env) + JS.member_expression( + JS.identifier(:Elixir), + JS.member_expression( + JS.identifier(:Kernel), + JS.identifier(:is_integer) + ) + ) end defp map_to_js({:__aliases__, _, [:Tuple]}) do - quoted = quote do - &Kernel.is_tuple/1 - end - - Translator.translate(quoted, ElixirScript.State.get().env) + JS.member_expression( + JS.identifier(:Elixir), + JS.member_expression( + JS.identifier(:Kernel), + JS.identifier(:is_tuple) + ) + ) end defp map_to_js({:__aliases__, _, [:Atom]}) do - quoted = quote do - &Kernel.is_atom/1 - end - - Translator.translate(quoted, ElixirScript.State.get().env) + JS.member_expression( + JS.identifier(:Elixir), + JS.member_expression( + JS.identifier(:Kernel), + JS.identifier(:is_atom) + ) + ) end defp map_to_js({:__aliases__, _, [:List]}) do - quoted = quote do - &Kernel.is_list/1 - end - - Translator.translate(quoted, ElixirScript.State.get().env) + JS.member_expression( + JS.identifier(:Elixir), + JS.member_expression( + JS.identifier(:Kernel), + JS.identifier(:is_list) + ) + ) end defp map_to_js({:__aliases__, _, [:BitString]}) do - quoted = quote do - &Kernel.is_bitstring/1 - end - - Translator.translate(quoted, ElixirScript.State.get().env) + JS.member_expression( + JS.identifier(:Elixir), + JS.member_expression( + JS.identifier(:Kernel), + JS.identifier(:is_bitstring) + ) + ) end defp map_to_js({:__aliases__, _, [:Float]}) do - quoted = quote do - &Kernel.is_float/1 - end - - Translator.translate(quoted, ElixirScript.State.get().env) + JS.member_expression( + JS.identifier(:Elixir), + JS.member_expression( + JS.identifier(:Kernel), + JS.identifier(:is_float) + ) + ) end defp map_to_js({:__aliases__, _, [:Function]}) do - quoted = quote do - &Kernel.is_function/1 - end - - Translator.translate(quoted, ElixirScript.State.get().env) + JS.member_expression( + JS.identifier(:Elixir), + JS.member_expression( + JS.identifier(:Kernel), + JS.identifier(:is_function) + ) + ) end defp map_to_js({:__aliases__, _, [:PID]}) do - quoted = quote do - &Kernel.is_pid/1 - end - - Translator.translate(quoted, ElixirScript.State.get().env) + JS.member_expression( + JS.identifier(:Elixir), + JS.member_expression( + JS.identifier(:Kernel), + JS.identifier(:is_pid) + ) + ) end defp map_to_js({:__aliases__, _, [:Port]}) do - quoted = quote do - &Kernel.is_port/1 - end - - Translator.translate(quoted, ElixirScript.State.get().env) + JS.member_expression( + JS.identifier(:Elixir), + JS.member_expression( + JS.identifier(:Kernel), + JS.identifier(:is_port) + ) + ) end defp map_to_js({:__aliases__, _, [:Reference]}) do - quoted = quote do - &Kernel.is_reference/1 - end - - Translator.translate(quoted, ElixirScript.State.get().env) + JS.member_expression( + JS.identifier(:Elixir), + JS.member_expression( + JS.identifier(:Kernel), + JS.identifier(:is_reference) + ) + ) end defp map_to_js({:__aliases__, _, [:Map]}) do - quoted = quote do - &Kernel.is_map/1 - end - - Translator.translate(quoted, ElixirScript.State.get().env) + JS.member_expression( + JS.identifier(:Elixir), + JS.member_expression( + JS.identifier(:Kernel), + JS.identifier(:is_map) + ) + ) end defp map_to_js({:__aliases__, _, [:Any]}) do @@ -305,8 +280,12 @@ defmodule ElixirScript.Translator.Protocol do defp map_to_js({:__aliases__, _, struct}) do + module_name = Enum.map(struct, &Atom.to_string(&1)) + |> Enum.join(".") + |> String.to_atom + quoted = quote do - Kernel.is_struct_fn(unquote(List.last(struct))) + Kernel.is_struct_fn(unquote(module_name)) end Translator.translate(quoted, ElixirScript.State.get().env) diff --git a/priv/javascript/elixir.js b/priv/javascript/elixir.js index 45722bb2..b0f4bc93 100644 --- a/priv/javascript/elixir.js +++ b/priv/javascript/elixir.js @@ -17,4 +17,7 @@ export { default as Keyword } from './lib/keyword'; export { default as Base } from './lib/base'; export { default as String } from './lib/string'; export { default as Bitwise } from './lib/bitwise'; +export { default as Enumerable } from './lib/enumable'; +export { default as Collectable } from './lib/collectable'; +export { default as Inspect } from './lib/inspect'; diff --git a/priv/javascript/lib/collectable.js b/priv/javascript/lib/collectable.js new file mode 100644 index 00000000..7fbd6eb2 --- /dev/null +++ b/priv/javascript/lib/collectable.js @@ -0,0 +1,63 @@ +import Kernel from "./kernel"; +import Patterns from "./patterns/patterns"; +import List from "./list"; + +let Collectable = Kernel.defprotocol({ + into: function(collectable){} +}); + +Kernel.defimpl(Collectable, Kernel.is_list, { + into: function(collectable){ + let original_value = Kernel.SpecialForms.list(); + + let fn = Patterns.defmatch( + Patterns.make_case( + [Patterns.parameter(), Kernel.SpecialForms.tuple(Kernel.SpecialForms.atom("cont"), Patterns.parameter())], + function(list, x){ + return List.append(list, x); + }), + Patterns.make_case( + [Patterns.parameter(), Kernel.SpecialForms.atom("done")], + function(list){ + return List.concat(collectable, list); + }), + Patterns.make_case( + [Patterns.wildcard(), Kernel.SpecialForms.atom("halt")], + function(){ + return Kernel.SpecialForms.atom("ok"); + }) + ); + + + return Kernel.SpecialForms.tuple(original_value, fn); + } +}); + + +Kernel.defimpl(Collectable, Kernel.is_map, { + into: function(collectable){ + + let fn = Patterns.defmatch( + Patterns.make_case( + [Patterns.parameter(), Kernel.SpecialForms.tuple(Kernel.SpecialForms.atom("cont"), Kernel.SpecialForms.tuple(Patterns.parameter(), Patterns.parameter()))], + function(map, key, value){ + return Kernel.SpecialForms.map_update(map, { [key]: value }); + }), + Patterns.make_case( + [Patterns.parameter(), Kernel.SpecialForms.atom("done")], + function(map){ + return map; + }), + Patterns.make_case( + [Patterns.wildcard(), Kernel.SpecialForms.atom("halt")], + function(){ + return Kernel.SpecialForms.atom("ok"); + }) + ); + + + return Kernel.SpecialForms.tuple(collectable, fn); + } +}); + +export default Collectable; \ No newline at end of file diff --git a/priv/javascript/lib/enumerable.js b/priv/javascript/lib/enumerable.js new file mode 100644 index 00000000..cec6bfe6 --- /dev/null +++ b/priv/javascript/lib/enumerable.js @@ -0,0 +1,9 @@ +import Kernel from "./kernel"; + +let Enumerable = Kernel.defprotocol({ + count: function(collection){}, + member_qmark__: function(collection, value){}, + reduce: function(collection, acc, fun){} +}); + +export default Enumerable; \ No newline at end of file diff --git a/priv/javascript/lib/inspect.js b/priv/javascript/lib/inspect.js new file mode 100644 index 00000000..6e38fa54 --- /dev/null +++ b/priv/javascript/lib/inspect.js @@ -0,0 +1,13 @@ +import Kernel from "./kernel"; + +let Inspect = Kernel.defprotocol({ + inspect: function(thing, opts){} +}); + +Kernel.defimpl(Inspect, null, { + inspect: function(thing, opts){ + return thing.toString(); + } +}); + +export default Inspect; \ No newline at end of file diff --git a/priv/javascript/lib/kernel.js b/priv/javascript/lib/kernel.js index 292d295a..ab040cb5 100644 --- a/priv/javascript/lib/kernel.js +++ b/priv/javascript/lib/kernel.js @@ -1,7 +1,10 @@ import SpecialForms from './kernel/special_forms'; import Patterns from './patterns/patterns'; import Tuple from './tuple'; +import BitString from './bit_string'; import Protocol from './protocol'; +import { PID } from './processes/processes'; + let Kernel = { SpecialForms: SpecialForms, @@ -34,13 +37,12 @@ let Kernel = { return typeof x === 'function' || x instanceof Function; }, - // from: http://stackoverflow.com/a/3885844 is_float: function(x){ - return x === +x && x !== (x|0); + return Kernel.is_number(x) && !Number.isInteger(x); }, is_integer: function(x){ - return x === +x && x === (x|0); + return Number.isInteger(x); }, is_list: function(x){ @@ -52,7 +54,7 @@ let Kernel = { }, is_number: function(x){ - return Kernel.is_integer(x) || Kernel.is_float(x); + return typeof x === "number"; }, is_tuple: function(x){ @@ -64,7 +66,7 @@ let Kernel = { }, is_pid: function(x){ - return false; + return x instanceof PID; }, is_port: function(x){ @@ -76,7 +78,7 @@ let Kernel = { }, is_bitstring: function(x){ - return Kernel.is_binary(x) || x instanceof SpecialForms.bitstring; + return Kernel.is_binary(x) || x instanceof BitString; }, __in__: function(left, right){ diff --git a/priv/javascript/lib/list.js b/priv/javascript/lib/list.js index 5f69478b..b2f154a2 100644 --- a/priv/javascript/lib/list.js +++ b/priv/javascript/lib/list.js @@ -1,7 +1,10 @@ import Kernel from './kernel'; +import Chars from './list/chars'; let List = {}; +List.Chars = Chars; + List.delete = function(list, item){ let new_value = []; let value_found = false; diff --git a/priv/javascript/lib/list/chars.js b/priv/javascript/lib/list/chars.js new file mode 100644 index 00000000..03bf1bda --- /dev/null +++ b/priv/javascript/lib/list/chars.js @@ -0,0 +1,40 @@ +import Kernel from "../kernel"; +import Atom from "../atom"; +import Integer from "../integer"; +import List from "../list"; +import String from "../string"; + +let Chars = Kernel.defprotocol({ + to_char_list: function(thing){} +}); + +Kernel.defimpl(Chars, Kernel.is_bitstring, { + to_char_list: function(thing){ + if(Kernel.is_binary(thing)){ + return String.to_char_list(thing); + } + + return thing.toString(); + } +}); + +Kernel.defimpl(Chars, Kernel.is_atom, { + to_char_list: function(thing){ + return Atom.to_char_list(thing); + } +}); + +Kernel.defimpl(Chars, Kernel.is_integer, { + to_char_list: function(thing){ + return Integer.to_char_list(thing); + } +}); + + +Kernel.defimpl(Chars, Kernel.is_list, { + to_char_list: function(thing){ + return thing; + } +}); + +export default Chars; \ No newline at end of file diff --git a/priv/javascript/lib/processes/processes.js b/priv/javascript/lib/processes/processes.js index ae7f3548..fadb605d 100644 --- a/priv/javascript/lib/processes/processes.js +++ b/priv/javascript/lib/processes/processes.js @@ -2,3 +2,4 @@ export { default as ProcessSystem } from "./processes/process_system"; export { default as GenServer } from "./processes/otp/gen_server"; export { default as GenEvent } from "./processes/otp/gen_event"; export { default as Application } from "./processes/otp/application"; +export { default as PID } from "./processes/pid"; diff --git a/priv/javascript/lib/protocol.js b/priv/javascript/lib/protocol.js index d44fcbbe..e0f658a2 100644 --- a/priv/javascript/lib/protocol.js +++ b/priv/javascript/lib/protocol.js @@ -13,7 +13,8 @@ class Protocol{ return function(...args) { let thing = args[0]; - for([check, implementation] of this.registry){ + for(let [check, implementation] of this.registry){ + if(check(thing)){ let fun = implementation[funName]; let retval = fun.apply(this, args); diff --git a/priv/javascript/lib/string.js b/priv/javascript/lib/string.js index 374dc448..37fb7cae 100644 --- a/priv/javascript/lib/string.js +++ b/priv/javascript/lib/string.js @@ -1,4 +1,5 @@ import Kernel from './kernel'; +import Chars from './string/chars'; function to_atom(string){ return Symbol.for(string); @@ -189,5 +190,6 @@ export default { to_float, to_integer, upcase, - valid_character__qm__ + valid_character__qm__, + Chars } \ No newline at end of file diff --git a/priv/javascript/lib/string/chars.js b/priv/javascript/lib/string/chars.js new file mode 100644 index 00000000..320857bc --- /dev/null +++ b/priv/javascript/lib/string/chars.js @@ -0,0 +1,55 @@ +import Kernel from "../kernel"; +import Atom from "../atom"; +import Integer from "../integer"; +import List from "../list"; +import Tuple from "../tuple"; + +let Chars = Kernel.defprotocol({ + to_string: function(thing){} +}); + +Kernel.defimpl(Chars, Kernel.is_bitstring, { + to_string: function(thing){ + if(Kernel.is_binary(thing)){ + return thing; + } + + return thing.toString(); + } +}); + +Kernel.defimpl(Chars, Kernel.is_atom, { + to_string: function(thing){ + if(nil){ + return ""; + } + + return Atom.to_string(thing); + } +}); + +Kernel.defimpl(Chars, Kernel.is_integer, { + to_string: function(thing){ + return Integer.to_string(thing); + } +}); + +Kernel.defimpl(Chars, Kernel.is_float, { + to_string: function(thing){ + return thing.toString; + } +}); + +Kernel.defimpl(Chars, Kernel.is_list, { + to_string: function(thing){ + return thing.toString(); + } +}); + +Kernel.defimpl(Chars, Kernel.is_tuple, { + to_string: function(thing){ + return Tuple.to_string(thing); + } +}); + +export default Chars; \ No newline at end of file diff --git a/priv/javascript/tests/string.chars.spec.js b/priv/javascript/tests/string.chars.spec.js new file mode 100644 index 00000000..0f92c147 --- /dev/null +++ b/priv/javascript/tests/string.chars.spec.js @@ -0,0 +1,14 @@ +var String = require('../lib/string'); +var Tuple = require('../lib/tuple'); +var expect = require('chai').expect; + +describe('String.Chars', function(){ + + it('to_string', function(){ + expect(String.Chars.to_string(1)).to.equal("1"); + expect(String.Chars.to_string("a string")).to.equal("a string"); + expect(String.Chars.to_string(new Tuple(1, 2, 3))).to.equal("{1, 2, 3}"); + expect(String.Chars.to_string([1, 2, 3])).to.equal("1,2,3"); + }); + +}); \ No newline at end of file diff --git a/test/elixir_script_test.exs b/test/elixir_script_test.exs index 994ddffa..3af69a94 100644 --- a/test/elixir_script_test.exs +++ b/test/elixir_script_test.exs @@ -26,6 +26,7 @@ defmodule ElixirScript.Test do end defp something_else() do + to_string(10) end end """) @@ -34,7 +35,7 @@ defmodule ElixirScript.Test do import * as Elixir from 'elixir'; const __MODULE__ = Elixir.Kernel.SpecialForms.atom('Elephant'); const something_else = Elixir.Patterns.defmatch(Elixir.Patterns.make_case([],function() { - return null; + return Elixir.String.Chars.to_string(10); })); const something = Elixir.Patterns.defmatch(Elixir.Patterns.make_case([],function() { return ul; diff --git a/test/test_helper.exs b/test/test_helper.exs index 7c74cc10..14417b8f 100644 --- a/test/test_helper.exs +++ b/test/test_helper.exs @@ -32,7 +32,7 @@ defmodule ElixirScript.TestHelper do end def ex_ast_to_js(ex_ast) do - ElixirScript.compile_quoted(ex_ast, [env: make_custom_env, import_standard_libs: false, use_default_protocols: false]) + ElixirScript.compile_quoted(ex_ast, [env: make_custom_env, import_standard_libs: false]) end def strip_spaces(js) do diff --git a/test/translator/protocol_test.exs b/test/translator/protocol_test.exs index 0f77d24d..f6ad85a3 100644 --- a/test/translator/protocol_test.exs +++ b/test/translator/protocol_test.exs @@ -50,50 +50,34 @@ defmodule ElixirScript.Translator.Protocol.Test do end js_code = """ - const __MODULE__ = Elixir.Kernel.SpecialForms.atom('Blank'); - - let Blank = Elixir.Kernel.defprotocol({ - blank__qmark__: Elixir.Patterns.defmatch( - Elixir.Patterns.make_case([Elixir.Patterns.variable()],function(data){ - return null; - }) - ) - }); - - Elixir.Kernel.defimpl(Blank, Elixir.Patterns.defmatch(Elixir.Patterns.make_case([Elixir.Patterns.variable()],function(__1) { - return Elixir.Kernel.is_list(__1); - })),{ - blank__qmark__: Elixir.Patterns.defmatch(Elixir.Patterns.make_case([Elixir.Kernel.SpecialForms.list()],function() { - return true; - }),Elixir.Patterns.make_case([Elixir.Patterns.wildcard()],function() { - return false; - })) - }) - - - Elixir.Kernel.defimpl(Blank, Elixir.Patterns.defmatch(Elixir.Patterns.make_case([Elixir.Patterns.variable()],function(__1) { - return Elixir.Kernel.is_atom(__1); - })),{ - blank__qmark__: Elixir.Patterns.defmatch(Elixir.Patterns.make_case([false],function() { - return true; - }),Elixir.Patterns.make_case([null],function() { - return true; - }),Elixir.Patterns.make_case([Elixir.Patterns.wildcard()],function() { - return false; - })) - }) - - - Elixir.Kernel.defimpl(Blank, Elixir.Patterns.defmatch(Elixir.Patterns.make_case([Elixir.Patterns.variable()],function(__1) { - return Elixir.Kernel.is_integer(__1); - })),{ - blank__qmark__: Elixir.Patterns.defmatch(Elixir.Patterns.make_case([Elixir.Patterns.variable()],function(number) { - return false; - })) - }) - - - export default Blank; + const __MODULE__ = Elixir.Kernel.SpecialForms.atom('Blank'); + let Blank = Elixir.Kernel.defprotocol({ + blank__qmark__: Elixir.Patterns.defmatch(Elixir.Patterns.make_case([Elixir.Patterns.variable()],function(data) { + return null; + })) + }); + Elixir.Kernel.defimpl(Blank,Elixir.Kernel.is_list,{ + blank__qmark__: Elixir.Patterns.defmatch(Elixir.Patterns.make_case([Elixir.Kernel.SpecialForms.list()],function() { + return true; + }),Elixir.Patterns.make_case([Elixir.Patterns.wildcard()],function() { + return false; + })) + }) + Elixir.Kernel.defimpl(Blank,Elixir.Kernel.is_atom,{ + blank__qmark__: Elixir.Patterns.defmatch(Elixir.Patterns.make_case([false],function() { + return true; + }),Elixir.Patterns.make_case([null],function() { + return true; + }),Elixir.Patterns.make_case([Elixir.Patterns.wildcard()],function() { + return false; + })) + }) + Elixir.Kernel.defimpl(Blank,Elixir.Kernel.is_integer,{ + blank__qmark__: Elixir.Patterns.defmatch(Elixir.Patterns.make_case([Elixir.Patterns.variable()],function(number) { + return false; + })) + }) + export default Blank; """ assert_translation(ex_ast, js_code) diff --git a/test/translator/string_test.exs b/test/translator/string_test.exs index df97f579..d48ef6cd 100644 --- a/test/translator/string_test.exs +++ b/test/translator/string_test.exs @@ -25,19 +25,19 @@ defmodule ElixirScript.Translator.String.Test do assert_translation(ex_ast, "'Hello ' + 'world'") ex_ast = quote do: "Hello #{length([])}" - assert_translation(ex_ast, "'Hello ' + Elixir.Kernel.to_string(Elixir.Kernel.SpecialForms.list().length)") + assert_translation(ex_ast, "'Hello ' + Elixir.String.Chars.to_string(Elixir.Kernel.SpecialForms.list().length)") end should "translate multiline string interpolation" do ex_ast = quote do: """ Hello #{length([])} """ - assert_translation(ex_ast, "'Hello ' + (Elixir.Kernel.to_string(Elixir.Kernel.SpecialForms.list().length) + '\\n')") + assert_translation(ex_ast, "'Hello ' + (Elixir.String.Chars.to_string(Elixir.Kernel.SpecialForms.list().length) + '\\n')") ex_ast = quote do: """ Hello #{length([])} How are you, #{length([])}? """ - assert_translation(ex_ast, "'Hello ' + (Elixir.Kernel.to_string(Elixir.Kernel.SpecialForms.list().length) + ('\\nHow are you, ' + (Elixir.Kernel.to_string(Elixir.Kernel.SpecialForms.list().length) + '?\\n')))") + assert_translation(ex_ast, "'Hello ' + (Elixir.String.Chars.to_string(Elixir.Kernel.SpecialForms.list().length) + ('\\nHow are you, ' + (Elixir.String.Chars.to_string(Elixir.Kernel.SpecialForms.list().length) + '?\\n')))") end end \ No newline at end of file From 00812dcd9a2c104e8c20e75ebf231de998a66697 Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Wed, 21 Oct 2015 18:22:11 -0500 Subject: [PATCH 022/860] Now treating translation of standard lib protocol implementations differently --- lib/elixir_script/preprocess/modules.ex | 12 ++++++++++-- lib/elixir_script/translator.ex | 22 ++++++++++++++++++++-- lib/elixir_script/translator/protocol.ex | 24 ++++++++++++++++++++++++ test/translator/protocol_test.exs | 18 ++++++++++++++++++ 4 files changed, 72 insertions(+), 4 deletions(-) diff --git a/lib/elixir_script/preprocess/modules.ex b/lib/elixir_script/preprocess/modules.ex index 41579727..10dd45dd 100644 --- a/lib/elixir_script/preprocess/modules.ex +++ b/lib/elixir_script/preprocess/modules.ex @@ -3,6 +3,14 @@ defmodule ElixirScript.Preprocess.Modules do alias ElixirScript.State + @standard_lib_protocols [ + [:Enumerable], + [:Inspect], + [:String, :Chars], + [:List, :Chars], + [:Collectable] + ] + def get_info(modules) do Enum.each(modules, fn(m) -> Macro.postwalk(m, fn(x) -> @@ -19,11 +27,11 @@ defmodule ElixirScript.Preprocess.Modules do ElixirScript.State.add_protocol(name, {:__block__, [], [spec]}) end - def do_get_info({:defimpl, _, [ {:__aliases__, _, protocol}, [for: type], [do: {:__block__, context, spec}] ]}) do + def do_get_info({:defimpl, _, [ {:__aliases__, _, protocol}, [for: type], [do: {:__block__, context, spec}] ]}) when not protocol in @standard_lib_protocols do ElixirScript.State.add_protocol_impl(protocol, type, {:__block__, context, spec}) end - def do_get_info({:defimpl, _, [ {:__aliases__, _, protocol}, [for: type], [do: spec] ]}) do + def do_get_info({:defimpl, _, [ {:__aliases__, _, protocol}, [for: type], [do: spec] ]}) when not protocol in @standard_lib_protocols do ElixirScript.State.add_protocol_impl(protocol, type, {:__block__, [], [spec]}) end diff --git a/lib/elixir_script/translator.ex b/lib/elixir_script/translator.ex index 27093a22..530835bd 100644 --- a/lib/elixir_script/translator.ex +++ b/lib/elixir_script/translator.ex @@ -20,11 +20,21 @@ defmodule ElixirScript.Translator do alias ElixirScript.Translator.Receive alias ElixirScript.Translator.Quote alias ElixirScript.Translator.Utils + alias ElixirScript.Translator.Protocol alias ElixirScript.Translator.Kernel, as: KernelLib alias ElixirScript.Translator.Logger alias ElixirScript.Translator.JS, as: JSLib alias ESTree.Tools.Builder, as: JS + @standard_lib_protocols [ + [:Enumerable], + [:Inspect], + [:String, :Chars], + [:List, :Chars], + [:Collectable] + ] + + @doc """ Translates Elixir AST to JavaScript AST """ @@ -285,11 +295,19 @@ defmodule ElixirScript.Translator do Module.make_module(module_name_list, body, env) end - defp do_translate({:defprotocol, _, _}) do + defp do_translate({:defprotocol, _, _}, _) do %ElixirScript.Translator.Group{} end - defp do_translate({:defimpl, _, _}) do + defp do_translate({:defimpl, _, [ {:__aliases__, _, protocol}, [for: type], [do: {:__block__, context, spec}] ]}, env) when protocol in @standard_lib_protocols do + Protocol.make_standard_lib_impl({:__aliases__, [], [:Elixir] ++ protocol}, type, {:__block__, context, spec}, env) + end + + defp do_translate({:defimpl, _, [ {:__aliases__, _, protocol}, [for: type], [do: spec] ]}, env) when protocol in @standard_lib_protocols do + Protocol.make_standard_lib_impl({:__aliases__, [], [:Elixir] ++ protocol}, type, {:__block__, [], [spec]}, env) + end + + defp do_translate({:defimpl, _, _}, _) do %ElixirScript.Translator.Group{} end diff --git a/lib/elixir_script/translator/protocol.ex b/lib/elixir_script/translator/protocol.ex index be14b6c1..3e36d639 100644 --- a/lib/elixir_script/translator/protocol.ex +++ b/lib/elixir_script/translator/protocol.ex @@ -113,6 +113,30 @@ defmodule ElixirScript.Translator.Protocol do end) end + def make_standard_lib_impl(protocol, type, impl, env) do + type = map_to_js(type) + protocol = Translator.translate(protocol, env) + + { _, functions } = Module.extract_functions_from_module(impl) + { exported_functions, _ } = process_functions(functions, env) + + object = Enum.map(exported_functions, fn({key, value}) -> + Map.make_property(JS.identifier(Utils.filter_name(key)), value) + end) + |> JS.object_expression + + JS.call_expression( + JS.member_expression( + JS.identifier(:Elixir), + JS.member_expression( + JS.identifier(:Kernel), + JS.identifier(:defimpl) + ) + ), + [protocol, type, object] + ) + end + defp create_module(name, spec, impls, imports, body, env) do default = JS.export_default_declaration(JS.identifier(List.last(name))) diff --git a/test/translator/protocol_test.exs b/test/translator/protocol_test.exs index f6ad85a3..ae896ff4 100644 --- a/test/translator/protocol_test.exs +++ b/test/translator/protocol_test.exs @@ -26,6 +26,24 @@ defmodule ElixirScript.Translator.Protocol.Test do assert_translation(ex_ast, js_code) end + test "translate standard lib protocol defimpl" do + ex_ast = quote do + defimpl String.Chars, for: Duck do + def to_string(duck), do: "quack" + end + end + + js_code = """ + Elixir.Kernel.defimpl(Elixir.String.Chars, Elixir.Kernel.is_struct_fn(Elixir.Kernel.SpecialForms.atom('Duck')),{ + to_string: Elixir.Patterns.defmatch(Elixir.Patterns.make_case([Elixir.Patterns.variable()],function(duck) { + return 'quack'; + })) + }) + """ + + assert_translation(ex_ast, js_code) + end + test "parse protocol spec with implementations" do ex_ast = quote do From c6f8ee82d80d854067c295e26746fa115d334e68 Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Thu, 22 Oct 2015 13:58:26 -0500 Subject: [PATCH 023/860] Fixed spelling and wrong module bugs found when running application --- lib/elixir_script/translator/struct.ex | 5 ++++- priv/javascript/elixir.js | 2 +- priv/javascript/lib/js.js | 21 +++++++++++++++++---- 3 files changed, 22 insertions(+), 6 deletions(-) diff --git a/lib/elixir_script/translator/struct.ex b/lib/elixir_script/translator/struct.ex index 6507459f..da79939d 100644 --- a/lib/elixir_script/translator/struct.ex +++ b/lib/elixir_script/translator/struct.ex @@ -86,7 +86,10 @@ defmodule ElixirScript.Translator.Struct do JS.return_statement( JS.call_expression( JS.member_expression( - JS.identifier("Kernel"), + JS.member_expression( + JS.identifier("Elixir"), + JS.identifier("Kernel") + ), JS.identifier("defstruct") ), [defaults, JS.identifier(:values)] diff --git a/priv/javascript/elixir.js b/priv/javascript/elixir.js index b0f4bc93..6d396ae7 100644 --- a/priv/javascript/elixir.js +++ b/priv/javascript/elixir.js @@ -17,7 +17,7 @@ export { default as Keyword } from './lib/keyword'; export { default as Base } from './lib/base'; export { default as String } from './lib/string'; export { default as Bitwise } from './lib/bitwise'; -export { default as Enumerable } from './lib/enumable'; +export { default as Enumerable } from './lib/enumerable'; export { default as Collectable } from './lib/collectable'; export { default as Inspect } from './lib/inspect'; diff --git a/priv/javascript/lib/js.js b/priv/javascript/lib/js.js index ad5949cd..261c4bfe 100644 --- a/priv/javascript/lib/js.js +++ b/priv/javascript/lib/js.js @@ -1,11 +1,24 @@ -let JS = { - call_property: function(item, property){ +function call_property(item, property){ + if(property in item){ + item[property]; if(item[property] instanceof Function){ return item[property](); }else{ return item[property]; } + + }else if(Symbol.for(property) in item){ + let prop = Symbol.for(property) + if(item[prop] instanceof Function){ + return item[prop](); + }else{ + return item[prop]; + } } -}; -export default JS; + throw new Error(`Property ${property} not found in ${item}`); +} + +export default { + call_property +}; From c0bc2d59ec1542e6de51516139c8cf226b680abb Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Thu, 22 Oct 2015 14:03:23 -0500 Subject: [PATCH 024/860] Fixed broken unit tests --- test/elixir_script_test.exs | 2 +- test/translator/defmodule_test.exs | 6 +++--- test/translator/struct_test.exs | 8 ++++---- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/test/elixir_script_test.exs b/test/elixir_script_test.exs index 3af69a94..a7656949 100644 --- a/test/elixir_script_test.exs +++ b/test/elixir_script_test.exs @@ -81,7 +81,7 @@ defmodule ElixirScript.Test do import * as Elixir from 'elixir'; const __MODULE__ = Elixir.Kernel.SpecialForms.atom('Animals.Elephant'); function defstruct(values = {}) { - return Kernel.defstruct({ + return Elixir.Kernel.defstruct({ [Elixir.Kernel.SpecialForms.atom('__struct__')]: __MODULE__, [Elixir.Kernel.SpecialForms.atom('trunk')]: true },values); } diff --git a/test/translator/defmodule_test.exs b/test/translator/defmodule_test.exs index 7fc635a7..dfe2368d 100644 --- a/test/translator/defmodule_test.exs +++ b/test/translator/defmodule_test.exs @@ -97,7 +97,7 @@ defmodule ElixirScript.Translator.Defmodule.Test do js_code = """ const __MODULE__ = Elixir.Kernel.SpecialForms.atom('Animals.Elephant'); function defstruct(values = {}) { - return Kernel.defstruct({ + return Elixir.Kernel.defstruct({ [Elixir.Kernel.SpecialForms.atom('__struct__')]: __MODULE__, [Elixir.Kernel.SpecialForms.atom('trunk')]: true },values); } @@ -149,7 +149,7 @@ defmodule ElixirScript.Translator.Defmodule.Test do js_code = """ const __MODULE__ = Elixir.Kernel.SpecialForms.atom('Elephant.Bear'); function defstruct(values = {}) { - return Kernel.defstruct({ + return Elixir.Kernel.defstruct({ [Elixir.Kernel.SpecialForms.atom('__struct__')]: __MODULE__, [Elixir.Kernel.SpecialForms.atom('trunk')]: true },values); } @@ -160,7 +160,7 @@ defmodule ElixirScript.Translator.Defmodule.Test do import * as Bear from 'elephant/bear'; const __MODULE__ = Elixir.Kernel.SpecialForms.atom('Animals.Elephant'); function defstruct(values = {}) { - return Kernel.defstruct({ + return Elixir.Kernel.defstruct({ [Elixir.Kernel.SpecialForms.atom('__struct__')]: __MODULE__, [Elixir.Kernel.SpecialForms.atom('trunk')]: true },values); } diff --git a/test/translator/struct_test.exs b/test/translator/struct_test.exs index 665a1260..ee8e4069 100644 --- a/test/translator/struct_test.exs +++ b/test/translator/struct_test.exs @@ -12,7 +12,7 @@ defmodule ElixirScript.Translator.Struct.Test do js_code = """ const __MODULE__ = Elixir.Kernel.SpecialForms.atom('User'); function defstruct(values = {}) { - return Kernel.defstruct({ + return Elixir.Kernel.defstruct({ [Elixir.Kernel.SpecialForms.atom('__struct__')]: __MODULE__, [Elixir.Kernel.SpecialForms.atom('name')]: 'john', [Elixir.Kernel.SpecialForms.atom('age')]: 27 },values); } @@ -35,7 +35,7 @@ defmodule ElixirScript.Translator.Struct.Test do js_code = """ const __MODULE__ = Elixir.Kernel.SpecialForms.atom('User'); function defstruct(values = {}) { - return Kernel.defstruct({ + return Elixir.Kernel.defstruct({ [Elixir.Kernel.SpecialForms.atom('__struct__')]: __MODULE__, [Elixir.Kernel.SpecialForms.atom('name')]: null, [Elixir.Kernel.SpecialForms.atom('age')]: null },values); } @@ -109,7 +109,7 @@ defmodule ElixirScript.Translator.Struct.Test do js_code = """ const __MODULE__ = Elixir.Kernel.SpecialForms.atom('MyAppError'); function defexception(values = {}) { - return Kernel.defstruct({ + return Elixir.Kernel.defstruct({ [Elixir.Kernel.SpecialForms.atom('__struct__')]: __MODULE__, [Elixir.Kernel.SpecialForms.atom('message')]: 'This is a message' },values); } @@ -129,7 +129,7 @@ defmodule ElixirScript.Translator.Struct.Test do js_code = """ const __MODULE__ = Elixir.Kernel.SpecialForms.atom('MyAppError'); function defexception(values = {}) { - return Kernel.defstruct({ + return Elixir.Kernel.defstruct({ [Elixir.Kernel.SpecialForms.atom('__struct__')]: __MODULE__, [Elixir.Kernel.SpecialForms.atom('message')]: null },values); } From d8f361c71ede8aadad161ac358e156e74f58df63 Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Thu, 22 Oct 2015 17:24:00 -0500 Subject: [PATCH 025/860] Updated modules module to check if there is more than one module in a file --- lib/elixir_script/preprocess/modules.ex | 13 +++++++++---- test/elixir_script_test.exs | 1 + 2 files changed, 10 insertions(+), 4 deletions(-) diff --git a/lib/elixir_script/preprocess/modules.ex b/lib/elixir_script/preprocess/modules.ex index 10dd45dd..1845dd29 100644 --- a/lib/elixir_script/preprocess/modules.ex +++ b/lib/elixir_script/preprocess/modules.ex @@ -12,10 +12,15 @@ defmodule ElixirScript.Preprocess.Modules do ] def get_info(modules) do - Enum.each(modules, fn(m) -> - Macro.postwalk(m, fn(x) -> - do_get_info(x) - end) + Enum.map(modules, fn + { :__block__, _, list } -> + list + x -> + x + end) + |> List.flatten + |> Enum.each(fn(m) -> + Macro.postwalk(m, &do_get_info(&1)) end) end diff --git a/test/elixir_script_test.exs b/test/elixir_script_test.exs index a7656949..1cb4dd24 100644 --- a/test/elixir_script_test.exs +++ b/test/elixir_script_test.exs @@ -29,6 +29,7 @@ defmodule ElixirScript.Test do to_string(10) end end + """) assert_js_matches """ From c573544371f1254d0d59d64b9c6d30ec4687d5c0 Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Fri, 23 Oct 2015 12:12:44 -0500 Subject: [PATCH 026/860] Simplified compile functions by making a temp module for non-module code --- lib/elixir_script.ex | 29 +-- lib/elixir_script/preprocess/modules.ex | 28 +- lib/elixir_script/translator/kernel.ex | 4 + lib/elixir_script/translator/module.ex | 4 + priv/javascript/lib/kernel.js | 325 +++++++++++++----------- test/elixir_script_test.exs | 4 +- 6 files changed, 216 insertions(+), 178 deletions(-) diff --git a/lib/elixir_script.ex b/lib/elixir_script.ex index 38ea5d30..fad46372 100644 --- a/lib/elixir_script.ex +++ b/lib/elixir_script.ex @@ -49,34 +49,7 @@ defmodule ElixirScript do build_environment([quoted]) state = ElixirScript.State.get() - - if Set.size(state.modules) > 0 || Dict.size(state.protocols) > 0 do - create_code(include_path, import_standard_libs?) - else - result = case Translator.translate(quoted, env) do - modules when is_list(modules) -> - List.flatten(modules) - |> Enum.map(fn(x) -> - convert_to_code(x, root, include_path, env, import_standard_libs?) - end) - module -> - List.wrap( - convert_to_code(module, root, include_path, env, import_standard_libs?) - ) - end - - ElixirScript.State.stop - - result - end - end - - def make_defmodule({:defmodule, _, _} = ast) do - ast - end - - def make_defmodule(ast) do - {:defmodule, [], [{:__aliases__, [], [:Temp]}, [do: { :__block__, [], [ast] }]]} + create_code(include_path, import_standard_libs?) end @doc """ diff --git a/lib/elixir_script/preprocess/modules.ex b/lib/elixir_script/preprocess/modules.ex index 1845dd29..2db7e4bb 100644 --- a/lib/elixir_script/preprocess/modules.ex +++ b/lib/elixir_script/preprocess/modules.ex @@ -14,9 +14,26 @@ defmodule ElixirScript.Preprocess.Modules do def get_info(modules) do Enum.map(modules, fn { :__block__, _, list } -> - list - x -> + {mods, no_mods} = Enum.partition(list, fn + ({:defprotocol, _, [{:__aliases__, _, protocol}| rest ] }) when not protocol in @standard_lib_protocols -> + true + ({:defimpl, _, [ {:__aliases__, _, protocol} | rest] }) when not protocol in @standard_lib_protocols -> + true + ({:defmodule, _, _}) -> + true + _ -> + false + end) + + mods ++ [{:defmodule, [], [{:__aliases__, [], [:ElixirScript, :Temp]}, [do: { :__block__, [], no_mods }]]}] + ({:defprotocol, _, [{:__aliases__, _, protocol}| rest ] }) = x when not protocol in @standard_lib_protocols -> x + ({:defimpl, _, [ {:__aliases__, _, protocol} | rest] }) = x when not protocol in @standard_lib_protocols -> + x + ({:defmodule, _, _}) = x -> + x + x -> + {:defmodule, [], [{:__aliases__, [], [:ElixirScript, :Temp]}, [do: { :__block__, [], [x] }]]} end) |> List.flatten |> Enum.each(fn(m) -> @@ -40,6 +57,13 @@ defmodule ElixirScript.Preprocess.Modules do ElixirScript.State.add_protocol_impl(protocol, type, {:__block__, [], [spec]}) end + def do_get_info({:defmodule, _, [{:__aliases__, meta, [:ElixirScript, :Temp]}, [do: body]]} = ast) do + mod = %ElixirScript.Module{ name: [:ElixirScript, :Temp] , body: body } + State.add_module(mod) + + ast + end + def do_get_info({:defmodule, _, [{:__aliases__, meta, module_name_list}, [do: body]]} = ast) do body = make_inner_module_aliases(module_name_list, body) diff --git a/lib/elixir_script/translator/kernel.ex b/lib/elixir_script/translator/kernel.ex index 147af9dc..b39d072a 100644 --- a/lib/elixir_script/translator/kernel.ex +++ b/lib/elixir_script/translator/kernel.ex @@ -216,6 +216,10 @@ defmodule ElixirScript.Translator.Kernel do |> Translator.translate(env) end + defp do_translate({:throw, _, [params]} = ast, env) do + JS.throw_statement(Translator.translate(params, env)) + end + defp do_translate({:|>, _, [left, right]}, env) do case right do {{:., meta, [module, fun]}, meta2, params} -> diff --git a/lib/elixir_script/translator/module.ex b/lib/elixir_script/translator/module.ex index b7d4e170..6228db61 100644 --- a/lib/elixir_script/translator/module.ex +++ b/lib/elixir_script/translator/module.ex @@ -9,6 +9,10 @@ defmodule ElixirScript.Translator.Module do alias ElixirScript.Translator.Function alias ElixirScript.Translator.Primitive + def make_module([:ElixirScript, :Temp], body, env) do + [%JSModule{ name: [:ElixirScript, :Temp], body: translate_body(body, env) |> Utils.inflate_groups }] + end + def make_module(module_name_list, nil, env) do [%JSModule{ name: module_name_list, body: List.wrap(create__module__(module_name_list, env)) }] end diff --git a/priv/javascript/lib/kernel.js b/priv/javascript/lib/kernel.js index ab040cb5..8b5ea067 100644 --- a/priv/javascript/lib/kernel.js +++ b/priv/javascript/lib/kernel.js @@ -5,171 +5,204 @@ import BitString from './bit_string'; import Protocol from './protocol'; import { PID } from './processes/processes'; -let Kernel = { - - SpecialForms: SpecialForms, - - tl: function(list){ - return SpecialForms.list(...list.slice(1)); - }, - - hd: function(list){ - return list[0]; - }, - - is_nil: function(x){ - return x == null; - }, - - is_atom: function(x){ - return typeof x === 'symbol'; - }, - - is_binary: function (x){ - return typeof x === 'string' || x instanceof String; - }, - - is_boolean: function (x){ - return typeof x === 'boolean' || x instanceof Boolean; - }, - - is_function: function(x, arity = -1){ - return typeof x === 'function' || x instanceof Function; - }, - - is_float: function(x){ - return Kernel.is_number(x) && !Number.isInteger(x); - }, - - is_integer: function(x){ - return Number.isInteger(x); - }, - - is_list: function(x){ - return x instanceof Array; - }, - - is_map: function(x){ - return typeof x === 'object' || x instanceof Object; - }, - - is_number: function(x){ - return typeof x === "number"; - }, - - is_tuple: function(x){ - return x instanceof Tuple; - }, - - length: function(x){ - return x.length; - }, - - is_pid: function(x){ - return x instanceof PID; - }, - - is_port: function(x){ - - }, - - is_reference: function(x){ - - }, - - is_bitstring: function(x){ - return Kernel.is_binary(x) || x instanceof BitString; - }, - - __in__: function(left, right){ - for(let x of right){ - if(Kernel.match__qmark__(left, x)){ - return true; - } +function tl(list){ + return SpecialForms.list(...list.slice(1)); +} + +function hd(list){ + return list[0]; +} + +function is_nil(x){ + return x === null; +} + +function is_atom(x){ + return typeof x === 'symbol'; +} + +function is_binary(x){ + return typeof x === 'string' || x instanceof String; +} + +function is_boolean(x){ + return typeof x === 'boolean' || x instanceof Boolean; +} + +function is_function(x, arity = -1){ + return typeof x === 'function' || x instanceof Function; +} + +function is_float(x){ + return is_number(x) && !Number.isInteger(x); +} + +function is_integer(x){ + return Number.isInteger(x); +} + +function is_list(x){ + return x instanceof Array; +} + +function is_map(x){ + return typeof x === 'object' || x instanceof Object; +} + +function is_number(x){ + return typeof x === "number"; +} + +function is_tuple(x){ + return x instanceof Tuple; +} + +function length(x){ + return x.length; +} + +function is_pid(x){ + return x instanceof PID; +} + +function is_port(x){ + return false; +} + +function is_reference(x){ + return false; +} + +function is_bitstring(x){ + return is_binary(x) || x instanceof BitString; +} + +function __in__(left, right){ + for(let x of right){ + if(match__qmark__(left, x)){ + return true; } + } - return false; - }, - - abs: function(number){ - return Math.abs(number); - }, - - round: function(number){ - return Math.round(number); - }, + return false; +} - elem: function(tuple, index){ - if(Kernel.is_list(tuple)){ - return tuple[index]; - } +function abs(number){ + return Math.abs(number); +} - return tuple.get(index); - }, +function round(number){ + return Math.round(number); +} - rem: function(left, right){ - return left % right; - }, +function elem(tuple, index){ + if(is_list(tuple)){ + return tuple[index]; + } - div: function(left, right){ - return left / right; - }, + return tuple.get(index); +} - and: function(left, right){ - return left && right; - }, +function rem(left, right){ + return left % right; +} - or: function(left, right){ - return left || right; - }, +function div(left, right){ + return left / right; +} - not: function(arg){ - return !arg; - }, +function and(left, right){ + return left && right; +} - apply: function(module, func, args){ - if(arguments.length === 3){ - return module[func].apply(null, args); - }else{ - return module.apply(null, func); - } - }, +function or(left, right){ + return left || right; +} - to_string: function(arg){ - if(Kernel.is_tuple(arg)){ - return Tuple.to_string(arg); - } +function not(arg){ + return !arg; +} - return arg.toString(); - }, +function apply(...args){ + if(args.length === 3){ + let mod = args[0]; + let func = args[1]; + let func_args = args[2]; + return mod[func].apply(null, func_args); + }else{ + let func = args[0]; + let func_args = args[1]; - throw: function(e){ - throw e; - }, + return func.apply(null, func_args); + } +} - match__qmark__: function(pattern, expr, guard = () => true){ - return Patterns.match_no_throw(pattern, expr, guard) != null; - }, +function to_string(arg){ + if(is_tuple(arg)){ + return Tuple.to_string(arg); + } - defstruct: function(defaults, values){ - return Kernel.SpecialForms.map_update(defaults, values); - }, + return arg.toString(); +} - is_struct_fn: function(__struct__){ - return function(x){ - return Kernel.is_map && x[Kernel.SpecialForms.atom("__struct__")] === __struct__; - } - }, +function match__qmark__(pattern, expr, guard = () => true){ + return Patterns.match_no_throw(pattern, expr, guard) != null; +} - defprotocol: function(spec){ - return new Protocol(spec); - }, +function defstruct(defaults, values){ + return SpecialForms.map_update(defaults, values); +} - defimpl: function(protocol, type, impl){ - protocol.implementation(type, impl); +function is_struct_fn(__struct__){ + return function(x){ + return is_map && x[SpecialForms.atom("__struct__")] === __struct__; } +} + +function defprotocol(spec){ + return new Protocol(spec); +} + +function defimpl(protocol, type, impl){ + protocol.implementation(type, impl); +} + +export default { + SpecialForms, + tl, + hd, + is_nil, + is_atom, + is_binary, + is_boolean, + is_function, + is_float, + is_integer, + is_list, + is_map, + is_number, + is_tuple, + length, + is_pid, + is_port, + is_reference, + is_bitstring, + __in__, + abs, + round, + elem, + rem, + div, + and, + or, + not, + apply, + to_string, + match__qmark__, + defstruct, + is_struct_fn, + defprotocol, + defimpl }; -export default Kernel; - diff --git a/test/elixir_script_test.exs b/test/elixir_script_test.exs index 1cb4dd24..287ab447 100644 --- a/test/elixir_script_test.exs +++ b/test/elixir_script_test.exs @@ -7,12 +7,12 @@ defmodule ElixirScript.Test do JQuery.("
").text(html) """) - assert hd(js_code) == "JQuery('
').text(html)" + assert hd(js_code) =~ "JQuery('
').text(html)" end should "turn javascript ast into javascript code strings" do js_code = ElixirScript.compile(":atom") - assert hd(js_code) == "Elixir.Kernel.SpecialForms.atom('atom')" + assert hd(js_code) =~ "Elixir.Kernel.SpecialForms.atom('atom')" end should "parse one module correctly" do From 1c166307746e29c84e04d26027c3b2a3ef392fbb Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Fri, 23 Oct 2015 12:34:54 -0500 Subject: [PATCH 027/860] Added support for the list prepend operator --- lib/elixir_script/translator/primitive.ex | 8 ++++++++ priv/javascript/lib/list.js | 4 ++++ test/translator/list_test.exs | 8 ++++++++ 3 files changed, 20 insertions(+) diff --git a/lib/elixir_script/translator/primitive.ex b/lib/elixir_script/translator/primitive.ex index f72612a8..07dda4d0 100644 --- a/lib/elixir_script/translator/primitive.ex +++ b/lib/elixir_script/translator/primitive.ex @@ -55,6 +55,14 @@ defmodule ElixirScript.Translator.Primitive do ) end + def make_list([{:|, [], [elem, list]}], env) do + quoted = quote do + List.prepend(unquote(list), unquote(elem)) + end + + Translator.translate(quoted, env) + end + def make_list(ast, env) when is_list(ast) do JS.call_expression( JS.member_expression( diff --git a/priv/javascript/lib/list.js b/priv/javascript/lib/list.js index b2f154a2..38493dac 100644 --- a/priv/javascript/lib/list.js +++ b/priv/javascript/lib/list.js @@ -268,6 +268,10 @@ List.append = function(list, value){ return Kernel.SpecialForms.list(...list.concat([value])); }; +List.prepend = function(list, value){ + return Kernel.SpecialForms.list(...[value].concat(list)); +}; + List.concat = function(left, right){ return left.concat(right); }; diff --git a/test/translator/list_test.exs b/test/translator/list_test.exs index 698e77d7..8bed43f0 100644 --- a/test/translator/list_test.exs +++ b/test/translator/list_test.exs @@ -35,4 +35,12 @@ defmodule ElixirScript.Translator.List.Test do assert_translation(ex_ast, js_code) end + + should "prepend element" do + ex_ast = quote do: [x|list] + + js_code = "Elixir.List.prepend(list, x)" + + assert_translation(ex_ast, js_code) + end end \ No newline at end of file From 92bd6e984ed63c6cbedbb0cfa3a438271bbee991 Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Fri, 23 Oct 2015 13:04:14 -0500 Subject: [PATCH 028/860] Added List.prepend. Refactored protocol module --- lib/elixir_script/translator.ex | 8 ++ lib/elixir_script/translator/function.ex | 1 + lib/elixir_script/translator/primitive.ex | 8 +- lib/elixir_script/translator/protocol.ex | 112 ++++++---------------- test/translator/list_test.exs | 14 +++ 5 files changed, 52 insertions(+), 91 deletions(-) diff --git a/lib/elixir_script/translator.ex b/lib/elixir_script/translator.ex index 530835bd..0caad9e7 100644 --- a/lib/elixir_script/translator.ex +++ b/lib/elixir_script/translator.ex @@ -311,6 +311,14 @@ defmodule ElixirScript.Translator do %ElixirScript.Translator.Group{} end + defp do_translate({:|, _, [elem, list]}, env) do + quoted = quote do + List.prepend(unquote(list), unquote(elem)) + end + + translate(quoted, env) + end + defp do_translate({name, metadata, params} = ast, env) when is_list(params) do if KernelLib.is_defined_in_kernel(name, length(params)) do KernelLib.translate_kernel_function(name, params, env) diff --git a/lib/elixir_script/translator/function.ex b/lib/elixir_script/translator/function.ex index 0ce5141a..e0716bed 100644 --- a/lib/elixir_script/translator/function.ex +++ b/lib/elixir_script/translator/function.ex @@ -55,6 +55,7 @@ defmodule ElixirScript.Translator.Function do end def make_anonymous_function(functions, env) do + clauses = functions |> Stream.map(fn(x) -> Variables.process(x) end) |> Stream.map(fn diff --git a/lib/elixir_script/translator/primitive.ex b/lib/elixir_script/translator/primitive.ex index 07dda4d0..ba895901 100644 --- a/lib/elixir_script/translator/primitive.ex +++ b/lib/elixir_script/translator/primitive.ex @@ -55,12 +55,8 @@ defmodule ElixirScript.Translator.Primitive do ) end - def make_list([{:|, [], [elem, list]}], env) do - quoted = quote do - List.prepend(unquote(list), unquote(elem)) - end - - Translator.translate(quoted, env) + def make_list([{:|, _, [elem, list]} = ast], env) do + Translator.translate(ast, env) end def make_list(ast, env) when is_list(ast) do diff --git a/lib/elixir_script/translator/protocol.ex b/lib/elixir_script/translator/protocol.ex index 3e36d639..1da884c4 100644 --- a/lib/elixir_script/translator/protocol.ex +++ b/lib/elixir_script/translator/protocol.ex @@ -10,6 +10,9 @@ defmodule ElixirScript.Translator.Protocol do alias ElixirScript.Translator.Function alias ElixirScript.Translator.Utils + @doc """ + Takes a list of protocols and turns them into modules + """ def consolidate(protocols, env) when is_list(protocols) do Enum.map(protocols, fn({_, protocol}) -> do_consolidate(protocol, env) @@ -36,7 +39,7 @@ defmodule ElixirScript.Translator.Protocol do { body, functions } = extract_function_from_spec(body) - { exported_functions, private_functions } = process_functions(functions, env) + { exported_functions, _ } = process_functions(functions, env) body = Module.translate_body(body, env) @@ -76,7 +79,7 @@ defmodule ElixirScript.Translator.Protocol do type = map_to_js(type) { body, aliases } = Aliases.process(impl, env) { body, functions } = Module.extract_functions_from_module(body) - { exported_functions, private_functions } = process_functions(functions, env) + { exported_functions, _ } = process_functions(functions, env) body = Module.translate_body(body, env) @@ -178,120 +181,48 @@ defmodule ElixirScript.Translator.Protocol do { exported_functions, private_functions } end - - @doc """ - Used to map Protocol types from Elixir to - a function used by the protocol implementation - in JavaScript - """ defp map_to_js({:__aliases__, _, [:Integer]}) do - JS.member_expression( - JS.identifier(:Elixir), - JS.member_expression( - JS.identifier(:Kernel), - JS.identifier(:is_integer) - ) - ) + do_map_to_js(:is_integer) end defp map_to_js({:__aliases__, _, [:Tuple]}) do - JS.member_expression( - JS.identifier(:Elixir), - JS.member_expression( - JS.identifier(:Kernel), - JS.identifier(:is_tuple) - ) - ) + do_map_to_js(:is_tuple) end defp map_to_js({:__aliases__, _, [:Atom]}) do - JS.member_expression( - JS.identifier(:Elixir), - JS.member_expression( - JS.identifier(:Kernel), - JS.identifier(:is_atom) - ) - ) + do_map_to_js(:is_atom) end defp map_to_js({:__aliases__, _, [:List]}) do - JS.member_expression( - JS.identifier(:Elixir), - JS.member_expression( - JS.identifier(:Kernel), - JS.identifier(:is_list) - ) - ) + do_map_to_js(:is_list) end defp map_to_js({:__aliases__, _, [:BitString]}) do - JS.member_expression( - JS.identifier(:Elixir), - JS.member_expression( - JS.identifier(:Kernel), - JS.identifier(:is_bitstring) - ) - ) + do_map_to_js(:is_bitstring) end defp map_to_js({:__aliases__, _, [:Float]}) do - JS.member_expression( - JS.identifier(:Elixir), - JS.member_expression( - JS.identifier(:Kernel), - JS.identifier(:is_float) - ) - ) + do_map_to_js(:is_float) end defp map_to_js({:__aliases__, _, [:Function]}) do - JS.member_expression( - JS.identifier(:Elixir), - JS.member_expression( - JS.identifier(:Kernel), - JS.identifier(:is_function) - ) - ) + do_map_to_js(:is_function) end defp map_to_js({:__aliases__, _, [:PID]}) do - JS.member_expression( - JS.identifier(:Elixir), - JS.member_expression( - JS.identifier(:Kernel), - JS.identifier(:is_pid) - ) - ) + do_map_to_js(:is_pid) end defp map_to_js({:__aliases__, _, [:Port]}) do - JS.member_expression( - JS.identifier(:Elixir), - JS.member_expression( - JS.identifier(:Kernel), - JS.identifier(:is_port) - ) - ) + do_map_to_js(:is_port) end defp map_to_js({:__aliases__, _, [:Reference]}) do - JS.member_expression( - JS.identifier(:Elixir), - JS.member_expression( - JS.identifier(:Kernel), - JS.identifier(:is_reference) - ) - ) + do_map_to_js(:is_reference) end defp map_to_js({:__aliases__, _, [:Map]}) do - JS.member_expression( - JS.identifier(:Elixir), - JS.member_expression( - JS.identifier(:Kernel), - JS.identifier(:is_map) - ) - ) + do_map_to_js(:is_map) end defp map_to_js({:__aliases__, _, [:Any]}) do @@ -315,4 +246,15 @@ defmodule ElixirScript.Translator.Protocol do Translator.translate(quoted, ElixirScript.State.get().env) end + + defp do_map_to_js(identifier) do + JS.member_expression( + JS.identifier(:Elixir), + JS.member_expression( + JS.identifier(:Kernel), + JS.identifier(identifier) + ) + ) + end + end \ No newline at end of file diff --git a/test/translator/list_test.exs b/test/translator/list_test.exs index 8bed43f0..05e5244b 100644 --- a/test/translator/list_test.exs +++ b/test/translator/list_test.exs @@ -43,4 +43,18 @@ defmodule ElixirScript.Translator.List.Test do assert_translation(ex_ast, js_code) end + + should "prepend element in function" do + ex_ast = quote do + fn (_) -> [x|list] end + end + + js_code = """ + Elixir.Patterns.defmatch(Elixir.Patterns.make_case([Elixir.Patterns.wildcard()],function(){ + return Elixir.List.prepend(list, x); + })) + """ + + assert_translation(ex_ast, js_code) + end end \ No newline at end of file From 48f304e7a4014ef3ead35fd64e978b457bf5aeeb Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Fri, 23 Oct 2015 13:07:00 -0500 Subject: [PATCH 029/860] Updated FAQ --- FAQ.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/FAQ.md b/FAQ.md index b1e385f4..747cab2c 100644 --- a/FAQ.md +++ b/FAQ.md @@ -92,7 +92,7 @@ You **can** use ElixirScript on your front ends and have it work and interoperat ## Q. Can I use processes? -### A. No, but follow [this issue](https://github.com/bryanjos/elixirscript/issues/95). Any ideas or contributions are appreciated. +### A. No, but follow [this issue](https://github.com/bryanjos/elixirscript/issues/99). Any ideas or contributions are appreciated. From 39bb47b54fef7ce833501474dd78ea45ada42804 Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Fri, 23 Oct 2015 13:09:28 -0500 Subject: [PATCH 030/860] Updated CHANGELOG --- CHANGELOG.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index cc676463..d7c21857 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,8 @@ * Added Base module with function: encode64, decode64, and decode64! * Added String module * Added Bitwise module + * Protocol support + * Added `Collectable`, `Enumerable`, `Inspect`, `List.Chars`, and `String.Chars` protocols # v0.12.0 * Enhancements From f1f885e4e568a509e2b15907424cb8c1f6a23674 Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Fri, 23 Oct 2015 14:03:02 -0500 Subject: [PATCH 031/860] Removed implementations from Collectable, and Inspect --- priv/javascript/lib/collectable.js | 54 ----------------------------- priv/javascript/lib/inspect.js | 6 ---- priv/javascript/lib/string/chars.js | 7 ++++ 3 files changed, 7 insertions(+), 60 deletions(-) diff --git a/priv/javascript/lib/collectable.js b/priv/javascript/lib/collectable.js index 7fbd6eb2..6462da3a 100644 --- a/priv/javascript/lib/collectable.js +++ b/priv/javascript/lib/collectable.js @@ -6,58 +6,4 @@ let Collectable = Kernel.defprotocol({ into: function(collectable){} }); -Kernel.defimpl(Collectable, Kernel.is_list, { - into: function(collectable){ - let original_value = Kernel.SpecialForms.list(); - - let fn = Patterns.defmatch( - Patterns.make_case( - [Patterns.parameter(), Kernel.SpecialForms.tuple(Kernel.SpecialForms.atom("cont"), Patterns.parameter())], - function(list, x){ - return List.append(list, x); - }), - Patterns.make_case( - [Patterns.parameter(), Kernel.SpecialForms.atom("done")], - function(list){ - return List.concat(collectable, list); - }), - Patterns.make_case( - [Patterns.wildcard(), Kernel.SpecialForms.atom("halt")], - function(){ - return Kernel.SpecialForms.atom("ok"); - }) - ); - - - return Kernel.SpecialForms.tuple(original_value, fn); - } -}); - - -Kernel.defimpl(Collectable, Kernel.is_map, { - into: function(collectable){ - - let fn = Patterns.defmatch( - Patterns.make_case( - [Patterns.parameter(), Kernel.SpecialForms.tuple(Kernel.SpecialForms.atom("cont"), Kernel.SpecialForms.tuple(Patterns.parameter(), Patterns.parameter()))], - function(map, key, value){ - return Kernel.SpecialForms.map_update(map, { [key]: value }); - }), - Patterns.make_case( - [Patterns.parameter(), Kernel.SpecialForms.atom("done")], - function(map){ - return map; - }), - Patterns.make_case( - [Patterns.wildcard(), Kernel.SpecialForms.atom("halt")], - function(){ - return Kernel.SpecialForms.atom("ok"); - }) - ); - - - return Kernel.SpecialForms.tuple(collectable, fn); - } -}); - export default Collectable; \ No newline at end of file diff --git a/priv/javascript/lib/inspect.js b/priv/javascript/lib/inspect.js index 6e38fa54..e9a7f140 100644 --- a/priv/javascript/lib/inspect.js +++ b/priv/javascript/lib/inspect.js @@ -4,10 +4,4 @@ let Inspect = Kernel.defprotocol({ inspect: function(thing, opts){} }); -Kernel.defimpl(Inspect, null, { - inspect: function(thing, opts){ - return thing.toString(); - } -}); - export default Inspect; \ No newline at end of file diff --git a/priv/javascript/lib/string/chars.js b/priv/javascript/lib/string/chars.js index 320857bc..5e1570fb 100644 --- a/priv/javascript/lib/string/chars.js +++ b/priv/javascript/lib/string/chars.js @@ -52,4 +52,11 @@ Kernel.defimpl(Chars, Kernel.is_tuple, { } }); + +Kernel.defimpl(Chars, null, { + to_string: function(thing){ + return thing.toString(); + } +}); + export default Chars; \ No newline at end of file From 1f785302260dae435547a9c2e49bcdb6ee825b0f Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Fri, 23 Oct 2015 14:15:41 -0500 Subject: [PATCH 032/860] Ignoring @doc and @moduledoc --- lib/elixir_script/translator.ex | 8 ++++++++ test/elixir_script_test.exs | 1 + 2 files changed, 9 insertions(+) diff --git a/lib/elixir_script/translator.ex b/lib/elixir_script/translator.ex index 0caad9e7..6ddce36a 100644 --- a/lib/elixir_script/translator.ex +++ b/lib/elixir_script/translator.ex @@ -77,6 +77,14 @@ defmodule ElixirScript.Translator do Function.make_anonymous_function([{:->, [], [params, body]}], env) end + defp do_translate({:@, _, [{:doc, _, _}]}, env) do + %ElixirScript.Translator.Group{} + end + + defp do_translate({:@, _, [{:moduledoc, _, _}]}, env) do + %ElixirScript.Translator.Group{} + end + defp do_translate({:@, _, [{name, _, [value]}]}, env) do name = Utils.filter_name(name) Module.make_attribute(name, value, env) diff --git a/test/elixir_script_test.exs b/test/elixir_script_test.exs index 287ab447..e1277059 100644 --- a/test/elixir_script_test.exs +++ b/test/elixir_script_test.exs @@ -21,6 +21,7 @@ defmodule ElixirScript.Test do defmodule Elephant do @ul JQuery.("#todo-list") + @doc "ignore" def something() do @ul end From 48a6cea7d43ab5dcf7a1a2aa3c481e9f8b3d0cb0 Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Fri, 23 Oct 2015 15:51:13 -0500 Subject: [PATCH 033/860] Added Map and MapSet --- CHANGELOG.md | 2 + lib/elixir_script/translator/function.ex | 2 +- lib/elixir_script/translator/utils.ex | 8 + priv/javascript/elixir.js | 2 + priv/javascript/lib/list.js | 2 +- priv/javascript/lib/map.js | 266 +++++++++++++++++++++++ priv/javascript/lib/map_set.js | 115 ++++++++++ priv/javascript/tests/list.spec.js | 2 +- 8 files changed, 396 insertions(+), 3 deletions(-) create mode 100644 priv/javascript/lib/map.js create mode 100644 priv/javascript/lib/map_set.js diff --git a/CHANGELOG.md b/CHANGELOG.md index d7c21857..c86f5115 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,8 @@ * Added Base module with function: encode64, decode64, and decode64! * Added String module * Added Bitwise module + * Added Map module + * Added MapSet module * Protocol support * Added `Collectable`, `Enumerable`, `Inspect`, `List.Chars`, and `String.Chars` protocols diff --git a/lib/elixir_script/translator/function.ex b/lib/elixir_script/translator/function.ex index e0716bed..86934291 100644 --- a/lib/elixir_script/translator/function.ex +++ b/lib/elixir_script/translator/function.ex @@ -11,7 +11,7 @@ defmodule ElixirScript.Translator.Function do :Patterns, :Kernel, :Atom, :Enum, :Integer, :JS, :List, :Range, :Tuple, :Agent, :Keyword, :BitString, :Base, :String, :Bitwise, :Collectable, :Enumerable, - :Inspect + :Inspect, :Map, :MapSet ] def update_alias({:__aliases__, context, [:List, :Chars]}) do diff --git a/lib/elixir_script/translator/utils.ex b/lib/elixir_script/translator/utils.ex index c1d085a4..8b72678a 100644 --- a/lib/elixir_script/translator/utils.ex +++ b/lib/elixir_script/translator/utils.ex @@ -177,6 +177,14 @@ defmodule ElixirScript.Translator.Utils do "__in__" end + def filter_name(:new) do + "__new__" + end + + def filter_name(:delete) do + "__delete__" + end + def filter_name(name) do to_string(name) |> String.replace("?", "__qmark__") diff --git a/priv/javascript/elixir.js b/priv/javascript/elixir.js index 6d396ae7..69635a16 100644 --- a/priv/javascript/elixir.js +++ b/priv/javascript/elixir.js @@ -20,4 +20,6 @@ export { default as Bitwise } from './lib/bitwise'; export { default as Enumerable } from './lib/enumerable'; export { default as Collectable } from './lib/collectable'; export { default as Inspect } from './lib/inspect'; +export { default as Map } from './lib/map'; +export { default as MapSet } from './lib/map_set'; diff --git a/priv/javascript/lib/list.js b/priv/javascript/lib/list.js index 38493dac..86b2bc64 100644 --- a/priv/javascript/lib/list.js +++ b/priv/javascript/lib/list.js @@ -5,7 +5,7 @@ let List = {}; List.Chars = Chars; -List.delete = function(list, item){ +List.__delete__ = function(list, item){ let new_value = []; let value_found = false; diff --git a/priv/javascript/lib/map.js b/priv/javascript/lib/map.js new file mode 100644 index 00000000..5b3758bf --- /dev/null +++ b/priv/javascript/lib/map.js @@ -0,0 +1,266 @@ +import SpecialForms from './kernel/special_forms'; +import List from './list'; + +function __new__(){ + return SpecialForms.map({}); +} + +function keys(map){ + return Object.keys(map); +} + +function size(map){ + return keys(map).length; +} + +function to_list(map){ + let map_keys = keys(map); + let list = []; + + for(let key of map_keys){ + list.push(SpecialForms.tuple(key, map[key])); + } + + return SpecialForms.list(...list); +} + +function values(map){ + let map_keys = keys(map); + let list = []; + + for(let key of map_keys){ + list.push(map[key]); + } + + return SpecialForms.list(...list); +} + +function from_struct(struct){ + let map = Object.assign({}, struct); + delete map[Symbol.for("__struct__")]; + + return SpecialForms.map(map); +} + +function __delete__(map, key){ + let new_map = Object.assign({}, map); + + delete new_map[key]; + + return SpecialForms.map(new_map); +} + +function drop(map, keys){ + let new_map = Object.assign({}, map); + + for(let key of keys){ + delete new_map[key]; + } + + return SpecialForms.map(new_map); +} + + +function equal__qmark__(map1, map2){ + return map1 === map2; +} + +function fetch__emark__(map, key){ + if(key in map){ + return map[key] + } + + throw new Error("Key not found."); +} + +function fetch(map, key){ + if(key in map){ + return SpecialForms.tuple(SpecialForms.atom("ok"), map[key]); + } + + return SpecialForms.atom("error"); +} + +function has_key__qmark__(map, key){ + return key in map; +} + +function merge(map1, map2){ + return SpecialForms.map_update(map1, map2); +} + +function split(map, keys){ + let split1 = {}; + let split2 = {}; + + for(let key of Object.keys(map)){ + if(keys.indexOf(key) > -1){ + split1[key] = map[key]; + }else{ + split2[key] = map[key]; + } + } + + return SpecialForms.tuple( + SpecialForms.map(split1), + SpecialForms.map(split2) + ); +} + +function take(map, keys){ + let split1 = {}; + + for(let key of Object.keys(map)){ + if(keys.indexOf(key) > -1){ + split1[key] = map[key]; + } + } + + return SpecialForms.map(split1); +} + +function drop(map, keys){ + let split1 = {}; + + for(let key of Object.keys(map)){ + if(keys.indexOf(key) === -1){ + split1[key] = map[key]; + } + } + + return SpecialForms.map(split1); +} + +function put_new(map, key, value){ + if(key in map){ + return map; + } + + let new_map = Object.assign({}, map); + new_map[key] = value; + + return SpecialForms.map(new_map); +} + +function put_new_lazy(map, key, fun){ + if(key in map){ + return map; + } + + let new_map = Object.assign({}, map); + new_map[key] = fun(); + + return SpecialForms.map(new_map); +} + +function get_and_update(map, key, fun){ + if(key in map){ + return map; + } + + let new_map = Object.assign({}, map); + new_map[key] = fun(map[key]); + + return SpecialForms.map(new_map); +} + +function pop_lazy(map, key, fun){ + if(!key in map){ + return SpecialForms.tuple(fun(), map); + } + + let new_map = Object.assign({}, map); + let value = fun(new_map[key]); + delete new_map[key]; + + return SpecialForms.tuple(value, new_map); +} + + +function pop(map, key, _default = null){ + if(!key in map){ + return SpecialForms.tuple(_default, map); + } + + let new_map = Object.assign({}, map); + let value = new_map[key]; + delete new_map[key]; + + return SpecialForms.tuple(value, new_map); +} + +function get_lazy(map, key, fun){ + if(!key in map){ + return fun(); + } + + return fun(map[key]); +} + + +function get(map, key, _default = null){ + if(!key in map){ + return _default; + } + + return map[key]; +} + +function put(map, key, val){ + let new_map = Object({}, map); + new_map[key] = val; + + return SpecialForms.map(new_map); +} + +function update__emark__(map, key, fun){ + if(!key in map){ + throw new Error("Key not found"); + } + + let new_map = Object({}, map); + new_map[key] = fun(map[key]); + + return SpecialForms.map(new_map); +} + +function update(map, key, initial, fun){ + let new_map = Object({}, map); + + if(!key in map){ + new_map[key] = initial; + }else{ + new_map[key] = fun(map[key]); + } + + return SpecialForms.map(new_map); +} + + +export default { + __new__, + keys, + size, + to_list, + values, + from_struct, + __delete__, + drop, + equal__qmark__, + fetch__emark__, + fetch, + has_key__qmark__, + split, + take, + drop, + put_new, + put_new_lazy, + get_and_update, + pop_lazy, + pop, + get_lazy, + get, + put, + update__emark__, + update +} \ No newline at end of file diff --git a/priv/javascript/lib/map_set.js b/priv/javascript/lib/map_set.js new file mode 100644 index 00000000..51373bb2 --- /dev/null +++ b/priv/javascript/lib/map_set.js @@ -0,0 +1,115 @@ +import SpecialForms from './kernel/special_forms'; +import List from './list'; + +function __new__(){ + return SpecialForms.map({ [Symbol.for("__struct__")]: Symbol.for("MapSet"), set: SpecialForms.list() }); +} + +function size(map){ + return keys(map.set).length; +} + +function to_list(map){ + return map.set; +} + +function __delete__(set, term){ + let new_list = List.__delete__(set.set, term); + + let new_map = Object.assign({}, set); + new_map.set = new_list; + return SpecialForms.map(new_map); +} + +function put(set, term){ + if(set.set.indexOf(term) === -1){ + let new_list = List.append(set.set, term); + + let new_map = Object.assign({}, set); + new_map.set = new_list; + return SpecialForms.map(new_map); + } + + return set; +} + +function difference(set1, set2){ + let new_map = Object.assign({}, set1); + + for(let val of set1.set){ + if(member__qmark__(set2, val)){ + new_map.set = List.__delete__(new_map.set, val); + } + } + + return SpecialForms.map(new_map); +} + + +function intersection(set1, set2){ + let new_map = Object.assign({}, set1); + + for(let val of set1.set){ + if(!member__qmark__(set2, val)){ + new_map.set = List.__delete__(new_map.set, val); + } + } + + return SpecialForms.map(new_map); +} + + +function union(set1, set2){ + let new_map = set1; + + for(let val of set2.set){ + new_map = put(set, val); + } + + return SpecialForms.map(new_map); +} + + +function disjoin__qmark__(set1, set2){ + for(let val of set1.set){ + if(member__qmark__(set2, val)){ + return false; + } + } + + return true; +} + +function member__qmark__(set, value){ + return set.set.indexof(value) >= 0; +} + +function equal__qmark__(set1, set2){ + return set1.set === set2.set; +} + +function subset__qmark__(set1, set2){ + for(let val of set1.set){ + if(!member__qmark__(set2, val)){ + return false; + } + } + + return true; +} + + +export default { + __new__, + size, + to_list, + disjoin__qmark__, + __delete__, + subset__qmark__, + equal__qmark__, + member__qmark__, + put, + union, + intersection, + difference +} \ No newline at end of file diff --git a/priv/javascript/tests/list.spec.js b/priv/javascript/tests/list.spec.js index 8f49edc5..bc43b605 100644 --- a/priv/javascript/tests/list.spec.js +++ b/priv/javascript/tests/list.spec.js @@ -29,7 +29,7 @@ describe('List', function(){ describe('delete', function(){ it('delete item in list', function(){ let t = Kernel.SpecialForms.list(Kernel.SpecialForms.atom("a"), Kernel.SpecialForms.atom("b"), Kernel.SpecialForms.atom("c")); - t = List.delete(t, Kernel.SpecialForms.atom("b")); + t = List.__delete__(t, Kernel.SpecialForms.atom("b")); expect(t[1]).to.equal(Kernel.SpecialForms.atom("c")); }) }) From 5ce14e8af47bab1f1292e31c47381ad061dba893 Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Fri, 23 Oct 2015 17:03:51 -0500 Subject: [PATCH 034/860] Added set.js --- FAQ.md | 3 ++ lib/elixir_script/translator/function.ex | 2 +- priv/javascript/elixir.js | 1 + priv/javascript/lib/set.js | 60 ++++++++++++++++++++++++ 4 files changed, 65 insertions(+), 1 deletion(-) create mode 100644 priv/javascript/lib/set.js diff --git a/FAQ.md b/FAQ.md index 747cab2c..7a0c79d7 100644 --- a/FAQ.md +++ b/FAQ.md @@ -64,6 +64,8 @@ The compiler to this point has been focused on translating Kernel.SpecialForms a * Atom * Range * Logger + * Map + * MapSet #### Incomplete Modules @@ -75,6 +77,7 @@ The compiler to this point has been focused on translating Kernel.SpecialForms a * Base * String * Bitwise + * Set #### Missing Modules * Everything else diff --git a/lib/elixir_script/translator/function.ex b/lib/elixir_script/translator/function.ex index 86934291..866ad79d 100644 --- a/lib/elixir_script/translator/function.ex +++ b/lib/elixir_script/translator/function.ex @@ -11,7 +11,7 @@ defmodule ElixirScript.Translator.Function do :Patterns, :Kernel, :Atom, :Enum, :Integer, :JS, :List, :Range, :Tuple, :Agent, :Keyword, :BitString, :Base, :String, :Bitwise, :Collectable, :Enumerable, - :Inspect, :Map, :MapSet + :Inspect, :Map, :MapSet, :Set ] def update_alias({:__aliases__, context, [:List, :Chars]}) do diff --git a/priv/javascript/elixir.js b/priv/javascript/elixir.js index 69635a16..d172cd88 100644 --- a/priv/javascript/elixir.js +++ b/priv/javascript/elixir.js @@ -21,5 +21,6 @@ export { default as Enumerable } from './lib/enumerable'; export { default as Collectable } from './lib/collectable'; export { default as Inspect } from './lib/inspect'; export { default as Map } from './lib/map'; +export { default as Set } from './lib/set'; export { default as MapSet } from './lib/map_set'; diff --git a/priv/javascript/lib/set.js b/priv/javascript/lib/set.js new file mode 100644 index 00000000..3a6d4030 --- /dev/null +++ b/priv/javascript/lib/set.js @@ -0,0 +1,60 @@ +import MapSet from './map_set'; + +function size(map){ + return MapSet.size(map); +} + +function to_list(map){ + return MapSet.to_list(map); +} + +function __delete__(set, term){ + return MapSet.__delete__(set, term); +} + +function put(set, term){ + return MapSet.put(set, term); +} + +function difference(set1, set2){ + return MapSet.difference(set1, set2); +} + +function intersection(set1, set2){ + return MapSet.intersection(set1, set2); +} + +function union(set1, set2){ + return MapSet.union(set1, set2); +} + +function disjoin__qmark__(set1, set2){ + return MapSet.disjoin__qmark__(set1, set2); +} + +function member__qmark__(set, value){ + return MapSet.member__qmark__(set1, set2); +} + +function equal__qmark__(set1, set2){ + return MapSet.equal__qmark__(set1, set2); +} + +function subset__qmark__(set1, set2){ + return MapSet.subset__qmark__(set1, set2); +} + + +export default { + size, + to_list, + disjoin__qmark__, + __delete__, + subset__qmark__, + equal__qmark__, + member__qmark__, + put, + union, + intersection, + difference +} \ No newline at end of file From 06c395c62bc3770a084a33cf9a95e8b4dbb95b0e Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Fri, 23 Oct 2015 17:04:44 -0500 Subject: [PATCH 035/860] Updated CHANGELOG --- CHANGELOG.md | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index c86f5115..5b455cf7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,10 +1,11 @@ # v0.13.0-dev * Enhancements - * Added Base module with function: encode64, decode64, and decode64! - * Added String module - * Added Bitwise module - * Added Map module - * Added MapSet module + * Added `Base` module with function: encode64, decode64, and decode64! + * Added `String` module + * Added `Bitwise` module + * Added `Map` module + * Added `MapSet` module + * Added `Set` module * Protocol support * Added `Collectable`, `Enumerable`, `Inspect`, `List.Chars`, and `String.Chars` protocols From 3634f91d1e14209e3e30e0d3e7955514815b3dd1 Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Fri, 23 Oct 2015 21:55:31 -0500 Subject: [PATCH 036/860] Added tests for Map and Set --- priv/javascript/lib/map_set.js | 6 +- priv/javascript/tests/map.spec.js | 39 +++++++++++ priv/javascript/tests/set.spec.js | 106 ++++++++++++++++++++++++++++++ 3 files changed, 148 insertions(+), 3 deletions(-) create mode 100644 priv/javascript/tests/map.spec.js create mode 100644 priv/javascript/tests/set.spec.js diff --git a/priv/javascript/lib/map_set.js b/priv/javascript/lib/map_set.js index 51373bb2..c4cfefb4 100644 --- a/priv/javascript/lib/map_set.js +++ b/priv/javascript/lib/map_set.js @@ -6,7 +6,7 @@ function __new__(){ } function size(map){ - return keys(map.set).length; + return map.set.length; } function to_list(map){ @@ -63,7 +63,7 @@ function union(set1, set2){ let new_map = set1; for(let val of set2.set){ - new_map = put(set, val); + new_map = put(new_map, val); } return SpecialForms.map(new_map); @@ -81,7 +81,7 @@ function disjoin__qmark__(set1, set2){ } function member__qmark__(set, value){ - return set.set.indexof(value) >= 0; + return set.set.indexOf(value) >= 0; } function equal__qmark__(set1, set2){ diff --git a/priv/javascript/tests/map.spec.js b/priv/javascript/tests/map.spec.js new file mode 100644 index 00000000..928dc505 --- /dev/null +++ b/priv/javascript/tests/map.spec.js @@ -0,0 +1,39 @@ +var Map = require('../lib/map'); +var Kernel = require('../lib/kernel'); +var expect = require('chai').expect; + +describe('Map', function(){ + + it('new', function(){ + let map = Map.__new__(); + + expect(Object.keys(map).length).to.equal(0); + }); + + it('keys', function(){ + let map = Map.__new__(); + expect(Map.keys(map)).to.deep.equal([]); + + map = Map.put(map, "hello", "world"); + expect(Map.keys(map)).to.deep.equal(["hello"]); + }); + + it('to_list', function(){ + let map = Map.__new__(); + + map = Map.put(map, "hello", "world"); + expect(Map.to_list(map)).to.deep.equal([Kernel.SpecialForms.tuple("hello", "world")]); + }); + + it('delete', function(){ + let map = Map.__new__(); + + map = Map.put(map, "hello", "world"); + expect(Map.keys(map).length).to.equal(1); + + map = Map.__delete__(map, "hello") + expect(Map.keys(map).length).to.equal(0); + }); + +}) + diff --git a/priv/javascript/tests/set.spec.js b/priv/javascript/tests/set.spec.js new file mode 100644 index 00000000..7a497860 --- /dev/null +++ b/priv/javascript/tests/set.spec.js @@ -0,0 +1,106 @@ +var Set = require('../lib/set'); +var MapSet = require('../lib/map_set'); +var Kernel = require('../lib/kernel'); +var expect = require('chai').expect; + +describe('Set', function(){ + + it('new', function(){ + let set = MapSet.__new__(); + + expect(Set.size(set)).to.equal(0); + }); + + it('put', function(){ + let set = MapSet.__new__(); + + expect(Set.size(set)).to.equal(0); + + set = Set.put(set, "hello"); + expect(Set.size(set)).to.equal(1); + + set = Set.put(set, "hello"); + expect(Set.size(set)).to.equal(1); + }); + + it('to_list', function(){ + let set = MapSet.__new__(); + + set = Set.put(set, "hello"); + expect(Set.to_list(set)).to.deep.equal(["hello"]); + }); + + it('delete', function(){ + let set = MapSet.__new__(); + + set = Set.put(set, "hello"); + expect(Set.size(set)).to.equal(1); + + set = Set.__delete__(set, "hello") + expect(Set.size(set)).to.equal(0); + }); + + + it('difference', function(){ + let set1 = MapSet.__new__(); + let set2 = MapSet.__new__(); + + set1 = Set.put(set1, "hello"); + set1 = Set.put(set1, "world"); + + set2 = Set.put(set2, "goodbye"); + set2 = Set.put(set2, "world"); + + let set3 = Set.difference(set1, set2); + + expect(Set.to_list(set3)).to.deep.equal(["hello"]); + }); + + + it('intersection', function(){ + let set1 = MapSet.__new__(); + let set2 = MapSet.__new__(); + + set1 = Set.put(set1, "hello"); + set1 = Set.put(set1, "world"); + + set2 = Set.put(set2, "goodbye"); + set2 = Set.put(set2, "world"); + + let set3 = Set.intersection(set1, set2); + + expect(Set.to_list(set3)).to.deep.equal(["world"]); + }); + + + it('union', function(){ + let set1 = MapSet.__new__(); + let set2 = MapSet.__new__(); + + set1 = Set.put(set1, "hello"); + set1 = Set.put(set1, "world"); + + set2 = Set.put(set2, "goodbye"); + set2 = Set.put(set2, "world"); + + let set3 = Set.union(set1, set2); + + expect(Set.to_list(set3)).to.deep.equal(["hello", "world", "goodbye"]); + }); + + + it('subset?', function(){ + let set1 = MapSet.__new__(); + let set2 = MapSet.__new__(); + + set1 = Set.put(set1, "world"); + + set2 = Set.put(set2, "goodbye"); + set2 = Set.put(set2, "world"); + + expect(Set.subset__qmark__(set1, set2)).to.equal(true); + expect(Set.subset__qmark__(set2, set1)).to.equal(false); + }); + +}) + From 274dc6932b2d65cd0e5f793cdc3d830a80fc3ff3 Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Fri, 23 Oct 2015 22:14:24 -0500 Subject: [PATCH 037/860] ignoring more typespec attributes --- lib/elixir_script/translator.ex | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/lib/elixir_script/translator.ex b/lib/elixir_script/translator.ex index 6ddce36a..55214e88 100644 --- a/lib/elixir_script/translator.ex +++ b/lib/elixir_script/translator.ex @@ -77,11 +77,8 @@ defmodule ElixirScript.Translator do Function.make_anonymous_function([{:->, [], [params, body]}], env) end - defp do_translate({:@, _, [{:doc, _, _}]}, env) do - %ElixirScript.Translator.Group{} - end - - defp do_translate({:@, _, [{:moduledoc, _, _}]}, env) do + defp do_translate({:@, _, [{name, _, _}]}, env) + when name in [:doc, :moduledoc, :type, :typep, :spec, :opaque, :callback, :macrocallback] do %ElixirScript.Translator.Group{} end From a278f8dcc4a035220f3668002853178e2e587cb9 Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Fri, 23 Oct 2015 22:31:02 -0500 Subject: [PATCH 038/860] Added __exception__ to defexception translation --- lib/elixir_script/translator/struct.ex | 8 ++++++-- test/translator/struct_test.exs | 8 ++++++-- 2 files changed, 12 insertions(+), 4 deletions(-) diff --git a/lib/elixir_script/translator/struct.ex b/lib/elixir_script/translator/struct.ex index da79939d..92f5e5ce 100644 --- a/lib/elixir_script/translator/struct.ex +++ b/lib/elixir_script/translator/struct.ex @@ -41,9 +41,11 @@ defmodule ElixirScript.Translator.Struct do end def make_defexception(attributes, env) when length(attributes) == 1 do + exception_key_value = Map.make_property(Translator.translate(:__exception__, env), Translator.translate(true, env)) + attributes = Enum.flat_map(attributes, fn(x) -> x end) - defaults = Enum.map(attributes, fn + defaults = [exception_key_value] ++ Enum.map(attributes, fn ({x, y}) -> Map.make_property( Translator.translate(x, env), @@ -61,7 +63,9 @@ defmodule ElixirScript.Translator.Struct do end def make_defexceptions(attributes, env) do - defaults = Enum.map(attributes, fn + exception_key_value = Map.make_property(Translator.translate(:__exception__, env), Translator.translate(true, env)) + + defaults = [exception_key_value] ++ Enum.map(attributes, fn (x) -> Map.make_property( Translator.translate(x, env), diff --git a/test/translator/struct_test.exs b/test/translator/struct_test.exs index ee8e4069..4f595814 100644 --- a/test/translator/struct_test.exs +++ b/test/translator/struct_test.exs @@ -110,7 +110,9 @@ defmodule ElixirScript.Translator.Struct.Test do const __MODULE__ = Elixir.Kernel.SpecialForms.atom('MyAppError'); function defexception(values = {}) { return Elixir.Kernel.defstruct({ - [Elixir.Kernel.SpecialForms.atom('__struct__')]: __MODULE__, [Elixir.Kernel.SpecialForms.atom('message')]: 'This is a message' + [Elixir.Kernel.SpecialForms.atom('__struct__')]: __MODULE__, + [Elixir.Kernel.SpecialForms.atom('__exception__')]: true, + [Elixir.Kernel.SpecialForms.atom('message')]: 'This is a message' },values); } export { @@ -130,7 +132,9 @@ defmodule ElixirScript.Translator.Struct.Test do const __MODULE__ = Elixir.Kernel.SpecialForms.atom('MyAppError'); function defexception(values = {}) { return Elixir.Kernel.defstruct({ - [Elixir.Kernel.SpecialForms.atom('__struct__')]: __MODULE__, [Elixir.Kernel.SpecialForms.atom('message')]: null + [Elixir.Kernel.SpecialForms.atom('__struct__')]: __MODULE__, + [Elixir.Kernel.SpecialForms.atom('__exception__')]: true, + [Elixir.Kernel.SpecialForms.atom('message')]: null },values); } export { From b428d94d25a0e7eecd5cb468fb60075b91013788 Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Fri, 23 Oct 2015 22:33:22 -0500 Subject: [PATCH 039/860] Added __exception__ to defexception translation for raise --- lib/elixir_script/translator/kernel.ex | 1 + test/translator/struct_test.exs | 4 +++- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/lib/elixir_script/translator/kernel.ex b/lib/elixir_script/translator/kernel.ex index b39d072a..be57aeaa 100644 --- a/lib/elixir_script/translator/kernel.ex +++ b/lib/elixir_script/translator/kernel.ex @@ -279,6 +279,7 @@ defmodule ElixirScript.Translator.Kernel do JS.object_expression( [ Map.make_property(Translator.translate(:__struct__, env), Translator.translate(:RuntimeError, env)), + Map.make_property(Translator.translate(:__exception__, env), Translator.translate(true, env)), Map.make_property(Translator.translate(:message, env), JS.literal(message)) ] ) diff --git a/test/translator/struct_test.exs b/test/translator/struct_test.exs index 4f595814..5bba4108 100644 --- a/test/translator/struct_test.exs +++ b/test/translator/struct_test.exs @@ -164,7 +164,9 @@ defmodule ElixirScript.Translator.Struct.Test do js_code = """ throw { - [Elixir.Kernel.SpecialForms.atom('__struct__')]: Elixir.Kernel.SpecialForms.atom('RuntimeError'), [Elixir.Kernel.SpecialForms.atom('message')]: 'did not get what was expected' + [Elixir.Kernel.SpecialForms.atom('__struct__')]: Elixir.Kernel.SpecialForms.atom('RuntimeError'), + [Elixir.Kernel.SpecialForms.atom('__exception__')]: true, + [Elixir.Kernel.SpecialForms.atom('message')]: 'did not get what was expected' }; """ From fc7721608d7785db3b5f317182cccd3480962534 Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Fri, 23 Oct 2015 22:42:57 -0500 Subject: [PATCH 040/860] Removed duplicate drop from map export --- priv/javascript/lib/map.js | 1 - 1 file changed, 1 deletion(-) diff --git a/priv/javascript/lib/map.js b/priv/javascript/lib/map.js index 5b3758bf..98aff98b 100644 --- a/priv/javascript/lib/map.js +++ b/priv/javascript/lib/map.js @@ -252,7 +252,6 @@ export default { has_key__qmark__, split, take, - drop, put_new, put_new_lazy, get_and_update, From 57c3737949d024db1ab0c204c95cbc81e5fc6c6d Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Sat, 24 Oct 2015 08:49:13 -0500 Subject: [PATCH 041/860] Made it so that functions exported with JS keywords can still use those names without modification --- lib/elixir_script/translator/utils.ex | 12 ------------ priv/javascript/lib/kernel.js | 2 +- priv/javascript/lib/list.js | 2 +- priv/javascript/lib/map.js | 5 ++--- priv/javascript/lib/map_set.js | 10 +++++----- priv/javascript/lib/set.js | 4 ++-- priv/javascript/tests/list.spec.js | 2 +- priv/javascript/tests/map.spec.js | 12 ++++++------ priv/javascript/tests/set.spec.js | 26 +++++++++++++------------- test/translator/case_test.exs | 2 +- test/translator/function_test.exs | 10 +++++----- test/translator/try_test.exs | 2 +- 12 files changed, 38 insertions(+), 51 deletions(-) diff --git a/lib/elixir_script/translator/utils.ex b/lib/elixir_script/translator/utils.ex index 8b72678a..7387e384 100644 --- a/lib/elixir_script/translator/utils.ex +++ b/lib/elixir_script/translator/utils.ex @@ -173,18 +173,6 @@ defmodule ElixirScript.Translator.Utils do ) end - def filter_name(:in) do - "__in__" - end - - def filter_name(:new) do - "__new__" - end - - def filter_name(:delete) do - "__delete__" - end - def filter_name(name) do to_string(name) |> String.replace("?", "__qmark__") diff --git a/priv/javascript/lib/kernel.js b/priv/javascript/lib/kernel.js index 8b5ea067..a1836984 100644 --- a/priv/javascript/lib/kernel.js +++ b/priv/javascript/lib/kernel.js @@ -187,7 +187,7 @@ export default { is_port, is_reference, is_bitstring, - __in__, + in: __in__, abs, round, elem, diff --git a/priv/javascript/lib/list.js b/priv/javascript/lib/list.js index 86b2bc64..38493dac 100644 --- a/priv/javascript/lib/list.js +++ b/priv/javascript/lib/list.js @@ -5,7 +5,7 @@ let List = {}; List.Chars = Chars; -List.__delete__ = function(list, item){ +List.delete = function(list, item){ let new_value = []; let value_found = false; diff --git a/priv/javascript/lib/map.js b/priv/javascript/lib/map.js index 98aff98b..00a5ba39 100644 --- a/priv/javascript/lib/map.js +++ b/priv/javascript/lib/map.js @@ -1,5 +1,4 @@ import SpecialForms from './kernel/special_forms'; -import List from './list'; function __new__(){ return SpecialForms.map({}); @@ -238,13 +237,13 @@ function update(map, key, initial, fun){ export default { - __new__, + new: __new__, keys, size, to_list, values, from_struct, - __delete__, + delete: __delete__, drop, equal__qmark__, fetch__emark__, diff --git a/priv/javascript/lib/map_set.js b/priv/javascript/lib/map_set.js index c4cfefb4..9b2b811a 100644 --- a/priv/javascript/lib/map_set.js +++ b/priv/javascript/lib/map_set.js @@ -14,7 +14,7 @@ function to_list(map){ } function __delete__(set, term){ - let new_list = List.__delete__(set.set, term); + let new_list = List.delete(set.set, term); let new_map = Object.assign({}, set); new_map.set = new_list; @@ -38,7 +38,7 @@ function difference(set1, set2){ for(let val of set1.set){ if(member__qmark__(set2, val)){ - new_map.set = List.__delete__(new_map.set, val); + new_map.set = List.delete(new_map.set, val); } } @@ -51,7 +51,7 @@ function intersection(set1, set2){ for(let val of set1.set){ if(!member__qmark__(set2, val)){ - new_map.set = List.__delete__(new_map.set, val); + new_map.set = List.delete(new_map.set, val); } } @@ -100,11 +100,11 @@ function subset__qmark__(set1, set2){ export default { - __new__, + new: __new__, size, to_list, disjoin__qmark__, - __delete__, + delete: __delete__, subset__qmark__, equal__qmark__, member__qmark__, diff --git a/priv/javascript/lib/set.js b/priv/javascript/lib/set.js index 3a6d4030..70fe61cf 100644 --- a/priv/javascript/lib/set.js +++ b/priv/javascript/lib/set.js @@ -9,7 +9,7 @@ function to_list(map){ } function __delete__(set, term){ - return MapSet.__delete__(set, term); + return MapSet.delete(set, term); } function put(set, term){ @@ -49,7 +49,7 @@ export default { size, to_list, disjoin__qmark__, - __delete__, + delete: __delete__, subset__qmark__, equal__qmark__, member__qmark__, diff --git a/priv/javascript/tests/list.spec.js b/priv/javascript/tests/list.spec.js index bc43b605..8f49edc5 100644 --- a/priv/javascript/tests/list.spec.js +++ b/priv/javascript/tests/list.spec.js @@ -29,7 +29,7 @@ describe('List', function(){ describe('delete', function(){ it('delete item in list', function(){ let t = Kernel.SpecialForms.list(Kernel.SpecialForms.atom("a"), Kernel.SpecialForms.atom("b"), Kernel.SpecialForms.atom("c")); - t = List.__delete__(t, Kernel.SpecialForms.atom("b")); + t = List.delete(t, Kernel.SpecialForms.atom("b")); expect(t[1]).to.equal(Kernel.SpecialForms.atom("c")); }) }) diff --git a/priv/javascript/tests/map.spec.js b/priv/javascript/tests/map.spec.js index 928dc505..3e3c99cd 100644 --- a/priv/javascript/tests/map.spec.js +++ b/priv/javascript/tests/map.spec.js @@ -5,13 +5,13 @@ var expect = require('chai').expect; describe('Map', function(){ it('new', function(){ - let map = Map.__new__(); + let map = Map.new(); expect(Object.keys(map).length).to.equal(0); }); it('keys', function(){ - let map = Map.__new__(); + let map = Map.new(); expect(Map.keys(map)).to.deep.equal([]); map = Map.put(map, "hello", "world"); @@ -19,21 +19,21 @@ describe('Map', function(){ }); it('to_list', function(){ - let map = Map.__new__(); + let map = Map.new(); map = Map.put(map, "hello", "world"); expect(Map.to_list(map)).to.deep.equal([Kernel.SpecialForms.tuple("hello", "world")]); }); it('delete', function(){ - let map = Map.__new__(); + let map = Map.new(); map = Map.put(map, "hello", "world"); expect(Map.keys(map).length).to.equal(1); - map = Map.__delete__(map, "hello") + map = Map.delete(map, "hello") expect(Map.keys(map).length).to.equal(0); }); - + }) diff --git a/priv/javascript/tests/set.spec.js b/priv/javascript/tests/set.spec.js index 7a497860..b1964b75 100644 --- a/priv/javascript/tests/set.spec.js +++ b/priv/javascript/tests/set.spec.js @@ -6,13 +6,13 @@ var expect = require('chai').expect; describe('Set', function(){ it('new', function(){ - let set = MapSet.__new__(); + let set = MapSet.new(); expect(Set.size(set)).to.equal(0); }); it('put', function(){ - let set = MapSet.__new__(); + let set = MapSet.new(); expect(Set.size(set)).to.equal(0); @@ -24,26 +24,26 @@ describe('Set', function(){ }); it('to_list', function(){ - let set = MapSet.__new__(); + let set = MapSet.new(); set = Set.put(set, "hello"); expect(Set.to_list(set)).to.deep.equal(["hello"]); }); it('delete', function(){ - let set = MapSet.__new__(); + let set = MapSet.new(); set = Set.put(set, "hello"); expect(Set.size(set)).to.equal(1); - set = Set.__delete__(set, "hello") + set = Set.delete(set, "hello") expect(Set.size(set)).to.equal(0); }); it('difference', function(){ - let set1 = MapSet.__new__(); - let set2 = MapSet.__new__(); + let set1 = MapSet.new(); + let set2 = MapSet.new(); set1 = Set.put(set1, "hello"); set1 = Set.put(set1, "world"); @@ -58,8 +58,8 @@ describe('Set', function(){ it('intersection', function(){ - let set1 = MapSet.__new__(); - let set2 = MapSet.__new__(); + let set1 = MapSet.new(); + let set2 = MapSet.new(); set1 = Set.put(set1, "hello"); set1 = Set.put(set1, "world"); @@ -74,8 +74,8 @@ describe('Set', function(){ it('union', function(){ - let set1 = MapSet.__new__(); - let set2 = MapSet.__new__(); + let set1 = MapSet.new(); + let set2 = MapSet.new(); set1 = Set.put(set1, "hello"); set1 = Set.put(set1, "world"); @@ -90,8 +90,8 @@ describe('Set', function(){ it('subset?', function(){ - let set1 = MapSet.__new__(); - let set2 = MapSet.__new__(); + let set1 = MapSet.new(); + let set2 = MapSet.new(); set1 = Set.put(set1, "world"); diff --git a/test/translator/case_test.exs b/test/translator/case_test.exs index e0635203..3169d903 100644 --- a/test/translator/case_test.exs +++ b/test/translator/case_test.exs @@ -75,7 +75,7 @@ defmodule ElixirScript.Translator.Case.Test do let [value0] = Elixir.Patterns.match(Elixir.Patterns.variable(),13); return value0; },function(number) { - return Elixir.Kernel.__in__(number,Elixir.Kernel.SpecialForms.list(1,2,3,4)); + return Elixir.Kernel.in(number,Elixir.Kernel.SpecialForms.list(1,2,3,4)); }),Elixir.Patterns.make_case([Elixir.Patterns.wildcard()],function() { return true; })).call(this,data) diff --git a/test/translator/function_test.exs b/test/translator/function_test.exs index bb551d53..60fccd24 100644 --- a/test/translator/function_test.exs +++ b/test/translator/function_test.exs @@ -89,7 +89,7 @@ defmodule ElixirScript.Translator.Function.Test do return Elixir.Patterns.defmatch(Elixir.Patterns.make_case([Elixir.Patterns.variable()],function(x) { return 2; },function(x) { - return Elixir.Kernel.__in__(x,Elixir.Kernel.SpecialForms.list(false,null)); + return Elixir.Kernel.in(x,Elixir.Kernel.SpecialForms.list(false,null)); }),Elixir.Patterns.make_case([Elixir.Patterns.wildcard()],function() { return 1; })).call(this,1 == 1); @@ -117,13 +117,13 @@ defmodule ElixirScript.Translator.Function.Test do return Elixir.Patterns.defmatch(Elixir.Patterns.make_case([Elixir.Patterns.variable()],function(x) { return 2; },function(x) { - return Elixir.Kernel.__in__(x,Elixir.Kernel.SpecialForms.list(false,null)); + return Elixir.Kernel.in(x,Elixir.Kernel.SpecialForms.list(false,null)); }),Elixir.Patterns.make_case([Elixir.Patterns.wildcard()],function() { return Elixir.Patterns.defmatch(Elixir.Patterns.make_case([Elixir.Patterns.variable()],function(x) { let [a000] = Elixir.Patterns.match(Elixir.Patterns.variable(),1); return a000; },function(x) { - return Elixir.Kernel.__in__(x,Elixir.Kernel.SpecialForms.list(false,null)); + return Elixir.Kernel.in(x,Elixir.Kernel.SpecialForms.list(false,null)); }),Elixir.Patterns.make_case([Elixir.Patterns.wildcard()],function() { return 4; })).call(this,2 == 2); @@ -402,7 +402,7 @@ defmodule ElixirScript.Translator.Function.Test do const something = Elixir.Patterns.defmatch(Elixir.Patterns.make_case([Elixir.Patterns.variable(), Elixir.Patterns.variable()],function(one,two) { return null; },function(one,two) { - return Elixir.Kernel.__in__(one,Elixir.Kernel.SpecialForms.list(1,2,3)); + return Elixir.Kernel.in(one,Elixir.Kernel.SpecialForms.list(1,2,3)); })); """ @@ -423,7 +423,7 @@ defmodule ElixirScript.Translator.Function.Test do const something = Elixir.Patterns.defmatch(Elixir.Patterns.make_case([Elixir.Patterns.variable()],function(one) { return null; },function(one) { - return Elixir.Kernel.__in__(one,Elixir.Kernel.SpecialForms.list(1,2,3)); + return Elixir.Kernel.in(one,Elixir.Kernel.SpecialForms.list(1,2,3)); }),Elixir.Patterns.make_case([Elixir.Patterns.variable()],function(one) { return null; },function(one) { diff --git a/test/translator/try_test.exs b/test/translator/try_test.exs index 2ee02aa8..53f178db 100644 --- a/test/translator/try_test.exs +++ b/test/translator/try_test.exs @@ -64,7 +64,7 @@ defmodule ElixirScript.Translator.Try.Test do },Elixir.Patterns.defmatch(Elixir.Patterns.make_case([Elixir.Patterns.variable()],function(x) { return IO.puts('Invalid argument given'); },function(x) { - return Elixir.Kernel.__in__(x,Elixir.Kernel.SpecialForms.list(ArgumentError.defstruct(Elixir.Kernel.SpecialForms.map({})))); + return Elixir.Kernel.in(x,Elixir.Kernel.SpecialForms.list(ArgumentError.defstruct(Elixir.Kernel.SpecialForms.map({})))); })),null,null,null) """ From 968016be77ab8252458a0b76a1e86d3e3df53e50 Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Sat, 24 Oct 2015 09:05:49 -0500 Subject: [PATCH 042/860] Updated CHANGELOG --- CHANGELOG.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 5b455cf7..7b295b43 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,7 +7,8 @@ * Added `MapSet` module * Added `Set` module * Protocol support - * Added `Collectable`, `Enumerable`, `Inspect`, `List.Chars`, and `String.Chars` protocols + * Added `Collectable`, `Enumerable`, `Inspect`, `List.Chars`, and `String.Chars` protocols. + The only one currently being used in the Standard Library, however, is String.Chars # v0.12.0 * Enhancements From 55e36ee87057067f0adf24ffe84f59aec51f5ec2 Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Sat, 24 Oct 2015 09:07:57 -0500 Subject: [PATCH 043/860] Removed README from doc extras --- mix.exs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mix.exs b/mix.exs index 95907255..a372767d 100644 --- a/mix.exs +++ b/mix.exs @@ -15,7 +15,7 @@ defmodule ElixirScript.Mixfile do test_coverage: [tool: ExCoveralls], preferred_cli_env: [coveralls: :test], docs: [ - extras: ["README.md", "GettingStarted.md", "FAQ.md"] + extras: ["GettingStarted.md", "FAQ.md"] ] ] end From 39235c65b3d8b239c7837b784ec4496af7b62662 Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Sat, 24 Oct 2015 09:11:28 -0500 Subject: [PATCH 044/860] Updated Getting Started guide --- GettingStarted.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/GettingStarted.md b/GettingStarted.md index cca3f28c..de21b963 100644 --- a/GettingStarted.md +++ b/GettingStarted.md @@ -73,7 +73,7 @@ The intent of this guide is to get you started with ElixirScript. It will give y The last option we will show is the root option. This option is for defining a root path for the import statements. By default your import statement will not have anything prepended to it. For example, the elixir import will look like this: ```javascript - import { Patterns, Kernel, Atom, Enum, Integer, JS, List, Range, Tuple, Agent, Keyword, BitString } from 'elixir'; + import * as Elixir from 'elixir'; ``` If we wanted to prepend "js" to the root, we can like this: @@ -85,7 +85,7 @@ The intent of this guide is to get you started with ElixirScript. It will give y Now the import will look like this: ```javascript - import { Patterns, Kernel, Atom, Enum, Integer, JS, List, Range, Tuple, Agent, Keyword, BitString } from 'js/elixir'; + import * as Elixir from 'js/elixir'; ``` That concludes the walkthrough on options, as well as the walkthrough on using the ex2js escript. From b66d5ac18d60c65335bcddd421c18801be3d4fa2 Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Mon, 26 Oct 2015 11:05:17 -0500 Subject: [PATCH 045/860] Updated docs for 0.13 release --- CHANGELOG.md | 2 +- GettingStarted.md | 2 +- mix.exs | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 7b295b43..be8fb91a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,4 +1,4 @@ -# v0.13.0-dev +# v0.13.0 * Enhancements * Added `Base` module with function: encode64, decode64, and decode64! * Added `String` module diff --git a/GettingStarted.md b/GettingStarted.md index de21b963..a16a6fb0 100644 --- a/GettingStarted.md +++ b/GettingStarted.md @@ -97,7 +97,7 @@ The intent of this guide is to get you started with ElixirScript. It will give y The first step is getting the dependency. In your mix.exs file for your elixir project, add elixir_script to your deps. ```elixir - {:elixir_script, "~> 0.12"} + {:elixir_script, "~> 0.13"} ``` * Step 2: Now download the dep diff --git a/mix.exs b/mix.exs index a372767d..5b4b6290 100644 --- a/mix.exs +++ b/mix.exs @@ -4,7 +4,7 @@ defmodule ElixirScript.Mixfile do def project do [ app: :elixir_script, - version: "0.13.0-dev", + version: "0.13.0", elixir: "~> 1.0", escript: escript_config, deps: deps, From fe377ad88c7617098917d884405ce15cad77fb02 Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Fri, 30 Oct 2015 15:08:47 -0500 Subject: [PATCH 046/860] started turning structs into classes --- lib/elixir_script/translator/module.ex | 33 ++++++++++++----- lib/elixir_script/translator/struct.ex | 27 +++++--------- priv/javascript/lib/kernel.js | 49 ++++++++++++++++++++++++++ test/translator/struct_test.exs | 9 +++-- 4 files changed, 87 insertions(+), 31 deletions(-) diff --git a/lib/elixir_script/translator/module.ex b/lib/elixir_script/translator/module.ex index 6228db61..c36556d3 100644 --- a/lib/elixir_script/translator/module.ex +++ b/lib/elixir_script/translator/module.ex @@ -29,6 +29,8 @@ defmodule ElixirScript.Translator.Module do {imports, body} = extract_imports_from_body(body) {structs, body} = extract_structs_from_body(body) + structs = process_struct(module_name_list, structs) + #Add imports found from walking the ast #and make sure to only put one declaration per alias @@ -48,7 +50,7 @@ defmodule ElixirScript.Translator.Module do body = Utils.inflate_groups(body) exported_object = JS.object_expression( - make_defstruct_property(structs) ++ + make_defstruct_property(module_name_list, structs) ++ Enum.map(exported_functions, fn({key, _value}) -> JS.property(JS.identifier(key), JS.identifier(key), :init, true) end) @@ -141,7 +143,9 @@ defmodule ElixirScript.Translator.Module do def extract_structs_from_body(body) do Enum.partition(body, fn(x) -> case x do - %ESTree.FunctionDeclaration{} -> + %ESTree.CallExpression{callee: %ESTree.MemberExpression{property: %ESTree.Identifier{name: "defstruct"}}} -> + true + %ESTree.CallExpression{callee: %ESTree.MemberExpression{property: %ESTree.Identifier{name: "defexception"}}} -> true _ -> false @@ -149,16 +153,29 @@ defmodule ElixirScript.Translator.Module do end) end - defp make_defstruct_property([]) do + defp process_struct(module_name, []) do + [] + end + + defp process_struct(module_name, [the_struct]) do + declarator = JS.variable_declarator( + JS.identifier(List.last(module_name)), + the_struct + ) + + [JS.variable_declaration([declarator], :const)] + end + + defp make_defstruct_property(module_name, []) do [] end - defp make_defstruct_property([the_struct]) do + defp make_defstruct_property(module_name, [the_struct]) do case the_struct do - %ESTree.FunctionDeclaration{id: %ESTree.Identifier{name: :defstruct}} -> - [JS.property(JS.identifier(:defstruct), JS.identifier(:defstruct), :init, true )] - %ESTree.FunctionDeclaration{id: %ESTree.Identifier{name: :defexception}} -> - [JS.property(JS.identifier(:defexception), JS.identifier(:defexception), :init, true )] + %ESTree.CallExpression{callee: %ESTree.MemberExpression{property: %ESTree.Identifier{name: "defstruct"}}} -> + [List.last(module_name), the_struct] + %ESTree.CallExpression{callee: %ESTree.MemberExpression{property: %ESTree.Identifier{name: "defexception"}}} -> + [List.last(module_name), the_struct] end end diff --git a/lib/elixir_script/translator/struct.ex b/lib/elixir_script/translator/struct.ex index 92f5e5ce..f1950377 100644 --- a/lib/elixir_script/translator/struct.ex +++ b/lib/elixir_script/translator/struct.ex @@ -82,24 +82,15 @@ defmodule ElixirScript.Translator.Struct do defaults = %{ defaults | properties: [struct_name] ++ defaults.properties } - JS.function_declaration( - JS.identifier(name), - [JS.identifier(:values)], - [JS.object_expression([])], - JS.block_statement([ - JS.return_statement( - JS.call_expression( - JS.member_expression( - JS.member_expression( - JS.identifier("Elixir"), - JS.identifier("Kernel") - ), - JS.identifier("defstruct") - ), - [defaults, JS.identifier(:values)] - ) - ) - ]) + JS.call_expression( + JS.member_expression( + JS.member_expression( + JS.identifier("Elixir"), + JS.identifier("Kernel") + ), + JS.identifier(name) + ), + [defaults] ) end diff --git a/priv/javascript/lib/kernel.js b/priv/javascript/lib/kernel.js index a1836984..c9f21729 100644 --- a/priv/javascript/lib/kernel.js +++ b/priv/javascript/lib/kernel.js @@ -149,6 +149,55 @@ function match__qmark__(pattern, expr, guard = () => true){ return Patterns.match_no_throw(pattern, expr, guard) != null; } +function defstruct(defaults){ + return class { + constructor(update = {}){ + let the_values = Object.assign(defaults, update); + Object.assign(this, the_values); + } + + static update(obj, updates = {}){ + let x = Object.assign(new this(), obj); + x = Object.assign(x, updates); + return Object.freeze(x); + } + + static create(updates = {}){ + let x = new this(updates); + return Object.freeze(x); + } + } +} + + +function defexception(defaults){ + return class extends Error { + constructor(update = {}){ + let message = update.message || ""; + super(message); + + let the_values = Object.assign(defaults, update); + Object.assign(this, the_values); + + this.name = this.constructor.name; + this.message = message; + this[SpecialForms.atom("__exception__")] = true; + Error.captureStackTrace(this, this.constructor.name); + } + + static update(obj, updates = {}){ + let x = Object.assign(new this(), obj); + x = Object.assign(x, updates); + return Object.freeze(x); + } + + static create(updates = {}){ + let x = new this(updates); + return Object.freeze(x); + } + } +} + function defstruct(defaults, values){ return SpecialForms.map_update(defaults, values); } diff --git a/test/translator/struct_test.exs b/test/translator/struct_test.exs index 5bba4108..36a8ab72 100644 --- a/test/translator/struct_test.exs +++ b/test/translator/struct_test.exs @@ -11,13 +11,12 @@ defmodule ElixirScript.Translator.Struct.Test do js_code = """ const __MODULE__ = Elixir.Kernel.SpecialForms.atom('User'); - function defstruct(values = {}) { - return Elixir.Kernel.defstruct({ + const User = Elixir.Kernel.defstruct({ [Elixir.Kernel.SpecialForms.atom('__struct__')]: __MODULE__, [Elixir.Kernel.SpecialForms.atom('name')]: 'john', [Elixir.Kernel.SpecialForms.atom('age')]: 27 - },values); - } + }); + export { - defstruct + User }; """ From 735625245195e2efb693416d514f170021d8f754 Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Sat, 31 Oct 2015 03:46:36 -0500 Subject: [PATCH 047/860] More struct changes --- lib/elixir_script/translator/struct.ex | 19 +++++++++++++++++++ test/translator/struct_test.exs | 15 ++++++++------- 2 files changed, 27 insertions(+), 7 deletions(-) diff --git a/lib/elixir_script/translator/struct.ex b/lib/elixir_script/translator/struct.ex index f1950377..c2a14e86 100644 --- a/lib/elixir_script/translator/struct.ex +++ b/lib/elixir_script/translator/struct.ex @@ -82,6 +82,25 @@ defmodule ElixirScript.Translator.Struct do defaults = %{ defaults | properties: [struct_name] ++ defaults.properties } + JS.function_declaration( + JS.identifier(name), + [JS.identifier(:values)], + [JS.object_expression([])], + JS.block_statement([ + JS.return_statement( + JS.call_expression( + JS.member_expression( + JS.member_expression( + JS.identifier("Elixir"), + JS.identifier("Kernel") + ), + JS.identifier("defstruct") + ), + [defaults, JS.identifier(:values)] + ) + ) + ]) + JS.call_expression( JS.member_expression( JS.member_expression( diff --git a/test/translator/struct_test.exs b/test/translator/struct_test.exs index 36a8ab72..56fbafbd 100644 --- a/test/translator/struct_test.exs +++ b/test/translator/struct_test.exs @@ -10,14 +10,15 @@ defmodule ElixirScript.Translator.Struct.Test do end js_code = """ - const __MODULE__ = Elixir.Kernel.SpecialForms.atom('User'); - const User = Elixir.Kernel.defstruct({ - [Elixir.Kernel.SpecialForms.atom('__struct__')]: __MODULE__, [Elixir.Kernel.SpecialForms.atom('name')]: 'john', [Elixir.Kernel.SpecialForms.atom('age')]: 27 - }); + const __MODULE__ = Elixir.Kernel.SpecialForms.atom('User'); + + const User = Elixir.Kernel.defstruct({ + [Elixir.Kernel.SpecialForms.atom('__struct__')]: __MODULE__, [Elixir.Kernel.SpecialForms.atom('name')]: 'john', [Elixir.Kernel.SpecialForms.atom('age')]: 27 + }); - export { - User - }; + export { + User + }; """ assert_translation(ex_ast, js_code) From b39a6b37559a62f9d40f781109fba7a365ee17f3 Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Wed, 11 Nov 2015 10:16:05 -0600 Subject: [PATCH 048/860] Fixed bug where functions defined without params threw exception --- lib/elixir_script/pattern_matching/match.ex | 6 ++-- lib/elixir_script/translator.ex | 12 +++---- lib/elixir_script/translator/function.ex | 37 ++++++++++++++------- test/translator/bug_test.exs | 32 +++++++++++++----- 4 files changed, 58 insertions(+), 29 deletions(-) diff --git a/lib/elixir_script/pattern_matching/match.ex b/lib/elixir_script/pattern_matching/match.ex index 89e50c5b..4f2e335c 100644 --- a/lib/elixir_script/pattern_matching/match.ex +++ b/lib/elixir_script/pattern_matching/match.ex @@ -96,7 +96,7 @@ defmodule ElixirScript.PatternMatching.Match do [value] ) end - + def build_match(params, env) do Enum.map(params, &do_build_match(&1, env)) |> reduce_patterns @@ -165,7 +165,7 @@ defmodule ElixirScript.PatternMatching.Match do |> Enum.map(&build_match([&1], env)) |> reduce_patterns - {[Primitive.make_tuple_no_translate(patterns)], params} + {[Primitive.make_tuple_no_translate(patterns)], params} end defp do_build_match({name, _, _}, env) do @@ -185,4 +185,4 @@ defmodule ElixirScript.PatternMatching.Match do { [capture(hd(patterns))], params ++ [JS.identifier(Utils.filter_name(target))] } end -end \ No newline at end of file +end diff --git a/lib/elixir_script/translator.ex b/lib/elixir_script/translator.ex index 55214e88..46a281ef 100644 --- a/lib/elixir_script/translator.ex +++ b/lib/elixir_script/translator.ex @@ -77,7 +77,7 @@ defmodule ElixirScript.Translator do Function.make_anonymous_function([{:->, [], [params, body]}], env) end - defp do_translate({:@, _, [{name, _, _}]}, env) + defp do_translate({:@, _, [{name, _, _}]}, _) when name in [:doc, :moduledoc, :type, :typep, :spec, :opaque, :callback, :macrocallback] do %ElixirScript.Translator.Group{} end @@ -106,7 +106,7 @@ defmodule ElixirScript.Translator do end defp do_translate({:<<>>, _, elements}, env) do - is_interpolated_string = Enum.all?(elements, fn(x) -> + is_interpolated_string = Enum.all?(elements, fn(x) -> case x do b when is_binary(b) -> true @@ -166,7 +166,7 @@ defmodule ElixirScript.Translator do end end - defp do_translate({{:., context, [module_name, function_name]}, _, params } = ast, env) do + defp do_translate({{:., _, [module_name, function_name]}, _, params } = ast, env) do case module_name do Kernel -> KernelLib.translate_kernel_function(function_name, params, env) @@ -324,13 +324,13 @@ defmodule ElixirScript.Translator do translate(quoted, env) end - defp do_translate({name, metadata, params} = ast, env) when is_list(params) do + defp do_translate({name, _, params} = ast, env) when is_list(params) do if KernelLib.is_defined_in_kernel(name, length(params)) do KernelLib.translate_kernel_function(name, params, env) else expanded_ast = Macro.expand(ast, env) if expanded_ast == ast do - Function.make_function_call(name, params, env) + Function.make_function_call(name, params, env) else translate(expanded_ast, env) end @@ -338,7 +338,7 @@ defmodule ElixirScript.Translator do end defp do_translate({ name, _, _ }, _) do - name = Utils.filter_name(name) + name = Utils.filter_name(name) Primitive.make_identifier(name) end diff --git a/lib/elixir_script/translator/function.ex b/lib/elixir_script/translator/function.ex index 866ad79d..ce88f2a3 100644 --- a/lib/elixir_script/translator/function.ex +++ b/lib/elixir_script/translator/function.ex @@ -8,8 +8,8 @@ defmodule ElixirScript.Translator.Function do alias ElixirScript.Translator.Map @standard_libs [ - :Patterns, :Kernel, :Atom, :Enum, :Integer, :JS, - :List, :Range, :Tuple, :Agent, :Keyword, :BitString, + :Patterns, :Kernel, :Atom, :Enum, :Integer, :JS, + :List, :Range, :Tuple, :Agent, :Keyword, :BitString, :Base, :String, :Bitwise, :Collectable, :Enumerable, :Inspect, :Map, :MapSet, :Set ] @@ -60,6 +60,7 @@ defmodule ElixirScript.Translator.Function do |> Stream.map(fn(x) -> Variables.process(x) end) |> Stream.map(fn {:->, _, [ [{:when, _, [params | guards]}], body ]} -> + params = wrap_params(params) { patterns, params } = Match.build_match(List.wrap(params), env) params = make_params(params) body = make_function_body(body, env) @@ -67,12 +68,14 @@ defmodule ElixirScript.Translator.Function do do_make_function_clause(patterns, params, body, guard_body) ({:->, _, [params, body]}) -> + params = wrap_params(params) { patterns, params } = Match.build_match(params, env) params = make_params(params) body = make_function_body(body, env) - do_make_function_clause(patterns, params, body) + do_make_function_clause(patterns, params, body) ({_, _, [{:when, _, [{_, _, params} | guards] }, [do: body]]}) -> + params = wrap_params(params) { patterns, params } = Match.build_match(params, env) params = make_params(params) body = make_function_body(body, env) @@ -80,12 +83,14 @@ defmodule ElixirScript.Translator.Function do do_make_function_clause(patterns, params, body, guard_body) ({_, _, [{_, _, params}, [do: body]]}) -> + params = wrap_params(params) { patterns, params } = Match.build_match(params, env) params = make_params(params) body = make_function_body(body, env) do_make_function_clause(patterns, params, body) ({_, _, [{_, _, params}]}) -> + params = wrap_params(params) { patterns, params } = Match.build_match(params, env) params = make_params(params) body = make_function_body([], env) @@ -109,6 +114,14 @@ defmodule ElixirScript.Translator.Function do ) end + def wrap_params(params) when is_atom(params) do + [] + end + + def wrap_params(params) do + params + end + def make_function_body(body, env) do body |> prepare_function_body(env) @@ -138,7 +151,7 @@ defmodule ElixirScript.Translator.Function do ) ), [ - JS.array_expression(patterns), + JS.array_expression(patterns), JS.function_expression(params, [], body), JS.function_expression(params, [], guard_body) ] @@ -155,7 +168,7 @@ defmodule ElixirScript.Translator.Function do ) ), [ - JS.array_expression(patterns), + JS.array_expression(patterns), JS.function_expression(params, [], body) ] ) @@ -255,9 +268,9 @@ defmodule ElixirScript.Translator.Function do last_item = case last_item do %ESTree.Literal{} -> - JS.return_statement(last_item) + JS.return_statement(last_item) %ESTree.Identifier{} -> - JS.return_statement(last_item) + JS.return_statement(last_item) %ESTree.VariableDeclaration{} -> declaration = hd(last_item.declarations).id @@ -269,7 +282,7 @@ defmodule ElixirScript.Translator.Function do JS.return_statement(JS.array_expression(declaration.elements)) end _ -> - JS.return_statement(declaration) + JS.return_statement(declaration) end [last_item, return_statement] @@ -277,14 +290,14 @@ defmodule ElixirScript.Translator.Function do last_item = %ESTree.BlockStatement{ last_item | body: return_last_expression(last_item.body) } _ -> if String.contains?(last_item.type, "Expression") do - JS.return_statement(last_item) + JS.return_statement(last_item) else [last_item, JS.return_statement(JS.literal(nil))] - end + end end - list = Enum.take(list, length(list)-1) + list = Enum.take(list, length(list)-1) |> Enum.map(fn(x) -> case x do %ESTree.MemberExpression{} -> @@ -302,4 +315,4 @@ defmodule ElixirScript.Translator.Function do list ++ [last_item] end end -end \ No newline at end of file +end diff --git a/test/translator/bug_test.exs b/test/translator/bug_test.exs index 856b4aeb..c43a3bde 100644 --- a/test/translator/bug_test.exs +++ b/test/translator/bug_test.exs @@ -2,6 +2,22 @@ defmodule ElixirScript.Translator.Bug.Test do use ShouldI import ElixirScript.TestHelper + should "Translate function with 0 arguments" do + ex_ast = quote do + def test do + :atom + end + end + + js_code = """ + const test = Elixir.Patterns.defmatch(Elixir.Patterns.make_case([],function(){ + return Elixir.Kernel.SpecialForms.atom('atom'); + })); + """ + + assert_translation(ex_ast, js_code) + end + should "Translate react element" do ex_ast = quote do React.createElement( @@ -17,7 +33,7 @@ defmodule ElixirScript.Translator.Bug.Test do }),'Welcome to React Native!') """ - assert_translation(ex_ast, js_code) + assert_translation(ex_ast, js_code) end @@ -32,12 +48,12 @@ defmodule ElixirScript.Translator.Bug.Test do js_code = """ import { default as JQuery } from 'jquery'; const __MODULE__ = Elixir.Kernel.SpecialForms.atom('App.Todo'); - + JQuery(Elixir.JS.call_property(e, 'target')); export {}; """ - assert_translation(ex_ast, js_code) + assert_translation(ex_ast, js_code) end should "correctly translate module names when used" do @@ -50,9 +66,9 @@ defmodule ElixirScript.Translator.Bug.Test do """ - assert_translation(ex_ast, js_code) + assert_translation(ex_ast, js_code) end - + should "replace !" do ex_ast = quote do Elixir.Enum.fetch!(data, i) @@ -62,7 +78,7 @@ defmodule ElixirScript.Translator.Bug.Test do Elixir.Enum.fetch__emark__(data, i) """ - assert_translation(ex_ast, js_code) + assert_translation(ex_ast, js_code) end should "chain calls correctly" do @@ -74,7 +90,7 @@ defmodule ElixirScript.Translator.Bug.Test do Elixir.JS.call_property(this, 'getRawCanvas').getContext('2d') """ - assert_translation(ex_ast, js_code) + assert_translation(ex_ast, js_code) ex_ast = quote do @@ -85,7 +101,7 @@ defmodule ElixirScript.Translator.Bug.Test do this.getRawCanvas(one).get('fg').getContext('2d') """ - assert_translation(ex_ast, js_code) + assert_translation(ex_ast, js_code) end should "correctly call multi-module functions" do From 570b3cd09d7ed2ab276528629fab01166261bd39 Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Wed, 18 Nov 2015 17:18:27 -0600 Subject: [PATCH 049/860] renamed ex2js to elixirscript --- .gitignore | 3 +- GettingStarted.md | 138 +++++++++--------- gulpfile.js | 26 +--- lib/elixir_script.ex | 14 +- lib/elixir_script/cli.ex | 26 ++-- lib/mix/tasks/{ex2js.ex => elixirscript.ex} | 8 +- mix.exs | 22 +-- mix.lock | 8 +- .../lib/patterns/patterns/defmatch.js | 13 +- 9 files changed, 125 insertions(+), 133 deletions(-) rename lib/mix/tasks/{ex2js.ex => elixirscript.ex} (86%) diff --git a/.gitignore b/.gitignore index b2d12146..25c0a751 100644 --- a/.gitignore +++ b/.gitignore @@ -3,9 +3,11 @@ erl_crash.dump *.ez ex2js +elixirscript node_modules priv/test_project/dest priv/javascript/build +priv/javascript/test_build priv/javascript/dist priv/javascript/dist_build /dist @@ -17,4 +19,3 @@ fprof.trace index.js /doc /bench/snapshots - diff --git a/GettingStarted.md b/GettingStarted.md index a16a6fb0..76fbd63d 100644 --- a/GettingStarted.md +++ b/GettingStarted.md @@ -10,142 +10,142 @@ The intent of this guide is to get you started with ElixirScript. It will give y ### Escript * Step 1: Get escript - - You can download the elixirscript escript from the [releases page on github](https://github.com/bryanjos/elixirscript/releases). It is a tar file named ex2js.tar.gz. + + You can download the elixirscript escript from the [releases page on github](https://github.com/bryanjos/elixirscript/releases). It is a tar file named elixirscript.tar.gz. * Step 2: Untar - Next, untar ex2js.tar.gz - + Next, untar elixirscript.tar.gz + ```bash - tar -xvzf ex2js.tar.gz + tar -xvzf elixirscript.tar.gz ``` - - You will want to put the bin folder from the uncompressed folder into your path. This should allow you to use the ex2js escript. - + + You will want to put the bin folder from the uncompressed folder into your path. This should allow you to use the elixirscript escript. + * Step 3: Use - This is the help output of ex2js - + This is the help output of elixirscript + ```bash - usage: ex2js [options] - + usage: elixirscript [options] + path to elixir files or the elixir code string if the -ex flag is used - + options: -o --output [path] places output at the given path -ex --elixir read input as elixir code string -r --root [path] root path for standard libs -h --help this message ``` - + the `` is the elixir code string or file path you want to convert from elixir to javascript. Below is an example of using a code string and turning it into JavaScript - + ```bash - $ ex2js ":atom" -ex + $ elixirscript ":atom" -ex Kernel.SpecialForms.atom('atom') ``` - - The ex2js escript changed the elixir code, `:atom` into the JavaScript code `Kernel.SpecialForms.atom('atom')`. The `-ex` parameter lets the script know that the input is an Elixir code string instead of a file. - + + The elixirscript escript changed the elixir code, `:atom` into the JavaScript code `Kernel.SpecialForms.atom('atom')`. The `-ex` parameter lets the script know that the input is an Elixir code string instead of a file. + What if we wanted to give it a file? You would simply do the following: - + ```bash - $ ex2js "example.exjs" + $ elixirscript "example.exjs" Kernel.SpecialForms.atom('atom') ``` - + What you will have noticed by now is that it has output everything we've done so far to the terminal. What about if we want to place the output to a path? The next example takes a file as input and outputs the result in another directory. - + ```bash - $ ex2js "example.exjs" -o "dist" + $ elixirscript "example.exjs" -o "dist" ``` - + If you look in the dist folder, you should see example.js as well as elixir.js. elixir.js is the JavaScript file that contains the Elixir Standard library. In example.js, the first line should be an import statement importing elixir.js for use. - + wildcards are also accepted: - + ```bash - $ ex2js "src/**/*.exjs" -o "dist" + $ elixirscript "src/**/*.exjs" -o "dist" ``` - + The last option we will show is the root option. This option is for defining a root path for the import statements. By default your import statement will not have anything prepended to it. For example, the elixir import will look like this: - + ```javascript import * as Elixir from 'elixir'; ``` - + If we wanted to prepend "js" to the root, we can like this: - + ``` - $ ex2js "example.ex" -o "dist" -r "js" + $ elixirscript "example.ex" -o "dist" -r "js" ``` - + Now the import will look like this: - + ```javascript import * as Elixir from 'js/elixir'; ``` - - That concludes the walkthrough on options, as well as the walkthrough on using the ex2js escript. - -### mix ex2js + + That concludes the walkthrough on options, as well as the walkthrough on using the elixirscript escript. + +### mix elixirscript * Step 1: Get dependency - + The first step is getting the dependency. In your mix.exs file for your elixir project, add elixir_script to your deps. ```elixir {:elixir_script, "~> 0.13"} ``` - + * Step 2: Now download the dep - + ```bash $ mix deps.get ``` - - Now you should have the mix task, ex2js. - + + Now you should have the mix task, elixirscript. + * Step 3: Use ```bash - $ mix ex2js "example.ex" -o "dist" -r "js" + $ mix elixirscript "example.ex" -o "dist" -r "js" ``` - + What you will notice is that the parameters are exactly the same as the escript. - + ### ElixirScript module * Step 1: Get dependency - + The first step is getting the dependency. In your mix.exs file for your elixir project, add elixir_script to your deps. ```elixir {:elixir_script, "~> 0.12"} ``` - + * Step 2: Now download the dep - + ```bash $ mix deps.get ``` * Step 3: Use - Now you will be able to use the ElixirScript module within your code. + Now you will be able to use the ElixirScript module within your code. ```elixir ElixirScript.compile(":atom") ``` - + The is also compile_path/2 and compile_quoted/2. Each of the functions take an options keyword list. - + * `:root` - a binary path prepended to the path of the standard lib imports if needed * `:env` - a Macro.env struct to use. This is most useful when using macros. Make sure that the given env has the macros required. Defaults to `__ENV__`. - + You may notice the mention of macros. Using the module in your code allows you to use macros. As long as you pass in an evironment with the macros loaded. By default, it uses the current environment. For example, if I have a module with a macro in it - + ```elixir defmodule ElixirScript.Math do defmacro squared(x) do @@ -155,23 +155,23 @@ The intent of this guide is to get you started with ElixirScript. It will give y end end ``` - + If I create a custom env I can pass it to the compile functions: - + ```elixir def make_custom_env do require Logger require ElixirScript.Math - + __ENV__ end - + ElixirScript.compile("ElixirScript.Math.squared(2)", [env: make_custom_env]) - + #Should return ["2 * 2"] ``` - - + + ### Appendix @@ -190,24 +190,24 @@ JS.import [A, B, C], "a" #translates to "import {A, B, C} from 'a'" #### Gulp I am a gulp user and I use elixirscript with gulp. Here is a snippet of how I my gulpfile looks - + ```javascript var gulp = require('gulp'); var exec = require('child_process').exec; var babel = require('gulp-babel'); - + //Calls out to the escript and places the output in src/js gulp.task('build-exjs', function(cb) { - exec('/usr/local/ex2js/bin/ex2js "' + exjsSrc + '" -o ' + "src/js", function (err, stdout, stderr) { + exec('/usr/local/elixirscript/bin/elixirscript "' + exjsSrc + '" -o ' + "src/js", function (err, stdout, stderr) { cb(err); }); }); - + gulp.task('build-js', ['build-exjs'], function() { return gulp.src(jsSrc) .pipe(babel({modules: 'system'})) .pipe(gulp.dest(jsDest)); }); ``` - -This is also the setup I use when using ElixirScript with Phoenix. If you are a brunch user, there is n [ElixirScript runch plugin](https://www.npmjs.com/package/elixirscript-brunch) \ No newline at end of file + +This is also the setup I use when using ElixirScript with Phoenix. If you are a brunch user, there is n [ElixirScript runch plugin](https://www.npmjs.com/package/elixirscript-brunch) diff --git a/gulpfile.js b/gulpfile.js index f59e845a..a57da53a 100644 --- a/gulpfile.js +++ b/gulpfile.js @@ -9,26 +9,23 @@ var sourcemaps = require('gulp-sourcemaps'); require("babel/polyfill"); var path = './priv/javascript'; - var stdLibPath = path + '/lib/**/*.js'; - -var testPath = path + '/build/tests/**/*.spec.js'; - +var testPath = path + '/test_build/tests/**/*.spec.js'; var libPath = path + '/lib'; -gulp.task('build', function() { - return gulp.src([libPath + '/**/*.js']) +gulp.task('test_build', function() { + return gulp.src(['./priv/javascript/lib/**/*.js']) .pipe(babel({sourceMap: false, modules:'common'})) - .pipe(gulp.dest('./priv/javascript/build/lib')); + .pipe(gulp.dest('./priv/javascript/test_build/lib')); }); -gulp.task('build_test', function() { +gulp.task('test_build_tests', function() { return gulp.src(['./priv/javascript/tests/**/*.spec.js']) .pipe(babel({sourceMap: false, modules:'common'})) - .pipe(gulp.dest('./priv/javascript/build/tests')); + .pipe(gulp.dest('./priv/javascript/test_build/tests')); }); -gulp.task('test',['build', 'build_test'], function () { +gulp.task('test', ['test_build', 'test_build_tests'], function () { return gulp.src(testPath, {read: false}) .pipe(mocha({reporter: 'nyan'})); }); @@ -40,14 +37,12 @@ gulp.task('lint', function () { .pipe(eslint.failOnError()); }); - gulp.task('dist_build', function() { return gulp.src(['./priv/javascript/**/*.js', '!./priv/javascript/build/**/*.js', '!./priv/javascript/dist/**/*.js', '!./priv/javascript/dist_build/**/*.js', '!./priv/javascript/tests/**/*.js']) .pipe(babel({whitelist: ['flow'], optional: ["minification.deadCodeElimination"]})) .pipe(gulp.dest('./priv/javascript/dist_build')); }); - gulp.task('dist_add_source_map', function() { return gulp.src(['./priv/javascript/dist/elixir.js']) .pipe(sourcemaps.init()) @@ -55,12 +50,5 @@ gulp.task('dist_add_source_map', function() { .pipe(gulp.dest('./priv/javascript/dist')); }); -gulp.task('common', function() { - return gulp.src(['./priv/javascript/dist/elixir.js']) - .pipe(babel({sourceMap: false, modules:'common'})) - .pipe(gulp.dest('./priv/javascript/umd')); -}); - - gulp.task('default', ['lint', 'test']); diff --git a/lib/elixir_script.ex b/lib/elixir_script.ex index fad46372..ee49e63b 100644 --- a/lib/elixir_script.ex +++ b/lib/elixir_script.ex @@ -1,5 +1,4 @@ defmodule ElixirScript do - alias ElixirScript.Translator alias ElixirScript.Translator.JSModule alias ESTree.Tools.Builder alias ESTree.Tools.Generator @@ -48,7 +47,6 @@ defmodule ElixirScript do ElixirScript.State.start_link(root, env) build_environment([quoted]) - state = ElixirScript.State.get() create_code(include_path, import_standard_libs?) end @@ -65,7 +63,7 @@ defmodule ElixirScript do path |> Path.wildcard - |> Enum.map(fn(x) -> + |> Enum.map(fn(x) -> File.read!(x) |> Code.string_to_quoted! end) @@ -77,7 +75,7 @@ defmodule ElixirScript do defp build_environment(code_list) do code_list - |> ElixirScript.Preprocess.Modules.get_info + |> ElixirScript.Preprocess.Modules.get_info end defp custom_env() do @@ -133,7 +131,7 @@ defmodule ElixirScript do File.read!(operating_path <> "/dist/elixir.js") end - defp convert_to_code(js_ast, root, include_path, env, import_standard_libs \\ true) do + defp convert_to_code(js_ast, root, include_path, env, import_standard_libs) do js_ast |> process_module(root, env, import_standard_libs) |> javascript_ast_to_code @@ -190,7 +188,7 @@ defmodule ElixirScript do Enum.reduce(modules, [], fn(x, list) -> list ++ x.body end) |> Builder.program %ElixirScript.Translator.Group{body: body} -> - Builder.program(body) + Builder.program(body) _ -> js_ast end @@ -201,12 +199,12 @@ defmodule ElixirScript do Mix.Project.build_path <> "/lib/elixir_script/priv/javascript" rescue UndefinedFunctionError -> - split_path = Path.split(Application.app_dir(:ex2js)) + split_path = Path.split(Application.app_dir(:elixirscript)) replaced_path = List.delete_at(split_path, length(split_path) - 1) replaced_path = List.delete_at(replaced_path, length(replaced_path) - 1) Path.join(replaced_path) end end - + end diff --git a/lib/elixir_script/cli.ex b/lib/elixir_script/cli.ex index ecf635e9..77a49523 100644 --- a/lib/elixir_script/cli.ex +++ b/lib/elixir_script/cli.ex @@ -1,12 +1,12 @@ defmodule ElixirScript.CLI do @moduledoc false - @switches [ - output: :binary, elixir: :boolean, root: :binary, + @switches [ + output: :binary, elixir: :boolean, root: :binary, help: :boolean, stdlib: :boolean ] - @aliases [ + @aliases [ o: :output, ex: :elixir, h: :help, r: :root, st: :stdlib ] @@ -16,7 +16,7 @@ defmodule ElixirScript.CLI do |> process end - def parse_args(args) do + def parse_args(args) do parse = OptionParser.parse(args, switches: @switches, aliases: @aliases) case parse do @@ -30,8 +30,8 @@ defmodule ElixirScript.CLI do def process(:help) do IO.write """ - usage: ex2js [options] - path to elixir files or + usage: elixirscript [options] + path to elixir files or the elixir code string if the -ex flag is used options: -o --output [path] places output at the given path @@ -55,8 +55,8 @@ defmodule ElixirScript.CLI do end def do_process(input, options) do - compile_opts = [ - root: options[:root], + compile_opts = [ + root: options[:root], include_path: options[:output] != nil ] @@ -64,19 +64,19 @@ defmodule ElixirScript.CLI do true -> ElixirScript.compile(input, compile_opts) _ -> - ElixirScript.compile_path(input, compile_opts) + ElixirScript.compile_path(input, compile_opts) end case options[:output] do nil -> - Enum.each(compile_output, + Enum.each(compile_output, fn - ({_path, code})-> IO.write(code) - (code)-> IO.write(code) + ({_path, code})-> IO.write(code) + (code)-> IO.write(code) end) output_path -> Enum.each(compile_output, fn(x) -> - write_to_file(x, output_path) + write_to_file(x, output_path) end) ElixirScript.copy_standard_libs_to_destination(output_path) diff --git a/lib/mix/tasks/ex2js.ex b/lib/mix/tasks/elixirscript.ex similarity index 86% rename from lib/mix/tasks/ex2js.ex rename to lib/mix/tasks/elixirscript.ex index d96d35a2..c2839f38 100644 --- a/lib/mix/tasks/ex2js.ex +++ b/lib/mix/tasks/elixirscript.ex @@ -1,8 +1,8 @@ -defmodule Mix.Tasks.Ex2js do +defmodule Mix.Tasks.Elixirscript do @moduledoc """ Translate Elixir code to javascript - usage: mix ex2js [options] + usage: mix elixirscript [options] path to elixir files or the elixir code string if the -ex flag is used options: -o --output [path] places output at the given path @@ -12,7 +12,7 @@ defmodule Mix.Tasks.Ex2js do """ use Mix.Task - + @shortdoc "Translate Elixir code to javascript" def run(args) do @@ -22,4 +22,4 @@ defmodule Mix.Tasks.Ex2js do |> ElixirScript.CLI.parse_args |> ElixirScript.CLI.process end -end \ No newline at end of file +end diff --git a/mix.exs b/mix.exs index 5b4b6290..41724e68 100644 --- a/mix.exs +++ b/mix.exs @@ -28,18 +28,18 @@ defmodule ElixirScript.Mixfile do defp deps do [ - {:inflex, "~> 1.4" }, + {:inflex, "~> 1.5" }, {:estree, "~> 2.0"}, {:shouldi, only: :test }, {:earmark, "~> 0.1", only: :dev }, {:ex_doc, "~> 0.10", only: :dev }, {:benchfella, "~> 0.2", only: :test}, - {:excoveralls, "~> 0.3", only: :test} + {:excoveralls, "~> 0.3", only: :test} ] end defp escript_config do - [main_module: ElixirScript.CLI, name: "ex2js"] + [main_module: ElixirScript.CLI, name: "elixirscript"] end defp description do @@ -69,8 +69,8 @@ defmodule ElixirScript.Mixfile do Mix.Task.run "app.start" dist_folder = "dist" - folder_name = "#{dist_folder}/ex2js" - archive_file_name = "#{dist_folder}/ex2js.tar.gz" + folder_name = "#{dist_folder}/elixirscript" + archive_file_name = "#{dist_folder}/elixirscript.tar.gz" File.mkdir_p("priv/javascript/dist") @@ -86,7 +86,7 @@ defmodule ElixirScript.Mixfile do { _ , _ } = System.cmd("node", ["node_modules/gulp/bin/gulp.js", "dist_add_source_map"]) File.mkdir_p(folder_name <> "/bin") - File.cp!("ex2js", "#{folder_name}/bin/ex2js") + File.cp!("elixirscript", "#{folder_name}/bin/elixirscript") File.cp_r!("priv/javascript/dist", "#{folder_name}/dist") File.cp_r!("LICENSE", "#{folder_name}/LICENSE") @@ -98,13 +98,13 @@ defmodule ElixirScript.Mixfile do def install(_) do Mix.Task.run "app.start" - System.cmd("tar", ["-zxvf", "dist/ex2js.tar.gz"]) + System.cmd("tar", ["-zxvf", "dist/elixirscript.tar.gz"]) - File.rm_rf!("/usr/local/ex2js") + File.rm_rf!("/usr/local/elixirscript") - System.cmd("mv", ["dist/ex2js", "/usr/local/ex2js"]) + System.cmd("mv", ["dist/elixirscript", "/usr/local/elixirscript"]) - IO.puts("installed at /usr/local/ex2js") + IO.puts("installed at /usr/local/elixirscript") end - + end diff --git a/mix.lock b/mix.lock index 3b317806..b2445938 100644 --- a/mix.lock +++ b/mix.lock @@ -1,14 +1,16 @@ %{"benchfella": {:hex, :benchfella, "0.2.1"}, + "certifi": {:hex, :certifi, "0.1.1"}, "dogma": {:hex, :dogma, "0.0.7"}, - "earmark": {:hex, :earmark, "0.1.17"}, + "earmark": {:hex, :earmark, "0.1.19"}, "estree": {:hex, :estree, "2.1.1"}, "ex_doc": {:hex, :ex_doc, "0.10.0"}, - "excoveralls": {:hex, :excoveralls, "0.4.0"}, + "excoveralls": {:hex, :excoveralls, "0.4.2"}, "exjsx": {:hex, :exjsx, "3.2.0"}, - "hackney": {:hex, :hackney, "1.3.2"}, + "hackney": {:hex, :hackney, "1.4.4"}, "idna": {:hex, :idna, "1.0.2"}, "inflex": {:hex, :inflex, "1.5.0"}, "jsx": {:hex, :jsx, "2.6.2"}, + "mimerl": {:hex, :mimerl, "1.0.0"}, "poison": {:hex, :poison, "1.5.0"}, "shouldi": {:hex, :shouldi, "0.2.3"}, "ssl_verify_hostname": {:hex, :ssl_verify_hostname, "1.0.5"}} diff --git a/priv/javascript/lib/patterns/patterns/defmatch.js b/priv/javascript/lib/patterns/patterns/defmatch.js index bd73c4a4..743544ce 100644 --- a/priv/javascript/lib/patterns/patterns/defmatch.js +++ b/priv/javascript/lib/patterns/patterns/defmatch.js @@ -7,9 +7,12 @@ export class MatchError extends Error { super(); if(typeof arg === 'symbol'){ - this.message = 'No match for: ' + arg.toString(); + this.message = 'No match for: ' + arg.toString(); + } else if(Array.isArray(arg)){ + let mappedValues = arg.map((x) => x.toString()); + this.message = 'No match for: ' + mappedValues; }else{ - this.message = 'No match for: ' + arg; + this.message = 'No match for: ' + arg; } this.stack = (new Error()).stack; @@ -32,7 +35,7 @@ export class Case { export function make_case(pattern: Array, fn: Function, guard: Function = () => true): Case { return new Case(pattern, fn, guard); -} +} export function defmatch(...cases: Array): Function { return function(...args: Array): any { @@ -75,7 +78,7 @@ export function patternMap(collection: Array, pattern: any, fun: Function, for(let elem of collection){ try{ let result = fun.apply(this, match(pattern, elem, guard)); - ret = ret.concat(result); + ret = ret.concat(result); }catch(e){ if(!(e instanceof MatchError)){ throw e; @@ -84,4 +87,4 @@ export function patternMap(collection: Array, pattern: any, fun: Function, } return ret; -} \ No newline at end of file +} From baf977049df2971cd1d2b2e73b719393160f813f Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Tue, 24 Nov 2015 10:56:30 -0600 Subject: [PATCH 050/860] Added aliases, requires, and imports to ElixirScript.Module --- lib/elixir_script.ex | 17 +- lib/elixir_script/env.ex | 7 +- lib/elixir_script/module.ex | 42 ++++- lib/elixir_script/preprocess/aliases.ex | 50 +++-- lib/elixir_script/preprocess/modules.ex | 228 +++++++++++++++++------ lib/elixir_script/state.ex | 80 +++++++- lib/elixir_script/translator.ex | 18 +- lib/elixir_script/translator/import.ex | 67 ++++--- lib/elixir_script/translator/module.ex | 41 ++-- lib/elixir_script/translator/protocol.ex | 25 ++- mix.exs | 3 +- mix.lock | 2 + 12 files changed, 411 insertions(+), 169 deletions(-) diff --git a/lib/elixir_script.ex b/lib/elixir_script.ex index ee49e63b..c8e0b492 100644 --- a/lib/elixir_script.ex +++ b/lib/elixir_script.ex @@ -86,18 +86,23 @@ defmodule ElixirScript do defp create_code(include_path, import_standard_libs?) do + ElixirScript.State.process_imports() + state = ElixirScript.State.get() current = self result = state.modules |> Enum.map(fn(x) -> - result = ElixirScript.Translator.Module.make_module(x.name, x.body, state.env) - |> Enum.map(fn(x) -> - convert_to_code(x, state.root, include_path, state.env, import_standard_libs?) - end) - - spawn_link fn -> (send current, { self, result }) end + spawn_link fn -> + Process.put(:current_module, x.name) + + result = ElixirScript.Translator.Module.make_module(x.name, x.body, state.env) + |> Enum.map(fn(x) -> + convert_to_code(x, state.root, include_path, state.env, import_standard_libs?) + end) + send current, { self, result } + end end) |> Enum.map(fn (pid) -> receive do { ^pid, x } -> x end diff --git a/lib/elixir_script/env.ex b/lib/elixir_script/env.ex index 7c319880..5fe1f014 100644 --- a/lib/elixir_script/env.ex +++ b/lib/elixir_script/env.ex @@ -1,5 +1,6 @@ defmodule ElixirScript.Env do @moduledoc false - - defstruct env: __ENV__, modules: HashSet.new, root: "", protocols: HashDict.new -end \ No newline at end of file + + defstruct env: __ENV__, modules: HashSet.new, root: "", protocols: HashDict.new + +end diff --git a/lib/elixir_script/module.ex b/lib/elixir_script/module.ex index 66d948e5..7f0f1a3f 100644 --- a/lib/elixir_script/module.ex +++ b/lib/elixir_script/module.ex @@ -1,5 +1,41 @@ defmodule ElixirScript.Module do @moduledoc false - - defstruct name: nil, functions: [], macros: [], body: nil -end \ No newline at end of file + + defstruct name: nil, functions: Keyword.new, macros: Keyword.new, body: nil, + aliases: [], requires: [], imports: [], js_imports: [] + + def functions(module) do + Keyword.keys(module.functions) |> Enum.uniq + end + + def macros(module) do + Keyword.keys(module.macros) |> Enum.uniq + end + + def aliases(module) do + module.aliases + end + + def requires(module) do + module.requires + end + + def imports(module) do + module.imports + end + + def has_alias?(module, name) do + List.keymember?(Set.to_list(module.aliases), name, 0) + end + + def imported?(module, function_name) do + imports = Enum.find(module.imports, fn({_, functions}) -> + Enum.member?(functions, function_name) + end) + + if imports do + elem(imports, 0) + end + end + +end diff --git a/lib/elixir_script/preprocess/aliases.ex b/lib/elixir_script/preprocess/aliases.ex index 6822267e..6a5b8fd4 100644 --- a/lib/elixir_script/preprocess/aliases.ex +++ b/lib/elixir_script/preprocess/aliases.ex @@ -13,50 +13,44 @@ defmodule ElixirScript.Preprocess.Aliases do #the "Hello.World" would be placed in a set and later used for building an alias """ - def process(ast, env) do - - state = %{ add: HashSet.new, defined: HashSet.new } - - {new_ast, state } = Macro.prewalk(ast, state, fn(x, acc) -> - process_aliases(x, acc, env) + def process(module_name_list, ast, env) do + new_ast = Macro.prewalk(ast, fn(x) -> + process_aliases(x, env, module_name_list) end) - { new_ast, state.add } - end - - def process_aliases({:alias, _, [{:__aliases__, _, _name}, [as: {:__aliases__, _, alias_name}]]} = ast, state, _) do - { ast, %{state | defined: HashSet.put(state.defined, List.last(alias_name)) } } - end + module = ElixirScript.State.get_module(module_name_list) - def process_aliases({:alias, _, [{:__aliases__, _, name}]} = ast, state, _) do - { ast, %{state | defined: HashSet.put(state.defined, List.last(name)) } } + if module do + { new_ast, ElixirScript.Module.aliases(module) } + else + { new_ast, [] } + end end - def process_aliases({{:., meta1, [{:__aliases__, meta2, aliases}, function]}, meta3, params} = ast, state, env) when aliases in [[:Collectable], [:Enumerable], [:Inspect], [:List, :Chars], [:String, :Chars]] do + def process_aliases({{:., meta1, [{:__aliases__, meta2, aliases}, function]}, meta3, params}, _, module_name_list) when aliases in [[:Collectable], [:Enumerable], [:Inspect], [:List, :Chars], [:String, :Chars]] do new_ast = {{:., meta1, [{:__aliases__, meta2, List.last(aliases) |> List.wrap }, function]}, meta3, params} - - new_state = %{ state | add: HashSet.put(state.add, [:Elixir] ++ aliases) } - { new_ast, new_state } + ElixirScript.State.add_alias(module_name_list, {:__aliases__, meta2, [:Elixir] ++ aliases}) + new_ast end - def process_aliases({{:., meta1, [{:__aliases__, meta2, aliases}, function]}, meta3, params} = ast, state, env) do + def process_aliases({{:., meta1, [{:__aliases__, meta2, aliases}, function]}, meta3, params} = ast, _, module_name_list) do if ElixirScript.State.module_listed?(aliases) do new_ast = {{:., meta1, [{:__aliases__, meta2, List.last(aliases) |> List.wrap }, function]}, meta3, params} - new_state = if !HashSet.member?(state.defined, List.last(aliases)) do - %{ state | add: HashSet.put(state.add, aliases) } - else - state + module = ElixirScript.State.get_module(module_name_list) + + if !ElixirScript.Module.has_alias?(module, {:__aliases__, meta2, List.last(aliases) |> List.wrap }) do + ElixirScript.State.add_alias(module_name_list, {:__aliases__, meta2, aliases}) end - { new_ast, new_state } + new_ast else - { ast, state } + ast end end - def process_aliases(ast, state, _) do - {ast, state} + def process_aliases(ast, _, _) do + ast end -end \ No newline at end of file +end diff --git a/lib/elixir_script/preprocess/modules.ex b/lib/elixir_script/preprocess/modules.ex index 2db7e4bb..53ee2a6f 100644 --- a/lib/elixir_script/preprocess/modules.ex +++ b/lib/elixir_script/preprocess/modules.ex @@ -15,20 +15,20 @@ defmodule ElixirScript.Preprocess.Modules do Enum.map(modules, fn { :__block__, _, list } -> {mods, no_mods} = Enum.partition(list, fn - ({:defprotocol, _, [{:__aliases__, _, protocol}| rest ] }) when not protocol in @standard_lib_protocols -> + ({:defprotocol, _, [{:__aliases__, _, protocol}| _ ] }) when not protocol in @standard_lib_protocols -> true - ({:defimpl, _, [ {:__aliases__, _, protocol} | rest] }) when not protocol in @standard_lib_protocols -> + ({:defimpl, _, [ {:__aliases__, _, protocol} | _] }) when not protocol in @standard_lib_protocols -> true - ({:defmodule, _, _}) -> + ({:defmodule, _, _}) -> true - _ -> + _ -> false end) mods ++ [{:defmodule, [], [{:__aliases__, [], [:ElixirScript, :Temp]}, [do: { :__block__, [], no_mods }]]}] - ({:defprotocol, _, [{:__aliases__, _, protocol}| rest ] }) = x when not protocol in @standard_lib_protocols -> + ({:defprotocol, _, [{:__aliases__, _, protocol}| _ ] }) = x when not protocol in @standard_lib_protocols -> x - ({:defimpl, _, [ {:__aliases__, _, protocol} | rest] }) = x when not protocol in @standard_lib_protocols -> + ({:defimpl, _, [ {:__aliases__, _, protocol} | _] }) = x when not protocol in @standard_lib_protocols -> x ({:defmodule, _, _}) = x -> x @@ -57,18 +57,21 @@ defmodule ElixirScript.Preprocess.Modules do ElixirScript.State.add_protocol_impl(protocol, type, {:__block__, [], [spec]}) end - def do_get_info({:defmodule, _, [{:__aliases__, meta, [:ElixirScript, :Temp]}, [do: body]]} = ast) do + def do_get_info({:defmodule, _, [{:__aliases__, _, [:ElixirScript, :Temp]}, [do: body]]} = ast) do mod = %ElixirScript.Module{ name: [:ElixirScript, :Temp] , body: body } State.add_module(mod) - + ast end - def do_get_info({:defmodule, _, [{:__aliases__, meta, module_name_list}, [do: body]]} = ast) do + def do_get_info({:defmodule, _, [{:__aliases__, _, module_name_list}, [do: body]]} = ast) do body = make_inner_module_aliases(module_name_list, body) functions = get_functions_from_module(body) macros = get_macros_from_module(body) + aliases = get_aliases_from_module(body) + requires = get_requires_from_module(body) + imports = get_imports_from_module(body) body = case body do {:__block__, _, _ } -> @@ -76,8 +79,13 @@ defmodule ElixirScript.Preprocess.Modules do _ -> body end - - mod = %ElixirScript.Module{ name: module_name_list , body: body, functions: functions, macros: macros } + + aliases = Set.union(aliases, requires.aliases) |> Set.union(imports.aliases) + + mod = %ElixirScript.Module{ name: module_name_list, body: body, + functions: functions, macros: macros, + aliases: aliases, requires: requires.requires, + imports: imports.imports } State.add_module(mod) @@ -96,24 +104,13 @@ defmodule ElixirScript.Preprocess.Modules do {:__block__, meta2, list2 } -> list2 = Enum.map(list2, fn(x) -> case x do - {:defmodule, meta1, [{:__aliases__, meta2, module_name_list2}, [do: body2]]} -> + {:defmodule, _, [{:__aliases__, _, module_name_list2}, [do: body2]]} -> body2 = make_inner_module_aliases(module_name_list2, body2) - - functions = get_functions_from_module(body2) - macros = get_macros_from_module(body2) - - mod = %ElixirScript.Module{ name: module_name_list2, body: body2, functions: functions, macros: macros } - - if State.module_listed?(module_name_list2) do - State.delete_module(mod) - end - - mod = %ElixirScript.Module{ name: module_name_list ++ module_name_list2, body: body2, functions: functions, macros: macros } - State.add_module(mod) + inner_alias = add_module_to_state(module_name_list, module_name_list2, body2) [ - {:alias, meta1, [{:__aliases__, [alias: false], module_name_list ++ module_name_list2}]} - ] + inner_alias + ] _ -> x end @@ -121,58 +118,175 @@ defmodule ElixirScript.Preprocess.Modules do |> List.flatten {:__block__, meta2, list2} - {:defmodule, meta1, [{:__aliases__, meta2, module_name_list2}, [do: body2]]} -> + {:defmodule, _, [{:__aliases__, meta2, module_name_list2}, [do: body2]]} -> body2 = make_inner_module_aliases(module_name_list2, body2) - - functions = get_functions_from_module(body2) - macros = get_macros_from_module(body2) - - mod = %ElixirScript.Module{ name: module_name_list2, body: body2, functions: functions, macros: macros } - - if State.module_listed?(module_name_list2) do - State.delete_module(mod) - end - - mod = %ElixirScript.Module{ name: module_name_list ++ module_name_list2, body: body2, functions: functions, macros: macros } - State.add_module(mod) + inner_alias = add_module_to_state(module_name_list, module_name_list2, body2) {:__block__, meta2, [ - {:alias, meta1, [{:__aliases__, [alias: false], module_name_list ++ module_name_list2}]} + inner_alias ] } _ -> - body + body end end + defp add_module_to_state(module_name_list, module_name_list2, body2) do + functions = get_functions_from_module(body2) + macros = get_macros_from_module(body2) + aliases = get_aliases_from_module(body2) + requires = get_requires_from_module(body2) + imports = get_imports_from_module(body2) + + inner_alias = {:alias, [], [{:__aliases__, [alias: false], module_name_list ++ module_name_list2}]} + {inner_alias_atom, _ } = Code.eval_quoted({:__aliases__, [alias: false], module_name_list ++ module_name_list2}) + + aliases = Set.put(aliases, {inner_alias_atom, inner_alias_atom}) + aliases = Set.union(aliases, requires.aliases) |> Set.union(imports.aliases) + + mod = %ElixirScript.Module{ name: module_name_list2, body: body2, + functions: functions, macros: macros, aliases: aliases, + requires: requires.requires, imports: imports.imports } + + if State.module_listed?(module_name_list2) do + State.delete_module(mod) + end + + mod = %ElixirScript.Module{ name: module_name_list ++ module_name_list2, body: body2, + functions: functions, macros: macros, aliases: aliases, + requires: requires.requires } + + State.add_module(mod) + + inner_alias + end + + + defp get_functions_from_module({:__block__, _, list}) do + Enum.reduce(list, Keyword.new, fn + ({:def, _, [{:when, _, [{name, _, params} | _guards] }, [do: _body]] }, state) -> + arity = length(params) + + unless Enum.member?(Keyword.get_values([], name), arity) do + Keyword.put(state, name, arity); + end + + ({:def, _, [{name, _, params}, [do: _body]]}, state) -> + arity = length(params) + + unless Enum.member?(Keyword.get_values([], name), arity) do + Keyword.put(state, name, arity); + end - defp get_functions_from_module({:__block__, meta, list}) do - Enum.reduce(list, HashSet.new, fn - ({:def, _, [{:when, _, [{name, _, _params} | _guards] }, [do: _body]] }, state) -> - Set.put(state, name) - ({:def, _, [{name, _, _params}, [do: _body]]}, state) -> - Set.put(state, name) _, state -> state + end) end - defp get_functions_from_module(ast) do - [] + defp get_functions_from_module(_) do + Keyword.new end - defp get_macros_from_module({:__block__, meta, list}) do + defp get_macros_from_module({:__block__, _, list}) do + Enum.reduce(list, Keyword.new, fn + ({:defmacro, _, [{:when, _, [{name, _, params} | _guards] }, [do: _body]] }, state) -> + arity = length(params) + + unless Enum.member?(Keyword.get_values([], name), arity) do + Keyword.put(state, name, arity); + end + + ({:defmacro, _, [{name, _, params}, [do: _body]]}, state) -> + arity = length(params) + + unless Enum.member?(Keyword.get_values([], name), arity) do + Keyword.put(state, name, arity); + end + + _, state -> + state + end) + end + + defp get_macros_from_module(_) do + Keyword.new + end + + + defp get_aliases_from_module({:__block__, _, list}) do Enum.reduce(list, HashSet.new, fn - ({:defmacro, _, [{:when, _, [{name, _, _params} | _guards] }, [do: _body]] }, state) -> - Set.put(state, name) - ({:defmacro, _, [{name, _, _params}, [do: _body]]}, state) -> - Set.put(state, name) + ({:alias, _, [name]}, state) -> + {main, _} = Code.eval_quoted(name) + {:__aliases__, _, aliases } = name + {the_alias, _} = Code.eval_quoted({:__aliases__, [alias: false], List.last(aliases) |> List.wrap }) + Set.put(state, {the_alias, main}) + ({:alias, _, [name, [as: the_alias]]}, state) -> + {name, _} = Code.eval_quoted(name) + {the_alias, _} = Code.eval_quoted(the_alias) + + Set.put(state, {the_alias, name}) + _, state -> state end) end - defp get_macros_from_module(ast) do - [] + + defp get_aliases_from_module(_) do + HashSet.new + end + + + defp get_requires_from_module({:__block__, _, list}) do + Enum.reduce(list, %{ requires: HashSet.new, aliases: HashSet.new }, fn + ({:require, _, [name]}, state) -> + {main, _} = Code.eval_quoted(name) + {:__aliases__, _, aliases } = name + {the_alias, _} = Code.eval_quoted({:__aliases__, [alias: false], List.last(aliases) |> List.wrap }) + + %{ state | requires: Set.put(state.requires, main), aliases: Set.put(state.aliases, {the_alias, main}) } + ({:require, _, [name, [as: the_alias]]}, state) -> + {name, _} = Code.eval_quoted(name) + {the_alias, _} = Code.eval_quoted(the_alias) + + %{ state | requires: Set.put(state.requires, name), aliases: Set.put(state.aliases, {the_alias, name}) } + + _, state -> + state + end) + end + + + defp get_requires_from_module(_) do + %{ requires: HashSet.new, aliases: HashSet.new } + end + + + defp get_imports_from_module({:__block__, _, list}) do + Enum.reduce(list, %{ imports: HashSet.new, aliases: HashSet.new }, fn + ({:import, _, [name]}, state) -> + {main, _} = Code.eval_quoted(name) + {:__aliases__, _, aliases } = name + {the_alias, _} = Code.eval_quoted({:__aliases__, [alias: false], List.last(aliases) |> List.wrap }) + + %{ state | imports: Set.put(state.imports, {main, []}), aliases: Set.put(state.aliases, {the_alias, main}) } + + ({:import, _, [name, options]}, state) -> + {main, _} = Code.eval_quoted(name) + {:__aliases__, _, aliases } = name + {the_alias, _} = Code.eval_quoted({:__aliases__, [alias: false], List.last(aliases) |> List.wrap }) + + %{ state | imports: Set.put(state.imports, {main, options}), aliases: Set.put(state.aliases, {the_alias, main}) } + + + _, state -> + state + end) + end + + + defp get_imports_from_module(_) do + %{ imports: HashSet.new, aliases: HashSet.new } end -end \ No newline at end of file +end diff --git a/lib/elixir_script/state.ex b/lib/elixir_script/state.ex index a2db37d3..c492b888 100644 --- a/lib/elixir_script/state.ex +++ b/lib/elixir_script/state.ex @@ -26,13 +26,13 @@ defmodule ElixirScript.State do def module_listed?(module_name) do Agent.get(__MODULE__, fn(state) -> Enum.any?(state.modules, fn(x) -> x.name == module_name end) || - Enum.any?(state.protocols, fn({key, value}) -> key == module_name end) + Enum.any?(state.protocols, fn({key, _}) -> key == module_name end) end) end def protocol_listed?(module_name) do Agent.get(__MODULE__, fn(state) -> - Enum.any?(state.protocols, fn({key, value}) -> key == module_name end) + Enum.any?(state.protocols, fn({key, _}) -> key == module_name end) end) end @@ -76,18 +76,92 @@ defmodule ElixirScript.State do end) end + def get_module(module) when is_atom(module) do + module_name_list = Atom.to_string(module) + |> String.split(".") + |> tl + |> Enum.map(fn(x) -> String.to_atom(x) end) + + get_module(module_name_list) + end + + def get_module(module_name_list) do state = Agent.get(__MODULE__, fn(state) -> state end) + do_get_module(state, module_name_list) + end + + defp do_get_module(state, module) when is_atom(module) do + module_name_list = Atom.to_string(module) + |> String.split(".") + |> tl + |> Enum.map(fn(x) -> String.to_atom(x) end) + + do_get_module(state, module_name_list) + end + + defp do_get_module(state, module_name_list) do Enum.find(Set.to_list(state.modules), fn(x) -> x.name == module_name_list end) end + + def add_alias(module_name_list, name) do + module = get_module(module_name_list) + + if module do + {main, _} = Code.eval_quoted(name) + {:__aliases__, _, aliases } = name + {the_alias, _} = Code.eval_quoted({:__aliases__, [alias: false], List.last(aliases) |> List.wrap }) + + delete_module(module) + + module = %{module | aliases: Set.put(module.aliases, {the_alias, main}) } + add_module(module) + end + end + + def process_imports() do + Agent.update(__MODULE__, fn(state) -> + modules = state.modules + |> Enum.map(fn(x) -> + %{x | imports: Enum.map(x.imports, fn({y, options}) -> {y, get_imported_functions(state, y, options)} end)} + end) + + %{ state | modules: Enum.into(modules, HashSet.new) } + end) + end + + defp get_imported_functions(state, module_name, []) do + module = do_get_module(state, module_name) + ElixirScript.Module.functions(module) ++ ElixirScript.Module.macros(module) + end + + defp get_imported_functions(_, _, [only: list]) do + Keyword.keys(list) + end + + defp get_imported_functions(state, module_name, [only: :functions]) do + module = do_get_module(state, module_name) + ElixirScript.Module.functions(module) + end + + defp get_imported_functions(state, module_name, [only: :macros]) do + module = do_get_module(state, module_name) + ElixirScript.Module.macros(module) + end + + defp get_imported_functions(state, module_name, [except: list]) do + module = do_get_module(state, module_name) + ElixirScript.Module.functions(module) ++ ElixirScript.Module.macros(module) -- Keyword.keys(list) + end + def stop() do Agent.stop(__MODULE__) end -end \ No newline at end of file +end diff --git a/lib/elixir_script/translator.ex b/lib/elixir_script/translator.ex index 46a281ef..040759df 100644 --- a/lib/elixir_script/translator.ex +++ b/lib/elixir_script/translator.ex @@ -232,12 +232,8 @@ defmodule ElixirScript.Translator do Quote.make_quote(opts, expr, env) end - defp do_translate({:import, _, [{:__aliases__, _, module_name_list}, params ]}, env) do - Import.make_import(module_name_list, params, env) - end - - defp do_translate({:import, _, [{:__aliases__, _, module_name_list}]}, env) do - Import.make_import(module_name_list, [], env) + defp do_translate({:import, _, _}, _) do + %ElixirScript.Translator.Group{} end defp do_translate({:alias, _, [alias_info, options]}, _) when is_tuple(alias_info) do @@ -330,7 +326,15 @@ defmodule ElixirScript.Translator do else expanded_ast = Macro.expand(ast, env) if expanded_ast == ast do - Function.make_function_call(name, params, env) + module = ElixirScript.State.get_module(Process.get(:current_module)) + imported_module = ElixirScript.Module.imported?(module, name) + + if imported_module do + imported_module = ElixirScript.State.get_module(imported_module) + Function.make_function_call({:__aliases__, [], List.last(imported_module.name) |> List.wrap }, name, params, env) + else + Function.make_function_call(name, params, env) + end else translate(expanded_ast, env) end diff --git a/lib/elixir_script/translator/import.ex b/lib/elixir_script/translator/import.ex index c2faed66..5c6617ec 100644 --- a/lib/elixir_script/translator/import.ex +++ b/lib/elixir_script/translator/import.ex @@ -11,51 +11,52 @@ defmodule ElixirScript.Translator.Import do if State.protocol_listed?(name) do default = true end - + import_specifier = if default == false do if options[:as] do {_, _, alt} = options[:as] - + JS.import_namespace_specifier( JS.identifier(List.last(alt)) ) - else + else JS.import_namespace_specifier( JS.identifier(List.last(name)) - ) + ) end else if options[:as] do {_, _, alt} = options[:as] - + JS.import_specifier( JS.identifier("default"), JS.identifier(List.last(alt)) ) - else + else JS.import_default_specifier( JS.identifier(List.last(name)), JS.identifier(List.last(name)) - ) + ) end end - + import_path = make_source(name) JS.import_declaration( - [import_specifier], + [import_specifier], JS.identifier(import_path) ) end def make_import(module_name_list, [], _) do - functions = State.get_module(module_name_list).functions + module = State.get_module(module_name_list) + functions = ElixirScript.Module.functions(module) functions = Enum.map(functions, fn ({name, _arity}) -> name (name) -> - name + name end) specifiers = Enum.map(functions, fn @@ -70,7 +71,7 @@ defmodule ElixirScript.Translator.Import do JS.import_specifier( name, name - ) + ) end) import_path = make_source(module_name_list) @@ -79,13 +80,14 @@ defmodule ElixirScript.Translator.Import do end def make_import(module_name_list, [only: :functions], _) do - functions = State.get_module(module_name_list).functions + module = State.get_module(module_name_list) + functions = ElixirScript.Module.functions(module) functions = Enum.map(functions, fn ({name, _arity}) -> name (name) -> - name + name end) specifiers = Enum.map(functions, fn @@ -94,7 +96,7 @@ defmodule ElixirScript.Translator.Import do JS.import_specifier( name, name - ) + ) end) import_path = make_source(module_name_list) @@ -107,10 +109,12 @@ defmodule ElixirScript.Translator.Import do ({name, _arity}) -> name (name) -> - name + name end) - functions = State.get_module(module_name_list) + module = State.get_module(module_name_list) + + functions = ElixirScript.Module.functions(module) |> get_functions_from_module([only: only]) specifiers = Enum.map(functions, fn @@ -119,7 +123,7 @@ defmodule ElixirScript.Translator.Import do JS.import_specifier( name, name - ) + ) end) import_path = make_source(module_name_list) @@ -132,10 +136,11 @@ defmodule ElixirScript.Translator.Import do ({name, _arity}) -> name (name) -> - name + name end) - functions = State.get_module(module_name_list) + module = State.get_module(module_name_list) + functions = ElixirScript.Module.functions(module) |> get_functions_from_module([except: except]) specifiers = Enum.map(functions, fn @@ -144,7 +149,7 @@ defmodule ElixirScript.Translator.Import do JS.import_specifier( name, name - ) + ) end) import_path = make_source(module_name_list) @@ -158,21 +163,21 @@ defmodule ElixirScript.Translator.Import do end def make_file_path(name) do - Enum.map(name, fn(x) -> + Enum.map(name, fn(x) -> x - |> Atom.to_string - |> Inflex.underscore - |> String.downcase - end) + |> Atom.to_string + |> Inflex.underscore + |> String.downcase + end) |> Enum.join("/") end - def get_functions_from_module(module, [only: only]) do - Set.intersection(Enum.into(only, HashSet.new), Enum.into(module.functions, HashSet.new)) + def get_functions_from_module(functions, [only: only]) do + Set.intersection(Enum.into(only, HashSet.new), Enum.into(functions, HashSet.new)) end - def get_functions_from_module(module, [except: except]) do - Set.difference(Enum.into(module.functions, HashSet.new), Enum.into(except, HashSet.new)) + def get_functions_from_module(functions, [except: except]) do + Set.difference(Enum.into(functions, HashSet.new), Enum.into(except, HashSet.new)) end def create_standard_lib_imports(root, _) do @@ -181,7 +186,7 @@ defmodule ElixirScript.Translator.Import do ) import_declaration = JS.import_declaration( - [import_specifier], + [import_specifier], JS.identifier("'#{root(root) <> "elixir"}'") ) diff --git a/lib/elixir_script/translator/module.ex b/lib/elixir_script/translator/module.ex index 6228db61..ef1f3d2c 100644 --- a/lib/elixir_script/translator/module.ex +++ b/lib/elixir_script/translator/module.ex @@ -10,16 +10,16 @@ defmodule ElixirScript.Translator.Module do alias ElixirScript.Translator.Primitive def make_module([:ElixirScript, :Temp], body, env) do - [%JSModule{ name: [:ElixirScript, :Temp], body: translate_body(body, env) |> Utils.inflate_groups }] + [%JSModule{ name: [:ElixirScript, :Temp], body: translate_body(body, env) |> Utils.inflate_groups }] end def make_module(module_name_list, nil, env) do - [%JSModule{ name: module_name_list, body: List.wrap(create__module__(module_name_list, env)) }] + [%JSModule{ name: module_name_list, body: List.wrap(create__module__(module_name_list, env)) }] end def make_module(module_name_list, body, env) do body = Using.process(body, env) - { body, aliases } = Aliases.process(body, env) + { body, aliases } = Aliases.process(module_name_list, body, env) { body, functions } = extract_functions_from_module(body) { exported_functions, private_functions } = process_functions(functions, env) @@ -31,7 +31,7 @@ defmodule ElixirScript.Translator.Module do #Add imports found from walking the ast - #and make sure to only put one declaration per alias + #and make sure to only put one declaration per alias imports = process_imports(imports, aliases) imports = imports.imports @@ -42,14 +42,14 @@ defmodule ElixirScript.Translator.Module do JS.expression_statement(x) _ -> x - end + end end) body = Utils.inflate_groups(body) exported_object = JS.object_expression( make_defstruct_property(structs) ++ - Enum.map(exported_functions, fn({key, _value}) -> + Enum.map(exported_functions, fn({key, _value}) -> JS.property(JS.identifier(key), JS.identifier(key), :init, true) end) ) @@ -73,14 +73,14 @@ defmodule ElixirScript.Translator.Module do body: imports ++ List.wrap(create__module__(module_name_list, env)) ++ structs ++ private_functions ++ exported_functions ++ body ++ [default] } ] ++ List.flatten(modules) - + result end def translate_body(body, env) do body = Translator.translate(body, env) - body = case body do + case body do [%ESTree.BlockStatement{ body: body }] -> body %ESTree.BlockStatement{ body: body } -> @@ -112,7 +112,7 @@ defmodule ElixirScript.Translator.Module do { nil, %{ state | private: HashDict.put(state.private, name, HashDict.get(state.private, name, []) ++ [function]) } - } + } (x, state) -> { x, state } end) @@ -158,14 +158,15 @@ defmodule ElixirScript.Translator.Module do %ESTree.FunctionDeclaration{id: %ESTree.Identifier{name: :defstruct}} -> [JS.property(JS.identifier(:defstruct), JS.identifier(:defstruct), :init, true )] %ESTree.FunctionDeclaration{id: %ESTree.Identifier{name: :defexception}} -> - [JS.property(JS.identifier(:defexception), JS.identifier(:defexception), :init, true )] + [JS.property(JS.identifier(:defexception), JS.identifier(:defexception), :init, true )] end end def process_imports(imports, aliases) do imports ++ make_imports(aliases) - |> Enum.reduce(HashSet.new, fn(x, acc)-> - HashSet.put(acc, x) + |> Enum.into(HashSet.new) + |> Enum.reduce(HashSet.new, fn(x, acc)-> + HashSet.put(acc, x) end) |> HashSet.to_list |> Enum.reduce(%{ identifiers: HashSet.new, imports: [] }, fn(x, state) -> @@ -183,8 +184,8 @@ defmodule ElixirScript.Translator.Module do %{ state | identifiers: HashSet.put(state.identifiers, id.name), imports: state.imports ++ [x] } end _ -> - %{ state | imports: state.imports ++ [x] } - end + %{ state | imports: state.imports ++ [x] } + end end) end @@ -211,7 +212,7 @@ defmodule ElixirScript.Translator.Module do JS.variable_declaration([declarator], :const) end - def create__module__(module_name_list, env) do + def create__module__(module_name_list, _) do module_name = Enum.map(module_name_list, &Atom.to_string(&1)) |> Enum.join(".") |> String.to_atom @@ -225,8 +226,14 @@ defmodule ElixirScript.Translator.Module do end def make_imports(enum) do - Enum.map(enum, fn(x) -> - ElixirScript.Translator.Import.make_alias_import({ nil, nil, x }, []) + Enum.map(enum, fn + + {as, name} -> + name = Atom.to_string(name) |> String.split(".") |> tl |> Enum.map(fn(x) -> String.to_atom(x) end) + as = Atom.to_string(as) |> String.split(".") |> tl |> Enum.map(fn(x) -> String.to_atom(x) end) + ElixirScript.Translator.Import.make_alias_import({ nil, nil, name }, [as: { nil, nil, as }]) + x -> + ElixirScript.Translator.Import.make_alias_import({ nil, nil, List.wrap(x) }, []) end) end diff --git a/lib/elixir_script/translator/protocol.ex b/lib/elixir_script/translator/protocol.ex index 1da884c4..424d1a6e 100644 --- a/lib/elixir_script/translator/protocol.ex +++ b/lib/elixir_script/translator/protocol.ex @@ -34,8 +34,7 @@ defmodule ElixirScript.Translator.Protocol do end defp define_spec(name, spec, env) do - - { body, aliases } = Aliases.process(spec, env) + { body, aliases } = Aliases.process(name, spec, env) { body, functions } = extract_function_from_spec(body) @@ -48,8 +47,8 @@ defmodule ElixirScript.Translator.Protocol do imports = Module.process_imports(imports, aliases) imports = imports.imports - object = Enum.map(exported_functions, fn({key, value}) -> - Map.make_property(JS.identifier(Utils.filter_name(key)), value) + object = Enum.map(exported_functions, fn({key, value}) -> + Map.make_property(JS.identifier(Utils.filter_name(key)), value) end) |> JS.object_expression @@ -77,7 +76,7 @@ defmodule ElixirScript.Translator.Protocol do defp define_impls(name, impls, env) do Enum.map(impls, fn({type, impl}) -> type = map_to_js(type) - { body, aliases } = Aliases.process(impl, env) + { body, aliases } = Aliases.process(name, impl, env) { body, functions } = Module.extract_functions_from_module(body) { exported_functions, _ } = process_functions(functions, env) @@ -88,8 +87,8 @@ defmodule ElixirScript.Translator.Protocol do imports = Module.process_imports(imports, aliases) imports = imports.imports - object = Enum.map(exported_functions, fn({key, value}) -> - Map.make_property(JS.identifier(Utils.filter_name(key)), value) + object = Enum.map(exported_functions, fn({key, value}) -> + Map.make_property(JS.identifier(Utils.filter_name(key)), value) end) |> JS.object_expression @@ -108,7 +107,7 @@ defmodule ElixirScript.Translator.Protocol do end) |> Enum.reduce({[], [], []}, fn({impl_imports, impl_body, impl}, acc) -> - { + { elem(acc, 0) ++ impl_imports, elem(acc, 1) ++ impl_body, elem(acc, 2) ++ impl @@ -121,10 +120,10 @@ defmodule ElixirScript.Translator.Protocol do protocol = Translator.translate(protocol, env) { _, functions } = Module.extract_functions_from_module(impl) - { exported_functions, _ } = process_functions(functions, env) + { exported_functions, _ } = process_functions(functions, env) - object = Enum.map(exported_functions, fn({key, value}) -> - Map.make_property(JS.identifier(Utils.filter_name(key)), value) + object = Enum.map(exported_functions, fn({key, value}) -> + Map.make_property(JS.identifier(Utils.filter_name(key)), value) end) |> JS.object_expression @@ -156,7 +155,7 @@ defmodule ElixirScript.Translator.Protocol do { nil, %{ state | exported: HashDict.put(state.exported, name, HashDict.get(state.exported, name, []) ++ [function]) } - } + } (x, state) -> { x, state } end) @@ -257,4 +256,4 @@ defmodule ElixirScript.Translator.Protocol do ) end -end \ No newline at end of file +end diff --git a/mix.exs b/mix.exs index 41724e68..d81ed8f0 100644 --- a/mix.exs +++ b/mix.exs @@ -34,7 +34,8 @@ defmodule ElixirScript.Mixfile do {:earmark, "~> 0.1", only: :dev }, {:ex_doc, "~> 0.10", only: :dev }, {:benchfella, "~> 0.2", only: :test}, - {:excoveralls, "~> 0.3", only: :test} + {:excoveralls, "~> 0.3", only: :test}, + {:credo, "~> 0.1.9", only: [:dev, :test]} ] end diff --git a/mix.lock b/mix.lock index b2445938..134aeb57 100644 --- a/mix.lock +++ b/mix.lock @@ -1,5 +1,7 @@ %{"benchfella": {:hex, :benchfella, "0.2.1"}, + "bunt": {:hex, :bunt, "0.1.4"}, "certifi": {:hex, :certifi, "0.1.1"}, + "credo": {:hex, :credo, "0.1.10"}, "dogma": {:hex, :dogma, "0.0.7"}, "earmark": {:hex, :earmark, "0.1.19"}, "estree": {:hex, :estree, "2.1.1"}, From c72371bb6839792984442f0e341a070afae3168f Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Tue, 24 Nov 2015 11:28:23 -0600 Subject: [PATCH 051/860] Added js_imports to modules --- lib/elixir_script/preprocess/modules.ex | 23 +++++++++++++++++++++-- 1 file changed, 21 insertions(+), 2 deletions(-) diff --git a/lib/elixir_script/preprocess/modules.ex b/lib/elixir_script/preprocess/modules.ex index 53ee2a6f..21e2f4de 100644 --- a/lib/elixir_script/preprocess/modules.ex +++ b/lib/elixir_script/preprocess/modules.ex @@ -72,6 +72,7 @@ defmodule ElixirScript.Preprocess.Modules do aliases = get_aliases_from_module(body) requires = get_requires_from_module(body) imports = get_imports_from_module(body) + js_imports = get_js_imports_from_module(body) body = case body do {:__block__, _, _ } -> @@ -85,7 +86,7 @@ defmodule ElixirScript.Preprocess.Modules do mod = %ElixirScript.Module{ name: module_name_list, body: body, functions: functions, macros: macros, aliases: aliases, requires: requires.requires, - imports: imports.imports } + imports: imports.imports, js_imports: js_imports } State.add_module(mod) @@ -137,6 +138,7 @@ defmodule ElixirScript.Preprocess.Modules do aliases = get_aliases_from_module(body2) requires = get_requires_from_module(body2) imports = get_imports_from_module(body2) + js_imports = get_js_imports_from_module(body2) inner_alias = {:alias, [], [{:__aliases__, [alias: false], module_name_list ++ module_name_list2}]} {inner_alias_atom, _ } = Code.eval_quoted({:__aliases__, [alias: false], module_name_list ++ module_name_list2}) @@ -146,7 +148,7 @@ defmodule ElixirScript.Preprocess.Modules do mod = %ElixirScript.Module{ name: module_name_list2, body: body2, functions: functions, macros: macros, aliases: aliases, - requires: requires.requires, imports: imports.imports } + requires: requires.requires, imports: imports.imports, js_imports: js_imports } if State.module_listed?(module_name_list2) do State.delete_module(mod) @@ -289,4 +291,21 @@ defmodule ElixirScript.Preprocess.Modules do defp get_imports_from_module(_) do %{ imports: HashSet.new, aliases: HashSet.new } end + + + defp get_js_imports_from_module({:__block__, _, list}) do + Enum.reduce(list, HashSet.new, fn + ({{:., _, [{:__aliases__, _, [:JS]}, :import]}, _, [name, path]}, state) -> + {name, _} = Code.eval_quoted(name) + Set.put(state, {name, path}) + + _, state -> + state + end) + end + + + defp get_js_imports_from_module(_) do + HashSet.new + end end From 08ebbd82c3d7d9dde84ef3890552a38ad1668c73 Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Wed, 25 Nov 2015 11:23:15 -0600 Subject: [PATCH 052/860] Structs are now matched on types Structs are also matched on their properties still when needed Tuples are matched on their type now as well --- lib/elixir_script/module.ex | 22 +++ lib/elixir_script/pattern_matching/match.ex | 35 +++- lib/elixir_script/translator.ex | 2 +- lib/elixir_script/translator/primitive.ex | 9 +- lib/elixir_script/translator/struct.ex | 33 +++- test/elixir_script_test.exs | 37 ++-- test/pattern_matching/match_test.exs | 107 ++++++----- test/translator/assignment_test.exs | 22 ++- test/translator/case_test.exs | 111 ++++++----- test/translator/defmodule_test.exs | 202 +++++++++++--------- test/translator/for_test.exs | 23 +-- test/translator/function_test.exs | 90 ++++----- test/translator/struct_test.exs | 84 +++++--- test/translator/try_test.exs | 88 ++++----- 14 files changed, 509 insertions(+), 356 deletions(-) diff --git a/lib/elixir_script/module.ex b/lib/elixir_script/module.ex index 7f0f1a3f..a25f0d49 100644 --- a/lib/elixir_script/module.ex +++ b/lib/elixir_script/module.ex @@ -24,10 +24,32 @@ defmodule ElixirScript.Module do module.imports end + def has_alias?(module, {:__aliases__, _, _} = ast) do + { name, _ } = Code.eval_quoted(ast) + has_alias?(module, name) + end + def has_alias?(module, name) do List.keymember?(Set.to_list(module.aliases), name, 0) end + def get_alias(nil, _) do + nil + end + + def get_alias(module, name) when is_list(name) do + name = {:__aliases__, [], name } + get_alias(module, name) + end + + def get_alias(module, {:__aliases__, _, _} = ast) do + { name, _ } = Code.eval_quoted(ast) + + Enum.find(module.aliases, fn({the_alias, _}) -> + name == the_alias + end) + end + def imported?(module, function_name) do imports = Enum.find(module.imports, fn({_, functions}) -> Enum.member?(functions, function_name) diff --git a/lib/elixir_script/pattern_matching/match.ex b/lib/elixir_script/pattern_matching/match.ex index 4f2e335c..0749c489 100644 --- a/lib/elixir_script/pattern_matching/match.ex +++ b/lib/elixir_script/pattern_matching/match.ex @@ -6,6 +6,7 @@ defmodule ElixirScript.PatternMatching.Match do alias ElixirScript.Translator.Primitive alias ElixirScript.Translator.Utils alias ElixirScript.Translator.Map + alias ElixirScript.Translator.Struct @wildcard JS.member_expression( JS.identifier("Elixir"), @@ -55,6 +56,14 @@ defmodule ElixirScript.PatternMatching.Match do ) ) + @_type JS.member_expression( + JS.identifier("Elixir"), + JS.member_expression( + JS.identifier(:Patterns), + JS.identifier(:type) + ) + ) + def wildcard() do JS.call_expression( @wildcard, @@ -97,6 +106,13 @@ defmodule ElixirScript.PatternMatching.Match do ) end + def type(prototype, value) do + JS.call_expression( + @_type, + [prototype, value] + ) + end + def build_match(params, env) do Enum.map(params, &do_build_match(&1, env)) |> reduce_patterns @@ -106,7 +122,7 @@ defmodule ElixirScript.PatternMatching.Match do { [bound(Translator.translate(value, env))], [nil] } end - defp do_build_match({:_, _, _}, env) do + defp do_build_match({:_, _, _}, _) do { [wildcard()], [JS.identifier(:undefined)] } end @@ -132,8 +148,10 @@ defmodule ElixirScript.PatternMatching.Match do end defp do_build_match({:%, _, [{:__aliases__, _, name}, {:%{}, meta, props}]}, env) do - props = [{:__struct__ , List.last(name)}] ++ props - do_build_match({:%{}, meta, props}, env) + struct_name = Struct.get_struct_class(name, env) + {pattern, params} = do_build_match({:%{}, meta, props}, env) + + { [type(struct_name, pattern)], params } end defp do_build_match({:=, _, [{name, _, _}, right]}, env) when not name in [:%, :{}, :__aliases__, :^, :%{}] do @@ -165,10 +183,17 @@ defmodule ElixirScript.PatternMatching.Match do |> Enum.map(&build_match([&1], env)) |> reduce_patterns - {[Primitive.make_tuple_no_translate(patterns)], params} + pattern = JS.object_expression([ + JS.property( + JS.identifier("values"), + JS.array_expression(patterns) + ) + ]) + + { [type(Primitive.tuple_class, pattern)], params } end - defp do_build_match({name, _, _}, env) do + defp do_build_match({name, _, _}, _) do name = Utils.filter_name(name) { [parameter()], [JS.identifier(name)] } end diff --git a/lib/elixir_script/translator.ex b/lib/elixir_script/translator.ex index 040759df..4904d378 100644 --- a/lib/elixir_script/translator.ex +++ b/lib/elixir_script/translator.ex @@ -94,7 +94,7 @@ defmodule ElixirScript.Translator do defp do_translate({:%, _, [alias_info, data]}, env) do {_, _, name} = alias_info - Struct.make_struct(name, data, env) + Struct.new_struct(name, data, env) end defp do_translate({:%{}, _, [{:|, _, [map, data]}]}, env) do diff --git a/lib/elixir_script/translator/primitive.ex b/lib/elixir_script/translator/primitive.ex index ba895901..a45ccd67 100644 --- a/lib/elixir_script/translator/primitive.ex +++ b/lib/elixir_script/translator/primitive.ex @@ -15,6 +15,13 @@ defmodule ElixirScript.Translator.Primitive do ) end + def tuple_class() do + JS.member_expression( + JS.identifier("Elixir"), + JS.identifier("Tuple") + ) + end + def scheduler() do JS.member_expression( JS.identifier("self"), @@ -55,7 +62,7 @@ defmodule ElixirScript.Translator.Primitive do ) end - def make_list([{:|, _, [elem, list]} = ast], env) do + def make_list([{:|, _, [_, _]} = ast], env) do Translator.translate(ast, env) end diff --git a/lib/elixir_script/translator/struct.ex b/lib/elixir_script/translator/struct.ex index 139fc3e1..17a8c326 100644 --- a/lib/elixir_script/translator/struct.ex +++ b/lib/elixir_script/translator/struct.ex @@ -2,13 +2,40 @@ defmodule ElixirScript.Translator.Struct do @moduledoc false alias ESTree.Tools.Builder, as: JS alias ElixirScript.Translator + alias ElixirScript.Translator.Utils alias ElixirScript.Translator.Map - def make_struct(module_name, data, env) do - JS.call_expression( + def get_struct_class(module_name, env) do + current_module = ElixirScript.State.get_module(Process.get(:current_module)) + + name = List.last(module_name) + + the_alias = ElixirScript.Module.get_alias(current_module, module_name) + + if the_alias do + { _, name } = the_alias + + name = Atom.to_string(name) + |> String.split(".") + |> List.last + end + + if the_alias == nil && ElixirScript.State.get_module(module_name) == nil do + Utils.make_module_expression_tree(module_name, false, env) + else JS.member_expression( JS.identifier(List.last(module_name)), - JS.identifier(:defstruct) + JS.identifier(name) + ) + end + + end + + def new_struct(module_name, data, env) do + JS.call_expression( + JS.member_expression( + get_struct_class(module_name, env), + JS.identifier(:create) ), [Translator.translate(data, env)] ) diff --git a/test/elixir_script_test.exs b/test/elixir_script_test.exs index e1277059..c554e5f2 100644 --- a/test/elixir_script_test.exs +++ b/test/elixir_script_test.exs @@ -67,29 +67,26 @@ defmodule ElixirScript.Test do """, env: make_custom_env) assert_js_matches """ - import * as Elixir from 'elixir'; - import * as Elephant from 'animals/elephant'; - - const __MODULE__ = Elixir.Kernel.SpecialForms.atom('Animals'); - const something = Elixir.Patterns.defmatch(Elixir.Patterns.make_case([],function() { - return Elephant.defstruct(Elixir.Kernel.SpecialForms.map({})); - })); - export { - something - }; + import * as Elixir from 'elixir'; + import * as Elephant from 'animals/elephant'; + const __MODULE__ = Elixir.Kernel.SpecialForms.atom('Animals.Elephant'); + const defstruct = Elixir.Kernel.defstruct({ + [Elixir.Kernel.SpecialForms.atom('__struct__')]: __MODULE__, [Elixir.Kernel.SpecialForms.atom('trunk')]: true + }); + export { + Elephant: defstruct + }; """, hd(js_code) assert_js_matches """ - import * as Elixir from 'elixir'; - const __MODULE__ = Elixir.Kernel.SpecialForms.atom('Animals.Elephant'); - function defstruct(values = {}) { - return Elixir.Kernel.defstruct({ - [Elixir.Kernel.SpecialForms.atom('__struct__')]: __MODULE__, [Elixir.Kernel.SpecialForms.atom('trunk')]: true - },values); - } - export { - defstruct - }; + import * as Elixir from 'elixir'; + const __MODULE__ = Elixir.Kernel.SpecialForms.atom('Elephant'); + const defstruct = Elixir.Kernel.defstruct({ + [Elixir.Kernel.SpecialForms.atom('__struct__')]: __MODULE__, [Elixir.Kernel.SpecialForms.atom('trunk')]: true + }); + export { + Elephant: defstruct + }; """, Enum.fetch!(js_code, 1) end diff --git a/test/pattern_matching/match_test.exs b/test/pattern_matching/match_test.exs index 96aded7e..3ae2cbdb 100644 --- a/test/pattern_matching/match_test.exs +++ b/test/pattern_matching/match_test.exs @@ -25,8 +25,8 @@ defmodule ElixirScript.PatternMatching.Match.Test do should "match multiple identifier params" do params = [{:a, [], Test}, {:b, [], Test}, {:c, [], Test}] result = Match.build_match(params, __ENV__) - expected_result = { - List.duplicate(Match.parameter, 3), + expected_result = { + List.duplicate(Match.parameter, 3), [JS.identifier("a"), JS.identifier("b"), JS.identifier("c")] } @@ -36,8 +36,8 @@ defmodule ElixirScript.PatternMatching.Match.Test do should "match head and tail param" do params = [[{:|, [], [{:head, [], Elixir}, {:tail, [], Elixir}]}]] result = Match.build_match(params, __ENV__) - expected_result = { - [Match.head_tail], + expected_result = { + [Match.head_tail], [JS.identifier("head"), JS.identifier("tail")] } @@ -47,8 +47,8 @@ defmodule ElixirScript.PatternMatching.Match.Test do should "match prefix param" do params = [{:<>, [context: Elixir, import: Elixir.Kernel], ["Bearer ", {:token, [], Elixir}]}] result = Match.build_match(params, __ENV__) - expected_result = { - [Match.starts_with("Bearer ")], + expected_result = { + [Match.starts_with("Bearer ")], [JS.identifier("token")] } @@ -58,8 +58,8 @@ defmodule ElixirScript.PatternMatching.Match.Test do should "match list" do params = [[{:a, [], Elixir}, {:b, [], Elixir}, {:c, [], Elixir}]] result = Match.build_match(params, __ENV__) - expected_result = { - [Primitive.make_list_no_translate(List.duplicate(Match.parameter, 3))], + expected_result = { + [Primitive.make_list_no_translate(List.duplicate(Match.parameter, 3))], [JS.identifier("a"), JS.identifier("b"), JS.identifier("c")] } @@ -69,8 +69,8 @@ defmodule ElixirScript.PatternMatching.Match.Test do should "match list with a literal" do params = [[1, {:b, [], Elixir}, {:c, [], Elixir}]] result = Match.build_match(params, __ENV__) - expected_result = { - [Primitive.make_list_no_translate([JS.literal(1), Match.parameter, Match.parameter])], + expected_result = { + [Primitive.make_list_no_translate([JS.literal(1), Match.parameter, Match.parameter])], [JS.identifier("b"), JS.identifier("c")] } @@ -80,8 +80,8 @@ defmodule ElixirScript.PatternMatching.Match.Test do should "match number" do params = [1] result = Match.build_match(params, __ENV__) - expected_result = { - [JS.literal(1)], + expected_result = { + [JS.literal(1)], [] } @@ -89,51 +89,64 @@ defmodule ElixirScript.PatternMatching.Match.Test do end should "match struct pattern" do + ElixirScript.State.start_link(nil, nil) + params = [{:%, [], [{:__aliases__, [alias: false], [:Hello]}, {:%{}, [], []}]}] result = Match.build_match(params, __ENV__) - expected_result = { - [JS.object_expression([ - Map.make_property(Translator.translate(:__struct__, __ENV__), Translator.translate(:Hello, __ENV__)) - ])], + expected_result = { + [Match.type(JS.identifier(:Hello), JS.object_expression([]))], [] } assert result == expected_result + + ElixirScript.State.stop() end should "match struct pattern with property" do + ElixirScript.State.start_link(nil, nil) + params = [{:%, [], [{:__aliases__, [alias: false], [:Hello]}, {:%{}, [], [key: 1]}]}] result = Match.build_match(params, __ENV__) - expected_result = { - [JS.object_expression([ - Map.make_property(Translator.translate(:__struct__, __ENV__), Translator.translate(:Hello, __ENV__)), - Map.make_property(Translator.translate(:key, __ENV__), Translator.translate(1, __ENV__)) - ])], + expected_result = { + [Match.type(JS.identifier(:Hello), JS.object_expression([ + Map.make_property(Translator.translate(:key, __ENV__), Translator.translate(1, __ENV__)) + ])) + ], [] } assert result == expected_result + + ElixirScript.State.stop() end should "match struct pattern with property param" do + ElixirScript.State.start_link(nil, nil) + params = [{:%, [], [{:__aliases__, [alias: false], [:Hello]}, {:%{}, [], [key: {:key, [], Elixir }]}]}] result = Match.build_match(params, __ENV__) - expected_result = { - [JS.object_expression([ - Map.make_property(Translator.translate(:__struct__, __ENV__), Translator.translate(:Hello, __ENV__)), - Map.make_property(Translator.translate(:key, __ENV__), Match.parameter) - ])], + expected_result = { + [Match.type(JS.identifier(:Hello), JS.object_expression([ + Map.make_property(Translator.translate(:key, __ENV__), Match.parameter) + ])) + ], [JS.identifier("key")] } assert result == expected_result + + ElixirScript.State.stop() + end should "capture parameter when assigning it" do + ElixirScript.State.start_link(nil, nil) + params = [{:=, [], [1, {:a, [], Elixir}]}] result = Match.build_match(params, __ENV__) - expected_result = { - [Match.capture(JS.literal(1))], + expected_result = { + [Match.capture(JS.literal(1))], [JS.identifier("a")] } @@ -142,8 +155,8 @@ defmodule ElixirScript.PatternMatching.Match.Test do params = [{:=, [], [{:a, [], Elixir}, 1]}] result = Match.build_match(params, __ENV__) - expected_result = { - [Match.capture(JS.literal(1))], + expected_result = { + [Match.capture(JS.literal(1))], [JS.identifier("a")] } @@ -152,21 +165,21 @@ defmodule ElixirScript.PatternMatching.Match.Test do params = [{:=, [], [{:%, [], [{:__aliases__, [alias: false], [:AStruct]}, {:%{}, [], []}]}, {:a, [], ElixirScript.Translator.Function.Test}]}] result = Match.build_match(params, __ENV__) - expected_result = { - [Match.capture(JS.object_expression([ - Map.make_property(Translator.translate(:__struct__, __ENV__), Translator.translate(:AStruct, __ENV__)), - ]))], + expected_result = { + [Match.capture(Match.type(JS.identifier(:AStruct), JS.object_expression([])))], [JS.identifier("a")] } - assert result == expected_result + assert result == expected_result + + ElixirScript.State.stop() end should "match and assign list" do params = [{:=, [], [[{:a, [], Elixir}, {:b, [], Elixir}, {:c, [], Elixir}], {:d, [], Elixir}]}] result = Match.build_match(params, __ENV__) - expected_result = { - [Match.capture(Primitive.make_list_no_translate([Match.parameter, Match.parameter, Match.parameter]))], + expected_result = { + [Match.capture(Primitive.make_list_no_translate([Match.parameter, Match.parameter, Match.parameter]))], [JS.identifier("a"), JS.identifier("b"), JS.identifier("c"), JS.identifier("d")] } @@ -176,8 +189,11 @@ defmodule ElixirScript.PatternMatching.Match.Test do should "match on tuple" do params = [{:{}, [], [1, {:b, [], Elixir}, 3]}] result = Match.build_match(params, __ENV__) - expected_result = { - [Primitive.make_tuple_no_translate([JS.literal(1), Match.parameter, JS.literal(3)])], + expected_result = { + [Match.type(Primitive.tuple_class, JS.object_expression([JS.property( + JS.identifier("values"), + JS.array_expression([JS.literal(1), Match.parameter, JS.literal(3)]) + ) ] )) ], [JS.identifier("b")] } @@ -185,8 +201,11 @@ defmodule ElixirScript.PatternMatching.Match.Test do params = [{1, {:b, [], Elixir}}] result = Match.build_match(params, __ENV__) - expected_result = { - [Primitive.make_tuple_no_translate([JS.literal(1), Match.parameter])], + expected_result = { + [Match.type(Primitive.tuple_class, JS.object_expression([JS.property( + JS.identifier("values"), + JS.array_expression([JS.literal(1), Match.parameter]) + ) ] )) ], [JS.identifier("b")] } @@ -197,7 +216,7 @@ defmodule ElixirScript.PatternMatching.Match.Test do params = [{:%{}, [], [which: 13]}] result = Match.build_match(params, __ENV__) - expected_result = { + expected_result = { [JS.object_expression([ Map.make_property(Translator.translate(:which, __ENV__), JS.literal(13)) ])], @@ -212,7 +231,7 @@ defmodule ElixirScript.PatternMatching.Match.Test do params = [{:^, [], [{:a, [], Elixir}]}] result = Match.build_match(params, __ENV__) - expected_result = { + expected_result = { [Match.bound(JS.identifier("a"))], [nil] } @@ -220,4 +239,4 @@ defmodule ElixirScript.PatternMatching.Match.Test do assert result == expected_result end -end \ No newline at end of file +end diff --git a/test/translator/assignment_test.exs b/test/translator/assignment_test.exs index b20d059c..375285ef 100644 --- a/test/translator/assignment_test.exs +++ b/test/translator/assignment_test.exs @@ -19,16 +19,20 @@ defmodule ElixirScript.Translator.Assignment.Test do {a, b} = {1, 2} end js_code = """ - let [a, b] = Elixir.Patterns.match(Elixir.Kernel.SpecialForms.tuple(Elixir.Patterns.variable(), Elixir.Patterns.variable()), Elixir.Kernel.SpecialForms.tuple(1, 2)); - let _ref = Elixir.Kernel.SpecialForms.tuple(a, b); + let [a, b] = Elixir.Patterns.match(Elixir.Patterns.type(Elixir.Tuple, { + values: [Elixir.Patterns.variable(), Elixir.Patterns.variable()] + }), Elixir.Kernel.SpecialForms.tuple(1, 2)); + let _ref = Elixir.Kernel.SpecialForms.tuple(a, b); """ assert_translation(ex_ast, js_code) ex_ast = quote do: {a, _, c} = {1, 2, 3} js_code = """ - let [a, undefined, c] = Elixir.Patterns.match(Elixir.Kernel.SpecialForms.tuple(Elixir.Patterns.variable(), Elixir.Patterns.wildcard(), Elixir.Patterns.variable()), Elixir.Kernel.SpecialForms.tuple(1, 2, 3)); - let _ref = Elixir.Kernel.SpecialForms.tuple(a, undefined, c); + let [a, undefined, c] = Elixir.Patterns.match(Elixir.Patterns.type(Elixir.Tuple, { + values: [Elixir.Patterns.variable(), Elixir.Patterns.wildcard(), Elixir.Patterns.variable()] + }), Elixir.Kernel.SpecialForms.tuple(1, 2, 3)); + let _ref = Elixir.Kernel.SpecialForms.tuple(a, undefined, c); """ assert_translation(ex_ast, js_code) @@ -36,8 +40,10 @@ defmodule ElixirScript.Translator.Assignment.Test do ex_ast = quote do: {^a, _, c} = {1, 2, 3} js_code = """ - let [,undefined,c] = Elixir.Patterns.match(Elixir.Kernel.SpecialForms.tuple(Elixir.Patterns.bound(a),Elixir.Patterns.wildcard(),Elixir.Patterns.variable()),Elixir.Kernel.SpecialForms.tuple(1,2,3)); - let _ref = Elixir.Kernel.SpecialForms.tuple(undefined,undefined,c); + let [, undefined, c] = Elixir.Patterns.match(Elixir.Patterns.type(Elixir.Tuple, { + values: [Elixir.Patterns.bound(a), Elixir.Patterns.wildcard(), Elixir.Patterns.variable()] + }), Elixir.Kernel.SpecialForms.tuple(1, 2, 3)); + let _ref = Elixir.Kernel.SpecialForms.tuple(undefined, undefined, c); """ assert_translation(ex_ast, js_code) @@ -45,7 +51,7 @@ defmodule ElixirScript.Translator.Assignment.Test do should "translate bound assignment" do ex_ast = quote do: ^a = 1 - js_code = """ + js_code = """ let [] = Elixir.Patterns.match(Elixir.Patterns.bound(a),1); """ @@ -71,4 +77,4 @@ defmodule ElixirScript.Translator.Assignment.Test do assert_translation(ex_ast, js_code) end -end \ No newline at end of file +end diff --git a/test/translator/case_test.exs b/test/translator/case_test.exs index 3169d903..fdc533b9 100644 --- a/test/translator/case_test.exs +++ b/test/translator/case_test.exs @@ -63,9 +63,9 @@ defmodule ElixirScript.Translator.Case.Test do should "translate case with guard" do ex_ast = quote do case data do - number when number in [1,2,3,4] -> + number when number in [1,2,3,4] -> value = 13 - _ -> + _ -> true end end @@ -87,10 +87,10 @@ defmodule ElixirScript.Translator.Case.Test do should "translate case with multiple statements in body" do ex_ast = quote do case data do - :ok -> + :ok -> Logger.info("info") Todo.add(data) - :error -> + :error -> nil end end @@ -110,19 +110,21 @@ defmodule ElixirScript.Translator.Case.Test do should "translate case with destructing" do ex_ast = quote do case data do - { one, two } -> + { one, two } -> Logger.info(one) - :error -> + :error -> nil end end js_code = """ - Elixir.Patterns.defmatch(Elixir.Patterns.make_case([Elixir.Kernel.SpecialForms.tuple(Elixir.Patterns.variable(),Elixir.Patterns.variable())],function(one,two) { - return console.info(one); - }),Elixir.Patterns.make_case([Elixir.Kernel.SpecialForms.atom('error')],function() { - return null; - })).call(this,data) + Elixir.Patterns.defmatch(Elixir.Patterns.make_case([Elixir.Patterns.type(Elixir.Tuple, { + values: [Elixir.Patterns.variable(), Elixir.Patterns.variable()] + })], function(one, two) { + return console.info(one); + }), Elixir.Patterns.make_case([Elixir.Kernel.SpecialForms.atom('error')], function() { + return null; + })).call(this, data) """ assert_translation(ex_ast, js_code) @@ -131,39 +133,46 @@ defmodule ElixirScript.Translator.Case.Test do should "translate case with nested destructing" do ex_ast = quote do case data do - { {one, two} , three } -> + { {one, two} , three } -> Logger.info(one) - :error -> + :error -> nil end end js_code = """ - Elixir.Patterns.defmatch(Elixir.Patterns.make_case([Elixir.Kernel.SpecialForms.tuple(Elixir.Kernel.SpecialForms.tuple(Elixir.Patterns.variable(),Elixir.Patterns.variable()),Elixir.Patterns.variable())],function(one,two,three) { - return console.info(one); - }),Elixir.Patterns.make_case([Elixir.Kernel.SpecialForms.atom('error')],function() { - return null; - })).call(this,data) + Elixir.Patterns.defmatch(Elixir.Patterns.make_case([Elixir.Patterns.type(Elixir.Tuple, { + values: [Elixir.Patterns.type(Elixir.Tuple, { + values: [Elixir.Patterns.variable(), Elixir.Patterns.variable()] + }), Elixir.Patterns.variable()] + })], function(one, two, three) { + return console.info(one); + }), Elixir.Patterns.make_case([Elixir.Kernel.SpecialForms.atom('error')], function() { + return null; + })).call(this, data) """ assert_translation(ex_ast, js_code) ex_ast = quote do case data do - { one, {two, three} } -> + { one, {two, three} } -> Logger.info(one) - :error -> + :error -> nil end end js_code = """ - Elixir.Patterns.defmatch(Elixir.Patterns.make_case([Elixir.Kernel.SpecialForms.tuple(Elixir.Patterns.variable(),Elixir.Kernel.SpecialForms.tuple(Elixir.Patterns.variable(),Elixir.Patterns.variable()))],function(one,two,three) { - return console.info(one); - }),Elixir.Patterns.make_case([Elixir.Kernel.SpecialForms.atom('error')],function() { - return null; - })).call(this,data) - + Elixir.Patterns.defmatch(Elixir.Patterns.make_case([Elixir.Patterns.type(Elixir.Tuple, { + values: [Elixir.Patterns.variable(), Elixir.Patterns.type(Elixir.Tuple, { + values: [Elixir.Patterns.variable(), Elixir.Patterns.variable()] + })] + })], function(one, two, three) { + return console.info(one); + }), Elixir.Patterns.make_case([Elixir.Kernel.SpecialForms.atom('error')], function() { + return null; + })).call(this, data) """ assert_translation(ex_ast, js_code) @@ -171,23 +180,23 @@ defmodule ElixirScript.Translator.Case.Test do ex_ast = quote do case data do - %AStruct{key: %BStruct{ key2: value }} -> + %AStruct{key: %BStruct{ key2: value }} -> Logger.info(value) - :error -> + :error -> nil end end js_code = """ - Elixir.Patterns.defmatch(Elixir.Patterns.make_case([{ - [Elixir.Kernel.SpecialForms.atom('__struct__')]: Elixir.Kernel.SpecialForms.atom('AStruct'), [Elixir.Kernel.SpecialForms.atom('key')]: { - [Elixir.Kernel.SpecialForms.atom('__struct__')]: Elixir.Kernel.SpecialForms.atom('BStruct'), [Elixir.Kernel.SpecialForms.atom('key2')]: Elixir.Patterns.variable() - } - }],function(value) { - return console.info(value); - }),Elixir.Patterns.make_case([Elixir.Kernel.SpecialForms.atom('error')],function() { - return null; - })).call(this,data) + Elixir.Patterns.defmatch(Elixir.Patterns.make_case([Elixir.Patterns.type(AStruct, { + [Elixir.Kernel.SpecialForms.atom('key')]: Elixir.Patterns.type(BStruct, { + [Elixir.Kernel.SpecialForms.atom('key2')]: Elixir.Patterns.variable() + }) + })], function(value) { + return console.info(value); + }), Elixir.Patterns.make_case([Elixir.Kernel.SpecialForms.atom('error')], function() { + return null; + })).call(this, data) """ assert_translation(ex_ast, js_code) @@ -195,27 +204,27 @@ defmodule ElixirScript.Translator.Case.Test do ex_ast = quote do case data do - %AStruct{key: %BStruct{ key2: value, key3: %CStruct{ key4: value2 } }} -> + %AStruct{key: %BStruct{ key2: value, key3: %CStruct{ key4: value2 } }} -> Logger.info(value) - :error -> + :error -> nil end end js_code = """ - Elixir.Patterns.defmatch(Elixir.Patterns.make_case([{ - [Elixir.Kernel.SpecialForms.atom('__struct__')]: Elixir.Kernel.SpecialForms.atom('AStruct'), [Elixir.Kernel.SpecialForms.atom('key')]: { - [Elixir.Kernel.SpecialForms.atom('__struct__')]: Elixir.Kernel.SpecialForms.atom('BStruct'), [Elixir.Kernel.SpecialForms.atom('key2')]: Elixir.Patterns.variable(), [Elixir.Kernel.SpecialForms.atom('key3')]: { - [Elixir.Kernel.SpecialForms.atom('__struct__')]: Elixir.Kernel.SpecialForms.atom('CStruct'), [Elixir.Kernel.SpecialForms.atom('key4')]: Elixir.Patterns.variable() - } - } - }],function(value,value2) { - return console.info(value); - }),Elixir.Patterns.make_case([Elixir.Kernel.SpecialForms.atom('error')],function() { - return null; - })).call(this,data) + Elixir.Patterns.defmatch(Elixir.Patterns.make_case([Elixir.Patterns.type(AStruct, { + [Elixir.Kernel.SpecialForms.atom('key')]: Elixir.Patterns.type(BStruct, { + [Elixir.Kernel.SpecialForms.atom('key2')]: Elixir.Patterns.variable(), [Elixir.Kernel.SpecialForms.atom('key3')]: Elixir.Patterns.type(CStruct, { + [Elixir.Kernel.SpecialForms.atom('key4')]: Elixir.Patterns.variable() + }) + }) + })], function(value, value2) { + return console.info(value); + }), Elixir.Patterns.make_case([Elixir.Kernel.SpecialForms.atom('error')], function() { + return null; + })).call(this, data) """ assert_translation(ex_ast, js_code) end -end \ No newline at end of file +end diff --git a/test/translator/defmodule_test.exs b/test/translator/defmodule_test.exs index dfe2368d..6b6ee4a2 100644 --- a/test/translator/defmodule_test.exs +++ b/test/translator/defmodule_test.exs @@ -95,28 +95,34 @@ defmodule ElixirScript.Translator.Defmodule.Test do end js_code = """ - const __MODULE__ = Elixir.Kernel.SpecialForms.atom('Animals.Elephant'); - function defstruct(values = {}) { - return Elixir.Kernel.defstruct({ - [Elixir.Kernel.SpecialForms.atom('__struct__')]: __MODULE__, [Elixir.Kernel.SpecialForms.atom('trunk')]: true - },values); - } - export { - defstruct - }; - - import * as Elephant from 'animals/elephant'; - const __MODULE__ = Elixir.Kernel.SpecialForms.atom('Animals'); - const something_else = Elixir.Patterns.defmatch(Elixir.Patterns.make_case([],function() { - return null; - })); - const something = Elixir.Patterns.defmatch(Elixir.Patterns.make_case([],function() { - return Elephant.defstruct(Elixir.Kernel.SpecialForms.map({})); - })); - export { - something - }; - + const __MODULE__ = Elixir.Kernel.SpecialForms.atom('Elephant'); + const defstruct = Elixir.Kernel.defstruct({ + [Elixir.Kernel.SpecialForms.atom('__struct__')]: __MODULE__, [Elixir.Kernel.SpecialForms.atom('trunk')]: true + }); + export { + Elephant: defstruct + }; + + import * as Elephant from 'animals/elephant'; + const __MODULE__ = Elixir.Kernel.SpecialForms.atom('Animals'); + const something_else = Elixir.Patterns.defmatch(Elixir.Patterns.make_case([], function() { + return null; + })); + const something = Elixir.Patterns.defmatch(Elixir.Patterns.make_case([], function() { + return Elephant.Elephant.create(Elixir.Kernel.SpecialForms.map({})); + })); + export { + something + }; + + import * as Elephant from 'animals/elephant'; + const __MODULE__ = Elixir.Kernel.SpecialForms.atom('Animals.Elephant'); + const defstruct = Elixir.Kernel.defstruct({ + [Elixir.Kernel.SpecialForms.atom('__struct__')]: __MODULE__, [Elixir.Kernel.SpecialForms.atom('trunk')]: true + }); + export { + Elephant: defstruct + }; """ assert_translation(ex_ast, js_code) @@ -147,38 +153,53 @@ defmodule ElixirScript.Translator.Defmodule.Test do end js_code = """ - const __MODULE__ = Elixir.Kernel.SpecialForms.atom('Elephant.Bear'); - function defstruct(values = {}) { - return Elixir.Kernel.defstruct({ - [Elixir.Kernel.SpecialForms.atom('__struct__')]: __MODULE__, [Elixir.Kernel.SpecialForms.atom('trunk')]: true - },values); - } - export { - defstruct - }; - - import * as Bear from 'elephant/bear'; - const __MODULE__ = Elixir.Kernel.SpecialForms.atom('Animals.Elephant'); - function defstruct(values = {}) { - return Elixir.Kernel.defstruct({ - [Elixir.Kernel.SpecialForms.atom('__struct__')]: __MODULE__, [Elixir.Kernel.SpecialForms.atom('trunk')]: true - },values); - } - export { - defstruct - }; - - import * as Elephant from 'animals/elephant'; - const __MODULE__ = Elixir.Kernel.SpecialForms.atom('Animals'); - const something_else = Elixir.Patterns.defmatch(Elixir.Patterns.make_case([],function() { - return null; - })); - const something = Elixir.Patterns.defmatch(Elixir.Patterns.make_case([],function() { - return Elephant.defstruct(Elixir.Kernel.SpecialForms.map({})); - })); - export { - something - }; + import * as Bear from 'elephant/bear'; + const __MODULE__ = Elixir.Kernel.SpecialForms.atom('Elephant.Bear'); + const defstruct = Elixir.Kernel.defstruct({ + [Elixir.Kernel.SpecialForms.atom('__struct__')]: __MODULE__, [Elixir.Kernel.SpecialForms.atom('trunk')]: true + }); + export { + Bear: defstruct + }; + + import * as Bear from 'elephant/bear'; + import * as Elephant from 'animals/elephant'; + const __MODULE__ = Elixir.Kernel.SpecialForms.atom('Animals.Elephant'); + const defstruct = Elixir.Kernel.defstruct({ + [Elixir.Kernel.SpecialForms.atom('__struct__')]: __MODULE__, [Elixir.Kernel.SpecialForms.atom('trunk')]: true + }); + export { + Elephant: defstruct + }; + + import * as Elephant from 'animals/elephant'; + const __MODULE__ = Elixir.Kernel.SpecialForms.atom('Animals'); + const something_else = Elixir.Patterns.defmatch(Elixir.Patterns.make_case([], function() { + return null; + })); + const something = Elixir.Patterns.defmatch(Elixir.Patterns.make_case([], function() { + return Elephant.Elephant.create(Elixir.Kernel.SpecialForms.map({})); + })); + export { + something + }; + + const __MODULE__ = Elixir.Kernel.SpecialForms.atom('Bear'); + const defstruct = Elixir.Kernel.defstruct({ + [Elixir.Kernel.SpecialForms.atom('__struct__')]: __MODULE__, [Elixir.Kernel.SpecialForms.atom('trunk')]: true + }); + export { + Bear: defstruct + }; + + import * as Bear from 'elephant/bear'; + const __MODULE__ = Elixir.Kernel.SpecialForms.atom('Elephant'); + const defstruct = Elixir.Kernel.defstruct({ + [Elixir.Kernel.SpecialForms.atom('__struct__')]: __MODULE__, [Elixir.Kernel.SpecialForms.atom('trunk')]: true + }); + export { + Elephant: defstruct + }; """ assert_translation(ex_ast, js_code) @@ -193,7 +214,7 @@ defmodule ElixirScript.Translator.Defmodule.Test do defmodule Lions.Tigers do Lions.Tigers.Bears.oh_my() end - end + end js_code = """ import * as Tigers from 'lions/tigers'; @@ -223,7 +244,7 @@ defmodule ElixirScript.Translator.Defmodule.Test do def oh_my() do end end - end + end js_code = """ const __MODULE__ = Elixir.Kernel.SpecialForms.atom('Lions.Tigers'); @@ -259,24 +280,27 @@ defmodule ElixirScript.Translator.Defmodule.Test do oh_my() end - end + end js_code = """ - import { oh_my } from 'lions/tigers'; - const __MODULE__ = Elixir.Kernel.SpecialForms.atom('Animals'); - oh_my(); - export {}; + import * as Tigers from 'lions/tigers'; + const __MODULE__ = Elixir.Kernel.SpecialForms.atom('Animals'); + Tigers.oh_my(); + export {}; - const __MODULE__ = Elixir.Kernel.SpecialForms.atom('Lions.Tigers'); - const oh_my2 = Elixir.Patterns.defmatch(Elixir.Patterns.make_case([],function() { - return null; - })); - const oh_my = Elixir.Patterns.defmatch(Elixir.Patterns.make_case([],function() { - return null; - })); - export { - oh_my2, oh_my - }; + + + const __MODULE__ = Elixir.Kernel.SpecialForms.atom('Lions.Tigers'); + const oh_my2 = Elixir.Patterns.defmatch(Elixir.Patterns.make_case([], function() { + return null; + })); + const oh_my = Elixir.Patterns.defmatch(Elixir.Patterns.make_case([], function() { + return null; + })); + export { + oh_my2, + oh_my + }; """ assert_translation(ex_ast, js_code) @@ -297,24 +321,30 @@ defmodule ElixirScript.Translator.Defmodule.Test do oh_my2() end - end + end js_code = """ - const __MODULE__ = Elixir.Kernel.SpecialForms.atom('Lions.Tigers'); - const oh_my2 = Elixir.Patterns.defmatch(Elixir.Patterns.make_case([],function() { - return null; - })); - const oh_my = Elixir.Patterns.defmatch(Elixir.Patterns.make_case([],function() { - return null; - })); - export { - oh_my2, oh_my - }; + import * as Tigers from 'lions/tigers'; + const __MODULE__ = Elixir.Kernel.SpecialForms.atom('Animals'); + Tigers.oh_my2(); + export {}; - import { oh_my2 } from 'lions/tigers'; - const __MODULE__ = Elixir.Kernel.SpecialForms.atom('Animals'); - oh_my2(); - export {}; + + + const __MODULE__ = Elixir.Kernel.SpecialForms.atom('Lions.Tigers'); + + const oh_my2 = Elixir.Patterns.defmatch(Elixir.Patterns.make_case([], function() { + return null; + })); + + const oh_my = Elixir.Patterns.defmatch(Elixir.Patterns.make_case([], function() { + return null; + })); + + export { + oh_my2, + oh_my + }; """ assert_translation(ex_ast, js_code) diff --git a/test/translator/for_test.exs b/test/translator/for_test.exs index 34f4551f..73f49d76 100644 --- a/test/translator/for_test.exs +++ b/test/translator/for_test.exs @@ -70,7 +70,7 @@ defmodule ElixirScript.Translator.For.Test do should "translate multiple generator for, assignment, and do block" do ex_ast = quote do - r = for x <- [1, 2], y <- [2, 3] do + r = for x <- [1, 2], y <- [2, 3] do x*y end end @@ -110,20 +110,15 @@ defmodule ElixirScript.Translator.For.Test do end js_code = """ - Elixir.Kernel.SpecialForms._for(Elixir.Kernel.SpecialForms.list( - Elixir.Kernel.SpecialForms.list( - Elixir.Kernel.SpecialForms.tuple(Elixir.Kernel.SpecialForms.atom('user'),Elixir.Patterns.variable()), - Elixir.Kernel.SpecialForms.list( - Elixir.Kernel.SpecialForms.tuple(Elixir.Kernel.SpecialForms.atom('user'),'john'), - Elixir.Kernel.SpecialForms.tuple(Elixir.Kernel.SpecialForms.atom('admin'),'john'), - Elixir.Kernel.SpecialForms.tuple(Elixir.Kernel.SpecialForms.atom('user'),'meg')))),function(name) { - return Elixir.String.upcase(name); - },function() { - return true; - },Elixir.Kernel.SpecialForms.list() - ) + Elixir.Kernel.SpecialForms._for(Elixir.Kernel.SpecialForms.list(Elixir.Kernel.SpecialForms.list(Elixir.Patterns.type(Elixir.Tuple,{ + values: [Elixir.Kernel.SpecialForms.atom('user'), Elixir.Patterns.variable()] + }),Elixir.Kernel.SpecialForms.list(Elixir.Kernel.SpecialForms.tuple(Elixir.Kernel.SpecialForms.atom('user'),'john'),Elixir.Kernel.SpecialForms.tuple(Elixir.Kernel.SpecialForms.atom('admin'),'john'),Elixir.Kernel.SpecialForms.tuple(Elixir.Kernel.SpecialForms.atom('user'),'meg')))),function(name) { + return Elixir.String.upcase(name); + },function() { + return true; + },Elixir.Kernel.SpecialForms.list()) """ assert_translation(ex_ast, js_code) end -end \ No newline at end of file +end diff --git a/test/translator/function_test.exs b/test/translator/function_test.exs index 60fccd24..2ce50f8a 100644 --- a/test/translator/function_test.exs +++ b/test/translator/function_test.exs @@ -11,7 +11,7 @@ defmodule ElixirScript.Translator.Function.Test do fun(Elixir.Kernel.SpecialForms.atom('atom')) """ - assert_translation(ex_ast, js_code) + assert_translation(ex_ast, js_code) end @@ -140,11 +140,13 @@ defmodule ElixirScript.Translator.Function.Test do end js_code = """ - const test1 = Elixir.Patterns.defmatch(Elixir.Patterns.make_case([Elixir.Patterns.variable(), Elixir.Patterns.variable()],function(alpha,beta) { - let [a0,b0] = Elixir.Patterns.match(Elixir.Kernel.SpecialForms.tuple(Elixir.Patterns.variable(),Elixir.Patterns.variable()),Elixir.Kernel.SpecialForms.tuple(1,2)); - let _ref = Elixir.Kernel.SpecialForms.tuple(a0,b0); - return _ref; - })); + const test1 = Elixir.Patterns.defmatch(Elixir.Patterns.make_case([Elixir.Patterns.variable(), Elixir.Patterns.variable()], function(alpha, beta) { + let [a0, b0] = Elixir.Patterns.match(Elixir.Patterns.type(Elixir.Tuple, { + values: [Elixir.Patterns.variable(), Elixir.Patterns.variable()] + }), Elixir.Kernel.SpecialForms.tuple(1, 2)); + let _ref = Elixir.Kernel.SpecialForms.tuple(a0, b0); + return _ref; + })); """ assert_translation(ex_ast, js_code) @@ -179,7 +181,7 @@ defmodule ElixirScript.Translator.Function.Test do Taco.test1() end - js_code = "Elixir.JS.call_property(Taco, 'test1')" + js_code = "Elixir.JS.call_property(Taco, 'test1')" assert_translation(ex_ast, js_code) @@ -187,7 +189,7 @@ defmodule ElixirScript.Translator.Function.Test do Taco.test1(3, 2) end - js_code = "Taco.test1(3,2)" + js_code = "Taco.test1(3,2)" assert_translation(ex_ast, js_code) @@ -195,7 +197,7 @@ defmodule ElixirScript.Translator.Function.Test do Taco.test1(Taco.test2(1), 2) end - js_code = "Taco.test1(Taco.test2(1),2)" + js_code = "Taco.test1(Taco.test2(1),2)" assert_translation(ex_ast, js_code) end @@ -234,7 +236,7 @@ defmodule ElixirScript.Translator.Function.Test do defp example(oneArg, twoArg, redArg, blueArg) do end end - end + end js_code = """ const __MODULE__ = Elixir.Kernel.SpecialForms.atom('Example'); @@ -250,7 +252,7 @@ defmodule ElixirScript.Translator.Function.Test do return null; })); export {}; - """ + """ assert_translation(ex_ast, js_code) @@ -271,7 +273,7 @@ defmodule ElixirScript.Translator.Function.Test do def example(oneArg, twoArg, redArg, blueArg) do end end - end + end js_code = """ const __MODULE__ = Elixir.Kernel.SpecialForms.atom('Example'); @@ -289,7 +291,7 @@ defmodule ElixirScript.Translator.Function.Test do export { example }; - """ + """ assert_translation(ex_ast, js_code) @@ -298,7 +300,7 @@ defmodule ElixirScript.Translator.Function.Test do def example(oneArg) do end end - end + end js_code = """ const __MODULE__ = Elixir.Kernel.SpecialForms.atom('Example'); @@ -308,7 +310,7 @@ defmodule ElixirScript.Translator.Function.Test do export { example }; - """ + """ assert_translation(ex_ast, js_code) end @@ -416,7 +418,7 @@ defmodule ElixirScript.Translator.Function.Test do def something(one) when is_number(one) or is_atom(one) do end end - end + end js_code = """ const __MODULE__ = Elixir.Kernel.SpecialForms.atom('Example'); @@ -432,7 +434,7 @@ defmodule ElixirScript.Translator.Function.Test do export { something }; - """ + """ assert_translation(ex_ast, js_code) end @@ -493,9 +495,11 @@ defmodule ElixirScript.Translator.Function.Test do js_code = """ - const something = Elixir.Patterns.defmatch(Elixir.Patterns.make_case([Elixir.Kernel.SpecialForms.tuple(Elixir.Patterns.variable(),Elixir.Patterns.variable())],function(apple,fruits) { - return null; - })); + const something = Elixir.Patterns.defmatch(Elixir.Patterns.make_case([Elixir.Patterns.type(Elixir.Tuple, { + values: [Elixir.Patterns.variable(), Elixir.Patterns.variable()] + })], function(apple, fruits) { + return null; + })); """ assert_translation(ex_ast, js_code) @@ -509,11 +513,9 @@ defmodule ElixirScript.Translator.Function.Test do js_code = """ - const something = Elixir.Patterns.defmatch(Elixir.Patterns.make_case([{ - [Elixir.Kernel.SpecialForms.atom('__struct__')]: Elixir.Kernel.SpecialForms.atom('AStruct') - }],function() { - return null; - })); + const something = Elixir.Patterns.defmatch(Elixir.Patterns.make_case([Elixir.Patterns.type(AStruct, {})], function() { + return null; + })); """ assert_translation(ex_ast, js_code) @@ -526,11 +528,9 @@ defmodule ElixirScript.Translator.Function.Test do end js_code = """ - const something = Elixir.Patterns.defmatch(Elixir.Patterns.make_case([Elixir.Patterns.capture({ - [Elixir.Kernel.SpecialForms.atom('__struct__')]: Elixir.Kernel.SpecialForms.atom('AStruct') - })],function(a) { - return null; - })); + const something = Elixir.Patterns.defmatch(Elixir.Patterns.make_case([Elixir.Patterns.capture(Elixir.Patterns.type(AStruct, {}))], function(a) { + return null; + })); """ assert_translation(ex_ast, js_code) end @@ -560,11 +560,11 @@ defmodule ElixirScript.Translator.Function.Test do js_code = """ - const something = Elixir.Patterns.defmatch(Elixir.Patterns.make_case([{ - [Elixir.Kernel.SpecialForms.atom('__struct__')]: Elixir.Kernel.SpecialForms.atom('AStruct'), [Elixir.Kernel.SpecialForms.atom('key')]: Elixir.Patterns.variable(), [Elixir.Kernel.SpecialForms.atom('key1')]: 2 - }],function(value) { - return null; - })); + const something = Elixir.Patterns.defmatch(Elixir.Patterns.make_case([Elixir.Patterns.type(AStruct, { + [Elixir.Kernel.SpecialForms.atom('key')]: Elixir.Patterns.variable(), [Elixir.Kernel.SpecialForms.atom('key1')]: 2 + })], function(value) { + return null; + })); """ assert_translation(ex_ast, js_code) @@ -576,13 +576,13 @@ defmodule ElixirScript.Translator.Function.Test do js_code = """ - const something = Elixir.Patterns.defmatch(Elixir.Patterns.make_case([{ - [Elixir.Kernel.SpecialForms.atom('__struct__')]: Elixir.Kernel.SpecialForms.atom('AStruct'), [Elixir.Kernel.SpecialForms.atom('key')]: Elixir.Patterns.variable(), [Elixir.Kernel.SpecialForms.atom('key1')]: 2 - }],function(value) { - return null; - },function(value) { - return Elixir.Kernel.is_number(value); - })); + const something = Elixir.Patterns.defmatch(Elixir.Patterns.make_case([Elixir.Patterns.type(AStruct, { + [Elixir.Kernel.SpecialForms.atom('key')]: Elixir.Patterns.variable(), [Elixir.Kernel.SpecialForms.atom('key1')]: 2 + })], function(value) { + return null; + }, function(value) { + return Elixir.Kernel.is_number(value); + })); """ assert_translation(ex_ast, js_code) @@ -645,7 +645,7 @@ defmodule ElixirScript.Translator.Function.Test do end def something(one) do - end + end end end @@ -668,7 +668,7 @@ defmodule ElixirScript.Translator.Function.Test do something }; """ - + assert_translation(ex_ast, js_code) end @@ -748,5 +748,5 @@ defmodule ElixirScript.Translator.Function.Test do assert_translation(ex_ast, js_code) end - + end diff --git a/test/translator/struct_test.exs b/test/translator/struct_test.exs index 266476b9..dfa0ceba 100644 --- a/test/translator/struct_test.exs +++ b/test/translator/struct_test.exs @@ -33,15 +33,16 @@ defmodule ElixirScript.Translator.Struct.Test do end js_code = """ - const __MODULE__ = Elixir.Kernel.SpecialForms.atom('User'); - function defstruct(values = {}) { - return Elixir.Kernel.defstruct({ - [Elixir.Kernel.SpecialForms.atom('__struct__')]: __MODULE__, [Elixir.Kernel.SpecialForms.atom('name')]: null, [Elixir.Kernel.SpecialForms.atom('age')]: null - },values); - } - export { - User: defstruct - }; + const __MODULE__ = Elixir.Kernel.SpecialForms.atom('User'); + const defstruct = Elixir.Kernel.defstruct({ + [Elixir.Kernel.SpecialForms.atom('__struct__')]: __MODULE__, + [Elixir.Kernel.SpecialForms.atom('name')]: null, + [Elixir.Kernel.SpecialForms.atom('age')]: null + }); + + export { + User: defstruct + }; """ assert_translation(ex_ast, js_code) @@ -50,20 +51,48 @@ defmodule ElixirScript.Translator.Struct.Test do should "translate struct creation" do ex_ast = quote do + defmodule User do + defstruct :name, :age + end + user = %User{} end js_code = """ - let [user] = Elixir.Patterns.match(Elixir.Patterns.variable(), User.User.create(Elixir.Kernel.SpecialForms.map({}))); + const __MODULE__ = Elixir.Kernel.SpecialForms.atom('User'); + const defstruct = Elixir.Kernel.defstruct({ + [Elixir.Kernel.SpecialForms.atom('__struct__')]: __MODULE__, + [Elixir.Kernel.SpecialForms.atom('name')]: null, + [Elixir.Kernel.SpecialForms.atom('age')]: null + }); + export { + User: defstruct + }; + + let [user] = Elixir.Patterns.match(Elixir.Patterns.variable(), User.User.create(Elixir.Kernel.SpecialForms.map({}))); """ assert_translation(ex_ast, js_code) ex_ast = quote do + defmodule User do + defstruct :name, :age + end + user = %User{name: "John"} end js_code = """ + const __MODULE__ = Elixir.Kernel.SpecialForms.atom('User'); + const defstruct = Elixir.Kernel.defstruct({ + [Elixir.Kernel.SpecialForms.atom('__struct__')]: __MODULE__, + [Elixir.Kernel.SpecialForms.atom('name')]: null, + [Elixir.Kernel.SpecialForms.atom('age')]: null + }); + export { + User: defstruct + }; + let [user] = Elixir.Patterns.match(Elixir.Patterns.variable(), User.User.create(Elixir.Kernel.SpecialForms.map({ [Elixir.Kernel.SpecialForms.atom('name')]: 'John' }))); @@ -107,17 +136,15 @@ defmodule ElixirScript.Translator.Struct.Test do end js_code = """ - const __MODULE__ = Elixir.Kernel.SpecialForms.atom('MyAppError'); - function defexception(values = {}) { - return Elixir.Kernel.defstruct({ - [Elixir.Kernel.SpecialForms.atom('__struct__')]: __MODULE__, - [Elixir.Kernel.SpecialForms.atom('__exception__')]: true, - [Elixir.Kernel.SpecialForms.atom('message')]: 'This is a message' - },values); - } - export { - MyAppError: defexception - }; + const __MODULE__ = Elixir.Kernel.SpecialForms.atom('MyAppError'); + const defexception = Elixir.Kernel.defexception({ + [Elixir.Kernel.SpecialForms.atom('__struct__')]: __MODULE__, + [Elixir.Kernel.SpecialForms.atom('__exception__')]: true, + [Elixir.Kernel.SpecialForms.atom('message')]: 'This is a message' + }); + export { + MyAppError: defexception + }; """ assert_translation(ex_ast, js_code) @@ -129,17 +156,16 @@ defmodule ElixirScript.Translator.Struct.Test do end js_code = """ - const __MODULE__ = Elixir.Kernel.SpecialForms.atom('MyAppError'); - function defexception(values = {}) { - return Elixir.Kernel.defstruct({ + const __MODULE__ = Elixir.Kernel.SpecialForms.atom('MyAppError'); + const defexception = Elixir.Kernel.defexception({ [Elixir.Kernel.SpecialForms.atom('__struct__')]: __MODULE__, [Elixir.Kernel.SpecialForms.atom('__exception__')]: true, [Elixir.Kernel.SpecialForms.atom('message')]: null - },values); - } - export { - defexception - }; + }); + + export { + MyAppError: defexception + }; """ assert_translation(ex_ast, js_code) diff --git a/test/translator/try_test.exs b/test/translator/try_test.exs index 53f178db..feee98d7 100644 --- a/test/translator/try_test.exs +++ b/test/translator/try_test.exs @@ -13,13 +13,11 @@ defmodule ElixirScript.Translator.Try.Test do end js_code = """ - Elixir.Kernel.SpecialForms._try(function() { - return do_something_that_may_fail(some_arg); - },Elixir.Patterns.defmatch(Elixir.Patterns.make_case([{ - [Elixir.Kernel.SpecialForms.atom('__struct__')]: Elixir.Kernel.SpecialForms.atom('ArgumentError') - }],function() { - return IO.puts('Invalid argument given'); - })),null,null,null) + Elixir.Kernel.SpecialForms._try(function() { + return do_something_that_may_fail(some_arg); + }, Elixir.Patterns.defmatch(Elixir.Patterns.make_case([Elixir.Patterns.type(ArgumentError, {})], function() { + return IO.puts('Invalid argument given'); + })), null, null, null) """ assert_translation(ex_ast, js_code) @@ -36,13 +34,11 @@ defmodule ElixirScript.Translator.Try.Test do end js_code = """ - Elixir.Kernel.SpecialForms._try(function() { - return do_something_that_may_fail(some_arg); - },Elixir.Patterns.defmatch(Elixir.Patterns.make_case([{ - [Elixir.Kernel.SpecialForms.atom('__struct__')]: Elixir.Kernel.SpecialForms.atom('ArgumentError') - }],function() { - return IO.puts('Invalid argument given'); - })),null,null,null) + Elixir.Kernel.SpecialForms._try(function() { + return do_something_that_may_fail(some_arg); + }, Elixir.Patterns.defmatch(Elixir.Patterns.make_case([Elixir.Patterns.type(ArgumentError, {})], function() { + return IO.puts('Invalid argument given'); + })), null, null, null) """ assert_translation(ex_ast, js_code) @@ -59,13 +55,13 @@ defmodule ElixirScript.Translator.Try.Test do end js_code = """ - Elixir.Kernel.SpecialForms._try(function() { - return do_something_that_may_fail(some_arg); - },Elixir.Patterns.defmatch(Elixir.Patterns.make_case([Elixir.Patterns.variable()],function(x) { - return IO.puts('Invalid argument given'); - },function(x) { - return Elixir.Kernel.in(x,Elixir.Kernel.SpecialForms.list(ArgumentError.defstruct(Elixir.Kernel.SpecialForms.map({})))); - })),null,null,null) + Elixir.Kernel.SpecialForms._try(function() { + return do_something_that_may_fail(some_arg); + }, Elixir.Patterns.defmatch(Elixir.Patterns.make_case([Elixir.Patterns.variable()], function(x) { + return IO.puts('Invalid argument given'); + }, function(x) { + return Elixir.Kernel.in(x, Elixir.Kernel.SpecialForms.list(ArgumentError.create(Elixir.Kernel.SpecialForms.map({})))); + })), null, null, null) """ assert_translation(ex_ast, js_code) @@ -106,15 +102,13 @@ defmodule ElixirScript.Translator.Try.Test do end js_code = """ - Elixir.Kernel.SpecialForms._try(function() { - return do_something_that_may_fail(some_arg); - },Elixir.Patterns.defmatch(Elixir.Patterns.make_case([{ - [Elixir.Kernel.SpecialForms.atom('__struct__')]: Elixir.Kernel.SpecialForms.atom('ArgumentError') - }],function() { - return IO.puts('ArgumentError'); - }),Elixir.Patterns.make_case([Elixir.Patterns.variable()],function(x) { - return IO.puts('x'); - })),null,null,null) + Elixir.Kernel.SpecialForms._try(function() { + return do_something_that_may_fail(some_arg); + }, Elixir.Patterns.defmatch(Elixir.Patterns.make_case([Elixir.Patterns.type(ArgumentError, {})], function() { + return IO.puts('ArgumentError'); + }), Elixir.Patterns.make_case([Elixir.Patterns.variable()], function(x) { + return IO.puts('x'); + })), null, null, null) """ assert_translation(ex_ast, js_code) @@ -133,15 +127,13 @@ defmodule ElixirScript.Translator.Try.Test do end js_code = """ - Elixir.Kernel.SpecialForms._try(function() { - return do_something_that_may_fail(some_arg); - },Elixir.Patterns.defmatch(Elixir.Patterns.make_case([{ - [Elixir.Kernel.SpecialForms.atom('__struct__')]: Elixir.Kernel.SpecialForms.atom('ArgumentError') - }],function() { - return IO.puts('Invalid argument given'); - })),null,null,function() { - return IO.puts('This is printed regardless if it failed or succeed'); - }) + Elixir.Kernel.SpecialForms._try(function() { + return do_something_that_may_fail(some_arg); + }, Elixir.Patterns.defmatch(Elixir.Patterns.make_case([Elixir.Patterns.type(ArgumentError, {})], function() { + return IO.puts('Invalid argument given'); + })), null, null, function() { + return IO.puts('This is printed regardless if it failed or succeed'); + }) """ assert_translation(ex_ast, js_code) @@ -208,17 +200,15 @@ defmodule ElixirScript.Translator.Try.Test do end js_code = """ - Elixir.Kernel.SpecialForms._try(function() { - return do_something_that_may_fail(some_arg); - },Elixir.Patterns.defmatch(Elixir.Patterns.make_case([{ - [Elixir.Kernel.SpecialForms.atom('__struct__')]: Elixir.Kernel.SpecialForms.atom('ArgumentError') - }],function() { - return IO.puts('Invalid argument given'); - })),Elixir.Patterns.defmatch(Elixir.Patterns.make_case([Elixir.Kernel.SpecialForms.atom('throw'), Elixir.Kernel.SpecialForms.atom('Error')],function() { - return IO.puts('caught error'); - })),null,null) + Elixir.Kernel.SpecialForms._try(function() { + return do_something_that_may_fail(some_arg); + }, Elixir.Patterns.defmatch(Elixir.Patterns.make_case([Elixir.Patterns.type(ArgumentError, {})], function() { + return IO.puts('Invalid argument given'); + })), Elixir.Patterns.defmatch(Elixir.Patterns.make_case([Elixir.Kernel.SpecialForms.atom('throw'), Elixir.Kernel.SpecialForms.atom('Error')], function() { + return IO.puts('caught error'); + })), null, null) """ assert_translation(ex_ast, js_code) end -end \ No newline at end of file +end From e12882128c04ef41f29d061ffff23093d551d557 Mon Sep 17 00:00:00 2001 From: Sonny Scroggin Date: Wed, 25 Nov 2015 16:11:23 -0600 Subject: [PATCH 053/860] Allow functions with zero arity without adding parens --- lib/elixir_script/preprocess/modules.ex | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/elixir_script/preprocess/modules.ex b/lib/elixir_script/preprocess/modules.ex index 21e2f4de..af024c03 100644 --- a/lib/elixir_script/preprocess/modules.ex +++ b/lib/elixir_script/preprocess/modules.ex @@ -167,14 +167,14 @@ defmodule ElixirScript.Preprocess.Modules do defp get_functions_from_module({:__block__, _, list}) do Enum.reduce(list, Keyword.new, fn ({:def, _, [{:when, _, [{name, _, params} | _guards] }, [do: _body]] }, state) -> - arity = length(params) + arity = if is_nil(params), do: 0, else: length(params) unless Enum.member?(Keyword.get_values([], name), arity) do Keyword.put(state, name, arity); end ({:def, _, [{name, _, params}, [do: _body]]}, state) -> - arity = length(params) + arity = if is_nil(params), do: 0, else: length(params) unless Enum.member?(Keyword.get_values([], name), arity) do Keyword.put(state, name, arity); From 7e76213c4d408b3e6fad329823bbfe342b3c9a1d Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Wed, 25 Nov 2015 17:13:11 -0600 Subject: [PATCH 054/860] Added types for Integer and Float protocols --- lib/elixir_script/translator/protocol.ex | 65 ++++++++++--------- priv/javascript/elixir.js | 2 +- priv/javascript/lib/kernel.js | 9 +-- .../lib/patterns/patterns/resolvers.js | 30 ++++----- priv/javascript/lib/protocol.js | 42 +++++++----- priv/javascript/lib/string/chars.js | 16 +++-- test/translator/protocol_test.exs | 10 +-- 7 files changed, 93 insertions(+), 81 deletions(-) diff --git a/lib/elixir_script/translator/protocol.ex b/lib/elixir_script/translator/protocol.ex index 424d1a6e..07cecd2d 100644 --- a/lib/elixir_script/translator/protocol.ex +++ b/lib/elixir_script/translator/protocol.ex @@ -181,47 +181,68 @@ defmodule ElixirScript.Translator.Protocol do end defp map_to_js({:__aliases__, _, [:Integer]}) do - do_map_to_js(:is_integer) + JS.member_expression( + JS.identifier(:Elixir), + JS.identifier(:IntegerType) + ) end defp map_to_js({:__aliases__, _, [:Tuple]}) do - do_map_to_js(:is_tuple) + JS.member_expression( + JS.identifier(:Elixir), + JS.identifier(:Tuple) + ) end defp map_to_js({:__aliases__, _, [:Atom]}) do - do_map_to_js(:is_atom) + JS.identifier(:Symbol) end defp map_to_js({:__aliases__, _, [:List]}) do - do_map_to_js(:is_list) + JS.identifier(:Array) end defp map_to_js({:__aliases__, _, [:BitString]}) do - do_map_to_js(:is_bitstring) + JS.member_expression( + JS.identifier(:Elixir), + JS.identifier(:BitString) + ) end defp map_to_js({:__aliases__, _, [:Float]}) do - do_map_to_js(:is_float) + JS.member_expression( + JS.identifier(:Elixir), + JS.identifier(:FloatType) + ) end defp map_to_js({:__aliases__, _, [:Function]}) do - do_map_to_js(:is_function) + JS.identifier(:Function) end defp map_to_js({:__aliases__, _, [:PID]}) do - do_map_to_js(:is_pid) + JS.member_expression( + JS.identifier(:Elixir), + JS.identifier(:Reference) + ) end defp map_to_js({:__aliases__, _, [:Port]}) do - do_map_to_js(:is_port) + JS.member_expression( + JS.identifier(:Elixir), + JS.identifier(:Port) + ) end defp map_to_js({:__aliases__, _, [:Reference]}) do - do_map_to_js(:is_reference) + JS.member_expression( + JS.identifier(:Elixir), + JS.identifier(:Reference) + ) end defp map_to_js({:__aliases__, _, [:Map]}) do - do_map_to_js(:is_map) + JS.identifier(:Object) end defp map_to_js({:__aliases__, _, [:Any]}) do @@ -234,25 +255,9 @@ defmodule ElixirScript.Translator.Protocol do defp map_to_js({:__aliases__, _, struct}) do - module_name = Enum.map(struct, &Atom.to_string(&1)) - |> Enum.join(".") - |> String.to_atom - - quoted = quote do - Kernel.is_struct_fn(unquote(module_name)) - end - - Translator.translate(quoted, ElixirScript.State.get().env) - end - - - defp do_map_to_js(identifier) do - JS.member_expression( - JS.identifier(:Elixir), - JS.member_expression( - JS.identifier(:Kernel), - JS.identifier(identifier) - ) + ElixirScript.Translator.Struct.get_struct_class( + struct, + ElixirScript.State.get().env ) end diff --git a/priv/javascript/elixir.js b/priv/javascript/elixir.js index d172cd88..f5bc3445 100644 --- a/priv/javascript/elixir.js +++ b/priv/javascript/elixir.js @@ -23,4 +23,4 @@ export { default as Inspect } from './lib/inspect'; export { default as Map } from './lib/map'; export { default as Set } from './lib/set'; export { default as MapSet } from './lib/map_set'; - +export { IntegerType, FloatType } from './lib/protocol'; diff --git a/priv/javascript/lib/kernel.js b/priv/javascript/lib/kernel.js index f68b061b..6ad534ec 100644 --- a/priv/javascript/lib/kernel.js +++ b/priv/javascript/lib/kernel.js @@ -2,7 +2,7 @@ import SpecialForms from './kernel/special_forms'; import Patterns from './patterns/patterns'; import Tuple from './tuple'; import BitString from './bit_string'; -import Protocol from './protocol'; +import { Protocol } from './protocol'; import { PID } from './processes/processes'; function tl(list){ @@ -186,12 +186,6 @@ function defexception(defaults){ } } -function is_struct_fn(__struct__){ - return function(x){ - return is_map && x[SpecialForms.atom("__struct__")] === __struct__; - } -} - function defprotocol(spec){ return new Protocol(spec); } @@ -233,7 +227,6 @@ export default { to_string, match__qmark__, defstruct, - is_struct_fn, defprotocol, defimpl }; diff --git a/priv/javascript/lib/patterns/patterns/resolvers.js b/priv/javascript/lib/patterns/patterns/resolvers.js index 593bec92..a42f15c4 100644 --- a/priv/javascript/lib/patterns/patterns/resolvers.js +++ b/priv/javascript/lib/patterns/patterns/resolvers.js @@ -27,37 +27,37 @@ function resolveTuple(pattern: any): Function { function resolveSymbol(pattern: any): Function { return function(value: any): boolean { return Checks.is_symbol(value) && value === pattern; - }; + }; } function resolveString(pattern: any): Function { return function(value: any): boolean { return Checks.is_string(value) && value === pattern - }; + }; } function resolveNumber(pattern: any): Function { return function(value: any): boolean { return Checks.is_number(value) && value === pattern; - }; + }; } function resolveBoolean(pattern: any): Function { return function(value: any): boolean { return Checks.is_boolean(value) && value === pattern - }; + }; } function resolveFunction(pattern: any): Function { return function(value: any): boolean { return Checks.is_function(value) && value === pattern - }; + }; } function resolveNull(pattern: any): Function { return function(value: any): boolean { return Checks.is_null(value); - }; + }; } function resolveBound(pattern: Types.Bound): Function { @@ -74,14 +74,14 @@ function resolveBound(pattern: Types.Bound): Function { function resolveWildcard(): Function { return function(): boolean { return true; - }; + }; } function resolveVariable(): Function { return function(value: any, args: Array): boolean { args.push(value); return true; - }; + }; } function resolveHeadTail(): Function { @@ -92,7 +92,7 @@ function resolveHeadTail(): Function { const head = value[0]; const tail = value.slice(1); - + args.push(head); args.push(tail); @@ -128,12 +128,12 @@ function resolveStartsWith(pattern: Types.StartsWith): Function { function resolveType(pattern: Types.Type): Function { return function(value: any, args: Array): boolean { - if(!value instanceof pattern.type){ - return false; + if(value instanceof pattern.type){ + const matches = buildMatch(pattern.objPattern); + return matches(value, args) && args.push(value) > 0; } - const matches = buildMatch(pattern.objPattern); - return matches(value, args) && args.push(value) > 0; + return false; }; } @@ -166,7 +166,7 @@ function resolveObject(pattern: Object): Function { for(let key of Object.keys(pattern)){ if(!(key in value) || !matches[key](value[key], args) ){ return false; - } + } } return true; @@ -197,4 +197,4 @@ export default { resolveFunction, resolveNull, resolveTuple -} \ No newline at end of file +} diff --git a/priv/javascript/lib/protocol.js b/priv/javascript/lib/protocol.js index e0f658a2..fba4a3b1 100644 --- a/priv/javascript/lib/protocol.js +++ b/priv/javascript/lib/protocol.js @@ -1,7 +1,10 @@ +class IntegerType {} +class FloatType {} + //https://github.com/airportyh/protomorphism class Protocol{ constructor(spec){ - this.registry = []; + this.registry = new Map(); this.fallback = null; for (let funName in spec){ @@ -12,23 +15,24 @@ class Protocol{ return function(...args) { let thing = args[0]; - - for(let [check, implementation] of this.registry){ - - if(check(thing)){ - let fun = implementation[funName]; - let retval = fun.apply(this, args); - return retval; - } + let fun = null; + + if(Number.isInteger(thing) && this.hasImplementation(IntegerType)){ + fun = this.registry.get(IntegerType)[funName]; + }else if(typeof thing === "number" && !Number.isInteger(thing) && this.hasImplementation(FloatType)){ + fun = this.registry.get(FloatType)[funName]; + }else if(this.hasImplementation(thing.constructor)){ + fun = this.registry.get(thing.constructor)[funName]; + }else if(this.fallback){ + fun = this.fallback[funName]; } - if(this.fallback){ - let fun = fallback; + if(fun != null){ let retval = fun.apply(this, args); - return retval; + return retval; } - throw new Error("No implementation found for " + thing); + throw new Error("No implementation found for " + thing); } } } @@ -37,10 +41,18 @@ class Protocol{ if(type === null){ this.fallback = implementation; }else{ - this.registry.push([type, implementation]); + this.registry.set(type, implementation); } } + + hasImplementation(thing) { + return this.registry.has(thing.constructor); + } } -export default Protocol; \ No newline at end of file +export { + Protocol, + IntegerType, + FloatType +} diff --git a/priv/javascript/lib/string/chars.js b/priv/javascript/lib/string/chars.js index 5e1570fb..9a4318f1 100644 --- a/priv/javascript/lib/string/chars.js +++ b/priv/javascript/lib/string/chars.js @@ -3,12 +3,14 @@ import Atom from "../atom"; import Integer from "../integer"; import List from "../list"; import Tuple from "../tuple"; +import BitString from "../bit_string"; +import { IntegerType, FloatType } from "../protocol"; let Chars = Kernel.defprotocol({ to_string: function(thing){} }); -Kernel.defimpl(Chars, Kernel.is_bitstring, { +Kernel.defimpl(Chars, BitString, { to_string: function(thing){ if(Kernel.is_binary(thing)){ return thing; @@ -18,7 +20,7 @@ Kernel.defimpl(Chars, Kernel.is_bitstring, { } }); -Kernel.defimpl(Chars, Kernel.is_atom, { +Kernel.defimpl(Chars, Symbol, { to_string: function(thing){ if(nil){ return ""; @@ -28,25 +30,25 @@ Kernel.defimpl(Chars, Kernel.is_atom, { } }); -Kernel.defimpl(Chars, Kernel.is_integer, { +Kernel.defimpl(Chars, IntegerType, { to_string: function(thing){ return Integer.to_string(thing); } }); -Kernel.defimpl(Chars, Kernel.is_float, { +Kernel.defimpl(Chars, FloatType, { to_string: function(thing){ return thing.toString; } }); -Kernel.defimpl(Chars, Kernel.is_list, { +Kernel.defimpl(Chars, Array, { to_string: function(thing){ return thing.toString(); } }); -Kernel.defimpl(Chars, Kernel.is_tuple, { +Kernel.defimpl(Chars, Tuple, { to_string: function(thing){ return Tuple.to_string(thing); } @@ -59,4 +61,4 @@ Kernel.defimpl(Chars, null, { } }); -export default Chars; \ No newline at end of file +export default Chars; diff --git a/test/translator/protocol_test.exs b/test/translator/protocol_test.exs index ae896ff4..6ea8bd64 100644 --- a/test/translator/protocol_test.exs +++ b/test/translator/protocol_test.exs @@ -34,7 +34,7 @@ defmodule ElixirScript.Translator.Protocol.Test do end js_code = """ - Elixir.Kernel.defimpl(Elixir.String.Chars, Elixir.Kernel.is_struct_fn(Elixir.Kernel.SpecialForms.atom('Duck')),{ + Elixir.Kernel.defimpl(Elixir.String.Chars, Duck, { to_string: Elixir.Patterns.defmatch(Elixir.Patterns.make_case([Elixir.Patterns.variable()],function(duck) { return 'quack'; })) @@ -74,14 +74,14 @@ defmodule ElixirScript.Translator.Protocol.Test do return null; })) }); - Elixir.Kernel.defimpl(Blank,Elixir.Kernel.is_list,{ + Elixir.Kernel.defimpl(Blank, Array,{ blank__qmark__: Elixir.Patterns.defmatch(Elixir.Patterns.make_case([Elixir.Kernel.SpecialForms.list()],function() { return true; }),Elixir.Patterns.make_case([Elixir.Patterns.wildcard()],function() { return false; })) }) - Elixir.Kernel.defimpl(Blank,Elixir.Kernel.is_atom,{ + Elixir.Kernel.defimpl(Blank,Symbol,{ blank__qmark__: Elixir.Patterns.defmatch(Elixir.Patterns.make_case([false],function() { return true; }),Elixir.Patterns.make_case([null],function() { @@ -90,7 +90,7 @@ defmodule ElixirScript.Translator.Protocol.Test do return false; })) }) - Elixir.Kernel.defimpl(Blank,Elixir.Kernel.is_integer,{ + Elixir.Kernel.defimpl(Blank,Elixir.IntegerType,{ blank__qmark__: Elixir.Patterns.defmatch(Elixir.Patterns.make_case([Elixir.Patterns.variable()],function(number) { return false; })) @@ -101,4 +101,4 @@ defmodule ElixirScript.Translator.Protocol.Test do assert_translation(ex_ast, js_code) end -end \ No newline at end of file +end From 5cc80e27da9267a83212e1f59047e08c0b9d1423 Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Wed, 25 Nov 2015 17:34:20 -0600 Subject: [PATCH 055/860] fixed hasImplementation call --- priv/javascript/lib/protocol.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/priv/javascript/lib/protocol.js b/priv/javascript/lib/protocol.js index fba4a3b1..29cfe0ff 100644 --- a/priv/javascript/lib/protocol.js +++ b/priv/javascript/lib/protocol.js @@ -21,7 +21,7 @@ class Protocol{ fun = this.registry.get(IntegerType)[funName]; }else if(typeof thing === "number" && !Number.isInteger(thing) && this.hasImplementation(FloatType)){ fun = this.registry.get(FloatType)[funName]; - }else if(this.hasImplementation(thing.constructor)){ + }else if(this.hasImplementation(thing)){ fun = this.registry.get(thing.constructor)[funName]; }else if(this.fallback){ fun = this.fallback[funName]; From b7bb75759cb9636308eeeb9b0dada8d966289f9b Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Wed, 25 Nov 2015 17:37:10 -0600 Subject: [PATCH 056/860] Updated version to 0.14.0-dev --- CHANGELOG.md | 9 ++++++++- mix.exs | 2 +- 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index be8fb91a..021369c3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,10 @@ +# v0.14.0-dev +* Enhancements + * Structs are now translated into classes + * Structs and Tuples now match on their types + * Can now match on JavaScript classes + * Can now implement protocols using JavaScript types + # v0.13.0 * Enhancements * Added `Base` module with function: encode64, decode64, and decode64! @@ -84,7 +91,7 @@ * Improved function chaining * added `from` clause to `import`, `alias`, and `require` so that the import path can be overridden * `alias` now acts like `require` in that it is translated into an import default statement - * modules now export a default object with def functions added as properties on it. + * modules now export a default object with def functions added as properties on it. * for function closures, now calling by using `.call(this)` so that `this` is available inside of it # v0.4.0 diff --git a/mix.exs b/mix.exs index d81ed8f0..9343ef89 100644 --- a/mix.exs +++ b/mix.exs @@ -4,7 +4,7 @@ defmodule ElixirScript.Mixfile do def project do [ app: :elixir_script, - version: "0.13.0", + version: "0.14.0-dev", elixir: "~> 1.0", escript: escript_config, deps: deps, From 08fb9f7cc737ab07598e0e6a419f7766793cf7cf Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Wed, 25 Nov 2015 19:03:29 -0600 Subject: [PATCH 057/860] moved javascript folder from priv to src. included built elixir.js in priv --- .gitignore | 10 +- gulpfile.js | 20 +- lib/elixir_script.ex | 6 +- mix.exs | 10 +- priv/elixir.js | 2923 +++++++++++++++++ {priv => src}/javascript/elixir.js | 0 {priv => src}/javascript/lib/agent.js | 0 {priv => src}/javascript/lib/atom.js | 0 {priv => src}/javascript/lib/base.js | 0 {priv => src}/javascript/lib/bit_string.js | 0 {priv => src}/javascript/lib/bitwise.js | 0 {priv => src}/javascript/lib/collectable.js | 0 {priv => src}/javascript/lib/enum.js | 0 {priv => src}/javascript/lib/enumerable.js | 0 {priv => src}/javascript/lib/inspect.js | 0 {priv => src}/javascript/lib/integer.js | 0 {priv => src}/javascript/lib/js.js | 0 {priv => src}/javascript/lib/kernel.js | 0 .../javascript/lib/kernel/special_forms.js | 0 {priv => src}/javascript/lib/keyword.js | 0 {priv => src}/javascript/lib/list.js | 0 {priv => src}/javascript/lib/list/chars.js | 0 {priv => src}/javascript/lib/map.js | 0 {priv => src}/javascript/lib/map_set.js | 0 .../javascript/lib/patterns/patterns.js | 0 .../lib/patterns/patterns/checks.js | 0 .../lib/patterns/patterns/defmatch.js | 0 .../javascript/lib/patterns/patterns/match.js | 0 .../lib/patterns/patterns/resolvers.js | 0 .../javascript/lib/patterns/patterns/types.js | 0 {priv => src}/javascript/lib/post_office.js | 0 .../javascript/lib/processes/processes.js | 0 .../lib/processes/processes/mailbox.js | 0 .../processes/processes/otp/application.js | 0 .../lib/processes/processes/otp/gen_event.js | 0 .../lib/processes/processes/otp/gen_server.js | 0 .../javascript/lib/processes/processes/pid.js | 0 .../lib/processes/processes/process.js | 0 .../lib/processes/processes/process_system.js | 0 .../lib/processes/processes/scheduler.js | 0 .../lib/processes/processes/states.js | 0 {priv => src}/javascript/lib/protocol.js | 0 {priv => src}/javascript/lib/range.js | 0 {priv => src}/javascript/lib/set.js | 0 {priv => src}/javascript/lib/signals.js | 0 {priv => src}/javascript/lib/string.js | 0 {priv => src}/javascript/lib/string/chars.js | 0 {priv => src}/javascript/lib/tuple.js | 0 {priv => src}/javascript/tests/atom.spec.js | 0 .../javascript/tests/bit_string.spec.js | 0 {priv => src}/javascript/tests/case.spec.js | 0 {priv => src}/javascript/tests/cond.spec.js | 0 {priv => src}/javascript/tests/enum.spec.js | 0 {priv => src}/javascript/tests/for.spec.js | 0 .../javascript/tests/integer.spec.js | 0 {priv => src}/javascript/tests/kernel.spec.js | 0 {priv => src}/javascript/tests/list.spec.js | 0 {priv => src}/javascript/tests/map.spec.js | 0 .../tests/patterns/defmatch.spec.js | 0 .../javascript/tests/patterns/match.spec.js | 0 {priv => src}/javascript/tests/range.spec.js | 0 {priv => src}/javascript/tests/set.spec.js | 0 .../javascript/tests/special_forms.spec.js | 0 .../javascript/tests/string.chars.spec.js | 0 {priv => src}/javascript/tests/try.spec.js | 0 {priv => src}/javascript/tests/tuple.spec.js | 0 66 files changed, 2944 insertions(+), 25 deletions(-) create mode 100644 priv/elixir.js rename {priv => src}/javascript/elixir.js (100%) rename {priv => src}/javascript/lib/agent.js (100%) rename {priv => src}/javascript/lib/atom.js (100%) rename {priv => src}/javascript/lib/base.js (100%) rename {priv => src}/javascript/lib/bit_string.js (100%) rename {priv => src}/javascript/lib/bitwise.js (100%) rename {priv => src}/javascript/lib/collectable.js (100%) rename {priv => src}/javascript/lib/enum.js (100%) rename {priv => src}/javascript/lib/enumerable.js (100%) rename {priv => src}/javascript/lib/inspect.js (100%) rename {priv => src}/javascript/lib/integer.js (100%) rename {priv => src}/javascript/lib/js.js (100%) rename {priv => src}/javascript/lib/kernel.js (100%) rename {priv => src}/javascript/lib/kernel/special_forms.js (100%) rename {priv => src}/javascript/lib/keyword.js (100%) rename {priv => src}/javascript/lib/list.js (100%) rename {priv => src}/javascript/lib/list/chars.js (100%) rename {priv => src}/javascript/lib/map.js (100%) rename {priv => src}/javascript/lib/map_set.js (100%) rename {priv => src}/javascript/lib/patterns/patterns.js (100%) rename {priv => src}/javascript/lib/patterns/patterns/checks.js (100%) rename {priv => src}/javascript/lib/patterns/patterns/defmatch.js (100%) rename {priv => src}/javascript/lib/patterns/patterns/match.js (100%) rename {priv => src}/javascript/lib/patterns/patterns/resolvers.js (100%) rename {priv => src}/javascript/lib/patterns/patterns/types.js (100%) rename {priv => src}/javascript/lib/post_office.js (100%) rename {priv => src}/javascript/lib/processes/processes.js (100%) rename {priv => src}/javascript/lib/processes/processes/mailbox.js (100%) rename {priv => src}/javascript/lib/processes/processes/otp/application.js (100%) rename {priv => src}/javascript/lib/processes/processes/otp/gen_event.js (100%) rename {priv => src}/javascript/lib/processes/processes/otp/gen_server.js (100%) rename {priv => src}/javascript/lib/processes/processes/pid.js (100%) rename {priv => src}/javascript/lib/processes/processes/process.js (100%) rename {priv => src}/javascript/lib/processes/processes/process_system.js (100%) rename {priv => src}/javascript/lib/processes/processes/scheduler.js (100%) rename {priv => src}/javascript/lib/processes/processes/states.js (100%) rename {priv => src}/javascript/lib/protocol.js (100%) rename {priv => src}/javascript/lib/range.js (100%) rename {priv => src}/javascript/lib/set.js (100%) rename {priv => src}/javascript/lib/signals.js (100%) rename {priv => src}/javascript/lib/string.js (100%) rename {priv => src}/javascript/lib/string/chars.js (100%) rename {priv => src}/javascript/lib/tuple.js (100%) rename {priv => src}/javascript/tests/atom.spec.js (100%) rename {priv => src}/javascript/tests/bit_string.spec.js (100%) rename {priv => src}/javascript/tests/case.spec.js (100%) rename {priv => src}/javascript/tests/cond.spec.js (100%) rename {priv => src}/javascript/tests/enum.spec.js (100%) rename {priv => src}/javascript/tests/for.spec.js (100%) rename {priv => src}/javascript/tests/integer.spec.js (100%) rename {priv => src}/javascript/tests/kernel.spec.js (100%) rename {priv => src}/javascript/tests/list.spec.js (100%) rename {priv => src}/javascript/tests/map.spec.js (100%) rename {priv => src}/javascript/tests/patterns/defmatch.spec.js (100%) rename {priv => src}/javascript/tests/patterns/match.spec.js (100%) rename {priv => src}/javascript/tests/range.spec.js (100%) rename {priv => src}/javascript/tests/set.spec.js (100%) rename {priv => src}/javascript/tests/special_forms.spec.js (100%) rename {priv => src}/javascript/tests/string.chars.spec.js (100%) rename {priv => src}/javascript/tests/try.spec.js (100%) rename {priv => src}/javascript/tests/tuple.spec.js (100%) diff --git a/.gitignore b/.gitignore index 25c0a751..072bdaa1 100644 --- a/.gitignore +++ b/.gitignore @@ -5,15 +5,13 @@ erl_crash.dump ex2js elixirscript node_modules -priv/test_project/dest -priv/javascript/build -priv/javascript/test_build -priv/javascript/dist -priv/javascript/dist_build +src/javascript/build +src/javascript/test_build +src/javascript/dist +src/javascript/dist_build /dist deploy.sh .DS_Store -priv/javascript/scratchpad.js sample/dest fprof.trace index.js diff --git a/gulpfile.js b/gulpfile.js index a57da53a..afe4f73f 100644 --- a/gulpfile.js +++ b/gulpfile.js @@ -8,21 +8,21 @@ var sourcemaps = require('gulp-sourcemaps'); require("babel/polyfill"); -var path = './priv/javascript'; +var path = './src/javascript'; var stdLibPath = path + '/lib/**/*.js'; var testPath = path + '/test_build/tests/**/*.spec.js'; var libPath = path + '/lib'; gulp.task('test_build', function() { - return gulp.src(['./priv/javascript/lib/**/*.js']) + return gulp.src([path + '/lib/**/*.js']) .pipe(babel({sourceMap: false, modules:'common'})) - .pipe(gulp.dest('./priv/javascript/test_build/lib')); + .pipe(gulp.dest(path + '/test_build/lib')); }); gulp.task('test_build_tests', function() { - return gulp.src(['./priv/javascript/tests/**/*.spec.js']) + return gulp.src([path + '/tests/**/*.spec.js']) .pipe(babel({sourceMap: false, modules:'common'})) - .pipe(gulp.dest('./priv/javascript/test_build/tests')); + .pipe(gulp.dest(path + '/test_build/tests')); }); gulp.task('test', ['test_build', 'test_build_tests'], function () { @@ -31,23 +31,23 @@ gulp.task('test', ['test_build', 'test_build_tests'], function () { }); gulp.task('lint', function () { - return gulp.src([stdLibPath, testPath, '!./priv/javascript/build/**/*.js']) + return gulp.src([stdLibPath, testPath, '!' + path + '/build/**/*.js']) .pipe(eslint()) .pipe(eslint.format()) .pipe(eslint.failOnError()); }); gulp.task('dist_build', function() { - return gulp.src(['./priv/javascript/**/*.js', '!./priv/javascript/build/**/*.js', '!./priv/javascript/dist/**/*.js', '!./priv/javascript/dist_build/**/*.js', '!./priv/javascript/tests/**/*.js']) + return gulp.src([path + '/**/*.js', '!' + path + '/build/**/*.js', '!' + path + '/dist/**/*.js', '!' + path + '/dist_build/**/*.js', '!' + path + '/tests/**/*.js']) .pipe(babel({whitelist: ['flow'], optional: ["minification.deadCodeElimination"]})) - .pipe(gulp.dest('./priv/javascript/dist_build')); + .pipe(gulp.dest(path + '/dist_build')); }); gulp.task('dist_add_source_map', function() { - return gulp.src(['./priv/javascript/dist/elixir.js']) + return gulp.src(['./priv/elixir.js']) .pipe(sourcemaps.init()) .pipe(sourcemaps.write()) - .pipe(gulp.dest('./priv/javascript/dist')); + .pipe(gulp.dest('./priv')); }); diff --git a/lib/elixir_script.ex b/lib/elixir_script.ex index c8e0b492..711be25c 100644 --- a/lib/elixir_script.ex +++ b/lib/elixir_script.ex @@ -126,14 +126,14 @@ defmodule ElixirScript do to the specified location """ def copy_standard_libs_to_destination(destination) do - File.cp_r!(operating_path <> "/dist", destination) + File.cp_r!(operating_path, destination) end @doc """ Returns the standard lib js code """ def standard_libs() do - File.read!(operating_path <> "/dist/elixir.js") + File.read!(operating_path <> "/elixir.js") end defp convert_to_code(js_ast, root, include_path, env, import_standard_libs) do @@ -201,7 +201,7 @@ defmodule ElixirScript do defp operating_path() do try do - Mix.Project.build_path <> "/lib/elixir_script/priv/javascript" + Mix.Project.build_path <> "/lib/elixir_script/priv" rescue UndefinedFunctionError -> split_path = Path.split(Application.app_dir(:elixirscript)) diff --git a/mix.exs b/mix.exs index 9343ef89..aa0cb0e7 100644 --- a/mix.exs +++ b/mix.exs @@ -51,7 +51,7 @@ defmodule ElixirScript.Mixfile do defp package do [ - files: ["lib", "priv/javascript/dist", "mix.exs", "README*", "readme*", "LICENSE*", "license*", "CHANGELOG*"], + files: ["lib", "priv/elixir.js", "mix.exs", "README*", "readme*", "LICENSE*", "license*", "CHANGELOG*"], maintainers: ["Bryan Joseph"], licenses: ["MIT"], links: %{ @@ -73,8 +73,6 @@ defmodule ElixirScript.Mixfile do folder_name = "#{dist_folder}/elixirscript" archive_file_name = "#{dist_folder}/elixirscript.tar.gz" - File.mkdir_p("priv/javascript/dist") - Mix.Tasks.Escript.Build.run([]) if File.exists?(dist_folder) do @@ -82,13 +80,13 @@ defmodule ElixirScript.Mixfile do end { _ , _ } = System.cmd("node", ["node_modules/gulp/bin/gulp.js", "dist_build"]) - { elixir_js, _ } = System.cmd("node", ["node_modules/rollup/bin/rollup", "./priv/javascript/dist_build/elixir.js"]) - File.write!("priv/javascript/dist/elixir.js", elixir_js) + { elixir_js, _ } = System.cmd("node", ["node_modules/rollup/bin/rollup", "./src/javascript/dist_build/elixir.js"]) + File.write!("priv/elixir.js", elixir_js) { _ , _ } = System.cmd("node", ["node_modules/gulp/bin/gulp.js", "dist_add_source_map"]) File.mkdir_p(folder_name <> "/bin") File.cp!("elixirscript", "#{folder_name}/bin/elixirscript") - File.cp_r!("priv/javascript/dist", "#{folder_name}/dist") + File.cp_r!("priv", "#{folder_name}") File.cp_r!("LICENSE", "#{folder_name}/LICENSE") System.cmd("tar", ["czf", archive_file_name, folder_name]) diff --git a/priv/elixir.js b/priv/elixir.js new file mode 100644 index 00000000..e581f8a4 --- /dev/null +++ b/priv/elixir.js @@ -0,0 +1,2923 @@ +var Patterns = { + get default () { return _Patterns; } +}; + +class Tuple { + + constructor(...args) { + this.values = Object.freeze(args); + } + + get(index) { + return this.values[index]; + } + + count() { + return this.values.length; + } + + [Symbol.iterator]() { + return this.values[Symbol.iterator](); + } + + toString() { + var i, + s = ""; + for (i = 0; i < this.values.length; i++) { + if (s !== "") { + s += ", "; + } + s += this.values[i].toString(); + } + + return "{" + s + "}"; + } + + static to_string(tuple) { + return tuple.toString(); + } + + static delete_at(tuple, index) { + let new_list = []; + + for (var i = 0; i < tuple.count(); i++) { + if (i !== index) { + new_list.push(tuple.get(i)); + } + } + + return Kernel.SpecialForms.tuple.apply(null, new_list); + } + + static duplicate(data, size) { + let array = []; + + for (var i = size - 1; i >= 0; i--) { + array.push(data); + } + + return Kernel.SpecialForms.tuple.apply(null, array); + } + + static insert_at(tuple, index, term) { + let new_tuple = []; + + for (var i = 0; i <= tuple.count(); i++) { + if (i === index) { + new_tuple.push(term); + i++; + new_tuple.push(tuple.get(i)); + } else { + new_tuple.push(tuple.get(i)); + } + } + + return Kernel.SpecialForms.tuple.apply(null, new_tuple); + } + + static from_list(list) { + return Kernel.SpecialForms.tuple.apply(null, list); + } + + static to_list(tuple) { + let new_list = []; + + for (var i = 0; i < tuple.count(); i++) { + new_list.push(tuple.get(i)); + } + + return Kernel.SpecialForms.list(...new_list); + } +} + +/* @flow */ + +class Variable { + + constructor(name = null) { + this.name = name; + } +} + +class Wildcard { + constructor() {} +} + +class StartsWith { + + constructor(prefix) { + this.prefix = prefix; + } +} + +class Capture { + + constructor(value) { + this.value = value; + } +} + +class HeadTail { + constructor() {} +} + +class Type { + + constructor(type, objPattern = {}) { + this.type = type; + this.objPattern = objPattern; + } +} + +class Bound { + + constructor(value) { + this.value = value; + } +} + +function variable(name = null) { + return new Variable(name); +} + +function wildcard() { + return new Wildcard(); +} + +function startsWith(prefix) { + return new StartsWith(prefix); +} + +function capture(value) { + return new Capture(value); +} + +function headTail() { + return new HeadTail(); +} + +function type(type, objPattern = {}) { + return new Type(type, objPattern); +} + +function bound(value) { + return new Bound(value); +} + +function _is_number(value) { + return typeof value === 'number'; +} + +function is_string(value) { + return typeof value === 'string'; +} + +function _is_tuple(value) { + return value instanceof Tuple; +} + +function _is_boolean(value) { + return typeof value === 'boolean'; +} + +function is_symbol(value) { + return typeof value === 'symbol'; +} + +function is_null(value) { + return value === null; +} + +function is_undefined(value) { + return typeof value === 'undefined'; +} + +function _is_function(value) { + return Object.prototype.toString.call(value) == '[object Function]'; +} + +function is_variable(value) { + return value instanceof Variable; +} + +function is_wildcard(value) { + return value instanceof Wildcard; +} + +function is_headTail(value) { + return value instanceof HeadTail; +} + +function is_capture(value) { + return value instanceof Capture; +} + +function is_type(value) { + return value instanceof Type; +} + +function is_startsWith(value) { + return value instanceof StartsWith; +} + +function is_bound(value) { + return value instanceof Bound; +} + +function is_object(value) { + return typeof value === 'object'; +} + +function is_array(value) { + return Array.isArray(value); +} + +var Checks = { + is_number: _is_number, + is_string, + is_boolean: _is_boolean, + is_symbol, + is_null, + is_undefined, + is_function: _is_function, + is_variable, + is_wildcard, + is_headTail, + is_capture, + is_type, + is_startsWith, + is_bound, + is_object, + is_array, + is_tuple: _is_tuple +}; + +function resolveTuple(pattern) { + let matches = []; + + for (let elem of pattern) { + matches.push(buildMatch(elem)); + } + + return function (value, args) { + if (!Checks.is_tuple(value) || value.count() != pattern.count()) { + return false; + } + + return value.values.every(function (v, i) { + return matches[i](value.get(i), args); + }); + }; +} + +function resolveSymbol(pattern) { + return function (value) { + return Checks.is_symbol(value) && value === pattern; + }; +} + +function resolveString(pattern) { + return function (value) { + return Checks.is_string(value) && value === pattern; + }; +} + +function resolveNumber(pattern) { + return function (value) { + return Checks.is_number(value) && value === pattern; + }; +} + +function resolveBoolean(pattern) { + return function (value) { + return Checks.is_boolean(value) && value === pattern; + }; +} + +function resolveFunction(pattern) { + return function (value) { + return Checks.is_function(value) && value === pattern; + }; +} + +function resolveNull(pattern) { + return function (value) { + return Checks.is_null(value); + }; +} + +function resolveBound(pattern) { + return function (value, args) { + if (typeof value === typeof pattern.value && value === pattern.value) { + args.push(value); + return true; + } + + return false; + }; +} + +function resolveWildcard() { + return function () { + return true; + }; +} + +function resolveVariable() { + return function (value, args) { + args.push(value); + return true; + }; +} + +function resolveHeadTail() { + return function (value, args) { + if (!Checks.is_array(value) || value.length < 2) { + return false; + } + + const head = value[0]; + const tail = value.slice(1); + + args.push(head); + args.push(tail); + + return true; + }; +} + +function resolveCapture(pattern) { + const matches = buildMatch(pattern.value); + + return function (value, args) { + if (matches(value, args)) { + args.push(value); + return true; + } + + return false; + }; +} + +function resolveStartsWith(pattern) { + const prefix = pattern.prefix; + + return function (value, args) { + if (Checks.is_string(value) && value.startsWith(prefix)) { + args.push(value.substring(prefix.length)); + return true; + } + + return false; + }; +} + +function resolveType(pattern) { + return function (value, args) { + if (value instanceof pattern.type) { + const matches = buildMatch(pattern.objPattern); + return matches(value, args) && args.push(value) > 0; + } + + return false; + }; +} + +function resolveArray(pattern) { + const matches = pattern.map(x => buildMatch(x)); + + return function (value, args) { + if (!Checks.is_array(value) || value.length != pattern.length) { + return false; + } + + return value.every(function (v, i) { + return matches[i](value[i], args); + }); + }; +} + +function resolveObject(pattern) { + let matches = {}; + + for (let key of Object.keys(pattern)) { + matches[key] = buildMatch(pattern[key]); + } + + return function (value, args) { + if (!Checks.is_object(value) || pattern.length > value.length) { + return false; + } + + for (let key of Object.keys(pattern)) { + if (!(key in value) || !matches[key](value[key], args)) { + return false; + } + } + + return true; + }; +} + +function resolveNoMatch() { + return function () { + return false; + }; +} + +var Resolvers = { + resolveBound, + resolveWildcard, + resolveVariable, + resolveHeadTail, + resolveCapture, + resolveStartsWith, + resolveType, + resolveArray, + resolveObject, + resolveNoMatch, + resolveSymbol, + resolveString, + resolveNumber, + resolveBoolean, + resolveFunction, + resolveNull, + resolveTuple +}; + +function buildMatch(pattern) { + + if (Checks.is_tuple(pattern)) { + return Resolvers.resolveTuple(pattern); + } + + if (Checks.is_variable(pattern)) { + return Resolvers.resolveVariable(pattern); + } + + if (Checks.is_wildcard(pattern)) { + return Resolvers.resolveWildcard(pattern); + } + + if (Checks.is_undefined(pattern)) { + return Resolvers.resolveWildcard(pattern); + } + + if (Checks.is_headTail(pattern)) { + return Resolvers.resolveHeadTail(pattern); + } + + if (Checks.is_startsWith(pattern)) { + return Resolvers.resolveStartsWith(pattern); + } + + if (Checks.is_capture(pattern)) { + return Resolvers.resolveCapture(pattern); + } + + if (Checks.is_bound(pattern)) { + return Resolvers.resolveBound(pattern); + } + + if (Checks.is_type(pattern)) { + return Resolvers.resolveType(pattern); + } + + if (Checks.is_array(pattern)) { + return Resolvers.resolveArray(pattern); + } + + if (Checks.is_number(pattern)) { + return Resolvers.resolveNumber(pattern); + } + + if (Checks.is_string(pattern)) { + return Resolvers.resolveString(pattern); + } + + if (Checks.is_boolean(pattern)) { + return Resolvers.resolveBoolean(pattern); + } + + if (Checks.is_symbol(pattern)) { + return Resolvers.resolveSymbol(pattern); + } + + if (Checks.is_null(pattern)) { + return Resolvers.resolveNull(pattern); + } + + if (Checks.is_object(pattern)) { + return Resolvers.resolveObject(pattern); + } + + return Resolvers.resolveNoMatch(); +} + +class MatchError extends Error { + constructor(arg) { + super(); + + if (typeof arg === 'symbol') { + this.message = 'No match for: ' + arg.toString(); + } else if (Array.isArray(arg)) { + let mappedValues = arg.map(x => x.toString()); + this.message = 'No match for: ' + mappedValues; + } else { + this.message = 'No match for: ' + arg; + } + + this.stack = new Error().stack; + this.name = this.constructor.name; + } +} + +class Case { + + constructor(pattern, fn, guard = () => true) { + this.pattern = buildMatch(pattern); + this.fn = fn; + this.guard = guard; + } +} + +function make_case(pattern, fn, guard = () => true) { + return new Case(pattern, fn, guard); +} + +function defmatch(...cases) { + return function (...args) { + for (let processedCase of cases) { + let result = []; + if (processedCase.pattern(args, result) && processedCase.guard.apply(this, result)) { + return processedCase.fn.apply(this, result); + } + } + + throw new MatchError(args); + }; +} + +function match(pattern, expr, guard = () => true) { + let result = []; + let processedPattern = buildMatch(pattern); + if (processedPattern(expr, result) && guard.apply(this, result)) { + return result; + } else { + throw new MatchError(expr); + } +} + +function match_no_throw(pattern, expr, guard = () => true) { + try { + return match(pattern, expr, guard); + } catch (e) { + if (e instanceof MatchError) { + return null; + } + + throw e; + } +} + +function patternMap(collection, pattern, fun, guard = () => true) { + let ret = []; + + for (let elem of collection) { + try { + let result = fun.apply(this, match(pattern, elem, guard)); + ret = ret.concat(result); + } catch (e) { + if (!(e instanceof MatchError)) { + throw e; + } + } + } + + return ret; +} + +var _Patterns = { + defmatch, match, MatchError, match_no_throw, patternMap, + variable, wildcard, startsWith, + capture, headTail, type, bound, Case, make_case +}; + +class BitString { + constructor(...args) { + this.raw_value = function () { + return Object.freeze(args); + }; + + this.value = Object.freeze(this.process(args)); + } + + get(index) { + return this.value[index]; + } + + count() { + return this.value.length; + } + + [Symbol.iterator]() { + return this.value[Symbol.iterator](); + } + + toString() { + var i, + s = ""; + for (i = 0; i < this.count(); i++) { + if (s !== "") { + s += ", "; + } + s += this[i].toString(); + } + + return "<<" + s + ">>"; + } + + process() { + let processed_values = []; + + var i; + for (i = 0; i < this.raw_value().length; i++) { + let processed_value = this["process_" + this.raw_value()[i].type](this.raw_value()[i]); + + for (let attr of this.raw_value()[i].attributes) { + processed_value = this["process_" + attr](processed_value); + } + + processed_values = processed_values.concat(processed_value); + } + + return processed_values; + } + + process_integer(value) { + return value.value; + } + + process_float(value) { + if (value.size === 64) { + return BitString.float64ToBytes(value.value); + } else if (value.size === 32) { + return BitString.float32ToBytes(value.value); + } + + throw new Error("Invalid size for float"); + } + + process_bitstring(value) { + return value.value.value; + } + + process_binary(value) { + return BitString.toUTF8Array(value.value); + } + + process_utf8(value) { + return BitString.toUTF8Array(value.value); + } + + process_utf16(value) { + return BitString.toUTF16Array(value.value); + } + + process_utf32(value) { + return BitString.toUTF32Array(value.value); + } + + process_signed(value) { + return new Uint8Array([value])[0]; + } + + process_unsigned(value) { + return value; + } + + process_native(value) { + return value; + } + + process_big(value) { + return value; + } + + process_little(value) { + return value.reverse(); + } + + process_size(value) { + return value; + } + + process_unit(value) { + return value; + } + + static integer(value) { + return BitString.wrap(value, { "type": "integer", "unit": 1, "size": 8 }); + } + + static float(value) { + return BitString.wrap(value, { "type": "float", "unit": 1, "size": 64 }); + } + + static bitstring(value) { + return BitString.wrap(value, { "type": "bitstring", "unit": 1, "size": value.length }); + } + + static bits(value) { + return BitString.bitstring(value); + } + + static binary(value) { + return BitString.wrap(value, { "type": "binary", "unit": 8, "size": value.length }); + } + + static bytes(value) { + return BitString.binary(value); + } + + static utf8(value) { + return BitString.wrap(value, { "type": "utf8" }); + } + + static utf16(value) { + return BitString.wrap(value, { "type": "utf16" }); + } + + static utf32(value) { + return BitString.wrap(value, { "type": "utf32" }); + } + + static signed(value) { + return BitString.wrap(value, {}, "signed"); + } + + static unsigned(value) { + return BitString.wrap(value, {}, "unsigned"); + } + + static native(value) { + return BitString.wrap(value, {}, "native"); + } + + static big(value) { + return BitString.wrap(value, {}, "big"); + } + + static little(value) { + return BitString.wrap(value, {}, "little"); + } + + static size(value, count) { + return BitString.wrap(value, { "size": count }); + } + + static unit(value, count) { + return BitString.wrap(value, { "unit": count }); + } + + static wrap(value, opt, new_attribute = null) { + let the_value = value; + + if (!(value instanceof Object)) { + the_value = { "value": value, "attributes": [] }; + } + + the_value = Object.assign(the_value, opt); + + if (new_attribute) { + the_value.attributes.push(new_attribute); + } + + return the_value; + } + + static toUTF8Array(str) { + var utf8 = []; + for (var i = 0; i < str.length; i++) { + var charcode = str.charCodeAt(i); + if (charcode < 128) { + utf8.push(charcode); + } else if (charcode < 2048) { + utf8.push(192 | charcode >> 6, 128 | charcode & 63); + } else if (charcode < 55296 || charcode >= 57344) { + utf8.push(224 | charcode >> 12, 128 | charcode >> 6 & 63, 128 | charcode & 63); + } + // surrogate pair + else { + i++; + // UTF-16 encodes 0x10000-0x10FFFF by + // subtracting 0x10000 and splitting the + // 20 bits of 0x0-0xFFFFF into two halves + charcode = 65536 + ((charcode & 1023) << 10 | str.charCodeAt(i) & 1023); + utf8.push(240 | charcode >> 18, 128 | charcode >> 12 & 63, 128 | charcode >> 6 & 63, 128 | charcode & 63); + } + } + return utf8; + } + + static toUTF16Array(str) { + var utf16 = []; + for (var i = 0; i < str.length; i++) { + var codePoint = str.codePointAt(i); + + if (codePoint <= 255) { + utf16.push(0); + utf16.push(codePoint); + } else { + utf16.push(codePoint >> 8 & 255); + utf16.push(codePoint & 255); + } + } + return utf16; + } + + static toUTF32Array(str) { + var utf32 = []; + for (var i = 0; i < str.length; i++) { + var codePoint = str.codePointAt(i); + + if (codePoint <= 255) { + utf32.push(0); + utf32.push(0); + utf32.push(0); + utf32.push(codePoint); + } else { + utf32.push(0); + utf32.push(0); + utf32.push(codePoint >> 8 & 255); + utf32.push(codePoint & 255); + } + } + return utf32; + } + + //http://stackoverflow.com/questions/2003493/javascript-float-from-to-bits + static float32ToBytes(f) { + var bytes = []; + + var buf = new ArrayBuffer(4); + new Float32Array(buf)[0] = f; + + let intVersion = new Uint32Array(buf)[0]; + + bytes.push(intVersion >> 24 & 255); + bytes.push(intVersion >> 16 & 255); + bytes.push(intVersion >> 8 & 255); + bytes.push(intVersion & 255); + + return bytes; + } + + static float64ToBytes(f) { + var bytes = []; + + var buf = new ArrayBuffer(8); + new Float64Array(buf)[0] = f; + + var intVersion1 = new Uint32Array(buf)[0]; + var intVersion2 = new Uint32Array(buf)[1]; + + bytes.push(intVersion2 >> 24 & 255); + bytes.push(intVersion2 >> 16 & 255); + bytes.push(intVersion2 >> 8 & 255); + bytes.push(intVersion2 & 255); + + bytes.push(intVersion1 >> 24 & 255); + bytes.push(intVersion1 >> 16 & 255); + bytes.push(intVersion1 >> 8 & 255); + bytes.push(intVersion1 & 255); + + return bytes; + } +} + +let SpecialForms = { + + __DIR__: function () { + if (__dirname) { + return __dirname; + } + + if (document.currentScript) { + return document.currentScript.src; + } + + return null; + }, + + atom: function (_value) { + return Symbol.for(_value); + }, + + list: function (...args) { + return Object.freeze(args); + }, + + bitstring: function (...args) { + return new BitString(...args); + }, + + bound: function (_var) { + return Patterns.bound(_var); + }, + + _case: function (condition, clauses) { + return Patterns.defmatch(...clauses)(condition); + }, + + cond: function (clauses) { + for (let clause of clauses) { + if (clause[0]) { + return clause[1](); + } + } + + throw new Error(); + }, + + fn: function (clauses) { + return Patterns.defmatch(clauses); + }, + + map: function (obj) { + return Object.freeze(obj); + }, + + map_update: function (map, values) { + return Object.freeze(Object.assign(Object.create(map.constructor.prototype), map, values)); + }, + + _for: function (collections, fun, filter = () => true, into = [], previousValues = []) { + let pattern = collections[0][0]; + let collection = collections[0][1]; + + if (collections.length === 1) { + + for (let elem of collection) { + let r = Patterns.match_no_throw(pattern, elem); + let args = previousValues.concat(r); + + if (r && filter.apply(this, args)) { + into = Enum.into([fun.apply(this, args)], into); + } + } + + return into; + } else { + let _into = []; + + for (let elem of collection) { + let r = Patterns.match_no_throw(pattern, elem); + if (r) { + _into = Enum.into(this._for(collections.slice(1), fun, filter, _into, previousValues.concat(r)), into); + } + } + + return _into; + } + }, + + receive: function (receive_fun, timeout_in_ms = null, timeout_fn = time => true) { + if (timeout_in_ms == null || timeout_in_ms === System.for('infinity')) { + while (true) { + if (self.mailbox.length !== 0) { + let message = self.mailbox[0]; + self.mailbox = self.mailbox.slice(1); + return receive_fun(message); + } + } + } else if (timeout_in_ms === 0) { + if (self.mailbox.length !== 0) { + let message = self.mailbox[0]; + self.mailbox = self.mailbox.slice(1); + return receive_fun(message); + } else { + return null; + } + } else { + let now = Date.now(); + while (Date.now() < now + timeout_in_ms) { + if (self.mailbox.length !== 0) { + let message = self.mailbox[0]; + self.mailbox = self.mailbox.slice(1); + return receive_fun(message); + } + } + + return timeout_fn(timeout_in_ms); + } + }, + + tuple: function (...args) { + return new Tuple(...args); + }, + + _try: function (do_fun, rescue_function, catch_fun, else_function, after_function) { + let result = null; + + try { + result = do_fun(); + } catch (e) { + let ex_result = null; + + if (rescue_function) { + try { + ex_result = rescue_function(e); + return ex_result; + } catch (ex) { + if (ex instanceof Patterns.MatchError) { + throw ex; + } + } + } + + if (catch_fun) { + try { + ex_result = catch_fun(e); + return ex_result; + } catch (ex) { + if (ex instanceof Patterns.MatchError) { + throw ex; + } + } + } + + throw e; + } finally { + if (after_function) { + after_function(); + } + } + + if (else_function) { + try { + return else_function(result); + } catch (ex) { + if (ex instanceof Patterns.MatchError) { + throw new Error('No Match Found in Else'); + } + + throw ex; + } + } else { + return result; + } + } + +}; + +/* @flow */ + +let process_counter = -1; + +class PID { + constructor() { + process_counter = process_counter + 1; + this.id = process_counter; + } + + toString() { + return "PID#<0." + this.id + ".0>"; + } +} + +class IntegerType {} +class FloatType {} + +//https://github.com/airportyh/protomorphism +class Protocol { + constructor(spec) { + this.registry = new Map(); + this.fallback = null; + + for (let funName in spec) { + this[funName] = createFun(funName).bind(this); + } + + function createFun(funName) { + + return function (...args) { + let thing = args[0]; + let fun = null; + + if (Number.isInteger(thing) && this.hasImplementation(IntegerType)) { + fun = this.registry.get(IntegerType)[funName]; + } else if (typeof thing === "number" && !Number.isInteger(thing) && this.hasImplementation(FloatType)) { + fun = this.registry.get(FloatType)[funName]; + } else if (this.hasImplementation(thing)) { + fun = this.registry.get(thing.constructor)[funName]; + } else if (this.fallback) { + fun = this.fallback[funName]; + } + + if (fun != null) { + let retval = fun.apply(this, args); + return retval; + } + + throw new Error("No implementation found for " + thing); + }; + } + } + + implementation(type, implementation) { + if (type === null) { + this.fallback = implementation; + } else { + this.registry.set(type, implementation); + } + } + + hasImplementation(thing) { + return this.registry.has(thing.constructor); + } +} + +function tl(list) { + return SpecialForms.list(...list.slice(1)); +} + +function hd(list) { + return list[0]; +} + +function is_nil(x) { + return x === null; +} + +function is_atom(x) { + return typeof x === 'symbol'; +} + +function is_binary(x) { + return typeof x === 'string' || x instanceof String; +} + +function is_boolean(x) { + return typeof x === 'boolean' || x instanceof Boolean; +} + +function is_function(x, arity = -1) { + return typeof x === 'function' || x instanceof Function; +} + +function is_float(x) { + return is_number(x) && !Number.isInteger(x); +} + +function is_integer(x) { + return Number.isInteger(x); +} + +function is_list(x) { + return x instanceof Array; +} + +function is_map(x) { + return typeof x === 'object' || x instanceof Object; +} + +function is_number(x) { + return typeof x === 'number'; +} + +function is_tuple(x) { + return x instanceof Tuple; +} + +function _length(x) { + return x.length; +} + +function is_pid(x) { + return x instanceof PID; +} + +function is_port(x) { + return false; +} + +function is_reference(x) { + return false; +} + +function is_bitstring(x) { + return is_binary(x) || x instanceof BitString; +} + +function __in__(left, right) { + for (let x of right) { + if (match__qmark__(left, x)) { + return true; + } + } + + return false; +} + +function abs(number) { + return Math.abs(number); +} + +function round(number) { + return Math.round(number); +} + +function elem(tuple, index) { + if (is_list(tuple)) { + return tuple[index]; + } + + return tuple.get(index); +} + +function rem(left, right) { + return left % right; +} + +function div(left, right) { + return left / right; +} + +function and(left, right) { + return left && right; +} + +function or(left, right) { + return left || right; +} + +function not(arg) { + return !arg; +} + +function apply(...args) { + if (args.length === 3) { + let mod = args[0]; + let func = args[1]; + let func_args = args[2]; + return mod[func].apply(null, func_args); + } else { + let func = args[0]; + let func_args = args[1]; + + return func.apply(null, func_args); + } +} + +function to_string(arg) { + if (is_tuple(arg)) { + return Tuple.to_string(arg); + } + + return arg.toString(); +} + +function match__qmark__(pattern, expr, guard = () => true) { + return _Patterns.match_no_throw(pattern, expr, guard) != null; +} + +function defstruct(defaults) { + return class { + constructor(update = {}) { + let the_values = Object.assign(defaults, update); + Object.assign(this, the_values); + } + + static create(updates = {}) { + let x = new this(updates); + return Object.freeze(x); + } + }; +} + +function defexception(defaults) { + return class extends Error { + constructor(update = {}) { + let message = update.message || ''; + super(message); + + let the_values = Object.assign(defaults, update); + Object.assign(this, the_values); + + this.name = this.constructor.name; + this.message = message; + this[SpecialForms.atom('__exception__')] = true; + Error.captureStackTrace(this, this.constructor.name); + } + + static create(updates = {}) { + let x = new this(updates); + return Object.freeze(x); + } + }; +} + +function defprotocol(spec) { + return new Protocol(spec); +} + +function defimpl(protocol, type, impl) { + protocol.implementation(type, impl); +} + +var Kernel = { + SpecialForms, + tl, + hd, + is_nil, + is_atom, + is_binary, + is_boolean, + is_function, + is_float, + is_integer, + is_list, + is_map, + is_number, + is_tuple, + length: _length, + is_pid, + is_port, + is_reference, + is_bitstring, + in: __in__, + abs, + round, + elem, + rem, + div, + and, + or, + not, + apply, + to_string, + match__qmark__, + defstruct, + defprotocol, + defimpl +}; + +let Enum = { + + all__qmark__: function (collection, fun = x => x) { + for (let elem of collection) { + if (!fun(elem)) { + return false; + } + } + + return true; + }, + + any__qmark__: function (collection, fun = x => x) { + for (let elem of collection) { + if (fun(elem)) { + return true; + } + } + + return false; + }, + + at: function (collection, n, the_default = null) { + if (n > this.count(collection) || n < 0) { + return the_default; + } + + return collection[n]; + }, + + concat: function (...enumables) { + return enumables[0].concat(enumables[1]); + }, + + count: function (collection, fun = null) { + if (fun == null) { + return collection.length; + } else { + return collection.filter(fun).length; + } + }, + + drop: function (collection, count) { + return collection.slice(count); + }, + + drop_while: function (collection, fun) { + let count = 0; + + for (let elem of collection) { + if (fun(elem)) { + count = count + 1; + } else { + break; + } + } + + return collection.slice(count); + }, + + each: function (collection, fun) { + for (let elem of collection) { + fun(elem); + } + }, + + empty__qmark__: function (collection) { + return collection.length === 0; + }, + + fetch: function (collection, n) { + if (Kernel.is_list(collection)) { + if (n < this.count(collection) && n >= 0) { + return Kernel.SpecialForms.tuple(Kernel.SpecialForms.atom("ok"), collection[n]); + } else { + return Kernel.SpecialForms.atom("error"); + } + } + + throw new Error("collection is not an Enumerable"); + }, + + fetch__emark__: function (collection, n) { + if (Kernel.is_list(collection)) { + if (n < this.count(collection) && n >= 0) { + return collection[n]; + } else { + throw new Error("out of bounds error"); + } + } + + throw new Error("collection is not an Enumerable"); + }, + + filter: function (collection, fun) { + let result = []; + + for (let elem of collection) { + if (fun(elem)) { + result.push(elem); + } + } + + return result; + }, + + filter_map: function (collection, filter, mapper) { + return Enum.map(Enum.filter(collection, filter), mapper); + }, + + find: function (collection, if_none = null, fun) { + for (let elem of collection) { + if (fun(elem)) { + return elem; + } + } + + return if_none; + }, + + into: function (collection, list) { + return list.concat(collection); + }, + + map: function (collection, fun) { + let result = []; + + for (let elem of collection) { + result.push(fun(elem)); + } + + return result; + }, + + map_reduce: function (collection, acc, fun) { + let mapped = Kernel.SpecialForms.list(); + let the_acc = acc; + + for (var i = 0; i < this.count(collection); i++) { + let tuple = fun(collection[i], the_acc); + + the_acc = Kernel.elem(tuple, 1); + mapped = Kernel.SpecialForms.list(...mapped.concat([Kernel.elem(tuple, 0)])); + } + + return Kernel.SpecialForms.tuple(mapped, the_acc); + }, + + member: function (collection, value) { + return collection.includes(value); + }, + + reduce: function (collection, acc, fun) { + let the_acc = acc; + + for (var i = 0; i < this.count(collection); i++) { + let tuple = fun(collection[i], the_acc); + + the_acc = Kernel.elem(tuple, 1); + } + + return the_acc; + }, + + take: function (collection, count) { + return collection.slice(0, count); + }, + + take_every: function (collection, nth) { + let result = []; + let index = 0; + + for (let elem of collection) { + if (index % nth === 0) { + result.push(elem); + } + } + + return Kernel.SpecialForms.list(...result); + }, + + take_while: function (collection, fun) { + let count = 0; + + for (let elem of collection) { + if (fun(elem)) { + count = count + 1; + } else { + break; + } + } + + return collection.slice(0, count); + }, + + to_list: function (collection) { + return collection; + } +}; + +let Atom = {}; + +Atom.to_string = function (atom) { + return Symbol.keyFor(atom); +}; + +Atom.to_char_list = function (atom) { + return Atom.to_string(atom).split(''); +}; + +let Integer = { + + is_even: function (n) { + return n % 2 === 0; + }, + + is_odd: function (n) { + return n % 2 !== 0; + }, + + parse: function (bin) { + let result = parseInt(bin); + + if (isNaN(result)) { + return Kernel.SpecialForms.atom("error"); + } + + let indexOfDot = bin.indexOf("."); + + if (indexOfDot >= 0) { + return Kernel.SpecialForms.tuple(result, bin.substring(indexOfDot)); + } + + return Kernel.SpecialForms.tuple(result, ""); + }, + + to_char_list: function (number, base = 10) { + return number.toString(base).split(""); + }, + + to_string: function (number, base = 10) { + return number.toString(base); + } +}; + +let _Chars = Kernel.defprotocol({ + to_string: function (thing) {} +}); + +Kernel.defimpl(_Chars, BitString, { + to_string: function (thing) { + if (Kernel.is_binary(thing)) { + return thing; + } + + return thing.toString(); + } +}); + +Kernel.defimpl(_Chars, Symbol, { + to_string: function (thing) { + if (nil) { + return ""; + } + + return Atom.to_string(thing); + } +}); + +Kernel.defimpl(_Chars, IntegerType, { + to_string: function (thing) { + return Integer.to_string(thing); + } +}); + +Kernel.defimpl(_Chars, FloatType, { + to_string: function (thing) { + return thing.toString; + } +}); + +Kernel.defimpl(_Chars, Array, { + to_string: function (thing) { + return thing.toString(); + } +}); + +Kernel.defimpl(_Chars, Tuple, { + to_string: function (thing) { + return Tuple.to_string(thing); + } +}); + +Kernel.defimpl(_Chars, null, { + to_string: function (thing) { + return thing.toString(); + } +}); + +function to_atom(string) { + return Symbol.for(string); +} + +function to_existing_atom(string) { + return Symbol.for(string); +} + +function to_char_list(string) { + return string.split(''); +} + +function to_float(string) { + return parseFloat(string); +} + +function to_integer(string, base = 10) { + return parseInt(string, base); +} + +function upcase(binary) { + return binary.toUpperCase(); +} + +function downcase(binary) { + return binary.toLowerCase(); +} + +function at(string, position) { + if (position > string.length - 1) { + return null; + } + + return string[position]; +} + +function capitalize(string) { + let returnString = ''; + + for (let i = 0; i < string.length; i++) { + if (i === 0) { + returnString = returnString + string[i].toUpperCase(); + } else { + returnString = returnString + string[i].toLowerCase(); + } + } + + return returnString; +} + +function codepoints(string) { + return to_char_list(string).map(function (c) { + return c.codePointAt(0); + }); +} + +function contains__qm__(string, contains) { + if (Array.isArray(contains)) { + return contains.some(function (s) { + return string.indexOf(s) > -1; + }); + } + + return string.indexOf(contains) > -1; +} + +function duplicate(subject, n) { + return subject.repeat(n); +} + +function ends_with__qm__(string, suffixes) { + if (Array.isArray(suffixes)) { + return suffixes.some(function (s) { + return string.endsWith(s); + }); + } + + return string.endsWith(suffixes); +} + +function first(string) { + if (!string) { + return null; + } + + return string[0]; +} + +function graphemes(string) { + return string.split(''); +} + +function last(string) { + if (!string) { + return null; + } + + return string[string.length - 1]; +} + +function length(string) { + return string.length; +} + +function match__qm__(string, regex) { + return string.match(regex) != null; +} + +function next_codepoint(string) { + if (!string || string === '') { + return null; + } + + return Kernel.SpecialForms.tuple(string[0].codePointAt(0), string.substr(1)); +} + +function next_grapheme(string) { + if (!string || string === '') { + return null; + } + + return Kernel.SpecialForms.tuple(string[0], string.substr(1)); +} + +function reverse(string) { + let returnValue = ''; + + for (var i = string.length - 1; i >= 0; i--) { + returnValue = returnValue + string[i]; + }; + + return returnValue; +} + +function _split(string) { + return string.split(); +} + +function starts_with__qm__(string, prefixes) { + if (Array.isArray(prefixes)) { + return prefixes.some(function (s) { + return string.startsWith(s); + }); + } + + return string.startsWith(prefixes); +} + +function valid_character__qm__(codepoint) { + try { + return String.fromCodePoint(codepoint) != null; + } catch (e) { + return false; + } +} + +var _String = { + at, + capitalize, + codepoints, + contains__qm__, + downcase, + duplicate, + ends_with__qm__, + first, + graphemes, + last, + length, + match__qm__, + next_codepoint, + next_grapheme, + reverse, + split: _split, + starts_with__qm__, + to_atom, + to_char_list, + to_existing_atom, + to_float, + to_integer, + upcase, + valid_character__qm__, + Chars: _Chars +}; + +let Chars = Kernel.defprotocol({ + to_char_list: function (thing) {} +}); + +Kernel.defimpl(Chars, Kernel.is_bitstring, { + to_char_list: function (thing) { + if (Kernel.is_binary(thing)) { + return _String.to_char_list(thing); + } + + return thing.toString(); + } +}); + +Kernel.defimpl(Chars, Kernel.is_atom, { + to_char_list: function (thing) { + return Atom.to_char_list(thing); + } +}); + +Kernel.defimpl(Chars, Kernel.is_integer, { + to_char_list: function (thing) { + return Integer.to_char_list(thing); + } +}); + +Kernel.defimpl(Chars, Kernel.is_list, { + to_char_list: function (thing) { + return thing; + } +}); + +let List = {}; + +List.Chars = Chars; + +List.delete = function (list, item) { + let new_value = []; + let value_found = false; + + for (let x of list) { + if (x === item && value_found !== false) { + new_value.push(x); + value_found = true; + } else if (x !== item) { + new_value.push(x); + } + } + + return Kernel.SpecialForms.list(...new_value); +}; + +List.delete_at = function (list, index) { + let new_value = []; + + for (let i = 0; i < list.length; i++) { + if (i !== index) { + new_value.push(list[i]); + } + } + + return Kernel.SpecialForms.list(...new_value); +}; + +List.duplicate = function (elem, n) { + let new_value = []; + + for (var i = 0; i < n; i++) { + new_value.push(elem); + } + + return Kernel.SpecialForms.list(...new_value); +}; + +List.first = function (list) { + return list[0]; +}; + +List.flatten = function (list, tail = Kernel.SpecialForms.list()) { + let new_value = []; + + for (let x of list) { + if (Kernel.is_list(x)) { + new_value = new_value.concat(List.flatten(x)); + } else { + new_value.push(x); + } + } + + new_value = new_value.concat(tail); + + return Kernel.SpecialForms.list(...new_value); +}; + +List.foldl = function (list, acc, func) { + return list.reduce(func, acc); +}; + +List.foldr = function (list, acc, func) { + let new_acc = acc; + + for (var i = list.length - 1; i >= 0; i--) { + new_acc = func(list[i], new_acc); + } + + return new_acc; +}; + +List.insert_at = function (list, index, value) { + let new_value = []; + + for (let i = 0; i < list.length; i++) { + if (i === index) { + new_value.push(value); + new_value.push(list[i]); + } else { + new_value.push(list[i]); + } + } + + return Kernel.SpecialForms.list(...new_value); +}; + +List.keydelete = function (list, key, position) { + let new_list = []; + + for (let i = 0; i < list.length; i++) { + if (!Kernel.match__qmark__(list[i][position], key)) { + new_list.push(list[i]); + } + } + + return Kernel.SpecialForms.list(...new_list); +}; + +List.keyfind = function (list, key, position, _default = null) { + + for (let i = 0; i < list.length; i++) { + if (Kernel.match__qmark__(list[i][position], key)) { + return list[i]; + } + } + + return _default; +}; + +List.keymember__qmark__ = function (list, key, position) { + + for (let i = 0; i < list.length; i++) { + if (Kernel.match__qmark__(list[i][position], key)) { + return true; + } + } + + return false; +}; + +List.keyreplace = function (list, key, position, new_tuple) { + let new_list = []; + + for (let i = 0; i < list.length; i++) { + if (!Kernel.match__qmark__(list[i][position], key)) { + new_list.push(list[i]); + } else { + new_list.push(new_tuple); + } + } + + return Kernel.SpecialForms.list(...new_list); +}; + +List.keysort = function (list, position) { + let new_list = list; + + new_list.sort(function (a, b) { + if (position === 0) { + if (a[position].value < b[position].value) { + return -1; + } + + if (a[position].value > b[position].value) { + return 1; + } + + return 0; + } else { + if (a[position] < b[position]) { + return -1; + } + + if (a[position] > b[position]) { + return 1; + } + + return 0; + } + }); + + return Kernel.SpecialForms.list(...new_list); +}; + +List.keystore = function (list, key, position, new_tuple) { + let new_list = []; + let replaced = false; + + for (let i = 0; i < list.length; i++) { + if (!Kernel.match__qmark__(list[i][position], key)) { + new_list.push(list[i]); + } else { + new_list.push(new_tuple); + replaced = true; + } + } + + if (!replaced) { + new_list.push(new_tuple); + } + + return Kernel.SpecialForms.list(...new_list); +}; + +List.last = function (list) { + return list[list.length - 1]; +}; + +List.replace_at = function (list, index, value) { + let new_value = []; + + for (let i = 0; i < list.length; i++) { + if (i === index) { + new_value.push(value); + } else { + new_value.push(list[i]); + } + } + + return Kernel.SpecialForms.list(...new_value); +}; + +List.update_at = function (list, index, fun) { + let new_value = []; + + for (let i = 0; i < list.count(); i++) { + if (i === index) { + new_value.push(fun(list.get(i))); + } else { + new_value.push(list.get(i)); + } + } + + return new_value; +}; + +List.wrap = function (list) { + if (Kernel.is_list(list)) { + return list; + } else if (list == null) { + return Kernel.SpecialForms.list(); + } else { + return Kernel.SpecialForms.list(list); + } +}; + +List.zip = function (list_of_lists) { + if (list_of_lists.length === 0) { + return Kernel.SpecialForms.list(); + } + + let new_value = []; + let smallest_length = list_of_lists[0]; + + for (let x of list_of_lists) { + if (x.length < smallest_length) { + smallest_length = x.length; + } + } + + for (let i = 0; i < smallest_length; i++) { + let current_value = []; + for (let j = 0; j < list_of_lists.length; j++) { + current_value.push(list_of_lists[j][i]); + } + + new_value.push(Kernel.SpecialForms.tuple(...current_value)); + } + + return Kernel.SpecialForms.list(...new_value); +}; + +List.to_tuple = function (list) { + return Kernel.SpecialForms.tuple.apply(null, list); +}; + +List.append = function (list, value) { + return Kernel.SpecialForms.list(...list.concat([value])); +}; + +List.prepend = function (list, value) { + return Kernel.SpecialForms.list(...[value].concat(list)); +}; + +List.concat = function (left, right) { + return left.concat(right); +}; + +class Signal { + + constructor() { + this.bindings = SpecialForms.list(); + } + + add(listener, context = this) { + this.bindings = List.append(this.bindings, new SignalBinding(this, listener, context)); + } + + remove(listener) { + this.bindings = Enum.filter(this.bindings, function (binding) { + return binding.listener !== listener; + }); + } + + dispatch(...params) { + for (let binding of this.bindings) { + binding.execute(...params); + } + } + + dispose() { + for (let binding of this.bindings) { + binding.dispose(); + } + + this.bindings = null; + } +} + +class SignalBinding { + + constructor(signal, listener, context) { + this.listener = listener; + this.signal = signal; + this.context = context; + } + + execute(...params) { + this.listener.apply(this.context, params); + } + + dispose() { + this.listener = null; + this.signal = null; + this.context = null; + } +} + +function __update(map, key, value) { + let m = new Map(map); + m.set(key, value); + return m; +} + +function remove(map, key) { + let m = new Map(map); + m.delete(key); + return m; +} + +class MailBox { + + constructor(context = this) { + this.signal = new Signal(); + this.signal.add((...params) => this.messages = this.messages.concat(params), context); + this.messages = []; + } + + receive(...messages) { + this.signal.dispatch(...messages); + } + + peek() { + if (this.messages.length === 0) { + return null; + } + + return this.messages[0]; + } + + read() { + let result = this.messages[0]; + this.messages = this.messages.slice(1); + + return result; + } + + add_subscriber(fn, context = this) { + this.signal.add(fn, context); + } + + remove_subscriber(fn) { + this.signal.remove(fn); + } + + dispose() { + this.signal.dispose(); + this.messages = null; + } +} + +class PostOffice { + + constructor() { + this.mailboxes = new Map(); + } + + send(address, message) { + this.mailboxes.get(address).receive(message); + } + + receive(address) { + return this.mailboxes.get(address).read(); + } + + peek(address) { + return this.mailboxes.get(address).peek(); + } + + add_mailbox(address = Symbol(), context = this) { + this.mailboxes = __update(this.mailboxes, address, new MailBox()); + return address; + } + + remove_mailbox(address) { + this.mailboxes.get(address).dispose(); + this.mailboxes = remove(this.mailboxes, address); + } + + subscribe(address, subscribtion_fn, context = this) { + this.mailboxes.get(address).add_subscriber(subscribtion_fn, context); + } + + unsubscribe(address, subscribtion_fn) { + this.mailboxes.get(address).remove_subscriber(subscribtion_fn); + } +} + +function call_property(item, property) { + if (property in item) { + item[property]; + if (item[property] instanceof Function) { + return item[property](); + } else { + return item[property]; + } + } else if (Symbol.for(property) in item) { + let prop = Symbol.for(property); + if (item[prop] instanceof Function) { + return item[prop](); + } else { + return item[prop]; + } + } + + throw new Error(`Property ${ property } not found in ${ item }`); +} + +var JS = { + call_property +}; + +let Range = function (_first, _last) { + if (!(this instanceof Range)) { + return new Range(_first, _last); + } + + this.first = function () { + return _first; + }; + + this.last = function () { + return _last; + }; + + let _range = []; + + for (let i = _first; i <= _last; i++) { + _range.push(i); + } + + _range = Object.freeze(_range); + + this.value = function () { + return _range; + }; + + this.length = function () { + return _range.length; + }; + + return this; +}; + +Range.prototype[Symbol.iterator] = function () { + return this.value()[Symbol.iterator](); +}; + +Range.new = function (first, last) { + return Range(first, last); +}; + +Range.range__qmark__ = function (range) { + return range instanceof Range; +}; + +let Keyword = {}; + +Keyword.has_key__qm__ = function (keywords, key) { + for (let keyword of keywords) { + if (Kernel.elem(keyword, 0) == key) { + return true; + } + } + + return false; +}; + +Keyword.get = function (keywords, key, the_default = null) { + for (let keyword of keywords) { + if (Kernel.elem(keyword, 0) == key) { + return Kernel.elem(keyword, 1); + } + } + + return the_default; +}; + +let Agent = {}; + +Agent.start = function (fun, options = []) { + const name = Keyword.has_key__qm__(options, Kernel.SpecialForms.atom('name')) ? Keyword.get(options, Kernel.SpecialForms.atom('name')) : Symbol(); + + self.post_office.add_mailbox(name); + self.post_office.send(name, fun()); + + return Kernel.SpecialForms.tuple(Kernel.SpecialForms.atom('ok'), name); +}; + +Agent.stop = function (agent, timeout = 5000) { + self.post_office.remove_mailbox(agent); + return Kernel.SpecialForms.atom('ok'); +}; + +Agent.update = function (agent, fun, timeout = 5000) { + + const current_state = self.post_office.receive(agent); + self.post_office.send(agent, fun(current_state)); + + return Kernel.SpecialForms.atom('ok'); +}; + +Agent.get = function (agent, fun, timeout = 5000) { + return fun(self.post_office.peek(agent)); +}; + +Agent.get_and_update = function (agent, fun, timeout = 5000) { + + const get_and_update_tuple = fun(self.post_office.receive(agent)); + self.post_office.send(agent, Kernel.elem(get_and_update_tuple, 1)); + + return Kernel.elem(get_and_update_tuple, 0); +}; + +//https://developer.mozilla.org/en-US/docs/Web/API/WindowBase64/Base64_encoding_and_decoding#Solution_2_%E2%80%93_rewrite_the_DOMs_atob()_and_btoa()_using_JavaScript's_TypedArrays_and_UTF-8 +function b64EncodeUnicode(str) { + return btoa(encodeURIComponent(str).replace(/%([0-9A-F]{2})/g, function (match, p1) { + return String.fromCharCode('0x' + p1); + })); +} + +function encode64(data) { + return b64EncodeUnicode(data); +} + +function decode64(data) { + try { + return Kernel.SpecialForms.tuple(Kernel.SpecialForms.atom('ok'), atob(data)); + } catch (e) { + return Kernel.SpecialForms.atom('error'); + } + return btoa(data); +} + +function decode64__em__(data) { + return atob(data); +} + +var Base = { + encode64, + decode64, + decode64__em__ +}; + +function bnot(expr) { + return ~expr; +} + +function band(left, right) { + return left & right; +} + +function bor(left, right) { + return left | right; +} + +function bsl(left, right) { + return left << right; +} + +function bsr(left, right) { + return left >> right; +} + +function bxor(left, right) { + return left ^ right; +} + +var Bitwise = { + bnot, + band, + bor, + bsl, + bsr, + bxor +}; + +let Enumerable = Kernel.defprotocol({ + count: function (collection) {}, + member_qmark__: function (collection, value) {}, + reduce: function (collection, acc, fun) {} +}); + +let Collectable = Kernel.defprotocol({ + into: function (collectable) {} +}); + +let Inspect = Kernel.defprotocol({ + inspect: function (thing, opts) {} +}); + +function ___new__() { + return SpecialForms.map({}); +} + +function keys(map) { + return Object.keys(map); +} + +function __size(map) { + return keys(map).length; +} + +function __to_list(map) { + let map_keys = keys(map); + let list = []; + + for (let key of map_keys) { + list.push(SpecialForms.tuple(key, map[key])); + } + + return SpecialForms.list(...list); +} + +function values(map) { + let map_keys = keys(map); + let list = []; + + for (let key of map_keys) { + list.push(map[key]); + } + + return SpecialForms.list(...list); +} + +function from_struct(struct) { + let map = Object.assign({}, struct); + delete map[Symbol.for("__struct__")]; + + return SpecialForms.map(map); +} + +function ____delete__(map, key) { + let new_map = Object.assign({}, map); + + delete new_map[key]; + + return SpecialForms.map(new_map); +} + +function drop(map, keys) { + let new_map = Object.assign({}, map); + + for (let key of keys) { + delete new_map[key]; + } + + return SpecialForms.map(new_map); +} + +function __equal__qmark__(map1, map2) { + return map1 === map2; +} + +function fetch__emark__(map, key) { + if (key in map) { + return map[key]; + } + + throw new Error("Key not found."); +} + +function fetch(map, key) { + if (key in map) { + return SpecialForms.tuple(SpecialForms.atom("ok"), map[key]); + } + + return SpecialForms.atom("error"); +} + +function has_key__qmark__(map, key) { + return key in map; +} + +function merge(map1, map2) { + return SpecialForms.map_update(map1, map2); +} + +function split(map, keys) { + let split1 = {}; + let split2 = {}; + + for (let key of Object.keys(map)) { + if (keys.indexOf(key) > -1) { + split1[key] = map[key]; + } else { + split2[key] = map[key]; + } + } + + return SpecialForms.tuple(SpecialForms.map(split1), SpecialForms.map(split2)); +} + +function take(map, keys) { + let split1 = {}; + + for (let key of Object.keys(map)) { + if (keys.indexOf(key) > -1) { + split1[key] = map[key]; + } + } + + return SpecialForms.map(split1); +} + +function drop(map, keys) { + let split1 = {}; + + for (let key of Object.keys(map)) { + if (keys.indexOf(key) === -1) { + split1[key] = map[key]; + } + } + + return SpecialForms.map(split1); +} + +function put_new(map, key, value) { + if (key in map) { + return map; + } + + let new_map = Object.assign({}, map); + new_map[key] = value; + + return SpecialForms.map(new_map); +} + +function put_new_lazy(map, key, fun) { + if (key in map) { + return map; + } + + let new_map = Object.assign({}, map); + new_map[key] = fun(); + + return SpecialForms.map(new_map); +} + +function get_and_update(map, key, fun) { + if (key in map) { + return map; + } + + let new_map = Object.assign({}, map); + new_map[key] = fun(map[key]); + + return SpecialForms.map(new_map); +} + +function pop_lazy(map, key, fun) { + if (!key in map) { + return SpecialForms.tuple(fun(), map); + } + + let new_map = Object.assign({}, map); + let value = fun(new_map[key]); + delete new_map[key]; + + return SpecialForms.tuple(value, new_map); +} + +function pop(map, key, _default = null) { + if (!key in map) { + return SpecialForms.tuple(_default, map); + } + + let new_map = Object.assign({}, map); + let value = new_map[key]; + delete new_map[key]; + + return SpecialForms.tuple(value, new_map); +} + +function get_lazy(map, key, fun) { + if (!key in map) { + return fun(); + } + + return fun(map[key]); +} + +function get(map, key, _default = null) { + if (!key in map) { + return _default; + } + + return map[key]; +} + +function __put(map, key, val) { + let new_map = Object({}, map); + new_map[key] = val; + + return SpecialForms.map(new_map); +} + +function update__emark__(map, key, fun) { + if (!key in map) { + throw new Error("Key not found"); + } + + let new_map = Object({}, map); + new_map[key] = fun(map[key]); + + return SpecialForms.map(new_map); +} + +function _update(map, key, initial, fun) { + let new_map = Object({}, map); + + if (!key in map) { + new_map[key] = initial; + } else { + new_map[key] = fun(map[key]); + } + + return SpecialForms.map(new_map); +} + +var _Map = { + new: ___new__, + keys, + size: __size, + to_list: __to_list, + values, + from_struct, + delete: ____delete__, + drop, + equal__qmark__: __equal__qmark__, + fetch__emark__, + fetch, + has_key__qmark__, + split, + take, + put_new, + put_new_lazy, + get_and_update, + pop_lazy, + pop, + get_lazy, + get, + put: __put, + update__emark__, + update: _update +}; + +function __new__() { + return SpecialForms.map({ [Symbol.for('__struct__')]: Symbol.for('MapSet'), set: SpecialForms.list() }); +} + +function _size(map) { + return map.set.length; +} + +function _to_list(map) { + return map.set; +} + +function ___delete__(set, term) { + let new_list = List.delete(set.set, term); + + let new_map = Object.assign({}, set); + new_map.set = new_list; + return SpecialForms.map(new_map); +} + +function _put(set, term) { + if (set.set.indexOf(term) === -1) { + let new_list = List.append(set.set, term); + + let new_map = Object.assign({}, set); + new_map.set = new_list; + return SpecialForms.map(new_map); + } + + return set; +} + +function _difference(set1, set2) { + let new_map = Object.assign({}, set1); + + for (let val of set1.set) { + if (_member__qmark__(set2, val)) { + new_map.set = List.delete(new_map.set, val); + } + } + + return SpecialForms.map(new_map); +} + +function _intersection(set1, set2) { + let new_map = Object.assign({}, set1); + + for (let val of set1.set) { + if (!_member__qmark__(set2, val)) { + new_map.set = List.delete(new_map.set, val); + } + } + + return SpecialForms.map(new_map); +} + +function _union(set1, set2) { + let new_map = set1; + + for (let val of set2.set) { + new_map = _put(new_map, val); + } + + return SpecialForms.map(new_map); +} + +function _disjoin__qmark__(set1, set2) { + for (let val of set1.set) { + if (_member__qmark__(set2, val)) { + return false; + } + } + + return true; +} + +function _member__qmark__(set, value) { + return set.set.indexOf(value) >= 0; +} + +function _equal__qmark__(set1, set2) { + return set1.set === set2.set; +} + +function _subset__qmark__(set1, set2) { + for (let val of set1.set) { + if (!_member__qmark__(set2, val)) { + return false; + } + } + + return true; +} + +var MapSet = { + new: __new__, + size: _size, + to_list: _to_list, + disjoin__qmark__: _disjoin__qmark__, + delete: ___delete__, + subset__qmark__: _subset__qmark__, + equal__qmark__: _equal__qmark__, + member__qmark__: _member__qmark__, + put: _put, + union: _union, + intersection: _intersection, + difference: _difference +}; + +function size(map) { + return MapSet.size(map); +} + +function to_list(map) { + return MapSet.to_list(map); +} + +function __delete__(set, term) { + return MapSet.delete(set, term); +} + +function put(set, term) { + return MapSet.put(set, term); +} + +function difference(set1, set2) { + return MapSet.difference(set1, set2); +} + +function intersection(set1, set2) { + return MapSet.intersection(set1, set2); +} + +function union(set1, set2) { + return MapSet.union(set1, set2); +} + +function disjoin__qmark__(set1, set2) { + return MapSet.disjoin__qmark__(set1, set2); +} + +function member__qmark__(set, value) { + return MapSet.member__qmark__(set1, set2); +} + +function equal__qmark__(set1, set2) { + return MapSet.equal__qmark__(set1, set2); +} + +function subset__qmark__(set1, set2) { + return MapSet.subset__qmark__(set1, set2); +} + +var _Set = { + size, + to_list, + disjoin__qmark__, + delete: __delete__, + subset__qmark__, + equal__qmark__, + member__qmark__, + put, + union, + intersection, + difference +}; + +self.post_office = self.post_office || new PostOffice(); + +export { _Patterns as Patterns, BitString, Kernel, Atom, Enum, Integer, JS, List, Range, Tuple, Agent, Keyword, Base, _String as String, Bitwise, Enumerable, Collectable, Inspect, _Map as Map, _Set as Set, MapSet, IntegerType, FloatType }; +//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiIiwic291cmNlcyI6WyJlbGl4aXIuanMiXSwic291cmNlc0NvbnRlbnQiOlsidmFyIFBhdHRlcm5zID0ge1xuICBnZXQgZGVmYXVsdCAoKSB7IHJldHVybiBfUGF0dGVybnM7IH1cbn07XG5cbmNsYXNzIFR1cGxlIHtcblxuICBjb25zdHJ1Y3RvciguLi5hcmdzKSB7XG4gICAgdGhpcy52YWx1ZXMgPSBPYmplY3QuZnJlZXplKGFyZ3MpO1xuICB9XG5cbiAgZ2V0KGluZGV4KSB7XG4gICAgcmV0dXJuIHRoaXMudmFsdWVzW2luZGV4XTtcbiAgfVxuXG4gIGNvdW50KCkge1xuICAgIHJldHVybiB0aGlzLnZhbHVlcy5sZW5ndGg7XG4gIH1cblxuICBbU3ltYm9sLml0ZXJhdG9yXSgpIHtcbiAgICByZXR1cm4gdGhpcy52YWx1ZXNbU3ltYm9sLml0ZXJhdG9yXSgpO1xuICB9XG5cbiAgdG9TdHJpbmcoKSB7XG4gICAgdmFyIGksXG4gICAgICAgIHMgPSBcIlwiO1xuICAgIGZvciAoaSA9IDA7IGkgPCB0aGlzLnZhbHVlcy5sZW5ndGg7IGkrKykge1xuICAgICAgaWYgKHMgIT09IFwiXCIpIHtcbiAgICAgICAgcyArPSBcIiwgXCI7XG4gICAgICB9XG4gICAgICBzICs9IHRoaXMudmFsdWVzW2ldLnRvU3RyaW5nKCk7XG4gICAgfVxuXG4gICAgcmV0dXJuIFwie1wiICsgcyArIFwifVwiO1xuICB9XG5cbiAgc3RhdGljIHRvX3N0cmluZyh0dXBsZSkge1xuICAgIHJldHVybiB0dXBsZS50b1N0cmluZygpO1xuICB9XG5cbiAgc3RhdGljIGRlbGV0ZV9hdCh0dXBsZSwgaW5kZXgpIHtcbiAgICBsZXQgbmV3X2xpc3QgPSBbXTtcblxuICAgIGZvciAodmFyIGkgPSAwOyBpIDwgdHVwbGUuY291bnQoKTsgaSsrKSB7XG4gICAgICBpZiAoaSAhPT0gaW5kZXgpIHtcbiAgICAgICAgbmV3X2xpc3QucHVzaCh0dXBsZS5nZXQoaSkpO1xuICAgICAgfVxuICAgIH1cblxuICAgIHJldHVybiBLZXJuZWwuU3BlY2lhbEZvcm1zLnR1cGxlLmFwcGx5KG51bGwsIG5ld19saXN0KTtcbiAgfVxuXG4gIHN0YXRpYyBkdXBsaWNhdGUoZGF0YSwgc2l6ZSkge1xuICAgIGxldCBhcnJheSA9IFtdO1xuXG4gICAgZm9yICh2YXIgaSA9IHNpemUgLSAxOyBpID49IDA7IGktLSkge1xuICAgICAgYXJyYXkucHVzaChkYXRhKTtcbiAgICB9XG5cbiAgICByZXR1cm4gS2VybmVsLlNwZWNpYWxGb3Jtcy50dXBsZS5hcHBseShudWxsLCBhcnJheSk7XG4gIH1cblxuICBzdGF0aWMgaW5zZXJ0X2F0KHR1cGxlLCBpbmRleCwgdGVybSkge1xuICAgIGxldCBuZXdfdHVwbGUgPSBbXTtcblxuICAgIGZvciAodmFyIGkgPSAwOyBpIDw9IHR1cGxlLmNvdW50KCk7IGkrKykge1xuICAgICAgaWYgKGkgPT09IGluZGV4KSB7XG4gICAgICAgIG5ld190dXBsZS5wdXNoKHRlcm0pO1xuICAgICAgICBpKys7XG4gICAgICAgIG5ld190dXBsZS5wdXNoKHR1cGxlLmdldChpKSk7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBuZXdfdHVwbGUucHVzaCh0dXBsZS5nZXQoaSkpO1xuICAgICAgfVxuICAgIH1cblxuICAgIHJldHVybiBLZXJuZWwuU3BlY2lhbEZvcm1zLnR1cGxlLmFwcGx5KG51bGwsIG5ld190dXBsZSk7XG4gIH1cblxuICBzdGF0aWMgZnJvbV9saXN0KGxpc3QpIHtcbiAgICByZXR1cm4gS2VybmVsLlNwZWNpYWxGb3Jtcy50dXBsZS5hcHBseShudWxsLCBsaXN0KTtcbiAgfVxuXG4gIHN0YXRpYyB0b19saXN0KHR1cGxlKSB7XG4gICAgbGV0IG5ld19saXN0ID0gW107XG5cbiAgICBmb3IgKHZhciBpID0gMDsgaSA8IHR1cGxlLmNvdW50KCk7IGkrKykge1xuICAgICAgbmV3X2xpc3QucHVzaCh0dXBsZS5nZXQoaSkpO1xuICAgIH1cblxuICAgIHJldHVybiBLZXJuZWwuU3BlY2lhbEZvcm1zLmxpc3QoLi4ubmV3X2xpc3QpO1xuICB9XG59XG5cbi8qIEBmbG93ICovXG5cbmNsYXNzIFZhcmlhYmxlIHtcblxuICBjb25zdHJ1Y3RvcihuYW1lID0gbnVsbCkge1xuICAgIHRoaXMubmFtZSA9IG5hbWU7XG4gIH1cbn1cblxuY2xhc3MgV2lsZGNhcmQge1xuICBjb25zdHJ1Y3RvcigpIHt9XG59XG5cbmNsYXNzIFN0YXJ0c1dpdGgge1xuXG4gIGNvbnN0cnVjdG9yKHByZWZpeCkge1xuICAgIHRoaXMucHJlZml4ID0gcHJlZml4O1xuICB9XG59XG5cbmNsYXNzIENhcHR1cmUge1xuXG4gIGNvbnN0cnVjdG9yKHZhbHVlKSB7XG4gICAgdGhpcy52YWx1ZSA9IHZhbHVlO1xuICB9XG59XG5cbmNsYXNzIEhlYWRUYWlsIHtcbiAgY29uc3RydWN0b3IoKSB7fVxufVxuXG5jbGFzcyBUeXBlIHtcblxuICBjb25zdHJ1Y3Rvcih0eXBlLCBvYmpQYXR0ZXJuID0ge30pIHtcbiAgICB0aGlzLnR5cGUgPSB0eXBlO1xuICAgIHRoaXMub2JqUGF0dGVybiA9IG9ialBhdHRlcm47XG4gIH1cbn1cblxuY2xhc3MgQm91bmQge1xuXG4gIGNvbnN0cnVjdG9yKHZhbHVlKSB7XG4gICAgdGhpcy52YWx1ZSA9IHZhbHVlO1xuICB9XG59XG5cbmZ1bmN0aW9uIHZhcmlhYmxlKG5hbWUgPSBudWxsKSB7XG4gIHJldHVybiBuZXcgVmFyaWFibGUobmFtZSk7XG59XG5cbmZ1bmN0aW9uIHdpbGRjYXJkKCkge1xuICByZXR1cm4gbmV3IFdpbGRjYXJkKCk7XG59XG5cbmZ1bmN0aW9uIHN0YXJ0c1dpdGgocHJlZml4KSB7XG4gIHJldHVybiBuZXcgU3RhcnRzV2l0aChwcmVmaXgpO1xufVxuXG5mdW5jdGlvbiBjYXB0dXJlKHZhbHVlKSB7XG4gIHJldHVybiBuZXcgQ2FwdHVyZSh2YWx1ZSk7XG59XG5cbmZ1bmN0aW9uIGhlYWRUYWlsKCkge1xuICByZXR1cm4gbmV3IEhlYWRUYWlsKCk7XG59XG5cbmZ1bmN0aW9uIHR5cGUodHlwZSwgb2JqUGF0dGVybiA9IHt9KSB7XG4gIHJldHVybiBuZXcgVHlwZSh0eXBlLCBvYmpQYXR0ZXJuKTtcbn1cblxuZnVuY3Rpb24gYm91bmQodmFsdWUpIHtcbiAgcmV0dXJuIG5ldyBCb3VuZCh2YWx1ZSk7XG59XG5cbmZ1bmN0aW9uIF9pc19udW1iZXIodmFsdWUpIHtcbiAgcmV0dXJuIHR5cGVvZiB2YWx1ZSA9PT0gJ251bWJlcic7XG59XG5cbmZ1bmN0aW9uIGlzX3N0cmluZyh2YWx1ZSkge1xuICByZXR1cm4gdHlwZW9mIHZhbHVlID09PSAnc3RyaW5nJztcbn1cblxuZnVuY3Rpb24gX2lzX3R1cGxlKHZhbHVlKSB7XG4gIHJldHVybiB2YWx1ZSBpbnN0YW5jZW9mIFR1cGxlO1xufVxuXG5mdW5jdGlvbiBfaXNfYm9vbGVhbih2YWx1ZSkge1xuICByZXR1cm4gdHlwZW9mIHZhbHVlID09PSAnYm9vbGVhbic7XG59XG5cbmZ1bmN0aW9uIGlzX3N5bWJvbCh2YWx1ZSkge1xuICByZXR1cm4gdHlwZW9mIHZhbHVlID09PSAnc3ltYm9sJztcbn1cblxuZnVuY3Rpb24gaXNfbnVsbCh2YWx1ZSkge1xuICByZXR1cm4gdmFsdWUgPT09IG51bGw7XG59XG5cbmZ1bmN0aW9uIGlzX3VuZGVmaW5lZCh2YWx1ZSkge1xuICByZXR1cm4gdHlwZW9mIHZhbHVlID09PSAndW5kZWZpbmVkJztcbn1cblxuZnVuY3Rpb24gX2lzX2Z1bmN0aW9uKHZhbHVlKSB7XG4gIHJldHVybiBPYmplY3QucHJvdG90eXBlLnRvU3RyaW5nLmNhbGwodmFsdWUpID09ICdbb2JqZWN0IEZ1bmN0aW9uXSc7XG59XG5cbmZ1bmN0aW9uIGlzX3ZhcmlhYmxlKHZhbHVlKSB7XG4gIHJldHVybiB2YWx1ZSBpbnN0YW5jZW9mIFZhcmlhYmxlO1xufVxuXG5mdW5jdGlvbiBpc193aWxkY2FyZCh2YWx1ZSkge1xuICByZXR1cm4gdmFsdWUgaW5zdGFuY2VvZiBXaWxkY2FyZDtcbn1cblxuZnVuY3Rpb24gaXNfaGVhZFRhaWwodmFsdWUpIHtcbiAgcmV0dXJuIHZhbHVlIGluc3RhbmNlb2YgSGVhZFRhaWw7XG59XG5cbmZ1bmN0aW9uIGlzX2NhcHR1cmUodmFsdWUpIHtcbiAgcmV0dXJuIHZhbHVlIGluc3RhbmNlb2YgQ2FwdHVyZTtcbn1cblxuZnVuY3Rpb24gaXNfdHlwZSh2YWx1ZSkge1xuICByZXR1cm4gdmFsdWUgaW5zdGFuY2VvZiBUeXBlO1xufVxuXG5mdW5jdGlvbiBpc19zdGFydHNXaXRoKHZhbHVlKSB7XG4gIHJldHVybiB2YWx1ZSBpbnN0YW5jZW9mIFN0YXJ0c1dpdGg7XG59XG5cbmZ1bmN0aW9uIGlzX2JvdW5kKHZhbHVlKSB7XG4gIHJldHVybiB2YWx1ZSBpbnN0YW5jZW9mIEJvdW5kO1xufVxuXG5mdW5jdGlvbiBpc19vYmplY3QodmFsdWUpIHtcbiAgcmV0dXJuIHR5cGVvZiB2YWx1ZSA9PT0gJ29iamVjdCc7XG59XG5cbmZ1bmN0aW9uIGlzX2FycmF5KHZhbHVlKSB7XG4gIHJldHVybiBBcnJheS5pc0FycmF5KHZhbHVlKTtcbn1cblxudmFyIENoZWNrcyA9IHtcbiAgaXNfbnVtYmVyOiBfaXNfbnVtYmVyLFxuICBpc19zdHJpbmcsXG4gIGlzX2Jvb2xlYW46IF9pc19ib29sZWFuLFxuICBpc19zeW1ib2wsXG4gIGlzX251bGwsXG4gIGlzX3VuZGVmaW5lZCxcbiAgaXNfZnVuY3Rpb246IF9pc19mdW5jdGlvbixcbiAgaXNfdmFyaWFibGUsXG4gIGlzX3dpbGRjYXJkLFxuICBpc19oZWFkVGFpbCxcbiAgaXNfY2FwdHVyZSxcbiAgaXNfdHlwZSxcbiAgaXNfc3RhcnRzV2l0aCxcbiAgaXNfYm91bmQsXG4gIGlzX29iamVjdCxcbiAgaXNfYXJyYXksXG4gIGlzX3R1cGxlOiBfaXNfdHVwbGVcbn07XG5cbmZ1bmN0aW9uIHJlc29sdmVUdXBsZShwYXR0ZXJuKSB7XG4gIGxldCBtYXRjaGVzID0gW107XG5cbiAgZm9yIChsZXQgZWxlbSBvZiBwYXR0ZXJuKSB7XG4gICAgbWF0Y2hlcy5wdXNoKGJ1aWxkTWF0Y2goZWxlbSkpO1xuICB9XG5cbiAgcmV0dXJuIGZ1bmN0aW9uICh2YWx1ZSwgYXJncykge1xuICAgIGlmICghQ2hlY2tzLmlzX3R1cGxlKHZhbHVlKSB8fCB2YWx1ZS5jb3VudCgpICE9IHBhdHRlcm4uY291bnQoKSkge1xuICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH1cblxuICAgIHJldHVybiB2YWx1ZS52YWx1ZXMuZXZlcnkoZnVuY3Rpb24gKHYsIGkpIHtcbiAgICAgIHJldHVybiBtYXRjaGVzW2ldKHZhbHVlLmdldChpKSwgYXJncyk7XG4gICAgfSk7XG4gIH07XG59XG5cbmZ1bmN0aW9uIHJlc29sdmVTeW1ib2wocGF0dGVybikge1xuICByZXR1cm4gZnVuY3Rpb24gKHZhbHVlKSB7XG4gICAgcmV0dXJuIENoZWNrcy5pc19zeW1ib2wodmFsdWUpICYmIHZhbHVlID09PSBwYXR0ZXJuO1xuICB9O1xufVxuXG5mdW5jdGlvbiByZXNvbHZlU3RyaW5nKHBhdHRlcm4pIHtcbiAgcmV0dXJuIGZ1bmN0aW9uICh2YWx1ZSkge1xuICAgIHJldHVybiBDaGVja3MuaXNfc3RyaW5nKHZhbHVlKSAmJiB2YWx1ZSA9PT0gcGF0dGVybjtcbiAgfTtcbn1cblxuZnVuY3Rpb24gcmVzb2x2ZU51bWJlcihwYXR0ZXJuKSB7XG4gIHJldHVybiBmdW5jdGlvbiAodmFsdWUpIHtcbiAgICByZXR1cm4gQ2hlY2tzLmlzX251bWJlcih2YWx1ZSkgJiYgdmFsdWUgPT09IHBhdHRlcm47XG4gIH07XG59XG5cbmZ1bmN0aW9uIHJlc29sdmVCb29sZWFuKHBhdHRlcm4pIHtcbiAgcmV0dXJuIGZ1bmN0aW9uICh2YWx1ZSkge1xuICAgIHJldHVybiBDaGVja3MuaXNfYm9vbGVhbih2YWx1ZSkgJiYgdmFsdWUgPT09IHBhdHRlcm47XG4gIH07XG59XG5cbmZ1bmN0aW9uIHJlc29sdmVGdW5jdGlvbihwYXR0ZXJuKSB7XG4gIHJldHVybiBmdW5jdGlvbiAodmFsdWUpIHtcbiAgICByZXR1cm4gQ2hlY2tzLmlzX2Z1bmN0aW9uKHZhbHVlKSAmJiB2YWx1ZSA9PT0gcGF0dGVybjtcbiAgfTtcbn1cblxuZnVuY3Rpb24gcmVzb2x2ZU51bGwocGF0dGVybikge1xuICByZXR1cm4gZnVuY3Rpb24gKHZhbHVlKSB7XG4gICAgcmV0dXJuIENoZWNrcy5pc19udWxsKHZhbHVlKTtcbiAgfTtcbn1cblxuZnVuY3Rpb24gcmVzb2x2ZUJvdW5kKHBhdHRlcm4pIHtcbiAgcmV0dXJuIGZ1bmN0aW9uICh2YWx1ZSwgYXJncykge1xuICAgIGlmICh0eXBlb2YgdmFsdWUgPT09IHR5cGVvZiBwYXR0ZXJuLnZhbHVlICYmIHZhbHVlID09PSBwYXR0ZXJuLnZhbHVlKSB7XG4gICAgICBhcmdzLnB1c2godmFsdWUpO1xuICAgICAgcmV0dXJuIHRydWU7XG4gICAgfVxuXG4gICAgcmV0dXJuIGZhbHNlO1xuICB9O1xufVxuXG5mdW5jdGlvbiByZXNvbHZlV2lsZGNhcmQoKSB7XG4gIHJldHVybiBmdW5jdGlvbiAoKSB7XG4gICAgcmV0dXJuIHRydWU7XG4gIH07XG59XG5cbmZ1bmN0aW9uIHJlc29sdmVWYXJpYWJsZSgpIHtcbiAgcmV0dXJuIGZ1bmN0aW9uICh2YWx1ZSwgYXJncykge1xuICAgIGFyZ3MucHVzaCh2YWx1ZSk7XG4gICAgcmV0dXJuIHRydWU7XG4gIH07XG59XG5cbmZ1bmN0aW9uIHJlc29sdmVIZWFkVGFpbCgpIHtcbiAgcmV0dXJuIGZ1bmN0aW9uICh2YWx1ZSwgYXJncykge1xuICAgIGlmICghQ2hlY2tzLmlzX2FycmF5KHZhbHVlKSB8fCB2YWx1ZS5sZW5ndGggPCAyKSB7XG4gICAgICByZXR1cm4gZmFsc2U7XG4gICAgfVxuXG4gICAgY29uc3QgaGVhZCA9IHZhbHVlWzBdO1xuICAgIGNvbnN0IHRhaWwgPSB2YWx1ZS5zbGljZSgxKTtcblxuICAgIGFyZ3MucHVzaChoZWFkKTtcbiAgICBhcmdzLnB1c2godGFpbCk7XG5cbiAgICByZXR1cm4gdHJ1ZTtcbiAgfTtcbn1cblxuZnVuY3Rpb24gcmVzb2x2ZUNhcHR1cmUocGF0dGVybikge1xuICBjb25zdCBtYXRjaGVzID0gYnVpbGRNYXRjaChwYXR0ZXJuLnZhbHVlKTtcblxuICByZXR1cm4gZnVuY3Rpb24gKHZhbHVlLCBhcmdzKSB7XG4gICAgaWYgKG1hdGNoZXModmFsdWUsIGFyZ3MpKSB7XG4gICAgICBhcmdzLnB1c2godmFsdWUpO1xuICAgICAgcmV0dXJuIHRydWU7XG4gICAgfVxuXG4gICAgcmV0dXJuIGZhbHNlO1xuICB9O1xufVxuXG5mdW5jdGlvbiByZXNvbHZlU3RhcnRzV2l0aChwYXR0ZXJuKSB7XG4gIGNvbnN0IHByZWZpeCA9IHBhdHRlcm4ucHJlZml4O1xuXG4gIHJldHVybiBmdW5jdGlvbiAodmFsdWUsIGFyZ3MpIHtcbiAgICBpZiAoQ2hlY2tzLmlzX3N0cmluZyh2YWx1ZSkgJiYgdmFsdWUuc3RhcnRzV2l0aChwcmVmaXgpKSB7XG4gICAgICBhcmdzLnB1c2godmFsdWUuc3Vic3RyaW5nKHByZWZpeC5sZW5ndGgpKTtcbiAgICAgIHJldHVybiB0cnVlO1xuICAgIH1cblxuICAgIHJldHVybiBmYWxzZTtcbiAgfTtcbn1cblxuZnVuY3Rpb24gcmVzb2x2ZVR5cGUocGF0dGVybikge1xuICByZXR1cm4gZnVuY3Rpb24gKHZhbHVlLCBhcmdzKSB7XG4gICAgaWYgKHZhbHVlIGluc3RhbmNlb2YgcGF0dGVybi50eXBlKSB7XG4gICAgICBjb25zdCBtYXRjaGVzID0gYnVpbGRNYXRjaChwYXR0ZXJuLm9ialBhdHRlcm4pO1xuICAgICAgcmV0dXJuIG1hdGNoZXModmFsdWUsIGFyZ3MpICYmIGFyZ3MucHVzaCh2YWx1ZSkgPiAwO1xuICAgIH1cblxuICAgIHJldHVybiBmYWxzZTtcbiAgfTtcbn1cblxuZnVuY3Rpb24gcmVzb2x2ZUFycmF5KHBhdHRlcm4pIHtcbiAgY29uc3QgbWF0Y2hlcyA9IHBhdHRlcm4ubWFwKHggPT4gYnVpbGRNYXRjaCh4KSk7XG5cbiAgcmV0dXJuIGZ1bmN0aW9uICh2YWx1ZSwgYXJncykge1xuICAgIGlmICghQ2hlY2tzLmlzX2FycmF5KHZhbHVlKSB8fCB2YWx1ZS5sZW5ndGggIT0gcGF0dGVybi5sZW5ndGgpIHtcbiAgICAgIHJldHVybiBmYWxzZTtcbiAgICB9XG5cbiAgICByZXR1cm4gdmFsdWUuZXZlcnkoZnVuY3Rpb24gKHYsIGkpIHtcbiAgICAgIHJldHVybiBtYXRjaGVzW2ldKHZhbHVlW2ldLCBhcmdzKTtcbiAgICB9KTtcbiAgfTtcbn1cblxuZnVuY3Rpb24gcmVzb2x2ZU9iamVjdChwYXR0ZXJuKSB7XG4gIGxldCBtYXRjaGVzID0ge307XG5cbiAgZm9yIChsZXQga2V5IG9mIE9iamVjdC5rZXlzKHBhdHRlcm4pKSB7XG4gICAgbWF0Y2hlc1trZXldID0gYnVpbGRNYXRjaChwYXR0ZXJuW2tleV0pO1xuICB9XG5cbiAgcmV0dXJuIGZ1bmN0aW9uICh2YWx1ZSwgYXJncykge1xuICAgIGlmICghQ2hlY2tzLmlzX29iamVjdCh2YWx1ZSkgfHwgcGF0dGVybi5sZW5ndGggPiB2YWx1ZS5sZW5ndGgpIHtcbiAgICAgIHJldHVybiBmYWxzZTtcbiAgICB9XG5cbiAgICBmb3IgKGxldCBrZXkgb2YgT2JqZWN0LmtleXMocGF0dGVybikpIHtcbiAgICAgIGlmICghKGtleSBpbiB2YWx1ZSkgfHwgIW1hdGNoZXNba2V5XSh2YWx1ZVtrZXldLCBhcmdzKSkge1xuICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICB9XG4gICAgfVxuXG4gICAgcmV0dXJuIHRydWU7XG4gIH07XG59XG5cbmZ1bmN0aW9uIHJlc29sdmVOb01hdGNoKCkge1xuICByZXR1cm4gZnVuY3Rpb24gKCkge1xuICAgIHJldHVybiBmYWxzZTtcbiAgfTtcbn1cblxudmFyIFJlc29sdmVycyA9IHtcbiAgcmVzb2x2ZUJvdW5kLFxuICByZXNvbHZlV2lsZGNhcmQsXG4gIHJlc29sdmVWYXJpYWJsZSxcbiAgcmVzb2x2ZUhlYWRUYWlsLFxuICByZXNvbHZlQ2FwdHVyZSxcbiAgcmVzb2x2ZVN0YXJ0c1dpdGgsXG4gIHJlc29sdmVUeXBlLFxuICByZXNvbHZlQXJyYXksXG4gIHJlc29sdmVPYmplY3QsXG4gIHJlc29sdmVOb01hdGNoLFxuICByZXNvbHZlU3ltYm9sLFxuICByZXNvbHZlU3RyaW5nLFxuICByZXNvbHZlTnVtYmVyLFxuICByZXNvbHZlQm9vbGVhbixcbiAgcmVzb2x2ZUZ1bmN0aW9uLFxuICByZXNvbHZlTnVsbCxcbiAgcmVzb2x2ZVR1cGxlXG59O1xuXG5mdW5jdGlvbiBidWlsZE1hdGNoKHBhdHRlcm4pIHtcblxuICBpZiAoQ2hlY2tzLmlzX3R1cGxlKHBhdHRlcm4pKSB7XG4gICAgcmV0dXJuIFJlc29sdmVycy5yZXNvbHZlVHVwbGUocGF0dGVybik7XG4gIH1cblxuICBpZiAoQ2hlY2tzLmlzX3ZhcmlhYmxlKHBhdHRlcm4pKSB7XG4gICAgcmV0dXJuIFJlc29sdmVycy5yZXNvbHZlVmFyaWFibGUocGF0dGVybik7XG4gIH1cblxuICBpZiAoQ2hlY2tzLmlzX3dpbGRjYXJkKHBhdHRlcm4pKSB7XG4gICAgcmV0dXJuIFJlc29sdmVycy5yZXNvbHZlV2lsZGNhcmQocGF0dGVybik7XG4gIH1cblxuICBpZiAoQ2hlY2tzLmlzX3VuZGVmaW5lZChwYXR0ZXJuKSkge1xuICAgIHJldHVybiBSZXNvbHZlcnMucmVzb2x2ZVdpbGRjYXJkKHBhdHRlcm4pO1xuICB9XG5cbiAgaWYgKENoZWNrcy5pc19oZWFkVGFpbChwYXR0ZXJuKSkge1xuICAgIHJldHVybiBSZXNvbHZlcnMucmVzb2x2ZUhlYWRUYWlsKHBhdHRlcm4pO1xuICB9XG5cbiAgaWYgKENoZWNrcy5pc19zdGFydHNXaXRoKHBhdHRlcm4pKSB7XG4gICAgcmV0dXJuIFJlc29sdmVycy5yZXNvbHZlU3RhcnRzV2l0aChwYXR0ZXJuKTtcbiAgfVxuXG4gIGlmIChDaGVja3MuaXNfY2FwdHVyZShwYXR0ZXJuKSkge1xuICAgIHJldHVybiBSZXNvbHZlcnMucmVzb2x2ZUNhcHR1cmUocGF0dGVybik7XG4gIH1cblxuICBpZiAoQ2hlY2tzLmlzX2JvdW5kKHBhdHRlcm4pKSB7XG4gICAgcmV0dXJuIFJlc29sdmVycy5yZXNvbHZlQm91bmQocGF0dGVybik7XG4gIH1cblxuICBpZiAoQ2hlY2tzLmlzX3R5cGUocGF0dGVybikpIHtcbiAgICByZXR1cm4gUmVzb2x2ZXJzLnJlc29sdmVUeXBlKHBhdHRlcm4pO1xuICB9XG5cbiAgaWYgKENoZWNrcy5pc19hcnJheShwYXR0ZXJuKSkge1xuICAgIHJldHVybiBSZXNvbHZlcnMucmVzb2x2ZUFycmF5KHBhdHRlcm4pO1xuICB9XG5cbiAgaWYgKENoZWNrcy5pc19udW1iZXIocGF0dGVybikpIHtcbiAgICByZXR1cm4gUmVzb2x2ZXJzLnJlc29sdmVOdW1iZXIocGF0dGVybik7XG4gIH1cblxuICBpZiAoQ2hlY2tzLmlzX3N0cmluZyhwYXR0ZXJuKSkge1xuICAgIHJldHVybiBSZXNvbHZlcnMucmVzb2x2ZVN0cmluZyhwYXR0ZXJuKTtcbiAgfVxuXG4gIGlmIChDaGVja3MuaXNfYm9vbGVhbihwYXR0ZXJuKSkge1xuICAgIHJldHVybiBSZXNvbHZlcnMucmVzb2x2ZUJvb2xlYW4ocGF0dGVybik7XG4gIH1cblxuICBpZiAoQ2hlY2tzLmlzX3N5bWJvbChwYXR0ZXJuKSkge1xuICAgIHJldHVybiBSZXNvbHZlcnMucmVzb2x2ZVN5bWJvbChwYXR0ZXJuKTtcbiAgfVxuXG4gIGlmIChDaGVja3MuaXNfbnVsbChwYXR0ZXJuKSkge1xuICAgIHJldHVybiBSZXNvbHZlcnMucmVzb2x2ZU51bGwocGF0dGVybik7XG4gIH1cblxuICBpZiAoQ2hlY2tzLmlzX29iamVjdChwYXR0ZXJuKSkge1xuICAgIHJldHVybiBSZXNvbHZlcnMucmVzb2x2ZU9iamVjdChwYXR0ZXJuKTtcbiAgfVxuXG4gIHJldHVybiBSZXNvbHZlcnMucmVzb2x2ZU5vTWF0Y2goKTtcbn1cblxuY2xhc3MgTWF0Y2hFcnJvciBleHRlbmRzIEVycm9yIHtcbiAgY29uc3RydWN0b3IoYXJnKSB7XG4gICAgc3VwZXIoKTtcblxuICAgIGlmICh0eXBlb2YgYXJnID09PSAnc3ltYm9sJykge1xuICAgICAgdGhpcy5tZXNzYWdlID0gJ05vIG1hdGNoIGZvcjogJyArIGFyZy50b1N0cmluZygpO1xuICAgIH0gZWxzZSBpZiAoQXJyYXkuaXNBcnJheShhcmcpKSB7XG4gICAgICBsZXQgbWFwcGVkVmFsdWVzID0gYXJnLm1hcCh4ID0+IHgudG9TdHJpbmcoKSk7XG4gICAgICB0aGlzLm1lc3NhZ2UgPSAnTm8gbWF0Y2ggZm9yOiAnICsgbWFwcGVkVmFsdWVzO1xuICAgIH0gZWxzZSB7XG4gICAgICB0aGlzLm1lc3NhZ2UgPSAnTm8gbWF0Y2ggZm9yOiAnICsgYXJnO1xuICAgIH1cblxuICAgIHRoaXMuc3RhY2sgPSBuZXcgRXJyb3IoKS5zdGFjaztcbiAgICB0aGlzLm5hbWUgPSB0aGlzLmNvbnN0cnVjdG9yLm5hbWU7XG4gIH1cbn1cblxuY2xhc3MgQ2FzZSB7XG5cbiAgY29uc3RydWN0b3IocGF0dGVybiwgZm4sIGd1YXJkID0gKCkgPT4gdHJ1ZSkge1xuICAgIHRoaXMucGF0dGVybiA9IGJ1aWxkTWF0Y2gocGF0dGVybik7XG4gICAgdGhpcy5mbiA9IGZuO1xuICAgIHRoaXMuZ3VhcmQgPSBndWFyZDtcbiAgfVxufVxuXG5mdW5jdGlvbiBtYWtlX2Nhc2UocGF0dGVybiwgZm4sIGd1YXJkID0gKCkgPT4gdHJ1ZSkge1xuICByZXR1cm4gbmV3IENhc2UocGF0dGVybiwgZm4sIGd1YXJkKTtcbn1cblxuZnVuY3Rpb24gZGVmbWF0Y2goLi4uY2FzZXMpIHtcbiAgcmV0dXJuIGZ1bmN0aW9uICguLi5hcmdzKSB7XG4gICAgZm9yIChsZXQgcHJvY2Vzc2VkQ2FzZSBvZiBjYXNlcykge1xuICAgICAgbGV0IHJlc3VsdCA9IFtdO1xuICAgICAgaWYgKHByb2Nlc3NlZENhc2UucGF0dGVybihhcmdzLCByZXN1bHQpICYmIHByb2Nlc3NlZENhc2UuZ3VhcmQuYXBwbHkodGhpcywgcmVzdWx0KSkge1xuICAgICAgICByZXR1cm4gcHJvY2Vzc2VkQ2FzZS5mbi5hcHBseSh0aGlzLCByZXN1bHQpO1xuICAgICAgfVxuICAgIH1cblxuICAgIHRocm93IG5ldyBNYXRjaEVycm9yKGFyZ3MpO1xuICB9O1xufVxuXG5mdW5jdGlvbiBtYXRjaChwYXR0ZXJuLCBleHByLCBndWFyZCA9ICgpID0+IHRydWUpIHtcbiAgbGV0IHJlc3VsdCA9IFtdO1xuICBsZXQgcHJvY2Vzc2VkUGF0dGVybiA9IGJ1aWxkTWF0Y2gocGF0dGVybik7XG4gIGlmIChwcm9jZXNzZWRQYXR0ZXJuKGV4cHIsIHJlc3VsdCkgJiYgZ3VhcmQuYXBwbHkodGhpcywgcmVzdWx0KSkge1xuICAgIHJldHVybiByZXN1bHQ7XG4gIH0gZWxzZSB7XG4gICAgdGhyb3cgbmV3IE1hdGNoRXJyb3IoZXhwcik7XG4gIH1cbn1cblxuZnVuY3Rpb24gbWF0Y2hfbm9fdGhyb3cocGF0dGVybiwgZXhwciwgZ3VhcmQgPSAoKSA9PiB0cnVlKSB7XG4gIHRyeSB7XG4gICAgcmV0dXJuIG1hdGNoKHBhdHRlcm4sIGV4cHIsIGd1YXJkKTtcbiAgfSBjYXRjaCAoZSkge1xuICAgIGlmIChlIGluc3RhbmNlb2YgTWF0Y2hFcnJvcikge1xuICAgICAgcmV0dXJuIG51bGw7XG4gICAgfVxuXG4gICAgdGhyb3cgZTtcbiAgfVxufVxuXG5mdW5jdGlvbiBwYXR0ZXJuTWFwKGNvbGxlY3Rpb24sIHBhdHRlcm4sIGZ1biwgZ3VhcmQgPSAoKSA9PiB0cnVlKSB7XG4gIGxldCByZXQgPSBbXTtcblxuICBmb3IgKGxldCBlbGVtIG9mIGNvbGxlY3Rpb24pIHtcbiAgICB0cnkge1xuICAgICAgbGV0IHJlc3VsdCA9IGZ1bi5hcHBseSh0aGlzLCBtYXRjaChwYXR0ZXJuLCBlbGVtLCBndWFyZCkpO1xuICAgICAgcmV0ID0gcmV0LmNvbmNhdChyZXN1bHQpO1xuICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgIGlmICghKGUgaW5zdGFuY2VvZiBNYXRjaEVycm9yKSkge1xuICAgICAgICB0aHJvdyBlO1xuICAgICAgfVxuICAgIH1cbiAgfVxuXG4gIHJldHVybiByZXQ7XG59XG5cbnZhciBfUGF0dGVybnMgPSB7XG4gIGRlZm1hdGNoLCBtYXRjaCwgTWF0Y2hFcnJvciwgbWF0Y2hfbm9fdGhyb3csIHBhdHRlcm5NYXAsXG4gIHZhcmlhYmxlLCB3aWxkY2FyZCwgc3RhcnRzV2l0aCxcbiAgY2FwdHVyZSwgaGVhZFRhaWwsIHR5cGUsIGJvdW5kLCBDYXNlLCBtYWtlX2Nhc2Vcbn07XG5cbmNsYXNzIEJpdFN0cmluZyB7XG4gIGNvbnN0cnVjdG9yKC4uLmFyZ3MpIHtcbiAgICB0aGlzLnJhd192YWx1ZSA9IGZ1bmN0aW9uICgpIHtcbiAgICAgIHJldHVybiBPYmplY3QuZnJlZXplKGFyZ3MpO1xuICAgIH07XG5cbiAgICB0aGlzLnZhbHVlID0gT2JqZWN0LmZyZWV6ZSh0aGlzLnByb2Nlc3MoYXJncykpO1xuICB9XG5cbiAgZ2V0KGluZGV4KSB7XG4gICAgcmV0dXJuIHRoaXMudmFsdWVbaW5kZXhdO1xuICB9XG5cbiAgY291bnQoKSB7XG4gICAgcmV0dXJuIHRoaXMudmFsdWUubGVuZ3RoO1xuICB9XG5cbiAgW1N5bWJvbC5pdGVyYXRvcl0oKSB7XG4gICAgcmV0dXJuIHRoaXMudmFsdWVbU3ltYm9sLml0ZXJhdG9yXSgpO1xuICB9XG5cbiAgdG9TdHJpbmcoKSB7XG4gICAgdmFyIGksXG4gICAgICAgIHMgPSBcIlwiO1xuICAgIGZvciAoaSA9IDA7IGkgPCB0aGlzLmNvdW50KCk7IGkrKykge1xuICAgICAgaWYgKHMgIT09IFwiXCIpIHtcbiAgICAgICAgcyArPSBcIiwgXCI7XG4gICAgICB9XG4gICAgICBzICs9IHRoaXNbaV0udG9TdHJpbmcoKTtcbiAgICB9XG5cbiAgICByZXR1cm4gXCI8PFwiICsgcyArIFwiPj5cIjtcbiAgfVxuXG4gIHByb2Nlc3MoKSB7XG4gICAgbGV0IHByb2Nlc3NlZF92YWx1ZXMgPSBbXTtcblxuICAgIHZhciBpO1xuICAgIGZvciAoaSA9IDA7IGkgPCB0aGlzLnJhd192YWx1ZSgpLmxlbmd0aDsgaSsrKSB7XG4gICAgICBsZXQgcHJvY2Vzc2VkX3ZhbHVlID0gdGhpc1tcInByb2Nlc3NfXCIgKyB0aGlzLnJhd192YWx1ZSgpW2ldLnR5cGVdKHRoaXMucmF3X3ZhbHVlKClbaV0pO1xuXG4gICAgICBmb3IgKGxldCBhdHRyIG9mIHRoaXMucmF3X3ZhbHVlKClbaV0uYXR0cmlidXRlcykge1xuICAgICAgICBwcm9jZXNzZWRfdmFsdWUgPSB0aGlzW1wicHJvY2Vzc19cIiArIGF0dHJdKHByb2Nlc3NlZF92YWx1ZSk7XG4gICAgICB9XG5cbiAgICAgIHByb2Nlc3NlZF92YWx1ZXMgPSBwcm9jZXNzZWRfdmFsdWVzLmNvbmNhdChwcm9jZXNzZWRfdmFsdWUpO1xuICAgIH1cblxuICAgIHJldHVybiBwcm9jZXNzZWRfdmFsdWVzO1xuICB9XG5cbiAgcHJvY2Vzc19pbnRlZ2VyKHZhbHVlKSB7XG4gICAgcmV0dXJuIHZhbHVlLnZhbHVlO1xuICB9XG5cbiAgcHJvY2Vzc19mbG9hdCh2YWx1ZSkge1xuICAgIGlmICh2YWx1ZS5zaXplID09PSA2NCkge1xuICAgICAgcmV0dXJuIEJpdFN0cmluZy5mbG9hdDY0VG9CeXRlcyh2YWx1ZS52YWx1ZSk7XG4gICAgfSBlbHNlIGlmICh2YWx1ZS5zaXplID09PSAzMikge1xuICAgICAgcmV0dXJuIEJpdFN0cmluZy5mbG9hdDMyVG9CeXRlcyh2YWx1ZS52YWx1ZSk7XG4gICAgfVxuXG4gICAgdGhyb3cgbmV3IEVycm9yKFwiSW52YWxpZCBzaXplIGZvciBmbG9hdFwiKTtcbiAgfVxuXG4gIHByb2Nlc3NfYml0c3RyaW5nKHZhbHVlKSB7XG4gICAgcmV0dXJuIHZhbHVlLnZhbHVlLnZhbHVlO1xuICB9XG5cbiAgcHJvY2Vzc19iaW5hcnkodmFsdWUpIHtcbiAgICByZXR1cm4gQml0U3RyaW5nLnRvVVRGOEFycmF5KHZhbHVlLnZhbHVlKTtcbiAgfVxuXG4gIHByb2Nlc3NfdXRmOCh2YWx1ZSkge1xuICAgIHJldHVybiBCaXRTdHJpbmcudG9VVEY4QXJyYXkodmFsdWUudmFsdWUpO1xuICB9XG5cbiAgcHJvY2Vzc191dGYxNih2YWx1ZSkge1xuICAgIHJldHVybiBCaXRTdHJpbmcudG9VVEYxNkFycmF5KHZhbHVlLnZhbHVlKTtcbiAgfVxuXG4gIHByb2Nlc3NfdXRmMzIodmFsdWUpIHtcbiAgICByZXR1cm4gQml0U3RyaW5nLnRvVVRGMzJBcnJheSh2YWx1ZS52YWx1ZSk7XG4gIH1cblxuICBwcm9jZXNzX3NpZ25lZCh2YWx1ZSkge1xuICAgIHJldHVybiBuZXcgVWludDhBcnJheShbdmFsdWVdKVswXTtcbiAgfVxuXG4gIHByb2Nlc3NfdW5zaWduZWQodmFsdWUpIHtcbiAgICByZXR1cm4gdmFsdWU7XG4gIH1cblxuICBwcm9jZXNzX25hdGl2ZSh2YWx1ZSkge1xuICAgIHJldHVybiB2YWx1ZTtcbiAgfVxuXG4gIHByb2Nlc3NfYmlnKHZhbHVlKSB7XG4gICAgcmV0dXJuIHZhbHVlO1xuICB9XG5cbiAgcHJvY2Vzc19saXR0bGUodmFsdWUpIHtcbiAgICByZXR1cm4gdmFsdWUucmV2ZXJzZSgpO1xuICB9XG5cbiAgcHJvY2Vzc19zaXplKHZhbHVlKSB7XG4gICAgcmV0dXJuIHZhbHVlO1xuICB9XG5cbiAgcHJvY2Vzc191bml0KHZhbHVlKSB7XG4gICAgcmV0dXJuIHZhbHVlO1xuICB9XG5cbiAgc3RhdGljIGludGVnZXIodmFsdWUpIHtcbiAgICByZXR1cm4gQml0U3RyaW5nLndyYXAodmFsdWUsIHsgXCJ0eXBlXCI6IFwiaW50ZWdlclwiLCBcInVuaXRcIjogMSwgXCJzaXplXCI6IDggfSk7XG4gIH1cblxuICBzdGF0aWMgZmxvYXQodmFsdWUpIHtcbiAgICByZXR1cm4gQml0U3RyaW5nLndyYXAodmFsdWUsIHsgXCJ0eXBlXCI6IFwiZmxvYXRcIiwgXCJ1bml0XCI6IDEsIFwic2l6ZVwiOiA2NCB9KTtcbiAgfVxuXG4gIHN0YXRpYyBiaXRzdHJpbmcodmFsdWUpIHtcbiAgICByZXR1cm4gQml0U3RyaW5nLndyYXAodmFsdWUsIHsgXCJ0eXBlXCI6IFwiYml0c3RyaW5nXCIsIFwidW5pdFwiOiAxLCBcInNpemVcIjogdmFsdWUubGVuZ3RoIH0pO1xuICB9XG5cbiAgc3RhdGljIGJpdHModmFsdWUpIHtcbiAgICByZXR1cm4gQml0U3RyaW5nLmJpdHN0cmluZyh2YWx1ZSk7XG4gIH1cblxuICBzdGF0aWMgYmluYXJ5KHZhbHVlKSB7XG4gICAgcmV0dXJuIEJpdFN0cmluZy53cmFwKHZhbHVlLCB7IFwidHlwZVwiOiBcImJpbmFyeVwiLCBcInVuaXRcIjogOCwgXCJzaXplXCI6IHZhbHVlLmxlbmd0aCB9KTtcbiAgfVxuXG4gIHN0YXRpYyBieXRlcyh2YWx1ZSkge1xuICAgIHJldHVybiBCaXRTdHJpbmcuYmluYXJ5KHZhbHVlKTtcbiAgfVxuXG4gIHN0YXRpYyB1dGY4KHZhbHVlKSB7XG4gICAgcmV0dXJuIEJpdFN0cmluZy53cmFwKHZhbHVlLCB7IFwidHlwZVwiOiBcInV0ZjhcIiB9KTtcbiAgfVxuXG4gIHN0YXRpYyB1dGYxNih2YWx1ZSkge1xuICAgIHJldHVybiBCaXRTdHJpbmcud3JhcCh2YWx1ZSwgeyBcInR5cGVcIjogXCJ1dGYxNlwiIH0pO1xuICB9XG5cbiAgc3RhdGljIHV0ZjMyKHZhbHVlKSB7XG4gICAgcmV0dXJuIEJpdFN0cmluZy53cmFwKHZhbHVlLCB7IFwidHlwZVwiOiBcInV0ZjMyXCIgfSk7XG4gIH1cblxuICBzdGF0aWMgc2lnbmVkKHZhbHVlKSB7XG4gICAgcmV0dXJuIEJpdFN0cmluZy53cmFwKHZhbHVlLCB7fSwgXCJzaWduZWRcIik7XG4gIH1cblxuICBzdGF0aWMgdW5zaWduZWQodmFsdWUpIHtcbiAgICByZXR1cm4gQml0U3RyaW5nLndyYXAodmFsdWUsIHt9LCBcInVuc2lnbmVkXCIpO1xuICB9XG5cbiAgc3RhdGljIG5hdGl2ZSh2YWx1ZSkge1xuICAgIHJldHVybiBCaXRTdHJpbmcud3JhcCh2YWx1ZSwge30sIFwibmF0aXZlXCIpO1xuICB9XG5cbiAgc3RhdGljIGJpZyh2YWx1ZSkge1xuICAgIHJldHVybiBCaXRTdHJpbmcud3JhcCh2YWx1ZSwge30sIFwiYmlnXCIpO1xuICB9XG5cbiAgc3RhdGljIGxpdHRsZSh2YWx1ZSkge1xuICAgIHJldHVybiBCaXRTdHJpbmcud3JhcCh2YWx1ZSwge30sIFwibGl0dGxlXCIpO1xuICB9XG5cbiAgc3RhdGljIHNpemUodmFsdWUsIGNvdW50KSB7XG4gICAgcmV0dXJuIEJpdFN0cmluZy53cmFwKHZhbHVlLCB7IFwic2l6ZVwiOiBjb3VudCB9KTtcbiAgfVxuXG4gIHN0YXRpYyB1bml0KHZhbHVlLCBjb3VudCkge1xuICAgIHJldHVybiBCaXRTdHJpbmcud3JhcCh2YWx1ZSwgeyBcInVuaXRcIjogY291bnQgfSk7XG4gIH1cblxuICBzdGF0aWMgd3JhcCh2YWx1ZSwgb3B0LCBuZXdfYXR0cmlidXRlID0gbnVsbCkge1xuICAgIGxldCB0aGVfdmFsdWUgPSB2YWx1ZTtcblxuICAgIGlmICghKHZhbHVlIGluc3RhbmNlb2YgT2JqZWN0KSkge1xuICAgICAgdGhlX3ZhbHVlID0geyBcInZhbHVlXCI6IHZhbHVlLCBcImF0dHJpYnV0ZXNcIjogW10gfTtcbiAgICB9XG5cbiAgICB0aGVfdmFsdWUgPSBPYmplY3QuYXNzaWduKHRoZV92YWx1ZSwgb3B0KTtcblxuICAgIGlmIChuZXdfYXR0cmlidXRlKSB7XG4gICAgICB0aGVfdmFsdWUuYXR0cmlidXRlcy5wdXNoKG5ld19hdHRyaWJ1dGUpO1xuICAgIH1cblxuICAgIHJldHVybiB0aGVfdmFsdWU7XG4gIH1cblxuICBzdGF0aWMgdG9VVEY4QXJyYXkoc3RyKSB7XG4gICAgdmFyIHV0ZjggPSBbXTtcbiAgICBmb3IgKHZhciBpID0gMDsgaSA8IHN0ci5sZW5ndGg7IGkrKykge1xuICAgICAgdmFyIGNoYXJjb2RlID0gc3RyLmNoYXJDb2RlQXQoaSk7XG4gICAgICBpZiAoY2hhcmNvZGUgPCAxMjgpIHtcbiAgICAgICAgdXRmOC5wdXNoKGNoYXJjb2RlKTtcbiAgICAgIH0gZWxzZSBpZiAoY2hhcmNvZGUgPCAyMDQ4KSB7XG4gICAgICAgIHV0ZjgucHVzaCgxOTIgfCBjaGFyY29kZSA+PiA2LCAxMjggfCBjaGFyY29kZSAmIDYzKTtcbiAgICAgIH0gZWxzZSBpZiAoY2hhcmNvZGUgPCA1NTI5NiB8fCBjaGFyY29kZSA+PSA1NzM0NCkge1xuICAgICAgICB1dGY4LnB1c2goMjI0IHwgY2hhcmNvZGUgPj4gMTIsIDEyOCB8IGNoYXJjb2RlID4+IDYgJiA2MywgMTI4IHwgY2hhcmNvZGUgJiA2Myk7XG4gICAgICB9XG4gICAgICAvLyBzdXJyb2dhdGUgcGFpclxuICAgICAgZWxzZSB7XG4gICAgICAgIGkrKztcbiAgICAgICAgLy8gVVRGLTE2IGVuY29kZXMgMHgxMDAwMC0weDEwRkZGRiBieVxuICAgICAgICAvLyBzdWJ0cmFjdGluZyAweDEwMDAwIGFuZCBzcGxpdHRpbmcgdGhlXG4gICAgICAgIC8vIDIwIGJpdHMgb2YgMHgwLTB4RkZGRkYgaW50byB0d28gaGFsdmVzXG4gICAgICAgIGNoYXJjb2RlID0gNjU1MzYgKyAoKGNoYXJjb2RlICYgMTAyMykgPDwgMTAgfCBzdHIuY2hhckNvZGVBdChpKSAmIDEwMjMpO1xuICAgICAgICB1dGY4LnB1c2goMjQwIHwgY2hhcmNvZGUgPj4gMTgsIDEyOCB8IGNoYXJjb2RlID4+IDEyICYgNjMsIDEyOCB8IGNoYXJjb2RlID4+IDYgJiA2MywgMTI4IHwgY2hhcmNvZGUgJiA2Myk7XG4gICAgICB9XG4gICAgfVxuICAgIHJldHVybiB1dGY4O1xuICB9XG5cbiAgc3RhdGljIHRvVVRGMTZBcnJheShzdHIpIHtcbiAgICB2YXIgdXRmMTYgPSBbXTtcbiAgICBmb3IgKHZhciBpID0gMDsgaSA8IHN0ci5sZW5ndGg7IGkrKykge1xuICAgICAgdmFyIGNvZGVQb2ludCA9IHN0ci5jb2RlUG9pbnRBdChpKTtcblxuICAgICAgaWYgKGNvZGVQb2ludCA8PSAyNTUpIHtcbiAgICAgICAgdXRmMTYucHVzaCgwKTtcbiAgICAgICAgdXRmMTYucHVzaChjb2RlUG9pbnQpO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgdXRmMTYucHVzaChjb2RlUG9pbnQgPj4gOCAmIDI1NSk7XG4gICAgICAgIHV0ZjE2LnB1c2goY29kZVBvaW50ICYgMjU1KTtcbiAgICAgIH1cbiAgICB9XG4gICAgcmV0dXJuIHV0ZjE2O1xuICB9XG5cbiAgc3RhdGljIHRvVVRGMzJBcnJheShzdHIpIHtcbiAgICB2YXIgdXRmMzIgPSBbXTtcbiAgICBmb3IgKHZhciBpID0gMDsgaSA8IHN0ci5sZW5ndGg7IGkrKykge1xuICAgICAgdmFyIGNvZGVQb2ludCA9IHN0ci5jb2RlUG9pbnRBdChpKTtcblxuICAgICAgaWYgKGNvZGVQb2ludCA8PSAyNTUpIHtcbiAgICAgICAgdXRmMzIucHVzaCgwKTtcbiAgICAgICAgdXRmMzIucHVzaCgwKTtcbiAgICAgICAgdXRmMzIucHVzaCgwKTtcbiAgICAgICAgdXRmMzIucHVzaChjb2RlUG9pbnQpO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgdXRmMzIucHVzaCgwKTtcbiAgICAgICAgdXRmMzIucHVzaCgwKTtcbiAgICAgICAgdXRmMzIucHVzaChjb2RlUG9pbnQgPj4gOCAmIDI1NSk7XG4gICAgICAgIHV0ZjMyLnB1c2goY29kZVBvaW50ICYgMjU1KTtcbiAgICAgIH1cbiAgICB9XG4gICAgcmV0dXJuIHV0ZjMyO1xuICB9XG5cbiAgLy9odHRwOi8vc3RhY2tvdmVyZmxvdy5jb20vcXVlc3Rpb25zLzIwMDM0OTMvamF2YXNjcmlwdC1mbG9hdC1mcm9tLXRvLWJpdHNcbiAgc3RhdGljIGZsb2F0MzJUb0J5dGVzKGYpIHtcbiAgICB2YXIgYnl0ZXMgPSBbXTtcblxuICAgIHZhciBidWYgPSBuZXcgQXJyYXlCdWZmZXIoNCk7XG4gICAgbmV3IEZsb2F0MzJBcnJheShidWYpWzBdID0gZjtcblxuICAgIGxldCBpbnRWZXJzaW9uID0gbmV3IFVpbnQzMkFycmF5KGJ1ZilbMF07XG5cbiAgICBieXRlcy5wdXNoKGludFZlcnNpb24gPj4gMjQgJiAyNTUpO1xuICAgIGJ5dGVzLnB1c2goaW50VmVyc2lvbiA+PiAxNiAmIDI1NSk7XG4gICAgYnl0ZXMucHVzaChpbnRWZXJzaW9uID4+IDggJiAyNTUpO1xuICAgIGJ5dGVzLnB1c2goaW50VmVyc2lvbiAmIDI1NSk7XG5cbiAgICByZXR1cm4gYnl0ZXM7XG4gIH1cblxuICBzdGF0aWMgZmxvYXQ2NFRvQnl0ZXMoZikge1xuICAgIHZhciBieXRlcyA9IFtdO1xuXG4gICAgdmFyIGJ1ZiA9IG5ldyBBcnJheUJ1ZmZlcig4KTtcbiAgICBuZXcgRmxvYXQ2NEFycmF5KGJ1ZilbMF0gPSBmO1xuXG4gICAgdmFyIGludFZlcnNpb24xID0gbmV3IFVpbnQzMkFycmF5KGJ1ZilbMF07XG4gICAgdmFyIGludFZlcnNpb24yID0gbmV3IFVpbnQzMkFycmF5KGJ1ZilbMV07XG5cbiAgICBieXRlcy5wdXNoKGludFZlcnNpb24yID4+IDI0ICYgMjU1KTtcbiAgICBieXRlcy5wdXNoKGludFZlcnNpb24yID4+IDE2ICYgMjU1KTtcbiAgICBieXRlcy5wdXNoKGludFZlcnNpb24yID4+IDggJiAyNTUpO1xuICAgIGJ5dGVzLnB1c2goaW50VmVyc2lvbjIgJiAyNTUpO1xuXG4gICAgYnl0ZXMucHVzaChpbnRWZXJzaW9uMSA+PiAyNCAmIDI1NSk7XG4gICAgYnl0ZXMucHVzaChpbnRWZXJzaW9uMSA+PiAxNiAmIDI1NSk7XG4gICAgYnl0ZXMucHVzaChpbnRWZXJzaW9uMSA+PiA4ICYgMjU1KTtcbiAgICBieXRlcy5wdXNoKGludFZlcnNpb24xICYgMjU1KTtcblxuICAgIHJldHVybiBieXRlcztcbiAgfVxufVxuXG5sZXQgU3BlY2lhbEZvcm1zID0ge1xuXG4gIF9fRElSX186IGZ1bmN0aW9uICgpIHtcbiAgICBpZiAoX19kaXJuYW1lKSB7XG4gICAgICByZXR1cm4gX19kaXJuYW1lO1xuICAgIH1cblxuICAgIGlmIChkb2N1bWVudC5jdXJyZW50U2NyaXB0KSB7XG4gICAgICByZXR1cm4gZG9jdW1lbnQuY3VycmVudFNjcmlwdC5zcmM7XG4gICAgfVxuXG4gICAgcmV0dXJuIG51bGw7XG4gIH0sXG5cbiAgYXRvbTogZnVuY3Rpb24gKF92YWx1ZSkge1xuICAgIHJldHVybiBTeW1ib2wuZm9yKF92YWx1ZSk7XG4gIH0sXG5cbiAgbGlzdDogZnVuY3Rpb24gKC4uLmFyZ3MpIHtcbiAgICByZXR1cm4gT2JqZWN0LmZyZWV6ZShhcmdzKTtcbiAgfSxcblxuICBiaXRzdHJpbmc6IGZ1bmN0aW9uICguLi5hcmdzKSB7XG4gICAgcmV0dXJuIG5ldyBCaXRTdHJpbmcoLi4uYXJncyk7XG4gIH0sXG5cbiAgYm91bmQ6IGZ1bmN0aW9uIChfdmFyKSB7XG4gICAgcmV0dXJuIFBhdHRlcm5zLmJvdW5kKF92YXIpO1xuICB9LFxuXG4gIF9jYXNlOiBmdW5jdGlvbiAoY29uZGl0aW9uLCBjbGF1c2VzKSB7XG4gICAgcmV0dXJuIFBhdHRlcm5zLmRlZm1hdGNoKC4uLmNsYXVzZXMpKGNvbmRpdGlvbik7XG4gIH0sXG5cbiAgY29uZDogZnVuY3Rpb24gKGNsYXVzZXMpIHtcbiAgICBmb3IgKGxldCBjbGF1c2Ugb2YgY2xhdXNlcykge1xuICAgICAgaWYgKGNsYXVzZVswXSkge1xuICAgICAgICByZXR1cm4gY2xhdXNlWzFdKCk7XG4gICAgICB9XG4gICAgfVxuXG4gICAgdGhyb3cgbmV3IEVycm9yKCk7XG4gIH0sXG5cbiAgZm46IGZ1bmN0aW9uIChjbGF1c2VzKSB7XG4gICAgcmV0dXJuIFBhdHRlcm5zLmRlZm1hdGNoKGNsYXVzZXMpO1xuICB9LFxuXG4gIG1hcDogZnVuY3Rpb24gKG9iaikge1xuICAgIHJldHVybiBPYmplY3QuZnJlZXplKG9iaik7XG4gIH0sXG5cbiAgbWFwX3VwZGF0ZTogZnVuY3Rpb24gKG1hcCwgdmFsdWVzKSB7XG4gICAgcmV0dXJuIE9iamVjdC5mcmVlemUoT2JqZWN0LmFzc2lnbihPYmplY3QuY3JlYXRlKG1hcC5jb25zdHJ1Y3Rvci5wcm90b3R5cGUpLCBtYXAsIHZhbHVlcykpO1xuICB9LFxuXG4gIF9mb3I6IGZ1bmN0aW9uIChjb2xsZWN0aW9ucywgZnVuLCBmaWx0ZXIgPSAoKSA9PiB0cnVlLCBpbnRvID0gW10sIHByZXZpb3VzVmFsdWVzID0gW10pIHtcbiAgICBsZXQgcGF0dGVybiA9IGNvbGxlY3Rpb25zWzBdWzBdO1xuICAgIGxldCBjb2xsZWN0aW9uID0gY29sbGVjdGlvbnNbMF1bMV07XG5cbiAgICBpZiAoY29sbGVjdGlvbnMubGVuZ3RoID09PSAxKSB7XG5cbiAgICAgIGZvciAobGV0IGVsZW0gb2YgY29sbGVjdGlvbikge1xuICAgICAgICBsZXQgciA9IFBhdHRlcm5zLm1hdGNoX25vX3Rocm93KHBhdHRlcm4sIGVsZW0pO1xuICAgICAgICBsZXQgYXJncyA9IHByZXZpb3VzVmFsdWVzLmNvbmNhdChyKTtcblxuICAgICAgICBpZiAociAmJiBmaWx0ZXIuYXBwbHkodGhpcywgYXJncykpIHtcbiAgICAgICAgICBpbnRvID0gRW51bS5pbnRvKFtmdW4uYXBwbHkodGhpcywgYXJncyldLCBpbnRvKTtcbiAgICAgICAgfVxuICAgICAgfVxuXG4gICAgICByZXR1cm4gaW50bztcbiAgICB9IGVsc2Uge1xuICAgICAgbGV0IF9pbnRvID0gW107XG5cbiAgICAgIGZvciAobGV0IGVsZW0gb2YgY29sbGVjdGlvbikge1xuICAgICAgICBsZXQgciA9IFBhdHRlcm5zLm1hdGNoX25vX3Rocm93KHBhdHRlcm4sIGVsZW0pO1xuICAgICAgICBpZiAocikge1xuICAgICAgICAgIF9pbnRvID0gRW51bS5pbnRvKHRoaXMuX2Zvcihjb2xsZWN0aW9ucy5zbGljZSgxKSwgZnVuLCBmaWx0ZXIsIF9pbnRvLCBwcmV2aW91c1ZhbHVlcy5jb25jYXQocikpLCBpbnRvKTtcbiAgICAgICAgfVxuICAgICAgfVxuXG4gICAgICByZXR1cm4gX2ludG87XG4gICAgfVxuICB9LFxuXG4gIHJlY2VpdmU6IGZ1bmN0aW9uIChyZWNlaXZlX2Z1biwgdGltZW91dF9pbl9tcyA9IG51bGwsIHRpbWVvdXRfZm4gPSB0aW1lID0+IHRydWUpIHtcbiAgICBpZiAodGltZW91dF9pbl9tcyA9PSBudWxsIHx8IHRpbWVvdXRfaW5fbXMgPT09IFN5c3RlbS5mb3IoJ2luZmluaXR5JykpIHtcbiAgICAgIHdoaWxlICh0cnVlKSB7XG4gICAgICAgIGlmIChzZWxmLm1haWxib3gubGVuZ3RoICE9PSAwKSB7XG4gICAgICAgICAgbGV0IG1lc3NhZ2UgPSBzZWxmLm1haWxib3hbMF07XG4gICAgICAgICAgc2VsZi5tYWlsYm94ID0gc2VsZi5tYWlsYm94LnNsaWNlKDEpO1xuICAgICAgICAgIHJldHVybiByZWNlaXZlX2Z1bihtZXNzYWdlKTtcbiAgICAgICAgfVxuICAgICAgfVxuICAgIH0gZWxzZSBpZiAodGltZW91dF9pbl9tcyA9PT0gMCkge1xuICAgICAgaWYgKHNlbGYubWFpbGJveC5sZW5ndGggIT09IDApIHtcbiAgICAgICAgbGV0IG1lc3NhZ2UgPSBzZWxmLm1haWxib3hbMF07XG4gICAgICAgIHNlbGYubWFpbGJveCA9IHNlbGYubWFpbGJveC5zbGljZSgxKTtcbiAgICAgICAgcmV0dXJuIHJlY2VpdmVfZnVuKG1lc3NhZ2UpO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgcmV0dXJuIG51bGw7XG4gICAgICB9XG4gICAgfSBlbHNlIHtcbiAgICAgIGxldCBub3cgPSBEYXRlLm5vdygpO1xuICAgICAgd2hpbGUgKERhdGUubm93KCkgPCBub3cgKyB0aW1lb3V0X2luX21zKSB7XG4gICAgICAgIGlmIChzZWxmLm1haWxib3gubGVuZ3RoICE9PSAwKSB7XG4gICAgICAgICAgbGV0IG1lc3NhZ2UgPSBzZWxmLm1haWxib3hbMF07XG4gICAgICAgICAgc2VsZi5tYWlsYm94ID0gc2VsZi5tYWlsYm94LnNsaWNlKDEpO1xuICAgICAgICAgIHJldHVybiByZWNlaXZlX2Z1bihtZXNzYWdlKTtcbiAgICAgICAgfVxuICAgICAgfVxuXG4gICAgICByZXR1cm4gdGltZW91dF9mbih0aW1lb3V0X2luX21zKTtcbiAgICB9XG4gIH0sXG5cbiAgdHVwbGU6IGZ1bmN0aW9uICguLi5hcmdzKSB7XG4gICAgcmV0dXJuIG5ldyBUdXBsZSguLi5hcmdzKTtcbiAgfSxcblxuICBfdHJ5OiBmdW5jdGlvbiAoZG9fZnVuLCByZXNjdWVfZnVuY3Rpb24sIGNhdGNoX2Z1biwgZWxzZV9mdW5jdGlvbiwgYWZ0ZXJfZnVuY3Rpb24pIHtcbiAgICBsZXQgcmVzdWx0ID0gbnVsbDtcblxuICAgIHRyeSB7XG4gICAgICByZXN1bHQgPSBkb19mdW4oKTtcbiAgICB9IGNhdGNoIChlKSB7XG4gICAgICBsZXQgZXhfcmVzdWx0ID0gbnVsbDtcblxuICAgICAgaWYgKHJlc2N1ZV9mdW5jdGlvbikge1xuICAgICAgICB0cnkge1xuICAgICAgICAgIGV4X3Jlc3VsdCA9IHJlc2N1ZV9mdW5jdGlvbihlKTtcbiAgICAgICAgICByZXR1cm4gZXhfcmVzdWx0O1xuICAgICAgICB9IGNhdGNoIChleCkge1xuICAgICAgICAgIGlmIChleCBpbnN0YW5jZW9mIFBhdHRlcm5zLk1hdGNoRXJyb3IpIHtcbiAgICAgICAgICAgIHRocm93IGV4O1xuICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgfVxuXG4gICAgICBpZiAoY2F0Y2hfZnVuKSB7XG4gICAgICAgIHRyeSB7XG4gICAgICAgICAgZXhfcmVzdWx0ID0gY2F0Y2hfZnVuKGUpO1xuICAgICAgICAgIHJldHVybiBleF9yZXN1bHQ7XG4gICAgICAgIH0gY2F0Y2ggKGV4KSB7XG4gICAgICAgICAgaWYgKGV4IGluc3RhbmNlb2YgUGF0dGVybnMuTWF0Y2hFcnJvcikge1xuICAgICAgICAgICAgdGhyb3cgZXg7XG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICB9XG5cbiAgICAgIHRocm93IGU7XG4gICAgfSBmaW5hbGx5IHtcbiAgICAgIGlmIChhZnRlcl9mdW5jdGlvbikge1xuICAgICAgICBhZnRlcl9mdW5jdGlvbigpO1xuICAgICAgfVxuICAgIH1cblxuICAgIGlmIChlbHNlX2Z1bmN0aW9uKSB7XG4gICAgICB0cnkge1xuICAgICAgICByZXR1cm4gZWxzZV9mdW5jdGlvbihyZXN1bHQpO1xuICAgICAgfSBjYXRjaCAoZXgpIHtcbiAgICAgICAgaWYgKGV4IGluc3RhbmNlb2YgUGF0dGVybnMuTWF0Y2hFcnJvcikge1xuICAgICAgICAgIHRocm93IG5ldyBFcnJvcignTm8gTWF0Y2ggRm91bmQgaW4gRWxzZScpO1xuICAgICAgICB9XG5cbiAgICAgICAgdGhyb3cgZXg7XG4gICAgICB9XG4gICAgfSBlbHNlIHtcbiAgICAgIHJldHVybiByZXN1bHQ7XG4gICAgfVxuICB9XG5cbn07XG5cbi8qIEBmbG93ICovXG5cbmxldCBwcm9jZXNzX2NvdW50ZXIgPSAtMTtcblxuY2xhc3MgUElEIHtcbiAgY29uc3RydWN0b3IoKSB7XG4gICAgcHJvY2Vzc19jb3VudGVyID0gcHJvY2Vzc19jb3VudGVyICsgMTtcbiAgICB0aGlzLmlkID0gcHJvY2Vzc19jb3VudGVyO1xuICB9XG5cbiAgdG9TdHJpbmcoKSB7XG4gICAgcmV0dXJuIFwiUElEIzwwLlwiICsgdGhpcy5pZCArIFwiLjA+XCI7XG4gIH1cbn1cblxuY2xhc3MgSW50ZWdlclR5cGUge31cbmNsYXNzIEZsb2F0VHlwZSB7fVxuXG4vL2h0dHBzOi8vZ2l0aHViLmNvbS9haXJwb3J0eWgvcHJvdG9tb3JwaGlzbVxuY2xhc3MgUHJvdG9jb2wge1xuICBjb25zdHJ1Y3RvcihzcGVjKSB7XG4gICAgdGhpcy5yZWdpc3RyeSA9IG5ldyBNYXAoKTtcbiAgICB0aGlzLmZhbGxiYWNrID0gbnVsbDtcblxuICAgIGZvciAobGV0IGZ1bk5hbWUgaW4gc3BlYykge1xuICAgICAgdGhpc1tmdW5OYW1lXSA9IGNyZWF0ZUZ1bihmdW5OYW1lKS5iaW5kKHRoaXMpO1xuICAgIH1cblxuICAgIGZ1bmN0aW9uIGNyZWF0ZUZ1bihmdW5OYW1lKSB7XG5cbiAgICAgIHJldHVybiBmdW5jdGlvbiAoLi4uYXJncykge1xuICAgICAgICBsZXQgdGhpbmcgPSBhcmdzWzBdO1xuICAgICAgICBsZXQgZnVuID0gbnVsbDtcblxuICAgICAgICBpZiAoTnVtYmVyLmlzSW50ZWdlcih0aGluZykgJiYgdGhpcy5oYXNJbXBsZW1lbnRhdGlvbihJbnRlZ2VyVHlwZSkpIHtcbiAgICAgICAgICBmdW4gPSB0aGlzLnJlZ2lzdHJ5LmdldChJbnRlZ2VyVHlwZSlbZnVuTmFtZV07XG4gICAgICAgIH0gZWxzZSBpZiAodHlwZW9mIHRoaW5nID09PSBcIm51bWJlclwiICYmICFOdW1iZXIuaXNJbnRlZ2VyKHRoaW5nKSAmJiB0aGlzLmhhc0ltcGxlbWVudGF0aW9uKEZsb2F0VHlwZSkpIHtcbiAgICAgICAgICBmdW4gPSB0aGlzLnJlZ2lzdHJ5LmdldChGbG9hdFR5cGUpW2Z1bk5hbWVdO1xuICAgICAgICB9IGVsc2UgaWYgKHRoaXMuaGFzSW1wbGVtZW50YXRpb24odGhpbmcpKSB7XG4gICAgICAgICAgZnVuID0gdGhpcy5yZWdpc3RyeS5nZXQodGhpbmcuY29uc3RydWN0b3IpW2Z1bk5hbWVdO1xuICAgICAgICB9IGVsc2UgaWYgKHRoaXMuZmFsbGJhY2spIHtcbiAgICAgICAgICBmdW4gPSB0aGlzLmZhbGxiYWNrW2Z1bk5hbWVdO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKGZ1biAhPSBudWxsKSB7XG4gICAgICAgICAgbGV0IHJldHZhbCA9IGZ1bi5hcHBseSh0aGlzLCBhcmdzKTtcbiAgICAgICAgICByZXR1cm4gcmV0dmFsO1xuICAgICAgICB9XG5cbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKFwiTm8gaW1wbGVtZW50YXRpb24gZm91bmQgZm9yIFwiICsgdGhpbmcpO1xuICAgICAgfTtcbiAgICB9XG4gIH1cblxuICBpbXBsZW1lbnRhdGlvbih0eXBlLCBpbXBsZW1lbnRhdGlvbikge1xuICAgIGlmICh0eXBlID09PSBudWxsKSB7XG4gICAgICB0aGlzLmZhbGxiYWNrID0gaW1wbGVtZW50YXRpb247XG4gICAgfSBlbHNlIHtcbiAgICAgIHRoaXMucmVnaXN0cnkuc2V0KHR5cGUsIGltcGxlbWVudGF0aW9uKTtcbiAgICB9XG4gIH1cblxuICBoYXNJbXBsZW1lbnRhdGlvbih0aGluZykge1xuICAgIHJldHVybiB0aGlzLnJlZ2lzdHJ5Lmhhcyh0aGluZy5jb25zdHJ1Y3Rvcik7XG4gIH1cbn1cblxuZnVuY3Rpb24gdGwobGlzdCkge1xuICByZXR1cm4gU3BlY2lhbEZvcm1zLmxpc3QoLi4ubGlzdC5zbGljZSgxKSk7XG59XG5cbmZ1bmN0aW9uIGhkKGxpc3QpIHtcbiAgcmV0dXJuIGxpc3RbMF07XG59XG5cbmZ1bmN0aW9uIGlzX25pbCh4KSB7XG4gIHJldHVybiB4ID09PSBudWxsO1xufVxuXG5mdW5jdGlvbiBpc19hdG9tKHgpIHtcbiAgcmV0dXJuIHR5cGVvZiB4ID09PSAnc3ltYm9sJztcbn1cblxuZnVuY3Rpb24gaXNfYmluYXJ5KHgpIHtcbiAgcmV0dXJuIHR5cGVvZiB4ID09PSAnc3RyaW5nJyB8fCB4IGluc3RhbmNlb2YgU3RyaW5nO1xufVxuXG5mdW5jdGlvbiBpc19ib29sZWFuKHgpIHtcbiAgcmV0dXJuIHR5cGVvZiB4ID09PSAnYm9vbGVhbicgfHwgeCBpbnN0YW5jZW9mIEJvb2xlYW47XG59XG5cbmZ1bmN0aW9uIGlzX2Z1bmN0aW9uKHgsIGFyaXR5ID0gLTEpIHtcbiAgcmV0dXJuIHR5cGVvZiB4ID09PSAnZnVuY3Rpb24nIHx8IHggaW5zdGFuY2VvZiBGdW5jdGlvbjtcbn1cblxuZnVuY3Rpb24gaXNfZmxvYXQoeCkge1xuICByZXR1cm4gaXNfbnVtYmVyKHgpICYmICFOdW1iZXIuaXNJbnRlZ2VyKHgpO1xufVxuXG5mdW5jdGlvbiBpc19pbnRlZ2VyKHgpIHtcbiAgcmV0dXJuIE51bWJlci5pc0ludGVnZXIoeCk7XG59XG5cbmZ1bmN0aW9uIGlzX2xpc3QoeCkge1xuICByZXR1cm4geCBpbnN0YW5jZW9mIEFycmF5O1xufVxuXG5mdW5jdGlvbiBpc19tYXAoeCkge1xuICByZXR1cm4gdHlwZW9mIHggPT09ICdvYmplY3QnIHx8IHggaW5zdGFuY2VvZiBPYmplY3Q7XG59XG5cbmZ1bmN0aW9uIGlzX251bWJlcih4KSB7XG4gIHJldHVybiB0eXBlb2YgeCA9PT0gJ251bWJlcic7XG59XG5cbmZ1bmN0aW9uIGlzX3R1cGxlKHgpIHtcbiAgcmV0dXJuIHggaW5zdGFuY2VvZiBUdXBsZTtcbn1cblxuZnVuY3Rpb24gX2xlbmd0aCh4KSB7XG4gIHJldHVybiB4Lmxlbmd0aDtcbn1cblxuZnVuY3Rpb24gaXNfcGlkKHgpIHtcbiAgcmV0dXJuIHggaW5zdGFuY2VvZiBQSUQ7XG59XG5cbmZ1bmN0aW9uIGlzX3BvcnQoeCkge1xuICByZXR1cm4gZmFsc2U7XG59XG5cbmZ1bmN0aW9uIGlzX3JlZmVyZW5jZSh4KSB7XG4gIHJldHVybiBmYWxzZTtcbn1cblxuZnVuY3Rpb24gaXNfYml0c3RyaW5nKHgpIHtcbiAgcmV0dXJuIGlzX2JpbmFyeSh4KSB8fCB4IGluc3RhbmNlb2YgQml0U3RyaW5nO1xufVxuXG5mdW5jdGlvbiBfX2luX18obGVmdCwgcmlnaHQpIHtcbiAgZm9yIChsZXQgeCBvZiByaWdodCkge1xuICAgIGlmIChtYXRjaF9fcW1hcmtfXyhsZWZ0LCB4KSkge1xuICAgICAgcmV0dXJuIHRydWU7XG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIGZhbHNlO1xufVxuXG5mdW5jdGlvbiBhYnMobnVtYmVyKSB7XG4gIHJldHVybiBNYXRoLmFicyhudW1iZXIpO1xufVxuXG5mdW5jdGlvbiByb3VuZChudW1iZXIpIHtcbiAgcmV0dXJuIE1hdGgucm91bmQobnVtYmVyKTtcbn1cblxuZnVuY3Rpb24gZWxlbSh0dXBsZSwgaW5kZXgpIHtcbiAgaWYgKGlzX2xpc3QodHVwbGUpKSB7XG4gICAgcmV0dXJuIHR1cGxlW2luZGV4XTtcbiAgfVxuXG4gIHJldHVybiB0dXBsZS5nZXQoaW5kZXgpO1xufVxuXG5mdW5jdGlvbiByZW0obGVmdCwgcmlnaHQpIHtcbiAgcmV0dXJuIGxlZnQgJSByaWdodDtcbn1cblxuZnVuY3Rpb24gZGl2KGxlZnQsIHJpZ2h0KSB7XG4gIHJldHVybiBsZWZ0IC8gcmlnaHQ7XG59XG5cbmZ1bmN0aW9uIGFuZChsZWZ0LCByaWdodCkge1xuICByZXR1cm4gbGVmdCAmJiByaWdodDtcbn1cblxuZnVuY3Rpb24gb3IobGVmdCwgcmlnaHQpIHtcbiAgcmV0dXJuIGxlZnQgfHwgcmlnaHQ7XG59XG5cbmZ1bmN0aW9uIG5vdChhcmcpIHtcbiAgcmV0dXJuICFhcmc7XG59XG5cbmZ1bmN0aW9uIGFwcGx5KC4uLmFyZ3MpIHtcbiAgaWYgKGFyZ3MubGVuZ3RoID09PSAzKSB7XG4gICAgbGV0IG1vZCA9IGFyZ3NbMF07XG4gICAgbGV0IGZ1bmMgPSBhcmdzWzFdO1xuICAgIGxldCBmdW5jX2FyZ3MgPSBhcmdzWzJdO1xuICAgIHJldHVybiBtb2RbZnVuY10uYXBwbHkobnVsbCwgZnVuY19hcmdzKTtcbiAgfSBlbHNlIHtcbiAgICBsZXQgZnVuYyA9IGFyZ3NbMF07XG4gICAgbGV0IGZ1bmNfYXJncyA9IGFyZ3NbMV07XG5cbiAgICByZXR1cm4gZnVuYy5hcHBseShudWxsLCBmdW5jX2FyZ3MpO1xuICB9XG59XG5cbmZ1bmN0aW9uIHRvX3N0cmluZyhhcmcpIHtcbiAgaWYgKGlzX3R1cGxlKGFyZykpIHtcbiAgICByZXR1cm4gVHVwbGUudG9fc3RyaW5nKGFyZyk7XG4gIH1cblxuICByZXR1cm4gYXJnLnRvU3RyaW5nKCk7XG59XG5cbmZ1bmN0aW9uIG1hdGNoX19xbWFya19fKHBhdHRlcm4sIGV4cHIsIGd1YXJkID0gKCkgPT4gdHJ1ZSkge1xuICByZXR1cm4gX1BhdHRlcm5zLm1hdGNoX25vX3Rocm93KHBhdHRlcm4sIGV4cHIsIGd1YXJkKSAhPSBudWxsO1xufVxuXG5mdW5jdGlvbiBkZWZzdHJ1Y3QoZGVmYXVsdHMpIHtcbiAgcmV0dXJuIGNsYXNzIHtcbiAgICBjb25zdHJ1Y3Rvcih1cGRhdGUgPSB7fSkge1xuICAgICAgbGV0IHRoZV92YWx1ZXMgPSBPYmplY3QuYXNzaWduKGRlZmF1bHRzLCB1cGRhdGUpO1xuICAgICAgT2JqZWN0LmFzc2lnbih0aGlzLCB0aGVfdmFsdWVzKTtcbiAgICB9XG5cbiAgICBzdGF0aWMgY3JlYXRlKHVwZGF0ZXMgPSB7fSkge1xuICAgICAgbGV0IHggPSBuZXcgdGhpcyh1cGRhdGVzKTtcbiAgICAgIHJldHVybiBPYmplY3QuZnJlZXplKHgpO1xuICAgIH1cbiAgfTtcbn1cblxuZnVuY3Rpb24gZGVmZXhjZXB0aW9uKGRlZmF1bHRzKSB7XG4gIHJldHVybiBjbGFzcyBleHRlbmRzIEVycm9yIHtcbiAgICBjb25zdHJ1Y3Rvcih1cGRhdGUgPSB7fSkge1xuICAgICAgbGV0IG1lc3NhZ2UgPSB1cGRhdGUubWVzc2FnZSB8fCAnJztcbiAgICAgIHN1cGVyKG1lc3NhZ2UpO1xuXG4gICAgICBsZXQgdGhlX3ZhbHVlcyA9IE9iamVjdC5hc3NpZ24oZGVmYXVsdHMsIHVwZGF0ZSk7XG4gICAgICBPYmplY3QuYXNzaWduKHRoaXMsIHRoZV92YWx1ZXMpO1xuXG4gICAgICB0aGlzLm5hbWUgPSB0aGlzLmNvbnN0cnVjdG9yLm5hbWU7XG4gICAgICB0aGlzLm1lc3NhZ2UgPSBtZXNzYWdlO1xuICAgICAgdGhpc1tTcGVjaWFsRm9ybXMuYXRvbSgnX19leGNlcHRpb25fXycpXSA9IHRydWU7XG4gICAgICBFcnJvci5jYXB0dXJlU3RhY2tUcmFjZSh0aGlzLCB0aGlzLmNvbnN0cnVjdG9yLm5hbWUpO1xuICAgIH1cblxuICAgIHN0YXRpYyBjcmVhdGUodXBkYXRlcyA9IHt9KSB7XG4gICAgICBsZXQgeCA9IG5ldyB0aGlzKHVwZGF0ZXMpO1xuICAgICAgcmV0dXJuIE9iamVjdC5mcmVlemUoeCk7XG4gICAgfVxuICB9O1xufVxuXG5mdW5jdGlvbiBkZWZwcm90b2NvbChzcGVjKSB7XG4gIHJldHVybiBuZXcgUHJvdG9jb2woc3BlYyk7XG59XG5cbmZ1bmN0aW9uIGRlZmltcGwocHJvdG9jb2wsIHR5cGUsIGltcGwpIHtcbiAgcHJvdG9jb2wuaW1wbGVtZW50YXRpb24odHlwZSwgaW1wbCk7XG59XG5cbnZhciBLZXJuZWwgPSB7XG4gIFNwZWNpYWxGb3JtcyxcbiAgdGwsXG4gIGhkLFxuICBpc19uaWwsXG4gIGlzX2F0b20sXG4gIGlzX2JpbmFyeSxcbiAgaXNfYm9vbGVhbixcbiAgaXNfZnVuY3Rpb24sXG4gIGlzX2Zsb2F0LFxuICBpc19pbnRlZ2VyLFxuICBpc19saXN0LFxuICBpc19tYXAsXG4gIGlzX251bWJlcixcbiAgaXNfdHVwbGUsXG4gIGxlbmd0aDogX2xlbmd0aCxcbiAgaXNfcGlkLFxuICBpc19wb3J0LFxuICBpc19yZWZlcmVuY2UsXG4gIGlzX2JpdHN0cmluZyxcbiAgaW46IF9faW5fXyxcbiAgYWJzLFxuICByb3VuZCxcbiAgZWxlbSxcbiAgcmVtLFxuICBkaXYsXG4gIGFuZCxcbiAgb3IsXG4gIG5vdCxcbiAgYXBwbHksXG4gIHRvX3N0cmluZyxcbiAgbWF0Y2hfX3FtYXJrX18sXG4gIGRlZnN0cnVjdCxcbiAgZGVmcHJvdG9jb2wsXG4gIGRlZmltcGxcbn07XG5cbmxldCBFbnVtID0ge1xuXG4gIGFsbF9fcW1hcmtfXzogZnVuY3Rpb24gKGNvbGxlY3Rpb24sIGZ1biA9IHggPT4geCkge1xuICAgIGZvciAobGV0IGVsZW0gb2YgY29sbGVjdGlvbikge1xuICAgICAgaWYgKCFmdW4oZWxlbSkpIHtcbiAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgfVxuICAgIH1cblxuICAgIHJldHVybiB0cnVlO1xuICB9LFxuXG4gIGFueV9fcW1hcmtfXzogZnVuY3Rpb24gKGNvbGxlY3Rpb24sIGZ1biA9IHggPT4geCkge1xuICAgIGZvciAobGV0IGVsZW0gb2YgY29sbGVjdGlvbikge1xuICAgICAgaWYgKGZ1bihlbGVtKSkge1xuICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICByZXR1cm4gZmFsc2U7XG4gIH0sXG5cbiAgYXQ6IGZ1bmN0aW9uIChjb2xsZWN0aW9uLCBuLCB0aGVfZGVmYXVsdCA9IG51bGwpIHtcbiAgICBpZiAobiA+IHRoaXMuY291bnQoY29sbGVjdGlvbikgfHwgbiA8IDApIHtcbiAgICAgIHJldHVybiB0aGVfZGVmYXVsdDtcbiAgICB9XG5cbiAgICByZXR1cm4gY29sbGVjdGlvbltuXTtcbiAgfSxcblxuICBjb25jYXQ6IGZ1bmN0aW9uICguLi5lbnVtYWJsZXMpIHtcbiAgICByZXR1cm4gZW51bWFibGVzWzBdLmNvbmNhdChlbnVtYWJsZXNbMV0pO1xuICB9LFxuXG4gIGNvdW50OiBmdW5jdGlvbiAoY29sbGVjdGlvbiwgZnVuID0gbnVsbCkge1xuICAgIGlmIChmdW4gPT0gbnVsbCkge1xuICAgICAgcmV0dXJuIGNvbGxlY3Rpb24ubGVuZ3RoO1xuICAgIH0gZWxzZSB7XG4gICAgICByZXR1cm4gY29sbGVjdGlvbi5maWx0ZXIoZnVuKS5sZW5ndGg7XG4gICAgfVxuICB9LFxuXG4gIGRyb3A6IGZ1bmN0aW9uIChjb2xsZWN0aW9uLCBjb3VudCkge1xuICAgIHJldHVybiBjb2xsZWN0aW9uLnNsaWNlKGNvdW50KTtcbiAgfSxcblxuICBkcm9wX3doaWxlOiBmdW5jdGlvbiAoY29sbGVjdGlvbiwgZnVuKSB7XG4gICAgbGV0IGNvdW50ID0gMDtcblxuICAgIGZvciAobGV0IGVsZW0gb2YgY29sbGVjdGlvbikge1xuICAgICAgaWYgKGZ1bihlbGVtKSkge1xuICAgICAgICBjb3VudCA9IGNvdW50ICsgMTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIGJyZWFrO1xuICAgICAgfVxuICAgIH1cblxuICAgIHJldHVybiBjb2xsZWN0aW9uLnNsaWNlKGNvdW50KTtcbiAgfSxcblxuICBlYWNoOiBmdW5jdGlvbiAoY29sbGVjdGlvbiwgZnVuKSB7XG4gICAgZm9yIChsZXQgZWxlbSBvZiBjb2xsZWN0aW9uKSB7XG4gICAgICBmdW4oZWxlbSk7XG4gICAgfVxuICB9LFxuXG4gIGVtcHR5X19xbWFya19fOiBmdW5jdGlvbiAoY29sbGVjdGlvbikge1xuICAgIHJldHVybiBjb2xsZWN0aW9uLmxlbmd0aCA9PT0gMDtcbiAgfSxcblxuICBmZXRjaDogZnVuY3Rpb24gKGNvbGxlY3Rpb24sIG4pIHtcbiAgICBpZiAoS2VybmVsLmlzX2xpc3QoY29sbGVjdGlvbikpIHtcbiAgICAgIGlmIChuIDwgdGhpcy5jb3VudChjb2xsZWN0aW9uKSAmJiBuID49IDApIHtcbiAgICAgICAgcmV0dXJuIEtlcm5lbC5TcGVjaWFsRm9ybXMudHVwbGUoS2VybmVsLlNwZWNpYWxGb3Jtcy5hdG9tKFwib2tcIiksIGNvbGxlY3Rpb25bbl0pO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgcmV0dXJuIEtlcm5lbC5TcGVjaWFsRm9ybXMuYXRvbShcImVycm9yXCIpO1xuICAgICAgfVxuICAgIH1cblxuICAgIHRocm93IG5ldyBFcnJvcihcImNvbGxlY3Rpb24gaXMgbm90IGFuIEVudW1lcmFibGVcIik7XG4gIH0sXG5cbiAgZmV0Y2hfX2VtYXJrX186IGZ1bmN0aW9uIChjb2xsZWN0aW9uLCBuKSB7XG4gICAgaWYgKEtlcm5lbC5pc19saXN0KGNvbGxlY3Rpb24pKSB7XG4gICAgICBpZiAobiA8IHRoaXMuY291bnQoY29sbGVjdGlvbikgJiYgbiA+PSAwKSB7XG4gICAgICAgIHJldHVybiBjb2xsZWN0aW9uW25dO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKFwib3V0IG9mIGJvdW5kcyBlcnJvclwiKTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICB0aHJvdyBuZXcgRXJyb3IoXCJjb2xsZWN0aW9uIGlzIG5vdCBhbiBFbnVtZXJhYmxlXCIpO1xuICB9LFxuXG4gIGZpbHRlcjogZnVuY3Rpb24gKGNvbGxlY3Rpb24sIGZ1bikge1xuICAgIGxldCByZXN1bHQgPSBbXTtcblxuICAgIGZvciAobGV0IGVsZW0gb2YgY29sbGVjdGlvbikge1xuICAgICAgaWYgKGZ1bihlbGVtKSkge1xuICAgICAgICByZXN1bHQucHVzaChlbGVtKTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICByZXR1cm4gcmVzdWx0O1xuICB9LFxuXG4gIGZpbHRlcl9tYXA6IGZ1bmN0aW9uIChjb2xsZWN0aW9uLCBmaWx0ZXIsIG1hcHBlcikge1xuICAgIHJldHVybiBFbnVtLm1hcChFbnVtLmZpbHRlcihjb2xsZWN0aW9uLCBmaWx0ZXIpLCBtYXBwZXIpO1xuICB9LFxuXG4gIGZpbmQ6IGZ1bmN0aW9uIChjb2xsZWN0aW9uLCBpZl9ub25lID0gbnVsbCwgZnVuKSB7XG4gICAgZm9yIChsZXQgZWxlbSBvZiBjb2xsZWN0aW9uKSB7XG4gICAgICBpZiAoZnVuKGVsZW0pKSB7XG4gICAgICAgIHJldHVybiBlbGVtO1xuICAgICAgfVxuICAgIH1cblxuICAgIHJldHVybiBpZl9ub25lO1xuICB9LFxuXG4gIGludG86IGZ1bmN0aW9uIChjb2xsZWN0aW9uLCBsaXN0KSB7XG4gICAgcmV0dXJuIGxpc3QuY29uY2F0KGNvbGxlY3Rpb24pO1xuICB9LFxuXG4gIG1hcDogZnVuY3Rpb24gKGNvbGxlY3Rpb24sIGZ1bikge1xuICAgIGxldCByZXN1bHQgPSBbXTtcblxuICAgIGZvciAobGV0IGVsZW0gb2YgY29sbGVjdGlvbikge1xuICAgICAgcmVzdWx0LnB1c2goZnVuKGVsZW0pKTtcbiAgICB9XG5cbiAgICByZXR1cm4gcmVzdWx0O1xuICB9LFxuXG4gIG1hcF9yZWR1Y2U6IGZ1bmN0aW9uIChjb2xsZWN0aW9uLCBhY2MsIGZ1bikge1xuICAgIGxldCBtYXBwZWQgPSBLZXJuZWwuU3BlY2lhbEZvcm1zLmxpc3QoKTtcbiAgICBsZXQgdGhlX2FjYyA9IGFjYztcblxuICAgIGZvciAodmFyIGkgPSAwOyBpIDwgdGhpcy5jb3VudChjb2xsZWN0aW9uKTsgaSsrKSB7XG4gICAgICBsZXQgdHVwbGUgPSBmdW4oY29sbGVjdGlvbltpXSwgdGhlX2FjYyk7XG5cbiAgICAgIHRoZV9hY2MgPSBLZXJuZWwuZWxlbSh0dXBsZSwgMSk7XG4gICAgICBtYXBwZWQgPSBLZXJuZWwuU3BlY2lhbEZvcm1zLmxpc3QoLi4ubWFwcGVkLmNvbmNhdChbS2VybmVsLmVsZW0odHVwbGUsIDApXSkpO1xuICAgIH1cblxuICAgIHJldHVybiBLZXJuZWwuU3BlY2lhbEZvcm1zLnR1cGxlKG1hcHBlZCwgdGhlX2FjYyk7XG4gIH0sXG5cbiAgbWVtYmVyOiBmdW5jdGlvbiAoY29sbGVjdGlvbiwgdmFsdWUpIHtcbiAgICByZXR1cm4gY29sbGVjdGlvbi5pbmNsdWRlcyh2YWx1ZSk7XG4gIH0sXG5cbiAgcmVkdWNlOiBmdW5jdGlvbiAoY29sbGVjdGlvbiwgYWNjLCBmdW4pIHtcbiAgICBsZXQgdGhlX2FjYyA9IGFjYztcblxuICAgIGZvciAodmFyIGkgPSAwOyBpIDwgdGhpcy5jb3VudChjb2xsZWN0aW9uKTsgaSsrKSB7XG4gICAgICBsZXQgdHVwbGUgPSBmdW4oY29sbGVjdGlvbltpXSwgdGhlX2FjYyk7XG5cbiAgICAgIHRoZV9hY2MgPSBLZXJuZWwuZWxlbSh0dXBsZSwgMSk7XG4gICAgfVxuXG4gICAgcmV0dXJuIHRoZV9hY2M7XG4gIH0sXG5cbiAgdGFrZTogZnVuY3Rpb24gKGNvbGxlY3Rpb24sIGNvdW50KSB7XG4gICAgcmV0dXJuIGNvbGxlY3Rpb24uc2xpY2UoMCwgY291bnQpO1xuICB9LFxuXG4gIHRha2VfZXZlcnk6IGZ1bmN0aW9uIChjb2xsZWN0aW9uLCBudGgpIHtcbiAgICBsZXQgcmVzdWx0ID0gW107XG4gICAgbGV0IGluZGV4ID0gMDtcblxuICAgIGZvciAobGV0IGVsZW0gb2YgY29sbGVjdGlvbikge1xuICAgICAgaWYgKGluZGV4ICUgbnRoID09PSAwKSB7XG4gICAgICAgIHJlc3VsdC5wdXNoKGVsZW0pO1xuICAgICAgfVxuICAgIH1cblxuICAgIHJldHVybiBLZXJuZWwuU3BlY2lhbEZvcm1zLmxpc3QoLi4ucmVzdWx0KTtcbiAgfSxcblxuICB0YWtlX3doaWxlOiBmdW5jdGlvbiAoY29sbGVjdGlvbiwgZnVuKSB7XG4gICAgbGV0IGNvdW50ID0gMDtcblxuICAgIGZvciAobGV0IGVsZW0gb2YgY29sbGVjdGlvbikge1xuICAgICAgaWYgKGZ1bihlbGVtKSkge1xuICAgICAgICBjb3VudCA9IGNvdW50ICsgMTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIGJyZWFrO1xuICAgICAgfVxuICAgIH1cblxuICAgIHJldHVybiBjb2xsZWN0aW9uLnNsaWNlKDAsIGNvdW50KTtcbiAgfSxcblxuICB0b19saXN0OiBmdW5jdGlvbiAoY29sbGVjdGlvbikge1xuICAgIHJldHVybiBjb2xsZWN0aW9uO1xuICB9XG59O1xuXG5sZXQgQXRvbSA9IHt9O1xuXG5BdG9tLnRvX3N0cmluZyA9IGZ1bmN0aW9uIChhdG9tKSB7XG4gIHJldHVybiBTeW1ib2wua2V5Rm9yKGF0b20pO1xufTtcblxuQXRvbS50b19jaGFyX2xpc3QgPSBmdW5jdGlvbiAoYXRvbSkge1xuICByZXR1cm4gQXRvbS50b19zdHJpbmcoYXRvbSkuc3BsaXQoJycpO1xufTtcblxubGV0IEludGVnZXIgPSB7XG5cbiAgaXNfZXZlbjogZnVuY3Rpb24gKG4pIHtcbiAgICByZXR1cm4gbiAlIDIgPT09IDA7XG4gIH0sXG5cbiAgaXNfb2RkOiBmdW5jdGlvbiAobikge1xuICAgIHJldHVybiBuICUgMiAhPT0gMDtcbiAgfSxcblxuICBwYXJzZTogZnVuY3Rpb24gKGJpbikge1xuICAgIGxldCByZXN1bHQgPSBwYXJzZUludChiaW4pO1xuXG4gICAgaWYgKGlzTmFOKHJlc3VsdCkpIHtcbiAgICAgIHJldHVybiBLZXJuZWwuU3BlY2lhbEZvcm1zLmF0b20oXCJlcnJvclwiKTtcbiAgICB9XG5cbiAgICBsZXQgaW5kZXhPZkRvdCA9IGJpbi5pbmRleE9mKFwiLlwiKTtcblxuICAgIGlmIChpbmRleE9mRG90ID49IDApIHtcbiAgICAgIHJldHVybiBLZXJuZWwuU3BlY2lhbEZvcm1zLnR1cGxlKHJlc3VsdCwgYmluLnN1YnN0cmluZyhpbmRleE9mRG90KSk7XG4gICAgfVxuXG4gICAgcmV0dXJuIEtlcm5lbC5TcGVjaWFsRm9ybXMudHVwbGUocmVzdWx0LCBcIlwiKTtcbiAgfSxcblxuICB0b19jaGFyX2xpc3Q6IGZ1bmN0aW9uIChudW1iZXIsIGJhc2UgPSAxMCkge1xuICAgIHJldHVybiBudW1iZXIudG9TdHJpbmcoYmFzZSkuc3BsaXQoXCJcIik7XG4gIH0sXG5cbiAgdG9fc3RyaW5nOiBmdW5jdGlvbiAobnVtYmVyLCBiYXNlID0gMTApIHtcbiAgICByZXR1cm4gbnVtYmVyLnRvU3RyaW5nKGJhc2UpO1xuICB9XG59O1xuXG5sZXQgX0NoYXJzID0gS2VybmVsLmRlZnByb3RvY29sKHtcbiAgdG9fc3RyaW5nOiBmdW5jdGlvbiAodGhpbmcpIHt9XG59KTtcblxuS2VybmVsLmRlZmltcGwoX0NoYXJzLCBCaXRTdHJpbmcsIHtcbiAgdG9fc3RyaW5nOiBmdW5jdGlvbiAodGhpbmcpIHtcbiAgICBpZiAoS2VybmVsLmlzX2JpbmFyeSh0aGluZykpIHtcbiAgICAgIHJldHVybiB0aGluZztcbiAgICB9XG5cbiAgICByZXR1cm4gdGhpbmcudG9TdHJpbmcoKTtcbiAgfVxufSk7XG5cbktlcm5lbC5kZWZpbXBsKF9DaGFycywgU3ltYm9sLCB7XG4gIHRvX3N0cmluZzogZnVuY3Rpb24gKHRoaW5nKSB7XG4gICAgaWYgKG5pbCkge1xuICAgICAgcmV0dXJuIFwiXCI7XG4gICAgfVxuXG4gICAgcmV0dXJuIEF0b20udG9fc3RyaW5nKHRoaW5nKTtcbiAgfVxufSk7XG5cbktlcm5lbC5kZWZpbXBsKF9DaGFycywgSW50ZWdlclR5cGUsIHtcbiAgdG9fc3RyaW5nOiBmdW5jdGlvbiAodGhpbmcpIHtcbiAgICByZXR1cm4gSW50ZWdlci50b19zdHJpbmcodGhpbmcpO1xuICB9XG59KTtcblxuS2VybmVsLmRlZmltcGwoX0NoYXJzLCBGbG9hdFR5cGUsIHtcbiAgdG9fc3RyaW5nOiBmdW5jdGlvbiAodGhpbmcpIHtcbiAgICByZXR1cm4gdGhpbmcudG9TdHJpbmc7XG4gIH1cbn0pO1xuXG5LZXJuZWwuZGVmaW1wbChfQ2hhcnMsIEFycmF5LCB7XG4gIHRvX3N0cmluZzogZnVuY3Rpb24gKHRoaW5nKSB7XG4gICAgcmV0dXJuIHRoaW5nLnRvU3RyaW5nKCk7XG4gIH1cbn0pO1xuXG5LZXJuZWwuZGVmaW1wbChfQ2hhcnMsIFR1cGxlLCB7XG4gIHRvX3N0cmluZzogZnVuY3Rpb24gKHRoaW5nKSB7XG4gICAgcmV0dXJuIFR1cGxlLnRvX3N0cmluZyh0aGluZyk7XG4gIH1cbn0pO1xuXG5LZXJuZWwuZGVmaW1wbChfQ2hhcnMsIG51bGwsIHtcbiAgdG9fc3RyaW5nOiBmdW5jdGlvbiAodGhpbmcpIHtcbiAgICByZXR1cm4gdGhpbmcudG9TdHJpbmcoKTtcbiAgfVxufSk7XG5cbmZ1bmN0aW9uIHRvX2F0b20oc3RyaW5nKSB7XG4gIHJldHVybiBTeW1ib2wuZm9yKHN0cmluZyk7XG59XG5cbmZ1bmN0aW9uIHRvX2V4aXN0aW5nX2F0b20oc3RyaW5nKSB7XG4gIHJldHVybiBTeW1ib2wuZm9yKHN0cmluZyk7XG59XG5cbmZ1bmN0aW9uIHRvX2NoYXJfbGlzdChzdHJpbmcpIHtcbiAgcmV0dXJuIHN0cmluZy5zcGxpdCgnJyk7XG59XG5cbmZ1bmN0aW9uIHRvX2Zsb2F0KHN0cmluZykge1xuICByZXR1cm4gcGFyc2VGbG9hdChzdHJpbmcpO1xufVxuXG5mdW5jdGlvbiB0b19pbnRlZ2VyKHN0cmluZywgYmFzZSA9IDEwKSB7XG4gIHJldHVybiBwYXJzZUludChzdHJpbmcsIGJhc2UpO1xufVxuXG5mdW5jdGlvbiB1cGNhc2UoYmluYXJ5KSB7XG4gIHJldHVybiBiaW5hcnkudG9VcHBlckNhc2UoKTtcbn1cblxuZnVuY3Rpb24gZG93bmNhc2UoYmluYXJ5KSB7XG4gIHJldHVybiBiaW5hcnkudG9Mb3dlckNhc2UoKTtcbn1cblxuZnVuY3Rpb24gYXQoc3RyaW5nLCBwb3NpdGlvbikge1xuICBpZiAocG9zaXRpb24gPiBzdHJpbmcubGVuZ3RoIC0gMSkge1xuICAgIHJldHVybiBudWxsO1xuICB9XG5cbiAgcmV0dXJuIHN0cmluZ1twb3NpdGlvbl07XG59XG5cbmZ1bmN0aW9uIGNhcGl0YWxpemUoc3RyaW5nKSB7XG4gIGxldCByZXR1cm5TdHJpbmcgPSAnJztcblxuICBmb3IgKGxldCBpID0gMDsgaSA8IHN0cmluZy5sZW5ndGg7IGkrKykge1xuICAgIGlmIChpID09PSAwKSB7XG4gICAgICByZXR1cm5TdHJpbmcgPSByZXR1cm5TdHJpbmcgKyBzdHJpbmdbaV0udG9VcHBlckNhc2UoKTtcbiAgICB9IGVsc2Uge1xuICAgICAgcmV0dXJuU3RyaW5nID0gcmV0dXJuU3RyaW5nICsgc3RyaW5nW2ldLnRvTG93ZXJDYXNlKCk7XG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIHJldHVyblN0cmluZztcbn1cblxuZnVuY3Rpb24gY29kZXBvaW50cyhzdHJpbmcpIHtcbiAgcmV0dXJuIHRvX2NoYXJfbGlzdChzdHJpbmcpLm1hcChmdW5jdGlvbiAoYykge1xuICAgIHJldHVybiBjLmNvZGVQb2ludEF0KDApO1xuICB9KTtcbn1cblxuZnVuY3Rpb24gY29udGFpbnNfX3FtX18oc3RyaW5nLCBjb250YWlucykge1xuICBpZiAoQXJyYXkuaXNBcnJheShjb250YWlucykpIHtcbiAgICByZXR1cm4gY29udGFpbnMuc29tZShmdW5jdGlvbiAocykge1xuICAgICAgcmV0dXJuIHN0cmluZy5pbmRleE9mKHMpID4gLTE7XG4gICAgfSk7XG4gIH1cblxuICByZXR1cm4gc3RyaW5nLmluZGV4T2YoY29udGFpbnMpID4gLTE7XG59XG5cbmZ1bmN0aW9uIGR1cGxpY2F0ZShzdWJqZWN0LCBuKSB7XG4gIHJldHVybiBzdWJqZWN0LnJlcGVhdChuKTtcbn1cblxuZnVuY3Rpb24gZW5kc193aXRoX19xbV9fKHN0cmluZywgc3VmZml4ZXMpIHtcbiAgaWYgKEFycmF5LmlzQXJyYXkoc3VmZml4ZXMpKSB7XG4gICAgcmV0dXJuIHN1ZmZpeGVzLnNvbWUoZnVuY3Rpb24gKHMpIHtcbiAgICAgIHJldHVybiBzdHJpbmcuZW5kc1dpdGgocyk7XG4gICAgfSk7XG4gIH1cblxuICByZXR1cm4gc3RyaW5nLmVuZHNXaXRoKHN1ZmZpeGVzKTtcbn1cblxuZnVuY3Rpb24gZmlyc3Qoc3RyaW5nKSB7XG4gIGlmICghc3RyaW5nKSB7XG4gICAgcmV0dXJuIG51bGw7XG4gIH1cblxuICByZXR1cm4gc3RyaW5nWzBdO1xufVxuXG5mdW5jdGlvbiBncmFwaGVtZXMoc3RyaW5nKSB7XG4gIHJldHVybiBzdHJpbmcuc3BsaXQoJycpO1xufVxuXG5mdW5jdGlvbiBsYXN0KHN0cmluZykge1xuICBpZiAoIXN0cmluZykge1xuICAgIHJldHVybiBudWxsO1xuICB9XG5cbiAgcmV0dXJuIHN0cmluZ1tzdHJpbmcubGVuZ3RoIC0gMV07XG59XG5cbmZ1bmN0aW9uIGxlbmd0aChzdHJpbmcpIHtcbiAgcmV0dXJuIHN0cmluZy5sZW5ndGg7XG59XG5cbmZ1bmN0aW9uIG1hdGNoX19xbV9fKHN0cmluZywgcmVnZXgpIHtcbiAgcmV0dXJuIHN0cmluZy5tYXRjaChyZWdleCkgIT0gbnVsbDtcbn1cblxuZnVuY3Rpb24gbmV4dF9jb2RlcG9pbnQoc3RyaW5nKSB7XG4gIGlmICghc3RyaW5nIHx8IHN0cmluZyA9PT0gJycpIHtcbiAgICByZXR1cm4gbnVsbDtcbiAgfVxuXG4gIHJldHVybiBLZXJuZWwuU3BlY2lhbEZvcm1zLnR1cGxlKHN0cmluZ1swXS5jb2RlUG9pbnRBdCgwKSwgc3RyaW5nLnN1YnN0cigxKSk7XG59XG5cbmZ1bmN0aW9uIG5leHRfZ3JhcGhlbWUoc3RyaW5nKSB7XG4gIGlmICghc3RyaW5nIHx8IHN0cmluZyA9PT0gJycpIHtcbiAgICByZXR1cm4gbnVsbDtcbiAgfVxuXG4gIHJldHVybiBLZXJuZWwuU3BlY2lhbEZvcm1zLnR1cGxlKHN0cmluZ1swXSwgc3RyaW5nLnN1YnN0cigxKSk7XG59XG5cbmZ1bmN0aW9uIHJldmVyc2Uoc3RyaW5nKSB7XG4gIGxldCByZXR1cm5WYWx1ZSA9ICcnO1xuXG4gIGZvciAodmFyIGkgPSBzdHJpbmcubGVuZ3RoIC0gMTsgaSA+PSAwOyBpLS0pIHtcbiAgICByZXR1cm5WYWx1ZSA9IHJldHVyblZhbHVlICsgc3RyaW5nW2ldO1xuICB9O1xuXG4gIHJldHVybiByZXR1cm5WYWx1ZTtcbn1cblxuZnVuY3Rpb24gX3NwbGl0KHN0cmluZykge1xuICByZXR1cm4gc3RyaW5nLnNwbGl0KCk7XG59XG5cbmZ1bmN0aW9uIHN0YXJ0c193aXRoX19xbV9fKHN0cmluZywgcHJlZml4ZXMpIHtcbiAgaWYgKEFycmF5LmlzQXJyYXkocHJlZml4ZXMpKSB7XG4gICAgcmV0dXJuIHByZWZpeGVzLnNvbWUoZnVuY3Rpb24gKHMpIHtcbiAgICAgIHJldHVybiBzdHJpbmcuc3RhcnRzV2l0aChzKTtcbiAgICB9KTtcbiAgfVxuXG4gIHJldHVybiBzdHJpbmcuc3RhcnRzV2l0aChwcmVmaXhlcyk7XG59XG5cbmZ1bmN0aW9uIHZhbGlkX2NoYXJhY3Rlcl9fcW1fXyhjb2RlcG9pbnQpIHtcbiAgdHJ5IHtcbiAgICByZXR1cm4gU3RyaW5nLmZyb21Db2RlUG9pbnQoY29kZXBvaW50KSAhPSBudWxsO1xuICB9IGNhdGNoIChlKSB7XG4gICAgcmV0dXJuIGZhbHNlO1xuICB9XG59XG5cbnZhciBfU3RyaW5nID0ge1xuICBhdCxcbiAgY2FwaXRhbGl6ZSxcbiAgY29kZXBvaW50cyxcbiAgY29udGFpbnNfX3FtX18sXG4gIGRvd25jYXNlLFxuICBkdXBsaWNhdGUsXG4gIGVuZHNfd2l0aF9fcW1fXyxcbiAgZmlyc3QsXG4gIGdyYXBoZW1lcyxcbiAgbGFzdCxcbiAgbGVuZ3RoLFxuICBtYXRjaF9fcW1fXyxcbiAgbmV4dF9jb2RlcG9pbnQsXG4gIG5leHRfZ3JhcGhlbWUsXG4gIHJldmVyc2UsXG4gIHNwbGl0OiBfc3BsaXQsXG4gIHN0YXJ0c193aXRoX19xbV9fLFxuICB0b19hdG9tLFxuICB0b19jaGFyX2xpc3QsXG4gIHRvX2V4aXN0aW5nX2F0b20sXG4gIHRvX2Zsb2F0LFxuICB0b19pbnRlZ2VyLFxuICB1cGNhc2UsXG4gIHZhbGlkX2NoYXJhY3Rlcl9fcW1fXyxcbiAgQ2hhcnM6IF9DaGFyc1xufTtcblxubGV0IENoYXJzID0gS2VybmVsLmRlZnByb3RvY29sKHtcbiAgdG9fY2hhcl9saXN0OiBmdW5jdGlvbiAodGhpbmcpIHt9XG59KTtcblxuS2VybmVsLmRlZmltcGwoQ2hhcnMsIEtlcm5lbC5pc19iaXRzdHJpbmcsIHtcbiAgdG9fY2hhcl9saXN0OiBmdW5jdGlvbiAodGhpbmcpIHtcbiAgICBpZiAoS2VybmVsLmlzX2JpbmFyeSh0aGluZykpIHtcbiAgICAgIHJldHVybiBfU3RyaW5nLnRvX2NoYXJfbGlzdCh0aGluZyk7XG4gICAgfVxuXG4gICAgcmV0dXJuIHRoaW5nLnRvU3RyaW5nKCk7XG4gIH1cbn0pO1xuXG5LZXJuZWwuZGVmaW1wbChDaGFycywgS2VybmVsLmlzX2F0b20sIHtcbiAgdG9fY2hhcl9saXN0OiBmdW5jdGlvbiAodGhpbmcpIHtcbiAgICByZXR1cm4gQXRvbS50b19jaGFyX2xpc3QodGhpbmcpO1xuICB9XG59KTtcblxuS2VybmVsLmRlZmltcGwoQ2hhcnMsIEtlcm5lbC5pc19pbnRlZ2VyLCB7XG4gIHRvX2NoYXJfbGlzdDogZnVuY3Rpb24gKHRoaW5nKSB7XG4gICAgcmV0dXJuIEludGVnZXIudG9fY2hhcl9saXN0KHRoaW5nKTtcbiAgfVxufSk7XG5cbktlcm5lbC5kZWZpbXBsKENoYXJzLCBLZXJuZWwuaXNfbGlzdCwge1xuICB0b19jaGFyX2xpc3Q6IGZ1bmN0aW9uICh0aGluZykge1xuICAgIHJldHVybiB0aGluZztcbiAgfVxufSk7XG5cbmxldCBMaXN0ID0ge307XG5cbkxpc3QuQ2hhcnMgPSBDaGFycztcblxuTGlzdC5kZWxldGUgPSBmdW5jdGlvbiAobGlzdCwgaXRlbSkge1xuICBsZXQgbmV3X3ZhbHVlID0gW107XG4gIGxldCB2YWx1ZV9mb3VuZCA9IGZhbHNlO1xuXG4gIGZvciAobGV0IHggb2YgbGlzdCkge1xuICAgIGlmICh4ID09PSBpdGVtICYmIHZhbHVlX2ZvdW5kICE9PSBmYWxzZSkge1xuICAgICAgbmV3X3ZhbHVlLnB1c2goeCk7XG4gICAgICB2YWx1ZV9mb3VuZCA9IHRydWU7XG4gICAgfSBlbHNlIGlmICh4ICE9PSBpdGVtKSB7XG4gICAgICBuZXdfdmFsdWUucHVzaCh4KTtcbiAgICB9XG4gIH1cblxuICByZXR1cm4gS2VybmVsLlNwZWNpYWxGb3Jtcy5saXN0KC4uLm5ld192YWx1ZSk7XG59O1xuXG5MaXN0LmRlbGV0ZV9hdCA9IGZ1bmN0aW9uIChsaXN0LCBpbmRleCkge1xuICBsZXQgbmV3X3ZhbHVlID0gW107XG5cbiAgZm9yIChsZXQgaSA9IDA7IGkgPCBsaXN0Lmxlbmd0aDsgaSsrKSB7XG4gICAgaWYgKGkgIT09IGluZGV4KSB7XG4gICAgICBuZXdfdmFsdWUucHVzaChsaXN0W2ldKTtcbiAgICB9XG4gIH1cblxuICByZXR1cm4gS2VybmVsLlNwZWNpYWxGb3Jtcy5saXN0KC4uLm5ld192YWx1ZSk7XG59O1xuXG5MaXN0LmR1cGxpY2F0ZSA9IGZ1bmN0aW9uIChlbGVtLCBuKSB7XG4gIGxldCBuZXdfdmFsdWUgPSBbXTtcblxuICBmb3IgKHZhciBpID0gMDsgaSA8IG47IGkrKykge1xuICAgIG5ld192YWx1ZS5wdXNoKGVsZW0pO1xuICB9XG5cbiAgcmV0dXJuIEtlcm5lbC5TcGVjaWFsRm9ybXMubGlzdCguLi5uZXdfdmFsdWUpO1xufTtcblxuTGlzdC5maXJzdCA9IGZ1bmN0aW9uIChsaXN0KSB7XG4gIHJldHVybiBsaXN0WzBdO1xufTtcblxuTGlzdC5mbGF0dGVuID0gZnVuY3Rpb24gKGxpc3QsIHRhaWwgPSBLZXJuZWwuU3BlY2lhbEZvcm1zLmxpc3QoKSkge1xuICBsZXQgbmV3X3ZhbHVlID0gW107XG5cbiAgZm9yIChsZXQgeCBvZiBsaXN0KSB7XG4gICAgaWYgKEtlcm5lbC5pc19saXN0KHgpKSB7XG4gICAgICBuZXdfdmFsdWUgPSBuZXdfdmFsdWUuY29uY2F0KExpc3QuZmxhdHRlbih4KSk7XG4gICAgfSBlbHNlIHtcbiAgICAgIG5ld192YWx1ZS5wdXNoKHgpO1xuICAgIH1cbiAgfVxuXG4gIG5ld192YWx1ZSA9IG5ld192YWx1ZS5jb25jYXQodGFpbCk7XG5cbiAgcmV0dXJuIEtlcm5lbC5TcGVjaWFsRm9ybXMubGlzdCguLi5uZXdfdmFsdWUpO1xufTtcblxuTGlzdC5mb2xkbCA9IGZ1bmN0aW9uIChsaXN0LCBhY2MsIGZ1bmMpIHtcbiAgcmV0dXJuIGxpc3QucmVkdWNlKGZ1bmMsIGFjYyk7XG59O1xuXG5MaXN0LmZvbGRyID0gZnVuY3Rpb24gKGxpc3QsIGFjYywgZnVuYykge1xuICBsZXQgbmV3X2FjYyA9IGFjYztcblxuICBmb3IgKHZhciBpID0gbGlzdC5sZW5ndGggLSAxOyBpID49IDA7IGktLSkge1xuICAgIG5ld19hY2MgPSBmdW5jKGxpc3RbaV0sIG5ld19hY2MpO1xuICB9XG5cbiAgcmV0dXJuIG5ld19hY2M7XG59O1xuXG5MaXN0Lmluc2VydF9hdCA9IGZ1bmN0aW9uIChsaXN0LCBpbmRleCwgdmFsdWUpIHtcbiAgbGV0IG5ld192YWx1ZSA9IFtdO1xuXG4gIGZvciAobGV0IGkgPSAwOyBpIDwgbGlzdC5sZW5ndGg7IGkrKykge1xuICAgIGlmIChpID09PSBpbmRleCkge1xuICAgICAgbmV3X3ZhbHVlLnB1c2godmFsdWUpO1xuICAgICAgbmV3X3ZhbHVlLnB1c2gobGlzdFtpXSk7XG4gICAgfSBlbHNlIHtcbiAgICAgIG5ld192YWx1ZS5wdXNoKGxpc3RbaV0pO1xuICAgIH1cbiAgfVxuXG4gIHJldHVybiBLZXJuZWwuU3BlY2lhbEZvcm1zLmxpc3QoLi4ubmV3X3ZhbHVlKTtcbn07XG5cbkxpc3Qua2V5ZGVsZXRlID0gZnVuY3Rpb24gKGxpc3QsIGtleSwgcG9zaXRpb24pIHtcbiAgbGV0IG5ld19saXN0ID0gW107XG5cbiAgZm9yIChsZXQgaSA9IDA7IGkgPCBsaXN0Lmxlbmd0aDsgaSsrKSB7XG4gICAgaWYgKCFLZXJuZWwubWF0Y2hfX3FtYXJrX18obGlzdFtpXVtwb3NpdGlvbl0sIGtleSkpIHtcbiAgICAgIG5ld19saXN0LnB1c2gobGlzdFtpXSk7XG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIEtlcm5lbC5TcGVjaWFsRm9ybXMubGlzdCguLi5uZXdfbGlzdCk7XG59O1xuXG5MaXN0LmtleWZpbmQgPSBmdW5jdGlvbiAobGlzdCwga2V5LCBwb3NpdGlvbiwgX2RlZmF1bHQgPSBudWxsKSB7XG5cbiAgZm9yIChsZXQgaSA9IDA7IGkgPCBsaXN0Lmxlbmd0aDsgaSsrKSB7XG4gICAgaWYgKEtlcm5lbC5tYXRjaF9fcW1hcmtfXyhsaXN0W2ldW3Bvc2l0aW9uXSwga2V5KSkge1xuICAgICAgcmV0dXJuIGxpc3RbaV07XG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIF9kZWZhdWx0O1xufTtcblxuTGlzdC5rZXltZW1iZXJfX3FtYXJrX18gPSBmdW5jdGlvbiAobGlzdCwga2V5LCBwb3NpdGlvbikge1xuXG4gIGZvciAobGV0IGkgPSAwOyBpIDwgbGlzdC5sZW5ndGg7IGkrKykge1xuICAgIGlmIChLZXJuZWwubWF0Y2hfX3FtYXJrX18obGlzdFtpXVtwb3NpdGlvbl0sIGtleSkpIHtcbiAgICAgIHJldHVybiB0cnVlO1xuICAgIH1cbiAgfVxuXG4gIHJldHVybiBmYWxzZTtcbn07XG5cbkxpc3Qua2V5cmVwbGFjZSA9IGZ1bmN0aW9uIChsaXN0LCBrZXksIHBvc2l0aW9uLCBuZXdfdHVwbGUpIHtcbiAgbGV0IG5ld19saXN0ID0gW107XG5cbiAgZm9yIChsZXQgaSA9IDA7IGkgPCBsaXN0Lmxlbmd0aDsgaSsrKSB7XG4gICAgaWYgKCFLZXJuZWwubWF0Y2hfX3FtYXJrX18obGlzdFtpXVtwb3NpdGlvbl0sIGtleSkpIHtcbiAgICAgIG5ld19saXN0LnB1c2gobGlzdFtpXSk7XG4gICAgfSBlbHNlIHtcbiAgICAgIG5ld19saXN0LnB1c2gobmV3X3R1cGxlKTtcbiAgICB9XG4gIH1cblxuICByZXR1cm4gS2VybmVsLlNwZWNpYWxGb3Jtcy5saXN0KC4uLm5ld19saXN0KTtcbn07XG5cbkxpc3Qua2V5c29ydCA9IGZ1bmN0aW9uIChsaXN0LCBwb3NpdGlvbikge1xuICBsZXQgbmV3X2xpc3QgPSBsaXN0O1xuXG4gIG5ld19saXN0LnNvcnQoZnVuY3Rpb24gKGEsIGIpIHtcbiAgICBpZiAocG9zaXRpb24gPT09IDApIHtcbiAgICAgIGlmIChhW3Bvc2l0aW9uXS52YWx1ZSA8IGJbcG9zaXRpb25dLnZhbHVlKSB7XG4gICAgICAgIHJldHVybiAtMTtcbiAgICAgIH1cblxuICAgICAgaWYgKGFbcG9zaXRpb25dLnZhbHVlID4gYltwb3NpdGlvbl0udmFsdWUpIHtcbiAgICAgICAgcmV0dXJuIDE7XG4gICAgICB9XG5cbiAgICAgIHJldHVybiAwO1xuICAgIH0gZWxzZSB7XG4gICAgICBpZiAoYVtwb3NpdGlvbl0gPCBiW3Bvc2l0aW9uXSkge1xuICAgICAgICByZXR1cm4gLTE7XG4gICAgICB9XG5cbiAgICAgIGlmIChhW3Bvc2l0aW9uXSA+IGJbcG9zaXRpb25dKSB7XG4gICAgICAgIHJldHVybiAxO1xuICAgICAgfVxuXG4gICAgICByZXR1cm4gMDtcbiAgICB9XG4gIH0pO1xuXG4gIHJldHVybiBLZXJuZWwuU3BlY2lhbEZvcm1zLmxpc3QoLi4ubmV3X2xpc3QpO1xufTtcblxuTGlzdC5rZXlzdG9yZSA9IGZ1bmN0aW9uIChsaXN0LCBrZXksIHBvc2l0aW9uLCBuZXdfdHVwbGUpIHtcbiAgbGV0IG5ld19saXN0ID0gW107XG4gIGxldCByZXBsYWNlZCA9IGZhbHNlO1xuXG4gIGZvciAobGV0IGkgPSAwOyBpIDwgbGlzdC5sZW5ndGg7IGkrKykge1xuICAgIGlmICghS2VybmVsLm1hdGNoX19xbWFya19fKGxpc3RbaV1bcG9zaXRpb25dLCBrZXkpKSB7XG4gICAgICBuZXdfbGlzdC5wdXNoKGxpc3RbaV0pO1xuICAgIH0gZWxzZSB7XG4gICAgICBuZXdfbGlzdC5wdXNoKG5ld190dXBsZSk7XG4gICAgICByZXBsYWNlZCA9IHRydWU7XG4gICAgfVxuICB9XG5cbiAgaWYgKCFyZXBsYWNlZCkge1xuICAgIG5ld19saXN0LnB1c2gobmV3X3R1cGxlKTtcbiAgfVxuXG4gIHJldHVybiBLZXJuZWwuU3BlY2lhbEZvcm1zLmxpc3QoLi4ubmV3X2xpc3QpO1xufTtcblxuTGlzdC5sYXN0ID0gZnVuY3Rpb24gKGxpc3QpIHtcbiAgcmV0dXJuIGxpc3RbbGlzdC5sZW5ndGggLSAxXTtcbn07XG5cbkxpc3QucmVwbGFjZV9hdCA9IGZ1bmN0aW9uIChsaXN0LCBpbmRleCwgdmFsdWUpIHtcbiAgbGV0IG5ld192YWx1ZSA9IFtdO1xuXG4gIGZvciAobGV0IGkgPSAwOyBpIDwgbGlzdC5sZW5ndGg7IGkrKykge1xuICAgIGlmIChpID09PSBpbmRleCkge1xuICAgICAgbmV3X3ZhbHVlLnB1c2godmFsdWUpO1xuICAgIH0gZWxzZSB7XG4gICAgICBuZXdfdmFsdWUucHVzaChsaXN0W2ldKTtcbiAgICB9XG4gIH1cblxuICByZXR1cm4gS2VybmVsLlNwZWNpYWxGb3Jtcy5saXN0KC4uLm5ld192YWx1ZSk7XG59O1xuXG5MaXN0LnVwZGF0ZV9hdCA9IGZ1bmN0aW9uIChsaXN0LCBpbmRleCwgZnVuKSB7XG4gIGxldCBuZXdfdmFsdWUgPSBbXTtcblxuICBmb3IgKGxldCBpID0gMDsgaSA8IGxpc3QuY291bnQoKTsgaSsrKSB7XG4gICAgaWYgKGkgPT09IGluZGV4KSB7XG4gICAgICBuZXdfdmFsdWUucHVzaChmdW4obGlzdC5nZXQoaSkpKTtcbiAgICB9IGVsc2Uge1xuICAgICAgbmV3X3ZhbHVlLnB1c2gobGlzdC5nZXQoaSkpO1xuICAgIH1cbiAgfVxuXG4gIHJldHVybiBuZXdfdmFsdWU7XG59O1xuXG5MaXN0LndyYXAgPSBmdW5jdGlvbiAobGlzdCkge1xuICBpZiAoS2VybmVsLmlzX2xpc3QobGlzdCkpIHtcbiAgICByZXR1cm4gbGlzdDtcbiAgfSBlbHNlIGlmIChsaXN0ID09IG51bGwpIHtcbiAgICByZXR1cm4gS2VybmVsLlNwZWNpYWxGb3Jtcy5saXN0KCk7XG4gIH0gZWxzZSB7XG4gICAgcmV0dXJuIEtlcm5lbC5TcGVjaWFsRm9ybXMubGlzdChsaXN0KTtcbiAgfVxufTtcblxuTGlzdC56aXAgPSBmdW5jdGlvbiAobGlzdF9vZl9saXN0cykge1xuICBpZiAobGlzdF9vZl9saXN0cy5sZW5ndGggPT09IDApIHtcbiAgICByZXR1cm4gS2VybmVsLlNwZWNpYWxGb3Jtcy5saXN0KCk7XG4gIH1cblxuICBsZXQgbmV3X3ZhbHVlID0gW107XG4gIGxldCBzbWFsbGVzdF9sZW5ndGggPSBsaXN0X29mX2xpc3RzWzBdO1xuXG4gIGZvciAobGV0IHggb2YgbGlzdF9vZl9saXN0cykge1xuICAgIGlmICh4Lmxlbmd0aCA8IHNtYWxsZXN0X2xlbmd0aCkge1xuICAgICAgc21hbGxlc3RfbGVuZ3RoID0geC5sZW5ndGg7XG4gICAgfVxuICB9XG5cbiAgZm9yIChsZXQgaSA9IDA7IGkgPCBzbWFsbGVzdF9sZW5ndGg7IGkrKykge1xuICAgIGxldCBjdXJyZW50X3ZhbHVlID0gW107XG4gICAgZm9yIChsZXQgaiA9IDA7IGogPCBsaXN0X29mX2xpc3RzLmxlbmd0aDsgaisrKSB7XG4gICAgICBjdXJyZW50X3ZhbHVlLnB1c2gobGlzdF9vZl9saXN0c1tqXVtpXSk7XG4gICAgfVxuXG4gICAgbmV3X3ZhbHVlLnB1c2goS2VybmVsLlNwZWNpYWxGb3Jtcy50dXBsZSguLi5jdXJyZW50X3ZhbHVlKSk7XG4gIH1cblxuICByZXR1cm4gS2VybmVsLlNwZWNpYWxGb3Jtcy5saXN0KC4uLm5ld192YWx1ZSk7XG59O1xuXG5MaXN0LnRvX3R1cGxlID0gZnVuY3Rpb24gKGxpc3QpIHtcbiAgcmV0dXJuIEtlcm5lbC5TcGVjaWFsRm9ybXMudHVwbGUuYXBwbHkobnVsbCwgbGlzdCk7XG59O1xuXG5MaXN0LmFwcGVuZCA9IGZ1bmN0aW9uIChsaXN0LCB2YWx1ZSkge1xuICByZXR1cm4gS2VybmVsLlNwZWNpYWxGb3Jtcy5saXN0KC4uLmxpc3QuY29uY2F0KFt2YWx1ZV0pKTtcbn07XG5cbkxpc3QucHJlcGVuZCA9IGZ1bmN0aW9uIChsaXN0LCB2YWx1ZSkge1xuICByZXR1cm4gS2VybmVsLlNwZWNpYWxGb3Jtcy5saXN0KC4uLlt2YWx1ZV0uY29uY2F0KGxpc3QpKTtcbn07XG5cbkxpc3QuY29uY2F0ID0gZnVuY3Rpb24gKGxlZnQsIHJpZ2h0KSB7XG4gIHJldHVybiBsZWZ0LmNvbmNhdChyaWdodCk7XG59O1xuXG5jbGFzcyBTaWduYWwge1xuXG4gIGNvbnN0cnVjdG9yKCkge1xuICAgIHRoaXMuYmluZGluZ3MgPSBTcGVjaWFsRm9ybXMubGlzdCgpO1xuICB9XG5cbiAgYWRkKGxpc3RlbmVyLCBjb250ZXh0ID0gdGhpcykge1xuICAgIHRoaXMuYmluZGluZ3MgPSBMaXN0LmFwcGVuZCh0aGlzLmJpbmRpbmdzLCBuZXcgU2lnbmFsQmluZGluZyh0aGlzLCBsaXN0ZW5lciwgY29udGV4dCkpO1xuICB9XG5cbiAgcmVtb3ZlKGxpc3RlbmVyKSB7XG4gICAgdGhpcy5iaW5kaW5ncyA9IEVudW0uZmlsdGVyKHRoaXMuYmluZGluZ3MsIGZ1bmN0aW9uIChiaW5kaW5nKSB7XG4gICAgICByZXR1cm4gYmluZGluZy5saXN0ZW5lciAhPT0gbGlzdGVuZXI7XG4gICAgfSk7XG4gIH1cblxuICBkaXNwYXRjaCguLi5wYXJhbXMpIHtcbiAgICBmb3IgKGxldCBiaW5kaW5nIG9mIHRoaXMuYmluZGluZ3MpIHtcbiAgICAgIGJpbmRpbmcuZXhlY3V0ZSguLi5wYXJhbXMpO1xuICAgIH1cbiAgfVxuXG4gIGRpc3Bvc2UoKSB7XG4gICAgZm9yIChsZXQgYmluZGluZyBvZiB0aGlzLmJpbmRpbmdzKSB7XG4gICAgICBiaW5kaW5nLmRpc3Bvc2UoKTtcbiAgICB9XG5cbiAgICB0aGlzLmJpbmRpbmdzID0gbnVsbDtcbiAgfVxufVxuXG5jbGFzcyBTaWduYWxCaW5kaW5nIHtcblxuICBjb25zdHJ1Y3RvcihzaWduYWwsIGxpc3RlbmVyLCBjb250ZXh0KSB7XG4gICAgdGhpcy5saXN0ZW5lciA9IGxpc3RlbmVyO1xuICAgIHRoaXMuc2lnbmFsID0gc2lnbmFsO1xuICAgIHRoaXMuY29udGV4dCA9IGNvbnRleHQ7XG4gIH1cblxuICBleGVjdXRlKC4uLnBhcmFtcykge1xuICAgIHRoaXMubGlzdGVuZXIuYXBwbHkodGhpcy5jb250ZXh0LCBwYXJhbXMpO1xuICB9XG5cbiAgZGlzcG9zZSgpIHtcbiAgICB0aGlzLmxpc3RlbmVyID0gbnVsbDtcbiAgICB0aGlzLnNpZ25hbCA9IG51bGw7XG4gICAgdGhpcy5jb250ZXh0ID0gbnVsbDtcbiAgfVxufVxuXG5mdW5jdGlvbiBfX3VwZGF0ZShtYXAsIGtleSwgdmFsdWUpIHtcbiAgbGV0IG0gPSBuZXcgTWFwKG1hcCk7XG4gIG0uc2V0KGtleSwgdmFsdWUpO1xuICByZXR1cm4gbTtcbn1cblxuZnVuY3Rpb24gcmVtb3ZlKG1hcCwga2V5KSB7XG4gIGxldCBtID0gbmV3IE1hcChtYXApO1xuICBtLmRlbGV0ZShrZXkpO1xuICByZXR1cm4gbTtcbn1cblxuY2xhc3MgTWFpbEJveCB7XG5cbiAgY29uc3RydWN0b3IoY29udGV4dCA9IHRoaXMpIHtcbiAgICB0aGlzLnNpZ25hbCA9IG5ldyBTaWduYWwoKTtcbiAgICB0aGlzLnNpZ25hbC5hZGQoKC4uLnBhcmFtcykgPT4gdGhpcy5tZXNzYWdlcyA9IHRoaXMubWVzc2FnZXMuY29uY2F0KHBhcmFtcyksIGNvbnRleHQpO1xuICAgIHRoaXMubWVzc2FnZXMgPSBbXTtcbiAgfVxuXG4gIHJlY2VpdmUoLi4ubWVzc2FnZXMpIHtcbiAgICB0aGlzLnNpZ25hbC5kaXNwYXRjaCguLi5tZXNzYWdlcyk7XG4gIH1cblxuICBwZWVrKCkge1xuICAgIGlmICh0aGlzLm1lc3NhZ2VzLmxlbmd0aCA9PT0gMCkge1xuICAgICAgcmV0dXJuIG51bGw7XG4gICAgfVxuXG4gICAgcmV0dXJuIHRoaXMubWVzc2FnZXNbMF07XG4gIH1cblxuICByZWFkKCkge1xuICAgIGxldCByZXN1bHQgPSB0aGlzLm1lc3NhZ2VzWzBdO1xuICAgIHRoaXMubWVzc2FnZXMgPSB0aGlzLm1lc3NhZ2VzLnNsaWNlKDEpO1xuXG4gICAgcmV0dXJuIHJlc3VsdDtcbiAgfVxuXG4gIGFkZF9zdWJzY3JpYmVyKGZuLCBjb250ZXh0ID0gdGhpcykge1xuICAgIHRoaXMuc2lnbmFsLmFkZChmbiwgY29udGV4dCk7XG4gIH1cblxuICByZW1vdmVfc3Vic2NyaWJlcihmbikge1xuICAgIHRoaXMuc2lnbmFsLnJlbW92ZShmbik7XG4gIH1cblxuICBkaXNwb3NlKCkge1xuICAgIHRoaXMuc2lnbmFsLmRpc3Bvc2UoKTtcbiAgICB0aGlzLm1lc3NhZ2VzID0gbnVsbDtcbiAgfVxufVxuXG5jbGFzcyBQb3N0T2ZmaWNlIHtcblxuICBjb25zdHJ1Y3RvcigpIHtcbiAgICB0aGlzLm1haWxib3hlcyA9IG5ldyBNYXAoKTtcbiAgfVxuXG4gIHNlbmQoYWRkcmVzcywgbWVzc2FnZSkge1xuICAgIHRoaXMubWFpbGJveGVzLmdldChhZGRyZXNzKS5yZWNlaXZlKG1lc3NhZ2UpO1xuICB9XG5cbiAgcmVjZWl2ZShhZGRyZXNzKSB7XG4gICAgcmV0dXJuIHRoaXMubWFpbGJveGVzLmdldChhZGRyZXNzKS5yZWFkKCk7XG4gIH1cblxuICBwZWVrKGFkZHJlc3MpIHtcbiAgICByZXR1cm4gdGhpcy5tYWlsYm94ZXMuZ2V0KGFkZHJlc3MpLnBlZWsoKTtcbiAgfVxuXG4gIGFkZF9tYWlsYm94KGFkZHJlc3MgPSBTeW1ib2woKSwgY29udGV4dCA9IHRoaXMpIHtcbiAgICB0aGlzLm1haWxib3hlcyA9IF9fdXBkYXRlKHRoaXMubWFpbGJveGVzLCBhZGRyZXNzLCBuZXcgTWFpbEJveCgpKTtcbiAgICByZXR1cm4gYWRkcmVzcztcbiAgfVxuXG4gIHJlbW92ZV9tYWlsYm94KGFkZHJlc3MpIHtcbiAgICB0aGlzLm1haWxib3hlcy5nZXQoYWRkcmVzcykuZGlzcG9zZSgpO1xuICAgIHRoaXMubWFpbGJveGVzID0gcmVtb3ZlKHRoaXMubWFpbGJveGVzLCBhZGRyZXNzKTtcbiAgfVxuXG4gIHN1YnNjcmliZShhZGRyZXNzLCBzdWJzY3JpYnRpb25fZm4sIGNvbnRleHQgPSB0aGlzKSB7XG4gICAgdGhpcy5tYWlsYm94ZXMuZ2V0KGFkZHJlc3MpLmFkZF9zdWJzY3JpYmVyKHN1YnNjcmlidGlvbl9mbiwgY29udGV4dCk7XG4gIH1cblxuICB1bnN1YnNjcmliZShhZGRyZXNzLCBzdWJzY3JpYnRpb25fZm4pIHtcbiAgICB0aGlzLm1haWxib3hlcy5nZXQoYWRkcmVzcykucmVtb3ZlX3N1YnNjcmliZXIoc3Vic2NyaWJ0aW9uX2ZuKTtcbiAgfVxufVxuXG5mdW5jdGlvbiBjYWxsX3Byb3BlcnR5KGl0ZW0sIHByb3BlcnR5KSB7XG4gIGlmIChwcm9wZXJ0eSBpbiBpdGVtKSB7XG4gICAgaXRlbVtwcm9wZXJ0eV07XG4gICAgaWYgKGl0ZW1bcHJvcGVydHldIGluc3RhbmNlb2YgRnVuY3Rpb24pIHtcbiAgICAgIHJldHVybiBpdGVtW3Byb3BlcnR5XSgpO1xuICAgIH0gZWxzZSB7XG4gICAgICByZXR1cm4gaXRlbVtwcm9wZXJ0eV07XG4gICAgfVxuICB9IGVsc2UgaWYgKFN5bWJvbC5mb3IocHJvcGVydHkpIGluIGl0ZW0pIHtcbiAgICBsZXQgcHJvcCA9IFN5bWJvbC5mb3IocHJvcGVydHkpO1xuICAgIGlmIChpdGVtW3Byb3BdIGluc3RhbmNlb2YgRnVuY3Rpb24pIHtcbiAgICAgIHJldHVybiBpdGVtW3Byb3BdKCk7XG4gICAgfSBlbHNlIHtcbiAgICAgIHJldHVybiBpdGVtW3Byb3BdO1xuICAgIH1cbiAgfVxuXG4gIHRocm93IG5ldyBFcnJvcihgUHJvcGVydHkgJHsgcHJvcGVydHkgfSBub3QgZm91bmQgaW4gJHsgaXRlbSB9YCk7XG59XG5cbnZhciBKUyA9IHtcbiAgY2FsbF9wcm9wZXJ0eVxufTtcblxubGV0IFJhbmdlID0gZnVuY3Rpb24gKF9maXJzdCwgX2xhc3QpIHtcbiAgaWYgKCEodGhpcyBpbnN0YW5jZW9mIFJhbmdlKSkge1xuICAgIHJldHVybiBuZXcgUmFuZ2UoX2ZpcnN0LCBfbGFzdCk7XG4gIH1cblxuICB0aGlzLmZpcnN0ID0gZnVuY3Rpb24gKCkge1xuICAgIHJldHVybiBfZmlyc3Q7XG4gIH07XG5cbiAgdGhpcy5sYXN0ID0gZnVuY3Rpb24gKCkge1xuICAgIHJldHVybiBfbGFzdDtcbiAgfTtcblxuICBsZXQgX3JhbmdlID0gW107XG5cbiAgZm9yIChsZXQgaSA9IF9maXJzdDsgaSA8PSBfbGFzdDsgaSsrKSB7XG4gICAgX3JhbmdlLnB1c2goaSk7XG4gIH1cblxuICBfcmFuZ2UgPSBPYmplY3QuZnJlZXplKF9yYW5nZSk7XG5cbiAgdGhpcy52YWx1ZSA9IGZ1bmN0aW9uICgpIHtcbiAgICByZXR1cm4gX3JhbmdlO1xuICB9O1xuXG4gIHRoaXMubGVuZ3RoID0gZnVuY3Rpb24gKCkge1xuICAgIHJldHVybiBfcmFuZ2UubGVuZ3RoO1xuICB9O1xuXG4gIHJldHVybiB0aGlzO1xufTtcblxuUmFuZ2UucHJvdG90eXBlW1N5bWJvbC5pdGVyYXRvcl0gPSBmdW5jdGlvbiAoKSB7XG4gIHJldHVybiB0aGlzLnZhbHVlKClbU3ltYm9sLml0ZXJhdG9yXSgpO1xufTtcblxuUmFuZ2UubmV3ID0gZnVuY3Rpb24gKGZpcnN0LCBsYXN0KSB7XG4gIHJldHVybiBSYW5nZShmaXJzdCwgbGFzdCk7XG59O1xuXG5SYW5nZS5yYW5nZV9fcW1hcmtfXyA9IGZ1bmN0aW9uIChyYW5nZSkge1xuICByZXR1cm4gcmFuZ2UgaW5zdGFuY2VvZiBSYW5nZTtcbn07XG5cbmxldCBLZXl3b3JkID0ge307XG5cbktleXdvcmQuaGFzX2tleV9fcW1fXyA9IGZ1bmN0aW9uIChrZXl3b3Jkcywga2V5KSB7XG4gIGZvciAobGV0IGtleXdvcmQgb2Yga2V5d29yZHMpIHtcbiAgICBpZiAoS2VybmVsLmVsZW0oa2V5d29yZCwgMCkgPT0ga2V5KSB7XG4gICAgICByZXR1cm4gdHJ1ZTtcbiAgICB9XG4gIH1cblxuICByZXR1cm4gZmFsc2U7XG59O1xuXG5LZXl3b3JkLmdldCA9IGZ1bmN0aW9uIChrZXl3b3Jkcywga2V5LCB0aGVfZGVmYXVsdCA9IG51bGwpIHtcbiAgZm9yIChsZXQga2V5d29yZCBvZiBrZXl3b3Jkcykge1xuICAgIGlmIChLZXJuZWwuZWxlbShrZXl3b3JkLCAwKSA9PSBrZXkpIHtcbiAgICAgIHJldHVybiBLZXJuZWwuZWxlbShrZXl3b3JkLCAxKTtcbiAgICB9XG4gIH1cblxuICByZXR1cm4gdGhlX2RlZmF1bHQ7XG59O1xuXG5sZXQgQWdlbnQgPSB7fTtcblxuQWdlbnQuc3RhcnQgPSBmdW5jdGlvbiAoZnVuLCBvcHRpb25zID0gW10pIHtcbiAgY29uc3QgbmFtZSA9IEtleXdvcmQuaGFzX2tleV9fcW1fXyhvcHRpb25zLCBLZXJuZWwuU3BlY2lhbEZvcm1zLmF0b20oJ25hbWUnKSkgPyBLZXl3b3JkLmdldChvcHRpb25zLCBLZXJuZWwuU3BlY2lhbEZvcm1zLmF0b20oJ25hbWUnKSkgOiBTeW1ib2woKTtcblxuICBzZWxmLnBvc3Rfb2ZmaWNlLmFkZF9tYWlsYm94KG5hbWUpO1xuICBzZWxmLnBvc3Rfb2ZmaWNlLnNlbmQobmFtZSwgZnVuKCkpO1xuXG4gIHJldHVybiBLZXJuZWwuU3BlY2lhbEZvcm1zLnR1cGxlKEtlcm5lbC5TcGVjaWFsRm9ybXMuYXRvbSgnb2snKSwgbmFtZSk7XG59O1xuXG5BZ2VudC5zdG9wID0gZnVuY3Rpb24gKGFnZW50LCB0aW1lb3V0ID0gNTAwMCkge1xuICBzZWxmLnBvc3Rfb2ZmaWNlLnJlbW92ZV9tYWlsYm94KGFnZW50KTtcbiAgcmV0dXJuIEtlcm5lbC5TcGVjaWFsRm9ybXMuYXRvbSgnb2snKTtcbn07XG5cbkFnZW50LnVwZGF0ZSA9IGZ1bmN0aW9uIChhZ2VudCwgZnVuLCB0aW1lb3V0ID0gNTAwMCkge1xuXG4gIGNvbnN0IGN1cnJlbnRfc3RhdGUgPSBzZWxmLnBvc3Rfb2ZmaWNlLnJlY2VpdmUoYWdlbnQpO1xuICBzZWxmLnBvc3Rfb2ZmaWNlLnNlbmQoYWdlbnQsIGZ1bihjdXJyZW50X3N0YXRlKSk7XG5cbiAgcmV0dXJuIEtlcm5lbC5TcGVjaWFsRm9ybXMuYXRvbSgnb2snKTtcbn07XG5cbkFnZW50LmdldCA9IGZ1bmN0aW9uIChhZ2VudCwgZnVuLCB0aW1lb3V0ID0gNTAwMCkge1xuICByZXR1cm4gZnVuKHNlbGYucG9zdF9vZmZpY2UucGVlayhhZ2VudCkpO1xufTtcblxuQWdlbnQuZ2V0X2FuZF91cGRhdGUgPSBmdW5jdGlvbiAoYWdlbnQsIGZ1biwgdGltZW91dCA9IDUwMDApIHtcblxuICBjb25zdCBnZXRfYW5kX3VwZGF0ZV90dXBsZSA9IGZ1bihzZWxmLnBvc3Rfb2ZmaWNlLnJlY2VpdmUoYWdlbnQpKTtcbiAgc2VsZi5wb3N0X29mZmljZS5zZW5kKGFnZW50LCBLZXJuZWwuZWxlbShnZXRfYW5kX3VwZGF0ZV90dXBsZSwgMSkpO1xuXG4gIHJldHVybiBLZXJuZWwuZWxlbShnZXRfYW5kX3VwZGF0ZV90dXBsZSwgMCk7XG59O1xuXG4vL2h0dHBzOi8vZGV2ZWxvcGVyLm1vemlsbGEub3JnL2VuLVVTL2RvY3MvV2ViL0FQSS9XaW5kb3dCYXNlNjQvQmFzZTY0X2VuY29kaW5nX2FuZF9kZWNvZGluZyNTb2x1dGlvbl8yXyVFMiU4MCU5M19yZXdyaXRlX3RoZV9ET01zX2F0b2IoKV9hbmRfYnRvYSgpX3VzaW5nX0phdmFTY3JpcHQnc19UeXBlZEFycmF5c19hbmRfVVRGLThcbmZ1bmN0aW9uIGI2NEVuY29kZVVuaWNvZGUoc3RyKSB7XG4gIHJldHVybiBidG9hKGVuY29kZVVSSUNvbXBvbmVudChzdHIpLnJlcGxhY2UoLyUoWzAtOUEtRl17Mn0pL2csIGZ1bmN0aW9uIChtYXRjaCwgcDEpIHtcbiAgICByZXR1cm4gU3RyaW5nLmZyb21DaGFyQ29kZSgnMHgnICsgcDEpO1xuICB9KSk7XG59XG5cbmZ1bmN0aW9uIGVuY29kZTY0KGRhdGEpIHtcbiAgcmV0dXJuIGI2NEVuY29kZVVuaWNvZGUoZGF0YSk7XG59XG5cbmZ1bmN0aW9uIGRlY29kZTY0KGRhdGEpIHtcbiAgdHJ5IHtcbiAgICByZXR1cm4gS2VybmVsLlNwZWNpYWxGb3Jtcy50dXBsZShLZXJuZWwuU3BlY2lhbEZvcm1zLmF0b20oJ29rJyksIGF0b2IoZGF0YSkpO1xuICB9IGNhdGNoIChlKSB7XG4gICAgcmV0dXJuIEtlcm5lbC5TcGVjaWFsRm9ybXMuYXRvbSgnZXJyb3InKTtcbiAgfVxuICByZXR1cm4gYnRvYShkYXRhKTtcbn1cblxuZnVuY3Rpb24gZGVjb2RlNjRfX2VtX18oZGF0YSkge1xuICByZXR1cm4gYXRvYihkYXRhKTtcbn1cblxudmFyIEJhc2UgPSB7XG4gIGVuY29kZTY0LFxuICBkZWNvZGU2NCxcbiAgZGVjb2RlNjRfX2VtX19cbn07XG5cbmZ1bmN0aW9uIGJub3QoZXhwcikge1xuICByZXR1cm4gfmV4cHI7XG59XG5cbmZ1bmN0aW9uIGJhbmQobGVmdCwgcmlnaHQpIHtcbiAgcmV0dXJuIGxlZnQgJiByaWdodDtcbn1cblxuZnVuY3Rpb24gYm9yKGxlZnQsIHJpZ2h0KSB7XG4gIHJldHVybiBsZWZ0IHwgcmlnaHQ7XG59XG5cbmZ1bmN0aW9uIGJzbChsZWZ0LCByaWdodCkge1xuICByZXR1cm4gbGVmdCA8PCByaWdodDtcbn1cblxuZnVuY3Rpb24gYnNyKGxlZnQsIHJpZ2h0KSB7XG4gIHJldHVybiBsZWZ0ID4+IHJpZ2h0O1xufVxuXG5mdW5jdGlvbiBieG9yKGxlZnQsIHJpZ2h0KSB7XG4gIHJldHVybiBsZWZ0IF4gcmlnaHQ7XG59XG5cbnZhciBCaXR3aXNlID0ge1xuICBibm90LFxuICBiYW5kLFxuICBib3IsXG4gIGJzbCxcbiAgYnNyLFxuICBieG9yXG59O1xuXG5sZXQgRW51bWVyYWJsZSA9IEtlcm5lbC5kZWZwcm90b2NvbCh7XG4gIGNvdW50OiBmdW5jdGlvbiAoY29sbGVjdGlvbikge30sXG4gIG1lbWJlcl9xbWFya19fOiBmdW5jdGlvbiAoY29sbGVjdGlvbiwgdmFsdWUpIHt9LFxuICByZWR1Y2U6IGZ1bmN0aW9uIChjb2xsZWN0aW9uLCBhY2MsIGZ1bikge31cbn0pO1xuXG5sZXQgQ29sbGVjdGFibGUgPSBLZXJuZWwuZGVmcHJvdG9jb2woe1xuICBpbnRvOiBmdW5jdGlvbiAoY29sbGVjdGFibGUpIHt9XG59KTtcblxubGV0IEluc3BlY3QgPSBLZXJuZWwuZGVmcHJvdG9jb2woe1xuICBpbnNwZWN0OiBmdW5jdGlvbiAodGhpbmcsIG9wdHMpIHt9XG59KTtcblxuZnVuY3Rpb24gX19fbmV3X18oKSB7XG4gIHJldHVybiBTcGVjaWFsRm9ybXMubWFwKHt9KTtcbn1cblxuZnVuY3Rpb24ga2V5cyhtYXApIHtcbiAgcmV0dXJuIE9iamVjdC5rZXlzKG1hcCk7XG59XG5cbmZ1bmN0aW9uIF9fc2l6ZShtYXApIHtcbiAgcmV0dXJuIGtleXMobWFwKS5sZW5ndGg7XG59XG5cbmZ1bmN0aW9uIF9fdG9fbGlzdChtYXApIHtcbiAgbGV0IG1hcF9rZXlzID0ga2V5cyhtYXApO1xuICBsZXQgbGlzdCA9IFtdO1xuXG4gIGZvciAobGV0IGtleSBvZiBtYXBfa2V5cykge1xuICAgIGxpc3QucHVzaChTcGVjaWFsRm9ybXMudHVwbGUoa2V5LCBtYXBba2V5XSkpO1xuICB9XG5cbiAgcmV0dXJuIFNwZWNpYWxGb3Jtcy5saXN0KC4uLmxpc3QpO1xufVxuXG5mdW5jdGlvbiB2YWx1ZXMobWFwKSB7XG4gIGxldCBtYXBfa2V5cyA9IGtleXMobWFwKTtcbiAgbGV0IGxpc3QgPSBbXTtcblxuICBmb3IgKGxldCBrZXkgb2YgbWFwX2tleXMpIHtcbiAgICBsaXN0LnB1c2gobWFwW2tleV0pO1xuICB9XG5cbiAgcmV0dXJuIFNwZWNpYWxGb3Jtcy5saXN0KC4uLmxpc3QpO1xufVxuXG5mdW5jdGlvbiBmcm9tX3N0cnVjdChzdHJ1Y3QpIHtcbiAgbGV0IG1hcCA9IE9iamVjdC5hc3NpZ24oe30sIHN0cnVjdCk7XG4gIGRlbGV0ZSBtYXBbU3ltYm9sLmZvcihcIl9fc3RydWN0X19cIildO1xuXG4gIHJldHVybiBTcGVjaWFsRm9ybXMubWFwKG1hcCk7XG59XG5cbmZ1bmN0aW9uIF9fX19kZWxldGVfXyhtYXAsIGtleSkge1xuICBsZXQgbmV3X21hcCA9IE9iamVjdC5hc3NpZ24oe30sIG1hcCk7XG5cbiAgZGVsZXRlIG5ld19tYXBba2V5XTtcblxuICByZXR1cm4gU3BlY2lhbEZvcm1zLm1hcChuZXdfbWFwKTtcbn1cblxuZnVuY3Rpb24gZHJvcChtYXAsIGtleXMpIHtcbiAgbGV0IG5ld19tYXAgPSBPYmplY3QuYXNzaWduKHt9LCBtYXApO1xuXG4gIGZvciAobGV0IGtleSBvZiBrZXlzKSB7XG4gICAgZGVsZXRlIG5ld19tYXBba2V5XTtcbiAgfVxuXG4gIHJldHVybiBTcGVjaWFsRm9ybXMubWFwKG5ld19tYXApO1xufVxuXG5mdW5jdGlvbiBfX2VxdWFsX19xbWFya19fKG1hcDEsIG1hcDIpIHtcbiAgcmV0dXJuIG1hcDEgPT09IG1hcDI7XG59XG5cbmZ1bmN0aW9uIGZldGNoX19lbWFya19fKG1hcCwga2V5KSB7XG4gIGlmIChrZXkgaW4gbWFwKSB7XG4gICAgcmV0dXJuIG1hcFtrZXldO1xuICB9XG5cbiAgdGhyb3cgbmV3IEVycm9yKFwiS2V5IG5vdCBmb3VuZC5cIik7XG59XG5cbmZ1bmN0aW9uIGZldGNoKG1hcCwga2V5KSB7XG4gIGlmIChrZXkgaW4gbWFwKSB7XG4gICAgcmV0dXJuIFNwZWNpYWxGb3Jtcy50dXBsZShTcGVjaWFsRm9ybXMuYXRvbShcIm9rXCIpLCBtYXBba2V5XSk7XG4gIH1cblxuICByZXR1cm4gU3BlY2lhbEZvcm1zLmF0b20oXCJlcnJvclwiKTtcbn1cblxuZnVuY3Rpb24gaGFzX2tleV9fcW1hcmtfXyhtYXAsIGtleSkge1xuICByZXR1cm4ga2V5IGluIG1hcDtcbn1cblxuZnVuY3Rpb24gbWVyZ2UobWFwMSwgbWFwMikge1xuICByZXR1cm4gU3BlY2lhbEZvcm1zLm1hcF91cGRhdGUobWFwMSwgbWFwMik7XG59XG5cbmZ1bmN0aW9uIHNwbGl0KG1hcCwga2V5cykge1xuICBsZXQgc3BsaXQxID0ge307XG4gIGxldCBzcGxpdDIgPSB7fTtcblxuICBmb3IgKGxldCBrZXkgb2YgT2JqZWN0LmtleXMobWFwKSkge1xuICAgIGlmIChrZXlzLmluZGV4T2Yoa2V5KSA+IC0xKSB7XG4gICAgICBzcGxpdDFba2V5XSA9IG1hcFtrZXldO1xuICAgIH0gZWxzZSB7XG4gICAgICBzcGxpdDJba2V5XSA9IG1hcFtrZXldO1xuICAgIH1cbiAgfVxuXG4gIHJldHVybiBTcGVjaWFsRm9ybXMudHVwbGUoU3BlY2lhbEZvcm1zLm1hcChzcGxpdDEpLCBTcGVjaWFsRm9ybXMubWFwKHNwbGl0MikpO1xufVxuXG5mdW5jdGlvbiB0YWtlKG1hcCwga2V5cykge1xuICBsZXQgc3BsaXQxID0ge307XG5cbiAgZm9yIChsZXQga2V5IG9mIE9iamVjdC5rZXlzKG1hcCkpIHtcbiAgICBpZiAoa2V5cy5pbmRleE9mKGtleSkgPiAtMSkge1xuICAgICAgc3BsaXQxW2tleV0gPSBtYXBba2V5XTtcbiAgICB9XG4gIH1cblxuICByZXR1cm4gU3BlY2lhbEZvcm1zLm1hcChzcGxpdDEpO1xufVxuXG5mdW5jdGlvbiBkcm9wKG1hcCwga2V5cykge1xuICBsZXQgc3BsaXQxID0ge307XG5cbiAgZm9yIChsZXQga2V5IG9mIE9iamVjdC5rZXlzKG1hcCkpIHtcbiAgICBpZiAoa2V5cy5pbmRleE9mKGtleSkgPT09IC0xKSB7XG4gICAgICBzcGxpdDFba2V5XSA9IG1hcFtrZXldO1xuICAgIH1cbiAgfVxuXG4gIHJldHVybiBTcGVjaWFsRm9ybXMubWFwKHNwbGl0MSk7XG59XG5cbmZ1bmN0aW9uIHB1dF9uZXcobWFwLCBrZXksIHZhbHVlKSB7XG4gIGlmIChrZXkgaW4gbWFwKSB7XG4gICAgcmV0dXJuIG1hcDtcbiAgfVxuXG4gIGxldCBuZXdfbWFwID0gT2JqZWN0LmFzc2lnbih7fSwgbWFwKTtcbiAgbmV3X21hcFtrZXldID0gdmFsdWU7XG5cbiAgcmV0dXJuIFNwZWNpYWxGb3Jtcy5tYXAobmV3X21hcCk7XG59XG5cbmZ1bmN0aW9uIHB1dF9uZXdfbGF6eShtYXAsIGtleSwgZnVuKSB7XG4gIGlmIChrZXkgaW4gbWFwKSB7XG4gICAgcmV0dXJuIG1hcDtcbiAgfVxuXG4gIGxldCBuZXdfbWFwID0gT2JqZWN0LmFzc2lnbih7fSwgbWFwKTtcbiAgbmV3X21hcFtrZXldID0gZnVuKCk7XG5cbiAgcmV0dXJuIFNwZWNpYWxGb3Jtcy5tYXAobmV3X21hcCk7XG59XG5cbmZ1bmN0aW9uIGdldF9hbmRfdXBkYXRlKG1hcCwga2V5LCBmdW4pIHtcbiAgaWYgKGtleSBpbiBtYXApIHtcbiAgICByZXR1cm4gbWFwO1xuICB9XG5cbiAgbGV0IG5ld19tYXAgPSBPYmplY3QuYXNzaWduKHt9LCBtYXApO1xuICBuZXdfbWFwW2tleV0gPSBmdW4obWFwW2tleV0pO1xuXG4gIHJldHVybiBTcGVjaWFsRm9ybXMubWFwKG5ld19tYXApO1xufVxuXG5mdW5jdGlvbiBwb3BfbGF6eShtYXAsIGtleSwgZnVuKSB7XG4gIGlmICgha2V5IGluIG1hcCkge1xuICAgIHJldHVybiBTcGVjaWFsRm9ybXMudHVwbGUoZnVuKCksIG1hcCk7XG4gIH1cblxuICBsZXQgbmV3X21hcCA9IE9iamVjdC5hc3NpZ24oe30sIG1hcCk7XG4gIGxldCB2YWx1ZSA9IGZ1bihuZXdfbWFwW2tleV0pO1xuICBkZWxldGUgbmV3X21hcFtrZXldO1xuXG4gIHJldHVybiBTcGVjaWFsRm9ybXMudHVwbGUodmFsdWUsIG5ld19tYXApO1xufVxuXG5mdW5jdGlvbiBwb3AobWFwLCBrZXksIF9kZWZhdWx0ID0gbnVsbCkge1xuICBpZiAoIWtleSBpbiBtYXApIHtcbiAgICByZXR1cm4gU3BlY2lhbEZvcm1zLnR1cGxlKF9kZWZhdWx0LCBtYXApO1xuICB9XG5cbiAgbGV0IG5ld19tYXAgPSBPYmplY3QuYXNzaWduKHt9LCBtYXApO1xuICBsZXQgdmFsdWUgPSBuZXdfbWFwW2tleV07XG4gIGRlbGV0ZSBuZXdfbWFwW2tleV07XG5cbiAgcmV0dXJuIFNwZWNpYWxGb3Jtcy50dXBsZSh2YWx1ZSwgbmV3X21hcCk7XG59XG5cbmZ1bmN0aW9uIGdldF9sYXp5KG1hcCwga2V5LCBmdW4pIHtcbiAgaWYgKCFrZXkgaW4gbWFwKSB7XG4gICAgcmV0dXJuIGZ1bigpO1xuICB9XG5cbiAgcmV0dXJuIGZ1bihtYXBba2V5XSk7XG59XG5cbmZ1bmN0aW9uIGdldChtYXAsIGtleSwgX2RlZmF1bHQgPSBudWxsKSB7XG4gIGlmICgha2V5IGluIG1hcCkge1xuICAgIHJldHVybiBfZGVmYXVsdDtcbiAgfVxuXG4gIHJldHVybiBtYXBba2V5XTtcbn1cblxuZnVuY3Rpb24gX19wdXQobWFwLCBrZXksIHZhbCkge1xuICBsZXQgbmV3X21hcCA9IE9iamVjdCh7fSwgbWFwKTtcbiAgbmV3X21hcFtrZXldID0gdmFsO1xuXG4gIHJldHVybiBTcGVjaWFsRm9ybXMubWFwKG5ld19tYXApO1xufVxuXG5mdW5jdGlvbiB1cGRhdGVfX2VtYXJrX18obWFwLCBrZXksIGZ1bikge1xuICBpZiAoIWtleSBpbiBtYXApIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoXCJLZXkgbm90IGZvdW5kXCIpO1xuICB9XG5cbiAgbGV0IG5ld19tYXAgPSBPYmplY3Qoe30sIG1hcCk7XG4gIG5ld19tYXBba2V5XSA9IGZ1bihtYXBba2V5XSk7XG5cbiAgcmV0dXJuIFNwZWNpYWxGb3Jtcy5tYXAobmV3X21hcCk7XG59XG5cbmZ1bmN0aW9uIF91cGRhdGUobWFwLCBrZXksIGluaXRpYWwsIGZ1bikge1xuICBsZXQgbmV3X21hcCA9IE9iamVjdCh7fSwgbWFwKTtcblxuICBpZiAoIWtleSBpbiBtYXApIHtcbiAgICBuZXdfbWFwW2tleV0gPSBpbml0aWFsO1xuICB9IGVsc2Uge1xuICAgIG5ld19tYXBba2V5XSA9IGZ1bihtYXBba2V5XSk7XG4gIH1cblxuICByZXR1cm4gU3BlY2lhbEZvcm1zLm1hcChuZXdfbWFwKTtcbn1cblxudmFyIF9NYXAgPSB7XG4gIG5ldzogX19fbmV3X18sXG4gIGtleXMsXG4gIHNpemU6IF9fc2l6ZSxcbiAgdG9fbGlzdDogX190b19saXN0LFxuICB2YWx1ZXMsXG4gIGZyb21fc3RydWN0LFxuICBkZWxldGU6IF9fX19kZWxldGVfXyxcbiAgZHJvcCxcbiAgZXF1YWxfX3FtYXJrX186IF9fZXF1YWxfX3FtYXJrX18sXG4gIGZldGNoX19lbWFya19fLFxuICBmZXRjaCxcbiAgaGFzX2tleV9fcW1hcmtfXyxcbiAgc3BsaXQsXG4gIHRha2UsXG4gIHB1dF9uZXcsXG4gIHB1dF9uZXdfbGF6eSxcbiAgZ2V0X2FuZF91cGRhdGUsXG4gIHBvcF9sYXp5LFxuICBwb3AsXG4gIGdldF9sYXp5LFxuICBnZXQsXG4gIHB1dDogX19wdXQsXG4gIHVwZGF0ZV9fZW1hcmtfXyxcbiAgdXBkYXRlOiBfdXBkYXRlXG59O1xuXG5mdW5jdGlvbiBfX25ld19fKCkge1xuICByZXR1cm4gU3BlY2lhbEZvcm1zLm1hcCh7IFtTeW1ib2wuZm9yKCdfX3N0cnVjdF9fJyldOiBTeW1ib2wuZm9yKCdNYXBTZXQnKSwgc2V0OiBTcGVjaWFsRm9ybXMubGlzdCgpIH0pO1xufVxuXG5mdW5jdGlvbiBfc2l6ZShtYXApIHtcbiAgcmV0dXJuIG1hcC5zZXQubGVuZ3RoO1xufVxuXG5mdW5jdGlvbiBfdG9fbGlzdChtYXApIHtcbiAgcmV0dXJuIG1hcC5zZXQ7XG59XG5cbmZ1bmN0aW9uIF9fX2RlbGV0ZV9fKHNldCwgdGVybSkge1xuICBsZXQgbmV3X2xpc3QgPSBMaXN0LmRlbGV0ZShzZXQuc2V0LCB0ZXJtKTtcblxuICBsZXQgbmV3X21hcCA9IE9iamVjdC5hc3NpZ24oe30sIHNldCk7XG4gIG5ld19tYXAuc2V0ID0gbmV3X2xpc3Q7XG4gIHJldHVybiBTcGVjaWFsRm9ybXMubWFwKG5ld19tYXApO1xufVxuXG5mdW5jdGlvbiBfcHV0KHNldCwgdGVybSkge1xuICBpZiAoc2V0LnNldC5pbmRleE9mKHRlcm0pID09PSAtMSkge1xuICAgIGxldCBuZXdfbGlzdCA9IExpc3QuYXBwZW5kKHNldC5zZXQsIHRlcm0pO1xuXG4gICAgbGV0IG5ld19tYXAgPSBPYmplY3QuYXNzaWduKHt9LCBzZXQpO1xuICAgIG5ld19tYXAuc2V0ID0gbmV3X2xpc3Q7XG4gICAgcmV0dXJuIFNwZWNpYWxGb3Jtcy5tYXAobmV3X21hcCk7XG4gIH1cblxuICByZXR1cm4gc2V0O1xufVxuXG5mdW5jdGlvbiBfZGlmZmVyZW5jZShzZXQxLCBzZXQyKSB7XG4gIGxldCBuZXdfbWFwID0gT2JqZWN0LmFzc2lnbih7fSwgc2V0MSk7XG5cbiAgZm9yIChsZXQgdmFsIG9mIHNldDEuc2V0KSB7XG4gICAgaWYgKF9tZW1iZXJfX3FtYXJrX18oc2V0MiwgdmFsKSkge1xuICAgICAgbmV3X21hcC5zZXQgPSBMaXN0LmRlbGV0ZShuZXdfbWFwLnNldCwgdmFsKTtcbiAgICB9XG4gIH1cblxuICByZXR1cm4gU3BlY2lhbEZvcm1zLm1hcChuZXdfbWFwKTtcbn1cblxuZnVuY3Rpb24gX2ludGVyc2VjdGlvbihzZXQxLCBzZXQyKSB7XG4gIGxldCBuZXdfbWFwID0gT2JqZWN0LmFzc2lnbih7fSwgc2V0MSk7XG5cbiAgZm9yIChsZXQgdmFsIG9mIHNldDEuc2V0KSB7XG4gICAgaWYgKCFfbWVtYmVyX19xbWFya19fKHNldDIsIHZhbCkpIHtcbiAgICAgIG5ld19tYXAuc2V0ID0gTGlzdC5kZWxldGUobmV3X21hcC5zZXQsIHZhbCk7XG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIFNwZWNpYWxGb3Jtcy5tYXAobmV3X21hcCk7XG59XG5cbmZ1bmN0aW9uIF91bmlvbihzZXQxLCBzZXQyKSB7XG4gIGxldCBuZXdfbWFwID0gc2V0MTtcblxuICBmb3IgKGxldCB2YWwgb2Ygc2V0Mi5zZXQpIHtcbiAgICBuZXdfbWFwID0gX3B1dChuZXdfbWFwLCB2YWwpO1xuICB9XG5cbiAgcmV0dXJuIFNwZWNpYWxGb3Jtcy5tYXAobmV3X21hcCk7XG59XG5cbmZ1bmN0aW9uIF9kaXNqb2luX19xbWFya19fKHNldDEsIHNldDIpIHtcbiAgZm9yIChsZXQgdmFsIG9mIHNldDEuc2V0KSB7XG4gICAgaWYgKF9tZW1iZXJfX3FtYXJrX18oc2V0MiwgdmFsKSkge1xuICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH1cbiAgfVxuXG4gIHJldHVybiB0cnVlO1xufVxuXG5mdW5jdGlvbiBfbWVtYmVyX19xbWFya19fKHNldCwgdmFsdWUpIHtcbiAgcmV0dXJuIHNldC5zZXQuaW5kZXhPZih2YWx1ZSkgPj0gMDtcbn1cblxuZnVuY3Rpb24gX2VxdWFsX19xbWFya19fKHNldDEsIHNldDIpIHtcbiAgcmV0dXJuIHNldDEuc2V0ID09PSBzZXQyLnNldDtcbn1cblxuZnVuY3Rpb24gX3N1YnNldF9fcW1hcmtfXyhzZXQxLCBzZXQyKSB7XG4gIGZvciAobGV0IHZhbCBvZiBzZXQxLnNldCkge1xuICAgIGlmICghX21lbWJlcl9fcW1hcmtfXyhzZXQyLCB2YWwpKSB7XG4gICAgICByZXR1cm4gZmFsc2U7XG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIHRydWU7XG59XG5cbnZhciBNYXBTZXQgPSB7XG4gIG5ldzogX19uZXdfXyxcbiAgc2l6ZTogX3NpemUsXG4gIHRvX2xpc3Q6IF90b19saXN0LFxuICBkaXNqb2luX19xbWFya19fOiBfZGlzam9pbl9fcW1hcmtfXyxcbiAgZGVsZXRlOiBfX19kZWxldGVfXyxcbiAgc3Vic2V0X19xbWFya19fOiBfc3Vic2V0X19xbWFya19fLFxuICBlcXVhbF9fcW1hcmtfXzogX2VxdWFsX19xbWFya19fLFxuICBtZW1iZXJfX3FtYXJrX186IF9tZW1iZXJfX3FtYXJrX18sXG4gIHB1dDogX3B1dCxcbiAgdW5pb246IF91bmlvbixcbiAgaW50ZXJzZWN0aW9uOiBfaW50ZXJzZWN0aW9uLFxuICBkaWZmZXJlbmNlOiBfZGlmZmVyZW5jZVxufTtcblxuZnVuY3Rpb24gc2l6ZShtYXApIHtcbiAgcmV0dXJuIE1hcFNldC5zaXplKG1hcCk7XG59XG5cbmZ1bmN0aW9uIHRvX2xpc3QobWFwKSB7XG4gIHJldHVybiBNYXBTZXQudG9fbGlzdChtYXApO1xufVxuXG5mdW5jdGlvbiBfX2RlbGV0ZV9fKHNldCwgdGVybSkge1xuICByZXR1cm4gTWFwU2V0LmRlbGV0ZShzZXQsIHRlcm0pO1xufVxuXG5mdW5jdGlvbiBwdXQoc2V0LCB0ZXJtKSB7XG4gIHJldHVybiBNYXBTZXQucHV0KHNldCwgdGVybSk7XG59XG5cbmZ1bmN0aW9uIGRpZmZlcmVuY2Uoc2V0MSwgc2V0Mikge1xuICByZXR1cm4gTWFwU2V0LmRpZmZlcmVuY2Uoc2V0MSwgc2V0Mik7XG59XG5cbmZ1bmN0aW9uIGludGVyc2VjdGlvbihzZXQxLCBzZXQyKSB7XG4gIHJldHVybiBNYXBTZXQuaW50ZXJzZWN0aW9uKHNldDEsIHNldDIpO1xufVxuXG5mdW5jdGlvbiB1bmlvbihzZXQxLCBzZXQyKSB7XG4gIHJldHVybiBNYXBTZXQudW5pb24oc2V0MSwgc2V0Mik7XG59XG5cbmZ1bmN0aW9uIGRpc2pvaW5fX3FtYXJrX18oc2V0MSwgc2V0Mikge1xuICByZXR1cm4gTWFwU2V0LmRpc2pvaW5fX3FtYXJrX18oc2V0MSwgc2V0Mik7XG59XG5cbmZ1bmN0aW9uIG1lbWJlcl9fcW1hcmtfXyhzZXQsIHZhbHVlKSB7XG4gIHJldHVybiBNYXBTZXQubWVtYmVyX19xbWFya19fKHNldDEsIHNldDIpO1xufVxuXG5mdW5jdGlvbiBlcXVhbF9fcW1hcmtfXyhzZXQxLCBzZXQyKSB7XG4gIHJldHVybiBNYXBTZXQuZXF1YWxfX3FtYXJrX18oc2V0MSwgc2V0Mik7XG59XG5cbmZ1bmN0aW9uIHN1YnNldF9fcW1hcmtfXyhzZXQxLCBzZXQyKSB7XG4gIHJldHVybiBNYXBTZXQuc3Vic2V0X19xbWFya19fKHNldDEsIHNldDIpO1xufVxuXG52YXIgX1NldCA9IHtcbiAgc2l6ZSxcbiAgdG9fbGlzdCxcbiAgZGlzam9pbl9fcW1hcmtfXyxcbiAgZGVsZXRlOiBfX2RlbGV0ZV9fLFxuICBzdWJzZXRfX3FtYXJrX18sXG4gIGVxdWFsX19xbWFya19fLFxuICBtZW1iZXJfX3FtYXJrX18sXG4gIHB1dCxcbiAgdW5pb24sXG4gIGludGVyc2VjdGlvbixcbiAgZGlmZmVyZW5jZVxufTtcblxuc2VsZi5wb3N0X29mZmljZSA9IHNlbGYucG9zdF9vZmZpY2UgfHwgbmV3IFBvc3RPZmZpY2UoKTtcblxuZXhwb3J0IHsgX1BhdHRlcm5zIGFzIFBhdHRlcm5zLCBCaXRTdHJpbmcsIEtlcm5lbCwgQXRvbSwgRW51bSwgSW50ZWdlciwgSlMsIExpc3QsIFJhbmdlLCBUdXBsZSwgQWdlbnQsIEtleXdvcmQsIEJhc2UsIF9TdHJpbmcgYXMgU3RyaW5nLCBCaXR3aXNlLCBFbnVtZXJhYmxlLCBDb2xsZWN0YWJsZSwgSW5zcGVjdCwgX01hcCBhcyBNYXAsIF9TZXQgYXMgU2V0LCBNYXBTZXQsIEludGVnZXJUeXBlLCBGbG9hdFR5cGUgfTsiXSwiZmlsZSI6ImVsaXhpci5qcyIsInNvdXJjZVJvb3QiOiIvc291cmNlLyJ9 \ No newline at end of file diff --git a/priv/javascript/elixir.js b/src/javascript/elixir.js similarity index 100% rename from priv/javascript/elixir.js rename to src/javascript/elixir.js diff --git a/priv/javascript/lib/agent.js b/src/javascript/lib/agent.js similarity index 100% rename from priv/javascript/lib/agent.js rename to src/javascript/lib/agent.js diff --git a/priv/javascript/lib/atom.js b/src/javascript/lib/atom.js similarity index 100% rename from priv/javascript/lib/atom.js rename to src/javascript/lib/atom.js diff --git a/priv/javascript/lib/base.js b/src/javascript/lib/base.js similarity index 100% rename from priv/javascript/lib/base.js rename to src/javascript/lib/base.js diff --git a/priv/javascript/lib/bit_string.js b/src/javascript/lib/bit_string.js similarity index 100% rename from priv/javascript/lib/bit_string.js rename to src/javascript/lib/bit_string.js diff --git a/priv/javascript/lib/bitwise.js b/src/javascript/lib/bitwise.js similarity index 100% rename from priv/javascript/lib/bitwise.js rename to src/javascript/lib/bitwise.js diff --git a/priv/javascript/lib/collectable.js b/src/javascript/lib/collectable.js similarity index 100% rename from priv/javascript/lib/collectable.js rename to src/javascript/lib/collectable.js diff --git a/priv/javascript/lib/enum.js b/src/javascript/lib/enum.js similarity index 100% rename from priv/javascript/lib/enum.js rename to src/javascript/lib/enum.js diff --git a/priv/javascript/lib/enumerable.js b/src/javascript/lib/enumerable.js similarity index 100% rename from priv/javascript/lib/enumerable.js rename to src/javascript/lib/enumerable.js diff --git a/priv/javascript/lib/inspect.js b/src/javascript/lib/inspect.js similarity index 100% rename from priv/javascript/lib/inspect.js rename to src/javascript/lib/inspect.js diff --git a/priv/javascript/lib/integer.js b/src/javascript/lib/integer.js similarity index 100% rename from priv/javascript/lib/integer.js rename to src/javascript/lib/integer.js diff --git a/priv/javascript/lib/js.js b/src/javascript/lib/js.js similarity index 100% rename from priv/javascript/lib/js.js rename to src/javascript/lib/js.js diff --git a/priv/javascript/lib/kernel.js b/src/javascript/lib/kernel.js similarity index 100% rename from priv/javascript/lib/kernel.js rename to src/javascript/lib/kernel.js diff --git a/priv/javascript/lib/kernel/special_forms.js b/src/javascript/lib/kernel/special_forms.js similarity index 100% rename from priv/javascript/lib/kernel/special_forms.js rename to src/javascript/lib/kernel/special_forms.js diff --git a/priv/javascript/lib/keyword.js b/src/javascript/lib/keyword.js similarity index 100% rename from priv/javascript/lib/keyword.js rename to src/javascript/lib/keyword.js diff --git a/priv/javascript/lib/list.js b/src/javascript/lib/list.js similarity index 100% rename from priv/javascript/lib/list.js rename to src/javascript/lib/list.js diff --git a/priv/javascript/lib/list/chars.js b/src/javascript/lib/list/chars.js similarity index 100% rename from priv/javascript/lib/list/chars.js rename to src/javascript/lib/list/chars.js diff --git a/priv/javascript/lib/map.js b/src/javascript/lib/map.js similarity index 100% rename from priv/javascript/lib/map.js rename to src/javascript/lib/map.js diff --git a/priv/javascript/lib/map_set.js b/src/javascript/lib/map_set.js similarity index 100% rename from priv/javascript/lib/map_set.js rename to src/javascript/lib/map_set.js diff --git a/priv/javascript/lib/patterns/patterns.js b/src/javascript/lib/patterns/patterns.js similarity index 100% rename from priv/javascript/lib/patterns/patterns.js rename to src/javascript/lib/patterns/patterns.js diff --git a/priv/javascript/lib/patterns/patterns/checks.js b/src/javascript/lib/patterns/patterns/checks.js similarity index 100% rename from priv/javascript/lib/patterns/patterns/checks.js rename to src/javascript/lib/patterns/patterns/checks.js diff --git a/priv/javascript/lib/patterns/patterns/defmatch.js b/src/javascript/lib/patterns/patterns/defmatch.js similarity index 100% rename from priv/javascript/lib/patterns/patterns/defmatch.js rename to src/javascript/lib/patterns/patterns/defmatch.js diff --git a/priv/javascript/lib/patterns/patterns/match.js b/src/javascript/lib/patterns/patterns/match.js similarity index 100% rename from priv/javascript/lib/patterns/patterns/match.js rename to src/javascript/lib/patterns/patterns/match.js diff --git a/priv/javascript/lib/patterns/patterns/resolvers.js b/src/javascript/lib/patterns/patterns/resolvers.js similarity index 100% rename from priv/javascript/lib/patterns/patterns/resolvers.js rename to src/javascript/lib/patterns/patterns/resolvers.js diff --git a/priv/javascript/lib/patterns/patterns/types.js b/src/javascript/lib/patterns/patterns/types.js similarity index 100% rename from priv/javascript/lib/patterns/patterns/types.js rename to src/javascript/lib/patterns/patterns/types.js diff --git a/priv/javascript/lib/post_office.js b/src/javascript/lib/post_office.js similarity index 100% rename from priv/javascript/lib/post_office.js rename to src/javascript/lib/post_office.js diff --git a/priv/javascript/lib/processes/processes.js b/src/javascript/lib/processes/processes.js similarity index 100% rename from priv/javascript/lib/processes/processes.js rename to src/javascript/lib/processes/processes.js diff --git a/priv/javascript/lib/processes/processes/mailbox.js b/src/javascript/lib/processes/processes/mailbox.js similarity index 100% rename from priv/javascript/lib/processes/processes/mailbox.js rename to src/javascript/lib/processes/processes/mailbox.js diff --git a/priv/javascript/lib/processes/processes/otp/application.js b/src/javascript/lib/processes/processes/otp/application.js similarity index 100% rename from priv/javascript/lib/processes/processes/otp/application.js rename to src/javascript/lib/processes/processes/otp/application.js diff --git a/priv/javascript/lib/processes/processes/otp/gen_event.js b/src/javascript/lib/processes/processes/otp/gen_event.js similarity index 100% rename from priv/javascript/lib/processes/processes/otp/gen_event.js rename to src/javascript/lib/processes/processes/otp/gen_event.js diff --git a/priv/javascript/lib/processes/processes/otp/gen_server.js b/src/javascript/lib/processes/processes/otp/gen_server.js similarity index 100% rename from priv/javascript/lib/processes/processes/otp/gen_server.js rename to src/javascript/lib/processes/processes/otp/gen_server.js diff --git a/priv/javascript/lib/processes/processes/pid.js b/src/javascript/lib/processes/processes/pid.js similarity index 100% rename from priv/javascript/lib/processes/processes/pid.js rename to src/javascript/lib/processes/processes/pid.js diff --git a/priv/javascript/lib/processes/processes/process.js b/src/javascript/lib/processes/processes/process.js similarity index 100% rename from priv/javascript/lib/processes/processes/process.js rename to src/javascript/lib/processes/processes/process.js diff --git a/priv/javascript/lib/processes/processes/process_system.js b/src/javascript/lib/processes/processes/process_system.js similarity index 100% rename from priv/javascript/lib/processes/processes/process_system.js rename to src/javascript/lib/processes/processes/process_system.js diff --git a/priv/javascript/lib/processes/processes/scheduler.js b/src/javascript/lib/processes/processes/scheduler.js similarity index 100% rename from priv/javascript/lib/processes/processes/scheduler.js rename to src/javascript/lib/processes/processes/scheduler.js diff --git a/priv/javascript/lib/processes/processes/states.js b/src/javascript/lib/processes/processes/states.js similarity index 100% rename from priv/javascript/lib/processes/processes/states.js rename to src/javascript/lib/processes/processes/states.js diff --git a/priv/javascript/lib/protocol.js b/src/javascript/lib/protocol.js similarity index 100% rename from priv/javascript/lib/protocol.js rename to src/javascript/lib/protocol.js diff --git a/priv/javascript/lib/range.js b/src/javascript/lib/range.js similarity index 100% rename from priv/javascript/lib/range.js rename to src/javascript/lib/range.js diff --git a/priv/javascript/lib/set.js b/src/javascript/lib/set.js similarity index 100% rename from priv/javascript/lib/set.js rename to src/javascript/lib/set.js diff --git a/priv/javascript/lib/signals.js b/src/javascript/lib/signals.js similarity index 100% rename from priv/javascript/lib/signals.js rename to src/javascript/lib/signals.js diff --git a/priv/javascript/lib/string.js b/src/javascript/lib/string.js similarity index 100% rename from priv/javascript/lib/string.js rename to src/javascript/lib/string.js diff --git a/priv/javascript/lib/string/chars.js b/src/javascript/lib/string/chars.js similarity index 100% rename from priv/javascript/lib/string/chars.js rename to src/javascript/lib/string/chars.js diff --git a/priv/javascript/lib/tuple.js b/src/javascript/lib/tuple.js similarity index 100% rename from priv/javascript/lib/tuple.js rename to src/javascript/lib/tuple.js diff --git a/priv/javascript/tests/atom.spec.js b/src/javascript/tests/atom.spec.js similarity index 100% rename from priv/javascript/tests/atom.spec.js rename to src/javascript/tests/atom.spec.js diff --git a/priv/javascript/tests/bit_string.spec.js b/src/javascript/tests/bit_string.spec.js similarity index 100% rename from priv/javascript/tests/bit_string.spec.js rename to src/javascript/tests/bit_string.spec.js diff --git a/priv/javascript/tests/case.spec.js b/src/javascript/tests/case.spec.js similarity index 100% rename from priv/javascript/tests/case.spec.js rename to src/javascript/tests/case.spec.js diff --git a/priv/javascript/tests/cond.spec.js b/src/javascript/tests/cond.spec.js similarity index 100% rename from priv/javascript/tests/cond.spec.js rename to src/javascript/tests/cond.spec.js diff --git a/priv/javascript/tests/enum.spec.js b/src/javascript/tests/enum.spec.js similarity index 100% rename from priv/javascript/tests/enum.spec.js rename to src/javascript/tests/enum.spec.js diff --git a/priv/javascript/tests/for.spec.js b/src/javascript/tests/for.spec.js similarity index 100% rename from priv/javascript/tests/for.spec.js rename to src/javascript/tests/for.spec.js diff --git a/priv/javascript/tests/integer.spec.js b/src/javascript/tests/integer.spec.js similarity index 100% rename from priv/javascript/tests/integer.spec.js rename to src/javascript/tests/integer.spec.js diff --git a/priv/javascript/tests/kernel.spec.js b/src/javascript/tests/kernel.spec.js similarity index 100% rename from priv/javascript/tests/kernel.spec.js rename to src/javascript/tests/kernel.spec.js diff --git a/priv/javascript/tests/list.spec.js b/src/javascript/tests/list.spec.js similarity index 100% rename from priv/javascript/tests/list.spec.js rename to src/javascript/tests/list.spec.js diff --git a/priv/javascript/tests/map.spec.js b/src/javascript/tests/map.spec.js similarity index 100% rename from priv/javascript/tests/map.spec.js rename to src/javascript/tests/map.spec.js diff --git a/priv/javascript/tests/patterns/defmatch.spec.js b/src/javascript/tests/patterns/defmatch.spec.js similarity index 100% rename from priv/javascript/tests/patterns/defmatch.spec.js rename to src/javascript/tests/patterns/defmatch.spec.js diff --git a/priv/javascript/tests/patterns/match.spec.js b/src/javascript/tests/patterns/match.spec.js similarity index 100% rename from priv/javascript/tests/patterns/match.spec.js rename to src/javascript/tests/patterns/match.spec.js diff --git a/priv/javascript/tests/range.spec.js b/src/javascript/tests/range.spec.js similarity index 100% rename from priv/javascript/tests/range.spec.js rename to src/javascript/tests/range.spec.js diff --git a/priv/javascript/tests/set.spec.js b/src/javascript/tests/set.spec.js similarity index 100% rename from priv/javascript/tests/set.spec.js rename to src/javascript/tests/set.spec.js diff --git a/priv/javascript/tests/special_forms.spec.js b/src/javascript/tests/special_forms.spec.js similarity index 100% rename from priv/javascript/tests/special_forms.spec.js rename to src/javascript/tests/special_forms.spec.js diff --git a/priv/javascript/tests/string.chars.spec.js b/src/javascript/tests/string.chars.spec.js similarity index 100% rename from priv/javascript/tests/string.chars.spec.js rename to src/javascript/tests/string.chars.spec.js diff --git a/priv/javascript/tests/try.spec.js b/src/javascript/tests/try.spec.js similarity index 100% rename from priv/javascript/tests/try.spec.js rename to src/javascript/tests/try.spec.js diff --git a/priv/javascript/tests/tuple.spec.js b/src/javascript/tests/tuple.spec.js similarity index 100% rename from priv/javascript/tests/tuple.spec.js rename to src/javascript/tests/tuple.spec.js From 29a586f1e692ee1cbca75a28619d1377475c1cba Mon Sep 17 00:00:00 2001 From: Sonny Scroggin Date: Wed, 25 Nov 2015 20:17:21 -0600 Subject: [PATCH 058/860] Code cleanup A few tweaks to make things a little cleaner --- lib/elixir_script.ex | 128 +++++++++++++++++++------------------ lib/elixir_script/state.ex | 92 +++++++++++++------------- 2 files changed, 112 insertions(+), 108 deletions(-) diff --git a/lib/elixir_script.ex b/lib/elixir_script.ex index 711be25c..69ec06c7 100644 --- a/lib/elixir_script.ex +++ b/lib/elixir_script.ex @@ -26,7 +26,7 @@ defmodule ElixirScript do @doc """ Compiles the given Elixir code string """ - @spec compile(binary, Dict.t) :: [binary | { binary, binary }] + @spec compile(binary, Dict.t) :: [binary | {binary, binary}] def compile(elixir_code, opts \\ []) do elixir_code |> Code.string_to_quoted! @@ -36,24 +36,23 @@ defmodule ElixirScript do @doc """ Compiles the given Elixir code in quoted form """ - @spec compile_quoted(Macro.t, Dict.t) :: [binary | { binary, binary }] + @spec compile_quoted(Macro.t, Dict.t) :: [binary | {binary, binary}] def compile_quoted(quoted, opts \\ []) do include_path = Dict.get(opts, :include_path, false) root = Dict.get(opts, :root) env = Dict.get(opts, :env, custom_env) import_standard_libs? = Dict.get(opts, :import_standard_libs, true) - ElixirScript.State.start_link(root, env) - build_environment([quoted]) + build_environment([quoted]) create_code(include_path, import_standard_libs?) end @doc """ Compiles the elixir files found at the given path """ - @spec compile_path(binary, Dict.t) :: [binary | { binary, binary }] + @spec compile_path(binary, Dict.t) :: [binary | {binary, binary}] def compile_path(path, opts \\ []) do include_path = Dict.get(opts, :include_path, false) root = Dict.get(opts, :root) @@ -63,16 +62,18 @@ defmodule ElixirScript do path |> Path.wildcard - |> Enum.map(fn(x) -> - File.read!(x) - |> Code.string_to_quoted! - end) + |> Enum.map(&file_to_quoted/1) |> build_environment - create_code(include_path, true) end + defp file_to_quoted(file) do + file + |> File.read! + |> Code.string_to_quoted! + end + defp build_environment(code_list) do code_list |> ElixirScript.Preprocess.Modules.get_info @@ -86,35 +87,37 @@ defmodule ElixirScript do defp create_code(include_path, import_standard_libs?) do - ElixirScript.State.process_imports() + ElixirScript.State.process_imports - state = ElixirScript.State.get() + state = ElixirScript.State.get - current = self + parent = self - result = state.modules - |> Enum.map(fn(x) -> - spawn_link fn -> - Process.put(:current_module, x.name) + result = + state.modules + |> Enum.map(fn ast -> + spawn_link fn -> + Process.put(:current_module, ast.name) - result = ElixirScript.Translator.Module.make_module(x.name, x.body, state.env) - |> Enum.map(fn(x) -> - convert_to_code(x, state.root, include_path, state.env, import_standard_libs?) - end) - send current, { self, result } - end - end) - |> Enum.map(fn (pid) -> - receive do { ^pid, x } -> x end - end) - |> List.flatten - - protocol_result = state.protocols |> Dict.to_list - |> ElixirScript.Translator.Protocol.consolidate(state.env) - |> Enum.map(fn(x) -> - convert_to_code(x, state.root, include_path, state.env, import_standard_libs?) + result = + ElixirScript.Translator.Module.make_module(ast.name, ast.body, state.env) + |> Enum.map(&(convert_to_code(&1, state.root, include_path, state.env, import_standard_libs?))) + send parent, {self, result} + end + end) + |> Enum.map(fn pid -> + receive do + {^pid, x} -> x + end end) - |> List.flatten + |> List.flatten + + protocol_result = + state.protocols + |> Dict.to_list + |> ElixirScript.Translator.Protocol.consolidate(state.env) + |> Enum.map(&(convert_to_code(&1, state.root, include_path, state.env, import_standard_libs?))) + |> List.flatten ElixirScript.State.stop @@ -137,60 +140,61 @@ defmodule ElixirScript do end defp convert_to_code(js_ast, root, include_path, env, import_standard_libs) do - js_ast - |> process_module(root, env, import_standard_libs) - |> javascript_ast_to_code - |> process_include_path(include_path) + js_ast + |> process_module(root, env, import_standard_libs) + |> javascript_ast_to_code + |> process_include_path(include_path) end defp process_module(%JSModule{} = module, root, env, import_standard_libs) do file_path = create_file_name(module) - standard_libs_import = if import_standard_libs do - ElixirScript.Translator.Import.create_standard_lib_imports(root, env) - else - [] - end + standard_libs_import = + if import_standard_libs do + ElixirScript.Translator.Import.create_standard_lib_imports(root, env) + else + [] + end - program = standard_libs_import ++ module.body - |> ESTree.Tools.Builder.program + program = + standard_libs_import ++ module.body + |> ESTree.Tools.Builder.program - { file_path, program } + {file_path, program} end - defp process_module(module, _root, _, _) do - { "", module } - end + defp process_module(module, _root, _, _), + do: {"", module} - defp create_file_name(%JSModule{ name: module_list }) do + defp create_file_name(%JSModule{name: module_list}) do name = ElixirScript.Translator.Import.make_file_path(module_list) "#{name}.js" end - defp process_include_path({ _, _ } = pair, true) do - pair - end + defp process_include_path({_, _} = pair, true), + do: pair - defp process_include_path({ _, code }, false) do - code - end + defp process_include_path({_, code}, false), + do: code @doc false - def javascript_ast_to_code({ path, js_ast }) do + def javascript_ast_to_code({path, js_ast}) do js_code = javascript_ast_to_code(js_ast) - { path, js_code } + {path, js_code} end @doc false def javascript_ast_to_code(js_ast) do - prepare_js_ast(js_ast) + js_ast + |> prepare_js_ast |> Generator.generate end defp prepare_js_ast(js_ast) do case js_ast do modules when is_list(modules) -> - Enum.reduce(modules, [], fn(x, list) -> list ++ x.body end) + modules + |> Enum.reduce([], &(&2 ++ &1.body)) |> Builder.program %ElixirScript.Translator.Group{body: body} -> Builder.program(body) @@ -199,7 +203,7 @@ defmodule ElixirScript do end end - defp operating_path() do + defp operating_path do try do Mix.Project.build_path <> "/lib/elixir_script/priv" rescue @@ -210,6 +214,4 @@ defmodule ElixirScript do Path.join(replaced_path) end end - - end diff --git a/lib/elixir_script/state.ex b/lib/elixir_script/state.ex index c492b888..853e822f 100644 --- a/lib/elixir_script/state.ex +++ b/lib/elixir_script/state.ex @@ -2,114 +2,112 @@ defmodule ElixirScript.State do @moduledoc false def start_link(root, env \\ __ENV__) do - Agent.start_link(fn -> %ElixirScript.Env{ root: root, env: env } end, name: __MODULE__) + Agent.start_link(fn -> + %ElixirScript.Env{root: root, env: env} + end, name: __MODULE__) end def update_env(env) do - Agent.update(__MODULE__, fn(state) -> - %{state | env: env } + Agent.update(__MODULE__, fn state -> + %{state | env: env} end) end def add_module(module) do - Agent.update(__MODULE__, fn(state) -> - %{ state | modules: Set.put(state.modules, module) } + Agent.update(__MODULE__, fn state -> + %{state | modules: Set.put(state.modules, module)} end) end def delete_module(module) do - Agent.update(__MODULE__, fn(state) -> - %{ state | modules: Set.delete(state.modules, module) } + Agent.update(__MODULE__, fn state -> + %{state | modules: Set.delete(state.modules, module)} end) end def module_listed?(module_name) do - Agent.get(__MODULE__, fn(state) -> + Agent.get(__MODULE__, fn state -> Enum.any?(state.modules, fn(x) -> x.name == module_name end) || Enum.any?(state.protocols, fn({key, _}) -> key == module_name end) end) end def protocol_listed?(module_name) do - Agent.get(__MODULE__, fn(state) -> + Agent.get(__MODULE__, fn state -> Enum.any?(state.protocols, fn({key, _}) -> key == module_name end) end) end def add_protocol(name, spec) do - Agent.update(__MODULE__, fn(state) -> + Agent.update(__MODULE__, fn state -> proto = Dict.get(state.protocols, name) if proto == nil do - proto = %{name: name, spec: spec, impls: HashDict.new } + proto = %{name: name, spec: spec, impls: HashDict.new} else - proto = %{ proto | spec: spec } + proto = %{proto | spec: spec} end - %{ state | protocols: Dict.put(state.protocols, name, proto) } + %{state | protocols: Dict.put(state.protocols, name, proto)} end) end def add_protocol_impl(protocol, type, impl) when is_list(type) do - Enum.each(type, fn(x) -> + Enum.each(type, fn x -> add_protocol_impl(protocol, x, impl) end) end def add_protocol_impl(protocol, type, impl) do - Agent.update(__MODULE__, fn(state) -> + Agent.update(__MODULE__, fn state -> proto = Dict.get(state.protocols, protocol) if proto == nil do - proto = %{name: protocol, spec: nil, impls: HashDict.new } + proto = %{name: protocol, spec: nil, impls: HashDict.new} end - proto = %{ proto | impls: Dict.put(proto.impls, type, impl) } + proto = %{proto | impls: Dict.put(proto.impls, type, impl)} - %{ state | protocols: Dict.put(state.protocols, protocol, proto) } + %{state | protocols: Dict.put(state.protocols, protocol, proto)} end) end - def get() do - Agent.get(__MODULE__, fn(state) -> - state - end) + def get do + Agent.get(__MODULE__, &(&1)) end def get_module(module) when is_atom(module) do - module_name_list = Atom.to_string(module) + module + |> Atom.to_string |> String.split(".") |> tl - |> Enum.map(fn(x) -> String.to_atom(x) end) - - get_module(module_name_list) + |> Enum.map(fn x -> String.to_atom(x) end) + |> get_module end def get_module(module_name_list) do - state = Agent.get(__MODULE__, fn(state) -> - state - end) - + state = Agent.get(__MODULE__, &(&1)) do_get_module(state, module_name_list) end defp do_get_module(state, module) when is_atom(module) do - module_name_list = Atom.to_string(module) - |> String.split(".") - |> tl - |> Enum.map(fn(x) -> String.to_atom(x) end) + module_name_list = + module + |> Atom.to_string + |> String.split(".") + |> tl + |> Enum.map(fn x -> String.to_atom(x) end) do_get_module(state, module_name_list) end defp do_get_module(state, module_name_list) do - Enum.find(Set.to_list(state.modules), fn(x) -> + Enum.find(Set.to_list(state.modules), fn x -> x.name == module_name_list end) end - def add_alias(module_name_list, name) do module = get_module(module_name_list) @@ -125,14 +123,19 @@ defmodule ElixirScript.State do end end - def process_imports() do - Agent.update(__MODULE__, fn(state) -> - modules = state.modules - |> Enum.map(fn(x) -> - %{x | imports: Enum.map(x.imports, fn({y, options}) -> {y, get_imported_functions(state, y, options)} end)} - end) + def process_imports do + Agent.update(__MODULE__, fn state -> + modules = + state.modules + |> Enum.map(fn x -> + imports = + Enum.map(x.imports, fn {y, options} -> + {y, get_imported_functions(state, y, options)} + end) + %{x | imports: imports} + end) - %{ state | modules: Enum.into(modules, HashSet.new) } + %{state | modules: Enum.into(modules, HashSet.new)} end) end @@ -160,8 +163,7 @@ defmodule ElixirScript.State do ElixirScript.Module.functions(module) ++ ElixirScript.Module.macros(module) -- Keyword.keys(list) end - def stop() do + def stop do Agent.stop(__MODULE__) end - end From e98da1b0bcc552e6ad9751151a0351733db15e37 Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Thu, 26 Nov 2015 10:34:12 -0600 Subject: [PATCH 059/860] Html module with macros that expand to virtual-dom functions --- lib/elixir_script.ex | 3 +- lib/elixir_script/lib/html.ex | 59 + lib/elixir_script/lib/js.ex | 8 +- lib/elixir_script/lib/tags.txt | 116 ++ lib/elixir_script/preprocess/modules.ex | 7 + priv/elixir.js | 1616 ++++++++++++++++++++- src/javascript/elixir.js | 1 + src/javascript/lib/virtual-dom.js | 1699 +++++++++++++++++++++++ test/elixir_script_test.exs | 22 + test/test_helper.exs | 3 +- 10 files changed, 3524 insertions(+), 10 deletions(-) create mode 100644 lib/elixir_script/lib/html.ex create mode 100644 lib/elixir_script/lib/tags.txt create mode 100644 src/javascript/lib/virtual-dom.js diff --git a/lib/elixir_script.ex b/lib/elixir_script.ex index 711be25c..971e36a2 100644 --- a/lib/elixir_script.ex +++ b/lib/elixir_script.ex @@ -80,7 +80,8 @@ defmodule ElixirScript do defp custom_env() do require Logger - require ElixirScript.Lib.JS, as: JS + require ElixirScript.JS, as: JS + require ElixirScript.Html, as: Html __ENV__ end diff --git a/lib/elixir_script/lib/html.ex b/lib/elixir_script/lib/html.ex new file mode 100644 index 00000000..b55bc16a --- /dev/null +++ b/lib/elixir_script/lib/html.ex @@ -0,0 +1,59 @@ +defmodule ElixirScript.Html do + + @external_resource tags_path = Path.join([__DIR__, "tags.txt"]) + @tags (for line <- File.stream!(tags_path, [], :line) do + line |> String.strip |> String.to_atom + end) + + for tag <- @tags do + defmacro unquote(tag)(config \\ [], block \\ [do: nil]) do + tag = Atom.to_string(unquote(tag)) + + inner = case Keyword.get(block, :do) do + {:__block__, [], params} -> + params + nil -> + [] + x -> + [x] + end + + config = config_to_map(config) + + quote do + Elixir.VirtualDOM.h(unquote(tag), unquote(config), unquote_splicing(inner)) + end + end + end + + defp config_to_map(config) do + config = Enum.map(config, fn({key, value}) -> + if is_atom(key) do + {Atom.to_string(key), value} + else + {key, value} + end + end) + + {:%{}, [], config} + end + + defmacro create(element) do + quote do + Elixir.VirtualDOM.create(unquote(element)) + end + end + + defmacro diff(tree, newTree) do + quote do + Elixir.VirtualDOM.diff(unquote(tree), unquote(newTree)) + end + end + + defmacro patch(root, patches) do + quote do + Elixir.VirtualDOM.patch(unquote(root), unquote(patches)) + end + end + +end diff --git a/lib/elixir_script/lib/js.ex b/lib/elixir_script/lib/js.ex index f3e1901e..29e1125a 100644 --- a/lib/elixir_script/lib/js.ex +++ b/lib/elixir_script/lib/js.ex @@ -1,4 +1,4 @@ -defmodule ElixirScript.Lib.JS do +defmodule ElixirScript.JS do @doc """ Creates new JavaScript objects. @@ -25,8 +25,8 @@ defmodule ElixirScript.Lib.JS do but JavaScript modules work differently and have to be imported using this. - If module is not a list, then it is treated as a default import, - otherwise it is not. + If module is not a list, then it is treated as a default import, + otherwise it is not. ex: JS.import A, "a" #translates to "import {default as A} from 'a'" @@ -47,4 +47,4 @@ defmodule ElixirScript.Lib.JS do """ defmacro to_json(value) -end \ No newline at end of file +end diff --git a/lib/elixir_script/lib/tags.txt b/lib/elixir_script/lib/tags.txt new file mode 100644 index 00000000..a25d3355 --- /dev/null +++ b/lib/elixir_script/lib/tags.txt @@ -0,0 +1,116 @@ +doctype! +a +abbr +acronym +address +applet +area +article +aside +audio +b +base +basefont +bdi +bdo +big +blockquote +body +br +button +canvas +caption +center +cite +code +col +colgroup +command +datalist +dd +del +details +dfn +dir +div +dl +dt +em +embed +fieldset +figcaption +figure +font +footer +form +frame +frameset +h1 +head +header +hgroup +hr +html +i +iframe +img +input +ins +kbd +keygen +label +legend +li +link +map +mark +menu +meta +meter +nav +noframes +noscript +object +ol +optgroup +option +output +p +param +pre +progress +q +rp +rt +ruby +s +samp +script +section +select +small +source +span +strike +strong +style +sub +summary +sup +table +tbody +td +textarea +tfoot +th +thead +time +title +tr +track +tt +u +ul +var +video +wbr diff --git a/lib/elixir_script/preprocess/modules.ex b/lib/elixir_script/preprocess/modules.ex index af024c03..a6071aac 100644 --- a/lib/elixir_script/preprocess/modules.ex +++ b/lib/elixir_script/preprocess/modules.ex @@ -58,6 +58,13 @@ defmodule ElixirScript.Preprocess.Modules do end def do_get_info({:defmodule, _, [{:__aliases__, _, [:ElixirScript, :Temp]}, [do: body]]} = ast) do + body = case body do + {:__block__, _, _ } -> + Macro.expand(body, State.get().env) + _ -> + body + end + mod = %ElixirScript.Module{ name: [:ElixirScript, :Temp] , body: body } State.add_module(mod) diff --git a/priv/elixir.js b/priv/elixir.js index e581f8a4..f4e4df97 100644 --- a/priv/elixir.js +++ b/priv/elixir.js @@ -1,5 +1,5 @@ var Patterns = { - get default () { return _Patterns; } + get default () { return _Patterns; } }; class Tuple { @@ -2917,7 +2917,1617 @@ var _Set = { difference }; +let virtualDom = (function (e) { + return e(); +})(function () { + var define, module, exports; + return (function e(t, n, r) { + function s(o, u) { + if (!n[o]) { + if (!t[o]) { + var a = typeof require == "function" && require; + if (!u && a) return a(o, !0); + if (i) return i(o, !0); + var f = new Error("Cannot find module '" + o + "'"); + throw (f.code = "MODULE_NOT_FOUND", f); + } + var l = n[o] = { + exports: {} + }; + t[o][0].call(l.exports, function (e) { + var n = t[o][1][e]; + return s(n ? n : e); + }, l, l.exports, e, t, n, r); + } + return n[o].exports; + } + var i = typeof require == "function" && require; + for (var o = 0; o < r.length; o++) s(r[o]); + return s; + })({ + 1: [function (require, module, exports) { + + var createElement = require("./vdom/create-element.js"); + + module.exports = createElement; + }, { "./vdom/create-element.js": 15 }], 2: [function (require, module, exports) { + var diff = require("./vtree/diff.js"); + + module.exports = diff; + }, { "./vtree/diff.js": 35 }], 3: [function (require, module, exports) { + var h = require("./virtual-hyperscript/index.js"); + + module.exports = h; + }, { "./virtual-hyperscript/index.js": 22 }], 4: [function (require, module, exports) { + var diff = require("./diff.js"); + var patch = require("./patch.js"); + var h = require("./h.js"); + var create = require("./create-element.js"); + var VNode = require("./vnode/vnode.js"); + var VText = require("./vnode/vtext.js"); + + module.exports = { + diff: diff, + patch: patch, + h: h, + create: create, + VNode: VNode, + VText: VText + }; + }, { "./create-element.js": 1, "./diff.js": 2, "./h.js": 3, "./patch.js": 13, "./vnode/vnode.js": 31, "./vnode/vtext.js": 33 }], 5: [function (require, module, exports) { + /*! + * Cross-Browser Split 1.1.1 + * Copyright 2007-2012 Steven Levithan + * Available under the MIT License + * ECMAScript compliant, uniform cross-browser split method + */ + + /** + * Splits a string into an array of strings using a regex or string separator. Matches of the + * separator are not included in the result array. However, if `separator` is a regex that contains + * capturing groups, backreferences are spliced into the result each time `separator` is matched. + * Fixes browser bugs compared to the native `String.prototype.split` and can be used reliably + * cross-browser. + * @param {String} str String to split. + * @param {RegExp|String} separator Regex or string to use for separating the string. + * @param {Number} [limit] Maximum number of items to include in the result array. + * @returns {Array} Array of substrings. + * @example + * + * // Basic use + * split('a b c d', ' '); + * // -> ['a', 'b', 'c', 'd'] + * + * // With limit + * split('a b c d', ' ', 2); + * // -> ['a', 'b'] + * + * // Backreferences in result array + * split('..word1 word2..', /([a-z]+)(\d+)/i); + * // -> ['..', 'word', '1', ' ', 'word', '2', '..'] + */ + module.exports = (function split(undef) { + + var nativeSplit = String.prototype.split, + compliantExecNpcg = /()??/.exec("")[1] === undef, + + // NPCG: nonparticipating capturing group + self; + + self = function (str, separator, limit) { + // If `separator` is not a regex, use `nativeSplit` + if (Object.prototype.toString.call(separator) !== "[object RegExp]") { + return nativeSplit.call(str, separator, limit); + } + var output = [], + flags = (separator.ignoreCase ? "i" : "") + (separator.multiline ? "m" : "") + (separator.extended ? "x" : "") + (separator.sticky ? "y" : ""), + + // Firefox 3+ + lastLastIndex = 0, + + // Make `global` and avoid `lastIndex` issues by working with a copy + separator = new RegExp(separator.source, flags + "g"), + separator2, + match, + lastIndex, + lastLength; + str += ""; // Type-convert + if (!compliantExecNpcg) { + // Doesn't need flags gy, but they don't hurt + separator2 = new RegExp("^" + separator.source + "$(?!\\s)", flags); + } + /* Values for `limit`, per the spec: + * If undefined: 4294967295 // Math.pow(2, 32) - 1 + * If 0, Infinity, or NaN: 0 + * If positive number: limit = Math.floor(limit); if (limit > 4294967295) limit -= 4294967296; + * If negative number: 4294967296 - Math.floor(Math.abs(limit)) + * If other: Type-convert, then use the above rules + */ + limit = limit === undef ? -1 >>> 0 : // Math.pow(2, 32) - 1 + limit >>> 0; // ToUint32(limit) + while (match = separator.exec(str)) { + // `separator.lastIndex` is not reliable cross-browser + lastIndex = match.index + match[0].length; + if (lastIndex > lastLastIndex) { + output.push(str.slice(lastLastIndex, match.index)); + // Fix browsers whose `exec` methods don't consistently return `undefined` for + // nonparticipating capturing groups + if (!compliantExecNpcg && match.length > 1) { + match[0].replace(separator2, function () { + for (var i = 1; i < arguments.length - 2; i++) { + if (arguments[i] === undef) { + match[i] = undef; + } + } + }); + } + if (match.length > 1 && match.index < str.length) { + Array.prototype.push.apply(output, match.slice(1)); + } + lastLength = match[0].length; + lastLastIndex = lastIndex; + if (output.length >= limit) { + break; + } + } + if (separator.lastIndex === match.index) { + separator.lastIndex++; // Avoid an infinite loop + } + } + if (lastLastIndex === str.length) { + if (lastLength || !separator.test("")) { + output.push(""); + } + } else { + output.push(str.slice(lastLastIndex)); + } + return output.length > limit ? output.slice(0, limit) : output; + }; + + return self; + })(); + }, {}], 6: [function (require, module, exports) {}, {}], 7: [function (require, module, exports) { + "use strict"; + + var OneVersionConstraint = require("individual/one-version"); + + var MY_VERSION = "7"; + OneVersionConstraint("ev-store", MY_VERSION); + + var hashKey = "__EV_STORE_KEY@" + MY_VERSION; + + module.exports = EvStore; + + function EvStore(elem) { + var hash = elem[hashKey]; + + if (!hash) { + hash = elem[hashKey] = {}; + } + + return hash; + } + }, { "individual/one-version": 9 }], 8: [function (require, module, exports) { + (function (global) { + "use strict"; + + /*global window, global*/ + + var root = typeof window !== "undefined" ? window : typeof global !== "undefined" ? global : {}; + + module.exports = Individual; + + function Individual(key, value) { + if (key in root) { + return root[key]; + } + + root[key] = value; + + return value; + } + }).call(this, typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}); + }, {}], 9: [function (require, module, exports) { + "use strict"; + + var Individual = require("./index.js"); + + module.exports = OneVersion; + + function OneVersion(moduleName, version, defaultValue) { + var key = "__INDIVIDUAL_ONE_VERSION_" + moduleName; + var enforceKey = key + "_ENFORCE_SINGLETON"; + + var versionValue = Individual(enforceKey, version); + + if (versionValue !== version) { + throw new Error("Can only have one copy of " + moduleName + ".\n" + "You already have version " + versionValue + " installed.\n" + "This means you cannot install version " + version); + } + + return Individual(key, defaultValue); + } + }, { "./index.js": 8 }], 10: [function (require, module, exports) { + (function (global) { + var topLevel = typeof global !== "undefined" ? global : typeof window !== "undefined" ? window : {}; + var minDoc = require("min-document"); + + if (typeof document !== "undefined") { + module.exports = document; + } else { + var doccy = topLevel["__GLOBAL_DOCUMENT_CACHE@4"]; + + if (!doccy) { + doccy = topLevel["__GLOBAL_DOCUMENT_CACHE@4"] = minDoc; + } + + module.exports = doccy; + } + }).call(this, typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}); + }, { "min-document": 6 }], 11: [function (require, module, exports) { + "use strict"; + + module.exports = function isObject(x) { + return typeof x === "object" && x !== null; + }; + }, {}], 12: [function (require, module, exports) { + var nativeIsArray = Array.isArray; + var toString = Object.prototype.toString; + + module.exports = nativeIsArray || isArray; + + function isArray(obj) { + return toString.call(obj) === "[object Array]"; + } + }, {}], 13: [function (require, module, exports) { + var patch = require("./vdom/patch.js"); + + module.exports = patch; + }, { "./vdom/patch.js": 18 }], 14: [function (require, module, exports) { + var isObject = require("is-object"); + var isHook = require("../vnode/is-vhook.js"); + + module.exports = applyProperties; + + function applyProperties(node, props, previous) { + for (var propName in props) { + var propValue = props[propName]; + + if (propValue === undefined) { + removeProperty(node, propName, propValue, previous); + } else if (isHook(propValue)) { + removeProperty(node, propName, propValue, previous); + if (propValue.hook) { + propValue.hook(node, propName, previous ? previous[propName] : undefined); + } + } else { + if (isObject(propValue)) { + patchObject(node, props, previous, propName, propValue); + } else { + node[propName] = propValue; + } + } + } + } + + function removeProperty(node, propName, propValue, previous) { + if (previous) { + var previousValue = previous[propName]; + + if (!isHook(previousValue)) { + if (propName === "attributes") { + for (var attrName in previousValue) { + node.removeAttribute(attrName); + } + } else if (propName === "style") { + for (var i in previousValue) { + node.style[i] = ""; + } + } else if (typeof previousValue === "string") { + node[propName] = ""; + } else { + node[propName] = null; + } + } else if (previousValue.unhook) { + previousValue.unhook(node, propName, propValue); + } + } + } + + function patchObject(node, props, previous, propName, propValue) { + var previousValue = previous ? previous[propName] : undefined; + + // Set attributes + if (propName === "attributes") { + for (var attrName in propValue) { + var attrValue = propValue[attrName]; + + if (attrValue === undefined) { + node.removeAttribute(attrName); + } else { + node.setAttribute(attrName, attrValue); + } + } + + return; + } + + if (previousValue && isObject(previousValue) && getPrototype(previousValue) !== getPrototype(propValue)) { + node[propName] = propValue; + return; + } + + if (!isObject(node[propName])) { + node[propName] = {}; + } + + var replacer = propName === "style" ? "" : undefined; + + for (var k in propValue) { + var value = propValue[k]; + node[propName][k] = value === undefined ? replacer : value; + } + } + + function getPrototype(value) { + if (Object.getPrototypeOf) { + return Object.getPrototypeOf(value); + } else if (value.__proto__) { + return value.__proto__; + } else if (value.constructor) { + return value.constructor.prototype; + } + } + }, { "../vnode/is-vhook.js": 26, "is-object": 11 }], 15: [function (require, module, exports) { + var document = require("global/document"); + + var applyProperties = require("./apply-properties"); + + var isVNode = require("../vnode/is-vnode.js"); + var isVText = require("../vnode/is-vtext.js"); + var isWidget = require("../vnode/is-widget.js"); + var handleThunk = require("../vnode/handle-thunk.js"); + + module.exports = createElement; + + function createElement(vnode, opts) { + var doc = opts ? opts.document || document : document; + var warn = opts ? opts.warn : null; + + vnode = handleThunk(vnode).a; + + if (isWidget(vnode)) { + return vnode.init(); + } else if (isVText(vnode)) { + return doc.createTextNode(vnode.text); + } else if (!isVNode(vnode)) { + if (warn) { + warn("Item is not a valid virtual dom node", vnode); + } + return null; + } + + var node = vnode.namespace === null ? doc.createElement(vnode.tagName) : doc.createElementNS(vnode.namespace, vnode.tagName); + + var props = vnode.properties; + applyProperties(node, props); + + var children = vnode.children; + + for (var i = 0; i < children.length; i++) { + var childNode = createElement(children[i], opts); + if (childNode) { + node.appendChild(childNode); + } + } + + return node; + } + }, { "../vnode/handle-thunk.js": 24, "../vnode/is-vnode.js": 27, "../vnode/is-vtext.js": 28, "../vnode/is-widget.js": 29, "./apply-properties": 14, "global/document": 10 }], 16: [function (require, module, exports) { + // Maps a virtual DOM tree onto a real DOM tree in an efficient manner. + // We don't want to read all of the DOM nodes in the tree so we use + // the in-order tree indexing to eliminate recursion down certain branches. + // We only recurse into a DOM node if we know that it contains a child of + // interest. + + var noChild = {}; + + module.exports = domIndex; + + function domIndex(rootNode, tree, indices, nodes) { + if (!indices || indices.length === 0) { + return {}; + } else { + indices.sort(ascending); + return recurse(rootNode, tree, indices, nodes, 0); + } + } + + function recurse(rootNode, tree, indices, nodes, rootIndex) { + nodes = nodes || {}; + + if (rootNode) { + if (indexInRange(indices, rootIndex, rootIndex)) { + nodes[rootIndex] = rootNode; + } + + var vChildren = tree.children; + + if (vChildren) { + + var childNodes = rootNode.childNodes; + + for (var i = 0; i < tree.children.length; i++) { + rootIndex += 1; + + var vChild = vChildren[i] || noChild; + var nextIndex = rootIndex + (vChild.count || 0); + + // skip recursion down the tree if there are no nodes down here + if (indexInRange(indices, rootIndex, nextIndex)) { + recurse(childNodes[i], vChild, indices, nodes, rootIndex); + } + + rootIndex = nextIndex; + } + } + } + + return nodes; + } + + // Binary search for an index in the interval [left, right] + function indexInRange(indices, left, right) { + if (indices.length === 0) { + return false; + } + + var minIndex = 0; + var maxIndex = indices.length - 1; + var currentIndex; + var currentItem; + + while (minIndex <= maxIndex) { + currentIndex = (maxIndex + minIndex) / 2 >> 0; + currentItem = indices[currentIndex]; + + if (minIndex === maxIndex) { + return currentItem >= left && currentItem <= right; + } else if (currentItem < left) { + minIndex = currentIndex + 1; + } else if (currentItem > right) { + maxIndex = currentIndex - 1; + } else { + return true; + } + } + + return false; + } + + function ascending(a, b) { + return a > b ? 1 : -1; + } + }, {}], 17: [function (require, module, exports) { + var applyProperties = require("./apply-properties"); + + var isWidget = require("../vnode/is-widget.js"); + var VPatch = require("../vnode/vpatch.js"); + + var updateWidget = require("./update-widget"); + + module.exports = applyPatch; + + function applyPatch(vpatch, domNode, renderOptions) { + var type = vpatch.type; + var vNode = vpatch.vNode; + var patch = vpatch.patch; + + switch (type) { + case VPatch.REMOVE: + return removeNode(domNode, vNode); + case VPatch.INSERT: + return insertNode(domNode, patch, renderOptions); + case VPatch.VTEXT: + return stringPatch(domNode, vNode, patch, renderOptions); + case VPatch.WIDGET: + return widgetPatch(domNode, vNode, patch, renderOptions); + case VPatch.VNODE: + return vNodePatch(domNode, vNode, patch, renderOptions); + case VPatch.ORDER: + reorderChildren(domNode, patch); + return domNode; + case VPatch.PROPS: + applyProperties(domNode, patch, vNode.properties); + return domNode; + case VPatch.THUNK: + return replaceRoot(domNode, renderOptions.patch(domNode, patch, renderOptions)); + default: + return domNode; + } + } + + function removeNode(domNode, vNode) { + var parentNode = domNode.parentNode; + + if (parentNode) { + parentNode.removeChild(domNode); + } + + destroyWidget(domNode, vNode); + + return null; + } + + function insertNode(parentNode, vNode, renderOptions) { + var newNode = renderOptions.render(vNode, renderOptions); + + if (parentNode) { + parentNode.appendChild(newNode); + } + + return parentNode; + } + + function stringPatch(domNode, leftVNode, vText, renderOptions) { + var newNode; + + if (domNode.nodeType === 3) { + domNode.replaceData(0, domNode.length, vText.text); + newNode = domNode; + } else { + var parentNode = domNode.parentNode; + newNode = renderOptions.render(vText, renderOptions); + + if (parentNode && newNode !== domNode) { + parentNode.replaceChild(newNode, domNode); + } + } + + return newNode; + } + + function widgetPatch(domNode, leftVNode, widget, renderOptions) { + var updating = updateWidget(leftVNode, widget); + var newNode; + + if (updating) { + newNode = widget.update(leftVNode, domNode) || domNode; + } else { + newNode = renderOptions.render(widget, renderOptions); + } + + var parentNode = domNode.parentNode; + + if (parentNode && newNode !== domNode) { + parentNode.replaceChild(newNode, domNode); + } + + if (!updating) { + destroyWidget(domNode, leftVNode); + } + + return newNode; + } + + function vNodePatch(domNode, leftVNode, vNode, renderOptions) { + var parentNode = domNode.parentNode; + var newNode = renderOptions.render(vNode, renderOptions); + + if (parentNode && newNode !== domNode) { + parentNode.replaceChild(newNode, domNode); + } + + return newNode; + } + + function destroyWidget(domNode, w) { + if (typeof w.destroy === "function" && isWidget(w)) { + w.destroy(domNode); + } + } + + function reorderChildren(domNode, moves) { + var childNodes = domNode.childNodes; + var keyMap = {}; + var node; + var remove; + var insert; + + for (var i = 0; i < moves.removes.length; i++) { + remove = moves.removes[i]; + node = childNodes[remove.from]; + if (remove.key) { + keyMap[remove.key] = node; + } + domNode.removeChild(node); + } + + var length = childNodes.length; + for (var j = 0; j < moves.inserts.length; j++) { + insert = moves.inserts[j]; + node = keyMap[insert.key]; + // this is the weirdest bug i've ever seen in webkit + domNode.insertBefore(node, insert.to >= length++ ? null : childNodes[insert.to]); + } + } + + function replaceRoot(oldRoot, newRoot) { + if (oldRoot && newRoot && oldRoot !== newRoot && oldRoot.parentNode) { + oldRoot.parentNode.replaceChild(newRoot, oldRoot); + } + + return newRoot; + } + }, { "../vnode/is-widget.js": 29, "../vnode/vpatch.js": 32, "./apply-properties": 14, "./update-widget": 19 }], 18: [function (require, module, exports) { + var document = require("global/document"); + var isArray = require("x-is-array"); + + var render = require("./create-element"); + var domIndex = require("./dom-index"); + var patchOp = require("./patch-op"); + module.exports = patch; + + function patch(rootNode, patches, renderOptions) { + renderOptions = renderOptions || {}; + renderOptions.patch = renderOptions.patch && renderOptions.patch !== patch ? renderOptions.patch : patchRecursive; + renderOptions.render = renderOptions.render || render; + + return renderOptions.patch(rootNode, patches, renderOptions); + } + + function patchRecursive(rootNode, patches, renderOptions) { + var indices = patchIndices(patches); + + if (indices.length === 0) { + return rootNode; + } + + var index = domIndex(rootNode, patches.a, indices); + var ownerDocument = rootNode.ownerDocument; + + if (!renderOptions.document && ownerDocument !== document) { + renderOptions.document = ownerDocument; + } + + for (var i = 0; i < indices.length; i++) { + var nodeIndex = indices[i]; + rootNode = applyPatch(rootNode, index[nodeIndex], patches[nodeIndex], renderOptions); + } + + return rootNode; + } + + function applyPatch(rootNode, domNode, patchList, renderOptions) { + if (!domNode) { + return rootNode; + } + + var newNode; + + if (isArray(patchList)) { + for (var i = 0; i < patchList.length; i++) { + newNode = patchOp(patchList[i], domNode, renderOptions); + + if (domNode === rootNode) { + rootNode = newNode; + } + } + } else { + newNode = patchOp(patchList, domNode, renderOptions); + + if (domNode === rootNode) { + rootNode = newNode; + } + } + + return rootNode; + } + + function patchIndices(patches) { + var indices = []; + + for (var key in patches) { + if (key !== "a") { + indices.push(Number(key)); + } + } + + return indices; + } + }, { "./create-element": 15, "./dom-index": 16, "./patch-op": 17, "global/document": 10, "x-is-array": 12 }], 19: [function (require, module, exports) { + var isWidget = require("../vnode/is-widget.js"); + + module.exports = updateWidget; + + function updateWidget(a, b) { + if (isWidget(a) && isWidget(b)) { + if ("name" in a && "name" in b) { + return a.id === b.id; + } else { + return a.init === b.init; + } + } + + return false; + } + }, { "../vnode/is-widget.js": 29 }], 20: [function (require, module, exports) { + "use strict"; + + var EvStore = require("ev-store"); + + module.exports = EvHook; + + function EvHook(value) { + if (!(this instanceof EvHook)) { + return new EvHook(value); + } + + this.value = value; + } + + EvHook.prototype.hook = function (node, propertyName) { + var es = EvStore(node); + var propName = propertyName.substr(3); + + es[propName] = this.value; + }; + + EvHook.prototype.unhook = function (node, propertyName) { + var es = EvStore(node); + var propName = propertyName.substr(3); + + es[propName] = undefined; + }; + }, { "ev-store": 7 }], 21: [function (require, module, exports) { + "use strict"; + + module.exports = SoftSetHook; + + function SoftSetHook(value) { + if (!(this instanceof SoftSetHook)) { + return new SoftSetHook(value); + } + + this.value = value; + } + + SoftSetHook.prototype.hook = function (node, propertyName) { + if (node[propertyName] !== this.value) { + node[propertyName] = this.value; + } + }; + }, {}], 22: [function (require, module, exports) { + "use strict"; + + var isArray = require("x-is-array"); + + var VNode = require("../vnode/vnode.js"); + var VText = require("../vnode/vtext.js"); + var isVNode = require("../vnode/is-vnode"); + var isVText = require("../vnode/is-vtext"); + var isWidget = require("../vnode/is-widget"); + var isHook = require("../vnode/is-vhook"); + var isVThunk = require("../vnode/is-thunk"); + + var parseTag = require("./parse-tag.js"); + var softSetHook = require("./hooks/soft-set-hook.js"); + var evHook = require("./hooks/ev-hook.js"); + + module.exports = h; + + function h(tagName, properties, children) { + var childNodes = []; + var tag, props, key, namespace; + + if (!children && isChildren(properties)) { + children = properties; + props = {}; + } + + props = props || properties || {}; + tag = parseTag(tagName, props); + + // support keys + if (props.hasOwnProperty("key")) { + key = props.key; + props.key = undefined; + } + + // support namespace + if (props.hasOwnProperty("namespace")) { + namespace = props.namespace; + props.namespace = undefined; + } + + // fix cursor bug + if (tag === "INPUT" && !namespace && props.hasOwnProperty("value") && props.value !== undefined && !isHook(props.value)) { + props.value = softSetHook(props.value); + } + + transformProperties(props); + + if (children !== undefined && children !== null) { + addChild(children, childNodes, tag, props); + } + + return new VNode(tag, props, childNodes, key, namespace); + } + + function addChild(c, childNodes, tag, props) { + if (typeof c === "string") { + childNodes.push(new VText(c)); + } else if (typeof c === "number") { + childNodes.push(new VText(String(c))); + } else if (isChild(c)) { + childNodes.push(c); + } else if (isArray(c)) { + for (var i = 0; i < c.length; i++) { + addChild(c[i], childNodes, tag, props); + } + } else if (c === null || c === undefined) { + return; + } else { + throw UnexpectedVirtualElement({ + foreignObject: c, + parentVnode: { + tagName: tag, + properties: props + } + }); + } + } + + function transformProperties(props) { + for (var propName in props) { + if (props.hasOwnProperty(propName)) { + var value = props[propName]; + + if (isHook(value)) { + continue; + } + + if (propName.substr(0, 3) === "ev-") { + // add ev-foo support + props[propName] = evHook(value); + } + } + } + } + + function isChild(x) { + return isVNode(x) || isVText(x) || isWidget(x) || isVThunk(x); + } + + function isChildren(x) { + return typeof x === "string" || isArray(x) || isChild(x); + } + + function UnexpectedVirtualElement(data) { + var err = new Error(); + + err.type = "virtual-hyperscript.unexpected.virtual-element"; + err.message = "Unexpected virtual child passed to h().\n" + "Expected a VNode / Vthunk / VWidget / string but:\n" + "got:\n" + errorString(data.foreignObject) + ".\n" + "The parent vnode is:\n" + errorString(data.parentVnode); + "\n" + "Suggested fix: change your `h(..., [ ... ])` callsite."; + err.foreignObject = data.foreignObject; + err.parentVnode = data.parentVnode; + + return err; + } + + function errorString(obj) { + try { + return JSON.stringify(obj, null, " "); + } catch (e) { + return String(obj); + } + } + }, { "../vnode/is-thunk": 25, "../vnode/is-vhook": 26, "../vnode/is-vnode": 27, "../vnode/is-vtext": 28, "../vnode/is-widget": 29, "../vnode/vnode.js": 31, "../vnode/vtext.js": 33, "./hooks/ev-hook.js": 20, "./hooks/soft-set-hook.js": 21, "./parse-tag.js": 23, "x-is-array": 12 }], 23: [function (require, module, exports) { + "use strict"; + + var split = require("browser-split"); + + var classIdSplit = /([\.#]?[a-zA-Z0-9\u007F-\uFFFF_:-]+)/; + var notClassId = /^\.|#/; + + module.exports = parseTag; + + function parseTag(tag, props) { + if (!tag) { + return "DIV"; + } + + var noId = !props.hasOwnProperty("id"); + + var tagParts = split(tag, classIdSplit); + var tagName = null; + + if (notClassId.test(tagParts[1])) { + tagName = "DIV"; + } + + var classes, part, type, i; + + for (i = 0; i < tagParts.length; i++) { + part = tagParts[i]; + + if (!part) { + continue; + } + + type = part.charAt(0); + + if (!tagName) { + tagName = part; + } else if (type === ".") { + classes = classes || []; + classes.push(part.substring(1, part.length)); + } else if (type === "#" && noId) { + props.id = part.substring(1, part.length); + } + } + + if (classes) { + if (props.className) { + classes.push(props.className); + } + + props.className = classes.join(" "); + } + + return props.namespace ? tagName : tagName.toUpperCase(); + } + }, { "browser-split": 5 }], 24: [function (require, module, exports) { + var isVNode = require("./is-vnode"); + var isVText = require("./is-vtext"); + var isWidget = require("./is-widget"); + var isThunk = require("./is-thunk"); + + module.exports = handleThunk; + + function handleThunk(a, b) { + var renderedA = a; + var renderedB = b; + + if (isThunk(b)) { + renderedB = renderThunk(b, a); + } + + if (isThunk(a)) { + renderedA = renderThunk(a, null); + } + + return { + a: renderedA, + b: renderedB + }; + } + + function renderThunk(thunk, previous) { + var renderedThunk = thunk.vnode; + + if (!renderedThunk) { + renderedThunk = thunk.vnode = thunk.render(previous); + } + + if (!(isVNode(renderedThunk) || isVText(renderedThunk) || isWidget(renderedThunk))) { + throw new Error("thunk did not return a valid node"); + } + + return renderedThunk; + } + }, { "./is-thunk": 25, "./is-vnode": 27, "./is-vtext": 28, "./is-widget": 29 }], 25: [function (require, module, exports) { + module.exports = isThunk; + + function isThunk(t) { + return t && t.type === "Thunk"; + } + }, {}], 26: [function (require, module, exports) { + module.exports = isHook; + + function isHook(hook) { + return hook && (typeof hook.hook === "function" && !hook.hasOwnProperty("hook") || typeof hook.unhook === "function" && !hook.hasOwnProperty("unhook")); + } + }, {}], 27: [function (require, module, exports) { + var version = require("./version"); + + module.exports = isVirtualNode; + + function isVirtualNode(x) { + return x && x.type === "VirtualNode" && x.version === version; + } + }, { "./version": 30 }], 28: [function (require, module, exports) { + var version = require("./version"); + + module.exports = isVirtualText; + + function isVirtualText(x) { + return x && x.type === "VirtualText" && x.version === version; + } + }, { "./version": 30 }], 29: [function (require, module, exports) { + module.exports = isWidget; + + function isWidget(w) { + return w && w.type === "Widget"; + } + }, {}], 30: [function (require, module, exports) { + module.exports = "2"; + }, {}], 31: [function (require, module, exports) { + var version = require("./version"); + var isVNode = require("./is-vnode"); + var isWidget = require("./is-widget"); + var isThunk = require("./is-thunk"); + var isVHook = require("./is-vhook"); + + module.exports = VirtualNode; + + var noProperties = {}; + var noChildren = []; + + function VirtualNode(tagName, properties, children, key, namespace) { + this.tagName = tagName; + this.properties = properties || noProperties; + this.children = children || noChildren; + this.key = key != null ? String(key) : undefined; + this.namespace = typeof namespace === "string" ? namespace : null; + + var count = children && children.length || 0; + var descendants = 0; + var hasWidgets = false; + var hasThunks = false; + var descendantHooks = false; + var hooks; + + for (var propName in properties) { + if (properties.hasOwnProperty(propName)) { + var property = properties[propName]; + if (isVHook(property) && property.unhook) { + if (!hooks) { + hooks = {}; + } + + hooks[propName] = property; + } + } + } + + for (var i = 0; i < count; i++) { + var child = children[i]; + if (isVNode(child)) { + descendants += child.count || 0; + + if (!hasWidgets && child.hasWidgets) { + hasWidgets = true; + } + + if (!hasThunks && child.hasThunks) { + hasThunks = true; + } + + if (!descendantHooks && (child.hooks || child.descendantHooks)) { + descendantHooks = true; + } + } else if (!hasWidgets && isWidget(child)) { + if (typeof child.destroy === "function") { + hasWidgets = true; + } + } else if (!hasThunks && isThunk(child)) { + hasThunks = true; + } + } + + this.count = count + descendants; + this.hasWidgets = hasWidgets; + this.hasThunks = hasThunks; + this.hooks = hooks; + this.descendantHooks = descendantHooks; + } + + VirtualNode.prototype.version = version; + VirtualNode.prototype.type = "VirtualNode"; + }, { "./is-thunk": 25, "./is-vhook": 26, "./is-vnode": 27, "./is-widget": 29, "./version": 30 }], 32: [function (require, module, exports) { + var version = require("./version"); + + VirtualPatch.NONE = 0; + VirtualPatch.VTEXT = 1; + VirtualPatch.VNODE = 2; + VirtualPatch.WIDGET = 3; + VirtualPatch.PROPS = 4; + VirtualPatch.ORDER = 5; + VirtualPatch.INSERT = 6; + VirtualPatch.REMOVE = 7; + VirtualPatch.THUNK = 8; + + module.exports = VirtualPatch; + + function VirtualPatch(type, vNode, patch) { + this.type = Number(type); + this.vNode = vNode; + this.patch = patch; + } + + VirtualPatch.prototype.version = version; + VirtualPatch.prototype.type = "VirtualPatch"; + }, { "./version": 30 }], 33: [function (require, module, exports) { + var version = require("./version"); + + module.exports = VirtualText; + + function VirtualText(text) { + this.text = String(text); + } + + VirtualText.prototype.version = version; + VirtualText.prototype.type = "VirtualText"; + }, { "./version": 30 }], 34: [function (require, module, exports) { + var isObject = require("is-object"); + var isHook = require("../vnode/is-vhook"); + + module.exports = diffProps; + + function diffProps(a, b) { + var diff; + + for (var aKey in a) { + if (!(aKey in b)) { + diff = diff || {}; + diff[aKey] = undefined; + } + + var aValue = a[aKey]; + var bValue = b[aKey]; + + if (aValue === bValue) { + continue; + } else if (isObject(aValue) && isObject(bValue)) { + if (getPrototype(bValue) !== getPrototype(aValue)) { + diff = diff || {}; + diff[aKey] = bValue; + } else if (isHook(bValue)) { + diff = diff || {}; + diff[aKey] = bValue; + } else { + var objectDiff = diffProps(aValue, bValue); + if (objectDiff) { + diff = diff || {}; + diff[aKey] = objectDiff; + } + } + } else { + diff = diff || {}; + diff[aKey] = bValue; + } + } + + for (var bKey in b) { + if (!(bKey in a)) { + diff = diff || {}; + diff[bKey] = b[bKey]; + } + } + + return diff; + } + + function getPrototype(value) { + if (Object.getPrototypeOf) { + return Object.getPrototypeOf(value); + } else if (value.__proto__) { + return value.__proto__; + } else if (value.constructor) { + return value.constructor.prototype; + } + } + }, { "../vnode/is-vhook": 26, "is-object": 11 }], 35: [function (require, module, exports) { + var isArray = require("x-is-array"); + + var VPatch = require("../vnode/vpatch"); + var isVNode = require("../vnode/is-vnode"); + var isVText = require("../vnode/is-vtext"); + var isWidget = require("../vnode/is-widget"); + var isThunk = require("../vnode/is-thunk"); + var handleThunk = require("../vnode/handle-thunk"); + + var diffProps = require("./diff-props"); + + module.exports = diff; + + function diff(a, b) { + var patch = { a: a }; + walk(a, b, patch, 0); + return patch; + } + + function walk(a, b, patch, index) { + if (a === b) { + return; + } + + var apply = patch[index]; + var applyClear = false; + + if (isThunk(a) || isThunk(b)) { + thunks(a, b, patch, index); + } else if (b == null) { + + // If a is a widget we will add a remove patch for it + // Otherwise any child widgets/hooks must be destroyed. + // This prevents adding two remove patches for a widget. + if (!isWidget(a)) { + clearState(a, patch, index); + apply = patch[index]; + } + + apply = appendPatch(apply, new VPatch(VPatch.REMOVE, a, b)); + } else if (isVNode(b)) { + if (isVNode(a)) { + if (a.tagName === b.tagName && a.namespace === b.namespace && a.key === b.key) { + var propsPatch = diffProps(a.properties, b.properties); + if (propsPatch) { + apply = appendPatch(apply, new VPatch(VPatch.PROPS, a, propsPatch)); + } + apply = diffChildren(a, b, patch, apply, index); + } else { + apply = appendPatch(apply, new VPatch(VPatch.VNODE, a, b)); + applyClear = true; + } + } else { + apply = appendPatch(apply, new VPatch(VPatch.VNODE, a, b)); + applyClear = true; + } + } else if (isVText(b)) { + if (!isVText(a)) { + apply = appendPatch(apply, new VPatch(VPatch.VTEXT, a, b)); + applyClear = true; + } else if (a.text !== b.text) { + apply = appendPatch(apply, new VPatch(VPatch.VTEXT, a, b)); + } + } else if (isWidget(b)) { + if (!isWidget(a)) { + applyClear = true; + } + + apply = appendPatch(apply, new VPatch(VPatch.WIDGET, a, b)); + } + + if (apply) { + patch[index] = apply; + } + + if (applyClear) { + clearState(a, patch, index); + } + } + + function diffChildren(a, b, patch, apply, index) { + var aChildren = a.children; + var orderedSet = reorder(aChildren, b.children); + var bChildren = orderedSet.children; + + var aLen = aChildren.length; + var bLen = bChildren.length; + var len = aLen > bLen ? aLen : bLen; + + for (var i = 0; i < len; i++) { + var leftNode = aChildren[i]; + var rightNode = bChildren[i]; + index += 1; + + if (!leftNode) { + if (rightNode) { + // Excess nodes in b need to be added + apply = appendPatch(apply, new VPatch(VPatch.INSERT, null, rightNode)); + } + } else { + walk(leftNode, rightNode, patch, index); + } + + if (isVNode(leftNode) && leftNode.count) { + index += leftNode.count; + } + } + + if (orderedSet.moves) { + // Reorder nodes last + apply = appendPatch(apply, new VPatch(VPatch.ORDER, a, orderedSet.moves)); + } + + return apply; + } + + function clearState(vNode, patch, index) { + // TODO: Make this a single walk, not two + unhook(vNode, patch, index); + destroyWidgets(vNode, patch, index); + } + + // Patch records for all destroyed widgets must be added because we need + // a DOM node reference for the destroy function + function destroyWidgets(vNode, patch, index) { + if (isWidget(vNode)) { + if (typeof vNode.destroy === "function") { + patch[index] = appendPatch(patch[index], new VPatch(VPatch.REMOVE, vNode, null)); + } + } else if (isVNode(vNode) && (vNode.hasWidgets || vNode.hasThunks)) { + var children = vNode.children; + var len = children.length; + for (var i = 0; i < len; i++) { + var child = children[i]; + index += 1; + + destroyWidgets(child, patch, index); + + if (isVNode(child) && child.count) { + index += child.count; + } + } + } else if (isThunk(vNode)) { + thunks(vNode, null, patch, index); + } + } + + // Create a sub-patch for thunks + function thunks(a, b, patch, index) { + var nodes = handleThunk(a, b); + var thunkPatch = diff(nodes.a, nodes.b); + if (hasPatches(thunkPatch)) { + patch[index] = new VPatch(VPatch.THUNK, null, thunkPatch); + } + } + + function hasPatches(patch) { + for (var index in patch) { + if (index !== "a") { + return true; + } + } + + return false; + } + + // Execute hooks when two nodes are identical + function unhook(vNode, patch, index) { + if (isVNode(vNode)) { + if (vNode.hooks) { + patch[index] = appendPatch(patch[index], new VPatch(VPatch.PROPS, vNode, undefinedKeys(vNode.hooks))); + } + + if (vNode.descendantHooks || vNode.hasThunks) { + var children = vNode.children; + var len = children.length; + for (var i = 0; i < len; i++) { + var child = children[i]; + index += 1; + + unhook(child, patch, index); + + if (isVNode(child) && child.count) { + index += child.count; + } + } + } + } else if (isThunk(vNode)) { + thunks(vNode, null, patch, index); + } + } + + function undefinedKeys(obj) { + var result = {}; + + for (var key in obj) { + result[key] = undefined; + } + + return result; + } + + // List diff, naive left to right reordering + function reorder(aChildren, bChildren) { + // O(M) time, O(M) memory + var bChildIndex = keyIndex(bChildren); + var bKeys = bChildIndex.keys; + var bFree = bChildIndex.free; + + if (bFree.length === bChildren.length) { + return { + children: bChildren, + moves: null + }; + } + + // O(N) time, O(N) memory + var aChildIndex = keyIndex(aChildren); + var aKeys = aChildIndex.keys; + var aFree = aChildIndex.free; + + if (aFree.length === aChildren.length) { + return { + children: bChildren, + moves: null + }; + } + + // O(MAX(N, M)) memory + var newChildren = []; + + var freeIndex = 0; + var freeCount = bFree.length; + var deletedItems = 0; + + // Iterate through a and match a node in b + // O(N) time, + for (var i = 0; i < aChildren.length; i++) { + var aItem = aChildren[i]; + var itemIndex; + + if (aItem.key) { + if (bKeys.hasOwnProperty(aItem.key)) { + // Match up the old keys + itemIndex = bKeys[aItem.key]; + newChildren.push(bChildren[itemIndex]); + } else { + // Remove old keyed items + itemIndex = i - deletedItems++; + newChildren.push(null); + } + } else { + // Match the item in a with the next free item in b + if (freeIndex < freeCount) { + itemIndex = bFree[freeIndex++]; + newChildren.push(bChildren[itemIndex]); + } else { + // There are no free items in b to match with + // the free items in a, so the extra free nodes + // are deleted. + itemIndex = i - deletedItems++; + newChildren.push(null); + } + } + } + + var lastFreeIndex = freeIndex >= bFree.length ? bChildren.length : bFree[freeIndex]; + + // Iterate through b and append any new keys + // O(M) time + for (var j = 0; j < bChildren.length; j++) { + var newItem = bChildren[j]; + + if (newItem.key) { + if (!aKeys.hasOwnProperty(newItem.key)) { + // Add any new keyed items + // We are adding new items to the end and then sorting them + // in place. In future we should insert new items in place. + newChildren.push(newItem); + } + } else if (j >= lastFreeIndex) { + // Add any leftover non-keyed items + newChildren.push(newItem); + } + } + + var simulate = newChildren.slice(); + var simulateIndex = 0; + var removes = []; + var inserts = []; + var simulateItem; + + for (var k = 0; k < bChildren.length;) { + var wantedItem = bChildren[k]; + simulateItem = simulate[simulateIndex]; + + // remove items + while (simulateItem === null && simulate.length) { + removes.push(remove(simulate, simulateIndex, null)); + simulateItem = simulate[simulateIndex]; + } + + if (!simulateItem || simulateItem.key !== wantedItem.key) { + // if we need a key in this position... + if (wantedItem.key) { + if (simulateItem && simulateItem.key) { + // if an insert doesn't put this key in place, it needs to move + if (bKeys[simulateItem.key] !== k + 1) { + removes.push(remove(simulate, simulateIndex, simulateItem.key)); + simulateItem = simulate[simulateIndex]; + // if the remove didn't put the wanted item in place, we need to insert it + if (!simulateItem || simulateItem.key !== wantedItem.key) { + inserts.push({ key: wantedItem.key, to: k }); + } + // items are matching, so skip ahead + else { + simulateIndex++; + } + } else { + inserts.push({ key: wantedItem.key, to: k }); + } + } else { + inserts.push({ key: wantedItem.key, to: k }); + } + k++; + } + // a key in simulate has no matching wanted key, remove it + else if (simulateItem && simulateItem.key) { + removes.push(remove(simulate, simulateIndex, simulateItem.key)); + } + } else { + simulateIndex++; + k++; + } + } + + // remove all the remaining nodes from simulate + while (simulateIndex < simulate.length) { + simulateItem = simulate[simulateIndex]; + removes.push(remove(simulate, simulateIndex, simulateItem && simulateItem.key)); + } + + // If the only moves we have are deletes then we can just + // let the delete patch remove these items. + if (removes.length === deletedItems && !inserts.length) { + return { + children: newChildren, + moves: null + }; + } + + return { + children: newChildren, + moves: { + removes: removes, + inserts: inserts + } + }; + } + + function remove(arr, index, key) { + arr.splice(index, 1); + + return { + from: index, + key: key + }; + } + + function keyIndex(children) { + var keys = {}; + var free = []; + var length = children.length; + + for (var i = 0; i < length; i++) { + var child = children[i]; + + if (child.key) { + keys[child.key] = i; + } else { + free.push(i); + } + } + + return { + keys: keys, // A hash of key name to index + free: free // An array of unkeyed item indices + }; + } + + function appendPatch(apply, patch) { + if (apply) { + if (isArray(apply)) { + apply.push(patch); + } else { + apply = [apply, patch]; + } + + return apply; + } else { + return patch; + } + } + }, { "../vnode/handle-thunk": 24, "../vnode/is-thunk": 25, "../vnode/is-vnode": 27, "../vnode/is-vtext": 28, "../vnode/is-widget": 29, "../vnode/vpatch": 32, "./diff-props": 34, "x-is-array": 12 }] }, {}, [4])(4); +}); + + +// Proposed for ES6 + self.post_office = self.post_office || new PostOffice(); -export { _Patterns as Patterns, BitString, Kernel, Atom, Enum, Integer, JS, List, Range, Tuple, Agent, Keyword, Base, _String as String, Bitwise, Enumerable, Collectable, Inspect, _Map as Map, _Set as Set, MapSet, IntegerType, FloatType }; -//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiIiwic291cmNlcyI6WyJlbGl4aXIuanMiXSwic291cmNlc0NvbnRlbnQiOlsidmFyIFBhdHRlcm5zID0ge1xuICBnZXQgZGVmYXVsdCAoKSB7IHJldHVybiBfUGF0dGVybnM7IH1cbn07XG5cbmNsYXNzIFR1cGxlIHtcblxuICBjb25zdHJ1Y3RvciguLi5hcmdzKSB7XG4gICAgdGhpcy52YWx1ZXMgPSBPYmplY3QuZnJlZXplKGFyZ3MpO1xuICB9XG5cbiAgZ2V0KGluZGV4KSB7XG4gICAgcmV0dXJuIHRoaXMudmFsdWVzW2luZGV4XTtcbiAgfVxuXG4gIGNvdW50KCkge1xuICAgIHJldHVybiB0aGlzLnZhbHVlcy5sZW5ndGg7XG4gIH1cblxuICBbU3ltYm9sLml0ZXJhdG9yXSgpIHtcbiAgICByZXR1cm4gdGhpcy52YWx1ZXNbU3ltYm9sLml0ZXJhdG9yXSgpO1xuICB9XG5cbiAgdG9TdHJpbmcoKSB7XG4gICAgdmFyIGksXG4gICAgICAgIHMgPSBcIlwiO1xuICAgIGZvciAoaSA9IDA7IGkgPCB0aGlzLnZhbHVlcy5sZW5ndGg7IGkrKykge1xuICAgICAgaWYgKHMgIT09IFwiXCIpIHtcbiAgICAgICAgcyArPSBcIiwgXCI7XG4gICAgICB9XG4gICAgICBzICs9IHRoaXMudmFsdWVzW2ldLnRvU3RyaW5nKCk7XG4gICAgfVxuXG4gICAgcmV0dXJuIFwie1wiICsgcyArIFwifVwiO1xuICB9XG5cbiAgc3RhdGljIHRvX3N0cmluZyh0dXBsZSkge1xuICAgIHJldHVybiB0dXBsZS50b1N0cmluZygpO1xuICB9XG5cbiAgc3RhdGljIGRlbGV0ZV9hdCh0dXBsZSwgaW5kZXgpIHtcbiAgICBsZXQgbmV3X2xpc3QgPSBbXTtcblxuICAgIGZvciAodmFyIGkgPSAwOyBpIDwgdHVwbGUuY291bnQoKTsgaSsrKSB7XG4gICAgICBpZiAoaSAhPT0gaW5kZXgpIHtcbiAgICAgICAgbmV3X2xpc3QucHVzaCh0dXBsZS5nZXQoaSkpO1xuICAgICAgfVxuICAgIH1cblxuICAgIHJldHVybiBLZXJuZWwuU3BlY2lhbEZvcm1zLnR1cGxlLmFwcGx5KG51bGwsIG5ld19saXN0KTtcbiAgfVxuXG4gIHN0YXRpYyBkdXBsaWNhdGUoZGF0YSwgc2l6ZSkge1xuICAgIGxldCBhcnJheSA9IFtdO1xuXG4gICAgZm9yICh2YXIgaSA9IHNpemUgLSAxOyBpID49IDA7IGktLSkge1xuICAgICAgYXJyYXkucHVzaChkYXRhKTtcbiAgICB9XG5cbiAgICByZXR1cm4gS2VybmVsLlNwZWNpYWxGb3Jtcy50dXBsZS5hcHBseShudWxsLCBhcnJheSk7XG4gIH1cblxuICBzdGF0aWMgaW5zZXJ0X2F0KHR1cGxlLCBpbmRleCwgdGVybSkge1xuICAgIGxldCBuZXdfdHVwbGUgPSBbXTtcblxuICAgIGZvciAodmFyIGkgPSAwOyBpIDw9IHR1cGxlLmNvdW50KCk7IGkrKykge1xuICAgICAgaWYgKGkgPT09IGluZGV4KSB7XG4gICAgICAgIG5ld190dXBsZS5wdXNoKHRlcm0pO1xuICAgICAgICBpKys7XG4gICAgICAgIG5ld190dXBsZS5wdXNoKHR1cGxlLmdldChpKSk7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBuZXdfdHVwbGUucHVzaCh0dXBsZS5nZXQoaSkpO1xuICAgICAgfVxuICAgIH1cblxuICAgIHJldHVybiBLZXJuZWwuU3BlY2lhbEZvcm1zLnR1cGxlLmFwcGx5KG51bGwsIG5ld190dXBsZSk7XG4gIH1cblxuICBzdGF0aWMgZnJvbV9saXN0KGxpc3QpIHtcbiAgICByZXR1cm4gS2VybmVsLlNwZWNpYWxGb3Jtcy50dXBsZS5hcHBseShudWxsLCBsaXN0KTtcbiAgfVxuXG4gIHN0YXRpYyB0b19saXN0KHR1cGxlKSB7XG4gICAgbGV0IG5ld19saXN0ID0gW107XG5cbiAgICBmb3IgKHZhciBpID0gMDsgaSA8IHR1cGxlLmNvdW50KCk7IGkrKykge1xuICAgICAgbmV3X2xpc3QucHVzaCh0dXBsZS5nZXQoaSkpO1xuICAgIH1cblxuICAgIHJldHVybiBLZXJuZWwuU3BlY2lhbEZvcm1zLmxpc3QoLi4ubmV3X2xpc3QpO1xuICB9XG59XG5cbi8qIEBmbG93ICovXG5cbmNsYXNzIFZhcmlhYmxlIHtcblxuICBjb25zdHJ1Y3RvcihuYW1lID0gbnVsbCkge1xuICAgIHRoaXMubmFtZSA9IG5hbWU7XG4gIH1cbn1cblxuY2xhc3MgV2lsZGNhcmQge1xuICBjb25zdHJ1Y3RvcigpIHt9XG59XG5cbmNsYXNzIFN0YXJ0c1dpdGgge1xuXG4gIGNvbnN0cnVjdG9yKHByZWZpeCkge1xuICAgIHRoaXMucHJlZml4ID0gcHJlZml4O1xuICB9XG59XG5cbmNsYXNzIENhcHR1cmUge1xuXG4gIGNvbnN0cnVjdG9yKHZhbHVlKSB7XG4gICAgdGhpcy52YWx1ZSA9IHZhbHVlO1xuICB9XG59XG5cbmNsYXNzIEhlYWRUYWlsIHtcbiAgY29uc3RydWN0b3IoKSB7fVxufVxuXG5jbGFzcyBUeXBlIHtcblxuICBjb25zdHJ1Y3Rvcih0eXBlLCBvYmpQYXR0ZXJuID0ge30pIHtcbiAgICB0aGlzLnR5cGUgPSB0eXBlO1xuICAgIHRoaXMub2JqUGF0dGVybiA9IG9ialBhdHRlcm47XG4gIH1cbn1cblxuY2xhc3MgQm91bmQge1xuXG4gIGNvbnN0cnVjdG9yKHZhbHVlKSB7XG4gICAgdGhpcy52YWx1ZSA9IHZhbHVlO1xuICB9XG59XG5cbmZ1bmN0aW9uIHZhcmlhYmxlKG5hbWUgPSBudWxsKSB7XG4gIHJldHVybiBuZXcgVmFyaWFibGUobmFtZSk7XG59XG5cbmZ1bmN0aW9uIHdpbGRjYXJkKCkge1xuICByZXR1cm4gbmV3IFdpbGRjYXJkKCk7XG59XG5cbmZ1bmN0aW9uIHN0YXJ0c1dpdGgocHJlZml4KSB7XG4gIHJldHVybiBuZXcgU3RhcnRzV2l0aChwcmVmaXgpO1xufVxuXG5mdW5jdGlvbiBjYXB0dXJlKHZhbHVlKSB7XG4gIHJldHVybiBuZXcgQ2FwdHVyZSh2YWx1ZSk7XG59XG5cbmZ1bmN0aW9uIGhlYWRUYWlsKCkge1xuICByZXR1cm4gbmV3IEhlYWRUYWlsKCk7XG59XG5cbmZ1bmN0aW9uIHR5cGUodHlwZSwgb2JqUGF0dGVybiA9IHt9KSB7XG4gIHJldHVybiBuZXcgVHlwZSh0eXBlLCBvYmpQYXR0ZXJuKTtcbn1cblxuZnVuY3Rpb24gYm91bmQodmFsdWUpIHtcbiAgcmV0dXJuIG5ldyBCb3VuZCh2YWx1ZSk7XG59XG5cbmZ1bmN0aW9uIF9pc19udW1iZXIodmFsdWUpIHtcbiAgcmV0dXJuIHR5cGVvZiB2YWx1ZSA9PT0gJ251bWJlcic7XG59XG5cbmZ1bmN0aW9uIGlzX3N0cmluZyh2YWx1ZSkge1xuICByZXR1cm4gdHlwZW9mIHZhbHVlID09PSAnc3RyaW5nJztcbn1cblxuZnVuY3Rpb24gX2lzX3R1cGxlKHZhbHVlKSB7XG4gIHJldHVybiB2YWx1ZSBpbnN0YW5jZW9mIFR1cGxlO1xufVxuXG5mdW5jdGlvbiBfaXNfYm9vbGVhbih2YWx1ZSkge1xuICByZXR1cm4gdHlwZW9mIHZhbHVlID09PSAnYm9vbGVhbic7XG59XG5cbmZ1bmN0aW9uIGlzX3N5bWJvbCh2YWx1ZSkge1xuICByZXR1cm4gdHlwZW9mIHZhbHVlID09PSAnc3ltYm9sJztcbn1cblxuZnVuY3Rpb24gaXNfbnVsbCh2YWx1ZSkge1xuICByZXR1cm4gdmFsdWUgPT09IG51bGw7XG59XG5cbmZ1bmN0aW9uIGlzX3VuZGVmaW5lZCh2YWx1ZSkge1xuICByZXR1cm4gdHlwZW9mIHZhbHVlID09PSAndW5kZWZpbmVkJztcbn1cblxuZnVuY3Rpb24gX2lzX2Z1bmN0aW9uKHZhbHVlKSB7XG4gIHJldHVybiBPYmplY3QucHJvdG90eXBlLnRvU3RyaW5nLmNhbGwodmFsdWUpID09ICdbb2JqZWN0IEZ1bmN0aW9uXSc7XG59XG5cbmZ1bmN0aW9uIGlzX3ZhcmlhYmxlKHZhbHVlKSB7XG4gIHJldHVybiB2YWx1ZSBpbnN0YW5jZW9mIFZhcmlhYmxlO1xufVxuXG5mdW5jdGlvbiBpc193aWxkY2FyZCh2YWx1ZSkge1xuICByZXR1cm4gdmFsdWUgaW5zdGFuY2VvZiBXaWxkY2FyZDtcbn1cblxuZnVuY3Rpb24gaXNfaGVhZFRhaWwodmFsdWUpIHtcbiAgcmV0dXJuIHZhbHVlIGluc3RhbmNlb2YgSGVhZFRhaWw7XG59XG5cbmZ1bmN0aW9uIGlzX2NhcHR1cmUodmFsdWUpIHtcbiAgcmV0dXJuIHZhbHVlIGluc3RhbmNlb2YgQ2FwdHVyZTtcbn1cblxuZnVuY3Rpb24gaXNfdHlwZSh2YWx1ZSkge1xuICByZXR1cm4gdmFsdWUgaW5zdGFuY2VvZiBUeXBlO1xufVxuXG5mdW5jdGlvbiBpc19zdGFydHNXaXRoKHZhbHVlKSB7XG4gIHJldHVybiB2YWx1ZSBpbnN0YW5jZW9mIFN0YXJ0c1dpdGg7XG59XG5cbmZ1bmN0aW9uIGlzX2JvdW5kKHZhbHVlKSB7XG4gIHJldHVybiB2YWx1ZSBpbnN0YW5jZW9mIEJvdW5kO1xufVxuXG5mdW5jdGlvbiBpc19vYmplY3QodmFsdWUpIHtcbiAgcmV0dXJuIHR5cGVvZiB2YWx1ZSA9PT0gJ29iamVjdCc7XG59XG5cbmZ1bmN0aW9uIGlzX2FycmF5KHZhbHVlKSB7XG4gIHJldHVybiBBcnJheS5pc0FycmF5KHZhbHVlKTtcbn1cblxudmFyIENoZWNrcyA9IHtcbiAgaXNfbnVtYmVyOiBfaXNfbnVtYmVyLFxuICBpc19zdHJpbmcsXG4gIGlzX2Jvb2xlYW46IF9pc19ib29sZWFuLFxuICBpc19zeW1ib2wsXG4gIGlzX251bGwsXG4gIGlzX3VuZGVmaW5lZCxcbiAgaXNfZnVuY3Rpb246IF9pc19mdW5jdGlvbixcbiAgaXNfdmFyaWFibGUsXG4gIGlzX3dpbGRjYXJkLFxuICBpc19oZWFkVGFpbCxcbiAgaXNfY2FwdHVyZSxcbiAgaXNfdHlwZSxcbiAgaXNfc3RhcnRzV2l0aCxcbiAgaXNfYm91bmQsXG4gIGlzX29iamVjdCxcbiAgaXNfYXJyYXksXG4gIGlzX3R1cGxlOiBfaXNfdHVwbGVcbn07XG5cbmZ1bmN0aW9uIHJlc29sdmVUdXBsZShwYXR0ZXJuKSB7XG4gIGxldCBtYXRjaGVzID0gW107XG5cbiAgZm9yIChsZXQgZWxlbSBvZiBwYXR0ZXJuKSB7XG4gICAgbWF0Y2hlcy5wdXNoKGJ1aWxkTWF0Y2goZWxlbSkpO1xuICB9XG5cbiAgcmV0dXJuIGZ1bmN0aW9uICh2YWx1ZSwgYXJncykge1xuICAgIGlmICghQ2hlY2tzLmlzX3R1cGxlKHZhbHVlKSB8fCB2YWx1ZS5jb3VudCgpICE9IHBhdHRlcm4uY291bnQoKSkge1xuICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH1cblxuICAgIHJldHVybiB2YWx1ZS52YWx1ZXMuZXZlcnkoZnVuY3Rpb24gKHYsIGkpIHtcbiAgICAgIHJldHVybiBtYXRjaGVzW2ldKHZhbHVlLmdldChpKSwgYXJncyk7XG4gICAgfSk7XG4gIH07XG59XG5cbmZ1bmN0aW9uIHJlc29sdmVTeW1ib2wocGF0dGVybikge1xuICByZXR1cm4gZnVuY3Rpb24gKHZhbHVlKSB7XG4gICAgcmV0dXJuIENoZWNrcy5pc19zeW1ib2wodmFsdWUpICYmIHZhbHVlID09PSBwYXR0ZXJuO1xuICB9O1xufVxuXG5mdW5jdGlvbiByZXNvbHZlU3RyaW5nKHBhdHRlcm4pIHtcbiAgcmV0dXJuIGZ1bmN0aW9uICh2YWx1ZSkge1xuICAgIHJldHVybiBDaGVja3MuaXNfc3RyaW5nKHZhbHVlKSAmJiB2YWx1ZSA9PT0gcGF0dGVybjtcbiAgfTtcbn1cblxuZnVuY3Rpb24gcmVzb2x2ZU51bWJlcihwYXR0ZXJuKSB7XG4gIHJldHVybiBmdW5jdGlvbiAodmFsdWUpIHtcbiAgICByZXR1cm4gQ2hlY2tzLmlzX251bWJlcih2YWx1ZSkgJiYgdmFsdWUgPT09IHBhdHRlcm47XG4gIH07XG59XG5cbmZ1bmN0aW9uIHJlc29sdmVCb29sZWFuKHBhdHRlcm4pIHtcbiAgcmV0dXJuIGZ1bmN0aW9uICh2YWx1ZSkge1xuICAgIHJldHVybiBDaGVja3MuaXNfYm9vbGVhbih2YWx1ZSkgJiYgdmFsdWUgPT09IHBhdHRlcm47XG4gIH07XG59XG5cbmZ1bmN0aW9uIHJlc29sdmVGdW5jdGlvbihwYXR0ZXJuKSB7XG4gIHJldHVybiBmdW5jdGlvbiAodmFsdWUpIHtcbiAgICByZXR1cm4gQ2hlY2tzLmlzX2Z1bmN0aW9uKHZhbHVlKSAmJiB2YWx1ZSA9PT0gcGF0dGVybjtcbiAgfTtcbn1cblxuZnVuY3Rpb24gcmVzb2x2ZU51bGwocGF0dGVybikge1xuICByZXR1cm4gZnVuY3Rpb24gKHZhbHVlKSB7XG4gICAgcmV0dXJuIENoZWNrcy5pc19udWxsKHZhbHVlKTtcbiAgfTtcbn1cblxuZnVuY3Rpb24gcmVzb2x2ZUJvdW5kKHBhdHRlcm4pIHtcbiAgcmV0dXJuIGZ1bmN0aW9uICh2YWx1ZSwgYXJncykge1xuICAgIGlmICh0eXBlb2YgdmFsdWUgPT09IHR5cGVvZiBwYXR0ZXJuLnZhbHVlICYmIHZhbHVlID09PSBwYXR0ZXJuLnZhbHVlKSB7XG4gICAgICBhcmdzLnB1c2godmFsdWUpO1xuICAgICAgcmV0dXJuIHRydWU7XG4gICAgfVxuXG4gICAgcmV0dXJuIGZhbHNlO1xuICB9O1xufVxuXG5mdW5jdGlvbiByZXNvbHZlV2lsZGNhcmQoKSB7XG4gIHJldHVybiBmdW5jdGlvbiAoKSB7XG4gICAgcmV0dXJuIHRydWU7XG4gIH07XG59XG5cbmZ1bmN0aW9uIHJlc29sdmVWYXJpYWJsZSgpIHtcbiAgcmV0dXJuIGZ1bmN0aW9uICh2YWx1ZSwgYXJncykge1xuICAgIGFyZ3MucHVzaCh2YWx1ZSk7XG4gICAgcmV0dXJuIHRydWU7XG4gIH07XG59XG5cbmZ1bmN0aW9uIHJlc29sdmVIZWFkVGFpbCgpIHtcbiAgcmV0dXJuIGZ1bmN0aW9uICh2YWx1ZSwgYXJncykge1xuICAgIGlmICghQ2hlY2tzLmlzX2FycmF5KHZhbHVlKSB8fCB2YWx1ZS5sZW5ndGggPCAyKSB7XG4gICAgICByZXR1cm4gZmFsc2U7XG4gICAgfVxuXG4gICAgY29uc3QgaGVhZCA9IHZhbHVlWzBdO1xuICAgIGNvbnN0IHRhaWwgPSB2YWx1ZS5zbGljZSgxKTtcblxuICAgIGFyZ3MucHVzaChoZWFkKTtcbiAgICBhcmdzLnB1c2godGFpbCk7XG5cbiAgICByZXR1cm4gdHJ1ZTtcbiAgfTtcbn1cblxuZnVuY3Rpb24gcmVzb2x2ZUNhcHR1cmUocGF0dGVybikge1xuICBjb25zdCBtYXRjaGVzID0gYnVpbGRNYXRjaChwYXR0ZXJuLnZhbHVlKTtcblxuICByZXR1cm4gZnVuY3Rpb24gKHZhbHVlLCBhcmdzKSB7XG4gICAgaWYgKG1hdGNoZXModmFsdWUsIGFyZ3MpKSB7XG4gICAgICBhcmdzLnB1c2godmFsdWUpO1xuICAgICAgcmV0dXJuIHRydWU7XG4gICAgfVxuXG4gICAgcmV0dXJuIGZhbHNlO1xuICB9O1xufVxuXG5mdW5jdGlvbiByZXNvbHZlU3RhcnRzV2l0aChwYXR0ZXJuKSB7XG4gIGNvbnN0IHByZWZpeCA9IHBhdHRlcm4ucHJlZml4O1xuXG4gIHJldHVybiBmdW5jdGlvbiAodmFsdWUsIGFyZ3MpIHtcbiAgICBpZiAoQ2hlY2tzLmlzX3N0cmluZyh2YWx1ZSkgJiYgdmFsdWUuc3RhcnRzV2l0aChwcmVmaXgpKSB7XG4gICAgICBhcmdzLnB1c2godmFsdWUuc3Vic3RyaW5nKHByZWZpeC5sZW5ndGgpKTtcbiAgICAgIHJldHVybiB0cnVlO1xuICAgIH1cblxuICAgIHJldHVybiBmYWxzZTtcbiAgfTtcbn1cblxuZnVuY3Rpb24gcmVzb2x2ZVR5cGUocGF0dGVybikge1xuICByZXR1cm4gZnVuY3Rpb24gKHZhbHVlLCBhcmdzKSB7XG4gICAgaWYgKHZhbHVlIGluc3RhbmNlb2YgcGF0dGVybi50eXBlKSB7XG4gICAgICBjb25zdCBtYXRjaGVzID0gYnVpbGRNYXRjaChwYXR0ZXJuLm9ialBhdHRlcm4pO1xuICAgICAgcmV0dXJuIG1hdGNoZXModmFsdWUsIGFyZ3MpICYmIGFyZ3MucHVzaCh2YWx1ZSkgPiAwO1xuICAgIH1cblxuICAgIHJldHVybiBmYWxzZTtcbiAgfTtcbn1cblxuZnVuY3Rpb24gcmVzb2x2ZUFycmF5KHBhdHRlcm4pIHtcbiAgY29uc3QgbWF0Y2hlcyA9IHBhdHRlcm4ubWFwKHggPT4gYnVpbGRNYXRjaCh4KSk7XG5cbiAgcmV0dXJuIGZ1bmN0aW9uICh2YWx1ZSwgYXJncykge1xuICAgIGlmICghQ2hlY2tzLmlzX2FycmF5KHZhbHVlKSB8fCB2YWx1ZS5sZW5ndGggIT0gcGF0dGVybi5sZW5ndGgpIHtcbiAgICAgIHJldHVybiBmYWxzZTtcbiAgICB9XG5cbiAgICByZXR1cm4gdmFsdWUuZXZlcnkoZnVuY3Rpb24gKHYsIGkpIHtcbiAgICAgIHJldHVybiBtYXRjaGVzW2ldKHZhbHVlW2ldLCBhcmdzKTtcbiAgICB9KTtcbiAgfTtcbn1cblxuZnVuY3Rpb24gcmVzb2x2ZU9iamVjdChwYXR0ZXJuKSB7XG4gIGxldCBtYXRjaGVzID0ge307XG5cbiAgZm9yIChsZXQga2V5IG9mIE9iamVjdC5rZXlzKHBhdHRlcm4pKSB7XG4gICAgbWF0Y2hlc1trZXldID0gYnVpbGRNYXRjaChwYXR0ZXJuW2tleV0pO1xuICB9XG5cbiAgcmV0dXJuIGZ1bmN0aW9uICh2YWx1ZSwgYXJncykge1xuICAgIGlmICghQ2hlY2tzLmlzX29iamVjdCh2YWx1ZSkgfHwgcGF0dGVybi5sZW5ndGggPiB2YWx1ZS5sZW5ndGgpIHtcbiAgICAgIHJldHVybiBmYWxzZTtcbiAgICB9XG5cbiAgICBmb3IgKGxldCBrZXkgb2YgT2JqZWN0LmtleXMocGF0dGVybikpIHtcbiAgICAgIGlmICghKGtleSBpbiB2YWx1ZSkgfHwgIW1hdGNoZXNba2V5XSh2YWx1ZVtrZXldLCBhcmdzKSkge1xuICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICB9XG4gICAgfVxuXG4gICAgcmV0dXJuIHRydWU7XG4gIH07XG59XG5cbmZ1bmN0aW9uIHJlc29sdmVOb01hdGNoKCkge1xuICByZXR1cm4gZnVuY3Rpb24gKCkge1xuICAgIHJldHVybiBmYWxzZTtcbiAgfTtcbn1cblxudmFyIFJlc29sdmVycyA9IHtcbiAgcmVzb2x2ZUJvdW5kLFxuICByZXNvbHZlV2lsZGNhcmQsXG4gIHJlc29sdmVWYXJpYWJsZSxcbiAgcmVzb2x2ZUhlYWRUYWlsLFxuICByZXNvbHZlQ2FwdHVyZSxcbiAgcmVzb2x2ZVN0YXJ0c1dpdGgsXG4gIHJlc29sdmVUeXBlLFxuICByZXNvbHZlQXJyYXksXG4gIHJlc29sdmVPYmplY3QsXG4gIHJlc29sdmVOb01hdGNoLFxuICByZXNvbHZlU3ltYm9sLFxuICByZXNvbHZlU3RyaW5nLFxuICByZXNvbHZlTnVtYmVyLFxuICByZXNvbHZlQm9vbGVhbixcbiAgcmVzb2x2ZUZ1bmN0aW9uLFxuICByZXNvbHZlTnVsbCxcbiAgcmVzb2x2ZVR1cGxlXG59O1xuXG5mdW5jdGlvbiBidWlsZE1hdGNoKHBhdHRlcm4pIHtcblxuICBpZiAoQ2hlY2tzLmlzX3R1cGxlKHBhdHRlcm4pKSB7XG4gICAgcmV0dXJuIFJlc29sdmVycy5yZXNvbHZlVHVwbGUocGF0dGVybik7XG4gIH1cblxuICBpZiAoQ2hlY2tzLmlzX3ZhcmlhYmxlKHBhdHRlcm4pKSB7XG4gICAgcmV0dXJuIFJlc29sdmVycy5yZXNvbHZlVmFyaWFibGUocGF0dGVybik7XG4gIH1cblxuICBpZiAoQ2hlY2tzLmlzX3dpbGRjYXJkKHBhdHRlcm4pKSB7XG4gICAgcmV0dXJuIFJlc29sdmVycy5yZXNvbHZlV2lsZGNhcmQocGF0dGVybik7XG4gIH1cblxuICBpZiAoQ2hlY2tzLmlzX3VuZGVmaW5lZChwYXR0ZXJuKSkge1xuICAgIHJldHVybiBSZXNvbHZlcnMucmVzb2x2ZVdpbGRjYXJkKHBhdHRlcm4pO1xuICB9XG5cbiAgaWYgKENoZWNrcy5pc19oZWFkVGFpbChwYXR0ZXJuKSkge1xuICAgIHJldHVybiBSZXNvbHZlcnMucmVzb2x2ZUhlYWRUYWlsKHBhdHRlcm4pO1xuICB9XG5cbiAgaWYgKENoZWNrcy5pc19zdGFydHNXaXRoKHBhdHRlcm4pKSB7XG4gICAgcmV0dXJuIFJlc29sdmVycy5yZXNvbHZlU3RhcnRzV2l0aChwYXR0ZXJuKTtcbiAgfVxuXG4gIGlmIChDaGVja3MuaXNfY2FwdHVyZShwYXR0ZXJuKSkge1xuICAgIHJldHVybiBSZXNvbHZlcnMucmVzb2x2ZUNhcHR1cmUocGF0dGVybik7XG4gIH1cblxuICBpZiAoQ2hlY2tzLmlzX2JvdW5kKHBhdHRlcm4pKSB7XG4gICAgcmV0dXJuIFJlc29sdmVycy5yZXNvbHZlQm91bmQocGF0dGVybik7XG4gIH1cblxuICBpZiAoQ2hlY2tzLmlzX3R5cGUocGF0dGVybikpIHtcbiAgICByZXR1cm4gUmVzb2x2ZXJzLnJlc29sdmVUeXBlKHBhdHRlcm4pO1xuICB9XG5cbiAgaWYgKENoZWNrcy5pc19hcnJheShwYXR0ZXJuKSkge1xuICAgIHJldHVybiBSZXNvbHZlcnMucmVzb2x2ZUFycmF5KHBhdHRlcm4pO1xuICB9XG5cbiAgaWYgKENoZWNrcy5pc19udW1iZXIocGF0dGVybikpIHtcbiAgICByZXR1cm4gUmVzb2x2ZXJzLnJlc29sdmVOdW1iZXIocGF0dGVybik7XG4gIH1cblxuICBpZiAoQ2hlY2tzLmlzX3N0cmluZyhwYXR0ZXJuKSkge1xuICAgIHJldHVybiBSZXNvbHZlcnMucmVzb2x2ZVN0cmluZyhwYXR0ZXJuKTtcbiAgfVxuXG4gIGlmIChDaGVja3MuaXNfYm9vbGVhbihwYXR0ZXJuKSkge1xuICAgIHJldHVybiBSZXNvbHZlcnMucmVzb2x2ZUJvb2xlYW4ocGF0dGVybik7XG4gIH1cblxuICBpZiAoQ2hlY2tzLmlzX3N5bWJvbChwYXR0ZXJuKSkge1xuICAgIHJldHVybiBSZXNvbHZlcnMucmVzb2x2ZVN5bWJvbChwYXR0ZXJuKTtcbiAgfVxuXG4gIGlmIChDaGVja3MuaXNfbnVsbChwYXR0ZXJuKSkge1xuICAgIHJldHVybiBSZXNvbHZlcnMucmVzb2x2ZU51bGwocGF0dGVybik7XG4gIH1cblxuICBpZiAoQ2hlY2tzLmlzX29iamVjdChwYXR0ZXJuKSkge1xuICAgIHJldHVybiBSZXNvbHZlcnMucmVzb2x2ZU9iamVjdChwYXR0ZXJuKTtcbiAgfVxuXG4gIHJldHVybiBSZXNvbHZlcnMucmVzb2x2ZU5vTWF0Y2goKTtcbn1cblxuY2xhc3MgTWF0Y2hFcnJvciBleHRlbmRzIEVycm9yIHtcbiAgY29uc3RydWN0b3IoYXJnKSB7XG4gICAgc3VwZXIoKTtcblxuICAgIGlmICh0eXBlb2YgYXJnID09PSAnc3ltYm9sJykge1xuICAgICAgdGhpcy5tZXNzYWdlID0gJ05vIG1hdGNoIGZvcjogJyArIGFyZy50b1N0cmluZygpO1xuICAgIH0gZWxzZSBpZiAoQXJyYXkuaXNBcnJheShhcmcpKSB7XG4gICAgICBsZXQgbWFwcGVkVmFsdWVzID0gYXJnLm1hcCh4ID0+IHgudG9TdHJpbmcoKSk7XG4gICAgICB0aGlzLm1lc3NhZ2UgPSAnTm8gbWF0Y2ggZm9yOiAnICsgbWFwcGVkVmFsdWVzO1xuICAgIH0gZWxzZSB7XG4gICAgICB0aGlzLm1lc3NhZ2UgPSAnTm8gbWF0Y2ggZm9yOiAnICsgYXJnO1xuICAgIH1cblxuICAgIHRoaXMuc3RhY2sgPSBuZXcgRXJyb3IoKS5zdGFjaztcbiAgICB0aGlzLm5hbWUgPSB0aGlzLmNvbnN0cnVjdG9yLm5hbWU7XG4gIH1cbn1cblxuY2xhc3MgQ2FzZSB7XG5cbiAgY29uc3RydWN0b3IocGF0dGVybiwgZm4sIGd1YXJkID0gKCkgPT4gdHJ1ZSkge1xuICAgIHRoaXMucGF0dGVybiA9IGJ1aWxkTWF0Y2gocGF0dGVybik7XG4gICAgdGhpcy5mbiA9IGZuO1xuICAgIHRoaXMuZ3VhcmQgPSBndWFyZDtcbiAgfVxufVxuXG5mdW5jdGlvbiBtYWtlX2Nhc2UocGF0dGVybiwgZm4sIGd1YXJkID0gKCkgPT4gdHJ1ZSkge1xuICByZXR1cm4gbmV3IENhc2UocGF0dGVybiwgZm4sIGd1YXJkKTtcbn1cblxuZnVuY3Rpb24gZGVmbWF0Y2goLi4uY2FzZXMpIHtcbiAgcmV0dXJuIGZ1bmN0aW9uICguLi5hcmdzKSB7XG4gICAgZm9yIChsZXQgcHJvY2Vzc2VkQ2FzZSBvZiBjYXNlcykge1xuICAgICAgbGV0IHJlc3VsdCA9IFtdO1xuICAgICAgaWYgKHByb2Nlc3NlZENhc2UucGF0dGVybihhcmdzLCByZXN1bHQpICYmIHByb2Nlc3NlZENhc2UuZ3VhcmQuYXBwbHkodGhpcywgcmVzdWx0KSkge1xuICAgICAgICByZXR1cm4gcHJvY2Vzc2VkQ2FzZS5mbi5hcHBseSh0aGlzLCByZXN1bHQpO1xuICAgICAgfVxuICAgIH1cblxuICAgIHRocm93IG5ldyBNYXRjaEVycm9yKGFyZ3MpO1xuICB9O1xufVxuXG5mdW5jdGlvbiBtYXRjaChwYXR0ZXJuLCBleHByLCBndWFyZCA9ICgpID0+IHRydWUpIHtcbiAgbGV0IHJlc3VsdCA9IFtdO1xuICBsZXQgcHJvY2Vzc2VkUGF0dGVybiA9IGJ1aWxkTWF0Y2gocGF0dGVybik7XG4gIGlmIChwcm9jZXNzZWRQYXR0ZXJuKGV4cHIsIHJlc3VsdCkgJiYgZ3VhcmQuYXBwbHkodGhpcywgcmVzdWx0KSkge1xuICAgIHJldHVybiByZXN1bHQ7XG4gIH0gZWxzZSB7XG4gICAgdGhyb3cgbmV3IE1hdGNoRXJyb3IoZXhwcik7XG4gIH1cbn1cblxuZnVuY3Rpb24gbWF0Y2hfbm9fdGhyb3cocGF0dGVybiwgZXhwciwgZ3VhcmQgPSAoKSA9PiB0cnVlKSB7XG4gIHRyeSB7XG4gICAgcmV0dXJuIG1hdGNoKHBhdHRlcm4sIGV4cHIsIGd1YXJkKTtcbiAgfSBjYXRjaCAoZSkge1xuICAgIGlmIChlIGluc3RhbmNlb2YgTWF0Y2hFcnJvcikge1xuICAgICAgcmV0dXJuIG51bGw7XG4gICAgfVxuXG4gICAgdGhyb3cgZTtcbiAgfVxufVxuXG5mdW5jdGlvbiBwYXR0ZXJuTWFwKGNvbGxlY3Rpb24sIHBhdHRlcm4sIGZ1biwgZ3VhcmQgPSAoKSA9PiB0cnVlKSB7XG4gIGxldCByZXQgPSBbXTtcblxuICBmb3IgKGxldCBlbGVtIG9mIGNvbGxlY3Rpb24pIHtcbiAgICB0cnkge1xuICAgICAgbGV0IHJlc3VsdCA9IGZ1bi5hcHBseSh0aGlzLCBtYXRjaChwYXR0ZXJuLCBlbGVtLCBndWFyZCkpO1xuICAgICAgcmV0ID0gcmV0LmNvbmNhdChyZXN1bHQpO1xuICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgIGlmICghKGUgaW5zdGFuY2VvZiBNYXRjaEVycm9yKSkge1xuICAgICAgICB0aHJvdyBlO1xuICAgICAgfVxuICAgIH1cbiAgfVxuXG4gIHJldHVybiByZXQ7XG59XG5cbnZhciBfUGF0dGVybnMgPSB7XG4gIGRlZm1hdGNoLCBtYXRjaCwgTWF0Y2hFcnJvciwgbWF0Y2hfbm9fdGhyb3csIHBhdHRlcm5NYXAsXG4gIHZhcmlhYmxlLCB3aWxkY2FyZCwgc3RhcnRzV2l0aCxcbiAgY2FwdHVyZSwgaGVhZFRhaWwsIHR5cGUsIGJvdW5kLCBDYXNlLCBtYWtlX2Nhc2Vcbn07XG5cbmNsYXNzIEJpdFN0cmluZyB7XG4gIGNvbnN0cnVjdG9yKC4uLmFyZ3MpIHtcbiAgICB0aGlzLnJhd192YWx1ZSA9IGZ1bmN0aW9uICgpIHtcbiAgICAgIHJldHVybiBPYmplY3QuZnJlZXplKGFyZ3MpO1xuICAgIH07XG5cbiAgICB0aGlzLnZhbHVlID0gT2JqZWN0LmZyZWV6ZSh0aGlzLnByb2Nlc3MoYXJncykpO1xuICB9XG5cbiAgZ2V0KGluZGV4KSB7XG4gICAgcmV0dXJuIHRoaXMudmFsdWVbaW5kZXhdO1xuICB9XG5cbiAgY291bnQoKSB7XG4gICAgcmV0dXJuIHRoaXMudmFsdWUubGVuZ3RoO1xuICB9XG5cbiAgW1N5bWJvbC5pdGVyYXRvcl0oKSB7XG4gICAgcmV0dXJuIHRoaXMudmFsdWVbU3ltYm9sLml0ZXJhdG9yXSgpO1xuICB9XG5cbiAgdG9TdHJpbmcoKSB7XG4gICAgdmFyIGksXG4gICAgICAgIHMgPSBcIlwiO1xuICAgIGZvciAoaSA9IDA7IGkgPCB0aGlzLmNvdW50KCk7IGkrKykge1xuICAgICAgaWYgKHMgIT09IFwiXCIpIHtcbiAgICAgICAgcyArPSBcIiwgXCI7XG4gICAgICB9XG4gICAgICBzICs9IHRoaXNbaV0udG9TdHJpbmcoKTtcbiAgICB9XG5cbiAgICByZXR1cm4gXCI8PFwiICsgcyArIFwiPj5cIjtcbiAgfVxuXG4gIHByb2Nlc3MoKSB7XG4gICAgbGV0IHByb2Nlc3NlZF92YWx1ZXMgPSBbXTtcblxuICAgIHZhciBpO1xuICAgIGZvciAoaSA9IDA7IGkgPCB0aGlzLnJhd192YWx1ZSgpLmxlbmd0aDsgaSsrKSB7XG4gICAgICBsZXQgcHJvY2Vzc2VkX3ZhbHVlID0gdGhpc1tcInByb2Nlc3NfXCIgKyB0aGlzLnJhd192YWx1ZSgpW2ldLnR5cGVdKHRoaXMucmF3X3ZhbHVlKClbaV0pO1xuXG4gICAgICBmb3IgKGxldCBhdHRyIG9mIHRoaXMucmF3X3ZhbHVlKClbaV0uYXR0cmlidXRlcykge1xuICAgICAgICBwcm9jZXNzZWRfdmFsdWUgPSB0aGlzW1wicHJvY2Vzc19cIiArIGF0dHJdKHByb2Nlc3NlZF92YWx1ZSk7XG4gICAgICB9XG5cbiAgICAgIHByb2Nlc3NlZF92YWx1ZXMgPSBwcm9jZXNzZWRfdmFsdWVzLmNvbmNhdChwcm9jZXNzZWRfdmFsdWUpO1xuICAgIH1cblxuICAgIHJldHVybiBwcm9jZXNzZWRfdmFsdWVzO1xuICB9XG5cbiAgcHJvY2Vzc19pbnRlZ2VyKHZhbHVlKSB7XG4gICAgcmV0dXJuIHZhbHVlLnZhbHVlO1xuICB9XG5cbiAgcHJvY2Vzc19mbG9hdCh2YWx1ZSkge1xuICAgIGlmICh2YWx1ZS5zaXplID09PSA2NCkge1xuICAgICAgcmV0dXJuIEJpdFN0cmluZy5mbG9hdDY0VG9CeXRlcyh2YWx1ZS52YWx1ZSk7XG4gICAgfSBlbHNlIGlmICh2YWx1ZS5zaXplID09PSAzMikge1xuICAgICAgcmV0dXJuIEJpdFN0cmluZy5mbG9hdDMyVG9CeXRlcyh2YWx1ZS52YWx1ZSk7XG4gICAgfVxuXG4gICAgdGhyb3cgbmV3IEVycm9yKFwiSW52YWxpZCBzaXplIGZvciBmbG9hdFwiKTtcbiAgfVxuXG4gIHByb2Nlc3NfYml0c3RyaW5nKHZhbHVlKSB7XG4gICAgcmV0dXJuIHZhbHVlLnZhbHVlLnZhbHVlO1xuICB9XG5cbiAgcHJvY2Vzc19iaW5hcnkodmFsdWUpIHtcbiAgICByZXR1cm4gQml0U3RyaW5nLnRvVVRGOEFycmF5KHZhbHVlLnZhbHVlKTtcbiAgfVxuXG4gIHByb2Nlc3NfdXRmOCh2YWx1ZSkge1xuICAgIHJldHVybiBCaXRTdHJpbmcudG9VVEY4QXJyYXkodmFsdWUudmFsdWUpO1xuICB9XG5cbiAgcHJvY2Vzc191dGYxNih2YWx1ZSkge1xuICAgIHJldHVybiBCaXRTdHJpbmcudG9VVEYxNkFycmF5KHZhbHVlLnZhbHVlKTtcbiAgfVxuXG4gIHByb2Nlc3NfdXRmMzIodmFsdWUpIHtcbiAgICByZXR1cm4gQml0U3RyaW5nLnRvVVRGMzJBcnJheSh2YWx1ZS52YWx1ZSk7XG4gIH1cblxuICBwcm9jZXNzX3NpZ25lZCh2YWx1ZSkge1xuICAgIHJldHVybiBuZXcgVWludDhBcnJheShbdmFsdWVdKVswXTtcbiAgfVxuXG4gIHByb2Nlc3NfdW5zaWduZWQodmFsdWUpIHtcbiAgICByZXR1cm4gdmFsdWU7XG4gIH1cblxuICBwcm9jZXNzX25hdGl2ZSh2YWx1ZSkge1xuICAgIHJldHVybiB2YWx1ZTtcbiAgfVxuXG4gIHByb2Nlc3NfYmlnKHZhbHVlKSB7XG4gICAgcmV0dXJuIHZhbHVlO1xuICB9XG5cbiAgcHJvY2Vzc19saXR0bGUodmFsdWUpIHtcbiAgICByZXR1cm4gdmFsdWUucmV2ZXJzZSgpO1xuICB9XG5cbiAgcHJvY2Vzc19zaXplKHZhbHVlKSB7XG4gICAgcmV0dXJuIHZhbHVlO1xuICB9XG5cbiAgcHJvY2Vzc191bml0KHZhbHVlKSB7XG4gICAgcmV0dXJuIHZhbHVlO1xuICB9XG5cbiAgc3RhdGljIGludGVnZXIodmFsdWUpIHtcbiAgICByZXR1cm4gQml0U3RyaW5nLndyYXAodmFsdWUsIHsgXCJ0eXBlXCI6IFwiaW50ZWdlclwiLCBcInVuaXRcIjogMSwgXCJzaXplXCI6IDggfSk7XG4gIH1cblxuICBzdGF0aWMgZmxvYXQodmFsdWUpIHtcbiAgICByZXR1cm4gQml0U3RyaW5nLndyYXAodmFsdWUsIHsgXCJ0eXBlXCI6IFwiZmxvYXRcIiwgXCJ1bml0XCI6IDEsIFwic2l6ZVwiOiA2NCB9KTtcbiAgfVxuXG4gIHN0YXRpYyBiaXRzdHJpbmcodmFsdWUpIHtcbiAgICByZXR1cm4gQml0U3RyaW5nLndyYXAodmFsdWUsIHsgXCJ0eXBlXCI6IFwiYml0c3RyaW5nXCIsIFwidW5pdFwiOiAxLCBcInNpemVcIjogdmFsdWUubGVuZ3RoIH0pO1xuICB9XG5cbiAgc3RhdGljIGJpdHModmFsdWUpIHtcbiAgICByZXR1cm4gQml0U3RyaW5nLmJpdHN0cmluZyh2YWx1ZSk7XG4gIH1cblxuICBzdGF0aWMgYmluYXJ5KHZhbHVlKSB7XG4gICAgcmV0dXJuIEJpdFN0cmluZy53cmFwKHZhbHVlLCB7IFwidHlwZVwiOiBcImJpbmFyeVwiLCBcInVuaXRcIjogOCwgXCJzaXplXCI6IHZhbHVlLmxlbmd0aCB9KTtcbiAgfVxuXG4gIHN0YXRpYyBieXRlcyh2YWx1ZSkge1xuICAgIHJldHVybiBCaXRTdHJpbmcuYmluYXJ5KHZhbHVlKTtcbiAgfVxuXG4gIHN0YXRpYyB1dGY4KHZhbHVlKSB7XG4gICAgcmV0dXJuIEJpdFN0cmluZy53cmFwKHZhbHVlLCB7IFwidHlwZVwiOiBcInV0ZjhcIiB9KTtcbiAgfVxuXG4gIHN0YXRpYyB1dGYxNih2YWx1ZSkge1xuICAgIHJldHVybiBCaXRTdHJpbmcud3JhcCh2YWx1ZSwgeyBcInR5cGVcIjogXCJ1dGYxNlwiIH0pO1xuICB9XG5cbiAgc3RhdGljIHV0ZjMyKHZhbHVlKSB7XG4gICAgcmV0dXJuIEJpdFN0cmluZy53cmFwKHZhbHVlLCB7IFwidHlwZVwiOiBcInV0ZjMyXCIgfSk7XG4gIH1cblxuICBzdGF0aWMgc2lnbmVkKHZhbHVlKSB7XG4gICAgcmV0dXJuIEJpdFN0cmluZy53cmFwKHZhbHVlLCB7fSwgXCJzaWduZWRcIik7XG4gIH1cblxuICBzdGF0aWMgdW5zaWduZWQodmFsdWUpIHtcbiAgICByZXR1cm4gQml0U3RyaW5nLndyYXAodmFsdWUsIHt9LCBcInVuc2lnbmVkXCIpO1xuICB9XG5cbiAgc3RhdGljIG5hdGl2ZSh2YWx1ZSkge1xuICAgIHJldHVybiBCaXRTdHJpbmcud3JhcCh2YWx1ZSwge30sIFwibmF0aXZlXCIpO1xuICB9XG5cbiAgc3RhdGljIGJpZyh2YWx1ZSkge1xuICAgIHJldHVybiBCaXRTdHJpbmcud3JhcCh2YWx1ZSwge30sIFwiYmlnXCIpO1xuICB9XG5cbiAgc3RhdGljIGxpdHRsZSh2YWx1ZSkge1xuICAgIHJldHVybiBCaXRTdHJpbmcud3JhcCh2YWx1ZSwge30sIFwibGl0dGxlXCIpO1xuICB9XG5cbiAgc3RhdGljIHNpemUodmFsdWUsIGNvdW50KSB7XG4gICAgcmV0dXJuIEJpdFN0cmluZy53cmFwKHZhbHVlLCB7IFwic2l6ZVwiOiBjb3VudCB9KTtcbiAgfVxuXG4gIHN0YXRpYyB1bml0KHZhbHVlLCBjb3VudCkge1xuICAgIHJldHVybiBCaXRTdHJpbmcud3JhcCh2YWx1ZSwgeyBcInVuaXRcIjogY291bnQgfSk7XG4gIH1cblxuICBzdGF0aWMgd3JhcCh2YWx1ZSwgb3B0LCBuZXdfYXR0cmlidXRlID0gbnVsbCkge1xuICAgIGxldCB0aGVfdmFsdWUgPSB2YWx1ZTtcblxuICAgIGlmICghKHZhbHVlIGluc3RhbmNlb2YgT2JqZWN0KSkge1xuICAgICAgdGhlX3ZhbHVlID0geyBcInZhbHVlXCI6IHZhbHVlLCBcImF0dHJpYnV0ZXNcIjogW10gfTtcbiAgICB9XG5cbiAgICB0aGVfdmFsdWUgPSBPYmplY3QuYXNzaWduKHRoZV92YWx1ZSwgb3B0KTtcblxuICAgIGlmIChuZXdfYXR0cmlidXRlKSB7XG4gICAgICB0aGVfdmFsdWUuYXR0cmlidXRlcy5wdXNoKG5ld19hdHRyaWJ1dGUpO1xuICAgIH1cblxuICAgIHJldHVybiB0aGVfdmFsdWU7XG4gIH1cblxuICBzdGF0aWMgdG9VVEY4QXJyYXkoc3RyKSB7XG4gICAgdmFyIHV0ZjggPSBbXTtcbiAgICBmb3IgKHZhciBpID0gMDsgaSA8IHN0ci5sZW5ndGg7IGkrKykge1xuICAgICAgdmFyIGNoYXJjb2RlID0gc3RyLmNoYXJDb2RlQXQoaSk7XG4gICAgICBpZiAoY2hhcmNvZGUgPCAxMjgpIHtcbiAgICAgICAgdXRmOC5wdXNoKGNoYXJjb2RlKTtcbiAgICAgIH0gZWxzZSBpZiAoY2hhcmNvZGUgPCAyMDQ4KSB7XG4gICAgICAgIHV0ZjgucHVzaCgxOTIgfCBjaGFyY29kZSA+PiA2LCAxMjggfCBjaGFyY29kZSAmIDYzKTtcbiAgICAgIH0gZWxzZSBpZiAoY2hhcmNvZGUgPCA1NTI5NiB8fCBjaGFyY29kZSA+PSA1NzM0NCkge1xuICAgICAgICB1dGY4LnB1c2goMjI0IHwgY2hhcmNvZGUgPj4gMTIsIDEyOCB8IGNoYXJjb2RlID4+IDYgJiA2MywgMTI4IHwgY2hhcmNvZGUgJiA2Myk7XG4gICAgICB9XG4gICAgICAvLyBzdXJyb2dhdGUgcGFpclxuICAgICAgZWxzZSB7XG4gICAgICAgIGkrKztcbiAgICAgICAgLy8gVVRGLTE2IGVuY29kZXMgMHgxMDAwMC0weDEwRkZGRiBieVxuICAgICAgICAvLyBzdWJ0cmFjdGluZyAweDEwMDAwIGFuZCBzcGxpdHRpbmcgdGhlXG4gICAgICAgIC8vIDIwIGJpdHMgb2YgMHgwLTB4RkZGRkYgaW50byB0d28gaGFsdmVzXG4gICAgICAgIGNoYXJjb2RlID0gNjU1MzYgKyAoKGNoYXJjb2RlICYgMTAyMykgPDwgMTAgfCBzdHIuY2hhckNvZGVBdChpKSAmIDEwMjMpO1xuICAgICAgICB1dGY4LnB1c2goMjQwIHwgY2hhcmNvZGUgPj4gMTgsIDEyOCB8IGNoYXJjb2RlID4+IDEyICYgNjMsIDEyOCB8IGNoYXJjb2RlID4+IDYgJiA2MywgMTI4IHwgY2hhcmNvZGUgJiA2Myk7XG4gICAgICB9XG4gICAgfVxuICAgIHJldHVybiB1dGY4O1xuICB9XG5cbiAgc3RhdGljIHRvVVRGMTZBcnJheShzdHIpIHtcbiAgICB2YXIgdXRmMTYgPSBbXTtcbiAgICBmb3IgKHZhciBpID0gMDsgaSA8IHN0ci5sZW5ndGg7IGkrKykge1xuICAgICAgdmFyIGNvZGVQb2ludCA9IHN0ci5jb2RlUG9pbnRBdChpKTtcblxuICAgICAgaWYgKGNvZGVQb2ludCA8PSAyNTUpIHtcbiAgICAgICAgdXRmMTYucHVzaCgwKTtcbiAgICAgICAgdXRmMTYucHVzaChjb2RlUG9pbnQpO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgdXRmMTYucHVzaChjb2RlUG9pbnQgPj4gOCAmIDI1NSk7XG4gICAgICAgIHV0ZjE2LnB1c2goY29kZVBvaW50ICYgMjU1KTtcbiAgICAgIH1cbiAgICB9XG4gICAgcmV0dXJuIHV0ZjE2O1xuICB9XG5cbiAgc3RhdGljIHRvVVRGMzJBcnJheShzdHIpIHtcbiAgICB2YXIgdXRmMzIgPSBbXTtcbiAgICBmb3IgKHZhciBpID0gMDsgaSA8IHN0ci5sZW5ndGg7IGkrKykge1xuICAgICAgdmFyIGNvZGVQb2ludCA9IHN0ci5jb2RlUG9pbnRBdChpKTtcblxuICAgICAgaWYgKGNvZGVQb2ludCA8PSAyNTUpIHtcbiAgICAgICAgdXRmMzIucHVzaCgwKTtcbiAgICAgICAgdXRmMzIucHVzaCgwKTtcbiAgICAgICAgdXRmMzIucHVzaCgwKTtcbiAgICAgICAgdXRmMzIucHVzaChjb2RlUG9pbnQpO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgdXRmMzIucHVzaCgwKTtcbiAgICAgICAgdXRmMzIucHVzaCgwKTtcbiAgICAgICAgdXRmMzIucHVzaChjb2RlUG9pbnQgPj4gOCAmIDI1NSk7XG4gICAgICAgIHV0ZjMyLnB1c2goY29kZVBvaW50ICYgMjU1KTtcbiAgICAgIH1cbiAgICB9XG4gICAgcmV0dXJuIHV0ZjMyO1xuICB9XG5cbiAgLy9odHRwOi8vc3RhY2tvdmVyZmxvdy5jb20vcXVlc3Rpb25zLzIwMDM0OTMvamF2YXNjcmlwdC1mbG9hdC1mcm9tLXRvLWJpdHNcbiAgc3RhdGljIGZsb2F0MzJUb0J5dGVzKGYpIHtcbiAgICB2YXIgYnl0ZXMgPSBbXTtcblxuICAgIHZhciBidWYgPSBuZXcgQXJyYXlCdWZmZXIoNCk7XG4gICAgbmV3IEZsb2F0MzJBcnJheShidWYpWzBdID0gZjtcblxuICAgIGxldCBpbnRWZXJzaW9uID0gbmV3IFVpbnQzMkFycmF5KGJ1ZilbMF07XG5cbiAgICBieXRlcy5wdXNoKGludFZlcnNpb24gPj4gMjQgJiAyNTUpO1xuICAgIGJ5dGVzLnB1c2goaW50VmVyc2lvbiA+PiAxNiAmIDI1NSk7XG4gICAgYnl0ZXMucHVzaChpbnRWZXJzaW9uID4+IDggJiAyNTUpO1xuICAgIGJ5dGVzLnB1c2goaW50VmVyc2lvbiAmIDI1NSk7XG5cbiAgICByZXR1cm4gYnl0ZXM7XG4gIH1cblxuICBzdGF0aWMgZmxvYXQ2NFRvQnl0ZXMoZikge1xuICAgIHZhciBieXRlcyA9IFtdO1xuXG4gICAgdmFyIGJ1ZiA9IG5ldyBBcnJheUJ1ZmZlcig4KTtcbiAgICBuZXcgRmxvYXQ2NEFycmF5KGJ1ZilbMF0gPSBmO1xuXG4gICAgdmFyIGludFZlcnNpb24xID0gbmV3IFVpbnQzMkFycmF5KGJ1ZilbMF07XG4gICAgdmFyIGludFZlcnNpb24yID0gbmV3IFVpbnQzMkFycmF5KGJ1ZilbMV07XG5cbiAgICBieXRlcy5wdXNoKGludFZlcnNpb24yID4+IDI0ICYgMjU1KTtcbiAgICBieXRlcy5wdXNoKGludFZlcnNpb24yID4+IDE2ICYgMjU1KTtcbiAgICBieXRlcy5wdXNoKGludFZlcnNpb24yID4+IDggJiAyNTUpO1xuICAgIGJ5dGVzLnB1c2goaW50VmVyc2lvbjIgJiAyNTUpO1xuXG4gICAgYnl0ZXMucHVzaChpbnRWZXJzaW9uMSA+PiAyNCAmIDI1NSk7XG4gICAgYnl0ZXMucHVzaChpbnRWZXJzaW9uMSA+PiAxNiAmIDI1NSk7XG4gICAgYnl0ZXMucHVzaChpbnRWZXJzaW9uMSA+PiA4ICYgMjU1KTtcbiAgICBieXRlcy5wdXNoKGludFZlcnNpb24xICYgMjU1KTtcblxuICAgIHJldHVybiBieXRlcztcbiAgfVxufVxuXG5sZXQgU3BlY2lhbEZvcm1zID0ge1xuXG4gIF9fRElSX186IGZ1bmN0aW9uICgpIHtcbiAgICBpZiAoX19kaXJuYW1lKSB7XG4gICAgICByZXR1cm4gX19kaXJuYW1lO1xuICAgIH1cblxuICAgIGlmIChkb2N1bWVudC5jdXJyZW50U2NyaXB0KSB7XG4gICAgICByZXR1cm4gZG9jdW1lbnQuY3VycmVudFNjcmlwdC5zcmM7XG4gICAgfVxuXG4gICAgcmV0dXJuIG51bGw7XG4gIH0sXG5cbiAgYXRvbTogZnVuY3Rpb24gKF92YWx1ZSkge1xuICAgIHJldHVybiBTeW1ib2wuZm9yKF92YWx1ZSk7XG4gIH0sXG5cbiAgbGlzdDogZnVuY3Rpb24gKC4uLmFyZ3MpIHtcbiAgICByZXR1cm4gT2JqZWN0LmZyZWV6ZShhcmdzKTtcbiAgfSxcblxuICBiaXRzdHJpbmc6IGZ1bmN0aW9uICguLi5hcmdzKSB7XG4gICAgcmV0dXJuIG5ldyBCaXRTdHJpbmcoLi4uYXJncyk7XG4gIH0sXG5cbiAgYm91bmQ6IGZ1bmN0aW9uIChfdmFyKSB7XG4gICAgcmV0dXJuIFBhdHRlcm5zLmJvdW5kKF92YXIpO1xuICB9LFxuXG4gIF9jYXNlOiBmdW5jdGlvbiAoY29uZGl0aW9uLCBjbGF1c2VzKSB7XG4gICAgcmV0dXJuIFBhdHRlcm5zLmRlZm1hdGNoKC4uLmNsYXVzZXMpKGNvbmRpdGlvbik7XG4gIH0sXG5cbiAgY29uZDogZnVuY3Rpb24gKGNsYXVzZXMpIHtcbiAgICBmb3IgKGxldCBjbGF1c2Ugb2YgY2xhdXNlcykge1xuICAgICAgaWYgKGNsYXVzZVswXSkge1xuICAgICAgICByZXR1cm4gY2xhdXNlWzFdKCk7XG4gICAgICB9XG4gICAgfVxuXG4gICAgdGhyb3cgbmV3IEVycm9yKCk7XG4gIH0sXG5cbiAgZm46IGZ1bmN0aW9uIChjbGF1c2VzKSB7XG4gICAgcmV0dXJuIFBhdHRlcm5zLmRlZm1hdGNoKGNsYXVzZXMpO1xuICB9LFxuXG4gIG1hcDogZnVuY3Rpb24gKG9iaikge1xuICAgIHJldHVybiBPYmplY3QuZnJlZXplKG9iaik7XG4gIH0sXG5cbiAgbWFwX3VwZGF0ZTogZnVuY3Rpb24gKG1hcCwgdmFsdWVzKSB7XG4gICAgcmV0dXJuIE9iamVjdC5mcmVlemUoT2JqZWN0LmFzc2lnbihPYmplY3QuY3JlYXRlKG1hcC5jb25zdHJ1Y3Rvci5wcm90b3R5cGUpLCBtYXAsIHZhbHVlcykpO1xuICB9LFxuXG4gIF9mb3I6IGZ1bmN0aW9uIChjb2xsZWN0aW9ucywgZnVuLCBmaWx0ZXIgPSAoKSA9PiB0cnVlLCBpbnRvID0gW10sIHByZXZpb3VzVmFsdWVzID0gW10pIHtcbiAgICBsZXQgcGF0dGVybiA9IGNvbGxlY3Rpb25zWzBdWzBdO1xuICAgIGxldCBjb2xsZWN0aW9uID0gY29sbGVjdGlvbnNbMF1bMV07XG5cbiAgICBpZiAoY29sbGVjdGlvbnMubGVuZ3RoID09PSAxKSB7XG5cbiAgICAgIGZvciAobGV0IGVsZW0gb2YgY29sbGVjdGlvbikge1xuICAgICAgICBsZXQgciA9IFBhdHRlcm5zLm1hdGNoX25vX3Rocm93KHBhdHRlcm4sIGVsZW0pO1xuICAgICAgICBsZXQgYXJncyA9IHByZXZpb3VzVmFsdWVzLmNvbmNhdChyKTtcblxuICAgICAgICBpZiAociAmJiBmaWx0ZXIuYXBwbHkodGhpcywgYXJncykpIHtcbiAgICAgICAgICBpbnRvID0gRW51bS5pbnRvKFtmdW4uYXBwbHkodGhpcywgYXJncyldLCBpbnRvKTtcbiAgICAgICAgfVxuICAgICAgfVxuXG4gICAgICByZXR1cm4gaW50bztcbiAgICB9IGVsc2Uge1xuICAgICAgbGV0IF9pbnRvID0gW107XG5cbiAgICAgIGZvciAobGV0IGVsZW0gb2YgY29sbGVjdGlvbikge1xuICAgICAgICBsZXQgciA9IFBhdHRlcm5zLm1hdGNoX25vX3Rocm93KHBhdHRlcm4sIGVsZW0pO1xuICAgICAgICBpZiAocikge1xuICAgICAgICAgIF9pbnRvID0gRW51bS5pbnRvKHRoaXMuX2Zvcihjb2xsZWN0aW9ucy5zbGljZSgxKSwgZnVuLCBmaWx0ZXIsIF9pbnRvLCBwcmV2aW91c1ZhbHVlcy5jb25jYXQocikpLCBpbnRvKTtcbiAgICAgICAgfVxuICAgICAgfVxuXG4gICAgICByZXR1cm4gX2ludG87XG4gICAgfVxuICB9LFxuXG4gIHJlY2VpdmU6IGZ1bmN0aW9uIChyZWNlaXZlX2Z1biwgdGltZW91dF9pbl9tcyA9IG51bGwsIHRpbWVvdXRfZm4gPSB0aW1lID0+IHRydWUpIHtcbiAgICBpZiAodGltZW91dF9pbl9tcyA9PSBudWxsIHx8IHRpbWVvdXRfaW5fbXMgPT09IFN5c3RlbS5mb3IoJ2luZmluaXR5JykpIHtcbiAgICAgIHdoaWxlICh0cnVlKSB7XG4gICAgICAgIGlmIChzZWxmLm1haWxib3gubGVuZ3RoICE9PSAwKSB7XG4gICAgICAgICAgbGV0IG1lc3NhZ2UgPSBzZWxmLm1haWxib3hbMF07XG4gICAgICAgICAgc2VsZi5tYWlsYm94ID0gc2VsZi5tYWlsYm94LnNsaWNlKDEpO1xuICAgICAgICAgIHJldHVybiByZWNlaXZlX2Z1bihtZXNzYWdlKTtcbiAgICAgICAgfVxuICAgICAgfVxuICAgIH0gZWxzZSBpZiAodGltZW91dF9pbl9tcyA9PT0gMCkge1xuICAgICAgaWYgKHNlbGYubWFpbGJveC5sZW5ndGggIT09IDApIHtcbiAgICAgICAgbGV0IG1lc3NhZ2UgPSBzZWxmLm1haWxib3hbMF07XG4gICAgICAgIHNlbGYubWFpbGJveCA9IHNlbGYubWFpbGJveC5zbGljZSgxKTtcbiAgICAgICAgcmV0dXJuIHJlY2VpdmVfZnVuKG1lc3NhZ2UpO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgcmV0dXJuIG51bGw7XG4gICAgICB9XG4gICAgfSBlbHNlIHtcbiAgICAgIGxldCBub3cgPSBEYXRlLm5vdygpO1xuICAgICAgd2hpbGUgKERhdGUubm93KCkgPCBub3cgKyB0aW1lb3V0X2luX21zKSB7XG4gICAgICAgIGlmIChzZWxmLm1haWxib3gubGVuZ3RoICE9PSAwKSB7XG4gICAgICAgICAgbGV0IG1lc3NhZ2UgPSBzZWxmLm1haWxib3hbMF07XG4gICAgICAgICAgc2VsZi5tYWlsYm94ID0gc2VsZi5tYWlsYm94LnNsaWNlKDEpO1xuICAgICAgICAgIHJldHVybiByZWNlaXZlX2Z1bihtZXNzYWdlKTtcbiAgICAgICAgfVxuICAgICAgfVxuXG4gICAgICByZXR1cm4gdGltZW91dF9mbih0aW1lb3V0X2luX21zKTtcbiAgICB9XG4gIH0sXG5cbiAgdHVwbGU6IGZ1bmN0aW9uICguLi5hcmdzKSB7XG4gICAgcmV0dXJuIG5ldyBUdXBsZSguLi5hcmdzKTtcbiAgfSxcblxuICBfdHJ5OiBmdW5jdGlvbiAoZG9fZnVuLCByZXNjdWVfZnVuY3Rpb24sIGNhdGNoX2Z1biwgZWxzZV9mdW5jdGlvbiwgYWZ0ZXJfZnVuY3Rpb24pIHtcbiAgICBsZXQgcmVzdWx0ID0gbnVsbDtcblxuICAgIHRyeSB7XG4gICAgICByZXN1bHQgPSBkb19mdW4oKTtcbiAgICB9IGNhdGNoIChlKSB7XG4gICAgICBsZXQgZXhfcmVzdWx0ID0gbnVsbDtcblxuICAgICAgaWYgKHJlc2N1ZV9mdW5jdGlvbikge1xuICAgICAgICB0cnkge1xuICAgICAgICAgIGV4X3Jlc3VsdCA9IHJlc2N1ZV9mdW5jdGlvbihlKTtcbiAgICAgICAgICByZXR1cm4gZXhfcmVzdWx0O1xuICAgICAgICB9IGNhdGNoIChleCkge1xuICAgICAgICAgIGlmIChleCBpbnN0YW5jZW9mIFBhdHRlcm5zLk1hdGNoRXJyb3IpIHtcbiAgICAgICAgICAgIHRocm93IGV4O1xuICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgfVxuXG4gICAgICBpZiAoY2F0Y2hfZnVuKSB7XG4gICAgICAgIHRyeSB7XG4gICAgICAgICAgZXhfcmVzdWx0ID0gY2F0Y2hfZnVuKGUpO1xuICAgICAgICAgIHJldHVybiBleF9yZXN1bHQ7XG4gICAgICAgIH0gY2F0Y2ggKGV4KSB7XG4gICAgICAgICAgaWYgKGV4IGluc3RhbmNlb2YgUGF0dGVybnMuTWF0Y2hFcnJvcikge1xuICAgICAgICAgICAgdGhyb3cgZXg7XG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICB9XG5cbiAgICAgIHRocm93IGU7XG4gICAgfSBmaW5hbGx5IHtcbiAgICAgIGlmIChhZnRlcl9mdW5jdGlvbikge1xuICAgICAgICBhZnRlcl9mdW5jdGlvbigpO1xuICAgICAgfVxuICAgIH1cblxuICAgIGlmIChlbHNlX2Z1bmN0aW9uKSB7XG4gICAgICB0cnkge1xuICAgICAgICByZXR1cm4gZWxzZV9mdW5jdGlvbihyZXN1bHQpO1xuICAgICAgfSBjYXRjaCAoZXgpIHtcbiAgICAgICAgaWYgKGV4IGluc3RhbmNlb2YgUGF0dGVybnMuTWF0Y2hFcnJvcikge1xuICAgICAgICAgIHRocm93IG5ldyBFcnJvcignTm8gTWF0Y2ggRm91bmQgaW4gRWxzZScpO1xuICAgICAgICB9XG5cbiAgICAgICAgdGhyb3cgZXg7XG4gICAgICB9XG4gICAgfSBlbHNlIHtcbiAgICAgIHJldHVybiByZXN1bHQ7XG4gICAgfVxuICB9XG5cbn07XG5cbi8qIEBmbG93ICovXG5cbmxldCBwcm9jZXNzX2NvdW50ZXIgPSAtMTtcblxuY2xhc3MgUElEIHtcbiAgY29uc3RydWN0b3IoKSB7XG4gICAgcHJvY2Vzc19jb3VudGVyID0gcHJvY2Vzc19jb3VudGVyICsgMTtcbiAgICB0aGlzLmlkID0gcHJvY2Vzc19jb3VudGVyO1xuICB9XG5cbiAgdG9TdHJpbmcoKSB7XG4gICAgcmV0dXJuIFwiUElEIzwwLlwiICsgdGhpcy5pZCArIFwiLjA+XCI7XG4gIH1cbn1cblxuY2xhc3MgSW50ZWdlclR5cGUge31cbmNsYXNzIEZsb2F0VHlwZSB7fVxuXG4vL2h0dHBzOi8vZ2l0aHViLmNvbS9haXJwb3J0eWgvcHJvdG9tb3JwaGlzbVxuY2xhc3MgUHJvdG9jb2wge1xuICBjb25zdHJ1Y3RvcihzcGVjKSB7XG4gICAgdGhpcy5yZWdpc3RyeSA9IG5ldyBNYXAoKTtcbiAgICB0aGlzLmZhbGxiYWNrID0gbnVsbDtcblxuICAgIGZvciAobGV0IGZ1bk5hbWUgaW4gc3BlYykge1xuICAgICAgdGhpc1tmdW5OYW1lXSA9IGNyZWF0ZUZ1bihmdW5OYW1lKS5iaW5kKHRoaXMpO1xuICAgIH1cblxuICAgIGZ1bmN0aW9uIGNyZWF0ZUZ1bihmdW5OYW1lKSB7XG5cbiAgICAgIHJldHVybiBmdW5jdGlvbiAoLi4uYXJncykge1xuICAgICAgICBsZXQgdGhpbmcgPSBhcmdzWzBdO1xuICAgICAgICBsZXQgZnVuID0gbnVsbDtcblxuICAgICAgICBpZiAoTnVtYmVyLmlzSW50ZWdlcih0aGluZykgJiYgdGhpcy5oYXNJbXBsZW1lbnRhdGlvbihJbnRlZ2VyVHlwZSkpIHtcbiAgICAgICAgICBmdW4gPSB0aGlzLnJlZ2lzdHJ5LmdldChJbnRlZ2VyVHlwZSlbZnVuTmFtZV07XG4gICAgICAgIH0gZWxzZSBpZiAodHlwZW9mIHRoaW5nID09PSBcIm51bWJlclwiICYmICFOdW1iZXIuaXNJbnRlZ2VyKHRoaW5nKSAmJiB0aGlzLmhhc0ltcGxlbWVudGF0aW9uKEZsb2F0VHlwZSkpIHtcbiAgICAgICAgICBmdW4gPSB0aGlzLnJlZ2lzdHJ5LmdldChGbG9hdFR5cGUpW2Z1bk5hbWVdO1xuICAgICAgICB9IGVsc2UgaWYgKHRoaXMuaGFzSW1wbGVtZW50YXRpb24odGhpbmcpKSB7XG4gICAgICAgICAgZnVuID0gdGhpcy5yZWdpc3RyeS5nZXQodGhpbmcuY29uc3RydWN0b3IpW2Z1bk5hbWVdO1xuICAgICAgICB9IGVsc2UgaWYgKHRoaXMuZmFsbGJhY2spIHtcbiAgICAgICAgICBmdW4gPSB0aGlzLmZhbGxiYWNrW2Z1bk5hbWVdO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKGZ1biAhPSBudWxsKSB7XG4gICAgICAgICAgbGV0IHJldHZhbCA9IGZ1bi5hcHBseSh0aGlzLCBhcmdzKTtcbiAgICAgICAgICByZXR1cm4gcmV0dmFsO1xuICAgICAgICB9XG5cbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKFwiTm8gaW1wbGVtZW50YXRpb24gZm91bmQgZm9yIFwiICsgdGhpbmcpO1xuICAgICAgfTtcbiAgICB9XG4gIH1cblxuICBpbXBsZW1lbnRhdGlvbih0eXBlLCBpbXBsZW1lbnRhdGlvbikge1xuICAgIGlmICh0eXBlID09PSBudWxsKSB7XG4gICAgICB0aGlzLmZhbGxiYWNrID0gaW1wbGVtZW50YXRpb247XG4gICAgfSBlbHNlIHtcbiAgICAgIHRoaXMucmVnaXN0cnkuc2V0KHR5cGUsIGltcGxlbWVudGF0aW9uKTtcbiAgICB9XG4gIH1cblxuICBoYXNJbXBsZW1lbnRhdGlvbih0aGluZykge1xuICAgIHJldHVybiB0aGlzLnJlZ2lzdHJ5Lmhhcyh0aGluZy5jb25zdHJ1Y3Rvcik7XG4gIH1cbn1cblxuZnVuY3Rpb24gdGwobGlzdCkge1xuICByZXR1cm4gU3BlY2lhbEZvcm1zLmxpc3QoLi4ubGlzdC5zbGljZSgxKSk7XG59XG5cbmZ1bmN0aW9uIGhkKGxpc3QpIHtcbiAgcmV0dXJuIGxpc3RbMF07XG59XG5cbmZ1bmN0aW9uIGlzX25pbCh4KSB7XG4gIHJldHVybiB4ID09PSBudWxsO1xufVxuXG5mdW5jdGlvbiBpc19hdG9tKHgpIHtcbiAgcmV0dXJuIHR5cGVvZiB4ID09PSAnc3ltYm9sJztcbn1cblxuZnVuY3Rpb24gaXNfYmluYXJ5KHgpIHtcbiAgcmV0dXJuIHR5cGVvZiB4ID09PSAnc3RyaW5nJyB8fCB4IGluc3RhbmNlb2YgU3RyaW5nO1xufVxuXG5mdW5jdGlvbiBpc19ib29sZWFuKHgpIHtcbiAgcmV0dXJuIHR5cGVvZiB4ID09PSAnYm9vbGVhbicgfHwgeCBpbnN0YW5jZW9mIEJvb2xlYW47XG59XG5cbmZ1bmN0aW9uIGlzX2Z1bmN0aW9uKHgsIGFyaXR5ID0gLTEpIHtcbiAgcmV0dXJuIHR5cGVvZiB4ID09PSAnZnVuY3Rpb24nIHx8IHggaW5zdGFuY2VvZiBGdW5jdGlvbjtcbn1cblxuZnVuY3Rpb24gaXNfZmxvYXQoeCkge1xuICByZXR1cm4gaXNfbnVtYmVyKHgpICYmICFOdW1iZXIuaXNJbnRlZ2VyKHgpO1xufVxuXG5mdW5jdGlvbiBpc19pbnRlZ2VyKHgpIHtcbiAgcmV0dXJuIE51bWJlci5pc0ludGVnZXIoeCk7XG59XG5cbmZ1bmN0aW9uIGlzX2xpc3QoeCkge1xuICByZXR1cm4geCBpbnN0YW5jZW9mIEFycmF5O1xufVxuXG5mdW5jdGlvbiBpc19tYXAoeCkge1xuICByZXR1cm4gdHlwZW9mIHggPT09ICdvYmplY3QnIHx8IHggaW5zdGFuY2VvZiBPYmplY3Q7XG59XG5cbmZ1bmN0aW9uIGlzX251bWJlcih4KSB7XG4gIHJldHVybiB0eXBlb2YgeCA9PT0gJ251bWJlcic7XG59XG5cbmZ1bmN0aW9uIGlzX3R1cGxlKHgpIHtcbiAgcmV0dXJuIHggaW5zdGFuY2VvZiBUdXBsZTtcbn1cblxuZnVuY3Rpb24gX2xlbmd0aCh4KSB7XG4gIHJldHVybiB4Lmxlbmd0aDtcbn1cblxuZnVuY3Rpb24gaXNfcGlkKHgpIHtcbiAgcmV0dXJuIHggaW5zdGFuY2VvZiBQSUQ7XG59XG5cbmZ1bmN0aW9uIGlzX3BvcnQoeCkge1xuICByZXR1cm4gZmFsc2U7XG59XG5cbmZ1bmN0aW9uIGlzX3JlZmVyZW5jZSh4KSB7XG4gIHJldHVybiBmYWxzZTtcbn1cblxuZnVuY3Rpb24gaXNfYml0c3RyaW5nKHgpIHtcbiAgcmV0dXJuIGlzX2JpbmFyeSh4KSB8fCB4IGluc3RhbmNlb2YgQml0U3RyaW5nO1xufVxuXG5mdW5jdGlvbiBfX2luX18obGVmdCwgcmlnaHQpIHtcbiAgZm9yIChsZXQgeCBvZiByaWdodCkge1xuICAgIGlmIChtYXRjaF9fcW1hcmtfXyhsZWZ0LCB4KSkge1xuICAgICAgcmV0dXJuIHRydWU7XG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIGZhbHNlO1xufVxuXG5mdW5jdGlvbiBhYnMobnVtYmVyKSB7XG4gIHJldHVybiBNYXRoLmFicyhudW1iZXIpO1xufVxuXG5mdW5jdGlvbiByb3VuZChudW1iZXIpIHtcbiAgcmV0dXJuIE1hdGgucm91bmQobnVtYmVyKTtcbn1cblxuZnVuY3Rpb24gZWxlbSh0dXBsZSwgaW5kZXgpIHtcbiAgaWYgKGlzX2xpc3QodHVwbGUpKSB7XG4gICAgcmV0dXJuIHR1cGxlW2luZGV4XTtcbiAgfVxuXG4gIHJldHVybiB0dXBsZS5nZXQoaW5kZXgpO1xufVxuXG5mdW5jdGlvbiByZW0obGVmdCwgcmlnaHQpIHtcbiAgcmV0dXJuIGxlZnQgJSByaWdodDtcbn1cblxuZnVuY3Rpb24gZGl2KGxlZnQsIHJpZ2h0KSB7XG4gIHJldHVybiBsZWZ0IC8gcmlnaHQ7XG59XG5cbmZ1bmN0aW9uIGFuZChsZWZ0LCByaWdodCkge1xuICByZXR1cm4gbGVmdCAmJiByaWdodDtcbn1cblxuZnVuY3Rpb24gb3IobGVmdCwgcmlnaHQpIHtcbiAgcmV0dXJuIGxlZnQgfHwgcmlnaHQ7XG59XG5cbmZ1bmN0aW9uIG5vdChhcmcpIHtcbiAgcmV0dXJuICFhcmc7XG59XG5cbmZ1bmN0aW9uIGFwcGx5KC4uLmFyZ3MpIHtcbiAgaWYgKGFyZ3MubGVuZ3RoID09PSAzKSB7XG4gICAgbGV0IG1vZCA9IGFyZ3NbMF07XG4gICAgbGV0IGZ1bmMgPSBhcmdzWzFdO1xuICAgIGxldCBmdW5jX2FyZ3MgPSBhcmdzWzJdO1xuICAgIHJldHVybiBtb2RbZnVuY10uYXBwbHkobnVsbCwgZnVuY19hcmdzKTtcbiAgfSBlbHNlIHtcbiAgICBsZXQgZnVuYyA9IGFyZ3NbMF07XG4gICAgbGV0IGZ1bmNfYXJncyA9IGFyZ3NbMV07XG5cbiAgICByZXR1cm4gZnVuYy5hcHBseShudWxsLCBmdW5jX2FyZ3MpO1xuICB9XG59XG5cbmZ1bmN0aW9uIHRvX3N0cmluZyhhcmcpIHtcbiAgaWYgKGlzX3R1cGxlKGFyZykpIHtcbiAgICByZXR1cm4gVHVwbGUudG9fc3RyaW5nKGFyZyk7XG4gIH1cblxuICByZXR1cm4gYXJnLnRvU3RyaW5nKCk7XG59XG5cbmZ1bmN0aW9uIG1hdGNoX19xbWFya19fKHBhdHRlcm4sIGV4cHIsIGd1YXJkID0gKCkgPT4gdHJ1ZSkge1xuICByZXR1cm4gX1BhdHRlcm5zLm1hdGNoX25vX3Rocm93KHBhdHRlcm4sIGV4cHIsIGd1YXJkKSAhPSBudWxsO1xufVxuXG5mdW5jdGlvbiBkZWZzdHJ1Y3QoZGVmYXVsdHMpIHtcbiAgcmV0dXJuIGNsYXNzIHtcbiAgICBjb25zdHJ1Y3Rvcih1cGRhdGUgPSB7fSkge1xuICAgICAgbGV0IHRoZV92YWx1ZXMgPSBPYmplY3QuYXNzaWduKGRlZmF1bHRzLCB1cGRhdGUpO1xuICAgICAgT2JqZWN0LmFzc2lnbih0aGlzLCB0aGVfdmFsdWVzKTtcbiAgICB9XG5cbiAgICBzdGF0aWMgY3JlYXRlKHVwZGF0ZXMgPSB7fSkge1xuICAgICAgbGV0IHggPSBuZXcgdGhpcyh1cGRhdGVzKTtcbiAgICAgIHJldHVybiBPYmplY3QuZnJlZXplKHgpO1xuICAgIH1cbiAgfTtcbn1cblxuZnVuY3Rpb24gZGVmZXhjZXB0aW9uKGRlZmF1bHRzKSB7XG4gIHJldHVybiBjbGFzcyBleHRlbmRzIEVycm9yIHtcbiAgICBjb25zdHJ1Y3Rvcih1cGRhdGUgPSB7fSkge1xuICAgICAgbGV0IG1lc3NhZ2UgPSB1cGRhdGUubWVzc2FnZSB8fCAnJztcbiAgICAgIHN1cGVyKG1lc3NhZ2UpO1xuXG4gICAgICBsZXQgdGhlX3ZhbHVlcyA9IE9iamVjdC5hc3NpZ24oZGVmYXVsdHMsIHVwZGF0ZSk7XG4gICAgICBPYmplY3QuYXNzaWduKHRoaXMsIHRoZV92YWx1ZXMpO1xuXG4gICAgICB0aGlzLm5hbWUgPSB0aGlzLmNvbnN0cnVjdG9yLm5hbWU7XG4gICAgICB0aGlzLm1lc3NhZ2UgPSBtZXNzYWdlO1xuICAgICAgdGhpc1tTcGVjaWFsRm9ybXMuYXRvbSgnX19leGNlcHRpb25fXycpXSA9IHRydWU7XG4gICAgICBFcnJvci5jYXB0dXJlU3RhY2tUcmFjZSh0aGlzLCB0aGlzLmNvbnN0cnVjdG9yLm5hbWUpO1xuICAgIH1cblxuICAgIHN0YXRpYyBjcmVhdGUodXBkYXRlcyA9IHt9KSB7XG4gICAgICBsZXQgeCA9IG5ldyB0aGlzKHVwZGF0ZXMpO1xuICAgICAgcmV0dXJuIE9iamVjdC5mcmVlemUoeCk7XG4gICAgfVxuICB9O1xufVxuXG5mdW5jdGlvbiBkZWZwcm90b2NvbChzcGVjKSB7XG4gIHJldHVybiBuZXcgUHJvdG9jb2woc3BlYyk7XG59XG5cbmZ1bmN0aW9uIGRlZmltcGwocHJvdG9jb2wsIHR5cGUsIGltcGwpIHtcbiAgcHJvdG9jb2wuaW1wbGVtZW50YXRpb24odHlwZSwgaW1wbCk7XG59XG5cbnZhciBLZXJuZWwgPSB7XG4gIFNwZWNpYWxGb3JtcyxcbiAgdGwsXG4gIGhkLFxuICBpc19uaWwsXG4gIGlzX2F0b20sXG4gIGlzX2JpbmFyeSxcbiAgaXNfYm9vbGVhbixcbiAgaXNfZnVuY3Rpb24sXG4gIGlzX2Zsb2F0LFxuICBpc19pbnRlZ2VyLFxuICBpc19saXN0LFxuICBpc19tYXAsXG4gIGlzX251bWJlcixcbiAgaXNfdHVwbGUsXG4gIGxlbmd0aDogX2xlbmd0aCxcbiAgaXNfcGlkLFxuICBpc19wb3J0LFxuICBpc19yZWZlcmVuY2UsXG4gIGlzX2JpdHN0cmluZyxcbiAgaW46IF9faW5fXyxcbiAgYWJzLFxuICByb3VuZCxcbiAgZWxlbSxcbiAgcmVtLFxuICBkaXYsXG4gIGFuZCxcbiAgb3IsXG4gIG5vdCxcbiAgYXBwbHksXG4gIHRvX3N0cmluZyxcbiAgbWF0Y2hfX3FtYXJrX18sXG4gIGRlZnN0cnVjdCxcbiAgZGVmcHJvdG9jb2wsXG4gIGRlZmltcGxcbn07XG5cbmxldCBFbnVtID0ge1xuXG4gIGFsbF9fcW1hcmtfXzogZnVuY3Rpb24gKGNvbGxlY3Rpb24sIGZ1biA9IHggPT4geCkge1xuICAgIGZvciAobGV0IGVsZW0gb2YgY29sbGVjdGlvbikge1xuICAgICAgaWYgKCFmdW4oZWxlbSkpIHtcbiAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgfVxuICAgIH1cblxuICAgIHJldHVybiB0cnVlO1xuICB9LFxuXG4gIGFueV9fcW1hcmtfXzogZnVuY3Rpb24gKGNvbGxlY3Rpb24sIGZ1biA9IHggPT4geCkge1xuICAgIGZvciAobGV0IGVsZW0gb2YgY29sbGVjdGlvbikge1xuICAgICAgaWYgKGZ1bihlbGVtKSkge1xuICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICByZXR1cm4gZmFsc2U7XG4gIH0sXG5cbiAgYXQ6IGZ1bmN0aW9uIChjb2xsZWN0aW9uLCBuLCB0aGVfZGVmYXVsdCA9IG51bGwpIHtcbiAgICBpZiAobiA+IHRoaXMuY291bnQoY29sbGVjdGlvbikgfHwgbiA8IDApIHtcbiAgICAgIHJldHVybiB0aGVfZGVmYXVsdDtcbiAgICB9XG5cbiAgICByZXR1cm4gY29sbGVjdGlvbltuXTtcbiAgfSxcblxuICBjb25jYXQ6IGZ1bmN0aW9uICguLi5lbnVtYWJsZXMpIHtcbiAgICByZXR1cm4gZW51bWFibGVzWzBdLmNvbmNhdChlbnVtYWJsZXNbMV0pO1xuICB9LFxuXG4gIGNvdW50OiBmdW5jdGlvbiAoY29sbGVjdGlvbiwgZnVuID0gbnVsbCkge1xuICAgIGlmIChmdW4gPT0gbnVsbCkge1xuICAgICAgcmV0dXJuIGNvbGxlY3Rpb24ubGVuZ3RoO1xuICAgIH0gZWxzZSB7XG4gICAgICByZXR1cm4gY29sbGVjdGlvbi5maWx0ZXIoZnVuKS5sZW5ndGg7XG4gICAgfVxuICB9LFxuXG4gIGRyb3A6IGZ1bmN0aW9uIChjb2xsZWN0aW9uLCBjb3VudCkge1xuICAgIHJldHVybiBjb2xsZWN0aW9uLnNsaWNlKGNvdW50KTtcbiAgfSxcblxuICBkcm9wX3doaWxlOiBmdW5jdGlvbiAoY29sbGVjdGlvbiwgZnVuKSB7XG4gICAgbGV0IGNvdW50ID0gMDtcblxuICAgIGZvciAobGV0IGVsZW0gb2YgY29sbGVjdGlvbikge1xuICAgICAgaWYgKGZ1bihlbGVtKSkge1xuICAgICAgICBjb3VudCA9IGNvdW50ICsgMTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIGJyZWFrO1xuICAgICAgfVxuICAgIH1cblxuICAgIHJldHVybiBjb2xsZWN0aW9uLnNsaWNlKGNvdW50KTtcbiAgfSxcblxuICBlYWNoOiBmdW5jdGlvbiAoY29sbGVjdGlvbiwgZnVuKSB7XG4gICAgZm9yIChsZXQgZWxlbSBvZiBjb2xsZWN0aW9uKSB7XG4gICAgICBmdW4oZWxlbSk7XG4gICAgfVxuICB9LFxuXG4gIGVtcHR5X19xbWFya19fOiBmdW5jdGlvbiAoY29sbGVjdGlvbikge1xuICAgIHJldHVybiBjb2xsZWN0aW9uLmxlbmd0aCA9PT0gMDtcbiAgfSxcblxuICBmZXRjaDogZnVuY3Rpb24gKGNvbGxlY3Rpb24sIG4pIHtcbiAgICBpZiAoS2VybmVsLmlzX2xpc3QoY29sbGVjdGlvbikpIHtcbiAgICAgIGlmIChuIDwgdGhpcy5jb3VudChjb2xsZWN0aW9uKSAmJiBuID49IDApIHtcbiAgICAgICAgcmV0dXJuIEtlcm5lbC5TcGVjaWFsRm9ybXMudHVwbGUoS2VybmVsLlNwZWNpYWxGb3Jtcy5hdG9tKFwib2tcIiksIGNvbGxlY3Rpb25bbl0pO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgcmV0dXJuIEtlcm5lbC5TcGVjaWFsRm9ybXMuYXRvbShcImVycm9yXCIpO1xuICAgICAgfVxuICAgIH1cblxuICAgIHRocm93IG5ldyBFcnJvcihcImNvbGxlY3Rpb24gaXMgbm90IGFuIEVudW1lcmFibGVcIik7XG4gIH0sXG5cbiAgZmV0Y2hfX2VtYXJrX186IGZ1bmN0aW9uIChjb2xsZWN0aW9uLCBuKSB7XG4gICAgaWYgKEtlcm5lbC5pc19saXN0KGNvbGxlY3Rpb24pKSB7XG4gICAgICBpZiAobiA8IHRoaXMuY291bnQoY29sbGVjdGlvbikgJiYgbiA+PSAwKSB7XG4gICAgICAgIHJldHVybiBjb2xsZWN0aW9uW25dO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKFwib3V0IG9mIGJvdW5kcyBlcnJvclwiKTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICB0aHJvdyBuZXcgRXJyb3IoXCJjb2xsZWN0aW9uIGlzIG5vdCBhbiBFbnVtZXJhYmxlXCIpO1xuICB9LFxuXG4gIGZpbHRlcjogZnVuY3Rpb24gKGNvbGxlY3Rpb24sIGZ1bikge1xuICAgIGxldCByZXN1bHQgPSBbXTtcblxuICAgIGZvciAobGV0IGVsZW0gb2YgY29sbGVjdGlvbikge1xuICAgICAgaWYgKGZ1bihlbGVtKSkge1xuICAgICAgICByZXN1bHQucHVzaChlbGVtKTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICByZXR1cm4gcmVzdWx0O1xuICB9LFxuXG4gIGZpbHRlcl9tYXA6IGZ1bmN0aW9uIChjb2xsZWN0aW9uLCBmaWx0ZXIsIG1hcHBlcikge1xuICAgIHJldHVybiBFbnVtLm1hcChFbnVtLmZpbHRlcihjb2xsZWN0aW9uLCBmaWx0ZXIpLCBtYXBwZXIpO1xuICB9LFxuXG4gIGZpbmQ6IGZ1bmN0aW9uIChjb2xsZWN0aW9uLCBpZl9ub25lID0gbnVsbCwgZnVuKSB7XG4gICAgZm9yIChsZXQgZWxlbSBvZiBjb2xsZWN0aW9uKSB7XG4gICAgICBpZiAoZnVuKGVsZW0pKSB7XG4gICAgICAgIHJldHVybiBlbGVtO1xuICAgICAgfVxuICAgIH1cblxuICAgIHJldHVybiBpZl9ub25lO1xuICB9LFxuXG4gIGludG86IGZ1bmN0aW9uIChjb2xsZWN0aW9uLCBsaXN0KSB7XG4gICAgcmV0dXJuIGxpc3QuY29uY2F0KGNvbGxlY3Rpb24pO1xuICB9LFxuXG4gIG1hcDogZnVuY3Rpb24gKGNvbGxlY3Rpb24sIGZ1bikge1xuICAgIGxldCByZXN1bHQgPSBbXTtcblxuICAgIGZvciAobGV0IGVsZW0gb2YgY29sbGVjdGlvbikge1xuICAgICAgcmVzdWx0LnB1c2goZnVuKGVsZW0pKTtcbiAgICB9XG5cbiAgICByZXR1cm4gcmVzdWx0O1xuICB9LFxuXG4gIG1hcF9yZWR1Y2U6IGZ1bmN0aW9uIChjb2xsZWN0aW9uLCBhY2MsIGZ1bikge1xuICAgIGxldCBtYXBwZWQgPSBLZXJuZWwuU3BlY2lhbEZvcm1zLmxpc3QoKTtcbiAgICBsZXQgdGhlX2FjYyA9IGFjYztcblxuICAgIGZvciAodmFyIGkgPSAwOyBpIDwgdGhpcy5jb3VudChjb2xsZWN0aW9uKTsgaSsrKSB7XG4gICAgICBsZXQgdHVwbGUgPSBmdW4oY29sbGVjdGlvbltpXSwgdGhlX2FjYyk7XG5cbiAgICAgIHRoZV9hY2MgPSBLZXJuZWwuZWxlbSh0dXBsZSwgMSk7XG4gICAgICBtYXBwZWQgPSBLZXJuZWwuU3BlY2lhbEZvcm1zLmxpc3QoLi4ubWFwcGVkLmNvbmNhdChbS2VybmVsLmVsZW0odHVwbGUsIDApXSkpO1xuICAgIH1cblxuICAgIHJldHVybiBLZXJuZWwuU3BlY2lhbEZvcm1zLnR1cGxlKG1hcHBlZCwgdGhlX2FjYyk7XG4gIH0sXG5cbiAgbWVtYmVyOiBmdW5jdGlvbiAoY29sbGVjdGlvbiwgdmFsdWUpIHtcbiAgICByZXR1cm4gY29sbGVjdGlvbi5pbmNsdWRlcyh2YWx1ZSk7XG4gIH0sXG5cbiAgcmVkdWNlOiBmdW5jdGlvbiAoY29sbGVjdGlvbiwgYWNjLCBmdW4pIHtcbiAgICBsZXQgdGhlX2FjYyA9IGFjYztcblxuICAgIGZvciAodmFyIGkgPSAwOyBpIDwgdGhpcy5jb3VudChjb2xsZWN0aW9uKTsgaSsrKSB7XG4gICAgICBsZXQgdHVwbGUgPSBmdW4oY29sbGVjdGlvbltpXSwgdGhlX2FjYyk7XG5cbiAgICAgIHRoZV9hY2MgPSBLZXJuZWwuZWxlbSh0dXBsZSwgMSk7XG4gICAgfVxuXG4gICAgcmV0dXJuIHRoZV9hY2M7XG4gIH0sXG5cbiAgdGFrZTogZnVuY3Rpb24gKGNvbGxlY3Rpb24sIGNvdW50KSB7XG4gICAgcmV0dXJuIGNvbGxlY3Rpb24uc2xpY2UoMCwgY291bnQpO1xuICB9LFxuXG4gIHRha2VfZXZlcnk6IGZ1bmN0aW9uIChjb2xsZWN0aW9uLCBudGgpIHtcbiAgICBsZXQgcmVzdWx0ID0gW107XG4gICAgbGV0IGluZGV4ID0gMDtcblxuICAgIGZvciAobGV0IGVsZW0gb2YgY29sbGVjdGlvbikge1xuICAgICAgaWYgKGluZGV4ICUgbnRoID09PSAwKSB7XG4gICAgICAgIHJlc3VsdC5wdXNoKGVsZW0pO1xuICAgICAgfVxuICAgIH1cblxuICAgIHJldHVybiBLZXJuZWwuU3BlY2lhbEZvcm1zLmxpc3QoLi4ucmVzdWx0KTtcbiAgfSxcblxuICB0YWtlX3doaWxlOiBmdW5jdGlvbiAoY29sbGVjdGlvbiwgZnVuKSB7XG4gICAgbGV0IGNvdW50ID0gMDtcblxuICAgIGZvciAobGV0IGVsZW0gb2YgY29sbGVjdGlvbikge1xuICAgICAgaWYgKGZ1bihlbGVtKSkge1xuICAgICAgICBjb3VudCA9IGNvdW50ICsgMTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIGJyZWFrO1xuICAgICAgfVxuICAgIH1cblxuICAgIHJldHVybiBjb2xsZWN0aW9uLnNsaWNlKDAsIGNvdW50KTtcbiAgfSxcblxuICB0b19saXN0OiBmdW5jdGlvbiAoY29sbGVjdGlvbikge1xuICAgIHJldHVybiBjb2xsZWN0aW9uO1xuICB9XG59O1xuXG5sZXQgQXRvbSA9IHt9O1xuXG5BdG9tLnRvX3N0cmluZyA9IGZ1bmN0aW9uIChhdG9tKSB7XG4gIHJldHVybiBTeW1ib2wua2V5Rm9yKGF0b20pO1xufTtcblxuQXRvbS50b19jaGFyX2xpc3QgPSBmdW5jdGlvbiAoYXRvbSkge1xuICByZXR1cm4gQXRvbS50b19zdHJpbmcoYXRvbSkuc3BsaXQoJycpO1xufTtcblxubGV0IEludGVnZXIgPSB7XG5cbiAgaXNfZXZlbjogZnVuY3Rpb24gKG4pIHtcbiAgICByZXR1cm4gbiAlIDIgPT09IDA7XG4gIH0sXG5cbiAgaXNfb2RkOiBmdW5jdGlvbiAobikge1xuICAgIHJldHVybiBuICUgMiAhPT0gMDtcbiAgfSxcblxuICBwYXJzZTogZnVuY3Rpb24gKGJpbikge1xuICAgIGxldCByZXN1bHQgPSBwYXJzZUludChiaW4pO1xuXG4gICAgaWYgKGlzTmFOKHJlc3VsdCkpIHtcbiAgICAgIHJldHVybiBLZXJuZWwuU3BlY2lhbEZvcm1zLmF0b20oXCJlcnJvclwiKTtcbiAgICB9XG5cbiAgICBsZXQgaW5kZXhPZkRvdCA9IGJpbi5pbmRleE9mKFwiLlwiKTtcblxuICAgIGlmIChpbmRleE9mRG90ID49IDApIHtcbiAgICAgIHJldHVybiBLZXJuZWwuU3BlY2lhbEZvcm1zLnR1cGxlKHJlc3VsdCwgYmluLnN1YnN0cmluZyhpbmRleE9mRG90KSk7XG4gICAgfVxuXG4gICAgcmV0dXJuIEtlcm5lbC5TcGVjaWFsRm9ybXMudHVwbGUocmVzdWx0LCBcIlwiKTtcbiAgfSxcblxuICB0b19jaGFyX2xpc3Q6IGZ1bmN0aW9uIChudW1iZXIsIGJhc2UgPSAxMCkge1xuICAgIHJldHVybiBudW1iZXIudG9TdHJpbmcoYmFzZSkuc3BsaXQoXCJcIik7XG4gIH0sXG5cbiAgdG9fc3RyaW5nOiBmdW5jdGlvbiAobnVtYmVyLCBiYXNlID0gMTApIHtcbiAgICByZXR1cm4gbnVtYmVyLnRvU3RyaW5nKGJhc2UpO1xuICB9XG59O1xuXG5sZXQgX0NoYXJzID0gS2VybmVsLmRlZnByb3RvY29sKHtcbiAgdG9fc3RyaW5nOiBmdW5jdGlvbiAodGhpbmcpIHt9XG59KTtcblxuS2VybmVsLmRlZmltcGwoX0NoYXJzLCBCaXRTdHJpbmcsIHtcbiAgdG9fc3RyaW5nOiBmdW5jdGlvbiAodGhpbmcpIHtcbiAgICBpZiAoS2VybmVsLmlzX2JpbmFyeSh0aGluZykpIHtcbiAgICAgIHJldHVybiB0aGluZztcbiAgICB9XG5cbiAgICByZXR1cm4gdGhpbmcudG9TdHJpbmcoKTtcbiAgfVxufSk7XG5cbktlcm5lbC5kZWZpbXBsKF9DaGFycywgU3ltYm9sLCB7XG4gIHRvX3N0cmluZzogZnVuY3Rpb24gKHRoaW5nKSB7XG4gICAgaWYgKG5pbCkge1xuICAgICAgcmV0dXJuIFwiXCI7XG4gICAgfVxuXG4gICAgcmV0dXJuIEF0b20udG9fc3RyaW5nKHRoaW5nKTtcbiAgfVxufSk7XG5cbktlcm5lbC5kZWZpbXBsKF9DaGFycywgSW50ZWdlclR5cGUsIHtcbiAgdG9fc3RyaW5nOiBmdW5jdGlvbiAodGhpbmcpIHtcbiAgICByZXR1cm4gSW50ZWdlci50b19zdHJpbmcodGhpbmcpO1xuICB9XG59KTtcblxuS2VybmVsLmRlZmltcGwoX0NoYXJzLCBGbG9hdFR5cGUsIHtcbiAgdG9fc3RyaW5nOiBmdW5jdGlvbiAodGhpbmcpIHtcbiAgICByZXR1cm4gdGhpbmcudG9TdHJpbmc7XG4gIH1cbn0pO1xuXG5LZXJuZWwuZGVmaW1wbChfQ2hhcnMsIEFycmF5LCB7XG4gIHRvX3N0cmluZzogZnVuY3Rpb24gKHRoaW5nKSB7XG4gICAgcmV0dXJuIHRoaW5nLnRvU3RyaW5nKCk7XG4gIH1cbn0pO1xuXG5LZXJuZWwuZGVmaW1wbChfQ2hhcnMsIFR1cGxlLCB7XG4gIHRvX3N0cmluZzogZnVuY3Rpb24gKHRoaW5nKSB7XG4gICAgcmV0dXJuIFR1cGxlLnRvX3N0cmluZyh0aGluZyk7XG4gIH1cbn0pO1xuXG5LZXJuZWwuZGVmaW1wbChfQ2hhcnMsIG51bGwsIHtcbiAgdG9fc3RyaW5nOiBmdW5jdGlvbiAodGhpbmcpIHtcbiAgICByZXR1cm4gdGhpbmcudG9TdHJpbmcoKTtcbiAgfVxufSk7XG5cbmZ1bmN0aW9uIHRvX2F0b20oc3RyaW5nKSB7XG4gIHJldHVybiBTeW1ib2wuZm9yKHN0cmluZyk7XG59XG5cbmZ1bmN0aW9uIHRvX2V4aXN0aW5nX2F0b20oc3RyaW5nKSB7XG4gIHJldHVybiBTeW1ib2wuZm9yKHN0cmluZyk7XG59XG5cbmZ1bmN0aW9uIHRvX2NoYXJfbGlzdChzdHJpbmcpIHtcbiAgcmV0dXJuIHN0cmluZy5zcGxpdCgnJyk7XG59XG5cbmZ1bmN0aW9uIHRvX2Zsb2F0KHN0cmluZykge1xuICByZXR1cm4gcGFyc2VGbG9hdChzdHJpbmcpO1xufVxuXG5mdW5jdGlvbiB0b19pbnRlZ2VyKHN0cmluZywgYmFzZSA9IDEwKSB7XG4gIHJldHVybiBwYXJzZUludChzdHJpbmcsIGJhc2UpO1xufVxuXG5mdW5jdGlvbiB1cGNhc2UoYmluYXJ5KSB7XG4gIHJldHVybiBiaW5hcnkudG9VcHBlckNhc2UoKTtcbn1cblxuZnVuY3Rpb24gZG93bmNhc2UoYmluYXJ5KSB7XG4gIHJldHVybiBiaW5hcnkudG9Mb3dlckNhc2UoKTtcbn1cblxuZnVuY3Rpb24gYXQoc3RyaW5nLCBwb3NpdGlvbikge1xuICBpZiAocG9zaXRpb24gPiBzdHJpbmcubGVuZ3RoIC0gMSkge1xuICAgIHJldHVybiBudWxsO1xuICB9XG5cbiAgcmV0dXJuIHN0cmluZ1twb3NpdGlvbl07XG59XG5cbmZ1bmN0aW9uIGNhcGl0YWxpemUoc3RyaW5nKSB7XG4gIGxldCByZXR1cm5TdHJpbmcgPSAnJztcblxuICBmb3IgKGxldCBpID0gMDsgaSA8IHN0cmluZy5sZW5ndGg7IGkrKykge1xuICAgIGlmIChpID09PSAwKSB7XG4gICAgICByZXR1cm5TdHJpbmcgPSByZXR1cm5TdHJpbmcgKyBzdHJpbmdbaV0udG9VcHBlckNhc2UoKTtcbiAgICB9IGVsc2Uge1xuICAgICAgcmV0dXJuU3RyaW5nID0gcmV0dXJuU3RyaW5nICsgc3RyaW5nW2ldLnRvTG93ZXJDYXNlKCk7XG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIHJldHVyblN0cmluZztcbn1cblxuZnVuY3Rpb24gY29kZXBvaW50cyhzdHJpbmcpIHtcbiAgcmV0dXJuIHRvX2NoYXJfbGlzdChzdHJpbmcpLm1hcChmdW5jdGlvbiAoYykge1xuICAgIHJldHVybiBjLmNvZGVQb2ludEF0KDApO1xuICB9KTtcbn1cblxuZnVuY3Rpb24gY29udGFpbnNfX3FtX18oc3RyaW5nLCBjb250YWlucykge1xuICBpZiAoQXJyYXkuaXNBcnJheShjb250YWlucykpIHtcbiAgICByZXR1cm4gY29udGFpbnMuc29tZShmdW5jdGlvbiAocykge1xuICAgICAgcmV0dXJuIHN0cmluZy5pbmRleE9mKHMpID4gLTE7XG4gICAgfSk7XG4gIH1cblxuICByZXR1cm4gc3RyaW5nLmluZGV4T2YoY29udGFpbnMpID4gLTE7XG59XG5cbmZ1bmN0aW9uIGR1cGxpY2F0ZShzdWJqZWN0LCBuKSB7XG4gIHJldHVybiBzdWJqZWN0LnJlcGVhdChuKTtcbn1cblxuZnVuY3Rpb24gZW5kc193aXRoX19xbV9fKHN0cmluZywgc3VmZml4ZXMpIHtcbiAgaWYgKEFycmF5LmlzQXJyYXkoc3VmZml4ZXMpKSB7XG4gICAgcmV0dXJuIHN1ZmZpeGVzLnNvbWUoZnVuY3Rpb24gKHMpIHtcbiAgICAgIHJldHVybiBzdHJpbmcuZW5kc1dpdGgocyk7XG4gICAgfSk7XG4gIH1cblxuICByZXR1cm4gc3RyaW5nLmVuZHNXaXRoKHN1ZmZpeGVzKTtcbn1cblxuZnVuY3Rpb24gZmlyc3Qoc3RyaW5nKSB7XG4gIGlmICghc3RyaW5nKSB7XG4gICAgcmV0dXJuIG51bGw7XG4gIH1cblxuICByZXR1cm4gc3RyaW5nWzBdO1xufVxuXG5mdW5jdGlvbiBncmFwaGVtZXMoc3RyaW5nKSB7XG4gIHJldHVybiBzdHJpbmcuc3BsaXQoJycpO1xufVxuXG5mdW5jdGlvbiBsYXN0KHN0cmluZykge1xuICBpZiAoIXN0cmluZykge1xuICAgIHJldHVybiBudWxsO1xuICB9XG5cbiAgcmV0dXJuIHN0cmluZ1tzdHJpbmcubGVuZ3RoIC0gMV07XG59XG5cbmZ1bmN0aW9uIGxlbmd0aChzdHJpbmcpIHtcbiAgcmV0dXJuIHN0cmluZy5sZW5ndGg7XG59XG5cbmZ1bmN0aW9uIG1hdGNoX19xbV9fKHN0cmluZywgcmVnZXgpIHtcbiAgcmV0dXJuIHN0cmluZy5tYXRjaChyZWdleCkgIT0gbnVsbDtcbn1cblxuZnVuY3Rpb24gbmV4dF9jb2RlcG9pbnQoc3RyaW5nKSB7XG4gIGlmICghc3RyaW5nIHx8IHN0cmluZyA9PT0gJycpIHtcbiAgICByZXR1cm4gbnVsbDtcbiAgfVxuXG4gIHJldHVybiBLZXJuZWwuU3BlY2lhbEZvcm1zLnR1cGxlKHN0cmluZ1swXS5jb2RlUG9pbnRBdCgwKSwgc3RyaW5nLnN1YnN0cigxKSk7XG59XG5cbmZ1bmN0aW9uIG5leHRfZ3JhcGhlbWUoc3RyaW5nKSB7XG4gIGlmICghc3RyaW5nIHx8IHN0cmluZyA9PT0gJycpIHtcbiAgICByZXR1cm4gbnVsbDtcbiAgfVxuXG4gIHJldHVybiBLZXJuZWwuU3BlY2lhbEZvcm1zLnR1cGxlKHN0cmluZ1swXSwgc3RyaW5nLnN1YnN0cigxKSk7XG59XG5cbmZ1bmN0aW9uIHJldmVyc2Uoc3RyaW5nKSB7XG4gIGxldCByZXR1cm5WYWx1ZSA9ICcnO1xuXG4gIGZvciAodmFyIGkgPSBzdHJpbmcubGVuZ3RoIC0gMTsgaSA+PSAwOyBpLS0pIHtcbiAgICByZXR1cm5WYWx1ZSA9IHJldHVyblZhbHVlICsgc3RyaW5nW2ldO1xuICB9O1xuXG4gIHJldHVybiByZXR1cm5WYWx1ZTtcbn1cblxuZnVuY3Rpb24gX3NwbGl0KHN0cmluZykge1xuICByZXR1cm4gc3RyaW5nLnNwbGl0KCk7XG59XG5cbmZ1bmN0aW9uIHN0YXJ0c193aXRoX19xbV9fKHN0cmluZywgcHJlZml4ZXMpIHtcbiAgaWYgKEFycmF5LmlzQXJyYXkocHJlZml4ZXMpKSB7XG4gICAgcmV0dXJuIHByZWZpeGVzLnNvbWUoZnVuY3Rpb24gKHMpIHtcbiAgICAgIHJldHVybiBzdHJpbmcuc3RhcnRzV2l0aChzKTtcbiAgICB9KTtcbiAgfVxuXG4gIHJldHVybiBzdHJpbmcuc3RhcnRzV2l0aChwcmVmaXhlcyk7XG59XG5cbmZ1bmN0aW9uIHZhbGlkX2NoYXJhY3Rlcl9fcW1fXyhjb2RlcG9pbnQpIHtcbiAgdHJ5IHtcbiAgICByZXR1cm4gU3RyaW5nLmZyb21Db2RlUG9pbnQoY29kZXBvaW50KSAhPSBudWxsO1xuICB9IGNhdGNoIChlKSB7XG4gICAgcmV0dXJuIGZhbHNlO1xuICB9XG59XG5cbnZhciBfU3RyaW5nID0ge1xuICBhdCxcbiAgY2FwaXRhbGl6ZSxcbiAgY29kZXBvaW50cyxcbiAgY29udGFpbnNfX3FtX18sXG4gIGRvd25jYXNlLFxuICBkdXBsaWNhdGUsXG4gIGVuZHNfd2l0aF9fcW1fXyxcbiAgZmlyc3QsXG4gIGdyYXBoZW1lcyxcbiAgbGFzdCxcbiAgbGVuZ3RoLFxuICBtYXRjaF9fcW1fXyxcbiAgbmV4dF9jb2RlcG9pbnQsXG4gIG5leHRfZ3JhcGhlbWUsXG4gIHJldmVyc2UsXG4gIHNwbGl0OiBfc3BsaXQsXG4gIHN0YXJ0c193aXRoX19xbV9fLFxuICB0b19hdG9tLFxuICB0b19jaGFyX2xpc3QsXG4gIHRvX2V4aXN0aW5nX2F0b20sXG4gIHRvX2Zsb2F0LFxuICB0b19pbnRlZ2VyLFxuICB1cGNhc2UsXG4gIHZhbGlkX2NoYXJhY3Rlcl9fcW1fXyxcbiAgQ2hhcnM6IF9DaGFyc1xufTtcblxubGV0IENoYXJzID0gS2VybmVsLmRlZnByb3RvY29sKHtcbiAgdG9fY2hhcl9saXN0OiBmdW5jdGlvbiAodGhpbmcpIHt9XG59KTtcblxuS2VybmVsLmRlZmltcGwoQ2hhcnMsIEtlcm5lbC5pc19iaXRzdHJpbmcsIHtcbiAgdG9fY2hhcl9saXN0OiBmdW5jdGlvbiAodGhpbmcpIHtcbiAgICBpZiAoS2VybmVsLmlzX2JpbmFyeSh0aGluZykpIHtcbiAgICAgIHJldHVybiBfU3RyaW5nLnRvX2NoYXJfbGlzdCh0aGluZyk7XG4gICAgfVxuXG4gICAgcmV0dXJuIHRoaW5nLnRvU3RyaW5nKCk7XG4gIH1cbn0pO1xuXG5LZXJuZWwuZGVmaW1wbChDaGFycywgS2VybmVsLmlzX2F0b20sIHtcbiAgdG9fY2hhcl9saXN0OiBmdW5jdGlvbiAodGhpbmcpIHtcbiAgICByZXR1cm4gQXRvbS50b19jaGFyX2xpc3QodGhpbmcpO1xuICB9XG59KTtcblxuS2VybmVsLmRlZmltcGwoQ2hhcnMsIEtlcm5lbC5pc19pbnRlZ2VyLCB7XG4gIHRvX2NoYXJfbGlzdDogZnVuY3Rpb24gKHRoaW5nKSB7XG4gICAgcmV0dXJuIEludGVnZXIudG9fY2hhcl9saXN0KHRoaW5nKTtcbiAgfVxufSk7XG5cbktlcm5lbC5kZWZpbXBsKENoYXJzLCBLZXJuZWwuaXNfbGlzdCwge1xuICB0b19jaGFyX2xpc3Q6IGZ1bmN0aW9uICh0aGluZykge1xuICAgIHJldHVybiB0aGluZztcbiAgfVxufSk7XG5cbmxldCBMaXN0ID0ge307XG5cbkxpc3QuQ2hhcnMgPSBDaGFycztcblxuTGlzdC5kZWxldGUgPSBmdW5jdGlvbiAobGlzdCwgaXRlbSkge1xuICBsZXQgbmV3X3ZhbHVlID0gW107XG4gIGxldCB2YWx1ZV9mb3VuZCA9IGZhbHNlO1xuXG4gIGZvciAobGV0IHggb2YgbGlzdCkge1xuICAgIGlmICh4ID09PSBpdGVtICYmIHZhbHVlX2ZvdW5kICE9PSBmYWxzZSkge1xuICAgICAgbmV3X3ZhbHVlLnB1c2goeCk7XG4gICAgICB2YWx1ZV9mb3VuZCA9IHRydWU7XG4gICAgfSBlbHNlIGlmICh4ICE9PSBpdGVtKSB7XG4gICAgICBuZXdfdmFsdWUucHVzaCh4KTtcbiAgICB9XG4gIH1cblxuICByZXR1cm4gS2VybmVsLlNwZWNpYWxGb3Jtcy5saXN0KC4uLm5ld192YWx1ZSk7XG59O1xuXG5MaXN0LmRlbGV0ZV9hdCA9IGZ1bmN0aW9uIChsaXN0LCBpbmRleCkge1xuICBsZXQgbmV3X3ZhbHVlID0gW107XG5cbiAgZm9yIChsZXQgaSA9IDA7IGkgPCBsaXN0Lmxlbmd0aDsgaSsrKSB7XG4gICAgaWYgKGkgIT09IGluZGV4KSB7XG4gICAgICBuZXdfdmFsdWUucHVzaChsaXN0W2ldKTtcbiAgICB9XG4gIH1cblxuICByZXR1cm4gS2VybmVsLlNwZWNpYWxGb3Jtcy5saXN0KC4uLm5ld192YWx1ZSk7XG59O1xuXG5MaXN0LmR1cGxpY2F0ZSA9IGZ1bmN0aW9uIChlbGVtLCBuKSB7XG4gIGxldCBuZXdfdmFsdWUgPSBbXTtcblxuICBmb3IgKHZhciBpID0gMDsgaSA8IG47IGkrKykge1xuICAgIG5ld192YWx1ZS5wdXNoKGVsZW0pO1xuICB9XG5cbiAgcmV0dXJuIEtlcm5lbC5TcGVjaWFsRm9ybXMubGlzdCguLi5uZXdfdmFsdWUpO1xufTtcblxuTGlzdC5maXJzdCA9IGZ1bmN0aW9uIChsaXN0KSB7XG4gIHJldHVybiBsaXN0WzBdO1xufTtcblxuTGlzdC5mbGF0dGVuID0gZnVuY3Rpb24gKGxpc3QsIHRhaWwgPSBLZXJuZWwuU3BlY2lhbEZvcm1zLmxpc3QoKSkge1xuICBsZXQgbmV3X3ZhbHVlID0gW107XG5cbiAgZm9yIChsZXQgeCBvZiBsaXN0KSB7XG4gICAgaWYgKEtlcm5lbC5pc19saXN0KHgpKSB7XG4gICAgICBuZXdfdmFsdWUgPSBuZXdfdmFsdWUuY29uY2F0KExpc3QuZmxhdHRlbih4KSk7XG4gICAgfSBlbHNlIHtcbiAgICAgIG5ld192YWx1ZS5wdXNoKHgpO1xuICAgIH1cbiAgfVxuXG4gIG5ld192YWx1ZSA9IG5ld192YWx1ZS5jb25jYXQodGFpbCk7XG5cbiAgcmV0dXJuIEtlcm5lbC5TcGVjaWFsRm9ybXMubGlzdCguLi5uZXdfdmFsdWUpO1xufTtcblxuTGlzdC5mb2xkbCA9IGZ1bmN0aW9uIChsaXN0LCBhY2MsIGZ1bmMpIHtcbiAgcmV0dXJuIGxpc3QucmVkdWNlKGZ1bmMsIGFjYyk7XG59O1xuXG5MaXN0LmZvbGRyID0gZnVuY3Rpb24gKGxpc3QsIGFjYywgZnVuYykge1xuICBsZXQgbmV3X2FjYyA9IGFjYztcblxuICBmb3IgKHZhciBpID0gbGlzdC5sZW5ndGggLSAxOyBpID49IDA7IGktLSkge1xuICAgIG5ld19hY2MgPSBmdW5jKGxpc3RbaV0sIG5ld19hY2MpO1xuICB9XG5cbiAgcmV0dXJuIG5ld19hY2M7XG59O1xuXG5MaXN0Lmluc2VydF9hdCA9IGZ1bmN0aW9uIChsaXN0LCBpbmRleCwgdmFsdWUpIHtcbiAgbGV0IG5ld192YWx1ZSA9IFtdO1xuXG4gIGZvciAobGV0IGkgPSAwOyBpIDwgbGlzdC5sZW5ndGg7IGkrKykge1xuICAgIGlmIChpID09PSBpbmRleCkge1xuICAgICAgbmV3X3ZhbHVlLnB1c2godmFsdWUpO1xuICAgICAgbmV3X3ZhbHVlLnB1c2gobGlzdFtpXSk7XG4gICAgfSBlbHNlIHtcbiAgICAgIG5ld192YWx1ZS5wdXNoKGxpc3RbaV0pO1xuICAgIH1cbiAgfVxuXG4gIHJldHVybiBLZXJuZWwuU3BlY2lhbEZvcm1zLmxpc3QoLi4ubmV3X3ZhbHVlKTtcbn07XG5cbkxpc3Qua2V5ZGVsZXRlID0gZnVuY3Rpb24gKGxpc3QsIGtleSwgcG9zaXRpb24pIHtcbiAgbGV0IG5ld19saXN0ID0gW107XG5cbiAgZm9yIChsZXQgaSA9IDA7IGkgPCBsaXN0Lmxlbmd0aDsgaSsrKSB7XG4gICAgaWYgKCFLZXJuZWwubWF0Y2hfX3FtYXJrX18obGlzdFtpXVtwb3NpdGlvbl0sIGtleSkpIHtcbiAgICAgIG5ld19saXN0LnB1c2gobGlzdFtpXSk7XG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIEtlcm5lbC5TcGVjaWFsRm9ybXMubGlzdCguLi5uZXdfbGlzdCk7XG59O1xuXG5MaXN0LmtleWZpbmQgPSBmdW5jdGlvbiAobGlzdCwga2V5LCBwb3NpdGlvbiwgX2RlZmF1bHQgPSBudWxsKSB7XG5cbiAgZm9yIChsZXQgaSA9IDA7IGkgPCBsaXN0Lmxlbmd0aDsgaSsrKSB7XG4gICAgaWYgKEtlcm5lbC5tYXRjaF9fcW1hcmtfXyhsaXN0W2ldW3Bvc2l0aW9uXSwga2V5KSkge1xuICAgICAgcmV0dXJuIGxpc3RbaV07XG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIF9kZWZhdWx0O1xufTtcblxuTGlzdC5rZXltZW1iZXJfX3FtYXJrX18gPSBmdW5jdGlvbiAobGlzdCwga2V5LCBwb3NpdGlvbikge1xuXG4gIGZvciAobGV0IGkgPSAwOyBpIDwgbGlzdC5sZW5ndGg7IGkrKykge1xuICAgIGlmIChLZXJuZWwubWF0Y2hfX3FtYXJrX18obGlzdFtpXVtwb3NpdGlvbl0sIGtleSkpIHtcbiAgICAgIHJldHVybiB0cnVlO1xuICAgIH1cbiAgfVxuXG4gIHJldHVybiBmYWxzZTtcbn07XG5cbkxpc3Qua2V5cmVwbGFjZSA9IGZ1bmN0aW9uIChsaXN0LCBrZXksIHBvc2l0aW9uLCBuZXdfdHVwbGUpIHtcbiAgbGV0IG5ld19saXN0ID0gW107XG5cbiAgZm9yIChsZXQgaSA9IDA7IGkgPCBsaXN0Lmxlbmd0aDsgaSsrKSB7XG4gICAgaWYgKCFLZXJuZWwubWF0Y2hfX3FtYXJrX18obGlzdFtpXVtwb3NpdGlvbl0sIGtleSkpIHtcbiAgICAgIG5ld19saXN0LnB1c2gobGlzdFtpXSk7XG4gICAgfSBlbHNlIHtcbiAgICAgIG5ld19saXN0LnB1c2gobmV3X3R1cGxlKTtcbiAgICB9XG4gIH1cblxuICByZXR1cm4gS2VybmVsLlNwZWNpYWxGb3Jtcy5saXN0KC4uLm5ld19saXN0KTtcbn07XG5cbkxpc3Qua2V5c29ydCA9IGZ1bmN0aW9uIChsaXN0LCBwb3NpdGlvbikge1xuICBsZXQgbmV3X2xpc3QgPSBsaXN0O1xuXG4gIG5ld19saXN0LnNvcnQoZnVuY3Rpb24gKGEsIGIpIHtcbiAgICBpZiAocG9zaXRpb24gPT09IDApIHtcbiAgICAgIGlmIChhW3Bvc2l0aW9uXS52YWx1ZSA8IGJbcG9zaXRpb25dLnZhbHVlKSB7XG4gICAgICAgIHJldHVybiAtMTtcbiAgICAgIH1cblxuICAgICAgaWYgKGFbcG9zaXRpb25dLnZhbHVlID4gYltwb3NpdGlvbl0udmFsdWUpIHtcbiAgICAgICAgcmV0dXJuIDE7XG4gICAgICB9XG5cbiAgICAgIHJldHVybiAwO1xuICAgIH0gZWxzZSB7XG4gICAgICBpZiAoYVtwb3NpdGlvbl0gPCBiW3Bvc2l0aW9uXSkge1xuICAgICAgICByZXR1cm4gLTE7XG4gICAgICB9XG5cbiAgICAgIGlmIChhW3Bvc2l0aW9uXSA+IGJbcG9zaXRpb25dKSB7XG4gICAgICAgIHJldHVybiAxO1xuICAgICAgfVxuXG4gICAgICByZXR1cm4gMDtcbiAgICB9XG4gIH0pO1xuXG4gIHJldHVybiBLZXJuZWwuU3BlY2lhbEZvcm1zLmxpc3QoLi4ubmV3X2xpc3QpO1xufTtcblxuTGlzdC5rZXlzdG9yZSA9IGZ1bmN0aW9uIChsaXN0LCBrZXksIHBvc2l0aW9uLCBuZXdfdHVwbGUpIHtcbiAgbGV0IG5ld19saXN0ID0gW107XG4gIGxldCByZXBsYWNlZCA9IGZhbHNlO1xuXG4gIGZvciAobGV0IGkgPSAwOyBpIDwgbGlzdC5sZW5ndGg7IGkrKykge1xuICAgIGlmICghS2VybmVsLm1hdGNoX19xbWFya19fKGxpc3RbaV1bcG9zaXRpb25dLCBrZXkpKSB7XG4gICAgICBuZXdfbGlzdC5wdXNoKGxpc3RbaV0pO1xuICAgIH0gZWxzZSB7XG4gICAgICBuZXdfbGlzdC5wdXNoKG5ld190dXBsZSk7XG4gICAgICByZXBsYWNlZCA9IHRydWU7XG4gICAgfVxuICB9XG5cbiAgaWYgKCFyZXBsYWNlZCkge1xuICAgIG5ld19saXN0LnB1c2gobmV3X3R1cGxlKTtcbiAgfVxuXG4gIHJldHVybiBLZXJuZWwuU3BlY2lhbEZvcm1zLmxpc3QoLi4ubmV3X2xpc3QpO1xufTtcblxuTGlzdC5sYXN0ID0gZnVuY3Rpb24gKGxpc3QpIHtcbiAgcmV0dXJuIGxpc3RbbGlzdC5sZW5ndGggLSAxXTtcbn07XG5cbkxpc3QucmVwbGFjZV9hdCA9IGZ1bmN0aW9uIChsaXN0LCBpbmRleCwgdmFsdWUpIHtcbiAgbGV0IG5ld192YWx1ZSA9IFtdO1xuXG4gIGZvciAobGV0IGkgPSAwOyBpIDwgbGlzdC5sZW5ndGg7IGkrKykge1xuICAgIGlmIChpID09PSBpbmRleCkge1xuICAgICAgbmV3X3ZhbHVlLnB1c2godmFsdWUpO1xuICAgIH0gZWxzZSB7XG4gICAgICBuZXdfdmFsdWUucHVzaChsaXN0W2ldKTtcbiAgICB9XG4gIH1cblxuICByZXR1cm4gS2VybmVsLlNwZWNpYWxGb3Jtcy5saXN0KC4uLm5ld192YWx1ZSk7XG59O1xuXG5MaXN0LnVwZGF0ZV9hdCA9IGZ1bmN0aW9uIChsaXN0LCBpbmRleCwgZnVuKSB7XG4gIGxldCBuZXdfdmFsdWUgPSBbXTtcblxuICBmb3IgKGxldCBpID0gMDsgaSA8IGxpc3QuY291bnQoKTsgaSsrKSB7XG4gICAgaWYgKGkgPT09IGluZGV4KSB7XG4gICAgICBuZXdfdmFsdWUucHVzaChmdW4obGlzdC5nZXQoaSkpKTtcbiAgICB9IGVsc2Uge1xuICAgICAgbmV3X3ZhbHVlLnB1c2gobGlzdC5nZXQoaSkpO1xuICAgIH1cbiAgfVxuXG4gIHJldHVybiBuZXdfdmFsdWU7XG59O1xuXG5MaXN0LndyYXAgPSBmdW5jdGlvbiAobGlzdCkge1xuICBpZiAoS2VybmVsLmlzX2xpc3QobGlzdCkpIHtcbiAgICByZXR1cm4gbGlzdDtcbiAgfSBlbHNlIGlmIChsaXN0ID09IG51bGwpIHtcbiAgICByZXR1cm4gS2VybmVsLlNwZWNpYWxGb3Jtcy5saXN0KCk7XG4gIH0gZWxzZSB7XG4gICAgcmV0dXJuIEtlcm5lbC5TcGVjaWFsRm9ybXMubGlzdChsaXN0KTtcbiAgfVxufTtcblxuTGlzdC56aXAgPSBmdW5jdGlvbiAobGlzdF9vZl9saXN0cykge1xuICBpZiAobGlzdF9vZl9saXN0cy5sZW5ndGggPT09IDApIHtcbiAgICByZXR1cm4gS2VybmVsLlNwZWNpYWxGb3Jtcy5saXN0KCk7XG4gIH1cblxuICBsZXQgbmV3X3ZhbHVlID0gW107XG4gIGxldCBzbWFsbGVzdF9sZW5ndGggPSBsaXN0X29mX2xpc3RzWzBdO1xuXG4gIGZvciAobGV0IHggb2YgbGlzdF9vZl9saXN0cykge1xuICAgIGlmICh4Lmxlbmd0aCA8IHNtYWxsZXN0X2xlbmd0aCkge1xuICAgICAgc21hbGxlc3RfbGVuZ3RoID0geC5sZW5ndGg7XG4gICAgfVxuICB9XG5cbiAgZm9yIChsZXQgaSA9IDA7IGkgPCBzbWFsbGVzdF9sZW5ndGg7IGkrKykge1xuICAgIGxldCBjdXJyZW50X3ZhbHVlID0gW107XG4gICAgZm9yIChsZXQgaiA9IDA7IGogPCBsaXN0X29mX2xpc3RzLmxlbmd0aDsgaisrKSB7XG4gICAgICBjdXJyZW50X3ZhbHVlLnB1c2gobGlzdF9vZl9saXN0c1tqXVtpXSk7XG4gICAgfVxuXG4gICAgbmV3X3ZhbHVlLnB1c2goS2VybmVsLlNwZWNpYWxGb3Jtcy50dXBsZSguLi5jdXJyZW50X3ZhbHVlKSk7XG4gIH1cblxuICByZXR1cm4gS2VybmVsLlNwZWNpYWxGb3Jtcy5saXN0KC4uLm5ld192YWx1ZSk7XG59O1xuXG5MaXN0LnRvX3R1cGxlID0gZnVuY3Rpb24gKGxpc3QpIHtcbiAgcmV0dXJuIEtlcm5lbC5TcGVjaWFsRm9ybXMudHVwbGUuYXBwbHkobnVsbCwgbGlzdCk7XG59O1xuXG5MaXN0LmFwcGVuZCA9IGZ1bmN0aW9uIChsaXN0LCB2YWx1ZSkge1xuICByZXR1cm4gS2VybmVsLlNwZWNpYWxGb3Jtcy5saXN0KC4uLmxpc3QuY29uY2F0KFt2YWx1ZV0pKTtcbn07XG5cbkxpc3QucHJlcGVuZCA9IGZ1bmN0aW9uIChsaXN0LCB2YWx1ZSkge1xuICByZXR1cm4gS2VybmVsLlNwZWNpYWxGb3Jtcy5saXN0KC4uLlt2YWx1ZV0uY29uY2F0KGxpc3QpKTtcbn07XG5cbkxpc3QuY29uY2F0ID0gZnVuY3Rpb24gKGxlZnQsIHJpZ2h0KSB7XG4gIHJldHVybiBsZWZ0LmNvbmNhdChyaWdodCk7XG59O1xuXG5jbGFzcyBTaWduYWwge1xuXG4gIGNvbnN0cnVjdG9yKCkge1xuICAgIHRoaXMuYmluZGluZ3MgPSBTcGVjaWFsRm9ybXMubGlzdCgpO1xuICB9XG5cbiAgYWRkKGxpc3RlbmVyLCBjb250ZXh0ID0gdGhpcykge1xuICAgIHRoaXMuYmluZGluZ3MgPSBMaXN0LmFwcGVuZCh0aGlzLmJpbmRpbmdzLCBuZXcgU2lnbmFsQmluZGluZyh0aGlzLCBsaXN0ZW5lciwgY29udGV4dCkpO1xuICB9XG5cbiAgcmVtb3ZlKGxpc3RlbmVyKSB7XG4gICAgdGhpcy5iaW5kaW5ncyA9IEVudW0uZmlsdGVyKHRoaXMuYmluZGluZ3MsIGZ1bmN0aW9uIChiaW5kaW5nKSB7XG4gICAgICByZXR1cm4gYmluZGluZy5saXN0ZW5lciAhPT0gbGlzdGVuZXI7XG4gICAgfSk7XG4gIH1cblxuICBkaXNwYXRjaCguLi5wYXJhbXMpIHtcbiAgICBmb3IgKGxldCBiaW5kaW5nIG9mIHRoaXMuYmluZGluZ3MpIHtcbiAgICAgIGJpbmRpbmcuZXhlY3V0ZSguLi5wYXJhbXMpO1xuICAgIH1cbiAgfVxuXG4gIGRpc3Bvc2UoKSB7XG4gICAgZm9yIChsZXQgYmluZGluZyBvZiB0aGlzLmJpbmRpbmdzKSB7XG4gICAgICBiaW5kaW5nLmRpc3Bvc2UoKTtcbiAgICB9XG5cbiAgICB0aGlzLmJpbmRpbmdzID0gbnVsbDtcbiAgfVxufVxuXG5jbGFzcyBTaWduYWxCaW5kaW5nIHtcblxuICBjb25zdHJ1Y3RvcihzaWduYWwsIGxpc3RlbmVyLCBjb250ZXh0KSB7XG4gICAgdGhpcy5saXN0ZW5lciA9IGxpc3RlbmVyO1xuICAgIHRoaXMuc2lnbmFsID0gc2lnbmFsO1xuICAgIHRoaXMuY29udGV4dCA9IGNvbnRleHQ7XG4gIH1cblxuICBleGVjdXRlKC4uLnBhcmFtcykge1xuICAgIHRoaXMubGlzdGVuZXIuYXBwbHkodGhpcy5jb250ZXh0LCBwYXJhbXMpO1xuICB9XG5cbiAgZGlzcG9zZSgpIHtcbiAgICB0aGlzLmxpc3RlbmVyID0gbnVsbDtcbiAgICB0aGlzLnNpZ25hbCA9IG51bGw7XG4gICAgdGhpcy5jb250ZXh0ID0gbnVsbDtcbiAgfVxufVxuXG5mdW5jdGlvbiBfX3VwZGF0ZShtYXAsIGtleSwgdmFsdWUpIHtcbiAgbGV0IG0gPSBuZXcgTWFwKG1hcCk7XG4gIG0uc2V0KGtleSwgdmFsdWUpO1xuICByZXR1cm4gbTtcbn1cblxuZnVuY3Rpb24gcmVtb3ZlKG1hcCwga2V5KSB7XG4gIGxldCBtID0gbmV3IE1hcChtYXApO1xuICBtLmRlbGV0ZShrZXkpO1xuICByZXR1cm4gbTtcbn1cblxuY2xhc3MgTWFpbEJveCB7XG5cbiAgY29uc3RydWN0b3IoY29udGV4dCA9IHRoaXMpIHtcbiAgICB0aGlzLnNpZ25hbCA9IG5ldyBTaWduYWwoKTtcbiAgICB0aGlzLnNpZ25hbC5hZGQoKC4uLnBhcmFtcykgPT4gdGhpcy5tZXNzYWdlcyA9IHRoaXMubWVzc2FnZXMuY29uY2F0KHBhcmFtcyksIGNvbnRleHQpO1xuICAgIHRoaXMubWVzc2FnZXMgPSBbXTtcbiAgfVxuXG4gIHJlY2VpdmUoLi4ubWVzc2FnZXMpIHtcbiAgICB0aGlzLnNpZ25hbC5kaXNwYXRjaCguLi5tZXNzYWdlcyk7XG4gIH1cblxuICBwZWVrKCkge1xuICAgIGlmICh0aGlzLm1lc3NhZ2VzLmxlbmd0aCA9PT0gMCkge1xuICAgICAgcmV0dXJuIG51bGw7XG4gICAgfVxuXG4gICAgcmV0dXJuIHRoaXMubWVzc2FnZXNbMF07XG4gIH1cblxuICByZWFkKCkge1xuICAgIGxldCByZXN1bHQgPSB0aGlzLm1lc3NhZ2VzWzBdO1xuICAgIHRoaXMubWVzc2FnZXMgPSB0aGlzLm1lc3NhZ2VzLnNsaWNlKDEpO1xuXG4gICAgcmV0dXJuIHJlc3VsdDtcbiAgfVxuXG4gIGFkZF9zdWJzY3JpYmVyKGZuLCBjb250ZXh0ID0gdGhpcykge1xuICAgIHRoaXMuc2lnbmFsLmFkZChmbiwgY29udGV4dCk7XG4gIH1cblxuICByZW1vdmVfc3Vic2NyaWJlcihmbikge1xuICAgIHRoaXMuc2lnbmFsLnJlbW92ZShmbik7XG4gIH1cblxuICBkaXNwb3NlKCkge1xuICAgIHRoaXMuc2lnbmFsLmRpc3Bvc2UoKTtcbiAgICB0aGlzLm1lc3NhZ2VzID0gbnVsbDtcbiAgfVxufVxuXG5jbGFzcyBQb3N0T2ZmaWNlIHtcblxuICBjb25zdHJ1Y3RvcigpIHtcbiAgICB0aGlzLm1haWxib3hlcyA9IG5ldyBNYXAoKTtcbiAgfVxuXG4gIHNlbmQoYWRkcmVzcywgbWVzc2FnZSkge1xuICAgIHRoaXMubWFpbGJveGVzLmdldChhZGRyZXNzKS5yZWNlaXZlKG1lc3NhZ2UpO1xuICB9XG5cbiAgcmVjZWl2ZShhZGRyZXNzKSB7XG4gICAgcmV0dXJuIHRoaXMubWFpbGJveGVzLmdldChhZGRyZXNzKS5yZWFkKCk7XG4gIH1cblxuICBwZWVrKGFkZHJlc3MpIHtcbiAgICByZXR1cm4gdGhpcy5tYWlsYm94ZXMuZ2V0KGFkZHJlc3MpLnBlZWsoKTtcbiAgfVxuXG4gIGFkZF9tYWlsYm94KGFkZHJlc3MgPSBTeW1ib2woKSwgY29udGV4dCA9IHRoaXMpIHtcbiAgICB0aGlzLm1haWxib3hlcyA9IF9fdXBkYXRlKHRoaXMubWFpbGJveGVzLCBhZGRyZXNzLCBuZXcgTWFpbEJveCgpKTtcbiAgICByZXR1cm4gYWRkcmVzcztcbiAgfVxuXG4gIHJlbW92ZV9tYWlsYm94KGFkZHJlc3MpIHtcbiAgICB0aGlzLm1haWxib3hlcy5nZXQoYWRkcmVzcykuZGlzcG9zZSgpO1xuICAgIHRoaXMubWFpbGJveGVzID0gcmVtb3ZlKHRoaXMubWFpbGJveGVzLCBhZGRyZXNzKTtcbiAgfVxuXG4gIHN1YnNjcmliZShhZGRyZXNzLCBzdWJzY3JpYnRpb25fZm4sIGNvbnRleHQgPSB0aGlzKSB7XG4gICAgdGhpcy5tYWlsYm94ZXMuZ2V0KGFkZHJlc3MpLmFkZF9zdWJzY3JpYmVyKHN1YnNjcmlidGlvbl9mbiwgY29udGV4dCk7XG4gIH1cblxuICB1bnN1YnNjcmliZShhZGRyZXNzLCBzdWJzY3JpYnRpb25fZm4pIHtcbiAgICB0aGlzLm1haWxib3hlcy5nZXQoYWRkcmVzcykucmVtb3ZlX3N1YnNjcmliZXIoc3Vic2NyaWJ0aW9uX2ZuKTtcbiAgfVxufVxuXG5mdW5jdGlvbiBjYWxsX3Byb3BlcnR5KGl0ZW0sIHByb3BlcnR5KSB7XG4gIGlmIChwcm9wZXJ0eSBpbiBpdGVtKSB7XG4gICAgaXRlbVtwcm9wZXJ0eV07XG4gICAgaWYgKGl0ZW1bcHJvcGVydHldIGluc3RhbmNlb2YgRnVuY3Rpb24pIHtcbiAgICAgIHJldHVybiBpdGVtW3Byb3BlcnR5XSgpO1xuICAgIH0gZWxzZSB7XG4gICAgICByZXR1cm4gaXRlbVtwcm9wZXJ0eV07XG4gICAgfVxuICB9IGVsc2UgaWYgKFN5bWJvbC5mb3IocHJvcGVydHkpIGluIGl0ZW0pIHtcbiAgICBsZXQgcHJvcCA9IFN5bWJvbC5mb3IocHJvcGVydHkpO1xuICAgIGlmIChpdGVtW3Byb3BdIGluc3RhbmNlb2YgRnVuY3Rpb24pIHtcbiAgICAgIHJldHVybiBpdGVtW3Byb3BdKCk7XG4gICAgfSBlbHNlIHtcbiAgICAgIHJldHVybiBpdGVtW3Byb3BdO1xuICAgIH1cbiAgfVxuXG4gIHRocm93IG5ldyBFcnJvcihgUHJvcGVydHkgJHsgcHJvcGVydHkgfSBub3QgZm91bmQgaW4gJHsgaXRlbSB9YCk7XG59XG5cbnZhciBKUyA9IHtcbiAgY2FsbF9wcm9wZXJ0eVxufTtcblxubGV0IFJhbmdlID0gZnVuY3Rpb24gKF9maXJzdCwgX2xhc3QpIHtcbiAgaWYgKCEodGhpcyBpbnN0YW5jZW9mIFJhbmdlKSkge1xuICAgIHJldHVybiBuZXcgUmFuZ2UoX2ZpcnN0LCBfbGFzdCk7XG4gIH1cblxuICB0aGlzLmZpcnN0ID0gZnVuY3Rpb24gKCkge1xuICAgIHJldHVybiBfZmlyc3Q7XG4gIH07XG5cbiAgdGhpcy5sYXN0ID0gZnVuY3Rpb24gKCkge1xuICAgIHJldHVybiBfbGFzdDtcbiAgfTtcblxuICBsZXQgX3JhbmdlID0gW107XG5cbiAgZm9yIChsZXQgaSA9IF9maXJzdDsgaSA8PSBfbGFzdDsgaSsrKSB7XG4gICAgX3JhbmdlLnB1c2goaSk7XG4gIH1cblxuICBfcmFuZ2UgPSBPYmplY3QuZnJlZXplKF9yYW5nZSk7XG5cbiAgdGhpcy52YWx1ZSA9IGZ1bmN0aW9uICgpIHtcbiAgICByZXR1cm4gX3JhbmdlO1xuICB9O1xuXG4gIHRoaXMubGVuZ3RoID0gZnVuY3Rpb24gKCkge1xuICAgIHJldHVybiBfcmFuZ2UubGVuZ3RoO1xuICB9O1xuXG4gIHJldHVybiB0aGlzO1xufTtcblxuUmFuZ2UucHJvdG90eXBlW1N5bWJvbC5pdGVyYXRvcl0gPSBmdW5jdGlvbiAoKSB7XG4gIHJldHVybiB0aGlzLnZhbHVlKClbU3ltYm9sLml0ZXJhdG9yXSgpO1xufTtcblxuUmFuZ2UubmV3ID0gZnVuY3Rpb24gKGZpcnN0LCBsYXN0KSB7XG4gIHJldHVybiBSYW5nZShmaXJzdCwgbGFzdCk7XG59O1xuXG5SYW5nZS5yYW5nZV9fcW1hcmtfXyA9IGZ1bmN0aW9uIChyYW5nZSkge1xuICByZXR1cm4gcmFuZ2UgaW5zdGFuY2VvZiBSYW5nZTtcbn07XG5cbmxldCBLZXl3b3JkID0ge307XG5cbktleXdvcmQuaGFzX2tleV9fcW1fXyA9IGZ1bmN0aW9uIChrZXl3b3Jkcywga2V5KSB7XG4gIGZvciAobGV0IGtleXdvcmQgb2Yga2V5d29yZHMpIHtcbiAgICBpZiAoS2VybmVsLmVsZW0oa2V5d29yZCwgMCkgPT0ga2V5KSB7XG4gICAgICByZXR1cm4gdHJ1ZTtcbiAgICB9XG4gIH1cblxuICByZXR1cm4gZmFsc2U7XG59O1xuXG5LZXl3b3JkLmdldCA9IGZ1bmN0aW9uIChrZXl3b3Jkcywga2V5LCB0aGVfZGVmYXVsdCA9IG51bGwpIHtcbiAgZm9yIChsZXQga2V5d29yZCBvZiBrZXl3b3Jkcykge1xuICAgIGlmIChLZXJuZWwuZWxlbShrZXl3b3JkLCAwKSA9PSBrZXkpIHtcbiAgICAgIHJldHVybiBLZXJuZWwuZWxlbShrZXl3b3JkLCAxKTtcbiAgICB9XG4gIH1cblxuICByZXR1cm4gdGhlX2RlZmF1bHQ7XG59O1xuXG5sZXQgQWdlbnQgPSB7fTtcblxuQWdlbnQuc3RhcnQgPSBmdW5jdGlvbiAoZnVuLCBvcHRpb25zID0gW10pIHtcbiAgY29uc3QgbmFtZSA9IEtleXdvcmQuaGFzX2tleV9fcW1fXyhvcHRpb25zLCBLZXJuZWwuU3BlY2lhbEZvcm1zLmF0b20oJ25hbWUnKSkgPyBLZXl3b3JkLmdldChvcHRpb25zLCBLZXJuZWwuU3BlY2lhbEZvcm1zLmF0b20oJ25hbWUnKSkgOiBTeW1ib2woKTtcblxuICBzZWxmLnBvc3Rfb2ZmaWNlLmFkZF9tYWlsYm94KG5hbWUpO1xuICBzZWxmLnBvc3Rfb2ZmaWNlLnNlbmQobmFtZSwgZnVuKCkpO1xuXG4gIHJldHVybiBLZXJuZWwuU3BlY2lhbEZvcm1zLnR1cGxlKEtlcm5lbC5TcGVjaWFsRm9ybXMuYXRvbSgnb2snKSwgbmFtZSk7XG59O1xuXG5BZ2VudC5zdG9wID0gZnVuY3Rpb24gKGFnZW50LCB0aW1lb3V0ID0gNTAwMCkge1xuICBzZWxmLnBvc3Rfb2ZmaWNlLnJlbW92ZV9tYWlsYm94KGFnZW50KTtcbiAgcmV0dXJuIEtlcm5lbC5TcGVjaWFsRm9ybXMuYXRvbSgnb2snKTtcbn07XG5cbkFnZW50LnVwZGF0ZSA9IGZ1bmN0aW9uIChhZ2VudCwgZnVuLCB0aW1lb3V0ID0gNTAwMCkge1xuXG4gIGNvbnN0IGN1cnJlbnRfc3RhdGUgPSBzZWxmLnBvc3Rfb2ZmaWNlLnJlY2VpdmUoYWdlbnQpO1xuICBzZWxmLnBvc3Rfb2ZmaWNlLnNlbmQoYWdlbnQsIGZ1bihjdXJyZW50X3N0YXRlKSk7XG5cbiAgcmV0dXJuIEtlcm5lbC5TcGVjaWFsRm9ybXMuYXRvbSgnb2snKTtcbn07XG5cbkFnZW50LmdldCA9IGZ1bmN0aW9uIChhZ2VudCwgZnVuLCB0aW1lb3V0ID0gNTAwMCkge1xuICByZXR1cm4gZnVuKHNlbGYucG9zdF9vZmZpY2UucGVlayhhZ2VudCkpO1xufTtcblxuQWdlbnQuZ2V0X2FuZF91cGRhdGUgPSBmdW5jdGlvbiAoYWdlbnQsIGZ1biwgdGltZW91dCA9IDUwMDApIHtcblxuICBjb25zdCBnZXRfYW5kX3VwZGF0ZV90dXBsZSA9IGZ1bihzZWxmLnBvc3Rfb2ZmaWNlLnJlY2VpdmUoYWdlbnQpKTtcbiAgc2VsZi5wb3N0X29mZmljZS5zZW5kKGFnZW50LCBLZXJuZWwuZWxlbShnZXRfYW5kX3VwZGF0ZV90dXBsZSwgMSkpO1xuXG4gIHJldHVybiBLZXJuZWwuZWxlbShnZXRfYW5kX3VwZGF0ZV90dXBsZSwgMCk7XG59O1xuXG4vL2h0dHBzOi8vZGV2ZWxvcGVyLm1vemlsbGEub3JnL2VuLVVTL2RvY3MvV2ViL0FQSS9XaW5kb3dCYXNlNjQvQmFzZTY0X2VuY29kaW5nX2FuZF9kZWNvZGluZyNTb2x1dGlvbl8yXyVFMiU4MCU5M19yZXdyaXRlX3RoZV9ET01zX2F0b2IoKV9hbmRfYnRvYSgpX3VzaW5nX0phdmFTY3JpcHQnc19UeXBlZEFycmF5c19hbmRfVVRGLThcbmZ1bmN0aW9uIGI2NEVuY29kZVVuaWNvZGUoc3RyKSB7XG4gIHJldHVybiBidG9hKGVuY29kZVVSSUNvbXBvbmVudChzdHIpLnJlcGxhY2UoLyUoWzAtOUEtRl17Mn0pL2csIGZ1bmN0aW9uIChtYXRjaCwgcDEpIHtcbiAgICByZXR1cm4gU3RyaW5nLmZyb21DaGFyQ29kZSgnMHgnICsgcDEpO1xuICB9KSk7XG59XG5cbmZ1bmN0aW9uIGVuY29kZTY0KGRhdGEpIHtcbiAgcmV0dXJuIGI2NEVuY29kZVVuaWNvZGUoZGF0YSk7XG59XG5cbmZ1bmN0aW9uIGRlY29kZTY0KGRhdGEpIHtcbiAgdHJ5IHtcbiAgICByZXR1cm4gS2VybmVsLlNwZWNpYWxGb3Jtcy50dXBsZShLZXJuZWwuU3BlY2lhbEZvcm1zLmF0b20oJ29rJyksIGF0b2IoZGF0YSkpO1xuICB9IGNhdGNoIChlKSB7XG4gICAgcmV0dXJuIEtlcm5lbC5TcGVjaWFsRm9ybXMuYXRvbSgnZXJyb3InKTtcbiAgfVxuICByZXR1cm4gYnRvYShkYXRhKTtcbn1cblxuZnVuY3Rpb24gZGVjb2RlNjRfX2VtX18oZGF0YSkge1xuICByZXR1cm4gYXRvYihkYXRhKTtcbn1cblxudmFyIEJhc2UgPSB7XG4gIGVuY29kZTY0LFxuICBkZWNvZGU2NCxcbiAgZGVjb2RlNjRfX2VtX19cbn07XG5cbmZ1bmN0aW9uIGJub3QoZXhwcikge1xuICByZXR1cm4gfmV4cHI7XG59XG5cbmZ1bmN0aW9uIGJhbmQobGVmdCwgcmlnaHQpIHtcbiAgcmV0dXJuIGxlZnQgJiByaWdodDtcbn1cblxuZnVuY3Rpb24gYm9yKGxlZnQsIHJpZ2h0KSB7XG4gIHJldHVybiBsZWZ0IHwgcmlnaHQ7XG59XG5cbmZ1bmN0aW9uIGJzbChsZWZ0LCByaWdodCkge1xuICByZXR1cm4gbGVmdCA8PCByaWdodDtcbn1cblxuZnVuY3Rpb24gYnNyKGxlZnQsIHJpZ2h0KSB7XG4gIHJldHVybiBsZWZ0ID4+IHJpZ2h0O1xufVxuXG5mdW5jdGlvbiBieG9yKGxlZnQsIHJpZ2h0KSB7XG4gIHJldHVybiBsZWZ0IF4gcmlnaHQ7XG59XG5cbnZhciBCaXR3aXNlID0ge1xuICBibm90LFxuICBiYW5kLFxuICBib3IsXG4gIGJzbCxcbiAgYnNyLFxuICBieG9yXG59O1xuXG5sZXQgRW51bWVyYWJsZSA9IEtlcm5lbC5kZWZwcm90b2NvbCh7XG4gIGNvdW50OiBmdW5jdGlvbiAoY29sbGVjdGlvbikge30sXG4gIG1lbWJlcl9xbWFya19fOiBmdW5jdGlvbiAoY29sbGVjdGlvbiwgdmFsdWUpIHt9LFxuICByZWR1Y2U6IGZ1bmN0aW9uIChjb2xsZWN0aW9uLCBhY2MsIGZ1bikge31cbn0pO1xuXG5sZXQgQ29sbGVjdGFibGUgPSBLZXJuZWwuZGVmcHJvdG9jb2woe1xuICBpbnRvOiBmdW5jdGlvbiAoY29sbGVjdGFibGUpIHt9XG59KTtcblxubGV0IEluc3BlY3QgPSBLZXJuZWwuZGVmcHJvdG9jb2woe1xuICBpbnNwZWN0OiBmdW5jdGlvbiAodGhpbmcsIG9wdHMpIHt9XG59KTtcblxuZnVuY3Rpb24gX19fbmV3X18oKSB7XG4gIHJldHVybiBTcGVjaWFsRm9ybXMubWFwKHt9KTtcbn1cblxuZnVuY3Rpb24ga2V5cyhtYXApIHtcbiAgcmV0dXJuIE9iamVjdC5rZXlzKG1hcCk7XG59XG5cbmZ1bmN0aW9uIF9fc2l6ZShtYXApIHtcbiAgcmV0dXJuIGtleXMobWFwKS5sZW5ndGg7XG59XG5cbmZ1bmN0aW9uIF9fdG9fbGlzdChtYXApIHtcbiAgbGV0IG1hcF9rZXlzID0ga2V5cyhtYXApO1xuICBsZXQgbGlzdCA9IFtdO1xuXG4gIGZvciAobGV0IGtleSBvZiBtYXBfa2V5cykge1xuICAgIGxpc3QucHVzaChTcGVjaWFsRm9ybXMudHVwbGUoa2V5LCBtYXBba2V5XSkpO1xuICB9XG5cbiAgcmV0dXJuIFNwZWNpYWxGb3Jtcy5saXN0KC4uLmxpc3QpO1xufVxuXG5mdW5jdGlvbiB2YWx1ZXMobWFwKSB7XG4gIGxldCBtYXBfa2V5cyA9IGtleXMobWFwKTtcbiAgbGV0IGxpc3QgPSBbXTtcblxuICBmb3IgKGxldCBrZXkgb2YgbWFwX2tleXMpIHtcbiAgICBsaXN0LnB1c2gobWFwW2tleV0pO1xuICB9XG5cbiAgcmV0dXJuIFNwZWNpYWxGb3Jtcy5saXN0KC4uLmxpc3QpO1xufVxuXG5mdW5jdGlvbiBmcm9tX3N0cnVjdChzdHJ1Y3QpIHtcbiAgbGV0IG1hcCA9IE9iamVjdC5hc3NpZ24oe30sIHN0cnVjdCk7XG4gIGRlbGV0ZSBtYXBbU3ltYm9sLmZvcihcIl9fc3RydWN0X19cIildO1xuXG4gIHJldHVybiBTcGVjaWFsRm9ybXMubWFwKG1hcCk7XG59XG5cbmZ1bmN0aW9uIF9fX19kZWxldGVfXyhtYXAsIGtleSkge1xuICBsZXQgbmV3X21hcCA9IE9iamVjdC5hc3NpZ24oe30sIG1hcCk7XG5cbiAgZGVsZXRlIG5ld19tYXBba2V5XTtcblxuICByZXR1cm4gU3BlY2lhbEZvcm1zLm1hcChuZXdfbWFwKTtcbn1cblxuZnVuY3Rpb24gZHJvcChtYXAsIGtleXMpIHtcbiAgbGV0IG5ld19tYXAgPSBPYmplY3QuYXNzaWduKHt9LCBtYXApO1xuXG4gIGZvciAobGV0IGtleSBvZiBrZXlzKSB7XG4gICAgZGVsZXRlIG5ld19tYXBba2V5XTtcbiAgfVxuXG4gIHJldHVybiBTcGVjaWFsRm9ybXMubWFwKG5ld19tYXApO1xufVxuXG5mdW5jdGlvbiBfX2VxdWFsX19xbWFya19fKG1hcDEsIG1hcDIpIHtcbiAgcmV0dXJuIG1hcDEgPT09IG1hcDI7XG59XG5cbmZ1bmN0aW9uIGZldGNoX19lbWFya19fKG1hcCwga2V5KSB7XG4gIGlmIChrZXkgaW4gbWFwKSB7XG4gICAgcmV0dXJuIG1hcFtrZXldO1xuICB9XG5cbiAgdGhyb3cgbmV3IEVycm9yKFwiS2V5IG5vdCBmb3VuZC5cIik7XG59XG5cbmZ1bmN0aW9uIGZldGNoKG1hcCwga2V5KSB7XG4gIGlmIChrZXkgaW4gbWFwKSB7XG4gICAgcmV0dXJuIFNwZWNpYWxGb3Jtcy50dXBsZShTcGVjaWFsRm9ybXMuYXRvbShcIm9rXCIpLCBtYXBba2V5XSk7XG4gIH1cblxuICByZXR1cm4gU3BlY2lhbEZvcm1zLmF0b20oXCJlcnJvclwiKTtcbn1cblxuZnVuY3Rpb24gaGFzX2tleV9fcW1hcmtfXyhtYXAsIGtleSkge1xuICByZXR1cm4ga2V5IGluIG1hcDtcbn1cblxuZnVuY3Rpb24gbWVyZ2UobWFwMSwgbWFwMikge1xuICByZXR1cm4gU3BlY2lhbEZvcm1zLm1hcF91cGRhdGUobWFwMSwgbWFwMik7XG59XG5cbmZ1bmN0aW9uIHNwbGl0KG1hcCwga2V5cykge1xuICBsZXQgc3BsaXQxID0ge307XG4gIGxldCBzcGxpdDIgPSB7fTtcblxuICBmb3IgKGxldCBrZXkgb2YgT2JqZWN0LmtleXMobWFwKSkge1xuICAgIGlmIChrZXlzLmluZGV4T2Yoa2V5KSA+IC0xKSB7XG4gICAgICBzcGxpdDFba2V5XSA9IG1hcFtrZXldO1xuICAgIH0gZWxzZSB7XG4gICAgICBzcGxpdDJba2V5XSA9IG1hcFtrZXldO1xuICAgIH1cbiAgfVxuXG4gIHJldHVybiBTcGVjaWFsRm9ybXMudHVwbGUoU3BlY2lhbEZvcm1zLm1hcChzcGxpdDEpLCBTcGVjaWFsRm9ybXMubWFwKHNwbGl0MikpO1xufVxuXG5mdW5jdGlvbiB0YWtlKG1hcCwga2V5cykge1xuICBsZXQgc3BsaXQxID0ge307XG5cbiAgZm9yIChsZXQga2V5IG9mIE9iamVjdC5rZXlzKG1hcCkpIHtcbiAgICBpZiAoa2V5cy5pbmRleE9mKGtleSkgPiAtMSkge1xuICAgICAgc3BsaXQxW2tleV0gPSBtYXBba2V5XTtcbiAgICB9XG4gIH1cblxuICByZXR1cm4gU3BlY2lhbEZvcm1zLm1hcChzcGxpdDEpO1xufVxuXG5mdW5jdGlvbiBkcm9wKG1hcCwga2V5cykge1xuICBsZXQgc3BsaXQxID0ge307XG5cbiAgZm9yIChsZXQga2V5IG9mIE9iamVjdC5rZXlzKG1hcCkpIHtcbiAgICBpZiAoa2V5cy5pbmRleE9mKGtleSkgPT09IC0xKSB7XG4gICAgICBzcGxpdDFba2V5XSA9IG1hcFtrZXldO1xuICAgIH1cbiAgfVxuXG4gIHJldHVybiBTcGVjaWFsRm9ybXMubWFwKHNwbGl0MSk7XG59XG5cbmZ1bmN0aW9uIHB1dF9uZXcobWFwLCBrZXksIHZhbHVlKSB7XG4gIGlmIChrZXkgaW4gbWFwKSB7XG4gICAgcmV0dXJuIG1hcDtcbiAgfVxuXG4gIGxldCBuZXdfbWFwID0gT2JqZWN0LmFzc2lnbih7fSwgbWFwKTtcbiAgbmV3X21hcFtrZXldID0gdmFsdWU7XG5cbiAgcmV0dXJuIFNwZWNpYWxGb3Jtcy5tYXAobmV3X21hcCk7XG59XG5cbmZ1bmN0aW9uIHB1dF9uZXdfbGF6eShtYXAsIGtleSwgZnVuKSB7XG4gIGlmIChrZXkgaW4gbWFwKSB7XG4gICAgcmV0dXJuIG1hcDtcbiAgfVxuXG4gIGxldCBuZXdfbWFwID0gT2JqZWN0LmFzc2lnbih7fSwgbWFwKTtcbiAgbmV3X21hcFtrZXldID0gZnVuKCk7XG5cbiAgcmV0dXJuIFNwZWNpYWxGb3Jtcy5tYXAobmV3X21hcCk7XG59XG5cbmZ1bmN0aW9uIGdldF9hbmRfdXBkYXRlKG1hcCwga2V5LCBmdW4pIHtcbiAgaWYgKGtleSBpbiBtYXApIHtcbiAgICByZXR1cm4gbWFwO1xuICB9XG5cbiAgbGV0IG5ld19tYXAgPSBPYmplY3QuYXNzaWduKHt9LCBtYXApO1xuICBuZXdfbWFwW2tleV0gPSBmdW4obWFwW2tleV0pO1xuXG4gIHJldHVybiBTcGVjaWFsRm9ybXMubWFwKG5ld19tYXApO1xufVxuXG5mdW5jdGlvbiBwb3BfbGF6eShtYXAsIGtleSwgZnVuKSB7XG4gIGlmICgha2V5IGluIG1hcCkge1xuICAgIHJldHVybiBTcGVjaWFsRm9ybXMudHVwbGUoZnVuKCksIG1hcCk7XG4gIH1cblxuICBsZXQgbmV3X21hcCA9IE9iamVjdC5hc3NpZ24oe30sIG1hcCk7XG4gIGxldCB2YWx1ZSA9IGZ1bihuZXdfbWFwW2tleV0pO1xuICBkZWxldGUgbmV3X21hcFtrZXldO1xuXG4gIHJldHVybiBTcGVjaWFsRm9ybXMudHVwbGUodmFsdWUsIG5ld19tYXApO1xufVxuXG5mdW5jdGlvbiBwb3AobWFwLCBrZXksIF9kZWZhdWx0ID0gbnVsbCkge1xuICBpZiAoIWtleSBpbiBtYXApIHtcbiAgICByZXR1cm4gU3BlY2lhbEZvcm1zLnR1cGxlKF9kZWZhdWx0LCBtYXApO1xuICB9XG5cbiAgbGV0IG5ld19tYXAgPSBPYmplY3QuYXNzaWduKHt9LCBtYXApO1xuICBsZXQgdmFsdWUgPSBuZXdfbWFwW2tleV07XG4gIGRlbGV0ZSBuZXdfbWFwW2tleV07XG5cbiAgcmV0dXJuIFNwZWNpYWxGb3Jtcy50dXBsZSh2YWx1ZSwgbmV3X21hcCk7XG59XG5cbmZ1bmN0aW9uIGdldF9sYXp5KG1hcCwga2V5LCBmdW4pIHtcbiAgaWYgKCFrZXkgaW4gbWFwKSB7XG4gICAgcmV0dXJuIGZ1bigpO1xuICB9XG5cbiAgcmV0dXJuIGZ1bihtYXBba2V5XSk7XG59XG5cbmZ1bmN0aW9uIGdldChtYXAsIGtleSwgX2RlZmF1bHQgPSBudWxsKSB7XG4gIGlmICgha2V5IGluIG1hcCkge1xuICAgIHJldHVybiBfZGVmYXVsdDtcbiAgfVxuXG4gIHJldHVybiBtYXBba2V5XTtcbn1cblxuZnVuY3Rpb24gX19wdXQobWFwLCBrZXksIHZhbCkge1xuICBsZXQgbmV3X21hcCA9IE9iamVjdCh7fSwgbWFwKTtcbiAgbmV3X21hcFtrZXldID0gdmFsO1xuXG4gIHJldHVybiBTcGVjaWFsRm9ybXMubWFwKG5ld19tYXApO1xufVxuXG5mdW5jdGlvbiB1cGRhdGVfX2VtYXJrX18obWFwLCBrZXksIGZ1bikge1xuICBpZiAoIWtleSBpbiBtYXApIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoXCJLZXkgbm90IGZvdW5kXCIpO1xuICB9XG5cbiAgbGV0IG5ld19tYXAgPSBPYmplY3Qoe30sIG1hcCk7XG4gIG5ld19tYXBba2V5XSA9IGZ1bihtYXBba2V5XSk7XG5cbiAgcmV0dXJuIFNwZWNpYWxGb3Jtcy5tYXAobmV3X21hcCk7XG59XG5cbmZ1bmN0aW9uIF91cGRhdGUobWFwLCBrZXksIGluaXRpYWwsIGZ1bikge1xuICBsZXQgbmV3X21hcCA9IE9iamVjdCh7fSwgbWFwKTtcblxuICBpZiAoIWtleSBpbiBtYXApIHtcbiAgICBuZXdfbWFwW2tleV0gPSBpbml0aWFsO1xuICB9IGVsc2Uge1xuICAgIG5ld19tYXBba2V5XSA9IGZ1bihtYXBba2V5XSk7XG4gIH1cblxuICByZXR1cm4gU3BlY2lhbEZvcm1zLm1hcChuZXdfbWFwKTtcbn1cblxudmFyIF9NYXAgPSB7XG4gIG5ldzogX19fbmV3X18sXG4gIGtleXMsXG4gIHNpemU6IF9fc2l6ZSxcbiAgdG9fbGlzdDogX190b19saXN0LFxuICB2YWx1ZXMsXG4gIGZyb21fc3RydWN0LFxuICBkZWxldGU6IF9fX19kZWxldGVfXyxcbiAgZHJvcCxcbiAgZXF1YWxfX3FtYXJrX186IF9fZXF1YWxfX3FtYXJrX18sXG4gIGZldGNoX19lbWFya19fLFxuICBmZXRjaCxcbiAgaGFzX2tleV9fcW1hcmtfXyxcbiAgc3BsaXQsXG4gIHRha2UsXG4gIHB1dF9uZXcsXG4gIHB1dF9uZXdfbGF6eSxcbiAgZ2V0X2FuZF91cGRhdGUsXG4gIHBvcF9sYXp5LFxuICBwb3AsXG4gIGdldF9sYXp5LFxuICBnZXQsXG4gIHB1dDogX19wdXQsXG4gIHVwZGF0ZV9fZW1hcmtfXyxcbiAgdXBkYXRlOiBfdXBkYXRlXG59O1xuXG5mdW5jdGlvbiBfX25ld19fKCkge1xuICByZXR1cm4gU3BlY2lhbEZvcm1zLm1hcCh7IFtTeW1ib2wuZm9yKCdfX3N0cnVjdF9fJyldOiBTeW1ib2wuZm9yKCdNYXBTZXQnKSwgc2V0OiBTcGVjaWFsRm9ybXMubGlzdCgpIH0pO1xufVxuXG5mdW5jdGlvbiBfc2l6ZShtYXApIHtcbiAgcmV0dXJuIG1hcC5zZXQubGVuZ3RoO1xufVxuXG5mdW5jdGlvbiBfdG9fbGlzdChtYXApIHtcbiAgcmV0dXJuIG1hcC5zZXQ7XG59XG5cbmZ1bmN0aW9uIF9fX2RlbGV0ZV9fKHNldCwgdGVybSkge1xuICBsZXQgbmV3X2xpc3QgPSBMaXN0LmRlbGV0ZShzZXQuc2V0LCB0ZXJtKTtcblxuICBsZXQgbmV3X21hcCA9IE9iamVjdC5hc3NpZ24oe30sIHNldCk7XG4gIG5ld19tYXAuc2V0ID0gbmV3X2xpc3Q7XG4gIHJldHVybiBTcGVjaWFsRm9ybXMubWFwKG5ld19tYXApO1xufVxuXG5mdW5jdGlvbiBfcHV0KHNldCwgdGVybSkge1xuICBpZiAoc2V0LnNldC5pbmRleE9mKHRlcm0pID09PSAtMSkge1xuICAgIGxldCBuZXdfbGlzdCA9IExpc3QuYXBwZW5kKHNldC5zZXQsIHRlcm0pO1xuXG4gICAgbGV0IG5ld19tYXAgPSBPYmplY3QuYXNzaWduKHt9LCBzZXQpO1xuICAgIG5ld19tYXAuc2V0ID0gbmV3X2xpc3Q7XG4gICAgcmV0dXJuIFNwZWNpYWxGb3Jtcy5tYXAobmV3X21hcCk7XG4gIH1cblxuICByZXR1cm4gc2V0O1xufVxuXG5mdW5jdGlvbiBfZGlmZmVyZW5jZShzZXQxLCBzZXQyKSB7XG4gIGxldCBuZXdfbWFwID0gT2JqZWN0LmFzc2lnbih7fSwgc2V0MSk7XG5cbiAgZm9yIChsZXQgdmFsIG9mIHNldDEuc2V0KSB7XG4gICAgaWYgKF9tZW1iZXJfX3FtYXJrX18oc2V0MiwgdmFsKSkge1xuICAgICAgbmV3X21hcC5zZXQgPSBMaXN0LmRlbGV0ZShuZXdfbWFwLnNldCwgdmFsKTtcbiAgICB9XG4gIH1cblxuICByZXR1cm4gU3BlY2lhbEZvcm1zLm1hcChuZXdfbWFwKTtcbn1cblxuZnVuY3Rpb24gX2ludGVyc2VjdGlvbihzZXQxLCBzZXQyKSB7XG4gIGxldCBuZXdfbWFwID0gT2JqZWN0LmFzc2lnbih7fSwgc2V0MSk7XG5cbiAgZm9yIChsZXQgdmFsIG9mIHNldDEuc2V0KSB7XG4gICAgaWYgKCFfbWVtYmVyX19xbWFya19fKHNldDIsIHZhbCkpIHtcbiAgICAgIG5ld19tYXAuc2V0ID0gTGlzdC5kZWxldGUobmV3X21hcC5zZXQsIHZhbCk7XG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIFNwZWNpYWxGb3Jtcy5tYXAobmV3X21hcCk7XG59XG5cbmZ1bmN0aW9uIF91bmlvbihzZXQxLCBzZXQyKSB7XG4gIGxldCBuZXdfbWFwID0gc2V0MTtcblxuICBmb3IgKGxldCB2YWwgb2Ygc2V0Mi5zZXQpIHtcbiAgICBuZXdfbWFwID0gX3B1dChuZXdfbWFwLCB2YWwpO1xuICB9XG5cbiAgcmV0dXJuIFNwZWNpYWxGb3Jtcy5tYXAobmV3X21hcCk7XG59XG5cbmZ1bmN0aW9uIF9kaXNqb2luX19xbWFya19fKHNldDEsIHNldDIpIHtcbiAgZm9yIChsZXQgdmFsIG9mIHNldDEuc2V0KSB7XG4gICAgaWYgKF9tZW1iZXJfX3FtYXJrX18oc2V0MiwgdmFsKSkge1xuICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH1cbiAgfVxuXG4gIHJldHVybiB0cnVlO1xufVxuXG5mdW5jdGlvbiBfbWVtYmVyX19xbWFya19fKHNldCwgdmFsdWUpIHtcbiAgcmV0dXJuIHNldC5zZXQuaW5kZXhPZih2YWx1ZSkgPj0gMDtcbn1cblxuZnVuY3Rpb24gX2VxdWFsX19xbWFya19fKHNldDEsIHNldDIpIHtcbiAgcmV0dXJuIHNldDEuc2V0ID09PSBzZXQyLnNldDtcbn1cblxuZnVuY3Rpb24gX3N1YnNldF9fcW1hcmtfXyhzZXQxLCBzZXQyKSB7XG4gIGZvciAobGV0IHZhbCBvZiBzZXQxLnNldCkge1xuICAgIGlmICghX21lbWJlcl9fcW1hcmtfXyhzZXQyLCB2YWwpKSB7XG4gICAgICByZXR1cm4gZmFsc2U7XG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIHRydWU7XG59XG5cbnZhciBNYXBTZXQgPSB7XG4gIG5ldzogX19uZXdfXyxcbiAgc2l6ZTogX3NpemUsXG4gIHRvX2xpc3Q6IF90b19saXN0LFxuICBkaXNqb2luX19xbWFya19fOiBfZGlzam9pbl9fcW1hcmtfXyxcbiAgZGVsZXRlOiBfX19kZWxldGVfXyxcbiAgc3Vic2V0X19xbWFya19fOiBfc3Vic2V0X19xbWFya19fLFxuICBlcXVhbF9fcW1hcmtfXzogX2VxdWFsX19xbWFya19fLFxuICBtZW1iZXJfX3FtYXJrX186IF9tZW1iZXJfX3FtYXJrX18sXG4gIHB1dDogX3B1dCxcbiAgdW5pb246IF91bmlvbixcbiAgaW50ZXJzZWN0aW9uOiBfaW50ZXJzZWN0aW9uLFxuICBkaWZmZXJlbmNlOiBfZGlmZmVyZW5jZVxufTtcblxuZnVuY3Rpb24gc2l6ZShtYXApIHtcbiAgcmV0dXJuIE1hcFNldC5zaXplKG1hcCk7XG59XG5cbmZ1bmN0aW9uIHRvX2xpc3QobWFwKSB7XG4gIHJldHVybiBNYXBTZXQudG9fbGlzdChtYXApO1xufVxuXG5mdW5jdGlvbiBfX2RlbGV0ZV9fKHNldCwgdGVybSkge1xuICByZXR1cm4gTWFwU2V0LmRlbGV0ZShzZXQsIHRlcm0pO1xufVxuXG5mdW5jdGlvbiBwdXQoc2V0LCB0ZXJtKSB7XG4gIHJldHVybiBNYXBTZXQucHV0KHNldCwgdGVybSk7XG59XG5cbmZ1bmN0aW9uIGRpZmZlcmVuY2Uoc2V0MSwgc2V0Mikge1xuICByZXR1cm4gTWFwU2V0LmRpZmZlcmVuY2Uoc2V0MSwgc2V0Mik7XG59XG5cbmZ1bmN0aW9uIGludGVyc2VjdGlvbihzZXQxLCBzZXQyKSB7XG4gIHJldHVybiBNYXBTZXQuaW50ZXJzZWN0aW9uKHNldDEsIHNldDIpO1xufVxuXG5mdW5jdGlvbiB1bmlvbihzZXQxLCBzZXQyKSB7XG4gIHJldHVybiBNYXBTZXQudW5pb24oc2V0MSwgc2V0Mik7XG59XG5cbmZ1bmN0aW9uIGRpc2pvaW5fX3FtYXJrX18oc2V0MSwgc2V0Mikge1xuICByZXR1cm4gTWFwU2V0LmRpc2pvaW5fX3FtYXJrX18oc2V0MSwgc2V0Mik7XG59XG5cbmZ1bmN0aW9uIG1lbWJlcl9fcW1hcmtfXyhzZXQsIHZhbHVlKSB7XG4gIHJldHVybiBNYXBTZXQubWVtYmVyX19xbWFya19fKHNldDEsIHNldDIpO1xufVxuXG5mdW5jdGlvbiBlcXVhbF9fcW1hcmtfXyhzZXQxLCBzZXQyKSB7XG4gIHJldHVybiBNYXBTZXQuZXF1YWxfX3FtYXJrX18oc2V0MSwgc2V0Mik7XG59XG5cbmZ1bmN0aW9uIHN1YnNldF9fcW1hcmtfXyhzZXQxLCBzZXQyKSB7XG4gIHJldHVybiBNYXBTZXQuc3Vic2V0X19xbWFya19fKHNldDEsIHNldDIpO1xufVxuXG52YXIgX1NldCA9IHtcbiAgc2l6ZSxcbiAgdG9fbGlzdCxcbiAgZGlzam9pbl9fcW1hcmtfXyxcbiAgZGVsZXRlOiBfX2RlbGV0ZV9fLFxuICBzdWJzZXRfX3FtYXJrX18sXG4gIGVxdWFsX19xbWFya19fLFxuICBtZW1iZXJfX3FtYXJrX18sXG4gIHB1dCxcbiAgdW5pb24sXG4gIGludGVyc2VjdGlvbixcbiAgZGlmZmVyZW5jZVxufTtcblxuc2VsZi5wb3N0X29mZmljZSA9IHNlbGYucG9zdF9vZmZpY2UgfHwgbmV3IFBvc3RPZmZpY2UoKTtcblxuZXhwb3J0IHsgX1BhdHRlcm5zIGFzIFBhdHRlcm5zLCBCaXRTdHJpbmcsIEtlcm5lbCwgQXRvbSwgRW51bSwgSW50ZWdlciwgSlMsIExpc3QsIFJhbmdlLCBUdXBsZSwgQWdlbnQsIEtleXdvcmQsIEJhc2UsIF9TdHJpbmcgYXMgU3RyaW5nLCBCaXR3aXNlLCBFbnVtZXJhYmxlLCBDb2xsZWN0YWJsZSwgSW5zcGVjdCwgX01hcCBhcyBNYXAsIF9TZXQgYXMgU2V0LCBNYXBTZXQsIEludGVnZXJUeXBlLCBGbG9hdFR5cGUgfTsiXSwiZmlsZSI6ImVsaXhpci5qcyIsInNvdXJjZVJvb3QiOiIvc291cmNlLyJ9 \ No newline at end of file +export { _Patterns as Patterns, BitString, Kernel, Atom, Enum, Integer, JS, List, Range, Tuple, Agent, Keyword, Base, _String as String, Bitwise, Enumerable, Collectable, Inspect, _Map as Map, _Set as Set, MapSet, IntegerType, FloatType, virtualDom as VirtualDOM }; +//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiIiwic291cmNlcyI6WyJlbGl4aXIuanMiXSwic291cmNlc0NvbnRlbnQiOlsidmFyIFBhdHRlcm5zID0ge1xuICAgIGdldCBkZWZhdWx0ICgpIHsgcmV0dXJuIF9QYXR0ZXJuczsgfVxufTtcblxuY2xhc3MgVHVwbGUge1xuXG4gIGNvbnN0cnVjdG9yKC4uLmFyZ3MpIHtcbiAgICB0aGlzLnZhbHVlcyA9IE9iamVjdC5mcmVlemUoYXJncyk7XG4gIH1cblxuICBnZXQoaW5kZXgpIHtcbiAgICByZXR1cm4gdGhpcy52YWx1ZXNbaW5kZXhdO1xuICB9XG5cbiAgY291bnQoKSB7XG4gICAgcmV0dXJuIHRoaXMudmFsdWVzLmxlbmd0aDtcbiAgfVxuXG4gIFtTeW1ib2wuaXRlcmF0b3JdKCkge1xuICAgIHJldHVybiB0aGlzLnZhbHVlc1tTeW1ib2wuaXRlcmF0b3JdKCk7XG4gIH1cblxuICB0b1N0cmluZygpIHtcbiAgICB2YXIgaSxcbiAgICAgICAgcyA9IFwiXCI7XG4gICAgZm9yIChpID0gMDsgaSA8IHRoaXMudmFsdWVzLmxlbmd0aDsgaSsrKSB7XG4gICAgICBpZiAocyAhPT0gXCJcIikge1xuICAgICAgICBzICs9IFwiLCBcIjtcbiAgICAgIH1cbiAgICAgIHMgKz0gdGhpcy52YWx1ZXNbaV0udG9TdHJpbmcoKTtcbiAgICB9XG5cbiAgICByZXR1cm4gXCJ7XCIgKyBzICsgXCJ9XCI7XG4gIH1cblxuICBzdGF0aWMgdG9fc3RyaW5nKHR1cGxlKSB7XG4gICAgcmV0dXJuIHR1cGxlLnRvU3RyaW5nKCk7XG4gIH1cblxuICBzdGF0aWMgZGVsZXRlX2F0KHR1cGxlLCBpbmRleCkge1xuICAgIGxldCBuZXdfbGlzdCA9IFtdO1xuXG4gICAgZm9yICh2YXIgaSA9IDA7IGkgPCB0dXBsZS5jb3VudCgpOyBpKyspIHtcbiAgICAgIGlmIChpICE9PSBpbmRleCkge1xuICAgICAgICBuZXdfbGlzdC5wdXNoKHR1cGxlLmdldChpKSk7XG4gICAgICB9XG4gICAgfVxuXG4gICAgcmV0dXJuIEtlcm5lbC5TcGVjaWFsRm9ybXMudHVwbGUuYXBwbHkobnVsbCwgbmV3X2xpc3QpO1xuICB9XG5cbiAgc3RhdGljIGR1cGxpY2F0ZShkYXRhLCBzaXplKSB7XG4gICAgbGV0IGFycmF5ID0gW107XG5cbiAgICBmb3IgKHZhciBpID0gc2l6ZSAtIDE7IGkgPj0gMDsgaS0tKSB7XG4gICAgICBhcnJheS5wdXNoKGRhdGEpO1xuICAgIH1cblxuICAgIHJldHVybiBLZXJuZWwuU3BlY2lhbEZvcm1zLnR1cGxlLmFwcGx5KG51bGwsIGFycmF5KTtcbiAgfVxuXG4gIHN0YXRpYyBpbnNlcnRfYXQodHVwbGUsIGluZGV4LCB0ZXJtKSB7XG4gICAgbGV0IG5ld190dXBsZSA9IFtdO1xuXG4gICAgZm9yICh2YXIgaSA9IDA7IGkgPD0gdHVwbGUuY291bnQoKTsgaSsrKSB7XG4gICAgICBpZiAoaSA9PT0gaW5kZXgpIHtcbiAgICAgICAgbmV3X3R1cGxlLnB1c2godGVybSk7XG4gICAgICAgIGkrKztcbiAgICAgICAgbmV3X3R1cGxlLnB1c2godHVwbGUuZ2V0KGkpKTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIG5ld190dXBsZS5wdXNoKHR1cGxlLmdldChpKSk7XG4gICAgICB9XG4gICAgfVxuXG4gICAgcmV0dXJuIEtlcm5lbC5TcGVjaWFsRm9ybXMudHVwbGUuYXBwbHkobnVsbCwgbmV3X3R1cGxlKTtcbiAgfVxuXG4gIHN0YXRpYyBmcm9tX2xpc3QobGlzdCkge1xuICAgIHJldHVybiBLZXJuZWwuU3BlY2lhbEZvcm1zLnR1cGxlLmFwcGx5KG51bGwsIGxpc3QpO1xuICB9XG5cbiAgc3RhdGljIHRvX2xpc3QodHVwbGUpIHtcbiAgICBsZXQgbmV3X2xpc3QgPSBbXTtcblxuICAgIGZvciAodmFyIGkgPSAwOyBpIDwgdHVwbGUuY291bnQoKTsgaSsrKSB7XG4gICAgICBuZXdfbGlzdC5wdXNoKHR1cGxlLmdldChpKSk7XG4gICAgfVxuXG4gICAgcmV0dXJuIEtlcm5lbC5TcGVjaWFsRm9ybXMubGlzdCguLi5uZXdfbGlzdCk7XG4gIH1cbn1cblxuLyogQGZsb3cgKi9cblxuY2xhc3MgVmFyaWFibGUge1xuXG4gIGNvbnN0cnVjdG9yKG5hbWUgPSBudWxsKSB7XG4gICAgdGhpcy5uYW1lID0gbmFtZTtcbiAgfVxufVxuXG5jbGFzcyBXaWxkY2FyZCB7XG4gIGNvbnN0cnVjdG9yKCkge31cbn1cblxuY2xhc3MgU3RhcnRzV2l0aCB7XG5cbiAgY29uc3RydWN0b3IocHJlZml4KSB7XG4gICAgdGhpcy5wcmVmaXggPSBwcmVmaXg7XG4gIH1cbn1cblxuY2xhc3MgQ2FwdHVyZSB7XG5cbiAgY29uc3RydWN0b3IodmFsdWUpIHtcbiAgICB0aGlzLnZhbHVlID0gdmFsdWU7XG4gIH1cbn1cblxuY2xhc3MgSGVhZFRhaWwge1xuICBjb25zdHJ1Y3RvcigpIHt9XG59XG5cbmNsYXNzIFR5cGUge1xuXG4gIGNvbnN0cnVjdG9yKHR5cGUsIG9ialBhdHRlcm4gPSB7fSkge1xuICAgIHRoaXMudHlwZSA9IHR5cGU7XG4gICAgdGhpcy5vYmpQYXR0ZXJuID0gb2JqUGF0dGVybjtcbiAgfVxufVxuXG5jbGFzcyBCb3VuZCB7XG5cbiAgY29uc3RydWN0b3IodmFsdWUpIHtcbiAgICB0aGlzLnZhbHVlID0gdmFsdWU7XG4gIH1cbn1cblxuZnVuY3Rpb24gdmFyaWFibGUobmFtZSA9IG51bGwpIHtcbiAgcmV0dXJuIG5ldyBWYXJpYWJsZShuYW1lKTtcbn1cblxuZnVuY3Rpb24gd2lsZGNhcmQoKSB7XG4gIHJldHVybiBuZXcgV2lsZGNhcmQoKTtcbn1cblxuZnVuY3Rpb24gc3RhcnRzV2l0aChwcmVmaXgpIHtcbiAgcmV0dXJuIG5ldyBTdGFydHNXaXRoKHByZWZpeCk7XG59XG5cbmZ1bmN0aW9uIGNhcHR1cmUodmFsdWUpIHtcbiAgcmV0dXJuIG5ldyBDYXB0dXJlKHZhbHVlKTtcbn1cblxuZnVuY3Rpb24gaGVhZFRhaWwoKSB7XG4gIHJldHVybiBuZXcgSGVhZFRhaWwoKTtcbn1cblxuZnVuY3Rpb24gdHlwZSh0eXBlLCBvYmpQYXR0ZXJuID0ge30pIHtcbiAgcmV0dXJuIG5ldyBUeXBlKHR5cGUsIG9ialBhdHRlcm4pO1xufVxuXG5mdW5jdGlvbiBib3VuZCh2YWx1ZSkge1xuICByZXR1cm4gbmV3IEJvdW5kKHZhbHVlKTtcbn1cblxuZnVuY3Rpb24gX2lzX251bWJlcih2YWx1ZSkge1xuICByZXR1cm4gdHlwZW9mIHZhbHVlID09PSAnbnVtYmVyJztcbn1cblxuZnVuY3Rpb24gaXNfc3RyaW5nKHZhbHVlKSB7XG4gIHJldHVybiB0eXBlb2YgdmFsdWUgPT09ICdzdHJpbmcnO1xufVxuXG5mdW5jdGlvbiBfaXNfdHVwbGUodmFsdWUpIHtcbiAgcmV0dXJuIHZhbHVlIGluc3RhbmNlb2YgVHVwbGU7XG59XG5cbmZ1bmN0aW9uIF9pc19ib29sZWFuKHZhbHVlKSB7XG4gIHJldHVybiB0eXBlb2YgdmFsdWUgPT09ICdib29sZWFuJztcbn1cblxuZnVuY3Rpb24gaXNfc3ltYm9sKHZhbHVlKSB7XG4gIHJldHVybiB0eXBlb2YgdmFsdWUgPT09ICdzeW1ib2wnO1xufVxuXG5mdW5jdGlvbiBpc19udWxsKHZhbHVlKSB7XG4gIHJldHVybiB2YWx1ZSA9PT0gbnVsbDtcbn1cblxuZnVuY3Rpb24gaXNfdW5kZWZpbmVkKHZhbHVlKSB7XG4gIHJldHVybiB0eXBlb2YgdmFsdWUgPT09ICd1bmRlZmluZWQnO1xufVxuXG5mdW5jdGlvbiBfaXNfZnVuY3Rpb24odmFsdWUpIHtcbiAgcmV0dXJuIE9iamVjdC5wcm90b3R5cGUudG9TdHJpbmcuY2FsbCh2YWx1ZSkgPT0gJ1tvYmplY3QgRnVuY3Rpb25dJztcbn1cblxuZnVuY3Rpb24gaXNfdmFyaWFibGUodmFsdWUpIHtcbiAgcmV0dXJuIHZhbHVlIGluc3RhbmNlb2YgVmFyaWFibGU7XG59XG5cbmZ1bmN0aW9uIGlzX3dpbGRjYXJkKHZhbHVlKSB7XG4gIHJldHVybiB2YWx1ZSBpbnN0YW5jZW9mIFdpbGRjYXJkO1xufVxuXG5mdW5jdGlvbiBpc19oZWFkVGFpbCh2YWx1ZSkge1xuICByZXR1cm4gdmFsdWUgaW5zdGFuY2VvZiBIZWFkVGFpbDtcbn1cblxuZnVuY3Rpb24gaXNfY2FwdHVyZSh2YWx1ZSkge1xuICByZXR1cm4gdmFsdWUgaW5zdGFuY2VvZiBDYXB0dXJlO1xufVxuXG5mdW5jdGlvbiBpc190eXBlKHZhbHVlKSB7XG4gIHJldHVybiB2YWx1ZSBpbnN0YW5jZW9mIFR5cGU7XG59XG5cbmZ1bmN0aW9uIGlzX3N0YXJ0c1dpdGgodmFsdWUpIHtcbiAgcmV0dXJuIHZhbHVlIGluc3RhbmNlb2YgU3RhcnRzV2l0aDtcbn1cblxuZnVuY3Rpb24gaXNfYm91bmQodmFsdWUpIHtcbiAgcmV0dXJuIHZhbHVlIGluc3RhbmNlb2YgQm91bmQ7XG59XG5cbmZ1bmN0aW9uIGlzX29iamVjdCh2YWx1ZSkge1xuICByZXR1cm4gdHlwZW9mIHZhbHVlID09PSAnb2JqZWN0Jztcbn1cblxuZnVuY3Rpb24gaXNfYXJyYXkodmFsdWUpIHtcbiAgcmV0dXJuIEFycmF5LmlzQXJyYXkodmFsdWUpO1xufVxuXG52YXIgQ2hlY2tzID0ge1xuICBpc19udW1iZXI6IF9pc19udW1iZXIsXG4gIGlzX3N0cmluZyxcbiAgaXNfYm9vbGVhbjogX2lzX2Jvb2xlYW4sXG4gIGlzX3N5bWJvbCxcbiAgaXNfbnVsbCxcbiAgaXNfdW5kZWZpbmVkLFxuICBpc19mdW5jdGlvbjogX2lzX2Z1bmN0aW9uLFxuICBpc192YXJpYWJsZSxcbiAgaXNfd2lsZGNhcmQsXG4gIGlzX2hlYWRUYWlsLFxuICBpc19jYXB0dXJlLFxuICBpc190eXBlLFxuICBpc19zdGFydHNXaXRoLFxuICBpc19ib3VuZCxcbiAgaXNfb2JqZWN0LFxuICBpc19hcnJheSxcbiAgaXNfdHVwbGU6IF9pc190dXBsZVxufTtcblxuZnVuY3Rpb24gcmVzb2x2ZVR1cGxlKHBhdHRlcm4pIHtcbiAgbGV0IG1hdGNoZXMgPSBbXTtcblxuICBmb3IgKGxldCBlbGVtIG9mIHBhdHRlcm4pIHtcbiAgICBtYXRjaGVzLnB1c2goYnVpbGRNYXRjaChlbGVtKSk7XG4gIH1cblxuICByZXR1cm4gZnVuY3Rpb24gKHZhbHVlLCBhcmdzKSB7XG4gICAgaWYgKCFDaGVja3MuaXNfdHVwbGUodmFsdWUpIHx8IHZhbHVlLmNvdW50KCkgIT0gcGF0dGVybi5jb3VudCgpKSB7XG4gICAgICByZXR1cm4gZmFsc2U7XG4gICAgfVxuXG4gICAgcmV0dXJuIHZhbHVlLnZhbHVlcy5ldmVyeShmdW5jdGlvbiAodiwgaSkge1xuICAgICAgcmV0dXJuIG1hdGNoZXNbaV0odmFsdWUuZ2V0KGkpLCBhcmdzKTtcbiAgICB9KTtcbiAgfTtcbn1cblxuZnVuY3Rpb24gcmVzb2x2ZVN5bWJvbChwYXR0ZXJuKSB7XG4gIHJldHVybiBmdW5jdGlvbiAodmFsdWUpIHtcbiAgICByZXR1cm4gQ2hlY2tzLmlzX3N5bWJvbCh2YWx1ZSkgJiYgdmFsdWUgPT09IHBhdHRlcm47XG4gIH07XG59XG5cbmZ1bmN0aW9uIHJlc29sdmVTdHJpbmcocGF0dGVybikge1xuICByZXR1cm4gZnVuY3Rpb24gKHZhbHVlKSB7XG4gICAgcmV0dXJuIENoZWNrcy5pc19zdHJpbmcodmFsdWUpICYmIHZhbHVlID09PSBwYXR0ZXJuO1xuICB9O1xufVxuXG5mdW5jdGlvbiByZXNvbHZlTnVtYmVyKHBhdHRlcm4pIHtcbiAgcmV0dXJuIGZ1bmN0aW9uICh2YWx1ZSkge1xuICAgIHJldHVybiBDaGVja3MuaXNfbnVtYmVyKHZhbHVlKSAmJiB2YWx1ZSA9PT0gcGF0dGVybjtcbiAgfTtcbn1cblxuZnVuY3Rpb24gcmVzb2x2ZUJvb2xlYW4ocGF0dGVybikge1xuICByZXR1cm4gZnVuY3Rpb24gKHZhbHVlKSB7XG4gICAgcmV0dXJuIENoZWNrcy5pc19ib29sZWFuKHZhbHVlKSAmJiB2YWx1ZSA9PT0gcGF0dGVybjtcbiAgfTtcbn1cblxuZnVuY3Rpb24gcmVzb2x2ZUZ1bmN0aW9uKHBhdHRlcm4pIHtcbiAgcmV0dXJuIGZ1bmN0aW9uICh2YWx1ZSkge1xuICAgIHJldHVybiBDaGVja3MuaXNfZnVuY3Rpb24odmFsdWUpICYmIHZhbHVlID09PSBwYXR0ZXJuO1xuICB9O1xufVxuXG5mdW5jdGlvbiByZXNvbHZlTnVsbChwYXR0ZXJuKSB7XG4gIHJldHVybiBmdW5jdGlvbiAodmFsdWUpIHtcbiAgICByZXR1cm4gQ2hlY2tzLmlzX251bGwodmFsdWUpO1xuICB9O1xufVxuXG5mdW5jdGlvbiByZXNvbHZlQm91bmQocGF0dGVybikge1xuICByZXR1cm4gZnVuY3Rpb24gKHZhbHVlLCBhcmdzKSB7XG4gICAgaWYgKHR5cGVvZiB2YWx1ZSA9PT0gdHlwZW9mIHBhdHRlcm4udmFsdWUgJiYgdmFsdWUgPT09IHBhdHRlcm4udmFsdWUpIHtcbiAgICAgIGFyZ3MucHVzaCh2YWx1ZSk7XG4gICAgICByZXR1cm4gdHJ1ZTtcbiAgICB9XG5cbiAgICByZXR1cm4gZmFsc2U7XG4gIH07XG59XG5cbmZ1bmN0aW9uIHJlc29sdmVXaWxkY2FyZCgpIHtcbiAgcmV0dXJuIGZ1bmN0aW9uICgpIHtcbiAgICByZXR1cm4gdHJ1ZTtcbiAgfTtcbn1cblxuZnVuY3Rpb24gcmVzb2x2ZVZhcmlhYmxlKCkge1xuICByZXR1cm4gZnVuY3Rpb24gKHZhbHVlLCBhcmdzKSB7XG4gICAgYXJncy5wdXNoKHZhbHVlKTtcbiAgICByZXR1cm4gdHJ1ZTtcbiAgfTtcbn1cblxuZnVuY3Rpb24gcmVzb2x2ZUhlYWRUYWlsKCkge1xuICByZXR1cm4gZnVuY3Rpb24gKHZhbHVlLCBhcmdzKSB7XG4gICAgaWYgKCFDaGVja3MuaXNfYXJyYXkodmFsdWUpIHx8IHZhbHVlLmxlbmd0aCA8IDIpIHtcbiAgICAgIHJldHVybiBmYWxzZTtcbiAgICB9XG5cbiAgICBjb25zdCBoZWFkID0gdmFsdWVbMF07XG4gICAgY29uc3QgdGFpbCA9IHZhbHVlLnNsaWNlKDEpO1xuXG4gICAgYXJncy5wdXNoKGhlYWQpO1xuICAgIGFyZ3MucHVzaCh0YWlsKTtcblxuICAgIHJldHVybiB0cnVlO1xuICB9O1xufVxuXG5mdW5jdGlvbiByZXNvbHZlQ2FwdHVyZShwYXR0ZXJuKSB7XG4gIGNvbnN0IG1hdGNoZXMgPSBidWlsZE1hdGNoKHBhdHRlcm4udmFsdWUpO1xuXG4gIHJldHVybiBmdW5jdGlvbiAodmFsdWUsIGFyZ3MpIHtcbiAgICBpZiAobWF0Y2hlcyh2YWx1ZSwgYXJncykpIHtcbiAgICAgIGFyZ3MucHVzaCh2YWx1ZSk7XG4gICAgICByZXR1cm4gdHJ1ZTtcbiAgICB9XG5cbiAgICByZXR1cm4gZmFsc2U7XG4gIH07XG59XG5cbmZ1bmN0aW9uIHJlc29sdmVTdGFydHNXaXRoKHBhdHRlcm4pIHtcbiAgY29uc3QgcHJlZml4ID0gcGF0dGVybi5wcmVmaXg7XG5cbiAgcmV0dXJuIGZ1bmN0aW9uICh2YWx1ZSwgYXJncykge1xuICAgIGlmIChDaGVja3MuaXNfc3RyaW5nKHZhbHVlKSAmJiB2YWx1ZS5zdGFydHNXaXRoKHByZWZpeCkpIHtcbiAgICAgIGFyZ3MucHVzaCh2YWx1ZS5zdWJzdHJpbmcocHJlZml4Lmxlbmd0aCkpO1xuICAgICAgcmV0dXJuIHRydWU7XG4gICAgfVxuXG4gICAgcmV0dXJuIGZhbHNlO1xuICB9O1xufVxuXG5mdW5jdGlvbiByZXNvbHZlVHlwZShwYXR0ZXJuKSB7XG4gIHJldHVybiBmdW5jdGlvbiAodmFsdWUsIGFyZ3MpIHtcbiAgICBpZiAodmFsdWUgaW5zdGFuY2VvZiBwYXR0ZXJuLnR5cGUpIHtcbiAgICAgIGNvbnN0IG1hdGNoZXMgPSBidWlsZE1hdGNoKHBhdHRlcm4ub2JqUGF0dGVybik7XG4gICAgICByZXR1cm4gbWF0Y2hlcyh2YWx1ZSwgYXJncykgJiYgYXJncy5wdXNoKHZhbHVlKSA+IDA7XG4gICAgfVxuXG4gICAgcmV0dXJuIGZhbHNlO1xuICB9O1xufVxuXG5mdW5jdGlvbiByZXNvbHZlQXJyYXkocGF0dGVybikge1xuICBjb25zdCBtYXRjaGVzID0gcGF0dGVybi5tYXAoeCA9PiBidWlsZE1hdGNoKHgpKTtcblxuICByZXR1cm4gZnVuY3Rpb24gKHZhbHVlLCBhcmdzKSB7XG4gICAgaWYgKCFDaGVja3MuaXNfYXJyYXkodmFsdWUpIHx8IHZhbHVlLmxlbmd0aCAhPSBwYXR0ZXJuLmxlbmd0aCkge1xuICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH1cblxuICAgIHJldHVybiB2YWx1ZS5ldmVyeShmdW5jdGlvbiAodiwgaSkge1xuICAgICAgcmV0dXJuIG1hdGNoZXNbaV0odmFsdWVbaV0sIGFyZ3MpO1xuICAgIH0pO1xuICB9O1xufVxuXG5mdW5jdGlvbiByZXNvbHZlT2JqZWN0KHBhdHRlcm4pIHtcbiAgbGV0IG1hdGNoZXMgPSB7fTtcblxuICBmb3IgKGxldCBrZXkgb2YgT2JqZWN0LmtleXMocGF0dGVybikpIHtcbiAgICBtYXRjaGVzW2tleV0gPSBidWlsZE1hdGNoKHBhdHRlcm5ba2V5XSk7XG4gIH1cblxuICByZXR1cm4gZnVuY3Rpb24gKHZhbHVlLCBhcmdzKSB7XG4gICAgaWYgKCFDaGVja3MuaXNfb2JqZWN0KHZhbHVlKSB8fCBwYXR0ZXJuLmxlbmd0aCA+IHZhbHVlLmxlbmd0aCkge1xuICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH1cblxuICAgIGZvciAobGV0IGtleSBvZiBPYmplY3Qua2V5cyhwYXR0ZXJuKSkge1xuICAgICAgaWYgKCEoa2V5IGluIHZhbHVlKSB8fCAhbWF0Y2hlc1trZXldKHZhbHVlW2tleV0sIGFyZ3MpKSB7XG4gICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICByZXR1cm4gdHJ1ZTtcbiAgfTtcbn1cblxuZnVuY3Rpb24gcmVzb2x2ZU5vTWF0Y2goKSB7XG4gIHJldHVybiBmdW5jdGlvbiAoKSB7XG4gICAgcmV0dXJuIGZhbHNlO1xuICB9O1xufVxuXG52YXIgUmVzb2x2ZXJzID0ge1xuICByZXNvbHZlQm91bmQsXG4gIHJlc29sdmVXaWxkY2FyZCxcbiAgcmVzb2x2ZVZhcmlhYmxlLFxuICByZXNvbHZlSGVhZFRhaWwsXG4gIHJlc29sdmVDYXB0dXJlLFxuICByZXNvbHZlU3RhcnRzV2l0aCxcbiAgcmVzb2x2ZVR5cGUsXG4gIHJlc29sdmVBcnJheSxcbiAgcmVzb2x2ZU9iamVjdCxcbiAgcmVzb2x2ZU5vTWF0Y2gsXG4gIHJlc29sdmVTeW1ib2wsXG4gIHJlc29sdmVTdHJpbmcsXG4gIHJlc29sdmVOdW1iZXIsXG4gIHJlc29sdmVCb29sZWFuLFxuICByZXNvbHZlRnVuY3Rpb24sXG4gIHJlc29sdmVOdWxsLFxuICByZXNvbHZlVHVwbGVcbn07XG5cbmZ1bmN0aW9uIGJ1aWxkTWF0Y2gocGF0dGVybikge1xuXG4gIGlmIChDaGVja3MuaXNfdHVwbGUocGF0dGVybikpIHtcbiAgICByZXR1cm4gUmVzb2x2ZXJzLnJlc29sdmVUdXBsZShwYXR0ZXJuKTtcbiAgfVxuXG4gIGlmIChDaGVja3MuaXNfdmFyaWFibGUocGF0dGVybikpIHtcbiAgICByZXR1cm4gUmVzb2x2ZXJzLnJlc29sdmVWYXJpYWJsZShwYXR0ZXJuKTtcbiAgfVxuXG4gIGlmIChDaGVja3MuaXNfd2lsZGNhcmQocGF0dGVybikpIHtcbiAgICByZXR1cm4gUmVzb2x2ZXJzLnJlc29sdmVXaWxkY2FyZChwYXR0ZXJuKTtcbiAgfVxuXG4gIGlmIChDaGVja3MuaXNfdW5kZWZpbmVkKHBhdHRlcm4pKSB7XG4gICAgcmV0dXJuIFJlc29sdmVycy5yZXNvbHZlV2lsZGNhcmQocGF0dGVybik7XG4gIH1cblxuICBpZiAoQ2hlY2tzLmlzX2hlYWRUYWlsKHBhdHRlcm4pKSB7XG4gICAgcmV0dXJuIFJlc29sdmVycy5yZXNvbHZlSGVhZFRhaWwocGF0dGVybik7XG4gIH1cblxuICBpZiAoQ2hlY2tzLmlzX3N0YXJ0c1dpdGgocGF0dGVybikpIHtcbiAgICByZXR1cm4gUmVzb2x2ZXJzLnJlc29sdmVTdGFydHNXaXRoKHBhdHRlcm4pO1xuICB9XG5cbiAgaWYgKENoZWNrcy5pc19jYXB0dXJlKHBhdHRlcm4pKSB7XG4gICAgcmV0dXJuIFJlc29sdmVycy5yZXNvbHZlQ2FwdHVyZShwYXR0ZXJuKTtcbiAgfVxuXG4gIGlmIChDaGVja3MuaXNfYm91bmQocGF0dGVybikpIHtcbiAgICByZXR1cm4gUmVzb2x2ZXJzLnJlc29sdmVCb3VuZChwYXR0ZXJuKTtcbiAgfVxuXG4gIGlmIChDaGVja3MuaXNfdHlwZShwYXR0ZXJuKSkge1xuICAgIHJldHVybiBSZXNvbHZlcnMucmVzb2x2ZVR5cGUocGF0dGVybik7XG4gIH1cblxuICBpZiAoQ2hlY2tzLmlzX2FycmF5KHBhdHRlcm4pKSB7XG4gICAgcmV0dXJuIFJlc29sdmVycy5yZXNvbHZlQXJyYXkocGF0dGVybik7XG4gIH1cblxuICBpZiAoQ2hlY2tzLmlzX251bWJlcihwYXR0ZXJuKSkge1xuICAgIHJldHVybiBSZXNvbHZlcnMucmVzb2x2ZU51bWJlcihwYXR0ZXJuKTtcbiAgfVxuXG4gIGlmIChDaGVja3MuaXNfc3RyaW5nKHBhdHRlcm4pKSB7XG4gICAgcmV0dXJuIFJlc29sdmVycy5yZXNvbHZlU3RyaW5nKHBhdHRlcm4pO1xuICB9XG5cbiAgaWYgKENoZWNrcy5pc19ib29sZWFuKHBhdHRlcm4pKSB7XG4gICAgcmV0dXJuIFJlc29sdmVycy5yZXNvbHZlQm9vbGVhbihwYXR0ZXJuKTtcbiAgfVxuXG4gIGlmIChDaGVja3MuaXNfc3ltYm9sKHBhdHRlcm4pKSB7XG4gICAgcmV0dXJuIFJlc29sdmVycy5yZXNvbHZlU3ltYm9sKHBhdHRlcm4pO1xuICB9XG5cbiAgaWYgKENoZWNrcy5pc19udWxsKHBhdHRlcm4pKSB7XG4gICAgcmV0dXJuIFJlc29sdmVycy5yZXNvbHZlTnVsbChwYXR0ZXJuKTtcbiAgfVxuXG4gIGlmIChDaGVja3MuaXNfb2JqZWN0KHBhdHRlcm4pKSB7XG4gICAgcmV0dXJuIFJlc29sdmVycy5yZXNvbHZlT2JqZWN0KHBhdHRlcm4pO1xuICB9XG5cbiAgcmV0dXJuIFJlc29sdmVycy5yZXNvbHZlTm9NYXRjaCgpO1xufVxuXG5jbGFzcyBNYXRjaEVycm9yIGV4dGVuZHMgRXJyb3Ige1xuICBjb25zdHJ1Y3RvcihhcmcpIHtcbiAgICBzdXBlcigpO1xuXG4gICAgaWYgKHR5cGVvZiBhcmcgPT09ICdzeW1ib2wnKSB7XG4gICAgICB0aGlzLm1lc3NhZ2UgPSAnTm8gbWF0Y2ggZm9yOiAnICsgYXJnLnRvU3RyaW5nKCk7XG4gICAgfSBlbHNlIGlmIChBcnJheS5pc0FycmF5KGFyZykpIHtcbiAgICAgIGxldCBtYXBwZWRWYWx1ZXMgPSBhcmcubWFwKHggPT4geC50b1N0cmluZygpKTtcbiAgICAgIHRoaXMubWVzc2FnZSA9ICdObyBtYXRjaCBmb3I6ICcgKyBtYXBwZWRWYWx1ZXM7XG4gICAgfSBlbHNlIHtcbiAgICAgIHRoaXMubWVzc2FnZSA9ICdObyBtYXRjaCBmb3I6ICcgKyBhcmc7XG4gICAgfVxuXG4gICAgdGhpcy5zdGFjayA9IG5ldyBFcnJvcigpLnN0YWNrO1xuICAgIHRoaXMubmFtZSA9IHRoaXMuY29uc3RydWN0b3IubmFtZTtcbiAgfVxufVxuXG5jbGFzcyBDYXNlIHtcblxuICBjb25zdHJ1Y3RvcihwYXR0ZXJuLCBmbiwgZ3VhcmQgPSAoKSA9PiB0cnVlKSB7XG4gICAgdGhpcy5wYXR0ZXJuID0gYnVpbGRNYXRjaChwYXR0ZXJuKTtcbiAgICB0aGlzLmZuID0gZm47XG4gICAgdGhpcy5ndWFyZCA9IGd1YXJkO1xuICB9XG59XG5cbmZ1bmN0aW9uIG1ha2VfY2FzZShwYXR0ZXJuLCBmbiwgZ3VhcmQgPSAoKSA9PiB0cnVlKSB7XG4gIHJldHVybiBuZXcgQ2FzZShwYXR0ZXJuLCBmbiwgZ3VhcmQpO1xufVxuXG5mdW5jdGlvbiBkZWZtYXRjaCguLi5jYXNlcykge1xuICByZXR1cm4gZnVuY3Rpb24gKC4uLmFyZ3MpIHtcbiAgICBmb3IgKGxldCBwcm9jZXNzZWRDYXNlIG9mIGNhc2VzKSB7XG4gICAgICBsZXQgcmVzdWx0ID0gW107XG4gICAgICBpZiAocHJvY2Vzc2VkQ2FzZS5wYXR0ZXJuKGFyZ3MsIHJlc3VsdCkgJiYgcHJvY2Vzc2VkQ2FzZS5ndWFyZC5hcHBseSh0aGlzLCByZXN1bHQpKSB7XG4gICAgICAgIHJldHVybiBwcm9jZXNzZWRDYXNlLmZuLmFwcGx5KHRoaXMsIHJlc3VsdCk7XG4gICAgICB9XG4gICAgfVxuXG4gICAgdGhyb3cgbmV3IE1hdGNoRXJyb3IoYXJncyk7XG4gIH07XG59XG5cbmZ1bmN0aW9uIG1hdGNoKHBhdHRlcm4sIGV4cHIsIGd1YXJkID0gKCkgPT4gdHJ1ZSkge1xuICBsZXQgcmVzdWx0ID0gW107XG4gIGxldCBwcm9jZXNzZWRQYXR0ZXJuID0gYnVpbGRNYXRjaChwYXR0ZXJuKTtcbiAgaWYgKHByb2Nlc3NlZFBhdHRlcm4oZXhwciwgcmVzdWx0KSAmJiBndWFyZC5hcHBseSh0aGlzLCByZXN1bHQpKSB7XG4gICAgcmV0dXJuIHJlc3VsdDtcbiAgfSBlbHNlIHtcbiAgICB0aHJvdyBuZXcgTWF0Y2hFcnJvcihleHByKTtcbiAgfVxufVxuXG5mdW5jdGlvbiBtYXRjaF9ub190aHJvdyhwYXR0ZXJuLCBleHByLCBndWFyZCA9ICgpID0+IHRydWUpIHtcbiAgdHJ5IHtcbiAgICByZXR1cm4gbWF0Y2gocGF0dGVybiwgZXhwciwgZ3VhcmQpO1xuICB9IGNhdGNoIChlKSB7XG4gICAgaWYgKGUgaW5zdGFuY2VvZiBNYXRjaEVycm9yKSB7XG4gICAgICByZXR1cm4gbnVsbDtcbiAgICB9XG5cbiAgICB0aHJvdyBlO1xuICB9XG59XG5cbmZ1bmN0aW9uIHBhdHRlcm5NYXAoY29sbGVjdGlvbiwgcGF0dGVybiwgZnVuLCBndWFyZCA9ICgpID0+IHRydWUpIHtcbiAgbGV0IHJldCA9IFtdO1xuXG4gIGZvciAobGV0IGVsZW0gb2YgY29sbGVjdGlvbikge1xuICAgIHRyeSB7XG4gICAgICBsZXQgcmVzdWx0ID0gZnVuLmFwcGx5KHRoaXMsIG1hdGNoKHBhdHRlcm4sIGVsZW0sIGd1YXJkKSk7XG4gICAgICByZXQgPSByZXQuY29uY2F0KHJlc3VsdCk7XG4gICAgfSBjYXRjaCAoZSkge1xuICAgICAgaWYgKCEoZSBpbnN0YW5jZW9mIE1hdGNoRXJyb3IpKSB7XG4gICAgICAgIHRocm93IGU7XG4gICAgICB9XG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIHJldDtcbn1cblxudmFyIF9QYXR0ZXJucyA9IHtcbiAgZGVmbWF0Y2gsIG1hdGNoLCBNYXRjaEVycm9yLCBtYXRjaF9ub190aHJvdywgcGF0dGVybk1hcCxcbiAgdmFyaWFibGUsIHdpbGRjYXJkLCBzdGFydHNXaXRoLFxuICBjYXB0dXJlLCBoZWFkVGFpbCwgdHlwZSwgYm91bmQsIENhc2UsIG1ha2VfY2FzZVxufTtcblxuY2xhc3MgQml0U3RyaW5nIHtcbiAgY29uc3RydWN0b3IoLi4uYXJncykge1xuICAgIHRoaXMucmF3X3ZhbHVlID0gZnVuY3Rpb24gKCkge1xuICAgICAgcmV0dXJuIE9iamVjdC5mcmVlemUoYXJncyk7XG4gICAgfTtcblxuICAgIHRoaXMudmFsdWUgPSBPYmplY3QuZnJlZXplKHRoaXMucHJvY2VzcyhhcmdzKSk7XG4gIH1cblxuICBnZXQoaW5kZXgpIHtcbiAgICByZXR1cm4gdGhpcy52YWx1ZVtpbmRleF07XG4gIH1cblxuICBjb3VudCgpIHtcbiAgICByZXR1cm4gdGhpcy52YWx1ZS5sZW5ndGg7XG4gIH1cblxuICBbU3ltYm9sLml0ZXJhdG9yXSgpIHtcbiAgICByZXR1cm4gdGhpcy52YWx1ZVtTeW1ib2wuaXRlcmF0b3JdKCk7XG4gIH1cblxuICB0b1N0cmluZygpIHtcbiAgICB2YXIgaSxcbiAgICAgICAgcyA9IFwiXCI7XG4gICAgZm9yIChpID0gMDsgaSA8IHRoaXMuY291bnQoKTsgaSsrKSB7XG4gICAgICBpZiAocyAhPT0gXCJcIikge1xuICAgICAgICBzICs9IFwiLCBcIjtcbiAgICAgIH1cbiAgICAgIHMgKz0gdGhpc1tpXS50b1N0cmluZygpO1xuICAgIH1cblxuICAgIHJldHVybiBcIjw8XCIgKyBzICsgXCI+PlwiO1xuICB9XG5cbiAgcHJvY2VzcygpIHtcbiAgICBsZXQgcHJvY2Vzc2VkX3ZhbHVlcyA9IFtdO1xuXG4gICAgdmFyIGk7XG4gICAgZm9yIChpID0gMDsgaSA8IHRoaXMucmF3X3ZhbHVlKCkubGVuZ3RoOyBpKyspIHtcbiAgICAgIGxldCBwcm9jZXNzZWRfdmFsdWUgPSB0aGlzW1wicHJvY2Vzc19cIiArIHRoaXMucmF3X3ZhbHVlKClbaV0udHlwZV0odGhpcy5yYXdfdmFsdWUoKVtpXSk7XG5cbiAgICAgIGZvciAobGV0IGF0dHIgb2YgdGhpcy5yYXdfdmFsdWUoKVtpXS5hdHRyaWJ1dGVzKSB7XG4gICAgICAgIHByb2Nlc3NlZF92YWx1ZSA9IHRoaXNbXCJwcm9jZXNzX1wiICsgYXR0cl0ocHJvY2Vzc2VkX3ZhbHVlKTtcbiAgICAgIH1cblxuICAgICAgcHJvY2Vzc2VkX3ZhbHVlcyA9IHByb2Nlc3NlZF92YWx1ZXMuY29uY2F0KHByb2Nlc3NlZF92YWx1ZSk7XG4gICAgfVxuXG4gICAgcmV0dXJuIHByb2Nlc3NlZF92YWx1ZXM7XG4gIH1cblxuICBwcm9jZXNzX2ludGVnZXIodmFsdWUpIHtcbiAgICByZXR1cm4gdmFsdWUudmFsdWU7XG4gIH1cblxuICBwcm9jZXNzX2Zsb2F0KHZhbHVlKSB7XG4gICAgaWYgKHZhbHVlLnNpemUgPT09IDY0KSB7XG4gICAgICByZXR1cm4gQml0U3RyaW5nLmZsb2F0NjRUb0J5dGVzKHZhbHVlLnZhbHVlKTtcbiAgICB9IGVsc2UgaWYgKHZhbHVlLnNpemUgPT09IDMyKSB7XG4gICAgICByZXR1cm4gQml0U3RyaW5nLmZsb2F0MzJUb0J5dGVzKHZhbHVlLnZhbHVlKTtcbiAgICB9XG5cbiAgICB0aHJvdyBuZXcgRXJyb3IoXCJJbnZhbGlkIHNpemUgZm9yIGZsb2F0XCIpO1xuICB9XG5cbiAgcHJvY2Vzc19iaXRzdHJpbmcodmFsdWUpIHtcbiAgICByZXR1cm4gdmFsdWUudmFsdWUudmFsdWU7XG4gIH1cblxuICBwcm9jZXNzX2JpbmFyeSh2YWx1ZSkge1xuICAgIHJldHVybiBCaXRTdHJpbmcudG9VVEY4QXJyYXkodmFsdWUudmFsdWUpO1xuICB9XG5cbiAgcHJvY2Vzc191dGY4KHZhbHVlKSB7XG4gICAgcmV0dXJuIEJpdFN0cmluZy50b1VURjhBcnJheSh2YWx1ZS52YWx1ZSk7XG4gIH1cblxuICBwcm9jZXNzX3V0ZjE2KHZhbHVlKSB7XG4gICAgcmV0dXJuIEJpdFN0cmluZy50b1VURjE2QXJyYXkodmFsdWUudmFsdWUpO1xuICB9XG5cbiAgcHJvY2Vzc191dGYzMih2YWx1ZSkge1xuICAgIHJldHVybiBCaXRTdHJpbmcudG9VVEYzMkFycmF5KHZhbHVlLnZhbHVlKTtcbiAgfVxuXG4gIHByb2Nlc3Nfc2lnbmVkKHZhbHVlKSB7XG4gICAgcmV0dXJuIG5ldyBVaW50OEFycmF5KFt2YWx1ZV0pWzBdO1xuICB9XG5cbiAgcHJvY2Vzc191bnNpZ25lZCh2YWx1ZSkge1xuICAgIHJldHVybiB2YWx1ZTtcbiAgfVxuXG4gIHByb2Nlc3NfbmF0aXZlKHZhbHVlKSB7XG4gICAgcmV0dXJuIHZhbHVlO1xuICB9XG5cbiAgcHJvY2Vzc19iaWcodmFsdWUpIHtcbiAgICByZXR1cm4gdmFsdWU7XG4gIH1cblxuICBwcm9jZXNzX2xpdHRsZSh2YWx1ZSkge1xuICAgIHJldHVybiB2YWx1ZS5yZXZlcnNlKCk7XG4gIH1cblxuICBwcm9jZXNzX3NpemUodmFsdWUpIHtcbiAgICByZXR1cm4gdmFsdWU7XG4gIH1cblxuICBwcm9jZXNzX3VuaXQodmFsdWUpIHtcbiAgICByZXR1cm4gdmFsdWU7XG4gIH1cblxuICBzdGF0aWMgaW50ZWdlcih2YWx1ZSkge1xuICAgIHJldHVybiBCaXRTdHJpbmcud3JhcCh2YWx1ZSwgeyBcInR5cGVcIjogXCJpbnRlZ2VyXCIsIFwidW5pdFwiOiAxLCBcInNpemVcIjogOCB9KTtcbiAgfVxuXG4gIHN0YXRpYyBmbG9hdCh2YWx1ZSkge1xuICAgIHJldHVybiBCaXRTdHJpbmcud3JhcCh2YWx1ZSwgeyBcInR5cGVcIjogXCJmbG9hdFwiLCBcInVuaXRcIjogMSwgXCJzaXplXCI6IDY0IH0pO1xuICB9XG5cbiAgc3RhdGljIGJpdHN0cmluZyh2YWx1ZSkge1xuICAgIHJldHVybiBCaXRTdHJpbmcud3JhcCh2YWx1ZSwgeyBcInR5cGVcIjogXCJiaXRzdHJpbmdcIiwgXCJ1bml0XCI6IDEsIFwic2l6ZVwiOiB2YWx1ZS5sZW5ndGggfSk7XG4gIH1cblxuICBzdGF0aWMgYml0cyh2YWx1ZSkge1xuICAgIHJldHVybiBCaXRTdHJpbmcuYml0c3RyaW5nKHZhbHVlKTtcbiAgfVxuXG4gIHN0YXRpYyBiaW5hcnkodmFsdWUpIHtcbiAgICByZXR1cm4gQml0U3RyaW5nLndyYXAodmFsdWUsIHsgXCJ0eXBlXCI6IFwiYmluYXJ5XCIsIFwidW5pdFwiOiA4LCBcInNpemVcIjogdmFsdWUubGVuZ3RoIH0pO1xuICB9XG5cbiAgc3RhdGljIGJ5dGVzKHZhbHVlKSB7XG4gICAgcmV0dXJuIEJpdFN0cmluZy5iaW5hcnkodmFsdWUpO1xuICB9XG5cbiAgc3RhdGljIHV0ZjgodmFsdWUpIHtcbiAgICByZXR1cm4gQml0U3RyaW5nLndyYXAodmFsdWUsIHsgXCJ0eXBlXCI6IFwidXRmOFwiIH0pO1xuICB9XG5cbiAgc3RhdGljIHV0ZjE2KHZhbHVlKSB7XG4gICAgcmV0dXJuIEJpdFN0cmluZy53cmFwKHZhbHVlLCB7IFwidHlwZVwiOiBcInV0ZjE2XCIgfSk7XG4gIH1cblxuICBzdGF0aWMgdXRmMzIodmFsdWUpIHtcbiAgICByZXR1cm4gQml0U3RyaW5nLndyYXAodmFsdWUsIHsgXCJ0eXBlXCI6IFwidXRmMzJcIiB9KTtcbiAgfVxuXG4gIHN0YXRpYyBzaWduZWQodmFsdWUpIHtcbiAgICByZXR1cm4gQml0U3RyaW5nLndyYXAodmFsdWUsIHt9LCBcInNpZ25lZFwiKTtcbiAgfVxuXG4gIHN0YXRpYyB1bnNpZ25lZCh2YWx1ZSkge1xuICAgIHJldHVybiBCaXRTdHJpbmcud3JhcCh2YWx1ZSwge30sIFwidW5zaWduZWRcIik7XG4gIH1cblxuICBzdGF0aWMgbmF0aXZlKHZhbHVlKSB7XG4gICAgcmV0dXJuIEJpdFN0cmluZy53cmFwKHZhbHVlLCB7fSwgXCJuYXRpdmVcIik7XG4gIH1cblxuICBzdGF0aWMgYmlnKHZhbHVlKSB7XG4gICAgcmV0dXJuIEJpdFN0cmluZy53cmFwKHZhbHVlLCB7fSwgXCJiaWdcIik7XG4gIH1cblxuICBzdGF0aWMgbGl0dGxlKHZhbHVlKSB7XG4gICAgcmV0dXJuIEJpdFN0cmluZy53cmFwKHZhbHVlLCB7fSwgXCJsaXR0bGVcIik7XG4gIH1cblxuICBzdGF0aWMgc2l6ZSh2YWx1ZSwgY291bnQpIHtcbiAgICByZXR1cm4gQml0U3RyaW5nLndyYXAodmFsdWUsIHsgXCJzaXplXCI6IGNvdW50IH0pO1xuICB9XG5cbiAgc3RhdGljIHVuaXQodmFsdWUsIGNvdW50KSB7XG4gICAgcmV0dXJuIEJpdFN0cmluZy53cmFwKHZhbHVlLCB7IFwidW5pdFwiOiBjb3VudCB9KTtcbiAgfVxuXG4gIHN0YXRpYyB3cmFwKHZhbHVlLCBvcHQsIG5ld19hdHRyaWJ1dGUgPSBudWxsKSB7XG4gICAgbGV0IHRoZV92YWx1ZSA9IHZhbHVlO1xuXG4gICAgaWYgKCEodmFsdWUgaW5zdGFuY2VvZiBPYmplY3QpKSB7XG4gICAgICB0aGVfdmFsdWUgPSB7IFwidmFsdWVcIjogdmFsdWUsIFwiYXR0cmlidXRlc1wiOiBbXSB9O1xuICAgIH1cblxuICAgIHRoZV92YWx1ZSA9IE9iamVjdC5hc3NpZ24odGhlX3ZhbHVlLCBvcHQpO1xuXG4gICAgaWYgKG5ld19hdHRyaWJ1dGUpIHtcbiAgICAgIHRoZV92YWx1ZS5hdHRyaWJ1dGVzLnB1c2gobmV3X2F0dHJpYnV0ZSk7XG4gICAgfVxuXG4gICAgcmV0dXJuIHRoZV92YWx1ZTtcbiAgfVxuXG4gIHN0YXRpYyB0b1VURjhBcnJheShzdHIpIHtcbiAgICB2YXIgdXRmOCA9IFtdO1xuICAgIGZvciAodmFyIGkgPSAwOyBpIDwgc3RyLmxlbmd0aDsgaSsrKSB7XG4gICAgICB2YXIgY2hhcmNvZGUgPSBzdHIuY2hhckNvZGVBdChpKTtcbiAgICAgIGlmIChjaGFyY29kZSA8IDEyOCkge1xuICAgICAgICB1dGY4LnB1c2goY2hhcmNvZGUpO1xuICAgICAgfSBlbHNlIGlmIChjaGFyY29kZSA8IDIwNDgpIHtcbiAgICAgICAgdXRmOC5wdXNoKDE5MiB8IGNoYXJjb2RlID4+IDYsIDEyOCB8IGNoYXJjb2RlICYgNjMpO1xuICAgICAgfSBlbHNlIGlmIChjaGFyY29kZSA8IDU1Mjk2IHx8IGNoYXJjb2RlID49IDU3MzQ0KSB7XG4gICAgICAgIHV0ZjgucHVzaCgyMjQgfCBjaGFyY29kZSA+PiAxMiwgMTI4IHwgY2hhcmNvZGUgPj4gNiAmIDYzLCAxMjggfCBjaGFyY29kZSAmIDYzKTtcbiAgICAgIH1cbiAgICAgIC8vIHN1cnJvZ2F0ZSBwYWlyXG4gICAgICBlbHNlIHtcbiAgICAgICAgaSsrO1xuICAgICAgICAvLyBVVEYtMTYgZW5jb2RlcyAweDEwMDAwLTB4MTBGRkZGIGJ5XG4gICAgICAgIC8vIHN1YnRyYWN0aW5nIDB4MTAwMDAgYW5kIHNwbGl0dGluZyB0aGVcbiAgICAgICAgLy8gMjAgYml0cyBvZiAweDAtMHhGRkZGRiBpbnRvIHR3byBoYWx2ZXNcbiAgICAgICAgY2hhcmNvZGUgPSA2NTUzNiArICgoY2hhcmNvZGUgJiAxMDIzKSA8PCAxMCB8IHN0ci5jaGFyQ29kZUF0KGkpICYgMTAyMyk7XG4gICAgICAgIHV0ZjgucHVzaCgyNDAgfCBjaGFyY29kZSA+PiAxOCwgMTI4IHwgY2hhcmNvZGUgPj4gMTIgJiA2MywgMTI4IHwgY2hhcmNvZGUgPj4gNiAmIDYzLCAxMjggfCBjaGFyY29kZSAmIDYzKTtcbiAgICAgIH1cbiAgICB9XG4gICAgcmV0dXJuIHV0Zjg7XG4gIH1cblxuICBzdGF0aWMgdG9VVEYxNkFycmF5KHN0cikge1xuICAgIHZhciB1dGYxNiA9IFtdO1xuICAgIGZvciAodmFyIGkgPSAwOyBpIDwgc3RyLmxlbmd0aDsgaSsrKSB7XG4gICAgICB2YXIgY29kZVBvaW50ID0gc3RyLmNvZGVQb2ludEF0KGkpO1xuXG4gICAgICBpZiAoY29kZVBvaW50IDw9IDI1NSkge1xuICAgICAgICB1dGYxNi5wdXNoKDApO1xuICAgICAgICB1dGYxNi5wdXNoKGNvZGVQb2ludCk7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICB1dGYxNi5wdXNoKGNvZGVQb2ludCA+PiA4ICYgMjU1KTtcbiAgICAgICAgdXRmMTYucHVzaChjb2RlUG9pbnQgJiAyNTUpO1xuICAgICAgfVxuICAgIH1cbiAgICByZXR1cm4gdXRmMTY7XG4gIH1cblxuICBzdGF0aWMgdG9VVEYzMkFycmF5KHN0cikge1xuICAgIHZhciB1dGYzMiA9IFtdO1xuICAgIGZvciAodmFyIGkgPSAwOyBpIDwgc3RyLmxlbmd0aDsgaSsrKSB7XG4gICAgICB2YXIgY29kZVBvaW50ID0gc3RyLmNvZGVQb2ludEF0KGkpO1xuXG4gICAgICBpZiAoY29kZVBvaW50IDw9IDI1NSkge1xuICAgICAgICB1dGYzMi5wdXNoKDApO1xuICAgICAgICB1dGYzMi5wdXNoKDApO1xuICAgICAgICB1dGYzMi5wdXNoKDApO1xuICAgICAgICB1dGYzMi5wdXNoKGNvZGVQb2ludCk7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICB1dGYzMi5wdXNoKDApO1xuICAgICAgICB1dGYzMi5wdXNoKDApO1xuICAgICAgICB1dGYzMi5wdXNoKGNvZGVQb2ludCA+PiA4ICYgMjU1KTtcbiAgICAgICAgdXRmMzIucHVzaChjb2RlUG9pbnQgJiAyNTUpO1xuICAgICAgfVxuICAgIH1cbiAgICByZXR1cm4gdXRmMzI7XG4gIH1cblxuICAvL2h0dHA6Ly9zdGFja292ZXJmbG93LmNvbS9xdWVzdGlvbnMvMjAwMzQ5My9qYXZhc2NyaXB0LWZsb2F0LWZyb20tdG8tYml0c1xuICBzdGF0aWMgZmxvYXQzMlRvQnl0ZXMoZikge1xuICAgIHZhciBieXRlcyA9IFtdO1xuXG4gICAgdmFyIGJ1ZiA9IG5ldyBBcnJheUJ1ZmZlcig0KTtcbiAgICBuZXcgRmxvYXQzMkFycmF5KGJ1ZilbMF0gPSBmO1xuXG4gICAgbGV0IGludFZlcnNpb24gPSBuZXcgVWludDMyQXJyYXkoYnVmKVswXTtcblxuICAgIGJ5dGVzLnB1c2goaW50VmVyc2lvbiA+PiAyNCAmIDI1NSk7XG4gICAgYnl0ZXMucHVzaChpbnRWZXJzaW9uID4+IDE2ICYgMjU1KTtcbiAgICBieXRlcy5wdXNoKGludFZlcnNpb24gPj4gOCAmIDI1NSk7XG4gICAgYnl0ZXMucHVzaChpbnRWZXJzaW9uICYgMjU1KTtcblxuICAgIHJldHVybiBieXRlcztcbiAgfVxuXG4gIHN0YXRpYyBmbG9hdDY0VG9CeXRlcyhmKSB7XG4gICAgdmFyIGJ5dGVzID0gW107XG5cbiAgICB2YXIgYnVmID0gbmV3IEFycmF5QnVmZmVyKDgpO1xuICAgIG5ldyBGbG9hdDY0QXJyYXkoYnVmKVswXSA9IGY7XG5cbiAgICB2YXIgaW50VmVyc2lvbjEgPSBuZXcgVWludDMyQXJyYXkoYnVmKVswXTtcbiAgICB2YXIgaW50VmVyc2lvbjIgPSBuZXcgVWludDMyQXJyYXkoYnVmKVsxXTtcblxuICAgIGJ5dGVzLnB1c2goaW50VmVyc2lvbjIgPj4gMjQgJiAyNTUpO1xuICAgIGJ5dGVzLnB1c2goaW50VmVyc2lvbjIgPj4gMTYgJiAyNTUpO1xuICAgIGJ5dGVzLnB1c2goaW50VmVyc2lvbjIgPj4gOCAmIDI1NSk7XG4gICAgYnl0ZXMucHVzaChpbnRWZXJzaW9uMiAmIDI1NSk7XG5cbiAgICBieXRlcy5wdXNoKGludFZlcnNpb24xID4+IDI0ICYgMjU1KTtcbiAgICBieXRlcy5wdXNoKGludFZlcnNpb24xID4+IDE2ICYgMjU1KTtcbiAgICBieXRlcy5wdXNoKGludFZlcnNpb24xID4+IDggJiAyNTUpO1xuICAgIGJ5dGVzLnB1c2goaW50VmVyc2lvbjEgJiAyNTUpO1xuXG4gICAgcmV0dXJuIGJ5dGVzO1xuICB9XG59XG5cbmxldCBTcGVjaWFsRm9ybXMgPSB7XG5cbiAgX19ESVJfXzogZnVuY3Rpb24gKCkge1xuICAgIGlmIChfX2Rpcm5hbWUpIHtcbiAgICAgIHJldHVybiBfX2Rpcm5hbWU7XG4gICAgfVxuXG4gICAgaWYgKGRvY3VtZW50LmN1cnJlbnRTY3JpcHQpIHtcbiAgICAgIHJldHVybiBkb2N1bWVudC5jdXJyZW50U2NyaXB0LnNyYztcbiAgICB9XG5cbiAgICByZXR1cm4gbnVsbDtcbiAgfSxcblxuICBhdG9tOiBmdW5jdGlvbiAoX3ZhbHVlKSB7XG4gICAgcmV0dXJuIFN5bWJvbC5mb3IoX3ZhbHVlKTtcbiAgfSxcblxuICBsaXN0OiBmdW5jdGlvbiAoLi4uYXJncykge1xuICAgIHJldHVybiBPYmplY3QuZnJlZXplKGFyZ3MpO1xuICB9LFxuXG4gIGJpdHN0cmluZzogZnVuY3Rpb24gKC4uLmFyZ3MpIHtcbiAgICByZXR1cm4gbmV3IEJpdFN0cmluZyguLi5hcmdzKTtcbiAgfSxcblxuICBib3VuZDogZnVuY3Rpb24gKF92YXIpIHtcbiAgICByZXR1cm4gUGF0dGVybnMuYm91bmQoX3Zhcik7XG4gIH0sXG5cbiAgX2Nhc2U6IGZ1bmN0aW9uIChjb25kaXRpb24sIGNsYXVzZXMpIHtcbiAgICByZXR1cm4gUGF0dGVybnMuZGVmbWF0Y2goLi4uY2xhdXNlcykoY29uZGl0aW9uKTtcbiAgfSxcblxuICBjb25kOiBmdW5jdGlvbiAoY2xhdXNlcykge1xuICAgIGZvciAobGV0IGNsYXVzZSBvZiBjbGF1c2VzKSB7XG4gICAgICBpZiAoY2xhdXNlWzBdKSB7XG4gICAgICAgIHJldHVybiBjbGF1c2VbMV0oKTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICB0aHJvdyBuZXcgRXJyb3IoKTtcbiAgfSxcblxuICBmbjogZnVuY3Rpb24gKGNsYXVzZXMpIHtcbiAgICByZXR1cm4gUGF0dGVybnMuZGVmbWF0Y2goY2xhdXNlcyk7XG4gIH0sXG5cbiAgbWFwOiBmdW5jdGlvbiAob2JqKSB7XG4gICAgcmV0dXJuIE9iamVjdC5mcmVlemUob2JqKTtcbiAgfSxcblxuICBtYXBfdXBkYXRlOiBmdW5jdGlvbiAobWFwLCB2YWx1ZXMpIHtcbiAgICByZXR1cm4gT2JqZWN0LmZyZWV6ZShPYmplY3QuYXNzaWduKE9iamVjdC5jcmVhdGUobWFwLmNvbnN0cnVjdG9yLnByb3RvdHlwZSksIG1hcCwgdmFsdWVzKSk7XG4gIH0sXG5cbiAgX2ZvcjogZnVuY3Rpb24gKGNvbGxlY3Rpb25zLCBmdW4sIGZpbHRlciA9ICgpID0+IHRydWUsIGludG8gPSBbXSwgcHJldmlvdXNWYWx1ZXMgPSBbXSkge1xuICAgIGxldCBwYXR0ZXJuID0gY29sbGVjdGlvbnNbMF1bMF07XG4gICAgbGV0IGNvbGxlY3Rpb24gPSBjb2xsZWN0aW9uc1swXVsxXTtcblxuICAgIGlmIChjb2xsZWN0aW9ucy5sZW5ndGggPT09IDEpIHtcblxuICAgICAgZm9yIChsZXQgZWxlbSBvZiBjb2xsZWN0aW9uKSB7XG4gICAgICAgIGxldCByID0gUGF0dGVybnMubWF0Y2hfbm9fdGhyb3cocGF0dGVybiwgZWxlbSk7XG4gICAgICAgIGxldCBhcmdzID0gcHJldmlvdXNWYWx1ZXMuY29uY2F0KHIpO1xuXG4gICAgICAgIGlmIChyICYmIGZpbHRlci5hcHBseSh0aGlzLCBhcmdzKSkge1xuICAgICAgICAgIGludG8gPSBFbnVtLmludG8oW2Z1bi5hcHBseSh0aGlzLCBhcmdzKV0sIGludG8pO1xuICAgICAgICB9XG4gICAgICB9XG5cbiAgICAgIHJldHVybiBpbnRvO1xuICAgIH0gZWxzZSB7XG4gICAgICBsZXQgX2ludG8gPSBbXTtcblxuICAgICAgZm9yIChsZXQgZWxlbSBvZiBjb2xsZWN0aW9uKSB7XG4gICAgICAgIGxldCByID0gUGF0dGVybnMubWF0Y2hfbm9fdGhyb3cocGF0dGVybiwgZWxlbSk7XG4gICAgICAgIGlmIChyKSB7XG4gICAgICAgICAgX2ludG8gPSBFbnVtLmludG8odGhpcy5fZm9yKGNvbGxlY3Rpb25zLnNsaWNlKDEpLCBmdW4sIGZpbHRlciwgX2ludG8sIHByZXZpb3VzVmFsdWVzLmNvbmNhdChyKSksIGludG8pO1xuICAgICAgICB9XG4gICAgICB9XG5cbiAgICAgIHJldHVybiBfaW50bztcbiAgICB9XG4gIH0sXG5cbiAgcmVjZWl2ZTogZnVuY3Rpb24gKHJlY2VpdmVfZnVuLCB0aW1lb3V0X2luX21zID0gbnVsbCwgdGltZW91dF9mbiA9IHRpbWUgPT4gdHJ1ZSkge1xuICAgIGlmICh0aW1lb3V0X2luX21zID09IG51bGwgfHwgdGltZW91dF9pbl9tcyA9PT0gU3lzdGVtLmZvcignaW5maW5pdHknKSkge1xuICAgICAgd2hpbGUgKHRydWUpIHtcbiAgICAgICAgaWYgKHNlbGYubWFpbGJveC5sZW5ndGggIT09IDApIHtcbiAgICAgICAgICBsZXQgbWVzc2FnZSA9IHNlbGYubWFpbGJveFswXTtcbiAgICAgICAgICBzZWxmLm1haWxib3ggPSBzZWxmLm1haWxib3guc2xpY2UoMSk7XG4gICAgICAgICAgcmV0dXJuIHJlY2VpdmVfZnVuKG1lc3NhZ2UpO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgfSBlbHNlIGlmICh0aW1lb3V0X2luX21zID09PSAwKSB7XG4gICAgICBpZiAoc2VsZi5tYWlsYm94Lmxlbmd0aCAhPT0gMCkge1xuICAgICAgICBsZXQgbWVzc2FnZSA9IHNlbGYubWFpbGJveFswXTtcbiAgICAgICAgc2VsZi5tYWlsYm94ID0gc2VsZi5tYWlsYm94LnNsaWNlKDEpO1xuICAgICAgICByZXR1cm4gcmVjZWl2ZV9mdW4obWVzc2FnZSk7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICByZXR1cm4gbnVsbDtcbiAgICAgIH1cbiAgICB9IGVsc2Uge1xuICAgICAgbGV0IG5vdyA9IERhdGUubm93KCk7XG4gICAgICB3aGlsZSAoRGF0ZS5ub3coKSA8IG5vdyArIHRpbWVvdXRfaW5fbXMpIHtcbiAgICAgICAgaWYgKHNlbGYubWFpbGJveC5sZW5ndGggIT09IDApIHtcbiAgICAgICAgICBsZXQgbWVzc2FnZSA9IHNlbGYubWFpbGJveFswXTtcbiAgICAgICAgICBzZWxmLm1haWxib3ggPSBzZWxmLm1haWxib3guc2xpY2UoMSk7XG4gICAgICAgICAgcmV0dXJuIHJlY2VpdmVfZnVuKG1lc3NhZ2UpO1xuICAgICAgICB9XG4gICAgICB9XG5cbiAgICAgIHJldHVybiB0aW1lb3V0X2ZuKHRpbWVvdXRfaW5fbXMpO1xuICAgIH1cbiAgfSxcblxuICB0dXBsZTogZnVuY3Rpb24gKC4uLmFyZ3MpIHtcbiAgICByZXR1cm4gbmV3IFR1cGxlKC4uLmFyZ3MpO1xuICB9LFxuXG4gIF90cnk6IGZ1bmN0aW9uIChkb19mdW4sIHJlc2N1ZV9mdW5jdGlvbiwgY2F0Y2hfZnVuLCBlbHNlX2Z1bmN0aW9uLCBhZnRlcl9mdW5jdGlvbikge1xuICAgIGxldCByZXN1bHQgPSBudWxsO1xuXG4gICAgdHJ5IHtcbiAgICAgIHJlc3VsdCA9IGRvX2Z1bigpO1xuICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgIGxldCBleF9yZXN1bHQgPSBudWxsO1xuXG4gICAgICBpZiAocmVzY3VlX2Z1bmN0aW9uKSB7XG4gICAgICAgIHRyeSB7XG4gICAgICAgICAgZXhfcmVzdWx0ID0gcmVzY3VlX2Z1bmN0aW9uKGUpO1xuICAgICAgICAgIHJldHVybiBleF9yZXN1bHQ7XG4gICAgICAgIH0gY2F0Y2ggKGV4KSB7XG4gICAgICAgICAgaWYgKGV4IGluc3RhbmNlb2YgUGF0dGVybnMuTWF0Y2hFcnJvcikge1xuICAgICAgICAgICAgdGhyb3cgZXg7XG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICB9XG5cbiAgICAgIGlmIChjYXRjaF9mdW4pIHtcbiAgICAgICAgdHJ5IHtcbiAgICAgICAgICBleF9yZXN1bHQgPSBjYXRjaF9mdW4oZSk7XG4gICAgICAgICAgcmV0dXJuIGV4X3Jlc3VsdDtcbiAgICAgICAgfSBjYXRjaCAoZXgpIHtcbiAgICAgICAgICBpZiAoZXggaW5zdGFuY2VvZiBQYXR0ZXJucy5NYXRjaEVycm9yKSB7XG4gICAgICAgICAgICB0aHJvdyBleDtcbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgIH1cblxuICAgICAgdGhyb3cgZTtcbiAgICB9IGZpbmFsbHkge1xuICAgICAgaWYgKGFmdGVyX2Z1bmN0aW9uKSB7XG4gICAgICAgIGFmdGVyX2Z1bmN0aW9uKCk7XG4gICAgICB9XG4gICAgfVxuXG4gICAgaWYgKGVsc2VfZnVuY3Rpb24pIHtcbiAgICAgIHRyeSB7XG4gICAgICAgIHJldHVybiBlbHNlX2Z1bmN0aW9uKHJlc3VsdCk7XG4gICAgICB9IGNhdGNoIChleCkge1xuICAgICAgICBpZiAoZXggaW5zdGFuY2VvZiBQYXR0ZXJucy5NYXRjaEVycm9yKSB7XG4gICAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdObyBNYXRjaCBGb3VuZCBpbiBFbHNlJyk7XG4gICAgICAgIH1cblxuICAgICAgICB0aHJvdyBleDtcbiAgICAgIH1cbiAgICB9IGVsc2Uge1xuICAgICAgcmV0dXJuIHJlc3VsdDtcbiAgICB9XG4gIH1cblxufTtcblxuLyogQGZsb3cgKi9cblxubGV0IHByb2Nlc3NfY291bnRlciA9IC0xO1xuXG5jbGFzcyBQSUQge1xuICBjb25zdHJ1Y3RvcigpIHtcbiAgICBwcm9jZXNzX2NvdW50ZXIgPSBwcm9jZXNzX2NvdW50ZXIgKyAxO1xuICAgIHRoaXMuaWQgPSBwcm9jZXNzX2NvdW50ZXI7XG4gIH1cblxuICB0b1N0cmluZygpIHtcbiAgICByZXR1cm4gXCJQSUQjPDAuXCIgKyB0aGlzLmlkICsgXCIuMD5cIjtcbiAgfVxufVxuXG5jbGFzcyBJbnRlZ2VyVHlwZSB7fVxuY2xhc3MgRmxvYXRUeXBlIHt9XG5cbi8vaHR0cHM6Ly9naXRodWIuY29tL2FpcnBvcnR5aC9wcm90b21vcnBoaXNtXG5jbGFzcyBQcm90b2NvbCB7XG4gIGNvbnN0cnVjdG9yKHNwZWMpIHtcbiAgICB0aGlzLnJlZ2lzdHJ5ID0gbmV3IE1hcCgpO1xuICAgIHRoaXMuZmFsbGJhY2sgPSBudWxsO1xuXG4gICAgZm9yIChsZXQgZnVuTmFtZSBpbiBzcGVjKSB7XG4gICAgICB0aGlzW2Z1bk5hbWVdID0gY3JlYXRlRnVuKGZ1bk5hbWUpLmJpbmQodGhpcyk7XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gY3JlYXRlRnVuKGZ1bk5hbWUpIHtcblxuICAgICAgcmV0dXJuIGZ1bmN0aW9uICguLi5hcmdzKSB7XG4gICAgICAgIGxldCB0aGluZyA9IGFyZ3NbMF07XG4gICAgICAgIGxldCBmdW4gPSBudWxsO1xuXG4gICAgICAgIGlmIChOdW1iZXIuaXNJbnRlZ2VyKHRoaW5nKSAmJiB0aGlzLmhhc0ltcGxlbWVudGF0aW9uKEludGVnZXJUeXBlKSkge1xuICAgICAgICAgIGZ1biA9IHRoaXMucmVnaXN0cnkuZ2V0KEludGVnZXJUeXBlKVtmdW5OYW1lXTtcbiAgICAgICAgfSBlbHNlIGlmICh0eXBlb2YgdGhpbmcgPT09IFwibnVtYmVyXCIgJiYgIU51bWJlci5pc0ludGVnZXIodGhpbmcpICYmIHRoaXMuaGFzSW1wbGVtZW50YXRpb24oRmxvYXRUeXBlKSkge1xuICAgICAgICAgIGZ1biA9IHRoaXMucmVnaXN0cnkuZ2V0KEZsb2F0VHlwZSlbZnVuTmFtZV07XG4gICAgICAgIH0gZWxzZSBpZiAodGhpcy5oYXNJbXBsZW1lbnRhdGlvbih0aGluZykpIHtcbiAgICAgICAgICBmdW4gPSB0aGlzLnJlZ2lzdHJ5LmdldCh0aGluZy5jb25zdHJ1Y3RvcilbZnVuTmFtZV07XG4gICAgICAgIH0gZWxzZSBpZiAodGhpcy5mYWxsYmFjaykge1xuICAgICAgICAgIGZ1biA9IHRoaXMuZmFsbGJhY2tbZnVuTmFtZV07XG4gICAgICAgIH1cblxuICAgICAgICBpZiAoZnVuICE9IG51bGwpIHtcbiAgICAgICAgICBsZXQgcmV0dmFsID0gZnVuLmFwcGx5KHRoaXMsIGFyZ3MpO1xuICAgICAgICAgIHJldHVybiByZXR2YWw7XG4gICAgICAgIH1cblxuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoXCJObyBpbXBsZW1lbnRhdGlvbiBmb3VuZCBmb3IgXCIgKyB0aGluZyk7XG4gICAgICB9O1xuICAgIH1cbiAgfVxuXG4gIGltcGxlbWVudGF0aW9uKHR5cGUsIGltcGxlbWVudGF0aW9uKSB7XG4gICAgaWYgKHR5cGUgPT09IG51bGwpIHtcbiAgICAgIHRoaXMuZmFsbGJhY2sgPSBpbXBsZW1lbnRhdGlvbjtcbiAgICB9IGVsc2Uge1xuICAgICAgdGhpcy5yZWdpc3RyeS5zZXQodHlwZSwgaW1wbGVtZW50YXRpb24pO1xuICAgIH1cbiAgfVxuXG4gIGhhc0ltcGxlbWVudGF0aW9uKHRoaW5nKSB7XG4gICAgcmV0dXJuIHRoaXMucmVnaXN0cnkuaGFzKHRoaW5nLmNvbnN0cnVjdG9yKTtcbiAgfVxufVxuXG5mdW5jdGlvbiB0bChsaXN0KSB7XG4gIHJldHVybiBTcGVjaWFsRm9ybXMubGlzdCguLi5saXN0LnNsaWNlKDEpKTtcbn1cblxuZnVuY3Rpb24gaGQobGlzdCkge1xuICByZXR1cm4gbGlzdFswXTtcbn1cblxuZnVuY3Rpb24gaXNfbmlsKHgpIHtcbiAgcmV0dXJuIHggPT09IG51bGw7XG59XG5cbmZ1bmN0aW9uIGlzX2F0b20oeCkge1xuICByZXR1cm4gdHlwZW9mIHggPT09ICdzeW1ib2wnO1xufVxuXG5mdW5jdGlvbiBpc19iaW5hcnkoeCkge1xuICByZXR1cm4gdHlwZW9mIHggPT09ICdzdHJpbmcnIHx8IHggaW5zdGFuY2VvZiBTdHJpbmc7XG59XG5cbmZ1bmN0aW9uIGlzX2Jvb2xlYW4oeCkge1xuICByZXR1cm4gdHlwZW9mIHggPT09ICdib29sZWFuJyB8fCB4IGluc3RhbmNlb2YgQm9vbGVhbjtcbn1cblxuZnVuY3Rpb24gaXNfZnVuY3Rpb24oeCwgYXJpdHkgPSAtMSkge1xuICByZXR1cm4gdHlwZW9mIHggPT09ICdmdW5jdGlvbicgfHwgeCBpbnN0YW5jZW9mIEZ1bmN0aW9uO1xufVxuXG5mdW5jdGlvbiBpc19mbG9hdCh4KSB7XG4gIHJldHVybiBpc19udW1iZXIoeCkgJiYgIU51bWJlci5pc0ludGVnZXIoeCk7XG59XG5cbmZ1bmN0aW9uIGlzX2ludGVnZXIoeCkge1xuICByZXR1cm4gTnVtYmVyLmlzSW50ZWdlcih4KTtcbn1cblxuZnVuY3Rpb24gaXNfbGlzdCh4KSB7XG4gIHJldHVybiB4IGluc3RhbmNlb2YgQXJyYXk7XG59XG5cbmZ1bmN0aW9uIGlzX21hcCh4KSB7XG4gIHJldHVybiB0eXBlb2YgeCA9PT0gJ29iamVjdCcgfHwgeCBpbnN0YW5jZW9mIE9iamVjdDtcbn1cblxuZnVuY3Rpb24gaXNfbnVtYmVyKHgpIHtcbiAgcmV0dXJuIHR5cGVvZiB4ID09PSAnbnVtYmVyJztcbn1cblxuZnVuY3Rpb24gaXNfdHVwbGUoeCkge1xuICByZXR1cm4geCBpbnN0YW5jZW9mIFR1cGxlO1xufVxuXG5mdW5jdGlvbiBfbGVuZ3RoKHgpIHtcbiAgcmV0dXJuIHgubGVuZ3RoO1xufVxuXG5mdW5jdGlvbiBpc19waWQoeCkge1xuICByZXR1cm4geCBpbnN0YW5jZW9mIFBJRDtcbn1cblxuZnVuY3Rpb24gaXNfcG9ydCh4KSB7XG4gIHJldHVybiBmYWxzZTtcbn1cblxuZnVuY3Rpb24gaXNfcmVmZXJlbmNlKHgpIHtcbiAgcmV0dXJuIGZhbHNlO1xufVxuXG5mdW5jdGlvbiBpc19iaXRzdHJpbmcoeCkge1xuICByZXR1cm4gaXNfYmluYXJ5KHgpIHx8IHggaW5zdGFuY2VvZiBCaXRTdHJpbmc7XG59XG5cbmZ1bmN0aW9uIF9faW5fXyhsZWZ0LCByaWdodCkge1xuICBmb3IgKGxldCB4IG9mIHJpZ2h0KSB7XG4gICAgaWYgKG1hdGNoX19xbWFya19fKGxlZnQsIHgpKSB7XG4gICAgICByZXR1cm4gdHJ1ZTtcbiAgICB9XG4gIH1cblxuICByZXR1cm4gZmFsc2U7XG59XG5cbmZ1bmN0aW9uIGFicyhudW1iZXIpIHtcbiAgcmV0dXJuIE1hdGguYWJzKG51bWJlcik7XG59XG5cbmZ1bmN0aW9uIHJvdW5kKG51bWJlcikge1xuICByZXR1cm4gTWF0aC5yb3VuZChudW1iZXIpO1xufVxuXG5mdW5jdGlvbiBlbGVtKHR1cGxlLCBpbmRleCkge1xuICBpZiAoaXNfbGlzdCh0dXBsZSkpIHtcbiAgICByZXR1cm4gdHVwbGVbaW5kZXhdO1xuICB9XG5cbiAgcmV0dXJuIHR1cGxlLmdldChpbmRleCk7XG59XG5cbmZ1bmN0aW9uIHJlbShsZWZ0LCByaWdodCkge1xuICByZXR1cm4gbGVmdCAlIHJpZ2h0O1xufVxuXG5mdW5jdGlvbiBkaXYobGVmdCwgcmlnaHQpIHtcbiAgcmV0dXJuIGxlZnQgLyByaWdodDtcbn1cblxuZnVuY3Rpb24gYW5kKGxlZnQsIHJpZ2h0KSB7XG4gIHJldHVybiBsZWZ0ICYmIHJpZ2h0O1xufVxuXG5mdW5jdGlvbiBvcihsZWZ0LCByaWdodCkge1xuICByZXR1cm4gbGVmdCB8fCByaWdodDtcbn1cblxuZnVuY3Rpb24gbm90KGFyZykge1xuICByZXR1cm4gIWFyZztcbn1cblxuZnVuY3Rpb24gYXBwbHkoLi4uYXJncykge1xuICBpZiAoYXJncy5sZW5ndGggPT09IDMpIHtcbiAgICBsZXQgbW9kID0gYXJnc1swXTtcbiAgICBsZXQgZnVuYyA9IGFyZ3NbMV07XG4gICAgbGV0IGZ1bmNfYXJncyA9IGFyZ3NbMl07XG4gICAgcmV0dXJuIG1vZFtmdW5jXS5hcHBseShudWxsLCBmdW5jX2FyZ3MpO1xuICB9IGVsc2Uge1xuICAgIGxldCBmdW5jID0gYXJnc1swXTtcbiAgICBsZXQgZnVuY19hcmdzID0gYXJnc1sxXTtcblxuICAgIHJldHVybiBmdW5jLmFwcGx5KG51bGwsIGZ1bmNfYXJncyk7XG4gIH1cbn1cblxuZnVuY3Rpb24gdG9fc3RyaW5nKGFyZykge1xuICBpZiAoaXNfdHVwbGUoYXJnKSkge1xuICAgIHJldHVybiBUdXBsZS50b19zdHJpbmcoYXJnKTtcbiAgfVxuXG4gIHJldHVybiBhcmcudG9TdHJpbmcoKTtcbn1cblxuZnVuY3Rpb24gbWF0Y2hfX3FtYXJrX18ocGF0dGVybiwgZXhwciwgZ3VhcmQgPSAoKSA9PiB0cnVlKSB7XG4gIHJldHVybiBfUGF0dGVybnMubWF0Y2hfbm9fdGhyb3cocGF0dGVybiwgZXhwciwgZ3VhcmQpICE9IG51bGw7XG59XG5cbmZ1bmN0aW9uIGRlZnN0cnVjdChkZWZhdWx0cykge1xuICByZXR1cm4gY2xhc3Mge1xuICAgIGNvbnN0cnVjdG9yKHVwZGF0ZSA9IHt9KSB7XG4gICAgICBsZXQgdGhlX3ZhbHVlcyA9IE9iamVjdC5hc3NpZ24oZGVmYXVsdHMsIHVwZGF0ZSk7XG4gICAgICBPYmplY3QuYXNzaWduKHRoaXMsIHRoZV92YWx1ZXMpO1xuICAgIH1cblxuICAgIHN0YXRpYyBjcmVhdGUodXBkYXRlcyA9IHt9KSB7XG4gICAgICBsZXQgeCA9IG5ldyB0aGlzKHVwZGF0ZXMpO1xuICAgICAgcmV0dXJuIE9iamVjdC5mcmVlemUoeCk7XG4gICAgfVxuICB9O1xufVxuXG5mdW5jdGlvbiBkZWZleGNlcHRpb24oZGVmYXVsdHMpIHtcbiAgcmV0dXJuIGNsYXNzIGV4dGVuZHMgRXJyb3Ige1xuICAgIGNvbnN0cnVjdG9yKHVwZGF0ZSA9IHt9KSB7XG4gICAgICBsZXQgbWVzc2FnZSA9IHVwZGF0ZS5tZXNzYWdlIHx8ICcnO1xuICAgICAgc3VwZXIobWVzc2FnZSk7XG5cbiAgICAgIGxldCB0aGVfdmFsdWVzID0gT2JqZWN0LmFzc2lnbihkZWZhdWx0cywgdXBkYXRlKTtcbiAgICAgIE9iamVjdC5hc3NpZ24odGhpcywgdGhlX3ZhbHVlcyk7XG5cbiAgICAgIHRoaXMubmFtZSA9IHRoaXMuY29uc3RydWN0b3IubmFtZTtcbiAgICAgIHRoaXMubWVzc2FnZSA9IG1lc3NhZ2U7XG4gICAgICB0aGlzW1NwZWNpYWxGb3Jtcy5hdG9tKCdfX2V4Y2VwdGlvbl9fJyldID0gdHJ1ZTtcbiAgICAgIEVycm9yLmNhcHR1cmVTdGFja1RyYWNlKHRoaXMsIHRoaXMuY29uc3RydWN0b3IubmFtZSk7XG4gICAgfVxuXG4gICAgc3RhdGljIGNyZWF0ZSh1cGRhdGVzID0ge30pIHtcbiAgICAgIGxldCB4ID0gbmV3IHRoaXModXBkYXRlcyk7XG4gICAgICByZXR1cm4gT2JqZWN0LmZyZWV6ZSh4KTtcbiAgICB9XG4gIH07XG59XG5cbmZ1bmN0aW9uIGRlZnByb3RvY29sKHNwZWMpIHtcbiAgcmV0dXJuIG5ldyBQcm90b2NvbChzcGVjKTtcbn1cblxuZnVuY3Rpb24gZGVmaW1wbChwcm90b2NvbCwgdHlwZSwgaW1wbCkge1xuICBwcm90b2NvbC5pbXBsZW1lbnRhdGlvbih0eXBlLCBpbXBsKTtcbn1cblxudmFyIEtlcm5lbCA9IHtcbiAgU3BlY2lhbEZvcm1zLFxuICB0bCxcbiAgaGQsXG4gIGlzX25pbCxcbiAgaXNfYXRvbSxcbiAgaXNfYmluYXJ5LFxuICBpc19ib29sZWFuLFxuICBpc19mdW5jdGlvbixcbiAgaXNfZmxvYXQsXG4gIGlzX2ludGVnZXIsXG4gIGlzX2xpc3QsXG4gIGlzX21hcCxcbiAgaXNfbnVtYmVyLFxuICBpc190dXBsZSxcbiAgbGVuZ3RoOiBfbGVuZ3RoLFxuICBpc19waWQsXG4gIGlzX3BvcnQsXG4gIGlzX3JlZmVyZW5jZSxcbiAgaXNfYml0c3RyaW5nLFxuICBpbjogX19pbl9fLFxuICBhYnMsXG4gIHJvdW5kLFxuICBlbGVtLFxuICByZW0sXG4gIGRpdixcbiAgYW5kLFxuICBvcixcbiAgbm90LFxuICBhcHBseSxcbiAgdG9fc3RyaW5nLFxuICBtYXRjaF9fcW1hcmtfXyxcbiAgZGVmc3RydWN0LFxuICBkZWZwcm90b2NvbCxcbiAgZGVmaW1wbFxufTtcblxubGV0IEVudW0gPSB7XG5cbiAgYWxsX19xbWFya19fOiBmdW5jdGlvbiAoY29sbGVjdGlvbiwgZnVuID0geCA9PiB4KSB7XG4gICAgZm9yIChsZXQgZWxlbSBvZiBjb2xsZWN0aW9uKSB7XG4gICAgICBpZiAoIWZ1bihlbGVtKSkge1xuICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICB9XG4gICAgfVxuXG4gICAgcmV0dXJuIHRydWU7XG4gIH0sXG5cbiAgYW55X19xbWFya19fOiBmdW5jdGlvbiAoY29sbGVjdGlvbiwgZnVuID0geCA9PiB4KSB7XG4gICAgZm9yIChsZXQgZWxlbSBvZiBjb2xsZWN0aW9uKSB7XG4gICAgICBpZiAoZnVuKGVsZW0pKSB7XG4gICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgfVxuICAgIH1cblxuICAgIHJldHVybiBmYWxzZTtcbiAgfSxcblxuICBhdDogZnVuY3Rpb24gKGNvbGxlY3Rpb24sIG4sIHRoZV9kZWZhdWx0ID0gbnVsbCkge1xuICAgIGlmIChuID4gdGhpcy5jb3VudChjb2xsZWN0aW9uKSB8fCBuIDwgMCkge1xuICAgICAgcmV0dXJuIHRoZV9kZWZhdWx0O1xuICAgIH1cblxuICAgIHJldHVybiBjb2xsZWN0aW9uW25dO1xuICB9LFxuXG4gIGNvbmNhdDogZnVuY3Rpb24gKC4uLmVudW1hYmxlcykge1xuICAgIHJldHVybiBlbnVtYWJsZXNbMF0uY29uY2F0KGVudW1hYmxlc1sxXSk7XG4gIH0sXG5cbiAgY291bnQ6IGZ1bmN0aW9uIChjb2xsZWN0aW9uLCBmdW4gPSBudWxsKSB7XG4gICAgaWYgKGZ1biA9PSBudWxsKSB7XG4gICAgICByZXR1cm4gY29sbGVjdGlvbi5sZW5ndGg7XG4gICAgfSBlbHNlIHtcbiAgICAgIHJldHVybiBjb2xsZWN0aW9uLmZpbHRlcihmdW4pLmxlbmd0aDtcbiAgICB9XG4gIH0sXG5cbiAgZHJvcDogZnVuY3Rpb24gKGNvbGxlY3Rpb24sIGNvdW50KSB7XG4gICAgcmV0dXJuIGNvbGxlY3Rpb24uc2xpY2UoY291bnQpO1xuICB9LFxuXG4gIGRyb3Bfd2hpbGU6IGZ1bmN0aW9uIChjb2xsZWN0aW9uLCBmdW4pIHtcbiAgICBsZXQgY291bnQgPSAwO1xuXG4gICAgZm9yIChsZXQgZWxlbSBvZiBjb2xsZWN0aW9uKSB7XG4gICAgICBpZiAoZnVuKGVsZW0pKSB7XG4gICAgICAgIGNvdW50ID0gY291bnQgKyAxO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgYnJlYWs7XG4gICAgICB9XG4gICAgfVxuXG4gICAgcmV0dXJuIGNvbGxlY3Rpb24uc2xpY2UoY291bnQpO1xuICB9LFxuXG4gIGVhY2g6IGZ1bmN0aW9uIChjb2xsZWN0aW9uLCBmdW4pIHtcbiAgICBmb3IgKGxldCBlbGVtIG9mIGNvbGxlY3Rpb24pIHtcbiAgICAgIGZ1bihlbGVtKTtcbiAgICB9XG4gIH0sXG5cbiAgZW1wdHlfX3FtYXJrX186IGZ1bmN0aW9uIChjb2xsZWN0aW9uKSB7XG4gICAgcmV0dXJuIGNvbGxlY3Rpb24ubGVuZ3RoID09PSAwO1xuICB9LFxuXG4gIGZldGNoOiBmdW5jdGlvbiAoY29sbGVjdGlvbiwgbikge1xuICAgIGlmIChLZXJuZWwuaXNfbGlzdChjb2xsZWN0aW9uKSkge1xuICAgICAgaWYgKG4gPCB0aGlzLmNvdW50KGNvbGxlY3Rpb24pICYmIG4gPj0gMCkge1xuICAgICAgICByZXR1cm4gS2VybmVsLlNwZWNpYWxGb3Jtcy50dXBsZShLZXJuZWwuU3BlY2lhbEZvcm1zLmF0b20oXCJva1wiKSwgY29sbGVjdGlvbltuXSk7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICByZXR1cm4gS2VybmVsLlNwZWNpYWxGb3Jtcy5hdG9tKFwiZXJyb3JcIik7XG4gICAgICB9XG4gICAgfVxuXG4gICAgdGhyb3cgbmV3IEVycm9yKFwiY29sbGVjdGlvbiBpcyBub3QgYW4gRW51bWVyYWJsZVwiKTtcbiAgfSxcblxuICBmZXRjaF9fZW1hcmtfXzogZnVuY3Rpb24gKGNvbGxlY3Rpb24sIG4pIHtcbiAgICBpZiAoS2VybmVsLmlzX2xpc3QoY29sbGVjdGlvbikpIHtcbiAgICAgIGlmIChuIDwgdGhpcy5jb3VudChjb2xsZWN0aW9uKSAmJiBuID49IDApIHtcbiAgICAgICAgcmV0dXJuIGNvbGxlY3Rpb25bbl07XG4gICAgICB9IGVsc2Uge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoXCJvdXQgb2YgYm91bmRzIGVycm9yXCIpO1xuICAgICAgfVxuICAgIH1cblxuICAgIHRocm93IG5ldyBFcnJvcihcImNvbGxlY3Rpb24gaXMgbm90IGFuIEVudW1lcmFibGVcIik7XG4gIH0sXG5cbiAgZmlsdGVyOiBmdW5jdGlvbiAoY29sbGVjdGlvbiwgZnVuKSB7XG4gICAgbGV0IHJlc3VsdCA9IFtdO1xuXG4gICAgZm9yIChsZXQgZWxlbSBvZiBjb2xsZWN0aW9uKSB7XG4gICAgICBpZiAoZnVuKGVsZW0pKSB7XG4gICAgICAgIHJlc3VsdC5wdXNoKGVsZW0pO1xuICAgICAgfVxuICAgIH1cblxuICAgIHJldHVybiByZXN1bHQ7XG4gIH0sXG5cbiAgZmlsdGVyX21hcDogZnVuY3Rpb24gKGNvbGxlY3Rpb24sIGZpbHRlciwgbWFwcGVyKSB7XG4gICAgcmV0dXJuIEVudW0ubWFwKEVudW0uZmlsdGVyKGNvbGxlY3Rpb24sIGZpbHRlciksIG1hcHBlcik7XG4gIH0sXG5cbiAgZmluZDogZnVuY3Rpb24gKGNvbGxlY3Rpb24sIGlmX25vbmUgPSBudWxsLCBmdW4pIHtcbiAgICBmb3IgKGxldCBlbGVtIG9mIGNvbGxlY3Rpb24pIHtcbiAgICAgIGlmIChmdW4oZWxlbSkpIHtcbiAgICAgICAgcmV0dXJuIGVsZW07XG4gICAgICB9XG4gICAgfVxuXG4gICAgcmV0dXJuIGlmX25vbmU7XG4gIH0sXG5cbiAgaW50bzogZnVuY3Rpb24gKGNvbGxlY3Rpb24sIGxpc3QpIHtcbiAgICByZXR1cm4gbGlzdC5jb25jYXQoY29sbGVjdGlvbik7XG4gIH0sXG5cbiAgbWFwOiBmdW5jdGlvbiAoY29sbGVjdGlvbiwgZnVuKSB7XG4gICAgbGV0IHJlc3VsdCA9IFtdO1xuXG4gICAgZm9yIChsZXQgZWxlbSBvZiBjb2xsZWN0aW9uKSB7XG4gICAgICByZXN1bHQucHVzaChmdW4oZWxlbSkpO1xuICAgIH1cblxuICAgIHJldHVybiByZXN1bHQ7XG4gIH0sXG5cbiAgbWFwX3JlZHVjZTogZnVuY3Rpb24gKGNvbGxlY3Rpb24sIGFjYywgZnVuKSB7XG4gICAgbGV0IG1hcHBlZCA9IEtlcm5lbC5TcGVjaWFsRm9ybXMubGlzdCgpO1xuICAgIGxldCB0aGVfYWNjID0gYWNjO1xuXG4gICAgZm9yICh2YXIgaSA9IDA7IGkgPCB0aGlzLmNvdW50KGNvbGxlY3Rpb24pOyBpKyspIHtcbiAgICAgIGxldCB0dXBsZSA9IGZ1bihjb2xsZWN0aW9uW2ldLCB0aGVfYWNjKTtcblxuICAgICAgdGhlX2FjYyA9IEtlcm5lbC5lbGVtKHR1cGxlLCAxKTtcbiAgICAgIG1hcHBlZCA9IEtlcm5lbC5TcGVjaWFsRm9ybXMubGlzdCguLi5tYXBwZWQuY29uY2F0KFtLZXJuZWwuZWxlbSh0dXBsZSwgMCldKSk7XG4gICAgfVxuXG4gICAgcmV0dXJuIEtlcm5lbC5TcGVjaWFsRm9ybXMudHVwbGUobWFwcGVkLCB0aGVfYWNjKTtcbiAgfSxcblxuICBtZW1iZXI6IGZ1bmN0aW9uIChjb2xsZWN0aW9uLCB2YWx1ZSkge1xuICAgIHJldHVybiBjb2xsZWN0aW9uLmluY2x1ZGVzKHZhbHVlKTtcbiAgfSxcblxuICByZWR1Y2U6IGZ1bmN0aW9uIChjb2xsZWN0aW9uLCBhY2MsIGZ1bikge1xuICAgIGxldCB0aGVfYWNjID0gYWNjO1xuXG4gICAgZm9yICh2YXIgaSA9IDA7IGkgPCB0aGlzLmNvdW50KGNvbGxlY3Rpb24pOyBpKyspIHtcbiAgICAgIGxldCB0dXBsZSA9IGZ1bihjb2xsZWN0aW9uW2ldLCB0aGVfYWNjKTtcblxuICAgICAgdGhlX2FjYyA9IEtlcm5lbC5lbGVtKHR1cGxlLCAxKTtcbiAgICB9XG5cbiAgICByZXR1cm4gdGhlX2FjYztcbiAgfSxcblxuICB0YWtlOiBmdW5jdGlvbiAoY29sbGVjdGlvbiwgY291bnQpIHtcbiAgICByZXR1cm4gY29sbGVjdGlvbi5zbGljZSgwLCBjb3VudCk7XG4gIH0sXG5cbiAgdGFrZV9ldmVyeTogZnVuY3Rpb24gKGNvbGxlY3Rpb24sIG50aCkge1xuICAgIGxldCByZXN1bHQgPSBbXTtcbiAgICBsZXQgaW5kZXggPSAwO1xuXG4gICAgZm9yIChsZXQgZWxlbSBvZiBjb2xsZWN0aW9uKSB7XG4gICAgICBpZiAoaW5kZXggJSBudGggPT09IDApIHtcbiAgICAgICAgcmVzdWx0LnB1c2goZWxlbSk7XG4gICAgICB9XG4gICAgfVxuXG4gICAgcmV0dXJuIEtlcm5lbC5TcGVjaWFsRm9ybXMubGlzdCguLi5yZXN1bHQpO1xuICB9LFxuXG4gIHRha2Vfd2hpbGU6IGZ1bmN0aW9uIChjb2xsZWN0aW9uLCBmdW4pIHtcbiAgICBsZXQgY291bnQgPSAwO1xuXG4gICAgZm9yIChsZXQgZWxlbSBvZiBjb2xsZWN0aW9uKSB7XG4gICAgICBpZiAoZnVuKGVsZW0pKSB7XG4gICAgICAgIGNvdW50ID0gY291bnQgKyAxO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgYnJlYWs7XG4gICAgICB9XG4gICAgfVxuXG4gICAgcmV0dXJuIGNvbGxlY3Rpb24uc2xpY2UoMCwgY291bnQpO1xuICB9LFxuXG4gIHRvX2xpc3Q6IGZ1bmN0aW9uIChjb2xsZWN0aW9uKSB7XG4gICAgcmV0dXJuIGNvbGxlY3Rpb247XG4gIH1cbn07XG5cbmxldCBBdG9tID0ge307XG5cbkF0b20udG9fc3RyaW5nID0gZnVuY3Rpb24gKGF0b20pIHtcbiAgcmV0dXJuIFN5bWJvbC5rZXlGb3IoYXRvbSk7XG59O1xuXG5BdG9tLnRvX2NoYXJfbGlzdCA9IGZ1bmN0aW9uIChhdG9tKSB7XG4gIHJldHVybiBBdG9tLnRvX3N0cmluZyhhdG9tKS5zcGxpdCgnJyk7XG59O1xuXG5sZXQgSW50ZWdlciA9IHtcblxuICBpc19ldmVuOiBmdW5jdGlvbiAobikge1xuICAgIHJldHVybiBuICUgMiA9PT0gMDtcbiAgfSxcblxuICBpc19vZGQ6IGZ1bmN0aW9uIChuKSB7XG4gICAgcmV0dXJuIG4gJSAyICE9PSAwO1xuICB9LFxuXG4gIHBhcnNlOiBmdW5jdGlvbiAoYmluKSB7XG4gICAgbGV0IHJlc3VsdCA9IHBhcnNlSW50KGJpbik7XG5cbiAgICBpZiAoaXNOYU4ocmVzdWx0KSkge1xuICAgICAgcmV0dXJuIEtlcm5lbC5TcGVjaWFsRm9ybXMuYXRvbShcImVycm9yXCIpO1xuICAgIH1cblxuICAgIGxldCBpbmRleE9mRG90ID0gYmluLmluZGV4T2YoXCIuXCIpO1xuXG4gICAgaWYgKGluZGV4T2ZEb3QgPj0gMCkge1xuICAgICAgcmV0dXJuIEtlcm5lbC5TcGVjaWFsRm9ybXMudHVwbGUocmVzdWx0LCBiaW4uc3Vic3RyaW5nKGluZGV4T2ZEb3QpKTtcbiAgICB9XG5cbiAgICByZXR1cm4gS2VybmVsLlNwZWNpYWxGb3Jtcy50dXBsZShyZXN1bHQsIFwiXCIpO1xuICB9LFxuXG4gIHRvX2NoYXJfbGlzdDogZnVuY3Rpb24gKG51bWJlciwgYmFzZSA9IDEwKSB7XG4gICAgcmV0dXJuIG51bWJlci50b1N0cmluZyhiYXNlKS5zcGxpdChcIlwiKTtcbiAgfSxcblxuICB0b19zdHJpbmc6IGZ1bmN0aW9uIChudW1iZXIsIGJhc2UgPSAxMCkge1xuICAgIHJldHVybiBudW1iZXIudG9TdHJpbmcoYmFzZSk7XG4gIH1cbn07XG5cbmxldCBfQ2hhcnMgPSBLZXJuZWwuZGVmcHJvdG9jb2woe1xuICB0b19zdHJpbmc6IGZ1bmN0aW9uICh0aGluZykge31cbn0pO1xuXG5LZXJuZWwuZGVmaW1wbChfQ2hhcnMsIEJpdFN0cmluZywge1xuICB0b19zdHJpbmc6IGZ1bmN0aW9uICh0aGluZykge1xuICAgIGlmIChLZXJuZWwuaXNfYmluYXJ5KHRoaW5nKSkge1xuICAgICAgcmV0dXJuIHRoaW5nO1xuICAgIH1cblxuICAgIHJldHVybiB0aGluZy50b1N0cmluZygpO1xuICB9XG59KTtcblxuS2VybmVsLmRlZmltcGwoX0NoYXJzLCBTeW1ib2wsIHtcbiAgdG9fc3RyaW5nOiBmdW5jdGlvbiAodGhpbmcpIHtcbiAgICBpZiAobmlsKSB7XG4gICAgICByZXR1cm4gXCJcIjtcbiAgICB9XG5cbiAgICByZXR1cm4gQXRvbS50b19zdHJpbmcodGhpbmcpO1xuICB9XG59KTtcblxuS2VybmVsLmRlZmltcGwoX0NoYXJzLCBJbnRlZ2VyVHlwZSwge1xuICB0b19zdHJpbmc6IGZ1bmN0aW9uICh0aGluZykge1xuICAgIHJldHVybiBJbnRlZ2VyLnRvX3N0cmluZyh0aGluZyk7XG4gIH1cbn0pO1xuXG5LZXJuZWwuZGVmaW1wbChfQ2hhcnMsIEZsb2F0VHlwZSwge1xuICB0b19zdHJpbmc6IGZ1bmN0aW9uICh0aGluZykge1xuICAgIHJldHVybiB0aGluZy50b1N0cmluZztcbiAgfVxufSk7XG5cbktlcm5lbC5kZWZpbXBsKF9DaGFycywgQXJyYXksIHtcbiAgdG9fc3RyaW5nOiBmdW5jdGlvbiAodGhpbmcpIHtcbiAgICByZXR1cm4gdGhpbmcudG9TdHJpbmcoKTtcbiAgfVxufSk7XG5cbktlcm5lbC5kZWZpbXBsKF9DaGFycywgVHVwbGUsIHtcbiAgdG9fc3RyaW5nOiBmdW5jdGlvbiAodGhpbmcpIHtcbiAgICByZXR1cm4gVHVwbGUudG9fc3RyaW5nKHRoaW5nKTtcbiAgfVxufSk7XG5cbktlcm5lbC5kZWZpbXBsKF9DaGFycywgbnVsbCwge1xuICB0b19zdHJpbmc6IGZ1bmN0aW9uICh0aGluZykge1xuICAgIHJldHVybiB0aGluZy50b1N0cmluZygpO1xuICB9XG59KTtcblxuZnVuY3Rpb24gdG9fYXRvbShzdHJpbmcpIHtcbiAgcmV0dXJuIFN5bWJvbC5mb3Ioc3RyaW5nKTtcbn1cblxuZnVuY3Rpb24gdG9fZXhpc3RpbmdfYXRvbShzdHJpbmcpIHtcbiAgcmV0dXJuIFN5bWJvbC5mb3Ioc3RyaW5nKTtcbn1cblxuZnVuY3Rpb24gdG9fY2hhcl9saXN0KHN0cmluZykge1xuICByZXR1cm4gc3RyaW5nLnNwbGl0KCcnKTtcbn1cblxuZnVuY3Rpb24gdG9fZmxvYXQoc3RyaW5nKSB7XG4gIHJldHVybiBwYXJzZUZsb2F0KHN0cmluZyk7XG59XG5cbmZ1bmN0aW9uIHRvX2ludGVnZXIoc3RyaW5nLCBiYXNlID0gMTApIHtcbiAgcmV0dXJuIHBhcnNlSW50KHN0cmluZywgYmFzZSk7XG59XG5cbmZ1bmN0aW9uIHVwY2FzZShiaW5hcnkpIHtcbiAgcmV0dXJuIGJpbmFyeS50b1VwcGVyQ2FzZSgpO1xufVxuXG5mdW5jdGlvbiBkb3duY2FzZShiaW5hcnkpIHtcbiAgcmV0dXJuIGJpbmFyeS50b0xvd2VyQ2FzZSgpO1xufVxuXG5mdW5jdGlvbiBhdChzdHJpbmcsIHBvc2l0aW9uKSB7XG4gIGlmIChwb3NpdGlvbiA+IHN0cmluZy5sZW5ndGggLSAxKSB7XG4gICAgcmV0dXJuIG51bGw7XG4gIH1cblxuICByZXR1cm4gc3RyaW5nW3Bvc2l0aW9uXTtcbn1cblxuZnVuY3Rpb24gY2FwaXRhbGl6ZShzdHJpbmcpIHtcbiAgbGV0IHJldHVyblN0cmluZyA9ICcnO1xuXG4gIGZvciAobGV0IGkgPSAwOyBpIDwgc3RyaW5nLmxlbmd0aDsgaSsrKSB7XG4gICAgaWYgKGkgPT09IDApIHtcbiAgICAgIHJldHVyblN0cmluZyA9IHJldHVyblN0cmluZyArIHN0cmluZ1tpXS50b1VwcGVyQ2FzZSgpO1xuICAgIH0gZWxzZSB7XG4gICAgICByZXR1cm5TdHJpbmcgPSByZXR1cm5TdHJpbmcgKyBzdHJpbmdbaV0udG9Mb3dlckNhc2UoKTtcbiAgICB9XG4gIH1cblxuICByZXR1cm4gcmV0dXJuU3RyaW5nO1xufVxuXG5mdW5jdGlvbiBjb2RlcG9pbnRzKHN0cmluZykge1xuICByZXR1cm4gdG9fY2hhcl9saXN0KHN0cmluZykubWFwKGZ1bmN0aW9uIChjKSB7XG4gICAgcmV0dXJuIGMuY29kZVBvaW50QXQoMCk7XG4gIH0pO1xufVxuXG5mdW5jdGlvbiBjb250YWluc19fcW1fXyhzdHJpbmcsIGNvbnRhaW5zKSB7XG4gIGlmIChBcnJheS5pc0FycmF5KGNvbnRhaW5zKSkge1xuICAgIHJldHVybiBjb250YWlucy5zb21lKGZ1bmN0aW9uIChzKSB7XG4gICAgICByZXR1cm4gc3RyaW5nLmluZGV4T2YocykgPiAtMTtcbiAgICB9KTtcbiAgfVxuXG4gIHJldHVybiBzdHJpbmcuaW5kZXhPZihjb250YWlucykgPiAtMTtcbn1cblxuZnVuY3Rpb24gZHVwbGljYXRlKHN1YmplY3QsIG4pIHtcbiAgcmV0dXJuIHN1YmplY3QucmVwZWF0KG4pO1xufVxuXG5mdW5jdGlvbiBlbmRzX3dpdGhfX3FtX18oc3RyaW5nLCBzdWZmaXhlcykge1xuICBpZiAoQXJyYXkuaXNBcnJheShzdWZmaXhlcykpIHtcbiAgICByZXR1cm4gc3VmZml4ZXMuc29tZShmdW5jdGlvbiAocykge1xuICAgICAgcmV0dXJuIHN0cmluZy5lbmRzV2l0aChzKTtcbiAgICB9KTtcbiAgfVxuXG4gIHJldHVybiBzdHJpbmcuZW5kc1dpdGgoc3VmZml4ZXMpO1xufVxuXG5mdW5jdGlvbiBmaXJzdChzdHJpbmcpIHtcbiAgaWYgKCFzdHJpbmcpIHtcbiAgICByZXR1cm4gbnVsbDtcbiAgfVxuXG4gIHJldHVybiBzdHJpbmdbMF07XG59XG5cbmZ1bmN0aW9uIGdyYXBoZW1lcyhzdHJpbmcpIHtcbiAgcmV0dXJuIHN0cmluZy5zcGxpdCgnJyk7XG59XG5cbmZ1bmN0aW9uIGxhc3Qoc3RyaW5nKSB7XG4gIGlmICghc3RyaW5nKSB7XG4gICAgcmV0dXJuIG51bGw7XG4gIH1cblxuICByZXR1cm4gc3RyaW5nW3N0cmluZy5sZW5ndGggLSAxXTtcbn1cblxuZnVuY3Rpb24gbGVuZ3RoKHN0cmluZykge1xuICByZXR1cm4gc3RyaW5nLmxlbmd0aDtcbn1cblxuZnVuY3Rpb24gbWF0Y2hfX3FtX18oc3RyaW5nLCByZWdleCkge1xuICByZXR1cm4gc3RyaW5nLm1hdGNoKHJlZ2V4KSAhPSBudWxsO1xufVxuXG5mdW5jdGlvbiBuZXh0X2NvZGVwb2ludChzdHJpbmcpIHtcbiAgaWYgKCFzdHJpbmcgfHwgc3RyaW5nID09PSAnJykge1xuICAgIHJldHVybiBudWxsO1xuICB9XG5cbiAgcmV0dXJuIEtlcm5lbC5TcGVjaWFsRm9ybXMudHVwbGUoc3RyaW5nWzBdLmNvZGVQb2ludEF0KDApLCBzdHJpbmcuc3Vic3RyKDEpKTtcbn1cblxuZnVuY3Rpb24gbmV4dF9ncmFwaGVtZShzdHJpbmcpIHtcbiAgaWYgKCFzdHJpbmcgfHwgc3RyaW5nID09PSAnJykge1xuICAgIHJldHVybiBudWxsO1xuICB9XG5cbiAgcmV0dXJuIEtlcm5lbC5TcGVjaWFsRm9ybXMudHVwbGUoc3RyaW5nWzBdLCBzdHJpbmcuc3Vic3RyKDEpKTtcbn1cblxuZnVuY3Rpb24gcmV2ZXJzZShzdHJpbmcpIHtcbiAgbGV0IHJldHVyblZhbHVlID0gJyc7XG5cbiAgZm9yICh2YXIgaSA9IHN0cmluZy5sZW5ndGggLSAxOyBpID49IDA7IGktLSkge1xuICAgIHJldHVyblZhbHVlID0gcmV0dXJuVmFsdWUgKyBzdHJpbmdbaV07XG4gIH07XG5cbiAgcmV0dXJuIHJldHVyblZhbHVlO1xufVxuXG5mdW5jdGlvbiBfc3BsaXQoc3RyaW5nKSB7XG4gIHJldHVybiBzdHJpbmcuc3BsaXQoKTtcbn1cblxuZnVuY3Rpb24gc3RhcnRzX3dpdGhfX3FtX18oc3RyaW5nLCBwcmVmaXhlcykge1xuICBpZiAoQXJyYXkuaXNBcnJheShwcmVmaXhlcykpIHtcbiAgICByZXR1cm4gcHJlZml4ZXMuc29tZShmdW5jdGlvbiAocykge1xuICAgICAgcmV0dXJuIHN0cmluZy5zdGFydHNXaXRoKHMpO1xuICAgIH0pO1xuICB9XG5cbiAgcmV0dXJuIHN0cmluZy5zdGFydHNXaXRoKHByZWZpeGVzKTtcbn1cblxuZnVuY3Rpb24gdmFsaWRfY2hhcmFjdGVyX19xbV9fKGNvZGVwb2ludCkge1xuICB0cnkge1xuICAgIHJldHVybiBTdHJpbmcuZnJvbUNvZGVQb2ludChjb2RlcG9pbnQpICE9IG51bGw7XG4gIH0gY2F0Y2ggKGUpIHtcbiAgICByZXR1cm4gZmFsc2U7XG4gIH1cbn1cblxudmFyIF9TdHJpbmcgPSB7XG4gIGF0LFxuICBjYXBpdGFsaXplLFxuICBjb2RlcG9pbnRzLFxuICBjb250YWluc19fcW1fXyxcbiAgZG93bmNhc2UsXG4gIGR1cGxpY2F0ZSxcbiAgZW5kc193aXRoX19xbV9fLFxuICBmaXJzdCxcbiAgZ3JhcGhlbWVzLFxuICBsYXN0LFxuICBsZW5ndGgsXG4gIG1hdGNoX19xbV9fLFxuICBuZXh0X2NvZGVwb2ludCxcbiAgbmV4dF9ncmFwaGVtZSxcbiAgcmV2ZXJzZSxcbiAgc3BsaXQ6IF9zcGxpdCxcbiAgc3RhcnRzX3dpdGhfX3FtX18sXG4gIHRvX2F0b20sXG4gIHRvX2NoYXJfbGlzdCxcbiAgdG9fZXhpc3RpbmdfYXRvbSxcbiAgdG9fZmxvYXQsXG4gIHRvX2ludGVnZXIsXG4gIHVwY2FzZSxcbiAgdmFsaWRfY2hhcmFjdGVyX19xbV9fLFxuICBDaGFyczogX0NoYXJzXG59O1xuXG5sZXQgQ2hhcnMgPSBLZXJuZWwuZGVmcHJvdG9jb2woe1xuICB0b19jaGFyX2xpc3Q6IGZ1bmN0aW9uICh0aGluZykge31cbn0pO1xuXG5LZXJuZWwuZGVmaW1wbChDaGFycywgS2VybmVsLmlzX2JpdHN0cmluZywge1xuICB0b19jaGFyX2xpc3Q6IGZ1bmN0aW9uICh0aGluZykge1xuICAgIGlmIChLZXJuZWwuaXNfYmluYXJ5KHRoaW5nKSkge1xuICAgICAgcmV0dXJuIF9TdHJpbmcudG9fY2hhcl9saXN0KHRoaW5nKTtcbiAgICB9XG5cbiAgICByZXR1cm4gdGhpbmcudG9TdHJpbmcoKTtcbiAgfVxufSk7XG5cbktlcm5lbC5kZWZpbXBsKENoYXJzLCBLZXJuZWwuaXNfYXRvbSwge1xuICB0b19jaGFyX2xpc3Q6IGZ1bmN0aW9uICh0aGluZykge1xuICAgIHJldHVybiBBdG9tLnRvX2NoYXJfbGlzdCh0aGluZyk7XG4gIH1cbn0pO1xuXG5LZXJuZWwuZGVmaW1wbChDaGFycywgS2VybmVsLmlzX2ludGVnZXIsIHtcbiAgdG9fY2hhcl9saXN0OiBmdW5jdGlvbiAodGhpbmcpIHtcbiAgICByZXR1cm4gSW50ZWdlci50b19jaGFyX2xpc3QodGhpbmcpO1xuICB9XG59KTtcblxuS2VybmVsLmRlZmltcGwoQ2hhcnMsIEtlcm5lbC5pc19saXN0LCB7XG4gIHRvX2NoYXJfbGlzdDogZnVuY3Rpb24gKHRoaW5nKSB7XG4gICAgcmV0dXJuIHRoaW5nO1xuICB9XG59KTtcblxubGV0IExpc3QgPSB7fTtcblxuTGlzdC5DaGFycyA9IENoYXJzO1xuXG5MaXN0LmRlbGV0ZSA9IGZ1bmN0aW9uIChsaXN0LCBpdGVtKSB7XG4gIGxldCBuZXdfdmFsdWUgPSBbXTtcbiAgbGV0IHZhbHVlX2ZvdW5kID0gZmFsc2U7XG5cbiAgZm9yIChsZXQgeCBvZiBsaXN0KSB7XG4gICAgaWYgKHggPT09IGl0ZW0gJiYgdmFsdWVfZm91bmQgIT09IGZhbHNlKSB7XG4gICAgICBuZXdfdmFsdWUucHVzaCh4KTtcbiAgICAgIHZhbHVlX2ZvdW5kID0gdHJ1ZTtcbiAgICB9IGVsc2UgaWYgKHggIT09IGl0ZW0pIHtcbiAgICAgIG5ld192YWx1ZS5wdXNoKHgpO1xuICAgIH1cbiAgfVxuXG4gIHJldHVybiBLZXJuZWwuU3BlY2lhbEZvcm1zLmxpc3QoLi4ubmV3X3ZhbHVlKTtcbn07XG5cbkxpc3QuZGVsZXRlX2F0ID0gZnVuY3Rpb24gKGxpc3QsIGluZGV4KSB7XG4gIGxldCBuZXdfdmFsdWUgPSBbXTtcblxuICBmb3IgKGxldCBpID0gMDsgaSA8IGxpc3QubGVuZ3RoOyBpKyspIHtcbiAgICBpZiAoaSAhPT0gaW5kZXgpIHtcbiAgICAgIG5ld192YWx1ZS5wdXNoKGxpc3RbaV0pO1xuICAgIH1cbiAgfVxuXG4gIHJldHVybiBLZXJuZWwuU3BlY2lhbEZvcm1zLmxpc3QoLi4ubmV3X3ZhbHVlKTtcbn07XG5cbkxpc3QuZHVwbGljYXRlID0gZnVuY3Rpb24gKGVsZW0sIG4pIHtcbiAgbGV0IG5ld192YWx1ZSA9IFtdO1xuXG4gIGZvciAodmFyIGkgPSAwOyBpIDwgbjsgaSsrKSB7XG4gICAgbmV3X3ZhbHVlLnB1c2goZWxlbSk7XG4gIH1cblxuICByZXR1cm4gS2VybmVsLlNwZWNpYWxGb3Jtcy5saXN0KC4uLm5ld192YWx1ZSk7XG59O1xuXG5MaXN0LmZpcnN0ID0gZnVuY3Rpb24gKGxpc3QpIHtcbiAgcmV0dXJuIGxpc3RbMF07XG59O1xuXG5MaXN0LmZsYXR0ZW4gPSBmdW5jdGlvbiAobGlzdCwgdGFpbCA9IEtlcm5lbC5TcGVjaWFsRm9ybXMubGlzdCgpKSB7XG4gIGxldCBuZXdfdmFsdWUgPSBbXTtcblxuICBmb3IgKGxldCB4IG9mIGxpc3QpIHtcbiAgICBpZiAoS2VybmVsLmlzX2xpc3QoeCkpIHtcbiAgICAgIG5ld192YWx1ZSA9IG5ld192YWx1ZS5jb25jYXQoTGlzdC5mbGF0dGVuKHgpKTtcbiAgICB9IGVsc2Uge1xuICAgICAgbmV3X3ZhbHVlLnB1c2goeCk7XG4gICAgfVxuICB9XG5cbiAgbmV3X3ZhbHVlID0gbmV3X3ZhbHVlLmNvbmNhdCh0YWlsKTtcblxuICByZXR1cm4gS2VybmVsLlNwZWNpYWxGb3Jtcy5saXN0KC4uLm5ld192YWx1ZSk7XG59O1xuXG5MaXN0LmZvbGRsID0gZnVuY3Rpb24gKGxpc3QsIGFjYywgZnVuYykge1xuICByZXR1cm4gbGlzdC5yZWR1Y2UoZnVuYywgYWNjKTtcbn07XG5cbkxpc3QuZm9sZHIgPSBmdW5jdGlvbiAobGlzdCwgYWNjLCBmdW5jKSB7XG4gIGxldCBuZXdfYWNjID0gYWNjO1xuXG4gIGZvciAodmFyIGkgPSBsaXN0Lmxlbmd0aCAtIDE7IGkgPj0gMDsgaS0tKSB7XG4gICAgbmV3X2FjYyA9IGZ1bmMobGlzdFtpXSwgbmV3X2FjYyk7XG4gIH1cblxuICByZXR1cm4gbmV3X2FjYztcbn07XG5cbkxpc3QuaW5zZXJ0X2F0ID0gZnVuY3Rpb24gKGxpc3QsIGluZGV4LCB2YWx1ZSkge1xuICBsZXQgbmV3X3ZhbHVlID0gW107XG5cbiAgZm9yIChsZXQgaSA9IDA7IGkgPCBsaXN0Lmxlbmd0aDsgaSsrKSB7XG4gICAgaWYgKGkgPT09IGluZGV4KSB7XG4gICAgICBuZXdfdmFsdWUucHVzaCh2YWx1ZSk7XG4gICAgICBuZXdfdmFsdWUucHVzaChsaXN0W2ldKTtcbiAgICB9IGVsc2Uge1xuICAgICAgbmV3X3ZhbHVlLnB1c2gobGlzdFtpXSk7XG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIEtlcm5lbC5TcGVjaWFsRm9ybXMubGlzdCguLi5uZXdfdmFsdWUpO1xufTtcblxuTGlzdC5rZXlkZWxldGUgPSBmdW5jdGlvbiAobGlzdCwga2V5LCBwb3NpdGlvbikge1xuICBsZXQgbmV3X2xpc3QgPSBbXTtcblxuICBmb3IgKGxldCBpID0gMDsgaSA8IGxpc3QubGVuZ3RoOyBpKyspIHtcbiAgICBpZiAoIUtlcm5lbC5tYXRjaF9fcW1hcmtfXyhsaXN0W2ldW3Bvc2l0aW9uXSwga2V5KSkge1xuICAgICAgbmV3X2xpc3QucHVzaChsaXN0W2ldKTtcbiAgICB9XG4gIH1cblxuICByZXR1cm4gS2VybmVsLlNwZWNpYWxGb3Jtcy5saXN0KC4uLm5ld19saXN0KTtcbn07XG5cbkxpc3Qua2V5ZmluZCA9IGZ1bmN0aW9uIChsaXN0LCBrZXksIHBvc2l0aW9uLCBfZGVmYXVsdCA9IG51bGwpIHtcblxuICBmb3IgKGxldCBpID0gMDsgaSA8IGxpc3QubGVuZ3RoOyBpKyspIHtcbiAgICBpZiAoS2VybmVsLm1hdGNoX19xbWFya19fKGxpc3RbaV1bcG9zaXRpb25dLCBrZXkpKSB7XG4gICAgICByZXR1cm4gbGlzdFtpXTtcbiAgICB9XG4gIH1cblxuICByZXR1cm4gX2RlZmF1bHQ7XG59O1xuXG5MaXN0LmtleW1lbWJlcl9fcW1hcmtfXyA9IGZ1bmN0aW9uIChsaXN0LCBrZXksIHBvc2l0aW9uKSB7XG5cbiAgZm9yIChsZXQgaSA9IDA7IGkgPCBsaXN0Lmxlbmd0aDsgaSsrKSB7XG4gICAgaWYgKEtlcm5lbC5tYXRjaF9fcW1hcmtfXyhsaXN0W2ldW3Bvc2l0aW9uXSwga2V5KSkge1xuICAgICAgcmV0dXJuIHRydWU7XG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIGZhbHNlO1xufTtcblxuTGlzdC5rZXlyZXBsYWNlID0gZnVuY3Rpb24gKGxpc3QsIGtleSwgcG9zaXRpb24sIG5ld190dXBsZSkge1xuICBsZXQgbmV3X2xpc3QgPSBbXTtcblxuICBmb3IgKGxldCBpID0gMDsgaSA8IGxpc3QubGVuZ3RoOyBpKyspIHtcbiAgICBpZiAoIUtlcm5lbC5tYXRjaF9fcW1hcmtfXyhsaXN0W2ldW3Bvc2l0aW9uXSwga2V5KSkge1xuICAgICAgbmV3X2xpc3QucHVzaChsaXN0W2ldKTtcbiAgICB9IGVsc2Uge1xuICAgICAgbmV3X2xpc3QucHVzaChuZXdfdHVwbGUpO1xuICAgIH1cbiAgfVxuXG4gIHJldHVybiBLZXJuZWwuU3BlY2lhbEZvcm1zLmxpc3QoLi4ubmV3X2xpc3QpO1xufTtcblxuTGlzdC5rZXlzb3J0ID0gZnVuY3Rpb24gKGxpc3QsIHBvc2l0aW9uKSB7XG4gIGxldCBuZXdfbGlzdCA9IGxpc3Q7XG5cbiAgbmV3X2xpc3Quc29ydChmdW5jdGlvbiAoYSwgYikge1xuICAgIGlmIChwb3NpdGlvbiA9PT0gMCkge1xuICAgICAgaWYgKGFbcG9zaXRpb25dLnZhbHVlIDwgYltwb3NpdGlvbl0udmFsdWUpIHtcbiAgICAgICAgcmV0dXJuIC0xO1xuICAgICAgfVxuXG4gICAgICBpZiAoYVtwb3NpdGlvbl0udmFsdWUgPiBiW3Bvc2l0aW9uXS52YWx1ZSkge1xuICAgICAgICByZXR1cm4gMTtcbiAgICAgIH1cblxuICAgICAgcmV0dXJuIDA7XG4gICAgfSBlbHNlIHtcbiAgICAgIGlmIChhW3Bvc2l0aW9uXSA8IGJbcG9zaXRpb25dKSB7XG4gICAgICAgIHJldHVybiAtMTtcbiAgICAgIH1cblxuICAgICAgaWYgKGFbcG9zaXRpb25dID4gYltwb3NpdGlvbl0pIHtcbiAgICAgICAgcmV0dXJuIDE7XG4gICAgICB9XG5cbiAgICAgIHJldHVybiAwO1xuICAgIH1cbiAgfSk7XG5cbiAgcmV0dXJuIEtlcm5lbC5TcGVjaWFsRm9ybXMubGlzdCguLi5uZXdfbGlzdCk7XG59O1xuXG5MaXN0LmtleXN0b3JlID0gZnVuY3Rpb24gKGxpc3QsIGtleSwgcG9zaXRpb24sIG5ld190dXBsZSkge1xuICBsZXQgbmV3X2xpc3QgPSBbXTtcbiAgbGV0IHJlcGxhY2VkID0gZmFsc2U7XG5cbiAgZm9yIChsZXQgaSA9IDA7IGkgPCBsaXN0Lmxlbmd0aDsgaSsrKSB7XG4gICAgaWYgKCFLZXJuZWwubWF0Y2hfX3FtYXJrX18obGlzdFtpXVtwb3NpdGlvbl0sIGtleSkpIHtcbiAgICAgIG5ld19saXN0LnB1c2gobGlzdFtpXSk7XG4gICAgfSBlbHNlIHtcbiAgICAgIG5ld19saXN0LnB1c2gobmV3X3R1cGxlKTtcbiAgICAgIHJlcGxhY2VkID0gdHJ1ZTtcbiAgICB9XG4gIH1cblxuICBpZiAoIXJlcGxhY2VkKSB7XG4gICAgbmV3X2xpc3QucHVzaChuZXdfdHVwbGUpO1xuICB9XG5cbiAgcmV0dXJuIEtlcm5lbC5TcGVjaWFsRm9ybXMubGlzdCguLi5uZXdfbGlzdCk7XG59O1xuXG5MaXN0Lmxhc3QgPSBmdW5jdGlvbiAobGlzdCkge1xuICByZXR1cm4gbGlzdFtsaXN0Lmxlbmd0aCAtIDFdO1xufTtcblxuTGlzdC5yZXBsYWNlX2F0ID0gZnVuY3Rpb24gKGxpc3QsIGluZGV4LCB2YWx1ZSkge1xuICBsZXQgbmV3X3ZhbHVlID0gW107XG5cbiAgZm9yIChsZXQgaSA9IDA7IGkgPCBsaXN0Lmxlbmd0aDsgaSsrKSB7XG4gICAgaWYgKGkgPT09IGluZGV4KSB7XG4gICAgICBuZXdfdmFsdWUucHVzaCh2YWx1ZSk7XG4gICAgfSBlbHNlIHtcbiAgICAgIG5ld192YWx1ZS5wdXNoKGxpc3RbaV0pO1xuICAgIH1cbiAgfVxuXG4gIHJldHVybiBLZXJuZWwuU3BlY2lhbEZvcm1zLmxpc3QoLi4ubmV3X3ZhbHVlKTtcbn07XG5cbkxpc3QudXBkYXRlX2F0ID0gZnVuY3Rpb24gKGxpc3QsIGluZGV4LCBmdW4pIHtcbiAgbGV0IG5ld192YWx1ZSA9IFtdO1xuXG4gIGZvciAobGV0IGkgPSAwOyBpIDwgbGlzdC5jb3VudCgpOyBpKyspIHtcbiAgICBpZiAoaSA9PT0gaW5kZXgpIHtcbiAgICAgIG5ld192YWx1ZS5wdXNoKGZ1bihsaXN0LmdldChpKSkpO1xuICAgIH0gZWxzZSB7XG4gICAgICBuZXdfdmFsdWUucHVzaChsaXN0LmdldChpKSk7XG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIG5ld192YWx1ZTtcbn07XG5cbkxpc3Qud3JhcCA9IGZ1bmN0aW9uIChsaXN0KSB7XG4gIGlmIChLZXJuZWwuaXNfbGlzdChsaXN0KSkge1xuICAgIHJldHVybiBsaXN0O1xuICB9IGVsc2UgaWYgKGxpc3QgPT0gbnVsbCkge1xuICAgIHJldHVybiBLZXJuZWwuU3BlY2lhbEZvcm1zLmxpc3QoKTtcbiAgfSBlbHNlIHtcbiAgICByZXR1cm4gS2VybmVsLlNwZWNpYWxGb3Jtcy5saXN0KGxpc3QpO1xuICB9XG59O1xuXG5MaXN0LnppcCA9IGZ1bmN0aW9uIChsaXN0X29mX2xpc3RzKSB7XG4gIGlmIChsaXN0X29mX2xpc3RzLmxlbmd0aCA9PT0gMCkge1xuICAgIHJldHVybiBLZXJuZWwuU3BlY2lhbEZvcm1zLmxpc3QoKTtcbiAgfVxuXG4gIGxldCBuZXdfdmFsdWUgPSBbXTtcbiAgbGV0IHNtYWxsZXN0X2xlbmd0aCA9IGxpc3Rfb2ZfbGlzdHNbMF07XG5cbiAgZm9yIChsZXQgeCBvZiBsaXN0X29mX2xpc3RzKSB7XG4gICAgaWYgKHgubGVuZ3RoIDwgc21hbGxlc3RfbGVuZ3RoKSB7XG4gICAgICBzbWFsbGVzdF9sZW5ndGggPSB4Lmxlbmd0aDtcbiAgICB9XG4gIH1cblxuICBmb3IgKGxldCBpID0gMDsgaSA8IHNtYWxsZXN0X2xlbmd0aDsgaSsrKSB7XG4gICAgbGV0IGN1cnJlbnRfdmFsdWUgPSBbXTtcbiAgICBmb3IgKGxldCBqID0gMDsgaiA8IGxpc3Rfb2ZfbGlzdHMubGVuZ3RoOyBqKyspIHtcbiAgICAgIGN1cnJlbnRfdmFsdWUucHVzaChsaXN0X29mX2xpc3RzW2pdW2ldKTtcbiAgICB9XG5cbiAgICBuZXdfdmFsdWUucHVzaChLZXJuZWwuU3BlY2lhbEZvcm1zLnR1cGxlKC4uLmN1cnJlbnRfdmFsdWUpKTtcbiAgfVxuXG4gIHJldHVybiBLZXJuZWwuU3BlY2lhbEZvcm1zLmxpc3QoLi4ubmV3X3ZhbHVlKTtcbn07XG5cbkxpc3QudG9fdHVwbGUgPSBmdW5jdGlvbiAobGlzdCkge1xuICByZXR1cm4gS2VybmVsLlNwZWNpYWxGb3Jtcy50dXBsZS5hcHBseShudWxsLCBsaXN0KTtcbn07XG5cbkxpc3QuYXBwZW5kID0gZnVuY3Rpb24gKGxpc3QsIHZhbHVlKSB7XG4gIHJldHVybiBLZXJuZWwuU3BlY2lhbEZvcm1zLmxpc3QoLi4ubGlzdC5jb25jYXQoW3ZhbHVlXSkpO1xufTtcblxuTGlzdC5wcmVwZW5kID0gZnVuY3Rpb24gKGxpc3QsIHZhbHVlKSB7XG4gIHJldHVybiBLZXJuZWwuU3BlY2lhbEZvcm1zLmxpc3QoLi4uW3ZhbHVlXS5jb25jYXQobGlzdCkpO1xufTtcblxuTGlzdC5jb25jYXQgPSBmdW5jdGlvbiAobGVmdCwgcmlnaHQpIHtcbiAgcmV0dXJuIGxlZnQuY29uY2F0KHJpZ2h0KTtcbn07XG5cbmNsYXNzIFNpZ25hbCB7XG5cbiAgY29uc3RydWN0b3IoKSB7XG4gICAgdGhpcy5iaW5kaW5ncyA9IFNwZWNpYWxGb3Jtcy5saXN0KCk7XG4gIH1cblxuICBhZGQobGlzdGVuZXIsIGNvbnRleHQgPSB0aGlzKSB7XG4gICAgdGhpcy5iaW5kaW5ncyA9IExpc3QuYXBwZW5kKHRoaXMuYmluZGluZ3MsIG5ldyBTaWduYWxCaW5kaW5nKHRoaXMsIGxpc3RlbmVyLCBjb250ZXh0KSk7XG4gIH1cblxuICByZW1vdmUobGlzdGVuZXIpIHtcbiAgICB0aGlzLmJpbmRpbmdzID0gRW51bS5maWx0ZXIodGhpcy5iaW5kaW5ncywgZnVuY3Rpb24gKGJpbmRpbmcpIHtcbiAgICAgIHJldHVybiBiaW5kaW5nLmxpc3RlbmVyICE9PSBsaXN0ZW5lcjtcbiAgICB9KTtcbiAgfVxuXG4gIGRpc3BhdGNoKC4uLnBhcmFtcykge1xuICAgIGZvciAobGV0IGJpbmRpbmcgb2YgdGhpcy5iaW5kaW5ncykge1xuICAgICAgYmluZGluZy5leGVjdXRlKC4uLnBhcmFtcyk7XG4gICAgfVxuICB9XG5cbiAgZGlzcG9zZSgpIHtcbiAgICBmb3IgKGxldCBiaW5kaW5nIG9mIHRoaXMuYmluZGluZ3MpIHtcbiAgICAgIGJpbmRpbmcuZGlzcG9zZSgpO1xuICAgIH1cblxuICAgIHRoaXMuYmluZGluZ3MgPSBudWxsO1xuICB9XG59XG5cbmNsYXNzIFNpZ25hbEJpbmRpbmcge1xuXG4gIGNvbnN0cnVjdG9yKHNpZ25hbCwgbGlzdGVuZXIsIGNvbnRleHQpIHtcbiAgICB0aGlzLmxpc3RlbmVyID0gbGlzdGVuZXI7XG4gICAgdGhpcy5zaWduYWwgPSBzaWduYWw7XG4gICAgdGhpcy5jb250ZXh0ID0gY29udGV4dDtcbiAgfVxuXG4gIGV4ZWN1dGUoLi4ucGFyYW1zKSB7XG4gICAgdGhpcy5saXN0ZW5lci5hcHBseSh0aGlzLmNvbnRleHQsIHBhcmFtcyk7XG4gIH1cblxuICBkaXNwb3NlKCkge1xuICAgIHRoaXMubGlzdGVuZXIgPSBudWxsO1xuICAgIHRoaXMuc2lnbmFsID0gbnVsbDtcbiAgICB0aGlzLmNvbnRleHQgPSBudWxsO1xuICB9XG59XG5cbmZ1bmN0aW9uIF9fdXBkYXRlKG1hcCwga2V5LCB2YWx1ZSkge1xuICBsZXQgbSA9IG5ldyBNYXAobWFwKTtcbiAgbS5zZXQoa2V5LCB2YWx1ZSk7XG4gIHJldHVybiBtO1xufVxuXG5mdW5jdGlvbiByZW1vdmUobWFwLCBrZXkpIHtcbiAgbGV0IG0gPSBuZXcgTWFwKG1hcCk7XG4gIG0uZGVsZXRlKGtleSk7XG4gIHJldHVybiBtO1xufVxuXG5jbGFzcyBNYWlsQm94IHtcblxuICBjb25zdHJ1Y3Rvcihjb250ZXh0ID0gdGhpcykge1xuICAgIHRoaXMuc2lnbmFsID0gbmV3IFNpZ25hbCgpO1xuICAgIHRoaXMuc2lnbmFsLmFkZCgoLi4ucGFyYW1zKSA9PiB0aGlzLm1lc3NhZ2VzID0gdGhpcy5tZXNzYWdlcy5jb25jYXQocGFyYW1zKSwgY29udGV4dCk7XG4gICAgdGhpcy5tZXNzYWdlcyA9IFtdO1xuICB9XG5cbiAgcmVjZWl2ZSguLi5tZXNzYWdlcykge1xuICAgIHRoaXMuc2lnbmFsLmRpc3BhdGNoKC4uLm1lc3NhZ2VzKTtcbiAgfVxuXG4gIHBlZWsoKSB7XG4gICAgaWYgKHRoaXMubWVzc2FnZXMubGVuZ3RoID09PSAwKSB7XG4gICAgICByZXR1cm4gbnVsbDtcbiAgICB9XG5cbiAgICByZXR1cm4gdGhpcy5tZXNzYWdlc1swXTtcbiAgfVxuXG4gIHJlYWQoKSB7XG4gICAgbGV0IHJlc3VsdCA9IHRoaXMubWVzc2FnZXNbMF07XG4gICAgdGhpcy5tZXNzYWdlcyA9IHRoaXMubWVzc2FnZXMuc2xpY2UoMSk7XG5cbiAgICByZXR1cm4gcmVzdWx0O1xuICB9XG5cbiAgYWRkX3N1YnNjcmliZXIoZm4sIGNvbnRleHQgPSB0aGlzKSB7XG4gICAgdGhpcy5zaWduYWwuYWRkKGZuLCBjb250ZXh0KTtcbiAgfVxuXG4gIHJlbW92ZV9zdWJzY3JpYmVyKGZuKSB7XG4gICAgdGhpcy5zaWduYWwucmVtb3ZlKGZuKTtcbiAgfVxuXG4gIGRpc3Bvc2UoKSB7XG4gICAgdGhpcy5zaWduYWwuZGlzcG9zZSgpO1xuICAgIHRoaXMubWVzc2FnZXMgPSBudWxsO1xuICB9XG59XG5cbmNsYXNzIFBvc3RPZmZpY2Uge1xuXG4gIGNvbnN0cnVjdG9yKCkge1xuICAgIHRoaXMubWFpbGJveGVzID0gbmV3IE1hcCgpO1xuICB9XG5cbiAgc2VuZChhZGRyZXNzLCBtZXNzYWdlKSB7XG4gICAgdGhpcy5tYWlsYm94ZXMuZ2V0KGFkZHJlc3MpLnJlY2VpdmUobWVzc2FnZSk7XG4gIH1cblxuICByZWNlaXZlKGFkZHJlc3MpIHtcbiAgICByZXR1cm4gdGhpcy5tYWlsYm94ZXMuZ2V0KGFkZHJlc3MpLnJlYWQoKTtcbiAgfVxuXG4gIHBlZWsoYWRkcmVzcykge1xuICAgIHJldHVybiB0aGlzLm1haWxib3hlcy5nZXQoYWRkcmVzcykucGVlaygpO1xuICB9XG5cbiAgYWRkX21haWxib3goYWRkcmVzcyA9IFN5bWJvbCgpLCBjb250ZXh0ID0gdGhpcykge1xuICAgIHRoaXMubWFpbGJveGVzID0gX191cGRhdGUodGhpcy5tYWlsYm94ZXMsIGFkZHJlc3MsIG5ldyBNYWlsQm94KCkpO1xuICAgIHJldHVybiBhZGRyZXNzO1xuICB9XG5cbiAgcmVtb3ZlX21haWxib3goYWRkcmVzcykge1xuICAgIHRoaXMubWFpbGJveGVzLmdldChhZGRyZXNzKS5kaXNwb3NlKCk7XG4gICAgdGhpcy5tYWlsYm94ZXMgPSByZW1vdmUodGhpcy5tYWlsYm94ZXMsIGFkZHJlc3MpO1xuICB9XG5cbiAgc3Vic2NyaWJlKGFkZHJlc3MsIHN1YnNjcmlidGlvbl9mbiwgY29udGV4dCA9IHRoaXMpIHtcbiAgICB0aGlzLm1haWxib3hlcy5nZXQoYWRkcmVzcykuYWRkX3N1YnNjcmliZXIoc3Vic2NyaWJ0aW9uX2ZuLCBjb250ZXh0KTtcbiAgfVxuXG4gIHVuc3Vic2NyaWJlKGFkZHJlc3MsIHN1YnNjcmlidGlvbl9mbikge1xuICAgIHRoaXMubWFpbGJveGVzLmdldChhZGRyZXNzKS5yZW1vdmVfc3Vic2NyaWJlcihzdWJzY3JpYnRpb25fZm4pO1xuICB9XG59XG5cbmZ1bmN0aW9uIGNhbGxfcHJvcGVydHkoaXRlbSwgcHJvcGVydHkpIHtcbiAgaWYgKHByb3BlcnR5IGluIGl0ZW0pIHtcbiAgICBpdGVtW3Byb3BlcnR5XTtcbiAgICBpZiAoaXRlbVtwcm9wZXJ0eV0gaW5zdGFuY2VvZiBGdW5jdGlvbikge1xuICAgICAgcmV0dXJuIGl0ZW1bcHJvcGVydHldKCk7XG4gICAgfSBlbHNlIHtcbiAgICAgIHJldHVybiBpdGVtW3Byb3BlcnR5XTtcbiAgICB9XG4gIH0gZWxzZSBpZiAoU3ltYm9sLmZvcihwcm9wZXJ0eSkgaW4gaXRlbSkge1xuICAgIGxldCBwcm9wID0gU3ltYm9sLmZvcihwcm9wZXJ0eSk7XG4gICAgaWYgKGl0ZW1bcHJvcF0gaW5zdGFuY2VvZiBGdW5jdGlvbikge1xuICAgICAgcmV0dXJuIGl0ZW1bcHJvcF0oKTtcbiAgICB9IGVsc2Uge1xuICAgICAgcmV0dXJuIGl0ZW1bcHJvcF07XG4gICAgfVxuICB9XG5cbiAgdGhyb3cgbmV3IEVycm9yKGBQcm9wZXJ0eSAkeyBwcm9wZXJ0eSB9IG5vdCBmb3VuZCBpbiAkeyBpdGVtIH1gKTtcbn1cblxudmFyIEpTID0ge1xuICBjYWxsX3Byb3BlcnR5XG59O1xuXG5sZXQgUmFuZ2UgPSBmdW5jdGlvbiAoX2ZpcnN0LCBfbGFzdCkge1xuICBpZiAoISh0aGlzIGluc3RhbmNlb2YgUmFuZ2UpKSB7XG4gICAgcmV0dXJuIG5ldyBSYW5nZShfZmlyc3QsIF9sYXN0KTtcbiAgfVxuXG4gIHRoaXMuZmlyc3QgPSBmdW5jdGlvbiAoKSB7XG4gICAgcmV0dXJuIF9maXJzdDtcbiAgfTtcblxuICB0aGlzLmxhc3QgPSBmdW5jdGlvbiAoKSB7XG4gICAgcmV0dXJuIF9sYXN0O1xuICB9O1xuXG4gIGxldCBfcmFuZ2UgPSBbXTtcblxuICBmb3IgKGxldCBpID0gX2ZpcnN0OyBpIDw9IF9sYXN0OyBpKyspIHtcbiAgICBfcmFuZ2UucHVzaChpKTtcbiAgfVxuXG4gIF9yYW5nZSA9IE9iamVjdC5mcmVlemUoX3JhbmdlKTtcblxuICB0aGlzLnZhbHVlID0gZnVuY3Rpb24gKCkge1xuICAgIHJldHVybiBfcmFuZ2U7XG4gIH07XG5cbiAgdGhpcy5sZW5ndGggPSBmdW5jdGlvbiAoKSB7XG4gICAgcmV0dXJuIF9yYW5nZS5sZW5ndGg7XG4gIH07XG5cbiAgcmV0dXJuIHRoaXM7XG59O1xuXG5SYW5nZS5wcm90b3R5cGVbU3ltYm9sLml0ZXJhdG9yXSA9IGZ1bmN0aW9uICgpIHtcbiAgcmV0dXJuIHRoaXMudmFsdWUoKVtTeW1ib2wuaXRlcmF0b3JdKCk7XG59O1xuXG5SYW5nZS5uZXcgPSBmdW5jdGlvbiAoZmlyc3QsIGxhc3QpIHtcbiAgcmV0dXJuIFJhbmdlKGZpcnN0LCBsYXN0KTtcbn07XG5cblJhbmdlLnJhbmdlX19xbWFya19fID0gZnVuY3Rpb24gKHJhbmdlKSB7XG4gIHJldHVybiByYW5nZSBpbnN0YW5jZW9mIFJhbmdlO1xufTtcblxubGV0IEtleXdvcmQgPSB7fTtcblxuS2V5d29yZC5oYXNfa2V5X19xbV9fID0gZnVuY3Rpb24gKGtleXdvcmRzLCBrZXkpIHtcbiAgZm9yIChsZXQga2V5d29yZCBvZiBrZXl3b3Jkcykge1xuICAgIGlmIChLZXJuZWwuZWxlbShrZXl3b3JkLCAwKSA9PSBrZXkpIHtcbiAgICAgIHJldHVybiB0cnVlO1xuICAgIH1cbiAgfVxuXG4gIHJldHVybiBmYWxzZTtcbn07XG5cbktleXdvcmQuZ2V0ID0gZnVuY3Rpb24gKGtleXdvcmRzLCBrZXksIHRoZV9kZWZhdWx0ID0gbnVsbCkge1xuICBmb3IgKGxldCBrZXl3b3JkIG9mIGtleXdvcmRzKSB7XG4gICAgaWYgKEtlcm5lbC5lbGVtKGtleXdvcmQsIDApID09IGtleSkge1xuICAgICAgcmV0dXJuIEtlcm5lbC5lbGVtKGtleXdvcmQsIDEpO1xuICAgIH1cbiAgfVxuXG4gIHJldHVybiB0aGVfZGVmYXVsdDtcbn07XG5cbmxldCBBZ2VudCA9IHt9O1xuXG5BZ2VudC5zdGFydCA9IGZ1bmN0aW9uIChmdW4sIG9wdGlvbnMgPSBbXSkge1xuICBjb25zdCBuYW1lID0gS2V5d29yZC5oYXNfa2V5X19xbV9fKG9wdGlvbnMsIEtlcm5lbC5TcGVjaWFsRm9ybXMuYXRvbSgnbmFtZScpKSA/IEtleXdvcmQuZ2V0KG9wdGlvbnMsIEtlcm5lbC5TcGVjaWFsRm9ybXMuYXRvbSgnbmFtZScpKSA6IFN5bWJvbCgpO1xuXG4gIHNlbGYucG9zdF9vZmZpY2UuYWRkX21haWxib3gobmFtZSk7XG4gIHNlbGYucG9zdF9vZmZpY2Uuc2VuZChuYW1lLCBmdW4oKSk7XG5cbiAgcmV0dXJuIEtlcm5lbC5TcGVjaWFsRm9ybXMudHVwbGUoS2VybmVsLlNwZWNpYWxGb3Jtcy5hdG9tKCdvaycpLCBuYW1lKTtcbn07XG5cbkFnZW50LnN0b3AgPSBmdW5jdGlvbiAoYWdlbnQsIHRpbWVvdXQgPSA1MDAwKSB7XG4gIHNlbGYucG9zdF9vZmZpY2UucmVtb3ZlX21haWxib3goYWdlbnQpO1xuICByZXR1cm4gS2VybmVsLlNwZWNpYWxGb3Jtcy5hdG9tKCdvaycpO1xufTtcblxuQWdlbnQudXBkYXRlID0gZnVuY3Rpb24gKGFnZW50LCBmdW4sIHRpbWVvdXQgPSA1MDAwKSB7XG5cbiAgY29uc3QgY3VycmVudF9zdGF0ZSA9IHNlbGYucG9zdF9vZmZpY2UucmVjZWl2ZShhZ2VudCk7XG4gIHNlbGYucG9zdF9vZmZpY2Uuc2VuZChhZ2VudCwgZnVuKGN1cnJlbnRfc3RhdGUpKTtcblxuICByZXR1cm4gS2VybmVsLlNwZWNpYWxGb3Jtcy5hdG9tKCdvaycpO1xufTtcblxuQWdlbnQuZ2V0ID0gZnVuY3Rpb24gKGFnZW50LCBmdW4sIHRpbWVvdXQgPSA1MDAwKSB7XG4gIHJldHVybiBmdW4oc2VsZi5wb3N0X29mZmljZS5wZWVrKGFnZW50KSk7XG59O1xuXG5BZ2VudC5nZXRfYW5kX3VwZGF0ZSA9IGZ1bmN0aW9uIChhZ2VudCwgZnVuLCB0aW1lb3V0ID0gNTAwMCkge1xuXG4gIGNvbnN0IGdldF9hbmRfdXBkYXRlX3R1cGxlID0gZnVuKHNlbGYucG9zdF9vZmZpY2UucmVjZWl2ZShhZ2VudCkpO1xuICBzZWxmLnBvc3Rfb2ZmaWNlLnNlbmQoYWdlbnQsIEtlcm5lbC5lbGVtKGdldF9hbmRfdXBkYXRlX3R1cGxlLCAxKSk7XG5cbiAgcmV0dXJuIEtlcm5lbC5lbGVtKGdldF9hbmRfdXBkYXRlX3R1cGxlLCAwKTtcbn07XG5cbi8vaHR0cHM6Ly9kZXZlbG9wZXIubW96aWxsYS5vcmcvZW4tVVMvZG9jcy9XZWIvQVBJL1dpbmRvd0Jhc2U2NC9CYXNlNjRfZW5jb2RpbmdfYW5kX2RlY29kaW5nI1NvbHV0aW9uXzJfJUUyJTgwJTkzX3Jld3JpdGVfdGhlX0RPTXNfYXRvYigpX2FuZF9idG9hKClfdXNpbmdfSmF2YVNjcmlwdCdzX1R5cGVkQXJyYXlzX2FuZF9VVEYtOFxuZnVuY3Rpb24gYjY0RW5jb2RlVW5pY29kZShzdHIpIHtcbiAgcmV0dXJuIGJ0b2EoZW5jb2RlVVJJQ29tcG9uZW50KHN0cikucmVwbGFjZSgvJShbMC05QS1GXXsyfSkvZywgZnVuY3Rpb24gKG1hdGNoLCBwMSkge1xuICAgIHJldHVybiBTdHJpbmcuZnJvbUNoYXJDb2RlKCcweCcgKyBwMSk7XG4gIH0pKTtcbn1cblxuZnVuY3Rpb24gZW5jb2RlNjQoZGF0YSkge1xuICByZXR1cm4gYjY0RW5jb2RlVW5pY29kZShkYXRhKTtcbn1cblxuZnVuY3Rpb24gZGVjb2RlNjQoZGF0YSkge1xuICB0cnkge1xuICAgIHJldHVybiBLZXJuZWwuU3BlY2lhbEZvcm1zLnR1cGxlKEtlcm5lbC5TcGVjaWFsRm9ybXMuYXRvbSgnb2snKSwgYXRvYihkYXRhKSk7XG4gIH0gY2F0Y2ggKGUpIHtcbiAgICByZXR1cm4gS2VybmVsLlNwZWNpYWxGb3Jtcy5hdG9tKCdlcnJvcicpO1xuICB9XG4gIHJldHVybiBidG9hKGRhdGEpO1xufVxuXG5mdW5jdGlvbiBkZWNvZGU2NF9fZW1fXyhkYXRhKSB7XG4gIHJldHVybiBhdG9iKGRhdGEpO1xufVxuXG52YXIgQmFzZSA9IHtcbiAgZW5jb2RlNjQsXG4gIGRlY29kZTY0LFxuICBkZWNvZGU2NF9fZW1fX1xufTtcblxuZnVuY3Rpb24gYm5vdChleHByKSB7XG4gIHJldHVybiB+ZXhwcjtcbn1cblxuZnVuY3Rpb24gYmFuZChsZWZ0LCByaWdodCkge1xuICByZXR1cm4gbGVmdCAmIHJpZ2h0O1xufVxuXG5mdW5jdGlvbiBib3IobGVmdCwgcmlnaHQpIHtcbiAgcmV0dXJuIGxlZnQgfCByaWdodDtcbn1cblxuZnVuY3Rpb24gYnNsKGxlZnQsIHJpZ2h0KSB7XG4gIHJldHVybiBsZWZ0IDw8IHJpZ2h0O1xufVxuXG5mdW5jdGlvbiBic3IobGVmdCwgcmlnaHQpIHtcbiAgcmV0dXJuIGxlZnQgPj4gcmlnaHQ7XG59XG5cbmZ1bmN0aW9uIGJ4b3IobGVmdCwgcmlnaHQpIHtcbiAgcmV0dXJuIGxlZnQgXiByaWdodDtcbn1cblxudmFyIEJpdHdpc2UgPSB7XG4gIGJub3QsXG4gIGJhbmQsXG4gIGJvcixcbiAgYnNsLFxuICBic3IsXG4gIGJ4b3Jcbn07XG5cbmxldCBFbnVtZXJhYmxlID0gS2VybmVsLmRlZnByb3RvY29sKHtcbiAgY291bnQ6IGZ1bmN0aW9uIChjb2xsZWN0aW9uKSB7fSxcbiAgbWVtYmVyX3FtYXJrX186IGZ1bmN0aW9uIChjb2xsZWN0aW9uLCB2YWx1ZSkge30sXG4gIHJlZHVjZTogZnVuY3Rpb24gKGNvbGxlY3Rpb24sIGFjYywgZnVuKSB7fVxufSk7XG5cbmxldCBDb2xsZWN0YWJsZSA9IEtlcm5lbC5kZWZwcm90b2NvbCh7XG4gIGludG86IGZ1bmN0aW9uIChjb2xsZWN0YWJsZSkge31cbn0pO1xuXG5sZXQgSW5zcGVjdCA9IEtlcm5lbC5kZWZwcm90b2NvbCh7XG4gIGluc3BlY3Q6IGZ1bmN0aW9uICh0aGluZywgb3B0cykge31cbn0pO1xuXG5mdW5jdGlvbiBfX19uZXdfXygpIHtcbiAgcmV0dXJuIFNwZWNpYWxGb3Jtcy5tYXAoe30pO1xufVxuXG5mdW5jdGlvbiBrZXlzKG1hcCkge1xuICByZXR1cm4gT2JqZWN0LmtleXMobWFwKTtcbn1cblxuZnVuY3Rpb24gX19zaXplKG1hcCkge1xuICByZXR1cm4ga2V5cyhtYXApLmxlbmd0aDtcbn1cblxuZnVuY3Rpb24gX190b19saXN0KG1hcCkge1xuICBsZXQgbWFwX2tleXMgPSBrZXlzKG1hcCk7XG4gIGxldCBsaXN0ID0gW107XG5cbiAgZm9yIChsZXQga2V5IG9mIG1hcF9rZXlzKSB7XG4gICAgbGlzdC5wdXNoKFNwZWNpYWxGb3Jtcy50dXBsZShrZXksIG1hcFtrZXldKSk7XG4gIH1cblxuICByZXR1cm4gU3BlY2lhbEZvcm1zLmxpc3QoLi4ubGlzdCk7XG59XG5cbmZ1bmN0aW9uIHZhbHVlcyhtYXApIHtcbiAgbGV0IG1hcF9rZXlzID0ga2V5cyhtYXApO1xuICBsZXQgbGlzdCA9IFtdO1xuXG4gIGZvciAobGV0IGtleSBvZiBtYXBfa2V5cykge1xuICAgIGxpc3QucHVzaChtYXBba2V5XSk7XG4gIH1cblxuICByZXR1cm4gU3BlY2lhbEZvcm1zLmxpc3QoLi4ubGlzdCk7XG59XG5cbmZ1bmN0aW9uIGZyb21fc3RydWN0KHN0cnVjdCkge1xuICBsZXQgbWFwID0gT2JqZWN0LmFzc2lnbih7fSwgc3RydWN0KTtcbiAgZGVsZXRlIG1hcFtTeW1ib2wuZm9yKFwiX19zdHJ1Y3RfX1wiKV07XG5cbiAgcmV0dXJuIFNwZWNpYWxGb3Jtcy5tYXAobWFwKTtcbn1cblxuZnVuY3Rpb24gX19fX2RlbGV0ZV9fKG1hcCwga2V5KSB7XG4gIGxldCBuZXdfbWFwID0gT2JqZWN0LmFzc2lnbih7fSwgbWFwKTtcblxuICBkZWxldGUgbmV3X21hcFtrZXldO1xuXG4gIHJldHVybiBTcGVjaWFsRm9ybXMubWFwKG5ld19tYXApO1xufVxuXG5mdW5jdGlvbiBkcm9wKG1hcCwga2V5cykge1xuICBsZXQgbmV3X21hcCA9IE9iamVjdC5hc3NpZ24oe30sIG1hcCk7XG5cbiAgZm9yIChsZXQga2V5IG9mIGtleXMpIHtcbiAgICBkZWxldGUgbmV3X21hcFtrZXldO1xuICB9XG5cbiAgcmV0dXJuIFNwZWNpYWxGb3Jtcy5tYXAobmV3X21hcCk7XG59XG5cbmZ1bmN0aW9uIF9fZXF1YWxfX3FtYXJrX18obWFwMSwgbWFwMikge1xuICByZXR1cm4gbWFwMSA9PT0gbWFwMjtcbn1cblxuZnVuY3Rpb24gZmV0Y2hfX2VtYXJrX18obWFwLCBrZXkpIHtcbiAgaWYgKGtleSBpbiBtYXApIHtcbiAgICByZXR1cm4gbWFwW2tleV07XG4gIH1cblxuICB0aHJvdyBuZXcgRXJyb3IoXCJLZXkgbm90IGZvdW5kLlwiKTtcbn1cblxuZnVuY3Rpb24gZmV0Y2gobWFwLCBrZXkpIHtcbiAgaWYgKGtleSBpbiBtYXApIHtcbiAgICByZXR1cm4gU3BlY2lhbEZvcm1zLnR1cGxlKFNwZWNpYWxGb3Jtcy5hdG9tKFwib2tcIiksIG1hcFtrZXldKTtcbiAgfVxuXG4gIHJldHVybiBTcGVjaWFsRm9ybXMuYXRvbShcImVycm9yXCIpO1xufVxuXG5mdW5jdGlvbiBoYXNfa2V5X19xbWFya19fKG1hcCwga2V5KSB7XG4gIHJldHVybiBrZXkgaW4gbWFwO1xufVxuXG5mdW5jdGlvbiBtZXJnZShtYXAxLCBtYXAyKSB7XG4gIHJldHVybiBTcGVjaWFsRm9ybXMubWFwX3VwZGF0ZShtYXAxLCBtYXAyKTtcbn1cblxuZnVuY3Rpb24gc3BsaXQobWFwLCBrZXlzKSB7XG4gIGxldCBzcGxpdDEgPSB7fTtcbiAgbGV0IHNwbGl0MiA9IHt9O1xuXG4gIGZvciAobGV0IGtleSBvZiBPYmplY3Qua2V5cyhtYXApKSB7XG4gICAgaWYgKGtleXMuaW5kZXhPZihrZXkpID4gLTEpIHtcbiAgICAgIHNwbGl0MVtrZXldID0gbWFwW2tleV07XG4gICAgfSBlbHNlIHtcbiAgICAgIHNwbGl0MltrZXldID0gbWFwW2tleV07XG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIFNwZWNpYWxGb3Jtcy50dXBsZShTcGVjaWFsRm9ybXMubWFwKHNwbGl0MSksIFNwZWNpYWxGb3Jtcy5tYXAoc3BsaXQyKSk7XG59XG5cbmZ1bmN0aW9uIHRha2UobWFwLCBrZXlzKSB7XG4gIGxldCBzcGxpdDEgPSB7fTtcblxuICBmb3IgKGxldCBrZXkgb2YgT2JqZWN0LmtleXMobWFwKSkge1xuICAgIGlmIChrZXlzLmluZGV4T2Yoa2V5KSA+IC0xKSB7XG4gICAgICBzcGxpdDFba2V5XSA9IG1hcFtrZXldO1xuICAgIH1cbiAgfVxuXG4gIHJldHVybiBTcGVjaWFsRm9ybXMubWFwKHNwbGl0MSk7XG59XG5cbmZ1bmN0aW9uIGRyb3AobWFwLCBrZXlzKSB7XG4gIGxldCBzcGxpdDEgPSB7fTtcblxuICBmb3IgKGxldCBrZXkgb2YgT2JqZWN0LmtleXMobWFwKSkge1xuICAgIGlmIChrZXlzLmluZGV4T2Yoa2V5KSA9PT0gLTEpIHtcbiAgICAgIHNwbGl0MVtrZXldID0gbWFwW2tleV07XG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIFNwZWNpYWxGb3Jtcy5tYXAoc3BsaXQxKTtcbn1cblxuZnVuY3Rpb24gcHV0X25ldyhtYXAsIGtleSwgdmFsdWUpIHtcbiAgaWYgKGtleSBpbiBtYXApIHtcbiAgICByZXR1cm4gbWFwO1xuICB9XG5cbiAgbGV0IG5ld19tYXAgPSBPYmplY3QuYXNzaWduKHt9LCBtYXApO1xuICBuZXdfbWFwW2tleV0gPSB2YWx1ZTtcblxuICByZXR1cm4gU3BlY2lhbEZvcm1zLm1hcChuZXdfbWFwKTtcbn1cblxuZnVuY3Rpb24gcHV0X25ld19sYXp5KG1hcCwga2V5LCBmdW4pIHtcbiAgaWYgKGtleSBpbiBtYXApIHtcbiAgICByZXR1cm4gbWFwO1xuICB9XG5cbiAgbGV0IG5ld19tYXAgPSBPYmplY3QuYXNzaWduKHt9LCBtYXApO1xuICBuZXdfbWFwW2tleV0gPSBmdW4oKTtcblxuICByZXR1cm4gU3BlY2lhbEZvcm1zLm1hcChuZXdfbWFwKTtcbn1cblxuZnVuY3Rpb24gZ2V0X2FuZF91cGRhdGUobWFwLCBrZXksIGZ1bikge1xuICBpZiAoa2V5IGluIG1hcCkge1xuICAgIHJldHVybiBtYXA7XG4gIH1cblxuICBsZXQgbmV3X21hcCA9IE9iamVjdC5hc3NpZ24oe30sIG1hcCk7XG4gIG5ld19tYXBba2V5XSA9IGZ1bihtYXBba2V5XSk7XG5cbiAgcmV0dXJuIFNwZWNpYWxGb3Jtcy5tYXAobmV3X21hcCk7XG59XG5cbmZ1bmN0aW9uIHBvcF9sYXp5KG1hcCwga2V5LCBmdW4pIHtcbiAgaWYgKCFrZXkgaW4gbWFwKSB7XG4gICAgcmV0dXJuIFNwZWNpYWxGb3Jtcy50dXBsZShmdW4oKSwgbWFwKTtcbiAgfVxuXG4gIGxldCBuZXdfbWFwID0gT2JqZWN0LmFzc2lnbih7fSwgbWFwKTtcbiAgbGV0IHZhbHVlID0gZnVuKG5ld19tYXBba2V5XSk7XG4gIGRlbGV0ZSBuZXdfbWFwW2tleV07XG5cbiAgcmV0dXJuIFNwZWNpYWxGb3Jtcy50dXBsZSh2YWx1ZSwgbmV3X21hcCk7XG59XG5cbmZ1bmN0aW9uIHBvcChtYXAsIGtleSwgX2RlZmF1bHQgPSBudWxsKSB7XG4gIGlmICgha2V5IGluIG1hcCkge1xuICAgIHJldHVybiBTcGVjaWFsRm9ybXMudHVwbGUoX2RlZmF1bHQsIG1hcCk7XG4gIH1cblxuICBsZXQgbmV3X21hcCA9IE9iamVjdC5hc3NpZ24oe30sIG1hcCk7XG4gIGxldCB2YWx1ZSA9IG5ld19tYXBba2V5XTtcbiAgZGVsZXRlIG5ld19tYXBba2V5XTtcblxuICByZXR1cm4gU3BlY2lhbEZvcm1zLnR1cGxlKHZhbHVlLCBuZXdfbWFwKTtcbn1cblxuZnVuY3Rpb24gZ2V0X2xhenkobWFwLCBrZXksIGZ1bikge1xuICBpZiAoIWtleSBpbiBtYXApIHtcbiAgICByZXR1cm4gZnVuKCk7XG4gIH1cblxuICByZXR1cm4gZnVuKG1hcFtrZXldKTtcbn1cblxuZnVuY3Rpb24gZ2V0KG1hcCwga2V5LCBfZGVmYXVsdCA9IG51bGwpIHtcbiAgaWYgKCFrZXkgaW4gbWFwKSB7XG4gICAgcmV0dXJuIF9kZWZhdWx0O1xuICB9XG5cbiAgcmV0dXJuIG1hcFtrZXldO1xufVxuXG5mdW5jdGlvbiBfX3B1dChtYXAsIGtleSwgdmFsKSB7XG4gIGxldCBuZXdfbWFwID0gT2JqZWN0KHt9LCBtYXApO1xuICBuZXdfbWFwW2tleV0gPSB2YWw7XG5cbiAgcmV0dXJuIFNwZWNpYWxGb3Jtcy5tYXAobmV3X21hcCk7XG59XG5cbmZ1bmN0aW9uIHVwZGF0ZV9fZW1hcmtfXyhtYXAsIGtleSwgZnVuKSB7XG4gIGlmICgha2V5IGluIG1hcCkge1xuICAgIHRocm93IG5ldyBFcnJvcihcIktleSBub3QgZm91bmRcIik7XG4gIH1cblxuICBsZXQgbmV3X21hcCA9IE9iamVjdCh7fSwgbWFwKTtcbiAgbmV3X21hcFtrZXldID0gZnVuKG1hcFtrZXldKTtcblxuICByZXR1cm4gU3BlY2lhbEZvcm1zLm1hcChuZXdfbWFwKTtcbn1cblxuZnVuY3Rpb24gX3VwZGF0ZShtYXAsIGtleSwgaW5pdGlhbCwgZnVuKSB7XG4gIGxldCBuZXdfbWFwID0gT2JqZWN0KHt9LCBtYXApO1xuXG4gIGlmICgha2V5IGluIG1hcCkge1xuICAgIG5ld19tYXBba2V5XSA9IGluaXRpYWw7XG4gIH0gZWxzZSB7XG4gICAgbmV3X21hcFtrZXldID0gZnVuKG1hcFtrZXldKTtcbiAgfVxuXG4gIHJldHVybiBTcGVjaWFsRm9ybXMubWFwKG5ld19tYXApO1xufVxuXG52YXIgX01hcCA9IHtcbiAgbmV3OiBfX19uZXdfXyxcbiAga2V5cyxcbiAgc2l6ZTogX19zaXplLFxuICB0b19saXN0OiBfX3RvX2xpc3QsXG4gIHZhbHVlcyxcbiAgZnJvbV9zdHJ1Y3QsXG4gIGRlbGV0ZTogX19fX2RlbGV0ZV9fLFxuICBkcm9wLFxuICBlcXVhbF9fcW1hcmtfXzogX19lcXVhbF9fcW1hcmtfXyxcbiAgZmV0Y2hfX2VtYXJrX18sXG4gIGZldGNoLFxuICBoYXNfa2V5X19xbWFya19fLFxuICBzcGxpdCxcbiAgdGFrZSxcbiAgcHV0X25ldyxcbiAgcHV0X25ld19sYXp5LFxuICBnZXRfYW5kX3VwZGF0ZSxcbiAgcG9wX2xhenksXG4gIHBvcCxcbiAgZ2V0X2xhenksXG4gIGdldCxcbiAgcHV0OiBfX3B1dCxcbiAgdXBkYXRlX19lbWFya19fLFxuICB1cGRhdGU6IF91cGRhdGVcbn07XG5cbmZ1bmN0aW9uIF9fbmV3X18oKSB7XG4gIHJldHVybiBTcGVjaWFsRm9ybXMubWFwKHsgW1N5bWJvbC5mb3IoJ19fc3RydWN0X18nKV06IFN5bWJvbC5mb3IoJ01hcFNldCcpLCBzZXQ6IFNwZWNpYWxGb3Jtcy5saXN0KCkgfSk7XG59XG5cbmZ1bmN0aW9uIF9zaXplKG1hcCkge1xuICByZXR1cm4gbWFwLnNldC5sZW5ndGg7XG59XG5cbmZ1bmN0aW9uIF90b19saXN0KG1hcCkge1xuICByZXR1cm4gbWFwLnNldDtcbn1cblxuZnVuY3Rpb24gX19fZGVsZXRlX18oc2V0LCB0ZXJtKSB7XG4gIGxldCBuZXdfbGlzdCA9IExpc3QuZGVsZXRlKHNldC5zZXQsIHRlcm0pO1xuXG4gIGxldCBuZXdfbWFwID0gT2JqZWN0LmFzc2lnbih7fSwgc2V0KTtcbiAgbmV3X21hcC5zZXQgPSBuZXdfbGlzdDtcbiAgcmV0dXJuIFNwZWNpYWxGb3Jtcy5tYXAobmV3X21hcCk7XG59XG5cbmZ1bmN0aW9uIF9wdXQoc2V0LCB0ZXJtKSB7XG4gIGlmIChzZXQuc2V0LmluZGV4T2YodGVybSkgPT09IC0xKSB7XG4gICAgbGV0IG5ld19saXN0ID0gTGlzdC5hcHBlbmQoc2V0LnNldCwgdGVybSk7XG5cbiAgICBsZXQgbmV3X21hcCA9IE9iamVjdC5hc3NpZ24oe30sIHNldCk7XG4gICAgbmV3X21hcC5zZXQgPSBuZXdfbGlzdDtcbiAgICByZXR1cm4gU3BlY2lhbEZvcm1zLm1hcChuZXdfbWFwKTtcbiAgfVxuXG4gIHJldHVybiBzZXQ7XG59XG5cbmZ1bmN0aW9uIF9kaWZmZXJlbmNlKHNldDEsIHNldDIpIHtcbiAgbGV0IG5ld19tYXAgPSBPYmplY3QuYXNzaWduKHt9LCBzZXQxKTtcblxuICBmb3IgKGxldCB2YWwgb2Ygc2V0MS5zZXQpIHtcbiAgICBpZiAoX21lbWJlcl9fcW1hcmtfXyhzZXQyLCB2YWwpKSB7XG4gICAgICBuZXdfbWFwLnNldCA9IExpc3QuZGVsZXRlKG5ld19tYXAuc2V0LCB2YWwpO1xuICAgIH1cbiAgfVxuXG4gIHJldHVybiBTcGVjaWFsRm9ybXMubWFwKG5ld19tYXApO1xufVxuXG5mdW5jdGlvbiBfaW50ZXJzZWN0aW9uKHNldDEsIHNldDIpIHtcbiAgbGV0IG5ld19tYXAgPSBPYmplY3QuYXNzaWduKHt9LCBzZXQxKTtcblxuICBmb3IgKGxldCB2YWwgb2Ygc2V0MS5zZXQpIHtcbiAgICBpZiAoIV9tZW1iZXJfX3FtYXJrX18oc2V0MiwgdmFsKSkge1xuICAgICAgbmV3X21hcC5zZXQgPSBMaXN0LmRlbGV0ZShuZXdfbWFwLnNldCwgdmFsKTtcbiAgICB9XG4gIH1cblxuICByZXR1cm4gU3BlY2lhbEZvcm1zLm1hcChuZXdfbWFwKTtcbn1cblxuZnVuY3Rpb24gX3VuaW9uKHNldDEsIHNldDIpIHtcbiAgbGV0IG5ld19tYXAgPSBzZXQxO1xuXG4gIGZvciAobGV0IHZhbCBvZiBzZXQyLnNldCkge1xuICAgIG5ld19tYXAgPSBfcHV0KG5ld19tYXAsIHZhbCk7XG4gIH1cblxuICByZXR1cm4gU3BlY2lhbEZvcm1zLm1hcChuZXdfbWFwKTtcbn1cblxuZnVuY3Rpb24gX2Rpc2pvaW5fX3FtYXJrX18oc2V0MSwgc2V0Mikge1xuICBmb3IgKGxldCB2YWwgb2Ygc2V0MS5zZXQpIHtcbiAgICBpZiAoX21lbWJlcl9fcW1hcmtfXyhzZXQyLCB2YWwpKSB7XG4gICAgICByZXR1cm4gZmFsc2U7XG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIHRydWU7XG59XG5cbmZ1bmN0aW9uIF9tZW1iZXJfX3FtYXJrX18oc2V0LCB2YWx1ZSkge1xuICByZXR1cm4gc2V0LnNldC5pbmRleE9mKHZhbHVlKSA+PSAwO1xufVxuXG5mdW5jdGlvbiBfZXF1YWxfX3FtYXJrX18oc2V0MSwgc2V0Mikge1xuICByZXR1cm4gc2V0MS5zZXQgPT09IHNldDIuc2V0O1xufVxuXG5mdW5jdGlvbiBfc3Vic2V0X19xbWFya19fKHNldDEsIHNldDIpIHtcbiAgZm9yIChsZXQgdmFsIG9mIHNldDEuc2V0KSB7XG4gICAgaWYgKCFfbWVtYmVyX19xbWFya19fKHNldDIsIHZhbCkpIHtcbiAgICAgIHJldHVybiBmYWxzZTtcbiAgICB9XG4gIH1cblxuICByZXR1cm4gdHJ1ZTtcbn1cblxudmFyIE1hcFNldCA9IHtcbiAgbmV3OiBfX25ld19fLFxuICBzaXplOiBfc2l6ZSxcbiAgdG9fbGlzdDogX3RvX2xpc3QsXG4gIGRpc2pvaW5fX3FtYXJrX186IF9kaXNqb2luX19xbWFya19fLFxuICBkZWxldGU6IF9fX2RlbGV0ZV9fLFxuICBzdWJzZXRfX3FtYXJrX186IF9zdWJzZXRfX3FtYXJrX18sXG4gIGVxdWFsX19xbWFya19fOiBfZXF1YWxfX3FtYXJrX18sXG4gIG1lbWJlcl9fcW1hcmtfXzogX21lbWJlcl9fcW1hcmtfXyxcbiAgcHV0OiBfcHV0LFxuICB1bmlvbjogX3VuaW9uLFxuICBpbnRlcnNlY3Rpb246IF9pbnRlcnNlY3Rpb24sXG4gIGRpZmZlcmVuY2U6IF9kaWZmZXJlbmNlXG59O1xuXG5mdW5jdGlvbiBzaXplKG1hcCkge1xuICByZXR1cm4gTWFwU2V0LnNpemUobWFwKTtcbn1cblxuZnVuY3Rpb24gdG9fbGlzdChtYXApIHtcbiAgcmV0dXJuIE1hcFNldC50b19saXN0KG1hcCk7XG59XG5cbmZ1bmN0aW9uIF9fZGVsZXRlX18oc2V0LCB0ZXJtKSB7XG4gIHJldHVybiBNYXBTZXQuZGVsZXRlKHNldCwgdGVybSk7XG59XG5cbmZ1bmN0aW9uIHB1dChzZXQsIHRlcm0pIHtcbiAgcmV0dXJuIE1hcFNldC5wdXQoc2V0LCB0ZXJtKTtcbn1cblxuZnVuY3Rpb24gZGlmZmVyZW5jZShzZXQxLCBzZXQyKSB7XG4gIHJldHVybiBNYXBTZXQuZGlmZmVyZW5jZShzZXQxLCBzZXQyKTtcbn1cblxuZnVuY3Rpb24gaW50ZXJzZWN0aW9uKHNldDEsIHNldDIpIHtcbiAgcmV0dXJuIE1hcFNldC5pbnRlcnNlY3Rpb24oc2V0MSwgc2V0Mik7XG59XG5cbmZ1bmN0aW9uIHVuaW9uKHNldDEsIHNldDIpIHtcbiAgcmV0dXJuIE1hcFNldC51bmlvbihzZXQxLCBzZXQyKTtcbn1cblxuZnVuY3Rpb24gZGlzam9pbl9fcW1hcmtfXyhzZXQxLCBzZXQyKSB7XG4gIHJldHVybiBNYXBTZXQuZGlzam9pbl9fcW1hcmtfXyhzZXQxLCBzZXQyKTtcbn1cblxuZnVuY3Rpb24gbWVtYmVyX19xbWFya19fKHNldCwgdmFsdWUpIHtcbiAgcmV0dXJuIE1hcFNldC5tZW1iZXJfX3FtYXJrX18oc2V0MSwgc2V0Mik7XG59XG5cbmZ1bmN0aW9uIGVxdWFsX19xbWFya19fKHNldDEsIHNldDIpIHtcbiAgcmV0dXJuIE1hcFNldC5lcXVhbF9fcW1hcmtfXyhzZXQxLCBzZXQyKTtcbn1cblxuZnVuY3Rpb24gc3Vic2V0X19xbWFya19fKHNldDEsIHNldDIpIHtcbiAgcmV0dXJuIE1hcFNldC5zdWJzZXRfX3FtYXJrX18oc2V0MSwgc2V0Mik7XG59XG5cbnZhciBfU2V0ID0ge1xuICBzaXplLFxuICB0b19saXN0LFxuICBkaXNqb2luX19xbWFya19fLFxuICBkZWxldGU6IF9fZGVsZXRlX18sXG4gIHN1YnNldF9fcW1hcmtfXyxcbiAgZXF1YWxfX3FtYXJrX18sXG4gIG1lbWJlcl9fcW1hcmtfXyxcbiAgcHV0LFxuICB1bmlvbixcbiAgaW50ZXJzZWN0aW9uLFxuICBkaWZmZXJlbmNlXG59O1xuXG5sZXQgdmlydHVhbERvbSA9IChmdW5jdGlvbiAoZSkge1xuICAgIHJldHVybiBlKCk7XG59KShmdW5jdGlvbiAoKSB7XG4gICAgdmFyIGRlZmluZSwgbW9kdWxlLCBleHBvcnRzO1xuICAgIHJldHVybiAoZnVuY3Rpb24gZSh0LCBuLCByKSB7XG4gICAgICAgIGZ1bmN0aW9uIHMobywgdSkge1xuICAgICAgICAgICAgaWYgKCFuW29dKSB7XG4gICAgICAgICAgICAgICAgaWYgKCF0W29dKSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciBhID0gdHlwZW9mIHJlcXVpcmUgPT0gXCJmdW5jdGlvblwiICYmIHJlcXVpcmU7XG4gICAgICAgICAgICAgICAgICAgIGlmICghdSAmJiBhKSByZXR1cm4gYShvLCAhMCk7XG4gICAgICAgICAgICAgICAgICAgIGlmIChpKSByZXR1cm4gaShvLCAhMCk7XG4gICAgICAgICAgICAgICAgICAgIHZhciBmID0gbmV3IEVycm9yKFwiQ2Fubm90IGZpbmQgbW9kdWxlICdcIiArIG8gKyBcIidcIik7XG4gICAgICAgICAgICAgICAgICAgIHRocm93IChmLmNvZGUgPSBcIk1PRFVMRV9OT1RfRk9VTkRcIiwgZik7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHZhciBsID0gbltvXSA9IHtcbiAgICAgICAgICAgICAgICAgICAgZXhwb3J0czoge31cbiAgICAgICAgICAgICAgICB9O1xuICAgICAgICAgICAgICAgIHRbb11bMF0uY2FsbChsLmV4cG9ydHMsIGZ1bmN0aW9uIChlKSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciBuID0gdFtvXVsxXVtlXTtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHMobiA/IG4gOiBlKTtcbiAgICAgICAgICAgICAgICB9LCBsLCBsLmV4cG9ydHMsIGUsIHQsIG4sIHIpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmV0dXJuIG5bb10uZXhwb3J0cztcbiAgICAgICAgfVxuICAgICAgICB2YXIgaSA9IHR5cGVvZiByZXF1aXJlID09IFwiZnVuY3Rpb25cIiAmJiByZXF1aXJlO1xuICAgICAgICBmb3IgKHZhciBvID0gMDsgbyA8IHIubGVuZ3RoOyBvKyspIHMocltvXSk7XG4gICAgICAgIHJldHVybiBzO1xuICAgIH0pKHtcbiAgICAgICAgMTogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHtcblxuICAgICAgICAgICAgdmFyIGNyZWF0ZUVsZW1lbnQgPSByZXF1aXJlKFwiLi92ZG9tL2NyZWF0ZS1lbGVtZW50LmpzXCIpO1xuXG4gICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IGNyZWF0ZUVsZW1lbnQ7XG4gICAgICAgIH0sIHsgXCIuL3Zkb20vY3JlYXRlLWVsZW1lbnQuanNcIjogMTUgfV0sIDI6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICB2YXIgZGlmZiA9IHJlcXVpcmUoXCIuL3Z0cmVlL2RpZmYuanNcIik7XG5cbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gZGlmZjtcbiAgICAgICAgfSwgeyBcIi4vdnRyZWUvZGlmZi5qc1wiOiAzNSB9XSwgMzogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHtcbiAgICAgICAgICAgIHZhciBoID0gcmVxdWlyZShcIi4vdmlydHVhbC1oeXBlcnNjcmlwdC9pbmRleC5qc1wiKTtcblxuICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBoO1xuICAgICAgICB9LCB7IFwiLi92aXJ0dWFsLWh5cGVyc2NyaXB0L2luZGV4LmpzXCI6IDIyIH1dLCA0OiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge1xuICAgICAgICAgICAgdmFyIGRpZmYgPSByZXF1aXJlKFwiLi9kaWZmLmpzXCIpO1xuICAgICAgICAgICAgdmFyIHBhdGNoID0gcmVxdWlyZShcIi4vcGF0Y2guanNcIik7XG4gICAgICAgICAgICB2YXIgaCA9IHJlcXVpcmUoXCIuL2guanNcIik7XG4gICAgICAgICAgICB2YXIgY3JlYXRlID0gcmVxdWlyZShcIi4vY3JlYXRlLWVsZW1lbnQuanNcIik7XG4gICAgICAgICAgICB2YXIgVk5vZGUgPSByZXF1aXJlKFwiLi92bm9kZS92bm9kZS5qc1wiKTtcbiAgICAgICAgICAgIHZhciBWVGV4dCA9IHJlcXVpcmUoXCIuL3Zub2RlL3Z0ZXh0LmpzXCIpO1xuXG4gICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IHtcbiAgICAgICAgICAgICAgICBkaWZmOiBkaWZmLFxuICAgICAgICAgICAgICAgIHBhdGNoOiBwYXRjaCxcbiAgICAgICAgICAgICAgICBoOiBoLFxuICAgICAgICAgICAgICAgIGNyZWF0ZTogY3JlYXRlLFxuICAgICAgICAgICAgICAgIFZOb2RlOiBWTm9kZSxcbiAgICAgICAgICAgICAgICBWVGV4dDogVlRleHRcbiAgICAgICAgICAgIH07XG4gICAgICAgIH0sIHsgXCIuL2NyZWF0ZS1lbGVtZW50LmpzXCI6IDEsIFwiLi9kaWZmLmpzXCI6IDIsIFwiLi9oLmpzXCI6IDMsIFwiLi9wYXRjaC5qc1wiOiAxMywgXCIuL3Zub2RlL3Zub2RlLmpzXCI6IDMxLCBcIi4vdm5vZGUvdnRleHQuanNcIjogMzMgfV0sIDU6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICAvKiFcbiAgICAgICAgICAgICAqIENyb3NzLUJyb3dzZXIgU3BsaXQgMS4xLjFcbiAgICAgICAgICAgICAqIENvcHlyaWdodCAyMDA3LTIwMTIgU3RldmVuIExldml0aGFuIDxzdGV2ZW5sZXZpdGhhbi5jb20+XG4gICAgICAgICAgICAgKiBBdmFpbGFibGUgdW5kZXIgdGhlIE1JVCBMaWNlbnNlXG4gICAgICAgICAgICAgKiBFQ01BU2NyaXB0IGNvbXBsaWFudCwgdW5pZm9ybSBjcm9zcy1icm93c2VyIHNwbGl0IG1ldGhvZFxuICAgICAgICAgICAgICovXG5cbiAgICAgICAgICAgIC8qKlxuICAgICAgICAgICAgICogU3BsaXRzIGEgc3RyaW5nIGludG8gYW4gYXJyYXkgb2Ygc3RyaW5ncyB1c2luZyBhIHJlZ2V4IG9yIHN0cmluZyBzZXBhcmF0b3IuIE1hdGNoZXMgb2YgdGhlXG4gICAgICAgICAgICAgKiBzZXBhcmF0b3IgYXJlIG5vdCBpbmNsdWRlZCBpbiB0aGUgcmVzdWx0IGFycmF5LiBIb3dldmVyLCBpZiBgc2VwYXJhdG9yYCBpcyBhIHJlZ2V4IHRoYXQgY29udGFpbnNcbiAgICAgICAgICAgICAqIGNhcHR1cmluZyBncm91cHMsIGJhY2tyZWZlcmVuY2VzIGFyZSBzcGxpY2VkIGludG8gdGhlIHJlc3VsdCBlYWNoIHRpbWUgYHNlcGFyYXRvcmAgaXMgbWF0Y2hlZC5cbiAgICAgICAgICAgICAqIEZpeGVzIGJyb3dzZXIgYnVncyBjb21wYXJlZCB0byB0aGUgbmF0aXZlIGBTdHJpbmcucHJvdG90eXBlLnNwbGl0YCBhbmQgY2FuIGJlIHVzZWQgcmVsaWFibHlcbiAgICAgICAgICAgICAqIGNyb3NzLWJyb3dzZXIuXG4gICAgICAgICAgICAgKiBAcGFyYW0ge1N0cmluZ30gc3RyIFN0cmluZyB0byBzcGxpdC5cbiAgICAgICAgICAgICAqIEBwYXJhbSB7UmVnRXhwfFN0cmluZ30gc2VwYXJhdG9yIFJlZ2V4IG9yIHN0cmluZyB0byB1c2UgZm9yIHNlcGFyYXRpbmcgdGhlIHN0cmluZy5cbiAgICAgICAgICAgICAqIEBwYXJhbSB7TnVtYmVyfSBbbGltaXRdIE1heGltdW0gbnVtYmVyIG9mIGl0ZW1zIHRvIGluY2x1ZGUgaW4gdGhlIHJlc3VsdCBhcnJheS5cbiAgICAgICAgICAgICAqIEByZXR1cm5zIHtBcnJheX0gQXJyYXkgb2Ygc3Vic3RyaW5ncy5cbiAgICAgICAgICAgICAqIEBleGFtcGxlXG4gICAgICAgICAgICAgKlxuICAgICAgICAgICAgICogLy8gQmFzaWMgdXNlXG4gICAgICAgICAgICAgKiBzcGxpdCgnYSBiIGMgZCcsICcgJyk7XG4gICAgICAgICAgICAgKiAvLyAtPiBbJ2EnLCAnYicsICdjJywgJ2QnXVxuICAgICAgICAgICAgICpcbiAgICAgICAgICAgICAqIC8vIFdpdGggbGltaXRcbiAgICAgICAgICAgICAqIHNwbGl0KCdhIGIgYyBkJywgJyAnLCAyKTtcbiAgICAgICAgICAgICAqIC8vIC0+IFsnYScsICdiJ11cbiAgICAgICAgICAgICAqXG4gICAgICAgICAgICAgKiAvLyBCYWNrcmVmZXJlbmNlcyBpbiByZXN1bHQgYXJyYXlcbiAgICAgICAgICAgICAqIHNwbGl0KCcuLndvcmQxIHdvcmQyLi4nLCAvKFthLXpdKykoXFxkKykvaSk7XG4gICAgICAgICAgICAgKiAvLyAtPiBbJy4uJywgJ3dvcmQnLCAnMScsICcgJywgJ3dvcmQnLCAnMicsICcuLiddXG4gICAgICAgICAgICAgKi9cbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gKGZ1bmN0aW9uIHNwbGl0KHVuZGVmKSB7XG5cbiAgICAgICAgICAgICAgICB2YXIgbmF0aXZlU3BsaXQgPSBTdHJpbmcucHJvdG90eXBlLnNwbGl0LFxuICAgICAgICAgICAgICAgICAgICBjb21wbGlhbnRFeGVjTnBjZyA9IC8oKT8/Ly5leGVjKFwiXCIpWzFdID09PSB1bmRlZixcblxuICAgICAgICAgICAgICAgIC8vIE5QQ0c6IG5vbnBhcnRpY2lwYXRpbmcgY2FwdHVyaW5nIGdyb3VwXG4gICAgICAgICAgICAgICAgc2VsZjtcblxuICAgICAgICAgICAgICAgIHNlbGYgPSBmdW5jdGlvbiAoc3RyLCBzZXBhcmF0b3IsIGxpbWl0KSB7XG4gICAgICAgICAgICAgICAgICAgIC8vIElmIGBzZXBhcmF0b3JgIGlzIG5vdCBhIHJlZ2V4LCB1c2UgYG5hdGl2ZVNwbGl0YFxuICAgICAgICAgICAgICAgICAgICBpZiAoT2JqZWN0LnByb3RvdHlwZS50b1N0cmluZy5jYWxsKHNlcGFyYXRvcikgIT09IFwiW29iamVjdCBSZWdFeHBdXCIpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBuYXRpdmVTcGxpdC5jYWxsKHN0ciwgc2VwYXJhdG9yLCBsaW1pdCk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgdmFyIG91dHB1dCA9IFtdLFxuICAgICAgICAgICAgICAgICAgICAgICAgZmxhZ3MgPSAoc2VwYXJhdG9yLmlnbm9yZUNhc2UgPyBcImlcIiA6IFwiXCIpICsgKHNlcGFyYXRvci5tdWx0aWxpbmUgPyBcIm1cIiA6IFwiXCIpICsgKHNlcGFyYXRvci5leHRlbmRlZCA/IFwieFwiIDogXCJcIikgKyAoc2VwYXJhdG9yLnN0aWNreSA/IFwieVwiIDogXCJcIiksXG5cbiAgICAgICAgICAgICAgICAgICAgLy8gRmlyZWZveCAzK1xuICAgICAgICAgICAgICAgICAgICBsYXN0TGFzdEluZGV4ID0gMCxcblxuICAgICAgICAgICAgICAgICAgICAvLyBNYWtlIGBnbG9iYWxgIGFuZCBhdm9pZCBgbGFzdEluZGV4YCBpc3N1ZXMgYnkgd29ya2luZyB3aXRoIGEgY29weVxuICAgICAgICAgICAgICAgICAgICBzZXBhcmF0b3IgPSBuZXcgUmVnRXhwKHNlcGFyYXRvci5zb3VyY2UsIGZsYWdzICsgXCJnXCIpLFxuICAgICAgICAgICAgICAgICAgICAgICAgc2VwYXJhdG9yMixcbiAgICAgICAgICAgICAgICAgICAgICAgIG1hdGNoLFxuICAgICAgICAgICAgICAgICAgICAgICAgbGFzdEluZGV4LFxuICAgICAgICAgICAgICAgICAgICAgICAgbGFzdExlbmd0aDtcbiAgICAgICAgICAgICAgICAgICAgc3RyICs9IFwiXCI7IC8vIFR5cGUtY29udmVydFxuICAgICAgICAgICAgICAgICAgICBpZiAoIWNvbXBsaWFudEV4ZWNOcGNnKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAvLyBEb2Vzbid0IG5lZWQgZmxhZ3MgZ3ksIGJ1dCB0aGV5IGRvbid0IGh1cnRcbiAgICAgICAgICAgICAgICAgICAgICAgIHNlcGFyYXRvcjIgPSBuZXcgUmVnRXhwKFwiXlwiICsgc2VwYXJhdG9yLnNvdXJjZSArIFwiJCg/IVxcXFxzKVwiLCBmbGFncyk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgLyogVmFsdWVzIGZvciBgbGltaXRgLCBwZXIgdGhlIHNwZWM6XG4gICAgICAgICAgICAgICAgICAgICAqIElmIHVuZGVmaW5lZDogNDI5NDk2NzI5NSAvLyBNYXRoLnBvdygyLCAzMikgLSAxXG4gICAgICAgICAgICAgICAgICAgICAqIElmIDAsIEluZmluaXR5LCBvciBOYU46IDBcbiAgICAgICAgICAgICAgICAgICAgICogSWYgcG9zaXRpdmUgbnVtYmVyOiBsaW1pdCA9IE1hdGguZmxvb3IobGltaXQpOyBpZiAobGltaXQgPiA0Mjk0OTY3Mjk1KSBsaW1pdCAtPSA0Mjk0OTY3Mjk2O1xuICAgICAgICAgICAgICAgICAgICAgKiBJZiBuZWdhdGl2ZSBudW1iZXI6IDQyOTQ5NjcyOTYgLSBNYXRoLmZsb29yKE1hdGguYWJzKGxpbWl0KSlcbiAgICAgICAgICAgICAgICAgICAgICogSWYgb3RoZXI6IFR5cGUtY29udmVydCwgdGhlbiB1c2UgdGhlIGFib3ZlIHJ1bGVzXG4gICAgICAgICAgICAgICAgICAgICAqL1xuICAgICAgICAgICAgICAgICAgICBsaW1pdCA9IGxpbWl0ID09PSB1bmRlZiA/IC0xID4+PiAwIDogLy8gTWF0aC5wb3coMiwgMzIpIC0gMVxuICAgICAgICAgICAgICAgICAgICBsaW1pdCA+Pj4gMDsgLy8gVG9VaW50MzIobGltaXQpXG4gICAgICAgICAgICAgICAgICAgIHdoaWxlIChtYXRjaCA9IHNlcGFyYXRvci5leGVjKHN0cikpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIGBzZXBhcmF0b3IubGFzdEluZGV4YCBpcyBub3QgcmVsaWFibGUgY3Jvc3MtYnJvd3NlclxuICAgICAgICAgICAgICAgICAgICAgICAgbGFzdEluZGV4ID0gbWF0Y2guaW5kZXggKyBtYXRjaFswXS5sZW5ndGg7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAobGFzdEluZGV4ID4gbGFzdExhc3RJbmRleCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIG91dHB1dC5wdXNoKHN0ci5zbGljZShsYXN0TGFzdEluZGV4LCBtYXRjaC5pbmRleCkpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIEZpeCBicm93c2VycyB3aG9zZSBgZXhlY2AgbWV0aG9kcyBkb24ndCBjb25zaXN0ZW50bHkgcmV0dXJuIGB1bmRlZmluZWRgIGZvclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIG5vbnBhcnRpY2lwYXRpbmcgY2FwdHVyaW5nIGdyb3Vwc1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmICghY29tcGxpYW50RXhlY05wY2cgJiYgbWF0Y2gubGVuZ3RoID4gMSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBtYXRjaFswXS5yZXBsYWNlKHNlcGFyYXRvcjIsIGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZvciAodmFyIGkgPSAxOyBpIDwgYXJndW1lbnRzLmxlbmd0aCAtIDI7IGkrKykge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChhcmd1bWVudHNbaV0gPT09IHVuZGVmKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1hdGNoW2ldID0gdW5kZWY7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKG1hdGNoLmxlbmd0aCA+IDEgJiYgbWF0Y2guaW5kZXggPCBzdHIubGVuZ3RoKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIEFycmF5LnByb3RvdHlwZS5wdXNoLmFwcGx5KG91dHB1dCwgbWF0Y2guc2xpY2UoMSkpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBsYXN0TGVuZ3RoID0gbWF0Y2hbMF0ubGVuZ3RoO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxhc3RMYXN0SW5kZXggPSBsYXN0SW5kZXg7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKG91dHB1dC5sZW5ndGggPj0gbGltaXQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHNlcGFyYXRvci5sYXN0SW5kZXggPT09IG1hdGNoLmluZGV4KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgc2VwYXJhdG9yLmxhc3RJbmRleCsrOyAvLyBBdm9pZCBhbiBpbmZpbml0ZSBsb29wXG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgaWYgKGxhc3RMYXN0SW5kZXggPT09IHN0ci5sZW5ndGgpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChsYXN0TGVuZ3RoIHx8ICFzZXBhcmF0b3IudGVzdChcIlwiKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIG91dHB1dC5wdXNoKFwiXCIpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgb3V0cHV0LnB1c2goc3RyLnNsaWNlKGxhc3RMYXN0SW5kZXgpKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICByZXR1cm4gb3V0cHV0Lmxlbmd0aCA+IGxpbWl0ID8gb3V0cHV0LnNsaWNlKDAsIGxpbWl0KSA6IG91dHB1dDtcbiAgICAgICAgICAgICAgICB9O1xuXG4gICAgICAgICAgICAgICAgcmV0dXJuIHNlbGY7XG4gICAgICAgICAgICB9KSgpO1xuICAgICAgICB9LCB7fV0sIDY6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7fSwge31dLCA3OiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge1xuICAgICAgICAgICAgXCJ1c2Ugc3RyaWN0XCI7XG5cbiAgICAgICAgICAgIHZhciBPbmVWZXJzaW9uQ29uc3RyYWludCA9IHJlcXVpcmUoXCJpbmRpdmlkdWFsL29uZS12ZXJzaW9uXCIpO1xuXG4gICAgICAgICAgICB2YXIgTVlfVkVSU0lPTiA9IFwiN1wiO1xuICAgICAgICAgICAgT25lVmVyc2lvbkNvbnN0cmFpbnQoXCJldi1zdG9yZVwiLCBNWV9WRVJTSU9OKTtcblxuICAgICAgICAgICAgdmFyIGhhc2hLZXkgPSBcIl9fRVZfU1RPUkVfS0VZQFwiICsgTVlfVkVSU0lPTjtcblxuICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBFdlN0b3JlO1xuXG4gICAgICAgICAgICBmdW5jdGlvbiBFdlN0b3JlKGVsZW0pIHtcbiAgICAgICAgICAgICAgICB2YXIgaGFzaCA9IGVsZW1baGFzaEtleV07XG5cbiAgICAgICAgICAgICAgICBpZiAoIWhhc2gpIHtcbiAgICAgICAgICAgICAgICAgICAgaGFzaCA9IGVsZW1baGFzaEtleV0gPSB7fTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICByZXR1cm4gaGFzaDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSwgeyBcImluZGl2aWR1YWwvb25lLXZlcnNpb25cIjogOSB9XSwgODogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHtcbiAgICAgICAgICAgIChmdW5jdGlvbiAoZ2xvYmFsKSB7XG4gICAgICAgICAgICAgICAgXCJ1c2Ugc3RyaWN0XCI7XG5cbiAgICAgICAgICAgICAgICAvKmdsb2JhbCB3aW5kb3csIGdsb2JhbCovXG5cbiAgICAgICAgICAgICAgICB2YXIgcm9vdCA9IHR5cGVvZiB3aW5kb3cgIT09IFwidW5kZWZpbmVkXCIgPyB3aW5kb3cgOiB0eXBlb2YgZ2xvYmFsICE9PSBcInVuZGVmaW5lZFwiID8gZ2xvYmFsIDoge307XG5cbiAgICAgICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IEluZGl2aWR1YWw7XG5cbiAgICAgICAgICAgICAgICBmdW5jdGlvbiBJbmRpdmlkdWFsKGtleSwgdmFsdWUpIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKGtleSBpbiByb290KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gcm9vdFtrZXldO1xuICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgcm9vdFtrZXldID0gdmFsdWU7XG5cbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHZhbHVlO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0pLmNhbGwodGhpcywgdHlwZW9mIGdsb2JhbCAhPT0gXCJ1bmRlZmluZWRcIiA/IGdsb2JhbCA6IHR5cGVvZiBzZWxmICE9PSBcInVuZGVmaW5lZFwiID8gc2VsZiA6IHR5cGVvZiB3aW5kb3cgIT09IFwidW5kZWZpbmVkXCIgPyB3aW5kb3cgOiB7fSk7XG4gICAgICAgIH0sIHt9XSwgOTogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHtcbiAgICAgICAgICAgIFwidXNlIHN0cmljdFwiO1xuXG4gICAgICAgICAgICB2YXIgSW5kaXZpZHVhbCA9IHJlcXVpcmUoXCIuL2luZGV4LmpzXCIpO1xuXG4gICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IE9uZVZlcnNpb247XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIE9uZVZlcnNpb24obW9kdWxlTmFtZSwgdmVyc2lvbiwgZGVmYXVsdFZhbHVlKSB7XG4gICAgICAgICAgICAgICAgdmFyIGtleSA9IFwiX19JTkRJVklEVUFMX09ORV9WRVJTSU9OX1wiICsgbW9kdWxlTmFtZTtcbiAgICAgICAgICAgICAgICB2YXIgZW5mb3JjZUtleSA9IGtleSArIFwiX0VORk9SQ0VfU0lOR0xFVE9OXCI7XG5cbiAgICAgICAgICAgICAgICB2YXIgdmVyc2lvblZhbHVlID0gSW5kaXZpZHVhbChlbmZvcmNlS2V5LCB2ZXJzaW9uKTtcblxuICAgICAgICAgICAgICAgIGlmICh2ZXJzaW9uVmFsdWUgIT09IHZlcnNpb24pIHtcbiAgICAgICAgICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKFwiQ2FuIG9ubHkgaGF2ZSBvbmUgY29weSBvZiBcIiArIG1vZHVsZU5hbWUgKyBcIi5cXG5cIiArIFwiWW91IGFscmVhZHkgaGF2ZSB2ZXJzaW9uIFwiICsgdmVyc2lvblZhbHVlICsgXCIgaW5zdGFsbGVkLlxcblwiICsgXCJUaGlzIG1lYW5zIHlvdSBjYW5ub3QgaW5zdGFsbCB2ZXJzaW9uIFwiICsgdmVyc2lvbik7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgcmV0dXJuIEluZGl2aWR1YWwoa2V5LCBkZWZhdWx0VmFsdWUpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9LCB7IFwiLi9pbmRleC5qc1wiOiA4IH1dLCAxMDogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHtcbiAgICAgICAgICAgIChmdW5jdGlvbiAoZ2xvYmFsKSB7XG4gICAgICAgICAgICAgICAgdmFyIHRvcExldmVsID0gdHlwZW9mIGdsb2JhbCAhPT0gXCJ1bmRlZmluZWRcIiA/IGdsb2JhbCA6IHR5cGVvZiB3aW5kb3cgIT09IFwidW5kZWZpbmVkXCIgPyB3aW5kb3cgOiB7fTtcbiAgICAgICAgICAgICAgICB2YXIgbWluRG9jID0gcmVxdWlyZShcIm1pbi1kb2N1bWVudFwiKTtcblxuICAgICAgICAgICAgICAgIGlmICh0eXBlb2YgZG9jdW1lbnQgIT09IFwidW5kZWZpbmVkXCIpIHtcbiAgICAgICAgICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBkb2N1bWVudDtcbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICB2YXIgZG9jY3kgPSB0b3BMZXZlbFtcIl9fR0xPQkFMX0RPQ1VNRU5UX0NBQ0hFQDRcIl07XG5cbiAgICAgICAgICAgICAgICAgICAgaWYgKCFkb2NjeSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgZG9jY3kgPSB0b3BMZXZlbFtcIl9fR0xPQkFMX0RPQ1VNRU5UX0NBQ0hFQDRcIl0gPSBtaW5Eb2M7XG4gICAgICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IGRvY2N5O1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0pLmNhbGwodGhpcywgdHlwZW9mIGdsb2JhbCAhPT0gXCJ1bmRlZmluZWRcIiA/IGdsb2JhbCA6IHR5cGVvZiBzZWxmICE9PSBcInVuZGVmaW5lZFwiID8gc2VsZiA6IHR5cGVvZiB3aW5kb3cgIT09IFwidW5kZWZpbmVkXCIgPyB3aW5kb3cgOiB7fSk7XG4gICAgICAgIH0sIHsgXCJtaW4tZG9jdW1lbnRcIjogNiB9XSwgMTE6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICBcInVzZSBzdHJpY3RcIjtcblxuICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiBpc09iamVjdCh4KSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHR5cGVvZiB4ID09PSBcIm9iamVjdFwiICYmIHggIT09IG51bGw7XG4gICAgICAgICAgICB9O1xuICAgICAgICB9LCB7fV0sIDEyOiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge1xuICAgICAgICAgICAgdmFyIG5hdGl2ZUlzQXJyYXkgPSBBcnJheS5pc0FycmF5O1xuICAgICAgICAgICAgdmFyIHRvU3RyaW5nID0gT2JqZWN0LnByb3RvdHlwZS50b1N0cmluZztcblxuICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBuYXRpdmVJc0FycmF5IHx8IGlzQXJyYXk7XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIGlzQXJyYXkob2JqKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHRvU3RyaW5nLmNhbGwob2JqKSA9PT0gXCJbb2JqZWN0IEFycmF5XVwiO1xuICAgICAgICAgICAgfVxuICAgICAgICB9LCB7fV0sIDEzOiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge1xuICAgICAgICAgICAgdmFyIHBhdGNoID0gcmVxdWlyZShcIi4vdmRvbS9wYXRjaC5qc1wiKTtcblxuICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBwYXRjaDtcbiAgICAgICAgfSwgeyBcIi4vdmRvbS9wYXRjaC5qc1wiOiAxOCB9XSwgMTQ6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICB2YXIgaXNPYmplY3QgPSByZXF1aXJlKFwiaXMtb2JqZWN0XCIpO1xuICAgICAgICAgICAgdmFyIGlzSG9vayA9IHJlcXVpcmUoXCIuLi92bm9kZS9pcy12aG9vay5qc1wiKTtcblxuICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBhcHBseVByb3BlcnRpZXM7XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIGFwcGx5UHJvcGVydGllcyhub2RlLCBwcm9wcywgcHJldmlvdXMpIHtcbiAgICAgICAgICAgICAgICBmb3IgKHZhciBwcm9wTmFtZSBpbiBwcm9wcykge1xuICAgICAgICAgICAgICAgICAgICB2YXIgcHJvcFZhbHVlID0gcHJvcHNbcHJvcE5hbWVdO1xuXG4gICAgICAgICAgICAgICAgICAgIGlmIChwcm9wVmFsdWUgPT09IHVuZGVmaW5lZCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgcmVtb3ZlUHJvcGVydHkobm9kZSwgcHJvcE5hbWUsIHByb3BWYWx1ZSwgcHJldmlvdXMpO1xuICAgICAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKGlzSG9vayhwcm9wVmFsdWUpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICByZW1vdmVQcm9wZXJ0eShub2RlLCBwcm9wTmFtZSwgcHJvcFZhbHVlLCBwcmV2aW91cyk7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAocHJvcFZhbHVlLmhvb2spIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBwcm9wVmFsdWUuaG9vayhub2RlLCBwcm9wTmFtZSwgcHJldmlvdXMgPyBwcmV2aW91c1twcm9wTmFtZV0gOiB1bmRlZmluZWQpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGlzT2JqZWN0KHByb3BWYWx1ZSkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBwYXRjaE9iamVjdChub2RlLCBwcm9wcywgcHJldmlvdXMsIHByb3BOYW1lLCBwcm9wVmFsdWUpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBub2RlW3Byb3BOYW1lXSA9IHByb3BWYWx1ZTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZnVuY3Rpb24gcmVtb3ZlUHJvcGVydHkobm9kZSwgcHJvcE5hbWUsIHByb3BWYWx1ZSwgcHJldmlvdXMpIHtcbiAgICAgICAgICAgICAgICBpZiAocHJldmlvdXMpIHtcbiAgICAgICAgICAgICAgICAgICAgdmFyIHByZXZpb3VzVmFsdWUgPSBwcmV2aW91c1twcm9wTmFtZV07XG5cbiAgICAgICAgICAgICAgICAgICAgaWYgKCFpc0hvb2socHJldmlvdXNWYWx1ZSkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChwcm9wTmFtZSA9PT0gXCJhdHRyaWJ1dGVzXCIpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBmb3IgKHZhciBhdHRyTmFtZSBpbiBwcmV2aW91c1ZhbHVlKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG5vZGUucmVtb3ZlQXR0cmlidXRlKGF0dHJOYW1lKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKHByb3BOYW1lID09PSBcInN0eWxlXCIpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBmb3IgKHZhciBpIGluIHByZXZpb3VzVmFsdWUpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbm9kZS5zdHlsZVtpXSA9IFwiXCI7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIGlmICh0eXBlb2YgcHJldmlvdXNWYWx1ZSA9PT0gXCJzdHJpbmdcIikge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIG5vZGVbcHJvcE5hbWVdID0gXCJcIjtcbiAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgbm9kZVtwcm9wTmFtZV0gPSBudWxsO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKHByZXZpb3VzVmFsdWUudW5ob29rKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBwcmV2aW91c1ZhbHVlLnVuaG9vayhub2RlLCBwcm9wTmFtZSwgcHJvcFZhbHVlKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZnVuY3Rpb24gcGF0Y2hPYmplY3Qobm9kZSwgcHJvcHMsIHByZXZpb3VzLCBwcm9wTmFtZSwgcHJvcFZhbHVlKSB7XG4gICAgICAgICAgICAgICAgdmFyIHByZXZpb3VzVmFsdWUgPSBwcmV2aW91cyA/IHByZXZpb3VzW3Byb3BOYW1lXSA6IHVuZGVmaW5lZDtcblxuICAgICAgICAgICAgICAgIC8vIFNldCBhdHRyaWJ1dGVzXG4gICAgICAgICAgICAgICAgaWYgKHByb3BOYW1lID09PSBcImF0dHJpYnV0ZXNcIikge1xuICAgICAgICAgICAgICAgICAgICBmb3IgKHZhciBhdHRyTmFtZSBpbiBwcm9wVmFsdWUpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHZhciBhdHRyVmFsdWUgPSBwcm9wVmFsdWVbYXR0ck5hbWVdO1xuXG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoYXR0clZhbHVlID09PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBub2RlLnJlbW92ZUF0dHJpYnV0ZShhdHRyTmFtZSk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIG5vZGUuc2V0QXR0cmlidXRlKGF0dHJOYW1lLCBhdHRyVmFsdWUpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIGlmIChwcmV2aW91c1ZhbHVlICYmIGlzT2JqZWN0KHByZXZpb3VzVmFsdWUpICYmIGdldFByb3RvdHlwZShwcmV2aW91c1ZhbHVlKSAhPT0gZ2V0UHJvdG90eXBlKHByb3BWYWx1ZSkpIHtcbiAgICAgICAgICAgICAgICAgICAgbm9kZVtwcm9wTmFtZV0gPSBwcm9wVmFsdWU7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICBpZiAoIWlzT2JqZWN0KG5vZGVbcHJvcE5hbWVdKSkge1xuICAgICAgICAgICAgICAgICAgICBub2RlW3Byb3BOYW1lXSA9IHt9O1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHZhciByZXBsYWNlciA9IHByb3BOYW1lID09PSBcInN0eWxlXCIgPyBcIlwiIDogdW5kZWZpbmVkO1xuXG4gICAgICAgICAgICAgICAgZm9yICh2YXIgayBpbiBwcm9wVmFsdWUpIHtcbiAgICAgICAgICAgICAgICAgICAgdmFyIHZhbHVlID0gcHJvcFZhbHVlW2tdO1xuICAgICAgICAgICAgICAgICAgICBub2RlW3Byb3BOYW1lXVtrXSA9IHZhbHVlID09PSB1bmRlZmluZWQgPyByZXBsYWNlciA6IHZhbHVlO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZnVuY3Rpb24gZ2V0UHJvdG90eXBlKHZhbHVlKSB7XG4gICAgICAgICAgICAgICAgaWYgKE9iamVjdC5nZXRQcm90b3R5cGVPZikge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gT2JqZWN0LmdldFByb3RvdHlwZU9mKHZhbHVlKTtcbiAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKHZhbHVlLl9fcHJvdG9fXykge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gdmFsdWUuX19wcm90b19fO1xuICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAodmFsdWUuY29uc3RydWN0b3IpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHZhbHVlLmNvbnN0cnVjdG9yLnByb3RvdHlwZTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH0sIHsgXCIuLi92bm9kZS9pcy12aG9vay5qc1wiOiAyNiwgXCJpcy1vYmplY3RcIjogMTEgfV0sIDE1OiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge1xuICAgICAgICAgICAgdmFyIGRvY3VtZW50ID0gcmVxdWlyZShcImdsb2JhbC9kb2N1bWVudFwiKTtcblxuICAgICAgICAgICAgdmFyIGFwcGx5UHJvcGVydGllcyA9IHJlcXVpcmUoXCIuL2FwcGx5LXByb3BlcnRpZXNcIik7XG5cbiAgICAgICAgICAgIHZhciBpc1ZOb2RlID0gcmVxdWlyZShcIi4uL3Zub2RlL2lzLXZub2RlLmpzXCIpO1xuICAgICAgICAgICAgdmFyIGlzVlRleHQgPSByZXF1aXJlKFwiLi4vdm5vZGUvaXMtdnRleHQuanNcIik7XG4gICAgICAgICAgICB2YXIgaXNXaWRnZXQgPSByZXF1aXJlKFwiLi4vdm5vZGUvaXMtd2lkZ2V0LmpzXCIpO1xuICAgICAgICAgICAgdmFyIGhhbmRsZVRodW5rID0gcmVxdWlyZShcIi4uL3Zub2RlL2hhbmRsZS10aHVuay5qc1wiKTtcblxuICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBjcmVhdGVFbGVtZW50O1xuXG4gICAgICAgICAgICBmdW5jdGlvbiBjcmVhdGVFbGVtZW50KHZub2RlLCBvcHRzKSB7XG4gICAgICAgICAgICAgICAgdmFyIGRvYyA9IG9wdHMgPyBvcHRzLmRvY3VtZW50IHx8IGRvY3VtZW50IDogZG9jdW1lbnQ7XG4gICAgICAgICAgICAgICAgdmFyIHdhcm4gPSBvcHRzID8gb3B0cy53YXJuIDogbnVsbDtcblxuICAgICAgICAgICAgICAgIHZub2RlID0gaGFuZGxlVGh1bmsodm5vZGUpLmE7XG5cbiAgICAgICAgICAgICAgICBpZiAoaXNXaWRnZXQodm5vZGUpKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiB2bm9kZS5pbml0KCk7XG4gICAgICAgICAgICAgICAgfSBlbHNlIGlmIChpc1ZUZXh0KHZub2RlKSkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gZG9jLmNyZWF0ZVRleHROb2RlKHZub2RlLnRleHQpO1xuICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoIWlzVk5vZGUodm5vZGUpKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmICh3YXJuKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICB3YXJuKFwiSXRlbSBpcyBub3QgYSB2YWxpZCB2aXJ0dWFsIGRvbSBub2RlXCIsIHZub2RlKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICByZXR1cm4gbnVsbDtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICB2YXIgbm9kZSA9IHZub2RlLm5hbWVzcGFjZSA9PT0gbnVsbCA/IGRvYy5jcmVhdGVFbGVtZW50KHZub2RlLnRhZ05hbWUpIDogZG9jLmNyZWF0ZUVsZW1lbnROUyh2bm9kZS5uYW1lc3BhY2UsIHZub2RlLnRhZ05hbWUpO1xuXG4gICAgICAgICAgICAgICAgdmFyIHByb3BzID0gdm5vZGUucHJvcGVydGllcztcbiAgICAgICAgICAgICAgICBhcHBseVByb3BlcnRpZXMobm9kZSwgcHJvcHMpO1xuXG4gICAgICAgICAgICAgICAgdmFyIGNoaWxkcmVuID0gdm5vZGUuY2hpbGRyZW47XG5cbiAgICAgICAgICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IGNoaWxkcmVuLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciBjaGlsZE5vZGUgPSBjcmVhdGVFbGVtZW50KGNoaWxkcmVuW2ldLCBvcHRzKTtcbiAgICAgICAgICAgICAgICAgICAgaWYgKGNoaWxkTm9kZSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgbm9kZS5hcHBlbmRDaGlsZChjaGlsZE5vZGUpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgcmV0dXJuIG5vZGU7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0sIHsgXCIuLi92bm9kZS9oYW5kbGUtdGh1bmsuanNcIjogMjQsIFwiLi4vdm5vZGUvaXMtdm5vZGUuanNcIjogMjcsIFwiLi4vdm5vZGUvaXMtdnRleHQuanNcIjogMjgsIFwiLi4vdm5vZGUvaXMtd2lkZ2V0LmpzXCI6IDI5LCBcIi4vYXBwbHktcHJvcGVydGllc1wiOiAxNCwgXCJnbG9iYWwvZG9jdW1lbnRcIjogMTAgfV0sIDE2OiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge1xuICAgICAgICAgICAgLy8gTWFwcyBhIHZpcnR1YWwgRE9NIHRyZWUgb250byBhIHJlYWwgRE9NIHRyZWUgaW4gYW4gZWZmaWNpZW50IG1hbm5lci5cbiAgICAgICAgICAgIC8vIFdlIGRvbid0IHdhbnQgdG8gcmVhZCBhbGwgb2YgdGhlIERPTSBub2RlcyBpbiB0aGUgdHJlZSBzbyB3ZSB1c2VcbiAgICAgICAgICAgIC8vIHRoZSBpbi1vcmRlciB0cmVlIGluZGV4aW5nIHRvIGVsaW1pbmF0ZSByZWN1cnNpb24gZG93biBjZXJ0YWluIGJyYW5jaGVzLlxuICAgICAgICAgICAgLy8gV2Ugb25seSByZWN1cnNlIGludG8gYSBET00gbm9kZSBpZiB3ZSBrbm93IHRoYXQgaXQgY29udGFpbnMgYSBjaGlsZCBvZlxuICAgICAgICAgICAgLy8gaW50ZXJlc3QuXG5cbiAgICAgICAgICAgIHZhciBub0NoaWxkID0ge307XG5cbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gZG9tSW5kZXg7XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIGRvbUluZGV4KHJvb3ROb2RlLCB0cmVlLCBpbmRpY2VzLCBub2Rlcykge1xuICAgICAgICAgICAgICAgIGlmICghaW5kaWNlcyB8fCBpbmRpY2VzLmxlbmd0aCA9PT0gMCkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4ge307XG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgaW5kaWNlcy5zb3J0KGFzY2VuZGluZyk7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiByZWN1cnNlKHJvb3ROb2RlLCB0cmVlLCBpbmRpY2VzLCBub2RlcywgMCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBmdW5jdGlvbiByZWN1cnNlKHJvb3ROb2RlLCB0cmVlLCBpbmRpY2VzLCBub2Rlcywgcm9vdEluZGV4KSB7XG4gICAgICAgICAgICAgICAgbm9kZXMgPSBub2RlcyB8fCB7fTtcblxuICAgICAgICAgICAgICAgIGlmIChyb290Tm9kZSkge1xuICAgICAgICAgICAgICAgICAgICBpZiAoaW5kZXhJblJhbmdlKGluZGljZXMsIHJvb3RJbmRleCwgcm9vdEluZGV4KSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgbm9kZXNbcm9vdEluZGV4XSA9IHJvb3ROb2RlO1xuICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgdmFyIHZDaGlsZHJlbiA9IHRyZWUuY2hpbGRyZW47XG5cbiAgICAgICAgICAgICAgICAgICAgaWYgKHZDaGlsZHJlbikge1xuXG4gICAgICAgICAgICAgICAgICAgICAgICB2YXIgY2hpbGROb2RlcyA9IHJvb3ROb2RlLmNoaWxkTm9kZXM7XG5cbiAgICAgICAgICAgICAgICAgICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgdHJlZS5jaGlsZHJlbi5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJvb3RJbmRleCArPSAxO1xuXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdmFyIHZDaGlsZCA9IHZDaGlsZHJlbltpXSB8fCBub0NoaWxkO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZhciBuZXh0SW5kZXggPSByb290SW5kZXggKyAodkNoaWxkLmNvdW50IHx8IDApO1xuXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gc2tpcCByZWN1cnNpb24gZG93biB0aGUgdHJlZSBpZiB0aGVyZSBhcmUgbm8gbm9kZXMgZG93biBoZXJlXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGluZGV4SW5SYW5nZShpbmRpY2VzLCByb290SW5kZXgsIG5leHRJbmRleCkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmVjdXJzZShjaGlsZE5vZGVzW2ldLCB2Q2hpbGQsIGluZGljZXMsIG5vZGVzLCByb290SW5kZXgpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJvb3RJbmRleCA9IG5leHRJbmRleDtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHJldHVybiBub2RlcztcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgLy8gQmluYXJ5IHNlYXJjaCBmb3IgYW4gaW5kZXggaW4gdGhlIGludGVydmFsIFtsZWZ0LCByaWdodF1cbiAgICAgICAgICAgIGZ1bmN0aW9uIGluZGV4SW5SYW5nZShpbmRpY2VzLCBsZWZ0LCByaWdodCkge1xuICAgICAgICAgICAgICAgIGlmIChpbmRpY2VzLmxlbmd0aCA9PT0gMCkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgdmFyIG1pbkluZGV4ID0gMDtcbiAgICAgICAgICAgICAgICB2YXIgbWF4SW5kZXggPSBpbmRpY2VzLmxlbmd0aCAtIDE7XG4gICAgICAgICAgICAgICAgdmFyIGN1cnJlbnRJbmRleDtcbiAgICAgICAgICAgICAgICB2YXIgY3VycmVudEl0ZW07XG5cbiAgICAgICAgICAgICAgICB3aGlsZSAobWluSW5kZXggPD0gbWF4SW5kZXgpIHtcbiAgICAgICAgICAgICAgICAgICAgY3VycmVudEluZGV4ID0gKG1heEluZGV4ICsgbWluSW5kZXgpIC8gMiA+PiAwO1xuICAgICAgICAgICAgICAgICAgICBjdXJyZW50SXRlbSA9IGluZGljZXNbY3VycmVudEluZGV4XTtcblxuICAgICAgICAgICAgICAgICAgICBpZiAobWluSW5kZXggPT09IG1heEluZGV4KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gY3VycmVudEl0ZW0gPj0gbGVmdCAmJiBjdXJyZW50SXRlbSA8PSByaWdodDtcbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIGlmIChjdXJyZW50SXRlbSA8IGxlZnQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIG1pbkluZGV4ID0gY3VycmVudEluZGV4ICsgMTtcbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIGlmIChjdXJyZW50SXRlbSA+IHJpZ2h0KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBtYXhJbmRleCA9IGN1cnJlbnRJbmRleCAtIDE7XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZnVuY3Rpb24gYXNjZW5kaW5nKGEsIGIpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gYSA+IGIgPyAxIDogLTE7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0sIHt9XSwgMTc6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICB2YXIgYXBwbHlQcm9wZXJ0aWVzID0gcmVxdWlyZShcIi4vYXBwbHktcHJvcGVydGllc1wiKTtcblxuICAgICAgICAgICAgdmFyIGlzV2lkZ2V0ID0gcmVxdWlyZShcIi4uL3Zub2RlL2lzLXdpZGdldC5qc1wiKTtcbiAgICAgICAgICAgIHZhciBWUGF0Y2ggPSByZXF1aXJlKFwiLi4vdm5vZGUvdnBhdGNoLmpzXCIpO1xuXG4gICAgICAgICAgICB2YXIgdXBkYXRlV2lkZ2V0ID0gcmVxdWlyZShcIi4vdXBkYXRlLXdpZGdldFwiKTtcblxuICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBhcHBseVBhdGNoO1xuXG4gICAgICAgICAgICBmdW5jdGlvbiBhcHBseVBhdGNoKHZwYXRjaCwgZG9tTm9kZSwgcmVuZGVyT3B0aW9ucykge1xuICAgICAgICAgICAgICAgIHZhciB0eXBlID0gdnBhdGNoLnR5cGU7XG4gICAgICAgICAgICAgICAgdmFyIHZOb2RlID0gdnBhdGNoLnZOb2RlO1xuICAgICAgICAgICAgICAgIHZhciBwYXRjaCA9IHZwYXRjaC5wYXRjaDtcblxuICAgICAgICAgICAgICAgIHN3aXRjaCAodHlwZSkge1xuICAgICAgICAgICAgICAgICAgICBjYXNlIFZQYXRjaC5SRU1PVkU6XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gcmVtb3ZlTm9kZShkb21Ob2RlLCB2Tm9kZSk7XG4gICAgICAgICAgICAgICAgICAgIGNhc2UgVlBhdGNoLklOU0VSVDpcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBpbnNlcnROb2RlKGRvbU5vZGUsIHBhdGNoLCByZW5kZXJPcHRpb25zKTtcbiAgICAgICAgICAgICAgICAgICAgY2FzZSBWUGF0Y2guVlRFWFQ6XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gc3RyaW5nUGF0Y2goZG9tTm9kZSwgdk5vZGUsIHBhdGNoLCByZW5kZXJPcHRpb25zKTtcbiAgICAgICAgICAgICAgICAgICAgY2FzZSBWUGF0Y2guV0lER0VUOlxuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHdpZGdldFBhdGNoKGRvbU5vZGUsIHZOb2RlLCBwYXRjaCwgcmVuZGVyT3B0aW9ucyk7XG4gICAgICAgICAgICAgICAgICAgIGNhc2UgVlBhdGNoLlZOT0RFOlxuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHZOb2RlUGF0Y2goZG9tTm9kZSwgdk5vZGUsIHBhdGNoLCByZW5kZXJPcHRpb25zKTtcbiAgICAgICAgICAgICAgICAgICAgY2FzZSBWUGF0Y2guT1JERVI6XG4gICAgICAgICAgICAgICAgICAgICAgICByZW9yZGVyQ2hpbGRyZW4oZG9tTm9kZSwgcGF0Y2gpO1xuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGRvbU5vZGU7XG4gICAgICAgICAgICAgICAgICAgIGNhc2UgVlBhdGNoLlBST1BTOlxuICAgICAgICAgICAgICAgICAgICAgICAgYXBwbHlQcm9wZXJ0aWVzKGRvbU5vZGUsIHBhdGNoLCB2Tm9kZS5wcm9wZXJ0aWVzKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBkb21Ob2RlO1xuICAgICAgICAgICAgICAgICAgICBjYXNlIFZQYXRjaC5USFVOSzpcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiByZXBsYWNlUm9vdChkb21Ob2RlLCByZW5kZXJPcHRpb25zLnBhdGNoKGRvbU5vZGUsIHBhdGNoLCByZW5kZXJPcHRpb25zKSk7XG4gICAgICAgICAgICAgICAgICAgIGRlZmF1bHQ6XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gZG9tTm9kZTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIHJlbW92ZU5vZGUoZG9tTm9kZSwgdk5vZGUpIHtcbiAgICAgICAgICAgICAgICB2YXIgcGFyZW50Tm9kZSA9IGRvbU5vZGUucGFyZW50Tm9kZTtcblxuICAgICAgICAgICAgICAgIGlmIChwYXJlbnROb2RlKSB7XG4gICAgICAgICAgICAgICAgICAgIHBhcmVudE5vZGUucmVtb3ZlQ2hpbGQoZG9tTm9kZSk7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgZGVzdHJveVdpZGdldChkb21Ob2RlLCB2Tm9kZSk7XG5cbiAgICAgICAgICAgICAgICByZXR1cm4gbnVsbDtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZnVuY3Rpb24gaW5zZXJ0Tm9kZShwYXJlbnROb2RlLCB2Tm9kZSwgcmVuZGVyT3B0aW9ucykge1xuICAgICAgICAgICAgICAgIHZhciBuZXdOb2RlID0gcmVuZGVyT3B0aW9ucy5yZW5kZXIodk5vZGUsIHJlbmRlck9wdGlvbnMpO1xuXG4gICAgICAgICAgICAgICAgaWYgKHBhcmVudE5vZGUpIHtcbiAgICAgICAgICAgICAgICAgICAgcGFyZW50Tm9kZS5hcHBlbmRDaGlsZChuZXdOb2RlKTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICByZXR1cm4gcGFyZW50Tm9kZTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZnVuY3Rpb24gc3RyaW5nUGF0Y2goZG9tTm9kZSwgbGVmdFZOb2RlLCB2VGV4dCwgcmVuZGVyT3B0aW9ucykge1xuICAgICAgICAgICAgICAgIHZhciBuZXdOb2RlO1xuXG4gICAgICAgICAgICAgICAgaWYgKGRvbU5vZGUubm9kZVR5cGUgPT09IDMpIHtcbiAgICAgICAgICAgICAgICAgICAgZG9tTm9kZS5yZXBsYWNlRGF0YSgwLCBkb21Ob2RlLmxlbmd0aCwgdlRleHQudGV4dCk7XG4gICAgICAgICAgICAgICAgICAgIG5ld05vZGUgPSBkb21Ob2RlO1xuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciBwYXJlbnROb2RlID0gZG9tTm9kZS5wYXJlbnROb2RlO1xuICAgICAgICAgICAgICAgICAgICBuZXdOb2RlID0gcmVuZGVyT3B0aW9ucy5yZW5kZXIodlRleHQsIHJlbmRlck9wdGlvbnMpO1xuXG4gICAgICAgICAgICAgICAgICAgIGlmIChwYXJlbnROb2RlICYmIG5ld05vZGUgIT09IGRvbU5vZGUpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHBhcmVudE5vZGUucmVwbGFjZUNoaWxkKG5ld05vZGUsIGRvbU5vZGUpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgcmV0dXJuIG5ld05vZGU7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIHdpZGdldFBhdGNoKGRvbU5vZGUsIGxlZnRWTm9kZSwgd2lkZ2V0LCByZW5kZXJPcHRpb25zKSB7XG4gICAgICAgICAgICAgICAgdmFyIHVwZGF0aW5nID0gdXBkYXRlV2lkZ2V0KGxlZnRWTm9kZSwgd2lkZ2V0KTtcbiAgICAgICAgICAgICAgICB2YXIgbmV3Tm9kZTtcblxuICAgICAgICAgICAgICAgIGlmICh1cGRhdGluZykge1xuICAgICAgICAgICAgICAgICAgICBuZXdOb2RlID0gd2lkZ2V0LnVwZGF0ZShsZWZ0Vk5vZGUsIGRvbU5vZGUpIHx8IGRvbU5vZGU7XG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgbmV3Tm9kZSA9IHJlbmRlck9wdGlvbnMucmVuZGVyKHdpZGdldCwgcmVuZGVyT3B0aW9ucyk7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgdmFyIHBhcmVudE5vZGUgPSBkb21Ob2RlLnBhcmVudE5vZGU7XG5cbiAgICAgICAgICAgICAgICBpZiAocGFyZW50Tm9kZSAmJiBuZXdOb2RlICE9PSBkb21Ob2RlKSB7XG4gICAgICAgICAgICAgICAgICAgIHBhcmVudE5vZGUucmVwbGFjZUNoaWxkKG5ld05vZGUsIGRvbU5vZGUpO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIGlmICghdXBkYXRpbmcpIHtcbiAgICAgICAgICAgICAgICAgICAgZGVzdHJveVdpZGdldChkb21Ob2RlLCBsZWZ0Vk5vZGUpO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHJldHVybiBuZXdOb2RlO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBmdW5jdGlvbiB2Tm9kZVBhdGNoKGRvbU5vZGUsIGxlZnRWTm9kZSwgdk5vZGUsIHJlbmRlck9wdGlvbnMpIHtcbiAgICAgICAgICAgICAgICB2YXIgcGFyZW50Tm9kZSA9IGRvbU5vZGUucGFyZW50Tm9kZTtcbiAgICAgICAgICAgICAgICB2YXIgbmV3Tm9kZSA9IHJlbmRlck9wdGlvbnMucmVuZGVyKHZOb2RlLCByZW5kZXJPcHRpb25zKTtcblxuICAgICAgICAgICAgICAgIGlmIChwYXJlbnROb2RlICYmIG5ld05vZGUgIT09IGRvbU5vZGUpIHtcbiAgICAgICAgICAgICAgICAgICAgcGFyZW50Tm9kZS5yZXBsYWNlQ2hpbGQobmV3Tm9kZSwgZG9tTm9kZSk7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgcmV0dXJuIG5ld05vZGU7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIGRlc3Ryb3lXaWRnZXQoZG9tTm9kZSwgdykge1xuICAgICAgICAgICAgICAgIGlmICh0eXBlb2Ygdy5kZXN0cm95ID09PSBcImZ1bmN0aW9uXCIgJiYgaXNXaWRnZXQodykpIHtcbiAgICAgICAgICAgICAgICAgICAgdy5kZXN0cm95KGRvbU5vZGUpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZnVuY3Rpb24gcmVvcmRlckNoaWxkcmVuKGRvbU5vZGUsIG1vdmVzKSB7XG4gICAgICAgICAgICAgICAgdmFyIGNoaWxkTm9kZXMgPSBkb21Ob2RlLmNoaWxkTm9kZXM7XG4gICAgICAgICAgICAgICAgdmFyIGtleU1hcCA9IHt9O1xuICAgICAgICAgICAgICAgIHZhciBub2RlO1xuICAgICAgICAgICAgICAgIHZhciByZW1vdmU7XG4gICAgICAgICAgICAgICAgdmFyIGluc2VydDtcblxuICAgICAgICAgICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgbW92ZXMucmVtb3Zlcy5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgICAgICAgICByZW1vdmUgPSBtb3Zlcy5yZW1vdmVzW2ldO1xuICAgICAgICAgICAgICAgICAgICBub2RlID0gY2hpbGROb2Rlc1tyZW1vdmUuZnJvbV07XG4gICAgICAgICAgICAgICAgICAgIGlmIChyZW1vdmUua2V5KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBrZXlNYXBbcmVtb3ZlLmtleV0gPSBub2RlO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIGRvbU5vZGUucmVtb3ZlQ2hpbGQobm9kZSk7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgdmFyIGxlbmd0aCA9IGNoaWxkTm9kZXMubGVuZ3RoO1xuICAgICAgICAgICAgICAgIGZvciAodmFyIGogPSAwOyBqIDwgbW92ZXMuaW5zZXJ0cy5sZW5ndGg7IGorKykge1xuICAgICAgICAgICAgICAgICAgICBpbnNlcnQgPSBtb3Zlcy5pbnNlcnRzW2pdO1xuICAgICAgICAgICAgICAgICAgICBub2RlID0ga2V5TWFwW2luc2VydC5rZXldO1xuICAgICAgICAgICAgICAgICAgICAvLyB0aGlzIGlzIHRoZSB3ZWlyZGVzdCBidWcgaSd2ZSBldmVyIHNlZW4gaW4gd2Via2l0XG4gICAgICAgICAgICAgICAgICAgIGRvbU5vZGUuaW5zZXJ0QmVmb3JlKG5vZGUsIGluc2VydC50byA+PSBsZW5ndGgrKyA/IG51bGwgOiBjaGlsZE5vZGVzW2luc2VydC50b10pO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZnVuY3Rpb24gcmVwbGFjZVJvb3Qob2xkUm9vdCwgbmV3Um9vdCkge1xuICAgICAgICAgICAgICAgIGlmIChvbGRSb290ICYmIG5ld1Jvb3QgJiYgb2xkUm9vdCAhPT0gbmV3Um9vdCAmJiBvbGRSb290LnBhcmVudE5vZGUpIHtcbiAgICAgICAgICAgICAgICAgICAgb2xkUm9vdC5wYXJlbnROb2RlLnJlcGxhY2VDaGlsZChuZXdSb290LCBvbGRSb290KTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICByZXR1cm4gbmV3Um9vdDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSwgeyBcIi4uL3Zub2RlL2lzLXdpZGdldC5qc1wiOiAyOSwgXCIuLi92bm9kZS92cGF0Y2guanNcIjogMzIsIFwiLi9hcHBseS1wcm9wZXJ0aWVzXCI6IDE0LCBcIi4vdXBkYXRlLXdpZGdldFwiOiAxOSB9XSwgMTg6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICB2YXIgZG9jdW1lbnQgPSByZXF1aXJlKFwiZ2xvYmFsL2RvY3VtZW50XCIpO1xuICAgICAgICAgICAgdmFyIGlzQXJyYXkgPSByZXF1aXJlKFwieC1pcy1hcnJheVwiKTtcblxuICAgICAgICAgICAgdmFyIHJlbmRlciA9IHJlcXVpcmUoXCIuL2NyZWF0ZS1lbGVtZW50XCIpO1xuICAgICAgICAgICAgdmFyIGRvbUluZGV4ID0gcmVxdWlyZShcIi4vZG9tLWluZGV4XCIpO1xuICAgICAgICAgICAgdmFyIHBhdGNoT3AgPSByZXF1aXJlKFwiLi9wYXRjaC1vcFwiKTtcbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gcGF0Y2g7XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIHBhdGNoKHJvb3ROb2RlLCBwYXRjaGVzLCByZW5kZXJPcHRpb25zKSB7XG4gICAgICAgICAgICAgICAgcmVuZGVyT3B0aW9ucyA9IHJlbmRlck9wdGlvbnMgfHwge307XG4gICAgICAgICAgICAgICAgcmVuZGVyT3B0aW9ucy5wYXRjaCA9IHJlbmRlck9wdGlvbnMucGF0Y2ggJiYgcmVuZGVyT3B0aW9ucy5wYXRjaCAhPT0gcGF0Y2ggPyByZW5kZXJPcHRpb25zLnBhdGNoIDogcGF0Y2hSZWN1cnNpdmU7XG4gICAgICAgICAgICAgICAgcmVuZGVyT3B0aW9ucy5yZW5kZXIgPSByZW5kZXJPcHRpb25zLnJlbmRlciB8fCByZW5kZXI7XG5cbiAgICAgICAgICAgICAgICByZXR1cm4gcmVuZGVyT3B0aW9ucy5wYXRjaChyb290Tm9kZSwgcGF0Y2hlcywgcmVuZGVyT3B0aW9ucyk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIHBhdGNoUmVjdXJzaXZlKHJvb3ROb2RlLCBwYXRjaGVzLCByZW5kZXJPcHRpb25zKSB7XG4gICAgICAgICAgICAgICAgdmFyIGluZGljZXMgPSBwYXRjaEluZGljZXMocGF0Y2hlcyk7XG5cbiAgICAgICAgICAgICAgICBpZiAoaW5kaWNlcy5sZW5ndGggPT09IDApIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHJvb3ROb2RlO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHZhciBpbmRleCA9IGRvbUluZGV4KHJvb3ROb2RlLCBwYXRjaGVzLmEsIGluZGljZXMpO1xuICAgICAgICAgICAgICAgIHZhciBvd25lckRvY3VtZW50ID0gcm9vdE5vZGUub3duZXJEb2N1bWVudDtcblxuICAgICAgICAgICAgICAgIGlmICghcmVuZGVyT3B0aW9ucy5kb2N1bWVudCAmJiBvd25lckRvY3VtZW50ICE9PSBkb2N1bWVudCkge1xuICAgICAgICAgICAgICAgICAgICByZW5kZXJPcHRpb25zLmRvY3VtZW50ID0gb3duZXJEb2N1bWVudDtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IGluZGljZXMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgICAgICAgICAgdmFyIG5vZGVJbmRleCA9IGluZGljZXNbaV07XG4gICAgICAgICAgICAgICAgICAgIHJvb3ROb2RlID0gYXBwbHlQYXRjaChyb290Tm9kZSwgaW5kZXhbbm9kZUluZGV4XSwgcGF0Y2hlc1tub2RlSW5kZXhdLCByZW5kZXJPcHRpb25zKTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICByZXR1cm4gcm9vdE5vZGU7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIGFwcGx5UGF0Y2gocm9vdE5vZGUsIGRvbU5vZGUsIHBhdGNoTGlzdCwgcmVuZGVyT3B0aW9ucykge1xuICAgICAgICAgICAgICAgIGlmICghZG9tTm9kZSkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gcm9vdE5vZGU7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgdmFyIG5ld05vZGU7XG5cbiAgICAgICAgICAgICAgICBpZiAoaXNBcnJheShwYXRjaExpc3QpKSB7XG4gICAgICAgICAgICAgICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgcGF0Y2hMaXN0Lmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBuZXdOb2RlID0gcGF0Y2hPcChwYXRjaExpc3RbaV0sIGRvbU5vZGUsIHJlbmRlck9wdGlvbnMpO1xuXG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoZG9tTm9kZSA9PT0gcm9vdE5vZGUpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICByb290Tm9kZSA9IG5ld05vZGU7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICBuZXdOb2RlID0gcGF0Y2hPcChwYXRjaExpc3QsIGRvbU5vZGUsIHJlbmRlck9wdGlvbnMpO1xuXG4gICAgICAgICAgICAgICAgICAgIGlmIChkb21Ob2RlID09PSByb290Tm9kZSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgcm9vdE5vZGUgPSBuZXdOb2RlO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgcmV0dXJuIHJvb3ROb2RlO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBmdW5jdGlvbiBwYXRjaEluZGljZXMocGF0Y2hlcykge1xuICAgICAgICAgICAgICAgIHZhciBpbmRpY2VzID0gW107XG5cbiAgICAgICAgICAgICAgICBmb3IgKHZhciBrZXkgaW4gcGF0Y2hlcykge1xuICAgICAgICAgICAgICAgICAgICBpZiAoa2V5ICE9PSBcImFcIikge1xuICAgICAgICAgICAgICAgICAgICAgICAgaW5kaWNlcy5wdXNoKE51bWJlcihrZXkpKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHJldHVybiBpbmRpY2VzO1xuICAgICAgICAgICAgfVxuICAgICAgICB9LCB7IFwiLi9jcmVhdGUtZWxlbWVudFwiOiAxNSwgXCIuL2RvbS1pbmRleFwiOiAxNiwgXCIuL3BhdGNoLW9wXCI6IDE3LCBcImdsb2JhbC9kb2N1bWVudFwiOiAxMCwgXCJ4LWlzLWFycmF5XCI6IDEyIH1dLCAxOTogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHtcbiAgICAgICAgICAgIHZhciBpc1dpZGdldCA9IHJlcXVpcmUoXCIuLi92bm9kZS9pcy13aWRnZXQuanNcIik7XG5cbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gdXBkYXRlV2lkZ2V0O1xuXG4gICAgICAgICAgICBmdW5jdGlvbiB1cGRhdGVXaWRnZXQoYSwgYikge1xuICAgICAgICAgICAgICAgIGlmIChpc1dpZGdldChhKSAmJiBpc1dpZGdldChiKSkge1xuICAgICAgICAgICAgICAgICAgICBpZiAoXCJuYW1lXCIgaW4gYSAmJiBcIm5hbWVcIiBpbiBiKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gYS5pZCA9PT0gYi5pZDtcbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBhLmluaXQgPT09IGIuaW5pdDtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSwgeyBcIi4uL3Zub2RlL2lzLXdpZGdldC5qc1wiOiAyOSB9XSwgMjA6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICBcInVzZSBzdHJpY3RcIjtcblxuICAgICAgICAgICAgdmFyIEV2U3RvcmUgPSByZXF1aXJlKFwiZXYtc3RvcmVcIik7XG5cbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gRXZIb29rO1xuXG4gICAgICAgICAgICBmdW5jdGlvbiBFdkhvb2sodmFsdWUpIHtcbiAgICAgICAgICAgICAgICBpZiAoISh0aGlzIGluc3RhbmNlb2YgRXZIb29rKSkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gbmV3IEV2SG9vayh2YWx1ZSk7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgdGhpcy52YWx1ZSA9IHZhbHVlO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBFdkhvb2sucHJvdG90eXBlLmhvb2sgPSBmdW5jdGlvbiAobm9kZSwgcHJvcGVydHlOYW1lKSB7XG4gICAgICAgICAgICAgICAgdmFyIGVzID0gRXZTdG9yZShub2RlKTtcbiAgICAgICAgICAgICAgICB2YXIgcHJvcE5hbWUgPSBwcm9wZXJ0eU5hbWUuc3Vic3RyKDMpO1xuXG4gICAgICAgICAgICAgICAgZXNbcHJvcE5hbWVdID0gdGhpcy52YWx1ZTtcbiAgICAgICAgICAgIH07XG5cbiAgICAgICAgICAgIEV2SG9vay5wcm90b3R5cGUudW5ob29rID0gZnVuY3Rpb24gKG5vZGUsIHByb3BlcnR5TmFtZSkge1xuICAgICAgICAgICAgICAgIHZhciBlcyA9IEV2U3RvcmUobm9kZSk7XG4gICAgICAgICAgICAgICAgdmFyIHByb3BOYW1lID0gcHJvcGVydHlOYW1lLnN1YnN0cigzKTtcblxuICAgICAgICAgICAgICAgIGVzW3Byb3BOYW1lXSA9IHVuZGVmaW5lZDtcbiAgICAgICAgICAgIH07XG4gICAgICAgIH0sIHsgXCJldi1zdG9yZVwiOiA3IH1dLCAyMTogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHtcbiAgICAgICAgICAgIFwidXNlIHN0cmljdFwiO1xuXG4gICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IFNvZnRTZXRIb29rO1xuXG4gICAgICAgICAgICBmdW5jdGlvbiBTb2Z0U2V0SG9vayh2YWx1ZSkge1xuICAgICAgICAgICAgICAgIGlmICghKHRoaXMgaW5zdGFuY2VvZiBTb2Z0U2V0SG9vaykpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIG5ldyBTb2Z0U2V0SG9vayh2YWx1ZSk7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgdGhpcy52YWx1ZSA9IHZhbHVlO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBTb2Z0U2V0SG9vay5wcm90b3R5cGUuaG9vayA9IGZ1bmN0aW9uIChub2RlLCBwcm9wZXJ0eU5hbWUpIHtcbiAgICAgICAgICAgICAgICBpZiAobm9kZVtwcm9wZXJ0eU5hbWVdICE9PSB0aGlzLnZhbHVlKSB7XG4gICAgICAgICAgICAgICAgICAgIG5vZGVbcHJvcGVydHlOYW1lXSA9IHRoaXMudmFsdWU7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfTtcbiAgICAgICAgfSwge31dLCAyMjogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHtcbiAgICAgICAgICAgIFwidXNlIHN0cmljdFwiO1xuXG4gICAgICAgICAgICB2YXIgaXNBcnJheSA9IHJlcXVpcmUoXCJ4LWlzLWFycmF5XCIpO1xuXG4gICAgICAgICAgICB2YXIgVk5vZGUgPSByZXF1aXJlKFwiLi4vdm5vZGUvdm5vZGUuanNcIik7XG4gICAgICAgICAgICB2YXIgVlRleHQgPSByZXF1aXJlKFwiLi4vdm5vZGUvdnRleHQuanNcIik7XG4gICAgICAgICAgICB2YXIgaXNWTm9kZSA9IHJlcXVpcmUoXCIuLi92bm9kZS9pcy12bm9kZVwiKTtcbiAgICAgICAgICAgIHZhciBpc1ZUZXh0ID0gcmVxdWlyZShcIi4uL3Zub2RlL2lzLXZ0ZXh0XCIpO1xuICAgICAgICAgICAgdmFyIGlzV2lkZ2V0ID0gcmVxdWlyZShcIi4uL3Zub2RlL2lzLXdpZGdldFwiKTtcbiAgICAgICAgICAgIHZhciBpc0hvb2sgPSByZXF1aXJlKFwiLi4vdm5vZGUvaXMtdmhvb2tcIik7XG4gICAgICAgICAgICB2YXIgaXNWVGh1bmsgPSByZXF1aXJlKFwiLi4vdm5vZGUvaXMtdGh1bmtcIik7XG5cbiAgICAgICAgICAgIHZhciBwYXJzZVRhZyA9IHJlcXVpcmUoXCIuL3BhcnNlLXRhZy5qc1wiKTtcbiAgICAgICAgICAgIHZhciBzb2Z0U2V0SG9vayA9IHJlcXVpcmUoXCIuL2hvb2tzL3NvZnQtc2V0LWhvb2suanNcIik7XG4gICAgICAgICAgICB2YXIgZXZIb29rID0gcmVxdWlyZShcIi4vaG9va3MvZXYtaG9vay5qc1wiKTtcblxuICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBoO1xuXG4gICAgICAgICAgICBmdW5jdGlvbiBoKHRhZ05hbWUsIHByb3BlcnRpZXMsIGNoaWxkcmVuKSB7XG4gICAgICAgICAgICAgICAgdmFyIGNoaWxkTm9kZXMgPSBbXTtcbiAgICAgICAgICAgICAgICB2YXIgdGFnLCBwcm9wcywga2V5LCBuYW1lc3BhY2U7XG5cbiAgICAgICAgICAgICAgICBpZiAoIWNoaWxkcmVuICYmIGlzQ2hpbGRyZW4ocHJvcGVydGllcykpIHtcbiAgICAgICAgICAgICAgICAgICAgY2hpbGRyZW4gPSBwcm9wZXJ0aWVzO1xuICAgICAgICAgICAgICAgICAgICBwcm9wcyA9IHt9O1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHByb3BzID0gcHJvcHMgfHwgcHJvcGVydGllcyB8fCB7fTtcbiAgICAgICAgICAgICAgICB0YWcgPSBwYXJzZVRhZyh0YWdOYW1lLCBwcm9wcyk7XG5cbiAgICAgICAgICAgICAgICAvLyBzdXBwb3J0IGtleXNcbiAgICAgICAgICAgICAgICBpZiAocHJvcHMuaGFzT3duUHJvcGVydHkoXCJrZXlcIikpIHtcbiAgICAgICAgICAgICAgICAgICAga2V5ID0gcHJvcHMua2V5O1xuICAgICAgICAgICAgICAgICAgICBwcm9wcy5rZXkgPSB1bmRlZmluZWQ7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgLy8gc3VwcG9ydCBuYW1lc3BhY2VcbiAgICAgICAgICAgICAgICBpZiAocHJvcHMuaGFzT3duUHJvcGVydHkoXCJuYW1lc3BhY2VcIikpIHtcbiAgICAgICAgICAgICAgICAgICAgbmFtZXNwYWNlID0gcHJvcHMubmFtZXNwYWNlO1xuICAgICAgICAgICAgICAgICAgICBwcm9wcy5uYW1lc3BhY2UgPSB1bmRlZmluZWQ7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgLy8gZml4IGN1cnNvciBidWdcbiAgICAgICAgICAgICAgICBpZiAodGFnID09PSBcIklOUFVUXCIgJiYgIW5hbWVzcGFjZSAmJiBwcm9wcy5oYXNPd25Qcm9wZXJ0eShcInZhbHVlXCIpICYmIHByb3BzLnZhbHVlICE9PSB1bmRlZmluZWQgJiYgIWlzSG9vayhwcm9wcy52YWx1ZSkpIHtcbiAgICAgICAgICAgICAgICAgICAgcHJvcHMudmFsdWUgPSBzb2Z0U2V0SG9vayhwcm9wcy52YWx1ZSk7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgdHJhbnNmb3JtUHJvcGVydGllcyhwcm9wcyk7XG5cbiAgICAgICAgICAgICAgICBpZiAoY2hpbGRyZW4gIT09IHVuZGVmaW5lZCAmJiBjaGlsZHJlbiAhPT0gbnVsbCkge1xuICAgICAgICAgICAgICAgICAgICBhZGRDaGlsZChjaGlsZHJlbiwgY2hpbGROb2RlcywgdGFnLCBwcm9wcyk7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgcmV0dXJuIG5ldyBWTm9kZSh0YWcsIHByb3BzLCBjaGlsZE5vZGVzLCBrZXksIG5hbWVzcGFjZSk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIGFkZENoaWxkKGMsIGNoaWxkTm9kZXMsIHRhZywgcHJvcHMpIHtcbiAgICAgICAgICAgICAgICBpZiAodHlwZW9mIGMgPT09IFwic3RyaW5nXCIpIHtcbiAgICAgICAgICAgICAgICAgICAgY2hpbGROb2Rlcy5wdXNoKG5ldyBWVGV4dChjKSk7XG4gICAgICAgICAgICAgICAgfSBlbHNlIGlmICh0eXBlb2YgYyA9PT0gXCJudW1iZXJcIikge1xuICAgICAgICAgICAgICAgICAgICBjaGlsZE5vZGVzLnB1c2gobmV3IFZUZXh0KFN0cmluZyhjKSkpO1xuICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoaXNDaGlsZChjKSkge1xuICAgICAgICAgICAgICAgICAgICBjaGlsZE5vZGVzLnB1c2goYyk7XG4gICAgICAgICAgICAgICAgfSBlbHNlIGlmIChpc0FycmF5KGMpKSB7XG4gICAgICAgICAgICAgICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgYy5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgICAgICAgICAgICAgYWRkQ2hpbGQoY1tpXSwgY2hpbGROb2RlcywgdGFnLCBwcm9wcyk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKGMgPT09IG51bGwgfHwgYyA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICB0aHJvdyBVbmV4cGVjdGVkVmlydHVhbEVsZW1lbnQoe1xuICAgICAgICAgICAgICAgICAgICAgICAgZm9yZWlnbk9iamVjdDogYyxcbiAgICAgICAgICAgICAgICAgICAgICAgIHBhcmVudFZub2RlOiB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdGFnTmFtZTogdGFnLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHByb3BlcnRpZXM6IHByb3BzXG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZnVuY3Rpb24gdHJhbnNmb3JtUHJvcGVydGllcyhwcm9wcykge1xuICAgICAgICAgICAgICAgIGZvciAodmFyIHByb3BOYW1lIGluIHByb3BzKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmIChwcm9wcy5oYXNPd25Qcm9wZXJ0eShwcm9wTmFtZSkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHZhciB2YWx1ZSA9IHByb3BzW3Byb3BOYW1lXTtcblxuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGlzSG9vayh2YWx1ZSkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb250aW51ZTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHByb3BOYW1lLnN1YnN0cigwLCAzKSA9PT0gXCJldi1cIikge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIGFkZCBldi1mb28gc3VwcG9ydFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHByb3BzW3Byb3BOYW1lXSA9IGV2SG9vayh2YWx1ZSk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIGlzQ2hpbGQoeCkge1xuICAgICAgICAgICAgICAgIHJldHVybiBpc1ZOb2RlKHgpIHx8IGlzVlRleHQoeCkgfHwgaXNXaWRnZXQoeCkgfHwgaXNWVGh1bmsoeCk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIGlzQ2hpbGRyZW4oeCkge1xuICAgICAgICAgICAgICAgIHJldHVybiB0eXBlb2YgeCA9PT0gXCJzdHJpbmdcIiB8fCBpc0FycmF5KHgpIHx8IGlzQ2hpbGQoeCk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIFVuZXhwZWN0ZWRWaXJ0dWFsRWxlbWVudChkYXRhKSB7XG4gICAgICAgICAgICAgICAgdmFyIGVyciA9IG5ldyBFcnJvcigpO1xuXG4gICAgICAgICAgICAgICAgZXJyLnR5cGUgPSBcInZpcnR1YWwtaHlwZXJzY3JpcHQudW5leHBlY3RlZC52aXJ0dWFsLWVsZW1lbnRcIjtcbiAgICAgICAgICAgICAgICBlcnIubWVzc2FnZSA9IFwiVW5leHBlY3RlZCB2aXJ0dWFsIGNoaWxkIHBhc3NlZCB0byBoKCkuXFxuXCIgKyBcIkV4cGVjdGVkIGEgVk5vZGUgLyBWdGh1bmsgLyBWV2lkZ2V0IC8gc3RyaW5nIGJ1dDpcXG5cIiArIFwiZ290OlxcblwiICsgZXJyb3JTdHJpbmcoZGF0YS5mb3JlaWduT2JqZWN0KSArIFwiLlxcblwiICsgXCJUaGUgcGFyZW50IHZub2RlIGlzOlxcblwiICsgZXJyb3JTdHJpbmcoZGF0YS5wYXJlbnRWbm9kZSk7XG4gICAgICAgICAgICAgICAgXCJcXG5cIiArIFwiU3VnZ2VzdGVkIGZpeDogY2hhbmdlIHlvdXIgYGgoLi4uLCBbIC4uLiBdKWAgY2FsbHNpdGUuXCI7XG4gICAgICAgICAgICAgICAgZXJyLmZvcmVpZ25PYmplY3QgPSBkYXRhLmZvcmVpZ25PYmplY3Q7XG4gICAgICAgICAgICAgICAgZXJyLnBhcmVudFZub2RlID0gZGF0YS5wYXJlbnRWbm9kZTtcblxuICAgICAgICAgICAgICAgIHJldHVybiBlcnI7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIGVycm9yU3RyaW5nKG9iaikge1xuICAgICAgICAgICAgICAgIHRyeSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBKU09OLnN0cmluZ2lmeShvYmosIG51bGwsIFwiICAgIFwiKTtcbiAgICAgICAgICAgICAgICB9IGNhdGNoIChlKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBTdHJpbmcob2JqKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH0sIHsgXCIuLi92bm9kZS9pcy10aHVua1wiOiAyNSwgXCIuLi92bm9kZS9pcy12aG9va1wiOiAyNiwgXCIuLi92bm9kZS9pcy12bm9kZVwiOiAyNywgXCIuLi92bm9kZS9pcy12dGV4dFwiOiAyOCwgXCIuLi92bm9kZS9pcy13aWRnZXRcIjogMjksIFwiLi4vdm5vZGUvdm5vZGUuanNcIjogMzEsIFwiLi4vdm5vZGUvdnRleHQuanNcIjogMzMsIFwiLi9ob29rcy9ldi1ob29rLmpzXCI6IDIwLCBcIi4vaG9va3Mvc29mdC1zZXQtaG9vay5qc1wiOiAyMSwgXCIuL3BhcnNlLXRhZy5qc1wiOiAyMywgXCJ4LWlzLWFycmF5XCI6IDEyIH1dLCAyMzogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHtcbiAgICAgICAgICAgIFwidXNlIHN0cmljdFwiO1xuXG4gICAgICAgICAgICB2YXIgc3BsaXQgPSByZXF1aXJlKFwiYnJvd3Nlci1zcGxpdFwiKTtcblxuICAgICAgICAgICAgdmFyIGNsYXNzSWRTcGxpdCA9IC8oW1xcLiNdP1thLXpBLVowLTlcXHUwMDdGLVxcdUZGRkZfOi1dKykvO1xuICAgICAgICAgICAgdmFyIG5vdENsYXNzSWQgPSAvXlxcLnwjLztcblxuICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBwYXJzZVRhZztcblxuICAgICAgICAgICAgZnVuY3Rpb24gcGFyc2VUYWcodGFnLCBwcm9wcykge1xuICAgICAgICAgICAgICAgIGlmICghdGFnKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBcIkRJVlwiO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHZhciBub0lkID0gIXByb3BzLmhhc093blByb3BlcnR5KFwiaWRcIik7XG5cbiAgICAgICAgICAgICAgICB2YXIgdGFnUGFydHMgPSBzcGxpdCh0YWcsIGNsYXNzSWRTcGxpdCk7XG4gICAgICAgICAgICAgICAgdmFyIHRhZ05hbWUgPSBudWxsO1xuXG4gICAgICAgICAgICAgICAgaWYgKG5vdENsYXNzSWQudGVzdCh0YWdQYXJ0c1sxXSkpIHtcbiAgICAgICAgICAgICAgICAgICAgdGFnTmFtZSA9IFwiRElWXCI7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgdmFyIGNsYXNzZXMsIHBhcnQsIHR5cGUsIGk7XG5cbiAgICAgICAgICAgICAgICBmb3IgKGkgPSAwOyBpIDwgdGFnUGFydHMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgICAgICAgICAgcGFydCA9IHRhZ1BhcnRzW2ldO1xuXG4gICAgICAgICAgICAgICAgICAgIGlmICghcGFydCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgY29udGludWU7XG4gICAgICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgICAgICB0eXBlID0gcGFydC5jaGFyQXQoMCk7XG5cbiAgICAgICAgICAgICAgICAgICAgaWYgKCF0YWdOYW1lKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICB0YWdOYW1lID0gcGFydDtcbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIGlmICh0eXBlID09PSBcIi5cIikge1xuICAgICAgICAgICAgICAgICAgICAgICAgY2xhc3NlcyA9IGNsYXNzZXMgfHwgW107XG4gICAgICAgICAgICAgICAgICAgICAgICBjbGFzc2VzLnB1c2gocGFydC5zdWJzdHJpbmcoMSwgcGFydC5sZW5ndGgpKTtcbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIGlmICh0eXBlID09PSBcIiNcIiAmJiBub0lkKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBwcm9wcy5pZCA9IHBhcnQuc3Vic3RyaW5nKDEsIHBhcnQubGVuZ3RoKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIGlmIChjbGFzc2VzKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmIChwcm9wcy5jbGFzc05hbWUpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGNsYXNzZXMucHVzaChwcm9wcy5jbGFzc05hbWUpO1xuICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgcHJvcHMuY2xhc3NOYW1lID0gY2xhc3Nlcy5qb2luKFwiIFwiKTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICByZXR1cm4gcHJvcHMubmFtZXNwYWNlID8gdGFnTmFtZSA6IHRhZ05hbWUudG9VcHBlckNhc2UoKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSwgeyBcImJyb3dzZXItc3BsaXRcIjogNSB9XSwgMjQ6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICB2YXIgaXNWTm9kZSA9IHJlcXVpcmUoXCIuL2lzLXZub2RlXCIpO1xuICAgICAgICAgICAgdmFyIGlzVlRleHQgPSByZXF1aXJlKFwiLi9pcy12dGV4dFwiKTtcbiAgICAgICAgICAgIHZhciBpc1dpZGdldCA9IHJlcXVpcmUoXCIuL2lzLXdpZGdldFwiKTtcbiAgICAgICAgICAgIHZhciBpc1RodW5rID0gcmVxdWlyZShcIi4vaXMtdGh1bmtcIik7XG5cbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gaGFuZGxlVGh1bms7XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIGhhbmRsZVRodW5rKGEsIGIpIHtcbiAgICAgICAgICAgICAgICB2YXIgcmVuZGVyZWRBID0gYTtcbiAgICAgICAgICAgICAgICB2YXIgcmVuZGVyZWRCID0gYjtcblxuICAgICAgICAgICAgICAgIGlmIChpc1RodW5rKGIpKSB7XG4gICAgICAgICAgICAgICAgICAgIHJlbmRlcmVkQiA9IHJlbmRlclRodW5rKGIsIGEpO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIGlmIChpc1RodW5rKGEpKSB7XG4gICAgICAgICAgICAgICAgICAgIHJlbmRlcmVkQSA9IHJlbmRlclRodW5rKGEsIG51bGwpO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHJldHVybiB7XG4gICAgICAgICAgICAgICAgICAgIGE6IHJlbmRlcmVkQSxcbiAgICAgICAgICAgICAgICAgICAgYjogcmVuZGVyZWRCXG4gICAgICAgICAgICAgICAgfTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZnVuY3Rpb24gcmVuZGVyVGh1bmsodGh1bmssIHByZXZpb3VzKSB7XG4gICAgICAgICAgICAgICAgdmFyIHJlbmRlcmVkVGh1bmsgPSB0aHVuay52bm9kZTtcblxuICAgICAgICAgICAgICAgIGlmICghcmVuZGVyZWRUaHVuaykge1xuICAgICAgICAgICAgICAgICAgICByZW5kZXJlZFRodW5rID0gdGh1bmsudm5vZGUgPSB0aHVuay5yZW5kZXIocHJldmlvdXMpO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIGlmICghKGlzVk5vZGUocmVuZGVyZWRUaHVuaykgfHwgaXNWVGV4dChyZW5kZXJlZFRodW5rKSB8fCBpc1dpZGdldChyZW5kZXJlZFRodW5rKSkpIHtcbiAgICAgICAgICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKFwidGh1bmsgZGlkIG5vdCByZXR1cm4gYSB2YWxpZCBub2RlXCIpO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHJldHVybiByZW5kZXJlZFRodW5rO1xuICAgICAgICAgICAgfVxuICAgICAgICB9LCB7IFwiLi9pcy10aHVua1wiOiAyNSwgXCIuL2lzLXZub2RlXCI6IDI3LCBcIi4vaXMtdnRleHRcIjogMjgsIFwiLi9pcy13aWRnZXRcIjogMjkgfV0sIDI1OiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge1xuICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBpc1RodW5rO1xuXG4gICAgICAgICAgICBmdW5jdGlvbiBpc1RodW5rKHQpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gdCAmJiB0LnR5cGUgPT09IFwiVGh1bmtcIjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSwge31dLCAyNjogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHtcbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gaXNIb29rO1xuXG4gICAgICAgICAgICBmdW5jdGlvbiBpc0hvb2soaG9vaykge1xuICAgICAgICAgICAgICAgIHJldHVybiBob29rICYmICh0eXBlb2YgaG9vay5ob29rID09PSBcImZ1bmN0aW9uXCIgJiYgIWhvb2suaGFzT3duUHJvcGVydHkoXCJob29rXCIpIHx8IHR5cGVvZiBob29rLnVuaG9vayA9PT0gXCJmdW5jdGlvblwiICYmICFob29rLmhhc093blByb3BlcnR5KFwidW5ob29rXCIpKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSwge31dLCAyNzogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHtcbiAgICAgICAgICAgIHZhciB2ZXJzaW9uID0gcmVxdWlyZShcIi4vdmVyc2lvblwiKTtcblxuICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBpc1ZpcnR1YWxOb2RlO1xuXG4gICAgICAgICAgICBmdW5jdGlvbiBpc1ZpcnR1YWxOb2RlKHgpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4geCAmJiB4LnR5cGUgPT09IFwiVmlydHVhbE5vZGVcIiAmJiB4LnZlcnNpb24gPT09IHZlcnNpb247XG4gICAgICAgICAgICB9XG4gICAgICAgIH0sIHsgXCIuL3ZlcnNpb25cIjogMzAgfV0sIDI4OiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge1xuICAgICAgICAgICAgdmFyIHZlcnNpb24gPSByZXF1aXJlKFwiLi92ZXJzaW9uXCIpO1xuXG4gICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IGlzVmlydHVhbFRleHQ7XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIGlzVmlydHVhbFRleHQoeCkge1xuICAgICAgICAgICAgICAgIHJldHVybiB4ICYmIHgudHlwZSA9PT0gXCJWaXJ0dWFsVGV4dFwiICYmIHgudmVyc2lvbiA9PT0gdmVyc2lvbjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSwgeyBcIi4vdmVyc2lvblwiOiAzMCB9XSwgMjk6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IGlzV2lkZ2V0O1xuXG4gICAgICAgICAgICBmdW5jdGlvbiBpc1dpZGdldCh3KSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHcgJiYgdy50eXBlID09PSBcIldpZGdldFwiO1xuICAgICAgICAgICAgfVxuICAgICAgICB9LCB7fV0sIDMwOiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge1xuICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBcIjJcIjtcbiAgICAgICAgfSwge31dLCAzMTogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHtcbiAgICAgICAgICAgIHZhciB2ZXJzaW9uID0gcmVxdWlyZShcIi4vdmVyc2lvblwiKTtcbiAgICAgICAgICAgIHZhciBpc1ZOb2RlID0gcmVxdWlyZShcIi4vaXMtdm5vZGVcIik7XG4gICAgICAgICAgICB2YXIgaXNXaWRnZXQgPSByZXF1aXJlKFwiLi9pcy13aWRnZXRcIik7XG4gICAgICAgICAgICB2YXIgaXNUaHVuayA9IHJlcXVpcmUoXCIuL2lzLXRodW5rXCIpO1xuICAgICAgICAgICAgdmFyIGlzVkhvb2sgPSByZXF1aXJlKFwiLi9pcy12aG9va1wiKTtcblxuICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBWaXJ0dWFsTm9kZTtcblxuICAgICAgICAgICAgdmFyIG5vUHJvcGVydGllcyA9IHt9O1xuICAgICAgICAgICAgdmFyIG5vQ2hpbGRyZW4gPSBbXTtcblxuICAgICAgICAgICAgZnVuY3Rpb24gVmlydHVhbE5vZGUodGFnTmFtZSwgcHJvcGVydGllcywgY2hpbGRyZW4sIGtleSwgbmFtZXNwYWNlKSB7XG4gICAgICAgICAgICAgICAgdGhpcy50YWdOYW1lID0gdGFnTmFtZTtcbiAgICAgICAgICAgICAgICB0aGlzLnByb3BlcnRpZXMgPSBwcm9wZXJ0aWVzIHx8IG5vUHJvcGVydGllcztcbiAgICAgICAgICAgICAgICB0aGlzLmNoaWxkcmVuID0gY2hpbGRyZW4gfHwgbm9DaGlsZHJlbjtcbiAgICAgICAgICAgICAgICB0aGlzLmtleSA9IGtleSAhPSBudWxsID8gU3RyaW5nKGtleSkgOiB1bmRlZmluZWQ7XG4gICAgICAgICAgICAgICAgdGhpcy5uYW1lc3BhY2UgPSB0eXBlb2YgbmFtZXNwYWNlID09PSBcInN0cmluZ1wiID8gbmFtZXNwYWNlIDogbnVsbDtcblxuICAgICAgICAgICAgICAgIHZhciBjb3VudCA9IGNoaWxkcmVuICYmIGNoaWxkcmVuLmxlbmd0aCB8fCAwO1xuICAgICAgICAgICAgICAgIHZhciBkZXNjZW5kYW50cyA9IDA7XG4gICAgICAgICAgICAgICAgdmFyIGhhc1dpZGdldHMgPSBmYWxzZTtcbiAgICAgICAgICAgICAgICB2YXIgaGFzVGh1bmtzID0gZmFsc2U7XG4gICAgICAgICAgICAgICAgdmFyIGRlc2NlbmRhbnRIb29rcyA9IGZhbHNlO1xuICAgICAgICAgICAgICAgIHZhciBob29rcztcblxuICAgICAgICAgICAgICAgIGZvciAodmFyIHByb3BOYW1lIGluIHByb3BlcnRpZXMpIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKHByb3BlcnRpZXMuaGFzT3duUHJvcGVydHkocHJvcE5hbWUpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICB2YXIgcHJvcGVydHkgPSBwcm9wZXJ0aWVzW3Byb3BOYW1lXTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChpc1ZIb29rKHByb3BlcnR5KSAmJiBwcm9wZXJ0eS51bmhvb2spIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoIWhvb2tzKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGhvb2tzID0ge307XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaG9va3NbcHJvcE5hbWVdID0gcHJvcGVydHk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IGNvdW50OyBpKyspIHtcbiAgICAgICAgICAgICAgICAgICAgdmFyIGNoaWxkID0gY2hpbGRyZW5baV07XG4gICAgICAgICAgICAgICAgICAgIGlmIChpc1ZOb2RlKGNoaWxkKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgZGVzY2VuZGFudHMgKz0gY2hpbGQuY291bnQgfHwgMDtcblxuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKCFoYXNXaWRnZXRzICYmIGNoaWxkLmhhc1dpZGdldHMpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBoYXNXaWRnZXRzID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKCFoYXNUaHVua3MgJiYgY2hpbGQuaGFzVGh1bmtzKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaGFzVGh1bmtzID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKCFkZXNjZW5kYW50SG9va3MgJiYgKGNoaWxkLmhvb2tzIHx8IGNoaWxkLmRlc2NlbmRhbnRIb29rcykpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBkZXNjZW5kYW50SG9va3MgPSB0cnVlO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKCFoYXNXaWRnZXRzICYmIGlzV2lkZ2V0KGNoaWxkKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHR5cGVvZiBjaGlsZC5kZXN0cm95ID09PSBcImZ1bmN0aW9uXCIpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBoYXNXaWRnZXRzID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIGlmICghaGFzVGh1bmtzICYmIGlzVGh1bmsoY2hpbGQpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBoYXNUaHVua3MgPSB0cnVlO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgdGhpcy5jb3VudCA9IGNvdW50ICsgZGVzY2VuZGFudHM7XG4gICAgICAgICAgICAgICAgdGhpcy5oYXNXaWRnZXRzID0gaGFzV2lkZ2V0cztcbiAgICAgICAgICAgICAgICB0aGlzLmhhc1RodW5rcyA9IGhhc1RodW5rcztcbiAgICAgICAgICAgICAgICB0aGlzLmhvb2tzID0gaG9va3M7XG4gICAgICAgICAgICAgICAgdGhpcy5kZXNjZW5kYW50SG9va3MgPSBkZXNjZW5kYW50SG9va3M7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIFZpcnR1YWxOb2RlLnByb3RvdHlwZS52ZXJzaW9uID0gdmVyc2lvbjtcbiAgICAgICAgICAgIFZpcnR1YWxOb2RlLnByb3RvdHlwZS50eXBlID0gXCJWaXJ0dWFsTm9kZVwiO1xuICAgICAgICB9LCB7IFwiLi9pcy10aHVua1wiOiAyNSwgXCIuL2lzLXZob29rXCI6IDI2LCBcIi4vaXMtdm5vZGVcIjogMjcsIFwiLi9pcy13aWRnZXRcIjogMjksIFwiLi92ZXJzaW9uXCI6IDMwIH1dLCAzMjogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHtcbiAgICAgICAgICAgIHZhciB2ZXJzaW9uID0gcmVxdWlyZShcIi4vdmVyc2lvblwiKTtcblxuICAgICAgICAgICAgVmlydHVhbFBhdGNoLk5PTkUgPSAwO1xuICAgICAgICAgICAgVmlydHVhbFBhdGNoLlZURVhUID0gMTtcbiAgICAgICAgICAgIFZpcnR1YWxQYXRjaC5WTk9ERSA9IDI7XG4gICAgICAgICAgICBWaXJ0dWFsUGF0Y2guV0lER0VUID0gMztcbiAgICAgICAgICAgIFZpcnR1YWxQYXRjaC5QUk9QUyA9IDQ7XG4gICAgICAgICAgICBWaXJ0dWFsUGF0Y2guT1JERVIgPSA1O1xuICAgICAgICAgICAgVmlydHVhbFBhdGNoLklOU0VSVCA9IDY7XG4gICAgICAgICAgICBWaXJ0dWFsUGF0Y2guUkVNT1ZFID0gNztcbiAgICAgICAgICAgIFZpcnR1YWxQYXRjaC5USFVOSyA9IDg7XG5cbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gVmlydHVhbFBhdGNoO1xuXG4gICAgICAgICAgICBmdW5jdGlvbiBWaXJ0dWFsUGF0Y2godHlwZSwgdk5vZGUsIHBhdGNoKSB7XG4gICAgICAgICAgICAgICAgdGhpcy50eXBlID0gTnVtYmVyKHR5cGUpO1xuICAgICAgICAgICAgICAgIHRoaXMudk5vZGUgPSB2Tm9kZTtcbiAgICAgICAgICAgICAgICB0aGlzLnBhdGNoID0gcGF0Y2g7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIFZpcnR1YWxQYXRjaC5wcm90b3R5cGUudmVyc2lvbiA9IHZlcnNpb247XG4gICAgICAgICAgICBWaXJ0dWFsUGF0Y2gucHJvdG90eXBlLnR5cGUgPSBcIlZpcnR1YWxQYXRjaFwiO1xuICAgICAgICB9LCB7IFwiLi92ZXJzaW9uXCI6IDMwIH1dLCAzMzogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHtcbiAgICAgICAgICAgIHZhciB2ZXJzaW9uID0gcmVxdWlyZShcIi4vdmVyc2lvblwiKTtcblxuICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBWaXJ0dWFsVGV4dDtcblxuICAgICAgICAgICAgZnVuY3Rpb24gVmlydHVhbFRleHQodGV4dCkge1xuICAgICAgICAgICAgICAgIHRoaXMudGV4dCA9IFN0cmluZyh0ZXh0KTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgVmlydHVhbFRleHQucHJvdG90eXBlLnZlcnNpb24gPSB2ZXJzaW9uO1xuICAgICAgICAgICAgVmlydHVhbFRleHQucHJvdG90eXBlLnR5cGUgPSBcIlZpcnR1YWxUZXh0XCI7XG4gICAgICAgIH0sIHsgXCIuL3ZlcnNpb25cIjogMzAgfV0sIDM0OiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge1xuICAgICAgICAgICAgdmFyIGlzT2JqZWN0ID0gcmVxdWlyZShcImlzLW9iamVjdFwiKTtcbiAgICAgICAgICAgIHZhciBpc0hvb2sgPSByZXF1aXJlKFwiLi4vdm5vZGUvaXMtdmhvb2tcIik7XG5cbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gZGlmZlByb3BzO1xuXG4gICAgICAgICAgICBmdW5jdGlvbiBkaWZmUHJvcHMoYSwgYikge1xuICAgICAgICAgICAgICAgIHZhciBkaWZmO1xuXG4gICAgICAgICAgICAgICAgZm9yICh2YXIgYUtleSBpbiBhKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmICghKGFLZXkgaW4gYikpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGRpZmYgPSBkaWZmIHx8IHt9O1xuICAgICAgICAgICAgICAgICAgICAgICAgZGlmZlthS2V5XSA9IHVuZGVmaW5lZDtcbiAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgIHZhciBhVmFsdWUgPSBhW2FLZXldO1xuICAgICAgICAgICAgICAgICAgICB2YXIgYlZhbHVlID0gYlthS2V5XTtcblxuICAgICAgICAgICAgICAgICAgICBpZiAoYVZhbHVlID09PSBiVmFsdWUpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnRpbnVlO1xuICAgICAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKGlzT2JqZWN0KGFWYWx1ZSkgJiYgaXNPYmplY3QoYlZhbHVlKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGdldFByb3RvdHlwZShiVmFsdWUpICE9PSBnZXRQcm90b3R5cGUoYVZhbHVlKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRpZmYgPSBkaWZmIHx8IHt9O1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRpZmZbYUtleV0gPSBiVmFsdWU7XG4gICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKGlzSG9vayhiVmFsdWUpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgZGlmZiA9IGRpZmYgfHwge307XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgZGlmZlthS2V5XSA9IGJWYWx1ZTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdmFyIG9iamVjdERpZmYgPSBkaWZmUHJvcHMoYVZhbHVlLCBiVmFsdWUpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChvYmplY3REaWZmKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRpZmYgPSBkaWZmIHx8IHt9O1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBkaWZmW2FLZXldID0gb2JqZWN0RGlmZjtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBkaWZmID0gZGlmZiB8fCB7fTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGRpZmZbYUtleV0gPSBiVmFsdWU7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICBmb3IgKHZhciBiS2V5IGluIGIpIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKCEoYktleSBpbiBhKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgZGlmZiA9IGRpZmYgfHwge307XG4gICAgICAgICAgICAgICAgICAgICAgICBkaWZmW2JLZXldID0gYltiS2V5XTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHJldHVybiBkaWZmO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBmdW5jdGlvbiBnZXRQcm90b3R5cGUodmFsdWUpIHtcbiAgICAgICAgICAgICAgICBpZiAoT2JqZWN0LmdldFByb3RvdHlwZU9mKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBPYmplY3QuZ2V0UHJvdG90eXBlT2YodmFsdWUpO1xuICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAodmFsdWUuX19wcm90b19fKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiB2YWx1ZS5fX3Byb3RvX187XG4gICAgICAgICAgICAgICAgfSBlbHNlIGlmICh2YWx1ZS5jb25zdHJ1Y3Rvcikge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gdmFsdWUuY29uc3RydWN0b3IucHJvdG90eXBlO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgfSwgeyBcIi4uL3Zub2RlL2lzLXZob29rXCI6IDI2LCBcImlzLW9iamVjdFwiOiAxMSB9XSwgMzU6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICB2YXIgaXNBcnJheSA9IHJlcXVpcmUoXCJ4LWlzLWFycmF5XCIpO1xuXG4gICAgICAgICAgICB2YXIgVlBhdGNoID0gcmVxdWlyZShcIi4uL3Zub2RlL3ZwYXRjaFwiKTtcbiAgICAgICAgICAgIHZhciBpc1ZOb2RlID0gcmVxdWlyZShcIi4uL3Zub2RlL2lzLXZub2RlXCIpO1xuICAgICAgICAgICAgdmFyIGlzVlRleHQgPSByZXF1aXJlKFwiLi4vdm5vZGUvaXMtdnRleHRcIik7XG4gICAgICAgICAgICB2YXIgaXNXaWRnZXQgPSByZXF1aXJlKFwiLi4vdm5vZGUvaXMtd2lkZ2V0XCIpO1xuICAgICAgICAgICAgdmFyIGlzVGh1bmsgPSByZXF1aXJlKFwiLi4vdm5vZGUvaXMtdGh1bmtcIik7XG4gICAgICAgICAgICB2YXIgaGFuZGxlVGh1bmsgPSByZXF1aXJlKFwiLi4vdm5vZGUvaGFuZGxlLXRodW5rXCIpO1xuXG4gICAgICAgICAgICB2YXIgZGlmZlByb3BzID0gcmVxdWlyZShcIi4vZGlmZi1wcm9wc1wiKTtcblxuICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBkaWZmO1xuXG4gICAgICAgICAgICBmdW5jdGlvbiBkaWZmKGEsIGIpIHtcbiAgICAgICAgICAgICAgICB2YXIgcGF0Y2ggPSB7IGE6IGEgfTtcbiAgICAgICAgICAgICAgICB3YWxrKGEsIGIsIHBhdGNoLCAwKTtcbiAgICAgICAgICAgICAgICByZXR1cm4gcGF0Y2g7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIHdhbGsoYSwgYiwgcGF0Y2gsIGluZGV4KSB7XG4gICAgICAgICAgICAgICAgaWYgKGEgPT09IGIpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHZhciBhcHBseSA9IHBhdGNoW2luZGV4XTtcbiAgICAgICAgICAgICAgICB2YXIgYXBwbHlDbGVhciA9IGZhbHNlO1xuXG4gICAgICAgICAgICAgICAgaWYgKGlzVGh1bmsoYSkgfHwgaXNUaHVuayhiKSkge1xuICAgICAgICAgICAgICAgICAgICB0aHVua3MoYSwgYiwgcGF0Y2gsIGluZGV4KTtcbiAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKGIgPT0gbnVsbCkge1xuXG4gICAgICAgICAgICAgICAgICAgIC8vIElmIGEgaXMgYSB3aWRnZXQgd2Ugd2lsbCBhZGQgYSByZW1vdmUgcGF0Y2ggZm9yIGl0XG4gICAgICAgICAgICAgICAgICAgIC8vIE90aGVyd2lzZSBhbnkgY2hpbGQgd2lkZ2V0cy9ob29rcyBtdXN0IGJlIGRlc3Ryb3llZC5cbiAgICAgICAgICAgICAgICAgICAgLy8gVGhpcyBwcmV2ZW50cyBhZGRpbmcgdHdvIHJlbW92ZSBwYXRjaGVzIGZvciBhIHdpZGdldC5cbiAgICAgICAgICAgICAgICAgICAgaWYgKCFpc1dpZGdldChhKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgY2xlYXJTdGF0ZShhLCBwYXRjaCwgaW5kZXgpO1xuICAgICAgICAgICAgICAgICAgICAgICAgYXBwbHkgPSBwYXRjaFtpbmRleF07XG4gICAgICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgICAgICBhcHBseSA9IGFwcGVuZFBhdGNoKGFwcGx5LCBuZXcgVlBhdGNoKFZQYXRjaC5SRU1PVkUsIGEsIGIpKTtcbiAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKGlzVk5vZGUoYikpIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKGlzVk5vZGUoYSkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChhLnRhZ05hbWUgPT09IGIudGFnTmFtZSAmJiBhLm5hbWVzcGFjZSA9PT0gYi5uYW1lc3BhY2UgJiYgYS5rZXkgPT09IGIua2V5KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdmFyIHByb3BzUGF0Y2ggPSBkaWZmUHJvcHMoYS5wcm9wZXJ0aWVzLCBiLnByb3BlcnRpZXMpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChwcm9wc1BhdGNoKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGFwcGx5ID0gYXBwZW5kUGF0Y2goYXBwbHksIG5ldyBWUGF0Y2goVlBhdGNoLlBST1BTLCBhLCBwcm9wc1BhdGNoKSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGFwcGx5ID0gZGlmZkNoaWxkcmVuKGEsIGIsIHBhdGNoLCBhcHBseSwgaW5kZXgpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBhcHBseSA9IGFwcGVuZFBhdGNoKGFwcGx5LCBuZXcgVlBhdGNoKFZQYXRjaC5WTk9ERSwgYSwgYikpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGFwcGx5Q2xlYXIgPSB0cnVlO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgYXBwbHkgPSBhcHBlbmRQYXRjaChhcHBseSwgbmV3IFZQYXRjaChWUGF0Y2guVk5PREUsIGEsIGIpKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGFwcGx5Q2xlYXIgPSB0cnVlO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfSBlbHNlIGlmIChpc1ZUZXh0KGIpKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmICghaXNWVGV4dChhKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgYXBwbHkgPSBhcHBlbmRQYXRjaChhcHBseSwgbmV3IFZQYXRjaChWUGF0Y2guVlRFWFQsIGEsIGIpKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGFwcGx5Q2xlYXIgPSB0cnVlO1xuICAgICAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKGEudGV4dCAhPT0gYi50ZXh0KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBhcHBseSA9IGFwcGVuZFBhdGNoKGFwcGx5LCBuZXcgVlBhdGNoKFZQYXRjaC5WVEVYVCwgYSwgYikpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfSBlbHNlIGlmIChpc1dpZGdldChiKSkge1xuICAgICAgICAgICAgICAgICAgICBpZiAoIWlzV2lkZ2V0KGEpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBhcHBseUNsZWFyID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgIGFwcGx5ID0gYXBwZW5kUGF0Y2goYXBwbHksIG5ldyBWUGF0Y2goVlBhdGNoLldJREdFVCwgYSwgYikpO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIGlmIChhcHBseSkge1xuICAgICAgICAgICAgICAgICAgICBwYXRjaFtpbmRleF0gPSBhcHBseTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICBpZiAoYXBwbHlDbGVhcikge1xuICAgICAgICAgICAgICAgICAgICBjbGVhclN0YXRlKGEsIHBhdGNoLCBpbmRleCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBmdW5jdGlvbiBkaWZmQ2hpbGRyZW4oYSwgYiwgcGF0Y2gsIGFwcGx5LCBpbmRleCkge1xuICAgICAgICAgICAgICAgIHZhciBhQ2hpbGRyZW4gPSBhLmNoaWxkcmVuO1xuICAgICAgICAgICAgICAgIHZhciBvcmRlcmVkU2V0ID0gcmVvcmRlcihhQ2hpbGRyZW4sIGIuY2hpbGRyZW4pO1xuICAgICAgICAgICAgICAgIHZhciBiQ2hpbGRyZW4gPSBvcmRlcmVkU2V0LmNoaWxkcmVuO1xuXG4gICAgICAgICAgICAgICAgdmFyIGFMZW4gPSBhQ2hpbGRyZW4ubGVuZ3RoO1xuICAgICAgICAgICAgICAgIHZhciBiTGVuID0gYkNoaWxkcmVuLmxlbmd0aDtcbiAgICAgICAgICAgICAgICB2YXIgbGVuID0gYUxlbiA+IGJMZW4gPyBhTGVuIDogYkxlbjtcblxuICAgICAgICAgICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgbGVuOyBpKyspIHtcbiAgICAgICAgICAgICAgICAgICAgdmFyIGxlZnROb2RlID0gYUNoaWxkcmVuW2ldO1xuICAgICAgICAgICAgICAgICAgICB2YXIgcmlnaHROb2RlID0gYkNoaWxkcmVuW2ldO1xuICAgICAgICAgICAgICAgICAgICBpbmRleCArPSAxO1xuXG4gICAgICAgICAgICAgICAgICAgIGlmICghbGVmdE5vZGUpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChyaWdodE5vZGUpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBFeGNlc3Mgbm9kZXMgaW4gYiBuZWVkIHRvIGJlIGFkZGVkXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgYXBwbHkgPSBhcHBlbmRQYXRjaChhcHBseSwgbmV3IFZQYXRjaChWUGF0Y2guSU5TRVJULCBudWxsLCByaWdodE5vZGUpKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHdhbGsobGVmdE5vZGUsIHJpZ2h0Tm9kZSwgcGF0Y2gsIGluZGV4KTtcbiAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgIGlmIChpc1ZOb2RlKGxlZnROb2RlKSAmJiBsZWZ0Tm9kZS5jb3VudCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgaW5kZXggKz0gbGVmdE5vZGUuY291bnQ7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICBpZiAob3JkZXJlZFNldC5tb3Zlcykge1xuICAgICAgICAgICAgICAgICAgICAvLyBSZW9yZGVyIG5vZGVzIGxhc3RcbiAgICAgICAgICAgICAgICAgICAgYXBwbHkgPSBhcHBlbmRQYXRjaChhcHBseSwgbmV3IFZQYXRjaChWUGF0Y2guT1JERVIsIGEsIG9yZGVyZWRTZXQubW92ZXMpKTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICByZXR1cm4gYXBwbHk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIGNsZWFyU3RhdGUodk5vZGUsIHBhdGNoLCBpbmRleCkge1xuICAgICAgICAgICAgICAgIC8vIFRPRE86IE1ha2UgdGhpcyBhIHNpbmdsZSB3YWxrLCBub3QgdHdvXG4gICAgICAgICAgICAgICAgdW5ob29rKHZOb2RlLCBwYXRjaCwgaW5kZXgpO1xuICAgICAgICAgICAgICAgIGRlc3Ryb3lXaWRnZXRzKHZOb2RlLCBwYXRjaCwgaW5kZXgpO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAvLyBQYXRjaCByZWNvcmRzIGZvciBhbGwgZGVzdHJveWVkIHdpZGdldHMgbXVzdCBiZSBhZGRlZCBiZWNhdXNlIHdlIG5lZWRcbiAgICAgICAgICAgIC8vIGEgRE9NIG5vZGUgcmVmZXJlbmNlIGZvciB0aGUgZGVzdHJveSBmdW5jdGlvblxuICAgICAgICAgICAgZnVuY3Rpb24gZGVzdHJveVdpZGdldHModk5vZGUsIHBhdGNoLCBpbmRleCkge1xuICAgICAgICAgICAgICAgIGlmIChpc1dpZGdldCh2Tm9kZSkpIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKHR5cGVvZiB2Tm9kZS5kZXN0cm95ID09PSBcImZ1bmN0aW9uXCIpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHBhdGNoW2luZGV4XSA9IGFwcGVuZFBhdGNoKHBhdGNoW2luZGV4XSwgbmV3IFZQYXRjaChWUGF0Y2guUkVNT1ZFLCB2Tm9kZSwgbnVsbCkpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfSBlbHNlIGlmIChpc1ZOb2RlKHZOb2RlKSAmJiAodk5vZGUuaGFzV2lkZ2V0cyB8fCB2Tm9kZS5oYXNUaHVua3MpKSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciBjaGlsZHJlbiA9IHZOb2RlLmNoaWxkcmVuO1xuICAgICAgICAgICAgICAgICAgICB2YXIgbGVuID0gY2hpbGRyZW4ubGVuZ3RoO1xuICAgICAgICAgICAgICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IGxlbjsgaSsrKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICB2YXIgY2hpbGQgPSBjaGlsZHJlbltpXTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGluZGV4ICs9IDE7XG5cbiAgICAgICAgICAgICAgICAgICAgICAgIGRlc3Ryb3lXaWRnZXRzKGNoaWxkLCBwYXRjaCwgaW5kZXgpO1xuXG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoaXNWTm9kZShjaGlsZCkgJiYgY2hpbGQuY291bnQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpbmRleCArPSBjaGlsZC5jb3VudDtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoaXNUaHVuayh2Tm9kZSkpIHtcbiAgICAgICAgICAgICAgICAgICAgdGh1bmtzKHZOb2RlLCBudWxsLCBwYXRjaCwgaW5kZXgpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgLy8gQ3JlYXRlIGEgc3ViLXBhdGNoIGZvciB0aHVua3NcbiAgICAgICAgICAgIGZ1bmN0aW9uIHRodW5rcyhhLCBiLCBwYXRjaCwgaW5kZXgpIHtcbiAgICAgICAgICAgICAgICB2YXIgbm9kZXMgPSBoYW5kbGVUaHVuayhhLCBiKTtcbiAgICAgICAgICAgICAgICB2YXIgdGh1bmtQYXRjaCA9IGRpZmYobm9kZXMuYSwgbm9kZXMuYik7XG4gICAgICAgICAgICAgICAgaWYgKGhhc1BhdGNoZXModGh1bmtQYXRjaCkpIHtcbiAgICAgICAgICAgICAgICAgICAgcGF0Y2hbaW5kZXhdID0gbmV3IFZQYXRjaChWUGF0Y2guVEhVTkssIG51bGwsIHRodW5rUGF0Y2gpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZnVuY3Rpb24gaGFzUGF0Y2hlcyhwYXRjaCkge1xuICAgICAgICAgICAgICAgIGZvciAodmFyIGluZGV4IGluIHBhdGNoKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmIChpbmRleCAhPT0gXCJhXCIpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAvLyBFeGVjdXRlIGhvb2tzIHdoZW4gdHdvIG5vZGVzIGFyZSBpZGVudGljYWxcbiAgICAgICAgICAgIGZ1bmN0aW9uIHVuaG9vayh2Tm9kZSwgcGF0Y2gsIGluZGV4KSB7XG4gICAgICAgICAgICAgICAgaWYgKGlzVk5vZGUodk5vZGUpKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmICh2Tm9kZS5ob29rcykge1xuICAgICAgICAgICAgICAgICAgICAgICAgcGF0Y2hbaW5kZXhdID0gYXBwZW5kUGF0Y2gocGF0Y2hbaW5kZXhdLCBuZXcgVlBhdGNoKFZQYXRjaC5QUk9QUywgdk5vZGUsIHVuZGVmaW5lZEtleXModk5vZGUuaG9va3MpKSk7XG4gICAgICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgICAgICBpZiAodk5vZGUuZGVzY2VuZGFudEhvb2tzIHx8IHZOb2RlLmhhc1RodW5rcykge1xuICAgICAgICAgICAgICAgICAgICAgICAgdmFyIGNoaWxkcmVuID0gdk5vZGUuY2hpbGRyZW47XG4gICAgICAgICAgICAgICAgICAgICAgICB2YXIgbGVuID0gY2hpbGRyZW4ubGVuZ3RoO1xuICAgICAgICAgICAgICAgICAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCBsZW47IGkrKykge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZhciBjaGlsZCA9IGNoaWxkcmVuW2ldO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGluZGV4ICs9IDE7XG5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB1bmhvb2soY2hpbGQsIHBhdGNoLCBpbmRleCk7XG5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoaXNWTm9kZShjaGlsZCkgJiYgY2hpbGQuY291bnQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaW5kZXggKz0gY2hpbGQuY291bnQ7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfSBlbHNlIGlmIChpc1RodW5rKHZOb2RlKSkge1xuICAgICAgICAgICAgICAgICAgICB0aHVua3Modk5vZGUsIG51bGwsIHBhdGNoLCBpbmRleCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBmdW5jdGlvbiB1bmRlZmluZWRLZXlzKG9iaikge1xuICAgICAgICAgICAgICAgIHZhciByZXN1bHQgPSB7fTtcblxuICAgICAgICAgICAgICAgIGZvciAodmFyIGtleSBpbiBvYmopIHtcbiAgICAgICAgICAgICAgICAgICAgcmVzdWx0W2tleV0gPSB1bmRlZmluZWQ7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgcmV0dXJuIHJlc3VsdDtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgLy8gTGlzdCBkaWZmLCBuYWl2ZSBsZWZ0IHRvIHJpZ2h0IHJlb3JkZXJpbmdcbiAgICAgICAgICAgIGZ1bmN0aW9uIHJlb3JkZXIoYUNoaWxkcmVuLCBiQ2hpbGRyZW4pIHtcbiAgICAgICAgICAgICAgICAvLyBPKE0pIHRpbWUsIE8oTSkgbWVtb3J5XG4gICAgICAgICAgICAgICAgdmFyIGJDaGlsZEluZGV4ID0ga2V5SW5kZXgoYkNoaWxkcmVuKTtcbiAgICAgICAgICAgICAgICB2YXIgYktleXMgPSBiQ2hpbGRJbmRleC5rZXlzO1xuICAgICAgICAgICAgICAgIHZhciBiRnJlZSA9IGJDaGlsZEluZGV4LmZyZWU7XG5cbiAgICAgICAgICAgICAgICBpZiAoYkZyZWUubGVuZ3RoID09PSBiQ2hpbGRyZW4ubGVuZ3RoKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiB7XG4gICAgICAgICAgICAgICAgICAgICAgICBjaGlsZHJlbjogYkNoaWxkcmVuLFxuICAgICAgICAgICAgICAgICAgICAgICAgbW92ZXM6IG51bGxcbiAgICAgICAgICAgICAgICAgICAgfTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAvLyBPKE4pIHRpbWUsIE8oTikgbWVtb3J5XG4gICAgICAgICAgICAgICAgdmFyIGFDaGlsZEluZGV4ID0ga2V5SW5kZXgoYUNoaWxkcmVuKTtcbiAgICAgICAgICAgICAgICB2YXIgYUtleXMgPSBhQ2hpbGRJbmRleC5rZXlzO1xuICAgICAgICAgICAgICAgIHZhciBhRnJlZSA9IGFDaGlsZEluZGV4LmZyZWU7XG5cbiAgICAgICAgICAgICAgICBpZiAoYUZyZWUubGVuZ3RoID09PSBhQ2hpbGRyZW4ubGVuZ3RoKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiB7XG4gICAgICAgICAgICAgICAgICAgICAgICBjaGlsZHJlbjogYkNoaWxkcmVuLFxuICAgICAgICAgICAgICAgICAgICAgICAgbW92ZXM6IG51bGxcbiAgICAgICAgICAgICAgICAgICAgfTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAvLyBPKE1BWChOLCBNKSkgbWVtb3J5XG4gICAgICAgICAgICAgICAgdmFyIG5ld0NoaWxkcmVuID0gW107XG5cbiAgICAgICAgICAgICAgICB2YXIgZnJlZUluZGV4ID0gMDtcbiAgICAgICAgICAgICAgICB2YXIgZnJlZUNvdW50ID0gYkZyZWUubGVuZ3RoO1xuICAgICAgICAgICAgICAgIHZhciBkZWxldGVkSXRlbXMgPSAwO1xuXG4gICAgICAgICAgICAgICAgLy8gSXRlcmF0ZSB0aHJvdWdoIGEgYW5kIG1hdGNoIGEgbm9kZSBpbiBiXG4gICAgICAgICAgICAgICAgLy8gTyhOKSB0aW1lLFxuICAgICAgICAgICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgYUNoaWxkcmVuLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciBhSXRlbSA9IGFDaGlsZHJlbltpXTtcbiAgICAgICAgICAgICAgICAgICAgdmFyIGl0ZW1JbmRleDtcblxuICAgICAgICAgICAgICAgICAgICBpZiAoYUl0ZW0ua2V5KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoYktleXMuaGFzT3duUHJvcGVydHkoYUl0ZW0ua2V5KSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIE1hdGNoIHVwIHRoZSBvbGQga2V5c1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGl0ZW1JbmRleCA9IGJLZXlzW2FJdGVtLmtleV07XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgbmV3Q2hpbGRyZW4ucHVzaChiQ2hpbGRyZW5baXRlbUluZGV4XSk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIFJlbW92ZSBvbGQga2V5ZWQgaXRlbXNcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpdGVtSW5kZXggPSBpIC0gZGVsZXRlZEl0ZW1zKys7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgbmV3Q2hpbGRyZW4ucHVzaChudWxsKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIE1hdGNoIHRoZSBpdGVtIGluIGEgd2l0aCB0aGUgbmV4dCBmcmVlIGl0ZW0gaW4gYlxuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGZyZWVJbmRleCA8IGZyZWVDb3VudCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGl0ZW1JbmRleCA9IGJGcmVlW2ZyZWVJbmRleCsrXTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBuZXdDaGlsZHJlbi5wdXNoKGJDaGlsZHJlbltpdGVtSW5kZXhdKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gVGhlcmUgYXJlIG5vIGZyZWUgaXRlbXMgaW4gYiB0byBtYXRjaCB3aXRoXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gdGhlIGZyZWUgaXRlbXMgaW4gYSwgc28gdGhlIGV4dHJhIGZyZWUgbm9kZXNcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBhcmUgZGVsZXRlZC5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpdGVtSW5kZXggPSBpIC0gZGVsZXRlZEl0ZW1zKys7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgbmV3Q2hpbGRyZW4ucHVzaChudWxsKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHZhciBsYXN0RnJlZUluZGV4ID0gZnJlZUluZGV4ID49IGJGcmVlLmxlbmd0aCA/IGJDaGlsZHJlbi5sZW5ndGggOiBiRnJlZVtmcmVlSW5kZXhdO1xuXG4gICAgICAgICAgICAgICAgLy8gSXRlcmF0ZSB0aHJvdWdoIGIgYW5kIGFwcGVuZCBhbnkgbmV3IGtleXNcbiAgICAgICAgICAgICAgICAvLyBPKE0pIHRpbWVcbiAgICAgICAgICAgICAgICBmb3IgKHZhciBqID0gMDsgaiA8IGJDaGlsZHJlbi5sZW5ndGg7IGorKykge1xuICAgICAgICAgICAgICAgICAgICB2YXIgbmV3SXRlbSA9IGJDaGlsZHJlbltqXTtcblxuICAgICAgICAgICAgICAgICAgICBpZiAobmV3SXRlbS5rZXkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmICghYUtleXMuaGFzT3duUHJvcGVydHkobmV3SXRlbS5rZXkpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gQWRkIGFueSBuZXcga2V5ZWQgaXRlbXNcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBXZSBhcmUgYWRkaW5nIG5ldyBpdGVtcyB0byB0aGUgZW5kIGFuZCB0aGVuIHNvcnRpbmcgdGhlbVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIGluIHBsYWNlLiBJbiBmdXR1cmUgd2Ugc2hvdWxkIGluc2VydCBuZXcgaXRlbXMgaW4gcGxhY2UuXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgbmV3Q2hpbGRyZW4ucHVzaChuZXdJdGVtKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIGlmIChqID49IGxhc3RGcmVlSW5kZXgpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIEFkZCBhbnkgbGVmdG92ZXIgbm9uLWtleWVkIGl0ZW1zXG4gICAgICAgICAgICAgICAgICAgICAgICBuZXdDaGlsZHJlbi5wdXNoKG5ld0l0ZW0pO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgdmFyIHNpbXVsYXRlID0gbmV3Q2hpbGRyZW4uc2xpY2UoKTtcbiAgICAgICAgICAgICAgICB2YXIgc2ltdWxhdGVJbmRleCA9IDA7XG4gICAgICAgICAgICAgICAgdmFyIHJlbW92ZXMgPSBbXTtcbiAgICAgICAgICAgICAgICB2YXIgaW5zZXJ0cyA9IFtdO1xuICAgICAgICAgICAgICAgIHZhciBzaW11bGF0ZUl0ZW07XG5cbiAgICAgICAgICAgICAgICBmb3IgKHZhciBrID0gMDsgayA8IGJDaGlsZHJlbi5sZW5ndGg7KSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciB3YW50ZWRJdGVtID0gYkNoaWxkcmVuW2tdO1xuICAgICAgICAgICAgICAgICAgICBzaW11bGF0ZUl0ZW0gPSBzaW11bGF0ZVtzaW11bGF0ZUluZGV4XTtcblxuICAgICAgICAgICAgICAgICAgICAvLyByZW1vdmUgaXRlbXNcbiAgICAgICAgICAgICAgICAgICAgd2hpbGUgKHNpbXVsYXRlSXRlbSA9PT0gbnVsbCAmJiBzaW11bGF0ZS5sZW5ndGgpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJlbW92ZXMucHVzaChyZW1vdmUoc2ltdWxhdGUsIHNpbXVsYXRlSW5kZXgsIG51bGwpKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIHNpbXVsYXRlSXRlbSA9IHNpbXVsYXRlW3NpbXVsYXRlSW5kZXhdO1xuICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgaWYgKCFzaW11bGF0ZUl0ZW0gfHwgc2ltdWxhdGVJdGVtLmtleSAhPT0gd2FudGVkSXRlbS5rZXkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIGlmIHdlIG5lZWQgYSBrZXkgaW4gdGhpcyBwb3NpdGlvbi4uLlxuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHdhbnRlZEl0ZW0ua2V5KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHNpbXVsYXRlSXRlbSAmJiBzaW11bGF0ZUl0ZW0ua2V5KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIGlmIGFuIGluc2VydCBkb2Vzbid0IHB1dCB0aGlzIGtleSBpbiBwbGFjZSwgaXQgbmVlZHMgdG8gbW92ZVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoYktleXNbc2ltdWxhdGVJdGVtLmtleV0gIT09IGsgKyAxKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICByZW1vdmVzLnB1c2gocmVtb3ZlKHNpbXVsYXRlLCBzaW11bGF0ZUluZGV4LCBzaW11bGF0ZUl0ZW0ua2V5KSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzaW11bGF0ZUl0ZW0gPSBzaW11bGF0ZVtzaW11bGF0ZUluZGV4XTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIGlmIHRoZSByZW1vdmUgZGlkbid0IHB1dCB0aGUgd2FudGVkIGl0ZW0gaW4gcGxhY2UsIHdlIG5lZWQgdG8gaW5zZXJ0IGl0XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoIXNpbXVsYXRlSXRlbSB8fCBzaW11bGF0ZUl0ZW0ua2V5ICE9PSB3YW50ZWRJdGVtLmtleSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGluc2VydHMucHVzaCh7IGtleTogd2FudGVkSXRlbS5rZXksIHRvOiBrIH0pO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gaXRlbXMgYXJlIG1hdGNoaW5nLCBzbyBza2lwIGFoZWFkXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzaW11bGF0ZUluZGV4Kys7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpbnNlcnRzLnB1c2goeyBrZXk6IHdhbnRlZEl0ZW0ua2V5LCB0bzogayB9KTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGluc2VydHMucHVzaCh7IGtleTogd2FudGVkSXRlbS5rZXksIHRvOiBrIH0pO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBrKys7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAvLyBhIGtleSBpbiBzaW11bGF0ZSBoYXMgbm8gbWF0Y2hpbmcgd2FudGVkIGtleSwgcmVtb3ZlIGl0XG4gICAgICAgICAgICAgICAgICAgICAgICBlbHNlIGlmIChzaW11bGF0ZUl0ZW0gJiYgc2ltdWxhdGVJdGVtLmtleSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlbW92ZXMucHVzaChyZW1vdmUoc2ltdWxhdGUsIHNpbXVsYXRlSW5kZXgsIHNpbXVsYXRlSXRlbS5rZXkpKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHNpbXVsYXRlSW5kZXgrKztcbiAgICAgICAgICAgICAgICAgICAgICAgIGsrKztcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIC8vIHJlbW92ZSBhbGwgdGhlIHJlbWFpbmluZyBub2RlcyBmcm9tIHNpbXVsYXRlXG4gICAgICAgICAgICAgICAgd2hpbGUgKHNpbXVsYXRlSW5kZXggPCBzaW11bGF0ZS5sZW5ndGgpIHtcbiAgICAgICAgICAgICAgICAgICAgc2ltdWxhdGVJdGVtID0gc2ltdWxhdGVbc2ltdWxhdGVJbmRleF07XG4gICAgICAgICAgICAgICAgICAgIHJlbW92ZXMucHVzaChyZW1vdmUoc2ltdWxhdGUsIHNpbXVsYXRlSW5kZXgsIHNpbXVsYXRlSXRlbSAmJiBzaW11bGF0ZUl0ZW0ua2V5KSk7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgLy8gSWYgdGhlIG9ubHkgbW92ZXMgd2UgaGF2ZSBhcmUgZGVsZXRlcyB0aGVuIHdlIGNhbiBqdXN0XG4gICAgICAgICAgICAgICAgLy8gbGV0IHRoZSBkZWxldGUgcGF0Y2ggcmVtb3ZlIHRoZXNlIGl0ZW1zLlxuICAgICAgICAgICAgICAgIGlmIChyZW1vdmVzLmxlbmd0aCA9PT0gZGVsZXRlZEl0ZW1zICYmICFpbnNlcnRzLmxlbmd0aCkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgICAgICAgICAgICAgY2hpbGRyZW46IG5ld0NoaWxkcmVuLFxuICAgICAgICAgICAgICAgICAgICAgICAgbW92ZXM6IG51bGxcbiAgICAgICAgICAgICAgICAgICAgfTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgICAgICAgICBjaGlsZHJlbjogbmV3Q2hpbGRyZW4sXG4gICAgICAgICAgICAgICAgICAgIG1vdmVzOiB7XG4gICAgICAgICAgICAgICAgICAgICAgICByZW1vdmVzOiByZW1vdmVzLFxuICAgICAgICAgICAgICAgICAgICAgICAgaW5zZXJ0czogaW5zZXJ0c1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZnVuY3Rpb24gcmVtb3ZlKGFyciwgaW5kZXgsIGtleSkge1xuICAgICAgICAgICAgICAgIGFyci5zcGxpY2UoaW5kZXgsIDEpO1xuXG4gICAgICAgICAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgICAgICAgICAgZnJvbTogaW5kZXgsXG4gICAgICAgICAgICAgICAgICAgIGtleToga2V5XG4gICAgICAgICAgICAgICAgfTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZnVuY3Rpb24ga2V5SW5kZXgoY2hpbGRyZW4pIHtcbiAgICAgICAgICAgICAgICB2YXIga2V5cyA9IHt9O1xuICAgICAgICAgICAgICAgIHZhciBmcmVlID0gW107XG4gICAgICAgICAgICAgICAgdmFyIGxlbmd0aCA9IGNoaWxkcmVuLmxlbmd0aDtcblxuICAgICAgICAgICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgbGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgICAgICAgICAgdmFyIGNoaWxkID0gY2hpbGRyZW5baV07XG5cbiAgICAgICAgICAgICAgICAgICAgaWYgKGNoaWxkLmtleSkge1xuICAgICAgICAgICAgICAgICAgICAgICAga2V5c1tjaGlsZC5rZXldID0gaTtcbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGZyZWUucHVzaChpKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHJldHVybiB7XG4gICAgICAgICAgICAgICAgICAgIGtleXM6IGtleXMsIC8vIEEgaGFzaCBvZiBrZXkgbmFtZSB0byBpbmRleFxuICAgICAgICAgICAgICAgICAgICBmcmVlOiBmcmVlIC8vIEFuIGFycmF5IG9mIHVua2V5ZWQgaXRlbSBpbmRpY2VzXG4gICAgICAgICAgICAgICAgfTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZnVuY3Rpb24gYXBwZW5kUGF0Y2goYXBwbHksIHBhdGNoKSB7XG4gICAgICAgICAgICAgICAgaWYgKGFwcGx5KSB7XG4gICAgICAgICAgICAgICAgICAgIGlmIChpc0FycmF5KGFwcGx5KSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgYXBwbHkucHVzaChwYXRjaCk7XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBhcHBseSA9IFthcHBseSwgcGF0Y2hdO1xuICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGFwcGx5O1xuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBwYXRjaDtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH0sIHsgXCIuLi92bm9kZS9oYW5kbGUtdGh1bmtcIjogMjQsIFwiLi4vdm5vZGUvaXMtdGh1bmtcIjogMjUsIFwiLi4vdm5vZGUvaXMtdm5vZGVcIjogMjcsIFwiLi4vdm5vZGUvaXMtdnRleHRcIjogMjgsIFwiLi4vdm5vZGUvaXMtd2lkZ2V0XCI6IDI5LCBcIi4uL3Zub2RlL3ZwYXRjaFwiOiAzMiwgXCIuL2RpZmYtcHJvcHNcIjogMzQsIFwieC1pcy1hcnJheVwiOiAxMiB9XSB9LCB7fSwgWzRdKSg0KTtcbn0pO1xuXG5cbi8vIFByb3Bvc2VkIGZvciBFUzZcblxuc2VsZi5wb3N0X29mZmljZSA9IHNlbGYucG9zdF9vZmZpY2UgfHwgbmV3IFBvc3RPZmZpY2UoKTtcblxuZXhwb3J0IHsgX1BhdHRlcm5zIGFzIFBhdHRlcm5zLCBCaXRTdHJpbmcsIEtlcm5lbCwgQXRvbSwgRW51bSwgSW50ZWdlciwgSlMsIExpc3QsIFJhbmdlLCBUdXBsZSwgQWdlbnQsIEtleXdvcmQsIEJhc2UsIF9TdHJpbmcgYXMgU3RyaW5nLCBCaXR3aXNlLCBFbnVtZXJhYmxlLCBDb2xsZWN0YWJsZSwgSW5zcGVjdCwgX01hcCBhcyBNYXAsIF9TZXQgYXMgU2V0LCBNYXBTZXQsIEludGVnZXJUeXBlLCBGbG9hdFR5cGUsIHZpcnR1YWxEb20gYXMgVmlydHVhbERPTSB9OyJdLCJmaWxlIjoiZWxpeGlyLmpzIiwic291cmNlUm9vdCI6Ii9zb3VyY2UvIn0= \ No newline at end of file diff --git a/src/javascript/elixir.js b/src/javascript/elixir.js index f5bc3445..dc3f70ed 100644 --- a/src/javascript/elixir.js +++ b/src/javascript/elixir.js @@ -24,3 +24,4 @@ export { default as Map } from './lib/map'; export { default as Set } from './lib/set'; export { default as MapSet } from './lib/map_set'; export { IntegerType, FloatType } from './lib/protocol'; +export { default as VirtualDOM } from './lib/virtual-dom'; diff --git a/src/javascript/lib/virtual-dom.js b/src/javascript/lib/virtual-dom.js new file mode 100644 index 00000000..af4bd974 --- /dev/null +++ b/src/javascript/lib/virtual-dom.js @@ -0,0 +1,1699 @@ +let virtualDom = function(e) { + return e(); +}(function() { + var define, module, exports; + return (function e(t, n, r) { + function s(o, u) { + if (!n[o]) { + if (!t[o]) { + var a = typeof require == "function" && require; + if (!u && a) return a(o, !0); + if (i) return i(o, !0); + var f = new Error("Cannot find module '" + o + "'"); + throw f.code = "MODULE_NOT_FOUND", f + } + var l = n[o] = { + exports: {} + }; + t[o][0].call(l.exports, function(e) { + var n = t[o][1][e]; + return s(n ? n : e) + }, l, l.exports, e, t, n, r) + } + return n[o].exports + } + var i = typeof require == "function" && require; + for (var o = 0; o < r.length; o++) s(r[o]); + return s + })({ + 1: [function(require, module, exports) { + +var createElement = require("./vdom/create-element.js") + +module.exports = createElement + +},{"./vdom/create-element.js":15}],2:[function(require,module,exports){ +var diff = require("./vtree/diff.js") + +module.exports = diff + +},{"./vtree/diff.js":35}],3:[function(require,module,exports){ +var h = require("./virtual-hyperscript/index.js") + +module.exports = h + +},{"./virtual-hyperscript/index.js":22}],4:[function(require,module,exports){ +var diff = require("./diff.js") +var patch = require("./patch.js") +var h = require("./h.js") +var create = require("./create-element.js") +var VNode = require('./vnode/vnode.js') +var VText = require('./vnode/vtext.js') + +module.exports = { + diff: diff, + patch: patch, + h: h, + create: create, + VNode: VNode, + VText: VText +} + +},{"./create-element.js":1,"./diff.js":2,"./h.js":3,"./patch.js":13,"./vnode/vnode.js":31,"./vnode/vtext.js":33}],5:[function(require,module,exports){ +/*! + * Cross-Browser Split 1.1.1 + * Copyright 2007-2012 Steven Levithan + * Available under the MIT License + * ECMAScript compliant, uniform cross-browser split method + */ + +/** + * Splits a string into an array of strings using a regex or string separator. Matches of the + * separator are not included in the result array. However, if `separator` is a regex that contains + * capturing groups, backreferences are spliced into the result each time `separator` is matched. + * Fixes browser bugs compared to the native `String.prototype.split` and can be used reliably + * cross-browser. + * @param {String} str String to split. + * @param {RegExp|String} separator Regex or string to use for separating the string. + * @param {Number} [limit] Maximum number of items to include in the result array. + * @returns {Array} Array of substrings. + * @example + * + * // Basic use + * split('a b c d', ' '); + * // -> ['a', 'b', 'c', 'd'] + * + * // With limit + * split('a b c d', ' ', 2); + * // -> ['a', 'b'] + * + * // Backreferences in result array + * split('..word1 word2..', /([a-z]+)(\d+)/i); + * // -> ['..', 'word', '1', ' ', 'word', '2', '..'] + */ +module.exports = (function split(undef) { + + var nativeSplit = String.prototype.split, + compliantExecNpcg = /()??/.exec("")[1] === undef, + // NPCG: nonparticipating capturing group + self; + + self = function(str, separator, limit) { + // If `separator` is not a regex, use `nativeSplit` + if (Object.prototype.toString.call(separator) !== "[object RegExp]") { + return nativeSplit.call(str, separator, limit); + } + var output = [], + flags = (separator.ignoreCase ? "i" : "") + (separator.multiline ? "m" : "") + (separator.extended ? "x" : "") + // Proposed for ES6 + (separator.sticky ? "y" : ""), + // Firefox 3+ + lastLastIndex = 0, + // Make `global` and avoid `lastIndex` issues by working with a copy + separator = new RegExp(separator.source, flags + "g"), + separator2, match, lastIndex, lastLength; + str += ""; // Type-convert + if (!compliantExecNpcg) { + // Doesn't need flags gy, but they don't hurt + separator2 = new RegExp("^" + separator.source + "$(?!\\s)", flags); + } + /* Values for `limit`, per the spec: + * If undefined: 4294967295 // Math.pow(2, 32) - 1 + * If 0, Infinity, or NaN: 0 + * If positive number: limit = Math.floor(limit); if (limit > 4294967295) limit -= 4294967296; + * If negative number: 4294967296 - Math.floor(Math.abs(limit)) + * If other: Type-convert, then use the above rules + */ + limit = limit === undef ? -1 >>> 0 : // Math.pow(2, 32) - 1 + limit >>> 0; // ToUint32(limit) + while (match = separator.exec(str)) { + // `separator.lastIndex` is not reliable cross-browser + lastIndex = match.index + match[0].length; + if (lastIndex > lastLastIndex) { + output.push(str.slice(lastLastIndex, match.index)); + // Fix browsers whose `exec` methods don't consistently return `undefined` for + // nonparticipating capturing groups + if (!compliantExecNpcg && match.length > 1) { + match[0].replace(separator2, function() { + for (var i = 1; i < arguments.length - 2; i++) { + if (arguments[i] === undef) { + match[i] = undef; + } + } + }); + } + if (match.length > 1 && match.index < str.length) { + Array.prototype.push.apply(output, match.slice(1)); + } + lastLength = match[0].length; + lastLastIndex = lastIndex; + if (output.length >= limit) { + break; + } + } + if (separator.lastIndex === match.index) { + separator.lastIndex++; // Avoid an infinite loop + } + } + if (lastLastIndex === str.length) { + if (lastLength || !separator.test("")) { + output.push(""); + } + } else { + output.push(str.slice(lastLastIndex)); + } + return output.length > limit ? output.slice(0, limit) : output; + }; + + return self; +})(); + +},{}],6:[function(require,module,exports){ + +},{}],7:[function(require,module,exports){ +'use strict'; + +var OneVersionConstraint = require('individual/one-version'); + +var MY_VERSION = '7'; +OneVersionConstraint('ev-store', MY_VERSION); + +var hashKey = '__EV_STORE_KEY@' + MY_VERSION; + +module.exports = EvStore; + +function EvStore(elem) { + var hash = elem[hashKey]; + + if (!hash) { + hash = elem[hashKey] = {}; + } + + return hash; +} + +},{"individual/one-version":9}],8:[function(require,module,exports){ +(function (global){ +'use strict'; + +/*global window, global*/ + +var root = typeof window !== 'undefined' ? + window : typeof global !== 'undefined' ? + global : {}; + +module.exports = Individual; + +function Individual(key, value) { + if (key in root) { + return root[key]; + } + + root[key] = value; + + return value; +} + +}).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}) +},{}],9:[function(require,module,exports){ +'use strict'; + +var Individual = require('./index.js'); + +module.exports = OneVersion; + +function OneVersion(moduleName, version, defaultValue) { + var key = '__INDIVIDUAL_ONE_VERSION_' + moduleName; + var enforceKey = key + '_ENFORCE_SINGLETON'; + + var versionValue = Individual(enforceKey, version); + + if (versionValue !== version) { + throw new Error('Can only have one copy of ' + + moduleName + '.\n' + + 'You already have version ' + versionValue + + ' installed.\n' + + 'This means you cannot install version ' + version); + } + + return Individual(key, defaultValue); +} + +},{"./index.js":8}],10:[function(require,module,exports){ +(function (global){ +var topLevel = typeof global !== 'undefined' ? global : + typeof window !== 'undefined' ? window : {} +var minDoc = require('min-document'); + +if (typeof document !== 'undefined') { + module.exports = document; +} else { + var doccy = topLevel['__GLOBAL_DOCUMENT_CACHE@4']; + + if (!doccy) { + doccy = topLevel['__GLOBAL_DOCUMENT_CACHE@4'] = minDoc; + } + + module.exports = doccy; +} + +}).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}) +},{"min-document":6}],11:[function(require,module,exports){ +"use strict"; + +module.exports = function isObject(x) { + return typeof x === "object" && x !== null; +}; + +},{}],12:[function(require,module,exports){ +var nativeIsArray = Array.isArray +var toString = Object.prototype.toString + +module.exports = nativeIsArray || isArray + +function isArray(obj) { + return toString.call(obj) === "[object Array]" +} + +},{}],13:[function(require,module,exports){ +var patch = require("./vdom/patch.js") + +module.exports = patch + +},{"./vdom/patch.js":18}],14:[function(require,module,exports){ +var isObject = require("is-object") +var isHook = require("../vnode/is-vhook.js") + +module.exports = applyProperties + +function applyProperties(node, props, previous) { + for (var propName in props) { + var propValue = props[propName] + + if (propValue === undefined) { + removeProperty(node, propName, propValue, previous); + } else if (isHook(propValue)) { + removeProperty(node, propName, propValue, previous) + if (propValue.hook) { + propValue.hook(node, + propName, + previous ? previous[propName] : undefined) + } + } else { + if (isObject(propValue)) { + patchObject(node, props, previous, propName, propValue); + } else { + node[propName] = propValue + } + } + } +} + +function removeProperty(node, propName, propValue, previous) { + if (previous) { + var previousValue = previous[propName] + + if (!isHook(previousValue)) { + if (propName === "attributes") { + for (var attrName in previousValue) { + node.removeAttribute(attrName) + } + } else if (propName === "style") { + for (var i in previousValue) { + node.style[i] = "" + } + } else if (typeof previousValue === "string") { + node[propName] = "" + } else { + node[propName] = null + } + } else if (previousValue.unhook) { + previousValue.unhook(node, propName, propValue) + } + } +} + +function patchObject(node, props, previous, propName, propValue) { + var previousValue = previous ? previous[propName] : undefined + + // Set attributes + if (propName === "attributes") { + for (var attrName in propValue) { + var attrValue = propValue[attrName] + + if (attrValue === undefined) { + node.removeAttribute(attrName) + } else { + node.setAttribute(attrName, attrValue) + } + } + + return + } + + if(previousValue && isObject(previousValue) && + getPrototype(previousValue) !== getPrototype(propValue)) { + node[propName] = propValue + return + } + + if (!isObject(node[propName])) { + node[propName] = {} + } + + var replacer = propName === "style" ? "" : undefined + + for (var k in propValue) { + var value = propValue[k] + node[propName][k] = (value === undefined) ? replacer : value + } +} + +function getPrototype(value) { + if (Object.getPrototypeOf) { + return Object.getPrototypeOf(value) + } else if (value.__proto__) { + return value.__proto__ + } else if (value.constructor) { + return value.constructor.prototype + } +} + +},{"../vnode/is-vhook.js":26,"is-object":11}],15:[function(require,module,exports){ +var document = require("global/document") + +var applyProperties = require("./apply-properties") + +var isVNode = require("../vnode/is-vnode.js") +var isVText = require("../vnode/is-vtext.js") +var isWidget = require("../vnode/is-widget.js") +var handleThunk = require("../vnode/handle-thunk.js") + +module.exports = createElement + +function createElement(vnode, opts) { + var doc = opts ? opts.document || document : document + var warn = opts ? opts.warn : null + + vnode = handleThunk(vnode).a + + if (isWidget(vnode)) { + return vnode.init() + } else if (isVText(vnode)) { + return doc.createTextNode(vnode.text) + } else if (!isVNode(vnode)) { + if (warn) { + warn("Item is not a valid virtual dom node", vnode) + } + return null + } + + var node = (vnode.namespace === null) ? + doc.createElement(vnode.tagName) : + doc.createElementNS(vnode.namespace, vnode.tagName) + + var props = vnode.properties + applyProperties(node, props) + + var children = vnode.children + + for (var i = 0; i < children.length; i++) { + var childNode = createElement(children[i], opts) + if (childNode) { + node.appendChild(childNode) + } + } + + return node +} + +},{"../vnode/handle-thunk.js":24,"../vnode/is-vnode.js":27,"../vnode/is-vtext.js":28,"../vnode/is-widget.js":29,"./apply-properties":14,"global/document":10}],16:[function(require,module,exports){ +// Maps a virtual DOM tree onto a real DOM tree in an efficient manner. +// We don't want to read all of the DOM nodes in the tree so we use +// the in-order tree indexing to eliminate recursion down certain branches. +// We only recurse into a DOM node if we know that it contains a child of +// interest. + +var noChild = {} + +module.exports = domIndex + +function domIndex(rootNode, tree, indices, nodes) { + if (!indices || indices.length === 0) { + return {} + } else { + indices.sort(ascending) + return recurse(rootNode, tree, indices, nodes, 0) + } +} + +function recurse(rootNode, tree, indices, nodes, rootIndex) { + nodes = nodes || {} + + + if (rootNode) { + if (indexInRange(indices, rootIndex, rootIndex)) { + nodes[rootIndex] = rootNode + } + + var vChildren = tree.children + + if (vChildren) { + + var childNodes = rootNode.childNodes + + for (var i = 0; i < tree.children.length; i++) { + rootIndex += 1 + + var vChild = vChildren[i] || noChild + var nextIndex = rootIndex + (vChild.count || 0) + + // skip recursion down the tree if there are no nodes down here + if (indexInRange(indices, rootIndex, nextIndex)) { + recurse(childNodes[i], vChild, indices, nodes, rootIndex) + } + + rootIndex = nextIndex + } + } + } + + return nodes +} + +// Binary search for an index in the interval [left, right] +function indexInRange(indices, left, right) { + if (indices.length === 0) { + return false + } + + var minIndex = 0 + var maxIndex = indices.length - 1 + var currentIndex + var currentItem + + while (minIndex <= maxIndex) { + currentIndex = ((maxIndex + minIndex) / 2) >> 0 + currentItem = indices[currentIndex] + + if (minIndex === maxIndex) { + return currentItem >= left && currentItem <= right + } else if (currentItem < left) { + minIndex = currentIndex + 1 + } else if (currentItem > right) { + maxIndex = currentIndex - 1 + } else { + return true + } + } + + return false; +} + +function ascending(a, b) { + return a > b ? 1 : -1 +} + +},{}],17:[function(require,module,exports){ +var applyProperties = require("./apply-properties") + +var isWidget = require("../vnode/is-widget.js") +var VPatch = require("../vnode/vpatch.js") + +var updateWidget = require("./update-widget") + +module.exports = applyPatch + +function applyPatch(vpatch, domNode, renderOptions) { + var type = vpatch.type + var vNode = vpatch.vNode + var patch = vpatch.patch + + switch (type) { + case VPatch.REMOVE: + return removeNode(domNode, vNode) + case VPatch.INSERT: + return insertNode(domNode, patch, renderOptions) + case VPatch.VTEXT: + return stringPatch(domNode, vNode, patch, renderOptions) + case VPatch.WIDGET: + return widgetPatch(domNode, vNode, patch, renderOptions) + case VPatch.VNODE: + return vNodePatch(domNode, vNode, patch, renderOptions) + case VPatch.ORDER: + reorderChildren(domNode, patch) + return domNode + case VPatch.PROPS: + applyProperties(domNode, patch, vNode.properties) + return domNode + case VPatch.THUNK: + return replaceRoot(domNode, + renderOptions.patch(domNode, patch, renderOptions)) + default: + return domNode + } +} + +function removeNode(domNode, vNode) { + var parentNode = domNode.parentNode + + if (parentNode) { + parentNode.removeChild(domNode) + } + + destroyWidget(domNode, vNode); + + return null +} + +function insertNode(parentNode, vNode, renderOptions) { + var newNode = renderOptions.render(vNode, renderOptions) + + if (parentNode) { + parentNode.appendChild(newNode) + } + + return parentNode +} + +function stringPatch(domNode, leftVNode, vText, renderOptions) { + var newNode + + if (domNode.nodeType === 3) { + domNode.replaceData(0, domNode.length, vText.text) + newNode = domNode + } else { + var parentNode = domNode.parentNode + newNode = renderOptions.render(vText, renderOptions) + + if (parentNode && newNode !== domNode) { + parentNode.replaceChild(newNode, domNode) + } + } + + return newNode +} + +function widgetPatch(domNode, leftVNode, widget, renderOptions) { + var updating = updateWidget(leftVNode, widget) + var newNode + + if (updating) { + newNode = widget.update(leftVNode, domNode) || domNode + } else { + newNode = renderOptions.render(widget, renderOptions) + } + + var parentNode = domNode.parentNode + + if (parentNode && newNode !== domNode) { + parentNode.replaceChild(newNode, domNode) + } + + if (!updating) { + destroyWidget(domNode, leftVNode) + } + + return newNode +} + +function vNodePatch(domNode, leftVNode, vNode, renderOptions) { + var parentNode = domNode.parentNode + var newNode = renderOptions.render(vNode, renderOptions) + + if (parentNode && newNode !== domNode) { + parentNode.replaceChild(newNode, domNode) + } + + return newNode +} + +function destroyWidget(domNode, w) { + if (typeof w.destroy === "function" && isWidget(w)) { + w.destroy(domNode) + } +} + +function reorderChildren(domNode, moves) { + var childNodes = domNode.childNodes + var keyMap = {} + var node + var remove + var insert + + for (var i = 0; i < moves.removes.length; i++) { + remove = moves.removes[i] + node = childNodes[remove.from] + if (remove.key) { + keyMap[remove.key] = node + } + domNode.removeChild(node) + } + + var length = childNodes.length + for (var j = 0; j < moves.inserts.length; j++) { + insert = moves.inserts[j] + node = keyMap[insert.key] + // this is the weirdest bug i've ever seen in webkit + domNode.insertBefore(node, insert.to >= length++ ? null : childNodes[insert.to]) + } +} + +function replaceRoot(oldRoot, newRoot) { + if (oldRoot && newRoot && oldRoot !== newRoot && oldRoot.parentNode) { + oldRoot.parentNode.replaceChild(newRoot, oldRoot) + } + + return newRoot; +} + +},{"../vnode/is-widget.js":29,"../vnode/vpatch.js":32,"./apply-properties":14,"./update-widget":19}],18:[function(require,module,exports){ +var document = require("global/document") +var isArray = require("x-is-array") + +var render = require("./create-element") +var domIndex = require("./dom-index") +var patchOp = require("./patch-op") +module.exports = patch + +function patch(rootNode, patches, renderOptions) { + renderOptions = renderOptions || {} + renderOptions.patch = renderOptions.patch && renderOptions.patch !== patch + ? renderOptions.patch + : patchRecursive + renderOptions.render = renderOptions.render || render + + return renderOptions.patch(rootNode, patches, renderOptions) +} + +function patchRecursive(rootNode, patches, renderOptions) { + var indices = patchIndices(patches) + + if (indices.length === 0) { + return rootNode + } + + var index = domIndex(rootNode, patches.a, indices) + var ownerDocument = rootNode.ownerDocument + + if (!renderOptions.document && ownerDocument !== document) { + renderOptions.document = ownerDocument + } + + for (var i = 0; i < indices.length; i++) { + var nodeIndex = indices[i] + rootNode = applyPatch(rootNode, + index[nodeIndex], + patches[nodeIndex], + renderOptions) + } + + return rootNode +} + +function applyPatch(rootNode, domNode, patchList, renderOptions) { + if (!domNode) { + return rootNode + } + + var newNode + + if (isArray(patchList)) { + for (var i = 0; i < patchList.length; i++) { + newNode = patchOp(patchList[i], domNode, renderOptions) + + if (domNode === rootNode) { + rootNode = newNode + } + } + } else { + newNode = patchOp(patchList, domNode, renderOptions) + + if (domNode === rootNode) { + rootNode = newNode + } + } + + return rootNode +} + +function patchIndices(patches) { + var indices = [] + + for (var key in patches) { + if (key !== "a") { + indices.push(Number(key)) + } + } + + return indices +} + +},{"./create-element":15,"./dom-index":16,"./patch-op":17,"global/document":10,"x-is-array":12}],19:[function(require,module,exports){ +var isWidget = require("../vnode/is-widget.js") + +module.exports = updateWidget + +function updateWidget(a, b) { + if (isWidget(a) && isWidget(b)) { + if ("name" in a && "name" in b) { + return a.id === b.id + } else { + return a.init === b.init + } + } + + return false +} + +},{"../vnode/is-widget.js":29}],20:[function(require,module,exports){ +'use strict'; + +var EvStore = require('ev-store'); + +module.exports = EvHook; + +function EvHook(value) { + if (!(this instanceof EvHook)) { + return new EvHook(value); + } + + this.value = value; +} + +EvHook.prototype.hook = function (node, propertyName) { + var es = EvStore(node); + var propName = propertyName.substr(3); + + es[propName] = this.value; +}; + +EvHook.prototype.unhook = function(node, propertyName) { + var es = EvStore(node); + var propName = propertyName.substr(3); + + es[propName] = undefined; +}; + +},{"ev-store":7}],21:[function(require,module,exports){ +'use strict'; + +module.exports = SoftSetHook; + +function SoftSetHook(value) { + if (!(this instanceof SoftSetHook)) { + return new SoftSetHook(value); + } + + this.value = value; +} + +SoftSetHook.prototype.hook = function (node, propertyName) { + if (node[propertyName] !== this.value) { + node[propertyName] = this.value; + } +}; + +},{}],22:[function(require,module,exports){ +'use strict'; + +var isArray = require('x-is-array'); + +var VNode = require('../vnode/vnode.js'); +var VText = require('../vnode/vtext.js'); +var isVNode = require('../vnode/is-vnode'); +var isVText = require('../vnode/is-vtext'); +var isWidget = require('../vnode/is-widget'); +var isHook = require('../vnode/is-vhook'); +var isVThunk = require('../vnode/is-thunk'); + +var parseTag = require('./parse-tag.js'); +var softSetHook = require('./hooks/soft-set-hook.js'); +var evHook = require('./hooks/ev-hook.js'); + +module.exports = h; + +function h(tagName, properties, children) { + var childNodes = []; + var tag, props, key, namespace; + + if (!children && isChildren(properties)) { + children = properties; + props = {}; + } + + props = props || properties || {}; + tag = parseTag(tagName, props); + + // support keys + if (props.hasOwnProperty('key')) { + key = props.key; + props.key = undefined; + } + + // support namespace + if (props.hasOwnProperty('namespace')) { + namespace = props.namespace; + props.namespace = undefined; + } + + // fix cursor bug + if (tag === 'INPUT' && + !namespace && + props.hasOwnProperty('value') && + props.value !== undefined && + !isHook(props.value) + ) { + props.value = softSetHook(props.value); + } + + transformProperties(props); + + if (children !== undefined && children !== null) { + addChild(children, childNodes, tag, props); + } + + + return new VNode(tag, props, childNodes, key, namespace); +} + +function addChild(c, childNodes, tag, props) { + if (typeof c === 'string') { + childNodes.push(new VText(c)); + } else if (typeof c === 'number') { + childNodes.push(new VText(String(c))); + } else if (isChild(c)) { + childNodes.push(c); + } else if (isArray(c)) { + for (var i = 0; i < c.length; i++) { + addChild(c[i], childNodes, tag, props); + } + } else if (c === null || c === undefined) { + return; + } else { + throw UnexpectedVirtualElement({ + foreignObject: c, + parentVnode: { + tagName: tag, + properties: props + } + }); + } +} + +function transformProperties(props) { + for (var propName in props) { + if (props.hasOwnProperty(propName)) { + var value = props[propName]; + + if (isHook(value)) { + continue; + } + + if (propName.substr(0, 3) === 'ev-') { + // add ev-foo support + props[propName] = evHook(value); + } + } + } +} + +function isChild(x) { + return isVNode(x) || isVText(x) || isWidget(x) || isVThunk(x); +} + +function isChildren(x) { + return typeof x === 'string' || isArray(x) || isChild(x); +} + +function UnexpectedVirtualElement(data) { + var err = new Error(); + + err.type = 'virtual-hyperscript.unexpected.virtual-element'; + err.message = 'Unexpected virtual child passed to h().\n' + + 'Expected a VNode / Vthunk / VWidget / string but:\n' + + 'got:\n' + + errorString(data.foreignObject) + + '.\n' + + 'The parent vnode is:\n' + + errorString(data.parentVnode) + '\n' + + 'Suggested fix: change your `h(..., [ ... ])` callsite.'; + err.foreignObject = data.foreignObject; + err.parentVnode = data.parentVnode; + + return err; +} + +function errorString(obj) { + try { + return JSON.stringify(obj, null, ' '); + } catch (e) { + return String(obj); + } +} + +},{"../vnode/is-thunk":25,"../vnode/is-vhook":26,"../vnode/is-vnode":27,"../vnode/is-vtext":28,"../vnode/is-widget":29,"../vnode/vnode.js":31,"../vnode/vtext.js":33,"./hooks/ev-hook.js":20,"./hooks/soft-set-hook.js":21,"./parse-tag.js":23,"x-is-array":12}],23:[function(require,module,exports){ +'use strict'; + +var split = require('browser-split'); + +var classIdSplit = /([\.#]?[a-zA-Z0-9\u007F-\uFFFF_:-]+)/; +var notClassId = /^\.|#/; + +module.exports = parseTag; + +function parseTag(tag, props) { + if (!tag) { + return 'DIV'; + } + + var noId = !(props.hasOwnProperty('id')); + + var tagParts = split(tag, classIdSplit); + var tagName = null; + + if (notClassId.test(tagParts[1])) { + tagName = 'DIV'; + } + + var classes, part, type, i; + + for (i = 0; i < tagParts.length; i++) { + part = tagParts[i]; + + if (!part) { + continue; + } + + type = part.charAt(0); + + if (!tagName) { + tagName = part; + } else if (type === '.') { + classes = classes || []; + classes.push(part.substring(1, part.length)); + } else if (type === '#' && noId) { + props.id = part.substring(1, part.length); + } + } + + if (classes) { + if (props.className) { + classes.push(props.className); + } + + props.className = classes.join(' '); + } + + return props.namespace ? tagName : tagName.toUpperCase(); +} + +},{"browser-split":5}],24:[function(require,module,exports){ +var isVNode = require("./is-vnode") +var isVText = require("./is-vtext") +var isWidget = require("./is-widget") +var isThunk = require("./is-thunk") + +module.exports = handleThunk + +function handleThunk(a, b) { + var renderedA = a + var renderedB = b + + if (isThunk(b)) { + renderedB = renderThunk(b, a) + } + + if (isThunk(a)) { + renderedA = renderThunk(a, null) + } + + return { + a: renderedA, + b: renderedB + } +} + +function renderThunk(thunk, previous) { + var renderedThunk = thunk.vnode + + if (!renderedThunk) { + renderedThunk = thunk.vnode = thunk.render(previous) + } + + if (!(isVNode(renderedThunk) || + isVText(renderedThunk) || + isWidget(renderedThunk))) { + throw new Error("thunk did not return a valid node"); + } + + return renderedThunk +} + +},{"./is-thunk":25,"./is-vnode":27,"./is-vtext":28,"./is-widget":29}],25:[function(require,module,exports){ +module.exports = isThunk + +function isThunk(t) { + return t && t.type === "Thunk" +} + +},{}],26:[function(require,module,exports){ +module.exports = isHook + +function isHook(hook) { + return hook && + (typeof hook.hook === "function" && !hook.hasOwnProperty("hook") || + typeof hook.unhook === "function" && !hook.hasOwnProperty("unhook")) +} + +},{}],27:[function(require,module,exports){ +var version = require("./version") + +module.exports = isVirtualNode + +function isVirtualNode(x) { + return x && x.type === "VirtualNode" && x.version === version +} + +},{"./version":30}],28:[function(require,module,exports){ +var version = require("./version") + +module.exports = isVirtualText + +function isVirtualText(x) { + return x && x.type === "VirtualText" && x.version === version +} + +},{"./version":30}],29:[function(require,module,exports){ +module.exports = isWidget + +function isWidget(w) { + return w && w.type === "Widget" +} + +},{}],30:[function(require,module,exports){ +module.exports = "2" + +},{}],31:[function(require,module,exports){ +var version = require("./version") +var isVNode = require("./is-vnode") +var isWidget = require("./is-widget") +var isThunk = require("./is-thunk") +var isVHook = require("./is-vhook") + +module.exports = VirtualNode + +var noProperties = {} +var noChildren = [] + +function VirtualNode(tagName, properties, children, key, namespace) { + this.tagName = tagName + this.properties = properties || noProperties + this.children = children || noChildren + this.key = key != null ? String(key) : undefined + this.namespace = (typeof namespace === "string") ? namespace : null + + var count = (children && children.length) || 0 + var descendants = 0 + var hasWidgets = false + var hasThunks = false + var descendantHooks = false + var hooks + + for (var propName in properties) { + if (properties.hasOwnProperty(propName)) { + var property = properties[propName] + if (isVHook(property) && property.unhook) { + if (!hooks) { + hooks = {} + } + + hooks[propName] = property + } + } + } + + for (var i = 0; i < count; i++) { + var child = children[i] + if (isVNode(child)) { + descendants += child.count || 0 + + if (!hasWidgets && child.hasWidgets) { + hasWidgets = true + } + + if (!hasThunks && child.hasThunks) { + hasThunks = true + } + + if (!descendantHooks && (child.hooks || child.descendantHooks)) { + descendantHooks = true + } + } else if (!hasWidgets && isWidget(child)) { + if (typeof child.destroy === "function") { + hasWidgets = true + } + } else if (!hasThunks && isThunk(child)) { + hasThunks = true; + } + } + + this.count = count + descendants + this.hasWidgets = hasWidgets + this.hasThunks = hasThunks + this.hooks = hooks + this.descendantHooks = descendantHooks +} + +VirtualNode.prototype.version = version +VirtualNode.prototype.type = "VirtualNode" + +},{"./is-thunk":25,"./is-vhook":26,"./is-vnode":27,"./is-widget":29,"./version":30}],32:[function(require,module,exports){ +var version = require("./version") + +VirtualPatch.NONE = 0 +VirtualPatch.VTEXT = 1 +VirtualPatch.VNODE = 2 +VirtualPatch.WIDGET = 3 +VirtualPatch.PROPS = 4 +VirtualPatch.ORDER = 5 +VirtualPatch.INSERT = 6 +VirtualPatch.REMOVE = 7 +VirtualPatch.THUNK = 8 + +module.exports = VirtualPatch + +function VirtualPatch(type, vNode, patch) { + this.type = Number(type) + this.vNode = vNode + this.patch = patch +} + +VirtualPatch.prototype.version = version +VirtualPatch.prototype.type = "VirtualPatch" + +},{"./version":30}],33:[function(require,module,exports){ +var version = require("./version") + +module.exports = VirtualText + +function VirtualText(text) { + this.text = String(text) +} + +VirtualText.prototype.version = version +VirtualText.prototype.type = "VirtualText" + +},{"./version":30}],34:[function(require,module,exports){ +var isObject = require("is-object") +var isHook = require("../vnode/is-vhook") + +module.exports = diffProps + +function diffProps(a, b) { + var diff + + for (var aKey in a) { + if (!(aKey in b)) { + diff = diff || {} + diff[aKey] = undefined + } + + var aValue = a[aKey] + var bValue = b[aKey] + + if (aValue === bValue) { + continue + } else if (isObject(aValue) && isObject(bValue)) { + if (getPrototype(bValue) !== getPrototype(aValue)) { + diff = diff || {} + diff[aKey] = bValue + } else if (isHook(bValue)) { + diff = diff || {} + diff[aKey] = bValue + } else { + var objectDiff = diffProps(aValue, bValue) + if (objectDiff) { + diff = diff || {} + diff[aKey] = objectDiff + } + } + } else { + diff = diff || {} + diff[aKey] = bValue + } + } + + for (var bKey in b) { + if (!(bKey in a)) { + diff = diff || {} + diff[bKey] = b[bKey] + } + } + + return diff +} + +function getPrototype(value) { + if (Object.getPrototypeOf) { + return Object.getPrototypeOf(value) + } else if (value.__proto__) { + return value.__proto__ + } else if (value.constructor) { + return value.constructor.prototype + } +} + +},{"../vnode/is-vhook":26,"is-object":11}],35:[function(require,module,exports){ +var isArray = require("x-is-array") + +var VPatch = require("../vnode/vpatch") +var isVNode = require("../vnode/is-vnode") +var isVText = require("../vnode/is-vtext") +var isWidget = require("../vnode/is-widget") +var isThunk = require("../vnode/is-thunk") +var handleThunk = require("../vnode/handle-thunk") + +var diffProps = require("./diff-props") + +module.exports = diff + +function diff(a, b) { + var patch = { a: a } + walk(a, b, patch, 0) + return patch +} + +function walk(a, b, patch, index) { + if (a === b) { + return + } + + var apply = patch[index] + var applyClear = false + + if (isThunk(a) || isThunk(b)) { + thunks(a, b, patch, index) + } else if (b == null) { + + // If a is a widget we will add a remove patch for it + // Otherwise any child widgets/hooks must be destroyed. + // This prevents adding two remove patches for a widget. + if (!isWidget(a)) { + clearState(a, patch, index) + apply = patch[index] + } + + apply = appendPatch(apply, new VPatch(VPatch.REMOVE, a, b)) + } else if (isVNode(b)) { + if (isVNode(a)) { + if (a.tagName === b.tagName && + a.namespace === b.namespace && + a.key === b.key) { + var propsPatch = diffProps(a.properties, b.properties) + if (propsPatch) { + apply = appendPatch(apply, + new VPatch(VPatch.PROPS, a, propsPatch)) + } + apply = diffChildren(a, b, patch, apply, index) + } else { + apply = appendPatch(apply, new VPatch(VPatch.VNODE, a, b)) + applyClear = true + } + } else { + apply = appendPatch(apply, new VPatch(VPatch.VNODE, a, b)) + applyClear = true + } + } else if (isVText(b)) { + if (!isVText(a)) { + apply = appendPatch(apply, new VPatch(VPatch.VTEXT, a, b)) + applyClear = true + } else if (a.text !== b.text) { + apply = appendPatch(apply, new VPatch(VPatch.VTEXT, a, b)) + } + } else if (isWidget(b)) { + if (!isWidget(a)) { + applyClear = true + } + + apply = appendPatch(apply, new VPatch(VPatch.WIDGET, a, b)) + } + + if (apply) { + patch[index] = apply + } + + if (applyClear) { + clearState(a, patch, index) + } +} + +function diffChildren(a, b, patch, apply, index) { + var aChildren = a.children + var orderedSet = reorder(aChildren, b.children) + var bChildren = orderedSet.children + + var aLen = aChildren.length + var bLen = bChildren.length + var len = aLen > bLen ? aLen : bLen + + for (var i = 0; i < len; i++) { + var leftNode = aChildren[i] + var rightNode = bChildren[i] + index += 1 + + if (!leftNode) { + if (rightNode) { + // Excess nodes in b need to be added + apply = appendPatch(apply, + new VPatch(VPatch.INSERT, null, rightNode)) + } + } else { + walk(leftNode, rightNode, patch, index) + } + + if (isVNode(leftNode) && leftNode.count) { + index += leftNode.count + } + } + + if (orderedSet.moves) { + // Reorder nodes last + apply = appendPatch(apply, new VPatch( + VPatch.ORDER, + a, + orderedSet.moves + )) + } + + return apply +} + +function clearState(vNode, patch, index) { + // TODO: Make this a single walk, not two + unhook(vNode, patch, index) + destroyWidgets(vNode, patch, index) +} + +// Patch records for all destroyed widgets must be added because we need +// a DOM node reference for the destroy function +function destroyWidgets(vNode, patch, index) { + if (isWidget(vNode)) { + if (typeof vNode.destroy === "function") { + patch[index] = appendPatch( + patch[index], + new VPatch(VPatch.REMOVE, vNode, null) + ) + } + } else if (isVNode(vNode) && (vNode.hasWidgets || vNode.hasThunks)) { + var children = vNode.children + var len = children.length + for (var i = 0; i < len; i++) { + var child = children[i] + index += 1 + + destroyWidgets(child, patch, index) + + if (isVNode(child) && child.count) { + index += child.count + } + } + } else if (isThunk(vNode)) { + thunks(vNode, null, patch, index) + } +} + +// Create a sub-patch for thunks +function thunks(a, b, patch, index) { + var nodes = handleThunk(a, b) + var thunkPatch = diff(nodes.a, nodes.b) + if (hasPatches(thunkPatch)) { + patch[index] = new VPatch(VPatch.THUNK, null, thunkPatch) + } +} + +function hasPatches(patch) { + for (var index in patch) { + if (index !== "a") { + return true + } + } + + return false +} + +// Execute hooks when two nodes are identical +function unhook(vNode, patch, index) { + if (isVNode(vNode)) { + if (vNode.hooks) { + patch[index] = appendPatch( + patch[index], + new VPatch( + VPatch.PROPS, + vNode, + undefinedKeys(vNode.hooks) + ) + ) + } + + if (vNode.descendantHooks || vNode.hasThunks) { + var children = vNode.children + var len = children.length + for (var i = 0; i < len; i++) { + var child = children[i] + index += 1 + + unhook(child, patch, index) + + if (isVNode(child) && child.count) { + index += child.count + } + } + } + } else if (isThunk(vNode)) { + thunks(vNode, null, patch, index) + } +} + +function undefinedKeys(obj) { + var result = {} + + for (var key in obj) { + result[key] = undefined + } + + return result +} + +// List diff, naive left to right reordering +function reorder(aChildren, bChildren) { + // O(M) time, O(M) memory + var bChildIndex = keyIndex(bChildren) + var bKeys = bChildIndex.keys + var bFree = bChildIndex.free + + if (bFree.length === bChildren.length) { + return { + children: bChildren, + moves: null + } + } + + // O(N) time, O(N) memory + var aChildIndex = keyIndex(aChildren) + var aKeys = aChildIndex.keys + var aFree = aChildIndex.free + + if (aFree.length === aChildren.length) { + return { + children: bChildren, + moves: null + } + } + + // O(MAX(N, M)) memory + var newChildren = [] + + var freeIndex = 0 + var freeCount = bFree.length + var deletedItems = 0 + + // Iterate through a and match a node in b + // O(N) time, + for (var i = 0 ; i < aChildren.length; i++) { + var aItem = aChildren[i] + var itemIndex + + if (aItem.key) { + if (bKeys.hasOwnProperty(aItem.key)) { + // Match up the old keys + itemIndex = bKeys[aItem.key] + newChildren.push(bChildren[itemIndex]) + + } else { + // Remove old keyed items + itemIndex = i - deletedItems++ + newChildren.push(null) + } + } else { + // Match the item in a with the next free item in b + if (freeIndex < freeCount) { + itemIndex = bFree[freeIndex++] + newChildren.push(bChildren[itemIndex]) + } else { + // There are no free items in b to match with + // the free items in a, so the extra free nodes + // are deleted. + itemIndex = i - deletedItems++ + newChildren.push(null) + } + } + } + + var lastFreeIndex = freeIndex >= bFree.length ? + bChildren.length : + bFree[freeIndex] + + // Iterate through b and append any new keys + // O(M) time + for (var j = 0; j < bChildren.length; j++) { + var newItem = bChildren[j] + + if (newItem.key) { + if (!aKeys.hasOwnProperty(newItem.key)) { + // Add any new keyed items + // We are adding new items to the end and then sorting them + // in place. In future we should insert new items in place. + newChildren.push(newItem) + } + } else if (j >= lastFreeIndex) { + // Add any leftover non-keyed items + newChildren.push(newItem) + } + } + + var simulate = newChildren.slice() + var simulateIndex = 0 + var removes = [] + var inserts = [] + var simulateItem + + for (var k = 0; k < bChildren.length;) { + var wantedItem = bChildren[k] + simulateItem = simulate[simulateIndex] + + // remove items + while (simulateItem === null && simulate.length) { + removes.push(remove(simulate, simulateIndex, null)) + simulateItem = simulate[simulateIndex] + } + + if (!simulateItem || simulateItem.key !== wantedItem.key) { + // if we need a key in this position... + if (wantedItem.key) { + if (simulateItem && simulateItem.key) { + // if an insert doesn't put this key in place, it needs to move + if (bKeys[simulateItem.key] !== k + 1) { + removes.push(remove(simulate, simulateIndex, simulateItem.key)) + simulateItem = simulate[simulateIndex] + // if the remove didn't put the wanted item in place, we need to insert it + if (!simulateItem || simulateItem.key !== wantedItem.key) { + inserts.push({key: wantedItem.key, to: k}) + } + // items are matching, so skip ahead + else { + simulateIndex++ + } + } + else { + inserts.push({key: wantedItem.key, to: k}) + } + } + else { + inserts.push({key: wantedItem.key, to: k}) + } + k++ + } + // a key in simulate has no matching wanted key, remove it + else if (simulateItem && simulateItem.key) { + removes.push(remove(simulate, simulateIndex, simulateItem.key)) + } + } + else { + simulateIndex++ + k++ + } + } + + // remove all the remaining nodes from simulate + while(simulateIndex < simulate.length) { + simulateItem = simulate[simulateIndex] + removes.push(remove(simulate, simulateIndex, simulateItem && simulateItem.key)) + } + + // If the only moves we have are deletes then we can just + // let the delete patch remove these items. + if (removes.length === deletedItems && !inserts.length) { + return { + children: newChildren, + moves: null + } + } + + return { + children: newChildren, + moves: { + removes: removes, + inserts: inserts + } + } +} + +function remove(arr, index, key) { + arr.splice(index, 1) + + return { + from: index, + key: key + } +} + +function keyIndex(children) { + var keys = {} + var free = [] + var length = children.length + + for (var i = 0; i < length; i++) { + var child = children[i] + + if (child.key) { + keys[child.key] = i + } else { + free.push(i) + } + } + + return { + keys: keys, // A hash of key name to index + free: free // An array of unkeyed item indices + } +} + +function appendPatch(apply, patch) { + if (apply) { + if (isArray(apply)) { + apply.push(patch) + } else { + apply = [apply, patch] + } + + return apply + } else { + return patch + } +} + +},{"../vnode/handle-thunk":24,"../vnode/is-thunk":25,"../vnode/is-vnode":27,"../vnode/is-vtext":28,"../vnode/is-widget":29,"../vnode/vpatch":32,"./diff-props":34,"x-is-array":12}]},{},[4])(4) +}); + +export default virtualDom; diff --git a/test/elixir_script_test.exs b/test/elixir_script_test.exs index c554e5f2..ee4ff937 100644 --- a/test/elixir_script_test.exs +++ b/test/elixir_script_test.exs @@ -119,4 +119,26 @@ defmodule ElixirScript.Test do """, hd(js_code) end + + should "expand Html macros" do + js_code = ElixirScript.compile(""" + tree = Html.div [id: "myDiv"] do + Html.span do + "Hello" + end + + Html.span do + "World" + end + end + + rootNode = Html.create(tree) + :document.getElementById("main").appendChild(rootNode) + """) + + assert hd(js_code) =~ "Elixir.VirtualDOM.h('div'" + assert hd(js_code) =~ "Elixir.VirtualDOM.h('span'" + assert hd(js_code) =~ "Elixir.VirtualDOM.create" + end + end diff --git a/test/test_helper.exs b/test/test_helper.exs index 14417b8f..0cc4b2ca 100644 --- a/test/test_helper.exs +++ b/test/test_helper.exs @@ -27,7 +27,6 @@ defmodule ElixirScript.TestHelper do require Logger require ElixirScript.Math require ElixirScript.Using - __ENV__ end @@ -36,7 +35,7 @@ defmodule ElixirScript.TestHelper do end def strip_spaces(js) do - js |> strip_new_lines |> String.replace(" ", "") + js |> strip_new_lines |> String.replace(" ", "") end def strip_new_lines(js) do From d78d1f65c349dc6a847fd6b12cd7859a951749dc Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Fri, 27 Nov 2015 11:04:05 -0600 Subject: [PATCH 060/860] moved create, diff, and patch into the VDom module --- lib/elixir_script.ex | 1 + lib/elixir_script/lib/html.ex | 48 +++++++++++--------- lib/elixir_script/lib/v_dom.ex | 80 ++++++++++++++++++++++++++++++++++ test/elixir_script_test.exs | 2 +- 4 files changed, 109 insertions(+), 22 deletions(-) create mode 100644 lib/elixir_script/lib/v_dom.ex diff --git a/lib/elixir_script.ex b/lib/elixir_script.ex index 971e36a2..631233d7 100644 --- a/lib/elixir_script.ex +++ b/lib/elixir_script.ex @@ -82,6 +82,7 @@ defmodule ElixirScript do require Logger require ElixirScript.JS, as: JS require ElixirScript.Html, as: Html + require ElixirScript.VDom, as: VDom __ENV__ end diff --git a/lib/elixir_script/lib/html.ex b/lib/elixir_script/lib/html.ex index b55bc16a..327b28f8 100644 --- a/lib/elixir_script/lib/html.ex +++ b/lib/elixir_script/lib/html.ex @@ -1,4 +1,25 @@ defmodule ElixirScript.Html do + @moduledoc """ + Defines macros for HTML elements to be used to build up a virtual dom tree. + The virtual dom tree defined here can then be used with macros defined in the + VDom module + + tree = Html.div [id: "hello"] do + Html.span do + "Hello" + end + end + + rootNode = VDom.create(tree) + :document.getElementById("main").appendChild(rootNode) + + newTree = Html.div [id: "world"] + + + patches = VDom.diff(tree, newTree) + rootNode = VDom.patch(rootNode, patches) + + """ @external_resource tags_path = Path.join([__DIR__, "tags.txt"]) @tags (for line <- File.stream!(tags_path, [], :line) do @@ -6,7 +27,10 @@ defmodule ElixirScript.Html do end) for tag <- @tags do - defmacro unquote(tag)(config \\ [], block \\ [do: nil]) do + @doc """ + Defines a macro for the html element, #{tag} + """ + defmacro unquote(tag)(attributes \\ [], block \\ [do: nil]) do tag = Atom.to_string(unquote(tag)) inner = case Keyword.get(block, :do) do @@ -18,10 +42,10 @@ defmodule ElixirScript.Html do [x] end - config = config_to_map(config) + attributes = config_to_map(attributes) quote do - Elixir.VirtualDOM.h(unquote(tag), unquote(config), unquote_splicing(inner)) + Elixir.VirtualDOM.h(unquote(tag), unquote(attributes), unquote_splicing(inner)) end end end @@ -38,22 +62,4 @@ defmodule ElixirScript.Html do {:%{}, [], config} end - defmacro create(element) do - quote do - Elixir.VirtualDOM.create(unquote(element)) - end - end - - defmacro diff(tree, newTree) do - quote do - Elixir.VirtualDOM.diff(unquote(tree), unquote(newTree)) - end - end - - defmacro patch(root, patches) do - quote do - Elixir.VirtualDOM.patch(unquote(root), unquote(patches)) - end - end - end diff --git a/lib/elixir_script/lib/v_dom.ex b/lib/elixir_script/lib/v_dom.ex new file mode 100644 index 00000000..e4d7cc87 --- /dev/null +++ b/lib/elixir_script/lib/v_dom.ex @@ -0,0 +1,80 @@ +defmodule ElixirScript.VDom do + @moduledoc """ + This defines macros for updating a virual dom tree based on patches. + This module is used in tandem with the Html module + + tree = Html.div [id: "hello"] do + Html.span do + "Hello" + end + end + + rootNode = VDom.create(tree) + :document.getElementById("main").appendChild(rootNode) + + newTree = Html.div [id: "world"] + + + patches = VDom.diff(tree, newTree) + rootNode = VDom.patch(rootNode, patches) + + """ + + + @doc """ + Creates a node from the virtual dom tree passed in. + This node is used to append to a real DOM element + + tree = Html.div [id: "hello"] do + Html.span do + "Hello" + end + end + + rootNode = VDom.create(tree) + :document.getElementById("main").appendChild(rootNode) + """ + defmacro create(element) do + quote do + Elixir.VirtualDOM.create(unquote(element)) + end + end + + + @doc """ + Takes two nodes and returns a list of differences between the two + This node is used to append to a real DOM element + + tree = Html.div [id: "hello"] + + newTree = Html.div [id: "world"] + + patches = VDom.diff(tree, newTree) + """ + defmacro diff(tree, newTree) do + quote do + Elixir.VirtualDOM.diff(unquote(tree), unquote(newTree)) + end + end + + + @doc """ + Returns a new node based on the node passed in with the passed in patches applied + + tree = Html.div [id: "hello"] + + rootNode = VDom.create(tree) + :document.getElementById("main").appendChild(rootNode) + + newTree = Html.div [id: "world"] + + + patches = VDom.diff(tree, newTree) + rootNode = VDom.patch(rootNode, patches) + """ + defmacro patch(root, patches) do + quote do + Elixir.VirtualDOM.patch(unquote(root), unquote(patches)) + end + end +end diff --git a/test/elixir_script_test.exs b/test/elixir_script_test.exs index ee4ff937..a9e236fd 100644 --- a/test/elixir_script_test.exs +++ b/test/elixir_script_test.exs @@ -132,7 +132,7 @@ defmodule ElixirScript.Test do end end - rootNode = Html.create(tree) + rootNode = VDom.create(tree) :document.getElementById("main").appendChild(rootNode) """) From 9fdd6fdf7633621a20d5200d2d13e42e8ee7cb1a Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Fri, 27 Nov 2015 11:16:26 -0600 Subject: [PATCH 061/860] updated tag list --- lib/elixir_script/lib/tags.txt | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/lib/elixir_script/lib/tags.txt b/lib/elixir_script/lib/tags.txt index a25d3355..57eefbe2 100644 --- a/lib/elixir_script/lib/tags.txt +++ b/lib/elixir_script/lib/tags.txt @@ -1,4 +1,3 @@ -doctype! a abbr acronym @@ -31,6 +30,7 @@ dd del details dfn +dialog dir div dl @@ -62,9 +62,11 @@ label legend li link +main map mark menu +menuitem meta meter nav From 7355a26b7d4deb658119e411af95e1055b0de887 Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Fri, 27 Nov 2015 11:21:28 -0600 Subject: [PATCH 062/860] Updated CHANGELOG --- CHANGELOG.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 021369c3..8c6444af 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,11 @@ * Structs and Tuples now match on their types * Can now match on JavaScript classes * Can now implement protocols using JavaScript types + * Added virtual-dom JavaScript library + * Added ElixirScript.Html module for defining a virtual-dom tree + * Added ElixirScript.VDom module for manipulating the virtual-dom tree created + using the ElixirScript.Html module + # v0.13.0 * Enhancements From 52d09c4c9e47d7c7ce993406f7d0b7112fd42e5a Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Fri, 27 Nov 2015 13:16:11 -0600 Subject: [PATCH 063/860] Removed unsupported tags --- lib/elixir_script/lib/tags.txt | 12 ------------ lib/elixir_script/translator/function.ex | 2 +- 2 files changed, 1 insertion(+), 13 deletions(-) diff --git a/lib/elixir_script/lib/tags.txt b/lib/elixir_script/lib/tags.txt index 57eefbe2..f4228193 100644 --- a/lib/elixir_script/lib/tags.txt +++ b/lib/elixir_script/lib/tags.txt @@ -1,25 +1,20 @@ a abbr -acronym address -applet area article aside audio b base -basefont bdi bdo -big blockquote body br button canvas caption -center cite code col @@ -31,7 +26,6 @@ del details dfn dialog -dir div dl dt @@ -40,11 +34,8 @@ embed fieldset figcaption figure -font footer form -frame -frameset h1 head header @@ -70,7 +61,6 @@ menuitem meta meter nav -noframes noscript object ol @@ -93,7 +83,6 @@ select small source span -strike strong style sub @@ -110,7 +99,6 @@ time title tr track -tt u ul var diff --git a/lib/elixir_script/translator/function.ex b/lib/elixir_script/translator/function.ex index ce88f2a3..91be26d6 100644 --- a/lib/elixir_script/translator/function.ex +++ b/lib/elixir_script/translator/function.ex @@ -11,7 +11,7 @@ defmodule ElixirScript.Translator.Function do :Patterns, :Kernel, :Atom, :Enum, :Integer, :JS, :List, :Range, :Tuple, :Agent, :Keyword, :BitString, :Base, :String, :Bitwise, :Collectable, :Enumerable, - :Inspect, :Map, :MapSet, :Set + :Inspect, :Map, :MapSet, :Set, :VirtualDom, :ViewAgent ] def update_alias({:__aliases__, context, [:List, :Chars]}) do From c2ae00c0ca519a5b7eec7428f5bd51c5811699fc Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Fri, 27 Nov 2015 14:03:45 -0600 Subject: [PATCH 064/860] Added View module for updating view based on state passed in --- lib/elixir_script/lib/html.ex | 34 +++++++++++---- lib/elixir_script/translator/function.ex | 3 +- priv/elixir.js | 55 +++++++++++++++++++++--- src/javascript/elixir.js | 1 + src/javascript/lib/view.js | 50 +++++++++++++++++++++ 5 files changed, 126 insertions(+), 17 deletions(-) create mode 100644 src/javascript/lib/view.js diff --git a/lib/elixir_script/lib/html.ex b/lib/elixir_script/lib/html.ex index 327b28f8..17b2e4ce 100644 --- a/lib/elixir_script/lib/html.ex +++ b/lib/elixir_script/lib/html.ex @@ -30,19 +30,20 @@ defmodule ElixirScript.Html do @doc """ Defines a macro for the html element, #{tag} """ - defmacro unquote(tag)(attributes \\ [], block \\ [do: nil]) do + defmacro unquote(tag)(attrs, do: inner) do tag = Atom.to_string(unquote(tag)) + { inner, attributes } = do_tag(inner, attrs) - inner = case Keyword.get(block, :do) do - {:__block__, [], params} -> - params - nil -> - [] - x -> - [x] + quote do + Elixir.VirtualDOM.h(unquote(tag), unquote(attributes), unquote_splicing(inner)) end + end + + defmacro unquote(tag)(attrs \\ []) do + tag = Atom.to_string(unquote(tag)) - attributes = config_to_map(attributes) + { inner, attributes } = Dict.pop(attrs, :do) + { inner, attributes } = do_tag(inner, attributes) quote do Elixir.VirtualDOM.h(unquote(tag), unquote(attributes), unquote_splicing(inner)) @@ -50,6 +51,21 @@ defmodule ElixirScript.Html do end end + defp do_tag(inner, attributes) do + inner = case inner do + {:__block__, [], params} -> + params + nil -> + [] + x -> + [x] + end + + attributes = config_to_map(attributes) + + {inner, attributes} + end + defp config_to_map(config) do config = Enum.map(config, fn({key, value}) -> if is_atom(key) do diff --git a/lib/elixir_script/translator/function.ex b/lib/elixir_script/translator/function.ex index 91be26d6..a08b38ad 100644 --- a/lib/elixir_script/translator/function.ex +++ b/lib/elixir_script/translator/function.ex @@ -5,13 +5,12 @@ defmodule ElixirScript.Translator.Function do alias ElixirScript.Translator.Utils alias ElixirScript.PatternMatching.Match alias ElixirScript.Preprocess.Variables - alias ElixirScript.Translator.Map @standard_libs [ :Patterns, :Kernel, :Atom, :Enum, :Integer, :JS, :List, :Range, :Tuple, :Agent, :Keyword, :BitString, :Base, :String, :Bitwise, :Collectable, :Enumerable, - :Inspect, :Map, :MapSet, :Set, :VirtualDom, :ViewAgent + :Inspect, :Map, :MapSet, :Set, :VirtualDom, :View ] def update_alias({:__aliases__, context, [:List, :Chars]}) do diff --git a/priv/elixir.js b/priv/elixir.js index f4e4df97..0c12d7a1 100644 --- a/priv/elixir.js +++ b/priv/elixir.js @@ -2201,7 +2201,7 @@ class SignalBinding { } } -function __update(map, key, value) { +function ___update(map, key, value) { let m = new Map(map); m.set(key, value); return m; @@ -2273,7 +2273,7 @@ class PostOffice { } add_mailbox(address = Symbol(), context = this) { - this.mailboxes = __update(this.mailboxes, address, new MailBox()); + this.mailboxes = ___update(this.mailboxes, address, new MailBox()); return address; } @@ -2711,7 +2711,7 @@ function update__emark__(map, key, fun) { return SpecialForms.map(new_map); } -function _update(map, key, initial, fun) { +function __update(map, key, initial, fun) { let new_map = Object({}, map); if (!key in map) { @@ -2747,7 +2747,7 @@ var _Map = { get, put: __put, update__emark__, - update: _update + update: __update }; function __new__() { @@ -4527,7 +4527,50 @@ let virtualDom = (function (e) { // Proposed for ES6 +const start = function (domRoot, renderFn, initialState, options = []) { + const name = Keyword.has_key__qm__(options, Kernel.SpecialForms.atom('name')) ? Keyword.get(options, Kernel.SpecialForms.atom('name')) : Symbol(); + + self.post_office.add_mailbox(name); + + const tree = renderFn.apply(this, initialState); + const rootNode = virtualDom.create(tree); + + domRoot.appendChild(rootNode); + self.post_office.send(name, Kernel.SpecialForms.tuple(rootNode, tree, renderFn)); + + return Kernel.SpecialForms.tuple(Kernel.SpecialForms.atom('ok'), name); +}; + +const stop = function (agent, timeout = 5000) { + self.post_office.remove_mailbox(agent); + return Kernel.SpecialForms.atom('ok'); +}; + +const _update = function (agent, state) { + + const current_state = self.post_office.receive(agent); + + let rootNode = Kernel.elem(current_state, 0); + let tree = Kernel.elem(current_state, 1); + let renderFn = Kernel.elem(current_state, 2); + + let newTree = renderFn.apply(this, state); + + let patches = virtualDom.diff(tree, newTree); + rootNode = virtualDom.patch(rootNode, patches); + + self.post_office.send(agent, Kernel.SpecialForms.tuple(rootNode, newTree, renderFn)); + + return Kernel.SpecialForms.atom('ok'); +}; + +var View = { + start, + stop, + update: _update +}; + self.post_office = self.post_office || new PostOffice(); -export { _Patterns as Patterns, BitString, Kernel, Atom, Enum, Integer, JS, List, Range, Tuple, Agent, Keyword, Base, _String as String, Bitwise, Enumerable, Collectable, Inspect, _Map as Map, _Set as Set, MapSet, IntegerType, FloatType, virtualDom as VirtualDOM }; -//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiIiwic291cmNlcyI6WyJlbGl4aXIuanMiXSwic291cmNlc0NvbnRlbnQiOlsidmFyIFBhdHRlcm5zID0ge1xuICAgIGdldCBkZWZhdWx0ICgpIHsgcmV0dXJuIF9QYXR0ZXJuczsgfVxufTtcblxuY2xhc3MgVHVwbGUge1xuXG4gIGNvbnN0cnVjdG9yKC4uLmFyZ3MpIHtcbiAgICB0aGlzLnZhbHVlcyA9IE9iamVjdC5mcmVlemUoYXJncyk7XG4gIH1cblxuICBnZXQoaW5kZXgpIHtcbiAgICByZXR1cm4gdGhpcy52YWx1ZXNbaW5kZXhdO1xuICB9XG5cbiAgY291bnQoKSB7XG4gICAgcmV0dXJuIHRoaXMudmFsdWVzLmxlbmd0aDtcbiAgfVxuXG4gIFtTeW1ib2wuaXRlcmF0b3JdKCkge1xuICAgIHJldHVybiB0aGlzLnZhbHVlc1tTeW1ib2wuaXRlcmF0b3JdKCk7XG4gIH1cblxuICB0b1N0cmluZygpIHtcbiAgICB2YXIgaSxcbiAgICAgICAgcyA9IFwiXCI7XG4gICAgZm9yIChpID0gMDsgaSA8IHRoaXMudmFsdWVzLmxlbmd0aDsgaSsrKSB7XG4gICAgICBpZiAocyAhPT0gXCJcIikge1xuICAgICAgICBzICs9IFwiLCBcIjtcbiAgICAgIH1cbiAgICAgIHMgKz0gdGhpcy52YWx1ZXNbaV0udG9TdHJpbmcoKTtcbiAgICB9XG5cbiAgICByZXR1cm4gXCJ7XCIgKyBzICsgXCJ9XCI7XG4gIH1cblxuICBzdGF0aWMgdG9fc3RyaW5nKHR1cGxlKSB7XG4gICAgcmV0dXJuIHR1cGxlLnRvU3RyaW5nKCk7XG4gIH1cblxuICBzdGF0aWMgZGVsZXRlX2F0KHR1cGxlLCBpbmRleCkge1xuICAgIGxldCBuZXdfbGlzdCA9IFtdO1xuXG4gICAgZm9yICh2YXIgaSA9IDA7IGkgPCB0dXBsZS5jb3VudCgpOyBpKyspIHtcbiAgICAgIGlmIChpICE9PSBpbmRleCkge1xuICAgICAgICBuZXdfbGlzdC5wdXNoKHR1cGxlLmdldChpKSk7XG4gICAgICB9XG4gICAgfVxuXG4gICAgcmV0dXJuIEtlcm5lbC5TcGVjaWFsRm9ybXMudHVwbGUuYXBwbHkobnVsbCwgbmV3X2xpc3QpO1xuICB9XG5cbiAgc3RhdGljIGR1cGxpY2F0ZShkYXRhLCBzaXplKSB7XG4gICAgbGV0IGFycmF5ID0gW107XG5cbiAgICBmb3IgKHZhciBpID0gc2l6ZSAtIDE7IGkgPj0gMDsgaS0tKSB7XG4gICAgICBhcnJheS5wdXNoKGRhdGEpO1xuICAgIH1cblxuICAgIHJldHVybiBLZXJuZWwuU3BlY2lhbEZvcm1zLnR1cGxlLmFwcGx5KG51bGwsIGFycmF5KTtcbiAgfVxuXG4gIHN0YXRpYyBpbnNlcnRfYXQodHVwbGUsIGluZGV4LCB0ZXJtKSB7XG4gICAgbGV0IG5ld190dXBsZSA9IFtdO1xuXG4gICAgZm9yICh2YXIgaSA9IDA7IGkgPD0gdHVwbGUuY291bnQoKTsgaSsrKSB7XG4gICAgICBpZiAoaSA9PT0gaW5kZXgpIHtcbiAgICAgICAgbmV3X3R1cGxlLnB1c2godGVybSk7XG4gICAgICAgIGkrKztcbiAgICAgICAgbmV3X3R1cGxlLnB1c2godHVwbGUuZ2V0KGkpKTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIG5ld190dXBsZS5wdXNoKHR1cGxlLmdldChpKSk7XG4gICAgICB9XG4gICAgfVxuXG4gICAgcmV0dXJuIEtlcm5lbC5TcGVjaWFsRm9ybXMudHVwbGUuYXBwbHkobnVsbCwgbmV3X3R1cGxlKTtcbiAgfVxuXG4gIHN0YXRpYyBmcm9tX2xpc3QobGlzdCkge1xuICAgIHJldHVybiBLZXJuZWwuU3BlY2lhbEZvcm1zLnR1cGxlLmFwcGx5KG51bGwsIGxpc3QpO1xuICB9XG5cbiAgc3RhdGljIHRvX2xpc3QodHVwbGUpIHtcbiAgICBsZXQgbmV3X2xpc3QgPSBbXTtcblxuICAgIGZvciAodmFyIGkgPSAwOyBpIDwgdHVwbGUuY291bnQoKTsgaSsrKSB7XG4gICAgICBuZXdfbGlzdC5wdXNoKHR1cGxlLmdldChpKSk7XG4gICAgfVxuXG4gICAgcmV0dXJuIEtlcm5lbC5TcGVjaWFsRm9ybXMubGlzdCguLi5uZXdfbGlzdCk7XG4gIH1cbn1cblxuLyogQGZsb3cgKi9cblxuY2xhc3MgVmFyaWFibGUge1xuXG4gIGNvbnN0cnVjdG9yKG5hbWUgPSBudWxsKSB7XG4gICAgdGhpcy5uYW1lID0gbmFtZTtcbiAgfVxufVxuXG5jbGFzcyBXaWxkY2FyZCB7XG4gIGNvbnN0cnVjdG9yKCkge31cbn1cblxuY2xhc3MgU3RhcnRzV2l0aCB7XG5cbiAgY29uc3RydWN0b3IocHJlZml4KSB7XG4gICAgdGhpcy5wcmVmaXggPSBwcmVmaXg7XG4gIH1cbn1cblxuY2xhc3MgQ2FwdHVyZSB7XG5cbiAgY29uc3RydWN0b3IodmFsdWUpIHtcbiAgICB0aGlzLnZhbHVlID0gdmFsdWU7XG4gIH1cbn1cblxuY2xhc3MgSGVhZFRhaWwge1xuICBjb25zdHJ1Y3RvcigpIHt9XG59XG5cbmNsYXNzIFR5cGUge1xuXG4gIGNvbnN0cnVjdG9yKHR5cGUsIG9ialBhdHRlcm4gPSB7fSkge1xuICAgIHRoaXMudHlwZSA9IHR5cGU7XG4gICAgdGhpcy5vYmpQYXR0ZXJuID0gb2JqUGF0dGVybjtcbiAgfVxufVxuXG5jbGFzcyBCb3VuZCB7XG5cbiAgY29uc3RydWN0b3IodmFsdWUpIHtcbiAgICB0aGlzLnZhbHVlID0gdmFsdWU7XG4gIH1cbn1cblxuZnVuY3Rpb24gdmFyaWFibGUobmFtZSA9IG51bGwpIHtcbiAgcmV0dXJuIG5ldyBWYXJpYWJsZShuYW1lKTtcbn1cblxuZnVuY3Rpb24gd2lsZGNhcmQoKSB7XG4gIHJldHVybiBuZXcgV2lsZGNhcmQoKTtcbn1cblxuZnVuY3Rpb24gc3RhcnRzV2l0aChwcmVmaXgpIHtcbiAgcmV0dXJuIG5ldyBTdGFydHNXaXRoKHByZWZpeCk7XG59XG5cbmZ1bmN0aW9uIGNhcHR1cmUodmFsdWUpIHtcbiAgcmV0dXJuIG5ldyBDYXB0dXJlKHZhbHVlKTtcbn1cblxuZnVuY3Rpb24gaGVhZFRhaWwoKSB7XG4gIHJldHVybiBuZXcgSGVhZFRhaWwoKTtcbn1cblxuZnVuY3Rpb24gdHlwZSh0eXBlLCBvYmpQYXR0ZXJuID0ge30pIHtcbiAgcmV0dXJuIG5ldyBUeXBlKHR5cGUsIG9ialBhdHRlcm4pO1xufVxuXG5mdW5jdGlvbiBib3VuZCh2YWx1ZSkge1xuICByZXR1cm4gbmV3IEJvdW5kKHZhbHVlKTtcbn1cblxuZnVuY3Rpb24gX2lzX251bWJlcih2YWx1ZSkge1xuICByZXR1cm4gdHlwZW9mIHZhbHVlID09PSAnbnVtYmVyJztcbn1cblxuZnVuY3Rpb24gaXNfc3RyaW5nKHZhbHVlKSB7XG4gIHJldHVybiB0eXBlb2YgdmFsdWUgPT09ICdzdHJpbmcnO1xufVxuXG5mdW5jdGlvbiBfaXNfdHVwbGUodmFsdWUpIHtcbiAgcmV0dXJuIHZhbHVlIGluc3RhbmNlb2YgVHVwbGU7XG59XG5cbmZ1bmN0aW9uIF9pc19ib29sZWFuKHZhbHVlKSB7XG4gIHJldHVybiB0eXBlb2YgdmFsdWUgPT09ICdib29sZWFuJztcbn1cblxuZnVuY3Rpb24gaXNfc3ltYm9sKHZhbHVlKSB7XG4gIHJldHVybiB0eXBlb2YgdmFsdWUgPT09ICdzeW1ib2wnO1xufVxuXG5mdW5jdGlvbiBpc19udWxsKHZhbHVlKSB7XG4gIHJldHVybiB2YWx1ZSA9PT0gbnVsbDtcbn1cblxuZnVuY3Rpb24gaXNfdW5kZWZpbmVkKHZhbHVlKSB7XG4gIHJldHVybiB0eXBlb2YgdmFsdWUgPT09ICd1bmRlZmluZWQnO1xufVxuXG5mdW5jdGlvbiBfaXNfZnVuY3Rpb24odmFsdWUpIHtcbiAgcmV0dXJuIE9iamVjdC5wcm90b3R5cGUudG9TdHJpbmcuY2FsbCh2YWx1ZSkgPT0gJ1tvYmplY3QgRnVuY3Rpb25dJztcbn1cblxuZnVuY3Rpb24gaXNfdmFyaWFibGUodmFsdWUpIHtcbiAgcmV0dXJuIHZhbHVlIGluc3RhbmNlb2YgVmFyaWFibGU7XG59XG5cbmZ1bmN0aW9uIGlzX3dpbGRjYXJkKHZhbHVlKSB7XG4gIHJldHVybiB2YWx1ZSBpbnN0YW5jZW9mIFdpbGRjYXJkO1xufVxuXG5mdW5jdGlvbiBpc19oZWFkVGFpbCh2YWx1ZSkge1xuICByZXR1cm4gdmFsdWUgaW5zdGFuY2VvZiBIZWFkVGFpbDtcbn1cblxuZnVuY3Rpb24gaXNfY2FwdHVyZSh2YWx1ZSkge1xuICByZXR1cm4gdmFsdWUgaW5zdGFuY2VvZiBDYXB0dXJlO1xufVxuXG5mdW5jdGlvbiBpc190eXBlKHZhbHVlKSB7XG4gIHJldHVybiB2YWx1ZSBpbnN0YW5jZW9mIFR5cGU7XG59XG5cbmZ1bmN0aW9uIGlzX3N0YXJ0c1dpdGgodmFsdWUpIHtcbiAgcmV0dXJuIHZhbHVlIGluc3RhbmNlb2YgU3RhcnRzV2l0aDtcbn1cblxuZnVuY3Rpb24gaXNfYm91bmQodmFsdWUpIHtcbiAgcmV0dXJuIHZhbHVlIGluc3RhbmNlb2YgQm91bmQ7XG59XG5cbmZ1bmN0aW9uIGlzX29iamVjdCh2YWx1ZSkge1xuICByZXR1cm4gdHlwZW9mIHZhbHVlID09PSAnb2JqZWN0Jztcbn1cblxuZnVuY3Rpb24gaXNfYXJyYXkodmFsdWUpIHtcbiAgcmV0dXJuIEFycmF5LmlzQXJyYXkodmFsdWUpO1xufVxuXG52YXIgQ2hlY2tzID0ge1xuICBpc19udW1iZXI6IF9pc19udW1iZXIsXG4gIGlzX3N0cmluZyxcbiAgaXNfYm9vbGVhbjogX2lzX2Jvb2xlYW4sXG4gIGlzX3N5bWJvbCxcbiAgaXNfbnVsbCxcbiAgaXNfdW5kZWZpbmVkLFxuICBpc19mdW5jdGlvbjogX2lzX2Z1bmN0aW9uLFxuICBpc192YXJpYWJsZSxcbiAgaXNfd2lsZGNhcmQsXG4gIGlzX2hlYWRUYWlsLFxuICBpc19jYXB0dXJlLFxuICBpc190eXBlLFxuICBpc19zdGFydHNXaXRoLFxuICBpc19ib3VuZCxcbiAgaXNfb2JqZWN0LFxuICBpc19hcnJheSxcbiAgaXNfdHVwbGU6IF9pc190dXBsZVxufTtcblxuZnVuY3Rpb24gcmVzb2x2ZVR1cGxlKHBhdHRlcm4pIHtcbiAgbGV0IG1hdGNoZXMgPSBbXTtcblxuICBmb3IgKGxldCBlbGVtIG9mIHBhdHRlcm4pIHtcbiAgICBtYXRjaGVzLnB1c2goYnVpbGRNYXRjaChlbGVtKSk7XG4gIH1cblxuICByZXR1cm4gZnVuY3Rpb24gKHZhbHVlLCBhcmdzKSB7XG4gICAgaWYgKCFDaGVja3MuaXNfdHVwbGUodmFsdWUpIHx8IHZhbHVlLmNvdW50KCkgIT0gcGF0dGVybi5jb3VudCgpKSB7XG4gICAgICByZXR1cm4gZmFsc2U7XG4gICAgfVxuXG4gICAgcmV0dXJuIHZhbHVlLnZhbHVlcy5ldmVyeShmdW5jdGlvbiAodiwgaSkge1xuICAgICAgcmV0dXJuIG1hdGNoZXNbaV0odmFsdWUuZ2V0KGkpLCBhcmdzKTtcbiAgICB9KTtcbiAgfTtcbn1cblxuZnVuY3Rpb24gcmVzb2x2ZVN5bWJvbChwYXR0ZXJuKSB7XG4gIHJldHVybiBmdW5jdGlvbiAodmFsdWUpIHtcbiAgICByZXR1cm4gQ2hlY2tzLmlzX3N5bWJvbCh2YWx1ZSkgJiYgdmFsdWUgPT09IHBhdHRlcm47XG4gIH07XG59XG5cbmZ1bmN0aW9uIHJlc29sdmVTdHJpbmcocGF0dGVybikge1xuICByZXR1cm4gZnVuY3Rpb24gKHZhbHVlKSB7XG4gICAgcmV0dXJuIENoZWNrcy5pc19zdHJpbmcodmFsdWUpICYmIHZhbHVlID09PSBwYXR0ZXJuO1xuICB9O1xufVxuXG5mdW5jdGlvbiByZXNvbHZlTnVtYmVyKHBhdHRlcm4pIHtcbiAgcmV0dXJuIGZ1bmN0aW9uICh2YWx1ZSkge1xuICAgIHJldHVybiBDaGVja3MuaXNfbnVtYmVyKHZhbHVlKSAmJiB2YWx1ZSA9PT0gcGF0dGVybjtcbiAgfTtcbn1cblxuZnVuY3Rpb24gcmVzb2x2ZUJvb2xlYW4ocGF0dGVybikge1xuICByZXR1cm4gZnVuY3Rpb24gKHZhbHVlKSB7XG4gICAgcmV0dXJuIENoZWNrcy5pc19ib29sZWFuKHZhbHVlKSAmJiB2YWx1ZSA9PT0gcGF0dGVybjtcbiAgfTtcbn1cblxuZnVuY3Rpb24gcmVzb2x2ZUZ1bmN0aW9uKHBhdHRlcm4pIHtcbiAgcmV0dXJuIGZ1bmN0aW9uICh2YWx1ZSkge1xuICAgIHJldHVybiBDaGVja3MuaXNfZnVuY3Rpb24odmFsdWUpICYmIHZhbHVlID09PSBwYXR0ZXJuO1xuICB9O1xufVxuXG5mdW5jdGlvbiByZXNvbHZlTnVsbChwYXR0ZXJuKSB7XG4gIHJldHVybiBmdW5jdGlvbiAodmFsdWUpIHtcbiAgICByZXR1cm4gQ2hlY2tzLmlzX251bGwodmFsdWUpO1xuICB9O1xufVxuXG5mdW5jdGlvbiByZXNvbHZlQm91bmQocGF0dGVybikge1xuICByZXR1cm4gZnVuY3Rpb24gKHZhbHVlLCBhcmdzKSB7XG4gICAgaWYgKHR5cGVvZiB2YWx1ZSA9PT0gdHlwZW9mIHBhdHRlcm4udmFsdWUgJiYgdmFsdWUgPT09IHBhdHRlcm4udmFsdWUpIHtcbiAgICAgIGFyZ3MucHVzaCh2YWx1ZSk7XG4gICAgICByZXR1cm4gdHJ1ZTtcbiAgICB9XG5cbiAgICByZXR1cm4gZmFsc2U7XG4gIH07XG59XG5cbmZ1bmN0aW9uIHJlc29sdmVXaWxkY2FyZCgpIHtcbiAgcmV0dXJuIGZ1bmN0aW9uICgpIHtcbiAgICByZXR1cm4gdHJ1ZTtcbiAgfTtcbn1cblxuZnVuY3Rpb24gcmVzb2x2ZVZhcmlhYmxlKCkge1xuICByZXR1cm4gZnVuY3Rpb24gKHZhbHVlLCBhcmdzKSB7XG4gICAgYXJncy5wdXNoKHZhbHVlKTtcbiAgICByZXR1cm4gdHJ1ZTtcbiAgfTtcbn1cblxuZnVuY3Rpb24gcmVzb2x2ZUhlYWRUYWlsKCkge1xuICByZXR1cm4gZnVuY3Rpb24gKHZhbHVlLCBhcmdzKSB7XG4gICAgaWYgKCFDaGVja3MuaXNfYXJyYXkodmFsdWUpIHx8IHZhbHVlLmxlbmd0aCA8IDIpIHtcbiAgICAgIHJldHVybiBmYWxzZTtcbiAgICB9XG5cbiAgICBjb25zdCBoZWFkID0gdmFsdWVbMF07XG4gICAgY29uc3QgdGFpbCA9IHZhbHVlLnNsaWNlKDEpO1xuXG4gICAgYXJncy5wdXNoKGhlYWQpO1xuICAgIGFyZ3MucHVzaCh0YWlsKTtcblxuICAgIHJldHVybiB0cnVlO1xuICB9O1xufVxuXG5mdW5jdGlvbiByZXNvbHZlQ2FwdHVyZShwYXR0ZXJuKSB7XG4gIGNvbnN0IG1hdGNoZXMgPSBidWlsZE1hdGNoKHBhdHRlcm4udmFsdWUpO1xuXG4gIHJldHVybiBmdW5jdGlvbiAodmFsdWUsIGFyZ3MpIHtcbiAgICBpZiAobWF0Y2hlcyh2YWx1ZSwgYXJncykpIHtcbiAgICAgIGFyZ3MucHVzaCh2YWx1ZSk7XG4gICAgICByZXR1cm4gdHJ1ZTtcbiAgICB9XG5cbiAgICByZXR1cm4gZmFsc2U7XG4gIH07XG59XG5cbmZ1bmN0aW9uIHJlc29sdmVTdGFydHNXaXRoKHBhdHRlcm4pIHtcbiAgY29uc3QgcHJlZml4ID0gcGF0dGVybi5wcmVmaXg7XG5cbiAgcmV0dXJuIGZ1bmN0aW9uICh2YWx1ZSwgYXJncykge1xuICAgIGlmIChDaGVja3MuaXNfc3RyaW5nKHZhbHVlKSAmJiB2YWx1ZS5zdGFydHNXaXRoKHByZWZpeCkpIHtcbiAgICAgIGFyZ3MucHVzaCh2YWx1ZS5zdWJzdHJpbmcocHJlZml4Lmxlbmd0aCkpO1xuICAgICAgcmV0dXJuIHRydWU7XG4gICAgfVxuXG4gICAgcmV0dXJuIGZhbHNlO1xuICB9O1xufVxuXG5mdW5jdGlvbiByZXNvbHZlVHlwZShwYXR0ZXJuKSB7XG4gIHJldHVybiBmdW5jdGlvbiAodmFsdWUsIGFyZ3MpIHtcbiAgICBpZiAodmFsdWUgaW5zdGFuY2VvZiBwYXR0ZXJuLnR5cGUpIHtcbiAgICAgIGNvbnN0IG1hdGNoZXMgPSBidWlsZE1hdGNoKHBhdHRlcm4ub2JqUGF0dGVybik7XG4gICAgICByZXR1cm4gbWF0Y2hlcyh2YWx1ZSwgYXJncykgJiYgYXJncy5wdXNoKHZhbHVlKSA+IDA7XG4gICAgfVxuXG4gICAgcmV0dXJuIGZhbHNlO1xuICB9O1xufVxuXG5mdW5jdGlvbiByZXNvbHZlQXJyYXkocGF0dGVybikge1xuICBjb25zdCBtYXRjaGVzID0gcGF0dGVybi5tYXAoeCA9PiBidWlsZE1hdGNoKHgpKTtcblxuICByZXR1cm4gZnVuY3Rpb24gKHZhbHVlLCBhcmdzKSB7XG4gICAgaWYgKCFDaGVja3MuaXNfYXJyYXkodmFsdWUpIHx8IHZhbHVlLmxlbmd0aCAhPSBwYXR0ZXJuLmxlbmd0aCkge1xuICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH1cblxuICAgIHJldHVybiB2YWx1ZS5ldmVyeShmdW5jdGlvbiAodiwgaSkge1xuICAgICAgcmV0dXJuIG1hdGNoZXNbaV0odmFsdWVbaV0sIGFyZ3MpO1xuICAgIH0pO1xuICB9O1xufVxuXG5mdW5jdGlvbiByZXNvbHZlT2JqZWN0KHBhdHRlcm4pIHtcbiAgbGV0IG1hdGNoZXMgPSB7fTtcblxuICBmb3IgKGxldCBrZXkgb2YgT2JqZWN0LmtleXMocGF0dGVybikpIHtcbiAgICBtYXRjaGVzW2tleV0gPSBidWlsZE1hdGNoKHBhdHRlcm5ba2V5XSk7XG4gIH1cblxuICByZXR1cm4gZnVuY3Rpb24gKHZhbHVlLCBhcmdzKSB7XG4gICAgaWYgKCFDaGVja3MuaXNfb2JqZWN0KHZhbHVlKSB8fCBwYXR0ZXJuLmxlbmd0aCA+IHZhbHVlLmxlbmd0aCkge1xuICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH1cblxuICAgIGZvciAobGV0IGtleSBvZiBPYmplY3Qua2V5cyhwYXR0ZXJuKSkge1xuICAgICAgaWYgKCEoa2V5IGluIHZhbHVlKSB8fCAhbWF0Y2hlc1trZXldKHZhbHVlW2tleV0sIGFyZ3MpKSB7XG4gICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICByZXR1cm4gdHJ1ZTtcbiAgfTtcbn1cblxuZnVuY3Rpb24gcmVzb2x2ZU5vTWF0Y2goKSB7XG4gIHJldHVybiBmdW5jdGlvbiAoKSB7XG4gICAgcmV0dXJuIGZhbHNlO1xuICB9O1xufVxuXG52YXIgUmVzb2x2ZXJzID0ge1xuICByZXNvbHZlQm91bmQsXG4gIHJlc29sdmVXaWxkY2FyZCxcbiAgcmVzb2x2ZVZhcmlhYmxlLFxuICByZXNvbHZlSGVhZFRhaWwsXG4gIHJlc29sdmVDYXB0dXJlLFxuICByZXNvbHZlU3RhcnRzV2l0aCxcbiAgcmVzb2x2ZVR5cGUsXG4gIHJlc29sdmVBcnJheSxcbiAgcmVzb2x2ZU9iamVjdCxcbiAgcmVzb2x2ZU5vTWF0Y2gsXG4gIHJlc29sdmVTeW1ib2wsXG4gIHJlc29sdmVTdHJpbmcsXG4gIHJlc29sdmVOdW1iZXIsXG4gIHJlc29sdmVCb29sZWFuLFxuICByZXNvbHZlRnVuY3Rpb24sXG4gIHJlc29sdmVOdWxsLFxuICByZXNvbHZlVHVwbGVcbn07XG5cbmZ1bmN0aW9uIGJ1aWxkTWF0Y2gocGF0dGVybikge1xuXG4gIGlmIChDaGVja3MuaXNfdHVwbGUocGF0dGVybikpIHtcbiAgICByZXR1cm4gUmVzb2x2ZXJzLnJlc29sdmVUdXBsZShwYXR0ZXJuKTtcbiAgfVxuXG4gIGlmIChDaGVja3MuaXNfdmFyaWFibGUocGF0dGVybikpIHtcbiAgICByZXR1cm4gUmVzb2x2ZXJzLnJlc29sdmVWYXJpYWJsZShwYXR0ZXJuKTtcbiAgfVxuXG4gIGlmIChDaGVja3MuaXNfd2lsZGNhcmQocGF0dGVybikpIHtcbiAgICByZXR1cm4gUmVzb2x2ZXJzLnJlc29sdmVXaWxkY2FyZChwYXR0ZXJuKTtcbiAgfVxuXG4gIGlmIChDaGVja3MuaXNfdW5kZWZpbmVkKHBhdHRlcm4pKSB7XG4gICAgcmV0dXJuIFJlc29sdmVycy5yZXNvbHZlV2lsZGNhcmQocGF0dGVybik7XG4gIH1cblxuICBpZiAoQ2hlY2tzLmlzX2hlYWRUYWlsKHBhdHRlcm4pKSB7XG4gICAgcmV0dXJuIFJlc29sdmVycy5yZXNvbHZlSGVhZFRhaWwocGF0dGVybik7XG4gIH1cblxuICBpZiAoQ2hlY2tzLmlzX3N0YXJ0c1dpdGgocGF0dGVybikpIHtcbiAgICByZXR1cm4gUmVzb2x2ZXJzLnJlc29sdmVTdGFydHNXaXRoKHBhdHRlcm4pO1xuICB9XG5cbiAgaWYgKENoZWNrcy5pc19jYXB0dXJlKHBhdHRlcm4pKSB7XG4gICAgcmV0dXJuIFJlc29sdmVycy5yZXNvbHZlQ2FwdHVyZShwYXR0ZXJuKTtcbiAgfVxuXG4gIGlmIChDaGVja3MuaXNfYm91bmQocGF0dGVybikpIHtcbiAgICByZXR1cm4gUmVzb2x2ZXJzLnJlc29sdmVCb3VuZChwYXR0ZXJuKTtcbiAgfVxuXG4gIGlmIChDaGVja3MuaXNfdHlwZShwYXR0ZXJuKSkge1xuICAgIHJldHVybiBSZXNvbHZlcnMucmVzb2x2ZVR5cGUocGF0dGVybik7XG4gIH1cblxuICBpZiAoQ2hlY2tzLmlzX2FycmF5KHBhdHRlcm4pKSB7XG4gICAgcmV0dXJuIFJlc29sdmVycy5yZXNvbHZlQXJyYXkocGF0dGVybik7XG4gIH1cblxuICBpZiAoQ2hlY2tzLmlzX251bWJlcihwYXR0ZXJuKSkge1xuICAgIHJldHVybiBSZXNvbHZlcnMucmVzb2x2ZU51bWJlcihwYXR0ZXJuKTtcbiAgfVxuXG4gIGlmIChDaGVja3MuaXNfc3RyaW5nKHBhdHRlcm4pKSB7XG4gICAgcmV0dXJuIFJlc29sdmVycy5yZXNvbHZlU3RyaW5nKHBhdHRlcm4pO1xuICB9XG5cbiAgaWYgKENoZWNrcy5pc19ib29sZWFuKHBhdHRlcm4pKSB7XG4gICAgcmV0dXJuIFJlc29sdmVycy5yZXNvbHZlQm9vbGVhbihwYXR0ZXJuKTtcbiAgfVxuXG4gIGlmIChDaGVja3MuaXNfc3ltYm9sKHBhdHRlcm4pKSB7XG4gICAgcmV0dXJuIFJlc29sdmVycy5yZXNvbHZlU3ltYm9sKHBhdHRlcm4pO1xuICB9XG5cbiAgaWYgKENoZWNrcy5pc19udWxsKHBhdHRlcm4pKSB7XG4gICAgcmV0dXJuIFJlc29sdmVycy5yZXNvbHZlTnVsbChwYXR0ZXJuKTtcbiAgfVxuXG4gIGlmIChDaGVja3MuaXNfb2JqZWN0KHBhdHRlcm4pKSB7XG4gICAgcmV0dXJuIFJlc29sdmVycy5yZXNvbHZlT2JqZWN0KHBhdHRlcm4pO1xuICB9XG5cbiAgcmV0dXJuIFJlc29sdmVycy5yZXNvbHZlTm9NYXRjaCgpO1xufVxuXG5jbGFzcyBNYXRjaEVycm9yIGV4dGVuZHMgRXJyb3Ige1xuICBjb25zdHJ1Y3RvcihhcmcpIHtcbiAgICBzdXBlcigpO1xuXG4gICAgaWYgKHR5cGVvZiBhcmcgPT09ICdzeW1ib2wnKSB7XG4gICAgICB0aGlzLm1lc3NhZ2UgPSAnTm8gbWF0Y2ggZm9yOiAnICsgYXJnLnRvU3RyaW5nKCk7XG4gICAgfSBlbHNlIGlmIChBcnJheS5pc0FycmF5KGFyZykpIHtcbiAgICAgIGxldCBtYXBwZWRWYWx1ZXMgPSBhcmcubWFwKHggPT4geC50b1N0cmluZygpKTtcbiAgICAgIHRoaXMubWVzc2FnZSA9ICdObyBtYXRjaCBmb3I6ICcgKyBtYXBwZWRWYWx1ZXM7XG4gICAgfSBlbHNlIHtcbiAgICAgIHRoaXMubWVzc2FnZSA9ICdObyBtYXRjaCBmb3I6ICcgKyBhcmc7XG4gICAgfVxuXG4gICAgdGhpcy5zdGFjayA9IG5ldyBFcnJvcigpLnN0YWNrO1xuICAgIHRoaXMubmFtZSA9IHRoaXMuY29uc3RydWN0b3IubmFtZTtcbiAgfVxufVxuXG5jbGFzcyBDYXNlIHtcblxuICBjb25zdHJ1Y3RvcihwYXR0ZXJuLCBmbiwgZ3VhcmQgPSAoKSA9PiB0cnVlKSB7XG4gICAgdGhpcy5wYXR0ZXJuID0gYnVpbGRNYXRjaChwYXR0ZXJuKTtcbiAgICB0aGlzLmZuID0gZm47XG4gICAgdGhpcy5ndWFyZCA9IGd1YXJkO1xuICB9XG59XG5cbmZ1bmN0aW9uIG1ha2VfY2FzZShwYXR0ZXJuLCBmbiwgZ3VhcmQgPSAoKSA9PiB0cnVlKSB7XG4gIHJldHVybiBuZXcgQ2FzZShwYXR0ZXJuLCBmbiwgZ3VhcmQpO1xufVxuXG5mdW5jdGlvbiBkZWZtYXRjaCguLi5jYXNlcykge1xuICByZXR1cm4gZnVuY3Rpb24gKC4uLmFyZ3MpIHtcbiAgICBmb3IgKGxldCBwcm9jZXNzZWRDYXNlIG9mIGNhc2VzKSB7XG4gICAgICBsZXQgcmVzdWx0ID0gW107XG4gICAgICBpZiAocHJvY2Vzc2VkQ2FzZS5wYXR0ZXJuKGFyZ3MsIHJlc3VsdCkgJiYgcHJvY2Vzc2VkQ2FzZS5ndWFyZC5hcHBseSh0aGlzLCByZXN1bHQpKSB7XG4gICAgICAgIHJldHVybiBwcm9jZXNzZWRDYXNlLmZuLmFwcGx5KHRoaXMsIHJlc3VsdCk7XG4gICAgICB9XG4gICAgfVxuXG4gICAgdGhyb3cgbmV3IE1hdGNoRXJyb3IoYXJncyk7XG4gIH07XG59XG5cbmZ1bmN0aW9uIG1hdGNoKHBhdHRlcm4sIGV4cHIsIGd1YXJkID0gKCkgPT4gdHJ1ZSkge1xuICBsZXQgcmVzdWx0ID0gW107XG4gIGxldCBwcm9jZXNzZWRQYXR0ZXJuID0gYnVpbGRNYXRjaChwYXR0ZXJuKTtcbiAgaWYgKHByb2Nlc3NlZFBhdHRlcm4oZXhwciwgcmVzdWx0KSAmJiBndWFyZC5hcHBseSh0aGlzLCByZXN1bHQpKSB7XG4gICAgcmV0dXJuIHJlc3VsdDtcbiAgfSBlbHNlIHtcbiAgICB0aHJvdyBuZXcgTWF0Y2hFcnJvcihleHByKTtcbiAgfVxufVxuXG5mdW5jdGlvbiBtYXRjaF9ub190aHJvdyhwYXR0ZXJuLCBleHByLCBndWFyZCA9ICgpID0+IHRydWUpIHtcbiAgdHJ5IHtcbiAgICByZXR1cm4gbWF0Y2gocGF0dGVybiwgZXhwciwgZ3VhcmQpO1xuICB9IGNhdGNoIChlKSB7XG4gICAgaWYgKGUgaW5zdGFuY2VvZiBNYXRjaEVycm9yKSB7XG4gICAgICByZXR1cm4gbnVsbDtcbiAgICB9XG5cbiAgICB0aHJvdyBlO1xuICB9XG59XG5cbmZ1bmN0aW9uIHBhdHRlcm5NYXAoY29sbGVjdGlvbiwgcGF0dGVybiwgZnVuLCBndWFyZCA9ICgpID0+IHRydWUpIHtcbiAgbGV0IHJldCA9IFtdO1xuXG4gIGZvciAobGV0IGVsZW0gb2YgY29sbGVjdGlvbikge1xuICAgIHRyeSB7XG4gICAgICBsZXQgcmVzdWx0ID0gZnVuLmFwcGx5KHRoaXMsIG1hdGNoKHBhdHRlcm4sIGVsZW0sIGd1YXJkKSk7XG4gICAgICByZXQgPSByZXQuY29uY2F0KHJlc3VsdCk7XG4gICAgfSBjYXRjaCAoZSkge1xuICAgICAgaWYgKCEoZSBpbnN0YW5jZW9mIE1hdGNoRXJyb3IpKSB7XG4gICAgICAgIHRocm93IGU7XG4gICAgICB9XG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIHJldDtcbn1cblxudmFyIF9QYXR0ZXJucyA9IHtcbiAgZGVmbWF0Y2gsIG1hdGNoLCBNYXRjaEVycm9yLCBtYXRjaF9ub190aHJvdywgcGF0dGVybk1hcCxcbiAgdmFyaWFibGUsIHdpbGRjYXJkLCBzdGFydHNXaXRoLFxuICBjYXB0dXJlLCBoZWFkVGFpbCwgdHlwZSwgYm91bmQsIENhc2UsIG1ha2VfY2FzZVxufTtcblxuY2xhc3MgQml0U3RyaW5nIHtcbiAgY29uc3RydWN0b3IoLi4uYXJncykge1xuICAgIHRoaXMucmF3X3ZhbHVlID0gZnVuY3Rpb24gKCkge1xuICAgICAgcmV0dXJuIE9iamVjdC5mcmVlemUoYXJncyk7XG4gICAgfTtcblxuICAgIHRoaXMudmFsdWUgPSBPYmplY3QuZnJlZXplKHRoaXMucHJvY2VzcyhhcmdzKSk7XG4gIH1cblxuICBnZXQoaW5kZXgpIHtcbiAgICByZXR1cm4gdGhpcy52YWx1ZVtpbmRleF07XG4gIH1cblxuICBjb3VudCgpIHtcbiAgICByZXR1cm4gdGhpcy52YWx1ZS5sZW5ndGg7XG4gIH1cblxuICBbU3ltYm9sLml0ZXJhdG9yXSgpIHtcbiAgICByZXR1cm4gdGhpcy52YWx1ZVtTeW1ib2wuaXRlcmF0b3JdKCk7XG4gIH1cblxuICB0b1N0cmluZygpIHtcbiAgICB2YXIgaSxcbiAgICAgICAgcyA9IFwiXCI7XG4gICAgZm9yIChpID0gMDsgaSA8IHRoaXMuY291bnQoKTsgaSsrKSB7XG4gICAgICBpZiAocyAhPT0gXCJcIikge1xuICAgICAgICBzICs9IFwiLCBcIjtcbiAgICAgIH1cbiAgICAgIHMgKz0gdGhpc1tpXS50b1N0cmluZygpO1xuICAgIH1cblxuICAgIHJldHVybiBcIjw8XCIgKyBzICsgXCI+PlwiO1xuICB9XG5cbiAgcHJvY2VzcygpIHtcbiAgICBsZXQgcHJvY2Vzc2VkX3ZhbHVlcyA9IFtdO1xuXG4gICAgdmFyIGk7XG4gICAgZm9yIChpID0gMDsgaSA8IHRoaXMucmF3X3ZhbHVlKCkubGVuZ3RoOyBpKyspIHtcbiAgICAgIGxldCBwcm9jZXNzZWRfdmFsdWUgPSB0aGlzW1wicHJvY2Vzc19cIiArIHRoaXMucmF3X3ZhbHVlKClbaV0udHlwZV0odGhpcy5yYXdfdmFsdWUoKVtpXSk7XG5cbiAgICAgIGZvciAobGV0IGF0dHIgb2YgdGhpcy5yYXdfdmFsdWUoKVtpXS5hdHRyaWJ1dGVzKSB7XG4gICAgICAgIHByb2Nlc3NlZF92YWx1ZSA9IHRoaXNbXCJwcm9jZXNzX1wiICsgYXR0cl0ocHJvY2Vzc2VkX3ZhbHVlKTtcbiAgICAgIH1cblxuICAgICAgcHJvY2Vzc2VkX3ZhbHVlcyA9IHByb2Nlc3NlZF92YWx1ZXMuY29uY2F0KHByb2Nlc3NlZF92YWx1ZSk7XG4gICAgfVxuXG4gICAgcmV0dXJuIHByb2Nlc3NlZF92YWx1ZXM7XG4gIH1cblxuICBwcm9jZXNzX2ludGVnZXIodmFsdWUpIHtcbiAgICByZXR1cm4gdmFsdWUudmFsdWU7XG4gIH1cblxuICBwcm9jZXNzX2Zsb2F0KHZhbHVlKSB7XG4gICAgaWYgKHZhbHVlLnNpemUgPT09IDY0KSB7XG4gICAgICByZXR1cm4gQml0U3RyaW5nLmZsb2F0NjRUb0J5dGVzKHZhbHVlLnZhbHVlKTtcbiAgICB9IGVsc2UgaWYgKHZhbHVlLnNpemUgPT09IDMyKSB7XG4gICAgICByZXR1cm4gQml0U3RyaW5nLmZsb2F0MzJUb0J5dGVzKHZhbHVlLnZhbHVlKTtcbiAgICB9XG5cbiAgICB0aHJvdyBuZXcgRXJyb3IoXCJJbnZhbGlkIHNpemUgZm9yIGZsb2F0XCIpO1xuICB9XG5cbiAgcHJvY2Vzc19iaXRzdHJpbmcodmFsdWUpIHtcbiAgICByZXR1cm4gdmFsdWUudmFsdWUudmFsdWU7XG4gIH1cblxuICBwcm9jZXNzX2JpbmFyeSh2YWx1ZSkge1xuICAgIHJldHVybiBCaXRTdHJpbmcudG9VVEY4QXJyYXkodmFsdWUudmFsdWUpO1xuICB9XG5cbiAgcHJvY2Vzc191dGY4KHZhbHVlKSB7XG4gICAgcmV0dXJuIEJpdFN0cmluZy50b1VURjhBcnJheSh2YWx1ZS52YWx1ZSk7XG4gIH1cblxuICBwcm9jZXNzX3V0ZjE2KHZhbHVlKSB7XG4gICAgcmV0dXJuIEJpdFN0cmluZy50b1VURjE2QXJyYXkodmFsdWUudmFsdWUpO1xuICB9XG5cbiAgcHJvY2Vzc191dGYzMih2YWx1ZSkge1xuICAgIHJldHVybiBCaXRTdHJpbmcudG9VVEYzMkFycmF5KHZhbHVlLnZhbHVlKTtcbiAgfVxuXG4gIHByb2Nlc3Nfc2lnbmVkKHZhbHVlKSB7XG4gICAgcmV0dXJuIG5ldyBVaW50OEFycmF5KFt2YWx1ZV0pWzBdO1xuICB9XG5cbiAgcHJvY2Vzc191bnNpZ25lZCh2YWx1ZSkge1xuICAgIHJldHVybiB2YWx1ZTtcbiAgfVxuXG4gIHByb2Nlc3NfbmF0aXZlKHZhbHVlKSB7XG4gICAgcmV0dXJuIHZhbHVlO1xuICB9XG5cbiAgcHJvY2Vzc19iaWcodmFsdWUpIHtcbiAgICByZXR1cm4gdmFsdWU7XG4gIH1cblxuICBwcm9jZXNzX2xpdHRsZSh2YWx1ZSkge1xuICAgIHJldHVybiB2YWx1ZS5yZXZlcnNlKCk7XG4gIH1cblxuICBwcm9jZXNzX3NpemUodmFsdWUpIHtcbiAgICByZXR1cm4gdmFsdWU7XG4gIH1cblxuICBwcm9jZXNzX3VuaXQodmFsdWUpIHtcbiAgICByZXR1cm4gdmFsdWU7XG4gIH1cblxuICBzdGF0aWMgaW50ZWdlcih2YWx1ZSkge1xuICAgIHJldHVybiBCaXRTdHJpbmcud3JhcCh2YWx1ZSwgeyBcInR5cGVcIjogXCJpbnRlZ2VyXCIsIFwidW5pdFwiOiAxLCBcInNpemVcIjogOCB9KTtcbiAgfVxuXG4gIHN0YXRpYyBmbG9hdCh2YWx1ZSkge1xuICAgIHJldHVybiBCaXRTdHJpbmcud3JhcCh2YWx1ZSwgeyBcInR5cGVcIjogXCJmbG9hdFwiLCBcInVuaXRcIjogMSwgXCJzaXplXCI6IDY0IH0pO1xuICB9XG5cbiAgc3RhdGljIGJpdHN0cmluZyh2YWx1ZSkge1xuICAgIHJldHVybiBCaXRTdHJpbmcud3JhcCh2YWx1ZSwgeyBcInR5cGVcIjogXCJiaXRzdHJpbmdcIiwgXCJ1bml0XCI6IDEsIFwic2l6ZVwiOiB2YWx1ZS5sZW5ndGggfSk7XG4gIH1cblxuICBzdGF0aWMgYml0cyh2YWx1ZSkge1xuICAgIHJldHVybiBCaXRTdHJpbmcuYml0c3RyaW5nKHZhbHVlKTtcbiAgfVxuXG4gIHN0YXRpYyBiaW5hcnkodmFsdWUpIHtcbiAgICByZXR1cm4gQml0U3RyaW5nLndyYXAodmFsdWUsIHsgXCJ0eXBlXCI6IFwiYmluYXJ5XCIsIFwidW5pdFwiOiA4LCBcInNpemVcIjogdmFsdWUubGVuZ3RoIH0pO1xuICB9XG5cbiAgc3RhdGljIGJ5dGVzKHZhbHVlKSB7XG4gICAgcmV0dXJuIEJpdFN0cmluZy5iaW5hcnkodmFsdWUpO1xuICB9XG5cbiAgc3RhdGljIHV0ZjgodmFsdWUpIHtcbiAgICByZXR1cm4gQml0U3RyaW5nLndyYXAodmFsdWUsIHsgXCJ0eXBlXCI6IFwidXRmOFwiIH0pO1xuICB9XG5cbiAgc3RhdGljIHV0ZjE2KHZhbHVlKSB7XG4gICAgcmV0dXJuIEJpdFN0cmluZy53cmFwKHZhbHVlLCB7IFwidHlwZVwiOiBcInV0ZjE2XCIgfSk7XG4gIH1cblxuICBzdGF0aWMgdXRmMzIodmFsdWUpIHtcbiAgICByZXR1cm4gQml0U3RyaW5nLndyYXAodmFsdWUsIHsgXCJ0eXBlXCI6IFwidXRmMzJcIiB9KTtcbiAgfVxuXG4gIHN0YXRpYyBzaWduZWQodmFsdWUpIHtcbiAgICByZXR1cm4gQml0U3RyaW5nLndyYXAodmFsdWUsIHt9LCBcInNpZ25lZFwiKTtcbiAgfVxuXG4gIHN0YXRpYyB1bnNpZ25lZCh2YWx1ZSkge1xuICAgIHJldHVybiBCaXRTdHJpbmcud3JhcCh2YWx1ZSwge30sIFwidW5zaWduZWRcIik7XG4gIH1cblxuICBzdGF0aWMgbmF0aXZlKHZhbHVlKSB7XG4gICAgcmV0dXJuIEJpdFN0cmluZy53cmFwKHZhbHVlLCB7fSwgXCJuYXRpdmVcIik7XG4gIH1cblxuICBzdGF0aWMgYmlnKHZhbHVlKSB7XG4gICAgcmV0dXJuIEJpdFN0cmluZy53cmFwKHZhbHVlLCB7fSwgXCJiaWdcIik7XG4gIH1cblxuICBzdGF0aWMgbGl0dGxlKHZhbHVlKSB7XG4gICAgcmV0dXJuIEJpdFN0cmluZy53cmFwKHZhbHVlLCB7fSwgXCJsaXR0bGVcIik7XG4gIH1cblxuICBzdGF0aWMgc2l6ZSh2YWx1ZSwgY291bnQpIHtcbiAgICByZXR1cm4gQml0U3RyaW5nLndyYXAodmFsdWUsIHsgXCJzaXplXCI6IGNvdW50IH0pO1xuICB9XG5cbiAgc3RhdGljIHVuaXQodmFsdWUsIGNvdW50KSB7XG4gICAgcmV0dXJuIEJpdFN0cmluZy53cmFwKHZhbHVlLCB7IFwidW5pdFwiOiBjb3VudCB9KTtcbiAgfVxuXG4gIHN0YXRpYyB3cmFwKHZhbHVlLCBvcHQsIG5ld19hdHRyaWJ1dGUgPSBudWxsKSB7XG4gICAgbGV0IHRoZV92YWx1ZSA9IHZhbHVlO1xuXG4gICAgaWYgKCEodmFsdWUgaW5zdGFuY2VvZiBPYmplY3QpKSB7XG4gICAgICB0aGVfdmFsdWUgPSB7IFwidmFsdWVcIjogdmFsdWUsIFwiYXR0cmlidXRlc1wiOiBbXSB9O1xuICAgIH1cblxuICAgIHRoZV92YWx1ZSA9IE9iamVjdC5hc3NpZ24odGhlX3ZhbHVlLCBvcHQpO1xuXG4gICAgaWYgKG5ld19hdHRyaWJ1dGUpIHtcbiAgICAgIHRoZV92YWx1ZS5hdHRyaWJ1dGVzLnB1c2gobmV3X2F0dHJpYnV0ZSk7XG4gICAgfVxuXG4gICAgcmV0dXJuIHRoZV92YWx1ZTtcbiAgfVxuXG4gIHN0YXRpYyB0b1VURjhBcnJheShzdHIpIHtcbiAgICB2YXIgdXRmOCA9IFtdO1xuICAgIGZvciAodmFyIGkgPSAwOyBpIDwgc3RyLmxlbmd0aDsgaSsrKSB7XG4gICAgICB2YXIgY2hhcmNvZGUgPSBzdHIuY2hhckNvZGVBdChpKTtcbiAgICAgIGlmIChjaGFyY29kZSA8IDEyOCkge1xuICAgICAgICB1dGY4LnB1c2goY2hhcmNvZGUpO1xuICAgICAgfSBlbHNlIGlmIChjaGFyY29kZSA8IDIwNDgpIHtcbiAgICAgICAgdXRmOC5wdXNoKDE5MiB8IGNoYXJjb2RlID4+IDYsIDEyOCB8IGNoYXJjb2RlICYgNjMpO1xuICAgICAgfSBlbHNlIGlmIChjaGFyY29kZSA8IDU1Mjk2IHx8IGNoYXJjb2RlID49IDU3MzQ0KSB7XG4gICAgICAgIHV0ZjgucHVzaCgyMjQgfCBjaGFyY29kZSA+PiAxMiwgMTI4IHwgY2hhcmNvZGUgPj4gNiAmIDYzLCAxMjggfCBjaGFyY29kZSAmIDYzKTtcbiAgICAgIH1cbiAgICAgIC8vIHN1cnJvZ2F0ZSBwYWlyXG4gICAgICBlbHNlIHtcbiAgICAgICAgaSsrO1xuICAgICAgICAvLyBVVEYtMTYgZW5jb2RlcyAweDEwMDAwLTB4MTBGRkZGIGJ5XG4gICAgICAgIC8vIHN1YnRyYWN0aW5nIDB4MTAwMDAgYW5kIHNwbGl0dGluZyB0aGVcbiAgICAgICAgLy8gMjAgYml0cyBvZiAweDAtMHhGRkZGRiBpbnRvIHR3byBoYWx2ZXNcbiAgICAgICAgY2hhcmNvZGUgPSA2NTUzNiArICgoY2hhcmNvZGUgJiAxMDIzKSA8PCAxMCB8IHN0ci5jaGFyQ29kZUF0KGkpICYgMTAyMyk7XG4gICAgICAgIHV0ZjgucHVzaCgyNDAgfCBjaGFyY29kZSA+PiAxOCwgMTI4IHwgY2hhcmNvZGUgPj4gMTIgJiA2MywgMTI4IHwgY2hhcmNvZGUgPj4gNiAmIDYzLCAxMjggfCBjaGFyY29kZSAmIDYzKTtcbiAgICAgIH1cbiAgICB9XG4gICAgcmV0dXJuIHV0Zjg7XG4gIH1cblxuICBzdGF0aWMgdG9VVEYxNkFycmF5KHN0cikge1xuICAgIHZhciB1dGYxNiA9IFtdO1xuICAgIGZvciAodmFyIGkgPSAwOyBpIDwgc3RyLmxlbmd0aDsgaSsrKSB7XG4gICAgICB2YXIgY29kZVBvaW50ID0gc3RyLmNvZGVQb2ludEF0KGkpO1xuXG4gICAgICBpZiAoY29kZVBvaW50IDw9IDI1NSkge1xuICAgICAgICB1dGYxNi5wdXNoKDApO1xuICAgICAgICB1dGYxNi5wdXNoKGNvZGVQb2ludCk7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICB1dGYxNi5wdXNoKGNvZGVQb2ludCA+PiA4ICYgMjU1KTtcbiAgICAgICAgdXRmMTYucHVzaChjb2RlUG9pbnQgJiAyNTUpO1xuICAgICAgfVxuICAgIH1cbiAgICByZXR1cm4gdXRmMTY7XG4gIH1cblxuICBzdGF0aWMgdG9VVEYzMkFycmF5KHN0cikge1xuICAgIHZhciB1dGYzMiA9IFtdO1xuICAgIGZvciAodmFyIGkgPSAwOyBpIDwgc3RyLmxlbmd0aDsgaSsrKSB7XG4gICAgICB2YXIgY29kZVBvaW50ID0gc3RyLmNvZGVQb2ludEF0KGkpO1xuXG4gICAgICBpZiAoY29kZVBvaW50IDw9IDI1NSkge1xuICAgICAgICB1dGYzMi5wdXNoKDApO1xuICAgICAgICB1dGYzMi5wdXNoKDApO1xuICAgICAgICB1dGYzMi5wdXNoKDApO1xuICAgICAgICB1dGYzMi5wdXNoKGNvZGVQb2ludCk7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICB1dGYzMi5wdXNoKDApO1xuICAgICAgICB1dGYzMi5wdXNoKDApO1xuICAgICAgICB1dGYzMi5wdXNoKGNvZGVQb2ludCA+PiA4ICYgMjU1KTtcbiAgICAgICAgdXRmMzIucHVzaChjb2RlUG9pbnQgJiAyNTUpO1xuICAgICAgfVxuICAgIH1cbiAgICByZXR1cm4gdXRmMzI7XG4gIH1cblxuICAvL2h0dHA6Ly9zdGFja292ZXJmbG93LmNvbS9xdWVzdGlvbnMvMjAwMzQ5My9qYXZhc2NyaXB0LWZsb2F0LWZyb20tdG8tYml0c1xuICBzdGF0aWMgZmxvYXQzMlRvQnl0ZXMoZikge1xuICAgIHZhciBieXRlcyA9IFtdO1xuXG4gICAgdmFyIGJ1ZiA9IG5ldyBBcnJheUJ1ZmZlcig0KTtcbiAgICBuZXcgRmxvYXQzMkFycmF5KGJ1ZilbMF0gPSBmO1xuXG4gICAgbGV0IGludFZlcnNpb24gPSBuZXcgVWludDMyQXJyYXkoYnVmKVswXTtcblxuICAgIGJ5dGVzLnB1c2goaW50VmVyc2lvbiA+PiAyNCAmIDI1NSk7XG4gICAgYnl0ZXMucHVzaChpbnRWZXJzaW9uID4+IDE2ICYgMjU1KTtcbiAgICBieXRlcy5wdXNoKGludFZlcnNpb24gPj4gOCAmIDI1NSk7XG4gICAgYnl0ZXMucHVzaChpbnRWZXJzaW9uICYgMjU1KTtcblxuICAgIHJldHVybiBieXRlcztcbiAgfVxuXG4gIHN0YXRpYyBmbG9hdDY0VG9CeXRlcyhmKSB7XG4gICAgdmFyIGJ5dGVzID0gW107XG5cbiAgICB2YXIgYnVmID0gbmV3IEFycmF5QnVmZmVyKDgpO1xuICAgIG5ldyBGbG9hdDY0QXJyYXkoYnVmKVswXSA9IGY7XG5cbiAgICB2YXIgaW50VmVyc2lvbjEgPSBuZXcgVWludDMyQXJyYXkoYnVmKVswXTtcbiAgICB2YXIgaW50VmVyc2lvbjIgPSBuZXcgVWludDMyQXJyYXkoYnVmKVsxXTtcblxuICAgIGJ5dGVzLnB1c2goaW50VmVyc2lvbjIgPj4gMjQgJiAyNTUpO1xuICAgIGJ5dGVzLnB1c2goaW50VmVyc2lvbjIgPj4gMTYgJiAyNTUpO1xuICAgIGJ5dGVzLnB1c2goaW50VmVyc2lvbjIgPj4gOCAmIDI1NSk7XG4gICAgYnl0ZXMucHVzaChpbnRWZXJzaW9uMiAmIDI1NSk7XG5cbiAgICBieXRlcy5wdXNoKGludFZlcnNpb24xID4+IDI0ICYgMjU1KTtcbiAgICBieXRlcy5wdXNoKGludFZlcnNpb24xID4+IDE2ICYgMjU1KTtcbiAgICBieXRlcy5wdXNoKGludFZlcnNpb24xID4+IDggJiAyNTUpO1xuICAgIGJ5dGVzLnB1c2goaW50VmVyc2lvbjEgJiAyNTUpO1xuXG4gICAgcmV0dXJuIGJ5dGVzO1xuICB9XG59XG5cbmxldCBTcGVjaWFsRm9ybXMgPSB7XG5cbiAgX19ESVJfXzogZnVuY3Rpb24gKCkge1xuICAgIGlmIChfX2Rpcm5hbWUpIHtcbiAgICAgIHJldHVybiBfX2Rpcm5hbWU7XG4gICAgfVxuXG4gICAgaWYgKGRvY3VtZW50LmN1cnJlbnRTY3JpcHQpIHtcbiAgICAgIHJldHVybiBkb2N1bWVudC5jdXJyZW50U2NyaXB0LnNyYztcbiAgICB9XG5cbiAgICByZXR1cm4gbnVsbDtcbiAgfSxcblxuICBhdG9tOiBmdW5jdGlvbiAoX3ZhbHVlKSB7XG4gICAgcmV0dXJuIFN5bWJvbC5mb3IoX3ZhbHVlKTtcbiAgfSxcblxuICBsaXN0OiBmdW5jdGlvbiAoLi4uYXJncykge1xuICAgIHJldHVybiBPYmplY3QuZnJlZXplKGFyZ3MpO1xuICB9LFxuXG4gIGJpdHN0cmluZzogZnVuY3Rpb24gKC4uLmFyZ3MpIHtcbiAgICByZXR1cm4gbmV3IEJpdFN0cmluZyguLi5hcmdzKTtcbiAgfSxcblxuICBib3VuZDogZnVuY3Rpb24gKF92YXIpIHtcbiAgICByZXR1cm4gUGF0dGVybnMuYm91bmQoX3Zhcik7XG4gIH0sXG5cbiAgX2Nhc2U6IGZ1bmN0aW9uIChjb25kaXRpb24sIGNsYXVzZXMpIHtcbiAgICByZXR1cm4gUGF0dGVybnMuZGVmbWF0Y2goLi4uY2xhdXNlcykoY29uZGl0aW9uKTtcbiAgfSxcblxuICBjb25kOiBmdW5jdGlvbiAoY2xhdXNlcykge1xuICAgIGZvciAobGV0IGNsYXVzZSBvZiBjbGF1c2VzKSB7XG4gICAgICBpZiAoY2xhdXNlWzBdKSB7XG4gICAgICAgIHJldHVybiBjbGF1c2VbMV0oKTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICB0aHJvdyBuZXcgRXJyb3IoKTtcbiAgfSxcblxuICBmbjogZnVuY3Rpb24gKGNsYXVzZXMpIHtcbiAgICByZXR1cm4gUGF0dGVybnMuZGVmbWF0Y2goY2xhdXNlcyk7XG4gIH0sXG5cbiAgbWFwOiBmdW5jdGlvbiAob2JqKSB7XG4gICAgcmV0dXJuIE9iamVjdC5mcmVlemUob2JqKTtcbiAgfSxcblxuICBtYXBfdXBkYXRlOiBmdW5jdGlvbiAobWFwLCB2YWx1ZXMpIHtcbiAgICByZXR1cm4gT2JqZWN0LmZyZWV6ZShPYmplY3QuYXNzaWduKE9iamVjdC5jcmVhdGUobWFwLmNvbnN0cnVjdG9yLnByb3RvdHlwZSksIG1hcCwgdmFsdWVzKSk7XG4gIH0sXG5cbiAgX2ZvcjogZnVuY3Rpb24gKGNvbGxlY3Rpb25zLCBmdW4sIGZpbHRlciA9ICgpID0+IHRydWUsIGludG8gPSBbXSwgcHJldmlvdXNWYWx1ZXMgPSBbXSkge1xuICAgIGxldCBwYXR0ZXJuID0gY29sbGVjdGlvbnNbMF1bMF07XG4gICAgbGV0IGNvbGxlY3Rpb24gPSBjb2xsZWN0aW9uc1swXVsxXTtcblxuICAgIGlmIChjb2xsZWN0aW9ucy5sZW5ndGggPT09IDEpIHtcblxuICAgICAgZm9yIChsZXQgZWxlbSBvZiBjb2xsZWN0aW9uKSB7XG4gICAgICAgIGxldCByID0gUGF0dGVybnMubWF0Y2hfbm9fdGhyb3cocGF0dGVybiwgZWxlbSk7XG4gICAgICAgIGxldCBhcmdzID0gcHJldmlvdXNWYWx1ZXMuY29uY2F0KHIpO1xuXG4gICAgICAgIGlmIChyICYmIGZpbHRlci5hcHBseSh0aGlzLCBhcmdzKSkge1xuICAgICAgICAgIGludG8gPSBFbnVtLmludG8oW2Z1bi5hcHBseSh0aGlzLCBhcmdzKV0sIGludG8pO1xuICAgICAgICB9XG4gICAgICB9XG5cbiAgICAgIHJldHVybiBpbnRvO1xuICAgIH0gZWxzZSB7XG4gICAgICBsZXQgX2ludG8gPSBbXTtcblxuICAgICAgZm9yIChsZXQgZWxlbSBvZiBjb2xsZWN0aW9uKSB7XG4gICAgICAgIGxldCByID0gUGF0dGVybnMubWF0Y2hfbm9fdGhyb3cocGF0dGVybiwgZWxlbSk7XG4gICAgICAgIGlmIChyKSB7XG4gICAgICAgICAgX2ludG8gPSBFbnVtLmludG8odGhpcy5fZm9yKGNvbGxlY3Rpb25zLnNsaWNlKDEpLCBmdW4sIGZpbHRlciwgX2ludG8sIHByZXZpb3VzVmFsdWVzLmNvbmNhdChyKSksIGludG8pO1xuICAgICAgICB9XG4gICAgICB9XG5cbiAgICAgIHJldHVybiBfaW50bztcbiAgICB9XG4gIH0sXG5cbiAgcmVjZWl2ZTogZnVuY3Rpb24gKHJlY2VpdmVfZnVuLCB0aW1lb3V0X2luX21zID0gbnVsbCwgdGltZW91dF9mbiA9IHRpbWUgPT4gdHJ1ZSkge1xuICAgIGlmICh0aW1lb3V0X2luX21zID09IG51bGwgfHwgdGltZW91dF9pbl9tcyA9PT0gU3lzdGVtLmZvcignaW5maW5pdHknKSkge1xuICAgICAgd2hpbGUgKHRydWUpIHtcbiAgICAgICAgaWYgKHNlbGYubWFpbGJveC5sZW5ndGggIT09IDApIHtcbiAgICAgICAgICBsZXQgbWVzc2FnZSA9IHNlbGYubWFpbGJveFswXTtcbiAgICAgICAgICBzZWxmLm1haWxib3ggPSBzZWxmLm1haWxib3guc2xpY2UoMSk7XG4gICAgICAgICAgcmV0dXJuIHJlY2VpdmVfZnVuKG1lc3NhZ2UpO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgfSBlbHNlIGlmICh0aW1lb3V0X2luX21zID09PSAwKSB7XG4gICAgICBpZiAoc2VsZi5tYWlsYm94Lmxlbmd0aCAhPT0gMCkge1xuICAgICAgICBsZXQgbWVzc2FnZSA9IHNlbGYubWFpbGJveFswXTtcbiAgICAgICAgc2VsZi5tYWlsYm94ID0gc2VsZi5tYWlsYm94LnNsaWNlKDEpO1xuICAgICAgICByZXR1cm4gcmVjZWl2ZV9mdW4obWVzc2FnZSk7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICByZXR1cm4gbnVsbDtcbiAgICAgIH1cbiAgICB9IGVsc2Uge1xuICAgICAgbGV0IG5vdyA9IERhdGUubm93KCk7XG4gICAgICB3aGlsZSAoRGF0ZS5ub3coKSA8IG5vdyArIHRpbWVvdXRfaW5fbXMpIHtcbiAgICAgICAgaWYgKHNlbGYubWFpbGJveC5sZW5ndGggIT09IDApIHtcbiAgICAgICAgICBsZXQgbWVzc2FnZSA9IHNlbGYubWFpbGJveFswXTtcbiAgICAgICAgICBzZWxmLm1haWxib3ggPSBzZWxmLm1haWxib3guc2xpY2UoMSk7XG4gICAgICAgICAgcmV0dXJuIHJlY2VpdmVfZnVuKG1lc3NhZ2UpO1xuICAgICAgICB9XG4gICAgICB9XG5cbiAgICAgIHJldHVybiB0aW1lb3V0X2ZuKHRpbWVvdXRfaW5fbXMpO1xuICAgIH1cbiAgfSxcblxuICB0dXBsZTogZnVuY3Rpb24gKC4uLmFyZ3MpIHtcbiAgICByZXR1cm4gbmV3IFR1cGxlKC4uLmFyZ3MpO1xuICB9LFxuXG4gIF90cnk6IGZ1bmN0aW9uIChkb19mdW4sIHJlc2N1ZV9mdW5jdGlvbiwgY2F0Y2hfZnVuLCBlbHNlX2Z1bmN0aW9uLCBhZnRlcl9mdW5jdGlvbikge1xuICAgIGxldCByZXN1bHQgPSBudWxsO1xuXG4gICAgdHJ5IHtcbiAgICAgIHJlc3VsdCA9IGRvX2Z1bigpO1xuICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgIGxldCBleF9yZXN1bHQgPSBudWxsO1xuXG4gICAgICBpZiAocmVzY3VlX2Z1bmN0aW9uKSB7XG4gICAgICAgIHRyeSB7XG4gICAgICAgICAgZXhfcmVzdWx0ID0gcmVzY3VlX2Z1bmN0aW9uKGUpO1xuICAgICAgICAgIHJldHVybiBleF9yZXN1bHQ7XG4gICAgICAgIH0gY2F0Y2ggKGV4KSB7XG4gICAgICAgICAgaWYgKGV4IGluc3RhbmNlb2YgUGF0dGVybnMuTWF0Y2hFcnJvcikge1xuICAgICAgICAgICAgdGhyb3cgZXg7XG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICB9XG5cbiAgICAgIGlmIChjYXRjaF9mdW4pIHtcbiAgICAgICAgdHJ5IHtcbiAgICAgICAgICBleF9yZXN1bHQgPSBjYXRjaF9mdW4oZSk7XG4gICAgICAgICAgcmV0dXJuIGV4X3Jlc3VsdDtcbiAgICAgICAgfSBjYXRjaCAoZXgpIHtcbiAgICAgICAgICBpZiAoZXggaW5zdGFuY2VvZiBQYXR0ZXJucy5NYXRjaEVycm9yKSB7XG4gICAgICAgICAgICB0aHJvdyBleDtcbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgIH1cblxuICAgICAgdGhyb3cgZTtcbiAgICB9IGZpbmFsbHkge1xuICAgICAgaWYgKGFmdGVyX2Z1bmN0aW9uKSB7XG4gICAgICAgIGFmdGVyX2Z1bmN0aW9uKCk7XG4gICAgICB9XG4gICAgfVxuXG4gICAgaWYgKGVsc2VfZnVuY3Rpb24pIHtcbiAgICAgIHRyeSB7XG4gICAgICAgIHJldHVybiBlbHNlX2Z1bmN0aW9uKHJlc3VsdCk7XG4gICAgICB9IGNhdGNoIChleCkge1xuICAgICAgICBpZiAoZXggaW5zdGFuY2VvZiBQYXR0ZXJucy5NYXRjaEVycm9yKSB7XG4gICAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdObyBNYXRjaCBGb3VuZCBpbiBFbHNlJyk7XG4gICAgICAgIH1cblxuICAgICAgICB0aHJvdyBleDtcbiAgICAgIH1cbiAgICB9IGVsc2Uge1xuICAgICAgcmV0dXJuIHJlc3VsdDtcbiAgICB9XG4gIH1cblxufTtcblxuLyogQGZsb3cgKi9cblxubGV0IHByb2Nlc3NfY291bnRlciA9IC0xO1xuXG5jbGFzcyBQSUQge1xuICBjb25zdHJ1Y3RvcigpIHtcbiAgICBwcm9jZXNzX2NvdW50ZXIgPSBwcm9jZXNzX2NvdW50ZXIgKyAxO1xuICAgIHRoaXMuaWQgPSBwcm9jZXNzX2NvdW50ZXI7XG4gIH1cblxuICB0b1N0cmluZygpIHtcbiAgICByZXR1cm4gXCJQSUQjPDAuXCIgKyB0aGlzLmlkICsgXCIuMD5cIjtcbiAgfVxufVxuXG5jbGFzcyBJbnRlZ2VyVHlwZSB7fVxuY2xhc3MgRmxvYXRUeXBlIHt9XG5cbi8vaHR0cHM6Ly9naXRodWIuY29tL2FpcnBvcnR5aC9wcm90b21vcnBoaXNtXG5jbGFzcyBQcm90b2NvbCB7XG4gIGNvbnN0cnVjdG9yKHNwZWMpIHtcbiAgICB0aGlzLnJlZ2lzdHJ5ID0gbmV3IE1hcCgpO1xuICAgIHRoaXMuZmFsbGJhY2sgPSBudWxsO1xuXG4gICAgZm9yIChsZXQgZnVuTmFtZSBpbiBzcGVjKSB7XG4gICAgICB0aGlzW2Z1bk5hbWVdID0gY3JlYXRlRnVuKGZ1bk5hbWUpLmJpbmQodGhpcyk7XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gY3JlYXRlRnVuKGZ1bk5hbWUpIHtcblxuICAgICAgcmV0dXJuIGZ1bmN0aW9uICguLi5hcmdzKSB7XG4gICAgICAgIGxldCB0aGluZyA9IGFyZ3NbMF07XG4gICAgICAgIGxldCBmdW4gPSBudWxsO1xuXG4gICAgICAgIGlmIChOdW1iZXIuaXNJbnRlZ2VyKHRoaW5nKSAmJiB0aGlzLmhhc0ltcGxlbWVudGF0aW9uKEludGVnZXJUeXBlKSkge1xuICAgICAgICAgIGZ1biA9IHRoaXMucmVnaXN0cnkuZ2V0KEludGVnZXJUeXBlKVtmdW5OYW1lXTtcbiAgICAgICAgfSBlbHNlIGlmICh0eXBlb2YgdGhpbmcgPT09IFwibnVtYmVyXCIgJiYgIU51bWJlci5pc0ludGVnZXIodGhpbmcpICYmIHRoaXMuaGFzSW1wbGVtZW50YXRpb24oRmxvYXRUeXBlKSkge1xuICAgICAgICAgIGZ1biA9IHRoaXMucmVnaXN0cnkuZ2V0KEZsb2F0VHlwZSlbZnVuTmFtZV07XG4gICAgICAgIH0gZWxzZSBpZiAodGhpcy5oYXNJbXBsZW1lbnRhdGlvbih0aGluZykpIHtcbiAgICAgICAgICBmdW4gPSB0aGlzLnJlZ2lzdHJ5LmdldCh0aGluZy5jb25zdHJ1Y3RvcilbZnVuTmFtZV07XG4gICAgICAgIH0gZWxzZSBpZiAodGhpcy5mYWxsYmFjaykge1xuICAgICAgICAgIGZ1biA9IHRoaXMuZmFsbGJhY2tbZnVuTmFtZV07XG4gICAgICAgIH1cblxuICAgICAgICBpZiAoZnVuICE9IG51bGwpIHtcbiAgICAgICAgICBsZXQgcmV0dmFsID0gZnVuLmFwcGx5KHRoaXMsIGFyZ3MpO1xuICAgICAgICAgIHJldHVybiByZXR2YWw7XG4gICAgICAgIH1cblxuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoXCJObyBpbXBsZW1lbnRhdGlvbiBmb3VuZCBmb3IgXCIgKyB0aGluZyk7XG4gICAgICB9O1xuICAgIH1cbiAgfVxuXG4gIGltcGxlbWVudGF0aW9uKHR5cGUsIGltcGxlbWVudGF0aW9uKSB7XG4gICAgaWYgKHR5cGUgPT09IG51bGwpIHtcbiAgICAgIHRoaXMuZmFsbGJhY2sgPSBpbXBsZW1lbnRhdGlvbjtcbiAgICB9IGVsc2Uge1xuICAgICAgdGhpcy5yZWdpc3RyeS5zZXQodHlwZSwgaW1wbGVtZW50YXRpb24pO1xuICAgIH1cbiAgfVxuXG4gIGhhc0ltcGxlbWVudGF0aW9uKHRoaW5nKSB7XG4gICAgcmV0dXJuIHRoaXMucmVnaXN0cnkuaGFzKHRoaW5nLmNvbnN0cnVjdG9yKTtcbiAgfVxufVxuXG5mdW5jdGlvbiB0bChsaXN0KSB7XG4gIHJldHVybiBTcGVjaWFsRm9ybXMubGlzdCguLi5saXN0LnNsaWNlKDEpKTtcbn1cblxuZnVuY3Rpb24gaGQobGlzdCkge1xuICByZXR1cm4gbGlzdFswXTtcbn1cblxuZnVuY3Rpb24gaXNfbmlsKHgpIHtcbiAgcmV0dXJuIHggPT09IG51bGw7XG59XG5cbmZ1bmN0aW9uIGlzX2F0b20oeCkge1xuICByZXR1cm4gdHlwZW9mIHggPT09ICdzeW1ib2wnO1xufVxuXG5mdW5jdGlvbiBpc19iaW5hcnkoeCkge1xuICByZXR1cm4gdHlwZW9mIHggPT09ICdzdHJpbmcnIHx8IHggaW5zdGFuY2VvZiBTdHJpbmc7XG59XG5cbmZ1bmN0aW9uIGlzX2Jvb2xlYW4oeCkge1xuICByZXR1cm4gdHlwZW9mIHggPT09ICdib29sZWFuJyB8fCB4IGluc3RhbmNlb2YgQm9vbGVhbjtcbn1cblxuZnVuY3Rpb24gaXNfZnVuY3Rpb24oeCwgYXJpdHkgPSAtMSkge1xuICByZXR1cm4gdHlwZW9mIHggPT09ICdmdW5jdGlvbicgfHwgeCBpbnN0YW5jZW9mIEZ1bmN0aW9uO1xufVxuXG5mdW5jdGlvbiBpc19mbG9hdCh4KSB7XG4gIHJldHVybiBpc19udW1iZXIoeCkgJiYgIU51bWJlci5pc0ludGVnZXIoeCk7XG59XG5cbmZ1bmN0aW9uIGlzX2ludGVnZXIoeCkge1xuICByZXR1cm4gTnVtYmVyLmlzSW50ZWdlcih4KTtcbn1cblxuZnVuY3Rpb24gaXNfbGlzdCh4KSB7XG4gIHJldHVybiB4IGluc3RhbmNlb2YgQXJyYXk7XG59XG5cbmZ1bmN0aW9uIGlzX21hcCh4KSB7XG4gIHJldHVybiB0eXBlb2YgeCA9PT0gJ29iamVjdCcgfHwgeCBpbnN0YW5jZW9mIE9iamVjdDtcbn1cblxuZnVuY3Rpb24gaXNfbnVtYmVyKHgpIHtcbiAgcmV0dXJuIHR5cGVvZiB4ID09PSAnbnVtYmVyJztcbn1cblxuZnVuY3Rpb24gaXNfdHVwbGUoeCkge1xuICByZXR1cm4geCBpbnN0YW5jZW9mIFR1cGxlO1xufVxuXG5mdW5jdGlvbiBfbGVuZ3RoKHgpIHtcbiAgcmV0dXJuIHgubGVuZ3RoO1xufVxuXG5mdW5jdGlvbiBpc19waWQoeCkge1xuICByZXR1cm4geCBpbnN0YW5jZW9mIFBJRDtcbn1cblxuZnVuY3Rpb24gaXNfcG9ydCh4KSB7XG4gIHJldHVybiBmYWxzZTtcbn1cblxuZnVuY3Rpb24gaXNfcmVmZXJlbmNlKHgpIHtcbiAgcmV0dXJuIGZhbHNlO1xufVxuXG5mdW5jdGlvbiBpc19iaXRzdHJpbmcoeCkge1xuICByZXR1cm4gaXNfYmluYXJ5KHgpIHx8IHggaW5zdGFuY2VvZiBCaXRTdHJpbmc7XG59XG5cbmZ1bmN0aW9uIF9faW5fXyhsZWZ0LCByaWdodCkge1xuICBmb3IgKGxldCB4IG9mIHJpZ2h0KSB7XG4gICAgaWYgKG1hdGNoX19xbWFya19fKGxlZnQsIHgpKSB7XG4gICAgICByZXR1cm4gdHJ1ZTtcbiAgICB9XG4gIH1cblxuICByZXR1cm4gZmFsc2U7XG59XG5cbmZ1bmN0aW9uIGFicyhudW1iZXIpIHtcbiAgcmV0dXJuIE1hdGguYWJzKG51bWJlcik7XG59XG5cbmZ1bmN0aW9uIHJvdW5kKG51bWJlcikge1xuICByZXR1cm4gTWF0aC5yb3VuZChudW1iZXIpO1xufVxuXG5mdW5jdGlvbiBlbGVtKHR1cGxlLCBpbmRleCkge1xuICBpZiAoaXNfbGlzdCh0dXBsZSkpIHtcbiAgICByZXR1cm4gdHVwbGVbaW5kZXhdO1xuICB9XG5cbiAgcmV0dXJuIHR1cGxlLmdldChpbmRleCk7XG59XG5cbmZ1bmN0aW9uIHJlbShsZWZ0LCByaWdodCkge1xuICByZXR1cm4gbGVmdCAlIHJpZ2h0O1xufVxuXG5mdW5jdGlvbiBkaXYobGVmdCwgcmlnaHQpIHtcbiAgcmV0dXJuIGxlZnQgLyByaWdodDtcbn1cblxuZnVuY3Rpb24gYW5kKGxlZnQsIHJpZ2h0KSB7XG4gIHJldHVybiBsZWZ0ICYmIHJpZ2h0O1xufVxuXG5mdW5jdGlvbiBvcihsZWZ0LCByaWdodCkge1xuICByZXR1cm4gbGVmdCB8fCByaWdodDtcbn1cblxuZnVuY3Rpb24gbm90KGFyZykge1xuICByZXR1cm4gIWFyZztcbn1cblxuZnVuY3Rpb24gYXBwbHkoLi4uYXJncykge1xuICBpZiAoYXJncy5sZW5ndGggPT09IDMpIHtcbiAgICBsZXQgbW9kID0gYXJnc1swXTtcbiAgICBsZXQgZnVuYyA9IGFyZ3NbMV07XG4gICAgbGV0IGZ1bmNfYXJncyA9IGFyZ3NbMl07XG4gICAgcmV0dXJuIG1vZFtmdW5jXS5hcHBseShudWxsLCBmdW5jX2FyZ3MpO1xuICB9IGVsc2Uge1xuICAgIGxldCBmdW5jID0gYXJnc1swXTtcbiAgICBsZXQgZnVuY19hcmdzID0gYXJnc1sxXTtcblxuICAgIHJldHVybiBmdW5jLmFwcGx5KG51bGwsIGZ1bmNfYXJncyk7XG4gIH1cbn1cblxuZnVuY3Rpb24gdG9fc3RyaW5nKGFyZykge1xuICBpZiAoaXNfdHVwbGUoYXJnKSkge1xuICAgIHJldHVybiBUdXBsZS50b19zdHJpbmcoYXJnKTtcbiAgfVxuXG4gIHJldHVybiBhcmcudG9TdHJpbmcoKTtcbn1cblxuZnVuY3Rpb24gbWF0Y2hfX3FtYXJrX18ocGF0dGVybiwgZXhwciwgZ3VhcmQgPSAoKSA9PiB0cnVlKSB7XG4gIHJldHVybiBfUGF0dGVybnMubWF0Y2hfbm9fdGhyb3cocGF0dGVybiwgZXhwciwgZ3VhcmQpICE9IG51bGw7XG59XG5cbmZ1bmN0aW9uIGRlZnN0cnVjdChkZWZhdWx0cykge1xuICByZXR1cm4gY2xhc3Mge1xuICAgIGNvbnN0cnVjdG9yKHVwZGF0ZSA9IHt9KSB7XG4gICAgICBsZXQgdGhlX3ZhbHVlcyA9IE9iamVjdC5hc3NpZ24oZGVmYXVsdHMsIHVwZGF0ZSk7XG4gICAgICBPYmplY3QuYXNzaWduKHRoaXMsIHRoZV92YWx1ZXMpO1xuICAgIH1cblxuICAgIHN0YXRpYyBjcmVhdGUodXBkYXRlcyA9IHt9KSB7XG4gICAgICBsZXQgeCA9IG5ldyB0aGlzKHVwZGF0ZXMpO1xuICAgICAgcmV0dXJuIE9iamVjdC5mcmVlemUoeCk7XG4gICAgfVxuICB9O1xufVxuXG5mdW5jdGlvbiBkZWZleGNlcHRpb24oZGVmYXVsdHMpIHtcbiAgcmV0dXJuIGNsYXNzIGV4dGVuZHMgRXJyb3Ige1xuICAgIGNvbnN0cnVjdG9yKHVwZGF0ZSA9IHt9KSB7XG4gICAgICBsZXQgbWVzc2FnZSA9IHVwZGF0ZS5tZXNzYWdlIHx8ICcnO1xuICAgICAgc3VwZXIobWVzc2FnZSk7XG5cbiAgICAgIGxldCB0aGVfdmFsdWVzID0gT2JqZWN0LmFzc2lnbihkZWZhdWx0cywgdXBkYXRlKTtcbiAgICAgIE9iamVjdC5hc3NpZ24odGhpcywgdGhlX3ZhbHVlcyk7XG5cbiAgICAgIHRoaXMubmFtZSA9IHRoaXMuY29uc3RydWN0b3IubmFtZTtcbiAgICAgIHRoaXMubWVzc2FnZSA9IG1lc3NhZ2U7XG4gICAgICB0aGlzW1NwZWNpYWxGb3Jtcy5hdG9tKCdfX2V4Y2VwdGlvbl9fJyldID0gdHJ1ZTtcbiAgICAgIEVycm9yLmNhcHR1cmVTdGFja1RyYWNlKHRoaXMsIHRoaXMuY29uc3RydWN0b3IubmFtZSk7XG4gICAgfVxuXG4gICAgc3RhdGljIGNyZWF0ZSh1cGRhdGVzID0ge30pIHtcbiAgICAgIGxldCB4ID0gbmV3IHRoaXModXBkYXRlcyk7XG4gICAgICByZXR1cm4gT2JqZWN0LmZyZWV6ZSh4KTtcbiAgICB9XG4gIH07XG59XG5cbmZ1bmN0aW9uIGRlZnByb3RvY29sKHNwZWMpIHtcbiAgcmV0dXJuIG5ldyBQcm90b2NvbChzcGVjKTtcbn1cblxuZnVuY3Rpb24gZGVmaW1wbChwcm90b2NvbCwgdHlwZSwgaW1wbCkge1xuICBwcm90b2NvbC5pbXBsZW1lbnRhdGlvbih0eXBlLCBpbXBsKTtcbn1cblxudmFyIEtlcm5lbCA9IHtcbiAgU3BlY2lhbEZvcm1zLFxuICB0bCxcbiAgaGQsXG4gIGlzX25pbCxcbiAgaXNfYXRvbSxcbiAgaXNfYmluYXJ5LFxuICBpc19ib29sZWFuLFxuICBpc19mdW5jdGlvbixcbiAgaXNfZmxvYXQsXG4gIGlzX2ludGVnZXIsXG4gIGlzX2xpc3QsXG4gIGlzX21hcCxcbiAgaXNfbnVtYmVyLFxuICBpc190dXBsZSxcbiAgbGVuZ3RoOiBfbGVuZ3RoLFxuICBpc19waWQsXG4gIGlzX3BvcnQsXG4gIGlzX3JlZmVyZW5jZSxcbiAgaXNfYml0c3RyaW5nLFxuICBpbjogX19pbl9fLFxuICBhYnMsXG4gIHJvdW5kLFxuICBlbGVtLFxuICByZW0sXG4gIGRpdixcbiAgYW5kLFxuICBvcixcbiAgbm90LFxuICBhcHBseSxcbiAgdG9fc3RyaW5nLFxuICBtYXRjaF9fcW1hcmtfXyxcbiAgZGVmc3RydWN0LFxuICBkZWZwcm90b2NvbCxcbiAgZGVmaW1wbFxufTtcblxubGV0IEVudW0gPSB7XG5cbiAgYWxsX19xbWFya19fOiBmdW5jdGlvbiAoY29sbGVjdGlvbiwgZnVuID0geCA9PiB4KSB7XG4gICAgZm9yIChsZXQgZWxlbSBvZiBjb2xsZWN0aW9uKSB7XG4gICAgICBpZiAoIWZ1bihlbGVtKSkge1xuICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICB9XG4gICAgfVxuXG4gICAgcmV0dXJuIHRydWU7XG4gIH0sXG5cbiAgYW55X19xbWFya19fOiBmdW5jdGlvbiAoY29sbGVjdGlvbiwgZnVuID0geCA9PiB4KSB7XG4gICAgZm9yIChsZXQgZWxlbSBvZiBjb2xsZWN0aW9uKSB7XG4gICAgICBpZiAoZnVuKGVsZW0pKSB7XG4gICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgfVxuICAgIH1cblxuICAgIHJldHVybiBmYWxzZTtcbiAgfSxcblxuICBhdDogZnVuY3Rpb24gKGNvbGxlY3Rpb24sIG4sIHRoZV9kZWZhdWx0ID0gbnVsbCkge1xuICAgIGlmIChuID4gdGhpcy5jb3VudChjb2xsZWN0aW9uKSB8fCBuIDwgMCkge1xuICAgICAgcmV0dXJuIHRoZV9kZWZhdWx0O1xuICAgIH1cblxuICAgIHJldHVybiBjb2xsZWN0aW9uW25dO1xuICB9LFxuXG4gIGNvbmNhdDogZnVuY3Rpb24gKC4uLmVudW1hYmxlcykge1xuICAgIHJldHVybiBlbnVtYWJsZXNbMF0uY29uY2F0KGVudW1hYmxlc1sxXSk7XG4gIH0sXG5cbiAgY291bnQ6IGZ1bmN0aW9uIChjb2xsZWN0aW9uLCBmdW4gPSBudWxsKSB7XG4gICAgaWYgKGZ1biA9PSBudWxsKSB7XG4gICAgICByZXR1cm4gY29sbGVjdGlvbi5sZW5ndGg7XG4gICAgfSBlbHNlIHtcbiAgICAgIHJldHVybiBjb2xsZWN0aW9uLmZpbHRlcihmdW4pLmxlbmd0aDtcbiAgICB9XG4gIH0sXG5cbiAgZHJvcDogZnVuY3Rpb24gKGNvbGxlY3Rpb24sIGNvdW50KSB7XG4gICAgcmV0dXJuIGNvbGxlY3Rpb24uc2xpY2UoY291bnQpO1xuICB9LFxuXG4gIGRyb3Bfd2hpbGU6IGZ1bmN0aW9uIChjb2xsZWN0aW9uLCBmdW4pIHtcbiAgICBsZXQgY291bnQgPSAwO1xuXG4gICAgZm9yIChsZXQgZWxlbSBvZiBjb2xsZWN0aW9uKSB7XG4gICAgICBpZiAoZnVuKGVsZW0pKSB7XG4gICAgICAgIGNvdW50ID0gY291bnQgKyAxO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgYnJlYWs7XG4gICAgICB9XG4gICAgfVxuXG4gICAgcmV0dXJuIGNvbGxlY3Rpb24uc2xpY2UoY291bnQpO1xuICB9LFxuXG4gIGVhY2g6IGZ1bmN0aW9uIChjb2xsZWN0aW9uLCBmdW4pIHtcbiAgICBmb3IgKGxldCBlbGVtIG9mIGNvbGxlY3Rpb24pIHtcbiAgICAgIGZ1bihlbGVtKTtcbiAgICB9XG4gIH0sXG5cbiAgZW1wdHlfX3FtYXJrX186IGZ1bmN0aW9uIChjb2xsZWN0aW9uKSB7XG4gICAgcmV0dXJuIGNvbGxlY3Rpb24ubGVuZ3RoID09PSAwO1xuICB9LFxuXG4gIGZldGNoOiBmdW5jdGlvbiAoY29sbGVjdGlvbiwgbikge1xuICAgIGlmIChLZXJuZWwuaXNfbGlzdChjb2xsZWN0aW9uKSkge1xuICAgICAgaWYgKG4gPCB0aGlzLmNvdW50KGNvbGxlY3Rpb24pICYmIG4gPj0gMCkge1xuICAgICAgICByZXR1cm4gS2VybmVsLlNwZWNpYWxGb3Jtcy50dXBsZShLZXJuZWwuU3BlY2lhbEZvcm1zLmF0b20oXCJva1wiKSwgY29sbGVjdGlvbltuXSk7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICByZXR1cm4gS2VybmVsLlNwZWNpYWxGb3Jtcy5hdG9tKFwiZXJyb3JcIik7XG4gICAgICB9XG4gICAgfVxuXG4gICAgdGhyb3cgbmV3IEVycm9yKFwiY29sbGVjdGlvbiBpcyBub3QgYW4gRW51bWVyYWJsZVwiKTtcbiAgfSxcblxuICBmZXRjaF9fZW1hcmtfXzogZnVuY3Rpb24gKGNvbGxlY3Rpb24sIG4pIHtcbiAgICBpZiAoS2VybmVsLmlzX2xpc3QoY29sbGVjdGlvbikpIHtcbiAgICAgIGlmIChuIDwgdGhpcy5jb3VudChjb2xsZWN0aW9uKSAmJiBuID49IDApIHtcbiAgICAgICAgcmV0dXJuIGNvbGxlY3Rpb25bbl07XG4gICAgICB9IGVsc2Uge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoXCJvdXQgb2YgYm91bmRzIGVycm9yXCIpO1xuICAgICAgfVxuICAgIH1cblxuICAgIHRocm93IG5ldyBFcnJvcihcImNvbGxlY3Rpb24gaXMgbm90IGFuIEVudW1lcmFibGVcIik7XG4gIH0sXG5cbiAgZmlsdGVyOiBmdW5jdGlvbiAoY29sbGVjdGlvbiwgZnVuKSB7XG4gICAgbGV0IHJlc3VsdCA9IFtdO1xuXG4gICAgZm9yIChsZXQgZWxlbSBvZiBjb2xsZWN0aW9uKSB7XG4gICAgICBpZiAoZnVuKGVsZW0pKSB7XG4gICAgICAgIHJlc3VsdC5wdXNoKGVsZW0pO1xuICAgICAgfVxuICAgIH1cblxuICAgIHJldHVybiByZXN1bHQ7XG4gIH0sXG5cbiAgZmlsdGVyX21hcDogZnVuY3Rpb24gKGNvbGxlY3Rpb24sIGZpbHRlciwgbWFwcGVyKSB7XG4gICAgcmV0dXJuIEVudW0ubWFwKEVudW0uZmlsdGVyKGNvbGxlY3Rpb24sIGZpbHRlciksIG1hcHBlcik7XG4gIH0sXG5cbiAgZmluZDogZnVuY3Rpb24gKGNvbGxlY3Rpb24sIGlmX25vbmUgPSBudWxsLCBmdW4pIHtcbiAgICBmb3IgKGxldCBlbGVtIG9mIGNvbGxlY3Rpb24pIHtcbiAgICAgIGlmIChmdW4oZWxlbSkpIHtcbiAgICAgICAgcmV0dXJuIGVsZW07XG4gICAgICB9XG4gICAgfVxuXG4gICAgcmV0dXJuIGlmX25vbmU7XG4gIH0sXG5cbiAgaW50bzogZnVuY3Rpb24gKGNvbGxlY3Rpb24sIGxpc3QpIHtcbiAgICByZXR1cm4gbGlzdC5jb25jYXQoY29sbGVjdGlvbik7XG4gIH0sXG5cbiAgbWFwOiBmdW5jdGlvbiAoY29sbGVjdGlvbiwgZnVuKSB7XG4gICAgbGV0IHJlc3VsdCA9IFtdO1xuXG4gICAgZm9yIChsZXQgZWxlbSBvZiBjb2xsZWN0aW9uKSB7XG4gICAgICByZXN1bHQucHVzaChmdW4oZWxlbSkpO1xuICAgIH1cblxuICAgIHJldHVybiByZXN1bHQ7XG4gIH0sXG5cbiAgbWFwX3JlZHVjZTogZnVuY3Rpb24gKGNvbGxlY3Rpb24sIGFjYywgZnVuKSB7XG4gICAgbGV0IG1hcHBlZCA9IEtlcm5lbC5TcGVjaWFsRm9ybXMubGlzdCgpO1xuICAgIGxldCB0aGVfYWNjID0gYWNjO1xuXG4gICAgZm9yICh2YXIgaSA9IDA7IGkgPCB0aGlzLmNvdW50KGNvbGxlY3Rpb24pOyBpKyspIHtcbiAgICAgIGxldCB0dXBsZSA9IGZ1bihjb2xsZWN0aW9uW2ldLCB0aGVfYWNjKTtcblxuICAgICAgdGhlX2FjYyA9IEtlcm5lbC5lbGVtKHR1cGxlLCAxKTtcbiAgICAgIG1hcHBlZCA9IEtlcm5lbC5TcGVjaWFsRm9ybXMubGlzdCguLi5tYXBwZWQuY29uY2F0KFtLZXJuZWwuZWxlbSh0dXBsZSwgMCldKSk7XG4gICAgfVxuXG4gICAgcmV0dXJuIEtlcm5lbC5TcGVjaWFsRm9ybXMudHVwbGUobWFwcGVkLCB0aGVfYWNjKTtcbiAgfSxcblxuICBtZW1iZXI6IGZ1bmN0aW9uIChjb2xsZWN0aW9uLCB2YWx1ZSkge1xuICAgIHJldHVybiBjb2xsZWN0aW9uLmluY2x1ZGVzKHZhbHVlKTtcbiAgfSxcblxuICByZWR1Y2U6IGZ1bmN0aW9uIChjb2xsZWN0aW9uLCBhY2MsIGZ1bikge1xuICAgIGxldCB0aGVfYWNjID0gYWNjO1xuXG4gICAgZm9yICh2YXIgaSA9IDA7IGkgPCB0aGlzLmNvdW50KGNvbGxlY3Rpb24pOyBpKyspIHtcbiAgICAgIGxldCB0dXBsZSA9IGZ1bihjb2xsZWN0aW9uW2ldLCB0aGVfYWNjKTtcblxuICAgICAgdGhlX2FjYyA9IEtlcm5lbC5lbGVtKHR1cGxlLCAxKTtcbiAgICB9XG5cbiAgICByZXR1cm4gdGhlX2FjYztcbiAgfSxcblxuICB0YWtlOiBmdW5jdGlvbiAoY29sbGVjdGlvbiwgY291bnQpIHtcbiAgICByZXR1cm4gY29sbGVjdGlvbi5zbGljZSgwLCBjb3VudCk7XG4gIH0sXG5cbiAgdGFrZV9ldmVyeTogZnVuY3Rpb24gKGNvbGxlY3Rpb24sIG50aCkge1xuICAgIGxldCByZXN1bHQgPSBbXTtcbiAgICBsZXQgaW5kZXggPSAwO1xuXG4gICAgZm9yIChsZXQgZWxlbSBvZiBjb2xsZWN0aW9uKSB7XG4gICAgICBpZiAoaW5kZXggJSBudGggPT09IDApIHtcbiAgICAgICAgcmVzdWx0LnB1c2goZWxlbSk7XG4gICAgICB9XG4gICAgfVxuXG4gICAgcmV0dXJuIEtlcm5lbC5TcGVjaWFsRm9ybXMubGlzdCguLi5yZXN1bHQpO1xuICB9LFxuXG4gIHRha2Vfd2hpbGU6IGZ1bmN0aW9uIChjb2xsZWN0aW9uLCBmdW4pIHtcbiAgICBsZXQgY291bnQgPSAwO1xuXG4gICAgZm9yIChsZXQgZWxlbSBvZiBjb2xsZWN0aW9uKSB7XG4gICAgICBpZiAoZnVuKGVsZW0pKSB7XG4gICAgICAgIGNvdW50ID0gY291bnQgKyAxO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgYnJlYWs7XG4gICAgICB9XG4gICAgfVxuXG4gICAgcmV0dXJuIGNvbGxlY3Rpb24uc2xpY2UoMCwgY291bnQpO1xuICB9LFxuXG4gIHRvX2xpc3Q6IGZ1bmN0aW9uIChjb2xsZWN0aW9uKSB7XG4gICAgcmV0dXJuIGNvbGxlY3Rpb247XG4gIH1cbn07XG5cbmxldCBBdG9tID0ge307XG5cbkF0b20udG9fc3RyaW5nID0gZnVuY3Rpb24gKGF0b20pIHtcbiAgcmV0dXJuIFN5bWJvbC5rZXlGb3IoYXRvbSk7XG59O1xuXG5BdG9tLnRvX2NoYXJfbGlzdCA9IGZ1bmN0aW9uIChhdG9tKSB7XG4gIHJldHVybiBBdG9tLnRvX3N0cmluZyhhdG9tKS5zcGxpdCgnJyk7XG59O1xuXG5sZXQgSW50ZWdlciA9IHtcblxuICBpc19ldmVuOiBmdW5jdGlvbiAobikge1xuICAgIHJldHVybiBuICUgMiA9PT0gMDtcbiAgfSxcblxuICBpc19vZGQ6IGZ1bmN0aW9uIChuKSB7XG4gICAgcmV0dXJuIG4gJSAyICE9PSAwO1xuICB9LFxuXG4gIHBhcnNlOiBmdW5jdGlvbiAoYmluKSB7XG4gICAgbGV0IHJlc3VsdCA9IHBhcnNlSW50KGJpbik7XG5cbiAgICBpZiAoaXNOYU4ocmVzdWx0KSkge1xuICAgICAgcmV0dXJuIEtlcm5lbC5TcGVjaWFsRm9ybXMuYXRvbShcImVycm9yXCIpO1xuICAgIH1cblxuICAgIGxldCBpbmRleE9mRG90ID0gYmluLmluZGV4T2YoXCIuXCIpO1xuXG4gICAgaWYgKGluZGV4T2ZEb3QgPj0gMCkge1xuICAgICAgcmV0dXJuIEtlcm5lbC5TcGVjaWFsRm9ybXMudHVwbGUocmVzdWx0LCBiaW4uc3Vic3RyaW5nKGluZGV4T2ZEb3QpKTtcbiAgICB9XG5cbiAgICByZXR1cm4gS2VybmVsLlNwZWNpYWxGb3Jtcy50dXBsZShyZXN1bHQsIFwiXCIpO1xuICB9LFxuXG4gIHRvX2NoYXJfbGlzdDogZnVuY3Rpb24gKG51bWJlciwgYmFzZSA9IDEwKSB7XG4gICAgcmV0dXJuIG51bWJlci50b1N0cmluZyhiYXNlKS5zcGxpdChcIlwiKTtcbiAgfSxcblxuICB0b19zdHJpbmc6IGZ1bmN0aW9uIChudW1iZXIsIGJhc2UgPSAxMCkge1xuICAgIHJldHVybiBudW1iZXIudG9TdHJpbmcoYmFzZSk7XG4gIH1cbn07XG5cbmxldCBfQ2hhcnMgPSBLZXJuZWwuZGVmcHJvdG9jb2woe1xuICB0b19zdHJpbmc6IGZ1bmN0aW9uICh0aGluZykge31cbn0pO1xuXG5LZXJuZWwuZGVmaW1wbChfQ2hhcnMsIEJpdFN0cmluZywge1xuICB0b19zdHJpbmc6IGZ1bmN0aW9uICh0aGluZykge1xuICAgIGlmIChLZXJuZWwuaXNfYmluYXJ5KHRoaW5nKSkge1xuICAgICAgcmV0dXJuIHRoaW5nO1xuICAgIH1cblxuICAgIHJldHVybiB0aGluZy50b1N0cmluZygpO1xuICB9XG59KTtcblxuS2VybmVsLmRlZmltcGwoX0NoYXJzLCBTeW1ib2wsIHtcbiAgdG9fc3RyaW5nOiBmdW5jdGlvbiAodGhpbmcpIHtcbiAgICBpZiAobmlsKSB7XG4gICAgICByZXR1cm4gXCJcIjtcbiAgICB9XG5cbiAgICByZXR1cm4gQXRvbS50b19zdHJpbmcodGhpbmcpO1xuICB9XG59KTtcblxuS2VybmVsLmRlZmltcGwoX0NoYXJzLCBJbnRlZ2VyVHlwZSwge1xuICB0b19zdHJpbmc6IGZ1bmN0aW9uICh0aGluZykge1xuICAgIHJldHVybiBJbnRlZ2VyLnRvX3N0cmluZyh0aGluZyk7XG4gIH1cbn0pO1xuXG5LZXJuZWwuZGVmaW1wbChfQ2hhcnMsIEZsb2F0VHlwZSwge1xuICB0b19zdHJpbmc6IGZ1bmN0aW9uICh0aGluZykge1xuICAgIHJldHVybiB0aGluZy50b1N0cmluZztcbiAgfVxufSk7XG5cbktlcm5lbC5kZWZpbXBsKF9DaGFycywgQXJyYXksIHtcbiAgdG9fc3RyaW5nOiBmdW5jdGlvbiAodGhpbmcpIHtcbiAgICByZXR1cm4gdGhpbmcudG9TdHJpbmcoKTtcbiAgfVxufSk7XG5cbktlcm5lbC5kZWZpbXBsKF9DaGFycywgVHVwbGUsIHtcbiAgdG9fc3RyaW5nOiBmdW5jdGlvbiAodGhpbmcpIHtcbiAgICByZXR1cm4gVHVwbGUudG9fc3RyaW5nKHRoaW5nKTtcbiAgfVxufSk7XG5cbktlcm5lbC5kZWZpbXBsKF9DaGFycywgbnVsbCwge1xuICB0b19zdHJpbmc6IGZ1bmN0aW9uICh0aGluZykge1xuICAgIHJldHVybiB0aGluZy50b1N0cmluZygpO1xuICB9XG59KTtcblxuZnVuY3Rpb24gdG9fYXRvbShzdHJpbmcpIHtcbiAgcmV0dXJuIFN5bWJvbC5mb3Ioc3RyaW5nKTtcbn1cblxuZnVuY3Rpb24gdG9fZXhpc3RpbmdfYXRvbShzdHJpbmcpIHtcbiAgcmV0dXJuIFN5bWJvbC5mb3Ioc3RyaW5nKTtcbn1cblxuZnVuY3Rpb24gdG9fY2hhcl9saXN0KHN0cmluZykge1xuICByZXR1cm4gc3RyaW5nLnNwbGl0KCcnKTtcbn1cblxuZnVuY3Rpb24gdG9fZmxvYXQoc3RyaW5nKSB7XG4gIHJldHVybiBwYXJzZUZsb2F0KHN0cmluZyk7XG59XG5cbmZ1bmN0aW9uIHRvX2ludGVnZXIoc3RyaW5nLCBiYXNlID0gMTApIHtcbiAgcmV0dXJuIHBhcnNlSW50KHN0cmluZywgYmFzZSk7XG59XG5cbmZ1bmN0aW9uIHVwY2FzZShiaW5hcnkpIHtcbiAgcmV0dXJuIGJpbmFyeS50b1VwcGVyQ2FzZSgpO1xufVxuXG5mdW5jdGlvbiBkb3duY2FzZShiaW5hcnkpIHtcbiAgcmV0dXJuIGJpbmFyeS50b0xvd2VyQ2FzZSgpO1xufVxuXG5mdW5jdGlvbiBhdChzdHJpbmcsIHBvc2l0aW9uKSB7XG4gIGlmIChwb3NpdGlvbiA+IHN0cmluZy5sZW5ndGggLSAxKSB7XG4gICAgcmV0dXJuIG51bGw7XG4gIH1cblxuICByZXR1cm4gc3RyaW5nW3Bvc2l0aW9uXTtcbn1cblxuZnVuY3Rpb24gY2FwaXRhbGl6ZShzdHJpbmcpIHtcbiAgbGV0IHJldHVyblN0cmluZyA9ICcnO1xuXG4gIGZvciAobGV0IGkgPSAwOyBpIDwgc3RyaW5nLmxlbmd0aDsgaSsrKSB7XG4gICAgaWYgKGkgPT09IDApIHtcbiAgICAgIHJldHVyblN0cmluZyA9IHJldHVyblN0cmluZyArIHN0cmluZ1tpXS50b1VwcGVyQ2FzZSgpO1xuICAgIH0gZWxzZSB7XG4gICAgICByZXR1cm5TdHJpbmcgPSByZXR1cm5TdHJpbmcgKyBzdHJpbmdbaV0udG9Mb3dlckNhc2UoKTtcbiAgICB9XG4gIH1cblxuICByZXR1cm4gcmV0dXJuU3RyaW5nO1xufVxuXG5mdW5jdGlvbiBjb2RlcG9pbnRzKHN0cmluZykge1xuICByZXR1cm4gdG9fY2hhcl9saXN0KHN0cmluZykubWFwKGZ1bmN0aW9uIChjKSB7XG4gICAgcmV0dXJuIGMuY29kZVBvaW50QXQoMCk7XG4gIH0pO1xufVxuXG5mdW5jdGlvbiBjb250YWluc19fcW1fXyhzdHJpbmcsIGNvbnRhaW5zKSB7XG4gIGlmIChBcnJheS5pc0FycmF5KGNvbnRhaW5zKSkge1xuICAgIHJldHVybiBjb250YWlucy5zb21lKGZ1bmN0aW9uIChzKSB7XG4gICAgICByZXR1cm4gc3RyaW5nLmluZGV4T2YocykgPiAtMTtcbiAgICB9KTtcbiAgfVxuXG4gIHJldHVybiBzdHJpbmcuaW5kZXhPZihjb250YWlucykgPiAtMTtcbn1cblxuZnVuY3Rpb24gZHVwbGljYXRlKHN1YmplY3QsIG4pIHtcbiAgcmV0dXJuIHN1YmplY3QucmVwZWF0KG4pO1xufVxuXG5mdW5jdGlvbiBlbmRzX3dpdGhfX3FtX18oc3RyaW5nLCBzdWZmaXhlcykge1xuICBpZiAoQXJyYXkuaXNBcnJheShzdWZmaXhlcykpIHtcbiAgICByZXR1cm4gc3VmZml4ZXMuc29tZShmdW5jdGlvbiAocykge1xuICAgICAgcmV0dXJuIHN0cmluZy5lbmRzV2l0aChzKTtcbiAgICB9KTtcbiAgfVxuXG4gIHJldHVybiBzdHJpbmcuZW5kc1dpdGgoc3VmZml4ZXMpO1xufVxuXG5mdW5jdGlvbiBmaXJzdChzdHJpbmcpIHtcbiAgaWYgKCFzdHJpbmcpIHtcbiAgICByZXR1cm4gbnVsbDtcbiAgfVxuXG4gIHJldHVybiBzdHJpbmdbMF07XG59XG5cbmZ1bmN0aW9uIGdyYXBoZW1lcyhzdHJpbmcpIHtcbiAgcmV0dXJuIHN0cmluZy5zcGxpdCgnJyk7XG59XG5cbmZ1bmN0aW9uIGxhc3Qoc3RyaW5nKSB7XG4gIGlmICghc3RyaW5nKSB7XG4gICAgcmV0dXJuIG51bGw7XG4gIH1cblxuICByZXR1cm4gc3RyaW5nW3N0cmluZy5sZW5ndGggLSAxXTtcbn1cblxuZnVuY3Rpb24gbGVuZ3RoKHN0cmluZykge1xuICByZXR1cm4gc3RyaW5nLmxlbmd0aDtcbn1cblxuZnVuY3Rpb24gbWF0Y2hfX3FtX18oc3RyaW5nLCByZWdleCkge1xuICByZXR1cm4gc3RyaW5nLm1hdGNoKHJlZ2V4KSAhPSBudWxsO1xufVxuXG5mdW5jdGlvbiBuZXh0X2NvZGVwb2ludChzdHJpbmcpIHtcbiAgaWYgKCFzdHJpbmcgfHwgc3RyaW5nID09PSAnJykge1xuICAgIHJldHVybiBudWxsO1xuICB9XG5cbiAgcmV0dXJuIEtlcm5lbC5TcGVjaWFsRm9ybXMudHVwbGUoc3RyaW5nWzBdLmNvZGVQb2ludEF0KDApLCBzdHJpbmcuc3Vic3RyKDEpKTtcbn1cblxuZnVuY3Rpb24gbmV4dF9ncmFwaGVtZShzdHJpbmcpIHtcbiAgaWYgKCFzdHJpbmcgfHwgc3RyaW5nID09PSAnJykge1xuICAgIHJldHVybiBudWxsO1xuICB9XG5cbiAgcmV0dXJuIEtlcm5lbC5TcGVjaWFsRm9ybXMudHVwbGUoc3RyaW5nWzBdLCBzdHJpbmcuc3Vic3RyKDEpKTtcbn1cblxuZnVuY3Rpb24gcmV2ZXJzZShzdHJpbmcpIHtcbiAgbGV0IHJldHVyblZhbHVlID0gJyc7XG5cbiAgZm9yICh2YXIgaSA9IHN0cmluZy5sZW5ndGggLSAxOyBpID49IDA7IGktLSkge1xuICAgIHJldHVyblZhbHVlID0gcmV0dXJuVmFsdWUgKyBzdHJpbmdbaV07XG4gIH07XG5cbiAgcmV0dXJuIHJldHVyblZhbHVlO1xufVxuXG5mdW5jdGlvbiBfc3BsaXQoc3RyaW5nKSB7XG4gIHJldHVybiBzdHJpbmcuc3BsaXQoKTtcbn1cblxuZnVuY3Rpb24gc3RhcnRzX3dpdGhfX3FtX18oc3RyaW5nLCBwcmVmaXhlcykge1xuICBpZiAoQXJyYXkuaXNBcnJheShwcmVmaXhlcykpIHtcbiAgICByZXR1cm4gcHJlZml4ZXMuc29tZShmdW5jdGlvbiAocykge1xuICAgICAgcmV0dXJuIHN0cmluZy5zdGFydHNXaXRoKHMpO1xuICAgIH0pO1xuICB9XG5cbiAgcmV0dXJuIHN0cmluZy5zdGFydHNXaXRoKHByZWZpeGVzKTtcbn1cblxuZnVuY3Rpb24gdmFsaWRfY2hhcmFjdGVyX19xbV9fKGNvZGVwb2ludCkge1xuICB0cnkge1xuICAgIHJldHVybiBTdHJpbmcuZnJvbUNvZGVQb2ludChjb2RlcG9pbnQpICE9IG51bGw7XG4gIH0gY2F0Y2ggKGUpIHtcbiAgICByZXR1cm4gZmFsc2U7XG4gIH1cbn1cblxudmFyIF9TdHJpbmcgPSB7XG4gIGF0LFxuICBjYXBpdGFsaXplLFxuICBjb2RlcG9pbnRzLFxuICBjb250YWluc19fcW1fXyxcbiAgZG93bmNhc2UsXG4gIGR1cGxpY2F0ZSxcbiAgZW5kc193aXRoX19xbV9fLFxuICBmaXJzdCxcbiAgZ3JhcGhlbWVzLFxuICBsYXN0LFxuICBsZW5ndGgsXG4gIG1hdGNoX19xbV9fLFxuICBuZXh0X2NvZGVwb2ludCxcbiAgbmV4dF9ncmFwaGVtZSxcbiAgcmV2ZXJzZSxcbiAgc3BsaXQ6IF9zcGxpdCxcbiAgc3RhcnRzX3dpdGhfX3FtX18sXG4gIHRvX2F0b20sXG4gIHRvX2NoYXJfbGlzdCxcbiAgdG9fZXhpc3RpbmdfYXRvbSxcbiAgdG9fZmxvYXQsXG4gIHRvX2ludGVnZXIsXG4gIHVwY2FzZSxcbiAgdmFsaWRfY2hhcmFjdGVyX19xbV9fLFxuICBDaGFyczogX0NoYXJzXG59O1xuXG5sZXQgQ2hhcnMgPSBLZXJuZWwuZGVmcHJvdG9jb2woe1xuICB0b19jaGFyX2xpc3Q6IGZ1bmN0aW9uICh0aGluZykge31cbn0pO1xuXG5LZXJuZWwuZGVmaW1wbChDaGFycywgS2VybmVsLmlzX2JpdHN0cmluZywge1xuICB0b19jaGFyX2xpc3Q6IGZ1bmN0aW9uICh0aGluZykge1xuICAgIGlmIChLZXJuZWwuaXNfYmluYXJ5KHRoaW5nKSkge1xuICAgICAgcmV0dXJuIF9TdHJpbmcudG9fY2hhcl9saXN0KHRoaW5nKTtcbiAgICB9XG5cbiAgICByZXR1cm4gdGhpbmcudG9TdHJpbmcoKTtcbiAgfVxufSk7XG5cbktlcm5lbC5kZWZpbXBsKENoYXJzLCBLZXJuZWwuaXNfYXRvbSwge1xuICB0b19jaGFyX2xpc3Q6IGZ1bmN0aW9uICh0aGluZykge1xuICAgIHJldHVybiBBdG9tLnRvX2NoYXJfbGlzdCh0aGluZyk7XG4gIH1cbn0pO1xuXG5LZXJuZWwuZGVmaW1wbChDaGFycywgS2VybmVsLmlzX2ludGVnZXIsIHtcbiAgdG9fY2hhcl9saXN0OiBmdW5jdGlvbiAodGhpbmcpIHtcbiAgICByZXR1cm4gSW50ZWdlci50b19jaGFyX2xpc3QodGhpbmcpO1xuICB9XG59KTtcblxuS2VybmVsLmRlZmltcGwoQ2hhcnMsIEtlcm5lbC5pc19saXN0LCB7XG4gIHRvX2NoYXJfbGlzdDogZnVuY3Rpb24gKHRoaW5nKSB7XG4gICAgcmV0dXJuIHRoaW5nO1xuICB9XG59KTtcblxubGV0IExpc3QgPSB7fTtcblxuTGlzdC5DaGFycyA9IENoYXJzO1xuXG5MaXN0LmRlbGV0ZSA9IGZ1bmN0aW9uIChsaXN0LCBpdGVtKSB7XG4gIGxldCBuZXdfdmFsdWUgPSBbXTtcbiAgbGV0IHZhbHVlX2ZvdW5kID0gZmFsc2U7XG5cbiAgZm9yIChsZXQgeCBvZiBsaXN0KSB7XG4gICAgaWYgKHggPT09IGl0ZW0gJiYgdmFsdWVfZm91bmQgIT09IGZhbHNlKSB7XG4gICAgICBuZXdfdmFsdWUucHVzaCh4KTtcbiAgICAgIHZhbHVlX2ZvdW5kID0gdHJ1ZTtcbiAgICB9IGVsc2UgaWYgKHggIT09IGl0ZW0pIHtcbiAgICAgIG5ld192YWx1ZS5wdXNoKHgpO1xuICAgIH1cbiAgfVxuXG4gIHJldHVybiBLZXJuZWwuU3BlY2lhbEZvcm1zLmxpc3QoLi4ubmV3X3ZhbHVlKTtcbn07XG5cbkxpc3QuZGVsZXRlX2F0ID0gZnVuY3Rpb24gKGxpc3QsIGluZGV4KSB7XG4gIGxldCBuZXdfdmFsdWUgPSBbXTtcblxuICBmb3IgKGxldCBpID0gMDsgaSA8IGxpc3QubGVuZ3RoOyBpKyspIHtcbiAgICBpZiAoaSAhPT0gaW5kZXgpIHtcbiAgICAgIG5ld192YWx1ZS5wdXNoKGxpc3RbaV0pO1xuICAgIH1cbiAgfVxuXG4gIHJldHVybiBLZXJuZWwuU3BlY2lhbEZvcm1zLmxpc3QoLi4ubmV3X3ZhbHVlKTtcbn07XG5cbkxpc3QuZHVwbGljYXRlID0gZnVuY3Rpb24gKGVsZW0sIG4pIHtcbiAgbGV0IG5ld192YWx1ZSA9IFtdO1xuXG4gIGZvciAodmFyIGkgPSAwOyBpIDwgbjsgaSsrKSB7XG4gICAgbmV3X3ZhbHVlLnB1c2goZWxlbSk7XG4gIH1cblxuICByZXR1cm4gS2VybmVsLlNwZWNpYWxGb3Jtcy5saXN0KC4uLm5ld192YWx1ZSk7XG59O1xuXG5MaXN0LmZpcnN0ID0gZnVuY3Rpb24gKGxpc3QpIHtcbiAgcmV0dXJuIGxpc3RbMF07XG59O1xuXG5MaXN0LmZsYXR0ZW4gPSBmdW5jdGlvbiAobGlzdCwgdGFpbCA9IEtlcm5lbC5TcGVjaWFsRm9ybXMubGlzdCgpKSB7XG4gIGxldCBuZXdfdmFsdWUgPSBbXTtcblxuICBmb3IgKGxldCB4IG9mIGxpc3QpIHtcbiAgICBpZiAoS2VybmVsLmlzX2xpc3QoeCkpIHtcbiAgICAgIG5ld192YWx1ZSA9IG5ld192YWx1ZS5jb25jYXQoTGlzdC5mbGF0dGVuKHgpKTtcbiAgICB9IGVsc2Uge1xuICAgICAgbmV3X3ZhbHVlLnB1c2goeCk7XG4gICAgfVxuICB9XG5cbiAgbmV3X3ZhbHVlID0gbmV3X3ZhbHVlLmNvbmNhdCh0YWlsKTtcblxuICByZXR1cm4gS2VybmVsLlNwZWNpYWxGb3Jtcy5saXN0KC4uLm5ld192YWx1ZSk7XG59O1xuXG5MaXN0LmZvbGRsID0gZnVuY3Rpb24gKGxpc3QsIGFjYywgZnVuYykge1xuICByZXR1cm4gbGlzdC5yZWR1Y2UoZnVuYywgYWNjKTtcbn07XG5cbkxpc3QuZm9sZHIgPSBmdW5jdGlvbiAobGlzdCwgYWNjLCBmdW5jKSB7XG4gIGxldCBuZXdfYWNjID0gYWNjO1xuXG4gIGZvciAodmFyIGkgPSBsaXN0Lmxlbmd0aCAtIDE7IGkgPj0gMDsgaS0tKSB7XG4gICAgbmV3X2FjYyA9IGZ1bmMobGlzdFtpXSwgbmV3X2FjYyk7XG4gIH1cblxuICByZXR1cm4gbmV3X2FjYztcbn07XG5cbkxpc3QuaW5zZXJ0X2F0ID0gZnVuY3Rpb24gKGxpc3QsIGluZGV4LCB2YWx1ZSkge1xuICBsZXQgbmV3X3ZhbHVlID0gW107XG5cbiAgZm9yIChsZXQgaSA9IDA7IGkgPCBsaXN0Lmxlbmd0aDsgaSsrKSB7XG4gICAgaWYgKGkgPT09IGluZGV4KSB7XG4gICAgICBuZXdfdmFsdWUucHVzaCh2YWx1ZSk7XG4gICAgICBuZXdfdmFsdWUucHVzaChsaXN0W2ldKTtcbiAgICB9IGVsc2Uge1xuICAgICAgbmV3X3ZhbHVlLnB1c2gobGlzdFtpXSk7XG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIEtlcm5lbC5TcGVjaWFsRm9ybXMubGlzdCguLi5uZXdfdmFsdWUpO1xufTtcblxuTGlzdC5rZXlkZWxldGUgPSBmdW5jdGlvbiAobGlzdCwga2V5LCBwb3NpdGlvbikge1xuICBsZXQgbmV3X2xpc3QgPSBbXTtcblxuICBmb3IgKGxldCBpID0gMDsgaSA8IGxpc3QubGVuZ3RoOyBpKyspIHtcbiAgICBpZiAoIUtlcm5lbC5tYXRjaF9fcW1hcmtfXyhsaXN0W2ldW3Bvc2l0aW9uXSwga2V5KSkge1xuICAgICAgbmV3X2xpc3QucHVzaChsaXN0W2ldKTtcbiAgICB9XG4gIH1cblxuICByZXR1cm4gS2VybmVsLlNwZWNpYWxGb3Jtcy5saXN0KC4uLm5ld19saXN0KTtcbn07XG5cbkxpc3Qua2V5ZmluZCA9IGZ1bmN0aW9uIChsaXN0LCBrZXksIHBvc2l0aW9uLCBfZGVmYXVsdCA9IG51bGwpIHtcblxuICBmb3IgKGxldCBpID0gMDsgaSA8IGxpc3QubGVuZ3RoOyBpKyspIHtcbiAgICBpZiAoS2VybmVsLm1hdGNoX19xbWFya19fKGxpc3RbaV1bcG9zaXRpb25dLCBrZXkpKSB7XG4gICAgICByZXR1cm4gbGlzdFtpXTtcbiAgICB9XG4gIH1cblxuICByZXR1cm4gX2RlZmF1bHQ7XG59O1xuXG5MaXN0LmtleW1lbWJlcl9fcW1hcmtfXyA9IGZ1bmN0aW9uIChsaXN0LCBrZXksIHBvc2l0aW9uKSB7XG5cbiAgZm9yIChsZXQgaSA9IDA7IGkgPCBsaXN0Lmxlbmd0aDsgaSsrKSB7XG4gICAgaWYgKEtlcm5lbC5tYXRjaF9fcW1hcmtfXyhsaXN0W2ldW3Bvc2l0aW9uXSwga2V5KSkge1xuICAgICAgcmV0dXJuIHRydWU7XG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIGZhbHNlO1xufTtcblxuTGlzdC5rZXlyZXBsYWNlID0gZnVuY3Rpb24gKGxpc3QsIGtleSwgcG9zaXRpb24sIG5ld190dXBsZSkge1xuICBsZXQgbmV3X2xpc3QgPSBbXTtcblxuICBmb3IgKGxldCBpID0gMDsgaSA8IGxpc3QubGVuZ3RoOyBpKyspIHtcbiAgICBpZiAoIUtlcm5lbC5tYXRjaF9fcW1hcmtfXyhsaXN0W2ldW3Bvc2l0aW9uXSwga2V5KSkge1xuICAgICAgbmV3X2xpc3QucHVzaChsaXN0W2ldKTtcbiAgICB9IGVsc2Uge1xuICAgICAgbmV3X2xpc3QucHVzaChuZXdfdHVwbGUpO1xuICAgIH1cbiAgfVxuXG4gIHJldHVybiBLZXJuZWwuU3BlY2lhbEZvcm1zLmxpc3QoLi4ubmV3X2xpc3QpO1xufTtcblxuTGlzdC5rZXlzb3J0ID0gZnVuY3Rpb24gKGxpc3QsIHBvc2l0aW9uKSB7XG4gIGxldCBuZXdfbGlzdCA9IGxpc3Q7XG5cbiAgbmV3X2xpc3Quc29ydChmdW5jdGlvbiAoYSwgYikge1xuICAgIGlmIChwb3NpdGlvbiA9PT0gMCkge1xuICAgICAgaWYgKGFbcG9zaXRpb25dLnZhbHVlIDwgYltwb3NpdGlvbl0udmFsdWUpIHtcbiAgICAgICAgcmV0dXJuIC0xO1xuICAgICAgfVxuXG4gICAgICBpZiAoYVtwb3NpdGlvbl0udmFsdWUgPiBiW3Bvc2l0aW9uXS52YWx1ZSkge1xuICAgICAgICByZXR1cm4gMTtcbiAgICAgIH1cblxuICAgICAgcmV0dXJuIDA7XG4gICAgfSBlbHNlIHtcbiAgICAgIGlmIChhW3Bvc2l0aW9uXSA8IGJbcG9zaXRpb25dKSB7XG4gICAgICAgIHJldHVybiAtMTtcbiAgICAgIH1cblxuICAgICAgaWYgKGFbcG9zaXRpb25dID4gYltwb3NpdGlvbl0pIHtcbiAgICAgICAgcmV0dXJuIDE7XG4gICAgICB9XG5cbiAgICAgIHJldHVybiAwO1xuICAgIH1cbiAgfSk7XG5cbiAgcmV0dXJuIEtlcm5lbC5TcGVjaWFsRm9ybXMubGlzdCguLi5uZXdfbGlzdCk7XG59O1xuXG5MaXN0LmtleXN0b3JlID0gZnVuY3Rpb24gKGxpc3QsIGtleSwgcG9zaXRpb24sIG5ld190dXBsZSkge1xuICBsZXQgbmV3X2xpc3QgPSBbXTtcbiAgbGV0IHJlcGxhY2VkID0gZmFsc2U7XG5cbiAgZm9yIChsZXQgaSA9IDA7IGkgPCBsaXN0Lmxlbmd0aDsgaSsrKSB7XG4gICAgaWYgKCFLZXJuZWwubWF0Y2hfX3FtYXJrX18obGlzdFtpXVtwb3NpdGlvbl0sIGtleSkpIHtcbiAgICAgIG5ld19saXN0LnB1c2gobGlzdFtpXSk7XG4gICAgfSBlbHNlIHtcbiAgICAgIG5ld19saXN0LnB1c2gobmV3X3R1cGxlKTtcbiAgICAgIHJlcGxhY2VkID0gdHJ1ZTtcbiAgICB9XG4gIH1cblxuICBpZiAoIXJlcGxhY2VkKSB7XG4gICAgbmV3X2xpc3QucHVzaChuZXdfdHVwbGUpO1xuICB9XG5cbiAgcmV0dXJuIEtlcm5lbC5TcGVjaWFsRm9ybXMubGlzdCguLi5uZXdfbGlzdCk7XG59O1xuXG5MaXN0Lmxhc3QgPSBmdW5jdGlvbiAobGlzdCkge1xuICByZXR1cm4gbGlzdFtsaXN0Lmxlbmd0aCAtIDFdO1xufTtcblxuTGlzdC5yZXBsYWNlX2F0ID0gZnVuY3Rpb24gKGxpc3QsIGluZGV4LCB2YWx1ZSkge1xuICBsZXQgbmV3X3ZhbHVlID0gW107XG5cbiAgZm9yIChsZXQgaSA9IDA7IGkgPCBsaXN0Lmxlbmd0aDsgaSsrKSB7XG4gICAgaWYgKGkgPT09IGluZGV4KSB7XG4gICAgICBuZXdfdmFsdWUucHVzaCh2YWx1ZSk7XG4gICAgfSBlbHNlIHtcbiAgICAgIG5ld192YWx1ZS5wdXNoKGxpc3RbaV0pO1xuICAgIH1cbiAgfVxuXG4gIHJldHVybiBLZXJuZWwuU3BlY2lhbEZvcm1zLmxpc3QoLi4ubmV3X3ZhbHVlKTtcbn07XG5cbkxpc3QudXBkYXRlX2F0ID0gZnVuY3Rpb24gKGxpc3QsIGluZGV4LCBmdW4pIHtcbiAgbGV0IG5ld192YWx1ZSA9IFtdO1xuXG4gIGZvciAobGV0IGkgPSAwOyBpIDwgbGlzdC5jb3VudCgpOyBpKyspIHtcbiAgICBpZiAoaSA9PT0gaW5kZXgpIHtcbiAgICAgIG5ld192YWx1ZS5wdXNoKGZ1bihsaXN0LmdldChpKSkpO1xuICAgIH0gZWxzZSB7XG4gICAgICBuZXdfdmFsdWUucHVzaChsaXN0LmdldChpKSk7XG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIG5ld192YWx1ZTtcbn07XG5cbkxpc3Qud3JhcCA9IGZ1bmN0aW9uIChsaXN0KSB7XG4gIGlmIChLZXJuZWwuaXNfbGlzdChsaXN0KSkge1xuICAgIHJldHVybiBsaXN0O1xuICB9IGVsc2UgaWYgKGxpc3QgPT0gbnVsbCkge1xuICAgIHJldHVybiBLZXJuZWwuU3BlY2lhbEZvcm1zLmxpc3QoKTtcbiAgfSBlbHNlIHtcbiAgICByZXR1cm4gS2VybmVsLlNwZWNpYWxGb3Jtcy5saXN0KGxpc3QpO1xuICB9XG59O1xuXG5MaXN0LnppcCA9IGZ1bmN0aW9uIChsaXN0X29mX2xpc3RzKSB7XG4gIGlmIChsaXN0X29mX2xpc3RzLmxlbmd0aCA9PT0gMCkge1xuICAgIHJldHVybiBLZXJuZWwuU3BlY2lhbEZvcm1zLmxpc3QoKTtcbiAgfVxuXG4gIGxldCBuZXdfdmFsdWUgPSBbXTtcbiAgbGV0IHNtYWxsZXN0X2xlbmd0aCA9IGxpc3Rfb2ZfbGlzdHNbMF07XG5cbiAgZm9yIChsZXQgeCBvZiBsaXN0X29mX2xpc3RzKSB7XG4gICAgaWYgKHgubGVuZ3RoIDwgc21hbGxlc3RfbGVuZ3RoKSB7XG4gICAgICBzbWFsbGVzdF9sZW5ndGggPSB4Lmxlbmd0aDtcbiAgICB9XG4gIH1cblxuICBmb3IgKGxldCBpID0gMDsgaSA8IHNtYWxsZXN0X2xlbmd0aDsgaSsrKSB7XG4gICAgbGV0IGN1cnJlbnRfdmFsdWUgPSBbXTtcbiAgICBmb3IgKGxldCBqID0gMDsgaiA8IGxpc3Rfb2ZfbGlzdHMubGVuZ3RoOyBqKyspIHtcbiAgICAgIGN1cnJlbnRfdmFsdWUucHVzaChsaXN0X29mX2xpc3RzW2pdW2ldKTtcbiAgICB9XG5cbiAgICBuZXdfdmFsdWUucHVzaChLZXJuZWwuU3BlY2lhbEZvcm1zLnR1cGxlKC4uLmN1cnJlbnRfdmFsdWUpKTtcbiAgfVxuXG4gIHJldHVybiBLZXJuZWwuU3BlY2lhbEZvcm1zLmxpc3QoLi4ubmV3X3ZhbHVlKTtcbn07XG5cbkxpc3QudG9fdHVwbGUgPSBmdW5jdGlvbiAobGlzdCkge1xuICByZXR1cm4gS2VybmVsLlNwZWNpYWxGb3Jtcy50dXBsZS5hcHBseShudWxsLCBsaXN0KTtcbn07XG5cbkxpc3QuYXBwZW5kID0gZnVuY3Rpb24gKGxpc3QsIHZhbHVlKSB7XG4gIHJldHVybiBLZXJuZWwuU3BlY2lhbEZvcm1zLmxpc3QoLi4ubGlzdC5jb25jYXQoW3ZhbHVlXSkpO1xufTtcblxuTGlzdC5wcmVwZW5kID0gZnVuY3Rpb24gKGxpc3QsIHZhbHVlKSB7XG4gIHJldHVybiBLZXJuZWwuU3BlY2lhbEZvcm1zLmxpc3QoLi4uW3ZhbHVlXS5jb25jYXQobGlzdCkpO1xufTtcblxuTGlzdC5jb25jYXQgPSBmdW5jdGlvbiAobGVmdCwgcmlnaHQpIHtcbiAgcmV0dXJuIGxlZnQuY29uY2F0KHJpZ2h0KTtcbn07XG5cbmNsYXNzIFNpZ25hbCB7XG5cbiAgY29uc3RydWN0b3IoKSB7XG4gICAgdGhpcy5iaW5kaW5ncyA9IFNwZWNpYWxGb3Jtcy5saXN0KCk7XG4gIH1cblxuICBhZGQobGlzdGVuZXIsIGNvbnRleHQgPSB0aGlzKSB7XG4gICAgdGhpcy5iaW5kaW5ncyA9IExpc3QuYXBwZW5kKHRoaXMuYmluZGluZ3MsIG5ldyBTaWduYWxCaW5kaW5nKHRoaXMsIGxpc3RlbmVyLCBjb250ZXh0KSk7XG4gIH1cblxuICByZW1vdmUobGlzdGVuZXIpIHtcbiAgICB0aGlzLmJpbmRpbmdzID0gRW51bS5maWx0ZXIodGhpcy5iaW5kaW5ncywgZnVuY3Rpb24gKGJpbmRpbmcpIHtcbiAgICAgIHJldHVybiBiaW5kaW5nLmxpc3RlbmVyICE9PSBsaXN0ZW5lcjtcbiAgICB9KTtcbiAgfVxuXG4gIGRpc3BhdGNoKC4uLnBhcmFtcykge1xuICAgIGZvciAobGV0IGJpbmRpbmcgb2YgdGhpcy5iaW5kaW5ncykge1xuICAgICAgYmluZGluZy5leGVjdXRlKC4uLnBhcmFtcyk7XG4gICAgfVxuICB9XG5cbiAgZGlzcG9zZSgpIHtcbiAgICBmb3IgKGxldCBiaW5kaW5nIG9mIHRoaXMuYmluZGluZ3MpIHtcbiAgICAgIGJpbmRpbmcuZGlzcG9zZSgpO1xuICAgIH1cblxuICAgIHRoaXMuYmluZGluZ3MgPSBudWxsO1xuICB9XG59XG5cbmNsYXNzIFNpZ25hbEJpbmRpbmcge1xuXG4gIGNvbnN0cnVjdG9yKHNpZ25hbCwgbGlzdGVuZXIsIGNvbnRleHQpIHtcbiAgICB0aGlzLmxpc3RlbmVyID0gbGlzdGVuZXI7XG4gICAgdGhpcy5zaWduYWwgPSBzaWduYWw7XG4gICAgdGhpcy5jb250ZXh0ID0gY29udGV4dDtcbiAgfVxuXG4gIGV4ZWN1dGUoLi4ucGFyYW1zKSB7XG4gICAgdGhpcy5saXN0ZW5lci5hcHBseSh0aGlzLmNvbnRleHQsIHBhcmFtcyk7XG4gIH1cblxuICBkaXNwb3NlKCkge1xuICAgIHRoaXMubGlzdGVuZXIgPSBudWxsO1xuICAgIHRoaXMuc2lnbmFsID0gbnVsbDtcbiAgICB0aGlzLmNvbnRleHQgPSBudWxsO1xuICB9XG59XG5cbmZ1bmN0aW9uIF9fdXBkYXRlKG1hcCwga2V5LCB2YWx1ZSkge1xuICBsZXQgbSA9IG5ldyBNYXAobWFwKTtcbiAgbS5zZXQoa2V5LCB2YWx1ZSk7XG4gIHJldHVybiBtO1xufVxuXG5mdW5jdGlvbiByZW1vdmUobWFwLCBrZXkpIHtcbiAgbGV0IG0gPSBuZXcgTWFwKG1hcCk7XG4gIG0uZGVsZXRlKGtleSk7XG4gIHJldHVybiBtO1xufVxuXG5jbGFzcyBNYWlsQm94IHtcblxuICBjb25zdHJ1Y3Rvcihjb250ZXh0ID0gdGhpcykge1xuICAgIHRoaXMuc2lnbmFsID0gbmV3IFNpZ25hbCgpO1xuICAgIHRoaXMuc2lnbmFsLmFkZCgoLi4ucGFyYW1zKSA9PiB0aGlzLm1lc3NhZ2VzID0gdGhpcy5tZXNzYWdlcy5jb25jYXQocGFyYW1zKSwgY29udGV4dCk7XG4gICAgdGhpcy5tZXNzYWdlcyA9IFtdO1xuICB9XG5cbiAgcmVjZWl2ZSguLi5tZXNzYWdlcykge1xuICAgIHRoaXMuc2lnbmFsLmRpc3BhdGNoKC4uLm1lc3NhZ2VzKTtcbiAgfVxuXG4gIHBlZWsoKSB7XG4gICAgaWYgKHRoaXMubWVzc2FnZXMubGVuZ3RoID09PSAwKSB7XG4gICAgICByZXR1cm4gbnVsbDtcbiAgICB9XG5cbiAgICByZXR1cm4gdGhpcy5tZXNzYWdlc1swXTtcbiAgfVxuXG4gIHJlYWQoKSB7XG4gICAgbGV0IHJlc3VsdCA9IHRoaXMubWVzc2FnZXNbMF07XG4gICAgdGhpcy5tZXNzYWdlcyA9IHRoaXMubWVzc2FnZXMuc2xpY2UoMSk7XG5cbiAgICByZXR1cm4gcmVzdWx0O1xuICB9XG5cbiAgYWRkX3N1YnNjcmliZXIoZm4sIGNvbnRleHQgPSB0aGlzKSB7XG4gICAgdGhpcy5zaWduYWwuYWRkKGZuLCBjb250ZXh0KTtcbiAgfVxuXG4gIHJlbW92ZV9zdWJzY3JpYmVyKGZuKSB7XG4gICAgdGhpcy5zaWduYWwucmVtb3ZlKGZuKTtcbiAgfVxuXG4gIGRpc3Bvc2UoKSB7XG4gICAgdGhpcy5zaWduYWwuZGlzcG9zZSgpO1xuICAgIHRoaXMubWVzc2FnZXMgPSBudWxsO1xuICB9XG59XG5cbmNsYXNzIFBvc3RPZmZpY2Uge1xuXG4gIGNvbnN0cnVjdG9yKCkge1xuICAgIHRoaXMubWFpbGJveGVzID0gbmV3IE1hcCgpO1xuICB9XG5cbiAgc2VuZChhZGRyZXNzLCBtZXNzYWdlKSB7XG4gICAgdGhpcy5tYWlsYm94ZXMuZ2V0KGFkZHJlc3MpLnJlY2VpdmUobWVzc2FnZSk7XG4gIH1cblxuICByZWNlaXZlKGFkZHJlc3MpIHtcbiAgICByZXR1cm4gdGhpcy5tYWlsYm94ZXMuZ2V0KGFkZHJlc3MpLnJlYWQoKTtcbiAgfVxuXG4gIHBlZWsoYWRkcmVzcykge1xuICAgIHJldHVybiB0aGlzLm1haWxib3hlcy5nZXQoYWRkcmVzcykucGVlaygpO1xuICB9XG5cbiAgYWRkX21haWxib3goYWRkcmVzcyA9IFN5bWJvbCgpLCBjb250ZXh0ID0gdGhpcykge1xuICAgIHRoaXMubWFpbGJveGVzID0gX191cGRhdGUodGhpcy5tYWlsYm94ZXMsIGFkZHJlc3MsIG5ldyBNYWlsQm94KCkpO1xuICAgIHJldHVybiBhZGRyZXNzO1xuICB9XG5cbiAgcmVtb3ZlX21haWxib3goYWRkcmVzcykge1xuICAgIHRoaXMubWFpbGJveGVzLmdldChhZGRyZXNzKS5kaXNwb3NlKCk7XG4gICAgdGhpcy5tYWlsYm94ZXMgPSByZW1vdmUodGhpcy5tYWlsYm94ZXMsIGFkZHJlc3MpO1xuICB9XG5cbiAgc3Vic2NyaWJlKGFkZHJlc3MsIHN1YnNjcmlidGlvbl9mbiwgY29udGV4dCA9IHRoaXMpIHtcbiAgICB0aGlzLm1haWxib3hlcy5nZXQoYWRkcmVzcykuYWRkX3N1YnNjcmliZXIoc3Vic2NyaWJ0aW9uX2ZuLCBjb250ZXh0KTtcbiAgfVxuXG4gIHVuc3Vic2NyaWJlKGFkZHJlc3MsIHN1YnNjcmlidGlvbl9mbikge1xuICAgIHRoaXMubWFpbGJveGVzLmdldChhZGRyZXNzKS5yZW1vdmVfc3Vic2NyaWJlcihzdWJzY3JpYnRpb25fZm4pO1xuICB9XG59XG5cbmZ1bmN0aW9uIGNhbGxfcHJvcGVydHkoaXRlbSwgcHJvcGVydHkpIHtcbiAgaWYgKHByb3BlcnR5IGluIGl0ZW0pIHtcbiAgICBpdGVtW3Byb3BlcnR5XTtcbiAgICBpZiAoaXRlbVtwcm9wZXJ0eV0gaW5zdGFuY2VvZiBGdW5jdGlvbikge1xuICAgICAgcmV0dXJuIGl0ZW1bcHJvcGVydHldKCk7XG4gICAgfSBlbHNlIHtcbiAgICAgIHJldHVybiBpdGVtW3Byb3BlcnR5XTtcbiAgICB9XG4gIH0gZWxzZSBpZiAoU3ltYm9sLmZvcihwcm9wZXJ0eSkgaW4gaXRlbSkge1xuICAgIGxldCBwcm9wID0gU3ltYm9sLmZvcihwcm9wZXJ0eSk7XG4gICAgaWYgKGl0ZW1bcHJvcF0gaW5zdGFuY2VvZiBGdW5jdGlvbikge1xuICAgICAgcmV0dXJuIGl0ZW1bcHJvcF0oKTtcbiAgICB9IGVsc2Uge1xuICAgICAgcmV0dXJuIGl0ZW1bcHJvcF07XG4gICAgfVxuICB9XG5cbiAgdGhyb3cgbmV3IEVycm9yKGBQcm9wZXJ0eSAkeyBwcm9wZXJ0eSB9IG5vdCBmb3VuZCBpbiAkeyBpdGVtIH1gKTtcbn1cblxudmFyIEpTID0ge1xuICBjYWxsX3Byb3BlcnR5XG59O1xuXG5sZXQgUmFuZ2UgPSBmdW5jdGlvbiAoX2ZpcnN0LCBfbGFzdCkge1xuICBpZiAoISh0aGlzIGluc3RhbmNlb2YgUmFuZ2UpKSB7XG4gICAgcmV0dXJuIG5ldyBSYW5nZShfZmlyc3QsIF9sYXN0KTtcbiAgfVxuXG4gIHRoaXMuZmlyc3QgPSBmdW5jdGlvbiAoKSB7XG4gICAgcmV0dXJuIF9maXJzdDtcbiAgfTtcblxuICB0aGlzLmxhc3QgPSBmdW5jdGlvbiAoKSB7XG4gICAgcmV0dXJuIF9sYXN0O1xuICB9O1xuXG4gIGxldCBfcmFuZ2UgPSBbXTtcblxuICBmb3IgKGxldCBpID0gX2ZpcnN0OyBpIDw9IF9sYXN0OyBpKyspIHtcbiAgICBfcmFuZ2UucHVzaChpKTtcbiAgfVxuXG4gIF9yYW5nZSA9IE9iamVjdC5mcmVlemUoX3JhbmdlKTtcblxuICB0aGlzLnZhbHVlID0gZnVuY3Rpb24gKCkge1xuICAgIHJldHVybiBfcmFuZ2U7XG4gIH07XG5cbiAgdGhpcy5sZW5ndGggPSBmdW5jdGlvbiAoKSB7XG4gICAgcmV0dXJuIF9yYW5nZS5sZW5ndGg7XG4gIH07XG5cbiAgcmV0dXJuIHRoaXM7XG59O1xuXG5SYW5nZS5wcm90b3R5cGVbU3ltYm9sLml0ZXJhdG9yXSA9IGZ1bmN0aW9uICgpIHtcbiAgcmV0dXJuIHRoaXMudmFsdWUoKVtTeW1ib2wuaXRlcmF0b3JdKCk7XG59O1xuXG5SYW5nZS5uZXcgPSBmdW5jdGlvbiAoZmlyc3QsIGxhc3QpIHtcbiAgcmV0dXJuIFJhbmdlKGZpcnN0LCBsYXN0KTtcbn07XG5cblJhbmdlLnJhbmdlX19xbWFya19fID0gZnVuY3Rpb24gKHJhbmdlKSB7XG4gIHJldHVybiByYW5nZSBpbnN0YW5jZW9mIFJhbmdlO1xufTtcblxubGV0IEtleXdvcmQgPSB7fTtcblxuS2V5d29yZC5oYXNfa2V5X19xbV9fID0gZnVuY3Rpb24gKGtleXdvcmRzLCBrZXkpIHtcbiAgZm9yIChsZXQga2V5d29yZCBvZiBrZXl3b3Jkcykge1xuICAgIGlmIChLZXJuZWwuZWxlbShrZXl3b3JkLCAwKSA9PSBrZXkpIHtcbiAgICAgIHJldHVybiB0cnVlO1xuICAgIH1cbiAgfVxuXG4gIHJldHVybiBmYWxzZTtcbn07XG5cbktleXdvcmQuZ2V0ID0gZnVuY3Rpb24gKGtleXdvcmRzLCBrZXksIHRoZV9kZWZhdWx0ID0gbnVsbCkge1xuICBmb3IgKGxldCBrZXl3b3JkIG9mIGtleXdvcmRzKSB7XG4gICAgaWYgKEtlcm5lbC5lbGVtKGtleXdvcmQsIDApID09IGtleSkge1xuICAgICAgcmV0dXJuIEtlcm5lbC5lbGVtKGtleXdvcmQsIDEpO1xuICAgIH1cbiAgfVxuXG4gIHJldHVybiB0aGVfZGVmYXVsdDtcbn07XG5cbmxldCBBZ2VudCA9IHt9O1xuXG5BZ2VudC5zdGFydCA9IGZ1bmN0aW9uIChmdW4sIG9wdGlvbnMgPSBbXSkge1xuICBjb25zdCBuYW1lID0gS2V5d29yZC5oYXNfa2V5X19xbV9fKG9wdGlvbnMsIEtlcm5lbC5TcGVjaWFsRm9ybXMuYXRvbSgnbmFtZScpKSA/IEtleXdvcmQuZ2V0KG9wdGlvbnMsIEtlcm5lbC5TcGVjaWFsRm9ybXMuYXRvbSgnbmFtZScpKSA6IFN5bWJvbCgpO1xuXG4gIHNlbGYucG9zdF9vZmZpY2UuYWRkX21haWxib3gobmFtZSk7XG4gIHNlbGYucG9zdF9vZmZpY2Uuc2VuZChuYW1lLCBmdW4oKSk7XG5cbiAgcmV0dXJuIEtlcm5lbC5TcGVjaWFsRm9ybXMudHVwbGUoS2VybmVsLlNwZWNpYWxGb3Jtcy5hdG9tKCdvaycpLCBuYW1lKTtcbn07XG5cbkFnZW50LnN0b3AgPSBmdW5jdGlvbiAoYWdlbnQsIHRpbWVvdXQgPSA1MDAwKSB7XG4gIHNlbGYucG9zdF9vZmZpY2UucmVtb3ZlX21haWxib3goYWdlbnQpO1xuICByZXR1cm4gS2VybmVsLlNwZWNpYWxGb3Jtcy5hdG9tKCdvaycpO1xufTtcblxuQWdlbnQudXBkYXRlID0gZnVuY3Rpb24gKGFnZW50LCBmdW4sIHRpbWVvdXQgPSA1MDAwKSB7XG5cbiAgY29uc3QgY3VycmVudF9zdGF0ZSA9IHNlbGYucG9zdF9vZmZpY2UucmVjZWl2ZShhZ2VudCk7XG4gIHNlbGYucG9zdF9vZmZpY2Uuc2VuZChhZ2VudCwgZnVuKGN1cnJlbnRfc3RhdGUpKTtcblxuICByZXR1cm4gS2VybmVsLlNwZWNpYWxGb3Jtcy5hdG9tKCdvaycpO1xufTtcblxuQWdlbnQuZ2V0ID0gZnVuY3Rpb24gKGFnZW50LCBmdW4sIHRpbWVvdXQgPSA1MDAwKSB7XG4gIHJldHVybiBmdW4oc2VsZi5wb3N0X29mZmljZS5wZWVrKGFnZW50KSk7XG59O1xuXG5BZ2VudC5nZXRfYW5kX3VwZGF0ZSA9IGZ1bmN0aW9uIChhZ2VudCwgZnVuLCB0aW1lb3V0ID0gNTAwMCkge1xuXG4gIGNvbnN0IGdldF9hbmRfdXBkYXRlX3R1cGxlID0gZnVuKHNlbGYucG9zdF9vZmZpY2UucmVjZWl2ZShhZ2VudCkpO1xuICBzZWxmLnBvc3Rfb2ZmaWNlLnNlbmQoYWdlbnQsIEtlcm5lbC5lbGVtKGdldF9hbmRfdXBkYXRlX3R1cGxlLCAxKSk7XG5cbiAgcmV0dXJuIEtlcm5lbC5lbGVtKGdldF9hbmRfdXBkYXRlX3R1cGxlLCAwKTtcbn07XG5cbi8vaHR0cHM6Ly9kZXZlbG9wZXIubW96aWxsYS5vcmcvZW4tVVMvZG9jcy9XZWIvQVBJL1dpbmRvd0Jhc2U2NC9CYXNlNjRfZW5jb2RpbmdfYW5kX2RlY29kaW5nI1NvbHV0aW9uXzJfJUUyJTgwJTkzX3Jld3JpdGVfdGhlX0RPTXNfYXRvYigpX2FuZF9idG9hKClfdXNpbmdfSmF2YVNjcmlwdCdzX1R5cGVkQXJyYXlzX2FuZF9VVEYtOFxuZnVuY3Rpb24gYjY0RW5jb2RlVW5pY29kZShzdHIpIHtcbiAgcmV0dXJuIGJ0b2EoZW5jb2RlVVJJQ29tcG9uZW50KHN0cikucmVwbGFjZSgvJShbMC05QS1GXXsyfSkvZywgZnVuY3Rpb24gKG1hdGNoLCBwMSkge1xuICAgIHJldHVybiBTdHJpbmcuZnJvbUNoYXJDb2RlKCcweCcgKyBwMSk7XG4gIH0pKTtcbn1cblxuZnVuY3Rpb24gZW5jb2RlNjQoZGF0YSkge1xuICByZXR1cm4gYjY0RW5jb2RlVW5pY29kZShkYXRhKTtcbn1cblxuZnVuY3Rpb24gZGVjb2RlNjQoZGF0YSkge1xuICB0cnkge1xuICAgIHJldHVybiBLZXJuZWwuU3BlY2lhbEZvcm1zLnR1cGxlKEtlcm5lbC5TcGVjaWFsRm9ybXMuYXRvbSgnb2snKSwgYXRvYihkYXRhKSk7XG4gIH0gY2F0Y2ggKGUpIHtcbiAgICByZXR1cm4gS2VybmVsLlNwZWNpYWxGb3Jtcy5hdG9tKCdlcnJvcicpO1xuICB9XG4gIHJldHVybiBidG9hKGRhdGEpO1xufVxuXG5mdW5jdGlvbiBkZWNvZGU2NF9fZW1fXyhkYXRhKSB7XG4gIHJldHVybiBhdG9iKGRhdGEpO1xufVxuXG52YXIgQmFzZSA9IHtcbiAgZW5jb2RlNjQsXG4gIGRlY29kZTY0LFxuICBkZWNvZGU2NF9fZW1fX1xufTtcblxuZnVuY3Rpb24gYm5vdChleHByKSB7XG4gIHJldHVybiB+ZXhwcjtcbn1cblxuZnVuY3Rpb24gYmFuZChsZWZ0LCByaWdodCkge1xuICByZXR1cm4gbGVmdCAmIHJpZ2h0O1xufVxuXG5mdW5jdGlvbiBib3IobGVmdCwgcmlnaHQpIHtcbiAgcmV0dXJuIGxlZnQgfCByaWdodDtcbn1cblxuZnVuY3Rpb24gYnNsKGxlZnQsIHJpZ2h0KSB7XG4gIHJldHVybiBsZWZ0IDw8IHJpZ2h0O1xufVxuXG5mdW5jdGlvbiBic3IobGVmdCwgcmlnaHQpIHtcbiAgcmV0dXJuIGxlZnQgPj4gcmlnaHQ7XG59XG5cbmZ1bmN0aW9uIGJ4b3IobGVmdCwgcmlnaHQpIHtcbiAgcmV0dXJuIGxlZnQgXiByaWdodDtcbn1cblxudmFyIEJpdHdpc2UgPSB7XG4gIGJub3QsXG4gIGJhbmQsXG4gIGJvcixcbiAgYnNsLFxuICBic3IsXG4gIGJ4b3Jcbn07XG5cbmxldCBFbnVtZXJhYmxlID0gS2VybmVsLmRlZnByb3RvY29sKHtcbiAgY291bnQ6IGZ1bmN0aW9uIChjb2xsZWN0aW9uKSB7fSxcbiAgbWVtYmVyX3FtYXJrX186IGZ1bmN0aW9uIChjb2xsZWN0aW9uLCB2YWx1ZSkge30sXG4gIHJlZHVjZTogZnVuY3Rpb24gKGNvbGxlY3Rpb24sIGFjYywgZnVuKSB7fVxufSk7XG5cbmxldCBDb2xsZWN0YWJsZSA9IEtlcm5lbC5kZWZwcm90b2NvbCh7XG4gIGludG86IGZ1bmN0aW9uIChjb2xsZWN0YWJsZSkge31cbn0pO1xuXG5sZXQgSW5zcGVjdCA9IEtlcm5lbC5kZWZwcm90b2NvbCh7XG4gIGluc3BlY3Q6IGZ1bmN0aW9uICh0aGluZywgb3B0cykge31cbn0pO1xuXG5mdW5jdGlvbiBfX19uZXdfXygpIHtcbiAgcmV0dXJuIFNwZWNpYWxGb3Jtcy5tYXAoe30pO1xufVxuXG5mdW5jdGlvbiBrZXlzKG1hcCkge1xuICByZXR1cm4gT2JqZWN0LmtleXMobWFwKTtcbn1cblxuZnVuY3Rpb24gX19zaXplKG1hcCkge1xuICByZXR1cm4ga2V5cyhtYXApLmxlbmd0aDtcbn1cblxuZnVuY3Rpb24gX190b19saXN0KG1hcCkge1xuICBsZXQgbWFwX2tleXMgPSBrZXlzKG1hcCk7XG4gIGxldCBsaXN0ID0gW107XG5cbiAgZm9yIChsZXQga2V5IG9mIG1hcF9rZXlzKSB7XG4gICAgbGlzdC5wdXNoKFNwZWNpYWxGb3Jtcy50dXBsZShrZXksIG1hcFtrZXldKSk7XG4gIH1cblxuICByZXR1cm4gU3BlY2lhbEZvcm1zLmxpc3QoLi4ubGlzdCk7XG59XG5cbmZ1bmN0aW9uIHZhbHVlcyhtYXApIHtcbiAgbGV0IG1hcF9rZXlzID0ga2V5cyhtYXApO1xuICBsZXQgbGlzdCA9IFtdO1xuXG4gIGZvciAobGV0IGtleSBvZiBtYXBfa2V5cykge1xuICAgIGxpc3QucHVzaChtYXBba2V5XSk7XG4gIH1cblxuICByZXR1cm4gU3BlY2lhbEZvcm1zLmxpc3QoLi4ubGlzdCk7XG59XG5cbmZ1bmN0aW9uIGZyb21fc3RydWN0KHN0cnVjdCkge1xuICBsZXQgbWFwID0gT2JqZWN0LmFzc2lnbih7fSwgc3RydWN0KTtcbiAgZGVsZXRlIG1hcFtTeW1ib2wuZm9yKFwiX19zdHJ1Y3RfX1wiKV07XG5cbiAgcmV0dXJuIFNwZWNpYWxGb3Jtcy5tYXAobWFwKTtcbn1cblxuZnVuY3Rpb24gX19fX2RlbGV0ZV9fKG1hcCwga2V5KSB7XG4gIGxldCBuZXdfbWFwID0gT2JqZWN0LmFzc2lnbih7fSwgbWFwKTtcblxuICBkZWxldGUgbmV3X21hcFtrZXldO1xuXG4gIHJldHVybiBTcGVjaWFsRm9ybXMubWFwKG5ld19tYXApO1xufVxuXG5mdW5jdGlvbiBkcm9wKG1hcCwga2V5cykge1xuICBsZXQgbmV3X21hcCA9IE9iamVjdC5hc3NpZ24oe30sIG1hcCk7XG5cbiAgZm9yIChsZXQga2V5IG9mIGtleXMpIHtcbiAgICBkZWxldGUgbmV3X21hcFtrZXldO1xuICB9XG5cbiAgcmV0dXJuIFNwZWNpYWxGb3Jtcy5tYXAobmV3X21hcCk7XG59XG5cbmZ1bmN0aW9uIF9fZXF1YWxfX3FtYXJrX18obWFwMSwgbWFwMikge1xuICByZXR1cm4gbWFwMSA9PT0gbWFwMjtcbn1cblxuZnVuY3Rpb24gZmV0Y2hfX2VtYXJrX18obWFwLCBrZXkpIHtcbiAgaWYgKGtleSBpbiBtYXApIHtcbiAgICByZXR1cm4gbWFwW2tleV07XG4gIH1cblxuICB0aHJvdyBuZXcgRXJyb3IoXCJLZXkgbm90IGZvdW5kLlwiKTtcbn1cblxuZnVuY3Rpb24gZmV0Y2gobWFwLCBrZXkpIHtcbiAgaWYgKGtleSBpbiBtYXApIHtcbiAgICByZXR1cm4gU3BlY2lhbEZvcm1zLnR1cGxlKFNwZWNpYWxGb3Jtcy5hdG9tKFwib2tcIiksIG1hcFtrZXldKTtcbiAgfVxuXG4gIHJldHVybiBTcGVjaWFsRm9ybXMuYXRvbShcImVycm9yXCIpO1xufVxuXG5mdW5jdGlvbiBoYXNfa2V5X19xbWFya19fKG1hcCwga2V5KSB7XG4gIHJldHVybiBrZXkgaW4gbWFwO1xufVxuXG5mdW5jdGlvbiBtZXJnZShtYXAxLCBtYXAyKSB7XG4gIHJldHVybiBTcGVjaWFsRm9ybXMubWFwX3VwZGF0ZShtYXAxLCBtYXAyKTtcbn1cblxuZnVuY3Rpb24gc3BsaXQobWFwLCBrZXlzKSB7XG4gIGxldCBzcGxpdDEgPSB7fTtcbiAgbGV0IHNwbGl0MiA9IHt9O1xuXG4gIGZvciAobGV0IGtleSBvZiBPYmplY3Qua2V5cyhtYXApKSB7XG4gICAgaWYgKGtleXMuaW5kZXhPZihrZXkpID4gLTEpIHtcbiAgICAgIHNwbGl0MVtrZXldID0gbWFwW2tleV07XG4gICAgfSBlbHNlIHtcbiAgICAgIHNwbGl0MltrZXldID0gbWFwW2tleV07XG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIFNwZWNpYWxGb3Jtcy50dXBsZShTcGVjaWFsRm9ybXMubWFwKHNwbGl0MSksIFNwZWNpYWxGb3Jtcy5tYXAoc3BsaXQyKSk7XG59XG5cbmZ1bmN0aW9uIHRha2UobWFwLCBrZXlzKSB7XG4gIGxldCBzcGxpdDEgPSB7fTtcblxuICBmb3IgKGxldCBrZXkgb2YgT2JqZWN0LmtleXMobWFwKSkge1xuICAgIGlmIChrZXlzLmluZGV4T2Yoa2V5KSA+IC0xKSB7XG4gICAgICBzcGxpdDFba2V5XSA9IG1hcFtrZXldO1xuICAgIH1cbiAgfVxuXG4gIHJldHVybiBTcGVjaWFsRm9ybXMubWFwKHNwbGl0MSk7XG59XG5cbmZ1bmN0aW9uIGRyb3AobWFwLCBrZXlzKSB7XG4gIGxldCBzcGxpdDEgPSB7fTtcblxuICBmb3IgKGxldCBrZXkgb2YgT2JqZWN0LmtleXMobWFwKSkge1xuICAgIGlmIChrZXlzLmluZGV4T2Yoa2V5KSA9PT0gLTEpIHtcbiAgICAgIHNwbGl0MVtrZXldID0gbWFwW2tleV07XG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIFNwZWNpYWxGb3Jtcy5tYXAoc3BsaXQxKTtcbn1cblxuZnVuY3Rpb24gcHV0X25ldyhtYXAsIGtleSwgdmFsdWUpIHtcbiAgaWYgKGtleSBpbiBtYXApIHtcbiAgICByZXR1cm4gbWFwO1xuICB9XG5cbiAgbGV0IG5ld19tYXAgPSBPYmplY3QuYXNzaWduKHt9LCBtYXApO1xuICBuZXdfbWFwW2tleV0gPSB2YWx1ZTtcblxuICByZXR1cm4gU3BlY2lhbEZvcm1zLm1hcChuZXdfbWFwKTtcbn1cblxuZnVuY3Rpb24gcHV0X25ld19sYXp5KG1hcCwga2V5LCBmdW4pIHtcbiAgaWYgKGtleSBpbiBtYXApIHtcbiAgICByZXR1cm4gbWFwO1xuICB9XG5cbiAgbGV0IG5ld19tYXAgPSBPYmplY3QuYXNzaWduKHt9LCBtYXApO1xuICBuZXdfbWFwW2tleV0gPSBmdW4oKTtcblxuICByZXR1cm4gU3BlY2lhbEZvcm1zLm1hcChuZXdfbWFwKTtcbn1cblxuZnVuY3Rpb24gZ2V0X2FuZF91cGRhdGUobWFwLCBrZXksIGZ1bikge1xuICBpZiAoa2V5IGluIG1hcCkge1xuICAgIHJldHVybiBtYXA7XG4gIH1cblxuICBsZXQgbmV3X21hcCA9IE9iamVjdC5hc3NpZ24oe30sIG1hcCk7XG4gIG5ld19tYXBba2V5XSA9IGZ1bihtYXBba2V5XSk7XG5cbiAgcmV0dXJuIFNwZWNpYWxGb3Jtcy5tYXAobmV3X21hcCk7XG59XG5cbmZ1bmN0aW9uIHBvcF9sYXp5KG1hcCwga2V5LCBmdW4pIHtcbiAgaWYgKCFrZXkgaW4gbWFwKSB7XG4gICAgcmV0dXJuIFNwZWNpYWxGb3Jtcy50dXBsZShmdW4oKSwgbWFwKTtcbiAgfVxuXG4gIGxldCBuZXdfbWFwID0gT2JqZWN0LmFzc2lnbih7fSwgbWFwKTtcbiAgbGV0IHZhbHVlID0gZnVuKG5ld19tYXBba2V5XSk7XG4gIGRlbGV0ZSBuZXdfbWFwW2tleV07XG5cbiAgcmV0dXJuIFNwZWNpYWxGb3Jtcy50dXBsZSh2YWx1ZSwgbmV3X21hcCk7XG59XG5cbmZ1bmN0aW9uIHBvcChtYXAsIGtleSwgX2RlZmF1bHQgPSBudWxsKSB7XG4gIGlmICgha2V5IGluIG1hcCkge1xuICAgIHJldHVybiBTcGVjaWFsRm9ybXMudHVwbGUoX2RlZmF1bHQsIG1hcCk7XG4gIH1cblxuICBsZXQgbmV3X21hcCA9IE9iamVjdC5hc3NpZ24oe30sIG1hcCk7XG4gIGxldCB2YWx1ZSA9IG5ld19tYXBba2V5XTtcbiAgZGVsZXRlIG5ld19tYXBba2V5XTtcblxuICByZXR1cm4gU3BlY2lhbEZvcm1zLnR1cGxlKHZhbHVlLCBuZXdfbWFwKTtcbn1cblxuZnVuY3Rpb24gZ2V0X2xhenkobWFwLCBrZXksIGZ1bikge1xuICBpZiAoIWtleSBpbiBtYXApIHtcbiAgICByZXR1cm4gZnVuKCk7XG4gIH1cblxuICByZXR1cm4gZnVuKG1hcFtrZXldKTtcbn1cblxuZnVuY3Rpb24gZ2V0KG1hcCwga2V5LCBfZGVmYXVsdCA9IG51bGwpIHtcbiAgaWYgKCFrZXkgaW4gbWFwKSB7XG4gICAgcmV0dXJuIF9kZWZhdWx0O1xuICB9XG5cbiAgcmV0dXJuIG1hcFtrZXldO1xufVxuXG5mdW5jdGlvbiBfX3B1dChtYXAsIGtleSwgdmFsKSB7XG4gIGxldCBuZXdfbWFwID0gT2JqZWN0KHt9LCBtYXApO1xuICBuZXdfbWFwW2tleV0gPSB2YWw7XG5cbiAgcmV0dXJuIFNwZWNpYWxGb3Jtcy5tYXAobmV3X21hcCk7XG59XG5cbmZ1bmN0aW9uIHVwZGF0ZV9fZW1hcmtfXyhtYXAsIGtleSwgZnVuKSB7XG4gIGlmICgha2V5IGluIG1hcCkge1xuICAgIHRocm93IG5ldyBFcnJvcihcIktleSBub3QgZm91bmRcIik7XG4gIH1cblxuICBsZXQgbmV3X21hcCA9IE9iamVjdCh7fSwgbWFwKTtcbiAgbmV3X21hcFtrZXldID0gZnVuKG1hcFtrZXldKTtcblxuICByZXR1cm4gU3BlY2lhbEZvcm1zLm1hcChuZXdfbWFwKTtcbn1cblxuZnVuY3Rpb24gX3VwZGF0ZShtYXAsIGtleSwgaW5pdGlhbCwgZnVuKSB7XG4gIGxldCBuZXdfbWFwID0gT2JqZWN0KHt9LCBtYXApO1xuXG4gIGlmICgha2V5IGluIG1hcCkge1xuICAgIG5ld19tYXBba2V5XSA9IGluaXRpYWw7XG4gIH0gZWxzZSB7XG4gICAgbmV3X21hcFtrZXldID0gZnVuKG1hcFtrZXldKTtcbiAgfVxuXG4gIHJldHVybiBTcGVjaWFsRm9ybXMubWFwKG5ld19tYXApO1xufVxuXG52YXIgX01hcCA9IHtcbiAgbmV3OiBfX19uZXdfXyxcbiAga2V5cyxcbiAgc2l6ZTogX19zaXplLFxuICB0b19saXN0OiBfX3RvX2xpc3QsXG4gIHZhbHVlcyxcbiAgZnJvbV9zdHJ1Y3QsXG4gIGRlbGV0ZTogX19fX2RlbGV0ZV9fLFxuICBkcm9wLFxuICBlcXVhbF9fcW1hcmtfXzogX19lcXVhbF9fcW1hcmtfXyxcbiAgZmV0Y2hfX2VtYXJrX18sXG4gIGZldGNoLFxuICBoYXNfa2V5X19xbWFya19fLFxuICBzcGxpdCxcbiAgdGFrZSxcbiAgcHV0X25ldyxcbiAgcHV0X25ld19sYXp5LFxuICBnZXRfYW5kX3VwZGF0ZSxcbiAgcG9wX2xhenksXG4gIHBvcCxcbiAgZ2V0X2xhenksXG4gIGdldCxcbiAgcHV0OiBfX3B1dCxcbiAgdXBkYXRlX19lbWFya19fLFxuICB1cGRhdGU6IF91cGRhdGVcbn07XG5cbmZ1bmN0aW9uIF9fbmV3X18oKSB7XG4gIHJldHVybiBTcGVjaWFsRm9ybXMubWFwKHsgW1N5bWJvbC5mb3IoJ19fc3RydWN0X18nKV06IFN5bWJvbC5mb3IoJ01hcFNldCcpLCBzZXQ6IFNwZWNpYWxGb3Jtcy5saXN0KCkgfSk7XG59XG5cbmZ1bmN0aW9uIF9zaXplKG1hcCkge1xuICByZXR1cm4gbWFwLnNldC5sZW5ndGg7XG59XG5cbmZ1bmN0aW9uIF90b19saXN0KG1hcCkge1xuICByZXR1cm4gbWFwLnNldDtcbn1cblxuZnVuY3Rpb24gX19fZGVsZXRlX18oc2V0LCB0ZXJtKSB7XG4gIGxldCBuZXdfbGlzdCA9IExpc3QuZGVsZXRlKHNldC5zZXQsIHRlcm0pO1xuXG4gIGxldCBuZXdfbWFwID0gT2JqZWN0LmFzc2lnbih7fSwgc2V0KTtcbiAgbmV3X21hcC5zZXQgPSBuZXdfbGlzdDtcbiAgcmV0dXJuIFNwZWNpYWxGb3Jtcy5tYXAobmV3X21hcCk7XG59XG5cbmZ1bmN0aW9uIF9wdXQoc2V0LCB0ZXJtKSB7XG4gIGlmIChzZXQuc2V0LmluZGV4T2YodGVybSkgPT09IC0xKSB7XG4gICAgbGV0IG5ld19saXN0ID0gTGlzdC5hcHBlbmQoc2V0LnNldCwgdGVybSk7XG5cbiAgICBsZXQgbmV3X21hcCA9IE9iamVjdC5hc3NpZ24oe30sIHNldCk7XG4gICAgbmV3X21hcC5zZXQgPSBuZXdfbGlzdDtcbiAgICByZXR1cm4gU3BlY2lhbEZvcm1zLm1hcChuZXdfbWFwKTtcbiAgfVxuXG4gIHJldHVybiBzZXQ7XG59XG5cbmZ1bmN0aW9uIF9kaWZmZXJlbmNlKHNldDEsIHNldDIpIHtcbiAgbGV0IG5ld19tYXAgPSBPYmplY3QuYXNzaWduKHt9LCBzZXQxKTtcblxuICBmb3IgKGxldCB2YWwgb2Ygc2V0MS5zZXQpIHtcbiAgICBpZiAoX21lbWJlcl9fcW1hcmtfXyhzZXQyLCB2YWwpKSB7XG4gICAgICBuZXdfbWFwLnNldCA9IExpc3QuZGVsZXRlKG5ld19tYXAuc2V0LCB2YWwpO1xuICAgIH1cbiAgfVxuXG4gIHJldHVybiBTcGVjaWFsRm9ybXMubWFwKG5ld19tYXApO1xufVxuXG5mdW5jdGlvbiBfaW50ZXJzZWN0aW9uKHNldDEsIHNldDIpIHtcbiAgbGV0IG5ld19tYXAgPSBPYmplY3QuYXNzaWduKHt9LCBzZXQxKTtcblxuICBmb3IgKGxldCB2YWwgb2Ygc2V0MS5zZXQpIHtcbiAgICBpZiAoIV9tZW1iZXJfX3FtYXJrX18oc2V0MiwgdmFsKSkge1xuICAgICAgbmV3X21hcC5zZXQgPSBMaXN0LmRlbGV0ZShuZXdfbWFwLnNldCwgdmFsKTtcbiAgICB9XG4gIH1cblxuICByZXR1cm4gU3BlY2lhbEZvcm1zLm1hcChuZXdfbWFwKTtcbn1cblxuZnVuY3Rpb24gX3VuaW9uKHNldDEsIHNldDIpIHtcbiAgbGV0IG5ld19tYXAgPSBzZXQxO1xuXG4gIGZvciAobGV0IHZhbCBvZiBzZXQyLnNldCkge1xuICAgIG5ld19tYXAgPSBfcHV0KG5ld19tYXAsIHZhbCk7XG4gIH1cblxuICByZXR1cm4gU3BlY2lhbEZvcm1zLm1hcChuZXdfbWFwKTtcbn1cblxuZnVuY3Rpb24gX2Rpc2pvaW5fX3FtYXJrX18oc2V0MSwgc2V0Mikge1xuICBmb3IgKGxldCB2YWwgb2Ygc2V0MS5zZXQpIHtcbiAgICBpZiAoX21lbWJlcl9fcW1hcmtfXyhzZXQyLCB2YWwpKSB7XG4gICAgICByZXR1cm4gZmFsc2U7XG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIHRydWU7XG59XG5cbmZ1bmN0aW9uIF9tZW1iZXJfX3FtYXJrX18oc2V0LCB2YWx1ZSkge1xuICByZXR1cm4gc2V0LnNldC5pbmRleE9mKHZhbHVlKSA+PSAwO1xufVxuXG5mdW5jdGlvbiBfZXF1YWxfX3FtYXJrX18oc2V0MSwgc2V0Mikge1xuICByZXR1cm4gc2V0MS5zZXQgPT09IHNldDIuc2V0O1xufVxuXG5mdW5jdGlvbiBfc3Vic2V0X19xbWFya19fKHNldDEsIHNldDIpIHtcbiAgZm9yIChsZXQgdmFsIG9mIHNldDEuc2V0KSB7XG4gICAgaWYgKCFfbWVtYmVyX19xbWFya19fKHNldDIsIHZhbCkpIHtcbiAgICAgIHJldHVybiBmYWxzZTtcbiAgICB9XG4gIH1cblxuICByZXR1cm4gdHJ1ZTtcbn1cblxudmFyIE1hcFNldCA9IHtcbiAgbmV3OiBfX25ld19fLFxuICBzaXplOiBfc2l6ZSxcbiAgdG9fbGlzdDogX3RvX2xpc3QsXG4gIGRpc2pvaW5fX3FtYXJrX186IF9kaXNqb2luX19xbWFya19fLFxuICBkZWxldGU6IF9fX2RlbGV0ZV9fLFxuICBzdWJzZXRfX3FtYXJrX186IF9zdWJzZXRfX3FtYXJrX18sXG4gIGVxdWFsX19xbWFya19fOiBfZXF1YWxfX3FtYXJrX18sXG4gIG1lbWJlcl9fcW1hcmtfXzogX21lbWJlcl9fcW1hcmtfXyxcbiAgcHV0OiBfcHV0LFxuICB1bmlvbjogX3VuaW9uLFxuICBpbnRlcnNlY3Rpb246IF9pbnRlcnNlY3Rpb24sXG4gIGRpZmZlcmVuY2U6IF9kaWZmZXJlbmNlXG59O1xuXG5mdW5jdGlvbiBzaXplKG1hcCkge1xuICByZXR1cm4gTWFwU2V0LnNpemUobWFwKTtcbn1cblxuZnVuY3Rpb24gdG9fbGlzdChtYXApIHtcbiAgcmV0dXJuIE1hcFNldC50b19saXN0KG1hcCk7XG59XG5cbmZ1bmN0aW9uIF9fZGVsZXRlX18oc2V0LCB0ZXJtKSB7XG4gIHJldHVybiBNYXBTZXQuZGVsZXRlKHNldCwgdGVybSk7XG59XG5cbmZ1bmN0aW9uIHB1dChzZXQsIHRlcm0pIHtcbiAgcmV0dXJuIE1hcFNldC5wdXQoc2V0LCB0ZXJtKTtcbn1cblxuZnVuY3Rpb24gZGlmZmVyZW5jZShzZXQxLCBzZXQyKSB7XG4gIHJldHVybiBNYXBTZXQuZGlmZmVyZW5jZShzZXQxLCBzZXQyKTtcbn1cblxuZnVuY3Rpb24gaW50ZXJzZWN0aW9uKHNldDEsIHNldDIpIHtcbiAgcmV0dXJuIE1hcFNldC5pbnRlcnNlY3Rpb24oc2V0MSwgc2V0Mik7XG59XG5cbmZ1bmN0aW9uIHVuaW9uKHNldDEsIHNldDIpIHtcbiAgcmV0dXJuIE1hcFNldC51bmlvbihzZXQxLCBzZXQyKTtcbn1cblxuZnVuY3Rpb24gZGlzam9pbl9fcW1hcmtfXyhzZXQxLCBzZXQyKSB7XG4gIHJldHVybiBNYXBTZXQuZGlzam9pbl9fcW1hcmtfXyhzZXQxLCBzZXQyKTtcbn1cblxuZnVuY3Rpb24gbWVtYmVyX19xbWFya19fKHNldCwgdmFsdWUpIHtcbiAgcmV0dXJuIE1hcFNldC5tZW1iZXJfX3FtYXJrX18oc2V0MSwgc2V0Mik7XG59XG5cbmZ1bmN0aW9uIGVxdWFsX19xbWFya19fKHNldDEsIHNldDIpIHtcbiAgcmV0dXJuIE1hcFNldC5lcXVhbF9fcW1hcmtfXyhzZXQxLCBzZXQyKTtcbn1cblxuZnVuY3Rpb24gc3Vic2V0X19xbWFya19fKHNldDEsIHNldDIpIHtcbiAgcmV0dXJuIE1hcFNldC5zdWJzZXRfX3FtYXJrX18oc2V0MSwgc2V0Mik7XG59XG5cbnZhciBfU2V0ID0ge1xuICBzaXplLFxuICB0b19saXN0LFxuICBkaXNqb2luX19xbWFya19fLFxuICBkZWxldGU6IF9fZGVsZXRlX18sXG4gIHN1YnNldF9fcW1hcmtfXyxcbiAgZXF1YWxfX3FtYXJrX18sXG4gIG1lbWJlcl9fcW1hcmtfXyxcbiAgcHV0LFxuICB1bmlvbixcbiAgaW50ZXJzZWN0aW9uLFxuICBkaWZmZXJlbmNlXG59O1xuXG5sZXQgdmlydHVhbERvbSA9IChmdW5jdGlvbiAoZSkge1xuICAgIHJldHVybiBlKCk7XG59KShmdW5jdGlvbiAoKSB7XG4gICAgdmFyIGRlZmluZSwgbW9kdWxlLCBleHBvcnRzO1xuICAgIHJldHVybiAoZnVuY3Rpb24gZSh0LCBuLCByKSB7XG4gICAgICAgIGZ1bmN0aW9uIHMobywgdSkge1xuICAgICAgICAgICAgaWYgKCFuW29dKSB7XG4gICAgICAgICAgICAgICAgaWYgKCF0W29dKSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciBhID0gdHlwZW9mIHJlcXVpcmUgPT0gXCJmdW5jdGlvblwiICYmIHJlcXVpcmU7XG4gICAgICAgICAgICAgICAgICAgIGlmICghdSAmJiBhKSByZXR1cm4gYShvLCAhMCk7XG4gICAgICAgICAgICAgICAgICAgIGlmIChpKSByZXR1cm4gaShvLCAhMCk7XG4gICAgICAgICAgICAgICAgICAgIHZhciBmID0gbmV3IEVycm9yKFwiQ2Fubm90IGZpbmQgbW9kdWxlICdcIiArIG8gKyBcIidcIik7XG4gICAgICAgICAgICAgICAgICAgIHRocm93IChmLmNvZGUgPSBcIk1PRFVMRV9OT1RfRk9VTkRcIiwgZik7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHZhciBsID0gbltvXSA9IHtcbiAgICAgICAgICAgICAgICAgICAgZXhwb3J0czoge31cbiAgICAgICAgICAgICAgICB9O1xuICAgICAgICAgICAgICAgIHRbb11bMF0uY2FsbChsLmV4cG9ydHMsIGZ1bmN0aW9uIChlKSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciBuID0gdFtvXVsxXVtlXTtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHMobiA/IG4gOiBlKTtcbiAgICAgICAgICAgICAgICB9LCBsLCBsLmV4cG9ydHMsIGUsIHQsIG4sIHIpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmV0dXJuIG5bb10uZXhwb3J0cztcbiAgICAgICAgfVxuICAgICAgICB2YXIgaSA9IHR5cGVvZiByZXF1aXJlID09IFwiZnVuY3Rpb25cIiAmJiByZXF1aXJlO1xuICAgICAgICBmb3IgKHZhciBvID0gMDsgbyA8IHIubGVuZ3RoOyBvKyspIHMocltvXSk7XG4gICAgICAgIHJldHVybiBzO1xuICAgIH0pKHtcbiAgICAgICAgMTogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHtcblxuICAgICAgICAgICAgdmFyIGNyZWF0ZUVsZW1lbnQgPSByZXF1aXJlKFwiLi92ZG9tL2NyZWF0ZS1lbGVtZW50LmpzXCIpO1xuXG4gICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IGNyZWF0ZUVsZW1lbnQ7XG4gICAgICAgIH0sIHsgXCIuL3Zkb20vY3JlYXRlLWVsZW1lbnQuanNcIjogMTUgfV0sIDI6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICB2YXIgZGlmZiA9IHJlcXVpcmUoXCIuL3Z0cmVlL2RpZmYuanNcIik7XG5cbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gZGlmZjtcbiAgICAgICAgfSwgeyBcIi4vdnRyZWUvZGlmZi5qc1wiOiAzNSB9XSwgMzogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHtcbiAgICAgICAgICAgIHZhciBoID0gcmVxdWlyZShcIi4vdmlydHVhbC1oeXBlcnNjcmlwdC9pbmRleC5qc1wiKTtcblxuICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBoO1xuICAgICAgICB9LCB7IFwiLi92aXJ0dWFsLWh5cGVyc2NyaXB0L2luZGV4LmpzXCI6IDIyIH1dLCA0OiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge1xuICAgICAgICAgICAgdmFyIGRpZmYgPSByZXF1aXJlKFwiLi9kaWZmLmpzXCIpO1xuICAgICAgICAgICAgdmFyIHBhdGNoID0gcmVxdWlyZShcIi4vcGF0Y2guanNcIik7XG4gICAgICAgICAgICB2YXIgaCA9IHJlcXVpcmUoXCIuL2guanNcIik7XG4gICAgICAgICAgICB2YXIgY3JlYXRlID0gcmVxdWlyZShcIi4vY3JlYXRlLWVsZW1lbnQuanNcIik7XG4gICAgICAgICAgICB2YXIgVk5vZGUgPSByZXF1aXJlKFwiLi92bm9kZS92bm9kZS5qc1wiKTtcbiAgICAgICAgICAgIHZhciBWVGV4dCA9IHJlcXVpcmUoXCIuL3Zub2RlL3Z0ZXh0LmpzXCIpO1xuXG4gICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IHtcbiAgICAgICAgICAgICAgICBkaWZmOiBkaWZmLFxuICAgICAgICAgICAgICAgIHBhdGNoOiBwYXRjaCxcbiAgICAgICAgICAgICAgICBoOiBoLFxuICAgICAgICAgICAgICAgIGNyZWF0ZTogY3JlYXRlLFxuICAgICAgICAgICAgICAgIFZOb2RlOiBWTm9kZSxcbiAgICAgICAgICAgICAgICBWVGV4dDogVlRleHRcbiAgICAgICAgICAgIH07XG4gICAgICAgIH0sIHsgXCIuL2NyZWF0ZS1lbGVtZW50LmpzXCI6IDEsIFwiLi9kaWZmLmpzXCI6IDIsIFwiLi9oLmpzXCI6IDMsIFwiLi9wYXRjaC5qc1wiOiAxMywgXCIuL3Zub2RlL3Zub2RlLmpzXCI6IDMxLCBcIi4vdm5vZGUvdnRleHQuanNcIjogMzMgfV0sIDU6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICAvKiFcbiAgICAgICAgICAgICAqIENyb3NzLUJyb3dzZXIgU3BsaXQgMS4xLjFcbiAgICAgICAgICAgICAqIENvcHlyaWdodCAyMDA3LTIwMTIgU3RldmVuIExldml0aGFuIDxzdGV2ZW5sZXZpdGhhbi5jb20+XG4gICAgICAgICAgICAgKiBBdmFpbGFibGUgdW5kZXIgdGhlIE1JVCBMaWNlbnNlXG4gICAgICAgICAgICAgKiBFQ01BU2NyaXB0IGNvbXBsaWFudCwgdW5pZm9ybSBjcm9zcy1icm93c2VyIHNwbGl0IG1ldGhvZFxuICAgICAgICAgICAgICovXG5cbiAgICAgICAgICAgIC8qKlxuICAgICAgICAgICAgICogU3BsaXRzIGEgc3RyaW5nIGludG8gYW4gYXJyYXkgb2Ygc3RyaW5ncyB1c2luZyBhIHJlZ2V4IG9yIHN0cmluZyBzZXBhcmF0b3IuIE1hdGNoZXMgb2YgdGhlXG4gICAgICAgICAgICAgKiBzZXBhcmF0b3IgYXJlIG5vdCBpbmNsdWRlZCBpbiB0aGUgcmVzdWx0IGFycmF5LiBIb3dldmVyLCBpZiBgc2VwYXJhdG9yYCBpcyBhIHJlZ2V4IHRoYXQgY29udGFpbnNcbiAgICAgICAgICAgICAqIGNhcHR1cmluZyBncm91cHMsIGJhY2tyZWZlcmVuY2VzIGFyZSBzcGxpY2VkIGludG8gdGhlIHJlc3VsdCBlYWNoIHRpbWUgYHNlcGFyYXRvcmAgaXMgbWF0Y2hlZC5cbiAgICAgICAgICAgICAqIEZpeGVzIGJyb3dzZXIgYnVncyBjb21wYXJlZCB0byB0aGUgbmF0aXZlIGBTdHJpbmcucHJvdG90eXBlLnNwbGl0YCBhbmQgY2FuIGJlIHVzZWQgcmVsaWFibHlcbiAgICAgICAgICAgICAqIGNyb3NzLWJyb3dzZXIuXG4gICAgICAgICAgICAgKiBAcGFyYW0ge1N0cmluZ30gc3RyIFN0cmluZyB0byBzcGxpdC5cbiAgICAgICAgICAgICAqIEBwYXJhbSB7UmVnRXhwfFN0cmluZ30gc2VwYXJhdG9yIFJlZ2V4IG9yIHN0cmluZyB0byB1c2UgZm9yIHNlcGFyYXRpbmcgdGhlIHN0cmluZy5cbiAgICAgICAgICAgICAqIEBwYXJhbSB7TnVtYmVyfSBbbGltaXRdIE1heGltdW0gbnVtYmVyIG9mIGl0ZW1zIHRvIGluY2x1ZGUgaW4gdGhlIHJlc3VsdCBhcnJheS5cbiAgICAgICAgICAgICAqIEByZXR1cm5zIHtBcnJheX0gQXJyYXkgb2Ygc3Vic3RyaW5ncy5cbiAgICAgICAgICAgICAqIEBleGFtcGxlXG4gICAgICAgICAgICAgKlxuICAgICAgICAgICAgICogLy8gQmFzaWMgdXNlXG4gICAgICAgICAgICAgKiBzcGxpdCgnYSBiIGMgZCcsICcgJyk7XG4gICAgICAgICAgICAgKiAvLyAtPiBbJ2EnLCAnYicsICdjJywgJ2QnXVxuICAgICAgICAgICAgICpcbiAgICAgICAgICAgICAqIC8vIFdpdGggbGltaXRcbiAgICAgICAgICAgICAqIHNwbGl0KCdhIGIgYyBkJywgJyAnLCAyKTtcbiAgICAgICAgICAgICAqIC8vIC0+IFsnYScsICdiJ11cbiAgICAgICAgICAgICAqXG4gICAgICAgICAgICAgKiAvLyBCYWNrcmVmZXJlbmNlcyBpbiByZXN1bHQgYXJyYXlcbiAgICAgICAgICAgICAqIHNwbGl0KCcuLndvcmQxIHdvcmQyLi4nLCAvKFthLXpdKykoXFxkKykvaSk7XG4gICAgICAgICAgICAgKiAvLyAtPiBbJy4uJywgJ3dvcmQnLCAnMScsICcgJywgJ3dvcmQnLCAnMicsICcuLiddXG4gICAgICAgICAgICAgKi9cbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gKGZ1bmN0aW9uIHNwbGl0KHVuZGVmKSB7XG5cbiAgICAgICAgICAgICAgICB2YXIgbmF0aXZlU3BsaXQgPSBTdHJpbmcucHJvdG90eXBlLnNwbGl0LFxuICAgICAgICAgICAgICAgICAgICBjb21wbGlhbnRFeGVjTnBjZyA9IC8oKT8/Ly5leGVjKFwiXCIpWzFdID09PSB1bmRlZixcblxuICAgICAgICAgICAgICAgIC8vIE5QQ0c6IG5vbnBhcnRpY2lwYXRpbmcgY2FwdHVyaW5nIGdyb3VwXG4gICAgICAgICAgICAgICAgc2VsZjtcblxuICAgICAgICAgICAgICAgIHNlbGYgPSBmdW5jdGlvbiAoc3RyLCBzZXBhcmF0b3IsIGxpbWl0KSB7XG4gICAgICAgICAgICAgICAgICAgIC8vIElmIGBzZXBhcmF0b3JgIGlzIG5vdCBhIHJlZ2V4LCB1c2UgYG5hdGl2ZVNwbGl0YFxuICAgICAgICAgICAgICAgICAgICBpZiAoT2JqZWN0LnByb3RvdHlwZS50b1N0cmluZy5jYWxsKHNlcGFyYXRvcikgIT09IFwiW29iamVjdCBSZWdFeHBdXCIpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBuYXRpdmVTcGxpdC5jYWxsKHN0ciwgc2VwYXJhdG9yLCBsaW1pdCk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgdmFyIG91dHB1dCA9IFtdLFxuICAgICAgICAgICAgICAgICAgICAgICAgZmxhZ3MgPSAoc2VwYXJhdG9yLmlnbm9yZUNhc2UgPyBcImlcIiA6IFwiXCIpICsgKHNlcGFyYXRvci5tdWx0aWxpbmUgPyBcIm1cIiA6IFwiXCIpICsgKHNlcGFyYXRvci5leHRlbmRlZCA/IFwieFwiIDogXCJcIikgKyAoc2VwYXJhdG9yLnN0aWNreSA/IFwieVwiIDogXCJcIiksXG5cbiAgICAgICAgICAgICAgICAgICAgLy8gRmlyZWZveCAzK1xuICAgICAgICAgICAgICAgICAgICBsYXN0TGFzdEluZGV4ID0gMCxcblxuICAgICAgICAgICAgICAgICAgICAvLyBNYWtlIGBnbG9iYWxgIGFuZCBhdm9pZCBgbGFzdEluZGV4YCBpc3N1ZXMgYnkgd29ya2luZyB3aXRoIGEgY29weVxuICAgICAgICAgICAgICAgICAgICBzZXBhcmF0b3IgPSBuZXcgUmVnRXhwKHNlcGFyYXRvci5zb3VyY2UsIGZsYWdzICsgXCJnXCIpLFxuICAgICAgICAgICAgICAgICAgICAgICAgc2VwYXJhdG9yMixcbiAgICAgICAgICAgICAgICAgICAgICAgIG1hdGNoLFxuICAgICAgICAgICAgICAgICAgICAgICAgbGFzdEluZGV4LFxuICAgICAgICAgICAgICAgICAgICAgICAgbGFzdExlbmd0aDtcbiAgICAgICAgICAgICAgICAgICAgc3RyICs9IFwiXCI7IC8vIFR5cGUtY29udmVydFxuICAgICAgICAgICAgICAgICAgICBpZiAoIWNvbXBsaWFudEV4ZWNOcGNnKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAvLyBEb2Vzbid0IG5lZWQgZmxhZ3MgZ3ksIGJ1dCB0aGV5IGRvbid0IGh1cnRcbiAgICAgICAgICAgICAgICAgICAgICAgIHNlcGFyYXRvcjIgPSBuZXcgUmVnRXhwKFwiXlwiICsgc2VwYXJhdG9yLnNvdXJjZSArIFwiJCg/IVxcXFxzKVwiLCBmbGFncyk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgLyogVmFsdWVzIGZvciBgbGltaXRgLCBwZXIgdGhlIHNwZWM6XG4gICAgICAgICAgICAgICAgICAgICAqIElmIHVuZGVmaW5lZDogNDI5NDk2NzI5NSAvLyBNYXRoLnBvdygyLCAzMikgLSAxXG4gICAgICAgICAgICAgICAgICAgICAqIElmIDAsIEluZmluaXR5LCBvciBOYU46IDBcbiAgICAgICAgICAgICAgICAgICAgICogSWYgcG9zaXRpdmUgbnVtYmVyOiBsaW1pdCA9IE1hdGguZmxvb3IobGltaXQpOyBpZiAobGltaXQgPiA0Mjk0OTY3Mjk1KSBsaW1pdCAtPSA0Mjk0OTY3Mjk2O1xuICAgICAgICAgICAgICAgICAgICAgKiBJZiBuZWdhdGl2ZSBudW1iZXI6IDQyOTQ5NjcyOTYgLSBNYXRoLmZsb29yKE1hdGguYWJzKGxpbWl0KSlcbiAgICAgICAgICAgICAgICAgICAgICogSWYgb3RoZXI6IFR5cGUtY29udmVydCwgdGhlbiB1c2UgdGhlIGFib3ZlIHJ1bGVzXG4gICAgICAgICAgICAgICAgICAgICAqL1xuICAgICAgICAgICAgICAgICAgICBsaW1pdCA9IGxpbWl0ID09PSB1bmRlZiA/IC0xID4+PiAwIDogLy8gTWF0aC5wb3coMiwgMzIpIC0gMVxuICAgICAgICAgICAgICAgICAgICBsaW1pdCA+Pj4gMDsgLy8gVG9VaW50MzIobGltaXQpXG4gICAgICAgICAgICAgICAgICAgIHdoaWxlIChtYXRjaCA9IHNlcGFyYXRvci5leGVjKHN0cikpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIGBzZXBhcmF0b3IubGFzdEluZGV4YCBpcyBub3QgcmVsaWFibGUgY3Jvc3MtYnJvd3NlclxuICAgICAgICAgICAgICAgICAgICAgICAgbGFzdEluZGV4ID0gbWF0Y2guaW5kZXggKyBtYXRjaFswXS5sZW5ndGg7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAobGFzdEluZGV4ID4gbGFzdExhc3RJbmRleCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIG91dHB1dC5wdXNoKHN0ci5zbGljZShsYXN0TGFzdEluZGV4LCBtYXRjaC5pbmRleCkpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIEZpeCBicm93c2VycyB3aG9zZSBgZXhlY2AgbWV0aG9kcyBkb24ndCBjb25zaXN0ZW50bHkgcmV0dXJuIGB1bmRlZmluZWRgIGZvclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIG5vbnBhcnRpY2lwYXRpbmcgY2FwdHVyaW5nIGdyb3Vwc1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmICghY29tcGxpYW50RXhlY05wY2cgJiYgbWF0Y2gubGVuZ3RoID4gMSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBtYXRjaFswXS5yZXBsYWNlKHNlcGFyYXRvcjIsIGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZvciAodmFyIGkgPSAxOyBpIDwgYXJndW1lbnRzLmxlbmd0aCAtIDI7IGkrKykge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChhcmd1bWVudHNbaV0gPT09IHVuZGVmKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1hdGNoW2ldID0gdW5kZWY7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKG1hdGNoLmxlbmd0aCA+IDEgJiYgbWF0Y2guaW5kZXggPCBzdHIubGVuZ3RoKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIEFycmF5LnByb3RvdHlwZS5wdXNoLmFwcGx5KG91dHB1dCwgbWF0Y2guc2xpY2UoMSkpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBsYXN0TGVuZ3RoID0gbWF0Y2hbMF0ubGVuZ3RoO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxhc3RMYXN0SW5kZXggPSBsYXN0SW5kZXg7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKG91dHB1dC5sZW5ndGggPj0gbGltaXQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHNlcGFyYXRvci5sYXN0SW5kZXggPT09IG1hdGNoLmluZGV4KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgc2VwYXJhdG9yLmxhc3RJbmRleCsrOyAvLyBBdm9pZCBhbiBpbmZpbml0ZSBsb29wXG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgaWYgKGxhc3RMYXN0SW5kZXggPT09IHN0ci5sZW5ndGgpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChsYXN0TGVuZ3RoIHx8ICFzZXBhcmF0b3IudGVzdChcIlwiKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIG91dHB1dC5wdXNoKFwiXCIpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgb3V0cHV0LnB1c2goc3RyLnNsaWNlKGxhc3RMYXN0SW5kZXgpKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICByZXR1cm4gb3V0cHV0Lmxlbmd0aCA+IGxpbWl0ID8gb3V0cHV0LnNsaWNlKDAsIGxpbWl0KSA6IG91dHB1dDtcbiAgICAgICAgICAgICAgICB9O1xuXG4gICAgICAgICAgICAgICAgcmV0dXJuIHNlbGY7XG4gICAgICAgICAgICB9KSgpO1xuICAgICAgICB9LCB7fV0sIDY6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7fSwge31dLCA3OiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge1xuICAgICAgICAgICAgXCJ1c2Ugc3RyaWN0XCI7XG5cbiAgICAgICAgICAgIHZhciBPbmVWZXJzaW9uQ29uc3RyYWludCA9IHJlcXVpcmUoXCJpbmRpdmlkdWFsL29uZS12ZXJzaW9uXCIpO1xuXG4gICAgICAgICAgICB2YXIgTVlfVkVSU0lPTiA9IFwiN1wiO1xuICAgICAgICAgICAgT25lVmVyc2lvbkNvbnN0cmFpbnQoXCJldi1zdG9yZVwiLCBNWV9WRVJTSU9OKTtcblxuICAgICAgICAgICAgdmFyIGhhc2hLZXkgPSBcIl9fRVZfU1RPUkVfS0VZQFwiICsgTVlfVkVSU0lPTjtcblxuICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBFdlN0b3JlO1xuXG4gICAgICAgICAgICBmdW5jdGlvbiBFdlN0b3JlKGVsZW0pIHtcbiAgICAgICAgICAgICAgICB2YXIgaGFzaCA9IGVsZW1baGFzaEtleV07XG5cbiAgICAgICAgICAgICAgICBpZiAoIWhhc2gpIHtcbiAgICAgICAgICAgICAgICAgICAgaGFzaCA9IGVsZW1baGFzaEtleV0gPSB7fTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICByZXR1cm4gaGFzaDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSwgeyBcImluZGl2aWR1YWwvb25lLXZlcnNpb25cIjogOSB9XSwgODogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHtcbiAgICAgICAgICAgIChmdW5jdGlvbiAoZ2xvYmFsKSB7XG4gICAgICAgICAgICAgICAgXCJ1c2Ugc3RyaWN0XCI7XG5cbiAgICAgICAgICAgICAgICAvKmdsb2JhbCB3aW5kb3csIGdsb2JhbCovXG5cbiAgICAgICAgICAgICAgICB2YXIgcm9vdCA9IHR5cGVvZiB3aW5kb3cgIT09IFwidW5kZWZpbmVkXCIgPyB3aW5kb3cgOiB0eXBlb2YgZ2xvYmFsICE9PSBcInVuZGVmaW5lZFwiID8gZ2xvYmFsIDoge307XG5cbiAgICAgICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IEluZGl2aWR1YWw7XG5cbiAgICAgICAgICAgICAgICBmdW5jdGlvbiBJbmRpdmlkdWFsKGtleSwgdmFsdWUpIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKGtleSBpbiByb290KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gcm9vdFtrZXldO1xuICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgcm9vdFtrZXldID0gdmFsdWU7XG5cbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHZhbHVlO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0pLmNhbGwodGhpcywgdHlwZW9mIGdsb2JhbCAhPT0gXCJ1bmRlZmluZWRcIiA/IGdsb2JhbCA6IHR5cGVvZiBzZWxmICE9PSBcInVuZGVmaW5lZFwiID8gc2VsZiA6IHR5cGVvZiB3aW5kb3cgIT09IFwidW5kZWZpbmVkXCIgPyB3aW5kb3cgOiB7fSk7XG4gICAgICAgIH0sIHt9XSwgOTogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHtcbiAgICAgICAgICAgIFwidXNlIHN0cmljdFwiO1xuXG4gICAgICAgICAgICB2YXIgSW5kaXZpZHVhbCA9IHJlcXVpcmUoXCIuL2luZGV4LmpzXCIpO1xuXG4gICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IE9uZVZlcnNpb247XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIE9uZVZlcnNpb24obW9kdWxlTmFtZSwgdmVyc2lvbiwgZGVmYXVsdFZhbHVlKSB7XG4gICAgICAgICAgICAgICAgdmFyIGtleSA9IFwiX19JTkRJVklEVUFMX09ORV9WRVJTSU9OX1wiICsgbW9kdWxlTmFtZTtcbiAgICAgICAgICAgICAgICB2YXIgZW5mb3JjZUtleSA9IGtleSArIFwiX0VORk9SQ0VfU0lOR0xFVE9OXCI7XG5cbiAgICAgICAgICAgICAgICB2YXIgdmVyc2lvblZhbHVlID0gSW5kaXZpZHVhbChlbmZvcmNlS2V5LCB2ZXJzaW9uKTtcblxuICAgICAgICAgICAgICAgIGlmICh2ZXJzaW9uVmFsdWUgIT09IHZlcnNpb24pIHtcbiAgICAgICAgICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKFwiQ2FuIG9ubHkgaGF2ZSBvbmUgY29weSBvZiBcIiArIG1vZHVsZU5hbWUgKyBcIi5cXG5cIiArIFwiWW91IGFscmVhZHkgaGF2ZSB2ZXJzaW9uIFwiICsgdmVyc2lvblZhbHVlICsgXCIgaW5zdGFsbGVkLlxcblwiICsgXCJUaGlzIG1lYW5zIHlvdSBjYW5ub3QgaW5zdGFsbCB2ZXJzaW9uIFwiICsgdmVyc2lvbik7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgcmV0dXJuIEluZGl2aWR1YWwoa2V5LCBkZWZhdWx0VmFsdWUpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9LCB7IFwiLi9pbmRleC5qc1wiOiA4IH1dLCAxMDogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHtcbiAgICAgICAgICAgIChmdW5jdGlvbiAoZ2xvYmFsKSB7XG4gICAgICAgICAgICAgICAgdmFyIHRvcExldmVsID0gdHlwZW9mIGdsb2JhbCAhPT0gXCJ1bmRlZmluZWRcIiA/IGdsb2JhbCA6IHR5cGVvZiB3aW5kb3cgIT09IFwidW5kZWZpbmVkXCIgPyB3aW5kb3cgOiB7fTtcbiAgICAgICAgICAgICAgICB2YXIgbWluRG9jID0gcmVxdWlyZShcIm1pbi1kb2N1bWVudFwiKTtcblxuICAgICAgICAgICAgICAgIGlmICh0eXBlb2YgZG9jdW1lbnQgIT09IFwidW5kZWZpbmVkXCIpIHtcbiAgICAgICAgICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBkb2N1bWVudDtcbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICB2YXIgZG9jY3kgPSB0b3BMZXZlbFtcIl9fR0xPQkFMX0RPQ1VNRU5UX0NBQ0hFQDRcIl07XG5cbiAgICAgICAgICAgICAgICAgICAgaWYgKCFkb2NjeSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgZG9jY3kgPSB0b3BMZXZlbFtcIl9fR0xPQkFMX0RPQ1VNRU5UX0NBQ0hFQDRcIl0gPSBtaW5Eb2M7XG4gICAgICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IGRvY2N5O1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0pLmNhbGwodGhpcywgdHlwZW9mIGdsb2JhbCAhPT0gXCJ1bmRlZmluZWRcIiA/IGdsb2JhbCA6IHR5cGVvZiBzZWxmICE9PSBcInVuZGVmaW5lZFwiID8gc2VsZiA6IHR5cGVvZiB3aW5kb3cgIT09IFwidW5kZWZpbmVkXCIgPyB3aW5kb3cgOiB7fSk7XG4gICAgICAgIH0sIHsgXCJtaW4tZG9jdW1lbnRcIjogNiB9XSwgMTE6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICBcInVzZSBzdHJpY3RcIjtcblxuICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiBpc09iamVjdCh4KSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHR5cGVvZiB4ID09PSBcIm9iamVjdFwiICYmIHggIT09IG51bGw7XG4gICAgICAgICAgICB9O1xuICAgICAgICB9LCB7fV0sIDEyOiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge1xuICAgICAgICAgICAgdmFyIG5hdGl2ZUlzQXJyYXkgPSBBcnJheS5pc0FycmF5O1xuICAgICAgICAgICAgdmFyIHRvU3RyaW5nID0gT2JqZWN0LnByb3RvdHlwZS50b1N0cmluZztcblxuICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBuYXRpdmVJc0FycmF5IHx8IGlzQXJyYXk7XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIGlzQXJyYXkob2JqKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHRvU3RyaW5nLmNhbGwob2JqKSA9PT0gXCJbb2JqZWN0IEFycmF5XVwiO1xuICAgICAgICAgICAgfVxuICAgICAgICB9LCB7fV0sIDEzOiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge1xuICAgICAgICAgICAgdmFyIHBhdGNoID0gcmVxdWlyZShcIi4vdmRvbS9wYXRjaC5qc1wiKTtcblxuICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBwYXRjaDtcbiAgICAgICAgfSwgeyBcIi4vdmRvbS9wYXRjaC5qc1wiOiAxOCB9XSwgMTQ6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICB2YXIgaXNPYmplY3QgPSByZXF1aXJlKFwiaXMtb2JqZWN0XCIpO1xuICAgICAgICAgICAgdmFyIGlzSG9vayA9IHJlcXVpcmUoXCIuLi92bm9kZS9pcy12aG9vay5qc1wiKTtcblxuICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBhcHBseVByb3BlcnRpZXM7XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIGFwcGx5UHJvcGVydGllcyhub2RlLCBwcm9wcywgcHJldmlvdXMpIHtcbiAgICAgICAgICAgICAgICBmb3IgKHZhciBwcm9wTmFtZSBpbiBwcm9wcykge1xuICAgICAgICAgICAgICAgICAgICB2YXIgcHJvcFZhbHVlID0gcHJvcHNbcHJvcE5hbWVdO1xuXG4gICAgICAgICAgICAgICAgICAgIGlmIChwcm9wVmFsdWUgPT09IHVuZGVmaW5lZCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgcmVtb3ZlUHJvcGVydHkobm9kZSwgcHJvcE5hbWUsIHByb3BWYWx1ZSwgcHJldmlvdXMpO1xuICAgICAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKGlzSG9vayhwcm9wVmFsdWUpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICByZW1vdmVQcm9wZXJ0eShub2RlLCBwcm9wTmFtZSwgcHJvcFZhbHVlLCBwcmV2aW91cyk7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAocHJvcFZhbHVlLmhvb2spIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBwcm9wVmFsdWUuaG9vayhub2RlLCBwcm9wTmFtZSwgcHJldmlvdXMgPyBwcmV2aW91c1twcm9wTmFtZV0gOiB1bmRlZmluZWQpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGlzT2JqZWN0KHByb3BWYWx1ZSkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBwYXRjaE9iamVjdChub2RlLCBwcm9wcywgcHJldmlvdXMsIHByb3BOYW1lLCBwcm9wVmFsdWUpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBub2RlW3Byb3BOYW1lXSA9IHByb3BWYWx1ZTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZnVuY3Rpb24gcmVtb3ZlUHJvcGVydHkobm9kZSwgcHJvcE5hbWUsIHByb3BWYWx1ZSwgcHJldmlvdXMpIHtcbiAgICAgICAgICAgICAgICBpZiAocHJldmlvdXMpIHtcbiAgICAgICAgICAgICAgICAgICAgdmFyIHByZXZpb3VzVmFsdWUgPSBwcmV2aW91c1twcm9wTmFtZV07XG5cbiAgICAgICAgICAgICAgICAgICAgaWYgKCFpc0hvb2socHJldmlvdXNWYWx1ZSkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChwcm9wTmFtZSA9PT0gXCJhdHRyaWJ1dGVzXCIpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBmb3IgKHZhciBhdHRyTmFtZSBpbiBwcmV2aW91c1ZhbHVlKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG5vZGUucmVtb3ZlQXR0cmlidXRlKGF0dHJOYW1lKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKHByb3BOYW1lID09PSBcInN0eWxlXCIpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBmb3IgKHZhciBpIGluIHByZXZpb3VzVmFsdWUpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbm9kZS5zdHlsZVtpXSA9IFwiXCI7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIGlmICh0eXBlb2YgcHJldmlvdXNWYWx1ZSA9PT0gXCJzdHJpbmdcIikge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIG5vZGVbcHJvcE5hbWVdID0gXCJcIjtcbiAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgbm9kZVtwcm9wTmFtZV0gPSBudWxsO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKHByZXZpb3VzVmFsdWUudW5ob29rKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBwcmV2aW91c1ZhbHVlLnVuaG9vayhub2RlLCBwcm9wTmFtZSwgcHJvcFZhbHVlKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZnVuY3Rpb24gcGF0Y2hPYmplY3Qobm9kZSwgcHJvcHMsIHByZXZpb3VzLCBwcm9wTmFtZSwgcHJvcFZhbHVlKSB7XG4gICAgICAgICAgICAgICAgdmFyIHByZXZpb3VzVmFsdWUgPSBwcmV2aW91cyA/IHByZXZpb3VzW3Byb3BOYW1lXSA6IHVuZGVmaW5lZDtcblxuICAgICAgICAgICAgICAgIC8vIFNldCBhdHRyaWJ1dGVzXG4gICAgICAgICAgICAgICAgaWYgKHByb3BOYW1lID09PSBcImF0dHJpYnV0ZXNcIikge1xuICAgICAgICAgICAgICAgICAgICBmb3IgKHZhciBhdHRyTmFtZSBpbiBwcm9wVmFsdWUpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHZhciBhdHRyVmFsdWUgPSBwcm9wVmFsdWVbYXR0ck5hbWVdO1xuXG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoYXR0clZhbHVlID09PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBub2RlLnJlbW92ZUF0dHJpYnV0ZShhdHRyTmFtZSk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIG5vZGUuc2V0QXR0cmlidXRlKGF0dHJOYW1lLCBhdHRyVmFsdWUpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIGlmIChwcmV2aW91c1ZhbHVlICYmIGlzT2JqZWN0KHByZXZpb3VzVmFsdWUpICYmIGdldFByb3RvdHlwZShwcmV2aW91c1ZhbHVlKSAhPT0gZ2V0UHJvdG90eXBlKHByb3BWYWx1ZSkpIHtcbiAgICAgICAgICAgICAgICAgICAgbm9kZVtwcm9wTmFtZV0gPSBwcm9wVmFsdWU7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICBpZiAoIWlzT2JqZWN0KG5vZGVbcHJvcE5hbWVdKSkge1xuICAgICAgICAgICAgICAgICAgICBub2RlW3Byb3BOYW1lXSA9IHt9O1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHZhciByZXBsYWNlciA9IHByb3BOYW1lID09PSBcInN0eWxlXCIgPyBcIlwiIDogdW5kZWZpbmVkO1xuXG4gICAgICAgICAgICAgICAgZm9yICh2YXIgayBpbiBwcm9wVmFsdWUpIHtcbiAgICAgICAgICAgICAgICAgICAgdmFyIHZhbHVlID0gcHJvcFZhbHVlW2tdO1xuICAgICAgICAgICAgICAgICAgICBub2RlW3Byb3BOYW1lXVtrXSA9IHZhbHVlID09PSB1bmRlZmluZWQgPyByZXBsYWNlciA6IHZhbHVlO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZnVuY3Rpb24gZ2V0UHJvdG90eXBlKHZhbHVlKSB7XG4gICAgICAgICAgICAgICAgaWYgKE9iamVjdC5nZXRQcm90b3R5cGVPZikge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gT2JqZWN0LmdldFByb3RvdHlwZU9mKHZhbHVlKTtcbiAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKHZhbHVlLl9fcHJvdG9fXykge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gdmFsdWUuX19wcm90b19fO1xuICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAodmFsdWUuY29uc3RydWN0b3IpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHZhbHVlLmNvbnN0cnVjdG9yLnByb3RvdHlwZTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH0sIHsgXCIuLi92bm9kZS9pcy12aG9vay5qc1wiOiAyNiwgXCJpcy1vYmplY3RcIjogMTEgfV0sIDE1OiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge1xuICAgICAgICAgICAgdmFyIGRvY3VtZW50ID0gcmVxdWlyZShcImdsb2JhbC9kb2N1bWVudFwiKTtcblxuICAgICAgICAgICAgdmFyIGFwcGx5UHJvcGVydGllcyA9IHJlcXVpcmUoXCIuL2FwcGx5LXByb3BlcnRpZXNcIik7XG5cbiAgICAgICAgICAgIHZhciBpc1ZOb2RlID0gcmVxdWlyZShcIi4uL3Zub2RlL2lzLXZub2RlLmpzXCIpO1xuICAgICAgICAgICAgdmFyIGlzVlRleHQgPSByZXF1aXJlKFwiLi4vdm5vZGUvaXMtdnRleHQuanNcIik7XG4gICAgICAgICAgICB2YXIgaXNXaWRnZXQgPSByZXF1aXJlKFwiLi4vdm5vZGUvaXMtd2lkZ2V0LmpzXCIpO1xuICAgICAgICAgICAgdmFyIGhhbmRsZVRodW5rID0gcmVxdWlyZShcIi4uL3Zub2RlL2hhbmRsZS10aHVuay5qc1wiKTtcblxuICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBjcmVhdGVFbGVtZW50O1xuXG4gICAgICAgICAgICBmdW5jdGlvbiBjcmVhdGVFbGVtZW50KHZub2RlLCBvcHRzKSB7XG4gICAgICAgICAgICAgICAgdmFyIGRvYyA9IG9wdHMgPyBvcHRzLmRvY3VtZW50IHx8IGRvY3VtZW50IDogZG9jdW1lbnQ7XG4gICAgICAgICAgICAgICAgdmFyIHdhcm4gPSBvcHRzID8gb3B0cy53YXJuIDogbnVsbDtcblxuICAgICAgICAgICAgICAgIHZub2RlID0gaGFuZGxlVGh1bmsodm5vZGUpLmE7XG5cbiAgICAgICAgICAgICAgICBpZiAoaXNXaWRnZXQodm5vZGUpKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiB2bm9kZS5pbml0KCk7XG4gICAgICAgICAgICAgICAgfSBlbHNlIGlmIChpc1ZUZXh0KHZub2RlKSkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gZG9jLmNyZWF0ZVRleHROb2RlKHZub2RlLnRleHQpO1xuICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoIWlzVk5vZGUodm5vZGUpKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmICh3YXJuKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICB3YXJuKFwiSXRlbSBpcyBub3QgYSB2YWxpZCB2aXJ0dWFsIGRvbSBub2RlXCIsIHZub2RlKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICByZXR1cm4gbnVsbDtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICB2YXIgbm9kZSA9IHZub2RlLm5hbWVzcGFjZSA9PT0gbnVsbCA/IGRvYy5jcmVhdGVFbGVtZW50KHZub2RlLnRhZ05hbWUpIDogZG9jLmNyZWF0ZUVsZW1lbnROUyh2bm9kZS5uYW1lc3BhY2UsIHZub2RlLnRhZ05hbWUpO1xuXG4gICAgICAgICAgICAgICAgdmFyIHByb3BzID0gdm5vZGUucHJvcGVydGllcztcbiAgICAgICAgICAgICAgICBhcHBseVByb3BlcnRpZXMobm9kZSwgcHJvcHMpO1xuXG4gICAgICAgICAgICAgICAgdmFyIGNoaWxkcmVuID0gdm5vZGUuY2hpbGRyZW47XG5cbiAgICAgICAgICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IGNoaWxkcmVuLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciBjaGlsZE5vZGUgPSBjcmVhdGVFbGVtZW50KGNoaWxkcmVuW2ldLCBvcHRzKTtcbiAgICAgICAgICAgICAgICAgICAgaWYgKGNoaWxkTm9kZSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgbm9kZS5hcHBlbmRDaGlsZChjaGlsZE5vZGUpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgcmV0dXJuIG5vZGU7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0sIHsgXCIuLi92bm9kZS9oYW5kbGUtdGh1bmsuanNcIjogMjQsIFwiLi4vdm5vZGUvaXMtdm5vZGUuanNcIjogMjcsIFwiLi4vdm5vZGUvaXMtdnRleHQuanNcIjogMjgsIFwiLi4vdm5vZGUvaXMtd2lkZ2V0LmpzXCI6IDI5LCBcIi4vYXBwbHktcHJvcGVydGllc1wiOiAxNCwgXCJnbG9iYWwvZG9jdW1lbnRcIjogMTAgfV0sIDE2OiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge1xuICAgICAgICAgICAgLy8gTWFwcyBhIHZpcnR1YWwgRE9NIHRyZWUgb250byBhIHJlYWwgRE9NIHRyZWUgaW4gYW4gZWZmaWNpZW50IG1hbm5lci5cbiAgICAgICAgICAgIC8vIFdlIGRvbid0IHdhbnQgdG8gcmVhZCBhbGwgb2YgdGhlIERPTSBub2RlcyBpbiB0aGUgdHJlZSBzbyB3ZSB1c2VcbiAgICAgICAgICAgIC8vIHRoZSBpbi1vcmRlciB0cmVlIGluZGV4aW5nIHRvIGVsaW1pbmF0ZSByZWN1cnNpb24gZG93biBjZXJ0YWluIGJyYW5jaGVzLlxuICAgICAgICAgICAgLy8gV2Ugb25seSByZWN1cnNlIGludG8gYSBET00gbm9kZSBpZiB3ZSBrbm93IHRoYXQgaXQgY29udGFpbnMgYSBjaGlsZCBvZlxuICAgICAgICAgICAgLy8gaW50ZXJlc3QuXG5cbiAgICAgICAgICAgIHZhciBub0NoaWxkID0ge307XG5cbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gZG9tSW5kZXg7XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIGRvbUluZGV4KHJvb3ROb2RlLCB0cmVlLCBpbmRpY2VzLCBub2Rlcykge1xuICAgICAgICAgICAgICAgIGlmICghaW5kaWNlcyB8fCBpbmRpY2VzLmxlbmd0aCA9PT0gMCkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4ge307XG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgaW5kaWNlcy5zb3J0KGFzY2VuZGluZyk7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiByZWN1cnNlKHJvb3ROb2RlLCB0cmVlLCBpbmRpY2VzLCBub2RlcywgMCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBmdW5jdGlvbiByZWN1cnNlKHJvb3ROb2RlLCB0cmVlLCBpbmRpY2VzLCBub2Rlcywgcm9vdEluZGV4KSB7XG4gICAgICAgICAgICAgICAgbm9kZXMgPSBub2RlcyB8fCB7fTtcblxuICAgICAgICAgICAgICAgIGlmIChyb290Tm9kZSkge1xuICAgICAgICAgICAgICAgICAgICBpZiAoaW5kZXhJblJhbmdlKGluZGljZXMsIHJvb3RJbmRleCwgcm9vdEluZGV4KSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgbm9kZXNbcm9vdEluZGV4XSA9IHJvb3ROb2RlO1xuICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgdmFyIHZDaGlsZHJlbiA9IHRyZWUuY2hpbGRyZW47XG5cbiAgICAgICAgICAgICAgICAgICAgaWYgKHZDaGlsZHJlbikge1xuXG4gICAgICAgICAgICAgICAgICAgICAgICB2YXIgY2hpbGROb2RlcyA9IHJvb3ROb2RlLmNoaWxkTm9kZXM7XG5cbiAgICAgICAgICAgICAgICAgICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgdHJlZS5jaGlsZHJlbi5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJvb3RJbmRleCArPSAxO1xuXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdmFyIHZDaGlsZCA9IHZDaGlsZHJlbltpXSB8fCBub0NoaWxkO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZhciBuZXh0SW5kZXggPSByb290SW5kZXggKyAodkNoaWxkLmNvdW50IHx8IDApO1xuXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gc2tpcCByZWN1cnNpb24gZG93biB0aGUgdHJlZSBpZiB0aGVyZSBhcmUgbm8gbm9kZXMgZG93biBoZXJlXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGluZGV4SW5SYW5nZShpbmRpY2VzLCByb290SW5kZXgsIG5leHRJbmRleCkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmVjdXJzZShjaGlsZE5vZGVzW2ldLCB2Q2hpbGQsIGluZGljZXMsIG5vZGVzLCByb290SW5kZXgpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJvb3RJbmRleCA9IG5leHRJbmRleDtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHJldHVybiBub2RlcztcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgLy8gQmluYXJ5IHNlYXJjaCBmb3IgYW4gaW5kZXggaW4gdGhlIGludGVydmFsIFtsZWZ0LCByaWdodF1cbiAgICAgICAgICAgIGZ1bmN0aW9uIGluZGV4SW5SYW5nZShpbmRpY2VzLCBsZWZ0LCByaWdodCkge1xuICAgICAgICAgICAgICAgIGlmIChpbmRpY2VzLmxlbmd0aCA9PT0gMCkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgdmFyIG1pbkluZGV4ID0gMDtcbiAgICAgICAgICAgICAgICB2YXIgbWF4SW5kZXggPSBpbmRpY2VzLmxlbmd0aCAtIDE7XG4gICAgICAgICAgICAgICAgdmFyIGN1cnJlbnRJbmRleDtcbiAgICAgICAgICAgICAgICB2YXIgY3VycmVudEl0ZW07XG5cbiAgICAgICAgICAgICAgICB3aGlsZSAobWluSW5kZXggPD0gbWF4SW5kZXgpIHtcbiAgICAgICAgICAgICAgICAgICAgY3VycmVudEluZGV4ID0gKG1heEluZGV4ICsgbWluSW5kZXgpIC8gMiA+PiAwO1xuICAgICAgICAgICAgICAgICAgICBjdXJyZW50SXRlbSA9IGluZGljZXNbY3VycmVudEluZGV4XTtcblxuICAgICAgICAgICAgICAgICAgICBpZiAobWluSW5kZXggPT09IG1heEluZGV4KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gY3VycmVudEl0ZW0gPj0gbGVmdCAmJiBjdXJyZW50SXRlbSA8PSByaWdodDtcbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIGlmIChjdXJyZW50SXRlbSA8IGxlZnQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIG1pbkluZGV4ID0gY3VycmVudEluZGV4ICsgMTtcbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIGlmIChjdXJyZW50SXRlbSA+IHJpZ2h0KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBtYXhJbmRleCA9IGN1cnJlbnRJbmRleCAtIDE7XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZnVuY3Rpb24gYXNjZW5kaW5nKGEsIGIpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gYSA+IGIgPyAxIDogLTE7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0sIHt9XSwgMTc6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICB2YXIgYXBwbHlQcm9wZXJ0aWVzID0gcmVxdWlyZShcIi4vYXBwbHktcHJvcGVydGllc1wiKTtcblxuICAgICAgICAgICAgdmFyIGlzV2lkZ2V0ID0gcmVxdWlyZShcIi4uL3Zub2RlL2lzLXdpZGdldC5qc1wiKTtcbiAgICAgICAgICAgIHZhciBWUGF0Y2ggPSByZXF1aXJlKFwiLi4vdm5vZGUvdnBhdGNoLmpzXCIpO1xuXG4gICAgICAgICAgICB2YXIgdXBkYXRlV2lkZ2V0ID0gcmVxdWlyZShcIi4vdXBkYXRlLXdpZGdldFwiKTtcblxuICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBhcHBseVBhdGNoO1xuXG4gICAgICAgICAgICBmdW5jdGlvbiBhcHBseVBhdGNoKHZwYXRjaCwgZG9tTm9kZSwgcmVuZGVyT3B0aW9ucykge1xuICAgICAgICAgICAgICAgIHZhciB0eXBlID0gdnBhdGNoLnR5cGU7XG4gICAgICAgICAgICAgICAgdmFyIHZOb2RlID0gdnBhdGNoLnZOb2RlO1xuICAgICAgICAgICAgICAgIHZhciBwYXRjaCA9IHZwYXRjaC5wYXRjaDtcblxuICAgICAgICAgICAgICAgIHN3aXRjaCAodHlwZSkge1xuICAgICAgICAgICAgICAgICAgICBjYXNlIFZQYXRjaC5SRU1PVkU6XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gcmVtb3ZlTm9kZShkb21Ob2RlLCB2Tm9kZSk7XG4gICAgICAgICAgICAgICAgICAgIGNhc2UgVlBhdGNoLklOU0VSVDpcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBpbnNlcnROb2RlKGRvbU5vZGUsIHBhdGNoLCByZW5kZXJPcHRpb25zKTtcbiAgICAgICAgICAgICAgICAgICAgY2FzZSBWUGF0Y2guVlRFWFQ6XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gc3RyaW5nUGF0Y2goZG9tTm9kZSwgdk5vZGUsIHBhdGNoLCByZW5kZXJPcHRpb25zKTtcbiAgICAgICAgICAgICAgICAgICAgY2FzZSBWUGF0Y2guV0lER0VUOlxuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHdpZGdldFBhdGNoKGRvbU5vZGUsIHZOb2RlLCBwYXRjaCwgcmVuZGVyT3B0aW9ucyk7XG4gICAgICAgICAgICAgICAgICAgIGNhc2UgVlBhdGNoLlZOT0RFOlxuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHZOb2RlUGF0Y2goZG9tTm9kZSwgdk5vZGUsIHBhdGNoLCByZW5kZXJPcHRpb25zKTtcbiAgICAgICAgICAgICAgICAgICAgY2FzZSBWUGF0Y2guT1JERVI6XG4gICAgICAgICAgICAgICAgICAgICAgICByZW9yZGVyQ2hpbGRyZW4oZG9tTm9kZSwgcGF0Y2gpO1xuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGRvbU5vZGU7XG4gICAgICAgICAgICAgICAgICAgIGNhc2UgVlBhdGNoLlBST1BTOlxuICAgICAgICAgICAgICAgICAgICAgICAgYXBwbHlQcm9wZXJ0aWVzKGRvbU5vZGUsIHBhdGNoLCB2Tm9kZS5wcm9wZXJ0aWVzKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBkb21Ob2RlO1xuICAgICAgICAgICAgICAgICAgICBjYXNlIFZQYXRjaC5USFVOSzpcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiByZXBsYWNlUm9vdChkb21Ob2RlLCByZW5kZXJPcHRpb25zLnBhdGNoKGRvbU5vZGUsIHBhdGNoLCByZW5kZXJPcHRpb25zKSk7XG4gICAgICAgICAgICAgICAgICAgIGRlZmF1bHQ6XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gZG9tTm9kZTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIHJlbW92ZU5vZGUoZG9tTm9kZSwgdk5vZGUpIHtcbiAgICAgICAgICAgICAgICB2YXIgcGFyZW50Tm9kZSA9IGRvbU5vZGUucGFyZW50Tm9kZTtcblxuICAgICAgICAgICAgICAgIGlmIChwYXJlbnROb2RlKSB7XG4gICAgICAgICAgICAgICAgICAgIHBhcmVudE5vZGUucmVtb3ZlQ2hpbGQoZG9tTm9kZSk7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgZGVzdHJveVdpZGdldChkb21Ob2RlLCB2Tm9kZSk7XG5cbiAgICAgICAgICAgICAgICByZXR1cm4gbnVsbDtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZnVuY3Rpb24gaW5zZXJ0Tm9kZShwYXJlbnROb2RlLCB2Tm9kZSwgcmVuZGVyT3B0aW9ucykge1xuICAgICAgICAgICAgICAgIHZhciBuZXdOb2RlID0gcmVuZGVyT3B0aW9ucy5yZW5kZXIodk5vZGUsIHJlbmRlck9wdGlvbnMpO1xuXG4gICAgICAgICAgICAgICAgaWYgKHBhcmVudE5vZGUpIHtcbiAgICAgICAgICAgICAgICAgICAgcGFyZW50Tm9kZS5hcHBlbmRDaGlsZChuZXdOb2RlKTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICByZXR1cm4gcGFyZW50Tm9kZTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZnVuY3Rpb24gc3RyaW5nUGF0Y2goZG9tTm9kZSwgbGVmdFZOb2RlLCB2VGV4dCwgcmVuZGVyT3B0aW9ucykge1xuICAgICAgICAgICAgICAgIHZhciBuZXdOb2RlO1xuXG4gICAgICAgICAgICAgICAgaWYgKGRvbU5vZGUubm9kZVR5cGUgPT09IDMpIHtcbiAgICAgICAgICAgICAgICAgICAgZG9tTm9kZS5yZXBsYWNlRGF0YSgwLCBkb21Ob2RlLmxlbmd0aCwgdlRleHQudGV4dCk7XG4gICAgICAgICAgICAgICAgICAgIG5ld05vZGUgPSBkb21Ob2RlO1xuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciBwYXJlbnROb2RlID0gZG9tTm9kZS5wYXJlbnROb2RlO1xuICAgICAgICAgICAgICAgICAgICBuZXdOb2RlID0gcmVuZGVyT3B0aW9ucy5yZW5kZXIodlRleHQsIHJlbmRlck9wdGlvbnMpO1xuXG4gICAgICAgICAgICAgICAgICAgIGlmIChwYXJlbnROb2RlICYmIG5ld05vZGUgIT09IGRvbU5vZGUpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHBhcmVudE5vZGUucmVwbGFjZUNoaWxkKG5ld05vZGUsIGRvbU5vZGUpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgcmV0dXJuIG5ld05vZGU7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIHdpZGdldFBhdGNoKGRvbU5vZGUsIGxlZnRWTm9kZSwgd2lkZ2V0LCByZW5kZXJPcHRpb25zKSB7XG4gICAgICAgICAgICAgICAgdmFyIHVwZGF0aW5nID0gdXBkYXRlV2lkZ2V0KGxlZnRWTm9kZSwgd2lkZ2V0KTtcbiAgICAgICAgICAgICAgICB2YXIgbmV3Tm9kZTtcblxuICAgICAgICAgICAgICAgIGlmICh1cGRhdGluZykge1xuICAgICAgICAgICAgICAgICAgICBuZXdOb2RlID0gd2lkZ2V0LnVwZGF0ZShsZWZ0Vk5vZGUsIGRvbU5vZGUpIHx8IGRvbU5vZGU7XG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgbmV3Tm9kZSA9IHJlbmRlck9wdGlvbnMucmVuZGVyKHdpZGdldCwgcmVuZGVyT3B0aW9ucyk7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgdmFyIHBhcmVudE5vZGUgPSBkb21Ob2RlLnBhcmVudE5vZGU7XG5cbiAgICAgICAgICAgICAgICBpZiAocGFyZW50Tm9kZSAmJiBuZXdOb2RlICE9PSBkb21Ob2RlKSB7XG4gICAgICAgICAgICAgICAgICAgIHBhcmVudE5vZGUucmVwbGFjZUNoaWxkKG5ld05vZGUsIGRvbU5vZGUpO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIGlmICghdXBkYXRpbmcpIHtcbiAgICAgICAgICAgICAgICAgICAgZGVzdHJveVdpZGdldChkb21Ob2RlLCBsZWZ0Vk5vZGUpO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHJldHVybiBuZXdOb2RlO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBmdW5jdGlvbiB2Tm9kZVBhdGNoKGRvbU5vZGUsIGxlZnRWTm9kZSwgdk5vZGUsIHJlbmRlck9wdGlvbnMpIHtcbiAgICAgICAgICAgICAgICB2YXIgcGFyZW50Tm9kZSA9IGRvbU5vZGUucGFyZW50Tm9kZTtcbiAgICAgICAgICAgICAgICB2YXIgbmV3Tm9kZSA9IHJlbmRlck9wdGlvbnMucmVuZGVyKHZOb2RlLCByZW5kZXJPcHRpb25zKTtcblxuICAgICAgICAgICAgICAgIGlmIChwYXJlbnROb2RlICYmIG5ld05vZGUgIT09IGRvbU5vZGUpIHtcbiAgICAgICAgICAgICAgICAgICAgcGFyZW50Tm9kZS5yZXBsYWNlQ2hpbGQobmV3Tm9kZSwgZG9tTm9kZSk7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgcmV0dXJuIG5ld05vZGU7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIGRlc3Ryb3lXaWRnZXQoZG9tTm9kZSwgdykge1xuICAgICAgICAgICAgICAgIGlmICh0eXBlb2Ygdy5kZXN0cm95ID09PSBcImZ1bmN0aW9uXCIgJiYgaXNXaWRnZXQodykpIHtcbiAgICAgICAgICAgICAgICAgICAgdy5kZXN0cm95KGRvbU5vZGUpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZnVuY3Rpb24gcmVvcmRlckNoaWxkcmVuKGRvbU5vZGUsIG1vdmVzKSB7XG4gICAgICAgICAgICAgICAgdmFyIGNoaWxkTm9kZXMgPSBkb21Ob2RlLmNoaWxkTm9kZXM7XG4gICAgICAgICAgICAgICAgdmFyIGtleU1hcCA9IHt9O1xuICAgICAgICAgICAgICAgIHZhciBub2RlO1xuICAgICAgICAgICAgICAgIHZhciByZW1vdmU7XG4gICAgICAgICAgICAgICAgdmFyIGluc2VydDtcblxuICAgICAgICAgICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgbW92ZXMucmVtb3Zlcy5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgICAgICAgICByZW1vdmUgPSBtb3Zlcy5yZW1vdmVzW2ldO1xuICAgICAgICAgICAgICAgICAgICBub2RlID0gY2hpbGROb2Rlc1tyZW1vdmUuZnJvbV07XG4gICAgICAgICAgICAgICAgICAgIGlmIChyZW1vdmUua2V5KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBrZXlNYXBbcmVtb3ZlLmtleV0gPSBub2RlO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIGRvbU5vZGUucmVtb3ZlQ2hpbGQobm9kZSk7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgdmFyIGxlbmd0aCA9IGNoaWxkTm9kZXMubGVuZ3RoO1xuICAgICAgICAgICAgICAgIGZvciAodmFyIGogPSAwOyBqIDwgbW92ZXMuaW5zZXJ0cy5sZW5ndGg7IGorKykge1xuICAgICAgICAgICAgICAgICAgICBpbnNlcnQgPSBtb3Zlcy5pbnNlcnRzW2pdO1xuICAgICAgICAgICAgICAgICAgICBub2RlID0ga2V5TWFwW2luc2VydC5rZXldO1xuICAgICAgICAgICAgICAgICAgICAvLyB0aGlzIGlzIHRoZSB3ZWlyZGVzdCBidWcgaSd2ZSBldmVyIHNlZW4gaW4gd2Via2l0XG4gICAgICAgICAgICAgICAgICAgIGRvbU5vZGUuaW5zZXJ0QmVmb3JlKG5vZGUsIGluc2VydC50byA+PSBsZW5ndGgrKyA/IG51bGwgOiBjaGlsZE5vZGVzW2luc2VydC50b10pO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZnVuY3Rpb24gcmVwbGFjZVJvb3Qob2xkUm9vdCwgbmV3Um9vdCkge1xuICAgICAgICAgICAgICAgIGlmIChvbGRSb290ICYmIG5ld1Jvb3QgJiYgb2xkUm9vdCAhPT0gbmV3Um9vdCAmJiBvbGRSb290LnBhcmVudE5vZGUpIHtcbiAgICAgICAgICAgICAgICAgICAgb2xkUm9vdC5wYXJlbnROb2RlLnJlcGxhY2VDaGlsZChuZXdSb290LCBvbGRSb290KTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICByZXR1cm4gbmV3Um9vdDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSwgeyBcIi4uL3Zub2RlL2lzLXdpZGdldC5qc1wiOiAyOSwgXCIuLi92bm9kZS92cGF0Y2guanNcIjogMzIsIFwiLi9hcHBseS1wcm9wZXJ0aWVzXCI6IDE0LCBcIi4vdXBkYXRlLXdpZGdldFwiOiAxOSB9XSwgMTg6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICB2YXIgZG9jdW1lbnQgPSByZXF1aXJlKFwiZ2xvYmFsL2RvY3VtZW50XCIpO1xuICAgICAgICAgICAgdmFyIGlzQXJyYXkgPSByZXF1aXJlKFwieC1pcy1hcnJheVwiKTtcblxuICAgICAgICAgICAgdmFyIHJlbmRlciA9IHJlcXVpcmUoXCIuL2NyZWF0ZS1lbGVtZW50XCIpO1xuICAgICAgICAgICAgdmFyIGRvbUluZGV4ID0gcmVxdWlyZShcIi4vZG9tLWluZGV4XCIpO1xuICAgICAgICAgICAgdmFyIHBhdGNoT3AgPSByZXF1aXJlKFwiLi9wYXRjaC1vcFwiKTtcbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gcGF0Y2g7XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIHBhdGNoKHJvb3ROb2RlLCBwYXRjaGVzLCByZW5kZXJPcHRpb25zKSB7XG4gICAgICAgICAgICAgICAgcmVuZGVyT3B0aW9ucyA9IHJlbmRlck9wdGlvbnMgfHwge307XG4gICAgICAgICAgICAgICAgcmVuZGVyT3B0aW9ucy5wYXRjaCA9IHJlbmRlck9wdGlvbnMucGF0Y2ggJiYgcmVuZGVyT3B0aW9ucy5wYXRjaCAhPT0gcGF0Y2ggPyByZW5kZXJPcHRpb25zLnBhdGNoIDogcGF0Y2hSZWN1cnNpdmU7XG4gICAgICAgICAgICAgICAgcmVuZGVyT3B0aW9ucy5yZW5kZXIgPSByZW5kZXJPcHRpb25zLnJlbmRlciB8fCByZW5kZXI7XG5cbiAgICAgICAgICAgICAgICByZXR1cm4gcmVuZGVyT3B0aW9ucy5wYXRjaChyb290Tm9kZSwgcGF0Y2hlcywgcmVuZGVyT3B0aW9ucyk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIHBhdGNoUmVjdXJzaXZlKHJvb3ROb2RlLCBwYXRjaGVzLCByZW5kZXJPcHRpb25zKSB7XG4gICAgICAgICAgICAgICAgdmFyIGluZGljZXMgPSBwYXRjaEluZGljZXMocGF0Y2hlcyk7XG5cbiAgICAgICAgICAgICAgICBpZiAoaW5kaWNlcy5sZW5ndGggPT09IDApIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHJvb3ROb2RlO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHZhciBpbmRleCA9IGRvbUluZGV4KHJvb3ROb2RlLCBwYXRjaGVzLmEsIGluZGljZXMpO1xuICAgICAgICAgICAgICAgIHZhciBvd25lckRvY3VtZW50ID0gcm9vdE5vZGUub3duZXJEb2N1bWVudDtcblxuICAgICAgICAgICAgICAgIGlmICghcmVuZGVyT3B0aW9ucy5kb2N1bWVudCAmJiBvd25lckRvY3VtZW50ICE9PSBkb2N1bWVudCkge1xuICAgICAgICAgICAgICAgICAgICByZW5kZXJPcHRpb25zLmRvY3VtZW50ID0gb3duZXJEb2N1bWVudDtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IGluZGljZXMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgICAgICAgICAgdmFyIG5vZGVJbmRleCA9IGluZGljZXNbaV07XG4gICAgICAgICAgICAgICAgICAgIHJvb3ROb2RlID0gYXBwbHlQYXRjaChyb290Tm9kZSwgaW5kZXhbbm9kZUluZGV4XSwgcGF0Y2hlc1tub2RlSW5kZXhdLCByZW5kZXJPcHRpb25zKTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICByZXR1cm4gcm9vdE5vZGU7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIGFwcGx5UGF0Y2gocm9vdE5vZGUsIGRvbU5vZGUsIHBhdGNoTGlzdCwgcmVuZGVyT3B0aW9ucykge1xuICAgICAgICAgICAgICAgIGlmICghZG9tTm9kZSkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gcm9vdE5vZGU7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgdmFyIG5ld05vZGU7XG5cbiAgICAgICAgICAgICAgICBpZiAoaXNBcnJheShwYXRjaExpc3QpKSB7XG4gICAgICAgICAgICAgICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgcGF0Y2hMaXN0Lmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBuZXdOb2RlID0gcGF0Y2hPcChwYXRjaExpc3RbaV0sIGRvbU5vZGUsIHJlbmRlck9wdGlvbnMpO1xuXG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoZG9tTm9kZSA9PT0gcm9vdE5vZGUpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICByb290Tm9kZSA9IG5ld05vZGU7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICBuZXdOb2RlID0gcGF0Y2hPcChwYXRjaExpc3QsIGRvbU5vZGUsIHJlbmRlck9wdGlvbnMpO1xuXG4gICAgICAgICAgICAgICAgICAgIGlmIChkb21Ob2RlID09PSByb290Tm9kZSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgcm9vdE5vZGUgPSBuZXdOb2RlO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgcmV0dXJuIHJvb3ROb2RlO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBmdW5jdGlvbiBwYXRjaEluZGljZXMocGF0Y2hlcykge1xuICAgICAgICAgICAgICAgIHZhciBpbmRpY2VzID0gW107XG5cbiAgICAgICAgICAgICAgICBmb3IgKHZhciBrZXkgaW4gcGF0Y2hlcykge1xuICAgICAgICAgICAgICAgICAgICBpZiAoa2V5ICE9PSBcImFcIikge1xuICAgICAgICAgICAgICAgICAgICAgICAgaW5kaWNlcy5wdXNoKE51bWJlcihrZXkpKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHJldHVybiBpbmRpY2VzO1xuICAgICAgICAgICAgfVxuICAgICAgICB9LCB7IFwiLi9jcmVhdGUtZWxlbWVudFwiOiAxNSwgXCIuL2RvbS1pbmRleFwiOiAxNiwgXCIuL3BhdGNoLW9wXCI6IDE3LCBcImdsb2JhbC9kb2N1bWVudFwiOiAxMCwgXCJ4LWlzLWFycmF5XCI6IDEyIH1dLCAxOTogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHtcbiAgICAgICAgICAgIHZhciBpc1dpZGdldCA9IHJlcXVpcmUoXCIuLi92bm9kZS9pcy13aWRnZXQuanNcIik7XG5cbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gdXBkYXRlV2lkZ2V0O1xuXG4gICAgICAgICAgICBmdW5jdGlvbiB1cGRhdGVXaWRnZXQoYSwgYikge1xuICAgICAgICAgICAgICAgIGlmIChpc1dpZGdldChhKSAmJiBpc1dpZGdldChiKSkge1xuICAgICAgICAgICAgICAgICAgICBpZiAoXCJuYW1lXCIgaW4gYSAmJiBcIm5hbWVcIiBpbiBiKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gYS5pZCA9PT0gYi5pZDtcbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBhLmluaXQgPT09IGIuaW5pdDtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSwgeyBcIi4uL3Zub2RlL2lzLXdpZGdldC5qc1wiOiAyOSB9XSwgMjA6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICBcInVzZSBzdHJpY3RcIjtcblxuICAgICAgICAgICAgdmFyIEV2U3RvcmUgPSByZXF1aXJlKFwiZXYtc3RvcmVcIik7XG5cbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gRXZIb29rO1xuXG4gICAgICAgICAgICBmdW5jdGlvbiBFdkhvb2sodmFsdWUpIHtcbiAgICAgICAgICAgICAgICBpZiAoISh0aGlzIGluc3RhbmNlb2YgRXZIb29rKSkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gbmV3IEV2SG9vayh2YWx1ZSk7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgdGhpcy52YWx1ZSA9IHZhbHVlO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBFdkhvb2sucHJvdG90eXBlLmhvb2sgPSBmdW5jdGlvbiAobm9kZSwgcHJvcGVydHlOYW1lKSB7XG4gICAgICAgICAgICAgICAgdmFyIGVzID0gRXZTdG9yZShub2RlKTtcbiAgICAgICAgICAgICAgICB2YXIgcHJvcE5hbWUgPSBwcm9wZXJ0eU5hbWUuc3Vic3RyKDMpO1xuXG4gICAgICAgICAgICAgICAgZXNbcHJvcE5hbWVdID0gdGhpcy52YWx1ZTtcbiAgICAgICAgICAgIH07XG5cbiAgICAgICAgICAgIEV2SG9vay5wcm90b3R5cGUudW5ob29rID0gZnVuY3Rpb24gKG5vZGUsIHByb3BlcnR5TmFtZSkge1xuICAgICAgICAgICAgICAgIHZhciBlcyA9IEV2U3RvcmUobm9kZSk7XG4gICAgICAgICAgICAgICAgdmFyIHByb3BOYW1lID0gcHJvcGVydHlOYW1lLnN1YnN0cigzKTtcblxuICAgICAgICAgICAgICAgIGVzW3Byb3BOYW1lXSA9IHVuZGVmaW5lZDtcbiAgICAgICAgICAgIH07XG4gICAgICAgIH0sIHsgXCJldi1zdG9yZVwiOiA3IH1dLCAyMTogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHtcbiAgICAgICAgICAgIFwidXNlIHN0cmljdFwiO1xuXG4gICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IFNvZnRTZXRIb29rO1xuXG4gICAgICAgICAgICBmdW5jdGlvbiBTb2Z0U2V0SG9vayh2YWx1ZSkge1xuICAgICAgICAgICAgICAgIGlmICghKHRoaXMgaW5zdGFuY2VvZiBTb2Z0U2V0SG9vaykpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIG5ldyBTb2Z0U2V0SG9vayh2YWx1ZSk7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgdGhpcy52YWx1ZSA9IHZhbHVlO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBTb2Z0U2V0SG9vay5wcm90b3R5cGUuaG9vayA9IGZ1bmN0aW9uIChub2RlLCBwcm9wZXJ0eU5hbWUpIHtcbiAgICAgICAgICAgICAgICBpZiAobm9kZVtwcm9wZXJ0eU5hbWVdICE9PSB0aGlzLnZhbHVlKSB7XG4gICAgICAgICAgICAgICAgICAgIG5vZGVbcHJvcGVydHlOYW1lXSA9IHRoaXMudmFsdWU7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfTtcbiAgICAgICAgfSwge31dLCAyMjogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHtcbiAgICAgICAgICAgIFwidXNlIHN0cmljdFwiO1xuXG4gICAgICAgICAgICB2YXIgaXNBcnJheSA9IHJlcXVpcmUoXCJ4LWlzLWFycmF5XCIpO1xuXG4gICAgICAgICAgICB2YXIgVk5vZGUgPSByZXF1aXJlKFwiLi4vdm5vZGUvdm5vZGUuanNcIik7XG4gICAgICAgICAgICB2YXIgVlRleHQgPSByZXF1aXJlKFwiLi4vdm5vZGUvdnRleHQuanNcIik7XG4gICAgICAgICAgICB2YXIgaXNWTm9kZSA9IHJlcXVpcmUoXCIuLi92bm9kZS9pcy12bm9kZVwiKTtcbiAgICAgICAgICAgIHZhciBpc1ZUZXh0ID0gcmVxdWlyZShcIi4uL3Zub2RlL2lzLXZ0ZXh0XCIpO1xuICAgICAgICAgICAgdmFyIGlzV2lkZ2V0ID0gcmVxdWlyZShcIi4uL3Zub2RlL2lzLXdpZGdldFwiKTtcbiAgICAgICAgICAgIHZhciBpc0hvb2sgPSByZXF1aXJlKFwiLi4vdm5vZGUvaXMtdmhvb2tcIik7XG4gICAgICAgICAgICB2YXIgaXNWVGh1bmsgPSByZXF1aXJlKFwiLi4vdm5vZGUvaXMtdGh1bmtcIik7XG5cbiAgICAgICAgICAgIHZhciBwYXJzZVRhZyA9IHJlcXVpcmUoXCIuL3BhcnNlLXRhZy5qc1wiKTtcbiAgICAgICAgICAgIHZhciBzb2Z0U2V0SG9vayA9IHJlcXVpcmUoXCIuL2hvb2tzL3NvZnQtc2V0LWhvb2suanNcIik7XG4gICAgICAgICAgICB2YXIgZXZIb29rID0gcmVxdWlyZShcIi4vaG9va3MvZXYtaG9vay5qc1wiKTtcblxuICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBoO1xuXG4gICAgICAgICAgICBmdW5jdGlvbiBoKHRhZ05hbWUsIHByb3BlcnRpZXMsIGNoaWxkcmVuKSB7XG4gICAgICAgICAgICAgICAgdmFyIGNoaWxkTm9kZXMgPSBbXTtcbiAgICAgICAgICAgICAgICB2YXIgdGFnLCBwcm9wcywga2V5LCBuYW1lc3BhY2U7XG5cbiAgICAgICAgICAgICAgICBpZiAoIWNoaWxkcmVuICYmIGlzQ2hpbGRyZW4ocHJvcGVydGllcykpIHtcbiAgICAgICAgICAgICAgICAgICAgY2hpbGRyZW4gPSBwcm9wZXJ0aWVzO1xuICAgICAgICAgICAgICAgICAgICBwcm9wcyA9IHt9O1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHByb3BzID0gcHJvcHMgfHwgcHJvcGVydGllcyB8fCB7fTtcbiAgICAgICAgICAgICAgICB0YWcgPSBwYXJzZVRhZyh0YWdOYW1lLCBwcm9wcyk7XG5cbiAgICAgICAgICAgICAgICAvLyBzdXBwb3J0IGtleXNcbiAgICAgICAgICAgICAgICBpZiAocHJvcHMuaGFzT3duUHJvcGVydHkoXCJrZXlcIikpIHtcbiAgICAgICAgICAgICAgICAgICAga2V5ID0gcHJvcHMua2V5O1xuICAgICAgICAgICAgICAgICAgICBwcm9wcy5rZXkgPSB1bmRlZmluZWQ7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgLy8gc3VwcG9ydCBuYW1lc3BhY2VcbiAgICAgICAgICAgICAgICBpZiAocHJvcHMuaGFzT3duUHJvcGVydHkoXCJuYW1lc3BhY2VcIikpIHtcbiAgICAgICAgICAgICAgICAgICAgbmFtZXNwYWNlID0gcHJvcHMubmFtZXNwYWNlO1xuICAgICAgICAgICAgICAgICAgICBwcm9wcy5uYW1lc3BhY2UgPSB1bmRlZmluZWQ7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgLy8gZml4IGN1cnNvciBidWdcbiAgICAgICAgICAgICAgICBpZiAodGFnID09PSBcIklOUFVUXCIgJiYgIW5hbWVzcGFjZSAmJiBwcm9wcy5oYXNPd25Qcm9wZXJ0eShcInZhbHVlXCIpICYmIHByb3BzLnZhbHVlICE9PSB1bmRlZmluZWQgJiYgIWlzSG9vayhwcm9wcy52YWx1ZSkpIHtcbiAgICAgICAgICAgICAgICAgICAgcHJvcHMudmFsdWUgPSBzb2Z0U2V0SG9vayhwcm9wcy52YWx1ZSk7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgdHJhbnNmb3JtUHJvcGVydGllcyhwcm9wcyk7XG5cbiAgICAgICAgICAgICAgICBpZiAoY2hpbGRyZW4gIT09IHVuZGVmaW5lZCAmJiBjaGlsZHJlbiAhPT0gbnVsbCkge1xuICAgICAgICAgICAgICAgICAgICBhZGRDaGlsZChjaGlsZHJlbiwgY2hpbGROb2RlcywgdGFnLCBwcm9wcyk7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgcmV0dXJuIG5ldyBWTm9kZSh0YWcsIHByb3BzLCBjaGlsZE5vZGVzLCBrZXksIG5hbWVzcGFjZSk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIGFkZENoaWxkKGMsIGNoaWxkTm9kZXMsIHRhZywgcHJvcHMpIHtcbiAgICAgICAgICAgICAgICBpZiAodHlwZW9mIGMgPT09IFwic3RyaW5nXCIpIHtcbiAgICAgICAgICAgICAgICAgICAgY2hpbGROb2Rlcy5wdXNoKG5ldyBWVGV4dChjKSk7XG4gICAgICAgICAgICAgICAgfSBlbHNlIGlmICh0eXBlb2YgYyA9PT0gXCJudW1iZXJcIikge1xuICAgICAgICAgICAgICAgICAgICBjaGlsZE5vZGVzLnB1c2gobmV3IFZUZXh0KFN0cmluZyhjKSkpO1xuICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoaXNDaGlsZChjKSkge1xuICAgICAgICAgICAgICAgICAgICBjaGlsZE5vZGVzLnB1c2goYyk7XG4gICAgICAgICAgICAgICAgfSBlbHNlIGlmIChpc0FycmF5KGMpKSB7XG4gICAgICAgICAgICAgICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgYy5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgICAgICAgICAgICAgYWRkQ2hpbGQoY1tpXSwgY2hpbGROb2RlcywgdGFnLCBwcm9wcyk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKGMgPT09IG51bGwgfHwgYyA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICB0aHJvdyBVbmV4cGVjdGVkVmlydHVhbEVsZW1lbnQoe1xuICAgICAgICAgICAgICAgICAgICAgICAgZm9yZWlnbk9iamVjdDogYyxcbiAgICAgICAgICAgICAgICAgICAgICAgIHBhcmVudFZub2RlOiB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdGFnTmFtZTogdGFnLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHByb3BlcnRpZXM6IHByb3BzXG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZnVuY3Rpb24gdHJhbnNmb3JtUHJvcGVydGllcyhwcm9wcykge1xuICAgICAgICAgICAgICAgIGZvciAodmFyIHByb3BOYW1lIGluIHByb3BzKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmIChwcm9wcy5oYXNPd25Qcm9wZXJ0eShwcm9wTmFtZSkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHZhciB2YWx1ZSA9IHByb3BzW3Byb3BOYW1lXTtcblxuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGlzSG9vayh2YWx1ZSkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb250aW51ZTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHByb3BOYW1lLnN1YnN0cigwLCAzKSA9PT0gXCJldi1cIikge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIGFkZCBldi1mb28gc3VwcG9ydFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHByb3BzW3Byb3BOYW1lXSA9IGV2SG9vayh2YWx1ZSk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIGlzQ2hpbGQoeCkge1xuICAgICAgICAgICAgICAgIHJldHVybiBpc1ZOb2RlKHgpIHx8IGlzVlRleHQoeCkgfHwgaXNXaWRnZXQoeCkgfHwgaXNWVGh1bmsoeCk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIGlzQ2hpbGRyZW4oeCkge1xuICAgICAgICAgICAgICAgIHJldHVybiB0eXBlb2YgeCA9PT0gXCJzdHJpbmdcIiB8fCBpc0FycmF5KHgpIHx8IGlzQ2hpbGQoeCk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIFVuZXhwZWN0ZWRWaXJ0dWFsRWxlbWVudChkYXRhKSB7XG4gICAgICAgICAgICAgICAgdmFyIGVyciA9IG5ldyBFcnJvcigpO1xuXG4gICAgICAgICAgICAgICAgZXJyLnR5cGUgPSBcInZpcnR1YWwtaHlwZXJzY3JpcHQudW5leHBlY3RlZC52aXJ0dWFsLWVsZW1lbnRcIjtcbiAgICAgICAgICAgICAgICBlcnIubWVzc2FnZSA9IFwiVW5leHBlY3RlZCB2aXJ0dWFsIGNoaWxkIHBhc3NlZCB0byBoKCkuXFxuXCIgKyBcIkV4cGVjdGVkIGEgVk5vZGUgLyBWdGh1bmsgLyBWV2lkZ2V0IC8gc3RyaW5nIGJ1dDpcXG5cIiArIFwiZ290OlxcblwiICsgZXJyb3JTdHJpbmcoZGF0YS5mb3JlaWduT2JqZWN0KSArIFwiLlxcblwiICsgXCJUaGUgcGFyZW50IHZub2RlIGlzOlxcblwiICsgZXJyb3JTdHJpbmcoZGF0YS5wYXJlbnRWbm9kZSk7XG4gICAgICAgICAgICAgICAgXCJcXG5cIiArIFwiU3VnZ2VzdGVkIGZpeDogY2hhbmdlIHlvdXIgYGgoLi4uLCBbIC4uLiBdKWAgY2FsbHNpdGUuXCI7XG4gICAgICAgICAgICAgICAgZXJyLmZvcmVpZ25PYmplY3QgPSBkYXRhLmZvcmVpZ25PYmplY3Q7XG4gICAgICAgICAgICAgICAgZXJyLnBhcmVudFZub2RlID0gZGF0YS5wYXJlbnRWbm9kZTtcblxuICAgICAgICAgICAgICAgIHJldHVybiBlcnI7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIGVycm9yU3RyaW5nKG9iaikge1xuICAgICAgICAgICAgICAgIHRyeSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBKU09OLnN0cmluZ2lmeShvYmosIG51bGwsIFwiICAgIFwiKTtcbiAgICAgICAgICAgICAgICB9IGNhdGNoIChlKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBTdHJpbmcob2JqKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH0sIHsgXCIuLi92bm9kZS9pcy10aHVua1wiOiAyNSwgXCIuLi92bm9kZS9pcy12aG9va1wiOiAyNiwgXCIuLi92bm9kZS9pcy12bm9kZVwiOiAyNywgXCIuLi92bm9kZS9pcy12dGV4dFwiOiAyOCwgXCIuLi92bm9kZS9pcy13aWRnZXRcIjogMjksIFwiLi4vdm5vZGUvdm5vZGUuanNcIjogMzEsIFwiLi4vdm5vZGUvdnRleHQuanNcIjogMzMsIFwiLi9ob29rcy9ldi1ob29rLmpzXCI6IDIwLCBcIi4vaG9va3Mvc29mdC1zZXQtaG9vay5qc1wiOiAyMSwgXCIuL3BhcnNlLXRhZy5qc1wiOiAyMywgXCJ4LWlzLWFycmF5XCI6IDEyIH1dLCAyMzogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHtcbiAgICAgICAgICAgIFwidXNlIHN0cmljdFwiO1xuXG4gICAgICAgICAgICB2YXIgc3BsaXQgPSByZXF1aXJlKFwiYnJvd3Nlci1zcGxpdFwiKTtcblxuICAgICAgICAgICAgdmFyIGNsYXNzSWRTcGxpdCA9IC8oW1xcLiNdP1thLXpBLVowLTlcXHUwMDdGLVxcdUZGRkZfOi1dKykvO1xuICAgICAgICAgICAgdmFyIG5vdENsYXNzSWQgPSAvXlxcLnwjLztcblxuICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBwYXJzZVRhZztcblxuICAgICAgICAgICAgZnVuY3Rpb24gcGFyc2VUYWcodGFnLCBwcm9wcykge1xuICAgICAgICAgICAgICAgIGlmICghdGFnKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBcIkRJVlwiO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHZhciBub0lkID0gIXByb3BzLmhhc093blByb3BlcnR5KFwiaWRcIik7XG5cbiAgICAgICAgICAgICAgICB2YXIgdGFnUGFydHMgPSBzcGxpdCh0YWcsIGNsYXNzSWRTcGxpdCk7XG4gICAgICAgICAgICAgICAgdmFyIHRhZ05hbWUgPSBudWxsO1xuXG4gICAgICAgICAgICAgICAgaWYgKG5vdENsYXNzSWQudGVzdCh0YWdQYXJ0c1sxXSkpIHtcbiAgICAgICAgICAgICAgICAgICAgdGFnTmFtZSA9IFwiRElWXCI7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgdmFyIGNsYXNzZXMsIHBhcnQsIHR5cGUsIGk7XG5cbiAgICAgICAgICAgICAgICBmb3IgKGkgPSAwOyBpIDwgdGFnUGFydHMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgICAgICAgICAgcGFydCA9IHRhZ1BhcnRzW2ldO1xuXG4gICAgICAgICAgICAgICAgICAgIGlmICghcGFydCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgY29udGludWU7XG4gICAgICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgICAgICB0eXBlID0gcGFydC5jaGFyQXQoMCk7XG5cbiAgICAgICAgICAgICAgICAgICAgaWYgKCF0YWdOYW1lKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICB0YWdOYW1lID0gcGFydDtcbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIGlmICh0eXBlID09PSBcIi5cIikge1xuICAgICAgICAgICAgICAgICAgICAgICAgY2xhc3NlcyA9IGNsYXNzZXMgfHwgW107XG4gICAgICAgICAgICAgICAgICAgICAgICBjbGFzc2VzLnB1c2gocGFydC5zdWJzdHJpbmcoMSwgcGFydC5sZW5ndGgpKTtcbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIGlmICh0eXBlID09PSBcIiNcIiAmJiBub0lkKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBwcm9wcy5pZCA9IHBhcnQuc3Vic3RyaW5nKDEsIHBhcnQubGVuZ3RoKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIGlmIChjbGFzc2VzKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmIChwcm9wcy5jbGFzc05hbWUpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGNsYXNzZXMucHVzaChwcm9wcy5jbGFzc05hbWUpO1xuICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgcHJvcHMuY2xhc3NOYW1lID0gY2xhc3Nlcy5qb2luKFwiIFwiKTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICByZXR1cm4gcHJvcHMubmFtZXNwYWNlID8gdGFnTmFtZSA6IHRhZ05hbWUudG9VcHBlckNhc2UoKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSwgeyBcImJyb3dzZXItc3BsaXRcIjogNSB9XSwgMjQ6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICB2YXIgaXNWTm9kZSA9IHJlcXVpcmUoXCIuL2lzLXZub2RlXCIpO1xuICAgICAgICAgICAgdmFyIGlzVlRleHQgPSByZXF1aXJlKFwiLi9pcy12dGV4dFwiKTtcbiAgICAgICAgICAgIHZhciBpc1dpZGdldCA9IHJlcXVpcmUoXCIuL2lzLXdpZGdldFwiKTtcbiAgICAgICAgICAgIHZhciBpc1RodW5rID0gcmVxdWlyZShcIi4vaXMtdGh1bmtcIik7XG5cbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gaGFuZGxlVGh1bms7XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIGhhbmRsZVRodW5rKGEsIGIpIHtcbiAgICAgICAgICAgICAgICB2YXIgcmVuZGVyZWRBID0gYTtcbiAgICAgICAgICAgICAgICB2YXIgcmVuZGVyZWRCID0gYjtcblxuICAgICAgICAgICAgICAgIGlmIChpc1RodW5rKGIpKSB7XG4gICAgICAgICAgICAgICAgICAgIHJlbmRlcmVkQiA9IHJlbmRlclRodW5rKGIsIGEpO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIGlmIChpc1RodW5rKGEpKSB7XG4gICAgICAgICAgICAgICAgICAgIHJlbmRlcmVkQSA9IHJlbmRlclRodW5rKGEsIG51bGwpO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHJldHVybiB7XG4gICAgICAgICAgICAgICAgICAgIGE6IHJlbmRlcmVkQSxcbiAgICAgICAgICAgICAgICAgICAgYjogcmVuZGVyZWRCXG4gICAgICAgICAgICAgICAgfTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZnVuY3Rpb24gcmVuZGVyVGh1bmsodGh1bmssIHByZXZpb3VzKSB7XG4gICAgICAgICAgICAgICAgdmFyIHJlbmRlcmVkVGh1bmsgPSB0aHVuay52bm9kZTtcblxuICAgICAgICAgICAgICAgIGlmICghcmVuZGVyZWRUaHVuaykge1xuICAgICAgICAgICAgICAgICAgICByZW5kZXJlZFRodW5rID0gdGh1bmsudm5vZGUgPSB0aHVuay5yZW5kZXIocHJldmlvdXMpO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIGlmICghKGlzVk5vZGUocmVuZGVyZWRUaHVuaykgfHwgaXNWVGV4dChyZW5kZXJlZFRodW5rKSB8fCBpc1dpZGdldChyZW5kZXJlZFRodW5rKSkpIHtcbiAgICAgICAgICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKFwidGh1bmsgZGlkIG5vdCByZXR1cm4gYSB2YWxpZCBub2RlXCIpO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHJldHVybiByZW5kZXJlZFRodW5rO1xuICAgICAgICAgICAgfVxuICAgICAgICB9LCB7IFwiLi9pcy10aHVua1wiOiAyNSwgXCIuL2lzLXZub2RlXCI6IDI3LCBcIi4vaXMtdnRleHRcIjogMjgsIFwiLi9pcy13aWRnZXRcIjogMjkgfV0sIDI1OiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge1xuICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBpc1RodW5rO1xuXG4gICAgICAgICAgICBmdW5jdGlvbiBpc1RodW5rKHQpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gdCAmJiB0LnR5cGUgPT09IFwiVGh1bmtcIjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSwge31dLCAyNjogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHtcbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gaXNIb29rO1xuXG4gICAgICAgICAgICBmdW5jdGlvbiBpc0hvb2soaG9vaykge1xuICAgICAgICAgICAgICAgIHJldHVybiBob29rICYmICh0eXBlb2YgaG9vay5ob29rID09PSBcImZ1bmN0aW9uXCIgJiYgIWhvb2suaGFzT3duUHJvcGVydHkoXCJob29rXCIpIHx8IHR5cGVvZiBob29rLnVuaG9vayA9PT0gXCJmdW5jdGlvblwiICYmICFob29rLmhhc093blByb3BlcnR5KFwidW5ob29rXCIpKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSwge31dLCAyNzogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHtcbiAgICAgICAgICAgIHZhciB2ZXJzaW9uID0gcmVxdWlyZShcIi4vdmVyc2lvblwiKTtcblxuICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBpc1ZpcnR1YWxOb2RlO1xuXG4gICAgICAgICAgICBmdW5jdGlvbiBpc1ZpcnR1YWxOb2RlKHgpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4geCAmJiB4LnR5cGUgPT09IFwiVmlydHVhbE5vZGVcIiAmJiB4LnZlcnNpb24gPT09IHZlcnNpb247XG4gICAgICAgICAgICB9XG4gICAgICAgIH0sIHsgXCIuL3ZlcnNpb25cIjogMzAgfV0sIDI4OiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge1xuICAgICAgICAgICAgdmFyIHZlcnNpb24gPSByZXF1aXJlKFwiLi92ZXJzaW9uXCIpO1xuXG4gICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IGlzVmlydHVhbFRleHQ7XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIGlzVmlydHVhbFRleHQoeCkge1xuICAgICAgICAgICAgICAgIHJldHVybiB4ICYmIHgudHlwZSA9PT0gXCJWaXJ0dWFsVGV4dFwiICYmIHgudmVyc2lvbiA9PT0gdmVyc2lvbjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSwgeyBcIi4vdmVyc2lvblwiOiAzMCB9XSwgMjk6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IGlzV2lkZ2V0O1xuXG4gICAgICAgICAgICBmdW5jdGlvbiBpc1dpZGdldCh3KSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHcgJiYgdy50eXBlID09PSBcIldpZGdldFwiO1xuICAgICAgICAgICAgfVxuICAgICAgICB9LCB7fV0sIDMwOiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge1xuICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBcIjJcIjtcbiAgICAgICAgfSwge31dLCAzMTogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHtcbiAgICAgICAgICAgIHZhciB2ZXJzaW9uID0gcmVxdWlyZShcIi4vdmVyc2lvblwiKTtcbiAgICAgICAgICAgIHZhciBpc1ZOb2RlID0gcmVxdWlyZShcIi4vaXMtdm5vZGVcIik7XG4gICAgICAgICAgICB2YXIgaXNXaWRnZXQgPSByZXF1aXJlKFwiLi9pcy13aWRnZXRcIik7XG4gICAgICAgICAgICB2YXIgaXNUaHVuayA9IHJlcXVpcmUoXCIuL2lzLXRodW5rXCIpO1xuICAgICAgICAgICAgdmFyIGlzVkhvb2sgPSByZXF1aXJlKFwiLi9pcy12aG9va1wiKTtcblxuICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBWaXJ0dWFsTm9kZTtcblxuICAgICAgICAgICAgdmFyIG5vUHJvcGVydGllcyA9IHt9O1xuICAgICAgICAgICAgdmFyIG5vQ2hpbGRyZW4gPSBbXTtcblxuICAgICAgICAgICAgZnVuY3Rpb24gVmlydHVhbE5vZGUodGFnTmFtZSwgcHJvcGVydGllcywgY2hpbGRyZW4sIGtleSwgbmFtZXNwYWNlKSB7XG4gICAgICAgICAgICAgICAgdGhpcy50YWdOYW1lID0gdGFnTmFtZTtcbiAgICAgICAgICAgICAgICB0aGlzLnByb3BlcnRpZXMgPSBwcm9wZXJ0aWVzIHx8IG5vUHJvcGVydGllcztcbiAgICAgICAgICAgICAgICB0aGlzLmNoaWxkcmVuID0gY2hpbGRyZW4gfHwgbm9DaGlsZHJlbjtcbiAgICAgICAgICAgICAgICB0aGlzLmtleSA9IGtleSAhPSBudWxsID8gU3RyaW5nKGtleSkgOiB1bmRlZmluZWQ7XG4gICAgICAgICAgICAgICAgdGhpcy5uYW1lc3BhY2UgPSB0eXBlb2YgbmFtZXNwYWNlID09PSBcInN0cmluZ1wiID8gbmFtZXNwYWNlIDogbnVsbDtcblxuICAgICAgICAgICAgICAgIHZhciBjb3VudCA9IGNoaWxkcmVuICYmIGNoaWxkcmVuLmxlbmd0aCB8fCAwO1xuICAgICAgICAgICAgICAgIHZhciBkZXNjZW5kYW50cyA9IDA7XG4gICAgICAgICAgICAgICAgdmFyIGhhc1dpZGdldHMgPSBmYWxzZTtcbiAgICAgICAgICAgICAgICB2YXIgaGFzVGh1bmtzID0gZmFsc2U7XG4gICAgICAgICAgICAgICAgdmFyIGRlc2NlbmRhbnRIb29rcyA9IGZhbHNlO1xuICAgICAgICAgICAgICAgIHZhciBob29rcztcblxuICAgICAgICAgICAgICAgIGZvciAodmFyIHByb3BOYW1lIGluIHByb3BlcnRpZXMpIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKHByb3BlcnRpZXMuaGFzT3duUHJvcGVydHkocHJvcE5hbWUpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICB2YXIgcHJvcGVydHkgPSBwcm9wZXJ0aWVzW3Byb3BOYW1lXTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChpc1ZIb29rKHByb3BlcnR5KSAmJiBwcm9wZXJ0eS51bmhvb2spIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoIWhvb2tzKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGhvb2tzID0ge307XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaG9va3NbcHJvcE5hbWVdID0gcHJvcGVydHk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IGNvdW50OyBpKyspIHtcbiAgICAgICAgICAgICAgICAgICAgdmFyIGNoaWxkID0gY2hpbGRyZW5baV07XG4gICAgICAgICAgICAgICAgICAgIGlmIChpc1ZOb2RlKGNoaWxkKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgZGVzY2VuZGFudHMgKz0gY2hpbGQuY291bnQgfHwgMDtcblxuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKCFoYXNXaWRnZXRzICYmIGNoaWxkLmhhc1dpZGdldHMpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBoYXNXaWRnZXRzID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKCFoYXNUaHVua3MgJiYgY2hpbGQuaGFzVGh1bmtzKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaGFzVGh1bmtzID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKCFkZXNjZW5kYW50SG9va3MgJiYgKGNoaWxkLmhvb2tzIHx8IGNoaWxkLmRlc2NlbmRhbnRIb29rcykpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBkZXNjZW5kYW50SG9va3MgPSB0cnVlO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKCFoYXNXaWRnZXRzICYmIGlzV2lkZ2V0KGNoaWxkKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHR5cGVvZiBjaGlsZC5kZXN0cm95ID09PSBcImZ1bmN0aW9uXCIpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBoYXNXaWRnZXRzID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIGlmICghaGFzVGh1bmtzICYmIGlzVGh1bmsoY2hpbGQpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBoYXNUaHVua3MgPSB0cnVlO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgdGhpcy5jb3VudCA9IGNvdW50ICsgZGVzY2VuZGFudHM7XG4gICAgICAgICAgICAgICAgdGhpcy5oYXNXaWRnZXRzID0gaGFzV2lkZ2V0cztcbiAgICAgICAgICAgICAgICB0aGlzLmhhc1RodW5rcyA9IGhhc1RodW5rcztcbiAgICAgICAgICAgICAgICB0aGlzLmhvb2tzID0gaG9va3M7XG4gICAgICAgICAgICAgICAgdGhpcy5kZXNjZW5kYW50SG9va3MgPSBkZXNjZW5kYW50SG9va3M7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIFZpcnR1YWxOb2RlLnByb3RvdHlwZS52ZXJzaW9uID0gdmVyc2lvbjtcbiAgICAgICAgICAgIFZpcnR1YWxOb2RlLnByb3RvdHlwZS50eXBlID0gXCJWaXJ0dWFsTm9kZVwiO1xuICAgICAgICB9LCB7IFwiLi9pcy10aHVua1wiOiAyNSwgXCIuL2lzLXZob29rXCI6IDI2LCBcIi4vaXMtdm5vZGVcIjogMjcsIFwiLi9pcy13aWRnZXRcIjogMjksIFwiLi92ZXJzaW9uXCI6IDMwIH1dLCAzMjogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHtcbiAgICAgICAgICAgIHZhciB2ZXJzaW9uID0gcmVxdWlyZShcIi4vdmVyc2lvblwiKTtcblxuICAgICAgICAgICAgVmlydHVhbFBhdGNoLk5PTkUgPSAwO1xuICAgICAgICAgICAgVmlydHVhbFBhdGNoLlZURVhUID0gMTtcbiAgICAgICAgICAgIFZpcnR1YWxQYXRjaC5WTk9ERSA9IDI7XG4gICAgICAgICAgICBWaXJ0dWFsUGF0Y2guV0lER0VUID0gMztcbiAgICAgICAgICAgIFZpcnR1YWxQYXRjaC5QUk9QUyA9IDQ7XG4gICAgICAgICAgICBWaXJ0dWFsUGF0Y2guT1JERVIgPSA1O1xuICAgICAgICAgICAgVmlydHVhbFBhdGNoLklOU0VSVCA9IDY7XG4gICAgICAgICAgICBWaXJ0dWFsUGF0Y2guUkVNT1ZFID0gNztcbiAgICAgICAgICAgIFZpcnR1YWxQYXRjaC5USFVOSyA9IDg7XG5cbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gVmlydHVhbFBhdGNoO1xuXG4gICAgICAgICAgICBmdW5jdGlvbiBWaXJ0dWFsUGF0Y2godHlwZSwgdk5vZGUsIHBhdGNoKSB7XG4gICAgICAgICAgICAgICAgdGhpcy50eXBlID0gTnVtYmVyKHR5cGUpO1xuICAgICAgICAgICAgICAgIHRoaXMudk5vZGUgPSB2Tm9kZTtcbiAgICAgICAgICAgICAgICB0aGlzLnBhdGNoID0gcGF0Y2g7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIFZpcnR1YWxQYXRjaC5wcm90b3R5cGUudmVyc2lvbiA9IHZlcnNpb247XG4gICAgICAgICAgICBWaXJ0dWFsUGF0Y2gucHJvdG90eXBlLnR5cGUgPSBcIlZpcnR1YWxQYXRjaFwiO1xuICAgICAgICB9LCB7IFwiLi92ZXJzaW9uXCI6IDMwIH1dLCAzMzogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHtcbiAgICAgICAgICAgIHZhciB2ZXJzaW9uID0gcmVxdWlyZShcIi4vdmVyc2lvblwiKTtcblxuICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBWaXJ0dWFsVGV4dDtcblxuICAgICAgICAgICAgZnVuY3Rpb24gVmlydHVhbFRleHQodGV4dCkge1xuICAgICAgICAgICAgICAgIHRoaXMudGV4dCA9IFN0cmluZyh0ZXh0KTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgVmlydHVhbFRleHQucHJvdG90eXBlLnZlcnNpb24gPSB2ZXJzaW9uO1xuICAgICAgICAgICAgVmlydHVhbFRleHQucHJvdG90eXBlLnR5cGUgPSBcIlZpcnR1YWxUZXh0XCI7XG4gICAgICAgIH0sIHsgXCIuL3ZlcnNpb25cIjogMzAgfV0sIDM0OiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge1xuICAgICAgICAgICAgdmFyIGlzT2JqZWN0ID0gcmVxdWlyZShcImlzLW9iamVjdFwiKTtcbiAgICAgICAgICAgIHZhciBpc0hvb2sgPSByZXF1aXJlKFwiLi4vdm5vZGUvaXMtdmhvb2tcIik7XG5cbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gZGlmZlByb3BzO1xuXG4gICAgICAgICAgICBmdW5jdGlvbiBkaWZmUHJvcHMoYSwgYikge1xuICAgICAgICAgICAgICAgIHZhciBkaWZmO1xuXG4gICAgICAgICAgICAgICAgZm9yICh2YXIgYUtleSBpbiBhKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmICghKGFLZXkgaW4gYikpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGRpZmYgPSBkaWZmIHx8IHt9O1xuICAgICAgICAgICAgICAgICAgICAgICAgZGlmZlthS2V5XSA9IHVuZGVmaW5lZDtcbiAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgIHZhciBhVmFsdWUgPSBhW2FLZXldO1xuICAgICAgICAgICAgICAgICAgICB2YXIgYlZhbHVlID0gYlthS2V5XTtcblxuICAgICAgICAgICAgICAgICAgICBpZiAoYVZhbHVlID09PSBiVmFsdWUpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnRpbnVlO1xuICAgICAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKGlzT2JqZWN0KGFWYWx1ZSkgJiYgaXNPYmplY3QoYlZhbHVlKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGdldFByb3RvdHlwZShiVmFsdWUpICE9PSBnZXRQcm90b3R5cGUoYVZhbHVlKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRpZmYgPSBkaWZmIHx8IHt9O1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRpZmZbYUtleV0gPSBiVmFsdWU7XG4gICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKGlzSG9vayhiVmFsdWUpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgZGlmZiA9IGRpZmYgfHwge307XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgZGlmZlthS2V5XSA9IGJWYWx1ZTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdmFyIG9iamVjdERpZmYgPSBkaWZmUHJvcHMoYVZhbHVlLCBiVmFsdWUpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChvYmplY3REaWZmKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRpZmYgPSBkaWZmIHx8IHt9O1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBkaWZmW2FLZXldID0gb2JqZWN0RGlmZjtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBkaWZmID0gZGlmZiB8fCB7fTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGRpZmZbYUtleV0gPSBiVmFsdWU7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICBmb3IgKHZhciBiS2V5IGluIGIpIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKCEoYktleSBpbiBhKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgZGlmZiA9IGRpZmYgfHwge307XG4gICAgICAgICAgICAgICAgICAgICAgICBkaWZmW2JLZXldID0gYltiS2V5XTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHJldHVybiBkaWZmO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBmdW5jdGlvbiBnZXRQcm90b3R5cGUodmFsdWUpIHtcbiAgICAgICAgICAgICAgICBpZiAoT2JqZWN0LmdldFByb3RvdHlwZU9mKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBPYmplY3QuZ2V0UHJvdG90eXBlT2YodmFsdWUpO1xuICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAodmFsdWUuX19wcm90b19fKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiB2YWx1ZS5fX3Byb3RvX187XG4gICAgICAgICAgICAgICAgfSBlbHNlIGlmICh2YWx1ZS5jb25zdHJ1Y3Rvcikge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gdmFsdWUuY29uc3RydWN0b3IucHJvdG90eXBlO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgfSwgeyBcIi4uL3Zub2RlL2lzLXZob29rXCI6IDI2LCBcImlzLW9iamVjdFwiOiAxMSB9XSwgMzU6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICB2YXIgaXNBcnJheSA9IHJlcXVpcmUoXCJ4LWlzLWFycmF5XCIpO1xuXG4gICAgICAgICAgICB2YXIgVlBhdGNoID0gcmVxdWlyZShcIi4uL3Zub2RlL3ZwYXRjaFwiKTtcbiAgICAgICAgICAgIHZhciBpc1ZOb2RlID0gcmVxdWlyZShcIi4uL3Zub2RlL2lzLXZub2RlXCIpO1xuICAgICAgICAgICAgdmFyIGlzVlRleHQgPSByZXF1aXJlKFwiLi4vdm5vZGUvaXMtdnRleHRcIik7XG4gICAgICAgICAgICB2YXIgaXNXaWRnZXQgPSByZXF1aXJlKFwiLi4vdm5vZGUvaXMtd2lkZ2V0XCIpO1xuICAgICAgICAgICAgdmFyIGlzVGh1bmsgPSByZXF1aXJlKFwiLi4vdm5vZGUvaXMtdGh1bmtcIik7XG4gICAgICAgICAgICB2YXIgaGFuZGxlVGh1bmsgPSByZXF1aXJlKFwiLi4vdm5vZGUvaGFuZGxlLXRodW5rXCIpO1xuXG4gICAgICAgICAgICB2YXIgZGlmZlByb3BzID0gcmVxdWlyZShcIi4vZGlmZi1wcm9wc1wiKTtcblxuICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBkaWZmO1xuXG4gICAgICAgICAgICBmdW5jdGlvbiBkaWZmKGEsIGIpIHtcbiAgICAgICAgICAgICAgICB2YXIgcGF0Y2ggPSB7IGE6IGEgfTtcbiAgICAgICAgICAgICAgICB3YWxrKGEsIGIsIHBhdGNoLCAwKTtcbiAgICAgICAgICAgICAgICByZXR1cm4gcGF0Y2g7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIHdhbGsoYSwgYiwgcGF0Y2gsIGluZGV4KSB7XG4gICAgICAgICAgICAgICAgaWYgKGEgPT09IGIpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHZhciBhcHBseSA9IHBhdGNoW2luZGV4XTtcbiAgICAgICAgICAgICAgICB2YXIgYXBwbHlDbGVhciA9IGZhbHNlO1xuXG4gICAgICAgICAgICAgICAgaWYgKGlzVGh1bmsoYSkgfHwgaXNUaHVuayhiKSkge1xuICAgICAgICAgICAgICAgICAgICB0aHVua3MoYSwgYiwgcGF0Y2gsIGluZGV4KTtcbiAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKGIgPT0gbnVsbCkge1xuXG4gICAgICAgICAgICAgICAgICAgIC8vIElmIGEgaXMgYSB3aWRnZXQgd2Ugd2lsbCBhZGQgYSByZW1vdmUgcGF0Y2ggZm9yIGl0XG4gICAgICAgICAgICAgICAgICAgIC8vIE90aGVyd2lzZSBhbnkgY2hpbGQgd2lkZ2V0cy9ob29rcyBtdXN0IGJlIGRlc3Ryb3llZC5cbiAgICAgICAgICAgICAgICAgICAgLy8gVGhpcyBwcmV2ZW50cyBhZGRpbmcgdHdvIHJlbW92ZSBwYXRjaGVzIGZvciBhIHdpZGdldC5cbiAgICAgICAgICAgICAgICAgICAgaWYgKCFpc1dpZGdldChhKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgY2xlYXJTdGF0ZShhLCBwYXRjaCwgaW5kZXgpO1xuICAgICAgICAgICAgICAgICAgICAgICAgYXBwbHkgPSBwYXRjaFtpbmRleF07XG4gICAgICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgICAgICBhcHBseSA9IGFwcGVuZFBhdGNoKGFwcGx5LCBuZXcgVlBhdGNoKFZQYXRjaC5SRU1PVkUsIGEsIGIpKTtcbiAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKGlzVk5vZGUoYikpIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKGlzVk5vZGUoYSkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChhLnRhZ05hbWUgPT09IGIudGFnTmFtZSAmJiBhLm5hbWVzcGFjZSA9PT0gYi5uYW1lc3BhY2UgJiYgYS5rZXkgPT09IGIua2V5KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdmFyIHByb3BzUGF0Y2ggPSBkaWZmUHJvcHMoYS5wcm9wZXJ0aWVzLCBiLnByb3BlcnRpZXMpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChwcm9wc1BhdGNoKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGFwcGx5ID0gYXBwZW5kUGF0Y2goYXBwbHksIG5ldyBWUGF0Y2goVlBhdGNoLlBST1BTLCBhLCBwcm9wc1BhdGNoKSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGFwcGx5ID0gZGlmZkNoaWxkcmVuKGEsIGIsIHBhdGNoLCBhcHBseSwgaW5kZXgpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBhcHBseSA9IGFwcGVuZFBhdGNoKGFwcGx5LCBuZXcgVlBhdGNoKFZQYXRjaC5WTk9ERSwgYSwgYikpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGFwcGx5Q2xlYXIgPSB0cnVlO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgYXBwbHkgPSBhcHBlbmRQYXRjaChhcHBseSwgbmV3IFZQYXRjaChWUGF0Y2guVk5PREUsIGEsIGIpKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGFwcGx5Q2xlYXIgPSB0cnVlO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfSBlbHNlIGlmIChpc1ZUZXh0KGIpKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmICghaXNWVGV4dChhKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgYXBwbHkgPSBhcHBlbmRQYXRjaChhcHBseSwgbmV3IFZQYXRjaChWUGF0Y2guVlRFWFQsIGEsIGIpKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGFwcGx5Q2xlYXIgPSB0cnVlO1xuICAgICAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKGEudGV4dCAhPT0gYi50ZXh0KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBhcHBseSA9IGFwcGVuZFBhdGNoKGFwcGx5LCBuZXcgVlBhdGNoKFZQYXRjaC5WVEVYVCwgYSwgYikpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfSBlbHNlIGlmIChpc1dpZGdldChiKSkge1xuICAgICAgICAgICAgICAgICAgICBpZiAoIWlzV2lkZ2V0KGEpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBhcHBseUNsZWFyID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgIGFwcGx5ID0gYXBwZW5kUGF0Y2goYXBwbHksIG5ldyBWUGF0Y2goVlBhdGNoLldJREdFVCwgYSwgYikpO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIGlmIChhcHBseSkge1xuICAgICAgICAgICAgICAgICAgICBwYXRjaFtpbmRleF0gPSBhcHBseTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICBpZiAoYXBwbHlDbGVhcikge1xuICAgICAgICAgICAgICAgICAgICBjbGVhclN0YXRlKGEsIHBhdGNoLCBpbmRleCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBmdW5jdGlvbiBkaWZmQ2hpbGRyZW4oYSwgYiwgcGF0Y2gsIGFwcGx5LCBpbmRleCkge1xuICAgICAgICAgICAgICAgIHZhciBhQ2hpbGRyZW4gPSBhLmNoaWxkcmVuO1xuICAgICAgICAgICAgICAgIHZhciBvcmRlcmVkU2V0ID0gcmVvcmRlcihhQ2hpbGRyZW4sIGIuY2hpbGRyZW4pO1xuICAgICAgICAgICAgICAgIHZhciBiQ2hpbGRyZW4gPSBvcmRlcmVkU2V0LmNoaWxkcmVuO1xuXG4gICAgICAgICAgICAgICAgdmFyIGFMZW4gPSBhQ2hpbGRyZW4ubGVuZ3RoO1xuICAgICAgICAgICAgICAgIHZhciBiTGVuID0gYkNoaWxkcmVuLmxlbmd0aDtcbiAgICAgICAgICAgICAgICB2YXIgbGVuID0gYUxlbiA+IGJMZW4gPyBhTGVuIDogYkxlbjtcblxuICAgICAgICAgICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgbGVuOyBpKyspIHtcbiAgICAgICAgICAgICAgICAgICAgdmFyIGxlZnROb2RlID0gYUNoaWxkcmVuW2ldO1xuICAgICAgICAgICAgICAgICAgICB2YXIgcmlnaHROb2RlID0gYkNoaWxkcmVuW2ldO1xuICAgICAgICAgICAgICAgICAgICBpbmRleCArPSAxO1xuXG4gICAgICAgICAgICAgICAgICAgIGlmICghbGVmdE5vZGUpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChyaWdodE5vZGUpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBFeGNlc3Mgbm9kZXMgaW4gYiBuZWVkIHRvIGJlIGFkZGVkXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgYXBwbHkgPSBhcHBlbmRQYXRjaChhcHBseSwgbmV3IFZQYXRjaChWUGF0Y2guSU5TRVJULCBudWxsLCByaWdodE5vZGUpKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHdhbGsobGVmdE5vZGUsIHJpZ2h0Tm9kZSwgcGF0Y2gsIGluZGV4KTtcbiAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgIGlmIChpc1ZOb2RlKGxlZnROb2RlKSAmJiBsZWZ0Tm9kZS5jb3VudCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgaW5kZXggKz0gbGVmdE5vZGUuY291bnQ7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICBpZiAob3JkZXJlZFNldC5tb3Zlcykge1xuICAgICAgICAgICAgICAgICAgICAvLyBSZW9yZGVyIG5vZGVzIGxhc3RcbiAgICAgICAgICAgICAgICAgICAgYXBwbHkgPSBhcHBlbmRQYXRjaChhcHBseSwgbmV3IFZQYXRjaChWUGF0Y2guT1JERVIsIGEsIG9yZGVyZWRTZXQubW92ZXMpKTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICByZXR1cm4gYXBwbHk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIGNsZWFyU3RhdGUodk5vZGUsIHBhdGNoLCBpbmRleCkge1xuICAgICAgICAgICAgICAgIC8vIFRPRE86IE1ha2UgdGhpcyBhIHNpbmdsZSB3YWxrLCBub3QgdHdvXG4gICAgICAgICAgICAgICAgdW5ob29rKHZOb2RlLCBwYXRjaCwgaW5kZXgpO1xuICAgICAgICAgICAgICAgIGRlc3Ryb3lXaWRnZXRzKHZOb2RlLCBwYXRjaCwgaW5kZXgpO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAvLyBQYXRjaCByZWNvcmRzIGZvciBhbGwgZGVzdHJveWVkIHdpZGdldHMgbXVzdCBiZSBhZGRlZCBiZWNhdXNlIHdlIG5lZWRcbiAgICAgICAgICAgIC8vIGEgRE9NIG5vZGUgcmVmZXJlbmNlIGZvciB0aGUgZGVzdHJveSBmdW5jdGlvblxuICAgICAgICAgICAgZnVuY3Rpb24gZGVzdHJveVdpZGdldHModk5vZGUsIHBhdGNoLCBpbmRleCkge1xuICAgICAgICAgICAgICAgIGlmIChpc1dpZGdldCh2Tm9kZSkpIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKHR5cGVvZiB2Tm9kZS5kZXN0cm95ID09PSBcImZ1bmN0aW9uXCIpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHBhdGNoW2luZGV4XSA9IGFwcGVuZFBhdGNoKHBhdGNoW2luZGV4XSwgbmV3IFZQYXRjaChWUGF0Y2guUkVNT1ZFLCB2Tm9kZSwgbnVsbCkpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfSBlbHNlIGlmIChpc1ZOb2RlKHZOb2RlKSAmJiAodk5vZGUuaGFzV2lkZ2V0cyB8fCB2Tm9kZS5oYXNUaHVua3MpKSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciBjaGlsZHJlbiA9IHZOb2RlLmNoaWxkcmVuO1xuICAgICAgICAgICAgICAgICAgICB2YXIgbGVuID0gY2hpbGRyZW4ubGVuZ3RoO1xuICAgICAgICAgICAgICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IGxlbjsgaSsrKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICB2YXIgY2hpbGQgPSBjaGlsZHJlbltpXTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGluZGV4ICs9IDE7XG5cbiAgICAgICAgICAgICAgICAgICAgICAgIGRlc3Ryb3lXaWRnZXRzKGNoaWxkLCBwYXRjaCwgaW5kZXgpO1xuXG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoaXNWTm9kZShjaGlsZCkgJiYgY2hpbGQuY291bnQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpbmRleCArPSBjaGlsZC5jb3VudDtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoaXNUaHVuayh2Tm9kZSkpIHtcbiAgICAgICAgICAgICAgICAgICAgdGh1bmtzKHZOb2RlLCBudWxsLCBwYXRjaCwgaW5kZXgpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgLy8gQ3JlYXRlIGEgc3ViLXBhdGNoIGZvciB0aHVua3NcbiAgICAgICAgICAgIGZ1bmN0aW9uIHRodW5rcyhhLCBiLCBwYXRjaCwgaW5kZXgpIHtcbiAgICAgICAgICAgICAgICB2YXIgbm9kZXMgPSBoYW5kbGVUaHVuayhhLCBiKTtcbiAgICAgICAgICAgICAgICB2YXIgdGh1bmtQYXRjaCA9IGRpZmYobm9kZXMuYSwgbm9kZXMuYik7XG4gICAgICAgICAgICAgICAgaWYgKGhhc1BhdGNoZXModGh1bmtQYXRjaCkpIHtcbiAgICAgICAgICAgICAgICAgICAgcGF0Y2hbaW5kZXhdID0gbmV3IFZQYXRjaChWUGF0Y2guVEhVTkssIG51bGwsIHRodW5rUGF0Y2gpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZnVuY3Rpb24gaGFzUGF0Y2hlcyhwYXRjaCkge1xuICAgICAgICAgICAgICAgIGZvciAodmFyIGluZGV4IGluIHBhdGNoKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmIChpbmRleCAhPT0gXCJhXCIpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAvLyBFeGVjdXRlIGhvb2tzIHdoZW4gdHdvIG5vZGVzIGFyZSBpZGVudGljYWxcbiAgICAgICAgICAgIGZ1bmN0aW9uIHVuaG9vayh2Tm9kZSwgcGF0Y2gsIGluZGV4KSB7XG4gICAgICAgICAgICAgICAgaWYgKGlzVk5vZGUodk5vZGUpKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmICh2Tm9kZS5ob29rcykge1xuICAgICAgICAgICAgICAgICAgICAgICAgcGF0Y2hbaW5kZXhdID0gYXBwZW5kUGF0Y2gocGF0Y2hbaW5kZXhdLCBuZXcgVlBhdGNoKFZQYXRjaC5QUk9QUywgdk5vZGUsIHVuZGVmaW5lZEtleXModk5vZGUuaG9va3MpKSk7XG4gICAgICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgICAgICBpZiAodk5vZGUuZGVzY2VuZGFudEhvb2tzIHx8IHZOb2RlLmhhc1RodW5rcykge1xuICAgICAgICAgICAgICAgICAgICAgICAgdmFyIGNoaWxkcmVuID0gdk5vZGUuY2hpbGRyZW47XG4gICAgICAgICAgICAgICAgICAgICAgICB2YXIgbGVuID0gY2hpbGRyZW4ubGVuZ3RoO1xuICAgICAgICAgICAgICAgICAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCBsZW47IGkrKykge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZhciBjaGlsZCA9IGNoaWxkcmVuW2ldO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGluZGV4ICs9IDE7XG5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB1bmhvb2soY2hpbGQsIHBhdGNoLCBpbmRleCk7XG5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoaXNWTm9kZShjaGlsZCkgJiYgY2hpbGQuY291bnQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaW5kZXggKz0gY2hpbGQuY291bnQ7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfSBlbHNlIGlmIChpc1RodW5rKHZOb2RlKSkge1xuICAgICAgICAgICAgICAgICAgICB0aHVua3Modk5vZGUsIG51bGwsIHBhdGNoLCBpbmRleCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBmdW5jdGlvbiB1bmRlZmluZWRLZXlzKG9iaikge1xuICAgICAgICAgICAgICAgIHZhciByZXN1bHQgPSB7fTtcblxuICAgICAgICAgICAgICAgIGZvciAodmFyIGtleSBpbiBvYmopIHtcbiAgICAgICAgICAgICAgICAgICAgcmVzdWx0W2tleV0gPSB1bmRlZmluZWQ7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgcmV0dXJuIHJlc3VsdDtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgLy8gTGlzdCBkaWZmLCBuYWl2ZSBsZWZ0IHRvIHJpZ2h0IHJlb3JkZXJpbmdcbiAgICAgICAgICAgIGZ1bmN0aW9uIHJlb3JkZXIoYUNoaWxkcmVuLCBiQ2hpbGRyZW4pIHtcbiAgICAgICAgICAgICAgICAvLyBPKE0pIHRpbWUsIE8oTSkgbWVtb3J5XG4gICAgICAgICAgICAgICAgdmFyIGJDaGlsZEluZGV4ID0ga2V5SW5kZXgoYkNoaWxkcmVuKTtcbiAgICAgICAgICAgICAgICB2YXIgYktleXMgPSBiQ2hpbGRJbmRleC5rZXlzO1xuICAgICAgICAgICAgICAgIHZhciBiRnJlZSA9IGJDaGlsZEluZGV4LmZyZWU7XG5cbiAgICAgICAgICAgICAgICBpZiAoYkZyZWUubGVuZ3RoID09PSBiQ2hpbGRyZW4ubGVuZ3RoKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiB7XG4gICAgICAgICAgICAgICAgICAgICAgICBjaGlsZHJlbjogYkNoaWxkcmVuLFxuICAgICAgICAgICAgICAgICAgICAgICAgbW92ZXM6IG51bGxcbiAgICAgICAgICAgICAgICAgICAgfTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAvLyBPKE4pIHRpbWUsIE8oTikgbWVtb3J5XG4gICAgICAgICAgICAgICAgdmFyIGFDaGlsZEluZGV4ID0ga2V5SW5kZXgoYUNoaWxkcmVuKTtcbiAgICAgICAgICAgICAgICB2YXIgYUtleXMgPSBhQ2hpbGRJbmRleC5rZXlzO1xuICAgICAgICAgICAgICAgIHZhciBhRnJlZSA9IGFDaGlsZEluZGV4LmZyZWU7XG5cbiAgICAgICAgICAgICAgICBpZiAoYUZyZWUubGVuZ3RoID09PSBhQ2hpbGRyZW4ubGVuZ3RoKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiB7XG4gICAgICAgICAgICAgICAgICAgICAgICBjaGlsZHJlbjogYkNoaWxkcmVuLFxuICAgICAgICAgICAgICAgICAgICAgICAgbW92ZXM6IG51bGxcbiAgICAgICAgICAgICAgICAgICAgfTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAvLyBPKE1BWChOLCBNKSkgbWVtb3J5XG4gICAgICAgICAgICAgICAgdmFyIG5ld0NoaWxkcmVuID0gW107XG5cbiAgICAgICAgICAgICAgICB2YXIgZnJlZUluZGV4ID0gMDtcbiAgICAgICAgICAgICAgICB2YXIgZnJlZUNvdW50ID0gYkZyZWUubGVuZ3RoO1xuICAgICAgICAgICAgICAgIHZhciBkZWxldGVkSXRlbXMgPSAwO1xuXG4gICAgICAgICAgICAgICAgLy8gSXRlcmF0ZSB0aHJvdWdoIGEgYW5kIG1hdGNoIGEgbm9kZSBpbiBiXG4gICAgICAgICAgICAgICAgLy8gTyhOKSB0aW1lLFxuICAgICAgICAgICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgYUNoaWxkcmVuLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciBhSXRlbSA9IGFDaGlsZHJlbltpXTtcbiAgICAgICAgICAgICAgICAgICAgdmFyIGl0ZW1JbmRleDtcblxuICAgICAgICAgICAgICAgICAgICBpZiAoYUl0ZW0ua2V5KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoYktleXMuaGFzT3duUHJvcGVydHkoYUl0ZW0ua2V5KSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIE1hdGNoIHVwIHRoZSBvbGQga2V5c1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGl0ZW1JbmRleCA9IGJLZXlzW2FJdGVtLmtleV07XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgbmV3Q2hpbGRyZW4ucHVzaChiQ2hpbGRyZW5baXRlbUluZGV4XSk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIFJlbW92ZSBvbGQga2V5ZWQgaXRlbXNcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpdGVtSW5kZXggPSBpIC0gZGVsZXRlZEl0ZW1zKys7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgbmV3Q2hpbGRyZW4ucHVzaChudWxsKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIE1hdGNoIHRoZSBpdGVtIGluIGEgd2l0aCB0aGUgbmV4dCBmcmVlIGl0ZW0gaW4gYlxuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGZyZWVJbmRleCA8IGZyZWVDb3VudCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGl0ZW1JbmRleCA9IGJGcmVlW2ZyZWVJbmRleCsrXTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBuZXdDaGlsZHJlbi5wdXNoKGJDaGlsZHJlbltpdGVtSW5kZXhdKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gVGhlcmUgYXJlIG5vIGZyZWUgaXRlbXMgaW4gYiB0byBtYXRjaCB3aXRoXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gdGhlIGZyZWUgaXRlbXMgaW4gYSwgc28gdGhlIGV4dHJhIGZyZWUgbm9kZXNcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBhcmUgZGVsZXRlZC5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpdGVtSW5kZXggPSBpIC0gZGVsZXRlZEl0ZW1zKys7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgbmV3Q2hpbGRyZW4ucHVzaChudWxsKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHZhciBsYXN0RnJlZUluZGV4ID0gZnJlZUluZGV4ID49IGJGcmVlLmxlbmd0aCA/IGJDaGlsZHJlbi5sZW5ndGggOiBiRnJlZVtmcmVlSW5kZXhdO1xuXG4gICAgICAgICAgICAgICAgLy8gSXRlcmF0ZSB0aHJvdWdoIGIgYW5kIGFwcGVuZCBhbnkgbmV3IGtleXNcbiAgICAgICAgICAgICAgICAvLyBPKE0pIHRpbWVcbiAgICAgICAgICAgICAgICBmb3IgKHZhciBqID0gMDsgaiA8IGJDaGlsZHJlbi5sZW5ndGg7IGorKykge1xuICAgICAgICAgICAgICAgICAgICB2YXIgbmV3SXRlbSA9IGJDaGlsZHJlbltqXTtcblxuICAgICAgICAgICAgICAgICAgICBpZiAobmV3SXRlbS5rZXkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmICghYUtleXMuaGFzT3duUHJvcGVydHkobmV3SXRlbS5rZXkpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gQWRkIGFueSBuZXcga2V5ZWQgaXRlbXNcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBXZSBhcmUgYWRkaW5nIG5ldyBpdGVtcyB0byB0aGUgZW5kIGFuZCB0aGVuIHNvcnRpbmcgdGhlbVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIGluIHBsYWNlLiBJbiBmdXR1cmUgd2Ugc2hvdWxkIGluc2VydCBuZXcgaXRlbXMgaW4gcGxhY2UuXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgbmV3Q2hpbGRyZW4ucHVzaChuZXdJdGVtKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIGlmIChqID49IGxhc3RGcmVlSW5kZXgpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIEFkZCBhbnkgbGVmdG92ZXIgbm9uLWtleWVkIGl0ZW1zXG4gICAgICAgICAgICAgICAgICAgICAgICBuZXdDaGlsZHJlbi5wdXNoKG5ld0l0ZW0pO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgdmFyIHNpbXVsYXRlID0gbmV3Q2hpbGRyZW4uc2xpY2UoKTtcbiAgICAgICAgICAgICAgICB2YXIgc2ltdWxhdGVJbmRleCA9IDA7XG4gICAgICAgICAgICAgICAgdmFyIHJlbW92ZXMgPSBbXTtcbiAgICAgICAgICAgICAgICB2YXIgaW5zZXJ0cyA9IFtdO1xuICAgICAgICAgICAgICAgIHZhciBzaW11bGF0ZUl0ZW07XG5cbiAgICAgICAgICAgICAgICBmb3IgKHZhciBrID0gMDsgayA8IGJDaGlsZHJlbi5sZW5ndGg7KSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciB3YW50ZWRJdGVtID0gYkNoaWxkcmVuW2tdO1xuICAgICAgICAgICAgICAgICAgICBzaW11bGF0ZUl0ZW0gPSBzaW11bGF0ZVtzaW11bGF0ZUluZGV4XTtcblxuICAgICAgICAgICAgICAgICAgICAvLyByZW1vdmUgaXRlbXNcbiAgICAgICAgICAgICAgICAgICAgd2hpbGUgKHNpbXVsYXRlSXRlbSA9PT0gbnVsbCAmJiBzaW11bGF0ZS5sZW5ndGgpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJlbW92ZXMucHVzaChyZW1vdmUoc2ltdWxhdGUsIHNpbXVsYXRlSW5kZXgsIG51bGwpKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIHNpbXVsYXRlSXRlbSA9IHNpbXVsYXRlW3NpbXVsYXRlSW5kZXhdO1xuICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgaWYgKCFzaW11bGF0ZUl0ZW0gfHwgc2ltdWxhdGVJdGVtLmtleSAhPT0gd2FudGVkSXRlbS5rZXkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIGlmIHdlIG5lZWQgYSBrZXkgaW4gdGhpcyBwb3NpdGlvbi4uLlxuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHdhbnRlZEl0ZW0ua2V5KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHNpbXVsYXRlSXRlbSAmJiBzaW11bGF0ZUl0ZW0ua2V5KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIGlmIGFuIGluc2VydCBkb2Vzbid0IHB1dCB0aGlzIGtleSBpbiBwbGFjZSwgaXQgbmVlZHMgdG8gbW92ZVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoYktleXNbc2ltdWxhdGVJdGVtLmtleV0gIT09IGsgKyAxKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICByZW1vdmVzLnB1c2gocmVtb3ZlKHNpbXVsYXRlLCBzaW11bGF0ZUluZGV4LCBzaW11bGF0ZUl0ZW0ua2V5KSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzaW11bGF0ZUl0ZW0gPSBzaW11bGF0ZVtzaW11bGF0ZUluZGV4XTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIGlmIHRoZSByZW1vdmUgZGlkbid0IHB1dCB0aGUgd2FudGVkIGl0ZW0gaW4gcGxhY2UsIHdlIG5lZWQgdG8gaW5zZXJ0IGl0XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoIXNpbXVsYXRlSXRlbSB8fCBzaW11bGF0ZUl0ZW0ua2V5ICE9PSB3YW50ZWRJdGVtLmtleSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGluc2VydHMucHVzaCh7IGtleTogd2FudGVkSXRlbS5rZXksIHRvOiBrIH0pO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gaXRlbXMgYXJlIG1hdGNoaW5nLCBzbyBza2lwIGFoZWFkXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzaW11bGF0ZUluZGV4Kys7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpbnNlcnRzLnB1c2goeyBrZXk6IHdhbnRlZEl0ZW0ua2V5LCB0bzogayB9KTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGluc2VydHMucHVzaCh7IGtleTogd2FudGVkSXRlbS5rZXksIHRvOiBrIH0pO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBrKys7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAvLyBhIGtleSBpbiBzaW11bGF0ZSBoYXMgbm8gbWF0Y2hpbmcgd2FudGVkIGtleSwgcmVtb3ZlIGl0XG4gICAgICAgICAgICAgICAgICAgICAgICBlbHNlIGlmIChzaW11bGF0ZUl0ZW0gJiYgc2ltdWxhdGVJdGVtLmtleSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlbW92ZXMucHVzaChyZW1vdmUoc2ltdWxhdGUsIHNpbXVsYXRlSW5kZXgsIHNpbXVsYXRlSXRlbS5rZXkpKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHNpbXVsYXRlSW5kZXgrKztcbiAgICAgICAgICAgICAgICAgICAgICAgIGsrKztcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIC8vIHJlbW92ZSBhbGwgdGhlIHJlbWFpbmluZyBub2RlcyBmcm9tIHNpbXVsYXRlXG4gICAgICAgICAgICAgICAgd2hpbGUgKHNpbXVsYXRlSW5kZXggPCBzaW11bGF0ZS5sZW5ndGgpIHtcbiAgICAgICAgICAgICAgICAgICAgc2ltdWxhdGVJdGVtID0gc2ltdWxhdGVbc2ltdWxhdGVJbmRleF07XG4gICAgICAgICAgICAgICAgICAgIHJlbW92ZXMucHVzaChyZW1vdmUoc2ltdWxhdGUsIHNpbXVsYXRlSW5kZXgsIHNpbXVsYXRlSXRlbSAmJiBzaW11bGF0ZUl0ZW0ua2V5KSk7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgLy8gSWYgdGhlIG9ubHkgbW92ZXMgd2UgaGF2ZSBhcmUgZGVsZXRlcyB0aGVuIHdlIGNhbiBqdXN0XG4gICAgICAgICAgICAgICAgLy8gbGV0IHRoZSBkZWxldGUgcGF0Y2ggcmVtb3ZlIHRoZXNlIGl0ZW1zLlxuICAgICAgICAgICAgICAgIGlmIChyZW1vdmVzLmxlbmd0aCA9PT0gZGVsZXRlZEl0ZW1zICYmICFpbnNlcnRzLmxlbmd0aCkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgICAgICAgICAgICAgY2hpbGRyZW46IG5ld0NoaWxkcmVuLFxuICAgICAgICAgICAgICAgICAgICAgICAgbW92ZXM6IG51bGxcbiAgICAgICAgICAgICAgICAgICAgfTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgICAgICAgICBjaGlsZHJlbjogbmV3Q2hpbGRyZW4sXG4gICAgICAgICAgICAgICAgICAgIG1vdmVzOiB7XG4gICAgICAgICAgICAgICAgICAgICAgICByZW1vdmVzOiByZW1vdmVzLFxuICAgICAgICAgICAgICAgICAgICAgICAgaW5zZXJ0czogaW5zZXJ0c1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZnVuY3Rpb24gcmVtb3ZlKGFyciwgaW5kZXgsIGtleSkge1xuICAgICAgICAgICAgICAgIGFyci5zcGxpY2UoaW5kZXgsIDEpO1xuXG4gICAgICAgICAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgICAgICAgICAgZnJvbTogaW5kZXgsXG4gICAgICAgICAgICAgICAgICAgIGtleToga2V5XG4gICAgICAgICAgICAgICAgfTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZnVuY3Rpb24ga2V5SW5kZXgoY2hpbGRyZW4pIHtcbiAgICAgICAgICAgICAgICB2YXIga2V5cyA9IHt9O1xuICAgICAgICAgICAgICAgIHZhciBmcmVlID0gW107XG4gICAgICAgICAgICAgICAgdmFyIGxlbmd0aCA9IGNoaWxkcmVuLmxlbmd0aDtcblxuICAgICAgICAgICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgbGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgICAgICAgICAgdmFyIGNoaWxkID0gY2hpbGRyZW5baV07XG5cbiAgICAgICAgICAgICAgICAgICAgaWYgKGNoaWxkLmtleSkge1xuICAgICAgICAgICAgICAgICAgICAgICAga2V5c1tjaGlsZC5rZXldID0gaTtcbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGZyZWUucHVzaChpKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHJldHVybiB7XG4gICAgICAgICAgICAgICAgICAgIGtleXM6IGtleXMsIC8vIEEgaGFzaCBvZiBrZXkgbmFtZSB0byBpbmRleFxuICAgICAgICAgICAgICAgICAgICBmcmVlOiBmcmVlIC8vIEFuIGFycmF5IG9mIHVua2V5ZWQgaXRlbSBpbmRpY2VzXG4gICAgICAgICAgICAgICAgfTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZnVuY3Rpb24gYXBwZW5kUGF0Y2goYXBwbHksIHBhdGNoKSB7XG4gICAgICAgICAgICAgICAgaWYgKGFwcGx5KSB7XG4gICAgICAgICAgICAgICAgICAgIGlmIChpc0FycmF5KGFwcGx5KSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgYXBwbHkucHVzaChwYXRjaCk7XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBhcHBseSA9IFthcHBseSwgcGF0Y2hdO1xuICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGFwcGx5O1xuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBwYXRjaDtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH0sIHsgXCIuLi92bm9kZS9oYW5kbGUtdGh1bmtcIjogMjQsIFwiLi4vdm5vZGUvaXMtdGh1bmtcIjogMjUsIFwiLi4vdm5vZGUvaXMtdm5vZGVcIjogMjcsIFwiLi4vdm5vZGUvaXMtdnRleHRcIjogMjgsIFwiLi4vdm5vZGUvaXMtd2lkZ2V0XCI6IDI5LCBcIi4uL3Zub2RlL3ZwYXRjaFwiOiAzMiwgXCIuL2RpZmYtcHJvcHNcIjogMzQsIFwieC1pcy1hcnJheVwiOiAxMiB9XSB9LCB7fSwgWzRdKSg0KTtcbn0pO1xuXG5cbi8vIFByb3Bvc2VkIGZvciBFUzZcblxuc2VsZi5wb3N0X29mZmljZSA9IHNlbGYucG9zdF9vZmZpY2UgfHwgbmV3IFBvc3RPZmZpY2UoKTtcblxuZXhwb3J0IHsgX1BhdHRlcm5zIGFzIFBhdHRlcm5zLCBCaXRTdHJpbmcsIEtlcm5lbCwgQXRvbSwgRW51bSwgSW50ZWdlciwgSlMsIExpc3QsIFJhbmdlLCBUdXBsZSwgQWdlbnQsIEtleXdvcmQsIEJhc2UsIF9TdHJpbmcgYXMgU3RyaW5nLCBCaXR3aXNlLCBFbnVtZXJhYmxlLCBDb2xsZWN0YWJsZSwgSW5zcGVjdCwgX01hcCBhcyBNYXAsIF9TZXQgYXMgU2V0LCBNYXBTZXQsIEludGVnZXJUeXBlLCBGbG9hdFR5cGUsIHZpcnR1YWxEb20gYXMgVmlydHVhbERPTSB9OyJdLCJmaWxlIjoiZWxpeGlyLmpzIiwic291cmNlUm9vdCI6Ii9zb3VyY2UvIn0= \ No newline at end of file +export { _Patterns as Patterns, BitString, Kernel, Atom, Enum, Integer, JS, List, Range, Tuple, Agent, Keyword, Base, _String as String, Bitwise, Enumerable, Collectable, Inspect, _Map as Map, _Set as Set, MapSet, IntegerType, FloatType, virtualDom as VirtualDOM, View }; +//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiIiwic291cmNlcyI6WyJlbGl4aXIuanMiXSwic291cmNlc0NvbnRlbnQiOlsidmFyIFBhdHRlcm5zID0ge1xuICAgIGdldCBkZWZhdWx0ICgpIHsgcmV0dXJuIF9QYXR0ZXJuczsgfVxufTtcblxuY2xhc3MgVHVwbGUge1xuXG4gIGNvbnN0cnVjdG9yKC4uLmFyZ3MpIHtcbiAgICB0aGlzLnZhbHVlcyA9IE9iamVjdC5mcmVlemUoYXJncyk7XG4gIH1cblxuICBnZXQoaW5kZXgpIHtcbiAgICByZXR1cm4gdGhpcy52YWx1ZXNbaW5kZXhdO1xuICB9XG5cbiAgY291bnQoKSB7XG4gICAgcmV0dXJuIHRoaXMudmFsdWVzLmxlbmd0aDtcbiAgfVxuXG4gIFtTeW1ib2wuaXRlcmF0b3JdKCkge1xuICAgIHJldHVybiB0aGlzLnZhbHVlc1tTeW1ib2wuaXRlcmF0b3JdKCk7XG4gIH1cblxuICB0b1N0cmluZygpIHtcbiAgICB2YXIgaSxcbiAgICAgICAgcyA9IFwiXCI7XG4gICAgZm9yIChpID0gMDsgaSA8IHRoaXMudmFsdWVzLmxlbmd0aDsgaSsrKSB7XG4gICAgICBpZiAocyAhPT0gXCJcIikge1xuICAgICAgICBzICs9IFwiLCBcIjtcbiAgICAgIH1cbiAgICAgIHMgKz0gdGhpcy52YWx1ZXNbaV0udG9TdHJpbmcoKTtcbiAgICB9XG5cbiAgICByZXR1cm4gXCJ7XCIgKyBzICsgXCJ9XCI7XG4gIH1cblxuICBzdGF0aWMgdG9fc3RyaW5nKHR1cGxlKSB7XG4gICAgcmV0dXJuIHR1cGxlLnRvU3RyaW5nKCk7XG4gIH1cblxuICBzdGF0aWMgZGVsZXRlX2F0KHR1cGxlLCBpbmRleCkge1xuICAgIGxldCBuZXdfbGlzdCA9IFtdO1xuXG4gICAgZm9yICh2YXIgaSA9IDA7IGkgPCB0dXBsZS5jb3VudCgpOyBpKyspIHtcbiAgICAgIGlmIChpICE9PSBpbmRleCkge1xuICAgICAgICBuZXdfbGlzdC5wdXNoKHR1cGxlLmdldChpKSk7XG4gICAgICB9XG4gICAgfVxuXG4gICAgcmV0dXJuIEtlcm5lbC5TcGVjaWFsRm9ybXMudHVwbGUuYXBwbHkobnVsbCwgbmV3X2xpc3QpO1xuICB9XG5cbiAgc3RhdGljIGR1cGxpY2F0ZShkYXRhLCBzaXplKSB7XG4gICAgbGV0IGFycmF5ID0gW107XG5cbiAgICBmb3IgKHZhciBpID0gc2l6ZSAtIDE7IGkgPj0gMDsgaS0tKSB7XG4gICAgICBhcnJheS5wdXNoKGRhdGEpO1xuICAgIH1cblxuICAgIHJldHVybiBLZXJuZWwuU3BlY2lhbEZvcm1zLnR1cGxlLmFwcGx5KG51bGwsIGFycmF5KTtcbiAgfVxuXG4gIHN0YXRpYyBpbnNlcnRfYXQodHVwbGUsIGluZGV4LCB0ZXJtKSB7XG4gICAgbGV0IG5ld190dXBsZSA9IFtdO1xuXG4gICAgZm9yICh2YXIgaSA9IDA7IGkgPD0gdHVwbGUuY291bnQoKTsgaSsrKSB7XG4gICAgICBpZiAoaSA9PT0gaW5kZXgpIHtcbiAgICAgICAgbmV3X3R1cGxlLnB1c2godGVybSk7XG4gICAgICAgIGkrKztcbiAgICAgICAgbmV3X3R1cGxlLnB1c2godHVwbGUuZ2V0KGkpKTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIG5ld190dXBsZS5wdXNoKHR1cGxlLmdldChpKSk7XG4gICAgICB9XG4gICAgfVxuXG4gICAgcmV0dXJuIEtlcm5lbC5TcGVjaWFsRm9ybXMudHVwbGUuYXBwbHkobnVsbCwgbmV3X3R1cGxlKTtcbiAgfVxuXG4gIHN0YXRpYyBmcm9tX2xpc3QobGlzdCkge1xuICAgIHJldHVybiBLZXJuZWwuU3BlY2lhbEZvcm1zLnR1cGxlLmFwcGx5KG51bGwsIGxpc3QpO1xuICB9XG5cbiAgc3RhdGljIHRvX2xpc3QodHVwbGUpIHtcbiAgICBsZXQgbmV3X2xpc3QgPSBbXTtcblxuICAgIGZvciAodmFyIGkgPSAwOyBpIDwgdHVwbGUuY291bnQoKTsgaSsrKSB7XG4gICAgICBuZXdfbGlzdC5wdXNoKHR1cGxlLmdldChpKSk7XG4gICAgfVxuXG4gICAgcmV0dXJuIEtlcm5lbC5TcGVjaWFsRm9ybXMubGlzdCguLi5uZXdfbGlzdCk7XG4gIH1cbn1cblxuLyogQGZsb3cgKi9cblxuY2xhc3MgVmFyaWFibGUge1xuXG4gIGNvbnN0cnVjdG9yKG5hbWUgPSBudWxsKSB7XG4gICAgdGhpcy5uYW1lID0gbmFtZTtcbiAgfVxufVxuXG5jbGFzcyBXaWxkY2FyZCB7XG4gIGNvbnN0cnVjdG9yKCkge31cbn1cblxuY2xhc3MgU3RhcnRzV2l0aCB7XG5cbiAgY29uc3RydWN0b3IocHJlZml4KSB7XG4gICAgdGhpcy5wcmVmaXggPSBwcmVmaXg7XG4gIH1cbn1cblxuY2xhc3MgQ2FwdHVyZSB7XG5cbiAgY29uc3RydWN0b3IodmFsdWUpIHtcbiAgICB0aGlzLnZhbHVlID0gdmFsdWU7XG4gIH1cbn1cblxuY2xhc3MgSGVhZFRhaWwge1xuICBjb25zdHJ1Y3RvcigpIHt9XG59XG5cbmNsYXNzIFR5cGUge1xuXG4gIGNvbnN0cnVjdG9yKHR5cGUsIG9ialBhdHRlcm4gPSB7fSkge1xuICAgIHRoaXMudHlwZSA9IHR5cGU7XG4gICAgdGhpcy5vYmpQYXR0ZXJuID0gb2JqUGF0dGVybjtcbiAgfVxufVxuXG5jbGFzcyBCb3VuZCB7XG5cbiAgY29uc3RydWN0b3IodmFsdWUpIHtcbiAgICB0aGlzLnZhbHVlID0gdmFsdWU7XG4gIH1cbn1cblxuZnVuY3Rpb24gdmFyaWFibGUobmFtZSA9IG51bGwpIHtcbiAgcmV0dXJuIG5ldyBWYXJpYWJsZShuYW1lKTtcbn1cblxuZnVuY3Rpb24gd2lsZGNhcmQoKSB7XG4gIHJldHVybiBuZXcgV2lsZGNhcmQoKTtcbn1cblxuZnVuY3Rpb24gc3RhcnRzV2l0aChwcmVmaXgpIHtcbiAgcmV0dXJuIG5ldyBTdGFydHNXaXRoKHByZWZpeCk7XG59XG5cbmZ1bmN0aW9uIGNhcHR1cmUodmFsdWUpIHtcbiAgcmV0dXJuIG5ldyBDYXB0dXJlKHZhbHVlKTtcbn1cblxuZnVuY3Rpb24gaGVhZFRhaWwoKSB7XG4gIHJldHVybiBuZXcgSGVhZFRhaWwoKTtcbn1cblxuZnVuY3Rpb24gdHlwZSh0eXBlLCBvYmpQYXR0ZXJuID0ge30pIHtcbiAgcmV0dXJuIG5ldyBUeXBlKHR5cGUsIG9ialBhdHRlcm4pO1xufVxuXG5mdW5jdGlvbiBib3VuZCh2YWx1ZSkge1xuICByZXR1cm4gbmV3IEJvdW5kKHZhbHVlKTtcbn1cblxuZnVuY3Rpb24gX2lzX251bWJlcih2YWx1ZSkge1xuICByZXR1cm4gdHlwZW9mIHZhbHVlID09PSAnbnVtYmVyJztcbn1cblxuZnVuY3Rpb24gaXNfc3RyaW5nKHZhbHVlKSB7XG4gIHJldHVybiB0eXBlb2YgdmFsdWUgPT09ICdzdHJpbmcnO1xufVxuXG5mdW5jdGlvbiBfaXNfdHVwbGUodmFsdWUpIHtcbiAgcmV0dXJuIHZhbHVlIGluc3RhbmNlb2YgVHVwbGU7XG59XG5cbmZ1bmN0aW9uIF9pc19ib29sZWFuKHZhbHVlKSB7XG4gIHJldHVybiB0eXBlb2YgdmFsdWUgPT09ICdib29sZWFuJztcbn1cblxuZnVuY3Rpb24gaXNfc3ltYm9sKHZhbHVlKSB7XG4gIHJldHVybiB0eXBlb2YgdmFsdWUgPT09ICdzeW1ib2wnO1xufVxuXG5mdW5jdGlvbiBpc19udWxsKHZhbHVlKSB7XG4gIHJldHVybiB2YWx1ZSA9PT0gbnVsbDtcbn1cblxuZnVuY3Rpb24gaXNfdW5kZWZpbmVkKHZhbHVlKSB7XG4gIHJldHVybiB0eXBlb2YgdmFsdWUgPT09ICd1bmRlZmluZWQnO1xufVxuXG5mdW5jdGlvbiBfaXNfZnVuY3Rpb24odmFsdWUpIHtcbiAgcmV0dXJuIE9iamVjdC5wcm90b3R5cGUudG9TdHJpbmcuY2FsbCh2YWx1ZSkgPT0gJ1tvYmplY3QgRnVuY3Rpb25dJztcbn1cblxuZnVuY3Rpb24gaXNfdmFyaWFibGUodmFsdWUpIHtcbiAgcmV0dXJuIHZhbHVlIGluc3RhbmNlb2YgVmFyaWFibGU7XG59XG5cbmZ1bmN0aW9uIGlzX3dpbGRjYXJkKHZhbHVlKSB7XG4gIHJldHVybiB2YWx1ZSBpbnN0YW5jZW9mIFdpbGRjYXJkO1xufVxuXG5mdW5jdGlvbiBpc19oZWFkVGFpbCh2YWx1ZSkge1xuICByZXR1cm4gdmFsdWUgaW5zdGFuY2VvZiBIZWFkVGFpbDtcbn1cblxuZnVuY3Rpb24gaXNfY2FwdHVyZSh2YWx1ZSkge1xuICByZXR1cm4gdmFsdWUgaW5zdGFuY2VvZiBDYXB0dXJlO1xufVxuXG5mdW5jdGlvbiBpc190eXBlKHZhbHVlKSB7XG4gIHJldHVybiB2YWx1ZSBpbnN0YW5jZW9mIFR5cGU7XG59XG5cbmZ1bmN0aW9uIGlzX3N0YXJ0c1dpdGgodmFsdWUpIHtcbiAgcmV0dXJuIHZhbHVlIGluc3RhbmNlb2YgU3RhcnRzV2l0aDtcbn1cblxuZnVuY3Rpb24gaXNfYm91bmQodmFsdWUpIHtcbiAgcmV0dXJuIHZhbHVlIGluc3RhbmNlb2YgQm91bmQ7XG59XG5cbmZ1bmN0aW9uIGlzX29iamVjdCh2YWx1ZSkge1xuICByZXR1cm4gdHlwZW9mIHZhbHVlID09PSAnb2JqZWN0Jztcbn1cblxuZnVuY3Rpb24gaXNfYXJyYXkodmFsdWUpIHtcbiAgcmV0dXJuIEFycmF5LmlzQXJyYXkodmFsdWUpO1xufVxuXG52YXIgQ2hlY2tzID0ge1xuICBpc19udW1iZXI6IF9pc19udW1iZXIsXG4gIGlzX3N0cmluZyxcbiAgaXNfYm9vbGVhbjogX2lzX2Jvb2xlYW4sXG4gIGlzX3N5bWJvbCxcbiAgaXNfbnVsbCxcbiAgaXNfdW5kZWZpbmVkLFxuICBpc19mdW5jdGlvbjogX2lzX2Z1bmN0aW9uLFxuICBpc192YXJpYWJsZSxcbiAgaXNfd2lsZGNhcmQsXG4gIGlzX2hlYWRUYWlsLFxuICBpc19jYXB0dXJlLFxuICBpc190eXBlLFxuICBpc19zdGFydHNXaXRoLFxuICBpc19ib3VuZCxcbiAgaXNfb2JqZWN0LFxuICBpc19hcnJheSxcbiAgaXNfdHVwbGU6IF9pc190dXBsZVxufTtcblxuZnVuY3Rpb24gcmVzb2x2ZVR1cGxlKHBhdHRlcm4pIHtcbiAgbGV0IG1hdGNoZXMgPSBbXTtcblxuICBmb3IgKGxldCBlbGVtIG9mIHBhdHRlcm4pIHtcbiAgICBtYXRjaGVzLnB1c2goYnVpbGRNYXRjaChlbGVtKSk7XG4gIH1cblxuICByZXR1cm4gZnVuY3Rpb24gKHZhbHVlLCBhcmdzKSB7XG4gICAgaWYgKCFDaGVja3MuaXNfdHVwbGUodmFsdWUpIHx8IHZhbHVlLmNvdW50KCkgIT0gcGF0dGVybi5jb3VudCgpKSB7XG4gICAgICByZXR1cm4gZmFsc2U7XG4gICAgfVxuXG4gICAgcmV0dXJuIHZhbHVlLnZhbHVlcy5ldmVyeShmdW5jdGlvbiAodiwgaSkge1xuICAgICAgcmV0dXJuIG1hdGNoZXNbaV0odmFsdWUuZ2V0KGkpLCBhcmdzKTtcbiAgICB9KTtcbiAgfTtcbn1cblxuZnVuY3Rpb24gcmVzb2x2ZVN5bWJvbChwYXR0ZXJuKSB7XG4gIHJldHVybiBmdW5jdGlvbiAodmFsdWUpIHtcbiAgICByZXR1cm4gQ2hlY2tzLmlzX3N5bWJvbCh2YWx1ZSkgJiYgdmFsdWUgPT09IHBhdHRlcm47XG4gIH07XG59XG5cbmZ1bmN0aW9uIHJlc29sdmVTdHJpbmcocGF0dGVybikge1xuICByZXR1cm4gZnVuY3Rpb24gKHZhbHVlKSB7XG4gICAgcmV0dXJuIENoZWNrcy5pc19zdHJpbmcodmFsdWUpICYmIHZhbHVlID09PSBwYXR0ZXJuO1xuICB9O1xufVxuXG5mdW5jdGlvbiByZXNvbHZlTnVtYmVyKHBhdHRlcm4pIHtcbiAgcmV0dXJuIGZ1bmN0aW9uICh2YWx1ZSkge1xuICAgIHJldHVybiBDaGVja3MuaXNfbnVtYmVyKHZhbHVlKSAmJiB2YWx1ZSA9PT0gcGF0dGVybjtcbiAgfTtcbn1cblxuZnVuY3Rpb24gcmVzb2x2ZUJvb2xlYW4ocGF0dGVybikge1xuICByZXR1cm4gZnVuY3Rpb24gKHZhbHVlKSB7XG4gICAgcmV0dXJuIENoZWNrcy5pc19ib29sZWFuKHZhbHVlKSAmJiB2YWx1ZSA9PT0gcGF0dGVybjtcbiAgfTtcbn1cblxuZnVuY3Rpb24gcmVzb2x2ZUZ1bmN0aW9uKHBhdHRlcm4pIHtcbiAgcmV0dXJuIGZ1bmN0aW9uICh2YWx1ZSkge1xuICAgIHJldHVybiBDaGVja3MuaXNfZnVuY3Rpb24odmFsdWUpICYmIHZhbHVlID09PSBwYXR0ZXJuO1xuICB9O1xufVxuXG5mdW5jdGlvbiByZXNvbHZlTnVsbChwYXR0ZXJuKSB7XG4gIHJldHVybiBmdW5jdGlvbiAodmFsdWUpIHtcbiAgICByZXR1cm4gQ2hlY2tzLmlzX251bGwodmFsdWUpO1xuICB9O1xufVxuXG5mdW5jdGlvbiByZXNvbHZlQm91bmQocGF0dGVybikge1xuICByZXR1cm4gZnVuY3Rpb24gKHZhbHVlLCBhcmdzKSB7XG4gICAgaWYgKHR5cGVvZiB2YWx1ZSA9PT0gdHlwZW9mIHBhdHRlcm4udmFsdWUgJiYgdmFsdWUgPT09IHBhdHRlcm4udmFsdWUpIHtcbiAgICAgIGFyZ3MucHVzaCh2YWx1ZSk7XG4gICAgICByZXR1cm4gdHJ1ZTtcbiAgICB9XG5cbiAgICByZXR1cm4gZmFsc2U7XG4gIH07XG59XG5cbmZ1bmN0aW9uIHJlc29sdmVXaWxkY2FyZCgpIHtcbiAgcmV0dXJuIGZ1bmN0aW9uICgpIHtcbiAgICByZXR1cm4gdHJ1ZTtcbiAgfTtcbn1cblxuZnVuY3Rpb24gcmVzb2x2ZVZhcmlhYmxlKCkge1xuICByZXR1cm4gZnVuY3Rpb24gKHZhbHVlLCBhcmdzKSB7XG4gICAgYXJncy5wdXNoKHZhbHVlKTtcbiAgICByZXR1cm4gdHJ1ZTtcbiAgfTtcbn1cblxuZnVuY3Rpb24gcmVzb2x2ZUhlYWRUYWlsKCkge1xuICByZXR1cm4gZnVuY3Rpb24gKHZhbHVlLCBhcmdzKSB7XG4gICAgaWYgKCFDaGVja3MuaXNfYXJyYXkodmFsdWUpIHx8IHZhbHVlLmxlbmd0aCA8IDIpIHtcbiAgICAgIHJldHVybiBmYWxzZTtcbiAgICB9XG5cbiAgICBjb25zdCBoZWFkID0gdmFsdWVbMF07XG4gICAgY29uc3QgdGFpbCA9IHZhbHVlLnNsaWNlKDEpO1xuXG4gICAgYXJncy5wdXNoKGhlYWQpO1xuICAgIGFyZ3MucHVzaCh0YWlsKTtcblxuICAgIHJldHVybiB0cnVlO1xuICB9O1xufVxuXG5mdW5jdGlvbiByZXNvbHZlQ2FwdHVyZShwYXR0ZXJuKSB7XG4gIGNvbnN0IG1hdGNoZXMgPSBidWlsZE1hdGNoKHBhdHRlcm4udmFsdWUpO1xuXG4gIHJldHVybiBmdW5jdGlvbiAodmFsdWUsIGFyZ3MpIHtcbiAgICBpZiAobWF0Y2hlcyh2YWx1ZSwgYXJncykpIHtcbiAgICAgIGFyZ3MucHVzaCh2YWx1ZSk7XG4gICAgICByZXR1cm4gdHJ1ZTtcbiAgICB9XG5cbiAgICByZXR1cm4gZmFsc2U7XG4gIH07XG59XG5cbmZ1bmN0aW9uIHJlc29sdmVTdGFydHNXaXRoKHBhdHRlcm4pIHtcbiAgY29uc3QgcHJlZml4ID0gcGF0dGVybi5wcmVmaXg7XG5cbiAgcmV0dXJuIGZ1bmN0aW9uICh2YWx1ZSwgYXJncykge1xuICAgIGlmIChDaGVja3MuaXNfc3RyaW5nKHZhbHVlKSAmJiB2YWx1ZS5zdGFydHNXaXRoKHByZWZpeCkpIHtcbiAgICAgIGFyZ3MucHVzaCh2YWx1ZS5zdWJzdHJpbmcocHJlZml4Lmxlbmd0aCkpO1xuICAgICAgcmV0dXJuIHRydWU7XG4gICAgfVxuXG4gICAgcmV0dXJuIGZhbHNlO1xuICB9O1xufVxuXG5mdW5jdGlvbiByZXNvbHZlVHlwZShwYXR0ZXJuKSB7XG4gIHJldHVybiBmdW5jdGlvbiAodmFsdWUsIGFyZ3MpIHtcbiAgICBpZiAodmFsdWUgaW5zdGFuY2VvZiBwYXR0ZXJuLnR5cGUpIHtcbiAgICAgIGNvbnN0IG1hdGNoZXMgPSBidWlsZE1hdGNoKHBhdHRlcm4ub2JqUGF0dGVybik7XG4gICAgICByZXR1cm4gbWF0Y2hlcyh2YWx1ZSwgYXJncykgJiYgYXJncy5wdXNoKHZhbHVlKSA+IDA7XG4gICAgfVxuXG4gICAgcmV0dXJuIGZhbHNlO1xuICB9O1xufVxuXG5mdW5jdGlvbiByZXNvbHZlQXJyYXkocGF0dGVybikge1xuICBjb25zdCBtYXRjaGVzID0gcGF0dGVybi5tYXAoeCA9PiBidWlsZE1hdGNoKHgpKTtcblxuICByZXR1cm4gZnVuY3Rpb24gKHZhbHVlLCBhcmdzKSB7XG4gICAgaWYgKCFDaGVja3MuaXNfYXJyYXkodmFsdWUpIHx8IHZhbHVlLmxlbmd0aCAhPSBwYXR0ZXJuLmxlbmd0aCkge1xuICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH1cblxuICAgIHJldHVybiB2YWx1ZS5ldmVyeShmdW5jdGlvbiAodiwgaSkge1xuICAgICAgcmV0dXJuIG1hdGNoZXNbaV0odmFsdWVbaV0sIGFyZ3MpO1xuICAgIH0pO1xuICB9O1xufVxuXG5mdW5jdGlvbiByZXNvbHZlT2JqZWN0KHBhdHRlcm4pIHtcbiAgbGV0IG1hdGNoZXMgPSB7fTtcblxuICBmb3IgKGxldCBrZXkgb2YgT2JqZWN0LmtleXMocGF0dGVybikpIHtcbiAgICBtYXRjaGVzW2tleV0gPSBidWlsZE1hdGNoKHBhdHRlcm5ba2V5XSk7XG4gIH1cblxuICByZXR1cm4gZnVuY3Rpb24gKHZhbHVlLCBhcmdzKSB7XG4gICAgaWYgKCFDaGVja3MuaXNfb2JqZWN0KHZhbHVlKSB8fCBwYXR0ZXJuLmxlbmd0aCA+IHZhbHVlLmxlbmd0aCkge1xuICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH1cblxuICAgIGZvciAobGV0IGtleSBvZiBPYmplY3Qua2V5cyhwYXR0ZXJuKSkge1xuICAgICAgaWYgKCEoa2V5IGluIHZhbHVlKSB8fCAhbWF0Y2hlc1trZXldKHZhbHVlW2tleV0sIGFyZ3MpKSB7XG4gICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICByZXR1cm4gdHJ1ZTtcbiAgfTtcbn1cblxuZnVuY3Rpb24gcmVzb2x2ZU5vTWF0Y2goKSB7XG4gIHJldHVybiBmdW5jdGlvbiAoKSB7XG4gICAgcmV0dXJuIGZhbHNlO1xuICB9O1xufVxuXG52YXIgUmVzb2x2ZXJzID0ge1xuICByZXNvbHZlQm91bmQsXG4gIHJlc29sdmVXaWxkY2FyZCxcbiAgcmVzb2x2ZVZhcmlhYmxlLFxuICByZXNvbHZlSGVhZFRhaWwsXG4gIHJlc29sdmVDYXB0dXJlLFxuICByZXNvbHZlU3RhcnRzV2l0aCxcbiAgcmVzb2x2ZVR5cGUsXG4gIHJlc29sdmVBcnJheSxcbiAgcmVzb2x2ZU9iamVjdCxcbiAgcmVzb2x2ZU5vTWF0Y2gsXG4gIHJlc29sdmVTeW1ib2wsXG4gIHJlc29sdmVTdHJpbmcsXG4gIHJlc29sdmVOdW1iZXIsXG4gIHJlc29sdmVCb29sZWFuLFxuICByZXNvbHZlRnVuY3Rpb24sXG4gIHJlc29sdmVOdWxsLFxuICByZXNvbHZlVHVwbGVcbn07XG5cbmZ1bmN0aW9uIGJ1aWxkTWF0Y2gocGF0dGVybikge1xuXG4gIGlmIChDaGVja3MuaXNfdHVwbGUocGF0dGVybikpIHtcbiAgICByZXR1cm4gUmVzb2x2ZXJzLnJlc29sdmVUdXBsZShwYXR0ZXJuKTtcbiAgfVxuXG4gIGlmIChDaGVja3MuaXNfdmFyaWFibGUocGF0dGVybikpIHtcbiAgICByZXR1cm4gUmVzb2x2ZXJzLnJlc29sdmVWYXJpYWJsZShwYXR0ZXJuKTtcbiAgfVxuXG4gIGlmIChDaGVja3MuaXNfd2lsZGNhcmQocGF0dGVybikpIHtcbiAgICByZXR1cm4gUmVzb2x2ZXJzLnJlc29sdmVXaWxkY2FyZChwYXR0ZXJuKTtcbiAgfVxuXG4gIGlmIChDaGVja3MuaXNfdW5kZWZpbmVkKHBhdHRlcm4pKSB7XG4gICAgcmV0dXJuIFJlc29sdmVycy5yZXNvbHZlV2lsZGNhcmQocGF0dGVybik7XG4gIH1cblxuICBpZiAoQ2hlY2tzLmlzX2hlYWRUYWlsKHBhdHRlcm4pKSB7XG4gICAgcmV0dXJuIFJlc29sdmVycy5yZXNvbHZlSGVhZFRhaWwocGF0dGVybik7XG4gIH1cblxuICBpZiAoQ2hlY2tzLmlzX3N0YXJ0c1dpdGgocGF0dGVybikpIHtcbiAgICByZXR1cm4gUmVzb2x2ZXJzLnJlc29sdmVTdGFydHNXaXRoKHBhdHRlcm4pO1xuICB9XG5cbiAgaWYgKENoZWNrcy5pc19jYXB0dXJlKHBhdHRlcm4pKSB7XG4gICAgcmV0dXJuIFJlc29sdmVycy5yZXNvbHZlQ2FwdHVyZShwYXR0ZXJuKTtcbiAgfVxuXG4gIGlmIChDaGVja3MuaXNfYm91bmQocGF0dGVybikpIHtcbiAgICByZXR1cm4gUmVzb2x2ZXJzLnJlc29sdmVCb3VuZChwYXR0ZXJuKTtcbiAgfVxuXG4gIGlmIChDaGVja3MuaXNfdHlwZShwYXR0ZXJuKSkge1xuICAgIHJldHVybiBSZXNvbHZlcnMucmVzb2x2ZVR5cGUocGF0dGVybik7XG4gIH1cblxuICBpZiAoQ2hlY2tzLmlzX2FycmF5KHBhdHRlcm4pKSB7XG4gICAgcmV0dXJuIFJlc29sdmVycy5yZXNvbHZlQXJyYXkocGF0dGVybik7XG4gIH1cblxuICBpZiAoQ2hlY2tzLmlzX251bWJlcihwYXR0ZXJuKSkge1xuICAgIHJldHVybiBSZXNvbHZlcnMucmVzb2x2ZU51bWJlcihwYXR0ZXJuKTtcbiAgfVxuXG4gIGlmIChDaGVja3MuaXNfc3RyaW5nKHBhdHRlcm4pKSB7XG4gICAgcmV0dXJuIFJlc29sdmVycy5yZXNvbHZlU3RyaW5nKHBhdHRlcm4pO1xuICB9XG5cbiAgaWYgKENoZWNrcy5pc19ib29sZWFuKHBhdHRlcm4pKSB7XG4gICAgcmV0dXJuIFJlc29sdmVycy5yZXNvbHZlQm9vbGVhbihwYXR0ZXJuKTtcbiAgfVxuXG4gIGlmIChDaGVja3MuaXNfc3ltYm9sKHBhdHRlcm4pKSB7XG4gICAgcmV0dXJuIFJlc29sdmVycy5yZXNvbHZlU3ltYm9sKHBhdHRlcm4pO1xuICB9XG5cbiAgaWYgKENoZWNrcy5pc19udWxsKHBhdHRlcm4pKSB7XG4gICAgcmV0dXJuIFJlc29sdmVycy5yZXNvbHZlTnVsbChwYXR0ZXJuKTtcbiAgfVxuXG4gIGlmIChDaGVja3MuaXNfb2JqZWN0KHBhdHRlcm4pKSB7XG4gICAgcmV0dXJuIFJlc29sdmVycy5yZXNvbHZlT2JqZWN0KHBhdHRlcm4pO1xuICB9XG5cbiAgcmV0dXJuIFJlc29sdmVycy5yZXNvbHZlTm9NYXRjaCgpO1xufVxuXG5jbGFzcyBNYXRjaEVycm9yIGV4dGVuZHMgRXJyb3Ige1xuICBjb25zdHJ1Y3RvcihhcmcpIHtcbiAgICBzdXBlcigpO1xuXG4gICAgaWYgKHR5cGVvZiBhcmcgPT09ICdzeW1ib2wnKSB7XG4gICAgICB0aGlzLm1lc3NhZ2UgPSAnTm8gbWF0Y2ggZm9yOiAnICsgYXJnLnRvU3RyaW5nKCk7XG4gICAgfSBlbHNlIGlmIChBcnJheS5pc0FycmF5KGFyZykpIHtcbiAgICAgIGxldCBtYXBwZWRWYWx1ZXMgPSBhcmcubWFwKHggPT4geC50b1N0cmluZygpKTtcbiAgICAgIHRoaXMubWVzc2FnZSA9ICdObyBtYXRjaCBmb3I6ICcgKyBtYXBwZWRWYWx1ZXM7XG4gICAgfSBlbHNlIHtcbiAgICAgIHRoaXMubWVzc2FnZSA9ICdObyBtYXRjaCBmb3I6ICcgKyBhcmc7XG4gICAgfVxuXG4gICAgdGhpcy5zdGFjayA9IG5ldyBFcnJvcigpLnN0YWNrO1xuICAgIHRoaXMubmFtZSA9IHRoaXMuY29uc3RydWN0b3IubmFtZTtcbiAgfVxufVxuXG5jbGFzcyBDYXNlIHtcblxuICBjb25zdHJ1Y3RvcihwYXR0ZXJuLCBmbiwgZ3VhcmQgPSAoKSA9PiB0cnVlKSB7XG4gICAgdGhpcy5wYXR0ZXJuID0gYnVpbGRNYXRjaChwYXR0ZXJuKTtcbiAgICB0aGlzLmZuID0gZm47XG4gICAgdGhpcy5ndWFyZCA9IGd1YXJkO1xuICB9XG59XG5cbmZ1bmN0aW9uIG1ha2VfY2FzZShwYXR0ZXJuLCBmbiwgZ3VhcmQgPSAoKSA9PiB0cnVlKSB7XG4gIHJldHVybiBuZXcgQ2FzZShwYXR0ZXJuLCBmbiwgZ3VhcmQpO1xufVxuXG5mdW5jdGlvbiBkZWZtYXRjaCguLi5jYXNlcykge1xuICByZXR1cm4gZnVuY3Rpb24gKC4uLmFyZ3MpIHtcbiAgICBmb3IgKGxldCBwcm9jZXNzZWRDYXNlIG9mIGNhc2VzKSB7XG4gICAgICBsZXQgcmVzdWx0ID0gW107XG4gICAgICBpZiAocHJvY2Vzc2VkQ2FzZS5wYXR0ZXJuKGFyZ3MsIHJlc3VsdCkgJiYgcHJvY2Vzc2VkQ2FzZS5ndWFyZC5hcHBseSh0aGlzLCByZXN1bHQpKSB7XG4gICAgICAgIHJldHVybiBwcm9jZXNzZWRDYXNlLmZuLmFwcGx5KHRoaXMsIHJlc3VsdCk7XG4gICAgICB9XG4gICAgfVxuXG4gICAgdGhyb3cgbmV3IE1hdGNoRXJyb3IoYXJncyk7XG4gIH07XG59XG5cbmZ1bmN0aW9uIG1hdGNoKHBhdHRlcm4sIGV4cHIsIGd1YXJkID0gKCkgPT4gdHJ1ZSkge1xuICBsZXQgcmVzdWx0ID0gW107XG4gIGxldCBwcm9jZXNzZWRQYXR0ZXJuID0gYnVpbGRNYXRjaChwYXR0ZXJuKTtcbiAgaWYgKHByb2Nlc3NlZFBhdHRlcm4oZXhwciwgcmVzdWx0KSAmJiBndWFyZC5hcHBseSh0aGlzLCByZXN1bHQpKSB7XG4gICAgcmV0dXJuIHJlc3VsdDtcbiAgfSBlbHNlIHtcbiAgICB0aHJvdyBuZXcgTWF0Y2hFcnJvcihleHByKTtcbiAgfVxufVxuXG5mdW5jdGlvbiBtYXRjaF9ub190aHJvdyhwYXR0ZXJuLCBleHByLCBndWFyZCA9ICgpID0+IHRydWUpIHtcbiAgdHJ5IHtcbiAgICByZXR1cm4gbWF0Y2gocGF0dGVybiwgZXhwciwgZ3VhcmQpO1xuICB9IGNhdGNoIChlKSB7XG4gICAgaWYgKGUgaW5zdGFuY2VvZiBNYXRjaEVycm9yKSB7XG4gICAgICByZXR1cm4gbnVsbDtcbiAgICB9XG5cbiAgICB0aHJvdyBlO1xuICB9XG59XG5cbmZ1bmN0aW9uIHBhdHRlcm5NYXAoY29sbGVjdGlvbiwgcGF0dGVybiwgZnVuLCBndWFyZCA9ICgpID0+IHRydWUpIHtcbiAgbGV0IHJldCA9IFtdO1xuXG4gIGZvciAobGV0IGVsZW0gb2YgY29sbGVjdGlvbikge1xuICAgIHRyeSB7XG4gICAgICBsZXQgcmVzdWx0ID0gZnVuLmFwcGx5KHRoaXMsIG1hdGNoKHBhdHRlcm4sIGVsZW0sIGd1YXJkKSk7XG4gICAgICByZXQgPSByZXQuY29uY2F0KHJlc3VsdCk7XG4gICAgfSBjYXRjaCAoZSkge1xuICAgICAgaWYgKCEoZSBpbnN0YW5jZW9mIE1hdGNoRXJyb3IpKSB7XG4gICAgICAgIHRocm93IGU7XG4gICAgICB9XG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIHJldDtcbn1cblxudmFyIF9QYXR0ZXJucyA9IHtcbiAgZGVmbWF0Y2gsIG1hdGNoLCBNYXRjaEVycm9yLCBtYXRjaF9ub190aHJvdywgcGF0dGVybk1hcCxcbiAgdmFyaWFibGUsIHdpbGRjYXJkLCBzdGFydHNXaXRoLFxuICBjYXB0dXJlLCBoZWFkVGFpbCwgdHlwZSwgYm91bmQsIENhc2UsIG1ha2VfY2FzZVxufTtcblxuY2xhc3MgQml0U3RyaW5nIHtcbiAgY29uc3RydWN0b3IoLi4uYXJncykge1xuICAgIHRoaXMucmF3X3ZhbHVlID0gZnVuY3Rpb24gKCkge1xuICAgICAgcmV0dXJuIE9iamVjdC5mcmVlemUoYXJncyk7XG4gICAgfTtcblxuICAgIHRoaXMudmFsdWUgPSBPYmplY3QuZnJlZXplKHRoaXMucHJvY2VzcyhhcmdzKSk7XG4gIH1cblxuICBnZXQoaW5kZXgpIHtcbiAgICByZXR1cm4gdGhpcy52YWx1ZVtpbmRleF07XG4gIH1cblxuICBjb3VudCgpIHtcbiAgICByZXR1cm4gdGhpcy52YWx1ZS5sZW5ndGg7XG4gIH1cblxuICBbU3ltYm9sLml0ZXJhdG9yXSgpIHtcbiAgICByZXR1cm4gdGhpcy52YWx1ZVtTeW1ib2wuaXRlcmF0b3JdKCk7XG4gIH1cblxuICB0b1N0cmluZygpIHtcbiAgICB2YXIgaSxcbiAgICAgICAgcyA9IFwiXCI7XG4gICAgZm9yIChpID0gMDsgaSA8IHRoaXMuY291bnQoKTsgaSsrKSB7XG4gICAgICBpZiAocyAhPT0gXCJcIikge1xuICAgICAgICBzICs9IFwiLCBcIjtcbiAgICAgIH1cbiAgICAgIHMgKz0gdGhpc1tpXS50b1N0cmluZygpO1xuICAgIH1cblxuICAgIHJldHVybiBcIjw8XCIgKyBzICsgXCI+PlwiO1xuICB9XG5cbiAgcHJvY2VzcygpIHtcbiAgICBsZXQgcHJvY2Vzc2VkX3ZhbHVlcyA9IFtdO1xuXG4gICAgdmFyIGk7XG4gICAgZm9yIChpID0gMDsgaSA8IHRoaXMucmF3X3ZhbHVlKCkubGVuZ3RoOyBpKyspIHtcbiAgICAgIGxldCBwcm9jZXNzZWRfdmFsdWUgPSB0aGlzW1wicHJvY2Vzc19cIiArIHRoaXMucmF3X3ZhbHVlKClbaV0udHlwZV0odGhpcy5yYXdfdmFsdWUoKVtpXSk7XG5cbiAgICAgIGZvciAobGV0IGF0dHIgb2YgdGhpcy5yYXdfdmFsdWUoKVtpXS5hdHRyaWJ1dGVzKSB7XG4gICAgICAgIHByb2Nlc3NlZF92YWx1ZSA9IHRoaXNbXCJwcm9jZXNzX1wiICsgYXR0cl0ocHJvY2Vzc2VkX3ZhbHVlKTtcbiAgICAgIH1cblxuICAgICAgcHJvY2Vzc2VkX3ZhbHVlcyA9IHByb2Nlc3NlZF92YWx1ZXMuY29uY2F0KHByb2Nlc3NlZF92YWx1ZSk7XG4gICAgfVxuXG4gICAgcmV0dXJuIHByb2Nlc3NlZF92YWx1ZXM7XG4gIH1cblxuICBwcm9jZXNzX2ludGVnZXIodmFsdWUpIHtcbiAgICByZXR1cm4gdmFsdWUudmFsdWU7XG4gIH1cblxuICBwcm9jZXNzX2Zsb2F0KHZhbHVlKSB7XG4gICAgaWYgKHZhbHVlLnNpemUgPT09IDY0KSB7XG4gICAgICByZXR1cm4gQml0U3RyaW5nLmZsb2F0NjRUb0J5dGVzKHZhbHVlLnZhbHVlKTtcbiAgICB9IGVsc2UgaWYgKHZhbHVlLnNpemUgPT09IDMyKSB7XG4gICAgICByZXR1cm4gQml0U3RyaW5nLmZsb2F0MzJUb0J5dGVzKHZhbHVlLnZhbHVlKTtcbiAgICB9XG5cbiAgICB0aHJvdyBuZXcgRXJyb3IoXCJJbnZhbGlkIHNpemUgZm9yIGZsb2F0XCIpO1xuICB9XG5cbiAgcHJvY2Vzc19iaXRzdHJpbmcodmFsdWUpIHtcbiAgICByZXR1cm4gdmFsdWUudmFsdWUudmFsdWU7XG4gIH1cblxuICBwcm9jZXNzX2JpbmFyeSh2YWx1ZSkge1xuICAgIHJldHVybiBCaXRTdHJpbmcudG9VVEY4QXJyYXkodmFsdWUudmFsdWUpO1xuICB9XG5cbiAgcHJvY2Vzc191dGY4KHZhbHVlKSB7XG4gICAgcmV0dXJuIEJpdFN0cmluZy50b1VURjhBcnJheSh2YWx1ZS52YWx1ZSk7XG4gIH1cblxuICBwcm9jZXNzX3V0ZjE2KHZhbHVlKSB7XG4gICAgcmV0dXJuIEJpdFN0cmluZy50b1VURjE2QXJyYXkodmFsdWUudmFsdWUpO1xuICB9XG5cbiAgcHJvY2Vzc191dGYzMih2YWx1ZSkge1xuICAgIHJldHVybiBCaXRTdHJpbmcudG9VVEYzMkFycmF5KHZhbHVlLnZhbHVlKTtcbiAgfVxuXG4gIHByb2Nlc3Nfc2lnbmVkKHZhbHVlKSB7XG4gICAgcmV0dXJuIG5ldyBVaW50OEFycmF5KFt2YWx1ZV0pWzBdO1xuICB9XG5cbiAgcHJvY2Vzc191bnNpZ25lZCh2YWx1ZSkge1xuICAgIHJldHVybiB2YWx1ZTtcbiAgfVxuXG4gIHByb2Nlc3NfbmF0aXZlKHZhbHVlKSB7XG4gICAgcmV0dXJuIHZhbHVlO1xuICB9XG5cbiAgcHJvY2Vzc19iaWcodmFsdWUpIHtcbiAgICByZXR1cm4gdmFsdWU7XG4gIH1cblxuICBwcm9jZXNzX2xpdHRsZSh2YWx1ZSkge1xuICAgIHJldHVybiB2YWx1ZS5yZXZlcnNlKCk7XG4gIH1cblxuICBwcm9jZXNzX3NpemUodmFsdWUpIHtcbiAgICByZXR1cm4gdmFsdWU7XG4gIH1cblxuICBwcm9jZXNzX3VuaXQodmFsdWUpIHtcbiAgICByZXR1cm4gdmFsdWU7XG4gIH1cblxuICBzdGF0aWMgaW50ZWdlcih2YWx1ZSkge1xuICAgIHJldHVybiBCaXRTdHJpbmcud3JhcCh2YWx1ZSwgeyBcInR5cGVcIjogXCJpbnRlZ2VyXCIsIFwidW5pdFwiOiAxLCBcInNpemVcIjogOCB9KTtcbiAgfVxuXG4gIHN0YXRpYyBmbG9hdCh2YWx1ZSkge1xuICAgIHJldHVybiBCaXRTdHJpbmcud3JhcCh2YWx1ZSwgeyBcInR5cGVcIjogXCJmbG9hdFwiLCBcInVuaXRcIjogMSwgXCJzaXplXCI6IDY0IH0pO1xuICB9XG5cbiAgc3RhdGljIGJpdHN0cmluZyh2YWx1ZSkge1xuICAgIHJldHVybiBCaXRTdHJpbmcud3JhcCh2YWx1ZSwgeyBcInR5cGVcIjogXCJiaXRzdHJpbmdcIiwgXCJ1bml0XCI6IDEsIFwic2l6ZVwiOiB2YWx1ZS5sZW5ndGggfSk7XG4gIH1cblxuICBzdGF0aWMgYml0cyh2YWx1ZSkge1xuICAgIHJldHVybiBCaXRTdHJpbmcuYml0c3RyaW5nKHZhbHVlKTtcbiAgfVxuXG4gIHN0YXRpYyBiaW5hcnkodmFsdWUpIHtcbiAgICByZXR1cm4gQml0U3RyaW5nLndyYXAodmFsdWUsIHsgXCJ0eXBlXCI6IFwiYmluYXJ5XCIsIFwidW5pdFwiOiA4LCBcInNpemVcIjogdmFsdWUubGVuZ3RoIH0pO1xuICB9XG5cbiAgc3RhdGljIGJ5dGVzKHZhbHVlKSB7XG4gICAgcmV0dXJuIEJpdFN0cmluZy5iaW5hcnkodmFsdWUpO1xuICB9XG5cbiAgc3RhdGljIHV0ZjgodmFsdWUpIHtcbiAgICByZXR1cm4gQml0U3RyaW5nLndyYXAodmFsdWUsIHsgXCJ0eXBlXCI6IFwidXRmOFwiIH0pO1xuICB9XG5cbiAgc3RhdGljIHV0ZjE2KHZhbHVlKSB7XG4gICAgcmV0dXJuIEJpdFN0cmluZy53cmFwKHZhbHVlLCB7IFwidHlwZVwiOiBcInV0ZjE2XCIgfSk7XG4gIH1cblxuICBzdGF0aWMgdXRmMzIodmFsdWUpIHtcbiAgICByZXR1cm4gQml0U3RyaW5nLndyYXAodmFsdWUsIHsgXCJ0eXBlXCI6IFwidXRmMzJcIiB9KTtcbiAgfVxuXG4gIHN0YXRpYyBzaWduZWQodmFsdWUpIHtcbiAgICByZXR1cm4gQml0U3RyaW5nLndyYXAodmFsdWUsIHt9LCBcInNpZ25lZFwiKTtcbiAgfVxuXG4gIHN0YXRpYyB1bnNpZ25lZCh2YWx1ZSkge1xuICAgIHJldHVybiBCaXRTdHJpbmcud3JhcCh2YWx1ZSwge30sIFwidW5zaWduZWRcIik7XG4gIH1cblxuICBzdGF0aWMgbmF0aXZlKHZhbHVlKSB7XG4gICAgcmV0dXJuIEJpdFN0cmluZy53cmFwKHZhbHVlLCB7fSwgXCJuYXRpdmVcIik7XG4gIH1cblxuICBzdGF0aWMgYmlnKHZhbHVlKSB7XG4gICAgcmV0dXJuIEJpdFN0cmluZy53cmFwKHZhbHVlLCB7fSwgXCJiaWdcIik7XG4gIH1cblxuICBzdGF0aWMgbGl0dGxlKHZhbHVlKSB7XG4gICAgcmV0dXJuIEJpdFN0cmluZy53cmFwKHZhbHVlLCB7fSwgXCJsaXR0bGVcIik7XG4gIH1cblxuICBzdGF0aWMgc2l6ZSh2YWx1ZSwgY291bnQpIHtcbiAgICByZXR1cm4gQml0U3RyaW5nLndyYXAodmFsdWUsIHsgXCJzaXplXCI6IGNvdW50IH0pO1xuICB9XG5cbiAgc3RhdGljIHVuaXQodmFsdWUsIGNvdW50KSB7XG4gICAgcmV0dXJuIEJpdFN0cmluZy53cmFwKHZhbHVlLCB7IFwidW5pdFwiOiBjb3VudCB9KTtcbiAgfVxuXG4gIHN0YXRpYyB3cmFwKHZhbHVlLCBvcHQsIG5ld19hdHRyaWJ1dGUgPSBudWxsKSB7XG4gICAgbGV0IHRoZV92YWx1ZSA9IHZhbHVlO1xuXG4gICAgaWYgKCEodmFsdWUgaW5zdGFuY2VvZiBPYmplY3QpKSB7XG4gICAgICB0aGVfdmFsdWUgPSB7IFwidmFsdWVcIjogdmFsdWUsIFwiYXR0cmlidXRlc1wiOiBbXSB9O1xuICAgIH1cblxuICAgIHRoZV92YWx1ZSA9IE9iamVjdC5hc3NpZ24odGhlX3ZhbHVlLCBvcHQpO1xuXG4gICAgaWYgKG5ld19hdHRyaWJ1dGUpIHtcbiAgICAgIHRoZV92YWx1ZS5hdHRyaWJ1dGVzLnB1c2gobmV3X2F0dHJpYnV0ZSk7XG4gICAgfVxuXG4gICAgcmV0dXJuIHRoZV92YWx1ZTtcbiAgfVxuXG4gIHN0YXRpYyB0b1VURjhBcnJheShzdHIpIHtcbiAgICB2YXIgdXRmOCA9IFtdO1xuICAgIGZvciAodmFyIGkgPSAwOyBpIDwgc3RyLmxlbmd0aDsgaSsrKSB7XG4gICAgICB2YXIgY2hhcmNvZGUgPSBzdHIuY2hhckNvZGVBdChpKTtcbiAgICAgIGlmIChjaGFyY29kZSA8IDEyOCkge1xuICAgICAgICB1dGY4LnB1c2goY2hhcmNvZGUpO1xuICAgICAgfSBlbHNlIGlmIChjaGFyY29kZSA8IDIwNDgpIHtcbiAgICAgICAgdXRmOC5wdXNoKDE5MiB8IGNoYXJjb2RlID4+IDYsIDEyOCB8IGNoYXJjb2RlICYgNjMpO1xuICAgICAgfSBlbHNlIGlmIChjaGFyY29kZSA8IDU1Mjk2IHx8IGNoYXJjb2RlID49IDU3MzQ0KSB7XG4gICAgICAgIHV0ZjgucHVzaCgyMjQgfCBjaGFyY29kZSA+PiAxMiwgMTI4IHwgY2hhcmNvZGUgPj4gNiAmIDYzLCAxMjggfCBjaGFyY29kZSAmIDYzKTtcbiAgICAgIH1cbiAgICAgIC8vIHN1cnJvZ2F0ZSBwYWlyXG4gICAgICBlbHNlIHtcbiAgICAgICAgaSsrO1xuICAgICAgICAvLyBVVEYtMTYgZW5jb2RlcyAweDEwMDAwLTB4MTBGRkZGIGJ5XG4gICAgICAgIC8vIHN1YnRyYWN0aW5nIDB4MTAwMDAgYW5kIHNwbGl0dGluZyB0aGVcbiAgICAgICAgLy8gMjAgYml0cyBvZiAweDAtMHhGRkZGRiBpbnRvIHR3byBoYWx2ZXNcbiAgICAgICAgY2hhcmNvZGUgPSA2NTUzNiArICgoY2hhcmNvZGUgJiAxMDIzKSA8PCAxMCB8IHN0ci5jaGFyQ29kZUF0KGkpICYgMTAyMyk7XG4gICAgICAgIHV0ZjgucHVzaCgyNDAgfCBjaGFyY29kZSA+PiAxOCwgMTI4IHwgY2hhcmNvZGUgPj4gMTIgJiA2MywgMTI4IHwgY2hhcmNvZGUgPj4gNiAmIDYzLCAxMjggfCBjaGFyY29kZSAmIDYzKTtcbiAgICAgIH1cbiAgICB9XG4gICAgcmV0dXJuIHV0Zjg7XG4gIH1cblxuICBzdGF0aWMgdG9VVEYxNkFycmF5KHN0cikge1xuICAgIHZhciB1dGYxNiA9IFtdO1xuICAgIGZvciAodmFyIGkgPSAwOyBpIDwgc3RyLmxlbmd0aDsgaSsrKSB7XG4gICAgICB2YXIgY29kZVBvaW50ID0gc3RyLmNvZGVQb2ludEF0KGkpO1xuXG4gICAgICBpZiAoY29kZVBvaW50IDw9IDI1NSkge1xuICAgICAgICB1dGYxNi5wdXNoKDApO1xuICAgICAgICB1dGYxNi5wdXNoKGNvZGVQb2ludCk7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICB1dGYxNi5wdXNoKGNvZGVQb2ludCA+PiA4ICYgMjU1KTtcbiAgICAgICAgdXRmMTYucHVzaChjb2RlUG9pbnQgJiAyNTUpO1xuICAgICAgfVxuICAgIH1cbiAgICByZXR1cm4gdXRmMTY7XG4gIH1cblxuICBzdGF0aWMgdG9VVEYzMkFycmF5KHN0cikge1xuICAgIHZhciB1dGYzMiA9IFtdO1xuICAgIGZvciAodmFyIGkgPSAwOyBpIDwgc3RyLmxlbmd0aDsgaSsrKSB7XG4gICAgICB2YXIgY29kZVBvaW50ID0gc3RyLmNvZGVQb2ludEF0KGkpO1xuXG4gICAgICBpZiAoY29kZVBvaW50IDw9IDI1NSkge1xuICAgICAgICB1dGYzMi5wdXNoKDApO1xuICAgICAgICB1dGYzMi5wdXNoKDApO1xuICAgICAgICB1dGYzMi5wdXNoKDApO1xuICAgICAgICB1dGYzMi5wdXNoKGNvZGVQb2ludCk7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICB1dGYzMi5wdXNoKDApO1xuICAgICAgICB1dGYzMi5wdXNoKDApO1xuICAgICAgICB1dGYzMi5wdXNoKGNvZGVQb2ludCA+PiA4ICYgMjU1KTtcbiAgICAgICAgdXRmMzIucHVzaChjb2RlUG9pbnQgJiAyNTUpO1xuICAgICAgfVxuICAgIH1cbiAgICByZXR1cm4gdXRmMzI7XG4gIH1cblxuICAvL2h0dHA6Ly9zdGFja292ZXJmbG93LmNvbS9xdWVzdGlvbnMvMjAwMzQ5My9qYXZhc2NyaXB0LWZsb2F0LWZyb20tdG8tYml0c1xuICBzdGF0aWMgZmxvYXQzMlRvQnl0ZXMoZikge1xuICAgIHZhciBieXRlcyA9IFtdO1xuXG4gICAgdmFyIGJ1ZiA9IG5ldyBBcnJheUJ1ZmZlcig0KTtcbiAgICBuZXcgRmxvYXQzMkFycmF5KGJ1ZilbMF0gPSBmO1xuXG4gICAgbGV0IGludFZlcnNpb24gPSBuZXcgVWludDMyQXJyYXkoYnVmKVswXTtcblxuICAgIGJ5dGVzLnB1c2goaW50VmVyc2lvbiA+PiAyNCAmIDI1NSk7XG4gICAgYnl0ZXMucHVzaChpbnRWZXJzaW9uID4+IDE2ICYgMjU1KTtcbiAgICBieXRlcy5wdXNoKGludFZlcnNpb24gPj4gOCAmIDI1NSk7XG4gICAgYnl0ZXMucHVzaChpbnRWZXJzaW9uICYgMjU1KTtcblxuICAgIHJldHVybiBieXRlcztcbiAgfVxuXG4gIHN0YXRpYyBmbG9hdDY0VG9CeXRlcyhmKSB7XG4gICAgdmFyIGJ5dGVzID0gW107XG5cbiAgICB2YXIgYnVmID0gbmV3IEFycmF5QnVmZmVyKDgpO1xuICAgIG5ldyBGbG9hdDY0QXJyYXkoYnVmKVswXSA9IGY7XG5cbiAgICB2YXIgaW50VmVyc2lvbjEgPSBuZXcgVWludDMyQXJyYXkoYnVmKVswXTtcbiAgICB2YXIgaW50VmVyc2lvbjIgPSBuZXcgVWludDMyQXJyYXkoYnVmKVsxXTtcblxuICAgIGJ5dGVzLnB1c2goaW50VmVyc2lvbjIgPj4gMjQgJiAyNTUpO1xuICAgIGJ5dGVzLnB1c2goaW50VmVyc2lvbjIgPj4gMTYgJiAyNTUpO1xuICAgIGJ5dGVzLnB1c2goaW50VmVyc2lvbjIgPj4gOCAmIDI1NSk7XG4gICAgYnl0ZXMucHVzaChpbnRWZXJzaW9uMiAmIDI1NSk7XG5cbiAgICBieXRlcy5wdXNoKGludFZlcnNpb24xID4+IDI0ICYgMjU1KTtcbiAgICBieXRlcy5wdXNoKGludFZlcnNpb24xID4+IDE2ICYgMjU1KTtcbiAgICBieXRlcy5wdXNoKGludFZlcnNpb24xID4+IDggJiAyNTUpO1xuICAgIGJ5dGVzLnB1c2goaW50VmVyc2lvbjEgJiAyNTUpO1xuXG4gICAgcmV0dXJuIGJ5dGVzO1xuICB9XG59XG5cbmxldCBTcGVjaWFsRm9ybXMgPSB7XG5cbiAgX19ESVJfXzogZnVuY3Rpb24gKCkge1xuICAgIGlmIChfX2Rpcm5hbWUpIHtcbiAgICAgIHJldHVybiBfX2Rpcm5hbWU7XG4gICAgfVxuXG4gICAgaWYgKGRvY3VtZW50LmN1cnJlbnRTY3JpcHQpIHtcbiAgICAgIHJldHVybiBkb2N1bWVudC5jdXJyZW50U2NyaXB0LnNyYztcbiAgICB9XG5cbiAgICByZXR1cm4gbnVsbDtcbiAgfSxcblxuICBhdG9tOiBmdW5jdGlvbiAoX3ZhbHVlKSB7XG4gICAgcmV0dXJuIFN5bWJvbC5mb3IoX3ZhbHVlKTtcbiAgfSxcblxuICBsaXN0OiBmdW5jdGlvbiAoLi4uYXJncykge1xuICAgIHJldHVybiBPYmplY3QuZnJlZXplKGFyZ3MpO1xuICB9LFxuXG4gIGJpdHN0cmluZzogZnVuY3Rpb24gKC4uLmFyZ3MpIHtcbiAgICByZXR1cm4gbmV3IEJpdFN0cmluZyguLi5hcmdzKTtcbiAgfSxcblxuICBib3VuZDogZnVuY3Rpb24gKF92YXIpIHtcbiAgICByZXR1cm4gUGF0dGVybnMuYm91bmQoX3Zhcik7XG4gIH0sXG5cbiAgX2Nhc2U6IGZ1bmN0aW9uIChjb25kaXRpb24sIGNsYXVzZXMpIHtcbiAgICByZXR1cm4gUGF0dGVybnMuZGVmbWF0Y2goLi4uY2xhdXNlcykoY29uZGl0aW9uKTtcbiAgfSxcblxuICBjb25kOiBmdW5jdGlvbiAoY2xhdXNlcykge1xuICAgIGZvciAobGV0IGNsYXVzZSBvZiBjbGF1c2VzKSB7XG4gICAgICBpZiAoY2xhdXNlWzBdKSB7XG4gICAgICAgIHJldHVybiBjbGF1c2VbMV0oKTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICB0aHJvdyBuZXcgRXJyb3IoKTtcbiAgfSxcblxuICBmbjogZnVuY3Rpb24gKGNsYXVzZXMpIHtcbiAgICByZXR1cm4gUGF0dGVybnMuZGVmbWF0Y2goY2xhdXNlcyk7XG4gIH0sXG5cbiAgbWFwOiBmdW5jdGlvbiAob2JqKSB7XG4gICAgcmV0dXJuIE9iamVjdC5mcmVlemUob2JqKTtcbiAgfSxcblxuICBtYXBfdXBkYXRlOiBmdW5jdGlvbiAobWFwLCB2YWx1ZXMpIHtcbiAgICByZXR1cm4gT2JqZWN0LmZyZWV6ZShPYmplY3QuYXNzaWduKE9iamVjdC5jcmVhdGUobWFwLmNvbnN0cnVjdG9yLnByb3RvdHlwZSksIG1hcCwgdmFsdWVzKSk7XG4gIH0sXG5cbiAgX2ZvcjogZnVuY3Rpb24gKGNvbGxlY3Rpb25zLCBmdW4sIGZpbHRlciA9ICgpID0+IHRydWUsIGludG8gPSBbXSwgcHJldmlvdXNWYWx1ZXMgPSBbXSkge1xuICAgIGxldCBwYXR0ZXJuID0gY29sbGVjdGlvbnNbMF1bMF07XG4gICAgbGV0IGNvbGxlY3Rpb24gPSBjb2xsZWN0aW9uc1swXVsxXTtcblxuICAgIGlmIChjb2xsZWN0aW9ucy5sZW5ndGggPT09IDEpIHtcblxuICAgICAgZm9yIChsZXQgZWxlbSBvZiBjb2xsZWN0aW9uKSB7XG4gICAgICAgIGxldCByID0gUGF0dGVybnMubWF0Y2hfbm9fdGhyb3cocGF0dGVybiwgZWxlbSk7XG4gICAgICAgIGxldCBhcmdzID0gcHJldmlvdXNWYWx1ZXMuY29uY2F0KHIpO1xuXG4gICAgICAgIGlmIChyICYmIGZpbHRlci5hcHBseSh0aGlzLCBhcmdzKSkge1xuICAgICAgICAgIGludG8gPSBFbnVtLmludG8oW2Z1bi5hcHBseSh0aGlzLCBhcmdzKV0sIGludG8pO1xuICAgICAgICB9XG4gICAgICB9XG5cbiAgICAgIHJldHVybiBpbnRvO1xuICAgIH0gZWxzZSB7XG4gICAgICBsZXQgX2ludG8gPSBbXTtcblxuICAgICAgZm9yIChsZXQgZWxlbSBvZiBjb2xsZWN0aW9uKSB7XG4gICAgICAgIGxldCByID0gUGF0dGVybnMubWF0Y2hfbm9fdGhyb3cocGF0dGVybiwgZWxlbSk7XG4gICAgICAgIGlmIChyKSB7XG4gICAgICAgICAgX2ludG8gPSBFbnVtLmludG8odGhpcy5fZm9yKGNvbGxlY3Rpb25zLnNsaWNlKDEpLCBmdW4sIGZpbHRlciwgX2ludG8sIHByZXZpb3VzVmFsdWVzLmNvbmNhdChyKSksIGludG8pO1xuICAgICAgICB9XG4gICAgICB9XG5cbiAgICAgIHJldHVybiBfaW50bztcbiAgICB9XG4gIH0sXG5cbiAgcmVjZWl2ZTogZnVuY3Rpb24gKHJlY2VpdmVfZnVuLCB0aW1lb3V0X2luX21zID0gbnVsbCwgdGltZW91dF9mbiA9IHRpbWUgPT4gdHJ1ZSkge1xuICAgIGlmICh0aW1lb3V0X2luX21zID09IG51bGwgfHwgdGltZW91dF9pbl9tcyA9PT0gU3lzdGVtLmZvcignaW5maW5pdHknKSkge1xuICAgICAgd2hpbGUgKHRydWUpIHtcbiAgICAgICAgaWYgKHNlbGYubWFpbGJveC5sZW5ndGggIT09IDApIHtcbiAgICAgICAgICBsZXQgbWVzc2FnZSA9IHNlbGYubWFpbGJveFswXTtcbiAgICAgICAgICBzZWxmLm1haWxib3ggPSBzZWxmLm1haWxib3guc2xpY2UoMSk7XG4gICAgICAgICAgcmV0dXJuIHJlY2VpdmVfZnVuKG1lc3NhZ2UpO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgfSBlbHNlIGlmICh0aW1lb3V0X2luX21zID09PSAwKSB7XG4gICAgICBpZiAoc2VsZi5tYWlsYm94Lmxlbmd0aCAhPT0gMCkge1xuICAgICAgICBsZXQgbWVzc2FnZSA9IHNlbGYubWFpbGJveFswXTtcbiAgICAgICAgc2VsZi5tYWlsYm94ID0gc2VsZi5tYWlsYm94LnNsaWNlKDEpO1xuICAgICAgICByZXR1cm4gcmVjZWl2ZV9mdW4obWVzc2FnZSk7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICByZXR1cm4gbnVsbDtcbiAgICAgIH1cbiAgICB9IGVsc2Uge1xuICAgICAgbGV0IG5vdyA9IERhdGUubm93KCk7XG4gICAgICB3aGlsZSAoRGF0ZS5ub3coKSA8IG5vdyArIHRpbWVvdXRfaW5fbXMpIHtcbiAgICAgICAgaWYgKHNlbGYubWFpbGJveC5sZW5ndGggIT09IDApIHtcbiAgICAgICAgICBsZXQgbWVzc2FnZSA9IHNlbGYubWFpbGJveFswXTtcbiAgICAgICAgICBzZWxmLm1haWxib3ggPSBzZWxmLm1haWxib3guc2xpY2UoMSk7XG4gICAgICAgICAgcmV0dXJuIHJlY2VpdmVfZnVuKG1lc3NhZ2UpO1xuICAgICAgICB9XG4gICAgICB9XG5cbiAgICAgIHJldHVybiB0aW1lb3V0X2ZuKHRpbWVvdXRfaW5fbXMpO1xuICAgIH1cbiAgfSxcblxuICB0dXBsZTogZnVuY3Rpb24gKC4uLmFyZ3MpIHtcbiAgICByZXR1cm4gbmV3IFR1cGxlKC4uLmFyZ3MpO1xuICB9LFxuXG4gIF90cnk6IGZ1bmN0aW9uIChkb19mdW4sIHJlc2N1ZV9mdW5jdGlvbiwgY2F0Y2hfZnVuLCBlbHNlX2Z1bmN0aW9uLCBhZnRlcl9mdW5jdGlvbikge1xuICAgIGxldCByZXN1bHQgPSBudWxsO1xuXG4gICAgdHJ5IHtcbiAgICAgIHJlc3VsdCA9IGRvX2Z1bigpO1xuICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgIGxldCBleF9yZXN1bHQgPSBudWxsO1xuXG4gICAgICBpZiAocmVzY3VlX2Z1bmN0aW9uKSB7XG4gICAgICAgIHRyeSB7XG4gICAgICAgICAgZXhfcmVzdWx0ID0gcmVzY3VlX2Z1bmN0aW9uKGUpO1xuICAgICAgICAgIHJldHVybiBleF9yZXN1bHQ7XG4gICAgICAgIH0gY2F0Y2ggKGV4KSB7XG4gICAgICAgICAgaWYgKGV4IGluc3RhbmNlb2YgUGF0dGVybnMuTWF0Y2hFcnJvcikge1xuICAgICAgICAgICAgdGhyb3cgZXg7XG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICB9XG5cbiAgICAgIGlmIChjYXRjaF9mdW4pIHtcbiAgICAgICAgdHJ5IHtcbiAgICAgICAgICBleF9yZXN1bHQgPSBjYXRjaF9mdW4oZSk7XG4gICAgICAgICAgcmV0dXJuIGV4X3Jlc3VsdDtcbiAgICAgICAgfSBjYXRjaCAoZXgpIHtcbiAgICAgICAgICBpZiAoZXggaW5zdGFuY2VvZiBQYXR0ZXJucy5NYXRjaEVycm9yKSB7XG4gICAgICAgICAgICB0aHJvdyBleDtcbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgIH1cblxuICAgICAgdGhyb3cgZTtcbiAgICB9IGZpbmFsbHkge1xuICAgICAgaWYgKGFmdGVyX2Z1bmN0aW9uKSB7XG4gICAgICAgIGFmdGVyX2Z1bmN0aW9uKCk7XG4gICAgICB9XG4gICAgfVxuXG4gICAgaWYgKGVsc2VfZnVuY3Rpb24pIHtcbiAgICAgIHRyeSB7XG4gICAgICAgIHJldHVybiBlbHNlX2Z1bmN0aW9uKHJlc3VsdCk7XG4gICAgICB9IGNhdGNoIChleCkge1xuICAgICAgICBpZiAoZXggaW5zdGFuY2VvZiBQYXR0ZXJucy5NYXRjaEVycm9yKSB7XG4gICAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdObyBNYXRjaCBGb3VuZCBpbiBFbHNlJyk7XG4gICAgICAgIH1cblxuICAgICAgICB0aHJvdyBleDtcbiAgICAgIH1cbiAgICB9IGVsc2Uge1xuICAgICAgcmV0dXJuIHJlc3VsdDtcbiAgICB9XG4gIH1cblxufTtcblxuLyogQGZsb3cgKi9cblxubGV0IHByb2Nlc3NfY291bnRlciA9IC0xO1xuXG5jbGFzcyBQSUQge1xuICBjb25zdHJ1Y3RvcigpIHtcbiAgICBwcm9jZXNzX2NvdW50ZXIgPSBwcm9jZXNzX2NvdW50ZXIgKyAxO1xuICAgIHRoaXMuaWQgPSBwcm9jZXNzX2NvdW50ZXI7XG4gIH1cblxuICB0b1N0cmluZygpIHtcbiAgICByZXR1cm4gXCJQSUQjPDAuXCIgKyB0aGlzLmlkICsgXCIuMD5cIjtcbiAgfVxufVxuXG5jbGFzcyBJbnRlZ2VyVHlwZSB7fVxuY2xhc3MgRmxvYXRUeXBlIHt9XG5cbi8vaHR0cHM6Ly9naXRodWIuY29tL2FpcnBvcnR5aC9wcm90b21vcnBoaXNtXG5jbGFzcyBQcm90b2NvbCB7XG4gIGNvbnN0cnVjdG9yKHNwZWMpIHtcbiAgICB0aGlzLnJlZ2lzdHJ5ID0gbmV3IE1hcCgpO1xuICAgIHRoaXMuZmFsbGJhY2sgPSBudWxsO1xuXG4gICAgZm9yIChsZXQgZnVuTmFtZSBpbiBzcGVjKSB7XG4gICAgICB0aGlzW2Z1bk5hbWVdID0gY3JlYXRlRnVuKGZ1bk5hbWUpLmJpbmQodGhpcyk7XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gY3JlYXRlRnVuKGZ1bk5hbWUpIHtcblxuICAgICAgcmV0dXJuIGZ1bmN0aW9uICguLi5hcmdzKSB7XG4gICAgICAgIGxldCB0aGluZyA9IGFyZ3NbMF07XG4gICAgICAgIGxldCBmdW4gPSBudWxsO1xuXG4gICAgICAgIGlmIChOdW1iZXIuaXNJbnRlZ2VyKHRoaW5nKSAmJiB0aGlzLmhhc0ltcGxlbWVudGF0aW9uKEludGVnZXJUeXBlKSkge1xuICAgICAgICAgIGZ1biA9IHRoaXMucmVnaXN0cnkuZ2V0KEludGVnZXJUeXBlKVtmdW5OYW1lXTtcbiAgICAgICAgfSBlbHNlIGlmICh0eXBlb2YgdGhpbmcgPT09IFwibnVtYmVyXCIgJiYgIU51bWJlci5pc0ludGVnZXIodGhpbmcpICYmIHRoaXMuaGFzSW1wbGVtZW50YXRpb24oRmxvYXRUeXBlKSkge1xuICAgICAgICAgIGZ1biA9IHRoaXMucmVnaXN0cnkuZ2V0KEZsb2F0VHlwZSlbZnVuTmFtZV07XG4gICAgICAgIH0gZWxzZSBpZiAodGhpcy5oYXNJbXBsZW1lbnRhdGlvbih0aGluZykpIHtcbiAgICAgICAgICBmdW4gPSB0aGlzLnJlZ2lzdHJ5LmdldCh0aGluZy5jb25zdHJ1Y3RvcilbZnVuTmFtZV07XG4gICAgICAgIH0gZWxzZSBpZiAodGhpcy5mYWxsYmFjaykge1xuICAgICAgICAgIGZ1biA9IHRoaXMuZmFsbGJhY2tbZnVuTmFtZV07XG4gICAgICAgIH1cblxuICAgICAgICBpZiAoZnVuICE9IG51bGwpIHtcbiAgICAgICAgICBsZXQgcmV0dmFsID0gZnVuLmFwcGx5KHRoaXMsIGFyZ3MpO1xuICAgICAgICAgIHJldHVybiByZXR2YWw7XG4gICAgICAgIH1cblxuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoXCJObyBpbXBsZW1lbnRhdGlvbiBmb3VuZCBmb3IgXCIgKyB0aGluZyk7XG4gICAgICB9O1xuICAgIH1cbiAgfVxuXG4gIGltcGxlbWVudGF0aW9uKHR5cGUsIGltcGxlbWVudGF0aW9uKSB7XG4gICAgaWYgKHR5cGUgPT09IG51bGwpIHtcbiAgICAgIHRoaXMuZmFsbGJhY2sgPSBpbXBsZW1lbnRhdGlvbjtcbiAgICB9IGVsc2Uge1xuICAgICAgdGhpcy5yZWdpc3RyeS5zZXQodHlwZSwgaW1wbGVtZW50YXRpb24pO1xuICAgIH1cbiAgfVxuXG4gIGhhc0ltcGxlbWVudGF0aW9uKHRoaW5nKSB7XG4gICAgcmV0dXJuIHRoaXMucmVnaXN0cnkuaGFzKHRoaW5nLmNvbnN0cnVjdG9yKTtcbiAgfVxufVxuXG5mdW5jdGlvbiB0bChsaXN0KSB7XG4gIHJldHVybiBTcGVjaWFsRm9ybXMubGlzdCguLi5saXN0LnNsaWNlKDEpKTtcbn1cblxuZnVuY3Rpb24gaGQobGlzdCkge1xuICByZXR1cm4gbGlzdFswXTtcbn1cblxuZnVuY3Rpb24gaXNfbmlsKHgpIHtcbiAgcmV0dXJuIHggPT09IG51bGw7XG59XG5cbmZ1bmN0aW9uIGlzX2F0b20oeCkge1xuICByZXR1cm4gdHlwZW9mIHggPT09ICdzeW1ib2wnO1xufVxuXG5mdW5jdGlvbiBpc19iaW5hcnkoeCkge1xuICByZXR1cm4gdHlwZW9mIHggPT09ICdzdHJpbmcnIHx8IHggaW5zdGFuY2VvZiBTdHJpbmc7XG59XG5cbmZ1bmN0aW9uIGlzX2Jvb2xlYW4oeCkge1xuICByZXR1cm4gdHlwZW9mIHggPT09ICdib29sZWFuJyB8fCB4IGluc3RhbmNlb2YgQm9vbGVhbjtcbn1cblxuZnVuY3Rpb24gaXNfZnVuY3Rpb24oeCwgYXJpdHkgPSAtMSkge1xuICByZXR1cm4gdHlwZW9mIHggPT09ICdmdW5jdGlvbicgfHwgeCBpbnN0YW5jZW9mIEZ1bmN0aW9uO1xufVxuXG5mdW5jdGlvbiBpc19mbG9hdCh4KSB7XG4gIHJldHVybiBpc19udW1iZXIoeCkgJiYgIU51bWJlci5pc0ludGVnZXIoeCk7XG59XG5cbmZ1bmN0aW9uIGlzX2ludGVnZXIoeCkge1xuICByZXR1cm4gTnVtYmVyLmlzSW50ZWdlcih4KTtcbn1cblxuZnVuY3Rpb24gaXNfbGlzdCh4KSB7XG4gIHJldHVybiB4IGluc3RhbmNlb2YgQXJyYXk7XG59XG5cbmZ1bmN0aW9uIGlzX21hcCh4KSB7XG4gIHJldHVybiB0eXBlb2YgeCA9PT0gJ29iamVjdCcgfHwgeCBpbnN0YW5jZW9mIE9iamVjdDtcbn1cblxuZnVuY3Rpb24gaXNfbnVtYmVyKHgpIHtcbiAgcmV0dXJuIHR5cGVvZiB4ID09PSAnbnVtYmVyJztcbn1cblxuZnVuY3Rpb24gaXNfdHVwbGUoeCkge1xuICByZXR1cm4geCBpbnN0YW5jZW9mIFR1cGxlO1xufVxuXG5mdW5jdGlvbiBfbGVuZ3RoKHgpIHtcbiAgcmV0dXJuIHgubGVuZ3RoO1xufVxuXG5mdW5jdGlvbiBpc19waWQoeCkge1xuICByZXR1cm4geCBpbnN0YW5jZW9mIFBJRDtcbn1cblxuZnVuY3Rpb24gaXNfcG9ydCh4KSB7XG4gIHJldHVybiBmYWxzZTtcbn1cblxuZnVuY3Rpb24gaXNfcmVmZXJlbmNlKHgpIHtcbiAgcmV0dXJuIGZhbHNlO1xufVxuXG5mdW5jdGlvbiBpc19iaXRzdHJpbmcoeCkge1xuICByZXR1cm4gaXNfYmluYXJ5KHgpIHx8IHggaW5zdGFuY2VvZiBCaXRTdHJpbmc7XG59XG5cbmZ1bmN0aW9uIF9faW5fXyhsZWZ0LCByaWdodCkge1xuICBmb3IgKGxldCB4IG9mIHJpZ2h0KSB7XG4gICAgaWYgKG1hdGNoX19xbWFya19fKGxlZnQsIHgpKSB7XG4gICAgICByZXR1cm4gdHJ1ZTtcbiAgICB9XG4gIH1cblxuICByZXR1cm4gZmFsc2U7XG59XG5cbmZ1bmN0aW9uIGFicyhudW1iZXIpIHtcbiAgcmV0dXJuIE1hdGguYWJzKG51bWJlcik7XG59XG5cbmZ1bmN0aW9uIHJvdW5kKG51bWJlcikge1xuICByZXR1cm4gTWF0aC5yb3VuZChudW1iZXIpO1xufVxuXG5mdW5jdGlvbiBlbGVtKHR1cGxlLCBpbmRleCkge1xuICBpZiAoaXNfbGlzdCh0dXBsZSkpIHtcbiAgICByZXR1cm4gdHVwbGVbaW5kZXhdO1xuICB9XG5cbiAgcmV0dXJuIHR1cGxlLmdldChpbmRleCk7XG59XG5cbmZ1bmN0aW9uIHJlbShsZWZ0LCByaWdodCkge1xuICByZXR1cm4gbGVmdCAlIHJpZ2h0O1xufVxuXG5mdW5jdGlvbiBkaXYobGVmdCwgcmlnaHQpIHtcbiAgcmV0dXJuIGxlZnQgLyByaWdodDtcbn1cblxuZnVuY3Rpb24gYW5kKGxlZnQsIHJpZ2h0KSB7XG4gIHJldHVybiBsZWZ0ICYmIHJpZ2h0O1xufVxuXG5mdW5jdGlvbiBvcihsZWZ0LCByaWdodCkge1xuICByZXR1cm4gbGVmdCB8fCByaWdodDtcbn1cblxuZnVuY3Rpb24gbm90KGFyZykge1xuICByZXR1cm4gIWFyZztcbn1cblxuZnVuY3Rpb24gYXBwbHkoLi4uYXJncykge1xuICBpZiAoYXJncy5sZW5ndGggPT09IDMpIHtcbiAgICBsZXQgbW9kID0gYXJnc1swXTtcbiAgICBsZXQgZnVuYyA9IGFyZ3NbMV07XG4gICAgbGV0IGZ1bmNfYXJncyA9IGFyZ3NbMl07XG4gICAgcmV0dXJuIG1vZFtmdW5jXS5hcHBseShudWxsLCBmdW5jX2FyZ3MpO1xuICB9IGVsc2Uge1xuICAgIGxldCBmdW5jID0gYXJnc1swXTtcbiAgICBsZXQgZnVuY19hcmdzID0gYXJnc1sxXTtcblxuICAgIHJldHVybiBmdW5jLmFwcGx5KG51bGwsIGZ1bmNfYXJncyk7XG4gIH1cbn1cblxuZnVuY3Rpb24gdG9fc3RyaW5nKGFyZykge1xuICBpZiAoaXNfdHVwbGUoYXJnKSkge1xuICAgIHJldHVybiBUdXBsZS50b19zdHJpbmcoYXJnKTtcbiAgfVxuXG4gIHJldHVybiBhcmcudG9TdHJpbmcoKTtcbn1cblxuZnVuY3Rpb24gbWF0Y2hfX3FtYXJrX18ocGF0dGVybiwgZXhwciwgZ3VhcmQgPSAoKSA9PiB0cnVlKSB7XG4gIHJldHVybiBfUGF0dGVybnMubWF0Y2hfbm9fdGhyb3cocGF0dGVybiwgZXhwciwgZ3VhcmQpICE9IG51bGw7XG59XG5cbmZ1bmN0aW9uIGRlZnN0cnVjdChkZWZhdWx0cykge1xuICByZXR1cm4gY2xhc3Mge1xuICAgIGNvbnN0cnVjdG9yKHVwZGF0ZSA9IHt9KSB7XG4gICAgICBsZXQgdGhlX3ZhbHVlcyA9IE9iamVjdC5hc3NpZ24oZGVmYXVsdHMsIHVwZGF0ZSk7XG4gICAgICBPYmplY3QuYXNzaWduKHRoaXMsIHRoZV92YWx1ZXMpO1xuICAgIH1cblxuICAgIHN0YXRpYyBjcmVhdGUodXBkYXRlcyA9IHt9KSB7XG4gICAgICBsZXQgeCA9IG5ldyB0aGlzKHVwZGF0ZXMpO1xuICAgICAgcmV0dXJuIE9iamVjdC5mcmVlemUoeCk7XG4gICAgfVxuICB9O1xufVxuXG5mdW5jdGlvbiBkZWZleGNlcHRpb24oZGVmYXVsdHMpIHtcbiAgcmV0dXJuIGNsYXNzIGV4dGVuZHMgRXJyb3Ige1xuICAgIGNvbnN0cnVjdG9yKHVwZGF0ZSA9IHt9KSB7XG4gICAgICBsZXQgbWVzc2FnZSA9IHVwZGF0ZS5tZXNzYWdlIHx8ICcnO1xuICAgICAgc3VwZXIobWVzc2FnZSk7XG5cbiAgICAgIGxldCB0aGVfdmFsdWVzID0gT2JqZWN0LmFzc2lnbihkZWZhdWx0cywgdXBkYXRlKTtcbiAgICAgIE9iamVjdC5hc3NpZ24odGhpcywgdGhlX3ZhbHVlcyk7XG5cbiAgICAgIHRoaXMubmFtZSA9IHRoaXMuY29uc3RydWN0b3IubmFtZTtcbiAgICAgIHRoaXMubWVzc2FnZSA9IG1lc3NhZ2U7XG4gICAgICB0aGlzW1NwZWNpYWxGb3Jtcy5hdG9tKCdfX2V4Y2VwdGlvbl9fJyldID0gdHJ1ZTtcbiAgICAgIEVycm9yLmNhcHR1cmVTdGFja1RyYWNlKHRoaXMsIHRoaXMuY29uc3RydWN0b3IubmFtZSk7XG4gICAgfVxuXG4gICAgc3RhdGljIGNyZWF0ZSh1cGRhdGVzID0ge30pIHtcbiAgICAgIGxldCB4ID0gbmV3IHRoaXModXBkYXRlcyk7XG4gICAgICByZXR1cm4gT2JqZWN0LmZyZWV6ZSh4KTtcbiAgICB9XG4gIH07XG59XG5cbmZ1bmN0aW9uIGRlZnByb3RvY29sKHNwZWMpIHtcbiAgcmV0dXJuIG5ldyBQcm90b2NvbChzcGVjKTtcbn1cblxuZnVuY3Rpb24gZGVmaW1wbChwcm90b2NvbCwgdHlwZSwgaW1wbCkge1xuICBwcm90b2NvbC5pbXBsZW1lbnRhdGlvbih0eXBlLCBpbXBsKTtcbn1cblxudmFyIEtlcm5lbCA9IHtcbiAgU3BlY2lhbEZvcm1zLFxuICB0bCxcbiAgaGQsXG4gIGlzX25pbCxcbiAgaXNfYXRvbSxcbiAgaXNfYmluYXJ5LFxuICBpc19ib29sZWFuLFxuICBpc19mdW5jdGlvbixcbiAgaXNfZmxvYXQsXG4gIGlzX2ludGVnZXIsXG4gIGlzX2xpc3QsXG4gIGlzX21hcCxcbiAgaXNfbnVtYmVyLFxuICBpc190dXBsZSxcbiAgbGVuZ3RoOiBfbGVuZ3RoLFxuICBpc19waWQsXG4gIGlzX3BvcnQsXG4gIGlzX3JlZmVyZW5jZSxcbiAgaXNfYml0c3RyaW5nLFxuICBpbjogX19pbl9fLFxuICBhYnMsXG4gIHJvdW5kLFxuICBlbGVtLFxuICByZW0sXG4gIGRpdixcbiAgYW5kLFxuICBvcixcbiAgbm90LFxuICBhcHBseSxcbiAgdG9fc3RyaW5nLFxuICBtYXRjaF9fcW1hcmtfXyxcbiAgZGVmc3RydWN0LFxuICBkZWZwcm90b2NvbCxcbiAgZGVmaW1wbFxufTtcblxubGV0IEVudW0gPSB7XG5cbiAgYWxsX19xbWFya19fOiBmdW5jdGlvbiAoY29sbGVjdGlvbiwgZnVuID0geCA9PiB4KSB7XG4gICAgZm9yIChsZXQgZWxlbSBvZiBjb2xsZWN0aW9uKSB7XG4gICAgICBpZiAoIWZ1bihlbGVtKSkge1xuICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICB9XG4gICAgfVxuXG4gICAgcmV0dXJuIHRydWU7XG4gIH0sXG5cbiAgYW55X19xbWFya19fOiBmdW5jdGlvbiAoY29sbGVjdGlvbiwgZnVuID0geCA9PiB4KSB7XG4gICAgZm9yIChsZXQgZWxlbSBvZiBjb2xsZWN0aW9uKSB7XG4gICAgICBpZiAoZnVuKGVsZW0pKSB7XG4gICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgfVxuICAgIH1cblxuICAgIHJldHVybiBmYWxzZTtcbiAgfSxcblxuICBhdDogZnVuY3Rpb24gKGNvbGxlY3Rpb24sIG4sIHRoZV9kZWZhdWx0ID0gbnVsbCkge1xuICAgIGlmIChuID4gdGhpcy5jb3VudChjb2xsZWN0aW9uKSB8fCBuIDwgMCkge1xuICAgICAgcmV0dXJuIHRoZV9kZWZhdWx0O1xuICAgIH1cblxuICAgIHJldHVybiBjb2xsZWN0aW9uW25dO1xuICB9LFxuXG4gIGNvbmNhdDogZnVuY3Rpb24gKC4uLmVudW1hYmxlcykge1xuICAgIHJldHVybiBlbnVtYWJsZXNbMF0uY29uY2F0KGVudW1hYmxlc1sxXSk7XG4gIH0sXG5cbiAgY291bnQ6IGZ1bmN0aW9uIChjb2xsZWN0aW9uLCBmdW4gPSBudWxsKSB7XG4gICAgaWYgKGZ1biA9PSBudWxsKSB7XG4gICAgICByZXR1cm4gY29sbGVjdGlvbi5sZW5ndGg7XG4gICAgfSBlbHNlIHtcbiAgICAgIHJldHVybiBjb2xsZWN0aW9uLmZpbHRlcihmdW4pLmxlbmd0aDtcbiAgICB9XG4gIH0sXG5cbiAgZHJvcDogZnVuY3Rpb24gKGNvbGxlY3Rpb24sIGNvdW50KSB7XG4gICAgcmV0dXJuIGNvbGxlY3Rpb24uc2xpY2UoY291bnQpO1xuICB9LFxuXG4gIGRyb3Bfd2hpbGU6IGZ1bmN0aW9uIChjb2xsZWN0aW9uLCBmdW4pIHtcbiAgICBsZXQgY291bnQgPSAwO1xuXG4gICAgZm9yIChsZXQgZWxlbSBvZiBjb2xsZWN0aW9uKSB7XG4gICAgICBpZiAoZnVuKGVsZW0pKSB7XG4gICAgICAgIGNvdW50ID0gY291bnQgKyAxO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgYnJlYWs7XG4gICAgICB9XG4gICAgfVxuXG4gICAgcmV0dXJuIGNvbGxlY3Rpb24uc2xpY2UoY291bnQpO1xuICB9LFxuXG4gIGVhY2g6IGZ1bmN0aW9uIChjb2xsZWN0aW9uLCBmdW4pIHtcbiAgICBmb3IgKGxldCBlbGVtIG9mIGNvbGxlY3Rpb24pIHtcbiAgICAgIGZ1bihlbGVtKTtcbiAgICB9XG4gIH0sXG5cbiAgZW1wdHlfX3FtYXJrX186IGZ1bmN0aW9uIChjb2xsZWN0aW9uKSB7XG4gICAgcmV0dXJuIGNvbGxlY3Rpb24ubGVuZ3RoID09PSAwO1xuICB9LFxuXG4gIGZldGNoOiBmdW5jdGlvbiAoY29sbGVjdGlvbiwgbikge1xuICAgIGlmIChLZXJuZWwuaXNfbGlzdChjb2xsZWN0aW9uKSkge1xuICAgICAgaWYgKG4gPCB0aGlzLmNvdW50KGNvbGxlY3Rpb24pICYmIG4gPj0gMCkge1xuICAgICAgICByZXR1cm4gS2VybmVsLlNwZWNpYWxGb3Jtcy50dXBsZShLZXJuZWwuU3BlY2lhbEZvcm1zLmF0b20oXCJva1wiKSwgY29sbGVjdGlvbltuXSk7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICByZXR1cm4gS2VybmVsLlNwZWNpYWxGb3Jtcy5hdG9tKFwiZXJyb3JcIik7XG4gICAgICB9XG4gICAgfVxuXG4gICAgdGhyb3cgbmV3IEVycm9yKFwiY29sbGVjdGlvbiBpcyBub3QgYW4gRW51bWVyYWJsZVwiKTtcbiAgfSxcblxuICBmZXRjaF9fZW1hcmtfXzogZnVuY3Rpb24gKGNvbGxlY3Rpb24sIG4pIHtcbiAgICBpZiAoS2VybmVsLmlzX2xpc3QoY29sbGVjdGlvbikpIHtcbiAgICAgIGlmIChuIDwgdGhpcy5jb3VudChjb2xsZWN0aW9uKSAmJiBuID49IDApIHtcbiAgICAgICAgcmV0dXJuIGNvbGxlY3Rpb25bbl07XG4gICAgICB9IGVsc2Uge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoXCJvdXQgb2YgYm91bmRzIGVycm9yXCIpO1xuICAgICAgfVxuICAgIH1cblxuICAgIHRocm93IG5ldyBFcnJvcihcImNvbGxlY3Rpb24gaXMgbm90IGFuIEVudW1lcmFibGVcIik7XG4gIH0sXG5cbiAgZmlsdGVyOiBmdW5jdGlvbiAoY29sbGVjdGlvbiwgZnVuKSB7XG4gICAgbGV0IHJlc3VsdCA9IFtdO1xuXG4gICAgZm9yIChsZXQgZWxlbSBvZiBjb2xsZWN0aW9uKSB7XG4gICAgICBpZiAoZnVuKGVsZW0pKSB7XG4gICAgICAgIHJlc3VsdC5wdXNoKGVsZW0pO1xuICAgICAgfVxuICAgIH1cblxuICAgIHJldHVybiByZXN1bHQ7XG4gIH0sXG5cbiAgZmlsdGVyX21hcDogZnVuY3Rpb24gKGNvbGxlY3Rpb24sIGZpbHRlciwgbWFwcGVyKSB7XG4gICAgcmV0dXJuIEVudW0ubWFwKEVudW0uZmlsdGVyKGNvbGxlY3Rpb24sIGZpbHRlciksIG1hcHBlcik7XG4gIH0sXG5cbiAgZmluZDogZnVuY3Rpb24gKGNvbGxlY3Rpb24sIGlmX25vbmUgPSBudWxsLCBmdW4pIHtcbiAgICBmb3IgKGxldCBlbGVtIG9mIGNvbGxlY3Rpb24pIHtcbiAgICAgIGlmIChmdW4oZWxlbSkpIHtcbiAgICAgICAgcmV0dXJuIGVsZW07XG4gICAgICB9XG4gICAgfVxuXG4gICAgcmV0dXJuIGlmX25vbmU7XG4gIH0sXG5cbiAgaW50bzogZnVuY3Rpb24gKGNvbGxlY3Rpb24sIGxpc3QpIHtcbiAgICByZXR1cm4gbGlzdC5jb25jYXQoY29sbGVjdGlvbik7XG4gIH0sXG5cbiAgbWFwOiBmdW5jdGlvbiAoY29sbGVjdGlvbiwgZnVuKSB7XG4gICAgbGV0IHJlc3VsdCA9IFtdO1xuXG4gICAgZm9yIChsZXQgZWxlbSBvZiBjb2xsZWN0aW9uKSB7XG4gICAgICByZXN1bHQucHVzaChmdW4oZWxlbSkpO1xuICAgIH1cblxuICAgIHJldHVybiByZXN1bHQ7XG4gIH0sXG5cbiAgbWFwX3JlZHVjZTogZnVuY3Rpb24gKGNvbGxlY3Rpb24sIGFjYywgZnVuKSB7XG4gICAgbGV0IG1hcHBlZCA9IEtlcm5lbC5TcGVjaWFsRm9ybXMubGlzdCgpO1xuICAgIGxldCB0aGVfYWNjID0gYWNjO1xuXG4gICAgZm9yICh2YXIgaSA9IDA7IGkgPCB0aGlzLmNvdW50KGNvbGxlY3Rpb24pOyBpKyspIHtcbiAgICAgIGxldCB0dXBsZSA9IGZ1bihjb2xsZWN0aW9uW2ldLCB0aGVfYWNjKTtcblxuICAgICAgdGhlX2FjYyA9IEtlcm5lbC5lbGVtKHR1cGxlLCAxKTtcbiAgICAgIG1hcHBlZCA9IEtlcm5lbC5TcGVjaWFsRm9ybXMubGlzdCguLi5tYXBwZWQuY29uY2F0KFtLZXJuZWwuZWxlbSh0dXBsZSwgMCldKSk7XG4gICAgfVxuXG4gICAgcmV0dXJuIEtlcm5lbC5TcGVjaWFsRm9ybXMudHVwbGUobWFwcGVkLCB0aGVfYWNjKTtcbiAgfSxcblxuICBtZW1iZXI6IGZ1bmN0aW9uIChjb2xsZWN0aW9uLCB2YWx1ZSkge1xuICAgIHJldHVybiBjb2xsZWN0aW9uLmluY2x1ZGVzKHZhbHVlKTtcbiAgfSxcblxuICByZWR1Y2U6IGZ1bmN0aW9uIChjb2xsZWN0aW9uLCBhY2MsIGZ1bikge1xuICAgIGxldCB0aGVfYWNjID0gYWNjO1xuXG4gICAgZm9yICh2YXIgaSA9IDA7IGkgPCB0aGlzLmNvdW50KGNvbGxlY3Rpb24pOyBpKyspIHtcbiAgICAgIGxldCB0dXBsZSA9IGZ1bihjb2xsZWN0aW9uW2ldLCB0aGVfYWNjKTtcblxuICAgICAgdGhlX2FjYyA9IEtlcm5lbC5lbGVtKHR1cGxlLCAxKTtcbiAgICB9XG5cbiAgICByZXR1cm4gdGhlX2FjYztcbiAgfSxcblxuICB0YWtlOiBmdW5jdGlvbiAoY29sbGVjdGlvbiwgY291bnQpIHtcbiAgICByZXR1cm4gY29sbGVjdGlvbi5zbGljZSgwLCBjb3VudCk7XG4gIH0sXG5cbiAgdGFrZV9ldmVyeTogZnVuY3Rpb24gKGNvbGxlY3Rpb24sIG50aCkge1xuICAgIGxldCByZXN1bHQgPSBbXTtcbiAgICBsZXQgaW5kZXggPSAwO1xuXG4gICAgZm9yIChsZXQgZWxlbSBvZiBjb2xsZWN0aW9uKSB7XG4gICAgICBpZiAoaW5kZXggJSBudGggPT09IDApIHtcbiAgICAgICAgcmVzdWx0LnB1c2goZWxlbSk7XG4gICAgICB9XG4gICAgfVxuXG4gICAgcmV0dXJuIEtlcm5lbC5TcGVjaWFsRm9ybXMubGlzdCguLi5yZXN1bHQpO1xuICB9LFxuXG4gIHRha2Vfd2hpbGU6IGZ1bmN0aW9uIChjb2xsZWN0aW9uLCBmdW4pIHtcbiAgICBsZXQgY291bnQgPSAwO1xuXG4gICAgZm9yIChsZXQgZWxlbSBvZiBjb2xsZWN0aW9uKSB7XG4gICAgICBpZiAoZnVuKGVsZW0pKSB7XG4gICAgICAgIGNvdW50ID0gY291bnQgKyAxO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgYnJlYWs7XG4gICAgICB9XG4gICAgfVxuXG4gICAgcmV0dXJuIGNvbGxlY3Rpb24uc2xpY2UoMCwgY291bnQpO1xuICB9LFxuXG4gIHRvX2xpc3Q6IGZ1bmN0aW9uIChjb2xsZWN0aW9uKSB7XG4gICAgcmV0dXJuIGNvbGxlY3Rpb247XG4gIH1cbn07XG5cbmxldCBBdG9tID0ge307XG5cbkF0b20udG9fc3RyaW5nID0gZnVuY3Rpb24gKGF0b20pIHtcbiAgcmV0dXJuIFN5bWJvbC5rZXlGb3IoYXRvbSk7XG59O1xuXG5BdG9tLnRvX2NoYXJfbGlzdCA9IGZ1bmN0aW9uIChhdG9tKSB7XG4gIHJldHVybiBBdG9tLnRvX3N0cmluZyhhdG9tKS5zcGxpdCgnJyk7XG59O1xuXG5sZXQgSW50ZWdlciA9IHtcblxuICBpc19ldmVuOiBmdW5jdGlvbiAobikge1xuICAgIHJldHVybiBuICUgMiA9PT0gMDtcbiAgfSxcblxuICBpc19vZGQ6IGZ1bmN0aW9uIChuKSB7XG4gICAgcmV0dXJuIG4gJSAyICE9PSAwO1xuICB9LFxuXG4gIHBhcnNlOiBmdW5jdGlvbiAoYmluKSB7XG4gICAgbGV0IHJlc3VsdCA9IHBhcnNlSW50KGJpbik7XG5cbiAgICBpZiAoaXNOYU4ocmVzdWx0KSkge1xuICAgICAgcmV0dXJuIEtlcm5lbC5TcGVjaWFsRm9ybXMuYXRvbShcImVycm9yXCIpO1xuICAgIH1cblxuICAgIGxldCBpbmRleE9mRG90ID0gYmluLmluZGV4T2YoXCIuXCIpO1xuXG4gICAgaWYgKGluZGV4T2ZEb3QgPj0gMCkge1xuICAgICAgcmV0dXJuIEtlcm5lbC5TcGVjaWFsRm9ybXMudHVwbGUocmVzdWx0LCBiaW4uc3Vic3RyaW5nKGluZGV4T2ZEb3QpKTtcbiAgICB9XG5cbiAgICByZXR1cm4gS2VybmVsLlNwZWNpYWxGb3Jtcy50dXBsZShyZXN1bHQsIFwiXCIpO1xuICB9LFxuXG4gIHRvX2NoYXJfbGlzdDogZnVuY3Rpb24gKG51bWJlciwgYmFzZSA9IDEwKSB7XG4gICAgcmV0dXJuIG51bWJlci50b1N0cmluZyhiYXNlKS5zcGxpdChcIlwiKTtcbiAgfSxcblxuICB0b19zdHJpbmc6IGZ1bmN0aW9uIChudW1iZXIsIGJhc2UgPSAxMCkge1xuICAgIHJldHVybiBudW1iZXIudG9TdHJpbmcoYmFzZSk7XG4gIH1cbn07XG5cbmxldCBfQ2hhcnMgPSBLZXJuZWwuZGVmcHJvdG9jb2woe1xuICB0b19zdHJpbmc6IGZ1bmN0aW9uICh0aGluZykge31cbn0pO1xuXG5LZXJuZWwuZGVmaW1wbChfQ2hhcnMsIEJpdFN0cmluZywge1xuICB0b19zdHJpbmc6IGZ1bmN0aW9uICh0aGluZykge1xuICAgIGlmIChLZXJuZWwuaXNfYmluYXJ5KHRoaW5nKSkge1xuICAgICAgcmV0dXJuIHRoaW5nO1xuICAgIH1cblxuICAgIHJldHVybiB0aGluZy50b1N0cmluZygpO1xuICB9XG59KTtcblxuS2VybmVsLmRlZmltcGwoX0NoYXJzLCBTeW1ib2wsIHtcbiAgdG9fc3RyaW5nOiBmdW5jdGlvbiAodGhpbmcpIHtcbiAgICBpZiAobmlsKSB7XG4gICAgICByZXR1cm4gXCJcIjtcbiAgICB9XG5cbiAgICByZXR1cm4gQXRvbS50b19zdHJpbmcodGhpbmcpO1xuICB9XG59KTtcblxuS2VybmVsLmRlZmltcGwoX0NoYXJzLCBJbnRlZ2VyVHlwZSwge1xuICB0b19zdHJpbmc6IGZ1bmN0aW9uICh0aGluZykge1xuICAgIHJldHVybiBJbnRlZ2VyLnRvX3N0cmluZyh0aGluZyk7XG4gIH1cbn0pO1xuXG5LZXJuZWwuZGVmaW1wbChfQ2hhcnMsIEZsb2F0VHlwZSwge1xuICB0b19zdHJpbmc6IGZ1bmN0aW9uICh0aGluZykge1xuICAgIHJldHVybiB0aGluZy50b1N0cmluZztcbiAgfVxufSk7XG5cbktlcm5lbC5kZWZpbXBsKF9DaGFycywgQXJyYXksIHtcbiAgdG9fc3RyaW5nOiBmdW5jdGlvbiAodGhpbmcpIHtcbiAgICByZXR1cm4gdGhpbmcudG9TdHJpbmcoKTtcbiAgfVxufSk7XG5cbktlcm5lbC5kZWZpbXBsKF9DaGFycywgVHVwbGUsIHtcbiAgdG9fc3RyaW5nOiBmdW5jdGlvbiAodGhpbmcpIHtcbiAgICByZXR1cm4gVHVwbGUudG9fc3RyaW5nKHRoaW5nKTtcbiAgfVxufSk7XG5cbktlcm5lbC5kZWZpbXBsKF9DaGFycywgbnVsbCwge1xuICB0b19zdHJpbmc6IGZ1bmN0aW9uICh0aGluZykge1xuICAgIHJldHVybiB0aGluZy50b1N0cmluZygpO1xuICB9XG59KTtcblxuZnVuY3Rpb24gdG9fYXRvbShzdHJpbmcpIHtcbiAgcmV0dXJuIFN5bWJvbC5mb3Ioc3RyaW5nKTtcbn1cblxuZnVuY3Rpb24gdG9fZXhpc3RpbmdfYXRvbShzdHJpbmcpIHtcbiAgcmV0dXJuIFN5bWJvbC5mb3Ioc3RyaW5nKTtcbn1cblxuZnVuY3Rpb24gdG9fY2hhcl9saXN0KHN0cmluZykge1xuICByZXR1cm4gc3RyaW5nLnNwbGl0KCcnKTtcbn1cblxuZnVuY3Rpb24gdG9fZmxvYXQoc3RyaW5nKSB7XG4gIHJldHVybiBwYXJzZUZsb2F0KHN0cmluZyk7XG59XG5cbmZ1bmN0aW9uIHRvX2ludGVnZXIoc3RyaW5nLCBiYXNlID0gMTApIHtcbiAgcmV0dXJuIHBhcnNlSW50KHN0cmluZywgYmFzZSk7XG59XG5cbmZ1bmN0aW9uIHVwY2FzZShiaW5hcnkpIHtcbiAgcmV0dXJuIGJpbmFyeS50b1VwcGVyQ2FzZSgpO1xufVxuXG5mdW5jdGlvbiBkb3duY2FzZShiaW5hcnkpIHtcbiAgcmV0dXJuIGJpbmFyeS50b0xvd2VyQ2FzZSgpO1xufVxuXG5mdW5jdGlvbiBhdChzdHJpbmcsIHBvc2l0aW9uKSB7XG4gIGlmIChwb3NpdGlvbiA+IHN0cmluZy5sZW5ndGggLSAxKSB7XG4gICAgcmV0dXJuIG51bGw7XG4gIH1cblxuICByZXR1cm4gc3RyaW5nW3Bvc2l0aW9uXTtcbn1cblxuZnVuY3Rpb24gY2FwaXRhbGl6ZShzdHJpbmcpIHtcbiAgbGV0IHJldHVyblN0cmluZyA9ICcnO1xuXG4gIGZvciAobGV0IGkgPSAwOyBpIDwgc3RyaW5nLmxlbmd0aDsgaSsrKSB7XG4gICAgaWYgKGkgPT09IDApIHtcbiAgICAgIHJldHVyblN0cmluZyA9IHJldHVyblN0cmluZyArIHN0cmluZ1tpXS50b1VwcGVyQ2FzZSgpO1xuICAgIH0gZWxzZSB7XG4gICAgICByZXR1cm5TdHJpbmcgPSByZXR1cm5TdHJpbmcgKyBzdHJpbmdbaV0udG9Mb3dlckNhc2UoKTtcbiAgICB9XG4gIH1cblxuICByZXR1cm4gcmV0dXJuU3RyaW5nO1xufVxuXG5mdW5jdGlvbiBjb2RlcG9pbnRzKHN0cmluZykge1xuICByZXR1cm4gdG9fY2hhcl9saXN0KHN0cmluZykubWFwKGZ1bmN0aW9uIChjKSB7XG4gICAgcmV0dXJuIGMuY29kZVBvaW50QXQoMCk7XG4gIH0pO1xufVxuXG5mdW5jdGlvbiBjb250YWluc19fcW1fXyhzdHJpbmcsIGNvbnRhaW5zKSB7XG4gIGlmIChBcnJheS5pc0FycmF5KGNvbnRhaW5zKSkge1xuICAgIHJldHVybiBjb250YWlucy5zb21lKGZ1bmN0aW9uIChzKSB7XG4gICAgICByZXR1cm4gc3RyaW5nLmluZGV4T2YocykgPiAtMTtcbiAgICB9KTtcbiAgfVxuXG4gIHJldHVybiBzdHJpbmcuaW5kZXhPZihjb250YWlucykgPiAtMTtcbn1cblxuZnVuY3Rpb24gZHVwbGljYXRlKHN1YmplY3QsIG4pIHtcbiAgcmV0dXJuIHN1YmplY3QucmVwZWF0KG4pO1xufVxuXG5mdW5jdGlvbiBlbmRzX3dpdGhfX3FtX18oc3RyaW5nLCBzdWZmaXhlcykge1xuICBpZiAoQXJyYXkuaXNBcnJheShzdWZmaXhlcykpIHtcbiAgICByZXR1cm4gc3VmZml4ZXMuc29tZShmdW5jdGlvbiAocykge1xuICAgICAgcmV0dXJuIHN0cmluZy5lbmRzV2l0aChzKTtcbiAgICB9KTtcbiAgfVxuXG4gIHJldHVybiBzdHJpbmcuZW5kc1dpdGgoc3VmZml4ZXMpO1xufVxuXG5mdW5jdGlvbiBmaXJzdChzdHJpbmcpIHtcbiAgaWYgKCFzdHJpbmcpIHtcbiAgICByZXR1cm4gbnVsbDtcbiAgfVxuXG4gIHJldHVybiBzdHJpbmdbMF07XG59XG5cbmZ1bmN0aW9uIGdyYXBoZW1lcyhzdHJpbmcpIHtcbiAgcmV0dXJuIHN0cmluZy5zcGxpdCgnJyk7XG59XG5cbmZ1bmN0aW9uIGxhc3Qoc3RyaW5nKSB7XG4gIGlmICghc3RyaW5nKSB7XG4gICAgcmV0dXJuIG51bGw7XG4gIH1cblxuICByZXR1cm4gc3RyaW5nW3N0cmluZy5sZW5ndGggLSAxXTtcbn1cblxuZnVuY3Rpb24gbGVuZ3RoKHN0cmluZykge1xuICByZXR1cm4gc3RyaW5nLmxlbmd0aDtcbn1cblxuZnVuY3Rpb24gbWF0Y2hfX3FtX18oc3RyaW5nLCByZWdleCkge1xuICByZXR1cm4gc3RyaW5nLm1hdGNoKHJlZ2V4KSAhPSBudWxsO1xufVxuXG5mdW5jdGlvbiBuZXh0X2NvZGVwb2ludChzdHJpbmcpIHtcbiAgaWYgKCFzdHJpbmcgfHwgc3RyaW5nID09PSAnJykge1xuICAgIHJldHVybiBudWxsO1xuICB9XG5cbiAgcmV0dXJuIEtlcm5lbC5TcGVjaWFsRm9ybXMudHVwbGUoc3RyaW5nWzBdLmNvZGVQb2ludEF0KDApLCBzdHJpbmcuc3Vic3RyKDEpKTtcbn1cblxuZnVuY3Rpb24gbmV4dF9ncmFwaGVtZShzdHJpbmcpIHtcbiAgaWYgKCFzdHJpbmcgfHwgc3RyaW5nID09PSAnJykge1xuICAgIHJldHVybiBudWxsO1xuICB9XG5cbiAgcmV0dXJuIEtlcm5lbC5TcGVjaWFsRm9ybXMudHVwbGUoc3RyaW5nWzBdLCBzdHJpbmcuc3Vic3RyKDEpKTtcbn1cblxuZnVuY3Rpb24gcmV2ZXJzZShzdHJpbmcpIHtcbiAgbGV0IHJldHVyblZhbHVlID0gJyc7XG5cbiAgZm9yICh2YXIgaSA9IHN0cmluZy5sZW5ndGggLSAxOyBpID49IDA7IGktLSkge1xuICAgIHJldHVyblZhbHVlID0gcmV0dXJuVmFsdWUgKyBzdHJpbmdbaV07XG4gIH07XG5cbiAgcmV0dXJuIHJldHVyblZhbHVlO1xufVxuXG5mdW5jdGlvbiBfc3BsaXQoc3RyaW5nKSB7XG4gIHJldHVybiBzdHJpbmcuc3BsaXQoKTtcbn1cblxuZnVuY3Rpb24gc3RhcnRzX3dpdGhfX3FtX18oc3RyaW5nLCBwcmVmaXhlcykge1xuICBpZiAoQXJyYXkuaXNBcnJheShwcmVmaXhlcykpIHtcbiAgICByZXR1cm4gcHJlZml4ZXMuc29tZShmdW5jdGlvbiAocykge1xuICAgICAgcmV0dXJuIHN0cmluZy5zdGFydHNXaXRoKHMpO1xuICAgIH0pO1xuICB9XG5cbiAgcmV0dXJuIHN0cmluZy5zdGFydHNXaXRoKHByZWZpeGVzKTtcbn1cblxuZnVuY3Rpb24gdmFsaWRfY2hhcmFjdGVyX19xbV9fKGNvZGVwb2ludCkge1xuICB0cnkge1xuICAgIHJldHVybiBTdHJpbmcuZnJvbUNvZGVQb2ludChjb2RlcG9pbnQpICE9IG51bGw7XG4gIH0gY2F0Y2ggKGUpIHtcbiAgICByZXR1cm4gZmFsc2U7XG4gIH1cbn1cblxudmFyIF9TdHJpbmcgPSB7XG4gIGF0LFxuICBjYXBpdGFsaXplLFxuICBjb2RlcG9pbnRzLFxuICBjb250YWluc19fcW1fXyxcbiAgZG93bmNhc2UsXG4gIGR1cGxpY2F0ZSxcbiAgZW5kc193aXRoX19xbV9fLFxuICBmaXJzdCxcbiAgZ3JhcGhlbWVzLFxuICBsYXN0LFxuICBsZW5ndGgsXG4gIG1hdGNoX19xbV9fLFxuICBuZXh0X2NvZGVwb2ludCxcbiAgbmV4dF9ncmFwaGVtZSxcbiAgcmV2ZXJzZSxcbiAgc3BsaXQ6IF9zcGxpdCxcbiAgc3RhcnRzX3dpdGhfX3FtX18sXG4gIHRvX2F0b20sXG4gIHRvX2NoYXJfbGlzdCxcbiAgdG9fZXhpc3RpbmdfYXRvbSxcbiAgdG9fZmxvYXQsXG4gIHRvX2ludGVnZXIsXG4gIHVwY2FzZSxcbiAgdmFsaWRfY2hhcmFjdGVyX19xbV9fLFxuICBDaGFyczogX0NoYXJzXG59O1xuXG5sZXQgQ2hhcnMgPSBLZXJuZWwuZGVmcHJvdG9jb2woe1xuICB0b19jaGFyX2xpc3Q6IGZ1bmN0aW9uICh0aGluZykge31cbn0pO1xuXG5LZXJuZWwuZGVmaW1wbChDaGFycywgS2VybmVsLmlzX2JpdHN0cmluZywge1xuICB0b19jaGFyX2xpc3Q6IGZ1bmN0aW9uICh0aGluZykge1xuICAgIGlmIChLZXJuZWwuaXNfYmluYXJ5KHRoaW5nKSkge1xuICAgICAgcmV0dXJuIF9TdHJpbmcudG9fY2hhcl9saXN0KHRoaW5nKTtcbiAgICB9XG5cbiAgICByZXR1cm4gdGhpbmcudG9TdHJpbmcoKTtcbiAgfVxufSk7XG5cbktlcm5lbC5kZWZpbXBsKENoYXJzLCBLZXJuZWwuaXNfYXRvbSwge1xuICB0b19jaGFyX2xpc3Q6IGZ1bmN0aW9uICh0aGluZykge1xuICAgIHJldHVybiBBdG9tLnRvX2NoYXJfbGlzdCh0aGluZyk7XG4gIH1cbn0pO1xuXG5LZXJuZWwuZGVmaW1wbChDaGFycywgS2VybmVsLmlzX2ludGVnZXIsIHtcbiAgdG9fY2hhcl9saXN0OiBmdW5jdGlvbiAodGhpbmcpIHtcbiAgICByZXR1cm4gSW50ZWdlci50b19jaGFyX2xpc3QodGhpbmcpO1xuICB9XG59KTtcblxuS2VybmVsLmRlZmltcGwoQ2hhcnMsIEtlcm5lbC5pc19saXN0LCB7XG4gIHRvX2NoYXJfbGlzdDogZnVuY3Rpb24gKHRoaW5nKSB7XG4gICAgcmV0dXJuIHRoaW5nO1xuICB9XG59KTtcblxubGV0IExpc3QgPSB7fTtcblxuTGlzdC5DaGFycyA9IENoYXJzO1xuXG5MaXN0LmRlbGV0ZSA9IGZ1bmN0aW9uIChsaXN0LCBpdGVtKSB7XG4gIGxldCBuZXdfdmFsdWUgPSBbXTtcbiAgbGV0IHZhbHVlX2ZvdW5kID0gZmFsc2U7XG5cbiAgZm9yIChsZXQgeCBvZiBsaXN0KSB7XG4gICAgaWYgKHggPT09IGl0ZW0gJiYgdmFsdWVfZm91bmQgIT09IGZhbHNlKSB7XG4gICAgICBuZXdfdmFsdWUucHVzaCh4KTtcbiAgICAgIHZhbHVlX2ZvdW5kID0gdHJ1ZTtcbiAgICB9IGVsc2UgaWYgKHggIT09IGl0ZW0pIHtcbiAgICAgIG5ld192YWx1ZS5wdXNoKHgpO1xuICAgIH1cbiAgfVxuXG4gIHJldHVybiBLZXJuZWwuU3BlY2lhbEZvcm1zLmxpc3QoLi4ubmV3X3ZhbHVlKTtcbn07XG5cbkxpc3QuZGVsZXRlX2F0ID0gZnVuY3Rpb24gKGxpc3QsIGluZGV4KSB7XG4gIGxldCBuZXdfdmFsdWUgPSBbXTtcblxuICBmb3IgKGxldCBpID0gMDsgaSA8IGxpc3QubGVuZ3RoOyBpKyspIHtcbiAgICBpZiAoaSAhPT0gaW5kZXgpIHtcbiAgICAgIG5ld192YWx1ZS5wdXNoKGxpc3RbaV0pO1xuICAgIH1cbiAgfVxuXG4gIHJldHVybiBLZXJuZWwuU3BlY2lhbEZvcm1zLmxpc3QoLi4ubmV3X3ZhbHVlKTtcbn07XG5cbkxpc3QuZHVwbGljYXRlID0gZnVuY3Rpb24gKGVsZW0sIG4pIHtcbiAgbGV0IG5ld192YWx1ZSA9IFtdO1xuXG4gIGZvciAodmFyIGkgPSAwOyBpIDwgbjsgaSsrKSB7XG4gICAgbmV3X3ZhbHVlLnB1c2goZWxlbSk7XG4gIH1cblxuICByZXR1cm4gS2VybmVsLlNwZWNpYWxGb3Jtcy5saXN0KC4uLm5ld192YWx1ZSk7XG59O1xuXG5MaXN0LmZpcnN0ID0gZnVuY3Rpb24gKGxpc3QpIHtcbiAgcmV0dXJuIGxpc3RbMF07XG59O1xuXG5MaXN0LmZsYXR0ZW4gPSBmdW5jdGlvbiAobGlzdCwgdGFpbCA9IEtlcm5lbC5TcGVjaWFsRm9ybXMubGlzdCgpKSB7XG4gIGxldCBuZXdfdmFsdWUgPSBbXTtcblxuICBmb3IgKGxldCB4IG9mIGxpc3QpIHtcbiAgICBpZiAoS2VybmVsLmlzX2xpc3QoeCkpIHtcbiAgICAgIG5ld192YWx1ZSA9IG5ld192YWx1ZS5jb25jYXQoTGlzdC5mbGF0dGVuKHgpKTtcbiAgICB9IGVsc2Uge1xuICAgICAgbmV3X3ZhbHVlLnB1c2goeCk7XG4gICAgfVxuICB9XG5cbiAgbmV3X3ZhbHVlID0gbmV3X3ZhbHVlLmNvbmNhdCh0YWlsKTtcblxuICByZXR1cm4gS2VybmVsLlNwZWNpYWxGb3Jtcy5saXN0KC4uLm5ld192YWx1ZSk7XG59O1xuXG5MaXN0LmZvbGRsID0gZnVuY3Rpb24gKGxpc3QsIGFjYywgZnVuYykge1xuICByZXR1cm4gbGlzdC5yZWR1Y2UoZnVuYywgYWNjKTtcbn07XG5cbkxpc3QuZm9sZHIgPSBmdW5jdGlvbiAobGlzdCwgYWNjLCBmdW5jKSB7XG4gIGxldCBuZXdfYWNjID0gYWNjO1xuXG4gIGZvciAodmFyIGkgPSBsaXN0Lmxlbmd0aCAtIDE7IGkgPj0gMDsgaS0tKSB7XG4gICAgbmV3X2FjYyA9IGZ1bmMobGlzdFtpXSwgbmV3X2FjYyk7XG4gIH1cblxuICByZXR1cm4gbmV3X2FjYztcbn07XG5cbkxpc3QuaW5zZXJ0X2F0ID0gZnVuY3Rpb24gKGxpc3QsIGluZGV4LCB2YWx1ZSkge1xuICBsZXQgbmV3X3ZhbHVlID0gW107XG5cbiAgZm9yIChsZXQgaSA9IDA7IGkgPCBsaXN0Lmxlbmd0aDsgaSsrKSB7XG4gICAgaWYgKGkgPT09IGluZGV4KSB7XG4gICAgICBuZXdfdmFsdWUucHVzaCh2YWx1ZSk7XG4gICAgICBuZXdfdmFsdWUucHVzaChsaXN0W2ldKTtcbiAgICB9IGVsc2Uge1xuICAgICAgbmV3X3ZhbHVlLnB1c2gobGlzdFtpXSk7XG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIEtlcm5lbC5TcGVjaWFsRm9ybXMubGlzdCguLi5uZXdfdmFsdWUpO1xufTtcblxuTGlzdC5rZXlkZWxldGUgPSBmdW5jdGlvbiAobGlzdCwga2V5LCBwb3NpdGlvbikge1xuICBsZXQgbmV3X2xpc3QgPSBbXTtcblxuICBmb3IgKGxldCBpID0gMDsgaSA8IGxpc3QubGVuZ3RoOyBpKyspIHtcbiAgICBpZiAoIUtlcm5lbC5tYXRjaF9fcW1hcmtfXyhsaXN0W2ldW3Bvc2l0aW9uXSwga2V5KSkge1xuICAgICAgbmV3X2xpc3QucHVzaChsaXN0W2ldKTtcbiAgICB9XG4gIH1cblxuICByZXR1cm4gS2VybmVsLlNwZWNpYWxGb3Jtcy5saXN0KC4uLm5ld19saXN0KTtcbn07XG5cbkxpc3Qua2V5ZmluZCA9IGZ1bmN0aW9uIChsaXN0LCBrZXksIHBvc2l0aW9uLCBfZGVmYXVsdCA9IG51bGwpIHtcblxuICBmb3IgKGxldCBpID0gMDsgaSA8IGxpc3QubGVuZ3RoOyBpKyspIHtcbiAgICBpZiAoS2VybmVsLm1hdGNoX19xbWFya19fKGxpc3RbaV1bcG9zaXRpb25dLCBrZXkpKSB7XG4gICAgICByZXR1cm4gbGlzdFtpXTtcbiAgICB9XG4gIH1cblxuICByZXR1cm4gX2RlZmF1bHQ7XG59O1xuXG5MaXN0LmtleW1lbWJlcl9fcW1hcmtfXyA9IGZ1bmN0aW9uIChsaXN0LCBrZXksIHBvc2l0aW9uKSB7XG5cbiAgZm9yIChsZXQgaSA9IDA7IGkgPCBsaXN0Lmxlbmd0aDsgaSsrKSB7XG4gICAgaWYgKEtlcm5lbC5tYXRjaF9fcW1hcmtfXyhsaXN0W2ldW3Bvc2l0aW9uXSwga2V5KSkge1xuICAgICAgcmV0dXJuIHRydWU7XG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIGZhbHNlO1xufTtcblxuTGlzdC5rZXlyZXBsYWNlID0gZnVuY3Rpb24gKGxpc3QsIGtleSwgcG9zaXRpb24sIG5ld190dXBsZSkge1xuICBsZXQgbmV3X2xpc3QgPSBbXTtcblxuICBmb3IgKGxldCBpID0gMDsgaSA8IGxpc3QubGVuZ3RoOyBpKyspIHtcbiAgICBpZiAoIUtlcm5lbC5tYXRjaF9fcW1hcmtfXyhsaXN0W2ldW3Bvc2l0aW9uXSwga2V5KSkge1xuICAgICAgbmV3X2xpc3QucHVzaChsaXN0W2ldKTtcbiAgICB9IGVsc2Uge1xuICAgICAgbmV3X2xpc3QucHVzaChuZXdfdHVwbGUpO1xuICAgIH1cbiAgfVxuXG4gIHJldHVybiBLZXJuZWwuU3BlY2lhbEZvcm1zLmxpc3QoLi4ubmV3X2xpc3QpO1xufTtcblxuTGlzdC5rZXlzb3J0ID0gZnVuY3Rpb24gKGxpc3QsIHBvc2l0aW9uKSB7XG4gIGxldCBuZXdfbGlzdCA9IGxpc3Q7XG5cbiAgbmV3X2xpc3Quc29ydChmdW5jdGlvbiAoYSwgYikge1xuICAgIGlmIChwb3NpdGlvbiA9PT0gMCkge1xuICAgICAgaWYgKGFbcG9zaXRpb25dLnZhbHVlIDwgYltwb3NpdGlvbl0udmFsdWUpIHtcbiAgICAgICAgcmV0dXJuIC0xO1xuICAgICAgfVxuXG4gICAgICBpZiAoYVtwb3NpdGlvbl0udmFsdWUgPiBiW3Bvc2l0aW9uXS52YWx1ZSkge1xuICAgICAgICByZXR1cm4gMTtcbiAgICAgIH1cblxuICAgICAgcmV0dXJuIDA7XG4gICAgfSBlbHNlIHtcbiAgICAgIGlmIChhW3Bvc2l0aW9uXSA8IGJbcG9zaXRpb25dKSB7XG4gICAgICAgIHJldHVybiAtMTtcbiAgICAgIH1cblxuICAgICAgaWYgKGFbcG9zaXRpb25dID4gYltwb3NpdGlvbl0pIHtcbiAgICAgICAgcmV0dXJuIDE7XG4gICAgICB9XG5cbiAgICAgIHJldHVybiAwO1xuICAgIH1cbiAgfSk7XG5cbiAgcmV0dXJuIEtlcm5lbC5TcGVjaWFsRm9ybXMubGlzdCguLi5uZXdfbGlzdCk7XG59O1xuXG5MaXN0LmtleXN0b3JlID0gZnVuY3Rpb24gKGxpc3QsIGtleSwgcG9zaXRpb24sIG5ld190dXBsZSkge1xuICBsZXQgbmV3X2xpc3QgPSBbXTtcbiAgbGV0IHJlcGxhY2VkID0gZmFsc2U7XG5cbiAgZm9yIChsZXQgaSA9IDA7IGkgPCBsaXN0Lmxlbmd0aDsgaSsrKSB7XG4gICAgaWYgKCFLZXJuZWwubWF0Y2hfX3FtYXJrX18obGlzdFtpXVtwb3NpdGlvbl0sIGtleSkpIHtcbiAgICAgIG5ld19saXN0LnB1c2gobGlzdFtpXSk7XG4gICAgfSBlbHNlIHtcbiAgICAgIG5ld19saXN0LnB1c2gobmV3X3R1cGxlKTtcbiAgICAgIHJlcGxhY2VkID0gdHJ1ZTtcbiAgICB9XG4gIH1cblxuICBpZiAoIXJlcGxhY2VkKSB7XG4gICAgbmV3X2xpc3QucHVzaChuZXdfdHVwbGUpO1xuICB9XG5cbiAgcmV0dXJuIEtlcm5lbC5TcGVjaWFsRm9ybXMubGlzdCguLi5uZXdfbGlzdCk7XG59O1xuXG5MaXN0Lmxhc3QgPSBmdW5jdGlvbiAobGlzdCkge1xuICByZXR1cm4gbGlzdFtsaXN0Lmxlbmd0aCAtIDFdO1xufTtcblxuTGlzdC5yZXBsYWNlX2F0ID0gZnVuY3Rpb24gKGxpc3QsIGluZGV4LCB2YWx1ZSkge1xuICBsZXQgbmV3X3ZhbHVlID0gW107XG5cbiAgZm9yIChsZXQgaSA9IDA7IGkgPCBsaXN0Lmxlbmd0aDsgaSsrKSB7XG4gICAgaWYgKGkgPT09IGluZGV4KSB7XG4gICAgICBuZXdfdmFsdWUucHVzaCh2YWx1ZSk7XG4gICAgfSBlbHNlIHtcbiAgICAgIG5ld192YWx1ZS5wdXNoKGxpc3RbaV0pO1xuICAgIH1cbiAgfVxuXG4gIHJldHVybiBLZXJuZWwuU3BlY2lhbEZvcm1zLmxpc3QoLi4ubmV3X3ZhbHVlKTtcbn07XG5cbkxpc3QudXBkYXRlX2F0ID0gZnVuY3Rpb24gKGxpc3QsIGluZGV4LCBmdW4pIHtcbiAgbGV0IG5ld192YWx1ZSA9IFtdO1xuXG4gIGZvciAobGV0IGkgPSAwOyBpIDwgbGlzdC5jb3VudCgpOyBpKyspIHtcbiAgICBpZiAoaSA9PT0gaW5kZXgpIHtcbiAgICAgIG5ld192YWx1ZS5wdXNoKGZ1bihsaXN0LmdldChpKSkpO1xuICAgIH0gZWxzZSB7XG4gICAgICBuZXdfdmFsdWUucHVzaChsaXN0LmdldChpKSk7XG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIG5ld192YWx1ZTtcbn07XG5cbkxpc3Qud3JhcCA9IGZ1bmN0aW9uIChsaXN0KSB7XG4gIGlmIChLZXJuZWwuaXNfbGlzdChsaXN0KSkge1xuICAgIHJldHVybiBsaXN0O1xuICB9IGVsc2UgaWYgKGxpc3QgPT0gbnVsbCkge1xuICAgIHJldHVybiBLZXJuZWwuU3BlY2lhbEZvcm1zLmxpc3QoKTtcbiAgfSBlbHNlIHtcbiAgICByZXR1cm4gS2VybmVsLlNwZWNpYWxGb3Jtcy5saXN0KGxpc3QpO1xuICB9XG59O1xuXG5MaXN0LnppcCA9IGZ1bmN0aW9uIChsaXN0X29mX2xpc3RzKSB7XG4gIGlmIChsaXN0X29mX2xpc3RzLmxlbmd0aCA9PT0gMCkge1xuICAgIHJldHVybiBLZXJuZWwuU3BlY2lhbEZvcm1zLmxpc3QoKTtcbiAgfVxuXG4gIGxldCBuZXdfdmFsdWUgPSBbXTtcbiAgbGV0IHNtYWxsZXN0X2xlbmd0aCA9IGxpc3Rfb2ZfbGlzdHNbMF07XG5cbiAgZm9yIChsZXQgeCBvZiBsaXN0X29mX2xpc3RzKSB7XG4gICAgaWYgKHgubGVuZ3RoIDwgc21hbGxlc3RfbGVuZ3RoKSB7XG4gICAgICBzbWFsbGVzdF9sZW5ndGggPSB4Lmxlbmd0aDtcbiAgICB9XG4gIH1cblxuICBmb3IgKGxldCBpID0gMDsgaSA8IHNtYWxsZXN0X2xlbmd0aDsgaSsrKSB7XG4gICAgbGV0IGN1cnJlbnRfdmFsdWUgPSBbXTtcbiAgICBmb3IgKGxldCBqID0gMDsgaiA8IGxpc3Rfb2ZfbGlzdHMubGVuZ3RoOyBqKyspIHtcbiAgICAgIGN1cnJlbnRfdmFsdWUucHVzaChsaXN0X29mX2xpc3RzW2pdW2ldKTtcbiAgICB9XG5cbiAgICBuZXdfdmFsdWUucHVzaChLZXJuZWwuU3BlY2lhbEZvcm1zLnR1cGxlKC4uLmN1cnJlbnRfdmFsdWUpKTtcbiAgfVxuXG4gIHJldHVybiBLZXJuZWwuU3BlY2lhbEZvcm1zLmxpc3QoLi4ubmV3X3ZhbHVlKTtcbn07XG5cbkxpc3QudG9fdHVwbGUgPSBmdW5jdGlvbiAobGlzdCkge1xuICByZXR1cm4gS2VybmVsLlNwZWNpYWxGb3Jtcy50dXBsZS5hcHBseShudWxsLCBsaXN0KTtcbn07XG5cbkxpc3QuYXBwZW5kID0gZnVuY3Rpb24gKGxpc3QsIHZhbHVlKSB7XG4gIHJldHVybiBLZXJuZWwuU3BlY2lhbEZvcm1zLmxpc3QoLi4ubGlzdC5jb25jYXQoW3ZhbHVlXSkpO1xufTtcblxuTGlzdC5wcmVwZW5kID0gZnVuY3Rpb24gKGxpc3QsIHZhbHVlKSB7XG4gIHJldHVybiBLZXJuZWwuU3BlY2lhbEZvcm1zLmxpc3QoLi4uW3ZhbHVlXS5jb25jYXQobGlzdCkpO1xufTtcblxuTGlzdC5jb25jYXQgPSBmdW5jdGlvbiAobGVmdCwgcmlnaHQpIHtcbiAgcmV0dXJuIGxlZnQuY29uY2F0KHJpZ2h0KTtcbn07XG5cbmNsYXNzIFNpZ25hbCB7XG5cbiAgY29uc3RydWN0b3IoKSB7XG4gICAgdGhpcy5iaW5kaW5ncyA9IFNwZWNpYWxGb3Jtcy5saXN0KCk7XG4gIH1cblxuICBhZGQobGlzdGVuZXIsIGNvbnRleHQgPSB0aGlzKSB7XG4gICAgdGhpcy5iaW5kaW5ncyA9IExpc3QuYXBwZW5kKHRoaXMuYmluZGluZ3MsIG5ldyBTaWduYWxCaW5kaW5nKHRoaXMsIGxpc3RlbmVyLCBjb250ZXh0KSk7XG4gIH1cblxuICByZW1vdmUobGlzdGVuZXIpIHtcbiAgICB0aGlzLmJpbmRpbmdzID0gRW51bS5maWx0ZXIodGhpcy5iaW5kaW5ncywgZnVuY3Rpb24gKGJpbmRpbmcpIHtcbiAgICAgIHJldHVybiBiaW5kaW5nLmxpc3RlbmVyICE9PSBsaXN0ZW5lcjtcbiAgICB9KTtcbiAgfVxuXG4gIGRpc3BhdGNoKC4uLnBhcmFtcykge1xuICAgIGZvciAobGV0IGJpbmRpbmcgb2YgdGhpcy5iaW5kaW5ncykge1xuICAgICAgYmluZGluZy5leGVjdXRlKC4uLnBhcmFtcyk7XG4gICAgfVxuICB9XG5cbiAgZGlzcG9zZSgpIHtcbiAgICBmb3IgKGxldCBiaW5kaW5nIG9mIHRoaXMuYmluZGluZ3MpIHtcbiAgICAgIGJpbmRpbmcuZGlzcG9zZSgpO1xuICAgIH1cblxuICAgIHRoaXMuYmluZGluZ3MgPSBudWxsO1xuICB9XG59XG5cbmNsYXNzIFNpZ25hbEJpbmRpbmcge1xuXG4gIGNvbnN0cnVjdG9yKHNpZ25hbCwgbGlzdGVuZXIsIGNvbnRleHQpIHtcbiAgICB0aGlzLmxpc3RlbmVyID0gbGlzdGVuZXI7XG4gICAgdGhpcy5zaWduYWwgPSBzaWduYWw7XG4gICAgdGhpcy5jb250ZXh0ID0gY29udGV4dDtcbiAgfVxuXG4gIGV4ZWN1dGUoLi4ucGFyYW1zKSB7XG4gICAgdGhpcy5saXN0ZW5lci5hcHBseSh0aGlzLmNvbnRleHQsIHBhcmFtcyk7XG4gIH1cblxuICBkaXNwb3NlKCkge1xuICAgIHRoaXMubGlzdGVuZXIgPSBudWxsO1xuICAgIHRoaXMuc2lnbmFsID0gbnVsbDtcbiAgICB0aGlzLmNvbnRleHQgPSBudWxsO1xuICB9XG59XG5cbmZ1bmN0aW9uIF9fX3VwZGF0ZShtYXAsIGtleSwgdmFsdWUpIHtcbiAgbGV0IG0gPSBuZXcgTWFwKG1hcCk7XG4gIG0uc2V0KGtleSwgdmFsdWUpO1xuICByZXR1cm4gbTtcbn1cblxuZnVuY3Rpb24gcmVtb3ZlKG1hcCwga2V5KSB7XG4gIGxldCBtID0gbmV3IE1hcChtYXApO1xuICBtLmRlbGV0ZShrZXkpO1xuICByZXR1cm4gbTtcbn1cblxuY2xhc3MgTWFpbEJveCB7XG5cbiAgY29uc3RydWN0b3IoY29udGV4dCA9IHRoaXMpIHtcbiAgICB0aGlzLnNpZ25hbCA9IG5ldyBTaWduYWwoKTtcbiAgICB0aGlzLnNpZ25hbC5hZGQoKC4uLnBhcmFtcykgPT4gdGhpcy5tZXNzYWdlcyA9IHRoaXMubWVzc2FnZXMuY29uY2F0KHBhcmFtcyksIGNvbnRleHQpO1xuICAgIHRoaXMubWVzc2FnZXMgPSBbXTtcbiAgfVxuXG4gIHJlY2VpdmUoLi4ubWVzc2FnZXMpIHtcbiAgICB0aGlzLnNpZ25hbC5kaXNwYXRjaCguLi5tZXNzYWdlcyk7XG4gIH1cblxuICBwZWVrKCkge1xuICAgIGlmICh0aGlzLm1lc3NhZ2VzLmxlbmd0aCA9PT0gMCkge1xuICAgICAgcmV0dXJuIG51bGw7XG4gICAgfVxuXG4gICAgcmV0dXJuIHRoaXMubWVzc2FnZXNbMF07XG4gIH1cblxuICByZWFkKCkge1xuICAgIGxldCByZXN1bHQgPSB0aGlzLm1lc3NhZ2VzWzBdO1xuICAgIHRoaXMubWVzc2FnZXMgPSB0aGlzLm1lc3NhZ2VzLnNsaWNlKDEpO1xuXG4gICAgcmV0dXJuIHJlc3VsdDtcbiAgfVxuXG4gIGFkZF9zdWJzY3JpYmVyKGZuLCBjb250ZXh0ID0gdGhpcykge1xuICAgIHRoaXMuc2lnbmFsLmFkZChmbiwgY29udGV4dCk7XG4gIH1cblxuICByZW1vdmVfc3Vic2NyaWJlcihmbikge1xuICAgIHRoaXMuc2lnbmFsLnJlbW92ZShmbik7XG4gIH1cblxuICBkaXNwb3NlKCkge1xuICAgIHRoaXMuc2lnbmFsLmRpc3Bvc2UoKTtcbiAgICB0aGlzLm1lc3NhZ2VzID0gbnVsbDtcbiAgfVxufVxuXG5jbGFzcyBQb3N0T2ZmaWNlIHtcblxuICBjb25zdHJ1Y3RvcigpIHtcbiAgICB0aGlzLm1haWxib3hlcyA9IG5ldyBNYXAoKTtcbiAgfVxuXG4gIHNlbmQoYWRkcmVzcywgbWVzc2FnZSkge1xuICAgIHRoaXMubWFpbGJveGVzLmdldChhZGRyZXNzKS5yZWNlaXZlKG1lc3NhZ2UpO1xuICB9XG5cbiAgcmVjZWl2ZShhZGRyZXNzKSB7XG4gICAgcmV0dXJuIHRoaXMubWFpbGJveGVzLmdldChhZGRyZXNzKS5yZWFkKCk7XG4gIH1cblxuICBwZWVrKGFkZHJlc3MpIHtcbiAgICByZXR1cm4gdGhpcy5tYWlsYm94ZXMuZ2V0KGFkZHJlc3MpLnBlZWsoKTtcbiAgfVxuXG4gIGFkZF9tYWlsYm94KGFkZHJlc3MgPSBTeW1ib2woKSwgY29udGV4dCA9IHRoaXMpIHtcbiAgICB0aGlzLm1haWxib3hlcyA9IF9fX3VwZGF0ZSh0aGlzLm1haWxib3hlcywgYWRkcmVzcywgbmV3IE1haWxCb3goKSk7XG4gICAgcmV0dXJuIGFkZHJlc3M7XG4gIH1cblxuICByZW1vdmVfbWFpbGJveChhZGRyZXNzKSB7XG4gICAgdGhpcy5tYWlsYm94ZXMuZ2V0KGFkZHJlc3MpLmRpc3Bvc2UoKTtcbiAgICB0aGlzLm1haWxib3hlcyA9IHJlbW92ZSh0aGlzLm1haWxib3hlcywgYWRkcmVzcyk7XG4gIH1cblxuICBzdWJzY3JpYmUoYWRkcmVzcywgc3Vic2NyaWJ0aW9uX2ZuLCBjb250ZXh0ID0gdGhpcykge1xuICAgIHRoaXMubWFpbGJveGVzLmdldChhZGRyZXNzKS5hZGRfc3Vic2NyaWJlcihzdWJzY3JpYnRpb25fZm4sIGNvbnRleHQpO1xuICB9XG5cbiAgdW5zdWJzY3JpYmUoYWRkcmVzcywgc3Vic2NyaWJ0aW9uX2ZuKSB7XG4gICAgdGhpcy5tYWlsYm94ZXMuZ2V0KGFkZHJlc3MpLnJlbW92ZV9zdWJzY3JpYmVyKHN1YnNjcmlidGlvbl9mbik7XG4gIH1cbn1cblxuZnVuY3Rpb24gY2FsbF9wcm9wZXJ0eShpdGVtLCBwcm9wZXJ0eSkge1xuICBpZiAocHJvcGVydHkgaW4gaXRlbSkge1xuICAgIGl0ZW1bcHJvcGVydHldO1xuICAgIGlmIChpdGVtW3Byb3BlcnR5XSBpbnN0YW5jZW9mIEZ1bmN0aW9uKSB7XG4gICAgICByZXR1cm4gaXRlbVtwcm9wZXJ0eV0oKTtcbiAgICB9IGVsc2Uge1xuICAgICAgcmV0dXJuIGl0ZW1bcHJvcGVydHldO1xuICAgIH1cbiAgfSBlbHNlIGlmIChTeW1ib2wuZm9yKHByb3BlcnR5KSBpbiBpdGVtKSB7XG4gICAgbGV0IHByb3AgPSBTeW1ib2wuZm9yKHByb3BlcnR5KTtcbiAgICBpZiAoaXRlbVtwcm9wXSBpbnN0YW5jZW9mIEZ1bmN0aW9uKSB7XG4gICAgICByZXR1cm4gaXRlbVtwcm9wXSgpO1xuICAgIH0gZWxzZSB7XG4gICAgICByZXR1cm4gaXRlbVtwcm9wXTtcbiAgICB9XG4gIH1cblxuICB0aHJvdyBuZXcgRXJyb3IoYFByb3BlcnR5ICR7IHByb3BlcnR5IH0gbm90IGZvdW5kIGluICR7IGl0ZW0gfWApO1xufVxuXG52YXIgSlMgPSB7XG4gIGNhbGxfcHJvcGVydHlcbn07XG5cbmxldCBSYW5nZSA9IGZ1bmN0aW9uIChfZmlyc3QsIF9sYXN0KSB7XG4gIGlmICghKHRoaXMgaW5zdGFuY2VvZiBSYW5nZSkpIHtcbiAgICByZXR1cm4gbmV3IFJhbmdlKF9maXJzdCwgX2xhc3QpO1xuICB9XG5cbiAgdGhpcy5maXJzdCA9IGZ1bmN0aW9uICgpIHtcbiAgICByZXR1cm4gX2ZpcnN0O1xuICB9O1xuXG4gIHRoaXMubGFzdCA9IGZ1bmN0aW9uICgpIHtcbiAgICByZXR1cm4gX2xhc3Q7XG4gIH07XG5cbiAgbGV0IF9yYW5nZSA9IFtdO1xuXG4gIGZvciAobGV0IGkgPSBfZmlyc3Q7IGkgPD0gX2xhc3Q7IGkrKykge1xuICAgIF9yYW5nZS5wdXNoKGkpO1xuICB9XG5cbiAgX3JhbmdlID0gT2JqZWN0LmZyZWV6ZShfcmFuZ2UpO1xuXG4gIHRoaXMudmFsdWUgPSBmdW5jdGlvbiAoKSB7XG4gICAgcmV0dXJuIF9yYW5nZTtcbiAgfTtcblxuICB0aGlzLmxlbmd0aCA9IGZ1bmN0aW9uICgpIHtcbiAgICByZXR1cm4gX3JhbmdlLmxlbmd0aDtcbiAgfTtcblxuICByZXR1cm4gdGhpcztcbn07XG5cblJhbmdlLnByb3RvdHlwZVtTeW1ib2wuaXRlcmF0b3JdID0gZnVuY3Rpb24gKCkge1xuICByZXR1cm4gdGhpcy52YWx1ZSgpW1N5bWJvbC5pdGVyYXRvcl0oKTtcbn07XG5cblJhbmdlLm5ldyA9IGZ1bmN0aW9uIChmaXJzdCwgbGFzdCkge1xuICByZXR1cm4gUmFuZ2UoZmlyc3QsIGxhc3QpO1xufTtcblxuUmFuZ2UucmFuZ2VfX3FtYXJrX18gPSBmdW5jdGlvbiAocmFuZ2UpIHtcbiAgcmV0dXJuIHJhbmdlIGluc3RhbmNlb2YgUmFuZ2U7XG59O1xuXG5sZXQgS2V5d29yZCA9IHt9O1xuXG5LZXl3b3JkLmhhc19rZXlfX3FtX18gPSBmdW5jdGlvbiAoa2V5d29yZHMsIGtleSkge1xuICBmb3IgKGxldCBrZXl3b3JkIG9mIGtleXdvcmRzKSB7XG4gICAgaWYgKEtlcm5lbC5lbGVtKGtleXdvcmQsIDApID09IGtleSkge1xuICAgICAgcmV0dXJuIHRydWU7XG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIGZhbHNlO1xufTtcblxuS2V5d29yZC5nZXQgPSBmdW5jdGlvbiAoa2V5d29yZHMsIGtleSwgdGhlX2RlZmF1bHQgPSBudWxsKSB7XG4gIGZvciAobGV0IGtleXdvcmQgb2Yga2V5d29yZHMpIHtcbiAgICBpZiAoS2VybmVsLmVsZW0oa2V5d29yZCwgMCkgPT0ga2V5KSB7XG4gICAgICByZXR1cm4gS2VybmVsLmVsZW0oa2V5d29yZCwgMSk7XG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIHRoZV9kZWZhdWx0O1xufTtcblxubGV0IEFnZW50ID0ge307XG5cbkFnZW50LnN0YXJ0ID0gZnVuY3Rpb24gKGZ1biwgb3B0aW9ucyA9IFtdKSB7XG4gIGNvbnN0IG5hbWUgPSBLZXl3b3JkLmhhc19rZXlfX3FtX18ob3B0aW9ucywgS2VybmVsLlNwZWNpYWxGb3Jtcy5hdG9tKCduYW1lJykpID8gS2V5d29yZC5nZXQob3B0aW9ucywgS2VybmVsLlNwZWNpYWxGb3Jtcy5hdG9tKCduYW1lJykpIDogU3ltYm9sKCk7XG5cbiAgc2VsZi5wb3N0X29mZmljZS5hZGRfbWFpbGJveChuYW1lKTtcbiAgc2VsZi5wb3N0X29mZmljZS5zZW5kKG5hbWUsIGZ1bigpKTtcblxuICByZXR1cm4gS2VybmVsLlNwZWNpYWxGb3Jtcy50dXBsZShLZXJuZWwuU3BlY2lhbEZvcm1zLmF0b20oJ29rJyksIG5hbWUpO1xufTtcblxuQWdlbnQuc3RvcCA9IGZ1bmN0aW9uIChhZ2VudCwgdGltZW91dCA9IDUwMDApIHtcbiAgc2VsZi5wb3N0X29mZmljZS5yZW1vdmVfbWFpbGJveChhZ2VudCk7XG4gIHJldHVybiBLZXJuZWwuU3BlY2lhbEZvcm1zLmF0b20oJ29rJyk7XG59O1xuXG5BZ2VudC51cGRhdGUgPSBmdW5jdGlvbiAoYWdlbnQsIGZ1biwgdGltZW91dCA9IDUwMDApIHtcblxuICBjb25zdCBjdXJyZW50X3N0YXRlID0gc2VsZi5wb3N0X29mZmljZS5yZWNlaXZlKGFnZW50KTtcbiAgc2VsZi5wb3N0X29mZmljZS5zZW5kKGFnZW50LCBmdW4oY3VycmVudF9zdGF0ZSkpO1xuXG4gIHJldHVybiBLZXJuZWwuU3BlY2lhbEZvcm1zLmF0b20oJ29rJyk7XG59O1xuXG5BZ2VudC5nZXQgPSBmdW5jdGlvbiAoYWdlbnQsIGZ1biwgdGltZW91dCA9IDUwMDApIHtcbiAgcmV0dXJuIGZ1bihzZWxmLnBvc3Rfb2ZmaWNlLnBlZWsoYWdlbnQpKTtcbn07XG5cbkFnZW50LmdldF9hbmRfdXBkYXRlID0gZnVuY3Rpb24gKGFnZW50LCBmdW4sIHRpbWVvdXQgPSA1MDAwKSB7XG5cbiAgY29uc3QgZ2V0X2FuZF91cGRhdGVfdHVwbGUgPSBmdW4oc2VsZi5wb3N0X29mZmljZS5yZWNlaXZlKGFnZW50KSk7XG4gIHNlbGYucG9zdF9vZmZpY2Uuc2VuZChhZ2VudCwgS2VybmVsLmVsZW0oZ2V0X2FuZF91cGRhdGVfdHVwbGUsIDEpKTtcblxuICByZXR1cm4gS2VybmVsLmVsZW0oZ2V0X2FuZF91cGRhdGVfdHVwbGUsIDApO1xufTtcblxuLy9odHRwczovL2RldmVsb3Blci5tb3ppbGxhLm9yZy9lbi1VUy9kb2NzL1dlYi9BUEkvV2luZG93QmFzZTY0L0Jhc2U2NF9lbmNvZGluZ19hbmRfZGVjb2RpbmcjU29sdXRpb25fMl8lRTIlODAlOTNfcmV3cml0ZV90aGVfRE9Nc19hdG9iKClfYW5kX2J0b2EoKV91c2luZ19KYXZhU2NyaXB0J3NfVHlwZWRBcnJheXNfYW5kX1VURi04XG5mdW5jdGlvbiBiNjRFbmNvZGVVbmljb2RlKHN0cikge1xuICByZXR1cm4gYnRvYShlbmNvZGVVUklDb21wb25lbnQoc3RyKS5yZXBsYWNlKC8lKFswLTlBLUZdezJ9KS9nLCBmdW5jdGlvbiAobWF0Y2gsIHAxKSB7XG4gICAgcmV0dXJuIFN0cmluZy5mcm9tQ2hhckNvZGUoJzB4JyArIHAxKTtcbiAgfSkpO1xufVxuXG5mdW5jdGlvbiBlbmNvZGU2NChkYXRhKSB7XG4gIHJldHVybiBiNjRFbmNvZGVVbmljb2RlKGRhdGEpO1xufVxuXG5mdW5jdGlvbiBkZWNvZGU2NChkYXRhKSB7XG4gIHRyeSB7XG4gICAgcmV0dXJuIEtlcm5lbC5TcGVjaWFsRm9ybXMudHVwbGUoS2VybmVsLlNwZWNpYWxGb3Jtcy5hdG9tKCdvaycpLCBhdG9iKGRhdGEpKTtcbiAgfSBjYXRjaCAoZSkge1xuICAgIHJldHVybiBLZXJuZWwuU3BlY2lhbEZvcm1zLmF0b20oJ2Vycm9yJyk7XG4gIH1cbiAgcmV0dXJuIGJ0b2EoZGF0YSk7XG59XG5cbmZ1bmN0aW9uIGRlY29kZTY0X19lbV9fKGRhdGEpIHtcbiAgcmV0dXJuIGF0b2IoZGF0YSk7XG59XG5cbnZhciBCYXNlID0ge1xuICBlbmNvZGU2NCxcbiAgZGVjb2RlNjQsXG4gIGRlY29kZTY0X19lbV9fXG59O1xuXG5mdW5jdGlvbiBibm90KGV4cHIpIHtcbiAgcmV0dXJuIH5leHByO1xufVxuXG5mdW5jdGlvbiBiYW5kKGxlZnQsIHJpZ2h0KSB7XG4gIHJldHVybiBsZWZ0ICYgcmlnaHQ7XG59XG5cbmZ1bmN0aW9uIGJvcihsZWZ0LCByaWdodCkge1xuICByZXR1cm4gbGVmdCB8IHJpZ2h0O1xufVxuXG5mdW5jdGlvbiBic2wobGVmdCwgcmlnaHQpIHtcbiAgcmV0dXJuIGxlZnQgPDwgcmlnaHQ7XG59XG5cbmZ1bmN0aW9uIGJzcihsZWZ0LCByaWdodCkge1xuICByZXR1cm4gbGVmdCA+PiByaWdodDtcbn1cblxuZnVuY3Rpb24gYnhvcihsZWZ0LCByaWdodCkge1xuICByZXR1cm4gbGVmdCBeIHJpZ2h0O1xufVxuXG52YXIgQml0d2lzZSA9IHtcbiAgYm5vdCxcbiAgYmFuZCxcbiAgYm9yLFxuICBic2wsXG4gIGJzcixcbiAgYnhvclxufTtcblxubGV0IEVudW1lcmFibGUgPSBLZXJuZWwuZGVmcHJvdG9jb2woe1xuICBjb3VudDogZnVuY3Rpb24gKGNvbGxlY3Rpb24pIHt9LFxuICBtZW1iZXJfcW1hcmtfXzogZnVuY3Rpb24gKGNvbGxlY3Rpb24sIHZhbHVlKSB7fSxcbiAgcmVkdWNlOiBmdW5jdGlvbiAoY29sbGVjdGlvbiwgYWNjLCBmdW4pIHt9XG59KTtcblxubGV0IENvbGxlY3RhYmxlID0gS2VybmVsLmRlZnByb3RvY29sKHtcbiAgaW50bzogZnVuY3Rpb24gKGNvbGxlY3RhYmxlKSB7fVxufSk7XG5cbmxldCBJbnNwZWN0ID0gS2VybmVsLmRlZnByb3RvY29sKHtcbiAgaW5zcGVjdDogZnVuY3Rpb24gKHRoaW5nLCBvcHRzKSB7fVxufSk7XG5cbmZ1bmN0aW9uIF9fX25ld19fKCkge1xuICByZXR1cm4gU3BlY2lhbEZvcm1zLm1hcCh7fSk7XG59XG5cbmZ1bmN0aW9uIGtleXMobWFwKSB7XG4gIHJldHVybiBPYmplY3Qua2V5cyhtYXApO1xufVxuXG5mdW5jdGlvbiBfX3NpemUobWFwKSB7XG4gIHJldHVybiBrZXlzKG1hcCkubGVuZ3RoO1xufVxuXG5mdW5jdGlvbiBfX3RvX2xpc3QobWFwKSB7XG4gIGxldCBtYXBfa2V5cyA9IGtleXMobWFwKTtcbiAgbGV0IGxpc3QgPSBbXTtcblxuICBmb3IgKGxldCBrZXkgb2YgbWFwX2tleXMpIHtcbiAgICBsaXN0LnB1c2goU3BlY2lhbEZvcm1zLnR1cGxlKGtleSwgbWFwW2tleV0pKTtcbiAgfVxuXG4gIHJldHVybiBTcGVjaWFsRm9ybXMubGlzdCguLi5saXN0KTtcbn1cblxuZnVuY3Rpb24gdmFsdWVzKG1hcCkge1xuICBsZXQgbWFwX2tleXMgPSBrZXlzKG1hcCk7XG4gIGxldCBsaXN0ID0gW107XG5cbiAgZm9yIChsZXQga2V5IG9mIG1hcF9rZXlzKSB7XG4gICAgbGlzdC5wdXNoKG1hcFtrZXldKTtcbiAgfVxuXG4gIHJldHVybiBTcGVjaWFsRm9ybXMubGlzdCguLi5saXN0KTtcbn1cblxuZnVuY3Rpb24gZnJvbV9zdHJ1Y3Qoc3RydWN0KSB7XG4gIGxldCBtYXAgPSBPYmplY3QuYXNzaWduKHt9LCBzdHJ1Y3QpO1xuICBkZWxldGUgbWFwW1N5bWJvbC5mb3IoXCJfX3N0cnVjdF9fXCIpXTtcblxuICByZXR1cm4gU3BlY2lhbEZvcm1zLm1hcChtYXApO1xufVxuXG5mdW5jdGlvbiBfX19fZGVsZXRlX18obWFwLCBrZXkpIHtcbiAgbGV0IG5ld19tYXAgPSBPYmplY3QuYXNzaWduKHt9LCBtYXApO1xuXG4gIGRlbGV0ZSBuZXdfbWFwW2tleV07XG5cbiAgcmV0dXJuIFNwZWNpYWxGb3Jtcy5tYXAobmV3X21hcCk7XG59XG5cbmZ1bmN0aW9uIGRyb3AobWFwLCBrZXlzKSB7XG4gIGxldCBuZXdfbWFwID0gT2JqZWN0LmFzc2lnbih7fSwgbWFwKTtcblxuICBmb3IgKGxldCBrZXkgb2Yga2V5cykge1xuICAgIGRlbGV0ZSBuZXdfbWFwW2tleV07XG4gIH1cblxuICByZXR1cm4gU3BlY2lhbEZvcm1zLm1hcChuZXdfbWFwKTtcbn1cblxuZnVuY3Rpb24gX19lcXVhbF9fcW1hcmtfXyhtYXAxLCBtYXAyKSB7XG4gIHJldHVybiBtYXAxID09PSBtYXAyO1xufVxuXG5mdW5jdGlvbiBmZXRjaF9fZW1hcmtfXyhtYXAsIGtleSkge1xuICBpZiAoa2V5IGluIG1hcCkge1xuICAgIHJldHVybiBtYXBba2V5XTtcbiAgfVxuXG4gIHRocm93IG5ldyBFcnJvcihcIktleSBub3QgZm91bmQuXCIpO1xufVxuXG5mdW5jdGlvbiBmZXRjaChtYXAsIGtleSkge1xuICBpZiAoa2V5IGluIG1hcCkge1xuICAgIHJldHVybiBTcGVjaWFsRm9ybXMudHVwbGUoU3BlY2lhbEZvcm1zLmF0b20oXCJva1wiKSwgbWFwW2tleV0pO1xuICB9XG5cbiAgcmV0dXJuIFNwZWNpYWxGb3Jtcy5hdG9tKFwiZXJyb3JcIik7XG59XG5cbmZ1bmN0aW9uIGhhc19rZXlfX3FtYXJrX18obWFwLCBrZXkpIHtcbiAgcmV0dXJuIGtleSBpbiBtYXA7XG59XG5cbmZ1bmN0aW9uIG1lcmdlKG1hcDEsIG1hcDIpIHtcbiAgcmV0dXJuIFNwZWNpYWxGb3Jtcy5tYXBfdXBkYXRlKG1hcDEsIG1hcDIpO1xufVxuXG5mdW5jdGlvbiBzcGxpdChtYXAsIGtleXMpIHtcbiAgbGV0IHNwbGl0MSA9IHt9O1xuICBsZXQgc3BsaXQyID0ge307XG5cbiAgZm9yIChsZXQga2V5IG9mIE9iamVjdC5rZXlzKG1hcCkpIHtcbiAgICBpZiAoa2V5cy5pbmRleE9mKGtleSkgPiAtMSkge1xuICAgICAgc3BsaXQxW2tleV0gPSBtYXBba2V5XTtcbiAgICB9IGVsc2Uge1xuICAgICAgc3BsaXQyW2tleV0gPSBtYXBba2V5XTtcbiAgICB9XG4gIH1cblxuICByZXR1cm4gU3BlY2lhbEZvcm1zLnR1cGxlKFNwZWNpYWxGb3Jtcy5tYXAoc3BsaXQxKSwgU3BlY2lhbEZvcm1zLm1hcChzcGxpdDIpKTtcbn1cblxuZnVuY3Rpb24gdGFrZShtYXAsIGtleXMpIHtcbiAgbGV0IHNwbGl0MSA9IHt9O1xuXG4gIGZvciAobGV0IGtleSBvZiBPYmplY3Qua2V5cyhtYXApKSB7XG4gICAgaWYgKGtleXMuaW5kZXhPZihrZXkpID4gLTEpIHtcbiAgICAgIHNwbGl0MVtrZXldID0gbWFwW2tleV07XG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIFNwZWNpYWxGb3Jtcy5tYXAoc3BsaXQxKTtcbn1cblxuZnVuY3Rpb24gZHJvcChtYXAsIGtleXMpIHtcbiAgbGV0IHNwbGl0MSA9IHt9O1xuXG4gIGZvciAobGV0IGtleSBvZiBPYmplY3Qua2V5cyhtYXApKSB7XG4gICAgaWYgKGtleXMuaW5kZXhPZihrZXkpID09PSAtMSkge1xuICAgICAgc3BsaXQxW2tleV0gPSBtYXBba2V5XTtcbiAgICB9XG4gIH1cblxuICByZXR1cm4gU3BlY2lhbEZvcm1zLm1hcChzcGxpdDEpO1xufVxuXG5mdW5jdGlvbiBwdXRfbmV3KG1hcCwga2V5LCB2YWx1ZSkge1xuICBpZiAoa2V5IGluIG1hcCkge1xuICAgIHJldHVybiBtYXA7XG4gIH1cblxuICBsZXQgbmV3X21hcCA9IE9iamVjdC5hc3NpZ24oe30sIG1hcCk7XG4gIG5ld19tYXBba2V5XSA9IHZhbHVlO1xuXG4gIHJldHVybiBTcGVjaWFsRm9ybXMubWFwKG5ld19tYXApO1xufVxuXG5mdW5jdGlvbiBwdXRfbmV3X2xhenkobWFwLCBrZXksIGZ1bikge1xuICBpZiAoa2V5IGluIG1hcCkge1xuICAgIHJldHVybiBtYXA7XG4gIH1cblxuICBsZXQgbmV3X21hcCA9IE9iamVjdC5hc3NpZ24oe30sIG1hcCk7XG4gIG5ld19tYXBba2V5XSA9IGZ1bigpO1xuXG4gIHJldHVybiBTcGVjaWFsRm9ybXMubWFwKG5ld19tYXApO1xufVxuXG5mdW5jdGlvbiBnZXRfYW5kX3VwZGF0ZShtYXAsIGtleSwgZnVuKSB7XG4gIGlmIChrZXkgaW4gbWFwKSB7XG4gICAgcmV0dXJuIG1hcDtcbiAgfVxuXG4gIGxldCBuZXdfbWFwID0gT2JqZWN0LmFzc2lnbih7fSwgbWFwKTtcbiAgbmV3X21hcFtrZXldID0gZnVuKG1hcFtrZXldKTtcblxuICByZXR1cm4gU3BlY2lhbEZvcm1zLm1hcChuZXdfbWFwKTtcbn1cblxuZnVuY3Rpb24gcG9wX2xhenkobWFwLCBrZXksIGZ1bikge1xuICBpZiAoIWtleSBpbiBtYXApIHtcbiAgICByZXR1cm4gU3BlY2lhbEZvcm1zLnR1cGxlKGZ1bigpLCBtYXApO1xuICB9XG5cbiAgbGV0IG5ld19tYXAgPSBPYmplY3QuYXNzaWduKHt9LCBtYXApO1xuICBsZXQgdmFsdWUgPSBmdW4obmV3X21hcFtrZXldKTtcbiAgZGVsZXRlIG5ld19tYXBba2V5XTtcblxuICByZXR1cm4gU3BlY2lhbEZvcm1zLnR1cGxlKHZhbHVlLCBuZXdfbWFwKTtcbn1cblxuZnVuY3Rpb24gcG9wKG1hcCwga2V5LCBfZGVmYXVsdCA9IG51bGwpIHtcbiAgaWYgKCFrZXkgaW4gbWFwKSB7XG4gICAgcmV0dXJuIFNwZWNpYWxGb3Jtcy50dXBsZShfZGVmYXVsdCwgbWFwKTtcbiAgfVxuXG4gIGxldCBuZXdfbWFwID0gT2JqZWN0LmFzc2lnbih7fSwgbWFwKTtcbiAgbGV0IHZhbHVlID0gbmV3X21hcFtrZXldO1xuICBkZWxldGUgbmV3X21hcFtrZXldO1xuXG4gIHJldHVybiBTcGVjaWFsRm9ybXMudHVwbGUodmFsdWUsIG5ld19tYXApO1xufVxuXG5mdW5jdGlvbiBnZXRfbGF6eShtYXAsIGtleSwgZnVuKSB7XG4gIGlmICgha2V5IGluIG1hcCkge1xuICAgIHJldHVybiBmdW4oKTtcbiAgfVxuXG4gIHJldHVybiBmdW4obWFwW2tleV0pO1xufVxuXG5mdW5jdGlvbiBnZXQobWFwLCBrZXksIF9kZWZhdWx0ID0gbnVsbCkge1xuICBpZiAoIWtleSBpbiBtYXApIHtcbiAgICByZXR1cm4gX2RlZmF1bHQ7XG4gIH1cblxuICByZXR1cm4gbWFwW2tleV07XG59XG5cbmZ1bmN0aW9uIF9fcHV0KG1hcCwga2V5LCB2YWwpIHtcbiAgbGV0IG5ld19tYXAgPSBPYmplY3Qoe30sIG1hcCk7XG4gIG5ld19tYXBba2V5XSA9IHZhbDtcblxuICByZXR1cm4gU3BlY2lhbEZvcm1zLm1hcChuZXdfbWFwKTtcbn1cblxuZnVuY3Rpb24gdXBkYXRlX19lbWFya19fKG1hcCwga2V5LCBmdW4pIHtcbiAgaWYgKCFrZXkgaW4gbWFwKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKFwiS2V5IG5vdCBmb3VuZFwiKTtcbiAgfVxuXG4gIGxldCBuZXdfbWFwID0gT2JqZWN0KHt9LCBtYXApO1xuICBuZXdfbWFwW2tleV0gPSBmdW4obWFwW2tleV0pO1xuXG4gIHJldHVybiBTcGVjaWFsRm9ybXMubWFwKG5ld19tYXApO1xufVxuXG5mdW5jdGlvbiBfX3VwZGF0ZShtYXAsIGtleSwgaW5pdGlhbCwgZnVuKSB7XG4gIGxldCBuZXdfbWFwID0gT2JqZWN0KHt9LCBtYXApO1xuXG4gIGlmICgha2V5IGluIG1hcCkge1xuICAgIG5ld19tYXBba2V5XSA9IGluaXRpYWw7XG4gIH0gZWxzZSB7XG4gICAgbmV3X21hcFtrZXldID0gZnVuKG1hcFtrZXldKTtcbiAgfVxuXG4gIHJldHVybiBTcGVjaWFsRm9ybXMubWFwKG5ld19tYXApO1xufVxuXG52YXIgX01hcCA9IHtcbiAgbmV3OiBfX19uZXdfXyxcbiAga2V5cyxcbiAgc2l6ZTogX19zaXplLFxuICB0b19saXN0OiBfX3RvX2xpc3QsXG4gIHZhbHVlcyxcbiAgZnJvbV9zdHJ1Y3QsXG4gIGRlbGV0ZTogX19fX2RlbGV0ZV9fLFxuICBkcm9wLFxuICBlcXVhbF9fcW1hcmtfXzogX19lcXVhbF9fcW1hcmtfXyxcbiAgZmV0Y2hfX2VtYXJrX18sXG4gIGZldGNoLFxuICBoYXNfa2V5X19xbWFya19fLFxuICBzcGxpdCxcbiAgdGFrZSxcbiAgcHV0X25ldyxcbiAgcHV0X25ld19sYXp5LFxuICBnZXRfYW5kX3VwZGF0ZSxcbiAgcG9wX2xhenksXG4gIHBvcCxcbiAgZ2V0X2xhenksXG4gIGdldCxcbiAgcHV0OiBfX3B1dCxcbiAgdXBkYXRlX19lbWFya19fLFxuICB1cGRhdGU6IF9fdXBkYXRlXG59O1xuXG5mdW5jdGlvbiBfX25ld19fKCkge1xuICByZXR1cm4gU3BlY2lhbEZvcm1zLm1hcCh7IFtTeW1ib2wuZm9yKCdfX3N0cnVjdF9fJyldOiBTeW1ib2wuZm9yKCdNYXBTZXQnKSwgc2V0OiBTcGVjaWFsRm9ybXMubGlzdCgpIH0pO1xufVxuXG5mdW5jdGlvbiBfc2l6ZShtYXApIHtcbiAgcmV0dXJuIG1hcC5zZXQubGVuZ3RoO1xufVxuXG5mdW5jdGlvbiBfdG9fbGlzdChtYXApIHtcbiAgcmV0dXJuIG1hcC5zZXQ7XG59XG5cbmZ1bmN0aW9uIF9fX2RlbGV0ZV9fKHNldCwgdGVybSkge1xuICBsZXQgbmV3X2xpc3QgPSBMaXN0LmRlbGV0ZShzZXQuc2V0LCB0ZXJtKTtcblxuICBsZXQgbmV3X21hcCA9IE9iamVjdC5hc3NpZ24oe30sIHNldCk7XG4gIG5ld19tYXAuc2V0ID0gbmV3X2xpc3Q7XG4gIHJldHVybiBTcGVjaWFsRm9ybXMubWFwKG5ld19tYXApO1xufVxuXG5mdW5jdGlvbiBfcHV0KHNldCwgdGVybSkge1xuICBpZiAoc2V0LnNldC5pbmRleE9mKHRlcm0pID09PSAtMSkge1xuICAgIGxldCBuZXdfbGlzdCA9IExpc3QuYXBwZW5kKHNldC5zZXQsIHRlcm0pO1xuXG4gICAgbGV0IG5ld19tYXAgPSBPYmplY3QuYXNzaWduKHt9LCBzZXQpO1xuICAgIG5ld19tYXAuc2V0ID0gbmV3X2xpc3Q7XG4gICAgcmV0dXJuIFNwZWNpYWxGb3Jtcy5tYXAobmV3X21hcCk7XG4gIH1cblxuICByZXR1cm4gc2V0O1xufVxuXG5mdW5jdGlvbiBfZGlmZmVyZW5jZShzZXQxLCBzZXQyKSB7XG4gIGxldCBuZXdfbWFwID0gT2JqZWN0LmFzc2lnbih7fSwgc2V0MSk7XG5cbiAgZm9yIChsZXQgdmFsIG9mIHNldDEuc2V0KSB7XG4gICAgaWYgKF9tZW1iZXJfX3FtYXJrX18oc2V0MiwgdmFsKSkge1xuICAgICAgbmV3X21hcC5zZXQgPSBMaXN0LmRlbGV0ZShuZXdfbWFwLnNldCwgdmFsKTtcbiAgICB9XG4gIH1cblxuICByZXR1cm4gU3BlY2lhbEZvcm1zLm1hcChuZXdfbWFwKTtcbn1cblxuZnVuY3Rpb24gX2ludGVyc2VjdGlvbihzZXQxLCBzZXQyKSB7XG4gIGxldCBuZXdfbWFwID0gT2JqZWN0LmFzc2lnbih7fSwgc2V0MSk7XG5cbiAgZm9yIChsZXQgdmFsIG9mIHNldDEuc2V0KSB7XG4gICAgaWYgKCFfbWVtYmVyX19xbWFya19fKHNldDIsIHZhbCkpIHtcbiAgICAgIG5ld19tYXAuc2V0ID0gTGlzdC5kZWxldGUobmV3X21hcC5zZXQsIHZhbCk7XG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIFNwZWNpYWxGb3Jtcy5tYXAobmV3X21hcCk7XG59XG5cbmZ1bmN0aW9uIF91bmlvbihzZXQxLCBzZXQyKSB7XG4gIGxldCBuZXdfbWFwID0gc2V0MTtcblxuICBmb3IgKGxldCB2YWwgb2Ygc2V0Mi5zZXQpIHtcbiAgICBuZXdfbWFwID0gX3B1dChuZXdfbWFwLCB2YWwpO1xuICB9XG5cbiAgcmV0dXJuIFNwZWNpYWxGb3Jtcy5tYXAobmV3X21hcCk7XG59XG5cbmZ1bmN0aW9uIF9kaXNqb2luX19xbWFya19fKHNldDEsIHNldDIpIHtcbiAgZm9yIChsZXQgdmFsIG9mIHNldDEuc2V0KSB7XG4gICAgaWYgKF9tZW1iZXJfX3FtYXJrX18oc2V0MiwgdmFsKSkge1xuICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH1cbiAgfVxuXG4gIHJldHVybiB0cnVlO1xufVxuXG5mdW5jdGlvbiBfbWVtYmVyX19xbWFya19fKHNldCwgdmFsdWUpIHtcbiAgcmV0dXJuIHNldC5zZXQuaW5kZXhPZih2YWx1ZSkgPj0gMDtcbn1cblxuZnVuY3Rpb24gX2VxdWFsX19xbWFya19fKHNldDEsIHNldDIpIHtcbiAgcmV0dXJuIHNldDEuc2V0ID09PSBzZXQyLnNldDtcbn1cblxuZnVuY3Rpb24gX3N1YnNldF9fcW1hcmtfXyhzZXQxLCBzZXQyKSB7XG4gIGZvciAobGV0IHZhbCBvZiBzZXQxLnNldCkge1xuICAgIGlmICghX21lbWJlcl9fcW1hcmtfXyhzZXQyLCB2YWwpKSB7XG4gICAgICByZXR1cm4gZmFsc2U7XG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIHRydWU7XG59XG5cbnZhciBNYXBTZXQgPSB7XG4gIG5ldzogX19uZXdfXyxcbiAgc2l6ZTogX3NpemUsXG4gIHRvX2xpc3Q6IF90b19saXN0LFxuICBkaXNqb2luX19xbWFya19fOiBfZGlzam9pbl9fcW1hcmtfXyxcbiAgZGVsZXRlOiBfX19kZWxldGVfXyxcbiAgc3Vic2V0X19xbWFya19fOiBfc3Vic2V0X19xbWFya19fLFxuICBlcXVhbF9fcW1hcmtfXzogX2VxdWFsX19xbWFya19fLFxuICBtZW1iZXJfX3FtYXJrX186IF9tZW1iZXJfX3FtYXJrX18sXG4gIHB1dDogX3B1dCxcbiAgdW5pb246IF91bmlvbixcbiAgaW50ZXJzZWN0aW9uOiBfaW50ZXJzZWN0aW9uLFxuICBkaWZmZXJlbmNlOiBfZGlmZmVyZW5jZVxufTtcblxuZnVuY3Rpb24gc2l6ZShtYXApIHtcbiAgcmV0dXJuIE1hcFNldC5zaXplKG1hcCk7XG59XG5cbmZ1bmN0aW9uIHRvX2xpc3QobWFwKSB7XG4gIHJldHVybiBNYXBTZXQudG9fbGlzdChtYXApO1xufVxuXG5mdW5jdGlvbiBfX2RlbGV0ZV9fKHNldCwgdGVybSkge1xuICByZXR1cm4gTWFwU2V0LmRlbGV0ZShzZXQsIHRlcm0pO1xufVxuXG5mdW5jdGlvbiBwdXQoc2V0LCB0ZXJtKSB7XG4gIHJldHVybiBNYXBTZXQucHV0KHNldCwgdGVybSk7XG59XG5cbmZ1bmN0aW9uIGRpZmZlcmVuY2Uoc2V0MSwgc2V0Mikge1xuICByZXR1cm4gTWFwU2V0LmRpZmZlcmVuY2Uoc2V0MSwgc2V0Mik7XG59XG5cbmZ1bmN0aW9uIGludGVyc2VjdGlvbihzZXQxLCBzZXQyKSB7XG4gIHJldHVybiBNYXBTZXQuaW50ZXJzZWN0aW9uKHNldDEsIHNldDIpO1xufVxuXG5mdW5jdGlvbiB1bmlvbihzZXQxLCBzZXQyKSB7XG4gIHJldHVybiBNYXBTZXQudW5pb24oc2V0MSwgc2V0Mik7XG59XG5cbmZ1bmN0aW9uIGRpc2pvaW5fX3FtYXJrX18oc2V0MSwgc2V0Mikge1xuICByZXR1cm4gTWFwU2V0LmRpc2pvaW5fX3FtYXJrX18oc2V0MSwgc2V0Mik7XG59XG5cbmZ1bmN0aW9uIG1lbWJlcl9fcW1hcmtfXyhzZXQsIHZhbHVlKSB7XG4gIHJldHVybiBNYXBTZXQubWVtYmVyX19xbWFya19fKHNldDEsIHNldDIpO1xufVxuXG5mdW5jdGlvbiBlcXVhbF9fcW1hcmtfXyhzZXQxLCBzZXQyKSB7XG4gIHJldHVybiBNYXBTZXQuZXF1YWxfX3FtYXJrX18oc2V0MSwgc2V0Mik7XG59XG5cbmZ1bmN0aW9uIHN1YnNldF9fcW1hcmtfXyhzZXQxLCBzZXQyKSB7XG4gIHJldHVybiBNYXBTZXQuc3Vic2V0X19xbWFya19fKHNldDEsIHNldDIpO1xufVxuXG52YXIgX1NldCA9IHtcbiAgc2l6ZSxcbiAgdG9fbGlzdCxcbiAgZGlzam9pbl9fcW1hcmtfXyxcbiAgZGVsZXRlOiBfX2RlbGV0ZV9fLFxuICBzdWJzZXRfX3FtYXJrX18sXG4gIGVxdWFsX19xbWFya19fLFxuICBtZW1iZXJfX3FtYXJrX18sXG4gIHB1dCxcbiAgdW5pb24sXG4gIGludGVyc2VjdGlvbixcbiAgZGlmZmVyZW5jZVxufTtcblxubGV0IHZpcnR1YWxEb20gPSAoZnVuY3Rpb24gKGUpIHtcbiAgICByZXR1cm4gZSgpO1xufSkoZnVuY3Rpb24gKCkge1xuICAgIHZhciBkZWZpbmUsIG1vZHVsZSwgZXhwb3J0cztcbiAgICByZXR1cm4gKGZ1bmN0aW9uIGUodCwgbiwgcikge1xuICAgICAgICBmdW5jdGlvbiBzKG8sIHUpIHtcbiAgICAgICAgICAgIGlmICghbltvXSkge1xuICAgICAgICAgICAgICAgIGlmICghdFtvXSkge1xuICAgICAgICAgICAgICAgICAgICB2YXIgYSA9IHR5cGVvZiByZXF1aXJlID09IFwiZnVuY3Rpb25cIiAmJiByZXF1aXJlO1xuICAgICAgICAgICAgICAgICAgICBpZiAoIXUgJiYgYSkgcmV0dXJuIGEobywgITApO1xuICAgICAgICAgICAgICAgICAgICBpZiAoaSkgcmV0dXJuIGkobywgITApO1xuICAgICAgICAgICAgICAgICAgICB2YXIgZiA9IG5ldyBFcnJvcihcIkNhbm5vdCBmaW5kIG1vZHVsZSAnXCIgKyBvICsgXCInXCIpO1xuICAgICAgICAgICAgICAgICAgICB0aHJvdyAoZi5jb2RlID0gXCJNT0RVTEVfTk9UX0ZPVU5EXCIsIGYpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB2YXIgbCA9IG5bb10gPSB7XG4gICAgICAgICAgICAgICAgICAgIGV4cG9ydHM6IHt9XG4gICAgICAgICAgICAgICAgfTtcbiAgICAgICAgICAgICAgICB0W29dWzBdLmNhbGwobC5leHBvcnRzLCBmdW5jdGlvbiAoZSkge1xuICAgICAgICAgICAgICAgICAgICB2YXIgbiA9IHRbb11bMV1bZV07XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBzKG4gPyBuIDogZSk7XG4gICAgICAgICAgICAgICAgfSwgbCwgbC5leHBvcnRzLCBlLCB0LCBuLCByKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJldHVybiBuW29dLmV4cG9ydHM7XG4gICAgICAgIH1cbiAgICAgICAgdmFyIGkgPSB0eXBlb2YgcmVxdWlyZSA9PSBcImZ1bmN0aW9uXCIgJiYgcmVxdWlyZTtcbiAgICAgICAgZm9yICh2YXIgbyA9IDA7IG8gPCByLmxlbmd0aDsgbysrKSBzKHJbb10pO1xuICAgICAgICByZXR1cm4gcztcbiAgICB9KSh7XG4gICAgICAgIDE6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG5cbiAgICAgICAgICAgIHZhciBjcmVhdGVFbGVtZW50ID0gcmVxdWlyZShcIi4vdmRvbS9jcmVhdGUtZWxlbWVudC5qc1wiKTtcblxuICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBjcmVhdGVFbGVtZW50O1xuICAgICAgICB9LCB7IFwiLi92ZG9tL2NyZWF0ZS1lbGVtZW50LmpzXCI6IDE1IH1dLCAyOiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge1xuICAgICAgICAgICAgdmFyIGRpZmYgPSByZXF1aXJlKFwiLi92dHJlZS9kaWZmLmpzXCIpO1xuXG4gICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IGRpZmY7XG4gICAgICAgIH0sIHsgXCIuL3Z0cmVlL2RpZmYuanNcIjogMzUgfV0sIDM6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICB2YXIgaCA9IHJlcXVpcmUoXCIuL3ZpcnR1YWwtaHlwZXJzY3JpcHQvaW5kZXguanNcIik7XG5cbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gaDtcbiAgICAgICAgfSwgeyBcIi4vdmlydHVhbC1oeXBlcnNjcmlwdC9pbmRleC5qc1wiOiAyMiB9XSwgNDogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHtcbiAgICAgICAgICAgIHZhciBkaWZmID0gcmVxdWlyZShcIi4vZGlmZi5qc1wiKTtcbiAgICAgICAgICAgIHZhciBwYXRjaCA9IHJlcXVpcmUoXCIuL3BhdGNoLmpzXCIpO1xuICAgICAgICAgICAgdmFyIGggPSByZXF1aXJlKFwiLi9oLmpzXCIpO1xuICAgICAgICAgICAgdmFyIGNyZWF0ZSA9IHJlcXVpcmUoXCIuL2NyZWF0ZS1lbGVtZW50LmpzXCIpO1xuICAgICAgICAgICAgdmFyIFZOb2RlID0gcmVxdWlyZShcIi4vdm5vZGUvdm5vZGUuanNcIik7XG4gICAgICAgICAgICB2YXIgVlRleHQgPSByZXF1aXJlKFwiLi92bm9kZS92dGV4dC5qc1wiKTtcblxuICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSB7XG4gICAgICAgICAgICAgICAgZGlmZjogZGlmZixcbiAgICAgICAgICAgICAgICBwYXRjaDogcGF0Y2gsXG4gICAgICAgICAgICAgICAgaDogaCxcbiAgICAgICAgICAgICAgICBjcmVhdGU6IGNyZWF0ZSxcbiAgICAgICAgICAgICAgICBWTm9kZTogVk5vZGUsXG4gICAgICAgICAgICAgICAgVlRleHQ6IFZUZXh0XG4gICAgICAgICAgICB9O1xuICAgICAgICB9LCB7IFwiLi9jcmVhdGUtZWxlbWVudC5qc1wiOiAxLCBcIi4vZGlmZi5qc1wiOiAyLCBcIi4vaC5qc1wiOiAzLCBcIi4vcGF0Y2guanNcIjogMTMsIFwiLi92bm9kZS92bm9kZS5qc1wiOiAzMSwgXCIuL3Zub2RlL3Z0ZXh0LmpzXCI6IDMzIH1dLCA1OiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge1xuICAgICAgICAgICAgLyohXG4gICAgICAgICAgICAgKiBDcm9zcy1Ccm93c2VyIFNwbGl0IDEuMS4xXG4gICAgICAgICAgICAgKiBDb3B5cmlnaHQgMjAwNy0yMDEyIFN0ZXZlbiBMZXZpdGhhbiA8c3RldmVubGV2aXRoYW4uY29tPlxuICAgICAgICAgICAgICogQXZhaWxhYmxlIHVuZGVyIHRoZSBNSVQgTGljZW5zZVxuICAgICAgICAgICAgICogRUNNQVNjcmlwdCBjb21wbGlhbnQsIHVuaWZvcm0gY3Jvc3MtYnJvd3NlciBzcGxpdCBtZXRob2RcbiAgICAgICAgICAgICAqL1xuXG4gICAgICAgICAgICAvKipcbiAgICAgICAgICAgICAqIFNwbGl0cyBhIHN0cmluZyBpbnRvIGFuIGFycmF5IG9mIHN0cmluZ3MgdXNpbmcgYSByZWdleCBvciBzdHJpbmcgc2VwYXJhdG9yLiBNYXRjaGVzIG9mIHRoZVxuICAgICAgICAgICAgICogc2VwYXJhdG9yIGFyZSBub3QgaW5jbHVkZWQgaW4gdGhlIHJlc3VsdCBhcnJheS4gSG93ZXZlciwgaWYgYHNlcGFyYXRvcmAgaXMgYSByZWdleCB0aGF0IGNvbnRhaW5zXG4gICAgICAgICAgICAgKiBjYXB0dXJpbmcgZ3JvdXBzLCBiYWNrcmVmZXJlbmNlcyBhcmUgc3BsaWNlZCBpbnRvIHRoZSByZXN1bHQgZWFjaCB0aW1lIGBzZXBhcmF0b3JgIGlzIG1hdGNoZWQuXG4gICAgICAgICAgICAgKiBGaXhlcyBicm93c2VyIGJ1Z3MgY29tcGFyZWQgdG8gdGhlIG5hdGl2ZSBgU3RyaW5nLnByb3RvdHlwZS5zcGxpdGAgYW5kIGNhbiBiZSB1c2VkIHJlbGlhYmx5XG4gICAgICAgICAgICAgKiBjcm9zcy1icm93c2VyLlxuICAgICAgICAgICAgICogQHBhcmFtIHtTdHJpbmd9IHN0ciBTdHJpbmcgdG8gc3BsaXQuXG4gICAgICAgICAgICAgKiBAcGFyYW0ge1JlZ0V4cHxTdHJpbmd9IHNlcGFyYXRvciBSZWdleCBvciBzdHJpbmcgdG8gdXNlIGZvciBzZXBhcmF0aW5nIHRoZSBzdHJpbmcuXG4gICAgICAgICAgICAgKiBAcGFyYW0ge051bWJlcn0gW2xpbWl0XSBNYXhpbXVtIG51bWJlciBvZiBpdGVtcyB0byBpbmNsdWRlIGluIHRoZSByZXN1bHQgYXJyYXkuXG4gICAgICAgICAgICAgKiBAcmV0dXJucyB7QXJyYXl9IEFycmF5IG9mIHN1YnN0cmluZ3MuXG4gICAgICAgICAgICAgKiBAZXhhbXBsZVxuICAgICAgICAgICAgICpcbiAgICAgICAgICAgICAqIC8vIEJhc2ljIHVzZVxuICAgICAgICAgICAgICogc3BsaXQoJ2EgYiBjIGQnLCAnICcpO1xuICAgICAgICAgICAgICogLy8gLT4gWydhJywgJ2InLCAnYycsICdkJ11cbiAgICAgICAgICAgICAqXG4gICAgICAgICAgICAgKiAvLyBXaXRoIGxpbWl0XG4gICAgICAgICAgICAgKiBzcGxpdCgnYSBiIGMgZCcsICcgJywgMik7XG4gICAgICAgICAgICAgKiAvLyAtPiBbJ2EnLCAnYiddXG4gICAgICAgICAgICAgKlxuICAgICAgICAgICAgICogLy8gQmFja3JlZmVyZW5jZXMgaW4gcmVzdWx0IGFycmF5XG4gICAgICAgICAgICAgKiBzcGxpdCgnLi53b3JkMSB3b3JkMi4uJywgLyhbYS16XSspKFxcZCspL2kpO1xuICAgICAgICAgICAgICogLy8gLT4gWycuLicsICd3b3JkJywgJzEnLCAnICcsICd3b3JkJywgJzInLCAnLi4nXVxuICAgICAgICAgICAgICovXG4gICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IChmdW5jdGlvbiBzcGxpdCh1bmRlZikge1xuXG4gICAgICAgICAgICAgICAgdmFyIG5hdGl2ZVNwbGl0ID0gU3RyaW5nLnByb3RvdHlwZS5zcGxpdCxcbiAgICAgICAgICAgICAgICAgICAgY29tcGxpYW50RXhlY05wY2cgPSAvKCk/Py8uZXhlYyhcIlwiKVsxXSA9PT0gdW5kZWYsXG5cbiAgICAgICAgICAgICAgICAvLyBOUENHOiBub25wYXJ0aWNpcGF0aW5nIGNhcHR1cmluZyBncm91cFxuICAgICAgICAgICAgICAgIHNlbGY7XG5cbiAgICAgICAgICAgICAgICBzZWxmID0gZnVuY3Rpb24gKHN0ciwgc2VwYXJhdG9yLCBsaW1pdCkge1xuICAgICAgICAgICAgICAgICAgICAvLyBJZiBgc2VwYXJhdG9yYCBpcyBub3QgYSByZWdleCwgdXNlIGBuYXRpdmVTcGxpdGBcbiAgICAgICAgICAgICAgICAgICAgaWYgKE9iamVjdC5wcm90b3R5cGUudG9TdHJpbmcuY2FsbChzZXBhcmF0b3IpICE9PSBcIltvYmplY3QgUmVnRXhwXVwiKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gbmF0aXZlU3BsaXQuY2FsbChzdHIsIHNlcGFyYXRvciwgbGltaXQpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIHZhciBvdXRwdXQgPSBbXSxcbiAgICAgICAgICAgICAgICAgICAgICAgIGZsYWdzID0gKHNlcGFyYXRvci5pZ25vcmVDYXNlID8gXCJpXCIgOiBcIlwiKSArIChzZXBhcmF0b3IubXVsdGlsaW5lID8gXCJtXCIgOiBcIlwiKSArIChzZXBhcmF0b3IuZXh0ZW5kZWQgPyBcInhcIiA6IFwiXCIpICsgKHNlcGFyYXRvci5zdGlja3kgPyBcInlcIiA6IFwiXCIpLFxuXG4gICAgICAgICAgICAgICAgICAgIC8vIEZpcmVmb3ggMytcbiAgICAgICAgICAgICAgICAgICAgbGFzdExhc3RJbmRleCA9IDAsXG5cbiAgICAgICAgICAgICAgICAgICAgLy8gTWFrZSBgZ2xvYmFsYCBhbmQgYXZvaWQgYGxhc3RJbmRleGAgaXNzdWVzIGJ5IHdvcmtpbmcgd2l0aCBhIGNvcHlcbiAgICAgICAgICAgICAgICAgICAgc2VwYXJhdG9yID0gbmV3IFJlZ0V4cChzZXBhcmF0b3Iuc291cmNlLCBmbGFncyArIFwiZ1wiKSxcbiAgICAgICAgICAgICAgICAgICAgICAgIHNlcGFyYXRvcjIsXG4gICAgICAgICAgICAgICAgICAgICAgICBtYXRjaCxcbiAgICAgICAgICAgICAgICAgICAgICAgIGxhc3RJbmRleCxcbiAgICAgICAgICAgICAgICAgICAgICAgIGxhc3RMZW5ndGg7XG4gICAgICAgICAgICAgICAgICAgIHN0ciArPSBcIlwiOyAvLyBUeXBlLWNvbnZlcnRcbiAgICAgICAgICAgICAgICAgICAgaWYgKCFjb21wbGlhbnRFeGVjTnBjZykge1xuICAgICAgICAgICAgICAgICAgICAgICAgLy8gRG9lc24ndCBuZWVkIGZsYWdzIGd5LCBidXQgdGhleSBkb24ndCBodXJ0XG4gICAgICAgICAgICAgICAgICAgICAgICBzZXBhcmF0b3IyID0gbmV3IFJlZ0V4cChcIl5cIiArIHNlcGFyYXRvci5zb3VyY2UgKyBcIiQoPyFcXFxccylcIiwgZmxhZ3MpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIC8qIFZhbHVlcyBmb3IgYGxpbWl0YCwgcGVyIHRoZSBzcGVjOlxuICAgICAgICAgICAgICAgICAgICAgKiBJZiB1bmRlZmluZWQ6IDQyOTQ5NjcyOTUgLy8gTWF0aC5wb3coMiwgMzIpIC0gMVxuICAgICAgICAgICAgICAgICAgICAgKiBJZiAwLCBJbmZpbml0eSwgb3IgTmFOOiAwXG4gICAgICAgICAgICAgICAgICAgICAqIElmIHBvc2l0aXZlIG51bWJlcjogbGltaXQgPSBNYXRoLmZsb29yKGxpbWl0KTsgaWYgKGxpbWl0ID4gNDI5NDk2NzI5NSkgbGltaXQgLT0gNDI5NDk2NzI5NjtcbiAgICAgICAgICAgICAgICAgICAgICogSWYgbmVnYXRpdmUgbnVtYmVyOiA0Mjk0OTY3Mjk2IC0gTWF0aC5mbG9vcihNYXRoLmFicyhsaW1pdCkpXG4gICAgICAgICAgICAgICAgICAgICAqIElmIG90aGVyOiBUeXBlLWNvbnZlcnQsIHRoZW4gdXNlIHRoZSBhYm92ZSBydWxlc1xuICAgICAgICAgICAgICAgICAgICAgKi9cbiAgICAgICAgICAgICAgICAgICAgbGltaXQgPSBsaW1pdCA9PT0gdW5kZWYgPyAtMSA+Pj4gMCA6IC8vIE1hdGgucG93KDIsIDMyKSAtIDFcbiAgICAgICAgICAgICAgICAgICAgbGltaXQgPj4+IDA7IC8vIFRvVWludDMyKGxpbWl0KVxuICAgICAgICAgICAgICAgICAgICB3aGlsZSAobWF0Y2ggPSBzZXBhcmF0b3IuZXhlYyhzdHIpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAvLyBgc2VwYXJhdG9yLmxhc3RJbmRleGAgaXMgbm90IHJlbGlhYmxlIGNyb3NzLWJyb3dzZXJcbiAgICAgICAgICAgICAgICAgICAgICAgIGxhc3RJbmRleCA9IG1hdGNoLmluZGV4ICsgbWF0Y2hbMF0ubGVuZ3RoO1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGxhc3RJbmRleCA+IGxhc3RMYXN0SW5kZXgpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBvdXRwdXQucHVzaChzdHIuc2xpY2UobGFzdExhc3RJbmRleCwgbWF0Y2guaW5kZXgpKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBGaXggYnJvd3NlcnMgd2hvc2UgYGV4ZWNgIG1ldGhvZHMgZG9uJ3QgY29uc2lzdGVudGx5IHJldHVybiBgdW5kZWZpbmVkYCBmb3JcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBub25wYXJ0aWNpcGF0aW5nIGNhcHR1cmluZyBncm91cHNcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoIWNvbXBsaWFudEV4ZWNOcGNnICYmIG1hdGNoLmxlbmd0aCA+IDEpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbWF0Y2hbMF0ucmVwbGFjZShzZXBhcmF0b3IyLCBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBmb3IgKHZhciBpID0gMTsgaSA8IGFyZ3VtZW50cy5sZW5ndGggLSAyOyBpKyspIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoYXJndW1lbnRzW2ldID09PSB1bmRlZikge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBtYXRjaFtpXSA9IHVuZGVmO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChtYXRjaC5sZW5ndGggPiAxICYmIG1hdGNoLmluZGV4IDwgc3RyLmxlbmd0aCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBBcnJheS5wcm90b3R5cGUucHVzaC5hcHBseShvdXRwdXQsIG1hdGNoLnNsaWNlKDEpKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgbGFzdExlbmd0aCA9IG1hdGNoWzBdLmxlbmd0aDtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBsYXN0TGFzdEluZGV4ID0gbGFzdEluZGV4O1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChvdXRwdXQubGVuZ3RoID49IGxpbWl0KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChzZXBhcmF0b3IubGFzdEluZGV4ID09PSBtYXRjaC5pbmRleCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNlcGFyYXRvci5sYXN0SW5kZXgrKzsgLy8gQXZvaWQgYW4gaW5maW5pdGUgbG9vcFxuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIGlmIChsYXN0TGFzdEluZGV4ID09PSBzdHIubGVuZ3RoKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAobGFzdExlbmd0aCB8fCAhc2VwYXJhdG9yLnRlc3QoXCJcIikpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBvdXRwdXQucHVzaChcIlwiKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIG91dHB1dC5wdXNoKHN0ci5zbGljZShsYXN0TGFzdEluZGV4KSk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIG91dHB1dC5sZW5ndGggPiBsaW1pdCA/IG91dHB1dC5zbGljZSgwLCBsaW1pdCkgOiBvdXRwdXQ7XG4gICAgICAgICAgICAgICAgfTtcblxuICAgICAgICAgICAgICAgIHJldHVybiBzZWxmO1xuICAgICAgICAgICAgfSkoKTtcbiAgICAgICAgfSwge31dLCA2OiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge30sIHt9XSwgNzogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHtcbiAgICAgICAgICAgIFwidXNlIHN0cmljdFwiO1xuXG4gICAgICAgICAgICB2YXIgT25lVmVyc2lvbkNvbnN0cmFpbnQgPSByZXF1aXJlKFwiaW5kaXZpZHVhbC9vbmUtdmVyc2lvblwiKTtcblxuICAgICAgICAgICAgdmFyIE1ZX1ZFUlNJT04gPSBcIjdcIjtcbiAgICAgICAgICAgIE9uZVZlcnNpb25Db25zdHJhaW50KFwiZXYtc3RvcmVcIiwgTVlfVkVSU0lPTik7XG5cbiAgICAgICAgICAgIHZhciBoYXNoS2V5ID0gXCJfX0VWX1NUT1JFX0tFWUBcIiArIE1ZX1ZFUlNJT047XG5cbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gRXZTdG9yZTtcblxuICAgICAgICAgICAgZnVuY3Rpb24gRXZTdG9yZShlbGVtKSB7XG4gICAgICAgICAgICAgICAgdmFyIGhhc2ggPSBlbGVtW2hhc2hLZXldO1xuXG4gICAgICAgICAgICAgICAgaWYgKCFoYXNoKSB7XG4gICAgICAgICAgICAgICAgICAgIGhhc2ggPSBlbGVtW2hhc2hLZXldID0ge307XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgcmV0dXJuIGhhc2g7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0sIHsgXCJpbmRpdmlkdWFsL29uZS12ZXJzaW9uXCI6IDkgfV0sIDg6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICAoZnVuY3Rpb24gKGdsb2JhbCkge1xuICAgICAgICAgICAgICAgIFwidXNlIHN0cmljdFwiO1xuXG4gICAgICAgICAgICAgICAgLypnbG9iYWwgd2luZG93LCBnbG9iYWwqL1xuXG4gICAgICAgICAgICAgICAgdmFyIHJvb3QgPSB0eXBlb2Ygd2luZG93ICE9PSBcInVuZGVmaW5lZFwiID8gd2luZG93IDogdHlwZW9mIGdsb2JhbCAhPT0gXCJ1bmRlZmluZWRcIiA/IGdsb2JhbCA6IHt9O1xuXG4gICAgICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBJbmRpdmlkdWFsO1xuXG4gICAgICAgICAgICAgICAgZnVuY3Rpb24gSW5kaXZpZHVhbChrZXksIHZhbHVlKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmIChrZXkgaW4gcm9vdCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHJvb3Rba2V5XTtcbiAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgIHJvb3Rba2V5XSA9IHZhbHVlO1xuXG4gICAgICAgICAgICAgICAgICAgIHJldHVybiB2YWx1ZTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9KS5jYWxsKHRoaXMsIHR5cGVvZiBnbG9iYWwgIT09IFwidW5kZWZpbmVkXCIgPyBnbG9iYWwgOiB0eXBlb2Ygc2VsZiAhPT0gXCJ1bmRlZmluZWRcIiA/IHNlbGYgOiB0eXBlb2Ygd2luZG93ICE9PSBcInVuZGVmaW5lZFwiID8gd2luZG93IDoge30pO1xuICAgICAgICB9LCB7fV0sIDk6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICBcInVzZSBzdHJpY3RcIjtcblxuICAgICAgICAgICAgdmFyIEluZGl2aWR1YWwgPSByZXF1aXJlKFwiLi9pbmRleC5qc1wiKTtcblxuICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBPbmVWZXJzaW9uO1xuXG4gICAgICAgICAgICBmdW5jdGlvbiBPbmVWZXJzaW9uKG1vZHVsZU5hbWUsIHZlcnNpb24sIGRlZmF1bHRWYWx1ZSkge1xuICAgICAgICAgICAgICAgIHZhciBrZXkgPSBcIl9fSU5ESVZJRFVBTF9PTkVfVkVSU0lPTl9cIiArIG1vZHVsZU5hbWU7XG4gICAgICAgICAgICAgICAgdmFyIGVuZm9yY2VLZXkgPSBrZXkgKyBcIl9FTkZPUkNFX1NJTkdMRVRPTlwiO1xuXG4gICAgICAgICAgICAgICAgdmFyIHZlcnNpb25WYWx1ZSA9IEluZGl2aWR1YWwoZW5mb3JjZUtleSwgdmVyc2lvbik7XG5cbiAgICAgICAgICAgICAgICBpZiAodmVyc2lvblZhbHVlICE9PSB2ZXJzaW9uKSB7XG4gICAgICAgICAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcihcIkNhbiBvbmx5IGhhdmUgb25lIGNvcHkgb2YgXCIgKyBtb2R1bGVOYW1lICsgXCIuXFxuXCIgKyBcIllvdSBhbHJlYWR5IGhhdmUgdmVyc2lvbiBcIiArIHZlcnNpb25WYWx1ZSArIFwiIGluc3RhbGxlZC5cXG5cIiArIFwiVGhpcyBtZWFucyB5b3UgY2Fubm90IGluc3RhbGwgdmVyc2lvbiBcIiArIHZlcnNpb24pO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHJldHVybiBJbmRpdmlkdWFsKGtleSwgZGVmYXVsdFZhbHVlKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSwgeyBcIi4vaW5kZXguanNcIjogOCB9XSwgMTA6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICAoZnVuY3Rpb24gKGdsb2JhbCkge1xuICAgICAgICAgICAgICAgIHZhciB0b3BMZXZlbCA9IHR5cGVvZiBnbG9iYWwgIT09IFwidW5kZWZpbmVkXCIgPyBnbG9iYWwgOiB0eXBlb2Ygd2luZG93ICE9PSBcInVuZGVmaW5lZFwiID8gd2luZG93IDoge307XG4gICAgICAgICAgICAgICAgdmFyIG1pbkRvYyA9IHJlcXVpcmUoXCJtaW4tZG9jdW1lbnRcIik7XG5cbiAgICAgICAgICAgICAgICBpZiAodHlwZW9mIGRvY3VtZW50ICE9PSBcInVuZGVmaW5lZFwiKSB7XG4gICAgICAgICAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gZG9jdW1lbnQ7XG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgdmFyIGRvY2N5ID0gdG9wTGV2ZWxbXCJfX0dMT0JBTF9ET0NVTUVOVF9DQUNIRUA0XCJdO1xuXG4gICAgICAgICAgICAgICAgICAgIGlmICghZG9jY3kpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGRvY2N5ID0gdG9wTGV2ZWxbXCJfX0dMT0JBTF9ET0NVTUVOVF9DQUNIRUA0XCJdID0gbWluRG9jO1xuICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBkb2NjeTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9KS5jYWxsKHRoaXMsIHR5cGVvZiBnbG9iYWwgIT09IFwidW5kZWZpbmVkXCIgPyBnbG9iYWwgOiB0eXBlb2Ygc2VsZiAhPT0gXCJ1bmRlZmluZWRcIiA/IHNlbGYgOiB0eXBlb2Ygd2luZG93ICE9PSBcInVuZGVmaW5lZFwiID8gd2luZG93IDoge30pO1xuICAgICAgICB9LCB7IFwibWluLWRvY3VtZW50XCI6IDYgfV0sIDExOiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge1xuICAgICAgICAgICAgXCJ1c2Ugc3RyaWN0XCI7XG5cbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gaXNPYmplY3QoeCkge1xuICAgICAgICAgICAgICAgIHJldHVybiB0eXBlb2YgeCA9PT0gXCJvYmplY3RcIiAmJiB4ICE9PSBudWxsO1xuICAgICAgICAgICAgfTtcbiAgICAgICAgfSwge31dLCAxMjogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHtcbiAgICAgICAgICAgIHZhciBuYXRpdmVJc0FycmF5ID0gQXJyYXkuaXNBcnJheTtcbiAgICAgICAgICAgIHZhciB0b1N0cmluZyA9IE9iamVjdC5wcm90b3R5cGUudG9TdHJpbmc7XG5cbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gbmF0aXZlSXNBcnJheSB8fCBpc0FycmF5O1xuXG4gICAgICAgICAgICBmdW5jdGlvbiBpc0FycmF5KG9iaikge1xuICAgICAgICAgICAgICAgIHJldHVybiB0b1N0cmluZy5jYWxsKG9iaikgPT09IFwiW29iamVjdCBBcnJheV1cIjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSwge31dLCAxMzogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHtcbiAgICAgICAgICAgIHZhciBwYXRjaCA9IHJlcXVpcmUoXCIuL3Zkb20vcGF0Y2guanNcIik7XG5cbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gcGF0Y2g7XG4gICAgICAgIH0sIHsgXCIuL3Zkb20vcGF0Y2guanNcIjogMTggfV0sIDE0OiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge1xuICAgICAgICAgICAgdmFyIGlzT2JqZWN0ID0gcmVxdWlyZShcImlzLW9iamVjdFwiKTtcbiAgICAgICAgICAgIHZhciBpc0hvb2sgPSByZXF1aXJlKFwiLi4vdm5vZGUvaXMtdmhvb2suanNcIik7XG5cbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gYXBwbHlQcm9wZXJ0aWVzO1xuXG4gICAgICAgICAgICBmdW5jdGlvbiBhcHBseVByb3BlcnRpZXMobm9kZSwgcHJvcHMsIHByZXZpb3VzKSB7XG4gICAgICAgICAgICAgICAgZm9yICh2YXIgcHJvcE5hbWUgaW4gcHJvcHMpIHtcbiAgICAgICAgICAgICAgICAgICAgdmFyIHByb3BWYWx1ZSA9IHByb3BzW3Byb3BOYW1lXTtcblxuICAgICAgICAgICAgICAgICAgICBpZiAocHJvcFZhbHVlID09PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJlbW92ZVByb3BlcnR5KG5vZGUsIHByb3BOYW1lLCBwcm9wVmFsdWUsIHByZXZpb3VzKTtcbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIGlmIChpc0hvb2socHJvcFZhbHVlKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgcmVtb3ZlUHJvcGVydHkobm9kZSwgcHJvcE5hbWUsIHByb3BWYWx1ZSwgcHJldmlvdXMpO1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHByb3BWYWx1ZS5ob29rKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcHJvcFZhbHVlLmhvb2sobm9kZSwgcHJvcE5hbWUsIHByZXZpb3VzID8gcHJldmlvdXNbcHJvcE5hbWVdIDogdW5kZWZpbmVkKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChpc09iamVjdChwcm9wVmFsdWUpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcGF0Y2hPYmplY3Qobm9kZSwgcHJvcHMsIHByZXZpb3VzLCBwcm9wTmFtZSwgcHJvcFZhbHVlKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgbm9kZVtwcm9wTmFtZV0gPSBwcm9wVmFsdWU7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIHJlbW92ZVByb3BlcnR5KG5vZGUsIHByb3BOYW1lLCBwcm9wVmFsdWUsIHByZXZpb3VzKSB7XG4gICAgICAgICAgICAgICAgaWYgKHByZXZpb3VzKSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciBwcmV2aW91c1ZhbHVlID0gcHJldmlvdXNbcHJvcE5hbWVdO1xuXG4gICAgICAgICAgICAgICAgICAgIGlmICghaXNIb29rKHByZXZpb3VzVmFsdWUpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAocHJvcE5hbWUgPT09IFwiYXR0cmlidXRlc1wiKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgZm9yICh2YXIgYXR0ck5hbWUgaW4gcHJldmlvdXNWYWx1ZSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBub2RlLnJlbW92ZUF0dHJpYnV0ZShhdHRyTmFtZSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIGlmIChwcm9wTmFtZSA9PT0gXCJzdHlsZVwiKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgZm9yICh2YXIgaSBpbiBwcmV2aW91c1ZhbHVlKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG5vZGUuc3R5bGVbaV0gPSBcIlwiO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAodHlwZW9mIHByZXZpb3VzVmFsdWUgPT09IFwic3RyaW5nXCIpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBub2RlW3Byb3BOYW1lXSA9IFwiXCI7XG4gICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIG5vZGVbcHJvcE5hbWVdID0gbnVsbDtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIGlmIChwcmV2aW91c1ZhbHVlLnVuaG9vaykge1xuICAgICAgICAgICAgICAgICAgICAgICAgcHJldmlvdXNWYWx1ZS51bmhvb2sobm9kZSwgcHJvcE5hbWUsIHByb3BWYWx1ZSk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIHBhdGNoT2JqZWN0KG5vZGUsIHByb3BzLCBwcmV2aW91cywgcHJvcE5hbWUsIHByb3BWYWx1ZSkge1xuICAgICAgICAgICAgICAgIHZhciBwcmV2aW91c1ZhbHVlID0gcHJldmlvdXMgPyBwcmV2aW91c1twcm9wTmFtZV0gOiB1bmRlZmluZWQ7XG5cbiAgICAgICAgICAgICAgICAvLyBTZXQgYXR0cmlidXRlc1xuICAgICAgICAgICAgICAgIGlmIChwcm9wTmFtZSA9PT0gXCJhdHRyaWJ1dGVzXCIpIHtcbiAgICAgICAgICAgICAgICAgICAgZm9yICh2YXIgYXR0ck5hbWUgaW4gcHJvcFZhbHVlKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICB2YXIgYXR0clZhbHVlID0gcHJvcFZhbHVlW2F0dHJOYW1lXTtcblxuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGF0dHJWYWx1ZSA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgbm9kZS5yZW1vdmVBdHRyaWJ1dGUoYXR0ck5hbWUpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBub2RlLnNldEF0dHJpYnV0ZShhdHRyTmFtZSwgYXR0clZhbHVlKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICBpZiAocHJldmlvdXNWYWx1ZSAmJiBpc09iamVjdChwcmV2aW91c1ZhbHVlKSAmJiBnZXRQcm90b3R5cGUocHJldmlvdXNWYWx1ZSkgIT09IGdldFByb3RvdHlwZShwcm9wVmFsdWUpKSB7XG4gICAgICAgICAgICAgICAgICAgIG5vZGVbcHJvcE5hbWVdID0gcHJvcFZhbHVlO1xuICAgICAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgaWYgKCFpc09iamVjdChub2RlW3Byb3BOYW1lXSkpIHtcbiAgICAgICAgICAgICAgICAgICAgbm9kZVtwcm9wTmFtZV0gPSB7fTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICB2YXIgcmVwbGFjZXIgPSBwcm9wTmFtZSA9PT0gXCJzdHlsZVwiID8gXCJcIiA6IHVuZGVmaW5lZDtcblxuICAgICAgICAgICAgICAgIGZvciAodmFyIGsgaW4gcHJvcFZhbHVlKSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciB2YWx1ZSA9IHByb3BWYWx1ZVtrXTtcbiAgICAgICAgICAgICAgICAgICAgbm9kZVtwcm9wTmFtZV1ba10gPSB2YWx1ZSA9PT0gdW5kZWZpbmVkID8gcmVwbGFjZXIgOiB2YWx1ZTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIGdldFByb3RvdHlwZSh2YWx1ZSkge1xuICAgICAgICAgICAgICAgIGlmIChPYmplY3QuZ2V0UHJvdG90eXBlT2YpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIE9iamVjdC5nZXRQcm90b3R5cGVPZih2YWx1ZSk7XG4gICAgICAgICAgICAgICAgfSBlbHNlIGlmICh2YWx1ZS5fX3Byb3RvX18pIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHZhbHVlLl9fcHJvdG9fXztcbiAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKHZhbHVlLmNvbnN0cnVjdG9yKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiB2YWx1ZS5jb25zdHJ1Y3Rvci5wcm90b3R5cGU7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9LCB7IFwiLi4vdm5vZGUvaXMtdmhvb2suanNcIjogMjYsIFwiaXMtb2JqZWN0XCI6IDExIH1dLCAxNTogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHtcbiAgICAgICAgICAgIHZhciBkb2N1bWVudCA9IHJlcXVpcmUoXCJnbG9iYWwvZG9jdW1lbnRcIik7XG5cbiAgICAgICAgICAgIHZhciBhcHBseVByb3BlcnRpZXMgPSByZXF1aXJlKFwiLi9hcHBseS1wcm9wZXJ0aWVzXCIpO1xuXG4gICAgICAgICAgICB2YXIgaXNWTm9kZSA9IHJlcXVpcmUoXCIuLi92bm9kZS9pcy12bm9kZS5qc1wiKTtcbiAgICAgICAgICAgIHZhciBpc1ZUZXh0ID0gcmVxdWlyZShcIi4uL3Zub2RlL2lzLXZ0ZXh0LmpzXCIpO1xuICAgICAgICAgICAgdmFyIGlzV2lkZ2V0ID0gcmVxdWlyZShcIi4uL3Zub2RlL2lzLXdpZGdldC5qc1wiKTtcbiAgICAgICAgICAgIHZhciBoYW5kbGVUaHVuayA9IHJlcXVpcmUoXCIuLi92bm9kZS9oYW5kbGUtdGh1bmsuanNcIik7XG5cbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gY3JlYXRlRWxlbWVudDtcblxuICAgICAgICAgICAgZnVuY3Rpb24gY3JlYXRlRWxlbWVudCh2bm9kZSwgb3B0cykge1xuICAgICAgICAgICAgICAgIHZhciBkb2MgPSBvcHRzID8gb3B0cy5kb2N1bWVudCB8fCBkb2N1bWVudCA6IGRvY3VtZW50O1xuICAgICAgICAgICAgICAgIHZhciB3YXJuID0gb3B0cyA/IG9wdHMud2FybiA6IG51bGw7XG5cbiAgICAgICAgICAgICAgICB2bm9kZSA9IGhhbmRsZVRodW5rKHZub2RlKS5hO1xuXG4gICAgICAgICAgICAgICAgaWYgKGlzV2lkZ2V0KHZub2RlKSkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gdm5vZGUuaW5pdCgpO1xuICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoaXNWVGV4dCh2bm9kZSkpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGRvYy5jcmVhdGVUZXh0Tm9kZSh2bm9kZS50ZXh0KTtcbiAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKCFpc1ZOb2RlKHZub2RlKSkge1xuICAgICAgICAgICAgICAgICAgICBpZiAod2Fybikge1xuICAgICAgICAgICAgICAgICAgICAgICAgd2FybihcIkl0ZW0gaXMgbm90IGEgdmFsaWQgdmlydHVhbCBkb20gbm9kZVwiLCB2bm9kZSk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIG51bGw7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgdmFyIG5vZGUgPSB2bm9kZS5uYW1lc3BhY2UgPT09IG51bGwgPyBkb2MuY3JlYXRlRWxlbWVudCh2bm9kZS50YWdOYW1lKSA6IGRvYy5jcmVhdGVFbGVtZW50TlModm5vZGUubmFtZXNwYWNlLCB2bm9kZS50YWdOYW1lKTtcblxuICAgICAgICAgICAgICAgIHZhciBwcm9wcyA9IHZub2RlLnByb3BlcnRpZXM7XG4gICAgICAgICAgICAgICAgYXBwbHlQcm9wZXJ0aWVzKG5vZGUsIHByb3BzKTtcblxuICAgICAgICAgICAgICAgIHZhciBjaGlsZHJlbiA9IHZub2RlLmNoaWxkcmVuO1xuXG4gICAgICAgICAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCBjaGlsZHJlbi5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgICAgICAgICB2YXIgY2hpbGROb2RlID0gY3JlYXRlRWxlbWVudChjaGlsZHJlbltpXSwgb3B0cyk7XG4gICAgICAgICAgICAgICAgICAgIGlmIChjaGlsZE5vZGUpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIG5vZGUuYXBwZW5kQ2hpbGQoY2hpbGROb2RlKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHJldHVybiBub2RlO1xuICAgICAgICAgICAgfVxuICAgICAgICB9LCB7IFwiLi4vdm5vZGUvaGFuZGxlLXRodW5rLmpzXCI6IDI0LCBcIi4uL3Zub2RlL2lzLXZub2RlLmpzXCI6IDI3LCBcIi4uL3Zub2RlL2lzLXZ0ZXh0LmpzXCI6IDI4LCBcIi4uL3Zub2RlL2lzLXdpZGdldC5qc1wiOiAyOSwgXCIuL2FwcGx5LXByb3BlcnRpZXNcIjogMTQsIFwiZ2xvYmFsL2RvY3VtZW50XCI6IDEwIH1dLCAxNjogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHtcbiAgICAgICAgICAgIC8vIE1hcHMgYSB2aXJ0dWFsIERPTSB0cmVlIG9udG8gYSByZWFsIERPTSB0cmVlIGluIGFuIGVmZmljaWVudCBtYW5uZXIuXG4gICAgICAgICAgICAvLyBXZSBkb24ndCB3YW50IHRvIHJlYWQgYWxsIG9mIHRoZSBET00gbm9kZXMgaW4gdGhlIHRyZWUgc28gd2UgdXNlXG4gICAgICAgICAgICAvLyB0aGUgaW4tb3JkZXIgdHJlZSBpbmRleGluZyB0byBlbGltaW5hdGUgcmVjdXJzaW9uIGRvd24gY2VydGFpbiBicmFuY2hlcy5cbiAgICAgICAgICAgIC8vIFdlIG9ubHkgcmVjdXJzZSBpbnRvIGEgRE9NIG5vZGUgaWYgd2Uga25vdyB0aGF0IGl0IGNvbnRhaW5zIGEgY2hpbGQgb2ZcbiAgICAgICAgICAgIC8vIGludGVyZXN0LlxuXG4gICAgICAgICAgICB2YXIgbm9DaGlsZCA9IHt9O1xuXG4gICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IGRvbUluZGV4O1xuXG4gICAgICAgICAgICBmdW5jdGlvbiBkb21JbmRleChyb290Tm9kZSwgdHJlZSwgaW5kaWNlcywgbm9kZXMpIHtcbiAgICAgICAgICAgICAgICBpZiAoIWluZGljZXMgfHwgaW5kaWNlcy5sZW5ndGggPT09IDApIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHt9O1xuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIGluZGljZXMuc29ydChhc2NlbmRpbmcpO1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gcmVjdXJzZShyb290Tm9kZSwgdHJlZSwgaW5kaWNlcywgbm9kZXMsIDApO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZnVuY3Rpb24gcmVjdXJzZShyb290Tm9kZSwgdHJlZSwgaW5kaWNlcywgbm9kZXMsIHJvb3RJbmRleCkge1xuICAgICAgICAgICAgICAgIG5vZGVzID0gbm9kZXMgfHwge307XG5cbiAgICAgICAgICAgICAgICBpZiAocm9vdE5vZGUpIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKGluZGV4SW5SYW5nZShpbmRpY2VzLCByb290SW5kZXgsIHJvb3RJbmRleCkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIG5vZGVzW3Jvb3RJbmRleF0gPSByb290Tm9kZTtcbiAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgIHZhciB2Q2hpbGRyZW4gPSB0cmVlLmNoaWxkcmVuO1xuXG4gICAgICAgICAgICAgICAgICAgIGlmICh2Q2hpbGRyZW4pIHtcblxuICAgICAgICAgICAgICAgICAgICAgICAgdmFyIGNoaWxkTm9kZXMgPSByb290Tm9kZS5jaGlsZE5vZGVzO1xuXG4gICAgICAgICAgICAgICAgICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IHRyZWUuY2hpbGRyZW4ubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICByb290SW5kZXggKz0gMTtcblxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZhciB2Q2hpbGQgPSB2Q2hpbGRyZW5baV0gfHwgbm9DaGlsZDtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB2YXIgbmV4dEluZGV4ID0gcm9vdEluZGV4ICsgKHZDaGlsZC5jb3VudCB8fCAwKTtcblxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIHNraXAgcmVjdXJzaW9uIGRvd24gdGhlIHRyZWUgaWYgdGhlcmUgYXJlIG5vIG5vZGVzIGRvd24gaGVyZVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChpbmRleEluUmFuZ2UoaW5kaWNlcywgcm9vdEluZGV4LCBuZXh0SW5kZXgpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlY3Vyc2UoY2hpbGROb2Rlc1tpXSwgdkNoaWxkLCBpbmRpY2VzLCBub2Rlcywgcm9vdEluZGV4KTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICByb290SW5kZXggPSBuZXh0SW5kZXg7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICByZXR1cm4gbm9kZXM7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIC8vIEJpbmFyeSBzZWFyY2ggZm9yIGFuIGluZGV4IGluIHRoZSBpbnRlcnZhbCBbbGVmdCwgcmlnaHRdXG4gICAgICAgICAgICBmdW5jdGlvbiBpbmRleEluUmFuZ2UoaW5kaWNlcywgbGVmdCwgcmlnaHQpIHtcbiAgICAgICAgICAgICAgICBpZiAoaW5kaWNlcy5sZW5ndGggPT09IDApIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHZhciBtaW5JbmRleCA9IDA7XG4gICAgICAgICAgICAgICAgdmFyIG1heEluZGV4ID0gaW5kaWNlcy5sZW5ndGggLSAxO1xuICAgICAgICAgICAgICAgIHZhciBjdXJyZW50SW5kZXg7XG4gICAgICAgICAgICAgICAgdmFyIGN1cnJlbnRJdGVtO1xuXG4gICAgICAgICAgICAgICAgd2hpbGUgKG1pbkluZGV4IDw9IG1heEluZGV4KSB7XG4gICAgICAgICAgICAgICAgICAgIGN1cnJlbnRJbmRleCA9IChtYXhJbmRleCArIG1pbkluZGV4KSAvIDIgPj4gMDtcbiAgICAgICAgICAgICAgICAgICAgY3VycmVudEl0ZW0gPSBpbmRpY2VzW2N1cnJlbnRJbmRleF07XG5cbiAgICAgICAgICAgICAgICAgICAgaWYgKG1pbkluZGV4ID09PSBtYXhJbmRleCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGN1cnJlbnRJdGVtID49IGxlZnQgJiYgY3VycmVudEl0ZW0gPD0gcmlnaHQ7XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoY3VycmVudEl0ZW0gPCBsZWZ0KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBtaW5JbmRleCA9IGN1cnJlbnRJbmRleCArIDE7XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoY3VycmVudEl0ZW0gPiByaWdodCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgbWF4SW5kZXggPSBjdXJyZW50SW5kZXggLSAxO1xuICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIGFzY2VuZGluZyhhLCBiKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGEgPiBiID8gMSA6IC0xO1xuICAgICAgICAgICAgfVxuICAgICAgICB9LCB7fV0sIDE3OiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge1xuICAgICAgICAgICAgdmFyIGFwcGx5UHJvcGVydGllcyA9IHJlcXVpcmUoXCIuL2FwcGx5LXByb3BlcnRpZXNcIik7XG5cbiAgICAgICAgICAgIHZhciBpc1dpZGdldCA9IHJlcXVpcmUoXCIuLi92bm9kZS9pcy13aWRnZXQuanNcIik7XG4gICAgICAgICAgICB2YXIgVlBhdGNoID0gcmVxdWlyZShcIi4uL3Zub2RlL3ZwYXRjaC5qc1wiKTtcblxuICAgICAgICAgICAgdmFyIHVwZGF0ZVdpZGdldCA9IHJlcXVpcmUoXCIuL3VwZGF0ZS13aWRnZXRcIik7XG5cbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gYXBwbHlQYXRjaDtcblxuICAgICAgICAgICAgZnVuY3Rpb24gYXBwbHlQYXRjaCh2cGF0Y2gsIGRvbU5vZGUsIHJlbmRlck9wdGlvbnMpIHtcbiAgICAgICAgICAgICAgICB2YXIgdHlwZSA9IHZwYXRjaC50eXBlO1xuICAgICAgICAgICAgICAgIHZhciB2Tm9kZSA9IHZwYXRjaC52Tm9kZTtcbiAgICAgICAgICAgICAgICB2YXIgcGF0Y2ggPSB2cGF0Y2gucGF0Y2g7XG5cbiAgICAgICAgICAgICAgICBzd2l0Y2ggKHR5cGUpIHtcbiAgICAgICAgICAgICAgICAgICAgY2FzZSBWUGF0Y2guUkVNT1ZFOlxuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHJlbW92ZU5vZGUoZG9tTm9kZSwgdk5vZGUpO1xuICAgICAgICAgICAgICAgICAgICBjYXNlIFZQYXRjaC5JTlNFUlQ6XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gaW5zZXJ0Tm9kZShkb21Ob2RlLCBwYXRjaCwgcmVuZGVyT3B0aW9ucyk7XG4gICAgICAgICAgICAgICAgICAgIGNhc2UgVlBhdGNoLlZURVhUOlxuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHN0cmluZ1BhdGNoKGRvbU5vZGUsIHZOb2RlLCBwYXRjaCwgcmVuZGVyT3B0aW9ucyk7XG4gICAgICAgICAgICAgICAgICAgIGNhc2UgVlBhdGNoLldJREdFVDpcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiB3aWRnZXRQYXRjaChkb21Ob2RlLCB2Tm9kZSwgcGF0Y2gsIHJlbmRlck9wdGlvbnMpO1xuICAgICAgICAgICAgICAgICAgICBjYXNlIFZQYXRjaC5WTk9ERTpcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiB2Tm9kZVBhdGNoKGRvbU5vZGUsIHZOb2RlLCBwYXRjaCwgcmVuZGVyT3B0aW9ucyk7XG4gICAgICAgICAgICAgICAgICAgIGNhc2UgVlBhdGNoLk9SREVSOlxuICAgICAgICAgICAgICAgICAgICAgICAgcmVvcmRlckNoaWxkcmVuKGRvbU5vZGUsIHBhdGNoKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBkb21Ob2RlO1xuICAgICAgICAgICAgICAgICAgICBjYXNlIFZQYXRjaC5QUk9QUzpcbiAgICAgICAgICAgICAgICAgICAgICAgIGFwcGx5UHJvcGVydGllcyhkb21Ob2RlLCBwYXRjaCwgdk5vZGUucHJvcGVydGllcyk7XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gZG9tTm9kZTtcbiAgICAgICAgICAgICAgICAgICAgY2FzZSBWUGF0Y2guVEhVTks6XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gcmVwbGFjZVJvb3QoZG9tTm9kZSwgcmVuZGVyT3B0aW9ucy5wYXRjaChkb21Ob2RlLCBwYXRjaCwgcmVuZGVyT3B0aW9ucykpO1xuICAgICAgICAgICAgICAgICAgICBkZWZhdWx0OlxuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGRvbU5vZGU7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBmdW5jdGlvbiByZW1vdmVOb2RlKGRvbU5vZGUsIHZOb2RlKSB7XG4gICAgICAgICAgICAgICAgdmFyIHBhcmVudE5vZGUgPSBkb21Ob2RlLnBhcmVudE5vZGU7XG5cbiAgICAgICAgICAgICAgICBpZiAocGFyZW50Tm9kZSkge1xuICAgICAgICAgICAgICAgICAgICBwYXJlbnROb2RlLnJlbW92ZUNoaWxkKGRvbU5vZGUpO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIGRlc3Ryb3lXaWRnZXQoZG9tTm9kZSwgdk5vZGUpO1xuXG4gICAgICAgICAgICAgICAgcmV0dXJuIG51bGw7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIGluc2VydE5vZGUocGFyZW50Tm9kZSwgdk5vZGUsIHJlbmRlck9wdGlvbnMpIHtcbiAgICAgICAgICAgICAgICB2YXIgbmV3Tm9kZSA9IHJlbmRlck9wdGlvbnMucmVuZGVyKHZOb2RlLCByZW5kZXJPcHRpb25zKTtcblxuICAgICAgICAgICAgICAgIGlmIChwYXJlbnROb2RlKSB7XG4gICAgICAgICAgICAgICAgICAgIHBhcmVudE5vZGUuYXBwZW5kQ2hpbGQobmV3Tm9kZSk7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgcmV0dXJuIHBhcmVudE5vZGU7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIHN0cmluZ1BhdGNoKGRvbU5vZGUsIGxlZnRWTm9kZSwgdlRleHQsIHJlbmRlck9wdGlvbnMpIHtcbiAgICAgICAgICAgICAgICB2YXIgbmV3Tm9kZTtcblxuICAgICAgICAgICAgICAgIGlmIChkb21Ob2RlLm5vZGVUeXBlID09PSAzKSB7XG4gICAgICAgICAgICAgICAgICAgIGRvbU5vZGUucmVwbGFjZURhdGEoMCwgZG9tTm9kZS5sZW5ndGgsIHZUZXh0LnRleHQpO1xuICAgICAgICAgICAgICAgICAgICBuZXdOb2RlID0gZG9tTm9kZTtcbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICB2YXIgcGFyZW50Tm9kZSA9IGRvbU5vZGUucGFyZW50Tm9kZTtcbiAgICAgICAgICAgICAgICAgICAgbmV3Tm9kZSA9IHJlbmRlck9wdGlvbnMucmVuZGVyKHZUZXh0LCByZW5kZXJPcHRpb25zKTtcblxuICAgICAgICAgICAgICAgICAgICBpZiAocGFyZW50Tm9kZSAmJiBuZXdOb2RlICE9PSBkb21Ob2RlKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBwYXJlbnROb2RlLnJlcGxhY2VDaGlsZChuZXdOb2RlLCBkb21Ob2RlKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHJldHVybiBuZXdOb2RlO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBmdW5jdGlvbiB3aWRnZXRQYXRjaChkb21Ob2RlLCBsZWZ0Vk5vZGUsIHdpZGdldCwgcmVuZGVyT3B0aW9ucykge1xuICAgICAgICAgICAgICAgIHZhciB1cGRhdGluZyA9IHVwZGF0ZVdpZGdldChsZWZ0Vk5vZGUsIHdpZGdldCk7XG4gICAgICAgICAgICAgICAgdmFyIG5ld05vZGU7XG5cbiAgICAgICAgICAgICAgICBpZiAodXBkYXRpbmcpIHtcbiAgICAgICAgICAgICAgICAgICAgbmV3Tm9kZSA9IHdpZGdldC51cGRhdGUobGVmdFZOb2RlLCBkb21Ob2RlKSB8fCBkb21Ob2RlO1xuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIG5ld05vZGUgPSByZW5kZXJPcHRpb25zLnJlbmRlcih3aWRnZXQsIHJlbmRlck9wdGlvbnMpO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHZhciBwYXJlbnROb2RlID0gZG9tTm9kZS5wYXJlbnROb2RlO1xuXG4gICAgICAgICAgICAgICAgaWYgKHBhcmVudE5vZGUgJiYgbmV3Tm9kZSAhPT0gZG9tTm9kZSkge1xuICAgICAgICAgICAgICAgICAgICBwYXJlbnROb2RlLnJlcGxhY2VDaGlsZChuZXdOb2RlLCBkb21Ob2RlKTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICBpZiAoIXVwZGF0aW5nKSB7XG4gICAgICAgICAgICAgICAgICAgIGRlc3Ryb3lXaWRnZXQoZG9tTm9kZSwgbGVmdFZOb2RlKTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICByZXR1cm4gbmV3Tm9kZTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZnVuY3Rpb24gdk5vZGVQYXRjaChkb21Ob2RlLCBsZWZ0Vk5vZGUsIHZOb2RlLCByZW5kZXJPcHRpb25zKSB7XG4gICAgICAgICAgICAgICAgdmFyIHBhcmVudE5vZGUgPSBkb21Ob2RlLnBhcmVudE5vZGU7XG4gICAgICAgICAgICAgICAgdmFyIG5ld05vZGUgPSByZW5kZXJPcHRpb25zLnJlbmRlcih2Tm9kZSwgcmVuZGVyT3B0aW9ucyk7XG5cbiAgICAgICAgICAgICAgICBpZiAocGFyZW50Tm9kZSAmJiBuZXdOb2RlICE9PSBkb21Ob2RlKSB7XG4gICAgICAgICAgICAgICAgICAgIHBhcmVudE5vZGUucmVwbGFjZUNoaWxkKG5ld05vZGUsIGRvbU5vZGUpO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHJldHVybiBuZXdOb2RlO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBmdW5jdGlvbiBkZXN0cm95V2lkZ2V0KGRvbU5vZGUsIHcpIHtcbiAgICAgICAgICAgICAgICBpZiAodHlwZW9mIHcuZGVzdHJveSA9PT0gXCJmdW5jdGlvblwiICYmIGlzV2lkZ2V0KHcpKSB7XG4gICAgICAgICAgICAgICAgICAgIHcuZGVzdHJveShkb21Ob2RlKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIHJlb3JkZXJDaGlsZHJlbihkb21Ob2RlLCBtb3Zlcykge1xuICAgICAgICAgICAgICAgIHZhciBjaGlsZE5vZGVzID0gZG9tTm9kZS5jaGlsZE5vZGVzO1xuICAgICAgICAgICAgICAgIHZhciBrZXlNYXAgPSB7fTtcbiAgICAgICAgICAgICAgICB2YXIgbm9kZTtcbiAgICAgICAgICAgICAgICB2YXIgcmVtb3ZlO1xuICAgICAgICAgICAgICAgIHZhciBpbnNlcnQ7XG5cbiAgICAgICAgICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IG1vdmVzLnJlbW92ZXMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgICAgICAgICAgcmVtb3ZlID0gbW92ZXMucmVtb3Zlc1tpXTtcbiAgICAgICAgICAgICAgICAgICAgbm9kZSA9IGNoaWxkTm9kZXNbcmVtb3ZlLmZyb21dO1xuICAgICAgICAgICAgICAgICAgICBpZiAocmVtb3ZlLmtleSkge1xuICAgICAgICAgICAgICAgICAgICAgICAga2V5TWFwW3JlbW92ZS5rZXldID0gbm9kZTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICBkb21Ob2RlLnJlbW92ZUNoaWxkKG5vZGUpO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHZhciBsZW5ndGggPSBjaGlsZE5vZGVzLmxlbmd0aDtcbiAgICAgICAgICAgICAgICBmb3IgKHZhciBqID0gMDsgaiA8IG1vdmVzLmluc2VydHMubGVuZ3RoOyBqKyspIHtcbiAgICAgICAgICAgICAgICAgICAgaW5zZXJ0ID0gbW92ZXMuaW5zZXJ0c1tqXTtcbiAgICAgICAgICAgICAgICAgICAgbm9kZSA9IGtleU1hcFtpbnNlcnQua2V5XTtcbiAgICAgICAgICAgICAgICAgICAgLy8gdGhpcyBpcyB0aGUgd2VpcmRlc3QgYnVnIGkndmUgZXZlciBzZWVuIGluIHdlYmtpdFxuICAgICAgICAgICAgICAgICAgICBkb21Ob2RlLmluc2VydEJlZm9yZShub2RlLCBpbnNlcnQudG8gPj0gbGVuZ3RoKysgPyBudWxsIDogY2hpbGROb2Rlc1tpbnNlcnQudG9dKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIHJlcGxhY2VSb290KG9sZFJvb3QsIG5ld1Jvb3QpIHtcbiAgICAgICAgICAgICAgICBpZiAob2xkUm9vdCAmJiBuZXdSb290ICYmIG9sZFJvb3QgIT09IG5ld1Jvb3QgJiYgb2xkUm9vdC5wYXJlbnROb2RlKSB7XG4gICAgICAgICAgICAgICAgICAgIG9sZFJvb3QucGFyZW50Tm9kZS5yZXBsYWNlQ2hpbGQobmV3Um9vdCwgb2xkUm9vdCk7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgcmV0dXJuIG5ld1Jvb3Q7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0sIHsgXCIuLi92bm9kZS9pcy13aWRnZXQuanNcIjogMjksIFwiLi4vdm5vZGUvdnBhdGNoLmpzXCI6IDMyLCBcIi4vYXBwbHktcHJvcGVydGllc1wiOiAxNCwgXCIuL3VwZGF0ZS13aWRnZXRcIjogMTkgfV0sIDE4OiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge1xuICAgICAgICAgICAgdmFyIGRvY3VtZW50ID0gcmVxdWlyZShcImdsb2JhbC9kb2N1bWVudFwiKTtcbiAgICAgICAgICAgIHZhciBpc0FycmF5ID0gcmVxdWlyZShcIngtaXMtYXJyYXlcIik7XG5cbiAgICAgICAgICAgIHZhciByZW5kZXIgPSByZXF1aXJlKFwiLi9jcmVhdGUtZWxlbWVudFwiKTtcbiAgICAgICAgICAgIHZhciBkb21JbmRleCA9IHJlcXVpcmUoXCIuL2RvbS1pbmRleFwiKTtcbiAgICAgICAgICAgIHZhciBwYXRjaE9wID0gcmVxdWlyZShcIi4vcGF0Y2gtb3BcIik7XG4gICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IHBhdGNoO1xuXG4gICAgICAgICAgICBmdW5jdGlvbiBwYXRjaChyb290Tm9kZSwgcGF0Y2hlcywgcmVuZGVyT3B0aW9ucykge1xuICAgICAgICAgICAgICAgIHJlbmRlck9wdGlvbnMgPSByZW5kZXJPcHRpb25zIHx8IHt9O1xuICAgICAgICAgICAgICAgIHJlbmRlck9wdGlvbnMucGF0Y2ggPSByZW5kZXJPcHRpb25zLnBhdGNoICYmIHJlbmRlck9wdGlvbnMucGF0Y2ggIT09IHBhdGNoID8gcmVuZGVyT3B0aW9ucy5wYXRjaCA6IHBhdGNoUmVjdXJzaXZlO1xuICAgICAgICAgICAgICAgIHJlbmRlck9wdGlvbnMucmVuZGVyID0gcmVuZGVyT3B0aW9ucy5yZW5kZXIgfHwgcmVuZGVyO1xuXG4gICAgICAgICAgICAgICAgcmV0dXJuIHJlbmRlck9wdGlvbnMucGF0Y2gocm9vdE5vZGUsIHBhdGNoZXMsIHJlbmRlck9wdGlvbnMpO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBmdW5jdGlvbiBwYXRjaFJlY3Vyc2l2ZShyb290Tm9kZSwgcGF0Y2hlcywgcmVuZGVyT3B0aW9ucykge1xuICAgICAgICAgICAgICAgIHZhciBpbmRpY2VzID0gcGF0Y2hJbmRpY2VzKHBhdGNoZXMpO1xuXG4gICAgICAgICAgICAgICAgaWYgKGluZGljZXMubGVuZ3RoID09PSAwKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiByb290Tm9kZTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICB2YXIgaW5kZXggPSBkb21JbmRleChyb290Tm9kZSwgcGF0Y2hlcy5hLCBpbmRpY2VzKTtcbiAgICAgICAgICAgICAgICB2YXIgb3duZXJEb2N1bWVudCA9IHJvb3ROb2RlLm93bmVyRG9jdW1lbnQ7XG5cbiAgICAgICAgICAgICAgICBpZiAoIXJlbmRlck9wdGlvbnMuZG9jdW1lbnQgJiYgb3duZXJEb2N1bWVudCAhPT0gZG9jdW1lbnQpIHtcbiAgICAgICAgICAgICAgICAgICAgcmVuZGVyT3B0aW9ucy5kb2N1bWVudCA9IG93bmVyRG9jdW1lbnQ7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCBpbmRpY2VzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciBub2RlSW5kZXggPSBpbmRpY2VzW2ldO1xuICAgICAgICAgICAgICAgICAgICByb290Tm9kZSA9IGFwcGx5UGF0Y2gocm9vdE5vZGUsIGluZGV4W25vZGVJbmRleF0sIHBhdGNoZXNbbm9kZUluZGV4XSwgcmVuZGVyT3B0aW9ucyk7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgcmV0dXJuIHJvb3ROb2RlO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBmdW5jdGlvbiBhcHBseVBhdGNoKHJvb3ROb2RlLCBkb21Ob2RlLCBwYXRjaExpc3QsIHJlbmRlck9wdGlvbnMpIHtcbiAgICAgICAgICAgICAgICBpZiAoIWRvbU5vZGUpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHJvb3ROb2RlO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHZhciBuZXdOb2RlO1xuXG4gICAgICAgICAgICAgICAgaWYgKGlzQXJyYXkocGF0Y2hMaXN0KSkge1xuICAgICAgICAgICAgICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IHBhdGNoTGlzdC5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgICAgICAgICAgICAgbmV3Tm9kZSA9IHBhdGNoT3AocGF0Y2hMaXN0W2ldLCBkb21Ob2RlLCByZW5kZXJPcHRpb25zKTtcblxuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGRvbU5vZGUgPT09IHJvb3ROb2RlKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcm9vdE5vZGUgPSBuZXdOb2RlO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgbmV3Tm9kZSA9IHBhdGNoT3AocGF0Y2hMaXN0LCBkb21Ob2RlLCByZW5kZXJPcHRpb25zKTtcblxuICAgICAgICAgICAgICAgICAgICBpZiAoZG9tTm9kZSA9PT0gcm9vdE5vZGUpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJvb3ROb2RlID0gbmV3Tm9kZTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHJldHVybiByb290Tm9kZTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZnVuY3Rpb24gcGF0Y2hJbmRpY2VzKHBhdGNoZXMpIHtcbiAgICAgICAgICAgICAgICB2YXIgaW5kaWNlcyA9IFtdO1xuXG4gICAgICAgICAgICAgICAgZm9yICh2YXIga2V5IGluIHBhdGNoZXMpIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKGtleSAhPT0gXCJhXCIpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGluZGljZXMucHVzaChOdW1iZXIoa2V5KSk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICByZXR1cm4gaW5kaWNlcztcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSwgeyBcIi4vY3JlYXRlLWVsZW1lbnRcIjogMTUsIFwiLi9kb20taW5kZXhcIjogMTYsIFwiLi9wYXRjaC1vcFwiOiAxNywgXCJnbG9iYWwvZG9jdW1lbnRcIjogMTAsIFwieC1pcy1hcnJheVwiOiAxMiB9XSwgMTk6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICB2YXIgaXNXaWRnZXQgPSByZXF1aXJlKFwiLi4vdm5vZGUvaXMtd2lkZ2V0LmpzXCIpO1xuXG4gICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IHVwZGF0ZVdpZGdldDtcblxuICAgICAgICAgICAgZnVuY3Rpb24gdXBkYXRlV2lkZ2V0KGEsIGIpIHtcbiAgICAgICAgICAgICAgICBpZiAoaXNXaWRnZXQoYSkgJiYgaXNXaWRnZXQoYikpIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKFwibmFtZVwiIGluIGEgJiYgXCJuYW1lXCIgaW4gYikge1xuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGEuaWQgPT09IGIuaWQ7XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gYS5pbml0ID09PSBiLmluaXQ7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0sIHsgXCIuLi92bm9kZS9pcy13aWRnZXQuanNcIjogMjkgfV0sIDIwOiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge1xuICAgICAgICAgICAgXCJ1c2Ugc3RyaWN0XCI7XG5cbiAgICAgICAgICAgIHZhciBFdlN0b3JlID0gcmVxdWlyZShcImV2LXN0b3JlXCIpO1xuXG4gICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IEV2SG9vaztcblxuICAgICAgICAgICAgZnVuY3Rpb24gRXZIb29rKHZhbHVlKSB7XG4gICAgICAgICAgICAgICAgaWYgKCEodGhpcyBpbnN0YW5jZW9mIEV2SG9vaykpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIG5ldyBFdkhvb2sodmFsdWUpO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHRoaXMudmFsdWUgPSB2YWx1ZTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgRXZIb29rLnByb3RvdHlwZS5ob29rID0gZnVuY3Rpb24gKG5vZGUsIHByb3BlcnR5TmFtZSkge1xuICAgICAgICAgICAgICAgIHZhciBlcyA9IEV2U3RvcmUobm9kZSk7XG4gICAgICAgICAgICAgICAgdmFyIHByb3BOYW1lID0gcHJvcGVydHlOYW1lLnN1YnN0cigzKTtcblxuICAgICAgICAgICAgICAgIGVzW3Byb3BOYW1lXSA9IHRoaXMudmFsdWU7XG4gICAgICAgICAgICB9O1xuXG4gICAgICAgICAgICBFdkhvb2sucHJvdG90eXBlLnVuaG9vayA9IGZ1bmN0aW9uIChub2RlLCBwcm9wZXJ0eU5hbWUpIHtcbiAgICAgICAgICAgICAgICB2YXIgZXMgPSBFdlN0b3JlKG5vZGUpO1xuICAgICAgICAgICAgICAgIHZhciBwcm9wTmFtZSA9IHByb3BlcnR5TmFtZS5zdWJzdHIoMyk7XG5cbiAgICAgICAgICAgICAgICBlc1twcm9wTmFtZV0gPSB1bmRlZmluZWQ7XG4gICAgICAgICAgICB9O1xuICAgICAgICB9LCB7IFwiZXYtc3RvcmVcIjogNyB9XSwgMjE6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICBcInVzZSBzdHJpY3RcIjtcblxuICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBTb2Z0U2V0SG9vaztcblxuICAgICAgICAgICAgZnVuY3Rpb24gU29mdFNldEhvb2sodmFsdWUpIHtcbiAgICAgICAgICAgICAgICBpZiAoISh0aGlzIGluc3RhbmNlb2YgU29mdFNldEhvb2spKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBuZXcgU29mdFNldEhvb2sodmFsdWUpO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHRoaXMudmFsdWUgPSB2YWx1ZTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgU29mdFNldEhvb2sucHJvdG90eXBlLmhvb2sgPSBmdW5jdGlvbiAobm9kZSwgcHJvcGVydHlOYW1lKSB7XG4gICAgICAgICAgICAgICAgaWYgKG5vZGVbcHJvcGVydHlOYW1lXSAhPT0gdGhpcy52YWx1ZSkge1xuICAgICAgICAgICAgICAgICAgICBub2RlW3Byb3BlcnR5TmFtZV0gPSB0aGlzLnZhbHVlO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH07XG4gICAgICAgIH0sIHt9XSwgMjI6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICBcInVzZSBzdHJpY3RcIjtcblxuICAgICAgICAgICAgdmFyIGlzQXJyYXkgPSByZXF1aXJlKFwieC1pcy1hcnJheVwiKTtcblxuICAgICAgICAgICAgdmFyIFZOb2RlID0gcmVxdWlyZShcIi4uL3Zub2RlL3Zub2RlLmpzXCIpO1xuICAgICAgICAgICAgdmFyIFZUZXh0ID0gcmVxdWlyZShcIi4uL3Zub2RlL3Z0ZXh0LmpzXCIpO1xuICAgICAgICAgICAgdmFyIGlzVk5vZGUgPSByZXF1aXJlKFwiLi4vdm5vZGUvaXMtdm5vZGVcIik7XG4gICAgICAgICAgICB2YXIgaXNWVGV4dCA9IHJlcXVpcmUoXCIuLi92bm9kZS9pcy12dGV4dFwiKTtcbiAgICAgICAgICAgIHZhciBpc1dpZGdldCA9IHJlcXVpcmUoXCIuLi92bm9kZS9pcy13aWRnZXRcIik7XG4gICAgICAgICAgICB2YXIgaXNIb29rID0gcmVxdWlyZShcIi4uL3Zub2RlL2lzLXZob29rXCIpO1xuICAgICAgICAgICAgdmFyIGlzVlRodW5rID0gcmVxdWlyZShcIi4uL3Zub2RlL2lzLXRodW5rXCIpO1xuXG4gICAgICAgICAgICB2YXIgcGFyc2VUYWcgPSByZXF1aXJlKFwiLi9wYXJzZS10YWcuanNcIik7XG4gICAgICAgICAgICB2YXIgc29mdFNldEhvb2sgPSByZXF1aXJlKFwiLi9ob29rcy9zb2Z0LXNldC1ob29rLmpzXCIpO1xuICAgICAgICAgICAgdmFyIGV2SG9vayA9IHJlcXVpcmUoXCIuL2hvb2tzL2V2LWhvb2suanNcIik7XG5cbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gaDtcblxuICAgICAgICAgICAgZnVuY3Rpb24gaCh0YWdOYW1lLCBwcm9wZXJ0aWVzLCBjaGlsZHJlbikge1xuICAgICAgICAgICAgICAgIHZhciBjaGlsZE5vZGVzID0gW107XG4gICAgICAgICAgICAgICAgdmFyIHRhZywgcHJvcHMsIGtleSwgbmFtZXNwYWNlO1xuXG4gICAgICAgICAgICAgICAgaWYgKCFjaGlsZHJlbiAmJiBpc0NoaWxkcmVuKHByb3BlcnRpZXMpKSB7XG4gICAgICAgICAgICAgICAgICAgIGNoaWxkcmVuID0gcHJvcGVydGllcztcbiAgICAgICAgICAgICAgICAgICAgcHJvcHMgPSB7fTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICBwcm9wcyA9IHByb3BzIHx8IHByb3BlcnRpZXMgfHwge307XG4gICAgICAgICAgICAgICAgdGFnID0gcGFyc2VUYWcodGFnTmFtZSwgcHJvcHMpO1xuXG4gICAgICAgICAgICAgICAgLy8gc3VwcG9ydCBrZXlzXG4gICAgICAgICAgICAgICAgaWYgKHByb3BzLmhhc093blByb3BlcnR5KFwia2V5XCIpKSB7XG4gICAgICAgICAgICAgICAgICAgIGtleSA9IHByb3BzLmtleTtcbiAgICAgICAgICAgICAgICAgICAgcHJvcHMua2V5ID0gdW5kZWZpbmVkO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIC8vIHN1cHBvcnQgbmFtZXNwYWNlXG4gICAgICAgICAgICAgICAgaWYgKHByb3BzLmhhc093blByb3BlcnR5KFwibmFtZXNwYWNlXCIpKSB7XG4gICAgICAgICAgICAgICAgICAgIG5hbWVzcGFjZSA9IHByb3BzLm5hbWVzcGFjZTtcbiAgICAgICAgICAgICAgICAgICAgcHJvcHMubmFtZXNwYWNlID0gdW5kZWZpbmVkO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIC8vIGZpeCBjdXJzb3IgYnVnXG4gICAgICAgICAgICAgICAgaWYgKHRhZyA9PT0gXCJJTlBVVFwiICYmICFuYW1lc3BhY2UgJiYgcHJvcHMuaGFzT3duUHJvcGVydHkoXCJ2YWx1ZVwiKSAmJiBwcm9wcy52YWx1ZSAhPT0gdW5kZWZpbmVkICYmICFpc0hvb2socHJvcHMudmFsdWUpKSB7XG4gICAgICAgICAgICAgICAgICAgIHByb3BzLnZhbHVlID0gc29mdFNldEhvb2socHJvcHMudmFsdWUpO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHRyYW5zZm9ybVByb3BlcnRpZXMocHJvcHMpO1xuXG4gICAgICAgICAgICAgICAgaWYgKGNoaWxkcmVuICE9PSB1bmRlZmluZWQgJiYgY2hpbGRyZW4gIT09IG51bGwpIHtcbiAgICAgICAgICAgICAgICAgICAgYWRkQ2hpbGQoY2hpbGRyZW4sIGNoaWxkTm9kZXMsIHRhZywgcHJvcHMpO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHJldHVybiBuZXcgVk5vZGUodGFnLCBwcm9wcywgY2hpbGROb2Rlcywga2V5LCBuYW1lc3BhY2UpO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBmdW5jdGlvbiBhZGRDaGlsZChjLCBjaGlsZE5vZGVzLCB0YWcsIHByb3BzKSB7XG4gICAgICAgICAgICAgICAgaWYgKHR5cGVvZiBjID09PSBcInN0cmluZ1wiKSB7XG4gICAgICAgICAgICAgICAgICAgIGNoaWxkTm9kZXMucHVzaChuZXcgVlRleHQoYykpO1xuICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAodHlwZW9mIGMgPT09IFwibnVtYmVyXCIpIHtcbiAgICAgICAgICAgICAgICAgICAgY2hpbGROb2Rlcy5wdXNoKG5ldyBWVGV4dChTdHJpbmcoYykpKTtcbiAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKGlzQ2hpbGQoYykpIHtcbiAgICAgICAgICAgICAgICAgICAgY2hpbGROb2Rlcy5wdXNoKGMpO1xuICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoaXNBcnJheShjKSkge1xuICAgICAgICAgICAgICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IGMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGFkZENoaWxkKGNbaV0sIGNoaWxkTm9kZXMsIHRhZywgcHJvcHMpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfSBlbHNlIGlmIChjID09PSBudWxsIHx8IGMgPT09IHVuZGVmaW5lZCkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgdGhyb3cgVW5leHBlY3RlZFZpcnR1YWxFbGVtZW50KHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGZvcmVpZ25PYmplY3Q6IGMsXG4gICAgICAgICAgICAgICAgICAgICAgICBwYXJlbnRWbm9kZToge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRhZ05hbWU6IHRhZyxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBwcm9wZXJ0aWVzOiBwcm9wc1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIHRyYW5zZm9ybVByb3BlcnRpZXMocHJvcHMpIHtcbiAgICAgICAgICAgICAgICBmb3IgKHZhciBwcm9wTmFtZSBpbiBwcm9wcykge1xuICAgICAgICAgICAgICAgICAgICBpZiAocHJvcHMuaGFzT3duUHJvcGVydHkocHJvcE5hbWUpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICB2YXIgdmFsdWUgPSBwcm9wc1twcm9wTmFtZV07XG5cbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChpc0hvb2sodmFsdWUpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgY29udGludWU7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChwcm9wTmFtZS5zdWJzdHIoMCwgMykgPT09IFwiZXYtXCIpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBhZGQgZXYtZm9vIHN1cHBvcnRcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBwcm9wc1twcm9wTmFtZV0gPSBldkhvb2sodmFsdWUpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBmdW5jdGlvbiBpc0NoaWxkKHgpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gaXNWTm9kZSh4KSB8fCBpc1ZUZXh0KHgpIHx8IGlzV2lkZ2V0KHgpIHx8IGlzVlRodW5rKHgpO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBmdW5jdGlvbiBpc0NoaWxkcmVuKHgpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gdHlwZW9mIHggPT09IFwic3RyaW5nXCIgfHwgaXNBcnJheSh4KSB8fCBpc0NoaWxkKHgpO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBmdW5jdGlvbiBVbmV4cGVjdGVkVmlydHVhbEVsZW1lbnQoZGF0YSkge1xuICAgICAgICAgICAgICAgIHZhciBlcnIgPSBuZXcgRXJyb3IoKTtcblxuICAgICAgICAgICAgICAgIGVyci50eXBlID0gXCJ2aXJ0dWFsLWh5cGVyc2NyaXB0LnVuZXhwZWN0ZWQudmlydHVhbC1lbGVtZW50XCI7XG4gICAgICAgICAgICAgICAgZXJyLm1lc3NhZ2UgPSBcIlVuZXhwZWN0ZWQgdmlydHVhbCBjaGlsZCBwYXNzZWQgdG8gaCgpLlxcblwiICsgXCJFeHBlY3RlZCBhIFZOb2RlIC8gVnRodW5rIC8gVldpZGdldCAvIHN0cmluZyBidXQ6XFxuXCIgKyBcImdvdDpcXG5cIiArIGVycm9yU3RyaW5nKGRhdGEuZm9yZWlnbk9iamVjdCkgKyBcIi5cXG5cIiArIFwiVGhlIHBhcmVudCB2bm9kZSBpczpcXG5cIiArIGVycm9yU3RyaW5nKGRhdGEucGFyZW50Vm5vZGUpO1xuICAgICAgICAgICAgICAgIFwiXFxuXCIgKyBcIlN1Z2dlc3RlZCBmaXg6IGNoYW5nZSB5b3VyIGBoKC4uLiwgWyAuLi4gXSlgIGNhbGxzaXRlLlwiO1xuICAgICAgICAgICAgICAgIGVyci5mb3JlaWduT2JqZWN0ID0gZGF0YS5mb3JlaWduT2JqZWN0O1xuICAgICAgICAgICAgICAgIGVyci5wYXJlbnRWbm9kZSA9IGRhdGEucGFyZW50Vm5vZGU7XG5cbiAgICAgICAgICAgICAgICByZXR1cm4gZXJyO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBmdW5jdGlvbiBlcnJvclN0cmluZyhvYmopIHtcbiAgICAgICAgICAgICAgICB0cnkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gSlNPTi5zdHJpbmdpZnkob2JqLCBudWxsLCBcIiAgICBcIik7XG4gICAgICAgICAgICAgICAgfSBjYXRjaCAoZSkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gU3RyaW5nKG9iaik7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9LCB7IFwiLi4vdm5vZGUvaXMtdGh1bmtcIjogMjUsIFwiLi4vdm5vZGUvaXMtdmhvb2tcIjogMjYsIFwiLi4vdm5vZGUvaXMtdm5vZGVcIjogMjcsIFwiLi4vdm5vZGUvaXMtdnRleHRcIjogMjgsIFwiLi4vdm5vZGUvaXMtd2lkZ2V0XCI6IDI5LCBcIi4uL3Zub2RlL3Zub2RlLmpzXCI6IDMxLCBcIi4uL3Zub2RlL3Z0ZXh0LmpzXCI6IDMzLCBcIi4vaG9va3MvZXYtaG9vay5qc1wiOiAyMCwgXCIuL2hvb2tzL3NvZnQtc2V0LWhvb2suanNcIjogMjEsIFwiLi9wYXJzZS10YWcuanNcIjogMjMsIFwieC1pcy1hcnJheVwiOiAxMiB9XSwgMjM6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICBcInVzZSBzdHJpY3RcIjtcblxuICAgICAgICAgICAgdmFyIHNwbGl0ID0gcmVxdWlyZShcImJyb3dzZXItc3BsaXRcIik7XG5cbiAgICAgICAgICAgIHZhciBjbGFzc0lkU3BsaXQgPSAvKFtcXC4jXT9bYS16QS1aMC05XFx1MDA3Ri1cXHVGRkZGXzotXSspLztcbiAgICAgICAgICAgIHZhciBub3RDbGFzc0lkID0gL15cXC58Iy87XG5cbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gcGFyc2VUYWc7XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIHBhcnNlVGFnKHRhZywgcHJvcHMpIHtcbiAgICAgICAgICAgICAgICBpZiAoIXRhZykge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gXCJESVZcIjtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICB2YXIgbm9JZCA9ICFwcm9wcy5oYXNPd25Qcm9wZXJ0eShcImlkXCIpO1xuXG4gICAgICAgICAgICAgICAgdmFyIHRhZ1BhcnRzID0gc3BsaXQodGFnLCBjbGFzc0lkU3BsaXQpO1xuICAgICAgICAgICAgICAgIHZhciB0YWdOYW1lID0gbnVsbDtcblxuICAgICAgICAgICAgICAgIGlmIChub3RDbGFzc0lkLnRlc3QodGFnUGFydHNbMV0pKSB7XG4gICAgICAgICAgICAgICAgICAgIHRhZ05hbWUgPSBcIkRJVlwiO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHZhciBjbGFzc2VzLCBwYXJ0LCB0eXBlLCBpO1xuXG4gICAgICAgICAgICAgICAgZm9yIChpID0gMDsgaSA8IHRhZ1BhcnRzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICAgICAgICAgIHBhcnQgPSB0YWdQYXJ0c1tpXTtcblxuICAgICAgICAgICAgICAgICAgICBpZiAoIXBhcnQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnRpbnVlO1xuICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgdHlwZSA9IHBhcnQuY2hhckF0KDApO1xuXG4gICAgICAgICAgICAgICAgICAgIGlmICghdGFnTmFtZSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgdGFnTmFtZSA9IHBhcnQ7XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAodHlwZSA9PT0gXCIuXCIpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGNsYXNzZXMgPSBjbGFzc2VzIHx8IFtdO1xuICAgICAgICAgICAgICAgICAgICAgICAgY2xhc3Nlcy5wdXNoKHBhcnQuc3Vic3RyaW5nKDEsIHBhcnQubGVuZ3RoKSk7XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAodHlwZSA9PT0gXCIjXCIgJiYgbm9JZCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgcHJvcHMuaWQgPSBwYXJ0LnN1YnN0cmluZygxLCBwYXJ0Lmxlbmd0aCk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICBpZiAoY2xhc3Nlcykge1xuICAgICAgICAgICAgICAgICAgICBpZiAocHJvcHMuY2xhc3NOYW1lKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBjbGFzc2VzLnB1c2gocHJvcHMuY2xhc3NOYW1lKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgIHByb3BzLmNsYXNzTmFtZSA9IGNsYXNzZXMuam9pbihcIiBcIik7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgcmV0dXJuIHByb3BzLm5hbWVzcGFjZSA/IHRhZ05hbWUgOiB0YWdOYW1lLnRvVXBwZXJDYXNlKCk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0sIHsgXCJicm93c2VyLXNwbGl0XCI6IDUgfV0sIDI0OiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge1xuICAgICAgICAgICAgdmFyIGlzVk5vZGUgPSByZXF1aXJlKFwiLi9pcy12bm9kZVwiKTtcbiAgICAgICAgICAgIHZhciBpc1ZUZXh0ID0gcmVxdWlyZShcIi4vaXMtdnRleHRcIik7XG4gICAgICAgICAgICB2YXIgaXNXaWRnZXQgPSByZXF1aXJlKFwiLi9pcy13aWRnZXRcIik7XG4gICAgICAgICAgICB2YXIgaXNUaHVuayA9IHJlcXVpcmUoXCIuL2lzLXRodW5rXCIpO1xuXG4gICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IGhhbmRsZVRodW5rO1xuXG4gICAgICAgICAgICBmdW5jdGlvbiBoYW5kbGVUaHVuayhhLCBiKSB7XG4gICAgICAgICAgICAgICAgdmFyIHJlbmRlcmVkQSA9IGE7XG4gICAgICAgICAgICAgICAgdmFyIHJlbmRlcmVkQiA9IGI7XG5cbiAgICAgICAgICAgICAgICBpZiAoaXNUaHVuayhiKSkge1xuICAgICAgICAgICAgICAgICAgICByZW5kZXJlZEIgPSByZW5kZXJUaHVuayhiLCBhKTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICBpZiAoaXNUaHVuayhhKSkge1xuICAgICAgICAgICAgICAgICAgICByZW5kZXJlZEEgPSByZW5kZXJUaHVuayhhLCBudWxsKTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgICAgICAgICBhOiByZW5kZXJlZEEsXG4gICAgICAgICAgICAgICAgICAgIGI6IHJlbmRlcmVkQlxuICAgICAgICAgICAgICAgIH07XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIHJlbmRlclRodW5rKHRodW5rLCBwcmV2aW91cykge1xuICAgICAgICAgICAgICAgIHZhciByZW5kZXJlZFRodW5rID0gdGh1bmsudm5vZGU7XG5cbiAgICAgICAgICAgICAgICBpZiAoIXJlbmRlcmVkVGh1bmspIHtcbiAgICAgICAgICAgICAgICAgICAgcmVuZGVyZWRUaHVuayA9IHRodW5rLnZub2RlID0gdGh1bmsucmVuZGVyKHByZXZpb3VzKTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICBpZiAoIShpc1ZOb2RlKHJlbmRlcmVkVGh1bmspIHx8IGlzVlRleHQocmVuZGVyZWRUaHVuaykgfHwgaXNXaWRnZXQocmVuZGVyZWRUaHVuaykpKSB7XG4gICAgICAgICAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcihcInRodW5rIGRpZCBub3QgcmV0dXJuIGEgdmFsaWQgbm9kZVwiKTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICByZXR1cm4gcmVuZGVyZWRUaHVuaztcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSwgeyBcIi4vaXMtdGh1bmtcIjogMjUsIFwiLi9pcy12bm9kZVwiOiAyNywgXCIuL2lzLXZ0ZXh0XCI6IDI4LCBcIi4vaXMtd2lkZ2V0XCI6IDI5IH1dLCAyNTogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHtcbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gaXNUaHVuaztcblxuICAgICAgICAgICAgZnVuY3Rpb24gaXNUaHVuayh0KSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHQgJiYgdC50eXBlID09PSBcIlRodW5rXCI7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0sIHt9XSwgMjY6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IGlzSG9vaztcblxuICAgICAgICAgICAgZnVuY3Rpb24gaXNIb29rKGhvb2spIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gaG9vayAmJiAodHlwZW9mIGhvb2suaG9vayA9PT0gXCJmdW5jdGlvblwiICYmICFob29rLmhhc093blByb3BlcnR5KFwiaG9va1wiKSB8fCB0eXBlb2YgaG9vay51bmhvb2sgPT09IFwiZnVuY3Rpb25cIiAmJiAhaG9vay5oYXNPd25Qcm9wZXJ0eShcInVuaG9va1wiKSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0sIHt9XSwgMjc6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICB2YXIgdmVyc2lvbiA9IHJlcXVpcmUoXCIuL3ZlcnNpb25cIik7XG5cbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gaXNWaXJ0dWFsTm9kZTtcblxuICAgICAgICAgICAgZnVuY3Rpb24gaXNWaXJ0dWFsTm9kZSh4KSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHggJiYgeC50eXBlID09PSBcIlZpcnR1YWxOb2RlXCIgJiYgeC52ZXJzaW9uID09PSB2ZXJzaW9uO1xuICAgICAgICAgICAgfVxuICAgICAgICB9LCB7IFwiLi92ZXJzaW9uXCI6IDMwIH1dLCAyODogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHtcbiAgICAgICAgICAgIHZhciB2ZXJzaW9uID0gcmVxdWlyZShcIi4vdmVyc2lvblwiKTtcblxuICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBpc1ZpcnR1YWxUZXh0O1xuXG4gICAgICAgICAgICBmdW5jdGlvbiBpc1ZpcnR1YWxUZXh0KHgpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4geCAmJiB4LnR5cGUgPT09IFwiVmlydHVhbFRleHRcIiAmJiB4LnZlcnNpb24gPT09IHZlcnNpb247XG4gICAgICAgICAgICB9XG4gICAgICAgIH0sIHsgXCIuL3ZlcnNpb25cIjogMzAgfV0sIDI5OiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge1xuICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBpc1dpZGdldDtcblxuICAgICAgICAgICAgZnVuY3Rpb24gaXNXaWRnZXQodykge1xuICAgICAgICAgICAgICAgIHJldHVybiB3ICYmIHcudHlwZSA9PT0gXCJXaWRnZXRcIjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSwge31dLCAzMDogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHtcbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gXCIyXCI7XG4gICAgICAgIH0sIHt9XSwgMzE6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICB2YXIgdmVyc2lvbiA9IHJlcXVpcmUoXCIuL3ZlcnNpb25cIik7XG4gICAgICAgICAgICB2YXIgaXNWTm9kZSA9IHJlcXVpcmUoXCIuL2lzLXZub2RlXCIpO1xuICAgICAgICAgICAgdmFyIGlzV2lkZ2V0ID0gcmVxdWlyZShcIi4vaXMtd2lkZ2V0XCIpO1xuICAgICAgICAgICAgdmFyIGlzVGh1bmsgPSByZXF1aXJlKFwiLi9pcy10aHVua1wiKTtcbiAgICAgICAgICAgIHZhciBpc1ZIb29rID0gcmVxdWlyZShcIi4vaXMtdmhvb2tcIik7XG5cbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gVmlydHVhbE5vZGU7XG5cbiAgICAgICAgICAgIHZhciBub1Byb3BlcnRpZXMgPSB7fTtcbiAgICAgICAgICAgIHZhciBub0NoaWxkcmVuID0gW107XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIFZpcnR1YWxOb2RlKHRhZ05hbWUsIHByb3BlcnRpZXMsIGNoaWxkcmVuLCBrZXksIG5hbWVzcGFjZSkge1xuICAgICAgICAgICAgICAgIHRoaXMudGFnTmFtZSA9IHRhZ05hbWU7XG4gICAgICAgICAgICAgICAgdGhpcy5wcm9wZXJ0aWVzID0gcHJvcGVydGllcyB8fCBub1Byb3BlcnRpZXM7XG4gICAgICAgICAgICAgICAgdGhpcy5jaGlsZHJlbiA9IGNoaWxkcmVuIHx8IG5vQ2hpbGRyZW47XG4gICAgICAgICAgICAgICAgdGhpcy5rZXkgPSBrZXkgIT0gbnVsbCA/IFN0cmluZyhrZXkpIDogdW5kZWZpbmVkO1xuICAgICAgICAgICAgICAgIHRoaXMubmFtZXNwYWNlID0gdHlwZW9mIG5hbWVzcGFjZSA9PT0gXCJzdHJpbmdcIiA/IG5hbWVzcGFjZSA6IG51bGw7XG5cbiAgICAgICAgICAgICAgICB2YXIgY291bnQgPSBjaGlsZHJlbiAmJiBjaGlsZHJlbi5sZW5ndGggfHwgMDtcbiAgICAgICAgICAgICAgICB2YXIgZGVzY2VuZGFudHMgPSAwO1xuICAgICAgICAgICAgICAgIHZhciBoYXNXaWRnZXRzID0gZmFsc2U7XG4gICAgICAgICAgICAgICAgdmFyIGhhc1RodW5rcyA9IGZhbHNlO1xuICAgICAgICAgICAgICAgIHZhciBkZXNjZW5kYW50SG9va3MgPSBmYWxzZTtcbiAgICAgICAgICAgICAgICB2YXIgaG9va3M7XG5cbiAgICAgICAgICAgICAgICBmb3IgKHZhciBwcm9wTmFtZSBpbiBwcm9wZXJ0aWVzKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmIChwcm9wZXJ0aWVzLmhhc093blByb3BlcnR5KHByb3BOYW1lKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgdmFyIHByb3BlcnR5ID0gcHJvcGVydGllc1twcm9wTmFtZV07XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoaXNWSG9vayhwcm9wZXJ0eSkgJiYgcHJvcGVydHkudW5ob29rKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKCFob29rcykge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBob29rcyA9IHt9O1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGhvb2tzW3Byb3BOYW1lXSA9IHByb3BlcnR5O1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCBjb3VudDsgaSsrKSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciBjaGlsZCA9IGNoaWxkcmVuW2ldO1xuICAgICAgICAgICAgICAgICAgICBpZiAoaXNWTm9kZShjaGlsZCkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGRlc2NlbmRhbnRzICs9IGNoaWxkLmNvdW50IHx8IDA7XG5cbiAgICAgICAgICAgICAgICAgICAgICAgIGlmICghaGFzV2lkZ2V0cyAmJiBjaGlsZC5oYXNXaWRnZXRzKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaGFzV2lkZ2V0cyA9IHRydWU7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgICAgIGlmICghaGFzVGh1bmtzICYmIGNoaWxkLmhhc1RodW5rcykge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGhhc1RodW5rcyA9IHRydWU7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgICAgIGlmICghZGVzY2VuZGFudEhvb2tzICYmIChjaGlsZC5ob29rcyB8fCBjaGlsZC5kZXNjZW5kYW50SG9va3MpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgZGVzY2VuZGFudEhvb2tzID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIGlmICghaGFzV2lkZ2V0cyAmJiBpc1dpZGdldChjaGlsZCkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmICh0eXBlb2YgY2hpbGQuZGVzdHJveSA9PT0gXCJmdW5jdGlvblwiKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaGFzV2lkZ2V0cyA9IHRydWU7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoIWhhc1RodW5rcyAmJiBpc1RodW5rKGNoaWxkKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgaGFzVGh1bmtzID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHRoaXMuY291bnQgPSBjb3VudCArIGRlc2NlbmRhbnRzO1xuICAgICAgICAgICAgICAgIHRoaXMuaGFzV2lkZ2V0cyA9IGhhc1dpZGdldHM7XG4gICAgICAgICAgICAgICAgdGhpcy5oYXNUaHVua3MgPSBoYXNUaHVua3M7XG4gICAgICAgICAgICAgICAgdGhpcy5ob29rcyA9IGhvb2tzO1xuICAgICAgICAgICAgICAgIHRoaXMuZGVzY2VuZGFudEhvb2tzID0gZGVzY2VuZGFudEhvb2tzO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBWaXJ0dWFsTm9kZS5wcm90b3R5cGUudmVyc2lvbiA9IHZlcnNpb247XG4gICAgICAgICAgICBWaXJ0dWFsTm9kZS5wcm90b3R5cGUudHlwZSA9IFwiVmlydHVhbE5vZGVcIjtcbiAgICAgICAgfSwgeyBcIi4vaXMtdGh1bmtcIjogMjUsIFwiLi9pcy12aG9va1wiOiAyNiwgXCIuL2lzLXZub2RlXCI6IDI3LCBcIi4vaXMtd2lkZ2V0XCI6IDI5LCBcIi4vdmVyc2lvblwiOiAzMCB9XSwgMzI6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICB2YXIgdmVyc2lvbiA9IHJlcXVpcmUoXCIuL3ZlcnNpb25cIik7XG5cbiAgICAgICAgICAgIFZpcnR1YWxQYXRjaC5OT05FID0gMDtcbiAgICAgICAgICAgIFZpcnR1YWxQYXRjaC5WVEVYVCA9IDE7XG4gICAgICAgICAgICBWaXJ0dWFsUGF0Y2guVk5PREUgPSAyO1xuICAgICAgICAgICAgVmlydHVhbFBhdGNoLldJREdFVCA9IDM7XG4gICAgICAgICAgICBWaXJ0dWFsUGF0Y2guUFJPUFMgPSA0O1xuICAgICAgICAgICAgVmlydHVhbFBhdGNoLk9SREVSID0gNTtcbiAgICAgICAgICAgIFZpcnR1YWxQYXRjaC5JTlNFUlQgPSA2O1xuICAgICAgICAgICAgVmlydHVhbFBhdGNoLlJFTU9WRSA9IDc7XG4gICAgICAgICAgICBWaXJ0dWFsUGF0Y2guVEhVTksgPSA4O1xuXG4gICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IFZpcnR1YWxQYXRjaDtcblxuICAgICAgICAgICAgZnVuY3Rpb24gVmlydHVhbFBhdGNoKHR5cGUsIHZOb2RlLCBwYXRjaCkge1xuICAgICAgICAgICAgICAgIHRoaXMudHlwZSA9IE51bWJlcih0eXBlKTtcbiAgICAgICAgICAgICAgICB0aGlzLnZOb2RlID0gdk5vZGU7XG4gICAgICAgICAgICAgICAgdGhpcy5wYXRjaCA9IHBhdGNoO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBWaXJ0dWFsUGF0Y2gucHJvdG90eXBlLnZlcnNpb24gPSB2ZXJzaW9uO1xuICAgICAgICAgICAgVmlydHVhbFBhdGNoLnByb3RvdHlwZS50eXBlID0gXCJWaXJ0dWFsUGF0Y2hcIjtcbiAgICAgICAgfSwgeyBcIi4vdmVyc2lvblwiOiAzMCB9XSwgMzM6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICB2YXIgdmVyc2lvbiA9IHJlcXVpcmUoXCIuL3ZlcnNpb25cIik7XG5cbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gVmlydHVhbFRleHQ7XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIFZpcnR1YWxUZXh0KHRleHQpIHtcbiAgICAgICAgICAgICAgICB0aGlzLnRleHQgPSBTdHJpbmcodGV4dCk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIFZpcnR1YWxUZXh0LnByb3RvdHlwZS52ZXJzaW9uID0gdmVyc2lvbjtcbiAgICAgICAgICAgIFZpcnR1YWxUZXh0LnByb3RvdHlwZS50eXBlID0gXCJWaXJ0dWFsVGV4dFwiO1xuICAgICAgICB9LCB7IFwiLi92ZXJzaW9uXCI6IDMwIH1dLCAzNDogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHtcbiAgICAgICAgICAgIHZhciBpc09iamVjdCA9IHJlcXVpcmUoXCJpcy1vYmplY3RcIik7XG4gICAgICAgICAgICB2YXIgaXNIb29rID0gcmVxdWlyZShcIi4uL3Zub2RlL2lzLXZob29rXCIpO1xuXG4gICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IGRpZmZQcm9wcztcblxuICAgICAgICAgICAgZnVuY3Rpb24gZGlmZlByb3BzKGEsIGIpIHtcbiAgICAgICAgICAgICAgICB2YXIgZGlmZjtcblxuICAgICAgICAgICAgICAgIGZvciAodmFyIGFLZXkgaW4gYSkge1xuICAgICAgICAgICAgICAgICAgICBpZiAoIShhS2V5IGluIGIpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBkaWZmID0gZGlmZiB8fCB7fTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGRpZmZbYUtleV0gPSB1bmRlZmluZWQ7XG4gICAgICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgICAgICB2YXIgYVZhbHVlID0gYVthS2V5XTtcbiAgICAgICAgICAgICAgICAgICAgdmFyIGJWYWx1ZSA9IGJbYUtleV07XG5cbiAgICAgICAgICAgICAgICAgICAgaWYgKGFWYWx1ZSA9PT0gYlZhbHVlKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBjb250aW51ZTtcbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIGlmIChpc09iamVjdChhVmFsdWUpICYmIGlzT2JqZWN0KGJWYWx1ZSkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChnZXRQcm90b3R5cGUoYlZhbHVlKSAhPT0gZ2V0UHJvdG90eXBlKGFWYWx1ZSkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBkaWZmID0gZGlmZiB8fCB7fTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBkaWZmW2FLZXldID0gYlZhbHVlO1xuICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIGlmIChpc0hvb2soYlZhbHVlKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRpZmYgPSBkaWZmIHx8IHt9O1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRpZmZbYUtleV0gPSBiVmFsdWU7XG4gICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZhciBvYmplY3REaWZmID0gZGlmZlByb3BzKGFWYWx1ZSwgYlZhbHVlKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAob2JqZWN0RGlmZikge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBkaWZmID0gZGlmZiB8fCB7fTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZGlmZlthS2V5XSA9IG9iamVjdERpZmY7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgZGlmZiA9IGRpZmYgfHwge307XG4gICAgICAgICAgICAgICAgICAgICAgICBkaWZmW2FLZXldID0gYlZhbHVlO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgZm9yICh2YXIgYktleSBpbiBiKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmICghKGJLZXkgaW4gYSkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGRpZmYgPSBkaWZmIHx8IHt9O1xuICAgICAgICAgICAgICAgICAgICAgICAgZGlmZltiS2V5XSA9IGJbYktleV07XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICByZXR1cm4gZGlmZjtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZnVuY3Rpb24gZ2V0UHJvdG90eXBlKHZhbHVlKSB7XG4gICAgICAgICAgICAgICAgaWYgKE9iamVjdC5nZXRQcm90b3R5cGVPZikge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gT2JqZWN0LmdldFByb3RvdHlwZU9mKHZhbHVlKTtcbiAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKHZhbHVlLl9fcHJvdG9fXykge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gdmFsdWUuX19wcm90b19fO1xuICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAodmFsdWUuY29uc3RydWN0b3IpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHZhbHVlLmNvbnN0cnVjdG9yLnByb3RvdHlwZTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH0sIHsgXCIuLi92bm9kZS9pcy12aG9va1wiOiAyNiwgXCJpcy1vYmplY3RcIjogMTEgfV0sIDM1OiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge1xuICAgICAgICAgICAgdmFyIGlzQXJyYXkgPSByZXF1aXJlKFwieC1pcy1hcnJheVwiKTtcblxuICAgICAgICAgICAgdmFyIFZQYXRjaCA9IHJlcXVpcmUoXCIuLi92bm9kZS92cGF0Y2hcIik7XG4gICAgICAgICAgICB2YXIgaXNWTm9kZSA9IHJlcXVpcmUoXCIuLi92bm9kZS9pcy12bm9kZVwiKTtcbiAgICAgICAgICAgIHZhciBpc1ZUZXh0ID0gcmVxdWlyZShcIi4uL3Zub2RlL2lzLXZ0ZXh0XCIpO1xuICAgICAgICAgICAgdmFyIGlzV2lkZ2V0ID0gcmVxdWlyZShcIi4uL3Zub2RlL2lzLXdpZGdldFwiKTtcbiAgICAgICAgICAgIHZhciBpc1RodW5rID0gcmVxdWlyZShcIi4uL3Zub2RlL2lzLXRodW5rXCIpO1xuICAgICAgICAgICAgdmFyIGhhbmRsZVRodW5rID0gcmVxdWlyZShcIi4uL3Zub2RlL2hhbmRsZS10aHVua1wiKTtcblxuICAgICAgICAgICAgdmFyIGRpZmZQcm9wcyA9IHJlcXVpcmUoXCIuL2RpZmYtcHJvcHNcIik7XG5cbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gZGlmZjtcblxuICAgICAgICAgICAgZnVuY3Rpb24gZGlmZihhLCBiKSB7XG4gICAgICAgICAgICAgICAgdmFyIHBhdGNoID0geyBhOiBhIH07XG4gICAgICAgICAgICAgICAgd2FsayhhLCBiLCBwYXRjaCwgMCk7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHBhdGNoO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBmdW5jdGlvbiB3YWxrKGEsIGIsIHBhdGNoLCBpbmRleCkge1xuICAgICAgICAgICAgICAgIGlmIChhID09PSBiKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICB2YXIgYXBwbHkgPSBwYXRjaFtpbmRleF07XG4gICAgICAgICAgICAgICAgdmFyIGFwcGx5Q2xlYXIgPSBmYWxzZTtcblxuICAgICAgICAgICAgICAgIGlmIChpc1RodW5rKGEpIHx8IGlzVGh1bmsoYikpIHtcbiAgICAgICAgICAgICAgICAgICAgdGh1bmtzKGEsIGIsIHBhdGNoLCBpbmRleCk7XG4gICAgICAgICAgICAgICAgfSBlbHNlIGlmIChiID09IG51bGwpIHtcblxuICAgICAgICAgICAgICAgICAgICAvLyBJZiBhIGlzIGEgd2lkZ2V0IHdlIHdpbGwgYWRkIGEgcmVtb3ZlIHBhdGNoIGZvciBpdFxuICAgICAgICAgICAgICAgICAgICAvLyBPdGhlcndpc2UgYW55IGNoaWxkIHdpZGdldHMvaG9va3MgbXVzdCBiZSBkZXN0cm95ZWQuXG4gICAgICAgICAgICAgICAgICAgIC8vIFRoaXMgcHJldmVudHMgYWRkaW5nIHR3byByZW1vdmUgcGF0Y2hlcyBmb3IgYSB3aWRnZXQuXG4gICAgICAgICAgICAgICAgICAgIGlmICghaXNXaWRnZXQoYSkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGNsZWFyU3RhdGUoYSwgcGF0Y2gsIGluZGV4KTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGFwcGx5ID0gcGF0Y2hbaW5kZXhdO1xuICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgYXBwbHkgPSBhcHBlbmRQYXRjaChhcHBseSwgbmV3IFZQYXRjaChWUGF0Y2guUkVNT1ZFLCBhLCBiKSk7XG4gICAgICAgICAgICAgICAgfSBlbHNlIGlmIChpc1ZOb2RlKGIpKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmIChpc1ZOb2RlKGEpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoYS50YWdOYW1lID09PSBiLnRhZ05hbWUgJiYgYS5uYW1lc3BhY2UgPT09IGIubmFtZXNwYWNlICYmIGEua2V5ID09PSBiLmtleSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZhciBwcm9wc1BhdGNoID0gZGlmZlByb3BzKGEucHJvcGVydGllcywgYi5wcm9wZXJ0aWVzKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAocHJvcHNQYXRjaCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBhcHBseSA9IGFwcGVuZFBhdGNoKGFwcGx5LCBuZXcgVlBhdGNoKFZQYXRjaC5QUk9QUywgYSwgcHJvcHNQYXRjaCkpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBhcHBseSA9IGRpZmZDaGlsZHJlbihhLCBiLCBwYXRjaCwgYXBwbHksIGluZGV4KTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgYXBwbHkgPSBhcHBlbmRQYXRjaChhcHBseSwgbmV3IFZQYXRjaChWUGF0Y2guVk5PREUsIGEsIGIpKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBhcHBseUNsZWFyID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGFwcGx5ID0gYXBwZW5kUGF0Y2goYXBwbHksIG5ldyBWUGF0Y2goVlBhdGNoLlZOT0RFLCBhLCBiKSk7XG4gICAgICAgICAgICAgICAgICAgICAgICBhcHBseUNsZWFyID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoaXNWVGV4dChiKSkge1xuICAgICAgICAgICAgICAgICAgICBpZiAoIWlzVlRleHQoYSkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGFwcGx5ID0gYXBwZW5kUGF0Y2goYXBwbHksIG5ldyBWUGF0Y2goVlBhdGNoLlZURVhULCBhLCBiKSk7XG4gICAgICAgICAgICAgICAgICAgICAgICBhcHBseUNsZWFyID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIGlmIChhLnRleHQgIT09IGIudGV4dCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgYXBwbHkgPSBhcHBlbmRQYXRjaChhcHBseSwgbmV3IFZQYXRjaChWUGF0Y2guVlRFWFQsIGEsIGIpKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoaXNXaWRnZXQoYikpIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKCFpc1dpZGdldChhKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgYXBwbHlDbGVhciA9IHRydWU7XG4gICAgICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgICAgICBhcHBseSA9IGFwcGVuZFBhdGNoKGFwcGx5LCBuZXcgVlBhdGNoKFZQYXRjaC5XSURHRVQsIGEsIGIpKTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICBpZiAoYXBwbHkpIHtcbiAgICAgICAgICAgICAgICAgICAgcGF0Y2hbaW5kZXhdID0gYXBwbHk7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgaWYgKGFwcGx5Q2xlYXIpIHtcbiAgICAgICAgICAgICAgICAgICAgY2xlYXJTdGF0ZShhLCBwYXRjaCwgaW5kZXgpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZnVuY3Rpb24gZGlmZkNoaWxkcmVuKGEsIGIsIHBhdGNoLCBhcHBseSwgaW5kZXgpIHtcbiAgICAgICAgICAgICAgICB2YXIgYUNoaWxkcmVuID0gYS5jaGlsZHJlbjtcbiAgICAgICAgICAgICAgICB2YXIgb3JkZXJlZFNldCA9IHJlb3JkZXIoYUNoaWxkcmVuLCBiLmNoaWxkcmVuKTtcbiAgICAgICAgICAgICAgICB2YXIgYkNoaWxkcmVuID0gb3JkZXJlZFNldC5jaGlsZHJlbjtcblxuICAgICAgICAgICAgICAgIHZhciBhTGVuID0gYUNoaWxkcmVuLmxlbmd0aDtcbiAgICAgICAgICAgICAgICB2YXIgYkxlbiA9IGJDaGlsZHJlbi5sZW5ndGg7XG4gICAgICAgICAgICAgICAgdmFyIGxlbiA9IGFMZW4gPiBiTGVuID8gYUxlbiA6IGJMZW47XG5cbiAgICAgICAgICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IGxlbjsgaSsrKSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciBsZWZ0Tm9kZSA9IGFDaGlsZHJlbltpXTtcbiAgICAgICAgICAgICAgICAgICAgdmFyIHJpZ2h0Tm9kZSA9IGJDaGlsZHJlbltpXTtcbiAgICAgICAgICAgICAgICAgICAgaW5kZXggKz0gMTtcblxuICAgICAgICAgICAgICAgICAgICBpZiAoIWxlZnROb2RlKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAocmlnaHROb2RlKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gRXhjZXNzIG5vZGVzIGluIGIgbmVlZCB0byBiZSBhZGRlZFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGFwcGx5ID0gYXBwZW5kUGF0Y2goYXBwbHksIG5ldyBWUGF0Y2goVlBhdGNoLklOU0VSVCwgbnVsbCwgcmlnaHROb2RlKSk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICB3YWxrKGxlZnROb2RlLCByaWdodE5vZGUsIHBhdGNoLCBpbmRleCk7XG4gICAgICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgICAgICBpZiAoaXNWTm9kZShsZWZ0Tm9kZSkgJiYgbGVmdE5vZGUuY291bnQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGluZGV4ICs9IGxlZnROb2RlLmNvdW50O1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgaWYgKG9yZGVyZWRTZXQubW92ZXMpIHtcbiAgICAgICAgICAgICAgICAgICAgLy8gUmVvcmRlciBub2RlcyBsYXN0XG4gICAgICAgICAgICAgICAgICAgIGFwcGx5ID0gYXBwZW5kUGF0Y2goYXBwbHksIG5ldyBWUGF0Y2goVlBhdGNoLk9SREVSLCBhLCBvcmRlcmVkU2V0Lm1vdmVzKSk7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgcmV0dXJuIGFwcGx5O1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBmdW5jdGlvbiBjbGVhclN0YXRlKHZOb2RlLCBwYXRjaCwgaW5kZXgpIHtcbiAgICAgICAgICAgICAgICAvLyBUT0RPOiBNYWtlIHRoaXMgYSBzaW5nbGUgd2Fsaywgbm90IHR3b1xuICAgICAgICAgICAgICAgIHVuaG9vayh2Tm9kZSwgcGF0Y2gsIGluZGV4KTtcbiAgICAgICAgICAgICAgICBkZXN0cm95V2lkZ2V0cyh2Tm9kZSwgcGF0Y2gsIGluZGV4KTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgLy8gUGF0Y2ggcmVjb3JkcyBmb3IgYWxsIGRlc3Ryb3llZCB3aWRnZXRzIG11c3QgYmUgYWRkZWQgYmVjYXVzZSB3ZSBuZWVkXG4gICAgICAgICAgICAvLyBhIERPTSBub2RlIHJlZmVyZW5jZSBmb3IgdGhlIGRlc3Ryb3kgZnVuY3Rpb25cbiAgICAgICAgICAgIGZ1bmN0aW9uIGRlc3Ryb3lXaWRnZXRzKHZOb2RlLCBwYXRjaCwgaW5kZXgpIHtcbiAgICAgICAgICAgICAgICBpZiAoaXNXaWRnZXQodk5vZGUpKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmICh0eXBlb2Ygdk5vZGUuZGVzdHJveSA9PT0gXCJmdW5jdGlvblwiKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBwYXRjaFtpbmRleF0gPSBhcHBlbmRQYXRjaChwYXRjaFtpbmRleF0sIG5ldyBWUGF0Y2goVlBhdGNoLlJFTU9WRSwgdk5vZGUsIG51bGwpKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoaXNWTm9kZSh2Tm9kZSkgJiYgKHZOb2RlLmhhc1dpZGdldHMgfHwgdk5vZGUuaGFzVGh1bmtzKSkge1xuICAgICAgICAgICAgICAgICAgICB2YXIgY2hpbGRyZW4gPSB2Tm9kZS5jaGlsZHJlbjtcbiAgICAgICAgICAgICAgICAgICAgdmFyIGxlbiA9IGNoaWxkcmVuLmxlbmd0aDtcbiAgICAgICAgICAgICAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCBsZW47IGkrKykge1xuICAgICAgICAgICAgICAgICAgICAgICAgdmFyIGNoaWxkID0gY2hpbGRyZW5baV07XG4gICAgICAgICAgICAgICAgICAgICAgICBpbmRleCArPSAxO1xuXG4gICAgICAgICAgICAgICAgICAgICAgICBkZXN0cm95V2lkZ2V0cyhjaGlsZCwgcGF0Y2gsIGluZGV4KTtcblxuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGlzVk5vZGUoY2hpbGQpICYmIGNoaWxkLmNvdW50KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaW5kZXggKz0gY2hpbGQuY291bnQ7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKGlzVGh1bmsodk5vZGUpKSB7XG4gICAgICAgICAgICAgICAgICAgIHRodW5rcyh2Tm9kZSwgbnVsbCwgcGF0Y2gsIGluZGV4KTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIC8vIENyZWF0ZSBhIHN1Yi1wYXRjaCBmb3IgdGh1bmtzXG4gICAgICAgICAgICBmdW5jdGlvbiB0aHVua3MoYSwgYiwgcGF0Y2gsIGluZGV4KSB7XG4gICAgICAgICAgICAgICAgdmFyIG5vZGVzID0gaGFuZGxlVGh1bmsoYSwgYik7XG4gICAgICAgICAgICAgICAgdmFyIHRodW5rUGF0Y2ggPSBkaWZmKG5vZGVzLmEsIG5vZGVzLmIpO1xuICAgICAgICAgICAgICAgIGlmIChoYXNQYXRjaGVzKHRodW5rUGF0Y2gpKSB7XG4gICAgICAgICAgICAgICAgICAgIHBhdGNoW2luZGV4XSA9IG5ldyBWUGF0Y2goVlBhdGNoLlRIVU5LLCBudWxsLCB0aHVua1BhdGNoKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIGhhc1BhdGNoZXMocGF0Y2gpIHtcbiAgICAgICAgICAgICAgICBmb3IgKHZhciBpbmRleCBpbiBwYXRjaCkge1xuICAgICAgICAgICAgICAgICAgICBpZiAoaW5kZXggIT09IFwiYVwiKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgLy8gRXhlY3V0ZSBob29rcyB3aGVuIHR3byBub2RlcyBhcmUgaWRlbnRpY2FsXG4gICAgICAgICAgICBmdW5jdGlvbiB1bmhvb2sodk5vZGUsIHBhdGNoLCBpbmRleCkge1xuICAgICAgICAgICAgICAgIGlmIChpc1ZOb2RlKHZOb2RlKSkge1xuICAgICAgICAgICAgICAgICAgICBpZiAodk5vZGUuaG9va3MpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHBhdGNoW2luZGV4XSA9IGFwcGVuZFBhdGNoKHBhdGNoW2luZGV4XSwgbmV3IFZQYXRjaChWUGF0Y2guUFJPUFMsIHZOb2RlLCB1bmRlZmluZWRLZXlzKHZOb2RlLmhvb2tzKSkpO1xuICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgaWYgKHZOb2RlLmRlc2NlbmRhbnRIb29rcyB8fCB2Tm9kZS5oYXNUaHVua3MpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHZhciBjaGlsZHJlbiA9IHZOb2RlLmNoaWxkcmVuO1xuICAgICAgICAgICAgICAgICAgICAgICAgdmFyIGxlbiA9IGNoaWxkcmVuLmxlbmd0aDtcbiAgICAgICAgICAgICAgICAgICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgbGVuOyBpKyspIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB2YXIgY2hpbGQgPSBjaGlsZHJlbltpXTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpbmRleCArPSAxO1xuXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdW5ob29rKGNoaWxkLCBwYXRjaCwgaW5kZXgpO1xuXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGlzVk5vZGUoY2hpbGQpICYmIGNoaWxkLmNvdW50KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGluZGV4ICs9IGNoaWxkLmNvdW50O1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoaXNUaHVuayh2Tm9kZSkpIHtcbiAgICAgICAgICAgICAgICAgICAgdGh1bmtzKHZOb2RlLCBudWxsLCBwYXRjaCwgaW5kZXgpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZnVuY3Rpb24gdW5kZWZpbmVkS2V5cyhvYmopIHtcbiAgICAgICAgICAgICAgICB2YXIgcmVzdWx0ID0ge307XG5cbiAgICAgICAgICAgICAgICBmb3IgKHZhciBrZXkgaW4gb2JqKSB7XG4gICAgICAgICAgICAgICAgICAgIHJlc3VsdFtrZXldID0gdW5kZWZpbmVkO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHJldHVybiByZXN1bHQ7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIC8vIExpc3QgZGlmZiwgbmFpdmUgbGVmdCB0byByaWdodCByZW9yZGVyaW5nXG4gICAgICAgICAgICBmdW5jdGlvbiByZW9yZGVyKGFDaGlsZHJlbiwgYkNoaWxkcmVuKSB7XG4gICAgICAgICAgICAgICAgLy8gTyhNKSB0aW1lLCBPKE0pIG1lbW9yeVxuICAgICAgICAgICAgICAgIHZhciBiQ2hpbGRJbmRleCA9IGtleUluZGV4KGJDaGlsZHJlbik7XG4gICAgICAgICAgICAgICAgdmFyIGJLZXlzID0gYkNoaWxkSW5kZXgua2V5cztcbiAgICAgICAgICAgICAgICB2YXIgYkZyZWUgPSBiQ2hpbGRJbmRleC5mcmVlO1xuXG4gICAgICAgICAgICAgICAgaWYgKGJGcmVlLmxlbmd0aCA9PT0gYkNoaWxkcmVuLmxlbmd0aCkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgICAgICAgICAgICAgY2hpbGRyZW46IGJDaGlsZHJlbixcbiAgICAgICAgICAgICAgICAgICAgICAgIG1vdmVzOiBudWxsXG4gICAgICAgICAgICAgICAgICAgIH07XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgLy8gTyhOKSB0aW1lLCBPKE4pIG1lbW9yeVxuICAgICAgICAgICAgICAgIHZhciBhQ2hpbGRJbmRleCA9IGtleUluZGV4KGFDaGlsZHJlbik7XG4gICAgICAgICAgICAgICAgdmFyIGFLZXlzID0gYUNoaWxkSW5kZXgua2V5cztcbiAgICAgICAgICAgICAgICB2YXIgYUZyZWUgPSBhQ2hpbGRJbmRleC5mcmVlO1xuXG4gICAgICAgICAgICAgICAgaWYgKGFGcmVlLmxlbmd0aCA9PT0gYUNoaWxkcmVuLmxlbmd0aCkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgICAgICAgICAgICAgY2hpbGRyZW46IGJDaGlsZHJlbixcbiAgICAgICAgICAgICAgICAgICAgICAgIG1vdmVzOiBudWxsXG4gICAgICAgICAgICAgICAgICAgIH07XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgLy8gTyhNQVgoTiwgTSkpIG1lbW9yeVxuICAgICAgICAgICAgICAgIHZhciBuZXdDaGlsZHJlbiA9IFtdO1xuXG4gICAgICAgICAgICAgICAgdmFyIGZyZWVJbmRleCA9IDA7XG4gICAgICAgICAgICAgICAgdmFyIGZyZWVDb3VudCA9IGJGcmVlLmxlbmd0aDtcbiAgICAgICAgICAgICAgICB2YXIgZGVsZXRlZEl0ZW1zID0gMDtcblxuICAgICAgICAgICAgICAgIC8vIEl0ZXJhdGUgdGhyb3VnaCBhIGFuZCBtYXRjaCBhIG5vZGUgaW4gYlxuICAgICAgICAgICAgICAgIC8vIE8oTikgdGltZSxcbiAgICAgICAgICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IGFDaGlsZHJlbi5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgICAgICAgICB2YXIgYUl0ZW0gPSBhQ2hpbGRyZW5baV07XG4gICAgICAgICAgICAgICAgICAgIHZhciBpdGVtSW5kZXg7XG5cbiAgICAgICAgICAgICAgICAgICAgaWYgKGFJdGVtLmtleSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGJLZXlzLmhhc093blByb3BlcnR5KGFJdGVtLmtleSkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBNYXRjaCB1cCB0aGUgb2xkIGtleXNcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpdGVtSW5kZXggPSBiS2V5c1thSXRlbS5rZXldO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIG5ld0NoaWxkcmVuLnB1c2goYkNoaWxkcmVuW2l0ZW1JbmRleF0pO1xuICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBSZW1vdmUgb2xkIGtleWVkIGl0ZW1zXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaXRlbUluZGV4ID0gaSAtIGRlbGV0ZWRJdGVtcysrO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIG5ld0NoaWxkcmVuLnB1c2gobnVsbCk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAvLyBNYXRjaCB0aGUgaXRlbSBpbiBhIHdpdGggdGhlIG5leHQgZnJlZSBpdGVtIGluIGJcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChmcmVlSW5kZXggPCBmcmVlQ291bnQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpdGVtSW5kZXggPSBiRnJlZVtmcmVlSW5kZXgrK107XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgbmV3Q2hpbGRyZW4ucHVzaChiQ2hpbGRyZW5baXRlbUluZGV4XSk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIFRoZXJlIGFyZSBubyBmcmVlIGl0ZW1zIGluIGIgdG8gbWF0Y2ggd2l0aFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIHRoZSBmcmVlIGl0ZW1zIGluIGEsIHNvIHRoZSBleHRyYSBmcmVlIG5vZGVzXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gYXJlIGRlbGV0ZWQuXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaXRlbUluZGV4ID0gaSAtIGRlbGV0ZWRJdGVtcysrO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIG5ld0NoaWxkcmVuLnB1c2gobnVsbCk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICB2YXIgbGFzdEZyZWVJbmRleCA9IGZyZWVJbmRleCA+PSBiRnJlZS5sZW5ndGggPyBiQ2hpbGRyZW4ubGVuZ3RoIDogYkZyZWVbZnJlZUluZGV4XTtcblxuICAgICAgICAgICAgICAgIC8vIEl0ZXJhdGUgdGhyb3VnaCBiIGFuZCBhcHBlbmQgYW55IG5ldyBrZXlzXG4gICAgICAgICAgICAgICAgLy8gTyhNKSB0aW1lXG4gICAgICAgICAgICAgICAgZm9yICh2YXIgaiA9IDA7IGogPCBiQ2hpbGRyZW4ubGVuZ3RoOyBqKyspIHtcbiAgICAgICAgICAgICAgICAgICAgdmFyIG5ld0l0ZW0gPSBiQ2hpbGRyZW5bal07XG5cbiAgICAgICAgICAgICAgICAgICAgaWYgKG5ld0l0ZW0ua2V5KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoIWFLZXlzLmhhc093blByb3BlcnR5KG5ld0l0ZW0ua2V5KSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIEFkZCBhbnkgbmV3IGtleWVkIGl0ZW1zXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gV2UgYXJlIGFkZGluZyBuZXcgaXRlbXMgdG8gdGhlIGVuZCBhbmQgdGhlbiBzb3J0aW5nIHRoZW1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBpbiBwbGFjZS4gSW4gZnV0dXJlIHdlIHNob3VsZCBpbnNlcnQgbmV3IGl0ZW1zIGluIHBsYWNlLlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIG5ld0NoaWxkcmVuLnB1c2gobmV3SXRlbSk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoaiA+PSBsYXN0RnJlZUluZGV4KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAvLyBBZGQgYW55IGxlZnRvdmVyIG5vbi1rZXllZCBpdGVtc1xuICAgICAgICAgICAgICAgICAgICAgICAgbmV3Q2hpbGRyZW4ucHVzaChuZXdJdGVtKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHZhciBzaW11bGF0ZSA9IG5ld0NoaWxkcmVuLnNsaWNlKCk7XG4gICAgICAgICAgICAgICAgdmFyIHNpbXVsYXRlSW5kZXggPSAwO1xuICAgICAgICAgICAgICAgIHZhciByZW1vdmVzID0gW107XG4gICAgICAgICAgICAgICAgdmFyIGluc2VydHMgPSBbXTtcbiAgICAgICAgICAgICAgICB2YXIgc2ltdWxhdGVJdGVtO1xuXG4gICAgICAgICAgICAgICAgZm9yICh2YXIgayA9IDA7IGsgPCBiQ2hpbGRyZW4ubGVuZ3RoOykge1xuICAgICAgICAgICAgICAgICAgICB2YXIgd2FudGVkSXRlbSA9IGJDaGlsZHJlbltrXTtcbiAgICAgICAgICAgICAgICAgICAgc2ltdWxhdGVJdGVtID0gc2ltdWxhdGVbc2ltdWxhdGVJbmRleF07XG5cbiAgICAgICAgICAgICAgICAgICAgLy8gcmVtb3ZlIGl0ZW1zXG4gICAgICAgICAgICAgICAgICAgIHdoaWxlIChzaW11bGF0ZUl0ZW0gPT09IG51bGwgJiYgc2ltdWxhdGUubGVuZ3RoKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICByZW1vdmVzLnB1c2gocmVtb3ZlKHNpbXVsYXRlLCBzaW11bGF0ZUluZGV4LCBudWxsKSk7XG4gICAgICAgICAgICAgICAgICAgICAgICBzaW11bGF0ZUl0ZW0gPSBzaW11bGF0ZVtzaW11bGF0ZUluZGV4XTtcbiAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgIGlmICghc2ltdWxhdGVJdGVtIHx8IHNpbXVsYXRlSXRlbS5rZXkgIT09IHdhbnRlZEl0ZW0ua2V5KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAvLyBpZiB3ZSBuZWVkIGEga2V5IGluIHRoaXMgcG9zaXRpb24uLi5cbiAgICAgICAgICAgICAgICAgICAgICAgIGlmICh3YW50ZWRJdGVtLmtleSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChzaW11bGF0ZUl0ZW0gJiYgc2ltdWxhdGVJdGVtLmtleSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBpZiBhbiBpbnNlcnQgZG9lc24ndCBwdXQgdGhpcyBrZXkgaW4gcGxhY2UsIGl0IG5lZWRzIHRvIG1vdmVcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGJLZXlzW3NpbXVsYXRlSXRlbS5rZXldICE9PSBrICsgMSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmVtb3Zlcy5wdXNoKHJlbW92ZShzaW11bGF0ZSwgc2ltdWxhdGVJbmRleCwgc2ltdWxhdGVJdGVtLmtleSkpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc2ltdWxhdGVJdGVtID0gc2ltdWxhdGVbc2ltdWxhdGVJbmRleF07XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBpZiB0aGUgcmVtb3ZlIGRpZG4ndCBwdXQgdGhlIHdhbnRlZCBpdGVtIGluIHBsYWNlLCB3ZSBuZWVkIHRvIGluc2VydCBpdFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKCFzaW11bGF0ZUl0ZW0gfHwgc2ltdWxhdGVJdGVtLmtleSAhPT0gd2FudGVkSXRlbS5rZXkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpbnNlcnRzLnB1c2goeyBrZXk6IHdhbnRlZEl0ZW0ua2V5LCB0bzogayB9KTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIGl0ZW1zIGFyZSBtYXRjaGluZywgc28gc2tpcCBhaGVhZFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc2ltdWxhdGVJbmRleCsrO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaW5zZXJ0cy5wdXNoKHsga2V5OiB3YW50ZWRJdGVtLmtleSwgdG86IGsgfSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpbnNlcnRzLnB1c2goeyBrZXk6IHdhbnRlZEl0ZW0ua2V5LCB0bzogayB9KTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaysrO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgLy8gYSBrZXkgaW4gc2ltdWxhdGUgaGFzIG5vIG1hdGNoaW5nIHdhbnRlZCBrZXksIHJlbW92ZSBpdFxuICAgICAgICAgICAgICAgICAgICAgICAgZWxzZSBpZiAoc2ltdWxhdGVJdGVtICYmIHNpbXVsYXRlSXRlbS5rZXkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICByZW1vdmVzLnB1c2gocmVtb3ZlKHNpbXVsYXRlLCBzaW11bGF0ZUluZGV4LCBzaW11bGF0ZUl0ZW0ua2V5KSk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBzaW11bGF0ZUluZGV4Kys7XG4gICAgICAgICAgICAgICAgICAgICAgICBrKys7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAvLyByZW1vdmUgYWxsIHRoZSByZW1haW5pbmcgbm9kZXMgZnJvbSBzaW11bGF0ZVxuICAgICAgICAgICAgICAgIHdoaWxlIChzaW11bGF0ZUluZGV4IDwgc2ltdWxhdGUubGVuZ3RoKSB7XG4gICAgICAgICAgICAgICAgICAgIHNpbXVsYXRlSXRlbSA9IHNpbXVsYXRlW3NpbXVsYXRlSW5kZXhdO1xuICAgICAgICAgICAgICAgICAgICByZW1vdmVzLnB1c2gocmVtb3ZlKHNpbXVsYXRlLCBzaW11bGF0ZUluZGV4LCBzaW11bGF0ZUl0ZW0gJiYgc2ltdWxhdGVJdGVtLmtleSkpO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIC8vIElmIHRoZSBvbmx5IG1vdmVzIHdlIGhhdmUgYXJlIGRlbGV0ZXMgdGhlbiB3ZSBjYW4ganVzdFxuICAgICAgICAgICAgICAgIC8vIGxldCB0aGUgZGVsZXRlIHBhdGNoIHJlbW92ZSB0aGVzZSBpdGVtcy5cbiAgICAgICAgICAgICAgICBpZiAocmVtb3Zlcy5sZW5ndGggPT09IGRlbGV0ZWRJdGVtcyAmJiAhaW5zZXJ0cy5sZW5ndGgpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGNoaWxkcmVuOiBuZXdDaGlsZHJlbixcbiAgICAgICAgICAgICAgICAgICAgICAgIG1vdmVzOiBudWxsXG4gICAgICAgICAgICAgICAgICAgIH07XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgICAgICAgICAgY2hpbGRyZW46IG5ld0NoaWxkcmVuLFxuICAgICAgICAgICAgICAgICAgICBtb3Zlczoge1xuICAgICAgICAgICAgICAgICAgICAgICAgcmVtb3ZlczogcmVtb3ZlcyxcbiAgICAgICAgICAgICAgICAgICAgICAgIGluc2VydHM6IGluc2VydHNcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH07XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIHJlbW92ZShhcnIsIGluZGV4LCBrZXkpIHtcbiAgICAgICAgICAgICAgICBhcnIuc3BsaWNlKGluZGV4LCAxKTtcblxuICAgICAgICAgICAgICAgIHJldHVybiB7XG4gICAgICAgICAgICAgICAgICAgIGZyb206IGluZGV4LFxuICAgICAgICAgICAgICAgICAgICBrZXk6IGtleVxuICAgICAgICAgICAgICAgIH07XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIGtleUluZGV4KGNoaWxkcmVuKSB7XG4gICAgICAgICAgICAgICAgdmFyIGtleXMgPSB7fTtcbiAgICAgICAgICAgICAgICB2YXIgZnJlZSA9IFtdO1xuICAgICAgICAgICAgICAgIHZhciBsZW5ndGggPSBjaGlsZHJlbi5sZW5ndGg7XG5cbiAgICAgICAgICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IGxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciBjaGlsZCA9IGNoaWxkcmVuW2ldO1xuXG4gICAgICAgICAgICAgICAgICAgIGlmIChjaGlsZC5rZXkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGtleXNbY2hpbGQua2V5XSA9IGk7XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBmcmVlLnB1c2goaSk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgICAgICAgICBrZXlzOiBrZXlzLCAvLyBBIGhhc2ggb2Yga2V5IG5hbWUgdG8gaW5kZXhcbiAgICAgICAgICAgICAgICAgICAgZnJlZTogZnJlZSAvLyBBbiBhcnJheSBvZiB1bmtleWVkIGl0ZW0gaW5kaWNlc1xuICAgICAgICAgICAgICAgIH07XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIGFwcGVuZFBhdGNoKGFwcGx5LCBwYXRjaCkge1xuICAgICAgICAgICAgICAgIGlmIChhcHBseSkge1xuICAgICAgICAgICAgICAgICAgICBpZiAoaXNBcnJheShhcHBseSkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGFwcGx5LnB1c2gocGF0Y2gpO1xuICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgYXBwbHkgPSBbYXBwbHksIHBhdGNoXTtcbiAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBhcHBseTtcbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gcGF0Y2g7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9LCB7IFwiLi4vdm5vZGUvaGFuZGxlLXRodW5rXCI6IDI0LCBcIi4uL3Zub2RlL2lzLXRodW5rXCI6IDI1LCBcIi4uL3Zub2RlL2lzLXZub2RlXCI6IDI3LCBcIi4uL3Zub2RlL2lzLXZ0ZXh0XCI6IDI4LCBcIi4uL3Zub2RlL2lzLXdpZGdldFwiOiAyOSwgXCIuLi92bm9kZS92cGF0Y2hcIjogMzIsIFwiLi9kaWZmLXByb3BzXCI6IDM0LCBcIngtaXMtYXJyYXlcIjogMTIgfV0gfSwge30sIFs0XSkoNCk7XG59KTtcblxuXG4vLyBQcm9wb3NlZCBmb3IgRVM2XG5cbmNvbnN0IHN0YXJ0ID0gZnVuY3Rpb24gKGRvbVJvb3QsIHJlbmRlckZuLCBpbml0aWFsU3RhdGUsIG9wdGlvbnMgPSBbXSkge1xuICBjb25zdCBuYW1lID0gS2V5d29yZC5oYXNfa2V5X19xbV9fKG9wdGlvbnMsIEtlcm5lbC5TcGVjaWFsRm9ybXMuYXRvbSgnbmFtZScpKSA/IEtleXdvcmQuZ2V0KG9wdGlvbnMsIEtlcm5lbC5TcGVjaWFsRm9ybXMuYXRvbSgnbmFtZScpKSA6IFN5bWJvbCgpO1xuXG4gIHNlbGYucG9zdF9vZmZpY2UuYWRkX21haWxib3gobmFtZSk7XG5cbiAgY29uc3QgdHJlZSA9IHJlbmRlckZuLmFwcGx5KHRoaXMsIGluaXRpYWxTdGF0ZSk7XG4gIGNvbnN0IHJvb3ROb2RlID0gdmlydHVhbERvbS5jcmVhdGUodHJlZSk7XG5cbiAgZG9tUm9vdC5hcHBlbmRDaGlsZChyb290Tm9kZSk7XG4gIHNlbGYucG9zdF9vZmZpY2Uuc2VuZChuYW1lLCBLZXJuZWwuU3BlY2lhbEZvcm1zLnR1cGxlKHJvb3ROb2RlLCB0cmVlLCByZW5kZXJGbikpO1xuXG4gIHJldHVybiBLZXJuZWwuU3BlY2lhbEZvcm1zLnR1cGxlKEtlcm5lbC5TcGVjaWFsRm9ybXMuYXRvbSgnb2snKSwgbmFtZSk7XG59O1xuXG5jb25zdCBzdG9wID0gZnVuY3Rpb24gKGFnZW50LCB0aW1lb3V0ID0gNTAwMCkge1xuICBzZWxmLnBvc3Rfb2ZmaWNlLnJlbW92ZV9tYWlsYm94KGFnZW50KTtcbiAgcmV0dXJuIEtlcm5lbC5TcGVjaWFsRm9ybXMuYXRvbSgnb2snKTtcbn07XG5cbmNvbnN0IF91cGRhdGUgPSBmdW5jdGlvbiAoYWdlbnQsIHN0YXRlKSB7XG5cbiAgY29uc3QgY3VycmVudF9zdGF0ZSA9IHNlbGYucG9zdF9vZmZpY2UucmVjZWl2ZShhZ2VudCk7XG5cbiAgbGV0IHJvb3ROb2RlID0gS2VybmVsLmVsZW0oY3VycmVudF9zdGF0ZSwgMCk7XG4gIGxldCB0cmVlID0gS2VybmVsLmVsZW0oY3VycmVudF9zdGF0ZSwgMSk7XG4gIGxldCByZW5kZXJGbiA9IEtlcm5lbC5lbGVtKGN1cnJlbnRfc3RhdGUsIDIpO1xuXG4gIGxldCBuZXdUcmVlID0gcmVuZGVyRm4uYXBwbHkodGhpcywgc3RhdGUpO1xuXG4gIGxldCBwYXRjaGVzID0gdmlydHVhbERvbS5kaWZmKHRyZWUsIG5ld1RyZWUpO1xuICByb290Tm9kZSA9IHZpcnR1YWxEb20ucGF0Y2gocm9vdE5vZGUsIHBhdGNoZXMpO1xuXG4gIHNlbGYucG9zdF9vZmZpY2Uuc2VuZChhZ2VudCwgS2VybmVsLlNwZWNpYWxGb3Jtcy50dXBsZShyb290Tm9kZSwgbmV3VHJlZSwgcmVuZGVyRm4pKTtcblxuICByZXR1cm4gS2VybmVsLlNwZWNpYWxGb3Jtcy5hdG9tKCdvaycpO1xufTtcblxudmFyIFZpZXcgPSB7XG4gIHN0YXJ0LFxuICBzdG9wLFxuICB1cGRhdGU6IF91cGRhdGVcbn07XG5cbnNlbGYucG9zdF9vZmZpY2UgPSBzZWxmLnBvc3Rfb2ZmaWNlIHx8IG5ldyBQb3N0T2ZmaWNlKCk7XG5cbmV4cG9ydCB7IF9QYXR0ZXJucyBhcyBQYXR0ZXJucywgQml0U3RyaW5nLCBLZXJuZWwsIEF0b20sIEVudW0sIEludGVnZXIsIEpTLCBMaXN0LCBSYW5nZSwgVHVwbGUsIEFnZW50LCBLZXl3b3JkLCBCYXNlLCBfU3RyaW5nIGFzIFN0cmluZywgQml0d2lzZSwgRW51bWVyYWJsZSwgQ29sbGVjdGFibGUsIEluc3BlY3QsIF9NYXAgYXMgTWFwLCBfU2V0IGFzIFNldCwgTWFwU2V0LCBJbnRlZ2VyVHlwZSwgRmxvYXRUeXBlLCB2aXJ0dWFsRG9tIGFzIFZpcnR1YWxET00sIFZpZXcgfTsiXSwiZmlsZSI6ImVsaXhpci5qcyIsInNvdXJjZVJvb3QiOiIvc291cmNlLyJ9 \ No newline at end of file diff --git a/src/javascript/elixir.js b/src/javascript/elixir.js index dc3f70ed..b996befe 100644 --- a/src/javascript/elixir.js +++ b/src/javascript/elixir.js @@ -25,3 +25,4 @@ export { default as Set } from './lib/set'; export { default as MapSet } from './lib/map_set'; export { IntegerType, FloatType } from './lib/protocol'; export { default as VirtualDOM } from './lib/virtual-dom'; +export { default as View } from './lib/view'; diff --git a/src/javascript/lib/view.js b/src/javascript/lib/view.js new file mode 100644 index 00000000..9c864863 --- /dev/null +++ b/src/javascript/lib/view.js @@ -0,0 +1,50 @@ +import Kernel from './kernel'; +import Keyword from './keyword'; +import VirtualDOM from './virtual-dom'; + + +const start = function(domRoot, renderFn, initialState, options = []){ + const name = Keyword.has_key__qm__(options, Kernel.SpecialForms.atom("name")) ? Keyword.get(options, Kernel.SpecialForms.atom("name")) : Symbol(); + + self.post_office.add_mailbox(name); + + const tree = renderFn.apply(this, initialState); + const rootNode = VirtualDOM.create(tree); + + domRoot.appendChild(rootNode); + self.post_office.send(name, Kernel.SpecialForms.tuple(rootNode, tree, renderFn)); + + return Kernel.SpecialForms.tuple(Kernel.SpecialForms.atom("ok"), name); +} + +const stop = function(agent, timeout = 5000){ + self.post_office.remove_mailbox(agent); + return Kernel.SpecialForms.atom("ok"); +} + + +const update = function(agent, state){ + + const current_state = self.post_office.receive(agent); + + let rootNode = Kernel.elem(current_state, 0); + let tree = Kernel.elem(current_state, 1); + let renderFn = Kernel.elem(current_state, 2); + + let newTree = renderFn.apply(this, state); + + let patches = VirtualDOM.diff(tree, newTree) + rootNode = VirtualDOM.patch(rootNode, patches) + + + self.post_office.send(agent, Kernel.SpecialForms.tuple(rootNode, newTree, renderFn)); + + return Kernel.SpecialForms.atom("ok"); +} + + +export default { + start, + stop, + update +} From 8864cc2e48c08b4f1f784e52629a10f46fa932cc Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Sat, 28 Nov 2015 10:36:36 -0600 Subject: [PATCH 065/860] Renamed View.update to View.render. Removed tuple match from Patterns lib --- priv/elixir.js | 14 +++++------ .../lib/patterns/patterns/checks.js | 12 +--------- src/javascript/lib/patterns/patterns/match.js | 6 +---- .../lib/patterns/patterns/resolvers.js | 23 +------------------ src/javascript/lib/view.js | 5 ++-- .../tests/patterns/defmatch.spec.js | 8 +++---- 6 files changed, 16 insertions(+), 52 deletions(-) diff --git a/priv/elixir.js b/priv/elixir.js index 0c12d7a1..19478875 100644 --- a/priv/elixir.js +++ b/priv/elixir.js @@ -2201,7 +2201,7 @@ class SignalBinding { } } -function ___update(map, key, value) { +function __update(map, key, value) { let m = new Map(map); m.set(key, value); return m; @@ -2273,7 +2273,7 @@ class PostOffice { } add_mailbox(address = Symbol(), context = this) { - this.mailboxes = ___update(this.mailboxes, address, new MailBox()); + this.mailboxes = __update(this.mailboxes, address, new MailBox()); return address; } @@ -2711,7 +2711,7 @@ function update__emark__(map, key, fun) { return SpecialForms.map(new_map); } -function __update(map, key, initial, fun) { +function _update(map, key, initial, fun) { let new_map = Object({}, map); if (!key in map) { @@ -2747,7 +2747,7 @@ var _Map = { get, put: __put, update__emark__, - update: __update + update: _update }; function __new__() { @@ -4546,7 +4546,7 @@ const stop = function (agent, timeout = 5000) { return Kernel.SpecialForms.atom('ok'); }; -const _update = function (agent, state) { +const render = function (agent, state) { const current_state = self.post_office.receive(agent); @@ -4567,10 +4567,10 @@ const _update = function (agent, state) { var View = { start, stop, - update: _update + render }; self.post_office = self.post_office || new PostOffice(); export { _Patterns as Patterns, BitString, Kernel, Atom, Enum, Integer, JS, List, Range, Tuple, Agent, Keyword, Base, _String as String, Bitwise, Enumerable, Collectable, Inspect, _Map as Map, _Set as Set, MapSet, IntegerType, FloatType, virtualDom as VirtualDOM, View }; -//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiIiwic291cmNlcyI6WyJlbGl4aXIuanMiXSwic291cmNlc0NvbnRlbnQiOlsidmFyIFBhdHRlcm5zID0ge1xuICAgIGdldCBkZWZhdWx0ICgpIHsgcmV0dXJuIF9QYXR0ZXJuczsgfVxufTtcblxuY2xhc3MgVHVwbGUge1xuXG4gIGNvbnN0cnVjdG9yKC4uLmFyZ3MpIHtcbiAgICB0aGlzLnZhbHVlcyA9IE9iamVjdC5mcmVlemUoYXJncyk7XG4gIH1cblxuICBnZXQoaW5kZXgpIHtcbiAgICByZXR1cm4gdGhpcy52YWx1ZXNbaW5kZXhdO1xuICB9XG5cbiAgY291bnQoKSB7XG4gICAgcmV0dXJuIHRoaXMudmFsdWVzLmxlbmd0aDtcbiAgfVxuXG4gIFtTeW1ib2wuaXRlcmF0b3JdKCkge1xuICAgIHJldHVybiB0aGlzLnZhbHVlc1tTeW1ib2wuaXRlcmF0b3JdKCk7XG4gIH1cblxuICB0b1N0cmluZygpIHtcbiAgICB2YXIgaSxcbiAgICAgICAgcyA9IFwiXCI7XG4gICAgZm9yIChpID0gMDsgaSA8IHRoaXMudmFsdWVzLmxlbmd0aDsgaSsrKSB7XG4gICAgICBpZiAocyAhPT0gXCJcIikge1xuICAgICAgICBzICs9IFwiLCBcIjtcbiAgICAgIH1cbiAgICAgIHMgKz0gdGhpcy52YWx1ZXNbaV0udG9TdHJpbmcoKTtcbiAgICB9XG5cbiAgICByZXR1cm4gXCJ7XCIgKyBzICsgXCJ9XCI7XG4gIH1cblxuICBzdGF0aWMgdG9fc3RyaW5nKHR1cGxlKSB7XG4gICAgcmV0dXJuIHR1cGxlLnRvU3RyaW5nKCk7XG4gIH1cblxuICBzdGF0aWMgZGVsZXRlX2F0KHR1cGxlLCBpbmRleCkge1xuICAgIGxldCBuZXdfbGlzdCA9IFtdO1xuXG4gICAgZm9yICh2YXIgaSA9IDA7IGkgPCB0dXBsZS5jb3VudCgpOyBpKyspIHtcbiAgICAgIGlmIChpICE9PSBpbmRleCkge1xuICAgICAgICBuZXdfbGlzdC5wdXNoKHR1cGxlLmdldChpKSk7XG4gICAgICB9XG4gICAgfVxuXG4gICAgcmV0dXJuIEtlcm5lbC5TcGVjaWFsRm9ybXMudHVwbGUuYXBwbHkobnVsbCwgbmV3X2xpc3QpO1xuICB9XG5cbiAgc3RhdGljIGR1cGxpY2F0ZShkYXRhLCBzaXplKSB7XG4gICAgbGV0IGFycmF5ID0gW107XG5cbiAgICBmb3IgKHZhciBpID0gc2l6ZSAtIDE7IGkgPj0gMDsgaS0tKSB7XG4gICAgICBhcnJheS5wdXNoKGRhdGEpO1xuICAgIH1cblxuICAgIHJldHVybiBLZXJuZWwuU3BlY2lhbEZvcm1zLnR1cGxlLmFwcGx5KG51bGwsIGFycmF5KTtcbiAgfVxuXG4gIHN0YXRpYyBpbnNlcnRfYXQodHVwbGUsIGluZGV4LCB0ZXJtKSB7XG4gICAgbGV0IG5ld190dXBsZSA9IFtdO1xuXG4gICAgZm9yICh2YXIgaSA9IDA7IGkgPD0gdHVwbGUuY291bnQoKTsgaSsrKSB7XG4gICAgICBpZiAoaSA9PT0gaW5kZXgpIHtcbiAgICAgICAgbmV3X3R1cGxlLnB1c2godGVybSk7XG4gICAgICAgIGkrKztcbiAgICAgICAgbmV3X3R1cGxlLnB1c2godHVwbGUuZ2V0KGkpKTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIG5ld190dXBsZS5wdXNoKHR1cGxlLmdldChpKSk7XG4gICAgICB9XG4gICAgfVxuXG4gICAgcmV0dXJuIEtlcm5lbC5TcGVjaWFsRm9ybXMudHVwbGUuYXBwbHkobnVsbCwgbmV3X3R1cGxlKTtcbiAgfVxuXG4gIHN0YXRpYyBmcm9tX2xpc3QobGlzdCkge1xuICAgIHJldHVybiBLZXJuZWwuU3BlY2lhbEZvcm1zLnR1cGxlLmFwcGx5KG51bGwsIGxpc3QpO1xuICB9XG5cbiAgc3RhdGljIHRvX2xpc3QodHVwbGUpIHtcbiAgICBsZXQgbmV3X2xpc3QgPSBbXTtcblxuICAgIGZvciAodmFyIGkgPSAwOyBpIDwgdHVwbGUuY291bnQoKTsgaSsrKSB7XG4gICAgICBuZXdfbGlzdC5wdXNoKHR1cGxlLmdldChpKSk7XG4gICAgfVxuXG4gICAgcmV0dXJuIEtlcm5lbC5TcGVjaWFsRm9ybXMubGlzdCguLi5uZXdfbGlzdCk7XG4gIH1cbn1cblxuLyogQGZsb3cgKi9cblxuY2xhc3MgVmFyaWFibGUge1xuXG4gIGNvbnN0cnVjdG9yKG5hbWUgPSBudWxsKSB7XG4gICAgdGhpcy5uYW1lID0gbmFtZTtcbiAgfVxufVxuXG5jbGFzcyBXaWxkY2FyZCB7XG4gIGNvbnN0cnVjdG9yKCkge31cbn1cblxuY2xhc3MgU3RhcnRzV2l0aCB7XG5cbiAgY29uc3RydWN0b3IocHJlZml4KSB7XG4gICAgdGhpcy5wcmVmaXggPSBwcmVmaXg7XG4gIH1cbn1cblxuY2xhc3MgQ2FwdHVyZSB7XG5cbiAgY29uc3RydWN0b3IodmFsdWUpIHtcbiAgICB0aGlzLnZhbHVlID0gdmFsdWU7XG4gIH1cbn1cblxuY2xhc3MgSGVhZFRhaWwge1xuICBjb25zdHJ1Y3RvcigpIHt9XG59XG5cbmNsYXNzIFR5cGUge1xuXG4gIGNvbnN0cnVjdG9yKHR5cGUsIG9ialBhdHRlcm4gPSB7fSkge1xuICAgIHRoaXMudHlwZSA9IHR5cGU7XG4gICAgdGhpcy5vYmpQYXR0ZXJuID0gb2JqUGF0dGVybjtcbiAgfVxufVxuXG5jbGFzcyBCb3VuZCB7XG5cbiAgY29uc3RydWN0b3IodmFsdWUpIHtcbiAgICB0aGlzLnZhbHVlID0gdmFsdWU7XG4gIH1cbn1cblxuZnVuY3Rpb24gdmFyaWFibGUobmFtZSA9IG51bGwpIHtcbiAgcmV0dXJuIG5ldyBWYXJpYWJsZShuYW1lKTtcbn1cblxuZnVuY3Rpb24gd2lsZGNhcmQoKSB7XG4gIHJldHVybiBuZXcgV2lsZGNhcmQoKTtcbn1cblxuZnVuY3Rpb24gc3RhcnRzV2l0aChwcmVmaXgpIHtcbiAgcmV0dXJuIG5ldyBTdGFydHNXaXRoKHByZWZpeCk7XG59XG5cbmZ1bmN0aW9uIGNhcHR1cmUodmFsdWUpIHtcbiAgcmV0dXJuIG5ldyBDYXB0dXJlKHZhbHVlKTtcbn1cblxuZnVuY3Rpb24gaGVhZFRhaWwoKSB7XG4gIHJldHVybiBuZXcgSGVhZFRhaWwoKTtcbn1cblxuZnVuY3Rpb24gdHlwZSh0eXBlLCBvYmpQYXR0ZXJuID0ge30pIHtcbiAgcmV0dXJuIG5ldyBUeXBlKHR5cGUsIG9ialBhdHRlcm4pO1xufVxuXG5mdW5jdGlvbiBib3VuZCh2YWx1ZSkge1xuICByZXR1cm4gbmV3IEJvdW5kKHZhbHVlKTtcbn1cblxuZnVuY3Rpb24gX2lzX251bWJlcih2YWx1ZSkge1xuICByZXR1cm4gdHlwZW9mIHZhbHVlID09PSAnbnVtYmVyJztcbn1cblxuZnVuY3Rpb24gaXNfc3RyaW5nKHZhbHVlKSB7XG4gIHJldHVybiB0eXBlb2YgdmFsdWUgPT09ICdzdHJpbmcnO1xufVxuXG5mdW5jdGlvbiBfaXNfdHVwbGUodmFsdWUpIHtcbiAgcmV0dXJuIHZhbHVlIGluc3RhbmNlb2YgVHVwbGU7XG59XG5cbmZ1bmN0aW9uIF9pc19ib29sZWFuKHZhbHVlKSB7XG4gIHJldHVybiB0eXBlb2YgdmFsdWUgPT09ICdib29sZWFuJztcbn1cblxuZnVuY3Rpb24gaXNfc3ltYm9sKHZhbHVlKSB7XG4gIHJldHVybiB0eXBlb2YgdmFsdWUgPT09ICdzeW1ib2wnO1xufVxuXG5mdW5jdGlvbiBpc19udWxsKHZhbHVlKSB7XG4gIHJldHVybiB2YWx1ZSA9PT0gbnVsbDtcbn1cblxuZnVuY3Rpb24gaXNfdW5kZWZpbmVkKHZhbHVlKSB7XG4gIHJldHVybiB0eXBlb2YgdmFsdWUgPT09ICd1bmRlZmluZWQnO1xufVxuXG5mdW5jdGlvbiBfaXNfZnVuY3Rpb24odmFsdWUpIHtcbiAgcmV0dXJuIE9iamVjdC5wcm90b3R5cGUudG9TdHJpbmcuY2FsbCh2YWx1ZSkgPT0gJ1tvYmplY3QgRnVuY3Rpb25dJztcbn1cblxuZnVuY3Rpb24gaXNfdmFyaWFibGUodmFsdWUpIHtcbiAgcmV0dXJuIHZhbHVlIGluc3RhbmNlb2YgVmFyaWFibGU7XG59XG5cbmZ1bmN0aW9uIGlzX3dpbGRjYXJkKHZhbHVlKSB7XG4gIHJldHVybiB2YWx1ZSBpbnN0YW5jZW9mIFdpbGRjYXJkO1xufVxuXG5mdW5jdGlvbiBpc19oZWFkVGFpbCh2YWx1ZSkge1xuICByZXR1cm4gdmFsdWUgaW5zdGFuY2VvZiBIZWFkVGFpbDtcbn1cblxuZnVuY3Rpb24gaXNfY2FwdHVyZSh2YWx1ZSkge1xuICByZXR1cm4gdmFsdWUgaW5zdGFuY2VvZiBDYXB0dXJlO1xufVxuXG5mdW5jdGlvbiBpc190eXBlKHZhbHVlKSB7XG4gIHJldHVybiB2YWx1ZSBpbnN0YW5jZW9mIFR5cGU7XG59XG5cbmZ1bmN0aW9uIGlzX3N0YXJ0c1dpdGgodmFsdWUpIHtcbiAgcmV0dXJuIHZhbHVlIGluc3RhbmNlb2YgU3RhcnRzV2l0aDtcbn1cblxuZnVuY3Rpb24gaXNfYm91bmQodmFsdWUpIHtcbiAgcmV0dXJuIHZhbHVlIGluc3RhbmNlb2YgQm91bmQ7XG59XG5cbmZ1bmN0aW9uIGlzX29iamVjdCh2YWx1ZSkge1xuICByZXR1cm4gdHlwZW9mIHZhbHVlID09PSAnb2JqZWN0Jztcbn1cblxuZnVuY3Rpb24gaXNfYXJyYXkodmFsdWUpIHtcbiAgcmV0dXJuIEFycmF5LmlzQXJyYXkodmFsdWUpO1xufVxuXG52YXIgQ2hlY2tzID0ge1xuICBpc19udW1iZXI6IF9pc19udW1iZXIsXG4gIGlzX3N0cmluZyxcbiAgaXNfYm9vbGVhbjogX2lzX2Jvb2xlYW4sXG4gIGlzX3N5bWJvbCxcbiAgaXNfbnVsbCxcbiAgaXNfdW5kZWZpbmVkLFxuICBpc19mdW5jdGlvbjogX2lzX2Z1bmN0aW9uLFxuICBpc192YXJpYWJsZSxcbiAgaXNfd2lsZGNhcmQsXG4gIGlzX2hlYWRUYWlsLFxuICBpc19jYXB0dXJlLFxuICBpc190eXBlLFxuICBpc19zdGFydHNXaXRoLFxuICBpc19ib3VuZCxcbiAgaXNfb2JqZWN0LFxuICBpc19hcnJheSxcbiAgaXNfdHVwbGU6IF9pc190dXBsZVxufTtcblxuZnVuY3Rpb24gcmVzb2x2ZVR1cGxlKHBhdHRlcm4pIHtcbiAgbGV0IG1hdGNoZXMgPSBbXTtcblxuICBmb3IgKGxldCBlbGVtIG9mIHBhdHRlcm4pIHtcbiAgICBtYXRjaGVzLnB1c2goYnVpbGRNYXRjaChlbGVtKSk7XG4gIH1cblxuICByZXR1cm4gZnVuY3Rpb24gKHZhbHVlLCBhcmdzKSB7XG4gICAgaWYgKCFDaGVja3MuaXNfdHVwbGUodmFsdWUpIHx8IHZhbHVlLmNvdW50KCkgIT0gcGF0dGVybi5jb3VudCgpKSB7XG4gICAgICByZXR1cm4gZmFsc2U7XG4gICAgfVxuXG4gICAgcmV0dXJuIHZhbHVlLnZhbHVlcy5ldmVyeShmdW5jdGlvbiAodiwgaSkge1xuICAgICAgcmV0dXJuIG1hdGNoZXNbaV0odmFsdWUuZ2V0KGkpLCBhcmdzKTtcbiAgICB9KTtcbiAgfTtcbn1cblxuZnVuY3Rpb24gcmVzb2x2ZVN5bWJvbChwYXR0ZXJuKSB7XG4gIHJldHVybiBmdW5jdGlvbiAodmFsdWUpIHtcbiAgICByZXR1cm4gQ2hlY2tzLmlzX3N5bWJvbCh2YWx1ZSkgJiYgdmFsdWUgPT09IHBhdHRlcm47XG4gIH07XG59XG5cbmZ1bmN0aW9uIHJlc29sdmVTdHJpbmcocGF0dGVybikge1xuICByZXR1cm4gZnVuY3Rpb24gKHZhbHVlKSB7XG4gICAgcmV0dXJuIENoZWNrcy5pc19zdHJpbmcodmFsdWUpICYmIHZhbHVlID09PSBwYXR0ZXJuO1xuICB9O1xufVxuXG5mdW5jdGlvbiByZXNvbHZlTnVtYmVyKHBhdHRlcm4pIHtcbiAgcmV0dXJuIGZ1bmN0aW9uICh2YWx1ZSkge1xuICAgIHJldHVybiBDaGVja3MuaXNfbnVtYmVyKHZhbHVlKSAmJiB2YWx1ZSA9PT0gcGF0dGVybjtcbiAgfTtcbn1cblxuZnVuY3Rpb24gcmVzb2x2ZUJvb2xlYW4ocGF0dGVybikge1xuICByZXR1cm4gZnVuY3Rpb24gKHZhbHVlKSB7XG4gICAgcmV0dXJuIENoZWNrcy5pc19ib29sZWFuKHZhbHVlKSAmJiB2YWx1ZSA9PT0gcGF0dGVybjtcbiAgfTtcbn1cblxuZnVuY3Rpb24gcmVzb2x2ZUZ1bmN0aW9uKHBhdHRlcm4pIHtcbiAgcmV0dXJuIGZ1bmN0aW9uICh2YWx1ZSkge1xuICAgIHJldHVybiBDaGVja3MuaXNfZnVuY3Rpb24odmFsdWUpICYmIHZhbHVlID09PSBwYXR0ZXJuO1xuICB9O1xufVxuXG5mdW5jdGlvbiByZXNvbHZlTnVsbChwYXR0ZXJuKSB7XG4gIHJldHVybiBmdW5jdGlvbiAodmFsdWUpIHtcbiAgICByZXR1cm4gQ2hlY2tzLmlzX251bGwodmFsdWUpO1xuICB9O1xufVxuXG5mdW5jdGlvbiByZXNvbHZlQm91bmQocGF0dGVybikge1xuICByZXR1cm4gZnVuY3Rpb24gKHZhbHVlLCBhcmdzKSB7XG4gICAgaWYgKHR5cGVvZiB2YWx1ZSA9PT0gdHlwZW9mIHBhdHRlcm4udmFsdWUgJiYgdmFsdWUgPT09IHBhdHRlcm4udmFsdWUpIHtcbiAgICAgIGFyZ3MucHVzaCh2YWx1ZSk7XG4gICAgICByZXR1cm4gdHJ1ZTtcbiAgICB9XG5cbiAgICByZXR1cm4gZmFsc2U7XG4gIH07XG59XG5cbmZ1bmN0aW9uIHJlc29sdmVXaWxkY2FyZCgpIHtcbiAgcmV0dXJuIGZ1bmN0aW9uICgpIHtcbiAgICByZXR1cm4gdHJ1ZTtcbiAgfTtcbn1cblxuZnVuY3Rpb24gcmVzb2x2ZVZhcmlhYmxlKCkge1xuICByZXR1cm4gZnVuY3Rpb24gKHZhbHVlLCBhcmdzKSB7XG4gICAgYXJncy5wdXNoKHZhbHVlKTtcbiAgICByZXR1cm4gdHJ1ZTtcbiAgfTtcbn1cblxuZnVuY3Rpb24gcmVzb2x2ZUhlYWRUYWlsKCkge1xuICByZXR1cm4gZnVuY3Rpb24gKHZhbHVlLCBhcmdzKSB7XG4gICAgaWYgKCFDaGVja3MuaXNfYXJyYXkodmFsdWUpIHx8IHZhbHVlLmxlbmd0aCA8IDIpIHtcbiAgICAgIHJldHVybiBmYWxzZTtcbiAgICB9XG5cbiAgICBjb25zdCBoZWFkID0gdmFsdWVbMF07XG4gICAgY29uc3QgdGFpbCA9IHZhbHVlLnNsaWNlKDEpO1xuXG4gICAgYXJncy5wdXNoKGhlYWQpO1xuICAgIGFyZ3MucHVzaCh0YWlsKTtcblxuICAgIHJldHVybiB0cnVlO1xuICB9O1xufVxuXG5mdW5jdGlvbiByZXNvbHZlQ2FwdHVyZShwYXR0ZXJuKSB7XG4gIGNvbnN0IG1hdGNoZXMgPSBidWlsZE1hdGNoKHBhdHRlcm4udmFsdWUpO1xuXG4gIHJldHVybiBmdW5jdGlvbiAodmFsdWUsIGFyZ3MpIHtcbiAgICBpZiAobWF0Y2hlcyh2YWx1ZSwgYXJncykpIHtcbiAgICAgIGFyZ3MucHVzaCh2YWx1ZSk7XG4gICAgICByZXR1cm4gdHJ1ZTtcbiAgICB9XG5cbiAgICByZXR1cm4gZmFsc2U7XG4gIH07XG59XG5cbmZ1bmN0aW9uIHJlc29sdmVTdGFydHNXaXRoKHBhdHRlcm4pIHtcbiAgY29uc3QgcHJlZml4ID0gcGF0dGVybi5wcmVmaXg7XG5cbiAgcmV0dXJuIGZ1bmN0aW9uICh2YWx1ZSwgYXJncykge1xuICAgIGlmIChDaGVja3MuaXNfc3RyaW5nKHZhbHVlKSAmJiB2YWx1ZS5zdGFydHNXaXRoKHByZWZpeCkpIHtcbiAgICAgIGFyZ3MucHVzaCh2YWx1ZS5zdWJzdHJpbmcocHJlZml4Lmxlbmd0aCkpO1xuICAgICAgcmV0dXJuIHRydWU7XG4gICAgfVxuXG4gICAgcmV0dXJuIGZhbHNlO1xuICB9O1xufVxuXG5mdW5jdGlvbiByZXNvbHZlVHlwZShwYXR0ZXJuKSB7XG4gIHJldHVybiBmdW5jdGlvbiAodmFsdWUsIGFyZ3MpIHtcbiAgICBpZiAodmFsdWUgaW5zdGFuY2VvZiBwYXR0ZXJuLnR5cGUpIHtcbiAgICAgIGNvbnN0IG1hdGNoZXMgPSBidWlsZE1hdGNoKHBhdHRlcm4ub2JqUGF0dGVybik7XG4gICAgICByZXR1cm4gbWF0Y2hlcyh2YWx1ZSwgYXJncykgJiYgYXJncy5wdXNoKHZhbHVlKSA+IDA7XG4gICAgfVxuXG4gICAgcmV0dXJuIGZhbHNlO1xuICB9O1xufVxuXG5mdW5jdGlvbiByZXNvbHZlQXJyYXkocGF0dGVybikge1xuICBjb25zdCBtYXRjaGVzID0gcGF0dGVybi5tYXAoeCA9PiBidWlsZE1hdGNoKHgpKTtcblxuICByZXR1cm4gZnVuY3Rpb24gKHZhbHVlLCBhcmdzKSB7XG4gICAgaWYgKCFDaGVja3MuaXNfYXJyYXkodmFsdWUpIHx8IHZhbHVlLmxlbmd0aCAhPSBwYXR0ZXJuLmxlbmd0aCkge1xuICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH1cblxuICAgIHJldHVybiB2YWx1ZS5ldmVyeShmdW5jdGlvbiAodiwgaSkge1xuICAgICAgcmV0dXJuIG1hdGNoZXNbaV0odmFsdWVbaV0sIGFyZ3MpO1xuICAgIH0pO1xuICB9O1xufVxuXG5mdW5jdGlvbiByZXNvbHZlT2JqZWN0KHBhdHRlcm4pIHtcbiAgbGV0IG1hdGNoZXMgPSB7fTtcblxuICBmb3IgKGxldCBrZXkgb2YgT2JqZWN0LmtleXMocGF0dGVybikpIHtcbiAgICBtYXRjaGVzW2tleV0gPSBidWlsZE1hdGNoKHBhdHRlcm5ba2V5XSk7XG4gIH1cblxuICByZXR1cm4gZnVuY3Rpb24gKHZhbHVlLCBhcmdzKSB7XG4gICAgaWYgKCFDaGVja3MuaXNfb2JqZWN0KHZhbHVlKSB8fCBwYXR0ZXJuLmxlbmd0aCA+IHZhbHVlLmxlbmd0aCkge1xuICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH1cblxuICAgIGZvciAobGV0IGtleSBvZiBPYmplY3Qua2V5cyhwYXR0ZXJuKSkge1xuICAgICAgaWYgKCEoa2V5IGluIHZhbHVlKSB8fCAhbWF0Y2hlc1trZXldKHZhbHVlW2tleV0sIGFyZ3MpKSB7XG4gICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICByZXR1cm4gdHJ1ZTtcbiAgfTtcbn1cblxuZnVuY3Rpb24gcmVzb2x2ZU5vTWF0Y2goKSB7XG4gIHJldHVybiBmdW5jdGlvbiAoKSB7XG4gICAgcmV0dXJuIGZhbHNlO1xuICB9O1xufVxuXG52YXIgUmVzb2x2ZXJzID0ge1xuICByZXNvbHZlQm91bmQsXG4gIHJlc29sdmVXaWxkY2FyZCxcbiAgcmVzb2x2ZVZhcmlhYmxlLFxuICByZXNvbHZlSGVhZFRhaWwsXG4gIHJlc29sdmVDYXB0dXJlLFxuICByZXNvbHZlU3RhcnRzV2l0aCxcbiAgcmVzb2x2ZVR5cGUsXG4gIHJlc29sdmVBcnJheSxcbiAgcmVzb2x2ZU9iamVjdCxcbiAgcmVzb2x2ZU5vTWF0Y2gsXG4gIHJlc29sdmVTeW1ib2wsXG4gIHJlc29sdmVTdHJpbmcsXG4gIHJlc29sdmVOdW1iZXIsXG4gIHJlc29sdmVCb29sZWFuLFxuICByZXNvbHZlRnVuY3Rpb24sXG4gIHJlc29sdmVOdWxsLFxuICByZXNvbHZlVHVwbGVcbn07XG5cbmZ1bmN0aW9uIGJ1aWxkTWF0Y2gocGF0dGVybikge1xuXG4gIGlmIChDaGVja3MuaXNfdHVwbGUocGF0dGVybikpIHtcbiAgICByZXR1cm4gUmVzb2x2ZXJzLnJlc29sdmVUdXBsZShwYXR0ZXJuKTtcbiAgfVxuXG4gIGlmIChDaGVja3MuaXNfdmFyaWFibGUocGF0dGVybikpIHtcbiAgICByZXR1cm4gUmVzb2x2ZXJzLnJlc29sdmVWYXJpYWJsZShwYXR0ZXJuKTtcbiAgfVxuXG4gIGlmIChDaGVja3MuaXNfd2lsZGNhcmQocGF0dGVybikpIHtcbiAgICByZXR1cm4gUmVzb2x2ZXJzLnJlc29sdmVXaWxkY2FyZChwYXR0ZXJuKTtcbiAgfVxuXG4gIGlmIChDaGVja3MuaXNfdW5kZWZpbmVkKHBhdHRlcm4pKSB7XG4gICAgcmV0dXJuIFJlc29sdmVycy5yZXNvbHZlV2lsZGNhcmQocGF0dGVybik7XG4gIH1cblxuICBpZiAoQ2hlY2tzLmlzX2hlYWRUYWlsKHBhdHRlcm4pKSB7XG4gICAgcmV0dXJuIFJlc29sdmVycy5yZXNvbHZlSGVhZFRhaWwocGF0dGVybik7XG4gIH1cblxuICBpZiAoQ2hlY2tzLmlzX3N0YXJ0c1dpdGgocGF0dGVybikpIHtcbiAgICByZXR1cm4gUmVzb2x2ZXJzLnJlc29sdmVTdGFydHNXaXRoKHBhdHRlcm4pO1xuICB9XG5cbiAgaWYgKENoZWNrcy5pc19jYXB0dXJlKHBhdHRlcm4pKSB7XG4gICAgcmV0dXJuIFJlc29sdmVycy5yZXNvbHZlQ2FwdHVyZShwYXR0ZXJuKTtcbiAgfVxuXG4gIGlmIChDaGVja3MuaXNfYm91bmQocGF0dGVybikpIHtcbiAgICByZXR1cm4gUmVzb2x2ZXJzLnJlc29sdmVCb3VuZChwYXR0ZXJuKTtcbiAgfVxuXG4gIGlmIChDaGVja3MuaXNfdHlwZShwYXR0ZXJuKSkge1xuICAgIHJldHVybiBSZXNvbHZlcnMucmVzb2x2ZVR5cGUocGF0dGVybik7XG4gIH1cblxuICBpZiAoQ2hlY2tzLmlzX2FycmF5KHBhdHRlcm4pKSB7XG4gICAgcmV0dXJuIFJlc29sdmVycy5yZXNvbHZlQXJyYXkocGF0dGVybik7XG4gIH1cblxuICBpZiAoQ2hlY2tzLmlzX251bWJlcihwYXR0ZXJuKSkge1xuICAgIHJldHVybiBSZXNvbHZlcnMucmVzb2x2ZU51bWJlcihwYXR0ZXJuKTtcbiAgfVxuXG4gIGlmIChDaGVja3MuaXNfc3RyaW5nKHBhdHRlcm4pKSB7XG4gICAgcmV0dXJuIFJlc29sdmVycy5yZXNvbHZlU3RyaW5nKHBhdHRlcm4pO1xuICB9XG5cbiAgaWYgKENoZWNrcy5pc19ib29sZWFuKHBhdHRlcm4pKSB7XG4gICAgcmV0dXJuIFJlc29sdmVycy5yZXNvbHZlQm9vbGVhbihwYXR0ZXJuKTtcbiAgfVxuXG4gIGlmIChDaGVja3MuaXNfc3ltYm9sKHBhdHRlcm4pKSB7XG4gICAgcmV0dXJuIFJlc29sdmVycy5yZXNvbHZlU3ltYm9sKHBhdHRlcm4pO1xuICB9XG5cbiAgaWYgKENoZWNrcy5pc19udWxsKHBhdHRlcm4pKSB7XG4gICAgcmV0dXJuIFJlc29sdmVycy5yZXNvbHZlTnVsbChwYXR0ZXJuKTtcbiAgfVxuXG4gIGlmIChDaGVja3MuaXNfb2JqZWN0KHBhdHRlcm4pKSB7XG4gICAgcmV0dXJuIFJlc29sdmVycy5yZXNvbHZlT2JqZWN0KHBhdHRlcm4pO1xuICB9XG5cbiAgcmV0dXJuIFJlc29sdmVycy5yZXNvbHZlTm9NYXRjaCgpO1xufVxuXG5jbGFzcyBNYXRjaEVycm9yIGV4dGVuZHMgRXJyb3Ige1xuICBjb25zdHJ1Y3RvcihhcmcpIHtcbiAgICBzdXBlcigpO1xuXG4gICAgaWYgKHR5cGVvZiBhcmcgPT09ICdzeW1ib2wnKSB7XG4gICAgICB0aGlzLm1lc3NhZ2UgPSAnTm8gbWF0Y2ggZm9yOiAnICsgYXJnLnRvU3RyaW5nKCk7XG4gICAgfSBlbHNlIGlmIChBcnJheS5pc0FycmF5KGFyZykpIHtcbiAgICAgIGxldCBtYXBwZWRWYWx1ZXMgPSBhcmcubWFwKHggPT4geC50b1N0cmluZygpKTtcbiAgICAgIHRoaXMubWVzc2FnZSA9ICdObyBtYXRjaCBmb3I6ICcgKyBtYXBwZWRWYWx1ZXM7XG4gICAgfSBlbHNlIHtcbiAgICAgIHRoaXMubWVzc2FnZSA9ICdObyBtYXRjaCBmb3I6ICcgKyBhcmc7XG4gICAgfVxuXG4gICAgdGhpcy5zdGFjayA9IG5ldyBFcnJvcigpLnN0YWNrO1xuICAgIHRoaXMubmFtZSA9IHRoaXMuY29uc3RydWN0b3IubmFtZTtcbiAgfVxufVxuXG5jbGFzcyBDYXNlIHtcblxuICBjb25zdHJ1Y3RvcihwYXR0ZXJuLCBmbiwgZ3VhcmQgPSAoKSA9PiB0cnVlKSB7XG4gICAgdGhpcy5wYXR0ZXJuID0gYnVpbGRNYXRjaChwYXR0ZXJuKTtcbiAgICB0aGlzLmZuID0gZm47XG4gICAgdGhpcy5ndWFyZCA9IGd1YXJkO1xuICB9XG59XG5cbmZ1bmN0aW9uIG1ha2VfY2FzZShwYXR0ZXJuLCBmbiwgZ3VhcmQgPSAoKSA9PiB0cnVlKSB7XG4gIHJldHVybiBuZXcgQ2FzZShwYXR0ZXJuLCBmbiwgZ3VhcmQpO1xufVxuXG5mdW5jdGlvbiBkZWZtYXRjaCguLi5jYXNlcykge1xuICByZXR1cm4gZnVuY3Rpb24gKC4uLmFyZ3MpIHtcbiAgICBmb3IgKGxldCBwcm9jZXNzZWRDYXNlIG9mIGNhc2VzKSB7XG4gICAgICBsZXQgcmVzdWx0ID0gW107XG4gICAgICBpZiAocHJvY2Vzc2VkQ2FzZS5wYXR0ZXJuKGFyZ3MsIHJlc3VsdCkgJiYgcHJvY2Vzc2VkQ2FzZS5ndWFyZC5hcHBseSh0aGlzLCByZXN1bHQpKSB7XG4gICAgICAgIHJldHVybiBwcm9jZXNzZWRDYXNlLmZuLmFwcGx5KHRoaXMsIHJlc3VsdCk7XG4gICAgICB9XG4gICAgfVxuXG4gICAgdGhyb3cgbmV3IE1hdGNoRXJyb3IoYXJncyk7XG4gIH07XG59XG5cbmZ1bmN0aW9uIG1hdGNoKHBhdHRlcm4sIGV4cHIsIGd1YXJkID0gKCkgPT4gdHJ1ZSkge1xuICBsZXQgcmVzdWx0ID0gW107XG4gIGxldCBwcm9jZXNzZWRQYXR0ZXJuID0gYnVpbGRNYXRjaChwYXR0ZXJuKTtcbiAgaWYgKHByb2Nlc3NlZFBhdHRlcm4oZXhwciwgcmVzdWx0KSAmJiBndWFyZC5hcHBseSh0aGlzLCByZXN1bHQpKSB7XG4gICAgcmV0dXJuIHJlc3VsdDtcbiAgfSBlbHNlIHtcbiAgICB0aHJvdyBuZXcgTWF0Y2hFcnJvcihleHByKTtcbiAgfVxufVxuXG5mdW5jdGlvbiBtYXRjaF9ub190aHJvdyhwYXR0ZXJuLCBleHByLCBndWFyZCA9ICgpID0+IHRydWUpIHtcbiAgdHJ5IHtcbiAgICByZXR1cm4gbWF0Y2gocGF0dGVybiwgZXhwciwgZ3VhcmQpO1xuICB9IGNhdGNoIChlKSB7XG4gICAgaWYgKGUgaW5zdGFuY2VvZiBNYXRjaEVycm9yKSB7XG4gICAgICByZXR1cm4gbnVsbDtcbiAgICB9XG5cbiAgICB0aHJvdyBlO1xuICB9XG59XG5cbmZ1bmN0aW9uIHBhdHRlcm5NYXAoY29sbGVjdGlvbiwgcGF0dGVybiwgZnVuLCBndWFyZCA9ICgpID0+IHRydWUpIHtcbiAgbGV0IHJldCA9IFtdO1xuXG4gIGZvciAobGV0IGVsZW0gb2YgY29sbGVjdGlvbikge1xuICAgIHRyeSB7XG4gICAgICBsZXQgcmVzdWx0ID0gZnVuLmFwcGx5KHRoaXMsIG1hdGNoKHBhdHRlcm4sIGVsZW0sIGd1YXJkKSk7XG4gICAgICByZXQgPSByZXQuY29uY2F0KHJlc3VsdCk7XG4gICAgfSBjYXRjaCAoZSkge1xuICAgICAgaWYgKCEoZSBpbnN0YW5jZW9mIE1hdGNoRXJyb3IpKSB7XG4gICAgICAgIHRocm93IGU7XG4gICAgICB9XG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIHJldDtcbn1cblxudmFyIF9QYXR0ZXJucyA9IHtcbiAgZGVmbWF0Y2gsIG1hdGNoLCBNYXRjaEVycm9yLCBtYXRjaF9ub190aHJvdywgcGF0dGVybk1hcCxcbiAgdmFyaWFibGUsIHdpbGRjYXJkLCBzdGFydHNXaXRoLFxuICBjYXB0dXJlLCBoZWFkVGFpbCwgdHlwZSwgYm91bmQsIENhc2UsIG1ha2VfY2FzZVxufTtcblxuY2xhc3MgQml0U3RyaW5nIHtcbiAgY29uc3RydWN0b3IoLi4uYXJncykge1xuICAgIHRoaXMucmF3X3ZhbHVlID0gZnVuY3Rpb24gKCkge1xuICAgICAgcmV0dXJuIE9iamVjdC5mcmVlemUoYXJncyk7XG4gICAgfTtcblxuICAgIHRoaXMudmFsdWUgPSBPYmplY3QuZnJlZXplKHRoaXMucHJvY2VzcyhhcmdzKSk7XG4gIH1cblxuICBnZXQoaW5kZXgpIHtcbiAgICByZXR1cm4gdGhpcy52YWx1ZVtpbmRleF07XG4gIH1cblxuICBjb3VudCgpIHtcbiAgICByZXR1cm4gdGhpcy52YWx1ZS5sZW5ndGg7XG4gIH1cblxuICBbU3ltYm9sLml0ZXJhdG9yXSgpIHtcbiAgICByZXR1cm4gdGhpcy52YWx1ZVtTeW1ib2wuaXRlcmF0b3JdKCk7XG4gIH1cblxuICB0b1N0cmluZygpIHtcbiAgICB2YXIgaSxcbiAgICAgICAgcyA9IFwiXCI7XG4gICAgZm9yIChpID0gMDsgaSA8IHRoaXMuY291bnQoKTsgaSsrKSB7XG4gICAgICBpZiAocyAhPT0gXCJcIikge1xuICAgICAgICBzICs9IFwiLCBcIjtcbiAgICAgIH1cbiAgICAgIHMgKz0gdGhpc1tpXS50b1N0cmluZygpO1xuICAgIH1cblxuICAgIHJldHVybiBcIjw8XCIgKyBzICsgXCI+PlwiO1xuICB9XG5cbiAgcHJvY2VzcygpIHtcbiAgICBsZXQgcHJvY2Vzc2VkX3ZhbHVlcyA9IFtdO1xuXG4gICAgdmFyIGk7XG4gICAgZm9yIChpID0gMDsgaSA8IHRoaXMucmF3X3ZhbHVlKCkubGVuZ3RoOyBpKyspIHtcbiAgICAgIGxldCBwcm9jZXNzZWRfdmFsdWUgPSB0aGlzW1wicHJvY2Vzc19cIiArIHRoaXMucmF3X3ZhbHVlKClbaV0udHlwZV0odGhpcy5yYXdfdmFsdWUoKVtpXSk7XG5cbiAgICAgIGZvciAobGV0IGF0dHIgb2YgdGhpcy5yYXdfdmFsdWUoKVtpXS5hdHRyaWJ1dGVzKSB7XG4gICAgICAgIHByb2Nlc3NlZF92YWx1ZSA9IHRoaXNbXCJwcm9jZXNzX1wiICsgYXR0cl0ocHJvY2Vzc2VkX3ZhbHVlKTtcbiAgICAgIH1cblxuICAgICAgcHJvY2Vzc2VkX3ZhbHVlcyA9IHByb2Nlc3NlZF92YWx1ZXMuY29uY2F0KHByb2Nlc3NlZF92YWx1ZSk7XG4gICAgfVxuXG4gICAgcmV0dXJuIHByb2Nlc3NlZF92YWx1ZXM7XG4gIH1cblxuICBwcm9jZXNzX2ludGVnZXIodmFsdWUpIHtcbiAgICByZXR1cm4gdmFsdWUudmFsdWU7XG4gIH1cblxuICBwcm9jZXNzX2Zsb2F0KHZhbHVlKSB7XG4gICAgaWYgKHZhbHVlLnNpemUgPT09IDY0KSB7XG4gICAgICByZXR1cm4gQml0U3RyaW5nLmZsb2F0NjRUb0J5dGVzKHZhbHVlLnZhbHVlKTtcbiAgICB9IGVsc2UgaWYgKHZhbHVlLnNpemUgPT09IDMyKSB7XG4gICAgICByZXR1cm4gQml0U3RyaW5nLmZsb2F0MzJUb0J5dGVzKHZhbHVlLnZhbHVlKTtcbiAgICB9XG5cbiAgICB0aHJvdyBuZXcgRXJyb3IoXCJJbnZhbGlkIHNpemUgZm9yIGZsb2F0XCIpO1xuICB9XG5cbiAgcHJvY2Vzc19iaXRzdHJpbmcodmFsdWUpIHtcbiAgICByZXR1cm4gdmFsdWUudmFsdWUudmFsdWU7XG4gIH1cblxuICBwcm9jZXNzX2JpbmFyeSh2YWx1ZSkge1xuICAgIHJldHVybiBCaXRTdHJpbmcudG9VVEY4QXJyYXkodmFsdWUudmFsdWUpO1xuICB9XG5cbiAgcHJvY2Vzc191dGY4KHZhbHVlKSB7XG4gICAgcmV0dXJuIEJpdFN0cmluZy50b1VURjhBcnJheSh2YWx1ZS52YWx1ZSk7XG4gIH1cblxuICBwcm9jZXNzX3V0ZjE2KHZhbHVlKSB7XG4gICAgcmV0dXJuIEJpdFN0cmluZy50b1VURjE2QXJyYXkodmFsdWUudmFsdWUpO1xuICB9XG5cbiAgcHJvY2Vzc191dGYzMih2YWx1ZSkge1xuICAgIHJldHVybiBCaXRTdHJpbmcudG9VVEYzMkFycmF5KHZhbHVlLnZhbHVlKTtcbiAgfVxuXG4gIHByb2Nlc3Nfc2lnbmVkKHZhbHVlKSB7XG4gICAgcmV0dXJuIG5ldyBVaW50OEFycmF5KFt2YWx1ZV0pWzBdO1xuICB9XG5cbiAgcHJvY2Vzc191bnNpZ25lZCh2YWx1ZSkge1xuICAgIHJldHVybiB2YWx1ZTtcbiAgfVxuXG4gIHByb2Nlc3NfbmF0aXZlKHZhbHVlKSB7XG4gICAgcmV0dXJuIHZhbHVlO1xuICB9XG5cbiAgcHJvY2Vzc19iaWcodmFsdWUpIHtcbiAgICByZXR1cm4gdmFsdWU7XG4gIH1cblxuICBwcm9jZXNzX2xpdHRsZSh2YWx1ZSkge1xuICAgIHJldHVybiB2YWx1ZS5yZXZlcnNlKCk7XG4gIH1cblxuICBwcm9jZXNzX3NpemUodmFsdWUpIHtcbiAgICByZXR1cm4gdmFsdWU7XG4gIH1cblxuICBwcm9jZXNzX3VuaXQodmFsdWUpIHtcbiAgICByZXR1cm4gdmFsdWU7XG4gIH1cblxuICBzdGF0aWMgaW50ZWdlcih2YWx1ZSkge1xuICAgIHJldHVybiBCaXRTdHJpbmcud3JhcCh2YWx1ZSwgeyBcInR5cGVcIjogXCJpbnRlZ2VyXCIsIFwidW5pdFwiOiAxLCBcInNpemVcIjogOCB9KTtcbiAgfVxuXG4gIHN0YXRpYyBmbG9hdCh2YWx1ZSkge1xuICAgIHJldHVybiBCaXRTdHJpbmcud3JhcCh2YWx1ZSwgeyBcInR5cGVcIjogXCJmbG9hdFwiLCBcInVuaXRcIjogMSwgXCJzaXplXCI6IDY0IH0pO1xuICB9XG5cbiAgc3RhdGljIGJpdHN0cmluZyh2YWx1ZSkge1xuICAgIHJldHVybiBCaXRTdHJpbmcud3JhcCh2YWx1ZSwgeyBcInR5cGVcIjogXCJiaXRzdHJpbmdcIiwgXCJ1bml0XCI6IDEsIFwic2l6ZVwiOiB2YWx1ZS5sZW5ndGggfSk7XG4gIH1cblxuICBzdGF0aWMgYml0cyh2YWx1ZSkge1xuICAgIHJldHVybiBCaXRTdHJpbmcuYml0c3RyaW5nKHZhbHVlKTtcbiAgfVxuXG4gIHN0YXRpYyBiaW5hcnkodmFsdWUpIHtcbiAgICByZXR1cm4gQml0U3RyaW5nLndyYXAodmFsdWUsIHsgXCJ0eXBlXCI6IFwiYmluYXJ5XCIsIFwidW5pdFwiOiA4LCBcInNpemVcIjogdmFsdWUubGVuZ3RoIH0pO1xuICB9XG5cbiAgc3RhdGljIGJ5dGVzKHZhbHVlKSB7XG4gICAgcmV0dXJuIEJpdFN0cmluZy5iaW5hcnkodmFsdWUpO1xuICB9XG5cbiAgc3RhdGljIHV0ZjgodmFsdWUpIHtcbiAgICByZXR1cm4gQml0U3RyaW5nLndyYXAodmFsdWUsIHsgXCJ0eXBlXCI6IFwidXRmOFwiIH0pO1xuICB9XG5cbiAgc3RhdGljIHV0ZjE2KHZhbHVlKSB7XG4gICAgcmV0dXJuIEJpdFN0cmluZy53cmFwKHZhbHVlLCB7IFwidHlwZVwiOiBcInV0ZjE2XCIgfSk7XG4gIH1cblxuICBzdGF0aWMgdXRmMzIodmFsdWUpIHtcbiAgICByZXR1cm4gQml0U3RyaW5nLndyYXAodmFsdWUsIHsgXCJ0eXBlXCI6IFwidXRmMzJcIiB9KTtcbiAgfVxuXG4gIHN0YXRpYyBzaWduZWQodmFsdWUpIHtcbiAgICByZXR1cm4gQml0U3RyaW5nLndyYXAodmFsdWUsIHt9LCBcInNpZ25lZFwiKTtcbiAgfVxuXG4gIHN0YXRpYyB1bnNpZ25lZCh2YWx1ZSkge1xuICAgIHJldHVybiBCaXRTdHJpbmcud3JhcCh2YWx1ZSwge30sIFwidW5zaWduZWRcIik7XG4gIH1cblxuICBzdGF0aWMgbmF0aXZlKHZhbHVlKSB7XG4gICAgcmV0dXJuIEJpdFN0cmluZy53cmFwKHZhbHVlLCB7fSwgXCJuYXRpdmVcIik7XG4gIH1cblxuICBzdGF0aWMgYmlnKHZhbHVlKSB7XG4gICAgcmV0dXJuIEJpdFN0cmluZy53cmFwKHZhbHVlLCB7fSwgXCJiaWdcIik7XG4gIH1cblxuICBzdGF0aWMgbGl0dGxlKHZhbHVlKSB7XG4gICAgcmV0dXJuIEJpdFN0cmluZy53cmFwKHZhbHVlLCB7fSwgXCJsaXR0bGVcIik7XG4gIH1cblxuICBzdGF0aWMgc2l6ZSh2YWx1ZSwgY291bnQpIHtcbiAgICByZXR1cm4gQml0U3RyaW5nLndyYXAodmFsdWUsIHsgXCJzaXplXCI6IGNvdW50IH0pO1xuICB9XG5cbiAgc3RhdGljIHVuaXQodmFsdWUsIGNvdW50KSB7XG4gICAgcmV0dXJuIEJpdFN0cmluZy53cmFwKHZhbHVlLCB7IFwidW5pdFwiOiBjb3VudCB9KTtcbiAgfVxuXG4gIHN0YXRpYyB3cmFwKHZhbHVlLCBvcHQsIG5ld19hdHRyaWJ1dGUgPSBudWxsKSB7XG4gICAgbGV0IHRoZV92YWx1ZSA9IHZhbHVlO1xuXG4gICAgaWYgKCEodmFsdWUgaW5zdGFuY2VvZiBPYmplY3QpKSB7XG4gICAgICB0aGVfdmFsdWUgPSB7IFwidmFsdWVcIjogdmFsdWUsIFwiYXR0cmlidXRlc1wiOiBbXSB9O1xuICAgIH1cblxuICAgIHRoZV92YWx1ZSA9IE9iamVjdC5hc3NpZ24odGhlX3ZhbHVlLCBvcHQpO1xuXG4gICAgaWYgKG5ld19hdHRyaWJ1dGUpIHtcbiAgICAgIHRoZV92YWx1ZS5hdHRyaWJ1dGVzLnB1c2gobmV3X2F0dHJpYnV0ZSk7XG4gICAgfVxuXG4gICAgcmV0dXJuIHRoZV92YWx1ZTtcbiAgfVxuXG4gIHN0YXRpYyB0b1VURjhBcnJheShzdHIpIHtcbiAgICB2YXIgdXRmOCA9IFtdO1xuICAgIGZvciAodmFyIGkgPSAwOyBpIDwgc3RyLmxlbmd0aDsgaSsrKSB7XG4gICAgICB2YXIgY2hhcmNvZGUgPSBzdHIuY2hhckNvZGVBdChpKTtcbiAgICAgIGlmIChjaGFyY29kZSA8IDEyOCkge1xuICAgICAgICB1dGY4LnB1c2goY2hhcmNvZGUpO1xuICAgICAgfSBlbHNlIGlmIChjaGFyY29kZSA8IDIwNDgpIHtcbiAgICAgICAgdXRmOC5wdXNoKDE5MiB8IGNoYXJjb2RlID4+IDYsIDEyOCB8IGNoYXJjb2RlICYgNjMpO1xuICAgICAgfSBlbHNlIGlmIChjaGFyY29kZSA8IDU1Mjk2IHx8IGNoYXJjb2RlID49IDU3MzQ0KSB7XG4gICAgICAgIHV0ZjgucHVzaCgyMjQgfCBjaGFyY29kZSA+PiAxMiwgMTI4IHwgY2hhcmNvZGUgPj4gNiAmIDYzLCAxMjggfCBjaGFyY29kZSAmIDYzKTtcbiAgICAgIH1cbiAgICAgIC8vIHN1cnJvZ2F0ZSBwYWlyXG4gICAgICBlbHNlIHtcbiAgICAgICAgaSsrO1xuICAgICAgICAvLyBVVEYtMTYgZW5jb2RlcyAweDEwMDAwLTB4MTBGRkZGIGJ5XG4gICAgICAgIC8vIHN1YnRyYWN0aW5nIDB4MTAwMDAgYW5kIHNwbGl0dGluZyB0aGVcbiAgICAgICAgLy8gMjAgYml0cyBvZiAweDAtMHhGRkZGRiBpbnRvIHR3byBoYWx2ZXNcbiAgICAgICAgY2hhcmNvZGUgPSA2NTUzNiArICgoY2hhcmNvZGUgJiAxMDIzKSA8PCAxMCB8IHN0ci5jaGFyQ29kZUF0KGkpICYgMTAyMyk7XG4gICAgICAgIHV0ZjgucHVzaCgyNDAgfCBjaGFyY29kZSA+PiAxOCwgMTI4IHwgY2hhcmNvZGUgPj4gMTIgJiA2MywgMTI4IHwgY2hhcmNvZGUgPj4gNiAmIDYzLCAxMjggfCBjaGFyY29kZSAmIDYzKTtcbiAgICAgIH1cbiAgICB9XG4gICAgcmV0dXJuIHV0Zjg7XG4gIH1cblxuICBzdGF0aWMgdG9VVEYxNkFycmF5KHN0cikge1xuICAgIHZhciB1dGYxNiA9IFtdO1xuICAgIGZvciAodmFyIGkgPSAwOyBpIDwgc3RyLmxlbmd0aDsgaSsrKSB7XG4gICAgICB2YXIgY29kZVBvaW50ID0gc3RyLmNvZGVQb2ludEF0KGkpO1xuXG4gICAgICBpZiAoY29kZVBvaW50IDw9IDI1NSkge1xuICAgICAgICB1dGYxNi5wdXNoKDApO1xuICAgICAgICB1dGYxNi5wdXNoKGNvZGVQb2ludCk7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICB1dGYxNi5wdXNoKGNvZGVQb2ludCA+PiA4ICYgMjU1KTtcbiAgICAgICAgdXRmMTYucHVzaChjb2RlUG9pbnQgJiAyNTUpO1xuICAgICAgfVxuICAgIH1cbiAgICByZXR1cm4gdXRmMTY7XG4gIH1cblxuICBzdGF0aWMgdG9VVEYzMkFycmF5KHN0cikge1xuICAgIHZhciB1dGYzMiA9IFtdO1xuICAgIGZvciAodmFyIGkgPSAwOyBpIDwgc3RyLmxlbmd0aDsgaSsrKSB7XG4gICAgICB2YXIgY29kZVBvaW50ID0gc3RyLmNvZGVQb2ludEF0KGkpO1xuXG4gICAgICBpZiAoY29kZVBvaW50IDw9IDI1NSkge1xuICAgICAgICB1dGYzMi5wdXNoKDApO1xuICAgICAgICB1dGYzMi5wdXNoKDApO1xuICAgICAgICB1dGYzMi5wdXNoKDApO1xuICAgICAgICB1dGYzMi5wdXNoKGNvZGVQb2ludCk7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICB1dGYzMi5wdXNoKDApO1xuICAgICAgICB1dGYzMi5wdXNoKDApO1xuICAgICAgICB1dGYzMi5wdXNoKGNvZGVQb2ludCA+PiA4ICYgMjU1KTtcbiAgICAgICAgdXRmMzIucHVzaChjb2RlUG9pbnQgJiAyNTUpO1xuICAgICAgfVxuICAgIH1cbiAgICByZXR1cm4gdXRmMzI7XG4gIH1cblxuICAvL2h0dHA6Ly9zdGFja292ZXJmbG93LmNvbS9xdWVzdGlvbnMvMjAwMzQ5My9qYXZhc2NyaXB0LWZsb2F0LWZyb20tdG8tYml0c1xuICBzdGF0aWMgZmxvYXQzMlRvQnl0ZXMoZikge1xuICAgIHZhciBieXRlcyA9IFtdO1xuXG4gICAgdmFyIGJ1ZiA9IG5ldyBBcnJheUJ1ZmZlcig0KTtcbiAgICBuZXcgRmxvYXQzMkFycmF5KGJ1ZilbMF0gPSBmO1xuXG4gICAgbGV0IGludFZlcnNpb24gPSBuZXcgVWludDMyQXJyYXkoYnVmKVswXTtcblxuICAgIGJ5dGVzLnB1c2goaW50VmVyc2lvbiA+PiAyNCAmIDI1NSk7XG4gICAgYnl0ZXMucHVzaChpbnRWZXJzaW9uID4+IDE2ICYgMjU1KTtcbiAgICBieXRlcy5wdXNoKGludFZlcnNpb24gPj4gOCAmIDI1NSk7XG4gICAgYnl0ZXMucHVzaChpbnRWZXJzaW9uICYgMjU1KTtcblxuICAgIHJldHVybiBieXRlcztcbiAgfVxuXG4gIHN0YXRpYyBmbG9hdDY0VG9CeXRlcyhmKSB7XG4gICAgdmFyIGJ5dGVzID0gW107XG5cbiAgICB2YXIgYnVmID0gbmV3IEFycmF5QnVmZmVyKDgpO1xuICAgIG5ldyBGbG9hdDY0QXJyYXkoYnVmKVswXSA9IGY7XG5cbiAgICB2YXIgaW50VmVyc2lvbjEgPSBuZXcgVWludDMyQXJyYXkoYnVmKVswXTtcbiAgICB2YXIgaW50VmVyc2lvbjIgPSBuZXcgVWludDMyQXJyYXkoYnVmKVsxXTtcblxuICAgIGJ5dGVzLnB1c2goaW50VmVyc2lvbjIgPj4gMjQgJiAyNTUpO1xuICAgIGJ5dGVzLnB1c2goaW50VmVyc2lvbjIgPj4gMTYgJiAyNTUpO1xuICAgIGJ5dGVzLnB1c2goaW50VmVyc2lvbjIgPj4gOCAmIDI1NSk7XG4gICAgYnl0ZXMucHVzaChpbnRWZXJzaW9uMiAmIDI1NSk7XG5cbiAgICBieXRlcy5wdXNoKGludFZlcnNpb24xID4+IDI0ICYgMjU1KTtcbiAgICBieXRlcy5wdXNoKGludFZlcnNpb24xID4+IDE2ICYgMjU1KTtcbiAgICBieXRlcy5wdXNoKGludFZlcnNpb24xID4+IDggJiAyNTUpO1xuICAgIGJ5dGVzLnB1c2goaW50VmVyc2lvbjEgJiAyNTUpO1xuXG4gICAgcmV0dXJuIGJ5dGVzO1xuICB9XG59XG5cbmxldCBTcGVjaWFsRm9ybXMgPSB7XG5cbiAgX19ESVJfXzogZnVuY3Rpb24gKCkge1xuICAgIGlmIChfX2Rpcm5hbWUpIHtcbiAgICAgIHJldHVybiBfX2Rpcm5hbWU7XG4gICAgfVxuXG4gICAgaWYgKGRvY3VtZW50LmN1cnJlbnRTY3JpcHQpIHtcbiAgICAgIHJldHVybiBkb2N1bWVudC5jdXJyZW50U2NyaXB0LnNyYztcbiAgICB9XG5cbiAgICByZXR1cm4gbnVsbDtcbiAgfSxcblxuICBhdG9tOiBmdW5jdGlvbiAoX3ZhbHVlKSB7XG4gICAgcmV0dXJuIFN5bWJvbC5mb3IoX3ZhbHVlKTtcbiAgfSxcblxuICBsaXN0OiBmdW5jdGlvbiAoLi4uYXJncykge1xuICAgIHJldHVybiBPYmplY3QuZnJlZXplKGFyZ3MpO1xuICB9LFxuXG4gIGJpdHN0cmluZzogZnVuY3Rpb24gKC4uLmFyZ3MpIHtcbiAgICByZXR1cm4gbmV3IEJpdFN0cmluZyguLi5hcmdzKTtcbiAgfSxcblxuICBib3VuZDogZnVuY3Rpb24gKF92YXIpIHtcbiAgICByZXR1cm4gUGF0dGVybnMuYm91bmQoX3Zhcik7XG4gIH0sXG5cbiAgX2Nhc2U6IGZ1bmN0aW9uIChjb25kaXRpb24sIGNsYXVzZXMpIHtcbiAgICByZXR1cm4gUGF0dGVybnMuZGVmbWF0Y2goLi4uY2xhdXNlcykoY29uZGl0aW9uKTtcbiAgfSxcblxuICBjb25kOiBmdW5jdGlvbiAoY2xhdXNlcykge1xuICAgIGZvciAobGV0IGNsYXVzZSBvZiBjbGF1c2VzKSB7XG4gICAgICBpZiAoY2xhdXNlWzBdKSB7XG4gICAgICAgIHJldHVybiBjbGF1c2VbMV0oKTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICB0aHJvdyBuZXcgRXJyb3IoKTtcbiAgfSxcblxuICBmbjogZnVuY3Rpb24gKGNsYXVzZXMpIHtcbiAgICByZXR1cm4gUGF0dGVybnMuZGVmbWF0Y2goY2xhdXNlcyk7XG4gIH0sXG5cbiAgbWFwOiBmdW5jdGlvbiAob2JqKSB7XG4gICAgcmV0dXJuIE9iamVjdC5mcmVlemUob2JqKTtcbiAgfSxcblxuICBtYXBfdXBkYXRlOiBmdW5jdGlvbiAobWFwLCB2YWx1ZXMpIHtcbiAgICByZXR1cm4gT2JqZWN0LmZyZWV6ZShPYmplY3QuYXNzaWduKE9iamVjdC5jcmVhdGUobWFwLmNvbnN0cnVjdG9yLnByb3RvdHlwZSksIG1hcCwgdmFsdWVzKSk7XG4gIH0sXG5cbiAgX2ZvcjogZnVuY3Rpb24gKGNvbGxlY3Rpb25zLCBmdW4sIGZpbHRlciA9ICgpID0+IHRydWUsIGludG8gPSBbXSwgcHJldmlvdXNWYWx1ZXMgPSBbXSkge1xuICAgIGxldCBwYXR0ZXJuID0gY29sbGVjdGlvbnNbMF1bMF07XG4gICAgbGV0IGNvbGxlY3Rpb24gPSBjb2xsZWN0aW9uc1swXVsxXTtcblxuICAgIGlmIChjb2xsZWN0aW9ucy5sZW5ndGggPT09IDEpIHtcblxuICAgICAgZm9yIChsZXQgZWxlbSBvZiBjb2xsZWN0aW9uKSB7XG4gICAgICAgIGxldCByID0gUGF0dGVybnMubWF0Y2hfbm9fdGhyb3cocGF0dGVybiwgZWxlbSk7XG4gICAgICAgIGxldCBhcmdzID0gcHJldmlvdXNWYWx1ZXMuY29uY2F0KHIpO1xuXG4gICAgICAgIGlmIChyICYmIGZpbHRlci5hcHBseSh0aGlzLCBhcmdzKSkge1xuICAgICAgICAgIGludG8gPSBFbnVtLmludG8oW2Z1bi5hcHBseSh0aGlzLCBhcmdzKV0sIGludG8pO1xuICAgICAgICB9XG4gICAgICB9XG5cbiAgICAgIHJldHVybiBpbnRvO1xuICAgIH0gZWxzZSB7XG4gICAgICBsZXQgX2ludG8gPSBbXTtcblxuICAgICAgZm9yIChsZXQgZWxlbSBvZiBjb2xsZWN0aW9uKSB7XG4gICAgICAgIGxldCByID0gUGF0dGVybnMubWF0Y2hfbm9fdGhyb3cocGF0dGVybiwgZWxlbSk7XG4gICAgICAgIGlmIChyKSB7XG4gICAgICAgICAgX2ludG8gPSBFbnVtLmludG8odGhpcy5fZm9yKGNvbGxlY3Rpb25zLnNsaWNlKDEpLCBmdW4sIGZpbHRlciwgX2ludG8sIHByZXZpb3VzVmFsdWVzLmNvbmNhdChyKSksIGludG8pO1xuICAgICAgICB9XG4gICAgICB9XG5cbiAgICAgIHJldHVybiBfaW50bztcbiAgICB9XG4gIH0sXG5cbiAgcmVjZWl2ZTogZnVuY3Rpb24gKHJlY2VpdmVfZnVuLCB0aW1lb3V0X2luX21zID0gbnVsbCwgdGltZW91dF9mbiA9IHRpbWUgPT4gdHJ1ZSkge1xuICAgIGlmICh0aW1lb3V0X2luX21zID09IG51bGwgfHwgdGltZW91dF9pbl9tcyA9PT0gU3lzdGVtLmZvcignaW5maW5pdHknKSkge1xuICAgICAgd2hpbGUgKHRydWUpIHtcbiAgICAgICAgaWYgKHNlbGYubWFpbGJveC5sZW5ndGggIT09IDApIHtcbiAgICAgICAgICBsZXQgbWVzc2FnZSA9IHNlbGYubWFpbGJveFswXTtcbiAgICAgICAgICBzZWxmLm1haWxib3ggPSBzZWxmLm1haWxib3guc2xpY2UoMSk7XG4gICAgICAgICAgcmV0dXJuIHJlY2VpdmVfZnVuKG1lc3NhZ2UpO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgfSBlbHNlIGlmICh0aW1lb3V0X2luX21zID09PSAwKSB7XG4gICAgICBpZiAoc2VsZi5tYWlsYm94Lmxlbmd0aCAhPT0gMCkge1xuICAgICAgICBsZXQgbWVzc2FnZSA9IHNlbGYubWFpbGJveFswXTtcbiAgICAgICAgc2VsZi5tYWlsYm94ID0gc2VsZi5tYWlsYm94LnNsaWNlKDEpO1xuICAgICAgICByZXR1cm4gcmVjZWl2ZV9mdW4obWVzc2FnZSk7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICByZXR1cm4gbnVsbDtcbiAgICAgIH1cbiAgICB9IGVsc2Uge1xuICAgICAgbGV0IG5vdyA9IERhdGUubm93KCk7XG4gICAgICB3aGlsZSAoRGF0ZS5ub3coKSA8IG5vdyArIHRpbWVvdXRfaW5fbXMpIHtcbiAgICAgICAgaWYgKHNlbGYubWFpbGJveC5sZW5ndGggIT09IDApIHtcbiAgICAgICAgICBsZXQgbWVzc2FnZSA9IHNlbGYubWFpbGJveFswXTtcbiAgICAgICAgICBzZWxmLm1haWxib3ggPSBzZWxmLm1haWxib3guc2xpY2UoMSk7XG4gICAgICAgICAgcmV0dXJuIHJlY2VpdmVfZnVuKG1lc3NhZ2UpO1xuICAgICAgICB9XG4gICAgICB9XG5cbiAgICAgIHJldHVybiB0aW1lb3V0X2ZuKHRpbWVvdXRfaW5fbXMpO1xuICAgIH1cbiAgfSxcblxuICB0dXBsZTogZnVuY3Rpb24gKC4uLmFyZ3MpIHtcbiAgICByZXR1cm4gbmV3IFR1cGxlKC4uLmFyZ3MpO1xuICB9LFxuXG4gIF90cnk6IGZ1bmN0aW9uIChkb19mdW4sIHJlc2N1ZV9mdW5jdGlvbiwgY2F0Y2hfZnVuLCBlbHNlX2Z1bmN0aW9uLCBhZnRlcl9mdW5jdGlvbikge1xuICAgIGxldCByZXN1bHQgPSBudWxsO1xuXG4gICAgdHJ5IHtcbiAgICAgIHJlc3VsdCA9IGRvX2Z1bigpO1xuICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgIGxldCBleF9yZXN1bHQgPSBudWxsO1xuXG4gICAgICBpZiAocmVzY3VlX2Z1bmN0aW9uKSB7XG4gICAgICAgIHRyeSB7XG4gICAgICAgICAgZXhfcmVzdWx0ID0gcmVzY3VlX2Z1bmN0aW9uKGUpO1xuICAgICAgICAgIHJldHVybiBleF9yZXN1bHQ7XG4gICAgICAgIH0gY2F0Y2ggKGV4KSB7XG4gICAgICAgICAgaWYgKGV4IGluc3RhbmNlb2YgUGF0dGVybnMuTWF0Y2hFcnJvcikge1xuICAgICAgICAgICAgdGhyb3cgZXg7XG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICB9XG5cbiAgICAgIGlmIChjYXRjaF9mdW4pIHtcbiAgICAgICAgdHJ5IHtcbiAgICAgICAgICBleF9yZXN1bHQgPSBjYXRjaF9mdW4oZSk7XG4gICAgICAgICAgcmV0dXJuIGV4X3Jlc3VsdDtcbiAgICAgICAgfSBjYXRjaCAoZXgpIHtcbiAgICAgICAgICBpZiAoZXggaW5zdGFuY2VvZiBQYXR0ZXJucy5NYXRjaEVycm9yKSB7XG4gICAgICAgICAgICB0aHJvdyBleDtcbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgIH1cblxuICAgICAgdGhyb3cgZTtcbiAgICB9IGZpbmFsbHkge1xuICAgICAgaWYgKGFmdGVyX2Z1bmN0aW9uKSB7XG4gICAgICAgIGFmdGVyX2Z1bmN0aW9uKCk7XG4gICAgICB9XG4gICAgfVxuXG4gICAgaWYgKGVsc2VfZnVuY3Rpb24pIHtcbiAgICAgIHRyeSB7XG4gICAgICAgIHJldHVybiBlbHNlX2Z1bmN0aW9uKHJlc3VsdCk7XG4gICAgICB9IGNhdGNoIChleCkge1xuICAgICAgICBpZiAoZXggaW5zdGFuY2VvZiBQYXR0ZXJucy5NYXRjaEVycm9yKSB7XG4gICAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdObyBNYXRjaCBGb3VuZCBpbiBFbHNlJyk7XG4gICAgICAgIH1cblxuICAgICAgICB0aHJvdyBleDtcbiAgICAgIH1cbiAgICB9IGVsc2Uge1xuICAgICAgcmV0dXJuIHJlc3VsdDtcbiAgICB9XG4gIH1cblxufTtcblxuLyogQGZsb3cgKi9cblxubGV0IHByb2Nlc3NfY291bnRlciA9IC0xO1xuXG5jbGFzcyBQSUQge1xuICBjb25zdHJ1Y3RvcigpIHtcbiAgICBwcm9jZXNzX2NvdW50ZXIgPSBwcm9jZXNzX2NvdW50ZXIgKyAxO1xuICAgIHRoaXMuaWQgPSBwcm9jZXNzX2NvdW50ZXI7XG4gIH1cblxuICB0b1N0cmluZygpIHtcbiAgICByZXR1cm4gXCJQSUQjPDAuXCIgKyB0aGlzLmlkICsgXCIuMD5cIjtcbiAgfVxufVxuXG5jbGFzcyBJbnRlZ2VyVHlwZSB7fVxuY2xhc3MgRmxvYXRUeXBlIHt9XG5cbi8vaHR0cHM6Ly9naXRodWIuY29tL2FpcnBvcnR5aC9wcm90b21vcnBoaXNtXG5jbGFzcyBQcm90b2NvbCB7XG4gIGNvbnN0cnVjdG9yKHNwZWMpIHtcbiAgICB0aGlzLnJlZ2lzdHJ5ID0gbmV3IE1hcCgpO1xuICAgIHRoaXMuZmFsbGJhY2sgPSBudWxsO1xuXG4gICAgZm9yIChsZXQgZnVuTmFtZSBpbiBzcGVjKSB7XG4gICAgICB0aGlzW2Z1bk5hbWVdID0gY3JlYXRlRnVuKGZ1bk5hbWUpLmJpbmQodGhpcyk7XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gY3JlYXRlRnVuKGZ1bk5hbWUpIHtcblxuICAgICAgcmV0dXJuIGZ1bmN0aW9uICguLi5hcmdzKSB7XG4gICAgICAgIGxldCB0aGluZyA9IGFyZ3NbMF07XG4gICAgICAgIGxldCBmdW4gPSBudWxsO1xuXG4gICAgICAgIGlmIChOdW1iZXIuaXNJbnRlZ2VyKHRoaW5nKSAmJiB0aGlzLmhhc0ltcGxlbWVudGF0aW9uKEludGVnZXJUeXBlKSkge1xuICAgICAgICAgIGZ1biA9IHRoaXMucmVnaXN0cnkuZ2V0KEludGVnZXJUeXBlKVtmdW5OYW1lXTtcbiAgICAgICAgfSBlbHNlIGlmICh0eXBlb2YgdGhpbmcgPT09IFwibnVtYmVyXCIgJiYgIU51bWJlci5pc0ludGVnZXIodGhpbmcpICYmIHRoaXMuaGFzSW1wbGVtZW50YXRpb24oRmxvYXRUeXBlKSkge1xuICAgICAgICAgIGZ1biA9IHRoaXMucmVnaXN0cnkuZ2V0KEZsb2F0VHlwZSlbZnVuTmFtZV07XG4gICAgICAgIH0gZWxzZSBpZiAodGhpcy5oYXNJbXBsZW1lbnRhdGlvbih0aGluZykpIHtcbiAgICAgICAgICBmdW4gPSB0aGlzLnJlZ2lzdHJ5LmdldCh0aGluZy5jb25zdHJ1Y3RvcilbZnVuTmFtZV07XG4gICAgICAgIH0gZWxzZSBpZiAodGhpcy5mYWxsYmFjaykge1xuICAgICAgICAgIGZ1biA9IHRoaXMuZmFsbGJhY2tbZnVuTmFtZV07XG4gICAgICAgIH1cblxuICAgICAgICBpZiAoZnVuICE9IG51bGwpIHtcbiAgICAgICAgICBsZXQgcmV0dmFsID0gZnVuLmFwcGx5KHRoaXMsIGFyZ3MpO1xuICAgICAgICAgIHJldHVybiByZXR2YWw7XG4gICAgICAgIH1cblxuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoXCJObyBpbXBsZW1lbnRhdGlvbiBmb3VuZCBmb3IgXCIgKyB0aGluZyk7XG4gICAgICB9O1xuICAgIH1cbiAgfVxuXG4gIGltcGxlbWVudGF0aW9uKHR5cGUsIGltcGxlbWVudGF0aW9uKSB7XG4gICAgaWYgKHR5cGUgPT09IG51bGwpIHtcbiAgICAgIHRoaXMuZmFsbGJhY2sgPSBpbXBsZW1lbnRhdGlvbjtcbiAgICB9IGVsc2Uge1xuICAgICAgdGhpcy5yZWdpc3RyeS5zZXQodHlwZSwgaW1wbGVtZW50YXRpb24pO1xuICAgIH1cbiAgfVxuXG4gIGhhc0ltcGxlbWVudGF0aW9uKHRoaW5nKSB7XG4gICAgcmV0dXJuIHRoaXMucmVnaXN0cnkuaGFzKHRoaW5nLmNvbnN0cnVjdG9yKTtcbiAgfVxufVxuXG5mdW5jdGlvbiB0bChsaXN0KSB7XG4gIHJldHVybiBTcGVjaWFsRm9ybXMubGlzdCguLi5saXN0LnNsaWNlKDEpKTtcbn1cblxuZnVuY3Rpb24gaGQobGlzdCkge1xuICByZXR1cm4gbGlzdFswXTtcbn1cblxuZnVuY3Rpb24gaXNfbmlsKHgpIHtcbiAgcmV0dXJuIHggPT09IG51bGw7XG59XG5cbmZ1bmN0aW9uIGlzX2F0b20oeCkge1xuICByZXR1cm4gdHlwZW9mIHggPT09ICdzeW1ib2wnO1xufVxuXG5mdW5jdGlvbiBpc19iaW5hcnkoeCkge1xuICByZXR1cm4gdHlwZW9mIHggPT09ICdzdHJpbmcnIHx8IHggaW5zdGFuY2VvZiBTdHJpbmc7XG59XG5cbmZ1bmN0aW9uIGlzX2Jvb2xlYW4oeCkge1xuICByZXR1cm4gdHlwZW9mIHggPT09ICdib29sZWFuJyB8fCB4IGluc3RhbmNlb2YgQm9vbGVhbjtcbn1cblxuZnVuY3Rpb24gaXNfZnVuY3Rpb24oeCwgYXJpdHkgPSAtMSkge1xuICByZXR1cm4gdHlwZW9mIHggPT09ICdmdW5jdGlvbicgfHwgeCBpbnN0YW5jZW9mIEZ1bmN0aW9uO1xufVxuXG5mdW5jdGlvbiBpc19mbG9hdCh4KSB7XG4gIHJldHVybiBpc19udW1iZXIoeCkgJiYgIU51bWJlci5pc0ludGVnZXIoeCk7XG59XG5cbmZ1bmN0aW9uIGlzX2ludGVnZXIoeCkge1xuICByZXR1cm4gTnVtYmVyLmlzSW50ZWdlcih4KTtcbn1cblxuZnVuY3Rpb24gaXNfbGlzdCh4KSB7XG4gIHJldHVybiB4IGluc3RhbmNlb2YgQXJyYXk7XG59XG5cbmZ1bmN0aW9uIGlzX21hcCh4KSB7XG4gIHJldHVybiB0eXBlb2YgeCA9PT0gJ29iamVjdCcgfHwgeCBpbnN0YW5jZW9mIE9iamVjdDtcbn1cblxuZnVuY3Rpb24gaXNfbnVtYmVyKHgpIHtcbiAgcmV0dXJuIHR5cGVvZiB4ID09PSAnbnVtYmVyJztcbn1cblxuZnVuY3Rpb24gaXNfdHVwbGUoeCkge1xuICByZXR1cm4geCBpbnN0YW5jZW9mIFR1cGxlO1xufVxuXG5mdW5jdGlvbiBfbGVuZ3RoKHgpIHtcbiAgcmV0dXJuIHgubGVuZ3RoO1xufVxuXG5mdW5jdGlvbiBpc19waWQoeCkge1xuICByZXR1cm4geCBpbnN0YW5jZW9mIFBJRDtcbn1cblxuZnVuY3Rpb24gaXNfcG9ydCh4KSB7XG4gIHJldHVybiBmYWxzZTtcbn1cblxuZnVuY3Rpb24gaXNfcmVmZXJlbmNlKHgpIHtcbiAgcmV0dXJuIGZhbHNlO1xufVxuXG5mdW5jdGlvbiBpc19iaXRzdHJpbmcoeCkge1xuICByZXR1cm4gaXNfYmluYXJ5KHgpIHx8IHggaW5zdGFuY2VvZiBCaXRTdHJpbmc7XG59XG5cbmZ1bmN0aW9uIF9faW5fXyhsZWZ0LCByaWdodCkge1xuICBmb3IgKGxldCB4IG9mIHJpZ2h0KSB7XG4gICAgaWYgKG1hdGNoX19xbWFya19fKGxlZnQsIHgpKSB7XG4gICAgICByZXR1cm4gdHJ1ZTtcbiAgICB9XG4gIH1cblxuICByZXR1cm4gZmFsc2U7XG59XG5cbmZ1bmN0aW9uIGFicyhudW1iZXIpIHtcbiAgcmV0dXJuIE1hdGguYWJzKG51bWJlcik7XG59XG5cbmZ1bmN0aW9uIHJvdW5kKG51bWJlcikge1xuICByZXR1cm4gTWF0aC5yb3VuZChudW1iZXIpO1xufVxuXG5mdW5jdGlvbiBlbGVtKHR1cGxlLCBpbmRleCkge1xuICBpZiAoaXNfbGlzdCh0dXBsZSkpIHtcbiAgICByZXR1cm4gdHVwbGVbaW5kZXhdO1xuICB9XG5cbiAgcmV0dXJuIHR1cGxlLmdldChpbmRleCk7XG59XG5cbmZ1bmN0aW9uIHJlbShsZWZ0LCByaWdodCkge1xuICByZXR1cm4gbGVmdCAlIHJpZ2h0O1xufVxuXG5mdW5jdGlvbiBkaXYobGVmdCwgcmlnaHQpIHtcbiAgcmV0dXJuIGxlZnQgLyByaWdodDtcbn1cblxuZnVuY3Rpb24gYW5kKGxlZnQsIHJpZ2h0KSB7XG4gIHJldHVybiBsZWZ0ICYmIHJpZ2h0O1xufVxuXG5mdW5jdGlvbiBvcihsZWZ0LCByaWdodCkge1xuICByZXR1cm4gbGVmdCB8fCByaWdodDtcbn1cblxuZnVuY3Rpb24gbm90KGFyZykge1xuICByZXR1cm4gIWFyZztcbn1cblxuZnVuY3Rpb24gYXBwbHkoLi4uYXJncykge1xuICBpZiAoYXJncy5sZW5ndGggPT09IDMpIHtcbiAgICBsZXQgbW9kID0gYXJnc1swXTtcbiAgICBsZXQgZnVuYyA9IGFyZ3NbMV07XG4gICAgbGV0IGZ1bmNfYXJncyA9IGFyZ3NbMl07XG4gICAgcmV0dXJuIG1vZFtmdW5jXS5hcHBseShudWxsLCBmdW5jX2FyZ3MpO1xuICB9IGVsc2Uge1xuICAgIGxldCBmdW5jID0gYXJnc1swXTtcbiAgICBsZXQgZnVuY19hcmdzID0gYXJnc1sxXTtcblxuICAgIHJldHVybiBmdW5jLmFwcGx5KG51bGwsIGZ1bmNfYXJncyk7XG4gIH1cbn1cblxuZnVuY3Rpb24gdG9fc3RyaW5nKGFyZykge1xuICBpZiAoaXNfdHVwbGUoYXJnKSkge1xuICAgIHJldHVybiBUdXBsZS50b19zdHJpbmcoYXJnKTtcbiAgfVxuXG4gIHJldHVybiBhcmcudG9TdHJpbmcoKTtcbn1cblxuZnVuY3Rpb24gbWF0Y2hfX3FtYXJrX18ocGF0dGVybiwgZXhwciwgZ3VhcmQgPSAoKSA9PiB0cnVlKSB7XG4gIHJldHVybiBfUGF0dGVybnMubWF0Y2hfbm9fdGhyb3cocGF0dGVybiwgZXhwciwgZ3VhcmQpICE9IG51bGw7XG59XG5cbmZ1bmN0aW9uIGRlZnN0cnVjdChkZWZhdWx0cykge1xuICByZXR1cm4gY2xhc3Mge1xuICAgIGNvbnN0cnVjdG9yKHVwZGF0ZSA9IHt9KSB7XG4gICAgICBsZXQgdGhlX3ZhbHVlcyA9IE9iamVjdC5hc3NpZ24oZGVmYXVsdHMsIHVwZGF0ZSk7XG4gICAgICBPYmplY3QuYXNzaWduKHRoaXMsIHRoZV92YWx1ZXMpO1xuICAgIH1cblxuICAgIHN0YXRpYyBjcmVhdGUodXBkYXRlcyA9IHt9KSB7XG4gICAgICBsZXQgeCA9IG5ldyB0aGlzKHVwZGF0ZXMpO1xuICAgICAgcmV0dXJuIE9iamVjdC5mcmVlemUoeCk7XG4gICAgfVxuICB9O1xufVxuXG5mdW5jdGlvbiBkZWZleGNlcHRpb24oZGVmYXVsdHMpIHtcbiAgcmV0dXJuIGNsYXNzIGV4dGVuZHMgRXJyb3Ige1xuICAgIGNvbnN0cnVjdG9yKHVwZGF0ZSA9IHt9KSB7XG4gICAgICBsZXQgbWVzc2FnZSA9IHVwZGF0ZS5tZXNzYWdlIHx8ICcnO1xuICAgICAgc3VwZXIobWVzc2FnZSk7XG5cbiAgICAgIGxldCB0aGVfdmFsdWVzID0gT2JqZWN0LmFzc2lnbihkZWZhdWx0cywgdXBkYXRlKTtcbiAgICAgIE9iamVjdC5hc3NpZ24odGhpcywgdGhlX3ZhbHVlcyk7XG5cbiAgICAgIHRoaXMubmFtZSA9IHRoaXMuY29uc3RydWN0b3IubmFtZTtcbiAgICAgIHRoaXMubWVzc2FnZSA9IG1lc3NhZ2U7XG4gICAgICB0aGlzW1NwZWNpYWxGb3Jtcy5hdG9tKCdfX2V4Y2VwdGlvbl9fJyldID0gdHJ1ZTtcbiAgICAgIEVycm9yLmNhcHR1cmVTdGFja1RyYWNlKHRoaXMsIHRoaXMuY29uc3RydWN0b3IubmFtZSk7XG4gICAgfVxuXG4gICAgc3RhdGljIGNyZWF0ZSh1cGRhdGVzID0ge30pIHtcbiAgICAgIGxldCB4ID0gbmV3IHRoaXModXBkYXRlcyk7XG4gICAgICByZXR1cm4gT2JqZWN0LmZyZWV6ZSh4KTtcbiAgICB9XG4gIH07XG59XG5cbmZ1bmN0aW9uIGRlZnByb3RvY29sKHNwZWMpIHtcbiAgcmV0dXJuIG5ldyBQcm90b2NvbChzcGVjKTtcbn1cblxuZnVuY3Rpb24gZGVmaW1wbChwcm90b2NvbCwgdHlwZSwgaW1wbCkge1xuICBwcm90b2NvbC5pbXBsZW1lbnRhdGlvbih0eXBlLCBpbXBsKTtcbn1cblxudmFyIEtlcm5lbCA9IHtcbiAgU3BlY2lhbEZvcm1zLFxuICB0bCxcbiAgaGQsXG4gIGlzX25pbCxcbiAgaXNfYXRvbSxcbiAgaXNfYmluYXJ5LFxuICBpc19ib29sZWFuLFxuICBpc19mdW5jdGlvbixcbiAgaXNfZmxvYXQsXG4gIGlzX2ludGVnZXIsXG4gIGlzX2xpc3QsXG4gIGlzX21hcCxcbiAgaXNfbnVtYmVyLFxuICBpc190dXBsZSxcbiAgbGVuZ3RoOiBfbGVuZ3RoLFxuICBpc19waWQsXG4gIGlzX3BvcnQsXG4gIGlzX3JlZmVyZW5jZSxcbiAgaXNfYml0c3RyaW5nLFxuICBpbjogX19pbl9fLFxuICBhYnMsXG4gIHJvdW5kLFxuICBlbGVtLFxuICByZW0sXG4gIGRpdixcbiAgYW5kLFxuICBvcixcbiAgbm90LFxuICBhcHBseSxcbiAgdG9fc3RyaW5nLFxuICBtYXRjaF9fcW1hcmtfXyxcbiAgZGVmc3RydWN0LFxuICBkZWZwcm90b2NvbCxcbiAgZGVmaW1wbFxufTtcblxubGV0IEVudW0gPSB7XG5cbiAgYWxsX19xbWFya19fOiBmdW5jdGlvbiAoY29sbGVjdGlvbiwgZnVuID0geCA9PiB4KSB7XG4gICAgZm9yIChsZXQgZWxlbSBvZiBjb2xsZWN0aW9uKSB7XG4gICAgICBpZiAoIWZ1bihlbGVtKSkge1xuICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICB9XG4gICAgfVxuXG4gICAgcmV0dXJuIHRydWU7XG4gIH0sXG5cbiAgYW55X19xbWFya19fOiBmdW5jdGlvbiAoY29sbGVjdGlvbiwgZnVuID0geCA9PiB4KSB7XG4gICAgZm9yIChsZXQgZWxlbSBvZiBjb2xsZWN0aW9uKSB7XG4gICAgICBpZiAoZnVuKGVsZW0pKSB7XG4gICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgfVxuICAgIH1cblxuICAgIHJldHVybiBmYWxzZTtcbiAgfSxcblxuICBhdDogZnVuY3Rpb24gKGNvbGxlY3Rpb24sIG4sIHRoZV9kZWZhdWx0ID0gbnVsbCkge1xuICAgIGlmIChuID4gdGhpcy5jb3VudChjb2xsZWN0aW9uKSB8fCBuIDwgMCkge1xuICAgICAgcmV0dXJuIHRoZV9kZWZhdWx0O1xuICAgIH1cblxuICAgIHJldHVybiBjb2xsZWN0aW9uW25dO1xuICB9LFxuXG4gIGNvbmNhdDogZnVuY3Rpb24gKC4uLmVudW1hYmxlcykge1xuICAgIHJldHVybiBlbnVtYWJsZXNbMF0uY29uY2F0KGVudW1hYmxlc1sxXSk7XG4gIH0sXG5cbiAgY291bnQ6IGZ1bmN0aW9uIChjb2xsZWN0aW9uLCBmdW4gPSBudWxsKSB7XG4gICAgaWYgKGZ1biA9PSBudWxsKSB7XG4gICAgICByZXR1cm4gY29sbGVjdGlvbi5sZW5ndGg7XG4gICAgfSBlbHNlIHtcbiAgICAgIHJldHVybiBjb2xsZWN0aW9uLmZpbHRlcihmdW4pLmxlbmd0aDtcbiAgICB9XG4gIH0sXG5cbiAgZHJvcDogZnVuY3Rpb24gKGNvbGxlY3Rpb24sIGNvdW50KSB7XG4gICAgcmV0dXJuIGNvbGxlY3Rpb24uc2xpY2UoY291bnQpO1xuICB9LFxuXG4gIGRyb3Bfd2hpbGU6IGZ1bmN0aW9uIChjb2xsZWN0aW9uLCBmdW4pIHtcbiAgICBsZXQgY291bnQgPSAwO1xuXG4gICAgZm9yIChsZXQgZWxlbSBvZiBjb2xsZWN0aW9uKSB7XG4gICAgICBpZiAoZnVuKGVsZW0pKSB7XG4gICAgICAgIGNvdW50ID0gY291bnQgKyAxO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgYnJlYWs7XG4gICAgICB9XG4gICAgfVxuXG4gICAgcmV0dXJuIGNvbGxlY3Rpb24uc2xpY2UoY291bnQpO1xuICB9LFxuXG4gIGVhY2g6IGZ1bmN0aW9uIChjb2xsZWN0aW9uLCBmdW4pIHtcbiAgICBmb3IgKGxldCBlbGVtIG9mIGNvbGxlY3Rpb24pIHtcbiAgICAgIGZ1bihlbGVtKTtcbiAgICB9XG4gIH0sXG5cbiAgZW1wdHlfX3FtYXJrX186IGZ1bmN0aW9uIChjb2xsZWN0aW9uKSB7XG4gICAgcmV0dXJuIGNvbGxlY3Rpb24ubGVuZ3RoID09PSAwO1xuICB9LFxuXG4gIGZldGNoOiBmdW5jdGlvbiAoY29sbGVjdGlvbiwgbikge1xuICAgIGlmIChLZXJuZWwuaXNfbGlzdChjb2xsZWN0aW9uKSkge1xuICAgICAgaWYgKG4gPCB0aGlzLmNvdW50KGNvbGxlY3Rpb24pICYmIG4gPj0gMCkge1xuICAgICAgICByZXR1cm4gS2VybmVsLlNwZWNpYWxGb3Jtcy50dXBsZShLZXJuZWwuU3BlY2lhbEZvcm1zLmF0b20oXCJva1wiKSwgY29sbGVjdGlvbltuXSk7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICByZXR1cm4gS2VybmVsLlNwZWNpYWxGb3Jtcy5hdG9tKFwiZXJyb3JcIik7XG4gICAgICB9XG4gICAgfVxuXG4gICAgdGhyb3cgbmV3IEVycm9yKFwiY29sbGVjdGlvbiBpcyBub3QgYW4gRW51bWVyYWJsZVwiKTtcbiAgfSxcblxuICBmZXRjaF9fZW1hcmtfXzogZnVuY3Rpb24gKGNvbGxlY3Rpb24sIG4pIHtcbiAgICBpZiAoS2VybmVsLmlzX2xpc3QoY29sbGVjdGlvbikpIHtcbiAgICAgIGlmIChuIDwgdGhpcy5jb3VudChjb2xsZWN0aW9uKSAmJiBuID49IDApIHtcbiAgICAgICAgcmV0dXJuIGNvbGxlY3Rpb25bbl07XG4gICAgICB9IGVsc2Uge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoXCJvdXQgb2YgYm91bmRzIGVycm9yXCIpO1xuICAgICAgfVxuICAgIH1cblxuICAgIHRocm93IG5ldyBFcnJvcihcImNvbGxlY3Rpb24gaXMgbm90IGFuIEVudW1lcmFibGVcIik7XG4gIH0sXG5cbiAgZmlsdGVyOiBmdW5jdGlvbiAoY29sbGVjdGlvbiwgZnVuKSB7XG4gICAgbGV0IHJlc3VsdCA9IFtdO1xuXG4gICAgZm9yIChsZXQgZWxlbSBvZiBjb2xsZWN0aW9uKSB7XG4gICAgICBpZiAoZnVuKGVsZW0pKSB7XG4gICAgICAgIHJlc3VsdC5wdXNoKGVsZW0pO1xuICAgICAgfVxuICAgIH1cblxuICAgIHJldHVybiByZXN1bHQ7XG4gIH0sXG5cbiAgZmlsdGVyX21hcDogZnVuY3Rpb24gKGNvbGxlY3Rpb24sIGZpbHRlciwgbWFwcGVyKSB7XG4gICAgcmV0dXJuIEVudW0ubWFwKEVudW0uZmlsdGVyKGNvbGxlY3Rpb24sIGZpbHRlciksIG1hcHBlcik7XG4gIH0sXG5cbiAgZmluZDogZnVuY3Rpb24gKGNvbGxlY3Rpb24sIGlmX25vbmUgPSBudWxsLCBmdW4pIHtcbiAgICBmb3IgKGxldCBlbGVtIG9mIGNvbGxlY3Rpb24pIHtcbiAgICAgIGlmIChmdW4oZWxlbSkpIHtcbiAgICAgICAgcmV0dXJuIGVsZW07XG4gICAgICB9XG4gICAgfVxuXG4gICAgcmV0dXJuIGlmX25vbmU7XG4gIH0sXG5cbiAgaW50bzogZnVuY3Rpb24gKGNvbGxlY3Rpb24sIGxpc3QpIHtcbiAgICByZXR1cm4gbGlzdC5jb25jYXQoY29sbGVjdGlvbik7XG4gIH0sXG5cbiAgbWFwOiBmdW5jdGlvbiAoY29sbGVjdGlvbiwgZnVuKSB7XG4gICAgbGV0IHJlc3VsdCA9IFtdO1xuXG4gICAgZm9yIChsZXQgZWxlbSBvZiBjb2xsZWN0aW9uKSB7XG4gICAgICByZXN1bHQucHVzaChmdW4oZWxlbSkpO1xuICAgIH1cblxuICAgIHJldHVybiByZXN1bHQ7XG4gIH0sXG5cbiAgbWFwX3JlZHVjZTogZnVuY3Rpb24gKGNvbGxlY3Rpb24sIGFjYywgZnVuKSB7XG4gICAgbGV0IG1hcHBlZCA9IEtlcm5lbC5TcGVjaWFsRm9ybXMubGlzdCgpO1xuICAgIGxldCB0aGVfYWNjID0gYWNjO1xuXG4gICAgZm9yICh2YXIgaSA9IDA7IGkgPCB0aGlzLmNvdW50KGNvbGxlY3Rpb24pOyBpKyspIHtcbiAgICAgIGxldCB0dXBsZSA9IGZ1bihjb2xsZWN0aW9uW2ldLCB0aGVfYWNjKTtcblxuICAgICAgdGhlX2FjYyA9IEtlcm5lbC5lbGVtKHR1cGxlLCAxKTtcbiAgICAgIG1hcHBlZCA9IEtlcm5lbC5TcGVjaWFsRm9ybXMubGlzdCguLi5tYXBwZWQuY29uY2F0KFtLZXJuZWwuZWxlbSh0dXBsZSwgMCldKSk7XG4gICAgfVxuXG4gICAgcmV0dXJuIEtlcm5lbC5TcGVjaWFsRm9ybXMudHVwbGUobWFwcGVkLCB0aGVfYWNjKTtcbiAgfSxcblxuICBtZW1iZXI6IGZ1bmN0aW9uIChjb2xsZWN0aW9uLCB2YWx1ZSkge1xuICAgIHJldHVybiBjb2xsZWN0aW9uLmluY2x1ZGVzKHZhbHVlKTtcbiAgfSxcblxuICByZWR1Y2U6IGZ1bmN0aW9uIChjb2xsZWN0aW9uLCBhY2MsIGZ1bikge1xuICAgIGxldCB0aGVfYWNjID0gYWNjO1xuXG4gICAgZm9yICh2YXIgaSA9IDA7IGkgPCB0aGlzLmNvdW50KGNvbGxlY3Rpb24pOyBpKyspIHtcbiAgICAgIGxldCB0dXBsZSA9IGZ1bihjb2xsZWN0aW9uW2ldLCB0aGVfYWNjKTtcblxuICAgICAgdGhlX2FjYyA9IEtlcm5lbC5lbGVtKHR1cGxlLCAxKTtcbiAgICB9XG5cbiAgICByZXR1cm4gdGhlX2FjYztcbiAgfSxcblxuICB0YWtlOiBmdW5jdGlvbiAoY29sbGVjdGlvbiwgY291bnQpIHtcbiAgICByZXR1cm4gY29sbGVjdGlvbi5zbGljZSgwLCBjb3VudCk7XG4gIH0sXG5cbiAgdGFrZV9ldmVyeTogZnVuY3Rpb24gKGNvbGxlY3Rpb24sIG50aCkge1xuICAgIGxldCByZXN1bHQgPSBbXTtcbiAgICBsZXQgaW5kZXggPSAwO1xuXG4gICAgZm9yIChsZXQgZWxlbSBvZiBjb2xsZWN0aW9uKSB7XG4gICAgICBpZiAoaW5kZXggJSBudGggPT09IDApIHtcbiAgICAgICAgcmVzdWx0LnB1c2goZWxlbSk7XG4gICAgICB9XG4gICAgfVxuXG4gICAgcmV0dXJuIEtlcm5lbC5TcGVjaWFsRm9ybXMubGlzdCguLi5yZXN1bHQpO1xuICB9LFxuXG4gIHRha2Vfd2hpbGU6IGZ1bmN0aW9uIChjb2xsZWN0aW9uLCBmdW4pIHtcbiAgICBsZXQgY291bnQgPSAwO1xuXG4gICAgZm9yIChsZXQgZWxlbSBvZiBjb2xsZWN0aW9uKSB7XG4gICAgICBpZiAoZnVuKGVsZW0pKSB7XG4gICAgICAgIGNvdW50ID0gY291bnQgKyAxO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgYnJlYWs7XG4gICAgICB9XG4gICAgfVxuXG4gICAgcmV0dXJuIGNvbGxlY3Rpb24uc2xpY2UoMCwgY291bnQpO1xuICB9LFxuXG4gIHRvX2xpc3Q6IGZ1bmN0aW9uIChjb2xsZWN0aW9uKSB7XG4gICAgcmV0dXJuIGNvbGxlY3Rpb247XG4gIH1cbn07XG5cbmxldCBBdG9tID0ge307XG5cbkF0b20udG9fc3RyaW5nID0gZnVuY3Rpb24gKGF0b20pIHtcbiAgcmV0dXJuIFN5bWJvbC5rZXlGb3IoYXRvbSk7XG59O1xuXG5BdG9tLnRvX2NoYXJfbGlzdCA9IGZ1bmN0aW9uIChhdG9tKSB7XG4gIHJldHVybiBBdG9tLnRvX3N0cmluZyhhdG9tKS5zcGxpdCgnJyk7XG59O1xuXG5sZXQgSW50ZWdlciA9IHtcblxuICBpc19ldmVuOiBmdW5jdGlvbiAobikge1xuICAgIHJldHVybiBuICUgMiA9PT0gMDtcbiAgfSxcblxuICBpc19vZGQ6IGZ1bmN0aW9uIChuKSB7XG4gICAgcmV0dXJuIG4gJSAyICE9PSAwO1xuICB9LFxuXG4gIHBhcnNlOiBmdW5jdGlvbiAoYmluKSB7XG4gICAgbGV0IHJlc3VsdCA9IHBhcnNlSW50KGJpbik7XG5cbiAgICBpZiAoaXNOYU4ocmVzdWx0KSkge1xuICAgICAgcmV0dXJuIEtlcm5lbC5TcGVjaWFsRm9ybXMuYXRvbShcImVycm9yXCIpO1xuICAgIH1cblxuICAgIGxldCBpbmRleE9mRG90ID0gYmluLmluZGV4T2YoXCIuXCIpO1xuXG4gICAgaWYgKGluZGV4T2ZEb3QgPj0gMCkge1xuICAgICAgcmV0dXJuIEtlcm5lbC5TcGVjaWFsRm9ybXMudHVwbGUocmVzdWx0LCBiaW4uc3Vic3RyaW5nKGluZGV4T2ZEb3QpKTtcbiAgICB9XG5cbiAgICByZXR1cm4gS2VybmVsLlNwZWNpYWxGb3Jtcy50dXBsZShyZXN1bHQsIFwiXCIpO1xuICB9LFxuXG4gIHRvX2NoYXJfbGlzdDogZnVuY3Rpb24gKG51bWJlciwgYmFzZSA9IDEwKSB7XG4gICAgcmV0dXJuIG51bWJlci50b1N0cmluZyhiYXNlKS5zcGxpdChcIlwiKTtcbiAgfSxcblxuICB0b19zdHJpbmc6IGZ1bmN0aW9uIChudW1iZXIsIGJhc2UgPSAxMCkge1xuICAgIHJldHVybiBudW1iZXIudG9TdHJpbmcoYmFzZSk7XG4gIH1cbn07XG5cbmxldCBfQ2hhcnMgPSBLZXJuZWwuZGVmcHJvdG9jb2woe1xuICB0b19zdHJpbmc6IGZ1bmN0aW9uICh0aGluZykge31cbn0pO1xuXG5LZXJuZWwuZGVmaW1wbChfQ2hhcnMsIEJpdFN0cmluZywge1xuICB0b19zdHJpbmc6IGZ1bmN0aW9uICh0aGluZykge1xuICAgIGlmIChLZXJuZWwuaXNfYmluYXJ5KHRoaW5nKSkge1xuICAgICAgcmV0dXJuIHRoaW5nO1xuICAgIH1cblxuICAgIHJldHVybiB0aGluZy50b1N0cmluZygpO1xuICB9XG59KTtcblxuS2VybmVsLmRlZmltcGwoX0NoYXJzLCBTeW1ib2wsIHtcbiAgdG9fc3RyaW5nOiBmdW5jdGlvbiAodGhpbmcpIHtcbiAgICBpZiAobmlsKSB7XG4gICAgICByZXR1cm4gXCJcIjtcbiAgICB9XG5cbiAgICByZXR1cm4gQXRvbS50b19zdHJpbmcodGhpbmcpO1xuICB9XG59KTtcblxuS2VybmVsLmRlZmltcGwoX0NoYXJzLCBJbnRlZ2VyVHlwZSwge1xuICB0b19zdHJpbmc6IGZ1bmN0aW9uICh0aGluZykge1xuICAgIHJldHVybiBJbnRlZ2VyLnRvX3N0cmluZyh0aGluZyk7XG4gIH1cbn0pO1xuXG5LZXJuZWwuZGVmaW1wbChfQ2hhcnMsIEZsb2F0VHlwZSwge1xuICB0b19zdHJpbmc6IGZ1bmN0aW9uICh0aGluZykge1xuICAgIHJldHVybiB0aGluZy50b1N0cmluZztcbiAgfVxufSk7XG5cbktlcm5lbC5kZWZpbXBsKF9DaGFycywgQXJyYXksIHtcbiAgdG9fc3RyaW5nOiBmdW5jdGlvbiAodGhpbmcpIHtcbiAgICByZXR1cm4gdGhpbmcudG9TdHJpbmcoKTtcbiAgfVxufSk7XG5cbktlcm5lbC5kZWZpbXBsKF9DaGFycywgVHVwbGUsIHtcbiAgdG9fc3RyaW5nOiBmdW5jdGlvbiAodGhpbmcpIHtcbiAgICByZXR1cm4gVHVwbGUudG9fc3RyaW5nKHRoaW5nKTtcbiAgfVxufSk7XG5cbktlcm5lbC5kZWZpbXBsKF9DaGFycywgbnVsbCwge1xuICB0b19zdHJpbmc6IGZ1bmN0aW9uICh0aGluZykge1xuICAgIHJldHVybiB0aGluZy50b1N0cmluZygpO1xuICB9XG59KTtcblxuZnVuY3Rpb24gdG9fYXRvbShzdHJpbmcpIHtcbiAgcmV0dXJuIFN5bWJvbC5mb3Ioc3RyaW5nKTtcbn1cblxuZnVuY3Rpb24gdG9fZXhpc3RpbmdfYXRvbShzdHJpbmcpIHtcbiAgcmV0dXJuIFN5bWJvbC5mb3Ioc3RyaW5nKTtcbn1cblxuZnVuY3Rpb24gdG9fY2hhcl9saXN0KHN0cmluZykge1xuICByZXR1cm4gc3RyaW5nLnNwbGl0KCcnKTtcbn1cblxuZnVuY3Rpb24gdG9fZmxvYXQoc3RyaW5nKSB7XG4gIHJldHVybiBwYXJzZUZsb2F0KHN0cmluZyk7XG59XG5cbmZ1bmN0aW9uIHRvX2ludGVnZXIoc3RyaW5nLCBiYXNlID0gMTApIHtcbiAgcmV0dXJuIHBhcnNlSW50KHN0cmluZywgYmFzZSk7XG59XG5cbmZ1bmN0aW9uIHVwY2FzZShiaW5hcnkpIHtcbiAgcmV0dXJuIGJpbmFyeS50b1VwcGVyQ2FzZSgpO1xufVxuXG5mdW5jdGlvbiBkb3duY2FzZShiaW5hcnkpIHtcbiAgcmV0dXJuIGJpbmFyeS50b0xvd2VyQ2FzZSgpO1xufVxuXG5mdW5jdGlvbiBhdChzdHJpbmcsIHBvc2l0aW9uKSB7XG4gIGlmIChwb3NpdGlvbiA+IHN0cmluZy5sZW5ndGggLSAxKSB7XG4gICAgcmV0dXJuIG51bGw7XG4gIH1cblxuICByZXR1cm4gc3RyaW5nW3Bvc2l0aW9uXTtcbn1cblxuZnVuY3Rpb24gY2FwaXRhbGl6ZShzdHJpbmcpIHtcbiAgbGV0IHJldHVyblN0cmluZyA9ICcnO1xuXG4gIGZvciAobGV0IGkgPSAwOyBpIDwgc3RyaW5nLmxlbmd0aDsgaSsrKSB7XG4gICAgaWYgKGkgPT09IDApIHtcbiAgICAgIHJldHVyblN0cmluZyA9IHJldHVyblN0cmluZyArIHN0cmluZ1tpXS50b1VwcGVyQ2FzZSgpO1xuICAgIH0gZWxzZSB7XG4gICAgICByZXR1cm5TdHJpbmcgPSByZXR1cm5TdHJpbmcgKyBzdHJpbmdbaV0udG9Mb3dlckNhc2UoKTtcbiAgICB9XG4gIH1cblxuICByZXR1cm4gcmV0dXJuU3RyaW5nO1xufVxuXG5mdW5jdGlvbiBjb2RlcG9pbnRzKHN0cmluZykge1xuICByZXR1cm4gdG9fY2hhcl9saXN0KHN0cmluZykubWFwKGZ1bmN0aW9uIChjKSB7XG4gICAgcmV0dXJuIGMuY29kZVBvaW50QXQoMCk7XG4gIH0pO1xufVxuXG5mdW5jdGlvbiBjb250YWluc19fcW1fXyhzdHJpbmcsIGNvbnRhaW5zKSB7XG4gIGlmIChBcnJheS5pc0FycmF5KGNvbnRhaW5zKSkge1xuICAgIHJldHVybiBjb250YWlucy5zb21lKGZ1bmN0aW9uIChzKSB7XG4gICAgICByZXR1cm4gc3RyaW5nLmluZGV4T2YocykgPiAtMTtcbiAgICB9KTtcbiAgfVxuXG4gIHJldHVybiBzdHJpbmcuaW5kZXhPZihjb250YWlucykgPiAtMTtcbn1cblxuZnVuY3Rpb24gZHVwbGljYXRlKHN1YmplY3QsIG4pIHtcbiAgcmV0dXJuIHN1YmplY3QucmVwZWF0KG4pO1xufVxuXG5mdW5jdGlvbiBlbmRzX3dpdGhfX3FtX18oc3RyaW5nLCBzdWZmaXhlcykge1xuICBpZiAoQXJyYXkuaXNBcnJheShzdWZmaXhlcykpIHtcbiAgICByZXR1cm4gc3VmZml4ZXMuc29tZShmdW5jdGlvbiAocykge1xuICAgICAgcmV0dXJuIHN0cmluZy5lbmRzV2l0aChzKTtcbiAgICB9KTtcbiAgfVxuXG4gIHJldHVybiBzdHJpbmcuZW5kc1dpdGgoc3VmZml4ZXMpO1xufVxuXG5mdW5jdGlvbiBmaXJzdChzdHJpbmcpIHtcbiAgaWYgKCFzdHJpbmcpIHtcbiAgICByZXR1cm4gbnVsbDtcbiAgfVxuXG4gIHJldHVybiBzdHJpbmdbMF07XG59XG5cbmZ1bmN0aW9uIGdyYXBoZW1lcyhzdHJpbmcpIHtcbiAgcmV0dXJuIHN0cmluZy5zcGxpdCgnJyk7XG59XG5cbmZ1bmN0aW9uIGxhc3Qoc3RyaW5nKSB7XG4gIGlmICghc3RyaW5nKSB7XG4gICAgcmV0dXJuIG51bGw7XG4gIH1cblxuICByZXR1cm4gc3RyaW5nW3N0cmluZy5sZW5ndGggLSAxXTtcbn1cblxuZnVuY3Rpb24gbGVuZ3RoKHN0cmluZykge1xuICByZXR1cm4gc3RyaW5nLmxlbmd0aDtcbn1cblxuZnVuY3Rpb24gbWF0Y2hfX3FtX18oc3RyaW5nLCByZWdleCkge1xuICByZXR1cm4gc3RyaW5nLm1hdGNoKHJlZ2V4KSAhPSBudWxsO1xufVxuXG5mdW5jdGlvbiBuZXh0X2NvZGVwb2ludChzdHJpbmcpIHtcbiAgaWYgKCFzdHJpbmcgfHwgc3RyaW5nID09PSAnJykge1xuICAgIHJldHVybiBudWxsO1xuICB9XG5cbiAgcmV0dXJuIEtlcm5lbC5TcGVjaWFsRm9ybXMudHVwbGUoc3RyaW5nWzBdLmNvZGVQb2ludEF0KDApLCBzdHJpbmcuc3Vic3RyKDEpKTtcbn1cblxuZnVuY3Rpb24gbmV4dF9ncmFwaGVtZShzdHJpbmcpIHtcbiAgaWYgKCFzdHJpbmcgfHwgc3RyaW5nID09PSAnJykge1xuICAgIHJldHVybiBudWxsO1xuICB9XG5cbiAgcmV0dXJuIEtlcm5lbC5TcGVjaWFsRm9ybXMudHVwbGUoc3RyaW5nWzBdLCBzdHJpbmcuc3Vic3RyKDEpKTtcbn1cblxuZnVuY3Rpb24gcmV2ZXJzZShzdHJpbmcpIHtcbiAgbGV0IHJldHVyblZhbHVlID0gJyc7XG5cbiAgZm9yICh2YXIgaSA9IHN0cmluZy5sZW5ndGggLSAxOyBpID49IDA7IGktLSkge1xuICAgIHJldHVyblZhbHVlID0gcmV0dXJuVmFsdWUgKyBzdHJpbmdbaV07XG4gIH07XG5cbiAgcmV0dXJuIHJldHVyblZhbHVlO1xufVxuXG5mdW5jdGlvbiBfc3BsaXQoc3RyaW5nKSB7XG4gIHJldHVybiBzdHJpbmcuc3BsaXQoKTtcbn1cblxuZnVuY3Rpb24gc3RhcnRzX3dpdGhfX3FtX18oc3RyaW5nLCBwcmVmaXhlcykge1xuICBpZiAoQXJyYXkuaXNBcnJheShwcmVmaXhlcykpIHtcbiAgICByZXR1cm4gcHJlZml4ZXMuc29tZShmdW5jdGlvbiAocykge1xuICAgICAgcmV0dXJuIHN0cmluZy5zdGFydHNXaXRoKHMpO1xuICAgIH0pO1xuICB9XG5cbiAgcmV0dXJuIHN0cmluZy5zdGFydHNXaXRoKHByZWZpeGVzKTtcbn1cblxuZnVuY3Rpb24gdmFsaWRfY2hhcmFjdGVyX19xbV9fKGNvZGVwb2ludCkge1xuICB0cnkge1xuICAgIHJldHVybiBTdHJpbmcuZnJvbUNvZGVQb2ludChjb2RlcG9pbnQpICE9IG51bGw7XG4gIH0gY2F0Y2ggKGUpIHtcbiAgICByZXR1cm4gZmFsc2U7XG4gIH1cbn1cblxudmFyIF9TdHJpbmcgPSB7XG4gIGF0LFxuICBjYXBpdGFsaXplLFxuICBjb2RlcG9pbnRzLFxuICBjb250YWluc19fcW1fXyxcbiAgZG93bmNhc2UsXG4gIGR1cGxpY2F0ZSxcbiAgZW5kc193aXRoX19xbV9fLFxuICBmaXJzdCxcbiAgZ3JhcGhlbWVzLFxuICBsYXN0LFxuICBsZW5ndGgsXG4gIG1hdGNoX19xbV9fLFxuICBuZXh0X2NvZGVwb2ludCxcbiAgbmV4dF9ncmFwaGVtZSxcbiAgcmV2ZXJzZSxcbiAgc3BsaXQ6IF9zcGxpdCxcbiAgc3RhcnRzX3dpdGhfX3FtX18sXG4gIHRvX2F0b20sXG4gIHRvX2NoYXJfbGlzdCxcbiAgdG9fZXhpc3RpbmdfYXRvbSxcbiAgdG9fZmxvYXQsXG4gIHRvX2ludGVnZXIsXG4gIHVwY2FzZSxcbiAgdmFsaWRfY2hhcmFjdGVyX19xbV9fLFxuICBDaGFyczogX0NoYXJzXG59O1xuXG5sZXQgQ2hhcnMgPSBLZXJuZWwuZGVmcHJvdG9jb2woe1xuICB0b19jaGFyX2xpc3Q6IGZ1bmN0aW9uICh0aGluZykge31cbn0pO1xuXG5LZXJuZWwuZGVmaW1wbChDaGFycywgS2VybmVsLmlzX2JpdHN0cmluZywge1xuICB0b19jaGFyX2xpc3Q6IGZ1bmN0aW9uICh0aGluZykge1xuICAgIGlmIChLZXJuZWwuaXNfYmluYXJ5KHRoaW5nKSkge1xuICAgICAgcmV0dXJuIF9TdHJpbmcudG9fY2hhcl9saXN0KHRoaW5nKTtcbiAgICB9XG5cbiAgICByZXR1cm4gdGhpbmcudG9TdHJpbmcoKTtcbiAgfVxufSk7XG5cbktlcm5lbC5kZWZpbXBsKENoYXJzLCBLZXJuZWwuaXNfYXRvbSwge1xuICB0b19jaGFyX2xpc3Q6IGZ1bmN0aW9uICh0aGluZykge1xuICAgIHJldHVybiBBdG9tLnRvX2NoYXJfbGlzdCh0aGluZyk7XG4gIH1cbn0pO1xuXG5LZXJuZWwuZGVmaW1wbChDaGFycywgS2VybmVsLmlzX2ludGVnZXIsIHtcbiAgdG9fY2hhcl9saXN0OiBmdW5jdGlvbiAodGhpbmcpIHtcbiAgICByZXR1cm4gSW50ZWdlci50b19jaGFyX2xpc3QodGhpbmcpO1xuICB9XG59KTtcblxuS2VybmVsLmRlZmltcGwoQ2hhcnMsIEtlcm5lbC5pc19saXN0LCB7XG4gIHRvX2NoYXJfbGlzdDogZnVuY3Rpb24gKHRoaW5nKSB7XG4gICAgcmV0dXJuIHRoaW5nO1xuICB9XG59KTtcblxubGV0IExpc3QgPSB7fTtcblxuTGlzdC5DaGFycyA9IENoYXJzO1xuXG5MaXN0LmRlbGV0ZSA9IGZ1bmN0aW9uIChsaXN0LCBpdGVtKSB7XG4gIGxldCBuZXdfdmFsdWUgPSBbXTtcbiAgbGV0IHZhbHVlX2ZvdW5kID0gZmFsc2U7XG5cbiAgZm9yIChsZXQgeCBvZiBsaXN0KSB7XG4gICAgaWYgKHggPT09IGl0ZW0gJiYgdmFsdWVfZm91bmQgIT09IGZhbHNlKSB7XG4gICAgICBuZXdfdmFsdWUucHVzaCh4KTtcbiAgICAgIHZhbHVlX2ZvdW5kID0gdHJ1ZTtcbiAgICB9IGVsc2UgaWYgKHggIT09IGl0ZW0pIHtcbiAgICAgIG5ld192YWx1ZS5wdXNoKHgpO1xuICAgIH1cbiAgfVxuXG4gIHJldHVybiBLZXJuZWwuU3BlY2lhbEZvcm1zLmxpc3QoLi4ubmV3X3ZhbHVlKTtcbn07XG5cbkxpc3QuZGVsZXRlX2F0ID0gZnVuY3Rpb24gKGxpc3QsIGluZGV4KSB7XG4gIGxldCBuZXdfdmFsdWUgPSBbXTtcblxuICBmb3IgKGxldCBpID0gMDsgaSA8IGxpc3QubGVuZ3RoOyBpKyspIHtcbiAgICBpZiAoaSAhPT0gaW5kZXgpIHtcbiAgICAgIG5ld192YWx1ZS5wdXNoKGxpc3RbaV0pO1xuICAgIH1cbiAgfVxuXG4gIHJldHVybiBLZXJuZWwuU3BlY2lhbEZvcm1zLmxpc3QoLi4ubmV3X3ZhbHVlKTtcbn07XG5cbkxpc3QuZHVwbGljYXRlID0gZnVuY3Rpb24gKGVsZW0sIG4pIHtcbiAgbGV0IG5ld192YWx1ZSA9IFtdO1xuXG4gIGZvciAodmFyIGkgPSAwOyBpIDwgbjsgaSsrKSB7XG4gICAgbmV3X3ZhbHVlLnB1c2goZWxlbSk7XG4gIH1cblxuICByZXR1cm4gS2VybmVsLlNwZWNpYWxGb3Jtcy5saXN0KC4uLm5ld192YWx1ZSk7XG59O1xuXG5MaXN0LmZpcnN0ID0gZnVuY3Rpb24gKGxpc3QpIHtcbiAgcmV0dXJuIGxpc3RbMF07XG59O1xuXG5MaXN0LmZsYXR0ZW4gPSBmdW5jdGlvbiAobGlzdCwgdGFpbCA9IEtlcm5lbC5TcGVjaWFsRm9ybXMubGlzdCgpKSB7XG4gIGxldCBuZXdfdmFsdWUgPSBbXTtcblxuICBmb3IgKGxldCB4IG9mIGxpc3QpIHtcbiAgICBpZiAoS2VybmVsLmlzX2xpc3QoeCkpIHtcbiAgICAgIG5ld192YWx1ZSA9IG5ld192YWx1ZS5jb25jYXQoTGlzdC5mbGF0dGVuKHgpKTtcbiAgICB9IGVsc2Uge1xuICAgICAgbmV3X3ZhbHVlLnB1c2goeCk7XG4gICAgfVxuICB9XG5cbiAgbmV3X3ZhbHVlID0gbmV3X3ZhbHVlLmNvbmNhdCh0YWlsKTtcblxuICByZXR1cm4gS2VybmVsLlNwZWNpYWxGb3Jtcy5saXN0KC4uLm5ld192YWx1ZSk7XG59O1xuXG5MaXN0LmZvbGRsID0gZnVuY3Rpb24gKGxpc3QsIGFjYywgZnVuYykge1xuICByZXR1cm4gbGlzdC5yZWR1Y2UoZnVuYywgYWNjKTtcbn07XG5cbkxpc3QuZm9sZHIgPSBmdW5jdGlvbiAobGlzdCwgYWNjLCBmdW5jKSB7XG4gIGxldCBuZXdfYWNjID0gYWNjO1xuXG4gIGZvciAodmFyIGkgPSBsaXN0Lmxlbmd0aCAtIDE7IGkgPj0gMDsgaS0tKSB7XG4gICAgbmV3X2FjYyA9IGZ1bmMobGlzdFtpXSwgbmV3X2FjYyk7XG4gIH1cblxuICByZXR1cm4gbmV3X2FjYztcbn07XG5cbkxpc3QuaW5zZXJ0X2F0ID0gZnVuY3Rpb24gKGxpc3QsIGluZGV4LCB2YWx1ZSkge1xuICBsZXQgbmV3X3ZhbHVlID0gW107XG5cbiAgZm9yIChsZXQgaSA9IDA7IGkgPCBsaXN0Lmxlbmd0aDsgaSsrKSB7XG4gICAgaWYgKGkgPT09IGluZGV4KSB7XG4gICAgICBuZXdfdmFsdWUucHVzaCh2YWx1ZSk7XG4gICAgICBuZXdfdmFsdWUucHVzaChsaXN0W2ldKTtcbiAgICB9IGVsc2Uge1xuICAgICAgbmV3X3ZhbHVlLnB1c2gobGlzdFtpXSk7XG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIEtlcm5lbC5TcGVjaWFsRm9ybXMubGlzdCguLi5uZXdfdmFsdWUpO1xufTtcblxuTGlzdC5rZXlkZWxldGUgPSBmdW5jdGlvbiAobGlzdCwga2V5LCBwb3NpdGlvbikge1xuICBsZXQgbmV3X2xpc3QgPSBbXTtcblxuICBmb3IgKGxldCBpID0gMDsgaSA8IGxpc3QubGVuZ3RoOyBpKyspIHtcbiAgICBpZiAoIUtlcm5lbC5tYXRjaF9fcW1hcmtfXyhsaXN0W2ldW3Bvc2l0aW9uXSwga2V5KSkge1xuICAgICAgbmV3X2xpc3QucHVzaChsaXN0W2ldKTtcbiAgICB9XG4gIH1cblxuICByZXR1cm4gS2VybmVsLlNwZWNpYWxGb3Jtcy5saXN0KC4uLm5ld19saXN0KTtcbn07XG5cbkxpc3Qua2V5ZmluZCA9IGZ1bmN0aW9uIChsaXN0LCBrZXksIHBvc2l0aW9uLCBfZGVmYXVsdCA9IG51bGwpIHtcblxuICBmb3IgKGxldCBpID0gMDsgaSA8IGxpc3QubGVuZ3RoOyBpKyspIHtcbiAgICBpZiAoS2VybmVsLm1hdGNoX19xbWFya19fKGxpc3RbaV1bcG9zaXRpb25dLCBrZXkpKSB7XG4gICAgICByZXR1cm4gbGlzdFtpXTtcbiAgICB9XG4gIH1cblxuICByZXR1cm4gX2RlZmF1bHQ7XG59O1xuXG5MaXN0LmtleW1lbWJlcl9fcW1hcmtfXyA9IGZ1bmN0aW9uIChsaXN0LCBrZXksIHBvc2l0aW9uKSB7XG5cbiAgZm9yIChsZXQgaSA9IDA7IGkgPCBsaXN0Lmxlbmd0aDsgaSsrKSB7XG4gICAgaWYgKEtlcm5lbC5tYXRjaF9fcW1hcmtfXyhsaXN0W2ldW3Bvc2l0aW9uXSwga2V5KSkge1xuICAgICAgcmV0dXJuIHRydWU7XG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIGZhbHNlO1xufTtcblxuTGlzdC5rZXlyZXBsYWNlID0gZnVuY3Rpb24gKGxpc3QsIGtleSwgcG9zaXRpb24sIG5ld190dXBsZSkge1xuICBsZXQgbmV3X2xpc3QgPSBbXTtcblxuICBmb3IgKGxldCBpID0gMDsgaSA8IGxpc3QubGVuZ3RoOyBpKyspIHtcbiAgICBpZiAoIUtlcm5lbC5tYXRjaF9fcW1hcmtfXyhsaXN0W2ldW3Bvc2l0aW9uXSwga2V5KSkge1xuICAgICAgbmV3X2xpc3QucHVzaChsaXN0W2ldKTtcbiAgICB9IGVsc2Uge1xuICAgICAgbmV3X2xpc3QucHVzaChuZXdfdHVwbGUpO1xuICAgIH1cbiAgfVxuXG4gIHJldHVybiBLZXJuZWwuU3BlY2lhbEZvcm1zLmxpc3QoLi4ubmV3X2xpc3QpO1xufTtcblxuTGlzdC5rZXlzb3J0ID0gZnVuY3Rpb24gKGxpc3QsIHBvc2l0aW9uKSB7XG4gIGxldCBuZXdfbGlzdCA9IGxpc3Q7XG5cbiAgbmV3X2xpc3Quc29ydChmdW5jdGlvbiAoYSwgYikge1xuICAgIGlmIChwb3NpdGlvbiA9PT0gMCkge1xuICAgICAgaWYgKGFbcG9zaXRpb25dLnZhbHVlIDwgYltwb3NpdGlvbl0udmFsdWUpIHtcbiAgICAgICAgcmV0dXJuIC0xO1xuICAgICAgfVxuXG4gICAgICBpZiAoYVtwb3NpdGlvbl0udmFsdWUgPiBiW3Bvc2l0aW9uXS52YWx1ZSkge1xuICAgICAgICByZXR1cm4gMTtcbiAgICAgIH1cblxuICAgICAgcmV0dXJuIDA7XG4gICAgfSBlbHNlIHtcbiAgICAgIGlmIChhW3Bvc2l0aW9uXSA8IGJbcG9zaXRpb25dKSB7XG4gICAgICAgIHJldHVybiAtMTtcbiAgICAgIH1cblxuICAgICAgaWYgKGFbcG9zaXRpb25dID4gYltwb3NpdGlvbl0pIHtcbiAgICAgICAgcmV0dXJuIDE7XG4gICAgICB9XG5cbiAgICAgIHJldHVybiAwO1xuICAgIH1cbiAgfSk7XG5cbiAgcmV0dXJuIEtlcm5lbC5TcGVjaWFsRm9ybXMubGlzdCguLi5uZXdfbGlzdCk7XG59O1xuXG5MaXN0LmtleXN0b3JlID0gZnVuY3Rpb24gKGxpc3QsIGtleSwgcG9zaXRpb24sIG5ld190dXBsZSkge1xuICBsZXQgbmV3X2xpc3QgPSBbXTtcbiAgbGV0IHJlcGxhY2VkID0gZmFsc2U7XG5cbiAgZm9yIChsZXQgaSA9IDA7IGkgPCBsaXN0Lmxlbmd0aDsgaSsrKSB7XG4gICAgaWYgKCFLZXJuZWwubWF0Y2hfX3FtYXJrX18obGlzdFtpXVtwb3NpdGlvbl0sIGtleSkpIHtcbiAgICAgIG5ld19saXN0LnB1c2gobGlzdFtpXSk7XG4gICAgfSBlbHNlIHtcbiAgICAgIG5ld19saXN0LnB1c2gobmV3X3R1cGxlKTtcbiAgICAgIHJlcGxhY2VkID0gdHJ1ZTtcbiAgICB9XG4gIH1cblxuICBpZiAoIXJlcGxhY2VkKSB7XG4gICAgbmV3X2xpc3QucHVzaChuZXdfdHVwbGUpO1xuICB9XG5cbiAgcmV0dXJuIEtlcm5lbC5TcGVjaWFsRm9ybXMubGlzdCguLi5uZXdfbGlzdCk7XG59O1xuXG5MaXN0Lmxhc3QgPSBmdW5jdGlvbiAobGlzdCkge1xuICByZXR1cm4gbGlzdFtsaXN0Lmxlbmd0aCAtIDFdO1xufTtcblxuTGlzdC5yZXBsYWNlX2F0ID0gZnVuY3Rpb24gKGxpc3QsIGluZGV4LCB2YWx1ZSkge1xuICBsZXQgbmV3X3ZhbHVlID0gW107XG5cbiAgZm9yIChsZXQgaSA9IDA7IGkgPCBsaXN0Lmxlbmd0aDsgaSsrKSB7XG4gICAgaWYgKGkgPT09IGluZGV4KSB7XG4gICAgICBuZXdfdmFsdWUucHVzaCh2YWx1ZSk7XG4gICAgfSBlbHNlIHtcbiAgICAgIG5ld192YWx1ZS5wdXNoKGxpc3RbaV0pO1xuICAgIH1cbiAgfVxuXG4gIHJldHVybiBLZXJuZWwuU3BlY2lhbEZvcm1zLmxpc3QoLi4ubmV3X3ZhbHVlKTtcbn07XG5cbkxpc3QudXBkYXRlX2F0ID0gZnVuY3Rpb24gKGxpc3QsIGluZGV4LCBmdW4pIHtcbiAgbGV0IG5ld192YWx1ZSA9IFtdO1xuXG4gIGZvciAobGV0IGkgPSAwOyBpIDwgbGlzdC5jb3VudCgpOyBpKyspIHtcbiAgICBpZiAoaSA9PT0gaW5kZXgpIHtcbiAgICAgIG5ld192YWx1ZS5wdXNoKGZ1bihsaXN0LmdldChpKSkpO1xuICAgIH0gZWxzZSB7XG4gICAgICBuZXdfdmFsdWUucHVzaChsaXN0LmdldChpKSk7XG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIG5ld192YWx1ZTtcbn07XG5cbkxpc3Qud3JhcCA9IGZ1bmN0aW9uIChsaXN0KSB7XG4gIGlmIChLZXJuZWwuaXNfbGlzdChsaXN0KSkge1xuICAgIHJldHVybiBsaXN0O1xuICB9IGVsc2UgaWYgKGxpc3QgPT0gbnVsbCkge1xuICAgIHJldHVybiBLZXJuZWwuU3BlY2lhbEZvcm1zLmxpc3QoKTtcbiAgfSBlbHNlIHtcbiAgICByZXR1cm4gS2VybmVsLlNwZWNpYWxGb3Jtcy5saXN0KGxpc3QpO1xuICB9XG59O1xuXG5MaXN0LnppcCA9IGZ1bmN0aW9uIChsaXN0X29mX2xpc3RzKSB7XG4gIGlmIChsaXN0X29mX2xpc3RzLmxlbmd0aCA9PT0gMCkge1xuICAgIHJldHVybiBLZXJuZWwuU3BlY2lhbEZvcm1zLmxpc3QoKTtcbiAgfVxuXG4gIGxldCBuZXdfdmFsdWUgPSBbXTtcbiAgbGV0IHNtYWxsZXN0X2xlbmd0aCA9IGxpc3Rfb2ZfbGlzdHNbMF07XG5cbiAgZm9yIChsZXQgeCBvZiBsaXN0X29mX2xpc3RzKSB7XG4gICAgaWYgKHgubGVuZ3RoIDwgc21hbGxlc3RfbGVuZ3RoKSB7XG4gICAgICBzbWFsbGVzdF9sZW5ndGggPSB4Lmxlbmd0aDtcbiAgICB9XG4gIH1cblxuICBmb3IgKGxldCBpID0gMDsgaSA8IHNtYWxsZXN0X2xlbmd0aDsgaSsrKSB7XG4gICAgbGV0IGN1cnJlbnRfdmFsdWUgPSBbXTtcbiAgICBmb3IgKGxldCBqID0gMDsgaiA8IGxpc3Rfb2ZfbGlzdHMubGVuZ3RoOyBqKyspIHtcbiAgICAgIGN1cnJlbnRfdmFsdWUucHVzaChsaXN0X29mX2xpc3RzW2pdW2ldKTtcbiAgICB9XG5cbiAgICBuZXdfdmFsdWUucHVzaChLZXJuZWwuU3BlY2lhbEZvcm1zLnR1cGxlKC4uLmN1cnJlbnRfdmFsdWUpKTtcbiAgfVxuXG4gIHJldHVybiBLZXJuZWwuU3BlY2lhbEZvcm1zLmxpc3QoLi4ubmV3X3ZhbHVlKTtcbn07XG5cbkxpc3QudG9fdHVwbGUgPSBmdW5jdGlvbiAobGlzdCkge1xuICByZXR1cm4gS2VybmVsLlNwZWNpYWxGb3Jtcy50dXBsZS5hcHBseShudWxsLCBsaXN0KTtcbn07XG5cbkxpc3QuYXBwZW5kID0gZnVuY3Rpb24gKGxpc3QsIHZhbHVlKSB7XG4gIHJldHVybiBLZXJuZWwuU3BlY2lhbEZvcm1zLmxpc3QoLi4ubGlzdC5jb25jYXQoW3ZhbHVlXSkpO1xufTtcblxuTGlzdC5wcmVwZW5kID0gZnVuY3Rpb24gKGxpc3QsIHZhbHVlKSB7XG4gIHJldHVybiBLZXJuZWwuU3BlY2lhbEZvcm1zLmxpc3QoLi4uW3ZhbHVlXS5jb25jYXQobGlzdCkpO1xufTtcblxuTGlzdC5jb25jYXQgPSBmdW5jdGlvbiAobGVmdCwgcmlnaHQpIHtcbiAgcmV0dXJuIGxlZnQuY29uY2F0KHJpZ2h0KTtcbn07XG5cbmNsYXNzIFNpZ25hbCB7XG5cbiAgY29uc3RydWN0b3IoKSB7XG4gICAgdGhpcy5iaW5kaW5ncyA9IFNwZWNpYWxGb3Jtcy5saXN0KCk7XG4gIH1cblxuICBhZGQobGlzdGVuZXIsIGNvbnRleHQgPSB0aGlzKSB7XG4gICAgdGhpcy5iaW5kaW5ncyA9IExpc3QuYXBwZW5kKHRoaXMuYmluZGluZ3MsIG5ldyBTaWduYWxCaW5kaW5nKHRoaXMsIGxpc3RlbmVyLCBjb250ZXh0KSk7XG4gIH1cblxuICByZW1vdmUobGlzdGVuZXIpIHtcbiAgICB0aGlzLmJpbmRpbmdzID0gRW51bS5maWx0ZXIodGhpcy5iaW5kaW5ncywgZnVuY3Rpb24gKGJpbmRpbmcpIHtcbiAgICAgIHJldHVybiBiaW5kaW5nLmxpc3RlbmVyICE9PSBsaXN0ZW5lcjtcbiAgICB9KTtcbiAgfVxuXG4gIGRpc3BhdGNoKC4uLnBhcmFtcykge1xuICAgIGZvciAobGV0IGJpbmRpbmcgb2YgdGhpcy5iaW5kaW5ncykge1xuICAgICAgYmluZGluZy5leGVjdXRlKC4uLnBhcmFtcyk7XG4gICAgfVxuICB9XG5cbiAgZGlzcG9zZSgpIHtcbiAgICBmb3IgKGxldCBiaW5kaW5nIG9mIHRoaXMuYmluZGluZ3MpIHtcbiAgICAgIGJpbmRpbmcuZGlzcG9zZSgpO1xuICAgIH1cblxuICAgIHRoaXMuYmluZGluZ3MgPSBudWxsO1xuICB9XG59XG5cbmNsYXNzIFNpZ25hbEJpbmRpbmcge1xuXG4gIGNvbnN0cnVjdG9yKHNpZ25hbCwgbGlzdGVuZXIsIGNvbnRleHQpIHtcbiAgICB0aGlzLmxpc3RlbmVyID0gbGlzdGVuZXI7XG4gICAgdGhpcy5zaWduYWwgPSBzaWduYWw7XG4gICAgdGhpcy5jb250ZXh0ID0gY29udGV4dDtcbiAgfVxuXG4gIGV4ZWN1dGUoLi4ucGFyYW1zKSB7XG4gICAgdGhpcy5saXN0ZW5lci5hcHBseSh0aGlzLmNvbnRleHQsIHBhcmFtcyk7XG4gIH1cblxuICBkaXNwb3NlKCkge1xuICAgIHRoaXMubGlzdGVuZXIgPSBudWxsO1xuICAgIHRoaXMuc2lnbmFsID0gbnVsbDtcbiAgICB0aGlzLmNvbnRleHQgPSBudWxsO1xuICB9XG59XG5cbmZ1bmN0aW9uIF9fX3VwZGF0ZShtYXAsIGtleSwgdmFsdWUpIHtcbiAgbGV0IG0gPSBuZXcgTWFwKG1hcCk7XG4gIG0uc2V0KGtleSwgdmFsdWUpO1xuICByZXR1cm4gbTtcbn1cblxuZnVuY3Rpb24gcmVtb3ZlKG1hcCwga2V5KSB7XG4gIGxldCBtID0gbmV3IE1hcChtYXApO1xuICBtLmRlbGV0ZShrZXkpO1xuICByZXR1cm4gbTtcbn1cblxuY2xhc3MgTWFpbEJveCB7XG5cbiAgY29uc3RydWN0b3IoY29udGV4dCA9IHRoaXMpIHtcbiAgICB0aGlzLnNpZ25hbCA9IG5ldyBTaWduYWwoKTtcbiAgICB0aGlzLnNpZ25hbC5hZGQoKC4uLnBhcmFtcykgPT4gdGhpcy5tZXNzYWdlcyA9IHRoaXMubWVzc2FnZXMuY29uY2F0KHBhcmFtcyksIGNvbnRleHQpO1xuICAgIHRoaXMubWVzc2FnZXMgPSBbXTtcbiAgfVxuXG4gIHJlY2VpdmUoLi4ubWVzc2FnZXMpIHtcbiAgICB0aGlzLnNpZ25hbC5kaXNwYXRjaCguLi5tZXNzYWdlcyk7XG4gIH1cblxuICBwZWVrKCkge1xuICAgIGlmICh0aGlzLm1lc3NhZ2VzLmxlbmd0aCA9PT0gMCkge1xuICAgICAgcmV0dXJuIG51bGw7XG4gICAgfVxuXG4gICAgcmV0dXJuIHRoaXMubWVzc2FnZXNbMF07XG4gIH1cblxuICByZWFkKCkge1xuICAgIGxldCByZXN1bHQgPSB0aGlzLm1lc3NhZ2VzWzBdO1xuICAgIHRoaXMubWVzc2FnZXMgPSB0aGlzLm1lc3NhZ2VzLnNsaWNlKDEpO1xuXG4gICAgcmV0dXJuIHJlc3VsdDtcbiAgfVxuXG4gIGFkZF9zdWJzY3JpYmVyKGZuLCBjb250ZXh0ID0gdGhpcykge1xuICAgIHRoaXMuc2lnbmFsLmFkZChmbiwgY29udGV4dCk7XG4gIH1cblxuICByZW1vdmVfc3Vic2NyaWJlcihmbikge1xuICAgIHRoaXMuc2lnbmFsLnJlbW92ZShmbik7XG4gIH1cblxuICBkaXNwb3NlKCkge1xuICAgIHRoaXMuc2lnbmFsLmRpc3Bvc2UoKTtcbiAgICB0aGlzLm1lc3NhZ2VzID0gbnVsbDtcbiAgfVxufVxuXG5jbGFzcyBQb3N0T2ZmaWNlIHtcblxuICBjb25zdHJ1Y3RvcigpIHtcbiAgICB0aGlzLm1haWxib3hlcyA9IG5ldyBNYXAoKTtcbiAgfVxuXG4gIHNlbmQoYWRkcmVzcywgbWVzc2FnZSkge1xuICAgIHRoaXMubWFpbGJveGVzLmdldChhZGRyZXNzKS5yZWNlaXZlKG1lc3NhZ2UpO1xuICB9XG5cbiAgcmVjZWl2ZShhZGRyZXNzKSB7XG4gICAgcmV0dXJuIHRoaXMubWFpbGJveGVzLmdldChhZGRyZXNzKS5yZWFkKCk7XG4gIH1cblxuICBwZWVrKGFkZHJlc3MpIHtcbiAgICByZXR1cm4gdGhpcy5tYWlsYm94ZXMuZ2V0KGFkZHJlc3MpLnBlZWsoKTtcbiAgfVxuXG4gIGFkZF9tYWlsYm94KGFkZHJlc3MgPSBTeW1ib2woKSwgY29udGV4dCA9IHRoaXMpIHtcbiAgICB0aGlzLm1haWxib3hlcyA9IF9fX3VwZGF0ZSh0aGlzLm1haWxib3hlcywgYWRkcmVzcywgbmV3IE1haWxCb3goKSk7XG4gICAgcmV0dXJuIGFkZHJlc3M7XG4gIH1cblxuICByZW1vdmVfbWFpbGJveChhZGRyZXNzKSB7XG4gICAgdGhpcy5tYWlsYm94ZXMuZ2V0KGFkZHJlc3MpLmRpc3Bvc2UoKTtcbiAgICB0aGlzLm1haWxib3hlcyA9IHJlbW92ZSh0aGlzLm1haWxib3hlcywgYWRkcmVzcyk7XG4gIH1cblxuICBzdWJzY3JpYmUoYWRkcmVzcywgc3Vic2NyaWJ0aW9uX2ZuLCBjb250ZXh0ID0gdGhpcykge1xuICAgIHRoaXMubWFpbGJveGVzLmdldChhZGRyZXNzKS5hZGRfc3Vic2NyaWJlcihzdWJzY3JpYnRpb25fZm4sIGNvbnRleHQpO1xuICB9XG5cbiAgdW5zdWJzY3JpYmUoYWRkcmVzcywgc3Vic2NyaWJ0aW9uX2ZuKSB7XG4gICAgdGhpcy5tYWlsYm94ZXMuZ2V0KGFkZHJlc3MpLnJlbW92ZV9zdWJzY3JpYmVyKHN1YnNjcmlidGlvbl9mbik7XG4gIH1cbn1cblxuZnVuY3Rpb24gY2FsbF9wcm9wZXJ0eShpdGVtLCBwcm9wZXJ0eSkge1xuICBpZiAocHJvcGVydHkgaW4gaXRlbSkge1xuICAgIGl0ZW1bcHJvcGVydHldO1xuICAgIGlmIChpdGVtW3Byb3BlcnR5XSBpbnN0YW5jZW9mIEZ1bmN0aW9uKSB7XG4gICAgICByZXR1cm4gaXRlbVtwcm9wZXJ0eV0oKTtcbiAgICB9IGVsc2Uge1xuICAgICAgcmV0dXJuIGl0ZW1bcHJvcGVydHldO1xuICAgIH1cbiAgfSBlbHNlIGlmIChTeW1ib2wuZm9yKHByb3BlcnR5KSBpbiBpdGVtKSB7XG4gICAgbGV0IHByb3AgPSBTeW1ib2wuZm9yKHByb3BlcnR5KTtcbiAgICBpZiAoaXRlbVtwcm9wXSBpbnN0YW5jZW9mIEZ1bmN0aW9uKSB7XG4gICAgICByZXR1cm4gaXRlbVtwcm9wXSgpO1xuICAgIH0gZWxzZSB7XG4gICAgICByZXR1cm4gaXRlbVtwcm9wXTtcbiAgICB9XG4gIH1cblxuICB0aHJvdyBuZXcgRXJyb3IoYFByb3BlcnR5ICR7IHByb3BlcnR5IH0gbm90IGZvdW5kIGluICR7IGl0ZW0gfWApO1xufVxuXG52YXIgSlMgPSB7XG4gIGNhbGxfcHJvcGVydHlcbn07XG5cbmxldCBSYW5nZSA9IGZ1bmN0aW9uIChfZmlyc3QsIF9sYXN0KSB7XG4gIGlmICghKHRoaXMgaW5zdGFuY2VvZiBSYW5nZSkpIHtcbiAgICByZXR1cm4gbmV3IFJhbmdlKF9maXJzdCwgX2xhc3QpO1xuICB9XG5cbiAgdGhpcy5maXJzdCA9IGZ1bmN0aW9uICgpIHtcbiAgICByZXR1cm4gX2ZpcnN0O1xuICB9O1xuXG4gIHRoaXMubGFzdCA9IGZ1bmN0aW9uICgpIHtcbiAgICByZXR1cm4gX2xhc3Q7XG4gIH07XG5cbiAgbGV0IF9yYW5nZSA9IFtdO1xuXG4gIGZvciAobGV0IGkgPSBfZmlyc3Q7IGkgPD0gX2xhc3Q7IGkrKykge1xuICAgIF9yYW5nZS5wdXNoKGkpO1xuICB9XG5cbiAgX3JhbmdlID0gT2JqZWN0LmZyZWV6ZShfcmFuZ2UpO1xuXG4gIHRoaXMudmFsdWUgPSBmdW5jdGlvbiAoKSB7XG4gICAgcmV0dXJuIF9yYW5nZTtcbiAgfTtcblxuICB0aGlzLmxlbmd0aCA9IGZ1bmN0aW9uICgpIHtcbiAgICByZXR1cm4gX3JhbmdlLmxlbmd0aDtcbiAgfTtcblxuICByZXR1cm4gdGhpcztcbn07XG5cblJhbmdlLnByb3RvdHlwZVtTeW1ib2wuaXRlcmF0b3JdID0gZnVuY3Rpb24gKCkge1xuICByZXR1cm4gdGhpcy52YWx1ZSgpW1N5bWJvbC5pdGVyYXRvcl0oKTtcbn07XG5cblJhbmdlLm5ldyA9IGZ1bmN0aW9uIChmaXJzdCwgbGFzdCkge1xuICByZXR1cm4gUmFuZ2UoZmlyc3QsIGxhc3QpO1xufTtcblxuUmFuZ2UucmFuZ2VfX3FtYXJrX18gPSBmdW5jdGlvbiAocmFuZ2UpIHtcbiAgcmV0dXJuIHJhbmdlIGluc3RhbmNlb2YgUmFuZ2U7XG59O1xuXG5sZXQgS2V5d29yZCA9IHt9O1xuXG5LZXl3b3JkLmhhc19rZXlfX3FtX18gPSBmdW5jdGlvbiAoa2V5d29yZHMsIGtleSkge1xuICBmb3IgKGxldCBrZXl3b3JkIG9mIGtleXdvcmRzKSB7XG4gICAgaWYgKEtlcm5lbC5lbGVtKGtleXdvcmQsIDApID09IGtleSkge1xuICAgICAgcmV0dXJuIHRydWU7XG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIGZhbHNlO1xufTtcblxuS2V5d29yZC5nZXQgPSBmdW5jdGlvbiAoa2V5d29yZHMsIGtleSwgdGhlX2RlZmF1bHQgPSBudWxsKSB7XG4gIGZvciAobGV0IGtleXdvcmQgb2Yga2V5d29yZHMpIHtcbiAgICBpZiAoS2VybmVsLmVsZW0oa2V5d29yZCwgMCkgPT0ga2V5KSB7XG4gICAgICByZXR1cm4gS2VybmVsLmVsZW0oa2V5d29yZCwgMSk7XG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIHRoZV9kZWZhdWx0O1xufTtcblxubGV0IEFnZW50ID0ge307XG5cbkFnZW50LnN0YXJ0ID0gZnVuY3Rpb24gKGZ1biwgb3B0aW9ucyA9IFtdKSB7XG4gIGNvbnN0IG5hbWUgPSBLZXl3b3JkLmhhc19rZXlfX3FtX18ob3B0aW9ucywgS2VybmVsLlNwZWNpYWxGb3Jtcy5hdG9tKCduYW1lJykpID8gS2V5d29yZC5nZXQob3B0aW9ucywgS2VybmVsLlNwZWNpYWxGb3Jtcy5hdG9tKCduYW1lJykpIDogU3ltYm9sKCk7XG5cbiAgc2VsZi5wb3N0X29mZmljZS5hZGRfbWFpbGJveChuYW1lKTtcbiAgc2VsZi5wb3N0X29mZmljZS5zZW5kKG5hbWUsIGZ1bigpKTtcblxuICByZXR1cm4gS2VybmVsLlNwZWNpYWxGb3Jtcy50dXBsZShLZXJuZWwuU3BlY2lhbEZvcm1zLmF0b20oJ29rJyksIG5hbWUpO1xufTtcblxuQWdlbnQuc3RvcCA9IGZ1bmN0aW9uIChhZ2VudCwgdGltZW91dCA9IDUwMDApIHtcbiAgc2VsZi5wb3N0X29mZmljZS5yZW1vdmVfbWFpbGJveChhZ2VudCk7XG4gIHJldHVybiBLZXJuZWwuU3BlY2lhbEZvcm1zLmF0b20oJ29rJyk7XG59O1xuXG5BZ2VudC51cGRhdGUgPSBmdW5jdGlvbiAoYWdlbnQsIGZ1biwgdGltZW91dCA9IDUwMDApIHtcblxuICBjb25zdCBjdXJyZW50X3N0YXRlID0gc2VsZi5wb3N0X29mZmljZS5yZWNlaXZlKGFnZW50KTtcbiAgc2VsZi5wb3N0X29mZmljZS5zZW5kKGFnZW50LCBmdW4oY3VycmVudF9zdGF0ZSkpO1xuXG4gIHJldHVybiBLZXJuZWwuU3BlY2lhbEZvcm1zLmF0b20oJ29rJyk7XG59O1xuXG5BZ2VudC5nZXQgPSBmdW5jdGlvbiAoYWdlbnQsIGZ1biwgdGltZW91dCA9IDUwMDApIHtcbiAgcmV0dXJuIGZ1bihzZWxmLnBvc3Rfb2ZmaWNlLnBlZWsoYWdlbnQpKTtcbn07XG5cbkFnZW50LmdldF9hbmRfdXBkYXRlID0gZnVuY3Rpb24gKGFnZW50LCBmdW4sIHRpbWVvdXQgPSA1MDAwKSB7XG5cbiAgY29uc3QgZ2V0X2FuZF91cGRhdGVfdHVwbGUgPSBmdW4oc2VsZi5wb3N0X29mZmljZS5yZWNlaXZlKGFnZW50KSk7XG4gIHNlbGYucG9zdF9vZmZpY2Uuc2VuZChhZ2VudCwgS2VybmVsLmVsZW0oZ2V0X2FuZF91cGRhdGVfdHVwbGUsIDEpKTtcblxuICByZXR1cm4gS2VybmVsLmVsZW0oZ2V0X2FuZF91cGRhdGVfdHVwbGUsIDApO1xufTtcblxuLy9odHRwczovL2RldmVsb3Blci5tb3ppbGxhLm9yZy9lbi1VUy9kb2NzL1dlYi9BUEkvV2luZG93QmFzZTY0L0Jhc2U2NF9lbmNvZGluZ19hbmRfZGVjb2RpbmcjU29sdXRpb25fMl8lRTIlODAlOTNfcmV3cml0ZV90aGVfRE9Nc19hdG9iKClfYW5kX2J0b2EoKV91c2luZ19KYXZhU2NyaXB0J3NfVHlwZWRBcnJheXNfYW5kX1VURi04XG5mdW5jdGlvbiBiNjRFbmNvZGVVbmljb2RlKHN0cikge1xuICByZXR1cm4gYnRvYShlbmNvZGVVUklDb21wb25lbnQoc3RyKS5yZXBsYWNlKC8lKFswLTlBLUZdezJ9KS9nLCBmdW5jdGlvbiAobWF0Y2gsIHAxKSB7XG4gICAgcmV0dXJuIFN0cmluZy5mcm9tQ2hhckNvZGUoJzB4JyArIHAxKTtcbiAgfSkpO1xufVxuXG5mdW5jdGlvbiBlbmNvZGU2NChkYXRhKSB7XG4gIHJldHVybiBiNjRFbmNvZGVVbmljb2RlKGRhdGEpO1xufVxuXG5mdW5jdGlvbiBkZWNvZGU2NChkYXRhKSB7XG4gIHRyeSB7XG4gICAgcmV0dXJuIEtlcm5lbC5TcGVjaWFsRm9ybXMudHVwbGUoS2VybmVsLlNwZWNpYWxGb3Jtcy5hdG9tKCdvaycpLCBhdG9iKGRhdGEpKTtcbiAgfSBjYXRjaCAoZSkge1xuICAgIHJldHVybiBLZXJuZWwuU3BlY2lhbEZvcm1zLmF0b20oJ2Vycm9yJyk7XG4gIH1cbiAgcmV0dXJuIGJ0b2EoZGF0YSk7XG59XG5cbmZ1bmN0aW9uIGRlY29kZTY0X19lbV9fKGRhdGEpIHtcbiAgcmV0dXJuIGF0b2IoZGF0YSk7XG59XG5cbnZhciBCYXNlID0ge1xuICBlbmNvZGU2NCxcbiAgZGVjb2RlNjQsXG4gIGRlY29kZTY0X19lbV9fXG59O1xuXG5mdW5jdGlvbiBibm90KGV4cHIpIHtcbiAgcmV0dXJuIH5leHByO1xufVxuXG5mdW5jdGlvbiBiYW5kKGxlZnQsIHJpZ2h0KSB7XG4gIHJldHVybiBsZWZ0ICYgcmlnaHQ7XG59XG5cbmZ1bmN0aW9uIGJvcihsZWZ0LCByaWdodCkge1xuICByZXR1cm4gbGVmdCB8IHJpZ2h0O1xufVxuXG5mdW5jdGlvbiBic2wobGVmdCwgcmlnaHQpIHtcbiAgcmV0dXJuIGxlZnQgPDwgcmlnaHQ7XG59XG5cbmZ1bmN0aW9uIGJzcihsZWZ0LCByaWdodCkge1xuICByZXR1cm4gbGVmdCA+PiByaWdodDtcbn1cblxuZnVuY3Rpb24gYnhvcihsZWZ0LCByaWdodCkge1xuICByZXR1cm4gbGVmdCBeIHJpZ2h0O1xufVxuXG52YXIgQml0d2lzZSA9IHtcbiAgYm5vdCxcbiAgYmFuZCxcbiAgYm9yLFxuICBic2wsXG4gIGJzcixcbiAgYnhvclxufTtcblxubGV0IEVudW1lcmFibGUgPSBLZXJuZWwuZGVmcHJvdG9jb2woe1xuICBjb3VudDogZnVuY3Rpb24gKGNvbGxlY3Rpb24pIHt9LFxuICBtZW1iZXJfcW1hcmtfXzogZnVuY3Rpb24gKGNvbGxlY3Rpb24sIHZhbHVlKSB7fSxcbiAgcmVkdWNlOiBmdW5jdGlvbiAoY29sbGVjdGlvbiwgYWNjLCBmdW4pIHt9XG59KTtcblxubGV0IENvbGxlY3RhYmxlID0gS2VybmVsLmRlZnByb3RvY29sKHtcbiAgaW50bzogZnVuY3Rpb24gKGNvbGxlY3RhYmxlKSB7fVxufSk7XG5cbmxldCBJbnNwZWN0ID0gS2VybmVsLmRlZnByb3RvY29sKHtcbiAgaW5zcGVjdDogZnVuY3Rpb24gKHRoaW5nLCBvcHRzKSB7fVxufSk7XG5cbmZ1bmN0aW9uIF9fX25ld19fKCkge1xuICByZXR1cm4gU3BlY2lhbEZvcm1zLm1hcCh7fSk7XG59XG5cbmZ1bmN0aW9uIGtleXMobWFwKSB7XG4gIHJldHVybiBPYmplY3Qua2V5cyhtYXApO1xufVxuXG5mdW5jdGlvbiBfX3NpemUobWFwKSB7XG4gIHJldHVybiBrZXlzKG1hcCkubGVuZ3RoO1xufVxuXG5mdW5jdGlvbiBfX3RvX2xpc3QobWFwKSB7XG4gIGxldCBtYXBfa2V5cyA9IGtleXMobWFwKTtcbiAgbGV0IGxpc3QgPSBbXTtcblxuICBmb3IgKGxldCBrZXkgb2YgbWFwX2tleXMpIHtcbiAgICBsaXN0LnB1c2goU3BlY2lhbEZvcm1zLnR1cGxlKGtleSwgbWFwW2tleV0pKTtcbiAgfVxuXG4gIHJldHVybiBTcGVjaWFsRm9ybXMubGlzdCguLi5saXN0KTtcbn1cblxuZnVuY3Rpb24gdmFsdWVzKG1hcCkge1xuICBsZXQgbWFwX2tleXMgPSBrZXlzKG1hcCk7XG4gIGxldCBsaXN0ID0gW107XG5cbiAgZm9yIChsZXQga2V5IG9mIG1hcF9rZXlzKSB7XG4gICAgbGlzdC5wdXNoKG1hcFtrZXldKTtcbiAgfVxuXG4gIHJldHVybiBTcGVjaWFsRm9ybXMubGlzdCguLi5saXN0KTtcbn1cblxuZnVuY3Rpb24gZnJvbV9zdHJ1Y3Qoc3RydWN0KSB7XG4gIGxldCBtYXAgPSBPYmplY3QuYXNzaWduKHt9LCBzdHJ1Y3QpO1xuICBkZWxldGUgbWFwW1N5bWJvbC5mb3IoXCJfX3N0cnVjdF9fXCIpXTtcblxuICByZXR1cm4gU3BlY2lhbEZvcm1zLm1hcChtYXApO1xufVxuXG5mdW5jdGlvbiBfX19fZGVsZXRlX18obWFwLCBrZXkpIHtcbiAgbGV0IG5ld19tYXAgPSBPYmplY3QuYXNzaWduKHt9LCBtYXApO1xuXG4gIGRlbGV0ZSBuZXdfbWFwW2tleV07XG5cbiAgcmV0dXJuIFNwZWNpYWxGb3Jtcy5tYXAobmV3X21hcCk7XG59XG5cbmZ1bmN0aW9uIGRyb3AobWFwLCBrZXlzKSB7XG4gIGxldCBuZXdfbWFwID0gT2JqZWN0LmFzc2lnbih7fSwgbWFwKTtcblxuICBmb3IgKGxldCBrZXkgb2Yga2V5cykge1xuICAgIGRlbGV0ZSBuZXdfbWFwW2tleV07XG4gIH1cblxuICByZXR1cm4gU3BlY2lhbEZvcm1zLm1hcChuZXdfbWFwKTtcbn1cblxuZnVuY3Rpb24gX19lcXVhbF9fcW1hcmtfXyhtYXAxLCBtYXAyKSB7XG4gIHJldHVybiBtYXAxID09PSBtYXAyO1xufVxuXG5mdW5jdGlvbiBmZXRjaF9fZW1hcmtfXyhtYXAsIGtleSkge1xuICBpZiAoa2V5IGluIG1hcCkge1xuICAgIHJldHVybiBtYXBba2V5XTtcbiAgfVxuXG4gIHRocm93IG5ldyBFcnJvcihcIktleSBub3QgZm91bmQuXCIpO1xufVxuXG5mdW5jdGlvbiBmZXRjaChtYXAsIGtleSkge1xuICBpZiAoa2V5IGluIG1hcCkge1xuICAgIHJldHVybiBTcGVjaWFsRm9ybXMudHVwbGUoU3BlY2lhbEZvcm1zLmF0b20oXCJva1wiKSwgbWFwW2tleV0pO1xuICB9XG5cbiAgcmV0dXJuIFNwZWNpYWxGb3Jtcy5hdG9tKFwiZXJyb3JcIik7XG59XG5cbmZ1bmN0aW9uIGhhc19rZXlfX3FtYXJrX18obWFwLCBrZXkpIHtcbiAgcmV0dXJuIGtleSBpbiBtYXA7XG59XG5cbmZ1bmN0aW9uIG1lcmdlKG1hcDEsIG1hcDIpIHtcbiAgcmV0dXJuIFNwZWNpYWxGb3Jtcy5tYXBfdXBkYXRlKG1hcDEsIG1hcDIpO1xufVxuXG5mdW5jdGlvbiBzcGxpdChtYXAsIGtleXMpIHtcbiAgbGV0IHNwbGl0MSA9IHt9O1xuICBsZXQgc3BsaXQyID0ge307XG5cbiAgZm9yIChsZXQga2V5IG9mIE9iamVjdC5rZXlzKG1hcCkpIHtcbiAgICBpZiAoa2V5cy5pbmRleE9mKGtleSkgPiAtMSkge1xuICAgICAgc3BsaXQxW2tleV0gPSBtYXBba2V5XTtcbiAgICB9IGVsc2Uge1xuICAgICAgc3BsaXQyW2tleV0gPSBtYXBba2V5XTtcbiAgICB9XG4gIH1cblxuICByZXR1cm4gU3BlY2lhbEZvcm1zLnR1cGxlKFNwZWNpYWxGb3Jtcy5tYXAoc3BsaXQxKSwgU3BlY2lhbEZvcm1zLm1hcChzcGxpdDIpKTtcbn1cblxuZnVuY3Rpb24gdGFrZShtYXAsIGtleXMpIHtcbiAgbGV0IHNwbGl0MSA9IHt9O1xuXG4gIGZvciAobGV0IGtleSBvZiBPYmplY3Qua2V5cyhtYXApKSB7XG4gICAgaWYgKGtleXMuaW5kZXhPZihrZXkpID4gLTEpIHtcbiAgICAgIHNwbGl0MVtrZXldID0gbWFwW2tleV07XG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIFNwZWNpYWxGb3Jtcy5tYXAoc3BsaXQxKTtcbn1cblxuZnVuY3Rpb24gZHJvcChtYXAsIGtleXMpIHtcbiAgbGV0IHNwbGl0MSA9IHt9O1xuXG4gIGZvciAobGV0IGtleSBvZiBPYmplY3Qua2V5cyhtYXApKSB7XG4gICAgaWYgKGtleXMuaW5kZXhPZihrZXkpID09PSAtMSkge1xuICAgICAgc3BsaXQxW2tleV0gPSBtYXBba2V5XTtcbiAgICB9XG4gIH1cblxuICByZXR1cm4gU3BlY2lhbEZvcm1zLm1hcChzcGxpdDEpO1xufVxuXG5mdW5jdGlvbiBwdXRfbmV3KG1hcCwga2V5LCB2YWx1ZSkge1xuICBpZiAoa2V5IGluIG1hcCkge1xuICAgIHJldHVybiBtYXA7XG4gIH1cblxuICBsZXQgbmV3X21hcCA9IE9iamVjdC5hc3NpZ24oe30sIG1hcCk7XG4gIG5ld19tYXBba2V5XSA9IHZhbHVlO1xuXG4gIHJldHVybiBTcGVjaWFsRm9ybXMubWFwKG5ld19tYXApO1xufVxuXG5mdW5jdGlvbiBwdXRfbmV3X2xhenkobWFwLCBrZXksIGZ1bikge1xuICBpZiAoa2V5IGluIG1hcCkge1xuICAgIHJldHVybiBtYXA7XG4gIH1cblxuICBsZXQgbmV3X21hcCA9IE9iamVjdC5hc3NpZ24oe30sIG1hcCk7XG4gIG5ld19tYXBba2V5XSA9IGZ1bigpO1xuXG4gIHJldHVybiBTcGVjaWFsRm9ybXMubWFwKG5ld19tYXApO1xufVxuXG5mdW5jdGlvbiBnZXRfYW5kX3VwZGF0ZShtYXAsIGtleSwgZnVuKSB7XG4gIGlmIChrZXkgaW4gbWFwKSB7XG4gICAgcmV0dXJuIG1hcDtcbiAgfVxuXG4gIGxldCBuZXdfbWFwID0gT2JqZWN0LmFzc2lnbih7fSwgbWFwKTtcbiAgbmV3X21hcFtrZXldID0gZnVuKG1hcFtrZXldKTtcblxuICByZXR1cm4gU3BlY2lhbEZvcm1zLm1hcChuZXdfbWFwKTtcbn1cblxuZnVuY3Rpb24gcG9wX2xhenkobWFwLCBrZXksIGZ1bikge1xuICBpZiAoIWtleSBpbiBtYXApIHtcbiAgICByZXR1cm4gU3BlY2lhbEZvcm1zLnR1cGxlKGZ1bigpLCBtYXApO1xuICB9XG5cbiAgbGV0IG5ld19tYXAgPSBPYmplY3QuYXNzaWduKHt9LCBtYXApO1xuICBsZXQgdmFsdWUgPSBmdW4obmV3X21hcFtrZXldKTtcbiAgZGVsZXRlIG5ld19tYXBba2V5XTtcblxuICByZXR1cm4gU3BlY2lhbEZvcm1zLnR1cGxlKHZhbHVlLCBuZXdfbWFwKTtcbn1cblxuZnVuY3Rpb24gcG9wKG1hcCwga2V5LCBfZGVmYXVsdCA9IG51bGwpIHtcbiAgaWYgKCFrZXkgaW4gbWFwKSB7XG4gICAgcmV0dXJuIFNwZWNpYWxGb3Jtcy50dXBsZShfZGVmYXVsdCwgbWFwKTtcbiAgfVxuXG4gIGxldCBuZXdfbWFwID0gT2JqZWN0LmFzc2lnbih7fSwgbWFwKTtcbiAgbGV0IHZhbHVlID0gbmV3X21hcFtrZXldO1xuICBkZWxldGUgbmV3X21hcFtrZXldO1xuXG4gIHJldHVybiBTcGVjaWFsRm9ybXMudHVwbGUodmFsdWUsIG5ld19tYXApO1xufVxuXG5mdW5jdGlvbiBnZXRfbGF6eShtYXAsIGtleSwgZnVuKSB7XG4gIGlmICgha2V5IGluIG1hcCkge1xuICAgIHJldHVybiBmdW4oKTtcbiAgfVxuXG4gIHJldHVybiBmdW4obWFwW2tleV0pO1xufVxuXG5mdW5jdGlvbiBnZXQobWFwLCBrZXksIF9kZWZhdWx0ID0gbnVsbCkge1xuICBpZiAoIWtleSBpbiBtYXApIHtcbiAgICByZXR1cm4gX2RlZmF1bHQ7XG4gIH1cblxuICByZXR1cm4gbWFwW2tleV07XG59XG5cbmZ1bmN0aW9uIF9fcHV0KG1hcCwga2V5LCB2YWwpIHtcbiAgbGV0IG5ld19tYXAgPSBPYmplY3Qoe30sIG1hcCk7XG4gIG5ld19tYXBba2V5XSA9IHZhbDtcblxuICByZXR1cm4gU3BlY2lhbEZvcm1zLm1hcChuZXdfbWFwKTtcbn1cblxuZnVuY3Rpb24gdXBkYXRlX19lbWFya19fKG1hcCwga2V5LCBmdW4pIHtcbiAgaWYgKCFrZXkgaW4gbWFwKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKFwiS2V5IG5vdCBmb3VuZFwiKTtcbiAgfVxuXG4gIGxldCBuZXdfbWFwID0gT2JqZWN0KHt9LCBtYXApO1xuICBuZXdfbWFwW2tleV0gPSBmdW4obWFwW2tleV0pO1xuXG4gIHJldHVybiBTcGVjaWFsRm9ybXMubWFwKG5ld19tYXApO1xufVxuXG5mdW5jdGlvbiBfX3VwZGF0ZShtYXAsIGtleSwgaW5pdGlhbCwgZnVuKSB7XG4gIGxldCBuZXdfbWFwID0gT2JqZWN0KHt9LCBtYXApO1xuXG4gIGlmICgha2V5IGluIG1hcCkge1xuICAgIG5ld19tYXBba2V5XSA9IGluaXRpYWw7XG4gIH0gZWxzZSB7XG4gICAgbmV3X21hcFtrZXldID0gZnVuKG1hcFtrZXldKTtcbiAgfVxuXG4gIHJldHVybiBTcGVjaWFsRm9ybXMubWFwKG5ld19tYXApO1xufVxuXG52YXIgX01hcCA9IHtcbiAgbmV3OiBfX19uZXdfXyxcbiAga2V5cyxcbiAgc2l6ZTogX19zaXplLFxuICB0b19saXN0OiBfX3RvX2xpc3QsXG4gIHZhbHVlcyxcbiAgZnJvbV9zdHJ1Y3QsXG4gIGRlbGV0ZTogX19fX2RlbGV0ZV9fLFxuICBkcm9wLFxuICBlcXVhbF9fcW1hcmtfXzogX19lcXVhbF9fcW1hcmtfXyxcbiAgZmV0Y2hfX2VtYXJrX18sXG4gIGZldGNoLFxuICBoYXNfa2V5X19xbWFya19fLFxuICBzcGxpdCxcbiAgdGFrZSxcbiAgcHV0X25ldyxcbiAgcHV0X25ld19sYXp5LFxuICBnZXRfYW5kX3VwZGF0ZSxcbiAgcG9wX2xhenksXG4gIHBvcCxcbiAgZ2V0X2xhenksXG4gIGdldCxcbiAgcHV0OiBfX3B1dCxcbiAgdXBkYXRlX19lbWFya19fLFxuICB1cGRhdGU6IF9fdXBkYXRlXG59O1xuXG5mdW5jdGlvbiBfX25ld19fKCkge1xuICByZXR1cm4gU3BlY2lhbEZvcm1zLm1hcCh7IFtTeW1ib2wuZm9yKCdfX3N0cnVjdF9fJyldOiBTeW1ib2wuZm9yKCdNYXBTZXQnKSwgc2V0OiBTcGVjaWFsRm9ybXMubGlzdCgpIH0pO1xufVxuXG5mdW5jdGlvbiBfc2l6ZShtYXApIHtcbiAgcmV0dXJuIG1hcC5zZXQubGVuZ3RoO1xufVxuXG5mdW5jdGlvbiBfdG9fbGlzdChtYXApIHtcbiAgcmV0dXJuIG1hcC5zZXQ7XG59XG5cbmZ1bmN0aW9uIF9fX2RlbGV0ZV9fKHNldCwgdGVybSkge1xuICBsZXQgbmV3X2xpc3QgPSBMaXN0LmRlbGV0ZShzZXQuc2V0LCB0ZXJtKTtcblxuICBsZXQgbmV3X21hcCA9IE9iamVjdC5hc3NpZ24oe30sIHNldCk7XG4gIG5ld19tYXAuc2V0ID0gbmV3X2xpc3Q7XG4gIHJldHVybiBTcGVjaWFsRm9ybXMubWFwKG5ld19tYXApO1xufVxuXG5mdW5jdGlvbiBfcHV0KHNldCwgdGVybSkge1xuICBpZiAoc2V0LnNldC5pbmRleE9mKHRlcm0pID09PSAtMSkge1xuICAgIGxldCBuZXdfbGlzdCA9IExpc3QuYXBwZW5kKHNldC5zZXQsIHRlcm0pO1xuXG4gICAgbGV0IG5ld19tYXAgPSBPYmplY3QuYXNzaWduKHt9LCBzZXQpO1xuICAgIG5ld19tYXAuc2V0ID0gbmV3X2xpc3Q7XG4gICAgcmV0dXJuIFNwZWNpYWxGb3Jtcy5tYXAobmV3X21hcCk7XG4gIH1cblxuICByZXR1cm4gc2V0O1xufVxuXG5mdW5jdGlvbiBfZGlmZmVyZW5jZShzZXQxLCBzZXQyKSB7XG4gIGxldCBuZXdfbWFwID0gT2JqZWN0LmFzc2lnbih7fSwgc2V0MSk7XG5cbiAgZm9yIChsZXQgdmFsIG9mIHNldDEuc2V0KSB7XG4gICAgaWYgKF9tZW1iZXJfX3FtYXJrX18oc2V0MiwgdmFsKSkge1xuICAgICAgbmV3X21hcC5zZXQgPSBMaXN0LmRlbGV0ZShuZXdfbWFwLnNldCwgdmFsKTtcbiAgICB9XG4gIH1cblxuICByZXR1cm4gU3BlY2lhbEZvcm1zLm1hcChuZXdfbWFwKTtcbn1cblxuZnVuY3Rpb24gX2ludGVyc2VjdGlvbihzZXQxLCBzZXQyKSB7XG4gIGxldCBuZXdfbWFwID0gT2JqZWN0LmFzc2lnbih7fSwgc2V0MSk7XG5cbiAgZm9yIChsZXQgdmFsIG9mIHNldDEuc2V0KSB7XG4gICAgaWYgKCFfbWVtYmVyX19xbWFya19fKHNldDIsIHZhbCkpIHtcbiAgICAgIG5ld19tYXAuc2V0ID0gTGlzdC5kZWxldGUobmV3X21hcC5zZXQsIHZhbCk7XG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIFNwZWNpYWxGb3Jtcy5tYXAobmV3X21hcCk7XG59XG5cbmZ1bmN0aW9uIF91bmlvbihzZXQxLCBzZXQyKSB7XG4gIGxldCBuZXdfbWFwID0gc2V0MTtcblxuICBmb3IgKGxldCB2YWwgb2Ygc2V0Mi5zZXQpIHtcbiAgICBuZXdfbWFwID0gX3B1dChuZXdfbWFwLCB2YWwpO1xuICB9XG5cbiAgcmV0dXJuIFNwZWNpYWxGb3Jtcy5tYXAobmV3X21hcCk7XG59XG5cbmZ1bmN0aW9uIF9kaXNqb2luX19xbWFya19fKHNldDEsIHNldDIpIHtcbiAgZm9yIChsZXQgdmFsIG9mIHNldDEuc2V0KSB7XG4gICAgaWYgKF9tZW1iZXJfX3FtYXJrX18oc2V0MiwgdmFsKSkge1xuICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH1cbiAgfVxuXG4gIHJldHVybiB0cnVlO1xufVxuXG5mdW5jdGlvbiBfbWVtYmVyX19xbWFya19fKHNldCwgdmFsdWUpIHtcbiAgcmV0dXJuIHNldC5zZXQuaW5kZXhPZih2YWx1ZSkgPj0gMDtcbn1cblxuZnVuY3Rpb24gX2VxdWFsX19xbWFya19fKHNldDEsIHNldDIpIHtcbiAgcmV0dXJuIHNldDEuc2V0ID09PSBzZXQyLnNldDtcbn1cblxuZnVuY3Rpb24gX3N1YnNldF9fcW1hcmtfXyhzZXQxLCBzZXQyKSB7XG4gIGZvciAobGV0IHZhbCBvZiBzZXQxLnNldCkge1xuICAgIGlmICghX21lbWJlcl9fcW1hcmtfXyhzZXQyLCB2YWwpKSB7XG4gICAgICByZXR1cm4gZmFsc2U7XG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIHRydWU7XG59XG5cbnZhciBNYXBTZXQgPSB7XG4gIG5ldzogX19uZXdfXyxcbiAgc2l6ZTogX3NpemUsXG4gIHRvX2xpc3Q6IF90b19saXN0LFxuICBkaXNqb2luX19xbWFya19fOiBfZGlzam9pbl9fcW1hcmtfXyxcbiAgZGVsZXRlOiBfX19kZWxldGVfXyxcbiAgc3Vic2V0X19xbWFya19fOiBfc3Vic2V0X19xbWFya19fLFxuICBlcXVhbF9fcW1hcmtfXzogX2VxdWFsX19xbWFya19fLFxuICBtZW1iZXJfX3FtYXJrX186IF9tZW1iZXJfX3FtYXJrX18sXG4gIHB1dDogX3B1dCxcbiAgdW5pb246IF91bmlvbixcbiAgaW50ZXJzZWN0aW9uOiBfaW50ZXJzZWN0aW9uLFxuICBkaWZmZXJlbmNlOiBfZGlmZmVyZW5jZVxufTtcblxuZnVuY3Rpb24gc2l6ZShtYXApIHtcbiAgcmV0dXJuIE1hcFNldC5zaXplKG1hcCk7XG59XG5cbmZ1bmN0aW9uIHRvX2xpc3QobWFwKSB7XG4gIHJldHVybiBNYXBTZXQudG9fbGlzdChtYXApO1xufVxuXG5mdW5jdGlvbiBfX2RlbGV0ZV9fKHNldCwgdGVybSkge1xuICByZXR1cm4gTWFwU2V0LmRlbGV0ZShzZXQsIHRlcm0pO1xufVxuXG5mdW5jdGlvbiBwdXQoc2V0LCB0ZXJtKSB7XG4gIHJldHVybiBNYXBTZXQucHV0KHNldCwgdGVybSk7XG59XG5cbmZ1bmN0aW9uIGRpZmZlcmVuY2Uoc2V0MSwgc2V0Mikge1xuICByZXR1cm4gTWFwU2V0LmRpZmZlcmVuY2Uoc2V0MSwgc2V0Mik7XG59XG5cbmZ1bmN0aW9uIGludGVyc2VjdGlvbihzZXQxLCBzZXQyKSB7XG4gIHJldHVybiBNYXBTZXQuaW50ZXJzZWN0aW9uKHNldDEsIHNldDIpO1xufVxuXG5mdW5jdGlvbiB1bmlvbihzZXQxLCBzZXQyKSB7XG4gIHJldHVybiBNYXBTZXQudW5pb24oc2V0MSwgc2V0Mik7XG59XG5cbmZ1bmN0aW9uIGRpc2pvaW5fX3FtYXJrX18oc2V0MSwgc2V0Mikge1xuICByZXR1cm4gTWFwU2V0LmRpc2pvaW5fX3FtYXJrX18oc2V0MSwgc2V0Mik7XG59XG5cbmZ1bmN0aW9uIG1lbWJlcl9fcW1hcmtfXyhzZXQsIHZhbHVlKSB7XG4gIHJldHVybiBNYXBTZXQubWVtYmVyX19xbWFya19fKHNldDEsIHNldDIpO1xufVxuXG5mdW5jdGlvbiBlcXVhbF9fcW1hcmtfXyhzZXQxLCBzZXQyKSB7XG4gIHJldHVybiBNYXBTZXQuZXF1YWxfX3FtYXJrX18oc2V0MSwgc2V0Mik7XG59XG5cbmZ1bmN0aW9uIHN1YnNldF9fcW1hcmtfXyhzZXQxLCBzZXQyKSB7XG4gIHJldHVybiBNYXBTZXQuc3Vic2V0X19xbWFya19fKHNldDEsIHNldDIpO1xufVxuXG52YXIgX1NldCA9IHtcbiAgc2l6ZSxcbiAgdG9fbGlzdCxcbiAgZGlzam9pbl9fcW1hcmtfXyxcbiAgZGVsZXRlOiBfX2RlbGV0ZV9fLFxuICBzdWJzZXRfX3FtYXJrX18sXG4gIGVxdWFsX19xbWFya19fLFxuICBtZW1iZXJfX3FtYXJrX18sXG4gIHB1dCxcbiAgdW5pb24sXG4gIGludGVyc2VjdGlvbixcbiAgZGlmZmVyZW5jZVxufTtcblxubGV0IHZpcnR1YWxEb20gPSAoZnVuY3Rpb24gKGUpIHtcbiAgICByZXR1cm4gZSgpO1xufSkoZnVuY3Rpb24gKCkge1xuICAgIHZhciBkZWZpbmUsIG1vZHVsZSwgZXhwb3J0cztcbiAgICByZXR1cm4gKGZ1bmN0aW9uIGUodCwgbiwgcikge1xuICAgICAgICBmdW5jdGlvbiBzKG8sIHUpIHtcbiAgICAgICAgICAgIGlmICghbltvXSkge1xuICAgICAgICAgICAgICAgIGlmICghdFtvXSkge1xuICAgICAgICAgICAgICAgICAgICB2YXIgYSA9IHR5cGVvZiByZXF1aXJlID09IFwiZnVuY3Rpb25cIiAmJiByZXF1aXJlO1xuICAgICAgICAgICAgICAgICAgICBpZiAoIXUgJiYgYSkgcmV0dXJuIGEobywgITApO1xuICAgICAgICAgICAgICAgICAgICBpZiAoaSkgcmV0dXJuIGkobywgITApO1xuICAgICAgICAgICAgICAgICAgICB2YXIgZiA9IG5ldyBFcnJvcihcIkNhbm5vdCBmaW5kIG1vZHVsZSAnXCIgKyBvICsgXCInXCIpO1xuICAgICAgICAgICAgICAgICAgICB0aHJvdyAoZi5jb2RlID0gXCJNT0RVTEVfTk9UX0ZPVU5EXCIsIGYpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB2YXIgbCA9IG5bb10gPSB7XG4gICAgICAgICAgICAgICAgICAgIGV4cG9ydHM6IHt9XG4gICAgICAgICAgICAgICAgfTtcbiAgICAgICAgICAgICAgICB0W29dWzBdLmNhbGwobC5leHBvcnRzLCBmdW5jdGlvbiAoZSkge1xuICAgICAgICAgICAgICAgICAgICB2YXIgbiA9IHRbb11bMV1bZV07XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBzKG4gPyBuIDogZSk7XG4gICAgICAgICAgICAgICAgfSwgbCwgbC5leHBvcnRzLCBlLCB0LCBuLCByKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJldHVybiBuW29dLmV4cG9ydHM7XG4gICAgICAgIH1cbiAgICAgICAgdmFyIGkgPSB0eXBlb2YgcmVxdWlyZSA9PSBcImZ1bmN0aW9uXCIgJiYgcmVxdWlyZTtcbiAgICAgICAgZm9yICh2YXIgbyA9IDA7IG8gPCByLmxlbmd0aDsgbysrKSBzKHJbb10pO1xuICAgICAgICByZXR1cm4gcztcbiAgICB9KSh7XG4gICAgICAgIDE6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG5cbiAgICAgICAgICAgIHZhciBjcmVhdGVFbGVtZW50ID0gcmVxdWlyZShcIi4vdmRvbS9jcmVhdGUtZWxlbWVudC5qc1wiKTtcblxuICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBjcmVhdGVFbGVtZW50O1xuICAgICAgICB9LCB7IFwiLi92ZG9tL2NyZWF0ZS1lbGVtZW50LmpzXCI6IDE1IH1dLCAyOiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge1xuICAgICAgICAgICAgdmFyIGRpZmYgPSByZXF1aXJlKFwiLi92dHJlZS9kaWZmLmpzXCIpO1xuXG4gICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IGRpZmY7XG4gICAgICAgIH0sIHsgXCIuL3Z0cmVlL2RpZmYuanNcIjogMzUgfV0sIDM6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICB2YXIgaCA9IHJlcXVpcmUoXCIuL3ZpcnR1YWwtaHlwZXJzY3JpcHQvaW5kZXguanNcIik7XG5cbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gaDtcbiAgICAgICAgfSwgeyBcIi4vdmlydHVhbC1oeXBlcnNjcmlwdC9pbmRleC5qc1wiOiAyMiB9XSwgNDogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHtcbiAgICAgICAgICAgIHZhciBkaWZmID0gcmVxdWlyZShcIi4vZGlmZi5qc1wiKTtcbiAgICAgICAgICAgIHZhciBwYXRjaCA9IHJlcXVpcmUoXCIuL3BhdGNoLmpzXCIpO1xuICAgICAgICAgICAgdmFyIGggPSByZXF1aXJlKFwiLi9oLmpzXCIpO1xuICAgICAgICAgICAgdmFyIGNyZWF0ZSA9IHJlcXVpcmUoXCIuL2NyZWF0ZS1lbGVtZW50LmpzXCIpO1xuICAgICAgICAgICAgdmFyIFZOb2RlID0gcmVxdWlyZShcIi4vdm5vZGUvdm5vZGUuanNcIik7XG4gICAgICAgICAgICB2YXIgVlRleHQgPSByZXF1aXJlKFwiLi92bm9kZS92dGV4dC5qc1wiKTtcblxuICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSB7XG4gICAgICAgICAgICAgICAgZGlmZjogZGlmZixcbiAgICAgICAgICAgICAgICBwYXRjaDogcGF0Y2gsXG4gICAgICAgICAgICAgICAgaDogaCxcbiAgICAgICAgICAgICAgICBjcmVhdGU6IGNyZWF0ZSxcbiAgICAgICAgICAgICAgICBWTm9kZTogVk5vZGUsXG4gICAgICAgICAgICAgICAgVlRleHQ6IFZUZXh0XG4gICAgICAgICAgICB9O1xuICAgICAgICB9LCB7IFwiLi9jcmVhdGUtZWxlbWVudC5qc1wiOiAxLCBcIi4vZGlmZi5qc1wiOiAyLCBcIi4vaC5qc1wiOiAzLCBcIi4vcGF0Y2guanNcIjogMTMsIFwiLi92bm9kZS92bm9kZS5qc1wiOiAzMSwgXCIuL3Zub2RlL3Z0ZXh0LmpzXCI6IDMzIH1dLCA1OiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge1xuICAgICAgICAgICAgLyohXG4gICAgICAgICAgICAgKiBDcm9zcy1Ccm93c2VyIFNwbGl0IDEuMS4xXG4gICAgICAgICAgICAgKiBDb3B5cmlnaHQgMjAwNy0yMDEyIFN0ZXZlbiBMZXZpdGhhbiA8c3RldmVubGV2aXRoYW4uY29tPlxuICAgICAgICAgICAgICogQXZhaWxhYmxlIHVuZGVyIHRoZSBNSVQgTGljZW5zZVxuICAgICAgICAgICAgICogRUNNQVNjcmlwdCBjb21wbGlhbnQsIHVuaWZvcm0gY3Jvc3MtYnJvd3NlciBzcGxpdCBtZXRob2RcbiAgICAgICAgICAgICAqL1xuXG4gICAgICAgICAgICAvKipcbiAgICAgICAgICAgICAqIFNwbGl0cyBhIHN0cmluZyBpbnRvIGFuIGFycmF5IG9mIHN0cmluZ3MgdXNpbmcgYSByZWdleCBvciBzdHJpbmcgc2VwYXJhdG9yLiBNYXRjaGVzIG9mIHRoZVxuICAgICAgICAgICAgICogc2VwYXJhdG9yIGFyZSBub3QgaW5jbHVkZWQgaW4gdGhlIHJlc3VsdCBhcnJheS4gSG93ZXZlciwgaWYgYHNlcGFyYXRvcmAgaXMgYSByZWdleCB0aGF0IGNvbnRhaW5zXG4gICAgICAgICAgICAgKiBjYXB0dXJpbmcgZ3JvdXBzLCBiYWNrcmVmZXJlbmNlcyBhcmUgc3BsaWNlZCBpbnRvIHRoZSByZXN1bHQgZWFjaCB0aW1lIGBzZXBhcmF0b3JgIGlzIG1hdGNoZWQuXG4gICAgICAgICAgICAgKiBGaXhlcyBicm93c2VyIGJ1Z3MgY29tcGFyZWQgdG8gdGhlIG5hdGl2ZSBgU3RyaW5nLnByb3RvdHlwZS5zcGxpdGAgYW5kIGNhbiBiZSB1c2VkIHJlbGlhYmx5XG4gICAgICAgICAgICAgKiBjcm9zcy1icm93c2VyLlxuICAgICAgICAgICAgICogQHBhcmFtIHtTdHJpbmd9IHN0ciBTdHJpbmcgdG8gc3BsaXQuXG4gICAgICAgICAgICAgKiBAcGFyYW0ge1JlZ0V4cHxTdHJpbmd9IHNlcGFyYXRvciBSZWdleCBvciBzdHJpbmcgdG8gdXNlIGZvciBzZXBhcmF0aW5nIHRoZSBzdHJpbmcuXG4gICAgICAgICAgICAgKiBAcGFyYW0ge051bWJlcn0gW2xpbWl0XSBNYXhpbXVtIG51bWJlciBvZiBpdGVtcyB0byBpbmNsdWRlIGluIHRoZSByZXN1bHQgYXJyYXkuXG4gICAgICAgICAgICAgKiBAcmV0dXJucyB7QXJyYXl9IEFycmF5IG9mIHN1YnN0cmluZ3MuXG4gICAgICAgICAgICAgKiBAZXhhbXBsZVxuICAgICAgICAgICAgICpcbiAgICAgICAgICAgICAqIC8vIEJhc2ljIHVzZVxuICAgICAgICAgICAgICogc3BsaXQoJ2EgYiBjIGQnLCAnICcpO1xuICAgICAgICAgICAgICogLy8gLT4gWydhJywgJ2InLCAnYycsICdkJ11cbiAgICAgICAgICAgICAqXG4gICAgICAgICAgICAgKiAvLyBXaXRoIGxpbWl0XG4gICAgICAgICAgICAgKiBzcGxpdCgnYSBiIGMgZCcsICcgJywgMik7XG4gICAgICAgICAgICAgKiAvLyAtPiBbJ2EnLCAnYiddXG4gICAgICAgICAgICAgKlxuICAgICAgICAgICAgICogLy8gQmFja3JlZmVyZW5jZXMgaW4gcmVzdWx0IGFycmF5XG4gICAgICAgICAgICAgKiBzcGxpdCgnLi53b3JkMSB3b3JkMi4uJywgLyhbYS16XSspKFxcZCspL2kpO1xuICAgICAgICAgICAgICogLy8gLT4gWycuLicsICd3b3JkJywgJzEnLCAnICcsICd3b3JkJywgJzInLCAnLi4nXVxuICAgICAgICAgICAgICovXG4gICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IChmdW5jdGlvbiBzcGxpdCh1bmRlZikge1xuXG4gICAgICAgICAgICAgICAgdmFyIG5hdGl2ZVNwbGl0ID0gU3RyaW5nLnByb3RvdHlwZS5zcGxpdCxcbiAgICAgICAgICAgICAgICAgICAgY29tcGxpYW50RXhlY05wY2cgPSAvKCk/Py8uZXhlYyhcIlwiKVsxXSA9PT0gdW5kZWYsXG5cbiAgICAgICAgICAgICAgICAvLyBOUENHOiBub25wYXJ0aWNpcGF0aW5nIGNhcHR1cmluZyBncm91cFxuICAgICAgICAgICAgICAgIHNlbGY7XG5cbiAgICAgICAgICAgICAgICBzZWxmID0gZnVuY3Rpb24gKHN0ciwgc2VwYXJhdG9yLCBsaW1pdCkge1xuICAgICAgICAgICAgICAgICAgICAvLyBJZiBgc2VwYXJhdG9yYCBpcyBub3QgYSByZWdleCwgdXNlIGBuYXRpdmVTcGxpdGBcbiAgICAgICAgICAgICAgICAgICAgaWYgKE9iamVjdC5wcm90b3R5cGUudG9TdHJpbmcuY2FsbChzZXBhcmF0b3IpICE9PSBcIltvYmplY3QgUmVnRXhwXVwiKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gbmF0aXZlU3BsaXQuY2FsbChzdHIsIHNlcGFyYXRvciwgbGltaXQpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIHZhciBvdXRwdXQgPSBbXSxcbiAgICAgICAgICAgICAgICAgICAgICAgIGZsYWdzID0gKHNlcGFyYXRvci5pZ25vcmVDYXNlID8gXCJpXCIgOiBcIlwiKSArIChzZXBhcmF0b3IubXVsdGlsaW5lID8gXCJtXCIgOiBcIlwiKSArIChzZXBhcmF0b3IuZXh0ZW5kZWQgPyBcInhcIiA6IFwiXCIpICsgKHNlcGFyYXRvci5zdGlja3kgPyBcInlcIiA6IFwiXCIpLFxuXG4gICAgICAgICAgICAgICAgICAgIC8vIEZpcmVmb3ggMytcbiAgICAgICAgICAgICAgICAgICAgbGFzdExhc3RJbmRleCA9IDAsXG5cbiAgICAgICAgICAgICAgICAgICAgLy8gTWFrZSBgZ2xvYmFsYCBhbmQgYXZvaWQgYGxhc3RJbmRleGAgaXNzdWVzIGJ5IHdvcmtpbmcgd2l0aCBhIGNvcHlcbiAgICAgICAgICAgICAgICAgICAgc2VwYXJhdG9yID0gbmV3IFJlZ0V4cChzZXBhcmF0b3Iuc291cmNlLCBmbGFncyArIFwiZ1wiKSxcbiAgICAgICAgICAgICAgICAgICAgICAgIHNlcGFyYXRvcjIsXG4gICAgICAgICAgICAgICAgICAgICAgICBtYXRjaCxcbiAgICAgICAgICAgICAgICAgICAgICAgIGxhc3RJbmRleCxcbiAgICAgICAgICAgICAgICAgICAgICAgIGxhc3RMZW5ndGg7XG4gICAgICAgICAgICAgICAgICAgIHN0ciArPSBcIlwiOyAvLyBUeXBlLWNvbnZlcnRcbiAgICAgICAgICAgICAgICAgICAgaWYgKCFjb21wbGlhbnRFeGVjTnBjZykge1xuICAgICAgICAgICAgICAgICAgICAgICAgLy8gRG9lc24ndCBuZWVkIGZsYWdzIGd5LCBidXQgdGhleSBkb24ndCBodXJ0XG4gICAgICAgICAgICAgICAgICAgICAgICBzZXBhcmF0b3IyID0gbmV3IFJlZ0V4cChcIl5cIiArIHNlcGFyYXRvci5zb3VyY2UgKyBcIiQoPyFcXFxccylcIiwgZmxhZ3MpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIC8qIFZhbHVlcyBmb3IgYGxpbWl0YCwgcGVyIHRoZSBzcGVjOlxuICAgICAgICAgICAgICAgICAgICAgKiBJZiB1bmRlZmluZWQ6IDQyOTQ5NjcyOTUgLy8gTWF0aC5wb3coMiwgMzIpIC0gMVxuICAgICAgICAgICAgICAgICAgICAgKiBJZiAwLCBJbmZpbml0eSwgb3IgTmFOOiAwXG4gICAgICAgICAgICAgICAgICAgICAqIElmIHBvc2l0aXZlIG51bWJlcjogbGltaXQgPSBNYXRoLmZsb29yKGxpbWl0KTsgaWYgKGxpbWl0ID4gNDI5NDk2NzI5NSkgbGltaXQgLT0gNDI5NDk2NzI5NjtcbiAgICAgICAgICAgICAgICAgICAgICogSWYgbmVnYXRpdmUgbnVtYmVyOiA0Mjk0OTY3Mjk2IC0gTWF0aC5mbG9vcihNYXRoLmFicyhsaW1pdCkpXG4gICAgICAgICAgICAgICAgICAgICAqIElmIG90aGVyOiBUeXBlLWNvbnZlcnQsIHRoZW4gdXNlIHRoZSBhYm92ZSBydWxlc1xuICAgICAgICAgICAgICAgICAgICAgKi9cbiAgICAgICAgICAgICAgICAgICAgbGltaXQgPSBsaW1pdCA9PT0gdW5kZWYgPyAtMSA+Pj4gMCA6IC8vIE1hdGgucG93KDIsIDMyKSAtIDFcbiAgICAgICAgICAgICAgICAgICAgbGltaXQgPj4+IDA7IC8vIFRvVWludDMyKGxpbWl0KVxuICAgICAgICAgICAgICAgICAgICB3aGlsZSAobWF0Y2ggPSBzZXBhcmF0b3IuZXhlYyhzdHIpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAvLyBgc2VwYXJhdG9yLmxhc3RJbmRleGAgaXMgbm90IHJlbGlhYmxlIGNyb3NzLWJyb3dzZXJcbiAgICAgICAgICAgICAgICAgICAgICAgIGxhc3RJbmRleCA9IG1hdGNoLmluZGV4ICsgbWF0Y2hbMF0ubGVuZ3RoO1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGxhc3RJbmRleCA+IGxhc3RMYXN0SW5kZXgpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBvdXRwdXQucHVzaChzdHIuc2xpY2UobGFzdExhc3RJbmRleCwgbWF0Y2guaW5kZXgpKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBGaXggYnJvd3NlcnMgd2hvc2UgYGV4ZWNgIG1ldGhvZHMgZG9uJ3QgY29uc2lzdGVudGx5IHJldHVybiBgdW5kZWZpbmVkYCBmb3JcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBub25wYXJ0aWNpcGF0aW5nIGNhcHR1cmluZyBncm91cHNcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoIWNvbXBsaWFudEV4ZWNOcGNnICYmIG1hdGNoLmxlbmd0aCA+IDEpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbWF0Y2hbMF0ucmVwbGFjZShzZXBhcmF0b3IyLCBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBmb3IgKHZhciBpID0gMTsgaSA8IGFyZ3VtZW50cy5sZW5ndGggLSAyOyBpKyspIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoYXJndW1lbnRzW2ldID09PSB1bmRlZikge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBtYXRjaFtpXSA9IHVuZGVmO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChtYXRjaC5sZW5ndGggPiAxICYmIG1hdGNoLmluZGV4IDwgc3RyLmxlbmd0aCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBBcnJheS5wcm90b3R5cGUucHVzaC5hcHBseShvdXRwdXQsIG1hdGNoLnNsaWNlKDEpKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgbGFzdExlbmd0aCA9IG1hdGNoWzBdLmxlbmd0aDtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBsYXN0TGFzdEluZGV4ID0gbGFzdEluZGV4O1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChvdXRwdXQubGVuZ3RoID49IGxpbWl0KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChzZXBhcmF0b3IubGFzdEluZGV4ID09PSBtYXRjaC5pbmRleCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNlcGFyYXRvci5sYXN0SW5kZXgrKzsgLy8gQXZvaWQgYW4gaW5maW5pdGUgbG9vcFxuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIGlmIChsYXN0TGFzdEluZGV4ID09PSBzdHIubGVuZ3RoKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAobGFzdExlbmd0aCB8fCAhc2VwYXJhdG9yLnRlc3QoXCJcIikpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBvdXRwdXQucHVzaChcIlwiKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIG91dHB1dC5wdXNoKHN0ci5zbGljZShsYXN0TGFzdEluZGV4KSk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIG91dHB1dC5sZW5ndGggPiBsaW1pdCA/IG91dHB1dC5zbGljZSgwLCBsaW1pdCkgOiBvdXRwdXQ7XG4gICAgICAgICAgICAgICAgfTtcblxuICAgICAgICAgICAgICAgIHJldHVybiBzZWxmO1xuICAgICAgICAgICAgfSkoKTtcbiAgICAgICAgfSwge31dLCA2OiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge30sIHt9XSwgNzogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHtcbiAgICAgICAgICAgIFwidXNlIHN0cmljdFwiO1xuXG4gICAgICAgICAgICB2YXIgT25lVmVyc2lvbkNvbnN0cmFpbnQgPSByZXF1aXJlKFwiaW5kaXZpZHVhbC9vbmUtdmVyc2lvblwiKTtcblxuICAgICAgICAgICAgdmFyIE1ZX1ZFUlNJT04gPSBcIjdcIjtcbiAgICAgICAgICAgIE9uZVZlcnNpb25Db25zdHJhaW50KFwiZXYtc3RvcmVcIiwgTVlfVkVSU0lPTik7XG5cbiAgICAgICAgICAgIHZhciBoYXNoS2V5ID0gXCJfX0VWX1NUT1JFX0tFWUBcIiArIE1ZX1ZFUlNJT047XG5cbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gRXZTdG9yZTtcblxuICAgICAgICAgICAgZnVuY3Rpb24gRXZTdG9yZShlbGVtKSB7XG4gICAgICAgICAgICAgICAgdmFyIGhhc2ggPSBlbGVtW2hhc2hLZXldO1xuXG4gICAgICAgICAgICAgICAgaWYgKCFoYXNoKSB7XG4gICAgICAgICAgICAgICAgICAgIGhhc2ggPSBlbGVtW2hhc2hLZXldID0ge307XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgcmV0dXJuIGhhc2g7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0sIHsgXCJpbmRpdmlkdWFsL29uZS12ZXJzaW9uXCI6IDkgfV0sIDg6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICAoZnVuY3Rpb24gKGdsb2JhbCkge1xuICAgICAgICAgICAgICAgIFwidXNlIHN0cmljdFwiO1xuXG4gICAgICAgICAgICAgICAgLypnbG9iYWwgd2luZG93LCBnbG9iYWwqL1xuXG4gICAgICAgICAgICAgICAgdmFyIHJvb3QgPSB0eXBlb2Ygd2luZG93ICE9PSBcInVuZGVmaW5lZFwiID8gd2luZG93IDogdHlwZW9mIGdsb2JhbCAhPT0gXCJ1bmRlZmluZWRcIiA/IGdsb2JhbCA6IHt9O1xuXG4gICAgICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBJbmRpdmlkdWFsO1xuXG4gICAgICAgICAgICAgICAgZnVuY3Rpb24gSW5kaXZpZHVhbChrZXksIHZhbHVlKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmIChrZXkgaW4gcm9vdCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHJvb3Rba2V5XTtcbiAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgIHJvb3Rba2V5XSA9IHZhbHVlO1xuXG4gICAgICAgICAgICAgICAgICAgIHJldHVybiB2YWx1ZTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9KS5jYWxsKHRoaXMsIHR5cGVvZiBnbG9iYWwgIT09IFwidW5kZWZpbmVkXCIgPyBnbG9iYWwgOiB0eXBlb2Ygc2VsZiAhPT0gXCJ1bmRlZmluZWRcIiA/IHNlbGYgOiB0eXBlb2Ygd2luZG93ICE9PSBcInVuZGVmaW5lZFwiID8gd2luZG93IDoge30pO1xuICAgICAgICB9LCB7fV0sIDk6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICBcInVzZSBzdHJpY3RcIjtcblxuICAgICAgICAgICAgdmFyIEluZGl2aWR1YWwgPSByZXF1aXJlKFwiLi9pbmRleC5qc1wiKTtcblxuICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBPbmVWZXJzaW9uO1xuXG4gICAgICAgICAgICBmdW5jdGlvbiBPbmVWZXJzaW9uKG1vZHVsZU5hbWUsIHZlcnNpb24sIGRlZmF1bHRWYWx1ZSkge1xuICAgICAgICAgICAgICAgIHZhciBrZXkgPSBcIl9fSU5ESVZJRFVBTF9PTkVfVkVSU0lPTl9cIiArIG1vZHVsZU5hbWU7XG4gICAgICAgICAgICAgICAgdmFyIGVuZm9yY2VLZXkgPSBrZXkgKyBcIl9FTkZPUkNFX1NJTkdMRVRPTlwiO1xuXG4gICAgICAgICAgICAgICAgdmFyIHZlcnNpb25WYWx1ZSA9IEluZGl2aWR1YWwoZW5mb3JjZUtleSwgdmVyc2lvbik7XG5cbiAgICAgICAgICAgICAgICBpZiAodmVyc2lvblZhbHVlICE9PSB2ZXJzaW9uKSB7XG4gICAgICAgICAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcihcIkNhbiBvbmx5IGhhdmUgb25lIGNvcHkgb2YgXCIgKyBtb2R1bGVOYW1lICsgXCIuXFxuXCIgKyBcIllvdSBhbHJlYWR5IGhhdmUgdmVyc2lvbiBcIiArIHZlcnNpb25WYWx1ZSArIFwiIGluc3RhbGxlZC5cXG5cIiArIFwiVGhpcyBtZWFucyB5b3UgY2Fubm90IGluc3RhbGwgdmVyc2lvbiBcIiArIHZlcnNpb24pO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHJldHVybiBJbmRpdmlkdWFsKGtleSwgZGVmYXVsdFZhbHVlKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSwgeyBcIi4vaW5kZXguanNcIjogOCB9XSwgMTA6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICAoZnVuY3Rpb24gKGdsb2JhbCkge1xuICAgICAgICAgICAgICAgIHZhciB0b3BMZXZlbCA9IHR5cGVvZiBnbG9iYWwgIT09IFwidW5kZWZpbmVkXCIgPyBnbG9iYWwgOiB0eXBlb2Ygd2luZG93ICE9PSBcInVuZGVmaW5lZFwiID8gd2luZG93IDoge307XG4gICAgICAgICAgICAgICAgdmFyIG1pbkRvYyA9IHJlcXVpcmUoXCJtaW4tZG9jdW1lbnRcIik7XG5cbiAgICAgICAgICAgICAgICBpZiAodHlwZW9mIGRvY3VtZW50ICE9PSBcInVuZGVmaW5lZFwiKSB7XG4gICAgICAgICAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gZG9jdW1lbnQ7XG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgdmFyIGRvY2N5ID0gdG9wTGV2ZWxbXCJfX0dMT0JBTF9ET0NVTUVOVF9DQUNIRUA0XCJdO1xuXG4gICAgICAgICAgICAgICAgICAgIGlmICghZG9jY3kpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGRvY2N5ID0gdG9wTGV2ZWxbXCJfX0dMT0JBTF9ET0NVTUVOVF9DQUNIRUA0XCJdID0gbWluRG9jO1xuICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBkb2NjeTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9KS5jYWxsKHRoaXMsIHR5cGVvZiBnbG9iYWwgIT09IFwidW5kZWZpbmVkXCIgPyBnbG9iYWwgOiB0eXBlb2Ygc2VsZiAhPT0gXCJ1bmRlZmluZWRcIiA/IHNlbGYgOiB0eXBlb2Ygd2luZG93ICE9PSBcInVuZGVmaW5lZFwiID8gd2luZG93IDoge30pO1xuICAgICAgICB9LCB7IFwibWluLWRvY3VtZW50XCI6IDYgfV0sIDExOiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge1xuICAgICAgICAgICAgXCJ1c2Ugc3RyaWN0XCI7XG5cbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gaXNPYmplY3QoeCkge1xuICAgICAgICAgICAgICAgIHJldHVybiB0eXBlb2YgeCA9PT0gXCJvYmplY3RcIiAmJiB4ICE9PSBudWxsO1xuICAgICAgICAgICAgfTtcbiAgICAgICAgfSwge31dLCAxMjogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHtcbiAgICAgICAgICAgIHZhciBuYXRpdmVJc0FycmF5ID0gQXJyYXkuaXNBcnJheTtcbiAgICAgICAgICAgIHZhciB0b1N0cmluZyA9IE9iamVjdC5wcm90b3R5cGUudG9TdHJpbmc7XG5cbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gbmF0aXZlSXNBcnJheSB8fCBpc0FycmF5O1xuXG4gICAgICAgICAgICBmdW5jdGlvbiBpc0FycmF5KG9iaikge1xuICAgICAgICAgICAgICAgIHJldHVybiB0b1N0cmluZy5jYWxsKG9iaikgPT09IFwiW29iamVjdCBBcnJheV1cIjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSwge31dLCAxMzogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHtcbiAgICAgICAgICAgIHZhciBwYXRjaCA9IHJlcXVpcmUoXCIuL3Zkb20vcGF0Y2guanNcIik7XG5cbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gcGF0Y2g7XG4gICAgICAgIH0sIHsgXCIuL3Zkb20vcGF0Y2guanNcIjogMTggfV0sIDE0OiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge1xuICAgICAgICAgICAgdmFyIGlzT2JqZWN0ID0gcmVxdWlyZShcImlzLW9iamVjdFwiKTtcbiAgICAgICAgICAgIHZhciBpc0hvb2sgPSByZXF1aXJlKFwiLi4vdm5vZGUvaXMtdmhvb2suanNcIik7XG5cbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gYXBwbHlQcm9wZXJ0aWVzO1xuXG4gICAgICAgICAgICBmdW5jdGlvbiBhcHBseVByb3BlcnRpZXMobm9kZSwgcHJvcHMsIHByZXZpb3VzKSB7XG4gICAgICAgICAgICAgICAgZm9yICh2YXIgcHJvcE5hbWUgaW4gcHJvcHMpIHtcbiAgICAgICAgICAgICAgICAgICAgdmFyIHByb3BWYWx1ZSA9IHByb3BzW3Byb3BOYW1lXTtcblxuICAgICAgICAgICAgICAgICAgICBpZiAocHJvcFZhbHVlID09PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJlbW92ZVByb3BlcnR5KG5vZGUsIHByb3BOYW1lLCBwcm9wVmFsdWUsIHByZXZpb3VzKTtcbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIGlmIChpc0hvb2socHJvcFZhbHVlKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgcmVtb3ZlUHJvcGVydHkobm9kZSwgcHJvcE5hbWUsIHByb3BWYWx1ZSwgcHJldmlvdXMpO1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHByb3BWYWx1ZS5ob29rKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcHJvcFZhbHVlLmhvb2sobm9kZSwgcHJvcE5hbWUsIHByZXZpb3VzID8gcHJldmlvdXNbcHJvcE5hbWVdIDogdW5kZWZpbmVkKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChpc09iamVjdChwcm9wVmFsdWUpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcGF0Y2hPYmplY3Qobm9kZSwgcHJvcHMsIHByZXZpb3VzLCBwcm9wTmFtZSwgcHJvcFZhbHVlKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgbm9kZVtwcm9wTmFtZV0gPSBwcm9wVmFsdWU7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIHJlbW92ZVByb3BlcnR5KG5vZGUsIHByb3BOYW1lLCBwcm9wVmFsdWUsIHByZXZpb3VzKSB7XG4gICAgICAgICAgICAgICAgaWYgKHByZXZpb3VzKSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciBwcmV2aW91c1ZhbHVlID0gcHJldmlvdXNbcHJvcE5hbWVdO1xuXG4gICAgICAgICAgICAgICAgICAgIGlmICghaXNIb29rKHByZXZpb3VzVmFsdWUpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAocHJvcE5hbWUgPT09IFwiYXR0cmlidXRlc1wiKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgZm9yICh2YXIgYXR0ck5hbWUgaW4gcHJldmlvdXNWYWx1ZSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBub2RlLnJlbW92ZUF0dHJpYnV0ZShhdHRyTmFtZSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIGlmIChwcm9wTmFtZSA9PT0gXCJzdHlsZVwiKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgZm9yICh2YXIgaSBpbiBwcmV2aW91c1ZhbHVlKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG5vZGUuc3R5bGVbaV0gPSBcIlwiO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAodHlwZW9mIHByZXZpb3VzVmFsdWUgPT09IFwic3RyaW5nXCIpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBub2RlW3Byb3BOYW1lXSA9IFwiXCI7XG4gICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIG5vZGVbcHJvcE5hbWVdID0gbnVsbDtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIGlmIChwcmV2aW91c1ZhbHVlLnVuaG9vaykge1xuICAgICAgICAgICAgICAgICAgICAgICAgcHJldmlvdXNWYWx1ZS51bmhvb2sobm9kZSwgcHJvcE5hbWUsIHByb3BWYWx1ZSk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIHBhdGNoT2JqZWN0KG5vZGUsIHByb3BzLCBwcmV2aW91cywgcHJvcE5hbWUsIHByb3BWYWx1ZSkge1xuICAgICAgICAgICAgICAgIHZhciBwcmV2aW91c1ZhbHVlID0gcHJldmlvdXMgPyBwcmV2aW91c1twcm9wTmFtZV0gOiB1bmRlZmluZWQ7XG5cbiAgICAgICAgICAgICAgICAvLyBTZXQgYXR0cmlidXRlc1xuICAgICAgICAgICAgICAgIGlmIChwcm9wTmFtZSA9PT0gXCJhdHRyaWJ1dGVzXCIpIHtcbiAgICAgICAgICAgICAgICAgICAgZm9yICh2YXIgYXR0ck5hbWUgaW4gcHJvcFZhbHVlKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICB2YXIgYXR0clZhbHVlID0gcHJvcFZhbHVlW2F0dHJOYW1lXTtcblxuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGF0dHJWYWx1ZSA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgbm9kZS5yZW1vdmVBdHRyaWJ1dGUoYXR0ck5hbWUpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBub2RlLnNldEF0dHJpYnV0ZShhdHRyTmFtZSwgYXR0clZhbHVlKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICBpZiAocHJldmlvdXNWYWx1ZSAmJiBpc09iamVjdChwcmV2aW91c1ZhbHVlKSAmJiBnZXRQcm90b3R5cGUocHJldmlvdXNWYWx1ZSkgIT09IGdldFByb3RvdHlwZShwcm9wVmFsdWUpKSB7XG4gICAgICAgICAgICAgICAgICAgIG5vZGVbcHJvcE5hbWVdID0gcHJvcFZhbHVlO1xuICAgICAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgaWYgKCFpc09iamVjdChub2RlW3Byb3BOYW1lXSkpIHtcbiAgICAgICAgICAgICAgICAgICAgbm9kZVtwcm9wTmFtZV0gPSB7fTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICB2YXIgcmVwbGFjZXIgPSBwcm9wTmFtZSA9PT0gXCJzdHlsZVwiID8gXCJcIiA6IHVuZGVmaW5lZDtcblxuICAgICAgICAgICAgICAgIGZvciAodmFyIGsgaW4gcHJvcFZhbHVlKSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciB2YWx1ZSA9IHByb3BWYWx1ZVtrXTtcbiAgICAgICAgICAgICAgICAgICAgbm9kZVtwcm9wTmFtZV1ba10gPSB2YWx1ZSA9PT0gdW5kZWZpbmVkID8gcmVwbGFjZXIgOiB2YWx1ZTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIGdldFByb3RvdHlwZSh2YWx1ZSkge1xuICAgICAgICAgICAgICAgIGlmIChPYmplY3QuZ2V0UHJvdG90eXBlT2YpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIE9iamVjdC5nZXRQcm90b3R5cGVPZih2YWx1ZSk7XG4gICAgICAgICAgICAgICAgfSBlbHNlIGlmICh2YWx1ZS5fX3Byb3RvX18pIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHZhbHVlLl9fcHJvdG9fXztcbiAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKHZhbHVlLmNvbnN0cnVjdG9yKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiB2YWx1ZS5jb25zdHJ1Y3Rvci5wcm90b3R5cGU7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9LCB7IFwiLi4vdm5vZGUvaXMtdmhvb2suanNcIjogMjYsIFwiaXMtb2JqZWN0XCI6IDExIH1dLCAxNTogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHtcbiAgICAgICAgICAgIHZhciBkb2N1bWVudCA9IHJlcXVpcmUoXCJnbG9iYWwvZG9jdW1lbnRcIik7XG5cbiAgICAgICAgICAgIHZhciBhcHBseVByb3BlcnRpZXMgPSByZXF1aXJlKFwiLi9hcHBseS1wcm9wZXJ0aWVzXCIpO1xuXG4gICAgICAgICAgICB2YXIgaXNWTm9kZSA9IHJlcXVpcmUoXCIuLi92bm9kZS9pcy12bm9kZS5qc1wiKTtcbiAgICAgICAgICAgIHZhciBpc1ZUZXh0ID0gcmVxdWlyZShcIi4uL3Zub2RlL2lzLXZ0ZXh0LmpzXCIpO1xuICAgICAgICAgICAgdmFyIGlzV2lkZ2V0ID0gcmVxdWlyZShcIi4uL3Zub2RlL2lzLXdpZGdldC5qc1wiKTtcbiAgICAgICAgICAgIHZhciBoYW5kbGVUaHVuayA9IHJlcXVpcmUoXCIuLi92bm9kZS9oYW5kbGUtdGh1bmsuanNcIik7XG5cbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gY3JlYXRlRWxlbWVudDtcblxuICAgICAgICAgICAgZnVuY3Rpb24gY3JlYXRlRWxlbWVudCh2bm9kZSwgb3B0cykge1xuICAgICAgICAgICAgICAgIHZhciBkb2MgPSBvcHRzID8gb3B0cy5kb2N1bWVudCB8fCBkb2N1bWVudCA6IGRvY3VtZW50O1xuICAgICAgICAgICAgICAgIHZhciB3YXJuID0gb3B0cyA/IG9wdHMud2FybiA6IG51bGw7XG5cbiAgICAgICAgICAgICAgICB2bm9kZSA9IGhhbmRsZVRodW5rKHZub2RlKS5hO1xuXG4gICAgICAgICAgICAgICAgaWYgKGlzV2lkZ2V0KHZub2RlKSkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gdm5vZGUuaW5pdCgpO1xuICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoaXNWVGV4dCh2bm9kZSkpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGRvYy5jcmVhdGVUZXh0Tm9kZSh2bm9kZS50ZXh0KTtcbiAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKCFpc1ZOb2RlKHZub2RlKSkge1xuICAgICAgICAgICAgICAgICAgICBpZiAod2Fybikge1xuICAgICAgICAgICAgICAgICAgICAgICAgd2FybihcIkl0ZW0gaXMgbm90IGEgdmFsaWQgdmlydHVhbCBkb20gbm9kZVwiLCB2bm9kZSk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIG51bGw7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgdmFyIG5vZGUgPSB2bm9kZS5uYW1lc3BhY2UgPT09IG51bGwgPyBkb2MuY3JlYXRlRWxlbWVudCh2bm9kZS50YWdOYW1lKSA6IGRvYy5jcmVhdGVFbGVtZW50TlModm5vZGUubmFtZXNwYWNlLCB2bm9kZS50YWdOYW1lKTtcblxuICAgICAgICAgICAgICAgIHZhciBwcm9wcyA9IHZub2RlLnByb3BlcnRpZXM7XG4gICAgICAgICAgICAgICAgYXBwbHlQcm9wZXJ0aWVzKG5vZGUsIHByb3BzKTtcblxuICAgICAgICAgICAgICAgIHZhciBjaGlsZHJlbiA9IHZub2RlLmNoaWxkcmVuO1xuXG4gICAgICAgICAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCBjaGlsZHJlbi5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgICAgICAgICB2YXIgY2hpbGROb2RlID0gY3JlYXRlRWxlbWVudChjaGlsZHJlbltpXSwgb3B0cyk7XG4gICAgICAgICAgICAgICAgICAgIGlmIChjaGlsZE5vZGUpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIG5vZGUuYXBwZW5kQ2hpbGQoY2hpbGROb2RlKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHJldHVybiBub2RlO1xuICAgICAgICAgICAgfVxuICAgICAgICB9LCB7IFwiLi4vdm5vZGUvaGFuZGxlLXRodW5rLmpzXCI6IDI0LCBcIi4uL3Zub2RlL2lzLXZub2RlLmpzXCI6IDI3LCBcIi4uL3Zub2RlL2lzLXZ0ZXh0LmpzXCI6IDI4LCBcIi4uL3Zub2RlL2lzLXdpZGdldC5qc1wiOiAyOSwgXCIuL2FwcGx5LXByb3BlcnRpZXNcIjogMTQsIFwiZ2xvYmFsL2RvY3VtZW50XCI6IDEwIH1dLCAxNjogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHtcbiAgICAgICAgICAgIC8vIE1hcHMgYSB2aXJ0dWFsIERPTSB0cmVlIG9udG8gYSByZWFsIERPTSB0cmVlIGluIGFuIGVmZmljaWVudCBtYW5uZXIuXG4gICAgICAgICAgICAvLyBXZSBkb24ndCB3YW50IHRvIHJlYWQgYWxsIG9mIHRoZSBET00gbm9kZXMgaW4gdGhlIHRyZWUgc28gd2UgdXNlXG4gICAgICAgICAgICAvLyB0aGUgaW4tb3JkZXIgdHJlZSBpbmRleGluZyB0byBlbGltaW5hdGUgcmVjdXJzaW9uIGRvd24gY2VydGFpbiBicmFuY2hlcy5cbiAgICAgICAgICAgIC8vIFdlIG9ubHkgcmVjdXJzZSBpbnRvIGEgRE9NIG5vZGUgaWYgd2Uga25vdyB0aGF0IGl0IGNvbnRhaW5zIGEgY2hpbGQgb2ZcbiAgICAgICAgICAgIC8vIGludGVyZXN0LlxuXG4gICAgICAgICAgICB2YXIgbm9DaGlsZCA9IHt9O1xuXG4gICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IGRvbUluZGV4O1xuXG4gICAgICAgICAgICBmdW5jdGlvbiBkb21JbmRleChyb290Tm9kZSwgdHJlZSwgaW5kaWNlcywgbm9kZXMpIHtcbiAgICAgICAgICAgICAgICBpZiAoIWluZGljZXMgfHwgaW5kaWNlcy5sZW5ndGggPT09IDApIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHt9O1xuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIGluZGljZXMuc29ydChhc2NlbmRpbmcpO1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gcmVjdXJzZShyb290Tm9kZSwgdHJlZSwgaW5kaWNlcywgbm9kZXMsIDApO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZnVuY3Rpb24gcmVjdXJzZShyb290Tm9kZSwgdHJlZSwgaW5kaWNlcywgbm9kZXMsIHJvb3RJbmRleCkge1xuICAgICAgICAgICAgICAgIG5vZGVzID0gbm9kZXMgfHwge307XG5cbiAgICAgICAgICAgICAgICBpZiAocm9vdE5vZGUpIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKGluZGV4SW5SYW5nZShpbmRpY2VzLCByb290SW5kZXgsIHJvb3RJbmRleCkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIG5vZGVzW3Jvb3RJbmRleF0gPSByb290Tm9kZTtcbiAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgIHZhciB2Q2hpbGRyZW4gPSB0cmVlLmNoaWxkcmVuO1xuXG4gICAgICAgICAgICAgICAgICAgIGlmICh2Q2hpbGRyZW4pIHtcblxuICAgICAgICAgICAgICAgICAgICAgICAgdmFyIGNoaWxkTm9kZXMgPSByb290Tm9kZS5jaGlsZE5vZGVzO1xuXG4gICAgICAgICAgICAgICAgICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IHRyZWUuY2hpbGRyZW4ubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICByb290SW5kZXggKz0gMTtcblxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZhciB2Q2hpbGQgPSB2Q2hpbGRyZW5baV0gfHwgbm9DaGlsZDtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB2YXIgbmV4dEluZGV4ID0gcm9vdEluZGV4ICsgKHZDaGlsZC5jb3VudCB8fCAwKTtcblxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIHNraXAgcmVjdXJzaW9uIGRvd24gdGhlIHRyZWUgaWYgdGhlcmUgYXJlIG5vIG5vZGVzIGRvd24gaGVyZVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChpbmRleEluUmFuZ2UoaW5kaWNlcywgcm9vdEluZGV4LCBuZXh0SW5kZXgpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlY3Vyc2UoY2hpbGROb2Rlc1tpXSwgdkNoaWxkLCBpbmRpY2VzLCBub2Rlcywgcm9vdEluZGV4KTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICByb290SW5kZXggPSBuZXh0SW5kZXg7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICByZXR1cm4gbm9kZXM7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIC8vIEJpbmFyeSBzZWFyY2ggZm9yIGFuIGluZGV4IGluIHRoZSBpbnRlcnZhbCBbbGVmdCwgcmlnaHRdXG4gICAgICAgICAgICBmdW5jdGlvbiBpbmRleEluUmFuZ2UoaW5kaWNlcywgbGVmdCwgcmlnaHQpIHtcbiAgICAgICAgICAgICAgICBpZiAoaW5kaWNlcy5sZW5ndGggPT09IDApIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHZhciBtaW5JbmRleCA9IDA7XG4gICAgICAgICAgICAgICAgdmFyIG1heEluZGV4ID0gaW5kaWNlcy5sZW5ndGggLSAxO1xuICAgICAgICAgICAgICAgIHZhciBjdXJyZW50SW5kZXg7XG4gICAgICAgICAgICAgICAgdmFyIGN1cnJlbnRJdGVtO1xuXG4gICAgICAgICAgICAgICAgd2hpbGUgKG1pbkluZGV4IDw9IG1heEluZGV4KSB7XG4gICAgICAgICAgICAgICAgICAgIGN1cnJlbnRJbmRleCA9IChtYXhJbmRleCArIG1pbkluZGV4KSAvIDIgPj4gMDtcbiAgICAgICAgICAgICAgICAgICAgY3VycmVudEl0ZW0gPSBpbmRpY2VzW2N1cnJlbnRJbmRleF07XG5cbiAgICAgICAgICAgICAgICAgICAgaWYgKG1pbkluZGV4ID09PSBtYXhJbmRleCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGN1cnJlbnRJdGVtID49IGxlZnQgJiYgY3VycmVudEl0ZW0gPD0gcmlnaHQ7XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoY3VycmVudEl0ZW0gPCBsZWZ0KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBtaW5JbmRleCA9IGN1cnJlbnRJbmRleCArIDE7XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoY3VycmVudEl0ZW0gPiByaWdodCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgbWF4SW5kZXggPSBjdXJyZW50SW5kZXggLSAxO1xuICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIGFzY2VuZGluZyhhLCBiKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGEgPiBiID8gMSA6IC0xO1xuICAgICAgICAgICAgfVxuICAgICAgICB9LCB7fV0sIDE3OiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge1xuICAgICAgICAgICAgdmFyIGFwcGx5UHJvcGVydGllcyA9IHJlcXVpcmUoXCIuL2FwcGx5LXByb3BlcnRpZXNcIik7XG5cbiAgICAgICAgICAgIHZhciBpc1dpZGdldCA9IHJlcXVpcmUoXCIuLi92bm9kZS9pcy13aWRnZXQuanNcIik7XG4gICAgICAgICAgICB2YXIgVlBhdGNoID0gcmVxdWlyZShcIi4uL3Zub2RlL3ZwYXRjaC5qc1wiKTtcblxuICAgICAgICAgICAgdmFyIHVwZGF0ZVdpZGdldCA9IHJlcXVpcmUoXCIuL3VwZGF0ZS13aWRnZXRcIik7XG5cbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gYXBwbHlQYXRjaDtcblxuICAgICAgICAgICAgZnVuY3Rpb24gYXBwbHlQYXRjaCh2cGF0Y2gsIGRvbU5vZGUsIHJlbmRlck9wdGlvbnMpIHtcbiAgICAgICAgICAgICAgICB2YXIgdHlwZSA9IHZwYXRjaC50eXBlO1xuICAgICAgICAgICAgICAgIHZhciB2Tm9kZSA9IHZwYXRjaC52Tm9kZTtcbiAgICAgICAgICAgICAgICB2YXIgcGF0Y2ggPSB2cGF0Y2gucGF0Y2g7XG5cbiAgICAgICAgICAgICAgICBzd2l0Y2ggKHR5cGUpIHtcbiAgICAgICAgICAgICAgICAgICAgY2FzZSBWUGF0Y2guUkVNT1ZFOlxuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHJlbW92ZU5vZGUoZG9tTm9kZSwgdk5vZGUpO1xuICAgICAgICAgICAgICAgICAgICBjYXNlIFZQYXRjaC5JTlNFUlQ6XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gaW5zZXJ0Tm9kZShkb21Ob2RlLCBwYXRjaCwgcmVuZGVyT3B0aW9ucyk7XG4gICAgICAgICAgICAgICAgICAgIGNhc2UgVlBhdGNoLlZURVhUOlxuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHN0cmluZ1BhdGNoKGRvbU5vZGUsIHZOb2RlLCBwYXRjaCwgcmVuZGVyT3B0aW9ucyk7XG4gICAgICAgICAgICAgICAgICAgIGNhc2UgVlBhdGNoLldJREdFVDpcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiB3aWRnZXRQYXRjaChkb21Ob2RlLCB2Tm9kZSwgcGF0Y2gsIHJlbmRlck9wdGlvbnMpO1xuICAgICAgICAgICAgICAgICAgICBjYXNlIFZQYXRjaC5WTk9ERTpcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiB2Tm9kZVBhdGNoKGRvbU5vZGUsIHZOb2RlLCBwYXRjaCwgcmVuZGVyT3B0aW9ucyk7XG4gICAgICAgICAgICAgICAgICAgIGNhc2UgVlBhdGNoLk9SREVSOlxuICAgICAgICAgICAgICAgICAgICAgICAgcmVvcmRlckNoaWxkcmVuKGRvbU5vZGUsIHBhdGNoKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBkb21Ob2RlO1xuICAgICAgICAgICAgICAgICAgICBjYXNlIFZQYXRjaC5QUk9QUzpcbiAgICAgICAgICAgICAgICAgICAgICAgIGFwcGx5UHJvcGVydGllcyhkb21Ob2RlLCBwYXRjaCwgdk5vZGUucHJvcGVydGllcyk7XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gZG9tTm9kZTtcbiAgICAgICAgICAgICAgICAgICAgY2FzZSBWUGF0Y2guVEhVTks6XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gcmVwbGFjZVJvb3QoZG9tTm9kZSwgcmVuZGVyT3B0aW9ucy5wYXRjaChkb21Ob2RlLCBwYXRjaCwgcmVuZGVyT3B0aW9ucykpO1xuICAgICAgICAgICAgICAgICAgICBkZWZhdWx0OlxuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGRvbU5vZGU7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBmdW5jdGlvbiByZW1vdmVOb2RlKGRvbU5vZGUsIHZOb2RlKSB7XG4gICAgICAgICAgICAgICAgdmFyIHBhcmVudE5vZGUgPSBkb21Ob2RlLnBhcmVudE5vZGU7XG5cbiAgICAgICAgICAgICAgICBpZiAocGFyZW50Tm9kZSkge1xuICAgICAgICAgICAgICAgICAgICBwYXJlbnROb2RlLnJlbW92ZUNoaWxkKGRvbU5vZGUpO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIGRlc3Ryb3lXaWRnZXQoZG9tTm9kZSwgdk5vZGUpO1xuXG4gICAgICAgICAgICAgICAgcmV0dXJuIG51bGw7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIGluc2VydE5vZGUocGFyZW50Tm9kZSwgdk5vZGUsIHJlbmRlck9wdGlvbnMpIHtcbiAgICAgICAgICAgICAgICB2YXIgbmV3Tm9kZSA9IHJlbmRlck9wdGlvbnMucmVuZGVyKHZOb2RlLCByZW5kZXJPcHRpb25zKTtcblxuICAgICAgICAgICAgICAgIGlmIChwYXJlbnROb2RlKSB7XG4gICAgICAgICAgICAgICAgICAgIHBhcmVudE5vZGUuYXBwZW5kQ2hpbGQobmV3Tm9kZSk7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgcmV0dXJuIHBhcmVudE5vZGU7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIHN0cmluZ1BhdGNoKGRvbU5vZGUsIGxlZnRWTm9kZSwgdlRleHQsIHJlbmRlck9wdGlvbnMpIHtcbiAgICAgICAgICAgICAgICB2YXIgbmV3Tm9kZTtcblxuICAgICAgICAgICAgICAgIGlmIChkb21Ob2RlLm5vZGVUeXBlID09PSAzKSB7XG4gICAgICAgICAgICAgICAgICAgIGRvbU5vZGUucmVwbGFjZURhdGEoMCwgZG9tTm9kZS5sZW5ndGgsIHZUZXh0LnRleHQpO1xuICAgICAgICAgICAgICAgICAgICBuZXdOb2RlID0gZG9tTm9kZTtcbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICB2YXIgcGFyZW50Tm9kZSA9IGRvbU5vZGUucGFyZW50Tm9kZTtcbiAgICAgICAgICAgICAgICAgICAgbmV3Tm9kZSA9IHJlbmRlck9wdGlvbnMucmVuZGVyKHZUZXh0LCByZW5kZXJPcHRpb25zKTtcblxuICAgICAgICAgICAgICAgICAgICBpZiAocGFyZW50Tm9kZSAmJiBuZXdOb2RlICE9PSBkb21Ob2RlKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBwYXJlbnROb2RlLnJlcGxhY2VDaGlsZChuZXdOb2RlLCBkb21Ob2RlKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHJldHVybiBuZXdOb2RlO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBmdW5jdGlvbiB3aWRnZXRQYXRjaChkb21Ob2RlLCBsZWZ0Vk5vZGUsIHdpZGdldCwgcmVuZGVyT3B0aW9ucykge1xuICAgICAgICAgICAgICAgIHZhciB1cGRhdGluZyA9IHVwZGF0ZVdpZGdldChsZWZ0Vk5vZGUsIHdpZGdldCk7XG4gICAgICAgICAgICAgICAgdmFyIG5ld05vZGU7XG5cbiAgICAgICAgICAgICAgICBpZiAodXBkYXRpbmcpIHtcbiAgICAgICAgICAgICAgICAgICAgbmV3Tm9kZSA9IHdpZGdldC51cGRhdGUobGVmdFZOb2RlLCBkb21Ob2RlKSB8fCBkb21Ob2RlO1xuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIG5ld05vZGUgPSByZW5kZXJPcHRpb25zLnJlbmRlcih3aWRnZXQsIHJlbmRlck9wdGlvbnMpO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHZhciBwYXJlbnROb2RlID0gZG9tTm9kZS5wYXJlbnROb2RlO1xuXG4gICAgICAgICAgICAgICAgaWYgKHBhcmVudE5vZGUgJiYgbmV3Tm9kZSAhPT0gZG9tTm9kZSkge1xuICAgICAgICAgICAgICAgICAgICBwYXJlbnROb2RlLnJlcGxhY2VDaGlsZChuZXdOb2RlLCBkb21Ob2RlKTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICBpZiAoIXVwZGF0aW5nKSB7XG4gICAgICAgICAgICAgICAgICAgIGRlc3Ryb3lXaWRnZXQoZG9tTm9kZSwgbGVmdFZOb2RlKTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICByZXR1cm4gbmV3Tm9kZTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZnVuY3Rpb24gdk5vZGVQYXRjaChkb21Ob2RlLCBsZWZ0Vk5vZGUsIHZOb2RlLCByZW5kZXJPcHRpb25zKSB7XG4gICAgICAgICAgICAgICAgdmFyIHBhcmVudE5vZGUgPSBkb21Ob2RlLnBhcmVudE5vZGU7XG4gICAgICAgICAgICAgICAgdmFyIG5ld05vZGUgPSByZW5kZXJPcHRpb25zLnJlbmRlcih2Tm9kZSwgcmVuZGVyT3B0aW9ucyk7XG5cbiAgICAgICAgICAgICAgICBpZiAocGFyZW50Tm9kZSAmJiBuZXdOb2RlICE9PSBkb21Ob2RlKSB7XG4gICAgICAgICAgICAgICAgICAgIHBhcmVudE5vZGUucmVwbGFjZUNoaWxkKG5ld05vZGUsIGRvbU5vZGUpO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHJldHVybiBuZXdOb2RlO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBmdW5jdGlvbiBkZXN0cm95V2lkZ2V0KGRvbU5vZGUsIHcpIHtcbiAgICAgICAgICAgICAgICBpZiAodHlwZW9mIHcuZGVzdHJveSA9PT0gXCJmdW5jdGlvblwiICYmIGlzV2lkZ2V0KHcpKSB7XG4gICAgICAgICAgICAgICAgICAgIHcuZGVzdHJveShkb21Ob2RlKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIHJlb3JkZXJDaGlsZHJlbihkb21Ob2RlLCBtb3Zlcykge1xuICAgICAgICAgICAgICAgIHZhciBjaGlsZE5vZGVzID0gZG9tTm9kZS5jaGlsZE5vZGVzO1xuICAgICAgICAgICAgICAgIHZhciBrZXlNYXAgPSB7fTtcbiAgICAgICAgICAgICAgICB2YXIgbm9kZTtcbiAgICAgICAgICAgICAgICB2YXIgcmVtb3ZlO1xuICAgICAgICAgICAgICAgIHZhciBpbnNlcnQ7XG5cbiAgICAgICAgICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IG1vdmVzLnJlbW92ZXMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgICAgICAgICAgcmVtb3ZlID0gbW92ZXMucmVtb3Zlc1tpXTtcbiAgICAgICAgICAgICAgICAgICAgbm9kZSA9IGNoaWxkTm9kZXNbcmVtb3ZlLmZyb21dO1xuICAgICAgICAgICAgICAgICAgICBpZiAocmVtb3ZlLmtleSkge1xuICAgICAgICAgICAgICAgICAgICAgICAga2V5TWFwW3JlbW92ZS5rZXldID0gbm9kZTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICBkb21Ob2RlLnJlbW92ZUNoaWxkKG5vZGUpO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHZhciBsZW5ndGggPSBjaGlsZE5vZGVzLmxlbmd0aDtcbiAgICAgICAgICAgICAgICBmb3IgKHZhciBqID0gMDsgaiA8IG1vdmVzLmluc2VydHMubGVuZ3RoOyBqKyspIHtcbiAgICAgICAgICAgICAgICAgICAgaW5zZXJ0ID0gbW92ZXMuaW5zZXJ0c1tqXTtcbiAgICAgICAgICAgICAgICAgICAgbm9kZSA9IGtleU1hcFtpbnNlcnQua2V5XTtcbiAgICAgICAgICAgICAgICAgICAgLy8gdGhpcyBpcyB0aGUgd2VpcmRlc3QgYnVnIGkndmUgZXZlciBzZWVuIGluIHdlYmtpdFxuICAgICAgICAgICAgICAgICAgICBkb21Ob2RlLmluc2VydEJlZm9yZShub2RlLCBpbnNlcnQudG8gPj0gbGVuZ3RoKysgPyBudWxsIDogY2hpbGROb2Rlc1tpbnNlcnQudG9dKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIHJlcGxhY2VSb290KG9sZFJvb3QsIG5ld1Jvb3QpIHtcbiAgICAgICAgICAgICAgICBpZiAob2xkUm9vdCAmJiBuZXdSb290ICYmIG9sZFJvb3QgIT09IG5ld1Jvb3QgJiYgb2xkUm9vdC5wYXJlbnROb2RlKSB7XG4gICAgICAgICAgICAgICAgICAgIG9sZFJvb3QucGFyZW50Tm9kZS5yZXBsYWNlQ2hpbGQobmV3Um9vdCwgb2xkUm9vdCk7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgcmV0dXJuIG5ld1Jvb3Q7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0sIHsgXCIuLi92bm9kZS9pcy13aWRnZXQuanNcIjogMjksIFwiLi4vdm5vZGUvdnBhdGNoLmpzXCI6IDMyLCBcIi4vYXBwbHktcHJvcGVydGllc1wiOiAxNCwgXCIuL3VwZGF0ZS13aWRnZXRcIjogMTkgfV0sIDE4OiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge1xuICAgICAgICAgICAgdmFyIGRvY3VtZW50ID0gcmVxdWlyZShcImdsb2JhbC9kb2N1bWVudFwiKTtcbiAgICAgICAgICAgIHZhciBpc0FycmF5ID0gcmVxdWlyZShcIngtaXMtYXJyYXlcIik7XG5cbiAgICAgICAgICAgIHZhciByZW5kZXIgPSByZXF1aXJlKFwiLi9jcmVhdGUtZWxlbWVudFwiKTtcbiAgICAgICAgICAgIHZhciBkb21JbmRleCA9IHJlcXVpcmUoXCIuL2RvbS1pbmRleFwiKTtcbiAgICAgICAgICAgIHZhciBwYXRjaE9wID0gcmVxdWlyZShcIi4vcGF0Y2gtb3BcIik7XG4gICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IHBhdGNoO1xuXG4gICAgICAgICAgICBmdW5jdGlvbiBwYXRjaChyb290Tm9kZSwgcGF0Y2hlcywgcmVuZGVyT3B0aW9ucykge1xuICAgICAgICAgICAgICAgIHJlbmRlck9wdGlvbnMgPSByZW5kZXJPcHRpb25zIHx8IHt9O1xuICAgICAgICAgICAgICAgIHJlbmRlck9wdGlvbnMucGF0Y2ggPSByZW5kZXJPcHRpb25zLnBhdGNoICYmIHJlbmRlck9wdGlvbnMucGF0Y2ggIT09IHBhdGNoID8gcmVuZGVyT3B0aW9ucy5wYXRjaCA6IHBhdGNoUmVjdXJzaXZlO1xuICAgICAgICAgICAgICAgIHJlbmRlck9wdGlvbnMucmVuZGVyID0gcmVuZGVyT3B0aW9ucy5yZW5kZXIgfHwgcmVuZGVyO1xuXG4gICAgICAgICAgICAgICAgcmV0dXJuIHJlbmRlck9wdGlvbnMucGF0Y2gocm9vdE5vZGUsIHBhdGNoZXMsIHJlbmRlck9wdGlvbnMpO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBmdW5jdGlvbiBwYXRjaFJlY3Vyc2l2ZShyb290Tm9kZSwgcGF0Y2hlcywgcmVuZGVyT3B0aW9ucykge1xuICAgICAgICAgICAgICAgIHZhciBpbmRpY2VzID0gcGF0Y2hJbmRpY2VzKHBhdGNoZXMpO1xuXG4gICAgICAgICAgICAgICAgaWYgKGluZGljZXMubGVuZ3RoID09PSAwKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiByb290Tm9kZTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICB2YXIgaW5kZXggPSBkb21JbmRleChyb290Tm9kZSwgcGF0Y2hlcy5hLCBpbmRpY2VzKTtcbiAgICAgICAgICAgICAgICB2YXIgb3duZXJEb2N1bWVudCA9IHJvb3ROb2RlLm93bmVyRG9jdW1lbnQ7XG5cbiAgICAgICAgICAgICAgICBpZiAoIXJlbmRlck9wdGlvbnMuZG9jdW1lbnQgJiYgb3duZXJEb2N1bWVudCAhPT0gZG9jdW1lbnQpIHtcbiAgICAgICAgICAgICAgICAgICAgcmVuZGVyT3B0aW9ucy5kb2N1bWVudCA9IG93bmVyRG9jdW1lbnQ7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCBpbmRpY2VzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciBub2RlSW5kZXggPSBpbmRpY2VzW2ldO1xuICAgICAgICAgICAgICAgICAgICByb290Tm9kZSA9IGFwcGx5UGF0Y2gocm9vdE5vZGUsIGluZGV4W25vZGVJbmRleF0sIHBhdGNoZXNbbm9kZUluZGV4XSwgcmVuZGVyT3B0aW9ucyk7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgcmV0dXJuIHJvb3ROb2RlO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBmdW5jdGlvbiBhcHBseVBhdGNoKHJvb3ROb2RlLCBkb21Ob2RlLCBwYXRjaExpc3QsIHJlbmRlck9wdGlvbnMpIHtcbiAgICAgICAgICAgICAgICBpZiAoIWRvbU5vZGUpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHJvb3ROb2RlO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHZhciBuZXdOb2RlO1xuXG4gICAgICAgICAgICAgICAgaWYgKGlzQXJyYXkocGF0Y2hMaXN0KSkge1xuICAgICAgICAgICAgICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IHBhdGNoTGlzdC5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgICAgICAgICAgICAgbmV3Tm9kZSA9IHBhdGNoT3AocGF0Y2hMaXN0W2ldLCBkb21Ob2RlLCByZW5kZXJPcHRpb25zKTtcblxuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGRvbU5vZGUgPT09IHJvb3ROb2RlKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcm9vdE5vZGUgPSBuZXdOb2RlO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgbmV3Tm9kZSA9IHBhdGNoT3AocGF0Y2hMaXN0LCBkb21Ob2RlLCByZW5kZXJPcHRpb25zKTtcblxuICAgICAgICAgICAgICAgICAgICBpZiAoZG9tTm9kZSA9PT0gcm9vdE5vZGUpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJvb3ROb2RlID0gbmV3Tm9kZTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHJldHVybiByb290Tm9kZTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZnVuY3Rpb24gcGF0Y2hJbmRpY2VzKHBhdGNoZXMpIHtcbiAgICAgICAgICAgICAgICB2YXIgaW5kaWNlcyA9IFtdO1xuXG4gICAgICAgICAgICAgICAgZm9yICh2YXIga2V5IGluIHBhdGNoZXMpIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKGtleSAhPT0gXCJhXCIpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGluZGljZXMucHVzaChOdW1iZXIoa2V5KSk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICByZXR1cm4gaW5kaWNlcztcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSwgeyBcIi4vY3JlYXRlLWVsZW1lbnRcIjogMTUsIFwiLi9kb20taW5kZXhcIjogMTYsIFwiLi9wYXRjaC1vcFwiOiAxNywgXCJnbG9iYWwvZG9jdW1lbnRcIjogMTAsIFwieC1pcy1hcnJheVwiOiAxMiB9XSwgMTk6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICB2YXIgaXNXaWRnZXQgPSByZXF1aXJlKFwiLi4vdm5vZGUvaXMtd2lkZ2V0LmpzXCIpO1xuXG4gICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IHVwZGF0ZVdpZGdldDtcblxuICAgICAgICAgICAgZnVuY3Rpb24gdXBkYXRlV2lkZ2V0KGEsIGIpIHtcbiAgICAgICAgICAgICAgICBpZiAoaXNXaWRnZXQoYSkgJiYgaXNXaWRnZXQoYikpIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKFwibmFtZVwiIGluIGEgJiYgXCJuYW1lXCIgaW4gYikge1xuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGEuaWQgPT09IGIuaWQ7XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gYS5pbml0ID09PSBiLmluaXQ7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0sIHsgXCIuLi92bm9kZS9pcy13aWRnZXQuanNcIjogMjkgfV0sIDIwOiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge1xuICAgICAgICAgICAgXCJ1c2Ugc3RyaWN0XCI7XG5cbiAgICAgICAgICAgIHZhciBFdlN0b3JlID0gcmVxdWlyZShcImV2LXN0b3JlXCIpO1xuXG4gICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IEV2SG9vaztcblxuICAgICAgICAgICAgZnVuY3Rpb24gRXZIb29rKHZhbHVlKSB7XG4gICAgICAgICAgICAgICAgaWYgKCEodGhpcyBpbnN0YW5jZW9mIEV2SG9vaykpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIG5ldyBFdkhvb2sodmFsdWUpO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHRoaXMudmFsdWUgPSB2YWx1ZTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgRXZIb29rLnByb3RvdHlwZS5ob29rID0gZnVuY3Rpb24gKG5vZGUsIHByb3BlcnR5TmFtZSkge1xuICAgICAgICAgICAgICAgIHZhciBlcyA9IEV2U3RvcmUobm9kZSk7XG4gICAgICAgICAgICAgICAgdmFyIHByb3BOYW1lID0gcHJvcGVydHlOYW1lLnN1YnN0cigzKTtcblxuICAgICAgICAgICAgICAgIGVzW3Byb3BOYW1lXSA9IHRoaXMudmFsdWU7XG4gICAgICAgICAgICB9O1xuXG4gICAgICAgICAgICBFdkhvb2sucHJvdG90eXBlLnVuaG9vayA9IGZ1bmN0aW9uIChub2RlLCBwcm9wZXJ0eU5hbWUpIHtcbiAgICAgICAgICAgICAgICB2YXIgZXMgPSBFdlN0b3JlKG5vZGUpO1xuICAgICAgICAgICAgICAgIHZhciBwcm9wTmFtZSA9IHByb3BlcnR5TmFtZS5zdWJzdHIoMyk7XG5cbiAgICAgICAgICAgICAgICBlc1twcm9wTmFtZV0gPSB1bmRlZmluZWQ7XG4gICAgICAgICAgICB9O1xuICAgICAgICB9LCB7IFwiZXYtc3RvcmVcIjogNyB9XSwgMjE6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICBcInVzZSBzdHJpY3RcIjtcblxuICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBTb2Z0U2V0SG9vaztcblxuICAgICAgICAgICAgZnVuY3Rpb24gU29mdFNldEhvb2sodmFsdWUpIHtcbiAgICAgICAgICAgICAgICBpZiAoISh0aGlzIGluc3RhbmNlb2YgU29mdFNldEhvb2spKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBuZXcgU29mdFNldEhvb2sodmFsdWUpO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHRoaXMudmFsdWUgPSB2YWx1ZTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgU29mdFNldEhvb2sucHJvdG90eXBlLmhvb2sgPSBmdW5jdGlvbiAobm9kZSwgcHJvcGVydHlOYW1lKSB7XG4gICAgICAgICAgICAgICAgaWYgKG5vZGVbcHJvcGVydHlOYW1lXSAhPT0gdGhpcy52YWx1ZSkge1xuICAgICAgICAgICAgICAgICAgICBub2RlW3Byb3BlcnR5TmFtZV0gPSB0aGlzLnZhbHVlO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH07XG4gICAgICAgIH0sIHt9XSwgMjI6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICBcInVzZSBzdHJpY3RcIjtcblxuICAgICAgICAgICAgdmFyIGlzQXJyYXkgPSByZXF1aXJlKFwieC1pcy1hcnJheVwiKTtcblxuICAgICAgICAgICAgdmFyIFZOb2RlID0gcmVxdWlyZShcIi4uL3Zub2RlL3Zub2RlLmpzXCIpO1xuICAgICAgICAgICAgdmFyIFZUZXh0ID0gcmVxdWlyZShcIi4uL3Zub2RlL3Z0ZXh0LmpzXCIpO1xuICAgICAgICAgICAgdmFyIGlzVk5vZGUgPSByZXF1aXJlKFwiLi4vdm5vZGUvaXMtdm5vZGVcIik7XG4gICAgICAgICAgICB2YXIgaXNWVGV4dCA9IHJlcXVpcmUoXCIuLi92bm9kZS9pcy12dGV4dFwiKTtcbiAgICAgICAgICAgIHZhciBpc1dpZGdldCA9IHJlcXVpcmUoXCIuLi92bm9kZS9pcy13aWRnZXRcIik7XG4gICAgICAgICAgICB2YXIgaXNIb29rID0gcmVxdWlyZShcIi4uL3Zub2RlL2lzLXZob29rXCIpO1xuICAgICAgICAgICAgdmFyIGlzVlRodW5rID0gcmVxdWlyZShcIi4uL3Zub2RlL2lzLXRodW5rXCIpO1xuXG4gICAgICAgICAgICB2YXIgcGFyc2VUYWcgPSByZXF1aXJlKFwiLi9wYXJzZS10YWcuanNcIik7XG4gICAgICAgICAgICB2YXIgc29mdFNldEhvb2sgPSByZXF1aXJlKFwiLi9ob29rcy9zb2Z0LXNldC1ob29rLmpzXCIpO1xuICAgICAgICAgICAgdmFyIGV2SG9vayA9IHJlcXVpcmUoXCIuL2hvb2tzL2V2LWhvb2suanNcIik7XG5cbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gaDtcblxuICAgICAgICAgICAgZnVuY3Rpb24gaCh0YWdOYW1lLCBwcm9wZXJ0aWVzLCBjaGlsZHJlbikge1xuICAgICAgICAgICAgICAgIHZhciBjaGlsZE5vZGVzID0gW107XG4gICAgICAgICAgICAgICAgdmFyIHRhZywgcHJvcHMsIGtleSwgbmFtZXNwYWNlO1xuXG4gICAgICAgICAgICAgICAgaWYgKCFjaGlsZHJlbiAmJiBpc0NoaWxkcmVuKHByb3BlcnRpZXMpKSB7XG4gICAgICAgICAgICAgICAgICAgIGNoaWxkcmVuID0gcHJvcGVydGllcztcbiAgICAgICAgICAgICAgICAgICAgcHJvcHMgPSB7fTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICBwcm9wcyA9IHByb3BzIHx8IHByb3BlcnRpZXMgfHwge307XG4gICAgICAgICAgICAgICAgdGFnID0gcGFyc2VUYWcodGFnTmFtZSwgcHJvcHMpO1xuXG4gICAgICAgICAgICAgICAgLy8gc3VwcG9ydCBrZXlzXG4gICAgICAgICAgICAgICAgaWYgKHByb3BzLmhhc093blByb3BlcnR5KFwia2V5XCIpKSB7XG4gICAgICAgICAgICAgICAgICAgIGtleSA9IHByb3BzLmtleTtcbiAgICAgICAgICAgICAgICAgICAgcHJvcHMua2V5ID0gdW5kZWZpbmVkO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIC8vIHN1cHBvcnQgbmFtZXNwYWNlXG4gICAgICAgICAgICAgICAgaWYgKHByb3BzLmhhc093blByb3BlcnR5KFwibmFtZXNwYWNlXCIpKSB7XG4gICAgICAgICAgICAgICAgICAgIG5hbWVzcGFjZSA9IHByb3BzLm5hbWVzcGFjZTtcbiAgICAgICAgICAgICAgICAgICAgcHJvcHMubmFtZXNwYWNlID0gdW5kZWZpbmVkO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIC8vIGZpeCBjdXJzb3IgYnVnXG4gICAgICAgICAgICAgICAgaWYgKHRhZyA9PT0gXCJJTlBVVFwiICYmICFuYW1lc3BhY2UgJiYgcHJvcHMuaGFzT3duUHJvcGVydHkoXCJ2YWx1ZVwiKSAmJiBwcm9wcy52YWx1ZSAhPT0gdW5kZWZpbmVkICYmICFpc0hvb2socHJvcHMudmFsdWUpKSB7XG4gICAgICAgICAgICAgICAgICAgIHByb3BzLnZhbHVlID0gc29mdFNldEhvb2socHJvcHMudmFsdWUpO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHRyYW5zZm9ybVByb3BlcnRpZXMocHJvcHMpO1xuXG4gICAgICAgICAgICAgICAgaWYgKGNoaWxkcmVuICE9PSB1bmRlZmluZWQgJiYgY2hpbGRyZW4gIT09IG51bGwpIHtcbiAgICAgICAgICAgICAgICAgICAgYWRkQ2hpbGQoY2hpbGRyZW4sIGNoaWxkTm9kZXMsIHRhZywgcHJvcHMpO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHJldHVybiBuZXcgVk5vZGUodGFnLCBwcm9wcywgY2hpbGROb2Rlcywga2V5LCBuYW1lc3BhY2UpO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBmdW5jdGlvbiBhZGRDaGlsZChjLCBjaGlsZE5vZGVzLCB0YWcsIHByb3BzKSB7XG4gICAgICAgICAgICAgICAgaWYgKHR5cGVvZiBjID09PSBcInN0cmluZ1wiKSB7XG4gICAgICAgICAgICAgICAgICAgIGNoaWxkTm9kZXMucHVzaChuZXcgVlRleHQoYykpO1xuICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAodHlwZW9mIGMgPT09IFwibnVtYmVyXCIpIHtcbiAgICAgICAgICAgICAgICAgICAgY2hpbGROb2Rlcy5wdXNoKG5ldyBWVGV4dChTdHJpbmcoYykpKTtcbiAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKGlzQ2hpbGQoYykpIHtcbiAgICAgICAgICAgICAgICAgICAgY2hpbGROb2Rlcy5wdXNoKGMpO1xuICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoaXNBcnJheShjKSkge1xuICAgICAgICAgICAgICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IGMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGFkZENoaWxkKGNbaV0sIGNoaWxkTm9kZXMsIHRhZywgcHJvcHMpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfSBlbHNlIGlmIChjID09PSBudWxsIHx8IGMgPT09IHVuZGVmaW5lZCkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgdGhyb3cgVW5leHBlY3RlZFZpcnR1YWxFbGVtZW50KHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGZvcmVpZ25PYmplY3Q6IGMsXG4gICAgICAgICAgICAgICAgICAgICAgICBwYXJlbnRWbm9kZToge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRhZ05hbWU6IHRhZyxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBwcm9wZXJ0aWVzOiBwcm9wc1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIHRyYW5zZm9ybVByb3BlcnRpZXMocHJvcHMpIHtcbiAgICAgICAgICAgICAgICBmb3IgKHZhciBwcm9wTmFtZSBpbiBwcm9wcykge1xuICAgICAgICAgICAgICAgICAgICBpZiAocHJvcHMuaGFzT3duUHJvcGVydHkocHJvcE5hbWUpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICB2YXIgdmFsdWUgPSBwcm9wc1twcm9wTmFtZV07XG5cbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChpc0hvb2sodmFsdWUpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgY29udGludWU7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChwcm9wTmFtZS5zdWJzdHIoMCwgMykgPT09IFwiZXYtXCIpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBhZGQgZXYtZm9vIHN1cHBvcnRcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBwcm9wc1twcm9wTmFtZV0gPSBldkhvb2sodmFsdWUpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBmdW5jdGlvbiBpc0NoaWxkKHgpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gaXNWTm9kZSh4KSB8fCBpc1ZUZXh0KHgpIHx8IGlzV2lkZ2V0KHgpIHx8IGlzVlRodW5rKHgpO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBmdW5jdGlvbiBpc0NoaWxkcmVuKHgpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gdHlwZW9mIHggPT09IFwic3RyaW5nXCIgfHwgaXNBcnJheSh4KSB8fCBpc0NoaWxkKHgpO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBmdW5jdGlvbiBVbmV4cGVjdGVkVmlydHVhbEVsZW1lbnQoZGF0YSkge1xuICAgICAgICAgICAgICAgIHZhciBlcnIgPSBuZXcgRXJyb3IoKTtcblxuICAgICAgICAgICAgICAgIGVyci50eXBlID0gXCJ2aXJ0dWFsLWh5cGVyc2NyaXB0LnVuZXhwZWN0ZWQudmlydHVhbC1lbGVtZW50XCI7XG4gICAgICAgICAgICAgICAgZXJyLm1lc3NhZ2UgPSBcIlVuZXhwZWN0ZWQgdmlydHVhbCBjaGlsZCBwYXNzZWQgdG8gaCgpLlxcblwiICsgXCJFeHBlY3RlZCBhIFZOb2RlIC8gVnRodW5rIC8gVldpZGdldCAvIHN0cmluZyBidXQ6XFxuXCIgKyBcImdvdDpcXG5cIiArIGVycm9yU3RyaW5nKGRhdGEuZm9yZWlnbk9iamVjdCkgKyBcIi5cXG5cIiArIFwiVGhlIHBhcmVudCB2bm9kZSBpczpcXG5cIiArIGVycm9yU3RyaW5nKGRhdGEucGFyZW50Vm5vZGUpO1xuICAgICAgICAgICAgICAgIFwiXFxuXCIgKyBcIlN1Z2dlc3RlZCBmaXg6IGNoYW5nZSB5b3VyIGBoKC4uLiwgWyAuLi4gXSlgIGNhbGxzaXRlLlwiO1xuICAgICAgICAgICAgICAgIGVyci5mb3JlaWduT2JqZWN0ID0gZGF0YS5mb3JlaWduT2JqZWN0O1xuICAgICAgICAgICAgICAgIGVyci5wYXJlbnRWbm9kZSA9IGRhdGEucGFyZW50Vm5vZGU7XG5cbiAgICAgICAgICAgICAgICByZXR1cm4gZXJyO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBmdW5jdGlvbiBlcnJvclN0cmluZyhvYmopIHtcbiAgICAgICAgICAgICAgICB0cnkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gSlNPTi5zdHJpbmdpZnkob2JqLCBudWxsLCBcIiAgICBcIik7XG4gICAgICAgICAgICAgICAgfSBjYXRjaCAoZSkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gU3RyaW5nKG9iaik7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9LCB7IFwiLi4vdm5vZGUvaXMtdGh1bmtcIjogMjUsIFwiLi4vdm5vZGUvaXMtdmhvb2tcIjogMjYsIFwiLi4vdm5vZGUvaXMtdm5vZGVcIjogMjcsIFwiLi4vdm5vZGUvaXMtdnRleHRcIjogMjgsIFwiLi4vdm5vZGUvaXMtd2lkZ2V0XCI6IDI5LCBcIi4uL3Zub2RlL3Zub2RlLmpzXCI6IDMxLCBcIi4uL3Zub2RlL3Z0ZXh0LmpzXCI6IDMzLCBcIi4vaG9va3MvZXYtaG9vay5qc1wiOiAyMCwgXCIuL2hvb2tzL3NvZnQtc2V0LWhvb2suanNcIjogMjEsIFwiLi9wYXJzZS10YWcuanNcIjogMjMsIFwieC1pcy1hcnJheVwiOiAxMiB9XSwgMjM6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICBcInVzZSBzdHJpY3RcIjtcblxuICAgICAgICAgICAgdmFyIHNwbGl0ID0gcmVxdWlyZShcImJyb3dzZXItc3BsaXRcIik7XG5cbiAgICAgICAgICAgIHZhciBjbGFzc0lkU3BsaXQgPSAvKFtcXC4jXT9bYS16QS1aMC05XFx1MDA3Ri1cXHVGRkZGXzotXSspLztcbiAgICAgICAgICAgIHZhciBub3RDbGFzc0lkID0gL15cXC58Iy87XG5cbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gcGFyc2VUYWc7XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIHBhcnNlVGFnKHRhZywgcHJvcHMpIHtcbiAgICAgICAgICAgICAgICBpZiAoIXRhZykge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gXCJESVZcIjtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICB2YXIgbm9JZCA9ICFwcm9wcy5oYXNPd25Qcm9wZXJ0eShcImlkXCIpO1xuXG4gICAgICAgICAgICAgICAgdmFyIHRhZ1BhcnRzID0gc3BsaXQodGFnLCBjbGFzc0lkU3BsaXQpO1xuICAgICAgICAgICAgICAgIHZhciB0YWdOYW1lID0gbnVsbDtcblxuICAgICAgICAgICAgICAgIGlmIChub3RDbGFzc0lkLnRlc3QodGFnUGFydHNbMV0pKSB7XG4gICAgICAgICAgICAgICAgICAgIHRhZ05hbWUgPSBcIkRJVlwiO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHZhciBjbGFzc2VzLCBwYXJ0LCB0eXBlLCBpO1xuXG4gICAgICAgICAgICAgICAgZm9yIChpID0gMDsgaSA8IHRhZ1BhcnRzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICAgICAgICAgIHBhcnQgPSB0YWdQYXJ0c1tpXTtcblxuICAgICAgICAgICAgICAgICAgICBpZiAoIXBhcnQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnRpbnVlO1xuICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgdHlwZSA9IHBhcnQuY2hhckF0KDApO1xuXG4gICAgICAgICAgICAgICAgICAgIGlmICghdGFnTmFtZSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgdGFnTmFtZSA9IHBhcnQ7XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAodHlwZSA9PT0gXCIuXCIpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGNsYXNzZXMgPSBjbGFzc2VzIHx8IFtdO1xuICAgICAgICAgICAgICAgICAgICAgICAgY2xhc3Nlcy5wdXNoKHBhcnQuc3Vic3RyaW5nKDEsIHBhcnQubGVuZ3RoKSk7XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAodHlwZSA9PT0gXCIjXCIgJiYgbm9JZCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgcHJvcHMuaWQgPSBwYXJ0LnN1YnN0cmluZygxLCBwYXJ0Lmxlbmd0aCk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICBpZiAoY2xhc3Nlcykge1xuICAgICAgICAgICAgICAgICAgICBpZiAocHJvcHMuY2xhc3NOYW1lKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBjbGFzc2VzLnB1c2gocHJvcHMuY2xhc3NOYW1lKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgIHByb3BzLmNsYXNzTmFtZSA9IGNsYXNzZXMuam9pbihcIiBcIik7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgcmV0dXJuIHByb3BzLm5hbWVzcGFjZSA/IHRhZ05hbWUgOiB0YWdOYW1lLnRvVXBwZXJDYXNlKCk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0sIHsgXCJicm93c2VyLXNwbGl0XCI6IDUgfV0sIDI0OiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge1xuICAgICAgICAgICAgdmFyIGlzVk5vZGUgPSByZXF1aXJlKFwiLi9pcy12bm9kZVwiKTtcbiAgICAgICAgICAgIHZhciBpc1ZUZXh0ID0gcmVxdWlyZShcIi4vaXMtdnRleHRcIik7XG4gICAgICAgICAgICB2YXIgaXNXaWRnZXQgPSByZXF1aXJlKFwiLi9pcy13aWRnZXRcIik7XG4gICAgICAgICAgICB2YXIgaXNUaHVuayA9IHJlcXVpcmUoXCIuL2lzLXRodW5rXCIpO1xuXG4gICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IGhhbmRsZVRodW5rO1xuXG4gICAgICAgICAgICBmdW5jdGlvbiBoYW5kbGVUaHVuayhhLCBiKSB7XG4gICAgICAgICAgICAgICAgdmFyIHJlbmRlcmVkQSA9IGE7XG4gICAgICAgICAgICAgICAgdmFyIHJlbmRlcmVkQiA9IGI7XG5cbiAgICAgICAgICAgICAgICBpZiAoaXNUaHVuayhiKSkge1xuICAgICAgICAgICAgICAgICAgICByZW5kZXJlZEIgPSByZW5kZXJUaHVuayhiLCBhKTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICBpZiAoaXNUaHVuayhhKSkge1xuICAgICAgICAgICAgICAgICAgICByZW5kZXJlZEEgPSByZW5kZXJUaHVuayhhLCBudWxsKTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgICAgICAgICBhOiByZW5kZXJlZEEsXG4gICAgICAgICAgICAgICAgICAgIGI6IHJlbmRlcmVkQlxuICAgICAgICAgICAgICAgIH07XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIHJlbmRlclRodW5rKHRodW5rLCBwcmV2aW91cykge1xuICAgICAgICAgICAgICAgIHZhciByZW5kZXJlZFRodW5rID0gdGh1bmsudm5vZGU7XG5cbiAgICAgICAgICAgICAgICBpZiAoIXJlbmRlcmVkVGh1bmspIHtcbiAgICAgICAgICAgICAgICAgICAgcmVuZGVyZWRUaHVuayA9IHRodW5rLnZub2RlID0gdGh1bmsucmVuZGVyKHByZXZpb3VzKTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICBpZiAoIShpc1ZOb2RlKHJlbmRlcmVkVGh1bmspIHx8IGlzVlRleHQocmVuZGVyZWRUaHVuaykgfHwgaXNXaWRnZXQocmVuZGVyZWRUaHVuaykpKSB7XG4gICAgICAgICAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcihcInRodW5rIGRpZCBub3QgcmV0dXJuIGEgdmFsaWQgbm9kZVwiKTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICByZXR1cm4gcmVuZGVyZWRUaHVuaztcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSwgeyBcIi4vaXMtdGh1bmtcIjogMjUsIFwiLi9pcy12bm9kZVwiOiAyNywgXCIuL2lzLXZ0ZXh0XCI6IDI4LCBcIi4vaXMtd2lkZ2V0XCI6IDI5IH1dLCAyNTogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHtcbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gaXNUaHVuaztcblxuICAgICAgICAgICAgZnVuY3Rpb24gaXNUaHVuayh0KSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHQgJiYgdC50eXBlID09PSBcIlRodW5rXCI7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0sIHt9XSwgMjY6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IGlzSG9vaztcblxuICAgICAgICAgICAgZnVuY3Rpb24gaXNIb29rKGhvb2spIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gaG9vayAmJiAodHlwZW9mIGhvb2suaG9vayA9PT0gXCJmdW5jdGlvblwiICYmICFob29rLmhhc093blByb3BlcnR5KFwiaG9va1wiKSB8fCB0eXBlb2YgaG9vay51bmhvb2sgPT09IFwiZnVuY3Rpb25cIiAmJiAhaG9vay5oYXNPd25Qcm9wZXJ0eShcInVuaG9va1wiKSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0sIHt9XSwgMjc6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICB2YXIgdmVyc2lvbiA9IHJlcXVpcmUoXCIuL3ZlcnNpb25cIik7XG5cbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gaXNWaXJ0dWFsTm9kZTtcblxuICAgICAgICAgICAgZnVuY3Rpb24gaXNWaXJ0dWFsTm9kZSh4KSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHggJiYgeC50eXBlID09PSBcIlZpcnR1YWxOb2RlXCIgJiYgeC52ZXJzaW9uID09PSB2ZXJzaW9uO1xuICAgICAgICAgICAgfVxuICAgICAgICB9LCB7IFwiLi92ZXJzaW9uXCI6IDMwIH1dLCAyODogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHtcbiAgICAgICAgICAgIHZhciB2ZXJzaW9uID0gcmVxdWlyZShcIi4vdmVyc2lvblwiKTtcblxuICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBpc1ZpcnR1YWxUZXh0O1xuXG4gICAgICAgICAgICBmdW5jdGlvbiBpc1ZpcnR1YWxUZXh0KHgpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4geCAmJiB4LnR5cGUgPT09IFwiVmlydHVhbFRleHRcIiAmJiB4LnZlcnNpb24gPT09IHZlcnNpb247XG4gICAgICAgICAgICB9XG4gICAgICAgIH0sIHsgXCIuL3ZlcnNpb25cIjogMzAgfV0sIDI5OiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge1xuICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBpc1dpZGdldDtcblxuICAgICAgICAgICAgZnVuY3Rpb24gaXNXaWRnZXQodykge1xuICAgICAgICAgICAgICAgIHJldHVybiB3ICYmIHcudHlwZSA9PT0gXCJXaWRnZXRcIjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSwge31dLCAzMDogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHtcbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gXCIyXCI7XG4gICAgICAgIH0sIHt9XSwgMzE6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICB2YXIgdmVyc2lvbiA9IHJlcXVpcmUoXCIuL3ZlcnNpb25cIik7XG4gICAgICAgICAgICB2YXIgaXNWTm9kZSA9IHJlcXVpcmUoXCIuL2lzLXZub2RlXCIpO1xuICAgICAgICAgICAgdmFyIGlzV2lkZ2V0ID0gcmVxdWlyZShcIi4vaXMtd2lkZ2V0XCIpO1xuICAgICAgICAgICAgdmFyIGlzVGh1bmsgPSByZXF1aXJlKFwiLi9pcy10aHVua1wiKTtcbiAgICAgICAgICAgIHZhciBpc1ZIb29rID0gcmVxdWlyZShcIi4vaXMtdmhvb2tcIik7XG5cbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gVmlydHVhbE5vZGU7XG5cbiAgICAgICAgICAgIHZhciBub1Byb3BlcnRpZXMgPSB7fTtcbiAgICAgICAgICAgIHZhciBub0NoaWxkcmVuID0gW107XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIFZpcnR1YWxOb2RlKHRhZ05hbWUsIHByb3BlcnRpZXMsIGNoaWxkcmVuLCBrZXksIG5hbWVzcGFjZSkge1xuICAgICAgICAgICAgICAgIHRoaXMudGFnTmFtZSA9IHRhZ05hbWU7XG4gICAgICAgICAgICAgICAgdGhpcy5wcm9wZXJ0aWVzID0gcHJvcGVydGllcyB8fCBub1Byb3BlcnRpZXM7XG4gICAgICAgICAgICAgICAgdGhpcy5jaGlsZHJlbiA9IGNoaWxkcmVuIHx8IG5vQ2hpbGRyZW47XG4gICAgICAgICAgICAgICAgdGhpcy5rZXkgPSBrZXkgIT0gbnVsbCA/IFN0cmluZyhrZXkpIDogdW5kZWZpbmVkO1xuICAgICAgICAgICAgICAgIHRoaXMubmFtZXNwYWNlID0gdHlwZW9mIG5hbWVzcGFjZSA9PT0gXCJzdHJpbmdcIiA/IG5hbWVzcGFjZSA6IG51bGw7XG5cbiAgICAgICAgICAgICAgICB2YXIgY291bnQgPSBjaGlsZHJlbiAmJiBjaGlsZHJlbi5sZW5ndGggfHwgMDtcbiAgICAgICAgICAgICAgICB2YXIgZGVzY2VuZGFudHMgPSAwO1xuICAgICAgICAgICAgICAgIHZhciBoYXNXaWRnZXRzID0gZmFsc2U7XG4gICAgICAgICAgICAgICAgdmFyIGhhc1RodW5rcyA9IGZhbHNlO1xuICAgICAgICAgICAgICAgIHZhciBkZXNjZW5kYW50SG9va3MgPSBmYWxzZTtcbiAgICAgICAgICAgICAgICB2YXIgaG9va3M7XG5cbiAgICAgICAgICAgICAgICBmb3IgKHZhciBwcm9wTmFtZSBpbiBwcm9wZXJ0aWVzKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmIChwcm9wZXJ0aWVzLmhhc093blByb3BlcnR5KHByb3BOYW1lKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgdmFyIHByb3BlcnR5ID0gcHJvcGVydGllc1twcm9wTmFtZV07XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoaXNWSG9vayhwcm9wZXJ0eSkgJiYgcHJvcGVydHkudW5ob29rKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKCFob29rcykge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBob29rcyA9IHt9O1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGhvb2tzW3Byb3BOYW1lXSA9IHByb3BlcnR5O1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCBjb3VudDsgaSsrKSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciBjaGlsZCA9IGNoaWxkcmVuW2ldO1xuICAgICAgICAgICAgICAgICAgICBpZiAoaXNWTm9kZShjaGlsZCkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGRlc2NlbmRhbnRzICs9IGNoaWxkLmNvdW50IHx8IDA7XG5cbiAgICAgICAgICAgICAgICAgICAgICAgIGlmICghaGFzV2lkZ2V0cyAmJiBjaGlsZC5oYXNXaWRnZXRzKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaGFzV2lkZ2V0cyA9IHRydWU7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgICAgIGlmICghaGFzVGh1bmtzICYmIGNoaWxkLmhhc1RodW5rcykge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGhhc1RodW5rcyA9IHRydWU7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgICAgIGlmICghZGVzY2VuZGFudEhvb2tzICYmIChjaGlsZC5ob29rcyB8fCBjaGlsZC5kZXNjZW5kYW50SG9va3MpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgZGVzY2VuZGFudEhvb2tzID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIGlmICghaGFzV2lkZ2V0cyAmJiBpc1dpZGdldChjaGlsZCkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmICh0eXBlb2YgY2hpbGQuZGVzdHJveSA9PT0gXCJmdW5jdGlvblwiKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaGFzV2lkZ2V0cyA9IHRydWU7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoIWhhc1RodW5rcyAmJiBpc1RodW5rKGNoaWxkKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgaGFzVGh1bmtzID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHRoaXMuY291bnQgPSBjb3VudCArIGRlc2NlbmRhbnRzO1xuICAgICAgICAgICAgICAgIHRoaXMuaGFzV2lkZ2V0cyA9IGhhc1dpZGdldHM7XG4gICAgICAgICAgICAgICAgdGhpcy5oYXNUaHVua3MgPSBoYXNUaHVua3M7XG4gICAgICAgICAgICAgICAgdGhpcy5ob29rcyA9IGhvb2tzO1xuICAgICAgICAgICAgICAgIHRoaXMuZGVzY2VuZGFudEhvb2tzID0gZGVzY2VuZGFudEhvb2tzO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBWaXJ0dWFsTm9kZS5wcm90b3R5cGUudmVyc2lvbiA9IHZlcnNpb247XG4gICAgICAgICAgICBWaXJ0dWFsTm9kZS5wcm90b3R5cGUudHlwZSA9IFwiVmlydHVhbE5vZGVcIjtcbiAgICAgICAgfSwgeyBcIi4vaXMtdGh1bmtcIjogMjUsIFwiLi9pcy12aG9va1wiOiAyNiwgXCIuL2lzLXZub2RlXCI6IDI3LCBcIi4vaXMtd2lkZ2V0XCI6IDI5LCBcIi4vdmVyc2lvblwiOiAzMCB9XSwgMzI6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICB2YXIgdmVyc2lvbiA9IHJlcXVpcmUoXCIuL3ZlcnNpb25cIik7XG5cbiAgICAgICAgICAgIFZpcnR1YWxQYXRjaC5OT05FID0gMDtcbiAgICAgICAgICAgIFZpcnR1YWxQYXRjaC5WVEVYVCA9IDE7XG4gICAgICAgICAgICBWaXJ0dWFsUGF0Y2guVk5PREUgPSAyO1xuICAgICAgICAgICAgVmlydHVhbFBhdGNoLldJREdFVCA9IDM7XG4gICAgICAgICAgICBWaXJ0dWFsUGF0Y2guUFJPUFMgPSA0O1xuICAgICAgICAgICAgVmlydHVhbFBhdGNoLk9SREVSID0gNTtcbiAgICAgICAgICAgIFZpcnR1YWxQYXRjaC5JTlNFUlQgPSA2O1xuICAgICAgICAgICAgVmlydHVhbFBhdGNoLlJFTU9WRSA9IDc7XG4gICAgICAgICAgICBWaXJ0dWFsUGF0Y2guVEhVTksgPSA4O1xuXG4gICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IFZpcnR1YWxQYXRjaDtcblxuICAgICAgICAgICAgZnVuY3Rpb24gVmlydHVhbFBhdGNoKHR5cGUsIHZOb2RlLCBwYXRjaCkge1xuICAgICAgICAgICAgICAgIHRoaXMudHlwZSA9IE51bWJlcih0eXBlKTtcbiAgICAgICAgICAgICAgICB0aGlzLnZOb2RlID0gdk5vZGU7XG4gICAgICAgICAgICAgICAgdGhpcy5wYXRjaCA9IHBhdGNoO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBWaXJ0dWFsUGF0Y2gucHJvdG90eXBlLnZlcnNpb24gPSB2ZXJzaW9uO1xuICAgICAgICAgICAgVmlydHVhbFBhdGNoLnByb3RvdHlwZS50eXBlID0gXCJWaXJ0dWFsUGF0Y2hcIjtcbiAgICAgICAgfSwgeyBcIi4vdmVyc2lvblwiOiAzMCB9XSwgMzM6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICB2YXIgdmVyc2lvbiA9IHJlcXVpcmUoXCIuL3ZlcnNpb25cIik7XG5cbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gVmlydHVhbFRleHQ7XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIFZpcnR1YWxUZXh0KHRleHQpIHtcbiAgICAgICAgICAgICAgICB0aGlzLnRleHQgPSBTdHJpbmcodGV4dCk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIFZpcnR1YWxUZXh0LnByb3RvdHlwZS52ZXJzaW9uID0gdmVyc2lvbjtcbiAgICAgICAgICAgIFZpcnR1YWxUZXh0LnByb3RvdHlwZS50eXBlID0gXCJWaXJ0dWFsVGV4dFwiO1xuICAgICAgICB9LCB7IFwiLi92ZXJzaW9uXCI6IDMwIH1dLCAzNDogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHtcbiAgICAgICAgICAgIHZhciBpc09iamVjdCA9IHJlcXVpcmUoXCJpcy1vYmplY3RcIik7XG4gICAgICAgICAgICB2YXIgaXNIb29rID0gcmVxdWlyZShcIi4uL3Zub2RlL2lzLXZob29rXCIpO1xuXG4gICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IGRpZmZQcm9wcztcblxuICAgICAgICAgICAgZnVuY3Rpb24gZGlmZlByb3BzKGEsIGIpIHtcbiAgICAgICAgICAgICAgICB2YXIgZGlmZjtcblxuICAgICAgICAgICAgICAgIGZvciAodmFyIGFLZXkgaW4gYSkge1xuICAgICAgICAgICAgICAgICAgICBpZiAoIShhS2V5IGluIGIpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBkaWZmID0gZGlmZiB8fCB7fTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGRpZmZbYUtleV0gPSB1bmRlZmluZWQ7XG4gICAgICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgICAgICB2YXIgYVZhbHVlID0gYVthS2V5XTtcbiAgICAgICAgICAgICAgICAgICAgdmFyIGJWYWx1ZSA9IGJbYUtleV07XG5cbiAgICAgICAgICAgICAgICAgICAgaWYgKGFWYWx1ZSA9PT0gYlZhbHVlKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBjb250aW51ZTtcbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIGlmIChpc09iamVjdChhVmFsdWUpICYmIGlzT2JqZWN0KGJWYWx1ZSkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChnZXRQcm90b3R5cGUoYlZhbHVlKSAhPT0gZ2V0UHJvdG90eXBlKGFWYWx1ZSkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBkaWZmID0gZGlmZiB8fCB7fTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBkaWZmW2FLZXldID0gYlZhbHVlO1xuICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIGlmIChpc0hvb2soYlZhbHVlKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRpZmYgPSBkaWZmIHx8IHt9O1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRpZmZbYUtleV0gPSBiVmFsdWU7XG4gICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZhciBvYmplY3REaWZmID0gZGlmZlByb3BzKGFWYWx1ZSwgYlZhbHVlKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAob2JqZWN0RGlmZikge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBkaWZmID0gZGlmZiB8fCB7fTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZGlmZlthS2V5XSA9IG9iamVjdERpZmY7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgZGlmZiA9IGRpZmYgfHwge307XG4gICAgICAgICAgICAgICAgICAgICAgICBkaWZmW2FLZXldID0gYlZhbHVlO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgZm9yICh2YXIgYktleSBpbiBiKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmICghKGJLZXkgaW4gYSkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGRpZmYgPSBkaWZmIHx8IHt9O1xuICAgICAgICAgICAgICAgICAgICAgICAgZGlmZltiS2V5XSA9IGJbYktleV07XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICByZXR1cm4gZGlmZjtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZnVuY3Rpb24gZ2V0UHJvdG90eXBlKHZhbHVlKSB7XG4gICAgICAgICAgICAgICAgaWYgKE9iamVjdC5nZXRQcm90b3R5cGVPZikge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gT2JqZWN0LmdldFByb3RvdHlwZU9mKHZhbHVlKTtcbiAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKHZhbHVlLl9fcHJvdG9fXykge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gdmFsdWUuX19wcm90b19fO1xuICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAodmFsdWUuY29uc3RydWN0b3IpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHZhbHVlLmNvbnN0cnVjdG9yLnByb3RvdHlwZTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH0sIHsgXCIuLi92bm9kZS9pcy12aG9va1wiOiAyNiwgXCJpcy1vYmplY3RcIjogMTEgfV0sIDM1OiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge1xuICAgICAgICAgICAgdmFyIGlzQXJyYXkgPSByZXF1aXJlKFwieC1pcy1hcnJheVwiKTtcblxuICAgICAgICAgICAgdmFyIFZQYXRjaCA9IHJlcXVpcmUoXCIuLi92bm9kZS92cGF0Y2hcIik7XG4gICAgICAgICAgICB2YXIgaXNWTm9kZSA9IHJlcXVpcmUoXCIuLi92bm9kZS9pcy12bm9kZVwiKTtcbiAgICAgICAgICAgIHZhciBpc1ZUZXh0ID0gcmVxdWlyZShcIi4uL3Zub2RlL2lzLXZ0ZXh0XCIpO1xuICAgICAgICAgICAgdmFyIGlzV2lkZ2V0ID0gcmVxdWlyZShcIi4uL3Zub2RlL2lzLXdpZGdldFwiKTtcbiAgICAgICAgICAgIHZhciBpc1RodW5rID0gcmVxdWlyZShcIi4uL3Zub2RlL2lzLXRodW5rXCIpO1xuICAgICAgICAgICAgdmFyIGhhbmRsZVRodW5rID0gcmVxdWlyZShcIi4uL3Zub2RlL2hhbmRsZS10aHVua1wiKTtcblxuICAgICAgICAgICAgdmFyIGRpZmZQcm9wcyA9IHJlcXVpcmUoXCIuL2RpZmYtcHJvcHNcIik7XG5cbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gZGlmZjtcblxuICAgICAgICAgICAgZnVuY3Rpb24gZGlmZihhLCBiKSB7XG4gICAgICAgICAgICAgICAgdmFyIHBhdGNoID0geyBhOiBhIH07XG4gICAgICAgICAgICAgICAgd2FsayhhLCBiLCBwYXRjaCwgMCk7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHBhdGNoO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBmdW5jdGlvbiB3YWxrKGEsIGIsIHBhdGNoLCBpbmRleCkge1xuICAgICAgICAgICAgICAgIGlmIChhID09PSBiKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICB2YXIgYXBwbHkgPSBwYXRjaFtpbmRleF07XG4gICAgICAgICAgICAgICAgdmFyIGFwcGx5Q2xlYXIgPSBmYWxzZTtcblxuICAgICAgICAgICAgICAgIGlmIChpc1RodW5rKGEpIHx8IGlzVGh1bmsoYikpIHtcbiAgICAgICAgICAgICAgICAgICAgdGh1bmtzKGEsIGIsIHBhdGNoLCBpbmRleCk7XG4gICAgICAgICAgICAgICAgfSBlbHNlIGlmIChiID09IG51bGwpIHtcblxuICAgICAgICAgICAgICAgICAgICAvLyBJZiBhIGlzIGEgd2lkZ2V0IHdlIHdpbGwgYWRkIGEgcmVtb3ZlIHBhdGNoIGZvciBpdFxuICAgICAgICAgICAgICAgICAgICAvLyBPdGhlcndpc2UgYW55IGNoaWxkIHdpZGdldHMvaG9va3MgbXVzdCBiZSBkZXN0cm95ZWQuXG4gICAgICAgICAgICAgICAgICAgIC8vIFRoaXMgcHJldmVudHMgYWRkaW5nIHR3byByZW1vdmUgcGF0Y2hlcyBmb3IgYSB3aWRnZXQuXG4gICAgICAgICAgICAgICAgICAgIGlmICghaXNXaWRnZXQoYSkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGNsZWFyU3RhdGUoYSwgcGF0Y2gsIGluZGV4KTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGFwcGx5ID0gcGF0Y2hbaW5kZXhdO1xuICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgYXBwbHkgPSBhcHBlbmRQYXRjaChhcHBseSwgbmV3IFZQYXRjaChWUGF0Y2guUkVNT1ZFLCBhLCBiKSk7XG4gICAgICAgICAgICAgICAgfSBlbHNlIGlmIChpc1ZOb2RlKGIpKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmIChpc1ZOb2RlKGEpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoYS50YWdOYW1lID09PSBiLnRhZ05hbWUgJiYgYS5uYW1lc3BhY2UgPT09IGIubmFtZXNwYWNlICYmIGEua2V5ID09PSBiLmtleSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZhciBwcm9wc1BhdGNoID0gZGlmZlByb3BzKGEucHJvcGVydGllcywgYi5wcm9wZXJ0aWVzKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAocHJvcHNQYXRjaCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBhcHBseSA9IGFwcGVuZFBhdGNoKGFwcGx5LCBuZXcgVlBhdGNoKFZQYXRjaC5QUk9QUywgYSwgcHJvcHNQYXRjaCkpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBhcHBseSA9IGRpZmZDaGlsZHJlbihhLCBiLCBwYXRjaCwgYXBwbHksIGluZGV4KTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgYXBwbHkgPSBhcHBlbmRQYXRjaChhcHBseSwgbmV3IFZQYXRjaChWUGF0Y2guVk5PREUsIGEsIGIpKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBhcHBseUNsZWFyID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGFwcGx5ID0gYXBwZW5kUGF0Y2goYXBwbHksIG5ldyBWUGF0Y2goVlBhdGNoLlZOT0RFLCBhLCBiKSk7XG4gICAgICAgICAgICAgICAgICAgICAgICBhcHBseUNsZWFyID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoaXNWVGV4dChiKSkge1xuICAgICAgICAgICAgICAgICAgICBpZiAoIWlzVlRleHQoYSkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGFwcGx5ID0gYXBwZW5kUGF0Y2goYXBwbHksIG5ldyBWUGF0Y2goVlBhdGNoLlZURVhULCBhLCBiKSk7XG4gICAgICAgICAgICAgICAgICAgICAgICBhcHBseUNsZWFyID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIGlmIChhLnRleHQgIT09IGIudGV4dCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgYXBwbHkgPSBhcHBlbmRQYXRjaChhcHBseSwgbmV3IFZQYXRjaChWUGF0Y2guVlRFWFQsIGEsIGIpKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoaXNXaWRnZXQoYikpIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKCFpc1dpZGdldChhKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgYXBwbHlDbGVhciA9IHRydWU7XG4gICAgICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgICAgICBhcHBseSA9IGFwcGVuZFBhdGNoKGFwcGx5LCBuZXcgVlBhdGNoKFZQYXRjaC5XSURHRVQsIGEsIGIpKTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICBpZiAoYXBwbHkpIHtcbiAgICAgICAgICAgICAgICAgICAgcGF0Y2hbaW5kZXhdID0gYXBwbHk7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgaWYgKGFwcGx5Q2xlYXIpIHtcbiAgICAgICAgICAgICAgICAgICAgY2xlYXJTdGF0ZShhLCBwYXRjaCwgaW5kZXgpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZnVuY3Rpb24gZGlmZkNoaWxkcmVuKGEsIGIsIHBhdGNoLCBhcHBseSwgaW5kZXgpIHtcbiAgICAgICAgICAgICAgICB2YXIgYUNoaWxkcmVuID0gYS5jaGlsZHJlbjtcbiAgICAgICAgICAgICAgICB2YXIgb3JkZXJlZFNldCA9IHJlb3JkZXIoYUNoaWxkcmVuLCBiLmNoaWxkcmVuKTtcbiAgICAgICAgICAgICAgICB2YXIgYkNoaWxkcmVuID0gb3JkZXJlZFNldC5jaGlsZHJlbjtcblxuICAgICAgICAgICAgICAgIHZhciBhTGVuID0gYUNoaWxkcmVuLmxlbmd0aDtcbiAgICAgICAgICAgICAgICB2YXIgYkxlbiA9IGJDaGlsZHJlbi5sZW5ndGg7XG4gICAgICAgICAgICAgICAgdmFyIGxlbiA9IGFMZW4gPiBiTGVuID8gYUxlbiA6IGJMZW47XG5cbiAgICAgICAgICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IGxlbjsgaSsrKSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciBsZWZ0Tm9kZSA9IGFDaGlsZHJlbltpXTtcbiAgICAgICAgICAgICAgICAgICAgdmFyIHJpZ2h0Tm9kZSA9IGJDaGlsZHJlbltpXTtcbiAgICAgICAgICAgICAgICAgICAgaW5kZXggKz0gMTtcblxuICAgICAgICAgICAgICAgICAgICBpZiAoIWxlZnROb2RlKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAocmlnaHROb2RlKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gRXhjZXNzIG5vZGVzIGluIGIgbmVlZCB0byBiZSBhZGRlZFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGFwcGx5ID0gYXBwZW5kUGF0Y2goYXBwbHksIG5ldyBWUGF0Y2goVlBhdGNoLklOU0VSVCwgbnVsbCwgcmlnaHROb2RlKSk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICB3YWxrKGxlZnROb2RlLCByaWdodE5vZGUsIHBhdGNoLCBpbmRleCk7XG4gICAgICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgICAgICBpZiAoaXNWTm9kZShsZWZ0Tm9kZSkgJiYgbGVmdE5vZGUuY291bnQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGluZGV4ICs9IGxlZnROb2RlLmNvdW50O1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgaWYgKG9yZGVyZWRTZXQubW92ZXMpIHtcbiAgICAgICAgICAgICAgICAgICAgLy8gUmVvcmRlciBub2RlcyBsYXN0XG4gICAgICAgICAgICAgICAgICAgIGFwcGx5ID0gYXBwZW5kUGF0Y2goYXBwbHksIG5ldyBWUGF0Y2goVlBhdGNoLk9SREVSLCBhLCBvcmRlcmVkU2V0Lm1vdmVzKSk7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgcmV0dXJuIGFwcGx5O1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBmdW5jdGlvbiBjbGVhclN0YXRlKHZOb2RlLCBwYXRjaCwgaW5kZXgpIHtcbiAgICAgICAgICAgICAgICAvLyBUT0RPOiBNYWtlIHRoaXMgYSBzaW5nbGUgd2Fsaywgbm90IHR3b1xuICAgICAgICAgICAgICAgIHVuaG9vayh2Tm9kZSwgcGF0Y2gsIGluZGV4KTtcbiAgICAgICAgICAgICAgICBkZXN0cm95V2lkZ2V0cyh2Tm9kZSwgcGF0Y2gsIGluZGV4KTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgLy8gUGF0Y2ggcmVjb3JkcyBmb3IgYWxsIGRlc3Ryb3llZCB3aWRnZXRzIG11c3QgYmUgYWRkZWQgYmVjYXVzZSB3ZSBuZWVkXG4gICAgICAgICAgICAvLyBhIERPTSBub2RlIHJlZmVyZW5jZSBmb3IgdGhlIGRlc3Ryb3kgZnVuY3Rpb25cbiAgICAgICAgICAgIGZ1bmN0aW9uIGRlc3Ryb3lXaWRnZXRzKHZOb2RlLCBwYXRjaCwgaW5kZXgpIHtcbiAgICAgICAgICAgICAgICBpZiAoaXNXaWRnZXQodk5vZGUpKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmICh0eXBlb2Ygdk5vZGUuZGVzdHJveSA9PT0gXCJmdW5jdGlvblwiKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBwYXRjaFtpbmRleF0gPSBhcHBlbmRQYXRjaChwYXRjaFtpbmRleF0sIG5ldyBWUGF0Y2goVlBhdGNoLlJFTU9WRSwgdk5vZGUsIG51bGwpKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoaXNWTm9kZSh2Tm9kZSkgJiYgKHZOb2RlLmhhc1dpZGdldHMgfHwgdk5vZGUuaGFzVGh1bmtzKSkge1xuICAgICAgICAgICAgICAgICAgICB2YXIgY2hpbGRyZW4gPSB2Tm9kZS5jaGlsZHJlbjtcbiAgICAgICAgICAgICAgICAgICAgdmFyIGxlbiA9IGNoaWxkcmVuLmxlbmd0aDtcbiAgICAgICAgICAgICAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCBsZW47IGkrKykge1xuICAgICAgICAgICAgICAgICAgICAgICAgdmFyIGNoaWxkID0gY2hpbGRyZW5baV07XG4gICAgICAgICAgICAgICAgICAgICAgICBpbmRleCArPSAxO1xuXG4gICAgICAgICAgICAgICAgICAgICAgICBkZXN0cm95V2lkZ2V0cyhjaGlsZCwgcGF0Y2gsIGluZGV4KTtcblxuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGlzVk5vZGUoY2hpbGQpICYmIGNoaWxkLmNvdW50KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaW5kZXggKz0gY2hpbGQuY291bnQ7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKGlzVGh1bmsodk5vZGUpKSB7XG4gICAgICAgICAgICAgICAgICAgIHRodW5rcyh2Tm9kZSwgbnVsbCwgcGF0Y2gsIGluZGV4KTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIC8vIENyZWF0ZSBhIHN1Yi1wYXRjaCBmb3IgdGh1bmtzXG4gICAgICAgICAgICBmdW5jdGlvbiB0aHVua3MoYSwgYiwgcGF0Y2gsIGluZGV4KSB7XG4gICAgICAgICAgICAgICAgdmFyIG5vZGVzID0gaGFuZGxlVGh1bmsoYSwgYik7XG4gICAgICAgICAgICAgICAgdmFyIHRodW5rUGF0Y2ggPSBkaWZmKG5vZGVzLmEsIG5vZGVzLmIpO1xuICAgICAgICAgICAgICAgIGlmIChoYXNQYXRjaGVzKHRodW5rUGF0Y2gpKSB7XG4gICAgICAgICAgICAgICAgICAgIHBhdGNoW2luZGV4XSA9IG5ldyBWUGF0Y2goVlBhdGNoLlRIVU5LLCBudWxsLCB0aHVua1BhdGNoKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIGhhc1BhdGNoZXMocGF0Y2gpIHtcbiAgICAgICAgICAgICAgICBmb3IgKHZhciBpbmRleCBpbiBwYXRjaCkge1xuICAgICAgICAgICAgICAgICAgICBpZiAoaW5kZXggIT09IFwiYVwiKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgLy8gRXhlY3V0ZSBob29rcyB3aGVuIHR3byBub2RlcyBhcmUgaWRlbnRpY2FsXG4gICAgICAgICAgICBmdW5jdGlvbiB1bmhvb2sodk5vZGUsIHBhdGNoLCBpbmRleCkge1xuICAgICAgICAgICAgICAgIGlmIChpc1ZOb2RlKHZOb2RlKSkge1xuICAgICAgICAgICAgICAgICAgICBpZiAodk5vZGUuaG9va3MpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHBhdGNoW2luZGV4XSA9IGFwcGVuZFBhdGNoKHBhdGNoW2luZGV4XSwgbmV3IFZQYXRjaChWUGF0Y2guUFJPUFMsIHZOb2RlLCB1bmRlZmluZWRLZXlzKHZOb2RlLmhvb2tzKSkpO1xuICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgaWYgKHZOb2RlLmRlc2NlbmRhbnRIb29rcyB8fCB2Tm9kZS5oYXNUaHVua3MpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHZhciBjaGlsZHJlbiA9IHZOb2RlLmNoaWxkcmVuO1xuICAgICAgICAgICAgICAgICAgICAgICAgdmFyIGxlbiA9IGNoaWxkcmVuLmxlbmd0aDtcbiAgICAgICAgICAgICAgICAgICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgbGVuOyBpKyspIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB2YXIgY2hpbGQgPSBjaGlsZHJlbltpXTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpbmRleCArPSAxO1xuXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdW5ob29rKGNoaWxkLCBwYXRjaCwgaW5kZXgpO1xuXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGlzVk5vZGUoY2hpbGQpICYmIGNoaWxkLmNvdW50KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGluZGV4ICs9IGNoaWxkLmNvdW50O1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoaXNUaHVuayh2Tm9kZSkpIHtcbiAgICAgICAgICAgICAgICAgICAgdGh1bmtzKHZOb2RlLCBudWxsLCBwYXRjaCwgaW5kZXgpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZnVuY3Rpb24gdW5kZWZpbmVkS2V5cyhvYmopIHtcbiAgICAgICAgICAgICAgICB2YXIgcmVzdWx0ID0ge307XG5cbiAgICAgICAgICAgICAgICBmb3IgKHZhciBrZXkgaW4gb2JqKSB7XG4gICAgICAgICAgICAgICAgICAgIHJlc3VsdFtrZXldID0gdW5kZWZpbmVkO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHJldHVybiByZXN1bHQ7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIC8vIExpc3QgZGlmZiwgbmFpdmUgbGVmdCB0byByaWdodCByZW9yZGVyaW5nXG4gICAgICAgICAgICBmdW5jdGlvbiByZW9yZGVyKGFDaGlsZHJlbiwgYkNoaWxkcmVuKSB7XG4gICAgICAgICAgICAgICAgLy8gTyhNKSB0aW1lLCBPKE0pIG1lbW9yeVxuICAgICAgICAgICAgICAgIHZhciBiQ2hpbGRJbmRleCA9IGtleUluZGV4KGJDaGlsZHJlbik7XG4gICAgICAgICAgICAgICAgdmFyIGJLZXlzID0gYkNoaWxkSW5kZXgua2V5cztcbiAgICAgICAgICAgICAgICB2YXIgYkZyZWUgPSBiQ2hpbGRJbmRleC5mcmVlO1xuXG4gICAgICAgICAgICAgICAgaWYgKGJGcmVlLmxlbmd0aCA9PT0gYkNoaWxkcmVuLmxlbmd0aCkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgICAgICAgICAgICAgY2hpbGRyZW46IGJDaGlsZHJlbixcbiAgICAgICAgICAgICAgICAgICAgICAgIG1vdmVzOiBudWxsXG4gICAgICAgICAgICAgICAgICAgIH07XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgLy8gTyhOKSB0aW1lLCBPKE4pIG1lbW9yeVxuICAgICAgICAgICAgICAgIHZhciBhQ2hpbGRJbmRleCA9IGtleUluZGV4KGFDaGlsZHJlbik7XG4gICAgICAgICAgICAgICAgdmFyIGFLZXlzID0gYUNoaWxkSW5kZXgua2V5cztcbiAgICAgICAgICAgICAgICB2YXIgYUZyZWUgPSBhQ2hpbGRJbmRleC5mcmVlO1xuXG4gICAgICAgICAgICAgICAgaWYgKGFGcmVlLmxlbmd0aCA9PT0gYUNoaWxkcmVuLmxlbmd0aCkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgICAgICAgICAgICAgY2hpbGRyZW46IGJDaGlsZHJlbixcbiAgICAgICAgICAgICAgICAgICAgICAgIG1vdmVzOiBudWxsXG4gICAgICAgICAgICAgICAgICAgIH07XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgLy8gTyhNQVgoTiwgTSkpIG1lbW9yeVxuICAgICAgICAgICAgICAgIHZhciBuZXdDaGlsZHJlbiA9IFtdO1xuXG4gICAgICAgICAgICAgICAgdmFyIGZyZWVJbmRleCA9IDA7XG4gICAgICAgICAgICAgICAgdmFyIGZyZWVDb3VudCA9IGJGcmVlLmxlbmd0aDtcbiAgICAgICAgICAgICAgICB2YXIgZGVsZXRlZEl0ZW1zID0gMDtcblxuICAgICAgICAgICAgICAgIC8vIEl0ZXJhdGUgdGhyb3VnaCBhIGFuZCBtYXRjaCBhIG5vZGUgaW4gYlxuICAgICAgICAgICAgICAgIC8vIE8oTikgdGltZSxcbiAgICAgICAgICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IGFDaGlsZHJlbi5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgICAgICAgICB2YXIgYUl0ZW0gPSBhQ2hpbGRyZW5baV07XG4gICAgICAgICAgICAgICAgICAgIHZhciBpdGVtSW5kZXg7XG5cbiAgICAgICAgICAgICAgICAgICAgaWYgKGFJdGVtLmtleSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGJLZXlzLmhhc093blByb3BlcnR5KGFJdGVtLmtleSkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBNYXRjaCB1cCB0aGUgb2xkIGtleXNcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpdGVtSW5kZXggPSBiS2V5c1thSXRlbS5rZXldO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIG5ld0NoaWxkcmVuLnB1c2goYkNoaWxkcmVuW2l0ZW1JbmRleF0pO1xuICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBSZW1vdmUgb2xkIGtleWVkIGl0ZW1zXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaXRlbUluZGV4ID0gaSAtIGRlbGV0ZWRJdGVtcysrO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIG5ld0NoaWxkcmVuLnB1c2gobnVsbCk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAvLyBNYXRjaCB0aGUgaXRlbSBpbiBhIHdpdGggdGhlIG5leHQgZnJlZSBpdGVtIGluIGJcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChmcmVlSW5kZXggPCBmcmVlQ291bnQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpdGVtSW5kZXggPSBiRnJlZVtmcmVlSW5kZXgrK107XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgbmV3Q2hpbGRyZW4ucHVzaChiQ2hpbGRyZW5baXRlbUluZGV4XSk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIFRoZXJlIGFyZSBubyBmcmVlIGl0ZW1zIGluIGIgdG8gbWF0Y2ggd2l0aFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIHRoZSBmcmVlIGl0ZW1zIGluIGEsIHNvIHRoZSBleHRyYSBmcmVlIG5vZGVzXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gYXJlIGRlbGV0ZWQuXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaXRlbUluZGV4ID0gaSAtIGRlbGV0ZWRJdGVtcysrO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIG5ld0NoaWxkcmVuLnB1c2gobnVsbCk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICB2YXIgbGFzdEZyZWVJbmRleCA9IGZyZWVJbmRleCA+PSBiRnJlZS5sZW5ndGggPyBiQ2hpbGRyZW4ubGVuZ3RoIDogYkZyZWVbZnJlZUluZGV4XTtcblxuICAgICAgICAgICAgICAgIC8vIEl0ZXJhdGUgdGhyb3VnaCBiIGFuZCBhcHBlbmQgYW55IG5ldyBrZXlzXG4gICAgICAgICAgICAgICAgLy8gTyhNKSB0aW1lXG4gICAgICAgICAgICAgICAgZm9yICh2YXIgaiA9IDA7IGogPCBiQ2hpbGRyZW4ubGVuZ3RoOyBqKyspIHtcbiAgICAgICAgICAgICAgICAgICAgdmFyIG5ld0l0ZW0gPSBiQ2hpbGRyZW5bal07XG5cbiAgICAgICAgICAgICAgICAgICAgaWYgKG5ld0l0ZW0ua2V5KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoIWFLZXlzLmhhc093blByb3BlcnR5KG5ld0l0ZW0ua2V5KSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIEFkZCBhbnkgbmV3IGtleWVkIGl0ZW1zXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gV2UgYXJlIGFkZGluZyBuZXcgaXRlbXMgdG8gdGhlIGVuZCBhbmQgdGhlbiBzb3J0aW5nIHRoZW1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBpbiBwbGFjZS4gSW4gZnV0dXJlIHdlIHNob3VsZCBpbnNlcnQgbmV3IGl0ZW1zIGluIHBsYWNlLlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIG5ld0NoaWxkcmVuLnB1c2gobmV3SXRlbSk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoaiA+PSBsYXN0RnJlZUluZGV4KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAvLyBBZGQgYW55IGxlZnRvdmVyIG5vbi1rZXllZCBpdGVtc1xuICAgICAgICAgICAgICAgICAgICAgICAgbmV3Q2hpbGRyZW4ucHVzaChuZXdJdGVtKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHZhciBzaW11bGF0ZSA9IG5ld0NoaWxkcmVuLnNsaWNlKCk7XG4gICAgICAgICAgICAgICAgdmFyIHNpbXVsYXRlSW5kZXggPSAwO1xuICAgICAgICAgICAgICAgIHZhciByZW1vdmVzID0gW107XG4gICAgICAgICAgICAgICAgdmFyIGluc2VydHMgPSBbXTtcbiAgICAgICAgICAgICAgICB2YXIgc2ltdWxhdGVJdGVtO1xuXG4gICAgICAgICAgICAgICAgZm9yICh2YXIgayA9IDA7IGsgPCBiQ2hpbGRyZW4ubGVuZ3RoOykge1xuICAgICAgICAgICAgICAgICAgICB2YXIgd2FudGVkSXRlbSA9IGJDaGlsZHJlbltrXTtcbiAgICAgICAgICAgICAgICAgICAgc2ltdWxhdGVJdGVtID0gc2ltdWxhdGVbc2ltdWxhdGVJbmRleF07XG5cbiAgICAgICAgICAgICAgICAgICAgLy8gcmVtb3ZlIGl0ZW1zXG4gICAgICAgICAgICAgICAgICAgIHdoaWxlIChzaW11bGF0ZUl0ZW0gPT09IG51bGwgJiYgc2ltdWxhdGUubGVuZ3RoKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICByZW1vdmVzLnB1c2gocmVtb3ZlKHNpbXVsYXRlLCBzaW11bGF0ZUluZGV4LCBudWxsKSk7XG4gICAgICAgICAgICAgICAgICAgICAgICBzaW11bGF0ZUl0ZW0gPSBzaW11bGF0ZVtzaW11bGF0ZUluZGV4XTtcbiAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgIGlmICghc2ltdWxhdGVJdGVtIHx8IHNpbXVsYXRlSXRlbS5rZXkgIT09IHdhbnRlZEl0ZW0ua2V5KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAvLyBpZiB3ZSBuZWVkIGEga2V5IGluIHRoaXMgcG9zaXRpb24uLi5cbiAgICAgICAgICAgICAgICAgICAgICAgIGlmICh3YW50ZWRJdGVtLmtleSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChzaW11bGF0ZUl0ZW0gJiYgc2ltdWxhdGVJdGVtLmtleSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBpZiBhbiBpbnNlcnQgZG9lc24ndCBwdXQgdGhpcyBrZXkgaW4gcGxhY2UsIGl0IG5lZWRzIHRvIG1vdmVcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGJLZXlzW3NpbXVsYXRlSXRlbS5rZXldICE9PSBrICsgMSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmVtb3Zlcy5wdXNoKHJlbW92ZShzaW11bGF0ZSwgc2ltdWxhdGVJbmRleCwgc2ltdWxhdGVJdGVtLmtleSkpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc2ltdWxhdGVJdGVtID0gc2ltdWxhdGVbc2ltdWxhdGVJbmRleF07XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBpZiB0aGUgcmVtb3ZlIGRpZG4ndCBwdXQgdGhlIHdhbnRlZCBpdGVtIGluIHBsYWNlLCB3ZSBuZWVkIHRvIGluc2VydCBpdFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKCFzaW11bGF0ZUl0ZW0gfHwgc2ltdWxhdGVJdGVtLmtleSAhPT0gd2FudGVkSXRlbS5rZXkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpbnNlcnRzLnB1c2goeyBrZXk6IHdhbnRlZEl0ZW0ua2V5LCB0bzogayB9KTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIGl0ZW1zIGFyZSBtYXRjaGluZywgc28gc2tpcCBhaGVhZFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc2ltdWxhdGVJbmRleCsrO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaW5zZXJ0cy5wdXNoKHsga2V5OiB3YW50ZWRJdGVtLmtleSwgdG86IGsgfSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpbnNlcnRzLnB1c2goeyBrZXk6IHdhbnRlZEl0ZW0ua2V5LCB0bzogayB9KTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaysrO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgLy8gYSBrZXkgaW4gc2ltdWxhdGUgaGFzIG5vIG1hdGNoaW5nIHdhbnRlZCBrZXksIHJlbW92ZSBpdFxuICAgICAgICAgICAgICAgICAgICAgICAgZWxzZSBpZiAoc2ltdWxhdGVJdGVtICYmIHNpbXVsYXRlSXRlbS5rZXkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICByZW1vdmVzLnB1c2gocmVtb3ZlKHNpbXVsYXRlLCBzaW11bGF0ZUluZGV4LCBzaW11bGF0ZUl0ZW0ua2V5KSk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBzaW11bGF0ZUluZGV4Kys7XG4gICAgICAgICAgICAgICAgICAgICAgICBrKys7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAvLyByZW1vdmUgYWxsIHRoZSByZW1haW5pbmcgbm9kZXMgZnJvbSBzaW11bGF0ZVxuICAgICAgICAgICAgICAgIHdoaWxlIChzaW11bGF0ZUluZGV4IDwgc2ltdWxhdGUubGVuZ3RoKSB7XG4gICAgICAgICAgICAgICAgICAgIHNpbXVsYXRlSXRlbSA9IHNpbXVsYXRlW3NpbXVsYXRlSW5kZXhdO1xuICAgICAgICAgICAgICAgICAgICByZW1vdmVzLnB1c2gocmVtb3ZlKHNpbXVsYXRlLCBzaW11bGF0ZUluZGV4LCBzaW11bGF0ZUl0ZW0gJiYgc2ltdWxhdGVJdGVtLmtleSkpO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIC8vIElmIHRoZSBvbmx5IG1vdmVzIHdlIGhhdmUgYXJlIGRlbGV0ZXMgdGhlbiB3ZSBjYW4ganVzdFxuICAgICAgICAgICAgICAgIC8vIGxldCB0aGUgZGVsZXRlIHBhdGNoIHJlbW92ZSB0aGVzZSBpdGVtcy5cbiAgICAgICAgICAgICAgICBpZiAocmVtb3Zlcy5sZW5ndGggPT09IGRlbGV0ZWRJdGVtcyAmJiAhaW5zZXJ0cy5sZW5ndGgpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGNoaWxkcmVuOiBuZXdDaGlsZHJlbixcbiAgICAgICAgICAgICAgICAgICAgICAgIG1vdmVzOiBudWxsXG4gICAgICAgICAgICAgICAgICAgIH07XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgICAgICAgICAgY2hpbGRyZW46IG5ld0NoaWxkcmVuLFxuICAgICAgICAgICAgICAgICAgICBtb3Zlczoge1xuICAgICAgICAgICAgICAgICAgICAgICAgcmVtb3ZlczogcmVtb3ZlcyxcbiAgICAgICAgICAgICAgICAgICAgICAgIGluc2VydHM6IGluc2VydHNcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH07XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIHJlbW92ZShhcnIsIGluZGV4LCBrZXkpIHtcbiAgICAgICAgICAgICAgICBhcnIuc3BsaWNlKGluZGV4LCAxKTtcblxuICAgICAgICAgICAgICAgIHJldHVybiB7XG4gICAgICAgICAgICAgICAgICAgIGZyb206IGluZGV4LFxuICAgICAgICAgICAgICAgICAgICBrZXk6IGtleVxuICAgICAgICAgICAgICAgIH07XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIGtleUluZGV4KGNoaWxkcmVuKSB7XG4gICAgICAgICAgICAgICAgdmFyIGtleXMgPSB7fTtcbiAgICAgICAgICAgICAgICB2YXIgZnJlZSA9IFtdO1xuICAgICAgICAgICAgICAgIHZhciBsZW5ndGggPSBjaGlsZHJlbi5sZW5ndGg7XG5cbiAgICAgICAgICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IGxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciBjaGlsZCA9IGNoaWxkcmVuW2ldO1xuXG4gICAgICAgICAgICAgICAgICAgIGlmIChjaGlsZC5rZXkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGtleXNbY2hpbGQua2V5XSA9IGk7XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBmcmVlLnB1c2goaSk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgICAgICAgICBrZXlzOiBrZXlzLCAvLyBBIGhhc2ggb2Yga2V5IG5hbWUgdG8gaW5kZXhcbiAgICAgICAgICAgICAgICAgICAgZnJlZTogZnJlZSAvLyBBbiBhcnJheSBvZiB1bmtleWVkIGl0ZW0gaW5kaWNlc1xuICAgICAgICAgICAgICAgIH07XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIGFwcGVuZFBhdGNoKGFwcGx5LCBwYXRjaCkge1xuICAgICAgICAgICAgICAgIGlmIChhcHBseSkge1xuICAgICAgICAgICAgICAgICAgICBpZiAoaXNBcnJheShhcHBseSkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGFwcGx5LnB1c2gocGF0Y2gpO1xuICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgYXBwbHkgPSBbYXBwbHksIHBhdGNoXTtcbiAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBhcHBseTtcbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gcGF0Y2g7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9LCB7IFwiLi4vdm5vZGUvaGFuZGxlLXRodW5rXCI6IDI0LCBcIi4uL3Zub2RlL2lzLXRodW5rXCI6IDI1LCBcIi4uL3Zub2RlL2lzLXZub2RlXCI6IDI3LCBcIi4uL3Zub2RlL2lzLXZ0ZXh0XCI6IDI4LCBcIi4uL3Zub2RlL2lzLXdpZGdldFwiOiAyOSwgXCIuLi92bm9kZS92cGF0Y2hcIjogMzIsIFwiLi9kaWZmLXByb3BzXCI6IDM0LCBcIngtaXMtYXJyYXlcIjogMTIgfV0gfSwge30sIFs0XSkoNCk7XG59KTtcblxuXG4vLyBQcm9wb3NlZCBmb3IgRVM2XG5cbmNvbnN0IHN0YXJ0ID0gZnVuY3Rpb24gKGRvbVJvb3QsIHJlbmRlckZuLCBpbml0aWFsU3RhdGUsIG9wdGlvbnMgPSBbXSkge1xuICBjb25zdCBuYW1lID0gS2V5d29yZC5oYXNfa2V5X19xbV9fKG9wdGlvbnMsIEtlcm5lbC5TcGVjaWFsRm9ybXMuYXRvbSgnbmFtZScpKSA/IEtleXdvcmQuZ2V0KG9wdGlvbnMsIEtlcm5lbC5TcGVjaWFsRm9ybXMuYXRvbSgnbmFtZScpKSA6IFN5bWJvbCgpO1xuXG4gIHNlbGYucG9zdF9vZmZpY2UuYWRkX21haWxib3gobmFtZSk7XG5cbiAgY29uc3QgdHJlZSA9IHJlbmRlckZuLmFwcGx5KHRoaXMsIGluaXRpYWxTdGF0ZSk7XG4gIGNvbnN0IHJvb3ROb2RlID0gdmlydHVhbERvbS5jcmVhdGUodHJlZSk7XG5cbiAgZG9tUm9vdC5hcHBlbmRDaGlsZChyb290Tm9kZSk7XG4gIHNlbGYucG9zdF9vZmZpY2Uuc2VuZChuYW1lLCBLZXJuZWwuU3BlY2lhbEZvcm1zLnR1cGxlKHJvb3ROb2RlLCB0cmVlLCByZW5kZXJGbikpO1xuXG4gIHJldHVybiBLZXJuZWwuU3BlY2lhbEZvcm1zLnR1cGxlKEtlcm5lbC5TcGVjaWFsRm9ybXMuYXRvbSgnb2snKSwgbmFtZSk7XG59O1xuXG5jb25zdCBzdG9wID0gZnVuY3Rpb24gKGFnZW50LCB0aW1lb3V0ID0gNTAwMCkge1xuICBzZWxmLnBvc3Rfb2ZmaWNlLnJlbW92ZV9tYWlsYm94KGFnZW50KTtcbiAgcmV0dXJuIEtlcm5lbC5TcGVjaWFsRm9ybXMuYXRvbSgnb2snKTtcbn07XG5cbmNvbnN0IF91cGRhdGUgPSBmdW5jdGlvbiAoYWdlbnQsIHN0YXRlKSB7XG5cbiAgY29uc3QgY3VycmVudF9zdGF0ZSA9IHNlbGYucG9zdF9vZmZpY2UucmVjZWl2ZShhZ2VudCk7XG5cbiAgbGV0IHJvb3ROb2RlID0gS2VybmVsLmVsZW0oY3VycmVudF9zdGF0ZSwgMCk7XG4gIGxldCB0cmVlID0gS2VybmVsLmVsZW0oY3VycmVudF9zdGF0ZSwgMSk7XG4gIGxldCByZW5kZXJGbiA9IEtlcm5lbC5lbGVtKGN1cnJlbnRfc3RhdGUsIDIpO1xuXG4gIGxldCBuZXdUcmVlID0gcmVuZGVyRm4uYXBwbHkodGhpcywgc3RhdGUpO1xuXG4gIGxldCBwYXRjaGVzID0gdmlydHVhbERvbS5kaWZmKHRyZWUsIG5ld1RyZWUpO1xuICByb290Tm9kZSA9IHZpcnR1YWxEb20ucGF0Y2gocm9vdE5vZGUsIHBhdGNoZXMpO1xuXG4gIHNlbGYucG9zdF9vZmZpY2Uuc2VuZChhZ2VudCwgS2VybmVsLlNwZWNpYWxGb3Jtcy50dXBsZShyb290Tm9kZSwgbmV3VHJlZSwgcmVuZGVyRm4pKTtcblxuICByZXR1cm4gS2VybmVsLlNwZWNpYWxGb3Jtcy5hdG9tKCdvaycpO1xufTtcblxudmFyIFZpZXcgPSB7XG4gIHN0YXJ0LFxuICBzdG9wLFxuICB1cGRhdGU6IF91cGRhdGVcbn07XG5cbnNlbGYucG9zdF9vZmZpY2UgPSBzZWxmLnBvc3Rfb2ZmaWNlIHx8IG5ldyBQb3N0T2ZmaWNlKCk7XG5cbmV4cG9ydCB7IF9QYXR0ZXJucyBhcyBQYXR0ZXJucywgQml0U3RyaW5nLCBLZXJuZWwsIEF0b20sIEVudW0sIEludGVnZXIsIEpTLCBMaXN0LCBSYW5nZSwgVHVwbGUsIEFnZW50LCBLZXl3b3JkLCBCYXNlLCBfU3RyaW5nIGFzIFN0cmluZywgQml0d2lzZSwgRW51bWVyYWJsZSwgQ29sbGVjdGFibGUsIEluc3BlY3QsIF9NYXAgYXMgTWFwLCBfU2V0IGFzIFNldCwgTWFwU2V0LCBJbnRlZ2VyVHlwZSwgRmxvYXRUeXBlLCB2aXJ0dWFsRG9tIGFzIFZpcnR1YWxET00sIFZpZXcgfTsiXSwiZmlsZSI6ImVsaXhpci5qcyIsInNvdXJjZVJvb3QiOiIvc291cmNlLyJ9 \ No newline at end of file +//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiIiwic291cmNlcyI6WyJlbGl4aXIuanMiXSwic291cmNlc0NvbnRlbnQiOlsidmFyIFBhdHRlcm5zID0ge1xuICAgIGdldCBkZWZhdWx0ICgpIHsgcmV0dXJuIF9QYXR0ZXJuczsgfVxufTtcblxuY2xhc3MgVHVwbGUge1xuXG4gIGNvbnN0cnVjdG9yKC4uLmFyZ3MpIHtcbiAgICB0aGlzLnZhbHVlcyA9IE9iamVjdC5mcmVlemUoYXJncyk7XG4gIH1cblxuICBnZXQoaW5kZXgpIHtcbiAgICByZXR1cm4gdGhpcy52YWx1ZXNbaW5kZXhdO1xuICB9XG5cbiAgY291bnQoKSB7XG4gICAgcmV0dXJuIHRoaXMudmFsdWVzLmxlbmd0aDtcbiAgfVxuXG4gIFtTeW1ib2wuaXRlcmF0b3JdKCkge1xuICAgIHJldHVybiB0aGlzLnZhbHVlc1tTeW1ib2wuaXRlcmF0b3JdKCk7XG4gIH1cblxuICB0b1N0cmluZygpIHtcbiAgICB2YXIgaSxcbiAgICAgICAgcyA9IFwiXCI7XG4gICAgZm9yIChpID0gMDsgaSA8IHRoaXMudmFsdWVzLmxlbmd0aDsgaSsrKSB7XG4gICAgICBpZiAocyAhPT0gXCJcIikge1xuICAgICAgICBzICs9IFwiLCBcIjtcbiAgICAgIH1cbiAgICAgIHMgKz0gdGhpcy52YWx1ZXNbaV0udG9TdHJpbmcoKTtcbiAgICB9XG5cbiAgICByZXR1cm4gXCJ7XCIgKyBzICsgXCJ9XCI7XG4gIH1cblxuICBzdGF0aWMgdG9fc3RyaW5nKHR1cGxlKSB7XG4gICAgcmV0dXJuIHR1cGxlLnRvU3RyaW5nKCk7XG4gIH1cblxuICBzdGF0aWMgZGVsZXRlX2F0KHR1cGxlLCBpbmRleCkge1xuICAgIGxldCBuZXdfbGlzdCA9IFtdO1xuXG4gICAgZm9yICh2YXIgaSA9IDA7IGkgPCB0dXBsZS5jb3VudCgpOyBpKyspIHtcbiAgICAgIGlmIChpICE9PSBpbmRleCkge1xuICAgICAgICBuZXdfbGlzdC5wdXNoKHR1cGxlLmdldChpKSk7XG4gICAgICB9XG4gICAgfVxuXG4gICAgcmV0dXJuIEtlcm5lbC5TcGVjaWFsRm9ybXMudHVwbGUuYXBwbHkobnVsbCwgbmV3X2xpc3QpO1xuICB9XG5cbiAgc3RhdGljIGR1cGxpY2F0ZShkYXRhLCBzaXplKSB7XG4gICAgbGV0IGFycmF5ID0gW107XG5cbiAgICBmb3IgKHZhciBpID0gc2l6ZSAtIDE7IGkgPj0gMDsgaS0tKSB7XG4gICAgICBhcnJheS5wdXNoKGRhdGEpO1xuICAgIH1cblxuICAgIHJldHVybiBLZXJuZWwuU3BlY2lhbEZvcm1zLnR1cGxlLmFwcGx5KG51bGwsIGFycmF5KTtcbiAgfVxuXG4gIHN0YXRpYyBpbnNlcnRfYXQodHVwbGUsIGluZGV4LCB0ZXJtKSB7XG4gICAgbGV0IG5ld190dXBsZSA9IFtdO1xuXG4gICAgZm9yICh2YXIgaSA9IDA7IGkgPD0gdHVwbGUuY291bnQoKTsgaSsrKSB7XG4gICAgICBpZiAoaSA9PT0gaW5kZXgpIHtcbiAgICAgICAgbmV3X3R1cGxlLnB1c2godGVybSk7XG4gICAgICAgIGkrKztcbiAgICAgICAgbmV3X3R1cGxlLnB1c2godHVwbGUuZ2V0KGkpKTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIG5ld190dXBsZS5wdXNoKHR1cGxlLmdldChpKSk7XG4gICAgICB9XG4gICAgfVxuXG4gICAgcmV0dXJuIEtlcm5lbC5TcGVjaWFsRm9ybXMudHVwbGUuYXBwbHkobnVsbCwgbmV3X3R1cGxlKTtcbiAgfVxuXG4gIHN0YXRpYyBmcm9tX2xpc3QobGlzdCkge1xuICAgIHJldHVybiBLZXJuZWwuU3BlY2lhbEZvcm1zLnR1cGxlLmFwcGx5KG51bGwsIGxpc3QpO1xuICB9XG5cbiAgc3RhdGljIHRvX2xpc3QodHVwbGUpIHtcbiAgICBsZXQgbmV3X2xpc3QgPSBbXTtcblxuICAgIGZvciAodmFyIGkgPSAwOyBpIDwgdHVwbGUuY291bnQoKTsgaSsrKSB7XG4gICAgICBuZXdfbGlzdC5wdXNoKHR1cGxlLmdldChpKSk7XG4gICAgfVxuXG4gICAgcmV0dXJuIEtlcm5lbC5TcGVjaWFsRm9ybXMubGlzdCguLi5uZXdfbGlzdCk7XG4gIH1cbn1cblxuLyogQGZsb3cgKi9cblxuY2xhc3MgVmFyaWFibGUge1xuXG4gIGNvbnN0cnVjdG9yKG5hbWUgPSBudWxsKSB7XG4gICAgdGhpcy5uYW1lID0gbmFtZTtcbiAgfVxufVxuXG5jbGFzcyBXaWxkY2FyZCB7XG4gIGNvbnN0cnVjdG9yKCkge31cbn1cblxuY2xhc3MgU3RhcnRzV2l0aCB7XG5cbiAgY29uc3RydWN0b3IocHJlZml4KSB7XG4gICAgdGhpcy5wcmVmaXggPSBwcmVmaXg7XG4gIH1cbn1cblxuY2xhc3MgQ2FwdHVyZSB7XG5cbiAgY29uc3RydWN0b3IodmFsdWUpIHtcbiAgICB0aGlzLnZhbHVlID0gdmFsdWU7XG4gIH1cbn1cblxuY2xhc3MgSGVhZFRhaWwge1xuICBjb25zdHJ1Y3RvcigpIHt9XG59XG5cbmNsYXNzIFR5cGUge1xuXG4gIGNvbnN0cnVjdG9yKHR5cGUsIG9ialBhdHRlcm4gPSB7fSkge1xuICAgIHRoaXMudHlwZSA9IHR5cGU7XG4gICAgdGhpcy5vYmpQYXR0ZXJuID0gb2JqUGF0dGVybjtcbiAgfVxufVxuXG5jbGFzcyBCb3VuZCB7XG5cbiAgY29uc3RydWN0b3IodmFsdWUpIHtcbiAgICB0aGlzLnZhbHVlID0gdmFsdWU7XG4gIH1cbn1cblxuZnVuY3Rpb24gdmFyaWFibGUobmFtZSA9IG51bGwpIHtcbiAgcmV0dXJuIG5ldyBWYXJpYWJsZShuYW1lKTtcbn1cblxuZnVuY3Rpb24gd2lsZGNhcmQoKSB7XG4gIHJldHVybiBuZXcgV2lsZGNhcmQoKTtcbn1cblxuZnVuY3Rpb24gc3RhcnRzV2l0aChwcmVmaXgpIHtcbiAgcmV0dXJuIG5ldyBTdGFydHNXaXRoKHByZWZpeCk7XG59XG5cbmZ1bmN0aW9uIGNhcHR1cmUodmFsdWUpIHtcbiAgcmV0dXJuIG5ldyBDYXB0dXJlKHZhbHVlKTtcbn1cblxuZnVuY3Rpb24gaGVhZFRhaWwoKSB7XG4gIHJldHVybiBuZXcgSGVhZFRhaWwoKTtcbn1cblxuZnVuY3Rpb24gdHlwZSh0eXBlLCBvYmpQYXR0ZXJuID0ge30pIHtcbiAgcmV0dXJuIG5ldyBUeXBlKHR5cGUsIG9ialBhdHRlcm4pO1xufVxuXG5mdW5jdGlvbiBib3VuZCh2YWx1ZSkge1xuICByZXR1cm4gbmV3IEJvdW5kKHZhbHVlKTtcbn1cblxuZnVuY3Rpb24gX2lzX251bWJlcih2YWx1ZSkge1xuICByZXR1cm4gdHlwZW9mIHZhbHVlID09PSAnbnVtYmVyJztcbn1cblxuZnVuY3Rpb24gaXNfc3RyaW5nKHZhbHVlKSB7XG4gIHJldHVybiB0eXBlb2YgdmFsdWUgPT09ICdzdHJpbmcnO1xufVxuXG5mdW5jdGlvbiBfaXNfdHVwbGUodmFsdWUpIHtcbiAgcmV0dXJuIHZhbHVlIGluc3RhbmNlb2YgVHVwbGU7XG59XG5cbmZ1bmN0aW9uIF9pc19ib29sZWFuKHZhbHVlKSB7XG4gIHJldHVybiB0eXBlb2YgdmFsdWUgPT09ICdib29sZWFuJztcbn1cblxuZnVuY3Rpb24gaXNfc3ltYm9sKHZhbHVlKSB7XG4gIHJldHVybiB0eXBlb2YgdmFsdWUgPT09ICdzeW1ib2wnO1xufVxuXG5mdW5jdGlvbiBpc19udWxsKHZhbHVlKSB7XG4gIHJldHVybiB2YWx1ZSA9PT0gbnVsbDtcbn1cblxuZnVuY3Rpb24gaXNfdW5kZWZpbmVkKHZhbHVlKSB7XG4gIHJldHVybiB0eXBlb2YgdmFsdWUgPT09ICd1bmRlZmluZWQnO1xufVxuXG5mdW5jdGlvbiBfaXNfZnVuY3Rpb24odmFsdWUpIHtcbiAgcmV0dXJuIE9iamVjdC5wcm90b3R5cGUudG9TdHJpbmcuY2FsbCh2YWx1ZSkgPT0gJ1tvYmplY3QgRnVuY3Rpb25dJztcbn1cblxuZnVuY3Rpb24gaXNfdmFyaWFibGUodmFsdWUpIHtcbiAgcmV0dXJuIHZhbHVlIGluc3RhbmNlb2YgVmFyaWFibGU7XG59XG5cbmZ1bmN0aW9uIGlzX3dpbGRjYXJkKHZhbHVlKSB7XG4gIHJldHVybiB2YWx1ZSBpbnN0YW5jZW9mIFdpbGRjYXJkO1xufVxuXG5mdW5jdGlvbiBpc19oZWFkVGFpbCh2YWx1ZSkge1xuICByZXR1cm4gdmFsdWUgaW5zdGFuY2VvZiBIZWFkVGFpbDtcbn1cblxuZnVuY3Rpb24gaXNfY2FwdHVyZSh2YWx1ZSkge1xuICByZXR1cm4gdmFsdWUgaW5zdGFuY2VvZiBDYXB0dXJlO1xufVxuXG5mdW5jdGlvbiBpc190eXBlKHZhbHVlKSB7XG4gIHJldHVybiB2YWx1ZSBpbnN0YW5jZW9mIFR5cGU7XG59XG5cbmZ1bmN0aW9uIGlzX3N0YXJ0c1dpdGgodmFsdWUpIHtcbiAgcmV0dXJuIHZhbHVlIGluc3RhbmNlb2YgU3RhcnRzV2l0aDtcbn1cblxuZnVuY3Rpb24gaXNfYm91bmQodmFsdWUpIHtcbiAgcmV0dXJuIHZhbHVlIGluc3RhbmNlb2YgQm91bmQ7XG59XG5cbmZ1bmN0aW9uIGlzX29iamVjdCh2YWx1ZSkge1xuICByZXR1cm4gdHlwZW9mIHZhbHVlID09PSAnb2JqZWN0Jztcbn1cblxuZnVuY3Rpb24gaXNfYXJyYXkodmFsdWUpIHtcbiAgcmV0dXJuIEFycmF5LmlzQXJyYXkodmFsdWUpO1xufVxuXG52YXIgQ2hlY2tzID0ge1xuICBpc19udW1iZXI6IF9pc19udW1iZXIsXG4gIGlzX3N0cmluZyxcbiAgaXNfYm9vbGVhbjogX2lzX2Jvb2xlYW4sXG4gIGlzX3N5bWJvbCxcbiAgaXNfbnVsbCxcbiAgaXNfdW5kZWZpbmVkLFxuICBpc19mdW5jdGlvbjogX2lzX2Z1bmN0aW9uLFxuICBpc192YXJpYWJsZSxcbiAgaXNfd2lsZGNhcmQsXG4gIGlzX2hlYWRUYWlsLFxuICBpc19jYXB0dXJlLFxuICBpc190eXBlLFxuICBpc19zdGFydHNXaXRoLFxuICBpc19ib3VuZCxcbiAgaXNfb2JqZWN0LFxuICBpc19hcnJheSxcbiAgaXNfdHVwbGU6IF9pc190dXBsZVxufTtcblxuZnVuY3Rpb24gcmVzb2x2ZVR1cGxlKHBhdHRlcm4pIHtcbiAgbGV0IG1hdGNoZXMgPSBbXTtcblxuICBmb3IgKGxldCBlbGVtIG9mIHBhdHRlcm4pIHtcbiAgICBtYXRjaGVzLnB1c2goYnVpbGRNYXRjaChlbGVtKSk7XG4gIH1cblxuICByZXR1cm4gZnVuY3Rpb24gKHZhbHVlLCBhcmdzKSB7XG4gICAgaWYgKCFDaGVja3MuaXNfdHVwbGUodmFsdWUpIHx8IHZhbHVlLmNvdW50KCkgIT0gcGF0dGVybi5jb3VudCgpKSB7XG4gICAgICByZXR1cm4gZmFsc2U7XG4gICAgfVxuXG4gICAgcmV0dXJuIHZhbHVlLnZhbHVlcy5ldmVyeShmdW5jdGlvbiAodiwgaSkge1xuICAgICAgcmV0dXJuIG1hdGNoZXNbaV0odmFsdWUuZ2V0KGkpLCBhcmdzKTtcbiAgICB9KTtcbiAgfTtcbn1cblxuZnVuY3Rpb24gcmVzb2x2ZVN5bWJvbChwYXR0ZXJuKSB7XG4gIHJldHVybiBmdW5jdGlvbiAodmFsdWUpIHtcbiAgICByZXR1cm4gQ2hlY2tzLmlzX3N5bWJvbCh2YWx1ZSkgJiYgdmFsdWUgPT09IHBhdHRlcm47XG4gIH07XG59XG5cbmZ1bmN0aW9uIHJlc29sdmVTdHJpbmcocGF0dGVybikge1xuICByZXR1cm4gZnVuY3Rpb24gKHZhbHVlKSB7XG4gICAgcmV0dXJuIENoZWNrcy5pc19zdHJpbmcodmFsdWUpICYmIHZhbHVlID09PSBwYXR0ZXJuO1xuICB9O1xufVxuXG5mdW5jdGlvbiByZXNvbHZlTnVtYmVyKHBhdHRlcm4pIHtcbiAgcmV0dXJuIGZ1bmN0aW9uICh2YWx1ZSkge1xuICAgIHJldHVybiBDaGVja3MuaXNfbnVtYmVyKHZhbHVlKSAmJiB2YWx1ZSA9PT0gcGF0dGVybjtcbiAgfTtcbn1cblxuZnVuY3Rpb24gcmVzb2x2ZUJvb2xlYW4ocGF0dGVybikge1xuICByZXR1cm4gZnVuY3Rpb24gKHZhbHVlKSB7XG4gICAgcmV0dXJuIENoZWNrcy5pc19ib29sZWFuKHZhbHVlKSAmJiB2YWx1ZSA9PT0gcGF0dGVybjtcbiAgfTtcbn1cblxuZnVuY3Rpb24gcmVzb2x2ZUZ1bmN0aW9uKHBhdHRlcm4pIHtcbiAgcmV0dXJuIGZ1bmN0aW9uICh2YWx1ZSkge1xuICAgIHJldHVybiBDaGVja3MuaXNfZnVuY3Rpb24odmFsdWUpICYmIHZhbHVlID09PSBwYXR0ZXJuO1xuICB9O1xufVxuXG5mdW5jdGlvbiByZXNvbHZlTnVsbChwYXR0ZXJuKSB7XG4gIHJldHVybiBmdW5jdGlvbiAodmFsdWUpIHtcbiAgICByZXR1cm4gQ2hlY2tzLmlzX251bGwodmFsdWUpO1xuICB9O1xufVxuXG5mdW5jdGlvbiByZXNvbHZlQm91bmQocGF0dGVybikge1xuICByZXR1cm4gZnVuY3Rpb24gKHZhbHVlLCBhcmdzKSB7XG4gICAgaWYgKHR5cGVvZiB2YWx1ZSA9PT0gdHlwZW9mIHBhdHRlcm4udmFsdWUgJiYgdmFsdWUgPT09IHBhdHRlcm4udmFsdWUpIHtcbiAgICAgIGFyZ3MucHVzaCh2YWx1ZSk7XG4gICAgICByZXR1cm4gdHJ1ZTtcbiAgICB9XG5cbiAgICByZXR1cm4gZmFsc2U7XG4gIH07XG59XG5cbmZ1bmN0aW9uIHJlc29sdmVXaWxkY2FyZCgpIHtcbiAgcmV0dXJuIGZ1bmN0aW9uICgpIHtcbiAgICByZXR1cm4gdHJ1ZTtcbiAgfTtcbn1cblxuZnVuY3Rpb24gcmVzb2x2ZVZhcmlhYmxlKCkge1xuICByZXR1cm4gZnVuY3Rpb24gKHZhbHVlLCBhcmdzKSB7XG4gICAgYXJncy5wdXNoKHZhbHVlKTtcbiAgICByZXR1cm4gdHJ1ZTtcbiAgfTtcbn1cblxuZnVuY3Rpb24gcmVzb2x2ZUhlYWRUYWlsKCkge1xuICByZXR1cm4gZnVuY3Rpb24gKHZhbHVlLCBhcmdzKSB7XG4gICAgaWYgKCFDaGVja3MuaXNfYXJyYXkodmFsdWUpIHx8IHZhbHVlLmxlbmd0aCA8IDIpIHtcbiAgICAgIHJldHVybiBmYWxzZTtcbiAgICB9XG5cbiAgICBjb25zdCBoZWFkID0gdmFsdWVbMF07XG4gICAgY29uc3QgdGFpbCA9IHZhbHVlLnNsaWNlKDEpO1xuXG4gICAgYXJncy5wdXNoKGhlYWQpO1xuICAgIGFyZ3MucHVzaCh0YWlsKTtcblxuICAgIHJldHVybiB0cnVlO1xuICB9O1xufVxuXG5mdW5jdGlvbiByZXNvbHZlQ2FwdHVyZShwYXR0ZXJuKSB7XG4gIGNvbnN0IG1hdGNoZXMgPSBidWlsZE1hdGNoKHBhdHRlcm4udmFsdWUpO1xuXG4gIHJldHVybiBmdW5jdGlvbiAodmFsdWUsIGFyZ3MpIHtcbiAgICBpZiAobWF0Y2hlcyh2YWx1ZSwgYXJncykpIHtcbiAgICAgIGFyZ3MucHVzaCh2YWx1ZSk7XG4gICAgICByZXR1cm4gdHJ1ZTtcbiAgICB9XG5cbiAgICByZXR1cm4gZmFsc2U7XG4gIH07XG59XG5cbmZ1bmN0aW9uIHJlc29sdmVTdGFydHNXaXRoKHBhdHRlcm4pIHtcbiAgY29uc3QgcHJlZml4ID0gcGF0dGVybi5wcmVmaXg7XG5cbiAgcmV0dXJuIGZ1bmN0aW9uICh2YWx1ZSwgYXJncykge1xuICAgIGlmIChDaGVja3MuaXNfc3RyaW5nKHZhbHVlKSAmJiB2YWx1ZS5zdGFydHNXaXRoKHByZWZpeCkpIHtcbiAgICAgIGFyZ3MucHVzaCh2YWx1ZS5zdWJzdHJpbmcocHJlZml4Lmxlbmd0aCkpO1xuICAgICAgcmV0dXJuIHRydWU7XG4gICAgfVxuXG4gICAgcmV0dXJuIGZhbHNlO1xuICB9O1xufVxuXG5mdW5jdGlvbiByZXNvbHZlVHlwZShwYXR0ZXJuKSB7XG4gIHJldHVybiBmdW5jdGlvbiAodmFsdWUsIGFyZ3MpIHtcbiAgICBpZiAodmFsdWUgaW5zdGFuY2VvZiBwYXR0ZXJuLnR5cGUpIHtcbiAgICAgIGNvbnN0IG1hdGNoZXMgPSBidWlsZE1hdGNoKHBhdHRlcm4ub2JqUGF0dGVybik7XG4gICAgICByZXR1cm4gbWF0Y2hlcyh2YWx1ZSwgYXJncykgJiYgYXJncy5wdXNoKHZhbHVlKSA+IDA7XG4gICAgfVxuXG4gICAgcmV0dXJuIGZhbHNlO1xuICB9O1xufVxuXG5mdW5jdGlvbiByZXNvbHZlQXJyYXkocGF0dGVybikge1xuICBjb25zdCBtYXRjaGVzID0gcGF0dGVybi5tYXAoeCA9PiBidWlsZE1hdGNoKHgpKTtcblxuICByZXR1cm4gZnVuY3Rpb24gKHZhbHVlLCBhcmdzKSB7XG4gICAgaWYgKCFDaGVja3MuaXNfYXJyYXkodmFsdWUpIHx8IHZhbHVlLmxlbmd0aCAhPSBwYXR0ZXJuLmxlbmd0aCkge1xuICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH1cblxuICAgIHJldHVybiB2YWx1ZS5ldmVyeShmdW5jdGlvbiAodiwgaSkge1xuICAgICAgcmV0dXJuIG1hdGNoZXNbaV0odmFsdWVbaV0sIGFyZ3MpO1xuICAgIH0pO1xuICB9O1xufVxuXG5mdW5jdGlvbiByZXNvbHZlT2JqZWN0KHBhdHRlcm4pIHtcbiAgbGV0IG1hdGNoZXMgPSB7fTtcblxuICBmb3IgKGxldCBrZXkgb2YgT2JqZWN0LmtleXMocGF0dGVybikpIHtcbiAgICBtYXRjaGVzW2tleV0gPSBidWlsZE1hdGNoKHBhdHRlcm5ba2V5XSk7XG4gIH1cblxuICByZXR1cm4gZnVuY3Rpb24gKHZhbHVlLCBhcmdzKSB7XG4gICAgaWYgKCFDaGVja3MuaXNfb2JqZWN0KHZhbHVlKSB8fCBwYXR0ZXJuLmxlbmd0aCA+IHZhbHVlLmxlbmd0aCkge1xuICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH1cblxuICAgIGZvciAobGV0IGtleSBvZiBPYmplY3Qua2V5cyhwYXR0ZXJuKSkge1xuICAgICAgaWYgKCEoa2V5IGluIHZhbHVlKSB8fCAhbWF0Y2hlc1trZXldKHZhbHVlW2tleV0sIGFyZ3MpKSB7XG4gICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICByZXR1cm4gdHJ1ZTtcbiAgfTtcbn1cblxuZnVuY3Rpb24gcmVzb2x2ZU5vTWF0Y2goKSB7XG4gIHJldHVybiBmdW5jdGlvbiAoKSB7XG4gICAgcmV0dXJuIGZhbHNlO1xuICB9O1xufVxuXG52YXIgUmVzb2x2ZXJzID0ge1xuICByZXNvbHZlQm91bmQsXG4gIHJlc29sdmVXaWxkY2FyZCxcbiAgcmVzb2x2ZVZhcmlhYmxlLFxuICByZXNvbHZlSGVhZFRhaWwsXG4gIHJlc29sdmVDYXB0dXJlLFxuICByZXNvbHZlU3RhcnRzV2l0aCxcbiAgcmVzb2x2ZVR5cGUsXG4gIHJlc29sdmVBcnJheSxcbiAgcmVzb2x2ZU9iamVjdCxcbiAgcmVzb2x2ZU5vTWF0Y2gsXG4gIHJlc29sdmVTeW1ib2wsXG4gIHJlc29sdmVTdHJpbmcsXG4gIHJlc29sdmVOdW1iZXIsXG4gIHJlc29sdmVCb29sZWFuLFxuICByZXNvbHZlRnVuY3Rpb24sXG4gIHJlc29sdmVOdWxsLFxuICByZXNvbHZlVHVwbGVcbn07XG5cbmZ1bmN0aW9uIGJ1aWxkTWF0Y2gocGF0dGVybikge1xuXG4gIGlmIChDaGVja3MuaXNfdHVwbGUocGF0dGVybikpIHtcbiAgICByZXR1cm4gUmVzb2x2ZXJzLnJlc29sdmVUdXBsZShwYXR0ZXJuKTtcbiAgfVxuXG4gIGlmIChDaGVja3MuaXNfdmFyaWFibGUocGF0dGVybikpIHtcbiAgICByZXR1cm4gUmVzb2x2ZXJzLnJlc29sdmVWYXJpYWJsZShwYXR0ZXJuKTtcbiAgfVxuXG4gIGlmIChDaGVja3MuaXNfd2lsZGNhcmQocGF0dGVybikpIHtcbiAgICByZXR1cm4gUmVzb2x2ZXJzLnJlc29sdmVXaWxkY2FyZChwYXR0ZXJuKTtcbiAgfVxuXG4gIGlmIChDaGVja3MuaXNfdW5kZWZpbmVkKHBhdHRlcm4pKSB7XG4gICAgcmV0dXJuIFJlc29sdmVycy5yZXNvbHZlV2lsZGNhcmQocGF0dGVybik7XG4gIH1cblxuICBpZiAoQ2hlY2tzLmlzX2hlYWRUYWlsKHBhdHRlcm4pKSB7XG4gICAgcmV0dXJuIFJlc29sdmVycy5yZXNvbHZlSGVhZFRhaWwocGF0dGVybik7XG4gIH1cblxuICBpZiAoQ2hlY2tzLmlzX3N0YXJ0c1dpdGgocGF0dGVybikpIHtcbiAgICByZXR1cm4gUmVzb2x2ZXJzLnJlc29sdmVTdGFydHNXaXRoKHBhdHRlcm4pO1xuICB9XG5cbiAgaWYgKENoZWNrcy5pc19jYXB0dXJlKHBhdHRlcm4pKSB7XG4gICAgcmV0dXJuIFJlc29sdmVycy5yZXNvbHZlQ2FwdHVyZShwYXR0ZXJuKTtcbiAgfVxuXG4gIGlmIChDaGVja3MuaXNfYm91bmQocGF0dGVybikpIHtcbiAgICByZXR1cm4gUmVzb2x2ZXJzLnJlc29sdmVCb3VuZChwYXR0ZXJuKTtcbiAgfVxuXG4gIGlmIChDaGVja3MuaXNfdHlwZShwYXR0ZXJuKSkge1xuICAgIHJldHVybiBSZXNvbHZlcnMucmVzb2x2ZVR5cGUocGF0dGVybik7XG4gIH1cblxuICBpZiAoQ2hlY2tzLmlzX2FycmF5KHBhdHRlcm4pKSB7XG4gICAgcmV0dXJuIFJlc29sdmVycy5yZXNvbHZlQXJyYXkocGF0dGVybik7XG4gIH1cblxuICBpZiAoQ2hlY2tzLmlzX251bWJlcihwYXR0ZXJuKSkge1xuICAgIHJldHVybiBSZXNvbHZlcnMucmVzb2x2ZU51bWJlcihwYXR0ZXJuKTtcbiAgfVxuXG4gIGlmIChDaGVja3MuaXNfc3RyaW5nKHBhdHRlcm4pKSB7XG4gICAgcmV0dXJuIFJlc29sdmVycy5yZXNvbHZlU3RyaW5nKHBhdHRlcm4pO1xuICB9XG5cbiAgaWYgKENoZWNrcy5pc19ib29sZWFuKHBhdHRlcm4pKSB7XG4gICAgcmV0dXJuIFJlc29sdmVycy5yZXNvbHZlQm9vbGVhbihwYXR0ZXJuKTtcbiAgfVxuXG4gIGlmIChDaGVja3MuaXNfc3ltYm9sKHBhdHRlcm4pKSB7XG4gICAgcmV0dXJuIFJlc29sdmVycy5yZXNvbHZlU3ltYm9sKHBhdHRlcm4pO1xuICB9XG5cbiAgaWYgKENoZWNrcy5pc19udWxsKHBhdHRlcm4pKSB7XG4gICAgcmV0dXJuIFJlc29sdmVycy5yZXNvbHZlTnVsbChwYXR0ZXJuKTtcbiAgfVxuXG4gIGlmIChDaGVja3MuaXNfb2JqZWN0KHBhdHRlcm4pKSB7XG4gICAgcmV0dXJuIFJlc29sdmVycy5yZXNvbHZlT2JqZWN0KHBhdHRlcm4pO1xuICB9XG5cbiAgcmV0dXJuIFJlc29sdmVycy5yZXNvbHZlTm9NYXRjaCgpO1xufVxuXG5jbGFzcyBNYXRjaEVycm9yIGV4dGVuZHMgRXJyb3Ige1xuICBjb25zdHJ1Y3RvcihhcmcpIHtcbiAgICBzdXBlcigpO1xuXG4gICAgaWYgKHR5cGVvZiBhcmcgPT09ICdzeW1ib2wnKSB7XG4gICAgICB0aGlzLm1lc3NhZ2UgPSAnTm8gbWF0Y2ggZm9yOiAnICsgYXJnLnRvU3RyaW5nKCk7XG4gICAgfSBlbHNlIGlmIChBcnJheS5pc0FycmF5KGFyZykpIHtcbiAgICAgIGxldCBtYXBwZWRWYWx1ZXMgPSBhcmcubWFwKHggPT4geC50b1N0cmluZygpKTtcbiAgICAgIHRoaXMubWVzc2FnZSA9ICdObyBtYXRjaCBmb3I6ICcgKyBtYXBwZWRWYWx1ZXM7XG4gICAgfSBlbHNlIHtcbiAgICAgIHRoaXMubWVzc2FnZSA9ICdObyBtYXRjaCBmb3I6ICcgKyBhcmc7XG4gICAgfVxuXG4gICAgdGhpcy5zdGFjayA9IG5ldyBFcnJvcigpLnN0YWNrO1xuICAgIHRoaXMubmFtZSA9IHRoaXMuY29uc3RydWN0b3IubmFtZTtcbiAgfVxufVxuXG5jbGFzcyBDYXNlIHtcblxuICBjb25zdHJ1Y3RvcihwYXR0ZXJuLCBmbiwgZ3VhcmQgPSAoKSA9PiB0cnVlKSB7XG4gICAgdGhpcy5wYXR0ZXJuID0gYnVpbGRNYXRjaChwYXR0ZXJuKTtcbiAgICB0aGlzLmZuID0gZm47XG4gICAgdGhpcy5ndWFyZCA9IGd1YXJkO1xuICB9XG59XG5cbmZ1bmN0aW9uIG1ha2VfY2FzZShwYXR0ZXJuLCBmbiwgZ3VhcmQgPSAoKSA9PiB0cnVlKSB7XG4gIHJldHVybiBuZXcgQ2FzZShwYXR0ZXJuLCBmbiwgZ3VhcmQpO1xufVxuXG5mdW5jdGlvbiBkZWZtYXRjaCguLi5jYXNlcykge1xuICByZXR1cm4gZnVuY3Rpb24gKC4uLmFyZ3MpIHtcbiAgICBmb3IgKGxldCBwcm9jZXNzZWRDYXNlIG9mIGNhc2VzKSB7XG4gICAgICBsZXQgcmVzdWx0ID0gW107XG4gICAgICBpZiAocHJvY2Vzc2VkQ2FzZS5wYXR0ZXJuKGFyZ3MsIHJlc3VsdCkgJiYgcHJvY2Vzc2VkQ2FzZS5ndWFyZC5hcHBseSh0aGlzLCByZXN1bHQpKSB7XG4gICAgICAgIHJldHVybiBwcm9jZXNzZWRDYXNlLmZuLmFwcGx5KHRoaXMsIHJlc3VsdCk7XG4gICAgICB9XG4gICAgfVxuXG4gICAgdGhyb3cgbmV3IE1hdGNoRXJyb3IoYXJncyk7XG4gIH07XG59XG5cbmZ1bmN0aW9uIG1hdGNoKHBhdHRlcm4sIGV4cHIsIGd1YXJkID0gKCkgPT4gdHJ1ZSkge1xuICBsZXQgcmVzdWx0ID0gW107XG4gIGxldCBwcm9jZXNzZWRQYXR0ZXJuID0gYnVpbGRNYXRjaChwYXR0ZXJuKTtcbiAgaWYgKHByb2Nlc3NlZFBhdHRlcm4oZXhwciwgcmVzdWx0KSAmJiBndWFyZC5hcHBseSh0aGlzLCByZXN1bHQpKSB7XG4gICAgcmV0dXJuIHJlc3VsdDtcbiAgfSBlbHNlIHtcbiAgICB0aHJvdyBuZXcgTWF0Y2hFcnJvcihleHByKTtcbiAgfVxufVxuXG5mdW5jdGlvbiBtYXRjaF9ub190aHJvdyhwYXR0ZXJuLCBleHByLCBndWFyZCA9ICgpID0+IHRydWUpIHtcbiAgdHJ5IHtcbiAgICByZXR1cm4gbWF0Y2gocGF0dGVybiwgZXhwciwgZ3VhcmQpO1xuICB9IGNhdGNoIChlKSB7XG4gICAgaWYgKGUgaW5zdGFuY2VvZiBNYXRjaEVycm9yKSB7XG4gICAgICByZXR1cm4gbnVsbDtcbiAgICB9XG5cbiAgICB0aHJvdyBlO1xuICB9XG59XG5cbmZ1bmN0aW9uIHBhdHRlcm5NYXAoY29sbGVjdGlvbiwgcGF0dGVybiwgZnVuLCBndWFyZCA9ICgpID0+IHRydWUpIHtcbiAgbGV0IHJldCA9IFtdO1xuXG4gIGZvciAobGV0IGVsZW0gb2YgY29sbGVjdGlvbikge1xuICAgIHRyeSB7XG4gICAgICBsZXQgcmVzdWx0ID0gZnVuLmFwcGx5KHRoaXMsIG1hdGNoKHBhdHRlcm4sIGVsZW0sIGd1YXJkKSk7XG4gICAgICByZXQgPSByZXQuY29uY2F0KHJlc3VsdCk7XG4gICAgfSBjYXRjaCAoZSkge1xuICAgICAgaWYgKCEoZSBpbnN0YW5jZW9mIE1hdGNoRXJyb3IpKSB7XG4gICAgICAgIHRocm93IGU7XG4gICAgICB9XG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIHJldDtcbn1cblxudmFyIF9QYXR0ZXJucyA9IHtcbiAgZGVmbWF0Y2gsIG1hdGNoLCBNYXRjaEVycm9yLCBtYXRjaF9ub190aHJvdywgcGF0dGVybk1hcCxcbiAgdmFyaWFibGUsIHdpbGRjYXJkLCBzdGFydHNXaXRoLFxuICBjYXB0dXJlLCBoZWFkVGFpbCwgdHlwZSwgYm91bmQsIENhc2UsIG1ha2VfY2FzZVxufTtcblxuY2xhc3MgQml0U3RyaW5nIHtcbiAgY29uc3RydWN0b3IoLi4uYXJncykge1xuICAgIHRoaXMucmF3X3ZhbHVlID0gZnVuY3Rpb24gKCkge1xuICAgICAgcmV0dXJuIE9iamVjdC5mcmVlemUoYXJncyk7XG4gICAgfTtcblxuICAgIHRoaXMudmFsdWUgPSBPYmplY3QuZnJlZXplKHRoaXMucHJvY2VzcyhhcmdzKSk7XG4gIH1cblxuICBnZXQoaW5kZXgpIHtcbiAgICByZXR1cm4gdGhpcy52YWx1ZVtpbmRleF07XG4gIH1cblxuICBjb3VudCgpIHtcbiAgICByZXR1cm4gdGhpcy52YWx1ZS5sZW5ndGg7XG4gIH1cblxuICBbU3ltYm9sLml0ZXJhdG9yXSgpIHtcbiAgICByZXR1cm4gdGhpcy52YWx1ZVtTeW1ib2wuaXRlcmF0b3JdKCk7XG4gIH1cblxuICB0b1N0cmluZygpIHtcbiAgICB2YXIgaSxcbiAgICAgICAgcyA9IFwiXCI7XG4gICAgZm9yIChpID0gMDsgaSA8IHRoaXMuY291bnQoKTsgaSsrKSB7XG4gICAgICBpZiAocyAhPT0gXCJcIikge1xuICAgICAgICBzICs9IFwiLCBcIjtcbiAgICAgIH1cbiAgICAgIHMgKz0gdGhpc1tpXS50b1N0cmluZygpO1xuICAgIH1cblxuICAgIHJldHVybiBcIjw8XCIgKyBzICsgXCI+PlwiO1xuICB9XG5cbiAgcHJvY2VzcygpIHtcbiAgICBsZXQgcHJvY2Vzc2VkX3ZhbHVlcyA9IFtdO1xuXG4gICAgdmFyIGk7XG4gICAgZm9yIChpID0gMDsgaSA8IHRoaXMucmF3X3ZhbHVlKCkubGVuZ3RoOyBpKyspIHtcbiAgICAgIGxldCBwcm9jZXNzZWRfdmFsdWUgPSB0aGlzW1wicHJvY2Vzc19cIiArIHRoaXMucmF3X3ZhbHVlKClbaV0udHlwZV0odGhpcy5yYXdfdmFsdWUoKVtpXSk7XG5cbiAgICAgIGZvciAobGV0IGF0dHIgb2YgdGhpcy5yYXdfdmFsdWUoKVtpXS5hdHRyaWJ1dGVzKSB7XG4gICAgICAgIHByb2Nlc3NlZF92YWx1ZSA9IHRoaXNbXCJwcm9jZXNzX1wiICsgYXR0cl0ocHJvY2Vzc2VkX3ZhbHVlKTtcbiAgICAgIH1cblxuICAgICAgcHJvY2Vzc2VkX3ZhbHVlcyA9IHByb2Nlc3NlZF92YWx1ZXMuY29uY2F0KHByb2Nlc3NlZF92YWx1ZSk7XG4gICAgfVxuXG4gICAgcmV0dXJuIHByb2Nlc3NlZF92YWx1ZXM7XG4gIH1cblxuICBwcm9jZXNzX2ludGVnZXIodmFsdWUpIHtcbiAgICByZXR1cm4gdmFsdWUudmFsdWU7XG4gIH1cblxuICBwcm9jZXNzX2Zsb2F0KHZhbHVlKSB7XG4gICAgaWYgKHZhbHVlLnNpemUgPT09IDY0KSB7XG4gICAgICByZXR1cm4gQml0U3RyaW5nLmZsb2F0NjRUb0J5dGVzKHZhbHVlLnZhbHVlKTtcbiAgICB9IGVsc2UgaWYgKHZhbHVlLnNpemUgPT09IDMyKSB7XG4gICAgICByZXR1cm4gQml0U3RyaW5nLmZsb2F0MzJUb0J5dGVzKHZhbHVlLnZhbHVlKTtcbiAgICB9XG5cbiAgICB0aHJvdyBuZXcgRXJyb3IoXCJJbnZhbGlkIHNpemUgZm9yIGZsb2F0XCIpO1xuICB9XG5cbiAgcHJvY2Vzc19iaXRzdHJpbmcodmFsdWUpIHtcbiAgICByZXR1cm4gdmFsdWUudmFsdWUudmFsdWU7XG4gIH1cblxuICBwcm9jZXNzX2JpbmFyeSh2YWx1ZSkge1xuICAgIHJldHVybiBCaXRTdHJpbmcudG9VVEY4QXJyYXkodmFsdWUudmFsdWUpO1xuICB9XG5cbiAgcHJvY2Vzc191dGY4KHZhbHVlKSB7XG4gICAgcmV0dXJuIEJpdFN0cmluZy50b1VURjhBcnJheSh2YWx1ZS52YWx1ZSk7XG4gIH1cblxuICBwcm9jZXNzX3V0ZjE2KHZhbHVlKSB7XG4gICAgcmV0dXJuIEJpdFN0cmluZy50b1VURjE2QXJyYXkodmFsdWUudmFsdWUpO1xuICB9XG5cbiAgcHJvY2Vzc191dGYzMih2YWx1ZSkge1xuICAgIHJldHVybiBCaXRTdHJpbmcudG9VVEYzMkFycmF5KHZhbHVlLnZhbHVlKTtcbiAgfVxuXG4gIHByb2Nlc3Nfc2lnbmVkKHZhbHVlKSB7XG4gICAgcmV0dXJuIG5ldyBVaW50OEFycmF5KFt2YWx1ZV0pWzBdO1xuICB9XG5cbiAgcHJvY2Vzc191bnNpZ25lZCh2YWx1ZSkge1xuICAgIHJldHVybiB2YWx1ZTtcbiAgfVxuXG4gIHByb2Nlc3NfbmF0aXZlKHZhbHVlKSB7XG4gICAgcmV0dXJuIHZhbHVlO1xuICB9XG5cbiAgcHJvY2Vzc19iaWcodmFsdWUpIHtcbiAgICByZXR1cm4gdmFsdWU7XG4gIH1cblxuICBwcm9jZXNzX2xpdHRsZSh2YWx1ZSkge1xuICAgIHJldHVybiB2YWx1ZS5yZXZlcnNlKCk7XG4gIH1cblxuICBwcm9jZXNzX3NpemUodmFsdWUpIHtcbiAgICByZXR1cm4gdmFsdWU7XG4gIH1cblxuICBwcm9jZXNzX3VuaXQodmFsdWUpIHtcbiAgICByZXR1cm4gdmFsdWU7XG4gIH1cblxuICBzdGF0aWMgaW50ZWdlcih2YWx1ZSkge1xuICAgIHJldHVybiBCaXRTdHJpbmcud3JhcCh2YWx1ZSwgeyBcInR5cGVcIjogXCJpbnRlZ2VyXCIsIFwidW5pdFwiOiAxLCBcInNpemVcIjogOCB9KTtcbiAgfVxuXG4gIHN0YXRpYyBmbG9hdCh2YWx1ZSkge1xuICAgIHJldHVybiBCaXRTdHJpbmcud3JhcCh2YWx1ZSwgeyBcInR5cGVcIjogXCJmbG9hdFwiLCBcInVuaXRcIjogMSwgXCJzaXplXCI6IDY0IH0pO1xuICB9XG5cbiAgc3RhdGljIGJpdHN0cmluZyh2YWx1ZSkge1xuICAgIHJldHVybiBCaXRTdHJpbmcud3JhcCh2YWx1ZSwgeyBcInR5cGVcIjogXCJiaXRzdHJpbmdcIiwgXCJ1bml0XCI6IDEsIFwic2l6ZVwiOiB2YWx1ZS5sZW5ndGggfSk7XG4gIH1cblxuICBzdGF0aWMgYml0cyh2YWx1ZSkge1xuICAgIHJldHVybiBCaXRTdHJpbmcuYml0c3RyaW5nKHZhbHVlKTtcbiAgfVxuXG4gIHN0YXRpYyBiaW5hcnkodmFsdWUpIHtcbiAgICByZXR1cm4gQml0U3RyaW5nLndyYXAodmFsdWUsIHsgXCJ0eXBlXCI6IFwiYmluYXJ5XCIsIFwidW5pdFwiOiA4LCBcInNpemVcIjogdmFsdWUubGVuZ3RoIH0pO1xuICB9XG5cbiAgc3RhdGljIGJ5dGVzKHZhbHVlKSB7XG4gICAgcmV0dXJuIEJpdFN0cmluZy5iaW5hcnkodmFsdWUpO1xuICB9XG5cbiAgc3RhdGljIHV0ZjgodmFsdWUpIHtcbiAgICByZXR1cm4gQml0U3RyaW5nLndyYXAodmFsdWUsIHsgXCJ0eXBlXCI6IFwidXRmOFwiIH0pO1xuICB9XG5cbiAgc3RhdGljIHV0ZjE2KHZhbHVlKSB7XG4gICAgcmV0dXJuIEJpdFN0cmluZy53cmFwKHZhbHVlLCB7IFwidHlwZVwiOiBcInV0ZjE2XCIgfSk7XG4gIH1cblxuICBzdGF0aWMgdXRmMzIodmFsdWUpIHtcbiAgICByZXR1cm4gQml0U3RyaW5nLndyYXAodmFsdWUsIHsgXCJ0eXBlXCI6IFwidXRmMzJcIiB9KTtcbiAgfVxuXG4gIHN0YXRpYyBzaWduZWQodmFsdWUpIHtcbiAgICByZXR1cm4gQml0U3RyaW5nLndyYXAodmFsdWUsIHt9LCBcInNpZ25lZFwiKTtcbiAgfVxuXG4gIHN0YXRpYyB1bnNpZ25lZCh2YWx1ZSkge1xuICAgIHJldHVybiBCaXRTdHJpbmcud3JhcCh2YWx1ZSwge30sIFwidW5zaWduZWRcIik7XG4gIH1cblxuICBzdGF0aWMgbmF0aXZlKHZhbHVlKSB7XG4gICAgcmV0dXJuIEJpdFN0cmluZy53cmFwKHZhbHVlLCB7fSwgXCJuYXRpdmVcIik7XG4gIH1cblxuICBzdGF0aWMgYmlnKHZhbHVlKSB7XG4gICAgcmV0dXJuIEJpdFN0cmluZy53cmFwKHZhbHVlLCB7fSwgXCJiaWdcIik7XG4gIH1cblxuICBzdGF0aWMgbGl0dGxlKHZhbHVlKSB7XG4gICAgcmV0dXJuIEJpdFN0cmluZy53cmFwKHZhbHVlLCB7fSwgXCJsaXR0bGVcIik7XG4gIH1cblxuICBzdGF0aWMgc2l6ZSh2YWx1ZSwgY291bnQpIHtcbiAgICByZXR1cm4gQml0U3RyaW5nLndyYXAodmFsdWUsIHsgXCJzaXplXCI6IGNvdW50IH0pO1xuICB9XG5cbiAgc3RhdGljIHVuaXQodmFsdWUsIGNvdW50KSB7XG4gICAgcmV0dXJuIEJpdFN0cmluZy53cmFwKHZhbHVlLCB7IFwidW5pdFwiOiBjb3VudCB9KTtcbiAgfVxuXG4gIHN0YXRpYyB3cmFwKHZhbHVlLCBvcHQsIG5ld19hdHRyaWJ1dGUgPSBudWxsKSB7XG4gICAgbGV0IHRoZV92YWx1ZSA9IHZhbHVlO1xuXG4gICAgaWYgKCEodmFsdWUgaW5zdGFuY2VvZiBPYmplY3QpKSB7XG4gICAgICB0aGVfdmFsdWUgPSB7IFwidmFsdWVcIjogdmFsdWUsIFwiYXR0cmlidXRlc1wiOiBbXSB9O1xuICAgIH1cblxuICAgIHRoZV92YWx1ZSA9IE9iamVjdC5hc3NpZ24odGhlX3ZhbHVlLCBvcHQpO1xuXG4gICAgaWYgKG5ld19hdHRyaWJ1dGUpIHtcbiAgICAgIHRoZV92YWx1ZS5hdHRyaWJ1dGVzLnB1c2gobmV3X2F0dHJpYnV0ZSk7XG4gICAgfVxuXG4gICAgcmV0dXJuIHRoZV92YWx1ZTtcbiAgfVxuXG4gIHN0YXRpYyB0b1VURjhBcnJheShzdHIpIHtcbiAgICB2YXIgdXRmOCA9IFtdO1xuICAgIGZvciAodmFyIGkgPSAwOyBpIDwgc3RyLmxlbmd0aDsgaSsrKSB7XG4gICAgICB2YXIgY2hhcmNvZGUgPSBzdHIuY2hhckNvZGVBdChpKTtcbiAgICAgIGlmIChjaGFyY29kZSA8IDEyOCkge1xuICAgICAgICB1dGY4LnB1c2goY2hhcmNvZGUpO1xuICAgICAgfSBlbHNlIGlmIChjaGFyY29kZSA8IDIwNDgpIHtcbiAgICAgICAgdXRmOC5wdXNoKDE5MiB8IGNoYXJjb2RlID4+IDYsIDEyOCB8IGNoYXJjb2RlICYgNjMpO1xuICAgICAgfSBlbHNlIGlmIChjaGFyY29kZSA8IDU1Mjk2IHx8IGNoYXJjb2RlID49IDU3MzQ0KSB7XG4gICAgICAgIHV0ZjgucHVzaCgyMjQgfCBjaGFyY29kZSA+PiAxMiwgMTI4IHwgY2hhcmNvZGUgPj4gNiAmIDYzLCAxMjggfCBjaGFyY29kZSAmIDYzKTtcbiAgICAgIH1cbiAgICAgIC8vIHN1cnJvZ2F0ZSBwYWlyXG4gICAgICBlbHNlIHtcbiAgICAgICAgaSsrO1xuICAgICAgICAvLyBVVEYtMTYgZW5jb2RlcyAweDEwMDAwLTB4MTBGRkZGIGJ5XG4gICAgICAgIC8vIHN1YnRyYWN0aW5nIDB4MTAwMDAgYW5kIHNwbGl0dGluZyB0aGVcbiAgICAgICAgLy8gMjAgYml0cyBvZiAweDAtMHhGRkZGRiBpbnRvIHR3byBoYWx2ZXNcbiAgICAgICAgY2hhcmNvZGUgPSA2NTUzNiArICgoY2hhcmNvZGUgJiAxMDIzKSA8PCAxMCB8IHN0ci5jaGFyQ29kZUF0KGkpICYgMTAyMyk7XG4gICAgICAgIHV0ZjgucHVzaCgyNDAgfCBjaGFyY29kZSA+PiAxOCwgMTI4IHwgY2hhcmNvZGUgPj4gMTIgJiA2MywgMTI4IHwgY2hhcmNvZGUgPj4gNiAmIDYzLCAxMjggfCBjaGFyY29kZSAmIDYzKTtcbiAgICAgIH1cbiAgICB9XG4gICAgcmV0dXJuIHV0Zjg7XG4gIH1cblxuICBzdGF0aWMgdG9VVEYxNkFycmF5KHN0cikge1xuICAgIHZhciB1dGYxNiA9IFtdO1xuICAgIGZvciAodmFyIGkgPSAwOyBpIDwgc3RyLmxlbmd0aDsgaSsrKSB7XG4gICAgICB2YXIgY29kZVBvaW50ID0gc3RyLmNvZGVQb2ludEF0KGkpO1xuXG4gICAgICBpZiAoY29kZVBvaW50IDw9IDI1NSkge1xuICAgICAgICB1dGYxNi5wdXNoKDApO1xuICAgICAgICB1dGYxNi5wdXNoKGNvZGVQb2ludCk7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICB1dGYxNi5wdXNoKGNvZGVQb2ludCA+PiA4ICYgMjU1KTtcbiAgICAgICAgdXRmMTYucHVzaChjb2RlUG9pbnQgJiAyNTUpO1xuICAgICAgfVxuICAgIH1cbiAgICByZXR1cm4gdXRmMTY7XG4gIH1cblxuICBzdGF0aWMgdG9VVEYzMkFycmF5KHN0cikge1xuICAgIHZhciB1dGYzMiA9IFtdO1xuICAgIGZvciAodmFyIGkgPSAwOyBpIDwgc3RyLmxlbmd0aDsgaSsrKSB7XG4gICAgICB2YXIgY29kZVBvaW50ID0gc3RyLmNvZGVQb2ludEF0KGkpO1xuXG4gICAgICBpZiAoY29kZVBvaW50IDw9IDI1NSkge1xuICAgICAgICB1dGYzMi5wdXNoKDApO1xuICAgICAgICB1dGYzMi5wdXNoKDApO1xuICAgICAgICB1dGYzMi5wdXNoKDApO1xuICAgICAgICB1dGYzMi5wdXNoKGNvZGVQb2ludCk7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICB1dGYzMi5wdXNoKDApO1xuICAgICAgICB1dGYzMi5wdXNoKDApO1xuICAgICAgICB1dGYzMi5wdXNoKGNvZGVQb2ludCA+PiA4ICYgMjU1KTtcbiAgICAgICAgdXRmMzIucHVzaChjb2RlUG9pbnQgJiAyNTUpO1xuICAgICAgfVxuICAgIH1cbiAgICByZXR1cm4gdXRmMzI7XG4gIH1cblxuICAvL2h0dHA6Ly9zdGFja292ZXJmbG93LmNvbS9xdWVzdGlvbnMvMjAwMzQ5My9qYXZhc2NyaXB0LWZsb2F0LWZyb20tdG8tYml0c1xuICBzdGF0aWMgZmxvYXQzMlRvQnl0ZXMoZikge1xuICAgIHZhciBieXRlcyA9IFtdO1xuXG4gICAgdmFyIGJ1ZiA9IG5ldyBBcnJheUJ1ZmZlcig0KTtcbiAgICBuZXcgRmxvYXQzMkFycmF5KGJ1ZilbMF0gPSBmO1xuXG4gICAgbGV0IGludFZlcnNpb24gPSBuZXcgVWludDMyQXJyYXkoYnVmKVswXTtcblxuICAgIGJ5dGVzLnB1c2goaW50VmVyc2lvbiA+PiAyNCAmIDI1NSk7XG4gICAgYnl0ZXMucHVzaChpbnRWZXJzaW9uID4+IDE2ICYgMjU1KTtcbiAgICBieXRlcy5wdXNoKGludFZlcnNpb24gPj4gOCAmIDI1NSk7XG4gICAgYnl0ZXMucHVzaChpbnRWZXJzaW9uICYgMjU1KTtcblxuICAgIHJldHVybiBieXRlcztcbiAgfVxuXG4gIHN0YXRpYyBmbG9hdDY0VG9CeXRlcyhmKSB7XG4gICAgdmFyIGJ5dGVzID0gW107XG5cbiAgICB2YXIgYnVmID0gbmV3IEFycmF5QnVmZmVyKDgpO1xuICAgIG5ldyBGbG9hdDY0QXJyYXkoYnVmKVswXSA9IGY7XG5cbiAgICB2YXIgaW50VmVyc2lvbjEgPSBuZXcgVWludDMyQXJyYXkoYnVmKVswXTtcbiAgICB2YXIgaW50VmVyc2lvbjIgPSBuZXcgVWludDMyQXJyYXkoYnVmKVsxXTtcblxuICAgIGJ5dGVzLnB1c2goaW50VmVyc2lvbjIgPj4gMjQgJiAyNTUpO1xuICAgIGJ5dGVzLnB1c2goaW50VmVyc2lvbjIgPj4gMTYgJiAyNTUpO1xuICAgIGJ5dGVzLnB1c2goaW50VmVyc2lvbjIgPj4gOCAmIDI1NSk7XG4gICAgYnl0ZXMucHVzaChpbnRWZXJzaW9uMiAmIDI1NSk7XG5cbiAgICBieXRlcy5wdXNoKGludFZlcnNpb24xID4+IDI0ICYgMjU1KTtcbiAgICBieXRlcy5wdXNoKGludFZlcnNpb24xID4+IDE2ICYgMjU1KTtcbiAgICBieXRlcy5wdXNoKGludFZlcnNpb24xID4+IDggJiAyNTUpO1xuICAgIGJ5dGVzLnB1c2goaW50VmVyc2lvbjEgJiAyNTUpO1xuXG4gICAgcmV0dXJuIGJ5dGVzO1xuICB9XG59XG5cbmxldCBTcGVjaWFsRm9ybXMgPSB7XG5cbiAgX19ESVJfXzogZnVuY3Rpb24gKCkge1xuICAgIGlmIChfX2Rpcm5hbWUpIHtcbiAgICAgIHJldHVybiBfX2Rpcm5hbWU7XG4gICAgfVxuXG4gICAgaWYgKGRvY3VtZW50LmN1cnJlbnRTY3JpcHQpIHtcbiAgICAgIHJldHVybiBkb2N1bWVudC5jdXJyZW50U2NyaXB0LnNyYztcbiAgICB9XG5cbiAgICByZXR1cm4gbnVsbDtcbiAgfSxcblxuICBhdG9tOiBmdW5jdGlvbiAoX3ZhbHVlKSB7XG4gICAgcmV0dXJuIFN5bWJvbC5mb3IoX3ZhbHVlKTtcbiAgfSxcblxuICBsaXN0OiBmdW5jdGlvbiAoLi4uYXJncykge1xuICAgIHJldHVybiBPYmplY3QuZnJlZXplKGFyZ3MpO1xuICB9LFxuXG4gIGJpdHN0cmluZzogZnVuY3Rpb24gKC4uLmFyZ3MpIHtcbiAgICByZXR1cm4gbmV3IEJpdFN0cmluZyguLi5hcmdzKTtcbiAgfSxcblxuICBib3VuZDogZnVuY3Rpb24gKF92YXIpIHtcbiAgICByZXR1cm4gUGF0dGVybnMuYm91bmQoX3Zhcik7XG4gIH0sXG5cbiAgX2Nhc2U6IGZ1bmN0aW9uIChjb25kaXRpb24sIGNsYXVzZXMpIHtcbiAgICByZXR1cm4gUGF0dGVybnMuZGVmbWF0Y2goLi4uY2xhdXNlcykoY29uZGl0aW9uKTtcbiAgfSxcblxuICBjb25kOiBmdW5jdGlvbiAoY2xhdXNlcykge1xuICAgIGZvciAobGV0IGNsYXVzZSBvZiBjbGF1c2VzKSB7XG4gICAgICBpZiAoY2xhdXNlWzBdKSB7XG4gICAgICAgIHJldHVybiBjbGF1c2VbMV0oKTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICB0aHJvdyBuZXcgRXJyb3IoKTtcbiAgfSxcblxuICBmbjogZnVuY3Rpb24gKGNsYXVzZXMpIHtcbiAgICByZXR1cm4gUGF0dGVybnMuZGVmbWF0Y2goY2xhdXNlcyk7XG4gIH0sXG5cbiAgbWFwOiBmdW5jdGlvbiAob2JqKSB7XG4gICAgcmV0dXJuIE9iamVjdC5mcmVlemUob2JqKTtcbiAgfSxcblxuICBtYXBfdXBkYXRlOiBmdW5jdGlvbiAobWFwLCB2YWx1ZXMpIHtcbiAgICByZXR1cm4gT2JqZWN0LmZyZWV6ZShPYmplY3QuYXNzaWduKE9iamVjdC5jcmVhdGUobWFwLmNvbnN0cnVjdG9yLnByb3RvdHlwZSksIG1hcCwgdmFsdWVzKSk7XG4gIH0sXG5cbiAgX2ZvcjogZnVuY3Rpb24gKGNvbGxlY3Rpb25zLCBmdW4sIGZpbHRlciA9ICgpID0+IHRydWUsIGludG8gPSBbXSwgcHJldmlvdXNWYWx1ZXMgPSBbXSkge1xuICAgIGxldCBwYXR0ZXJuID0gY29sbGVjdGlvbnNbMF1bMF07XG4gICAgbGV0IGNvbGxlY3Rpb24gPSBjb2xsZWN0aW9uc1swXVsxXTtcblxuICAgIGlmIChjb2xsZWN0aW9ucy5sZW5ndGggPT09IDEpIHtcblxuICAgICAgZm9yIChsZXQgZWxlbSBvZiBjb2xsZWN0aW9uKSB7XG4gICAgICAgIGxldCByID0gUGF0dGVybnMubWF0Y2hfbm9fdGhyb3cocGF0dGVybiwgZWxlbSk7XG4gICAgICAgIGxldCBhcmdzID0gcHJldmlvdXNWYWx1ZXMuY29uY2F0KHIpO1xuXG4gICAgICAgIGlmIChyICYmIGZpbHRlci5hcHBseSh0aGlzLCBhcmdzKSkge1xuICAgICAgICAgIGludG8gPSBFbnVtLmludG8oW2Z1bi5hcHBseSh0aGlzLCBhcmdzKV0sIGludG8pO1xuICAgICAgICB9XG4gICAgICB9XG5cbiAgICAgIHJldHVybiBpbnRvO1xuICAgIH0gZWxzZSB7XG4gICAgICBsZXQgX2ludG8gPSBbXTtcblxuICAgICAgZm9yIChsZXQgZWxlbSBvZiBjb2xsZWN0aW9uKSB7XG4gICAgICAgIGxldCByID0gUGF0dGVybnMubWF0Y2hfbm9fdGhyb3cocGF0dGVybiwgZWxlbSk7XG4gICAgICAgIGlmIChyKSB7XG4gICAgICAgICAgX2ludG8gPSBFbnVtLmludG8odGhpcy5fZm9yKGNvbGxlY3Rpb25zLnNsaWNlKDEpLCBmdW4sIGZpbHRlciwgX2ludG8sIHByZXZpb3VzVmFsdWVzLmNvbmNhdChyKSksIGludG8pO1xuICAgICAgICB9XG4gICAgICB9XG5cbiAgICAgIHJldHVybiBfaW50bztcbiAgICB9XG4gIH0sXG5cbiAgcmVjZWl2ZTogZnVuY3Rpb24gKHJlY2VpdmVfZnVuLCB0aW1lb3V0X2luX21zID0gbnVsbCwgdGltZW91dF9mbiA9IHRpbWUgPT4gdHJ1ZSkge1xuICAgIGlmICh0aW1lb3V0X2luX21zID09IG51bGwgfHwgdGltZW91dF9pbl9tcyA9PT0gU3lzdGVtLmZvcignaW5maW5pdHknKSkge1xuICAgICAgd2hpbGUgKHRydWUpIHtcbiAgICAgICAgaWYgKHNlbGYubWFpbGJveC5sZW5ndGggIT09IDApIHtcbiAgICAgICAgICBsZXQgbWVzc2FnZSA9IHNlbGYubWFpbGJveFswXTtcbiAgICAgICAgICBzZWxmLm1haWxib3ggPSBzZWxmLm1haWxib3guc2xpY2UoMSk7XG4gICAgICAgICAgcmV0dXJuIHJlY2VpdmVfZnVuKG1lc3NhZ2UpO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgfSBlbHNlIGlmICh0aW1lb3V0X2luX21zID09PSAwKSB7XG4gICAgICBpZiAoc2VsZi5tYWlsYm94Lmxlbmd0aCAhPT0gMCkge1xuICAgICAgICBsZXQgbWVzc2FnZSA9IHNlbGYubWFpbGJveFswXTtcbiAgICAgICAgc2VsZi5tYWlsYm94ID0gc2VsZi5tYWlsYm94LnNsaWNlKDEpO1xuICAgICAgICByZXR1cm4gcmVjZWl2ZV9mdW4obWVzc2FnZSk7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICByZXR1cm4gbnVsbDtcbiAgICAgIH1cbiAgICB9IGVsc2Uge1xuICAgICAgbGV0IG5vdyA9IERhdGUubm93KCk7XG4gICAgICB3aGlsZSAoRGF0ZS5ub3coKSA8IG5vdyArIHRpbWVvdXRfaW5fbXMpIHtcbiAgICAgICAgaWYgKHNlbGYubWFpbGJveC5sZW5ndGggIT09IDApIHtcbiAgICAgICAgICBsZXQgbWVzc2FnZSA9IHNlbGYubWFpbGJveFswXTtcbiAgICAgICAgICBzZWxmLm1haWxib3ggPSBzZWxmLm1haWxib3guc2xpY2UoMSk7XG4gICAgICAgICAgcmV0dXJuIHJlY2VpdmVfZnVuKG1lc3NhZ2UpO1xuICAgICAgICB9XG4gICAgICB9XG5cbiAgICAgIHJldHVybiB0aW1lb3V0X2ZuKHRpbWVvdXRfaW5fbXMpO1xuICAgIH1cbiAgfSxcblxuICB0dXBsZTogZnVuY3Rpb24gKC4uLmFyZ3MpIHtcbiAgICByZXR1cm4gbmV3IFR1cGxlKC4uLmFyZ3MpO1xuICB9LFxuXG4gIF90cnk6IGZ1bmN0aW9uIChkb19mdW4sIHJlc2N1ZV9mdW5jdGlvbiwgY2F0Y2hfZnVuLCBlbHNlX2Z1bmN0aW9uLCBhZnRlcl9mdW5jdGlvbikge1xuICAgIGxldCByZXN1bHQgPSBudWxsO1xuXG4gICAgdHJ5IHtcbiAgICAgIHJlc3VsdCA9IGRvX2Z1bigpO1xuICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgIGxldCBleF9yZXN1bHQgPSBudWxsO1xuXG4gICAgICBpZiAocmVzY3VlX2Z1bmN0aW9uKSB7XG4gICAgICAgIHRyeSB7XG4gICAgICAgICAgZXhfcmVzdWx0ID0gcmVzY3VlX2Z1bmN0aW9uKGUpO1xuICAgICAgICAgIHJldHVybiBleF9yZXN1bHQ7XG4gICAgICAgIH0gY2F0Y2ggKGV4KSB7XG4gICAgICAgICAgaWYgKGV4IGluc3RhbmNlb2YgUGF0dGVybnMuTWF0Y2hFcnJvcikge1xuICAgICAgICAgICAgdGhyb3cgZXg7XG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICB9XG5cbiAgICAgIGlmIChjYXRjaF9mdW4pIHtcbiAgICAgICAgdHJ5IHtcbiAgICAgICAgICBleF9yZXN1bHQgPSBjYXRjaF9mdW4oZSk7XG4gICAgICAgICAgcmV0dXJuIGV4X3Jlc3VsdDtcbiAgICAgICAgfSBjYXRjaCAoZXgpIHtcbiAgICAgICAgICBpZiAoZXggaW5zdGFuY2VvZiBQYXR0ZXJucy5NYXRjaEVycm9yKSB7XG4gICAgICAgICAgICB0aHJvdyBleDtcbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgIH1cblxuICAgICAgdGhyb3cgZTtcbiAgICB9IGZpbmFsbHkge1xuICAgICAgaWYgKGFmdGVyX2Z1bmN0aW9uKSB7XG4gICAgICAgIGFmdGVyX2Z1bmN0aW9uKCk7XG4gICAgICB9XG4gICAgfVxuXG4gICAgaWYgKGVsc2VfZnVuY3Rpb24pIHtcbiAgICAgIHRyeSB7XG4gICAgICAgIHJldHVybiBlbHNlX2Z1bmN0aW9uKHJlc3VsdCk7XG4gICAgICB9IGNhdGNoIChleCkge1xuICAgICAgICBpZiAoZXggaW5zdGFuY2VvZiBQYXR0ZXJucy5NYXRjaEVycm9yKSB7XG4gICAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdObyBNYXRjaCBGb3VuZCBpbiBFbHNlJyk7XG4gICAgICAgIH1cblxuICAgICAgICB0aHJvdyBleDtcbiAgICAgIH1cbiAgICB9IGVsc2Uge1xuICAgICAgcmV0dXJuIHJlc3VsdDtcbiAgICB9XG4gIH1cblxufTtcblxuLyogQGZsb3cgKi9cblxubGV0IHByb2Nlc3NfY291bnRlciA9IC0xO1xuXG5jbGFzcyBQSUQge1xuICBjb25zdHJ1Y3RvcigpIHtcbiAgICBwcm9jZXNzX2NvdW50ZXIgPSBwcm9jZXNzX2NvdW50ZXIgKyAxO1xuICAgIHRoaXMuaWQgPSBwcm9jZXNzX2NvdW50ZXI7XG4gIH1cblxuICB0b1N0cmluZygpIHtcbiAgICByZXR1cm4gXCJQSUQjPDAuXCIgKyB0aGlzLmlkICsgXCIuMD5cIjtcbiAgfVxufVxuXG5jbGFzcyBJbnRlZ2VyVHlwZSB7fVxuY2xhc3MgRmxvYXRUeXBlIHt9XG5cbi8vaHR0cHM6Ly9naXRodWIuY29tL2FpcnBvcnR5aC9wcm90b21vcnBoaXNtXG5jbGFzcyBQcm90b2NvbCB7XG4gIGNvbnN0cnVjdG9yKHNwZWMpIHtcbiAgICB0aGlzLnJlZ2lzdHJ5ID0gbmV3IE1hcCgpO1xuICAgIHRoaXMuZmFsbGJhY2sgPSBudWxsO1xuXG4gICAgZm9yIChsZXQgZnVuTmFtZSBpbiBzcGVjKSB7XG4gICAgICB0aGlzW2Z1bk5hbWVdID0gY3JlYXRlRnVuKGZ1bk5hbWUpLmJpbmQodGhpcyk7XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gY3JlYXRlRnVuKGZ1bk5hbWUpIHtcblxuICAgICAgcmV0dXJuIGZ1bmN0aW9uICguLi5hcmdzKSB7XG4gICAgICAgIGxldCB0aGluZyA9IGFyZ3NbMF07XG4gICAgICAgIGxldCBmdW4gPSBudWxsO1xuXG4gICAgICAgIGlmIChOdW1iZXIuaXNJbnRlZ2VyKHRoaW5nKSAmJiB0aGlzLmhhc0ltcGxlbWVudGF0aW9uKEludGVnZXJUeXBlKSkge1xuICAgICAgICAgIGZ1biA9IHRoaXMucmVnaXN0cnkuZ2V0KEludGVnZXJUeXBlKVtmdW5OYW1lXTtcbiAgICAgICAgfSBlbHNlIGlmICh0eXBlb2YgdGhpbmcgPT09IFwibnVtYmVyXCIgJiYgIU51bWJlci5pc0ludGVnZXIodGhpbmcpICYmIHRoaXMuaGFzSW1wbGVtZW50YXRpb24oRmxvYXRUeXBlKSkge1xuICAgICAgICAgIGZ1biA9IHRoaXMucmVnaXN0cnkuZ2V0KEZsb2F0VHlwZSlbZnVuTmFtZV07XG4gICAgICAgIH0gZWxzZSBpZiAodGhpcy5oYXNJbXBsZW1lbnRhdGlvbih0aGluZykpIHtcbiAgICAgICAgICBmdW4gPSB0aGlzLnJlZ2lzdHJ5LmdldCh0aGluZy5jb25zdHJ1Y3RvcilbZnVuTmFtZV07XG4gICAgICAgIH0gZWxzZSBpZiAodGhpcy5mYWxsYmFjaykge1xuICAgICAgICAgIGZ1biA9IHRoaXMuZmFsbGJhY2tbZnVuTmFtZV07XG4gICAgICAgIH1cblxuICAgICAgICBpZiAoZnVuICE9IG51bGwpIHtcbiAgICAgICAgICBsZXQgcmV0dmFsID0gZnVuLmFwcGx5KHRoaXMsIGFyZ3MpO1xuICAgICAgICAgIHJldHVybiByZXR2YWw7XG4gICAgICAgIH1cblxuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoXCJObyBpbXBsZW1lbnRhdGlvbiBmb3VuZCBmb3IgXCIgKyB0aGluZyk7XG4gICAgICB9O1xuICAgIH1cbiAgfVxuXG4gIGltcGxlbWVudGF0aW9uKHR5cGUsIGltcGxlbWVudGF0aW9uKSB7XG4gICAgaWYgKHR5cGUgPT09IG51bGwpIHtcbiAgICAgIHRoaXMuZmFsbGJhY2sgPSBpbXBsZW1lbnRhdGlvbjtcbiAgICB9IGVsc2Uge1xuICAgICAgdGhpcy5yZWdpc3RyeS5zZXQodHlwZSwgaW1wbGVtZW50YXRpb24pO1xuICAgIH1cbiAgfVxuXG4gIGhhc0ltcGxlbWVudGF0aW9uKHRoaW5nKSB7XG4gICAgcmV0dXJuIHRoaXMucmVnaXN0cnkuaGFzKHRoaW5nLmNvbnN0cnVjdG9yKTtcbiAgfVxufVxuXG5mdW5jdGlvbiB0bChsaXN0KSB7XG4gIHJldHVybiBTcGVjaWFsRm9ybXMubGlzdCguLi5saXN0LnNsaWNlKDEpKTtcbn1cblxuZnVuY3Rpb24gaGQobGlzdCkge1xuICByZXR1cm4gbGlzdFswXTtcbn1cblxuZnVuY3Rpb24gaXNfbmlsKHgpIHtcbiAgcmV0dXJuIHggPT09IG51bGw7XG59XG5cbmZ1bmN0aW9uIGlzX2F0b20oeCkge1xuICByZXR1cm4gdHlwZW9mIHggPT09ICdzeW1ib2wnO1xufVxuXG5mdW5jdGlvbiBpc19iaW5hcnkoeCkge1xuICByZXR1cm4gdHlwZW9mIHggPT09ICdzdHJpbmcnIHx8IHggaW5zdGFuY2VvZiBTdHJpbmc7XG59XG5cbmZ1bmN0aW9uIGlzX2Jvb2xlYW4oeCkge1xuICByZXR1cm4gdHlwZW9mIHggPT09ICdib29sZWFuJyB8fCB4IGluc3RhbmNlb2YgQm9vbGVhbjtcbn1cblxuZnVuY3Rpb24gaXNfZnVuY3Rpb24oeCwgYXJpdHkgPSAtMSkge1xuICByZXR1cm4gdHlwZW9mIHggPT09ICdmdW5jdGlvbicgfHwgeCBpbnN0YW5jZW9mIEZ1bmN0aW9uO1xufVxuXG5mdW5jdGlvbiBpc19mbG9hdCh4KSB7XG4gIHJldHVybiBpc19udW1iZXIoeCkgJiYgIU51bWJlci5pc0ludGVnZXIoeCk7XG59XG5cbmZ1bmN0aW9uIGlzX2ludGVnZXIoeCkge1xuICByZXR1cm4gTnVtYmVyLmlzSW50ZWdlcih4KTtcbn1cblxuZnVuY3Rpb24gaXNfbGlzdCh4KSB7XG4gIHJldHVybiB4IGluc3RhbmNlb2YgQXJyYXk7XG59XG5cbmZ1bmN0aW9uIGlzX21hcCh4KSB7XG4gIHJldHVybiB0eXBlb2YgeCA9PT0gJ29iamVjdCcgfHwgeCBpbnN0YW5jZW9mIE9iamVjdDtcbn1cblxuZnVuY3Rpb24gaXNfbnVtYmVyKHgpIHtcbiAgcmV0dXJuIHR5cGVvZiB4ID09PSAnbnVtYmVyJztcbn1cblxuZnVuY3Rpb24gaXNfdHVwbGUoeCkge1xuICByZXR1cm4geCBpbnN0YW5jZW9mIFR1cGxlO1xufVxuXG5mdW5jdGlvbiBfbGVuZ3RoKHgpIHtcbiAgcmV0dXJuIHgubGVuZ3RoO1xufVxuXG5mdW5jdGlvbiBpc19waWQoeCkge1xuICByZXR1cm4geCBpbnN0YW5jZW9mIFBJRDtcbn1cblxuZnVuY3Rpb24gaXNfcG9ydCh4KSB7XG4gIHJldHVybiBmYWxzZTtcbn1cblxuZnVuY3Rpb24gaXNfcmVmZXJlbmNlKHgpIHtcbiAgcmV0dXJuIGZhbHNlO1xufVxuXG5mdW5jdGlvbiBpc19iaXRzdHJpbmcoeCkge1xuICByZXR1cm4gaXNfYmluYXJ5KHgpIHx8IHggaW5zdGFuY2VvZiBCaXRTdHJpbmc7XG59XG5cbmZ1bmN0aW9uIF9faW5fXyhsZWZ0LCByaWdodCkge1xuICBmb3IgKGxldCB4IG9mIHJpZ2h0KSB7XG4gICAgaWYgKG1hdGNoX19xbWFya19fKGxlZnQsIHgpKSB7XG4gICAgICByZXR1cm4gdHJ1ZTtcbiAgICB9XG4gIH1cblxuICByZXR1cm4gZmFsc2U7XG59XG5cbmZ1bmN0aW9uIGFicyhudW1iZXIpIHtcbiAgcmV0dXJuIE1hdGguYWJzKG51bWJlcik7XG59XG5cbmZ1bmN0aW9uIHJvdW5kKG51bWJlcikge1xuICByZXR1cm4gTWF0aC5yb3VuZChudW1iZXIpO1xufVxuXG5mdW5jdGlvbiBlbGVtKHR1cGxlLCBpbmRleCkge1xuICBpZiAoaXNfbGlzdCh0dXBsZSkpIHtcbiAgICByZXR1cm4gdHVwbGVbaW5kZXhdO1xuICB9XG5cbiAgcmV0dXJuIHR1cGxlLmdldChpbmRleCk7XG59XG5cbmZ1bmN0aW9uIHJlbShsZWZ0LCByaWdodCkge1xuICByZXR1cm4gbGVmdCAlIHJpZ2h0O1xufVxuXG5mdW5jdGlvbiBkaXYobGVmdCwgcmlnaHQpIHtcbiAgcmV0dXJuIGxlZnQgLyByaWdodDtcbn1cblxuZnVuY3Rpb24gYW5kKGxlZnQsIHJpZ2h0KSB7XG4gIHJldHVybiBsZWZ0ICYmIHJpZ2h0O1xufVxuXG5mdW5jdGlvbiBvcihsZWZ0LCByaWdodCkge1xuICByZXR1cm4gbGVmdCB8fCByaWdodDtcbn1cblxuZnVuY3Rpb24gbm90KGFyZykge1xuICByZXR1cm4gIWFyZztcbn1cblxuZnVuY3Rpb24gYXBwbHkoLi4uYXJncykge1xuICBpZiAoYXJncy5sZW5ndGggPT09IDMpIHtcbiAgICBsZXQgbW9kID0gYXJnc1swXTtcbiAgICBsZXQgZnVuYyA9IGFyZ3NbMV07XG4gICAgbGV0IGZ1bmNfYXJncyA9IGFyZ3NbMl07XG4gICAgcmV0dXJuIG1vZFtmdW5jXS5hcHBseShudWxsLCBmdW5jX2FyZ3MpO1xuICB9IGVsc2Uge1xuICAgIGxldCBmdW5jID0gYXJnc1swXTtcbiAgICBsZXQgZnVuY19hcmdzID0gYXJnc1sxXTtcblxuICAgIHJldHVybiBmdW5jLmFwcGx5KG51bGwsIGZ1bmNfYXJncyk7XG4gIH1cbn1cblxuZnVuY3Rpb24gdG9fc3RyaW5nKGFyZykge1xuICBpZiAoaXNfdHVwbGUoYXJnKSkge1xuICAgIHJldHVybiBUdXBsZS50b19zdHJpbmcoYXJnKTtcbiAgfVxuXG4gIHJldHVybiBhcmcudG9TdHJpbmcoKTtcbn1cblxuZnVuY3Rpb24gbWF0Y2hfX3FtYXJrX18ocGF0dGVybiwgZXhwciwgZ3VhcmQgPSAoKSA9PiB0cnVlKSB7XG4gIHJldHVybiBfUGF0dGVybnMubWF0Y2hfbm9fdGhyb3cocGF0dGVybiwgZXhwciwgZ3VhcmQpICE9IG51bGw7XG59XG5cbmZ1bmN0aW9uIGRlZnN0cnVjdChkZWZhdWx0cykge1xuICByZXR1cm4gY2xhc3Mge1xuICAgIGNvbnN0cnVjdG9yKHVwZGF0ZSA9IHt9KSB7XG4gICAgICBsZXQgdGhlX3ZhbHVlcyA9IE9iamVjdC5hc3NpZ24oZGVmYXVsdHMsIHVwZGF0ZSk7XG4gICAgICBPYmplY3QuYXNzaWduKHRoaXMsIHRoZV92YWx1ZXMpO1xuICAgIH1cblxuICAgIHN0YXRpYyBjcmVhdGUodXBkYXRlcyA9IHt9KSB7XG4gICAgICBsZXQgeCA9IG5ldyB0aGlzKHVwZGF0ZXMpO1xuICAgICAgcmV0dXJuIE9iamVjdC5mcmVlemUoeCk7XG4gICAgfVxuICB9O1xufVxuXG5mdW5jdGlvbiBkZWZleGNlcHRpb24oZGVmYXVsdHMpIHtcbiAgcmV0dXJuIGNsYXNzIGV4dGVuZHMgRXJyb3Ige1xuICAgIGNvbnN0cnVjdG9yKHVwZGF0ZSA9IHt9KSB7XG4gICAgICBsZXQgbWVzc2FnZSA9IHVwZGF0ZS5tZXNzYWdlIHx8ICcnO1xuICAgICAgc3VwZXIobWVzc2FnZSk7XG5cbiAgICAgIGxldCB0aGVfdmFsdWVzID0gT2JqZWN0LmFzc2lnbihkZWZhdWx0cywgdXBkYXRlKTtcbiAgICAgIE9iamVjdC5hc3NpZ24odGhpcywgdGhlX3ZhbHVlcyk7XG5cbiAgICAgIHRoaXMubmFtZSA9IHRoaXMuY29uc3RydWN0b3IubmFtZTtcbiAgICAgIHRoaXMubWVzc2FnZSA9IG1lc3NhZ2U7XG4gICAgICB0aGlzW1NwZWNpYWxGb3Jtcy5hdG9tKCdfX2V4Y2VwdGlvbl9fJyldID0gdHJ1ZTtcbiAgICAgIEVycm9yLmNhcHR1cmVTdGFja1RyYWNlKHRoaXMsIHRoaXMuY29uc3RydWN0b3IubmFtZSk7XG4gICAgfVxuXG4gICAgc3RhdGljIGNyZWF0ZSh1cGRhdGVzID0ge30pIHtcbiAgICAgIGxldCB4ID0gbmV3IHRoaXModXBkYXRlcyk7XG4gICAgICByZXR1cm4gT2JqZWN0LmZyZWV6ZSh4KTtcbiAgICB9XG4gIH07XG59XG5cbmZ1bmN0aW9uIGRlZnByb3RvY29sKHNwZWMpIHtcbiAgcmV0dXJuIG5ldyBQcm90b2NvbChzcGVjKTtcbn1cblxuZnVuY3Rpb24gZGVmaW1wbChwcm90b2NvbCwgdHlwZSwgaW1wbCkge1xuICBwcm90b2NvbC5pbXBsZW1lbnRhdGlvbih0eXBlLCBpbXBsKTtcbn1cblxudmFyIEtlcm5lbCA9IHtcbiAgU3BlY2lhbEZvcm1zLFxuICB0bCxcbiAgaGQsXG4gIGlzX25pbCxcbiAgaXNfYXRvbSxcbiAgaXNfYmluYXJ5LFxuICBpc19ib29sZWFuLFxuICBpc19mdW5jdGlvbixcbiAgaXNfZmxvYXQsXG4gIGlzX2ludGVnZXIsXG4gIGlzX2xpc3QsXG4gIGlzX21hcCxcbiAgaXNfbnVtYmVyLFxuICBpc190dXBsZSxcbiAgbGVuZ3RoOiBfbGVuZ3RoLFxuICBpc19waWQsXG4gIGlzX3BvcnQsXG4gIGlzX3JlZmVyZW5jZSxcbiAgaXNfYml0c3RyaW5nLFxuICBpbjogX19pbl9fLFxuICBhYnMsXG4gIHJvdW5kLFxuICBlbGVtLFxuICByZW0sXG4gIGRpdixcbiAgYW5kLFxuICBvcixcbiAgbm90LFxuICBhcHBseSxcbiAgdG9fc3RyaW5nLFxuICBtYXRjaF9fcW1hcmtfXyxcbiAgZGVmc3RydWN0LFxuICBkZWZwcm90b2NvbCxcbiAgZGVmaW1wbFxufTtcblxubGV0IEVudW0gPSB7XG5cbiAgYWxsX19xbWFya19fOiBmdW5jdGlvbiAoY29sbGVjdGlvbiwgZnVuID0geCA9PiB4KSB7XG4gICAgZm9yIChsZXQgZWxlbSBvZiBjb2xsZWN0aW9uKSB7XG4gICAgICBpZiAoIWZ1bihlbGVtKSkge1xuICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICB9XG4gICAgfVxuXG4gICAgcmV0dXJuIHRydWU7XG4gIH0sXG5cbiAgYW55X19xbWFya19fOiBmdW5jdGlvbiAoY29sbGVjdGlvbiwgZnVuID0geCA9PiB4KSB7XG4gICAgZm9yIChsZXQgZWxlbSBvZiBjb2xsZWN0aW9uKSB7XG4gICAgICBpZiAoZnVuKGVsZW0pKSB7XG4gICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgfVxuICAgIH1cblxuICAgIHJldHVybiBmYWxzZTtcbiAgfSxcblxuICBhdDogZnVuY3Rpb24gKGNvbGxlY3Rpb24sIG4sIHRoZV9kZWZhdWx0ID0gbnVsbCkge1xuICAgIGlmIChuID4gdGhpcy5jb3VudChjb2xsZWN0aW9uKSB8fCBuIDwgMCkge1xuICAgICAgcmV0dXJuIHRoZV9kZWZhdWx0O1xuICAgIH1cblxuICAgIHJldHVybiBjb2xsZWN0aW9uW25dO1xuICB9LFxuXG4gIGNvbmNhdDogZnVuY3Rpb24gKC4uLmVudW1hYmxlcykge1xuICAgIHJldHVybiBlbnVtYWJsZXNbMF0uY29uY2F0KGVudW1hYmxlc1sxXSk7XG4gIH0sXG5cbiAgY291bnQ6IGZ1bmN0aW9uIChjb2xsZWN0aW9uLCBmdW4gPSBudWxsKSB7XG4gICAgaWYgKGZ1biA9PSBudWxsKSB7XG4gICAgICByZXR1cm4gY29sbGVjdGlvbi5sZW5ndGg7XG4gICAgfSBlbHNlIHtcbiAgICAgIHJldHVybiBjb2xsZWN0aW9uLmZpbHRlcihmdW4pLmxlbmd0aDtcbiAgICB9XG4gIH0sXG5cbiAgZHJvcDogZnVuY3Rpb24gKGNvbGxlY3Rpb24sIGNvdW50KSB7XG4gICAgcmV0dXJuIGNvbGxlY3Rpb24uc2xpY2UoY291bnQpO1xuICB9LFxuXG4gIGRyb3Bfd2hpbGU6IGZ1bmN0aW9uIChjb2xsZWN0aW9uLCBmdW4pIHtcbiAgICBsZXQgY291bnQgPSAwO1xuXG4gICAgZm9yIChsZXQgZWxlbSBvZiBjb2xsZWN0aW9uKSB7XG4gICAgICBpZiAoZnVuKGVsZW0pKSB7XG4gICAgICAgIGNvdW50ID0gY291bnQgKyAxO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgYnJlYWs7XG4gICAgICB9XG4gICAgfVxuXG4gICAgcmV0dXJuIGNvbGxlY3Rpb24uc2xpY2UoY291bnQpO1xuICB9LFxuXG4gIGVhY2g6IGZ1bmN0aW9uIChjb2xsZWN0aW9uLCBmdW4pIHtcbiAgICBmb3IgKGxldCBlbGVtIG9mIGNvbGxlY3Rpb24pIHtcbiAgICAgIGZ1bihlbGVtKTtcbiAgICB9XG4gIH0sXG5cbiAgZW1wdHlfX3FtYXJrX186IGZ1bmN0aW9uIChjb2xsZWN0aW9uKSB7XG4gICAgcmV0dXJuIGNvbGxlY3Rpb24ubGVuZ3RoID09PSAwO1xuICB9LFxuXG4gIGZldGNoOiBmdW5jdGlvbiAoY29sbGVjdGlvbiwgbikge1xuICAgIGlmIChLZXJuZWwuaXNfbGlzdChjb2xsZWN0aW9uKSkge1xuICAgICAgaWYgKG4gPCB0aGlzLmNvdW50KGNvbGxlY3Rpb24pICYmIG4gPj0gMCkge1xuICAgICAgICByZXR1cm4gS2VybmVsLlNwZWNpYWxGb3Jtcy50dXBsZShLZXJuZWwuU3BlY2lhbEZvcm1zLmF0b20oXCJva1wiKSwgY29sbGVjdGlvbltuXSk7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICByZXR1cm4gS2VybmVsLlNwZWNpYWxGb3Jtcy5hdG9tKFwiZXJyb3JcIik7XG4gICAgICB9XG4gICAgfVxuXG4gICAgdGhyb3cgbmV3IEVycm9yKFwiY29sbGVjdGlvbiBpcyBub3QgYW4gRW51bWVyYWJsZVwiKTtcbiAgfSxcblxuICBmZXRjaF9fZW1hcmtfXzogZnVuY3Rpb24gKGNvbGxlY3Rpb24sIG4pIHtcbiAgICBpZiAoS2VybmVsLmlzX2xpc3QoY29sbGVjdGlvbikpIHtcbiAgICAgIGlmIChuIDwgdGhpcy5jb3VudChjb2xsZWN0aW9uKSAmJiBuID49IDApIHtcbiAgICAgICAgcmV0dXJuIGNvbGxlY3Rpb25bbl07XG4gICAgICB9IGVsc2Uge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoXCJvdXQgb2YgYm91bmRzIGVycm9yXCIpO1xuICAgICAgfVxuICAgIH1cblxuICAgIHRocm93IG5ldyBFcnJvcihcImNvbGxlY3Rpb24gaXMgbm90IGFuIEVudW1lcmFibGVcIik7XG4gIH0sXG5cbiAgZmlsdGVyOiBmdW5jdGlvbiAoY29sbGVjdGlvbiwgZnVuKSB7XG4gICAgbGV0IHJlc3VsdCA9IFtdO1xuXG4gICAgZm9yIChsZXQgZWxlbSBvZiBjb2xsZWN0aW9uKSB7XG4gICAgICBpZiAoZnVuKGVsZW0pKSB7XG4gICAgICAgIHJlc3VsdC5wdXNoKGVsZW0pO1xuICAgICAgfVxuICAgIH1cblxuICAgIHJldHVybiByZXN1bHQ7XG4gIH0sXG5cbiAgZmlsdGVyX21hcDogZnVuY3Rpb24gKGNvbGxlY3Rpb24sIGZpbHRlciwgbWFwcGVyKSB7XG4gICAgcmV0dXJuIEVudW0ubWFwKEVudW0uZmlsdGVyKGNvbGxlY3Rpb24sIGZpbHRlciksIG1hcHBlcik7XG4gIH0sXG5cbiAgZmluZDogZnVuY3Rpb24gKGNvbGxlY3Rpb24sIGlmX25vbmUgPSBudWxsLCBmdW4pIHtcbiAgICBmb3IgKGxldCBlbGVtIG9mIGNvbGxlY3Rpb24pIHtcbiAgICAgIGlmIChmdW4oZWxlbSkpIHtcbiAgICAgICAgcmV0dXJuIGVsZW07XG4gICAgICB9XG4gICAgfVxuXG4gICAgcmV0dXJuIGlmX25vbmU7XG4gIH0sXG5cbiAgaW50bzogZnVuY3Rpb24gKGNvbGxlY3Rpb24sIGxpc3QpIHtcbiAgICByZXR1cm4gbGlzdC5jb25jYXQoY29sbGVjdGlvbik7XG4gIH0sXG5cbiAgbWFwOiBmdW5jdGlvbiAoY29sbGVjdGlvbiwgZnVuKSB7XG4gICAgbGV0IHJlc3VsdCA9IFtdO1xuXG4gICAgZm9yIChsZXQgZWxlbSBvZiBjb2xsZWN0aW9uKSB7XG4gICAgICByZXN1bHQucHVzaChmdW4oZWxlbSkpO1xuICAgIH1cblxuICAgIHJldHVybiByZXN1bHQ7XG4gIH0sXG5cbiAgbWFwX3JlZHVjZTogZnVuY3Rpb24gKGNvbGxlY3Rpb24sIGFjYywgZnVuKSB7XG4gICAgbGV0IG1hcHBlZCA9IEtlcm5lbC5TcGVjaWFsRm9ybXMubGlzdCgpO1xuICAgIGxldCB0aGVfYWNjID0gYWNjO1xuXG4gICAgZm9yICh2YXIgaSA9IDA7IGkgPCB0aGlzLmNvdW50KGNvbGxlY3Rpb24pOyBpKyspIHtcbiAgICAgIGxldCB0dXBsZSA9IGZ1bihjb2xsZWN0aW9uW2ldLCB0aGVfYWNjKTtcblxuICAgICAgdGhlX2FjYyA9IEtlcm5lbC5lbGVtKHR1cGxlLCAxKTtcbiAgICAgIG1hcHBlZCA9IEtlcm5lbC5TcGVjaWFsRm9ybXMubGlzdCguLi5tYXBwZWQuY29uY2F0KFtLZXJuZWwuZWxlbSh0dXBsZSwgMCldKSk7XG4gICAgfVxuXG4gICAgcmV0dXJuIEtlcm5lbC5TcGVjaWFsRm9ybXMudHVwbGUobWFwcGVkLCB0aGVfYWNjKTtcbiAgfSxcblxuICBtZW1iZXI6IGZ1bmN0aW9uIChjb2xsZWN0aW9uLCB2YWx1ZSkge1xuICAgIHJldHVybiBjb2xsZWN0aW9uLmluY2x1ZGVzKHZhbHVlKTtcbiAgfSxcblxuICByZWR1Y2U6IGZ1bmN0aW9uIChjb2xsZWN0aW9uLCBhY2MsIGZ1bikge1xuICAgIGxldCB0aGVfYWNjID0gYWNjO1xuXG4gICAgZm9yICh2YXIgaSA9IDA7IGkgPCB0aGlzLmNvdW50KGNvbGxlY3Rpb24pOyBpKyspIHtcbiAgICAgIGxldCB0dXBsZSA9IGZ1bihjb2xsZWN0aW9uW2ldLCB0aGVfYWNjKTtcblxuICAgICAgdGhlX2FjYyA9IEtlcm5lbC5lbGVtKHR1cGxlLCAxKTtcbiAgICB9XG5cbiAgICByZXR1cm4gdGhlX2FjYztcbiAgfSxcblxuICB0YWtlOiBmdW5jdGlvbiAoY29sbGVjdGlvbiwgY291bnQpIHtcbiAgICByZXR1cm4gY29sbGVjdGlvbi5zbGljZSgwLCBjb3VudCk7XG4gIH0sXG5cbiAgdGFrZV9ldmVyeTogZnVuY3Rpb24gKGNvbGxlY3Rpb24sIG50aCkge1xuICAgIGxldCByZXN1bHQgPSBbXTtcbiAgICBsZXQgaW5kZXggPSAwO1xuXG4gICAgZm9yIChsZXQgZWxlbSBvZiBjb2xsZWN0aW9uKSB7XG4gICAgICBpZiAoaW5kZXggJSBudGggPT09IDApIHtcbiAgICAgICAgcmVzdWx0LnB1c2goZWxlbSk7XG4gICAgICB9XG4gICAgfVxuXG4gICAgcmV0dXJuIEtlcm5lbC5TcGVjaWFsRm9ybXMubGlzdCguLi5yZXN1bHQpO1xuICB9LFxuXG4gIHRha2Vfd2hpbGU6IGZ1bmN0aW9uIChjb2xsZWN0aW9uLCBmdW4pIHtcbiAgICBsZXQgY291bnQgPSAwO1xuXG4gICAgZm9yIChsZXQgZWxlbSBvZiBjb2xsZWN0aW9uKSB7XG4gICAgICBpZiAoZnVuKGVsZW0pKSB7XG4gICAgICAgIGNvdW50ID0gY291bnQgKyAxO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgYnJlYWs7XG4gICAgICB9XG4gICAgfVxuXG4gICAgcmV0dXJuIGNvbGxlY3Rpb24uc2xpY2UoMCwgY291bnQpO1xuICB9LFxuXG4gIHRvX2xpc3Q6IGZ1bmN0aW9uIChjb2xsZWN0aW9uKSB7XG4gICAgcmV0dXJuIGNvbGxlY3Rpb247XG4gIH1cbn07XG5cbmxldCBBdG9tID0ge307XG5cbkF0b20udG9fc3RyaW5nID0gZnVuY3Rpb24gKGF0b20pIHtcbiAgcmV0dXJuIFN5bWJvbC5rZXlGb3IoYXRvbSk7XG59O1xuXG5BdG9tLnRvX2NoYXJfbGlzdCA9IGZ1bmN0aW9uIChhdG9tKSB7XG4gIHJldHVybiBBdG9tLnRvX3N0cmluZyhhdG9tKS5zcGxpdCgnJyk7XG59O1xuXG5sZXQgSW50ZWdlciA9IHtcblxuICBpc19ldmVuOiBmdW5jdGlvbiAobikge1xuICAgIHJldHVybiBuICUgMiA9PT0gMDtcbiAgfSxcblxuICBpc19vZGQ6IGZ1bmN0aW9uIChuKSB7XG4gICAgcmV0dXJuIG4gJSAyICE9PSAwO1xuICB9LFxuXG4gIHBhcnNlOiBmdW5jdGlvbiAoYmluKSB7XG4gICAgbGV0IHJlc3VsdCA9IHBhcnNlSW50KGJpbik7XG5cbiAgICBpZiAoaXNOYU4ocmVzdWx0KSkge1xuICAgICAgcmV0dXJuIEtlcm5lbC5TcGVjaWFsRm9ybXMuYXRvbShcImVycm9yXCIpO1xuICAgIH1cblxuICAgIGxldCBpbmRleE9mRG90ID0gYmluLmluZGV4T2YoXCIuXCIpO1xuXG4gICAgaWYgKGluZGV4T2ZEb3QgPj0gMCkge1xuICAgICAgcmV0dXJuIEtlcm5lbC5TcGVjaWFsRm9ybXMudHVwbGUocmVzdWx0LCBiaW4uc3Vic3RyaW5nKGluZGV4T2ZEb3QpKTtcbiAgICB9XG5cbiAgICByZXR1cm4gS2VybmVsLlNwZWNpYWxGb3Jtcy50dXBsZShyZXN1bHQsIFwiXCIpO1xuICB9LFxuXG4gIHRvX2NoYXJfbGlzdDogZnVuY3Rpb24gKG51bWJlciwgYmFzZSA9IDEwKSB7XG4gICAgcmV0dXJuIG51bWJlci50b1N0cmluZyhiYXNlKS5zcGxpdChcIlwiKTtcbiAgfSxcblxuICB0b19zdHJpbmc6IGZ1bmN0aW9uIChudW1iZXIsIGJhc2UgPSAxMCkge1xuICAgIHJldHVybiBudW1iZXIudG9TdHJpbmcoYmFzZSk7XG4gIH1cbn07XG5cbmxldCBfQ2hhcnMgPSBLZXJuZWwuZGVmcHJvdG9jb2woe1xuICB0b19zdHJpbmc6IGZ1bmN0aW9uICh0aGluZykge31cbn0pO1xuXG5LZXJuZWwuZGVmaW1wbChfQ2hhcnMsIEJpdFN0cmluZywge1xuICB0b19zdHJpbmc6IGZ1bmN0aW9uICh0aGluZykge1xuICAgIGlmIChLZXJuZWwuaXNfYmluYXJ5KHRoaW5nKSkge1xuICAgICAgcmV0dXJuIHRoaW5nO1xuICAgIH1cblxuICAgIHJldHVybiB0aGluZy50b1N0cmluZygpO1xuICB9XG59KTtcblxuS2VybmVsLmRlZmltcGwoX0NoYXJzLCBTeW1ib2wsIHtcbiAgdG9fc3RyaW5nOiBmdW5jdGlvbiAodGhpbmcpIHtcbiAgICBpZiAobmlsKSB7XG4gICAgICByZXR1cm4gXCJcIjtcbiAgICB9XG5cbiAgICByZXR1cm4gQXRvbS50b19zdHJpbmcodGhpbmcpO1xuICB9XG59KTtcblxuS2VybmVsLmRlZmltcGwoX0NoYXJzLCBJbnRlZ2VyVHlwZSwge1xuICB0b19zdHJpbmc6IGZ1bmN0aW9uICh0aGluZykge1xuICAgIHJldHVybiBJbnRlZ2VyLnRvX3N0cmluZyh0aGluZyk7XG4gIH1cbn0pO1xuXG5LZXJuZWwuZGVmaW1wbChfQ2hhcnMsIEZsb2F0VHlwZSwge1xuICB0b19zdHJpbmc6IGZ1bmN0aW9uICh0aGluZykge1xuICAgIHJldHVybiB0aGluZy50b1N0cmluZztcbiAgfVxufSk7XG5cbktlcm5lbC5kZWZpbXBsKF9DaGFycywgQXJyYXksIHtcbiAgdG9fc3RyaW5nOiBmdW5jdGlvbiAodGhpbmcpIHtcbiAgICByZXR1cm4gdGhpbmcudG9TdHJpbmcoKTtcbiAgfVxufSk7XG5cbktlcm5lbC5kZWZpbXBsKF9DaGFycywgVHVwbGUsIHtcbiAgdG9fc3RyaW5nOiBmdW5jdGlvbiAodGhpbmcpIHtcbiAgICByZXR1cm4gVHVwbGUudG9fc3RyaW5nKHRoaW5nKTtcbiAgfVxufSk7XG5cbktlcm5lbC5kZWZpbXBsKF9DaGFycywgbnVsbCwge1xuICB0b19zdHJpbmc6IGZ1bmN0aW9uICh0aGluZykge1xuICAgIHJldHVybiB0aGluZy50b1N0cmluZygpO1xuICB9XG59KTtcblxuZnVuY3Rpb24gdG9fYXRvbShzdHJpbmcpIHtcbiAgcmV0dXJuIFN5bWJvbC5mb3Ioc3RyaW5nKTtcbn1cblxuZnVuY3Rpb24gdG9fZXhpc3RpbmdfYXRvbShzdHJpbmcpIHtcbiAgcmV0dXJuIFN5bWJvbC5mb3Ioc3RyaW5nKTtcbn1cblxuZnVuY3Rpb24gdG9fY2hhcl9saXN0KHN0cmluZykge1xuICByZXR1cm4gc3RyaW5nLnNwbGl0KCcnKTtcbn1cblxuZnVuY3Rpb24gdG9fZmxvYXQoc3RyaW5nKSB7XG4gIHJldHVybiBwYXJzZUZsb2F0KHN0cmluZyk7XG59XG5cbmZ1bmN0aW9uIHRvX2ludGVnZXIoc3RyaW5nLCBiYXNlID0gMTApIHtcbiAgcmV0dXJuIHBhcnNlSW50KHN0cmluZywgYmFzZSk7XG59XG5cbmZ1bmN0aW9uIHVwY2FzZShiaW5hcnkpIHtcbiAgcmV0dXJuIGJpbmFyeS50b1VwcGVyQ2FzZSgpO1xufVxuXG5mdW5jdGlvbiBkb3duY2FzZShiaW5hcnkpIHtcbiAgcmV0dXJuIGJpbmFyeS50b0xvd2VyQ2FzZSgpO1xufVxuXG5mdW5jdGlvbiBhdChzdHJpbmcsIHBvc2l0aW9uKSB7XG4gIGlmIChwb3NpdGlvbiA+IHN0cmluZy5sZW5ndGggLSAxKSB7XG4gICAgcmV0dXJuIG51bGw7XG4gIH1cblxuICByZXR1cm4gc3RyaW5nW3Bvc2l0aW9uXTtcbn1cblxuZnVuY3Rpb24gY2FwaXRhbGl6ZShzdHJpbmcpIHtcbiAgbGV0IHJldHVyblN0cmluZyA9ICcnO1xuXG4gIGZvciAobGV0IGkgPSAwOyBpIDwgc3RyaW5nLmxlbmd0aDsgaSsrKSB7XG4gICAgaWYgKGkgPT09IDApIHtcbiAgICAgIHJldHVyblN0cmluZyA9IHJldHVyblN0cmluZyArIHN0cmluZ1tpXS50b1VwcGVyQ2FzZSgpO1xuICAgIH0gZWxzZSB7XG4gICAgICByZXR1cm5TdHJpbmcgPSByZXR1cm5TdHJpbmcgKyBzdHJpbmdbaV0udG9Mb3dlckNhc2UoKTtcbiAgICB9XG4gIH1cblxuICByZXR1cm4gcmV0dXJuU3RyaW5nO1xufVxuXG5mdW5jdGlvbiBjb2RlcG9pbnRzKHN0cmluZykge1xuICByZXR1cm4gdG9fY2hhcl9saXN0KHN0cmluZykubWFwKGZ1bmN0aW9uIChjKSB7XG4gICAgcmV0dXJuIGMuY29kZVBvaW50QXQoMCk7XG4gIH0pO1xufVxuXG5mdW5jdGlvbiBjb250YWluc19fcW1fXyhzdHJpbmcsIGNvbnRhaW5zKSB7XG4gIGlmIChBcnJheS5pc0FycmF5KGNvbnRhaW5zKSkge1xuICAgIHJldHVybiBjb250YWlucy5zb21lKGZ1bmN0aW9uIChzKSB7XG4gICAgICByZXR1cm4gc3RyaW5nLmluZGV4T2YocykgPiAtMTtcbiAgICB9KTtcbiAgfVxuXG4gIHJldHVybiBzdHJpbmcuaW5kZXhPZihjb250YWlucykgPiAtMTtcbn1cblxuZnVuY3Rpb24gZHVwbGljYXRlKHN1YmplY3QsIG4pIHtcbiAgcmV0dXJuIHN1YmplY3QucmVwZWF0KG4pO1xufVxuXG5mdW5jdGlvbiBlbmRzX3dpdGhfX3FtX18oc3RyaW5nLCBzdWZmaXhlcykge1xuICBpZiAoQXJyYXkuaXNBcnJheShzdWZmaXhlcykpIHtcbiAgICByZXR1cm4gc3VmZml4ZXMuc29tZShmdW5jdGlvbiAocykge1xuICAgICAgcmV0dXJuIHN0cmluZy5lbmRzV2l0aChzKTtcbiAgICB9KTtcbiAgfVxuXG4gIHJldHVybiBzdHJpbmcuZW5kc1dpdGgoc3VmZml4ZXMpO1xufVxuXG5mdW5jdGlvbiBmaXJzdChzdHJpbmcpIHtcbiAgaWYgKCFzdHJpbmcpIHtcbiAgICByZXR1cm4gbnVsbDtcbiAgfVxuXG4gIHJldHVybiBzdHJpbmdbMF07XG59XG5cbmZ1bmN0aW9uIGdyYXBoZW1lcyhzdHJpbmcpIHtcbiAgcmV0dXJuIHN0cmluZy5zcGxpdCgnJyk7XG59XG5cbmZ1bmN0aW9uIGxhc3Qoc3RyaW5nKSB7XG4gIGlmICghc3RyaW5nKSB7XG4gICAgcmV0dXJuIG51bGw7XG4gIH1cblxuICByZXR1cm4gc3RyaW5nW3N0cmluZy5sZW5ndGggLSAxXTtcbn1cblxuZnVuY3Rpb24gbGVuZ3RoKHN0cmluZykge1xuICByZXR1cm4gc3RyaW5nLmxlbmd0aDtcbn1cblxuZnVuY3Rpb24gbWF0Y2hfX3FtX18oc3RyaW5nLCByZWdleCkge1xuICByZXR1cm4gc3RyaW5nLm1hdGNoKHJlZ2V4KSAhPSBudWxsO1xufVxuXG5mdW5jdGlvbiBuZXh0X2NvZGVwb2ludChzdHJpbmcpIHtcbiAgaWYgKCFzdHJpbmcgfHwgc3RyaW5nID09PSAnJykge1xuICAgIHJldHVybiBudWxsO1xuICB9XG5cbiAgcmV0dXJuIEtlcm5lbC5TcGVjaWFsRm9ybXMudHVwbGUoc3RyaW5nWzBdLmNvZGVQb2ludEF0KDApLCBzdHJpbmcuc3Vic3RyKDEpKTtcbn1cblxuZnVuY3Rpb24gbmV4dF9ncmFwaGVtZShzdHJpbmcpIHtcbiAgaWYgKCFzdHJpbmcgfHwgc3RyaW5nID09PSAnJykge1xuICAgIHJldHVybiBudWxsO1xuICB9XG5cbiAgcmV0dXJuIEtlcm5lbC5TcGVjaWFsRm9ybXMudHVwbGUoc3RyaW5nWzBdLCBzdHJpbmcuc3Vic3RyKDEpKTtcbn1cblxuZnVuY3Rpb24gcmV2ZXJzZShzdHJpbmcpIHtcbiAgbGV0IHJldHVyblZhbHVlID0gJyc7XG5cbiAgZm9yICh2YXIgaSA9IHN0cmluZy5sZW5ndGggLSAxOyBpID49IDA7IGktLSkge1xuICAgIHJldHVyblZhbHVlID0gcmV0dXJuVmFsdWUgKyBzdHJpbmdbaV07XG4gIH07XG5cbiAgcmV0dXJuIHJldHVyblZhbHVlO1xufVxuXG5mdW5jdGlvbiBfc3BsaXQoc3RyaW5nKSB7XG4gIHJldHVybiBzdHJpbmcuc3BsaXQoKTtcbn1cblxuZnVuY3Rpb24gc3RhcnRzX3dpdGhfX3FtX18oc3RyaW5nLCBwcmVmaXhlcykge1xuICBpZiAoQXJyYXkuaXNBcnJheShwcmVmaXhlcykpIHtcbiAgICByZXR1cm4gcHJlZml4ZXMuc29tZShmdW5jdGlvbiAocykge1xuICAgICAgcmV0dXJuIHN0cmluZy5zdGFydHNXaXRoKHMpO1xuICAgIH0pO1xuICB9XG5cbiAgcmV0dXJuIHN0cmluZy5zdGFydHNXaXRoKHByZWZpeGVzKTtcbn1cblxuZnVuY3Rpb24gdmFsaWRfY2hhcmFjdGVyX19xbV9fKGNvZGVwb2ludCkge1xuICB0cnkge1xuICAgIHJldHVybiBTdHJpbmcuZnJvbUNvZGVQb2ludChjb2RlcG9pbnQpICE9IG51bGw7XG4gIH0gY2F0Y2ggKGUpIHtcbiAgICByZXR1cm4gZmFsc2U7XG4gIH1cbn1cblxudmFyIF9TdHJpbmcgPSB7XG4gIGF0LFxuICBjYXBpdGFsaXplLFxuICBjb2RlcG9pbnRzLFxuICBjb250YWluc19fcW1fXyxcbiAgZG93bmNhc2UsXG4gIGR1cGxpY2F0ZSxcbiAgZW5kc193aXRoX19xbV9fLFxuICBmaXJzdCxcbiAgZ3JhcGhlbWVzLFxuICBsYXN0LFxuICBsZW5ndGgsXG4gIG1hdGNoX19xbV9fLFxuICBuZXh0X2NvZGVwb2ludCxcbiAgbmV4dF9ncmFwaGVtZSxcbiAgcmV2ZXJzZSxcbiAgc3BsaXQ6IF9zcGxpdCxcbiAgc3RhcnRzX3dpdGhfX3FtX18sXG4gIHRvX2F0b20sXG4gIHRvX2NoYXJfbGlzdCxcbiAgdG9fZXhpc3RpbmdfYXRvbSxcbiAgdG9fZmxvYXQsXG4gIHRvX2ludGVnZXIsXG4gIHVwY2FzZSxcbiAgdmFsaWRfY2hhcmFjdGVyX19xbV9fLFxuICBDaGFyczogX0NoYXJzXG59O1xuXG5sZXQgQ2hhcnMgPSBLZXJuZWwuZGVmcHJvdG9jb2woe1xuICB0b19jaGFyX2xpc3Q6IGZ1bmN0aW9uICh0aGluZykge31cbn0pO1xuXG5LZXJuZWwuZGVmaW1wbChDaGFycywgS2VybmVsLmlzX2JpdHN0cmluZywge1xuICB0b19jaGFyX2xpc3Q6IGZ1bmN0aW9uICh0aGluZykge1xuICAgIGlmIChLZXJuZWwuaXNfYmluYXJ5KHRoaW5nKSkge1xuICAgICAgcmV0dXJuIF9TdHJpbmcudG9fY2hhcl9saXN0KHRoaW5nKTtcbiAgICB9XG5cbiAgICByZXR1cm4gdGhpbmcudG9TdHJpbmcoKTtcbiAgfVxufSk7XG5cbktlcm5lbC5kZWZpbXBsKENoYXJzLCBLZXJuZWwuaXNfYXRvbSwge1xuICB0b19jaGFyX2xpc3Q6IGZ1bmN0aW9uICh0aGluZykge1xuICAgIHJldHVybiBBdG9tLnRvX2NoYXJfbGlzdCh0aGluZyk7XG4gIH1cbn0pO1xuXG5LZXJuZWwuZGVmaW1wbChDaGFycywgS2VybmVsLmlzX2ludGVnZXIsIHtcbiAgdG9fY2hhcl9saXN0OiBmdW5jdGlvbiAodGhpbmcpIHtcbiAgICByZXR1cm4gSW50ZWdlci50b19jaGFyX2xpc3QodGhpbmcpO1xuICB9XG59KTtcblxuS2VybmVsLmRlZmltcGwoQ2hhcnMsIEtlcm5lbC5pc19saXN0LCB7XG4gIHRvX2NoYXJfbGlzdDogZnVuY3Rpb24gKHRoaW5nKSB7XG4gICAgcmV0dXJuIHRoaW5nO1xuICB9XG59KTtcblxubGV0IExpc3QgPSB7fTtcblxuTGlzdC5DaGFycyA9IENoYXJzO1xuXG5MaXN0LmRlbGV0ZSA9IGZ1bmN0aW9uIChsaXN0LCBpdGVtKSB7XG4gIGxldCBuZXdfdmFsdWUgPSBbXTtcbiAgbGV0IHZhbHVlX2ZvdW5kID0gZmFsc2U7XG5cbiAgZm9yIChsZXQgeCBvZiBsaXN0KSB7XG4gICAgaWYgKHggPT09IGl0ZW0gJiYgdmFsdWVfZm91bmQgIT09IGZhbHNlKSB7XG4gICAgICBuZXdfdmFsdWUucHVzaCh4KTtcbiAgICAgIHZhbHVlX2ZvdW5kID0gdHJ1ZTtcbiAgICB9IGVsc2UgaWYgKHggIT09IGl0ZW0pIHtcbiAgICAgIG5ld192YWx1ZS5wdXNoKHgpO1xuICAgIH1cbiAgfVxuXG4gIHJldHVybiBLZXJuZWwuU3BlY2lhbEZvcm1zLmxpc3QoLi4ubmV3X3ZhbHVlKTtcbn07XG5cbkxpc3QuZGVsZXRlX2F0ID0gZnVuY3Rpb24gKGxpc3QsIGluZGV4KSB7XG4gIGxldCBuZXdfdmFsdWUgPSBbXTtcblxuICBmb3IgKGxldCBpID0gMDsgaSA8IGxpc3QubGVuZ3RoOyBpKyspIHtcbiAgICBpZiAoaSAhPT0gaW5kZXgpIHtcbiAgICAgIG5ld192YWx1ZS5wdXNoKGxpc3RbaV0pO1xuICAgIH1cbiAgfVxuXG4gIHJldHVybiBLZXJuZWwuU3BlY2lhbEZvcm1zLmxpc3QoLi4ubmV3X3ZhbHVlKTtcbn07XG5cbkxpc3QuZHVwbGljYXRlID0gZnVuY3Rpb24gKGVsZW0sIG4pIHtcbiAgbGV0IG5ld192YWx1ZSA9IFtdO1xuXG4gIGZvciAodmFyIGkgPSAwOyBpIDwgbjsgaSsrKSB7XG4gICAgbmV3X3ZhbHVlLnB1c2goZWxlbSk7XG4gIH1cblxuICByZXR1cm4gS2VybmVsLlNwZWNpYWxGb3Jtcy5saXN0KC4uLm5ld192YWx1ZSk7XG59O1xuXG5MaXN0LmZpcnN0ID0gZnVuY3Rpb24gKGxpc3QpIHtcbiAgcmV0dXJuIGxpc3RbMF07XG59O1xuXG5MaXN0LmZsYXR0ZW4gPSBmdW5jdGlvbiAobGlzdCwgdGFpbCA9IEtlcm5lbC5TcGVjaWFsRm9ybXMubGlzdCgpKSB7XG4gIGxldCBuZXdfdmFsdWUgPSBbXTtcblxuICBmb3IgKGxldCB4IG9mIGxpc3QpIHtcbiAgICBpZiAoS2VybmVsLmlzX2xpc3QoeCkpIHtcbiAgICAgIG5ld192YWx1ZSA9IG5ld192YWx1ZS5jb25jYXQoTGlzdC5mbGF0dGVuKHgpKTtcbiAgICB9IGVsc2Uge1xuICAgICAgbmV3X3ZhbHVlLnB1c2goeCk7XG4gICAgfVxuICB9XG5cbiAgbmV3X3ZhbHVlID0gbmV3X3ZhbHVlLmNvbmNhdCh0YWlsKTtcblxuICByZXR1cm4gS2VybmVsLlNwZWNpYWxGb3Jtcy5saXN0KC4uLm5ld192YWx1ZSk7XG59O1xuXG5MaXN0LmZvbGRsID0gZnVuY3Rpb24gKGxpc3QsIGFjYywgZnVuYykge1xuICByZXR1cm4gbGlzdC5yZWR1Y2UoZnVuYywgYWNjKTtcbn07XG5cbkxpc3QuZm9sZHIgPSBmdW5jdGlvbiAobGlzdCwgYWNjLCBmdW5jKSB7XG4gIGxldCBuZXdfYWNjID0gYWNjO1xuXG4gIGZvciAodmFyIGkgPSBsaXN0Lmxlbmd0aCAtIDE7IGkgPj0gMDsgaS0tKSB7XG4gICAgbmV3X2FjYyA9IGZ1bmMobGlzdFtpXSwgbmV3X2FjYyk7XG4gIH1cblxuICByZXR1cm4gbmV3X2FjYztcbn07XG5cbkxpc3QuaW5zZXJ0X2F0ID0gZnVuY3Rpb24gKGxpc3QsIGluZGV4LCB2YWx1ZSkge1xuICBsZXQgbmV3X3ZhbHVlID0gW107XG5cbiAgZm9yIChsZXQgaSA9IDA7IGkgPCBsaXN0Lmxlbmd0aDsgaSsrKSB7XG4gICAgaWYgKGkgPT09IGluZGV4KSB7XG4gICAgICBuZXdfdmFsdWUucHVzaCh2YWx1ZSk7XG4gICAgICBuZXdfdmFsdWUucHVzaChsaXN0W2ldKTtcbiAgICB9IGVsc2Uge1xuICAgICAgbmV3X3ZhbHVlLnB1c2gobGlzdFtpXSk7XG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIEtlcm5lbC5TcGVjaWFsRm9ybXMubGlzdCguLi5uZXdfdmFsdWUpO1xufTtcblxuTGlzdC5rZXlkZWxldGUgPSBmdW5jdGlvbiAobGlzdCwga2V5LCBwb3NpdGlvbikge1xuICBsZXQgbmV3X2xpc3QgPSBbXTtcblxuICBmb3IgKGxldCBpID0gMDsgaSA8IGxpc3QubGVuZ3RoOyBpKyspIHtcbiAgICBpZiAoIUtlcm5lbC5tYXRjaF9fcW1hcmtfXyhsaXN0W2ldW3Bvc2l0aW9uXSwga2V5KSkge1xuICAgICAgbmV3X2xpc3QucHVzaChsaXN0W2ldKTtcbiAgICB9XG4gIH1cblxuICByZXR1cm4gS2VybmVsLlNwZWNpYWxGb3Jtcy5saXN0KC4uLm5ld19saXN0KTtcbn07XG5cbkxpc3Qua2V5ZmluZCA9IGZ1bmN0aW9uIChsaXN0LCBrZXksIHBvc2l0aW9uLCBfZGVmYXVsdCA9IG51bGwpIHtcblxuICBmb3IgKGxldCBpID0gMDsgaSA8IGxpc3QubGVuZ3RoOyBpKyspIHtcbiAgICBpZiAoS2VybmVsLm1hdGNoX19xbWFya19fKGxpc3RbaV1bcG9zaXRpb25dLCBrZXkpKSB7XG4gICAgICByZXR1cm4gbGlzdFtpXTtcbiAgICB9XG4gIH1cblxuICByZXR1cm4gX2RlZmF1bHQ7XG59O1xuXG5MaXN0LmtleW1lbWJlcl9fcW1hcmtfXyA9IGZ1bmN0aW9uIChsaXN0LCBrZXksIHBvc2l0aW9uKSB7XG5cbiAgZm9yIChsZXQgaSA9IDA7IGkgPCBsaXN0Lmxlbmd0aDsgaSsrKSB7XG4gICAgaWYgKEtlcm5lbC5tYXRjaF9fcW1hcmtfXyhsaXN0W2ldW3Bvc2l0aW9uXSwga2V5KSkge1xuICAgICAgcmV0dXJuIHRydWU7XG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIGZhbHNlO1xufTtcblxuTGlzdC5rZXlyZXBsYWNlID0gZnVuY3Rpb24gKGxpc3QsIGtleSwgcG9zaXRpb24sIG5ld190dXBsZSkge1xuICBsZXQgbmV3X2xpc3QgPSBbXTtcblxuICBmb3IgKGxldCBpID0gMDsgaSA8IGxpc3QubGVuZ3RoOyBpKyspIHtcbiAgICBpZiAoIUtlcm5lbC5tYXRjaF9fcW1hcmtfXyhsaXN0W2ldW3Bvc2l0aW9uXSwga2V5KSkge1xuICAgICAgbmV3X2xpc3QucHVzaChsaXN0W2ldKTtcbiAgICB9IGVsc2Uge1xuICAgICAgbmV3X2xpc3QucHVzaChuZXdfdHVwbGUpO1xuICAgIH1cbiAgfVxuXG4gIHJldHVybiBLZXJuZWwuU3BlY2lhbEZvcm1zLmxpc3QoLi4ubmV3X2xpc3QpO1xufTtcblxuTGlzdC5rZXlzb3J0ID0gZnVuY3Rpb24gKGxpc3QsIHBvc2l0aW9uKSB7XG4gIGxldCBuZXdfbGlzdCA9IGxpc3Q7XG5cbiAgbmV3X2xpc3Quc29ydChmdW5jdGlvbiAoYSwgYikge1xuICAgIGlmIChwb3NpdGlvbiA9PT0gMCkge1xuICAgICAgaWYgKGFbcG9zaXRpb25dLnZhbHVlIDwgYltwb3NpdGlvbl0udmFsdWUpIHtcbiAgICAgICAgcmV0dXJuIC0xO1xuICAgICAgfVxuXG4gICAgICBpZiAoYVtwb3NpdGlvbl0udmFsdWUgPiBiW3Bvc2l0aW9uXS52YWx1ZSkge1xuICAgICAgICByZXR1cm4gMTtcbiAgICAgIH1cblxuICAgICAgcmV0dXJuIDA7XG4gICAgfSBlbHNlIHtcbiAgICAgIGlmIChhW3Bvc2l0aW9uXSA8IGJbcG9zaXRpb25dKSB7XG4gICAgICAgIHJldHVybiAtMTtcbiAgICAgIH1cblxuICAgICAgaWYgKGFbcG9zaXRpb25dID4gYltwb3NpdGlvbl0pIHtcbiAgICAgICAgcmV0dXJuIDE7XG4gICAgICB9XG5cbiAgICAgIHJldHVybiAwO1xuICAgIH1cbiAgfSk7XG5cbiAgcmV0dXJuIEtlcm5lbC5TcGVjaWFsRm9ybXMubGlzdCguLi5uZXdfbGlzdCk7XG59O1xuXG5MaXN0LmtleXN0b3JlID0gZnVuY3Rpb24gKGxpc3QsIGtleSwgcG9zaXRpb24sIG5ld190dXBsZSkge1xuICBsZXQgbmV3X2xpc3QgPSBbXTtcbiAgbGV0IHJlcGxhY2VkID0gZmFsc2U7XG5cbiAgZm9yIChsZXQgaSA9IDA7IGkgPCBsaXN0Lmxlbmd0aDsgaSsrKSB7XG4gICAgaWYgKCFLZXJuZWwubWF0Y2hfX3FtYXJrX18obGlzdFtpXVtwb3NpdGlvbl0sIGtleSkpIHtcbiAgICAgIG5ld19saXN0LnB1c2gobGlzdFtpXSk7XG4gICAgfSBlbHNlIHtcbiAgICAgIG5ld19saXN0LnB1c2gobmV3X3R1cGxlKTtcbiAgICAgIHJlcGxhY2VkID0gdHJ1ZTtcbiAgICB9XG4gIH1cblxuICBpZiAoIXJlcGxhY2VkKSB7XG4gICAgbmV3X2xpc3QucHVzaChuZXdfdHVwbGUpO1xuICB9XG5cbiAgcmV0dXJuIEtlcm5lbC5TcGVjaWFsRm9ybXMubGlzdCguLi5uZXdfbGlzdCk7XG59O1xuXG5MaXN0Lmxhc3QgPSBmdW5jdGlvbiAobGlzdCkge1xuICByZXR1cm4gbGlzdFtsaXN0Lmxlbmd0aCAtIDFdO1xufTtcblxuTGlzdC5yZXBsYWNlX2F0ID0gZnVuY3Rpb24gKGxpc3QsIGluZGV4LCB2YWx1ZSkge1xuICBsZXQgbmV3X3ZhbHVlID0gW107XG5cbiAgZm9yIChsZXQgaSA9IDA7IGkgPCBsaXN0Lmxlbmd0aDsgaSsrKSB7XG4gICAgaWYgKGkgPT09IGluZGV4KSB7XG4gICAgICBuZXdfdmFsdWUucHVzaCh2YWx1ZSk7XG4gICAgfSBlbHNlIHtcbiAgICAgIG5ld192YWx1ZS5wdXNoKGxpc3RbaV0pO1xuICAgIH1cbiAgfVxuXG4gIHJldHVybiBLZXJuZWwuU3BlY2lhbEZvcm1zLmxpc3QoLi4ubmV3X3ZhbHVlKTtcbn07XG5cbkxpc3QudXBkYXRlX2F0ID0gZnVuY3Rpb24gKGxpc3QsIGluZGV4LCBmdW4pIHtcbiAgbGV0IG5ld192YWx1ZSA9IFtdO1xuXG4gIGZvciAobGV0IGkgPSAwOyBpIDwgbGlzdC5jb3VudCgpOyBpKyspIHtcbiAgICBpZiAoaSA9PT0gaW5kZXgpIHtcbiAgICAgIG5ld192YWx1ZS5wdXNoKGZ1bihsaXN0LmdldChpKSkpO1xuICAgIH0gZWxzZSB7XG4gICAgICBuZXdfdmFsdWUucHVzaChsaXN0LmdldChpKSk7XG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIG5ld192YWx1ZTtcbn07XG5cbkxpc3Qud3JhcCA9IGZ1bmN0aW9uIChsaXN0KSB7XG4gIGlmIChLZXJuZWwuaXNfbGlzdChsaXN0KSkge1xuICAgIHJldHVybiBsaXN0O1xuICB9IGVsc2UgaWYgKGxpc3QgPT0gbnVsbCkge1xuICAgIHJldHVybiBLZXJuZWwuU3BlY2lhbEZvcm1zLmxpc3QoKTtcbiAgfSBlbHNlIHtcbiAgICByZXR1cm4gS2VybmVsLlNwZWNpYWxGb3Jtcy5saXN0KGxpc3QpO1xuICB9XG59O1xuXG5MaXN0LnppcCA9IGZ1bmN0aW9uIChsaXN0X29mX2xpc3RzKSB7XG4gIGlmIChsaXN0X29mX2xpc3RzLmxlbmd0aCA9PT0gMCkge1xuICAgIHJldHVybiBLZXJuZWwuU3BlY2lhbEZvcm1zLmxpc3QoKTtcbiAgfVxuXG4gIGxldCBuZXdfdmFsdWUgPSBbXTtcbiAgbGV0IHNtYWxsZXN0X2xlbmd0aCA9IGxpc3Rfb2ZfbGlzdHNbMF07XG5cbiAgZm9yIChsZXQgeCBvZiBsaXN0X29mX2xpc3RzKSB7XG4gICAgaWYgKHgubGVuZ3RoIDwgc21hbGxlc3RfbGVuZ3RoKSB7XG4gICAgICBzbWFsbGVzdF9sZW5ndGggPSB4Lmxlbmd0aDtcbiAgICB9XG4gIH1cblxuICBmb3IgKGxldCBpID0gMDsgaSA8IHNtYWxsZXN0X2xlbmd0aDsgaSsrKSB7XG4gICAgbGV0IGN1cnJlbnRfdmFsdWUgPSBbXTtcbiAgICBmb3IgKGxldCBqID0gMDsgaiA8IGxpc3Rfb2ZfbGlzdHMubGVuZ3RoOyBqKyspIHtcbiAgICAgIGN1cnJlbnRfdmFsdWUucHVzaChsaXN0X29mX2xpc3RzW2pdW2ldKTtcbiAgICB9XG5cbiAgICBuZXdfdmFsdWUucHVzaChLZXJuZWwuU3BlY2lhbEZvcm1zLnR1cGxlKC4uLmN1cnJlbnRfdmFsdWUpKTtcbiAgfVxuXG4gIHJldHVybiBLZXJuZWwuU3BlY2lhbEZvcm1zLmxpc3QoLi4ubmV3X3ZhbHVlKTtcbn07XG5cbkxpc3QudG9fdHVwbGUgPSBmdW5jdGlvbiAobGlzdCkge1xuICByZXR1cm4gS2VybmVsLlNwZWNpYWxGb3Jtcy50dXBsZS5hcHBseShudWxsLCBsaXN0KTtcbn07XG5cbkxpc3QuYXBwZW5kID0gZnVuY3Rpb24gKGxpc3QsIHZhbHVlKSB7XG4gIHJldHVybiBLZXJuZWwuU3BlY2lhbEZvcm1zLmxpc3QoLi4ubGlzdC5jb25jYXQoW3ZhbHVlXSkpO1xufTtcblxuTGlzdC5wcmVwZW5kID0gZnVuY3Rpb24gKGxpc3QsIHZhbHVlKSB7XG4gIHJldHVybiBLZXJuZWwuU3BlY2lhbEZvcm1zLmxpc3QoLi4uW3ZhbHVlXS5jb25jYXQobGlzdCkpO1xufTtcblxuTGlzdC5jb25jYXQgPSBmdW5jdGlvbiAobGVmdCwgcmlnaHQpIHtcbiAgcmV0dXJuIGxlZnQuY29uY2F0KHJpZ2h0KTtcbn07XG5cbmNsYXNzIFNpZ25hbCB7XG5cbiAgY29uc3RydWN0b3IoKSB7XG4gICAgdGhpcy5iaW5kaW5ncyA9IFNwZWNpYWxGb3Jtcy5saXN0KCk7XG4gIH1cblxuICBhZGQobGlzdGVuZXIsIGNvbnRleHQgPSB0aGlzKSB7XG4gICAgdGhpcy5iaW5kaW5ncyA9IExpc3QuYXBwZW5kKHRoaXMuYmluZGluZ3MsIG5ldyBTaWduYWxCaW5kaW5nKHRoaXMsIGxpc3RlbmVyLCBjb250ZXh0KSk7XG4gIH1cblxuICByZW1vdmUobGlzdGVuZXIpIHtcbiAgICB0aGlzLmJpbmRpbmdzID0gRW51bS5maWx0ZXIodGhpcy5iaW5kaW5ncywgZnVuY3Rpb24gKGJpbmRpbmcpIHtcbiAgICAgIHJldHVybiBiaW5kaW5nLmxpc3RlbmVyICE9PSBsaXN0ZW5lcjtcbiAgICB9KTtcbiAgfVxuXG4gIGRpc3BhdGNoKC4uLnBhcmFtcykge1xuICAgIGZvciAobGV0IGJpbmRpbmcgb2YgdGhpcy5iaW5kaW5ncykge1xuICAgICAgYmluZGluZy5leGVjdXRlKC4uLnBhcmFtcyk7XG4gICAgfVxuICB9XG5cbiAgZGlzcG9zZSgpIHtcbiAgICBmb3IgKGxldCBiaW5kaW5nIG9mIHRoaXMuYmluZGluZ3MpIHtcbiAgICAgIGJpbmRpbmcuZGlzcG9zZSgpO1xuICAgIH1cblxuICAgIHRoaXMuYmluZGluZ3MgPSBudWxsO1xuICB9XG59XG5cbmNsYXNzIFNpZ25hbEJpbmRpbmcge1xuXG4gIGNvbnN0cnVjdG9yKHNpZ25hbCwgbGlzdGVuZXIsIGNvbnRleHQpIHtcbiAgICB0aGlzLmxpc3RlbmVyID0gbGlzdGVuZXI7XG4gICAgdGhpcy5zaWduYWwgPSBzaWduYWw7XG4gICAgdGhpcy5jb250ZXh0ID0gY29udGV4dDtcbiAgfVxuXG4gIGV4ZWN1dGUoLi4ucGFyYW1zKSB7XG4gICAgdGhpcy5saXN0ZW5lci5hcHBseSh0aGlzLmNvbnRleHQsIHBhcmFtcyk7XG4gIH1cblxuICBkaXNwb3NlKCkge1xuICAgIHRoaXMubGlzdGVuZXIgPSBudWxsO1xuICAgIHRoaXMuc2lnbmFsID0gbnVsbDtcbiAgICB0aGlzLmNvbnRleHQgPSBudWxsO1xuICB9XG59XG5cbmZ1bmN0aW9uIF9fdXBkYXRlKG1hcCwga2V5LCB2YWx1ZSkge1xuICBsZXQgbSA9IG5ldyBNYXAobWFwKTtcbiAgbS5zZXQoa2V5LCB2YWx1ZSk7XG4gIHJldHVybiBtO1xufVxuXG5mdW5jdGlvbiByZW1vdmUobWFwLCBrZXkpIHtcbiAgbGV0IG0gPSBuZXcgTWFwKG1hcCk7XG4gIG0uZGVsZXRlKGtleSk7XG4gIHJldHVybiBtO1xufVxuXG5jbGFzcyBNYWlsQm94IHtcblxuICBjb25zdHJ1Y3Rvcihjb250ZXh0ID0gdGhpcykge1xuICAgIHRoaXMuc2lnbmFsID0gbmV3IFNpZ25hbCgpO1xuICAgIHRoaXMuc2lnbmFsLmFkZCgoLi4ucGFyYW1zKSA9PiB0aGlzLm1lc3NhZ2VzID0gdGhpcy5tZXNzYWdlcy5jb25jYXQocGFyYW1zKSwgY29udGV4dCk7XG4gICAgdGhpcy5tZXNzYWdlcyA9IFtdO1xuICB9XG5cbiAgcmVjZWl2ZSguLi5tZXNzYWdlcykge1xuICAgIHRoaXMuc2lnbmFsLmRpc3BhdGNoKC4uLm1lc3NhZ2VzKTtcbiAgfVxuXG4gIHBlZWsoKSB7XG4gICAgaWYgKHRoaXMubWVzc2FnZXMubGVuZ3RoID09PSAwKSB7XG4gICAgICByZXR1cm4gbnVsbDtcbiAgICB9XG5cbiAgICByZXR1cm4gdGhpcy5tZXNzYWdlc1swXTtcbiAgfVxuXG4gIHJlYWQoKSB7XG4gICAgbGV0IHJlc3VsdCA9IHRoaXMubWVzc2FnZXNbMF07XG4gICAgdGhpcy5tZXNzYWdlcyA9IHRoaXMubWVzc2FnZXMuc2xpY2UoMSk7XG5cbiAgICByZXR1cm4gcmVzdWx0O1xuICB9XG5cbiAgYWRkX3N1YnNjcmliZXIoZm4sIGNvbnRleHQgPSB0aGlzKSB7XG4gICAgdGhpcy5zaWduYWwuYWRkKGZuLCBjb250ZXh0KTtcbiAgfVxuXG4gIHJlbW92ZV9zdWJzY3JpYmVyKGZuKSB7XG4gICAgdGhpcy5zaWduYWwucmVtb3ZlKGZuKTtcbiAgfVxuXG4gIGRpc3Bvc2UoKSB7XG4gICAgdGhpcy5zaWduYWwuZGlzcG9zZSgpO1xuICAgIHRoaXMubWVzc2FnZXMgPSBudWxsO1xuICB9XG59XG5cbmNsYXNzIFBvc3RPZmZpY2Uge1xuXG4gIGNvbnN0cnVjdG9yKCkge1xuICAgIHRoaXMubWFpbGJveGVzID0gbmV3IE1hcCgpO1xuICB9XG5cbiAgc2VuZChhZGRyZXNzLCBtZXNzYWdlKSB7XG4gICAgdGhpcy5tYWlsYm94ZXMuZ2V0KGFkZHJlc3MpLnJlY2VpdmUobWVzc2FnZSk7XG4gIH1cblxuICByZWNlaXZlKGFkZHJlc3MpIHtcbiAgICByZXR1cm4gdGhpcy5tYWlsYm94ZXMuZ2V0KGFkZHJlc3MpLnJlYWQoKTtcbiAgfVxuXG4gIHBlZWsoYWRkcmVzcykge1xuICAgIHJldHVybiB0aGlzLm1haWxib3hlcy5nZXQoYWRkcmVzcykucGVlaygpO1xuICB9XG5cbiAgYWRkX21haWxib3goYWRkcmVzcyA9IFN5bWJvbCgpLCBjb250ZXh0ID0gdGhpcykge1xuICAgIHRoaXMubWFpbGJveGVzID0gX191cGRhdGUodGhpcy5tYWlsYm94ZXMsIGFkZHJlc3MsIG5ldyBNYWlsQm94KCkpO1xuICAgIHJldHVybiBhZGRyZXNzO1xuICB9XG5cbiAgcmVtb3ZlX21haWxib3goYWRkcmVzcykge1xuICAgIHRoaXMubWFpbGJveGVzLmdldChhZGRyZXNzKS5kaXNwb3NlKCk7XG4gICAgdGhpcy5tYWlsYm94ZXMgPSByZW1vdmUodGhpcy5tYWlsYm94ZXMsIGFkZHJlc3MpO1xuICB9XG5cbiAgc3Vic2NyaWJlKGFkZHJlc3MsIHN1YnNjcmlidGlvbl9mbiwgY29udGV4dCA9IHRoaXMpIHtcbiAgICB0aGlzLm1haWxib3hlcy5nZXQoYWRkcmVzcykuYWRkX3N1YnNjcmliZXIoc3Vic2NyaWJ0aW9uX2ZuLCBjb250ZXh0KTtcbiAgfVxuXG4gIHVuc3Vic2NyaWJlKGFkZHJlc3MsIHN1YnNjcmlidGlvbl9mbikge1xuICAgIHRoaXMubWFpbGJveGVzLmdldChhZGRyZXNzKS5yZW1vdmVfc3Vic2NyaWJlcihzdWJzY3JpYnRpb25fZm4pO1xuICB9XG59XG5cbmZ1bmN0aW9uIGNhbGxfcHJvcGVydHkoaXRlbSwgcHJvcGVydHkpIHtcbiAgaWYgKHByb3BlcnR5IGluIGl0ZW0pIHtcbiAgICBpdGVtW3Byb3BlcnR5XTtcbiAgICBpZiAoaXRlbVtwcm9wZXJ0eV0gaW5zdGFuY2VvZiBGdW5jdGlvbikge1xuICAgICAgcmV0dXJuIGl0ZW1bcHJvcGVydHldKCk7XG4gICAgfSBlbHNlIHtcbiAgICAgIHJldHVybiBpdGVtW3Byb3BlcnR5XTtcbiAgICB9XG4gIH0gZWxzZSBpZiAoU3ltYm9sLmZvcihwcm9wZXJ0eSkgaW4gaXRlbSkge1xuICAgIGxldCBwcm9wID0gU3ltYm9sLmZvcihwcm9wZXJ0eSk7XG4gICAgaWYgKGl0ZW1bcHJvcF0gaW5zdGFuY2VvZiBGdW5jdGlvbikge1xuICAgICAgcmV0dXJuIGl0ZW1bcHJvcF0oKTtcbiAgICB9IGVsc2Uge1xuICAgICAgcmV0dXJuIGl0ZW1bcHJvcF07XG4gICAgfVxuICB9XG5cbiAgdGhyb3cgbmV3IEVycm9yKGBQcm9wZXJ0eSAkeyBwcm9wZXJ0eSB9IG5vdCBmb3VuZCBpbiAkeyBpdGVtIH1gKTtcbn1cblxudmFyIEpTID0ge1xuICBjYWxsX3Byb3BlcnR5XG59O1xuXG5sZXQgUmFuZ2UgPSBmdW5jdGlvbiAoX2ZpcnN0LCBfbGFzdCkge1xuICBpZiAoISh0aGlzIGluc3RhbmNlb2YgUmFuZ2UpKSB7XG4gICAgcmV0dXJuIG5ldyBSYW5nZShfZmlyc3QsIF9sYXN0KTtcbiAgfVxuXG4gIHRoaXMuZmlyc3QgPSBmdW5jdGlvbiAoKSB7XG4gICAgcmV0dXJuIF9maXJzdDtcbiAgfTtcblxuICB0aGlzLmxhc3QgPSBmdW5jdGlvbiAoKSB7XG4gICAgcmV0dXJuIF9sYXN0O1xuICB9O1xuXG4gIGxldCBfcmFuZ2UgPSBbXTtcblxuICBmb3IgKGxldCBpID0gX2ZpcnN0OyBpIDw9IF9sYXN0OyBpKyspIHtcbiAgICBfcmFuZ2UucHVzaChpKTtcbiAgfVxuXG4gIF9yYW5nZSA9IE9iamVjdC5mcmVlemUoX3JhbmdlKTtcblxuICB0aGlzLnZhbHVlID0gZnVuY3Rpb24gKCkge1xuICAgIHJldHVybiBfcmFuZ2U7XG4gIH07XG5cbiAgdGhpcy5sZW5ndGggPSBmdW5jdGlvbiAoKSB7XG4gICAgcmV0dXJuIF9yYW5nZS5sZW5ndGg7XG4gIH07XG5cbiAgcmV0dXJuIHRoaXM7XG59O1xuXG5SYW5nZS5wcm90b3R5cGVbU3ltYm9sLml0ZXJhdG9yXSA9IGZ1bmN0aW9uICgpIHtcbiAgcmV0dXJuIHRoaXMudmFsdWUoKVtTeW1ib2wuaXRlcmF0b3JdKCk7XG59O1xuXG5SYW5nZS5uZXcgPSBmdW5jdGlvbiAoZmlyc3QsIGxhc3QpIHtcbiAgcmV0dXJuIFJhbmdlKGZpcnN0LCBsYXN0KTtcbn07XG5cblJhbmdlLnJhbmdlX19xbWFya19fID0gZnVuY3Rpb24gKHJhbmdlKSB7XG4gIHJldHVybiByYW5nZSBpbnN0YW5jZW9mIFJhbmdlO1xufTtcblxubGV0IEtleXdvcmQgPSB7fTtcblxuS2V5d29yZC5oYXNfa2V5X19xbV9fID0gZnVuY3Rpb24gKGtleXdvcmRzLCBrZXkpIHtcbiAgZm9yIChsZXQga2V5d29yZCBvZiBrZXl3b3Jkcykge1xuICAgIGlmIChLZXJuZWwuZWxlbShrZXl3b3JkLCAwKSA9PSBrZXkpIHtcbiAgICAgIHJldHVybiB0cnVlO1xuICAgIH1cbiAgfVxuXG4gIHJldHVybiBmYWxzZTtcbn07XG5cbktleXdvcmQuZ2V0ID0gZnVuY3Rpb24gKGtleXdvcmRzLCBrZXksIHRoZV9kZWZhdWx0ID0gbnVsbCkge1xuICBmb3IgKGxldCBrZXl3b3JkIG9mIGtleXdvcmRzKSB7XG4gICAgaWYgKEtlcm5lbC5lbGVtKGtleXdvcmQsIDApID09IGtleSkge1xuICAgICAgcmV0dXJuIEtlcm5lbC5lbGVtKGtleXdvcmQsIDEpO1xuICAgIH1cbiAgfVxuXG4gIHJldHVybiB0aGVfZGVmYXVsdDtcbn07XG5cbmxldCBBZ2VudCA9IHt9O1xuXG5BZ2VudC5zdGFydCA9IGZ1bmN0aW9uIChmdW4sIG9wdGlvbnMgPSBbXSkge1xuICBjb25zdCBuYW1lID0gS2V5d29yZC5oYXNfa2V5X19xbV9fKG9wdGlvbnMsIEtlcm5lbC5TcGVjaWFsRm9ybXMuYXRvbSgnbmFtZScpKSA/IEtleXdvcmQuZ2V0KG9wdGlvbnMsIEtlcm5lbC5TcGVjaWFsRm9ybXMuYXRvbSgnbmFtZScpKSA6IFN5bWJvbCgpO1xuXG4gIHNlbGYucG9zdF9vZmZpY2UuYWRkX21haWxib3gobmFtZSk7XG4gIHNlbGYucG9zdF9vZmZpY2Uuc2VuZChuYW1lLCBmdW4oKSk7XG5cbiAgcmV0dXJuIEtlcm5lbC5TcGVjaWFsRm9ybXMudHVwbGUoS2VybmVsLlNwZWNpYWxGb3Jtcy5hdG9tKCdvaycpLCBuYW1lKTtcbn07XG5cbkFnZW50LnN0b3AgPSBmdW5jdGlvbiAoYWdlbnQsIHRpbWVvdXQgPSA1MDAwKSB7XG4gIHNlbGYucG9zdF9vZmZpY2UucmVtb3ZlX21haWxib3goYWdlbnQpO1xuICByZXR1cm4gS2VybmVsLlNwZWNpYWxGb3Jtcy5hdG9tKCdvaycpO1xufTtcblxuQWdlbnQudXBkYXRlID0gZnVuY3Rpb24gKGFnZW50LCBmdW4sIHRpbWVvdXQgPSA1MDAwKSB7XG5cbiAgY29uc3QgY3VycmVudF9zdGF0ZSA9IHNlbGYucG9zdF9vZmZpY2UucmVjZWl2ZShhZ2VudCk7XG4gIHNlbGYucG9zdF9vZmZpY2Uuc2VuZChhZ2VudCwgZnVuKGN1cnJlbnRfc3RhdGUpKTtcblxuICByZXR1cm4gS2VybmVsLlNwZWNpYWxGb3Jtcy5hdG9tKCdvaycpO1xufTtcblxuQWdlbnQuZ2V0ID0gZnVuY3Rpb24gKGFnZW50LCBmdW4sIHRpbWVvdXQgPSA1MDAwKSB7XG4gIHJldHVybiBmdW4oc2VsZi5wb3N0X29mZmljZS5wZWVrKGFnZW50KSk7XG59O1xuXG5BZ2VudC5nZXRfYW5kX3VwZGF0ZSA9IGZ1bmN0aW9uIChhZ2VudCwgZnVuLCB0aW1lb3V0ID0gNTAwMCkge1xuXG4gIGNvbnN0IGdldF9hbmRfdXBkYXRlX3R1cGxlID0gZnVuKHNlbGYucG9zdF9vZmZpY2UucmVjZWl2ZShhZ2VudCkpO1xuICBzZWxmLnBvc3Rfb2ZmaWNlLnNlbmQoYWdlbnQsIEtlcm5lbC5lbGVtKGdldF9hbmRfdXBkYXRlX3R1cGxlLCAxKSk7XG5cbiAgcmV0dXJuIEtlcm5lbC5lbGVtKGdldF9hbmRfdXBkYXRlX3R1cGxlLCAwKTtcbn07XG5cbi8vaHR0cHM6Ly9kZXZlbG9wZXIubW96aWxsYS5vcmcvZW4tVVMvZG9jcy9XZWIvQVBJL1dpbmRvd0Jhc2U2NC9CYXNlNjRfZW5jb2RpbmdfYW5kX2RlY29kaW5nI1NvbHV0aW9uXzJfJUUyJTgwJTkzX3Jld3JpdGVfdGhlX0RPTXNfYXRvYigpX2FuZF9idG9hKClfdXNpbmdfSmF2YVNjcmlwdCdzX1R5cGVkQXJyYXlzX2FuZF9VVEYtOFxuZnVuY3Rpb24gYjY0RW5jb2RlVW5pY29kZShzdHIpIHtcbiAgcmV0dXJuIGJ0b2EoZW5jb2RlVVJJQ29tcG9uZW50KHN0cikucmVwbGFjZSgvJShbMC05QS1GXXsyfSkvZywgZnVuY3Rpb24gKG1hdGNoLCBwMSkge1xuICAgIHJldHVybiBTdHJpbmcuZnJvbUNoYXJDb2RlKCcweCcgKyBwMSk7XG4gIH0pKTtcbn1cblxuZnVuY3Rpb24gZW5jb2RlNjQoZGF0YSkge1xuICByZXR1cm4gYjY0RW5jb2RlVW5pY29kZShkYXRhKTtcbn1cblxuZnVuY3Rpb24gZGVjb2RlNjQoZGF0YSkge1xuICB0cnkge1xuICAgIHJldHVybiBLZXJuZWwuU3BlY2lhbEZvcm1zLnR1cGxlKEtlcm5lbC5TcGVjaWFsRm9ybXMuYXRvbSgnb2snKSwgYXRvYihkYXRhKSk7XG4gIH0gY2F0Y2ggKGUpIHtcbiAgICByZXR1cm4gS2VybmVsLlNwZWNpYWxGb3Jtcy5hdG9tKCdlcnJvcicpO1xuICB9XG4gIHJldHVybiBidG9hKGRhdGEpO1xufVxuXG5mdW5jdGlvbiBkZWNvZGU2NF9fZW1fXyhkYXRhKSB7XG4gIHJldHVybiBhdG9iKGRhdGEpO1xufVxuXG52YXIgQmFzZSA9IHtcbiAgZW5jb2RlNjQsXG4gIGRlY29kZTY0LFxuICBkZWNvZGU2NF9fZW1fX1xufTtcblxuZnVuY3Rpb24gYm5vdChleHByKSB7XG4gIHJldHVybiB+ZXhwcjtcbn1cblxuZnVuY3Rpb24gYmFuZChsZWZ0LCByaWdodCkge1xuICByZXR1cm4gbGVmdCAmIHJpZ2h0O1xufVxuXG5mdW5jdGlvbiBib3IobGVmdCwgcmlnaHQpIHtcbiAgcmV0dXJuIGxlZnQgfCByaWdodDtcbn1cblxuZnVuY3Rpb24gYnNsKGxlZnQsIHJpZ2h0KSB7XG4gIHJldHVybiBsZWZ0IDw8IHJpZ2h0O1xufVxuXG5mdW5jdGlvbiBic3IobGVmdCwgcmlnaHQpIHtcbiAgcmV0dXJuIGxlZnQgPj4gcmlnaHQ7XG59XG5cbmZ1bmN0aW9uIGJ4b3IobGVmdCwgcmlnaHQpIHtcbiAgcmV0dXJuIGxlZnQgXiByaWdodDtcbn1cblxudmFyIEJpdHdpc2UgPSB7XG4gIGJub3QsXG4gIGJhbmQsXG4gIGJvcixcbiAgYnNsLFxuICBic3IsXG4gIGJ4b3Jcbn07XG5cbmxldCBFbnVtZXJhYmxlID0gS2VybmVsLmRlZnByb3RvY29sKHtcbiAgY291bnQ6IGZ1bmN0aW9uIChjb2xsZWN0aW9uKSB7fSxcbiAgbWVtYmVyX3FtYXJrX186IGZ1bmN0aW9uIChjb2xsZWN0aW9uLCB2YWx1ZSkge30sXG4gIHJlZHVjZTogZnVuY3Rpb24gKGNvbGxlY3Rpb24sIGFjYywgZnVuKSB7fVxufSk7XG5cbmxldCBDb2xsZWN0YWJsZSA9IEtlcm5lbC5kZWZwcm90b2NvbCh7XG4gIGludG86IGZ1bmN0aW9uIChjb2xsZWN0YWJsZSkge31cbn0pO1xuXG5sZXQgSW5zcGVjdCA9IEtlcm5lbC5kZWZwcm90b2NvbCh7XG4gIGluc3BlY3Q6IGZ1bmN0aW9uICh0aGluZywgb3B0cykge31cbn0pO1xuXG5mdW5jdGlvbiBfX19uZXdfXygpIHtcbiAgcmV0dXJuIFNwZWNpYWxGb3Jtcy5tYXAoe30pO1xufVxuXG5mdW5jdGlvbiBrZXlzKG1hcCkge1xuICByZXR1cm4gT2JqZWN0LmtleXMobWFwKTtcbn1cblxuZnVuY3Rpb24gX19zaXplKG1hcCkge1xuICByZXR1cm4ga2V5cyhtYXApLmxlbmd0aDtcbn1cblxuZnVuY3Rpb24gX190b19saXN0KG1hcCkge1xuICBsZXQgbWFwX2tleXMgPSBrZXlzKG1hcCk7XG4gIGxldCBsaXN0ID0gW107XG5cbiAgZm9yIChsZXQga2V5IG9mIG1hcF9rZXlzKSB7XG4gICAgbGlzdC5wdXNoKFNwZWNpYWxGb3Jtcy50dXBsZShrZXksIG1hcFtrZXldKSk7XG4gIH1cblxuICByZXR1cm4gU3BlY2lhbEZvcm1zLmxpc3QoLi4ubGlzdCk7XG59XG5cbmZ1bmN0aW9uIHZhbHVlcyhtYXApIHtcbiAgbGV0IG1hcF9rZXlzID0ga2V5cyhtYXApO1xuICBsZXQgbGlzdCA9IFtdO1xuXG4gIGZvciAobGV0IGtleSBvZiBtYXBfa2V5cykge1xuICAgIGxpc3QucHVzaChtYXBba2V5XSk7XG4gIH1cblxuICByZXR1cm4gU3BlY2lhbEZvcm1zLmxpc3QoLi4ubGlzdCk7XG59XG5cbmZ1bmN0aW9uIGZyb21fc3RydWN0KHN0cnVjdCkge1xuICBsZXQgbWFwID0gT2JqZWN0LmFzc2lnbih7fSwgc3RydWN0KTtcbiAgZGVsZXRlIG1hcFtTeW1ib2wuZm9yKFwiX19zdHJ1Y3RfX1wiKV07XG5cbiAgcmV0dXJuIFNwZWNpYWxGb3Jtcy5tYXAobWFwKTtcbn1cblxuZnVuY3Rpb24gX19fX2RlbGV0ZV9fKG1hcCwga2V5KSB7XG4gIGxldCBuZXdfbWFwID0gT2JqZWN0LmFzc2lnbih7fSwgbWFwKTtcblxuICBkZWxldGUgbmV3X21hcFtrZXldO1xuXG4gIHJldHVybiBTcGVjaWFsRm9ybXMubWFwKG5ld19tYXApO1xufVxuXG5mdW5jdGlvbiBkcm9wKG1hcCwga2V5cykge1xuICBsZXQgbmV3X21hcCA9IE9iamVjdC5hc3NpZ24oe30sIG1hcCk7XG5cbiAgZm9yIChsZXQga2V5IG9mIGtleXMpIHtcbiAgICBkZWxldGUgbmV3X21hcFtrZXldO1xuICB9XG5cbiAgcmV0dXJuIFNwZWNpYWxGb3Jtcy5tYXAobmV3X21hcCk7XG59XG5cbmZ1bmN0aW9uIF9fZXF1YWxfX3FtYXJrX18obWFwMSwgbWFwMikge1xuICByZXR1cm4gbWFwMSA9PT0gbWFwMjtcbn1cblxuZnVuY3Rpb24gZmV0Y2hfX2VtYXJrX18obWFwLCBrZXkpIHtcbiAgaWYgKGtleSBpbiBtYXApIHtcbiAgICByZXR1cm4gbWFwW2tleV07XG4gIH1cblxuICB0aHJvdyBuZXcgRXJyb3IoXCJLZXkgbm90IGZvdW5kLlwiKTtcbn1cblxuZnVuY3Rpb24gZmV0Y2gobWFwLCBrZXkpIHtcbiAgaWYgKGtleSBpbiBtYXApIHtcbiAgICByZXR1cm4gU3BlY2lhbEZvcm1zLnR1cGxlKFNwZWNpYWxGb3Jtcy5hdG9tKFwib2tcIiksIG1hcFtrZXldKTtcbiAgfVxuXG4gIHJldHVybiBTcGVjaWFsRm9ybXMuYXRvbShcImVycm9yXCIpO1xufVxuXG5mdW5jdGlvbiBoYXNfa2V5X19xbWFya19fKG1hcCwga2V5KSB7XG4gIHJldHVybiBrZXkgaW4gbWFwO1xufVxuXG5mdW5jdGlvbiBtZXJnZShtYXAxLCBtYXAyKSB7XG4gIHJldHVybiBTcGVjaWFsRm9ybXMubWFwX3VwZGF0ZShtYXAxLCBtYXAyKTtcbn1cblxuZnVuY3Rpb24gc3BsaXQobWFwLCBrZXlzKSB7XG4gIGxldCBzcGxpdDEgPSB7fTtcbiAgbGV0IHNwbGl0MiA9IHt9O1xuXG4gIGZvciAobGV0IGtleSBvZiBPYmplY3Qua2V5cyhtYXApKSB7XG4gICAgaWYgKGtleXMuaW5kZXhPZihrZXkpID4gLTEpIHtcbiAgICAgIHNwbGl0MVtrZXldID0gbWFwW2tleV07XG4gICAgfSBlbHNlIHtcbiAgICAgIHNwbGl0MltrZXldID0gbWFwW2tleV07XG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIFNwZWNpYWxGb3Jtcy50dXBsZShTcGVjaWFsRm9ybXMubWFwKHNwbGl0MSksIFNwZWNpYWxGb3Jtcy5tYXAoc3BsaXQyKSk7XG59XG5cbmZ1bmN0aW9uIHRha2UobWFwLCBrZXlzKSB7XG4gIGxldCBzcGxpdDEgPSB7fTtcblxuICBmb3IgKGxldCBrZXkgb2YgT2JqZWN0LmtleXMobWFwKSkge1xuICAgIGlmIChrZXlzLmluZGV4T2Yoa2V5KSA+IC0xKSB7XG4gICAgICBzcGxpdDFba2V5XSA9IG1hcFtrZXldO1xuICAgIH1cbiAgfVxuXG4gIHJldHVybiBTcGVjaWFsRm9ybXMubWFwKHNwbGl0MSk7XG59XG5cbmZ1bmN0aW9uIGRyb3AobWFwLCBrZXlzKSB7XG4gIGxldCBzcGxpdDEgPSB7fTtcblxuICBmb3IgKGxldCBrZXkgb2YgT2JqZWN0LmtleXMobWFwKSkge1xuICAgIGlmIChrZXlzLmluZGV4T2Yoa2V5KSA9PT0gLTEpIHtcbiAgICAgIHNwbGl0MVtrZXldID0gbWFwW2tleV07XG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIFNwZWNpYWxGb3Jtcy5tYXAoc3BsaXQxKTtcbn1cblxuZnVuY3Rpb24gcHV0X25ldyhtYXAsIGtleSwgdmFsdWUpIHtcbiAgaWYgKGtleSBpbiBtYXApIHtcbiAgICByZXR1cm4gbWFwO1xuICB9XG5cbiAgbGV0IG5ld19tYXAgPSBPYmplY3QuYXNzaWduKHt9LCBtYXApO1xuICBuZXdfbWFwW2tleV0gPSB2YWx1ZTtcblxuICByZXR1cm4gU3BlY2lhbEZvcm1zLm1hcChuZXdfbWFwKTtcbn1cblxuZnVuY3Rpb24gcHV0X25ld19sYXp5KG1hcCwga2V5LCBmdW4pIHtcbiAgaWYgKGtleSBpbiBtYXApIHtcbiAgICByZXR1cm4gbWFwO1xuICB9XG5cbiAgbGV0IG5ld19tYXAgPSBPYmplY3QuYXNzaWduKHt9LCBtYXApO1xuICBuZXdfbWFwW2tleV0gPSBmdW4oKTtcblxuICByZXR1cm4gU3BlY2lhbEZvcm1zLm1hcChuZXdfbWFwKTtcbn1cblxuZnVuY3Rpb24gZ2V0X2FuZF91cGRhdGUobWFwLCBrZXksIGZ1bikge1xuICBpZiAoa2V5IGluIG1hcCkge1xuICAgIHJldHVybiBtYXA7XG4gIH1cblxuICBsZXQgbmV3X21hcCA9IE9iamVjdC5hc3NpZ24oe30sIG1hcCk7XG4gIG5ld19tYXBba2V5XSA9IGZ1bihtYXBba2V5XSk7XG5cbiAgcmV0dXJuIFNwZWNpYWxGb3Jtcy5tYXAobmV3X21hcCk7XG59XG5cbmZ1bmN0aW9uIHBvcF9sYXp5KG1hcCwga2V5LCBmdW4pIHtcbiAgaWYgKCFrZXkgaW4gbWFwKSB7XG4gICAgcmV0dXJuIFNwZWNpYWxGb3Jtcy50dXBsZShmdW4oKSwgbWFwKTtcbiAgfVxuXG4gIGxldCBuZXdfbWFwID0gT2JqZWN0LmFzc2lnbih7fSwgbWFwKTtcbiAgbGV0IHZhbHVlID0gZnVuKG5ld19tYXBba2V5XSk7XG4gIGRlbGV0ZSBuZXdfbWFwW2tleV07XG5cbiAgcmV0dXJuIFNwZWNpYWxGb3Jtcy50dXBsZSh2YWx1ZSwgbmV3X21hcCk7XG59XG5cbmZ1bmN0aW9uIHBvcChtYXAsIGtleSwgX2RlZmF1bHQgPSBudWxsKSB7XG4gIGlmICgha2V5IGluIG1hcCkge1xuICAgIHJldHVybiBTcGVjaWFsRm9ybXMudHVwbGUoX2RlZmF1bHQsIG1hcCk7XG4gIH1cblxuICBsZXQgbmV3X21hcCA9IE9iamVjdC5hc3NpZ24oe30sIG1hcCk7XG4gIGxldCB2YWx1ZSA9IG5ld19tYXBba2V5XTtcbiAgZGVsZXRlIG5ld19tYXBba2V5XTtcblxuICByZXR1cm4gU3BlY2lhbEZvcm1zLnR1cGxlKHZhbHVlLCBuZXdfbWFwKTtcbn1cblxuZnVuY3Rpb24gZ2V0X2xhenkobWFwLCBrZXksIGZ1bikge1xuICBpZiAoIWtleSBpbiBtYXApIHtcbiAgICByZXR1cm4gZnVuKCk7XG4gIH1cblxuICByZXR1cm4gZnVuKG1hcFtrZXldKTtcbn1cblxuZnVuY3Rpb24gZ2V0KG1hcCwga2V5LCBfZGVmYXVsdCA9IG51bGwpIHtcbiAgaWYgKCFrZXkgaW4gbWFwKSB7XG4gICAgcmV0dXJuIF9kZWZhdWx0O1xuICB9XG5cbiAgcmV0dXJuIG1hcFtrZXldO1xufVxuXG5mdW5jdGlvbiBfX3B1dChtYXAsIGtleSwgdmFsKSB7XG4gIGxldCBuZXdfbWFwID0gT2JqZWN0KHt9LCBtYXApO1xuICBuZXdfbWFwW2tleV0gPSB2YWw7XG5cbiAgcmV0dXJuIFNwZWNpYWxGb3Jtcy5tYXAobmV3X21hcCk7XG59XG5cbmZ1bmN0aW9uIHVwZGF0ZV9fZW1hcmtfXyhtYXAsIGtleSwgZnVuKSB7XG4gIGlmICgha2V5IGluIG1hcCkge1xuICAgIHRocm93IG5ldyBFcnJvcihcIktleSBub3QgZm91bmRcIik7XG4gIH1cblxuICBsZXQgbmV3X21hcCA9IE9iamVjdCh7fSwgbWFwKTtcbiAgbmV3X21hcFtrZXldID0gZnVuKG1hcFtrZXldKTtcblxuICByZXR1cm4gU3BlY2lhbEZvcm1zLm1hcChuZXdfbWFwKTtcbn1cblxuZnVuY3Rpb24gX3VwZGF0ZShtYXAsIGtleSwgaW5pdGlhbCwgZnVuKSB7XG4gIGxldCBuZXdfbWFwID0gT2JqZWN0KHt9LCBtYXApO1xuXG4gIGlmICgha2V5IGluIG1hcCkge1xuICAgIG5ld19tYXBba2V5XSA9IGluaXRpYWw7XG4gIH0gZWxzZSB7XG4gICAgbmV3X21hcFtrZXldID0gZnVuKG1hcFtrZXldKTtcbiAgfVxuXG4gIHJldHVybiBTcGVjaWFsRm9ybXMubWFwKG5ld19tYXApO1xufVxuXG52YXIgX01hcCA9IHtcbiAgbmV3OiBfX19uZXdfXyxcbiAga2V5cyxcbiAgc2l6ZTogX19zaXplLFxuICB0b19saXN0OiBfX3RvX2xpc3QsXG4gIHZhbHVlcyxcbiAgZnJvbV9zdHJ1Y3QsXG4gIGRlbGV0ZTogX19fX2RlbGV0ZV9fLFxuICBkcm9wLFxuICBlcXVhbF9fcW1hcmtfXzogX19lcXVhbF9fcW1hcmtfXyxcbiAgZmV0Y2hfX2VtYXJrX18sXG4gIGZldGNoLFxuICBoYXNfa2V5X19xbWFya19fLFxuICBzcGxpdCxcbiAgdGFrZSxcbiAgcHV0X25ldyxcbiAgcHV0X25ld19sYXp5LFxuICBnZXRfYW5kX3VwZGF0ZSxcbiAgcG9wX2xhenksXG4gIHBvcCxcbiAgZ2V0X2xhenksXG4gIGdldCxcbiAgcHV0OiBfX3B1dCxcbiAgdXBkYXRlX19lbWFya19fLFxuICB1cGRhdGU6IF91cGRhdGVcbn07XG5cbmZ1bmN0aW9uIF9fbmV3X18oKSB7XG4gIHJldHVybiBTcGVjaWFsRm9ybXMubWFwKHsgW1N5bWJvbC5mb3IoJ19fc3RydWN0X18nKV06IFN5bWJvbC5mb3IoJ01hcFNldCcpLCBzZXQ6IFNwZWNpYWxGb3Jtcy5saXN0KCkgfSk7XG59XG5cbmZ1bmN0aW9uIF9zaXplKG1hcCkge1xuICByZXR1cm4gbWFwLnNldC5sZW5ndGg7XG59XG5cbmZ1bmN0aW9uIF90b19saXN0KG1hcCkge1xuICByZXR1cm4gbWFwLnNldDtcbn1cblxuZnVuY3Rpb24gX19fZGVsZXRlX18oc2V0LCB0ZXJtKSB7XG4gIGxldCBuZXdfbGlzdCA9IExpc3QuZGVsZXRlKHNldC5zZXQsIHRlcm0pO1xuXG4gIGxldCBuZXdfbWFwID0gT2JqZWN0LmFzc2lnbih7fSwgc2V0KTtcbiAgbmV3X21hcC5zZXQgPSBuZXdfbGlzdDtcbiAgcmV0dXJuIFNwZWNpYWxGb3Jtcy5tYXAobmV3X21hcCk7XG59XG5cbmZ1bmN0aW9uIF9wdXQoc2V0LCB0ZXJtKSB7XG4gIGlmIChzZXQuc2V0LmluZGV4T2YodGVybSkgPT09IC0xKSB7XG4gICAgbGV0IG5ld19saXN0ID0gTGlzdC5hcHBlbmQoc2V0LnNldCwgdGVybSk7XG5cbiAgICBsZXQgbmV3X21hcCA9IE9iamVjdC5hc3NpZ24oe30sIHNldCk7XG4gICAgbmV3X21hcC5zZXQgPSBuZXdfbGlzdDtcbiAgICByZXR1cm4gU3BlY2lhbEZvcm1zLm1hcChuZXdfbWFwKTtcbiAgfVxuXG4gIHJldHVybiBzZXQ7XG59XG5cbmZ1bmN0aW9uIF9kaWZmZXJlbmNlKHNldDEsIHNldDIpIHtcbiAgbGV0IG5ld19tYXAgPSBPYmplY3QuYXNzaWduKHt9LCBzZXQxKTtcblxuICBmb3IgKGxldCB2YWwgb2Ygc2V0MS5zZXQpIHtcbiAgICBpZiAoX21lbWJlcl9fcW1hcmtfXyhzZXQyLCB2YWwpKSB7XG4gICAgICBuZXdfbWFwLnNldCA9IExpc3QuZGVsZXRlKG5ld19tYXAuc2V0LCB2YWwpO1xuICAgIH1cbiAgfVxuXG4gIHJldHVybiBTcGVjaWFsRm9ybXMubWFwKG5ld19tYXApO1xufVxuXG5mdW5jdGlvbiBfaW50ZXJzZWN0aW9uKHNldDEsIHNldDIpIHtcbiAgbGV0IG5ld19tYXAgPSBPYmplY3QuYXNzaWduKHt9LCBzZXQxKTtcblxuICBmb3IgKGxldCB2YWwgb2Ygc2V0MS5zZXQpIHtcbiAgICBpZiAoIV9tZW1iZXJfX3FtYXJrX18oc2V0MiwgdmFsKSkge1xuICAgICAgbmV3X21hcC5zZXQgPSBMaXN0LmRlbGV0ZShuZXdfbWFwLnNldCwgdmFsKTtcbiAgICB9XG4gIH1cblxuICByZXR1cm4gU3BlY2lhbEZvcm1zLm1hcChuZXdfbWFwKTtcbn1cblxuZnVuY3Rpb24gX3VuaW9uKHNldDEsIHNldDIpIHtcbiAgbGV0IG5ld19tYXAgPSBzZXQxO1xuXG4gIGZvciAobGV0IHZhbCBvZiBzZXQyLnNldCkge1xuICAgIG5ld19tYXAgPSBfcHV0KG5ld19tYXAsIHZhbCk7XG4gIH1cblxuICByZXR1cm4gU3BlY2lhbEZvcm1zLm1hcChuZXdfbWFwKTtcbn1cblxuZnVuY3Rpb24gX2Rpc2pvaW5fX3FtYXJrX18oc2V0MSwgc2V0Mikge1xuICBmb3IgKGxldCB2YWwgb2Ygc2V0MS5zZXQpIHtcbiAgICBpZiAoX21lbWJlcl9fcW1hcmtfXyhzZXQyLCB2YWwpKSB7XG4gICAgICByZXR1cm4gZmFsc2U7XG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIHRydWU7XG59XG5cbmZ1bmN0aW9uIF9tZW1iZXJfX3FtYXJrX18oc2V0LCB2YWx1ZSkge1xuICByZXR1cm4gc2V0LnNldC5pbmRleE9mKHZhbHVlKSA+PSAwO1xufVxuXG5mdW5jdGlvbiBfZXF1YWxfX3FtYXJrX18oc2V0MSwgc2V0Mikge1xuICByZXR1cm4gc2V0MS5zZXQgPT09IHNldDIuc2V0O1xufVxuXG5mdW5jdGlvbiBfc3Vic2V0X19xbWFya19fKHNldDEsIHNldDIpIHtcbiAgZm9yIChsZXQgdmFsIG9mIHNldDEuc2V0KSB7XG4gICAgaWYgKCFfbWVtYmVyX19xbWFya19fKHNldDIsIHZhbCkpIHtcbiAgICAgIHJldHVybiBmYWxzZTtcbiAgICB9XG4gIH1cblxuICByZXR1cm4gdHJ1ZTtcbn1cblxudmFyIE1hcFNldCA9IHtcbiAgbmV3OiBfX25ld19fLFxuICBzaXplOiBfc2l6ZSxcbiAgdG9fbGlzdDogX3RvX2xpc3QsXG4gIGRpc2pvaW5fX3FtYXJrX186IF9kaXNqb2luX19xbWFya19fLFxuICBkZWxldGU6IF9fX2RlbGV0ZV9fLFxuICBzdWJzZXRfX3FtYXJrX186IF9zdWJzZXRfX3FtYXJrX18sXG4gIGVxdWFsX19xbWFya19fOiBfZXF1YWxfX3FtYXJrX18sXG4gIG1lbWJlcl9fcW1hcmtfXzogX21lbWJlcl9fcW1hcmtfXyxcbiAgcHV0OiBfcHV0LFxuICB1bmlvbjogX3VuaW9uLFxuICBpbnRlcnNlY3Rpb246IF9pbnRlcnNlY3Rpb24sXG4gIGRpZmZlcmVuY2U6IF9kaWZmZXJlbmNlXG59O1xuXG5mdW5jdGlvbiBzaXplKG1hcCkge1xuICByZXR1cm4gTWFwU2V0LnNpemUobWFwKTtcbn1cblxuZnVuY3Rpb24gdG9fbGlzdChtYXApIHtcbiAgcmV0dXJuIE1hcFNldC50b19saXN0KG1hcCk7XG59XG5cbmZ1bmN0aW9uIF9fZGVsZXRlX18oc2V0LCB0ZXJtKSB7XG4gIHJldHVybiBNYXBTZXQuZGVsZXRlKHNldCwgdGVybSk7XG59XG5cbmZ1bmN0aW9uIHB1dChzZXQsIHRlcm0pIHtcbiAgcmV0dXJuIE1hcFNldC5wdXQoc2V0LCB0ZXJtKTtcbn1cblxuZnVuY3Rpb24gZGlmZmVyZW5jZShzZXQxLCBzZXQyKSB7XG4gIHJldHVybiBNYXBTZXQuZGlmZmVyZW5jZShzZXQxLCBzZXQyKTtcbn1cblxuZnVuY3Rpb24gaW50ZXJzZWN0aW9uKHNldDEsIHNldDIpIHtcbiAgcmV0dXJuIE1hcFNldC5pbnRlcnNlY3Rpb24oc2V0MSwgc2V0Mik7XG59XG5cbmZ1bmN0aW9uIHVuaW9uKHNldDEsIHNldDIpIHtcbiAgcmV0dXJuIE1hcFNldC51bmlvbihzZXQxLCBzZXQyKTtcbn1cblxuZnVuY3Rpb24gZGlzam9pbl9fcW1hcmtfXyhzZXQxLCBzZXQyKSB7XG4gIHJldHVybiBNYXBTZXQuZGlzam9pbl9fcW1hcmtfXyhzZXQxLCBzZXQyKTtcbn1cblxuZnVuY3Rpb24gbWVtYmVyX19xbWFya19fKHNldCwgdmFsdWUpIHtcbiAgcmV0dXJuIE1hcFNldC5tZW1iZXJfX3FtYXJrX18oc2V0MSwgc2V0Mik7XG59XG5cbmZ1bmN0aW9uIGVxdWFsX19xbWFya19fKHNldDEsIHNldDIpIHtcbiAgcmV0dXJuIE1hcFNldC5lcXVhbF9fcW1hcmtfXyhzZXQxLCBzZXQyKTtcbn1cblxuZnVuY3Rpb24gc3Vic2V0X19xbWFya19fKHNldDEsIHNldDIpIHtcbiAgcmV0dXJuIE1hcFNldC5zdWJzZXRfX3FtYXJrX18oc2V0MSwgc2V0Mik7XG59XG5cbnZhciBfU2V0ID0ge1xuICBzaXplLFxuICB0b19saXN0LFxuICBkaXNqb2luX19xbWFya19fLFxuICBkZWxldGU6IF9fZGVsZXRlX18sXG4gIHN1YnNldF9fcW1hcmtfXyxcbiAgZXF1YWxfX3FtYXJrX18sXG4gIG1lbWJlcl9fcW1hcmtfXyxcbiAgcHV0LFxuICB1bmlvbixcbiAgaW50ZXJzZWN0aW9uLFxuICBkaWZmZXJlbmNlXG59O1xuXG5sZXQgdmlydHVhbERvbSA9IChmdW5jdGlvbiAoZSkge1xuICAgIHJldHVybiBlKCk7XG59KShmdW5jdGlvbiAoKSB7XG4gICAgdmFyIGRlZmluZSwgbW9kdWxlLCBleHBvcnRzO1xuICAgIHJldHVybiAoZnVuY3Rpb24gZSh0LCBuLCByKSB7XG4gICAgICAgIGZ1bmN0aW9uIHMobywgdSkge1xuICAgICAgICAgICAgaWYgKCFuW29dKSB7XG4gICAgICAgICAgICAgICAgaWYgKCF0W29dKSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciBhID0gdHlwZW9mIHJlcXVpcmUgPT0gXCJmdW5jdGlvblwiICYmIHJlcXVpcmU7XG4gICAgICAgICAgICAgICAgICAgIGlmICghdSAmJiBhKSByZXR1cm4gYShvLCAhMCk7XG4gICAgICAgICAgICAgICAgICAgIGlmIChpKSByZXR1cm4gaShvLCAhMCk7XG4gICAgICAgICAgICAgICAgICAgIHZhciBmID0gbmV3IEVycm9yKFwiQ2Fubm90IGZpbmQgbW9kdWxlICdcIiArIG8gKyBcIidcIik7XG4gICAgICAgICAgICAgICAgICAgIHRocm93IChmLmNvZGUgPSBcIk1PRFVMRV9OT1RfRk9VTkRcIiwgZik7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHZhciBsID0gbltvXSA9IHtcbiAgICAgICAgICAgICAgICAgICAgZXhwb3J0czoge31cbiAgICAgICAgICAgICAgICB9O1xuICAgICAgICAgICAgICAgIHRbb11bMF0uY2FsbChsLmV4cG9ydHMsIGZ1bmN0aW9uIChlKSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciBuID0gdFtvXVsxXVtlXTtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHMobiA/IG4gOiBlKTtcbiAgICAgICAgICAgICAgICB9LCBsLCBsLmV4cG9ydHMsIGUsIHQsIG4sIHIpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmV0dXJuIG5bb10uZXhwb3J0cztcbiAgICAgICAgfVxuICAgICAgICB2YXIgaSA9IHR5cGVvZiByZXF1aXJlID09IFwiZnVuY3Rpb25cIiAmJiByZXF1aXJlO1xuICAgICAgICBmb3IgKHZhciBvID0gMDsgbyA8IHIubGVuZ3RoOyBvKyspIHMocltvXSk7XG4gICAgICAgIHJldHVybiBzO1xuICAgIH0pKHtcbiAgICAgICAgMTogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHtcblxuICAgICAgICAgICAgdmFyIGNyZWF0ZUVsZW1lbnQgPSByZXF1aXJlKFwiLi92ZG9tL2NyZWF0ZS1lbGVtZW50LmpzXCIpO1xuXG4gICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IGNyZWF0ZUVsZW1lbnQ7XG4gICAgICAgIH0sIHsgXCIuL3Zkb20vY3JlYXRlLWVsZW1lbnQuanNcIjogMTUgfV0sIDI6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICB2YXIgZGlmZiA9IHJlcXVpcmUoXCIuL3Z0cmVlL2RpZmYuanNcIik7XG5cbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gZGlmZjtcbiAgICAgICAgfSwgeyBcIi4vdnRyZWUvZGlmZi5qc1wiOiAzNSB9XSwgMzogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHtcbiAgICAgICAgICAgIHZhciBoID0gcmVxdWlyZShcIi4vdmlydHVhbC1oeXBlcnNjcmlwdC9pbmRleC5qc1wiKTtcblxuICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBoO1xuICAgICAgICB9LCB7IFwiLi92aXJ0dWFsLWh5cGVyc2NyaXB0L2luZGV4LmpzXCI6IDIyIH1dLCA0OiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge1xuICAgICAgICAgICAgdmFyIGRpZmYgPSByZXF1aXJlKFwiLi9kaWZmLmpzXCIpO1xuICAgICAgICAgICAgdmFyIHBhdGNoID0gcmVxdWlyZShcIi4vcGF0Y2guanNcIik7XG4gICAgICAgICAgICB2YXIgaCA9IHJlcXVpcmUoXCIuL2guanNcIik7XG4gICAgICAgICAgICB2YXIgY3JlYXRlID0gcmVxdWlyZShcIi4vY3JlYXRlLWVsZW1lbnQuanNcIik7XG4gICAgICAgICAgICB2YXIgVk5vZGUgPSByZXF1aXJlKFwiLi92bm9kZS92bm9kZS5qc1wiKTtcbiAgICAgICAgICAgIHZhciBWVGV4dCA9IHJlcXVpcmUoXCIuL3Zub2RlL3Z0ZXh0LmpzXCIpO1xuXG4gICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IHtcbiAgICAgICAgICAgICAgICBkaWZmOiBkaWZmLFxuICAgICAgICAgICAgICAgIHBhdGNoOiBwYXRjaCxcbiAgICAgICAgICAgICAgICBoOiBoLFxuICAgICAgICAgICAgICAgIGNyZWF0ZTogY3JlYXRlLFxuICAgICAgICAgICAgICAgIFZOb2RlOiBWTm9kZSxcbiAgICAgICAgICAgICAgICBWVGV4dDogVlRleHRcbiAgICAgICAgICAgIH07XG4gICAgICAgIH0sIHsgXCIuL2NyZWF0ZS1lbGVtZW50LmpzXCI6IDEsIFwiLi9kaWZmLmpzXCI6IDIsIFwiLi9oLmpzXCI6IDMsIFwiLi9wYXRjaC5qc1wiOiAxMywgXCIuL3Zub2RlL3Zub2RlLmpzXCI6IDMxLCBcIi4vdm5vZGUvdnRleHQuanNcIjogMzMgfV0sIDU6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICAvKiFcbiAgICAgICAgICAgICAqIENyb3NzLUJyb3dzZXIgU3BsaXQgMS4xLjFcbiAgICAgICAgICAgICAqIENvcHlyaWdodCAyMDA3LTIwMTIgU3RldmVuIExldml0aGFuIDxzdGV2ZW5sZXZpdGhhbi5jb20+XG4gICAgICAgICAgICAgKiBBdmFpbGFibGUgdW5kZXIgdGhlIE1JVCBMaWNlbnNlXG4gICAgICAgICAgICAgKiBFQ01BU2NyaXB0IGNvbXBsaWFudCwgdW5pZm9ybSBjcm9zcy1icm93c2VyIHNwbGl0IG1ldGhvZFxuICAgICAgICAgICAgICovXG5cbiAgICAgICAgICAgIC8qKlxuICAgICAgICAgICAgICogU3BsaXRzIGEgc3RyaW5nIGludG8gYW4gYXJyYXkgb2Ygc3RyaW5ncyB1c2luZyBhIHJlZ2V4IG9yIHN0cmluZyBzZXBhcmF0b3IuIE1hdGNoZXMgb2YgdGhlXG4gICAgICAgICAgICAgKiBzZXBhcmF0b3IgYXJlIG5vdCBpbmNsdWRlZCBpbiB0aGUgcmVzdWx0IGFycmF5LiBIb3dldmVyLCBpZiBgc2VwYXJhdG9yYCBpcyBhIHJlZ2V4IHRoYXQgY29udGFpbnNcbiAgICAgICAgICAgICAqIGNhcHR1cmluZyBncm91cHMsIGJhY2tyZWZlcmVuY2VzIGFyZSBzcGxpY2VkIGludG8gdGhlIHJlc3VsdCBlYWNoIHRpbWUgYHNlcGFyYXRvcmAgaXMgbWF0Y2hlZC5cbiAgICAgICAgICAgICAqIEZpeGVzIGJyb3dzZXIgYnVncyBjb21wYXJlZCB0byB0aGUgbmF0aXZlIGBTdHJpbmcucHJvdG90eXBlLnNwbGl0YCBhbmQgY2FuIGJlIHVzZWQgcmVsaWFibHlcbiAgICAgICAgICAgICAqIGNyb3NzLWJyb3dzZXIuXG4gICAgICAgICAgICAgKiBAcGFyYW0ge1N0cmluZ30gc3RyIFN0cmluZyB0byBzcGxpdC5cbiAgICAgICAgICAgICAqIEBwYXJhbSB7UmVnRXhwfFN0cmluZ30gc2VwYXJhdG9yIFJlZ2V4IG9yIHN0cmluZyB0byB1c2UgZm9yIHNlcGFyYXRpbmcgdGhlIHN0cmluZy5cbiAgICAgICAgICAgICAqIEBwYXJhbSB7TnVtYmVyfSBbbGltaXRdIE1heGltdW0gbnVtYmVyIG9mIGl0ZW1zIHRvIGluY2x1ZGUgaW4gdGhlIHJlc3VsdCBhcnJheS5cbiAgICAgICAgICAgICAqIEByZXR1cm5zIHtBcnJheX0gQXJyYXkgb2Ygc3Vic3RyaW5ncy5cbiAgICAgICAgICAgICAqIEBleGFtcGxlXG4gICAgICAgICAgICAgKlxuICAgICAgICAgICAgICogLy8gQmFzaWMgdXNlXG4gICAgICAgICAgICAgKiBzcGxpdCgnYSBiIGMgZCcsICcgJyk7XG4gICAgICAgICAgICAgKiAvLyAtPiBbJ2EnLCAnYicsICdjJywgJ2QnXVxuICAgICAgICAgICAgICpcbiAgICAgICAgICAgICAqIC8vIFdpdGggbGltaXRcbiAgICAgICAgICAgICAqIHNwbGl0KCdhIGIgYyBkJywgJyAnLCAyKTtcbiAgICAgICAgICAgICAqIC8vIC0+IFsnYScsICdiJ11cbiAgICAgICAgICAgICAqXG4gICAgICAgICAgICAgKiAvLyBCYWNrcmVmZXJlbmNlcyBpbiByZXN1bHQgYXJyYXlcbiAgICAgICAgICAgICAqIHNwbGl0KCcuLndvcmQxIHdvcmQyLi4nLCAvKFthLXpdKykoXFxkKykvaSk7XG4gICAgICAgICAgICAgKiAvLyAtPiBbJy4uJywgJ3dvcmQnLCAnMScsICcgJywgJ3dvcmQnLCAnMicsICcuLiddXG4gICAgICAgICAgICAgKi9cbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gKGZ1bmN0aW9uIHNwbGl0KHVuZGVmKSB7XG5cbiAgICAgICAgICAgICAgICB2YXIgbmF0aXZlU3BsaXQgPSBTdHJpbmcucHJvdG90eXBlLnNwbGl0LFxuICAgICAgICAgICAgICAgICAgICBjb21wbGlhbnRFeGVjTnBjZyA9IC8oKT8/Ly5leGVjKFwiXCIpWzFdID09PSB1bmRlZixcblxuICAgICAgICAgICAgICAgIC8vIE5QQ0c6IG5vbnBhcnRpY2lwYXRpbmcgY2FwdHVyaW5nIGdyb3VwXG4gICAgICAgICAgICAgICAgc2VsZjtcblxuICAgICAgICAgICAgICAgIHNlbGYgPSBmdW5jdGlvbiAoc3RyLCBzZXBhcmF0b3IsIGxpbWl0KSB7XG4gICAgICAgICAgICAgICAgICAgIC8vIElmIGBzZXBhcmF0b3JgIGlzIG5vdCBhIHJlZ2V4LCB1c2UgYG5hdGl2ZVNwbGl0YFxuICAgICAgICAgICAgICAgICAgICBpZiAoT2JqZWN0LnByb3RvdHlwZS50b1N0cmluZy5jYWxsKHNlcGFyYXRvcikgIT09IFwiW29iamVjdCBSZWdFeHBdXCIpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBuYXRpdmVTcGxpdC5jYWxsKHN0ciwgc2VwYXJhdG9yLCBsaW1pdCk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgdmFyIG91dHB1dCA9IFtdLFxuICAgICAgICAgICAgICAgICAgICAgICAgZmxhZ3MgPSAoc2VwYXJhdG9yLmlnbm9yZUNhc2UgPyBcImlcIiA6IFwiXCIpICsgKHNlcGFyYXRvci5tdWx0aWxpbmUgPyBcIm1cIiA6IFwiXCIpICsgKHNlcGFyYXRvci5leHRlbmRlZCA/IFwieFwiIDogXCJcIikgKyAoc2VwYXJhdG9yLnN0aWNreSA/IFwieVwiIDogXCJcIiksXG5cbiAgICAgICAgICAgICAgICAgICAgLy8gRmlyZWZveCAzK1xuICAgICAgICAgICAgICAgICAgICBsYXN0TGFzdEluZGV4ID0gMCxcblxuICAgICAgICAgICAgICAgICAgICAvLyBNYWtlIGBnbG9iYWxgIGFuZCBhdm9pZCBgbGFzdEluZGV4YCBpc3N1ZXMgYnkgd29ya2luZyB3aXRoIGEgY29weVxuICAgICAgICAgICAgICAgICAgICBzZXBhcmF0b3IgPSBuZXcgUmVnRXhwKHNlcGFyYXRvci5zb3VyY2UsIGZsYWdzICsgXCJnXCIpLFxuICAgICAgICAgICAgICAgICAgICAgICAgc2VwYXJhdG9yMixcbiAgICAgICAgICAgICAgICAgICAgICAgIG1hdGNoLFxuICAgICAgICAgICAgICAgICAgICAgICAgbGFzdEluZGV4LFxuICAgICAgICAgICAgICAgICAgICAgICAgbGFzdExlbmd0aDtcbiAgICAgICAgICAgICAgICAgICAgc3RyICs9IFwiXCI7IC8vIFR5cGUtY29udmVydFxuICAgICAgICAgICAgICAgICAgICBpZiAoIWNvbXBsaWFudEV4ZWNOcGNnKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAvLyBEb2Vzbid0IG5lZWQgZmxhZ3MgZ3ksIGJ1dCB0aGV5IGRvbid0IGh1cnRcbiAgICAgICAgICAgICAgICAgICAgICAgIHNlcGFyYXRvcjIgPSBuZXcgUmVnRXhwKFwiXlwiICsgc2VwYXJhdG9yLnNvdXJjZSArIFwiJCg/IVxcXFxzKVwiLCBmbGFncyk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgLyogVmFsdWVzIGZvciBgbGltaXRgLCBwZXIgdGhlIHNwZWM6XG4gICAgICAgICAgICAgICAgICAgICAqIElmIHVuZGVmaW5lZDogNDI5NDk2NzI5NSAvLyBNYXRoLnBvdygyLCAzMikgLSAxXG4gICAgICAgICAgICAgICAgICAgICAqIElmIDAsIEluZmluaXR5LCBvciBOYU46IDBcbiAgICAgICAgICAgICAgICAgICAgICogSWYgcG9zaXRpdmUgbnVtYmVyOiBsaW1pdCA9IE1hdGguZmxvb3IobGltaXQpOyBpZiAobGltaXQgPiA0Mjk0OTY3Mjk1KSBsaW1pdCAtPSA0Mjk0OTY3Mjk2O1xuICAgICAgICAgICAgICAgICAgICAgKiBJZiBuZWdhdGl2ZSBudW1iZXI6IDQyOTQ5NjcyOTYgLSBNYXRoLmZsb29yKE1hdGguYWJzKGxpbWl0KSlcbiAgICAgICAgICAgICAgICAgICAgICogSWYgb3RoZXI6IFR5cGUtY29udmVydCwgdGhlbiB1c2UgdGhlIGFib3ZlIHJ1bGVzXG4gICAgICAgICAgICAgICAgICAgICAqL1xuICAgICAgICAgICAgICAgICAgICBsaW1pdCA9IGxpbWl0ID09PSB1bmRlZiA/IC0xID4+PiAwIDogLy8gTWF0aC5wb3coMiwgMzIpIC0gMVxuICAgICAgICAgICAgICAgICAgICBsaW1pdCA+Pj4gMDsgLy8gVG9VaW50MzIobGltaXQpXG4gICAgICAgICAgICAgICAgICAgIHdoaWxlIChtYXRjaCA9IHNlcGFyYXRvci5leGVjKHN0cikpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIGBzZXBhcmF0b3IubGFzdEluZGV4YCBpcyBub3QgcmVsaWFibGUgY3Jvc3MtYnJvd3NlclxuICAgICAgICAgICAgICAgICAgICAgICAgbGFzdEluZGV4ID0gbWF0Y2guaW5kZXggKyBtYXRjaFswXS5sZW5ndGg7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAobGFzdEluZGV4ID4gbGFzdExhc3RJbmRleCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIG91dHB1dC5wdXNoKHN0ci5zbGljZShsYXN0TGFzdEluZGV4LCBtYXRjaC5pbmRleCkpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIEZpeCBicm93c2VycyB3aG9zZSBgZXhlY2AgbWV0aG9kcyBkb24ndCBjb25zaXN0ZW50bHkgcmV0dXJuIGB1bmRlZmluZWRgIGZvclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIG5vbnBhcnRpY2lwYXRpbmcgY2FwdHVyaW5nIGdyb3Vwc1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmICghY29tcGxpYW50RXhlY05wY2cgJiYgbWF0Y2gubGVuZ3RoID4gMSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBtYXRjaFswXS5yZXBsYWNlKHNlcGFyYXRvcjIsIGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZvciAodmFyIGkgPSAxOyBpIDwgYXJndW1lbnRzLmxlbmd0aCAtIDI7IGkrKykge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChhcmd1bWVudHNbaV0gPT09IHVuZGVmKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1hdGNoW2ldID0gdW5kZWY7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKG1hdGNoLmxlbmd0aCA+IDEgJiYgbWF0Y2guaW5kZXggPCBzdHIubGVuZ3RoKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIEFycmF5LnByb3RvdHlwZS5wdXNoLmFwcGx5KG91dHB1dCwgbWF0Y2guc2xpY2UoMSkpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBsYXN0TGVuZ3RoID0gbWF0Y2hbMF0ubGVuZ3RoO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxhc3RMYXN0SW5kZXggPSBsYXN0SW5kZXg7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKG91dHB1dC5sZW5ndGggPj0gbGltaXQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHNlcGFyYXRvci5sYXN0SW5kZXggPT09IG1hdGNoLmluZGV4KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgc2VwYXJhdG9yLmxhc3RJbmRleCsrOyAvLyBBdm9pZCBhbiBpbmZpbml0ZSBsb29wXG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgaWYgKGxhc3RMYXN0SW5kZXggPT09IHN0ci5sZW5ndGgpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChsYXN0TGVuZ3RoIHx8ICFzZXBhcmF0b3IudGVzdChcIlwiKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIG91dHB1dC5wdXNoKFwiXCIpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgb3V0cHV0LnB1c2goc3RyLnNsaWNlKGxhc3RMYXN0SW5kZXgpKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICByZXR1cm4gb3V0cHV0Lmxlbmd0aCA+IGxpbWl0ID8gb3V0cHV0LnNsaWNlKDAsIGxpbWl0KSA6IG91dHB1dDtcbiAgICAgICAgICAgICAgICB9O1xuXG4gICAgICAgICAgICAgICAgcmV0dXJuIHNlbGY7XG4gICAgICAgICAgICB9KSgpO1xuICAgICAgICB9LCB7fV0sIDY6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7fSwge31dLCA3OiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge1xuICAgICAgICAgICAgXCJ1c2Ugc3RyaWN0XCI7XG5cbiAgICAgICAgICAgIHZhciBPbmVWZXJzaW9uQ29uc3RyYWludCA9IHJlcXVpcmUoXCJpbmRpdmlkdWFsL29uZS12ZXJzaW9uXCIpO1xuXG4gICAgICAgICAgICB2YXIgTVlfVkVSU0lPTiA9IFwiN1wiO1xuICAgICAgICAgICAgT25lVmVyc2lvbkNvbnN0cmFpbnQoXCJldi1zdG9yZVwiLCBNWV9WRVJTSU9OKTtcblxuICAgICAgICAgICAgdmFyIGhhc2hLZXkgPSBcIl9fRVZfU1RPUkVfS0VZQFwiICsgTVlfVkVSU0lPTjtcblxuICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBFdlN0b3JlO1xuXG4gICAgICAgICAgICBmdW5jdGlvbiBFdlN0b3JlKGVsZW0pIHtcbiAgICAgICAgICAgICAgICB2YXIgaGFzaCA9IGVsZW1baGFzaEtleV07XG5cbiAgICAgICAgICAgICAgICBpZiAoIWhhc2gpIHtcbiAgICAgICAgICAgICAgICAgICAgaGFzaCA9IGVsZW1baGFzaEtleV0gPSB7fTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICByZXR1cm4gaGFzaDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSwgeyBcImluZGl2aWR1YWwvb25lLXZlcnNpb25cIjogOSB9XSwgODogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHtcbiAgICAgICAgICAgIChmdW5jdGlvbiAoZ2xvYmFsKSB7XG4gICAgICAgICAgICAgICAgXCJ1c2Ugc3RyaWN0XCI7XG5cbiAgICAgICAgICAgICAgICAvKmdsb2JhbCB3aW5kb3csIGdsb2JhbCovXG5cbiAgICAgICAgICAgICAgICB2YXIgcm9vdCA9IHR5cGVvZiB3aW5kb3cgIT09IFwidW5kZWZpbmVkXCIgPyB3aW5kb3cgOiB0eXBlb2YgZ2xvYmFsICE9PSBcInVuZGVmaW5lZFwiID8gZ2xvYmFsIDoge307XG5cbiAgICAgICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IEluZGl2aWR1YWw7XG5cbiAgICAgICAgICAgICAgICBmdW5jdGlvbiBJbmRpdmlkdWFsKGtleSwgdmFsdWUpIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKGtleSBpbiByb290KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gcm9vdFtrZXldO1xuICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgcm9vdFtrZXldID0gdmFsdWU7XG5cbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHZhbHVlO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0pLmNhbGwodGhpcywgdHlwZW9mIGdsb2JhbCAhPT0gXCJ1bmRlZmluZWRcIiA/IGdsb2JhbCA6IHR5cGVvZiBzZWxmICE9PSBcInVuZGVmaW5lZFwiID8gc2VsZiA6IHR5cGVvZiB3aW5kb3cgIT09IFwidW5kZWZpbmVkXCIgPyB3aW5kb3cgOiB7fSk7XG4gICAgICAgIH0sIHt9XSwgOTogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHtcbiAgICAgICAgICAgIFwidXNlIHN0cmljdFwiO1xuXG4gICAgICAgICAgICB2YXIgSW5kaXZpZHVhbCA9IHJlcXVpcmUoXCIuL2luZGV4LmpzXCIpO1xuXG4gICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IE9uZVZlcnNpb247XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIE9uZVZlcnNpb24obW9kdWxlTmFtZSwgdmVyc2lvbiwgZGVmYXVsdFZhbHVlKSB7XG4gICAgICAgICAgICAgICAgdmFyIGtleSA9IFwiX19JTkRJVklEVUFMX09ORV9WRVJTSU9OX1wiICsgbW9kdWxlTmFtZTtcbiAgICAgICAgICAgICAgICB2YXIgZW5mb3JjZUtleSA9IGtleSArIFwiX0VORk9SQ0VfU0lOR0xFVE9OXCI7XG5cbiAgICAgICAgICAgICAgICB2YXIgdmVyc2lvblZhbHVlID0gSW5kaXZpZHVhbChlbmZvcmNlS2V5LCB2ZXJzaW9uKTtcblxuICAgICAgICAgICAgICAgIGlmICh2ZXJzaW9uVmFsdWUgIT09IHZlcnNpb24pIHtcbiAgICAgICAgICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKFwiQ2FuIG9ubHkgaGF2ZSBvbmUgY29weSBvZiBcIiArIG1vZHVsZU5hbWUgKyBcIi5cXG5cIiArIFwiWW91IGFscmVhZHkgaGF2ZSB2ZXJzaW9uIFwiICsgdmVyc2lvblZhbHVlICsgXCIgaW5zdGFsbGVkLlxcblwiICsgXCJUaGlzIG1lYW5zIHlvdSBjYW5ub3QgaW5zdGFsbCB2ZXJzaW9uIFwiICsgdmVyc2lvbik7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgcmV0dXJuIEluZGl2aWR1YWwoa2V5LCBkZWZhdWx0VmFsdWUpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9LCB7IFwiLi9pbmRleC5qc1wiOiA4IH1dLCAxMDogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHtcbiAgICAgICAgICAgIChmdW5jdGlvbiAoZ2xvYmFsKSB7XG4gICAgICAgICAgICAgICAgdmFyIHRvcExldmVsID0gdHlwZW9mIGdsb2JhbCAhPT0gXCJ1bmRlZmluZWRcIiA/IGdsb2JhbCA6IHR5cGVvZiB3aW5kb3cgIT09IFwidW5kZWZpbmVkXCIgPyB3aW5kb3cgOiB7fTtcbiAgICAgICAgICAgICAgICB2YXIgbWluRG9jID0gcmVxdWlyZShcIm1pbi1kb2N1bWVudFwiKTtcblxuICAgICAgICAgICAgICAgIGlmICh0eXBlb2YgZG9jdW1lbnQgIT09IFwidW5kZWZpbmVkXCIpIHtcbiAgICAgICAgICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBkb2N1bWVudDtcbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICB2YXIgZG9jY3kgPSB0b3BMZXZlbFtcIl9fR0xPQkFMX0RPQ1VNRU5UX0NBQ0hFQDRcIl07XG5cbiAgICAgICAgICAgICAgICAgICAgaWYgKCFkb2NjeSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgZG9jY3kgPSB0b3BMZXZlbFtcIl9fR0xPQkFMX0RPQ1VNRU5UX0NBQ0hFQDRcIl0gPSBtaW5Eb2M7XG4gICAgICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IGRvY2N5O1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0pLmNhbGwodGhpcywgdHlwZW9mIGdsb2JhbCAhPT0gXCJ1bmRlZmluZWRcIiA/IGdsb2JhbCA6IHR5cGVvZiBzZWxmICE9PSBcInVuZGVmaW5lZFwiID8gc2VsZiA6IHR5cGVvZiB3aW5kb3cgIT09IFwidW5kZWZpbmVkXCIgPyB3aW5kb3cgOiB7fSk7XG4gICAgICAgIH0sIHsgXCJtaW4tZG9jdW1lbnRcIjogNiB9XSwgMTE6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICBcInVzZSBzdHJpY3RcIjtcblxuICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiBpc09iamVjdCh4KSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHR5cGVvZiB4ID09PSBcIm9iamVjdFwiICYmIHggIT09IG51bGw7XG4gICAgICAgICAgICB9O1xuICAgICAgICB9LCB7fV0sIDEyOiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge1xuICAgICAgICAgICAgdmFyIG5hdGl2ZUlzQXJyYXkgPSBBcnJheS5pc0FycmF5O1xuICAgICAgICAgICAgdmFyIHRvU3RyaW5nID0gT2JqZWN0LnByb3RvdHlwZS50b1N0cmluZztcblxuICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBuYXRpdmVJc0FycmF5IHx8IGlzQXJyYXk7XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIGlzQXJyYXkob2JqKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHRvU3RyaW5nLmNhbGwob2JqKSA9PT0gXCJbb2JqZWN0IEFycmF5XVwiO1xuICAgICAgICAgICAgfVxuICAgICAgICB9LCB7fV0sIDEzOiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge1xuICAgICAgICAgICAgdmFyIHBhdGNoID0gcmVxdWlyZShcIi4vdmRvbS9wYXRjaC5qc1wiKTtcblxuICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBwYXRjaDtcbiAgICAgICAgfSwgeyBcIi4vdmRvbS9wYXRjaC5qc1wiOiAxOCB9XSwgMTQ6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICB2YXIgaXNPYmplY3QgPSByZXF1aXJlKFwiaXMtb2JqZWN0XCIpO1xuICAgICAgICAgICAgdmFyIGlzSG9vayA9IHJlcXVpcmUoXCIuLi92bm9kZS9pcy12aG9vay5qc1wiKTtcblxuICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBhcHBseVByb3BlcnRpZXM7XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIGFwcGx5UHJvcGVydGllcyhub2RlLCBwcm9wcywgcHJldmlvdXMpIHtcbiAgICAgICAgICAgICAgICBmb3IgKHZhciBwcm9wTmFtZSBpbiBwcm9wcykge1xuICAgICAgICAgICAgICAgICAgICB2YXIgcHJvcFZhbHVlID0gcHJvcHNbcHJvcE5hbWVdO1xuXG4gICAgICAgICAgICAgICAgICAgIGlmIChwcm9wVmFsdWUgPT09IHVuZGVmaW5lZCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgcmVtb3ZlUHJvcGVydHkobm9kZSwgcHJvcE5hbWUsIHByb3BWYWx1ZSwgcHJldmlvdXMpO1xuICAgICAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKGlzSG9vayhwcm9wVmFsdWUpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICByZW1vdmVQcm9wZXJ0eShub2RlLCBwcm9wTmFtZSwgcHJvcFZhbHVlLCBwcmV2aW91cyk7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAocHJvcFZhbHVlLmhvb2spIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBwcm9wVmFsdWUuaG9vayhub2RlLCBwcm9wTmFtZSwgcHJldmlvdXMgPyBwcmV2aW91c1twcm9wTmFtZV0gOiB1bmRlZmluZWQpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGlzT2JqZWN0KHByb3BWYWx1ZSkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBwYXRjaE9iamVjdChub2RlLCBwcm9wcywgcHJldmlvdXMsIHByb3BOYW1lLCBwcm9wVmFsdWUpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBub2RlW3Byb3BOYW1lXSA9IHByb3BWYWx1ZTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZnVuY3Rpb24gcmVtb3ZlUHJvcGVydHkobm9kZSwgcHJvcE5hbWUsIHByb3BWYWx1ZSwgcHJldmlvdXMpIHtcbiAgICAgICAgICAgICAgICBpZiAocHJldmlvdXMpIHtcbiAgICAgICAgICAgICAgICAgICAgdmFyIHByZXZpb3VzVmFsdWUgPSBwcmV2aW91c1twcm9wTmFtZV07XG5cbiAgICAgICAgICAgICAgICAgICAgaWYgKCFpc0hvb2socHJldmlvdXNWYWx1ZSkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChwcm9wTmFtZSA9PT0gXCJhdHRyaWJ1dGVzXCIpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBmb3IgKHZhciBhdHRyTmFtZSBpbiBwcmV2aW91c1ZhbHVlKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG5vZGUucmVtb3ZlQXR0cmlidXRlKGF0dHJOYW1lKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKHByb3BOYW1lID09PSBcInN0eWxlXCIpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBmb3IgKHZhciBpIGluIHByZXZpb3VzVmFsdWUpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbm9kZS5zdHlsZVtpXSA9IFwiXCI7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIGlmICh0eXBlb2YgcHJldmlvdXNWYWx1ZSA9PT0gXCJzdHJpbmdcIikge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIG5vZGVbcHJvcE5hbWVdID0gXCJcIjtcbiAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgbm9kZVtwcm9wTmFtZV0gPSBudWxsO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKHByZXZpb3VzVmFsdWUudW5ob29rKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBwcmV2aW91c1ZhbHVlLnVuaG9vayhub2RlLCBwcm9wTmFtZSwgcHJvcFZhbHVlKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZnVuY3Rpb24gcGF0Y2hPYmplY3Qobm9kZSwgcHJvcHMsIHByZXZpb3VzLCBwcm9wTmFtZSwgcHJvcFZhbHVlKSB7XG4gICAgICAgICAgICAgICAgdmFyIHByZXZpb3VzVmFsdWUgPSBwcmV2aW91cyA/IHByZXZpb3VzW3Byb3BOYW1lXSA6IHVuZGVmaW5lZDtcblxuICAgICAgICAgICAgICAgIC8vIFNldCBhdHRyaWJ1dGVzXG4gICAgICAgICAgICAgICAgaWYgKHByb3BOYW1lID09PSBcImF0dHJpYnV0ZXNcIikge1xuICAgICAgICAgICAgICAgICAgICBmb3IgKHZhciBhdHRyTmFtZSBpbiBwcm9wVmFsdWUpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHZhciBhdHRyVmFsdWUgPSBwcm9wVmFsdWVbYXR0ck5hbWVdO1xuXG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoYXR0clZhbHVlID09PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBub2RlLnJlbW92ZUF0dHJpYnV0ZShhdHRyTmFtZSk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIG5vZGUuc2V0QXR0cmlidXRlKGF0dHJOYW1lLCBhdHRyVmFsdWUpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIGlmIChwcmV2aW91c1ZhbHVlICYmIGlzT2JqZWN0KHByZXZpb3VzVmFsdWUpICYmIGdldFByb3RvdHlwZShwcmV2aW91c1ZhbHVlKSAhPT0gZ2V0UHJvdG90eXBlKHByb3BWYWx1ZSkpIHtcbiAgICAgICAgICAgICAgICAgICAgbm9kZVtwcm9wTmFtZV0gPSBwcm9wVmFsdWU7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICBpZiAoIWlzT2JqZWN0KG5vZGVbcHJvcE5hbWVdKSkge1xuICAgICAgICAgICAgICAgICAgICBub2RlW3Byb3BOYW1lXSA9IHt9O1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHZhciByZXBsYWNlciA9IHByb3BOYW1lID09PSBcInN0eWxlXCIgPyBcIlwiIDogdW5kZWZpbmVkO1xuXG4gICAgICAgICAgICAgICAgZm9yICh2YXIgayBpbiBwcm9wVmFsdWUpIHtcbiAgICAgICAgICAgICAgICAgICAgdmFyIHZhbHVlID0gcHJvcFZhbHVlW2tdO1xuICAgICAgICAgICAgICAgICAgICBub2RlW3Byb3BOYW1lXVtrXSA9IHZhbHVlID09PSB1bmRlZmluZWQgPyByZXBsYWNlciA6IHZhbHVlO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZnVuY3Rpb24gZ2V0UHJvdG90eXBlKHZhbHVlKSB7XG4gICAgICAgICAgICAgICAgaWYgKE9iamVjdC5nZXRQcm90b3R5cGVPZikge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gT2JqZWN0LmdldFByb3RvdHlwZU9mKHZhbHVlKTtcbiAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKHZhbHVlLl9fcHJvdG9fXykge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gdmFsdWUuX19wcm90b19fO1xuICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAodmFsdWUuY29uc3RydWN0b3IpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHZhbHVlLmNvbnN0cnVjdG9yLnByb3RvdHlwZTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH0sIHsgXCIuLi92bm9kZS9pcy12aG9vay5qc1wiOiAyNiwgXCJpcy1vYmplY3RcIjogMTEgfV0sIDE1OiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge1xuICAgICAgICAgICAgdmFyIGRvY3VtZW50ID0gcmVxdWlyZShcImdsb2JhbC9kb2N1bWVudFwiKTtcblxuICAgICAgICAgICAgdmFyIGFwcGx5UHJvcGVydGllcyA9IHJlcXVpcmUoXCIuL2FwcGx5LXByb3BlcnRpZXNcIik7XG5cbiAgICAgICAgICAgIHZhciBpc1ZOb2RlID0gcmVxdWlyZShcIi4uL3Zub2RlL2lzLXZub2RlLmpzXCIpO1xuICAgICAgICAgICAgdmFyIGlzVlRleHQgPSByZXF1aXJlKFwiLi4vdm5vZGUvaXMtdnRleHQuanNcIik7XG4gICAgICAgICAgICB2YXIgaXNXaWRnZXQgPSByZXF1aXJlKFwiLi4vdm5vZGUvaXMtd2lkZ2V0LmpzXCIpO1xuICAgICAgICAgICAgdmFyIGhhbmRsZVRodW5rID0gcmVxdWlyZShcIi4uL3Zub2RlL2hhbmRsZS10aHVuay5qc1wiKTtcblxuICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBjcmVhdGVFbGVtZW50O1xuXG4gICAgICAgICAgICBmdW5jdGlvbiBjcmVhdGVFbGVtZW50KHZub2RlLCBvcHRzKSB7XG4gICAgICAgICAgICAgICAgdmFyIGRvYyA9IG9wdHMgPyBvcHRzLmRvY3VtZW50IHx8IGRvY3VtZW50IDogZG9jdW1lbnQ7XG4gICAgICAgICAgICAgICAgdmFyIHdhcm4gPSBvcHRzID8gb3B0cy53YXJuIDogbnVsbDtcblxuICAgICAgICAgICAgICAgIHZub2RlID0gaGFuZGxlVGh1bmsodm5vZGUpLmE7XG5cbiAgICAgICAgICAgICAgICBpZiAoaXNXaWRnZXQodm5vZGUpKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiB2bm9kZS5pbml0KCk7XG4gICAgICAgICAgICAgICAgfSBlbHNlIGlmIChpc1ZUZXh0KHZub2RlKSkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gZG9jLmNyZWF0ZVRleHROb2RlKHZub2RlLnRleHQpO1xuICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoIWlzVk5vZGUodm5vZGUpKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmICh3YXJuKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICB3YXJuKFwiSXRlbSBpcyBub3QgYSB2YWxpZCB2aXJ0dWFsIGRvbSBub2RlXCIsIHZub2RlKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICByZXR1cm4gbnVsbDtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICB2YXIgbm9kZSA9IHZub2RlLm5hbWVzcGFjZSA9PT0gbnVsbCA/IGRvYy5jcmVhdGVFbGVtZW50KHZub2RlLnRhZ05hbWUpIDogZG9jLmNyZWF0ZUVsZW1lbnROUyh2bm9kZS5uYW1lc3BhY2UsIHZub2RlLnRhZ05hbWUpO1xuXG4gICAgICAgICAgICAgICAgdmFyIHByb3BzID0gdm5vZGUucHJvcGVydGllcztcbiAgICAgICAgICAgICAgICBhcHBseVByb3BlcnRpZXMobm9kZSwgcHJvcHMpO1xuXG4gICAgICAgICAgICAgICAgdmFyIGNoaWxkcmVuID0gdm5vZGUuY2hpbGRyZW47XG5cbiAgICAgICAgICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IGNoaWxkcmVuLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciBjaGlsZE5vZGUgPSBjcmVhdGVFbGVtZW50KGNoaWxkcmVuW2ldLCBvcHRzKTtcbiAgICAgICAgICAgICAgICAgICAgaWYgKGNoaWxkTm9kZSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgbm9kZS5hcHBlbmRDaGlsZChjaGlsZE5vZGUpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgcmV0dXJuIG5vZGU7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0sIHsgXCIuLi92bm9kZS9oYW5kbGUtdGh1bmsuanNcIjogMjQsIFwiLi4vdm5vZGUvaXMtdm5vZGUuanNcIjogMjcsIFwiLi4vdm5vZGUvaXMtdnRleHQuanNcIjogMjgsIFwiLi4vdm5vZGUvaXMtd2lkZ2V0LmpzXCI6IDI5LCBcIi4vYXBwbHktcHJvcGVydGllc1wiOiAxNCwgXCJnbG9iYWwvZG9jdW1lbnRcIjogMTAgfV0sIDE2OiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge1xuICAgICAgICAgICAgLy8gTWFwcyBhIHZpcnR1YWwgRE9NIHRyZWUgb250byBhIHJlYWwgRE9NIHRyZWUgaW4gYW4gZWZmaWNpZW50IG1hbm5lci5cbiAgICAgICAgICAgIC8vIFdlIGRvbid0IHdhbnQgdG8gcmVhZCBhbGwgb2YgdGhlIERPTSBub2RlcyBpbiB0aGUgdHJlZSBzbyB3ZSB1c2VcbiAgICAgICAgICAgIC8vIHRoZSBpbi1vcmRlciB0cmVlIGluZGV4aW5nIHRvIGVsaW1pbmF0ZSByZWN1cnNpb24gZG93biBjZXJ0YWluIGJyYW5jaGVzLlxuICAgICAgICAgICAgLy8gV2Ugb25seSByZWN1cnNlIGludG8gYSBET00gbm9kZSBpZiB3ZSBrbm93IHRoYXQgaXQgY29udGFpbnMgYSBjaGlsZCBvZlxuICAgICAgICAgICAgLy8gaW50ZXJlc3QuXG5cbiAgICAgICAgICAgIHZhciBub0NoaWxkID0ge307XG5cbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gZG9tSW5kZXg7XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIGRvbUluZGV4KHJvb3ROb2RlLCB0cmVlLCBpbmRpY2VzLCBub2Rlcykge1xuICAgICAgICAgICAgICAgIGlmICghaW5kaWNlcyB8fCBpbmRpY2VzLmxlbmd0aCA9PT0gMCkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4ge307XG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgaW5kaWNlcy5zb3J0KGFzY2VuZGluZyk7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiByZWN1cnNlKHJvb3ROb2RlLCB0cmVlLCBpbmRpY2VzLCBub2RlcywgMCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBmdW5jdGlvbiByZWN1cnNlKHJvb3ROb2RlLCB0cmVlLCBpbmRpY2VzLCBub2Rlcywgcm9vdEluZGV4KSB7XG4gICAgICAgICAgICAgICAgbm9kZXMgPSBub2RlcyB8fCB7fTtcblxuICAgICAgICAgICAgICAgIGlmIChyb290Tm9kZSkge1xuICAgICAgICAgICAgICAgICAgICBpZiAoaW5kZXhJblJhbmdlKGluZGljZXMsIHJvb3RJbmRleCwgcm9vdEluZGV4KSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgbm9kZXNbcm9vdEluZGV4XSA9IHJvb3ROb2RlO1xuICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgdmFyIHZDaGlsZHJlbiA9IHRyZWUuY2hpbGRyZW47XG5cbiAgICAgICAgICAgICAgICAgICAgaWYgKHZDaGlsZHJlbikge1xuXG4gICAgICAgICAgICAgICAgICAgICAgICB2YXIgY2hpbGROb2RlcyA9IHJvb3ROb2RlLmNoaWxkTm9kZXM7XG5cbiAgICAgICAgICAgICAgICAgICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgdHJlZS5jaGlsZHJlbi5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJvb3RJbmRleCArPSAxO1xuXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdmFyIHZDaGlsZCA9IHZDaGlsZHJlbltpXSB8fCBub0NoaWxkO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZhciBuZXh0SW5kZXggPSByb290SW5kZXggKyAodkNoaWxkLmNvdW50IHx8IDApO1xuXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gc2tpcCByZWN1cnNpb24gZG93biB0aGUgdHJlZSBpZiB0aGVyZSBhcmUgbm8gbm9kZXMgZG93biBoZXJlXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGluZGV4SW5SYW5nZShpbmRpY2VzLCByb290SW5kZXgsIG5leHRJbmRleCkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmVjdXJzZShjaGlsZE5vZGVzW2ldLCB2Q2hpbGQsIGluZGljZXMsIG5vZGVzLCByb290SW5kZXgpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJvb3RJbmRleCA9IG5leHRJbmRleDtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHJldHVybiBub2RlcztcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgLy8gQmluYXJ5IHNlYXJjaCBmb3IgYW4gaW5kZXggaW4gdGhlIGludGVydmFsIFtsZWZ0LCByaWdodF1cbiAgICAgICAgICAgIGZ1bmN0aW9uIGluZGV4SW5SYW5nZShpbmRpY2VzLCBsZWZ0LCByaWdodCkge1xuICAgICAgICAgICAgICAgIGlmIChpbmRpY2VzLmxlbmd0aCA9PT0gMCkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgdmFyIG1pbkluZGV4ID0gMDtcbiAgICAgICAgICAgICAgICB2YXIgbWF4SW5kZXggPSBpbmRpY2VzLmxlbmd0aCAtIDE7XG4gICAgICAgICAgICAgICAgdmFyIGN1cnJlbnRJbmRleDtcbiAgICAgICAgICAgICAgICB2YXIgY3VycmVudEl0ZW07XG5cbiAgICAgICAgICAgICAgICB3aGlsZSAobWluSW5kZXggPD0gbWF4SW5kZXgpIHtcbiAgICAgICAgICAgICAgICAgICAgY3VycmVudEluZGV4ID0gKG1heEluZGV4ICsgbWluSW5kZXgpIC8gMiA+PiAwO1xuICAgICAgICAgICAgICAgICAgICBjdXJyZW50SXRlbSA9IGluZGljZXNbY3VycmVudEluZGV4XTtcblxuICAgICAgICAgICAgICAgICAgICBpZiAobWluSW5kZXggPT09IG1heEluZGV4KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gY3VycmVudEl0ZW0gPj0gbGVmdCAmJiBjdXJyZW50SXRlbSA8PSByaWdodDtcbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIGlmIChjdXJyZW50SXRlbSA8IGxlZnQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIG1pbkluZGV4ID0gY3VycmVudEluZGV4ICsgMTtcbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIGlmIChjdXJyZW50SXRlbSA+IHJpZ2h0KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBtYXhJbmRleCA9IGN1cnJlbnRJbmRleCAtIDE7XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZnVuY3Rpb24gYXNjZW5kaW5nKGEsIGIpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gYSA+IGIgPyAxIDogLTE7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0sIHt9XSwgMTc6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICB2YXIgYXBwbHlQcm9wZXJ0aWVzID0gcmVxdWlyZShcIi4vYXBwbHktcHJvcGVydGllc1wiKTtcblxuICAgICAgICAgICAgdmFyIGlzV2lkZ2V0ID0gcmVxdWlyZShcIi4uL3Zub2RlL2lzLXdpZGdldC5qc1wiKTtcbiAgICAgICAgICAgIHZhciBWUGF0Y2ggPSByZXF1aXJlKFwiLi4vdm5vZGUvdnBhdGNoLmpzXCIpO1xuXG4gICAgICAgICAgICB2YXIgdXBkYXRlV2lkZ2V0ID0gcmVxdWlyZShcIi4vdXBkYXRlLXdpZGdldFwiKTtcblxuICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBhcHBseVBhdGNoO1xuXG4gICAgICAgICAgICBmdW5jdGlvbiBhcHBseVBhdGNoKHZwYXRjaCwgZG9tTm9kZSwgcmVuZGVyT3B0aW9ucykge1xuICAgICAgICAgICAgICAgIHZhciB0eXBlID0gdnBhdGNoLnR5cGU7XG4gICAgICAgICAgICAgICAgdmFyIHZOb2RlID0gdnBhdGNoLnZOb2RlO1xuICAgICAgICAgICAgICAgIHZhciBwYXRjaCA9IHZwYXRjaC5wYXRjaDtcblxuICAgICAgICAgICAgICAgIHN3aXRjaCAodHlwZSkge1xuICAgICAgICAgICAgICAgICAgICBjYXNlIFZQYXRjaC5SRU1PVkU6XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gcmVtb3ZlTm9kZShkb21Ob2RlLCB2Tm9kZSk7XG4gICAgICAgICAgICAgICAgICAgIGNhc2UgVlBhdGNoLklOU0VSVDpcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBpbnNlcnROb2RlKGRvbU5vZGUsIHBhdGNoLCByZW5kZXJPcHRpb25zKTtcbiAgICAgICAgICAgICAgICAgICAgY2FzZSBWUGF0Y2guVlRFWFQ6XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gc3RyaW5nUGF0Y2goZG9tTm9kZSwgdk5vZGUsIHBhdGNoLCByZW5kZXJPcHRpb25zKTtcbiAgICAgICAgICAgICAgICAgICAgY2FzZSBWUGF0Y2guV0lER0VUOlxuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHdpZGdldFBhdGNoKGRvbU5vZGUsIHZOb2RlLCBwYXRjaCwgcmVuZGVyT3B0aW9ucyk7XG4gICAgICAgICAgICAgICAgICAgIGNhc2UgVlBhdGNoLlZOT0RFOlxuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHZOb2RlUGF0Y2goZG9tTm9kZSwgdk5vZGUsIHBhdGNoLCByZW5kZXJPcHRpb25zKTtcbiAgICAgICAgICAgICAgICAgICAgY2FzZSBWUGF0Y2guT1JERVI6XG4gICAgICAgICAgICAgICAgICAgICAgICByZW9yZGVyQ2hpbGRyZW4oZG9tTm9kZSwgcGF0Y2gpO1xuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGRvbU5vZGU7XG4gICAgICAgICAgICAgICAgICAgIGNhc2UgVlBhdGNoLlBST1BTOlxuICAgICAgICAgICAgICAgICAgICAgICAgYXBwbHlQcm9wZXJ0aWVzKGRvbU5vZGUsIHBhdGNoLCB2Tm9kZS5wcm9wZXJ0aWVzKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBkb21Ob2RlO1xuICAgICAgICAgICAgICAgICAgICBjYXNlIFZQYXRjaC5USFVOSzpcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiByZXBsYWNlUm9vdChkb21Ob2RlLCByZW5kZXJPcHRpb25zLnBhdGNoKGRvbU5vZGUsIHBhdGNoLCByZW5kZXJPcHRpb25zKSk7XG4gICAgICAgICAgICAgICAgICAgIGRlZmF1bHQ6XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gZG9tTm9kZTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIHJlbW92ZU5vZGUoZG9tTm9kZSwgdk5vZGUpIHtcbiAgICAgICAgICAgICAgICB2YXIgcGFyZW50Tm9kZSA9IGRvbU5vZGUucGFyZW50Tm9kZTtcblxuICAgICAgICAgICAgICAgIGlmIChwYXJlbnROb2RlKSB7XG4gICAgICAgICAgICAgICAgICAgIHBhcmVudE5vZGUucmVtb3ZlQ2hpbGQoZG9tTm9kZSk7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgZGVzdHJveVdpZGdldChkb21Ob2RlLCB2Tm9kZSk7XG5cbiAgICAgICAgICAgICAgICByZXR1cm4gbnVsbDtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZnVuY3Rpb24gaW5zZXJ0Tm9kZShwYXJlbnROb2RlLCB2Tm9kZSwgcmVuZGVyT3B0aW9ucykge1xuICAgICAgICAgICAgICAgIHZhciBuZXdOb2RlID0gcmVuZGVyT3B0aW9ucy5yZW5kZXIodk5vZGUsIHJlbmRlck9wdGlvbnMpO1xuXG4gICAgICAgICAgICAgICAgaWYgKHBhcmVudE5vZGUpIHtcbiAgICAgICAgICAgICAgICAgICAgcGFyZW50Tm9kZS5hcHBlbmRDaGlsZChuZXdOb2RlKTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICByZXR1cm4gcGFyZW50Tm9kZTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZnVuY3Rpb24gc3RyaW5nUGF0Y2goZG9tTm9kZSwgbGVmdFZOb2RlLCB2VGV4dCwgcmVuZGVyT3B0aW9ucykge1xuICAgICAgICAgICAgICAgIHZhciBuZXdOb2RlO1xuXG4gICAgICAgICAgICAgICAgaWYgKGRvbU5vZGUubm9kZVR5cGUgPT09IDMpIHtcbiAgICAgICAgICAgICAgICAgICAgZG9tTm9kZS5yZXBsYWNlRGF0YSgwLCBkb21Ob2RlLmxlbmd0aCwgdlRleHQudGV4dCk7XG4gICAgICAgICAgICAgICAgICAgIG5ld05vZGUgPSBkb21Ob2RlO1xuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciBwYXJlbnROb2RlID0gZG9tTm9kZS5wYXJlbnROb2RlO1xuICAgICAgICAgICAgICAgICAgICBuZXdOb2RlID0gcmVuZGVyT3B0aW9ucy5yZW5kZXIodlRleHQsIHJlbmRlck9wdGlvbnMpO1xuXG4gICAgICAgICAgICAgICAgICAgIGlmIChwYXJlbnROb2RlICYmIG5ld05vZGUgIT09IGRvbU5vZGUpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHBhcmVudE5vZGUucmVwbGFjZUNoaWxkKG5ld05vZGUsIGRvbU5vZGUpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgcmV0dXJuIG5ld05vZGU7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIHdpZGdldFBhdGNoKGRvbU5vZGUsIGxlZnRWTm9kZSwgd2lkZ2V0LCByZW5kZXJPcHRpb25zKSB7XG4gICAgICAgICAgICAgICAgdmFyIHVwZGF0aW5nID0gdXBkYXRlV2lkZ2V0KGxlZnRWTm9kZSwgd2lkZ2V0KTtcbiAgICAgICAgICAgICAgICB2YXIgbmV3Tm9kZTtcblxuICAgICAgICAgICAgICAgIGlmICh1cGRhdGluZykge1xuICAgICAgICAgICAgICAgICAgICBuZXdOb2RlID0gd2lkZ2V0LnVwZGF0ZShsZWZ0Vk5vZGUsIGRvbU5vZGUpIHx8IGRvbU5vZGU7XG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgbmV3Tm9kZSA9IHJlbmRlck9wdGlvbnMucmVuZGVyKHdpZGdldCwgcmVuZGVyT3B0aW9ucyk7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgdmFyIHBhcmVudE5vZGUgPSBkb21Ob2RlLnBhcmVudE5vZGU7XG5cbiAgICAgICAgICAgICAgICBpZiAocGFyZW50Tm9kZSAmJiBuZXdOb2RlICE9PSBkb21Ob2RlKSB7XG4gICAgICAgICAgICAgICAgICAgIHBhcmVudE5vZGUucmVwbGFjZUNoaWxkKG5ld05vZGUsIGRvbU5vZGUpO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIGlmICghdXBkYXRpbmcpIHtcbiAgICAgICAgICAgICAgICAgICAgZGVzdHJveVdpZGdldChkb21Ob2RlLCBsZWZ0Vk5vZGUpO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHJldHVybiBuZXdOb2RlO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBmdW5jdGlvbiB2Tm9kZVBhdGNoKGRvbU5vZGUsIGxlZnRWTm9kZSwgdk5vZGUsIHJlbmRlck9wdGlvbnMpIHtcbiAgICAgICAgICAgICAgICB2YXIgcGFyZW50Tm9kZSA9IGRvbU5vZGUucGFyZW50Tm9kZTtcbiAgICAgICAgICAgICAgICB2YXIgbmV3Tm9kZSA9IHJlbmRlck9wdGlvbnMucmVuZGVyKHZOb2RlLCByZW5kZXJPcHRpb25zKTtcblxuICAgICAgICAgICAgICAgIGlmIChwYXJlbnROb2RlICYmIG5ld05vZGUgIT09IGRvbU5vZGUpIHtcbiAgICAgICAgICAgICAgICAgICAgcGFyZW50Tm9kZS5yZXBsYWNlQ2hpbGQobmV3Tm9kZSwgZG9tTm9kZSk7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgcmV0dXJuIG5ld05vZGU7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIGRlc3Ryb3lXaWRnZXQoZG9tTm9kZSwgdykge1xuICAgICAgICAgICAgICAgIGlmICh0eXBlb2Ygdy5kZXN0cm95ID09PSBcImZ1bmN0aW9uXCIgJiYgaXNXaWRnZXQodykpIHtcbiAgICAgICAgICAgICAgICAgICAgdy5kZXN0cm95KGRvbU5vZGUpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZnVuY3Rpb24gcmVvcmRlckNoaWxkcmVuKGRvbU5vZGUsIG1vdmVzKSB7XG4gICAgICAgICAgICAgICAgdmFyIGNoaWxkTm9kZXMgPSBkb21Ob2RlLmNoaWxkTm9kZXM7XG4gICAgICAgICAgICAgICAgdmFyIGtleU1hcCA9IHt9O1xuICAgICAgICAgICAgICAgIHZhciBub2RlO1xuICAgICAgICAgICAgICAgIHZhciByZW1vdmU7XG4gICAgICAgICAgICAgICAgdmFyIGluc2VydDtcblxuICAgICAgICAgICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgbW92ZXMucmVtb3Zlcy5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgICAgICAgICByZW1vdmUgPSBtb3Zlcy5yZW1vdmVzW2ldO1xuICAgICAgICAgICAgICAgICAgICBub2RlID0gY2hpbGROb2Rlc1tyZW1vdmUuZnJvbV07XG4gICAgICAgICAgICAgICAgICAgIGlmIChyZW1vdmUua2V5KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBrZXlNYXBbcmVtb3ZlLmtleV0gPSBub2RlO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIGRvbU5vZGUucmVtb3ZlQ2hpbGQobm9kZSk7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgdmFyIGxlbmd0aCA9IGNoaWxkTm9kZXMubGVuZ3RoO1xuICAgICAgICAgICAgICAgIGZvciAodmFyIGogPSAwOyBqIDwgbW92ZXMuaW5zZXJ0cy5sZW5ndGg7IGorKykge1xuICAgICAgICAgICAgICAgICAgICBpbnNlcnQgPSBtb3Zlcy5pbnNlcnRzW2pdO1xuICAgICAgICAgICAgICAgICAgICBub2RlID0ga2V5TWFwW2luc2VydC5rZXldO1xuICAgICAgICAgICAgICAgICAgICAvLyB0aGlzIGlzIHRoZSB3ZWlyZGVzdCBidWcgaSd2ZSBldmVyIHNlZW4gaW4gd2Via2l0XG4gICAgICAgICAgICAgICAgICAgIGRvbU5vZGUuaW5zZXJ0QmVmb3JlKG5vZGUsIGluc2VydC50byA+PSBsZW5ndGgrKyA/IG51bGwgOiBjaGlsZE5vZGVzW2luc2VydC50b10pO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZnVuY3Rpb24gcmVwbGFjZVJvb3Qob2xkUm9vdCwgbmV3Um9vdCkge1xuICAgICAgICAgICAgICAgIGlmIChvbGRSb290ICYmIG5ld1Jvb3QgJiYgb2xkUm9vdCAhPT0gbmV3Um9vdCAmJiBvbGRSb290LnBhcmVudE5vZGUpIHtcbiAgICAgICAgICAgICAgICAgICAgb2xkUm9vdC5wYXJlbnROb2RlLnJlcGxhY2VDaGlsZChuZXdSb290LCBvbGRSb290KTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICByZXR1cm4gbmV3Um9vdDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSwgeyBcIi4uL3Zub2RlL2lzLXdpZGdldC5qc1wiOiAyOSwgXCIuLi92bm9kZS92cGF0Y2guanNcIjogMzIsIFwiLi9hcHBseS1wcm9wZXJ0aWVzXCI6IDE0LCBcIi4vdXBkYXRlLXdpZGdldFwiOiAxOSB9XSwgMTg6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICB2YXIgZG9jdW1lbnQgPSByZXF1aXJlKFwiZ2xvYmFsL2RvY3VtZW50XCIpO1xuICAgICAgICAgICAgdmFyIGlzQXJyYXkgPSByZXF1aXJlKFwieC1pcy1hcnJheVwiKTtcblxuICAgICAgICAgICAgdmFyIHJlbmRlciA9IHJlcXVpcmUoXCIuL2NyZWF0ZS1lbGVtZW50XCIpO1xuICAgICAgICAgICAgdmFyIGRvbUluZGV4ID0gcmVxdWlyZShcIi4vZG9tLWluZGV4XCIpO1xuICAgICAgICAgICAgdmFyIHBhdGNoT3AgPSByZXF1aXJlKFwiLi9wYXRjaC1vcFwiKTtcbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gcGF0Y2g7XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIHBhdGNoKHJvb3ROb2RlLCBwYXRjaGVzLCByZW5kZXJPcHRpb25zKSB7XG4gICAgICAgICAgICAgICAgcmVuZGVyT3B0aW9ucyA9IHJlbmRlck9wdGlvbnMgfHwge307XG4gICAgICAgICAgICAgICAgcmVuZGVyT3B0aW9ucy5wYXRjaCA9IHJlbmRlck9wdGlvbnMucGF0Y2ggJiYgcmVuZGVyT3B0aW9ucy5wYXRjaCAhPT0gcGF0Y2ggPyByZW5kZXJPcHRpb25zLnBhdGNoIDogcGF0Y2hSZWN1cnNpdmU7XG4gICAgICAgICAgICAgICAgcmVuZGVyT3B0aW9ucy5yZW5kZXIgPSByZW5kZXJPcHRpb25zLnJlbmRlciB8fCByZW5kZXI7XG5cbiAgICAgICAgICAgICAgICByZXR1cm4gcmVuZGVyT3B0aW9ucy5wYXRjaChyb290Tm9kZSwgcGF0Y2hlcywgcmVuZGVyT3B0aW9ucyk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIHBhdGNoUmVjdXJzaXZlKHJvb3ROb2RlLCBwYXRjaGVzLCByZW5kZXJPcHRpb25zKSB7XG4gICAgICAgICAgICAgICAgdmFyIGluZGljZXMgPSBwYXRjaEluZGljZXMocGF0Y2hlcyk7XG5cbiAgICAgICAgICAgICAgICBpZiAoaW5kaWNlcy5sZW5ndGggPT09IDApIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHJvb3ROb2RlO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHZhciBpbmRleCA9IGRvbUluZGV4KHJvb3ROb2RlLCBwYXRjaGVzLmEsIGluZGljZXMpO1xuICAgICAgICAgICAgICAgIHZhciBvd25lckRvY3VtZW50ID0gcm9vdE5vZGUub3duZXJEb2N1bWVudDtcblxuICAgICAgICAgICAgICAgIGlmICghcmVuZGVyT3B0aW9ucy5kb2N1bWVudCAmJiBvd25lckRvY3VtZW50ICE9PSBkb2N1bWVudCkge1xuICAgICAgICAgICAgICAgICAgICByZW5kZXJPcHRpb25zLmRvY3VtZW50ID0gb3duZXJEb2N1bWVudDtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IGluZGljZXMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgICAgICAgICAgdmFyIG5vZGVJbmRleCA9IGluZGljZXNbaV07XG4gICAgICAgICAgICAgICAgICAgIHJvb3ROb2RlID0gYXBwbHlQYXRjaChyb290Tm9kZSwgaW5kZXhbbm9kZUluZGV4XSwgcGF0Y2hlc1tub2RlSW5kZXhdLCByZW5kZXJPcHRpb25zKTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICByZXR1cm4gcm9vdE5vZGU7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIGFwcGx5UGF0Y2gocm9vdE5vZGUsIGRvbU5vZGUsIHBhdGNoTGlzdCwgcmVuZGVyT3B0aW9ucykge1xuICAgICAgICAgICAgICAgIGlmICghZG9tTm9kZSkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gcm9vdE5vZGU7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgdmFyIG5ld05vZGU7XG5cbiAgICAgICAgICAgICAgICBpZiAoaXNBcnJheShwYXRjaExpc3QpKSB7XG4gICAgICAgICAgICAgICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgcGF0Y2hMaXN0Lmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBuZXdOb2RlID0gcGF0Y2hPcChwYXRjaExpc3RbaV0sIGRvbU5vZGUsIHJlbmRlck9wdGlvbnMpO1xuXG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoZG9tTm9kZSA9PT0gcm9vdE5vZGUpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICByb290Tm9kZSA9IG5ld05vZGU7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICBuZXdOb2RlID0gcGF0Y2hPcChwYXRjaExpc3QsIGRvbU5vZGUsIHJlbmRlck9wdGlvbnMpO1xuXG4gICAgICAgICAgICAgICAgICAgIGlmIChkb21Ob2RlID09PSByb290Tm9kZSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgcm9vdE5vZGUgPSBuZXdOb2RlO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgcmV0dXJuIHJvb3ROb2RlO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBmdW5jdGlvbiBwYXRjaEluZGljZXMocGF0Y2hlcykge1xuICAgICAgICAgICAgICAgIHZhciBpbmRpY2VzID0gW107XG5cbiAgICAgICAgICAgICAgICBmb3IgKHZhciBrZXkgaW4gcGF0Y2hlcykge1xuICAgICAgICAgICAgICAgICAgICBpZiAoa2V5ICE9PSBcImFcIikge1xuICAgICAgICAgICAgICAgICAgICAgICAgaW5kaWNlcy5wdXNoKE51bWJlcihrZXkpKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHJldHVybiBpbmRpY2VzO1xuICAgICAgICAgICAgfVxuICAgICAgICB9LCB7IFwiLi9jcmVhdGUtZWxlbWVudFwiOiAxNSwgXCIuL2RvbS1pbmRleFwiOiAxNiwgXCIuL3BhdGNoLW9wXCI6IDE3LCBcImdsb2JhbC9kb2N1bWVudFwiOiAxMCwgXCJ4LWlzLWFycmF5XCI6IDEyIH1dLCAxOTogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHtcbiAgICAgICAgICAgIHZhciBpc1dpZGdldCA9IHJlcXVpcmUoXCIuLi92bm9kZS9pcy13aWRnZXQuanNcIik7XG5cbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gdXBkYXRlV2lkZ2V0O1xuXG4gICAgICAgICAgICBmdW5jdGlvbiB1cGRhdGVXaWRnZXQoYSwgYikge1xuICAgICAgICAgICAgICAgIGlmIChpc1dpZGdldChhKSAmJiBpc1dpZGdldChiKSkge1xuICAgICAgICAgICAgICAgICAgICBpZiAoXCJuYW1lXCIgaW4gYSAmJiBcIm5hbWVcIiBpbiBiKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gYS5pZCA9PT0gYi5pZDtcbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBhLmluaXQgPT09IGIuaW5pdDtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSwgeyBcIi4uL3Zub2RlL2lzLXdpZGdldC5qc1wiOiAyOSB9XSwgMjA6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICBcInVzZSBzdHJpY3RcIjtcblxuICAgICAgICAgICAgdmFyIEV2U3RvcmUgPSByZXF1aXJlKFwiZXYtc3RvcmVcIik7XG5cbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gRXZIb29rO1xuXG4gICAgICAgICAgICBmdW5jdGlvbiBFdkhvb2sodmFsdWUpIHtcbiAgICAgICAgICAgICAgICBpZiAoISh0aGlzIGluc3RhbmNlb2YgRXZIb29rKSkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gbmV3IEV2SG9vayh2YWx1ZSk7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgdGhpcy52YWx1ZSA9IHZhbHVlO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBFdkhvb2sucHJvdG90eXBlLmhvb2sgPSBmdW5jdGlvbiAobm9kZSwgcHJvcGVydHlOYW1lKSB7XG4gICAgICAgICAgICAgICAgdmFyIGVzID0gRXZTdG9yZShub2RlKTtcbiAgICAgICAgICAgICAgICB2YXIgcHJvcE5hbWUgPSBwcm9wZXJ0eU5hbWUuc3Vic3RyKDMpO1xuXG4gICAgICAgICAgICAgICAgZXNbcHJvcE5hbWVdID0gdGhpcy52YWx1ZTtcbiAgICAgICAgICAgIH07XG5cbiAgICAgICAgICAgIEV2SG9vay5wcm90b3R5cGUudW5ob29rID0gZnVuY3Rpb24gKG5vZGUsIHByb3BlcnR5TmFtZSkge1xuICAgICAgICAgICAgICAgIHZhciBlcyA9IEV2U3RvcmUobm9kZSk7XG4gICAgICAgICAgICAgICAgdmFyIHByb3BOYW1lID0gcHJvcGVydHlOYW1lLnN1YnN0cigzKTtcblxuICAgICAgICAgICAgICAgIGVzW3Byb3BOYW1lXSA9IHVuZGVmaW5lZDtcbiAgICAgICAgICAgIH07XG4gICAgICAgIH0sIHsgXCJldi1zdG9yZVwiOiA3IH1dLCAyMTogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHtcbiAgICAgICAgICAgIFwidXNlIHN0cmljdFwiO1xuXG4gICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IFNvZnRTZXRIb29rO1xuXG4gICAgICAgICAgICBmdW5jdGlvbiBTb2Z0U2V0SG9vayh2YWx1ZSkge1xuICAgICAgICAgICAgICAgIGlmICghKHRoaXMgaW5zdGFuY2VvZiBTb2Z0U2V0SG9vaykpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIG5ldyBTb2Z0U2V0SG9vayh2YWx1ZSk7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgdGhpcy52YWx1ZSA9IHZhbHVlO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBTb2Z0U2V0SG9vay5wcm90b3R5cGUuaG9vayA9IGZ1bmN0aW9uIChub2RlLCBwcm9wZXJ0eU5hbWUpIHtcbiAgICAgICAgICAgICAgICBpZiAobm9kZVtwcm9wZXJ0eU5hbWVdICE9PSB0aGlzLnZhbHVlKSB7XG4gICAgICAgICAgICAgICAgICAgIG5vZGVbcHJvcGVydHlOYW1lXSA9IHRoaXMudmFsdWU7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfTtcbiAgICAgICAgfSwge31dLCAyMjogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHtcbiAgICAgICAgICAgIFwidXNlIHN0cmljdFwiO1xuXG4gICAgICAgICAgICB2YXIgaXNBcnJheSA9IHJlcXVpcmUoXCJ4LWlzLWFycmF5XCIpO1xuXG4gICAgICAgICAgICB2YXIgVk5vZGUgPSByZXF1aXJlKFwiLi4vdm5vZGUvdm5vZGUuanNcIik7XG4gICAgICAgICAgICB2YXIgVlRleHQgPSByZXF1aXJlKFwiLi4vdm5vZGUvdnRleHQuanNcIik7XG4gICAgICAgICAgICB2YXIgaXNWTm9kZSA9IHJlcXVpcmUoXCIuLi92bm9kZS9pcy12bm9kZVwiKTtcbiAgICAgICAgICAgIHZhciBpc1ZUZXh0ID0gcmVxdWlyZShcIi4uL3Zub2RlL2lzLXZ0ZXh0XCIpO1xuICAgICAgICAgICAgdmFyIGlzV2lkZ2V0ID0gcmVxdWlyZShcIi4uL3Zub2RlL2lzLXdpZGdldFwiKTtcbiAgICAgICAgICAgIHZhciBpc0hvb2sgPSByZXF1aXJlKFwiLi4vdm5vZGUvaXMtdmhvb2tcIik7XG4gICAgICAgICAgICB2YXIgaXNWVGh1bmsgPSByZXF1aXJlKFwiLi4vdm5vZGUvaXMtdGh1bmtcIik7XG5cbiAgICAgICAgICAgIHZhciBwYXJzZVRhZyA9IHJlcXVpcmUoXCIuL3BhcnNlLXRhZy5qc1wiKTtcbiAgICAgICAgICAgIHZhciBzb2Z0U2V0SG9vayA9IHJlcXVpcmUoXCIuL2hvb2tzL3NvZnQtc2V0LWhvb2suanNcIik7XG4gICAgICAgICAgICB2YXIgZXZIb29rID0gcmVxdWlyZShcIi4vaG9va3MvZXYtaG9vay5qc1wiKTtcblxuICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBoO1xuXG4gICAgICAgICAgICBmdW5jdGlvbiBoKHRhZ05hbWUsIHByb3BlcnRpZXMsIGNoaWxkcmVuKSB7XG4gICAgICAgICAgICAgICAgdmFyIGNoaWxkTm9kZXMgPSBbXTtcbiAgICAgICAgICAgICAgICB2YXIgdGFnLCBwcm9wcywga2V5LCBuYW1lc3BhY2U7XG5cbiAgICAgICAgICAgICAgICBpZiAoIWNoaWxkcmVuICYmIGlzQ2hpbGRyZW4ocHJvcGVydGllcykpIHtcbiAgICAgICAgICAgICAgICAgICAgY2hpbGRyZW4gPSBwcm9wZXJ0aWVzO1xuICAgICAgICAgICAgICAgICAgICBwcm9wcyA9IHt9O1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHByb3BzID0gcHJvcHMgfHwgcHJvcGVydGllcyB8fCB7fTtcbiAgICAgICAgICAgICAgICB0YWcgPSBwYXJzZVRhZyh0YWdOYW1lLCBwcm9wcyk7XG5cbiAgICAgICAgICAgICAgICAvLyBzdXBwb3J0IGtleXNcbiAgICAgICAgICAgICAgICBpZiAocHJvcHMuaGFzT3duUHJvcGVydHkoXCJrZXlcIikpIHtcbiAgICAgICAgICAgICAgICAgICAga2V5ID0gcHJvcHMua2V5O1xuICAgICAgICAgICAgICAgICAgICBwcm9wcy5rZXkgPSB1bmRlZmluZWQ7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgLy8gc3VwcG9ydCBuYW1lc3BhY2VcbiAgICAgICAgICAgICAgICBpZiAocHJvcHMuaGFzT3duUHJvcGVydHkoXCJuYW1lc3BhY2VcIikpIHtcbiAgICAgICAgICAgICAgICAgICAgbmFtZXNwYWNlID0gcHJvcHMubmFtZXNwYWNlO1xuICAgICAgICAgICAgICAgICAgICBwcm9wcy5uYW1lc3BhY2UgPSB1bmRlZmluZWQ7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgLy8gZml4IGN1cnNvciBidWdcbiAgICAgICAgICAgICAgICBpZiAodGFnID09PSBcIklOUFVUXCIgJiYgIW5hbWVzcGFjZSAmJiBwcm9wcy5oYXNPd25Qcm9wZXJ0eShcInZhbHVlXCIpICYmIHByb3BzLnZhbHVlICE9PSB1bmRlZmluZWQgJiYgIWlzSG9vayhwcm9wcy52YWx1ZSkpIHtcbiAgICAgICAgICAgICAgICAgICAgcHJvcHMudmFsdWUgPSBzb2Z0U2V0SG9vayhwcm9wcy52YWx1ZSk7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgdHJhbnNmb3JtUHJvcGVydGllcyhwcm9wcyk7XG5cbiAgICAgICAgICAgICAgICBpZiAoY2hpbGRyZW4gIT09IHVuZGVmaW5lZCAmJiBjaGlsZHJlbiAhPT0gbnVsbCkge1xuICAgICAgICAgICAgICAgICAgICBhZGRDaGlsZChjaGlsZHJlbiwgY2hpbGROb2RlcywgdGFnLCBwcm9wcyk7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgcmV0dXJuIG5ldyBWTm9kZSh0YWcsIHByb3BzLCBjaGlsZE5vZGVzLCBrZXksIG5hbWVzcGFjZSk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIGFkZENoaWxkKGMsIGNoaWxkTm9kZXMsIHRhZywgcHJvcHMpIHtcbiAgICAgICAgICAgICAgICBpZiAodHlwZW9mIGMgPT09IFwic3RyaW5nXCIpIHtcbiAgICAgICAgICAgICAgICAgICAgY2hpbGROb2Rlcy5wdXNoKG5ldyBWVGV4dChjKSk7XG4gICAgICAgICAgICAgICAgfSBlbHNlIGlmICh0eXBlb2YgYyA9PT0gXCJudW1iZXJcIikge1xuICAgICAgICAgICAgICAgICAgICBjaGlsZE5vZGVzLnB1c2gobmV3IFZUZXh0KFN0cmluZyhjKSkpO1xuICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoaXNDaGlsZChjKSkge1xuICAgICAgICAgICAgICAgICAgICBjaGlsZE5vZGVzLnB1c2goYyk7XG4gICAgICAgICAgICAgICAgfSBlbHNlIGlmIChpc0FycmF5KGMpKSB7XG4gICAgICAgICAgICAgICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgYy5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgICAgICAgICAgICAgYWRkQ2hpbGQoY1tpXSwgY2hpbGROb2RlcywgdGFnLCBwcm9wcyk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKGMgPT09IG51bGwgfHwgYyA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICB0aHJvdyBVbmV4cGVjdGVkVmlydHVhbEVsZW1lbnQoe1xuICAgICAgICAgICAgICAgICAgICAgICAgZm9yZWlnbk9iamVjdDogYyxcbiAgICAgICAgICAgICAgICAgICAgICAgIHBhcmVudFZub2RlOiB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdGFnTmFtZTogdGFnLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHByb3BlcnRpZXM6IHByb3BzXG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZnVuY3Rpb24gdHJhbnNmb3JtUHJvcGVydGllcyhwcm9wcykge1xuICAgICAgICAgICAgICAgIGZvciAodmFyIHByb3BOYW1lIGluIHByb3BzKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmIChwcm9wcy5oYXNPd25Qcm9wZXJ0eShwcm9wTmFtZSkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHZhciB2YWx1ZSA9IHByb3BzW3Byb3BOYW1lXTtcblxuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGlzSG9vayh2YWx1ZSkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb250aW51ZTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHByb3BOYW1lLnN1YnN0cigwLCAzKSA9PT0gXCJldi1cIikge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIGFkZCBldi1mb28gc3VwcG9ydFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHByb3BzW3Byb3BOYW1lXSA9IGV2SG9vayh2YWx1ZSk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIGlzQ2hpbGQoeCkge1xuICAgICAgICAgICAgICAgIHJldHVybiBpc1ZOb2RlKHgpIHx8IGlzVlRleHQoeCkgfHwgaXNXaWRnZXQoeCkgfHwgaXNWVGh1bmsoeCk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIGlzQ2hpbGRyZW4oeCkge1xuICAgICAgICAgICAgICAgIHJldHVybiB0eXBlb2YgeCA9PT0gXCJzdHJpbmdcIiB8fCBpc0FycmF5KHgpIHx8IGlzQ2hpbGQoeCk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIFVuZXhwZWN0ZWRWaXJ0dWFsRWxlbWVudChkYXRhKSB7XG4gICAgICAgICAgICAgICAgdmFyIGVyciA9IG5ldyBFcnJvcigpO1xuXG4gICAgICAgICAgICAgICAgZXJyLnR5cGUgPSBcInZpcnR1YWwtaHlwZXJzY3JpcHQudW5leHBlY3RlZC52aXJ0dWFsLWVsZW1lbnRcIjtcbiAgICAgICAgICAgICAgICBlcnIubWVzc2FnZSA9IFwiVW5leHBlY3RlZCB2aXJ0dWFsIGNoaWxkIHBhc3NlZCB0byBoKCkuXFxuXCIgKyBcIkV4cGVjdGVkIGEgVk5vZGUgLyBWdGh1bmsgLyBWV2lkZ2V0IC8gc3RyaW5nIGJ1dDpcXG5cIiArIFwiZ290OlxcblwiICsgZXJyb3JTdHJpbmcoZGF0YS5mb3JlaWduT2JqZWN0KSArIFwiLlxcblwiICsgXCJUaGUgcGFyZW50IHZub2RlIGlzOlxcblwiICsgZXJyb3JTdHJpbmcoZGF0YS5wYXJlbnRWbm9kZSk7XG4gICAgICAgICAgICAgICAgXCJcXG5cIiArIFwiU3VnZ2VzdGVkIGZpeDogY2hhbmdlIHlvdXIgYGgoLi4uLCBbIC4uLiBdKWAgY2FsbHNpdGUuXCI7XG4gICAgICAgICAgICAgICAgZXJyLmZvcmVpZ25PYmplY3QgPSBkYXRhLmZvcmVpZ25PYmplY3Q7XG4gICAgICAgICAgICAgICAgZXJyLnBhcmVudFZub2RlID0gZGF0YS5wYXJlbnRWbm9kZTtcblxuICAgICAgICAgICAgICAgIHJldHVybiBlcnI7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIGVycm9yU3RyaW5nKG9iaikge1xuICAgICAgICAgICAgICAgIHRyeSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBKU09OLnN0cmluZ2lmeShvYmosIG51bGwsIFwiICAgIFwiKTtcbiAgICAgICAgICAgICAgICB9IGNhdGNoIChlKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBTdHJpbmcob2JqKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH0sIHsgXCIuLi92bm9kZS9pcy10aHVua1wiOiAyNSwgXCIuLi92bm9kZS9pcy12aG9va1wiOiAyNiwgXCIuLi92bm9kZS9pcy12bm9kZVwiOiAyNywgXCIuLi92bm9kZS9pcy12dGV4dFwiOiAyOCwgXCIuLi92bm9kZS9pcy13aWRnZXRcIjogMjksIFwiLi4vdm5vZGUvdm5vZGUuanNcIjogMzEsIFwiLi4vdm5vZGUvdnRleHQuanNcIjogMzMsIFwiLi9ob29rcy9ldi1ob29rLmpzXCI6IDIwLCBcIi4vaG9va3Mvc29mdC1zZXQtaG9vay5qc1wiOiAyMSwgXCIuL3BhcnNlLXRhZy5qc1wiOiAyMywgXCJ4LWlzLWFycmF5XCI6IDEyIH1dLCAyMzogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHtcbiAgICAgICAgICAgIFwidXNlIHN0cmljdFwiO1xuXG4gICAgICAgICAgICB2YXIgc3BsaXQgPSByZXF1aXJlKFwiYnJvd3Nlci1zcGxpdFwiKTtcblxuICAgICAgICAgICAgdmFyIGNsYXNzSWRTcGxpdCA9IC8oW1xcLiNdP1thLXpBLVowLTlcXHUwMDdGLVxcdUZGRkZfOi1dKykvO1xuICAgICAgICAgICAgdmFyIG5vdENsYXNzSWQgPSAvXlxcLnwjLztcblxuICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBwYXJzZVRhZztcblxuICAgICAgICAgICAgZnVuY3Rpb24gcGFyc2VUYWcodGFnLCBwcm9wcykge1xuICAgICAgICAgICAgICAgIGlmICghdGFnKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBcIkRJVlwiO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHZhciBub0lkID0gIXByb3BzLmhhc093blByb3BlcnR5KFwiaWRcIik7XG5cbiAgICAgICAgICAgICAgICB2YXIgdGFnUGFydHMgPSBzcGxpdCh0YWcsIGNsYXNzSWRTcGxpdCk7XG4gICAgICAgICAgICAgICAgdmFyIHRhZ05hbWUgPSBudWxsO1xuXG4gICAgICAgICAgICAgICAgaWYgKG5vdENsYXNzSWQudGVzdCh0YWdQYXJ0c1sxXSkpIHtcbiAgICAgICAgICAgICAgICAgICAgdGFnTmFtZSA9IFwiRElWXCI7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgdmFyIGNsYXNzZXMsIHBhcnQsIHR5cGUsIGk7XG5cbiAgICAgICAgICAgICAgICBmb3IgKGkgPSAwOyBpIDwgdGFnUGFydHMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgICAgICAgICAgcGFydCA9IHRhZ1BhcnRzW2ldO1xuXG4gICAgICAgICAgICAgICAgICAgIGlmICghcGFydCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgY29udGludWU7XG4gICAgICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgICAgICB0eXBlID0gcGFydC5jaGFyQXQoMCk7XG5cbiAgICAgICAgICAgICAgICAgICAgaWYgKCF0YWdOYW1lKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICB0YWdOYW1lID0gcGFydDtcbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIGlmICh0eXBlID09PSBcIi5cIikge1xuICAgICAgICAgICAgICAgICAgICAgICAgY2xhc3NlcyA9IGNsYXNzZXMgfHwgW107XG4gICAgICAgICAgICAgICAgICAgICAgICBjbGFzc2VzLnB1c2gocGFydC5zdWJzdHJpbmcoMSwgcGFydC5sZW5ndGgpKTtcbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIGlmICh0eXBlID09PSBcIiNcIiAmJiBub0lkKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBwcm9wcy5pZCA9IHBhcnQuc3Vic3RyaW5nKDEsIHBhcnQubGVuZ3RoKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIGlmIChjbGFzc2VzKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmIChwcm9wcy5jbGFzc05hbWUpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGNsYXNzZXMucHVzaChwcm9wcy5jbGFzc05hbWUpO1xuICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgcHJvcHMuY2xhc3NOYW1lID0gY2xhc3Nlcy5qb2luKFwiIFwiKTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICByZXR1cm4gcHJvcHMubmFtZXNwYWNlID8gdGFnTmFtZSA6IHRhZ05hbWUudG9VcHBlckNhc2UoKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSwgeyBcImJyb3dzZXItc3BsaXRcIjogNSB9XSwgMjQ6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICB2YXIgaXNWTm9kZSA9IHJlcXVpcmUoXCIuL2lzLXZub2RlXCIpO1xuICAgICAgICAgICAgdmFyIGlzVlRleHQgPSByZXF1aXJlKFwiLi9pcy12dGV4dFwiKTtcbiAgICAgICAgICAgIHZhciBpc1dpZGdldCA9IHJlcXVpcmUoXCIuL2lzLXdpZGdldFwiKTtcbiAgICAgICAgICAgIHZhciBpc1RodW5rID0gcmVxdWlyZShcIi4vaXMtdGh1bmtcIik7XG5cbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gaGFuZGxlVGh1bms7XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIGhhbmRsZVRodW5rKGEsIGIpIHtcbiAgICAgICAgICAgICAgICB2YXIgcmVuZGVyZWRBID0gYTtcbiAgICAgICAgICAgICAgICB2YXIgcmVuZGVyZWRCID0gYjtcblxuICAgICAgICAgICAgICAgIGlmIChpc1RodW5rKGIpKSB7XG4gICAgICAgICAgICAgICAgICAgIHJlbmRlcmVkQiA9IHJlbmRlclRodW5rKGIsIGEpO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIGlmIChpc1RodW5rKGEpKSB7XG4gICAgICAgICAgICAgICAgICAgIHJlbmRlcmVkQSA9IHJlbmRlclRodW5rKGEsIG51bGwpO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHJldHVybiB7XG4gICAgICAgICAgICAgICAgICAgIGE6IHJlbmRlcmVkQSxcbiAgICAgICAgICAgICAgICAgICAgYjogcmVuZGVyZWRCXG4gICAgICAgICAgICAgICAgfTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZnVuY3Rpb24gcmVuZGVyVGh1bmsodGh1bmssIHByZXZpb3VzKSB7XG4gICAgICAgICAgICAgICAgdmFyIHJlbmRlcmVkVGh1bmsgPSB0aHVuay52bm9kZTtcblxuICAgICAgICAgICAgICAgIGlmICghcmVuZGVyZWRUaHVuaykge1xuICAgICAgICAgICAgICAgICAgICByZW5kZXJlZFRodW5rID0gdGh1bmsudm5vZGUgPSB0aHVuay5yZW5kZXIocHJldmlvdXMpO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIGlmICghKGlzVk5vZGUocmVuZGVyZWRUaHVuaykgfHwgaXNWVGV4dChyZW5kZXJlZFRodW5rKSB8fCBpc1dpZGdldChyZW5kZXJlZFRodW5rKSkpIHtcbiAgICAgICAgICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKFwidGh1bmsgZGlkIG5vdCByZXR1cm4gYSB2YWxpZCBub2RlXCIpO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHJldHVybiByZW5kZXJlZFRodW5rO1xuICAgICAgICAgICAgfVxuICAgICAgICB9LCB7IFwiLi9pcy10aHVua1wiOiAyNSwgXCIuL2lzLXZub2RlXCI6IDI3LCBcIi4vaXMtdnRleHRcIjogMjgsIFwiLi9pcy13aWRnZXRcIjogMjkgfV0sIDI1OiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge1xuICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBpc1RodW5rO1xuXG4gICAgICAgICAgICBmdW5jdGlvbiBpc1RodW5rKHQpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gdCAmJiB0LnR5cGUgPT09IFwiVGh1bmtcIjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSwge31dLCAyNjogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHtcbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gaXNIb29rO1xuXG4gICAgICAgICAgICBmdW5jdGlvbiBpc0hvb2soaG9vaykge1xuICAgICAgICAgICAgICAgIHJldHVybiBob29rICYmICh0eXBlb2YgaG9vay5ob29rID09PSBcImZ1bmN0aW9uXCIgJiYgIWhvb2suaGFzT3duUHJvcGVydHkoXCJob29rXCIpIHx8IHR5cGVvZiBob29rLnVuaG9vayA9PT0gXCJmdW5jdGlvblwiICYmICFob29rLmhhc093blByb3BlcnR5KFwidW5ob29rXCIpKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSwge31dLCAyNzogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHtcbiAgICAgICAgICAgIHZhciB2ZXJzaW9uID0gcmVxdWlyZShcIi4vdmVyc2lvblwiKTtcblxuICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBpc1ZpcnR1YWxOb2RlO1xuXG4gICAgICAgICAgICBmdW5jdGlvbiBpc1ZpcnR1YWxOb2RlKHgpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4geCAmJiB4LnR5cGUgPT09IFwiVmlydHVhbE5vZGVcIiAmJiB4LnZlcnNpb24gPT09IHZlcnNpb247XG4gICAgICAgICAgICB9XG4gICAgICAgIH0sIHsgXCIuL3ZlcnNpb25cIjogMzAgfV0sIDI4OiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge1xuICAgICAgICAgICAgdmFyIHZlcnNpb24gPSByZXF1aXJlKFwiLi92ZXJzaW9uXCIpO1xuXG4gICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IGlzVmlydHVhbFRleHQ7XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIGlzVmlydHVhbFRleHQoeCkge1xuICAgICAgICAgICAgICAgIHJldHVybiB4ICYmIHgudHlwZSA9PT0gXCJWaXJ0dWFsVGV4dFwiICYmIHgudmVyc2lvbiA9PT0gdmVyc2lvbjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSwgeyBcIi4vdmVyc2lvblwiOiAzMCB9XSwgMjk6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IGlzV2lkZ2V0O1xuXG4gICAgICAgICAgICBmdW5jdGlvbiBpc1dpZGdldCh3KSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHcgJiYgdy50eXBlID09PSBcIldpZGdldFwiO1xuICAgICAgICAgICAgfVxuICAgICAgICB9LCB7fV0sIDMwOiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge1xuICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBcIjJcIjtcbiAgICAgICAgfSwge31dLCAzMTogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHtcbiAgICAgICAgICAgIHZhciB2ZXJzaW9uID0gcmVxdWlyZShcIi4vdmVyc2lvblwiKTtcbiAgICAgICAgICAgIHZhciBpc1ZOb2RlID0gcmVxdWlyZShcIi4vaXMtdm5vZGVcIik7XG4gICAgICAgICAgICB2YXIgaXNXaWRnZXQgPSByZXF1aXJlKFwiLi9pcy13aWRnZXRcIik7XG4gICAgICAgICAgICB2YXIgaXNUaHVuayA9IHJlcXVpcmUoXCIuL2lzLXRodW5rXCIpO1xuICAgICAgICAgICAgdmFyIGlzVkhvb2sgPSByZXF1aXJlKFwiLi9pcy12aG9va1wiKTtcblxuICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBWaXJ0dWFsTm9kZTtcblxuICAgICAgICAgICAgdmFyIG5vUHJvcGVydGllcyA9IHt9O1xuICAgICAgICAgICAgdmFyIG5vQ2hpbGRyZW4gPSBbXTtcblxuICAgICAgICAgICAgZnVuY3Rpb24gVmlydHVhbE5vZGUodGFnTmFtZSwgcHJvcGVydGllcywgY2hpbGRyZW4sIGtleSwgbmFtZXNwYWNlKSB7XG4gICAgICAgICAgICAgICAgdGhpcy50YWdOYW1lID0gdGFnTmFtZTtcbiAgICAgICAgICAgICAgICB0aGlzLnByb3BlcnRpZXMgPSBwcm9wZXJ0aWVzIHx8IG5vUHJvcGVydGllcztcbiAgICAgICAgICAgICAgICB0aGlzLmNoaWxkcmVuID0gY2hpbGRyZW4gfHwgbm9DaGlsZHJlbjtcbiAgICAgICAgICAgICAgICB0aGlzLmtleSA9IGtleSAhPSBudWxsID8gU3RyaW5nKGtleSkgOiB1bmRlZmluZWQ7XG4gICAgICAgICAgICAgICAgdGhpcy5uYW1lc3BhY2UgPSB0eXBlb2YgbmFtZXNwYWNlID09PSBcInN0cmluZ1wiID8gbmFtZXNwYWNlIDogbnVsbDtcblxuICAgICAgICAgICAgICAgIHZhciBjb3VudCA9IGNoaWxkcmVuICYmIGNoaWxkcmVuLmxlbmd0aCB8fCAwO1xuICAgICAgICAgICAgICAgIHZhciBkZXNjZW5kYW50cyA9IDA7XG4gICAgICAgICAgICAgICAgdmFyIGhhc1dpZGdldHMgPSBmYWxzZTtcbiAgICAgICAgICAgICAgICB2YXIgaGFzVGh1bmtzID0gZmFsc2U7XG4gICAgICAgICAgICAgICAgdmFyIGRlc2NlbmRhbnRIb29rcyA9IGZhbHNlO1xuICAgICAgICAgICAgICAgIHZhciBob29rcztcblxuICAgICAgICAgICAgICAgIGZvciAodmFyIHByb3BOYW1lIGluIHByb3BlcnRpZXMpIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKHByb3BlcnRpZXMuaGFzT3duUHJvcGVydHkocHJvcE5hbWUpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICB2YXIgcHJvcGVydHkgPSBwcm9wZXJ0aWVzW3Byb3BOYW1lXTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChpc1ZIb29rKHByb3BlcnR5KSAmJiBwcm9wZXJ0eS51bmhvb2spIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoIWhvb2tzKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGhvb2tzID0ge307XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaG9va3NbcHJvcE5hbWVdID0gcHJvcGVydHk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IGNvdW50OyBpKyspIHtcbiAgICAgICAgICAgICAgICAgICAgdmFyIGNoaWxkID0gY2hpbGRyZW5baV07XG4gICAgICAgICAgICAgICAgICAgIGlmIChpc1ZOb2RlKGNoaWxkKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgZGVzY2VuZGFudHMgKz0gY2hpbGQuY291bnQgfHwgMDtcblxuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKCFoYXNXaWRnZXRzICYmIGNoaWxkLmhhc1dpZGdldHMpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBoYXNXaWRnZXRzID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKCFoYXNUaHVua3MgJiYgY2hpbGQuaGFzVGh1bmtzKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaGFzVGh1bmtzID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKCFkZXNjZW5kYW50SG9va3MgJiYgKGNoaWxkLmhvb2tzIHx8IGNoaWxkLmRlc2NlbmRhbnRIb29rcykpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBkZXNjZW5kYW50SG9va3MgPSB0cnVlO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKCFoYXNXaWRnZXRzICYmIGlzV2lkZ2V0KGNoaWxkKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHR5cGVvZiBjaGlsZC5kZXN0cm95ID09PSBcImZ1bmN0aW9uXCIpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBoYXNXaWRnZXRzID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIGlmICghaGFzVGh1bmtzICYmIGlzVGh1bmsoY2hpbGQpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBoYXNUaHVua3MgPSB0cnVlO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgdGhpcy5jb3VudCA9IGNvdW50ICsgZGVzY2VuZGFudHM7XG4gICAgICAgICAgICAgICAgdGhpcy5oYXNXaWRnZXRzID0gaGFzV2lkZ2V0cztcbiAgICAgICAgICAgICAgICB0aGlzLmhhc1RodW5rcyA9IGhhc1RodW5rcztcbiAgICAgICAgICAgICAgICB0aGlzLmhvb2tzID0gaG9va3M7XG4gICAgICAgICAgICAgICAgdGhpcy5kZXNjZW5kYW50SG9va3MgPSBkZXNjZW5kYW50SG9va3M7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIFZpcnR1YWxOb2RlLnByb3RvdHlwZS52ZXJzaW9uID0gdmVyc2lvbjtcbiAgICAgICAgICAgIFZpcnR1YWxOb2RlLnByb3RvdHlwZS50eXBlID0gXCJWaXJ0dWFsTm9kZVwiO1xuICAgICAgICB9LCB7IFwiLi9pcy10aHVua1wiOiAyNSwgXCIuL2lzLXZob29rXCI6IDI2LCBcIi4vaXMtdm5vZGVcIjogMjcsIFwiLi9pcy13aWRnZXRcIjogMjksIFwiLi92ZXJzaW9uXCI6IDMwIH1dLCAzMjogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHtcbiAgICAgICAgICAgIHZhciB2ZXJzaW9uID0gcmVxdWlyZShcIi4vdmVyc2lvblwiKTtcblxuICAgICAgICAgICAgVmlydHVhbFBhdGNoLk5PTkUgPSAwO1xuICAgICAgICAgICAgVmlydHVhbFBhdGNoLlZURVhUID0gMTtcbiAgICAgICAgICAgIFZpcnR1YWxQYXRjaC5WTk9ERSA9IDI7XG4gICAgICAgICAgICBWaXJ0dWFsUGF0Y2guV0lER0VUID0gMztcbiAgICAgICAgICAgIFZpcnR1YWxQYXRjaC5QUk9QUyA9IDQ7XG4gICAgICAgICAgICBWaXJ0dWFsUGF0Y2guT1JERVIgPSA1O1xuICAgICAgICAgICAgVmlydHVhbFBhdGNoLklOU0VSVCA9IDY7XG4gICAgICAgICAgICBWaXJ0dWFsUGF0Y2guUkVNT1ZFID0gNztcbiAgICAgICAgICAgIFZpcnR1YWxQYXRjaC5USFVOSyA9IDg7XG5cbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gVmlydHVhbFBhdGNoO1xuXG4gICAgICAgICAgICBmdW5jdGlvbiBWaXJ0dWFsUGF0Y2godHlwZSwgdk5vZGUsIHBhdGNoKSB7XG4gICAgICAgICAgICAgICAgdGhpcy50eXBlID0gTnVtYmVyKHR5cGUpO1xuICAgICAgICAgICAgICAgIHRoaXMudk5vZGUgPSB2Tm9kZTtcbiAgICAgICAgICAgICAgICB0aGlzLnBhdGNoID0gcGF0Y2g7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIFZpcnR1YWxQYXRjaC5wcm90b3R5cGUudmVyc2lvbiA9IHZlcnNpb247XG4gICAgICAgICAgICBWaXJ0dWFsUGF0Y2gucHJvdG90eXBlLnR5cGUgPSBcIlZpcnR1YWxQYXRjaFwiO1xuICAgICAgICB9LCB7IFwiLi92ZXJzaW9uXCI6IDMwIH1dLCAzMzogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHtcbiAgICAgICAgICAgIHZhciB2ZXJzaW9uID0gcmVxdWlyZShcIi4vdmVyc2lvblwiKTtcblxuICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBWaXJ0dWFsVGV4dDtcblxuICAgICAgICAgICAgZnVuY3Rpb24gVmlydHVhbFRleHQodGV4dCkge1xuICAgICAgICAgICAgICAgIHRoaXMudGV4dCA9IFN0cmluZyh0ZXh0KTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgVmlydHVhbFRleHQucHJvdG90eXBlLnZlcnNpb24gPSB2ZXJzaW9uO1xuICAgICAgICAgICAgVmlydHVhbFRleHQucHJvdG90eXBlLnR5cGUgPSBcIlZpcnR1YWxUZXh0XCI7XG4gICAgICAgIH0sIHsgXCIuL3ZlcnNpb25cIjogMzAgfV0sIDM0OiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge1xuICAgICAgICAgICAgdmFyIGlzT2JqZWN0ID0gcmVxdWlyZShcImlzLW9iamVjdFwiKTtcbiAgICAgICAgICAgIHZhciBpc0hvb2sgPSByZXF1aXJlKFwiLi4vdm5vZGUvaXMtdmhvb2tcIik7XG5cbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gZGlmZlByb3BzO1xuXG4gICAgICAgICAgICBmdW5jdGlvbiBkaWZmUHJvcHMoYSwgYikge1xuICAgICAgICAgICAgICAgIHZhciBkaWZmO1xuXG4gICAgICAgICAgICAgICAgZm9yICh2YXIgYUtleSBpbiBhKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmICghKGFLZXkgaW4gYikpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGRpZmYgPSBkaWZmIHx8IHt9O1xuICAgICAgICAgICAgICAgICAgICAgICAgZGlmZlthS2V5XSA9IHVuZGVmaW5lZDtcbiAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgIHZhciBhVmFsdWUgPSBhW2FLZXldO1xuICAgICAgICAgICAgICAgICAgICB2YXIgYlZhbHVlID0gYlthS2V5XTtcblxuICAgICAgICAgICAgICAgICAgICBpZiAoYVZhbHVlID09PSBiVmFsdWUpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnRpbnVlO1xuICAgICAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKGlzT2JqZWN0KGFWYWx1ZSkgJiYgaXNPYmplY3QoYlZhbHVlKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGdldFByb3RvdHlwZShiVmFsdWUpICE9PSBnZXRQcm90b3R5cGUoYVZhbHVlKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRpZmYgPSBkaWZmIHx8IHt9O1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRpZmZbYUtleV0gPSBiVmFsdWU7XG4gICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKGlzSG9vayhiVmFsdWUpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgZGlmZiA9IGRpZmYgfHwge307XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgZGlmZlthS2V5XSA9IGJWYWx1ZTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdmFyIG9iamVjdERpZmYgPSBkaWZmUHJvcHMoYVZhbHVlLCBiVmFsdWUpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChvYmplY3REaWZmKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRpZmYgPSBkaWZmIHx8IHt9O1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBkaWZmW2FLZXldID0gb2JqZWN0RGlmZjtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBkaWZmID0gZGlmZiB8fCB7fTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGRpZmZbYUtleV0gPSBiVmFsdWU7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICBmb3IgKHZhciBiS2V5IGluIGIpIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKCEoYktleSBpbiBhKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgZGlmZiA9IGRpZmYgfHwge307XG4gICAgICAgICAgICAgICAgICAgICAgICBkaWZmW2JLZXldID0gYltiS2V5XTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHJldHVybiBkaWZmO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBmdW5jdGlvbiBnZXRQcm90b3R5cGUodmFsdWUpIHtcbiAgICAgICAgICAgICAgICBpZiAoT2JqZWN0LmdldFByb3RvdHlwZU9mKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBPYmplY3QuZ2V0UHJvdG90eXBlT2YodmFsdWUpO1xuICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAodmFsdWUuX19wcm90b19fKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiB2YWx1ZS5fX3Byb3RvX187XG4gICAgICAgICAgICAgICAgfSBlbHNlIGlmICh2YWx1ZS5jb25zdHJ1Y3Rvcikge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gdmFsdWUuY29uc3RydWN0b3IucHJvdG90eXBlO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgfSwgeyBcIi4uL3Zub2RlL2lzLXZob29rXCI6IDI2LCBcImlzLW9iamVjdFwiOiAxMSB9XSwgMzU6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICB2YXIgaXNBcnJheSA9IHJlcXVpcmUoXCJ4LWlzLWFycmF5XCIpO1xuXG4gICAgICAgICAgICB2YXIgVlBhdGNoID0gcmVxdWlyZShcIi4uL3Zub2RlL3ZwYXRjaFwiKTtcbiAgICAgICAgICAgIHZhciBpc1ZOb2RlID0gcmVxdWlyZShcIi4uL3Zub2RlL2lzLXZub2RlXCIpO1xuICAgICAgICAgICAgdmFyIGlzVlRleHQgPSByZXF1aXJlKFwiLi4vdm5vZGUvaXMtdnRleHRcIik7XG4gICAgICAgICAgICB2YXIgaXNXaWRnZXQgPSByZXF1aXJlKFwiLi4vdm5vZGUvaXMtd2lkZ2V0XCIpO1xuICAgICAgICAgICAgdmFyIGlzVGh1bmsgPSByZXF1aXJlKFwiLi4vdm5vZGUvaXMtdGh1bmtcIik7XG4gICAgICAgICAgICB2YXIgaGFuZGxlVGh1bmsgPSByZXF1aXJlKFwiLi4vdm5vZGUvaGFuZGxlLXRodW5rXCIpO1xuXG4gICAgICAgICAgICB2YXIgZGlmZlByb3BzID0gcmVxdWlyZShcIi4vZGlmZi1wcm9wc1wiKTtcblxuICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBkaWZmO1xuXG4gICAgICAgICAgICBmdW5jdGlvbiBkaWZmKGEsIGIpIHtcbiAgICAgICAgICAgICAgICB2YXIgcGF0Y2ggPSB7IGE6IGEgfTtcbiAgICAgICAgICAgICAgICB3YWxrKGEsIGIsIHBhdGNoLCAwKTtcbiAgICAgICAgICAgICAgICByZXR1cm4gcGF0Y2g7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIHdhbGsoYSwgYiwgcGF0Y2gsIGluZGV4KSB7XG4gICAgICAgICAgICAgICAgaWYgKGEgPT09IGIpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHZhciBhcHBseSA9IHBhdGNoW2luZGV4XTtcbiAgICAgICAgICAgICAgICB2YXIgYXBwbHlDbGVhciA9IGZhbHNlO1xuXG4gICAgICAgICAgICAgICAgaWYgKGlzVGh1bmsoYSkgfHwgaXNUaHVuayhiKSkge1xuICAgICAgICAgICAgICAgICAgICB0aHVua3MoYSwgYiwgcGF0Y2gsIGluZGV4KTtcbiAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKGIgPT0gbnVsbCkge1xuXG4gICAgICAgICAgICAgICAgICAgIC8vIElmIGEgaXMgYSB3aWRnZXQgd2Ugd2lsbCBhZGQgYSByZW1vdmUgcGF0Y2ggZm9yIGl0XG4gICAgICAgICAgICAgICAgICAgIC8vIE90aGVyd2lzZSBhbnkgY2hpbGQgd2lkZ2V0cy9ob29rcyBtdXN0IGJlIGRlc3Ryb3llZC5cbiAgICAgICAgICAgICAgICAgICAgLy8gVGhpcyBwcmV2ZW50cyBhZGRpbmcgdHdvIHJlbW92ZSBwYXRjaGVzIGZvciBhIHdpZGdldC5cbiAgICAgICAgICAgICAgICAgICAgaWYgKCFpc1dpZGdldChhKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgY2xlYXJTdGF0ZShhLCBwYXRjaCwgaW5kZXgpO1xuICAgICAgICAgICAgICAgICAgICAgICAgYXBwbHkgPSBwYXRjaFtpbmRleF07XG4gICAgICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgICAgICBhcHBseSA9IGFwcGVuZFBhdGNoKGFwcGx5LCBuZXcgVlBhdGNoKFZQYXRjaC5SRU1PVkUsIGEsIGIpKTtcbiAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKGlzVk5vZGUoYikpIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKGlzVk5vZGUoYSkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChhLnRhZ05hbWUgPT09IGIudGFnTmFtZSAmJiBhLm5hbWVzcGFjZSA9PT0gYi5uYW1lc3BhY2UgJiYgYS5rZXkgPT09IGIua2V5KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdmFyIHByb3BzUGF0Y2ggPSBkaWZmUHJvcHMoYS5wcm9wZXJ0aWVzLCBiLnByb3BlcnRpZXMpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChwcm9wc1BhdGNoKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGFwcGx5ID0gYXBwZW5kUGF0Y2goYXBwbHksIG5ldyBWUGF0Y2goVlBhdGNoLlBST1BTLCBhLCBwcm9wc1BhdGNoKSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGFwcGx5ID0gZGlmZkNoaWxkcmVuKGEsIGIsIHBhdGNoLCBhcHBseSwgaW5kZXgpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBhcHBseSA9IGFwcGVuZFBhdGNoKGFwcGx5LCBuZXcgVlBhdGNoKFZQYXRjaC5WTk9ERSwgYSwgYikpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGFwcGx5Q2xlYXIgPSB0cnVlO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgYXBwbHkgPSBhcHBlbmRQYXRjaChhcHBseSwgbmV3IFZQYXRjaChWUGF0Y2guVk5PREUsIGEsIGIpKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGFwcGx5Q2xlYXIgPSB0cnVlO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfSBlbHNlIGlmIChpc1ZUZXh0KGIpKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmICghaXNWVGV4dChhKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgYXBwbHkgPSBhcHBlbmRQYXRjaChhcHBseSwgbmV3IFZQYXRjaChWUGF0Y2guVlRFWFQsIGEsIGIpKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGFwcGx5Q2xlYXIgPSB0cnVlO1xuICAgICAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKGEudGV4dCAhPT0gYi50ZXh0KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBhcHBseSA9IGFwcGVuZFBhdGNoKGFwcGx5LCBuZXcgVlBhdGNoKFZQYXRjaC5WVEVYVCwgYSwgYikpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfSBlbHNlIGlmIChpc1dpZGdldChiKSkge1xuICAgICAgICAgICAgICAgICAgICBpZiAoIWlzV2lkZ2V0KGEpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBhcHBseUNsZWFyID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgIGFwcGx5ID0gYXBwZW5kUGF0Y2goYXBwbHksIG5ldyBWUGF0Y2goVlBhdGNoLldJREdFVCwgYSwgYikpO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIGlmIChhcHBseSkge1xuICAgICAgICAgICAgICAgICAgICBwYXRjaFtpbmRleF0gPSBhcHBseTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICBpZiAoYXBwbHlDbGVhcikge1xuICAgICAgICAgICAgICAgICAgICBjbGVhclN0YXRlKGEsIHBhdGNoLCBpbmRleCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBmdW5jdGlvbiBkaWZmQ2hpbGRyZW4oYSwgYiwgcGF0Y2gsIGFwcGx5LCBpbmRleCkge1xuICAgICAgICAgICAgICAgIHZhciBhQ2hpbGRyZW4gPSBhLmNoaWxkcmVuO1xuICAgICAgICAgICAgICAgIHZhciBvcmRlcmVkU2V0ID0gcmVvcmRlcihhQ2hpbGRyZW4sIGIuY2hpbGRyZW4pO1xuICAgICAgICAgICAgICAgIHZhciBiQ2hpbGRyZW4gPSBvcmRlcmVkU2V0LmNoaWxkcmVuO1xuXG4gICAgICAgICAgICAgICAgdmFyIGFMZW4gPSBhQ2hpbGRyZW4ubGVuZ3RoO1xuICAgICAgICAgICAgICAgIHZhciBiTGVuID0gYkNoaWxkcmVuLmxlbmd0aDtcbiAgICAgICAgICAgICAgICB2YXIgbGVuID0gYUxlbiA+IGJMZW4gPyBhTGVuIDogYkxlbjtcblxuICAgICAgICAgICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgbGVuOyBpKyspIHtcbiAgICAgICAgICAgICAgICAgICAgdmFyIGxlZnROb2RlID0gYUNoaWxkcmVuW2ldO1xuICAgICAgICAgICAgICAgICAgICB2YXIgcmlnaHROb2RlID0gYkNoaWxkcmVuW2ldO1xuICAgICAgICAgICAgICAgICAgICBpbmRleCArPSAxO1xuXG4gICAgICAgICAgICAgICAgICAgIGlmICghbGVmdE5vZGUpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChyaWdodE5vZGUpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBFeGNlc3Mgbm9kZXMgaW4gYiBuZWVkIHRvIGJlIGFkZGVkXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgYXBwbHkgPSBhcHBlbmRQYXRjaChhcHBseSwgbmV3IFZQYXRjaChWUGF0Y2guSU5TRVJULCBudWxsLCByaWdodE5vZGUpKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHdhbGsobGVmdE5vZGUsIHJpZ2h0Tm9kZSwgcGF0Y2gsIGluZGV4KTtcbiAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgIGlmIChpc1ZOb2RlKGxlZnROb2RlKSAmJiBsZWZ0Tm9kZS5jb3VudCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgaW5kZXggKz0gbGVmdE5vZGUuY291bnQ7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICBpZiAob3JkZXJlZFNldC5tb3Zlcykge1xuICAgICAgICAgICAgICAgICAgICAvLyBSZW9yZGVyIG5vZGVzIGxhc3RcbiAgICAgICAgICAgICAgICAgICAgYXBwbHkgPSBhcHBlbmRQYXRjaChhcHBseSwgbmV3IFZQYXRjaChWUGF0Y2guT1JERVIsIGEsIG9yZGVyZWRTZXQubW92ZXMpKTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICByZXR1cm4gYXBwbHk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIGNsZWFyU3RhdGUodk5vZGUsIHBhdGNoLCBpbmRleCkge1xuICAgICAgICAgICAgICAgIC8vIFRPRE86IE1ha2UgdGhpcyBhIHNpbmdsZSB3YWxrLCBub3QgdHdvXG4gICAgICAgICAgICAgICAgdW5ob29rKHZOb2RlLCBwYXRjaCwgaW5kZXgpO1xuICAgICAgICAgICAgICAgIGRlc3Ryb3lXaWRnZXRzKHZOb2RlLCBwYXRjaCwgaW5kZXgpO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAvLyBQYXRjaCByZWNvcmRzIGZvciBhbGwgZGVzdHJveWVkIHdpZGdldHMgbXVzdCBiZSBhZGRlZCBiZWNhdXNlIHdlIG5lZWRcbiAgICAgICAgICAgIC8vIGEgRE9NIG5vZGUgcmVmZXJlbmNlIGZvciB0aGUgZGVzdHJveSBmdW5jdGlvblxuICAgICAgICAgICAgZnVuY3Rpb24gZGVzdHJveVdpZGdldHModk5vZGUsIHBhdGNoLCBpbmRleCkge1xuICAgICAgICAgICAgICAgIGlmIChpc1dpZGdldCh2Tm9kZSkpIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKHR5cGVvZiB2Tm9kZS5kZXN0cm95ID09PSBcImZ1bmN0aW9uXCIpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHBhdGNoW2luZGV4XSA9IGFwcGVuZFBhdGNoKHBhdGNoW2luZGV4XSwgbmV3IFZQYXRjaChWUGF0Y2guUkVNT1ZFLCB2Tm9kZSwgbnVsbCkpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfSBlbHNlIGlmIChpc1ZOb2RlKHZOb2RlKSAmJiAodk5vZGUuaGFzV2lkZ2V0cyB8fCB2Tm9kZS5oYXNUaHVua3MpKSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciBjaGlsZHJlbiA9IHZOb2RlLmNoaWxkcmVuO1xuICAgICAgICAgICAgICAgICAgICB2YXIgbGVuID0gY2hpbGRyZW4ubGVuZ3RoO1xuICAgICAgICAgICAgICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IGxlbjsgaSsrKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICB2YXIgY2hpbGQgPSBjaGlsZHJlbltpXTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGluZGV4ICs9IDE7XG5cbiAgICAgICAgICAgICAgICAgICAgICAgIGRlc3Ryb3lXaWRnZXRzKGNoaWxkLCBwYXRjaCwgaW5kZXgpO1xuXG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoaXNWTm9kZShjaGlsZCkgJiYgY2hpbGQuY291bnQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpbmRleCArPSBjaGlsZC5jb3VudDtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoaXNUaHVuayh2Tm9kZSkpIHtcbiAgICAgICAgICAgICAgICAgICAgdGh1bmtzKHZOb2RlLCBudWxsLCBwYXRjaCwgaW5kZXgpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgLy8gQ3JlYXRlIGEgc3ViLXBhdGNoIGZvciB0aHVua3NcbiAgICAgICAgICAgIGZ1bmN0aW9uIHRodW5rcyhhLCBiLCBwYXRjaCwgaW5kZXgpIHtcbiAgICAgICAgICAgICAgICB2YXIgbm9kZXMgPSBoYW5kbGVUaHVuayhhLCBiKTtcbiAgICAgICAgICAgICAgICB2YXIgdGh1bmtQYXRjaCA9IGRpZmYobm9kZXMuYSwgbm9kZXMuYik7XG4gICAgICAgICAgICAgICAgaWYgKGhhc1BhdGNoZXModGh1bmtQYXRjaCkpIHtcbiAgICAgICAgICAgICAgICAgICAgcGF0Y2hbaW5kZXhdID0gbmV3IFZQYXRjaChWUGF0Y2guVEhVTkssIG51bGwsIHRodW5rUGF0Y2gpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZnVuY3Rpb24gaGFzUGF0Y2hlcyhwYXRjaCkge1xuICAgICAgICAgICAgICAgIGZvciAodmFyIGluZGV4IGluIHBhdGNoKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmIChpbmRleCAhPT0gXCJhXCIpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAvLyBFeGVjdXRlIGhvb2tzIHdoZW4gdHdvIG5vZGVzIGFyZSBpZGVudGljYWxcbiAgICAgICAgICAgIGZ1bmN0aW9uIHVuaG9vayh2Tm9kZSwgcGF0Y2gsIGluZGV4KSB7XG4gICAgICAgICAgICAgICAgaWYgKGlzVk5vZGUodk5vZGUpKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmICh2Tm9kZS5ob29rcykge1xuICAgICAgICAgICAgICAgICAgICAgICAgcGF0Y2hbaW5kZXhdID0gYXBwZW5kUGF0Y2gocGF0Y2hbaW5kZXhdLCBuZXcgVlBhdGNoKFZQYXRjaC5QUk9QUywgdk5vZGUsIHVuZGVmaW5lZEtleXModk5vZGUuaG9va3MpKSk7XG4gICAgICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgICAgICBpZiAodk5vZGUuZGVzY2VuZGFudEhvb2tzIHx8IHZOb2RlLmhhc1RodW5rcykge1xuICAgICAgICAgICAgICAgICAgICAgICAgdmFyIGNoaWxkcmVuID0gdk5vZGUuY2hpbGRyZW47XG4gICAgICAgICAgICAgICAgICAgICAgICB2YXIgbGVuID0gY2hpbGRyZW4ubGVuZ3RoO1xuICAgICAgICAgICAgICAgICAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCBsZW47IGkrKykge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZhciBjaGlsZCA9IGNoaWxkcmVuW2ldO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGluZGV4ICs9IDE7XG5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB1bmhvb2soY2hpbGQsIHBhdGNoLCBpbmRleCk7XG5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoaXNWTm9kZShjaGlsZCkgJiYgY2hpbGQuY291bnQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaW5kZXggKz0gY2hpbGQuY291bnQ7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfSBlbHNlIGlmIChpc1RodW5rKHZOb2RlKSkge1xuICAgICAgICAgICAgICAgICAgICB0aHVua3Modk5vZGUsIG51bGwsIHBhdGNoLCBpbmRleCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBmdW5jdGlvbiB1bmRlZmluZWRLZXlzKG9iaikge1xuICAgICAgICAgICAgICAgIHZhciByZXN1bHQgPSB7fTtcblxuICAgICAgICAgICAgICAgIGZvciAodmFyIGtleSBpbiBvYmopIHtcbiAgICAgICAgICAgICAgICAgICAgcmVzdWx0W2tleV0gPSB1bmRlZmluZWQ7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgcmV0dXJuIHJlc3VsdDtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgLy8gTGlzdCBkaWZmLCBuYWl2ZSBsZWZ0IHRvIHJpZ2h0IHJlb3JkZXJpbmdcbiAgICAgICAgICAgIGZ1bmN0aW9uIHJlb3JkZXIoYUNoaWxkcmVuLCBiQ2hpbGRyZW4pIHtcbiAgICAgICAgICAgICAgICAvLyBPKE0pIHRpbWUsIE8oTSkgbWVtb3J5XG4gICAgICAgICAgICAgICAgdmFyIGJDaGlsZEluZGV4ID0ga2V5SW5kZXgoYkNoaWxkcmVuKTtcbiAgICAgICAgICAgICAgICB2YXIgYktleXMgPSBiQ2hpbGRJbmRleC5rZXlzO1xuICAgICAgICAgICAgICAgIHZhciBiRnJlZSA9IGJDaGlsZEluZGV4LmZyZWU7XG5cbiAgICAgICAgICAgICAgICBpZiAoYkZyZWUubGVuZ3RoID09PSBiQ2hpbGRyZW4ubGVuZ3RoKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiB7XG4gICAgICAgICAgICAgICAgICAgICAgICBjaGlsZHJlbjogYkNoaWxkcmVuLFxuICAgICAgICAgICAgICAgICAgICAgICAgbW92ZXM6IG51bGxcbiAgICAgICAgICAgICAgICAgICAgfTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAvLyBPKE4pIHRpbWUsIE8oTikgbWVtb3J5XG4gICAgICAgICAgICAgICAgdmFyIGFDaGlsZEluZGV4ID0ga2V5SW5kZXgoYUNoaWxkcmVuKTtcbiAgICAgICAgICAgICAgICB2YXIgYUtleXMgPSBhQ2hpbGRJbmRleC5rZXlzO1xuICAgICAgICAgICAgICAgIHZhciBhRnJlZSA9IGFDaGlsZEluZGV4LmZyZWU7XG5cbiAgICAgICAgICAgICAgICBpZiAoYUZyZWUubGVuZ3RoID09PSBhQ2hpbGRyZW4ubGVuZ3RoKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiB7XG4gICAgICAgICAgICAgICAgICAgICAgICBjaGlsZHJlbjogYkNoaWxkcmVuLFxuICAgICAgICAgICAgICAgICAgICAgICAgbW92ZXM6IG51bGxcbiAgICAgICAgICAgICAgICAgICAgfTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAvLyBPKE1BWChOLCBNKSkgbWVtb3J5XG4gICAgICAgICAgICAgICAgdmFyIG5ld0NoaWxkcmVuID0gW107XG5cbiAgICAgICAgICAgICAgICB2YXIgZnJlZUluZGV4ID0gMDtcbiAgICAgICAgICAgICAgICB2YXIgZnJlZUNvdW50ID0gYkZyZWUubGVuZ3RoO1xuICAgICAgICAgICAgICAgIHZhciBkZWxldGVkSXRlbXMgPSAwO1xuXG4gICAgICAgICAgICAgICAgLy8gSXRlcmF0ZSB0aHJvdWdoIGEgYW5kIG1hdGNoIGEgbm9kZSBpbiBiXG4gICAgICAgICAgICAgICAgLy8gTyhOKSB0aW1lLFxuICAgICAgICAgICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgYUNoaWxkcmVuLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciBhSXRlbSA9IGFDaGlsZHJlbltpXTtcbiAgICAgICAgICAgICAgICAgICAgdmFyIGl0ZW1JbmRleDtcblxuICAgICAgICAgICAgICAgICAgICBpZiAoYUl0ZW0ua2V5KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoYktleXMuaGFzT3duUHJvcGVydHkoYUl0ZW0ua2V5KSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIE1hdGNoIHVwIHRoZSBvbGQga2V5c1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGl0ZW1JbmRleCA9IGJLZXlzW2FJdGVtLmtleV07XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgbmV3Q2hpbGRyZW4ucHVzaChiQ2hpbGRyZW5baXRlbUluZGV4XSk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIFJlbW92ZSBvbGQga2V5ZWQgaXRlbXNcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpdGVtSW5kZXggPSBpIC0gZGVsZXRlZEl0ZW1zKys7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgbmV3Q2hpbGRyZW4ucHVzaChudWxsKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIE1hdGNoIHRoZSBpdGVtIGluIGEgd2l0aCB0aGUgbmV4dCBmcmVlIGl0ZW0gaW4gYlxuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGZyZWVJbmRleCA8IGZyZWVDb3VudCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGl0ZW1JbmRleCA9IGJGcmVlW2ZyZWVJbmRleCsrXTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBuZXdDaGlsZHJlbi5wdXNoKGJDaGlsZHJlbltpdGVtSW5kZXhdKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gVGhlcmUgYXJlIG5vIGZyZWUgaXRlbXMgaW4gYiB0byBtYXRjaCB3aXRoXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gdGhlIGZyZWUgaXRlbXMgaW4gYSwgc28gdGhlIGV4dHJhIGZyZWUgbm9kZXNcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBhcmUgZGVsZXRlZC5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpdGVtSW5kZXggPSBpIC0gZGVsZXRlZEl0ZW1zKys7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgbmV3Q2hpbGRyZW4ucHVzaChudWxsKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHZhciBsYXN0RnJlZUluZGV4ID0gZnJlZUluZGV4ID49IGJGcmVlLmxlbmd0aCA/IGJDaGlsZHJlbi5sZW5ndGggOiBiRnJlZVtmcmVlSW5kZXhdO1xuXG4gICAgICAgICAgICAgICAgLy8gSXRlcmF0ZSB0aHJvdWdoIGIgYW5kIGFwcGVuZCBhbnkgbmV3IGtleXNcbiAgICAgICAgICAgICAgICAvLyBPKE0pIHRpbWVcbiAgICAgICAgICAgICAgICBmb3IgKHZhciBqID0gMDsgaiA8IGJDaGlsZHJlbi5sZW5ndGg7IGorKykge1xuICAgICAgICAgICAgICAgICAgICB2YXIgbmV3SXRlbSA9IGJDaGlsZHJlbltqXTtcblxuICAgICAgICAgICAgICAgICAgICBpZiAobmV3SXRlbS5rZXkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmICghYUtleXMuaGFzT3duUHJvcGVydHkobmV3SXRlbS5rZXkpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gQWRkIGFueSBuZXcga2V5ZWQgaXRlbXNcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBXZSBhcmUgYWRkaW5nIG5ldyBpdGVtcyB0byB0aGUgZW5kIGFuZCB0aGVuIHNvcnRpbmcgdGhlbVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIGluIHBsYWNlLiBJbiBmdXR1cmUgd2Ugc2hvdWxkIGluc2VydCBuZXcgaXRlbXMgaW4gcGxhY2UuXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgbmV3Q2hpbGRyZW4ucHVzaChuZXdJdGVtKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIGlmIChqID49IGxhc3RGcmVlSW5kZXgpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIEFkZCBhbnkgbGVmdG92ZXIgbm9uLWtleWVkIGl0ZW1zXG4gICAgICAgICAgICAgICAgICAgICAgICBuZXdDaGlsZHJlbi5wdXNoKG5ld0l0ZW0pO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgdmFyIHNpbXVsYXRlID0gbmV3Q2hpbGRyZW4uc2xpY2UoKTtcbiAgICAgICAgICAgICAgICB2YXIgc2ltdWxhdGVJbmRleCA9IDA7XG4gICAgICAgICAgICAgICAgdmFyIHJlbW92ZXMgPSBbXTtcbiAgICAgICAgICAgICAgICB2YXIgaW5zZXJ0cyA9IFtdO1xuICAgICAgICAgICAgICAgIHZhciBzaW11bGF0ZUl0ZW07XG5cbiAgICAgICAgICAgICAgICBmb3IgKHZhciBrID0gMDsgayA8IGJDaGlsZHJlbi5sZW5ndGg7KSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciB3YW50ZWRJdGVtID0gYkNoaWxkcmVuW2tdO1xuICAgICAgICAgICAgICAgICAgICBzaW11bGF0ZUl0ZW0gPSBzaW11bGF0ZVtzaW11bGF0ZUluZGV4XTtcblxuICAgICAgICAgICAgICAgICAgICAvLyByZW1vdmUgaXRlbXNcbiAgICAgICAgICAgICAgICAgICAgd2hpbGUgKHNpbXVsYXRlSXRlbSA9PT0gbnVsbCAmJiBzaW11bGF0ZS5sZW5ndGgpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJlbW92ZXMucHVzaChyZW1vdmUoc2ltdWxhdGUsIHNpbXVsYXRlSW5kZXgsIG51bGwpKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIHNpbXVsYXRlSXRlbSA9IHNpbXVsYXRlW3NpbXVsYXRlSW5kZXhdO1xuICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgaWYgKCFzaW11bGF0ZUl0ZW0gfHwgc2ltdWxhdGVJdGVtLmtleSAhPT0gd2FudGVkSXRlbS5rZXkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIGlmIHdlIG5lZWQgYSBrZXkgaW4gdGhpcyBwb3NpdGlvbi4uLlxuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHdhbnRlZEl0ZW0ua2V5KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHNpbXVsYXRlSXRlbSAmJiBzaW11bGF0ZUl0ZW0ua2V5KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIGlmIGFuIGluc2VydCBkb2Vzbid0IHB1dCB0aGlzIGtleSBpbiBwbGFjZSwgaXQgbmVlZHMgdG8gbW92ZVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoYktleXNbc2ltdWxhdGVJdGVtLmtleV0gIT09IGsgKyAxKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICByZW1vdmVzLnB1c2gocmVtb3ZlKHNpbXVsYXRlLCBzaW11bGF0ZUluZGV4LCBzaW11bGF0ZUl0ZW0ua2V5KSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzaW11bGF0ZUl0ZW0gPSBzaW11bGF0ZVtzaW11bGF0ZUluZGV4XTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIGlmIHRoZSByZW1vdmUgZGlkbid0IHB1dCB0aGUgd2FudGVkIGl0ZW0gaW4gcGxhY2UsIHdlIG5lZWQgdG8gaW5zZXJ0IGl0XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoIXNpbXVsYXRlSXRlbSB8fCBzaW11bGF0ZUl0ZW0ua2V5ICE9PSB3YW50ZWRJdGVtLmtleSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGluc2VydHMucHVzaCh7IGtleTogd2FudGVkSXRlbS5rZXksIHRvOiBrIH0pO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gaXRlbXMgYXJlIG1hdGNoaW5nLCBzbyBza2lwIGFoZWFkXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzaW11bGF0ZUluZGV4Kys7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpbnNlcnRzLnB1c2goeyBrZXk6IHdhbnRlZEl0ZW0ua2V5LCB0bzogayB9KTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGluc2VydHMucHVzaCh7IGtleTogd2FudGVkSXRlbS5rZXksIHRvOiBrIH0pO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBrKys7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAvLyBhIGtleSBpbiBzaW11bGF0ZSBoYXMgbm8gbWF0Y2hpbmcgd2FudGVkIGtleSwgcmVtb3ZlIGl0XG4gICAgICAgICAgICAgICAgICAgICAgICBlbHNlIGlmIChzaW11bGF0ZUl0ZW0gJiYgc2ltdWxhdGVJdGVtLmtleSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlbW92ZXMucHVzaChyZW1vdmUoc2ltdWxhdGUsIHNpbXVsYXRlSW5kZXgsIHNpbXVsYXRlSXRlbS5rZXkpKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHNpbXVsYXRlSW5kZXgrKztcbiAgICAgICAgICAgICAgICAgICAgICAgIGsrKztcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIC8vIHJlbW92ZSBhbGwgdGhlIHJlbWFpbmluZyBub2RlcyBmcm9tIHNpbXVsYXRlXG4gICAgICAgICAgICAgICAgd2hpbGUgKHNpbXVsYXRlSW5kZXggPCBzaW11bGF0ZS5sZW5ndGgpIHtcbiAgICAgICAgICAgICAgICAgICAgc2ltdWxhdGVJdGVtID0gc2ltdWxhdGVbc2ltdWxhdGVJbmRleF07XG4gICAgICAgICAgICAgICAgICAgIHJlbW92ZXMucHVzaChyZW1vdmUoc2ltdWxhdGUsIHNpbXVsYXRlSW5kZXgsIHNpbXVsYXRlSXRlbSAmJiBzaW11bGF0ZUl0ZW0ua2V5KSk7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgLy8gSWYgdGhlIG9ubHkgbW92ZXMgd2UgaGF2ZSBhcmUgZGVsZXRlcyB0aGVuIHdlIGNhbiBqdXN0XG4gICAgICAgICAgICAgICAgLy8gbGV0IHRoZSBkZWxldGUgcGF0Y2ggcmVtb3ZlIHRoZXNlIGl0ZW1zLlxuICAgICAgICAgICAgICAgIGlmIChyZW1vdmVzLmxlbmd0aCA9PT0gZGVsZXRlZEl0ZW1zICYmICFpbnNlcnRzLmxlbmd0aCkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgICAgICAgICAgICAgY2hpbGRyZW46IG5ld0NoaWxkcmVuLFxuICAgICAgICAgICAgICAgICAgICAgICAgbW92ZXM6IG51bGxcbiAgICAgICAgICAgICAgICAgICAgfTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgICAgICAgICBjaGlsZHJlbjogbmV3Q2hpbGRyZW4sXG4gICAgICAgICAgICAgICAgICAgIG1vdmVzOiB7XG4gICAgICAgICAgICAgICAgICAgICAgICByZW1vdmVzOiByZW1vdmVzLFxuICAgICAgICAgICAgICAgICAgICAgICAgaW5zZXJ0czogaW5zZXJ0c1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZnVuY3Rpb24gcmVtb3ZlKGFyciwgaW5kZXgsIGtleSkge1xuICAgICAgICAgICAgICAgIGFyci5zcGxpY2UoaW5kZXgsIDEpO1xuXG4gICAgICAgICAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgICAgICAgICAgZnJvbTogaW5kZXgsXG4gICAgICAgICAgICAgICAgICAgIGtleToga2V5XG4gICAgICAgICAgICAgICAgfTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZnVuY3Rpb24ga2V5SW5kZXgoY2hpbGRyZW4pIHtcbiAgICAgICAgICAgICAgICB2YXIga2V5cyA9IHt9O1xuICAgICAgICAgICAgICAgIHZhciBmcmVlID0gW107XG4gICAgICAgICAgICAgICAgdmFyIGxlbmd0aCA9IGNoaWxkcmVuLmxlbmd0aDtcblxuICAgICAgICAgICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgbGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgICAgICAgICAgdmFyIGNoaWxkID0gY2hpbGRyZW5baV07XG5cbiAgICAgICAgICAgICAgICAgICAgaWYgKGNoaWxkLmtleSkge1xuICAgICAgICAgICAgICAgICAgICAgICAga2V5c1tjaGlsZC5rZXldID0gaTtcbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGZyZWUucHVzaChpKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHJldHVybiB7XG4gICAgICAgICAgICAgICAgICAgIGtleXM6IGtleXMsIC8vIEEgaGFzaCBvZiBrZXkgbmFtZSB0byBpbmRleFxuICAgICAgICAgICAgICAgICAgICBmcmVlOiBmcmVlIC8vIEFuIGFycmF5IG9mIHVua2V5ZWQgaXRlbSBpbmRpY2VzXG4gICAgICAgICAgICAgICAgfTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZnVuY3Rpb24gYXBwZW5kUGF0Y2goYXBwbHksIHBhdGNoKSB7XG4gICAgICAgICAgICAgICAgaWYgKGFwcGx5KSB7XG4gICAgICAgICAgICAgICAgICAgIGlmIChpc0FycmF5KGFwcGx5KSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgYXBwbHkucHVzaChwYXRjaCk7XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBhcHBseSA9IFthcHBseSwgcGF0Y2hdO1xuICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGFwcGx5O1xuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBwYXRjaDtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH0sIHsgXCIuLi92bm9kZS9oYW5kbGUtdGh1bmtcIjogMjQsIFwiLi4vdm5vZGUvaXMtdGh1bmtcIjogMjUsIFwiLi4vdm5vZGUvaXMtdm5vZGVcIjogMjcsIFwiLi4vdm5vZGUvaXMtdnRleHRcIjogMjgsIFwiLi4vdm5vZGUvaXMtd2lkZ2V0XCI6IDI5LCBcIi4uL3Zub2RlL3ZwYXRjaFwiOiAzMiwgXCIuL2RpZmYtcHJvcHNcIjogMzQsIFwieC1pcy1hcnJheVwiOiAxMiB9XSB9LCB7fSwgWzRdKSg0KTtcbn0pO1xuXG5cbi8vIFByb3Bvc2VkIGZvciBFUzZcblxuY29uc3Qgc3RhcnQgPSBmdW5jdGlvbiAoZG9tUm9vdCwgcmVuZGVyRm4sIGluaXRpYWxTdGF0ZSwgb3B0aW9ucyA9IFtdKSB7XG4gIGNvbnN0IG5hbWUgPSBLZXl3b3JkLmhhc19rZXlfX3FtX18ob3B0aW9ucywgS2VybmVsLlNwZWNpYWxGb3Jtcy5hdG9tKCduYW1lJykpID8gS2V5d29yZC5nZXQob3B0aW9ucywgS2VybmVsLlNwZWNpYWxGb3Jtcy5hdG9tKCduYW1lJykpIDogU3ltYm9sKCk7XG5cbiAgc2VsZi5wb3N0X29mZmljZS5hZGRfbWFpbGJveChuYW1lKTtcblxuICBjb25zdCB0cmVlID0gcmVuZGVyRm4uYXBwbHkodGhpcywgaW5pdGlhbFN0YXRlKTtcbiAgY29uc3Qgcm9vdE5vZGUgPSB2aXJ0dWFsRG9tLmNyZWF0ZSh0cmVlKTtcblxuICBkb21Sb290LmFwcGVuZENoaWxkKHJvb3ROb2RlKTtcbiAgc2VsZi5wb3N0X29mZmljZS5zZW5kKG5hbWUsIEtlcm5lbC5TcGVjaWFsRm9ybXMudHVwbGUocm9vdE5vZGUsIHRyZWUsIHJlbmRlckZuKSk7XG5cbiAgcmV0dXJuIEtlcm5lbC5TcGVjaWFsRm9ybXMudHVwbGUoS2VybmVsLlNwZWNpYWxGb3Jtcy5hdG9tKCdvaycpLCBuYW1lKTtcbn07XG5cbmNvbnN0IHN0b3AgPSBmdW5jdGlvbiAoYWdlbnQsIHRpbWVvdXQgPSA1MDAwKSB7XG4gIHNlbGYucG9zdF9vZmZpY2UucmVtb3ZlX21haWxib3goYWdlbnQpO1xuICByZXR1cm4gS2VybmVsLlNwZWNpYWxGb3Jtcy5hdG9tKCdvaycpO1xufTtcblxuY29uc3QgcmVuZGVyID0gZnVuY3Rpb24gKGFnZW50LCBzdGF0ZSkge1xuXG4gIGNvbnN0IGN1cnJlbnRfc3RhdGUgPSBzZWxmLnBvc3Rfb2ZmaWNlLnJlY2VpdmUoYWdlbnQpO1xuXG4gIGxldCByb290Tm9kZSA9IEtlcm5lbC5lbGVtKGN1cnJlbnRfc3RhdGUsIDApO1xuICBsZXQgdHJlZSA9IEtlcm5lbC5lbGVtKGN1cnJlbnRfc3RhdGUsIDEpO1xuICBsZXQgcmVuZGVyRm4gPSBLZXJuZWwuZWxlbShjdXJyZW50X3N0YXRlLCAyKTtcblxuICBsZXQgbmV3VHJlZSA9IHJlbmRlckZuLmFwcGx5KHRoaXMsIHN0YXRlKTtcblxuICBsZXQgcGF0Y2hlcyA9IHZpcnR1YWxEb20uZGlmZih0cmVlLCBuZXdUcmVlKTtcbiAgcm9vdE5vZGUgPSB2aXJ0dWFsRG9tLnBhdGNoKHJvb3ROb2RlLCBwYXRjaGVzKTtcblxuICBzZWxmLnBvc3Rfb2ZmaWNlLnNlbmQoYWdlbnQsIEtlcm5lbC5TcGVjaWFsRm9ybXMudHVwbGUocm9vdE5vZGUsIG5ld1RyZWUsIHJlbmRlckZuKSk7XG5cbiAgcmV0dXJuIEtlcm5lbC5TcGVjaWFsRm9ybXMuYXRvbSgnb2snKTtcbn07XG5cbnZhciBWaWV3ID0ge1xuICBzdGFydCxcbiAgc3RvcCxcbiAgcmVuZGVyXG59O1xuXG5zZWxmLnBvc3Rfb2ZmaWNlID0gc2VsZi5wb3N0X29mZmljZSB8fCBuZXcgUG9zdE9mZmljZSgpO1xuXG5leHBvcnQgeyBfUGF0dGVybnMgYXMgUGF0dGVybnMsIEJpdFN0cmluZywgS2VybmVsLCBBdG9tLCBFbnVtLCBJbnRlZ2VyLCBKUywgTGlzdCwgUmFuZ2UsIFR1cGxlLCBBZ2VudCwgS2V5d29yZCwgQmFzZSwgX1N0cmluZyBhcyBTdHJpbmcsIEJpdHdpc2UsIEVudW1lcmFibGUsIENvbGxlY3RhYmxlLCBJbnNwZWN0LCBfTWFwIGFzIE1hcCwgX1NldCBhcyBTZXQsIE1hcFNldCwgSW50ZWdlclR5cGUsIEZsb2F0VHlwZSwgdmlydHVhbERvbSBhcyBWaXJ0dWFsRE9NLCBWaWV3IH07Il0sImZpbGUiOiJlbGl4aXIuanMiLCJzb3VyY2VSb290IjoiL3NvdXJjZS8ifQ== \ No newline at end of file diff --git a/src/javascript/lib/patterns/patterns/checks.js b/src/javascript/lib/patterns/patterns/checks.js index 50e67f33..1840e5c4 100644 --- a/src/javascript/lib/patterns/patterns/checks.js +++ b/src/javascript/lib/patterns/patterns/checks.js @@ -1,7 +1,6 @@ /* @flow */ import { Variable, Wildcard, HeadTail, Capture, Type, StartsWith, Bound } from "./types"; -import Tuple from '../../tuple'; function is_number(value: any): boolean { return typeof value === 'number'; @@ -11,10 +10,6 @@ function is_string(value: any): boolean{ return typeof value === 'string'; } -function is_tuple(value: any): boolean{ - return value instanceof Tuple; -} - function is_boolean(value: any): boolean { return typeof value === 'boolean'; } @@ -71,10 +66,6 @@ function is_array(value: any): boolean { return Array.isArray(value); } -function is_struct(__struct__: Symbol, value: any): boolean { - return is_object(value) && value[Symbol.for("__struct__")] === __struct__; -} - export default { is_number, is_string, @@ -91,6 +82,5 @@ export default { is_startsWith, is_bound, is_object, - is_array, - is_tuple + is_array }; diff --git a/src/javascript/lib/patterns/patterns/match.js b/src/javascript/lib/patterns/patterns/match.js index cb99bc25..f2e1c140 100644 --- a/src/javascript/lib/patterns/patterns/match.js +++ b/src/javascript/lib/patterns/patterns/match.js @@ -4,10 +4,6 @@ import Resolvers from "./resolvers"; export function buildMatch(pattern: any): Function { - if(Checks.is_tuple(pattern)){ - return Resolvers.resolveTuple(pattern); - } - if(Checks.is_variable(pattern)){ return Resolvers.resolveVariable(pattern); } @@ -69,4 +65,4 @@ export function buildMatch(pattern: any): Function { } return Resolvers.resolveNoMatch(); -} \ No newline at end of file +} diff --git a/src/javascript/lib/patterns/patterns/resolvers.js b/src/javascript/lib/patterns/patterns/resolvers.js index a42f15c4..9b0fcbd1 100644 --- a/src/javascript/lib/patterns/patterns/resolvers.js +++ b/src/javascript/lib/patterns/patterns/resolvers.js @@ -3,26 +3,6 @@ import Checks from "./checks"; import * as Types from "./types"; import { buildMatch } from "./match"; -import Tuple from '../../tuple'; - -function resolveTuple(pattern: any): Function { - let matches = []; - - for(let elem of pattern){ - matches.push(buildMatch(elem)); - } - - return function(value: any, args: Array): boolean { - if(!Checks.is_tuple(value) || value.count() != pattern.count()){ - return false; - } - - - return value.values.every(function(v, i) { - return matches[i](value.get(i), args); - }); - }; -} function resolveSymbol(pattern: any): Function { return function(value: any): boolean { @@ -195,6 +175,5 @@ export default { resolveNumber, resolveBoolean, resolveFunction, - resolveNull, - resolveTuple + resolveNull } diff --git a/src/javascript/lib/view.js b/src/javascript/lib/view.js index 9c864863..109001c9 100644 --- a/src/javascript/lib/view.js +++ b/src/javascript/lib/view.js @@ -22,8 +22,7 @@ const stop = function(agent, timeout = 5000){ return Kernel.SpecialForms.atom("ok"); } - -const update = function(agent, state){ +const render = function(agent, state){ const current_state = self.post_office.receive(agent); @@ -46,5 +45,5 @@ const update = function(agent, state){ export default { start, stop, - update + render } diff --git a/src/javascript/tests/patterns/defmatch.spec.js b/src/javascript/tests/patterns/defmatch.spec.js index 2b28498f..6bae9d39 100644 --- a/src/javascript/tests/patterns/defmatch.spec.js +++ b/src/javascript/tests/patterns/defmatch.spec.js @@ -111,7 +111,7 @@ describe('defmatch', () => { fn = Patterns.defmatch( Patterns.make_case( - [Patterns.capture([1, Patterns.capture({a: {b: {c: $} } }), 3, $])], + [Patterns.capture([1, Patterns.capture({a: {b: {c: $} } }), 3, $])], (c, two, four, arg) => two["a"]["b"]["c"] ) ); @@ -123,7 +123,7 @@ describe('defmatch', () => { let fn = Patterns.defmatch( Patterns.make_case( - [Patterns.headTail()], + [Patterns.headTail()], (head, tail) => tail ) ); @@ -135,7 +135,7 @@ describe('defmatch', () => { let fn = Patterns.defmatch( Patterns.make_case( - [new Tuple(1, 2, 3)], + [Patterns.type(Tuple, {values: [1, 2, 3]})], () => 3 ) ); @@ -146,4 +146,4 @@ describe('defmatch', () => { -}); \ No newline at end of file +}); From d653a9043799baead77d3371e4e05d5b91e2756c Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Sat, 28 Nov 2015 10:53:58 -0600 Subject: [PATCH 066/860] updated elixir.js output --- priv/elixir.js | 210 +++++++++++++++++++++---------------------------- 1 file changed, 91 insertions(+), 119 deletions(-) diff --git a/priv/elixir.js b/priv/elixir.js index 19478875..a24ece74 100644 --- a/priv/elixir.js +++ b/priv/elixir.js @@ -2,94 +2,6 @@ var Patterns = { get default () { return _Patterns; } }; -class Tuple { - - constructor(...args) { - this.values = Object.freeze(args); - } - - get(index) { - return this.values[index]; - } - - count() { - return this.values.length; - } - - [Symbol.iterator]() { - return this.values[Symbol.iterator](); - } - - toString() { - var i, - s = ""; - for (i = 0; i < this.values.length; i++) { - if (s !== "") { - s += ", "; - } - s += this.values[i].toString(); - } - - return "{" + s + "}"; - } - - static to_string(tuple) { - return tuple.toString(); - } - - static delete_at(tuple, index) { - let new_list = []; - - for (var i = 0; i < tuple.count(); i++) { - if (i !== index) { - new_list.push(tuple.get(i)); - } - } - - return Kernel.SpecialForms.tuple.apply(null, new_list); - } - - static duplicate(data, size) { - let array = []; - - for (var i = size - 1; i >= 0; i--) { - array.push(data); - } - - return Kernel.SpecialForms.tuple.apply(null, array); - } - - static insert_at(tuple, index, term) { - let new_tuple = []; - - for (var i = 0; i <= tuple.count(); i++) { - if (i === index) { - new_tuple.push(term); - i++; - new_tuple.push(tuple.get(i)); - } else { - new_tuple.push(tuple.get(i)); - } - } - - return Kernel.SpecialForms.tuple.apply(null, new_tuple); - } - - static from_list(list) { - return Kernel.SpecialForms.tuple.apply(null, list); - } - - static to_list(tuple) { - let new_list = []; - - for (var i = 0; i < tuple.count(); i++) { - new_list.push(tuple.get(i)); - } - - return Kernel.SpecialForms.list(...new_list); - } -} - /* @flow */ class Variable { @@ -172,10 +84,6 @@ function is_string(value) { return typeof value === 'string'; } -function _is_tuple(value) { - return value instanceof Tuple; -} - function _is_boolean(value) { return typeof value === 'boolean'; } @@ -248,28 +156,9 @@ var Checks = { is_startsWith, is_bound, is_object, - is_array, - is_tuple: _is_tuple + is_array }; -function resolveTuple(pattern) { - let matches = []; - - for (let elem of pattern) { - matches.push(buildMatch(elem)); - } - - return function (value, args) { - if (!Checks.is_tuple(value) || value.count() != pattern.count()) { - return false; - } - - return value.values.every(function (v, i) { - return matches[i](value.get(i), args); - }); - }; -} - function resolveSymbol(pattern) { return function (value) { return Checks.is_symbol(value) && value === pattern; @@ -441,16 +330,11 @@ var Resolvers = { resolveNumber, resolveBoolean, resolveFunction, - resolveNull, - resolveTuple + resolveNull }; function buildMatch(pattern) { - if (Checks.is_tuple(pattern)) { - return Resolvers.resolveTuple(pattern); - } - if (Checks.is_variable(pattern)) { return Resolvers.resolveVariable(pattern); } @@ -603,6 +487,94 @@ var _Patterns = { capture, headTail, type, bound, Case, make_case }; +class Tuple { + + constructor(...args) { + this.values = Object.freeze(args); + } + + get(index) { + return this.values[index]; + } + + count() { + return this.values.length; + } + + [Symbol.iterator]() { + return this.values[Symbol.iterator](); + } + + toString() { + var i, + s = ""; + for (i = 0; i < this.values.length; i++) { + if (s !== "") { + s += ", "; + } + s += this.values[i].toString(); + } + + return "{" + s + "}"; + } + + static to_string(tuple) { + return tuple.toString(); + } + + static delete_at(tuple, index) { + let new_list = []; + + for (var i = 0; i < tuple.count(); i++) { + if (i !== index) { + new_list.push(tuple.get(i)); + } + } + + return Kernel.SpecialForms.tuple.apply(null, new_list); + } + + static duplicate(data, size) { + let array = []; + + for (var i = size - 1; i >= 0; i--) { + array.push(data); + } + + return Kernel.SpecialForms.tuple.apply(null, array); + } + + static insert_at(tuple, index, term) { + let new_tuple = []; + + for (var i = 0; i <= tuple.count(); i++) { + if (i === index) { + new_tuple.push(term); + i++; + new_tuple.push(tuple.get(i)); + } else { + new_tuple.push(tuple.get(i)); + } + } + + return Kernel.SpecialForms.tuple.apply(null, new_tuple); + } + + static from_list(list) { + return Kernel.SpecialForms.tuple.apply(null, list); + } + + static to_list(tuple) { + let new_list = []; + + for (var i = 0; i < tuple.count(); i++) { + new_list.push(tuple.get(i)); + } + + return Kernel.SpecialForms.list(...new_list); + } +} + class BitString { constructor(...args) { this.raw_value = function () { @@ -4573,4 +4545,4 @@ var View = { self.post_office = self.post_office || new PostOffice(); export { _Patterns as Patterns, BitString, Kernel, Atom, Enum, Integer, JS, List, Range, Tuple, Agent, Keyword, Base, _String as String, Bitwise, Enumerable, Collectable, Inspect, _Map as Map, _Set as Set, MapSet, IntegerType, FloatType, virtualDom as VirtualDOM, View }; -//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiIiwic291cmNlcyI6WyJlbGl4aXIuanMiXSwic291cmNlc0NvbnRlbnQiOlsidmFyIFBhdHRlcm5zID0ge1xuICAgIGdldCBkZWZhdWx0ICgpIHsgcmV0dXJuIF9QYXR0ZXJuczsgfVxufTtcblxuY2xhc3MgVHVwbGUge1xuXG4gIGNvbnN0cnVjdG9yKC4uLmFyZ3MpIHtcbiAgICB0aGlzLnZhbHVlcyA9IE9iamVjdC5mcmVlemUoYXJncyk7XG4gIH1cblxuICBnZXQoaW5kZXgpIHtcbiAgICByZXR1cm4gdGhpcy52YWx1ZXNbaW5kZXhdO1xuICB9XG5cbiAgY291bnQoKSB7XG4gICAgcmV0dXJuIHRoaXMudmFsdWVzLmxlbmd0aDtcbiAgfVxuXG4gIFtTeW1ib2wuaXRlcmF0b3JdKCkge1xuICAgIHJldHVybiB0aGlzLnZhbHVlc1tTeW1ib2wuaXRlcmF0b3JdKCk7XG4gIH1cblxuICB0b1N0cmluZygpIHtcbiAgICB2YXIgaSxcbiAgICAgICAgcyA9IFwiXCI7XG4gICAgZm9yIChpID0gMDsgaSA8IHRoaXMudmFsdWVzLmxlbmd0aDsgaSsrKSB7XG4gICAgICBpZiAocyAhPT0gXCJcIikge1xuICAgICAgICBzICs9IFwiLCBcIjtcbiAgICAgIH1cbiAgICAgIHMgKz0gdGhpcy52YWx1ZXNbaV0udG9TdHJpbmcoKTtcbiAgICB9XG5cbiAgICByZXR1cm4gXCJ7XCIgKyBzICsgXCJ9XCI7XG4gIH1cblxuICBzdGF0aWMgdG9fc3RyaW5nKHR1cGxlKSB7XG4gICAgcmV0dXJuIHR1cGxlLnRvU3RyaW5nKCk7XG4gIH1cblxuICBzdGF0aWMgZGVsZXRlX2F0KHR1cGxlLCBpbmRleCkge1xuICAgIGxldCBuZXdfbGlzdCA9IFtdO1xuXG4gICAgZm9yICh2YXIgaSA9IDA7IGkgPCB0dXBsZS5jb3VudCgpOyBpKyspIHtcbiAgICAgIGlmIChpICE9PSBpbmRleCkge1xuICAgICAgICBuZXdfbGlzdC5wdXNoKHR1cGxlLmdldChpKSk7XG4gICAgICB9XG4gICAgfVxuXG4gICAgcmV0dXJuIEtlcm5lbC5TcGVjaWFsRm9ybXMudHVwbGUuYXBwbHkobnVsbCwgbmV3X2xpc3QpO1xuICB9XG5cbiAgc3RhdGljIGR1cGxpY2F0ZShkYXRhLCBzaXplKSB7XG4gICAgbGV0IGFycmF5ID0gW107XG5cbiAgICBmb3IgKHZhciBpID0gc2l6ZSAtIDE7IGkgPj0gMDsgaS0tKSB7XG4gICAgICBhcnJheS5wdXNoKGRhdGEpO1xuICAgIH1cblxuICAgIHJldHVybiBLZXJuZWwuU3BlY2lhbEZvcm1zLnR1cGxlLmFwcGx5KG51bGwsIGFycmF5KTtcbiAgfVxuXG4gIHN0YXRpYyBpbnNlcnRfYXQodHVwbGUsIGluZGV4LCB0ZXJtKSB7XG4gICAgbGV0IG5ld190dXBsZSA9IFtdO1xuXG4gICAgZm9yICh2YXIgaSA9IDA7IGkgPD0gdHVwbGUuY291bnQoKTsgaSsrKSB7XG4gICAgICBpZiAoaSA9PT0gaW5kZXgpIHtcbiAgICAgICAgbmV3X3R1cGxlLnB1c2godGVybSk7XG4gICAgICAgIGkrKztcbiAgICAgICAgbmV3X3R1cGxlLnB1c2godHVwbGUuZ2V0KGkpKTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIG5ld190dXBsZS5wdXNoKHR1cGxlLmdldChpKSk7XG4gICAgICB9XG4gICAgfVxuXG4gICAgcmV0dXJuIEtlcm5lbC5TcGVjaWFsRm9ybXMudHVwbGUuYXBwbHkobnVsbCwgbmV3X3R1cGxlKTtcbiAgfVxuXG4gIHN0YXRpYyBmcm9tX2xpc3QobGlzdCkge1xuICAgIHJldHVybiBLZXJuZWwuU3BlY2lhbEZvcm1zLnR1cGxlLmFwcGx5KG51bGwsIGxpc3QpO1xuICB9XG5cbiAgc3RhdGljIHRvX2xpc3QodHVwbGUpIHtcbiAgICBsZXQgbmV3X2xpc3QgPSBbXTtcblxuICAgIGZvciAodmFyIGkgPSAwOyBpIDwgdHVwbGUuY291bnQoKTsgaSsrKSB7XG4gICAgICBuZXdfbGlzdC5wdXNoKHR1cGxlLmdldChpKSk7XG4gICAgfVxuXG4gICAgcmV0dXJuIEtlcm5lbC5TcGVjaWFsRm9ybXMubGlzdCguLi5uZXdfbGlzdCk7XG4gIH1cbn1cblxuLyogQGZsb3cgKi9cblxuY2xhc3MgVmFyaWFibGUge1xuXG4gIGNvbnN0cnVjdG9yKG5hbWUgPSBudWxsKSB7XG4gICAgdGhpcy5uYW1lID0gbmFtZTtcbiAgfVxufVxuXG5jbGFzcyBXaWxkY2FyZCB7XG4gIGNvbnN0cnVjdG9yKCkge31cbn1cblxuY2xhc3MgU3RhcnRzV2l0aCB7XG5cbiAgY29uc3RydWN0b3IocHJlZml4KSB7XG4gICAgdGhpcy5wcmVmaXggPSBwcmVmaXg7XG4gIH1cbn1cblxuY2xhc3MgQ2FwdHVyZSB7XG5cbiAgY29uc3RydWN0b3IodmFsdWUpIHtcbiAgICB0aGlzLnZhbHVlID0gdmFsdWU7XG4gIH1cbn1cblxuY2xhc3MgSGVhZFRhaWwge1xuICBjb25zdHJ1Y3RvcigpIHt9XG59XG5cbmNsYXNzIFR5cGUge1xuXG4gIGNvbnN0cnVjdG9yKHR5cGUsIG9ialBhdHRlcm4gPSB7fSkge1xuICAgIHRoaXMudHlwZSA9IHR5cGU7XG4gICAgdGhpcy5vYmpQYXR0ZXJuID0gb2JqUGF0dGVybjtcbiAgfVxufVxuXG5jbGFzcyBCb3VuZCB7XG5cbiAgY29uc3RydWN0b3IodmFsdWUpIHtcbiAgICB0aGlzLnZhbHVlID0gdmFsdWU7XG4gIH1cbn1cblxuZnVuY3Rpb24gdmFyaWFibGUobmFtZSA9IG51bGwpIHtcbiAgcmV0dXJuIG5ldyBWYXJpYWJsZShuYW1lKTtcbn1cblxuZnVuY3Rpb24gd2lsZGNhcmQoKSB7XG4gIHJldHVybiBuZXcgV2lsZGNhcmQoKTtcbn1cblxuZnVuY3Rpb24gc3RhcnRzV2l0aChwcmVmaXgpIHtcbiAgcmV0dXJuIG5ldyBTdGFydHNXaXRoKHByZWZpeCk7XG59XG5cbmZ1bmN0aW9uIGNhcHR1cmUodmFsdWUpIHtcbiAgcmV0dXJuIG5ldyBDYXB0dXJlKHZhbHVlKTtcbn1cblxuZnVuY3Rpb24gaGVhZFRhaWwoKSB7XG4gIHJldHVybiBuZXcgSGVhZFRhaWwoKTtcbn1cblxuZnVuY3Rpb24gdHlwZSh0eXBlLCBvYmpQYXR0ZXJuID0ge30pIHtcbiAgcmV0dXJuIG5ldyBUeXBlKHR5cGUsIG9ialBhdHRlcm4pO1xufVxuXG5mdW5jdGlvbiBib3VuZCh2YWx1ZSkge1xuICByZXR1cm4gbmV3IEJvdW5kKHZhbHVlKTtcbn1cblxuZnVuY3Rpb24gX2lzX251bWJlcih2YWx1ZSkge1xuICByZXR1cm4gdHlwZW9mIHZhbHVlID09PSAnbnVtYmVyJztcbn1cblxuZnVuY3Rpb24gaXNfc3RyaW5nKHZhbHVlKSB7XG4gIHJldHVybiB0eXBlb2YgdmFsdWUgPT09ICdzdHJpbmcnO1xufVxuXG5mdW5jdGlvbiBfaXNfdHVwbGUodmFsdWUpIHtcbiAgcmV0dXJuIHZhbHVlIGluc3RhbmNlb2YgVHVwbGU7XG59XG5cbmZ1bmN0aW9uIF9pc19ib29sZWFuKHZhbHVlKSB7XG4gIHJldHVybiB0eXBlb2YgdmFsdWUgPT09ICdib29sZWFuJztcbn1cblxuZnVuY3Rpb24gaXNfc3ltYm9sKHZhbHVlKSB7XG4gIHJldHVybiB0eXBlb2YgdmFsdWUgPT09ICdzeW1ib2wnO1xufVxuXG5mdW5jdGlvbiBpc19udWxsKHZhbHVlKSB7XG4gIHJldHVybiB2YWx1ZSA9PT0gbnVsbDtcbn1cblxuZnVuY3Rpb24gaXNfdW5kZWZpbmVkKHZhbHVlKSB7XG4gIHJldHVybiB0eXBlb2YgdmFsdWUgPT09ICd1bmRlZmluZWQnO1xufVxuXG5mdW5jdGlvbiBfaXNfZnVuY3Rpb24odmFsdWUpIHtcbiAgcmV0dXJuIE9iamVjdC5wcm90b3R5cGUudG9TdHJpbmcuY2FsbCh2YWx1ZSkgPT0gJ1tvYmplY3QgRnVuY3Rpb25dJztcbn1cblxuZnVuY3Rpb24gaXNfdmFyaWFibGUodmFsdWUpIHtcbiAgcmV0dXJuIHZhbHVlIGluc3RhbmNlb2YgVmFyaWFibGU7XG59XG5cbmZ1bmN0aW9uIGlzX3dpbGRjYXJkKHZhbHVlKSB7XG4gIHJldHVybiB2YWx1ZSBpbnN0YW5jZW9mIFdpbGRjYXJkO1xufVxuXG5mdW5jdGlvbiBpc19oZWFkVGFpbCh2YWx1ZSkge1xuICByZXR1cm4gdmFsdWUgaW5zdGFuY2VvZiBIZWFkVGFpbDtcbn1cblxuZnVuY3Rpb24gaXNfY2FwdHVyZSh2YWx1ZSkge1xuICByZXR1cm4gdmFsdWUgaW5zdGFuY2VvZiBDYXB0dXJlO1xufVxuXG5mdW5jdGlvbiBpc190eXBlKHZhbHVlKSB7XG4gIHJldHVybiB2YWx1ZSBpbnN0YW5jZW9mIFR5cGU7XG59XG5cbmZ1bmN0aW9uIGlzX3N0YXJ0c1dpdGgodmFsdWUpIHtcbiAgcmV0dXJuIHZhbHVlIGluc3RhbmNlb2YgU3RhcnRzV2l0aDtcbn1cblxuZnVuY3Rpb24gaXNfYm91bmQodmFsdWUpIHtcbiAgcmV0dXJuIHZhbHVlIGluc3RhbmNlb2YgQm91bmQ7XG59XG5cbmZ1bmN0aW9uIGlzX29iamVjdCh2YWx1ZSkge1xuICByZXR1cm4gdHlwZW9mIHZhbHVlID09PSAnb2JqZWN0Jztcbn1cblxuZnVuY3Rpb24gaXNfYXJyYXkodmFsdWUpIHtcbiAgcmV0dXJuIEFycmF5LmlzQXJyYXkodmFsdWUpO1xufVxuXG52YXIgQ2hlY2tzID0ge1xuICBpc19udW1iZXI6IF9pc19udW1iZXIsXG4gIGlzX3N0cmluZyxcbiAgaXNfYm9vbGVhbjogX2lzX2Jvb2xlYW4sXG4gIGlzX3N5bWJvbCxcbiAgaXNfbnVsbCxcbiAgaXNfdW5kZWZpbmVkLFxuICBpc19mdW5jdGlvbjogX2lzX2Z1bmN0aW9uLFxuICBpc192YXJpYWJsZSxcbiAgaXNfd2lsZGNhcmQsXG4gIGlzX2hlYWRUYWlsLFxuICBpc19jYXB0dXJlLFxuICBpc190eXBlLFxuICBpc19zdGFydHNXaXRoLFxuICBpc19ib3VuZCxcbiAgaXNfb2JqZWN0LFxuICBpc19hcnJheSxcbiAgaXNfdHVwbGU6IF9pc190dXBsZVxufTtcblxuZnVuY3Rpb24gcmVzb2x2ZVR1cGxlKHBhdHRlcm4pIHtcbiAgbGV0IG1hdGNoZXMgPSBbXTtcblxuICBmb3IgKGxldCBlbGVtIG9mIHBhdHRlcm4pIHtcbiAgICBtYXRjaGVzLnB1c2goYnVpbGRNYXRjaChlbGVtKSk7XG4gIH1cblxuICByZXR1cm4gZnVuY3Rpb24gKHZhbHVlLCBhcmdzKSB7XG4gICAgaWYgKCFDaGVja3MuaXNfdHVwbGUodmFsdWUpIHx8IHZhbHVlLmNvdW50KCkgIT0gcGF0dGVybi5jb3VudCgpKSB7XG4gICAgICByZXR1cm4gZmFsc2U7XG4gICAgfVxuXG4gICAgcmV0dXJuIHZhbHVlLnZhbHVlcy5ldmVyeShmdW5jdGlvbiAodiwgaSkge1xuICAgICAgcmV0dXJuIG1hdGNoZXNbaV0odmFsdWUuZ2V0KGkpLCBhcmdzKTtcbiAgICB9KTtcbiAgfTtcbn1cblxuZnVuY3Rpb24gcmVzb2x2ZVN5bWJvbChwYXR0ZXJuKSB7XG4gIHJldHVybiBmdW5jdGlvbiAodmFsdWUpIHtcbiAgICByZXR1cm4gQ2hlY2tzLmlzX3N5bWJvbCh2YWx1ZSkgJiYgdmFsdWUgPT09IHBhdHRlcm47XG4gIH07XG59XG5cbmZ1bmN0aW9uIHJlc29sdmVTdHJpbmcocGF0dGVybikge1xuICByZXR1cm4gZnVuY3Rpb24gKHZhbHVlKSB7XG4gICAgcmV0dXJuIENoZWNrcy5pc19zdHJpbmcodmFsdWUpICYmIHZhbHVlID09PSBwYXR0ZXJuO1xuICB9O1xufVxuXG5mdW5jdGlvbiByZXNvbHZlTnVtYmVyKHBhdHRlcm4pIHtcbiAgcmV0dXJuIGZ1bmN0aW9uICh2YWx1ZSkge1xuICAgIHJldHVybiBDaGVja3MuaXNfbnVtYmVyKHZhbHVlKSAmJiB2YWx1ZSA9PT0gcGF0dGVybjtcbiAgfTtcbn1cblxuZnVuY3Rpb24gcmVzb2x2ZUJvb2xlYW4ocGF0dGVybikge1xuICByZXR1cm4gZnVuY3Rpb24gKHZhbHVlKSB7XG4gICAgcmV0dXJuIENoZWNrcy5pc19ib29sZWFuKHZhbHVlKSAmJiB2YWx1ZSA9PT0gcGF0dGVybjtcbiAgfTtcbn1cblxuZnVuY3Rpb24gcmVzb2x2ZUZ1bmN0aW9uKHBhdHRlcm4pIHtcbiAgcmV0dXJuIGZ1bmN0aW9uICh2YWx1ZSkge1xuICAgIHJldHVybiBDaGVja3MuaXNfZnVuY3Rpb24odmFsdWUpICYmIHZhbHVlID09PSBwYXR0ZXJuO1xuICB9O1xufVxuXG5mdW5jdGlvbiByZXNvbHZlTnVsbChwYXR0ZXJuKSB7XG4gIHJldHVybiBmdW5jdGlvbiAodmFsdWUpIHtcbiAgICByZXR1cm4gQ2hlY2tzLmlzX251bGwodmFsdWUpO1xuICB9O1xufVxuXG5mdW5jdGlvbiByZXNvbHZlQm91bmQocGF0dGVybikge1xuICByZXR1cm4gZnVuY3Rpb24gKHZhbHVlLCBhcmdzKSB7XG4gICAgaWYgKHR5cGVvZiB2YWx1ZSA9PT0gdHlwZW9mIHBhdHRlcm4udmFsdWUgJiYgdmFsdWUgPT09IHBhdHRlcm4udmFsdWUpIHtcbiAgICAgIGFyZ3MucHVzaCh2YWx1ZSk7XG4gICAgICByZXR1cm4gdHJ1ZTtcbiAgICB9XG5cbiAgICByZXR1cm4gZmFsc2U7XG4gIH07XG59XG5cbmZ1bmN0aW9uIHJlc29sdmVXaWxkY2FyZCgpIHtcbiAgcmV0dXJuIGZ1bmN0aW9uICgpIHtcbiAgICByZXR1cm4gdHJ1ZTtcbiAgfTtcbn1cblxuZnVuY3Rpb24gcmVzb2x2ZVZhcmlhYmxlKCkge1xuICByZXR1cm4gZnVuY3Rpb24gKHZhbHVlLCBhcmdzKSB7XG4gICAgYXJncy5wdXNoKHZhbHVlKTtcbiAgICByZXR1cm4gdHJ1ZTtcbiAgfTtcbn1cblxuZnVuY3Rpb24gcmVzb2x2ZUhlYWRUYWlsKCkge1xuICByZXR1cm4gZnVuY3Rpb24gKHZhbHVlLCBhcmdzKSB7XG4gICAgaWYgKCFDaGVja3MuaXNfYXJyYXkodmFsdWUpIHx8IHZhbHVlLmxlbmd0aCA8IDIpIHtcbiAgICAgIHJldHVybiBmYWxzZTtcbiAgICB9XG5cbiAgICBjb25zdCBoZWFkID0gdmFsdWVbMF07XG4gICAgY29uc3QgdGFpbCA9IHZhbHVlLnNsaWNlKDEpO1xuXG4gICAgYXJncy5wdXNoKGhlYWQpO1xuICAgIGFyZ3MucHVzaCh0YWlsKTtcblxuICAgIHJldHVybiB0cnVlO1xuICB9O1xufVxuXG5mdW5jdGlvbiByZXNvbHZlQ2FwdHVyZShwYXR0ZXJuKSB7XG4gIGNvbnN0IG1hdGNoZXMgPSBidWlsZE1hdGNoKHBhdHRlcm4udmFsdWUpO1xuXG4gIHJldHVybiBmdW5jdGlvbiAodmFsdWUsIGFyZ3MpIHtcbiAgICBpZiAobWF0Y2hlcyh2YWx1ZSwgYXJncykpIHtcbiAgICAgIGFyZ3MucHVzaCh2YWx1ZSk7XG4gICAgICByZXR1cm4gdHJ1ZTtcbiAgICB9XG5cbiAgICByZXR1cm4gZmFsc2U7XG4gIH07XG59XG5cbmZ1bmN0aW9uIHJlc29sdmVTdGFydHNXaXRoKHBhdHRlcm4pIHtcbiAgY29uc3QgcHJlZml4ID0gcGF0dGVybi5wcmVmaXg7XG5cbiAgcmV0dXJuIGZ1bmN0aW9uICh2YWx1ZSwgYXJncykge1xuICAgIGlmIChDaGVja3MuaXNfc3RyaW5nKHZhbHVlKSAmJiB2YWx1ZS5zdGFydHNXaXRoKHByZWZpeCkpIHtcbiAgICAgIGFyZ3MucHVzaCh2YWx1ZS5zdWJzdHJpbmcocHJlZml4Lmxlbmd0aCkpO1xuICAgICAgcmV0dXJuIHRydWU7XG4gICAgfVxuXG4gICAgcmV0dXJuIGZhbHNlO1xuICB9O1xufVxuXG5mdW5jdGlvbiByZXNvbHZlVHlwZShwYXR0ZXJuKSB7XG4gIHJldHVybiBmdW5jdGlvbiAodmFsdWUsIGFyZ3MpIHtcbiAgICBpZiAodmFsdWUgaW5zdGFuY2VvZiBwYXR0ZXJuLnR5cGUpIHtcbiAgICAgIGNvbnN0IG1hdGNoZXMgPSBidWlsZE1hdGNoKHBhdHRlcm4ub2JqUGF0dGVybik7XG4gICAgICByZXR1cm4gbWF0Y2hlcyh2YWx1ZSwgYXJncykgJiYgYXJncy5wdXNoKHZhbHVlKSA+IDA7XG4gICAgfVxuXG4gICAgcmV0dXJuIGZhbHNlO1xuICB9O1xufVxuXG5mdW5jdGlvbiByZXNvbHZlQXJyYXkocGF0dGVybikge1xuICBjb25zdCBtYXRjaGVzID0gcGF0dGVybi5tYXAoeCA9PiBidWlsZE1hdGNoKHgpKTtcblxuICByZXR1cm4gZnVuY3Rpb24gKHZhbHVlLCBhcmdzKSB7XG4gICAgaWYgKCFDaGVja3MuaXNfYXJyYXkodmFsdWUpIHx8IHZhbHVlLmxlbmd0aCAhPSBwYXR0ZXJuLmxlbmd0aCkge1xuICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH1cblxuICAgIHJldHVybiB2YWx1ZS5ldmVyeShmdW5jdGlvbiAodiwgaSkge1xuICAgICAgcmV0dXJuIG1hdGNoZXNbaV0odmFsdWVbaV0sIGFyZ3MpO1xuICAgIH0pO1xuICB9O1xufVxuXG5mdW5jdGlvbiByZXNvbHZlT2JqZWN0KHBhdHRlcm4pIHtcbiAgbGV0IG1hdGNoZXMgPSB7fTtcblxuICBmb3IgKGxldCBrZXkgb2YgT2JqZWN0LmtleXMocGF0dGVybikpIHtcbiAgICBtYXRjaGVzW2tleV0gPSBidWlsZE1hdGNoKHBhdHRlcm5ba2V5XSk7XG4gIH1cblxuICByZXR1cm4gZnVuY3Rpb24gKHZhbHVlLCBhcmdzKSB7XG4gICAgaWYgKCFDaGVja3MuaXNfb2JqZWN0KHZhbHVlKSB8fCBwYXR0ZXJuLmxlbmd0aCA+IHZhbHVlLmxlbmd0aCkge1xuICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH1cblxuICAgIGZvciAobGV0IGtleSBvZiBPYmplY3Qua2V5cyhwYXR0ZXJuKSkge1xuICAgICAgaWYgKCEoa2V5IGluIHZhbHVlKSB8fCAhbWF0Y2hlc1trZXldKHZhbHVlW2tleV0sIGFyZ3MpKSB7XG4gICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICByZXR1cm4gdHJ1ZTtcbiAgfTtcbn1cblxuZnVuY3Rpb24gcmVzb2x2ZU5vTWF0Y2goKSB7XG4gIHJldHVybiBmdW5jdGlvbiAoKSB7XG4gICAgcmV0dXJuIGZhbHNlO1xuICB9O1xufVxuXG52YXIgUmVzb2x2ZXJzID0ge1xuICByZXNvbHZlQm91bmQsXG4gIHJlc29sdmVXaWxkY2FyZCxcbiAgcmVzb2x2ZVZhcmlhYmxlLFxuICByZXNvbHZlSGVhZFRhaWwsXG4gIHJlc29sdmVDYXB0dXJlLFxuICByZXNvbHZlU3RhcnRzV2l0aCxcbiAgcmVzb2x2ZVR5cGUsXG4gIHJlc29sdmVBcnJheSxcbiAgcmVzb2x2ZU9iamVjdCxcbiAgcmVzb2x2ZU5vTWF0Y2gsXG4gIHJlc29sdmVTeW1ib2wsXG4gIHJlc29sdmVTdHJpbmcsXG4gIHJlc29sdmVOdW1iZXIsXG4gIHJlc29sdmVCb29sZWFuLFxuICByZXNvbHZlRnVuY3Rpb24sXG4gIHJlc29sdmVOdWxsLFxuICByZXNvbHZlVHVwbGVcbn07XG5cbmZ1bmN0aW9uIGJ1aWxkTWF0Y2gocGF0dGVybikge1xuXG4gIGlmIChDaGVja3MuaXNfdHVwbGUocGF0dGVybikpIHtcbiAgICByZXR1cm4gUmVzb2x2ZXJzLnJlc29sdmVUdXBsZShwYXR0ZXJuKTtcbiAgfVxuXG4gIGlmIChDaGVja3MuaXNfdmFyaWFibGUocGF0dGVybikpIHtcbiAgICByZXR1cm4gUmVzb2x2ZXJzLnJlc29sdmVWYXJpYWJsZShwYXR0ZXJuKTtcbiAgfVxuXG4gIGlmIChDaGVja3MuaXNfd2lsZGNhcmQocGF0dGVybikpIHtcbiAgICByZXR1cm4gUmVzb2x2ZXJzLnJlc29sdmVXaWxkY2FyZChwYXR0ZXJuKTtcbiAgfVxuXG4gIGlmIChDaGVja3MuaXNfdW5kZWZpbmVkKHBhdHRlcm4pKSB7XG4gICAgcmV0dXJuIFJlc29sdmVycy5yZXNvbHZlV2lsZGNhcmQocGF0dGVybik7XG4gIH1cblxuICBpZiAoQ2hlY2tzLmlzX2hlYWRUYWlsKHBhdHRlcm4pKSB7XG4gICAgcmV0dXJuIFJlc29sdmVycy5yZXNvbHZlSGVhZFRhaWwocGF0dGVybik7XG4gIH1cblxuICBpZiAoQ2hlY2tzLmlzX3N0YXJ0c1dpdGgocGF0dGVybikpIHtcbiAgICByZXR1cm4gUmVzb2x2ZXJzLnJlc29sdmVTdGFydHNXaXRoKHBhdHRlcm4pO1xuICB9XG5cbiAgaWYgKENoZWNrcy5pc19jYXB0dXJlKHBhdHRlcm4pKSB7XG4gICAgcmV0dXJuIFJlc29sdmVycy5yZXNvbHZlQ2FwdHVyZShwYXR0ZXJuKTtcbiAgfVxuXG4gIGlmIChDaGVja3MuaXNfYm91bmQocGF0dGVybikpIHtcbiAgICByZXR1cm4gUmVzb2x2ZXJzLnJlc29sdmVCb3VuZChwYXR0ZXJuKTtcbiAgfVxuXG4gIGlmIChDaGVja3MuaXNfdHlwZShwYXR0ZXJuKSkge1xuICAgIHJldHVybiBSZXNvbHZlcnMucmVzb2x2ZVR5cGUocGF0dGVybik7XG4gIH1cblxuICBpZiAoQ2hlY2tzLmlzX2FycmF5KHBhdHRlcm4pKSB7XG4gICAgcmV0dXJuIFJlc29sdmVycy5yZXNvbHZlQXJyYXkocGF0dGVybik7XG4gIH1cblxuICBpZiAoQ2hlY2tzLmlzX251bWJlcihwYXR0ZXJuKSkge1xuICAgIHJldHVybiBSZXNvbHZlcnMucmVzb2x2ZU51bWJlcihwYXR0ZXJuKTtcbiAgfVxuXG4gIGlmIChDaGVja3MuaXNfc3RyaW5nKHBhdHRlcm4pKSB7XG4gICAgcmV0dXJuIFJlc29sdmVycy5yZXNvbHZlU3RyaW5nKHBhdHRlcm4pO1xuICB9XG5cbiAgaWYgKENoZWNrcy5pc19ib29sZWFuKHBhdHRlcm4pKSB7XG4gICAgcmV0dXJuIFJlc29sdmVycy5yZXNvbHZlQm9vbGVhbihwYXR0ZXJuKTtcbiAgfVxuXG4gIGlmIChDaGVja3MuaXNfc3ltYm9sKHBhdHRlcm4pKSB7XG4gICAgcmV0dXJuIFJlc29sdmVycy5yZXNvbHZlU3ltYm9sKHBhdHRlcm4pO1xuICB9XG5cbiAgaWYgKENoZWNrcy5pc19udWxsKHBhdHRlcm4pKSB7XG4gICAgcmV0dXJuIFJlc29sdmVycy5yZXNvbHZlTnVsbChwYXR0ZXJuKTtcbiAgfVxuXG4gIGlmIChDaGVja3MuaXNfb2JqZWN0KHBhdHRlcm4pKSB7XG4gICAgcmV0dXJuIFJlc29sdmVycy5yZXNvbHZlT2JqZWN0KHBhdHRlcm4pO1xuICB9XG5cbiAgcmV0dXJuIFJlc29sdmVycy5yZXNvbHZlTm9NYXRjaCgpO1xufVxuXG5jbGFzcyBNYXRjaEVycm9yIGV4dGVuZHMgRXJyb3Ige1xuICBjb25zdHJ1Y3RvcihhcmcpIHtcbiAgICBzdXBlcigpO1xuXG4gICAgaWYgKHR5cGVvZiBhcmcgPT09ICdzeW1ib2wnKSB7XG4gICAgICB0aGlzLm1lc3NhZ2UgPSAnTm8gbWF0Y2ggZm9yOiAnICsgYXJnLnRvU3RyaW5nKCk7XG4gICAgfSBlbHNlIGlmIChBcnJheS5pc0FycmF5KGFyZykpIHtcbiAgICAgIGxldCBtYXBwZWRWYWx1ZXMgPSBhcmcubWFwKHggPT4geC50b1N0cmluZygpKTtcbiAgICAgIHRoaXMubWVzc2FnZSA9ICdObyBtYXRjaCBmb3I6ICcgKyBtYXBwZWRWYWx1ZXM7XG4gICAgfSBlbHNlIHtcbiAgICAgIHRoaXMubWVzc2FnZSA9ICdObyBtYXRjaCBmb3I6ICcgKyBhcmc7XG4gICAgfVxuXG4gICAgdGhpcy5zdGFjayA9IG5ldyBFcnJvcigpLnN0YWNrO1xuICAgIHRoaXMubmFtZSA9IHRoaXMuY29uc3RydWN0b3IubmFtZTtcbiAgfVxufVxuXG5jbGFzcyBDYXNlIHtcblxuICBjb25zdHJ1Y3RvcihwYXR0ZXJuLCBmbiwgZ3VhcmQgPSAoKSA9PiB0cnVlKSB7XG4gICAgdGhpcy5wYXR0ZXJuID0gYnVpbGRNYXRjaChwYXR0ZXJuKTtcbiAgICB0aGlzLmZuID0gZm47XG4gICAgdGhpcy5ndWFyZCA9IGd1YXJkO1xuICB9XG59XG5cbmZ1bmN0aW9uIG1ha2VfY2FzZShwYXR0ZXJuLCBmbiwgZ3VhcmQgPSAoKSA9PiB0cnVlKSB7XG4gIHJldHVybiBuZXcgQ2FzZShwYXR0ZXJuLCBmbiwgZ3VhcmQpO1xufVxuXG5mdW5jdGlvbiBkZWZtYXRjaCguLi5jYXNlcykge1xuICByZXR1cm4gZnVuY3Rpb24gKC4uLmFyZ3MpIHtcbiAgICBmb3IgKGxldCBwcm9jZXNzZWRDYXNlIG9mIGNhc2VzKSB7XG4gICAgICBsZXQgcmVzdWx0ID0gW107XG4gICAgICBpZiAocHJvY2Vzc2VkQ2FzZS5wYXR0ZXJuKGFyZ3MsIHJlc3VsdCkgJiYgcHJvY2Vzc2VkQ2FzZS5ndWFyZC5hcHBseSh0aGlzLCByZXN1bHQpKSB7XG4gICAgICAgIHJldHVybiBwcm9jZXNzZWRDYXNlLmZuLmFwcGx5KHRoaXMsIHJlc3VsdCk7XG4gICAgICB9XG4gICAgfVxuXG4gICAgdGhyb3cgbmV3IE1hdGNoRXJyb3IoYXJncyk7XG4gIH07XG59XG5cbmZ1bmN0aW9uIG1hdGNoKHBhdHRlcm4sIGV4cHIsIGd1YXJkID0gKCkgPT4gdHJ1ZSkge1xuICBsZXQgcmVzdWx0ID0gW107XG4gIGxldCBwcm9jZXNzZWRQYXR0ZXJuID0gYnVpbGRNYXRjaChwYXR0ZXJuKTtcbiAgaWYgKHByb2Nlc3NlZFBhdHRlcm4oZXhwciwgcmVzdWx0KSAmJiBndWFyZC5hcHBseSh0aGlzLCByZXN1bHQpKSB7XG4gICAgcmV0dXJuIHJlc3VsdDtcbiAgfSBlbHNlIHtcbiAgICB0aHJvdyBuZXcgTWF0Y2hFcnJvcihleHByKTtcbiAgfVxufVxuXG5mdW5jdGlvbiBtYXRjaF9ub190aHJvdyhwYXR0ZXJuLCBleHByLCBndWFyZCA9ICgpID0+IHRydWUpIHtcbiAgdHJ5IHtcbiAgICByZXR1cm4gbWF0Y2gocGF0dGVybiwgZXhwciwgZ3VhcmQpO1xuICB9IGNhdGNoIChlKSB7XG4gICAgaWYgKGUgaW5zdGFuY2VvZiBNYXRjaEVycm9yKSB7XG4gICAgICByZXR1cm4gbnVsbDtcbiAgICB9XG5cbiAgICB0aHJvdyBlO1xuICB9XG59XG5cbmZ1bmN0aW9uIHBhdHRlcm5NYXAoY29sbGVjdGlvbiwgcGF0dGVybiwgZnVuLCBndWFyZCA9ICgpID0+IHRydWUpIHtcbiAgbGV0IHJldCA9IFtdO1xuXG4gIGZvciAobGV0IGVsZW0gb2YgY29sbGVjdGlvbikge1xuICAgIHRyeSB7XG4gICAgICBsZXQgcmVzdWx0ID0gZnVuLmFwcGx5KHRoaXMsIG1hdGNoKHBhdHRlcm4sIGVsZW0sIGd1YXJkKSk7XG4gICAgICByZXQgPSByZXQuY29uY2F0KHJlc3VsdCk7XG4gICAgfSBjYXRjaCAoZSkge1xuICAgICAgaWYgKCEoZSBpbnN0YW5jZW9mIE1hdGNoRXJyb3IpKSB7XG4gICAgICAgIHRocm93IGU7XG4gICAgICB9XG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIHJldDtcbn1cblxudmFyIF9QYXR0ZXJucyA9IHtcbiAgZGVmbWF0Y2gsIG1hdGNoLCBNYXRjaEVycm9yLCBtYXRjaF9ub190aHJvdywgcGF0dGVybk1hcCxcbiAgdmFyaWFibGUsIHdpbGRjYXJkLCBzdGFydHNXaXRoLFxuICBjYXB0dXJlLCBoZWFkVGFpbCwgdHlwZSwgYm91bmQsIENhc2UsIG1ha2VfY2FzZVxufTtcblxuY2xhc3MgQml0U3RyaW5nIHtcbiAgY29uc3RydWN0b3IoLi4uYXJncykge1xuICAgIHRoaXMucmF3X3ZhbHVlID0gZnVuY3Rpb24gKCkge1xuICAgICAgcmV0dXJuIE9iamVjdC5mcmVlemUoYXJncyk7XG4gICAgfTtcblxuICAgIHRoaXMudmFsdWUgPSBPYmplY3QuZnJlZXplKHRoaXMucHJvY2VzcyhhcmdzKSk7XG4gIH1cblxuICBnZXQoaW5kZXgpIHtcbiAgICByZXR1cm4gdGhpcy52YWx1ZVtpbmRleF07XG4gIH1cblxuICBjb3VudCgpIHtcbiAgICByZXR1cm4gdGhpcy52YWx1ZS5sZW5ndGg7XG4gIH1cblxuICBbU3ltYm9sLml0ZXJhdG9yXSgpIHtcbiAgICByZXR1cm4gdGhpcy52YWx1ZVtTeW1ib2wuaXRlcmF0b3JdKCk7XG4gIH1cblxuICB0b1N0cmluZygpIHtcbiAgICB2YXIgaSxcbiAgICAgICAgcyA9IFwiXCI7XG4gICAgZm9yIChpID0gMDsgaSA8IHRoaXMuY291bnQoKTsgaSsrKSB7XG4gICAgICBpZiAocyAhPT0gXCJcIikge1xuICAgICAgICBzICs9IFwiLCBcIjtcbiAgICAgIH1cbiAgICAgIHMgKz0gdGhpc1tpXS50b1N0cmluZygpO1xuICAgIH1cblxuICAgIHJldHVybiBcIjw8XCIgKyBzICsgXCI+PlwiO1xuICB9XG5cbiAgcHJvY2VzcygpIHtcbiAgICBsZXQgcHJvY2Vzc2VkX3ZhbHVlcyA9IFtdO1xuXG4gICAgdmFyIGk7XG4gICAgZm9yIChpID0gMDsgaSA8IHRoaXMucmF3X3ZhbHVlKCkubGVuZ3RoOyBpKyspIHtcbiAgICAgIGxldCBwcm9jZXNzZWRfdmFsdWUgPSB0aGlzW1wicHJvY2Vzc19cIiArIHRoaXMucmF3X3ZhbHVlKClbaV0udHlwZV0odGhpcy5yYXdfdmFsdWUoKVtpXSk7XG5cbiAgICAgIGZvciAobGV0IGF0dHIgb2YgdGhpcy5yYXdfdmFsdWUoKVtpXS5hdHRyaWJ1dGVzKSB7XG4gICAgICAgIHByb2Nlc3NlZF92YWx1ZSA9IHRoaXNbXCJwcm9jZXNzX1wiICsgYXR0cl0ocHJvY2Vzc2VkX3ZhbHVlKTtcbiAgICAgIH1cblxuICAgICAgcHJvY2Vzc2VkX3ZhbHVlcyA9IHByb2Nlc3NlZF92YWx1ZXMuY29uY2F0KHByb2Nlc3NlZF92YWx1ZSk7XG4gICAgfVxuXG4gICAgcmV0dXJuIHByb2Nlc3NlZF92YWx1ZXM7XG4gIH1cblxuICBwcm9jZXNzX2ludGVnZXIodmFsdWUpIHtcbiAgICByZXR1cm4gdmFsdWUudmFsdWU7XG4gIH1cblxuICBwcm9jZXNzX2Zsb2F0KHZhbHVlKSB7XG4gICAgaWYgKHZhbHVlLnNpemUgPT09IDY0KSB7XG4gICAgICByZXR1cm4gQml0U3RyaW5nLmZsb2F0NjRUb0J5dGVzKHZhbHVlLnZhbHVlKTtcbiAgICB9IGVsc2UgaWYgKHZhbHVlLnNpemUgPT09IDMyKSB7XG4gICAgICByZXR1cm4gQml0U3RyaW5nLmZsb2F0MzJUb0J5dGVzKHZhbHVlLnZhbHVlKTtcbiAgICB9XG5cbiAgICB0aHJvdyBuZXcgRXJyb3IoXCJJbnZhbGlkIHNpemUgZm9yIGZsb2F0XCIpO1xuICB9XG5cbiAgcHJvY2Vzc19iaXRzdHJpbmcodmFsdWUpIHtcbiAgICByZXR1cm4gdmFsdWUudmFsdWUudmFsdWU7XG4gIH1cblxuICBwcm9jZXNzX2JpbmFyeSh2YWx1ZSkge1xuICAgIHJldHVybiBCaXRTdHJpbmcudG9VVEY4QXJyYXkodmFsdWUudmFsdWUpO1xuICB9XG5cbiAgcHJvY2Vzc191dGY4KHZhbHVlKSB7XG4gICAgcmV0dXJuIEJpdFN0cmluZy50b1VURjhBcnJheSh2YWx1ZS52YWx1ZSk7XG4gIH1cblxuICBwcm9jZXNzX3V0ZjE2KHZhbHVlKSB7XG4gICAgcmV0dXJuIEJpdFN0cmluZy50b1VURjE2QXJyYXkodmFsdWUudmFsdWUpO1xuICB9XG5cbiAgcHJvY2Vzc191dGYzMih2YWx1ZSkge1xuICAgIHJldHVybiBCaXRTdHJpbmcudG9VVEYzMkFycmF5KHZhbHVlLnZhbHVlKTtcbiAgfVxuXG4gIHByb2Nlc3Nfc2lnbmVkKHZhbHVlKSB7XG4gICAgcmV0dXJuIG5ldyBVaW50OEFycmF5KFt2YWx1ZV0pWzBdO1xuICB9XG5cbiAgcHJvY2Vzc191bnNpZ25lZCh2YWx1ZSkge1xuICAgIHJldHVybiB2YWx1ZTtcbiAgfVxuXG4gIHByb2Nlc3NfbmF0aXZlKHZhbHVlKSB7XG4gICAgcmV0dXJuIHZhbHVlO1xuICB9XG5cbiAgcHJvY2Vzc19iaWcodmFsdWUpIHtcbiAgICByZXR1cm4gdmFsdWU7XG4gIH1cblxuICBwcm9jZXNzX2xpdHRsZSh2YWx1ZSkge1xuICAgIHJldHVybiB2YWx1ZS5yZXZlcnNlKCk7XG4gIH1cblxuICBwcm9jZXNzX3NpemUodmFsdWUpIHtcbiAgICByZXR1cm4gdmFsdWU7XG4gIH1cblxuICBwcm9jZXNzX3VuaXQodmFsdWUpIHtcbiAgICByZXR1cm4gdmFsdWU7XG4gIH1cblxuICBzdGF0aWMgaW50ZWdlcih2YWx1ZSkge1xuICAgIHJldHVybiBCaXRTdHJpbmcud3JhcCh2YWx1ZSwgeyBcInR5cGVcIjogXCJpbnRlZ2VyXCIsIFwidW5pdFwiOiAxLCBcInNpemVcIjogOCB9KTtcbiAgfVxuXG4gIHN0YXRpYyBmbG9hdCh2YWx1ZSkge1xuICAgIHJldHVybiBCaXRTdHJpbmcud3JhcCh2YWx1ZSwgeyBcInR5cGVcIjogXCJmbG9hdFwiLCBcInVuaXRcIjogMSwgXCJzaXplXCI6IDY0IH0pO1xuICB9XG5cbiAgc3RhdGljIGJpdHN0cmluZyh2YWx1ZSkge1xuICAgIHJldHVybiBCaXRTdHJpbmcud3JhcCh2YWx1ZSwgeyBcInR5cGVcIjogXCJiaXRzdHJpbmdcIiwgXCJ1bml0XCI6IDEsIFwic2l6ZVwiOiB2YWx1ZS5sZW5ndGggfSk7XG4gIH1cblxuICBzdGF0aWMgYml0cyh2YWx1ZSkge1xuICAgIHJldHVybiBCaXRTdHJpbmcuYml0c3RyaW5nKHZhbHVlKTtcbiAgfVxuXG4gIHN0YXRpYyBiaW5hcnkodmFsdWUpIHtcbiAgICByZXR1cm4gQml0U3RyaW5nLndyYXAodmFsdWUsIHsgXCJ0eXBlXCI6IFwiYmluYXJ5XCIsIFwidW5pdFwiOiA4LCBcInNpemVcIjogdmFsdWUubGVuZ3RoIH0pO1xuICB9XG5cbiAgc3RhdGljIGJ5dGVzKHZhbHVlKSB7XG4gICAgcmV0dXJuIEJpdFN0cmluZy5iaW5hcnkodmFsdWUpO1xuICB9XG5cbiAgc3RhdGljIHV0ZjgodmFsdWUpIHtcbiAgICByZXR1cm4gQml0U3RyaW5nLndyYXAodmFsdWUsIHsgXCJ0eXBlXCI6IFwidXRmOFwiIH0pO1xuICB9XG5cbiAgc3RhdGljIHV0ZjE2KHZhbHVlKSB7XG4gICAgcmV0dXJuIEJpdFN0cmluZy53cmFwKHZhbHVlLCB7IFwidHlwZVwiOiBcInV0ZjE2XCIgfSk7XG4gIH1cblxuICBzdGF0aWMgdXRmMzIodmFsdWUpIHtcbiAgICByZXR1cm4gQml0U3RyaW5nLndyYXAodmFsdWUsIHsgXCJ0eXBlXCI6IFwidXRmMzJcIiB9KTtcbiAgfVxuXG4gIHN0YXRpYyBzaWduZWQodmFsdWUpIHtcbiAgICByZXR1cm4gQml0U3RyaW5nLndyYXAodmFsdWUsIHt9LCBcInNpZ25lZFwiKTtcbiAgfVxuXG4gIHN0YXRpYyB1bnNpZ25lZCh2YWx1ZSkge1xuICAgIHJldHVybiBCaXRTdHJpbmcud3JhcCh2YWx1ZSwge30sIFwidW5zaWduZWRcIik7XG4gIH1cblxuICBzdGF0aWMgbmF0aXZlKHZhbHVlKSB7XG4gICAgcmV0dXJuIEJpdFN0cmluZy53cmFwKHZhbHVlLCB7fSwgXCJuYXRpdmVcIik7XG4gIH1cblxuICBzdGF0aWMgYmlnKHZhbHVlKSB7XG4gICAgcmV0dXJuIEJpdFN0cmluZy53cmFwKHZhbHVlLCB7fSwgXCJiaWdcIik7XG4gIH1cblxuICBzdGF0aWMgbGl0dGxlKHZhbHVlKSB7XG4gICAgcmV0dXJuIEJpdFN0cmluZy53cmFwKHZhbHVlLCB7fSwgXCJsaXR0bGVcIik7XG4gIH1cblxuICBzdGF0aWMgc2l6ZSh2YWx1ZSwgY291bnQpIHtcbiAgICByZXR1cm4gQml0U3RyaW5nLndyYXAodmFsdWUsIHsgXCJzaXplXCI6IGNvdW50IH0pO1xuICB9XG5cbiAgc3RhdGljIHVuaXQodmFsdWUsIGNvdW50KSB7XG4gICAgcmV0dXJuIEJpdFN0cmluZy53cmFwKHZhbHVlLCB7IFwidW5pdFwiOiBjb3VudCB9KTtcbiAgfVxuXG4gIHN0YXRpYyB3cmFwKHZhbHVlLCBvcHQsIG5ld19hdHRyaWJ1dGUgPSBudWxsKSB7XG4gICAgbGV0IHRoZV92YWx1ZSA9IHZhbHVlO1xuXG4gICAgaWYgKCEodmFsdWUgaW5zdGFuY2VvZiBPYmplY3QpKSB7XG4gICAgICB0aGVfdmFsdWUgPSB7IFwidmFsdWVcIjogdmFsdWUsIFwiYXR0cmlidXRlc1wiOiBbXSB9O1xuICAgIH1cblxuICAgIHRoZV92YWx1ZSA9IE9iamVjdC5hc3NpZ24odGhlX3ZhbHVlLCBvcHQpO1xuXG4gICAgaWYgKG5ld19hdHRyaWJ1dGUpIHtcbiAgICAgIHRoZV92YWx1ZS5hdHRyaWJ1dGVzLnB1c2gobmV3X2F0dHJpYnV0ZSk7XG4gICAgfVxuXG4gICAgcmV0dXJuIHRoZV92YWx1ZTtcbiAgfVxuXG4gIHN0YXRpYyB0b1VURjhBcnJheShzdHIpIHtcbiAgICB2YXIgdXRmOCA9IFtdO1xuICAgIGZvciAodmFyIGkgPSAwOyBpIDwgc3RyLmxlbmd0aDsgaSsrKSB7XG4gICAgICB2YXIgY2hhcmNvZGUgPSBzdHIuY2hhckNvZGVBdChpKTtcbiAgICAgIGlmIChjaGFyY29kZSA8IDEyOCkge1xuICAgICAgICB1dGY4LnB1c2goY2hhcmNvZGUpO1xuICAgICAgfSBlbHNlIGlmIChjaGFyY29kZSA8IDIwNDgpIHtcbiAgICAgICAgdXRmOC5wdXNoKDE5MiB8IGNoYXJjb2RlID4+IDYsIDEyOCB8IGNoYXJjb2RlICYgNjMpO1xuICAgICAgfSBlbHNlIGlmIChjaGFyY29kZSA8IDU1Mjk2IHx8IGNoYXJjb2RlID49IDU3MzQ0KSB7XG4gICAgICAgIHV0ZjgucHVzaCgyMjQgfCBjaGFyY29kZSA+PiAxMiwgMTI4IHwgY2hhcmNvZGUgPj4gNiAmIDYzLCAxMjggfCBjaGFyY29kZSAmIDYzKTtcbiAgICAgIH1cbiAgICAgIC8vIHN1cnJvZ2F0ZSBwYWlyXG4gICAgICBlbHNlIHtcbiAgICAgICAgaSsrO1xuICAgICAgICAvLyBVVEYtMTYgZW5jb2RlcyAweDEwMDAwLTB4MTBGRkZGIGJ5XG4gICAgICAgIC8vIHN1YnRyYWN0aW5nIDB4MTAwMDAgYW5kIHNwbGl0dGluZyB0aGVcbiAgICAgICAgLy8gMjAgYml0cyBvZiAweDAtMHhGRkZGRiBpbnRvIHR3byBoYWx2ZXNcbiAgICAgICAgY2hhcmNvZGUgPSA2NTUzNiArICgoY2hhcmNvZGUgJiAxMDIzKSA8PCAxMCB8IHN0ci5jaGFyQ29kZUF0KGkpICYgMTAyMyk7XG4gICAgICAgIHV0ZjgucHVzaCgyNDAgfCBjaGFyY29kZSA+PiAxOCwgMTI4IHwgY2hhcmNvZGUgPj4gMTIgJiA2MywgMTI4IHwgY2hhcmNvZGUgPj4gNiAmIDYzLCAxMjggfCBjaGFyY29kZSAmIDYzKTtcbiAgICAgIH1cbiAgICB9XG4gICAgcmV0dXJuIHV0Zjg7XG4gIH1cblxuICBzdGF0aWMgdG9VVEYxNkFycmF5KHN0cikge1xuICAgIHZhciB1dGYxNiA9IFtdO1xuICAgIGZvciAodmFyIGkgPSAwOyBpIDwgc3RyLmxlbmd0aDsgaSsrKSB7XG4gICAgICB2YXIgY29kZVBvaW50ID0gc3RyLmNvZGVQb2ludEF0KGkpO1xuXG4gICAgICBpZiAoY29kZVBvaW50IDw9IDI1NSkge1xuICAgICAgICB1dGYxNi5wdXNoKDApO1xuICAgICAgICB1dGYxNi5wdXNoKGNvZGVQb2ludCk7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICB1dGYxNi5wdXNoKGNvZGVQb2ludCA+PiA4ICYgMjU1KTtcbiAgICAgICAgdXRmMTYucHVzaChjb2RlUG9pbnQgJiAyNTUpO1xuICAgICAgfVxuICAgIH1cbiAgICByZXR1cm4gdXRmMTY7XG4gIH1cblxuICBzdGF0aWMgdG9VVEYzMkFycmF5KHN0cikge1xuICAgIHZhciB1dGYzMiA9IFtdO1xuICAgIGZvciAodmFyIGkgPSAwOyBpIDwgc3RyLmxlbmd0aDsgaSsrKSB7XG4gICAgICB2YXIgY29kZVBvaW50ID0gc3RyLmNvZGVQb2ludEF0KGkpO1xuXG4gICAgICBpZiAoY29kZVBvaW50IDw9IDI1NSkge1xuICAgICAgICB1dGYzMi5wdXNoKDApO1xuICAgICAgICB1dGYzMi5wdXNoKDApO1xuICAgICAgICB1dGYzMi5wdXNoKDApO1xuICAgICAgICB1dGYzMi5wdXNoKGNvZGVQb2ludCk7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICB1dGYzMi5wdXNoKDApO1xuICAgICAgICB1dGYzMi5wdXNoKDApO1xuICAgICAgICB1dGYzMi5wdXNoKGNvZGVQb2ludCA+PiA4ICYgMjU1KTtcbiAgICAgICAgdXRmMzIucHVzaChjb2RlUG9pbnQgJiAyNTUpO1xuICAgICAgfVxuICAgIH1cbiAgICByZXR1cm4gdXRmMzI7XG4gIH1cblxuICAvL2h0dHA6Ly9zdGFja292ZXJmbG93LmNvbS9xdWVzdGlvbnMvMjAwMzQ5My9qYXZhc2NyaXB0LWZsb2F0LWZyb20tdG8tYml0c1xuICBzdGF0aWMgZmxvYXQzMlRvQnl0ZXMoZikge1xuICAgIHZhciBieXRlcyA9IFtdO1xuXG4gICAgdmFyIGJ1ZiA9IG5ldyBBcnJheUJ1ZmZlcig0KTtcbiAgICBuZXcgRmxvYXQzMkFycmF5KGJ1ZilbMF0gPSBmO1xuXG4gICAgbGV0IGludFZlcnNpb24gPSBuZXcgVWludDMyQXJyYXkoYnVmKVswXTtcblxuICAgIGJ5dGVzLnB1c2goaW50VmVyc2lvbiA+PiAyNCAmIDI1NSk7XG4gICAgYnl0ZXMucHVzaChpbnRWZXJzaW9uID4+IDE2ICYgMjU1KTtcbiAgICBieXRlcy5wdXNoKGludFZlcnNpb24gPj4gOCAmIDI1NSk7XG4gICAgYnl0ZXMucHVzaChpbnRWZXJzaW9uICYgMjU1KTtcblxuICAgIHJldHVybiBieXRlcztcbiAgfVxuXG4gIHN0YXRpYyBmbG9hdDY0VG9CeXRlcyhmKSB7XG4gICAgdmFyIGJ5dGVzID0gW107XG5cbiAgICB2YXIgYnVmID0gbmV3IEFycmF5QnVmZmVyKDgpO1xuICAgIG5ldyBGbG9hdDY0QXJyYXkoYnVmKVswXSA9IGY7XG5cbiAgICB2YXIgaW50VmVyc2lvbjEgPSBuZXcgVWludDMyQXJyYXkoYnVmKVswXTtcbiAgICB2YXIgaW50VmVyc2lvbjIgPSBuZXcgVWludDMyQXJyYXkoYnVmKVsxXTtcblxuICAgIGJ5dGVzLnB1c2goaW50VmVyc2lvbjIgPj4gMjQgJiAyNTUpO1xuICAgIGJ5dGVzLnB1c2goaW50VmVyc2lvbjIgPj4gMTYgJiAyNTUpO1xuICAgIGJ5dGVzLnB1c2goaW50VmVyc2lvbjIgPj4gOCAmIDI1NSk7XG4gICAgYnl0ZXMucHVzaChpbnRWZXJzaW9uMiAmIDI1NSk7XG5cbiAgICBieXRlcy5wdXNoKGludFZlcnNpb24xID4+IDI0ICYgMjU1KTtcbiAgICBieXRlcy5wdXNoKGludFZlcnNpb24xID4+IDE2ICYgMjU1KTtcbiAgICBieXRlcy5wdXNoKGludFZlcnNpb24xID4+IDggJiAyNTUpO1xuICAgIGJ5dGVzLnB1c2goaW50VmVyc2lvbjEgJiAyNTUpO1xuXG4gICAgcmV0dXJuIGJ5dGVzO1xuICB9XG59XG5cbmxldCBTcGVjaWFsRm9ybXMgPSB7XG5cbiAgX19ESVJfXzogZnVuY3Rpb24gKCkge1xuICAgIGlmIChfX2Rpcm5hbWUpIHtcbiAgICAgIHJldHVybiBfX2Rpcm5hbWU7XG4gICAgfVxuXG4gICAgaWYgKGRvY3VtZW50LmN1cnJlbnRTY3JpcHQpIHtcbiAgICAgIHJldHVybiBkb2N1bWVudC5jdXJyZW50U2NyaXB0LnNyYztcbiAgICB9XG5cbiAgICByZXR1cm4gbnVsbDtcbiAgfSxcblxuICBhdG9tOiBmdW5jdGlvbiAoX3ZhbHVlKSB7XG4gICAgcmV0dXJuIFN5bWJvbC5mb3IoX3ZhbHVlKTtcbiAgfSxcblxuICBsaXN0OiBmdW5jdGlvbiAoLi4uYXJncykge1xuICAgIHJldHVybiBPYmplY3QuZnJlZXplKGFyZ3MpO1xuICB9LFxuXG4gIGJpdHN0cmluZzogZnVuY3Rpb24gKC4uLmFyZ3MpIHtcbiAgICByZXR1cm4gbmV3IEJpdFN0cmluZyguLi5hcmdzKTtcbiAgfSxcblxuICBib3VuZDogZnVuY3Rpb24gKF92YXIpIHtcbiAgICByZXR1cm4gUGF0dGVybnMuYm91bmQoX3Zhcik7XG4gIH0sXG5cbiAgX2Nhc2U6IGZ1bmN0aW9uIChjb25kaXRpb24sIGNsYXVzZXMpIHtcbiAgICByZXR1cm4gUGF0dGVybnMuZGVmbWF0Y2goLi4uY2xhdXNlcykoY29uZGl0aW9uKTtcbiAgfSxcblxuICBjb25kOiBmdW5jdGlvbiAoY2xhdXNlcykge1xuICAgIGZvciAobGV0IGNsYXVzZSBvZiBjbGF1c2VzKSB7XG4gICAgICBpZiAoY2xhdXNlWzBdKSB7XG4gICAgICAgIHJldHVybiBjbGF1c2VbMV0oKTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICB0aHJvdyBuZXcgRXJyb3IoKTtcbiAgfSxcblxuICBmbjogZnVuY3Rpb24gKGNsYXVzZXMpIHtcbiAgICByZXR1cm4gUGF0dGVybnMuZGVmbWF0Y2goY2xhdXNlcyk7XG4gIH0sXG5cbiAgbWFwOiBmdW5jdGlvbiAob2JqKSB7XG4gICAgcmV0dXJuIE9iamVjdC5mcmVlemUob2JqKTtcbiAgfSxcblxuICBtYXBfdXBkYXRlOiBmdW5jdGlvbiAobWFwLCB2YWx1ZXMpIHtcbiAgICByZXR1cm4gT2JqZWN0LmZyZWV6ZShPYmplY3QuYXNzaWduKE9iamVjdC5jcmVhdGUobWFwLmNvbnN0cnVjdG9yLnByb3RvdHlwZSksIG1hcCwgdmFsdWVzKSk7XG4gIH0sXG5cbiAgX2ZvcjogZnVuY3Rpb24gKGNvbGxlY3Rpb25zLCBmdW4sIGZpbHRlciA9ICgpID0+IHRydWUsIGludG8gPSBbXSwgcHJldmlvdXNWYWx1ZXMgPSBbXSkge1xuICAgIGxldCBwYXR0ZXJuID0gY29sbGVjdGlvbnNbMF1bMF07XG4gICAgbGV0IGNvbGxlY3Rpb24gPSBjb2xsZWN0aW9uc1swXVsxXTtcblxuICAgIGlmIChjb2xsZWN0aW9ucy5sZW5ndGggPT09IDEpIHtcblxuICAgICAgZm9yIChsZXQgZWxlbSBvZiBjb2xsZWN0aW9uKSB7XG4gICAgICAgIGxldCByID0gUGF0dGVybnMubWF0Y2hfbm9fdGhyb3cocGF0dGVybiwgZWxlbSk7XG4gICAgICAgIGxldCBhcmdzID0gcHJldmlvdXNWYWx1ZXMuY29uY2F0KHIpO1xuXG4gICAgICAgIGlmIChyICYmIGZpbHRlci5hcHBseSh0aGlzLCBhcmdzKSkge1xuICAgICAgICAgIGludG8gPSBFbnVtLmludG8oW2Z1bi5hcHBseSh0aGlzLCBhcmdzKV0sIGludG8pO1xuICAgICAgICB9XG4gICAgICB9XG5cbiAgICAgIHJldHVybiBpbnRvO1xuICAgIH0gZWxzZSB7XG4gICAgICBsZXQgX2ludG8gPSBbXTtcblxuICAgICAgZm9yIChsZXQgZWxlbSBvZiBjb2xsZWN0aW9uKSB7XG4gICAgICAgIGxldCByID0gUGF0dGVybnMubWF0Y2hfbm9fdGhyb3cocGF0dGVybiwgZWxlbSk7XG4gICAgICAgIGlmIChyKSB7XG4gICAgICAgICAgX2ludG8gPSBFbnVtLmludG8odGhpcy5fZm9yKGNvbGxlY3Rpb25zLnNsaWNlKDEpLCBmdW4sIGZpbHRlciwgX2ludG8sIHByZXZpb3VzVmFsdWVzLmNvbmNhdChyKSksIGludG8pO1xuICAgICAgICB9XG4gICAgICB9XG5cbiAgICAgIHJldHVybiBfaW50bztcbiAgICB9XG4gIH0sXG5cbiAgcmVjZWl2ZTogZnVuY3Rpb24gKHJlY2VpdmVfZnVuLCB0aW1lb3V0X2luX21zID0gbnVsbCwgdGltZW91dF9mbiA9IHRpbWUgPT4gdHJ1ZSkge1xuICAgIGlmICh0aW1lb3V0X2luX21zID09IG51bGwgfHwgdGltZW91dF9pbl9tcyA9PT0gU3lzdGVtLmZvcignaW5maW5pdHknKSkge1xuICAgICAgd2hpbGUgKHRydWUpIHtcbiAgICAgICAgaWYgKHNlbGYubWFpbGJveC5sZW5ndGggIT09IDApIHtcbiAgICAgICAgICBsZXQgbWVzc2FnZSA9IHNlbGYubWFpbGJveFswXTtcbiAgICAgICAgICBzZWxmLm1haWxib3ggPSBzZWxmLm1haWxib3guc2xpY2UoMSk7XG4gICAgICAgICAgcmV0dXJuIHJlY2VpdmVfZnVuKG1lc3NhZ2UpO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgfSBlbHNlIGlmICh0aW1lb3V0X2luX21zID09PSAwKSB7XG4gICAgICBpZiAoc2VsZi5tYWlsYm94Lmxlbmd0aCAhPT0gMCkge1xuICAgICAgICBsZXQgbWVzc2FnZSA9IHNlbGYubWFpbGJveFswXTtcbiAgICAgICAgc2VsZi5tYWlsYm94ID0gc2VsZi5tYWlsYm94LnNsaWNlKDEpO1xuICAgICAgICByZXR1cm4gcmVjZWl2ZV9mdW4obWVzc2FnZSk7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICByZXR1cm4gbnVsbDtcbiAgICAgIH1cbiAgICB9IGVsc2Uge1xuICAgICAgbGV0IG5vdyA9IERhdGUubm93KCk7XG4gICAgICB3aGlsZSAoRGF0ZS5ub3coKSA8IG5vdyArIHRpbWVvdXRfaW5fbXMpIHtcbiAgICAgICAgaWYgKHNlbGYubWFpbGJveC5sZW5ndGggIT09IDApIHtcbiAgICAgICAgICBsZXQgbWVzc2FnZSA9IHNlbGYubWFpbGJveFswXTtcbiAgICAgICAgICBzZWxmLm1haWxib3ggPSBzZWxmLm1haWxib3guc2xpY2UoMSk7XG4gICAgICAgICAgcmV0dXJuIHJlY2VpdmVfZnVuKG1lc3NhZ2UpO1xuICAgICAgICB9XG4gICAgICB9XG5cbiAgICAgIHJldHVybiB0aW1lb3V0X2ZuKHRpbWVvdXRfaW5fbXMpO1xuICAgIH1cbiAgfSxcblxuICB0dXBsZTogZnVuY3Rpb24gKC4uLmFyZ3MpIHtcbiAgICByZXR1cm4gbmV3IFR1cGxlKC4uLmFyZ3MpO1xuICB9LFxuXG4gIF90cnk6IGZ1bmN0aW9uIChkb19mdW4sIHJlc2N1ZV9mdW5jdGlvbiwgY2F0Y2hfZnVuLCBlbHNlX2Z1bmN0aW9uLCBhZnRlcl9mdW5jdGlvbikge1xuICAgIGxldCByZXN1bHQgPSBudWxsO1xuXG4gICAgdHJ5IHtcbiAgICAgIHJlc3VsdCA9IGRvX2Z1bigpO1xuICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgIGxldCBleF9yZXN1bHQgPSBudWxsO1xuXG4gICAgICBpZiAocmVzY3VlX2Z1bmN0aW9uKSB7XG4gICAgICAgIHRyeSB7XG4gICAgICAgICAgZXhfcmVzdWx0ID0gcmVzY3VlX2Z1bmN0aW9uKGUpO1xuICAgICAgICAgIHJldHVybiBleF9yZXN1bHQ7XG4gICAgICAgIH0gY2F0Y2ggKGV4KSB7XG4gICAgICAgICAgaWYgKGV4IGluc3RhbmNlb2YgUGF0dGVybnMuTWF0Y2hFcnJvcikge1xuICAgICAgICAgICAgdGhyb3cgZXg7XG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICB9XG5cbiAgICAgIGlmIChjYXRjaF9mdW4pIHtcbiAgICAgICAgdHJ5IHtcbiAgICAgICAgICBleF9yZXN1bHQgPSBjYXRjaF9mdW4oZSk7XG4gICAgICAgICAgcmV0dXJuIGV4X3Jlc3VsdDtcbiAgICAgICAgfSBjYXRjaCAoZXgpIHtcbiAgICAgICAgICBpZiAoZXggaW5zdGFuY2VvZiBQYXR0ZXJucy5NYXRjaEVycm9yKSB7XG4gICAgICAgICAgICB0aHJvdyBleDtcbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgIH1cblxuICAgICAgdGhyb3cgZTtcbiAgICB9IGZpbmFsbHkge1xuICAgICAgaWYgKGFmdGVyX2Z1bmN0aW9uKSB7XG4gICAgICAgIGFmdGVyX2Z1bmN0aW9uKCk7XG4gICAgICB9XG4gICAgfVxuXG4gICAgaWYgKGVsc2VfZnVuY3Rpb24pIHtcbiAgICAgIHRyeSB7XG4gICAgICAgIHJldHVybiBlbHNlX2Z1bmN0aW9uKHJlc3VsdCk7XG4gICAgICB9IGNhdGNoIChleCkge1xuICAgICAgICBpZiAoZXggaW5zdGFuY2VvZiBQYXR0ZXJucy5NYXRjaEVycm9yKSB7XG4gICAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdObyBNYXRjaCBGb3VuZCBpbiBFbHNlJyk7XG4gICAgICAgIH1cblxuICAgICAgICB0aHJvdyBleDtcbiAgICAgIH1cbiAgICB9IGVsc2Uge1xuICAgICAgcmV0dXJuIHJlc3VsdDtcbiAgICB9XG4gIH1cblxufTtcblxuLyogQGZsb3cgKi9cblxubGV0IHByb2Nlc3NfY291bnRlciA9IC0xO1xuXG5jbGFzcyBQSUQge1xuICBjb25zdHJ1Y3RvcigpIHtcbiAgICBwcm9jZXNzX2NvdW50ZXIgPSBwcm9jZXNzX2NvdW50ZXIgKyAxO1xuICAgIHRoaXMuaWQgPSBwcm9jZXNzX2NvdW50ZXI7XG4gIH1cblxuICB0b1N0cmluZygpIHtcbiAgICByZXR1cm4gXCJQSUQjPDAuXCIgKyB0aGlzLmlkICsgXCIuMD5cIjtcbiAgfVxufVxuXG5jbGFzcyBJbnRlZ2VyVHlwZSB7fVxuY2xhc3MgRmxvYXRUeXBlIHt9XG5cbi8vaHR0cHM6Ly9naXRodWIuY29tL2FpcnBvcnR5aC9wcm90b21vcnBoaXNtXG5jbGFzcyBQcm90b2NvbCB7XG4gIGNvbnN0cnVjdG9yKHNwZWMpIHtcbiAgICB0aGlzLnJlZ2lzdHJ5ID0gbmV3IE1hcCgpO1xuICAgIHRoaXMuZmFsbGJhY2sgPSBudWxsO1xuXG4gICAgZm9yIChsZXQgZnVuTmFtZSBpbiBzcGVjKSB7XG4gICAgICB0aGlzW2Z1bk5hbWVdID0gY3JlYXRlRnVuKGZ1bk5hbWUpLmJpbmQodGhpcyk7XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gY3JlYXRlRnVuKGZ1bk5hbWUpIHtcblxuICAgICAgcmV0dXJuIGZ1bmN0aW9uICguLi5hcmdzKSB7XG4gICAgICAgIGxldCB0aGluZyA9IGFyZ3NbMF07XG4gICAgICAgIGxldCBmdW4gPSBudWxsO1xuXG4gICAgICAgIGlmIChOdW1iZXIuaXNJbnRlZ2VyKHRoaW5nKSAmJiB0aGlzLmhhc0ltcGxlbWVudGF0aW9uKEludGVnZXJUeXBlKSkge1xuICAgICAgICAgIGZ1biA9IHRoaXMucmVnaXN0cnkuZ2V0KEludGVnZXJUeXBlKVtmdW5OYW1lXTtcbiAgICAgICAgfSBlbHNlIGlmICh0eXBlb2YgdGhpbmcgPT09IFwibnVtYmVyXCIgJiYgIU51bWJlci5pc0ludGVnZXIodGhpbmcpICYmIHRoaXMuaGFzSW1wbGVtZW50YXRpb24oRmxvYXRUeXBlKSkge1xuICAgICAgICAgIGZ1biA9IHRoaXMucmVnaXN0cnkuZ2V0KEZsb2F0VHlwZSlbZnVuTmFtZV07XG4gICAgICAgIH0gZWxzZSBpZiAodGhpcy5oYXNJbXBsZW1lbnRhdGlvbih0aGluZykpIHtcbiAgICAgICAgICBmdW4gPSB0aGlzLnJlZ2lzdHJ5LmdldCh0aGluZy5jb25zdHJ1Y3RvcilbZnVuTmFtZV07XG4gICAgICAgIH0gZWxzZSBpZiAodGhpcy5mYWxsYmFjaykge1xuICAgICAgICAgIGZ1biA9IHRoaXMuZmFsbGJhY2tbZnVuTmFtZV07XG4gICAgICAgIH1cblxuICAgICAgICBpZiAoZnVuICE9IG51bGwpIHtcbiAgICAgICAgICBsZXQgcmV0dmFsID0gZnVuLmFwcGx5KHRoaXMsIGFyZ3MpO1xuICAgICAgICAgIHJldHVybiByZXR2YWw7XG4gICAgICAgIH1cblxuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoXCJObyBpbXBsZW1lbnRhdGlvbiBmb3VuZCBmb3IgXCIgKyB0aGluZyk7XG4gICAgICB9O1xuICAgIH1cbiAgfVxuXG4gIGltcGxlbWVudGF0aW9uKHR5cGUsIGltcGxlbWVudGF0aW9uKSB7XG4gICAgaWYgKHR5cGUgPT09IG51bGwpIHtcbiAgICAgIHRoaXMuZmFsbGJhY2sgPSBpbXBsZW1lbnRhdGlvbjtcbiAgICB9IGVsc2Uge1xuICAgICAgdGhpcy5yZWdpc3RyeS5zZXQodHlwZSwgaW1wbGVtZW50YXRpb24pO1xuICAgIH1cbiAgfVxuXG4gIGhhc0ltcGxlbWVudGF0aW9uKHRoaW5nKSB7XG4gICAgcmV0dXJuIHRoaXMucmVnaXN0cnkuaGFzKHRoaW5nLmNvbnN0cnVjdG9yKTtcbiAgfVxufVxuXG5mdW5jdGlvbiB0bChsaXN0KSB7XG4gIHJldHVybiBTcGVjaWFsRm9ybXMubGlzdCguLi5saXN0LnNsaWNlKDEpKTtcbn1cblxuZnVuY3Rpb24gaGQobGlzdCkge1xuICByZXR1cm4gbGlzdFswXTtcbn1cblxuZnVuY3Rpb24gaXNfbmlsKHgpIHtcbiAgcmV0dXJuIHggPT09IG51bGw7XG59XG5cbmZ1bmN0aW9uIGlzX2F0b20oeCkge1xuICByZXR1cm4gdHlwZW9mIHggPT09ICdzeW1ib2wnO1xufVxuXG5mdW5jdGlvbiBpc19iaW5hcnkoeCkge1xuICByZXR1cm4gdHlwZW9mIHggPT09ICdzdHJpbmcnIHx8IHggaW5zdGFuY2VvZiBTdHJpbmc7XG59XG5cbmZ1bmN0aW9uIGlzX2Jvb2xlYW4oeCkge1xuICByZXR1cm4gdHlwZW9mIHggPT09ICdib29sZWFuJyB8fCB4IGluc3RhbmNlb2YgQm9vbGVhbjtcbn1cblxuZnVuY3Rpb24gaXNfZnVuY3Rpb24oeCwgYXJpdHkgPSAtMSkge1xuICByZXR1cm4gdHlwZW9mIHggPT09ICdmdW5jdGlvbicgfHwgeCBpbnN0YW5jZW9mIEZ1bmN0aW9uO1xufVxuXG5mdW5jdGlvbiBpc19mbG9hdCh4KSB7XG4gIHJldHVybiBpc19udW1iZXIoeCkgJiYgIU51bWJlci5pc0ludGVnZXIoeCk7XG59XG5cbmZ1bmN0aW9uIGlzX2ludGVnZXIoeCkge1xuICByZXR1cm4gTnVtYmVyLmlzSW50ZWdlcih4KTtcbn1cblxuZnVuY3Rpb24gaXNfbGlzdCh4KSB7XG4gIHJldHVybiB4IGluc3RhbmNlb2YgQXJyYXk7XG59XG5cbmZ1bmN0aW9uIGlzX21hcCh4KSB7XG4gIHJldHVybiB0eXBlb2YgeCA9PT0gJ29iamVjdCcgfHwgeCBpbnN0YW5jZW9mIE9iamVjdDtcbn1cblxuZnVuY3Rpb24gaXNfbnVtYmVyKHgpIHtcbiAgcmV0dXJuIHR5cGVvZiB4ID09PSAnbnVtYmVyJztcbn1cblxuZnVuY3Rpb24gaXNfdHVwbGUoeCkge1xuICByZXR1cm4geCBpbnN0YW5jZW9mIFR1cGxlO1xufVxuXG5mdW5jdGlvbiBfbGVuZ3RoKHgpIHtcbiAgcmV0dXJuIHgubGVuZ3RoO1xufVxuXG5mdW5jdGlvbiBpc19waWQoeCkge1xuICByZXR1cm4geCBpbnN0YW5jZW9mIFBJRDtcbn1cblxuZnVuY3Rpb24gaXNfcG9ydCh4KSB7XG4gIHJldHVybiBmYWxzZTtcbn1cblxuZnVuY3Rpb24gaXNfcmVmZXJlbmNlKHgpIHtcbiAgcmV0dXJuIGZhbHNlO1xufVxuXG5mdW5jdGlvbiBpc19iaXRzdHJpbmcoeCkge1xuICByZXR1cm4gaXNfYmluYXJ5KHgpIHx8IHggaW5zdGFuY2VvZiBCaXRTdHJpbmc7XG59XG5cbmZ1bmN0aW9uIF9faW5fXyhsZWZ0LCByaWdodCkge1xuICBmb3IgKGxldCB4IG9mIHJpZ2h0KSB7XG4gICAgaWYgKG1hdGNoX19xbWFya19fKGxlZnQsIHgpKSB7XG4gICAgICByZXR1cm4gdHJ1ZTtcbiAgICB9XG4gIH1cblxuICByZXR1cm4gZmFsc2U7XG59XG5cbmZ1bmN0aW9uIGFicyhudW1iZXIpIHtcbiAgcmV0dXJuIE1hdGguYWJzKG51bWJlcik7XG59XG5cbmZ1bmN0aW9uIHJvdW5kKG51bWJlcikge1xuICByZXR1cm4gTWF0aC5yb3VuZChudW1iZXIpO1xufVxuXG5mdW5jdGlvbiBlbGVtKHR1cGxlLCBpbmRleCkge1xuICBpZiAoaXNfbGlzdCh0dXBsZSkpIHtcbiAgICByZXR1cm4gdHVwbGVbaW5kZXhdO1xuICB9XG5cbiAgcmV0dXJuIHR1cGxlLmdldChpbmRleCk7XG59XG5cbmZ1bmN0aW9uIHJlbShsZWZ0LCByaWdodCkge1xuICByZXR1cm4gbGVmdCAlIHJpZ2h0O1xufVxuXG5mdW5jdGlvbiBkaXYobGVmdCwgcmlnaHQpIHtcbiAgcmV0dXJuIGxlZnQgLyByaWdodDtcbn1cblxuZnVuY3Rpb24gYW5kKGxlZnQsIHJpZ2h0KSB7XG4gIHJldHVybiBsZWZ0ICYmIHJpZ2h0O1xufVxuXG5mdW5jdGlvbiBvcihsZWZ0LCByaWdodCkge1xuICByZXR1cm4gbGVmdCB8fCByaWdodDtcbn1cblxuZnVuY3Rpb24gbm90KGFyZykge1xuICByZXR1cm4gIWFyZztcbn1cblxuZnVuY3Rpb24gYXBwbHkoLi4uYXJncykge1xuICBpZiAoYXJncy5sZW5ndGggPT09IDMpIHtcbiAgICBsZXQgbW9kID0gYXJnc1swXTtcbiAgICBsZXQgZnVuYyA9IGFyZ3NbMV07XG4gICAgbGV0IGZ1bmNfYXJncyA9IGFyZ3NbMl07XG4gICAgcmV0dXJuIG1vZFtmdW5jXS5hcHBseShudWxsLCBmdW5jX2FyZ3MpO1xuICB9IGVsc2Uge1xuICAgIGxldCBmdW5jID0gYXJnc1swXTtcbiAgICBsZXQgZnVuY19hcmdzID0gYXJnc1sxXTtcblxuICAgIHJldHVybiBmdW5jLmFwcGx5KG51bGwsIGZ1bmNfYXJncyk7XG4gIH1cbn1cblxuZnVuY3Rpb24gdG9fc3RyaW5nKGFyZykge1xuICBpZiAoaXNfdHVwbGUoYXJnKSkge1xuICAgIHJldHVybiBUdXBsZS50b19zdHJpbmcoYXJnKTtcbiAgfVxuXG4gIHJldHVybiBhcmcudG9TdHJpbmcoKTtcbn1cblxuZnVuY3Rpb24gbWF0Y2hfX3FtYXJrX18ocGF0dGVybiwgZXhwciwgZ3VhcmQgPSAoKSA9PiB0cnVlKSB7XG4gIHJldHVybiBfUGF0dGVybnMubWF0Y2hfbm9fdGhyb3cocGF0dGVybiwgZXhwciwgZ3VhcmQpICE9IG51bGw7XG59XG5cbmZ1bmN0aW9uIGRlZnN0cnVjdChkZWZhdWx0cykge1xuICByZXR1cm4gY2xhc3Mge1xuICAgIGNvbnN0cnVjdG9yKHVwZGF0ZSA9IHt9KSB7XG4gICAgICBsZXQgdGhlX3ZhbHVlcyA9IE9iamVjdC5hc3NpZ24oZGVmYXVsdHMsIHVwZGF0ZSk7XG4gICAgICBPYmplY3QuYXNzaWduKHRoaXMsIHRoZV92YWx1ZXMpO1xuICAgIH1cblxuICAgIHN0YXRpYyBjcmVhdGUodXBkYXRlcyA9IHt9KSB7XG4gICAgICBsZXQgeCA9IG5ldyB0aGlzKHVwZGF0ZXMpO1xuICAgICAgcmV0dXJuIE9iamVjdC5mcmVlemUoeCk7XG4gICAgfVxuICB9O1xufVxuXG5mdW5jdGlvbiBkZWZleGNlcHRpb24oZGVmYXVsdHMpIHtcbiAgcmV0dXJuIGNsYXNzIGV4dGVuZHMgRXJyb3Ige1xuICAgIGNvbnN0cnVjdG9yKHVwZGF0ZSA9IHt9KSB7XG4gICAgICBsZXQgbWVzc2FnZSA9IHVwZGF0ZS5tZXNzYWdlIHx8ICcnO1xuICAgICAgc3VwZXIobWVzc2FnZSk7XG5cbiAgICAgIGxldCB0aGVfdmFsdWVzID0gT2JqZWN0LmFzc2lnbihkZWZhdWx0cywgdXBkYXRlKTtcbiAgICAgIE9iamVjdC5hc3NpZ24odGhpcywgdGhlX3ZhbHVlcyk7XG5cbiAgICAgIHRoaXMubmFtZSA9IHRoaXMuY29uc3RydWN0b3IubmFtZTtcbiAgICAgIHRoaXMubWVzc2FnZSA9IG1lc3NhZ2U7XG4gICAgICB0aGlzW1NwZWNpYWxGb3Jtcy5hdG9tKCdfX2V4Y2VwdGlvbl9fJyldID0gdHJ1ZTtcbiAgICAgIEVycm9yLmNhcHR1cmVTdGFja1RyYWNlKHRoaXMsIHRoaXMuY29uc3RydWN0b3IubmFtZSk7XG4gICAgfVxuXG4gICAgc3RhdGljIGNyZWF0ZSh1cGRhdGVzID0ge30pIHtcbiAgICAgIGxldCB4ID0gbmV3IHRoaXModXBkYXRlcyk7XG4gICAgICByZXR1cm4gT2JqZWN0LmZyZWV6ZSh4KTtcbiAgICB9XG4gIH07XG59XG5cbmZ1bmN0aW9uIGRlZnByb3RvY29sKHNwZWMpIHtcbiAgcmV0dXJuIG5ldyBQcm90b2NvbChzcGVjKTtcbn1cblxuZnVuY3Rpb24gZGVmaW1wbChwcm90b2NvbCwgdHlwZSwgaW1wbCkge1xuICBwcm90b2NvbC5pbXBsZW1lbnRhdGlvbih0eXBlLCBpbXBsKTtcbn1cblxudmFyIEtlcm5lbCA9IHtcbiAgU3BlY2lhbEZvcm1zLFxuICB0bCxcbiAgaGQsXG4gIGlzX25pbCxcbiAgaXNfYXRvbSxcbiAgaXNfYmluYXJ5LFxuICBpc19ib29sZWFuLFxuICBpc19mdW5jdGlvbixcbiAgaXNfZmxvYXQsXG4gIGlzX2ludGVnZXIsXG4gIGlzX2xpc3QsXG4gIGlzX21hcCxcbiAgaXNfbnVtYmVyLFxuICBpc190dXBsZSxcbiAgbGVuZ3RoOiBfbGVuZ3RoLFxuICBpc19waWQsXG4gIGlzX3BvcnQsXG4gIGlzX3JlZmVyZW5jZSxcbiAgaXNfYml0c3RyaW5nLFxuICBpbjogX19pbl9fLFxuICBhYnMsXG4gIHJvdW5kLFxuICBlbGVtLFxuICByZW0sXG4gIGRpdixcbiAgYW5kLFxuICBvcixcbiAgbm90LFxuICBhcHBseSxcbiAgdG9fc3RyaW5nLFxuICBtYXRjaF9fcW1hcmtfXyxcbiAgZGVmc3RydWN0LFxuICBkZWZwcm90b2NvbCxcbiAgZGVmaW1wbFxufTtcblxubGV0IEVudW0gPSB7XG5cbiAgYWxsX19xbWFya19fOiBmdW5jdGlvbiAoY29sbGVjdGlvbiwgZnVuID0geCA9PiB4KSB7XG4gICAgZm9yIChsZXQgZWxlbSBvZiBjb2xsZWN0aW9uKSB7XG4gICAgICBpZiAoIWZ1bihlbGVtKSkge1xuICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICB9XG4gICAgfVxuXG4gICAgcmV0dXJuIHRydWU7XG4gIH0sXG5cbiAgYW55X19xbWFya19fOiBmdW5jdGlvbiAoY29sbGVjdGlvbiwgZnVuID0geCA9PiB4KSB7XG4gICAgZm9yIChsZXQgZWxlbSBvZiBjb2xsZWN0aW9uKSB7XG4gICAgICBpZiAoZnVuKGVsZW0pKSB7XG4gICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgfVxuICAgIH1cblxuICAgIHJldHVybiBmYWxzZTtcbiAgfSxcblxuICBhdDogZnVuY3Rpb24gKGNvbGxlY3Rpb24sIG4sIHRoZV9kZWZhdWx0ID0gbnVsbCkge1xuICAgIGlmIChuID4gdGhpcy5jb3VudChjb2xsZWN0aW9uKSB8fCBuIDwgMCkge1xuICAgICAgcmV0dXJuIHRoZV9kZWZhdWx0O1xuICAgIH1cblxuICAgIHJldHVybiBjb2xsZWN0aW9uW25dO1xuICB9LFxuXG4gIGNvbmNhdDogZnVuY3Rpb24gKC4uLmVudW1hYmxlcykge1xuICAgIHJldHVybiBlbnVtYWJsZXNbMF0uY29uY2F0KGVudW1hYmxlc1sxXSk7XG4gIH0sXG5cbiAgY291bnQ6IGZ1bmN0aW9uIChjb2xsZWN0aW9uLCBmdW4gPSBudWxsKSB7XG4gICAgaWYgKGZ1biA9PSBudWxsKSB7XG4gICAgICByZXR1cm4gY29sbGVjdGlvbi5sZW5ndGg7XG4gICAgfSBlbHNlIHtcbiAgICAgIHJldHVybiBjb2xsZWN0aW9uLmZpbHRlcihmdW4pLmxlbmd0aDtcbiAgICB9XG4gIH0sXG5cbiAgZHJvcDogZnVuY3Rpb24gKGNvbGxlY3Rpb24sIGNvdW50KSB7XG4gICAgcmV0dXJuIGNvbGxlY3Rpb24uc2xpY2UoY291bnQpO1xuICB9LFxuXG4gIGRyb3Bfd2hpbGU6IGZ1bmN0aW9uIChjb2xsZWN0aW9uLCBmdW4pIHtcbiAgICBsZXQgY291bnQgPSAwO1xuXG4gICAgZm9yIChsZXQgZWxlbSBvZiBjb2xsZWN0aW9uKSB7XG4gICAgICBpZiAoZnVuKGVsZW0pKSB7XG4gICAgICAgIGNvdW50ID0gY291bnQgKyAxO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgYnJlYWs7XG4gICAgICB9XG4gICAgfVxuXG4gICAgcmV0dXJuIGNvbGxlY3Rpb24uc2xpY2UoY291bnQpO1xuICB9LFxuXG4gIGVhY2g6IGZ1bmN0aW9uIChjb2xsZWN0aW9uLCBmdW4pIHtcbiAgICBmb3IgKGxldCBlbGVtIG9mIGNvbGxlY3Rpb24pIHtcbiAgICAgIGZ1bihlbGVtKTtcbiAgICB9XG4gIH0sXG5cbiAgZW1wdHlfX3FtYXJrX186IGZ1bmN0aW9uIChjb2xsZWN0aW9uKSB7XG4gICAgcmV0dXJuIGNvbGxlY3Rpb24ubGVuZ3RoID09PSAwO1xuICB9LFxuXG4gIGZldGNoOiBmdW5jdGlvbiAoY29sbGVjdGlvbiwgbikge1xuICAgIGlmIChLZXJuZWwuaXNfbGlzdChjb2xsZWN0aW9uKSkge1xuICAgICAgaWYgKG4gPCB0aGlzLmNvdW50KGNvbGxlY3Rpb24pICYmIG4gPj0gMCkge1xuICAgICAgICByZXR1cm4gS2VybmVsLlNwZWNpYWxGb3Jtcy50dXBsZShLZXJuZWwuU3BlY2lhbEZvcm1zLmF0b20oXCJva1wiKSwgY29sbGVjdGlvbltuXSk7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICByZXR1cm4gS2VybmVsLlNwZWNpYWxGb3Jtcy5hdG9tKFwiZXJyb3JcIik7XG4gICAgICB9XG4gICAgfVxuXG4gICAgdGhyb3cgbmV3IEVycm9yKFwiY29sbGVjdGlvbiBpcyBub3QgYW4gRW51bWVyYWJsZVwiKTtcbiAgfSxcblxuICBmZXRjaF9fZW1hcmtfXzogZnVuY3Rpb24gKGNvbGxlY3Rpb24sIG4pIHtcbiAgICBpZiAoS2VybmVsLmlzX2xpc3QoY29sbGVjdGlvbikpIHtcbiAgICAgIGlmIChuIDwgdGhpcy5jb3VudChjb2xsZWN0aW9uKSAmJiBuID49IDApIHtcbiAgICAgICAgcmV0dXJuIGNvbGxlY3Rpb25bbl07XG4gICAgICB9IGVsc2Uge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoXCJvdXQgb2YgYm91bmRzIGVycm9yXCIpO1xuICAgICAgfVxuICAgIH1cblxuICAgIHRocm93IG5ldyBFcnJvcihcImNvbGxlY3Rpb24gaXMgbm90IGFuIEVudW1lcmFibGVcIik7XG4gIH0sXG5cbiAgZmlsdGVyOiBmdW5jdGlvbiAoY29sbGVjdGlvbiwgZnVuKSB7XG4gICAgbGV0IHJlc3VsdCA9IFtdO1xuXG4gICAgZm9yIChsZXQgZWxlbSBvZiBjb2xsZWN0aW9uKSB7XG4gICAgICBpZiAoZnVuKGVsZW0pKSB7XG4gICAgICAgIHJlc3VsdC5wdXNoKGVsZW0pO1xuICAgICAgfVxuICAgIH1cblxuICAgIHJldHVybiByZXN1bHQ7XG4gIH0sXG5cbiAgZmlsdGVyX21hcDogZnVuY3Rpb24gKGNvbGxlY3Rpb24sIGZpbHRlciwgbWFwcGVyKSB7XG4gICAgcmV0dXJuIEVudW0ubWFwKEVudW0uZmlsdGVyKGNvbGxlY3Rpb24sIGZpbHRlciksIG1hcHBlcik7XG4gIH0sXG5cbiAgZmluZDogZnVuY3Rpb24gKGNvbGxlY3Rpb24sIGlmX25vbmUgPSBudWxsLCBmdW4pIHtcbiAgICBmb3IgKGxldCBlbGVtIG9mIGNvbGxlY3Rpb24pIHtcbiAgICAgIGlmIChmdW4oZWxlbSkpIHtcbiAgICAgICAgcmV0dXJuIGVsZW07XG4gICAgICB9XG4gICAgfVxuXG4gICAgcmV0dXJuIGlmX25vbmU7XG4gIH0sXG5cbiAgaW50bzogZnVuY3Rpb24gKGNvbGxlY3Rpb24sIGxpc3QpIHtcbiAgICByZXR1cm4gbGlzdC5jb25jYXQoY29sbGVjdGlvbik7XG4gIH0sXG5cbiAgbWFwOiBmdW5jdGlvbiAoY29sbGVjdGlvbiwgZnVuKSB7XG4gICAgbGV0IHJlc3VsdCA9IFtdO1xuXG4gICAgZm9yIChsZXQgZWxlbSBvZiBjb2xsZWN0aW9uKSB7XG4gICAgICByZXN1bHQucHVzaChmdW4oZWxlbSkpO1xuICAgIH1cblxuICAgIHJldHVybiByZXN1bHQ7XG4gIH0sXG5cbiAgbWFwX3JlZHVjZTogZnVuY3Rpb24gKGNvbGxlY3Rpb24sIGFjYywgZnVuKSB7XG4gICAgbGV0IG1hcHBlZCA9IEtlcm5lbC5TcGVjaWFsRm9ybXMubGlzdCgpO1xuICAgIGxldCB0aGVfYWNjID0gYWNjO1xuXG4gICAgZm9yICh2YXIgaSA9IDA7IGkgPCB0aGlzLmNvdW50KGNvbGxlY3Rpb24pOyBpKyspIHtcbiAgICAgIGxldCB0dXBsZSA9IGZ1bihjb2xsZWN0aW9uW2ldLCB0aGVfYWNjKTtcblxuICAgICAgdGhlX2FjYyA9IEtlcm5lbC5lbGVtKHR1cGxlLCAxKTtcbiAgICAgIG1hcHBlZCA9IEtlcm5lbC5TcGVjaWFsRm9ybXMubGlzdCguLi5tYXBwZWQuY29uY2F0KFtLZXJuZWwuZWxlbSh0dXBsZSwgMCldKSk7XG4gICAgfVxuXG4gICAgcmV0dXJuIEtlcm5lbC5TcGVjaWFsRm9ybXMudHVwbGUobWFwcGVkLCB0aGVfYWNjKTtcbiAgfSxcblxuICBtZW1iZXI6IGZ1bmN0aW9uIChjb2xsZWN0aW9uLCB2YWx1ZSkge1xuICAgIHJldHVybiBjb2xsZWN0aW9uLmluY2x1ZGVzKHZhbHVlKTtcbiAgfSxcblxuICByZWR1Y2U6IGZ1bmN0aW9uIChjb2xsZWN0aW9uLCBhY2MsIGZ1bikge1xuICAgIGxldCB0aGVfYWNjID0gYWNjO1xuXG4gICAgZm9yICh2YXIgaSA9IDA7IGkgPCB0aGlzLmNvdW50KGNvbGxlY3Rpb24pOyBpKyspIHtcbiAgICAgIGxldCB0dXBsZSA9IGZ1bihjb2xsZWN0aW9uW2ldLCB0aGVfYWNjKTtcblxuICAgICAgdGhlX2FjYyA9IEtlcm5lbC5lbGVtKHR1cGxlLCAxKTtcbiAgICB9XG5cbiAgICByZXR1cm4gdGhlX2FjYztcbiAgfSxcblxuICB0YWtlOiBmdW5jdGlvbiAoY29sbGVjdGlvbiwgY291bnQpIHtcbiAgICByZXR1cm4gY29sbGVjdGlvbi5zbGljZSgwLCBjb3VudCk7XG4gIH0sXG5cbiAgdGFrZV9ldmVyeTogZnVuY3Rpb24gKGNvbGxlY3Rpb24sIG50aCkge1xuICAgIGxldCByZXN1bHQgPSBbXTtcbiAgICBsZXQgaW5kZXggPSAwO1xuXG4gICAgZm9yIChsZXQgZWxlbSBvZiBjb2xsZWN0aW9uKSB7XG4gICAgICBpZiAoaW5kZXggJSBudGggPT09IDApIHtcbiAgICAgICAgcmVzdWx0LnB1c2goZWxlbSk7XG4gICAgICB9XG4gICAgfVxuXG4gICAgcmV0dXJuIEtlcm5lbC5TcGVjaWFsRm9ybXMubGlzdCguLi5yZXN1bHQpO1xuICB9LFxuXG4gIHRha2Vfd2hpbGU6IGZ1bmN0aW9uIChjb2xsZWN0aW9uLCBmdW4pIHtcbiAgICBsZXQgY291bnQgPSAwO1xuXG4gICAgZm9yIChsZXQgZWxlbSBvZiBjb2xsZWN0aW9uKSB7XG4gICAgICBpZiAoZnVuKGVsZW0pKSB7XG4gICAgICAgIGNvdW50ID0gY291bnQgKyAxO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgYnJlYWs7XG4gICAgICB9XG4gICAgfVxuXG4gICAgcmV0dXJuIGNvbGxlY3Rpb24uc2xpY2UoMCwgY291bnQpO1xuICB9LFxuXG4gIHRvX2xpc3Q6IGZ1bmN0aW9uIChjb2xsZWN0aW9uKSB7XG4gICAgcmV0dXJuIGNvbGxlY3Rpb247XG4gIH1cbn07XG5cbmxldCBBdG9tID0ge307XG5cbkF0b20udG9fc3RyaW5nID0gZnVuY3Rpb24gKGF0b20pIHtcbiAgcmV0dXJuIFN5bWJvbC5rZXlGb3IoYXRvbSk7XG59O1xuXG5BdG9tLnRvX2NoYXJfbGlzdCA9IGZ1bmN0aW9uIChhdG9tKSB7XG4gIHJldHVybiBBdG9tLnRvX3N0cmluZyhhdG9tKS5zcGxpdCgnJyk7XG59O1xuXG5sZXQgSW50ZWdlciA9IHtcblxuICBpc19ldmVuOiBmdW5jdGlvbiAobikge1xuICAgIHJldHVybiBuICUgMiA9PT0gMDtcbiAgfSxcblxuICBpc19vZGQ6IGZ1bmN0aW9uIChuKSB7XG4gICAgcmV0dXJuIG4gJSAyICE9PSAwO1xuICB9LFxuXG4gIHBhcnNlOiBmdW5jdGlvbiAoYmluKSB7XG4gICAgbGV0IHJlc3VsdCA9IHBhcnNlSW50KGJpbik7XG5cbiAgICBpZiAoaXNOYU4ocmVzdWx0KSkge1xuICAgICAgcmV0dXJuIEtlcm5lbC5TcGVjaWFsRm9ybXMuYXRvbShcImVycm9yXCIpO1xuICAgIH1cblxuICAgIGxldCBpbmRleE9mRG90ID0gYmluLmluZGV4T2YoXCIuXCIpO1xuXG4gICAgaWYgKGluZGV4T2ZEb3QgPj0gMCkge1xuICAgICAgcmV0dXJuIEtlcm5lbC5TcGVjaWFsRm9ybXMudHVwbGUocmVzdWx0LCBiaW4uc3Vic3RyaW5nKGluZGV4T2ZEb3QpKTtcbiAgICB9XG5cbiAgICByZXR1cm4gS2VybmVsLlNwZWNpYWxGb3Jtcy50dXBsZShyZXN1bHQsIFwiXCIpO1xuICB9LFxuXG4gIHRvX2NoYXJfbGlzdDogZnVuY3Rpb24gKG51bWJlciwgYmFzZSA9IDEwKSB7XG4gICAgcmV0dXJuIG51bWJlci50b1N0cmluZyhiYXNlKS5zcGxpdChcIlwiKTtcbiAgfSxcblxuICB0b19zdHJpbmc6IGZ1bmN0aW9uIChudW1iZXIsIGJhc2UgPSAxMCkge1xuICAgIHJldHVybiBudW1iZXIudG9TdHJpbmcoYmFzZSk7XG4gIH1cbn07XG5cbmxldCBfQ2hhcnMgPSBLZXJuZWwuZGVmcHJvdG9jb2woe1xuICB0b19zdHJpbmc6IGZ1bmN0aW9uICh0aGluZykge31cbn0pO1xuXG5LZXJuZWwuZGVmaW1wbChfQ2hhcnMsIEJpdFN0cmluZywge1xuICB0b19zdHJpbmc6IGZ1bmN0aW9uICh0aGluZykge1xuICAgIGlmIChLZXJuZWwuaXNfYmluYXJ5KHRoaW5nKSkge1xuICAgICAgcmV0dXJuIHRoaW5nO1xuICAgIH1cblxuICAgIHJldHVybiB0aGluZy50b1N0cmluZygpO1xuICB9XG59KTtcblxuS2VybmVsLmRlZmltcGwoX0NoYXJzLCBTeW1ib2wsIHtcbiAgdG9fc3RyaW5nOiBmdW5jdGlvbiAodGhpbmcpIHtcbiAgICBpZiAobmlsKSB7XG4gICAgICByZXR1cm4gXCJcIjtcbiAgICB9XG5cbiAgICByZXR1cm4gQXRvbS50b19zdHJpbmcodGhpbmcpO1xuICB9XG59KTtcblxuS2VybmVsLmRlZmltcGwoX0NoYXJzLCBJbnRlZ2VyVHlwZSwge1xuICB0b19zdHJpbmc6IGZ1bmN0aW9uICh0aGluZykge1xuICAgIHJldHVybiBJbnRlZ2VyLnRvX3N0cmluZyh0aGluZyk7XG4gIH1cbn0pO1xuXG5LZXJuZWwuZGVmaW1wbChfQ2hhcnMsIEZsb2F0VHlwZSwge1xuICB0b19zdHJpbmc6IGZ1bmN0aW9uICh0aGluZykge1xuICAgIHJldHVybiB0aGluZy50b1N0cmluZztcbiAgfVxufSk7XG5cbktlcm5lbC5kZWZpbXBsKF9DaGFycywgQXJyYXksIHtcbiAgdG9fc3RyaW5nOiBmdW5jdGlvbiAodGhpbmcpIHtcbiAgICByZXR1cm4gdGhpbmcudG9TdHJpbmcoKTtcbiAgfVxufSk7XG5cbktlcm5lbC5kZWZpbXBsKF9DaGFycywgVHVwbGUsIHtcbiAgdG9fc3RyaW5nOiBmdW5jdGlvbiAodGhpbmcpIHtcbiAgICByZXR1cm4gVHVwbGUudG9fc3RyaW5nKHRoaW5nKTtcbiAgfVxufSk7XG5cbktlcm5lbC5kZWZpbXBsKF9DaGFycywgbnVsbCwge1xuICB0b19zdHJpbmc6IGZ1bmN0aW9uICh0aGluZykge1xuICAgIHJldHVybiB0aGluZy50b1N0cmluZygpO1xuICB9XG59KTtcblxuZnVuY3Rpb24gdG9fYXRvbShzdHJpbmcpIHtcbiAgcmV0dXJuIFN5bWJvbC5mb3Ioc3RyaW5nKTtcbn1cblxuZnVuY3Rpb24gdG9fZXhpc3RpbmdfYXRvbShzdHJpbmcpIHtcbiAgcmV0dXJuIFN5bWJvbC5mb3Ioc3RyaW5nKTtcbn1cblxuZnVuY3Rpb24gdG9fY2hhcl9saXN0KHN0cmluZykge1xuICByZXR1cm4gc3RyaW5nLnNwbGl0KCcnKTtcbn1cblxuZnVuY3Rpb24gdG9fZmxvYXQoc3RyaW5nKSB7XG4gIHJldHVybiBwYXJzZUZsb2F0KHN0cmluZyk7XG59XG5cbmZ1bmN0aW9uIHRvX2ludGVnZXIoc3RyaW5nLCBiYXNlID0gMTApIHtcbiAgcmV0dXJuIHBhcnNlSW50KHN0cmluZywgYmFzZSk7XG59XG5cbmZ1bmN0aW9uIHVwY2FzZShiaW5hcnkpIHtcbiAgcmV0dXJuIGJpbmFyeS50b1VwcGVyQ2FzZSgpO1xufVxuXG5mdW5jdGlvbiBkb3duY2FzZShiaW5hcnkpIHtcbiAgcmV0dXJuIGJpbmFyeS50b0xvd2VyQ2FzZSgpO1xufVxuXG5mdW5jdGlvbiBhdChzdHJpbmcsIHBvc2l0aW9uKSB7XG4gIGlmIChwb3NpdGlvbiA+IHN0cmluZy5sZW5ndGggLSAxKSB7XG4gICAgcmV0dXJuIG51bGw7XG4gIH1cblxuICByZXR1cm4gc3RyaW5nW3Bvc2l0aW9uXTtcbn1cblxuZnVuY3Rpb24gY2FwaXRhbGl6ZShzdHJpbmcpIHtcbiAgbGV0IHJldHVyblN0cmluZyA9ICcnO1xuXG4gIGZvciAobGV0IGkgPSAwOyBpIDwgc3RyaW5nLmxlbmd0aDsgaSsrKSB7XG4gICAgaWYgKGkgPT09IDApIHtcbiAgICAgIHJldHVyblN0cmluZyA9IHJldHVyblN0cmluZyArIHN0cmluZ1tpXS50b1VwcGVyQ2FzZSgpO1xuICAgIH0gZWxzZSB7XG4gICAgICByZXR1cm5TdHJpbmcgPSByZXR1cm5TdHJpbmcgKyBzdHJpbmdbaV0udG9Mb3dlckNhc2UoKTtcbiAgICB9XG4gIH1cblxuICByZXR1cm4gcmV0dXJuU3RyaW5nO1xufVxuXG5mdW5jdGlvbiBjb2RlcG9pbnRzKHN0cmluZykge1xuICByZXR1cm4gdG9fY2hhcl9saXN0KHN0cmluZykubWFwKGZ1bmN0aW9uIChjKSB7XG4gICAgcmV0dXJuIGMuY29kZVBvaW50QXQoMCk7XG4gIH0pO1xufVxuXG5mdW5jdGlvbiBjb250YWluc19fcW1fXyhzdHJpbmcsIGNvbnRhaW5zKSB7XG4gIGlmIChBcnJheS5pc0FycmF5KGNvbnRhaW5zKSkge1xuICAgIHJldHVybiBjb250YWlucy5zb21lKGZ1bmN0aW9uIChzKSB7XG4gICAgICByZXR1cm4gc3RyaW5nLmluZGV4T2YocykgPiAtMTtcbiAgICB9KTtcbiAgfVxuXG4gIHJldHVybiBzdHJpbmcuaW5kZXhPZihjb250YWlucykgPiAtMTtcbn1cblxuZnVuY3Rpb24gZHVwbGljYXRlKHN1YmplY3QsIG4pIHtcbiAgcmV0dXJuIHN1YmplY3QucmVwZWF0KG4pO1xufVxuXG5mdW5jdGlvbiBlbmRzX3dpdGhfX3FtX18oc3RyaW5nLCBzdWZmaXhlcykge1xuICBpZiAoQXJyYXkuaXNBcnJheShzdWZmaXhlcykpIHtcbiAgICByZXR1cm4gc3VmZml4ZXMuc29tZShmdW5jdGlvbiAocykge1xuICAgICAgcmV0dXJuIHN0cmluZy5lbmRzV2l0aChzKTtcbiAgICB9KTtcbiAgfVxuXG4gIHJldHVybiBzdHJpbmcuZW5kc1dpdGgoc3VmZml4ZXMpO1xufVxuXG5mdW5jdGlvbiBmaXJzdChzdHJpbmcpIHtcbiAgaWYgKCFzdHJpbmcpIHtcbiAgICByZXR1cm4gbnVsbDtcbiAgfVxuXG4gIHJldHVybiBzdHJpbmdbMF07XG59XG5cbmZ1bmN0aW9uIGdyYXBoZW1lcyhzdHJpbmcpIHtcbiAgcmV0dXJuIHN0cmluZy5zcGxpdCgnJyk7XG59XG5cbmZ1bmN0aW9uIGxhc3Qoc3RyaW5nKSB7XG4gIGlmICghc3RyaW5nKSB7XG4gICAgcmV0dXJuIG51bGw7XG4gIH1cblxuICByZXR1cm4gc3RyaW5nW3N0cmluZy5sZW5ndGggLSAxXTtcbn1cblxuZnVuY3Rpb24gbGVuZ3RoKHN0cmluZykge1xuICByZXR1cm4gc3RyaW5nLmxlbmd0aDtcbn1cblxuZnVuY3Rpb24gbWF0Y2hfX3FtX18oc3RyaW5nLCByZWdleCkge1xuICByZXR1cm4gc3RyaW5nLm1hdGNoKHJlZ2V4KSAhPSBudWxsO1xufVxuXG5mdW5jdGlvbiBuZXh0X2NvZGVwb2ludChzdHJpbmcpIHtcbiAgaWYgKCFzdHJpbmcgfHwgc3RyaW5nID09PSAnJykge1xuICAgIHJldHVybiBudWxsO1xuICB9XG5cbiAgcmV0dXJuIEtlcm5lbC5TcGVjaWFsRm9ybXMudHVwbGUoc3RyaW5nWzBdLmNvZGVQb2ludEF0KDApLCBzdHJpbmcuc3Vic3RyKDEpKTtcbn1cblxuZnVuY3Rpb24gbmV4dF9ncmFwaGVtZShzdHJpbmcpIHtcbiAgaWYgKCFzdHJpbmcgfHwgc3RyaW5nID09PSAnJykge1xuICAgIHJldHVybiBudWxsO1xuICB9XG5cbiAgcmV0dXJuIEtlcm5lbC5TcGVjaWFsRm9ybXMudHVwbGUoc3RyaW5nWzBdLCBzdHJpbmcuc3Vic3RyKDEpKTtcbn1cblxuZnVuY3Rpb24gcmV2ZXJzZShzdHJpbmcpIHtcbiAgbGV0IHJldHVyblZhbHVlID0gJyc7XG5cbiAgZm9yICh2YXIgaSA9IHN0cmluZy5sZW5ndGggLSAxOyBpID49IDA7IGktLSkge1xuICAgIHJldHVyblZhbHVlID0gcmV0dXJuVmFsdWUgKyBzdHJpbmdbaV07XG4gIH07XG5cbiAgcmV0dXJuIHJldHVyblZhbHVlO1xufVxuXG5mdW5jdGlvbiBfc3BsaXQoc3RyaW5nKSB7XG4gIHJldHVybiBzdHJpbmcuc3BsaXQoKTtcbn1cblxuZnVuY3Rpb24gc3RhcnRzX3dpdGhfX3FtX18oc3RyaW5nLCBwcmVmaXhlcykge1xuICBpZiAoQXJyYXkuaXNBcnJheShwcmVmaXhlcykpIHtcbiAgICByZXR1cm4gcHJlZml4ZXMuc29tZShmdW5jdGlvbiAocykge1xuICAgICAgcmV0dXJuIHN0cmluZy5zdGFydHNXaXRoKHMpO1xuICAgIH0pO1xuICB9XG5cbiAgcmV0dXJuIHN0cmluZy5zdGFydHNXaXRoKHByZWZpeGVzKTtcbn1cblxuZnVuY3Rpb24gdmFsaWRfY2hhcmFjdGVyX19xbV9fKGNvZGVwb2ludCkge1xuICB0cnkge1xuICAgIHJldHVybiBTdHJpbmcuZnJvbUNvZGVQb2ludChjb2RlcG9pbnQpICE9IG51bGw7XG4gIH0gY2F0Y2ggKGUpIHtcbiAgICByZXR1cm4gZmFsc2U7XG4gIH1cbn1cblxudmFyIF9TdHJpbmcgPSB7XG4gIGF0LFxuICBjYXBpdGFsaXplLFxuICBjb2RlcG9pbnRzLFxuICBjb250YWluc19fcW1fXyxcbiAgZG93bmNhc2UsXG4gIGR1cGxpY2F0ZSxcbiAgZW5kc193aXRoX19xbV9fLFxuICBmaXJzdCxcbiAgZ3JhcGhlbWVzLFxuICBsYXN0LFxuICBsZW5ndGgsXG4gIG1hdGNoX19xbV9fLFxuICBuZXh0X2NvZGVwb2ludCxcbiAgbmV4dF9ncmFwaGVtZSxcbiAgcmV2ZXJzZSxcbiAgc3BsaXQ6IF9zcGxpdCxcbiAgc3RhcnRzX3dpdGhfX3FtX18sXG4gIHRvX2F0b20sXG4gIHRvX2NoYXJfbGlzdCxcbiAgdG9fZXhpc3RpbmdfYXRvbSxcbiAgdG9fZmxvYXQsXG4gIHRvX2ludGVnZXIsXG4gIHVwY2FzZSxcbiAgdmFsaWRfY2hhcmFjdGVyX19xbV9fLFxuICBDaGFyczogX0NoYXJzXG59O1xuXG5sZXQgQ2hhcnMgPSBLZXJuZWwuZGVmcHJvdG9jb2woe1xuICB0b19jaGFyX2xpc3Q6IGZ1bmN0aW9uICh0aGluZykge31cbn0pO1xuXG5LZXJuZWwuZGVmaW1wbChDaGFycywgS2VybmVsLmlzX2JpdHN0cmluZywge1xuICB0b19jaGFyX2xpc3Q6IGZ1bmN0aW9uICh0aGluZykge1xuICAgIGlmIChLZXJuZWwuaXNfYmluYXJ5KHRoaW5nKSkge1xuICAgICAgcmV0dXJuIF9TdHJpbmcudG9fY2hhcl9saXN0KHRoaW5nKTtcbiAgICB9XG5cbiAgICByZXR1cm4gdGhpbmcudG9TdHJpbmcoKTtcbiAgfVxufSk7XG5cbktlcm5lbC5kZWZpbXBsKENoYXJzLCBLZXJuZWwuaXNfYXRvbSwge1xuICB0b19jaGFyX2xpc3Q6IGZ1bmN0aW9uICh0aGluZykge1xuICAgIHJldHVybiBBdG9tLnRvX2NoYXJfbGlzdCh0aGluZyk7XG4gIH1cbn0pO1xuXG5LZXJuZWwuZGVmaW1wbChDaGFycywgS2VybmVsLmlzX2ludGVnZXIsIHtcbiAgdG9fY2hhcl9saXN0OiBmdW5jdGlvbiAodGhpbmcpIHtcbiAgICByZXR1cm4gSW50ZWdlci50b19jaGFyX2xpc3QodGhpbmcpO1xuICB9XG59KTtcblxuS2VybmVsLmRlZmltcGwoQ2hhcnMsIEtlcm5lbC5pc19saXN0LCB7XG4gIHRvX2NoYXJfbGlzdDogZnVuY3Rpb24gKHRoaW5nKSB7XG4gICAgcmV0dXJuIHRoaW5nO1xuICB9XG59KTtcblxubGV0IExpc3QgPSB7fTtcblxuTGlzdC5DaGFycyA9IENoYXJzO1xuXG5MaXN0LmRlbGV0ZSA9IGZ1bmN0aW9uIChsaXN0LCBpdGVtKSB7XG4gIGxldCBuZXdfdmFsdWUgPSBbXTtcbiAgbGV0IHZhbHVlX2ZvdW5kID0gZmFsc2U7XG5cbiAgZm9yIChsZXQgeCBvZiBsaXN0KSB7XG4gICAgaWYgKHggPT09IGl0ZW0gJiYgdmFsdWVfZm91bmQgIT09IGZhbHNlKSB7XG4gICAgICBuZXdfdmFsdWUucHVzaCh4KTtcbiAgICAgIHZhbHVlX2ZvdW5kID0gdHJ1ZTtcbiAgICB9IGVsc2UgaWYgKHggIT09IGl0ZW0pIHtcbiAgICAgIG5ld192YWx1ZS5wdXNoKHgpO1xuICAgIH1cbiAgfVxuXG4gIHJldHVybiBLZXJuZWwuU3BlY2lhbEZvcm1zLmxpc3QoLi4ubmV3X3ZhbHVlKTtcbn07XG5cbkxpc3QuZGVsZXRlX2F0ID0gZnVuY3Rpb24gKGxpc3QsIGluZGV4KSB7XG4gIGxldCBuZXdfdmFsdWUgPSBbXTtcblxuICBmb3IgKGxldCBpID0gMDsgaSA8IGxpc3QubGVuZ3RoOyBpKyspIHtcbiAgICBpZiAoaSAhPT0gaW5kZXgpIHtcbiAgICAgIG5ld192YWx1ZS5wdXNoKGxpc3RbaV0pO1xuICAgIH1cbiAgfVxuXG4gIHJldHVybiBLZXJuZWwuU3BlY2lhbEZvcm1zLmxpc3QoLi4ubmV3X3ZhbHVlKTtcbn07XG5cbkxpc3QuZHVwbGljYXRlID0gZnVuY3Rpb24gKGVsZW0sIG4pIHtcbiAgbGV0IG5ld192YWx1ZSA9IFtdO1xuXG4gIGZvciAodmFyIGkgPSAwOyBpIDwgbjsgaSsrKSB7XG4gICAgbmV3X3ZhbHVlLnB1c2goZWxlbSk7XG4gIH1cblxuICByZXR1cm4gS2VybmVsLlNwZWNpYWxGb3Jtcy5saXN0KC4uLm5ld192YWx1ZSk7XG59O1xuXG5MaXN0LmZpcnN0ID0gZnVuY3Rpb24gKGxpc3QpIHtcbiAgcmV0dXJuIGxpc3RbMF07XG59O1xuXG5MaXN0LmZsYXR0ZW4gPSBmdW5jdGlvbiAobGlzdCwgdGFpbCA9IEtlcm5lbC5TcGVjaWFsRm9ybXMubGlzdCgpKSB7XG4gIGxldCBuZXdfdmFsdWUgPSBbXTtcblxuICBmb3IgKGxldCB4IG9mIGxpc3QpIHtcbiAgICBpZiAoS2VybmVsLmlzX2xpc3QoeCkpIHtcbiAgICAgIG5ld192YWx1ZSA9IG5ld192YWx1ZS5jb25jYXQoTGlzdC5mbGF0dGVuKHgpKTtcbiAgICB9IGVsc2Uge1xuICAgICAgbmV3X3ZhbHVlLnB1c2goeCk7XG4gICAgfVxuICB9XG5cbiAgbmV3X3ZhbHVlID0gbmV3X3ZhbHVlLmNvbmNhdCh0YWlsKTtcblxuICByZXR1cm4gS2VybmVsLlNwZWNpYWxGb3Jtcy5saXN0KC4uLm5ld192YWx1ZSk7XG59O1xuXG5MaXN0LmZvbGRsID0gZnVuY3Rpb24gKGxpc3QsIGFjYywgZnVuYykge1xuICByZXR1cm4gbGlzdC5yZWR1Y2UoZnVuYywgYWNjKTtcbn07XG5cbkxpc3QuZm9sZHIgPSBmdW5jdGlvbiAobGlzdCwgYWNjLCBmdW5jKSB7XG4gIGxldCBuZXdfYWNjID0gYWNjO1xuXG4gIGZvciAodmFyIGkgPSBsaXN0Lmxlbmd0aCAtIDE7IGkgPj0gMDsgaS0tKSB7XG4gICAgbmV3X2FjYyA9IGZ1bmMobGlzdFtpXSwgbmV3X2FjYyk7XG4gIH1cblxuICByZXR1cm4gbmV3X2FjYztcbn07XG5cbkxpc3QuaW5zZXJ0X2F0ID0gZnVuY3Rpb24gKGxpc3QsIGluZGV4LCB2YWx1ZSkge1xuICBsZXQgbmV3X3ZhbHVlID0gW107XG5cbiAgZm9yIChsZXQgaSA9IDA7IGkgPCBsaXN0Lmxlbmd0aDsgaSsrKSB7XG4gICAgaWYgKGkgPT09IGluZGV4KSB7XG4gICAgICBuZXdfdmFsdWUucHVzaCh2YWx1ZSk7XG4gICAgICBuZXdfdmFsdWUucHVzaChsaXN0W2ldKTtcbiAgICB9IGVsc2Uge1xuICAgICAgbmV3X3ZhbHVlLnB1c2gobGlzdFtpXSk7XG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIEtlcm5lbC5TcGVjaWFsRm9ybXMubGlzdCguLi5uZXdfdmFsdWUpO1xufTtcblxuTGlzdC5rZXlkZWxldGUgPSBmdW5jdGlvbiAobGlzdCwga2V5LCBwb3NpdGlvbikge1xuICBsZXQgbmV3X2xpc3QgPSBbXTtcblxuICBmb3IgKGxldCBpID0gMDsgaSA8IGxpc3QubGVuZ3RoOyBpKyspIHtcbiAgICBpZiAoIUtlcm5lbC5tYXRjaF9fcW1hcmtfXyhsaXN0W2ldW3Bvc2l0aW9uXSwga2V5KSkge1xuICAgICAgbmV3X2xpc3QucHVzaChsaXN0W2ldKTtcbiAgICB9XG4gIH1cblxuICByZXR1cm4gS2VybmVsLlNwZWNpYWxGb3Jtcy5saXN0KC4uLm5ld19saXN0KTtcbn07XG5cbkxpc3Qua2V5ZmluZCA9IGZ1bmN0aW9uIChsaXN0LCBrZXksIHBvc2l0aW9uLCBfZGVmYXVsdCA9IG51bGwpIHtcblxuICBmb3IgKGxldCBpID0gMDsgaSA8IGxpc3QubGVuZ3RoOyBpKyspIHtcbiAgICBpZiAoS2VybmVsLm1hdGNoX19xbWFya19fKGxpc3RbaV1bcG9zaXRpb25dLCBrZXkpKSB7XG4gICAgICByZXR1cm4gbGlzdFtpXTtcbiAgICB9XG4gIH1cblxuICByZXR1cm4gX2RlZmF1bHQ7XG59O1xuXG5MaXN0LmtleW1lbWJlcl9fcW1hcmtfXyA9IGZ1bmN0aW9uIChsaXN0LCBrZXksIHBvc2l0aW9uKSB7XG5cbiAgZm9yIChsZXQgaSA9IDA7IGkgPCBsaXN0Lmxlbmd0aDsgaSsrKSB7XG4gICAgaWYgKEtlcm5lbC5tYXRjaF9fcW1hcmtfXyhsaXN0W2ldW3Bvc2l0aW9uXSwga2V5KSkge1xuICAgICAgcmV0dXJuIHRydWU7XG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIGZhbHNlO1xufTtcblxuTGlzdC5rZXlyZXBsYWNlID0gZnVuY3Rpb24gKGxpc3QsIGtleSwgcG9zaXRpb24sIG5ld190dXBsZSkge1xuICBsZXQgbmV3X2xpc3QgPSBbXTtcblxuICBmb3IgKGxldCBpID0gMDsgaSA8IGxpc3QubGVuZ3RoOyBpKyspIHtcbiAgICBpZiAoIUtlcm5lbC5tYXRjaF9fcW1hcmtfXyhsaXN0W2ldW3Bvc2l0aW9uXSwga2V5KSkge1xuICAgICAgbmV3X2xpc3QucHVzaChsaXN0W2ldKTtcbiAgICB9IGVsc2Uge1xuICAgICAgbmV3X2xpc3QucHVzaChuZXdfdHVwbGUpO1xuICAgIH1cbiAgfVxuXG4gIHJldHVybiBLZXJuZWwuU3BlY2lhbEZvcm1zLmxpc3QoLi4ubmV3X2xpc3QpO1xufTtcblxuTGlzdC5rZXlzb3J0ID0gZnVuY3Rpb24gKGxpc3QsIHBvc2l0aW9uKSB7XG4gIGxldCBuZXdfbGlzdCA9IGxpc3Q7XG5cbiAgbmV3X2xpc3Quc29ydChmdW5jdGlvbiAoYSwgYikge1xuICAgIGlmIChwb3NpdGlvbiA9PT0gMCkge1xuICAgICAgaWYgKGFbcG9zaXRpb25dLnZhbHVlIDwgYltwb3NpdGlvbl0udmFsdWUpIHtcbiAgICAgICAgcmV0dXJuIC0xO1xuICAgICAgfVxuXG4gICAgICBpZiAoYVtwb3NpdGlvbl0udmFsdWUgPiBiW3Bvc2l0aW9uXS52YWx1ZSkge1xuICAgICAgICByZXR1cm4gMTtcbiAgICAgIH1cblxuICAgICAgcmV0dXJuIDA7XG4gICAgfSBlbHNlIHtcbiAgICAgIGlmIChhW3Bvc2l0aW9uXSA8IGJbcG9zaXRpb25dKSB7XG4gICAgICAgIHJldHVybiAtMTtcbiAgICAgIH1cblxuICAgICAgaWYgKGFbcG9zaXRpb25dID4gYltwb3NpdGlvbl0pIHtcbiAgICAgICAgcmV0dXJuIDE7XG4gICAgICB9XG5cbiAgICAgIHJldHVybiAwO1xuICAgIH1cbiAgfSk7XG5cbiAgcmV0dXJuIEtlcm5lbC5TcGVjaWFsRm9ybXMubGlzdCguLi5uZXdfbGlzdCk7XG59O1xuXG5MaXN0LmtleXN0b3JlID0gZnVuY3Rpb24gKGxpc3QsIGtleSwgcG9zaXRpb24sIG5ld190dXBsZSkge1xuICBsZXQgbmV3X2xpc3QgPSBbXTtcbiAgbGV0IHJlcGxhY2VkID0gZmFsc2U7XG5cbiAgZm9yIChsZXQgaSA9IDA7IGkgPCBsaXN0Lmxlbmd0aDsgaSsrKSB7XG4gICAgaWYgKCFLZXJuZWwubWF0Y2hfX3FtYXJrX18obGlzdFtpXVtwb3NpdGlvbl0sIGtleSkpIHtcbiAgICAgIG5ld19saXN0LnB1c2gobGlzdFtpXSk7XG4gICAgfSBlbHNlIHtcbiAgICAgIG5ld19saXN0LnB1c2gobmV3X3R1cGxlKTtcbiAgICAgIHJlcGxhY2VkID0gdHJ1ZTtcbiAgICB9XG4gIH1cblxuICBpZiAoIXJlcGxhY2VkKSB7XG4gICAgbmV3X2xpc3QucHVzaChuZXdfdHVwbGUpO1xuICB9XG5cbiAgcmV0dXJuIEtlcm5lbC5TcGVjaWFsRm9ybXMubGlzdCguLi5uZXdfbGlzdCk7XG59O1xuXG5MaXN0Lmxhc3QgPSBmdW5jdGlvbiAobGlzdCkge1xuICByZXR1cm4gbGlzdFtsaXN0Lmxlbmd0aCAtIDFdO1xufTtcblxuTGlzdC5yZXBsYWNlX2F0ID0gZnVuY3Rpb24gKGxpc3QsIGluZGV4LCB2YWx1ZSkge1xuICBsZXQgbmV3X3ZhbHVlID0gW107XG5cbiAgZm9yIChsZXQgaSA9IDA7IGkgPCBsaXN0Lmxlbmd0aDsgaSsrKSB7XG4gICAgaWYgKGkgPT09IGluZGV4KSB7XG4gICAgICBuZXdfdmFsdWUucHVzaCh2YWx1ZSk7XG4gICAgfSBlbHNlIHtcbiAgICAgIG5ld192YWx1ZS5wdXNoKGxpc3RbaV0pO1xuICAgIH1cbiAgfVxuXG4gIHJldHVybiBLZXJuZWwuU3BlY2lhbEZvcm1zLmxpc3QoLi4ubmV3X3ZhbHVlKTtcbn07XG5cbkxpc3QudXBkYXRlX2F0ID0gZnVuY3Rpb24gKGxpc3QsIGluZGV4LCBmdW4pIHtcbiAgbGV0IG5ld192YWx1ZSA9IFtdO1xuXG4gIGZvciAobGV0IGkgPSAwOyBpIDwgbGlzdC5jb3VudCgpOyBpKyspIHtcbiAgICBpZiAoaSA9PT0gaW5kZXgpIHtcbiAgICAgIG5ld192YWx1ZS5wdXNoKGZ1bihsaXN0LmdldChpKSkpO1xuICAgIH0gZWxzZSB7XG4gICAgICBuZXdfdmFsdWUucHVzaChsaXN0LmdldChpKSk7XG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIG5ld192YWx1ZTtcbn07XG5cbkxpc3Qud3JhcCA9IGZ1bmN0aW9uIChsaXN0KSB7XG4gIGlmIChLZXJuZWwuaXNfbGlzdChsaXN0KSkge1xuICAgIHJldHVybiBsaXN0O1xuICB9IGVsc2UgaWYgKGxpc3QgPT0gbnVsbCkge1xuICAgIHJldHVybiBLZXJuZWwuU3BlY2lhbEZvcm1zLmxpc3QoKTtcbiAgfSBlbHNlIHtcbiAgICByZXR1cm4gS2VybmVsLlNwZWNpYWxGb3Jtcy5saXN0KGxpc3QpO1xuICB9XG59O1xuXG5MaXN0LnppcCA9IGZ1bmN0aW9uIChsaXN0X29mX2xpc3RzKSB7XG4gIGlmIChsaXN0X29mX2xpc3RzLmxlbmd0aCA9PT0gMCkge1xuICAgIHJldHVybiBLZXJuZWwuU3BlY2lhbEZvcm1zLmxpc3QoKTtcbiAgfVxuXG4gIGxldCBuZXdfdmFsdWUgPSBbXTtcbiAgbGV0IHNtYWxsZXN0X2xlbmd0aCA9IGxpc3Rfb2ZfbGlzdHNbMF07XG5cbiAgZm9yIChsZXQgeCBvZiBsaXN0X29mX2xpc3RzKSB7XG4gICAgaWYgKHgubGVuZ3RoIDwgc21hbGxlc3RfbGVuZ3RoKSB7XG4gICAgICBzbWFsbGVzdF9sZW5ndGggPSB4Lmxlbmd0aDtcbiAgICB9XG4gIH1cblxuICBmb3IgKGxldCBpID0gMDsgaSA8IHNtYWxsZXN0X2xlbmd0aDsgaSsrKSB7XG4gICAgbGV0IGN1cnJlbnRfdmFsdWUgPSBbXTtcbiAgICBmb3IgKGxldCBqID0gMDsgaiA8IGxpc3Rfb2ZfbGlzdHMubGVuZ3RoOyBqKyspIHtcbiAgICAgIGN1cnJlbnRfdmFsdWUucHVzaChsaXN0X29mX2xpc3RzW2pdW2ldKTtcbiAgICB9XG5cbiAgICBuZXdfdmFsdWUucHVzaChLZXJuZWwuU3BlY2lhbEZvcm1zLnR1cGxlKC4uLmN1cnJlbnRfdmFsdWUpKTtcbiAgfVxuXG4gIHJldHVybiBLZXJuZWwuU3BlY2lhbEZvcm1zLmxpc3QoLi4ubmV3X3ZhbHVlKTtcbn07XG5cbkxpc3QudG9fdHVwbGUgPSBmdW5jdGlvbiAobGlzdCkge1xuICByZXR1cm4gS2VybmVsLlNwZWNpYWxGb3Jtcy50dXBsZS5hcHBseShudWxsLCBsaXN0KTtcbn07XG5cbkxpc3QuYXBwZW5kID0gZnVuY3Rpb24gKGxpc3QsIHZhbHVlKSB7XG4gIHJldHVybiBLZXJuZWwuU3BlY2lhbEZvcm1zLmxpc3QoLi4ubGlzdC5jb25jYXQoW3ZhbHVlXSkpO1xufTtcblxuTGlzdC5wcmVwZW5kID0gZnVuY3Rpb24gKGxpc3QsIHZhbHVlKSB7XG4gIHJldHVybiBLZXJuZWwuU3BlY2lhbEZvcm1zLmxpc3QoLi4uW3ZhbHVlXS5jb25jYXQobGlzdCkpO1xufTtcblxuTGlzdC5jb25jYXQgPSBmdW5jdGlvbiAobGVmdCwgcmlnaHQpIHtcbiAgcmV0dXJuIGxlZnQuY29uY2F0KHJpZ2h0KTtcbn07XG5cbmNsYXNzIFNpZ25hbCB7XG5cbiAgY29uc3RydWN0b3IoKSB7XG4gICAgdGhpcy5iaW5kaW5ncyA9IFNwZWNpYWxGb3Jtcy5saXN0KCk7XG4gIH1cblxuICBhZGQobGlzdGVuZXIsIGNvbnRleHQgPSB0aGlzKSB7XG4gICAgdGhpcy5iaW5kaW5ncyA9IExpc3QuYXBwZW5kKHRoaXMuYmluZGluZ3MsIG5ldyBTaWduYWxCaW5kaW5nKHRoaXMsIGxpc3RlbmVyLCBjb250ZXh0KSk7XG4gIH1cblxuICByZW1vdmUobGlzdGVuZXIpIHtcbiAgICB0aGlzLmJpbmRpbmdzID0gRW51bS5maWx0ZXIodGhpcy5iaW5kaW5ncywgZnVuY3Rpb24gKGJpbmRpbmcpIHtcbiAgICAgIHJldHVybiBiaW5kaW5nLmxpc3RlbmVyICE9PSBsaXN0ZW5lcjtcbiAgICB9KTtcbiAgfVxuXG4gIGRpc3BhdGNoKC4uLnBhcmFtcykge1xuICAgIGZvciAobGV0IGJpbmRpbmcgb2YgdGhpcy5iaW5kaW5ncykge1xuICAgICAgYmluZGluZy5leGVjdXRlKC4uLnBhcmFtcyk7XG4gICAgfVxuICB9XG5cbiAgZGlzcG9zZSgpIHtcbiAgICBmb3IgKGxldCBiaW5kaW5nIG9mIHRoaXMuYmluZGluZ3MpIHtcbiAgICAgIGJpbmRpbmcuZGlzcG9zZSgpO1xuICAgIH1cblxuICAgIHRoaXMuYmluZGluZ3MgPSBudWxsO1xuICB9XG59XG5cbmNsYXNzIFNpZ25hbEJpbmRpbmcge1xuXG4gIGNvbnN0cnVjdG9yKHNpZ25hbCwgbGlzdGVuZXIsIGNvbnRleHQpIHtcbiAgICB0aGlzLmxpc3RlbmVyID0gbGlzdGVuZXI7XG4gICAgdGhpcy5zaWduYWwgPSBzaWduYWw7XG4gICAgdGhpcy5jb250ZXh0ID0gY29udGV4dDtcbiAgfVxuXG4gIGV4ZWN1dGUoLi4ucGFyYW1zKSB7XG4gICAgdGhpcy5saXN0ZW5lci5hcHBseSh0aGlzLmNvbnRleHQsIHBhcmFtcyk7XG4gIH1cblxuICBkaXNwb3NlKCkge1xuICAgIHRoaXMubGlzdGVuZXIgPSBudWxsO1xuICAgIHRoaXMuc2lnbmFsID0gbnVsbDtcbiAgICB0aGlzLmNvbnRleHQgPSBudWxsO1xuICB9XG59XG5cbmZ1bmN0aW9uIF9fdXBkYXRlKG1hcCwga2V5LCB2YWx1ZSkge1xuICBsZXQgbSA9IG5ldyBNYXAobWFwKTtcbiAgbS5zZXQoa2V5LCB2YWx1ZSk7XG4gIHJldHVybiBtO1xufVxuXG5mdW5jdGlvbiByZW1vdmUobWFwLCBrZXkpIHtcbiAgbGV0IG0gPSBuZXcgTWFwKG1hcCk7XG4gIG0uZGVsZXRlKGtleSk7XG4gIHJldHVybiBtO1xufVxuXG5jbGFzcyBNYWlsQm94IHtcblxuICBjb25zdHJ1Y3Rvcihjb250ZXh0ID0gdGhpcykge1xuICAgIHRoaXMuc2lnbmFsID0gbmV3IFNpZ25hbCgpO1xuICAgIHRoaXMuc2lnbmFsLmFkZCgoLi4ucGFyYW1zKSA9PiB0aGlzLm1lc3NhZ2VzID0gdGhpcy5tZXNzYWdlcy5jb25jYXQocGFyYW1zKSwgY29udGV4dCk7XG4gICAgdGhpcy5tZXNzYWdlcyA9IFtdO1xuICB9XG5cbiAgcmVjZWl2ZSguLi5tZXNzYWdlcykge1xuICAgIHRoaXMuc2lnbmFsLmRpc3BhdGNoKC4uLm1lc3NhZ2VzKTtcbiAgfVxuXG4gIHBlZWsoKSB7XG4gICAgaWYgKHRoaXMubWVzc2FnZXMubGVuZ3RoID09PSAwKSB7XG4gICAgICByZXR1cm4gbnVsbDtcbiAgICB9XG5cbiAgICByZXR1cm4gdGhpcy5tZXNzYWdlc1swXTtcbiAgfVxuXG4gIHJlYWQoKSB7XG4gICAgbGV0IHJlc3VsdCA9IHRoaXMubWVzc2FnZXNbMF07XG4gICAgdGhpcy5tZXNzYWdlcyA9IHRoaXMubWVzc2FnZXMuc2xpY2UoMSk7XG5cbiAgICByZXR1cm4gcmVzdWx0O1xuICB9XG5cbiAgYWRkX3N1YnNjcmliZXIoZm4sIGNvbnRleHQgPSB0aGlzKSB7XG4gICAgdGhpcy5zaWduYWwuYWRkKGZuLCBjb250ZXh0KTtcbiAgfVxuXG4gIHJlbW92ZV9zdWJzY3JpYmVyKGZuKSB7XG4gICAgdGhpcy5zaWduYWwucmVtb3ZlKGZuKTtcbiAgfVxuXG4gIGRpc3Bvc2UoKSB7XG4gICAgdGhpcy5zaWduYWwuZGlzcG9zZSgpO1xuICAgIHRoaXMubWVzc2FnZXMgPSBudWxsO1xuICB9XG59XG5cbmNsYXNzIFBvc3RPZmZpY2Uge1xuXG4gIGNvbnN0cnVjdG9yKCkge1xuICAgIHRoaXMubWFpbGJveGVzID0gbmV3IE1hcCgpO1xuICB9XG5cbiAgc2VuZChhZGRyZXNzLCBtZXNzYWdlKSB7XG4gICAgdGhpcy5tYWlsYm94ZXMuZ2V0KGFkZHJlc3MpLnJlY2VpdmUobWVzc2FnZSk7XG4gIH1cblxuICByZWNlaXZlKGFkZHJlc3MpIHtcbiAgICByZXR1cm4gdGhpcy5tYWlsYm94ZXMuZ2V0KGFkZHJlc3MpLnJlYWQoKTtcbiAgfVxuXG4gIHBlZWsoYWRkcmVzcykge1xuICAgIHJldHVybiB0aGlzLm1haWxib3hlcy5nZXQoYWRkcmVzcykucGVlaygpO1xuICB9XG5cbiAgYWRkX21haWxib3goYWRkcmVzcyA9IFN5bWJvbCgpLCBjb250ZXh0ID0gdGhpcykge1xuICAgIHRoaXMubWFpbGJveGVzID0gX191cGRhdGUodGhpcy5tYWlsYm94ZXMsIGFkZHJlc3MsIG5ldyBNYWlsQm94KCkpO1xuICAgIHJldHVybiBhZGRyZXNzO1xuICB9XG5cbiAgcmVtb3ZlX21haWxib3goYWRkcmVzcykge1xuICAgIHRoaXMubWFpbGJveGVzLmdldChhZGRyZXNzKS5kaXNwb3NlKCk7XG4gICAgdGhpcy5tYWlsYm94ZXMgPSByZW1vdmUodGhpcy5tYWlsYm94ZXMsIGFkZHJlc3MpO1xuICB9XG5cbiAgc3Vic2NyaWJlKGFkZHJlc3MsIHN1YnNjcmlidGlvbl9mbiwgY29udGV4dCA9IHRoaXMpIHtcbiAgICB0aGlzLm1haWxib3hlcy5nZXQoYWRkcmVzcykuYWRkX3N1YnNjcmliZXIoc3Vic2NyaWJ0aW9uX2ZuLCBjb250ZXh0KTtcbiAgfVxuXG4gIHVuc3Vic2NyaWJlKGFkZHJlc3MsIHN1YnNjcmlidGlvbl9mbikge1xuICAgIHRoaXMubWFpbGJveGVzLmdldChhZGRyZXNzKS5yZW1vdmVfc3Vic2NyaWJlcihzdWJzY3JpYnRpb25fZm4pO1xuICB9XG59XG5cbmZ1bmN0aW9uIGNhbGxfcHJvcGVydHkoaXRlbSwgcHJvcGVydHkpIHtcbiAgaWYgKHByb3BlcnR5IGluIGl0ZW0pIHtcbiAgICBpdGVtW3Byb3BlcnR5XTtcbiAgICBpZiAoaXRlbVtwcm9wZXJ0eV0gaW5zdGFuY2VvZiBGdW5jdGlvbikge1xuICAgICAgcmV0dXJuIGl0ZW1bcHJvcGVydHldKCk7XG4gICAgfSBlbHNlIHtcbiAgICAgIHJldHVybiBpdGVtW3Byb3BlcnR5XTtcbiAgICB9XG4gIH0gZWxzZSBpZiAoU3ltYm9sLmZvcihwcm9wZXJ0eSkgaW4gaXRlbSkge1xuICAgIGxldCBwcm9wID0gU3ltYm9sLmZvcihwcm9wZXJ0eSk7XG4gICAgaWYgKGl0ZW1bcHJvcF0gaW5zdGFuY2VvZiBGdW5jdGlvbikge1xuICAgICAgcmV0dXJuIGl0ZW1bcHJvcF0oKTtcbiAgICB9IGVsc2Uge1xuICAgICAgcmV0dXJuIGl0ZW1bcHJvcF07XG4gICAgfVxuICB9XG5cbiAgdGhyb3cgbmV3IEVycm9yKGBQcm9wZXJ0eSAkeyBwcm9wZXJ0eSB9IG5vdCBmb3VuZCBpbiAkeyBpdGVtIH1gKTtcbn1cblxudmFyIEpTID0ge1xuICBjYWxsX3Byb3BlcnR5XG59O1xuXG5sZXQgUmFuZ2UgPSBmdW5jdGlvbiAoX2ZpcnN0LCBfbGFzdCkge1xuICBpZiAoISh0aGlzIGluc3RhbmNlb2YgUmFuZ2UpKSB7XG4gICAgcmV0dXJuIG5ldyBSYW5nZShfZmlyc3QsIF9sYXN0KTtcbiAgfVxuXG4gIHRoaXMuZmlyc3QgPSBmdW5jdGlvbiAoKSB7XG4gICAgcmV0dXJuIF9maXJzdDtcbiAgfTtcblxuICB0aGlzLmxhc3QgPSBmdW5jdGlvbiAoKSB7XG4gICAgcmV0dXJuIF9sYXN0O1xuICB9O1xuXG4gIGxldCBfcmFuZ2UgPSBbXTtcblxuICBmb3IgKGxldCBpID0gX2ZpcnN0OyBpIDw9IF9sYXN0OyBpKyspIHtcbiAgICBfcmFuZ2UucHVzaChpKTtcbiAgfVxuXG4gIF9yYW5nZSA9IE9iamVjdC5mcmVlemUoX3JhbmdlKTtcblxuICB0aGlzLnZhbHVlID0gZnVuY3Rpb24gKCkge1xuICAgIHJldHVybiBfcmFuZ2U7XG4gIH07XG5cbiAgdGhpcy5sZW5ndGggPSBmdW5jdGlvbiAoKSB7XG4gICAgcmV0dXJuIF9yYW5nZS5sZW5ndGg7XG4gIH07XG5cbiAgcmV0dXJuIHRoaXM7XG59O1xuXG5SYW5nZS5wcm90b3R5cGVbU3ltYm9sLml0ZXJhdG9yXSA9IGZ1bmN0aW9uICgpIHtcbiAgcmV0dXJuIHRoaXMudmFsdWUoKVtTeW1ib2wuaXRlcmF0b3JdKCk7XG59O1xuXG5SYW5nZS5uZXcgPSBmdW5jdGlvbiAoZmlyc3QsIGxhc3QpIHtcbiAgcmV0dXJuIFJhbmdlKGZpcnN0LCBsYXN0KTtcbn07XG5cblJhbmdlLnJhbmdlX19xbWFya19fID0gZnVuY3Rpb24gKHJhbmdlKSB7XG4gIHJldHVybiByYW5nZSBpbnN0YW5jZW9mIFJhbmdlO1xufTtcblxubGV0IEtleXdvcmQgPSB7fTtcblxuS2V5d29yZC5oYXNfa2V5X19xbV9fID0gZnVuY3Rpb24gKGtleXdvcmRzLCBrZXkpIHtcbiAgZm9yIChsZXQga2V5d29yZCBvZiBrZXl3b3Jkcykge1xuICAgIGlmIChLZXJuZWwuZWxlbShrZXl3b3JkLCAwKSA9PSBrZXkpIHtcbiAgICAgIHJldHVybiB0cnVlO1xuICAgIH1cbiAgfVxuXG4gIHJldHVybiBmYWxzZTtcbn07XG5cbktleXdvcmQuZ2V0ID0gZnVuY3Rpb24gKGtleXdvcmRzLCBrZXksIHRoZV9kZWZhdWx0ID0gbnVsbCkge1xuICBmb3IgKGxldCBrZXl3b3JkIG9mIGtleXdvcmRzKSB7XG4gICAgaWYgKEtlcm5lbC5lbGVtKGtleXdvcmQsIDApID09IGtleSkge1xuICAgICAgcmV0dXJuIEtlcm5lbC5lbGVtKGtleXdvcmQsIDEpO1xuICAgIH1cbiAgfVxuXG4gIHJldHVybiB0aGVfZGVmYXVsdDtcbn07XG5cbmxldCBBZ2VudCA9IHt9O1xuXG5BZ2VudC5zdGFydCA9IGZ1bmN0aW9uIChmdW4sIG9wdGlvbnMgPSBbXSkge1xuICBjb25zdCBuYW1lID0gS2V5d29yZC5oYXNfa2V5X19xbV9fKG9wdGlvbnMsIEtlcm5lbC5TcGVjaWFsRm9ybXMuYXRvbSgnbmFtZScpKSA/IEtleXdvcmQuZ2V0KG9wdGlvbnMsIEtlcm5lbC5TcGVjaWFsRm9ybXMuYXRvbSgnbmFtZScpKSA6IFN5bWJvbCgpO1xuXG4gIHNlbGYucG9zdF9vZmZpY2UuYWRkX21haWxib3gobmFtZSk7XG4gIHNlbGYucG9zdF9vZmZpY2Uuc2VuZChuYW1lLCBmdW4oKSk7XG5cbiAgcmV0dXJuIEtlcm5lbC5TcGVjaWFsRm9ybXMudHVwbGUoS2VybmVsLlNwZWNpYWxGb3Jtcy5hdG9tKCdvaycpLCBuYW1lKTtcbn07XG5cbkFnZW50LnN0b3AgPSBmdW5jdGlvbiAoYWdlbnQsIHRpbWVvdXQgPSA1MDAwKSB7XG4gIHNlbGYucG9zdF9vZmZpY2UucmVtb3ZlX21haWxib3goYWdlbnQpO1xuICByZXR1cm4gS2VybmVsLlNwZWNpYWxGb3Jtcy5hdG9tKCdvaycpO1xufTtcblxuQWdlbnQudXBkYXRlID0gZnVuY3Rpb24gKGFnZW50LCBmdW4sIHRpbWVvdXQgPSA1MDAwKSB7XG5cbiAgY29uc3QgY3VycmVudF9zdGF0ZSA9IHNlbGYucG9zdF9vZmZpY2UucmVjZWl2ZShhZ2VudCk7XG4gIHNlbGYucG9zdF9vZmZpY2Uuc2VuZChhZ2VudCwgZnVuKGN1cnJlbnRfc3RhdGUpKTtcblxuICByZXR1cm4gS2VybmVsLlNwZWNpYWxGb3Jtcy5hdG9tKCdvaycpO1xufTtcblxuQWdlbnQuZ2V0ID0gZnVuY3Rpb24gKGFnZW50LCBmdW4sIHRpbWVvdXQgPSA1MDAwKSB7XG4gIHJldHVybiBmdW4oc2VsZi5wb3N0X29mZmljZS5wZWVrKGFnZW50KSk7XG59O1xuXG5BZ2VudC5nZXRfYW5kX3VwZGF0ZSA9IGZ1bmN0aW9uIChhZ2VudCwgZnVuLCB0aW1lb3V0ID0gNTAwMCkge1xuXG4gIGNvbnN0IGdldF9hbmRfdXBkYXRlX3R1cGxlID0gZnVuKHNlbGYucG9zdF9vZmZpY2UucmVjZWl2ZShhZ2VudCkpO1xuICBzZWxmLnBvc3Rfb2ZmaWNlLnNlbmQoYWdlbnQsIEtlcm5lbC5lbGVtKGdldF9hbmRfdXBkYXRlX3R1cGxlLCAxKSk7XG5cbiAgcmV0dXJuIEtlcm5lbC5lbGVtKGdldF9hbmRfdXBkYXRlX3R1cGxlLCAwKTtcbn07XG5cbi8vaHR0cHM6Ly9kZXZlbG9wZXIubW96aWxsYS5vcmcvZW4tVVMvZG9jcy9XZWIvQVBJL1dpbmRvd0Jhc2U2NC9CYXNlNjRfZW5jb2RpbmdfYW5kX2RlY29kaW5nI1NvbHV0aW9uXzJfJUUyJTgwJTkzX3Jld3JpdGVfdGhlX0RPTXNfYXRvYigpX2FuZF9idG9hKClfdXNpbmdfSmF2YVNjcmlwdCdzX1R5cGVkQXJyYXlzX2FuZF9VVEYtOFxuZnVuY3Rpb24gYjY0RW5jb2RlVW5pY29kZShzdHIpIHtcbiAgcmV0dXJuIGJ0b2EoZW5jb2RlVVJJQ29tcG9uZW50KHN0cikucmVwbGFjZSgvJShbMC05QS1GXXsyfSkvZywgZnVuY3Rpb24gKG1hdGNoLCBwMSkge1xuICAgIHJldHVybiBTdHJpbmcuZnJvbUNoYXJDb2RlKCcweCcgKyBwMSk7XG4gIH0pKTtcbn1cblxuZnVuY3Rpb24gZW5jb2RlNjQoZGF0YSkge1xuICByZXR1cm4gYjY0RW5jb2RlVW5pY29kZShkYXRhKTtcbn1cblxuZnVuY3Rpb24gZGVjb2RlNjQoZGF0YSkge1xuICB0cnkge1xuICAgIHJldHVybiBLZXJuZWwuU3BlY2lhbEZvcm1zLnR1cGxlKEtlcm5lbC5TcGVjaWFsRm9ybXMuYXRvbSgnb2snKSwgYXRvYihkYXRhKSk7XG4gIH0gY2F0Y2ggKGUpIHtcbiAgICByZXR1cm4gS2VybmVsLlNwZWNpYWxGb3Jtcy5hdG9tKCdlcnJvcicpO1xuICB9XG4gIHJldHVybiBidG9hKGRhdGEpO1xufVxuXG5mdW5jdGlvbiBkZWNvZGU2NF9fZW1fXyhkYXRhKSB7XG4gIHJldHVybiBhdG9iKGRhdGEpO1xufVxuXG52YXIgQmFzZSA9IHtcbiAgZW5jb2RlNjQsXG4gIGRlY29kZTY0LFxuICBkZWNvZGU2NF9fZW1fX1xufTtcblxuZnVuY3Rpb24gYm5vdChleHByKSB7XG4gIHJldHVybiB+ZXhwcjtcbn1cblxuZnVuY3Rpb24gYmFuZChsZWZ0LCByaWdodCkge1xuICByZXR1cm4gbGVmdCAmIHJpZ2h0O1xufVxuXG5mdW5jdGlvbiBib3IobGVmdCwgcmlnaHQpIHtcbiAgcmV0dXJuIGxlZnQgfCByaWdodDtcbn1cblxuZnVuY3Rpb24gYnNsKGxlZnQsIHJpZ2h0KSB7XG4gIHJldHVybiBsZWZ0IDw8IHJpZ2h0O1xufVxuXG5mdW5jdGlvbiBic3IobGVmdCwgcmlnaHQpIHtcbiAgcmV0dXJuIGxlZnQgPj4gcmlnaHQ7XG59XG5cbmZ1bmN0aW9uIGJ4b3IobGVmdCwgcmlnaHQpIHtcbiAgcmV0dXJuIGxlZnQgXiByaWdodDtcbn1cblxudmFyIEJpdHdpc2UgPSB7XG4gIGJub3QsXG4gIGJhbmQsXG4gIGJvcixcbiAgYnNsLFxuICBic3IsXG4gIGJ4b3Jcbn07XG5cbmxldCBFbnVtZXJhYmxlID0gS2VybmVsLmRlZnByb3RvY29sKHtcbiAgY291bnQ6IGZ1bmN0aW9uIChjb2xsZWN0aW9uKSB7fSxcbiAgbWVtYmVyX3FtYXJrX186IGZ1bmN0aW9uIChjb2xsZWN0aW9uLCB2YWx1ZSkge30sXG4gIHJlZHVjZTogZnVuY3Rpb24gKGNvbGxlY3Rpb24sIGFjYywgZnVuKSB7fVxufSk7XG5cbmxldCBDb2xsZWN0YWJsZSA9IEtlcm5lbC5kZWZwcm90b2NvbCh7XG4gIGludG86IGZ1bmN0aW9uIChjb2xsZWN0YWJsZSkge31cbn0pO1xuXG5sZXQgSW5zcGVjdCA9IEtlcm5lbC5kZWZwcm90b2NvbCh7XG4gIGluc3BlY3Q6IGZ1bmN0aW9uICh0aGluZywgb3B0cykge31cbn0pO1xuXG5mdW5jdGlvbiBfX19uZXdfXygpIHtcbiAgcmV0dXJuIFNwZWNpYWxGb3Jtcy5tYXAoe30pO1xufVxuXG5mdW5jdGlvbiBrZXlzKG1hcCkge1xuICByZXR1cm4gT2JqZWN0LmtleXMobWFwKTtcbn1cblxuZnVuY3Rpb24gX19zaXplKG1hcCkge1xuICByZXR1cm4ga2V5cyhtYXApLmxlbmd0aDtcbn1cblxuZnVuY3Rpb24gX190b19saXN0KG1hcCkge1xuICBsZXQgbWFwX2tleXMgPSBrZXlzKG1hcCk7XG4gIGxldCBsaXN0ID0gW107XG5cbiAgZm9yIChsZXQga2V5IG9mIG1hcF9rZXlzKSB7XG4gICAgbGlzdC5wdXNoKFNwZWNpYWxGb3Jtcy50dXBsZShrZXksIG1hcFtrZXldKSk7XG4gIH1cblxuICByZXR1cm4gU3BlY2lhbEZvcm1zLmxpc3QoLi4ubGlzdCk7XG59XG5cbmZ1bmN0aW9uIHZhbHVlcyhtYXApIHtcbiAgbGV0IG1hcF9rZXlzID0ga2V5cyhtYXApO1xuICBsZXQgbGlzdCA9IFtdO1xuXG4gIGZvciAobGV0IGtleSBvZiBtYXBfa2V5cykge1xuICAgIGxpc3QucHVzaChtYXBba2V5XSk7XG4gIH1cblxuICByZXR1cm4gU3BlY2lhbEZvcm1zLmxpc3QoLi4ubGlzdCk7XG59XG5cbmZ1bmN0aW9uIGZyb21fc3RydWN0KHN0cnVjdCkge1xuICBsZXQgbWFwID0gT2JqZWN0LmFzc2lnbih7fSwgc3RydWN0KTtcbiAgZGVsZXRlIG1hcFtTeW1ib2wuZm9yKFwiX19zdHJ1Y3RfX1wiKV07XG5cbiAgcmV0dXJuIFNwZWNpYWxGb3Jtcy5tYXAobWFwKTtcbn1cblxuZnVuY3Rpb24gX19fX2RlbGV0ZV9fKG1hcCwga2V5KSB7XG4gIGxldCBuZXdfbWFwID0gT2JqZWN0LmFzc2lnbih7fSwgbWFwKTtcblxuICBkZWxldGUgbmV3X21hcFtrZXldO1xuXG4gIHJldHVybiBTcGVjaWFsRm9ybXMubWFwKG5ld19tYXApO1xufVxuXG5mdW5jdGlvbiBkcm9wKG1hcCwga2V5cykge1xuICBsZXQgbmV3X21hcCA9IE9iamVjdC5hc3NpZ24oe30sIG1hcCk7XG5cbiAgZm9yIChsZXQga2V5IG9mIGtleXMpIHtcbiAgICBkZWxldGUgbmV3X21hcFtrZXldO1xuICB9XG5cbiAgcmV0dXJuIFNwZWNpYWxGb3Jtcy5tYXAobmV3X21hcCk7XG59XG5cbmZ1bmN0aW9uIF9fZXF1YWxfX3FtYXJrX18obWFwMSwgbWFwMikge1xuICByZXR1cm4gbWFwMSA9PT0gbWFwMjtcbn1cblxuZnVuY3Rpb24gZmV0Y2hfX2VtYXJrX18obWFwLCBrZXkpIHtcbiAgaWYgKGtleSBpbiBtYXApIHtcbiAgICByZXR1cm4gbWFwW2tleV07XG4gIH1cblxuICB0aHJvdyBuZXcgRXJyb3IoXCJLZXkgbm90IGZvdW5kLlwiKTtcbn1cblxuZnVuY3Rpb24gZmV0Y2gobWFwLCBrZXkpIHtcbiAgaWYgKGtleSBpbiBtYXApIHtcbiAgICByZXR1cm4gU3BlY2lhbEZvcm1zLnR1cGxlKFNwZWNpYWxGb3Jtcy5hdG9tKFwib2tcIiksIG1hcFtrZXldKTtcbiAgfVxuXG4gIHJldHVybiBTcGVjaWFsRm9ybXMuYXRvbShcImVycm9yXCIpO1xufVxuXG5mdW5jdGlvbiBoYXNfa2V5X19xbWFya19fKG1hcCwga2V5KSB7XG4gIHJldHVybiBrZXkgaW4gbWFwO1xufVxuXG5mdW5jdGlvbiBtZXJnZShtYXAxLCBtYXAyKSB7XG4gIHJldHVybiBTcGVjaWFsRm9ybXMubWFwX3VwZGF0ZShtYXAxLCBtYXAyKTtcbn1cblxuZnVuY3Rpb24gc3BsaXQobWFwLCBrZXlzKSB7XG4gIGxldCBzcGxpdDEgPSB7fTtcbiAgbGV0IHNwbGl0MiA9IHt9O1xuXG4gIGZvciAobGV0IGtleSBvZiBPYmplY3Qua2V5cyhtYXApKSB7XG4gICAgaWYgKGtleXMuaW5kZXhPZihrZXkpID4gLTEpIHtcbiAgICAgIHNwbGl0MVtrZXldID0gbWFwW2tleV07XG4gICAgfSBlbHNlIHtcbiAgICAgIHNwbGl0MltrZXldID0gbWFwW2tleV07XG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIFNwZWNpYWxGb3Jtcy50dXBsZShTcGVjaWFsRm9ybXMubWFwKHNwbGl0MSksIFNwZWNpYWxGb3Jtcy5tYXAoc3BsaXQyKSk7XG59XG5cbmZ1bmN0aW9uIHRha2UobWFwLCBrZXlzKSB7XG4gIGxldCBzcGxpdDEgPSB7fTtcblxuICBmb3IgKGxldCBrZXkgb2YgT2JqZWN0LmtleXMobWFwKSkge1xuICAgIGlmIChrZXlzLmluZGV4T2Yoa2V5KSA+IC0xKSB7XG4gICAgICBzcGxpdDFba2V5XSA9IG1hcFtrZXldO1xuICAgIH1cbiAgfVxuXG4gIHJldHVybiBTcGVjaWFsRm9ybXMubWFwKHNwbGl0MSk7XG59XG5cbmZ1bmN0aW9uIGRyb3AobWFwLCBrZXlzKSB7XG4gIGxldCBzcGxpdDEgPSB7fTtcblxuICBmb3IgKGxldCBrZXkgb2YgT2JqZWN0LmtleXMobWFwKSkge1xuICAgIGlmIChrZXlzLmluZGV4T2Yoa2V5KSA9PT0gLTEpIHtcbiAgICAgIHNwbGl0MVtrZXldID0gbWFwW2tleV07XG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIFNwZWNpYWxGb3Jtcy5tYXAoc3BsaXQxKTtcbn1cblxuZnVuY3Rpb24gcHV0X25ldyhtYXAsIGtleSwgdmFsdWUpIHtcbiAgaWYgKGtleSBpbiBtYXApIHtcbiAgICByZXR1cm4gbWFwO1xuICB9XG5cbiAgbGV0IG5ld19tYXAgPSBPYmplY3QuYXNzaWduKHt9LCBtYXApO1xuICBuZXdfbWFwW2tleV0gPSB2YWx1ZTtcblxuICByZXR1cm4gU3BlY2lhbEZvcm1zLm1hcChuZXdfbWFwKTtcbn1cblxuZnVuY3Rpb24gcHV0X25ld19sYXp5KG1hcCwga2V5LCBmdW4pIHtcbiAgaWYgKGtleSBpbiBtYXApIHtcbiAgICByZXR1cm4gbWFwO1xuICB9XG5cbiAgbGV0IG5ld19tYXAgPSBPYmplY3QuYXNzaWduKHt9LCBtYXApO1xuICBuZXdfbWFwW2tleV0gPSBmdW4oKTtcblxuICByZXR1cm4gU3BlY2lhbEZvcm1zLm1hcChuZXdfbWFwKTtcbn1cblxuZnVuY3Rpb24gZ2V0X2FuZF91cGRhdGUobWFwLCBrZXksIGZ1bikge1xuICBpZiAoa2V5IGluIG1hcCkge1xuICAgIHJldHVybiBtYXA7XG4gIH1cblxuICBsZXQgbmV3X21hcCA9IE9iamVjdC5hc3NpZ24oe30sIG1hcCk7XG4gIG5ld19tYXBba2V5XSA9IGZ1bihtYXBba2V5XSk7XG5cbiAgcmV0dXJuIFNwZWNpYWxGb3Jtcy5tYXAobmV3X21hcCk7XG59XG5cbmZ1bmN0aW9uIHBvcF9sYXp5KG1hcCwga2V5LCBmdW4pIHtcbiAgaWYgKCFrZXkgaW4gbWFwKSB7XG4gICAgcmV0dXJuIFNwZWNpYWxGb3Jtcy50dXBsZShmdW4oKSwgbWFwKTtcbiAgfVxuXG4gIGxldCBuZXdfbWFwID0gT2JqZWN0LmFzc2lnbih7fSwgbWFwKTtcbiAgbGV0IHZhbHVlID0gZnVuKG5ld19tYXBba2V5XSk7XG4gIGRlbGV0ZSBuZXdfbWFwW2tleV07XG5cbiAgcmV0dXJuIFNwZWNpYWxGb3Jtcy50dXBsZSh2YWx1ZSwgbmV3X21hcCk7XG59XG5cbmZ1bmN0aW9uIHBvcChtYXAsIGtleSwgX2RlZmF1bHQgPSBudWxsKSB7XG4gIGlmICgha2V5IGluIG1hcCkge1xuICAgIHJldHVybiBTcGVjaWFsRm9ybXMudHVwbGUoX2RlZmF1bHQsIG1hcCk7XG4gIH1cblxuICBsZXQgbmV3X21hcCA9IE9iamVjdC5hc3NpZ24oe30sIG1hcCk7XG4gIGxldCB2YWx1ZSA9IG5ld19tYXBba2V5XTtcbiAgZGVsZXRlIG5ld19tYXBba2V5XTtcblxuICByZXR1cm4gU3BlY2lhbEZvcm1zLnR1cGxlKHZhbHVlLCBuZXdfbWFwKTtcbn1cblxuZnVuY3Rpb24gZ2V0X2xhenkobWFwLCBrZXksIGZ1bikge1xuICBpZiAoIWtleSBpbiBtYXApIHtcbiAgICByZXR1cm4gZnVuKCk7XG4gIH1cblxuICByZXR1cm4gZnVuKG1hcFtrZXldKTtcbn1cblxuZnVuY3Rpb24gZ2V0KG1hcCwga2V5LCBfZGVmYXVsdCA9IG51bGwpIHtcbiAgaWYgKCFrZXkgaW4gbWFwKSB7XG4gICAgcmV0dXJuIF9kZWZhdWx0O1xuICB9XG5cbiAgcmV0dXJuIG1hcFtrZXldO1xufVxuXG5mdW5jdGlvbiBfX3B1dChtYXAsIGtleSwgdmFsKSB7XG4gIGxldCBuZXdfbWFwID0gT2JqZWN0KHt9LCBtYXApO1xuICBuZXdfbWFwW2tleV0gPSB2YWw7XG5cbiAgcmV0dXJuIFNwZWNpYWxGb3Jtcy5tYXAobmV3X21hcCk7XG59XG5cbmZ1bmN0aW9uIHVwZGF0ZV9fZW1hcmtfXyhtYXAsIGtleSwgZnVuKSB7XG4gIGlmICgha2V5IGluIG1hcCkge1xuICAgIHRocm93IG5ldyBFcnJvcihcIktleSBub3QgZm91bmRcIik7XG4gIH1cblxuICBsZXQgbmV3X21hcCA9IE9iamVjdCh7fSwgbWFwKTtcbiAgbmV3X21hcFtrZXldID0gZnVuKG1hcFtrZXldKTtcblxuICByZXR1cm4gU3BlY2lhbEZvcm1zLm1hcChuZXdfbWFwKTtcbn1cblxuZnVuY3Rpb24gX3VwZGF0ZShtYXAsIGtleSwgaW5pdGlhbCwgZnVuKSB7XG4gIGxldCBuZXdfbWFwID0gT2JqZWN0KHt9LCBtYXApO1xuXG4gIGlmICgha2V5IGluIG1hcCkge1xuICAgIG5ld19tYXBba2V5XSA9IGluaXRpYWw7XG4gIH0gZWxzZSB7XG4gICAgbmV3X21hcFtrZXldID0gZnVuKG1hcFtrZXldKTtcbiAgfVxuXG4gIHJldHVybiBTcGVjaWFsRm9ybXMubWFwKG5ld19tYXApO1xufVxuXG52YXIgX01hcCA9IHtcbiAgbmV3OiBfX19uZXdfXyxcbiAga2V5cyxcbiAgc2l6ZTogX19zaXplLFxuICB0b19saXN0OiBfX3RvX2xpc3QsXG4gIHZhbHVlcyxcbiAgZnJvbV9zdHJ1Y3QsXG4gIGRlbGV0ZTogX19fX2RlbGV0ZV9fLFxuICBkcm9wLFxuICBlcXVhbF9fcW1hcmtfXzogX19lcXVhbF9fcW1hcmtfXyxcbiAgZmV0Y2hfX2VtYXJrX18sXG4gIGZldGNoLFxuICBoYXNfa2V5X19xbWFya19fLFxuICBzcGxpdCxcbiAgdGFrZSxcbiAgcHV0X25ldyxcbiAgcHV0X25ld19sYXp5LFxuICBnZXRfYW5kX3VwZGF0ZSxcbiAgcG9wX2xhenksXG4gIHBvcCxcbiAgZ2V0X2xhenksXG4gIGdldCxcbiAgcHV0OiBfX3B1dCxcbiAgdXBkYXRlX19lbWFya19fLFxuICB1cGRhdGU6IF91cGRhdGVcbn07XG5cbmZ1bmN0aW9uIF9fbmV3X18oKSB7XG4gIHJldHVybiBTcGVjaWFsRm9ybXMubWFwKHsgW1N5bWJvbC5mb3IoJ19fc3RydWN0X18nKV06IFN5bWJvbC5mb3IoJ01hcFNldCcpLCBzZXQ6IFNwZWNpYWxGb3Jtcy5saXN0KCkgfSk7XG59XG5cbmZ1bmN0aW9uIF9zaXplKG1hcCkge1xuICByZXR1cm4gbWFwLnNldC5sZW5ndGg7XG59XG5cbmZ1bmN0aW9uIF90b19saXN0KG1hcCkge1xuICByZXR1cm4gbWFwLnNldDtcbn1cblxuZnVuY3Rpb24gX19fZGVsZXRlX18oc2V0LCB0ZXJtKSB7XG4gIGxldCBuZXdfbGlzdCA9IExpc3QuZGVsZXRlKHNldC5zZXQsIHRlcm0pO1xuXG4gIGxldCBuZXdfbWFwID0gT2JqZWN0LmFzc2lnbih7fSwgc2V0KTtcbiAgbmV3X21hcC5zZXQgPSBuZXdfbGlzdDtcbiAgcmV0dXJuIFNwZWNpYWxGb3Jtcy5tYXAobmV3X21hcCk7XG59XG5cbmZ1bmN0aW9uIF9wdXQoc2V0LCB0ZXJtKSB7XG4gIGlmIChzZXQuc2V0LmluZGV4T2YodGVybSkgPT09IC0xKSB7XG4gICAgbGV0IG5ld19saXN0ID0gTGlzdC5hcHBlbmQoc2V0LnNldCwgdGVybSk7XG5cbiAgICBsZXQgbmV3X21hcCA9IE9iamVjdC5hc3NpZ24oe30sIHNldCk7XG4gICAgbmV3X21hcC5zZXQgPSBuZXdfbGlzdDtcbiAgICByZXR1cm4gU3BlY2lhbEZvcm1zLm1hcChuZXdfbWFwKTtcbiAgfVxuXG4gIHJldHVybiBzZXQ7XG59XG5cbmZ1bmN0aW9uIF9kaWZmZXJlbmNlKHNldDEsIHNldDIpIHtcbiAgbGV0IG5ld19tYXAgPSBPYmplY3QuYXNzaWduKHt9LCBzZXQxKTtcblxuICBmb3IgKGxldCB2YWwgb2Ygc2V0MS5zZXQpIHtcbiAgICBpZiAoX21lbWJlcl9fcW1hcmtfXyhzZXQyLCB2YWwpKSB7XG4gICAgICBuZXdfbWFwLnNldCA9IExpc3QuZGVsZXRlKG5ld19tYXAuc2V0LCB2YWwpO1xuICAgIH1cbiAgfVxuXG4gIHJldHVybiBTcGVjaWFsRm9ybXMubWFwKG5ld19tYXApO1xufVxuXG5mdW5jdGlvbiBfaW50ZXJzZWN0aW9uKHNldDEsIHNldDIpIHtcbiAgbGV0IG5ld19tYXAgPSBPYmplY3QuYXNzaWduKHt9LCBzZXQxKTtcblxuICBmb3IgKGxldCB2YWwgb2Ygc2V0MS5zZXQpIHtcbiAgICBpZiAoIV9tZW1iZXJfX3FtYXJrX18oc2V0MiwgdmFsKSkge1xuICAgICAgbmV3X21hcC5zZXQgPSBMaXN0LmRlbGV0ZShuZXdfbWFwLnNldCwgdmFsKTtcbiAgICB9XG4gIH1cblxuICByZXR1cm4gU3BlY2lhbEZvcm1zLm1hcChuZXdfbWFwKTtcbn1cblxuZnVuY3Rpb24gX3VuaW9uKHNldDEsIHNldDIpIHtcbiAgbGV0IG5ld19tYXAgPSBzZXQxO1xuXG4gIGZvciAobGV0IHZhbCBvZiBzZXQyLnNldCkge1xuICAgIG5ld19tYXAgPSBfcHV0KG5ld19tYXAsIHZhbCk7XG4gIH1cblxuICByZXR1cm4gU3BlY2lhbEZvcm1zLm1hcChuZXdfbWFwKTtcbn1cblxuZnVuY3Rpb24gX2Rpc2pvaW5fX3FtYXJrX18oc2V0MSwgc2V0Mikge1xuICBmb3IgKGxldCB2YWwgb2Ygc2V0MS5zZXQpIHtcbiAgICBpZiAoX21lbWJlcl9fcW1hcmtfXyhzZXQyLCB2YWwpKSB7XG4gICAgICByZXR1cm4gZmFsc2U7XG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIHRydWU7XG59XG5cbmZ1bmN0aW9uIF9tZW1iZXJfX3FtYXJrX18oc2V0LCB2YWx1ZSkge1xuICByZXR1cm4gc2V0LnNldC5pbmRleE9mKHZhbHVlKSA+PSAwO1xufVxuXG5mdW5jdGlvbiBfZXF1YWxfX3FtYXJrX18oc2V0MSwgc2V0Mikge1xuICByZXR1cm4gc2V0MS5zZXQgPT09IHNldDIuc2V0O1xufVxuXG5mdW5jdGlvbiBfc3Vic2V0X19xbWFya19fKHNldDEsIHNldDIpIHtcbiAgZm9yIChsZXQgdmFsIG9mIHNldDEuc2V0KSB7XG4gICAgaWYgKCFfbWVtYmVyX19xbWFya19fKHNldDIsIHZhbCkpIHtcbiAgICAgIHJldHVybiBmYWxzZTtcbiAgICB9XG4gIH1cblxuICByZXR1cm4gdHJ1ZTtcbn1cblxudmFyIE1hcFNldCA9IHtcbiAgbmV3OiBfX25ld19fLFxuICBzaXplOiBfc2l6ZSxcbiAgdG9fbGlzdDogX3RvX2xpc3QsXG4gIGRpc2pvaW5fX3FtYXJrX186IF9kaXNqb2luX19xbWFya19fLFxuICBkZWxldGU6IF9fX2RlbGV0ZV9fLFxuICBzdWJzZXRfX3FtYXJrX186IF9zdWJzZXRfX3FtYXJrX18sXG4gIGVxdWFsX19xbWFya19fOiBfZXF1YWxfX3FtYXJrX18sXG4gIG1lbWJlcl9fcW1hcmtfXzogX21lbWJlcl9fcW1hcmtfXyxcbiAgcHV0OiBfcHV0LFxuICB1bmlvbjogX3VuaW9uLFxuICBpbnRlcnNlY3Rpb246IF9pbnRlcnNlY3Rpb24sXG4gIGRpZmZlcmVuY2U6IF9kaWZmZXJlbmNlXG59O1xuXG5mdW5jdGlvbiBzaXplKG1hcCkge1xuICByZXR1cm4gTWFwU2V0LnNpemUobWFwKTtcbn1cblxuZnVuY3Rpb24gdG9fbGlzdChtYXApIHtcbiAgcmV0dXJuIE1hcFNldC50b19saXN0KG1hcCk7XG59XG5cbmZ1bmN0aW9uIF9fZGVsZXRlX18oc2V0LCB0ZXJtKSB7XG4gIHJldHVybiBNYXBTZXQuZGVsZXRlKHNldCwgdGVybSk7XG59XG5cbmZ1bmN0aW9uIHB1dChzZXQsIHRlcm0pIHtcbiAgcmV0dXJuIE1hcFNldC5wdXQoc2V0LCB0ZXJtKTtcbn1cblxuZnVuY3Rpb24gZGlmZmVyZW5jZShzZXQxLCBzZXQyKSB7XG4gIHJldHVybiBNYXBTZXQuZGlmZmVyZW5jZShzZXQxLCBzZXQyKTtcbn1cblxuZnVuY3Rpb24gaW50ZXJzZWN0aW9uKHNldDEsIHNldDIpIHtcbiAgcmV0dXJuIE1hcFNldC5pbnRlcnNlY3Rpb24oc2V0MSwgc2V0Mik7XG59XG5cbmZ1bmN0aW9uIHVuaW9uKHNldDEsIHNldDIpIHtcbiAgcmV0dXJuIE1hcFNldC51bmlvbihzZXQxLCBzZXQyKTtcbn1cblxuZnVuY3Rpb24gZGlzam9pbl9fcW1hcmtfXyhzZXQxLCBzZXQyKSB7XG4gIHJldHVybiBNYXBTZXQuZGlzam9pbl9fcW1hcmtfXyhzZXQxLCBzZXQyKTtcbn1cblxuZnVuY3Rpb24gbWVtYmVyX19xbWFya19fKHNldCwgdmFsdWUpIHtcbiAgcmV0dXJuIE1hcFNldC5tZW1iZXJfX3FtYXJrX18oc2V0MSwgc2V0Mik7XG59XG5cbmZ1bmN0aW9uIGVxdWFsX19xbWFya19fKHNldDEsIHNldDIpIHtcbiAgcmV0dXJuIE1hcFNldC5lcXVhbF9fcW1hcmtfXyhzZXQxLCBzZXQyKTtcbn1cblxuZnVuY3Rpb24gc3Vic2V0X19xbWFya19fKHNldDEsIHNldDIpIHtcbiAgcmV0dXJuIE1hcFNldC5zdWJzZXRfX3FtYXJrX18oc2V0MSwgc2V0Mik7XG59XG5cbnZhciBfU2V0ID0ge1xuICBzaXplLFxuICB0b19saXN0LFxuICBkaXNqb2luX19xbWFya19fLFxuICBkZWxldGU6IF9fZGVsZXRlX18sXG4gIHN1YnNldF9fcW1hcmtfXyxcbiAgZXF1YWxfX3FtYXJrX18sXG4gIG1lbWJlcl9fcW1hcmtfXyxcbiAgcHV0LFxuICB1bmlvbixcbiAgaW50ZXJzZWN0aW9uLFxuICBkaWZmZXJlbmNlXG59O1xuXG5sZXQgdmlydHVhbERvbSA9IChmdW5jdGlvbiAoZSkge1xuICAgIHJldHVybiBlKCk7XG59KShmdW5jdGlvbiAoKSB7XG4gICAgdmFyIGRlZmluZSwgbW9kdWxlLCBleHBvcnRzO1xuICAgIHJldHVybiAoZnVuY3Rpb24gZSh0LCBuLCByKSB7XG4gICAgICAgIGZ1bmN0aW9uIHMobywgdSkge1xuICAgICAgICAgICAgaWYgKCFuW29dKSB7XG4gICAgICAgICAgICAgICAgaWYgKCF0W29dKSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciBhID0gdHlwZW9mIHJlcXVpcmUgPT0gXCJmdW5jdGlvblwiICYmIHJlcXVpcmU7XG4gICAgICAgICAgICAgICAgICAgIGlmICghdSAmJiBhKSByZXR1cm4gYShvLCAhMCk7XG4gICAgICAgICAgICAgICAgICAgIGlmIChpKSByZXR1cm4gaShvLCAhMCk7XG4gICAgICAgICAgICAgICAgICAgIHZhciBmID0gbmV3IEVycm9yKFwiQ2Fubm90IGZpbmQgbW9kdWxlICdcIiArIG8gKyBcIidcIik7XG4gICAgICAgICAgICAgICAgICAgIHRocm93IChmLmNvZGUgPSBcIk1PRFVMRV9OT1RfRk9VTkRcIiwgZik7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHZhciBsID0gbltvXSA9IHtcbiAgICAgICAgICAgICAgICAgICAgZXhwb3J0czoge31cbiAgICAgICAgICAgICAgICB9O1xuICAgICAgICAgICAgICAgIHRbb11bMF0uY2FsbChsLmV4cG9ydHMsIGZ1bmN0aW9uIChlKSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciBuID0gdFtvXVsxXVtlXTtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHMobiA/IG4gOiBlKTtcbiAgICAgICAgICAgICAgICB9LCBsLCBsLmV4cG9ydHMsIGUsIHQsIG4sIHIpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmV0dXJuIG5bb10uZXhwb3J0cztcbiAgICAgICAgfVxuICAgICAgICB2YXIgaSA9IHR5cGVvZiByZXF1aXJlID09IFwiZnVuY3Rpb25cIiAmJiByZXF1aXJlO1xuICAgICAgICBmb3IgKHZhciBvID0gMDsgbyA8IHIubGVuZ3RoOyBvKyspIHMocltvXSk7XG4gICAgICAgIHJldHVybiBzO1xuICAgIH0pKHtcbiAgICAgICAgMTogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHtcblxuICAgICAgICAgICAgdmFyIGNyZWF0ZUVsZW1lbnQgPSByZXF1aXJlKFwiLi92ZG9tL2NyZWF0ZS1lbGVtZW50LmpzXCIpO1xuXG4gICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IGNyZWF0ZUVsZW1lbnQ7XG4gICAgICAgIH0sIHsgXCIuL3Zkb20vY3JlYXRlLWVsZW1lbnQuanNcIjogMTUgfV0sIDI6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICB2YXIgZGlmZiA9IHJlcXVpcmUoXCIuL3Z0cmVlL2RpZmYuanNcIik7XG5cbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gZGlmZjtcbiAgICAgICAgfSwgeyBcIi4vdnRyZWUvZGlmZi5qc1wiOiAzNSB9XSwgMzogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHtcbiAgICAgICAgICAgIHZhciBoID0gcmVxdWlyZShcIi4vdmlydHVhbC1oeXBlcnNjcmlwdC9pbmRleC5qc1wiKTtcblxuICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBoO1xuICAgICAgICB9LCB7IFwiLi92aXJ0dWFsLWh5cGVyc2NyaXB0L2luZGV4LmpzXCI6IDIyIH1dLCA0OiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge1xuICAgICAgICAgICAgdmFyIGRpZmYgPSByZXF1aXJlKFwiLi9kaWZmLmpzXCIpO1xuICAgICAgICAgICAgdmFyIHBhdGNoID0gcmVxdWlyZShcIi4vcGF0Y2guanNcIik7XG4gICAgICAgICAgICB2YXIgaCA9IHJlcXVpcmUoXCIuL2guanNcIik7XG4gICAgICAgICAgICB2YXIgY3JlYXRlID0gcmVxdWlyZShcIi4vY3JlYXRlLWVsZW1lbnQuanNcIik7XG4gICAgICAgICAgICB2YXIgVk5vZGUgPSByZXF1aXJlKFwiLi92bm9kZS92bm9kZS5qc1wiKTtcbiAgICAgICAgICAgIHZhciBWVGV4dCA9IHJlcXVpcmUoXCIuL3Zub2RlL3Z0ZXh0LmpzXCIpO1xuXG4gICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IHtcbiAgICAgICAgICAgICAgICBkaWZmOiBkaWZmLFxuICAgICAgICAgICAgICAgIHBhdGNoOiBwYXRjaCxcbiAgICAgICAgICAgICAgICBoOiBoLFxuICAgICAgICAgICAgICAgIGNyZWF0ZTogY3JlYXRlLFxuICAgICAgICAgICAgICAgIFZOb2RlOiBWTm9kZSxcbiAgICAgICAgICAgICAgICBWVGV4dDogVlRleHRcbiAgICAgICAgICAgIH07XG4gICAgICAgIH0sIHsgXCIuL2NyZWF0ZS1lbGVtZW50LmpzXCI6IDEsIFwiLi9kaWZmLmpzXCI6IDIsIFwiLi9oLmpzXCI6IDMsIFwiLi9wYXRjaC5qc1wiOiAxMywgXCIuL3Zub2RlL3Zub2RlLmpzXCI6IDMxLCBcIi4vdm5vZGUvdnRleHQuanNcIjogMzMgfV0sIDU6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICAvKiFcbiAgICAgICAgICAgICAqIENyb3NzLUJyb3dzZXIgU3BsaXQgMS4xLjFcbiAgICAgICAgICAgICAqIENvcHlyaWdodCAyMDA3LTIwMTIgU3RldmVuIExldml0aGFuIDxzdGV2ZW5sZXZpdGhhbi5jb20+XG4gICAgICAgICAgICAgKiBBdmFpbGFibGUgdW5kZXIgdGhlIE1JVCBMaWNlbnNlXG4gICAgICAgICAgICAgKiBFQ01BU2NyaXB0IGNvbXBsaWFudCwgdW5pZm9ybSBjcm9zcy1icm93c2VyIHNwbGl0IG1ldGhvZFxuICAgICAgICAgICAgICovXG5cbiAgICAgICAgICAgIC8qKlxuICAgICAgICAgICAgICogU3BsaXRzIGEgc3RyaW5nIGludG8gYW4gYXJyYXkgb2Ygc3RyaW5ncyB1c2luZyBhIHJlZ2V4IG9yIHN0cmluZyBzZXBhcmF0b3IuIE1hdGNoZXMgb2YgdGhlXG4gICAgICAgICAgICAgKiBzZXBhcmF0b3IgYXJlIG5vdCBpbmNsdWRlZCBpbiB0aGUgcmVzdWx0IGFycmF5LiBIb3dldmVyLCBpZiBgc2VwYXJhdG9yYCBpcyBhIHJlZ2V4IHRoYXQgY29udGFpbnNcbiAgICAgICAgICAgICAqIGNhcHR1cmluZyBncm91cHMsIGJhY2tyZWZlcmVuY2VzIGFyZSBzcGxpY2VkIGludG8gdGhlIHJlc3VsdCBlYWNoIHRpbWUgYHNlcGFyYXRvcmAgaXMgbWF0Y2hlZC5cbiAgICAgICAgICAgICAqIEZpeGVzIGJyb3dzZXIgYnVncyBjb21wYXJlZCB0byB0aGUgbmF0aXZlIGBTdHJpbmcucHJvdG90eXBlLnNwbGl0YCBhbmQgY2FuIGJlIHVzZWQgcmVsaWFibHlcbiAgICAgICAgICAgICAqIGNyb3NzLWJyb3dzZXIuXG4gICAgICAgICAgICAgKiBAcGFyYW0ge1N0cmluZ30gc3RyIFN0cmluZyB0byBzcGxpdC5cbiAgICAgICAgICAgICAqIEBwYXJhbSB7UmVnRXhwfFN0cmluZ30gc2VwYXJhdG9yIFJlZ2V4IG9yIHN0cmluZyB0byB1c2UgZm9yIHNlcGFyYXRpbmcgdGhlIHN0cmluZy5cbiAgICAgICAgICAgICAqIEBwYXJhbSB7TnVtYmVyfSBbbGltaXRdIE1heGltdW0gbnVtYmVyIG9mIGl0ZW1zIHRvIGluY2x1ZGUgaW4gdGhlIHJlc3VsdCBhcnJheS5cbiAgICAgICAgICAgICAqIEByZXR1cm5zIHtBcnJheX0gQXJyYXkgb2Ygc3Vic3RyaW5ncy5cbiAgICAgICAgICAgICAqIEBleGFtcGxlXG4gICAgICAgICAgICAgKlxuICAgICAgICAgICAgICogLy8gQmFzaWMgdXNlXG4gICAgICAgICAgICAgKiBzcGxpdCgnYSBiIGMgZCcsICcgJyk7XG4gICAgICAgICAgICAgKiAvLyAtPiBbJ2EnLCAnYicsICdjJywgJ2QnXVxuICAgICAgICAgICAgICpcbiAgICAgICAgICAgICAqIC8vIFdpdGggbGltaXRcbiAgICAgICAgICAgICAqIHNwbGl0KCdhIGIgYyBkJywgJyAnLCAyKTtcbiAgICAgICAgICAgICAqIC8vIC0+IFsnYScsICdiJ11cbiAgICAgICAgICAgICAqXG4gICAgICAgICAgICAgKiAvLyBCYWNrcmVmZXJlbmNlcyBpbiByZXN1bHQgYXJyYXlcbiAgICAgICAgICAgICAqIHNwbGl0KCcuLndvcmQxIHdvcmQyLi4nLCAvKFthLXpdKykoXFxkKykvaSk7XG4gICAgICAgICAgICAgKiAvLyAtPiBbJy4uJywgJ3dvcmQnLCAnMScsICcgJywgJ3dvcmQnLCAnMicsICcuLiddXG4gICAgICAgICAgICAgKi9cbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gKGZ1bmN0aW9uIHNwbGl0KHVuZGVmKSB7XG5cbiAgICAgICAgICAgICAgICB2YXIgbmF0aXZlU3BsaXQgPSBTdHJpbmcucHJvdG90eXBlLnNwbGl0LFxuICAgICAgICAgICAgICAgICAgICBjb21wbGlhbnRFeGVjTnBjZyA9IC8oKT8/Ly5leGVjKFwiXCIpWzFdID09PSB1bmRlZixcblxuICAgICAgICAgICAgICAgIC8vIE5QQ0c6IG5vbnBhcnRpY2lwYXRpbmcgY2FwdHVyaW5nIGdyb3VwXG4gICAgICAgICAgICAgICAgc2VsZjtcblxuICAgICAgICAgICAgICAgIHNlbGYgPSBmdW5jdGlvbiAoc3RyLCBzZXBhcmF0b3IsIGxpbWl0KSB7XG4gICAgICAgICAgICAgICAgICAgIC8vIElmIGBzZXBhcmF0b3JgIGlzIG5vdCBhIHJlZ2V4LCB1c2UgYG5hdGl2ZVNwbGl0YFxuICAgICAgICAgICAgICAgICAgICBpZiAoT2JqZWN0LnByb3RvdHlwZS50b1N0cmluZy5jYWxsKHNlcGFyYXRvcikgIT09IFwiW29iamVjdCBSZWdFeHBdXCIpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBuYXRpdmVTcGxpdC5jYWxsKHN0ciwgc2VwYXJhdG9yLCBsaW1pdCk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgdmFyIG91dHB1dCA9IFtdLFxuICAgICAgICAgICAgICAgICAgICAgICAgZmxhZ3MgPSAoc2VwYXJhdG9yLmlnbm9yZUNhc2UgPyBcImlcIiA6IFwiXCIpICsgKHNlcGFyYXRvci5tdWx0aWxpbmUgPyBcIm1cIiA6IFwiXCIpICsgKHNlcGFyYXRvci5leHRlbmRlZCA/IFwieFwiIDogXCJcIikgKyAoc2VwYXJhdG9yLnN0aWNreSA/IFwieVwiIDogXCJcIiksXG5cbiAgICAgICAgICAgICAgICAgICAgLy8gRmlyZWZveCAzK1xuICAgICAgICAgICAgICAgICAgICBsYXN0TGFzdEluZGV4ID0gMCxcblxuICAgICAgICAgICAgICAgICAgICAvLyBNYWtlIGBnbG9iYWxgIGFuZCBhdm9pZCBgbGFzdEluZGV4YCBpc3N1ZXMgYnkgd29ya2luZyB3aXRoIGEgY29weVxuICAgICAgICAgICAgICAgICAgICBzZXBhcmF0b3IgPSBuZXcgUmVnRXhwKHNlcGFyYXRvci5zb3VyY2UsIGZsYWdzICsgXCJnXCIpLFxuICAgICAgICAgICAgICAgICAgICAgICAgc2VwYXJhdG9yMixcbiAgICAgICAgICAgICAgICAgICAgICAgIG1hdGNoLFxuICAgICAgICAgICAgICAgICAgICAgICAgbGFzdEluZGV4LFxuICAgICAgICAgICAgICAgICAgICAgICAgbGFzdExlbmd0aDtcbiAgICAgICAgICAgICAgICAgICAgc3RyICs9IFwiXCI7IC8vIFR5cGUtY29udmVydFxuICAgICAgICAgICAgICAgICAgICBpZiAoIWNvbXBsaWFudEV4ZWNOcGNnKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAvLyBEb2Vzbid0IG5lZWQgZmxhZ3MgZ3ksIGJ1dCB0aGV5IGRvbid0IGh1cnRcbiAgICAgICAgICAgICAgICAgICAgICAgIHNlcGFyYXRvcjIgPSBuZXcgUmVnRXhwKFwiXlwiICsgc2VwYXJhdG9yLnNvdXJjZSArIFwiJCg/IVxcXFxzKVwiLCBmbGFncyk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgLyogVmFsdWVzIGZvciBgbGltaXRgLCBwZXIgdGhlIHNwZWM6XG4gICAgICAgICAgICAgICAgICAgICAqIElmIHVuZGVmaW5lZDogNDI5NDk2NzI5NSAvLyBNYXRoLnBvdygyLCAzMikgLSAxXG4gICAgICAgICAgICAgICAgICAgICAqIElmIDAsIEluZmluaXR5LCBvciBOYU46IDBcbiAgICAgICAgICAgICAgICAgICAgICogSWYgcG9zaXRpdmUgbnVtYmVyOiBsaW1pdCA9IE1hdGguZmxvb3IobGltaXQpOyBpZiAobGltaXQgPiA0Mjk0OTY3Mjk1KSBsaW1pdCAtPSA0Mjk0OTY3Mjk2O1xuICAgICAgICAgICAgICAgICAgICAgKiBJZiBuZWdhdGl2ZSBudW1iZXI6IDQyOTQ5NjcyOTYgLSBNYXRoLmZsb29yKE1hdGguYWJzKGxpbWl0KSlcbiAgICAgICAgICAgICAgICAgICAgICogSWYgb3RoZXI6IFR5cGUtY29udmVydCwgdGhlbiB1c2UgdGhlIGFib3ZlIHJ1bGVzXG4gICAgICAgICAgICAgICAgICAgICAqL1xuICAgICAgICAgICAgICAgICAgICBsaW1pdCA9IGxpbWl0ID09PSB1bmRlZiA/IC0xID4+PiAwIDogLy8gTWF0aC5wb3coMiwgMzIpIC0gMVxuICAgICAgICAgICAgICAgICAgICBsaW1pdCA+Pj4gMDsgLy8gVG9VaW50MzIobGltaXQpXG4gICAgICAgICAgICAgICAgICAgIHdoaWxlIChtYXRjaCA9IHNlcGFyYXRvci5leGVjKHN0cikpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIGBzZXBhcmF0b3IubGFzdEluZGV4YCBpcyBub3QgcmVsaWFibGUgY3Jvc3MtYnJvd3NlclxuICAgICAgICAgICAgICAgICAgICAgICAgbGFzdEluZGV4ID0gbWF0Y2guaW5kZXggKyBtYXRjaFswXS5sZW5ndGg7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAobGFzdEluZGV4ID4gbGFzdExhc3RJbmRleCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIG91dHB1dC5wdXNoKHN0ci5zbGljZShsYXN0TGFzdEluZGV4LCBtYXRjaC5pbmRleCkpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIEZpeCBicm93c2VycyB3aG9zZSBgZXhlY2AgbWV0aG9kcyBkb24ndCBjb25zaXN0ZW50bHkgcmV0dXJuIGB1bmRlZmluZWRgIGZvclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIG5vbnBhcnRpY2lwYXRpbmcgY2FwdHVyaW5nIGdyb3Vwc1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmICghY29tcGxpYW50RXhlY05wY2cgJiYgbWF0Y2gubGVuZ3RoID4gMSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBtYXRjaFswXS5yZXBsYWNlKHNlcGFyYXRvcjIsIGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZvciAodmFyIGkgPSAxOyBpIDwgYXJndW1lbnRzLmxlbmd0aCAtIDI7IGkrKykge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChhcmd1bWVudHNbaV0gPT09IHVuZGVmKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1hdGNoW2ldID0gdW5kZWY7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKG1hdGNoLmxlbmd0aCA+IDEgJiYgbWF0Y2guaW5kZXggPCBzdHIubGVuZ3RoKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIEFycmF5LnByb3RvdHlwZS5wdXNoLmFwcGx5KG91dHB1dCwgbWF0Y2guc2xpY2UoMSkpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBsYXN0TGVuZ3RoID0gbWF0Y2hbMF0ubGVuZ3RoO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxhc3RMYXN0SW5kZXggPSBsYXN0SW5kZXg7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKG91dHB1dC5sZW5ndGggPj0gbGltaXQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHNlcGFyYXRvci5sYXN0SW5kZXggPT09IG1hdGNoLmluZGV4KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgc2VwYXJhdG9yLmxhc3RJbmRleCsrOyAvLyBBdm9pZCBhbiBpbmZpbml0ZSBsb29wXG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgaWYgKGxhc3RMYXN0SW5kZXggPT09IHN0ci5sZW5ndGgpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChsYXN0TGVuZ3RoIHx8ICFzZXBhcmF0b3IudGVzdChcIlwiKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIG91dHB1dC5wdXNoKFwiXCIpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgb3V0cHV0LnB1c2goc3RyLnNsaWNlKGxhc3RMYXN0SW5kZXgpKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICByZXR1cm4gb3V0cHV0Lmxlbmd0aCA+IGxpbWl0ID8gb3V0cHV0LnNsaWNlKDAsIGxpbWl0KSA6IG91dHB1dDtcbiAgICAgICAgICAgICAgICB9O1xuXG4gICAgICAgICAgICAgICAgcmV0dXJuIHNlbGY7XG4gICAgICAgICAgICB9KSgpO1xuICAgICAgICB9LCB7fV0sIDY6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7fSwge31dLCA3OiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge1xuICAgICAgICAgICAgXCJ1c2Ugc3RyaWN0XCI7XG5cbiAgICAgICAgICAgIHZhciBPbmVWZXJzaW9uQ29uc3RyYWludCA9IHJlcXVpcmUoXCJpbmRpdmlkdWFsL29uZS12ZXJzaW9uXCIpO1xuXG4gICAgICAgICAgICB2YXIgTVlfVkVSU0lPTiA9IFwiN1wiO1xuICAgICAgICAgICAgT25lVmVyc2lvbkNvbnN0cmFpbnQoXCJldi1zdG9yZVwiLCBNWV9WRVJTSU9OKTtcblxuICAgICAgICAgICAgdmFyIGhhc2hLZXkgPSBcIl9fRVZfU1RPUkVfS0VZQFwiICsgTVlfVkVSU0lPTjtcblxuICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBFdlN0b3JlO1xuXG4gICAgICAgICAgICBmdW5jdGlvbiBFdlN0b3JlKGVsZW0pIHtcbiAgICAgICAgICAgICAgICB2YXIgaGFzaCA9IGVsZW1baGFzaEtleV07XG5cbiAgICAgICAgICAgICAgICBpZiAoIWhhc2gpIHtcbiAgICAgICAgICAgICAgICAgICAgaGFzaCA9IGVsZW1baGFzaEtleV0gPSB7fTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICByZXR1cm4gaGFzaDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSwgeyBcImluZGl2aWR1YWwvb25lLXZlcnNpb25cIjogOSB9XSwgODogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHtcbiAgICAgICAgICAgIChmdW5jdGlvbiAoZ2xvYmFsKSB7XG4gICAgICAgICAgICAgICAgXCJ1c2Ugc3RyaWN0XCI7XG5cbiAgICAgICAgICAgICAgICAvKmdsb2JhbCB3aW5kb3csIGdsb2JhbCovXG5cbiAgICAgICAgICAgICAgICB2YXIgcm9vdCA9IHR5cGVvZiB3aW5kb3cgIT09IFwidW5kZWZpbmVkXCIgPyB3aW5kb3cgOiB0eXBlb2YgZ2xvYmFsICE9PSBcInVuZGVmaW5lZFwiID8gZ2xvYmFsIDoge307XG5cbiAgICAgICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IEluZGl2aWR1YWw7XG5cbiAgICAgICAgICAgICAgICBmdW5jdGlvbiBJbmRpdmlkdWFsKGtleSwgdmFsdWUpIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKGtleSBpbiByb290KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gcm9vdFtrZXldO1xuICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgcm9vdFtrZXldID0gdmFsdWU7XG5cbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHZhbHVlO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0pLmNhbGwodGhpcywgdHlwZW9mIGdsb2JhbCAhPT0gXCJ1bmRlZmluZWRcIiA/IGdsb2JhbCA6IHR5cGVvZiBzZWxmICE9PSBcInVuZGVmaW5lZFwiID8gc2VsZiA6IHR5cGVvZiB3aW5kb3cgIT09IFwidW5kZWZpbmVkXCIgPyB3aW5kb3cgOiB7fSk7XG4gICAgICAgIH0sIHt9XSwgOTogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHtcbiAgICAgICAgICAgIFwidXNlIHN0cmljdFwiO1xuXG4gICAgICAgICAgICB2YXIgSW5kaXZpZHVhbCA9IHJlcXVpcmUoXCIuL2luZGV4LmpzXCIpO1xuXG4gICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IE9uZVZlcnNpb247XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIE9uZVZlcnNpb24obW9kdWxlTmFtZSwgdmVyc2lvbiwgZGVmYXVsdFZhbHVlKSB7XG4gICAgICAgICAgICAgICAgdmFyIGtleSA9IFwiX19JTkRJVklEVUFMX09ORV9WRVJTSU9OX1wiICsgbW9kdWxlTmFtZTtcbiAgICAgICAgICAgICAgICB2YXIgZW5mb3JjZUtleSA9IGtleSArIFwiX0VORk9SQ0VfU0lOR0xFVE9OXCI7XG5cbiAgICAgICAgICAgICAgICB2YXIgdmVyc2lvblZhbHVlID0gSW5kaXZpZHVhbChlbmZvcmNlS2V5LCB2ZXJzaW9uKTtcblxuICAgICAgICAgICAgICAgIGlmICh2ZXJzaW9uVmFsdWUgIT09IHZlcnNpb24pIHtcbiAgICAgICAgICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKFwiQ2FuIG9ubHkgaGF2ZSBvbmUgY29weSBvZiBcIiArIG1vZHVsZU5hbWUgKyBcIi5cXG5cIiArIFwiWW91IGFscmVhZHkgaGF2ZSB2ZXJzaW9uIFwiICsgdmVyc2lvblZhbHVlICsgXCIgaW5zdGFsbGVkLlxcblwiICsgXCJUaGlzIG1lYW5zIHlvdSBjYW5ub3QgaW5zdGFsbCB2ZXJzaW9uIFwiICsgdmVyc2lvbik7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgcmV0dXJuIEluZGl2aWR1YWwoa2V5LCBkZWZhdWx0VmFsdWUpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9LCB7IFwiLi9pbmRleC5qc1wiOiA4IH1dLCAxMDogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHtcbiAgICAgICAgICAgIChmdW5jdGlvbiAoZ2xvYmFsKSB7XG4gICAgICAgICAgICAgICAgdmFyIHRvcExldmVsID0gdHlwZW9mIGdsb2JhbCAhPT0gXCJ1bmRlZmluZWRcIiA/IGdsb2JhbCA6IHR5cGVvZiB3aW5kb3cgIT09IFwidW5kZWZpbmVkXCIgPyB3aW5kb3cgOiB7fTtcbiAgICAgICAgICAgICAgICB2YXIgbWluRG9jID0gcmVxdWlyZShcIm1pbi1kb2N1bWVudFwiKTtcblxuICAgICAgICAgICAgICAgIGlmICh0eXBlb2YgZG9jdW1lbnQgIT09IFwidW5kZWZpbmVkXCIpIHtcbiAgICAgICAgICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBkb2N1bWVudDtcbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICB2YXIgZG9jY3kgPSB0b3BMZXZlbFtcIl9fR0xPQkFMX0RPQ1VNRU5UX0NBQ0hFQDRcIl07XG5cbiAgICAgICAgICAgICAgICAgICAgaWYgKCFkb2NjeSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgZG9jY3kgPSB0b3BMZXZlbFtcIl9fR0xPQkFMX0RPQ1VNRU5UX0NBQ0hFQDRcIl0gPSBtaW5Eb2M7XG4gICAgICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IGRvY2N5O1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0pLmNhbGwodGhpcywgdHlwZW9mIGdsb2JhbCAhPT0gXCJ1bmRlZmluZWRcIiA/IGdsb2JhbCA6IHR5cGVvZiBzZWxmICE9PSBcInVuZGVmaW5lZFwiID8gc2VsZiA6IHR5cGVvZiB3aW5kb3cgIT09IFwidW5kZWZpbmVkXCIgPyB3aW5kb3cgOiB7fSk7XG4gICAgICAgIH0sIHsgXCJtaW4tZG9jdW1lbnRcIjogNiB9XSwgMTE6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICBcInVzZSBzdHJpY3RcIjtcblxuICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiBpc09iamVjdCh4KSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHR5cGVvZiB4ID09PSBcIm9iamVjdFwiICYmIHggIT09IG51bGw7XG4gICAgICAgICAgICB9O1xuICAgICAgICB9LCB7fV0sIDEyOiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge1xuICAgICAgICAgICAgdmFyIG5hdGl2ZUlzQXJyYXkgPSBBcnJheS5pc0FycmF5O1xuICAgICAgICAgICAgdmFyIHRvU3RyaW5nID0gT2JqZWN0LnByb3RvdHlwZS50b1N0cmluZztcblxuICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBuYXRpdmVJc0FycmF5IHx8IGlzQXJyYXk7XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIGlzQXJyYXkob2JqKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHRvU3RyaW5nLmNhbGwob2JqKSA9PT0gXCJbb2JqZWN0IEFycmF5XVwiO1xuICAgICAgICAgICAgfVxuICAgICAgICB9LCB7fV0sIDEzOiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge1xuICAgICAgICAgICAgdmFyIHBhdGNoID0gcmVxdWlyZShcIi4vdmRvbS9wYXRjaC5qc1wiKTtcblxuICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBwYXRjaDtcbiAgICAgICAgfSwgeyBcIi4vdmRvbS9wYXRjaC5qc1wiOiAxOCB9XSwgMTQ6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICB2YXIgaXNPYmplY3QgPSByZXF1aXJlKFwiaXMtb2JqZWN0XCIpO1xuICAgICAgICAgICAgdmFyIGlzSG9vayA9IHJlcXVpcmUoXCIuLi92bm9kZS9pcy12aG9vay5qc1wiKTtcblxuICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBhcHBseVByb3BlcnRpZXM7XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIGFwcGx5UHJvcGVydGllcyhub2RlLCBwcm9wcywgcHJldmlvdXMpIHtcbiAgICAgICAgICAgICAgICBmb3IgKHZhciBwcm9wTmFtZSBpbiBwcm9wcykge1xuICAgICAgICAgICAgICAgICAgICB2YXIgcHJvcFZhbHVlID0gcHJvcHNbcHJvcE5hbWVdO1xuXG4gICAgICAgICAgICAgICAgICAgIGlmIChwcm9wVmFsdWUgPT09IHVuZGVmaW5lZCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgcmVtb3ZlUHJvcGVydHkobm9kZSwgcHJvcE5hbWUsIHByb3BWYWx1ZSwgcHJldmlvdXMpO1xuICAgICAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKGlzSG9vayhwcm9wVmFsdWUpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICByZW1vdmVQcm9wZXJ0eShub2RlLCBwcm9wTmFtZSwgcHJvcFZhbHVlLCBwcmV2aW91cyk7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAocHJvcFZhbHVlLmhvb2spIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBwcm9wVmFsdWUuaG9vayhub2RlLCBwcm9wTmFtZSwgcHJldmlvdXMgPyBwcmV2aW91c1twcm9wTmFtZV0gOiB1bmRlZmluZWQpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGlzT2JqZWN0KHByb3BWYWx1ZSkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBwYXRjaE9iamVjdChub2RlLCBwcm9wcywgcHJldmlvdXMsIHByb3BOYW1lLCBwcm9wVmFsdWUpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBub2RlW3Byb3BOYW1lXSA9IHByb3BWYWx1ZTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZnVuY3Rpb24gcmVtb3ZlUHJvcGVydHkobm9kZSwgcHJvcE5hbWUsIHByb3BWYWx1ZSwgcHJldmlvdXMpIHtcbiAgICAgICAgICAgICAgICBpZiAocHJldmlvdXMpIHtcbiAgICAgICAgICAgICAgICAgICAgdmFyIHByZXZpb3VzVmFsdWUgPSBwcmV2aW91c1twcm9wTmFtZV07XG5cbiAgICAgICAgICAgICAgICAgICAgaWYgKCFpc0hvb2socHJldmlvdXNWYWx1ZSkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChwcm9wTmFtZSA9PT0gXCJhdHRyaWJ1dGVzXCIpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBmb3IgKHZhciBhdHRyTmFtZSBpbiBwcmV2aW91c1ZhbHVlKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG5vZGUucmVtb3ZlQXR0cmlidXRlKGF0dHJOYW1lKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKHByb3BOYW1lID09PSBcInN0eWxlXCIpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBmb3IgKHZhciBpIGluIHByZXZpb3VzVmFsdWUpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbm9kZS5zdHlsZVtpXSA9IFwiXCI7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIGlmICh0eXBlb2YgcHJldmlvdXNWYWx1ZSA9PT0gXCJzdHJpbmdcIikge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIG5vZGVbcHJvcE5hbWVdID0gXCJcIjtcbiAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgbm9kZVtwcm9wTmFtZV0gPSBudWxsO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKHByZXZpb3VzVmFsdWUudW5ob29rKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBwcmV2aW91c1ZhbHVlLnVuaG9vayhub2RlLCBwcm9wTmFtZSwgcHJvcFZhbHVlKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZnVuY3Rpb24gcGF0Y2hPYmplY3Qobm9kZSwgcHJvcHMsIHByZXZpb3VzLCBwcm9wTmFtZSwgcHJvcFZhbHVlKSB7XG4gICAgICAgICAgICAgICAgdmFyIHByZXZpb3VzVmFsdWUgPSBwcmV2aW91cyA/IHByZXZpb3VzW3Byb3BOYW1lXSA6IHVuZGVmaW5lZDtcblxuICAgICAgICAgICAgICAgIC8vIFNldCBhdHRyaWJ1dGVzXG4gICAgICAgICAgICAgICAgaWYgKHByb3BOYW1lID09PSBcImF0dHJpYnV0ZXNcIikge1xuICAgICAgICAgICAgICAgICAgICBmb3IgKHZhciBhdHRyTmFtZSBpbiBwcm9wVmFsdWUpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHZhciBhdHRyVmFsdWUgPSBwcm9wVmFsdWVbYXR0ck5hbWVdO1xuXG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoYXR0clZhbHVlID09PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBub2RlLnJlbW92ZUF0dHJpYnV0ZShhdHRyTmFtZSk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIG5vZGUuc2V0QXR0cmlidXRlKGF0dHJOYW1lLCBhdHRyVmFsdWUpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIGlmIChwcmV2aW91c1ZhbHVlICYmIGlzT2JqZWN0KHByZXZpb3VzVmFsdWUpICYmIGdldFByb3RvdHlwZShwcmV2aW91c1ZhbHVlKSAhPT0gZ2V0UHJvdG90eXBlKHByb3BWYWx1ZSkpIHtcbiAgICAgICAgICAgICAgICAgICAgbm9kZVtwcm9wTmFtZV0gPSBwcm9wVmFsdWU7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICBpZiAoIWlzT2JqZWN0KG5vZGVbcHJvcE5hbWVdKSkge1xuICAgICAgICAgICAgICAgICAgICBub2RlW3Byb3BOYW1lXSA9IHt9O1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHZhciByZXBsYWNlciA9IHByb3BOYW1lID09PSBcInN0eWxlXCIgPyBcIlwiIDogdW5kZWZpbmVkO1xuXG4gICAgICAgICAgICAgICAgZm9yICh2YXIgayBpbiBwcm9wVmFsdWUpIHtcbiAgICAgICAgICAgICAgICAgICAgdmFyIHZhbHVlID0gcHJvcFZhbHVlW2tdO1xuICAgICAgICAgICAgICAgICAgICBub2RlW3Byb3BOYW1lXVtrXSA9IHZhbHVlID09PSB1bmRlZmluZWQgPyByZXBsYWNlciA6IHZhbHVlO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZnVuY3Rpb24gZ2V0UHJvdG90eXBlKHZhbHVlKSB7XG4gICAgICAgICAgICAgICAgaWYgKE9iamVjdC5nZXRQcm90b3R5cGVPZikge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gT2JqZWN0LmdldFByb3RvdHlwZU9mKHZhbHVlKTtcbiAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKHZhbHVlLl9fcHJvdG9fXykge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gdmFsdWUuX19wcm90b19fO1xuICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAodmFsdWUuY29uc3RydWN0b3IpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHZhbHVlLmNvbnN0cnVjdG9yLnByb3RvdHlwZTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH0sIHsgXCIuLi92bm9kZS9pcy12aG9vay5qc1wiOiAyNiwgXCJpcy1vYmplY3RcIjogMTEgfV0sIDE1OiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge1xuICAgICAgICAgICAgdmFyIGRvY3VtZW50ID0gcmVxdWlyZShcImdsb2JhbC9kb2N1bWVudFwiKTtcblxuICAgICAgICAgICAgdmFyIGFwcGx5UHJvcGVydGllcyA9IHJlcXVpcmUoXCIuL2FwcGx5LXByb3BlcnRpZXNcIik7XG5cbiAgICAgICAgICAgIHZhciBpc1ZOb2RlID0gcmVxdWlyZShcIi4uL3Zub2RlL2lzLXZub2RlLmpzXCIpO1xuICAgICAgICAgICAgdmFyIGlzVlRleHQgPSByZXF1aXJlKFwiLi4vdm5vZGUvaXMtdnRleHQuanNcIik7XG4gICAgICAgICAgICB2YXIgaXNXaWRnZXQgPSByZXF1aXJlKFwiLi4vdm5vZGUvaXMtd2lkZ2V0LmpzXCIpO1xuICAgICAgICAgICAgdmFyIGhhbmRsZVRodW5rID0gcmVxdWlyZShcIi4uL3Zub2RlL2hhbmRsZS10aHVuay5qc1wiKTtcblxuICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBjcmVhdGVFbGVtZW50O1xuXG4gICAgICAgICAgICBmdW5jdGlvbiBjcmVhdGVFbGVtZW50KHZub2RlLCBvcHRzKSB7XG4gICAgICAgICAgICAgICAgdmFyIGRvYyA9IG9wdHMgPyBvcHRzLmRvY3VtZW50IHx8IGRvY3VtZW50IDogZG9jdW1lbnQ7XG4gICAgICAgICAgICAgICAgdmFyIHdhcm4gPSBvcHRzID8gb3B0cy53YXJuIDogbnVsbDtcblxuICAgICAgICAgICAgICAgIHZub2RlID0gaGFuZGxlVGh1bmsodm5vZGUpLmE7XG5cbiAgICAgICAgICAgICAgICBpZiAoaXNXaWRnZXQodm5vZGUpKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiB2bm9kZS5pbml0KCk7XG4gICAgICAgICAgICAgICAgfSBlbHNlIGlmIChpc1ZUZXh0KHZub2RlKSkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gZG9jLmNyZWF0ZVRleHROb2RlKHZub2RlLnRleHQpO1xuICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoIWlzVk5vZGUodm5vZGUpKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmICh3YXJuKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICB3YXJuKFwiSXRlbSBpcyBub3QgYSB2YWxpZCB2aXJ0dWFsIGRvbSBub2RlXCIsIHZub2RlKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICByZXR1cm4gbnVsbDtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICB2YXIgbm9kZSA9IHZub2RlLm5hbWVzcGFjZSA9PT0gbnVsbCA/IGRvYy5jcmVhdGVFbGVtZW50KHZub2RlLnRhZ05hbWUpIDogZG9jLmNyZWF0ZUVsZW1lbnROUyh2bm9kZS5uYW1lc3BhY2UsIHZub2RlLnRhZ05hbWUpO1xuXG4gICAgICAgICAgICAgICAgdmFyIHByb3BzID0gdm5vZGUucHJvcGVydGllcztcbiAgICAgICAgICAgICAgICBhcHBseVByb3BlcnRpZXMobm9kZSwgcHJvcHMpO1xuXG4gICAgICAgICAgICAgICAgdmFyIGNoaWxkcmVuID0gdm5vZGUuY2hpbGRyZW47XG5cbiAgICAgICAgICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IGNoaWxkcmVuLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciBjaGlsZE5vZGUgPSBjcmVhdGVFbGVtZW50KGNoaWxkcmVuW2ldLCBvcHRzKTtcbiAgICAgICAgICAgICAgICAgICAgaWYgKGNoaWxkTm9kZSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgbm9kZS5hcHBlbmRDaGlsZChjaGlsZE5vZGUpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgcmV0dXJuIG5vZGU7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0sIHsgXCIuLi92bm9kZS9oYW5kbGUtdGh1bmsuanNcIjogMjQsIFwiLi4vdm5vZGUvaXMtdm5vZGUuanNcIjogMjcsIFwiLi4vdm5vZGUvaXMtdnRleHQuanNcIjogMjgsIFwiLi4vdm5vZGUvaXMtd2lkZ2V0LmpzXCI6IDI5LCBcIi4vYXBwbHktcHJvcGVydGllc1wiOiAxNCwgXCJnbG9iYWwvZG9jdW1lbnRcIjogMTAgfV0sIDE2OiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge1xuICAgICAgICAgICAgLy8gTWFwcyBhIHZpcnR1YWwgRE9NIHRyZWUgb250byBhIHJlYWwgRE9NIHRyZWUgaW4gYW4gZWZmaWNpZW50IG1hbm5lci5cbiAgICAgICAgICAgIC8vIFdlIGRvbid0IHdhbnQgdG8gcmVhZCBhbGwgb2YgdGhlIERPTSBub2RlcyBpbiB0aGUgdHJlZSBzbyB3ZSB1c2VcbiAgICAgICAgICAgIC8vIHRoZSBpbi1vcmRlciB0cmVlIGluZGV4aW5nIHRvIGVsaW1pbmF0ZSByZWN1cnNpb24gZG93biBjZXJ0YWluIGJyYW5jaGVzLlxuICAgICAgICAgICAgLy8gV2Ugb25seSByZWN1cnNlIGludG8gYSBET00gbm9kZSBpZiB3ZSBrbm93IHRoYXQgaXQgY29udGFpbnMgYSBjaGlsZCBvZlxuICAgICAgICAgICAgLy8gaW50ZXJlc3QuXG5cbiAgICAgICAgICAgIHZhciBub0NoaWxkID0ge307XG5cbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gZG9tSW5kZXg7XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIGRvbUluZGV4KHJvb3ROb2RlLCB0cmVlLCBpbmRpY2VzLCBub2Rlcykge1xuICAgICAgICAgICAgICAgIGlmICghaW5kaWNlcyB8fCBpbmRpY2VzLmxlbmd0aCA9PT0gMCkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4ge307XG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgaW5kaWNlcy5zb3J0KGFzY2VuZGluZyk7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiByZWN1cnNlKHJvb3ROb2RlLCB0cmVlLCBpbmRpY2VzLCBub2RlcywgMCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBmdW5jdGlvbiByZWN1cnNlKHJvb3ROb2RlLCB0cmVlLCBpbmRpY2VzLCBub2Rlcywgcm9vdEluZGV4KSB7XG4gICAgICAgICAgICAgICAgbm9kZXMgPSBub2RlcyB8fCB7fTtcblxuICAgICAgICAgICAgICAgIGlmIChyb290Tm9kZSkge1xuICAgICAgICAgICAgICAgICAgICBpZiAoaW5kZXhJblJhbmdlKGluZGljZXMsIHJvb3RJbmRleCwgcm9vdEluZGV4KSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgbm9kZXNbcm9vdEluZGV4XSA9IHJvb3ROb2RlO1xuICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgdmFyIHZDaGlsZHJlbiA9IHRyZWUuY2hpbGRyZW47XG5cbiAgICAgICAgICAgICAgICAgICAgaWYgKHZDaGlsZHJlbikge1xuXG4gICAgICAgICAgICAgICAgICAgICAgICB2YXIgY2hpbGROb2RlcyA9IHJvb3ROb2RlLmNoaWxkTm9kZXM7XG5cbiAgICAgICAgICAgICAgICAgICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgdHJlZS5jaGlsZHJlbi5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJvb3RJbmRleCArPSAxO1xuXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdmFyIHZDaGlsZCA9IHZDaGlsZHJlbltpXSB8fCBub0NoaWxkO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZhciBuZXh0SW5kZXggPSByb290SW5kZXggKyAodkNoaWxkLmNvdW50IHx8IDApO1xuXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gc2tpcCByZWN1cnNpb24gZG93biB0aGUgdHJlZSBpZiB0aGVyZSBhcmUgbm8gbm9kZXMgZG93biBoZXJlXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGluZGV4SW5SYW5nZShpbmRpY2VzLCByb290SW5kZXgsIG5leHRJbmRleCkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmVjdXJzZShjaGlsZE5vZGVzW2ldLCB2Q2hpbGQsIGluZGljZXMsIG5vZGVzLCByb290SW5kZXgpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJvb3RJbmRleCA9IG5leHRJbmRleDtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHJldHVybiBub2RlcztcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgLy8gQmluYXJ5IHNlYXJjaCBmb3IgYW4gaW5kZXggaW4gdGhlIGludGVydmFsIFtsZWZ0LCByaWdodF1cbiAgICAgICAgICAgIGZ1bmN0aW9uIGluZGV4SW5SYW5nZShpbmRpY2VzLCBsZWZ0LCByaWdodCkge1xuICAgICAgICAgICAgICAgIGlmIChpbmRpY2VzLmxlbmd0aCA9PT0gMCkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgdmFyIG1pbkluZGV4ID0gMDtcbiAgICAgICAgICAgICAgICB2YXIgbWF4SW5kZXggPSBpbmRpY2VzLmxlbmd0aCAtIDE7XG4gICAgICAgICAgICAgICAgdmFyIGN1cnJlbnRJbmRleDtcbiAgICAgICAgICAgICAgICB2YXIgY3VycmVudEl0ZW07XG5cbiAgICAgICAgICAgICAgICB3aGlsZSAobWluSW5kZXggPD0gbWF4SW5kZXgpIHtcbiAgICAgICAgICAgICAgICAgICAgY3VycmVudEluZGV4ID0gKG1heEluZGV4ICsgbWluSW5kZXgpIC8gMiA+PiAwO1xuICAgICAgICAgICAgICAgICAgICBjdXJyZW50SXRlbSA9IGluZGljZXNbY3VycmVudEluZGV4XTtcblxuICAgICAgICAgICAgICAgICAgICBpZiAobWluSW5kZXggPT09IG1heEluZGV4KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gY3VycmVudEl0ZW0gPj0gbGVmdCAmJiBjdXJyZW50SXRlbSA8PSByaWdodDtcbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIGlmIChjdXJyZW50SXRlbSA8IGxlZnQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIG1pbkluZGV4ID0gY3VycmVudEluZGV4ICsgMTtcbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIGlmIChjdXJyZW50SXRlbSA+IHJpZ2h0KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBtYXhJbmRleCA9IGN1cnJlbnRJbmRleCAtIDE7XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZnVuY3Rpb24gYXNjZW5kaW5nKGEsIGIpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gYSA+IGIgPyAxIDogLTE7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0sIHt9XSwgMTc6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICB2YXIgYXBwbHlQcm9wZXJ0aWVzID0gcmVxdWlyZShcIi4vYXBwbHktcHJvcGVydGllc1wiKTtcblxuICAgICAgICAgICAgdmFyIGlzV2lkZ2V0ID0gcmVxdWlyZShcIi4uL3Zub2RlL2lzLXdpZGdldC5qc1wiKTtcbiAgICAgICAgICAgIHZhciBWUGF0Y2ggPSByZXF1aXJlKFwiLi4vdm5vZGUvdnBhdGNoLmpzXCIpO1xuXG4gICAgICAgICAgICB2YXIgdXBkYXRlV2lkZ2V0ID0gcmVxdWlyZShcIi4vdXBkYXRlLXdpZGdldFwiKTtcblxuICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBhcHBseVBhdGNoO1xuXG4gICAgICAgICAgICBmdW5jdGlvbiBhcHBseVBhdGNoKHZwYXRjaCwgZG9tTm9kZSwgcmVuZGVyT3B0aW9ucykge1xuICAgICAgICAgICAgICAgIHZhciB0eXBlID0gdnBhdGNoLnR5cGU7XG4gICAgICAgICAgICAgICAgdmFyIHZOb2RlID0gdnBhdGNoLnZOb2RlO1xuICAgICAgICAgICAgICAgIHZhciBwYXRjaCA9IHZwYXRjaC5wYXRjaDtcblxuICAgICAgICAgICAgICAgIHN3aXRjaCAodHlwZSkge1xuICAgICAgICAgICAgICAgICAgICBjYXNlIFZQYXRjaC5SRU1PVkU6XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gcmVtb3ZlTm9kZShkb21Ob2RlLCB2Tm9kZSk7XG4gICAgICAgICAgICAgICAgICAgIGNhc2UgVlBhdGNoLklOU0VSVDpcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBpbnNlcnROb2RlKGRvbU5vZGUsIHBhdGNoLCByZW5kZXJPcHRpb25zKTtcbiAgICAgICAgICAgICAgICAgICAgY2FzZSBWUGF0Y2guVlRFWFQ6XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gc3RyaW5nUGF0Y2goZG9tTm9kZSwgdk5vZGUsIHBhdGNoLCByZW5kZXJPcHRpb25zKTtcbiAgICAgICAgICAgICAgICAgICAgY2FzZSBWUGF0Y2guV0lER0VUOlxuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHdpZGdldFBhdGNoKGRvbU5vZGUsIHZOb2RlLCBwYXRjaCwgcmVuZGVyT3B0aW9ucyk7XG4gICAgICAgICAgICAgICAgICAgIGNhc2UgVlBhdGNoLlZOT0RFOlxuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHZOb2RlUGF0Y2goZG9tTm9kZSwgdk5vZGUsIHBhdGNoLCByZW5kZXJPcHRpb25zKTtcbiAgICAgICAgICAgICAgICAgICAgY2FzZSBWUGF0Y2guT1JERVI6XG4gICAgICAgICAgICAgICAgICAgICAgICByZW9yZGVyQ2hpbGRyZW4oZG9tTm9kZSwgcGF0Y2gpO1xuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGRvbU5vZGU7XG4gICAgICAgICAgICAgICAgICAgIGNhc2UgVlBhdGNoLlBST1BTOlxuICAgICAgICAgICAgICAgICAgICAgICAgYXBwbHlQcm9wZXJ0aWVzKGRvbU5vZGUsIHBhdGNoLCB2Tm9kZS5wcm9wZXJ0aWVzKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBkb21Ob2RlO1xuICAgICAgICAgICAgICAgICAgICBjYXNlIFZQYXRjaC5USFVOSzpcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiByZXBsYWNlUm9vdChkb21Ob2RlLCByZW5kZXJPcHRpb25zLnBhdGNoKGRvbU5vZGUsIHBhdGNoLCByZW5kZXJPcHRpb25zKSk7XG4gICAgICAgICAgICAgICAgICAgIGRlZmF1bHQ6XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gZG9tTm9kZTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIHJlbW92ZU5vZGUoZG9tTm9kZSwgdk5vZGUpIHtcbiAgICAgICAgICAgICAgICB2YXIgcGFyZW50Tm9kZSA9IGRvbU5vZGUucGFyZW50Tm9kZTtcblxuICAgICAgICAgICAgICAgIGlmIChwYXJlbnROb2RlKSB7XG4gICAgICAgICAgICAgICAgICAgIHBhcmVudE5vZGUucmVtb3ZlQ2hpbGQoZG9tTm9kZSk7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgZGVzdHJveVdpZGdldChkb21Ob2RlLCB2Tm9kZSk7XG5cbiAgICAgICAgICAgICAgICByZXR1cm4gbnVsbDtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZnVuY3Rpb24gaW5zZXJ0Tm9kZShwYXJlbnROb2RlLCB2Tm9kZSwgcmVuZGVyT3B0aW9ucykge1xuICAgICAgICAgICAgICAgIHZhciBuZXdOb2RlID0gcmVuZGVyT3B0aW9ucy5yZW5kZXIodk5vZGUsIHJlbmRlck9wdGlvbnMpO1xuXG4gICAgICAgICAgICAgICAgaWYgKHBhcmVudE5vZGUpIHtcbiAgICAgICAgICAgICAgICAgICAgcGFyZW50Tm9kZS5hcHBlbmRDaGlsZChuZXdOb2RlKTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICByZXR1cm4gcGFyZW50Tm9kZTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZnVuY3Rpb24gc3RyaW5nUGF0Y2goZG9tTm9kZSwgbGVmdFZOb2RlLCB2VGV4dCwgcmVuZGVyT3B0aW9ucykge1xuICAgICAgICAgICAgICAgIHZhciBuZXdOb2RlO1xuXG4gICAgICAgICAgICAgICAgaWYgKGRvbU5vZGUubm9kZVR5cGUgPT09IDMpIHtcbiAgICAgICAgICAgICAgICAgICAgZG9tTm9kZS5yZXBsYWNlRGF0YSgwLCBkb21Ob2RlLmxlbmd0aCwgdlRleHQudGV4dCk7XG4gICAgICAgICAgICAgICAgICAgIG5ld05vZGUgPSBkb21Ob2RlO1xuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciBwYXJlbnROb2RlID0gZG9tTm9kZS5wYXJlbnROb2RlO1xuICAgICAgICAgICAgICAgICAgICBuZXdOb2RlID0gcmVuZGVyT3B0aW9ucy5yZW5kZXIodlRleHQsIHJlbmRlck9wdGlvbnMpO1xuXG4gICAgICAgICAgICAgICAgICAgIGlmIChwYXJlbnROb2RlICYmIG5ld05vZGUgIT09IGRvbU5vZGUpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHBhcmVudE5vZGUucmVwbGFjZUNoaWxkKG5ld05vZGUsIGRvbU5vZGUpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgcmV0dXJuIG5ld05vZGU7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIHdpZGdldFBhdGNoKGRvbU5vZGUsIGxlZnRWTm9kZSwgd2lkZ2V0LCByZW5kZXJPcHRpb25zKSB7XG4gICAgICAgICAgICAgICAgdmFyIHVwZGF0aW5nID0gdXBkYXRlV2lkZ2V0KGxlZnRWTm9kZSwgd2lkZ2V0KTtcbiAgICAgICAgICAgICAgICB2YXIgbmV3Tm9kZTtcblxuICAgICAgICAgICAgICAgIGlmICh1cGRhdGluZykge1xuICAgICAgICAgICAgICAgICAgICBuZXdOb2RlID0gd2lkZ2V0LnVwZGF0ZShsZWZ0Vk5vZGUsIGRvbU5vZGUpIHx8IGRvbU5vZGU7XG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgbmV3Tm9kZSA9IHJlbmRlck9wdGlvbnMucmVuZGVyKHdpZGdldCwgcmVuZGVyT3B0aW9ucyk7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgdmFyIHBhcmVudE5vZGUgPSBkb21Ob2RlLnBhcmVudE5vZGU7XG5cbiAgICAgICAgICAgICAgICBpZiAocGFyZW50Tm9kZSAmJiBuZXdOb2RlICE9PSBkb21Ob2RlKSB7XG4gICAgICAgICAgICAgICAgICAgIHBhcmVudE5vZGUucmVwbGFjZUNoaWxkKG5ld05vZGUsIGRvbU5vZGUpO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIGlmICghdXBkYXRpbmcpIHtcbiAgICAgICAgICAgICAgICAgICAgZGVzdHJveVdpZGdldChkb21Ob2RlLCBsZWZ0Vk5vZGUpO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHJldHVybiBuZXdOb2RlO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBmdW5jdGlvbiB2Tm9kZVBhdGNoKGRvbU5vZGUsIGxlZnRWTm9kZSwgdk5vZGUsIHJlbmRlck9wdGlvbnMpIHtcbiAgICAgICAgICAgICAgICB2YXIgcGFyZW50Tm9kZSA9IGRvbU5vZGUucGFyZW50Tm9kZTtcbiAgICAgICAgICAgICAgICB2YXIgbmV3Tm9kZSA9IHJlbmRlck9wdGlvbnMucmVuZGVyKHZOb2RlLCByZW5kZXJPcHRpb25zKTtcblxuICAgICAgICAgICAgICAgIGlmIChwYXJlbnROb2RlICYmIG5ld05vZGUgIT09IGRvbU5vZGUpIHtcbiAgICAgICAgICAgICAgICAgICAgcGFyZW50Tm9kZS5yZXBsYWNlQ2hpbGQobmV3Tm9kZSwgZG9tTm9kZSk7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgcmV0dXJuIG5ld05vZGU7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIGRlc3Ryb3lXaWRnZXQoZG9tTm9kZSwgdykge1xuICAgICAgICAgICAgICAgIGlmICh0eXBlb2Ygdy5kZXN0cm95ID09PSBcImZ1bmN0aW9uXCIgJiYgaXNXaWRnZXQodykpIHtcbiAgICAgICAgICAgICAgICAgICAgdy5kZXN0cm95KGRvbU5vZGUpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZnVuY3Rpb24gcmVvcmRlckNoaWxkcmVuKGRvbU5vZGUsIG1vdmVzKSB7XG4gICAgICAgICAgICAgICAgdmFyIGNoaWxkTm9kZXMgPSBkb21Ob2RlLmNoaWxkTm9kZXM7XG4gICAgICAgICAgICAgICAgdmFyIGtleU1hcCA9IHt9O1xuICAgICAgICAgICAgICAgIHZhciBub2RlO1xuICAgICAgICAgICAgICAgIHZhciByZW1vdmU7XG4gICAgICAgICAgICAgICAgdmFyIGluc2VydDtcblxuICAgICAgICAgICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgbW92ZXMucmVtb3Zlcy5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgICAgICAgICByZW1vdmUgPSBtb3Zlcy5yZW1vdmVzW2ldO1xuICAgICAgICAgICAgICAgICAgICBub2RlID0gY2hpbGROb2Rlc1tyZW1vdmUuZnJvbV07XG4gICAgICAgICAgICAgICAgICAgIGlmIChyZW1vdmUua2V5KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBrZXlNYXBbcmVtb3ZlLmtleV0gPSBub2RlO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIGRvbU5vZGUucmVtb3ZlQ2hpbGQobm9kZSk7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgdmFyIGxlbmd0aCA9IGNoaWxkTm9kZXMubGVuZ3RoO1xuICAgICAgICAgICAgICAgIGZvciAodmFyIGogPSAwOyBqIDwgbW92ZXMuaW5zZXJ0cy5sZW5ndGg7IGorKykge1xuICAgICAgICAgICAgICAgICAgICBpbnNlcnQgPSBtb3Zlcy5pbnNlcnRzW2pdO1xuICAgICAgICAgICAgICAgICAgICBub2RlID0ga2V5TWFwW2luc2VydC5rZXldO1xuICAgICAgICAgICAgICAgICAgICAvLyB0aGlzIGlzIHRoZSB3ZWlyZGVzdCBidWcgaSd2ZSBldmVyIHNlZW4gaW4gd2Via2l0XG4gICAgICAgICAgICAgICAgICAgIGRvbU5vZGUuaW5zZXJ0QmVmb3JlKG5vZGUsIGluc2VydC50byA+PSBsZW5ndGgrKyA/IG51bGwgOiBjaGlsZE5vZGVzW2luc2VydC50b10pO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZnVuY3Rpb24gcmVwbGFjZVJvb3Qob2xkUm9vdCwgbmV3Um9vdCkge1xuICAgICAgICAgICAgICAgIGlmIChvbGRSb290ICYmIG5ld1Jvb3QgJiYgb2xkUm9vdCAhPT0gbmV3Um9vdCAmJiBvbGRSb290LnBhcmVudE5vZGUpIHtcbiAgICAgICAgICAgICAgICAgICAgb2xkUm9vdC5wYXJlbnROb2RlLnJlcGxhY2VDaGlsZChuZXdSb290LCBvbGRSb290KTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICByZXR1cm4gbmV3Um9vdDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSwgeyBcIi4uL3Zub2RlL2lzLXdpZGdldC5qc1wiOiAyOSwgXCIuLi92bm9kZS92cGF0Y2guanNcIjogMzIsIFwiLi9hcHBseS1wcm9wZXJ0aWVzXCI6IDE0LCBcIi4vdXBkYXRlLXdpZGdldFwiOiAxOSB9XSwgMTg6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICB2YXIgZG9jdW1lbnQgPSByZXF1aXJlKFwiZ2xvYmFsL2RvY3VtZW50XCIpO1xuICAgICAgICAgICAgdmFyIGlzQXJyYXkgPSByZXF1aXJlKFwieC1pcy1hcnJheVwiKTtcblxuICAgICAgICAgICAgdmFyIHJlbmRlciA9IHJlcXVpcmUoXCIuL2NyZWF0ZS1lbGVtZW50XCIpO1xuICAgICAgICAgICAgdmFyIGRvbUluZGV4ID0gcmVxdWlyZShcIi4vZG9tLWluZGV4XCIpO1xuICAgICAgICAgICAgdmFyIHBhdGNoT3AgPSByZXF1aXJlKFwiLi9wYXRjaC1vcFwiKTtcbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gcGF0Y2g7XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIHBhdGNoKHJvb3ROb2RlLCBwYXRjaGVzLCByZW5kZXJPcHRpb25zKSB7XG4gICAgICAgICAgICAgICAgcmVuZGVyT3B0aW9ucyA9IHJlbmRlck9wdGlvbnMgfHwge307XG4gICAgICAgICAgICAgICAgcmVuZGVyT3B0aW9ucy5wYXRjaCA9IHJlbmRlck9wdGlvbnMucGF0Y2ggJiYgcmVuZGVyT3B0aW9ucy5wYXRjaCAhPT0gcGF0Y2ggPyByZW5kZXJPcHRpb25zLnBhdGNoIDogcGF0Y2hSZWN1cnNpdmU7XG4gICAgICAgICAgICAgICAgcmVuZGVyT3B0aW9ucy5yZW5kZXIgPSByZW5kZXJPcHRpb25zLnJlbmRlciB8fCByZW5kZXI7XG5cbiAgICAgICAgICAgICAgICByZXR1cm4gcmVuZGVyT3B0aW9ucy5wYXRjaChyb290Tm9kZSwgcGF0Y2hlcywgcmVuZGVyT3B0aW9ucyk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIHBhdGNoUmVjdXJzaXZlKHJvb3ROb2RlLCBwYXRjaGVzLCByZW5kZXJPcHRpb25zKSB7XG4gICAgICAgICAgICAgICAgdmFyIGluZGljZXMgPSBwYXRjaEluZGljZXMocGF0Y2hlcyk7XG5cbiAgICAgICAgICAgICAgICBpZiAoaW5kaWNlcy5sZW5ndGggPT09IDApIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHJvb3ROb2RlO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHZhciBpbmRleCA9IGRvbUluZGV4KHJvb3ROb2RlLCBwYXRjaGVzLmEsIGluZGljZXMpO1xuICAgICAgICAgICAgICAgIHZhciBvd25lckRvY3VtZW50ID0gcm9vdE5vZGUub3duZXJEb2N1bWVudDtcblxuICAgICAgICAgICAgICAgIGlmICghcmVuZGVyT3B0aW9ucy5kb2N1bWVudCAmJiBvd25lckRvY3VtZW50ICE9PSBkb2N1bWVudCkge1xuICAgICAgICAgICAgICAgICAgICByZW5kZXJPcHRpb25zLmRvY3VtZW50ID0gb3duZXJEb2N1bWVudDtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IGluZGljZXMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgICAgICAgICAgdmFyIG5vZGVJbmRleCA9IGluZGljZXNbaV07XG4gICAgICAgICAgICAgICAgICAgIHJvb3ROb2RlID0gYXBwbHlQYXRjaChyb290Tm9kZSwgaW5kZXhbbm9kZUluZGV4XSwgcGF0Y2hlc1tub2RlSW5kZXhdLCByZW5kZXJPcHRpb25zKTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICByZXR1cm4gcm9vdE5vZGU7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIGFwcGx5UGF0Y2gocm9vdE5vZGUsIGRvbU5vZGUsIHBhdGNoTGlzdCwgcmVuZGVyT3B0aW9ucykge1xuICAgICAgICAgICAgICAgIGlmICghZG9tTm9kZSkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gcm9vdE5vZGU7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgdmFyIG5ld05vZGU7XG5cbiAgICAgICAgICAgICAgICBpZiAoaXNBcnJheShwYXRjaExpc3QpKSB7XG4gICAgICAgICAgICAgICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgcGF0Y2hMaXN0Lmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBuZXdOb2RlID0gcGF0Y2hPcChwYXRjaExpc3RbaV0sIGRvbU5vZGUsIHJlbmRlck9wdGlvbnMpO1xuXG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoZG9tTm9kZSA9PT0gcm9vdE5vZGUpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICByb290Tm9kZSA9IG5ld05vZGU7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICBuZXdOb2RlID0gcGF0Y2hPcChwYXRjaExpc3QsIGRvbU5vZGUsIHJlbmRlck9wdGlvbnMpO1xuXG4gICAgICAgICAgICAgICAgICAgIGlmIChkb21Ob2RlID09PSByb290Tm9kZSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgcm9vdE5vZGUgPSBuZXdOb2RlO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgcmV0dXJuIHJvb3ROb2RlO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBmdW5jdGlvbiBwYXRjaEluZGljZXMocGF0Y2hlcykge1xuICAgICAgICAgICAgICAgIHZhciBpbmRpY2VzID0gW107XG5cbiAgICAgICAgICAgICAgICBmb3IgKHZhciBrZXkgaW4gcGF0Y2hlcykge1xuICAgICAgICAgICAgICAgICAgICBpZiAoa2V5ICE9PSBcImFcIikge1xuICAgICAgICAgICAgICAgICAgICAgICAgaW5kaWNlcy5wdXNoKE51bWJlcihrZXkpKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHJldHVybiBpbmRpY2VzO1xuICAgICAgICAgICAgfVxuICAgICAgICB9LCB7IFwiLi9jcmVhdGUtZWxlbWVudFwiOiAxNSwgXCIuL2RvbS1pbmRleFwiOiAxNiwgXCIuL3BhdGNoLW9wXCI6IDE3LCBcImdsb2JhbC9kb2N1bWVudFwiOiAxMCwgXCJ4LWlzLWFycmF5XCI6IDEyIH1dLCAxOTogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHtcbiAgICAgICAgICAgIHZhciBpc1dpZGdldCA9IHJlcXVpcmUoXCIuLi92bm9kZS9pcy13aWRnZXQuanNcIik7XG5cbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gdXBkYXRlV2lkZ2V0O1xuXG4gICAgICAgICAgICBmdW5jdGlvbiB1cGRhdGVXaWRnZXQoYSwgYikge1xuICAgICAgICAgICAgICAgIGlmIChpc1dpZGdldChhKSAmJiBpc1dpZGdldChiKSkge1xuICAgICAgICAgICAgICAgICAgICBpZiAoXCJuYW1lXCIgaW4gYSAmJiBcIm5hbWVcIiBpbiBiKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gYS5pZCA9PT0gYi5pZDtcbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBhLmluaXQgPT09IGIuaW5pdDtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSwgeyBcIi4uL3Zub2RlL2lzLXdpZGdldC5qc1wiOiAyOSB9XSwgMjA6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICBcInVzZSBzdHJpY3RcIjtcblxuICAgICAgICAgICAgdmFyIEV2U3RvcmUgPSByZXF1aXJlKFwiZXYtc3RvcmVcIik7XG5cbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gRXZIb29rO1xuXG4gICAgICAgICAgICBmdW5jdGlvbiBFdkhvb2sodmFsdWUpIHtcbiAgICAgICAgICAgICAgICBpZiAoISh0aGlzIGluc3RhbmNlb2YgRXZIb29rKSkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gbmV3IEV2SG9vayh2YWx1ZSk7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgdGhpcy52YWx1ZSA9IHZhbHVlO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBFdkhvb2sucHJvdG90eXBlLmhvb2sgPSBmdW5jdGlvbiAobm9kZSwgcHJvcGVydHlOYW1lKSB7XG4gICAgICAgICAgICAgICAgdmFyIGVzID0gRXZTdG9yZShub2RlKTtcbiAgICAgICAgICAgICAgICB2YXIgcHJvcE5hbWUgPSBwcm9wZXJ0eU5hbWUuc3Vic3RyKDMpO1xuXG4gICAgICAgICAgICAgICAgZXNbcHJvcE5hbWVdID0gdGhpcy52YWx1ZTtcbiAgICAgICAgICAgIH07XG5cbiAgICAgICAgICAgIEV2SG9vay5wcm90b3R5cGUudW5ob29rID0gZnVuY3Rpb24gKG5vZGUsIHByb3BlcnR5TmFtZSkge1xuICAgICAgICAgICAgICAgIHZhciBlcyA9IEV2U3RvcmUobm9kZSk7XG4gICAgICAgICAgICAgICAgdmFyIHByb3BOYW1lID0gcHJvcGVydHlOYW1lLnN1YnN0cigzKTtcblxuICAgICAgICAgICAgICAgIGVzW3Byb3BOYW1lXSA9IHVuZGVmaW5lZDtcbiAgICAgICAgICAgIH07XG4gICAgICAgIH0sIHsgXCJldi1zdG9yZVwiOiA3IH1dLCAyMTogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHtcbiAgICAgICAgICAgIFwidXNlIHN0cmljdFwiO1xuXG4gICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IFNvZnRTZXRIb29rO1xuXG4gICAgICAgICAgICBmdW5jdGlvbiBTb2Z0U2V0SG9vayh2YWx1ZSkge1xuICAgICAgICAgICAgICAgIGlmICghKHRoaXMgaW5zdGFuY2VvZiBTb2Z0U2V0SG9vaykpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIG5ldyBTb2Z0U2V0SG9vayh2YWx1ZSk7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgdGhpcy52YWx1ZSA9IHZhbHVlO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBTb2Z0U2V0SG9vay5wcm90b3R5cGUuaG9vayA9IGZ1bmN0aW9uIChub2RlLCBwcm9wZXJ0eU5hbWUpIHtcbiAgICAgICAgICAgICAgICBpZiAobm9kZVtwcm9wZXJ0eU5hbWVdICE9PSB0aGlzLnZhbHVlKSB7XG4gICAgICAgICAgICAgICAgICAgIG5vZGVbcHJvcGVydHlOYW1lXSA9IHRoaXMudmFsdWU7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfTtcbiAgICAgICAgfSwge31dLCAyMjogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHtcbiAgICAgICAgICAgIFwidXNlIHN0cmljdFwiO1xuXG4gICAgICAgICAgICB2YXIgaXNBcnJheSA9IHJlcXVpcmUoXCJ4LWlzLWFycmF5XCIpO1xuXG4gICAgICAgICAgICB2YXIgVk5vZGUgPSByZXF1aXJlKFwiLi4vdm5vZGUvdm5vZGUuanNcIik7XG4gICAgICAgICAgICB2YXIgVlRleHQgPSByZXF1aXJlKFwiLi4vdm5vZGUvdnRleHQuanNcIik7XG4gICAgICAgICAgICB2YXIgaXNWTm9kZSA9IHJlcXVpcmUoXCIuLi92bm9kZS9pcy12bm9kZVwiKTtcbiAgICAgICAgICAgIHZhciBpc1ZUZXh0ID0gcmVxdWlyZShcIi4uL3Zub2RlL2lzLXZ0ZXh0XCIpO1xuICAgICAgICAgICAgdmFyIGlzV2lkZ2V0ID0gcmVxdWlyZShcIi4uL3Zub2RlL2lzLXdpZGdldFwiKTtcbiAgICAgICAgICAgIHZhciBpc0hvb2sgPSByZXF1aXJlKFwiLi4vdm5vZGUvaXMtdmhvb2tcIik7XG4gICAgICAgICAgICB2YXIgaXNWVGh1bmsgPSByZXF1aXJlKFwiLi4vdm5vZGUvaXMtdGh1bmtcIik7XG5cbiAgICAgICAgICAgIHZhciBwYXJzZVRhZyA9IHJlcXVpcmUoXCIuL3BhcnNlLXRhZy5qc1wiKTtcbiAgICAgICAgICAgIHZhciBzb2Z0U2V0SG9vayA9IHJlcXVpcmUoXCIuL2hvb2tzL3NvZnQtc2V0LWhvb2suanNcIik7XG4gICAgICAgICAgICB2YXIgZXZIb29rID0gcmVxdWlyZShcIi4vaG9va3MvZXYtaG9vay5qc1wiKTtcblxuICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBoO1xuXG4gICAgICAgICAgICBmdW5jdGlvbiBoKHRhZ05hbWUsIHByb3BlcnRpZXMsIGNoaWxkcmVuKSB7XG4gICAgICAgICAgICAgICAgdmFyIGNoaWxkTm9kZXMgPSBbXTtcbiAgICAgICAgICAgICAgICB2YXIgdGFnLCBwcm9wcywga2V5LCBuYW1lc3BhY2U7XG5cbiAgICAgICAgICAgICAgICBpZiAoIWNoaWxkcmVuICYmIGlzQ2hpbGRyZW4ocHJvcGVydGllcykpIHtcbiAgICAgICAgICAgICAgICAgICAgY2hpbGRyZW4gPSBwcm9wZXJ0aWVzO1xuICAgICAgICAgICAgICAgICAgICBwcm9wcyA9IHt9O1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHByb3BzID0gcHJvcHMgfHwgcHJvcGVydGllcyB8fCB7fTtcbiAgICAgICAgICAgICAgICB0YWcgPSBwYXJzZVRhZyh0YWdOYW1lLCBwcm9wcyk7XG5cbiAgICAgICAgICAgICAgICAvLyBzdXBwb3J0IGtleXNcbiAgICAgICAgICAgICAgICBpZiAocHJvcHMuaGFzT3duUHJvcGVydHkoXCJrZXlcIikpIHtcbiAgICAgICAgICAgICAgICAgICAga2V5ID0gcHJvcHMua2V5O1xuICAgICAgICAgICAgICAgICAgICBwcm9wcy5rZXkgPSB1bmRlZmluZWQ7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgLy8gc3VwcG9ydCBuYW1lc3BhY2VcbiAgICAgICAgICAgICAgICBpZiAocHJvcHMuaGFzT3duUHJvcGVydHkoXCJuYW1lc3BhY2VcIikpIHtcbiAgICAgICAgICAgICAgICAgICAgbmFtZXNwYWNlID0gcHJvcHMubmFtZXNwYWNlO1xuICAgICAgICAgICAgICAgICAgICBwcm9wcy5uYW1lc3BhY2UgPSB1bmRlZmluZWQ7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgLy8gZml4IGN1cnNvciBidWdcbiAgICAgICAgICAgICAgICBpZiAodGFnID09PSBcIklOUFVUXCIgJiYgIW5hbWVzcGFjZSAmJiBwcm9wcy5oYXNPd25Qcm9wZXJ0eShcInZhbHVlXCIpICYmIHByb3BzLnZhbHVlICE9PSB1bmRlZmluZWQgJiYgIWlzSG9vayhwcm9wcy52YWx1ZSkpIHtcbiAgICAgICAgICAgICAgICAgICAgcHJvcHMudmFsdWUgPSBzb2Z0U2V0SG9vayhwcm9wcy52YWx1ZSk7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgdHJhbnNmb3JtUHJvcGVydGllcyhwcm9wcyk7XG5cbiAgICAgICAgICAgICAgICBpZiAoY2hpbGRyZW4gIT09IHVuZGVmaW5lZCAmJiBjaGlsZHJlbiAhPT0gbnVsbCkge1xuICAgICAgICAgICAgICAgICAgICBhZGRDaGlsZChjaGlsZHJlbiwgY2hpbGROb2RlcywgdGFnLCBwcm9wcyk7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgcmV0dXJuIG5ldyBWTm9kZSh0YWcsIHByb3BzLCBjaGlsZE5vZGVzLCBrZXksIG5hbWVzcGFjZSk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIGFkZENoaWxkKGMsIGNoaWxkTm9kZXMsIHRhZywgcHJvcHMpIHtcbiAgICAgICAgICAgICAgICBpZiAodHlwZW9mIGMgPT09IFwic3RyaW5nXCIpIHtcbiAgICAgICAgICAgICAgICAgICAgY2hpbGROb2Rlcy5wdXNoKG5ldyBWVGV4dChjKSk7XG4gICAgICAgICAgICAgICAgfSBlbHNlIGlmICh0eXBlb2YgYyA9PT0gXCJudW1iZXJcIikge1xuICAgICAgICAgICAgICAgICAgICBjaGlsZE5vZGVzLnB1c2gobmV3IFZUZXh0KFN0cmluZyhjKSkpO1xuICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoaXNDaGlsZChjKSkge1xuICAgICAgICAgICAgICAgICAgICBjaGlsZE5vZGVzLnB1c2goYyk7XG4gICAgICAgICAgICAgICAgfSBlbHNlIGlmIChpc0FycmF5KGMpKSB7XG4gICAgICAgICAgICAgICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgYy5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgICAgICAgICAgICAgYWRkQ2hpbGQoY1tpXSwgY2hpbGROb2RlcywgdGFnLCBwcm9wcyk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKGMgPT09IG51bGwgfHwgYyA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICB0aHJvdyBVbmV4cGVjdGVkVmlydHVhbEVsZW1lbnQoe1xuICAgICAgICAgICAgICAgICAgICAgICAgZm9yZWlnbk9iamVjdDogYyxcbiAgICAgICAgICAgICAgICAgICAgICAgIHBhcmVudFZub2RlOiB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdGFnTmFtZTogdGFnLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHByb3BlcnRpZXM6IHByb3BzXG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZnVuY3Rpb24gdHJhbnNmb3JtUHJvcGVydGllcyhwcm9wcykge1xuICAgICAgICAgICAgICAgIGZvciAodmFyIHByb3BOYW1lIGluIHByb3BzKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmIChwcm9wcy5oYXNPd25Qcm9wZXJ0eShwcm9wTmFtZSkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHZhciB2YWx1ZSA9IHByb3BzW3Byb3BOYW1lXTtcblxuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGlzSG9vayh2YWx1ZSkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb250aW51ZTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHByb3BOYW1lLnN1YnN0cigwLCAzKSA9PT0gXCJldi1cIikge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIGFkZCBldi1mb28gc3VwcG9ydFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHByb3BzW3Byb3BOYW1lXSA9IGV2SG9vayh2YWx1ZSk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIGlzQ2hpbGQoeCkge1xuICAgICAgICAgICAgICAgIHJldHVybiBpc1ZOb2RlKHgpIHx8IGlzVlRleHQoeCkgfHwgaXNXaWRnZXQoeCkgfHwgaXNWVGh1bmsoeCk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIGlzQ2hpbGRyZW4oeCkge1xuICAgICAgICAgICAgICAgIHJldHVybiB0eXBlb2YgeCA9PT0gXCJzdHJpbmdcIiB8fCBpc0FycmF5KHgpIHx8IGlzQ2hpbGQoeCk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIFVuZXhwZWN0ZWRWaXJ0dWFsRWxlbWVudChkYXRhKSB7XG4gICAgICAgICAgICAgICAgdmFyIGVyciA9IG5ldyBFcnJvcigpO1xuXG4gICAgICAgICAgICAgICAgZXJyLnR5cGUgPSBcInZpcnR1YWwtaHlwZXJzY3JpcHQudW5leHBlY3RlZC52aXJ0dWFsLWVsZW1lbnRcIjtcbiAgICAgICAgICAgICAgICBlcnIubWVzc2FnZSA9IFwiVW5leHBlY3RlZCB2aXJ0dWFsIGNoaWxkIHBhc3NlZCB0byBoKCkuXFxuXCIgKyBcIkV4cGVjdGVkIGEgVk5vZGUgLyBWdGh1bmsgLyBWV2lkZ2V0IC8gc3RyaW5nIGJ1dDpcXG5cIiArIFwiZ290OlxcblwiICsgZXJyb3JTdHJpbmcoZGF0YS5mb3JlaWduT2JqZWN0KSArIFwiLlxcblwiICsgXCJUaGUgcGFyZW50IHZub2RlIGlzOlxcblwiICsgZXJyb3JTdHJpbmcoZGF0YS5wYXJlbnRWbm9kZSk7XG4gICAgICAgICAgICAgICAgXCJcXG5cIiArIFwiU3VnZ2VzdGVkIGZpeDogY2hhbmdlIHlvdXIgYGgoLi4uLCBbIC4uLiBdKWAgY2FsbHNpdGUuXCI7XG4gICAgICAgICAgICAgICAgZXJyLmZvcmVpZ25PYmplY3QgPSBkYXRhLmZvcmVpZ25PYmplY3Q7XG4gICAgICAgICAgICAgICAgZXJyLnBhcmVudFZub2RlID0gZGF0YS5wYXJlbnRWbm9kZTtcblxuICAgICAgICAgICAgICAgIHJldHVybiBlcnI7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIGVycm9yU3RyaW5nKG9iaikge1xuICAgICAgICAgICAgICAgIHRyeSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBKU09OLnN0cmluZ2lmeShvYmosIG51bGwsIFwiICAgIFwiKTtcbiAgICAgICAgICAgICAgICB9IGNhdGNoIChlKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBTdHJpbmcob2JqKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH0sIHsgXCIuLi92bm9kZS9pcy10aHVua1wiOiAyNSwgXCIuLi92bm9kZS9pcy12aG9va1wiOiAyNiwgXCIuLi92bm9kZS9pcy12bm9kZVwiOiAyNywgXCIuLi92bm9kZS9pcy12dGV4dFwiOiAyOCwgXCIuLi92bm9kZS9pcy13aWRnZXRcIjogMjksIFwiLi4vdm5vZGUvdm5vZGUuanNcIjogMzEsIFwiLi4vdm5vZGUvdnRleHQuanNcIjogMzMsIFwiLi9ob29rcy9ldi1ob29rLmpzXCI6IDIwLCBcIi4vaG9va3Mvc29mdC1zZXQtaG9vay5qc1wiOiAyMSwgXCIuL3BhcnNlLXRhZy5qc1wiOiAyMywgXCJ4LWlzLWFycmF5XCI6IDEyIH1dLCAyMzogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHtcbiAgICAgICAgICAgIFwidXNlIHN0cmljdFwiO1xuXG4gICAgICAgICAgICB2YXIgc3BsaXQgPSByZXF1aXJlKFwiYnJvd3Nlci1zcGxpdFwiKTtcblxuICAgICAgICAgICAgdmFyIGNsYXNzSWRTcGxpdCA9IC8oW1xcLiNdP1thLXpBLVowLTlcXHUwMDdGLVxcdUZGRkZfOi1dKykvO1xuICAgICAgICAgICAgdmFyIG5vdENsYXNzSWQgPSAvXlxcLnwjLztcblxuICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBwYXJzZVRhZztcblxuICAgICAgICAgICAgZnVuY3Rpb24gcGFyc2VUYWcodGFnLCBwcm9wcykge1xuICAgICAgICAgICAgICAgIGlmICghdGFnKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBcIkRJVlwiO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHZhciBub0lkID0gIXByb3BzLmhhc093blByb3BlcnR5KFwiaWRcIik7XG5cbiAgICAgICAgICAgICAgICB2YXIgdGFnUGFydHMgPSBzcGxpdCh0YWcsIGNsYXNzSWRTcGxpdCk7XG4gICAgICAgICAgICAgICAgdmFyIHRhZ05hbWUgPSBudWxsO1xuXG4gICAgICAgICAgICAgICAgaWYgKG5vdENsYXNzSWQudGVzdCh0YWdQYXJ0c1sxXSkpIHtcbiAgICAgICAgICAgICAgICAgICAgdGFnTmFtZSA9IFwiRElWXCI7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgdmFyIGNsYXNzZXMsIHBhcnQsIHR5cGUsIGk7XG5cbiAgICAgICAgICAgICAgICBmb3IgKGkgPSAwOyBpIDwgdGFnUGFydHMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgICAgICAgICAgcGFydCA9IHRhZ1BhcnRzW2ldO1xuXG4gICAgICAgICAgICAgICAgICAgIGlmICghcGFydCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgY29udGludWU7XG4gICAgICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgICAgICB0eXBlID0gcGFydC5jaGFyQXQoMCk7XG5cbiAgICAgICAgICAgICAgICAgICAgaWYgKCF0YWdOYW1lKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICB0YWdOYW1lID0gcGFydDtcbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIGlmICh0eXBlID09PSBcIi5cIikge1xuICAgICAgICAgICAgICAgICAgICAgICAgY2xhc3NlcyA9IGNsYXNzZXMgfHwgW107XG4gICAgICAgICAgICAgICAgICAgICAgICBjbGFzc2VzLnB1c2gocGFydC5zdWJzdHJpbmcoMSwgcGFydC5sZW5ndGgpKTtcbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIGlmICh0eXBlID09PSBcIiNcIiAmJiBub0lkKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBwcm9wcy5pZCA9IHBhcnQuc3Vic3RyaW5nKDEsIHBhcnQubGVuZ3RoKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIGlmIChjbGFzc2VzKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmIChwcm9wcy5jbGFzc05hbWUpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGNsYXNzZXMucHVzaChwcm9wcy5jbGFzc05hbWUpO1xuICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgcHJvcHMuY2xhc3NOYW1lID0gY2xhc3Nlcy5qb2luKFwiIFwiKTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICByZXR1cm4gcHJvcHMubmFtZXNwYWNlID8gdGFnTmFtZSA6IHRhZ05hbWUudG9VcHBlckNhc2UoKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSwgeyBcImJyb3dzZXItc3BsaXRcIjogNSB9XSwgMjQ6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICB2YXIgaXNWTm9kZSA9IHJlcXVpcmUoXCIuL2lzLXZub2RlXCIpO1xuICAgICAgICAgICAgdmFyIGlzVlRleHQgPSByZXF1aXJlKFwiLi9pcy12dGV4dFwiKTtcbiAgICAgICAgICAgIHZhciBpc1dpZGdldCA9IHJlcXVpcmUoXCIuL2lzLXdpZGdldFwiKTtcbiAgICAgICAgICAgIHZhciBpc1RodW5rID0gcmVxdWlyZShcIi4vaXMtdGh1bmtcIik7XG5cbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gaGFuZGxlVGh1bms7XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIGhhbmRsZVRodW5rKGEsIGIpIHtcbiAgICAgICAgICAgICAgICB2YXIgcmVuZGVyZWRBID0gYTtcbiAgICAgICAgICAgICAgICB2YXIgcmVuZGVyZWRCID0gYjtcblxuICAgICAgICAgICAgICAgIGlmIChpc1RodW5rKGIpKSB7XG4gICAgICAgICAgICAgICAgICAgIHJlbmRlcmVkQiA9IHJlbmRlclRodW5rKGIsIGEpO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIGlmIChpc1RodW5rKGEpKSB7XG4gICAgICAgICAgICAgICAgICAgIHJlbmRlcmVkQSA9IHJlbmRlclRodW5rKGEsIG51bGwpO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHJldHVybiB7XG4gICAgICAgICAgICAgICAgICAgIGE6IHJlbmRlcmVkQSxcbiAgICAgICAgICAgICAgICAgICAgYjogcmVuZGVyZWRCXG4gICAgICAgICAgICAgICAgfTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZnVuY3Rpb24gcmVuZGVyVGh1bmsodGh1bmssIHByZXZpb3VzKSB7XG4gICAgICAgICAgICAgICAgdmFyIHJlbmRlcmVkVGh1bmsgPSB0aHVuay52bm9kZTtcblxuICAgICAgICAgICAgICAgIGlmICghcmVuZGVyZWRUaHVuaykge1xuICAgICAgICAgICAgICAgICAgICByZW5kZXJlZFRodW5rID0gdGh1bmsudm5vZGUgPSB0aHVuay5yZW5kZXIocHJldmlvdXMpO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIGlmICghKGlzVk5vZGUocmVuZGVyZWRUaHVuaykgfHwgaXNWVGV4dChyZW5kZXJlZFRodW5rKSB8fCBpc1dpZGdldChyZW5kZXJlZFRodW5rKSkpIHtcbiAgICAgICAgICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKFwidGh1bmsgZGlkIG5vdCByZXR1cm4gYSB2YWxpZCBub2RlXCIpO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHJldHVybiByZW5kZXJlZFRodW5rO1xuICAgICAgICAgICAgfVxuICAgICAgICB9LCB7IFwiLi9pcy10aHVua1wiOiAyNSwgXCIuL2lzLXZub2RlXCI6IDI3LCBcIi4vaXMtdnRleHRcIjogMjgsIFwiLi9pcy13aWRnZXRcIjogMjkgfV0sIDI1OiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge1xuICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBpc1RodW5rO1xuXG4gICAgICAgICAgICBmdW5jdGlvbiBpc1RodW5rKHQpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gdCAmJiB0LnR5cGUgPT09IFwiVGh1bmtcIjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSwge31dLCAyNjogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHtcbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gaXNIb29rO1xuXG4gICAgICAgICAgICBmdW5jdGlvbiBpc0hvb2soaG9vaykge1xuICAgICAgICAgICAgICAgIHJldHVybiBob29rICYmICh0eXBlb2YgaG9vay5ob29rID09PSBcImZ1bmN0aW9uXCIgJiYgIWhvb2suaGFzT3duUHJvcGVydHkoXCJob29rXCIpIHx8IHR5cGVvZiBob29rLnVuaG9vayA9PT0gXCJmdW5jdGlvblwiICYmICFob29rLmhhc093blByb3BlcnR5KFwidW5ob29rXCIpKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSwge31dLCAyNzogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHtcbiAgICAgICAgICAgIHZhciB2ZXJzaW9uID0gcmVxdWlyZShcIi4vdmVyc2lvblwiKTtcblxuICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBpc1ZpcnR1YWxOb2RlO1xuXG4gICAgICAgICAgICBmdW5jdGlvbiBpc1ZpcnR1YWxOb2RlKHgpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4geCAmJiB4LnR5cGUgPT09IFwiVmlydHVhbE5vZGVcIiAmJiB4LnZlcnNpb24gPT09IHZlcnNpb247XG4gICAgICAgICAgICB9XG4gICAgICAgIH0sIHsgXCIuL3ZlcnNpb25cIjogMzAgfV0sIDI4OiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge1xuICAgICAgICAgICAgdmFyIHZlcnNpb24gPSByZXF1aXJlKFwiLi92ZXJzaW9uXCIpO1xuXG4gICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IGlzVmlydHVhbFRleHQ7XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIGlzVmlydHVhbFRleHQoeCkge1xuICAgICAgICAgICAgICAgIHJldHVybiB4ICYmIHgudHlwZSA9PT0gXCJWaXJ0dWFsVGV4dFwiICYmIHgudmVyc2lvbiA9PT0gdmVyc2lvbjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSwgeyBcIi4vdmVyc2lvblwiOiAzMCB9XSwgMjk6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IGlzV2lkZ2V0O1xuXG4gICAgICAgICAgICBmdW5jdGlvbiBpc1dpZGdldCh3KSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHcgJiYgdy50eXBlID09PSBcIldpZGdldFwiO1xuICAgICAgICAgICAgfVxuICAgICAgICB9LCB7fV0sIDMwOiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge1xuICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBcIjJcIjtcbiAgICAgICAgfSwge31dLCAzMTogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHtcbiAgICAgICAgICAgIHZhciB2ZXJzaW9uID0gcmVxdWlyZShcIi4vdmVyc2lvblwiKTtcbiAgICAgICAgICAgIHZhciBpc1ZOb2RlID0gcmVxdWlyZShcIi4vaXMtdm5vZGVcIik7XG4gICAgICAgICAgICB2YXIgaXNXaWRnZXQgPSByZXF1aXJlKFwiLi9pcy13aWRnZXRcIik7XG4gICAgICAgICAgICB2YXIgaXNUaHVuayA9IHJlcXVpcmUoXCIuL2lzLXRodW5rXCIpO1xuICAgICAgICAgICAgdmFyIGlzVkhvb2sgPSByZXF1aXJlKFwiLi9pcy12aG9va1wiKTtcblxuICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBWaXJ0dWFsTm9kZTtcblxuICAgICAgICAgICAgdmFyIG5vUHJvcGVydGllcyA9IHt9O1xuICAgICAgICAgICAgdmFyIG5vQ2hpbGRyZW4gPSBbXTtcblxuICAgICAgICAgICAgZnVuY3Rpb24gVmlydHVhbE5vZGUodGFnTmFtZSwgcHJvcGVydGllcywgY2hpbGRyZW4sIGtleSwgbmFtZXNwYWNlKSB7XG4gICAgICAgICAgICAgICAgdGhpcy50YWdOYW1lID0gdGFnTmFtZTtcbiAgICAgICAgICAgICAgICB0aGlzLnByb3BlcnRpZXMgPSBwcm9wZXJ0aWVzIHx8IG5vUHJvcGVydGllcztcbiAgICAgICAgICAgICAgICB0aGlzLmNoaWxkcmVuID0gY2hpbGRyZW4gfHwgbm9DaGlsZHJlbjtcbiAgICAgICAgICAgICAgICB0aGlzLmtleSA9IGtleSAhPSBudWxsID8gU3RyaW5nKGtleSkgOiB1bmRlZmluZWQ7XG4gICAgICAgICAgICAgICAgdGhpcy5uYW1lc3BhY2UgPSB0eXBlb2YgbmFtZXNwYWNlID09PSBcInN0cmluZ1wiID8gbmFtZXNwYWNlIDogbnVsbDtcblxuICAgICAgICAgICAgICAgIHZhciBjb3VudCA9IGNoaWxkcmVuICYmIGNoaWxkcmVuLmxlbmd0aCB8fCAwO1xuICAgICAgICAgICAgICAgIHZhciBkZXNjZW5kYW50cyA9IDA7XG4gICAgICAgICAgICAgICAgdmFyIGhhc1dpZGdldHMgPSBmYWxzZTtcbiAgICAgICAgICAgICAgICB2YXIgaGFzVGh1bmtzID0gZmFsc2U7XG4gICAgICAgICAgICAgICAgdmFyIGRlc2NlbmRhbnRIb29rcyA9IGZhbHNlO1xuICAgICAgICAgICAgICAgIHZhciBob29rcztcblxuICAgICAgICAgICAgICAgIGZvciAodmFyIHByb3BOYW1lIGluIHByb3BlcnRpZXMpIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKHByb3BlcnRpZXMuaGFzT3duUHJvcGVydHkocHJvcE5hbWUpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICB2YXIgcHJvcGVydHkgPSBwcm9wZXJ0aWVzW3Byb3BOYW1lXTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChpc1ZIb29rKHByb3BlcnR5KSAmJiBwcm9wZXJ0eS51bmhvb2spIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoIWhvb2tzKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGhvb2tzID0ge307XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaG9va3NbcHJvcE5hbWVdID0gcHJvcGVydHk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IGNvdW50OyBpKyspIHtcbiAgICAgICAgICAgICAgICAgICAgdmFyIGNoaWxkID0gY2hpbGRyZW5baV07XG4gICAgICAgICAgICAgICAgICAgIGlmIChpc1ZOb2RlKGNoaWxkKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgZGVzY2VuZGFudHMgKz0gY2hpbGQuY291bnQgfHwgMDtcblxuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKCFoYXNXaWRnZXRzICYmIGNoaWxkLmhhc1dpZGdldHMpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBoYXNXaWRnZXRzID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKCFoYXNUaHVua3MgJiYgY2hpbGQuaGFzVGh1bmtzKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaGFzVGh1bmtzID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKCFkZXNjZW5kYW50SG9va3MgJiYgKGNoaWxkLmhvb2tzIHx8IGNoaWxkLmRlc2NlbmRhbnRIb29rcykpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBkZXNjZW5kYW50SG9va3MgPSB0cnVlO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKCFoYXNXaWRnZXRzICYmIGlzV2lkZ2V0KGNoaWxkKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHR5cGVvZiBjaGlsZC5kZXN0cm95ID09PSBcImZ1bmN0aW9uXCIpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBoYXNXaWRnZXRzID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIGlmICghaGFzVGh1bmtzICYmIGlzVGh1bmsoY2hpbGQpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBoYXNUaHVua3MgPSB0cnVlO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgdGhpcy5jb3VudCA9IGNvdW50ICsgZGVzY2VuZGFudHM7XG4gICAgICAgICAgICAgICAgdGhpcy5oYXNXaWRnZXRzID0gaGFzV2lkZ2V0cztcbiAgICAgICAgICAgICAgICB0aGlzLmhhc1RodW5rcyA9IGhhc1RodW5rcztcbiAgICAgICAgICAgICAgICB0aGlzLmhvb2tzID0gaG9va3M7XG4gICAgICAgICAgICAgICAgdGhpcy5kZXNjZW5kYW50SG9va3MgPSBkZXNjZW5kYW50SG9va3M7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIFZpcnR1YWxOb2RlLnByb3RvdHlwZS52ZXJzaW9uID0gdmVyc2lvbjtcbiAgICAgICAgICAgIFZpcnR1YWxOb2RlLnByb3RvdHlwZS50eXBlID0gXCJWaXJ0dWFsTm9kZVwiO1xuICAgICAgICB9LCB7IFwiLi9pcy10aHVua1wiOiAyNSwgXCIuL2lzLXZob29rXCI6IDI2LCBcIi4vaXMtdm5vZGVcIjogMjcsIFwiLi9pcy13aWRnZXRcIjogMjksIFwiLi92ZXJzaW9uXCI6IDMwIH1dLCAzMjogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHtcbiAgICAgICAgICAgIHZhciB2ZXJzaW9uID0gcmVxdWlyZShcIi4vdmVyc2lvblwiKTtcblxuICAgICAgICAgICAgVmlydHVhbFBhdGNoLk5PTkUgPSAwO1xuICAgICAgICAgICAgVmlydHVhbFBhdGNoLlZURVhUID0gMTtcbiAgICAgICAgICAgIFZpcnR1YWxQYXRjaC5WTk9ERSA9IDI7XG4gICAgICAgICAgICBWaXJ0dWFsUGF0Y2guV0lER0VUID0gMztcbiAgICAgICAgICAgIFZpcnR1YWxQYXRjaC5QUk9QUyA9IDQ7XG4gICAgICAgICAgICBWaXJ0dWFsUGF0Y2guT1JERVIgPSA1O1xuICAgICAgICAgICAgVmlydHVhbFBhdGNoLklOU0VSVCA9IDY7XG4gICAgICAgICAgICBWaXJ0dWFsUGF0Y2guUkVNT1ZFID0gNztcbiAgICAgICAgICAgIFZpcnR1YWxQYXRjaC5USFVOSyA9IDg7XG5cbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gVmlydHVhbFBhdGNoO1xuXG4gICAgICAgICAgICBmdW5jdGlvbiBWaXJ0dWFsUGF0Y2godHlwZSwgdk5vZGUsIHBhdGNoKSB7XG4gICAgICAgICAgICAgICAgdGhpcy50eXBlID0gTnVtYmVyKHR5cGUpO1xuICAgICAgICAgICAgICAgIHRoaXMudk5vZGUgPSB2Tm9kZTtcbiAgICAgICAgICAgICAgICB0aGlzLnBhdGNoID0gcGF0Y2g7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIFZpcnR1YWxQYXRjaC5wcm90b3R5cGUudmVyc2lvbiA9IHZlcnNpb247XG4gICAgICAgICAgICBWaXJ0dWFsUGF0Y2gucHJvdG90eXBlLnR5cGUgPSBcIlZpcnR1YWxQYXRjaFwiO1xuICAgICAgICB9LCB7IFwiLi92ZXJzaW9uXCI6IDMwIH1dLCAzMzogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHtcbiAgICAgICAgICAgIHZhciB2ZXJzaW9uID0gcmVxdWlyZShcIi4vdmVyc2lvblwiKTtcblxuICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBWaXJ0dWFsVGV4dDtcblxuICAgICAgICAgICAgZnVuY3Rpb24gVmlydHVhbFRleHQodGV4dCkge1xuICAgICAgICAgICAgICAgIHRoaXMudGV4dCA9IFN0cmluZyh0ZXh0KTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgVmlydHVhbFRleHQucHJvdG90eXBlLnZlcnNpb24gPSB2ZXJzaW9uO1xuICAgICAgICAgICAgVmlydHVhbFRleHQucHJvdG90eXBlLnR5cGUgPSBcIlZpcnR1YWxUZXh0XCI7XG4gICAgICAgIH0sIHsgXCIuL3ZlcnNpb25cIjogMzAgfV0sIDM0OiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge1xuICAgICAgICAgICAgdmFyIGlzT2JqZWN0ID0gcmVxdWlyZShcImlzLW9iamVjdFwiKTtcbiAgICAgICAgICAgIHZhciBpc0hvb2sgPSByZXF1aXJlKFwiLi4vdm5vZGUvaXMtdmhvb2tcIik7XG5cbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gZGlmZlByb3BzO1xuXG4gICAgICAgICAgICBmdW5jdGlvbiBkaWZmUHJvcHMoYSwgYikge1xuICAgICAgICAgICAgICAgIHZhciBkaWZmO1xuXG4gICAgICAgICAgICAgICAgZm9yICh2YXIgYUtleSBpbiBhKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmICghKGFLZXkgaW4gYikpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGRpZmYgPSBkaWZmIHx8IHt9O1xuICAgICAgICAgICAgICAgICAgICAgICAgZGlmZlthS2V5XSA9IHVuZGVmaW5lZDtcbiAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgIHZhciBhVmFsdWUgPSBhW2FLZXldO1xuICAgICAgICAgICAgICAgICAgICB2YXIgYlZhbHVlID0gYlthS2V5XTtcblxuICAgICAgICAgICAgICAgICAgICBpZiAoYVZhbHVlID09PSBiVmFsdWUpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnRpbnVlO1xuICAgICAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKGlzT2JqZWN0KGFWYWx1ZSkgJiYgaXNPYmplY3QoYlZhbHVlKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGdldFByb3RvdHlwZShiVmFsdWUpICE9PSBnZXRQcm90b3R5cGUoYVZhbHVlKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRpZmYgPSBkaWZmIHx8IHt9O1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRpZmZbYUtleV0gPSBiVmFsdWU7XG4gICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKGlzSG9vayhiVmFsdWUpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgZGlmZiA9IGRpZmYgfHwge307XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgZGlmZlthS2V5XSA9IGJWYWx1ZTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdmFyIG9iamVjdERpZmYgPSBkaWZmUHJvcHMoYVZhbHVlLCBiVmFsdWUpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChvYmplY3REaWZmKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRpZmYgPSBkaWZmIHx8IHt9O1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBkaWZmW2FLZXldID0gb2JqZWN0RGlmZjtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBkaWZmID0gZGlmZiB8fCB7fTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGRpZmZbYUtleV0gPSBiVmFsdWU7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICBmb3IgKHZhciBiS2V5IGluIGIpIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKCEoYktleSBpbiBhKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgZGlmZiA9IGRpZmYgfHwge307XG4gICAgICAgICAgICAgICAgICAgICAgICBkaWZmW2JLZXldID0gYltiS2V5XTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHJldHVybiBkaWZmO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBmdW5jdGlvbiBnZXRQcm90b3R5cGUodmFsdWUpIHtcbiAgICAgICAgICAgICAgICBpZiAoT2JqZWN0LmdldFByb3RvdHlwZU9mKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBPYmplY3QuZ2V0UHJvdG90eXBlT2YodmFsdWUpO1xuICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAodmFsdWUuX19wcm90b19fKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiB2YWx1ZS5fX3Byb3RvX187XG4gICAgICAgICAgICAgICAgfSBlbHNlIGlmICh2YWx1ZS5jb25zdHJ1Y3Rvcikge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gdmFsdWUuY29uc3RydWN0b3IucHJvdG90eXBlO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgfSwgeyBcIi4uL3Zub2RlL2lzLXZob29rXCI6IDI2LCBcImlzLW9iamVjdFwiOiAxMSB9XSwgMzU6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICB2YXIgaXNBcnJheSA9IHJlcXVpcmUoXCJ4LWlzLWFycmF5XCIpO1xuXG4gICAgICAgICAgICB2YXIgVlBhdGNoID0gcmVxdWlyZShcIi4uL3Zub2RlL3ZwYXRjaFwiKTtcbiAgICAgICAgICAgIHZhciBpc1ZOb2RlID0gcmVxdWlyZShcIi4uL3Zub2RlL2lzLXZub2RlXCIpO1xuICAgICAgICAgICAgdmFyIGlzVlRleHQgPSByZXF1aXJlKFwiLi4vdm5vZGUvaXMtdnRleHRcIik7XG4gICAgICAgICAgICB2YXIgaXNXaWRnZXQgPSByZXF1aXJlKFwiLi4vdm5vZGUvaXMtd2lkZ2V0XCIpO1xuICAgICAgICAgICAgdmFyIGlzVGh1bmsgPSByZXF1aXJlKFwiLi4vdm5vZGUvaXMtdGh1bmtcIik7XG4gICAgICAgICAgICB2YXIgaGFuZGxlVGh1bmsgPSByZXF1aXJlKFwiLi4vdm5vZGUvaGFuZGxlLXRodW5rXCIpO1xuXG4gICAgICAgICAgICB2YXIgZGlmZlByb3BzID0gcmVxdWlyZShcIi4vZGlmZi1wcm9wc1wiKTtcblxuICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBkaWZmO1xuXG4gICAgICAgICAgICBmdW5jdGlvbiBkaWZmKGEsIGIpIHtcbiAgICAgICAgICAgICAgICB2YXIgcGF0Y2ggPSB7IGE6IGEgfTtcbiAgICAgICAgICAgICAgICB3YWxrKGEsIGIsIHBhdGNoLCAwKTtcbiAgICAgICAgICAgICAgICByZXR1cm4gcGF0Y2g7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIHdhbGsoYSwgYiwgcGF0Y2gsIGluZGV4KSB7XG4gICAgICAgICAgICAgICAgaWYgKGEgPT09IGIpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHZhciBhcHBseSA9IHBhdGNoW2luZGV4XTtcbiAgICAgICAgICAgICAgICB2YXIgYXBwbHlDbGVhciA9IGZhbHNlO1xuXG4gICAgICAgICAgICAgICAgaWYgKGlzVGh1bmsoYSkgfHwgaXNUaHVuayhiKSkge1xuICAgICAgICAgICAgICAgICAgICB0aHVua3MoYSwgYiwgcGF0Y2gsIGluZGV4KTtcbiAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKGIgPT0gbnVsbCkge1xuXG4gICAgICAgICAgICAgICAgICAgIC8vIElmIGEgaXMgYSB3aWRnZXQgd2Ugd2lsbCBhZGQgYSByZW1vdmUgcGF0Y2ggZm9yIGl0XG4gICAgICAgICAgICAgICAgICAgIC8vIE90aGVyd2lzZSBhbnkgY2hpbGQgd2lkZ2V0cy9ob29rcyBtdXN0IGJlIGRlc3Ryb3llZC5cbiAgICAgICAgICAgICAgICAgICAgLy8gVGhpcyBwcmV2ZW50cyBhZGRpbmcgdHdvIHJlbW92ZSBwYXRjaGVzIGZvciBhIHdpZGdldC5cbiAgICAgICAgICAgICAgICAgICAgaWYgKCFpc1dpZGdldChhKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgY2xlYXJTdGF0ZShhLCBwYXRjaCwgaW5kZXgpO1xuICAgICAgICAgICAgICAgICAgICAgICAgYXBwbHkgPSBwYXRjaFtpbmRleF07XG4gICAgICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgICAgICBhcHBseSA9IGFwcGVuZFBhdGNoKGFwcGx5LCBuZXcgVlBhdGNoKFZQYXRjaC5SRU1PVkUsIGEsIGIpKTtcbiAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKGlzVk5vZGUoYikpIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKGlzVk5vZGUoYSkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChhLnRhZ05hbWUgPT09IGIudGFnTmFtZSAmJiBhLm5hbWVzcGFjZSA9PT0gYi5uYW1lc3BhY2UgJiYgYS5rZXkgPT09IGIua2V5KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdmFyIHByb3BzUGF0Y2ggPSBkaWZmUHJvcHMoYS5wcm9wZXJ0aWVzLCBiLnByb3BlcnRpZXMpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChwcm9wc1BhdGNoKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGFwcGx5ID0gYXBwZW5kUGF0Y2goYXBwbHksIG5ldyBWUGF0Y2goVlBhdGNoLlBST1BTLCBhLCBwcm9wc1BhdGNoKSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGFwcGx5ID0gZGlmZkNoaWxkcmVuKGEsIGIsIHBhdGNoLCBhcHBseSwgaW5kZXgpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBhcHBseSA9IGFwcGVuZFBhdGNoKGFwcGx5LCBuZXcgVlBhdGNoKFZQYXRjaC5WTk9ERSwgYSwgYikpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGFwcGx5Q2xlYXIgPSB0cnVlO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgYXBwbHkgPSBhcHBlbmRQYXRjaChhcHBseSwgbmV3IFZQYXRjaChWUGF0Y2guVk5PREUsIGEsIGIpKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGFwcGx5Q2xlYXIgPSB0cnVlO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfSBlbHNlIGlmIChpc1ZUZXh0KGIpKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmICghaXNWVGV4dChhKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgYXBwbHkgPSBhcHBlbmRQYXRjaChhcHBseSwgbmV3IFZQYXRjaChWUGF0Y2guVlRFWFQsIGEsIGIpKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGFwcGx5Q2xlYXIgPSB0cnVlO1xuICAgICAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKGEudGV4dCAhPT0gYi50ZXh0KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBhcHBseSA9IGFwcGVuZFBhdGNoKGFwcGx5LCBuZXcgVlBhdGNoKFZQYXRjaC5WVEVYVCwgYSwgYikpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfSBlbHNlIGlmIChpc1dpZGdldChiKSkge1xuICAgICAgICAgICAgICAgICAgICBpZiAoIWlzV2lkZ2V0KGEpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBhcHBseUNsZWFyID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgIGFwcGx5ID0gYXBwZW5kUGF0Y2goYXBwbHksIG5ldyBWUGF0Y2goVlBhdGNoLldJREdFVCwgYSwgYikpO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIGlmIChhcHBseSkge1xuICAgICAgICAgICAgICAgICAgICBwYXRjaFtpbmRleF0gPSBhcHBseTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICBpZiAoYXBwbHlDbGVhcikge1xuICAgICAgICAgICAgICAgICAgICBjbGVhclN0YXRlKGEsIHBhdGNoLCBpbmRleCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBmdW5jdGlvbiBkaWZmQ2hpbGRyZW4oYSwgYiwgcGF0Y2gsIGFwcGx5LCBpbmRleCkge1xuICAgICAgICAgICAgICAgIHZhciBhQ2hpbGRyZW4gPSBhLmNoaWxkcmVuO1xuICAgICAgICAgICAgICAgIHZhciBvcmRlcmVkU2V0ID0gcmVvcmRlcihhQ2hpbGRyZW4sIGIuY2hpbGRyZW4pO1xuICAgICAgICAgICAgICAgIHZhciBiQ2hpbGRyZW4gPSBvcmRlcmVkU2V0LmNoaWxkcmVuO1xuXG4gICAgICAgICAgICAgICAgdmFyIGFMZW4gPSBhQ2hpbGRyZW4ubGVuZ3RoO1xuICAgICAgICAgICAgICAgIHZhciBiTGVuID0gYkNoaWxkcmVuLmxlbmd0aDtcbiAgICAgICAgICAgICAgICB2YXIgbGVuID0gYUxlbiA+IGJMZW4gPyBhTGVuIDogYkxlbjtcblxuICAgICAgICAgICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgbGVuOyBpKyspIHtcbiAgICAgICAgICAgICAgICAgICAgdmFyIGxlZnROb2RlID0gYUNoaWxkcmVuW2ldO1xuICAgICAgICAgICAgICAgICAgICB2YXIgcmlnaHROb2RlID0gYkNoaWxkcmVuW2ldO1xuICAgICAgICAgICAgICAgICAgICBpbmRleCArPSAxO1xuXG4gICAgICAgICAgICAgICAgICAgIGlmICghbGVmdE5vZGUpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChyaWdodE5vZGUpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBFeGNlc3Mgbm9kZXMgaW4gYiBuZWVkIHRvIGJlIGFkZGVkXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgYXBwbHkgPSBhcHBlbmRQYXRjaChhcHBseSwgbmV3IFZQYXRjaChWUGF0Y2guSU5TRVJULCBudWxsLCByaWdodE5vZGUpKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHdhbGsobGVmdE5vZGUsIHJpZ2h0Tm9kZSwgcGF0Y2gsIGluZGV4KTtcbiAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgIGlmIChpc1ZOb2RlKGxlZnROb2RlKSAmJiBsZWZ0Tm9kZS5jb3VudCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgaW5kZXggKz0gbGVmdE5vZGUuY291bnQ7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICBpZiAob3JkZXJlZFNldC5tb3Zlcykge1xuICAgICAgICAgICAgICAgICAgICAvLyBSZW9yZGVyIG5vZGVzIGxhc3RcbiAgICAgICAgICAgICAgICAgICAgYXBwbHkgPSBhcHBlbmRQYXRjaChhcHBseSwgbmV3IFZQYXRjaChWUGF0Y2guT1JERVIsIGEsIG9yZGVyZWRTZXQubW92ZXMpKTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICByZXR1cm4gYXBwbHk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIGNsZWFyU3RhdGUodk5vZGUsIHBhdGNoLCBpbmRleCkge1xuICAgICAgICAgICAgICAgIC8vIFRPRE86IE1ha2UgdGhpcyBhIHNpbmdsZSB3YWxrLCBub3QgdHdvXG4gICAgICAgICAgICAgICAgdW5ob29rKHZOb2RlLCBwYXRjaCwgaW5kZXgpO1xuICAgICAgICAgICAgICAgIGRlc3Ryb3lXaWRnZXRzKHZOb2RlLCBwYXRjaCwgaW5kZXgpO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAvLyBQYXRjaCByZWNvcmRzIGZvciBhbGwgZGVzdHJveWVkIHdpZGdldHMgbXVzdCBiZSBhZGRlZCBiZWNhdXNlIHdlIG5lZWRcbiAgICAgICAgICAgIC8vIGEgRE9NIG5vZGUgcmVmZXJlbmNlIGZvciB0aGUgZGVzdHJveSBmdW5jdGlvblxuICAgICAgICAgICAgZnVuY3Rpb24gZGVzdHJveVdpZGdldHModk5vZGUsIHBhdGNoLCBpbmRleCkge1xuICAgICAgICAgICAgICAgIGlmIChpc1dpZGdldCh2Tm9kZSkpIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKHR5cGVvZiB2Tm9kZS5kZXN0cm95ID09PSBcImZ1bmN0aW9uXCIpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHBhdGNoW2luZGV4XSA9IGFwcGVuZFBhdGNoKHBhdGNoW2luZGV4XSwgbmV3IFZQYXRjaChWUGF0Y2guUkVNT1ZFLCB2Tm9kZSwgbnVsbCkpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfSBlbHNlIGlmIChpc1ZOb2RlKHZOb2RlKSAmJiAodk5vZGUuaGFzV2lkZ2V0cyB8fCB2Tm9kZS5oYXNUaHVua3MpKSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciBjaGlsZHJlbiA9IHZOb2RlLmNoaWxkcmVuO1xuICAgICAgICAgICAgICAgICAgICB2YXIgbGVuID0gY2hpbGRyZW4ubGVuZ3RoO1xuICAgICAgICAgICAgICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IGxlbjsgaSsrKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICB2YXIgY2hpbGQgPSBjaGlsZHJlbltpXTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGluZGV4ICs9IDE7XG5cbiAgICAgICAgICAgICAgICAgICAgICAgIGRlc3Ryb3lXaWRnZXRzKGNoaWxkLCBwYXRjaCwgaW5kZXgpO1xuXG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoaXNWTm9kZShjaGlsZCkgJiYgY2hpbGQuY291bnQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpbmRleCArPSBjaGlsZC5jb3VudDtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoaXNUaHVuayh2Tm9kZSkpIHtcbiAgICAgICAgICAgICAgICAgICAgdGh1bmtzKHZOb2RlLCBudWxsLCBwYXRjaCwgaW5kZXgpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgLy8gQ3JlYXRlIGEgc3ViLXBhdGNoIGZvciB0aHVua3NcbiAgICAgICAgICAgIGZ1bmN0aW9uIHRodW5rcyhhLCBiLCBwYXRjaCwgaW5kZXgpIHtcbiAgICAgICAgICAgICAgICB2YXIgbm9kZXMgPSBoYW5kbGVUaHVuayhhLCBiKTtcbiAgICAgICAgICAgICAgICB2YXIgdGh1bmtQYXRjaCA9IGRpZmYobm9kZXMuYSwgbm9kZXMuYik7XG4gICAgICAgICAgICAgICAgaWYgKGhhc1BhdGNoZXModGh1bmtQYXRjaCkpIHtcbiAgICAgICAgICAgICAgICAgICAgcGF0Y2hbaW5kZXhdID0gbmV3IFZQYXRjaChWUGF0Y2guVEhVTkssIG51bGwsIHRodW5rUGF0Y2gpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZnVuY3Rpb24gaGFzUGF0Y2hlcyhwYXRjaCkge1xuICAgICAgICAgICAgICAgIGZvciAodmFyIGluZGV4IGluIHBhdGNoKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmIChpbmRleCAhPT0gXCJhXCIpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAvLyBFeGVjdXRlIGhvb2tzIHdoZW4gdHdvIG5vZGVzIGFyZSBpZGVudGljYWxcbiAgICAgICAgICAgIGZ1bmN0aW9uIHVuaG9vayh2Tm9kZSwgcGF0Y2gsIGluZGV4KSB7XG4gICAgICAgICAgICAgICAgaWYgKGlzVk5vZGUodk5vZGUpKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmICh2Tm9kZS5ob29rcykge1xuICAgICAgICAgICAgICAgICAgICAgICAgcGF0Y2hbaW5kZXhdID0gYXBwZW5kUGF0Y2gocGF0Y2hbaW5kZXhdLCBuZXcgVlBhdGNoKFZQYXRjaC5QUk9QUywgdk5vZGUsIHVuZGVmaW5lZEtleXModk5vZGUuaG9va3MpKSk7XG4gICAgICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgICAgICBpZiAodk5vZGUuZGVzY2VuZGFudEhvb2tzIHx8IHZOb2RlLmhhc1RodW5rcykge1xuICAgICAgICAgICAgICAgICAgICAgICAgdmFyIGNoaWxkcmVuID0gdk5vZGUuY2hpbGRyZW47XG4gICAgICAgICAgICAgICAgICAgICAgICB2YXIgbGVuID0gY2hpbGRyZW4ubGVuZ3RoO1xuICAgICAgICAgICAgICAgICAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCBsZW47IGkrKykge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZhciBjaGlsZCA9IGNoaWxkcmVuW2ldO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGluZGV4ICs9IDE7XG5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB1bmhvb2soY2hpbGQsIHBhdGNoLCBpbmRleCk7XG5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoaXNWTm9kZShjaGlsZCkgJiYgY2hpbGQuY291bnQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaW5kZXggKz0gY2hpbGQuY291bnQ7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfSBlbHNlIGlmIChpc1RodW5rKHZOb2RlKSkge1xuICAgICAgICAgICAgICAgICAgICB0aHVua3Modk5vZGUsIG51bGwsIHBhdGNoLCBpbmRleCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBmdW5jdGlvbiB1bmRlZmluZWRLZXlzKG9iaikge1xuICAgICAgICAgICAgICAgIHZhciByZXN1bHQgPSB7fTtcblxuICAgICAgICAgICAgICAgIGZvciAodmFyIGtleSBpbiBvYmopIHtcbiAgICAgICAgICAgICAgICAgICAgcmVzdWx0W2tleV0gPSB1bmRlZmluZWQ7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgcmV0dXJuIHJlc3VsdDtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgLy8gTGlzdCBkaWZmLCBuYWl2ZSBsZWZ0IHRvIHJpZ2h0IHJlb3JkZXJpbmdcbiAgICAgICAgICAgIGZ1bmN0aW9uIHJlb3JkZXIoYUNoaWxkcmVuLCBiQ2hpbGRyZW4pIHtcbiAgICAgICAgICAgICAgICAvLyBPKE0pIHRpbWUsIE8oTSkgbWVtb3J5XG4gICAgICAgICAgICAgICAgdmFyIGJDaGlsZEluZGV4ID0ga2V5SW5kZXgoYkNoaWxkcmVuKTtcbiAgICAgICAgICAgICAgICB2YXIgYktleXMgPSBiQ2hpbGRJbmRleC5rZXlzO1xuICAgICAgICAgICAgICAgIHZhciBiRnJlZSA9IGJDaGlsZEluZGV4LmZyZWU7XG5cbiAgICAgICAgICAgICAgICBpZiAoYkZyZWUubGVuZ3RoID09PSBiQ2hpbGRyZW4ubGVuZ3RoKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiB7XG4gICAgICAgICAgICAgICAgICAgICAgICBjaGlsZHJlbjogYkNoaWxkcmVuLFxuICAgICAgICAgICAgICAgICAgICAgICAgbW92ZXM6IG51bGxcbiAgICAgICAgICAgICAgICAgICAgfTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAvLyBPKE4pIHRpbWUsIE8oTikgbWVtb3J5XG4gICAgICAgICAgICAgICAgdmFyIGFDaGlsZEluZGV4ID0ga2V5SW5kZXgoYUNoaWxkcmVuKTtcbiAgICAgICAgICAgICAgICB2YXIgYUtleXMgPSBhQ2hpbGRJbmRleC5rZXlzO1xuICAgICAgICAgICAgICAgIHZhciBhRnJlZSA9IGFDaGlsZEluZGV4LmZyZWU7XG5cbiAgICAgICAgICAgICAgICBpZiAoYUZyZWUubGVuZ3RoID09PSBhQ2hpbGRyZW4ubGVuZ3RoKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiB7XG4gICAgICAgICAgICAgICAgICAgICAgICBjaGlsZHJlbjogYkNoaWxkcmVuLFxuICAgICAgICAgICAgICAgICAgICAgICAgbW92ZXM6IG51bGxcbiAgICAgICAgICAgICAgICAgICAgfTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAvLyBPKE1BWChOLCBNKSkgbWVtb3J5XG4gICAgICAgICAgICAgICAgdmFyIG5ld0NoaWxkcmVuID0gW107XG5cbiAgICAgICAgICAgICAgICB2YXIgZnJlZUluZGV4ID0gMDtcbiAgICAgICAgICAgICAgICB2YXIgZnJlZUNvdW50ID0gYkZyZWUubGVuZ3RoO1xuICAgICAgICAgICAgICAgIHZhciBkZWxldGVkSXRlbXMgPSAwO1xuXG4gICAgICAgICAgICAgICAgLy8gSXRlcmF0ZSB0aHJvdWdoIGEgYW5kIG1hdGNoIGEgbm9kZSBpbiBiXG4gICAgICAgICAgICAgICAgLy8gTyhOKSB0aW1lLFxuICAgICAgICAgICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgYUNoaWxkcmVuLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciBhSXRlbSA9IGFDaGlsZHJlbltpXTtcbiAgICAgICAgICAgICAgICAgICAgdmFyIGl0ZW1JbmRleDtcblxuICAgICAgICAgICAgICAgICAgICBpZiAoYUl0ZW0ua2V5KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoYktleXMuaGFzT3duUHJvcGVydHkoYUl0ZW0ua2V5KSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIE1hdGNoIHVwIHRoZSBvbGQga2V5c1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGl0ZW1JbmRleCA9IGJLZXlzW2FJdGVtLmtleV07XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgbmV3Q2hpbGRyZW4ucHVzaChiQ2hpbGRyZW5baXRlbUluZGV4XSk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIFJlbW92ZSBvbGQga2V5ZWQgaXRlbXNcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpdGVtSW5kZXggPSBpIC0gZGVsZXRlZEl0ZW1zKys7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgbmV3Q2hpbGRyZW4ucHVzaChudWxsKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIE1hdGNoIHRoZSBpdGVtIGluIGEgd2l0aCB0aGUgbmV4dCBmcmVlIGl0ZW0gaW4gYlxuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGZyZWVJbmRleCA8IGZyZWVDb3VudCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGl0ZW1JbmRleCA9IGJGcmVlW2ZyZWVJbmRleCsrXTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBuZXdDaGlsZHJlbi5wdXNoKGJDaGlsZHJlbltpdGVtSW5kZXhdKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gVGhlcmUgYXJlIG5vIGZyZWUgaXRlbXMgaW4gYiB0byBtYXRjaCB3aXRoXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gdGhlIGZyZWUgaXRlbXMgaW4gYSwgc28gdGhlIGV4dHJhIGZyZWUgbm9kZXNcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBhcmUgZGVsZXRlZC5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpdGVtSW5kZXggPSBpIC0gZGVsZXRlZEl0ZW1zKys7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgbmV3Q2hpbGRyZW4ucHVzaChudWxsKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHZhciBsYXN0RnJlZUluZGV4ID0gZnJlZUluZGV4ID49IGJGcmVlLmxlbmd0aCA/IGJDaGlsZHJlbi5sZW5ndGggOiBiRnJlZVtmcmVlSW5kZXhdO1xuXG4gICAgICAgICAgICAgICAgLy8gSXRlcmF0ZSB0aHJvdWdoIGIgYW5kIGFwcGVuZCBhbnkgbmV3IGtleXNcbiAgICAgICAgICAgICAgICAvLyBPKE0pIHRpbWVcbiAgICAgICAgICAgICAgICBmb3IgKHZhciBqID0gMDsgaiA8IGJDaGlsZHJlbi5sZW5ndGg7IGorKykge1xuICAgICAgICAgICAgICAgICAgICB2YXIgbmV3SXRlbSA9IGJDaGlsZHJlbltqXTtcblxuICAgICAgICAgICAgICAgICAgICBpZiAobmV3SXRlbS5rZXkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmICghYUtleXMuaGFzT3duUHJvcGVydHkobmV3SXRlbS5rZXkpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gQWRkIGFueSBuZXcga2V5ZWQgaXRlbXNcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBXZSBhcmUgYWRkaW5nIG5ldyBpdGVtcyB0byB0aGUgZW5kIGFuZCB0aGVuIHNvcnRpbmcgdGhlbVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIGluIHBsYWNlLiBJbiBmdXR1cmUgd2Ugc2hvdWxkIGluc2VydCBuZXcgaXRlbXMgaW4gcGxhY2UuXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgbmV3Q2hpbGRyZW4ucHVzaChuZXdJdGVtKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIGlmIChqID49IGxhc3RGcmVlSW5kZXgpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIEFkZCBhbnkgbGVmdG92ZXIgbm9uLWtleWVkIGl0ZW1zXG4gICAgICAgICAgICAgICAgICAgICAgICBuZXdDaGlsZHJlbi5wdXNoKG5ld0l0ZW0pO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgdmFyIHNpbXVsYXRlID0gbmV3Q2hpbGRyZW4uc2xpY2UoKTtcbiAgICAgICAgICAgICAgICB2YXIgc2ltdWxhdGVJbmRleCA9IDA7XG4gICAgICAgICAgICAgICAgdmFyIHJlbW92ZXMgPSBbXTtcbiAgICAgICAgICAgICAgICB2YXIgaW5zZXJ0cyA9IFtdO1xuICAgICAgICAgICAgICAgIHZhciBzaW11bGF0ZUl0ZW07XG5cbiAgICAgICAgICAgICAgICBmb3IgKHZhciBrID0gMDsgayA8IGJDaGlsZHJlbi5sZW5ndGg7KSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciB3YW50ZWRJdGVtID0gYkNoaWxkcmVuW2tdO1xuICAgICAgICAgICAgICAgICAgICBzaW11bGF0ZUl0ZW0gPSBzaW11bGF0ZVtzaW11bGF0ZUluZGV4XTtcblxuICAgICAgICAgICAgICAgICAgICAvLyByZW1vdmUgaXRlbXNcbiAgICAgICAgICAgICAgICAgICAgd2hpbGUgKHNpbXVsYXRlSXRlbSA9PT0gbnVsbCAmJiBzaW11bGF0ZS5sZW5ndGgpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJlbW92ZXMucHVzaChyZW1vdmUoc2ltdWxhdGUsIHNpbXVsYXRlSW5kZXgsIG51bGwpKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIHNpbXVsYXRlSXRlbSA9IHNpbXVsYXRlW3NpbXVsYXRlSW5kZXhdO1xuICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgaWYgKCFzaW11bGF0ZUl0ZW0gfHwgc2ltdWxhdGVJdGVtLmtleSAhPT0gd2FudGVkSXRlbS5rZXkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIGlmIHdlIG5lZWQgYSBrZXkgaW4gdGhpcyBwb3NpdGlvbi4uLlxuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHdhbnRlZEl0ZW0ua2V5KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHNpbXVsYXRlSXRlbSAmJiBzaW11bGF0ZUl0ZW0ua2V5KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIGlmIGFuIGluc2VydCBkb2Vzbid0IHB1dCB0aGlzIGtleSBpbiBwbGFjZSwgaXQgbmVlZHMgdG8gbW92ZVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoYktleXNbc2ltdWxhdGVJdGVtLmtleV0gIT09IGsgKyAxKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICByZW1vdmVzLnB1c2gocmVtb3ZlKHNpbXVsYXRlLCBzaW11bGF0ZUluZGV4LCBzaW11bGF0ZUl0ZW0ua2V5KSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzaW11bGF0ZUl0ZW0gPSBzaW11bGF0ZVtzaW11bGF0ZUluZGV4XTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIGlmIHRoZSByZW1vdmUgZGlkbid0IHB1dCB0aGUgd2FudGVkIGl0ZW0gaW4gcGxhY2UsIHdlIG5lZWQgdG8gaW5zZXJ0IGl0XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoIXNpbXVsYXRlSXRlbSB8fCBzaW11bGF0ZUl0ZW0ua2V5ICE9PSB3YW50ZWRJdGVtLmtleSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGluc2VydHMucHVzaCh7IGtleTogd2FudGVkSXRlbS5rZXksIHRvOiBrIH0pO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gaXRlbXMgYXJlIG1hdGNoaW5nLCBzbyBza2lwIGFoZWFkXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzaW11bGF0ZUluZGV4Kys7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpbnNlcnRzLnB1c2goeyBrZXk6IHdhbnRlZEl0ZW0ua2V5LCB0bzogayB9KTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGluc2VydHMucHVzaCh7IGtleTogd2FudGVkSXRlbS5rZXksIHRvOiBrIH0pO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBrKys7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAvLyBhIGtleSBpbiBzaW11bGF0ZSBoYXMgbm8gbWF0Y2hpbmcgd2FudGVkIGtleSwgcmVtb3ZlIGl0XG4gICAgICAgICAgICAgICAgICAgICAgICBlbHNlIGlmIChzaW11bGF0ZUl0ZW0gJiYgc2ltdWxhdGVJdGVtLmtleSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlbW92ZXMucHVzaChyZW1vdmUoc2ltdWxhdGUsIHNpbXVsYXRlSW5kZXgsIHNpbXVsYXRlSXRlbS5rZXkpKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHNpbXVsYXRlSW5kZXgrKztcbiAgICAgICAgICAgICAgICAgICAgICAgIGsrKztcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIC8vIHJlbW92ZSBhbGwgdGhlIHJlbWFpbmluZyBub2RlcyBmcm9tIHNpbXVsYXRlXG4gICAgICAgICAgICAgICAgd2hpbGUgKHNpbXVsYXRlSW5kZXggPCBzaW11bGF0ZS5sZW5ndGgpIHtcbiAgICAgICAgICAgICAgICAgICAgc2ltdWxhdGVJdGVtID0gc2ltdWxhdGVbc2ltdWxhdGVJbmRleF07XG4gICAgICAgICAgICAgICAgICAgIHJlbW92ZXMucHVzaChyZW1vdmUoc2ltdWxhdGUsIHNpbXVsYXRlSW5kZXgsIHNpbXVsYXRlSXRlbSAmJiBzaW11bGF0ZUl0ZW0ua2V5KSk7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgLy8gSWYgdGhlIG9ubHkgbW92ZXMgd2UgaGF2ZSBhcmUgZGVsZXRlcyB0aGVuIHdlIGNhbiBqdXN0XG4gICAgICAgICAgICAgICAgLy8gbGV0IHRoZSBkZWxldGUgcGF0Y2ggcmVtb3ZlIHRoZXNlIGl0ZW1zLlxuICAgICAgICAgICAgICAgIGlmIChyZW1vdmVzLmxlbmd0aCA9PT0gZGVsZXRlZEl0ZW1zICYmICFpbnNlcnRzLmxlbmd0aCkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgICAgICAgICAgICAgY2hpbGRyZW46IG5ld0NoaWxkcmVuLFxuICAgICAgICAgICAgICAgICAgICAgICAgbW92ZXM6IG51bGxcbiAgICAgICAgICAgICAgICAgICAgfTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgICAgICAgICBjaGlsZHJlbjogbmV3Q2hpbGRyZW4sXG4gICAgICAgICAgICAgICAgICAgIG1vdmVzOiB7XG4gICAgICAgICAgICAgICAgICAgICAgICByZW1vdmVzOiByZW1vdmVzLFxuICAgICAgICAgICAgICAgICAgICAgICAgaW5zZXJ0czogaW5zZXJ0c1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZnVuY3Rpb24gcmVtb3ZlKGFyciwgaW5kZXgsIGtleSkge1xuICAgICAgICAgICAgICAgIGFyci5zcGxpY2UoaW5kZXgsIDEpO1xuXG4gICAgICAgICAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgICAgICAgICAgZnJvbTogaW5kZXgsXG4gICAgICAgICAgICAgICAgICAgIGtleToga2V5XG4gICAgICAgICAgICAgICAgfTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZnVuY3Rpb24ga2V5SW5kZXgoY2hpbGRyZW4pIHtcbiAgICAgICAgICAgICAgICB2YXIga2V5cyA9IHt9O1xuICAgICAgICAgICAgICAgIHZhciBmcmVlID0gW107XG4gICAgICAgICAgICAgICAgdmFyIGxlbmd0aCA9IGNoaWxkcmVuLmxlbmd0aDtcblxuICAgICAgICAgICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgbGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgICAgICAgICAgdmFyIGNoaWxkID0gY2hpbGRyZW5baV07XG5cbiAgICAgICAgICAgICAgICAgICAgaWYgKGNoaWxkLmtleSkge1xuICAgICAgICAgICAgICAgICAgICAgICAga2V5c1tjaGlsZC5rZXldID0gaTtcbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGZyZWUucHVzaChpKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHJldHVybiB7XG4gICAgICAgICAgICAgICAgICAgIGtleXM6IGtleXMsIC8vIEEgaGFzaCBvZiBrZXkgbmFtZSB0byBpbmRleFxuICAgICAgICAgICAgICAgICAgICBmcmVlOiBmcmVlIC8vIEFuIGFycmF5IG9mIHVua2V5ZWQgaXRlbSBpbmRpY2VzXG4gICAgICAgICAgICAgICAgfTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZnVuY3Rpb24gYXBwZW5kUGF0Y2goYXBwbHksIHBhdGNoKSB7XG4gICAgICAgICAgICAgICAgaWYgKGFwcGx5KSB7XG4gICAgICAgICAgICAgICAgICAgIGlmIChpc0FycmF5KGFwcGx5KSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgYXBwbHkucHVzaChwYXRjaCk7XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBhcHBseSA9IFthcHBseSwgcGF0Y2hdO1xuICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGFwcGx5O1xuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBwYXRjaDtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH0sIHsgXCIuLi92bm9kZS9oYW5kbGUtdGh1bmtcIjogMjQsIFwiLi4vdm5vZGUvaXMtdGh1bmtcIjogMjUsIFwiLi4vdm5vZGUvaXMtdm5vZGVcIjogMjcsIFwiLi4vdm5vZGUvaXMtdnRleHRcIjogMjgsIFwiLi4vdm5vZGUvaXMtd2lkZ2V0XCI6IDI5LCBcIi4uL3Zub2RlL3ZwYXRjaFwiOiAzMiwgXCIuL2RpZmYtcHJvcHNcIjogMzQsIFwieC1pcy1hcnJheVwiOiAxMiB9XSB9LCB7fSwgWzRdKSg0KTtcbn0pO1xuXG5cbi8vIFByb3Bvc2VkIGZvciBFUzZcblxuY29uc3Qgc3RhcnQgPSBmdW5jdGlvbiAoZG9tUm9vdCwgcmVuZGVyRm4sIGluaXRpYWxTdGF0ZSwgb3B0aW9ucyA9IFtdKSB7XG4gIGNvbnN0IG5hbWUgPSBLZXl3b3JkLmhhc19rZXlfX3FtX18ob3B0aW9ucywgS2VybmVsLlNwZWNpYWxGb3Jtcy5hdG9tKCduYW1lJykpID8gS2V5d29yZC5nZXQob3B0aW9ucywgS2VybmVsLlNwZWNpYWxGb3Jtcy5hdG9tKCduYW1lJykpIDogU3ltYm9sKCk7XG5cbiAgc2VsZi5wb3N0X29mZmljZS5hZGRfbWFpbGJveChuYW1lKTtcblxuICBjb25zdCB0cmVlID0gcmVuZGVyRm4uYXBwbHkodGhpcywgaW5pdGlhbFN0YXRlKTtcbiAgY29uc3Qgcm9vdE5vZGUgPSB2aXJ0dWFsRG9tLmNyZWF0ZSh0cmVlKTtcblxuICBkb21Sb290LmFwcGVuZENoaWxkKHJvb3ROb2RlKTtcbiAgc2VsZi5wb3N0X29mZmljZS5zZW5kKG5hbWUsIEtlcm5lbC5TcGVjaWFsRm9ybXMudHVwbGUocm9vdE5vZGUsIHRyZWUsIHJlbmRlckZuKSk7XG5cbiAgcmV0dXJuIEtlcm5lbC5TcGVjaWFsRm9ybXMudHVwbGUoS2VybmVsLlNwZWNpYWxGb3Jtcy5hdG9tKCdvaycpLCBuYW1lKTtcbn07XG5cbmNvbnN0IHN0b3AgPSBmdW5jdGlvbiAoYWdlbnQsIHRpbWVvdXQgPSA1MDAwKSB7XG4gIHNlbGYucG9zdF9vZmZpY2UucmVtb3ZlX21haWxib3goYWdlbnQpO1xuICByZXR1cm4gS2VybmVsLlNwZWNpYWxGb3Jtcy5hdG9tKCdvaycpO1xufTtcblxuY29uc3QgcmVuZGVyID0gZnVuY3Rpb24gKGFnZW50LCBzdGF0ZSkge1xuXG4gIGNvbnN0IGN1cnJlbnRfc3RhdGUgPSBzZWxmLnBvc3Rfb2ZmaWNlLnJlY2VpdmUoYWdlbnQpO1xuXG4gIGxldCByb290Tm9kZSA9IEtlcm5lbC5lbGVtKGN1cnJlbnRfc3RhdGUsIDApO1xuICBsZXQgdHJlZSA9IEtlcm5lbC5lbGVtKGN1cnJlbnRfc3RhdGUsIDEpO1xuICBsZXQgcmVuZGVyRm4gPSBLZXJuZWwuZWxlbShjdXJyZW50X3N0YXRlLCAyKTtcblxuICBsZXQgbmV3VHJlZSA9IHJlbmRlckZuLmFwcGx5KHRoaXMsIHN0YXRlKTtcblxuICBsZXQgcGF0Y2hlcyA9IHZpcnR1YWxEb20uZGlmZih0cmVlLCBuZXdUcmVlKTtcbiAgcm9vdE5vZGUgPSB2aXJ0dWFsRG9tLnBhdGNoKHJvb3ROb2RlLCBwYXRjaGVzKTtcblxuICBzZWxmLnBvc3Rfb2ZmaWNlLnNlbmQoYWdlbnQsIEtlcm5lbC5TcGVjaWFsRm9ybXMudHVwbGUocm9vdE5vZGUsIG5ld1RyZWUsIHJlbmRlckZuKSk7XG5cbiAgcmV0dXJuIEtlcm5lbC5TcGVjaWFsRm9ybXMuYXRvbSgnb2snKTtcbn07XG5cbnZhciBWaWV3ID0ge1xuICBzdGFydCxcbiAgc3RvcCxcbiAgcmVuZGVyXG59O1xuXG5zZWxmLnBvc3Rfb2ZmaWNlID0gc2VsZi5wb3N0X29mZmljZSB8fCBuZXcgUG9zdE9mZmljZSgpO1xuXG5leHBvcnQgeyBfUGF0dGVybnMgYXMgUGF0dGVybnMsIEJpdFN0cmluZywgS2VybmVsLCBBdG9tLCBFbnVtLCBJbnRlZ2VyLCBKUywgTGlzdCwgUmFuZ2UsIFR1cGxlLCBBZ2VudCwgS2V5d29yZCwgQmFzZSwgX1N0cmluZyBhcyBTdHJpbmcsIEJpdHdpc2UsIEVudW1lcmFibGUsIENvbGxlY3RhYmxlLCBJbnNwZWN0LCBfTWFwIGFzIE1hcCwgX1NldCBhcyBTZXQsIE1hcFNldCwgSW50ZWdlclR5cGUsIEZsb2F0VHlwZSwgdmlydHVhbERvbSBhcyBWaXJ0dWFsRE9NLCBWaWV3IH07Il0sImZpbGUiOiJlbGl4aXIuanMiLCJzb3VyY2VSb290IjoiL3NvdXJjZS8ifQ== \ No newline at end of file +//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiIiwic291cmNlcyI6WyJlbGl4aXIuanMiXSwic291cmNlc0NvbnRlbnQiOlsidmFyIFBhdHRlcm5zID0ge1xuICAgIGdldCBkZWZhdWx0ICgpIHsgcmV0dXJuIF9QYXR0ZXJuczsgfVxufTtcblxuLyogQGZsb3cgKi9cblxuY2xhc3MgVmFyaWFibGUge1xuXG4gIGNvbnN0cnVjdG9yKG5hbWUgPSBudWxsKSB7XG4gICAgdGhpcy5uYW1lID0gbmFtZTtcbiAgfVxufVxuXG5jbGFzcyBXaWxkY2FyZCB7XG4gIGNvbnN0cnVjdG9yKCkge31cbn1cblxuY2xhc3MgU3RhcnRzV2l0aCB7XG5cbiAgY29uc3RydWN0b3IocHJlZml4KSB7XG4gICAgdGhpcy5wcmVmaXggPSBwcmVmaXg7XG4gIH1cbn1cblxuY2xhc3MgQ2FwdHVyZSB7XG5cbiAgY29uc3RydWN0b3IodmFsdWUpIHtcbiAgICB0aGlzLnZhbHVlID0gdmFsdWU7XG4gIH1cbn1cblxuY2xhc3MgSGVhZFRhaWwge1xuICBjb25zdHJ1Y3RvcigpIHt9XG59XG5cbmNsYXNzIFR5cGUge1xuXG4gIGNvbnN0cnVjdG9yKHR5cGUsIG9ialBhdHRlcm4gPSB7fSkge1xuICAgIHRoaXMudHlwZSA9IHR5cGU7XG4gICAgdGhpcy5vYmpQYXR0ZXJuID0gb2JqUGF0dGVybjtcbiAgfVxufVxuXG5jbGFzcyBCb3VuZCB7XG5cbiAgY29uc3RydWN0b3IodmFsdWUpIHtcbiAgICB0aGlzLnZhbHVlID0gdmFsdWU7XG4gIH1cbn1cblxuZnVuY3Rpb24gdmFyaWFibGUobmFtZSA9IG51bGwpIHtcbiAgcmV0dXJuIG5ldyBWYXJpYWJsZShuYW1lKTtcbn1cblxuZnVuY3Rpb24gd2lsZGNhcmQoKSB7XG4gIHJldHVybiBuZXcgV2lsZGNhcmQoKTtcbn1cblxuZnVuY3Rpb24gc3RhcnRzV2l0aChwcmVmaXgpIHtcbiAgcmV0dXJuIG5ldyBTdGFydHNXaXRoKHByZWZpeCk7XG59XG5cbmZ1bmN0aW9uIGNhcHR1cmUodmFsdWUpIHtcbiAgcmV0dXJuIG5ldyBDYXB0dXJlKHZhbHVlKTtcbn1cblxuZnVuY3Rpb24gaGVhZFRhaWwoKSB7XG4gIHJldHVybiBuZXcgSGVhZFRhaWwoKTtcbn1cblxuZnVuY3Rpb24gdHlwZSh0eXBlLCBvYmpQYXR0ZXJuID0ge30pIHtcbiAgcmV0dXJuIG5ldyBUeXBlKHR5cGUsIG9ialBhdHRlcm4pO1xufVxuXG5mdW5jdGlvbiBib3VuZCh2YWx1ZSkge1xuICByZXR1cm4gbmV3IEJvdW5kKHZhbHVlKTtcbn1cblxuZnVuY3Rpb24gX2lzX251bWJlcih2YWx1ZSkge1xuICByZXR1cm4gdHlwZW9mIHZhbHVlID09PSAnbnVtYmVyJztcbn1cblxuZnVuY3Rpb24gaXNfc3RyaW5nKHZhbHVlKSB7XG4gIHJldHVybiB0eXBlb2YgdmFsdWUgPT09ICdzdHJpbmcnO1xufVxuXG5mdW5jdGlvbiBfaXNfYm9vbGVhbih2YWx1ZSkge1xuICByZXR1cm4gdHlwZW9mIHZhbHVlID09PSAnYm9vbGVhbic7XG59XG5cbmZ1bmN0aW9uIGlzX3N5bWJvbCh2YWx1ZSkge1xuICByZXR1cm4gdHlwZW9mIHZhbHVlID09PSAnc3ltYm9sJztcbn1cblxuZnVuY3Rpb24gaXNfbnVsbCh2YWx1ZSkge1xuICByZXR1cm4gdmFsdWUgPT09IG51bGw7XG59XG5cbmZ1bmN0aW9uIGlzX3VuZGVmaW5lZCh2YWx1ZSkge1xuICByZXR1cm4gdHlwZW9mIHZhbHVlID09PSAndW5kZWZpbmVkJztcbn1cblxuZnVuY3Rpb24gX2lzX2Z1bmN0aW9uKHZhbHVlKSB7XG4gIHJldHVybiBPYmplY3QucHJvdG90eXBlLnRvU3RyaW5nLmNhbGwodmFsdWUpID09ICdbb2JqZWN0IEZ1bmN0aW9uXSc7XG59XG5cbmZ1bmN0aW9uIGlzX3ZhcmlhYmxlKHZhbHVlKSB7XG4gIHJldHVybiB2YWx1ZSBpbnN0YW5jZW9mIFZhcmlhYmxlO1xufVxuXG5mdW5jdGlvbiBpc193aWxkY2FyZCh2YWx1ZSkge1xuICByZXR1cm4gdmFsdWUgaW5zdGFuY2VvZiBXaWxkY2FyZDtcbn1cblxuZnVuY3Rpb24gaXNfaGVhZFRhaWwodmFsdWUpIHtcbiAgcmV0dXJuIHZhbHVlIGluc3RhbmNlb2YgSGVhZFRhaWw7XG59XG5cbmZ1bmN0aW9uIGlzX2NhcHR1cmUodmFsdWUpIHtcbiAgcmV0dXJuIHZhbHVlIGluc3RhbmNlb2YgQ2FwdHVyZTtcbn1cblxuZnVuY3Rpb24gaXNfdHlwZSh2YWx1ZSkge1xuICByZXR1cm4gdmFsdWUgaW5zdGFuY2VvZiBUeXBlO1xufVxuXG5mdW5jdGlvbiBpc19zdGFydHNXaXRoKHZhbHVlKSB7XG4gIHJldHVybiB2YWx1ZSBpbnN0YW5jZW9mIFN0YXJ0c1dpdGg7XG59XG5cbmZ1bmN0aW9uIGlzX2JvdW5kKHZhbHVlKSB7XG4gIHJldHVybiB2YWx1ZSBpbnN0YW5jZW9mIEJvdW5kO1xufVxuXG5mdW5jdGlvbiBpc19vYmplY3QodmFsdWUpIHtcbiAgcmV0dXJuIHR5cGVvZiB2YWx1ZSA9PT0gJ29iamVjdCc7XG59XG5cbmZ1bmN0aW9uIGlzX2FycmF5KHZhbHVlKSB7XG4gIHJldHVybiBBcnJheS5pc0FycmF5KHZhbHVlKTtcbn1cblxudmFyIENoZWNrcyA9IHtcbiAgaXNfbnVtYmVyOiBfaXNfbnVtYmVyLFxuICBpc19zdHJpbmcsXG4gIGlzX2Jvb2xlYW46IF9pc19ib29sZWFuLFxuICBpc19zeW1ib2wsXG4gIGlzX251bGwsXG4gIGlzX3VuZGVmaW5lZCxcbiAgaXNfZnVuY3Rpb246IF9pc19mdW5jdGlvbixcbiAgaXNfdmFyaWFibGUsXG4gIGlzX3dpbGRjYXJkLFxuICBpc19oZWFkVGFpbCxcbiAgaXNfY2FwdHVyZSxcbiAgaXNfdHlwZSxcbiAgaXNfc3RhcnRzV2l0aCxcbiAgaXNfYm91bmQsXG4gIGlzX29iamVjdCxcbiAgaXNfYXJyYXlcbn07XG5cbmZ1bmN0aW9uIHJlc29sdmVTeW1ib2wocGF0dGVybikge1xuICByZXR1cm4gZnVuY3Rpb24gKHZhbHVlKSB7XG4gICAgcmV0dXJuIENoZWNrcy5pc19zeW1ib2wodmFsdWUpICYmIHZhbHVlID09PSBwYXR0ZXJuO1xuICB9O1xufVxuXG5mdW5jdGlvbiByZXNvbHZlU3RyaW5nKHBhdHRlcm4pIHtcbiAgcmV0dXJuIGZ1bmN0aW9uICh2YWx1ZSkge1xuICAgIHJldHVybiBDaGVja3MuaXNfc3RyaW5nKHZhbHVlKSAmJiB2YWx1ZSA9PT0gcGF0dGVybjtcbiAgfTtcbn1cblxuZnVuY3Rpb24gcmVzb2x2ZU51bWJlcihwYXR0ZXJuKSB7XG4gIHJldHVybiBmdW5jdGlvbiAodmFsdWUpIHtcbiAgICByZXR1cm4gQ2hlY2tzLmlzX251bWJlcih2YWx1ZSkgJiYgdmFsdWUgPT09IHBhdHRlcm47XG4gIH07XG59XG5cbmZ1bmN0aW9uIHJlc29sdmVCb29sZWFuKHBhdHRlcm4pIHtcbiAgcmV0dXJuIGZ1bmN0aW9uICh2YWx1ZSkge1xuICAgIHJldHVybiBDaGVja3MuaXNfYm9vbGVhbih2YWx1ZSkgJiYgdmFsdWUgPT09IHBhdHRlcm47XG4gIH07XG59XG5cbmZ1bmN0aW9uIHJlc29sdmVGdW5jdGlvbihwYXR0ZXJuKSB7XG4gIHJldHVybiBmdW5jdGlvbiAodmFsdWUpIHtcbiAgICByZXR1cm4gQ2hlY2tzLmlzX2Z1bmN0aW9uKHZhbHVlKSAmJiB2YWx1ZSA9PT0gcGF0dGVybjtcbiAgfTtcbn1cblxuZnVuY3Rpb24gcmVzb2x2ZU51bGwocGF0dGVybikge1xuICByZXR1cm4gZnVuY3Rpb24gKHZhbHVlKSB7XG4gICAgcmV0dXJuIENoZWNrcy5pc19udWxsKHZhbHVlKTtcbiAgfTtcbn1cblxuZnVuY3Rpb24gcmVzb2x2ZUJvdW5kKHBhdHRlcm4pIHtcbiAgcmV0dXJuIGZ1bmN0aW9uICh2YWx1ZSwgYXJncykge1xuICAgIGlmICh0eXBlb2YgdmFsdWUgPT09IHR5cGVvZiBwYXR0ZXJuLnZhbHVlICYmIHZhbHVlID09PSBwYXR0ZXJuLnZhbHVlKSB7XG4gICAgICBhcmdzLnB1c2godmFsdWUpO1xuICAgICAgcmV0dXJuIHRydWU7XG4gICAgfVxuXG4gICAgcmV0dXJuIGZhbHNlO1xuICB9O1xufVxuXG5mdW5jdGlvbiByZXNvbHZlV2lsZGNhcmQoKSB7XG4gIHJldHVybiBmdW5jdGlvbiAoKSB7XG4gICAgcmV0dXJuIHRydWU7XG4gIH07XG59XG5cbmZ1bmN0aW9uIHJlc29sdmVWYXJpYWJsZSgpIHtcbiAgcmV0dXJuIGZ1bmN0aW9uICh2YWx1ZSwgYXJncykge1xuICAgIGFyZ3MucHVzaCh2YWx1ZSk7XG4gICAgcmV0dXJuIHRydWU7XG4gIH07XG59XG5cbmZ1bmN0aW9uIHJlc29sdmVIZWFkVGFpbCgpIHtcbiAgcmV0dXJuIGZ1bmN0aW9uICh2YWx1ZSwgYXJncykge1xuICAgIGlmICghQ2hlY2tzLmlzX2FycmF5KHZhbHVlKSB8fCB2YWx1ZS5sZW5ndGggPCAyKSB7XG4gICAgICByZXR1cm4gZmFsc2U7XG4gICAgfVxuXG4gICAgY29uc3QgaGVhZCA9IHZhbHVlWzBdO1xuICAgIGNvbnN0IHRhaWwgPSB2YWx1ZS5zbGljZSgxKTtcblxuICAgIGFyZ3MucHVzaChoZWFkKTtcbiAgICBhcmdzLnB1c2godGFpbCk7XG5cbiAgICByZXR1cm4gdHJ1ZTtcbiAgfTtcbn1cblxuZnVuY3Rpb24gcmVzb2x2ZUNhcHR1cmUocGF0dGVybikge1xuICBjb25zdCBtYXRjaGVzID0gYnVpbGRNYXRjaChwYXR0ZXJuLnZhbHVlKTtcblxuICByZXR1cm4gZnVuY3Rpb24gKHZhbHVlLCBhcmdzKSB7XG4gICAgaWYgKG1hdGNoZXModmFsdWUsIGFyZ3MpKSB7XG4gICAgICBhcmdzLnB1c2godmFsdWUpO1xuICAgICAgcmV0dXJuIHRydWU7XG4gICAgfVxuXG4gICAgcmV0dXJuIGZhbHNlO1xuICB9O1xufVxuXG5mdW5jdGlvbiByZXNvbHZlU3RhcnRzV2l0aChwYXR0ZXJuKSB7XG4gIGNvbnN0IHByZWZpeCA9IHBhdHRlcm4ucHJlZml4O1xuXG4gIHJldHVybiBmdW5jdGlvbiAodmFsdWUsIGFyZ3MpIHtcbiAgICBpZiAoQ2hlY2tzLmlzX3N0cmluZyh2YWx1ZSkgJiYgdmFsdWUuc3RhcnRzV2l0aChwcmVmaXgpKSB7XG4gICAgICBhcmdzLnB1c2godmFsdWUuc3Vic3RyaW5nKHByZWZpeC5sZW5ndGgpKTtcbiAgICAgIHJldHVybiB0cnVlO1xuICAgIH1cblxuICAgIHJldHVybiBmYWxzZTtcbiAgfTtcbn1cblxuZnVuY3Rpb24gcmVzb2x2ZVR5cGUocGF0dGVybikge1xuICByZXR1cm4gZnVuY3Rpb24gKHZhbHVlLCBhcmdzKSB7XG4gICAgaWYgKHZhbHVlIGluc3RhbmNlb2YgcGF0dGVybi50eXBlKSB7XG4gICAgICBjb25zdCBtYXRjaGVzID0gYnVpbGRNYXRjaChwYXR0ZXJuLm9ialBhdHRlcm4pO1xuICAgICAgcmV0dXJuIG1hdGNoZXModmFsdWUsIGFyZ3MpICYmIGFyZ3MucHVzaCh2YWx1ZSkgPiAwO1xuICAgIH1cblxuICAgIHJldHVybiBmYWxzZTtcbiAgfTtcbn1cblxuZnVuY3Rpb24gcmVzb2x2ZUFycmF5KHBhdHRlcm4pIHtcbiAgY29uc3QgbWF0Y2hlcyA9IHBhdHRlcm4ubWFwKHggPT4gYnVpbGRNYXRjaCh4KSk7XG5cbiAgcmV0dXJuIGZ1bmN0aW9uICh2YWx1ZSwgYXJncykge1xuICAgIGlmICghQ2hlY2tzLmlzX2FycmF5KHZhbHVlKSB8fCB2YWx1ZS5sZW5ndGggIT0gcGF0dGVybi5sZW5ndGgpIHtcbiAgICAgIHJldHVybiBmYWxzZTtcbiAgICB9XG5cbiAgICByZXR1cm4gdmFsdWUuZXZlcnkoZnVuY3Rpb24gKHYsIGkpIHtcbiAgICAgIHJldHVybiBtYXRjaGVzW2ldKHZhbHVlW2ldLCBhcmdzKTtcbiAgICB9KTtcbiAgfTtcbn1cblxuZnVuY3Rpb24gcmVzb2x2ZU9iamVjdChwYXR0ZXJuKSB7XG4gIGxldCBtYXRjaGVzID0ge307XG5cbiAgZm9yIChsZXQga2V5IG9mIE9iamVjdC5rZXlzKHBhdHRlcm4pKSB7XG4gICAgbWF0Y2hlc1trZXldID0gYnVpbGRNYXRjaChwYXR0ZXJuW2tleV0pO1xuICB9XG5cbiAgcmV0dXJuIGZ1bmN0aW9uICh2YWx1ZSwgYXJncykge1xuICAgIGlmICghQ2hlY2tzLmlzX29iamVjdCh2YWx1ZSkgfHwgcGF0dGVybi5sZW5ndGggPiB2YWx1ZS5sZW5ndGgpIHtcbiAgICAgIHJldHVybiBmYWxzZTtcbiAgICB9XG5cbiAgICBmb3IgKGxldCBrZXkgb2YgT2JqZWN0LmtleXMocGF0dGVybikpIHtcbiAgICAgIGlmICghKGtleSBpbiB2YWx1ZSkgfHwgIW1hdGNoZXNba2V5XSh2YWx1ZVtrZXldLCBhcmdzKSkge1xuICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICB9XG4gICAgfVxuXG4gICAgcmV0dXJuIHRydWU7XG4gIH07XG59XG5cbmZ1bmN0aW9uIHJlc29sdmVOb01hdGNoKCkge1xuICByZXR1cm4gZnVuY3Rpb24gKCkge1xuICAgIHJldHVybiBmYWxzZTtcbiAgfTtcbn1cblxudmFyIFJlc29sdmVycyA9IHtcbiAgcmVzb2x2ZUJvdW5kLFxuICByZXNvbHZlV2lsZGNhcmQsXG4gIHJlc29sdmVWYXJpYWJsZSxcbiAgcmVzb2x2ZUhlYWRUYWlsLFxuICByZXNvbHZlQ2FwdHVyZSxcbiAgcmVzb2x2ZVN0YXJ0c1dpdGgsXG4gIHJlc29sdmVUeXBlLFxuICByZXNvbHZlQXJyYXksXG4gIHJlc29sdmVPYmplY3QsXG4gIHJlc29sdmVOb01hdGNoLFxuICByZXNvbHZlU3ltYm9sLFxuICByZXNvbHZlU3RyaW5nLFxuICByZXNvbHZlTnVtYmVyLFxuICByZXNvbHZlQm9vbGVhbixcbiAgcmVzb2x2ZUZ1bmN0aW9uLFxuICByZXNvbHZlTnVsbFxufTtcblxuZnVuY3Rpb24gYnVpbGRNYXRjaChwYXR0ZXJuKSB7XG5cbiAgaWYgKENoZWNrcy5pc192YXJpYWJsZShwYXR0ZXJuKSkge1xuICAgIHJldHVybiBSZXNvbHZlcnMucmVzb2x2ZVZhcmlhYmxlKHBhdHRlcm4pO1xuICB9XG5cbiAgaWYgKENoZWNrcy5pc193aWxkY2FyZChwYXR0ZXJuKSkge1xuICAgIHJldHVybiBSZXNvbHZlcnMucmVzb2x2ZVdpbGRjYXJkKHBhdHRlcm4pO1xuICB9XG5cbiAgaWYgKENoZWNrcy5pc191bmRlZmluZWQocGF0dGVybikpIHtcbiAgICByZXR1cm4gUmVzb2x2ZXJzLnJlc29sdmVXaWxkY2FyZChwYXR0ZXJuKTtcbiAgfVxuXG4gIGlmIChDaGVja3MuaXNfaGVhZFRhaWwocGF0dGVybikpIHtcbiAgICByZXR1cm4gUmVzb2x2ZXJzLnJlc29sdmVIZWFkVGFpbChwYXR0ZXJuKTtcbiAgfVxuXG4gIGlmIChDaGVja3MuaXNfc3RhcnRzV2l0aChwYXR0ZXJuKSkge1xuICAgIHJldHVybiBSZXNvbHZlcnMucmVzb2x2ZVN0YXJ0c1dpdGgocGF0dGVybik7XG4gIH1cblxuICBpZiAoQ2hlY2tzLmlzX2NhcHR1cmUocGF0dGVybikpIHtcbiAgICByZXR1cm4gUmVzb2x2ZXJzLnJlc29sdmVDYXB0dXJlKHBhdHRlcm4pO1xuICB9XG5cbiAgaWYgKENoZWNrcy5pc19ib3VuZChwYXR0ZXJuKSkge1xuICAgIHJldHVybiBSZXNvbHZlcnMucmVzb2x2ZUJvdW5kKHBhdHRlcm4pO1xuICB9XG5cbiAgaWYgKENoZWNrcy5pc190eXBlKHBhdHRlcm4pKSB7XG4gICAgcmV0dXJuIFJlc29sdmVycy5yZXNvbHZlVHlwZShwYXR0ZXJuKTtcbiAgfVxuXG4gIGlmIChDaGVja3MuaXNfYXJyYXkocGF0dGVybikpIHtcbiAgICByZXR1cm4gUmVzb2x2ZXJzLnJlc29sdmVBcnJheShwYXR0ZXJuKTtcbiAgfVxuXG4gIGlmIChDaGVja3MuaXNfbnVtYmVyKHBhdHRlcm4pKSB7XG4gICAgcmV0dXJuIFJlc29sdmVycy5yZXNvbHZlTnVtYmVyKHBhdHRlcm4pO1xuICB9XG5cbiAgaWYgKENoZWNrcy5pc19zdHJpbmcocGF0dGVybikpIHtcbiAgICByZXR1cm4gUmVzb2x2ZXJzLnJlc29sdmVTdHJpbmcocGF0dGVybik7XG4gIH1cblxuICBpZiAoQ2hlY2tzLmlzX2Jvb2xlYW4ocGF0dGVybikpIHtcbiAgICByZXR1cm4gUmVzb2x2ZXJzLnJlc29sdmVCb29sZWFuKHBhdHRlcm4pO1xuICB9XG5cbiAgaWYgKENoZWNrcy5pc19zeW1ib2wocGF0dGVybikpIHtcbiAgICByZXR1cm4gUmVzb2x2ZXJzLnJlc29sdmVTeW1ib2wocGF0dGVybik7XG4gIH1cblxuICBpZiAoQ2hlY2tzLmlzX251bGwocGF0dGVybikpIHtcbiAgICByZXR1cm4gUmVzb2x2ZXJzLnJlc29sdmVOdWxsKHBhdHRlcm4pO1xuICB9XG5cbiAgaWYgKENoZWNrcy5pc19vYmplY3QocGF0dGVybikpIHtcbiAgICByZXR1cm4gUmVzb2x2ZXJzLnJlc29sdmVPYmplY3QocGF0dGVybik7XG4gIH1cblxuICByZXR1cm4gUmVzb2x2ZXJzLnJlc29sdmVOb01hdGNoKCk7XG59XG5cbmNsYXNzIE1hdGNoRXJyb3IgZXh0ZW5kcyBFcnJvciB7XG4gIGNvbnN0cnVjdG9yKGFyZykge1xuICAgIHN1cGVyKCk7XG5cbiAgICBpZiAodHlwZW9mIGFyZyA9PT0gJ3N5bWJvbCcpIHtcbiAgICAgIHRoaXMubWVzc2FnZSA9ICdObyBtYXRjaCBmb3I6ICcgKyBhcmcudG9TdHJpbmcoKTtcbiAgICB9IGVsc2UgaWYgKEFycmF5LmlzQXJyYXkoYXJnKSkge1xuICAgICAgbGV0IG1hcHBlZFZhbHVlcyA9IGFyZy5tYXAoeCA9PiB4LnRvU3RyaW5nKCkpO1xuICAgICAgdGhpcy5tZXNzYWdlID0gJ05vIG1hdGNoIGZvcjogJyArIG1hcHBlZFZhbHVlcztcbiAgICB9IGVsc2Uge1xuICAgICAgdGhpcy5tZXNzYWdlID0gJ05vIG1hdGNoIGZvcjogJyArIGFyZztcbiAgICB9XG5cbiAgICB0aGlzLnN0YWNrID0gbmV3IEVycm9yKCkuc3RhY2s7XG4gICAgdGhpcy5uYW1lID0gdGhpcy5jb25zdHJ1Y3Rvci5uYW1lO1xuICB9XG59XG5cbmNsYXNzIENhc2Uge1xuXG4gIGNvbnN0cnVjdG9yKHBhdHRlcm4sIGZuLCBndWFyZCA9ICgpID0+IHRydWUpIHtcbiAgICB0aGlzLnBhdHRlcm4gPSBidWlsZE1hdGNoKHBhdHRlcm4pO1xuICAgIHRoaXMuZm4gPSBmbjtcbiAgICB0aGlzLmd1YXJkID0gZ3VhcmQ7XG4gIH1cbn1cblxuZnVuY3Rpb24gbWFrZV9jYXNlKHBhdHRlcm4sIGZuLCBndWFyZCA9ICgpID0+IHRydWUpIHtcbiAgcmV0dXJuIG5ldyBDYXNlKHBhdHRlcm4sIGZuLCBndWFyZCk7XG59XG5cbmZ1bmN0aW9uIGRlZm1hdGNoKC4uLmNhc2VzKSB7XG4gIHJldHVybiBmdW5jdGlvbiAoLi4uYXJncykge1xuICAgIGZvciAobGV0IHByb2Nlc3NlZENhc2Ugb2YgY2FzZXMpIHtcbiAgICAgIGxldCByZXN1bHQgPSBbXTtcbiAgICAgIGlmIChwcm9jZXNzZWRDYXNlLnBhdHRlcm4oYXJncywgcmVzdWx0KSAmJiBwcm9jZXNzZWRDYXNlLmd1YXJkLmFwcGx5KHRoaXMsIHJlc3VsdCkpIHtcbiAgICAgICAgcmV0dXJuIHByb2Nlc3NlZENhc2UuZm4uYXBwbHkodGhpcywgcmVzdWx0KTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICB0aHJvdyBuZXcgTWF0Y2hFcnJvcihhcmdzKTtcbiAgfTtcbn1cblxuZnVuY3Rpb24gbWF0Y2gocGF0dGVybiwgZXhwciwgZ3VhcmQgPSAoKSA9PiB0cnVlKSB7XG4gIGxldCByZXN1bHQgPSBbXTtcbiAgbGV0IHByb2Nlc3NlZFBhdHRlcm4gPSBidWlsZE1hdGNoKHBhdHRlcm4pO1xuICBpZiAocHJvY2Vzc2VkUGF0dGVybihleHByLCByZXN1bHQpICYmIGd1YXJkLmFwcGx5KHRoaXMsIHJlc3VsdCkpIHtcbiAgICByZXR1cm4gcmVzdWx0O1xuICB9IGVsc2Uge1xuICAgIHRocm93IG5ldyBNYXRjaEVycm9yKGV4cHIpO1xuICB9XG59XG5cbmZ1bmN0aW9uIG1hdGNoX25vX3Rocm93KHBhdHRlcm4sIGV4cHIsIGd1YXJkID0gKCkgPT4gdHJ1ZSkge1xuICB0cnkge1xuICAgIHJldHVybiBtYXRjaChwYXR0ZXJuLCBleHByLCBndWFyZCk7XG4gIH0gY2F0Y2ggKGUpIHtcbiAgICBpZiAoZSBpbnN0YW5jZW9mIE1hdGNoRXJyb3IpIHtcbiAgICAgIHJldHVybiBudWxsO1xuICAgIH1cblxuICAgIHRocm93IGU7XG4gIH1cbn1cblxuZnVuY3Rpb24gcGF0dGVybk1hcChjb2xsZWN0aW9uLCBwYXR0ZXJuLCBmdW4sIGd1YXJkID0gKCkgPT4gdHJ1ZSkge1xuICBsZXQgcmV0ID0gW107XG5cbiAgZm9yIChsZXQgZWxlbSBvZiBjb2xsZWN0aW9uKSB7XG4gICAgdHJ5IHtcbiAgICAgIGxldCByZXN1bHQgPSBmdW4uYXBwbHkodGhpcywgbWF0Y2gocGF0dGVybiwgZWxlbSwgZ3VhcmQpKTtcbiAgICAgIHJldCA9IHJldC5jb25jYXQocmVzdWx0KTtcbiAgICB9IGNhdGNoIChlKSB7XG4gICAgICBpZiAoIShlIGluc3RhbmNlb2YgTWF0Y2hFcnJvcikpIHtcbiAgICAgICAgdGhyb3cgZTtcbiAgICAgIH1cbiAgICB9XG4gIH1cblxuICByZXR1cm4gcmV0O1xufVxuXG52YXIgX1BhdHRlcm5zID0ge1xuICBkZWZtYXRjaCwgbWF0Y2gsIE1hdGNoRXJyb3IsIG1hdGNoX25vX3Rocm93LCBwYXR0ZXJuTWFwLFxuICB2YXJpYWJsZSwgd2lsZGNhcmQsIHN0YXJ0c1dpdGgsXG4gIGNhcHR1cmUsIGhlYWRUYWlsLCB0eXBlLCBib3VuZCwgQ2FzZSwgbWFrZV9jYXNlXG59O1xuXG5jbGFzcyBUdXBsZSB7XG5cbiAgY29uc3RydWN0b3IoLi4uYXJncykge1xuICAgIHRoaXMudmFsdWVzID0gT2JqZWN0LmZyZWV6ZShhcmdzKTtcbiAgfVxuXG4gIGdldChpbmRleCkge1xuICAgIHJldHVybiB0aGlzLnZhbHVlc1tpbmRleF07XG4gIH1cblxuICBjb3VudCgpIHtcbiAgICByZXR1cm4gdGhpcy52YWx1ZXMubGVuZ3RoO1xuICB9XG5cbiAgW1N5bWJvbC5pdGVyYXRvcl0oKSB7XG4gICAgcmV0dXJuIHRoaXMudmFsdWVzW1N5bWJvbC5pdGVyYXRvcl0oKTtcbiAgfVxuXG4gIHRvU3RyaW5nKCkge1xuICAgIHZhciBpLFxuICAgICAgICBzID0gXCJcIjtcbiAgICBmb3IgKGkgPSAwOyBpIDwgdGhpcy52YWx1ZXMubGVuZ3RoOyBpKyspIHtcbiAgICAgIGlmIChzICE9PSBcIlwiKSB7XG4gICAgICAgIHMgKz0gXCIsIFwiO1xuICAgICAgfVxuICAgICAgcyArPSB0aGlzLnZhbHVlc1tpXS50b1N0cmluZygpO1xuICAgIH1cblxuICAgIHJldHVybiBcIntcIiArIHMgKyBcIn1cIjtcbiAgfVxuXG4gIHN0YXRpYyB0b19zdHJpbmcodHVwbGUpIHtcbiAgICByZXR1cm4gdHVwbGUudG9TdHJpbmcoKTtcbiAgfVxuXG4gIHN0YXRpYyBkZWxldGVfYXQodHVwbGUsIGluZGV4KSB7XG4gICAgbGV0IG5ld19saXN0ID0gW107XG5cbiAgICBmb3IgKHZhciBpID0gMDsgaSA8IHR1cGxlLmNvdW50KCk7IGkrKykge1xuICAgICAgaWYgKGkgIT09IGluZGV4KSB7XG4gICAgICAgIG5ld19saXN0LnB1c2godHVwbGUuZ2V0KGkpKTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICByZXR1cm4gS2VybmVsLlNwZWNpYWxGb3Jtcy50dXBsZS5hcHBseShudWxsLCBuZXdfbGlzdCk7XG4gIH1cblxuICBzdGF0aWMgZHVwbGljYXRlKGRhdGEsIHNpemUpIHtcbiAgICBsZXQgYXJyYXkgPSBbXTtcblxuICAgIGZvciAodmFyIGkgPSBzaXplIC0gMTsgaSA+PSAwOyBpLS0pIHtcbiAgICAgIGFycmF5LnB1c2goZGF0YSk7XG4gICAgfVxuXG4gICAgcmV0dXJuIEtlcm5lbC5TcGVjaWFsRm9ybXMudHVwbGUuYXBwbHkobnVsbCwgYXJyYXkpO1xuICB9XG5cbiAgc3RhdGljIGluc2VydF9hdCh0dXBsZSwgaW5kZXgsIHRlcm0pIHtcbiAgICBsZXQgbmV3X3R1cGxlID0gW107XG5cbiAgICBmb3IgKHZhciBpID0gMDsgaSA8PSB0dXBsZS5jb3VudCgpOyBpKyspIHtcbiAgICAgIGlmIChpID09PSBpbmRleCkge1xuICAgICAgICBuZXdfdHVwbGUucHVzaCh0ZXJtKTtcbiAgICAgICAgaSsrO1xuICAgICAgICBuZXdfdHVwbGUucHVzaCh0dXBsZS5nZXQoaSkpO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgbmV3X3R1cGxlLnB1c2godHVwbGUuZ2V0KGkpKTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICByZXR1cm4gS2VybmVsLlNwZWNpYWxGb3Jtcy50dXBsZS5hcHBseShudWxsLCBuZXdfdHVwbGUpO1xuICB9XG5cbiAgc3RhdGljIGZyb21fbGlzdChsaXN0KSB7XG4gICAgcmV0dXJuIEtlcm5lbC5TcGVjaWFsRm9ybXMudHVwbGUuYXBwbHkobnVsbCwgbGlzdCk7XG4gIH1cblxuICBzdGF0aWMgdG9fbGlzdCh0dXBsZSkge1xuICAgIGxldCBuZXdfbGlzdCA9IFtdO1xuXG4gICAgZm9yICh2YXIgaSA9IDA7IGkgPCB0dXBsZS5jb3VudCgpOyBpKyspIHtcbiAgICAgIG5ld19saXN0LnB1c2godHVwbGUuZ2V0KGkpKTtcbiAgICB9XG5cbiAgICByZXR1cm4gS2VybmVsLlNwZWNpYWxGb3Jtcy5saXN0KC4uLm5ld19saXN0KTtcbiAgfVxufVxuXG5jbGFzcyBCaXRTdHJpbmcge1xuICBjb25zdHJ1Y3RvciguLi5hcmdzKSB7XG4gICAgdGhpcy5yYXdfdmFsdWUgPSBmdW5jdGlvbiAoKSB7XG4gICAgICByZXR1cm4gT2JqZWN0LmZyZWV6ZShhcmdzKTtcbiAgICB9O1xuXG4gICAgdGhpcy52YWx1ZSA9IE9iamVjdC5mcmVlemUodGhpcy5wcm9jZXNzKGFyZ3MpKTtcbiAgfVxuXG4gIGdldChpbmRleCkge1xuICAgIHJldHVybiB0aGlzLnZhbHVlW2luZGV4XTtcbiAgfVxuXG4gIGNvdW50KCkge1xuICAgIHJldHVybiB0aGlzLnZhbHVlLmxlbmd0aDtcbiAgfVxuXG4gIFtTeW1ib2wuaXRlcmF0b3JdKCkge1xuICAgIHJldHVybiB0aGlzLnZhbHVlW1N5bWJvbC5pdGVyYXRvcl0oKTtcbiAgfVxuXG4gIHRvU3RyaW5nKCkge1xuICAgIHZhciBpLFxuICAgICAgICBzID0gXCJcIjtcbiAgICBmb3IgKGkgPSAwOyBpIDwgdGhpcy5jb3VudCgpOyBpKyspIHtcbiAgICAgIGlmIChzICE9PSBcIlwiKSB7XG4gICAgICAgIHMgKz0gXCIsIFwiO1xuICAgICAgfVxuICAgICAgcyArPSB0aGlzW2ldLnRvU3RyaW5nKCk7XG4gICAgfVxuXG4gICAgcmV0dXJuIFwiPDxcIiArIHMgKyBcIj4+XCI7XG4gIH1cblxuICBwcm9jZXNzKCkge1xuICAgIGxldCBwcm9jZXNzZWRfdmFsdWVzID0gW107XG5cbiAgICB2YXIgaTtcbiAgICBmb3IgKGkgPSAwOyBpIDwgdGhpcy5yYXdfdmFsdWUoKS5sZW5ndGg7IGkrKykge1xuICAgICAgbGV0IHByb2Nlc3NlZF92YWx1ZSA9IHRoaXNbXCJwcm9jZXNzX1wiICsgdGhpcy5yYXdfdmFsdWUoKVtpXS50eXBlXSh0aGlzLnJhd192YWx1ZSgpW2ldKTtcblxuICAgICAgZm9yIChsZXQgYXR0ciBvZiB0aGlzLnJhd192YWx1ZSgpW2ldLmF0dHJpYnV0ZXMpIHtcbiAgICAgICAgcHJvY2Vzc2VkX3ZhbHVlID0gdGhpc1tcInByb2Nlc3NfXCIgKyBhdHRyXShwcm9jZXNzZWRfdmFsdWUpO1xuICAgICAgfVxuXG4gICAgICBwcm9jZXNzZWRfdmFsdWVzID0gcHJvY2Vzc2VkX3ZhbHVlcy5jb25jYXQocHJvY2Vzc2VkX3ZhbHVlKTtcbiAgICB9XG5cbiAgICByZXR1cm4gcHJvY2Vzc2VkX3ZhbHVlcztcbiAgfVxuXG4gIHByb2Nlc3NfaW50ZWdlcih2YWx1ZSkge1xuICAgIHJldHVybiB2YWx1ZS52YWx1ZTtcbiAgfVxuXG4gIHByb2Nlc3NfZmxvYXQodmFsdWUpIHtcbiAgICBpZiAodmFsdWUuc2l6ZSA9PT0gNjQpIHtcbiAgICAgIHJldHVybiBCaXRTdHJpbmcuZmxvYXQ2NFRvQnl0ZXModmFsdWUudmFsdWUpO1xuICAgIH0gZWxzZSBpZiAodmFsdWUuc2l6ZSA9PT0gMzIpIHtcbiAgICAgIHJldHVybiBCaXRTdHJpbmcuZmxvYXQzMlRvQnl0ZXModmFsdWUudmFsdWUpO1xuICAgIH1cblxuICAgIHRocm93IG5ldyBFcnJvcihcIkludmFsaWQgc2l6ZSBmb3IgZmxvYXRcIik7XG4gIH1cblxuICBwcm9jZXNzX2JpdHN0cmluZyh2YWx1ZSkge1xuICAgIHJldHVybiB2YWx1ZS52YWx1ZS52YWx1ZTtcbiAgfVxuXG4gIHByb2Nlc3NfYmluYXJ5KHZhbHVlKSB7XG4gICAgcmV0dXJuIEJpdFN0cmluZy50b1VURjhBcnJheSh2YWx1ZS52YWx1ZSk7XG4gIH1cblxuICBwcm9jZXNzX3V0ZjgodmFsdWUpIHtcbiAgICByZXR1cm4gQml0U3RyaW5nLnRvVVRGOEFycmF5KHZhbHVlLnZhbHVlKTtcbiAgfVxuXG4gIHByb2Nlc3NfdXRmMTYodmFsdWUpIHtcbiAgICByZXR1cm4gQml0U3RyaW5nLnRvVVRGMTZBcnJheSh2YWx1ZS52YWx1ZSk7XG4gIH1cblxuICBwcm9jZXNzX3V0ZjMyKHZhbHVlKSB7XG4gICAgcmV0dXJuIEJpdFN0cmluZy50b1VURjMyQXJyYXkodmFsdWUudmFsdWUpO1xuICB9XG5cbiAgcHJvY2Vzc19zaWduZWQodmFsdWUpIHtcbiAgICByZXR1cm4gbmV3IFVpbnQ4QXJyYXkoW3ZhbHVlXSlbMF07XG4gIH1cblxuICBwcm9jZXNzX3Vuc2lnbmVkKHZhbHVlKSB7XG4gICAgcmV0dXJuIHZhbHVlO1xuICB9XG5cbiAgcHJvY2Vzc19uYXRpdmUodmFsdWUpIHtcbiAgICByZXR1cm4gdmFsdWU7XG4gIH1cblxuICBwcm9jZXNzX2JpZyh2YWx1ZSkge1xuICAgIHJldHVybiB2YWx1ZTtcbiAgfVxuXG4gIHByb2Nlc3NfbGl0dGxlKHZhbHVlKSB7XG4gICAgcmV0dXJuIHZhbHVlLnJldmVyc2UoKTtcbiAgfVxuXG4gIHByb2Nlc3Nfc2l6ZSh2YWx1ZSkge1xuICAgIHJldHVybiB2YWx1ZTtcbiAgfVxuXG4gIHByb2Nlc3NfdW5pdCh2YWx1ZSkge1xuICAgIHJldHVybiB2YWx1ZTtcbiAgfVxuXG4gIHN0YXRpYyBpbnRlZ2VyKHZhbHVlKSB7XG4gICAgcmV0dXJuIEJpdFN0cmluZy53cmFwKHZhbHVlLCB7IFwidHlwZVwiOiBcImludGVnZXJcIiwgXCJ1bml0XCI6IDEsIFwic2l6ZVwiOiA4IH0pO1xuICB9XG5cbiAgc3RhdGljIGZsb2F0KHZhbHVlKSB7XG4gICAgcmV0dXJuIEJpdFN0cmluZy53cmFwKHZhbHVlLCB7IFwidHlwZVwiOiBcImZsb2F0XCIsIFwidW5pdFwiOiAxLCBcInNpemVcIjogNjQgfSk7XG4gIH1cblxuICBzdGF0aWMgYml0c3RyaW5nKHZhbHVlKSB7XG4gICAgcmV0dXJuIEJpdFN0cmluZy53cmFwKHZhbHVlLCB7IFwidHlwZVwiOiBcImJpdHN0cmluZ1wiLCBcInVuaXRcIjogMSwgXCJzaXplXCI6IHZhbHVlLmxlbmd0aCB9KTtcbiAgfVxuXG4gIHN0YXRpYyBiaXRzKHZhbHVlKSB7XG4gICAgcmV0dXJuIEJpdFN0cmluZy5iaXRzdHJpbmcodmFsdWUpO1xuICB9XG5cbiAgc3RhdGljIGJpbmFyeSh2YWx1ZSkge1xuICAgIHJldHVybiBCaXRTdHJpbmcud3JhcCh2YWx1ZSwgeyBcInR5cGVcIjogXCJiaW5hcnlcIiwgXCJ1bml0XCI6IDgsIFwic2l6ZVwiOiB2YWx1ZS5sZW5ndGggfSk7XG4gIH1cblxuICBzdGF0aWMgYnl0ZXModmFsdWUpIHtcbiAgICByZXR1cm4gQml0U3RyaW5nLmJpbmFyeSh2YWx1ZSk7XG4gIH1cblxuICBzdGF0aWMgdXRmOCh2YWx1ZSkge1xuICAgIHJldHVybiBCaXRTdHJpbmcud3JhcCh2YWx1ZSwgeyBcInR5cGVcIjogXCJ1dGY4XCIgfSk7XG4gIH1cblxuICBzdGF0aWMgdXRmMTYodmFsdWUpIHtcbiAgICByZXR1cm4gQml0U3RyaW5nLndyYXAodmFsdWUsIHsgXCJ0eXBlXCI6IFwidXRmMTZcIiB9KTtcbiAgfVxuXG4gIHN0YXRpYyB1dGYzMih2YWx1ZSkge1xuICAgIHJldHVybiBCaXRTdHJpbmcud3JhcCh2YWx1ZSwgeyBcInR5cGVcIjogXCJ1dGYzMlwiIH0pO1xuICB9XG5cbiAgc3RhdGljIHNpZ25lZCh2YWx1ZSkge1xuICAgIHJldHVybiBCaXRTdHJpbmcud3JhcCh2YWx1ZSwge30sIFwic2lnbmVkXCIpO1xuICB9XG5cbiAgc3RhdGljIHVuc2lnbmVkKHZhbHVlKSB7XG4gICAgcmV0dXJuIEJpdFN0cmluZy53cmFwKHZhbHVlLCB7fSwgXCJ1bnNpZ25lZFwiKTtcbiAgfVxuXG4gIHN0YXRpYyBuYXRpdmUodmFsdWUpIHtcbiAgICByZXR1cm4gQml0U3RyaW5nLndyYXAodmFsdWUsIHt9LCBcIm5hdGl2ZVwiKTtcbiAgfVxuXG4gIHN0YXRpYyBiaWcodmFsdWUpIHtcbiAgICByZXR1cm4gQml0U3RyaW5nLndyYXAodmFsdWUsIHt9LCBcImJpZ1wiKTtcbiAgfVxuXG4gIHN0YXRpYyBsaXR0bGUodmFsdWUpIHtcbiAgICByZXR1cm4gQml0U3RyaW5nLndyYXAodmFsdWUsIHt9LCBcImxpdHRsZVwiKTtcbiAgfVxuXG4gIHN0YXRpYyBzaXplKHZhbHVlLCBjb3VudCkge1xuICAgIHJldHVybiBCaXRTdHJpbmcud3JhcCh2YWx1ZSwgeyBcInNpemVcIjogY291bnQgfSk7XG4gIH1cblxuICBzdGF0aWMgdW5pdCh2YWx1ZSwgY291bnQpIHtcbiAgICByZXR1cm4gQml0U3RyaW5nLndyYXAodmFsdWUsIHsgXCJ1bml0XCI6IGNvdW50IH0pO1xuICB9XG5cbiAgc3RhdGljIHdyYXAodmFsdWUsIG9wdCwgbmV3X2F0dHJpYnV0ZSA9IG51bGwpIHtcbiAgICBsZXQgdGhlX3ZhbHVlID0gdmFsdWU7XG5cbiAgICBpZiAoISh2YWx1ZSBpbnN0YW5jZW9mIE9iamVjdCkpIHtcbiAgICAgIHRoZV92YWx1ZSA9IHsgXCJ2YWx1ZVwiOiB2YWx1ZSwgXCJhdHRyaWJ1dGVzXCI6IFtdIH07XG4gICAgfVxuXG4gICAgdGhlX3ZhbHVlID0gT2JqZWN0LmFzc2lnbih0aGVfdmFsdWUsIG9wdCk7XG5cbiAgICBpZiAobmV3X2F0dHJpYnV0ZSkge1xuICAgICAgdGhlX3ZhbHVlLmF0dHJpYnV0ZXMucHVzaChuZXdfYXR0cmlidXRlKTtcbiAgICB9XG5cbiAgICByZXR1cm4gdGhlX3ZhbHVlO1xuICB9XG5cbiAgc3RhdGljIHRvVVRGOEFycmF5KHN0cikge1xuICAgIHZhciB1dGY4ID0gW107XG4gICAgZm9yICh2YXIgaSA9IDA7IGkgPCBzdHIubGVuZ3RoOyBpKyspIHtcbiAgICAgIHZhciBjaGFyY29kZSA9IHN0ci5jaGFyQ29kZUF0KGkpO1xuICAgICAgaWYgKGNoYXJjb2RlIDwgMTI4KSB7XG4gICAgICAgIHV0ZjgucHVzaChjaGFyY29kZSk7XG4gICAgICB9IGVsc2UgaWYgKGNoYXJjb2RlIDwgMjA0OCkge1xuICAgICAgICB1dGY4LnB1c2goMTkyIHwgY2hhcmNvZGUgPj4gNiwgMTI4IHwgY2hhcmNvZGUgJiA2Myk7XG4gICAgICB9IGVsc2UgaWYgKGNoYXJjb2RlIDwgNTUyOTYgfHwgY2hhcmNvZGUgPj0gNTczNDQpIHtcbiAgICAgICAgdXRmOC5wdXNoKDIyNCB8IGNoYXJjb2RlID4+IDEyLCAxMjggfCBjaGFyY29kZSA+PiA2ICYgNjMsIDEyOCB8IGNoYXJjb2RlICYgNjMpO1xuICAgICAgfVxuICAgICAgLy8gc3Vycm9nYXRlIHBhaXJcbiAgICAgIGVsc2Uge1xuICAgICAgICBpKys7XG4gICAgICAgIC8vIFVURi0xNiBlbmNvZGVzIDB4MTAwMDAtMHgxMEZGRkYgYnlcbiAgICAgICAgLy8gc3VidHJhY3RpbmcgMHgxMDAwMCBhbmQgc3BsaXR0aW5nIHRoZVxuICAgICAgICAvLyAyMCBiaXRzIG9mIDB4MC0weEZGRkZGIGludG8gdHdvIGhhbHZlc1xuICAgICAgICBjaGFyY29kZSA9IDY1NTM2ICsgKChjaGFyY29kZSAmIDEwMjMpIDw8IDEwIHwgc3RyLmNoYXJDb2RlQXQoaSkgJiAxMDIzKTtcbiAgICAgICAgdXRmOC5wdXNoKDI0MCB8IGNoYXJjb2RlID4+IDE4LCAxMjggfCBjaGFyY29kZSA+PiAxMiAmIDYzLCAxMjggfCBjaGFyY29kZSA+PiA2ICYgNjMsIDEyOCB8IGNoYXJjb2RlICYgNjMpO1xuICAgICAgfVxuICAgIH1cbiAgICByZXR1cm4gdXRmODtcbiAgfVxuXG4gIHN0YXRpYyB0b1VURjE2QXJyYXkoc3RyKSB7XG4gICAgdmFyIHV0ZjE2ID0gW107XG4gICAgZm9yICh2YXIgaSA9IDA7IGkgPCBzdHIubGVuZ3RoOyBpKyspIHtcbiAgICAgIHZhciBjb2RlUG9pbnQgPSBzdHIuY29kZVBvaW50QXQoaSk7XG5cbiAgICAgIGlmIChjb2RlUG9pbnQgPD0gMjU1KSB7XG4gICAgICAgIHV0ZjE2LnB1c2goMCk7XG4gICAgICAgIHV0ZjE2LnB1c2goY29kZVBvaW50KTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHV0ZjE2LnB1c2goY29kZVBvaW50ID4+IDggJiAyNTUpO1xuICAgICAgICB1dGYxNi5wdXNoKGNvZGVQb2ludCAmIDI1NSk7XG4gICAgICB9XG4gICAgfVxuICAgIHJldHVybiB1dGYxNjtcbiAgfVxuXG4gIHN0YXRpYyB0b1VURjMyQXJyYXkoc3RyKSB7XG4gICAgdmFyIHV0ZjMyID0gW107XG4gICAgZm9yICh2YXIgaSA9IDA7IGkgPCBzdHIubGVuZ3RoOyBpKyspIHtcbiAgICAgIHZhciBjb2RlUG9pbnQgPSBzdHIuY29kZVBvaW50QXQoaSk7XG5cbiAgICAgIGlmIChjb2RlUG9pbnQgPD0gMjU1KSB7XG4gICAgICAgIHV0ZjMyLnB1c2goMCk7XG4gICAgICAgIHV0ZjMyLnB1c2goMCk7XG4gICAgICAgIHV0ZjMyLnB1c2goMCk7XG4gICAgICAgIHV0ZjMyLnB1c2goY29kZVBvaW50KTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHV0ZjMyLnB1c2goMCk7XG4gICAgICAgIHV0ZjMyLnB1c2goMCk7XG4gICAgICAgIHV0ZjMyLnB1c2goY29kZVBvaW50ID4+IDggJiAyNTUpO1xuICAgICAgICB1dGYzMi5wdXNoKGNvZGVQb2ludCAmIDI1NSk7XG4gICAgICB9XG4gICAgfVxuICAgIHJldHVybiB1dGYzMjtcbiAgfVxuXG4gIC8vaHR0cDovL3N0YWNrb3ZlcmZsb3cuY29tL3F1ZXN0aW9ucy8yMDAzNDkzL2phdmFzY3JpcHQtZmxvYXQtZnJvbS10by1iaXRzXG4gIHN0YXRpYyBmbG9hdDMyVG9CeXRlcyhmKSB7XG4gICAgdmFyIGJ5dGVzID0gW107XG5cbiAgICB2YXIgYnVmID0gbmV3IEFycmF5QnVmZmVyKDQpO1xuICAgIG5ldyBGbG9hdDMyQXJyYXkoYnVmKVswXSA9IGY7XG5cbiAgICBsZXQgaW50VmVyc2lvbiA9IG5ldyBVaW50MzJBcnJheShidWYpWzBdO1xuXG4gICAgYnl0ZXMucHVzaChpbnRWZXJzaW9uID4+IDI0ICYgMjU1KTtcbiAgICBieXRlcy5wdXNoKGludFZlcnNpb24gPj4gMTYgJiAyNTUpO1xuICAgIGJ5dGVzLnB1c2goaW50VmVyc2lvbiA+PiA4ICYgMjU1KTtcbiAgICBieXRlcy5wdXNoKGludFZlcnNpb24gJiAyNTUpO1xuXG4gICAgcmV0dXJuIGJ5dGVzO1xuICB9XG5cbiAgc3RhdGljIGZsb2F0NjRUb0J5dGVzKGYpIHtcbiAgICB2YXIgYnl0ZXMgPSBbXTtcblxuICAgIHZhciBidWYgPSBuZXcgQXJyYXlCdWZmZXIoOCk7XG4gICAgbmV3IEZsb2F0NjRBcnJheShidWYpWzBdID0gZjtcblxuICAgIHZhciBpbnRWZXJzaW9uMSA9IG5ldyBVaW50MzJBcnJheShidWYpWzBdO1xuICAgIHZhciBpbnRWZXJzaW9uMiA9IG5ldyBVaW50MzJBcnJheShidWYpWzFdO1xuXG4gICAgYnl0ZXMucHVzaChpbnRWZXJzaW9uMiA+PiAyNCAmIDI1NSk7XG4gICAgYnl0ZXMucHVzaChpbnRWZXJzaW9uMiA+PiAxNiAmIDI1NSk7XG4gICAgYnl0ZXMucHVzaChpbnRWZXJzaW9uMiA+PiA4ICYgMjU1KTtcbiAgICBieXRlcy5wdXNoKGludFZlcnNpb24yICYgMjU1KTtcblxuICAgIGJ5dGVzLnB1c2goaW50VmVyc2lvbjEgPj4gMjQgJiAyNTUpO1xuICAgIGJ5dGVzLnB1c2goaW50VmVyc2lvbjEgPj4gMTYgJiAyNTUpO1xuICAgIGJ5dGVzLnB1c2goaW50VmVyc2lvbjEgPj4gOCAmIDI1NSk7XG4gICAgYnl0ZXMucHVzaChpbnRWZXJzaW9uMSAmIDI1NSk7XG5cbiAgICByZXR1cm4gYnl0ZXM7XG4gIH1cbn1cblxubGV0IFNwZWNpYWxGb3JtcyA9IHtcblxuICBfX0RJUl9fOiBmdW5jdGlvbiAoKSB7XG4gICAgaWYgKF9fZGlybmFtZSkge1xuICAgICAgcmV0dXJuIF9fZGlybmFtZTtcbiAgICB9XG5cbiAgICBpZiAoZG9jdW1lbnQuY3VycmVudFNjcmlwdCkge1xuICAgICAgcmV0dXJuIGRvY3VtZW50LmN1cnJlbnRTY3JpcHQuc3JjO1xuICAgIH1cblxuICAgIHJldHVybiBudWxsO1xuICB9LFxuXG4gIGF0b206IGZ1bmN0aW9uIChfdmFsdWUpIHtcbiAgICByZXR1cm4gU3ltYm9sLmZvcihfdmFsdWUpO1xuICB9LFxuXG4gIGxpc3Q6IGZ1bmN0aW9uICguLi5hcmdzKSB7XG4gICAgcmV0dXJuIE9iamVjdC5mcmVlemUoYXJncyk7XG4gIH0sXG5cbiAgYml0c3RyaW5nOiBmdW5jdGlvbiAoLi4uYXJncykge1xuICAgIHJldHVybiBuZXcgQml0U3RyaW5nKC4uLmFyZ3MpO1xuICB9LFxuXG4gIGJvdW5kOiBmdW5jdGlvbiAoX3Zhcikge1xuICAgIHJldHVybiBQYXR0ZXJucy5ib3VuZChfdmFyKTtcbiAgfSxcblxuICBfY2FzZTogZnVuY3Rpb24gKGNvbmRpdGlvbiwgY2xhdXNlcykge1xuICAgIHJldHVybiBQYXR0ZXJucy5kZWZtYXRjaCguLi5jbGF1c2VzKShjb25kaXRpb24pO1xuICB9LFxuXG4gIGNvbmQ6IGZ1bmN0aW9uIChjbGF1c2VzKSB7XG4gICAgZm9yIChsZXQgY2xhdXNlIG9mIGNsYXVzZXMpIHtcbiAgICAgIGlmIChjbGF1c2VbMF0pIHtcbiAgICAgICAgcmV0dXJuIGNsYXVzZVsxXSgpO1xuICAgICAgfVxuICAgIH1cblxuICAgIHRocm93IG5ldyBFcnJvcigpO1xuICB9LFxuXG4gIGZuOiBmdW5jdGlvbiAoY2xhdXNlcykge1xuICAgIHJldHVybiBQYXR0ZXJucy5kZWZtYXRjaChjbGF1c2VzKTtcbiAgfSxcblxuICBtYXA6IGZ1bmN0aW9uIChvYmopIHtcbiAgICByZXR1cm4gT2JqZWN0LmZyZWV6ZShvYmopO1xuICB9LFxuXG4gIG1hcF91cGRhdGU6IGZ1bmN0aW9uIChtYXAsIHZhbHVlcykge1xuICAgIHJldHVybiBPYmplY3QuZnJlZXplKE9iamVjdC5hc3NpZ24oT2JqZWN0LmNyZWF0ZShtYXAuY29uc3RydWN0b3IucHJvdG90eXBlKSwgbWFwLCB2YWx1ZXMpKTtcbiAgfSxcblxuICBfZm9yOiBmdW5jdGlvbiAoY29sbGVjdGlvbnMsIGZ1biwgZmlsdGVyID0gKCkgPT4gdHJ1ZSwgaW50byA9IFtdLCBwcmV2aW91c1ZhbHVlcyA9IFtdKSB7XG4gICAgbGV0IHBhdHRlcm4gPSBjb2xsZWN0aW9uc1swXVswXTtcbiAgICBsZXQgY29sbGVjdGlvbiA9IGNvbGxlY3Rpb25zWzBdWzFdO1xuXG4gICAgaWYgKGNvbGxlY3Rpb25zLmxlbmd0aCA9PT0gMSkge1xuXG4gICAgICBmb3IgKGxldCBlbGVtIG9mIGNvbGxlY3Rpb24pIHtcbiAgICAgICAgbGV0IHIgPSBQYXR0ZXJucy5tYXRjaF9ub190aHJvdyhwYXR0ZXJuLCBlbGVtKTtcbiAgICAgICAgbGV0IGFyZ3MgPSBwcmV2aW91c1ZhbHVlcy5jb25jYXQocik7XG5cbiAgICAgICAgaWYgKHIgJiYgZmlsdGVyLmFwcGx5KHRoaXMsIGFyZ3MpKSB7XG4gICAgICAgICAgaW50byA9IEVudW0uaW50byhbZnVuLmFwcGx5KHRoaXMsIGFyZ3MpXSwgaW50byk7XG4gICAgICAgIH1cbiAgICAgIH1cblxuICAgICAgcmV0dXJuIGludG87XG4gICAgfSBlbHNlIHtcbiAgICAgIGxldCBfaW50byA9IFtdO1xuXG4gICAgICBmb3IgKGxldCBlbGVtIG9mIGNvbGxlY3Rpb24pIHtcbiAgICAgICAgbGV0IHIgPSBQYXR0ZXJucy5tYXRjaF9ub190aHJvdyhwYXR0ZXJuLCBlbGVtKTtcbiAgICAgICAgaWYgKHIpIHtcbiAgICAgICAgICBfaW50byA9IEVudW0uaW50byh0aGlzLl9mb3IoY29sbGVjdGlvbnMuc2xpY2UoMSksIGZ1biwgZmlsdGVyLCBfaW50bywgcHJldmlvdXNWYWx1ZXMuY29uY2F0KHIpKSwgaW50byk7XG4gICAgICAgIH1cbiAgICAgIH1cblxuICAgICAgcmV0dXJuIF9pbnRvO1xuICAgIH1cbiAgfSxcblxuICByZWNlaXZlOiBmdW5jdGlvbiAocmVjZWl2ZV9mdW4sIHRpbWVvdXRfaW5fbXMgPSBudWxsLCB0aW1lb3V0X2ZuID0gdGltZSA9PiB0cnVlKSB7XG4gICAgaWYgKHRpbWVvdXRfaW5fbXMgPT0gbnVsbCB8fCB0aW1lb3V0X2luX21zID09PSBTeXN0ZW0uZm9yKCdpbmZpbml0eScpKSB7XG4gICAgICB3aGlsZSAodHJ1ZSkge1xuICAgICAgICBpZiAoc2VsZi5tYWlsYm94Lmxlbmd0aCAhPT0gMCkge1xuICAgICAgICAgIGxldCBtZXNzYWdlID0gc2VsZi5tYWlsYm94WzBdO1xuICAgICAgICAgIHNlbGYubWFpbGJveCA9IHNlbGYubWFpbGJveC5zbGljZSgxKTtcbiAgICAgICAgICByZXR1cm4gcmVjZWl2ZV9mdW4obWVzc2FnZSk7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9IGVsc2UgaWYgKHRpbWVvdXRfaW5fbXMgPT09IDApIHtcbiAgICAgIGlmIChzZWxmLm1haWxib3gubGVuZ3RoICE9PSAwKSB7XG4gICAgICAgIGxldCBtZXNzYWdlID0gc2VsZi5tYWlsYm94WzBdO1xuICAgICAgICBzZWxmLm1haWxib3ggPSBzZWxmLm1haWxib3guc2xpY2UoMSk7XG4gICAgICAgIHJldHVybiByZWNlaXZlX2Z1bihtZXNzYWdlKTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHJldHVybiBudWxsO1xuICAgICAgfVxuICAgIH0gZWxzZSB7XG4gICAgICBsZXQgbm93ID0gRGF0ZS5ub3coKTtcbiAgICAgIHdoaWxlIChEYXRlLm5vdygpIDwgbm93ICsgdGltZW91dF9pbl9tcykge1xuICAgICAgICBpZiAoc2VsZi5tYWlsYm94Lmxlbmd0aCAhPT0gMCkge1xuICAgICAgICAgIGxldCBtZXNzYWdlID0gc2VsZi5tYWlsYm94WzBdO1xuICAgICAgICAgIHNlbGYubWFpbGJveCA9IHNlbGYubWFpbGJveC5zbGljZSgxKTtcbiAgICAgICAgICByZXR1cm4gcmVjZWl2ZV9mdW4obWVzc2FnZSk7XG4gICAgICAgIH1cbiAgICAgIH1cblxuICAgICAgcmV0dXJuIHRpbWVvdXRfZm4odGltZW91dF9pbl9tcyk7XG4gICAgfVxuICB9LFxuXG4gIHR1cGxlOiBmdW5jdGlvbiAoLi4uYXJncykge1xuICAgIHJldHVybiBuZXcgVHVwbGUoLi4uYXJncyk7XG4gIH0sXG5cbiAgX3RyeTogZnVuY3Rpb24gKGRvX2Z1biwgcmVzY3VlX2Z1bmN0aW9uLCBjYXRjaF9mdW4sIGVsc2VfZnVuY3Rpb24sIGFmdGVyX2Z1bmN0aW9uKSB7XG4gICAgbGV0IHJlc3VsdCA9IG51bGw7XG5cbiAgICB0cnkge1xuICAgICAgcmVzdWx0ID0gZG9fZnVuKCk7XG4gICAgfSBjYXRjaCAoZSkge1xuICAgICAgbGV0IGV4X3Jlc3VsdCA9IG51bGw7XG5cbiAgICAgIGlmIChyZXNjdWVfZnVuY3Rpb24pIHtcbiAgICAgICAgdHJ5IHtcbiAgICAgICAgICBleF9yZXN1bHQgPSByZXNjdWVfZnVuY3Rpb24oZSk7XG4gICAgICAgICAgcmV0dXJuIGV4X3Jlc3VsdDtcbiAgICAgICAgfSBjYXRjaCAoZXgpIHtcbiAgICAgICAgICBpZiAoZXggaW5zdGFuY2VvZiBQYXR0ZXJucy5NYXRjaEVycm9yKSB7XG4gICAgICAgICAgICB0aHJvdyBleDtcbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgIH1cblxuICAgICAgaWYgKGNhdGNoX2Z1bikge1xuICAgICAgICB0cnkge1xuICAgICAgICAgIGV4X3Jlc3VsdCA9IGNhdGNoX2Z1bihlKTtcbiAgICAgICAgICByZXR1cm4gZXhfcmVzdWx0O1xuICAgICAgICB9IGNhdGNoIChleCkge1xuICAgICAgICAgIGlmIChleCBpbnN0YW5jZW9mIFBhdHRlcm5zLk1hdGNoRXJyb3IpIHtcbiAgICAgICAgICAgIHRocm93IGV4O1xuICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgfVxuXG4gICAgICB0aHJvdyBlO1xuICAgIH0gZmluYWxseSB7XG4gICAgICBpZiAoYWZ0ZXJfZnVuY3Rpb24pIHtcbiAgICAgICAgYWZ0ZXJfZnVuY3Rpb24oKTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICBpZiAoZWxzZV9mdW5jdGlvbikge1xuICAgICAgdHJ5IHtcbiAgICAgICAgcmV0dXJuIGVsc2VfZnVuY3Rpb24ocmVzdWx0KTtcbiAgICAgIH0gY2F0Y2ggKGV4KSB7XG4gICAgICAgIGlmIChleCBpbnN0YW5jZW9mIFBhdHRlcm5zLk1hdGNoRXJyb3IpIHtcbiAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ05vIE1hdGNoIEZvdW5kIGluIEVsc2UnKTtcbiAgICAgICAgfVxuXG4gICAgICAgIHRocm93IGV4O1xuICAgICAgfVxuICAgIH0gZWxzZSB7XG4gICAgICByZXR1cm4gcmVzdWx0O1xuICAgIH1cbiAgfVxuXG59O1xuXG4vKiBAZmxvdyAqL1xuXG5sZXQgcHJvY2Vzc19jb3VudGVyID0gLTE7XG5cbmNsYXNzIFBJRCB7XG4gIGNvbnN0cnVjdG9yKCkge1xuICAgIHByb2Nlc3NfY291bnRlciA9IHByb2Nlc3NfY291bnRlciArIDE7XG4gICAgdGhpcy5pZCA9IHByb2Nlc3NfY291bnRlcjtcbiAgfVxuXG4gIHRvU3RyaW5nKCkge1xuICAgIHJldHVybiBcIlBJRCM8MC5cIiArIHRoaXMuaWQgKyBcIi4wPlwiO1xuICB9XG59XG5cbmNsYXNzIEludGVnZXJUeXBlIHt9XG5jbGFzcyBGbG9hdFR5cGUge31cblxuLy9odHRwczovL2dpdGh1Yi5jb20vYWlycG9ydHloL3Byb3RvbW9ycGhpc21cbmNsYXNzIFByb3RvY29sIHtcbiAgY29uc3RydWN0b3Ioc3BlYykge1xuICAgIHRoaXMucmVnaXN0cnkgPSBuZXcgTWFwKCk7XG4gICAgdGhpcy5mYWxsYmFjayA9IG51bGw7XG5cbiAgICBmb3IgKGxldCBmdW5OYW1lIGluIHNwZWMpIHtcbiAgICAgIHRoaXNbZnVuTmFtZV0gPSBjcmVhdGVGdW4oZnVuTmFtZSkuYmluZCh0aGlzKTtcbiAgICB9XG5cbiAgICBmdW5jdGlvbiBjcmVhdGVGdW4oZnVuTmFtZSkge1xuXG4gICAgICByZXR1cm4gZnVuY3Rpb24gKC4uLmFyZ3MpIHtcbiAgICAgICAgbGV0IHRoaW5nID0gYXJnc1swXTtcbiAgICAgICAgbGV0IGZ1biA9IG51bGw7XG5cbiAgICAgICAgaWYgKE51bWJlci5pc0ludGVnZXIodGhpbmcpICYmIHRoaXMuaGFzSW1wbGVtZW50YXRpb24oSW50ZWdlclR5cGUpKSB7XG4gICAgICAgICAgZnVuID0gdGhpcy5yZWdpc3RyeS5nZXQoSW50ZWdlclR5cGUpW2Z1bk5hbWVdO1xuICAgICAgICB9IGVsc2UgaWYgKHR5cGVvZiB0aGluZyA9PT0gXCJudW1iZXJcIiAmJiAhTnVtYmVyLmlzSW50ZWdlcih0aGluZykgJiYgdGhpcy5oYXNJbXBsZW1lbnRhdGlvbihGbG9hdFR5cGUpKSB7XG4gICAgICAgICAgZnVuID0gdGhpcy5yZWdpc3RyeS5nZXQoRmxvYXRUeXBlKVtmdW5OYW1lXTtcbiAgICAgICAgfSBlbHNlIGlmICh0aGlzLmhhc0ltcGxlbWVudGF0aW9uKHRoaW5nKSkge1xuICAgICAgICAgIGZ1biA9IHRoaXMucmVnaXN0cnkuZ2V0KHRoaW5nLmNvbnN0cnVjdG9yKVtmdW5OYW1lXTtcbiAgICAgICAgfSBlbHNlIGlmICh0aGlzLmZhbGxiYWNrKSB7XG4gICAgICAgICAgZnVuID0gdGhpcy5mYWxsYmFja1tmdW5OYW1lXTtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmIChmdW4gIT0gbnVsbCkge1xuICAgICAgICAgIGxldCByZXR2YWwgPSBmdW4uYXBwbHkodGhpcywgYXJncyk7XG4gICAgICAgICAgcmV0dXJuIHJldHZhbDtcbiAgICAgICAgfVxuXG4gICAgICAgIHRocm93IG5ldyBFcnJvcihcIk5vIGltcGxlbWVudGF0aW9uIGZvdW5kIGZvciBcIiArIHRoaW5nKTtcbiAgICAgIH07XG4gICAgfVxuICB9XG5cbiAgaW1wbGVtZW50YXRpb24odHlwZSwgaW1wbGVtZW50YXRpb24pIHtcbiAgICBpZiAodHlwZSA9PT0gbnVsbCkge1xuICAgICAgdGhpcy5mYWxsYmFjayA9IGltcGxlbWVudGF0aW9uO1xuICAgIH0gZWxzZSB7XG4gICAgICB0aGlzLnJlZ2lzdHJ5LnNldCh0eXBlLCBpbXBsZW1lbnRhdGlvbik7XG4gICAgfVxuICB9XG5cbiAgaGFzSW1wbGVtZW50YXRpb24odGhpbmcpIHtcbiAgICByZXR1cm4gdGhpcy5yZWdpc3RyeS5oYXModGhpbmcuY29uc3RydWN0b3IpO1xuICB9XG59XG5cbmZ1bmN0aW9uIHRsKGxpc3QpIHtcbiAgcmV0dXJuIFNwZWNpYWxGb3Jtcy5saXN0KC4uLmxpc3Quc2xpY2UoMSkpO1xufVxuXG5mdW5jdGlvbiBoZChsaXN0KSB7XG4gIHJldHVybiBsaXN0WzBdO1xufVxuXG5mdW5jdGlvbiBpc19uaWwoeCkge1xuICByZXR1cm4geCA9PT0gbnVsbDtcbn1cblxuZnVuY3Rpb24gaXNfYXRvbSh4KSB7XG4gIHJldHVybiB0eXBlb2YgeCA9PT0gJ3N5bWJvbCc7XG59XG5cbmZ1bmN0aW9uIGlzX2JpbmFyeSh4KSB7XG4gIHJldHVybiB0eXBlb2YgeCA9PT0gJ3N0cmluZycgfHwgeCBpbnN0YW5jZW9mIFN0cmluZztcbn1cblxuZnVuY3Rpb24gaXNfYm9vbGVhbih4KSB7XG4gIHJldHVybiB0eXBlb2YgeCA9PT0gJ2Jvb2xlYW4nIHx8IHggaW5zdGFuY2VvZiBCb29sZWFuO1xufVxuXG5mdW5jdGlvbiBpc19mdW5jdGlvbih4LCBhcml0eSA9IC0xKSB7XG4gIHJldHVybiB0eXBlb2YgeCA9PT0gJ2Z1bmN0aW9uJyB8fCB4IGluc3RhbmNlb2YgRnVuY3Rpb247XG59XG5cbmZ1bmN0aW9uIGlzX2Zsb2F0KHgpIHtcbiAgcmV0dXJuIGlzX251bWJlcih4KSAmJiAhTnVtYmVyLmlzSW50ZWdlcih4KTtcbn1cblxuZnVuY3Rpb24gaXNfaW50ZWdlcih4KSB7XG4gIHJldHVybiBOdW1iZXIuaXNJbnRlZ2VyKHgpO1xufVxuXG5mdW5jdGlvbiBpc19saXN0KHgpIHtcbiAgcmV0dXJuIHggaW5zdGFuY2VvZiBBcnJheTtcbn1cblxuZnVuY3Rpb24gaXNfbWFwKHgpIHtcbiAgcmV0dXJuIHR5cGVvZiB4ID09PSAnb2JqZWN0JyB8fCB4IGluc3RhbmNlb2YgT2JqZWN0O1xufVxuXG5mdW5jdGlvbiBpc19udW1iZXIoeCkge1xuICByZXR1cm4gdHlwZW9mIHggPT09ICdudW1iZXInO1xufVxuXG5mdW5jdGlvbiBpc190dXBsZSh4KSB7XG4gIHJldHVybiB4IGluc3RhbmNlb2YgVHVwbGU7XG59XG5cbmZ1bmN0aW9uIF9sZW5ndGgoeCkge1xuICByZXR1cm4geC5sZW5ndGg7XG59XG5cbmZ1bmN0aW9uIGlzX3BpZCh4KSB7XG4gIHJldHVybiB4IGluc3RhbmNlb2YgUElEO1xufVxuXG5mdW5jdGlvbiBpc19wb3J0KHgpIHtcbiAgcmV0dXJuIGZhbHNlO1xufVxuXG5mdW5jdGlvbiBpc19yZWZlcmVuY2UoeCkge1xuICByZXR1cm4gZmFsc2U7XG59XG5cbmZ1bmN0aW9uIGlzX2JpdHN0cmluZyh4KSB7XG4gIHJldHVybiBpc19iaW5hcnkoeCkgfHwgeCBpbnN0YW5jZW9mIEJpdFN0cmluZztcbn1cblxuZnVuY3Rpb24gX19pbl9fKGxlZnQsIHJpZ2h0KSB7XG4gIGZvciAobGV0IHggb2YgcmlnaHQpIHtcbiAgICBpZiAobWF0Y2hfX3FtYXJrX18obGVmdCwgeCkpIHtcbiAgICAgIHJldHVybiB0cnVlO1xuICAgIH1cbiAgfVxuXG4gIHJldHVybiBmYWxzZTtcbn1cblxuZnVuY3Rpb24gYWJzKG51bWJlcikge1xuICByZXR1cm4gTWF0aC5hYnMobnVtYmVyKTtcbn1cblxuZnVuY3Rpb24gcm91bmQobnVtYmVyKSB7XG4gIHJldHVybiBNYXRoLnJvdW5kKG51bWJlcik7XG59XG5cbmZ1bmN0aW9uIGVsZW0odHVwbGUsIGluZGV4KSB7XG4gIGlmIChpc19saXN0KHR1cGxlKSkge1xuICAgIHJldHVybiB0dXBsZVtpbmRleF07XG4gIH1cblxuICByZXR1cm4gdHVwbGUuZ2V0KGluZGV4KTtcbn1cblxuZnVuY3Rpb24gcmVtKGxlZnQsIHJpZ2h0KSB7XG4gIHJldHVybiBsZWZ0ICUgcmlnaHQ7XG59XG5cbmZ1bmN0aW9uIGRpdihsZWZ0LCByaWdodCkge1xuICByZXR1cm4gbGVmdCAvIHJpZ2h0O1xufVxuXG5mdW5jdGlvbiBhbmQobGVmdCwgcmlnaHQpIHtcbiAgcmV0dXJuIGxlZnQgJiYgcmlnaHQ7XG59XG5cbmZ1bmN0aW9uIG9yKGxlZnQsIHJpZ2h0KSB7XG4gIHJldHVybiBsZWZ0IHx8IHJpZ2h0O1xufVxuXG5mdW5jdGlvbiBub3QoYXJnKSB7XG4gIHJldHVybiAhYXJnO1xufVxuXG5mdW5jdGlvbiBhcHBseSguLi5hcmdzKSB7XG4gIGlmIChhcmdzLmxlbmd0aCA9PT0gMykge1xuICAgIGxldCBtb2QgPSBhcmdzWzBdO1xuICAgIGxldCBmdW5jID0gYXJnc1sxXTtcbiAgICBsZXQgZnVuY19hcmdzID0gYXJnc1syXTtcbiAgICByZXR1cm4gbW9kW2Z1bmNdLmFwcGx5KG51bGwsIGZ1bmNfYXJncyk7XG4gIH0gZWxzZSB7XG4gICAgbGV0IGZ1bmMgPSBhcmdzWzBdO1xuICAgIGxldCBmdW5jX2FyZ3MgPSBhcmdzWzFdO1xuXG4gICAgcmV0dXJuIGZ1bmMuYXBwbHkobnVsbCwgZnVuY19hcmdzKTtcbiAgfVxufVxuXG5mdW5jdGlvbiB0b19zdHJpbmcoYXJnKSB7XG4gIGlmIChpc190dXBsZShhcmcpKSB7XG4gICAgcmV0dXJuIFR1cGxlLnRvX3N0cmluZyhhcmcpO1xuICB9XG5cbiAgcmV0dXJuIGFyZy50b1N0cmluZygpO1xufVxuXG5mdW5jdGlvbiBtYXRjaF9fcW1hcmtfXyhwYXR0ZXJuLCBleHByLCBndWFyZCA9ICgpID0+IHRydWUpIHtcbiAgcmV0dXJuIF9QYXR0ZXJucy5tYXRjaF9ub190aHJvdyhwYXR0ZXJuLCBleHByLCBndWFyZCkgIT0gbnVsbDtcbn1cblxuZnVuY3Rpb24gZGVmc3RydWN0KGRlZmF1bHRzKSB7XG4gIHJldHVybiBjbGFzcyB7XG4gICAgY29uc3RydWN0b3IodXBkYXRlID0ge30pIHtcbiAgICAgIGxldCB0aGVfdmFsdWVzID0gT2JqZWN0LmFzc2lnbihkZWZhdWx0cywgdXBkYXRlKTtcbiAgICAgIE9iamVjdC5hc3NpZ24odGhpcywgdGhlX3ZhbHVlcyk7XG4gICAgfVxuXG4gICAgc3RhdGljIGNyZWF0ZSh1cGRhdGVzID0ge30pIHtcbiAgICAgIGxldCB4ID0gbmV3IHRoaXModXBkYXRlcyk7XG4gICAgICByZXR1cm4gT2JqZWN0LmZyZWV6ZSh4KTtcbiAgICB9XG4gIH07XG59XG5cbmZ1bmN0aW9uIGRlZmV4Y2VwdGlvbihkZWZhdWx0cykge1xuICByZXR1cm4gY2xhc3MgZXh0ZW5kcyBFcnJvciB7XG4gICAgY29uc3RydWN0b3IodXBkYXRlID0ge30pIHtcbiAgICAgIGxldCBtZXNzYWdlID0gdXBkYXRlLm1lc3NhZ2UgfHwgJyc7XG4gICAgICBzdXBlcihtZXNzYWdlKTtcblxuICAgICAgbGV0IHRoZV92YWx1ZXMgPSBPYmplY3QuYXNzaWduKGRlZmF1bHRzLCB1cGRhdGUpO1xuICAgICAgT2JqZWN0LmFzc2lnbih0aGlzLCB0aGVfdmFsdWVzKTtcblxuICAgICAgdGhpcy5uYW1lID0gdGhpcy5jb25zdHJ1Y3Rvci5uYW1lO1xuICAgICAgdGhpcy5tZXNzYWdlID0gbWVzc2FnZTtcbiAgICAgIHRoaXNbU3BlY2lhbEZvcm1zLmF0b20oJ19fZXhjZXB0aW9uX18nKV0gPSB0cnVlO1xuICAgICAgRXJyb3IuY2FwdHVyZVN0YWNrVHJhY2UodGhpcywgdGhpcy5jb25zdHJ1Y3Rvci5uYW1lKTtcbiAgICB9XG5cbiAgICBzdGF0aWMgY3JlYXRlKHVwZGF0ZXMgPSB7fSkge1xuICAgICAgbGV0IHggPSBuZXcgdGhpcyh1cGRhdGVzKTtcbiAgICAgIHJldHVybiBPYmplY3QuZnJlZXplKHgpO1xuICAgIH1cbiAgfTtcbn1cblxuZnVuY3Rpb24gZGVmcHJvdG9jb2woc3BlYykge1xuICByZXR1cm4gbmV3IFByb3RvY29sKHNwZWMpO1xufVxuXG5mdW5jdGlvbiBkZWZpbXBsKHByb3RvY29sLCB0eXBlLCBpbXBsKSB7XG4gIHByb3RvY29sLmltcGxlbWVudGF0aW9uKHR5cGUsIGltcGwpO1xufVxuXG52YXIgS2VybmVsID0ge1xuICBTcGVjaWFsRm9ybXMsXG4gIHRsLFxuICBoZCxcbiAgaXNfbmlsLFxuICBpc19hdG9tLFxuICBpc19iaW5hcnksXG4gIGlzX2Jvb2xlYW4sXG4gIGlzX2Z1bmN0aW9uLFxuICBpc19mbG9hdCxcbiAgaXNfaW50ZWdlcixcbiAgaXNfbGlzdCxcbiAgaXNfbWFwLFxuICBpc19udW1iZXIsXG4gIGlzX3R1cGxlLFxuICBsZW5ndGg6IF9sZW5ndGgsXG4gIGlzX3BpZCxcbiAgaXNfcG9ydCxcbiAgaXNfcmVmZXJlbmNlLFxuICBpc19iaXRzdHJpbmcsXG4gIGluOiBfX2luX18sXG4gIGFicyxcbiAgcm91bmQsXG4gIGVsZW0sXG4gIHJlbSxcbiAgZGl2LFxuICBhbmQsXG4gIG9yLFxuICBub3QsXG4gIGFwcGx5LFxuICB0b19zdHJpbmcsXG4gIG1hdGNoX19xbWFya19fLFxuICBkZWZzdHJ1Y3QsXG4gIGRlZnByb3RvY29sLFxuICBkZWZpbXBsXG59O1xuXG5sZXQgRW51bSA9IHtcblxuICBhbGxfX3FtYXJrX186IGZ1bmN0aW9uIChjb2xsZWN0aW9uLCBmdW4gPSB4ID0+IHgpIHtcbiAgICBmb3IgKGxldCBlbGVtIG9mIGNvbGxlY3Rpb24pIHtcbiAgICAgIGlmICghZnVuKGVsZW0pKSB7XG4gICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICByZXR1cm4gdHJ1ZTtcbiAgfSxcblxuICBhbnlfX3FtYXJrX186IGZ1bmN0aW9uIChjb2xsZWN0aW9uLCBmdW4gPSB4ID0+IHgpIHtcbiAgICBmb3IgKGxldCBlbGVtIG9mIGNvbGxlY3Rpb24pIHtcbiAgICAgIGlmIChmdW4oZWxlbSkpIHtcbiAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICB9XG4gICAgfVxuXG4gICAgcmV0dXJuIGZhbHNlO1xuICB9LFxuXG4gIGF0OiBmdW5jdGlvbiAoY29sbGVjdGlvbiwgbiwgdGhlX2RlZmF1bHQgPSBudWxsKSB7XG4gICAgaWYgKG4gPiB0aGlzLmNvdW50KGNvbGxlY3Rpb24pIHx8IG4gPCAwKSB7XG4gICAgICByZXR1cm4gdGhlX2RlZmF1bHQ7XG4gICAgfVxuXG4gICAgcmV0dXJuIGNvbGxlY3Rpb25bbl07XG4gIH0sXG5cbiAgY29uY2F0OiBmdW5jdGlvbiAoLi4uZW51bWFibGVzKSB7XG4gICAgcmV0dXJuIGVudW1hYmxlc1swXS5jb25jYXQoZW51bWFibGVzWzFdKTtcbiAgfSxcblxuICBjb3VudDogZnVuY3Rpb24gKGNvbGxlY3Rpb24sIGZ1biA9IG51bGwpIHtcbiAgICBpZiAoZnVuID09IG51bGwpIHtcbiAgICAgIHJldHVybiBjb2xsZWN0aW9uLmxlbmd0aDtcbiAgICB9IGVsc2Uge1xuICAgICAgcmV0dXJuIGNvbGxlY3Rpb24uZmlsdGVyKGZ1bikubGVuZ3RoO1xuICAgIH1cbiAgfSxcblxuICBkcm9wOiBmdW5jdGlvbiAoY29sbGVjdGlvbiwgY291bnQpIHtcbiAgICByZXR1cm4gY29sbGVjdGlvbi5zbGljZShjb3VudCk7XG4gIH0sXG5cbiAgZHJvcF93aGlsZTogZnVuY3Rpb24gKGNvbGxlY3Rpb24sIGZ1bikge1xuICAgIGxldCBjb3VudCA9IDA7XG5cbiAgICBmb3IgKGxldCBlbGVtIG9mIGNvbGxlY3Rpb24pIHtcbiAgICAgIGlmIChmdW4oZWxlbSkpIHtcbiAgICAgICAgY291bnQgPSBjb3VudCArIDE7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBicmVhaztcbiAgICAgIH1cbiAgICB9XG5cbiAgICByZXR1cm4gY29sbGVjdGlvbi5zbGljZShjb3VudCk7XG4gIH0sXG5cbiAgZWFjaDogZnVuY3Rpb24gKGNvbGxlY3Rpb24sIGZ1bikge1xuICAgIGZvciAobGV0IGVsZW0gb2YgY29sbGVjdGlvbikge1xuICAgICAgZnVuKGVsZW0pO1xuICAgIH1cbiAgfSxcblxuICBlbXB0eV9fcW1hcmtfXzogZnVuY3Rpb24gKGNvbGxlY3Rpb24pIHtcbiAgICByZXR1cm4gY29sbGVjdGlvbi5sZW5ndGggPT09IDA7XG4gIH0sXG5cbiAgZmV0Y2g6IGZ1bmN0aW9uIChjb2xsZWN0aW9uLCBuKSB7XG4gICAgaWYgKEtlcm5lbC5pc19saXN0KGNvbGxlY3Rpb24pKSB7XG4gICAgICBpZiAobiA8IHRoaXMuY291bnQoY29sbGVjdGlvbikgJiYgbiA+PSAwKSB7XG4gICAgICAgIHJldHVybiBLZXJuZWwuU3BlY2lhbEZvcm1zLnR1cGxlKEtlcm5lbC5TcGVjaWFsRm9ybXMuYXRvbShcIm9rXCIpLCBjb2xsZWN0aW9uW25dKTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHJldHVybiBLZXJuZWwuU3BlY2lhbEZvcm1zLmF0b20oXCJlcnJvclwiKTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICB0aHJvdyBuZXcgRXJyb3IoXCJjb2xsZWN0aW9uIGlzIG5vdCBhbiBFbnVtZXJhYmxlXCIpO1xuICB9LFxuXG4gIGZldGNoX19lbWFya19fOiBmdW5jdGlvbiAoY29sbGVjdGlvbiwgbikge1xuICAgIGlmIChLZXJuZWwuaXNfbGlzdChjb2xsZWN0aW9uKSkge1xuICAgICAgaWYgKG4gPCB0aGlzLmNvdW50KGNvbGxlY3Rpb24pICYmIG4gPj0gMCkge1xuICAgICAgICByZXR1cm4gY29sbGVjdGlvbltuXTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcihcIm91dCBvZiBib3VuZHMgZXJyb3JcIik7XG4gICAgICB9XG4gICAgfVxuXG4gICAgdGhyb3cgbmV3IEVycm9yKFwiY29sbGVjdGlvbiBpcyBub3QgYW4gRW51bWVyYWJsZVwiKTtcbiAgfSxcblxuICBmaWx0ZXI6IGZ1bmN0aW9uIChjb2xsZWN0aW9uLCBmdW4pIHtcbiAgICBsZXQgcmVzdWx0ID0gW107XG5cbiAgICBmb3IgKGxldCBlbGVtIG9mIGNvbGxlY3Rpb24pIHtcbiAgICAgIGlmIChmdW4oZWxlbSkpIHtcbiAgICAgICAgcmVzdWx0LnB1c2goZWxlbSk7XG4gICAgICB9XG4gICAgfVxuXG4gICAgcmV0dXJuIHJlc3VsdDtcbiAgfSxcblxuICBmaWx0ZXJfbWFwOiBmdW5jdGlvbiAoY29sbGVjdGlvbiwgZmlsdGVyLCBtYXBwZXIpIHtcbiAgICByZXR1cm4gRW51bS5tYXAoRW51bS5maWx0ZXIoY29sbGVjdGlvbiwgZmlsdGVyKSwgbWFwcGVyKTtcbiAgfSxcblxuICBmaW5kOiBmdW5jdGlvbiAoY29sbGVjdGlvbiwgaWZfbm9uZSA9IG51bGwsIGZ1bikge1xuICAgIGZvciAobGV0IGVsZW0gb2YgY29sbGVjdGlvbikge1xuICAgICAgaWYgKGZ1bihlbGVtKSkge1xuICAgICAgICByZXR1cm4gZWxlbTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICByZXR1cm4gaWZfbm9uZTtcbiAgfSxcblxuICBpbnRvOiBmdW5jdGlvbiAoY29sbGVjdGlvbiwgbGlzdCkge1xuICAgIHJldHVybiBsaXN0LmNvbmNhdChjb2xsZWN0aW9uKTtcbiAgfSxcblxuICBtYXA6IGZ1bmN0aW9uIChjb2xsZWN0aW9uLCBmdW4pIHtcbiAgICBsZXQgcmVzdWx0ID0gW107XG5cbiAgICBmb3IgKGxldCBlbGVtIG9mIGNvbGxlY3Rpb24pIHtcbiAgICAgIHJlc3VsdC5wdXNoKGZ1bihlbGVtKSk7XG4gICAgfVxuXG4gICAgcmV0dXJuIHJlc3VsdDtcbiAgfSxcblxuICBtYXBfcmVkdWNlOiBmdW5jdGlvbiAoY29sbGVjdGlvbiwgYWNjLCBmdW4pIHtcbiAgICBsZXQgbWFwcGVkID0gS2VybmVsLlNwZWNpYWxGb3Jtcy5saXN0KCk7XG4gICAgbGV0IHRoZV9hY2MgPSBhY2M7XG5cbiAgICBmb3IgKHZhciBpID0gMDsgaSA8IHRoaXMuY291bnQoY29sbGVjdGlvbik7IGkrKykge1xuICAgICAgbGV0IHR1cGxlID0gZnVuKGNvbGxlY3Rpb25baV0sIHRoZV9hY2MpO1xuXG4gICAgICB0aGVfYWNjID0gS2VybmVsLmVsZW0odHVwbGUsIDEpO1xuICAgICAgbWFwcGVkID0gS2VybmVsLlNwZWNpYWxGb3Jtcy5saXN0KC4uLm1hcHBlZC5jb25jYXQoW0tlcm5lbC5lbGVtKHR1cGxlLCAwKV0pKTtcbiAgICB9XG5cbiAgICByZXR1cm4gS2VybmVsLlNwZWNpYWxGb3Jtcy50dXBsZShtYXBwZWQsIHRoZV9hY2MpO1xuICB9LFxuXG4gIG1lbWJlcjogZnVuY3Rpb24gKGNvbGxlY3Rpb24sIHZhbHVlKSB7XG4gICAgcmV0dXJuIGNvbGxlY3Rpb24uaW5jbHVkZXModmFsdWUpO1xuICB9LFxuXG4gIHJlZHVjZTogZnVuY3Rpb24gKGNvbGxlY3Rpb24sIGFjYywgZnVuKSB7XG4gICAgbGV0IHRoZV9hY2MgPSBhY2M7XG5cbiAgICBmb3IgKHZhciBpID0gMDsgaSA8IHRoaXMuY291bnQoY29sbGVjdGlvbik7IGkrKykge1xuICAgICAgbGV0IHR1cGxlID0gZnVuKGNvbGxlY3Rpb25baV0sIHRoZV9hY2MpO1xuXG4gICAgICB0aGVfYWNjID0gS2VybmVsLmVsZW0odHVwbGUsIDEpO1xuICAgIH1cblxuICAgIHJldHVybiB0aGVfYWNjO1xuICB9LFxuXG4gIHRha2U6IGZ1bmN0aW9uIChjb2xsZWN0aW9uLCBjb3VudCkge1xuICAgIHJldHVybiBjb2xsZWN0aW9uLnNsaWNlKDAsIGNvdW50KTtcbiAgfSxcblxuICB0YWtlX2V2ZXJ5OiBmdW5jdGlvbiAoY29sbGVjdGlvbiwgbnRoKSB7XG4gICAgbGV0IHJlc3VsdCA9IFtdO1xuICAgIGxldCBpbmRleCA9IDA7XG5cbiAgICBmb3IgKGxldCBlbGVtIG9mIGNvbGxlY3Rpb24pIHtcbiAgICAgIGlmIChpbmRleCAlIG50aCA9PT0gMCkge1xuICAgICAgICByZXN1bHQucHVzaChlbGVtKTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICByZXR1cm4gS2VybmVsLlNwZWNpYWxGb3Jtcy5saXN0KC4uLnJlc3VsdCk7XG4gIH0sXG5cbiAgdGFrZV93aGlsZTogZnVuY3Rpb24gKGNvbGxlY3Rpb24sIGZ1bikge1xuICAgIGxldCBjb3VudCA9IDA7XG5cbiAgICBmb3IgKGxldCBlbGVtIG9mIGNvbGxlY3Rpb24pIHtcbiAgICAgIGlmIChmdW4oZWxlbSkpIHtcbiAgICAgICAgY291bnQgPSBjb3VudCArIDE7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBicmVhaztcbiAgICAgIH1cbiAgICB9XG5cbiAgICByZXR1cm4gY29sbGVjdGlvbi5zbGljZSgwLCBjb3VudCk7XG4gIH0sXG5cbiAgdG9fbGlzdDogZnVuY3Rpb24gKGNvbGxlY3Rpb24pIHtcbiAgICByZXR1cm4gY29sbGVjdGlvbjtcbiAgfVxufTtcblxubGV0IEF0b20gPSB7fTtcblxuQXRvbS50b19zdHJpbmcgPSBmdW5jdGlvbiAoYXRvbSkge1xuICByZXR1cm4gU3ltYm9sLmtleUZvcihhdG9tKTtcbn07XG5cbkF0b20udG9fY2hhcl9saXN0ID0gZnVuY3Rpb24gKGF0b20pIHtcbiAgcmV0dXJuIEF0b20udG9fc3RyaW5nKGF0b20pLnNwbGl0KCcnKTtcbn07XG5cbmxldCBJbnRlZ2VyID0ge1xuXG4gIGlzX2V2ZW46IGZ1bmN0aW9uIChuKSB7XG4gICAgcmV0dXJuIG4gJSAyID09PSAwO1xuICB9LFxuXG4gIGlzX29kZDogZnVuY3Rpb24gKG4pIHtcbiAgICByZXR1cm4gbiAlIDIgIT09IDA7XG4gIH0sXG5cbiAgcGFyc2U6IGZ1bmN0aW9uIChiaW4pIHtcbiAgICBsZXQgcmVzdWx0ID0gcGFyc2VJbnQoYmluKTtcblxuICAgIGlmIChpc05hTihyZXN1bHQpKSB7XG4gICAgICByZXR1cm4gS2VybmVsLlNwZWNpYWxGb3Jtcy5hdG9tKFwiZXJyb3JcIik7XG4gICAgfVxuXG4gICAgbGV0IGluZGV4T2ZEb3QgPSBiaW4uaW5kZXhPZihcIi5cIik7XG5cbiAgICBpZiAoaW5kZXhPZkRvdCA+PSAwKSB7XG4gICAgICByZXR1cm4gS2VybmVsLlNwZWNpYWxGb3Jtcy50dXBsZShyZXN1bHQsIGJpbi5zdWJzdHJpbmcoaW5kZXhPZkRvdCkpO1xuICAgIH1cblxuICAgIHJldHVybiBLZXJuZWwuU3BlY2lhbEZvcm1zLnR1cGxlKHJlc3VsdCwgXCJcIik7XG4gIH0sXG5cbiAgdG9fY2hhcl9saXN0OiBmdW5jdGlvbiAobnVtYmVyLCBiYXNlID0gMTApIHtcbiAgICByZXR1cm4gbnVtYmVyLnRvU3RyaW5nKGJhc2UpLnNwbGl0KFwiXCIpO1xuICB9LFxuXG4gIHRvX3N0cmluZzogZnVuY3Rpb24gKG51bWJlciwgYmFzZSA9IDEwKSB7XG4gICAgcmV0dXJuIG51bWJlci50b1N0cmluZyhiYXNlKTtcbiAgfVxufTtcblxubGV0IF9DaGFycyA9IEtlcm5lbC5kZWZwcm90b2NvbCh7XG4gIHRvX3N0cmluZzogZnVuY3Rpb24gKHRoaW5nKSB7fVxufSk7XG5cbktlcm5lbC5kZWZpbXBsKF9DaGFycywgQml0U3RyaW5nLCB7XG4gIHRvX3N0cmluZzogZnVuY3Rpb24gKHRoaW5nKSB7XG4gICAgaWYgKEtlcm5lbC5pc19iaW5hcnkodGhpbmcpKSB7XG4gICAgICByZXR1cm4gdGhpbmc7XG4gICAgfVxuXG4gICAgcmV0dXJuIHRoaW5nLnRvU3RyaW5nKCk7XG4gIH1cbn0pO1xuXG5LZXJuZWwuZGVmaW1wbChfQ2hhcnMsIFN5bWJvbCwge1xuICB0b19zdHJpbmc6IGZ1bmN0aW9uICh0aGluZykge1xuICAgIGlmIChuaWwpIHtcbiAgICAgIHJldHVybiBcIlwiO1xuICAgIH1cblxuICAgIHJldHVybiBBdG9tLnRvX3N0cmluZyh0aGluZyk7XG4gIH1cbn0pO1xuXG5LZXJuZWwuZGVmaW1wbChfQ2hhcnMsIEludGVnZXJUeXBlLCB7XG4gIHRvX3N0cmluZzogZnVuY3Rpb24gKHRoaW5nKSB7XG4gICAgcmV0dXJuIEludGVnZXIudG9fc3RyaW5nKHRoaW5nKTtcbiAgfVxufSk7XG5cbktlcm5lbC5kZWZpbXBsKF9DaGFycywgRmxvYXRUeXBlLCB7XG4gIHRvX3N0cmluZzogZnVuY3Rpb24gKHRoaW5nKSB7XG4gICAgcmV0dXJuIHRoaW5nLnRvU3RyaW5nO1xuICB9XG59KTtcblxuS2VybmVsLmRlZmltcGwoX0NoYXJzLCBBcnJheSwge1xuICB0b19zdHJpbmc6IGZ1bmN0aW9uICh0aGluZykge1xuICAgIHJldHVybiB0aGluZy50b1N0cmluZygpO1xuICB9XG59KTtcblxuS2VybmVsLmRlZmltcGwoX0NoYXJzLCBUdXBsZSwge1xuICB0b19zdHJpbmc6IGZ1bmN0aW9uICh0aGluZykge1xuICAgIHJldHVybiBUdXBsZS50b19zdHJpbmcodGhpbmcpO1xuICB9XG59KTtcblxuS2VybmVsLmRlZmltcGwoX0NoYXJzLCBudWxsLCB7XG4gIHRvX3N0cmluZzogZnVuY3Rpb24gKHRoaW5nKSB7XG4gICAgcmV0dXJuIHRoaW5nLnRvU3RyaW5nKCk7XG4gIH1cbn0pO1xuXG5mdW5jdGlvbiB0b19hdG9tKHN0cmluZykge1xuICByZXR1cm4gU3ltYm9sLmZvcihzdHJpbmcpO1xufVxuXG5mdW5jdGlvbiB0b19leGlzdGluZ19hdG9tKHN0cmluZykge1xuICByZXR1cm4gU3ltYm9sLmZvcihzdHJpbmcpO1xufVxuXG5mdW5jdGlvbiB0b19jaGFyX2xpc3Qoc3RyaW5nKSB7XG4gIHJldHVybiBzdHJpbmcuc3BsaXQoJycpO1xufVxuXG5mdW5jdGlvbiB0b19mbG9hdChzdHJpbmcpIHtcbiAgcmV0dXJuIHBhcnNlRmxvYXQoc3RyaW5nKTtcbn1cblxuZnVuY3Rpb24gdG9faW50ZWdlcihzdHJpbmcsIGJhc2UgPSAxMCkge1xuICByZXR1cm4gcGFyc2VJbnQoc3RyaW5nLCBiYXNlKTtcbn1cblxuZnVuY3Rpb24gdXBjYXNlKGJpbmFyeSkge1xuICByZXR1cm4gYmluYXJ5LnRvVXBwZXJDYXNlKCk7XG59XG5cbmZ1bmN0aW9uIGRvd25jYXNlKGJpbmFyeSkge1xuICByZXR1cm4gYmluYXJ5LnRvTG93ZXJDYXNlKCk7XG59XG5cbmZ1bmN0aW9uIGF0KHN0cmluZywgcG9zaXRpb24pIHtcbiAgaWYgKHBvc2l0aW9uID4gc3RyaW5nLmxlbmd0aCAtIDEpIHtcbiAgICByZXR1cm4gbnVsbDtcbiAgfVxuXG4gIHJldHVybiBzdHJpbmdbcG9zaXRpb25dO1xufVxuXG5mdW5jdGlvbiBjYXBpdGFsaXplKHN0cmluZykge1xuICBsZXQgcmV0dXJuU3RyaW5nID0gJyc7XG5cbiAgZm9yIChsZXQgaSA9IDA7IGkgPCBzdHJpbmcubGVuZ3RoOyBpKyspIHtcbiAgICBpZiAoaSA9PT0gMCkge1xuICAgICAgcmV0dXJuU3RyaW5nID0gcmV0dXJuU3RyaW5nICsgc3RyaW5nW2ldLnRvVXBwZXJDYXNlKCk7XG4gICAgfSBlbHNlIHtcbiAgICAgIHJldHVyblN0cmluZyA9IHJldHVyblN0cmluZyArIHN0cmluZ1tpXS50b0xvd2VyQ2FzZSgpO1xuICAgIH1cbiAgfVxuXG4gIHJldHVybiByZXR1cm5TdHJpbmc7XG59XG5cbmZ1bmN0aW9uIGNvZGVwb2ludHMoc3RyaW5nKSB7XG4gIHJldHVybiB0b19jaGFyX2xpc3Qoc3RyaW5nKS5tYXAoZnVuY3Rpb24gKGMpIHtcbiAgICByZXR1cm4gYy5jb2RlUG9pbnRBdCgwKTtcbiAgfSk7XG59XG5cbmZ1bmN0aW9uIGNvbnRhaW5zX19xbV9fKHN0cmluZywgY29udGFpbnMpIHtcbiAgaWYgKEFycmF5LmlzQXJyYXkoY29udGFpbnMpKSB7XG4gICAgcmV0dXJuIGNvbnRhaW5zLnNvbWUoZnVuY3Rpb24gKHMpIHtcbiAgICAgIHJldHVybiBzdHJpbmcuaW5kZXhPZihzKSA+IC0xO1xuICAgIH0pO1xuICB9XG5cbiAgcmV0dXJuIHN0cmluZy5pbmRleE9mKGNvbnRhaW5zKSA+IC0xO1xufVxuXG5mdW5jdGlvbiBkdXBsaWNhdGUoc3ViamVjdCwgbikge1xuICByZXR1cm4gc3ViamVjdC5yZXBlYXQobik7XG59XG5cbmZ1bmN0aW9uIGVuZHNfd2l0aF9fcW1fXyhzdHJpbmcsIHN1ZmZpeGVzKSB7XG4gIGlmIChBcnJheS5pc0FycmF5KHN1ZmZpeGVzKSkge1xuICAgIHJldHVybiBzdWZmaXhlcy5zb21lKGZ1bmN0aW9uIChzKSB7XG4gICAgICByZXR1cm4gc3RyaW5nLmVuZHNXaXRoKHMpO1xuICAgIH0pO1xuICB9XG5cbiAgcmV0dXJuIHN0cmluZy5lbmRzV2l0aChzdWZmaXhlcyk7XG59XG5cbmZ1bmN0aW9uIGZpcnN0KHN0cmluZykge1xuICBpZiAoIXN0cmluZykge1xuICAgIHJldHVybiBudWxsO1xuICB9XG5cbiAgcmV0dXJuIHN0cmluZ1swXTtcbn1cblxuZnVuY3Rpb24gZ3JhcGhlbWVzKHN0cmluZykge1xuICByZXR1cm4gc3RyaW5nLnNwbGl0KCcnKTtcbn1cblxuZnVuY3Rpb24gbGFzdChzdHJpbmcpIHtcbiAgaWYgKCFzdHJpbmcpIHtcbiAgICByZXR1cm4gbnVsbDtcbiAgfVxuXG4gIHJldHVybiBzdHJpbmdbc3RyaW5nLmxlbmd0aCAtIDFdO1xufVxuXG5mdW5jdGlvbiBsZW5ndGgoc3RyaW5nKSB7XG4gIHJldHVybiBzdHJpbmcubGVuZ3RoO1xufVxuXG5mdW5jdGlvbiBtYXRjaF9fcW1fXyhzdHJpbmcsIHJlZ2V4KSB7XG4gIHJldHVybiBzdHJpbmcubWF0Y2gocmVnZXgpICE9IG51bGw7XG59XG5cbmZ1bmN0aW9uIG5leHRfY29kZXBvaW50KHN0cmluZykge1xuICBpZiAoIXN0cmluZyB8fCBzdHJpbmcgPT09ICcnKSB7XG4gICAgcmV0dXJuIG51bGw7XG4gIH1cblxuICByZXR1cm4gS2VybmVsLlNwZWNpYWxGb3Jtcy50dXBsZShzdHJpbmdbMF0uY29kZVBvaW50QXQoMCksIHN0cmluZy5zdWJzdHIoMSkpO1xufVxuXG5mdW5jdGlvbiBuZXh0X2dyYXBoZW1lKHN0cmluZykge1xuICBpZiAoIXN0cmluZyB8fCBzdHJpbmcgPT09ICcnKSB7XG4gICAgcmV0dXJuIG51bGw7XG4gIH1cblxuICByZXR1cm4gS2VybmVsLlNwZWNpYWxGb3Jtcy50dXBsZShzdHJpbmdbMF0sIHN0cmluZy5zdWJzdHIoMSkpO1xufVxuXG5mdW5jdGlvbiByZXZlcnNlKHN0cmluZykge1xuICBsZXQgcmV0dXJuVmFsdWUgPSAnJztcblxuICBmb3IgKHZhciBpID0gc3RyaW5nLmxlbmd0aCAtIDE7IGkgPj0gMDsgaS0tKSB7XG4gICAgcmV0dXJuVmFsdWUgPSByZXR1cm5WYWx1ZSArIHN0cmluZ1tpXTtcbiAgfTtcblxuICByZXR1cm4gcmV0dXJuVmFsdWU7XG59XG5cbmZ1bmN0aW9uIF9zcGxpdChzdHJpbmcpIHtcbiAgcmV0dXJuIHN0cmluZy5zcGxpdCgpO1xufVxuXG5mdW5jdGlvbiBzdGFydHNfd2l0aF9fcW1fXyhzdHJpbmcsIHByZWZpeGVzKSB7XG4gIGlmIChBcnJheS5pc0FycmF5KHByZWZpeGVzKSkge1xuICAgIHJldHVybiBwcmVmaXhlcy5zb21lKGZ1bmN0aW9uIChzKSB7XG4gICAgICByZXR1cm4gc3RyaW5nLnN0YXJ0c1dpdGgocyk7XG4gICAgfSk7XG4gIH1cblxuICByZXR1cm4gc3RyaW5nLnN0YXJ0c1dpdGgocHJlZml4ZXMpO1xufVxuXG5mdW5jdGlvbiB2YWxpZF9jaGFyYWN0ZXJfX3FtX18oY29kZXBvaW50KSB7XG4gIHRyeSB7XG4gICAgcmV0dXJuIFN0cmluZy5mcm9tQ29kZVBvaW50KGNvZGVwb2ludCkgIT0gbnVsbDtcbiAgfSBjYXRjaCAoZSkge1xuICAgIHJldHVybiBmYWxzZTtcbiAgfVxufVxuXG52YXIgX1N0cmluZyA9IHtcbiAgYXQsXG4gIGNhcGl0YWxpemUsXG4gIGNvZGVwb2ludHMsXG4gIGNvbnRhaW5zX19xbV9fLFxuICBkb3duY2FzZSxcbiAgZHVwbGljYXRlLFxuICBlbmRzX3dpdGhfX3FtX18sXG4gIGZpcnN0LFxuICBncmFwaGVtZXMsXG4gIGxhc3QsXG4gIGxlbmd0aCxcbiAgbWF0Y2hfX3FtX18sXG4gIG5leHRfY29kZXBvaW50LFxuICBuZXh0X2dyYXBoZW1lLFxuICByZXZlcnNlLFxuICBzcGxpdDogX3NwbGl0LFxuICBzdGFydHNfd2l0aF9fcW1fXyxcbiAgdG9fYXRvbSxcbiAgdG9fY2hhcl9saXN0LFxuICB0b19leGlzdGluZ19hdG9tLFxuICB0b19mbG9hdCxcbiAgdG9faW50ZWdlcixcbiAgdXBjYXNlLFxuICB2YWxpZF9jaGFyYWN0ZXJfX3FtX18sXG4gIENoYXJzOiBfQ2hhcnNcbn07XG5cbmxldCBDaGFycyA9IEtlcm5lbC5kZWZwcm90b2NvbCh7XG4gIHRvX2NoYXJfbGlzdDogZnVuY3Rpb24gKHRoaW5nKSB7fVxufSk7XG5cbktlcm5lbC5kZWZpbXBsKENoYXJzLCBLZXJuZWwuaXNfYml0c3RyaW5nLCB7XG4gIHRvX2NoYXJfbGlzdDogZnVuY3Rpb24gKHRoaW5nKSB7XG4gICAgaWYgKEtlcm5lbC5pc19iaW5hcnkodGhpbmcpKSB7XG4gICAgICByZXR1cm4gX1N0cmluZy50b19jaGFyX2xpc3QodGhpbmcpO1xuICAgIH1cblxuICAgIHJldHVybiB0aGluZy50b1N0cmluZygpO1xuICB9XG59KTtcblxuS2VybmVsLmRlZmltcGwoQ2hhcnMsIEtlcm5lbC5pc19hdG9tLCB7XG4gIHRvX2NoYXJfbGlzdDogZnVuY3Rpb24gKHRoaW5nKSB7XG4gICAgcmV0dXJuIEF0b20udG9fY2hhcl9saXN0KHRoaW5nKTtcbiAgfVxufSk7XG5cbktlcm5lbC5kZWZpbXBsKENoYXJzLCBLZXJuZWwuaXNfaW50ZWdlciwge1xuICB0b19jaGFyX2xpc3Q6IGZ1bmN0aW9uICh0aGluZykge1xuICAgIHJldHVybiBJbnRlZ2VyLnRvX2NoYXJfbGlzdCh0aGluZyk7XG4gIH1cbn0pO1xuXG5LZXJuZWwuZGVmaW1wbChDaGFycywgS2VybmVsLmlzX2xpc3QsIHtcbiAgdG9fY2hhcl9saXN0OiBmdW5jdGlvbiAodGhpbmcpIHtcbiAgICByZXR1cm4gdGhpbmc7XG4gIH1cbn0pO1xuXG5sZXQgTGlzdCA9IHt9O1xuXG5MaXN0LkNoYXJzID0gQ2hhcnM7XG5cbkxpc3QuZGVsZXRlID0gZnVuY3Rpb24gKGxpc3QsIGl0ZW0pIHtcbiAgbGV0IG5ld192YWx1ZSA9IFtdO1xuICBsZXQgdmFsdWVfZm91bmQgPSBmYWxzZTtcblxuICBmb3IgKGxldCB4IG9mIGxpc3QpIHtcbiAgICBpZiAoeCA9PT0gaXRlbSAmJiB2YWx1ZV9mb3VuZCAhPT0gZmFsc2UpIHtcbiAgICAgIG5ld192YWx1ZS5wdXNoKHgpO1xuICAgICAgdmFsdWVfZm91bmQgPSB0cnVlO1xuICAgIH0gZWxzZSBpZiAoeCAhPT0gaXRlbSkge1xuICAgICAgbmV3X3ZhbHVlLnB1c2goeCk7XG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIEtlcm5lbC5TcGVjaWFsRm9ybXMubGlzdCguLi5uZXdfdmFsdWUpO1xufTtcblxuTGlzdC5kZWxldGVfYXQgPSBmdW5jdGlvbiAobGlzdCwgaW5kZXgpIHtcbiAgbGV0IG5ld192YWx1ZSA9IFtdO1xuXG4gIGZvciAobGV0IGkgPSAwOyBpIDwgbGlzdC5sZW5ndGg7IGkrKykge1xuICAgIGlmIChpICE9PSBpbmRleCkge1xuICAgICAgbmV3X3ZhbHVlLnB1c2gobGlzdFtpXSk7XG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIEtlcm5lbC5TcGVjaWFsRm9ybXMubGlzdCguLi5uZXdfdmFsdWUpO1xufTtcblxuTGlzdC5kdXBsaWNhdGUgPSBmdW5jdGlvbiAoZWxlbSwgbikge1xuICBsZXQgbmV3X3ZhbHVlID0gW107XG5cbiAgZm9yICh2YXIgaSA9IDA7IGkgPCBuOyBpKyspIHtcbiAgICBuZXdfdmFsdWUucHVzaChlbGVtKTtcbiAgfVxuXG4gIHJldHVybiBLZXJuZWwuU3BlY2lhbEZvcm1zLmxpc3QoLi4ubmV3X3ZhbHVlKTtcbn07XG5cbkxpc3QuZmlyc3QgPSBmdW5jdGlvbiAobGlzdCkge1xuICByZXR1cm4gbGlzdFswXTtcbn07XG5cbkxpc3QuZmxhdHRlbiA9IGZ1bmN0aW9uIChsaXN0LCB0YWlsID0gS2VybmVsLlNwZWNpYWxGb3Jtcy5saXN0KCkpIHtcbiAgbGV0IG5ld192YWx1ZSA9IFtdO1xuXG4gIGZvciAobGV0IHggb2YgbGlzdCkge1xuICAgIGlmIChLZXJuZWwuaXNfbGlzdCh4KSkge1xuICAgICAgbmV3X3ZhbHVlID0gbmV3X3ZhbHVlLmNvbmNhdChMaXN0LmZsYXR0ZW4oeCkpO1xuICAgIH0gZWxzZSB7XG4gICAgICBuZXdfdmFsdWUucHVzaCh4KTtcbiAgICB9XG4gIH1cblxuICBuZXdfdmFsdWUgPSBuZXdfdmFsdWUuY29uY2F0KHRhaWwpO1xuXG4gIHJldHVybiBLZXJuZWwuU3BlY2lhbEZvcm1zLmxpc3QoLi4ubmV3X3ZhbHVlKTtcbn07XG5cbkxpc3QuZm9sZGwgPSBmdW5jdGlvbiAobGlzdCwgYWNjLCBmdW5jKSB7XG4gIHJldHVybiBsaXN0LnJlZHVjZShmdW5jLCBhY2MpO1xufTtcblxuTGlzdC5mb2xkciA9IGZ1bmN0aW9uIChsaXN0LCBhY2MsIGZ1bmMpIHtcbiAgbGV0IG5ld19hY2MgPSBhY2M7XG5cbiAgZm9yICh2YXIgaSA9IGxpc3QubGVuZ3RoIC0gMTsgaSA+PSAwOyBpLS0pIHtcbiAgICBuZXdfYWNjID0gZnVuYyhsaXN0W2ldLCBuZXdfYWNjKTtcbiAgfVxuXG4gIHJldHVybiBuZXdfYWNjO1xufTtcblxuTGlzdC5pbnNlcnRfYXQgPSBmdW5jdGlvbiAobGlzdCwgaW5kZXgsIHZhbHVlKSB7XG4gIGxldCBuZXdfdmFsdWUgPSBbXTtcblxuICBmb3IgKGxldCBpID0gMDsgaSA8IGxpc3QubGVuZ3RoOyBpKyspIHtcbiAgICBpZiAoaSA9PT0gaW5kZXgpIHtcbiAgICAgIG5ld192YWx1ZS5wdXNoKHZhbHVlKTtcbiAgICAgIG5ld192YWx1ZS5wdXNoKGxpc3RbaV0pO1xuICAgIH0gZWxzZSB7XG4gICAgICBuZXdfdmFsdWUucHVzaChsaXN0W2ldKTtcbiAgICB9XG4gIH1cblxuICByZXR1cm4gS2VybmVsLlNwZWNpYWxGb3Jtcy5saXN0KC4uLm5ld192YWx1ZSk7XG59O1xuXG5MaXN0LmtleWRlbGV0ZSA9IGZ1bmN0aW9uIChsaXN0LCBrZXksIHBvc2l0aW9uKSB7XG4gIGxldCBuZXdfbGlzdCA9IFtdO1xuXG4gIGZvciAobGV0IGkgPSAwOyBpIDwgbGlzdC5sZW5ndGg7IGkrKykge1xuICAgIGlmICghS2VybmVsLm1hdGNoX19xbWFya19fKGxpc3RbaV1bcG9zaXRpb25dLCBrZXkpKSB7XG4gICAgICBuZXdfbGlzdC5wdXNoKGxpc3RbaV0pO1xuICAgIH1cbiAgfVxuXG4gIHJldHVybiBLZXJuZWwuU3BlY2lhbEZvcm1zLmxpc3QoLi4ubmV3X2xpc3QpO1xufTtcblxuTGlzdC5rZXlmaW5kID0gZnVuY3Rpb24gKGxpc3QsIGtleSwgcG9zaXRpb24sIF9kZWZhdWx0ID0gbnVsbCkge1xuXG4gIGZvciAobGV0IGkgPSAwOyBpIDwgbGlzdC5sZW5ndGg7IGkrKykge1xuICAgIGlmIChLZXJuZWwubWF0Y2hfX3FtYXJrX18obGlzdFtpXVtwb3NpdGlvbl0sIGtleSkpIHtcbiAgICAgIHJldHVybiBsaXN0W2ldO1xuICAgIH1cbiAgfVxuXG4gIHJldHVybiBfZGVmYXVsdDtcbn07XG5cbkxpc3Qua2V5bWVtYmVyX19xbWFya19fID0gZnVuY3Rpb24gKGxpc3QsIGtleSwgcG9zaXRpb24pIHtcblxuICBmb3IgKGxldCBpID0gMDsgaSA8IGxpc3QubGVuZ3RoOyBpKyspIHtcbiAgICBpZiAoS2VybmVsLm1hdGNoX19xbWFya19fKGxpc3RbaV1bcG9zaXRpb25dLCBrZXkpKSB7XG4gICAgICByZXR1cm4gdHJ1ZTtcbiAgICB9XG4gIH1cblxuICByZXR1cm4gZmFsc2U7XG59O1xuXG5MaXN0LmtleXJlcGxhY2UgPSBmdW5jdGlvbiAobGlzdCwga2V5LCBwb3NpdGlvbiwgbmV3X3R1cGxlKSB7XG4gIGxldCBuZXdfbGlzdCA9IFtdO1xuXG4gIGZvciAobGV0IGkgPSAwOyBpIDwgbGlzdC5sZW5ndGg7IGkrKykge1xuICAgIGlmICghS2VybmVsLm1hdGNoX19xbWFya19fKGxpc3RbaV1bcG9zaXRpb25dLCBrZXkpKSB7XG4gICAgICBuZXdfbGlzdC5wdXNoKGxpc3RbaV0pO1xuICAgIH0gZWxzZSB7XG4gICAgICBuZXdfbGlzdC5wdXNoKG5ld190dXBsZSk7XG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIEtlcm5lbC5TcGVjaWFsRm9ybXMubGlzdCguLi5uZXdfbGlzdCk7XG59O1xuXG5MaXN0LmtleXNvcnQgPSBmdW5jdGlvbiAobGlzdCwgcG9zaXRpb24pIHtcbiAgbGV0IG5ld19saXN0ID0gbGlzdDtcblxuICBuZXdfbGlzdC5zb3J0KGZ1bmN0aW9uIChhLCBiKSB7XG4gICAgaWYgKHBvc2l0aW9uID09PSAwKSB7XG4gICAgICBpZiAoYVtwb3NpdGlvbl0udmFsdWUgPCBiW3Bvc2l0aW9uXS52YWx1ZSkge1xuICAgICAgICByZXR1cm4gLTE7XG4gICAgICB9XG5cbiAgICAgIGlmIChhW3Bvc2l0aW9uXS52YWx1ZSA+IGJbcG9zaXRpb25dLnZhbHVlKSB7XG4gICAgICAgIHJldHVybiAxO1xuICAgICAgfVxuXG4gICAgICByZXR1cm4gMDtcbiAgICB9IGVsc2Uge1xuICAgICAgaWYgKGFbcG9zaXRpb25dIDwgYltwb3NpdGlvbl0pIHtcbiAgICAgICAgcmV0dXJuIC0xO1xuICAgICAgfVxuXG4gICAgICBpZiAoYVtwb3NpdGlvbl0gPiBiW3Bvc2l0aW9uXSkge1xuICAgICAgICByZXR1cm4gMTtcbiAgICAgIH1cblxuICAgICAgcmV0dXJuIDA7XG4gICAgfVxuICB9KTtcblxuICByZXR1cm4gS2VybmVsLlNwZWNpYWxGb3Jtcy5saXN0KC4uLm5ld19saXN0KTtcbn07XG5cbkxpc3Qua2V5c3RvcmUgPSBmdW5jdGlvbiAobGlzdCwga2V5LCBwb3NpdGlvbiwgbmV3X3R1cGxlKSB7XG4gIGxldCBuZXdfbGlzdCA9IFtdO1xuICBsZXQgcmVwbGFjZWQgPSBmYWxzZTtcblxuICBmb3IgKGxldCBpID0gMDsgaSA8IGxpc3QubGVuZ3RoOyBpKyspIHtcbiAgICBpZiAoIUtlcm5lbC5tYXRjaF9fcW1hcmtfXyhsaXN0W2ldW3Bvc2l0aW9uXSwga2V5KSkge1xuICAgICAgbmV3X2xpc3QucHVzaChsaXN0W2ldKTtcbiAgICB9IGVsc2Uge1xuICAgICAgbmV3X2xpc3QucHVzaChuZXdfdHVwbGUpO1xuICAgICAgcmVwbGFjZWQgPSB0cnVlO1xuICAgIH1cbiAgfVxuXG4gIGlmICghcmVwbGFjZWQpIHtcbiAgICBuZXdfbGlzdC5wdXNoKG5ld190dXBsZSk7XG4gIH1cblxuICByZXR1cm4gS2VybmVsLlNwZWNpYWxGb3Jtcy5saXN0KC4uLm5ld19saXN0KTtcbn07XG5cbkxpc3QubGFzdCA9IGZ1bmN0aW9uIChsaXN0KSB7XG4gIHJldHVybiBsaXN0W2xpc3QubGVuZ3RoIC0gMV07XG59O1xuXG5MaXN0LnJlcGxhY2VfYXQgPSBmdW5jdGlvbiAobGlzdCwgaW5kZXgsIHZhbHVlKSB7XG4gIGxldCBuZXdfdmFsdWUgPSBbXTtcblxuICBmb3IgKGxldCBpID0gMDsgaSA8IGxpc3QubGVuZ3RoOyBpKyspIHtcbiAgICBpZiAoaSA9PT0gaW5kZXgpIHtcbiAgICAgIG5ld192YWx1ZS5wdXNoKHZhbHVlKTtcbiAgICB9IGVsc2Uge1xuICAgICAgbmV3X3ZhbHVlLnB1c2gobGlzdFtpXSk7XG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIEtlcm5lbC5TcGVjaWFsRm9ybXMubGlzdCguLi5uZXdfdmFsdWUpO1xufTtcblxuTGlzdC51cGRhdGVfYXQgPSBmdW5jdGlvbiAobGlzdCwgaW5kZXgsIGZ1bikge1xuICBsZXQgbmV3X3ZhbHVlID0gW107XG5cbiAgZm9yIChsZXQgaSA9IDA7IGkgPCBsaXN0LmNvdW50KCk7IGkrKykge1xuICAgIGlmIChpID09PSBpbmRleCkge1xuICAgICAgbmV3X3ZhbHVlLnB1c2goZnVuKGxpc3QuZ2V0KGkpKSk7XG4gICAgfSBlbHNlIHtcbiAgICAgIG5ld192YWx1ZS5wdXNoKGxpc3QuZ2V0KGkpKTtcbiAgICB9XG4gIH1cblxuICByZXR1cm4gbmV3X3ZhbHVlO1xufTtcblxuTGlzdC53cmFwID0gZnVuY3Rpb24gKGxpc3QpIHtcbiAgaWYgKEtlcm5lbC5pc19saXN0KGxpc3QpKSB7XG4gICAgcmV0dXJuIGxpc3Q7XG4gIH0gZWxzZSBpZiAobGlzdCA9PSBudWxsKSB7XG4gICAgcmV0dXJuIEtlcm5lbC5TcGVjaWFsRm9ybXMubGlzdCgpO1xuICB9IGVsc2Uge1xuICAgIHJldHVybiBLZXJuZWwuU3BlY2lhbEZvcm1zLmxpc3QobGlzdCk7XG4gIH1cbn07XG5cbkxpc3QuemlwID0gZnVuY3Rpb24gKGxpc3Rfb2ZfbGlzdHMpIHtcbiAgaWYgKGxpc3Rfb2ZfbGlzdHMubGVuZ3RoID09PSAwKSB7XG4gICAgcmV0dXJuIEtlcm5lbC5TcGVjaWFsRm9ybXMubGlzdCgpO1xuICB9XG5cbiAgbGV0IG5ld192YWx1ZSA9IFtdO1xuICBsZXQgc21hbGxlc3RfbGVuZ3RoID0gbGlzdF9vZl9saXN0c1swXTtcblxuICBmb3IgKGxldCB4IG9mIGxpc3Rfb2ZfbGlzdHMpIHtcbiAgICBpZiAoeC5sZW5ndGggPCBzbWFsbGVzdF9sZW5ndGgpIHtcbiAgICAgIHNtYWxsZXN0X2xlbmd0aCA9IHgubGVuZ3RoO1xuICAgIH1cbiAgfVxuXG4gIGZvciAobGV0IGkgPSAwOyBpIDwgc21hbGxlc3RfbGVuZ3RoOyBpKyspIHtcbiAgICBsZXQgY3VycmVudF92YWx1ZSA9IFtdO1xuICAgIGZvciAobGV0IGogPSAwOyBqIDwgbGlzdF9vZl9saXN0cy5sZW5ndGg7IGorKykge1xuICAgICAgY3VycmVudF92YWx1ZS5wdXNoKGxpc3Rfb2ZfbGlzdHNbal1baV0pO1xuICAgIH1cblxuICAgIG5ld192YWx1ZS5wdXNoKEtlcm5lbC5TcGVjaWFsRm9ybXMudHVwbGUoLi4uY3VycmVudF92YWx1ZSkpO1xuICB9XG5cbiAgcmV0dXJuIEtlcm5lbC5TcGVjaWFsRm9ybXMubGlzdCguLi5uZXdfdmFsdWUpO1xufTtcblxuTGlzdC50b190dXBsZSA9IGZ1bmN0aW9uIChsaXN0KSB7XG4gIHJldHVybiBLZXJuZWwuU3BlY2lhbEZvcm1zLnR1cGxlLmFwcGx5KG51bGwsIGxpc3QpO1xufTtcblxuTGlzdC5hcHBlbmQgPSBmdW5jdGlvbiAobGlzdCwgdmFsdWUpIHtcbiAgcmV0dXJuIEtlcm5lbC5TcGVjaWFsRm9ybXMubGlzdCguLi5saXN0LmNvbmNhdChbdmFsdWVdKSk7XG59O1xuXG5MaXN0LnByZXBlbmQgPSBmdW5jdGlvbiAobGlzdCwgdmFsdWUpIHtcbiAgcmV0dXJuIEtlcm5lbC5TcGVjaWFsRm9ybXMubGlzdCguLi5bdmFsdWVdLmNvbmNhdChsaXN0KSk7XG59O1xuXG5MaXN0LmNvbmNhdCA9IGZ1bmN0aW9uIChsZWZ0LCByaWdodCkge1xuICByZXR1cm4gbGVmdC5jb25jYXQocmlnaHQpO1xufTtcblxuY2xhc3MgU2lnbmFsIHtcblxuICBjb25zdHJ1Y3RvcigpIHtcbiAgICB0aGlzLmJpbmRpbmdzID0gU3BlY2lhbEZvcm1zLmxpc3QoKTtcbiAgfVxuXG4gIGFkZChsaXN0ZW5lciwgY29udGV4dCA9IHRoaXMpIHtcbiAgICB0aGlzLmJpbmRpbmdzID0gTGlzdC5hcHBlbmQodGhpcy5iaW5kaW5ncywgbmV3IFNpZ25hbEJpbmRpbmcodGhpcywgbGlzdGVuZXIsIGNvbnRleHQpKTtcbiAgfVxuXG4gIHJlbW92ZShsaXN0ZW5lcikge1xuICAgIHRoaXMuYmluZGluZ3MgPSBFbnVtLmZpbHRlcih0aGlzLmJpbmRpbmdzLCBmdW5jdGlvbiAoYmluZGluZykge1xuICAgICAgcmV0dXJuIGJpbmRpbmcubGlzdGVuZXIgIT09IGxpc3RlbmVyO1xuICAgIH0pO1xuICB9XG5cbiAgZGlzcGF0Y2goLi4ucGFyYW1zKSB7XG4gICAgZm9yIChsZXQgYmluZGluZyBvZiB0aGlzLmJpbmRpbmdzKSB7XG4gICAgICBiaW5kaW5nLmV4ZWN1dGUoLi4ucGFyYW1zKTtcbiAgICB9XG4gIH1cblxuICBkaXNwb3NlKCkge1xuICAgIGZvciAobGV0IGJpbmRpbmcgb2YgdGhpcy5iaW5kaW5ncykge1xuICAgICAgYmluZGluZy5kaXNwb3NlKCk7XG4gICAgfVxuXG4gICAgdGhpcy5iaW5kaW5ncyA9IG51bGw7XG4gIH1cbn1cblxuY2xhc3MgU2lnbmFsQmluZGluZyB7XG5cbiAgY29uc3RydWN0b3Ioc2lnbmFsLCBsaXN0ZW5lciwgY29udGV4dCkge1xuICAgIHRoaXMubGlzdGVuZXIgPSBsaXN0ZW5lcjtcbiAgICB0aGlzLnNpZ25hbCA9IHNpZ25hbDtcbiAgICB0aGlzLmNvbnRleHQgPSBjb250ZXh0O1xuICB9XG5cbiAgZXhlY3V0ZSguLi5wYXJhbXMpIHtcbiAgICB0aGlzLmxpc3RlbmVyLmFwcGx5KHRoaXMuY29udGV4dCwgcGFyYW1zKTtcbiAgfVxuXG4gIGRpc3Bvc2UoKSB7XG4gICAgdGhpcy5saXN0ZW5lciA9IG51bGw7XG4gICAgdGhpcy5zaWduYWwgPSBudWxsO1xuICAgIHRoaXMuY29udGV4dCA9IG51bGw7XG4gIH1cbn1cblxuZnVuY3Rpb24gX191cGRhdGUobWFwLCBrZXksIHZhbHVlKSB7XG4gIGxldCBtID0gbmV3IE1hcChtYXApO1xuICBtLnNldChrZXksIHZhbHVlKTtcbiAgcmV0dXJuIG07XG59XG5cbmZ1bmN0aW9uIHJlbW92ZShtYXAsIGtleSkge1xuICBsZXQgbSA9IG5ldyBNYXAobWFwKTtcbiAgbS5kZWxldGUoa2V5KTtcbiAgcmV0dXJuIG07XG59XG5cbmNsYXNzIE1haWxCb3gge1xuXG4gIGNvbnN0cnVjdG9yKGNvbnRleHQgPSB0aGlzKSB7XG4gICAgdGhpcy5zaWduYWwgPSBuZXcgU2lnbmFsKCk7XG4gICAgdGhpcy5zaWduYWwuYWRkKCguLi5wYXJhbXMpID0+IHRoaXMubWVzc2FnZXMgPSB0aGlzLm1lc3NhZ2VzLmNvbmNhdChwYXJhbXMpLCBjb250ZXh0KTtcbiAgICB0aGlzLm1lc3NhZ2VzID0gW107XG4gIH1cblxuICByZWNlaXZlKC4uLm1lc3NhZ2VzKSB7XG4gICAgdGhpcy5zaWduYWwuZGlzcGF0Y2goLi4ubWVzc2FnZXMpO1xuICB9XG5cbiAgcGVlaygpIHtcbiAgICBpZiAodGhpcy5tZXNzYWdlcy5sZW5ndGggPT09IDApIHtcbiAgICAgIHJldHVybiBudWxsO1xuICAgIH1cblxuICAgIHJldHVybiB0aGlzLm1lc3NhZ2VzWzBdO1xuICB9XG5cbiAgcmVhZCgpIHtcbiAgICBsZXQgcmVzdWx0ID0gdGhpcy5tZXNzYWdlc1swXTtcbiAgICB0aGlzLm1lc3NhZ2VzID0gdGhpcy5tZXNzYWdlcy5zbGljZSgxKTtcblxuICAgIHJldHVybiByZXN1bHQ7XG4gIH1cblxuICBhZGRfc3Vic2NyaWJlcihmbiwgY29udGV4dCA9IHRoaXMpIHtcbiAgICB0aGlzLnNpZ25hbC5hZGQoZm4sIGNvbnRleHQpO1xuICB9XG5cbiAgcmVtb3ZlX3N1YnNjcmliZXIoZm4pIHtcbiAgICB0aGlzLnNpZ25hbC5yZW1vdmUoZm4pO1xuICB9XG5cbiAgZGlzcG9zZSgpIHtcbiAgICB0aGlzLnNpZ25hbC5kaXNwb3NlKCk7XG4gICAgdGhpcy5tZXNzYWdlcyA9IG51bGw7XG4gIH1cbn1cblxuY2xhc3MgUG9zdE9mZmljZSB7XG5cbiAgY29uc3RydWN0b3IoKSB7XG4gICAgdGhpcy5tYWlsYm94ZXMgPSBuZXcgTWFwKCk7XG4gIH1cblxuICBzZW5kKGFkZHJlc3MsIG1lc3NhZ2UpIHtcbiAgICB0aGlzLm1haWxib3hlcy5nZXQoYWRkcmVzcykucmVjZWl2ZShtZXNzYWdlKTtcbiAgfVxuXG4gIHJlY2VpdmUoYWRkcmVzcykge1xuICAgIHJldHVybiB0aGlzLm1haWxib3hlcy5nZXQoYWRkcmVzcykucmVhZCgpO1xuICB9XG5cbiAgcGVlayhhZGRyZXNzKSB7XG4gICAgcmV0dXJuIHRoaXMubWFpbGJveGVzLmdldChhZGRyZXNzKS5wZWVrKCk7XG4gIH1cblxuICBhZGRfbWFpbGJveChhZGRyZXNzID0gU3ltYm9sKCksIGNvbnRleHQgPSB0aGlzKSB7XG4gICAgdGhpcy5tYWlsYm94ZXMgPSBfX3VwZGF0ZSh0aGlzLm1haWxib3hlcywgYWRkcmVzcywgbmV3IE1haWxCb3goKSk7XG4gICAgcmV0dXJuIGFkZHJlc3M7XG4gIH1cblxuICByZW1vdmVfbWFpbGJveChhZGRyZXNzKSB7XG4gICAgdGhpcy5tYWlsYm94ZXMuZ2V0KGFkZHJlc3MpLmRpc3Bvc2UoKTtcbiAgICB0aGlzLm1haWxib3hlcyA9IHJlbW92ZSh0aGlzLm1haWxib3hlcywgYWRkcmVzcyk7XG4gIH1cblxuICBzdWJzY3JpYmUoYWRkcmVzcywgc3Vic2NyaWJ0aW9uX2ZuLCBjb250ZXh0ID0gdGhpcykge1xuICAgIHRoaXMubWFpbGJveGVzLmdldChhZGRyZXNzKS5hZGRfc3Vic2NyaWJlcihzdWJzY3JpYnRpb25fZm4sIGNvbnRleHQpO1xuICB9XG5cbiAgdW5zdWJzY3JpYmUoYWRkcmVzcywgc3Vic2NyaWJ0aW9uX2ZuKSB7XG4gICAgdGhpcy5tYWlsYm94ZXMuZ2V0KGFkZHJlc3MpLnJlbW92ZV9zdWJzY3JpYmVyKHN1YnNjcmlidGlvbl9mbik7XG4gIH1cbn1cblxuZnVuY3Rpb24gY2FsbF9wcm9wZXJ0eShpdGVtLCBwcm9wZXJ0eSkge1xuICBpZiAocHJvcGVydHkgaW4gaXRlbSkge1xuICAgIGl0ZW1bcHJvcGVydHldO1xuICAgIGlmIChpdGVtW3Byb3BlcnR5XSBpbnN0YW5jZW9mIEZ1bmN0aW9uKSB7XG4gICAgICByZXR1cm4gaXRlbVtwcm9wZXJ0eV0oKTtcbiAgICB9IGVsc2Uge1xuICAgICAgcmV0dXJuIGl0ZW1bcHJvcGVydHldO1xuICAgIH1cbiAgfSBlbHNlIGlmIChTeW1ib2wuZm9yKHByb3BlcnR5KSBpbiBpdGVtKSB7XG4gICAgbGV0IHByb3AgPSBTeW1ib2wuZm9yKHByb3BlcnR5KTtcbiAgICBpZiAoaXRlbVtwcm9wXSBpbnN0YW5jZW9mIEZ1bmN0aW9uKSB7XG4gICAgICByZXR1cm4gaXRlbVtwcm9wXSgpO1xuICAgIH0gZWxzZSB7XG4gICAgICByZXR1cm4gaXRlbVtwcm9wXTtcbiAgICB9XG4gIH1cblxuICB0aHJvdyBuZXcgRXJyb3IoYFByb3BlcnR5ICR7IHByb3BlcnR5IH0gbm90IGZvdW5kIGluICR7IGl0ZW0gfWApO1xufVxuXG52YXIgSlMgPSB7XG4gIGNhbGxfcHJvcGVydHlcbn07XG5cbmxldCBSYW5nZSA9IGZ1bmN0aW9uIChfZmlyc3QsIF9sYXN0KSB7XG4gIGlmICghKHRoaXMgaW5zdGFuY2VvZiBSYW5nZSkpIHtcbiAgICByZXR1cm4gbmV3IFJhbmdlKF9maXJzdCwgX2xhc3QpO1xuICB9XG5cbiAgdGhpcy5maXJzdCA9IGZ1bmN0aW9uICgpIHtcbiAgICByZXR1cm4gX2ZpcnN0O1xuICB9O1xuXG4gIHRoaXMubGFzdCA9IGZ1bmN0aW9uICgpIHtcbiAgICByZXR1cm4gX2xhc3Q7XG4gIH07XG5cbiAgbGV0IF9yYW5nZSA9IFtdO1xuXG4gIGZvciAobGV0IGkgPSBfZmlyc3Q7IGkgPD0gX2xhc3Q7IGkrKykge1xuICAgIF9yYW5nZS5wdXNoKGkpO1xuICB9XG5cbiAgX3JhbmdlID0gT2JqZWN0LmZyZWV6ZShfcmFuZ2UpO1xuXG4gIHRoaXMudmFsdWUgPSBmdW5jdGlvbiAoKSB7XG4gICAgcmV0dXJuIF9yYW5nZTtcbiAgfTtcblxuICB0aGlzLmxlbmd0aCA9IGZ1bmN0aW9uICgpIHtcbiAgICByZXR1cm4gX3JhbmdlLmxlbmd0aDtcbiAgfTtcblxuICByZXR1cm4gdGhpcztcbn07XG5cblJhbmdlLnByb3RvdHlwZVtTeW1ib2wuaXRlcmF0b3JdID0gZnVuY3Rpb24gKCkge1xuICByZXR1cm4gdGhpcy52YWx1ZSgpW1N5bWJvbC5pdGVyYXRvcl0oKTtcbn07XG5cblJhbmdlLm5ldyA9IGZ1bmN0aW9uIChmaXJzdCwgbGFzdCkge1xuICByZXR1cm4gUmFuZ2UoZmlyc3QsIGxhc3QpO1xufTtcblxuUmFuZ2UucmFuZ2VfX3FtYXJrX18gPSBmdW5jdGlvbiAocmFuZ2UpIHtcbiAgcmV0dXJuIHJhbmdlIGluc3RhbmNlb2YgUmFuZ2U7XG59O1xuXG5sZXQgS2V5d29yZCA9IHt9O1xuXG5LZXl3b3JkLmhhc19rZXlfX3FtX18gPSBmdW5jdGlvbiAoa2V5d29yZHMsIGtleSkge1xuICBmb3IgKGxldCBrZXl3b3JkIG9mIGtleXdvcmRzKSB7XG4gICAgaWYgKEtlcm5lbC5lbGVtKGtleXdvcmQsIDApID09IGtleSkge1xuICAgICAgcmV0dXJuIHRydWU7XG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIGZhbHNlO1xufTtcblxuS2V5d29yZC5nZXQgPSBmdW5jdGlvbiAoa2V5d29yZHMsIGtleSwgdGhlX2RlZmF1bHQgPSBudWxsKSB7XG4gIGZvciAobGV0IGtleXdvcmQgb2Yga2V5d29yZHMpIHtcbiAgICBpZiAoS2VybmVsLmVsZW0oa2V5d29yZCwgMCkgPT0ga2V5KSB7XG4gICAgICByZXR1cm4gS2VybmVsLmVsZW0oa2V5d29yZCwgMSk7XG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIHRoZV9kZWZhdWx0O1xufTtcblxubGV0IEFnZW50ID0ge307XG5cbkFnZW50LnN0YXJ0ID0gZnVuY3Rpb24gKGZ1biwgb3B0aW9ucyA9IFtdKSB7XG4gIGNvbnN0IG5hbWUgPSBLZXl3b3JkLmhhc19rZXlfX3FtX18ob3B0aW9ucywgS2VybmVsLlNwZWNpYWxGb3Jtcy5hdG9tKCduYW1lJykpID8gS2V5d29yZC5nZXQob3B0aW9ucywgS2VybmVsLlNwZWNpYWxGb3Jtcy5hdG9tKCduYW1lJykpIDogU3ltYm9sKCk7XG5cbiAgc2VsZi5wb3N0X29mZmljZS5hZGRfbWFpbGJveChuYW1lKTtcbiAgc2VsZi5wb3N0X29mZmljZS5zZW5kKG5hbWUsIGZ1bigpKTtcblxuICByZXR1cm4gS2VybmVsLlNwZWNpYWxGb3Jtcy50dXBsZShLZXJuZWwuU3BlY2lhbEZvcm1zLmF0b20oJ29rJyksIG5hbWUpO1xufTtcblxuQWdlbnQuc3RvcCA9IGZ1bmN0aW9uIChhZ2VudCwgdGltZW91dCA9IDUwMDApIHtcbiAgc2VsZi5wb3N0X29mZmljZS5yZW1vdmVfbWFpbGJveChhZ2VudCk7XG4gIHJldHVybiBLZXJuZWwuU3BlY2lhbEZvcm1zLmF0b20oJ29rJyk7XG59O1xuXG5BZ2VudC51cGRhdGUgPSBmdW5jdGlvbiAoYWdlbnQsIGZ1biwgdGltZW91dCA9IDUwMDApIHtcblxuICBjb25zdCBjdXJyZW50X3N0YXRlID0gc2VsZi5wb3N0X29mZmljZS5yZWNlaXZlKGFnZW50KTtcbiAgc2VsZi5wb3N0X29mZmljZS5zZW5kKGFnZW50LCBmdW4oY3VycmVudF9zdGF0ZSkpO1xuXG4gIHJldHVybiBLZXJuZWwuU3BlY2lhbEZvcm1zLmF0b20oJ29rJyk7XG59O1xuXG5BZ2VudC5nZXQgPSBmdW5jdGlvbiAoYWdlbnQsIGZ1biwgdGltZW91dCA9IDUwMDApIHtcbiAgcmV0dXJuIGZ1bihzZWxmLnBvc3Rfb2ZmaWNlLnBlZWsoYWdlbnQpKTtcbn07XG5cbkFnZW50LmdldF9hbmRfdXBkYXRlID0gZnVuY3Rpb24gKGFnZW50LCBmdW4sIHRpbWVvdXQgPSA1MDAwKSB7XG5cbiAgY29uc3QgZ2V0X2FuZF91cGRhdGVfdHVwbGUgPSBmdW4oc2VsZi5wb3N0X29mZmljZS5yZWNlaXZlKGFnZW50KSk7XG4gIHNlbGYucG9zdF9vZmZpY2Uuc2VuZChhZ2VudCwgS2VybmVsLmVsZW0oZ2V0X2FuZF91cGRhdGVfdHVwbGUsIDEpKTtcblxuICByZXR1cm4gS2VybmVsLmVsZW0oZ2V0X2FuZF91cGRhdGVfdHVwbGUsIDApO1xufTtcblxuLy9odHRwczovL2RldmVsb3Blci5tb3ppbGxhLm9yZy9lbi1VUy9kb2NzL1dlYi9BUEkvV2luZG93QmFzZTY0L0Jhc2U2NF9lbmNvZGluZ19hbmRfZGVjb2RpbmcjU29sdXRpb25fMl8lRTIlODAlOTNfcmV3cml0ZV90aGVfRE9Nc19hdG9iKClfYW5kX2J0b2EoKV91c2luZ19KYXZhU2NyaXB0J3NfVHlwZWRBcnJheXNfYW5kX1VURi04XG5mdW5jdGlvbiBiNjRFbmNvZGVVbmljb2RlKHN0cikge1xuICByZXR1cm4gYnRvYShlbmNvZGVVUklDb21wb25lbnQoc3RyKS5yZXBsYWNlKC8lKFswLTlBLUZdezJ9KS9nLCBmdW5jdGlvbiAobWF0Y2gsIHAxKSB7XG4gICAgcmV0dXJuIFN0cmluZy5mcm9tQ2hhckNvZGUoJzB4JyArIHAxKTtcbiAgfSkpO1xufVxuXG5mdW5jdGlvbiBlbmNvZGU2NChkYXRhKSB7XG4gIHJldHVybiBiNjRFbmNvZGVVbmljb2RlKGRhdGEpO1xufVxuXG5mdW5jdGlvbiBkZWNvZGU2NChkYXRhKSB7XG4gIHRyeSB7XG4gICAgcmV0dXJuIEtlcm5lbC5TcGVjaWFsRm9ybXMudHVwbGUoS2VybmVsLlNwZWNpYWxGb3Jtcy5hdG9tKCdvaycpLCBhdG9iKGRhdGEpKTtcbiAgfSBjYXRjaCAoZSkge1xuICAgIHJldHVybiBLZXJuZWwuU3BlY2lhbEZvcm1zLmF0b20oJ2Vycm9yJyk7XG4gIH1cbiAgcmV0dXJuIGJ0b2EoZGF0YSk7XG59XG5cbmZ1bmN0aW9uIGRlY29kZTY0X19lbV9fKGRhdGEpIHtcbiAgcmV0dXJuIGF0b2IoZGF0YSk7XG59XG5cbnZhciBCYXNlID0ge1xuICBlbmNvZGU2NCxcbiAgZGVjb2RlNjQsXG4gIGRlY29kZTY0X19lbV9fXG59O1xuXG5mdW5jdGlvbiBibm90KGV4cHIpIHtcbiAgcmV0dXJuIH5leHByO1xufVxuXG5mdW5jdGlvbiBiYW5kKGxlZnQsIHJpZ2h0KSB7XG4gIHJldHVybiBsZWZ0ICYgcmlnaHQ7XG59XG5cbmZ1bmN0aW9uIGJvcihsZWZ0LCByaWdodCkge1xuICByZXR1cm4gbGVmdCB8IHJpZ2h0O1xufVxuXG5mdW5jdGlvbiBic2wobGVmdCwgcmlnaHQpIHtcbiAgcmV0dXJuIGxlZnQgPDwgcmlnaHQ7XG59XG5cbmZ1bmN0aW9uIGJzcihsZWZ0LCByaWdodCkge1xuICByZXR1cm4gbGVmdCA+PiByaWdodDtcbn1cblxuZnVuY3Rpb24gYnhvcihsZWZ0LCByaWdodCkge1xuICByZXR1cm4gbGVmdCBeIHJpZ2h0O1xufVxuXG52YXIgQml0d2lzZSA9IHtcbiAgYm5vdCxcbiAgYmFuZCxcbiAgYm9yLFxuICBic2wsXG4gIGJzcixcbiAgYnhvclxufTtcblxubGV0IEVudW1lcmFibGUgPSBLZXJuZWwuZGVmcHJvdG9jb2woe1xuICBjb3VudDogZnVuY3Rpb24gKGNvbGxlY3Rpb24pIHt9LFxuICBtZW1iZXJfcW1hcmtfXzogZnVuY3Rpb24gKGNvbGxlY3Rpb24sIHZhbHVlKSB7fSxcbiAgcmVkdWNlOiBmdW5jdGlvbiAoY29sbGVjdGlvbiwgYWNjLCBmdW4pIHt9XG59KTtcblxubGV0IENvbGxlY3RhYmxlID0gS2VybmVsLmRlZnByb3RvY29sKHtcbiAgaW50bzogZnVuY3Rpb24gKGNvbGxlY3RhYmxlKSB7fVxufSk7XG5cbmxldCBJbnNwZWN0ID0gS2VybmVsLmRlZnByb3RvY29sKHtcbiAgaW5zcGVjdDogZnVuY3Rpb24gKHRoaW5nLCBvcHRzKSB7fVxufSk7XG5cbmZ1bmN0aW9uIF9fX25ld19fKCkge1xuICByZXR1cm4gU3BlY2lhbEZvcm1zLm1hcCh7fSk7XG59XG5cbmZ1bmN0aW9uIGtleXMobWFwKSB7XG4gIHJldHVybiBPYmplY3Qua2V5cyhtYXApO1xufVxuXG5mdW5jdGlvbiBfX3NpemUobWFwKSB7XG4gIHJldHVybiBrZXlzKG1hcCkubGVuZ3RoO1xufVxuXG5mdW5jdGlvbiBfX3RvX2xpc3QobWFwKSB7XG4gIGxldCBtYXBfa2V5cyA9IGtleXMobWFwKTtcbiAgbGV0IGxpc3QgPSBbXTtcblxuICBmb3IgKGxldCBrZXkgb2YgbWFwX2tleXMpIHtcbiAgICBsaXN0LnB1c2goU3BlY2lhbEZvcm1zLnR1cGxlKGtleSwgbWFwW2tleV0pKTtcbiAgfVxuXG4gIHJldHVybiBTcGVjaWFsRm9ybXMubGlzdCguLi5saXN0KTtcbn1cblxuZnVuY3Rpb24gdmFsdWVzKG1hcCkge1xuICBsZXQgbWFwX2tleXMgPSBrZXlzKG1hcCk7XG4gIGxldCBsaXN0ID0gW107XG5cbiAgZm9yIChsZXQga2V5IG9mIG1hcF9rZXlzKSB7XG4gICAgbGlzdC5wdXNoKG1hcFtrZXldKTtcbiAgfVxuXG4gIHJldHVybiBTcGVjaWFsRm9ybXMubGlzdCguLi5saXN0KTtcbn1cblxuZnVuY3Rpb24gZnJvbV9zdHJ1Y3Qoc3RydWN0KSB7XG4gIGxldCBtYXAgPSBPYmplY3QuYXNzaWduKHt9LCBzdHJ1Y3QpO1xuICBkZWxldGUgbWFwW1N5bWJvbC5mb3IoXCJfX3N0cnVjdF9fXCIpXTtcblxuICByZXR1cm4gU3BlY2lhbEZvcm1zLm1hcChtYXApO1xufVxuXG5mdW5jdGlvbiBfX19fZGVsZXRlX18obWFwLCBrZXkpIHtcbiAgbGV0IG5ld19tYXAgPSBPYmplY3QuYXNzaWduKHt9LCBtYXApO1xuXG4gIGRlbGV0ZSBuZXdfbWFwW2tleV07XG5cbiAgcmV0dXJuIFNwZWNpYWxGb3Jtcy5tYXAobmV3X21hcCk7XG59XG5cbmZ1bmN0aW9uIGRyb3AobWFwLCBrZXlzKSB7XG4gIGxldCBuZXdfbWFwID0gT2JqZWN0LmFzc2lnbih7fSwgbWFwKTtcblxuICBmb3IgKGxldCBrZXkgb2Yga2V5cykge1xuICAgIGRlbGV0ZSBuZXdfbWFwW2tleV07XG4gIH1cblxuICByZXR1cm4gU3BlY2lhbEZvcm1zLm1hcChuZXdfbWFwKTtcbn1cblxuZnVuY3Rpb24gX19lcXVhbF9fcW1hcmtfXyhtYXAxLCBtYXAyKSB7XG4gIHJldHVybiBtYXAxID09PSBtYXAyO1xufVxuXG5mdW5jdGlvbiBmZXRjaF9fZW1hcmtfXyhtYXAsIGtleSkge1xuICBpZiAoa2V5IGluIG1hcCkge1xuICAgIHJldHVybiBtYXBba2V5XTtcbiAgfVxuXG4gIHRocm93IG5ldyBFcnJvcihcIktleSBub3QgZm91bmQuXCIpO1xufVxuXG5mdW5jdGlvbiBmZXRjaChtYXAsIGtleSkge1xuICBpZiAoa2V5IGluIG1hcCkge1xuICAgIHJldHVybiBTcGVjaWFsRm9ybXMudHVwbGUoU3BlY2lhbEZvcm1zLmF0b20oXCJva1wiKSwgbWFwW2tleV0pO1xuICB9XG5cbiAgcmV0dXJuIFNwZWNpYWxGb3Jtcy5hdG9tKFwiZXJyb3JcIik7XG59XG5cbmZ1bmN0aW9uIGhhc19rZXlfX3FtYXJrX18obWFwLCBrZXkpIHtcbiAgcmV0dXJuIGtleSBpbiBtYXA7XG59XG5cbmZ1bmN0aW9uIG1lcmdlKG1hcDEsIG1hcDIpIHtcbiAgcmV0dXJuIFNwZWNpYWxGb3Jtcy5tYXBfdXBkYXRlKG1hcDEsIG1hcDIpO1xufVxuXG5mdW5jdGlvbiBzcGxpdChtYXAsIGtleXMpIHtcbiAgbGV0IHNwbGl0MSA9IHt9O1xuICBsZXQgc3BsaXQyID0ge307XG5cbiAgZm9yIChsZXQga2V5IG9mIE9iamVjdC5rZXlzKG1hcCkpIHtcbiAgICBpZiAoa2V5cy5pbmRleE9mKGtleSkgPiAtMSkge1xuICAgICAgc3BsaXQxW2tleV0gPSBtYXBba2V5XTtcbiAgICB9IGVsc2Uge1xuICAgICAgc3BsaXQyW2tleV0gPSBtYXBba2V5XTtcbiAgICB9XG4gIH1cblxuICByZXR1cm4gU3BlY2lhbEZvcm1zLnR1cGxlKFNwZWNpYWxGb3Jtcy5tYXAoc3BsaXQxKSwgU3BlY2lhbEZvcm1zLm1hcChzcGxpdDIpKTtcbn1cblxuZnVuY3Rpb24gdGFrZShtYXAsIGtleXMpIHtcbiAgbGV0IHNwbGl0MSA9IHt9O1xuXG4gIGZvciAobGV0IGtleSBvZiBPYmplY3Qua2V5cyhtYXApKSB7XG4gICAgaWYgKGtleXMuaW5kZXhPZihrZXkpID4gLTEpIHtcbiAgICAgIHNwbGl0MVtrZXldID0gbWFwW2tleV07XG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIFNwZWNpYWxGb3Jtcy5tYXAoc3BsaXQxKTtcbn1cblxuZnVuY3Rpb24gZHJvcChtYXAsIGtleXMpIHtcbiAgbGV0IHNwbGl0MSA9IHt9O1xuXG4gIGZvciAobGV0IGtleSBvZiBPYmplY3Qua2V5cyhtYXApKSB7XG4gICAgaWYgKGtleXMuaW5kZXhPZihrZXkpID09PSAtMSkge1xuICAgICAgc3BsaXQxW2tleV0gPSBtYXBba2V5XTtcbiAgICB9XG4gIH1cblxuICByZXR1cm4gU3BlY2lhbEZvcm1zLm1hcChzcGxpdDEpO1xufVxuXG5mdW5jdGlvbiBwdXRfbmV3KG1hcCwga2V5LCB2YWx1ZSkge1xuICBpZiAoa2V5IGluIG1hcCkge1xuICAgIHJldHVybiBtYXA7XG4gIH1cblxuICBsZXQgbmV3X21hcCA9IE9iamVjdC5hc3NpZ24oe30sIG1hcCk7XG4gIG5ld19tYXBba2V5XSA9IHZhbHVlO1xuXG4gIHJldHVybiBTcGVjaWFsRm9ybXMubWFwKG5ld19tYXApO1xufVxuXG5mdW5jdGlvbiBwdXRfbmV3X2xhenkobWFwLCBrZXksIGZ1bikge1xuICBpZiAoa2V5IGluIG1hcCkge1xuICAgIHJldHVybiBtYXA7XG4gIH1cblxuICBsZXQgbmV3X21hcCA9IE9iamVjdC5hc3NpZ24oe30sIG1hcCk7XG4gIG5ld19tYXBba2V5XSA9IGZ1bigpO1xuXG4gIHJldHVybiBTcGVjaWFsRm9ybXMubWFwKG5ld19tYXApO1xufVxuXG5mdW5jdGlvbiBnZXRfYW5kX3VwZGF0ZShtYXAsIGtleSwgZnVuKSB7XG4gIGlmIChrZXkgaW4gbWFwKSB7XG4gICAgcmV0dXJuIG1hcDtcbiAgfVxuXG4gIGxldCBuZXdfbWFwID0gT2JqZWN0LmFzc2lnbih7fSwgbWFwKTtcbiAgbmV3X21hcFtrZXldID0gZnVuKG1hcFtrZXldKTtcblxuICByZXR1cm4gU3BlY2lhbEZvcm1zLm1hcChuZXdfbWFwKTtcbn1cblxuZnVuY3Rpb24gcG9wX2xhenkobWFwLCBrZXksIGZ1bikge1xuICBpZiAoIWtleSBpbiBtYXApIHtcbiAgICByZXR1cm4gU3BlY2lhbEZvcm1zLnR1cGxlKGZ1bigpLCBtYXApO1xuICB9XG5cbiAgbGV0IG5ld19tYXAgPSBPYmplY3QuYXNzaWduKHt9LCBtYXApO1xuICBsZXQgdmFsdWUgPSBmdW4obmV3X21hcFtrZXldKTtcbiAgZGVsZXRlIG5ld19tYXBba2V5XTtcblxuICByZXR1cm4gU3BlY2lhbEZvcm1zLnR1cGxlKHZhbHVlLCBuZXdfbWFwKTtcbn1cblxuZnVuY3Rpb24gcG9wKG1hcCwga2V5LCBfZGVmYXVsdCA9IG51bGwpIHtcbiAgaWYgKCFrZXkgaW4gbWFwKSB7XG4gICAgcmV0dXJuIFNwZWNpYWxGb3Jtcy50dXBsZShfZGVmYXVsdCwgbWFwKTtcbiAgfVxuXG4gIGxldCBuZXdfbWFwID0gT2JqZWN0LmFzc2lnbih7fSwgbWFwKTtcbiAgbGV0IHZhbHVlID0gbmV3X21hcFtrZXldO1xuICBkZWxldGUgbmV3X21hcFtrZXldO1xuXG4gIHJldHVybiBTcGVjaWFsRm9ybXMudHVwbGUodmFsdWUsIG5ld19tYXApO1xufVxuXG5mdW5jdGlvbiBnZXRfbGF6eShtYXAsIGtleSwgZnVuKSB7XG4gIGlmICgha2V5IGluIG1hcCkge1xuICAgIHJldHVybiBmdW4oKTtcbiAgfVxuXG4gIHJldHVybiBmdW4obWFwW2tleV0pO1xufVxuXG5mdW5jdGlvbiBnZXQobWFwLCBrZXksIF9kZWZhdWx0ID0gbnVsbCkge1xuICBpZiAoIWtleSBpbiBtYXApIHtcbiAgICByZXR1cm4gX2RlZmF1bHQ7XG4gIH1cblxuICByZXR1cm4gbWFwW2tleV07XG59XG5cbmZ1bmN0aW9uIF9fcHV0KG1hcCwga2V5LCB2YWwpIHtcbiAgbGV0IG5ld19tYXAgPSBPYmplY3Qoe30sIG1hcCk7XG4gIG5ld19tYXBba2V5XSA9IHZhbDtcblxuICByZXR1cm4gU3BlY2lhbEZvcm1zLm1hcChuZXdfbWFwKTtcbn1cblxuZnVuY3Rpb24gdXBkYXRlX19lbWFya19fKG1hcCwga2V5LCBmdW4pIHtcbiAgaWYgKCFrZXkgaW4gbWFwKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKFwiS2V5IG5vdCBmb3VuZFwiKTtcbiAgfVxuXG4gIGxldCBuZXdfbWFwID0gT2JqZWN0KHt9LCBtYXApO1xuICBuZXdfbWFwW2tleV0gPSBmdW4obWFwW2tleV0pO1xuXG4gIHJldHVybiBTcGVjaWFsRm9ybXMubWFwKG5ld19tYXApO1xufVxuXG5mdW5jdGlvbiBfdXBkYXRlKG1hcCwga2V5LCBpbml0aWFsLCBmdW4pIHtcbiAgbGV0IG5ld19tYXAgPSBPYmplY3Qoe30sIG1hcCk7XG5cbiAgaWYgKCFrZXkgaW4gbWFwKSB7XG4gICAgbmV3X21hcFtrZXldID0gaW5pdGlhbDtcbiAgfSBlbHNlIHtcbiAgICBuZXdfbWFwW2tleV0gPSBmdW4obWFwW2tleV0pO1xuICB9XG5cbiAgcmV0dXJuIFNwZWNpYWxGb3Jtcy5tYXAobmV3X21hcCk7XG59XG5cbnZhciBfTWFwID0ge1xuICBuZXc6IF9fX25ld19fLFxuICBrZXlzLFxuICBzaXplOiBfX3NpemUsXG4gIHRvX2xpc3Q6IF9fdG9fbGlzdCxcbiAgdmFsdWVzLFxuICBmcm9tX3N0cnVjdCxcbiAgZGVsZXRlOiBfX19fZGVsZXRlX18sXG4gIGRyb3AsXG4gIGVxdWFsX19xbWFya19fOiBfX2VxdWFsX19xbWFya19fLFxuICBmZXRjaF9fZW1hcmtfXyxcbiAgZmV0Y2gsXG4gIGhhc19rZXlfX3FtYXJrX18sXG4gIHNwbGl0LFxuICB0YWtlLFxuICBwdXRfbmV3LFxuICBwdXRfbmV3X2xhenksXG4gIGdldF9hbmRfdXBkYXRlLFxuICBwb3BfbGF6eSxcbiAgcG9wLFxuICBnZXRfbGF6eSxcbiAgZ2V0LFxuICBwdXQ6IF9fcHV0LFxuICB1cGRhdGVfX2VtYXJrX18sXG4gIHVwZGF0ZTogX3VwZGF0ZVxufTtcblxuZnVuY3Rpb24gX19uZXdfXygpIHtcbiAgcmV0dXJuIFNwZWNpYWxGb3Jtcy5tYXAoeyBbU3ltYm9sLmZvcignX19zdHJ1Y3RfXycpXTogU3ltYm9sLmZvcignTWFwU2V0JyksIHNldDogU3BlY2lhbEZvcm1zLmxpc3QoKSB9KTtcbn1cblxuZnVuY3Rpb24gX3NpemUobWFwKSB7XG4gIHJldHVybiBtYXAuc2V0Lmxlbmd0aDtcbn1cblxuZnVuY3Rpb24gX3RvX2xpc3QobWFwKSB7XG4gIHJldHVybiBtYXAuc2V0O1xufVxuXG5mdW5jdGlvbiBfX19kZWxldGVfXyhzZXQsIHRlcm0pIHtcbiAgbGV0IG5ld19saXN0ID0gTGlzdC5kZWxldGUoc2V0LnNldCwgdGVybSk7XG5cbiAgbGV0IG5ld19tYXAgPSBPYmplY3QuYXNzaWduKHt9LCBzZXQpO1xuICBuZXdfbWFwLnNldCA9IG5ld19saXN0O1xuICByZXR1cm4gU3BlY2lhbEZvcm1zLm1hcChuZXdfbWFwKTtcbn1cblxuZnVuY3Rpb24gX3B1dChzZXQsIHRlcm0pIHtcbiAgaWYgKHNldC5zZXQuaW5kZXhPZih0ZXJtKSA9PT0gLTEpIHtcbiAgICBsZXQgbmV3X2xpc3QgPSBMaXN0LmFwcGVuZChzZXQuc2V0LCB0ZXJtKTtcblxuICAgIGxldCBuZXdfbWFwID0gT2JqZWN0LmFzc2lnbih7fSwgc2V0KTtcbiAgICBuZXdfbWFwLnNldCA9IG5ld19saXN0O1xuICAgIHJldHVybiBTcGVjaWFsRm9ybXMubWFwKG5ld19tYXApO1xuICB9XG5cbiAgcmV0dXJuIHNldDtcbn1cblxuZnVuY3Rpb24gX2RpZmZlcmVuY2Uoc2V0MSwgc2V0Mikge1xuICBsZXQgbmV3X21hcCA9IE9iamVjdC5hc3NpZ24oe30sIHNldDEpO1xuXG4gIGZvciAobGV0IHZhbCBvZiBzZXQxLnNldCkge1xuICAgIGlmIChfbWVtYmVyX19xbWFya19fKHNldDIsIHZhbCkpIHtcbiAgICAgIG5ld19tYXAuc2V0ID0gTGlzdC5kZWxldGUobmV3X21hcC5zZXQsIHZhbCk7XG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIFNwZWNpYWxGb3Jtcy5tYXAobmV3X21hcCk7XG59XG5cbmZ1bmN0aW9uIF9pbnRlcnNlY3Rpb24oc2V0MSwgc2V0Mikge1xuICBsZXQgbmV3X21hcCA9IE9iamVjdC5hc3NpZ24oe30sIHNldDEpO1xuXG4gIGZvciAobGV0IHZhbCBvZiBzZXQxLnNldCkge1xuICAgIGlmICghX21lbWJlcl9fcW1hcmtfXyhzZXQyLCB2YWwpKSB7XG4gICAgICBuZXdfbWFwLnNldCA9IExpc3QuZGVsZXRlKG5ld19tYXAuc2V0LCB2YWwpO1xuICAgIH1cbiAgfVxuXG4gIHJldHVybiBTcGVjaWFsRm9ybXMubWFwKG5ld19tYXApO1xufVxuXG5mdW5jdGlvbiBfdW5pb24oc2V0MSwgc2V0Mikge1xuICBsZXQgbmV3X21hcCA9IHNldDE7XG5cbiAgZm9yIChsZXQgdmFsIG9mIHNldDIuc2V0KSB7XG4gICAgbmV3X21hcCA9IF9wdXQobmV3X21hcCwgdmFsKTtcbiAgfVxuXG4gIHJldHVybiBTcGVjaWFsRm9ybXMubWFwKG5ld19tYXApO1xufVxuXG5mdW5jdGlvbiBfZGlzam9pbl9fcW1hcmtfXyhzZXQxLCBzZXQyKSB7XG4gIGZvciAobGV0IHZhbCBvZiBzZXQxLnNldCkge1xuICAgIGlmIChfbWVtYmVyX19xbWFya19fKHNldDIsIHZhbCkpIHtcbiAgICAgIHJldHVybiBmYWxzZTtcbiAgICB9XG4gIH1cblxuICByZXR1cm4gdHJ1ZTtcbn1cblxuZnVuY3Rpb24gX21lbWJlcl9fcW1hcmtfXyhzZXQsIHZhbHVlKSB7XG4gIHJldHVybiBzZXQuc2V0LmluZGV4T2YodmFsdWUpID49IDA7XG59XG5cbmZ1bmN0aW9uIF9lcXVhbF9fcW1hcmtfXyhzZXQxLCBzZXQyKSB7XG4gIHJldHVybiBzZXQxLnNldCA9PT0gc2V0Mi5zZXQ7XG59XG5cbmZ1bmN0aW9uIF9zdWJzZXRfX3FtYXJrX18oc2V0MSwgc2V0Mikge1xuICBmb3IgKGxldCB2YWwgb2Ygc2V0MS5zZXQpIHtcbiAgICBpZiAoIV9tZW1iZXJfX3FtYXJrX18oc2V0MiwgdmFsKSkge1xuICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH1cbiAgfVxuXG4gIHJldHVybiB0cnVlO1xufVxuXG52YXIgTWFwU2V0ID0ge1xuICBuZXc6IF9fbmV3X18sXG4gIHNpemU6IF9zaXplLFxuICB0b19saXN0OiBfdG9fbGlzdCxcbiAgZGlzam9pbl9fcW1hcmtfXzogX2Rpc2pvaW5fX3FtYXJrX18sXG4gIGRlbGV0ZTogX19fZGVsZXRlX18sXG4gIHN1YnNldF9fcW1hcmtfXzogX3N1YnNldF9fcW1hcmtfXyxcbiAgZXF1YWxfX3FtYXJrX186IF9lcXVhbF9fcW1hcmtfXyxcbiAgbWVtYmVyX19xbWFya19fOiBfbWVtYmVyX19xbWFya19fLFxuICBwdXQ6IF9wdXQsXG4gIHVuaW9uOiBfdW5pb24sXG4gIGludGVyc2VjdGlvbjogX2ludGVyc2VjdGlvbixcbiAgZGlmZmVyZW5jZTogX2RpZmZlcmVuY2Vcbn07XG5cbmZ1bmN0aW9uIHNpemUobWFwKSB7XG4gIHJldHVybiBNYXBTZXQuc2l6ZShtYXApO1xufVxuXG5mdW5jdGlvbiB0b19saXN0KG1hcCkge1xuICByZXR1cm4gTWFwU2V0LnRvX2xpc3QobWFwKTtcbn1cblxuZnVuY3Rpb24gX19kZWxldGVfXyhzZXQsIHRlcm0pIHtcbiAgcmV0dXJuIE1hcFNldC5kZWxldGUoc2V0LCB0ZXJtKTtcbn1cblxuZnVuY3Rpb24gcHV0KHNldCwgdGVybSkge1xuICByZXR1cm4gTWFwU2V0LnB1dChzZXQsIHRlcm0pO1xufVxuXG5mdW5jdGlvbiBkaWZmZXJlbmNlKHNldDEsIHNldDIpIHtcbiAgcmV0dXJuIE1hcFNldC5kaWZmZXJlbmNlKHNldDEsIHNldDIpO1xufVxuXG5mdW5jdGlvbiBpbnRlcnNlY3Rpb24oc2V0MSwgc2V0Mikge1xuICByZXR1cm4gTWFwU2V0LmludGVyc2VjdGlvbihzZXQxLCBzZXQyKTtcbn1cblxuZnVuY3Rpb24gdW5pb24oc2V0MSwgc2V0Mikge1xuICByZXR1cm4gTWFwU2V0LnVuaW9uKHNldDEsIHNldDIpO1xufVxuXG5mdW5jdGlvbiBkaXNqb2luX19xbWFya19fKHNldDEsIHNldDIpIHtcbiAgcmV0dXJuIE1hcFNldC5kaXNqb2luX19xbWFya19fKHNldDEsIHNldDIpO1xufVxuXG5mdW5jdGlvbiBtZW1iZXJfX3FtYXJrX18oc2V0LCB2YWx1ZSkge1xuICByZXR1cm4gTWFwU2V0Lm1lbWJlcl9fcW1hcmtfXyhzZXQxLCBzZXQyKTtcbn1cblxuZnVuY3Rpb24gZXF1YWxfX3FtYXJrX18oc2V0MSwgc2V0Mikge1xuICByZXR1cm4gTWFwU2V0LmVxdWFsX19xbWFya19fKHNldDEsIHNldDIpO1xufVxuXG5mdW5jdGlvbiBzdWJzZXRfX3FtYXJrX18oc2V0MSwgc2V0Mikge1xuICByZXR1cm4gTWFwU2V0LnN1YnNldF9fcW1hcmtfXyhzZXQxLCBzZXQyKTtcbn1cblxudmFyIF9TZXQgPSB7XG4gIHNpemUsXG4gIHRvX2xpc3QsXG4gIGRpc2pvaW5fX3FtYXJrX18sXG4gIGRlbGV0ZTogX19kZWxldGVfXyxcbiAgc3Vic2V0X19xbWFya19fLFxuICBlcXVhbF9fcW1hcmtfXyxcbiAgbWVtYmVyX19xbWFya19fLFxuICBwdXQsXG4gIHVuaW9uLFxuICBpbnRlcnNlY3Rpb24sXG4gIGRpZmZlcmVuY2Vcbn07XG5cbmxldCB2aXJ0dWFsRG9tID0gKGZ1bmN0aW9uIChlKSB7XG4gICAgcmV0dXJuIGUoKTtcbn0pKGZ1bmN0aW9uICgpIHtcbiAgICB2YXIgZGVmaW5lLCBtb2R1bGUsIGV4cG9ydHM7XG4gICAgcmV0dXJuIChmdW5jdGlvbiBlKHQsIG4sIHIpIHtcbiAgICAgICAgZnVuY3Rpb24gcyhvLCB1KSB7XG4gICAgICAgICAgICBpZiAoIW5bb10pIHtcbiAgICAgICAgICAgICAgICBpZiAoIXRbb10pIHtcbiAgICAgICAgICAgICAgICAgICAgdmFyIGEgPSB0eXBlb2YgcmVxdWlyZSA9PSBcImZ1bmN0aW9uXCIgJiYgcmVxdWlyZTtcbiAgICAgICAgICAgICAgICAgICAgaWYgKCF1ICYmIGEpIHJldHVybiBhKG8sICEwKTtcbiAgICAgICAgICAgICAgICAgICAgaWYgKGkpIHJldHVybiBpKG8sICEwKTtcbiAgICAgICAgICAgICAgICAgICAgdmFyIGYgPSBuZXcgRXJyb3IoXCJDYW5ub3QgZmluZCBtb2R1bGUgJ1wiICsgbyArIFwiJ1wiKTtcbiAgICAgICAgICAgICAgICAgICAgdGhyb3cgKGYuY29kZSA9IFwiTU9EVUxFX05PVF9GT1VORFwiLCBmKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgdmFyIGwgPSBuW29dID0ge1xuICAgICAgICAgICAgICAgICAgICBleHBvcnRzOiB7fVxuICAgICAgICAgICAgICAgIH07XG4gICAgICAgICAgICAgICAgdFtvXVswXS5jYWxsKGwuZXhwb3J0cywgZnVuY3Rpb24gKGUpIHtcbiAgICAgICAgICAgICAgICAgICAgdmFyIG4gPSB0W29dWzFdW2VdO1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gcyhuID8gbiA6IGUpO1xuICAgICAgICAgICAgICAgIH0sIGwsIGwuZXhwb3J0cywgZSwgdCwgbiwgcik7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXR1cm4gbltvXS5leHBvcnRzO1xuICAgICAgICB9XG4gICAgICAgIHZhciBpID0gdHlwZW9mIHJlcXVpcmUgPT0gXCJmdW5jdGlvblwiICYmIHJlcXVpcmU7XG4gICAgICAgIGZvciAodmFyIG8gPSAwOyBvIDwgci5sZW5ndGg7IG8rKykgcyhyW29dKTtcbiAgICAgICAgcmV0dXJuIHM7XG4gICAgfSkoe1xuICAgICAgICAxOiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge1xuXG4gICAgICAgICAgICB2YXIgY3JlYXRlRWxlbWVudCA9IHJlcXVpcmUoXCIuL3Zkb20vY3JlYXRlLWVsZW1lbnQuanNcIik7XG5cbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gY3JlYXRlRWxlbWVudDtcbiAgICAgICAgfSwgeyBcIi4vdmRvbS9jcmVhdGUtZWxlbWVudC5qc1wiOiAxNSB9XSwgMjogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHtcbiAgICAgICAgICAgIHZhciBkaWZmID0gcmVxdWlyZShcIi4vdnRyZWUvZGlmZi5qc1wiKTtcblxuICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBkaWZmO1xuICAgICAgICB9LCB7IFwiLi92dHJlZS9kaWZmLmpzXCI6IDM1IH1dLCAzOiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge1xuICAgICAgICAgICAgdmFyIGggPSByZXF1aXJlKFwiLi92aXJ0dWFsLWh5cGVyc2NyaXB0L2luZGV4LmpzXCIpO1xuXG4gICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IGg7XG4gICAgICAgIH0sIHsgXCIuL3ZpcnR1YWwtaHlwZXJzY3JpcHQvaW5kZXguanNcIjogMjIgfV0sIDQ6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICB2YXIgZGlmZiA9IHJlcXVpcmUoXCIuL2RpZmYuanNcIik7XG4gICAgICAgICAgICB2YXIgcGF0Y2ggPSByZXF1aXJlKFwiLi9wYXRjaC5qc1wiKTtcbiAgICAgICAgICAgIHZhciBoID0gcmVxdWlyZShcIi4vaC5qc1wiKTtcbiAgICAgICAgICAgIHZhciBjcmVhdGUgPSByZXF1aXJlKFwiLi9jcmVhdGUtZWxlbWVudC5qc1wiKTtcbiAgICAgICAgICAgIHZhciBWTm9kZSA9IHJlcXVpcmUoXCIuL3Zub2RlL3Zub2RlLmpzXCIpO1xuICAgICAgICAgICAgdmFyIFZUZXh0ID0gcmVxdWlyZShcIi4vdm5vZGUvdnRleHQuanNcIik7XG5cbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0ge1xuICAgICAgICAgICAgICAgIGRpZmY6IGRpZmYsXG4gICAgICAgICAgICAgICAgcGF0Y2g6IHBhdGNoLFxuICAgICAgICAgICAgICAgIGg6IGgsXG4gICAgICAgICAgICAgICAgY3JlYXRlOiBjcmVhdGUsXG4gICAgICAgICAgICAgICAgVk5vZGU6IFZOb2RlLFxuICAgICAgICAgICAgICAgIFZUZXh0OiBWVGV4dFxuICAgICAgICAgICAgfTtcbiAgICAgICAgfSwgeyBcIi4vY3JlYXRlLWVsZW1lbnQuanNcIjogMSwgXCIuL2RpZmYuanNcIjogMiwgXCIuL2guanNcIjogMywgXCIuL3BhdGNoLmpzXCI6IDEzLCBcIi4vdm5vZGUvdm5vZGUuanNcIjogMzEsIFwiLi92bm9kZS92dGV4dC5qc1wiOiAzMyB9XSwgNTogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHtcbiAgICAgICAgICAgIC8qIVxuICAgICAgICAgICAgICogQ3Jvc3MtQnJvd3NlciBTcGxpdCAxLjEuMVxuICAgICAgICAgICAgICogQ29weXJpZ2h0IDIwMDctMjAxMiBTdGV2ZW4gTGV2aXRoYW4gPHN0ZXZlbmxldml0aGFuLmNvbT5cbiAgICAgICAgICAgICAqIEF2YWlsYWJsZSB1bmRlciB0aGUgTUlUIExpY2Vuc2VcbiAgICAgICAgICAgICAqIEVDTUFTY3JpcHQgY29tcGxpYW50LCB1bmlmb3JtIGNyb3NzLWJyb3dzZXIgc3BsaXQgbWV0aG9kXG4gICAgICAgICAgICAgKi9cblxuICAgICAgICAgICAgLyoqXG4gICAgICAgICAgICAgKiBTcGxpdHMgYSBzdHJpbmcgaW50byBhbiBhcnJheSBvZiBzdHJpbmdzIHVzaW5nIGEgcmVnZXggb3Igc3RyaW5nIHNlcGFyYXRvci4gTWF0Y2hlcyBvZiB0aGVcbiAgICAgICAgICAgICAqIHNlcGFyYXRvciBhcmUgbm90IGluY2x1ZGVkIGluIHRoZSByZXN1bHQgYXJyYXkuIEhvd2V2ZXIsIGlmIGBzZXBhcmF0b3JgIGlzIGEgcmVnZXggdGhhdCBjb250YWluc1xuICAgICAgICAgICAgICogY2FwdHVyaW5nIGdyb3VwcywgYmFja3JlZmVyZW5jZXMgYXJlIHNwbGljZWQgaW50byB0aGUgcmVzdWx0IGVhY2ggdGltZSBgc2VwYXJhdG9yYCBpcyBtYXRjaGVkLlxuICAgICAgICAgICAgICogRml4ZXMgYnJvd3NlciBidWdzIGNvbXBhcmVkIHRvIHRoZSBuYXRpdmUgYFN0cmluZy5wcm90b3R5cGUuc3BsaXRgIGFuZCBjYW4gYmUgdXNlZCByZWxpYWJseVxuICAgICAgICAgICAgICogY3Jvc3MtYnJvd3Nlci5cbiAgICAgICAgICAgICAqIEBwYXJhbSB7U3RyaW5nfSBzdHIgU3RyaW5nIHRvIHNwbGl0LlxuICAgICAgICAgICAgICogQHBhcmFtIHtSZWdFeHB8U3RyaW5nfSBzZXBhcmF0b3IgUmVnZXggb3Igc3RyaW5nIHRvIHVzZSBmb3Igc2VwYXJhdGluZyB0aGUgc3RyaW5nLlxuICAgICAgICAgICAgICogQHBhcmFtIHtOdW1iZXJ9IFtsaW1pdF0gTWF4aW11bSBudW1iZXIgb2YgaXRlbXMgdG8gaW5jbHVkZSBpbiB0aGUgcmVzdWx0IGFycmF5LlxuICAgICAgICAgICAgICogQHJldHVybnMge0FycmF5fSBBcnJheSBvZiBzdWJzdHJpbmdzLlxuICAgICAgICAgICAgICogQGV4YW1wbGVcbiAgICAgICAgICAgICAqXG4gICAgICAgICAgICAgKiAvLyBCYXNpYyB1c2VcbiAgICAgICAgICAgICAqIHNwbGl0KCdhIGIgYyBkJywgJyAnKTtcbiAgICAgICAgICAgICAqIC8vIC0+IFsnYScsICdiJywgJ2MnLCAnZCddXG4gICAgICAgICAgICAgKlxuICAgICAgICAgICAgICogLy8gV2l0aCBsaW1pdFxuICAgICAgICAgICAgICogc3BsaXQoJ2EgYiBjIGQnLCAnICcsIDIpO1xuICAgICAgICAgICAgICogLy8gLT4gWydhJywgJ2InXVxuICAgICAgICAgICAgICpcbiAgICAgICAgICAgICAqIC8vIEJhY2tyZWZlcmVuY2VzIGluIHJlc3VsdCBhcnJheVxuICAgICAgICAgICAgICogc3BsaXQoJy4ud29yZDEgd29yZDIuLicsIC8oW2Etel0rKShcXGQrKS9pKTtcbiAgICAgICAgICAgICAqIC8vIC0+IFsnLi4nLCAnd29yZCcsICcxJywgJyAnLCAnd29yZCcsICcyJywgJy4uJ11cbiAgICAgICAgICAgICAqL1xuICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSAoZnVuY3Rpb24gc3BsaXQodW5kZWYpIHtcblxuICAgICAgICAgICAgICAgIHZhciBuYXRpdmVTcGxpdCA9IFN0cmluZy5wcm90b3R5cGUuc3BsaXQsXG4gICAgICAgICAgICAgICAgICAgIGNvbXBsaWFudEV4ZWNOcGNnID0gLygpPz8vLmV4ZWMoXCJcIilbMV0gPT09IHVuZGVmLFxuXG4gICAgICAgICAgICAgICAgLy8gTlBDRzogbm9ucGFydGljaXBhdGluZyBjYXB0dXJpbmcgZ3JvdXBcbiAgICAgICAgICAgICAgICBzZWxmO1xuXG4gICAgICAgICAgICAgICAgc2VsZiA9IGZ1bmN0aW9uIChzdHIsIHNlcGFyYXRvciwgbGltaXQpIHtcbiAgICAgICAgICAgICAgICAgICAgLy8gSWYgYHNlcGFyYXRvcmAgaXMgbm90IGEgcmVnZXgsIHVzZSBgbmF0aXZlU3BsaXRgXG4gICAgICAgICAgICAgICAgICAgIGlmIChPYmplY3QucHJvdG90eXBlLnRvU3RyaW5nLmNhbGwoc2VwYXJhdG9yKSAhPT0gXCJbb2JqZWN0IFJlZ0V4cF1cIikge1xuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIG5hdGl2ZVNwbGl0LmNhbGwoc3RyLCBzZXBhcmF0b3IsIGxpbWl0KTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB2YXIgb3V0cHV0ID0gW10sXG4gICAgICAgICAgICAgICAgICAgICAgICBmbGFncyA9IChzZXBhcmF0b3IuaWdub3JlQ2FzZSA/IFwiaVwiIDogXCJcIikgKyAoc2VwYXJhdG9yLm11bHRpbGluZSA/IFwibVwiIDogXCJcIikgKyAoc2VwYXJhdG9yLmV4dGVuZGVkID8gXCJ4XCIgOiBcIlwiKSArIChzZXBhcmF0b3Iuc3RpY2t5ID8gXCJ5XCIgOiBcIlwiKSxcblxuICAgICAgICAgICAgICAgICAgICAvLyBGaXJlZm94IDMrXG4gICAgICAgICAgICAgICAgICAgIGxhc3RMYXN0SW5kZXggPSAwLFxuXG4gICAgICAgICAgICAgICAgICAgIC8vIE1ha2UgYGdsb2JhbGAgYW5kIGF2b2lkIGBsYXN0SW5kZXhgIGlzc3VlcyBieSB3b3JraW5nIHdpdGggYSBjb3B5XG4gICAgICAgICAgICAgICAgICAgIHNlcGFyYXRvciA9IG5ldyBSZWdFeHAoc2VwYXJhdG9yLnNvdXJjZSwgZmxhZ3MgKyBcImdcIiksXG4gICAgICAgICAgICAgICAgICAgICAgICBzZXBhcmF0b3IyLFxuICAgICAgICAgICAgICAgICAgICAgICAgbWF0Y2gsXG4gICAgICAgICAgICAgICAgICAgICAgICBsYXN0SW5kZXgsXG4gICAgICAgICAgICAgICAgICAgICAgICBsYXN0TGVuZ3RoO1xuICAgICAgICAgICAgICAgICAgICBzdHIgKz0gXCJcIjsgLy8gVHlwZS1jb252ZXJ0XG4gICAgICAgICAgICAgICAgICAgIGlmICghY29tcGxpYW50RXhlY05wY2cpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIERvZXNuJ3QgbmVlZCBmbGFncyBneSwgYnV0IHRoZXkgZG9uJ3QgaHVydFxuICAgICAgICAgICAgICAgICAgICAgICAgc2VwYXJhdG9yMiA9IG5ldyBSZWdFeHAoXCJeXCIgKyBzZXBhcmF0b3Iuc291cmNlICsgXCIkKD8hXFxcXHMpXCIsIGZsYWdzKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAvKiBWYWx1ZXMgZm9yIGBsaW1pdGAsIHBlciB0aGUgc3BlYzpcbiAgICAgICAgICAgICAgICAgICAgICogSWYgdW5kZWZpbmVkOiA0Mjk0OTY3Mjk1IC8vIE1hdGgucG93KDIsIDMyKSAtIDFcbiAgICAgICAgICAgICAgICAgICAgICogSWYgMCwgSW5maW5pdHksIG9yIE5hTjogMFxuICAgICAgICAgICAgICAgICAgICAgKiBJZiBwb3NpdGl2ZSBudW1iZXI6IGxpbWl0ID0gTWF0aC5mbG9vcihsaW1pdCk7IGlmIChsaW1pdCA+IDQyOTQ5NjcyOTUpIGxpbWl0IC09IDQyOTQ5NjcyOTY7XG4gICAgICAgICAgICAgICAgICAgICAqIElmIG5lZ2F0aXZlIG51bWJlcjogNDI5NDk2NzI5NiAtIE1hdGguZmxvb3IoTWF0aC5hYnMobGltaXQpKVxuICAgICAgICAgICAgICAgICAgICAgKiBJZiBvdGhlcjogVHlwZS1jb252ZXJ0LCB0aGVuIHVzZSB0aGUgYWJvdmUgcnVsZXNcbiAgICAgICAgICAgICAgICAgICAgICovXG4gICAgICAgICAgICAgICAgICAgIGxpbWl0ID0gbGltaXQgPT09IHVuZGVmID8gLTEgPj4+IDAgOiAvLyBNYXRoLnBvdygyLCAzMikgLSAxXG4gICAgICAgICAgICAgICAgICAgIGxpbWl0ID4+PiAwOyAvLyBUb1VpbnQzMihsaW1pdClcbiAgICAgICAgICAgICAgICAgICAgd2hpbGUgKG1hdGNoID0gc2VwYXJhdG9yLmV4ZWMoc3RyKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgLy8gYHNlcGFyYXRvci5sYXN0SW5kZXhgIGlzIG5vdCByZWxpYWJsZSBjcm9zcy1icm93c2VyXG4gICAgICAgICAgICAgICAgICAgICAgICBsYXN0SW5kZXggPSBtYXRjaC5pbmRleCArIG1hdGNoWzBdLmxlbmd0aDtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChsYXN0SW5kZXggPiBsYXN0TGFzdEluZGV4KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgb3V0cHV0LnB1c2goc3RyLnNsaWNlKGxhc3RMYXN0SW5kZXgsIG1hdGNoLmluZGV4KSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gRml4IGJyb3dzZXJzIHdob3NlIGBleGVjYCBtZXRob2RzIGRvbid0IGNvbnNpc3RlbnRseSByZXR1cm4gYHVuZGVmaW5lZGAgZm9yXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gbm9ucGFydGljaXBhdGluZyBjYXB0dXJpbmcgZ3JvdXBzXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKCFjb21wbGlhbnRFeGVjTnBjZyAmJiBtYXRjaC5sZW5ndGggPiAxKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1hdGNoWzBdLnJlcGxhY2Uoc2VwYXJhdG9yMiwgZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZm9yICh2YXIgaSA9IDE7IGkgPCBhcmd1bWVudHMubGVuZ3RoIC0gMjsgaSsrKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGFyZ3VtZW50c1tpXSA9PT0gdW5kZWYpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbWF0Y2hbaV0gPSB1bmRlZjtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAobWF0Y2gubGVuZ3RoID4gMSAmJiBtYXRjaC5pbmRleCA8IHN0ci5sZW5ndGgpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgQXJyYXkucHJvdG90eXBlLnB1c2guYXBwbHkob3V0cHV0LCBtYXRjaC5zbGljZSgxKSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxhc3RMZW5ndGggPSBtYXRjaFswXS5sZW5ndGg7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgbGFzdExhc3RJbmRleCA9IGxhc3RJbmRleDtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAob3V0cHV0Lmxlbmd0aCA+PSBsaW1pdCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoc2VwYXJhdG9yLmxhc3RJbmRleCA9PT0gbWF0Y2guaW5kZXgpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBzZXBhcmF0b3IubGFzdEluZGV4Kys7IC8vIEF2b2lkIGFuIGluZmluaXRlIGxvb3BcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICBpZiAobGFzdExhc3RJbmRleCA9PT0gc3RyLmxlbmd0aCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGxhc3RMZW5ndGggfHwgIXNlcGFyYXRvci50ZXN0KFwiXCIpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgb3V0cHV0LnB1c2goXCJcIik7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBvdXRwdXQucHVzaChzdHIuc2xpY2UobGFzdExhc3RJbmRleCkpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBvdXRwdXQubGVuZ3RoID4gbGltaXQgPyBvdXRwdXQuc2xpY2UoMCwgbGltaXQpIDogb3V0cHV0O1xuICAgICAgICAgICAgICAgIH07XG5cbiAgICAgICAgICAgICAgICByZXR1cm4gc2VsZjtcbiAgICAgICAgICAgIH0pKCk7XG4gICAgICAgIH0sIHt9XSwgNjogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHt9LCB7fV0sIDc6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICBcInVzZSBzdHJpY3RcIjtcblxuICAgICAgICAgICAgdmFyIE9uZVZlcnNpb25Db25zdHJhaW50ID0gcmVxdWlyZShcImluZGl2aWR1YWwvb25lLXZlcnNpb25cIik7XG5cbiAgICAgICAgICAgIHZhciBNWV9WRVJTSU9OID0gXCI3XCI7XG4gICAgICAgICAgICBPbmVWZXJzaW9uQ29uc3RyYWludChcImV2LXN0b3JlXCIsIE1ZX1ZFUlNJT04pO1xuXG4gICAgICAgICAgICB2YXIgaGFzaEtleSA9IFwiX19FVl9TVE9SRV9LRVlAXCIgKyBNWV9WRVJTSU9OO1xuXG4gICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IEV2U3RvcmU7XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIEV2U3RvcmUoZWxlbSkge1xuICAgICAgICAgICAgICAgIHZhciBoYXNoID0gZWxlbVtoYXNoS2V5XTtcblxuICAgICAgICAgICAgICAgIGlmICghaGFzaCkge1xuICAgICAgICAgICAgICAgICAgICBoYXNoID0gZWxlbVtoYXNoS2V5XSA9IHt9O1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHJldHVybiBoYXNoO1xuICAgICAgICAgICAgfVxuICAgICAgICB9LCB7IFwiaW5kaXZpZHVhbC9vbmUtdmVyc2lvblwiOiA5IH1dLCA4OiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge1xuICAgICAgICAgICAgKGZ1bmN0aW9uIChnbG9iYWwpIHtcbiAgICAgICAgICAgICAgICBcInVzZSBzdHJpY3RcIjtcblxuICAgICAgICAgICAgICAgIC8qZ2xvYmFsIHdpbmRvdywgZ2xvYmFsKi9cblxuICAgICAgICAgICAgICAgIHZhciByb290ID0gdHlwZW9mIHdpbmRvdyAhPT0gXCJ1bmRlZmluZWRcIiA/IHdpbmRvdyA6IHR5cGVvZiBnbG9iYWwgIT09IFwidW5kZWZpbmVkXCIgPyBnbG9iYWwgOiB7fTtcblxuICAgICAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gSW5kaXZpZHVhbDtcblxuICAgICAgICAgICAgICAgIGZ1bmN0aW9uIEluZGl2aWR1YWwoa2V5LCB2YWx1ZSkge1xuICAgICAgICAgICAgICAgICAgICBpZiAoa2V5IGluIHJvb3QpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiByb290W2tleV07XG4gICAgICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgICAgICByb290W2tleV0gPSB2YWx1ZTtcblxuICAgICAgICAgICAgICAgICAgICByZXR1cm4gdmFsdWU7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSkuY2FsbCh0aGlzLCB0eXBlb2YgZ2xvYmFsICE9PSBcInVuZGVmaW5lZFwiID8gZ2xvYmFsIDogdHlwZW9mIHNlbGYgIT09IFwidW5kZWZpbmVkXCIgPyBzZWxmIDogdHlwZW9mIHdpbmRvdyAhPT0gXCJ1bmRlZmluZWRcIiA/IHdpbmRvdyA6IHt9KTtcbiAgICAgICAgfSwge31dLCA5OiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge1xuICAgICAgICAgICAgXCJ1c2Ugc3RyaWN0XCI7XG5cbiAgICAgICAgICAgIHZhciBJbmRpdmlkdWFsID0gcmVxdWlyZShcIi4vaW5kZXguanNcIik7XG5cbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gT25lVmVyc2lvbjtcblxuICAgICAgICAgICAgZnVuY3Rpb24gT25lVmVyc2lvbihtb2R1bGVOYW1lLCB2ZXJzaW9uLCBkZWZhdWx0VmFsdWUpIHtcbiAgICAgICAgICAgICAgICB2YXIga2V5ID0gXCJfX0lORElWSURVQUxfT05FX1ZFUlNJT05fXCIgKyBtb2R1bGVOYW1lO1xuICAgICAgICAgICAgICAgIHZhciBlbmZvcmNlS2V5ID0ga2V5ICsgXCJfRU5GT1JDRV9TSU5HTEVUT05cIjtcblxuICAgICAgICAgICAgICAgIHZhciB2ZXJzaW9uVmFsdWUgPSBJbmRpdmlkdWFsKGVuZm9yY2VLZXksIHZlcnNpb24pO1xuXG4gICAgICAgICAgICAgICAgaWYgKHZlcnNpb25WYWx1ZSAhPT0gdmVyc2lvbikge1xuICAgICAgICAgICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoXCJDYW4gb25seSBoYXZlIG9uZSBjb3B5IG9mIFwiICsgbW9kdWxlTmFtZSArIFwiLlxcblwiICsgXCJZb3UgYWxyZWFkeSBoYXZlIHZlcnNpb24gXCIgKyB2ZXJzaW9uVmFsdWUgKyBcIiBpbnN0YWxsZWQuXFxuXCIgKyBcIlRoaXMgbWVhbnMgeW91IGNhbm5vdCBpbnN0YWxsIHZlcnNpb24gXCIgKyB2ZXJzaW9uKTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICByZXR1cm4gSW5kaXZpZHVhbChrZXksIGRlZmF1bHRWYWx1ZSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0sIHsgXCIuL2luZGV4LmpzXCI6IDggfV0sIDEwOiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge1xuICAgICAgICAgICAgKGZ1bmN0aW9uIChnbG9iYWwpIHtcbiAgICAgICAgICAgICAgICB2YXIgdG9wTGV2ZWwgPSB0eXBlb2YgZ2xvYmFsICE9PSBcInVuZGVmaW5lZFwiID8gZ2xvYmFsIDogdHlwZW9mIHdpbmRvdyAhPT0gXCJ1bmRlZmluZWRcIiA/IHdpbmRvdyA6IHt9O1xuICAgICAgICAgICAgICAgIHZhciBtaW5Eb2MgPSByZXF1aXJlKFwibWluLWRvY3VtZW50XCIpO1xuXG4gICAgICAgICAgICAgICAgaWYgKHR5cGVvZiBkb2N1bWVudCAhPT0gXCJ1bmRlZmluZWRcIikge1xuICAgICAgICAgICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IGRvY3VtZW50O1xuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciBkb2NjeSA9IHRvcExldmVsW1wiX19HTE9CQUxfRE9DVU1FTlRfQ0FDSEVANFwiXTtcblxuICAgICAgICAgICAgICAgICAgICBpZiAoIWRvY2N5KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBkb2NjeSA9IHRvcExldmVsW1wiX19HTE9CQUxfRE9DVU1FTlRfQ0FDSEVANFwiXSA9IG1pbkRvYztcbiAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gZG9jY3k7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSkuY2FsbCh0aGlzLCB0eXBlb2YgZ2xvYmFsICE9PSBcInVuZGVmaW5lZFwiID8gZ2xvYmFsIDogdHlwZW9mIHNlbGYgIT09IFwidW5kZWZpbmVkXCIgPyBzZWxmIDogdHlwZW9mIHdpbmRvdyAhPT0gXCJ1bmRlZmluZWRcIiA/IHdpbmRvdyA6IHt9KTtcbiAgICAgICAgfSwgeyBcIm1pbi1kb2N1bWVudFwiOiA2IH1dLCAxMTogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHtcbiAgICAgICAgICAgIFwidXNlIHN0cmljdFwiO1xuXG4gICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uIGlzT2JqZWN0KHgpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gdHlwZW9mIHggPT09IFwib2JqZWN0XCIgJiYgeCAhPT0gbnVsbDtcbiAgICAgICAgICAgIH07XG4gICAgICAgIH0sIHt9XSwgMTI6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICB2YXIgbmF0aXZlSXNBcnJheSA9IEFycmF5LmlzQXJyYXk7XG4gICAgICAgICAgICB2YXIgdG9TdHJpbmcgPSBPYmplY3QucHJvdG90eXBlLnRvU3RyaW5nO1xuXG4gICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IG5hdGl2ZUlzQXJyYXkgfHwgaXNBcnJheTtcblxuICAgICAgICAgICAgZnVuY3Rpb24gaXNBcnJheShvYmopIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gdG9TdHJpbmcuY2FsbChvYmopID09PSBcIltvYmplY3QgQXJyYXldXCI7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0sIHt9XSwgMTM6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICB2YXIgcGF0Y2ggPSByZXF1aXJlKFwiLi92ZG9tL3BhdGNoLmpzXCIpO1xuXG4gICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IHBhdGNoO1xuICAgICAgICB9LCB7IFwiLi92ZG9tL3BhdGNoLmpzXCI6IDE4IH1dLCAxNDogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHtcbiAgICAgICAgICAgIHZhciBpc09iamVjdCA9IHJlcXVpcmUoXCJpcy1vYmplY3RcIik7XG4gICAgICAgICAgICB2YXIgaXNIb29rID0gcmVxdWlyZShcIi4uL3Zub2RlL2lzLXZob29rLmpzXCIpO1xuXG4gICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IGFwcGx5UHJvcGVydGllcztcblxuICAgICAgICAgICAgZnVuY3Rpb24gYXBwbHlQcm9wZXJ0aWVzKG5vZGUsIHByb3BzLCBwcmV2aW91cykge1xuICAgICAgICAgICAgICAgIGZvciAodmFyIHByb3BOYW1lIGluIHByb3BzKSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciBwcm9wVmFsdWUgPSBwcm9wc1twcm9wTmFtZV07XG5cbiAgICAgICAgICAgICAgICAgICAgaWYgKHByb3BWYWx1ZSA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICByZW1vdmVQcm9wZXJ0eShub2RlLCBwcm9wTmFtZSwgcHJvcFZhbHVlLCBwcmV2aW91cyk7XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoaXNIb29rKHByb3BWYWx1ZSkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJlbW92ZVByb3BlcnR5KG5vZGUsIHByb3BOYW1lLCBwcm9wVmFsdWUsIHByZXZpb3VzKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChwcm9wVmFsdWUuaG9vaykge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHByb3BWYWx1ZS5ob29rKG5vZGUsIHByb3BOYW1lLCBwcmV2aW91cyA/IHByZXZpb3VzW3Byb3BOYW1lXSA6IHVuZGVmaW5lZCk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoaXNPYmplY3QocHJvcFZhbHVlKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHBhdGNoT2JqZWN0KG5vZGUsIHByb3BzLCBwcmV2aW91cywgcHJvcE5hbWUsIHByb3BWYWx1ZSk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIG5vZGVbcHJvcE5hbWVdID0gcHJvcFZhbHVlO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBmdW5jdGlvbiByZW1vdmVQcm9wZXJ0eShub2RlLCBwcm9wTmFtZSwgcHJvcFZhbHVlLCBwcmV2aW91cykge1xuICAgICAgICAgICAgICAgIGlmIChwcmV2aW91cykge1xuICAgICAgICAgICAgICAgICAgICB2YXIgcHJldmlvdXNWYWx1ZSA9IHByZXZpb3VzW3Byb3BOYW1lXTtcblxuICAgICAgICAgICAgICAgICAgICBpZiAoIWlzSG9vayhwcmV2aW91c1ZhbHVlKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHByb3BOYW1lID09PSBcImF0dHJpYnV0ZXNcIikge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZvciAodmFyIGF0dHJOYW1lIGluIHByZXZpb3VzVmFsdWUpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbm9kZS5yZW1vdmVBdHRyaWJ1dGUoYXR0ck5hbWUpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAocHJvcE5hbWUgPT09IFwic3R5bGVcIikge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZvciAodmFyIGkgaW4gcHJldmlvdXNWYWx1ZSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBub2RlLnN0eWxlW2ldID0gXCJcIjtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKHR5cGVvZiBwcmV2aW91c1ZhbHVlID09PSBcInN0cmluZ1wiKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgbm9kZVtwcm9wTmFtZV0gPSBcIlwiO1xuICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBub2RlW3Byb3BOYW1lXSA9IG51bGw7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAocHJldmlvdXNWYWx1ZS51bmhvb2spIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHByZXZpb3VzVmFsdWUudW5ob29rKG5vZGUsIHByb3BOYW1lLCBwcm9wVmFsdWUpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBmdW5jdGlvbiBwYXRjaE9iamVjdChub2RlLCBwcm9wcywgcHJldmlvdXMsIHByb3BOYW1lLCBwcm9wVmFsdWUpIHtcbiAgICAgICAgICAgICAgICB2YXIgcHJldmlvdXNWYWx1ZSA9IHByZXZpb3VzID8gcHJldmlvdXNbcHJvcE5hbWVdIDogdW5kZWZpbmVkO1xuXG4gICAgICAgICAgICAgICAgLy8gU2V0IGF0dHJpYnV0ZXNcbiAgICAgICAgICAgICAgICBpZiAocHJvcE5hbWUgPT09IFwiYXR0cmlidXRlc1wiKSB7XG4gICAgICAgICAgICAgICAgICAgIGZvciAodmFyIGF0dHJOYW1lIGluIHByb3BWYWx1ZSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgdmFyIGF0dHJWYWx1ZSA9IHByb3BWYWx1ZVthdHRyTmFtZV07XG5cbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChhdHRyVmFsdWUgPT09IHVuZGVmaW5lZCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIG5vZGUucmVtb3ZlQXR0cmlidXRlKGF0dHJOYW1lKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgbm9kZS5zZXRBdHRyaWJ1dGUoYXR0ck5hbWUsIGF0dHJWYWx1ZSk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgaWYgKHByZXZpb3VzVmFsdWUgJiYgaXNPYmplY3QocHJldmlvdXNWYWx1ZSkgJiYgZ2V0UHJvdG90eXBlKHByZXZpb3VzVmFsdWUpICE9PSBnZXRQcm90b3R5cGUocHJvcFZhbHVlKSkge1xuICAgICAgICAgICAgICAgICAgICBub2RlW3Byb3BOYW1lXSA9IHByb3BWYWx1ZTtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIGlmICghaXNPYmplY3Qobm9kZVtwcm9wTmFtZV0pKSB7XG4gICAgICAgICAgICAgICAgICAgIG5vZGVbcHJvcE5hbWVdID0ge307XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgdmFyIHJlcGxhY2VyID0gcHJvcE5hbWUgPT09IFwic3R5bGVcIiA/IFwiXCIgOiB1bmRlZmluZWQ7XG5cbiAgICAgICAgICAgICAgICBmb3IgKHZhciBrIGluIHByb3BWYWx1ZSkge1xuICAgICAgICAgICAgICAgICAgICB2YXIgdmFsdWUgPSBwcm9wVmFsdWVba107XG4gICAgICAgICAgICAgICAgICAgIG5vZGVbcHJvcE5hbWVdW2tdID0gdmFsdWUgPT09IHVuZGVmaW5lZCA/IHJlcGxhY2VyIDogdmFsdWU7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBmdW5jdGlvbiBnZXRQcm90b3R5cGUodmFsdWUpIHtcbiAgICAgICAgICAgICAgICBpZiAoT2JqZWN0LmdldFByb3RvdHlwZU9mKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBPYmplY3QuZ2V0UHJvdG90eXBlT2YodmFsdWUpO1xuICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAodmFsdWUuX19wcm90b19fKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiB2YWx1ZS5fX3Byb3RvX187XG4gICAgICAgICAgICAgICAgfSBlbHNlIGlmICh2YWx1ZS5jb25zdHJ1Y3Rvcikge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gdmFsdWUuY29uc3RydWN0b3IucHJvdG90eXBlO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgfSwgeyBcIi4uL3Zub2RlL2lzLXZob29rLmpzXCI6IDI2LCBcImlzLW9iamVjdFwiOiAxMSB9XSwgMTU6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICB2YXIgZG9jdW1lbnQgPSByZXF1aXJlKFwiZ2xvYmFsL2RvY3VtZW50XCIpO1xuXG4gICAgICAgICAgICB2YXIgYXBwbHlQcm9wZXJ0aWVzID0gcmVxdWlyZShcIi4vYXBwbHktcHJvcGVydGllc1wiKTtcblxuICAgICAgICAgICAgdmFyIGlzVk5vZGUgPSByZXF1aXJlKFwiLi4vdm5vZGUvaXMtdm5vZGUuanNcIik7XG4gICAgICAgICAgICB2YXIgaXNWVGV4dCA9IHJlcXVpcmUoXCIuLi92bm9kZS9pcy12dGV4dC5qc1wiKTtcbiAgICAgICAgICAgIHZhciBpc1dpZGdldCA9IHJlcXVpcmUoXCIuLi92bm9kZS9pcy13aWRnZXQuanNcIik7XG4gICAgICAgICAgICB2YXIgaGFuZGxlVGh1bmsgPSByZXF1aXJlKFwiLi4vdm5vZGUvaGFuZGxlLXRodW5rLmpzXCIpO1xuXG4gICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IGNyZWF0ZUVsZW1lbnQ7XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIGNyZWF0ZUVsZW1lbnQodm5vZGUsIG9wdHMpIHtcbiAgICAgICAgICAgICAgICB2YXIgZG9jID0gb3B0cyA/IG9wdHMuZG9jdW1lbnQgfHwgZG9jdW1lbnQgOiBkb2N1bWVudDtcbiAgICAgICAgICAgICAgICB2YXIgd2FybiA9IG9wdHMgPyBvcHRzLndhcm4gOiBudWxsO1xuXG4gICAgICAgICAgICAgICAgdm5vZGUgPSBoYW5kbGVUaHVuayh2bm9kZSkuYTtcblxuICAgICAgICAgICAgICAgIGlmIChpc1dpZGdldCh2bm9kZSkpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHZub2RlLmluaXQoKTtcbiAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKGlzVlRleHQodm5vZGUpKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBkb2MuY3JlYXRlVGV4dE5vZGUodm5vZGUudGV4dCk7XG4gICAgICAgICAgICAgICAgfSBlbHNlIGlmICghaXNWTm9kZSh2bm9kZSkpIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKHdhcm4pIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHdhcm4oXCJJdGVtIGlzIG5vdCBhIHZhbGlkIHZpcnR1YWwgZG9tIG5vZGVcIiwgdm5vZGUpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBudWxsO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHZhciBub2RlID0gdm5vZGUubmFtZXNwYWNlID09PSBudWxsID8gZG9jLmNyZWF0ZUVsZW1lbnQodm5vZGUudGFnTmFtZSkgOiBkb2MuY3JlYXRlRWxlbWVudE5TKHZub2RlLm5hbWVzcGFjZSwgdm5vZGUudGFnTmFtZSk7XG5cbiAgICAgICAgICAgICAgICB2YXIgcHJvcHMgPSB2bm9kZS5wcm9wZXJ0aWVzO1xuICAgICAgICAgICAgICAgIGFwcGx5UHJvcGVydGllcyhub2RlLCBwcm9wcyk7XG5cbiAgICAgICAgICAgICAgICB2YXIgY2hpbGRyZW4gPSB2bm9kZS5jaGlsZHJlbjtcblxuICAgICAgICAgICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgY2hpbGRyZW4ubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgICAgICAgICAgdmFyIGNoaWxkTm9kZSA9IGNyZWF0ZUVsZW1lbnQoY2hpbGRyZW5baV0sIG9wdHMpO1xuICAgICAgICAgICAgICAgICAgICBpZiAoY2hpbGROb2RlKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBub2RlLmFwcGVuZENoaWxkKGNoaWxkTm9kZSk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICByZXR1cm4gbm9kZTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSwgeyBcIi4uL3Zub2RlL2hhbmRsZS10aHVuay5qc1wiOiAyNCwgXCIuLi92bm9kZS9pcy12bm9kZS5qc1wiOiAyNywgXCIuLi92bm9kZS9pcy12dGV4dC5qc1wiOiAyOCwgXCIuLi92bm9kZS9pcy13aWRnZXQuanNcIjogMjksIFwiLi9hcHBseS1wcm9wZXJ0aWVzXCI6IDE0LCBcImdsb2JhbC9kb2N1bWVudFwiOiAxMCB9XSwgMTY6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICAvLyBNYXBzIGEgdmlydHVhbCBET00gdHJlZSBvbnRvIGEgcmVhbCBET00gdHJlZSBpbiBhbiBlZmZpY2llbnQgbWFubmVyLlxuICAgICAgICAgICAgLy8gV2UgZG9uJ3Qgd2FudCB0byByZWFkIGFsbCBvZiB0aGUgRE9NIG5vZGVzIGluIHRoZSB0cmVlIHNvIHdlIHVzZVxuICAgICAgICAgICAgLy8gdGhlIGluLW9yZGVyIHRyZWUgaW5kZXhpbmcgdG8gZWxpbWluYXRlIHJlY3Vyc2lvbiBkb3duIGNlcnRhaW4gYnJhbmNoZXMuXG4gICAgICAgICAgICAvLyBXZSBvbmx5IHJlY3Vyc2UgaW50byBhIERPTSBub2RlIGlmIHdlIGtub3cgdGhhdCBpdCBjb250YWlucyBhIGNoaWxkIG9mXG4gICAgICAgICAgICAvLyBpbnRlcmVzdC5cblxuICAgICAgICAgICAgdmFyIG5vQ2hpbGQgPSB7fTtcblxuICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBkb21JbmRleDtcblxuICAgICAgICAgICAgZnVuY3Rpb24gZG9tSW5kZXgocm9vdE5vZGUsIHRyZWUsIGluZGljZXMsIG5vZGVzKSB7XG4gICAgICAgICAgICAgICAgaWYgKCFpbmRpY2VzIHx8IGluZGljZXMubGVuZ3RoID09PSAwKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiB7fTtcbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICBpbmRpY2VzLnNvcnQoYXNjZW5kaW5nKTtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHJlY3Vyc2Uocm9vdE5vZGUsIHRyZWUsIGluZGljZXMsIG5vZGVzLCAwKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIHJlY3Vyc2Uocm9vdE5vZGUsIHRyZWUsIGluZGljZXMsIG5vZGVzLCByb290SW5kZXgpIHtcbiAgICAgICAgICAgICAgICBub2RlcyA9IG5vZGVzIHx8IHt9O1xuXG4gICAgICAgICAgICAgICAgaWYgKHJvb3ROb2RlKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmIChpbmRleEluUmFuZ2UoaW5kaWNlcywgcm9vdEluZGV4LCByb290SW5kZXgpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBub2Rlc1tyb290SW5kZXhdID0gcm9vdE5vZGU7XG4gICAgICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgICAgICB2YXIgdkNoaWxkcmVuID0gdHJlZS5jaGlsZHJlbjtcblxuICAgICAgICAgICAgICAgICAgICBpZiAodkNoaWxkcmVuKSB7XG5cbiAgICAgICAgICAgICAgICAgICAgICAgIHZhciBjaGlsZE5vZGVzID0gcm9vdE5vZGUuY2hpbGROb2RlcztcblxuICAgICAgICAgICAgICAgICAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCB0cmVlLmNoaWxkcmVuLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcm9vdEluZGV4ICs9IDE7XG5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB2YXIgdkNoaWxkID0gdkNoaWxkcmVuW2ldIHx8IG5vQ2hpbGQ7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdmFyIG5leHRJbmRleCA9IHJvb3RJbmRleCArICh2Q2hpbGQuY291bnQgfHwgMCk7XG5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBza2lwIHJlY3Vyc2lvbiBkb3duIHRoZSB0cmVlIGlmIHRoZXJlIGFyZSBubyBub2RlcyBkb3duIGhlcmVcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoaW5kZXhJblJhbmdlKGluZGljZXMsIHJvb3RJbmRleCwgbmV4dEluZGV4KSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICByZWN1cnNlKGNoaWxkTm9kZXNbaV0sIHZDaGlsZCwgaW5kaWNlcywgbm9kZXMsIHJvb3RJbmRleCk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcm9vdEluZGV4ID0gbmV4dEluZGV4O1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgcmV0dXJuIG5vZGVzO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAvLyBCaW5hcnkgc2VhcmNoIGZvciBhbiBpbmRleCBpbiB0aGUgaW50ZXJ2YWwgW2xlZnQsIHJpZ2h0XVxuICAgICAgICAgICAgZnVuY3Rpb24gaW5kZXhJblJhbmdlKGluZGljZXMsIGxlZnQsIHJpZ2h0KSB7XG4gICAgICAgICAgICAgICAgaWYgKGluZGljZXMubGVuZ3RoID09PSAwKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICB2YXIgbWluSW5kZXggPSAwO1xuICAgICAgICAgICAgICAgIHZhciBtYXhJbmRleCA9IGluZGljZXMubGVuZ3RoIC0gMTtcbiAgICAgICAgICAgICAgICB2YXIgY3VycmVudEluZGV4O1xuICAgICAgICAgICAgICAgIHZhciBjdXJyZW50SXRlbTtcblxuICAgICAgICAgICAgICAgIHdoaWxlIChtaW5JbmRleCA8PSBtYXhJbmRleCkge1xuICAgICAgICAgICAgICAgICAgICBjdXJyZW50SW5kZXggPSAobWF4SW5kZXggKyBtaW5JbmRleCkgLyAyID4+IDA7XG4gICAgICAgICAgICAgICAgICAgIGN1cnJlbnRJdGVtID0gaW5kaWNlc1tjdXJyZW50SW5kZXhdO1xuXG4gICAgICAgICAgICAgICAgICAgIGlmIChtaW5JbmRleCA9PT0gbWF4SW5kZXgpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBjdXJyZW50SXRlbSA+PSBsZWZ0ICYmIGN1cnJlbnRJdGVtIDw9IHJpZ2h0O1xuICAgICAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKGN1cnJlbnRJdGVtIDwgbGVmdCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgbWluSW5kZXggPSBjdXJyZW50SW5kZXggKyAxO1xuICAgICAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKGN1cnJlbnRJdGVtID4gcmlnaHQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIG1heEluZGV4ID0gY3VycmVudEluZGV4IC0gMTtcbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBmdW5jdGlvbiBhc2NlbmRpbmcoYSwgYikge1xuICAgICAgICAgICAgICAgIHJldHVybiBhID4gYiA/IDEgOiAtMTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSwge31dLCAxNzogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHtcbiAgICAgICAgICAgIHZhciBhcHBseVByb3BlcnRpZXMgPSByZXF1aXJlKFwiLi9hcHBseS1wcm9wZXJ0aWVzXCIpO1xuXG4gICAgICAgICAgICB2YXIgaXNXaWRnZXQgPSByZXF1aXJlKFwiLi4vdm5vZGUvaXMtd2lkZ2V0LmpzXCIpO1xuICAgICAgICAgICAgdmFyIFZQYXRjaCA9IHJlcXVpcmUoXCIuLi92bm9kZS92cGF0Y2guanNcIik7XG5cbiAgICAgICAgICAgIHZhciB1cGRhdGVXaWRnZXQgPSByZXF1aXJlKFwiLi91cGRhdGUtd2lkZ2V0XCIpO1xuXG4gICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IGFwcGx5UGF0Y2g7XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIGFwcGx5UGF0Y2godnBhdGNoLCBkb21Ob2RlLCByZW5kZXJPcHRpb25zKSB7XG4gICAgICAgICAgICAgICAgdmFyIHR5cGUgPSB2cGF0Y2gudHlwZTtcbiAgICAgICAgICAgICAgICB2YXIgdk5vZGUgPSB2cGF0Y2gudk5vZGU7XG4gICAgICAgICAgICAgICAgdmFyIHBhdGNoID0gdnBhdGNoLnBhdGNoO1xuXG4gICAgICAgICAgICAgICAgc3dpdGNoICh0eXBlKSB7XG4gICAgICAgICAgICAgICAgICAgIGNhc2UgVlBhdGNoLlJFTU9WRTpcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiByZW1vdmVOb2RlKGRvbU5vZGUsIHZOb2RlKTtcbiAgICAgICAgICAgICAgICAgICAgY2FzZSBWUGF0Y2guSU5TRVJUOlxuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGluc2VydE5vZGUoZG9tTm9kZSwgcGF0Y2gsIHJlbmRlck9wdGlvbnMpO1xuICAgICAgICAgICAgICAgICAgICBjYXNlIFZQYXRjaC5WVEVYVDpcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBzdHJpbmdQYXRjaChkb21Ob2RlLCB2Tm9kZSwgcGF0Y2gsIHJlbmRlck9wdGlvbnMpO1xuICAgICAgICAgICAgICAgICAgICBjYXNlIFZQYXRjaC5XSURHRVQ6XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gd2lkZ2V0UGF0Y2goZG9tTm9kZSwgdk5vZGUsIHBhdGNoLCByZW5kZXJPcHRpb25zKTtcbiAgICAgICAgICAgICAgICAgICAgY2FzZSBWUGF0Y2guVk5PREU6XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gdk5vZGVQYXRjaChkb21Ob2RlLCB2Tm9kZSwgcGF0Y2gsIHJlbmRlck9wdGlvbnMpO1xuICAgICAgICAgICAgICAgICAgICBjYXNlIFZQYXRjaC5PUkRFUjpcbiAgICAgICAgICAgICAgICAgICAgICAgIHJlb3JkZXJDaGlsZHJlbihkb21Ob2RlLCBwYXRjaCk7XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gZG9tTm9kZTtcbiAgICAgICAgICAgICAgICAgICAgY2FzZSBWUGF0Y2guUFJPUFM6XG4gICAgICAgICAgICAgICAgICAgICAgICBhcHBseVByb3BlcnRpZXMoZG9tTm9kZSwgcGF0Y2gsIHZOb2RlLnByb3BlcnRpZXMpO1xuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGRvbU5vZGU7XG4gICAgICAgICAgICAgICAgICAgIGNhc2UgVlBhdGNoLlRIVU5LOlxuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHJlcGxhY2VSb290KGRvbU5vZGUsIHJlbmRlck9wdGlvbnMucGF0Y2goZG9tTm9kZSwgcGF0Y2gsIHJlbmRlck9wdGlvbnMpKTtcbiAgICAgICAgICAgICAgICAgICAgZGVmYXVsdDpcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBkb21Ob2RlO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZnVuY3Rpb24gcmVtb3ZlTm9kZShkb21Ob2RlLCB2Tm9kZSkge1xuICAgICAgICAgICAgICAgIHZhciBwYXJlbnROb2RlID0gZG9tTm9kZS5wYXJlbnROb2RlO1xuXG4gICAgICAgICAgICAgICAgaWYgKHBhcmVudE5vZGUpIHtcbiAgICAgICAgICAgICAgICAgICAgcGFyZW50Tm9kZS5yZW1vdmVDaGlsZChkb21Ob2RlKTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICBkZXN0cm95V2lkZ2V0KGRvbU5vZGUsIHZOb2RlKTtcblxuICAgICAgICAgICAgICAgIHJldHVybiBudWxsO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBmdW5jdGlvbiBpbnNlcnROb2RlKHBhcmVudE5vZGUsIHZOb2RlLCByZW5kZXJPcHRpb25zKSB7XG4gICAgICAgICAgICAgICAgdmFyIG5ld05vZGUgPSByZW5kZXJPcHRpb25zLnJlbmRlcih2Tm9kZSwgcmVuZGVyT3B0aW9ucyk7XG5cbiAgICAgICAgICAgICAgICBpZiAocGFyZW50Tm9kZSkge1xuICAgICAgICAgICAgICAgICAgICBwYXJlbnROb2RlLmFwcGVuZENoaWxkKG5ld05vZGUpO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHJldHVybiBwYXJlbnROb2RlO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBmdW5jdGlvbiBzdHJpbmdQYXRjaChkb21Ob2RlLCBsZWZ0Vk5vZGUsIHZUZXh0LCByZW5kZXJPcHRpb25zKSB7XG4gICAgICAgICAgICAgICAgdmFyIG5ld05vZGU7XG5cbiAgICAgICAgICAgICAgICBpZiAoZG9tTm9kZS5ub2RlVHlwZSA9PT0gMykge1xuICAgICAgICAgICAgICAgICAgICBkb21Ob2RlLnJlcGxhY2VEYXRhKDAsIGRvbU5vZGUubGVuZ3RoLCB2VGV4dC50ZXh0KTtcbiAgICAgICAgICAgICAgICAgICAgbmV3Tm9kZSA9IGRvbU5vZGU7XG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgdmFyIHBhcmVudE5vZGUgPSBkb21Ob2RlLnBhcmVudE5vZGU7XG4gICAgICAgICAgICAgICAgICAgIG5ld05vZGUgPSByZW5kZXJPcHRpb25zLnJlbmRlcih2VGV4dCwgcmVuZGVyT3B0aW9ucyk7XG5cbiAgICAgICAgICAgICAgICAgICAgaWYgKHBhcmVudE5vZGUgJiYgbmV3Tm9kZSAhPT0gZG9tTm9kZSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgcGFyZW50Tm9kZS5yZXBsYWNlQ2hpbGQobmV3Tm9kZSwgZG9tTm9kZSk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICByZXR1cm4gbmV3Tm9kZTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZnVuY3Rpb24gd2lkZ2V0UGF0Y2goZG9tTm9kZSwgbGVmdFZOb2RlLCB3aWRnZXQsIHJlbmRlck9wdGlvbnMpIHtcbiAgICAgICAgICAgICAgICB2YXIgdXBkYXRpbmcgPSB1cGRhdGVXaWRnZXQobGVmdFZOb2RlLCB3aWRnZXQpO1xuICAgICAgICAgICAgICAgIHZhciBuZXdOb2RlO1xuXG4gICAgICAgICAgICAgICAgaWYgKHVwZGF0aW5nKSB7XG4gICAgICAgICAgICAgICAgICAgIG5ld05vZGUgPSB3aWRnZXQudXBkYXRlKGxlZnRWTm9kZSwgZG9tTm9kZSkgfHwgZG9tTm9kZTtcbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICBuZXdOb2RlID0gcmVuZGVyT3B0aW9ucy5yZW5kZXIod2lkZ2V0LCByZW5kZXJPcHRpb25zKTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICB2YXIgcGFyZW50Tm9kZSA9IGRvbU5vZGUucGFyZW50Tm9kZTtcblxuICAgICAgICAgICAgICAgIGlmIChwYXJlbnROb2RlICYmIG5ld05vZGUgIT09IGRvbU5vZGUpIHtcbiAgICAgICAgICAgICAgICAgICAgcGFyZW50Tm9kZS5yZXBsYWNlQ2hpbGQobmV3Tm9kZSwgZG9tTm9kZSk7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgaWYgKCF1cGRhdGluZykge1xuICAgICAgICAgICAgICAgICAgICBkZXN0cm95V2lkZ2V0KGRvbU5vZGUsIGxlZnRWTm9kZSk7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgcmV0dXJuIG5ld05vZGU7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIHZOb2RlUGF0Y2goZG9tTm9kZSwgbGVmdFZOb2RlLCB2Tm9kZSwgcmVuZGVyT3B0aW9ucykge1xuICAgICAgICAgICAgICAgIHZhciBwYXJlbnROb2RlID0gZG9tTm9kZS5wYXJlbnROb2RlO1xuICAgICAgICAgICAgICAgIHZhciBuZXdOb2RlID0gcmVuZGVyT3B0aW9ucy5yZW5kZXIodk5vZGUsIHJlbmRlck9wdGlvbnMpO1xuXG4gICAgICAgICAgICAgICAgaWYgKHBhcmVudE5vZGUgJiYgbmV3Tm9kZSAhPT0gZG9tTm9kZSkge1xuICAgICAgICAgICAgICAgICAgICBwYXJlbnROb2RlLnJlcGxhY2VDaGlsZChuZXdOb2RlLCBkb21Ob2RlKTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICByZXR1cm4gbmV3Tm9kZTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZnVuY3Rpb24gZGVzdHJveVdpZGdldChkb21Ob2RlLCB3KSB7XG4gICAgICAgICAgICAgICAgaWYgKHR5cGVvZiB3LmRlc3Ryb3kgPT09IFwiZnVuY3Rpb25cIiAmJiBpc1dpZGdldCh3KSkge1xuICAgICAgICAgICAgICAgICAgICB3LmRlc3Ryb3koZG9tTm9kZSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBmdW5jdGlvbiByZW9yZGVyQ2hpbGRyZW4oZG9tTm9kZSwgbW92ZXMpIHtcbiAgICAgICAgICAgICAgICB2YXIgY2hpbGROb2RlcyA9IGRvbU5vZGUuY2hpbGROb2RlcztcbiAgICAgICAgICAgICAgICB2YXIga2V5TWFwID0ge307XG4gICAgICAgICAgICAgICAgdmFyIG5vZGU7XG4gICAgICAgICAgICAgICAgdmFyIHJlbW92ZTtcbiAgICAgICAgICAgICAgICB2YXIgaW5zZXJ0O1xuXG4gICAgICAgICAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCBtb3Zlcy5yZW1vdmVzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICAgICAgICAgIHJlbW92ZSA9IG1vdmVzLnJlbW92ZXNbaV07XG4gICAgICAgICAgICAgICAgICAgIG5vZGUgPSBjaGlsZE5vZGVzW3JlbW92ZS5mcm9tXTtcbiAgICAgICAgICAgICAgICAgICAgaWYgKHJlbW92ZS5rZXkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGtleU1hcFtyZW1vdmUua2V5XSA9IG5vZGU7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgZG9tTm9kZS5yZW1vdmVDaGlsZChub2RlKTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICB2YXIgbGVuZ3RoID0gY2hpbGROb2Rlcy5sZW5ndGg7XG4gICAgICAgICAgICAgICAgZm9yICh2YXIgaiA9IDA7IGogPCBtb3Zlcy5pbnNlcnRzLmxlbmd0aDsgaisrKSB7XG4gICAgICAgICAgICAgICAgICAgIGluc2VydCA9IG1vdmVzLmluc2VydHNbal07XG4gICAgICAgICAgICAgICAgICAgIG5vZGUgPSBrZXlNYXBbaW5zZXJ0LmtleV07XG4gICAgICAgICAgICAgICAgICAgIC8vIHRoaXMgaXMgdGhlIHdlaXJkZXN0IGJ1ZyBpJ3ZlIGV2ZXIgc2VlbiBpbiB3ZWJraXRcbiAgICAgICAgICAgICAgICAgICAgZG9tTm9kZS5pbnNlcnRCZWZvcmUobm9kZSwgaW5zZXJ0LnRvID49IGxlbmd0aCsrID8gbnVsbCA6IGNoaWxkTm9kZXNbaW5zZXJ0LnRvXSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBmdW5jdGlvbiByZXBsYWNlUm9vdChvbGRSb290LCBuZXdSb290KSB7XG4gICAgICAgICAgICAgICAgaWYgKG9sZFJvb3QgJiYgbmV3Um9vdCAmJiBvbGRSb290ICE9PSBuZXdSb290ICYmIG9sZFJvb3QucGFyZW50Tm9kZSkge1xuICAgICAgICAgICAgICAgICAgICBvbGRSb290LnBhcmVudE5vZGUucmVwbGFjZUNoaWxkKG5ld1Jvb3QsIG9sZFJvb3QpO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHJldHVybiBuZXdSb290O1xuICAgICAgICAgICAgfVxuICAgICAgICB9LCB7IFwiLi4vdm5vZGUvaXMtd2lkZ2V0LmpzXCI6IDI5LCBcIi4uL3Zub2RlL3ZwYXRjaC5qc1wiOiAzMiwgXCIuL2FwcGx5LXByb3BlcnRpZXNcIjogMTQsIFwiLi91cGRhdGUtd2lkZ2V0XCI6IDE5IH1dLCAxODogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHtcbiAgICAgICAgICAgIHZhciBkb2N1bWVudCA9IHJlcXVpcmUoXCJnbG9iYWwvZG9jdW1lbnRcIik7XG4gICAgICAgICAgICB2YXIgaXNBcnJheSA9IHJlcXVpcmUoXCJ4LWlzLWFycmF5XCIpO1xuXG4gICAgICAgICAgICB2YXIgcmVuZGVyID0gcmVxdWlyZShcIi4vY3JlYXRlLWVsZW1lbnRcIik7XG4gICAgICAgICAgICB2YXIgZG9tSW5kZXggPSByZXF1aXJlKFwiLi9kb20taW5kZXhcIik7XG4gICAgICAgICAgICB2YXIgcGF0Y2hPcCA9IHJlcXVpcmUoXCIuL3BhdGNoLW9wXCIpO1xuICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBwYXRjaDtcblxuICAgICAgICAgICAgZnVuY3Rpb24gcGF0Y2gocm9vdE5vZGUsIHBhdGNoZXMsIHJlbmRlck9wdGlvbnMpIHtcbiAgICAgICAgICAgICAgICByZW5kZXJPcHRpb25zID0gcmVuZGVyT3B0aW9ucyB8fCB7fTtcbiAgICAgICAgICAgICAgICByZW5kZXJPcHRpb25zLnBhdGNoID0gcmVuZGVyT3B0aW9ucy5wYXRjaCAmJiByZW5kZXJPcHRpb25zLnBhdGNoICE9PSBwYXRjaCA/IHJlbmRlck9wdGlvbnMucGF0Y2ggOiBwYXRjaFJlY3Vyc2l2ZTtcbiAgICAgICAgICAgICAgICByZW5kZXJPcHRpb25zLnJlbmRlciA9IHJlbmRlck9wdGlvbnMucmVuZGVyIHx8IHJlbmRlcjtcblxuICAgICAgICAgICAgICAgIHJldHVybiByZW5kZXJPcHRpb25zLnBhdGNoKHJvb3ROb2RlLCBwYXRjaGVzLCByZW5kZXJPcHRpb25zKTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZnVuY3Rpb24gcGF0Y2hSZWN1cnNpdmUocm9vdE5vZGUsIHBhdGNoZXMsIHJlbmRlck9wdGlvbnMpIHtcbiAgICAgICAgICAgICAgICB2YXIgaW5kaWNlcyA9IHBhdGNoSW5kaWNlcyhwYXRjaGVzKTtcblxuICAgICAgICAgICAgICAgIGlmIChpbmRpY2VzLmxlbmd0aCA9PT0gMCkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gcm9vdE5vZGU7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgdmFyIGluZGV4ID0gZG9tSW5kZXgocm9vdE5vZGUsIHBhdGNoZXMuYSwgaW5kaWNlcyk7XG4gICAgICAgICAgICAgICAgdmFyIG93bmVyRG9jdW1lbnQgPSByb290Tm9kZS5vd25lckRvY3VtZW50O1xuXG4gICAgICAgICAgICAgICAgaWYgKCFyZW5kZXJPcHRpb25zLmRvY3VtZW50ICYmIG93bmVyRG9jdW1lbnQgIT09IGRvY3VtZW50KSB7XG4gICAgICAgICAgICAgICAgICAgIHJlbmRlck9wdGlvbnMuZG9jdW1lbnQgPSBvd25lckRvY3VtZW50O1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgaW5kaWNlcy5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgICAgICAgICB2YXIgbm9kZUluZGV4ID0gaW5kaWNlc1tpXTtcbiAgICAgICAgICAgICAgICAgICAgcm9vdE5vZGUgPSBhcHBseVBhdGNoKHJvb3ROb2RlLCBpbmRleFtub2RlSW5kZXhdLCBwYXRjaGVzW25vZGVJbmRleF0sIHJlbmRlck9wdGlvbnMpO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHJldHVybiByb290Tm9kZTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZnVuY3Rpb24gYXBwbHlQYXRjaChyb290Tm9kZSwgZG9tTm9kZSwgcGF0Y2hMaXN0LCByZW5kZXJPcHRpb25zKSB7XG4gICAgICAgICAgICAgICAgaWYgKCFkb21Ob2RlKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiByb290Tm9kZTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICB2YXIgbmV3Tm9kZTtcblxuICAgICAgICAgICAgICAgIGlmIChpc0FycmF5KHBhdGNoTGlzdCkpIHtcbiAgICAgICAgICAgICAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCBwYXRjaExpc3QubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIG5ld05vZGUgPSBwYXRjaE9wKHBhdGNoTGlzdFtpXSwgZG9tTm9kZSwgcmVuZGVyT3B0aW9ucyk7XG5cbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChkb21Ob2RlID09PSByb290Tm9kZSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJvb3ROb2RlID0gbmV3Tm9kZTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIG5ld05vZGUgPSBwYXRjaE9wKHBhdGNoTGlzdCwgZG9tTm9kZSwgcmVuZGVyT3B0aW9ucyk7XG5cbiAgICAgICAgICAgICAgICAgICAgaWYgKGRvbU5vZGUgPT09IHJvb3ROb2RlKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICByb290Tm9kZSA9IG5ld05vZGU7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICByZXR1cm4gcm9vdE5vZGU7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIHBhdGNoSW5kaWNlcyhwYXRjaGVzKSB7XG4gICAgICAgICAgICAgICAgdmFyIGluZGljZXMgPSBbXTtcblxuICAgICAgICAgICAgICAgIGZvciAodmFyIGtleSBpbiBwYXRjaGVzKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmIChrZXkgIT09IFwiYVwiKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBpbmRpY2VzLnB1c2goTnVtYmVyKGtleSkpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgcmV0dXJuIGluZGljZXM7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0sIHsgXCIuL2NyZWF0ZS1lbGVtZW50XCI6IDE1LCBcIi4vZG9tLWluZGV4XCI6IDE2LCBcIi4vcGF0Y2gtb3BcIjogMTcsIFwiZ2xvYmFsL2RvY3VtZW50XCI6IDEwLCBcIngtaXMtYXJyYXlcIjogMTIgfV0sIDE5OiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge1xuICAgICAgICAgICAgdmFyIGlzV2lkZ2V0ID0gcmVxdWlyZShcIi4uL3Zub2RlL2lzLXdpZGdldC5qc1wiKTtcblxuICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSB1cGRhdGVXaWRnZXQ7XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIHVwZGF0ZVdpZGdldChhLCBiKSB7XG4gICAgICAgICAgICAgICAgaWYgKGlzV2lkZ2V0KGEpICYmIGlzV2lkZ2V0KGIpKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmIChcIm5hbWVcIiBpbiBhICYmIFwibmFtZVwiIGluIGIpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBhLmlkID09PSBiLmlkO1xuICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGEuaW5pdCA9PT0gYi5pbml0O1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICAgICAgfVxuICAgICAgICB9LCB7IFwiLi4vdm5vZGUvaXMtd2lkZ2V0LmpzXCI6IDI5IH1dLCAyMDogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHtcbiAgICAgICAgICAgIFwidXNlIHN0cmljdFwiO1xuXG4gICAgICAgICAgICB2YXIgRXZTdG9yZSA9IHJlcXVpcmUoXCJldi1zdG9yZVwiKTtcblxuICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBFdkhvb2s7XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIEV2SG9vayh2YWx1ZSkge1xuICAgICAgICAgICAgICAgIGlmICghKHRoaXMgaW5zdGFuY2VvZiBFdkhvb2spKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBuZXcgRXZIb29rKHZhbHVlKTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICB0aGlzLnZhbHVlID0gdmFsdWU7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIEV2SG9vay5wcm90b3R5cGUuaG9vayA9IGZ1bmN0aW9uIChub2RlLCBwcm9wZXJ0eU5hbWUpIHtcbiAgICAgICAgICAgICAgICB2YXIgZXMgPSBFdlN0b3JlKG5vZGUpO1xuICAgICAgICAgICAgICAgIHZhciBwcm9wTmFtZSA9IHByb3BlcnR5TmFtZS5zdWJzdHIoMyk7XG5cbiAgICAgICAgICAgICAgICBlc1twcm9wTmFtZV0gPSB0aGlzLnZhbHVlO1xuICAgICAgICAgICAgfTtcblxuICAgICAgICAgICAgRXZIb29rLnByb3RvdHlwZS51bmhvb2sgPSBmdW5jdGlvbiAobm9kZSwgcHJvcGVydHlOYW1lKSB7XG4gICAgICAgICAgICAgICAgdmFyIGVzID0gRXZTdG9yZShub2RlKTtcbiAgICAgICAgICAgICAgICB2YXIgcHJvcE5hbWUgPSBwcm9wZXJ0eU5hbWUuc3Vic3RyKDMpO1xuXG4gICAgICAgICAgICAgICAgZXNbcHJvcE5hbWVdID0gdW5kZWZpbmVkO1xuICAgICAgICAgICAgfTtcbiAgICAgICAgfSwgeyBcImV2LXN0b3JlXCI6IDcgfV0sIDIxOiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge1xuICAgICAgICAgICAgXCJ1c2Ugc3RyaWN0XCI7XG5cbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gU29mdFNldEhvb2s7XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIFNvZnRTZXRIb29rKHZhbHVlKSB7XG4gICAgICAgICAgICAgICAgaWYgKCEodGhpcyBpbnN0YW5jZW9mIFNvZnRTZXRIb29rKSkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gbmV3IFNvZnRTZXRIb29rKHZhbHVlKTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICB0aGlzLnZhbHVlID0gdmFsdWU7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIFNvZnRTZXRIb29rLnByb3RvdHlwZS5ob29rID0gZnVuY3Rpb24gKG5vZGUsIHByb3BlcnR5TmFtZSkge1xuICAgICAgICAgICAgICAgIGlmIChub2RlW3Byb3BlcnR5TmFtZV0gIT09IHRoaXMudmFsdWUpIHtcbiAgICAgICAgICAgICAgICAgICAgbm9kZVtwcm9wZXJ0eU5hbWVdID0gdGhpcy52YWx1ZTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9O1xuICAgICAgICB9LCB7fV0sIDIyOiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge1xuICAgICAgICAgICAgXCJ1c2Ugc3RyaWN0XCI7XG5cbiAgICAgICAgICAgIHZhciBpc0FycmF5ID0gcmVxdWlyZShcIngtaXMtYXJyYXlcIik7XG5cbiAgICAgICAgICAgIHZhciBWTm9kZSA9IHJlcXVpcmUoXCIuLi92bm9kZS92bm9kZS5qc1wiKTtcbiAgICAgICAgICAgIHZhciBWVGV4dCA9IHJlcXVpcmUoXCIuLi92bm9kZS92dGV4dC5qc1wiKTtcbiAgICAgICAgICAgIHZhciBpc1ZOb2RlID0gcmVxdWlyZShcIi4uL3Zub2RlL2lzLXZub2RlXCIpO1xuICAgICAgICAgICAgdmFyIGlzVlRleHQgPSByZXF1aXJlKFwiLi4vdm5vZGUvaXMtdnRleHRcIik7XG4gICAgICAgICAgICB2YXIgaXNXaWRnZXQgPSByZXF1aXJlKFwiLi4vdm5vZGUvaXMtd2lkZ2V0XCIpO1xuICAgICAgICAgICAgdmFyIGlzSG9vayA9IHJlcXVpcmUoXCIuLi92bm9kZS9pcy12aG9va1wiKTtcbiAgICAgICAgICAgIHZhciBpc1ZUaHVuayA9IHJlcXVpcmUoXCIuLi92bm9kZS9pcy10aHVua1wiKTtcblxuICAgICAgICAgICAgdmFyIHBhcnNlVGFnID0gcmVxdWlyZShcIi4vcGFyc2UtdGFnLmpzXCIpO1xuICAgICAgICAgICAgdmFyIHNvZnRTZXRIb29rID0gcmVxdWlyZShcIi4vaG9va3Mvc29mdC1zZXQtaG9vay5qc1wiKTtcbiAgICAgICAgICAgIHZhciBldkhvb2sgPSByZXF1aXJlKFwiLi9ob29rcy9ldi1ob29rLmpzXCIpO1xuXG4gICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IGg7XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIGgodGFnTmFtZSwgcHJvcGVydGllcywgY2hpbGRyZW4pIHtcbiAgICAgICAgICAgICAgICB2YXIgY2hpbGROb2RlcyA9IFtdO1xuICAgICAgICAgICAgICAgIHZhciB0YWcsIHByb3BzLCBrZXksIG5hbWVzcGFjZTtcblxuICAgICAgICAgICAgICAgIGlmICghY2hpbGRyZW4gJiYgaXNDaGlsZHJlbihwcm9wZXJ0aWVzKSkge1xuICAgICAgICAgICAgICAgICAgICBjaGlsZHJlbiA9IHByb3BlcnRpZXM7XG4gICAgICAgICAgICAgICAgICAgIHByb3BzID0ge307XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgcHJvcHMgPSBwcm9wcyB8fCBwcm9wZXJ0aWVzIHx8IHt9O1xuICAgICAgICAgICAgICAgIHRhZyA9IHBhcnNlVGFnKHRhZ05hbWUsIHByb3BzKTtcblxuICAgICAgICAgICAgICAgIC8vIHN1cHBvcnQga2V5c1xuICAgICAgICAgICAgICAgIGlmIChwcm9wcy5oYXNPd25Qcm9wZXJ0eShcImtleVwiKSkge1xuICAgICAgICAgICAgICAgICAgICBrZXkgPSBwcm9wcy5rZXk7XG4gICAgICAgICAgICAgICAgICAgIHByb3BzLmtleSA9IHVuZGVmaW5lZDtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAvLyBzdXBwb3J0IG5hbWVzcGFjZVxuICAgICAgICAgICAgICAgIGlmIChwcm9wcy5oYXNPd25Qcm9wZXJ0eShcIm5hbWVzcGFjZVwiKSkge1xuICAgICAgICAgICAgICAgICAgICBuYW1lc3BhY2UgPSBwcm9wcy5uYW1lc3BhY2U7XG4gICAgICAgICAgICAgICAgICAgIHByb3BzLm5hbWVzcGFjZSA9IHVuZGVmaW5lZDtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAvLyBmaXggY3Vyc29yIGJ1Z1xuICAgICAgICAgICAgICAgIGlmICh0YWcgPT09IFwiSU5QVVRcIiAmJiAhbmFtZXNwYWNlICYmIHByb3BzLmhhc093blByb3BlcnR5KFwidmFsdWVcIikgJiYgcHJvcHMudmFsdWUgIT09IHVuZGVmaW5lZCAmJiAhaXNIb29rKHByb3BzLnZhbHVlKSkge1xuICAgICAgICAgICAgICAgICAgICBwcm9wcy52YWx1ZSA9IHNvZnRTZXRIb29rKHByb3BzLnZhbHVlKTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICB0cmFuc2Zvcm1Qcm9wZXJ0aWVzKHByb3BzKTtcblxuICAgICAgICAgICAgICAgIGlmIChjaGlsZHJlbiAhPT0gdW5kZWZpbmVkICYmIGNoaWxkcmVuICE9PSBudWxsKSB7XG4gICAgICAgICAgICAgICAgICAgIGFkZENoaWxkKGNoaWxkcmVuLCBjaGlsZE5vZGVzLCB0YWcsIHByb3BzKTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICByZXR1cm4gbmV3IFZOb2RlKHRhZywgcHJvcHMsIGNoaWxkTm9kZXMsIGtleSwgbmFtZXNwYWNlKTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZnVuY3Rpb24gYWRkQ2hpbGQoYywgY2hpbGROb2RlcywgdGFnLCBwcm9wcykge1xuICAgICAgICAgICAgICAgIGlmICh0eXBlb2YgYyA9PT0gXCJzdHJpbmdcIikge1xuICAgICAgICAgICAgICAgICAgICBjaGlsZE5vZGVzLnB1c2gobmV3IFZUZXh0KGMpKTtcbiAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKHR5cGVvZiBjID09PSBcIm51bWJlclwiKSB7XG4gICAgICAgICAgICAgICAgICAgIGNoaWxkTm9kZXMucHVzaChuZXcgVlRleHQoU3RyaW5nKGMpKSk7XG4gICAgICAgICAgICAgICAgfSBlbHNlIGlmIChpc0NoaWxkKGMpKSB7XG4gICAgICAgICAgICAgICAgICAgIGNoaWxkTm9kZXMucHVzaChjKTtcbiAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKGlzQXJyYXkoYykpIHtcbiAgICAgICAgICAgICAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCBjLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBhZGRDaGlsZChjW2ldLCBjaGlsZE5vZGVzLCB0YWcsIHByb3BzKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoYyA9PT0gbnVsbCB8fCBjID09PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIHRocm93IFVuZXhwZWN0ZWRWaXJ0dWFsRWxlbWVudCh7XG4gICAgICAgICAgICAgICAgICAgICAgICBmb3JlaWduT2JqZWN0OiBjLFxuICAgICAgICAgICAgICAgICAgICAgICAgcGFyZW50Vm5vZGU6IHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0YWdOYW1lOiB0YWcsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcHJvcGVydGllczogcHJvcHNcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBmdW5jdGlvbiB0cmFuc2Zvcm1Qcm9wZXJ0aWVzKHByb3BzKSB7XG4gICAgICAgICAgICAgICAgZm9yICh2YXIgcHJvcE5hbWUgaW4gcHJvcHMpIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKHByb3BzLmhhc093blByb3BlcnR5KHByb3BOYW1lKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgdmFyIHZhbHVlID0gcHJvcHNbcHJvcE5hbWVdO1xuXG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoaXNIb29rKHZhbHVlKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnRpbnVlO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAocHJvcE5hbWUuc3Vic3RyKDAsIDMpID09PSBcImV2LVwiKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gYWRkIGV2LWZvbyBzdXBwb3J0XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcHJvcHNbcHJvcE5hbWVdID0gZXZIb29rKHZhbHVlKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZnVuY3Rpb24gaXNDaGlsZCh4KSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGlzVk5vZGUoeCkgfHwgaXNWVGV4dCh4KSB8fCBpc1dpZGdldCh4KSB8fCBpc1ZUaHVuayh4KTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZnVuY3Rpb24gaXNDaGlsZHJlbih4KSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHR5cGVvZiB4ID09PSBcInN0cmluZ1wiIHx8IGlzQXJyYXkoeCkgfHwgaXNDaGlsZCh4KTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZnVuY3Rpb24gVW5leHBlY3RlZFZpcnR1YWxFbGVtZW50KGRhdGEpIHtcbiAgICAgICAgICAgICAgICB2YXIgZXJyID0gbmV3IEVycm9yKCk7XG5cbiAgICAgICAgICAgICAgICBlcnIudHlwZSA9IFwidmlydHVhbC1oeXBlcnNjcmlwdC51bmV4cGVjdGVkLnZpcnR1YWwtZWxlbWVudFwiO1xuICAgICAgICAgICAgICAgIGVyci5tZXNzYWdlID0gXCJVbmV4cGVjdGVkIHZpcnR1YWwgY2hpbGQgcGFzc2VkIHRvIGgoKS5cXG5cIiArIFwiRXhwZWN0ZWQgYSBWTm9kZSAvIFZ0aHVuayAvIFZXaWRnZXQgLyBzdHJpbmcgYnV0OlxcblwiICsgXCJnb3Q6XFxuXCIgKyBlcnJvclN0cmluZyhkYXRhLmZvcmVpZ25PYmplY3QpICsgXCIuXFxuXCIgKyBcIlRoZSBwYXJlbnQgdm5vZGUgaXM6XFxuXCIgKyBlcnJvclN0cmluZyhkYXRhLnBhcmVudFZub2RlKTtcbiAgICAgICAgICAgICAgICBcIlxcblwiICsgXCJTdWdnZXN0ZWQgZml4OiBjaGFuZ2UgeW91ciBgaCguLi4sIFsgLi4uIF0pYCBjYWxsc2l0ZS5cIjtcbiAgICAgICAgICAgICAgICBlcnIuZm9yZWlnbk9iamVjdCA9IGRhdGEuZm9yZWlnbk9iamVjdDtcbiAgICAgICAgICAgICAgICBlcnIucGFyZW50Vm5vZGUgPSBkYXRhLnBhcmVudFZub2RlO1xuXG4gICAgICAgICAgICAgICAgcmV0dXJuIGVycjtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZnVuY3Rpb24gZXJyb3JTdHJpbmcob2JqKSB7XG4gICAgICAgICAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIEpTT04uc3RyaW5naWZ5KG9iaiwgbnVsbCwgXCIgICAgXCIpO1xuICAgICAgICAgICAgICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIFN0cmluZyhvYmopO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgfSwgeyBcIi4uL3Zub2RlL2lzLXRodW5rXCI6IDI1LCBcIi4uL3Zub2RlL2lzLXZob29rXCI6IDI2LCBcIi4uL3Zub2RlL2lzLXZub2RlXCI6IDI3LCBcIi4uL3Zub2RlL2lzLXZ0ZXh0XCI6IDI4LCBcIi4uL3Zub2RlL2lzLXdpZGdldFwiOiAyOSwgXCIuLi92bm9kZS92bm9kZS5qc1wiOiAzMSwgXCIuLi92bm9kZS92dGV4dC5qc1wiOiAzMywgXCIuL2hvb2tzL2V2LWhvb2suanNcIjogMjAsIFwiLi9ob29rcy9zb2Z0LXNldC1ob29rLmpzXCI6IDIxLCBcIi4vcGFyc2UtdGFnLmpzXCI6IDIzLCBcIngtaXMtYXJyYXlcIjogMTIgfV0sIDIzOiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge1xuICAgICAgICAgICAgXCJ1c2Ugc3RyaWN0XCI7XG5cbiAgICAgICAgICAgIHZhciBzcGxpdCA9IHJlcXVpcmUoXCJicm93c2VyLXNwbGl0XCIpO1xuXG4gICAgICAgICAgICB2YXIgY2xhc3NJZFNwbGl0ID0gLyhbXFwuI10/W2EtekEtWjAtOVxcdTAwN0YtXFx1RkZGRl86LV0rKS87XG4gICAgICAgICAgICB2YXIgbm90Q2xhc3NJZCA9IC9eXFwufCMvO1xuXG4gICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IHBhcnNlVGFnO1xuXG4gICAgICAgICAgICBmdW5jdGlvbiBwYXJzZVRhZyh0YWcsIHByb3BzKSB7XG4gICAgICAgICAgICAgICAgaWYgKCF0YWcpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIFwiRElWXCI7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgdmFyIG5vSWQgPSAhcHJvcHMuaGFzT3duUHJvcGVydHkoXCJpZFwiKTtcblxuICAgICAgICAgICAgICAgIHZhciB0YWdQYXJ0cyA9IHNwbGl0KHRhZywgY2xhc3NJZFNwbGl0KTtcbiAgICAgICAgICAgICAgICB2YXIgdGFnTmFtZSA9IG51bGw7XG5cbiAgICAgICAgICAgICAgICBpZiAobm90Q2xhc3NJZC50ZXN0KHRhZ1BhcnRzWzFdKSkge1xuICAgICAgICAgICAgICAgICAgICB0YWdOYW1lID0gXCJESVZcIjtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICB2YXIgY2xhc3NlcywgcGFydCwgdHlwZSwgaTtcblxuICAgICAgICAgICAgICAgIGZvciAoaSA9IDA7IGkgPCB0YWdQYXJ0cy5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgICAgICAgICBwYXJ0ID0gdGFnUGFydHNbaV07XG5cbiAgICAgICAgICAgICAgICAgICAgaWYgKCFwYXJ0KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBjb250aW51ZTtcbiAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgIHR5cGUgPSBwYXJ0LmNoYXJBdCgwKTtcblxuICAgICAgICAgICAgICAgICAgICBpZiAoIXRhZ05hbWUpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHRhZ05hbWUgPSBwYXJ0O1xuICAgICAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKHR5cGUgPT09IFwiLlwiKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBjbGFzc2VzID0gY2xhc3NlcyB8fCBbXTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGNsYXNzZXMucHVzaChwYXJ0LnN1YnN0cmluZygxLCBwYXJ0Lmxlbmd0aCkpO1xuICAgICAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKHR5cGUgPT09IFwiI1wiICYmIG5vSWQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHByb3BzLmlkID0gcGFydC5zdWJzdHJpbmcoMSwgcGFydC5sZW5ndGgpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgaWYgKGNsYXNzZXMpIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKHByb3BzLmNsYXNzTmFtZSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgY2xhc3Nlcy5wdXNoKHByb3BzLmNsYXNzTmFtZSk7XG4gICAgICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgICAgICBwcm9wcy5jbGFzc05hbWUgPSBjbGFzc2VzLmpvaW4oXCIgXCIpO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHJldHVybiBwcm9wcy5uYW1lc3BhY2UgPyB0YWdOYW1lIDogdGFnTmFtZS50b1VwcGVyQ2FzZSgpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9LCB7IFwiYnJvd3Nlci1zcGxpdFwiOiA1IH1dLCAyNDogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHtcbiAgICAgICAgICAgIHZhciBpc1ZOb2RlID0gcmVxdWlyZShcIi4vaXMtdm5vZGVcIik7XG4gICAgICAgICAgICB2YXIgaXNWVGV4dCA9IHJlcXVpcmUoXCIuL2lzLXZ0ZXh0XCIpO1xuICAgICAgICAgICAgdmFyIGlzV2lkZ2V0ID0gcmVxdWlyZShcIi4vaXMtd2lkZ2V0XCIpO1xuICAgICAgICAgICAgdmFyIGlzVGh1bmsgPSByZXF1aXJlKFwiLi9pcy10aHVua1wiKTtcblxuICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBoYW5kbGVUaHVuaztcblxuICAgICAgICAgICAgZnVuY3Rpb24gaGFuZGxlVGh1bmsoYSwgYikge1xuICAgICAgICAgICAgICAgIHZhciByZW5kZXJlZEEgPSBhO1xuICAgICAgICAgICAgICAgIHZhciByZW5kZXJlZEIgPSBiO1xuXG4gICAgICAgICAgICAgICAgaWYgKGlzVGh1bmsoYikpIHtcbiAgICAgICAgICAgICAgICAgICAgcmVuZGVyZWRCID0gcmVuZGVyVGh1bmsoYiwgYSk7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgaWYgKGlzVGh1bmsoYSkpIHtcbiAgICAgICAgICAgICAgICAgICAgcmVuZGVyZWRBID0gcmVuZGVyVGh1bmsoYSwgbnVsbCk7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgICAgICAgICAgYTogcmVuZGVyZWRBLFxuICAgICAgICAgICAgICAgICAgICBiOiByZW5kZXJlZEJcbiAgICAgICAgICAgICAgICB9O1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBmdW5jdGlvbiByZW5kZXJUaHVuayh0aHVuaywgcHJldmlvdXMpIHtcbiAgICAgICAgICAgICAgICB2YXIgcmVuZGVyZWRUaHVuayA9IHRodW5rLnZub2RlO1xuXG4gICAgICAgICAgICAgICAgaWYgKCFyZW5kZXJlZFRodW5rKSB7XG4gICAgICAgICAgICAgICAgICAgIHJlbmRlcmVkVGh1bmsgPSB0aHVuay52bm9kZSA9IHRodW5rLnJlbmRlcihwcmV2aW91cyk7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgaWYgKCEoaXNWTm9kZShyZW5kZXJlZFRodW5rKSB8fCBpc1ZUZXh0KHJlbmRlcmVkVGh1bmspIHx8IGlzV2lkZ2V0KHJlbmRlcmVkVGh1bmspKSkge1xuICAgICAgICAgICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoXCJ0aHVuayBkaWQgbm90IHJldHVybiBhIHZhbGlkIG5vZGVcIik7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgcmV0dXJuIHJlbmRlcmVkVGh1bms7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0sIHsgXCIuL2lzLXRodW5rXCI6IDI1LCBcIi4vaXMtdm5vZGVcIjogMjcsIFwiLi9pcy12dGV4dFwiOiAyOCwgXCIuL2lzLXdpZGdldFwiOiAyOSB9XSwgMjU6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IGlzVGh1bms7XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIGlzVGh1bmsodCkge1xuICAgICAgICAgICAgICAgIHJldHVybiB0ICYmIHQudHlwZSA9PT0gXCJUaHVua1wiO1xuICAgICAgICAgICAgfVxuICAgICAgICB9LCB7fV0sIDI2OiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge1xuICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBpc0hvb2s7XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIGlzSG9vayhob29rKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGhvb2sgJiYgKHR5cGVvZiBob29rLmhvb2sgPT09IFwiZnVuY3Rpb25cIiAmJiAhaG9vay5oYXNPd25Qcm9wZXJ0eShcImhvb2tcIikgfHwgdHlwZW9mIGhvb2sudW5ob29rID09PSBcImZ1bmN0aW9uXCIgJiYgIWhvb2suaGFzT3duUHJvcGVydHkoXCJ1bmhvb2tcIikpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9LCB7fV0sIDI3OiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge1xuICAgICAgICAgICAgdmFyIHZlcnNpb24gPSByZXF1aXJlKFwiLi92ZXJzaW9uXCIpO1xuXG4gICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IGlzVmlydHVhbE5vZGU7XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIGlzVmlydHVhbE5vZGUoeCkge1xuICAgICAgICAgICAgICAgIHJldHVybiB4ICYmIHgudHlwZSA9PT0gXCJWaXJ0dWFsTm9kZVwiICYmIHgudmVyc2lvbiA9PT0gdmVyc2lvbjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSwgeyBcIi4vdmVyc2lvblwiOiAzMCB9XSwgMjg6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICB2YXIgdmVyc2lvbiA9IHJlcXVpcmUoXCIuL3ZlcnNpb25cIik7XG5cbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gaXNWaXJ0dWFsVGV4dDtcblxuICAgICAgICAgICAgZnVuY3Rpb24gaXNWaXJ0dWFsVGV4dCh4KSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHggJiYgeC50eXBlID09PSBcIlZpcnR1YWxUZXh0XCIgJiYgeC52ZXJzaW9uID09PSB2ZXJzaW9uO1xuICAgICAgICAgICAgfVxuICAgICAgICB9LCB7IFwiLi92ZXJzaW9uXCI6IDMwIH1dLCAyOTogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHtcbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gaXNXaWRnZXQ7XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIGlzV2lkZ2V0KHcpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gdyAmJiB3LnR5cGUgPT09IFwiV2lkZ2V0XCI7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0sIHt9XSwgMzA6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IFwiMlwiO1xuICAgICAgICB9LCB7fV0sIDMxOiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge1xuICAgICAgICAgICAgdmFyIHZlcnNpb24gPSByZXF1aXJlKFwiLi92ZXJzaW9uXCIpO1xuICAgICAgICAgICAgdmFyIGlzVk5vZGUgPSByZXF1aXJlKFwiLi9pcy12bm9kZVwiKTtcbiAgICAgICAgICAgIHZhciBpc1dpZGdldCA9IHJlcXVpcmUoXCIuL2lzLXdpZGdldFwiKTtcbiAgICAgICAgICAgIHZhciBpc1RodW5rID0gcmVxdWlyZShcIi4vaXMtdGh1bmtcIik7XG4gICAgICAgICAgICB2YXIgaXNWSG9vayA9IHJlcXVpcmUoXCIuL2lzLXZob29rXCIpO1xuXG4gICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IFZpcnR1YWxOb2RlO1xuXG4gICAgICAgICAgICB2YXIgbm9Qcm9wZXJ0aWVzID0ge307XG4gICAgICAgICAgICB2YXIgbm9DaGlsZHJlbiA9IFtdO1xuXG4gICAgICAgICAgICBmdW5jdGlvbiBWaXJ0dWFsTm9kZSh0YWdOYW1lLCBwcm9wZXJ0aWVzLCBjaGlsZHJlbiwga2V5LCBuYW1lc3BhY2UpIHtcbiAgICAgICAgICAgICAgICB0aGlzLnRhZ05hbWUgPSB0YWdOYW1lO1xuICAgICAgICAgICAgICAgIHRoaXMucHJvcGVydGllcyA9IHByb3BlcnRpZXMgfHwgbm9Qcm9wZXJ0aWVzO1xuICAgICAgICAgICAgICAgIHRoaXMuY2hpbGRyZW4gPSBjaGlsZHJlbiB8fCBub0NoaWxkcmVuO1xuICAgICAgICAgICAgICAgIHRoaXMua2V5ID0ga2V5ICE9IG51bGwgPyBTdHJpbmcoa2V5KSA6IHVuZGVmaW5lZDtcbiAgICAgICAgICAgICAgICB0aGlzLm5hbWVzcGFjZSA9IHR5cGVvZiBuYW1lc3BhY2UgPT09IFwic3RyaW5nXCIgPyBuYW1lc3BhY2UgOiBudWxsO1xuXG4gICAgICAgICAgICAgICAgdmFyIGNvdW50ID0gY2hpbGRyZW4gJiYgY2hpbGRyZW4ubGVuZ3RoIHx8IDA7XG4gICAgICAgICAgICAgICAgdmFyIGRlc2NlbmRhbnRzID0gMDtcbiAgICAgICAgICAgICAgICB2YXIgaGFzV2lkZ2V0cyA9IGZhbHNlO1xuICAgICAgICAgICAgICAgIHZhciBoYXNUaHVua3MgPSBmYWxzZTtcbiAgICAgICAgICAgICAgICB2YXIgZGVzY2VuZGFudEhvb2tzID0gZmFsc2U7XG4gICAgICAgICAgICAgICAgdmFyIGhvb2tzO1xuXG4gICAgICAgICAgICAgICAgZm9yICh2YXIgcHJvcE5hbWUgaW4gcHJvcGVydGllcykge1xuICAgICAgICAgICAgICAgICAgICBpZiAocHJvcGVydGllcy5oYXNPd25Qcm9wZXJ0eShwcm9wTmFtZSkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHZhciBwcm9wZXJ0eSA9IHByb3BlcnRpZXNbcHJvcE5hbWVdO1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGlzVkhvb2socHJvcGVydHkpICYmIHByb3BlcnR5LnVuaG9vaykge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmICghaG9va3MpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaG9va3MgPSB7fTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBob29rc1twcm9wTmFtZV0gPSBwcm9wZXJ0eTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgY291bnQ7IGkrKykge1xuICAgICAgICAgICAgICAgICAgICB2YXIgY2hpbGQgPSBjaGlsZHJlbltpXTtcbiAgICAgICAgICAgICAgICAgICAgaWYgKGlzVk5vZGUoY2hpbGQpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBkZXNjZW5kYW50cyArPSBjaGlsZC5jb3VudCB8fCAwO1xuXG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoIWhhc1dpZGdldHMgJiYgY2hpbGQuaGFzV2lkZ2V0cykge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGhhc1dpZGdldHMgPSB0cnVlO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoIWhhc1RodW5rcyAmJiBjaGlsZC5oYXNUaHVua3MpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBoYXNUaHVua3MgPSB0cnVlO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoIWRlc2NlbmRhbnRIb29rcyAmJiAoY2hpbGQuaG9va3MgfHwgY2hpbGQuZGVzY2VuZGFudEhvb2tzKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRlc2NlbmRhbnRIb29rcyA9IHRydWU7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoIWhhc1dpZGdldHMgJiYgaXNXaWRnZXQoY2hpbGQpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAodHlwZW9mIGNoaWxkLmRlc3Ryb3kgPT09IFwiZnVuY3Rpb25cIikge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGhhc1dpZGdldHMgPSB0cnVlO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKCFoYXNUaHVua3MgJiYgaXNUaHVuayhjaGlsZCkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGhhc1RodW5rcyA9IHRydWU7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICB0aGlzLmNvdW50ID0gY291bnQgKyBkZXNjZW5kYW50cztcbiAgICAgICAgICAgICAgICB0aGlzLmhhc1dpZGdldHMgPSBoYXNXaWRnZXRzO1xuICAgICAgICAgICAgICAgIHRoaXMuaGFzVGh1bmtzID0gaGFzVGh1bmtzO1xuICAgICAgICAgICAgICAgIHRoaXMuaG9va3MgPSBob29rcztcbiAgICAgICAgICAgICAgICB0aGlzLmRlc2NlbmRhbnRIb29rcyA9IGRlc2NlbmRhbnRIb29rcztcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgVmlydHVhbE5vZGUucHJvdG90eXBlLnZlcnNpb24gPSB2ZXJzaW9uO1xuICAgICAgICAgICAgVmlydHVhbE5vZGUucHJvdG90eXBlLnR5cGUgPSBcIlZpcnR1YWxOb2RlXCI7XG4gICAgICAgIH0sIHsgXCIuL2lzLXRodW5rXCI6IDI1LCBcIi4vaXMtdmhvb2tcIjogMjYsIFwiLi9pcy12bm9kZVwiOiAyNywgXCIuL2lzLXdpZGdldFwiOiAyOSwgXCIuL3ZlcnNpb25cIjogMzAgfV0sIDMyOiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge1xuICAgICAgICAgICAgdmFyIHZlcnNpb24gPSByZXF1aXJlKFwiLi92ZXJzaW9uXCIpO1xuXG4gICAgICAgICAgICBWaXJ0dWFsUGF0Y2guTk9ORSA9IDA7XG4gICAgICAgICAgICBWaXJ0dWFsUGF0Y2guVlRFWFQgPSAxO1xuICAgICAgICAgICAgVmlydHVhbFBhdGNoLlZOT0RFID0gMjtcbiAgICAgICAgICAgIFZpcnR1YWxQYXRjaC5XSURHRVQgPSAzO1xuICAgICAgICAgICAgVmlydHVhbFBhdGNoLlBST1BTID0gNDtcbiAgICAgICAgICAgIFZpcnR1YWxQYXRjaC5PUkRFUiA9IDU7XG4gICAgICAgICAgICBWaXJ0dWFsUGF0Y2guSU5TRVJUID0gNjtcbiAgICAgICAgICAgIFZpcnR1YWxQYXRjaC5SRU1PVkUgPSA3O1xuICAgICAgICAgICAgVmlydHVhbFBhdGNoLlRIVU5LID0gODtcblxuICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBWaXJ0dWFsUGF0Y2g7XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIFZpcnR1YWxQYXRjaCh0eXBlLCB2Tm9kZSwgcGF0Y2gpIHtcbiAgICAgICAgICAgICAgICB0aGlzLnR5cGUgPSBOdW1iZXIodHlwZSk7XG4gICAgICAgICAgICAgICAgdGhpcy52Tm9kZSA9IHZOb2RlO1xuICAgICAgICAgICAgICAgIHRoaXMucGF0Y2ggPSBwYXRjaDtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgVmlydHVhbFBhdGNoLnByb3RvdHlwZS52ZXJzaW9uID0gdmVyc2lvbjtcbiAgICAgICAgICAgIFZpcnR1YWxQYXRjaC5wcm90b3R5cGUudHlwZSA9IFwiVmlydHVhbFBhdGNoXCI7XG4gICAgICAgIH0sIHsgXCIuL3ZlcnNpb25cIjogMzAgfV0sIDMzOiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge1xuICAgICAgICAgICAgdmFyIHZlcnNpb24gPSByZXF1aXJlKFwiLi92ZXJzaW9uXCIpO1xuXG4gICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IFZpcnR1YWxUZXh0O1xuXG4gICAgICAgICAgICBmdW5jdGlvbiBWaXJ0dWFsVGV4dCh0ZXh0KSB7XG4gICAgICAgICAgICAgICAgdGhpcy50ZXh0ID0gU3RyaW5nKHRleHQpO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBWaXJ0dWFsVGV4dC5wcm90b3R5cGUudmVyc2lvbiA9IHZlcnNpb247XG4gICAgICAgICAgICBWaXJ0dWFsVGV4dC5wcm90b3R5cGUudHlwZSA9IFwiVmlydHVhbFRleHRcIjtcbiAgICAgICAgfSwgeyBcIi4vdmVyc2lvblwiOiAzMCB9XSwgMzQ6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICB2YXIgaXNPYmplY3QgPSByZXF1aXJlKFwiaXMtb2JqZWN0XCIpO1xuICAgICAgICAgICAgdmFyIGlzSG9vayA9IHJlcXVpcmUoXCIuLi92bm9kZS9pcy12aG9va1wiKTtcblxuICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBkaWZmUHJvcHM7XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIGRpZmZQcm9wcyhhLCBiKSB7XG4gICAgICAgICAgICAgICAgdmFyIGRpZmY7XG5cbiAgICAgICAgICAgICAgICBmb3IgKHZhciBhS2V5IGluIGEpIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKCEoYUtleSBpbiBiKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgZGlmZiA9IGRpZmYgfHwge307XG4gICAgICAgICAgICAgICAgICAgICAgICBkaWZmW2FLZXldID0gdW5kZWZpbmVkO1xuICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgdmFyIGFWYWx1ZSA9IGFbYUtleV07XG4gICAgICAgICAgICAgICAgICAgIHZhciBiVmFsdWUgPSBiW2FLZXldO1xuXG4gICAgICAgICAgICAgICAgICAgIGlmIChhVmFsdWUgPT09IGJWYWx1ZSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgY29udGludWU7XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoaXNPYmplY3QoYVZhbHVlKSAmJiBpc09iamVjdChiVmFsdWUpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoZ2V0UHJvdG90eXBlKGJWYWx1ZSkgIT09IGdldFByb3RvdHlwZShhVmFsdWUpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgZGlmZiA9IGRpZmYgfHwge307XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgZGlmZlthS2V5XSA9IGJWYWx1ZTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoaXNIb29rKGJWYWx1ZSkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBkaWZmID0gZGlmZiB8fCB7fTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBkaWZmW2FLZXldID0gYlZhbHVlO1xuICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB2YXIgb2JqZWN0RGlmZiA9IGRpZmZQcm9wcyhhVmFsdWUsIGJWYWx1ZSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKG9iamVjdERpZmYpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZGlmZiA9IGRpZmYgfHwge307XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRpZmZbYUtleV0gPSBvYmplY3REaWZmO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGRpZmYgPSBkaWZmIHx8IHt9O1xuICAgICAgICAgICAgICAgICAgICAgICAgZGlmZlthS2V5XSA9IGJWYWx1ZTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIGZvciAodmFyIGJLZXkgaW4gYikge1xuICAgICAgICAgICAgICAgICAgICBpZiAoIShiS2V5IGluIGEpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBkaWZmID0gZGlmZiB8fCB7fTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGRpZmZbYktleV0gPSBiW2JLZXldO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgcmV0dXJuIGRpZmY7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIGdldFByb3RvdHlwZSh2YWx1ZSkge1xuICAgICAgICAgICAgICAgIGlmIChPYmplY3QuZ2V0UHJvdG90eXBlT2YpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIE9iamVjdC5nZXRQcm90b3R5cGVPZih2YWx1ZSk7XG4gICAgICAgICAgICAgICAgfSBlbHNlIGlmICh2YWx1ZS5fX3Byb3RvX18pIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHZhbHVlLl9fcHJvdG9fXztcbiAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKHZhbHVlLmNvbnN0cnVjdG9yKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiB2YWx1ZS5jb25zdHJ1Y3Rvci5wcm90b3R5cGU7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9LCB7IFwiLi4vdm5vZGUvaXMtdmhvb2tcIjogMjYsIFwiaXMtb2JqZWN0XCI6IDExIH1dLCAzNTogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHtcbiAgICAgICAgICAgIHZhciBpc0FycmF5ID0gcmVxdWlyZShcIngtaXMtYXJyYXlcIik7XG5cbiAgICAgICAgICAgIHZhciBWUGF0Y2ggPSByZXF1aXJlKFwiLi4vdm5vZGUvdnBhdGNoXCIpO1xuICAgICAgICAgICAgdmFyIGlzVk5vZGUgPSByZXF1aXJlKFwiLi4vdm5vZGUvaXMtdm5vZGVcIik7XG4gICAgICAgICAgICB2YXIgaXNWVGV4dCA9IHJlcXVpcmUoXCIuLi92bm9kZS9pcy12dGV4dFwiKTtcbiAgICAgICAgICAgIHZhciBpc1dpZGdldCA9IHJlcXVpcmUoXCIuLi92bm9kZS9pcy13aWRnZXRcIik7XG4gICAgICAgICAgICB2YXIgaXNUaHVuayA9IHJlcXVpcmUoXCIuLi92bm9kZS9pcy10aHVua1wiKTtcbiAgICAgICAgICAgIHZhciBoYW5kbGVUaHVuayA9IHJlcXVpcmUoXCIuLi92bm9kZS9oYW5kbGUtdGh1bmtcIik7XG5cbiAgICAgICAgICAgIHZhciBkaWZmUHJvcHMgPSByZXF1aXJlKFwiLi9kaWZmLXByb3BzXCIpO1xuXG4gICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IGRpZmY7XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIGRpZmYoYSwgYikge1xuICAgICAgICAgICAgICAgIHZhciBwYXRjaCA9IHsgYTogYSB9O1xuICAgICAgICAgICAgICAgIHdhbGsoYSwgYiwgcGF0Y2gsIDApO1xuICAgICAgICAgICAgICAgIHJldHVybiBwYXRjaDtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZnVuY3Rpb24gd2FsayhhLCBiLCBwYXRjaCwgaW5kZXgpIHtcbiAgICAgICAgICAgICAgICBpZiAoYSA9PT0gYikge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgdmFyIGFwcGx5ID0gcGF0Y2hbaW5kZXhdO1xuICAgICAgICAgICAgICAgIHZhciBhcHBseUNsZWFyID0gZmFsc2U7XG5cbiAgICAgICAgICAgICAgICBpZiAoaXNUaHVuayhhKSB8fCBpc1RodW5rKGIpKSB7XG4gICAgICAgICAgICAgICAgICAgIHRodW5rcyhhLCBiLCBwYXRjaCwgaW5kZXgpO1xuICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoYiA9PSBudWxsKSB7XG5cbiAgICAgICAgICAgICAgICAgICAgLy8gSWYgYSBpcyBhIHdpZGdldCB3ZSB3aWxsIGFkZCBhIHJlbW92ZSBwYXRjaCBmb3IgaXRcbiAgICAgICAgICAgICAgICAgICAgLy8gT3RoZXJ3aXNlIGFueSBjaGlsZCB3aWRnZXRzL2hvb2tzIG11c3QgYmUgZGVzdHJveWVkLlxuICAgICAgICAgICAgICAgICAgICAvLyBUaGlzIHByZXZlbnRzIGFkZGluZyB0d28gcmVtb3ZlIHBhdGNoZXMgZm9yIGEgd2lkZ2V0LlxuICAgICAgICAgICAgICAgICAgICBpZiAoIWlzV2lkZ2V0KGEpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBjbGVhclN0YXRlKGEsIHBhdGNoLCBpbmRleCk7XG4gICAgICAgICAgICAgICAgICAgICAgICBhcHBseSA9IHBhdGNoW2luZGV4XTtcbiAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgIGFwcGx5ID0gYXBwZW5kUGF0Y2goYXBwbHksIG5ldyBWUGF0Y2goVlBhdGNoLlJFTU9WRSwgYSwgYikpO1xuICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoaXNWTm9kZShiKSkge1xuICAgICAgICAgICAgICAgICAgICBpZiAoaXNWTm9kZShhKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGEudGFnTmFtZSA9PT0gYi50YWdOYW1lICYmIGEubmFtZXNwYWNlID09PSBiLm5hbWVzcGFjZSAmJiBhLmtleSA9PT0gYi5rZXkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB2YXIgcHJvcHNQYXRjaCA9IGRpZmZQcm9wcyhhLnByb3BlcnRpZXMsIGIucHJvcGVydGllcyk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHByb3BzUGF0Y2gpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYXBwbHkgPSBhcHBlbmRQYXRjaChhcHBseSwgbmV3IFZQYXRjaChWUGF0Y2guUFJPUFMsIGEsIHByb3BzUGF0Y2gpKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgYXBwbHkgPSBkaWZmQ2hpbGRyZW4oYSwgYiwgcGF0Y2gsIGFwcGx5LCBpbmRleCk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGFwcGx5ID0gYXBwZW5kUGF0Y2goYXBwbHksIG5ldyBWUGF0Y2goVlBhdGNoLlZOT0RFLCBhLCBiKSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgYXBwbHlDbGVhciA9IHRydWU7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBhcHBseSA9IGFwcGVuZFBhdGNoKGFwcGx5LCBuZXcgVlBhdGNoKFZQYXRjaC5WTk9ERSwgYSwgYikpO1xuICAgICAgICAgICAgICAgICAgICAgICAgYXBwbHlDbGVhciA9IHRydWU7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKGlzVlRleHQoYikpIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKCFpc1ZUZXh0KGEpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBhcHBseSA9IGFwcGVuZFBhdGNoKGFwcGx5LCBuZXcgVlBhdGNoKFZQYXRjaC5WVEVYVCwgYSwgYikpO1xuICAgICAgICAgICAgICAgICAgICAgICAgYXBwbHlDbGVhciA9IHRydWU7XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoYS50ZXh0ICE9PSBiLnRleHQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGFwcGx5ID0gYXBwZW5kUGF0Y2goYXBwbHksIG5ldyBWUGF0Y2goVlBhdGNoLlZURVhULCBhLCBiKSk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKGlzV2lkZ2V0KGIpKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmICghaXNXaWRnZXQoYSkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGFwcGx5Q2xlYXIgPSB0cnVlO1xuICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgYXBwbHkgPSBhcHBlbmRQYXRjaChhcHBseSwgbmV3IFZQYXRjaChWUGF0Y2guV0lER0VULCBhLCBiKSk7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgaWYgKGFwcGx5KSB7XG4gICAgICAgICAgICAgICAgICAgIHBhdGNoW2luZGV4XSA9IGFwcGx5O1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIGlmIChhcHBseUNsZWFyKSB7XG4gICAgICAgICAgICAgICAgICAgIGNsZWFyU3RhdGUoYSwgcGF0Y2gsIGluZGV4KTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIGRpZmZDaGlsZHJlbihhLCBiLCBwYXRjaCwgYXBwbHksIGluZGV4KSB7XG4gICAgICAgICAgICAgICAgdmFyIGFDaGlsZHJlbiA9IGEuY2hpbGRyZW47XG4gICAgICAgICAgICAgICAgdmFyIG9yZGVyZWRTZXQgPSByZW9yZGVyKGFDaGlsZHJlbiwgYi5jaGlsZHJlbik7XG4gICAgICAgICAgICAgICAgdmFyIGJDaGlsZHJlbiA9IG9yZGVyZWRTZXQuY2hpbGRyZW47XG5cbiAgICAgICAgICAgICAgICB2YXIgYUxlbiA9IGFDaGlsZHJlbi5sZW5ndGg7XG4gICAgICAgICAgICAgICAgdmFyIGJMZW4gPSBiQ2hpbGRyZW4ubGVuZ3RoO1xuICAgICAgICAgICAgICAgIHZhciBsZW4gPSBhTGVuID4gYkxlbiA/IGFMZW4gOiBiTGVuO1xuXG4gICAgICAgICAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCBsZW47IGkrKykge1xuICAgICAgICAgICAgICAgICAgICB2YXIgbGVmdE5vZGUgPSBhQ2hpbGRyZW5baV07XG4gICAgICAgICAgICAgICAgICAgIHZhciByaWdodE5vZGUgPSBiQ2hpbGRyZW5baV07XG4gICAgICAgICAgICAgICAgICAgIGluZGV4ICs9IDE7XG5cbiAgICAgICAgICAgICAgICAgICAgaWYgKCFsZWZ0Tm9kZSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHJpZ2h0Tm9kZSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIEV4Y2VzcyBub2RlcyBpbiBiIG5lZWQgdG8gYmUgYWRkZWRcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBhcHBseSA9IGFwcGVuZFBhdGNoKGFwcGx5LCBuZXcgVlBhdGNoKFZQYXRjaC5JTlNFUlQsIG51bGwsIHJpZ2h0Tm9kZSkpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgd2FsayhsZWZ0Tm9kZSwgcmlnaHROb2RlLCBwYXRjaCwgaW5kZXgpO1xuICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgaWYgKGlzVk5vZGUobGVmdE5vZGUpICYmIGxlZnROb2RlLmNvdW50KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBpbmRleCArPSBsZWZ0Tm9kZS5jb3VudDtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIGlmIChvcmRlcmVkU2V0Lm1vdmVzKSB7XG4gICAgICAgICAgICAgICAgICAgIC8vIFJlb3JkZXIgbm9kZXMgbGFzdFxuICAgICAgICAgICAgICAgICAgICBhcHBseSA9IGFwcGVuZFBhdGNoKGFwcGx5LCBuZXcgVlBhdGNoKFZQYXRjaC5PUkRFUiwgYSwgb3JkZXJlZFNldC5tb3ZlcykpO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHJldHVybiBhcHBseTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZnVuY3Rpb24gY2xlYXJTdGF0ZSh2Tm9kZSwgcGF0Y2gsIGluZGV4KSB7XG4gICAgICAgICAgICAgICAgLy8gVE9ETzogTWFrZSB0aGlzIGEgc2luZ2xlIHdhbGssIG5vdCB0d29cbiAgICAgICAgICAgICAgICB1bmhvb2sodk5vZGUsIHBhdGNoLCBpbmRleCk7XG4gICAgICAgICAgICAgICAgZGVzdHJveVdpZGdldHModk5vZGUsIHBhdGNoLCBpbmRleCk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIC8vIFBhdGNoIHJlY29yZHMgZm9yIGFsbCBkZXN0cm95ZWQgd2lkZ2V0cyBtdXN0IGJlIGFkZGVkIGJlY2F1c2Ugd2UgbmVlZFxuICAgICAgICAgICAgLy8gYSBET00gbm9kZSByZWZlcmVuY2UgZm9yIHRoZSBkZXN0cm95IGZ1bmN0aW9uXG4gICAgICAgICAgICBmdW5jdGlvbiBkZXN0cm95V2lkZ2V0cyh2Tm9kZSwgcGF0Y2gsIGluZGV4KSB7XG4gICAgICAgICAgICAgICAgaWYgKGlzV2lkZ2V0KHZOb2RlKSkge1xuICAgICAgICAgICAgICAgICAgICBpZiAodHlwZW9mIHZOb2RlLmRlc3Ryb3kgPT09IFwiZnVuY3Rpb25cIikge1xuICAgICAgICAgICAgICAgICAgICAgICAgcGF0Y2hbaW5kZXhdID0gYXBwZW5kUGF0Y2gocGF0Y2hbaW5kZXhdLCBuZXcgVlBhdGNoKFZQYXRjaC5SRU1PVkUsIHZOb2RlLCBudWxsKSk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKGlzVk5vZGUodk5vZGUpICYmICh2Tm9kZS5oYXNXaWRnZXRzIHx8IHZOb2RlLmhhc1RodW5rcykpIHtcbiAgICAgICAgICAgICAgICAgICAgdmFyIGNoaWxkcmVuID0gdk5vZGUuY2hpbGRyZW47XG4gICAgICAgICAgICAgICAgICAgIHZhciBsZW4gPSBjaGlsZHJlbi5sZW5ndGg7XG4gICAgICAgICAgICAgICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgbGVuOyBpKyspIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHZhciBjaGlsZCA9IGNoaWxkcmVuW2ldO1xuICAgICAgICAgICAgICAgICAgICAgICAgaW5kZXggKz0gMTtcblxuICAgICAgICAgICAgICAgICAgICAgICAgZGVzdHJveVdpZGdldHMoY2hpbGQsIHBhdGNoLCBpbmRleCk7XG5cbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChpc1ZOb2RlKGNoaWxkKSAmJiBjaGlsZC5jb3VudCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGluZGV4ICs9IGNoaWxkLmNvdW50O1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfSBlbHNlIGlmIChpc1RodW5rKHZOb2RlKSkge1xuICAgICAgICAgICAgICAgICAgICB0aHVua3Modk5vZGUsIG51bGwsIHBhdGNoLCBpbmRleCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAvLyBDcmVhdGUgYSBzdWItcGF0Y2ggZm9yIHRodW5rc1xuICAgICAgICAgICAgZnVuY3Rpb24gdGh1bmtzKGEsIGIsIHBhdGNoLCBpbmRleCkge1xuICAgICAgICAgICAgICAgIHZhciBub2RlcyA9IGhhbmRsZVRodW5rKGEsIGIpO1xuICAgICAgICAgICAgICAgIHZhciB0aHVua1BhdGNoID0gZGlmZihub2Rlcy5hLCBub2Rlcy5iKTtcbiAgICAgICAgICAgICAgICBpZiAoaGFzUGF0Y2hlcyh0aHVua1BhdGNoKSkge1xuICAgICAgICAgICAgICAgICAgICBwYXRjaFtpbmRleF0gPSBuZXcgVlBhdGNoKFZQYXRjaC5USFVOSywgbnVsbCwgdGh1bmtQYXRjaCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBmdW5jdGlvbiBoYXNQYXRjaGVzKHBhdGNoKSB7XG4gICAgICAgICAgICAgICAgZm9yICh2YXIgaW5kZXggaW4gcGF0Y2gpIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKGluZGV4ICE9PSBcImFcIikge1xuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIC8vIEV4ZWN1dGUgaG9va3Mgd2hlbiB0d28gbm9kZXMgYXJlIGlkZW50aWNhbFxuICAgICAgICAgICAgZnVuY3Rpb24gdW5ob29rKHZOb2RlLCBwYXRjaCwgaW5kZXgpIHtcbiAgICAgICAgICAgICAgICBpZiAoaXNWTm9kZSh2Tm9kZSkpIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKHZOb2RlLmhvb2tzKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBwYXRjaFtpbmRleF0gPSBhcHBlbmRQYXRjaChwYXRjaFtpbmRleF0sIG5ldyBWUGF0Y2goVlBhdGNoLlBST1BTLCB2Tm9kZSwgdW5kZWZpbmVkS2V5cyh2Tm9kZS5ob29rcykpKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgIGlmICh2Tm9kZS5kZXNjZW5kYW50SG9va3MgfHwgdk5vZGUuaGFzVGh1bmtzKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICB2YXIgY2hpbGRyZW4gPSB2Tm9kZS5jaGlsZHJlbjtcbiAgICAgICAgICAgICAgICAgICAgICAgIHZhciBsZW4gPSBjaGlsZHJlbi5sZW5ndGg7XG4gICAgICAgICAgICAgICAgICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IGxlbjsgaSsrKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdmFyIGNoaWxkID0gY2hpbGRyZW5baV07XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaW5kZXggKz0gMTtcblxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHVuaG9vayhjaGlsZCwgcGF0Y2gsIGluZGV4KTtcblxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChpc1ZOb2RlKGNoaWxkKSAmJiBjaGlsZC5jb3VudCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpbmRleCArPSBjaGlsZC5jb3VudDtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKGlzVGh1bmsodk5vZGUpKSB7XG4gICAgICAgICAgICAgICAgICAgIHRodW5rcyh2Tm9kZSwgbnVsbCwgcGF0Y2gsIGluZGV4KTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIHVuZGVmaW5lZEtleXMob2JqKSB7XG4gICAgICAgICAgICAgICAgdmFyIHJlc3VsdCA9IHt9O1xuXG4gICAgICAgICAgICAgICAgZm9yICh2YXIga2V5IGluIG9iaikge1xuICAgICAgICAgICAgICAgICAgICByZXN1bHRba2V5XSA9IHVuZGVmaW5lZDtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICByZXR1cm4gcmVzdWx0O1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAvLyBMaXN0IGRpZmYsIG5haXZlIGxlZnQgdG8gcmlnaHQgcmVvcmRlcmluZ1xuICAgICAgICAgICAgZnVuY3Rpb24gcmVvcmRlcihhQ2hpbGRyZW4sIGJDaGlsZHJlbikge1xuICAgICAgICAgICAgICAgIC8vIE8oTSkgdGltZSwgTyhNKSBtZW1vcnlcbiAgICAgICAgICAgICAgICB2YXIgYkNoaWxkSW5kZXggPSBrZXlJbmRleChiQ2hpbGRyZW4pO1xuICAgICAgICAgICAgICAgIHZhciBiS2V5cyA9IGJDaGlsZEluZGV4LmtleXM7XG4gICAgICAgICAgICAgICAgdmFyIGJGcmVlID0gYkNoaWxkSW5kZXguZnJlZTtcblxuICAgICAgICAgICAgICAgIGlmIChiRnJlZS5sZW5ndGggPT09IGJDaGlsZHJlbi5sZW5ndGgpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGNoaWxkcmVuOiBiQ2hpbGRyZW4sXG4gICAgICAgICAgICAgICAgICAgICAgICBtb3ZlczogbnVsbFxuICAgICAgICAgICAgICAgICAgICB9O1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIC8vIE8oTikgdGltZSwgTyhOKSBtZW1vcnlcbiAgICAgICAgICAgICAgICB2YXIgYUNoaWxkSW5kZXggPSBrZXlJbmRleChhQ2hpbGRyZW4pO1xuICAgICAgICAgICAgICAgIHZhciBhS2V5cyA9IGFDaGlsZEluZGV4LmtleXM7XG4gICAgICAgICAgICAgICAgdmFyIGFGcmVlID0gYUNoaWxkSW5kZXguZnJlZTtcblxuICAgICAgICAgICAgICAgIGlmIChhRnJlZS5sZW5ndGggPT09IGFDaGlsZHJlbi5sZW5ndGgpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGNoaWxkcmVuOiBiQ2hpbGRyZW4sXG4gICAgICAgICAgICAgICAgICAgICAgICBtb3ZlczogbnVsbFxuICAgICAgICAgICAgICAgICAgICB9O1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIC8vIE8oTUFYKE4sIE0pKSBtZW1vcnlcbiAgICAgICAgICAgICAgICB2YXIgbmV3Q2hpbGRyZW4gPSBbXTtcblxuICAgICAgICAgICAgICAgIHZhciBmcmVlSW5kZXggPSAwO1xuICAgICAgICAgICAgICAgIHZhciBmcmVlQ291bnQgPSBiRnJlZS5sZW5ndGg7XG4gICAgICAgICAgICAgICAgdmFyIGRlbGV0ZWRJdGVtcyA9IDA7XG5cbiAgICAgICAgICAgICAgICAvLyBJdGVyYXRlIHRocm91Z2ggYSBhbmQgbWF0Y2ggYSBub2RlIGluIGJcbiAgICAgICAgICAgICAgICAvLyBPKE4pIHRpbWUsXG4gICAgICAgICAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCBhQ2hpbGRyZW4ubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgICAgICAgICAgdmFyIGFJdGVtID0gYUNoaWxkcmVuW2ldO1xuICAgICAgICAgICAgICAgICAgICB2YXIgaXRlbUluZGV4O1xuXG4gICAgICAgICAgICAgICAgICAgIGlmIChhSXRlbS5rZXkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChiS2V5cy5oYXNPd25Qcm9wZXJ0eShhSXRlbS5rZXkpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gTWF0Y2ggdXAgdGhlIG9sZCBrZXlzXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaXRlbUluZGV4ID0gYktleXNbYUl0ZW0ua2V5XTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBuZXdDaGlsZHJlbi5wdXNoKGJDaGlsZHJlbltpdGVtSW5kZXhdKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gUmVtb3ZlIG9sZCBrZXllZCBpdGVtc1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGl0ZW1JbmRleCA9IGkgLSBkZWxldGVkSXRlbXMrKztcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBuZXdDaGlsZHJlbi5wdXNoKG51bGwpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgLy8gTWF0Y2ggdGhlIGl0ZW0gaW4gYSB3aXRoIHRoZSBuZXh0IGZyZWUgaXRlbSBpbiBiXG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoZnJlZUluZGV4IDwgZnJlZUNvdW50KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaXRlbUluZGV4ID0gYkZyZWVbZnJlZUluZGV4KytdO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIG5ld0NoaWxkcmVuLnB1c2goYkNoaWxkcmVuW2l0ZW1JbmRleF0pO1xuICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBUaGVyZSBhcmUgbm8gZnJlZSBpdGVtcyBpbiBiIHRvIG1hdGNoIHdpdGhcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyB0aGUgZnJlZSBpdGVtcyBpbiBhLCBzbyB0aGUgZXh0cmEgZnJlZSBub2Rlc1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIGFyZSBkZWxldGVkLlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGl0ZW1JbmRleCA9IGkgLSBkZWxldGVkSXRlbXMrKztcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBuZXdDaGlsZHJlbi5wdXNoKG51bGwpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgdmFyIGxhc3RGcmVlSW5kZXggPSBmcmVlSW5kZXggPj0gYkZyZWUubGVuZ3RoID8gYkNoaWxkcmVuLmxlbmd0aCA6IGJGcmVlW2ZyZWVJbmRleF07XG5cbiAgICAgICAgICAgICAgICAvLyBJdGVyYXRlIHRocm91Z2ggYiBhbmQgYXBwZW5kIGFueSBuZXcga2V5c1xuICAgICAgICAgICAgICAgIC8vIE8oTSkgdGltZVxuICAgICAgICAgICAgICAgIGZvciAodmFyIGogPSAwOyBqIDwgYkNoaWxkcmVuLmxlbmd0aDsgaisrKSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciBuZXdJdGVtID0gYkNoaWxkcmVuW2pdO1xuXG4gICAgICAgICAgICAgICAgICAgIGlmIChuZXdJdGVtLmtleSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKCFhS2V5cy5oYXNPd25Qcm9wZXJ0eShuZXdJdGVtLmtleSkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBBZGQgYW55IG5ldyBrZXllZCBpdGVtc1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIFdlIGFyZSBhZGRpbmcgbmV3IGl0ZW1zIHRvIHRoZSBlbmQgYW5kIHRoZW4gc29ydGluZyB0aGVtXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gaW4gcGxhY2UuIEluIGZ1dHVyZSB3ZSBzaG91bGQgaW5zZXJ0IG5ldyBpdGVtcyBpbiBwbGFjZS5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBuZXdDaGlsZHJlbi5wdXNoKG5ld0l0ZW0pO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKGogPj0gbGFzdEZyZWVJbmRleCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgLy8gQWRkIGFueSBsZWZ0b3ZlciBub24ta2V5ZWQgaXRlbXNcbiAgICAgICAgICAgICAgICAgICAgICAgIG5ld0NoaWxkcmVuLnB1c2gobmV3SXRlbSk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICB2YXIgc2ltdWxhdGUgPSBuZXdDaGlsZHJlbi5zbGljZSgpO1xuICAgICAgICAgICAgICAgIHZhciBzaW11bGF0ZUluZGV4ID0gMDtcbiAgICAgICAgICAgICAgICB2YXIgcmVtb3ZlcyA9IFtdO1xuICAgICAgICAgICAgICAgIHZhciBpbnNlcnRzID0gW107XG4gICAgICAgICAgICAgICAgdmFyIHNpbXVsYXRlSXRlbTtcblxuICAgICAgICAgICAgICAgIGZvciAodmFyIGsgPSAwOyBrIDwgYkNoaWxkcmVuLmxlbmd0aDspIHtcbiAgICAgICAgICAgICAgICAgICAgdmFyIHdhbnRlZEl0ZW0gPSBiQ2hpbGRyZW5ba107XG4gICAgICAgICAgICAgICAgICAgIHNpbXVsYXRlSXRlbSA9IHNpbXVsYXRlW3NpbXVsYXRlSW5kZXhdO1xuXG4gICAgICAgICAgICAgICAgICAgIC8vIHJlbW92ZSBpdGVtc1xuICAgICAgICAgICAgICAgICAgICB3aGlsZSAoc2ltdWxhdGVJdGVtID09PSBudWxsICYmIHNpbXVsYXRlLmxlbmd0aCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgcmVtb3Zlcy5wdXNoKHJlbW92ZShzaW11bGF0ZSwgc2ltdWxhdGVJbmRleCwgbnVsbCkpO1xuICAgICAgICAgICAgICAgICAgICAgICAgc2ltdWxhdGVJdGVtID0gc2ltdWxhdGVbc2ltdWxhdGVJbmRleF07XG4gICAgICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgICAgICBpZiAoIXNpbXVsYXRlSXRlbSB8fCBzaW11bGF0ZUl0ZW0ua2V5ICE9PSB3YW50ZWRJdGVtLmtleSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgLy8gaWYgd2UgbmVlZCBhIGtleSBpbiB0aGlzIHBvc2l0aW9uLi4uXG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAod2FudGVkSXRlbS5rZXkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoc2ltdWxhdGVJdGVtICYmIHNpbXVsYXRlSXRlbS5rZXkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gaWYgYW4gaW5zZXJ0IGRvZXNuJ3QgcHV0IHRoaXMga2V5IGluIHBsYWNlLCBpdCBuZWVkcyB0byBtb3ZlXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChiS2V5c1tzaW11bGF0ZUl0ZW0ua2V5XSAhPT0gayArIDEpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlbW92ZXMucHVzaChyZW1vdmUoc2ltdWxhdGUsIHNpbXVsYXRlSW5kZXgsIHNpbXVsYXRlSXRlbS5rZXkpKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNpbXVsYXRlSXRlbSA9IHNpbXVsYXRlW3NpbXVsYXRlSW5kZXhdO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gaWYgdGhlIHJlbW92ZSBkaWRuJ3QgcHV0IHRoZSB3YW50ZWQgaXRlbSBpbiBwbGFjZSwgd2UgbmVlZCB0byBpbnNlcnQgaXRcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmICghc2ltdWxhdGVJdGVtIHx8IHNpbXVsYXRlSXRlbS5rZXkgIT09IHdhbnRlZEl0ZW0ua2V5KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaW5zZXJ0cy5wdXNoKHsga2V5OiB3YW50ZWRJdGVtLmtleSwgdG86IGsgfSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBpdGVtcyBhcmUgbWF0Y2hpbmcsIHNvIHNraXAgYWhlYWRcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNpbXVsYXRlSW5kZXgrKztcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGluc2VydHMucHVzaCh7IGtleTogd2FudGVkSXRlbS5rZXksIHRvOiBrIH0pO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaW5zZXJ0cy5wdXNoKHsga2V5OiB3YW50ZWRJdGVtLmtleSwgdG86IGsgfSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGsrKztcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIGEga2V5IGluIHNpbXVsYXRlIGhhcyBubyBtYXRjaGluZyB3YW50ZWQga2V5LCByZW1vdmUgaXRcbiAgICAgICAgICAgICAgICAgICAgICAgIGVsc2UgaWYgKHNpbXVsYXRlSXRlbSAmJiBzaW11bGF0ZUl0ZW0ua2V5KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcmVtb3Zlcy5wdXNoKHJlbW92ZShzaW11bGF0ZSwgc2ltdWxhdGVJbmRleCwgc2ltdWxhdGVJdGVtLmtleSkpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgc2ltdWxhdGVJbmRleCsrO1xuICAgICAgICAgICAgICAgICAgICAgICAgaysrO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgLy8gcmVtb3ZlIGFsbCB0aGUgcmVtYWluaW5nIG5vZGVzIGZyb20gc2ltdWxhdGVcbiAgICAgICAgICAgICAgICB3aGlsZSAoc2ltdWxhdGVJbmRleCA8IHNpbXVsYXRlLmxlbmd0aCkge1xuICAgICAgICAgICAgICAgICAgICBzaW11bGF0ZUl0ZW0gPSBzaW11bGF0ZVtzaW11bGF0ZUluZGV4XTtcbiAgICAgICAgICAgICAgICAgICAgcmVtb3Zlcy5wdXNoKHJlbW92ZShzaW11bGF0ZSwgc2ltdWxhdGVJbmRleCwgc2ltdWxhdGVJdGVtICYmIHNpbXVsYXRlSXRlbS5rZXkpKTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAvLyBJZiB0aGUgb25seSBtb3ZlcyB3ZSBoYXZlIGFyZSBkZWxldGVzIHRoZW4gd2UgY2FuIGp1c3RcbiAgICAgICAgICAgICAgICAvLyBsZXQgdGhlIGRlbGV0ZSBwYXRjaCByZW1vdmUgdGhlc2UgaXRlbXMuXG4gICAgICAgICAgICAgICAgaWYgKHJlbW92ZXMubGVuZ3RoID09PSBkZWxldGVkSXRlbXMgJiYgIWluc2VydHMubGVuZ3RoKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiB7XG4gICAgICAgICAgICAgICAgICAgICAgICBjaGlsZHJlbjogbmV3Q2hpbGRyZW4sXG4gICAgICAgICAgICAgICAgICAgICAgICBtb3ZlczogbnVsbFxuICAgICAgICAgICAgICAgICAgICB9O1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHJldHVybiB7XG4gICAgICAgICAgICAgICAgICAgIGNoaWxkcmVuOiBuZXdDaGlsZHJlbixcbiAgICAgICAgICAgICAgICAgICAgbW92ZXM6IHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJlbW92ZXM6IHJlbW92ZXMsXG4gICAgICAgICAgICAgICAgICAgICAgICBpbnNlcnRzOiBpbnNlcnRzXG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9O1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBmdW5jdGlvbiByZW1vdmUoYXJyLCBpbmRleCwga2V5KSB7XG4gICAgICAgICAgICAgICAgYXJyLnNwbGljZShpbmRleCwgMSk7XG5cbiAgICAgICAgICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgICAgICAgICBmcm9tOiBpbmRleCxcbiAgICAgICAgICAgICAgICAgICAga2V5OiBrZXlcbiAgICAgICAgICAgICAgICB9O1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBmdW5jdGlvbiBrZXlJbmRleChjaGlsZHJlbikge1xuICAgICAgICAgICAgICAgIHZhciBrZXlzID0ge307XG4gICAgICAgICAgICAgICAgdmFyIGZyZWUgPSBbXTtcbiAgICAgICAgICAgICAgICB2YXIgbGVuZ3RoID0gY2hpbGRyZW4ubGVuZ3RoO1xuXG4gICAgICAgICAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCBsZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgICAgICAgICB2YXIgY2hpbGQgPSBjaGlsZHJlbltpXTtcblxuICAgICAgICAgICAgICAgICAgICBpZiAoY2hpbGQua2V5KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBrZXlzW2NoaWxkLmtleV0gPSBpO1xuICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgZnJlZS5wdXNoKGkpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgICAgICAgICAga2V5czoga2V5cywgLy8gQSBoYXNoIG9mIGtleSBuYW1lIHRvIGluZGV4XG4gICAgICAgICAgICAgICAgICAgIGZyZWU6IGZyZWUgLy8gQW4gYXJyYXkgb2YgdW5rZXllZCBpdGVtIGluZGljZXNcbiAgICAgICAgICAgICAgICB9O1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBmdW5jdGlvbiBhcHBlbmRQYXRjaChhcHBseSwgcGF0Y2gpIHtcbiAgICAgICAgICAgICAgICBpZiAoYXBwbHkpIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKGlzQXJyYXkoYXBwbHkpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBhcHBseS5wdXNoKHBhdGNoKTtcbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGFwcGx5ID0gW2FwcGx5LCBwYXRjaF07XG4gICAgICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgICAgICByZXR1cm4gYXBwbHk7XG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHBhdGNoO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgfSwgeyBcIi4uL3Zub2RlL2hhbmRsZS10aHVua1wiOiAyNCwgXCIuLi92bm9kZS9pcy10aHVua1wiOiAyNSwgXCIuLi92bm9kZS9pcy12bm9kZVwiOiAyNywgXCIuLi92bm9kZS9pcy12dGV4dFwiOiAyOCwgXCIuLi92bm9kZS9pcy13aWRnZXRcIjogMjksIFwiLi4vdm5vZGUvdnBhdGNoXCI6IDMyLCBcIi4vZGlmZi1wcm9wc1wiOiAzNCwgXCJ4LWlzLWFycmF5XCI6IDEyIH1dIH0sIHt9LCBbNF0pKDQpO1xufSk7XG5cblxuLy8gUHJvcG9zZWQgZm9yIEVTNlxuXG5jb25zdCBzdGFydCA9IGZ1bmN0aW9uIChkb21Sb290LCByZW5kZXJGbiwgaW5pdGlhbFN0YXRlLCBvcHRpb25zID0gW10pIHtcbiAgY29uc3QgbmFtZSA9IEtleXdvcmQuaGFzX2tleV9fcW1fXyhvcHRpb25zLCBLZXJuZWwuU3BlY2lhbEZvcm1zLmF0b20oJ25hbWUnKSkgPyBLZXl3b3JkLmdldChvcHRpb25zLCBLZXJuZWwuU3BlY2lhbEZvcm1zLmF0b20oJ25hbWUnKSkgOiBTeW1ib2woKTtcblxuICBzZWxmLnBvc3Rfb2ZmaWNlLmFkZF9tYWlsYm94KG5hbWUpO1xuXG4gIGNvbnN0IHRyZWUgPSByZW5kZXJGbi5hcHBseSh0aGlzLCBpbml0aWFsU3RhdGUpO1xuICBjb25zdCByb290Tm9kZSA9IHZpcnR1YWxEb20uY3JlYXRlKHRyZWUpO1xuXG4gIGRvbVJvb3QuYXBwZW5kQ2hpbGQocm9vdE5vZGUpO1xuICBzZWxmLnBvc3Rfb2ZmaWNlLnNlbmQobmFtZSwgS2VybmVsLlNwZWNpYWxGb3Jtcy50dXBsZShyb290Tm9kZSwgdHJlZSwgcmVuZGVyRm4pKTtcblxuICByZXR1cm4gS2VybmVsLlNwZWNpYWxGb3Jtcy50dXBsZShLZXJuZWwuU3BlY2lhbEZvcm1zLmF0b20oJ29rJyksIG5hbWUpO1xufTtcblxuY29uc3Qgc3RvcCA9IGZ1bmN0aW9uIChhZ2VudCwgdGltZW91dCA9IDUwMDApIHtcbiAgc2VsZi5wb3N0X29mZmljZS5yZW1vdmVfbWFpbGJveChhZ2VudCk7XG4gIHJldHVybiBLZXJuZWwuU3BlY2lhbEZvcm1zLmF0b20oJ29rJyk7XG59O1xuXG5jb25zdCByZW5kZXIgPSBmdW5jdGlvbiAoYWdlbnQsIHN0YXRlKSB7XG5cbiAgY29uc3QgY3VycmVudF9zdGF0ZSA9IHNlbGYucG9zdF9vZmZpY2UucmVjZWl2ZShhZ2VudCk7XG5cbiAgbGV0IHJvb3ROb2RlID0gS2VybmVsLmVsZW0oY3VycmVudF9zdGF0ZSwgMCk7XG4gIGxldCB0cmVlID0gS2VybmVsLmVsZW0oY3VycmVudF9zdGF0ZSwgMSk7XG4gIGxldCByZW5kZXJGbiA9IEtlcm5lbC5lbGVtKGN1cnJlbnRfc3RhdGUsIDIpO1xuXG4gIGxldCBuZXdUcmVlID0gcmVuZGVyRm4uYXBwbHkodGhpcywgc3RhdGUpO1xuXG4gIGxldCBwYXRjaGVzID0gdmlydHVhbERvbS5kaWZmKHRyZWUsIG5ld1RyZWUpO1xuICByb290Tm9kZSA9IHZpcnR1YWxEb20ucGF0Y2gocm9vdE5vZGUsIHBhdGNoZXMpO1xuXG4gIHNlbGYucG9zdF9vZmZpY2Uuc2VuZChhZ2VudCwgS2VybmVsLlNwZWNpYWxGb3Jtcy50dXBsZShyb290Tm9kZSwgbmV3VHJlZSwgcmVuZGVyRm4pKTtcblxuICByZXR1cm4gS2VybmVsLlNwZWNpYWxGb3Jtcy5hdG9tKCdvaycpO1xufTtcblxudmFyIFZpZXcgPSB7XG4gIHN0YXJ0LFxuICBzdG9wLFxuICByZW5kZXJcbn07XG5cbnNlbGYucG9zdF9vZmZpY2UgPSBzZWxmLnBvc3Rfb2ZmaWNlIHx8IG5ldyBQb3N0T2ZmaWNlKCk7XG5cbmV4cG9ydCB7IF9QYXR0ZXJucyBhcyBQYXR0ZXJucywgQml0U3RyaW5nLCBLZXJuZWwsIEF0b20sIEVudW0sIEludGVnZXIsIEpTLCBMaXN0LCBSYW5nZSwgVHVwbGUsIEFnZW50LCBLZXl3b3JkLCBCYXNlLCBfU3RyaW5nIGFzIFN0cmluZywgQml0d2lzZSwgRW51bWVyYWJsZSwgQ29sbGVjdGFibGUsIEluc3BlY3QsIF9NYXAgYXMgTWFwLCBfU2V0IGFzIFNldCwgTWFwU2V0LCBJbnRlZ2VyVHlwZSwgRmxvYXRUeXBlLCB2aXJ0dWFsRG9tIGFzIFZpcnR1YWxET00sIFZpZXcgfTsiXSwiZmlsZSI6ImVsaXhpci5qcyIsInNvdXJjZVJvb3QiOiIvc291cmNlLyJ9 \ No newline at end of file From 0b826025c46a4684b8caeff5d58ec40c78feb242 Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Sat, 28 Nov 2015 12:43:07 -0600 Subject: [PATCH 067/860] Added stdlib_path option to compiler --- CHANGELOG.md | 2 ++ lib/elixir_script.ex | 24 +++++++++++---------- lib/elixir_script/cli.ex | 17 +++++++++------ lib/elixir_script/translator/import.ex | 11 +++++----- lib/mix/tasks/elixirscript.ex | 5 ++++- test/elixir_script_test.exs | 29 ++++++++++++++++++++++++++ 6 files changed, 65 insertions(+), 23 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 8c6444af..33ea116a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,8 @@ * Added ElixirScript.Html module for defining a virtual-dom tree * Added ElixirScript.VDom module for manipulating the virtual-dom tree created using the ElixirScript.Html module + * Added `stdlib_path` compiler option to specify the es6 path to the standard library. + If used, elixir.js will not be exported with the compiled modules # v0.13.0 diff --git a/lib/elixir_script.ex b/lib/elixir_script.ex index e2d057c4..004d0f3d 100644 --- a/lib/elixir_script.ex +++ b/lib/elixir_script.ex @@ -17,10 +17,10 @@ defmodule ElixirScript do Available options are: * `:include_path` - a boolean controlling whether to return just the JavaScript code or a tuple of the file name and the JavaScript code - * `:root` - a binary path prepended to the path of the standard lib imports if needed * `:env` - a Macro.env struct to use. This is most useful when using macros. Make sure that the - given env has the macros required. Defaults to __ENV__. + * `:stdlib_path` - The es6 import path used to import the elixirscript standard lib. + When using this option, the elixir.js file is not exported """ @doc """ @@ -42,11 +42,12 @@ defmodule ElixirScript do root = Dict.get(opts, :root) env = Dict.get(opts, :env, custom_env) import_standard_libs? = Dict.get(opts, :import_standard_libs, true) + stdlib_path = Dict.get(opts, :stdlib_path, "elixir") ElixirScript.State.start_link(root, env) build_environment([quoted]) - create_code(include_path, import_standard_libs?) + create_code(include_path, import_standard_libs?, stdlib_path) end @doc """ @@ -57,6 +58,7 @@ defmodule ElixirScript do include_path = Dict.get(opts, :include_path, false) root = Dict.get(opts, :root) env = Dict.get(opts, :env, custom_env) + stdlib_path = Dict.get(opts, :stdlib_path, "elixir") ElixirScript.State.start_link(root, env) @@ -65,7 +67,7 @@ defmodule ElixirScript do |> Enum.map(&file_to_quoted/1) |> build_environment - create_code(include_path, true) + create_code(include_path, true, stdlib_path) end defp file_to_quoted(file) do @@ -87,7 +89,7 @@ defmodule ElixirScript do __ENV__ end - defp create_code(include_path, import_standard_libs?) do + defp create_code(include_path, import_standard_libs?, stdlib_path) do ElixirScript.State.process_imports @@ -103,7 +105,7 @@ defmodule ElixirScript do result = ElixirScript.Translator.Module.make_module(ast.name, ast.body, state.env) - |> Enum.map(&(convert_to_code(&1, state.root, include_path, state.env, import_standard_libs?))) + |> Enum.map(&(convert_to_code(&1, state.root, include_path, state.env, import_standard_libs?, stdlib_path))) send parent, {self, result} end end) @@ -118,7 +120,7 @@ defmodule ElixirScript do state.protocols |> Dict.to_list |> ElixirScript.Translator.Protocol.consolidate(state.env) - |> Enum.map(&(convert_to_code(&1, state.root, include_path, state.env, import_standard_libs?))) + |> Enum.map(&(convert_to_code(&1, state.root, include_path, state.env, import_standard_libs?, stdlib_path))) |> List.flatten ElixirScript.State.stop @@ -141,19 +143,19 @@ defmodule ElixirScript do File.read!(operating_path <> "/elixir.js") end - defp convert_to_code(js_ast, root, include_path, env, import_standard_libs) do + defp convert_to_code(js_ast, root, include_path, env, import_standard_libs, stdlib_path) do js_ast - |> process_module(root, env, import_standard_libs) + |> process_module(root, env, import_standard_libs, stdlib_path) |> javascript_ast_to_code |> process_include_path(include_path) end - defp process_module(%JSModule{} = module, root, env, import_standard_libs) do + defp process_module(%JSModule{} = module, root, env, import_standard_libs, stdlib_path) do file_path = create_file_name(module) standard_libs_import = if import_standard_libs do - ElixirScript.Translator.Import.create_standard_lib_imports(root, env) + ElixirScript.Translator.Import.create_standard_lib_imports(root, stdlib_path) else [] end diff --git a/lib/elixir_script/cli.ex b/lib/elixir_script/cli.ex index 77a49523..82d2e5bc 100644 --- a/lib/elixir_script/cli.ex +++ b/lib/elixir_script/cli.ex @@ -3,11 +3,11 @@ defmodule ElixirScript.CLI do @switches [ output: :binary, elixir: :boolean, root: :binary, - help: :boolean, stdlib: :boolean + help: :boolean, stdlib: :boolean, stdlib_path: :binary ] @aliases [ - o: :output, ex: :elixir, h: :help, r: :root, st: :stdlib + o: :output, ex: :elixir, h: :help, r: :root, st: :stdlib, stp: :stdlib_path ] def main(argv) do @@ -23,7 +23,7 @@ defmodule ElixirScript.CLI do { [help: true] , _ , _ } -> :help { [stdlib: true] , _ , _ } -> :stdlib { options , [input], _ } -> { input, options } - { [], [], [] } -> :help + _ -> :help end end @@ -36,8 +36,10 @@ defmodule ElixirScript.CLI do options: -o --output [path] places output at the given path -ex --elixir read input as elixir code string - -r --root [path] root path for standard libs + -r --root [path] root import path for all exported modules -st --stdlib outputs the standard lib js file + -stp --stdlib_path es6 import path to the elixirscript standard lib + only used with the [output] option. When used, elixir.js is not exported -h --help this message """ end @@ -57,7 +59,8 @@ defmodule ElixirScript.CLI do def do_process(input, options) do compile_opts = [ root: options[:root], - include_path: options[:output] != nil + include_path: options[:output] != nil, + stdlib_path: Dict.get(options, :stdlib_path, "elixir") ] compile_output = case options[:elixir] do @@ -79,7 +82,9 @@ defmodule ElixirScript.CLI do write_to_file(x, output_path) end) - ElixirScript.copy_standard_libs_to_destination(output_path) + if Dict.get(options, :stdlib_path) == nil do + ElixirScript.copy_standard_libs_to_destination(output_path) + end end end diff --git a/lib/elixir_script/translator/import.ex b/lib/elixir_script/translator/import.ex index 5c6617ec..eb7ad17d 100644 --- a/lib/elixir_script/translator/import.ex +++ b/lib/elixir_script/translator/import.ex @@ -159,7 +159,7 @@ defmodule ElixirScript.Translator.Import do defp make_source(name) do root = ElixirScript.State.get().root - "'#{root(root)}#{make_file_path(name)}'" + "'#{make_root(root)}#{make_file_path(name)}'" end def make_file_path(name) do @@ -180,24 +180,25 @@ defmodule ElixirScript.Translator.Import do Set.difference(Enum.into(functions, HashSet.new), Enum.into(except, HashSet.new)) end - def create_standard_lib_imports(root, _) do + def create_standard_lib_imports(root, name) do + import_specifier = JS.import_namespace_specifier( JS.identifier(:Elixir) ) import_declaration = JS.import_declaration( [import_specifier], - JS.identifier("'#{root(root) <> "elixir"}'") + JS.identifier("'#{make_root(root) <> name}'") ) [import_declaration] end - defp root(nil) do + defp make_root(nil) do "" end - defp root(root) do + defp make_root(root) do root <> "/" end diff --git a/lib/mix/tasks/elixirscript.ex b/lib/mix/tasks/elixirscript.ex index c2839f38..34e4cb5d 100644 --- a/lib/mix/tasks/elixirscript.ex +++ b/lib/mix/tasks/elixirscript.ex @@ -7,7 +7,10 @@ defmodule Mix.Tasks.Elixirscript do options: -o --output [path] places output at the given path -ex --elixir read input as elixir code string - -r --root [path] root path for standard libs + -r --root [path] root import path for all exported modules + -st --stdlib outputs the standard lib js file + -stp --stdlib_path es6 import path to the elixirscript standard lib + only used with the [output] option. When used, elixir.js is not exported -h --help this message """ diff --git a/test/elixir_script_test.exs b/test/elixir_script_test.exs index a9e236fd..4d7dbe42 100644 --- a/test/elixir_script_test.exs +++ b/test/elixir_script_test.exs @@ -141,4 +141,33 @@ defmodule ElixirScript.Test do assert hd(js_code) =~ "Elixir.VirtualDOM.create" end + + should "set standard lib path" do + + js_code = ElixirScript.compile(""" + defmodule Animals do + use ElixirScript.Using + + defp something_else() do + ElixirScript.Math.squared(1) + end + + end + """, env: make_custom_env, stdlib_path: "elixirscript") + + assert_js_matches """ + import * as Elixir from 'elixirscript'; + const __MODULE__ = Elixir.Kernel.SpecialForms.atom('Animals'); + const something_else = Elixir.Patterns.defmatch(Elixir.Patterns.make_case([],function() { + return 1 * 1; + })); + const sandwich = Elixir.Patterns.defmatch(Elixir.Patterns.make_case([],function() { + return null; + })); + export { + sandwich + }; + """, hd(js_code) + end + end From 0bb615885a8b9dd9d2e967bc0d01ce604d948482 Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Wed, 2 Dec 2015 18:42:52 -0600 Subject: [PATCH 068/860] Replaced PostOffice with ProcessSystem --- lib/elixir_script/translator/primitive.ex | 5 +- lib/elixir_script/translator/protocol.ex | 12 +- package.json | 2 +- priv/elixir.js | 1504 +++++++++-------- src/javascript/elixir.js | 5 +- src/javascript/lib/agent.js | 26 +- src/javascript/lib/core.js | 2 + .../{processes/processes => core}/mailbox.js | 0 src/javascript/lib/core/primitives.js | 47 + src/javascript/lib/core/process.js | 20 + src/javascript/lib/core/process_system.js | 158 ++ .../{processes/processes => core}/states.js | 0 src/javascript/lib/kernel.js | 8 +- src/javascript/lib/kernel/special_forms.js | 4 +- src/javascript/lib/patterns/patterns.js | 7 +- src/javascript/lib/post_office.js | 98 -- src/javascript/lib/processes/processes.js | 5 - .../processes/processes/otp/application.js | 5 - .../lib/processes/processes/otp/gen_event.js | 38 - .../lib/processes/processes/otp/gen_server.js | 74 - src/javascript/lib/processes/processes/pid.js | 18 - .../lib/processes/processes/process.js | 147 -- .../lib/processes/processes/process_system.js | 257 --- .../lib/processes/processes/scheduler.js | 103 -- src/javascript/lib/signals.js | 61 - src/javascript/lib/string/chars.js | 3 +- src/javascript/lib/tuple.js | 120 +- src/javascript/lib/view.js | 16 +- src/javascript/lib/virtual-dom.js | 4 +- .../tests/patterns/defmatch.spec.js | 2 +- src/javascript/tests/string.chars.spec.js | 4 +- test/translator/assignment_test.exs | 6 +- test/translator/case_test.exs | 10 +- test/translator/for_test.exs | 2 +- test/translator/function_test.exs | 4 +- 35 files changed, 1100 insertions(+), 1677 deletions(-) create mode 100644 src/javascript/lib/core.js rename src/javascript/lib/{processes/processes => core}/mailbox.js (100%) create mode 100644 src/javascript/lib/core/primitives.js create mode 100644 src/javascript/lib/core/process.js create mode 100644 src/javascript/lib/core/process_system.js rename src/javascript/lib/{processes/processes => core}/states.js (100%) delete mode 100644 src/javascript/lib/post_office.js delete mode 100644 src/javascript/lib/processes/processes.js delete mode 100644 src/javascript/lib/processes/processes/otp/application.js delete mode 100644 src/javascript/lib/processes/processes/otp/gen_event.js delete mode 100644 src/javascript/lib/processes/processes/otp/gen_server.js delete mode 100644 src/javascript/lib/processes/processes/pid.js delete mode 100644 src/javascript/lib/processes/processes/process.js delete mode 100644 src/javascript/lib/processes/processes/process_system.js delete mode 100644 src/javascript/lib/processes/processes/scheduler.js delete mode 100644 src/javascript/lib/signals.js diff --git a/lib/elixir_script/translator/primitive.ex b/lib/elixir_script/translator/primitive.ex index a45ccd67..53c46aaa 100644 --- a/lib/elixir_script/translator/primitive.ex +++ b/lib/elixir_script/translator/primitive.ex @@ -17,7 +17,10 @@ defmodule ElixirScript.Translator.Primitive do def tuple_class() do JS.member_expression( - JS.identifier("Elixir"), + JS.member_expression( + JS.identifier("Elixir"), + JS.identifier("Core") + ), JS.identifier("Tuple") ) end diff --git a/lib/elixir_script/translator/protocol.ex b/lib/elixir_script/translator/protocol.ex index 07cecd2d..63e8acbd 100644 --- a/lib/elixir_script/translator/protocol.ex +++ b/lib/elixir_script/translator/protocol.ex @@ -189,7 +189,10 @@ defmodule ElixirScript.Translator.Protocol do defp map_to_js({:__aliases__, _, [:Tuple]}) do JS.member_expression( - JS.identifier(:Elixir), + JS.member_expression( + JS.identifier(:Elixir), + JS.identifier(:Core) + ), JS.identifier(:Tuple) ) end @@ -222,8 +225,11 @@ defmodule ElixirScript.Translator.Protocol do defp map_to_js({:__aliases__, _, [:PID]}) do JS.member_expression( - JS.identifier(:Elixir), - JS.identifier(:Reference) + JS.member_expression( + JS.identifier(:Elixir), + JS.identifier(:Core) + ), + JS.identifier(:PID) ) end diff --git a/package.json b/package.json index 624c0209..9116a303 100644 --- a/package.json +++ b/package.json @@ -29,6 +29,6 @@ "gulp-rollup": "^1.0.1", "gulp-sourcemaps": "^1.5.2", "mocha": "^2.3.3", - "rollup": "^0.14.1" + "rollup": "^0.21.1" } } diff --git a/priv/elixir.js b/priv/elixir.js index a24ece74..d7a8b4ce 100644 --- a/priv/elixir.js +++ b/priv/elixir.js @@ -1,7 +1,251 @@ -var Patterns = { - get default () { return _Patterns; } +/* @flow */ + +class Mailbox { + + constructor() { + this.messages = []; + } + + deliver(message) { + this.messages.push(message); + return message; + } + + get() { + return this.messages; + } + + isEmpty() { + return this.messages.length === 0; + } + + removeAt(index) { + this.messages.splice(index, 1); + } +} + +var States = { + NORMAL: Symbol.for("normal"), + KILL: Symbol.for("kill"), + SUSPEND: Symbol.for("suspend"), + CONTINUE: Symbol.for("continue"), + RECEIVE: Symbol.for("receive"), + SEND: Symbol.for("send"), + SLEEPING: Symbol.for("sleeping"), + RUNNING: Symbol.for("running"), + SUSPENDED: Symbol.for("suspended"), + STOPPED: Symbol.for("stopped"), + SLEEP: Symbol.for("sleep"), + EXIT: Symbol.for("exit"), + NOMATCH: Symbol.for("no_match") }; +class Process { + + constructor(pid, mailbox) { + this.pid = pid; + this.mailbox = mailbox; + this.status = States.STOPPED; + this.dict = {}; + } +} + +class Tuple$1 { + + constructor(...args) { + this.values = Object.freeze(args); + } + + get(index) { + return this.values[index]; + } + + count() { + return this.values.length; + } + + [Symbol.iterator]() { + return this.values[Symbol.iterator](); + } + + toString() { + var i, + s = ""; + for (i = 0; i < this.values.length; i++) { + if (s !== "") { + s += ", "; + } + s += this.values[i].toString(); + } + + return "{" + s + "}"; + } + +} + +let process_counter = -1; + +class PID { + constructor() { + process_counter = process_counter + 1; + this.id = process_counter; + } + + toString() { + return "PID#<0." + this.id + ".0>"; + } +} + +var Core = { PID, Tuple: Tuple$1 }; + +class ProcessSystem { + + constructor() { + this.pids = new Map(); + this.mailboxes = new Map(); + this.names = new Map(); + this.links = new Map(); + + this.current_process = null; + this.suspended = new Map(); + + this.main_process_pid = this.spawn(); + this.set_current(this.main_process_pid); + } + + spawn() { + return this.add_proc(false).pid; + } + + spawn_link() { + return this.add_proc(true).pid; + } + + link(pid) { + this.links.get(this.pid()).add(pid); + this.links.get(pid).add(this.pid()); + } + + unlink(pid) { + this.links.get(this.pid()).delete(pid); + this.links.get(pid).delete(this.pid()); + } + + set_current(id) { + let pid = this.pidof(id); + if (pid !== null) { + this.current_process = this.pids.get(pid); + this.current_process.status = States.RUNNING; + } + } + + add_proc(linked) { + let newpid = new Core.PID(); + let mailbox = new Mailbox(); + let newproc = new Process(newpid, mailbox); + + this.pids.set(newpid, newproc); + this.mailboxes.set(newpid, mailbox); + this.links.set(newpid, new Set()); + + if (linked) { + this.link(newpid); + } + + return newproc; + } + + remove_proc(pid) { + this.pids.delete(pid); + this.unregister(pid); + + if (this.links.has(pid)) { + for (let linkpid of this.links.get(pid)) { + this.links.get(linkpid).delete(pid); + } + + this.links.delete(pid); + } + } + + exit(id) { + let pid = this.pidof(id); + this.remove_proc(id); + } + + register(name, pid) { + if (!this.names.has(name)) { + this.names.set(name, pid); + return name; + } else { + throw new Error("Name is already registered to another process"); + } + } + + registered(name) { + return this.names.has(name) ? this.names.get(name) : null; + } + + unregister(pid) { + for (let name of this.names.keys()) { + if (this.names.has(name) && this.names.get(name) === pid) { + this.names.delete(name); + } + } + } + + pid() { + return this.current_process.pid; + } + + pidof(id) { + if (id instanceof Core.PID) { + return this.pids.has(id) ? id : null; + } else if (id instanceof Process) { + return id.pid; + } else { + let pid = this.registered(id); + if (pid === null) throw "Process name not registered: " + id + " (" + typeof id + ")"; + return pid; + } + } + + put(id, key, value) { + let pid = this.pidof(id); + let process = this.pids.get(pid); + process.dict[key] = value; + } + + get(id, key) { + let pid = this.pidof(id); + let process = this.pids.get(pid); + + if (key != null) { + return process.dict[key]; + } else { + return process.dict; + } + } + + get_keys(id) { + let pid = this.pidof(id); + let process = this.pids.get(pid); + + return Object.keys(process.dict); + } + + erase(id, key) { + let pid = this.pidof(id); + let process = this.pids.get(pid); + + if (key != null) { + delete process.dict[key]; + } else { + process.dict = {}; + } + } +} + /* @flow */ class Variable { @@ -76,7 +320,7 @@ function bound(value) { return new Bound(value); } -function _is_number(value) { +function is_number$1(value) { return typeof value === 'number'; } @@ -84,7 +328,7 @@ function is_string(value) { return typeof value === 'string'; } -function _is_boolean(value) { +function is_boolean$1(value) { return typeof value === 'boolean'; } @@ -100,7 +344,7 @@ function is_undefined(value) { return typeof value === 'undefined'; } -function _is_function(value) { +function is_function$1(value) { return Object.prototype.toString.call(value) == '[object Function]'; } @@ -141,13 +385,13 @@ function is_array(value) { } var Checks = { - is_number: _is_number, + is_number: is_number$1, is_string, - is_boolean: _is_boolean, + is_boolean: is_boolean$1, is_symbol, is_null, is_undefined, - is_function: _is_function, + is_function: is_function$1, is_variable, is_wildcard, is_headTail, @@ -464,117 +708,12 @@ function match_no_throw(pattern, expr, guard = () => true) { } } -function patternMap(collection, pattern, fun, guard = () => true) { - let ret = []; - - for (let elem of collection) { - try { - let result = fun.apply(this, match(pattern, elem, guard)); - ret = ret.concat(result); - } catch (e) { - if (!(e instanceof MatchError)) { - throw e; - } - } - } - - return ret; -} - -var _Patterns = { - defmatch, match, MatchError, match_no_throw, patternMap, +var Patterns = { + defmatch, match, MatchError, match_no_throw, variable, wildcard, startsWith, capture, headTail, type, bound, Case, make_case }; -class Tuple { - - constructor(...args) { - this.values = Object.freeze(args); - } - - get(index) { - return this.values[index]; - } - - count() { - return this.values.length; - } - - [Symbol.iterator]() { - return this.values[Symbol.iterator](); - } - - toString() { - var i, - s = ""; - for (i = 0; i < this.values.length; i++) { - if (s !== "") { - s += ", "; - } - s += this.values[i].toString(); - } - - return "{" + s + "}"; - } - - static to_string(tuple) { - return tuple.toString(); - } - - static delete_at(tuple, index) { - let new_list = []; - - for (var i = 0; i < tuple.count(); i++) { - if (i !== index) { - new_list.push(tuple.get(i)); - } - } - - return Kernel.SpecialForms.tuple.apply(null, new_list); - } - - static duplicate(data, size) { - let array = []; - - for (var i = size - 1; i >= 0; i--) { - array.push(data); - } - - return Kernel.SpecialForms.tuple.apply(null, array); - } - - static insert_at(tuple, index, term) { - let new_tuple = []; - - for (var i = 0; i <= tuple.count(); i++) { - if (i === index) { - new_tuple.push(term); - i++; - new_tuple.push(tuple.get(i)); - } else { - new_tuple.push(tuple.get(i)); - } - } - - return Kernel.SpecialForms.tuple.apply(null, new_tuple); - } - - static from_list(list) { - return Kernel.SpecialForms.tuple.apply(null, list); - } - - static to_list(tuple) { - let new_list = []; - - for (var i = 0; i < tuple.count(); i++) { - new_list.push(tuple.get(i)); - } - - return Kernel.SpecialForms.list(...new_list); - } -} - class BitString { constructor(...args) { this.raw_value = function () { @@ -868,52 +1007,252 @@ class BitString { } } -let SpecialForms = { - - __DIR__: function () { - if (__dirname) { - return __dirname; - } +let Enum = { - if (document.currentScript) { - return document.currentScript.src; + all__qmark__: function (collection, fun = x => x) { + for (let elem of collection) { + if (!fun(elem)) { + return false; + } } - return null; + return true; }, - atom: function (_value) { - return Symbol.for(_value); - }, + any__qmark__: function (collection, fun = x => x) { + for (let elem of collection) { + if (fun(elem)) { + return true; + } + } - list: function (...args) { - return Object.freeze(args); + return false; }, - bitstring: function (...args) { - return new BitString(...args); - }, + at: function (collection, n, the_default = null) { + if (n > this.count(collection) || n < 0) { + return the_default; + } - bound: function (_var) { - return Patterns.bound(_var); + return collection[n]; }, - _case: function (condition, clauses) { - return Patterns.defmatch(...clauses)(condition); + concat: function (...enumables) { + return enumables[0].concat(enumables[1]); }, - cond: function (clauses) { - for (let clause of clauses) { - if (clause[0]) { - return clause[1](); - } + count: function (collection, fun = null) { + if (fun == null) { + return collection.length; + } else { + return collection.filter(fun).length; } - - throw new Error(); }, - fn: function (clauses) { - return Patterns.defmatch(clauses); + drop: function (collection, count) { + return collection.slice(count); + }, + + drop_while: function (collection, fun) { + let count = 0; + + for (let elem of collection) { + if (fun(elem)) { + count = count + 1; + } else { + break; + } + } + + return collection.slice(count); + }, + + each: function (collection, fun) { + for (let elem of collection) { + fun(elem); + } + }, + + empty__qmark__: function (collection) { + return collection.length === 0; + }, + + fetch: function (collection, n) { + if (Kernel.is_list(collection)) { + if (n < this.count(collection) && n >= 0) { + return Kernel.SpecialForms.tuple(Kernel.SpecialForms.atom("ok"), collection[n]); + } else { + return Kernel.SpecialForms.atom("error"); + } + } + + throw new Error("collection is not an Enumerable"); + }, + + fetch__emark__: function (collection, n) { + if (Kernel.is_list(collection)) { + if (n < this.count(collection) && n >= 0) { + return collection[n]; + } else { + throw new Error("out of bounds error"); + } + } + + throw new Error("collection is not an Enumerable"); + }, + + filter: function (collection, fun) { + let result = []; + + for (let elem of collection) { + if (fun(elem)) { + result.push(elem); + } + } + + return result; + }, + + filter_map: function (collection, filter, mapper) { + return Enum.map(Enum.filter(collection, filter), mapper); + }, + + find: function (collection, if_none = null, fun) { + for (let elem of collection) { + if (fun(elem)) { + return elem; + } + } + + return if_none; + }, + + into: function (collection, list) { + return list.concat(collection); + }, + + map: function (collection, fun) { + let result = []; + + for (let elem of collection) { + result.push(fun(elem)); + } + + return result; + }, + + map_reduce: function (collection, acc, fun) { + let mapped = Kernel.SpecialForms.list(); + let the_acc = acc; + + for (var i = 0; i < this.count(collection); i++) { + let tuple = fun(collection[i], the_acc); + + the_acc = Kernel.elem(tuple, 1); + mapped = Kernel.SpecialForms.list(...mapped.concat([Kernel.elem(tuple, 0)])); + } + + return Kernel.SpecialForms.tuple(mapped, the_acc); + }, + + member: function (collection, value) { + return collection.includes(value); + }, + + reduce: function (collection, acc, fun) { + let the_acc = acc; + + for (var i = 0; i < this.count(collection); i++) { + let tuple = fun(collection[i], the_acc); + + the_acc = Kernel.elem(tuple, 1); + } + + return the_acc; + }, + + take: function (collection, count) { + return collection.slice(0, count); + }, + + take_every: function (collection, nth) { + let result = []; + let index = 0; + + for (let elem of collection) { + if (index % nth === 0) { + result.push(elem); + } + } + + return Kernel.SpecialForms.list(...result); + }, + + take_while: function (collection, fun) { + let count = 0; + + for (let elem of collection) { + if (fun(elem)) { + count = count + 1; + } else { + break; + } + } + + return collection.slice(0, count); + }, + + to_list: function (collection) { + return collection; + } +}; + +let SpecialForms = { + + __DIR__: function () { + if (__dirname) { + return __dirname; + } + + if (document.currentScript) { + return document.currentScript.src; + } + + return null; + }, + + atom: function (_value) { + return Symbol.for(_value); + }, + + list: function (...args) { + return Object.freeze(args); + }, + + bitstring: function (...args) { + return new BitString(...args); + }, + + bound: function (_var) { + return undefined(_var); + }, + + _case: function (condition, clauses) { + return undefined(...clauses)(condition); + }, + + cond: function (clauses) { + for (let clause of clauses) { + if (clause[0]) { + return clause[1](); + } + } + + throw new Error(); + }, + + fn: function (clauses) { + return undefined(clauses); }, map: function (obj) { @@ -931,7 +1270,7 @@ let SpecialForms = { if (collections.length === 1) { for (let elem of collection) { - let r = Patterns.match_no_throw(pattern, elem); + let r = undefined(pattern, elem); let args = previousValues.concat(r); if (r && filter.apply(this, args)) { @@ -944,7 +1283,7 @@ let SpecialForms = { let _into = []; for (let elem of collection) { - let r = Patterns.match_no_throw(pattern, elem); + let r = undefined(pattern, elem); if (r) { _into = Enum.into(this._for(collections.slice(1), fun, filter, _into, previousValues.concat(r)), into); } @@ -986,7 +1325,7 @@ let SpecialForms = { }, tuple: function (...args) { - return new Tuple(...args); + return new Core.Tuple(...args); }, _try: function (do_fun, rescue_function, catch_fun, else_function, after_function) { @@ -1002,7 +1341,7 @@ let SpecialForms = { ex_result = rescue_function(e); return ex_result; } catch (ex) { - if (ex instanceof Patterns.MatchError) { + if (ex instanceof undefined) { throw ex; } } @@ -1013,7 +1352,7 @@ let SpecialForms = { ex_result = catch_fun(e); return ex_result; } catch (ex) { - if (ex instanceof Patterns.MatchError) { + if (ex instanceof undefined) { throw ex; } } @@ -1030,7 +1369,7 @@ let SpecialForms = { try { return else_function(result); } catch (ex) { - if (ex instanceof Patterns.MatchError) { + if (ex instanceof undefined) { throw new Error('No Match Found in Else'); } @@ -1043,20 +1382,70 @@ let SpecialForms = { }; -/* @flow */ +function to_string$1(tuple) { + return tuple.toString(); +}; -let process_counter = -1; +function delete_at(tuple, index) { + let new_list = []; -class PID { - constructor() { - process_counter = process_counter + 1; - this.id = process_counter; + for (var i = 0; i < tuple.count(); i++) { + if (i !== index) { + new_list.push(tuple.get(i)); + } } - toString() { - return "PID#<0." + this.id + ".0>"; + return Kernel.SpecialForms.tuple.apply(null, new_list); +}; + +function duplicate(data, size) { + let array = []; + + for (var i = size - 1; i >= 0; i--) { + array.push(data); } -} + + return Kernel.SpecialForms.tuple.apply(null, array); +}; + +function insert_at(tuple, index, term) { + let new_tuple = []; + + for (var i = 0; i <= tuple.count(); i++) { + if (i === index) { + new_tuple.push(term); + i++; + new_tuple.push(tuple.get(i)); + } else { + new_tuple.push(tuple.get(i)); + } + } + + return Kernel.SpecialForms.tuple.apply(null, new_tuple); +}; + +function from_list(list) { + return Kernel.SpecialForms.tuple.apply(null, list); +}; + +function to_list(tuple) { + let new_list = []; + + for (var i = 0; i < tuple.count(); i++) { + new_list.push(tuple.get(i)); + } + + return Kernel.SpecialForms.list(...new_list); +}; + +var Tuple = { + to_string: to_string$1, + delete_at, + duplicate, + insert_at, + from_list, + to_list +}; class IntegerType {} class FloatType {} @@ -1159,15 +1548,15 @@ function is_number(x) { } function is_tuple(x) { - return x instanceof Tuple; + return x instanceof Core.Tuple; } -function _length(x) { +function length(x) { return x.length; } function is_pid(x) { - return x instanceof PID; + return x instanceof Core.PID; } function is_port(x) { @@ -1222,317 +1611,95 @@ function and(left, right) { function or(left, right) { return left || right; -} - -function not(arg) { - return !arg; -} - -function apply(...args) { - if (args.length === 3) { - let mod = args[0]; - let func = args[1]; - let func_args = args[2]; - return mod[func].apply(null, func_args); - } else { - let func = args[0]; - let func_args = args[1]; - - return func.apply(null, func_args); - } -} - -function to_string(arg) { - if (is_tuple(arg)) { - return Tuple.to_string(arg); - } - - return arg.toString(); -} - -function match__qmark__(pattern, expr, guard = () => true) { - return _Patterns.match_no_throw(pattern, expr, guard) != null; -} - -function defstruct(defaults) { - return class { - constructor(update = {}) { - let the_values = Object.assign(defaults, update); - Object.assign(this, the_values); - } - - static create(updates = {}) { - let x = new this(updates); - return Object.freeze(x); - } - }; -} - -function defexception(defaults) { - return class extends Error { - constructor(update = {}) { - let message = update.message || ''; - super(message); - - let the_values = Object.assign(defaults, update); - Object.assign(this, the_values); - - this.name = this.constructor.name; - this.message = message; - this[SpecialForms.atom('__exception__')] = true; - Error.captureStackTrace(this, this.constructor.name); - } - - static create(updates = {}) { - let x = new this(updates); - return Object.freeze(x); - } - }; -} - -function defprotocol(spec) { - return new Protocol(spec); -} - -function defimpl(protocol, type, impl) { - protocol.implementation(type, impl); -} - -var Kernel = { - SpecialForms, - tl, - hd, - is_nil, - is_atom, - is_binary, - is_boolean, - is_function, - is_float, - is_integer, - is_list, - is_map, - is_number, - is_tuple, - length: _length, - is_pid, - is_port, - is_reference, - is_bitstring, - in: __in__, - abs, - round, - elem, - rem, - div, - and, - or, - not, - apply, - to_string, - match__qmark__, - defstruct, - defprotocol, - defimpl -}; - -let Enum = { - - all__qmark__: function (collection, fun = x => x) { - for (let elem of collection) { - if (!fun(elem)) { - return false; - } - } - - return true; - }, - - any__qmark__: function (collection, fun = x => x) { - for (let elem of collection) { - if (fun(elem)) { - return true; - } - } - - return false; - }, - - at: function (collection, n, the_default = null) { - if (n > this.count(collection) || n < 0) { - return the_default; - } - - return collection[n]; - }, - - concat: function (...enumables) { - return enumables[0].concat(enumables[1]); - }, - - count: function (collection, fun = null) { - if (fun == null) { - return collection.length; - } else { - return collection.filter(fun).length; - } - }, - - drop: function (collection, count) { - return collection.slice(count); - }, - - drop_while: function (collection, fun) { - let count = 0; - - for (let elem of collection) { - if (fun(elem)) { - count = count + 1; - } else { - break; - } - } - - return collection.slice(count); - }, - - each: function (collection, fun) { - for (let elem of collection) { - fun(elem); - } - }, - - empty__qmark__: function (collection) { - return collection.length === 0; - }, - - fetch: function (collection, n) { - if (Kernel.is_list(collection)) { - if (n < this.count(collection) && n >= 0) { - return Kernel.SpecialForms.tuple(Kernel.SpecialForms.atom("ok"), collection[n]); - } else { - return Kernel.SpecialForms.atom("error"); - } - } - - throw new Error("collection is not an Enumerable"); - }, - - fetch__emark__: function (collection, n) { - if (Kernel.is_list(collection)) { - if (n < this.count(collection) && n >= 0) { - return collection[n]; - } else { - throw new Error("out of bounds error"); - } - } - - throw new Error("collection is not an Enumerable"); - }, - - filter: function (collection, fun) { - let result = []; - - for (let elem of collection) { - if (fun(elem)) { - result.push(elem); - } - } - - return result; - }, - - filter_map: function (collection, filter, mapper) { - return Enum.map(Enum.filter(collection, filter), mapper); - }, - - find: function (collection, if_none = null, fun) { - for (let elem of collection) { - if (fun(elem)) { - return elem; - } - } - - return if_none; - }, - - into: function (collection, list) { - return list.concat(collection); - }, - - map: function (collection, fun) { - let result = []; - - for (let elem of collection) { - result.push(fun(elem)); - } - - return result; - }, - - map_reduce: function (collection, acc, fun) { - let mapped = Kernel.SpecialForms.list(); - let the_acc = acc; - - for (var i = 0; i < this.count(collection); i++) { - let tuple = fun(collection[i], the_acc); - - the_acc = Kernel.elem(tuple, 1); - mapped = Kernel.SpecialForms.list(...mapped.concat([Kernel.elem(tuple, 0)])); - } - - return Kernel.SpecialForms.tuple(mapped, the_acc); - }, - - member: function (collection, value) { - return collection.includes(value); - }, - - reduce: function (collection, acc, fun) { - let the_acc = acc; - - for (var i = 0; i < this.count(collection); i++) { - let tuple = fun(collection[i], the_acc); +} - the_acc = Kernel.elem(tuple, 1); - } +function not(arg) { + return !arg; +} - return the_acc; - }, +function apply(...args) { + if (args.length === 3) { + let mod = args[0]; + let func = args[1]; + let func_args = args[2]; + return mod[func].apply(null, func_args); + } else { + let func = args[0]; + let func_args = args[1]; - take: function (collection, count) { - return collection.slice(0, count); - }, + return func.apply(null, func_args); + } +} - take_every: function (collection, nth) { - let result = []; - let index = 0; +function to_string(arg) { + if (is_tuple(arg)) { + return Tuple.to_string(arg); + } - for (let elem of collection) { - if (index % nth === 0) { - result.push(elem); - } - } + return arg.toString(); +} - return Kernel.SpecialForms.list(...result); - }, +function match__qmark__(pattern, expr, guard = () => true) { + return Patterns.match_no_throw(pattern, expr, guard) != null; +} - take_while: function (collection, fun) { - let count = 0; +function defstruct(defaults) { + return class { + constructor(update = {}) { + let the_values = Object.assign(defaults, update); + Object.assign(this, the_values); + } - for (let elem of collection) { - if (fun(elem)) { - count = count + 1; - } else { - break; - } + static create(updates = {}) { + let x = new this(updates); + return Object.freeze(x); } + }; +} - return collection.slice(0, count); - }, +function defprotocol(spec) { + return new Protocol(spec); +} - to_list: function (collection) { - return collection; - } +function defimpl(protocol, type, impl) { + protocol.implementation(type, impl); +} + +var Kernel = { + SpecialForms, + tl, + hd, + is_nil, + is_atom, + is_binary, + is_boolean, + is_function, + is_float, + is_integer, + is_list, + is_map, + is_number, + is_tuple, + length, + is_pid, + is_port, + is_reference, + is_bitstring, + in: __in__, + abs, + round, + elem, + rem, + div, + and, + or, + not, + apply, + to_string, + match__qmark__, + defstruct, + defprotocol, + defimpl }; let Atom = {}; @@ -1580,11 +1747,35 @@ let Integer = { } }; -let _Chars = Kernel.defprotocol({ +function call_property(item, property) { + if (property in item) { + item[property]; + if (item[property] instanceof Function) { + return item[property](); + } else { + return item[property]; + } + } else if (Symbol.for(property) in item) { + let prop = Symbol.for(property); + if (item[prop] instanceof Function) { + return item[prop](); + } else { + return item[prop]; + } + } + + throw new Error(`Property ${ property } not found in ${ item }`); +} + +var js = { + call_property +}; + +let Chars$1 = Kernel.defprotocol({ to_string: function (thing) {} }); -Kernel.defimpl(_Chars, BitString, { +Kernel.defimpl(Chars$1, BitString, { to_string: function (thing) { if (Kernel.is_binary(thing)) { return thing; @@ -1594,7 +1785,7 @@ Kernel.defimpl(_Chars, BitString, { } }); -Kernel.defimpl(_Chars, Symbol, { +Kernel.defimpl(Chars$1, Symbol, { to_string: function (thing) { if (nil) { return ""; @@ -1604,31 +1795,31 @@ Kernel.defimpl(_Chars, Symbol, { } }); -Kernel.defimpl(_Chars, IntegerType, { +Kernel.defimpl(Chars$1, IntegerType, { to_string: function (thing) { return Integer.to_string(thing); } }); -Kernel.defimpl(_Chars, FloatType, { +Kernel.defimpl(Chars$1, FloatType, { to_string: function (thing) { return thing.toString; } }); -Kernel.defimpl(_Chars, Array, { +Kernel.defimpl(Chars$1, Array, { to_string: function (thing) { return thing.toString(); } }); -Kernel.defimpl(_Chars, Tuple, { +Kernel.defimpl(Chars$1, Core.Tuple, { to_string: function (thing) { return Tuple.to_string(thing); } }); -Kernel.defimpl(_Chars, null, { +Kernel.defimpl(Chars$1, null, { to_string: function (thing) { return thing.toString(); } @@ -1700,7 +1891,7 @@ function contains__qm__(string, contains) { return string.indexOf(contains) > -1; } -function duplicate(subject, n) { +function duplicate$1(subject, n) { return subject.repeat(n); } @@ -1734,7 +1925,7 @@ function last(string) { return string[string.length - 1]; } -function length(string) { +function length$1(string) { return string.length; } @@ -1768,7 +1959,7 @@ function reverse(string) { return returnValue; } -function _split(string) { +function split(string) { return string.split(); } @@ -1790,23 +1981,23 @@ function valid_character__qm__(codepoint) { } } -var _String = { +var String$1 = { at, capitalize, codepoints, contains__qm__, downcase, - duplicate, + duplicate: duplicate$1, ends_with__qm__, first, graphemes, last, - length, + length: length$1, match__qm__, next_codepoint, next_grapheme, reverse, - split: _split, + split, starts_with__qm__, to_atom, to_char_list, @@ -1815,7 +2006,7 @@ var _String = { to_integer, upcase, valid_character__qm__, - Chars: _Chars + Chars: Chars$1 }; let Chars = Kernel.defprotocol({ @@ -1825,7 +2016,7 @@ let Chars = Kernel.defprotocol({ Kernel.defimpl(Chars, Kernel.is_bitstring, { to_char_list: function (thing) { if (Kernel.is_binary(thing)) { - return _String.to_char_list(thing); + return String$1.to_char_list(thing); } return thing.toString(); @@ -2123,170 +2314,6 @@ List.concat = function (left, right) { return left.concat(right); }; -class Signal { - - constructor() { - this.bindings = SpecialForms.list(); - } - - add(listener, context = this) { - this.bindings = List.append(this.bindings, new SignalBinding(this, listener, context)); - } - - remove(listener) { - this.bindings = Enum.filter(this.bindings, function (binding) { - return binding.listener !== listener; - }); - } - - dispatch(...params) { - for (let binding of this.bindings) { - binding.execute(...params); - } - } - - dispose() { - for (let binding of this.bindings) { - binding.dispose(); - } - - this.bindings = null; - } -} - -class SignalBinding { - - constructor(signal, listener, context) { - this.listener = listener; - this.signal = signal; - this.context = context; - } - - execute(...params) { - this.listener.apply(this.context, params); - } - - dispose() { - this.listener = null; - this.signal = null; - this.context = null; - } -} - -function __update(map, key, value) { - let m = new Map(map); - m.set(key, value); - return m; -} - -function remove(map, key) { - let m = new Map(map); - m.delete(key); - return m; -} - -class MailBox { - - constructor(context = this) { - this.signal = new Signal(); - this.signal.add((...params) => this.messages = this.messages.concat(params), context); - this.messages = []; - } - - receive(...messages) { - this.signal.dispatch(...messages); - } - - peek() { - if (this.messages.length === 0) { - return null; - } - - return this.messages[0]; - } - - read() { - let result = this.messages[0]; - this.messages = this.messages.slice(1); - - return result; - } - - add_subscriber(fn, context = this) { - this.signal.add(fn, context); - } - - remove_subscriber(fn) { - this.signal.remove(fn); - } - - dispose() { - this.signal.dispose(); - this.messages = null; - } -} - -class PostOffice { - - constructor() { - this.mailboxes = new Map(); - } - - send(address, message) { - this.mailboxes.get(address).receive(message); - } - - receive(address) { - return this.mailboxes.get(address).read(); - } - - peek(address) { - return this.mailboxes.get(address).peek(); - } - - add_mailbox(address = Symbol(), context = this) { - this.mailboxes = __update(this.mailboxes, address, new MailBox()); - return address; - } - - remove_mailbox(address) { - this.mailboxes.get(address).dispose(); - this.mailboxes = remove(this.mailboxes, address); - } - - subscribe(address, subscribtion_fn, context = this) { - this.mailboxes.get(address).add_subscriber(subscribtion_fn, context); - } - - unsubscribe(address, subscribtion_fn) { - this.mailboxes.get(address).remove_subscriber(subscribtion_fn); - } -} - -function call_property(item, property) { - if (property in item) { - item[property]; - if (item[property] instanceof Function) { - return item[property](); - } else { - return item[property]; - } - } else if (Symbol.for(property) in item) { - let prop = Symbol.for(property); - if (item[prop] instanceof Function) { - return item[prop](); - } else { - return item[prop]; - } - } - - throw new Error(`Property ${ property } not found in ${ item }`); -} - -var JS = { - call_property -}; - let Range = function (_first, _last) { if (!(this instanceof Range)) { return new Range(_first, _last); @@ -2356,35 +2383,37 @@ Keyword.get = function (keywords, key, the_default = null) { let Agent = {}; Agent.start = function (fun, options = []) { - const name = Keyword.has_key__qm__(options, Kernel.SpecialForms.atom('name')) ? Keyword.get(options, Kernel.SpecialForms.atom('name')) : Symbol(); + let pid = self.processes.spawn(); - self.post_office.add_mailbox(name); - self.post_office.send(name, fun()); + if (Keyword.has_key__qm__(options, Kernel.SpecialForms.atom('name'))) { + pid = self.processes.register(Keyword.get(options, Kernel.SpecialForms.atom('name')), pid); + } - return Kernel.SpecialForms.tuple(Kernel.SpecialForms.atom('ok'), name); + self.processes.put(pid, 'state', fun()); + return Kernel.SpecialForms.tuple(Kernel.SpecialForms.atom('ok'), pid); }; Agent.stop = function (agent, timeout = 5000) { - self.post_office.remove_mailbox(agent); + self.processes.exit(agent); return Kernel.SpecialForms.atom('ok'); }; Agent.update = function (agent, fun, timeout = 5000) { - const current_state = self.post_office.receive(agent); - self.post_office.send(agent, fun(current_state)); + const current_state = self.processes.get(agent, 'state'); + self.processes.put(agent, 'state', fun(current_state)); return Kernel.SpecialForms.atom('ok'); }; Agent.get = function (agent, fun, timeout = 5000) { - return fun(self.post_office.peek(agent)); + return fun(self.processes.get(agent, 'state')); }; Agent.get_and_update = function (agent, fun, timeout = 5000) { - const get_and_update_tuple = fun(self.post_office.receive(agent)); - self.post_office.send(agent, Kernel.elem(get_and_update_tuple, 1)); + const get_and_update_tuple = fun(self.processes.get(agent, 'state')); + self.processes.put(agent, 'state', Kernel.elem(get_and_update_tuple, 1)); return Kernel.elem(get_and_update_tuple, 0); }; @@ -2413,7 +2442,7 @@ function decode64__em__(data) { return atob(data); } -var Base = { +var base = { encode64, decode64, decode64__em__ @@ -2443,7 +2472,7 @@ function bxor(left, right) { return left ^ right; } -var Bitwise = { +var bitwise = { bnot, band, bor, @@ -2466,7 +2495,7 @@ let Inspect = Kernel.defprotocol({ inspect: function (thing, opts) {} }); -function ___new__() { +function __new__() { return SpecialForms.map({}); } @@ -2474,11 +2503,11 @@ function keys(map) { return Object.keys(map); } -function __size(map) { +function size(map) { return keys(map).length; } -function __to_list(map) { +function to_list$1(map) { let map_keys = keys(map); let list = []; @@ -2507,7 +2536,7 @@ function from_struct(struct) { return SpecialForms.map(map); } -function ____delete__(map, key) { +function __delete__(map, key) { let new_map = Object.assign({}, map); delete new_map[key]; @@ -2515,17 +2544,7 @@ function ____delete__(map, key) { return SpecialForms.map(new_map); } -function drop(map, keys) { - let new_map = Object.assign({}, map); - - for (let key of keys) { - delete new_map[key]; - } - - return SpecialForms.map(new_map); -} - -function __equal__qmark__(map1, map2) { +function equal__qmark__(map1, map2) { return map1 === map2; } @@ -2549,11 +2568,7 @@ function has_key__qmark__(map, key) { return key in map; } -function merge(map1, map2) { - return SpecialForms.map_update(map1, map2); -} - -function split(map, keys) { +function split$1(map, keys) { let split1 = {}; let split2 = {}; @@ -2665,7 +2680,7 @@ function get(map, key, _default = null) { return map[key]; } -function __put(map, key, val) { +function put(map, key, val) { let new_map = Object({}, map); new_map[key] = val; @@ -2683,7 +2698,7 @@ function update__emark__(map, key, fun) { return SpecialForms.map(new_map); } -function _update(map, key, initial, fun) { +function update(map, key, initial, fun) { let new_map = Object({}, map); if (!key in map) { @@ -2695,20 +2710,20 @@ function _update(map, key, initial, fun) { return SpecialForms.map(new_map); } -var _Map = { - new: ___new__, +var map = { + new: __new__, keys, - size: __size, - to_list: __to_list, + size, + to_list: to_list$1, values, from_struct, - delete: ____delete__, + delete: __delete__, drop, - equal__qmark__: __equal__qmark__, + equal__qmark__, fetch__emark__, fetch, has_key__qmark__, - split, + split: split$1, take, put_new, put_new_lazy, @@ -2717,24 +2732,24 @@ var _Map = { pop, get_lazy, get, - put: __put, + put, update__emark__, - update: _update + update }; -function __new__() { +function __new__$1() { return SpecialForms.map({ [Symbol.for('__struct__')]: Symbol.for('MapSet'), set: SpecialForms.list() }); } -function _size(map) { +function size$2(map) { return map.set.length; } -function _to_list(map) { +function to_list$3(map) { return map.set; } -function ___delete__(set, term) { +function __delete__$2(set, term) { let new_list = List.delete(set.set, term); let new_map = Object.assign({}, set); @@ -2742,7 +2757,7 @@ function ___delete__(set, term) { return SpecialForms.map(new_map); } -function _put(set, term) { +function put$2(set, term) { if (set.set.indexOf(term) === -1) { let new_list = List.append(set.set, term); @@ -2754,11 +2769,11 @@ function _put(set, term) { return set; } -function _difference(set1, set2) { +function difference$1(set1, set2) { let new_map = Object.assign({}, set1); for (let val of set1.set) { - if (_member__qmark__(set2, val)) { + if (member__qmark__$1(set2, val)) { new_map.set = List.delete(new_map.set, val); } } @@ -2766,11 +2781,11 @@ function _difference(set1, set2) { return SpecialForms.map(new_map); } -function _intersection(set1, set2) { +function intersection$1(set1, set2) { let new_map = Object.assign({}, set1); for (let val of set1.set) { - if (!_member__qmark__(set2, val)) { + if (!member__qmark__$1(set2, val)) { new_map.set = List.delete(new_map.set, val); } } @@ -2778,19 +2793,19 @@ function _intersection(set1, set2) { return SpecialForms.map(new_map); } -function _union(set1, set2) { +function union$1(set1, set2) { let new_map = set1; for (let val of set2.set) { - new_map = _put(new_map, val); + new_map = put$2(new_map, val); } return SpecialForms.map(new_map); } -function _disjoin__qmark__(set1, set2) { +function disjoin__qmark__$1(set1, set2) { for (let val of set1.set) { - if (_member__qmark__(set2, val)) { + if (member__qmark__$1(set2, val)) { return false; } } @@ -2798,17 +2813,17 @@ function _disjoin__qmark__(set1, set2) { return true; } -function _member__qmark__(set, value) { +function member__qmark__$1(set, value) { return set.set.indexOf(value) >= 0; } -function _equal__qmark__(set1, set2) { +function equal__qmark__$2(set1, set2) { return set1.set === set2.set; } -function _subset__qmark__(set1, set2) { +function subset__qmark__$1(set1, set2) { for (let val of set1.set) { - if (!_member__qmark__(set2, val)) { + if (!member__qmark__$1(set2, val)) { return false; } } @@ -2817,33 +2832,33 @@ function _subset__qmark__(set1, set2) { } var MapSet = { - new: __new__, - size: _size, - to_list: _to_list, - disjoin__qmark__: _disjoin__qmark__, - delete: ___delete__, - subset__qmark__: _subset__qmark__, - equal__qmark__: _equal__qmark__, - member__qmark__: _member__qmark__, - put: _put, - union: _union, - intersection: _intersection, - difference: _difference + new: __new__$1, + size: size$2, + to_list: to_list$3, + disjoin__qmark__: disjoin__qmark__$1, + delete: __delete__$2, + subset__qmark__: subset__qmark__$1, + equal__qmark__: equal__qmark__$2, + member__qmark__: member__qmark__$1, + put: put$2, + union: union$1, + intersection: intersection$1, + difference: difference$1 }; -function size(map) { +function size$1(map) { return MapSet.size(map); } -function to_list(map) { +function to_list$2(map) { return MapSet.to_list(map); } -function __delete__(set, term) { +function __delete__$1(set, term) { return MapSet.delete(set, term); } -function put(set, term) { +function put$1(set, term) { return MapSet.put(set, term); } @@ -2867,7 +2882,7 @@ function member__qmark__(set, value) { return MapSet.member__qmark__(set1, set2); } -function equal__qmark__(set1, set2) { +function equal__qmark__$1(set1, set2) { return MapSet.equal__qmark__(set1, set2); } @@ -2875,21 +2890,21 @@ function subset__qmark__(set1, set2) { return MapSet.subset__qmark__(set1, set2); } -var _Set = { - size, - to_list, +var set = { + size: size$1, + to_list: to_list$2, disjoin__qmark__, - delete: __delete__, + delete: __delete__$1, subset__qmark__, - equal__qmark__, + equal__qmark__: equal__qmark__$1, member__qmark__, - put, + put: put$1, union, intersection, difference }; -let virtualDom = (function (e) { +let VirtualDOM = (function (e) { return e(); })(function () { var define, module, exports; @@ -4496,31 +4511,30 @@ let virtualDom = (function (e) { }, { "../vnode/handle-thunk": 24, "../vnode/is-thunk": 25, "../vnode/is-vnode": 27, "../vnode/is-vtext": 28, "../vnode/is-widget": 29, "../vnode/vpatch": 32, "./diff-props": 34, "x-is-array": 12 }] }, {}, [4])(4); }); - -// Proposed for ES6 - const start = function (domRoot, renderFn, initialState, options = []) { - const name = Keyword.has_key__qm__(options, Kernel.SpecialForms.atom('name')) ? Keyword.get(options, Kernel.SpecialForms.atom('name')) : Symbol(); + let pid = self.processes.spawn(); - self.post_office.add_mailbox(name); + if (Keyword.has_key__qm__(options, Kernel.SpecialForms.atom('name'))) { + pid = self.processes.register(Keyword.get(options, Kernel.SpecialForms.atom('name')), pid); + } const tree = renderFn.apply(this, initialState); - const rootNode = virtualDom.create(tree); + const rootNode = VirtualDOM.create(tree); domRoot.appendChild(rootNode); - self.post_office.send(name, Kernel.SpecialForms.tuple(rootNode, tree, renderFn)); - return Kernel.SpecialForms.tuple(Kernel.SpecialForms.atom('ok'), name); + self.processes.put(pid, 'state', Kernel.SpecialForms.tuple(rootNode, tree, renderFn)); + return Kernel.SpecialForms.tuple(Kernel.SpecialForms.atom('ok'), pid); }; const stop = function (agent, timeout = 5000) { - self.post_office.remove_mailbox(agent); + self.processes.exit(agent); return Kernel.SpecialForms.atom('ok'); }; const render = function (agent, state) { - const current_state = self.post_office.receive(agent); + const current_state = self.processes.get(agent, 'state'); let rootNode = Kernel.elem(current_state, 0); let tree = Kernel.elem(current_state, 1); @@ -4528,21 +4542,21 @@ const render = function (agent, state) { let newTree = renderFn.apply(this, state); - let patches = virtualDom.diff(tree, newTree); - rootNode = virtualDom.patch(rootNode, patches); + let patches = VirtualDOM.diff(tree, newTree); + rootNode = VirtualDOM.patch(rootNode, patches); - self.post_office.send(agent, Kernel.SpecialForms.tuple(rootNode, newTree, renderFn)); + self.processes.put(agent, 'state', Kernel.SpecialForms.tuple(rootNode, newTree, renderFn)); return Kernel.SpecialForms.atom('ok'); }; -var View = { +var view = { start, stop, render }; -self.post_office = self.post_office || new PostOffice(); +self.processes = self.processes || new ProcessSystem(); -export { _Patterns as Patterns, BitString, Kernel, Atom, Enum, Integer, JS, List, Range, Tuple, Agent, Keyword, Base, _String as String, Bitwise, Enumerable, Collectable, Inspect, _Map as Map, _Set as Set, MapSet, IntegerType, FloatType, virtualDom as VirtualDOM, View }; -//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiIiwic291cmNlcyI6WyJlbGl4aXIuanMiXSwic291cmNlc0NvbnRlbnQiOlsidmFyIFBhdHRlcm5zID0ge1xuICAgIGdldCBkZWZhdWx0ICgpIHsgcmV0dXJuIF9QYXR0ZXJuczsgfVxufTtcblxuLyogQGZsb3cgKi9cblxuY2xhc3MgVmFyaWFibGUge1xuXG4gIGNvbnN0cnVjdG9yKG5hbWUgPSBudWxsKSB7XG4gICAgdGhpcy5uYW1lID0gbmFtZTtcbiAgfVxufVxuXG5jbGFzcyBXaWxkY2FyZCB7XG4gIGNvbnN0cnVjdG9yKCkge31cbn1cblxuY2xhc3MgU3RhcnRzV2l0aCB7XG5cbiAgY29uc3RydWN0b3IocHJlZml4KSB7XG4gICAgdGhpcy5wcmVmaXggPSBwcmVmaXg7XG4gIH1cbn1cblxuY2xhc3MgQ2FwdHVyZSB7XG5cbiAgY29uc3RydWN0b3IodmFsdWUpIHtcbiAgICB0aGlzLnZhbHVlID0gdmFsdWU7XG4gIH1cbn1cblxuY2xhc3MgSGVhZFRhaWwge1xuICBjb25zdHJ1Y3RvcigpIHt9XG59XG5cbmNsYXNzIFR5cGUge1xuXG4gIGNvbnN0cnVjdG9yKHR5cGUsIG9ialBhdHRlcm4gPSB7fSkge1xuICAgIHRoaXMudHlwZSA9IHR5cGU7XG4gICAgdGhpcy5vYmpQYXR0ZXJuID0gb2JqUGF0dGVybjtcbiAgfVxufVxuXG5jbGFzcyBCb3VuZCB7XG5cbiAgY29uc3RydWN0b3IodmFsdWUpIHtcbiAgICB0aGlzLnZhbHVlID0gdmFsdWU7XG4gIH1cbn1cblxuZnVuY3Rpb24gdmFyaWFibGUobmFtZSA9IG51bGwpIHtcbiAgcmV0dXJuIG5ldyBWYXJpYWJsZShuYW1lKTtcbn1cblxuZnVuY3Rpb24gd2lsZGNhcmQoKSB7XG4gIHJldHVybiBuZXcgV2lsZGNhcmQoKTtcbn1cblxuZnVuY3Rpb24gc3RhcnRzV2l0aChwcmVmaXgpIHtcbiAgcmV0dXJuIG5ldyBTdGFydHNXaXRoKHByZWZpeCk7XG59XG5cbmZ1bmN0aW9uIGNhcHR1cmUodmFsdWUpIHtcbiAgcmV0dXJuIG5ldyBDYXB0dXJlKHZhbHVlKTtcbn1cblxuZnVuY3Rpb24gaGVhZFRhaWwoKSB7XG4gIHJldHVybiBuZXcgSGVhZFRhaWwoKTtcbn1cblxuZnVuY3Rpb24gdHlwZSh0eXBlLCBvYmpQYXR0ZXJuID0ge30pIHtcbiAgcmV0dXJuIG5ldyBUeXBlKHR5cGUsIG9ialBhdHRlcm4pO1xufVxuXG5mdW5jdGlvbiBib3VuZCh2YWx1ZSkge1xuICByZXR1cm4gbmV3IEJvdW5kKHZhbHVlKTtcbn1cblxuZnVuY3Rpb24gX2lzX251bWJlcih2YWx1ZSkge1xuICByZXR1cm4gdHlwZW9mIHZhbHVlID09PSAnbnVtYmVyJztcbn1cblxuZnVuY3Rpb24gaXNfc3RyaW5nKHZhbHVlKSB7XG4gIHJldHVybiB0eXBlb2YgdmFsdWUgPT09ICdzdHJpbmcnO1xufVxuXG5mdW5jdGlvbiBfaXNfYm9vbGVhbih2YWx1ZSkge1xuICByZXR1cm4gdHlwZW9mIHZhbHVlID09PSAnYm9vbGVhbic7XG59XG5cbmZ1bmN0aW9uIGlzX3N5bWJvbCh2YWx1ZSkge1xuICByZXR1cm4gdHlwZW9mIHZhbHVlID09PSAnc3ltYm9sJztcbn1cblxuZnVuY3Rpb24gaXNfbnVsbCh2YWx1ZSkge1xuICByZXR1cm4gdmFsdWUgPT09IG51bGw7XG59XG5cbmZ1bmN0aW9uIGlzX3VuZGVmaW5lZCh2YWx1ZSkge1xuICByZXR1cm4gdHlwZW9mIHZhbHVlID09PSAndW5kZWZpbmVkJztcbn1cblxuZnVuY3Rpb24gX2lzX2Z1bmN0aW9uKHZhbHVlKSB7XG4gIHJldHVybiBPYmplY3QucHJvdG90eXBlLnRvU3RyaW5nLmNhbGwodmFsdWUpID09ICdbb2JqZWN0IEZ1bmN0aW9uXSc7XG59XG5cbmZ1bmN0aW9uIGlzX3ZhcmlhYmxlKHZhbHVlKSB7XG4gIHJldHVybiB2YWx1ZSBpbnN0YW5jZW9mIFZhcmlhYmxlO1xufVxuXG5mdW5jdGlvbiBpc193aWxkY2FyZCh2YWx1ZSkge1xuICByZXR1cm4gdmFsdWUgaW5zdGFuY2VvZiBXaWxkY2FyZDtcbn1cblxuZnVuY3Rpb24gaXNfaGVhZFRhaWwodmFsdWUpIHtcbiAgcmV0dXJuIHZhbHVlIGluc3RhbmNlb2YgSGVhZFRhaWw7XG59XG5cbmZ1bmN0aW9uIGlzX2NhcHR1cmUodmFsdWUpIHtcbiAgcmV0dXJuIHZhbHVlIGluc3RhbmNlb2YgQ2FwdHVyZTtcbn1cblxuZnVuY3Rpb24gaXNfdHlwZSh2YWx1ZSkge1xuICByZXR1cm4gdmFsdWUgaW5zdGFuY2VvZiBUeXBlO1xufVxuXG5mdW5jdGlvbiBpc19zdGFydHNXaXRoKHZhbHVlKSB7XG4gIHJldHVybiB2YWx1ZSBpbnN0YW5jZW9mIFN0YXJ0c1dpdGg7XG59XG5cbmZ1bmN0aW9uIGlzX2JvdW5kKHZhbHVlKSB7XG4gIHJldHVybiB2YWx1ZSBpbnN0YW5jZW9mIEJvdW5kO1xufVxuXG5mdW5jdGlvbiBpc19vYmplY3QodmFsdWUpIHtcbiAgcmV0dXJuIHR5cGVvZiB2YWx1ZSA9PT0gJ29iamVjdCc7XG59XG5cbmZ1bmN0aW9uIGlzX2FycmF5KHZhbHVlKSB7XG4gIHJldHVybiBBcnJheS5pc0FycmF5KHZhbHVlKTtcbn1cblxudmFyIENoZWNrcyA9IHtcbiAgaXNfbnVtYmVyOiBfaXNfbnVtYmVyLFxuICBpc19zdHJpbmcsXG4gIGlzX2Jvb2xlYW46IF9pc19ib29sZWFuLFxuICBpc19zeW1ib2wsXG4gIGlzX251bGwsXG4gIGlzX3VuZGVmaW5lZCxcbiAgaXNfZnVuY3Rpb246IF9pc19mdW5jdGlvbixcbiAgaXNfdmFyaWFibGUsXG4gIGlzX3dpbGRjYXJkLFxuICBpc19oZWFkVGFpbCxcbiAgaXNfY2FwdHVyZSxcbiAgaXNfdHlwZSxcbiAgaXNfc3RhcnRzV2l0aCxcbiAgaXNfYm91bmQsXG4gIGlzX29iamVjdCxcbiAgaXNfYXJyYXlcbn07XG5cbmZ1bmN0aW9uIHJlc29sdmVTeW1ib2wocGF0dGVybikge1xuICByZXR1cm4gZnVuY3Rpb24gKHZhbHVlKSB7XG4gICAgcmV0dXJuIENoZWNrcy5pc19zeW1ib2wodmFsdWUpICYmIHZhbHVlID09PSBwYXR0ZXJuO1xuICB9O1xufVxuXG5mdW5jdGlvbiByZXNvbHZlU3RyaW5nKHBhdHRlcm4pIHtcbiAgcmV0dXJuIGZ1bmN0aW9uICh2YWx1ZSkge1xuICAgIHJldHVybiBDaGVja3MuaXNfc3RyaW5nKHZhbHVlKSAmJiB2YWx1ZSA9PT0gcGF0dGVybjtcbiAgfTtcbn1cblxuZnVuY3Rpb24gcmVzb2x2ZU51bWJlcihwYXR0ZXJuKSB7XG4gIHJldHVybiBmdW5jdGlvbiAodmFsdWUpIHtcbiAgICByZXR1cm4gQ2hlY2tzLmlzX251bWJlcih2YWx1ZSkgJiYgdmFsdWUgPT09IHBhdHRlcm47XG4gIH07XG59XG5cbmZ1bmN0aW9uIHJlc29sdmVCb29sZWFuKHBhdHRlcm4pIHtcbiAgcmV0dXJuIGZ1bmN0aW9uICh2YWx1ZSkge1xuICAgIHJldHVybiBDaGVja3MuaXNfYm9vbGVhbih2YWx1ZSkgJiYgdmFsdWUgPT09IHBhdHRlcm47XG4gIH07XG59XG5cbmZ1bmN0aW9uIHJlc29sdmVGdW5jdGlvbihwYXR0ZXJuKSB7XG4gIHJldHVybiBmdW5jdGlvbiAodmFsdWUpIHtcbiAgICByZXR1cm4gQ2hlY2tzLmlzX2Z1bmN0aW9uKHZhbHVlKSAmJiB2YWx1ZSA9PT0gcGF0dGVybjtcbiAgfTtcbn1cblxuZnVuY3Rpb24gcmVzb2x2ZU51bGwocGF0dGVybikge1xuICByZXR1cm4gZnVuY3Rpb24gKHZhbHVlKSB7XG4gICAgcmV0dXJuIENoZWNrcy5pc19udWxsKHZhbHVlKTtcbiAgfTtcbn1cblxuZnVuY3Rpb24gcmVzb2x2ZUJvdW5kKHBhdHRlcm4pIHtcbiAgcmV0dXJuIGZ1bmN0aW9uICh2YWx1ZSwgYXJncykge1xuICAgIGlmICh0eXBlb2YgdmFsdWUgPT09IHR5cGVvZiBwYXR0ZXJuLnZhbHVlICYmIHZhbHVlID09PSBwYXR0ZXJuLnZhbHVlKSB7XG4gICAgICBhcmdzLnB1c2godmFsdWUpO1xuICAgICAgcmV0dXJuIHRydWU7XG4gICAgfVxuXG4gICAgcmV0dXJuIGZhbHNlO1xuICB9O1xufVxuXG5mdW5jdGlvbiByZXNvbHZlV2lsZGNhcmQoKSB7XG4gIHJldHVybiBmdW5jdGlvbiAoKSB7XG4gICAgcmV0dXJuIHRydWU7XG4gIH07XG59XG5cbmZ1bmN0aW9uIHJlc29sdmVWYXJpYWJsZSgpIHtcbiAgcmV0dXJuIGZ1bmN0aW9uICh2YWx1ZSwgYXJncykge1xuICAgIGFyZ3MucHVzaCh2YWx1ZSk7XG4gICAgcmV0dXJuIHRydWU7XG4gIH07XG59XG5cbmZ1bmN0aW9uIHJlc29sdmVIZWFkVGFpbCgpIHtcbiAgcmV0dXJuIGZ1bmN0aW9uICh2YWx1ZSwgYXJncykge1xuICAgIGlmICghQ2hlY2tzLmlzX2FycmF5KHZhbHVlKSB8fCB2YWx1ZS5sZW5ndGggPCAyKSB7XG4gICAgICByZXR1cm4gZmFsc2U7XG4gICAgfVxuXG4gICAgY29uc3QgaGVhZCA9IHZhbHVlWzBdO1xuICAgIGNvbnN0IHRhaWwgPSB2YWx1ZS5zbGljZSgxKTtcblxuICAgIGFyZ3MucHVzaChoZWFkKTtcbiAgICBhcmdzLnB1c2godGFpbCk7XG5cbiAgICByZXR1cm4gdHJ1ZTtcbiAgfTtcbn1cblxuZnVuY3Rpb24gcmVzb2x2ZUNhcHR1cmUocGF0dGVybikge1xuICBjb25zdCBtYXRjaGVzID0gYnVpbGRNYXRjaChwYXR0ZXJuLnZhbHVlKTtcblxuICByZXR1cm4gZnVuY3Rpb24gKHZhbHVlLCBhcmdzKSB7XG4gICAgaWYgKG1hdGNoZXModmFsdWUsIGFyZ3MpKSB7XG4gICAgICBhcmdzLnB1c2godmFsdWUpO1xuICAgICAgcmV0dXJuIHRydWU7XG4gICAgfVxuXG4gICAgcmV0dXJuIGZhbHNlO1xuICB9O1xufVxuXG5mdW5jdGlvbiByZXNvbHZlU3RhcnRzV2l0aChwYXR0ZXJuKSB7XG4gIGNvbnN0IHByZWZpeCA9IHBhdHRlcm4ucHJlZml4O1xuXG4gIHJldHVybiBmdW5jdGlvbiAodmFsdWUsIGFyZ3MpIHtcbiAgICBpZiAoQ2hlY2tzLmlzX3N0cmluZyh2YWx1ZSkgJiYgdmFsdWUuc3RhcnRzV2l0aChwcmVmaXgpKSB7XG4gICAgICBhcmdzLnB1c2godmFsdWUuc3Vic3RyaW5nKHByZWZpeC5sZW5ndGgpKTtcbiAgICAgIHJldHVybiB0cnVlO1xuICAgIH1cblxuICAgIHJldHVybiBmYWxzZTtcbiAgfTtcbn1cblxuZnVuY3Rpb24gcmVzb2x2ZVR5cGUocGF0dGVybikge1xuICByZXR1cm4gZnVuY3Rpb24gKHZhbHVlLCBhcmdzKSB7XG4gICAgaWYgKHZhbHVlIGluc3RhbmNlb2YgcGF0dGVybi50eXBlKSB7XG4gICAgICBjb25zdCBtYXRjaGVzID0gYnVpbGRNYXRjaChwYXR0ZXJuLm9ialBhdHRlcm4pO1xuICAgICAgcmV0dXJuIG1hdGNoZXModmFsdWUsIGFyZ3MpICYmIGFyZ3MucHVzaCh2YWx1ZSkgPiAwO1xuICAgIH1cblxuICAgIHJldHVybiBmYWxzZTtcbiAgfTtcbn1cblxuZnVuY3Rpb24gcmVzb2x2ZUFycmF5KHBhdHRlcm4pIHtcbiAgY29uc3QgbWF0Y2hlcyA9IHBhdHRlcm4ubWFwKHggPT4gYnVpbGRNYXRjaCh4KSk7XG5cbiAgcmV0dXJuIGZ1bmN0aW9uICh2YWx1ZSwgYXJncykge1xuICAgIGlmICghQ2hlY2tzLmlzX2FycmF5KHZhbHVlKSB8fCB2YWx1ZS5sZW5ndGggIT0gcGF0dGVybi5sZW5ndGgpIHtcbiAgICAgIHJldHVybiBmYWxzZTtcbiAgICB9XG5cbiAgICByZXR1cm4gdmFsdWUuZXZlcnkoZnVuY3Rpb24gKHYsIGkpIHtcbiAgICAgIHJldHVybiBtYXRjaGVzW2ldKHZhbHVlW2ldLCBhcmdzKTtcbiAgICB9KTtcbiAgfTtcbn1cblxuZnVuY3Rpb24gcmVzb2x2ZU9iamVjdChwYXR0ZXJuKSB7XG4gIGxldCBtYXRjaGVzID0ge307XG5cbiAgZm9yIChsZXQga2V5IG9mIE9iamVjdC5rZXlzKHBhdHRlcm4pKSB7XG4gICAgbWF0Y2hlc1trZXldID0gYnVpbGRNYXRjaChwYXR0ZXJuW2tleV0pO1xuICB9XG5cbiAgcmV0dXJuIGZ1bmN0aW9uICh2YWx1ZSwgYXJncykge1xuICAgIGlmICghQ2hlY2tzLmlzX29iamVjdCh2YWx1ZSkgfHwgcGF0dGVybi5sZW5ndGggPiB2YWx1ZS5sZW5ndGgpIHtcbiAgICAgIHJldHVybiBmYWxzZTtcbiAgICB9XG5cbiAgICBmb3IgKGxldCBrZXkgb2YgT2JqZWN0LmtleXMocGF0dGVybikpIHtcbiAgICAgIGlmICghKGtleSBpbiB2YWx1ZSkgfHwgIW1hdGNoZXNba2V5XSh2YWx1ZVtrZXldLCBhcmdzKSkge1xuICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICB9XG4gICAgfVxuXG4gICAgcmV0dXJuIHRydWU7XG4gIH07XG59XG5cbmZ1bmN0aW9uIHJlc29sdmVOb01hdGNoKCkge1xuICByZXR1cm4gZnVuY3Rpb24gKCkge1xuICAgIHJldHVybiBmYWxzZTtcbiAgfTtcbn1cblxudmFyIFJlc29sdmVycyA9IHtcbiAgcmVzb2x2ZUJvdW5kLFxuICByZXNvbHZlV2lsZGNhcmQsXG4gIHJlc29sdmVWYXJpYWJsZSxcbiAgcmVzb2x2ZUhlYWRUYWlsLFxuICByZXNvbHZlQ2FwdHVyZSxcbiAgcmVzb2x2ZVN0YXJ0c1dpdGgsXG4gIHJlc29sdmVUeXBlLFxuICByZXNvbHZlQXJyYXksXG4gIHJlc29sdmVPYmplY3QsXG4gIHJlc29sdmVOb01hdGNoLFxuICByZXNvbHZlU3ltYm9sLFxuICByZXNvbHZlU3RyaW5nLFxuICByZXNvbHZlTnVtYmVyLFxuICByZXNvbHZlQm9vbGVhbixcbiAgcmVzb2x2ZUZ1bmN0aW9uLFxuICByZXNvbHZlTnVsbFxufTtcblxuZnVuY3Rpb24gYnVpbGRNYXRjaChwYXR0ZXJuKSB7XG5cbiAgaWYgKENoZWNrcy5pc192YXJpYWJsZShwYXR0ZXJuKSkge1xuICAgIHJldHVybiBSZXNvbHZlcnMucmVzb2x2ZVZhcmlhYmxlKHBhdHRlcm4pO1xuICB9XG5cbiAgaWYgKENoZWNrcy5pc193aWxkY2FyZChwYXR0ZXJuKSkge1xuICAgIHJldHVybiBSZXNvbHZlcnMucmVzb2x2ZVdpbGRjYXJkKHBhdHRlcm4pO1xuICB9XG5cbiAgaWYgKENoZWNrcy5pc191bmRlZmluZWQocGF0dGVybikpIHtcbiAgICByZXR1cm4gUmVzb2x2ZXJzLnJlc29sdmVXaWxkY2FyZChwYXR0ZXJuKTtcbiAgfVxuXG4gIGlmIChDaGVja3MuaXNfaGVhZFRhaWwocGF0dGVybikpIHtcbiAgICByZXR1cm4gUmVzb2x2ZXJzLnJlc29sdmVIZWFkVGFpbChwYXR0ZXJuKTtcbiAgfVxuXG4gIGlmIChDaGVja3MuaXNfc3RhcnRzV2l0aChwYXR0ZXJuKSkge1xuICAgIHJldHVybiBSZXNvbHZlcnMucmVzb2x2ZVN0YXJ0c1dpdGgocGF0dGVybik7XG4gIH1cblxuICBpZiAoQ2hlY2tzLmlzX2NhcHR1cmUocGF0dGVybikpIHtcbiAgICByZXR1cm4gUmVzb2x2ZXJzLnJlc29sdmVDYXB0dXJlKHBhdHRlcm4pO1xuICB9XG5cbiAgaWYgKENoZWNrcy5pc19ib3VuZChwYXR0ZXJuKSkge1xuICAgIHJldHVybiBSZXNvbHZlcnMucmVzb2x2ZUJvdW5kKHBhdHRlcm4pO1xuICB9XG5cbiAgaWYgKENoZWNrcy5pc190eXBlKHBhdHRlcm4pKSB7XG4gICAgcmV0dXJuIFJlc29sdmVycy5yZXNvbHZlVHlwZShwYXR0ZXJuKTtcbiAgfVxuXG4gIGlmIChDaGVja3MuaXNfYXJyYXkocGF0dGVybikpIHtcbiAgICByZXR1cm4gUmVzb2x2ZXJzLnJlc29sdmVBcnJheShwYXR0ZXJuKTtcbiAgfVxuXG4gIGlmIChDaGVja3MuaXNfbnVtYmVyKHBhdHRlcm4pKSB7XG4gICAgcmV0dXJuIFJlc29sdmVycy5yZXNvbHZlTnVtYmVyKHBhdHRlcm4pO1xuICB9XG5cbiAgaWYgKENoZWNrcy5pc19zdHJpbmcocGF0dGVybikpIHtcbiAgICByZXR1cm4gUmVzb2x2ZXJzLnJlc29sdmVTdHJpbmcocGF0dGVybik7XG4gIH1cblxuICBpZiAoQ2hlY2tzLmlzX2Jvb2xlYW4ocGF0dGVybikpIHtcbiAgICByZXR1cm4gUmVzb2x2ZXJzLnJlc29sdmVCb29sZWFuKHBhdHRlcm4pO1xuICB9XG5cbiAgaWYgKENoZWNrcy5pc19zeW1ib2wocGF0dGVybikpIHtcbiAgICByZXR1cm4gUmVzb2x2ZXJzLnJlc29sdmVTeW1ib2wocGF0dGVybik7XG4gIH1cblxuICBpZiAoQ2hlY2tzLmlzX251bGwocGF0dGVybikpIHtcbiAgICByZXR1cm4gUmVzb2x2ZXJzLnJlc29sdmVOdWxsKHBhdHRlcm4pO1xuICB9XG5cbiAgaWYgKENoZWNrcy5pc19vYmplY3QocGF0dGVybikpIHtcbiAgICByZXR1cm4gUmVzb2x2ZXJzLnJlc29sdmVPYmplY3QocGF0dGVybik7XG4gIH1cblxuICByZXR1cm4gUmVzb2x2ZXJzLnJlc29sdmVOb01hdGNoKCk7XG59XG5cbmNsYXNzIE1hdGNoRXJyb3IgZXh0ZW5kcyBFcnJvciB7XG4gIGNvbnN0cnVjdG9yKGFyZykge1xuICAgIHN1cGVyKCk7XG5cbiAgICBpZiAodHlwZW9mIGFyZyA9PT0gJ3N5bWJvbCcpIHtcbiAgICAgIHRoaXMubWVzc2FnZSA9ICdObyBtYXRjaCBmb3I6ICcgKyBhcmcudG9TdHJpbmcoKTtcbiAgICB9IGVsc2UgaWYgKEFycmF5LmlzQXJyYXkoYXJnKSkge1xuICAgICAgbGV0IG1hcHBlZFZhbHVlcyA9IGFyZy5tYXAoeCA9PiB4LnRvU3RyaW5nKCkpO1xuICAgICAgdGhpcy5tZXNzYWdlID0gJ05vIG1hdGNoIGZvcjogJyArIG1hcHBlZFZhbHVlcztcbiAgICB9IGVsc2Uge1xuICAgICAgdGhpcy5tZXNzYWdlID0gJ05vIG1hdGNoIGZvcjogJyArIGFyZztcbiAgICB9XG5cbiAgICB0aGlzLnN0YWNrID0gbmV3IEVycm9yKCkuc3RhY2s7XG4gICAgdGhpcy5uYW1lID0gdGhpcy5jb25zdHJ1Y3Rvci5uYW1lO1xuICB9XG59XG5cbmNsYXNzIENhc2Uge1xuXG4gIGNvbnN0cnVjdG9yKHBhdHRlcm4sIGZuLCBndWFyZCA9ICgpID0+IHRydWUpIHtcbiAgICB0aGlzLnBhdHRlcm4gPSBidWlsZE1hdGNoKHBhdHRlcm4pO1xuICAgIHRoaXMuZm4gPSBmbjtcbiAgICB0aGlzLmd1YXJkID0gZ3VhcmQ7XG4gIH1cbn1cblxuZnVuY3Rpb24gbWFrZV9jYXNlKHBhdHRlcm4sIGZuLCBndWFyZCA9ICgpID0+IHRydWUpIHtcbiAgcmV0dXJuIG5ldyBDYXNlKHBhdHRlcm4sIGZuLCBndWFyZCk7XG59XG5cbmZ1bmN0aW9uIGRlZm1hdGNoKC4uLmNhc2VzKSB7XG4gIHJldHVybiBmdW5jdGlvbiAoLi4uYXJncykge1xuICAgIGZvciAobGV0IHByb2Nlc3NlZENhc2Ugb2YgY2FzZXMpIHtcbiAgICAgIGxldCByZXN1bHQgPSBbXTtcbiAgICAgIGlmIChwcm9jZXNzZWRDYXNlLnBhdHRlcm4oYXJncywgcmVzdWx0KSAmJiBwcm9jZXNzZWRDYXNlLmd1YXJkLmFwcGx5KHRoaXMsIHJlc3VsdCkpIHtcbiAgICAgICAgcmV0dXJuIHByb2Nlc3NlZENhc2UuZm4uYXBwbHkodGhpcywgcmVzdWx0KTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICB0aHJvdyBuZXcgTWF0Y2hFcnJvcihhcmdzKTtcbiAgfTtcbn1cblxuZnVuY3Rpb24gbWF0Y2gocGF0dGVybiwgZXhwciwgZ3VhcmQgPSAoKSA9PiB0cnVlKSB7XG4gIGxldCByZXN1bHQgPSBbXTtcbiAgbGV0IHByb2Nlc3NlZFBhdHRlcm4gPSBidWlsZE1hdGNoKHBhdHRlcm4pO1xuICBpZiAocHJvY2Vzc2VkUGF0dGVybihleHByLCByZXN1bHQpICYmIGd1YXJkLmFwcGx5KHRoaXMsIHJlc3VsdCkpIHtcbiAgICByZXR1cm4gcmVzdWx0O1xuICB9IGVsc2Uge1xuICAgIHRocm93IG5ldyBNYXRjaEVycm9yKGV4cHIpO1xuICB9XG59XG5cbmZ1bmN0aW9uIG1hdGNoX25vX3Rocm93KHBhdHRlcm4sIGV4cHIsIGd1YXJkID0gKCkgPT4gdHJ1ZSkge1xuICB0cnkge1xuICAgIHJldHVybiBtYXRjaChwYXR0ZXJuLCBleHByLCBndWFyZCk7XG4gIH0gY2F0Y2ggKGUpIHtcbiAgICBpZiAoZSBpbnN0YW5jZW9mIE1hdGNoRXJyb3IpIHtcbiAgICAgIHJldHVybiBudWxsO1xuICAgIH1cblxuICAgIHRocm93IGU7XG4gIH1cbn1cblxuZnVuY3Rpb24gcGF0dGVybk1hcChjb2xsZWN0aW9uLCBwYXR0ZXJuLCBmdW4sIGd1YXJkID0gKCkgPT4gdHJ1ZSkge1xuICBsZXQgcmV0ID0gW107XG5cbiAgZm9yIChsZXQgZWxlbSBvZiBjb2xsZWN0aW9uKSB7XG4gICAgdHJ5IHtcbiAgICAgIGxldCByZXN1bHQgPSBmdW4uYXBwbHkodGhpcywgbWF0Y2gocGF0dGVybiwgZWxlbSwgZ3VhcmQpKTtcbiAgICAgIHJldCA9IHJldC5jb25jYXQocmVzdWx0KTtcbiAgICB9IGNhdGNoIChlKSB7XG4gICAgICBpZiAoIShlIGluc3RhbmNlb2YgTWF0Y2hFcnJvcikpIHtcbiAgICAgICAgdGhyb3cgZTtcbiAgICAgIH1cbiAgICB9XG4gIH1cblxuICByZXR1cm4gcmV0O1xufVxuXG52YXIgX1BhdHRlcm5zID0ge1xuICBkZWZtYXRjaCwgbWF0Y2gsIE1hdGNoRXJyb3IsIG1hdGNoX25vX3Rocm93LCBwYXR0ZXJuTWFwLFxuICB2YXJpYWJsZSwgd2lsZGNhcmQsIHN0YXJ0c1dpdGgsXG4gIGNhcHR1cmUsIGhlYWRUYWlsLCB0eXBlLCBib3VuZCwgQ2FzZSwgbWFrZV9jYXNlXG59O1xuXG5jbGFzcyBUdXBsZSB7XG5cbiAgY29uc3RydWN0b3IoLi4uYXJncykge1xuICAgIHRoaXMudmFsdWVzID0gT2JqZWN0LmZyZWV6ZShhcmdzKTtcbiAgfVxuXG4gIGdldChpbmRleCkge1xuICAgIHJldHVybiB0aGlzLnZhbHVlc1tpbmRleF07XG4gIH1cblxuICBjb3VudCgpIHtcbiAgICByZXR1cm4gdGhpcy52YWx1ZXMubGVuZ3RoO1xuICB9XG5cbiAgW1N5bWJvbC5pdGVyYXRvcl0oKSB7XG4gICAgcmV0dXJuIHRoaXMudmFsdWVzW1N5bWJvbC5pdGVyYXRvcl0oKTtcbiAgfVxuXG4gIHRvU3RyaW5nKCkge1xuICAgIHZhciBpLFxuICAgICAgICBzID0gXCJcIjtcbiAgICBmb3IgKGkgPSAwOyBpIDwgdGhpcy52YWx1ZXMubGVuZ3RoOyBpKyspIHtcbiAgICAgIGlmIChzICE9PSBcIlwiKSB7XG4gICAgICAgIHMgKz0gXCIsIFwiO1xuICAgICAgfVxuICAgICAgcyArPSB0aGlzLnZhbHVlc1tpXS50b1N0cmluZygpO1xuICAgIH1cblxuICAgIHJldHVybiBcIntcIiArIHMgKyBcIn1cIjtcbiAgfVxuXG4gIHN0YXRpYyB0b19zdHJpbmcodHVwbGUpIHtcbiAgICByZXR1cm4gdHVwbGUudG9TdHJpbmcoKTtcbiAgfVxuXG4gIHN0YXRpYyBkZWxldGVfYXQodHVwbGUsIGluZGV4KSB7XG4gICAgbGV0IG5ld19saXN0ID0gW107XG5cbiAgICBmb3IgKHZhciBpID0gMDsgaSA8IHR1cGxlLmNvdW50KCk7IGkrKykge1xuICAgICAgaWYgKGkgIT09IGluZGV4KSB7XG4gICAgICAgIG5ld19saXN0LnB1c2godHVwbGUuZ2V0KGkpKTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICByZXR1cm4gS2VybmVsLlNwZWNpYWxGb3Jtcy50dXBsZS5hcHBseShudWxsLCBuZXdfbGlzdCk7XG4gIH1cblxuICBzdGF0aWMgZHVwbGljYXRlKGRhdGEsIHNpemUpIHtcbiAgICBsZXQgYXJyYXkgPSBbXTtcblxuICAgIGZvciAodmFyIGkgPSBzaXplIC0gMTsgaSA+PSAwOyBpLS0pIHtcbiAgICAgIGFycmF5LnB1c2goZGF0YSk7XG4gICAgfVxuXG4gICAgcmV0dXJuIEtlcm5lbC5TcGVjaWFsRm9ybXMudHVwbGUuYXBwbHkobnVsbCwgYXJyYXkpO1xuICB9XG5cbiAgc3RhdGljIGluc2VydF9hdCh0dXBsZSwgaW5kZXgsIHRlcm0pIHtcbiAgICBsZXQgbmV3X3R1cGxlID0gW107XG5cbiAgICBmb3IgKHZhciBpID0gMDsgaSA8PSB0dXBsZS5jb3VudCgpOyBpKyspIHtcbiAgICAgIGlmIChpID09PSBpbmRleCkge1xuICAgICAgICBuZXdfdHVwbGUucHVzaCh0ZXJtKTtcbiAgICAgICAgaSsrO1xuICAgICAgICBuZXdfdHVwbGUucHVzaCh0dXBsZS5nZXQoaSkpO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgbmV3X3R1cGxlLnB1c2godHVwbGUuZ2V0KGkpKTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICByZXR1cm4gS2VybmVsLlNwZWNpYWxGb3Jtcy50dXBsZS5hcHBseShudWxsLCBuZXdfdHVwbGUpO1xuICB9XG5cbiAgc3RhdGljIGZyb21fbGlzdChsaXN0KSB7XG4gICAgcmV0dXJuIEtlcm5lbC5TcGVjaWFsRm9ybXMudHVwbGUuYXBwbHkobnVsbCwgbGlzdCk7XG4gIH1cblxuICBzdGF0aWMgdG9fbGlzdCh0dXBsZSkge1xuICAgIGxldCBuZXdfbGlzdCA9IFtdO1xuXG4gICAgZm9yICh2YXIgaSA9IDA7IGkgPCB0dXBsZS5jb3VudCgpOyBpKyspIHtcbiAgICAgIG5ld19saXN0LnB1c2godHVwbGUuZ2V0KGkpKTtcbiAgICB9XG5cbiAgICByZXR1cm4gS2VybmVsLlNwZWNpYWxGb3Jtcy5saXN0KC4uLm5ld19saXN0KTtcbiAgfVxufVxuXG5jbGFzcyBCaXRTdHJpbmcge1xuICBjb25zdHJ1Y3RvciguLi5hcmdzKSB7XG4gICAgdGhpcy5yYXdfdmFsdWUgPSBmdW5jdGlvbiAoKSB7XG4gICAgICByZXR1cm4gT2JqZWN0LmZyZWV6ZShhcmdzKTtcbiAgICB9O1xuXG4gICAgdGhpcy52YWx1ZSA9IE9iamVjdC5mcmVlemUodGhpcy5wcm9jZXNzKGFyZ3MpKTtcbiAgfVxuXG4gIGdldChpbmRleCkge1xuICAgIHJldHVybiB0aGlzLnZhbHVlW2luZGV4XTtcbiAgfVxuXG4gIGNvdW50KCkge1xuICAgIHJldHVybiB0aGlzLnZhbHVlLmxlbmd0aDtcbiAgfVxuXG4gIFtTeW1ib2wuaXRlcmF0b3JdKCkge1xuICAgIHJldHVybiB0aGlzLnZhbHVlW1N5bWJvbC5pdGVyYXRvcl0oKTtcbiAgfVxuXG4gIHRvU3RyaW5nKCkge1xuICAgIHZhciBpLFxuICAgICAgICBzID0gXCJcIjtcbiAgICBmb3IgKGkgPSAwOyBpIDwgdGhpcy5jb3VudCgpOyBpKyspIHtcbiAgICAgIGlmIChzICE9PSBcIlwiKSB7XG4gICAgICAgIHMgKz0gXCIsIFwiO1xuICAgICAgfVxuICAgICAgcyArPSB0aGlzW2ldLnRvU3RyaW5nKCk7XG4gICAgfVxuXG4gICAgcmV0dXJuIFwiPDxcIiArIHMgKyBcIj4+XCI7XG4gIH1cblxuICBwcm9jZXNzKCkge1xuICAgIGxldCBwcm9jZXNzZWRfdmFsdWVzID0gW107XG5cbiAgICB2YXIgaTtcbiAgICBmb3IgKGkgPSAwOyBpIDwgdGhpcy5yYXdfdmFsdWUoKS5sZW5ndGg7IGkrKykge1xuICAgICAgbGV0IHByb2Nlc3NlZF92YWx1ZSA9IHRoaXNbXCJwcm9jZXNzX1wiICsgdGhpcy5yYXdfdmFsdWUoKVtpXS50eXBlXSh0aGlzLnJhd192YWx1ZSgpW2ldKTtcblxuICAgICAgZm9yIChsZXQgYXR0ciBvZiB0aGlzLnJhd192YWx1ZSgpW2ldLmF0dHJpYnV0ZXMpIHtcbiAgICAgICAgcHJvY2Vzc2VkX3ZhbHVlID0gdGhpc1tcInByb2Nlc3NfXCIgKyBhdHRyXShwcm9jZXNzZWRfdmFsdWUpO1xuICAgICAgfVxuXG4gICAgICBwcm9jZXNzZWRfdmFsdWVzID0gcHJvY2Vzc2VkX3ZhbHVlcy5jb25jYXQocHJvY2Vzc2VkX3ZhbHVlKTtcbiAgICB9XG5cbiAgICByZXR1cm4gcHJvY2Vzc2VkX3ZhbHVlcztcbiAgfVxuXG4gIHByb2Nlc3NfaW50ZWdlcih2YWx1ZSkge1xuICAgIHJldHVybiB2YWx1ZS52YWx1ZTtcbiAgfVxuXG4gIHByb2Nlc3NfZmxvYXQodmFsdWUpIHtcbiAgICBpZiAodmFsdWUuc2l6ZSA9PT0gNjQpIHtcbiAgICAgIHJldHVybiBCaXRTdHJpbmcuZmxvYXQ2NFRvQnl0ZXModmFsdWUudmFsdWUpO1xuICAgIH0gZWxzZSBpZiAodmFsdWUuc2l6ZSA9PT0gMzIpIHtcbiAgICAgIHJldHVybiBCaXRTdHJpbmcuZmxvYXQzMlRvQnl0ZXModmFsdWUudmFsdWUpO1xuICAgIH1cblxuICAgIHRocm93IG5ldyBFcnJvcihcIkludmFsaWQgc2l6ZSBmb3IgZmxvYXRcIik7XG4gIH1cblxuICBwcm9jZXNzX2JpdHN0cmluZyh2YWx1ZSkge1xuICAgIHJldHVybiB2YWx1ZS52YWx1ZS52YWx1ZTtcbiAgfVxuXG4gIHByb2Nlc3NfYmluYXJ5KHZhbHVlKSB7XG4gICAgcmV0dXJuIEJpdFN0cmluZy50b1VURjhBcnJheSh2YWx1ZS52YWx1ZSk7XG4gIH1cblxuICBwcm9jZXNzX3V0ZjgodmFsdWUpIHtcbiAgICByZXR1cm4gQml0U3RyaW5nLnRvVVRGOEFycmF5KHZhbHVlLnZhbHVlKTtcbiAgfVxuXG4gIHByb2Nlc3NfdXRmMTYodmFsdWUpIHtcbiAgICByZXR1cm4gQml0U3RyaW5nLnRvVVRGMTZBcnJheSh2YWx1ZS52YWx1ZSk7XG4gIH1cblxuICBwcm9jZXNzX3V0ZjMyKHZhbHVlKSB7XG4gICAgcmV0dXJuIEJpdFN0cmluZy50b1VURjMyQXJyYXkodmFsdWUudmFsdWUpO1xuICB9XG5cbiAgcHJvY2Vzc19zaWduZWQodmFsdWUpIHtcbiAgICByZXR1cm4gbmV3IFVpbnQ4QXJyYXkoW3ZhbHVlXSlbMF07XG4gIH1cblxuICBwcm9jZXNzX3Vuc2lnbmVkKHZhbHVlKSB7XG4gICAgcmV0dXJuIHZhbHVlO1xuICB9XG5cbiAgcHJvY2Vzc19uYXRpdmUodmFsdWUpIHtcbiAgICByZXR1cm4gdmFsdWU7XG4gIH1cblxuICBwcm9jZXNzX2JpZyh2YWx1ZSkge1xuICAgIHJldHVybiB2YWx1ZTtcbiAgfVxuXG4gIHByb2Nlc3NfbGl0dGxlKHZhbHVlKSB7XG4gICAgcmV0dXJuIHZhbHVlLnJldmVyc2UoKTtcbiAgfVxuXG4gIHByb2Nlc3Nfc2l6ZSh2YWx1ZSkge1xuICAgIHJldHVybiB2YWx1ZTtcbiAgfVxuXG4gIHByb2Nlc3NfdW5pdCh2YWx1ZSkge1xuICAgIHJldHVybiB2YWx1ZTtcbiAgfVxuXG4gIHN0YXRpYyBpbnRlZ2VyKHZhbHVlKSB7XG4gICAgcmV0dXJuIEJpdFN0cmluZy53cmFwKHZhbHVlLCB7IFwidHlwZVwiOiBcImludGVnZXJcIiwgXCJ1bml0XCI6IDEsIFwic2l6ZVwiOiA4IH0pO1xuICB9XG5cbiAgc3RhdGljIGZsb2F0KHZhbHVlKSB7XG4gICAgcmV0dXJuIEJpdFN0cmluZy53cmFwKHZhbHVlLCB7IFwidHlwZVwiOiBcImZsb2F0XCIsIFwidW5pdFwiOiAxLCBcInNpemVcIjogNjQgfSk7XG4gIH1cblxuICBzdGF0aWMgYml0c3RyaW5nKHZhbHVlKSB7XG4gICAgcmV0dXJuIEJpdFN0cmluZy53cmFwKHZhbHVlLCB7IFwidHlwZVwiOiBcImJpdHN0cmluZ1wiLCBcInVuaXRcIjogMSwgXCJzaXplXCI6IHZhbHVlLmxlbmd0aCB9KTtcbiAgfVxuXG4gIHN0YXRpYyBiaXRzKHZhbHVlKSB7XG4gICAgcmV0dXJuIEJpdFN0cmluZy5iaXRzdHJpbmcodmFsdWUpO1xuICB9XG5cbiAgc3RhdGljIGJpbmFyeSh2YWx1ZSkge1xuICAgIHJldHVybiBCaXRTdHJpbmcud3JhcCh2YWx1ZSwgeyBcInR5cGVcIjogXCJiaW5hcnlcIiwgXCJ1bml0XCI6IDgsIFwic2l6ZVwiOiB2YWx1ZS5sZW5ndGggfSk7XG4gIH1cblxuICBzdGF0aWMgYnl0ZXModmFsdWUpIHtcbiAgICByZXR1cm4gQml0U3RyaW5nLmJpbmFyeSh2YWx1ZSk7XG4gIH1cblxuICBzdGF0aWMgdXRmOCh2YWx1ZSkge1xuICAgIHJldHVybiBCaXRTdHJpbmcud3JhcCh2YWx1ZSwgeyBcInR5cGVcIjogXCJ1dGY4XCIgfSk7XG4gIH1cblxuICBzdGF0aWMgdXRmMTYodmFsdWUpIHtcbiAgICByZXR1cm4gQml0U3RyaW5nLndyYXAodmFsdWUsIHsgXCJ0eXBlXCI6IFwidXRmMTZcIiB9KTtcbiAgfVxuXG4gIHN0YXRpYyB1dGYzMih2YWx1ZSkge1xuICAgIHJldHVybiBCaXRTdHJpbmcud3JhcCh2YWx1ZSwgeyBcInR5cGVcIjogXCJ1dGYzMlwiIH0pO1xuICB9XG5cbiAgc3RhdGljIHNpZ25lZCh2YWx1ZSkge1xuICAgIHJldHVybiBCaXRTdHJpbmcud3JhcCh2YWx1ZSwge30sIFwic2lnbmVkXCIpO1xuICB9XG5cbiAgc3RhdGljIHVuc2lnbmVkKHZhbHVlKSB7XG4gICAgcmV0dXJuIEJpdFN0cmluZy53cmFwKHZhbHVlLCB7fSwgXCJ1bnNpZ25lZFwiKTtcbiAgfVxuXG4gIHN0YXRpYyBuYXRpdmUodmFsdWUpIHtcbiAgICByZXR1cm4gQml0U3RyaW5nLndyYXAodmFsdWUsIHt9LCBcIm5hdGl2ZVwiKTtcbiAgfVxuXG4gIHN0YXRpYyBiaWcodmFsdWUpIHtcbiAgICByZXR1cm4gQml0U3RyaW5nLndyYXAodmFsdWUsIHt9LCBcImJpZ1wiKTtcbiAgfVxuXG4gIHN0YXRpYyBsaXR0bGUodmFsdWUpIHtcbiAgICByZXR1cm4gQml0U3RyaW5nLndyYXAodmFsdWUsIHt9LCBcImxpdHRsZVwiKTtcbiAgfVxuXG4gIHN0YXRpYyBzaXplKHZhbHVlLCBjb3VudCkge1xuICAgIHJldHVybiBCaXRTdHJpbmcud3JhcCh2YWx1ZSwgeyBcInNpemVcIjogY291bnQgfSk7XG4gIH1cblxuICBzdGF0aWMgdW5pdCh2YWx1ZSwgY291bnQpIHtcbiAgICByZXR1cm4gQml0U3RyaW5nLndyYXAodmFsdWUsIHsgXCJ1bml0XCI6IGNvdW50IH0pO1xuICB9XG5cbiAgc3RhdGljIHdyYXAodmFsdWUsIG9wdCwgbmV3X2F0dHJpYnV0ZSA9IG51bGwpIHtcbiAgICBsZXQgdGhlX3ZhbHVlID0gdmFsdWU7XG5cbiAgICBpZiAoISh2YWx1ZSBpbnN0YW5jZW9mIE9iamVjdCkpIHtcbiAgICAgIHRoZV92YWx1ZSA9IHsgXCJ2YWx1ZVwiOiB2YWx1ZSwgXCJhdHRyaWJ1dGVzXCI6IFtdIH07XG4gICAgfVxuXG4gICAgdGhlX3ZhbHVlID0gT2JqZWN0LmFzc2lnbih0aGVfdmFsdWUsIG9wdCk7XG5cbiAgICBpZiAobmV3X2F0dHJpYnV0ZSkge1xuICAgICAgdGhlX3ZhbHVlLmF0dHJpYnV0ZXMucHVzaChuZXdfYXR0cmlidXRlKTtcbiAgICB9XG5cbiAgICByZXR1cm4gdGhlX3ZhbHVlO1xuICB9XG5cbiAgc3RhdGljIHRvVVRGOEFycmF5KHN0cikge1xuICAgIHZhciB1dGY4ID0gW107XG4gICAgZm9yICh2YXIgaSA9IDA7IGkgPCBzdHIubGVuZ3RoOyBpKyspIHtcbiAgICAgIHZhciBjaGFyY29kZSA9IHN0ci5jaGFyQ29kZUF0KGkpO1xuICAgICAgaWYgKGNoYXJjb2RlIDwgMTI4KSB7XG4gICAgICAgIHV0ZjgucHVzaChjaGFyY29kZSk7XG4gICAgICB9IGVsc2UgaWYgKGNoYXJjb2RlIDwgMjA0OCkge1xuICAgICAgICB1dGY4LnB1c2goMTkyIHwgY2hhcmNvZGUgPj4gNiwgMTI4IHwgY2hhcmNvZGUgJiA2Myk7XG4gICAgICB9IGVsc2UgaWYgKGNoYXJjb2RlIDwgNTUyOTYgfHwgY2hhcmNvZGUgPj0gNTczNDQpIHtcbiAgICAgICAgdXRmOC5wdXNoKDIyNCB8IGNoYXJjb2RlID4+IDEyLCAxMjggfCBjaGFyY29kZSA+PiA2ICYgNjMsIDEyOCB8IGNoYXJjb2RlICYgNjMpO1xuICAgICAgfVxuICAgICAgLy8gc3Vycm9nYXRlIHBhaXJcbiAgICAgIGVsc2Uge1xuICAgICAgICBpKys7XG4gICAgICAgIC8vIFVURi0xNiBlbmNvZGVzIDB4MTAwMDAtMHgxMEZGRkYgYnlcbiAgICAgICAgLy8gc3VidHJhY3RpbmcgMHgxMDAwMCBhbmQgc3BsaXR0aW5nIHRoZVxuICAgICAgICAvLyAyMCBiaXRzIG9mIDB4MC0weEZGRkZGIGludG8gdHdvIGhhbHZlc1xuICAgICAgICBjaGFyY29kZSA9IDY1NTM2ICsgKChjaGFyY29kZSAmIDEwMjMpIDw8IDEwIHwgc3RyLmNoYXJDb2RlQXQoaSkgJiAxMDIzKTtcbiAgICAgICAgdXRmOC5wdXNoKDI0MCB8IGNoYXJjb2RlID4+IDE4LCAxMjggfCBjaGFyY29kZSA+PiAxMiAmIDYzLCAxMjggfCBjaGFyY29kZSA+PiA2ICYgNjMsIDEyOCB8IGNoYXJjb2RlICYgNjMpO1xuICAgICAgfVxuICAgIH1cbiAgICByZXR1cm4gdXRmODtcbiAgfVxuXG4gIHN0YXRpYyB0b1VURjE2QXJyYXkoc3RyKSB7XG4gICAgdmFyIHV0ZjE2ID0gW107XG4gICAgZm9yICh2YXIgaSA9IDA7IGkgPCBzdHIubGVuZ3RoOyBpKyspIHtcbiAgICAgIHZhciBjb2RlUG9pbnQgPSBzdHIuY29kZVBvaW50QXQoaSk7XG5cbiAgICAgIGlmIChjb2RlUG9pbnQgPD0gMjU1KSB7XG4gICAgICAgIHV0ZjE2LnB1c2goMCk7XG4gICAgICAgIHV0ZjE2LnB1c2goY29kZVBvaW50KTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHV0ZjE2LnB1c2goY29kZVBvaW50ID4+IDggJiAyNTUpO1xuICAgICAgICB1dGYxNi5wdXNoKGNvZGVQb2ludCAmIDI1NSk7XG4gICAgICB9XG4gICAgfVxuICAgIHJldHVybiB1dGYxNjtcbiAgfVxuXG4gIHN0YXRpYyB0b1VURjMyQXJyYXkoc3RyKSB7XG4gICAgdmFyIHV0ZjMyID0gW107XG4gICAgZm9yICh2YXIgaSA9IDA7IGkgPCBzdHIubGVuZ3RoOyBpKyspIHtcbiAgICAgIHZhciBjb2RlUG9pbnQgPSBzdHIuY29kZVBvaW50QXQoaSk7XG5cbiAgICAgIGlmIChjb2RlUG9pbnQgPD0gMjU1KSB7XG4gICAgICAgIHV0ZjMyLnB1c2goMCk7XG4gICAgICAgIHV0ZjMyLnB1c2goMCk7XG4gICAgICAgIHV0ZjMyLnB1c2goMCk7XG4gICAgICAgIHV0ZjMyLnB1c2goY29kZVBvaW50KTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHV0ZjMyLnB1c2goMCk7XG4gICAgICAgIHV0ZjMyLnB1c2goMCk7XG4gICAgICAgIHV0ZjMyLnB1c2goY29kZVBvaW50ID4+IDggJiAyNTUpO1xuICAgICAgICB1dGYzMi5wdXNoKGNvZGVQb2ludCAmIDI1NSk7XG4gICAgICB9XG4gICAgfVxuICAgIHJldHVybiB1dGYzMjtcbiAgfVxuXG4gIC8vaHR0cDovL3N0YWNrb3ZlcmZsb3cuY29tL3F1ZXN0aW9ucy8yMDAzNDkzL2phdmFzY3JpcHQtZmxvYXQtZnJvbS10by1iaXRzXG4gIHN0YXRpYyBmbG9hdDMyVG9CeXRlcyhmKSB7XG4gICAgdmFyIGJ5dGVzID0gW107XG5cbiAgICB2YXIgYnVmID0gbmV3IEFycmF5QnVmZmVyKDQpO1xuICAgIG5ldyBGbG9hdDMyQXJyYXkoYnVmKVswXSA9IGY7XG5cbiAgICBsZXQgaW50VmVyc2lvbiA9IG5ldyBVaW50MzJBcnJheShidWYpWzBdO1xuXG4gICAgYnl0ZXMucHVzaChpbnRWZXJzaW9uID4+IDI0ICYgMjU1KTtcbiAgICBieXRlcy5wdXNoKGludFZlcnNpb24gPj4gMTYgJiAyNTUpO1xuICAgIGJ5dGVzLnB1c2goaW50VmVyc2lvbiA+PiA4ICYgMjU1KTtcbiAgICBieXRlcy5wdXNoKGludFZlcnNpb24gJiAyNTUpO1xuXG4gICAgcmV0dXJuIGJ5dGVzO1xuICB9XG5cbiAgc3RhdGljIGZsb2F0NjRUb0J5dGVzKGYpIHtcbiAgICB2YXIgYnl0ZXMgPSBbXTtcblxuICAgIHZhciBidWYgPSBuZXcgQXJyYXlCdWZmZXIoOCk7XG4gICAgbmV3IEZsb2F0NjRBcnJheShidWYpWzBdID0gZjtcblxuICAgIHZhciBpbnRWZXJzaW9uMSA9IG5ldyBVaW50MzJBcnJheShidWYpWzBdO1xuICAgIHZhciBpbnRWZXJzaW9uMiA9IG5ldyBVaW50MzJBcnJheShidWYpWzFdO1xuXG4gICAgYnl0ZXMucHVzaChpbnRWZXJzaW9uMiA+PiAyNCAmIDI1NSk7XG4gICAgYnl0ZXMucHVzaChpbnRWZXJzaW9uMiA+PiAxNiAmIDI1NSk7XG4gICAgYnl0ZXMucHVzaChpbnRWZXJzaW9uMiA+PiA4ICYgMjU1KTtcbiAgICBieXRlcy5wdXNoKGludFZlcnNpb24yICYgMjU1KTtcblxuICAgIGJ5dGVzLnB1c2goaW50VmVyc2lvbjEgPj4gMjQgJiAyNTUpO1xuICAgIGJ5dGVzLnB1c2goaW50VmVyc2lvbjEgPj4gMTYgJiAyNTUpO1xuICAgIGJ5dGVzLnB1c2goaW50VmVyc2lvbjEgPj4gOCAmIDI1NSk7XG4gICAgYnl0ZXMucHVzaChpbnRWZXJzaW9uMSAmIDI1NSk7XG5cbiAgICByZXR1cm4gYnl0ZXM7XG4gIH1cbn1cblxubGV0IFNwZWNpYWxGb3JtcyA9IHtcblxuICBfX0RJUl9fOiBmdW5jdGlvbiAoKSB7XG4gICAgaWYgKF9fZGlybmFtZSkge1xuICAgICAgcmV0dXJuIF9fZGlybmFtZTtcbiAgICB9XG5cbiAgICBpZiAoZG9jdW1lbnQuY3VycmVudFNjcmlwdCkge1xuICAgICAgcmV0dXJuIGRvY3VtZW50LmN1cnJlbnRTY3JpcHQuc3JjO1xuICAgIH1cblxuICAgIHJldHVybiBudWxsO1xuICB9LFxuXG4gIGF0b206IGZ1bmN0aW9uIChfdmFsdWUpIHtcbiAgICByZXR1cm4gU3ltYm9sLmZvcihfdmFsdWUpO1xuICB9LFxuXG4gIGxpc3Q6IGZ1bmN0aW9uICguLi5hcmdzKSB7XG4gICAgcmV0dXJuIE9iamVjdC5mcmVlemUoYXJncyk7XG4gIH0sXG5cbiAgYml0c3RyaW5nOiBmdW5jdGlvbiAoLi4uYXJncykge1xuICAgIHJldHVybiBuZXcgQml0U3RyaW5nKC4uLmFyZ3MpO1xuICB9LFxuXG4gIGJvdW5kOiBmdW5jdGlvbiAoX3Zhcikge1xuICAgIHJldHVybiBQYXR0ZXJucy5ib3VuZChfdmFyKTtcbiAgfSxcblxuICBfY2FzZTogZnVuY3Rpb24gKGNvbmRpdGlvbiwgY2xhdXNlcykge1xuICAgIHJldHVybiBQYXR0ZXJucy5kZWZtYXRjaCguLi5jbGF1c2VzKShjb25kaXRpb24pO1xuICB9LFxuXG4gIGNvbmQ6IGZ1bmN0aW9uIChjbGF1c2VzKSB7XG4gICAgZm9yIChsZXQgY2xhdXNlIG9mIGNsYXVzZXMpIHtcbiAgICAgIGlmIChjbGF1c2VbMF0pIHtcbiAgICAgICAgcmV0dXJuIGNsYXVzZVsxXSgpO1xuICAgICAgfVxuICAgIH1cblxuICAgIHRocm93IG5ldyBFcnJvcigpO1xuICB9LFxuXG4gIGZuOiBmdW5jdGlvbiAoY2xhdXNlcykge1xuICAgIHJldHVybiBQYXR0ZXJucy5kZWZtYXRjaChjbGF1c2VzKTtcbiAgfSxcblxuICBtYXA6IGZ1bmN0aW9uIChvYmopIHtcbiAgICByZXR1cm4gT2JqZWN0LmZyZWV6ZShvYmopO1xuICB9LFxuXG4gIG1hcF91cGRhdGU6IGZ1bmN0aW9uIChtYXAsIHZhbHVlcykge1xuICAgIHJldHVybiBPYmplY3QuZnJlZXplKE9iamVjdC5hc3NpZ24oT2JqZWN0LmNyZWF0ZShtYXAuY29uc3RydWN0b3IucHJvdG90eXBlKSwgbWFwLCB2YWx1ZXMpKTtcbiAgfSxcblxuICBfZm9yOiBmdW5jdGlvbiAoY29sbGVjdGlvbnMsIGZ1biwgZmlsdGVyID0gKCkgPT4gdHJ1ZSwgaW50byA9IFtdLCBwcmV2aW91c1ZhbHVlcyA9IFtdKSB7XG4gICAgbGV0IHBhdHRlcm4gPSBjb2xsZWN0aW9uc1swXVswXTtcbiAgICBsZXQgY29sbGVjdGlvbiA9IGNvbGxlY3Rpb25zWzBdWzFdO1xuXG4gICAgaWYgKGNvbGxlY3Rpb25zLmxlbmd0aCA9PT0gMSkge1xuXG4gICAgICBmb3IgKGxldCBlbGVtIG9mIGNvbGxlY3Rpb24pIHtcbiAgICAgICAgbGV0IHIgPSBQYXR0ZXJucy5tYXRjaF9ub190aHJvdyhwYXR0ZXJuLCBlbGVtKTtcbiAgICAgICAgbGV0IGFyZ3MgPSBwcmV2aW91c1ZhbHVlcy5jb25jYXQocik7XG5cbiAgICAgICAgaWYgKHIgJiYgZmlsdGVyLmFwcGx5KHRoaXMsIGFyZ3MpKSB7XG4gICAgICAgICAgaW50byA9IEVudW0uaW50byhbZnVuLmFwcGx5KHRoaXMsIGFyZ3MpXSwgaW50byk7XG4gICAgICAgIH1cbiAgICAgIH1cblxuICAgICAgcmV0dXJuIGludG87XG4gICAgfSBlbHNlIHtcbiAgICAgIGxldCBfaW50byA9IFtdO1xuXG4gICAgICBmb3IgKGxldCBlbGVtIG9mIGNvbGxlY3Rpb24pIHtcbiAgICAgICAgbGV0IHIgPSBQYXR0ZXJucy5tYXRjaF9ub190aHJvdyhwYXR0ZXJuLCBlbGVtKTtcbiAgICAgICAgaWYgKHIpIHtcbiAgICAgICAgICBfaW50byA9IEVudW0uaW50byh0aGlzLl9mb3IoY29sbGVjdGlvbnMuc2xpY2UoMSksIGZ1biwgZmlsdGVyLCBfaW50bywgcHJldmlvdXNWYWx1ZXMuY29uY2F0KHIpKSwgaW50byk7XG4gICAgICAgIH1cbiAgICAgIH1cblxuICAgICAgcmV0dXJuIF9pbnRvO1xuICAgIH1cbiAgfSxcblxuICByZWNlaXZlOiBmdW5jdGlvbiAocmVjZWl2ZV9mdW4sIHRpbWVvdXRfaW5fbXMgPSBudWxsLCB0aW1lb3V0X2ZuID0gdGltZSA9PiB0cnVlKSB7XG4gICAgaWYgKHRpbWVvdXRfaW5fbXMgPT0gbnVsbCB8fCB0aW1lb3V0X2luX21zID09PSBTeXN0ZW0uZm9yKCdpbmZpbml0eScpKSB7XG4gICAgICB3aGlsZSAodHJ1ZSkge1xuICAgICAgICBpZiAoc2VsZi5tYWlsYm94Lmxlbmd0aCAhPT0gMCkge1xuICAgICAgICAgIGxldCBtZXNzYWdlID0gc2VsZi5tYWlsYm94WzBdO1xuICAgICAgICAgIHNlbGYubWFpbGJveCA9IHNlbGYubWFpbGJveC5zbGljZSgxKTtcbiAgICAgICAgICByZXR1cm4gcmVjZWl2ZV9mdW4obWVzc2FnZSk7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9IGVsc2UgaWYgKHRpbWVvdXRfaW5fbXMgPT09IDApIHtcbiAgICAgIGlmIChzZWxmLm1haWxib3gubGVuZ3RoICE9PSAwKSB7XG4gICAgICAgIGxldCBtZXNzYWdlID0gc2VsZi5tYWlsYm94WzBdO1xuICAgICAgICBzZWxmLm1haWxib3ggPSBzZWxmLm1haWxib3guc2xpY2UoMSk7XG4gICAgICAgIHJldHVybiByZWNlaXZlX2Z1bihtZXNzYWdlKTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHJldHVybiBudWxsO1xuICAgICAgfVxuICAgIH0gZWxzZSB7XG4gICAgICBsZXQgbm93ID0gRGF0ZS5ub3coKTtcbiAgICAgIHdoaWxlIChEYXRlLm5vdygpIDwgbm93ICsgdGltZW91dF9pbl9tcykge1xuICAgICAgICBpZiAoc2VsZi5tYWlsYm94Lmxlbmd0aCAhPT0gMCkge1xuICAgICAgICAgIGxldCBtZXNzYWdlID0gc2VsZi5tYWlsYm94WzBdO1xuICAgICAgICAgIHNlbGYubWFpbGJveCA9IHNlbGYubWFpbGJveC5zbGljZSgxKTtcbiAgICAgICAgICByZXR1cm4gcmVjZWl2ZV9mdW4obWVzc2FnZSk7XG4gICAgICAgIH1cbiAgICAgIH1cblxuICAgICAgcmV0dXJuIHRpbWVvdXRfZm4odGltZW91dF9pbl9tcyk7XG4gICAgfVxuICB9LFxuXG4gIHR1cGxlOiBmdW5jdGlvbiAoLi4uYXJncykge1xuICAgIHJldHVybiBuZXcgVHVwbGUoLi4uYXJncyk7XG4gIH0sXG5cbiAgX3RyeTogZnVuY3Rpb24gKGRvX2Z1biwgcmVzY3VlX2Z1bmN0aW9uLCBjYXRjaF9mdW4sIGVsc2VfZnVuY3Rpb24sIGFmdGVyX2Z1bmN0aW9uKSB7XG4gICAgbGV0IHJlc3VsdCA9IG51bGw7XG5cbiAgICB0cnkge1xuICAgICAgcmVzdWx0ID0gZG9fZnVuKCk7XG4gICAgfSBjYXRjaCAoZSkge1xuICAgICAgbGV0IGV4X3Jlc3VsdCA9IG51bGw7XG5cbiAgICAgIGlmIChyZXNjdWVfZnVuY3Rpb24pIHtcbiAgICAgICAgdHJ5IHtcbiAgICAgICAgICBleF9yZXN1bHQgPSByZXNjdWVfZnVuY3Rpb24oZSk7XG4gICAgICAgICAgcmV0dXJuIGV4X3Jlc3VsdDtcbiAgICAgICAgfSBjYXRjaCAoZXgpIHtcbiAgICAgICAgICBpZiAoZXggaW5zdGFuY2VvZiBQYXR0ZXJucy5NYXRjaEVycm9yKSB7XG4gICAgICAgICAgICB0aHJvdyBleDtcbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgIH1cblxuICAgICAgaWYgKGNhdGNoX2Z1bikge1xuICAgICAgICB0cnkge1xuICAgICAgICAgIGV4X3Jlc3VsdCA9IGNhdGNoX2Z1bihlKTtcbiAgICAgICAgICByZXR1cm4gZXhfcmVzdWx0O1xuICAgICAgICB9IGNhdGNoIChleCkge1xuICAgICAgICAgIGlmIChleCBpbnN0YW5jZW9mIFBhdHRlcm5zLk1hdGNoRXJyb3IpIHtcbiAgICAgICAgICAgIHRocm93IGV4O1xuICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgfVxuXG4gICAgICB0aHJvdyBlO1xuICAgIH0gZmluYWxseSB7XG4gICAgICBpZiAoYWZ0ZXJfZnVuY3Rpb24pIHtcbiAgICAgICAgYWZ0ZXJfZnVuY3Rpb24oKTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICBpZiAoZWxzZV9mdW5jdGlvbikge1xuICAgICAgdHJ5IHtcbiAgICAgICAgcmV0dXJuIGVsc2VfZnVuY3Rpb24ocmVzdWx0KTtcbiAgICAgIH0gY2F0Y2ggKGV4KSB7XG4gICAgICAgIGlmIChleCBpbnN0YW5jZW9mIFBhdHRlcm5zLk1hdGNoRXJyb3IpIHtcbiAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ05vIE1hdGNoIEZvdW5kIGluIEVsc2UnKTtcbiAgICAgICAgfVxuXG4gICAgICAgIHRocm93IGV4O1xuICAgICAgfVxuICAgIH0gZWxzZSB7XG4gICAgICByZXR1cm4gcmVzdWx0O1xuICAgIH1cbiAgfVxuXG59O1xuXG4vKiBAZmxvdyAqL1xuXG5sZXQgcHJvY2Vzc19jb3VudGVyID0gLTE7XG5cbmNsYXNzIFBJRCB7XG4gIGNvbnN0cnVjdG9yKCkge1xuICAgIHByb2Nlc3NfY291bnRlciA9IHByb2Nlc3NfY291bnRlciArIDE7XG4gICAgdGhpcy5pZCA9IHByb2Nlc3NfY291bnRlcjtcbiAgfVxuXG4gIHRvU3RyaW5nKCkge1xuICAgIHJldHVybiBcIlBJRCM8MC5cIiArIHRoaXMuaWQgKyBcIi4wPlwiO1xuICB9XG59XG5cbmNsYXNzIEludGVnZXJUeXBlIHt9XG5jbGFzcyBGbG9hdFR5cGUge31cblxuLy9odHRwczovL2dpdGh1Yi5jb20vYWlycG9ydHloL3Byb3RvbW9ycGhpc21cbmNsYXNzIFByb3RvY29sIHtcbiAgY29uc3RydWN0b3Ioc3BlYykge1xuICAgIHRoaXMucmVnaXN0cnkgPSBuZXcgTWFwKCk7XG4gICAgdGhpcy5mYWxsYmFjayA9IG51bGw7XG5cbiAgICBmb3IgKGxldCBmdW5OYW1lIGluIHNwZWMpIHtcbiAgICAgIHRoaXNbZnVuTmFtZV0gPSBjcmVhdGVGdW4oZnVuTmFtZSkuYmluZCh0aGlzKTtcbiAgICB9XG5cbiAgICBmdW5jdGlvbiBjcmVhdGVGdW4oZnVuTmFtZSkge1xuXG4gICAgICByZXR1cm4gZnVuY3Rpb24gKC4uLmFyZ3MpIHtcbiAgICAgICAgbGV0IHRoaW5nID0gYXJnc1swXTtcbiAgICAgICAgbGV0IGZ1biA9IG51bGw7XG5cbiAgICAgICAgaWYgKE51bWJlci5pc0ludGVnZXIodGhpbmcpICYmIHRoaXMuaGFzSW1wbGVtZW50YXRpb24oSW50ZWdlclR5cGUpKSB7XG4gICAgICAgICAgZnVuID0gdGhpcy5yZWdpc3RyeS5nZXQoSW50ZWdlclR5cGUpW2Z1bk5hbWVdO1xuICAgICAgICB9IGVsc2UgaWYgKHR5cGVvZiB0aGluZyA9PT0gXCJudW1iZXJcIiAmJiAhTnVtYmVyLmlzSW50ZWdlcih0aGluZykgJiYgdGhpcy5oYXNJbXBsZW1lbnRhdGlvbihGbG9hdFR5cGUpKSB7XG4gICAgICAgICAgZnVuID0gdGhpcy5yZWdpc3RyeS5nZXQoRmxvYXRUeXBlKVtmdW5OYW1lXTtcbiAgICAgICAgfSBlbHNlIGlmICh0aGlzLmhhc0ltcGxlbWVudGF0aW9uKHRoaW5nKSkge1xuICAgICAgICAgIGZ1biA9IHRoaXMucmVnaXN0cnkuZ2V0KHRoaW5nLmNvbnN0cnVjdG9yKVtmdW5OYW1lXTtcbiAgICAgICAgfSBlbHNlIGlmICh0aGlzLmZhbGxiYWNrKSB7XG4gICAgICAgICAgZnVuID0gdGhpcy5mYWxsYmFja1tmdW5OYW1lXTtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmIChmdW4gIT0gbnVsbCkge1xuICAgICAgICAgIGxldCByZXR2YWwgPSBmdW4uYXBwbHkodGhpcywgYXJncyk7XG4gICAgICAgICAgcmV0dXJuIHJldHZhbDtcbiAgICAgICAgfVxuXG4gICAgICAgIHRocm93IG5ldyBFcnJvcihcIk5vIGltcGxlbWVudGF0aW9uIGZvdW5kIGZvciBcIiArIHRoaW5nKTtcbiAgICAgIH07XG4gICAgfVxuICB9XG5cbiAgaW1wbGVtZW50YXRpb24odHlwZSwgaW1wbGVtZW50YXRpb24pIHtcbiAgICBpZiAodHlwZSA9PT0gbnVsbCkge1xuICAgICAgdGhpcy5mYWxsYmFjayA9IGltcGxlbWVudGF0aW9uO1xuICAgIH0gZWxzZSB7XG4gICAgICB0aGlzLnJlZ2lzdHJ5LnNldCh0eXBlLCBpbXBsZW1lbnRhdGlvbik7XG4gICAgfVxuICB9XG5cbiAgaGFzSW1wbGVtZW50YXRpb24odGhpbmcpIHtcbiAgICByZXR1cm4gdGhpcy5yZWdpc3RyeS5oYXModGhpbmcuY29uc3RydWN0b3IpO1xuICB9XG59XG5cbmZ1bmN0aW9uIHRsKGxpc3QpIHtcbiAgcmV0dXJuIFNwZWNpYWxGb3Jtcy5saXN0KC4uLmxpc3Quc2xpY2UoMSkpO1xufVxuXG5mdW5jdGlvbiBoZChsaXN0KSB7XG4gIHJldHVybiBsaXN0WzBdO1xufVxuXG5mdW5jdGlvbiBpc19uaWwoeCkge1xuICByZXR1cm4geCA9PT0gbnVsbDtcbn1cblxuZnVuY3Rpb24gaXNfYXRvbSh4KSB7XG4gIHJldHVybiB0eXBlb2YgeCA9PT0gJ3N5bWJvbCc7XG59XG5cbmZ1bmN0aW9uIGlzX2JpbmFyeSh4KSB7XG4gIHJldHVybiB0eXBlb2YgeCA9PT0gJ3N0cmluZycgfHwgeCBpbnN0YW5jZW9mIFN0cmluZztcbn1cblxuZnVuY3Rpb24gaXNfYm9vbGVhbih4KSB7XG4gIHJldHVybiB0eXBlb2YgeCA9PT0gJ2Jvb2xlYW4nIHx8IHggaW5zdGFuY2VvZiBCb29sZWFuO1xufVxuXG5mdW5jdGlvbiBpc19mdW5jdGlvbih4LCBhcml0eSA9IC0xKSB7XG4gIHJldHVybiB0eXBlb2YgeCA9PT0gJ2Z1bmN0aW9uJyB8fCB4IGluc3RhbmNlb2YgRnVuY3Rpb247XG59XG5cbmZ1bmN0aW9uIGlzX2Zsb2F0KHgpIHtcbiAgcmV0dXJuIGlzX251bWJlcih4KSAmJiAhTnVtYmVyLmlzSW50ZWdlcih4KTtcbn1cblxuZnVuY3Rpb24gaXNfaW50ZWdlcih4KSB7XG4gIHJldHVybiBOdW1iZXIuaXNJbnRlZ2VyKHgpO1xufVxuXG5mdW5jdGlvbiBpc19saXN0KHgpIHtcbiAgcmV0dXJuIHggaW5zdGFuY2VvZiBBcnJheTtcbn1cblxuZnVuY3Rpb24gaXNfbWFwKHgpIHtcbiAgcmV0dXJuIHR5cGVvZiB4ID09PSAnb2JqZWN0JyB8fCB4IGluc3RhbmNlb2YgT2JqZWN0O1xufVxuXG5mdW5jdGlvbiBpc19udW1iZXIoeCkge1xuICByZXR1cm4gdHlwZW9mIHggPT09ICdudW1iZXInO1xufVxuXG5mdW5jdGlvbiBpc190dXBsZSh4KSB7XG4gIHJldHVybiB4IGluc3RhbmNlb2YgVHVwbGU7XG59XG5cbmZ1bmN0aW9uIF9sZW5ndGgoeCkge1xuICByZXR1cm4geC5sZW5ndGg7XG59XG5cbmZ1bmN0aW9uIGlzX3BpZCh4KSB7XG4gIHJldHVybiB4IGluc3RhbmNlb2YgUElEO1xufVxuXG5mdW5jdGlvbiBpc19wb3J0KHgpIHtcbiAgcmV0dXJuIGZhbHNlO1xufVxuXG5mdW5jdGlvbiBpc19yZWZlcmVuY2UoeCkge1xuICByZXR1cm4gZmFsc2U7XG59XG5cbmZ1bmN0aW9uIGlzX2JpdHN0cmluZyh4KSB7XG4gIHJldHVybiBpc19iaW5hcnkoeCkgfHwgeCBpbnN0YW5jZW9mIEJpdFN0cmluZztcbn1cblxuZnVuY3Rpb24gX19pbl9fKGxlZnQsIHJpZ2h0KSB7XG4gIGZvciAobGV0IHggb2YgcmlnaHQpIHtcbiAgICBpZiAobWF0Y2hfX3FtYXJrX18obGVmdCwgeCkpIHtcbiAgICAgIHJldHVybiB0cnVlO1xuICAgIH1cbiAgfVxuXG4gIHJldHVybiBmYWxzZTtcbn1cblxuZnVuY3Rpb24gYWJzKG51bWJlcikge1xuICByZXR1cm4gTWF0aC5hYnMobnVtYmVyKTtcbn1cblxuZnVuY3Rpb24gcm91bmQobnVtYmVyKSB7XG4gIHJldHVybiBNYXRoLnJvdW5kKG51bWJlcik7XG59XG5cbmZ1bmN0aW9uIGVsZW0odHVwbGUsIGluZGV4KSB7XG4gIGlmIChpc19saXN0KHR1cGxlKSkge1xuICAgIHJldHVybiB0dXBsZVtpbmRleF07XG4gIH1cblxuICByZXR1cm4gdHVwbGUuZ2V0KGluZGV4KTtcbn1cblxuZnVuY3Rpb24gcmVtKGxlZnQsIHJpZ2h0KSB7XG4gIHJldHVybiBsZWZ0ICUgcmlnaHQ7XG59XG5cbmZ1bmN0aW9uIGRpdihsZWZ0LCByaWdodCkge1xuICByZXR1cm4gbGVmdCAvIHJpZ2h0O1xufVxuXG5mdW5jdGlvbiBhbmQobGVmdCwgcmlnaHQpIHtcbiAgcmV0dXJuIGxlZnQgJiYgcmlnaHQ7XG59XG5cbmZ1bmN0aW9uIG9yKGxlZnQsIHJpZ2h0KSB7XG4gIHJldHVybiBsZWZ0IHx8IHJpZ2h0O1xufVxuXG5mdW5jdGlvbiBub3QoYXJnKSB7XG4gIHJldHVybiAhYXJnO1xufVxuXG5mdW5jdGlvbiBhcHBseSguLi5hcmdzKSB7XG4gIGlmIChhcmdzLmxlbmd0aCA9PT0gMykge1xuICAgIGxldCBtb2QgPSBhcmdzWzBdO1xuICAgIGxldCBmdW5jID0gYXJnc1sxXTtcbiAgICBsZXQgZnVuY19hcmdzID0gYXJnc1syXTtcbiAgICByZXR1cm4gbW9kW2Z1bmNdLmFwcGx5KG51bGwsIGZ1bmNfYXJncyk7XG4gIH0gZWxzZSB7XG4gICAgbGV0IGZ1bmMgPSBhcmdzWzBdO1xuICAgIGxldCBmdW5jX2FyZ3MgPSBhcmdzWzFdO1xuXG4gICAgcmV0dXJuIGZ1bmMuYXBwbHkobnVsbCwgZnVuY19hcmdzKTtcbiAgfVxufVxuXG5mdW5jdGlvbiB0b19zdHJpbmcoYXJnKSB7XG4gIGlmIChpc190dXBsZShhcmcpKSB7XG4gICAgcmV0dXJuIFR1cGxlLnRvX3N0cmluZyhhcmcpO1xuICB9XG5cbiAgcmV0dXJuIGFyZy50b1N0cmluZygpO1xufVxuXG5mdW5jdGlvbiBtYXRjaF9fcW1hcmtfXyhwYXR0ZXJuLCBleHByLCBndWFyZCA9ICgpID0+IHRydWUpIHtcbiAgcmV0dXJuIF9QYXR0ZXJucy5tYXRjaF9ub190aHJvdyhwYXR0ZXJuLCBleHByLCBndWFyZCkgIT0gbnVsbDtcbn1cblxuZnVuY3Rpb24gZGVmc3RydWN0KGRlZmF1bHRzKSB7XG4gIHJldHVybiBjbGFzcyB7XG4gICAgY29uc3RydWN0b3IodXBkYXRlID0ge30pIHtcbiAgICAgIGxldCB0aGVfdmFsdWVzID0gT2JqZWN0LmFzc2lnbihkZWZhdWx0cywgdXBkYXRlKTtcbiAgICAgIE9iamVjdC5hc3NpZ24odGhpcywgdGhlX3ZhbHVlcyk7XG4gICAgfVxuXG4gICAgc3RhdGljIGNyZWF0ZSh1cGRhdGVzID0ge30pIHtcbiAgICAgIGxldCB4ID0gbmV3IHRoaXModXBkYXRlcyk7XG4gICAgICByZXR1cm4gT2JqZWN0LmZyZWV6ZSh4KTtcbiAgICB9XG4gIH07XG59XG5cbmZ1bmN0aW9uIGRlZmV4Y2VwdGlvbihkZWZhdWx0cykge1xuICByZXR1cm4gY2xhc3MgZXh0ZW5kcyBFcnJvciB7XG4gICAgY29uc3RydWN0b3IodXBkYXRlID0ge30pIHtcbiAgICAgIGxldCBtZXNzYWdlID0gdXBkYXRlLm1lc3NhZ2UgfHwgJyc7XG4gICAgICBzdXBlcihtZXNzYWdlKTtcblxuICAgICAgbGV0IHRoZV92YWx1ZXMgPSBPYmplY3QuYXNzaWduKGRlZmF1bHRzLCB1cGRhdGUpO1xuICAgICAgT2JqZWN0LmFzc2lnbih0aGlzLCB0aGVfdmFsdWVzKTtcblxuICAgICAgdGhpcy5uYW1lID0gdGhpcy5jb25zdHJ1Y3Rvci5uYW1lO1xuICAgICAgdGhpcy5tZXNzYWdlID0gbWVzc2FnZTtcbiAgICAgIHRoaXNbU3BlY2lhbEZvcm1zLmF0b20oJ19fZXhjZXB0aW9uX18nKV0gPSB0cnVlO1xuICAgICAgRXJyb3IuY2FwdHVyZVN0YWNrVHJhY2UodGhpcywgdGhpcy5jb25zdHJ1Y3Rvci5uYW1lKTtcbiAgICB9XG5cbiAgICBzdGF0aWMgY3JlYXRlKHVwZGF0ZXMgPSB7fSkge1xuICAgICAgbGV0IHggPSBuZXcgdGhpcyh1cGRhdGVzKTtcbiAgICAgIHJldHVybiBPYmplY3QuZnJlZXplKHgpO1xuICAgIH1cbiAgfTtcbn1cblxuZnVuY3Rpb24gZGVmcHJvdG9jb2woc3BlYykge1xuICByZXR1cm4gbmV3IFByb3RvY29sKHNwZWMpO1xufVxuXG5mdW5jdGlvbiBkZWZpbXBsKHByb3RvY29sLCB0eXBlLCBpbXBsKSB7XG4gIHByb3RvY29sLmltcGxlbWVudGF0aW9uKHR5cGUsIGltcGwpO1xufVxuXG52YXIgS2VybmVsID0ge1xuICBTcGVjaWFsRm9ybXMsXG4gIHRsLFxuICBoZCxcbiAgaXNfbmlsLFxuICBpc19hdG9tLFxuICBpc19iaW5hcnksXG4gIGlzX2Jvb2xlYW4sXG4gIGlzX2Z1bmN0aW9uLFxuICBpc19mbG9hdCxcbiAgaXNfaW50ZWdlcixcbiAgaXNfbGlzdCxcbiAgaXNfbWFwLFxuICBpc19udW1iZXIsXG4gIGlzX3R1cGxlLFxuICBsZW5ndGg6IF9sZW5ndGgsXG4gIGlzX3BpZCxcbiAgaXNfcG9ydCxcbiAgaXNfcmVmZXJlbmNlLFxuICBpc19iaXRzdHJpbmcsXG4gIGluOiBfX2luX18sXG4gIGFicyxcbiAgcm91bmQsXG4gIGVsZW0sXG4gIHJlbSxcbiAgZGl2LFxuICBhbmQsXG4gIG9yLFxuICBub3QsXG4gIGFwcGx5LFxuICB0b19zdHJpbmcsXG4gIG1hdGNoX19xbWFya19fLFxuICBkZWZzdHJ1Y3QsXG4gIGRlZnByb3RvY29sLFxuICBkZWZpbXBsXG59O1xuXG5sZXQgRW51bSA9IHtcblxuICBhbGxfX3FtYXJrX186IGZ1bmN0aW9uIChjb2xsZWN0aW9uLCBmdW4gPSB4ID0+IHgpIHtcbiAgICBmb3IgKGxldCBlbGVtIG9mIGNvbGxlY3Rpb24pIHtcbiAgICAgIGlmICghZnVuKGVsZW0pKSB7XG4gICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICByZXR1cm4gdHJ1ZTtcbiAgfSxcblxuICBhbnlfX3FtYXJrX186IGZ1bmN0aW9uIChjb2xsZWN0aW9uLCBmdW4gPSB4ID0+IHgpIHtcbiAgICBmb3IgKGxldCBlbGVtIG9mIGNvbGxlY3Rpb24pIHtcbiAgICAgIGlmIChmdW4oZWxlbSkpIHtcbiAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICB9XG4gICAgfVxuXG4gICAgcmV0dXJuIGZhbHNlO1xuICB9LFxuXG4gIGF0OiBmdW5jdGlvbiAoY29sbGVjdGlvbiwgbiwgdGhlX2RlZmF1bHQgPSBudWxsKSB7XG4gICAgaWYgKG4gPiB0aGlzLmNvdW50KGNvbGxlY3Rpb24pIHx8IG4gPCAwKSB7XG4gICAgICByZXR1cm4gdGhlX2RlZmF1bHQ7XG4gICAgfVxuXG4gICAgcmV0dXJuIGNvbGxlY3Rpb25bbl07XG4gIH0sXG5cbiAgY29uY2F0OiBmdW5jdGlvbiAoLi4uZW51bWFibGVzKSB7XG4gICAgcmV0dXJuIGVudW1hYmxlc1swXS5jb25jYXQoZW51bWFibGVzWzFdKTtcbiAgfSxcblxuICBjb3VudDogZnVuY3Rpb24gKGNvbGxlY3Rpb24sIGZ1biA9IG51bGwpIHtcbiAgICBpZiAoZnVuID09IG51bGwpIHtcbiAgICAgIHJldHVybiBjb2xsZWN0aW9uLmxlbmd0aDtcbiAgICB9IGVsc2Uge1xuICAgICAgcmV0dXJuIGNvbGxlY3Rpb24uZmlsdGVyKGZ1bikubGVuZ3RoO1xuICAgIH1cbiAgfSxcblxuICBkcm9wOiBmdW5jdGlvbiAoY29sbGVjdGlvbiwgY291bnQpIHtcbiAgICByZXR1cm4gY29sbGVjdGlvbi5zbGljZShjb3VudCk7XG4gIH0sXG5cbiAgZHJvcF93aGlsZTogZnVuY3Rpb24gKGNvbGxlY3Rpb24sIGZ1bikge1xuICAgIGxldCBjb3VudCA9IDA7XG5cbiAgICBmb3IgKGxldCBlbGVtIG9mIGNvbGxlY3Rpb24pIHtcbiAgICAgIGlmIChmdW4oZWxlbSkpIHtcbiAgICAgICAgY291bnQgPSBjb3VudCArIDE7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBicmVhaztcbiAgICAgIH1cbiAgICB9XG5cbiAgICByZXR1cm4gY29sbGVjdGlvbi5zbGljZShjb3VudCk7XG4gIH0sXG5cbiAgZWFjaDogZnVuY3Rpb24gKGNvbGxlY3Rpb24sIGZ1bikge1xuICAgIGZvciAobGV0IGVsZW0gb2YgY29sbGVjdGlvbikge1xuICAgICAgZnVuKGVsZW0pO1xuICAgIH1cbiAgfSxcblxuICBlbXB0eV9fcW1hcmtfXzogZnVuY3Rpb24gKGNvbGxlY3Rpb24pIHtcbiAgICByZXR1cm4gY29sbGVjdGlvbi5sZW5ndGggPT09IDA7XG4gIH0sXG5cbiAgZmV0Y2g6IGZ1bmN0aW9uIChjb2xsZWN0aW9uLCBuKSB7XG4gICAgaWYgKEtlcm5lbC5pc19saXN0KGNvbGxlY3Rpb24pKSB7XG4gICAgICBpZiAobiA8IHRoaXMuY291bnQoY29sbGVjdGlvbikgJiYgbiA+PSAwKSB7XG4gICAgICAgIHJldHVybiBLZXJuZWwuU3BlY2lhbEZvcm1zLnR1cGxlKEtlcm5lbC5TcGVjaWFsRm9ybXMuYXRvbShcIm9rXCIpLCBjb2xsZWN0aW9uW25dKTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHJldHVybiBLZXJuZWwuU3BlY2lhbEZvcm1zLmF0b20oXCJlcnJvclwiKTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICB0aHJvdyBuZXcgRXJyb3IoXCJjb2xsZWN0aW9uIGlzIG5vdCBhbiBFbnVtZXJhYmxlXCIpO1xuICB9LFxuXG4gIGZldGNoX19lbWFya19fOiBmdW5jdGlvbiAoY29sbGVjdGlvbiwgbikge1xuICAgIGlmIChLZXJuZWwuaXNfbGlzdChjb2xsZWN0aW9uKSkge1xuICAgICAgaWYgKG4gPCB0aGlzLmNvdW50KGNvbGxlY3Rpb24pICYmIG4gPj0gMCkge1xuICAgICAgICByZXR1cm4gY29sbGVjdGlvbltuXTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcihcIm91dCBvZiBib3VuZHMgZXJyb3JcIik7XG4gICAgICB9XG4gICAgfVxuXG4gICAgdGhyb3cgbmV3IEVycm9yKFwiY29sbGVjdGlvbiBpcyBub3QgYW4gRW51bWVyYWJsZVwiKTtcbiAgfSxcblxuICBmaWx0ZXI6IGZ1bmN0aW9uIChjb2xsZWN0aW9uLCBmdW4pIHtcbiAgICBsZXQgcmVzdWx0ID0gW107XG5cbiAgICBmb3IgKGxldCBlbGVtIG9mIGNvbGxlY3Rpb24pIHtcbiAgICAgIGlmIChmdW4oZWxlbSkpIHtcbiAgICAgICAgcmVzdWx0LnB1c2goZWxlbSk7XG4gICAgICB9XG4gICAgfVxuXG4gICAgcmV0dXJuIHJlc3VsdDtcbiAgfSxcblxuICBmaWx0ZXJfbWFwOiBmdW5jdGlvbiAoY29sbGVjdGlvbiwgZmlsdGVyLCBtYXBwZXIpIHtcbiAgICByZXR1cm4gRW51bS5tYXAoRW51bS5maWx0ZXIoY29sbGVjdGlvbiwgZmlsdGVyKSwgbWFwcGVyKTtcbiAgfSxcblxuICBmaW5kOiBmdW5jdGlvbiAoY29sbGVjdGlvbiwgaWZfbm9uZSA9IG51bGwsIGZ1bikge1xuICAgIGZvciAobGV0IGVsZW0gb2YgY29sbGVjdGlvbikge1xuICAgICAgaWYgKGZ1bihlbGVtKSkge1xuICAgICAgICByZXR1cm4gZWxlbTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICByZXR1cm4gaWZfbm9uZTtcbiAgfSxcblxuICBpbnRvOiBmdW5jdGlvbiAoY29sbGVjdGlvbiwgbGlzdCkge1xuICAgIHJldHVybiBsaXN0LmNvbmNhdChjb2xsZWN0aW9uKTtcbiAgfSxcblxuICBtYXA6IGZ1bmN0aW9uIChjb2xsZWN0aW9uLCBmdW4pIHtcbiAgICBsZXQgcmVzdWx0ID0gW107XG5cbiAgICBmb3IgKGxldCBlbGVtIG9mIGNvbGxlY3Rpb24pIHtcbiAgICAgIHJlc3VsdC5wdXNoKGZ1bihlbGVtKSk7XG4gICAgfVxuXG4gICAgcmV0dXJuIHJlc3VsdDtcbiAgfSxcblxuICBtYXBfcmVkdWNlOiBmdW5jdGlvbiAoY29sbGVjdGlvbiwgYWNjLCBmdW4pIHtcbiAgICBsZXQgbWFwcGVkID0gS2VybmVsLlNwZWNpYWxGb3Jtcy5saXN0KCk7XG4gICAgbGV0IHRoZV9hY2MgPSBhY2M7XG5cbiAgICBmb3IgKHZhciBpID0gMDsgaSA8IHRoaXMuY291bnQoY29sbGVjdGlvbik7IGkrKykge1xuICAgICAgbGV0IHR1cGxlID0gZnVuKGNvbGxlY3Rpb25baV0sIHRoZV9hY2MpO1xuXG4gICAgICB0aGVfYWNjID0gS2VybmVsLmVsZW0odHVwbGUsIDEpO1xuICAgICAgbWFwcGVkID0gS2VybmVsLlNwZWNpYWxGb3Jtcy5saXN0KC4uLm1hcHBlZC5jb25jYXQoW0tlcm5lbC5lbGVtKHR1cGxlLCAwKV0pKTtcbiAgICB9XG5cbiAgICByZXR1cm4gS2VybmVsLlNwZWNpYWxGb3Jtcy50dXBsZShtYXBwZWQsIHRoZV9hY2MpO1xuICB9LFxuXG4gIG1lbWJlcjogZnVuY3Rpb24gKGNvbGxlY3Rpb24sIHZhbHVlKSB7XG4gICAgcmV0dXJuIGNvbGxlY3Rpb24uaW5jbHVkZXModmFsdWUpO1xuICB9LFxuXG4gIHJlZHVjZTogZnVuY3Rpb24gKGNvbGxlY3Rpb24sIGFjYywgZnVuKSB7XG4gICAgbGV0IHRoZV9hY2MgPSBhY2M7XG5cbiAgICBmb3IgKHZhciBpID0gMDsgaSA8IHRoaXMuY291bnQoY29sbGVjdGlvbik7IGkrKykge1xuICAgICAgbGV0IHR1cGxlID0gZnVuKGNvbGxlY3Rpb25baV0sIHRoZV9hY2MpO1xuXG4gICAgICB0aGVfYWNjID0gS2VybmVsLmVsZW0odHVwbGUsIDEpO1xuICAgIH1cblxuICAgIHJldHVybiB0aGVfYWNjO1xuICB9LFxuXG4gIHRha2U6IGZ1bmN0aW9uIChjb2xsZWN0aW9uLCBjb3VudCkge1xuICAgIHJldHVybiBjb2xsZWN0aW9uLnNsaWNlKDAsIGNvdW50KTtcbiAgfSxcblxuICB0YWtlX2V2ZXJ5OiBmdW5jdGlvbiAoY29sbGVjdGlvbiwgbnRoKSB7XG4gICAgbGV0IHJlc3VsdCA9IFtdO1xuICAgIGxldCBpbmRleCA9IDA7XG5cbiAgICBmb3IgKGxldCBlbGVtIG9mIGNvbGxlY3Rpb24pIHtcbiAgICAgIGlmIChpbmRleCAlIG50aCA9PT0gMCkge1xuICAgICAgICByZXN1bHQucHVzaChlbGVtKTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICByZXR1cm4gS2VybmVsLlNwZWNpYWxGb3Jtcy5saXN0KC4uLnJlc3VsdCk7XG4gIH0sXG5cbiAgdGFrZV93aGlsZTogZnVuY3Rpb24gKGNvbGxlY3Rpb24sIGZ1bikge1xuICAgIGxldCBjb3VudCA9IDA7XG5cbiAgICBmb3IgKGxldCBlbGVtIG9mIGNvbGxlY3Rpb24pIHtcbiAgICAgIGlmIChmdW4oZWxlbSkpIHtcbiAgICAgICAgY291bnQgPSBjb3VudCArIDE7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBicmVhaztcbiAgICAgIH1cbiAgICB9XG5cbiAgICByZXR1cm4gY29sbGVjdGlvbi5zbGljZSgwLCBjb3VudCk7XG4gIH0sXG5cbiAgdG9fbGlzdDogZnVuY3Rpb24gKGNvbGxlY3Rpb24pIHtcbiAgICByZXR1cm4gY29sbGVjdGlvbjtcbiAgfVxufTtcblxubGV0IEF0b20gPSB7fTtcblxuQXRvbS50b19zdHJpbmcgPSBmdW5jdGlvbiAoYXRvbSkge1xuICByZXR1cm4gU3ltYm9sLmtleUZvcihhdG9tKTtcbn07XG5cbkF0b20udG9fY2hhcl9saXN0ID0gZnVuY3Rpb24gKGF0b20pIHtcbiAgcmV0dXJuIEF0b20udG9fc3RyaW5nKGF0b20pLnNwbGl0KCcnKTtcbn07XG5cbmxldCBJbnRlZ2VyID0ge1xuXG4gIGlzX2V2ZW46IGZ1bmN0aW9uIChuKSB7XG4gICAgcmV0dXJuIG4gJSAyID09PSAwO1xuICB9LFxuXG4gIGlzX29kZDogZnVuY3Rpb24gKG4pIHtcbiAgICByZXR1cm4gbiAlIDIgIT09IDA7XG4gIH0sXG5cbiAgcGFyc2U6IGZ1bmN0aW9uIChiaW4pIHtcbiAgICBsZXQgcmVzdWx0ID0gcGFyc2VJbnQoYmluKTtcblxuICAgIGlmIChpc05hTihyZXN1bHQpKSB7XG4gICAgICByZXR1cm4gS2VybmVsLlNwZWNpYWxGb3Jtcy5hdG9tKFwiZXJyb3JcIik7XG4gICAgfVxuXG4gICAgbGV0IGluZGV4T2ZEb3QgPSBiaW4uaW5kZXhPZihcIi5cIik7XG5cbiAgICBpZiAoaW5kZXhPZkRvdCA+PSAwKSB7XG4gICAgICByZXR1cm4gS2VybmVsLlNwZWNpYWxGb3Jtcy50dXBsZShyZXN1bHQsIGJpbi5zdWJzdHJpbmcoaW5kZXhPZkRvdCkpO1xuICAgIH1cblxuICAgIHJldHVybiBLZXJuZWwuU3BlY2lhbEZvcm1zLnR1cGxlKHJlc3VsdCwgXCJcIik7XG4gIH0sXG5cbiAgdG9fY2hhcl9saXN0OiBmdW5jdGlvbiAobnVtYmVyLCBiYXNlID0gMTApIHtcbiAgICByZXR1cm4gbnVtYmVyLnRvU3RyaW5nKGJhc2UpLnNwbGl0KFwiXCIpO1xuICB9LFxuXG4gIHRvX3N0cmluZzogZnVuY3Rpb24gKG51bWJlciwgYmFzZSA9IDEwKSB7XG4gICAgcmV0dXJuIG51bWJlci50b1N0cmluZyhiYXNlKTtcbiAgfVxufTtcblxubGV0IF9DaGFycyA9IEtlcm5lbC5kZWZwcm90b2NvbCh7XG4gIHRvX3N0cmluZzogZnVuY3Rpb24gKHRoaW5nKSB7fVxufSk7XG5cbktlcm5lbC5kZWZpbXBsKF9DaGFycywgQml0U3RyaW5nLCB7XG4gIHRvX3N0cmluZzogZnVuY3Rpb24gKHRoaW5nKSB7XG4gICAgaWYgKEtlcm5lbC5pc19iaW5hcnkodGhpbmcpKSB7XG4gICAgICByZXR1cm4gdGhpbmc7XG4gICAgfVxuXG4gICAgcmV0dXJuIHRoaW5nLnRvU3RyaW5nKCk7XG4gIH1cbn0pO1xuXG5LZXJuZWwuZGVmaW1wbChfQ2hhcnMsIFN5bWJvbCwge1xuICB0b19zdHJpbmc6IGZ1bmN0aW9uICh0aGluZykge1xuICAgIGlmIChuaWwpIHtcbiAgICAgIHJldHVybiBcIlwiO1xuICAgIH1cblxuICAgIHJldHVybiBBdG9tLnRvX3N0cmluZyh0aGluZyk7XG4gIH1cbn0pO1xuXG5LZXJuZWwuZGVmaW1wbChfQ2hhcnMsIEludGVnZXJUeXBlLCB7XG4gIHRvX3N0cmluZzogZnVuY3Rpb24gKHRoaW5nKSB7XG4gICAgcmV0dXJuIEludGVnZXIudG9fc3RyaW5nKHRoaW5nKTtcbiAgfVxufSk7XG5cbktlcm5lbC5kZWZpbXBsKF9DaGFycywgRmxvYXRUeXBlLCB7XG4gIHRvX3N0cmluZzogZnVuY3Rpb24gKHRoaW5nKSB7XG4gICAgcmV0dXJuIHRoaW5nLnRvU3RyaW5nO1xuICB9XG59KTtcblxuS2VybmVsLmRlZmltcGwoX0NoYXJzLCBBcnJheSwge1xuICB0b19zdHJpbmc6IGZ1bmN0aW9uICh0aGluZykge1xuICAgIHJldHVybiB0aGluZy50b1N0cmluZygpO1xuICB9XG59KTtcblxuS2VybmVsLmRlZmltcGwoX0NoYXJzLCBUdXBsZSwge1xuICB0b19zdHJpbmc6IGZ1bmN0aW9uICh0aGluZykge1xuICAgIHJldHVybiBUdXBsZS50b19zdHJpbmcodGhpbmcpO1xuICB9XG59KTtcblxuS2VybmVsLmRlZmltcGwoX0NoYXJzLCBudWxsLCB7XG4gIHRvX3N0cmluZzogZnVuY3Rpb24gKHRoaW5nKSB7XG4gICAgcmV0dXJuIHRoaW5nLnRvU3RyaW5nKCk7XG4gIH1cbn0pO1xuXG5mdW5jdGlvbiB0b19hdG9tKHN0cmluZykge1xuICByZXR1cm4gU3ltYm9sLmZvcihzdHJpbmcpO1xufVxuXG5mdW5jdGlvbiB0b19leGlzdGluZ19hdG9tKHN0cmluZykge1xuICByZXR1cm4gU3ltYm9sLmZvcihzdHJpbmcpO1xufVxuXG5mdW5jdGlvbiB0b19jaGFyX2xpc3Qoc3RyaW5nKSB7XG4gIHJldHVybiBzdHJpbmcuc3BsaXQoJycpO1xufVxuXG5mdW5jdGlvbiB0b19mbG9hdChzdHJpbmcpIHtcbiAgcmV0dXJuIHBhcnNlRmxvYXQoc3RyaW5nKTtcbn1cblxuZnVuY3Rpb24gdG9faW50ZWdlcihzdHJpbmcsIGJhc2UgPSAxMCkge1xuICByZXR1cm4gcGFyc2VJbnQoc3RyaW5nLCBiYXNlKTtcbn1cblxuZnVuY3Rpb24gdXBjYXNlKGJpbmFyeSkge1xuICByZXR1cm4gYmluYXJ5LnRvVXBwZXJDYXNlKCk7XG59XG5cbmZ1bmN0aW9uIGRvd25jYXNlKGJpbmFyeSkge1xuICByZXR1cm4gYmluYXJ5LnRvTG93ZXJDYXNlKCk7XG59XG5cbmZ1bmN0aW9uIGF0KHN0cmluZywgcG9zaXRpb24pIHtcbiAgaWYgKHBvc2l0aW9uID4gc3RyaW5nLmxlbmd0aCAtIDEpIHtcbiAgICByZXR1cm4gbnVsbDtcbiAgfVxuXG4gIHJldHVybiBzdHJpbmdbcG9zaXRpb25dO1xufVxuXG5mdW5jdGlvbiBjYXBpdGFsaXplKHN0cmluZykge1xuICBsZXQgcmV0dXJuU3RyaW5nID0gJyc7XG5cbiAgZm9yIChsZXQgaSA9IDA7IGkgPCBzdHJpbmcubGVuZ3RoOyBpKyspIHtcbiAgICBpZiAoaSA9PT0gMCkge1xuICAgICAgcmV0dXJuU3RyaW5nID0gcmV0dXJuU3RyaW5nICsgc3RyaW5nW2ldLnRvVXBwZXJDYXNlKCk7XG4gICAgfSBlbHNlIHtcbiAgICAgIHJldHVyblN0cmluZyA9IHJldHVyblN0cmluZyArIHN0cmluZ1tpXS50b0xvd2VyQ2FzZSgpO1xuICAgIH1cbiAgfVxuXG4gIHJldHVybiByZXR1cm5TdHJpbmc7XG59XG5cbmZ1bmN0aW9uIGNvZGVwb2ludHMoc3RyaW5nKSB7XG4gIHJldHVybiB0b19jaGFyX2xpc3Qoc3RyaW5nKS5tYXAoZnVuY3Rpb24gKGMpIHtcbiAgICByZXR1cm4gYy5jb2RlUG9pbnRBdCgwKTtcbiAgfSk7XG59XG5cbmZ1bmN0aW9uIGNvbnRhaW5zX19xbV9fKHN0cmluZywgY29udGFpbnMpIHtcbiAgaWYgKEFycmF5LmlzQXJyYXkoY29udGFpbnMpKSB7XG4gICAgcmV0dXJuIGNvbnRhaW5zLnNvbWUoZnVuY3Rpb24gKHMpIHtcbiAgICAgIHJldHVybiBzdHJpbmcuaW5kZXhPZihzKSA+IC0xO1xuICAgIH0pO1xuICB9XG5cbiAgcmV0dXJuIHN0cmluZy5pbmRleE9mKGNvbnRhaW5zKSA+IC0xO1xufVxuXG5mdW5jdGlvbiBkdXBsaWNhdGUoc3ViamVjdCwgbikge1xuICByZXR1cm4gc3ViamVjdC5yZXBlYXQobik7XG59XG5cbmZ1bmN0aW9uIGVuZHNfd2l0aF9fcW1fXyhzdHJpbmcsIHN1ZmZpeGVzKSB7XG4gIGlmIChBcnJheS5pc0FycmF5KHN1ZmZpeGVzKSkge1xuICAgIHJldHVybiBzdWZmaXhlcy5zb21lKGZ1bmN0aW9uIChzKSB7XG4gICAgICByZXR1cm4gc3RyaW5nLmVuZHNXaXRoKHMpO1xuICAgIH0pO1xuICB9XG5cbiAgcmV0dXJuIHN0cmluZy5lbmRzV2l0aChzdWZmaXhlcyk7XG59XG5cbmZ1bmN0aW9uIGZpcnN0KHN0cmluZykge1xuICBpZiAoIXN0cmluZykge1xuICAgIHJldHVybiBudWxsO1xuICB9XG5cbiAgcmV0dXJuIHN0cmluZ1swXTtcbn1cblxuZnVuY3Rpb24gZ3JhcGhlbWVzKHN0cmluZykge1xuICByZXR1cm4gc3RyaW5nLnNwbGl0KCcnKTtcbn1cblxuZnVuY3Rpb24gbGFzdChzdHJpbmcpIHtcbiAgaWYgKCFzdHJpbmcpIHtcbiAgICByZXR1cm4gbnVsbDtcbiAgfVxuXG4gIHJldHVybiBzdHJpbmdbc3RyaW5nLmxlbmd0aCAtIDFdO1xufVxuXG5mdW5jdGlvbiBsZW5ndGgoc3RyaW5nKSB7XG4gIHJldHVybiBzdHJpbmcubGVuZ3RoO1xufVxuXG5mdW5jdGlvbiBtYXRjaF9fcW1fXyhzdHJpbmcsIHJlZ2V4KSB7XG4gIHJldHVybiBzdHJpbmcubWF0Y2gocmVnZXgpICE9IG51bGw7XG59XG5cbmZ1bmN0aW9uIG5leHRfY29kZXBvaW50KHN0cmluZykge1xuICBpZiAoIXN0cmluZyB8fCBzdHJpbmcgPT09ICcnKSB7XG4gICAgcmV0dXJuIG51bGw7XG4gIH1cblxuICByZXR1cm4gS2VybmVsLlNwZWNpYWxGb3Jtcy50dXBsZShzdHJpbmdbMF0uY29kZVBvaW50QXQoMCksIHN0cmluZy5zdWJzdHIoMSkpO1xufVxuXG5mdW5jdGlvbiBuZXh0X2dyYXBoZW1lKHN0cmluZykge1xuICBpZiAoIXN0cmluZyB8fCBzdHJpbmcgPT09ICcnKSB7XG4gICAgcmV0dXJuIG51bGw7XG4gIH1cblxuICByZXR1cm4gS2VybmVsLlNwZWNpYWxGb3Jtcy50dXBsZShzdHJpbmdbMF0sIHN0cmluZy5zdWJzdHIoMSkpO1xufVxuXG5mdW5jdGlvbiByZXZlcnNlKHN0cmluZykge1xuICBsZXQgcmV0dXJuVmFsdWUgPSAnJztcblxuICBmb3IgKHZhciBpID0gc3RyaW5nLmxlbmd0aCAtIDE7IGkgPj0gMDsgaS0tKSB7XG4gICAgcmV0dXJuVmFsdWUgPSByZXR1cm5WYWx1ZSArIHN0cmluZ1tpXTtcbiAgfTtcblxuICByZXR1cm4gcmV0dXJuVmFsdWU7XG59XG5cbmZ1bmN0aW9uIF9zcGxpdChzdHJpbmcpIHtcbiAgcmV0dXJuIHN0cmluZy5zcGxpdCgpO1xufVxuXG5mdW5jdGlvbiBzdGFydHNfd2l0aF9fcW1fXyhzdHJpbmcsIHByZWZpeGVzKSB7XG4gIGlmIChBcnJheS5pc0FycmF5KHByZWZpeGVzKSkge1xuICAgIHJldHVybiBwcmVmaXhlcy5zb21lKGZ1bmN0aW9uIChzKSB7XG4gICAgICByZXR1cm4gc3RyaW5nLnN0YXJ0c1dpdGgocyk7XG4gICAgfSk7XG4gIH1cblxuICByZXR1cm4gc3RyaW5nLnN0YXJ0c1dpdGgocHJlZml4ZXMpO1xufVxuXG5mdW5jdGlvbiB2YWxpZF9jaGFyYWN0ZXJfX3FtX18oY29kZXBvaW50KSB7XG4gIHRyeSB7XG4gICAgcmV0dXJuIFN0cmluZy5mcm9tQ29kZVBvaW50KGNvZGVwb2ludCkgIT0gbnVsbDtcbiAgfSBjYXRjaCAoZSkge1xuICAgIHJldHVybiBmYWxzZTtcbiAgfVxufVxuXG52YXIgX1N0cmluZyA9IHtcbiAgYXQsXG4gIGNhcGl0YWxpemUsXG4gIGNvZGVwb2ludHMsXG4gIGNvbnRhaW5zX19xbV9fLFxuICBkb3duY2FzZSxcbiAgZHVwbGljYXRlLFxuICBlbmRzX3dpdGhfX3FtX18sXG4gIGZpcnN0LFxuICBncmFwaGVtZXMsXG4gIGxhc3QsXG4gIGxlbmd0aCxcbiAgbWF0Y2hfX3FtX18sXG4gIG5leHRfY29kZXBvaW50LFxuICBuZXh0X2dyYXBoZW1lLFxuICByZXZlcnNlLFxuICBzcGxpdDogX3NwbGl0LFxuICBzdGFydHNfd2l0aF9fcW1fXyxcbiAgdG9fYXRvbSxcbiAgdG9fY2hhcl9saXN0LFxuICB0b19leGlzdGluZ19hdG9tLFxuICB0b19mbG9hdCxcbiAgdG9faW50ZWdlcixcbiAgdXBjYXNlLFxuICB2YWxpZF9jaGFyYWN0ZXJfX3FtX18sXG4gIENoYXJzOiBfQ2hhcnNcbn07XG5cbmxldCBDaGFycyA9IEtlcm5lbC5kZWZwcm90b2NvbCh7XG4gIHRvX2NoYXJfbGlzdDogZnVuY3Rpb24gKHRoaW5nKSB7fVxufSk7XG5cbktlcm5lbC5kZWZpbXBsKENoYXJzLCBLZXJuZWwuaXNfYml0c3RyaW5nLCB7XG4gIHRvX2NoYXJfbGlzdDogZnVuY3Rpb24gKHRoaW5nKSB7XG4gICAgaWYgKEtlcm5lbC5pc19iaW5hcnkodGhpbmcpKSB7XG4gICAgICByZXR1cm4gX1N0cmluZy50b19jaGFyX2xpc3QodGhpbmcpO1xuICAgIH1cblxuICAgIHJldHVybiB0aGluZy50b1N0cmluZygpO1xuICB9XG59KTtcblxuS2VybmVsLmRlZmltcGwoQ2hhcnMsIEtlcm5lbC5pc19hdG9tLCB7XG4gIHRvX2NoYXJfbGlzdDogZnVuY3Rpb24gKHRoaW5nKSB7XG4gICAgcmV0dXJuIEF0b20udG9fY2hhcl9saXN0KHRoaW5nKTtcbiAgfVxufSk7XG5cbktlcm5lbC5kZWZpbXBsKENoYXJzLCBLZXJuZWwuaXNfaW50ZWdlciwge1xuICB0b19jaGFyX2xpc3Q6IGZ1bmN0aW9uICh0aGluZykge1xuICAgIHJldHVybiBJbnRlZ2VyLnRvX2NoYXJfbGlzdCh0aGluZyk7XG4gIH1cbn0pO1xuXG5LZXJuZWwuZGVmaW1wbChDaGFycywgS2VybmVsLmlzX2xpc3QsIHtcbiAgdG9fY2hhcl9saXN0OiBmdW5jdGlvbiAodGhpbmcpIHtcbiAgICByZXR1cm4gdGhpbmc7XG4gIH1cbn0pO1xuXG5sZXQgTGlzdCA9IHt9O1xuXG5MaXN0LkNoYXJzID0gQ2hhcnM7XG5cbkxpc3QuZGVsZXRlID0gZnVuY3Rpb24gKGxpc3QsIGl0ZW0pIHtcbiAgbGV0IG5ld192YWx1ZSA9IFtdO1xuICBsZXQgdmFsdWVfZm91bmQgPSBmYWxzZTtcblxuICBmb3IgKGxldCB4IG9mIGxpc3QpIHtcbiAgICBpZiAoeCA9PT0gaXRlbSAmJiB2YWx1ZV9mb3VuZCAhPT0gZmFsc2UpIHtcbiAgICAgIG5ld192YWx1ZS5wdXNoKHgpO1xuICAgICAgdmFsdWVfZm91bmQgPSB0cnVlO1xuICAgIH0gZWxzZSBpZiAoeCAhPT0gaXRlbSkge1xuICAgICAgbmV3X3ZhbHVlLnB1c2goeCk7XG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIEtlcm5lbC5TcGVjaWFsRm9ybXMubGlzdCguLi5uZXdfdmFsdWUpO1xufTtcblxuTGlzdC5kZWxldGVfYXQgPSBmdW5jdGlvbiAobGlzdCwgaW5kZXgpIHtcbiAgbGV0IG5ld192YWx1ZSA9IFtdO1xuXG4gIGZvciAobGV0IGkgPSAwOyBpIDwgbGlzdC5sZW5ndGg7IGkrKykge1xuICAgIGlmIChpICE9PSBpbmRleCkge1xuICAgICAgbmV3X3ZhbHVlLnB1c2gobGlzdFtpXSk7XG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIEtlcm5lbC5TcGVjaWFsRm9ybXMubGlzdCguLi5uZXdfdmFsdWUpO1xufTtcblxuTGlzdC5kdXBsaWNhdGUgPSBmdW5jdGlvbiAoZWxlbSwgbikge1xuICBsZXQgbmV3X3ZhbHVlID0gW107XG5cbiAgZm9yICh2YXIgaSA9IDA7IGkgPCBuOyBpKyspIHtcbiAgICBuZXdfdmFsdWUucHVzaChlbGVtKTtcbiAgfVxuXG4gIHJldHVybiBLZXJuZWwuU3BlY2lhbEZvcm1zLmxpc3QoLi4ubmV3X3ZhbHVlKTtcbn07XG5cbkxpc3QuZmlyc3QgPSBmdW5jdGlvbiAobGlzdCkge1xuICByZXR1cm4gbGlzdFswXTtcbn07XG5cbkxpc3QuZmxhdHRlbiA9IGZ1bmN0aW9uIChsaXN0LCB0YWlsID0gS2VybmVsLlNwZWNpYWxGb3Jtcy5saXN0KCkpIHtcbiAgbGV0IG5ld192YWx1ZSA9IFtdO1xuXG4gIGZvciAobGV0IHggb2YgbGlzdCkge1xuICAgIGlmIChLZXJuZWwuaXNfbGlzdCh4KSkge1xuICAgICAgbmV3X3ZhbHVlID0gbmV3X3ZhbHVlLmNvbmNhdChMaXN0LmZsYXR0ZW4oeCkpO1xuICAgIH0gZWxzZSB7XG4gICAgICBuZXdfdmFsdWUucHVzaCh4KTtcbiAgICB9XG4gIH1cblxuICBuZXdfdmFsdWUgPSBuZXdfdmFsdWUuY29uY2F0KHRhaWwpO1xuXG4gIHJldHVybiBLZXJuZWwuU3BlY2lhbEZvcm1zLmxpc3QoLi4ubmV3X3ZhbHVlKTtcbn07XG5cbkxpc3QuZm9sZGwgPSBmdW5jdGlvbiAobGlzdCwgYWNjLCBmdW5jKSB7XG4gIHJldHVybiBsaXN0LnJlZHVjZShmdW5jLCBhY2MpO1xufTtcblxuTGlzdC5mb2xkciA9IGZ1bmN0aW9uIChsaXN0LCBhY2MsIGZ1bmMpIHtcbiAgbGV0IG5ld19hY2MgPSBhY2M7XG5cbiAgZm9yICh2YXIgaSA9IGxpc3QubGVuZ3RoIC0gMTsgaSA+PSAwOyBpLS0pIHtcbiAgICBuZXdfYWNjID0gZnVuYyhsaXN0W2ldLCBuZXdfYWNjKTtcbiAgfVxuXG4gIHJldHVybiBuZXdfYWNjO1xufTtcblxuTGlzdC5pbnNlcnRfYXQgPSBmdW5jdGlvbiAobGlzdCwgaW5kZXgsIHZhbHVlKSB7XG4gIGxldCBuZXdfdmFsdWUgPSBbXTtcblxuICBmb3IgKGxldCBpID0gMDsgaSA8IGxpc3QubGVuZ3RoOyBpKyspIHtcbiAgICBpZiAoaSA9PT0gaW5kZXgpIHtcbiAgICAgIG5ld192YWx1ZS5wdXNoKHZhbHVlKTtcbiAgICAgIG5ld192YWx1ZS5wdXNoKGxpc3RbaV0pO1xuICAgIH0gZWxzZSB7XG4gICAgICBuZXdfdmFsdWUucHVzaChsaXN0W2ldKTtcbiAgICB9XG4gIH1cblxuICByZXR1cm4gS2VybmVsLlNwZWNpYWxGb3Jtcy5saXN0KC4uLm5ld192YWx1ZSk7XG59O1xuXG5MaXN0LmtleWRlbGV0ZSA9IGZ1bmN0aW9uIChsaXN0LCBrZXksIHBvc2l0aW9uKSB7XG4gIGxldCBuZXdfbGlzdCA9IFtdO1xuXG4gIGZvciAobGV0IGkgPSAwOyBpIDwgbGlzdC5sZW5ndGg7IGkrKykge1xuICAgIGlmICghS2VybmVsLm1hdGNoX19xbWFya19fKGxpc3RbaV1bcG9zaXRpb25dLCBrZXkpKSB7XG4gICAgICBuZXdfbGlzdC5wdXNoKGxpc3RbaV0pO1xuICAgIH1cbiAgfVxuXG4gIHJldHVybiBLZXJuZWwuU3BlY2lhbEZvcm1zLmxpc3QoLi4ubmV3X2xpc3QpO1xufTtcblxuTGlzdC5rZXlmaW5kID0gZnVuY3Rpb24gKGxpc3QsIGtleSwgcG9zaXRpb24sIF9kZWZhdWx0ID0gbnVsbCkge1xuXG4gIGZvciAobGV0IGkgPSAwOyBpIDwgbGlzdC5sZW5ndGg7IGkrKykge1xuICAgIGlmIChLZXJuZWwubWF0Y2hfX3FtYXJrX18obGlzdFtpXVtwb3NpdGlvbl0sIGtleSkpIHtcbiAgICAgIHJldHVybiBsaXN0W2ldO1xuICAgIH1cbiAgfVxuXG4gIHJldHVybiBfZGVmYXVsdDtcbn07XG5cbkxpc3Qua2V5bWVtYmVyX19xbWFya19fID0gZnVuY3Rpb24gKGxpc3QsIGtleSwgcG9zaXRpb24pIHtcblxuICBmb3IgKGxldCBpID0gMDsgaSA8IGxpc3QubGVuZ3RoOyBpKyspIHtcbiAgICBpZiAoS2VybmVsLm1hdGNoX19xbWFya19fKGxpc3RbaV1bcG9zaXRpb25dLCBrZXkpKSB7XG4gICAgICByZXR1cm4gdHJ1ZTtcbiAgICB9XG4gIH1cblxuICByZXR1cm4gZmFsc2U7XG59O1xuXG5MaXN0LmtleXJlcGxhY2UgPSBmdW5jdGlvbiAobGlzdCwga2V5LCBwb3NpdGlvbiwgbmV3X3R1cGxlKSB7XG4gIGxldCBuZXdfbGlzdCA9IFtdO1xuXG4gIGZvciAobGV0IGkgPSAwOyBpIDwgbGlzdC5sZW5ndGg7IGkrKykge1xuICAgIGlmICghS2VybmVsLm1hdGNoX19xbWFya19fKGxpc3RbaV1bcG9zaXRpb25dLCBrZXkpKSB7XG4gICAgICBuZXdfbGlzdC5wdXNoKGxpc3RbaV0pO1xuICAgIH0gZWxzZSB7XG4gICAgICBuZXdfbGlzdC5wdXNoKG5ld190dXBsZSk7XG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIEtlcm5lbC5TcGVjaWFsRm9ybXMubGlzdCguLi5uZXdfbGlzdCk7XG59O1xuXG5MaXN0LmtleXNvcnQgPSBmdW5jdGlvbiAobGlzdCwgcG9zaXRpb24pIHtcbiAgbGV0IG5ld19saXN0ID0gbGlzdDtcblxuICBuZXdfbGlzdC5zb3J0KGZ1bmN0aW9uIChhLCBiKSB7XG4gICAgaWYgKHBvc2l0aW9uID09PSAwKSB7XG4gICAgICBpZiAoYVtwb3NpdGlvbl0udmFsdWUgPCBiW3Bvc2l0aW9uXS52YWx1ZSkge1xuICAgICAgICByZXR1cm4gLTE7XG4gICAgICB9XG5cbiAgICAgIGlmIChhW3Bvc2l0aW9uXS52YWx1ZSA+IGJbcG9zaXRpb25dLnZhbHVlKSB7XG4gICAgICAgIHJldHVybiAxO1xuICAgICAgfVxuXG4gICAgICByZXR1cm4gMDtcbiAgICB9IGVsc2Uge1xuICAgICAgaWYgKGFbcG9zaXRpb25dIDwgYltwb3NpdGlvbl0pIHtcbiAgICAgICAgcmV0dXJuIC0xO1xuICAgICAgfVxuXG4gICAgICBpZiAoYVtwb3NpdGlvbl0gPiBiW3Bvc2l0aW9uXSkge1xuICAgICAgICByZXR1cm4gMTtcbiAgICAgIH1cblxuICAgICAgcmV0dXJuIDA7XG4gICAgfVxuICB9KTtcblxuICByZXR1cm4gS2VybmVsLlNwZWNpYWxGb3Jtcy5saXN0KC4uLm5ld19saXN0KTtcbn07XG5cbkxpc3Qua2V5c3RvcmUgPSBmdW5jdGlvbiAobGlzdCwga2V5LCBwb3NpdGlvbiwgbmV3X3R1cGxlKSB7XG4gIGxldCBuZXdfbGlzdCA9IFtdO1xuICBsZXQgcmVwbGFjZWQgPSBmYWxzZTtcblxuICBmb3IgKGxldCBpID0gMDsgaSA8IGxpc3QubGVuZ3RoOyBpKyspIHtcbiAgICBpZiAoIUtlcm5lbC5tYXRjaF9fcW1hcmtfXyhsaXN0W2ldW3Bvc2l0aW9uXSwga2V5KSkge1xuICAgICAgbmV3X2xpc3QucHVzaChsaXN0W2ldKTtcbiAgICB9IGVsc2Uge1xuICAgICAgbmV3X2xpc3QucHVzaChuZXdfdHVwbGUpO1xuICAgICAgcmVwbGFjZWQgPSB0cnVlO1xuICAgIH1cbiAgfVxuXG4gIGlmICghcmVwbGFjZWQpIHtcbiAgICBuZXdfbGlzdC5wdXNoKG5ld190dXBsZSk7XG4gIH1cblxuICByZXR1cm4gS2VybmVsLlNwZWNpYWxGb3Jtcy5saXN0KC4uLm5ld19saXN0KTtcbn07XG5cbkxpc3QubGFzdCA9IGZ1bmN0aW9uIChsaXN0KSB7XG4gIHJldHVybiBsaXN0W2xpc3QubGVuZ3RoIC0gMV07XG59O1xuXG5MaXN0LnJlcGxhY2VfYXQgPSBmdW5jdGlvbiAobGlzdCwgaW5kZXgsIHZhbHVlKSB7XG4gIGxldCBuZXdfdmFsdWUgPSBbXTtcblxuICBmb3IgKGxldCBpID0gMDsgaSA8IGxpc3QubGVuZ3RoOyBpKyspIHtcbiAgICBpZiAoaSA9PT0gaW5kZXgpIHtcbiAgICAgIG5ld192YWx1ZS5wdXNoKHZhbHVlKTtcbiAgICB9IGVsc2Uge1xuICAgICAgbmV3X3ZhbHVlLnB1c2gobGlzdFtpXSk7XG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIEtlcm5lbC5TcGVjaWFsRm9ybXMubGlzdCguLi5uZXdfdmFsdWUpO1xufTtcblxuTGlzdC51cGRhdGVfYXQgPSBmdW5jdGlvbiAobGlzdCwgaW5kZXgsIGZ1bikge1xuICBsZXQgbmV3X3ZhbHVlID0gW107XG5cbiAgZm9yIChsZXQgaSA9IDA7IGkgPCBsaXN0LmNvdW50KCk7IGkrKykge1xuICAgIGlmIChpID09PSBpbmRleCkge1xuICAgICAgbmV3X3ZhbHVlLnB1c2goZnVuKGxpc3QuZ2V0KGkpKSk7XG4gICAgfSBlbHNlIHtcbiAgICAgIG5ld192YWx1ZS5wdXNoKGxpc3QuZ2V0KGkpKTtcbiAgICB9XG4gIH1cblxuICByZXR1cm4gbmV3X3ZhbHVlO1xufTtcblxuTGlzdC53cmFwID0gZnVuY3Rpb24gKGxpc3QpIHtcbiAgaWYgKEtlcm5lbC5pc19saXN0KGxpc3QpKSB7XG4gICAgcmV0dXJuIGxpc3Q7XG4gIH0gZWxzZSBpZiAobGlzdCA9PSBudWxsKSB7XG4gICAgcmV0dXJuIEtlcm5lbC5TcGVjaWFsRm9ybXMubGlzdCgpO1xuICB9IGVsc2Uge1xuICAgIHJldHVybiBLZXJuZWwuU3BlY2lhbEZvcm1zLmxpc3QobGlzdCk7XG4gIH1cbn07XG5cbkxpc3QuemlwID0gZnVuY3Rpb24gKGxpc3Rfb2ZfbGlzdHMpIHtcbiAgaWYgKGxpc3Rfb2ZfbGlzdHMubGVuZ3RoID09PSAwKSB7XG4gICAgcmV0dXJuIEtlcm5lbC5TcGVjaWFsRm9ybXMubGlzdCgpO1xuICB9XG5cbiAgbGV0IG5ld192YWx1ZSA9IFtdO1xuICBsZXQgc21hbGxlc3RfbGVuZ3RoID0gbGlzdF9vZl9saXN0c1swXTtcblxuICBmb3IgKGxldCB4IG9mIGxpc3Rfb2ZfbGlzdHMpIHtcbiAgICBpZiAoeC5sZW5ndGggPCBzbWFsbGVzdF9sZW5ndGgpIHtcbiAgICAgIHNtYWxsZXN0X2xlbmd0aCA9IHgubGVuZ3RoO1xuICAgIH1cbiAgfVxuXG4gIGZvciAobGV0IGkgPSAwOyBpIDwgc21hbGxlc3RfbGVuZ3RoOyBpKyspIHtcbiAgICBsZXQgY3VycmVudF92YWx1ZSA9IFtdO1xuICAgIGZvciAobGV0IGogPSAwOyBqIDwgbGlzdF9vZl9saXN0cy5sZW5ndGg7IGorKykge1xuICAgICAgY3VycmVudF92YWx1ZS5wdXNoKGxpc3Rfb2ZfbGlzdHNbal1baV0pO1xuICAgIH1cblxuICAgIG5ld192YWx1ZS5wdXNoKEtlcm5lbC5TcGVjaWFsRm9ybXMudHVwbGUoLi4uY3VycmVudF92YWx1ZSkpO1xuICB9XG5cbiAgcmV0dXJuIEtlcm5lbC5TcGVjaWFsRm9ybXMubGlzdCguLi5uZXdfdmFsdWUpO1xufTtcblxuTGlzdC50b190dXBsZSA9IGZ1bmN0aW9uIChsaXN0KSB7XG4gIHJldHVybiBLZXJuZWwuU3BlY2lhbEZvcm1zLnR1cGxlLmFwcGx5KG51bGwsIGxpc3QpO1xufTtcblxuTGlzdC5hcHBlbmQgPSBmdW5jdGlvbiAobGlzdCwgdmFsdWUpIHtcbiAgcmV0dXJuIEtlcm5lbC5TcGVjaWFsRm9ybXMubGlzdCguLi5saXN0LmNvbmNhdChbdmFsdWVdKSk7XG59O1xuXG5MaXN0LnByZXBlbmQgPSBmdW5jdGlvbiAobGlzdCwgdmFsdWUpIHtcbiAgcmV0dXJuIEtlcm5lbC5TcGVjaWFsRm9ybXMubGlzdCguLi5bdmFsdWVdLmNvbmNhdChsaXN0KSk7XG59O1xuXG5MaXN0LmNvbmNhdCA9IGZ1bmN0aW9uIChsZWZ0LCByaWdodCkge1xuICByZXR1cm4gbGVmdC5jb25jYXQocmlnaHQpO1xufTtcblxuY2xhc3MgU2lnbmFsIHtcblxuICBjb25zdHJ1Y3RvcigpIHtcbiAgICB0aGlzLmJpbmRpbmdzID0gU3BlY2lhbEZvcm1zLmxpc3QoKTtcbiAgfVxuXG4gIGFkZChsaXN0ZW5lciwgY29udGV4dCA9IHRoaXMpIHtcbiAgICB0aGlzLmJpbmRpbmdzID0gTGlzdC5hcHBlbmQodGhpcy5iaW5kaW5ncywgbmV3IFNpZ25hbEJpbmRpbmcodGhpcywgbGlzdGVuZXIsIGNvbnRleHQpKTtcbiAgfVxuXG4gIHJlbW92ZShsaXN0ZW5lcikge1xuICAgIHRoaXMuYmluZGluZ3MgPSBFbnVtLmZpbHRlcih0aGlzLmJpbmRpbmdzLCBmdW5jdGlvbiAoYmluZGluZykge1xuICAgICAgcmV0dXJuIGJpbmRpbmcubGlzdGVuZXIgIT09IGxpc3RlbmVyO1xuICAgIH0pO1xuICB9XG5cbiAgZGlzcGF0Y2goLi4ucGFyYW1zKSB7XG4gICAgZm9yIChsZXQgYmluZGluZyBvZiB0aGlzLmJpbmRpbmdzKSB7XG4gICAgICBiaW5kaW5nLmV4ZWN1dGUoLi4ucGFyYW1zKTtcbiAgICB9XG4gIH1cblxuICBkaXNwb3NlKCkge1xuICAgIGZvciAobGV0IGJpbmRpbmcgb2YgdGhpcy5iaW5kaW5ncykge1xuICAgICAgYmluZGluZy5kaXNwb3NlKCk7XG4gICAgfVxuXG4gICAgdGhpcy5iaW5kaW5ncyA9IG51bGw7XG4gIH1cbn1cblxuY2xhc3MgU2lnbmFsQmluZGluZyB7XG5cbiAgY29uc3RydWN0b3Ioc2lnbmFsLCBsaXN0ZW5lciwgY29udGV4dCkge1xuICAgIHRoaXMubGlzdGVuZXIgPSBsaXN0ZW5lcjtcbiAgICB0aGlzLnNpZ25hbCA9IHNpZ25hbDtcbiAgICB0aGlzLmNvbnRleHQgPSBjb250ZXh0O1xuICB9XG5cbiAgZXhlY3V0ZSguLi5wYXJhbXMpIHtcbiAgICB0aGlzLmxpc3RlbmVyLmFwcGx5KHRoaXMuY29udGV4dCwgcGFyYW1zKTtcbiAgfVxuXG4gIGRpc3Bvc2UoKSB7XG4gICAgdGhpcy5saXN0ZW5lciA9IG51bGw7XG4gICAgdGhpcy5zaWduYWwgPSBudWxsO1xuICAgIHRoaXMuY29udGV4dCA9IG51bGw7XG4gIH1cbn1cblxuZnVuY3Rpb24gX191cGRhdGUobWFwLCBrZXksIHZhbHVlKSB7XG4gIGxldCBtID0gbmV3IE1hcChtYXApO1xuICBtLnNldChrZXksIHZhbHVlKTtcbiAgcmV0dXJuIG07XG59XG5cbmZ1bmN0aW9uIHJlbW92ZShtYXAsIGtleSkge1xuICBsZXQgbSA9IG5ldyBNYXAobWFwKTtcbiAgbS5kZWxldGUoa2V5KTtcbiAgcmV0dXJuIG07XG59XG5cbmNsYXNzIE1haWxCb3gge1xuXG4gIGNvbnN0cnVjdG9yKGNvbnRleHQgPSB0aGlzKSB7XG4gICAgdGhpcy5zaWduYWwgPSBuZXcgU2lnbmFsKCk7XG4gICAgdGhpcy5zaWduYWwuYWRkKCguLi5wYXJhbXMpID0+IHRoaXMubWVzc2FnZXMgPSB0aGlzLm1lc3NhZ2VzLmNvbmNhdChwYXJhbXMpLCBjb250ZXh0KTtcbiAgICB0aGlzLm1lc3NhZ2VzID0gW107XG4gIH1cblxuICByZWNlaXZlKC4uLm1lc3NhZ2VzKSB7XG4gICAgdGhpcy5zaWduYWwuZGlzcGF0Y2goLi4ubWVzc2FnZXMpO1xuICB9XG5cbiAgcGVlaygpIHtcbiAgICBpZiAodGhpcy5tZXNzYWdlcy5sZW5ndGggPT09IDApIHtcbiAgICAgIHJldHVybiBudWxsO1xuICAgIH1cblxuICAgIHJldHVybiB0aGlzLm1lc3NhZ2VzWzBdO1xuICB9XG5cbiAgcmVhZCgpIHtcbiAgICBsZXQgcmVzdWx0ID0gdGhpcy5tZXNzYWdlc1swXTtcbiAgICB0aGlzLm1lc3NhZ2VzID0gdGhpcy5tZXNzYWdlcy5zbGljZSgxKTtcblxuICAgIHJldHVybiByZXN1bHQ7XG4gIH1cblxuICBhZGRfc3Vic2NyaWJlcihmbiwgY29udGV4dCA9IHRoaXMpIHtcbiAgICB0aGlzLnNpZ25hbC5hZGQoZm4sIGNvbnRleHQpO1xuICB9XG5cbiAgcmVtb3ZlX3N1YnNjcmliZXIoZm4pIHtcbiAgICB0aGlzLnNpZ25hbC5yZW1vdmUoZm4pO1xuICB9XG5cbiAgZGlzcG9zZSgpIHtcbiAgICB0aGlzLnNpZ25hbC5kaXNwb3NlKCk7XG4gICAgdGhpcy5tZXNzYWdlcyA9IG51bGw7XG4gIH1cbn1cblxuY2xhc3MgUG9zdE9mZmljZSB7XG5cbiAgY29uc3RydWN0b3IoKSB7XG4gICAgdGhpcy5tYWlsYm94ZXMgPSBuZXcgTWFwKCk7XG4gIH1cblxuICBzZW5kKGFkZHJlc3MsIG1lc3NhZ2UpIHtcbiAgICB0aGlzLm1haWxib3hlcy5nZXQoYWRkcmVzcykucmVjZWl2ZShtZXNzYWdlKTtcbiAgfVxuXG4gIHJlY2VpdmUoYWRkcmVzcykge1xuICAgIHJldHVybiB0aGlzLm1haWxib3hlcy5nZXQoYWRkcmVzcykucmVhZCgpO1xuICB9XG5cbiAgcGVlayhhZGRyZXNzKSB7XG4gICAgcmV0dXJuIHRoaXMubWFpbGJveGVzLmdldChhZGRyZXNzKS5wZWVrKCk7XG4gIH1cblxuICBhZGRfbWFpbGJveChhZGRyZXNzID0gU3ltYm9sKCksIGNvbnRleHQgPSB0aGlzKSB7XG4gICAgdGhpcy5tYWlsYm94ZXMgPSBfX3VwZGF0ZSh0aGlzLm1haWxib3hlcywgYWRkcmVzcywgbmV3IE1haWxCb3goKSk7XG4gICAgcmV0dXJuIGFkZHJlc3M7XG4gIH1cblxuICByZW1vdmVfbWFpbGJveChhZGRyZXNzKSB7XG4gICAgdGhpcy5tYWlsYm94ZXMuZ2V0KGFkZHJlc3MpLmRpc3Bvc2UoKTtcbiAgICB0aGlzLm1haWxib3hlcyA9IHJlbW92ZSh0aGlzLm1haWxib3hlcywgYWRkcmVzcyk7XG4gIH1cblxuICBzdWJzY3JpYmUoYWRkcmVzcywgc3Vic2NyaWJ0aW9uX2ZuLCBjb250ZXh0ID0gdGhpcykge1xuICAgIHRoaXMubWFpbGJveGVzLmdldChhZGRyZXNzKS5hZGRfc3Vic2NyaWJlcihzdWJzY3JpYnRpb25fZm4sIGNvbnRleHQpO1xuICB9XG5cbiAgdW5zdWJzY3JpYmUoYWRkcmVzcywgc3Vic2NyaWJ0aW9uX2ZuKSB7XG4gICAgdGhpcy5tYWlsYm94ZXMuZ2V0KGFkZHJlc3MpLnJlbW92ZV9zdWJzY3JpYmVyKHN1YnNjcmlidGlvbl9mbik7XG4gIH1cbn1cblxuZnVuY3Rpb24gY2FsbF9wcm9wZXJ0eShpdGVtLCBwcm9wZXJ0eSkge1xuICBpZiAocHJvcGVydHkgaW4gaXRlbSkge1xuICAgIGl0ZW1bcHJvcGVydHldO1xuICAgIGlmIChpdGVtW3Byb3BlcnR5XSBpbnN0YW5jZW9mIEZ1bmN0aW9uKSB7XG4gICAgICByZXR1cm4gaXRlbVtwcm9wZXJ0eV0oKTtcbiAgICB9IGVsc2Uge1xuICAgICAgcmV0dXJuIGl0ZW1bcHJvcGVydHldO1xuICAgIH1cbiAgfSBlbHNlIGlmIChTeW1ib2wuZm9yKHByb3BlcnR5KSBpbiBpdGVtKSB7XG4gICAgbGV0IHByb3AgPSBTeW1ib2wuZm9yKHByb3BlcnR5KTtcbiAgICBpZiAoaXRlbVtwcm9wXSBpbnN0YW5jZW9mIEZ1bmN0aW9uKSB7XG4gICAgICByZXR1cm4gaXRlbVtwcm9wXSgpO1xuICAgIH0gZWxzZSB7XG4gICAgICByZXR1cm4gaXRlbVtwcm9wXTtcbiAgICB9XG4gIH1cblxuICB0aHJvdyBuZXcgRXJyb3IoYFByb3BlcnR5ICR7IHByb3BlcnR5IH0gbm90IGZvdW5kIGluICR7IGl0ZW0gfWApO1xufVxuXG52YXIgSlMgPSB7XG4gIGNhbGxfcHJvcGVydHlcbn07XG5cbmxldCBSYW5nZSA9IGZ1bmN0aW9uIChfZmlyc3QsIF9sYXN0KSB7XG4gIGlmICghKHRoaXMgaW5zdGFuY2VvZiBSYW5nZSkpIHtcbiAgICByZXR1cm4gbmV3IFJhbmdlKF9maXJzdCwgX2xhc3QpO1xuICB9XG5cbiAgdGhpcy5maXJzdCA9IGZ1bmN0aW9uICgpIHtcbiAgICByZXR1cm4gX2ZpcnN0O1xuICB9O1xuXG4gIHRoaXMubGFzdCA9IGZ1bmN0aW9uICgpIHtcbiAgICByZXR1cm4gX2xhc3Q7XG4gIH07XG5cbiAgbGV0IF9yYW5nZSA9IFtdO1xuXG4gIGZvciAobGV0IGkgPSBfZmlyc3Q7IGkgPD0gX2xhc3Q7IGkrKykge1xuICAgIF9yYW5nZS5wdXNoKGkpO1xuICB9XG5cbiAgX3JhbmdlID0gT2JqZWN0LmZyZWV6ZShfcmFuZ2UpO1xuXG4gIHRoaXMudmFsdWUgPSBmdW5jdGlvbiAoKSB7XG4gICAgcmV0dXJuIF9yYW5nZTtcbiAgfTtcblxuICB0aGlzLmxlbmd0aCA9IGZ1bmN0aW9uICgpIHtcbiAgICByZXR1cm4gX3JhbmdlLmxlbmd0aDtcbiAgfTtcblxuICByZXR1cm4gdGhpcztcbn07XG5cblJhbmdlLnByb3RvdHlwZVtTeW1ib2wuaXRlcmF0b3JdID0gZnVuY3Rpb24gKCkge1xuICByZXR1cm4gdGhpcy52YWx1ZSgpW1N5bWJvbC5pdGVyYXRvcl0oKTtcbn07XG5cblJhbmdlLm5ldyA9IGZ1bmN0aW9uIChmaXJzdCwgbGFzdCkge1xuICByZXR1cm4gUmFuZ2UoZmlyc3QsIGxhc3QpO1xufTtcblxuUmFuZ2UucmFuZ2VfX3FtYXJrX18gPSBmdW5jdGlvbiAocmFuZ2UpIHtcbiAgcmV0dXJuIHJhbmdlIGluc3RhbmNlb2YgUmFuZ2U7XG59O1xuXG5sZXQgS2V5d29yZCA9IHt9O1xuXG5LZXl3b3JkLmhhc19rZXlfX3FtX18gPSBmdW5jdGlvbiAoa2V5d29yZHMsIGtleSkge1xuICBmb3IgKGxldCBrZXl3b3JkIG9mIGtleXdvcmRzKSB7XG4gICAgaWYgKEtlcm5lbC5lbGVtKGtleXdvcmQsIDApID09IGtleSkge1xuICAgICAgcmV0dXJuIHRydWU7XG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIGZhbHNlO1xufTtcblxuS2V5d29yZC5nZXQgPSBmdW5jdGlvbiAoa2V5d29yZHMsIGtleSwgdGhlX2RlZmF1bHQgPSBudWxsKSB7XG4gIGZvciAobGV0IGtleXdvcmQgb2Yga2V5d29yZHMpIHtcbiAgICBpZiAoS2VybmVsLmVsZW0oa2V5d29yZCwgMCkgPT0ga2V5KSB7XG4gICAgICByZXR1cm4gS2VybmVsLmVsZW0oa2V5d29yZCwgMSk7XG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIHRoZV9kZWZhdWx0O1xufTtcblxubGV0IEFnZW50ID0ge307XG5cbkFnZW50LnN0YXJ0ID0gZnVuY3Rpb24gKGZ1biwgb3B0aW9ucyA9IFtdKSB7XG4gIGNvbnN0IG5hbWUgPSBLZXl3b3JkLmhhc19rZXlfX3FtX18ob3B0aW9ucywgS2VybmVsLlNwZWNpYWxGb3Jtcy5hdG9tKCduYW1lJykpID8gS2V5d29yZC5nZXQob3B0aW9ucywgS2VybmVsLlNwZWNpYWxGb3Jtcy5hdG9tKCduYW1lJykpIDogU3ltYm9sKCk7XG5cbiAgc2VsZi5wb3N0X29mZmljZS5hZGRfbWFpbGJveChuYW1lKTtcbiAgc2VsZi5wb3N0X29mZmljZS5zZW5kKG5hbWUsIGZ1bigpKTtcblxuICByZXR1cm4gS2VybmVsLlNwZWNpYWxGb3Jtcy50dXBsZShLZXJuZWwuU3BlY2lhbEZvcm1zLmF0b20oJ29rJyksIG5hbWUpO1xufTtcblxuQWdlbnQuc3RvcCA9IGZ1bmN0aW9uIChhZ2VudCwgdGltZW91dCA9IDUwMDApIHtcbiAgc2VsZi5wb3N0X29mZmljZS5yZW1vdmVfbWFpbGJveChhZ2VudCk7XG4gIHJldHVybiBLZXJuZWwuU3BlY2lhbEZvcm1zLmF0b20oJ29rJyk7XG59O1xuXG5BZ2VudC51cGRhdGUgPSBmdW5jdGlvbiAoYWdlbnQsIGZ1biwgdGltZW91dCA9IDUwMDApIHtcblxuICBjb25zdCBjdXJyZW50X3N0YXRlID0gc2VsZi5wb3N0X29mZmljZS5yZWNlaXZlKGFnZW50KTtcbiAgc2VsZi5wb3N0X29mZmljZS5zZW5kKGFnZW50LCBmdW4oY3VycmVudF9zdGF0ZSkpO1xuXG4gIHJldHVybiBLZXJuZWwuU3BlY2lhbEZvcm1zLmF0b20oJ29rJyk7XG59O1xuXG5BZ2VudC5nZXQgPSBmdW5jdGlvbiAoYWdlbnQsIGZ1biwgdGltZW91dCA9IDUwMDApIHtcbiAgcmV0dXJuIGZ1bihzZWxmLnBvc3Rfb2ZmaWNlLnBlZWsoYWdlbnQpKTtcbn07XG5cbkFnZW50LmdldF9hbmRfdXBkYXRlID0gZnVuY3Rpb24gKGFnZW50LCBmdW4sIHRpbWVvdXQgPSA1MDAwKSB7XG5cbiAgY29uc3QgZ2V0X2FuZF91cGRhdGVfdHVwbGUgPSBmdW4oc2VsZi5wb3N0X29mZmljZS5yZWNlaXZlKGFnZW50KSk7XG4gIHNlbGYucG9zdF9vZmZpY2Uuc2VuZChhZ2VudCwgS2VybmVsLmVsZW0oZ2V0X2FuZF91cGRhdGVfdHVwbGUsIDEpKTtcblxuICByZXR1cm4gS2VybmVsLmVsZW0oZ2V0X2FuZF91cGRhdGVfdHVwbGUsIDApO1xufTtcblxuLy9odHRwczovL2RldmVsb3Blci5tb3ppbGxhLm9yZy9lbi1VUy9kb2NzL1dlYi9BUEkvV2luZG93QmFzZTY0L0Jhc2U2NF9lbmNvZGluZ19hbmRfZGVjb2RpbmcjU29sdXRpb25fMl8lRTIlODAlOTNfcmV3cml0ZV90aGVfRE9Nc19hdG9iKClfYW5kX2J0b2EoKV91c2luZ19KYXZhU2NyaXB0J3NfVHlwZWRBcnJheXNfYW5kX1VURi04XG5mdW5jdGlvbiBiNjRFbmNvZGVVbmljb2RlKHN0cikge1xuICByZXR1cm4gYnRvYShlbmNvZGVVUklDb21wb25lbnQoc3RyKS5yZXBsYWNlKC8lKFswLTlBLUZdezJ9KS9nLCBmdW5jdGlvbiAobWF0Y2gsIHAxKSB7XG4gICAgcmV0dXJuIFN0cmluZy5mcm9tQ2hhckNvZGUoJzB4JyArIHAxKTtcbiAgfSkpO1xufVxuXG5mdW5jdGlvbiBlbmNvZGU2NChkYXRhKSB7XG4gIHJldHVybiBiNjRFbmNvZGVVbmljb2RlKGRhdGEpO1xufVxuXG5mdW5jdGlvbiBkZWNvZGU2NChkYXRhKSB7XG4gIHRyeSB7XG4gICAgcmV0dXJuIEtlcm5lbC5TcGVjaWFsRm9ybXMudHVwbGUoS2VybmVsLlNwZWNpYWxGb3Jtcy5hdG9tKCdvaycpLCBhdG9iKGRhdGEpKTtcbiAgfSBjYXRjaCAoZSkge1xuICAgIHJldHVybiBLZXJuZWwuU3BlY2lhbEZvcm1zLmF0b20oJ2Vycm9yJyk7XG4gIH1cbiAgcmV0dXJuIGJ0b2EoZGF0YSk7XG59XG5cbmZ1bmN0aW9uIGRlY29kZTY0X19lbV9fKGRhdGEpIHtcbiAgcmV0dXJuIGF0b2IoZGF0YSk7XG59XG5cbnZhciBCYXNlID0ge1xuICBlbmNvZGU2NCxcbiAgZGVjb2RlNjQsXG4gIGRlY29kZTY0X19lbV9fXG59O1xuXG5mdW5jdGlvbiBibm90KGV4cHIpIHtcbiAgcmV0dXJuIH5leHByO1xufVxuXG5mdW5jdGlvbiBiYW5kKGxlZnQsIHJpZ2h0KSB7XG4gIHJldHVybiBsZWZ0ICYgcmlnaHQ7XG59XG5cbmZ1bmN0aW9uIGJvcihsZWZ0LCByaWdodCkge1xuICByZXR1cm4gbGVmdCB8IHJpZ2h0O1xufVxuXG5mdW5jdGlvbiBic2wobGVmdCwgcmlnaHQpIHtcbiAgcmV0dXJuIGxlZnQgPDwgcmlnaHQ7XG59XG5cbmZ1bmN0aW9uIGJzcihsZWZ0LCByaWdodCkge1xuICByZXR1cm4gbGVmdCA+PiByaWdodDtcbn1cblxuZnVuY3Rpb24gYnhvcihsZWZ0LCByaWdodCkge1xuICByZXR1cm4gbGVmdCBeIHJpZ2h0O1xufVxuXG52YXIgQml0d2lzZSA9IHtcbiAgYm5vdCxcbiAgYmFuZCxcbiAgYm9yLFxuICBic2wsXG4gIGJzcixcbiAgYnhvclxufTtcblxubGV0IEVudW1lcmFibGUgPSBLZXJuZWwuZGVmcHJvdG9jb2woe1xuICBjb3VudDogZnVuY3Rpb24gKGNvbGxlY3Rpb24pIHt9LFxuICBtZW1iZXJfcW1hcmtfXzogZnVuY3Rpb24gKGNvbGxlY3Rpb24sIHZhbHVlKSB7fSxcbiAgcmVkdWNlOiBmdW5jdGlvbiAoY29sbGVjdGlvbiwgYWNjLCBmdW4pIHt9XG59KTtcblxubGV0IENvbGxlY3RhYmxlID0gS2VybmVsLmRlZnByb3RvY29sKHtcbiAgaW50bzogZnVuY3Rpb24gKGNvbGxlY3RhYmxlKSB7fVxufSk7XG5cbmxldCBJbnNwZWN0ID0gS2VybmVsLmRlZnByb3RvY29sKHtcbiAgaW5zcGVjdDogZnVuY3Rpb24gKHRoaW5nLCBvcHRzKSB7fVxufSk7XG5cbmZ1bmN0aW9uIF9fX25ld19fKCkge1xuICByZXR1cm4gU3BlY2lhbEZvcm1zLm1hcCh7fSk7XG59XG5cbmZ1bmN0aW9uIGtleXMobWFwKSB7XG4gIHJldHVybiBPYmplY3Qua2V5cyhtYXApO1xufVxuXG5mdW5jdGlvbiBfX3NpemUobWFwKSB7XG4gIHJldHVybiBrZXlzKG1hcCkubGVuZ3RoO1xufVxuXG5mdW5jdGlvbiBfX3RvX2xpc3QobWFwKSB7XG4gIGxldCBtYXBfa2V5cyA9IGtleXMobWFwKTtcbiAgbGV0IGxpc3QgPSBbXTtcblxuICBmb3IgKGxldCBrZXkgb2YgbWFwX2tleXMpIHtcbiAgICBsaXN0LnB1c2goU3BlY2lhbEZvcm1zLnR1cGxlKGtleSwgbWFwW2tleV0pKTtcbiAgfVxuXG4gIHJldHVybiBTcGVjaWFsRm9ybXMubGlzdCguLi5saXN0KTtcbn1cblxuZnVuY3Rpb24gdmFsdWVzKG1hcCkge1xuICBsZXQgbWFwX2tleXMgPSBrZXlzKG1hcCk7XG4gIGxldCBsaXN0ID0gW107XG5cbiAgZm9yIChsZXQga2V5IG9mIG1hcF9rZXlzKSB7XG4gICAgbGlzdC5wdXNoKG1hcFtrZXldKTtcbiAgfVxuXG4gIHJldHVybiBTcGVjaWFsRm9ybXMubGlzdCguLi5saXN0KTtcbn1cblxuZnVuY3Rpb24gZnJvbV9zdHJ1Y3Qoc3RydWN0KSB7XG4gIGxldCBtYXAgPSBPYmplY3QuYXNzaWduKHt9LCBzdHJ1Y3QpO1xuICBkZWxldGUgbWFwW1N5bWJvbC5mb3IoXCJfX3N0cnVjdF9fXCIpXTtcblxuICByZXR1cm4gU3BlY2lhbEZvcm1zLm1hcChtYXApO1xufVxuXG5mdW5jdGlvbiBfX19fZGVsZXRlX18obWFwLCBrZXkpIHtcbiAgbGV0IG5ld19tYXAgPSBPYmplY3QuYXNzaWduKHt9LCBtYXApO1xuXG4gIGRlbGV0ZSBuZXdfbWFwW2tleV07XG5cbiAgcmV0dXJuIFNwZWNpYWxGb3Jtcy5tYXAobmV3X21hcCk7XG59XG5cbmZ1bmN0aW9uIGRyb3AobWFwLCBrZXlzKSB7XG4gIGxldCBuZXdfbWFwID0gT2JqZWN0LmFzc2lnbih7fSwgbWFwKTtcblxuICBmb3IgKGxldCBrZXkgb2Yga2V5cykge1xuICAgIGRlbGV0ZSBuZXdfbWFwW2tleV07XG4gIH1cblxuICByZXR1cm4gU3BlY2lhbEZvcm1zLm1hcChuZXdfbWFwKTtcbn1cblxuZnVuY3Rpb24gX19lcXVhbF9fcW1hcmtfXyhtYXAxLCBtYXAyKSB7XG4gIHJldHVybiBtYXAxID09PSBtYXAyO1xufVxuXG5mdW5jdGlvbiBmZXRjaF9fZW1hcmtfXyhtYXAsIGtleSkge1xuICBpZiAoa2V5IGluIG1hcCkge1xuICAgIHJldHVybiBtYXBba2V5XTtcbiAgfVxuXG4gIHRocm93IG5ldyBFcnJvcihcIktleSBub3QgZm91bmQuXCIpO1xufVxuXG5mdW5jdGlvbiBmZXRjaChtYXAsIGtleSkge1xuICBpZiAoa2V5IGluIG1hcCkge1xuICAgIHJldHVybiBTcGVjaWFsRm9ybXMudHVwbGUoU3BlY2lhbEZvcm1zLmF0b20oXCJva1wiKSwgbWFwW2tleV0pO1xuICB9XG5cbiAgcmV0dXJuIFNwZWNpYWxGb3Jtcy5hdG9tKFwiZXJyb3JcIik7XG59XG5cbmZ1bmN0aW9uIGhhc19rZXlfX3FtYXJrX18obWFwLCBrZXkpIHtcbiAgcmV0dXJuIGtleSBpbiBtYXA7XG59XG5cbmZ1bmN0aW9uIG1lcmdlKG1hcDEsIG1hcDIpIHtcbiAgcmV0dXJuIFNwZWNpYWxGb3Jtcy5tYXBfdXBkYXRlKG1hcDEsIG1hcDIpO1xufVxuXG5mdW5jdGlvbiBzcGxpdChtYXAsIGtleXMpIHtcbiAgbGV0IHNwbGl0MSA9IHt9O1xuICBsZXQgc3BsaXQyID0ge307XG5cbiAgZm9yIChsZXQga2V5IG9mIE9iamVjdC5rZXlzKG1hcCkpIHtcbiAgICBpZiAoa2V5cy5pbmRleE9mKGtleSkgPiAtMSkge1xuICAgICAgc3BsaXQxW2tleV0gPSBtYXBba2V5XTtcbiAgICB9IGVsc2Uge1xuICAgICAgc3BsaXQyW2tleV0gPSBtYXBba2V5XTtcbiAgICB9XG4gIH1cblxuICByZXR1cm4gU3BlY2lhbEZvcm1zLnR1cGxlKFNwZWNpYWxGb3Jtcy5tYXAoc3BsaXQxKSwgU3BlY2lhbEZvcm1zLm1hcChzcGxpdDIpKTtcbn1cblxuZnVuY3Rpb24gdGFrZShtYXAsIGtleXMpIHtcbiAgbGV0IHNwbGl0MSA9IHt9O1xuXG4gIGZvciAobGV0IGtleSBvZiBPYmplY3Qua2V5cyhtYXApKSB7XG4gICAgaWYgKGtleXMuaW5kZXhPZihrZXkpID4gLTEpIHtcbiAgICAgIHNwbGl0MVtrZXldID0gbWFwW2tleV07XG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIFNwZWNpYWxGb3Jtcy5tYXAoc3BsaXQxKTtcbn1cblxuZnVuY3Rpb24gZHJvcChtYXAsIGtleXMpIHtcbiAgbGV0IHNwbGl0MSA9IHt9O1xuXG4gIGZvciAobGV0IGtleSBvZiBPYmplY3Qua2V5cyhtYXApKSB7XG4gICAgaWYgKGtleXMuaW5kZXhPZihrZXkpID09PSAtMSkge1xuICAgICAgc3BsaXQxW2tleV0gPSBtYXBba2V5XTtcbiAgICB9XG4gIH1cblxuICByZXR1cm4gU3BlY2lhbEZvcm1zLm1hcChzcGxpdDEpO1xufVxuXG5mdW5jdGlvbiBwdXRfbmV3KG1hcCwga2V5LCB2YWx1ZSkge1xuICBpZiAoa2V5IGluIG1hcCkge1xuICAgIHJldHVybiBtYXA7XG4gIH1cblxuICBsZXQgbmV3X21hcCA9IE9iamVjdC5hc3NpZ24oe30sIG1hcCk7XG4gIG5ld19tYXBba2V5XSA9IHZhbHVlO1xuXG4gIHJldHVybiBTcGVjaWFsRm9ybXMubWFwKG5ld19tYXApO1xufVxuXG5mdW5jdGlvbiBwdXRfbmV3X2xhenkobWFwLCBrZXksIGZ1bikge1xuICBpZiAoa2V5IGluIG1hcCkge1xuICAgIHJldHVybiBtYXA7XG4gIH1cblxuICBsZXQgbmV3X21hcCA9IE9iamVjdC5hc3NpZ24oe30sIG1hcCk7XG4gIG5ld19tYXBba2V5XSA9IGZ1bigpO1xuXG4gIHJldHVybiBTcGVjaWFsRm9ybXMubWFwKG5ld19tYXApO1xufVxuXG5mdW5jdGlvbiBnZXRfYW5kX3VwZGF0ZShtYXAsIGtleSwgZnVuKSB7XG4gIGlmIChrZXkgaW4gbWFwKSB7XG4gICAgcmV0dXJuIG1hcDtcbiAgfVxuXG4gIGxldCBuZXdfbWFwID0gT2JqZWN0LmFzc2lnbih7fSwgbWFwKTtcbiAgbmV3X21hcFtrZXldID0gZnVuKG1hcFtrZXldKTtcblxuICByZXR1cm4gU3BlY2lhbEZvcm1zLm1hcChuZXdfbWFwKTtcbn1cblxuZnVuY3Rpb24gcG9wX2xhenkobWFwLCBrZXksIGZ1bikge1xuICBpZiAoIWtleSBpbiBtYXApIHtcbiAgICByZXR1cm4gU3BlY2lhbEZvcm1zLnR1cGxlKGZ1bigpLCBtYXApO1xuICB9XG5cbiAgbGV0IG5ld19tYXAgPSBPYmplY3QuYXNzaWduKHt9LCBtYXApO1xuICBsZXQgdmFsdWUgPSBmdW4obmV3X21hcFtrZXldKTtcbiAgZGVsZXRlIG5ld19tYXBba2V5XTtcblxuICByZXR1cm4gU3BlY2lhbEZvcm1zLnR1cGxlKHZhbHVlLCBuZXdfbWFwKTtcbn1cblxuZnVuY3Rpb24gcG9wKG1hcCwga2V5LCBfZGVmYXVsdCA9IG51bGwpIHtcbiAgaWYgKCFrZXkgaW4gbWFwKSB7XG4gICAgcmV0dXJuIFNwZWNpYWxGb3Jtcy50dXBsZShfZGVmYXVsdCwgbWFwKTtcbiAgfVxuXG4gIGxldCBuZXdfbWFwID0gT2JqZWN0LmFzc2lnbih7fSwgbWFwKTtcbiAgbGV0IHZhbHVlID0gbmV3X21hcFtrZXldO1xuICBkZWxldGUgbmV3X21hcFtrZXldO1xuXG4gIHJldHVybiBTcGVjaWFsRm9ybXMudHVwbGUodmFsdWUsIG5ld19tYXApO1xufVxuXG5mdW5jdGlvbiBnZXRfbGF6eShtYXAsIGtleSwgZnVuKSB7XG4gIGlmICgha2V5IGluIG1hcCkge1xuICAgIHJldHVybiBmdW4oKTtcbiAgfVxuXG4gIHJldHVybiBmdW4obWFwW2tleV0pO1xufVxuXG5mdW5jdGlvbiBnZXQobWFwLCBrZXksIF9kZWZhdWx0ID0gbnVsbCkge1xuICBpZiAoIWtleSBpbiBtYXApIHtcbiAgICByZXR1cm4gX2RlZmF1bHQ7XG4gIH1cblxuICByZXR1cm4gbWFwW2tleV07XG59XG5cbmZ1bmN0aW9uIF9fcHV0KG1hcCwga2V5LCB2YWwpIHtcbiAgbGV0IG5ld19tYXAgPSBPYmplY3Qoe30sIG1hcCk7XG4gIG5ld19tYXBba2V5XSA9IHZhbDtcblxuICByZXR1cm4gU3BlY2lhbEZvcm1zLm1hcChuZXdfbWFwKTtcbn1cblxuZnVuY3Rpb24gdXBkYXRlX19lbWFya19fKG1hcCwga2V5LCBmdW4pIHtcbiAgaWYgKCFrZXkgaW4gbWFwKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKFwiS2V5IG5vdCBmb3VuZFwiKTtcbiAgfVxuXG4gIGxldCBuZXdfbWFwID0gT2JqZWN0KHt9LCBtYXApO1xuICBuZXdfbWFwW2tleV0gPSBmdW4obWFwW2tleV0pO1xuXG4gIHJldHVybiBTcGVjaWFsRm9ybXMubWFwKG5ld19tYXApO1xufVxuXG5mdW5jdGlvbiBfdXBkYXRlKG1hcCwga2V5LCBpbml0aWFsLCBmdW4pIHtcbiAgbGV0IG5ld19tYXAgPSBPYmplY3Qoe30sIG1hcCk7XG5cbiAgaWYgKCFrZXkgaW4gbWFwKSB7XG4gICAgbmV3X21hcFtrZXldID0gaW5pdGlhbDtcbiAgfSBlbHNlIHtcbiAgICBuZXdfbWFwW2tleV0gPSBmdW4obWFwW2tleV0pO1xuICB9XG5cbiAgcmV0dXJuIFNwZWNpYWxGb3Jtcy5tYXAobmV3X21hcCk7XG59XG5cbnZhciBfTWFwID0ge1xuICBuZXc6IF9fX25ld19fLFxuICBrZXlzLFxuICBzaXplOiBfX3NpemUsXG4gIHRvX2xpc3Q6IF9fdG9fbGlzdCxcbiAgdmFsdWVzLFxuICBmcm9tX3N0cnVjdCxcbiAgZGVsZXRlOiBfX19fZGVsZXRlX18sXG4gIGRyb3AsXG4gIGVxdWFsX19xbWFya19fOiBfX2VxdWFsX19xbWFya19fLFxuICBmZXRjaF9fZW1hcmtfXyxcbiAgZmV0Y2gsXG4gIGhhc19rZXlfX3FtYXJrX18sXG4gIHNwbGl0LFxuICB0YWtlLFxuICBwdXRfbmV3LFxuICBwdXRfbmV3X2xhenksXG4gIGdldF9hbmRfdXBkYXRlLFxuICBwb3BfbGF6eSxcbiAgcG9wLFxuICBnZXRfbGF6eSxcbiAgZ2V0LFxuICBwdXQ6IF9fcHV0LFxuICB1cGRhdGVfX2VtYXJrX18sXG4gIHVwZGF0ZTogX3VwZGF0ZVxufTtcblxuZnVuY3Rpb24gX19uZXdfXygpIHtcbiAgcmV0dXJuIFNwZWNpYWxGb3Jtcy5tYXAoeyBbU3ltYm9sLmZvcignX19zdHJ1Y3RfXycpXTogU3ltYm9sLmZvcignTWFwU2V0JyksIHNldDogU3BlY2lhbEZvcm1zLmxpc3QoKSB9KTtcbn1cblxuZnVuY3Rpb24gX3NpemUobWFwKSB7XG4gIHJldHVybiBtYXAuc2V0Lmxlbmd0aDtcbn1cblxuZnVuY3Rpb24gX3RvX2xpc3QobWFwKSB7XG4gIHJldHVybiBtYXAuc2V0O1xufVxuXG5mdW5jdGlvbiBfX19kZWxldGVfXyhzZXQsIHRlcm0pIHtcbiAgbGV0IG5ld19saXN0ID0gTGlzdC5kZWxldGUoc2V0LnNldCwgdGVybSk7XG5cbiAgbGV0IG5ld19tYXAgPSBPYmplY3QuYXNzaWduKHt9LCBzZXQpO1xuICBuZXdfbWFwLnNldCA9IG5ld19saXN0O1xuICByZXR1cm4gU3BlY2lhbEZvcm1zLm1hcChuZXdfbWFwKTtcbn1cblxuZnVuY3Rpb24gX3B1dChzZXQsIHRlcm0pIHtcbiAgaWYgKHNldC5zZXQuaW5kZXhPZih0ZXJtKSA9PT0gLTEpIHtcbiAgICBsZXQgbmV3X2xpc3QgPSBMaXN0LmFwcGVuZChzZXQuc2V0LCB0ZXJtKTtcblxuICAgIGxldCBuZXdfbWFwID0gT2JqZWN0LmFzc2lnbih7fSwgc2V0KTtcbiAgICBuZXdfbWFwLnNldCA9IG5ld19saXN0O1xuICAgIHJldHVybiBTcGVjaWFsRm9ybXMubWFwKG5ld19tYXApO1xuICB9XG5cbiAgcmV0dXJuIHNldDtcbn1cblxuZnVuY3Rpb24gX2RpZmZlcmVuY2Uoc2V0MSwgc2V0Mikge1xuICBsZXQgbmV3X21hcCA9IE9iamVjdC5hc3NpZ24oe30sIHNldDEpO1xuXG4gIGZvciAobGV0IHZhbCBvZiBzZXQxLnNldCkge1xuICAgIGlmIChfbWVtYmVyX19xbWFya19fKHNldDIsIHZhbCkpIHtcbiAgICAgIG5ld19tYXAuc2V0ID0gTGlzdC5kZWxldGUobmV3X21hcC5zZXQsIHZhbCk7XG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIFNwZWNpYWxGb3Jtcy5tYXAobmV3X21hcCk7XG59XG5cbmZ1bmN0aW9uIF9pbnRlcnNlY3Rpb24oc2V0MSwgc2V0Mikge1xuICBsZXQgbmV3X21hcCA9IE9iamVjdC5hc3NpZ24oe30sIHNldDEpO1xuXG4gIGZvciAobGV0IHZhbCBvZiBzZXQxLnNldCkge1xuICAgIGlmICghX21lbWJlcl9fcW1hcmtfXyhzZXQyLCB2YWwpKSB7XG4gICAgICBuZXdfbWFwLnNldCA9IExpc3QuZGVsZXRlKG5ld19tYXAuc2V0LCB2YWwpO1xuICAgIH1cbiAgfVxuXG4gIHJldHVybiBTcGVjaWFsRm9ybXMubWFwKG5ld19tYXApO1xufVxuXG5mdW5jdGlvbiBfdW5pb24oc2V0MSwgc2V0Mikge1xuICBsZXQgbmV3X21hcCA9IHNldDE7XG5cbiAgZm9yIChsZXQgdmFsIG9mIHNldDIuc2V0KSB7XG4gICAgbmV3X21hcCA9IF9wdXQobmV3X21hcCwgdmFsKTtcbiAgfVxuXG4gIHJldHVybiBTcGVjaWFsRm9ybXMubWFwKG5ld19tYXApO1xufVxuXG5mdW5jdGlvbiBfZGlzam9pbl9fcW1hcmtfXyhzZXQxLCBzZXQyKSB7XG4gIGZvciAobGV0IHZhbCBvZiBzZXQxLnNldCkge1xuICAgIGlmIChfbWVtYmVyX19xbWFya19fKHNldDIsIHZhbCkpIHtcbiAgICAgIHJldHVybiBmYWxzZTtcbiAgICB9XG4gIH1cblxuICByZXR1cm4gdHJ1ZTtcbn1cblxuZnVuY3Rpb24gX21lbWJlcl9fcW1hcmtfXyhzZXQsIHZhbHVlKSB7XG4gIHJldHVybiBzZXQuc2V0LmluZGV4T2YodmFsdWUpID49IDA7XG59XG5cbmZ1bmN0aW9uIF9lcXVhbF9fcW1hcmtfXyhzZXQxLCBzZXQyKSB7XG4gIHJldHVybiBzZXQxLnNldCA9PT0gc2V0Mi5zZXQ7XG59XG5cbmZ1bmN0aW9uIF9zdWJzZXRfX3FtYXJrX18oc2V0MSwgc2V0Mikge1xuICBmb3IgKGxldCB2YWwgb2Ygc2V0MS5zZXQpIHtcbiAgICBpZiAoIV9tZW1iZXJfX3FtYXJrX18oc2V0MiwgdmFsKSkge1xuICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH1cbiAgfVxuXG4gIHJldHVybiB0cnVlO1xufVxuXG52YXIgTWFwU2V0ID0ge1xuICBuZXc6IF9fbmV3X18sXG4gIHNpemU6IF9zaXplLFxuICB0b19saXN0OiBfdG9fbGlzdCxcbiAgZGlzam9pbl9fcW1hcmtfXzogX2Rpc2pvaW5fX3FtYXJrX18sXG4gIGRlbGV0ZTogX19fZGVsZXRlX18sXG4gIHN1YnNldF9fcW1hcmtfXzogX3N1YnNldF9fcW1hcmtfXyxcbiAgZXF1YWxfX3FtYXJrX186IF9lcXVhbF9fcW1hcmtfXyxcbiAgbWVtYmVyX19xbWFya19fOiBfbWVtYmVyX19xbWFya19fLFxuICBwdXQ6IF9wdXQsXG4gIHVuaW9uOiBfdW5pb24sXG4gIGludGVyc2VjdGlvbjogX2ludGVyc2VjdGlvbixcbiAgZGlmZmVyZW5jZTogX2RpZmZlcmVuY2Vcbn07XG5cbmZ1bmN0aW9uIHNpemUobWFwKSB7XG4gIHJldHVybiBNYXBTZXQuc2l6ZShtYXApO1xufVxuXG5mdW5jdGlvbiB0b19saXN0KG1hcCkge1xuICByZXR1cm4gTWFwU2V0LnRvX2xpc3QobWFwKTtcbn1cblxuZnVuY3Rpb24gX19kZWxldGVfXyhzZXQsIHRlcm0pIHtcbiAgcmV0dXJuIE1hcFNldC5kZWxldGUoc2V0LCB0ZXJtKTtcbn1cblxuZnVuY3Rpb24gcHV0KHNldCwgdGVybSkge1xuICByZXR1cm4gTWFwU2V0LnB1dChzZXQsIHRlcm0pO1xufVxuXG5mdW5jdGlvbiBkaWZmZXJlbmNlKHNldDEsIHNldDIpIHtcbiAgcmV0dXJuIE1hcFNldC5kaWZmZXJlbmNlKHNldDEsIHNldDIpO1xufVxuXG5mdW5jdGlvbiBpbnRlcnNlY3Rpb24oc2V0MSwgc2V0Mikge1xuICByZXR1cm4gTWFwU2V0LmludGVyc2VjdGlvbihzZXQxLCBzZXQyKTtcbn1cblxuZnVuY3Rpb24gdW5pb24oc2V0MSwgc2V0Mikge1xuICByZXR1cm4gTWFwU2V0LnVuaW9uKHNldDEsIHNldDIpO1xufVxuXG5mdW5jdGlvbiBkaXNqb2luX19xbWFya19fKHNldDEsIHNldDIpIHtcbiAgcmV0dXJuIE1hcFNldC5kaXNqb2luX19xbWFya19fKHNldDEsIHNldDIpO1xufVxuXG5mdW5jdGlvbiBtZW1iZXJfX3FtYXJrX18oc2V0LCB2YWx1ZSkge1xuICByZXR1cm4gTWFwU2V0Lm1lbWJlcl9fcW1hcmtfXyhzZXQxLCBzZXQyKTtcbn1cblxuZnVuY3Rpb24gZXF1YWxfX3FtYXJrX18oc2V0MSwgc2V0Mikge1xuICByZXR1cm4gTWFwU2V0LmVxdWFsX19xbWFya19fKHNldDEsIHNldDIpO1xufVxuXG5mdW5jdGlvbiBzdWJzZXRfX3FtYXJrX18oc2V0MSwgc2V0Mikge1xuICByZXR1cm4gTWFwU2V0LnN1YnNldF9fcW1hcmtfXyhzZXQxLCBzZXQyKTtcbn1cblxudmFyIF9TZXQgPSB7XG4gIHNpemUsXG4gIHRvX2xpc3QsXG4gIGRpc2pvaW5fX3FtYXJrX18sXG4gIGRlbGV0ZTogX19kZWxldGVfXyxcbiAgc3Vic2V0X19xbWFya19fLFxuICBlcXVhbF9fcW1hcmtfXyxcbiAgbWVtYmVyX19xbWFya19fLFxuICBwdXQsXG4gIHVuaW9uLFxuICBpbnRlcnNlY3Rpb24sXG4gIGRpZmZlcmVuY2Vcbn07XG5cbmxldCB2aXJ0dWFsRG9tID0gKGZ1bmN0aW9uIChlKSB7XG4gICAgcmV0dXJuIGUoKTtcbn0pKGZ1bmN0aW9uICgpIHtcbiAgICB2YXIgZGVmaW5lLCBtb2R1bGUsIGV4cG9ydHM7XG4gICAgcmV0dXJuIChmdW5jdGlvbiBlKHQsIG4sIHIpIHtcbiAgICAgICAgZnVuY3Rpb24gcyhvLCB1KSB7XG4gICAgICAgICAgICBpZiAoIW5bb10pIHtcbiAgICAgICAgICAgICAgICBpZiAoIXRbb10pIHtcbiAgICAgICAgICAgICAgICAgICAgdmFyIGEgPSB0eXBlb2YgcmVxdWlyZSA9PSBcImZ1bmN0aW9uXCIgJiYgcmVxdWlyZTtcbiAgICAgICAgICAgICAgICAgICAgaWYgKCF1ICYmIGEpIHJldHVybiBhKG8sICEwKTtcbiAgICAgICAgICAgICAgICAgICAgaWYgKGkpIHJldHVybiBpKG8sICEwKTtcbiAgICAgICAgICAgICAgICAgICAgdmFyIGYgPSBuZXcgRXJyb3IoXCJDYW5ub3QgZmluZCBtb2R1bGUgJ1wiICsgbyArIFwiJ1wiKTtcbiAgICAgICAgICAgICAgICAgICAgdGhyb3cgKGYuY29kZSA9IFwiTU9EVUxFX05PVF9GT1VORFwiLCBmKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgdmFyIGwgPSBuW29dID0ge1xuICAgICAgICAgICAgICAgICAgICBleHBvcnRzOiB7fVxuICAgICAgICAgICAgICAgIH07XG4gICAgICAgICAgICAgICAgdFtvXVswXS5jYWxsKGwuZXhwb3J0cywgZnVuY3Rpb24gKGUpIHtcbiAgICAgICAgICAgICAgICAgICAgdmFyIG4gPSB0W29dWzFdW2VdO1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gcyhuID8gbiA6IGUpO1xuICAgICAgICAgICAgICAgIH0sIGwsIGwuZXhwb3J0cywgZSwgdCwgbiwgcik7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXR1cm4gbltvXS5leHBvcnRzO1xuICAgICAgICB9XG4gICAgICAgIHZhciBpID0gdHlwZW9mIHJlcXVpcmUgPT0gXCJmdW5jdGlvblwiICYmIHJlcXVpcmU7XG4gICAgICAgIGZvciAodmFyIG8gPSAwOyBvIDwgci5sZW5ndGg7IG8rKykgcyhyW29dKTtcbiAgICAgICAgcmV0dXJuIHM7XG4gICAgfSkoe1xuICAgICAgICAxOiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge1xuXG4gICAgICAgICAgICB2YXIgY3JlYXRlRWxlbWVudCA9IHJlcXVpcmUoXCIuL3Zkb20vY3JlYXRlLWVsZW1lbnQuanNcIik7XG5cbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gY3JlYXRlRWxlbWVudDtcbiAgICAgICAgfSwgeyBcIi4vdmRvbS9jcmVhdGUtZWxlbWVudC5qc1wiOiAxNSB9XSwgMjogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHtcbiAgICAgICAgICAgIHZhciBkaWZmID0gcmVxdWlyZShcIi4vdnRyZWUvZGlmZi5qc1wiKTtcblxuICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBkaWZmO1xuICAgICAgICB9LCB7IFwiLi92dHJlZS9kaWZmLmpzXCI6IDM1IH1dLCAzOiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge1xuICAgICAgICAgICAgdmFyIGggPSByZXF1aXJlKFwiLi92aXJ0dWFsLWh5cGVyc2NyaXB0L2luZGV4LmpzXCIpO1xuXG4gICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IGg7XG4gICAgICAgIH0sIHsgXCIuL3ZpcnR1YWwtaHlwZXJzY3JpcHQvaW5kZXguanNcIjogMjIgfV0sIDQ6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICB2YXIgZGlmZiA9IHJlcXVpcmUoXCIuL2RpZmYuanNcIik7XG4gICAgICAgICAgICB2YXIgcGF0Y2ggPSByZXF1aXJlKFwiLi9wYXRjaC5qc1wiKTtcbiAgICAgICAgICAgIHZhciBoID0gcmVxdWlyZShcIi4vaC5qc1wiKTtcbiAgICAgICAgICAgIHZhciBjcmVhdGUgPSByZXF1aXJlKFwiLi9jcmVhdGUtZWxlbWVudC5qc1wiKTtcbiAgICAgICAgICAgIHZhciBWTm9kZSA9IHJlcXVpcmUoXCIuL3Zub2RlL3Zub2RlLmpzXCIpO1xuICAgICAgICAgICAgdmFyIFZUZXh0ID0gcmVxdWlyZShcIi4vdm5vZGUvdnRleHQuanNcIik7XG5cbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0ge1xuICAgICAgICAgICAgICAgIGRpZmY6IGRpZmYsXG4gICAgICAgICAgICAgICAgcGF0Y2g6IHBhdGNoLFxuICAgICAgICAgICAgICAgIGg6IGgsXG4gICAgICAgICAgICAgICAgY3JlYXRlOiBjcmVhdGUsXG4gICAgICAgICAgICAgICAgVk5vZGU6IFZOb2RlLFxuICAgICAgICAgICAgICAgIFZUZXh0OiBWVGV4dFxuICAgICAgICAgICAgfTtcbiAgICAgICAgfSwgeyBcIi4vY3JlYXRlLWVsZW1lbnQuanNcIjogMSwgXCIuL2RpZmYuanNcIjogMiwgXCIuL2guanNcIjogMywgXCIuL3BhdGNoLmpzXCI6IDEzLCBcIi4vdm5vZGUvdm5vZGUuanNcIjogMzEsIFwiLi92bm9kZS92dGV4dC5qc1wiOiAzMyB9XSwgNTogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHtcbiAgICAgICAgICAgIC8qIVxuICAgICAgICAgICAgICogQ3Jvc3MtQnJvd3NlciBTcGxpdCAxLjEuMVxuICAgICAgICAgICAgICogQ29weXJpZ2h0IDIwMDctMjAxMiBTdGV2ZW4gTGV2aXRoYW4gPHN0ZXZlbmxldml0aGFuLmNvbT5cbiAgICAgICAgICAgICAqIEF2YWlsYWJsZSB1bmRlciB0aGUgTUlUIExpY2Vuc2VcbiAgICAgICAgICAgICAqIEVDTUFTY3JpcHQgY29tcGxpYW50LCB1bmlmb3JtIGNyb3NzLWJyb3dzZXIgc3BsaXQgbWV0aG9kXG4gICAgICAgICAgICAgKi9cblxuICAgICAgICAgICAgLyoqXG4gICAgICAgICAgICAgKiBTcGxpdHMgYSBzdHJpbmcgaW50byBhbiBhcnJheSBvZiBzdHJpbmdzIHVzaW5nIGEgcmVnZXggb3Igc3RyaW5nIHNlcGFyYXRvci4gTWF0Y2hlcyBvZiB0aGVcbiAgICAgICAgICAgICAqIHNlcGFyYXRvciBhcmUgbm90IGluY2x1ZGVkIGluIHRoZSByZXN1bHQgYXJyYXkuIEhvd2V2ZXIsIGlmIGBzZXBhcmF0b3JgIGlzIGEgcmVnZXggdGhhdCBjb250YWluc1xuICAgICAgICAgICAgICogY2FwdHVyaW5nIGdyb3VwcywgYmFja3JlZmVyZW5jZXMgYXJlIHNwbGljZWQgaW50byB0aGUgcmVzdWx0IGVhY2ggdGltZSBgc2VwYXJhdG9yYCBpcyBtYXRjaGVkLlxuICAgICAgICAgICAgICogRml4ZXMgYnJvd3NlciBidWdzIGNvbXBhcmVkIHRvIHRoZSBuYXRpdmUgYFN0cmluZy5wcm90b3R5cGUuc3BsaXRgIGFuZCBjYW4gYmUgdXNlZCByZWxpYWJseVxuICAgICAgICAgICAgICogY3Jvc3MtYnJvd3Nlci5cbiAgICAgICAgICAgICAqIEBwYXJhbSB7U3RyaW5nfSBzdHIgU3RyaW5nIHRvIHNwbGl0LlxuICAgICAgICAgICAgICogQHBhcmFtIHtSZWdFeHB8U3RyaW5nfSBzZXBhcmF0b3IgUmVnZXggb3Igc3RyaW5nIHRvIHVzZSBmb3Igc2VwYXJhdGluZyB0aGUgc3RyaW5nLlxuICAgICAgICAgICAgICogQHBhcmFtIHtOdW1iZXJ9IFtsaW1pdF0gTWF4aW11bSBudW1iZXIgb2YgaXRlbXMgdG8gaW5jbHVkZSBpbiB0aGUgcmVzdWx0IGFycmF5LlxuICAgICAgICAgICAgICogQHJldHVybnMge0FycmF5fSBBcnJheSBvZiBzdWJzdHJpbmdzLlxuICAgICAgICAgICAgICogQGV4YW1wbGVcbiAgICAgICAgICAgICAqXG4gICAgICAgICAgICAgKiAvLyBCYXNpYyB1c2VcbiAgICAgICAgICAgICAqIHNwbGl0KCdhIGIgYyBkJywgJyAnKTtcbiAgICAgICAgICAgICAqIC8vIC0+IFsnYScsICdiJywgJ2MnLCAnZCddXG4gICAgICAgICAgICAgKlxuICAgICAgICAgICAgICogLy8gV2l0aCBsaW1pdFxuICAgICAgICAgICAgICogc3BsaXQoJ2EgYiBjIGQnLCAnICcsIDIpO1xuICAgICAgICAgICAgICogLy8gLT4gWydhJywgJ2InXVxuICAgICAgICAgICAgICpcbiAgICAgICAgICAgICAqIC8vIEJhY2tyZWZlcmVuY2VzIGluIHJlc3VsdCBhcnJheVxuICAgICAgICAgICAgICogc3BsaXQoJy4ud29yZDEgd29yZDIuLicsIC8oW2Etel0rKShcXGQrKS9pKTtcbiAgICAgICAgICAgICAqIC8vIC0+IFsnLi4nLCAnd29yZCcsICcxJywgJyAnLCAnd29yZCcsICcyJywgJy4uJ11cbiAgICAgICAgICAgICAqL1xuICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSAoZnVuY3Rpb24gc3BsaXQodW5kZWYpIHtcblxuICAgICAgICAgICAgICAgIHZhciBuYXRpdmVTcGxpdCA9IFN0cmluZy5wcm90b3R5cGUuc3BsaXQsXG4gICAgICAgICAgICAgICAgICAgIGNvbXBsaWFudEV4ZWNOcGNnID0gLygpPz8vLmV4ZWMoXCJcIilbMV0gPT09IHVuZGVmLFxuXG4gICAgICAgICAgICAgICAgLy8gTlBDRzogbm9ucGFydGljaXBhdGluZyBjYXB0dXJpbmcgZ3JvdXBcbiAgICAgICAgICAgICAgICBzZWxmO1xuXG4gICAgICAgICAgICAgICAgc2VsZiA9IGZ1bmN0aW9uIChzdHIsIHNlcGFyYXRvciwgbGltaXQpIHtcbiAgICAgICAgICAgICAgICAgICAgLy8gSWYgYHNlcGFyYXRvcmAgaXMgbm90IGEgcmVnZXgsIHVzZSBgbmF0aXZlU3BsaXRgXG4gICAgICAgICAgICAgICAgICAgIGlmIChPYmplY3QucHJvdG90eXBlLnRvU3RyaW5nLmNhbGwoc2VwYXJhdG9yKSAhPT0gXCJbb2JqZWN0IFJlZ0V4cF1cIikge1xuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIG5hdGl2ZVNwbGl0LmNhbGwoc3RyLCBzZXBhcmF0b3IsIGxpbWl0KTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB2YXIgb3V0cHV0ID0gW10sXG4gICAgICAgICAgICAgICAgICAgICAgICBmbGFncyA9IChzZXBhcmF0b3IuaWdub3JlQ2FzZSA/IFwiaVwiIDogXCJcIikgKyAoc2VwYXJhdG9yLm11bHRpbGluZSA/IFwibVwiIDogXCJcIikgKyAoc2VwYXJhdG9yLmV4dGVuZGVkID8gXCJ4XCIgOiBcIlwiKSArIChzZXBhcmF0b3Iuc3RpY2t5ID8gXCJ5XCIgOiBcIlwiKSxcblxuICAgICAgICAgICAgICAgICAgICAvLyBGaXJlZm94IDMrXG4gICAgICAgICAgICAgICAgICAgIGxhc3RMYXN0SW5kZXggPSAwLFxuXG4gICAgICAgICAgICAgICAgICAgIC8vIE1ha2UgYGdsb2JhbGAgYW5kIGF2b2lkIGBsYXN0SW5kZXhgIGlzc3VlcyBieSB3b3JraW5nIHdpdGggYSBjb3B5XG4gICAgICAgICAgICAgICAgICAgIHNlcGFyYXRvciA9IG5ldyBSZWdFeHAoc2VwYXJhdG9yLnNvdXJjZSwgZmxhZ3MgKyBcImdcIiksXG4gICAgICAgICAgICAgICAgICAgICAgICBzZXBhcmF0b3IyLFxuICAgICAgICAgICAgICAgICAgICAgICAgbWF0Y2gsXG4gICAgICAgICAgICAgICAgICAgICAgICBsYXN0SW5kZXgsXG4gICAgICAgICAgICAgICAgICAgICAgICBsYXN0TGVuZ3RoO1xuICAgICAgICAgICAgICAgICAgICBzdHIgKz0gXCJcIjsgLy8gVHlwZS1jb252ZXJ0XG4gICAgICAgICAgICAgICAgICAgIGlmICghY29tcGxpYW50RXhlY05wY2cpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIERvZXNuJ3QgbmVlZCBmbGFncyBneSwgYnV0IHRoZXkgZG9uJ3QgaHVydFxuICAgICAgICAgICAgICAgICAgICAgICAgc2VwYXJhdG9yMiA9IG5ldyBSZWdFeHAoXCJeXCIgKyBzZXBhcmF0b3Iuc291cmNlICsgXCIkKD8hXFxcXHMpXCIsIGZsYWdzKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAvKiBWYWx1ZXMgZm9yIGBsaW1pdGAsIHBlciB0aGUgc3BlYzpcbiAgICAgICAgICAgICAgICAgICAgICogSWYgdW5kZWZpbmVkOiA0Mjk0OTY3Mjk1IC8vIE1hdGgucG93KDIsIDMyKSAtIDFcbiAgICAgICAgICAgICAgICAgICAgICogSWYgMCwgSW5maW5pdHksIG9yIE5hTjogMFxuICAgICAgICAgICAgICAgICAgICAgKiBJZiBwb3NpdGl2ZSBudW1iZXI6IGxpbWl0ID0gTWF0aC5mbG9vcihsaW1pdCk7IGlmIChsaW1pdCA+IDQyOTQ5NjcyOTUpIGxpbWl0IC09IDQyOTQ5NjcyOTY7XG4gICAgICAgICAgICAgICAgICAgICAqIElmIG5lZ2F0aXZlIG51bWJlcjogNDI5NDk2NzI5NiAtIE1hdGguZmxvb3IoTWF0aC5hYnMobGltaXQpKVxuICAgICAgICAgICAgICAgICAgICAgKiBJZiBvdGhlcjogVHlwZS1jb252ZXJ0LCB0aGVuIHVzZSB0aGUgYWJvdmUgcnVsZXNcbiAgICAgICAgICAgICAgICAgICAgICovXG4gICAgICAgICAgICAgICAgICAgIGxpbWl0ID0gbGltaXQgPT09IHVuZGVmID8gLTEgPj4+IDAgOiAvLyBNYXRoLnBvdygyLCAzMikgLSAxXG4gICAgICAgICAgICAgICAgICAgIGxpbWl0ID4+PiAwOyAvLyBUb1VpbnQzMihsaW1pdClcbiAgICAgICAgICAgICAgICAgICAgd2hpbGUgKG1hdGNoID0gc2VwYXJhdG9yLmV4ZWMoc3RyKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgLy8gYHNlcGFyYXRvci5sYXN0SW5kZXhgIGlzIG5vdCByZWxpYWJsZSBjcm9zcy1icm93c2VyXG4gICAgICAgICAgICAgICAgICAgICAgICBsYXN0SW5kZXggPSBtYXRjaC5pbmRleCArIG1hdGNoWzBdLmxlbmd0aDtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChsYXN0SW5kZXggPiBsYXN0TGFzdEluZGV4KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgb3V0cHV0LnB1c2goc3RyLnNsaWNlKGxhc3RMYXN0SW5kZXgsIG1hdGNoLmluZGV4KSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gRml4IGJyb3dzZXJzIHdob3NlIGBleGVjYCBtZXRob2RzIGRvbid0IGNvbnNpc3RlbnRseSByZXR1cm4gYHVuZGVmaW5lZGAgZm9yXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gbm9ucGFydGljaXBhdGluZyBjYXB0dXJpbmcgZ3JvdXBzXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKCFjb21wbGlhbnRFeGVjTnBjZyAmJiBtYXRjaC5sZW5ndGggPiAxKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1hdGNoWzBdLnJlcGxhY2Uoc2VwYXJhdG9yMiwgZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZm9yICh2YXIgaSA9IDE7IGkgPCBhcmd1bWVudHMubGVuZ3RoIC0gMjsgaSsrKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGFyZ3VtZW50c1tpXSA9PT0gdW5kZWYpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbWF0Y2hbaV0gPSB1bmRlZjtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAobWF0Y2gubGVuZ3RoID4gMSAmJiBtYXRjaC5pbmRleCA8IHN0ci5sZW5ndGgpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgQXJyYXkucHJvdG90eXBlLnB1c2guYXBwbHkob3V0cHV0LCBtYXRjaC5zbGljZSgxKSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxhc3RMZW5ndGggPSBtYXRjaFswXS5sZW5ndGg7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgbGFzdExhc3RJbmRleCA9IGxhc3RJbmRleDtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAob3V0cHV0Lmxlbmd0aCA+PSBsaW1pdCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoc2VwYXJhdG9yLmxhc3RJbmRleCA9PT0gbWF0Y2guaW5kZXgpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBzZXBhcmF0b3IubGFzdEluZGV4Kys7IC8vIEF2b2lkIGFuIGluZmluaXRlIGxvb3BcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICBpZiAobGFzdExhc3RJbmRleCA9PT0gc3RyLmxlbmd0aCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGxhc3RMZW5ndGggfHwgIXNlcGFyYXRvci50ZXN0KFwiXCIpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgb3V0cHV0LnB1c2goXCJcIik7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBvdXRwdXQucHVzaChzdHIuc2xpY2UobGFzdExhc3RJbmRleCkpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBvdXRwdXQubGVuZ3RoID4gbGltaXQgPyBvdXRwdXQuc2xpY2UoMCwgbGltaXQpIDogb3V0cHV0O1xuICAgICAgICAgICAgICAgIH07XG5cbiAgICAgICAgICAgICAgICByZXR1cm4gc2VsZjtcbiAgICAgICAgICAgIH0pKCk7XG4gICAgICAgIH0sIHt9XSwgNjogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHt9LCB7fV0sIDc6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICBcInVzZSBzdHJpY3RcIjtcblxuICAgICAgICAgICAgdmFyIE9uZVZlcnNpb25Db25zdHJhaW50ID0gcmVxdWlyZShcImluZGl2aWR1YWwvb25lLXZlcnNpb25cIik7XG5cbiAgICAgICAgICAgIHZhciBNWV9WRVJTSU9OID0gXCI3XCI7XG4gICAgICAgICAgICBPbmVWZXJzaW9uQ29uc3RyYWludChcImV2LXN0b3JlXCIsIE1ZX1ZFUlNJT04pO1xuXG4gICAgICAgICAgICB2YXIgaGFzaEtleSA9IFwiX19FVl9TVE9SRV9LRVlAXCIgKyBNWV9WRVJTSU9OO1xuXG4gICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IEV2U3RvcmU7XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIEV2U3RvcmUoZWxlbSkge1xuICAgICAgICAgICAgICAgIHZhciBoYXNoID0gZWxlbVtoYXNoS2V5XTtcblxuICAgICAgICAgICAgICAgIGlmICghaGFzaCkge1xuICAgICAgICAgICAgICAgICAgICBoYXNoID0gZWxlbVtoYXNoS2V5XSA9IHt9O1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHJldHVybiBoYXNoO1xuICAgICAgICAgICAgfVxuICAgICAgICB9LCB7IFwiaW5kaXZpZHVhbC9vbmUtdmVyc2lvblwiOiA5IH1dLCA4OiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge1xuICAgICAgICAgICAgKGZ1bmN0aW9uIChnbG9iYWwpIHtcbiAgICAgICAgICAgICAgICBcInVzZSBzdHJpY3RcIjtcblxuICAgICAgICAgICAgICAgIC8qZ2xvYmFsIHdpbmRvdywgZ2xvYmFsKi9cblxuICAgICAgICAgICAgICAgIHZhciByb290ID0gdHlwZW9mIHdpbmRvdyAhPT0gXCJ1bmRlZmluZWRcIiA/IHdpbmRvdyA6IHR5cGVvZiBnbG9iYWwgIT09IFwidW5kZWZpbmVkXCIgPyBnbG9iYWwgOiB7fTtcblxuICAgICAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gSW5kaXZpZHVhbDtcblxuICAgICAgICAgICAgICAgIGZ1bmN0aW9uIEluZGl2aWR1YWwoa2V5LCB2YWx1ZSkge1xuICAgICAgICAgICAgICAgICAgICBpZiAoa2V5IGluIHJvb3QpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiByb290W2tleV07XG4gICAgICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgICAgICByb290W2tleV0gPSB2YWx1ZTtcblxuICAgICAgICAgICAgICAgICAgICByZXR1cm4gdmFsdWU7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSkuY2FsbCh0aGlzLCB0eXBlb2YgZ2xvYmFsICE9PSBcInVuZGVmaW5lZFwiID8gZ2xvYmFsIDogdHlwZW9mIHNlbGYgIT09IFwidW5kZWZpbmVkXCIgPyBzZWxmIDogdHlwZW9mIHdpbmRvdyAhPT0gXCJ1bmRlZmluZWRcIiA/IHdpbmRvdyA6IHt9KTtcbiAgICAgICAgfSwge31dLCA5OiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge1xuICAgICAgICAgICAgXCJ1c2Ugc3RyaWN0XCI7XG5cbiAgICAgICAgICAgIHZhciBJbmRpdmlkdWFsID0gcmVxdWlyZShcIi4vaW5kZXguanNcIik7XG5cbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gT25lVmVyc2lvbjtcblxuICAgICAgICAgICAgZnVuY3Rpb24gT25lVmVyc2lvbihtb2R1bGVOYW1lLCB2ZXJzaW9uLCBkZWZhdWx0VmFsdWUpIHtcbiAgICAgICAgICAgICAgICB2YXIga2V5ID0gXCJfX0lORElWSURVQUxfT05FX1ZFUlNJT05fXCIgKyBtb2R1bGVOYW1lO1xuICAgICAgICAgICAgICAgIHZhciBlbmZvcmNlS2V5ID0ga2V5ICsgXCJfRU5GT1JDRV9TSU5HTEVUT05cIjtcblxuICAgICAgICAgICAgICAgIHZhciB2ZXJzaW9uVmFsdWUgPSBJbmRpdmlkdWFsKGVuZm9yY2VLZXksIHZlcnNpb24pO1xuXG4gICAgICAgICAgICAgICAgaWYgKHZlcnNpb25WYWx1ZSAhPT0gdmVyc2lvbikge1xuICAgICAgICAgICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoXCJDYW4gb25seSBoYXZlIG9uZSBjb3B5IG9mIFwiICsgbW9kdWxlTmFtZSArIFwiLlxcblwiICsgXCJZb3UgYWxyZWFkeSBoYXZlIHZlcnNpb24gXCIgKyB2ZXJzaW9uVmFsdWUgKyBcIiBpbnN0YWxsZWQuXFxuXCIgKyBcIlRoaXMgbWVhbnMgeW91IGNhbm5vdCBpbnN0YWxsIHZlcnNpb24gXCIgKyB2ZXJzaW9uKTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICByZXR1cm4gSW5kaXZpZHVhbChrZXksIGRlZmF1bHRWYWx1ZSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0sIHsgXCIuL2luZGV4LmpzXCI6IDggfV0sIDEwOiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge1xuICAgICAgICAgICAgKGZ1bmN0aW9uIChnbG9iYWwpIHtcbiAgICAgICAgICAgICAgICB2YXIgdG9wTGV2ZWwgPSB0eXBlb2YgZ2xvYmFsICE9PSBcInVuZGVmaW5lZFwiID8gZ2xvYmFsIDogdHlwZW9mIHdpbmRvdyAhPT0gXCJ1bmRlZmluZWRcIiA/IHdpbmRvdyA6IHt9O1xuICAgICAgICAgICAgICAgIHZhciBtaW5Eb2MgPSByZXF1aXJlKFwibWluLWRvY3VtZW50XCIpO1xuXG4gICAgICAgICAgICAgICAgaWYgKHR5cGVvZiBkb2N1bWVudCAhPT0gXCJ1bmRlZmluZWRcIikge1xuICAgICAgICAgICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IGRvY3VtZW50O1xuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciBkb2NjeSA9IHRvcExldmVsW1wiX19HTE9CQUxfRE9DVU1FTlRfQ0FDSEVANFwiXTtcblxuICAgICAgICAgICAgICAgICAgICBpZiAoIWRvY2N5KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBkb2NjeSA9IHRvcExldmVsW1wiX19HTE9CQUxfRE9DVU1FTlRfQ0FDSEVANFwiXSA9IG1pbkRvYztcbiAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gZG9jY3k7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSkuY2FsbCh0aGlzLCB0eXBlb2YgZ2xvYmFsICE9PSBcInVuZGVmaW5lZFwiID8gZ2xvYmFsIDogdHlwZW9mIHNlbGYgIT09IFwidW5kZWZpbmVkXCIgPyBzZWxmIDogdHlwZW9mIHdpbmRvdyAhPT0gXCJ1bmRlZmluZWRcIiA/IHdpbmRvdyA6IHt9KTtcbiAgICAgICAgfSwgeyBcIm1pbi1kb2N1bWVudFwiOiA2IH1dLCAxMTogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHtcbiAgICAgICAgICAgIFwidXNlIHN0cmljdFwiO1xuXG4gICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uIGlzT2JqZWN0KHgpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gdHlwZW9mIHggPT09IFwib2JqZWN0XCIgJiYgeCAhPT0gbnVsbDtcbiAgICAgICAgICAgIH07XG4gICAgICAgIH0sIHt9XSwgMTI6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICB2YXIgbmF0aXZlSXNBcnJheSA9IEFycmF5LmlzQXJyYXk7XG4gICAgICAgICAgICB2YXIgdG9TdHJpbmcgPSBPYmplY3QucHJvdG90eXBlLnRvU3RyaW5nO1xuXG4gICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IG5hdGl2ZUlzQXJyYXkgfHwgaXNBcnJheTtcblxuICAgICAgICAgICAgZnVuY3Rpb24gaXNBcnJheShvYmopIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gdG9TdHJpbmcuY2FsbChvYmopID09PSBcIltvYmplY3QgQXJyYXldXCI7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0sIHt9XSwgMTM6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICB2YXIgcGF0Y2ggPSByZXF1aXJlKFwiLi92ZG9tL3BhdGNoLmpzXCIpO1xuXG4gICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IHBhdGNoO1xuICAgICAgICB9LCB7IFwiLi92ZG9tL3BhdGNoLmpzXCI6IDE4IH1dLCAxNDogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHtcbiAgICAgICAgICAgIHZhciBpc09iamVjdCA9IHJlcXVpcmUoXCJpcy1vYmplY3RcIik7XG4gICAgICAgICAgICB2YXIgaXNIb29rID0gcmVxdWlyZShcIi4uL3Zub2RlL2lzLXZob29rLmpzXCIpO1xuXG4gICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IGFwcGx5UHJvcGVydGllcztcblxuICAgICAgICAgICAgZnVuY3Rpb24gYXBwbHlQcm9wZXJ0aWVzKG5vZGUsIHByb3BzLCBwcmV2aW91cykge1xuICAgICAgICAgICAgICAgIGZvciAodmFyIHByb3BOYW1lIGluIHByb3BzKSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciBwcm9wVmFsdWUgPSBwcm9wc1twcm9wTmFtZV07XG5cbiAgICAgICAgICAgICAgICAgICAgaWYgKHByb3BWYWx1ZSA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICByZW1vdmVQcm9wZXJ0eShub2RlLCBwcm9wTmFtZSwgcHJvcFZhbHVlLCBwcmV2aW91cyk7XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoaXNIb29rKHByb3BWYWx1ZSkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJlbW92ZVByb3BlcnR5KG5vZGUsIHByb3BOYW1lLCBwcm9wVmFsdWUsIHByZXZpb3VzKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChwcm9wVmFsdWUuaG9vaykge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHByb3BWYWx1ZS5ob29rKG5vZGUsIHByb3BOYW1lLCBwcmV2aW91cyA/IHByZXZpb3VzW3Byb3BOYW1lXSA6IHVuZGVmaW5lZCk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoaXNPYmplY3QocHJvcFZhbHVlKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHBhdGNoT2JqZWN0KG5vZGUsIHByb3BzLCBwcmV2aW91cywgcHJvcE5hbWUsIHByb3BWYWx1ZSk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIG5vZGVbcHJvcE5hbWVdID0gcHJvcFZhbHVlO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBmdW5jdGlvbiByZW1vdmVQcm9wZXJ0eShub2RlLCBwcm9wTmFtZSwgcHJvcFZhbHVlLCBwcmV2aW91cykge1xuICAgICAgICAgICAgICAgIGlmIChwcmV2aW91cykge1xuICAgICAgICAgICAgICAgICAgICB2YXIgcHJldmlvdXNWYWx1ZSA9IHByZXZpb3VzW3Byb3BOYW1lXTtcblxuICAgICAgICAgICAgICAgICAgICBpZiAoIWlzSG9vayhwcmV2aW91c1ZhbHVlKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHByb3BOYW1lID09PSBcImF0dHJpYnV0ZXNcIikge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZvciAodmFyIGF0dHJOYW1lIGluIHByZXZpb3VzVmFsdWUpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbm9kZS5yZW1vdmVBdHRyaWJ1dGUoYXR0ck5hbWUpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAocHJvcE5hbWUgPT09IFwic3R5bGVcIikge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZvciAodmFyIGkgaW4gcHJldmlvdXNWYWx1ZSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBub2RlLnN0eWxlW2ldID0gXCJcIjtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKHR5cGVvZiBwcmV2aW91c1ZhbHVlID09PSBcInN0cmluZ1wiKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgbm9kZVtwcm9wTmFtZV0gPSBcIlwiO1xuICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBub2RlW3Byb3BOYW1lXSA9IG51bGw7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAocHJldmlvdXNWYWx1ZS51bmhvb2spIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHByZXZpb3VzVmFsdWUudW5ob29rKG5vZGUsIHByb3BOYW1lLCBwcm9wVmFsdWUpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBmdW5jdGlvbiBwYXRjaE9iamVjdChub2RlLCBwcm9wcywgcHJldmlvdXMsIHByb3BOYW1lLCBwcm9wVmFsdWUpIHtcbiAgICAgICAgICAgICAgICB2YXIgcHJldmlvdXNWYWx1ZSA9IHByZXZpb3VzID8gcHJldmlvdXNbcHJvcE5hbWVdIDogdW5kZWZpbmVkO1xuXG4gICAgICAgICAgICAgICAgLy8gU2V0IGF0dHJpYnV0ZXNcbiAgICAgICAgICAgICAgICBpZiAocHJvcE5hbWUgPT09IFwiYXR0cmlidXRlc1wiKSB7XG4gICAgICAgICAgICAgICAgICAgIGZvciAodmFyIGF0dHJOYW1lIGluIHByb3BWYWx1ZSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgdmFyIGF0dHJWYWx1ZSA9IHByb3BWYWx1ZVthdHRyTmFtZV07XG5cbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChhdHRyVmFsdWUgPT09IHVuZGVmaW5lZCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIG5vZGUucmVtb3ZlQXR0cmlidXRlKGF0dHJOYW1lKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgbm9kZS5zZXRBdHRyaWJ1dGUoYXR0ck5hbWUsIGF0dHJWYWx1ZSk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgaWYgKHByZXZpb3VzVmFsdWUgJiYgaXNPYmplY3QocHJldmlvdXNWYWx1ZSkgJiYgZ2V0UHJvdG90eXBlKHByZXZpb3VzVmFsdWUpICE9PSBnZXRQcm90b3R5cGUocHJvcFZhbHVlKSkge1xuICAgICAgICAgICAgICAgICAgICBub2RlW3Byb3BOYW1lXSA9IHByb3BWYWx1ZTtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIGlmICghaXNPYmplY3Qobm9kZVtwcm9wTmFtZV0pKSB7XG4gICAgICAgICAgICAgICAgICAgIG5vZGVbcHJvcE5hbWVdID0ge307XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgdmFyIHJlcGxhY2VyID0gcHJvcE5hbWUgPT09IFwic3R5bGVcIiA/IFwiXCIgOiB1bmRlZmluZWQ7XG5cbiAgICAgICAgICAgICAgICBmb3IgKHZhciBrIGluIHByb3BWYWx1ZSkge1xuICAgICAgICAgICAgICAgICAgICB2YXIgdmFsdWUgPSBwcm9wVmFsdWVba107XG4gICAgICAgICAgICAgICAgICAgIG5vZGVbcHJvcE5hbWVdW2tdID0gdmFsdWUgPT09IHVuZGVmaW5lZCA/IHJlcGxhY2VyIDogdmFsdWU7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBmdW5jdGlvbiBnZXRQcm90b3R5cGUodmFsdWUpIHtcbiAgICAgICAgICAgICAgICBpZiAoT2JqZWN0LmdldFByb3RvdHlwZU9mKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBPYmplY3QuZ2V0UHJvdG90eXBlT2YodmFsdWUpO1xuICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAodmFsdWUuX19wcm90b19fKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiB2YWx1ZS5fX3Byb3RvX187XG4gICAgICAgICAgICAgICAgfSBlbHNlIGlmICh2YWx1ZS5jb25zdHJ1Y3Rvcikge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gdmFsdWUuY29uc3RydWN0b3IucHJvdG90eXBlO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgfSwgeyBcIi4uL3Zub2RlL2lzLXZob29rLmpzXCI6IDI2LCBcImlzLW9iamVjdFwiOiAxMSB9XSwgMTU6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICB2YXIgZG9jdW1lbnQgPSByZXF1aXJlKFwiZ2xvYmFsL2RvY3VtZW50XCIpO1xuXG4gICAgICAgICAgICB2YXIgYXBwbHlQcm9wZXJ0aWVzID0gcmVxdWlyZShcIi4vYXBwbHktcHJvcGVydGllc1wiKTtcblxuICAgICAgICAgICAgdmFyIGlzVk5vZGUgPSByZXF1aXJlKFwiLi4vdm5vZGUvaXMtdm5vZGUuanNcIik7XG4gICAgICAgICAgICB2YXIgaXNWVGV4dCA9IHJlcXVpcmUoXCIuLi92bm9kZS9pcy12dGV4dC5qc1wiKTtcbiAgICAgICAgICAgIHZhciBpc1dpZGdldCA9IHJlcXVpcmUoXCIuLi92bm9kZS9pcy13aWRnZXQuanNcIik7XG4gICAgICAgICAgICB2YXIgaGFuZGxlVGh1bmsgPSByZXF1aXJlKFwiLi4vdm5vZGUvaGFuZGxlLXRodW5rLmpzXCIpO1xuXG4gICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IGNyZWF0ZUVsZW1lbnQ7XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIGNyZWF0ZUVsZW1lbnQodm5vZGUsIG9wdHMpIHtcbiAgICAgICAgICAgICAgICB2YXIgZG9jID0gb3B0cyA/IG9wdHMuZG9jdW1lbnQgfHwgZG9jdW1lbnQgOiBkb2N1bWVudDtcbiAgICAgICAgICAgICAgICB2YXIgd2FybiA9IG9wdHMgPyBvcHRzLndhcm4gOiBudWxsO1xuXG4gICAgICAgICAgICAgICAgdm5vZGUgPSBoYW5kbGVUaHVuayh2bm9kZSkuYTtcblxuICAgICAgICAgICAgICAgIGlmIChpc1dpZGdldCh2bm9kZSkpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHZub2RlLmluaXQoKTtcbiAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKGlzVlRleHQodm5vZGUpKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBkb2MuY3JlYXRlVGV4dE5vZGUodm5vZGUudGV4dCk7XG4gICAgICAgICAgICAgICAgfSBlbHNlIGlmICghaXNWTm9kZSh2bm9kZSkpIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKHdhcm4pIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHdhcm4oXCJJdGVtIGlzIG5vdCBhIHZhbGlkIHZpcnR1YWwgZG9tIG5vZGVcIiwgdm5vZGUpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBudWxsO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHZhciBub2RlID0gdm5vZGUubmFtZXNwYWNlID09PSBudWxsID8gZG9jLmNyZWF0ZUVsZW1lbnQodm5vZGUudGFnTmFtZSkgOiBkb2MuY3JlYXRlRWxlbWVudE5TKHZub2RlLm5hbWVzcGFjZSwgdm5vZGUudGFnTmFtZSk7XG5cbiAgICAgICAgICAgICAgICB2YXIgcHJvcHMgPSB2bm9kZS5wcm9wZXJ0aWVzO1xuICAgICAgICAgICAgICAgIGFwcGx5UHJvcGVydGllcyhub2RlLCBwcm9wcyk7XG5cbiAgICAgICAgICAgICAgICB2YXIgY2hpbGRyZW4gPSB2bm9kZS5jaGlsZHJlbjtcblxuICAgICAgICAgICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgY2hpbGRyZW4ubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgICAgICAgICAgdmFyIGNoaWxkTm9kZSA9IGNyZWF0ZUVsZW1lbnQoY2hpbGRyZW5baV0sIG9wdHMpO1xuICAgICAgICAgICAgICAgICAgICBpZiAoY2hpbGROb2RlKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBub2RlLmFwcGVuZENoaWxkKGNoaWxkTm9kZSk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICByZXR1cm4gbm9kZTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSwgeyBcIi4uL3Zub2RlL2hhbmRsZS10aHVuay5qc1wiOiAyNCwgXCIuLi92bm9kZS9pcy12bm9kZS5qc1wiOiAyNywgXCIuLi92bm9kZS9pcy12dGV4dC5qc1wiOiAyOCwgXCIuLi92bm9kZS9pcy13aWRnZXQuanNcIjogMjksIFwiLi9hcHBseS1wcm9wZXJ0aWVzXCI6IDE0LCBcImdsb2JhbC9kb2N1bWVudFwiOiAxMCB9XSwgMTY6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICAvLyBNYXBzIGEgdmlydHVhbCBET00gdHJlZSBvbnRvIGEgcmVhbCBET00gdHJlZSBpbiBhbiBlZmZpY2llbnQgbWFubmVyLlxuICAgICAgICAgICAgLy8gV2UgZG9uJ3Qgd2FudCB0byByZWFkIGFsbCBvZiB0aGUgRE9NIG5vZGVzIGluIHRoZSB0cmVlIHNvIHdlIHVzZVxuICAgICAgICAgICAgLy8gdGhlIGluLW9yZGVyIHRyZWUgaW5kZXhpbmcgdG8gZWxpbWluYXRlIHJlY3Vyc2lvbiBkb3duIGNlcnRhaW4gYnJhbmNoZXMuXG4gICAgICAgICAgICAvLyBXZSBvbmx5IHJlY3Vyc2UgaW50byBhIERPTSBub2RlIGlmIHdlIGtub3cgdGhhdCBpdCBjb250YWlucyBhIGNoaWxkIG9mXG4gICAgICAgICAgICAvLyBpbnRlcmVzdC5cblxuICAgICAgICAgICAgdmFyIG5vQ2hpbGQgPSB7fTtcblxuICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBkb21JbmRleDtcblxuICAgICAgICAgICAgZnVuY3Rpb24gZG9tSW5kZXgocm9vdE5vZGUsIHRyZWUsIGluZGljZXMsIG5vZGVzKSB7XG4gICAgICAgICAgICAgICAgaWYgKCFpbmRpY2VzIHx8IGluZGljZXMubGVuZ3RoID09PSAwKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiB7fTtcbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICBpbmRpY2VzLnNvcnQoYXNjZW5kaW5nKTtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHJlY3Vyc2Uocm9vdE5vZGUsIHRyZWUsIGluZGljZXMsIG5vZGVzLCAwKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIHJlY3Vyc2Uocm9vdE5vZGUsIHRyZWUsIGluZGljZXMsIG5vZGVzLCByb290SW5kZXgpIHtcbiAgICAgICAgICAgICAgICBub2RlcyA9IG5vZGVzIHx8IHt9O1xuXG4gICAgICAgICAgICAgICAgaWYgKHJvb3ROb2RlKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmIChpbmRleEluUmFuZ2UoaW5kaWNlcywgcm9vdEluZGV4LCByb290SW5kZXgpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBub2Rlc1tyb290SW5kZXhdID0gcm9vdE5vZGU7XG4gICAgICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgICAgICB2YXIgdkNoaWxkcmVuID0gdHJlZS5jaGlsZHJlbjtcblxuICAgICAgICAgICAgICAgICAgICBpZiAodkNoaWxkcmVuKSB7XG5cbiAgICAgICAgICAgICAgICAgICAgICAgIHZhciBjaGlsZE5vZGVzID0gcm9vdE5vZGUuY2hpbGROb2RlcztcblxuICAgICAgICAgICAgICAgICAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCB0cmVlLmNoaWxkcmVuLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcm9vdEluZGV4ICs9IDE7XG5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB2YXIgdkNoaWxkID0gdkNoaWxkcmVuW2ldIHx8IG5vQ2hpbGQ7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdmFyIG5leHRJbmRleCA9IHJvb3RJbmRleCArICh2Q2hpbGQuY291bnQgfHwgMCk7XG5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBza2lwIHJlY3Vyc2lvbiBkb3duIHRoZSB0cmVlIGlmIHRoZXJlIGFyZSBubyBub2RlcyBkb3duIGhlcmVcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoaW5kZXhJblJhbmdlKGluZGljZXMsIHJvb3RJbmRleCwgbmV4dEluZGV4KSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICByZWN1cnNlKGNoaWxkTm9kZXNbaV0sIHZDaGlsZCwgaW5kaWNlcywgbm9kZXMsIHJvb3RJbmRleCk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcm9vdEluZGV4ID0gbmV4dEluZGV4O1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgcmV0dXJuIG5vZGVzO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAvLyBCaW5hcnkgc2VhcmNoIGZvciBhbiBpbmRleCBpbiB0aGUgaW50ZXJ2YWwgW2xlZnQsIHJpZ2h0XVxuICAgICAgICAgICAgZnVuY3Rpb24gaW5kZXhJblJhbmdlKGluZGljZXMsIGxlZnQsIHJpZ2h0KSB7XG4gICAgICAgICAgICAgICAgaWYgKGluZGljZXMubGVuZ3RoID09PSAwKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICB2YXIgbWluSW5kZXggPSAwO1xuICAgICAgICAgICAgICAgIHZhciBtYXhJbmRleCA9IGluZGljZXMubGVuZ3RoIC0gMTtcbiAgICAgICAgICAgICAgICB2YXIgY3VycmVudEluZGV4O1xuICAgICAgICAgICAgICAgIHZhciBjdXJyZW50SXRlbTtcblxuICAgICAgICAgICAgICAgIHdoaWxlIChtaW5JbmRleCA8PSBtYXhJbmRleCkge1xuICAgICAgICAgICAgICAgICAgICBjdXJyZW50SW5kZXggPSAobWF4SW5kZXggKyBtaW5JbmRleCkgLyAyID4+IDA7XG4gICAgICAgICAgICAgICAgICAgIGN1cnJlbnRJdGVtID0gaW5kaWNlc1tjdXJyZW50SW5kZXhdO1xuXG4gICAgICAgICAgICAgICAgICAgIGlmIChtaW5JbmRleCA9PT0gbWF4SW5kZXgpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBjdXJyZW50SXRlbSA+PSBsZWZ0ICYmIGN1cnJlbnRJdGVtIDw9IHJpZ2h0O1xuICAgICAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKGN1cnJlbnRJdGVtIDwgbGVmdCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgbWluSW5kZXggPSBjdXJyZW50SW5kZXggKyAxO1xuICAgICAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKGN1cnJlbnRJdGVtID4gcmlnaHQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIG1heEluZGV4ID0gY3VycmVudEluZGV4IC0gMTtcbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBmdW5jdGlvbiBhc2NlbmRpbmcoYSwgYikge1xuICAgICAgICAgICAgICAgIHJldHVybiBhID4gYiA/IDEgOiAtMTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSwge31dLCAxNzogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHtcbiAgICAgICAgICAgIHZhciBhcHBseVByb3BlcnRpZXMgPSByZXF1aXJlKFwiLi9hcHBseS1wcm9wZXJ0aWVzXCIpO1xuXG4gICAgICAgICAgICB2YXIgaXNXaWRnZXQgPSByZXF1aXJlKFwiLi4vdm5vZGUvaXMtd2lkZ2V0LmpzXCIpO1xuICAgICAgICAgICAgdmFyIFZQYXRjaCA9IHJlcXVpcmUoXCIuLi92bm9kZS92cGF0Y2guanNcIik7XG5cbiAgICAgICAgICAgIHZhciB1cGRhdGVXaWRnZXQgPSByZXF1aXJlKFwiLi91cGRhdGUtd2lkZ2V0XCIpO1xuXG4gICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IGFwcGx5UGF0Y2g7XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIGFwcGx5UGF0Y2godnBhdGNoLCBkb21Ob2RlLCByZW5kZXJPcHRpb25zKSB7XG4gICAgICAgICAgICAgICAgdmFyIHR5cGUgPSB2cGF0Y2gudHlwZTtcbiAgICAgICAgICAgICAgICB2YXIgdk5vZGUgPSB2cGF0Y2gudk5vZGU7XG4gICAgICAgICAgICAgICAgdmFyIHBhdGNoID0gdnBhdGNoLnBhdGNoO1xuXG4gICAgICAgICAgICAgICAgc3dpdGNoICh0eXBlKSB7XG4gICAgICAgICAgICAgICAgICAgIGNhc2UgVlBhdGNoLlJFTU9WRTpcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiByZW1vdmVOb2RlKGRvbU5vZGUsIHZOb2RlKTtcbiAgICAgICAgICAgICAgICAgICAgY2FzZSBWUGF0Y2guSU5TRVJUOlxuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGluc2VydE5vZGUoZG9tTm9kZSwgcGF0Y2gsIHJlbmRlck9wdGlvbnMpO1xuICAgICAgICAgICAgICAgICAgICBjYXNlIFZQYXRjaC5WVEVYVDpcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBzdHJpbmdQYXRjaChkb21Ob2RlLCB2Tm9kZSwgcGF0Y2gsIHJlbmRlck9wdGlvbnMpO1xuICAgICAgICAgICAgICAgICAgICBjYXNlIFZQYXRjaC5XSURHRVQ6XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gd2lkZ2V0UGF0Y2goZG9tTm9kZSwgdk5vZGUsIHBhdGNoLCByZW5kZXJPcHRpb25zKTtcbiAgICAgICAgICAgICAgICAgICAgY2FzZSBWUGF0Y2guVk5PREU6XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gdk5vZGVQYXRjaChkb21Ob2RlLCB2Tm9kZSwgcGF0Y2gsIHJlbmRlck9wdGlvbnMpO1xuICAgICAgICAgICAgICAgICAgICBjYXNlIFZQYXRjaC5PUkRFUjpcbiAgICAgICAgICAgICAgICAgICAgICAgIHJlb3JkZXJDaGlsZHJlbihkb21Ob2RlLCBwYXRjaCk7XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gZG9tTm9kZTtcbiAgICAgICAgICAgICAgICAgICAgY2FzZSBWUGF0Y2guUFJPUFM6XG4gICAgICAgICAgICAgICAgICAgICAgICBhcHBseVByb3BlcnRpZXMoZG9tTm9kZSwgcGF0Y2gsIHZOb2RlLnByb3BlcnRpZXMpO1xuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGRvbU5vZGU7XG4gICAgICAgICAgICAgICAgICAgIGNhc2UgVlBhdGNoLlRIVU5LOlxuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHJlcGxhY2VSb290KGRvbU5vZGUsIHJlbmRlck9wdGlvbnMucGF0Y2goZG9tTm9kZSwgcGF0Y2gsIHJlbmRlck9wdGlvbnMpKTtcbiAgICAgICAgICAgICAgICAgICAgZGVmYXVsdDpcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBkb21Ob2RlO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZnVuY3Rpb24gcmVtb3ZlTm9kZShkb21Ob2RlLCB2Tm9kZSkge1xuICAgICAgICAgICAgICAgIHZhciBwYXJlbnROb2RlID0gZG9tTm9kZS5wYXJlbnROb2RlO1xuXG4gICAgICAgICAgICAgICAgaWYgKHBhcmVudE5vZGUpIHtcbiAgICAgICAgICAgICAgICAgICAgcGFyZW50Tm9kZS5yZW1vdmVDaGlsZChkb21Ob2RlKTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICBkZXN0cm95V2lkZ2V0KGRvbU5vZGUsIHZOb2RlKTtcblxuICAgICAgICAgICAgICAgIHJldHVybiBudWxsO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBmdW5jdGlvbiBpbnNlcnROb2RlKHBhcmVudE5vZGUsIHZOb2RlLCByZW5kZXJPcHRpb25zKSB7XG4gICAgICAgICAgICAgICAgdmFyIG5ld05vZGUgPSByZW5kZXJPcHRpb25zLnJlbmRlcih2Tm9kZSwgcmVuZGVyT3B0aW9ucyk7XG5cbiAgICAgICAgICAgICAgICBpZiAocGFyZW50Tm9kZSkge1xuICAgICAgICAgICAgICAgICAgICBwYXJlbnROb2RlLmFwcGVuZENoaWxkKG5ld05vZGUpO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHJldHVybiBwYXJlbnROb2RlO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBmdW5jdGlvbiBzdHJpbmdQYXRjaChkb21Ob2RlLCBsZWZ0Vk5vZGUsIHZUZXh0LCByZW5kZXJPcHRpb25zKSB7XG4gICAgICAgICAgICAgICAgdmFyIG5ld05vZGU7XG5cbiAgICAgICAgICAgICAgICBpZiAoZG9tTm9kZS5ub2RlVHlwZSA9PT0gMykge1xuICAgICAgICAgICAgICAgICAgICBkb21Ob2RlLnJlcGxhY2VEYXRhKDAsIGRvbU5vZGUubGVuZ3RoLCB2VGV4dC50ZXh0KTtcbiAgICAgICAgICAgICAgICAgICAgbmV3Tm9kZSA9IGRvbU5vZGU7XG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgdmFyIHBhcmVudE5vZGUgPSBkb21Ob2RlLnBhcmVudE5vZGU7XG4gICAgICAgICAgICAgICAgICAgIG5ld05vZGUgPSByZW5kZXJPcHRpb25zLnJlbmRlcih2VGV4dCwgcmVuZGVyT3B0aW9ucyk7XG5cbiAgICAgICAgICAgICAgICAgICAgaWYgKHBhcmVudE5vZGUgJiYgbmV3Tm9kZSAhPT0gZG9tTm9kZSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgcGFyZW50Tm9kZS5yZXBsYWNlQ2hpbGQobmV3Tm9kZSwgZG9tTm9kZSk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICByZXR1cm4gbmV3Tm9kZTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZnVuY3Rpb24gd2lkZ2V0UGF0Y2goZG9tTm9kZSwgbGVmdFZOb2RlLCB3aWRnZXQsIHJlbmRlck9wdGlvbnMpIHtcbiAgICAgICAgICAgICAgICB2YXIgdXBkYXRpbmcgPSB1cGRhdGVXaWRnZXQobGVmdFZOb2RlLCB3aWRnZXQpO1xuICAgICAgICAgICAgICAgIHZhciBuZXdOb2RlO1xuXG4gICAgICAgICAgICAgICAgaWYgKHVwZGF0aW5nKSB7XG4gICAgICAgICAgICAgICAgICAgIG5ld05vZGUgPSB3aWRnZXQudXBkYXRlKGxlZnRWTm9kZSwgZG9tTm9kZSkgfHwgZG9tTm9kZTtcbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICBuZXdOb2RlID0gcmVuZGVyT3B0aW9ucy5yZW5kZXIod2lkZ2V0LCByZW5kZXJPcHRpb25zKTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICB2YXIgcGFyZW50Tm9kZSA9IGRvbU5vZGUucGFyZW50Tm9kZTtcblxuICAgICAgICAgICAgICAgIGlmIChwYXJlbnROb2RlICYmIG5ld05vZGUgIT09IGRvbU5vZGUpIHtcbiAgICAgICAgICAgICAgICAgICAgcGFyZW50Tm9kZS5yZXBsYWNlQ2hpbGQobmV3Tm9kZSwgZG9tTm9kZSk7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgaWYgKCF1cGRhdGluZykge1xuICAgICAgICAgICAgICAgICAgICBkZXN0cm95V2lkZ2V0KGRvbU5vZGUsIGxlZnRWTm9kZSk7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgcmV0dXJuIG5ld05vZGU7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIHZOb2RlUGF0Y2goZG9tTm9kZSwgbGVmdFZOb2RlLCB2Tm9kZSwgcmVuZGVyT3B0aW9ucykge1xuICAgICAgICAgICAgICAgIHZhciBwYXJlbnROb2RlID0gZG9tTm9kZS5wYXJlbnROb2RlO1xuICAgICAgICAgICAgICAgIHZhciBuZXdOb2RlID0gcmVuZGVyT3B0aW9ucy5yZW5kZXIodk5vZGUsIHJlbmRlck9wdGlvbnMpO1xuXG4gICAgICAgICAgICAgICAgaWYgKHBhcmVudE5vZGUgJiYgbmV3Tm9kZSAhPT0gZG9tTm9kZSkge1xuICAgICAgICAgICAgICAgICAgICBwYXJlbnROb2RlLnJlcGxhY2VDaGlsZChuZXdOb2RlLCBkb21Ob2RlKTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICByZXR1cm4gbmV3Tm9kZTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZnVuY3Rpb24gZGVzdHJveVdpZGdldChkb21Ob2RlLCB3KSB7XG4gICAgICAgICAgICAgICAgaWYgKHR5cGVvZiB3LmRlc3Ryb3kgPT09IFwiZnVuY3Rpb25cIiAmJiBpc1dpZGdldCh3KSkge1xuICAgICAgICAgICAgICAgICAgICB3LmRlc3Ryb3koZG9tTm9kZSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBmdW5jdGlvbiByZW9yZGVyQ2hpbGRyZW4oZG9tTm9kZSwgbW92ZXMpIHtcbiAgICAgICAgICAgICAgICB2YXIgY2hpbGROb2RlcyA9IGRvbU5vZGUuY2hpbGROb2RlcztcbiAgICAgICAgICAgICAgICB2YXIga2V5TWFwID0ge307XG4gICAgICAgICAgICAgICAgdmFyIG5vZGU7XG4gICAgICAgICAgICAgICAgdmFyIHJlbW92ZTtcbiAgICAgICAgICAgICAgICB2YXIgaW5zZXJ0O1xuXG4gICAgICAgICAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCBtb3Zlcy5yZW1vdmVzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICAgICAgICAgIHJlbW92ZSA9IG1vdmVzLnJlbW92ZXNbaV07XG4gICAgICAgICAgICAgICAgICAgIG5vZGUgPSBjaGlsZE5vZGVzW3JlbW92ZS5mcm9tXTtcbiAgICAgICAgICAgICAgICAgICAgaWYgKHJlbW92ZS5rZXkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGtleU1hcFtyZW1vdmUua2V5XSA9IG5vZGU7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgZG9tTm9kZS5yZW1vdmVDaGlsZChub2RlKTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICB2YXIgbGVuZ3RoID0gY2hpbGROb2Rlcy5sZW5ndGg7XG4gICAgICAgICAgICAgICAgZm9yICh2YXIgaiA9IDA7IGogPCBtb3Zlcy5pbnNlcnRzLmxlbmd0aDsgaisrKSB7XG4gICAgICAgICAgICAgICAgICAgIGluc2VydCA9IG1vdmVzLmluc2VydHNbal07XG4gICAgICAgICAgICAgICAgICAgIG5vZGUgPSBrZXlNYXBbaW5zZXJ0LmtleV07XG4gICAgICAgICAgICAgICAgICAgIC8vIHRoaXMgaXMgdGhlIHdlaXJkZXN0IGJ1ZyBpJ3ZlIGV2ZXIgc2VlbiBpbiB3ZWJraXRcbiAgICAgICAgICAgICAgICAgICAgZG9tTm9kZS5pbnNlcnRCZWZvcmUobm9kZSwgaW5zZXJ0LnRvID49IGxlbmd0aCsrID8gbnVsbCA6IGNoaWxkTm9kZXNbaW5zZXJ0LnRvXSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBmdW5jdGlvbiByZXBsYWNlUm9vdChvbGRSb290LCBuZXdSb290KSB7XG4gICAgICAgICAgICAgICAgaWYgKG9sZFJvb3QgJiYgbmV3Um9vdCAmJiBvbGRSb290ICE9PSBuZXdSb290ICYmIG9sZFJvb3QucGFyZW50Tm9kZSkge1xuICAgICAgICAgICAgICAgICAgICBvbGRSb290LnBhcmVudE5vZGUucmVwbGFjZUNoaWxkKG5ld1Jvb3QsIG9sZFJvb3QpO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHJldHVybiBuZXdSb290O1xuICAgICAgICAgICAgfVxuICAgICAgICB9LCB7IFwiLi4vdm5vZGUvaXMtd2lkZ2V0LmpzXCI6IDI5LCBcIi4uL3Zub2RlL3ZwYXRjaC5qc1wiOiAzMiwgXCIuL2FwcGx5LXByb3BlcnRpZXNcIjogMTQsIFwiLi91cGRhdGUtd2lkZ2V0XCI6IDE5IH1dLCAxODogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHtcbiAgICAgICAgICAgIHZhciBkb2N1bWVudCA9IHJlcXVpcmUoXCJnbG9iYWwvZG9jdW1lbnRcIik7XG4gICAgICAgICAgICB2YXIgaXNBcnJheSA9IHJlcXVpcmUoXCJ4LWlzLWFycmF5XCIpO1xuXG4gICAgICAgICAgICB2YXIgcmVuZGVyID0gcmVxdWlyZShcIi4vY3JlYXRlLWVsZW1lbnRcIik7XG4gICAgICAgICAgICB2YXIgZG9tSW5kZXggPSByZXF1aXJlKFwiLi9kb20taW5kZXhcIik7XG4gICAgICAgICAgICB2YXIgcGF0Y2hPcCA9IHJlcXVpcmUoXCIuL3BhdGNoLW9wXCIpO1xuICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBwYXRjaDtcblxuICAgICAgICAgICAgZnVuY3Rpb24gcGF0Y2gocm9vdE5vZGUsIHBhdGNoZXMsIHJlbmRlck9wdGlvbnMpIHtcbiAgICAgICAgICAgICAgICByZW5kZXJPcHRpb25zID0gcmVuZGVyT3B0aW9ucyB8fCB7fTtcbiAgICAgICAgICAgICAgICByZW5kZXJPcHRpb25zLnBhdGNoID0gcmVuZGVyT3B0aW9ucy5wYXRjaCAmJiByZW5kZXJPcHRpb25zLnBhdGNoICE9PSBwYXRjaCA/IHJlbmRlck9wdGlvbnMucGF0Y2ggOiBwYXRjaFJlY3Vyc2l2ZTtcbiAgICAgICAgICAgICAgICByZW5kZXJPcHRpb25zLnJlbmRlciA9IHJlbmRlck9wdGlvbnMucmVuZGVyIHx8IHJlbmRlcjtcblxuICAgICAgICAgICAgICAgIHJldHVybiByZW5kZXJPcHRpb25zLnBhdGNoKHJvb3ROb2RlLCBwYXRjaGVzLCByZW5kZXJPcHRpb25zKTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZnVuY3Rpb24gcGF0Y2hSZWN1cnNpdmUocm9vdE5vZGUsIHBhdGNoZXMsIHJlbmRlck9wdGlvbnMpIHtcbiAgICAgICAgICAgICAgICB2YXIgaW5kaWNlcyA9IHBhdGNoSW5kaWNlcyhwYXRjaGVzKTtcblxuICAgICAgICAgICAgICAgIGlmIChpbmRpY2VzLmxlbmd0aCA9PT0gMCkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gcm9vdE5vZGU7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgdmFyIGluZGV4ID0gZG9tSW5kZXgocm9vdE5vZGUsIHBhdGNoZXMuYSwgaW5kaWNlcyk7XG4gICAgICAgICAgICAgICAgdmFyIG93bmVyRG9jdW1lbnQgPSByb290Tm9kZS5vd25lckRvY3VtZW50O1xuXG4gICAgICAgICAgICAgICAgaWYgKCFyZW5kZXJPcHRpb25zLmRvY3VtZW50ICYmIG93bmVyRG9jdW1lbnQgIT09IGRvY3VtZW50KSB7XG4gICAgICAgICAgICAgICAgICAgIHJlbmRlck9wdGlvbnMuZG9jdW1lbnQgPSBvd25lckRvY3VtZW50O1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgaW5kaWNlcy5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgICAgICAgICB2YXIgbm9kZUluZGV4ID0gaW5kaWNlc1tpXTtcbiAgICAgICAgICAgICAgICAgICAgcm9vdE5vZGUgPSBhcHBseVBhdGNoKHJvb3ROb2RlLCBpbmRleFtub2RlSW5kZXhdLCBwYXRjaGVzW25vZGVJbmRleF0sIHJlbmRlck9wdGlvbnMpO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHJldHVybiByb290Tm9kZTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZnVuY3Rpb24gYXBwbHlQYXRjaChyb290Tm9kZSwgZG9tTm9kZSwgcGF0Y2hMaXN0LCByZW5kZXJPcHRpb25zKSB7XG4gICAgICAgICAgICAgICAgaWYgKCFkb21Ob2RlKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiByb290Tm9kZTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICB2YXIgbmV3Tm9kZTtcblxuICAgICAgICAgICAgICAgIGlmIChpc0FycmF5KHBhdGNoTGlzdCkpIHtcbiAgICAgICAgICAgICAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCBwYXRjaExpc3QubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIG5ld05vZGUgPSBwYXRjaE9wKHBhdGNoTGlzdFtpXSwgZG9tTm9kZSwgcmVuZGVyT3B0aW9ucyk7XG5cbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChkb21Ob2RlID09PSByb290Tm9kZSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJvb3ROb2RlID0gbmV3Tm9kZTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIG5ld05vZGUgPSBwYXRjaE9wKHBhdGNoTGlzdCwgZG9tTm9kZSwgcmVuZGVyT3B0aW9ucyk7XG5cbiAgICAgICAgICAgICAgICAgICAgaWYgKGRvbU5vZGUgPT09IHJvb3ROb2RlKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICByb290Tm9kZSA9IG5ld05vZGU7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICByZXR1cm4gcm9vdE5vZGU7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIHBhdGNoSW5kaWNlcyhwYXRjaGVzKSB7XG4gICAgICAgICAgICAgICAgdmFyIGluZGljZXMgPSBbXTtcblxuICAgICAgICAgICAgICAgIGZvciAodmFyIGtleSBpbiBwYXRjaGVzKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmIChrZXkgIT09IFwiYVwiKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBpbmRpY2VzLnB1c2goTnVtYmVyKGtleSkpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgcmV0dXJuIGluZGljZXM7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0sIHsgXCIuL2NyZWF0ZS1lbGVtZW50XCI6IDE1LCBcIi4vZG9tLWluZGV4XCI6IDE2LCBcIi4vcGF0Y2gtb3BcIjogMTcsIFwiZ2xvYmFsL2RvY3VtZW50XCI6IDEwLCBcIngtaXMtYXJyYXlcIjogMTIgfV0sIDE5OiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge1xuICAgICAgICAgICAgdmFyIGlzV2lkZ2V0ID0gcmVxdWlyZShcIi4uL3Zub2RlL2lzLXdpZGdldC5qc1wiKTtcblxuICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSB1cGRhdGVXaWRnZXQ7XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIHVwZGF0ZVdpZGdldChhLCBiKSB7XG4gICAgICAgICAgICAgICAgaWYgKGlzV2lkZ2V0KGEpICYmIGlzV2lkZ2V0KGIpKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmIChcIm5hbWVcIiBpbiBhICYmIFwibmFtZVwiIGluIGIpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBhLmlkID09PSBiLmlkO1xuICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGEuaW5pdCA9PT0gYi5pbml0O1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICAgICAgfVxuICAgICAgICB9LCB7IFwiLi4vdm5vZGUvaXMtd2lkZ2V0LmpzXCI6IDI5IH1dLCAyMDogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHtcbiAgICAgICAgICAgIFwidXNlIHN0cmljdFwiO1xuXG4gICAgICAgICAgICB2YXIgRXZTdG9yZSA9IHJlcXVpcmUoXCJldi1zdG9yZVwiKTtcblxuICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBFdkhvb2s7XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIEV2SG9vayh2YWx1ZSkge1xuICAgICAgICAgICAgICAgIGlmICghKHRoaXMgaW5zdGFuY2VvZiBFdkhvb2spKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBuZXcgRXZIb29rKHZhbHVlKTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICB0aGlzLnZhbHVlID0gdmFsdWU7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIEV2SG9vay5wcm90b3R5cGUuaG9vayA9IGZ1bmN0aW9uIChub2RlLCBwcm9wZXJ0eU5hbWUpIHtcbiAgICAgICAgICAgICAgICB2YXIgZXMgPSBFdlN0b3JlKG5vZGUpO1xuICAgICAgICAgICAgICAgIHZhciBwcm9wTmFtZSA9IHByb3BlcnR5TmFtZS5zdWJzdHIoMyk7XG5cbiAgICAgICAgICAgICAgICBlc1twcm9wTmFtZV0gPSB0aGlzLnZhbHVlO1xuICAgICAgICAgICAgfTtcblxuICAgICAgICAgICAgRXZIb29rLnByb3RvdHlwZS51bmhvb2sgPSBmdW5jdGlvbiAobm9kZSwgcHJvcGVydHlOYW1lKSB7XG4gICAgICAgICAgICAgICAgdmFyIGVzID0gRXZTdG9yZShub2RlKTtcbiAgICAgICAgICAgICAgICB2YXIgcHJvcE5hbWUgPSBwcm9wZXJ0eU5hbWUuc3Vic3RyKDMpO1xuXG4gICAgICAgICAgICAgICAgZXNbcHJvcE5hbWVdID0gdW5kZWZpbmVkO1xuICAgICAgICAgICAgfTtcbiAgICAgICAgfSwgeyBcImV2LXN0b3JlXCI6IDcgfV0sIDIxOiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge1xuICAgICAgICAgICAgXCJ1c2Ugc3RyaWN0XCI7XG5cbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gU29mdFNldEhvb2s7XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIFNvZnRTZXRIb29rKHZhbHVlKSB7XG4gICAgICAgICAgICAgICAgaWYgKCEodGhpcyBpbnN0YW5jZW9mIFNvZnRTZXRIb29rKSkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gbmV3IFNvZnRTZXRIb29rKHZhbHVlKTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICB0aGlzLnZhbHVlID0gdmFsdWU7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIFNvZnRTZXRIb29rLnByb3RvdHlwZS5ob29rID0gZnVuY3Rpb24gKG5vZGUsIHByb3BlcnR5TmFtZSkge1xuICAgICAgICAgICAgICAgIGlmIChub2RlW3Byb3BlcnR5TmFtZV0gIT09IHRoaXMudmFsdWUpIHtcbiAgICAgICAgICAgICAgICAgICAgbm9kZVtwcm9wZXJ0eU5hbWVdID0gdGhpcy52YWx1ZTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9O1xuICAgICAgICB9LCB7fV0sIDIyOiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge1xuICAgICAgICAgICAgXCJ1c2Ugc3RyaWN0XCI7XG5cbiAgICAgICAgICAgIHZhciBpc0FycmF5ID0gcmVxdWlyZShcIngtaXMtYXJyYXlcIik7XG5cbiAgICAgICAgICAgIHZhciBWTm9kZSA9IHJlcXVpcmUoXCIuLi92bm9kZS92bm9kZS5qc1wiKTtcbiAgICAgICAgICAgIHZhciBWVGV4dCA9IHJlcXVpcmUoXCIuLi92bm9kZS92dGV4dC5qc1wiKTtcbiAgICAgICAgICAgIHZhciBpc1ZOb2RlID0gcmVxdWlyZShcIi4uL3Zub2RlL2lzLXZub2RlXCIpO1xuICAgICAgICAgICAgdmFyIGlzVlRleHQgPSByZXF1aXJlKFwiLi4vdm5vZGUvaXMtdnRleHRcIik7XG4gICAgICAgICAgICB2YXIgaXNXaWRnZXQgPSByZXF1aXJlKFwiLi4vdm5vZGUvaXMtd2lkZ2V0XCIpO1xuICAgICAgICAgICAgdmFyIGlzSG9vayA9IHJlcXVpcmUoXCIuLi92bm9kZS9pcy12aG9va1wiKTtcbiAgICAgICAgICAgIHZhciBpc1ZUaHVuayA9IHJlcXVpcmUoXCIuLi92bm9kZS9pcy10aHVua1wiKTtcblxuICAgICAgICAgICAgdmFyIHBhcnNlVGFnID0gcmVxdWlyZShcIi4vcGFyc2UtdGFnLmpzXCIpO1xuICAgICAgICAgICAgdmFyIHNvZnRTZXRIb29rID0gcmVxdWlyZShcIi4vaG9va3Mvc29mdC1zZXQtaG9vay5qc1wiKTtcbiAgICAgICAgICAgIHZhciBldkhvb2sgPSByZXF1aXJlKFwiLi9ob29rcy9ldi1ob29rLmpzXCIpO1xuXG4gICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IGg7XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIGgodGFnTmFtZSwgcHJvcGVydGllcywgY2hpbGRyZW4pIHtcbiAgICAgICAgICAgICAgICB2YXIgY2hpbGROb2RlcyA9IFtdO1xuICAgICAgICAgICAgICAgIHZhciB0YWcsIHByb3BzLCBrZXksIG5hbWVzcGFjZTtcblxuICAgICAgICAgICAgICAgIGlmICghY2hpbGRyZW4gJiYgaXNDaGlsZHJlbihwcm9wZXJ0aWVzKSkge1xuICAgICAgICAgICAgICAgICAgICBjaGlsZHJlbiA9IHByb3BlcnRpZXM7XG4gICAgICAgICAgICAgICAgICAgIHByb3BzID0ge307XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgcHJvcHMgPSBwcm9wcyB8fCBwcm9wZXJ0aWVzIHx8IHt9O1xuICAgICAgICAgICAgICAgIHRhZyA9IHBhcnNlVGFnKHRhZ05hbWUsIHByb3BzKTtcblxuICAgICAgICAgICAgICAgIC8vIHN1cHBvcnQga2V5c1xuICAgICAgICAgICAgICAgIGlmIChwcm9wcy5oYXNPd25Qcm9wZXJ0eShcImtleVwiKSkge1xuICAgICAgICAgICAgICAgICAgICBrZXkgPSBwcm9wcy5rZXk7XG4gICAgICAgICAgICAgICAgICAgIHByb3BzLmtleSA9IHVuZGVmaW5lZDtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAvLyBzdXBwb3J0IG5hbWVzcGFjZVxuICAgICAgICAgICAgICAgIGlmIChwcm9wcy5oYXNPd25Qcm9wZXJ0eShcIm5hbWVzcGFjZVwiKSkge1xuICAgICAgICAgICAgICAgICAgICBuYW1lc3BhY2UgPSBwcm9wcy5uYW1lc3BhY2U7XG4gICAgICAgICAgICAgICAgICAgIHByb3BzLm5hbWVzcGFjZSA9IHVuZGVmaW5lZDtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAvLyBmaXggY3Vyc29yIGJ1Z1xuICAgICAgICAgICAgICAgIGlmICh0YWcgPT09IFwiSU5QVVRcIiAmJiAhbmFtZXNwYWNlICYmIHByb3BzLmhhc093blByb3BlcnR5KFwidmFsdWVcIikgJiYgcHJvcHMudmFsdWUgIT09IHVuZGVmaW5lZCAmJiAhaXNIb29rKHByb3BzLnZhbHVlKSkge1xuICAgICAgICAgICAgICAgICAgICBwcm9wcy52YWx1ZSA9IHNvZnRTZXRIb29rKHByb3BzLnZhbHVlKTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICB0cmFuc2Zvcm1Qcm9wZXJ0aWVzKHByb3BzKTtcblxuICAgICAgICAgICAgICAgIGlmIChjaGlsZHJlbiAhPT0gdW5kZWZpbmVkICYmIGNoaWxkcmVuICE9PSBudWxsKSB7XG4gICAgICAgICAgICAgICAgICAgIGFkZENoaWxkKGNoaWxkcmVuLCBjaGlsZE5vZGVzLCB0YWcsIHByb3BzKTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICByZXR1cm4gbmV3IFZOb2RlKHRhZywgcHJvcHMsIGNoaWxkTm9kZXMsIGtleSwgbmFtZXNwYWNlKTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZnVuY3Rpb24gYWRkQ2hpbGQoYywgY2hpbGROb2RlcywgdGFnLCBwcm9wcykge1xuICAgICAgICAgICAgICAgIGlmICh0eXBlb2YgYyA9PT0gXCJzdHJpbmdcIikge1xuICAgICAgICAgICAgICAgICAgICBjaGlsZE5vZGVzLnB1c2gobmV3IFZUZXh0KGMpKTtcbiAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKHR5cGVvZiBjID09PSBcIm51bWJlclwiKSB7XG4gICAgICAgICAgICAgICAgICAgIGNoaWxkTm9kZXMucHVzaChuZXcgVlRleHQoU3RyaW5nKGMpKSk7XG4gICAgICAgICAgICAgICAgfSBlbHNlIGlmIChpc0NoaWxkKGMpKSB7XG4gICAgICAgICAgICAgICAgICAgIGNoaWxkTm9kZXMucHVzaChjKTtcbiAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKGlzQXJyYXkoYykpIHtcbiAgICAgICAgICAgICAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCBjLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBhZGRDaGlsZChjW2ldLCBjaGlsZE5vZGVzLCB0YWcsIHByb3BzKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoYyA9PT0gbnVsbCB8fCBjID09PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIHRocm93IFVuZXhwZWN0ZWRWaXJ0dWFsRWxlbWVudCh7XG4gICAgICAgICAgICAgICAgICAgICAgICBmb3JlaWduT2JqZWN0OiBjLFxuICAgICAgICAgICAgICAgICAgICAgICAgcGFyZW50Vm5vZGU6IHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0YWdOYW1lOiB0YWcsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcHJvcGVydGllczogcHJvcHNcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBmdW5jdGlvbiB0cmFuc2Zvcm1Qcm9wZXJ0aWVzKHByb3BzKSB7XG4gICAgICAgICAgICAgICAgZm9yICh2YXIgcHJvcE5hbWUgaW4gcHJvcHMpIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKHByb3BzLmhhc093blByb3BlcnR5KHByb3BOYW1lKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgdmFyIHZhbHVlID0gcHJvcHNbcHJvcE5hbWVdO1xuXG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoaXNIb29rKHZhbHVlKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnRpbnVlO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAocHJvcE5hbWUuc3Vic3RyKDAsIDMpID09PSBcImV2LVwiKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gYWRkIGV2LWZvbyBzdXBwb3J0XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcHJvcHNbcHJvcE5hbWVdID0gZXZIb29rKHZhbHVlKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZnVuY3Rpb24gaXNDaGlsZCh4KSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGlzVk5vZGUoeCkgfHwgaXNWVGV4dCh4KSB8fCBpc1dpZGdldCh4KSB8fCBpc1ZUaHVuayh4KTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZnVuY3Rpb24gaXNDaGlsZHJlbih4KSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHR5cGVvZiB4ID09PSBcInN0cmluZ1wiIHx8IGlzQXJyYXkoeCkgfHwgaXNDaGlsZCh4KTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZnVuY3Rpb24gVW5leHBlY3RlZFZpcnR1YWxFbGVtZW50KGRhdGEpIHtcbiAgICAgICAgICAgICAgICB2YXIgZXJyID0gbmV3IEVycm9yKCk7XG5cbiAgICAgICAgICAgICAgICBlcnIudHlwZSA9IFwidmlydHVhbC1oeXBlcnNjcmlwdC51bmV4cGVjdGVkLnZpcnR1YWwtZWxlbWVudFwiO1xuICAgICAgICAgICAgICAgIGVyci5tZXNzYWdlID0gXCJVbmV4cGVjdGVkIHZpcnR1YWwgY2hpbGQgcGFzc2VkIHRvIGgoKS5cXG5cIiArIFwiRXhwZWN0ZWQgYSBWTm9kZSAvIFZ0aHVuayAvIFZXaWRnZXQgLyBzdHJpbmcgYnV0OlxcblwiICsgXCJnb3Q6XFxuXCIgKyBlcnJvclN0cmluZyhkYXRhLmZvcmVpZ25PYmplY3QpICsgXCIuXFxuXCIgKyBcIlRoZSBwYXJlbnQgdm5vZGUgaXM6XFxuXCIgKyBlcnJvclN0cmluZyhkYXRhLnBhcmVudFZub2RlKTtcbiAgICAgICAgICAgICAgICBcIlxcblwiICsgXCJTdWdnZXN0ZWQgZml4OiBjaGFuZ2UgeW91ciBgaCguLi4sIFsgLi4uIF0pYCBjYWxsc2l0ZS5cIjtcbiAgICAgICAgICAgICAgICBlcnIuZm9yZWlnbk9iamVjdCA9IGRhdGEuZm9yZWlnbk9iamVjdDtcbiAgICAgICAgICAgICAgICBlcnIucGFyZW50Vm5vZGUgPSBkYXRhLnBhcmVudFZub2RlO1xuXG4gICAgICAgICAgICAgICAgcmV0dXJuIGVycjtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZnVuY3Rpb24gZXJyb3JTdHJpbmcob2JqKSB7XG4gICAgICAgICAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIEpTT04uc3RyaW5naWZ5KG9iaiwgbnVsbCwgXCIgICAgXCIpO1xuICAgICAgICAgICAgICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIFN0cmluZyhvYmopO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgfSwgeyBcIi4uL3Zub2RlL2lzLXRodW5rXCI6IDI1LCBcIi4uL3Zub2RlL2lzLXZob29rXCI6IDI2LCBcIi4uL3Zub2RlL2lzLXZub2RlXCI6IDI3LCBcIi4uL3Zub2RlL2lzLXZ0ZXh0XCI6IDI4LCBcIi4uL3Zub2RlL2lzLXdpZGdldFwiOiAyOSwgXCIuLi92bm9kZS92bm9kZS5qc1wiOiAzMSwgXCIuLi92bm9kZS92dGV4dC5qc1wiOiAzMywgXCIuL2hvb2tzL2V2LWhvb2suanNcIjogMjAsIFwiLi9ob29rcy9zb2Z0LXNldC1ob29rLmpzXCI6IDIxLCBcIi4vcGFyc2UtdGFnLmpzXCI6IDIzLCBcIngtaXMtYXJyYXlcIjogMTIgfV0sIDIzOiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge1xuICAgICAgICAgICAgXCJ1c2Ugc3RyaWN0XCI7XG5cbiAgICAgICAgICAgIHZhciBzcGxpdCA9IHJlcXVpcmUoXCJicm93c2VyLXNwbGl0XCIpO1xuXG4gICAgICAgICAgICB2YXIgY2xhc3NJZFNwbGl0ID0gLyhbXFwuI10/W2EtekEtWjAtOVxcdTAwN0YtXFx1RkZGRl86LV0rKS87XG4gICAgICAgICAgICB2YXIgbm90Q2xhc3NJZCA9IC9eXFwufCMvO1xuXG4gICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IHBhcnNlVGFnO1xuXG4gICAgICAgICAgICBmdW5jdGlvbiBwYXJzZVRhZyh0YWcsIHByb3BzKSB7XG4gICAgICAgICAgICAgICAgaWYgKCF0YWcpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIFwiRElWXCI7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgdmFyIG5vSWQgPSAhcHJvcHMuaGFzT3duUHJvcGVydHkoXCJpZFwiKTtcblxuICAgICAgICAgICAgICAgIHZhciB0YWdQYXJ0cyA9IHNwbGl0KHRhZywgY2xhc3NJZFNwbGl0KTtcbiAgICAgICAgICAgICAgICB2YXIgdGFnTmFtZSA9IG51bGw7XG5cbiAgICAgICAgICAgICAgICBpZiAobm90Q2xhc3NJZC50ZXN0KHRhZ1BhcnRzWzFdKSkge1xuICAgICAgICAgICAgICAgICAgICB0YWdOYW1lID0gXCJESVZcIjtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICB2YXIgY2xhc3NlcywgcGFydCwgdHlwZSwgaTtcblxuICAgICAgICAgICAgICAgIGZvciAoaSA9IDA7IGkgPCB0YWdQYXJ0cy5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgICAgICAgICBwYXJ0ID0gdGFnUGFydHNbaV07XG5cbiAgICAgICAgICAgICAgICAgICAgaWYgKCFwYXJ0KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBjb250aW51ZTtcbiAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgIHR5cGUgPSBwYXJ0LmNoYXJBdCgwKTtcblxuICAgICAgICAgICAgICAgICAgICBpZiAoIXRhZ05hbWUpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHRhZ05hbWUgPSBwYXJ0O1xuICAgICAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKHR5cGUgPT09IFwiLlwiKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBjbGFzc2VzID0gY2xhc3NlcyB8fCBbXTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGNsYXNzZXMucHVzaChwYXJ0LnN1YnN0cmluZygxLCBwYXJ0Lmxlbmd0aCkpO1xuICAgICAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKHR5cGUgPT09IFwiI1wiICYmIG5vSWQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHByb3BzLmlkID0gcGFydC5zdWJzdHJpbmcoMSwgcGFydC5sZW5ndGgpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgaWYgKGNsYXNzZXMpIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKHByb3BzLmNsYXNzTmFtZSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgY2xhc3Nlcy5wdXNoKHByb3BzLmNsYXNzTmFtZSk7XG4gICAgICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgICAgICBwcm9wcy5jbGFzc05hbWUgPSBjbGFzc2VzLmpvaW4oXCIgXCIpO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHJldHVybiBwcm9wcy5uYW1lc3BhY2UgPyB0YWdOYW1lIDogdGFnTmFtZS50b1VwcGVyQ2FzZSgpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9LCB7IFwiYnJvd3Nlci1zcGxpdFwiOiA1IH1dLCAyNDogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHtcbiAgICAgICAgICAgIHZhciBpc1ZOb2RlID0gcmVxdWlyZShcIi4vaXMtdm5vZGVcIik7XG4gICAgICAgICAgICB2YXIgaXNWVGV4dCA9IHJlcXVpcmUoXCIuL2lzLXZ0ZXh0XCIpO1xuICAgICAgICAgICAgdmFyIGlzV2lkZ2V0ID0gcmVxdWlyZShcIi4vaXMtd2lkZ2V0XCIpO1xuICAgICAgICAgICAgdmFyIGlzVGh1bmsgPSByZXF1aXJlKFwiLi9pcy10aHVua1wiKTtcblxuICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBoYW5kbGVUaHVuaztcblxuICAgICAgICAgICAgZnVuY3Rpb24gaGFuZGxlVGh1bmsoYSwgYikge1xuICAgICAgICAgICAgICAgIHZhciByZW5kZXJlZEEgPSBhO1xuICAgICAgICAgICAgICAgIHZhciByZW5kZXJlZEIgPSBiO1xuXG4gICAgICAgICAgICAgICAgaWYgKGlzVGh1bmsoYikpIHtcbiAgICAgICAgICAgICAgICAgICAgcmVuZGVyZWRCID0gcmVuZGVyVGh1bmsoYiwgYSk7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgaWYgKGlzVGh1bmsoYSkpIHtcbiAgICAgICAgICAgICAgICAgICAgcmVuZGVyZWRBID0gcmVuZGVyVGh1bmsoYSwgbnVsbCk7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgICAgICAgICAgYTogcmVuZGVyZWRBLFxuICAgICAgICAgICAgICAgICAgICBiOiByZW5kZXJlZEJcbiAgICAgICAgICAgICAgICB9O1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBmdW5jdGlvbiByZW5kZXJUaHVuayh0aHVuaywgcHJldmlvdXMpIHtcbiAgICAgICAgICAgICAgICB2YXIgcmVuZGVyZWRUaHVuayA9IHRodW5rLnZub2RlO1xuXG4gICAgICAgICAgICAgICAgaWYgKCFyZW5kZXJlZFRodW5rKSB7XG4gICAgICAgICAgICAgICAgICAgIHJlbmRlcmVkVGh1bmsgPSB0aHVuay52bm9kZSA9IHRodW5rLnJlbmRlcihwcmV2aW91cyk7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgaWYgKCEoaXNWTm9kZShyZW5kZXJlZFRodW5rKSB8fCBpc1ZUZXh0KHJlbmRlcmVkVGh1bmspIHx8IGlzV2lkZ2V0KHJlbmRlcmVkVGh1bmspKSkge1xuICAgICAgICAgICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoXCJ0aHVuayBkaWQgbm90IHJldHVybiBhIHZhbGlkIG5vZGVcIik7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgcmV0dXJuIHJlbmRlcmVkVGh1bms7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0sIHsgXCIuL2lzLXRodW5rXCI6IDI1LCBcIi4vaXMtdm5vZGVcIjogMjcsIFwiLi9pcy12dGV4dFwiOiAyOCwgXCIuL2lzLXdpZGdldFwiOiAyOSB9XSwgMjU6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IGlzVGh1bms7XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIGlzVGh1bmsodCkge1xuICAgICAgICAgICAgICAgIHJldHVybiB0ICYmIHQudHlwZSA9PT0gXCJUaHVua1wiO1xuICAgICAgICAgICAgfVxuICAgICAgICB9LCB7fV0sIDI2OiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge1xuICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBpc0hvb2s7XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIGlzSG9vayhob29rKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGhvb2sgJiYgKHR5cGVvZiBob29rLmhvb2sgPT09IFwiZnVuY3Rpb25cIiAmJiAhaG9vay5oYXNPd25Qcm9wZXJ0eShcImhvb2tcIikgfHwgdHlwZW9mIGhvb2sudW5ob29rID09PSBcImZ1bmN0aW9uXCIgJiYgIWhvb2suaGFzT3duUHJvcGVydHkoXCJ1bmhvb2tcIikpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9LCB7fV0sIDI3OiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge1xuICAgICAgICAgICAgdmFyIHZlcnNpb24gPSByZXF1aXJlKFwiLi92ZXJzaW9uXCIpO1xuXG4gICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IGlzVmlydHVhbE5vZGU7XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIGlzVmlydHVhbE5vZGUoeCkge1xuICAgICAgICAgICAgICAgIHJldHVybiB4ICYmIHgudHlwZSA9PT0gXCJWaXJ0dWFsTm9kZVwiICYmIHgudmVyc2lvbiA9PT0gdmVyc2lvbjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSwgeyBcIi4vdmVyc2lvblwiOiAzMCB9XSwgMjg6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICB2YXIgdmVyc2lvbiA9IHJlcXVpcmUoXCIuL3ZlcnNpb25cIik7XG5cbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gaXNWaXJ0dWFsVGV4dDtcblxuICAgICAgICAgICAgZnVuY3Rpb24gaXNWaXJ0dWFsVGV4dCh4KSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHggJiYgeC50eXBlID09PSBcIlZpcnR1YWxUZXh0XCIgJiYgeC52ZXJzaW9uID09PSB2ZXJzaW9uO1xuICAgICAgICAgICAgfVxuICAgICAgICB9LCB7IFwiLi92ZXJzaW9uXCI6IDMwIH1dLCAyOTogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHtcbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gaXNXaWRnZXQ7XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIGlzV2lkZ2V0KHcpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gdyAmJiB3LnR5cGUgPT09IFwiV2lkZ2V0XCI7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0sIHt9XSwgMzA6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IFwiMlwiO1xuICAgICAgICB9LCB7fV0sIDMxOiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge1xuICAgICAgICAgICAgdmFyIHZlcnNpb24gPSByZXF1aXJlKFwiLi92ZXJzaW9uXCIpO1xuICAgICAgICAgICAgdmFyIGlzVk5vZGUgPSByZXF1aXJlKFwiLi9pcy12bm9kZVwiKTtcbiAgICAgICAgICAgIHZhciBpc1dpZGdldCA9IHJlcXVpcmUoXCIuL2lzLXdpZGdldFwiKTtcbiAgICAgICAgICAgIHZhciBpc1RodW5rID0gcmVxdWlyZShcIi4vaXMtdGh1bmtcIik7XG4gICAgICAgICAgICB2YXIgaXNWSG9vayA9IHJlcXVpcmUoXCIuL2lzLXZob29rXCIpO1xuXG4gICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IFZpcnR1YWxOb2RlO1xuXG4gICAgICAgICAgICB2YXIgbm9Qcm9wZXJ0aWVzID0ge307XG4gICAgICAgICAgICB2YXIgbm9DaGlsZHJlbiA9IFtdO1xuXG4gICAgICAgICAgICBmdW5jdGlvbiBWaXJ0dWFsTm9kZSh0YWdOYW1lLCBwcm9wZXJ0aWVzLCBjaGlsZHJlbiwga2V5LCBuYW1lc3BhY2UpIHtcbiAgICAgICAgICAgICAgICB0aGlzLnRhZ05hbWUgPSB0YWdOYW1lO1xuICAgICAgICAgICAgICAgIHRoaXMucHJvcGVydGllcyA9IHByb3BlcnRpZXMgfHwgbm9Qcm9wZXJ0aWVzO1xuICAgICAgICAgICAgICAgIHRoaXMuY2hpbGRyZW4gPSBjaGlsZHJlbiB8fCBub0NoaWxkcmVuO1xuICAgICAgICAgICAgICAgIHRoaXMua2V5ID0ga2V5ICE9IG51bGwgPyBTdHJpbmcoa2V5KSA6IHVuZGVmaW5lZDtcbiAgICAgICAgICAgICAgICB0aGlzLm5hbWVzcGFjZSA9IHR5cGVvZiBuYW1lc3BhY2UgPT09IFwic3RyaW5nXCIgPyBuYW1lc3BhY2UgOiBudWxsO1xuXG4gICAgICAgICAgICAgICAgdmFyIGNvdW50ID0gY2hpbGRyZW4gJiYgY2hpbGRyZW4ubGVuZ3RoIHx8IDA7XG4gICAgICAgICAgICAgICAgdmFyIGRlc2NlbmRhbnRzID0gMDtcbiAgICAgICAgICAgICAgICB2YXIgaGFzV2lkZ2V0cyA9IGZhbHNlO1xuICAgICAgICAgICAgICAgIHZhciBoYXNUaHVua3MgPSBmYWxzZTtcbiAgICAgICAgICAgICAgICB2YXIgZGVzY2VuZGFudEhvb2tzID0gZmFsc2U7XG4gICAgICAgICAgICAgICAgdmFyIGhvb2tzO1xuXG4gICAgICAgICAgICAgICAgZm9yICh2YXIgcHJvcE5hbWUgaW4gcHJvcGVydGllcykge1xuICAgICAgICAgICAgICAgICAgICBpZiAocHJvcGVydGllcy5oYXNPd25Qcm9wZXJ0eShwcm9wTmFtZSkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHZhciBwcm9wZXJ0eSA9IHByb3BlcnRpZXNbcHJvcE5hbWVdO1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGlzVkhvb2socHJvcGVydHkpICYmIHByb3BlcnR5LnVuaG9vaykge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmICghaG9va3MpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaG9va3MgPSB7fTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBob29rc1twcm9wTmFtZV0gPSBwcm9wZXJ0eTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgY291bnQ7IGkrKykge1xuICAgICAgICAgICAgICAgICAgICB2YXIgY2hpbGQgPSBjaGlsZHJlbltpXTtcbiAgICAgICAgICAgICAgICAgICAgaWYgKGlzVk5vZGUoY2hpbGQpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBkZXNjZW5kYW50cyArPSBjaGlsZC5jb3VudCB8fCAwO1xuXG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoIWhhc1dpZGdldHMgJiYgY2hpbGQuaGFzV2lkZ2V0cykge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGhhc1dpZGdldHMgPSB0cnVlO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoIWhhc1RodW5rcyAmJiBjaGlsZC5oYXNUaHVua3MpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBoYXNUaHVua3MgPSB0cnVlO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoIWRlc2NlbmRhbnRIb29rcyAmJiAoY2hpbGQuaG9va3MgfHwgY2hpbGQuZGVzY2VuZGFudEhvb2tzKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRlc2NlbmRhbnRIb29rcyA9IHRydWU7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoIWhhc1dpZGdldHMgJiYgaXNXaWRnZXQoY2hpbGQpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAodHlwZW9mIGNoaWxkLmRlc3Ryb3kgPT09IFwiZnVuY3Rpb25cIikge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGhhc1dpZGdldHMgPSB0cnVlO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKCFoYXNUaHVua3MgJiYgaXNUaHVuayhjaGlsZCkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGhhc1RodW5rcyA9IHRydWU7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICB0aGlzLmNvdW50ID0gY291bnQgKyBkZXNjZW5kYW50cztcbiAgICAgICAgICAgICAgICB0aGlzLmhhc1dpZGdldHMgPSBoYXNXaWRnZXRzO1xuICAgICAgICAgICAgICAgIHRoaXMuaGFzVGh1bmtzID0gaGFzVGh1bmtzO1xuICAgICAgICAgICAgICAgIHRoaXMuaG9va3MgPSBob29rcztcbiAgICAgICAgICAgICAgICB0aGlzLmRlc2NlbmRhbnRIb29rcyA9IGRlc2NlbmRhbnRIb29rcztcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgVmlydHVhbE5vZGUucHJvdG90eXBlLnZlcnNpb24gPSB2ZXJzaW9uO1xuICAgICAgICAgICAgVmlydHVhbE5vZGUucHJvdG90eXBlLnR5cGUgPSBcIlZpcnR1YWxOb2RlXCI7XG4gICAgICAgIH0sIHsgXCIuL2lzLXRodW5rXCI6IDI1LCBcIi4vaXMtdmhvb2tcIjogMjYsIFwiLi9pcy12bm9kZVwiOiAyNywgXCIuL2lzLXdpZGdldFwiOiAyOSwgXCIuL3ZlcnNpb25cIjogMzAgfV0sIDMyOiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge1xuICAgICAgICAgICAgdmFyIHZlcnNpb24gPSByZXF1aXJlKFwiLi92ZXJzaW9uXCIpO1xuXG4gICAgICAgICAgICBWaXJ0dWFsUGF0Y2guTk9ORSA9IDA7XG4gICAgICAgICAgICBWaXJ0dWFsUGF0Y2guVlRFWFQgPSAxO1xuICAgICAgICAgICAgVmlydHVhbFBhdGNoLlZOT0RFID0gMjtcbiAgICAgICAgICAgIFZpcnR1YWxQYXRjaC5XSURHRVQgPSAzO1xuICAgICAgICAgICAgVmlydHVhbFBhdGNoLlBST1BTID0gNDtcbiAgICAgICAgICAgIFZpcnR1YWxQYXRjaC5PUkRFUiA9IDU7XG4gICAgICAgICAgICBWaXJ0dWFsUGF0Y2guSU5TRVJUID0gNjtcbiAgICAgICAgICAgIFZpcnR1YWxQYXRjaC5SRU1PVkUgPSA3O1xuICAgICAgICAgICAgVmlydHVhbFBhdGNoLlRIVU5LID0gODtcblxuICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBWaXJ0dWFsUGF0Y2g7XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIFZpcnR1YWxQYXRjaCh0eXBlLCB2Tm9kZSwgcGF0Y2gpIHtcbiAgICAgICAgICAgICAgICB0aGlzLnR5cGUgPSBOdW1iZXIodHlwZSk7XG4gICAgICAgICAgICAgICAgdGhpcy52Tm9kZSA9IHZOb2RlO1xuICAgICAgICAgICAgICAgIHRoaXMucGF0Y2ggPSBwYXRjaDtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgVmlydHVhbFBhdGNoLnByb3RvdHlwZS52ZXJzaW9uID0gdmVyc2lvbjtcbiAgICAgICAgICAgIFZpcnR1YWxQYXRjaC5wcm90b3R5cGUudHlwZSA9IFwiVmlydHVhbFBhdGNoXCI7XG4gICAgICAgIH0sIHsgXCIuL3ZlcnNpb25cIjogMzAgfV0sIDMzOiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge1xuICAgICAgICAgICAgdmFyIHZlcnNpb24gPSByZXF1aXJlKFwiLi92ZXJzaW9uXCIpO1xuXG4gICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IFZpcnR1YWxUZXh0O1xuXG4gICAgICAgICAgICBmdW5jdGlvbiBWaXJ0dWFsVGV4dCh0ZXh0KSB7XG4gICAgICAgICAgICAgICAgdGhpcy50ZXh0ID0gU3RyaW5nKHRleHQpO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBWaXJ0dWFsVGV4dC5wcm90b3R5cGUudmVyc2lvbiA9IHZlcnNpb247XG4gICAgICAgICAgICBWaXJ0dWFsVGV4dC5wcm90b3R5cGUudHlwZSA9IFwiVmlydHVhbFRleHRcIjtcbiAgICAgICAgfSwgeyBcIi4vdmVyc2lvblwiOiAzMCB9XSwgMzQ6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICB2YXIgaXNPYmplY3QgPSByZXF1aXJlKFwiaXMtb2JqZWN0XCIpO1xuICAgICAgICAgICAgdmFyIGlzSG9vayA9IHJlcXVpcmUoXCIuLi92bm9kZS9pcy12aG9va1wiKTtcblxuICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBkaWZmUHJvcHM7XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIGRpZmZQcm9wcyhhLCBiKSB7XG4gICAgICAgICAgICAgICAgdmFyIGRpZmY7XG5cbiAgICAgICAgICAgICAgICBmb3IgKHZhciBhS2V5IGluIGEpIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKCEoYUtleSBpbiBiKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgZGlmZiA9IGRpZmYgfHwge307XG4gICAgICAgICAgICAgICAgICAgICAgICBkaWZmW2FLZXldID0gdW5kZWZpbmVkO1xuICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgdmFyIGFWYWx1ZSA9IGFbYUtleV07XG4gICAgICAgICAgICAgICAgICAgIHZhciBiVmFsdWUgPSBiW2FLZXldO1xuXG4gICAgICAgICAgICAgICAgICAgIGlmIChhVmFsdWUgPT09IGJWYWx1ZSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgY29udGludWU7XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoaXNPYmplY3QoYVZhbHVlKSAmJiBpc09iamVjdChiVmFsdWUpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoZ2V0UHJvdG90eXBlKGJWYWx1ZSkgIT09IGdldFByb3RvdHlwZShhVmFsdWUpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgZGlmZiA9IGRpZmYgfHwge307XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgZGlmZlthS2V5XSA9IGJWYWx1ZTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoaXNIb29rKGJWYWx1ZSkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBkaWZmID0gZGlmZiB8fCB7fTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBkaWZmW2FLZXldID0gYlZhbHVlO1xuICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB2YXIgb2JqZWN0RGlmZiA9IGRpZmZQcm9wcyhhVmFsdWUsIGJWYWx1ZSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKG9iamVjdERpZmYpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZGlmZiA9IGRpZmYgfHwge307XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRpZmZbYUtleV0gPSBvYmplY3REaWZmO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGRpZmYgPSBkaWZmIHx8IHt9O1xuICAgICAgICAgICAgICAgICAgICAgICAgZGlmZlthS2V5XSA9IGJWYWx1ZTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIGZvciAodmFyIGJLZXkgaW4gYikge1xuICAgICAgICAgICAgICAgICAgICBpZiAoIShiS2V5IGluIGEpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBkaWZmID0gZGlmZiB8fCB7fTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGRpZmZbYktleV0gPSBiW2JLZXldO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgcmV0dXJuIGRpZmY7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIGdldFByb3RvdHlwZSh2YWx1ZSkge1xuICAgICAgICAgICAgICAgIGlmIChPYmplY3QuZ2V0UHJvdG90eXBlT2YpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIE9iamVjdC5nZXRQcm90b3R5cGVPZih2YWx1ZSk7XG4gICAgICAgICAgICAgICAgfSBlbHNlIGlmICh2YWx1ZS5fX3Byb3RvX18pIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHZhbHVlLl9fcHJvdG9fXztcbiAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKHZhbHVlLmNvbnN0cnVjdG9yKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiB2YWx1ZS5jb25zdHJ1Y3Rvci5wcm90b3R5cGU7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9LCB7IFwiLi4vdm5vZGUvaXMtdmhvb2tcIjogMjYsIFwiaXMtb2JqZWN0XCI6IDExIH1dLCAzNTogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHtcbiAgICAgICAgICAgIHZhciBpc0FycmF5ID0gcmVxdWlyZShcIngtaXMtYXJyYXlcIik7XG5cbiAgICAgICAgICAgIHZhciBWUGF0Y2ggPSByZXF1aXJlKFwiLi4vdm5vZGUvdnBhdGNoXCIpO1xuICAgICAgICAgICAgdmFyIGlzVk5vZGUgPSByZXF1aXJlKFwiLi4vdm5vZGUvaXMtdm5vZGVcIik7XG4gICAgICAgICAgICB2YXIgaXNWVGV4dCA9IHJlcXVpcmUoXCIuLi92bm9kZS9pcy12dGV4dFwiKTtcbiAgICAgICAgICAgIHZhciBpc1dpZGdldCA9IHJlcXVpcmUoXCIuLi92bm9kZS9pcy13aWRnZXRcIik7XG4gICAgICAgICAgICB2YXIgaXNUaHVuayA9IHJlcXVpcmUoXCIuLi92bm9kZS9pcy10aHVua1wiKTtcbiAgICAgICAgICAgIHZhciBoYW5kbGVUaHVuayA9IHJlcXVpcmUoXCIuLi92bm9kZS9oYW5kbGUtdGh1bmtcIik7XG5cbiAgICAgICAgICAgIHZhciBkaWZmUHJvcHMgPSByZXF1aXJlKFwiLi9kaWZmLXByb3BzXCIpO1xuXG4gICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IGRpZmY7XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIGRpZmYoYSwgYikge1xuICAgICAgICAgICAgICAgIHZhciBwYXRjaCA9IHsgYTogYSB9O1xuICAgICAgICAgICAgICAgIHdhbGsoYSwgYiwgcGF0Y2gsIDApO1xuICAgICAgICAgICAgICAgIHJldHVybiBwYXRjaDtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZnVuY3Rpb24gd2FsayhhLCBiLCBwYXRjaCwgaW5kZXgpIHtcbiAgICAgICAgICAgICAgICBpZiAoYSA9PT0gYikge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgdmFyIGFwcGx5ID0gcGF0Y2hbaW5kZXhdO1xuICAgICAgICAgICAgICAgIHZhciBhcHBseUNsZWFyID0gZmFsc2U7XG5cbiAgICAgICAgICAgICAgICBpZiAoaXNUaHVuayhhKSB8fCBpc1RodW5rKGIpKSB7XG4gICAgICAgICAgICAgICAgICAgIHRodW5rcyhhLCBiLCBwYXRjaCwgaW5kZXgpO1xuICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoYiA9PSBudWxsKSB7XG5cbiAgICAgICAgICAgICAgICAgICAgLy8gSWYgYSBpcyBhIHdpZGdldCB3ZSB3aWxsIGFkZCBhIHJlbW92ZSBwYXRjaCBmb3IgaXRcbiAgICAgICAgICAgICAgICAgICAgLy8gT3RoZXJ3aXNlIGFueSBjaGlsZCB3aWRnZXRzL2hvb2tzIG11c3QgYmUgZGVzdHJveWVkLlxuICAgICAgICAgICAgICAgICAgICAvLyBUaGlzIHByZXZlbnRzIGFkZGluZyB0d28gcmVtb3ZlIHBhdGNoZXMgZm9yIGEgd2lkZ2V0LlxuICAgICAgICAgICAgICAgICAgICBpZiAoIWlzV2lkZ2V0KGEpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBjbGVhclN0YXRlKGEsIHBhdGNoLCBpbmRleCk7XG4gICAgICAgICAgICAgICAgICAgICAgICBhcHBseSA9IHBhdGNoW2luZGV4XTtcbiAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgIGFwcGx5ID0gYXBwZW5kUGF0Y2goYXBwbHksIG5ldyBWUGF0Y2goVlBhdGNoLlJFTU9WRSwgYSwgYikpO1xuICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoaXNWTm9kZShiKSkge1xuICAgICAgICAgICAgICAgICAgICBpZiAoaXNWTm9kZShhKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGEudGFnTmFtZSA9PT0gYi50YWdOYW1lICYmIGEubmFtZXNwYWNlID09PSBiLm5hbWVzcGFjZSAmJiBhLmtleSA9PT0gYi5rZXkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB2YXIgcHJvcHNQYXRjaCA9IGRpZmZQcm9wcyhhLnByb3BlcnRpZXMsIGIucHJvcGVydGllcyk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHByb3BzUGF0Y2gpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYXBwbHkgPSBhcHBlbmRQYXRjaChhcHBseSwgbmV3IFZQYXRjaChWUGF0Y2guUFJPUFMsIGEsIHByb3BzUGF0Y2gpKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgYXBwbHkgPSBkaWZmQ2hpbGRyZW4oYSwgYiwgcGF0Y2gsIGFwcGx5LCBpbmRleCk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGFwcGx5ID0gYXBwZW5kUGF0Y2goYXBwbHksIG5ldyBWUGF0Y2goVlBhdGNoLlZOT0RFLCBhLCBiKSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgYXBwbHlDbGVhciA9IHRydWU7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBhcHBseSA9IGFwcGVuZFBhdGNoKGFwcGx5LCBuZXcgVlBhdGNoKFZQYXRjaC5WTk9ERSwgYSwgYikpO1xuICAgICAgICAgICAgICAgICAgICAgICAgYXBwbHlDbGVhciA9IHRydWU7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKGlzVlRleHQoYikpIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKCFpc1ZUZXh0KGEpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBhcHBseSA9IGFwcGVuZFBhdGNoKGFwcGx5LCBuZXcgVlBhdGNoKFZQYXRjaC5WVEVYVCwgYSwgYikpO1xuICAgICAgICAgICAgICAgICAgICAgICAgYXBwbHlDbGVhciA9IHRydWU7XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoYS50ZXh0ICE9PSBiLnRleHQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGFwcGx5ID0gYXBwZW5kUGF0Y2goYXBwbHksIG5ldyBWUGF0Y2goVlBhdGNoLlZURVhULCBhLCBiKSk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKGlzV2lkZ2V0KGIpKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmICghaXNXaWRnZXQoYSkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGFwcGx5Q2xlYXIgPSB0cnVlO1xuICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgYXBwbHkgPSBhcHBlbmRQYXRjaChhcHBseSwgbmV3IFZQYXRjaChWUGF0Y2guV0lER0VULCBhLCBiKSk7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgaWYgKGFwcGx5KSB7XG4gICAgICAgICAgICAgICAgICAgIHBhdGNoW2luZGV4XSA9IGFwcGx5O1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIGlmIChhcHBseUNsZWFyKSB7XG4gICAgICAgICAgICAgICAgICAgIGNsZWFyU3RhdGUoYSwgcGF0Y2gsIGluZGV4KTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIGRpZmZDaGlsZHJlbihhLCBiLCBwYXRjaCwgYXBwbHksIGluZGV4KSB7XG4gICAgICAgICAgICAgICAgdmFyIGFDaGlsZHJlbiA9IGEuY2hpbGRyZW47XG4gICAgICAgICAgICAgICAgdmFyIG9yZGVyZWRTZXQgPSByZW9yZGVyKGFDaGlsZHJlbiwgYi5jaGlsZHJlbik7XG4gICAgICAgICAgICAgICAgdmFyIGJDaGlsZHJlbiA9IG9yZGVyZWRTZXQuY2hpbGRyZW47XG5cbiAgICAgICAgICAgICAgICB2YXIgYUxlbiA9IGFDaGlsZHJlbi5sZW5ndGg7XG4gICAgICAgICAgICAgICAgdmFyIGJMZW4gPSBiQ2hpbGRyZW4ubGVuZ3RoO1xuICAgICAgICAgICAgICAgIHZhciBsZW4gPSBhTGVuID4gYkxlbiA/IGFMZW4gOiBiTGVuO1xuXG4gICAgICAgICAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCBsZW47IGkrKykge1xuICAgICAgICAgICAgICAgICAgICB2YXIgbGVmdE5vZGUgPSBhQ2hpbGRyZW5baV07XG4gICAgICAgICAgICAgICAgICAgIHZhciByaWdodE5vZGUgPSBiQ2hpbGRyZW5baV07XG4gICAgICAgICAgICAgICAgICAgIGluZGV4ICs9IDE7XG5cbiAgICAgICAgICAgICAgICAgICAgaWYgKCFsZWZ0Tm9kZSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHJpZ2h0Tm9kZSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIEV4Y2VzcyBub2RlcyBpbiBiIG5lZWQgdG8gYmUgYWRkZWRcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBhcHBseSA9IGFwcGVuZFBhdGNoKGFwcGx5LCBuZXcgVlBhdGNoKFZQYXRjaC5JTlNFUlQsIG51bGwsIHJpZ2h0Tm9kZSkpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgd2FsayhsZWZ0Tm9kZSwgcmlnaHROb2RlLCBwYXRjaCwgaW5kZXgpO1xuICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgaWYgKGlzVk5vZGUobGVmdE5vZGUpICYmIGxlZnROb2RlLmNvdW50KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBpbmRleCArPSBsZWZ0Tm9kZS5jb3VudDtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIGlmIChvcmRlcmVkU2V0Lm1vdmVzKSB7XG4gICAgICAgICAgICAgICAgICAgIC8vIFJlb3JkZXIgbm9kZXMgbGFzdFxuICAgICAgICAgICAgICAgICAgICBhcHBseSA9IGFwcGVuZFBhdGNoKGFwcGx5LCBuZXcgVlBhdGNoKFZQYXRjaC5PUkRFUiwgYSwgb3JkZXJlZFNldC5tb3ZlcykpO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHJldHVybiBhcHBseTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZnVuY3Rpb24gY2xlYXJTdGF0ZSh2Tm9kZSwgcGF0Y2gsIGluZGV4KSB7XG4gICAgICAgICAgICAgICAgLy8gVE9ETzogTWFrZSB0aGlzIGEgc2luZ2xlIHdhbGssIG5vdCB0d29cbiAgICAgICAgICAgICAgICB1bmhvb2sodk5vZGUsIHBhdGNoLCBpbmRleCk7XG4gICAgICAgICAgICAgICAgZGVzdHJveVdpZGdldHModk5vZGUsIHBhdGNoLCBpbmRleCk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIC8vIFBhdGNoIHJlY29yZHMgZm9yIGFsbCBkZXN0cm95ZWQgd2lkZ2V0cyBtdXN0IGJlIGFkZGVkIGJlY2F1c2Ugd2UgbmVlZFxuICAgICAgICAgICAgLy8gYSBET00gbm9kZSByZWZlcmVuY2UgZm9yIHRoZSBkZXN0cm95IGZ1bmN0aW9uXG4gICAgICAgICAgICBmdW5jdGlvbiBkZXN0cm95V2lkZ2V0cyh2Tm9kZSwgcGF0Y2gsIGluZGV4KSB7XG4gICAgICAgICAgICAgICAgaWYgKGlzV2lkZ2V0KHZOb2RlKSkge1xuICAgICAgICAgICAgICAgICAgICBpZiAodHlwZW9mIHZOb2RlLmRlc3Ryb3kgPT09IFwiZnVuY3Rpb25cIikge1xuICAgICAgICAgICAgICAgICAgICAgICAgcGF0Y2hbaW5kZXhdID0gYXBwZW5kUGF0Y2gocGF0Y2hbaW5kZXhdLCBuZXcgVlBhdGNoKFZQYXRjaC5SRU1PVkUsIHZOb2RlLCBudWxsKSk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKGlzVk5vZGUodk5vZGUpICYmICh2Tm9kZS5oYXNXaWRnZXRzIHx8IHZOb2RlLmhhc1RodW5rcykpIHtcbiAgICAgICAgICAgICAgICAgICAgdmFyIGNoaWxkcmVuID0gdk5vZGUuY2hpbGRyZW47XG4gICAgICAgICAgICAgICAgICAgIHZhciBsZW4gPSBjaGlsZHJlbi5sZW5ndGg7XG4gICAgICAgICAgICAgICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgbGVuOyBpKyspIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHZhciBjaGlsZCA9IGNoaWxkcmVuW2ldO1xuICAgICAgICAgICAgICAgICAgICAgICAgaW5kZXggKz0gMTtcblxuICAgICAgICAgICAgICAgICAgICAgICAgZGVzdHJveVdpZGdldHMoY2hpbGQsIHBhdGNoLCBpbmRleCk7XG5cbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChpc1ZOb2RlKGNoaWxkKSAmJiBjaGlsZC5jb3VudCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGluZGV4ICs9IGNoaWxkLmNvdW50O1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfSBlbHNlIGlmIChpc1RodW5rKHZOb2RlKSkge1xuICAgICAgICAgICAgICAgICAgICB0aHVua3Modk5vZGUsIG51bGwsIHBhdGNoLCBpbmRleCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAvLyBDcmVhdGUgYSBzdWItcGF0Y2ggZm9yIHRodW5rc1xuICAgICAgICAgICAgZnVuY3Rpb24gdGh1bmtzKGEsIGIsIHBhdGNoLCBpbmRleCkge1xuICAgICAgICAgICAgICAgIHZhciBub2RlcyA9IGhhbmRsZVRodW5rKGEsIGIpO1xuICAgICAgICAgICAgICAgIHZhciB0aHVua1BhdGNoID0gZGlmZihub2Rlcy5hLCBub2Rlcy5iKTtcbiAgICAgICAgICAgICAgICBpZiAoaGFzUGF0Y2hlcyh0aHVua1BhdGNoKSkge1xuICAgICAgICAgICAgICAgICAgICBwYXRjaFtpbmRleF0gPSBuZXcgVlBhdGNoKFZQYXRjaC5USFVOSywgbnVsbCwgdGh1bmtQYXRjaCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBmdW5jdGlvbiBoYXNQYXRjaGVzKHBhdGNoKSB7XG4gICAgICAgICAgICAgICAgZm9yICh2YXIgaW5kZXggaW4gcGF0Y2gpIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKGluZGV4ICE9PSBcImFcIikge1xuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIC8vIEV4ZWN1dGUgaG9va3Mgd2hlbiB0d28gbm9kZXMgYXJlIGlkZW50aWNhbFxuICAgICAgICAgICAgZnVuY3Rpb24gdW5ob29rKHZOb2RlLCBwYXRjaCwgaW5kZXgpIHtcbiAgICAgICAgICAgICAgICBpZiAoaXNWTm9kZSh2Tm9kZSkpIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKHZOb2RlLmhvb2tzKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBwYXRjaFtpbmRleF0gPSBhcHBlbmRQYXRjaChwYXRjaFtpbmRleF0sIG5ldyBWUGF0Y2goVlBhdGNoLlBST1BTLCB2Tm9kZSwgdW5kZWZpbmVkS2V5cyh2Tm9kZS5ob29rcykpKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgIGlmICh2Tm9kZS5kZXNjZW5kYW50SG9va3MgfHwgdk5vZGUuaGFzVGh1bmtzKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICB2YXIgY2hpbGRyZW4gPSB2Tm9kZS5jaGlsZHJlbjtcbiAgICAgICAgICAgICAgICAgICAgICAgIHZhciBsZW4gPSBjaGlsZHJlbi5sZW5ndGg7XG4gICAgICAgICAgICAgICAgICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IGxlbjsgaSsrKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdmFyIGNoaWxkID0gY2hpbGRyZW5baV07XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaW5kZXggKz0gMTtcblxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHVuaG9vayhjaGlsZCwgcGF0Y2gsIGluZGV4KTtcblxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChpc1ZOb2RlKGNoaWxkKSAmJiBjaGlsZC5jb3VudCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpbmRleCArPSBjaGlsZC5jb3VudDtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKGlzVGh1bmsodk5vZGUpKSB7XG4gICAgICAgICAgICAgICAgICAgIHRodW5rcyh2Tm9kZSwgbnVsbCwgcGF0Y2gsIGluZGV4KTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIHVuZGVmaW5lZEtleXMob2JqKSB7XG4gICAgICAgICAgICAgICAgdmFyIHJlc3VsdCA9IHt9O1xuXG4gICAgICAgICAgICAgICAgZm9yICh2YXIga2V5IGluIG9iaikge1xuICAgICAgICAgICAgICAgICAgICByZXN1bHRba2V5XSA9IHVuZGVmaW5lZDtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICByZXR1cm4gcmVzdWx0O1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAvLyBMaXN0IGRpZmYsIG5haXZlIGxlZnQgdG8gcmlnaHQgcmVvcmRlcmluZ1xuICAgICAgICAgICAgZnVuY3Rpb24gcmVvcmRlcihhQ2hpbGRyZW4sIGJDaGlsZHJlbikge1xuICAgICAgICAgICAgICAgIC8vIE8oTSkgdGltZSwgTyhNKSBtZW1vcnlcbiAgICAgICAgICAgICAgICB2YXIgYkNoaWxkSW5kZXggPSBrZXlJbmRleChiQ2hpbGRyZW4pO1xuICAgICAgICAgICAgICAgIHZhciBiS2V5cyA9IGJDaGlsZEluZGV4LmtleXM7XG4gICAgICAgICAgICAgICAgdmFyIGJGcmVlID0gYkNoaWxkSW5kZXguZnJlZTtcblxuICAgICAgICAgICAgICAgIGlmIChiRnJlZS5sZW5ndGggPT09IGJDaGlsZHJlbi5sZW5ndGgpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGNoaWxkcmVuOiBiQ2hpbGRyZW4sXG4gICAgICAgICAgICAgICAgICAgICAgICBtb3ZlczogbnVsbFxuICAgICAgICAgICAgICAgICAgICB9O1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIC8vIE8oTikgdGltZSwgTyhOKSBtZW1vcnlcbiAgICAgICAgICAgICAgICB2YXIgYUNoaWxkSW5kZXggPSBrZXlJbmRleChhQ2hpbGRyZW4pO1xuICAgICAgICAgICAgICAgIHZhciBhS2V5cyA9IGFDaGlsZEluZGV4LmtleXM7XG4gICAgICAgICAgICAgICAgdmFyIGFGcmVlID0gYUNoaWxkSW5kZXguZnJlZTtcblxuICAgICAgICAgICAgICAgIGlmIChhRnJlZS5sZW5ndGggPT09IGFDaGlsZHJlbi5sZW5ndGgpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGNoaWxkcmVuOiBiQ2hpbGRyZW4sXG4gICAgICAgICAgICAgICAgICAgICAgICBtb3ZlczogbnVsbFxuICAgICAgICAgICAgICAgICAgICB9O1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIC8vIE8oTUFYKE4sIE0pKSBtZW1vcnlcbiAgICAgICAgICAgICAgICB2YXIgbmV3Q2hpbGRyZW4gPSBbXTtcblxuICAgICAgICAgICAgICAgIHZhciBmcmVlSW5kZXggPSAwO1xuICAgICAgICAgICAgICAgIHZhciBmcmVlQ291bnQgPSBiRnJlZS5sZW5ndGg7XG4gICAgICAgICAgICAgICAgdmFyIGRlbGV0ZWRJdGVtcyA9IDA7XG5cbiAgICAgICAgICAgICAgICAvLyBJdGVyYXRlIHRocm91Z2ggYSBhbmQgbWF0Y2ggYSBub2RlIGluIGJcbiAgICAgICAgICAgICAgICAvLyBPKE4pIHRpbWUsXG4gICAgICAgICAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCBhQ2hpbGRyZW4ubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgICAgICAgICAgdmFyIGFJdGVtID0gYUNoaWxkcmVuW2ldO1xuICAgICAgICAgICAgICAgICAgICB2YXIgaXRlbUluZGV4O1xuXG4gICAgICAgICAgICAgICAgICAgIGlmIChhSXRlbS5rZXkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChiS2V5cy5oYXNPd25Qcm9wZXJ0eShhSXRlbS5rZXkpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gTWF0Y2ggdXAgdGhlIG9sZCBrZXlzXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaXRlbUluZGV4ID0gYktleXNbYUl0ZW0ua2V5XTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBuZXdDaGlsZHJlbi5wdXNoKGJDaGlsZHJlbltpdGVtSW5kZXhdKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gUmVtb3ZlIG9sZCBrZXllZCBpdGVtc1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGl0ZW1JbmRleCA9IGkgLSBkZWxldGVkSXRlbXMrKztcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBuZXdDaGlsZHJlbi5wdXNoKG51bGwpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgLy8gTWF0Y2ggdGhlIGl0ZW0gaW4gYSB3aXRoIHRoZSBuZXh0IGZyZWUgaXRlbSBpbiBiXG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoZnJlZUluZGV4IDwgZnJlZUNvdW50KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaXRlbUluZGV4ID0gYkZyZWVbZnJlZUluZGV4KytdO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIG5ld0NoaWxkcmVuLnB1c2goYkNoaWxkcmVuW2l0ZW1JbmRleF0pO1xuICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBUaGVyZSBhcmUgbm8gZnJlZSBpdGVtcyBpbiBiIHRvIG1hdGNoIHdpdGhcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyB0aGUgZnJlZSBpdGVtcyBpbiBhLCBzbyB0aGUgZXh0cmEgZnJlZSBub2Rlc1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIGFyZSBkZWxldGVkLlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGl0ZW1JbmRleCA9IGkgLSBkZWxldGVkSXRlbXMrKztcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBuZXdDaGlsZHJlbi5wdXNoKG51bGwpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgdmFyIGxhc3RGcmVlSW5kZXggPSBmcmVlSW5kZXggPj0gYkZyZWUubGVuZ3RoID8gYkNoaWxkcmVuLmxlbmd0aCA6IGJGcmVlW2ZyZWVJbmRleF07XG5cbiAgICAgICAgICAgICAgICAvLyBJdGVyYXRlIHRocm91Z2ggYiBhbmQgYXBwZW5kIGFueSBuZXcga2V5c1xuICAgICAgICAgICAgICAgIC8vIE8oTSkgdGltZVxuICAgICAgICAgICAgICAgIGZvciAodmFyIGogPSAwOyBqIDwgYkNoaWxkcmVuLmxlbmd0aDsgaisrKSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciBuZXdJdGVtID0gYkNoaWxkcmVuW2pdO1xuXG4gICAgICAgICAgICAgICAgICAgIGlmIChuZXdJdGVtLmtleSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKCFhS2V5cy5oYXNPd25Qcm9wZXJ0eShuZXdJdGVtLmtleSkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBBZGQgYW55IG5ldyBrZXllZCBpdGVtc1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIFdlIGFyZSBhZGRpbmcgbmV3IGl0ZW1zIHRvIHRoZSBlbmQgYW5kIHRoZW4gc29ydGluZyB0aGVtXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gaW4gcGxhY2UuIEluIGZ1dHVyZSB3ZSBzaG91bGQgaW5zZXJ0IG5ldyBpdGVtcyBpbiBwbGFjZS5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBuZXdDaGlsZHJlbi5wdXNoKG5ld0l0ZW0pO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKGogPj0gbGFzdEZyZWVJbmRleCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgLy8gQWRkIGFueSBsZWZ0b3ZlciBub24ta2V5ZWQgaXRlbXNcbiAgICAgICAgICAgICAgICAgICAgICAgIG5ld0NoaWxkcmVuLnB1c2gobmV3SXRlbSk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICB2YXIgc2ltdWxhdGUgPSBuZXdDaGlsZHJlbi5zbGljZSgpO1xuICAgICAgICAgICAgICAgIHZhciBzaW11bGF0ZUluZGV4ID0gMDtcbiAgICAgICAgICAgICAgICB2YXIgcmVtb3ZlcyA9IFtdO1xuICAgICAgICAgICAgICAgIHZhciBpbnNlcnRzID0gW107XG4gICAgICAgICAgICAgICAgdmFyIHNpbXVsYXRlSXRlbTtcblxuICAgICAgICAgICAgICAgIGZvciAodmFyIGsgPSAwOyBrIDwgYkNoaWxkcmVuLmxlbmd0aDspIHtcbiAgICAgICAgICAgICAgICAgICAgdmFyIHdhbnRlZEl0ZW0gPSBiQ2hpbGRyZW5ba107XG4gICAgICAgICAgICAgICAgICAgIHNpbXVsYXRlSXRlbSA9IHNpbXVsYXRlW3NpbXVsYXRlSW5kZXhdO1xuXG4gICAgICAgICAgICAgICAgICAgIC8vIHJlbW92ZSBpdGVtc1xuICAgICAgICAgICAgICAgICAgICB3aGlsZSAoc2ltdWxhdGVJdGVtID09PSBudWxsICYmIHNpbXVsYXRlLmxlbmd0aCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgcmVtb3Zlcy5wdXNoKHJlbW92ZShzaW11bGF0ZSwgc2ltdWxhdGVJbmRleCwgbnVsbCkpO1xuICAgICAgICAgICAgICAgICAgICAgICAgc2ltdWxhdGVJdGVtID0gc2ltdWxhdGVbc2ltdWxhdGVJbmRleF07XG4gICAgICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgICAgICBpZiAoIXNpbXVsYXRlSXRlbSB8fCBzaW11bGF0ZUl0ZW0ua2V5ICE9PSB3YW50ZWRJdGVtLmtleSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgLy8gaWYgd2UgbmVlZCBhIGtleSBpbiB0aGlzIHBvc2l0aW9uLi4uXG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAod2FudGVkSXRlbS5rZXkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoc2ltdWxhdGVJdGVtICYmIHNpbXVsYXRlSXRlbS5rZXkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gaWYgYW4gaW5zZXJ0IGRvZXNuJ3QgcHV0IHRoaXMga2V5IGluIHBsYWNlLCBpdCBuZWVkcyB0byBtb3ZlXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChiS2V5c1tzaW11bGF0ZUl0ZW0ua2V5XSAhPT0gayArIDEpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlbW92ZXMucHVzaChyZW1vdmUoc2ltdWxhdGUsIHNpbXVsYXRlSW5kZXgsIHNpbXVsYXRlSXRlbS5rZXkpKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNpbXVsYXRlSXRlbSA9IHNpbXVsYXRlW3NpbXVsYXRlSW5kZXhdO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gaWYgdGhlIHJlbW92ZSBkaWRuJ3QgcHV0IHRoZSB3YW50ZWQgaXRlbSBpbiBwbGFjZSwgd2UgbmVlZCB0byBpbnNlcnQgaXRcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmICghc2ltdWxhdGVJdGVtIHx8IHNpbXVsYXRlSXRlbS5rZXkgIT09IHdhbnRlZEl0ZW0ua2V5KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaW5zZXJ0cy5wdXNoKHsga2V5OiB3YW50ZWRJdGVtLmtleSwgdG86IGsgfSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBpdGVtcyBhcmUgbWF0Y2hpbmcsIHNvIHNraXAgYWhlYWRcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNpbXVsYXRlSW5kZXgrKztcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGluc2VydHMucHVzaCh7IGtleTogd2FudGVkSXRlbS5rZXksIHRvOiBrIH0pO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaW5zZXJ0cy5wdXNoKHsga2V5OiB3YW50ZWRJdGVtLmtleSwgdG86IGsgfSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGsrKztcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIGEga2V5IGluIHNpbXVsYXRlIGhhcyBubyBtYXRjaGluZyB3YW50ZWQga2V5LCByZW1vdmUgaXRcbiAgICAgICAgICAgICAgICAgICAgICAgIGVsc2UgaWYgKHNpbXVsYXRlSXRlbSAmJiBzaW11bGF0ZUl0ZW0ua2V5KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcmVtb3Zlcy5wdXNoKHJlbW92ZShzaW11bGF0ZSwgc2ltdWxhdGVJbmRleCwgc2ltdWxhdGVJdGVtLmtleSkpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgc2ltdWxhdGVJbmRleCsrO1xuICAgICAgICAgICAgICAgICAgICAgICAgaysrO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgLy8gcmVtb3ZlIGFsbCB0aGUgcmVtYWluaW5nIG5vZGVzIGZyb20gc2ltdWxhdGVcbiAgICAgICAgICAgICAgICB3aGlsZSAoc2ltdWxhdGVJbmRleCA8IHNpbXVsYXRlLmxlbmd0aCkge1xuICAgICAgICAgICAgICAgICAgICBzaW11bGF0ZUl0ZW0gPSBzaW11bGF0ZVtzaW11bGF0ZUluZGV4XTtcbiAgICAgICAgICAgICAgICAgICAgcmVtb3Zlcy5wdXNoKHJlbW92ZShzaW11bGF0ZSwgc2ltdWxhdGVJbmRleCwgc2ltdWxhdGVJdGVtICYmIHNpbXVsYXRlSXRlbS5rZXkpKTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAvLyBJZiB0aGUgb25seSBtb3ZlcyB3ZSBoYXZlIGFyZSBkZWxldGVzIHRoZW4gd2UgY2FuIGp1c3RcbiAgICAgICAgICAgICAgICAvLyBsZXQgdGhlIGRlbGV0ZSBwYXRjaCByZW1vdmUgdGhlc2UgaXRlbXMuXG4gICAgICAgICAgICAgICAgaWYgKHJlbW92ZXMubGVuZ3RoID09PSBkZWxldGVkSXRlbXMgJiYgIWluc2VydHMubGVuZ3RoKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiB7XG4gICAgICAgICAgICAgICAgICAgICAgICBjaGlsZHJlbjogbmV3Q2hpbGRyZW4sXG4gICAgICAgICAgICAgICAgICAgICAgICBtb3ZlczogbnVsbFxuICAgICAgICAgICAgICAgICAgICB9O1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHJldHVybiB7XG4gICAgICAgICAgICAgICAgICAgIGNoaWxkcmVuOiBuZXdDaGlsZHJlbixcbiAgICAgICAgICAgICAgICAgICAgbW92ZXM6IHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJlbW92ZXM6IHJlbW92ZXMsXG4gICAgICAgICAgICAgICAgICAgICAgICBpbnNlcnRzOiBpbnNlcnRzXG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9O1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBmdW5jdGlvbiByZW1vdmUoYXJyLCBpbmRleCwga2V5KSB7XG4gICAgICAgICAgICAgICAgYXJyLnNwbGljZShpbmRleCwgMSk7XG5cbiAgICAgICAgICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgICAgICAgICBmcm9tOiBpbmRleCxcbiAgICAgICAgICAgICAgICAgICAga2V5OiBrZXlcbiAgICAgICAgICAgICAgICB9O1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBmdW5jdGlvbiBrZXlJbmRleChjaGlsZHJlbikge1xuICAgICAgICAgICAgICAgIHZhciBrZXlzID0ge307XG4gICAgICAgICAgICAgICAgdmFyIGZyZWUgPSBbXTtcbiAgICAgICAgICAgICAgICB2YXIgbGVuZ3RoID0gY2hpbGRyZW4ubGVuZ3RoO1xuXG4gICAgICAgICAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCBsZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgICAgICAgICB2YXIgY2hpbGQgPSBjaGlsZHJlbltpXTtcblxuICAgICAgICAgICAgICAgICAgICBpZiAoY2hpbGQua2V5KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBrZXlzW2NoaWxkLmtleV0gPSBpO1xuICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgZnJlZS5wdXNoKGkpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgICAgICAgICAga2V5czoga2V5cywgLy8gQSBoYXNoIG9mIGtleSBuYW1lIHRvIGluZGV4XG4gICAgICAgICAgICAgICAgICAgIGZyZWU6IGZyZWUgLy8gQW4gYXJyYXkgb2YgdW5rZXllZCBpdGVtIGluZGljZXNcbiAgICAgICAgICAgICAgICB9O1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBmdW5jdGlvbiBhcHBlbmRQYXRjaChhcHBseSwgcGF0Y2gpIHtcbiAgICAgICAgICAgICAgICBpZiAoYXBwbHkpIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKGlzQXJyYXkoYXBwbHkpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBhcHBseS5wdXNoKHBhdGNoKTtcbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGFwcGx5ID0gW2FwcGx5LCBwYXRjaF07XG4gICAgICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgICAgICByZXR1cm4gYXBwbHk7XG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHBhdGNoO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgfSwgeyBcIi4uL3Zub2RlL2hhbmRsZS10aHVua1wiOiAyNCwgXCIuLi92bm9kZS9pcy10aHVua1wiOiAyNSwgXCIuLi92bm9kZS9pcy12bm9kZVwiOiAyNywgXCIuLi92bm9kZS9pcy12dGV4dFwiOiAyOCwgXCIuLi92bm9kZS9pcy13aWRnZXRcIjogMjksIFwiLi4vdm5vZGUvdnBhdGNoXCI6IDMyLCBcIi4vZGlmZi1wcm9wc1wiOiAzNCwgXCJ4LWlzLWFycmF5XCI6IDEyIH1dIH0sIHt9LCBbNF0pKDQpO1xufSk7XG5cblxuLy8gUHJvcG9zZWQgZm9yIEVTNlxuXG5jb25zdCBzdGFydCA9IGZ1bmN0aW9uIChkb21Sb290LCByZW5kZXJGbiwgaW5pdGlhbFN0YXRlLCBvcHRpb25zID0gW10pIHtcbiAgY29uc3QgbmFtZSA9IEtleXdvcmQuaGFzX2tleV9fcW1fXyhvcHRpb25zLCBLZXJuZWwuU3BlY2lhbEZvcm1zLmF0b20oJ25hbWUnKSkgPyBLZXl3b3JkLmdldChvcHRpb25zLCBLZXJuZWwuU3BlY2lhbEZvcm1zLmF0b20oJ25hbWUnKSkgOiBTeW1ib2woKTtcblxuICBzZWxmLnBvc3Rfb2ZmaWNlLmFkZF9tYWlsYm94KG5hbWUpO1xuXG4gIGNvbnN0IHRyZWUgPSByZW5kZXJGbi5hcHBseSh0aGlzLCBpbml0aWFsU3RhdGUpO1xuICBjb25zdCByb290Tm9kZSA9IHZpcnR1YWxEb20uY3JlYXRlKHRyZWUpO1xuXG4gIGRvbVJvb3QuYXBwZW5kQ2hpbGQocm9vdE5vZGUpO1xuICBzZWxmLnBvc3Rfb2ZmaWNlLnNlbmQobmFtZSwgS2VybmVsLlNwZWNpYWxGb3Jtcy50dXBsZShyb290Tm9kZSwgdHJlZSwgcmVuZGVyRm4pKTtcblxuICByZXR1cm4gS2VybmVsLlNwZWNpYWxGb3Jtcy50dXBsZShLZXJuZWwuU3BlY2lhbEZvcm1zLmF0b20oJ29rJyksIG5hbWUpO1xufTtcblxuY29uc3Qgc3RvcCA9IGZ1bmN0aW9uIChhZ2VudCwgdGltZW91dCA9IDUwMDApIHtcbiAgc2VsZi5wb3N0X29mZmljZS5yZW1vdmVfbWFpbGJveChhZ2VudCk7XG4gIHJldHVybiBLZXJuZWwuU3BlY2lhbEZvcm1zLmF0b20oJ29rJyk7XG59O1xuXG5jb25zdCByZW5kZXIgPSBmdW5jdGlvbiAoYWdlbnQsIHN0YXRlKSB7XG5cbiAgY29uc3QgY3VycmVudF9zdGF0ZSA9IHNlbGYucG9zdF9vZmZpY2UucmVjZWl2ZShhZ2VudCk7XG5cbiAgbGV0IHJvb3ROb2RlID0gS2VybmVsLmVsZW0oY3VycmVudF9zdGF0ZSwgMCk7XG4gIGxldCB0cmVlID0gS2VybmVsLmVsZW0oY3VycmVudF9zdGF0ZSwgMSk7XG4gIGxldCByZW5kZXJGbiA9IEtlcm5lbC5lbGVtKGN1cnJlbnRfc3RhdGUsIDIpO1xuXG4gIGxldCBuZXdUcmVlID0gcmVuZGVyRm4uYXBwbHkodGhpcywgc3RhdGUpO1xuXG4gIGxldCBwYXRjaGVzID0gdmlydHVhbERvbS5kaWZmKHRyZWUsIG5ld1RyZWUpO1xuICByb290Tm9kZSA9IHZpcnR1YWxEb20ucGF0Y2gocm9vdE5vZGUsIHBhdGNoZXMpO1xuXG4gIHNlbGYucG9zdF9vZmZpY2Uuc2VuZChhZ2VudCwgS2VybmVsLlNwZWNpYWxGb3Jtcy50dXBsZShyb290Tm9kZSwgbmV3VHJlZSwgcmVuZGVyRm4pKTtcblxuICByZXR1cm4gS2VybmVsLlNwZWNpYWxGb3Jtcy5hdG9tKCdvaycpO1xufTtcblxudmFyIFZpZXcgPSB7XG4gIHN0YXJ0LFxuICBzdG9wLFxuICByZW5kZXJcbn07XG5cbnNlbGYucG9zdF9vZmZpY2UgPSBzZWxmLnBvc3Rfb2ZmaWNlIHx8IG5ldyBQb3N0T2ZmaWNlKCk7XG5cbmV4cG9ydCB7IF9QYXR0ZXJucyBhcyBQYXR0ZXJucywgQml0U3RyaW5nLCBLZXJuZWwsIEF0b20sIEVudW0sIEludGVnZXIsIEpTLCBMaXN0LCBSYW5nZSwgVHVwbGUsIEFnZW50LCBLZXl3b3JkLCBCYXNlLCBfU3RyaW5nIGFzIFN0cmluZywgQml0d2lzZSwgRW51bWVyYWJsZSwgQ29sbGVjdGFibGUsIEluc3BlY3QsIF9NYXAgYXMgTWFwLCBfU2V0IGFzIFNldCwgTWFwU2V0LCBJbnRlZ2VyVHlwZSwgRmxvYXRUeXBlLCB2aXJ0dWFsRG9tIGFzIFZpcnR1YWxET00sIFZpZXcgfTsiXSwiZmlsZSI6ImVsaXhpci5qcyIsInNvdXJjZVJvb3QiOiIvc291cmNlLyJ9 \ No newline at end of file +export { Core, Patterns, BitString, Kernel, Atom, Enum, Integer, js as JS, List, Range, Tuple, Agent, Keyword, base as Base, String$1 as String, bitwise as Bitwise, Enumerable, Collectable, Inspect, map as Map, set as Set, MapSet, IntegerType, FloatType, VirtualDOM, view as View }; +//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiIiwic291cmNlcyI6WyJlbGl4aXIuanMiXSwic291cmNlc0NvbnRlbnQiOlsiLyogQGZsb3cgKi9cblxuY2xhc3MgTWFpbGJveCB7XG5cbiAgY29uc3RydWN0b3IoKSB7XG4gICAgdGhpcy5tZXNzYWdlcyA9IFtdO1xuICB9XG5cbiAgZGVsaXZlcihtZXNzYWdlKSB7XG4gICAgdGhpcy5tZXNzYWdlcy5wdXNoKG1lc3NhZ2UpO1xuICAgIHJldHVybiBtZXNzYWdlO1xuICB9XG5cbiAgZ2V0KCkge1xuICAgIHJldHVybiB0aGlzLm1lc3NhZ2VzO1xuICB9XG5cbiAgaXNFbXB0eSgpIHtcbiAgICByZXR1cm4gdGhpcy5tZXNzYWdlcy5sZW5ndGggPT09IDA7XG4gIH1cblxuICByZW1vdmVBdChpbmRleCkge1xuICAgIHRoaXMubWVzc2FnZXMuc3BsaWNlKGluZGV4LCAxKTtcbiAgfVxufVxuXG52YXIgU3RhdGVzID0ge1xuICBOT1JNQUw6IFN5bWJvbC5mb3IoXCJub3JtYWxcIiksXG4gIEtJTEw6IFN5bWJvbC5mb3IoXCJraWxsXCIpLFxuICBTVVNQRU5EOiBTeW1ib2wuZm9yKFwic3VzcGVuZFwiKSxcbiAgQ09OVElOVUU6IFN5bWJvbC5mb3IoXCJjb250aW51ZVwiKSxcbiAgUkVDRUlWRTogU3ltYm9sLmZvcihcInJlY2VpdmVcIiksXG4gIFNFTkQ6IFN5bWJvbC5mb3IoXCJzZW5kXCIpLFxuICBTTEVFUElORzogU3ltYm9sLmZvcihcInNsZWVwaW5nXCIpLFxuICBSVU5OSU5HOiBTeW1ib2wuZm9yKFwicnVubmluZ1wiKSxcbiAgU1VTUEVOREVEOiBTeW1ib2wuZm9yKFwic3VzcGVuZGVkXCIpLFxuICBTVE9QUEVEOiBTeW1ib2wuZm9yKFwic3RvcHBlZFwiKSxcbiAgU0xFRVA6IFN5bWJvbC5mb3IoXCJzbGVlcFwiKSxcbiAgRVhJVDogU3ltYm9sLmZvcihcImV4aXRcIiksXG4gIE5PTUFUQ0g6IFN5bWJvbC5mb3IoXCJub19tYXRjaFwiKVxufTtcblxuY2xhc3MgUHJvY2VzcyB7XG5cbiAgY29uc3RydWN0b3IocGlkLCBtYWlsYm94KSB7XG4gICAgdGhpcy5waWQgPSBwaWQ7XG4gICAgdGhpcy5tYWlsYm94ID0gbWFpbGJveDtcbiAgICB0aGlzLnN0YXR1cyA9IFN0YXRlcy5TVE9QUEVEO1xuICAgIHRoaXMuZGljdCA9IHt9O1xuICB9XG59XG5cbmNsYXNzIFR1cGxlJDEge1xuXG4gIGNvbnN0cnVjdG9yKC4uLmFyZ3MpIHtcbiAgICB0aGlzLnZhbHVlcyA9IE9iamVjdC5mcmVlemUoYXJncyk7XG4gIH1cblxuICBnZXQoaW5kZXgpIHtcbiAgICByZXR1cm4gdGhpcy52YWx1ZXNbaW5kZXhdO1xuICB9XG5cbiAgY291bnQoKSB7XG4gICAgcmV0dXJuIHRoaXMudmFsdWVzLmxlbmd0aDtcbiAgfVxuXG4gIFtTeW1ib2wuaXRlcmF0b3JdKCkge1xuICAgIHJldHVybiB0aGlzLnZhbHVlc1tTeW1ib2wuaXRlcmF0b3JdKCk7XG4gIH1cblxuICB0b1N0cmluZygpIHtcbiAgICB2YXIgaSxcbiAgICAgICAgcyA9IFwiXCI7XG4gICAgZm9yIChpID0gMDsgaSA8IHRoaXMudmFsdWVzLmxlbmd0aDsgaSsrKSB7XG4gICAgICBpZiAocyAhPT0gXCJcIikge1xuICAgICAgICBzICs9IFwiLCBcIjtcbiAgICAgIH1cbiAgICAgIHMgKz0gdGhpcy52YWx1ZXNbaV0udG9TdHJpbmcoKTtcbiAgICB9XG5cbiAgICByZXR1cm4gXCJ7XCIgKyBzICsgXCJ9XCI7XG4gIH1cblxufVxuXG5sZXQgcHJvY2Vzc19jb3VudGVyID0gLTE7XG5cbmNsYXNzIFBJRCB7XG4gIGNvbnN0cnVjdG9yKCkge1xuICAgIHByb2Nlc3NfY291bnRlciA9IHByb2Nlc3NfY291bnRlciArIDE7XG4gICAgdGhpcy5pZCA9IHByb2Nlc3NfY291bnRlcjtcbiAgfVxuXG4gIHRvU3RyaW5nKCkge1xuICAgIHJldHVybiBcIlBJRCM8MC5cIiArIHRoaXMuaWQgKyBcIi4wPlwiO1xuICB9XG59XG5cbnZhciBDb3JlID0geyBQSUQsIFR1cGxlOiBUdXBsZSQxIH07XG5cbmNsYXNzIFByb2Nlc3NTeXN0ZW0ge1xuXG4gIGNvbnN0cnVjdG9yKCkge1xuICAgIHRoaXMucGlkcyA9IG5ldyBNYXAoKTtcbiAgICB0aGlzLm1haWxib3hlcyA9IG5ldyBNYXAoKTtcbiAgICB0aGlzLm5hbWVzID0gbmV3IE1hcCgpO1xuICAgIHRoaXMubGlua3MgPSBuZXcgTWFwKCk7XG5cbiAgICB0aGlzLmN1cnJlbnRfcHJvY2VzcyA9IG51bGw7XG4gICAgdGhpcy5zdXNwZW5kZWQgPSBuZXcgTWFwKCk7XG5cbiAgICB0aGlzLm1haW5fcHJvY2Vzc19waWQgPSB0aGlzLnNwYXduKCk7XG4gICAgdGhpcy5zZXRfY3VycmVudCh0aGlzLm1haW5fcHJvY2Vzc19waWQpO1xuICB9XG5cbiAgc3Bhd24oKSB7XG4gICAgcmV0dXJuIHRoaXMuYWRkX3Byb2MoZmFsc2UpLnBpZDtcbiAgfVxuXG4gIHNwYXduX2xpbmsoKSB7XG4gICAgcmV0dXJuIHRoaXMuYWRkX3Byb2ModHJ1ZSkucGlkO1xuICB9XG5cbiAgbGluayhwaWQpIHtcbiAgICB0aGlzLmxpbmtzLmdldCh0aGlzLnBpZCgpKS5hZGQocGlkKTtcbiAgICB0aGlzLmxpbmtzLmdldChwaWQpLmFkZCh0aGlzLnBpZCgpKTtcbiAgfVxuXG4gIHVubGluayhwaWQpIHtcbiAgICB0aGlzLmxpbmtzLmdldCh0aGlzLnBpZCgpKS5kZWxldGUocGlkKTtcbiAgICB0aGlzLmxpbmtzLmdldChwaWQpLmRlbGV0ZSh0aGlzLnBpZCgpKTtcbiAgfVxuXG4gIHNldF9jdXJyZW50KGlkKSB7XG4gICAgbGV0IHBpZCA9IHRoaXMucGlkb2YoaWQpO1xuICAgIGlmIChwaWQgIT09IG51bGwpIHtcbiAgICAgIHRoaXMuY3VycmVudF9wcm9jZXNzID0gdGhpcy5waWRzLmdldChwaWQpO1xuICAgICAgdGhpcy5jdXJyZW50X3Byb2Nlc3Muc3RhdHVzID0gU3RhdGVzLlJVTk5JTkc7XG4gICAgfVxuICB9XG5cbiAgYWRkX3Byb2MobGlua2VkKSB7XG4gICAgbGV0IG5ld3BpZCA9IG5ldyBDb3JlLlBJRCgpO1xuICAgIGxldCBtYWlsYm94ID0gbmV3IE1haWxib3goKTtcbiAgICBsZXQgbmV3cHJvYyA9IG5ldyBQcm9jZXNzKG5ld3BpZCwgbWFpbGJveCk7XG5cbiAgICB0aGlzLnBpZHMuc2V0KG5ld3BpZCwgbmV3cHJvYyk7XG4gICAgdGhpcy5tYWlsYm94ZXMuc2V0KG5ld3BpZCwgbWFpbGJveCk7XG4gICAgdGhpcy5saW5rcy5zZXQobmV3cGlkLCBuZXcgU2V0KCkpO1xuXG4gICAgaWYgKGxpbmtlZCkge1xuICAgICAgdGhpcy5saW5rKG5ld3BpZCk7XG4gICAgfVxuXG4gICAgcmV0dXJuIG5ld3Byb2M7XG4gIH1cblxuICByZW1vdmVfcHJvYyhwaWQpIHtcbiAgICB0aGlzLnBpZHMuZGVsZXRlKHBpZCk7XG4gICAgdGhpcy51bnJlZ2lzdGVyKHBpZCk7XG5cbiAgICBpZiAodGhpcy5saW5rcy5oYXMocGlkKSkge1xuICAgICAgZm9yIChsZXQgbGlua3BpZCBvZiB0aGlzLmxpbmtzLmdldChwaWQpKSB7XG4gICAgICAgIHRoaXMubGlua3MuZ2V0KGxpbmtwaWQpLmRlbGV0ZShwaWQpO1xuICAgICAgfVxuXG4gICAgICB0aGlzLmxpbmtzLmRlbGV0ZShwaWQpO1xuICAgIH1cbiAgfVxuXG4gIGV4aXQoaWQpIHtcbiAgICBsZXQgcGlkID0gdGhpcy5waWRvZihpZCk7XG4gICAgdGhpcy5yZW1vdmVfcHJvYyhpZCk7XG4gIH1cblxuICByZWdpc3RlcihuYW1lLCBwaWQpIHtcbiAgICBpZiAoIXRoaXMubmFtZXMuaGFzKG5hbWUpKSB7XG4gICAgICB0aGlzLm5hbWVzLnNldChuYW1lLCBwaWQpO1xuICAgICAgcmV0dXJuIG5hbWU7XG4gICAgfSBlbHNlIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcihcIk5hbWUgaXMgYWxyZWFkeSByZWdpc3RlcmVkIHRvIGFub3RoZXIgcHJvY2Vzc1wiKTtcbiAgICB9XG4gIH1cblxuICByZWdpc3RlcmVkKG5hbWUpIHtcbiAgICByZXR1cm4gdGhpcy5uYW1lcy5oYXMobmFtZSkgPyB0aGlzLm5hbWVzLmdldChuYW1lKSA6IG51bGw7XG4gIH1cblxuICB1bnJlZ2lzdGVyKHBpZCkge1xuICAgIGZvciAobGV0IG5hbWUgb2YgdGhpcy5uYW1lcy5rZXlzKCkpIHtcbiAgICAgIGlmICh0aGlzLm5hbWVzLmhhcyhuYW1lKSAmJiB0aGlzLm5hbWVzLmdldChuYW1lKSA9PT0gcGlkKSB7XG4gICAgICAgIHRoaXMubmFtZXMuZGVsZXRlKG5hbWUpO1xuICAgICAgfVxuICAgIH1cbiAgfVxuXG4gIHBpZCgpIHtcbiAgICByZXR1cm4gdGhpcy5jdXJyZW50X3Byb2Nlc3MucGlkO1xuICB9XG5cbiAgcGlkb2YoaWQpIHtcbiAgICBpZiAoaWQgaW5zdGFuY2VvZiBDb3JlLlBJRCkge1xuICAgICAgcmV0dXJuIHRoaXMucGlkcy5oYXMoaWQpID8gaWQgOiBudWxsO1xuICAgIH0gZWxzZSBpZiAoaWQgaW5zdGFuY2VvZiBQcm9jZXNzKSB7XG4gICAgICByZXR1cm4gaWQucGlkO1xuICAgIH0gZWxzZSB7XG4gICAgICBsZXQgcGlkID0gdGhpcy5yZWdpc3RlcmVkKGlkKTtcbiAgICAgIGlmIChwaWQgPT09IG51bGwpIHRocm93IFwiUHJvY2VzcyBuYW1lIG5vdCByZWdpc3RlcmVkOiBcIiArIGlkICsgXCIgKFwiICsgdHlwZW9mIGlkICsgXCIpXCI7XG4gICAgICByZXR1cm4gcGlkO1xuICAgIH1cbiAgfVxuXG4gIHB1dChpZCwga2V5LCB2YWx1ZSkge1xuICAgIGxldCBwaWQgPSB0aGlzLnBpZG9mKGlkKTtcbiAgICBsZXQgcHJvY2VzcyA9IHRoaXMucGlkcy5nZXQocGlkKTtcbiAgICBwcm9jZXNzLmRpY3Rba2V5XSA9IHZhbHVlO1xuICB9XG5cbiAgZ2V0KGlkLCBrZXkpIHtcbiAgICBsZXQgcGlkID0gdGhpcy5waWRvZihpZCk7XG4gICAgbGV0IHByb2Nlc3MgPSB0aGlzLnBpZHMuZ2V0KHBpZCk7XG5cbiAgICBpZiAoa2V5ICE9IG51bGwpIHtcbiAgICAgIHJldHVybiBwcm9jZXNzLmRpY3Rba2V5XTtcbiAgICB9IGVsc2Uge1xuICAgICAgcmV0dXJuIHByb2Nlc3MuZGljdDtcbiAgICB9XG4gIH1cblxuICBnZXRfa2V5cyhpZCkge1xuICAgIGxldCBwaWQgPSB0aGlzLnBpZG9mKGlkKTtcbiAgICBsZXQgcHJvY2VzcyA9IHRoaXMucGlkcy5nZXQocGlkKTtcblxuICAgIHJldHVybiBPYmplY3Qua2V5cyhwcm9jZXNzLmRpY3QpO1xuICB9XG5cbiAgZXJhc2UoaWQsIGtleSkge1xuICAgIGxldCBwaWQgPSB0aGlzLnBpZG9mKGlkKTtcbiAgICBsZXQgcHJvY2VzcyA9IHRoaXMucGlkcy5nZXQocGlkKTtcblxuICAgIGlmIChrZXkgIT0gbnVsbCkge1xuICAgICAgZGVsZXRlIHByb2Nlc3MuZGljdFtrZXldO1xuICAgIH0gZWxzZSB7XG4gICAgICBwcm9jZXNzLmRpY3QgPSB7fTtcbiAgICB9XG4gIH1cbn1cblxuLyogQGZsb3cgKi9cblxuY2xhc3MgVmFyaWFibGUge1xuXG4gIGNvbnN0cnVjdG9yKG5hbWUgPSBudWxsKSB7XG4gICAgdGhpcy5uYW1lID0gbmFtZTtcbiAgfVxufVxuXG5jbGFzcyBXaWxkY2FyZCB7XG4gIGNvbnN0cnVjdG9yKCkge31cbn1cblxuY2xhc3MgU3RhcnRzV2l0aCB7XG5cbiAgY29uc3RydWN0b3IocHJlZml4KSB7XG4gICAgdGhpcy5wcmVmaXggPSBwcmVmaXg7XG4gIH1cbn1cblxuY2xhc3MgQ2FwdHVyZSB7XG5cbiAgY29uc3RydWN0b3IodmFsdWUpIHtcbiAgICB0aGlzLnZhbHVlID0gdmFsdWU7XG4gIH1cbn1cblxuY2xhc3MgSGVhZFRhaWwge1xuICBjb25zdHJ1Y3RvcigpIHt9XG59XG5cbmNsYXNzIFR5cGUge1xuXG4gIGNvbnN0cnVjdG9yKHR5cGUsIG9ialBhdHRlcm4gPSB7fSkge1xuICAgIHRoaXMudHlwZSA9IHR5cGU7XG4gICAgdGhpcy5vYmpQYXR0ZXJuID0gb2JqUGF0dGVybjtcbiAgfVxufVxuXG5jbGFzcyBCb3VuZCB7XG5cbiAgY29uc3RydWN0b3IodmFsdWUpIHtcbiAgICB0aGlzLnZhbHVlID0gdmFsdWU7XG4gIH1cbn1cblxuZnVuY3Rpb24gdmFyaWFibGUobmFtZSA9IG51bGwpIHtcbiAgcmV0dXJuIG5ldyBWYXJpYWJsZShuYW1lKTtcbn1cblxuZnVuY3Rpb24gd2lsZGNhcmQoKSB7XG4gIHJldHVybiBuZXcgV2lsZGNhcmQoKTtcbn1cblxuZnVuY3Rpb24gc3RhcnRzV2l0aChwcmVmaXgpIHtcbiAgcmV0dXJuIG5ldyBTdGFydHNXaXRoKHByZWZpeCk7XG59XG5cbmZ1bmN0aW9uIGNhcHR1cmUodmFsdWUpIHtcbiAgcmV0dXJuIG5ldyBDYXB0dXJlKHZhbHVlKTtcbn1cblxuZnVuY3Rpb24gaGVhZFRhaWwoKSB7XG4gIHJldHVybiBuZXcgSGVhZFRhaWwoKTtcbn1cblxuZnVuY3Rpb24gdHlwZSh0eXBlLCBvYmpQYXR0ZXJuID0ge30pIHtcbiAgcmV0dXJuIG5ldyBUeXBlKHR5cGUsIG9ialBhdHRlcm4pO1xufVxuXG5mdW5jdGlvbiBib3VuZCh2YWx1ZSkge1xuICByZXR1cm4gbmV3IEJvdW5kKHZhbHVlKTtcbn1cblxuZnVuY3Rpb24gaXNfbnVtYmVyJDEodmFsdWUpIHtcbiAgcmV0dXJuIHR5cGVvZiB2YWx1ZSA9PT0gJ251bWJlcic7XG59XG5cbmZ1bmN0aW9uIGlzX3N0cmluZyh2YWx1ZSkge1xuICByZXR1cm4gdHlwZW9mIHZhbHVlID09PSAnc3RyaW5nJztcbn1cblxuZnVuY3Rpb24gaXNfYm9vbGVhbiQxKHZhbHVlKSB7XG4gIHJldHVybiB0eXBlb2YgdmFsdWUgPT09ICdib29sZWFuJztcbn1cblxuZnVuY3Rpb24gaXNfc3ltYm9sKHZhbHVlKSB7XG4gIHJldHVybiB0eXBlb2YgdmFsdWUgPT09ICdzeW1ib2wnO1xufVxuXG5mdW5jdGlvbiBpc19udWxsKHZhbHVlKSB7XG4gIHJldHVybiB2YWx1ZSA9PT0gbnVsbDtcbn1cblxuZnVuY3Rpb24gaXNfdW5kZWZpbmVkKHZhbHVlKSB7XG4gIHJldHVybiB0eXBlb2YgdmFsdWUgPT09ICd1bmRlZmluZWQnO1xufVxuXG5mdW5jdGlvbiBpc19mdW5jdGlvbiQxKHZhbHVlKSB7XG4gIHJldHVybiBPYmplY3QucHJvdG90eXBlLnRvU3RyaW5nLmNhbGwodmFsdWUpID09ICdbb2JqZWN0IEZ1bmN0aW9uXSc7XG59XG5cbmZ1bmN0aW9uIGlzX3ZhcmlhYmxlKHZhbHVlKSB7XG4gIHJldHVybiB2YWx1ZSBpbnN0YW5jZW9mIFZhcmlhYmxlO1xufVxuXG5mdW5jdGlvbiBpc193aWxkY2FyZCh2YWx1ZSkge1xuICByZXR1cm4gdmFsdWUgaW5zdGFuY2VvZiBXaWxkY2FyZDtcbn1cblxuZnVuY3Rpb24gaXNfaGVhZFRhaWwodmFsdWUpIHtcbiAgcmV0dXJuIHZhbHVlIGluc3RhbmNlb2YgSGVhZFRhaWw7XG59XG5cbmZ1bmN0aW9uIGlzX2NhcHR1cmUodmFsdWUpIHtcbiAgcmV0dXJuIHZhbHVlIGluc3RhbmNlb2YgQ2FwdHVyZTtcbn1cblxuZnVuY3Rpb24gaXNfdHlwZSh2YWx1ZSkge1xuICByZXR1cm4gdmFsdWUgaW5zdGFuY2VvZiBUeXBlO1xufVxuXG5mdW5jdGlvbiBpc19zdGFydHNXaXRoKHZhbHVlKSB7XG4gIHJldHVybiB2YWx1ZSBpbnN0YW5jZW9mIFN0YXJ0c1dpdGg7XG59XG5cbmZ1bmN0aW9uIGlzX2JvdW5kKHZhbHVlKSB7XG4gIHJldHVybiB2YWx1ZSBpbnN0YW5jZW9mIEJvdW5kO1xufVxuXG5mdW5jdGlvbiBpc19vYmplY3QodmFsdWUpIHtcbiAgcmV0dXJuIHR5cGVvZiB2YWx1ZSA9PT0gJ29iamVjdCc7XG59XG5cbmZ1bmN0aW9uIGlzX2FycmF5KHZhbHVlKSB7XG4gIHJldHVybiBBcnJheS5pc0FycmF5KHZhbHVlKTtcbn1cblxudmFyIENoZWNrcyA9IHtcbiAgaXNfbnVtYmVyOiBpc19udW1iZXIkMSxcbiAgaXNfc3RyaW5nLFxuICBpc19ib29sZWFuOiBpc19ib29sZWFuJDEsXG4gIGlzX3N5bWJvbCxcbiAgaXNfbnVsbCxcbiAgaXNfdW5kZWZpbmVkLFxuICBpc19mdW5jdGlvbjogaXNfZnVuY3Rpb24kMSxcbiAgaXNfdmFyaWFibGUsXG4gIGlzX3dpbGRjYXJkLFxuICBpc19oZWFkVGFpbCxcbiAgaXNfY2FwdHVyZSxcbiAgaXNfdHlwZSxcbiAgaXNfc3RhcnRzV2l0aCxcbiAgaXNfYm91bmQsXG4gIGlzX29iamVjdCxcbiAgaXNfYXJyYXlcbn07XG5cbmZ1bmN0aW9uIHJlc29sdmVTeW1ib2wocGF0dGVybikge1xuICByZXR1cm4gZnVuY3Rpb24gKHZhbHVlKSB7XG4gICAgcmV0dXJuIENoZWNrcy5pc19zeW1ib2wodmFsdWUpICYmIHZhbHVlID09PSBwYXR0ZXJuO1xuICB9O1xufVxuXG5mdW5jdGlvbiByZXNvbHZlU3RyaW5nKHBhdHRlcm4pIHtcbiAgcmV0dXJuIGZ1bmN0aW9uICh2YWx1ZSkge1xuICAgIHJldHVybiBDaGVja3MuaXNfc3RyaW5nKHZhbHVlKSAmJiB2YWx1ZSA9PT0gcGF0dGVybjtcbiAgfTtcbn1cblxuZnVuY3Rpb24gcmVzb2x2ZU51bWJlcihwYXR0ZXJuKSB7XG4gIHJldHVybiBmdW5jdGlvbiAodmFsdWUpIHtcbiAgICByZXR1cm4gQ2hlY2tzLmlzX251bWJlcih2YWx1ZSkgJiYgdmFsdWUgPT09IHBhdHRlcm47XG4gIH07XG59XG5cbmZ1bmN0aW9uIHJlc29sdmVCb29sZWFuKHBhdHRlcm4pIHtcbiAgcmV0dXJuIGZ1bmN0aW9uICh2YWx1ZSkge1xuICAgIHJldHVybiBDaGVja3MuaXNfYm9vbGVhbih2YWx1ZSkgJiYgdmFsdWUgPT09IHBhdHRlcm47XG4gIH07XG59XG5cbmZ1bmN0aW9uIHJlc29sdmVGdW5jdGlvbihwYXR0ZXJuKSB7XG4gIHJldHVybiBmdW5jdGlvbiAodmFsdWUpIHtcbiAgICByZXR1cm4gQ2hlY2tzLmlzX2Z1bmN0aW9uKHZhbHVlKSAmJiB2YWx1ZSA9PT0gcGF0dGVybjtcbiAgfTtcbn1cblxuZnVuY3Rpb24gcmVzb2x2ZU51bGwocGF0dGVybikge1xuICByZXR1cm4gZnVuY3Rpb24gKHZhbHVlKSB7XG4gICAgcmV0dXJuIENoZWNrcy5pc19udWxsKHZhbHVlKTtcbiAgfTtcbn1cblxuZnVuY3Rpb24gcmVzb2x2ZUJvdW5kKHBhdHRlcm4pIHtcbiAgcmV0dXJuIGZ1bmN0aW9uICh2YWx1ZSwgYXJncykge1xuICAgIGlmICh0eXBlb2YgdmFsdWUgPT09IHR5cGVvZiBwYXR0ZXJuLnZhbHVlICYmIHZhbHVlID09PSBwYXR0ZXJuLnZhbHVlKSB7XG4gICAgICBhcmdzLnB1c2godmFsdWUpO1xuICAgICAgcmV0dXJuIHRydWU7XG4gICAgfVxuXG4gICAgcmV0dXJuIGZhbHNlO1xuICB9O1xufVxuXG5mdW5jdGlvbiByZXNvbHZlV2lsZGNhcmQoKSB7XG4gIHJldHVybiBmdW5jdGlvbiAoKSB7XG4gICAgcmV0dXJuIHRydWU7XG4gIH07XG59XG5cbmZ1bmN0aW9uIHJlc29sdmVWYXJpYWJsZSgpIHtcbiAgcmV0dXJuIGZ1bmN0aW9uICh2YWx1ZSwgYXJncykge1xuICAgIGFyZ3MucHVzaCh2YWx1ZSk7XG4gICAgcmV0dXJuIHRydWU7XG4gIH07XG59XG5cbmZ1bmN0aW9uIHJlc29sdmVIZWFkVGFpbCgpIHtcbiAgcmV0dXJuIGZ1bmN0aW9uICh2YWx1ZSwgYXJncykge1xuICAgIGlmICghQ2hlY2tzLmlzX2FycmF5KHZhbHVlKSB8fCB2YWx1ZS5sZW5ndGggPCAyKSB7XG4gICAgICByZXR1cm4gZmFsc2U7XG4gICAgfVxuXG4gICAgY29uc3QgaGVhZCA9IHZhbHVlWzBdO1xuICAgIGNvbnN0IHRhaWwgPSB2YWx1ZS5zbGljZSgxKTtcblxuICAgIGFyZ3MucHVzaChoZWFkKTtcbiAgICBhcmdzLnB1c2godGFpbCk7XG5cbiAgICByZXR1cm4gdHJ1ZTtcbiAgfTtcbn1cblxuZnVuY3Rpb24gcmVzb2x2ZUNhcHR1cmUocGF0dGVybikge1xuICBjb25zdCBtYXRjaGVzID0gYnVpbGRNYXRjaChwYXR0ZXJuLnZhbHVlKTtcblxuICByZXR1cm4gZnVuY3Rpb24gKHZhbHVlLCBhcmdzKSB7XG4gICAgaWYgKG1hdGNoZXModmFsdWUsIGFyZ3MpKSB7XG4gICAgICBhcmdzLnB1c2godmFsdWUpO1xuICAgICAgcmV0dXJuIHRydWU7XG4gICAgfVxuXG4gICAgcmV0dXJuIGZhbHNlO1xuICB9O1xufVxuXG5mdW5jdGlvbiByZXNvbHZlU3RhcnRzV2l0aChwYXR0ZXJuKSB7XG4gIGNvbnN0IHByZWZpeCA9IHBhdHRlcm4ucHJlZml4O1xuXG4gIHJldHVybiBmdW5jdGlvbiAodmFsdWUsIGFyZ3MpIHtcbiAgICBpZiAoQ2hlY2tzLmlzX3N0cmluZyh2YWx1ZSkgJiYgdmFsdWUuc3RhcnRzV2l0aChwcmVmaXgpKSB7XG4gICAgICBhcmdzLnB1c2godmFsdWUuc3Vic3RyaW5nKHByZWZpeC5sZW5ndGgpKTtcbiAgICAgIHJldHVybiB0cnVlO1xuICAgIH1cblxuICAgIHJldHVybiBmYWxzZTtcbiAgfTtcbn1cblxuZnVuY3Rpb24gcmVzb2x2ZVR5cGUocGF0dGVybikge1xuICByZXR1cm4gZnVuY3Rpb24gKHZhbHVlLCBhcmdzKSB7XG4gICAgaWYgKHZhbHVlIGluc3RhbmNlb2YgcGF0dGVybi50eXBlKSB7XG4gICAgICBjb25zdCBtYXRjaGVzID0gYnVpbGRNYXRjaChwYXR0ZXJuLm9ialBhdHRlcm4pO1xuICAgICAgcmV0dXJuIG1hdGNoZXModmFsdWUsIGFyZ3MpICYmIGFyZ3MucHVzaCh2YWx1ZSkgPiAwO1xuICAgIH1cblxuICAgIHJldHVybiBmYWxzZTtcbiAgfTtcbn1cblxuZnVuY3Rpb24gcmVzb2x2ZUFycmF5KHBhdHRlcm4pIHtcbiAgY29uc3QgbWF0Y2hlcyA9IHBhdHRlcm4ubWFwKHggPT4gYnVpbGRNYXRjaCh4KSk7XG5cbiAgcmV0dXJuIGZ1bmN0aW9uICh2YWx1ZSwgYXJncykge1xuICAgIGlmICghQ2hlY2tzLmlzX2FycmF5KHZhbHVlKSB8fCB2YWx1ZS5sZW5ndGggIT0gcGF0dGVybi5sZW5ndGgpIHtcbiAgICAgIHJldHVybiBmYWxzZTtcbiAgICB9XG5cbiAgICByZXR1cm4gdmFsdWUuZXZlcnkoZnVuY3Rpb24gKHYsIGkpIHtcbiAgICAgIHJldHVybiBtYXRjaGVzW2ldKHZhbHVlW2ldLCBhcmdzKTtcbiAgICB9KTtcbiAgfTtcbn1cblxuZnVuY3Rpb24gcmVzb2x2ZU9iamVjdChwYXR0ZXJuKSB7XG4gIGxldCBtYXRjaGVzID0ge307XG5cbiAgZm9yIChsZXQga2V5IG9mIE9iamVjdC5rZXlzKHBhdHRlcm4pKSB7XG4gICAgbWF0Y2hlc1trZXldID0gYnVpbGRNYXRjaChwYXR0ZXJuW2tleV0pO1xuICB9XG5cbiAgcmV0dXJuIGZ1bmN0aW9uICh2YWx1ZSwgYXJncykge1xuICAgIGlmICghQ2hlY2tzLmlzX29iamVjdCh2YWx1ZSkgfHwgcGF0dGVybi5sZW5ndGggPiB2YWx1ZS5sZW5ndGgpIHtcbiAgICAgIHJldHVybiBmYWxzZTtcbiAgICB9XG5cbiAgICBmb3IgKGxldCBrZXkgb2YgT2JqZWN0LmtleXMocGF0dGVybikpIHtcbiAgICAgIGlmICghKGtleSBpbiB2YWx1ZSkgfHwgIW1hdGNoZXNba2V5XSh2YWx1ZVtrZXldLCBhcmdzKSkge1xuICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICB9XG4gICAgfVxuXG4gICAgcmV0dXJuIHRydWU7XG4gIH07XG59XG5cbmZ1bmN0aW9uIHJlc29sdmVOb01hdGNoKCkge1xuICByZXR1cm4gZnVuY3Rpb24gKCkge1xuICAgIHJldHVybiBmYWxzZTtcbiAgfTtcbn1cblxudmFyIFJlc29sdmVycyA9IHtcbiAgcmVzb2x2ZUJvdW5kLFxuICByZXNvbHZlV2lsZGNhcmQsXG4gIHJlc29sdmVWYXJpYWJsZSxcbiAgcmVzb2x2ZUhlYWRUYWlsLFxuICByZXNvbHZlQ2FwdHVyZSxcbiAgcmVzb2x2ZVN0YXJ0c1dpdGgsXG4gIHJlc29sdmVUeXBlLFxuICByZXNvbHZlQXJyYXksXG4gIHJlc29sdmVPYmplY3QsXG4gIHJlc29sdmVOb01hdGNoLFxuICByZXNvbHZlU3ltYm9sLFxuICByZXNvbHZlU3RyaW5nLFxuICByZXNvbHZlTnVtYmVyLFxuICByZXNvbHZlQm9vbGVhbixcbiAgcmVzb2x2ZUZ1bmN0aW9uLFxuICByZXNvbHZlTnVsbFxufTtcblxuZnVuY3Rpb24gYnVpbGRNYXRjaChwYXR0ZXJuKSB7XG5cbiAgaWYgKENoZWNrcy5pc192YXJpYWJsZShwYXR0ZXJuKSkge1xuICAgIHJldHVybiBSZXNvbHZlcnMucmVzb2x2ZVZhcmlhYmxlKHBhdHRlcm4pO1xuICB9XG5cbiAgaWYgKENoZWNrcy5pc193aWxkY2FyZChwYXR0ZXJuKSkge1xuICAgIHJldHVybiBSZXNvbHZlcnMucmVzb2x2ZVdpbGRjYXJkKHBhdHRlcm4pO1xuICB9XG5cbiAgaWYgKENoZWNrcy5pc191bmRlZmluZWQocGF0dGVybikpIHtcbiAgICByZXR1cm4gUmVzb2x2ZXJzLnJlc29sdmVXaWxkY2FyZChwYXR0ZXJuKTtcbiAgfVxuXG4gIGlmIChDaGVja3MuaXNfaGVhZFRhaWwocGF0dGVybikpIHtcbiAgICByZXR1cm4gUmVzb2x2ZXJzLnJlc29sdmVIZWFkVGFpbChwYXR0ZXJuKTtcbiAgfVxuXG4gIGlmIChDaGVja3MuaXNfc3RhcnRzV2l0aChwYXR0ZXJuKSkge1xuICAgIHJldHVybiBSZXNvbHZlcnMucmVzb2x2ZVN0YXJ0c1dpdGgocGF0dGVybik7XG4gIH1cblxuICBpZiAoQ2hlY2tzLmlzX2NhcHR1cmUocGF0dGVybikpIHtcbiAgICByZXR1cm4gUmVzb2x2ZXJzLnJlc29sdmVDYXB0dXJlKHBhdHRlcm4pO1xuICB9XG5cbiAgaWYgKENoZWNrcy5pc19ib3VuZChwYXR0ZXJuKSkge1xuICAgIHJldHVybiBSZXNvbHZlcnMucmVzb2x2ZUJvdW5kKHBhdHRlcm4pO1xuICB9XG5cbiAgaWYgKENoZWNrcy5pc190eXBlKHBhdHRlcm4pKSB7XG4gICAgcmV0dXJuIFJlc29sdmVycy5yZXNvbHZlVHlwZShwYXR0ZXJuKTtcbiAgfVxuXG4gIGlmIChDaGVja3MuaXNfYXJyYXkocGF0dGVybikpIHtcbiAgICByZXR1cm4gUmVzb2x2ZXJzLnJlc29sdmVBcnJheShwYXR0ZXJuKTtcbiAgfVxuXG4gIGlmIChDaGVja3MuaXNfbnVtYmVyKHBhdHRlcm4pKSB7XG4gICAgcmV0dXJuIFJlc29sdmVycy5yZXNvbHZlTnVtYmVyKHBhdHRlcm4pO1xuICB9XG5cbiAgaWYgKENoZWNrcy5pc19zdHJpbmcocGF0dGVybikpIHtcbiAgICByZXR1cm4gUmVzb2x2ZXJzLnJlc29sdmVTdHJpbmcocGF0dGVybik7XG4gIH1cblxuICBpZiAoQ2hlY2tzLmlzX2Jvb2xlYW4ocGF0dGVybikpIHtcbiAgICByZXR1cm4gUmVzb2x2ZXJzLnJlc29sdmVCb29sZWFuKHBhdHRlcm4pO1xuICB9XG5cbiAgaWYgKENoZWNrcy5pc19zeW1ib2wocGF0dGVybikpIHtcbiAgICByZXR1cm4gUmVzb2x2ZXJzLnJlc29sdmVTeW1ib2wocGF0dGVybik7XG4gIH1cblxuICBpZiAoQ2hlY2tzLmlzX251bGwocGF0dGVybikpIHtcbiAgICByZXR1cm4gUmVzb2x2ZXJzLnJlc29sdmVOdWxsKHBhdHRlcm4pO1xuICB9XG5cbiAgaWYgKENoZWNrcy5pc19vYmplY3QocGF0dGVybikpIHtcbiAgICByZXR1cm4gUmVzb2x2ZXJzLnJlc29sdmVPYmplY3QocGF0dGVybik7XG4gIH1cblxuICByZXR1cm4gUmVzb2x2ZXJzLnJlc29sdmVOb01hdGNoKCk7XG59XG5cbmNsYXNzIE1hdGNoRXJyb3IgZXh0ZW5kcyBFcnJvciB7XG4gIGNvbnN0cnVjdG9yKGFyZykge1xuICAgIHN1cGVyKCk7XG5cbiAgICBpZiAodHlwZW9mIGFyZyA9PT0gJ3N5bWJvbCcpIHtcbiAgICAgIHRoaXMubWVzc2FnZSA9ICdObyBtYXRjaCBmb3I6ICcgKyBhcmcudG9TdHJpbmcoKTtcbiAgICB9IGVsc2UgaWYgKEFycmF5LmlzQXJyYXkoYXJnKSkge1xuICAgICAgbGV0IG1hcHBlZFZhbHVlcyA9IGFyZy5tYXAoeCA9PiB4LnRvU3RyaW5nKCkpO1xuICAgICAgdGhpcy5tZXNzYWdlID0gJ05vIG1hdGNoIGZvcjogJyArIG1hcHBlZFZhbHVlcztcbiAgICB9IGVsc2Uge1xuICAgICAgdGhpcy5tZXNzYWdlID0gJ05vIG1hdGNoIGZvcjogJyArIGFyZztcbiAgICB9XG5cbiAgICB0aGlzLnN0YWNrID0gbmV3IEVycm9yKCkuc3RhY2s7XG4gICAgdGhpcy5uYW1lID0gdGhpcy5jb25zdHJ1Y3Rvci5uYW1lO1xuICB9XG59XG5cbmNsYXNzIENhc2Uge1xuXG4gIGNvbnN0cnVjdG9yKHBhdHRlcm4sIGZuLCBndWFyZCA9ICgpID0+IHRydWUpIHtcbiAgICB0aGlzLnBhdHRlcm4gPSBidWlsZE1hdGNoKHBhdHRlcm4pO1xuICAgIHRoaXMuZm4gPSBmbjtcbiAgICB0aGlzLmd1YXJkID0gZ3VhcmQ7XG4gIH1cbn1cblxuZnVuY3Rpb24gbWFrZV9jYXNlKHBhdHRlcm4sIGZuLCBndWFyZCA9ICgpID0+IHRydWUpIHtcbiAgcmV0dXJuIG5ldyBDYXNlKHBhdHRlcm4sIGZuLCBndWFyZCk7XG59XG5cbmZ1bmN0aW9uIGRlZm1hdGNoKC4uLmNhc2VzKSB7XG4gIHJldHVybiBmdW5jdGlvbiAoLi4uYXJncykge1xuICAgIGZvciAobGV0IHByb2Nlc3NlZENhc2Ugb2YgY2FzZXMpIHtcbiAgICAgIGxldCByZXN1bHQgPSBbXTtcbiAgICAgIGlmIChwcm9jZXNzZWRDYXNlLnBhdHRlcm4oYXJncywgcmVzdWx0KSAmJiBwcm9jZXNzZWRDYXNlLmd1YXJkLmFwcGx5KHRoaXMsIHJlc3VsdCkpIHtcbiAgICAgICAgcmV0dXJuIHByb2Nlc3NlZENhc2UuZm4uYXBwbHkodGhpcywgcmVzdWx0KTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICB0aHJvdyBuZXcgTWF0Y2hFcnJvcihhcmdzKTtcbiAgfTtcbn1cblxuZnVuY3Rpb24gbWF0Y2gocGF0dGVybiwgZXhwciwgZ3VhcmQgPSAoKSA9PiB0cnVlKSB7XG4gIGxldCByZXN1bHQgPSBbXTtcbiAgbGV0IHByb2Nlc3NlZFBhdHRlcm4gPSBidWlsZE1hdGNoKHBhdHRlcm4pO1xuICBpZiAocHJvY2Vzc2VkUGF0dGVybihleHByLCByZXN1bHQpICYmIGd1YXJkLmFwcGx5KHRoaXMsIHJlc3VsdCkpIHtcbiAgICByZXR1cm4gcmVzdWx0O1xuICB9IGVsc2Uge1xuICAgIHRocm93IG5ldyBNYXRjaEVycm9yKGV4cHIpO1xuICB9XG59XG5cbmZ1bmN0aW9uIG1hdGNoX25vX3Rocm93KHBhdHRlcm4sIGV4cHIsIGd1YXJkID0gKCkgPT4gdHJ1ZSkge1xuICB0cnkge1xuICAgIHJldHVybiBtYXRjaChwYXR0ZXJuLCBleHByLCBndWFyZCk7XG4gIH0gY2F0Y2ggKGUpIHtcbiAgICBpZiAoZSBpbnN0YW5jZW9mIE1hdGNoRXJyb3IpIHtcbiAgICAgIHJldHVybiBudWxsO1xuICAgIH1cblxuICAgIHRocm93IGU7XG4gIH1cbn1cblxudmFyIFBhdHRlcm5zID0ge1xuICBkZWZtYXRjaCwgbWF0Y2gsIE1hdGNoRXJyb3IsIG1hdGNoX25vX3Rocm93LFxuICB2YXJpYWJsZSwgd2lsZGNhcmQsIHN0YXJ0c1dpdGgsXG4gIGNhcHR1cmUsIGhlYWRUYWlsLCB0eXBlLCBib3VuZCwgQ2FzZSwgbWFrZV9jYXNlXG59O1xuXG5jbGFzcyBCaXRTdHJpbmcge1xuICBjb25zdHJ1Y3RvciguLi5hcmdzKSB7XG4gICAgdGhpcy5yYXdfdmFsdWUgPSBmdW5jdGlvbiAoKSB7XG4gICAgICByZXR1cm4gT2JqZWN0LmZyZWV6ZShhcmdzKTtcbiAgICB9O1xuXG4gICAgdGhpcy52YWx1ZSA9IE9iamVjdC5mcmVlemUodGhpcy5wcm9jZXNzKGFyZ3MpKTtcbiAgfVxuXG4gIGdldChpbmRleCkge1xuICAgIHJldHVybiB0aGlzLnZhbHVlW2luZGV4XTtcbiAgfVxuXG4gIGNvdW50KCkge1xuICAgIHJldHVybiB0aGlzLnZhbHVlLmxlbmd0aDtcbiAgfVxuXG4gIFtTeW1ib2wuaXRlcmF0b3JdKCkge1xuICAgIHJldHVybiB0aGlzLnZhbHVlW1N5bWJvbC5pdGVyYXRvcl0oKTtcbiAgfVxuXG4gIHRvU3RyaW5nKCkge1xuICAgIHZhciBpLFxuICAgICAgICBzID0gXCJcIjtcbiAgICBmb3IgKGkgPSAwOyBpIDwgdGhpcy5jb3VudCgpOyBpKyspIHtcbiAgICAgIGlmIChzICE9PSBcIlwiKSB7XG4gICAgICAgIHMgKz0gXCIsIFwiO1xuICAgICAgfVxuICAgICAgcyArPSB0aGlzW2ldLnRvU3RyaW5nKCk7XG4gICAgfVxuXG4gICAgcmV0dXJuIFwiPDxcIiArIHMgKyBcIj4+XCI7XG4gIH1cblxuICBwcm9jZXNzKCkge1xuICAgIGxldCBwcm9jZXNzZWRfdmFsdWVzID0gW107XG5cbiAgICB2YXIgaTtcbiAgICBmb3IgKGkgPSAwOyBpIDwgdGhpcy5yYXdfdmFsdWUoKS5sZW5ndGg7IGkrKykge1xuICAgICAgbGV0IHByb2Nlc3NlZF92YWx1ZSA9IHRoaXNbXCJwcm9jZXNzX1wiICsgdGhpcy5yYXdfdmFsdWUoKVtpXS50eXBlXSh0aGlzLnJhd192YWx1ZSgpW2ldKTtcblxuICAgICAgZm9yIChsZXQgYXR0ciBvZiB0aGlzLnJhd192YWx1ZSgpW2ldLmF0dHJpYnV0ZXMpIHtcbiAgICAgICAgcHJvY2Vzc2VkX3ZhbHVlID0gdGhpc1tcInByb2Nlc3NfXCIgKyBhdHRyXShwcm9jZXNzZWRfdmFsdWUpO1xuICAgICAgfVxuXG4gICAgICBwcm9jZXNzZWRfdmFsdWVzID0gcHJvY2Vzc2VkX3ZhbHVlcy5jb25jYXQocHJvY2Vzc2VkX3ZhbHVlKTtcbiAgICB9XG5cbiAgICByZXR1cm4gcHJvY2Vzc2VkX3ZhbHVlcztcbiAgfVxuXG4gIHByb2Nlc3NfaW50ZWdlcih2YWx1ZSkge1xuICAgIHJldHVybiB2YWx1ZS52YWx1ZTtcbiAgfVxuXG4gIHByb2Nlc3NfZmxvYXQodmFsdWUpIHtcbiAgICBpZiAodmFsdWUuc2l6ZSA9PT0gNjQpIHtcbiAgICAgIHJldHVybiBCaXRTdHJpbmcuZmxvYXQ2NFRvQnl0ZXModmFsdWUudmFsdWUpO1xuICAgIH0gZWxzZSBpZiAodmFsdWUuc2l6ZSA9PT0gMzIpIHtcbiAgICAgIHJldHVybiBCaXRTdHJpbmcuZmxvYXQzMlRvQnl0ZXModmFsdWUudmFsdWUpO1xuICAgIH1cblxuICAgIHRocm93IG5ldyBFcnJvcihcIkludmFsaWQgc2l6ZSBmb3IgZmxvYXRcIik7XG4gIH1cblxuICBwcm9jZXNzX2JpdHN0cmluZyh2YWx1ZSkge1xuICAgIHJldHVybiB2YWx1ZS52YWx1ZS52YWx1ZTtcbiAgfVxuXG4gIHByb2Nlc3NfYmluYXJ5KHZhbHVlKSB7XG4gICAgcmV0dXJuIEJpdFN0cmluZy50b1VURjhBcnJheSh2YWx1ZS52YWx1ZSk7XG4gIH1cblxuICBwcm9jZXNzX3V0ZjgodmFsdWUpIHtcbiAgICByZXR1cm4gQml0U3RyaW5nLnRvVVRGOEFycmF5KHZhbHVlLnZhbHVlKTtcbiAgfVxuXG4gIHByb2Nlc3NfdXRmMTYodmFsdWUpIHtcbiAgICByZXR1cm4gQml0U3RyaW5nLnRvVVRGMTZBcnJheSh2YWx1ZS52YWx1ZSk7XG4gIH1cblxuICBwcm9jZXNzX3V0ZjMyKHZhbHVlKSB7XG4gICAgcmV0dXJuIEJpdFN0cmluZy50b1VURjMyQXJyYXkodmFsdWUudmFsdWUpO1xuICB9XG5cbiAgcHJvY2Vzc19zaWduZWQodmFsdWUpIHtcbiAgICByZXR1cm4gbmV3IFVpbnQ4QXJyYXkoW3ZhbHVlXSlbMF07XG4gIH1cblxuICBwcm9jZXNzX3Vuc2lnbmVkKHZhbHVlKSB7XG4gICAgcmV0dXJuIHZhbHVlO1xuICB9XG5cbiAgcHJvY2Vzc19uYXRpdmUodmFsdWUpIHtcbiAgICByZXR1cm4gdmFsdWU7XG4gIH1cblxuICBwcm9jZXNzX2JpZyh2YWx1ZSkge1xuICAgIHJldHVybiB2YWx1ZTtcbiAgfVxuXG4gIHByb2Nlc3NfbGl0dGxlKHZhbHVlKSB7XG4gICAgcmV0dXJuIHZhbHVlLnJldmVyc2UoKTtcbiAgfVxuXG4gIHByb2Nlc3Nfc2l6ZSh2YWx1ZSkge1xuICAgIHJldHVybiB2YWx1ZTtcbiAgfVxuXG4gIHByb2Nlc3NfdW5pdCh2YWx1ZSkge1xuICAgIHJldHVybiB2YWx1ZTtcbiAgfVxuXG4gIHN0YXRpYyBpbnRlZ2VyKHZhbHVlKSB7XG4gICAgcmV0dXJuIEJpdFN0cmluZy53cmFwKHZhbHVlLCB7IFwidHlwZVwiOiBcImludGVnZXJcIiwgXCJ1bml0XCI6IDEsIFwic2l6ZVwiOiA4IH0pO1xuICB9XG5cbiAgc3RhdGljIGZsb2F0KHZhbHVlKSB7XG4gICAgcmV0dXJuIEJpdFN0cmluZy53cmFwKHZhbHVlLCB7IFwidHlwZVwiOiBcImZsb2F0XCIsIFwidW5pdFwiOiAxLCBcInNpemVcIjogNjQgfSk7XG4gIH1cblxuICBzdGF0aWMgYml0c3RyaW5nKHZhbHVlKSB7XG4gICAgcmV0dXJuIEJpdFN0cmluZy53cmFwKHZhbHVlLCB7IFwidHlwZVwiOiBcImJpdHN0cmluZ1wiLCBcInVuaXRcIjogMSwgXCJzaXplXCI6IHZhbHVlLmxlbmd0aCB9KTtcbiAgfVxuXG4gIHN0YXRpYyBiaXRzKHZhbHVlKSB7XG4gICAgcmV0dXJuIEJpdFN0cmluZy5iaXRzdHJpbmcodmFsdWUpO1xuICB9XG5cbiAgc3RhdGljIGJpbmFyeSh2YWx1ZSkge1xuICAgIHJldHVybiBCaXRTdHJpbmcud3JhcCh2YWx1ZSwgeyBcInR5cGVcIjogXCJiaW5hcnlcIiwgXCJ1bml0XCI6IDgsIFwic2l6ZVwiOiB2YWx1ZS5sZW5ndGggfSk7XG4gIH1cblxuICBzdGF0aWMgYnl0ZXModmFsdWUpIHtcbiAgICByZXR1cm4gQml0U3RyaW5nLmJpbmFyeSh2YWx1ZSk7XG4gIH1cblxuICBzdGF0aWMgdXRmOCh2YWx1ZSkge1xuICAgIHJldHVybiBCaXRTdHJpbmcud3JhcCh2YWx1ZSwgeyBcInR5cGVcIjogXCJ1dGY4XCIgfSk7XG4gIH1cblxuICBzdGF0aWMgdXRmMTYodmFsdWUpIHtcbiAgICByZXR1cm4gQml0U3RyaW5nLndyYXAodmFsdWUsIHsgXCJ0eXBlXCI6IFwidXRmMTZcIiB9KTtcbiAgfVxuXG4gIHN0YXRpYyB1dGYzMih2YWx1ZSkge1xuICAgIHJldHVybiBCaXRTdHJpbmcud3JhcCh2YWx1ZSwgeyBcInR5cGVcIjogXCJ1dGYzMlwiIH0pO1xuICB9XG5cbiAgc3RhdGljIHNpZ25lZCh2YWx1ZSkge1xuICAgIHJldHVybiBCaXRTdHJpbmcud3JhcCh2YWx1ZSwge30sIFwic2lnbmVkXCIpO1xuICB9XG5cbiAgc3RhdGljIHVuc2lnbmVkKHZhbHVlKSB7XG4gICAgcmV0dXJuIEJpdFN0cmluZy53cmFwKHZhbHVlLCB7fSwgXCJ1bnNpZ25lZFwiKTtcbiAgfVxuXG4gIHN0YXRpYyBuYXRpdmUodmFsdWUpIHtcbiAgICByZXR1cm4gQml0U3RyaW5nLndyYXAodmFsdWUsIHt9LCBcIm5hdGl2ZVwiKTtcbiAgfVxuXG4gIHN0YXRpYyBiaWcodmFsdWUpIHtcbiAgICByZXR1cm4gQml0U3RyaW5nLndyYXAodmFsdWUsIHt9LCBcImJpZ1wiKTtcbiAgfVxuXG4gIHN0YXRpYyBsaXR0bGUodmFsdWUpIHtcbiAgICByZXR1cm4gQml0U3RyaW5nLndyYXAodmFsdWUsIHt9LCBcImxpdHRsZVwiKTtcbiAgfVxuXG4gIHN0YXRpYyBzaXplKHZhbHVlLCBjb3VudCkge1xuICAgIHJldHVybiBCaXRTdHJpbmcud3JhcCh2YWx1ZSwgeyBcInNpemVcIjogY291bnQgfSk7XG4gIH1cblxuICBzdGF0aWMgdW5pdCh2YWx1ZSwgY291bnQpIHtcbiAgICByZXR1cm4gQml0U3RyaW5nLndyYXAodmFsdWUsIHsgXCJ1bml0XCI6IGNvdW50IH0pO1xuICB9XG5cbiAgc3RhdGljIHdyYXAodmFsdWUsIG9wdCwgbmV3X2F0dHJpYnV0ZSA9IG51bGwpIHtcbiAgICBsZXQgdGhlX3ZhbHVlID0gdmFsdWU7XG5cbiAgICBpZiAoISh2YWx1ZSBpbnN0YW5jZW9mIE9iamVjdCkpIHtcbiAgICAgIHRoZV92YWx1ZSA9IHsgXCJ2YWx1ZVwiOiB2YWx1ZSwgXCJhdHRyaWJ1dGVzXCI6IFtdIH07XG4gICAgfVxuXG4gICAgdGhlX3ZhbHVlID0gT2JqZWN0LmFzc2lnbih0aGVfdmFsdWUsIG9wdCk7XG5cbiAgICBpZiAobmV3X2F0dHJpYnV0ZSkge1xuICAgICAgdGhlX3ZhbHVlLmF0dHJpYnV0ZXMucHVzaChuZXdfYXR0cmlidXRlKTtcbiAgICB9XG5cbiAgICByZXR1cm4gdGhlX3ZhbHVlO1xuICB9XG5cbiAgc3RhdGljIHRvVVRGOEFycmF5KHN0cikge1xuICAgIHZhciB1dGY4ID0gW107XG4gICAgZm9yICh2YXIgaSA9IDA7IGkgPCBzdHIubGVuZ3RoOyBpKyspIHtcbiAgICAgIHZhciBjaGFyY29kZSA9IHN0ci5jaGFyQ29kZUF0KGkpO1xuICAgICAgaWYgKGNoYXJjb2RlIDwgMTI4KSB7XG4gICAgICAgIHV0ZjgucHVzaChjaGFyY29kZSk7XG4gICAgICB9IGVsc2UgaWYgKGNoYXJjb2RlIDwgMjA0OCkge1xuICAgICAgICB1dGY4LnB1c2goMTkyIHwgY2hhcmNvZGUgPj4gNiwgMTI4IHwgY2hhcmNvZGUgJiA2Myk7XG4gICAgICB9IGVsc2UgaWYgKGNoYXJjb2RlIDwgNTUyOTYgfHwgY2hhcmNvZGUgPj0gNTczNDQpIHtcbiAgICAgICAgdXRmOC5wdXNoKDIyNCB8IGNoYXJjb2RlID4+IDEyLCAxMjggfCBjaGFyY29kZSA+PiA2ICYgNjMsIDEyOCB8IGNoYXJjb2RlICYgNjMpO1xuICAgICAgfVxuICAgICAgLy8gc3Vycm9nYXRlIHBhaXJcbiAgICAgIGVsc2Uge1xuICAgICAgICBpKys7XG4gICAgICAgIC8vIFVURi0xNiBlbmNvZGVzIDB4MTAwMDAtMHgxMEZGRkYgYnlcbiAgICAgICAgLy8gc3VidHJhY3RpbmcgMHgxMDAwMCBhbmQgc3BsaXR0aW5nIHRoZVxuICAgICAgICAvLyAyMCBiaXRzIG9mIDB4MC0weEZGRkZGIGludG8gdHdvIGhhbHZlc1xuICAgICAgICBjaGFyY29kZSA9IDY1NTM2ICsgKChjaGFyY29kZSAmIDEwMjMpIDw8IDEwIHwgc3RyLmNoYXJDb2RlQXQoaSkgJiAxMDIzKTtcbiAgICAgICAgdXRmOC5wdXNoKDI0MCB8IGNoYXJjb2RlID4+IDE4LCAxMjggfCBjaGFyY29kZSA+PiAxMiAmIDYzLCAxMjggfCBjaGFyY29kZSA+PiA2ICYgNjMsIDEyOCB8IGNoYXJjb2RlICYgNjMpO1xuICAgICAgfVxuICAgIH1cbiAgICByZXR1cm4gdXRmODtcbiAgfVxuXG4gIHN0YXRpYyB0b1VURjE2QXJyYXkoc3RyKSB7XG4gICAgdmFyIHV0ZjE2ID0gW107XG4gICAgZm9yICh2YXIgaSA9IDA7IGkgPCBzdHIubGVuZ3RoOyBpKyspIHtcbiAgICAgIHZhciBjb2RlUG9pbnQgPSBzdHIuY29kZVBvaW50QXQoaSk7XG5cbiAgICAgIGlmIChjb2RlUG9pbnQgPD0gMjU1KSB7XG4gICAgICAgIHV0ZjE2LnB1c2goMCk7XG4gICAgICAgIHV0ZjE2LnB1c2goY29kZVBvaW50KTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHV0ZjE2LnB1c2goY29kZVBvaW50ID4+IDggJiAyNTUpO1xuICAgICAgICB1dGYxNi5wdXNoKGNvZGVQb2ludCAmIDI1NSk7XG4gICAgICB9XG4gICAgfVxuICAgIHJldHVybiB1dGYxNjtcbiAgfVxuXG4gIHN0YXRpYyB0b1VURjMyQXJyYXkoc3RyKSB7XG4gICAgdmFyIHV0ZjMyID0gW107XG4gICAgZm9yICh2YXIgaSA9IDA7IGkgPCBzdHIubGVuZ3RoOyBpKyspIHtcbiAgICAgIHZhciBjb2RlUG9pbnQgPSBzdHIuY29kZVBvaW50QXQoaSk7XG5cbiAgICAgIGlmIChjb2RlUG9pbnQgPD0gMjU1KSB7XG4gICAgICAgIHV0ZjMyLnB1c2goMCk7XG4gICAgICAgIHV0ZjMyLnB1c2goMCk7XG4gICAgICAgIHV0ZjMyLnB1c2goMCk7XG4gICAgICAgIHV0ZjMyLnB1c2goY29kZVBvaW50KTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHV0ZjMyLnB1c2goMCk7XG4gICAgICAgIHV0ZjMyLnB1c2goMCk7XG4gICAgICAgIHV0ZjMyLnB1c2goY29kZVBvaW50ID4+IDggJiAyNTUpO1xuICAgICAgICB1dGYzMi5wdXNoKGNvZGVQb2ludCAmIDI1NSk7XG4gICAgICB9XG4gICAgfVxuICAgIHJldHVybiB1dGYzMjtcbiAgfVxuXG4gIC8vaHR0cDovL3N0YWNrb3ZlcmZsb3cuY29tL3F1ZXN0aW9ucy8yMDAzNDkzL2phdmFzY3JpcHQtZmxvYXQtZnJvbS10by1iaXRzXG4gIHN0YXRpYyBmbG9hdDMyVG9CeXRlcyhmKSB7XG4gICAgdmFyIGJ5dGVzID0gW107XG5cbiAgICB2YXIgYnVmID0gbmV3IEFycmF5QnVmZmVyKDQpO1xuICAgIG5ldyBGbG9hdDMyQXJyYXkoYnVmKVswXSA9IGY7XG5cbiAgICBsZXQgaW50VmVyc2lvbiA9IG5ldyBVaW50MzJBcnJheShidWYpWzBdO1xuXG4gICAgYnl0ZXMucHVzaChpbnRWZXJzaW9uID4+IDI0ICYgMjU1KTtcbiAgICBieXRlcy5wdXNoKGludFZlcnNpb24gPj4gMTYgJiAyNTUpO1xuICAgIGJ5dGVzLnB1c2goaW50VmVyc2lvbiA+PiA4ICYgMjU1KTtcbiAgICBieXRlcy5wdXNoKGludFZlcnNpb24gJiAyNTUpO1xuXG4gICAgcmV0dXJuIGJ5dGVzO1xuICB9XG5cbiAgc3RhdGljIGZsb2F0NjRUb0J5dGVzKGYpIHtcbiAgICB2YXIgYnl0ZXMgPSBbXTtcblxuICAgIHZhciBidWYgPSBuZXcgQXJyYXlCdWZmZXIoOCk7XG4gICAgbmV3IEZsb2F0NjRBcnJheShidWYpWzBdID0gZjtcblxuICAgIHZhciBpbnRWZXJzaW9uMSA9IG5ldyBVaW50MzJBcnJheShidWYpWzBdO1xuICAgIHZhciBpbnRWZXJzaW9uMiA9IG5ldyBVaW50MzJBcnJheShidWYpWzFdO1xuXG4gICAgYnl0ZXMucHVzaChpbnRWZXJzaW9uMiA+PiAyNCAmIDI1NSk7XG4gICAgYnl0ZXMucHVzaChpbnRWZXJzaW9uMiA+PiAxNiAmIDI1NSk7XG4gICAgYnl0ZXMucHVzaChpbnRWZXJzaW9uMiA+PiA4ICYgMjU1KTtcbiAgICBieXRlcy5wdXNoKGludFZlcnNpb24yICYgMjU1KTtcblxuICAgIGJ5dGVzLnB1c2goaW50VmVyc2lvbjEgPj4gMjQgJiAyNTUpO1xuICAgIGJ5dGVzLnB1c2goaW50VmVyc2lvbjEgPj4gMTYgJiAyNTUpO1xuICAgIGJ5dGVzLnB1c2goaW50VmVyc2lvbjEgPj4gOCAmIDI1NSk7XG4gICAgYnl0ZXMucHVzaChpbnRWZXJzaW9uMSAmIDI1NSk7XG5cbiAgICByZXR1cm4gYnl0ZXM7XG4gIH1cbn1cblxubGV0IEVudW0gPSB7XG5cbiAgYWxsX19xbWFya19fOiBmdW5jdGlvbiAoY29sbGVjdGlvbiwgZnVuID0geCA9PiB4KSB7XG4gICAgZm9yIChsZXQgZWxlbSBvZiBjb2xsZWN0aW9uKSB7XG4gICAgICBpZiAoIWZ1bihlbGVtKSkge1xuICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICB9XG4gICAgfVxuXG4gICAgcmV0dXJuIHRydWU7XG4gIH0sXG5cbiAgYW55X19xbWFya19fOiBmdW5jdGlvbiAoY29sbGVjdGlvbiwgZnVuID0geCA9PiB4KSB7XG4gICAgZm9yIChsZXQgZWxlbSBvZiBjb2xsZWN0aW9uKSB7XG4gICAgICBpZiAoZnVuKGVsZW0pKSB7XG4gICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgfVxuICAgIH1cblxuICAgIHJldHVybiBmYWxzZTtcbiAgfSxcblxuICBhdDogZnVuY3Rpb24gKGNvbGxlY3Rpb24sIG4sIHRoZV9kZWZhdWx0ID0gbnVsbCkge1xuICAgIGlmIChuID4gdGhpcy5jb3VudChjb2xsZWN0aW9uKSB8fCBuIDwgMCkge1xuICAgICAgcmV0dXJuIHRoZV9kZWZhdWx0O1xuICAgIH1cblxuICAgIHJldHVybiBjb2xsZWN0aW9uW25dO1xuICB9LFxuXG4gIGNvbmNhdDogZnVuY3Rpb24gKC4uLmVudW1hYmxlcykge1xuICAgIHJldHVybiBlbnVtYWJsZXNbMF0uY29uY2F0KGVudW1hYmxlc1sxXSk7XG4gIH0sXG5cbiAgY291bnQ6IGZ1bmN0aW9uIChjb2xsZWN0aW9uLCBmdW4gPSBudWxsKSB7XG4gICAgaWYgKGZ1biA9PSBudWxsKSB7XG4gICAgICByZXR1cm4gY29sbGVjdGlvbi5sZW5ndGg7XG4gICAgfSBlbHNlIHtcbiAgICAgIHJldHVybiBjb2xsZWN0aW9uLmZpbHRlcihmdW4pLmxlbmd0aDtcbiAgICB9XG4gIH0sXG5cbiAgZHJvcDogZnVuY3Rpb24gKGNvbGxlY3Rpb24sIGNvdW50KSB7XG4gICAgcmV0dXJuIGNvbGxlY3Rpb24uc2xpY2UoY291bnQpO1xuICB9LFxuXG4gIGRyb3Bfd2hpbGU6IGZ1bmN0aW9uIChjb2xsZWN0aW9uLCBmdW4pIHtcbiAgICBsZXQgY291bnQgPSAwO1xuXG4gICAgZm9yIChsZXQgZWxlbSBvZiBjb2xsZWN0aW9uKSB7XG4gICAgICBpZiAoZnVuKGVsZW0pKSB7XG4gICAgICAgIGNvdW50ID0gY291bnQgKyAxO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgYnJlYWs7XG4gICAgICB9XG4gICAgfVxuXG4gICAgcmV0dXJuIGNvbGxlY3Rpb24uc2xpY2UoY291bnQpO1xuICB9LFxuXG4gIGVhY2g6IGZ1bmN0aW9uIChjb2xsZWN0aW9uLCBmdW4pIHtcbiAgICBmb3IgKGxldCBlbGVtIG9mIGNvbGxlY3Rpb24pIHtcbiAgICAgIGZ1bihlbGVtKTtcbiAgICB9XG4gIH0sXG5cbiAgZW1wdHlfX3FtYXJrX186IGZ1bmN0aW9uIChjb2xsZWN0aW9uKSB7XG4gICAgcmV0dXJuIGNvbGxlY3Rpb24ubGVuZ3RoID09PSAwO1xuICB9LFxuXG4gIGZldGNoOiBmdW5jdGlvbiAoY29sbGVjdGlvbiwgbikge1xuICAgIGlmIChLZXJuZWwuaXNfbGlzdChjb2xsZWN0aW9uKSkge1xuICAgICAgaWYgKG4gPCB0aGlzLmNvdW50KGNvbGxlY3Rpb24pICYmIG4gPj0gMCkge1xuICAgICAgICByZXR1cm4gS2VybmVsLlNwZWNpYWxGb3Jtcy50dXBsZShLZXJuZWwuU3BlY2lhbEZvcm1zLmF0b20oXCJva1wiKSwgY29sbGVjdGlvbltuXSk7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICByZXR1cm4gS2VybmVsLlNwZWNpYWxGb3Jtcy5hdG9tKFwiZXJyb3JcIik7XG4gICAgICB9XG4gICAgfVxuXG4gICAgdGhyb3cgbmV3IEVycm9yKFwiY29sbGVjdGlvbiBpcyBub3QgYW4gRW51bWVyYWJsZVwiKTtcbiAgfSxcblxuICBmZXRjaF9fZW1hcmtfXzogZnVuY3Rpb24gKGNvbGxlY3Rpb24sIG4pIHtcbiAgICBpZiAoS2VybmVsLmlzX2xpc3QoY29sbGVjdGlvbikpIHtcbiAgICAgIGlmIChuIDwgdGhpcy5jb3VudChjb2xsZWN0aW9uKSAmJiBuID49IDApIHtcbiAgICAgICAgcmV0dXJuIGNvbGxlY3Rpb25bbl07XG4gICAgICB9IGVsc2Uge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoXCJvdXQgb2YgYm91bmRzIGVycm9yXCIpO1xuICAgICAgfVxuICAgIH1cblxuICAgIHRocm93IG5ldyBFcnJvcihcImNvbGxlY3Rpb24gaXMgbm90IGFuIEVudW1lcmFibGVcIik7XG4gIH0sXG5cbiAgZmlsdGVyOiBmdW5jdGlvbiAoY29sbGVjdGlvbiwgZnVuKSB7XG4gICAgbGV0IHJlc3VsdCA9IFtdO1xuXG4gICAgZm9yIChsZXQgZWxlbSBvZiBjb2xsZWN0aW9uKSB7XG4gICAgICBpZiAoZnVuKGVsZW0pKSB7XG4gICAgICAgIHJlc3VsdC5wdXNoKGVsZW0pO1xuICAgICAgfVxuICAgIH1cblxuICAgIHJldHVybiByZXN1bHQ7XG4gIH0sXG5cbiAgZmlsdGVyX21hcDogZnVuY3Rpb24gKGNvbGxlY3Rpb24sIGZpbHRlciwgbWFwcGVyKSB7XG4gICAgcmV0dXJuIEVudW0ubWFwKEVudW0uZmlsdGVyKGNvbGxlY3Rpb24sIGZpbHRlciksIG1hcHBlcik7XG4gIH0sXG5cbiAgZmluZDogZnVuY3Rpb24gKGNvbGxlY3Rpb24sIGlmX25vbmUgPSBudWxsLCBmdW4pIHtcbiAgICBmb3IgKGxldCBlbGVtIG9mIGNvbGxlY3Rpb24pIHtcbiAgICAgIGlmIChmdW4oZWxlbSkpIHtcbiAgICAgICAgcmV0dXJuIGVsZW07XG4gICAgICB9XG4gICAgfVxuXG4gICAgcmV0dXJuIGlmX25vbmU7XG4gIH0sXG5cbiAgaW50bzogZnVuY3Rpb24gKGNvbGxlY3Rpb24sIGxpc3QpIHtcbiAgICByZXR1cm4gbGlzdC5jb25jYXQoY29sbGVjdGlvbik7XG4gIH0sXG5cbiAgbWFwOiBmdW5jdGlvbiAoY29sbGVjdGlvbiwgZnVuKSB7XG4gICAgbGV0IHJlc3VsdCA9IFtdO1xuXG4gICAgZm9yIChsZXQgZWxlbSBvZiBjb2xsZWN0aW9uKSB7XG4gICAgICByZXN1bHQucHVzaChmdW4oZWxlbSkpO1xuICAgIH1cblxuICAgIHJldHVybiByZXN1bHQ7XG4gIH0sXG5cbiAgbWFwX3JlZHVjZTogZnVuY3Rpb24gKGNvbGxlY3Rpb24sIGFjYywgZnVuKSB7XG4gICAgbGV0IG1hcHBlZCA9IEtlcm5lbC5TcGVjaWFsRm9ybXMubGlzdCgpO1xuICAgIGxldCB0aGVfYWNjID0gYWNjO1xuXG4gICAgZm9yICh2YXIgaSA9IDA7IGkgPCB0aGlzLmNvdW50KGNvbGxlY3Rpb24pOyBpKyspIHtcbiAgICAgIGxldCB0dXBsZSA9IGZ1bihjb2xsZWN0aW9uW2ldLCB0aGVfYWNjKTtcblxuICAgICAgdGhlX2FjYyA9IEtlcm5lbC5lbGVtKHR1cGxlLCAxKTtcbiAgICAgIG1hcHBlZCA9IEtlcm5lbC5TcGVjaWFsRm9ybXMubGlzdCguLi5tYXBwZWQuY29uY2F0KFtLZXJuZWwuZWxlbSh0dXBsZSwgMCldKSk7XG4gICAgfVxuXG4gICAgcmV0dXJuIEtlcm5lbC5TcGVjaWFsRm9ybXMudHVwbGUobWFwcGVkLCB0aGVfYWNjKTtcbiAgfSxcblxuICBtZW1iZXI6IGZ1bmN0aW9uIChjb2xsZWN0aW9uLCB2YWx1ZSkge1xuICAgIHJldHVybiBjb2xsZWN0aW9uLmluY2x1ZGVzKHZhbHVlKTtcbiAgfSxcblxuICByZWR1Y2U6IGZ1bmN0aW9uIChjb2xsZWN0aW9uLCBhY2MsIGZ1bikge1xuICAgIGxldCB0aGVfYWNjID0gYWNjO1xuXG4gICAgZm9yICh2YXIgaSA9IDA7IGkgPCB0aGlzLmNvdW50KGNvbGxlY3Rpb24pOyBpKyspIHtcbiAgICAgIGxldCB0dXBsZSA9IGZ1bihjb2xsZWN0aW9uW2ldLCB0aGVfYWNjKTtcblxuICAgICAgdGhlX2FjYyA9IEtlcm5lbC5lbGVtKHR1cGxlLCAxKTtcbiAgICB9XG5cbiAgICByZXR1cm4gdGhlX2FjYztcbiAgfSxcblxuICB0YWtlOiBmdW5jdGlvbiAoY29sbGVjdGlvbiwgY291bnQpIHtcbiAgICByZXR1cm4gY29sbGVjdGlvbi5zbGljZSgwLCBjb3VudCk7XG4gIH0sXG5cbiAgdGFrZV9ldmVyeTogZnVuY3Rpb24gKGNvbGxlY3Rpb24sIG50aCkge1xuICAgIGxldCByZXN1bHQgPSBbXTtcbiAgICBsZXQgaW5kZXggPSAwO1xuXG4gICAgZm9yIChsZXQgZWxlbSBvZiBjb2xsZWN0aW9uKSB7XG4gICAgICBpZiAoaW5kZXggJSBudGggPT09IDApIHtcbiAgICAgICAgcmVzdWx0LnB1c2goZWxlbSk7XG4gICAgICB9XG4gICAgfVxuXG4gICAgcmV0dXJuIEtlcm5lbC5TcGVjaWFsRm9ybXMubGlzdCguLi5yZXN1bHQpO1xuICB9LFxuXG4gIHRha2Vfd2hpbGU6IGZ1bmN0aW9uIChjb2xsZWN0aW9uLCBmdW4pIHtcbiAgICBsZXQgY291bnQgPSAwO1xuXG4gICAgZm9yIChsZXQgZWxlbSBvZiBjb2xsZWN0aW9uKSB7XG4gICAgICBpZiAoZnVuKGVsZW0pKSB7XG4gICAgICAgIGNvdW50ID0gY291bnQgKyAxO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgYnJlYWs7XG4gICAgICB9XG4gICAgfVxuXG4gICAgcmV0dXJuIGNvbGxlY3Rpb24uc2xpY2UoMCwgY291bnQpO1xuICB9LFxuXG4gIHRvX2xpc3Q6IGZ1bmN0aW9uIChjb2xsZWN0aW9uKSB7XG4gICAgcmV0dXJuIGNvbGxlY3Rpb247XG4gIH1cbn07XG5cbmxldCBTcGVjaWFsRm9ybXMgPSB7XG5cbiAgX19ESVJfXzogZnVuY3Rpb24gKCkge1xuICAgIGlmIChfX2Rpcm5hbWUpIHtcbiAgICAgIHJldHVybiBfX2Rpcm5hbWU7XG4gICAgfVxuXG4gICAgaWYgKGRvY3VtZW50LmN1cnJlbnRTY3JpcHQpIHtcbiAgICAgIHJldHVybiBkb2N1bWVudC5jdXJyZW50U2NyaXB0LnNyYztcbiAgICB9XG5cbiAgICByZXR1cm4gbnVsbDtcbiAgfSxcblxuICBhdG9tOiBmdW5jdGlvbiAoX3ZhbHVlKSB7XG4gICAgcmV0dXJuIFN5bWJvbC5mb3IoX3ZhbHVlKTtcbiAgfSxcblxuICBsaXN0OiBmdW5jdGlvbiAoLi4uYXJncykge1xuICAgIHJldHVybiBPYmplY3QuZnJlZXplKGFyZ3MpO1xuICB9LFxuXG4gIGJpdHN0cmluZzogZnVuY3Rpb24gKC4uLmFyZ3MpIHtcbiAgICByZXR1cm4gbmV3IEJpdFN0cmluZyguLi5hcmdzKTtcbiAgfSxcblxuICBib3VuZDogZnVuY3Rpb24gKF92YXIpIHtcbiAgICByZXR1cm4gdW5kZWZpbmVkKF92YXIpO1xuICB9LFxuXG4gIF9jYXNlOiBmdW5jdGlvbiAoY29uZGl0aW9uLCBjbGF1c2VzKSB7XG4gICAgcmV0dXJuIHVuZGVmaW5lZCguLi5jbGF1c2VzKShjb25kaXRpb24pO1xuICB9LFxuXG4gIGNvbmQ6IGZ1bmN0aW9uIChjbGF1c2VzKSB7XG4gICAgZm9yIChsZXQgY2xhdXNlIG9mIGNsYXVzZXMpIHtcbiAgICAgIGlmIChjbGF1c2VbMF0pIHtcbiAgICAgICAgcmV0dXJuIGNsYXVzZVsxXSgpO1xuICAgICAgfVxuICAgIH1cblxuICAgIHRocm93IG5ldyBFcnJvcigpO1xuICB9LFxuXG4gIGZuOiBmdW5jdGlvbiAoY2xhdXNlcykge1xuICAgIHJldHVybiB1bmRlZmluZWQoY2xhdXNlcyk7XG4gIH0sXG5cbiAgbWFwOiBmdW5jdGlvbiAob2JqKSB7XG4gICAgcmV0dXJuIE9iamVjdC5mcmVlemUob2JqKTtcbiAgfSxcblxuICBtYXBfdXBkYXRlOiBmdW5jdGlvbiAobWFwLCB2YWx1ZXMpIHtcbiAgICByZXR1cm4gT2JqZWN0LmZyZWV6ZShPYmplY3QuYXNzaWduKE9iamVjdC5jcmVhdGUobWFwLmNvbnN0cnVjdG9yLnByb3RvdHlwZSksIG1hcCwgdmFsdWVzKSk7XG4gIH0sXG5cbiAgX2ZvcjogZnVuY3Rpb24gKGNvbGxlY3Rpb25zLCBmdW4sIGZpbHRlciA9ICgpID0+IHRydWUsIGludG8gPSBbXSwgcHJldmlvdXNWYWx1ZXMgPSBbXSkge1xuICAgIGxldCBwYXR0ZXJuID0gY29sbGVjdGlvbnNbMF1bMF07XG4gICAgbGV0IGNvbGxlY3Rpb24gPSBjb2xsZWN0aW9uc1swXVsxXTtcblxuICAgIGlmIChjb2xsZWN0aW9ucy5sZW5ndGggPT09IDEpIHtcblxuICAgICAgZm9yIChsZXQgZWxlbSBvZiBjb2xsZWN0aW9uKSB7XG4gICAgICAgIGxldCByID0gdW5kZWZpbmVkKHBhdHRlcm4sIGVsZW0pO1xuICAgICAgICBsZXQgYXJncyA9IHByZXZpb3VzVmFsdWVzLmNvbmNhdChyKTtcblxuICAgICAgICBpZiAociAmJiBmaWx0ZXIuYXBwbHkodGhpcywgYXJncykpIHtcbiAgICAgICAgICBpbnRvID0gRW51bS5pbnRvKFtmdW4uYXBwbHkodGhpcywgYXJncyldLCBpbnRvKTtcbiAgICAgICAgfVxuICAgICAgfVxuXG4gICAgICByZXR1cm4gaW50bztcbiAgICB9IGVsc2Uge1xuICAgICAgbGV0IF9pbnRvID0gW107XG5cbiAgICAgIGZvciAobGV0IGVsZW0gb2YgY29sbGVjdGlvbikge1xuICAgICAgICBsZXQgciA9IHVuZGVmaW5lZChwYXR0ZXJuLCBlbGVtKTtcbiAgICAgICAgaWYgKHIpIHtcbiAgICAgICAgICBfaW50byA9IEVudW0uaW50byh0aGlzLl9mb3IoY29sbGVjdGlvbnMuc2xpY2UoMSksIGZ1biwgZmlsdGVyLCBfaW50bywgcHJldmlvdXNWYWx1ZXMuY29uY2F0KHIpKSwgaW50byk7XG4gICAgICAgIH1cbiAgICAgIH1cblxuICAgICAgcmV0dXJuIF9pbnRvO1xuICAgIH1cbiAgfSxcblxuICByZWNlaXZlOiBmdW5jdGlvbiAocmVjZWl2ZV9mdW4sIHRpbWVvdXRfaW5fbXMgPSBudWxsLCB0aW1lb3V0X2ZuID0gdGltZSA9PiB0cnVlKSB7XG4gICAgaWYgKHRpbWVvdXRfaW5fbXMgPT0gbnVsbCB8fCB0aW1lb3V0X2luX21zID09PSBTeXN0ZW0uZm9yKCdpbmZpbml0eScpKSB7XG4gICAgICB3aGlsZSAodHJ1ZSkge1xuICAgICAgICBpZiAoc2VsZi5tYWlsYm94Lmxlbmd0aCAhPT0gMCkge1xuICAgICAgICAgIGxldCBtZXNzYWdlID0gc2VsZi5tYWlsYm94WzBdO1xuICAgICAgICAgIHNlbGYubWFpbGJveCA9IHNlbGYubWFpbGJveC5zbGljZSgxKTtcbiAgICAgICAgICByZXR1cm4gcmVjZWl2ZV9mdW4obWVzc2FnZSk7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9IGVsc2UgaWYgKHRpbWVvdXRfaW5fbXMgPT09IDApIHtcbiAgICAgIGlmIChzZWxmLm1haWxib3gubGVuZ3RoICE9PSAwKSB7XG4gICAgICAgIGxldCBtZXNzYWdlID0gc2VsZi5tYWlsYm94WzBdO1xuICAgICAgICBzZWxmLm1haWxib3ggPSBzZWxmLm1haWxib3guc2xpY2UoMSk7XG4gICAgICAgIHJldHVybiByZWNlaXZlX2Z1bihtZXNzYWdlKTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHJldHVybiBudWxsO1xuICAgICAgfVxuICAgIH0gZWxzZSB7XG4gICAgICBsZXQgbm93ID0gRGF0ZS5ub3coKTtcbiAgICAgIHdoaWxlIChEYXRlLm5vdygpIDwgbm93ICsgdGltZW91dF9pbl9tcykge1xuICAgICAgICBpZiAoc2VsZi5tYWlsYm94Lmxlbmd0aCAhPT0gMCkge1xuICAgICAgICAgIGxldCBtZXNzYWdlID0gc2VsZi5tYWlsYm94WzBdO1xuICAgICAgICAgIHNlbGYubWFpbGJveCA9IHNlbGYubWFpbGJveC5zbGljZSgxKTtcbiAgICAgICAgICByZXR1cm4gcmVjZWl2ZV9mdW4obWVzc2FnZSk7XG4gICAgICAgIH1cbiAgICAgIH1cblxuICAgICAgcmV0dXJuIHRpbWVvdXRfZm4odGltZW91dF9pbl9tcyk7XG4gICAgfVxuICB9LFxuXG4gIHR1cGxlOiBmdW5jdGlvbiAoLi4uYXJncykge1xuICAgIHJldHVybiBuZXcgQ29yZS5UdXBsZSguLi5hcmdzKTtcbiAgfSxcblxuICBfdHJ5OiBmdW5jdGlvbiAoZG9fZnVuLCByZXNjdWVfZnVuY3Rpb24sIGNhdGNoX2Z1biwgZWxzZV9mdW5jdGlvbiwgYWZ0ZXJfZnVuY3Rpb24pIHtcbiAgICBsZXQgcmVzdWx0ID0gbnVsbDtcblxuICAgIHRyeSB7XG4gICAgICByZXN1bHQgPSBkb19mdW4oKTtcbiAgICB9IGNhdGNoIChlKSB7XG4gICAgICBsZXQgZXhfcmVzdWx0ID0gbnVsbDtcblxuICAgICAgaWYgKHJlc2N1ZV9mdW5jdGlvbikge1xuICAgICAgICB0cnkge1xuICAgICAgICAgIGV4X3Jlc3VsdCA9IHJlc2N1ZV9mdW5jdGlvbihlKTtcbiAgICAgICAgICByZXR1cm4gZXhfcmVzdWx0O1xuICAgICAgICB9IGNhdGNoIChleCkge1xuICAgICAgICAgIGlmIChleCBpbnN0YW5jZW9mIHVuZGVmaW5lZCkge1xuICAgICAgICAgICAgdGhyb3cgZXg7XG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICB9XG5cbiAgICAgIGlmIChjYXRjaF9mdW4pIHtcbiAgICAgICAgdHJ5IHtcbiAgICAgICAgICBleF9yZXN1bHQgPSBjYXRjaF9mdW4oZSk7XG4gICAgICAgICAgcmV0dXJuIGV4X3Jlc3VsdDtcbiAgICAgICAgfSBjYXRjaCAoZXgpIHtcbiAgICAgICAgICBpZiAoZXggaW5zdGFuY2VvZiB1bmRlZmluZWQpIHtcbiAgICAgICAgICAgIHRocm93IGV4O1xuICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgfVxuXG4gICAgICB0aHJvdyBlO1xuICAgIH0gZmluYWxseSB7XG4gICAgICBpZiAoYWZ0ZXJfZnVuY3Rpb24pIHtcbiAgICAgICAgYWZ0ZXJfZnVuY3Rpb24oKTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICBpZiAoZWxzZV9mdW5jdGlvbikge1xuICAgICAgdHJ5IHtcbiAgICAgICAgcmV0dXJuIGVsc2VfZnVuY3Rpb24ocmVzdWx0KTtcbiAgICAgIH0gY2F0Y2ggKGV4KSB7XG4gICAgICAgIGlmIChleCBpbnN0YW5jZW9mIHVuZGVmaW5lZCkge1xuICAgICAgICAgIHRocm93IG5ldyBFcnJvcignTm8gTWF0Y2ggRm91bmQgaW4gRWxzZScpO1xuICAgICAgICB9XG5cbiAgICAgICAgdGhyb3cgZXg7XG4gICAgICB9XG4gICAgfSBlbHNlIHtcbiAgICAgIHJldHVybiByZXN1bHQ7XG4gICAgfVxuICB9XG5cbn07XG5cbmZ1bmN0aW9uIHRvX3N0cmluZyQxKHR1cGxlKSB7XG4gIHJldHVybiB0dXBsZS50b1N0cmluZygpO1xufTtcblxuZnVuY3Rpb24gZGVsZXRlX2F0KHR1cGxlLCBpbmRleCkge1xuICBsZXQgbmV3X2xpc3QgPSBbXTtcblxuICBmb3IgKHZhciBpID0gMDsgaSA8IHR1cGxlLmNvdW50KCk7IGkrKykge1xuICAgIGlmIChpICE9PSBpbmRleCkge1xuICAgICAgbmV3X2xpc3QucHVzaCh0dXBsZS5nZXQoaSkpO1xuICAgIH1cbiAgfVxuXG4gIHJldHVybiBLZXJuZWwuU3BlY2lhbEZvcm1zLnR1cGxlLmFwcGx5KG51bGwsIG5ld19saXN0KTtcbn07XG5cbmZ1bmN0aW9uIGR1cGxpY2F0ZShkYXRhLCBzaXplKSB7XG4gIGxldCBhcnJheSA9IFtdO1xuXG4gIGZvciAodmFyIGkgPSBzaXplIC0gMTsgaSA+PSAwOyBpLS0pIHtcbiAgICBhcnJheS5wdXNoKGRhdGEpO1xuICB9XG5cbiAgcmV0dXJuIEtlcm5lbC5TcGVjaWFsRm9ybXMudHVwbGUuYXBwbHkobnVsbCwgYXJyYXkpO1xufTtcblxuZnVuY3Rpb24gaW5zZXJ0X2F0KHR1cGxlLCBpbmRleCwgdGVybSkge1xuICBsZXQgbmV3X3R1cGxlID0gW107XG5cbiAgZm9yICh2YXIgaSA9IDA7IGkgPD0gdHVwbGUuY291bnQoKTsgaSsrKSB7XG4gICAgaWYgKGkgPT09IGluZGV4KSB7XG4gICAgICBuZXdfdHVwbGUucHVzaCh0ZXJtKTtcbiAgICAgIGkrKztcbiAgICAgIG5ld190dXBsZS5wdXNoKHR1cGxlLmdldChpKSk7XG4gICAgfSBlbHNlIHtcbiAgICAgIG5ld190dXBsZS5wdXNoKHR1cGxlLmdldChpKSk7XG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIEtlcm5lbC5TcGVjaWFsRm9ybXMudHVwbGUuYXBwbHkobnVsbCwgbmV3X3R1cGxlKTtcbn07XG5cbmZ1bmN0aW9uIGZyb21fbGlzdChsaXN0KSB7XG4gIHJldHVybiBLZXJuZWwuU3BlY2lhbEZvcm1zLnR1cGxlLmFwcGx5KG51bGwsIGxpc3QpO1xufTtcblxuZnVuY3Rpb24gdG9fbGlzdCh0dXBsZSkge1xuICBsZXQgbmV3X2xpc3QgPSBbXTtcblxuICBmb3IgKHZhciBpID0gMDsgaSA8IHR1cGxlLmNvdW50KCk7IGkrKykge1xuICAgIG5ld19saXN0LnB1c2godHVwbGUuZ2V0KGkpKTtcbiAgfVxuXG4gIHJldHVybiBLZXJuZWwuU3BlY2lhbEZvcm1zLmxpc3QoLi4ubmV3X2xpc3QpO1xufTtcblxudmFyIFR1cGxlID0ge1xuICB0b19zdHJpbmc6IHRvX3N0cmluZyQxLFxuICBkZWxldGVfYXQsXG4gIGR1cGxpY2F0ZSxcbiAgaW5zZXJ0X2F0LFxuICBmcm9tX2xpc3QsXG4gIHRvX2xpc3Rcbn07XG5cbmNsYXNzIEludGVnZXJUeXBlIHt9XG5jbGFzcyBGbG9hdFR5cGUge31cblxuLy9odHRwczovL2dpdGh1Yi5jb20vYWlycG9ydHloL3Byb3RvbW9ycGhpc21cbmNsYXNzIFByb3RvY29sIHtcbiAgY29uc3RydWN0b3Ioc3BlYykge1xuICAgIHRoaXMucmVnaXN0cnkgPSBuZXcgTWFwKCk7XG4gICAgdGhpcy5mYWxsYmFjayA9IG51bGw7XG5cbiAgICBmb3IgKGxldCBmdW5OYW1lIGluIHNwZWMpIHtcbiAgICAgIHRoaXNbZnVuTmFtZV0gPSBjcmVhdGVGdW4oZnVuTmFtZSkuYmluZCh0aGlzKTtcbiAgICB9XG5cbiAgICBmdW5jdGlvbiBjcmVhdGVGdW4oZnVuTmFtZSkge1xuXG4gICAgICByZXR1cm4gZnVuY3Rpb24gKC4uLmFyZ3MpIHtcbiAgICAgICAgbGV0IHRoaW5nID0gYXJnc1swXTtcbiAgICAgICAgbGV0IGZ1biA9IG51bGw7XG5cbiAgICAgICAgaWYgKE51bWJlci5pc0ludGVnZXIodGhpbmcpICYmIHRoaXMuaGFzSW1wbGVtZW50YXRpb24oSW50ZWdlclR5cGUpKSB7XG4gICAgICAgICAgZnVuID0gdGhpcy5yZWdpc3RyeS5nZXQoSW50ZWdlclR5cGUpW2Z1bk5hbWVdO1xuICAgICAgICB9IGVsc2UgaWYgKHR5cGVvZiB0aGluZyA9PT0gXCJudW1iZXJcIiAmJiAhTnVtYmVyLmlzSW50ZWdlcih0aGluZykgJiYgdGhpcy5oYXNJbXBsZW1lbnRhdGlvbihGbG9hdFR5cGUpKSB7XG4gICAgICAgICAgZnVuID0gdGhpcy5yZWdpc3RyeS5nZXQoRmxvYXRUeXBlKVtmdW5OYW1lXTtcbiAgICAgICAgfSBlbHNlIGlmICh0aGlzLmhhc0ltcGxlbWVudGF0aW9uKHRoaW5nKSkge1xuICAgICAgICAgIGZ1biA9IHRoaXMucmVnaXN0cnkuZ2V0KHRoaW5nLmNvbnN0cnVjdG9yKVtmdW5OYW1lXTtcbiAgICAgICAgfSBlbHNlIGlmICh0aGlzLmZhbGxiYWNrKSB7XG4gICAgICAgICAgZnVuID0gdGhpcy5mYWxsYmFja1tmdW5OYW1lXTtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmIChmdW4gIT0gbnVsbCkge1xuICAgICAgICAgIGxldCByZXR2YWwgPSBmdW4uYXBwbHkodGhpcywgYXJncyk7XG4gICAgICAgICAgcmV0dXJuIHJldHZhbDtcbiAgICAgICAgfVxuXG4gICAgICAgIHRocm93IG5ldyBFcnJvcihcIk5vIGltcGxlbWVudGF0aW9uIGZvdW5kIGZvciBcIiArIHRoaW5nKTtcbiAgICAgIH07XG4gICAgfVxuICB9XG5cbiAgaW1wbGVtZW50YXRpb24odHlwZSwgaW1wbGVtZW50YXRpb24pIHtcbiAgICBpZiAodHlwZSA9PT0gbnVsbCkge1xuICAgICAgdGhpcy5mYWxsYmFjayA9IGltcGxlbWVudGF0aW9uO1xuICAgIH0gZWxzZSB7XG4gICAgICB0aGlzLnJlZ2lzdHJ5LnNldCh0eXBlLCBpbXBsZW1lbnRhdGlvbik7XG4gICAgfVxuICB9XG5cbiAgaGFzSW1wbGVtZW50YXRpb24odGhpbmcpIHtcbiAgICByZXR1cm4gdGhpcy5yZWdpc3RyeS5oYXModGhpbmcuY29uc3RydWN0b3IpO1xuICB9XG59XG5cbmZ1bmN0aW9uIHRsKGxpc3QpIHtcbiAgcmV0dXJuIFNwZWNpYWxGb3Jtcy5saXN0KC4uLmxpc3Quc2xpY2UoMSkpO1xufVxuXG5mdW5jdGlvbiBoZChsaXN0KSB7XG4gIHJldHVybiBsaXN0WzBdO1xufVxuXG5mdW5jdGlvbiBpc19uaWwoeCkge1xuICByZXR1cm4geCA9PT0gbnVsbDtcbn1cblxuZnVuY3Rpb24gaXNfYXRvbSh4KSB7XG4gIHJldHVybiB0eXBlb2YgeCA9PT0gJ3N5bWJvbCc7XG59XG5cbmZ1bmN0aW9uIGlzX2JpbmFyeSh4KSB7XG4gIHJldHVybiB0eXBlb2YgeCA9PT0gJ3N0cmluZycgfHwgeCBpbnN0YW5jZW9mIFN0cmluZztcbn1cblxuZnVuY3Rpb24gaXNfYm9vbGVhbih4KSB7XG4gIHJldHVybiB0eXBlb2YgeCA9PT0gJ2Jvb2xlYW4nIHx8IHggaW5zdGFuY2VvZiBCb29sZWFuO1xufVxuXG5mdW5jdGlvbiBpc19mdW5jdGlvbih4LCBhcml0eSA9IC0xKSB7XG4gIHJldHVybiB0eXBlb2YgeCA9PT0gJ2Z1bmN0aW9uJyB8fCB4IGluc3RhbmNlb2YgRnVuY3Rpb247XG59XG5cbmZ1bmN0aW9uIGlzX2Zsb2F0KHgpIHtcbiAgcmV0dXJuIGlzX251bWJlcih4KSAmJiAhTnVtYmVyLmlzSW50ZWdlcih4KTtcbn1cblxuZnVuY3Rpb24gaXNfaW50ZWdlcih4KSB7XG4gIHJldHVybiBOdW1iZXIuaXNJbnRlZ2VyKHgpO1xufVxuXG5mdW5jdGlvbiBpc19saXN0KHgpIHtcbiAgcmV0dXJuIHggaW5zdGFuY2VvZiBBcnJheTtcbn1cblxuZnVuY3Rpb24gaXNfbWFwKHgpIHtcbiAgcmV0dXJuIHR5cGVvZiB4ID09PSAnb2JqZWN0JyB8fCB4IGluc3RhbmNlb2YgT2JqZWN0O1xufVxuXG5mdW5jdGlvbiBpc19udW1iZXIoeCkge1xuICByZXR1cm4gdHlwZW9mIHggPT09ICdudW1iZXInO1xufVxuXG5mdW5jdGlvbiBpc190dXBsZSh4KSB7XG4gIHJldHVybiB4IGluc3RhbmNlb2YgQ29yZS5UdXBsZTtcbn1cblxuZnVuY3Rpb24gbGVuZ3RoKHgpIHtcbiAgcmV0dXJuIHgubGVuZ3RoO1xufVxuXG5mdW5jdGlvbiBpc19waWQoeCkge1xuICByZXR1cm4geCBpbnN0YW5jZW9mIENvcmUuUElEO1xufVxuXG5mdW5jdGlvbiBpc19wb3J0KHgpIHtcbiAgcmV0dXJuIGZhbHNlO1xufVxuXG5mdW5jdGlvbiBpc19yZWZlcmVuY2UoeCkge1xuICByZXR1cm4gZmFsc2U7XG59XG5cbmZ1bmN0aW9uIGlzX2JpdHN0cmluZyh4KSB7XG4gIHJldHVybiBpc19iaW5hcnkoeCkgfHwgeCBpbnN0YW5jZW9mIEJpdFN0cmluZztcbn1cblxuZnVuY3Rpb24gX19pbl9fKGxlZnQsIHJpZ2h0KSB7XG4gIGZvciAobGV0IHggb2YgcmlnaHQpIHtcbiAgICBpZiAobWF0Y2hfX3FtYXJrX18obGVmdCwgeCkpIHtcbiAgICAgIHJldHVybiB0cnVlO1xuICAgIH1cbiAgfVxuXG4gIHJldHVybiBmYWxzZTtcbn1cblxuZnVuY3Rpb24gYWJzKG51bWJlcikge1xuICByZXR1cm4gTWF0aC5hYnMobnVtYmVyKTtcbn1cblxuZnVuY3Rpb24gcm91bmQobnVtYmVyKSB7XG4gIHJldHVybiBNYXRoLnJvdW5kKG51bWJlcik7XG59XG5cbmZ1bmN0aW9uIGVsZW0odHVwbGUsIGluZGV4KSB7XG4gIGlmIChpc19saXN0KHR1cGxlKSkge1xuICAgIHJldHVybiB0dXBsZVtpbmRleF07XG4gIH1cblxuICByZXR1cm4gdHVwbGUuZ2V0KGluZGV4KTtcbn1cblxuZnVuY3Rpb24gcmVtKGxlZnQsIHJpZ2h0KSB7XG4gIHJldHVybiBsZWZ0ICUgcmlnaHQ7XG59XG5cbmZ1bmN0aW9uIGRpdihsZWZ0LCByaWdodCkge1xuICByZXR1cm4gbGVmdCAvIHJpZ2h0O1xufVxuXG5mdW5jdGlvbiBhbmQobGVmdCwgcmlnaHQpIHtcbiAgcmV0dXJuIGxlZnQgJiYgcmlnaHQ7XG59XG5cbmZ1bmN0aW9uIG9yKGxlZnQsIHJpZ2h0KSB7XG4gIHJldHVybiBsZWZ0IHx8IHJpZ2h0O1xufVxuXG5mdW5jdGlvbiBub3QoYXJnKSB7XG4gIHJldHVybiAhYXJnO1xufVxuXG5mdW5jdGlvbiBhcHBseSguLi5hcmdzKSB7XG4gIGlmIChhcmdzLmxlbmd0aCA9PT0gMykge1xuICAgIGxldCBtb2QgPSBhcmdzWzBdO1xuICAgIGxldCBmdW5jID0gYXJnc1sxXTtcbiAgICBsZXQgZnVuY19hcmdzID0gYXJnc1syXTtcbiAgICByZXR1cm4gbW9kW2Z1bmNdLmFwcGx5KG51bGwsIGZ1bmNfYXJncyk7XG4gIH0gZWxzZSB7XG4gICAgbGV0IGZ1bmMgPSBhcmdzWzBdO1xuICAgIGxldCBmdW5jX2FyZ3MgPSBhcmdzWzFdO1xuXG4gICAgcmV0dXJuIGZ1bmMuYXBwbHkobnVsbCwgZnVuY19hcmdzKTtcbiAgfVxufVxuXG5mdW5jdGlvbiB0b19zdHJpbmcoYXJnKSB7XG4gIGlmIChpc190dXBsZShhcmcpKSB7XG4gICAgcmV0dXJuIFR1cGxlLnRvX3N0cmluZyhhcmcpO1xuICB9XG5cbiAgcmV0dXJuIGFyZy50b1N0cmluZygpO1xufVxuXG5mdW5jdGlvbiBtYXRjaF9fcW1hcmtfXyhwYXR0ZXJuLCBleHByLCBndWFyZCA9ICgpID0+IHRydWUpIHtcbiAgcmV0dXJuIFBhdHRlcm5zLm1hdGNoX25vX3Rocm93KHBhdHRlcm4sIGV4cHIsIGd1YXJkKSAhPSBudWxsO1xufVxuXG5mdW5jdGlvbiBkZWZzdHJ1Y3QoZGVmYXVsdHMpIHtcbiAgcmV0dXJuIGNsYXNzIHtcbiAgICBjb25zdHJ1Y3Rvcih1cGRhdGUgPSB7fSkge1xuICAgICAgbGV0IHRoZV92YWx1ZXMgPSBPYmplY3QuYXNzaWduKGRlZmF1bHRzLCB1cGRhdGUpO1xuICAgICAgT2JqZWN0LmFzc2lnbih0aGlzLCB0aGVfdmFsdWVzKTtcbiAgICB9XG5cbiAgICBzdGF0aWMgY3JlYXRlKHVwZGF0ZXMgPSB7fSkge1xuICAgICAgbGV0IHggPSBuZXcgdGhpcyh1cGRhdGVzKTtcbiAgICAgIHJldHVybiBPYmplY3QuZnJlZXplKHgpO1xuICAgIH1cbiAgfTtcbn1cblxuZnVuY3Rpb24gZGVmcHJvdG9jb2woc3BlYykge1xuICByZXR1cm4gbmV3IFByb3RvY29sKHNwZWMpO1xufVxuXG5mdW5jdGlvbiBkZWZpbXBsKHByb3RvY29sLCB0eXBlLCBpbXBsKSB7XG4gIHByb3RvY29sLmltcGxlbWVudGF0aW9uKHR5cGUsIGltcGwpO1xufVxuXG52YXIgS2VybmVsID0ge1xuICBTcGVjaWFsRm9ybXMsXG4gIHRsLFxuICBoZCxcbiAgaXNfbmlsLFxuICBpc19hdG9tLFxuICBpc19iaW5hcnksXG4gIGlzX2Jvb2xlYW4sXG4gIGlzX2Z1bmN0aW9uLFxuICBpc19mbG9hdCxcbiAgaXNfaW50ZWdlcixcbiAgaXNfbGlzdCxcbiAgaXNfbWFwLFxuICBpc19udW1iZXIsXG4gIGlzX3R1cGxlLFxuICBsZW5ndGgsXG4gIGlzX3BpZCxcbiAgaXNfcG9ydCxcbiAgaXNfcmVmZXJlbmNlLFxuICBpc19iaXRzdHJpbmcsXG4gIGluOiBfX2luX18sXG4gIGFicyxcbiAgcm91bmQsXG4gIGVsZW0sXG4gIHJlbSxcbiAgZGl2LFxuICBhbmQsXG4gIG9yLFxuICBub3QsXG4gIGFwcGx5LFxuICB0b19zdHJpbmcsXG4gIG1hdGNoX19xbWFya19fLFxuICBkZWZzdHJ1Y3QsXG4gIGRlZnByb3RvY29sLFxuICBkZWZpbXBsXG59O1xuXG5sZXQgQXRvbSA9IHt9O1xuXG5BdG9tLnRvX3N0cmluZyA9IGZ1bmN0aW9uIChhdG9tKSB7XG4gIHJldHVybiBTeW1ib2wua2V5Rm9yKGF0b20pO1xufTtcblxuQXRvbS50b19jaGFyX2xpc3QgPSBmdW5jdGlvbiAoYXRvbSkge1xuICByZXR1cm4gQXRvbS50b19zdHJpbmcoYXRvbSkuc3BsaXQoJycpO1xufTtcblxubGV0IEludGVnZXIgPSB7XG5cbiAgaXNfZXZlbjogZnVuY3Rpb24gKG4pIHtcbiAgICByZXR1cm4gbiAlIDIgPT09IDA7XG4gIH0sXG5cbiAgaXNfb2RkOiBmdW5jdGlvbiAobikge1xuICAgIHJldHVybiBuICUgMiAhPT0gMDtcbiAgfSxcblxuICBwYXJzZTogZnVuY3Rpb24gKGJpbikge1xuICAgIGxldCByZXN1bHQgPSBwYXJzZUludChiaW4pO1xuXG4gICAgaWYgKGlzTmFOKHJlc3VsdCkpIHtcbiAgICAgIHJldHVybiBLZXJuZWwuU3BlY2lhbEZvcm1zLmF0b20oXCJlcnJvclwiKTtcbiAgICB9XG5cbiAgICBsZXQgaW5kZXhPZkRvdCA9IGJpbi5pbmRleE9mKFwiLlwiKTtcblxuICAgIGlmIChpbmRleE9mRG90ID49IDApIHtcbiAgICAgIHJldHVybiBLZXJuZWwuU3BlY2lhbEZvcm1zLnR1cGxlKHJlc3VsdCwgYmluLnN1YnN0cmluZyhpbmRleE9mRG90KSk7XG4gICAgfVxuXG4gICAgcmV0dXJuIEtlcm5lbC5TcGVjaWFsRm9ybXMudHVwbGUocmVzdWx0LCBcIlwiKTtcbiAgfSxcblxuICB0b19jaGFyX2xpc3Q6IGZ1bmN0aW9uIChudW1iZXIsIGJhc2UgPSAxMCkge1xuICAgIHJldHVybiBudW1iZXIudG9TdHJpbmcoYmFzZSkuc3BsaXQoXCJcIik7XG4gIH0sXG5cbiAgdG9fc3RyaW5nOiBmdW5jdGlvbiAobnVtYmVyLCBiYXNlID0gMTApIHtcbiAgICByZXR1cm4gbnVtYmVyLnRvU3RyaW5nKGJhc2UpO1xuICB9XG59O1xuXG5mdW5jdGlvbiBjYWxsX3Byb3BlcnR5KGl0ZW0sIHByb3BlcnR5KSB7XG4gIGlmIChwcm9wZXJ0eSBpbiBpdGVtKSB7XG4gICAgaXRlbVtwcm9wZXJ0eV07XG4gICAgaWYgKGl0ZW1bcHJvcGVydHldIGluc3RhbmNlb2YgRnVuY3Rpb24pIHtcbiAgICAgIHJldHVybiBpdGVtW3Byb3BlcnR5XSgpO1xuICAgIH0gZWxzZSB7XG4gICAgICByZXR1cm4gaXRlbVtwcm9wZXJ0eV07XG4gICAgfVxuICB9IGVsc2UgaWYgKFN5bWJvbC5mb3IocHJvcGVydHkpIGluIGl0ZW0pIHtcbiAgICBsZXQgcHJvcCA9IFN5bWJvbC5mb3IocHJvcGVydHkpO1xuICAgIGlmIChpdGVtW3Byb3BdIGluc3RhbmNlb2YgRnVuY3Rpb24pIHtcbiAgICAgIHJldHVybiBpdGVtW3Byb3BdKCk7XG4gICAgfSBlbHNlIHtcbiAgICAgIHJldHVybiBpdGVtW3Byb3BdO1xuICAgIH1cbiAgfVxuXG4gIHRocm93IG5ldyBFcnJvcihgUHJvcGVydHkgJHsgcHJvcGVydHkgfSBub3QgZm91bmQgaW4gJHsgaXRlbSB9YCk7XG59XG5cbnZhciBqcyA9IHtcbiAgY2FsbF9wcm9wZXJ0eVxufTtcblxubGV0IENoYXJzJDEgPSBLZXJuZWwuZGVmcHJvdG9jb2woe1xuICB0b19zdHJpbmc6IGZ1bmN0aW9uICh0aGluZykge31cbn0pO1xuXG5LZXJuZWwuZGVmaW1wbChDaGFycyQxLCBCaXRTdHJpbmcsIHtcbiAgdG9fc3RyaW5nOiBmdW5jdGlvbiAodGhpbmcpIHtcbiAgICBpZiAoS2VybmVsLmlzX2JpbmFyeSh0aGluZykpIHtcbiAgICAgIHJldHVybiB0aGluZztcbiAgICB9XG5cbiAgICByZXR1cm4gdGhpbmcudG9TdHJpbmcoKTtcbiAgfVxufSk7XG5cbktlcm5lbC5kZWZpbXBsKENoYXJzJDEsIFN5bWJvbCwge1xuICB0b19zdHJpbmc6IGZ1bmN0aW9uICh0aGluZykge1xuICAgIGlmIChuaWwpIHtcbiAgICAgIHJldHVybiBcIlwiO1xuICAgIH1cblxuICAgIHJldHVybiBBdG9tLnRvX3N0cmluZyh0aGluZyk7XG4gIH1cbn0pO1xuXG5LZXJuZWwuZGVmaW1wbChDaGFycyQxLCBJbnRlZ2VyVHlwZSwge1xuICB0b19zdHJpbmc6IGZ1bmN0aW9uICh0aGluZykge1xuICAgIHJldHVybiBJbnRlZ2VyLnRvX3N0cmluZyh0aGluZyk7XG4gIH1cbn0pO1xuXG5LZXJuZWwuZGVmaW1wbChDaGFycyQxLCBGbG9hdFR5cGUsIHtcbiAgdG9fc3RyaW5nOiBmdW5jdGlvbiAodGhpbmcpIHtcbiAgICByZXR1cm4gdGhpbmcudG9TdHJpbmc7XG4gIH1cbn0pO1xuXG5LZXJuZWwuZGVmaW1wbChDaGFycyQxLCBBcnJheSwge1xuICB0b19zdHJpbmc6IGZ1bmN0aW9uICh0aGluZykge1xuICAgIHJldHVybiB0aGluZy50b1N0cmluZygpO1xuICB9XG59KTtcblxuS2VybmVsLmRlZmltcGwoQ2hhcnMkMSwgQ29yZS5UdXBsZSwge1xuICB0b19zdHJpbmc6IGZ1bmN0aW9uICh0aGluZykge1xuICAgIHJldHVybiBUdXBsZS50b19zdHJpbmcodGhpbmcpO1xuICB9XG59KTtcblxuS2VybmVsLmRlZmltcGwoQ2hhcnMkMSwgbnVsbCwge1xuICB0b19zdHJpbmc6IGZ1bmN0aW9uICh0aGluZykge1xuICAgIHJldHVybiB0aGluZy50b1N0cmluZygpO1xuICB9XG59KTtcblxuZnVuY3Rpb24gdG9fYXRvbShzdHJpbmcpIHtcbiAgcmV0dXJuIFN5bWJvbC5mb3Ioc3RyaW5nKTtcbn1cblxuZnVuY3Rpb24gdG9fZXhpc3RpbmdfYXRvbShzdHJpbmcpIHtcbiAgcmV0dXJuIFN5bWJvbC5mb3Ioc3RyaW5nKTtcbn1cblxuZnVuY3Rpb24gdG9fY2hhcl9saXN0KHN0cmluZykge1xuICByZXR1cm4gc3RyaW5nLnNwbGl0KCcnKTtcbn1cblxuZnVuY3Rpb24gdG9fZmxvYXQoc3RyaW5nKSB7XG4gIHJldHVybiBwYXJzZUZsb2F0KHN0cmluZyk7XG59XG5cbmZ1bmN0aW9uIHRvX2ludGVnZXIoc3RyaW5nLCBiYXNlID0gMTApIHtcbiAgcmV0dXJuIHBhcnNlSW50KHN0cmluZywgYmFzZSk7XG59XG5cbmZ1bmN0aW9uIHVwY2FzZShiaW5hcnkpIHtcbiAgcmV0dXJuIGJpbmFyeS50b1VwcGVyQ2FzZSgpO1xufVxuXG5mdW5jdGlvbiBkb3duY2FzZShiaW5hcnkpIHtcbiAgcmV0dXJuIGJpbmFyeS50b0xvd2VyQ2FzZSgpO1xufVxuXG5mdW5jdGlvbiBhdChzdHJpbmcsIHBvc2l0aW9uKSB7XG4gIGlmIChwb3NpdGlvbiA+IHN0cmluZy5sZW5ndGggLSAxKSB7XG4gICAgcmV0dXJuIG51bGw7XG4gIH1cblxuICByZXR1cm4gc3RyaW5nW3Bvc2l0aW9uXTtcbn1cblxuZnVuY3Rpb24gY2FwaXRhbGl6ZShzdHJpbmcpIHtcbiAgbGV0IHJldHVyblN0cmluZyA9ICcnO1xuXG4gIGZvciAobGV0IGkgPSAwOyBpIDwgc3RyaW5nLmxlbmd0aDsgaSsrKSB7XG4gICAgaWYgKGkgPT09IDApIHtcbiAgICAgIHJldHVyblN0cmluZyA9IHJldHVyblN0cmluZyArIHN0cmluZ1tpXS50b1VwcGVyQ2FzZSgpO1xuICAgIH0gZWxzZSB7XG4gICAgICByZXR1cm5TdHJpbmcgPSByZXR1cm5TdHJpbmcgKyBzdHJpbmdbaV0udG9Mb3dlckNhc2UoKTtcbiAgICB9XG4gIH1cblxuICByZXR1cm4gcmV0dXJuU3RyaW5nO1xufVxuXG5mdW5jdGlvbiBjb2RlcG9pbnRzKHN0cmluZykge1xuICByZXR1cm4gdG9fY2hhcl9saXN0KHN0cmluZykubWFwKGZ1bmN0aW9uIChjKSB7XG4gICAgcmV0dXJuIGMuY29kZVBvaW50QXQoMCk7XG4gIH0pO1xufVxuXG5mdW5jdGlvbiBjb250YWluc19fcW1fXyhzdHJpbmcsIGNvbnRhaW5zKSB7XG4gIGlmIChBcnJheS5pc0FycmF5KGNvbnRhaW5zKSkge1xuICAgIHJldHVybiBjb250YWlucy5zb21lKGZ1bmN0aW9uIChzKSB7XG4gICAgICByZXR1cm4gc3RyaW5nLmluZGV4T2YocykgPiAtMTtcbiAgICB9KTtcbiAgfVxuXG4gIHJldHVybiBzdHJpbmcuaW5kZXhPZihjb250YWlucykgPiAtMTtcbn1cblxuZnVuY3Rpb24gZHVwbGljYXRlJDEoc3ViamVjdCwgbikge1xuICByZXR1cm4gc3ViamVjdC5yZXBlYXQobik7XG59XG5cbmZ1bmN0aW9uIGVuZHNfd2l0aF9fcW1fXyhzdHJpbmcsIHN1ZmZpeGVzKSB7XG4gIGlmIChBcnJheS5pc0FycmF5KHN1ZmZpeGVzKSkge1xuICAgIHJldHVybiBzdWZmaXhlcy5zb21lKGZ1bmN0aW9uIChzKSB7XG4gICAgICByZXR1cm4gc3RyaW5nLmVuZHNXaXRoKHMpO1xuICAgIH0pO1xuICB9XG5cbiAgcmV0dXJuIHN0cmluZy5lbmRzV2l0aChzdWZmaXhlcyk7XG59XG5cbmZ1bmN0aW9uIGZpcnN0KHN0cmluZykge1xuICBpZiAoIXN0cmluZykge1xuICAgIHJldHVybiBudWxsO1xuICB9XG5cbiAgcmV0dXJuIHN0cmluZ1swXTtcbn1cblxuZnVuY3Rpb24gZ3JhcGhlbWVzKHN0cmluZykge1xuICByZXR1cm4gc3RyaW5nLnNwbGl0KCcnKTtcbn1cblxuZnVuY3Rpb24gbGFzdChzdHJpbmcpIHtcbiAgaWYgKCFzdHJpbmcpIHtcbiAgICByZXR1cm4gbnVsbDtcbiAgfVxuXG4gIHJldHVybiBzdHJpbmdbc3RyaW5nLmxlbmd0aCAtIDFdO1xufVxuXG5mdW5jdGlvbiBsZW5ndGgkMShzdHJpbmcpIHtcbiAgcmV0dXJuIHN0cmluZy5sZW5ndGg7XG59XG5cbmZ1bmN0aW9uIG1hdGNoX19xbV9fKHN0cmluZywgcmVnZXgpIHtcbiAgcmV0dXJuIHN0cmluZy5tYXRjaChyZWdleCkgIT0gbnVsbDtcbn1cblxuZnVuY3Rpb24gbmV4dF9jb2RlcG9pbnQoc3RyaW5nKSB7XG4gIGlmICghc3RyaW5nIHx8IHN0cmluZyA9PT0gJycpIHtcbiAgICByZXR1cm4gbnVsbDtcbiAgfVxuXG4gIHJldHVybiBLZXJuZWwuU3BlY2lhbEZvcm1zLnR1cGxlKHN0cmluZ1swXS5jb2RlUG9pbnRBdCgwKSwgc3RyaW5nLnN1YnN0cigxKSk7XG59XG5cbmZ1bmN0aW9uIG5leHRfZ3JhcGhlbWUoc3RyaW5nKSB7XG4gIGlmICghc3RyaW5nIHx8IHN0cmluZyA9PT0gJycpIHtcbiAgICByZXR1cm4gbnVsbDtcbiAgfVxuXG4gIHJldHVybiBLZXJuZWwuU3BlY2lhbEZvcm1zLnR1cGxlKHN0cmluZ1swXSwgc3RyaW5nLnN1YnN0cigxKSk7XG59XG5cbmZ1bmN0aW9uIHJldmVyc2Uoc3RyaW5nKSB7XG4gIGxldCByZXR1cm5WYWx1ZSA9ICcnO1xuXG4gIGZvciAodmFyIGkgPSBzdHJpbmcubGVuZ3RoIC0gMTsgaSA+PSAwOyBpLS0pIHtcbiAgICByZXR1cm5WYWx1ZSA9IHJldHVyblZhbHVlICsgc3RyaW5nW2ldO1xuICB9O1xuXG4gIHJldHVybiByZXR1cm5WYWx1ZTtcbn1cblxuZnVuY3Rpb24gc3BsaXQoc3RyaW5nKSB7XG4gIHJldHVybiBzdHJpbmcuc3BsaXQoKTtcbn1cblxuZnVuY3Rpb24gc3RhcnRzX3dpdGhfX3FtX18oc3RyaW5nLCBwcmVmaXhlcykge1xuICBpZiAoQXJyYXkuaXNBcnJheShwcmVmaXhlcykpIHtcbiAgICByZXR1cm4gcHJlZml4ZXMuc29tZShmdW5jdGlvbiAocykge1xuICAgICAgcmV0dXJuIHN0cmluZy5zdGFydHNXaXRoKHMpO1xuICAgIH0pO1xuICB9XG5cbiAgcmV0dXJuIHN0cmluZy5zdGFydHNXaXRoKHByZWZpeGVzKTtcbn1cblxuZnVuY3Rpb24gdmFsaWRfY2hhcmFjdGVyX19xbV9fKGNvZGVwb2ludCkge1xuICB0cnkge1xuICAgIHJldHVybiBTdHJpbmcuZnJvbUNvZGVQb2ludChjb2RlcG9pbnQpICE9IG51bGw7XG4gIH0gY2F0Y2ggKGUpIHtcbiAgICByZXR1cm4gZmFsc2U7XG4gIH1cbn1cblxudmFyIFN0cmluZyQxID0ge1xuICBhdCxcbiAgY2FwaXRhbGl6ZSxcbiAgY29kZXBvaW50cyxcbiAgY29udGFpbnNfX3FtX18sXG4gIGRvd25jYXNlLFxuICBkdXBsaWNhdGU6IGR1cGxpY2F0ZSQxLFxuICBlbmRzX3dpdGhfX3FtX18sXG4gIGZpcnN0LFxuICBncmFwaGVtZXMsXG4gIGxhc3QsXG4gIGxlbmd0aDogbGVuZ3RoJDEsXG4gIG1hdGNoX19xbV9fLFxuICBuZXh0X2NvZGVwb2ludCxcbiAgbmV4dF9ncmFwaGVtZSxcbiAgcmV2ZXJzZSxcbiAgc3BsaXQsXG4gIHN0YXJ0c193aXRoX19xbV9fLFxuICB0b19hdG9tLFxuICB0b19jaGFyX2xpc3QsXG4gIHRvX2V4aXN0aW5nX2F0b20sXG4gIHRvX2Zsb2F0LFxuICB0b19pbnRlZ2VyLFxuICB1cGNhc2UsXG4gIHZhbGlkX2NoYXJhY3Rlcl9fcW1fXyxcbiAgQ2hhcnM6IENoYXJzJDFcbn07XG5cbmxldCBDaGFycyA9IEtlcm5lbC5kZWZwcm90b2NvbCh7XG4gIHRvX2NoYXJfbGlzdDogZnVuY3Rpb24gKHRoaW5nKSB7fVxufSk7XG5cbktlcm5lbC5kZWZpbXBsKENoYXJzLCBLZXJuZWwuaXNfYml0c3RyaW5nLCB7XG4gIHRvX2NoYXJfbGlzdDogZnVuY3Rpb24gKHRoaW5nKSB7XG4gICAgaWYgKEtlcm5lbC5pc19iaW5hcnkodGhpbmcpKSB7XG4gICAgICByZXR1cm4gU3RyaW5nJDEudG9fY2hhcl9saXN0KHRoaW5nKTtcbiAgICB9XG5cbiAgICByZXR1cm4gdGhpbmcudG9TdHJpbmcoKTtcbiAgfVxufSk7XG5cbktlcm5lbC5kZWZpbXBsKENoYXJzLCBLZXJuZWwuaXNfYXRvbSwge1xuICB0b19jaGFyX2xpc3Q6IGZ1bmN0aW9uICh0aGluZykge1xuICAgIHJldHVybiBBdG9tLnRvX2NoYXJfbGlzdCh0aGluZyk7XG4gIH1cbn0pO1xuXG5LZXJuZWwuZGVmaW1wbChDaGFycywgS2VybmVsLmlzX2ludGVnZXIsIHtcbiAgdG9fY2hhcl9saXN0OiBmdW5jdGlvbiAodGhpbmcpIHtcbiAgICByZXR1cm4gSW50ZWdlci50b19jaGFyX2xpc3QodGhpbmcpO1xuICB9XG59KTtcblxuS2VybmVsLmRlZmltcGwoQ2hhcnMsIEtlcm5lbC5pc19saXN0LCB7XG4gIHRvX2NoYXJfbGlzdDogZnVuY3Rpb24gKHRoaW5nKSB7XG4gICAgcmV0dXJuIHRoaW5nO1xuICB9XG59KTtcblxubGV0IExpc3QgPSB7fTtcblxuTGlzdC5DaGFycyA9IENoYXJzO1xuXG5MaXN0LmRlbGV0ZSA9IGZ1bmN0aW9uIChsaXN0LCBpdGVtKSB7XG4gIGxldCBuZXdfdmFsdWUgPSBbXTtcbiAgbGV0IHZhbHVlX2ZvdW5kID0gZmFsc2U7XG5cbiAgZm9yIChsZXQgeCBvZiBsaXN0KSB7XG4gICAgaWYgKHggPT09IGl0ZW0gJiYgdmFsdWVfZm91bmQgIT09IGZhbHNlKSB7XG4gICAgICBuZXdfdmFsdWUucHVzaCh4KTtcbiAgICAgIHZhbHVlX2ZvdW5kID0gdHJ1ZTtcbiAgICB9IGVsc2UgaWYgKHggIT09IGl0ZW0pIHtcbiAgICAgIG5ld192YWx1ZS5wdXNoKHgpO1xuICAgIH1cbiAgfVxuXG4gIHJldHVybiBLZXJuZWwuU3BlY2lhbEZvcm1zLmxpc3QoLi4ubmV3X3ZhbHVlKTtcbn07XG5cbkxpc3QuZGVsZXRlX2F0ID0gZnVuY3Rpb24gKGxpc3QsIGluZGV4KSB7XG4gIGxldCBuZXdfdmFsdWUgPSBbXTtcblxuICBmb3IgKGxldCBpID0gMDsgaSA8IGxpc3QubGVuZ3RoOyBpKyspIHtcbiAgICBpZiAoaSAhPT0gaW5kZXgpIHtcbiAgICAgIG5ld192YWx1ZS5wdXNoKGxpc3RbaV0pO1xuICAgIH1cbiAgfVxuXG4gIHJldHVybiBLZXJuZWwuU3BlY2lhbEZvcm1zLmxpc3QoLi4ubmV3X3ZhbHVlKTtcbn07XG5cbkxpc3QuZHVwbGljYXRlID0gZnVuY3Rpb24gKGVsZW0sIG4pIHtcbiAgbGV0IG5ld192YWx1ZSA9IFtdO1xuXG4gIGZvciAodmFyIGkgPSAwOyBpIDwgbjsgaSsrKSB7XG4gICAgbmV3X3ZhbHVlLnB1c2goZWxlbSk7XG4gIH1cblxuICByZXR1cm4gS2VybmVsLlNwZWNpYWxGb3Jtcy5saXN0KC4uLm5ld192YWx1ZSk7XG59O1xuXG5MaXN0LmZpcnN0ID0gZnVuY3Rpb24gKGxpc3QpIHtcbiAgcmV0dXJuIGxpc3RbMF07XG59O1xuXG5MaXN0LmZsYXR0ZW4gPSBmdW5jdGlvbiAobGlzdCwgdGFpbCA9IEtlcm5lbC5TcGVjaWFsRm9ybXMubGlzdCgpKSB7XG4gIGxldCBuZXdfdmFsdWUgPSBbXTtcblxuICBmb3IgKGxldCB4IG9mIGxpc3QpIHtcbiAgICBpZiAoS2VybmVsLmlzX2xpc3QoeCkpIHtcbiAgICAgIG5ld192YWx1ZSA9IG5ld192YWx1ZS5jb25jYXQoTGlzdC5mbGF0dGVuKHgpKTtcbiAgICB9IGVsc2Uge1xuICAgICAgbmV3X3ZhbHVlLnB1c2goeCk7XG4gICAgfVxuICB9XG5cbiAgbmV3X3ZhbHVlID0gbmV3X3ZhbHVlLmNvbmNhdCh0YWlsKTtcblxuICByZXR1cm4gS2VybmVsLlNwZWNpYWxGb3Jtcy5saXN0KC4uLm5ld192YWx1ZSk7XG59O1xuXG5MaXN0LmZvbGRsID0gZnVuY3Rpb24gKGxpc3QsIGFjYywgZnVuYykge1xuICByZXR1cm4gbGlzdC5yZWR1Y2UoZnVuYywgYWNjKTtcbn07XG5cbkxpc3QuZm9sZHIgPSBmdW5jdGlvbiAobGlzdCwgYWNjLCBmdW5jKSB7XG4gIGxldCBuZXdfYWNjID0gYWNjO1xuXG4gIGZvciAodmFyIGkgPSBsaXN0Lmxlbmd0aCAtIDE7IGkgPj0gMDsgaS0tKSB7XG4gICAgbmV3X2FjYyA9IGZ1bmMobGlzdFtpXSwgbmV3X2FjYyk7XG4gIH1cblxuICByZXR1cm4gbmV3X2FjYztcbn07XG5cbkxpc3QuaW5zZXJ0X2F0ID0gZnVuY3Rpb24gKGxpc3QsIGluZGV4LCB2YWx1ZSkge1xuICBsZXQgbmV3X3ZhbHVlID0gW107XG5cbiAgZm9yIChsZXQgaSA9IDA7IGkgPCBsaXN0Lmxlbmd0aDsgaSsrKSB7XG4gICAgaWYgKGkgPT09IGluZGV4KSB7XG4gICAgICBuZXdfdmFsdWUucHVzaCh2YWx1ZSk7XG4gICAgICBuZXdfdmFsdWUucHVzaChsaXN0W2ldKTtcbiAgICB9IGVsc2Uge1xuICAgICAgbmV3X3ZhbHVlLnB1c2gobGlzdFtpXSk7XG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIEtlcm5lbC5TcGVjaWFsRm9ybXMubGlzdCguLi5uZXdfdmFsdWUpO1xufTtcblxuTGlzdC5rZXlkZWxldGUgPSBmdW5jdGlvbiAobGlzdCwga2V5LCBwb3NpdGlvbikge1xuICBsZXQgbmV3X2xpc3QgPSBbXTtcblxuICBmb3IgKGxldCBpID0gMDsgaSA8IGxpc3QubGVuZ3RoOyBpKyspIHtcbiAgICBpZiAoIUtlcm5lbC5tYXRjaF9fcW1hcmtfXyhsaXN0W2ldW3Bvc2l0aW9uXSwga2V5KSkge1xuICAgICAgbmV3X2xpc3QucHVzaChsaXN0W2ldKTtcbiAgICB9XG4gIH1cblxuICByZXR1cm4gS2VybmVsLlNwZWNpYWxGb3Jtcy5saXN0KC4uLm5ld19saXN0KTtcbn07XG5cbkxpc3Qua2V5ZmluZCA9IGZ1bmN0aW9uIChsaXN0LCBrZXksIHBvc2l0aW9uLCBfZGVmYXVsdCA9IG51bGwpIHtcblxuICBmb3IgKGxldCBpID0gMDsgaSA8IGxpc3QubGVuZ3RoOyBpKyspIHtcbiAgICBpZiAoS2VybmVsLm1hdGNoX19xbWFya19fKGxpc3RbaV1bcG9zaXRpb25dLCBrZXkpKSB7XG4gICAgICByZXR1cm4gbGlzdFtpXTtcbiAgICB9XG4gIH1cblxuICByZXR1cm4gX2RlZmF1bHQ7XG59O1xuXG5MaXN0LmtleW1lbWJlcl9fcW1hcmtfXyA9IGZ1bmN0aW9uIChsaXN0LCBrZXksIHBvc2l0aW9uKSB7XG5cbiAgZm9yIChsZXQgaSA9IDA7IGkgPCBsaXN0Lmxlbmd0aDsgaSsrKSB7XG4gICAgaWYgKEtlcm5lbC5tYXRjaF9fcW1hcmtfXyhsaXN0W2ldW3Bvc2l0aW9uXSwga2V5KSkge1xuICAgICAgcmV0dXJuIHRydWU7XG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIGZhbHNlO1xufTtcblxuTGlzdC5rZXlyZXBsYWNlID0gZnVuY3Rpb24gKGxpc3QsIGtleSwgcG9zaXRpb24sIG5ld190dXBsZSkge1xuICBsZXQgbmV3X2xpc3QgPSBbXTtcblxuICBmb3IgKGxldCBpID0gMDsgaSA8IGxpc3QubGVuZ3RoOyBpKyspIHtcbiAgICBpZiAoIUtlcm5lbC5tYXRjaF9fcW1hcmtfXyhsaXN0W2ldW3Bvc2l0aW9uXSwga2V5KSkge1xuICAgICAgbmV3X2xpc3QucHVzaChsaXN0W2ldKTtcbiAgICB9IGVsc2Uge1xuICAgICAgbmV3X2xpc3QucHVzaChuZXdfdHVwbGUpO1xuICAgIH1cbiAgfVxuXG4gIHJldHVybiBLZXJuZWwuU3BlY2lhbEZvcm1zLmxpc3QoLi4ubmV3X2xpc3QpO1xufTtcblxuTGlzdC5rZXlzb3J0ID0gZnVuY3Rpb24gKGxpc3QsIHBvc2l0aW9uKSB7XG4gIGxldCBuZXdfbGlzdCA9IGxpc3Q7XG5cbiAgbmV3X2xpc3Quc29ydChmdW5jdGlvbiAoYSwgYikge1xuICAgIGlmIChwb3NpdGlvbiA9PT0gMCkge1xuICAgICAgaWYgKGFbcG9zaXRpb25dLnZhbHVlIDwgYltwb3NpdGlvbl0udmFsdWUpIHtcbiAgICAgICAgcmV0dXJuIC0xO1xuICAgICAgfVxuXG4gICAgICBpZiAoYVtwb3NpdGlvbl0udmFsdWUgPiBiW3Bvc2l0aW9uXS52YWx1ZSkge1xuICAgICAgICByZXR1cm4gMTtcbiAgICAgIH1cblxuICAgICAgcmV0dXJuIDA7XG4gICAgfSBlbHNlIHtcbiAgICAgIGlmIChhW3Bvc2l0aW9uXSA8IGJbcG9zaXRpb25dKSB7XG4gICAgICAgIHJldHVybiAtMTtcbiAgICAgIH1cblxuICAgICAgaWYgKGFbcG9zaXRpb25dID4gYltwb3NpdGlvbl0pIHtcbiAgICAgICAgcmV0dXJuIDE7XG4gICAgICB9XG5cbiAgICAgIHJldHVybiAwO1xuICAgIH1cbiAgfSk7XG5cbiAgcmV0dXJuIEtlcm5lbC5TcGVjaWFsRm9ybXMubGlzdCguLi5uZXdfbGlzdCk7XG59O1xuXG5MaXN0LmtleXN0b3JlID0gZnVuY3Rpb24gKGxpc3QsIGtleSwgcG9zaXRpb24sIG5ld190dXBsZSkge1xuICBsZXQgbmV3X2xpc3QgPSBbXTtcbiAgbGV0IHJlcGxhY2VkID0gZmFsc2U7XG5cbiAgZm9yIChsZXQgaSA9IDA7IGkgPCBsaXN0Lmxlbmd0aDsgaSsrKSB7XG4gICAgaWYgKCFLZXJuZWwubWF0Y2hfX3FtYXJrX18obGlzdFtpXVtwb3NpdGlvbl0sIGtleSkpIHtcbiAgICAgIG5ld19saXN0LnB1c2gobGlzdFtpXSk7XG4gICAgfSBlbHNlIHtcbiAgICAgIG5ld19saXN0LnB1c2gobmV3X3R1cGxlKTtcbiAgICAgIHJlcGxhY2VkID0gdHJ1ZTtcbiAgICB9XG4gIH1cblxuICBpZiAoIXJlcGxhY2VkKSB7XG4gICAgbmV3X2xpc3QucHVzaChuZXdfdHVwbGUpO1xuICB9XG5cbiAgcmV0dXJuIEtlcm5lbC5TcGVjaWFsRm9ybXMubGlzdCguLi5uZXdfbGlzdCk7XG59O1xuXG5MaXN0Lmxhc3QgPSBmdW5jdGlvbiAobGlzdCkge1xuICByZXR1cm4gbGlzdFtsaXN0Lmxlbmd0aCAtIDFdO1xufTtcblxuTGlzdC5yZXBsYWNlX2F0ID0gZnVuY3Rpb24gKGxpc3QsIGluZGV4LCB2YWx1ZSkge1xuICBsZXQgbmV3X3ZhbHVlID0gW107XG5cbiAgZm9yIChsZXQgaSA9IDA7IGkgPCBsaXN0Lmxlbmd0aDsgaSsrKSB7XG4gICAgaWYgKGkgPT09IGluZGV4KSB7XG4gICAgICBuZXdfdmFsdWUucHVzaCh2YWx1ZSk7XG4gICAgfSBlbHNlIHtcbiAgICAgIG5ld192YWx1ZS5wdXNoKGxpc3RbaV0pO1xuICAgIH1cbiAgfVxuXG4gIHJldHVybiBLZXJuZWwuU3BlY2lhbEZvcm1zLmxpc3QoLi4ubmV3X3ZhbHVlKTtcbn07XG5cbkxpc3QudXBkYXRlX2F0ID0gZnVuY3Rpb24gKGxpc3QsIGluZGV4LCBmdW4pIHtcbiAgbGV0IG5ld192YWx1ZSA9IFtdO1xuXG4gIGZvciAobGV0IGkgPSAwOyBpIDwgbGlzdC5jb3VudCgpOyBpKyspIHtcbiAgICBpZiAoaSA9PT0gaW5kZXgpIHtcbiAgICAgIG5ld192YWx1ZS5wdXNoKGZ1bihsaXN0LmdldChpKSkpO1xuICAgIH0gZWxzZSB7XG4gICAgICBuZXdfdmFsdWUucHVzaChsaXN0LmdldChpKSk7XG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIG5ld192YWx1ZTtcbn07XG5cbkxpc3Qud3JhcCA9IGZ1bmN0aW9uIChsaXN0KSB7XG4gIGlmIChLZXJuZWwuaXNfbGlzdChsaXN0KSkge1xuICAgIHJldHVybiBsaXN0O1xuICB9IGVsc2UgaWYgKGxpc3QgPT0gbnVsbCkge1xuICAgIHJldHVybiBLZXJuZWwuU3BlY2lhbEZvcm1zLmxpc3QoKTtcbiAgfSBlbHNlIHtcbiAgICByZXR1cm4gS2VybmVsLlNwZWNpYWxGb3Jtcy5saXN0KGxpc3QpO1xuICB9XG59O1xuXG5MaXN0LnppcCA9IGZ1bmN0aW9uIChsaXN0X29mX2xpc3RzKSB7XG4gIGlmIChsaXN0X29mX2xpc3RzLmxlbmd0aCA9PT0gMCkge1xuICAgIHJldHVybiBLZXJuZWwuU3BlY2lhbEZvcm1zLmxpc3QoKTtcbiAgfVxuXG4gIGxldCBuZXdfdmFsdWUgPSBbXTtcbiAgbGV0IHNtYWxsZXN0X2xlbmd0aCA9IGxpc3Rfb2ZfbGlzdHNbMF07XG5cbiAgZm9yIChsZXQgeCBvZiBsaXN0X29mX2xpc3RzKSB7XG4gICAgaWYgKHgubGVuZ3RoIDwgc21hbGxlc3RfbGVuZ3RoKSB7XG4gICAgICBzbWFsbGVzdF9sZW5ndGggPSB4Lmxlbmd0aDtcbiAgICB9XG4gIH1cblxuICBmb3IgKGxldCBpID0gMDsgaSA8IHNtYWxsZXN0X2xlbmd0aDsgaSsrKSB7XG4gICAgbGV0IGN1cnJlbnRfdmFsdWUgPSBbXTtcbiAgICBmb3IgKGxldCBqID0gMDsgaiA8IGxpc3Rfb2ZfbGlzdHMubGVuZ3RoOyBqKyspIHtcbiAgICAgIGN1cnJlbnRfdmFsdWUucHVzaChsaXN0X29mX2xpc3RzW2pdW2ldKTtcbiAgICB9XG5cbiAgICBuZXdfdmFsdWUucHVzaChLZXJuZWwuU3BlY2lhbEZvcm1zLnR1cGxlKC4uLmN1cnJlbnRfdmFsdWUpKTtcbiAgfVxuXG4gIHJldHVybiBLZXJuZWwuU3BlY2lhbEZvcm1zLmxpc3QoLi4ubmV3X3ZhbHVlKTtcbn07XG5cbkxpc3QudG9fdHVwbGUgPSBmdW5jdGlvbiAobGlzdCkge1xuICByZXR1cm4gS2VybmVsLlNwZWNpYWxGb3Jtcy50dXBsZS5hcHBseShudWxsLCBsaXN0KTtcbn07XG5cbkxpc3QuYXBwZW5kID0gZnVuY3Rpb24gKGxpc3QsIHZhbHVlKSB7XG4gIHJldHVybiBLZXJuZWwuU3BlY2lhbEZvcm1zLmxpc3QoLi4ubGlzdC5jb25jYXQoW3ZhbHVlXSkpO1xufTtcblxuTGlzdC5wcmVwZW5kID0gZnVuY3Rpb24gKGxpc3QsIHZhbHVlKSB7XG4gIHJldHVybiBLZXJuZWwuU3BlY2lhbEZvcm1zLmxpc3QoLi4uW3ZhbHVlXS5jb25jYXQobGlzdCkpO1xufTtcblxuTGlzdC5jb25jYXQgPSBmdW5jdGlvbiAobGVmdCwgcmlnaHQpIHtcbiAgcmV0dXJuIGxlZnQuY29uY2F0KHJpZ2h0KTtcbn07XG5cbmxldCBSYW5nZSA9IGZ1bmN0aW9uIChfZmlyc3QsIF9sYXN0KSB7XG4gIGlmICghKHRoaXMgaW5zdGFuY2VvZiBSYW5nZSkpIHtcbiAgICByZXR1cm4gbmV3IFJhbmdlKF9maXJzdCwgX2xhc3QpO1xuICB9XG5cbiAgdGhpcy5maXJzdCA9IGZ1bmN0aW9uICgpIHtcbiAgICByZXR1cm4gX2ZpcnN0O1xuICB9O1xuXG4gIHRoaXMubGFzdCA9IGZ1bmN0aW9uICgpIHtcbiAgICByZXR1cm4gX2xhc3Q7XG4gIH07XG5cbiAgbGV0IF9yYW5nZSA9IFtdO1xuXG4gIGZvciAobGV0IGkgPSBfZmlyc3Q7IGkgPD0gX2xhc3Q7IGkrKykge1xuICAgIF9yYW5nZS5wdXNoKGkpO1xuICB9XG5cbiAgX3JhbmdlID0gT2JqZWN0LmZyZWV6ZShfcmFuZ2UpO1xuXG4gIHRoaXMudmFsdWUgPSBmdW5jdGlvbiAoKSB7XG4gICAgcmV0dXJuIF9yYW5nZTtcbiAgfTtcblxuICB0aGlzLmxlbmd0aCA9IGZ1bmN0aW9uICgpIHtcbiAgICByZXR1cm4gX3JhbmdlLmxlbmd0aDtcbiAgfTtcblxuICByZXR1cm4gdGhpcztcbn07XG5cblJhbmdlLnByb3RvdHlwZVtTeW1ib2wuaXRlcmF0b3JdID0gZnVuY3Rpb24gKCkge1xuICByZXR1cm4gdGhpcy52YWx1ZSgpW1N5bWJvbC5pdGVyYXRvcl0oKTtcbn07XG5cblJhbmdlLm5ldyA9IGZ1bmN0aW9uIChmaXJzdCwgbGFzdCkge1xuICByZXR1cm4gUmFuZ2UoZmlyc3QsIGxhc3QpO1xufTtcblxuUmFuZ2UucmFuZ2VfX3FtYXJrX18gPSBmdW5jdGlvbiAocmFuZ2UpIHtcbiAgcmV0dXJuIHJhbmdlIGluc3RhbmNlb2YgUmFuZ2U7XG59O1xuXG5sZXQgS2V5d29yZCA9IHt9O1xuXG5LZXl3b3JkLmhhc19rZXlfX3FtX18gPSBmdW5jdGlvbiAoa2V5d29yZHMsIGtleSkge1xuICBmb3IgKGxldCBrZXl3b3JkIG9mIGtleXdvcmRzKSB7XG4gICAgaWYgKEtlcm5lbC5lbGVtKGtleXdvcmQsIDApID09IGtleSkge1xuICAgICAgcmV0dXJuIHRydWU7XG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIGZhbHNlO1xufTtcblxuS2V5d29yZC5nZXQgPSBmdW5jdGlvbiAoa2V5d29yZHMsIGtleSwgdGhlX2RlZmF1bHQgPSBudWxsKSB7XG4gIGZvciAobGV0IGtleXdvcmQgb2Yga2V5d29yZHMpIHtcbiAgICBpZiAoS2VybmVsLmVsZW0oa2V5d29yZCwgMCkgPT0ga2V5KSB7XG4gICAgICByZXR1cm4gS2VybmVsLmVsZW0oa2V5d29yZCwgMSk7XG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIHRoZV9kZWZhdWx0O1xufTtcblxubGV0IEFnZW50ID0ge307XG5cbkFnZW50LnN0YXJ0ID0gZnVuY3Rpb24gKGZ1biwgb3B0aW9ucyA9IFtdKSB7XG4gIGxldCBwaWQgPSBzZWxmLnByb2Nlc3Nlcy5zcGF3bigpO1xuXG4gIGlmIChLZXl3b3JkLmhhc19rZXlfX3FtX18ob3B0aW9ucywgS2VybmVsLlNwZWNpYWxGb3Jtcy5hdG9tKCduYW1lJykpKSB7XG4gICAgcGlkID0gc2VsZi5wcm9jZXNzZXMucmVnaXN0ZXIoS2V5d29yZC5nZXQob3B0aW9ucywgS2VybmVsLlNwZWNpYWxGb3Jtcy5hdG9tKCduYW1lJykpLCBwaWQpO1xuICB9XG5cbiAgc2VsZi5wcm9jZXNzZXMucHV0KHBpZCwgJ3N0YXRlJywgZnVuKCkpO1xuICByZXR1cm4gS2VybmVsLlNwZWNpYWxGb3Jtcy50dXBsZShLZXJuZWwuU3BlY2lhbEZvcm1zLmF0b20oJ29rJyksIHBpZCk7XG59O1xuXG5BZ2VudC5zdG9wID0gZnVuY3Rpb24gKGFnZW50LCB0aW1lb3V0ID0gNTAwMCkge1xuICBzZWxmLnByb2Nlc3Nlcy5leGl0KGFnZW50KTtcbiAgcmV0dXJuIEtlcm5lbC5TcGVjaWFsRm9ybXMuYXRvbSgnb2snKTtcbn07XG5cbkFnZW50LnVwZGF0ZSA9IGZ1bmN0aW9uIChhZ2VudCwgZnVuLCB0aW1lb3V0ID0gNTAwMCkge1xuXG4gIGNvbnN0IGN1cnJlbnRfc3RhdGUgPSBzZWxmLnByb2Nlc3Nlcy5nZXQoYWdlbnQsICdzdGF0ZScpO1xuICBzZWxmLnByb2Nlc3Nlcy5wdXQoYWdlbnQsICdzdGF0ZScsIGZ1bihjdXJyZW50X3N0YXRlKSk7XG5cbiAgcmV0dXJuIEtlcm5lbC5TcGVjaWFsRm9ybXMuYXRvbSgnb2snKTtcbn07XG5cbkFnZW50LmdldCA9IGZ1bmN0aW9uIChhZ2VudCwgZnVuLCB0aW1lb3V0ID0gNTAwMCkge1xuICByZXR1cm4gZnVuKHNlbGYucHJvY2Vzc2VzLmdldChhZ2VudCwgJ3N0YXRlJykpO1xufTtcblxuQWdlbnQuZ2V0X2FuZF91cGRhdGUgPSBmdW5jdGlvbiAoYWdlbnQsIGZ1biwgdGltZW91dCA9IDUwMDApIHtcblxuICBjb25zdCBnZXRfYW5kX3VwZGF0ZV90dXBsZSA9IGZ1bihzZWxmLnByb2Nlc3Nlcy5nZXQoYWdlbnQsICdzdGF0ZScpKTtcbiAgc2VsZi5wcm9jZXNzZXMucHV0KGFnZW50LCAnc3RhdGUnLCBLZXJuZWwuZWxlbShnZXRfYW5kX3VwZGF0ZV90dXBsZSwgMSkpO1xuXG4gIHJldHVybiBLZXJuZWwuZWxlbShnZXRfYW5kX3VwZGF0ZV90dXBsZSwgMCk7XG59O1xuXG4vL2h0dHBzOi8vZGV2ZWxvcGVyLm1vemlsbGEub3JnL2VuLVVTL2RvY3MvV2ViL0FQSS9XaW5kb3dCYXNlNjQvQmFzZTY0X2VuY29kaW5nX2FuZF9kZWNvZGluZyNTb2x1dGlvbl8yXyVFMiU4MCU5M19yZXdyaXRlX3RoZV9ET01zX2F0b2IoKV9hbmRfYnRvYSgpX3VzaW5nX0phdmFTY3JpcHQnc19UeXBlZEFycmF5c19hbmRfVVRGLThcbmZ1bmN0aW9uIGI2NEVuY29kZVVuaWNvZGUoc3RyKSB7XG4gIHJldHVybiBidG9hKGVuY29kZVVSSUNvbXBvbmVudChzdHIpLnJlcGxhY2UoLyUoWzAtOUEtRl17Mn0pL2csIGZ1bmN0aW9uIChtYXRjaCwgcDEpIHtcbiAgICByZXR1cm4gU3RyaW5nLmZyb21DaGFyQ29kZSgnMHgnICsgcDEpO1xuICB9KSk7XG59XG5cbmZ1bmN0aW9uIGVuY29kZTY0KGRhdGEpIHtcbiAgcmV0dXJuIGI2NEVuY29kZVVuaWNvZGUoZGF0YSk7XG59XG5cbmZ1bmN0aW9uIGRlY29kZTY0KGRhdGEpIHtcbiAgdHJ5IHtcbiAgICByZXR1cm4gS2VybmVsLlNwZWNpYWxGb3Jtcy50dXBsZShLZXJuZWwuU3BlY2lhbEZvcm1zLmF0b20oJ29rJyksIGF0b2IoZGF0YSkpO1xuICB9IGNhdGNoIChlKSB7XG4gICAgcmV0dXJuIEtlcm5lbC5TcGVjaWFsRm9ybXMuYXRvbSgnZXJyb3InKTtcbiAgfVxuICByZXR1cm4gYnRvYShkYXRhKTtcbn1cblxuZnVuY3Rpb24gZGVjb2RlNjRfX2VtX18oZGF0YSkge1xuICByZXR1cm4gYXRvYihkYXRhKTtcbn1cblxudmFyIGJhc2UgPSB7XG4gIGVuY29kZTY0LFxuICBkZWNvZGU2NCxcbiAgZGVjb2RlNjRfX2VtX19cbn07XG5cbmZ1bmN0aW9uIGJub3QoZXhwcikge1xuICByZXR1cm4gfmV4cHI7XG59XG5cbmZ1bmN0aW9uIGJhbmQobGVmdCwgcmlnaHQpIHtcbiAgcmV0dXJuIGxlZnQgJiByaWdodDtcbn1cblxuZnVuY3Rpb24gYm9yKGxlZnQsIHJpZ2h0KSB7XG4gIHJldHVybiBsZWZ0IHwgcmlnaHQ7XG59XG5cbmZ1bmN0aW9uIGJzbChsZWZ0LCByaWdodCkge1xuICByZXR1cm4gbGVmdCA8PCByaWdodDtcbn1cblxuZnVuY3Rpb24gYnNyKGxlZnQsIHJpZ2h0KSB7XG4gIHJldHVybiBsZWZ0ID4+IHJpZ2h0O1xufVxuXG5mdW5jdGlvbiBieG9yKGxlZnQsIHJpZ2h0KSB7XG4gIHJldHVybiBsZWZ0IF4gcmlnaHQ7XG59XG5cbnZhciBiaXR3aXNlID0ge1xuICBibm90LFxuICBiYW5kLFxuICBib3IsXG4gIGJzbCxcbiAgYnNyLFxuICBieG9yXG59O1xuXG5sZXQgRW51bWVyYWJsZSA9IEtlcm5lbC5kZWZwcm90b2NvbCh7XG4gIGNvdW50OiBmdW5jdGlvbiAoY29sbGVjdGlvbikge30sXG4gIG1lbWJlcl9xbWFya19fOiBmdW5jdGlvbiAoY29sbGVjdGlvbiwgdmFsdWUpIHt9LFxuICByZWR1Y2U6IGZ1bmN0aW9uIChjb2xsZWN0aW9uLCBhY2MsIGZ1bikge31cbn0pO1xuXG5sZXQgQ29sbGVjdGFibGUgPSBLZXJuZWwuZGVmcHJvdG9jb2woe1xuICBpbnRvOiBmdW5jdGlvbiAoY29sbGVjdGFibGUpIHt9XG59KTtcblxubGV0IEluc3BlY3QgPSBLZXJuZWwuZGVmcHJvdG9jb2woe1xuICBpbnNwZWN0OiBmdW5jdGlvbiAodGhpbmcsIG9wdHMpIHt9XG59KTtcblxuZnVuY3Rpb24gX19uZXdfXygpIHtcbiAgcmV0dXJuIFNwZWNpYWxGb3Jtcy5tYXAoe30pO1xufVxuXG5mdW5jdGlvbiBrZXlzKG1hcCkge1xuICByZXR1cm4gT2JqZWN0LmtleXMobWFwKTtcbn1cblxuZnVuY3Rpb24gc2l6ZShtYXApIHtcbiAgcmV0dXJuIGtleXMobWFwKS5sZW5ndGg7XG59XG5cbmZ1bmN0aW9uIHRvX2xpc3QkMShtYXApIHtcbiAgbGV0IG1hcF9rZXlzID0ga2V5cyhtYXApO1xuICBsZXQgbGlzdCA9IFtdO1xuXG4gIGZvciAobGV0IGtleSBvZiBtYXBfa2V5cykge1xuICAgIGxpc3QucHVzaChTcGVjaWFsRm9ybXMudHVwbGUoa2V5LCBtYXBba2V5XSkpO1xuICB9XG5cbiAgcmV0dXJuIFNwZWNpYWxGb3Jtcy5saXN0KC4uLmxpc3QpO1xufVxuXG5mdW5jdGlvbiB2YWx1ZXMobWFwKSB7XG4gIGxldCBtYXBfa2V5cyA9IGtleXMobWFwKTtcbiAgbGV0IGxpc3QgPSBbXTtcblxuICBmb3IgKGxldCBrZXkgb2YgbWFwX2tleXMpIHtcbiAgICBsaXN0LnB1c2gobWFwW2tleV0pO1xuICB9XG5cbiAgcmV0dXJuIFNwZWNpYWxGb3Jtcy5saXN0KC4uLmxpc3QpO1xufVxuXG5mdW5jdGlvbiBmcm9tX3N0cnVjdChzdHJ1Y3QpIHtcbiAgbGV0IG1hcCA9IE9iamVjdC5hc3NpZ24oe30sIHN0cnVjdCk7XG4gIGRlbGV0ZSBtYXBbU3ltYm9sLmZvcihcIl9fc3RydWN0X19cIildO1xuXG4gIHJldHVybiBTcGVjaWFsRm9ybXMubWFwKG1hcCk7XG59XG5cbmZ1bmN0aW9uIF9fZGVsZXRlX18obWFwLCBrZXkpIHtcbiAgbGV0IG5ld19tYXAgPSBPYmplY3QuYXNzaWduKHt9LCBtYXApO1xuXG4gIGRlbGV0ZSBuZXdfbWFwW2tleV07XG5cbiAgcmV0dXJuIFNwZWNpYWxGb3Jtcy5tYXAobmV3X21hcCk7XG59XG5cbmZ1bmN0aW9uIGVxdWFsX19xbWFya19fKG1hcDEsIG1hcDIpIHtcbiAgcmV0dXJuIG1hcDEgPT09IG1hcDI7XG59XG5cbmZ1bmN0aW9uIGZldGNoX19lbWFya19fKG1hcCwga2V5KSB7XG4gIGlmIChrZXkgaW4gbWFwKSB7XG4gICAgcmV0dXJuIG1hcFtrZXldO1xuICB9XG5cbiAgdGhyb3cgbmV3IEVycm9yKFwiS2V5IG5vdCBmb3VuZC5cIik7XG59XG5cbmZ1bmN0aW9uIGZldGNoKG1hcCwga2V5KSB7XG4gIGlmIChrZXkgaW4gbWFwKSB7XG4gICAgcmV0dXJuIFNwZWNpYWxGb3Jtcy50dXBsZShTcGVjaWFsRm9ybXMuYXRvbShcIm9rXCIpLCBtYXBba2V5XSk7XG4gIH1cblxuICByZXR1cm4gU3BlY2lhbEZvcm1zLmF0b20oXCJlcnJvclwiKTtcbn1cblxuZnVuY3Rpb24gaGFzX2tleV9fcW1hcmtfXyhtYXAsIGtleSkge1xuICByZXR1cm4ga2V5IGluIG1hcDtcbn1cblxuZnVuY3Rpb24gc3BsaXQkMShtYXAsIGtleXMpIHtcbiAgbGV0IHNwbGl0MSA9IHt9O1xuICBsZXQgc3BsaXQyID0ge307XG5cbiAgZm9yIChsZXQga2V5IG9mIE9iamVjdC5rZXlzKG1hcCkpIHtcbiAgICBpZiAoa2V5cy5pbmRleE9mKGtleSkgPiAtMSkge1xuICAgICAgc3BsaXQxW2tleV0gPSBtYXBba2V5XTtcbiAgICB9IGVsc2Uge1xuICAgICAgc3BsaXQyW2tleV0gPSBtYXBba2V5XTtcbiAgICB9XG4gIH1cblxuICByZXR1cm4gU3BlY2lhbEZvcm1zLnR1cGxlKFNwZWNpYWxGb3Jtcy5tYXAoc3BsaXQxKSwgU3BlY2lhbEZvcm1zLm1hcChzcGxpdDIpKTtcbn1cblxuZnVuY3Rpb24gdGFrZShtYXAsIGtleXMpIHtcbiAgbGV0IHNwbGl0MSA9IHt9O1xuXG4gIGZvciAobGV0IGtleSBvZiBPYmplY3Qua2V5cyhtYXApKSB7XG4gICAgaWYgKGtleXMuaW5kZXhPZihrZXkpID4gLTEpIHtcbiAgICAgIHNwbGl0MVtrZXldID0gbWFwW2tleV07XG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIFNwZWNpYWxGb3Jtcy5tYXAoc3BsaXQxKTtcbn1cblxuZnVuY3Rpb24gZHJvcChtYXAsIGtleXMpIHtcbiAgbGV0IHNwbGl0MSA9IHt9O1xuXG4gIGZvciAobGV0IGtleSBvZiBPYmplY3Qua2V5cyhtYXApKSB7XG4gICAgaWYgKGtleXMuaW5kZXhPZihrZXkpID09PSAtMSkge1xuICAgICAgc3BsaXQxW2tleV0gPSBtYXBba2V5XTtcbiAgICB9XG4gIH1cblxuICByZXR1cm4gU3BlY2lhbEZvcm1zLm1hcChzcGxpdDEpO1xufVxuXG5mdW5jdGlvbiBwdXRfbmV3KG1hcCwga2V5LCB2YWx1ZSkge1xuICBpZiAoa2V5IGluIG1hcCkge1xuICAgIHJldHVybiBtYXA7XG4gIH1cblxuICBsZXQgbmV3X21hcCA9IE9iamVjdC5hc3NpZ24oe30sIG1hcCk7XG4gIG5ld19tYXBba2V5XSA9IHZhbHVlO1xuXG4gIHJldHVybiBTcGVjaWFsRm9ybXMubWFwKG5ld19tYXApO1xufVxuXG5mdW5jdGlvbiBwdXRfbmV3X2xhenkobWFwLCBrZXksIGZ1bikge1xuICBpZiAoa2V5IGluIG1hcCkge1xuICAgIHJldHVybiBtYXA7XG4gIH1cblxuICBsZXQgbmV3X21hcCA9IE9iamVjdC5hc3NpZ24oe30sIG1hcCk7XG4gIG5ld19tYXBba2V5XSA9IGZ1bigpO1xuXG4gIHJldHVybiBTcGVjaWFsRm9ybXMubWFwKG5ld19tYXApO1xufVxuXG5mdW5jdGlvbiBnZXRfYW5kX3VwZGF0ZShtYXAsIGtleSwgZnVuKSB7XG4gIGlmIChrZXkgaW4gbWFwKSB7XG4gICAgcmV0dXJuIG1hcDtcbiAgfVxuXG4gIGxldCBuZXdfbWFwID0gT2JqZWN0LmFzc2lnbih7fSwgbWFwKTtcbiAgbmV3X21hcFtrZXldID0gZnVuKG1hcFtrZXldKTtcblxuICByZXR1cm4gU3BlY2lhbEZvcm1zLm1hcChuZXdfbWFwKTtcbn1cblxuZnVuY3Rpb24gcG9wX2xhenkobWFwLCBrZXksIGZ1bikge1xuICBpZiAoIWtleSBpbiBtYXApIHtcbiAgICByZXR1cm4gU3BlY2lhbEZvcm1zLnR1cGxlKGZ1bigpLCBtYXApO1xuICB9XG5cbiAgbGV0IG5ld19tYXAgPSBPYmplY3QuYXNzaWduKHt9LCBtYXApO1xuICBsZXQgdmFsdWUgPSBmdW4obmV3X21hcFtrZXldKTtcbiAgZGVsZXRlIG5ld19tYXBba2V5XTtcblxuICByZXR1cm4gU3BlY2lhbEZvcm1zLnR1cGxlKHZhbHVlLCBuZXdfbWFwKTtcbn1cblxuZnVuY3Rpb24gcG9wKG1hcCwga2V5LCBfZGVmYXVsdCA9IG51bGwpIHtcbiAgaWYgKCFrZXkgaW4gbWFwKSB7XG4gICAgcmV0dXJuIFNwZWNpYWxGb3Jtcy50dXBsZShfZGVmYXVsdCwgbWFwKTtcbiAgfVxuXG4gIGxldCBuZXdfbWFwID0gT2JqZWN0LmFzc2lnbih7fSwgbWFwKTtcbiAgbGV0IHZhbHVlID0gbmV3X21hcFtrZXldO1xuICBkZWxldGUgbmV3X21hcFtrZXldO1xuXG4gIHJldHVybiBTcGVjaWFsRm9ybXMudHVwbGUodmFsdWUsIG5ld19tYXApO1xufVxuXG5mdW5jdGlvbiBnZXRfbGF6eShtYXAsIGtleSwgZnVuKSB7XG4gIGlmICgha2V5IGluIG1hcCkge1xuICAgIHJldHVybiBmdW4oKTtcbiAgfVxuXG4gIHJldHVybiBmdW4obWFwW2tleV0pO1xufVxuXG5mdW5jdGlvbiBnZXQobWFwLCBrZXksIF9kZWZhdWx0ID0gbnVsbCkge1xuICBpZiAoIWtleSBpbiBtYXApIHtcbiAgICByZXR1cm4gX2RlZmF1bHQ7XG4gIH1cblxuICByZXR1cm4gbWFwW2tleV07XG59XG5cbmZ1bmN0aW9uIHB1dChtYXAsIGtleSwgdmFsKSB7XG4gIGxldCBuZXdfbWFwID0gT2JqZWN0KHt9LCBtYXApO1xuICBuZXdfbWFwW2tleV0gPSB2YWw7XG5cbiAgcmV0dXJuIFNwZWNpYWxGb3Jtcy5tYXAobmV3X21hcCk7XG59XG5cbmZ1bmN0aW9uIHVwZGF0ZV9fZW1hcmtfXyhtYXAsIGtleSwgZnVuKSB7XG4gIGlmICgha2V5IGluIG1hcCkge1xuICAgIHRocm93IG5ldyBFcnJvcihcIktleSBub3QgZm91bmRcIik7XG4gIH1cblxuICBsZXQgbmV3X21hcCA9IE9iamVjdCh7fSwgbWFwKTtcbiAgbmV3X21hcFtrZXldID0gZnVuKG1hcFtrZXldKTtcblxuICByZXR1cm4gU3BlY2lhbEZvcm1zLm1hcChuZXdfbWFwKTtcbn1cblxuZnVuY3Rpb24gdXBkYXRlKG1hcCwga2V5LCBpbml0aWFsLCBmdW4pIHtcbiAgbGV0IG5ld19tYXAgPSBPYmplY3Qoe30sIG1hcCk7XG5cbiAgaWYgKCFrZXkgaW4gbWFwKSB7XG4gICAgbmV3X21hcFtrZXldID0gaW5pdGlhbDtcbiAgfSBlbHNlIHtcbiAgICBuZXdfbWFwW2tleV0gPSBmdW4obWFwW2tleV0pO1xuICB9XG5cbiAgcmV0dXJuIFNwZWNpYWxGb3Jtcy5tYXAobmV3X21hcCk7XG59XG5cbnZhciBtYXAgPSB7XG4gIG5ldzogX19uZXdfXyxcbiAga2V5cyxcbiAgc2l6ZSxcbiAgdG9fbGlzdDogdG9fbGlzdCQxLFxuICB2YWx1ZXMsXG4gIGZyb21fc3RydWN0LFxuICBkZWxldGU6IF9fZGVsZXRlX18sXG4gIGRyb3AsXG4gIGVxdWFsX19xbWFya19fLFxuICBmZXRjaF9fZW1hcmtfXyxcbiAgZmV0Y2gsXG4gIGhhc19rZXlfX3FtYXJrX18sXG4gIHNwbGl0OiBzcGxpdCQxLFxuICB0YWtlLFxuICBwdXRfbmV3LFxuICBwdXRfbmV3X2xhenksXG4gIGdldF9hbmRfdXBkYXRlLFxuICBwb3BfbGF6eSxcbiAgcG9wLFxuICBnZXRfbGF6eSxcbiAgZ2V0LFxuICBwdXQsXG4gIHVwZGF0ZV9fZW1hcmtfXyxcbiAgdXBkYXRlXG59O1xuXG5mdW5jdGlvbiBfX25ld19fJDEoKSB7XG4gIHJldHVybiBTcGVjaWFsRm9ybXMubWFwKHsgW1N5bWJvbC5mb3IoJ19fc3RydWN0X18nKV06IFN5bWJvbC5mb3IoJ01hcFNldCcpLCBzZXQ6IFNwZWNpYWxGb3Jtcy5saXN0KCkgfSk7XG59XG5cbmZ1bmN0aW9uIHNpemUkMihtYXApIHtcbiAgcmV0dXJuIG1hcC5zZXQubGVuZ3RoO1xufVxuXG5mdW5jdGlvbiB0b19saXN0JDMobWFwKSB7XG4gIHJldHVybiBtYXAuc2V0O1xufVxuXG5mdW5jdGlvbiBfX2RlbGV0ZV9fJDIoc2V0LCB0ZXJtKSB7XG4gIGxldCBuZXdfbGlzdCA9IExpc3QuZGVsZXRlKHNldC5zZXQsIHRlcm0pO1xuXG4gIGxldCBuZXdfbWFwID0gT2JqZWN0LmFzc2lnbih7fSwgc2V0KTtcbiAgbmV3X21hcC5zZXQgPSBuZXdfbGlzdDtcbiAgcmV0dXJuIFNwZWNpYWxGb3Jtcy5tYXAobmV3X21hcCk7XG59XG5cbmZ1bmN0aW9uIHB1dCQyKHNldCwgdGVybSkge1xuICBpZiAoc2V0LnNldC5pbmRleE9mKHRlcm0pID09PSAtMSkge1xuICAgIGxldCBuZXdfbGlzdCA9IExpc3QuYXBwZW5kKHNldC5zZXQsIHRlcm0pO1xuXG4gICAgbGV0IG5ld19tYXAgPSBPYmplY3QuYXNzaWduKHt9LCBzZXQpO1xuICAgIG5ld19tYXAuc2V0ID0gbmV3X2xpc3Q7XG4gICAgcmV0dXJuIFNwZWNpYWxGb3Jtcy5tYXAobmV3X21hcCk7XG4gIH1cblxuICByZXR1cm4gc2V0O1xufVxuXG5mdW5jdGlvbiBkaWZmZXJlbmNlJDEoc2V0MSwgc2V0Mikge1xuICBsZXQgbmV3X21hcCA9IE9iamVjdC5hc3NpZ24oe30sIHNldDEpO1xuXG4gIGZvciAobGV0IHZhbCBvZiBzZXQxLnNldCkge1xuICAgIGlmIChtZW1iZXJfX3FtYXJrX18kMShzZXQyLCB2YWwpKSB7XG4gICAgICBuZXdfbWFwLnNldCA9IExpc3QuZGVsZXRlKG5ld19tYXAuc2V0LCB2YWwpO1xuICAgIH1cbiAgfVxuXG4gIHJldHVybiBTcGVjaWFsRm9ybXMubWFwKG5ld19tYXApO1xufVxuXG5mdW5jdGlvbiBpbnRlcnNlY3Rpb24kMShzZXQxLCBzZXQyKSB7XG4gIGxldCBuZXdfbWFwID0gT2JqZWN0LmFzc2lnbih7fSwgc2V0MSk7XG5cbiAgZm9yIChsZXQgdmFsIG9mIHNldDEuc2V0KSB7XG4gICAgaWYgKCFtZW1iZXJfX3FtYXJrX18kMShzZXQyLCB2YWwpKSB7XG4gICAgICBuZXdfbWFwLnNldCA9IExpc3QuZGVsZXRlKG5ld19tYXAuc2V0LCB2YWwpO1xuICAgIH1cbiAgfVxuXG4gIHJldHVybiBTcGVjaWFsRm9ybXMubWFwKG5ld19tYXApO1xufVxuXG5mdW5jdGlvbiB1bmlvbiQxKHNldDEsIHNldDIpIHtcbiAgbGV0IG5ld19tYXAgPSBzZXQxO1xuXG4gIGZvciAobGV0IHZhbCBvZiBzZXQyLnNldCkge1xuICAgIG5ld19tYXAgPSBwdXQkMihuZXdfbWFwLCB2YWwpO1xuICB9XG5cbiAgcmV0dXJuIFNwZWNpYWxGb3Jtcy5tYXAobmV3X21hcCk7XG59XG5cbmZ1bmN0aW9uIGRpc2pvaW5fX3FtYXJrX18kMShzZXQxLCBzZXQyKSB7XG4gIGZvciAobGV0IHZhbCBvZiBzZXQxLnNldCkge1xuICAgIGlmIChtZW1iZXJfX3FtYXJrX18kMShzZXQyLCB2YWwpKSB7XG4gICAgICByZXR1cm4gZmFsc2U7XG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIHRydWU7XG59XG5cbmZ1bmN0aW9uIG1lbWJlcl9fcW1hcmtfXyQxKHNldCwgdmFsdWUpIHtcbiAgcmV0dXJuIHNldC5zZXQuaW5kZXhPZih2YWx1ZSkgPj0gMDtcbn1cblxuZnVuY3Rpb24gZXF1YWxfX3FtYXJrX18kMihzZXQxLCBzZXQyKSB7XG4gIHJldHVybiBzZXQxLnNldCA9PT0gc2V0Mi5zZXQ7XG59XG5cbmZ1bmN0aW9uIHN1YnNldF9fcW1hcmtfXyQxKHNldDEsIHNldDIpIHtcbiAgZm9yIChsZXQgdmFsIG9mIHNldDEuc2V0KSB7XG4gICAgaWYgKCFtZW1iZXJfX3FtYXJrX18kMShzZXQyLCB2YWwpKSB7XG4gICAgICByZXR1cm4gZmFsc2U7XG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIHRydWU7XG59XG5cbnZhciBNYXBTZXQgPSB7XG4gIG5ldzogX19uZXdfXyQxLFxuICBzaXplOiBzaXplJDIsXG4gIHRvX2xpc3Q6IHRvX2xpc3QkMyxcbiAgZGlzam9pbl9fcW1hcmtfXzogZGlzam9pbl9fcW1hcmtfXyQxLFxuICBkZWxldGU6IF9fZGVsZXRlX18kMixcbiAgc3Vic2V0X19xbWFya19fOiBzdWJzZXRfX3FtYXJrX18kMSxcbiAgZXF1YWxfX3FtYXJrX186IGVxdWFsX19xbWFya19fJDIsXG4gIG1lbWJlcl9fcW1hcmtfXzogbWVtYmVyX19xbWFya19fJDEsXG4gIHB1dDogcHV0JDIsXG4gIHVuaW9uOiB1bmlvbiQxLFxuICBpbnRlcnNlY3Rpb246IGludGVyc2VjdGlvbiQxLFxuICBkaWZmZXJlbmNlOiBkaWZmZXJlbmNlJDFcbn07XG5cbmZ1bmN0aW9uIHNpemUkMShtYXApIHtcbiAgcmV0dXJuIE1hcFNldC5zaXplKG1hcCk7XG59XG5cbmZ1bmN0aW9uIHRvX2xpc3QkMihtYXApIHtcbiAgcmV0dXJuIE1hcFNldC50b19saXN0KG1hcCk7XG59XG5cbmZ1bmN0aW9uIF9fZGVsZXRlX18kMShzZXQsIHRlcm0pIHtcbiAgcmV0dXJuIE1hcFNldC5kZWxldGUoc2V0LCB0ZXJtKTtcbn1cblxuZnVuY3Rpb24gcHV0JDEoc2V0LCB0ZXJtKSB7XG4gIHJldHVybiBNYXBTZXQucHV0KHNldCwgdGVybSk7XG59XG5cbmZ1bmN0aW9uIGRpZmZlcmVuY2Uoc2V0MSwgc2V0Mikge1xuICByZXR1cm4gTWFwU2V0LmRpZmZlcmVuY2Uoc2V0MSwgc2V0Mik7XG59XG5cbmZ1bmN0aW9uIGludGVyc2VjdGlvbihzZXQxLCBzZXQyKSB7XG4gIHJldHVybiBNYXBTZXQuaW50ZXJzZWN0aW9uKHNldDEsIHNldDIpO1xufVxuXG5mdW5jdGlvbiB1bmlvbihzZXQxLCBzZXQyKSB7XG4gIHJldHVybiBNYXBTZXQudW5pb24oc2V0MSwgc2V0Mik7XG59XG5cbmZ1bmN0aW9uIGRpc2pvaW5fX3FtYXJrX18oc2V0MSwgc2V0Mikge1xuICByZXR1cm4gTWFwU2V0LmRpc2pvaW5fX3FtYXJrX18oc2V0MSwgc2V0Mik7XG59XG5cbmZ1bmN0aW9uIG1lbWJlcl9fcW1hcmtfXyhzZXQsIHZhbHVlKSB7XG4gIHJldHVybiBNYXBTZXQubWVtYmVyX19xbWFya19fKHNldDEsIHNldDIpO1xufVxuXG5mdW5jdGlvbiBlcXVhbF9fcW1hcmtfXyQxKHNldDEsIHNldDIpIHtcbiAgcmV0dXJuIE1hcFNldC5lcXVhbF9fcW1hcmtfXyhzZXQxLCBzZXQyKTtcbn1cblxuZnVuY3Rpb24gc3Vic2V0X19xbWFya19fKHNldDEsIHNldDIpIHtcbiAgcmV0dXJuIE1hcFNldC5zdWJzZXRfX3FtYXJrX18oc2V0MSwgc2V0Mik7XG59XG5cbnZhciBzZXQgPSB7XG4gIHNpemU6IHNpemUkMSxcbiAgdG9fbGlzdDogdG9fbGlzdCQyLFxuICBkaXNqb2luX19xbWFya19fLFxuICBkZWxldGU6IF9fZGVsZXRlX18kMSxcbiAgc3Vic2V0X19xbWFya19fLFxuICBlcXVhbF9fcW1hcmtfXzogZXF1YWxfX3FtYXJrX18kMSxcbiAgbWVtYmVyX19xbWFya19fLFxuICBwdXQ6IHB1dCQxLFxuICB1bmlvbixcbiAgaW50ZXJzZWN0aW9uLFxuICBkaWZmZXJlbmNlXG59O1xuXG5sZXQgVmlydHVhbERPTSA9IChmdW5jdGlvbiAoZSkge1xuICAgIHJldHVybiBlKCk7XG59KShmdW5jdGlvbiAoKSB7XG4gICAgdmFyIGRlZmluZSwgbW9kdWxlLCBleHBvcnRzO1xuICAgIHJldHVybiAoZnVuY3Rpb24gZSh0LCBuLCByKSB7XG4gICAgICAgIGZ1bmN0aW9uIHMobywgdSkge1xuICAgICAgICAgICAgaWYgKCFuW29dKSB7XG4gICAgICAgICAgICAgICAgaWYgKCF0W29dKSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciBhID0gdHlwZW9mIHJlcXVpcmUgPT0gXCJmdW5jdGlvblwiICYmIHJlcXVpcmU7XG4gICAgICAgICAgICAgICAgICAgIGlmICghdSAmJiBhKSByZXR1cm4gYShvLCAhMCk7XG4gICAgICAgICAgICAgICAgICAgIGlmIChpKSByZXR1cm4gaShvLCAhMCk7XG4gICAgICAgICAgICAgICAgICAgIHZhciBmID0gbmV3IEVycm9yKFwiQ2Fubm90IGZpbmQgbW9kdWxlICdcIiArIG8gKyBcIidcIik7XG4gICAgICAgICAgICAgICAgICAgIHRocm93IChmLmNvZGUgPSBcIk1PRFVMRV9OT1RfRk9VTkRcIiwgZik7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHZhciBsID0gbltvXSA9IHtcbiAgICAgICAgICAgICAgICAgICAgZXhwb3J0czoge31cbiAgICAgICAgICAgICAgICB9O1xuICAgICAgICAgICAgICAgIHRbb11bMF0uY2FsbChsLmV4cG9ydHMsIGZ1bmN0aW9uIChlKSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciBuID0gdFtvXVsxXVtlXTtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHMobiA/IG4gOiBlKTtcbiAgICAgICAgICAgICAgICB9LCBsLCBsLmV4cG9ydHMsIGUsIHQsIG4sIHIpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmV0dXJuIG5bb10uZXhwb3J0cztcbiAgICAgICAgfVxuICAgICAgICB2YXIgaSA9IHR5cGVvZiByZXF1aXJlID09IFwiZnVuY3Rpb25cIiAmJiByZXF1aXJlO1xuICAgICAgICBmb3IgKHZhciBvID0gMDsgbyA8IHIubGVuZ3RoOyBvKyspIHMocltvXSk7XG4gICAgICAgIHJldHVybiBzO1xuICAgIH0pKHtcbiAgICAgICAgMTogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHtcblxuICAgICAgICAgICAgdmFyIGNyZWF0ZUVsZW1lbnQgPSByZXF1aXJlKFwiLi92ZG9tL2NyZWF0ZS1lbGVtZW50LmpzXCIpO1xuXG4gICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IGNyZWF0ZUVsZW1lbnQ7XG4gICAgICAgIH0sIHsgXCIuL3Zkb20vY3JlYXRlLWVsZW1lbnQuanNcIjogMTUgfV0sIDI6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICB2YXIgZGlmZiA9IHJlcXVpcmUoXCIuL3Z0cmVlL2RpZmYuanNcIik7XG5cbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gZGlmZjtcbiAgICAgICAgfSwgeyBcIi4vdnRyZWUvZGlmZi5qc1wiOiAzNSB9XSwgMzogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHtcbiAgICAgICAgICAgIHZhciBoID0gcmVxdWlyZShcIi4vdmlydHVhbC1oeXBlcnNjcmlwdC9pbmRleC5qc1wiKTtcblxuICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBoO1xuICAgICAgICB9LCB7IFwiLi92aXJ0dWFsLWh5cGVyc2NyaXB0L2luZGV4LmpzXCI6IDIyIH1dLCA0OiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge1xuICAgICAgICAgICAgdmFyIGRpZmYgPSByZXF1aXJlKFwiLi9kaWZmLmpzXCIpO1xuICAgICAgICAgICAgdmFyIHBhdGNoID0gcmVxdWlyZShcIi4vcGF0Y2guanNcIik7XG4gICAgICAgICAgICB2YXIgaCA9IHJlcXVpcmUoXCIuL2guanNcIik7XG4gICAgICAgICAgICB2YXIgY3JlYXRlID0gcmVxdWlyZShcIi4vY3JlYXRlLWVsZW1lbnQuanNcIik7XG4gICAgICAgICAgICB2YXIgVk5vZGUgPSByZXF1aXJlKFwiLi92bm9kZS92bm9kZS5qc1wiKTtcbiAgICAgICAgICAgIHZhciBWVGV4dCA9IHJlcXVpcmUoXCIuL3Zub2RlL3Z0ZXh0LmpzXCIpO1xuXG4gICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IHtcbiAgICAgICAgICAgICAgICBkaWZmOiBkaWZmLFxuICAgICAgICAgICAgICAgIHBhdGNoOiBwYXRjaCxcbiAgICAgICAgICAgICAgICBoOiBoLFxuICAgICAgICAgICAgICAgIGNyZWF0ZTogY3JlYXRlLFxuICAgICAgICAgICAgICAgIFZOb2RlOiBWTm9kZSxcbiAgICAgICAgICAgICAgICBWVGV4dDogVlRleHRcbiAgICAgICAgICAgIH07XG4gICAgICAgIH0sIHsgXCIuL2NyZWF0ZS1lbGVtZW50LmpzXCI6IDEsIFwiLi9kaWZmLmpzXCI6IDIsIFwiLi9oLmpzXCI6IDMsIFwiLi9wYXRjaC5qc1wiOiAxMywgXCIuL3Zub2RlL3Zub2RlLmpzXCI6IDMxLCBcIi4vdm5vZGUvdnRleHQuanNcIjogMzMgfV0sIDU6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICAvKiFcbiAgICAgICAgICAgICAqIENyb3NzLUJyb3dzZXIgU3BsaXQgMS4xLjFcbiAgICAgICAgICAgICAqIENvcHlyaWdodCAyMDA3LTIwMTIgU3RldmVuIExldml0aGFuIDxzdGV2ZW5sZXZpdGhhbi5jb20+XG4gICAgICAgICAgICAgKiBBdmFpbGFibGUgdW5kZXIgdGhlIE1JVCBMaWNlbnNlXG4gICAgICAgICAgICAgKiBFQ01BU2NyaXB0IGNvbXBsaWFudCwgdW5pZm9ybSBjcm9zcy1icm93c2VyIHNwbGl0IG1ldGhvZFxuICAgICAgICAgICAgICovXG5cbiAgICAgICAgICAgIC8qKlxuICAgICAgICAgICAgICogU3BsaXRzIGEgc3RyaW5nIGludG8gYW4gYXJyYXkgb2Ygc3RyaW5ncyB1c2luZyBhIHJlZ2V4IG9yIHN0cmluZyBzZXBhcmF0b3IuIE1hdGNoZXMgb2YgdGhlXG4gICAgICAgICAgICAgKiBzZXBhcmF0b3IgYXJlIG5vdCBpbmNsdWRlZCBpbiB0aGUgcmVzdWx0IGFycmF5LiBIb3dldmVyLCBpZiBgc2VwYXJhdG9yYCBpcyBhIHJlZ2V4IHRoYXQgY29udGFpbnNcbiAgICAgICAgICAgICAqIGNhcHR1cmluZyBncm91cHMsIGJhY2tyZWZlcmVuY2VzIGFyZSBzcGxpY2VkIGludG8gdGhlIHJlc3VsdCBlYWNoIHRpbWUgYHNlcGFyYXRvcmAgaXMgbWF0Y2hlZC5cbiAgICAgICAgICAgICAqIEZpeGVzIGJyb3dzZXIgYnVncyBjb21wYXJlZCB0byB0aGUgbmF0aXZlIGBTdHJpbmcucHJvdG90eXBlLnNwbGl0YCBhbmQgY2FuIGJlIHVzZWQgcmVsaWFibHlcbiAgICAgICAgICAgICAqIGNyb3NzLWJyb3dzZXIuXG4gICAgICAgICAgICAgKiBAcGFyYW0ge1N0cmluZ30gc3RyIFN0cmluZyB0byBzcGxpdC5cbiAgICAgICAgICAgICAqIEBwYXJhbSB7UmVnRXhwfFN0cmluZ30gc2VwYXJhdG9yIFJlZ2V4IG9yIHN0cmluZyB0byB1c2UgZm9yIHNlcGFyYXRpbmcgdGhlIHN0cmluZy5cbiAgICAgICAgICAgICAqIEBwYXJhbSB7TnVtYmVyfSBbbGltaXRdIE1heGltdW0gbnVtYmVyIG9mIGl0ZW1zIHRvIGluY2x1ZGUgaW4gdGhlIHJlc3VsdCBhcnJheS5cbiAgICAgICAgICAgICAqIEByZXR1cm5zIHtBcnJheX0gQXJyYXkgb2Ygc3Vic3RyaW5ncy5cbiAgICAgICAgICAgICAqIEBleGFtcGxlXG4gICAgICAgICAgICAgKlxuICAgICAgICAgICAgICogLy8gQmFzaWMgdXNlXG4gICAgICAgICAgICAgKiBzcGxpdCgnYSBiIGMgZCcsICcgJyk7XG4gICAgICAgICAgICAgKiAvLyAtPiBbJ2EnLCAnYicsICdjJywgJ2QnXVxuICAgICAgICAgICAgICpcbiAgICAgICAgICAgICAqIC8vIFdpdGggbGltaXRcbiAgICAgICAgICAgICAqIHNwbGl0KCdhIGIgYyBkJywgJyAnLCAyKTtcbiAgICAgICAgICAgICAqIC8vIC0+IFsnYScsICdiJ11cbiAgICAgICAgICAgICAqXG4gICAgICAgICAgICAgKiAvLyBCYWNrcmVmZXJlbmNlcyBpbiByZXN1bHQgYXJyYXlcbiAgICAgICAgICAgICAqIHNwbGl0KCcuLndvcmQxIHdvcmQyLi4nLCAvKFthLXpdKykoXFxkKykvaSk7XG4gICAgICAgICAgICAgKiAvLyAtPiBbJy4uJywgJ3dvcmQnLCAnMScsICcgJywgJ3dvcmQnLCAnMicsICcuLiddXG4gICAgICAgICAgICAgKi9cbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gKGZ1bmN0aW9uIHNwbGl0KHVuZGVmKSB7XG5cbiAgICAgICAgICAgICAgICB2YXIgbmF0aXZlU3BsaXQgPSBTdHJpbmcucHJvdG90eXBlLnNwbGl0LFxuICAgICAgICAgICAgICAgICAgICBjb21wbGlhbnRFeGVjTnBjZyA9IC8oKT8/Ly5leGVjKFwiXCIpWzFdID09PSB1bmRlZixcblxuICAgICAgICAgICAgICAgIC8vIE5QQ0c6IG5vbnBhcnRpY2lwYXRpbmcgY2FwdHVyaW5nIGdyb3VwXG4gICAgICAgICAgICAgICAgc2VsZjtcblxuICAgICAgICAgICAgICAgIHNlbGYgPSBmdW5jdGlvbiAoc3RyLCBzZXBhcmF0b3IsIGxpbWl0KSB7XG4gICAgICAgICAgICAgICAgICAgIC8vIElmIGBzZXBhcmF0b3JgIGlzIG5vdCBhIHJlZ2V4LCB1c2UgYG5hdGl2ZVNwbGl0YFxuICAgICAgICAgICAgICAgICAgICBpZiAoT2JqZWN0LnByb3RvdHlwZS50b1N0cmluZy5jYWxsKHNlcGFyYXRvcikgIT09IFwiW29iamVjdCBSZWdFeHBdXCIpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBuYXRpdmVTcGxpdC5jYWxsKHN0ciwgc2VwYXJhdG9yLCBsaW1pdCk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgdmFyIG91dHB1dCA9IFtdLFxuICAgICAgICAgICAgICAgICAgICAgICAgZmxhZ3MgPSAoc2VwYXJhdG9yLmlnbm9yZUNhc2UgPyBcImlcIiA6IFwiXCIpICsgKHNlcGFyYXRvci5tdWx0aWxpbmUgPyBcIm1cIiA6IFwiXCIpICsgKHNlcGFyYXRvci5leHRlbmRlZCA/IFwieFwiIDogXCJcIikgKyAoc2VwYXJhdG9yLnN0aWNreSA/IFwieVwiIDogXCJcIiksXG5cbiAgICAgICAgICAgICAgICAgICAgLy8gRmlyZWZveCAzK1xuICAgICAgICAgICAgICAgICAgICBsYXN0TGFzdEluZGV4ID0gMCxcblxuICAgICAgICAgICAgICAgICAgICAvLyBNYWtlIGBnbG9iYWxgIGFuZCBhdm9pZCBgbGFzdEluZGV4YCBpc3N1ZXMgYnkgd29ya2luZyB3aXRoIGEgY29weVxuICAgICAgICAgICAgICAgICAgICBzZXBhcmF0b3IgPSBuZXcgUmVnRXhwKHNlcGFyYXRvci5zb3VyY2UsIGZsYWdzICsgXCJnXCIpLFxuICAgICAgICAgICAgICAgICAgICAgICAgc2VwYXJhdG9yMixcbiAgICAgICAgICAgICAgICAgICAgICAgIG1hdGNoLFxuICAgICAgICAgICAgICAgICAgICAgICAgbGFzdEluZGV4LFxuICAgICAgICAgICAgICAgICAgICAgICAgbGFzdExlbmd0aDtcbiAgICAgICAgICAgICAgICAgICAgc3RyICs9IFwiXCI7IC8vIFR5cGUtY29udmVydFxuICAgICAgICAgICAgICAgICAgICBpZiAoIWNvbXBsaWFudEV4ZWNOcGNnKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAvLyBEb2Vzbid0IG5lZWQgZmxhZ3MgZ3ksIGJ1dCB0aGV5IGRvbid0IGh1cnRcbiAgICAgICAgICAgICAgICAgICAgICAgIHNlcGFyYXRvcjIgPSBuZXcgUmVnRXhwKFwiXlwiICsgc2VwYXJhdG9yLnNvdXJjZSArIFwiJCg/IVxcXFxzKVwiLCBmbGFncyk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgLyogVmFsdWVzIGZvciBgbGltaXRgLCBwZXIgdGhlIHNwZWM6XG4gICAgICAgICAgICAgICAgICAgICAqIElmIHVuZGVmaW5lZDogNDI5NDk2NzI5NSAvLyBNYXRoLnBvdygyLCAzMikgLSAxXG4gICAgICAgICAgICAgICAgICAgICAqIElmIDAsIEluZmluaXR5LCBvciBOYU46IDBcbiAgICAgICAgICAgICAgICAgICAgICogSWYgcG9zaXRpdmUgbnVtYmVyOiBsaW1pdCA9IE1hdGguZmxvb3IobGltaXQpOyBpZiAobGltaXQgPiA0Mjk0OTY3Mjk1KSBsaW1pdCAtPSA0Mjk0OTY3Mjk2O1xuICAgICAgICAgICAgICAgICAgICAgKiBJZiBuZWdhdGl2ZSBudW1iZXI6IDQyOTQ5NjcyOTYgLSBNYXRoLmZsb29yKE1hdGguYWJzKGxpbWl0KSlcbiAgICAgICAgICAgICAgICAgICAgICogSWYgb3RoZXI6IFR5cGUtY29udmVydCwgdGhlbiB1c2UgdGhlIGFib3ZlIHJ1bGVzXG4gICAgICAgICAgICAgICAgICAgICAqL1xuICAgICAgICAgICAgICAgICAgICBsaW1pdCA9IGxpbWl0ID09PSB1bmRlZiA/IC0xID4+PiAwIDogLy8gTWF0aC5wb3coMiwgMzIpIC0gMVxuICAgICAgICAgICAgICAgICAgICBsaW1pdCA+Pj4gMDsgLy8gVG9VaW50MzIobGltaXQpXG4gICAgICAgICAgICAgICAgICAgIHdoaWxlIChtYXRjaCA9IHNlcGFyYXRvci5leGVjKHN0cikpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIGBzZXBhcmF0b3IubGFzdEluZGV4YCBpcyBub3QgcmVsaWFibGUgY3Jvc3MtYnJvd3NlclxuICAgICAgICAgICAgICAgICAgICAgICAgbGFzdEluZGV4ID0gbWF0Y2guaW5kZXggKyBtYXRjaFswXS5sZW5ndGg7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAobGFzdEluZGV4ID4gbGFzdExhc3RJbmRleCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIG91dHB1dC5wdXNoKHN0ci5zbGljZShsYXN0TGFzdEluZGV4LCBtYXRjaC5pbmRleCkpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIEZpeCBicm93c2VycyB3aG9zZSBgZXhlY2AgbWV0aG9kcyBkb24ndCBjb25zaXN0ZW50bHkgcmV0dXJuIGB1bmRlZmluZWRgIGZvclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIG5vbnBhcnRpY2lwYXRpbmcgY2FwdHVyaW5nIGdyb3Vwc1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmICghY29tcGxpYW50RXhlY05wY2cgJiYgbWF0Y2gubGVuZ3RoID4gMSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBtYXRjaFswXS5yZXBsYWNlKHNlcGFyYXRvcjIsIGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZvciAodmFyIGkgPSAxOyBpIDwgYXJndW1lbnRzLmxlbmd0aCAtIDI7IGkrKykge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChhcmd1bWVudHNbaV0gPT09IHVuZGVmKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1hdGNoW2ldID0gdW5kZWY7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKG1hdGNoLmxlbmd0aCA+IDEgJiYgbWF0Y2guaW5kZXggPCBzdHIubGVuZ3RoKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIEFycmF5LnByb3RvdHlwZS5wdXNoLmFwcGx5KG91dHB1dCwgbWF0Y2guc2xpY2UoMSkpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBsYXN0TGVuZ3RoID0gbWF0Y2hbMF0ubGVuZ3RoO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxhc3RMYXN0SW5kZXggPSBsYXN0SW5kZXg7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKG91dHB1dC5sZW5ndGggPj0gbGltaXQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHNlcGFyYXRvci5sYXN0SW5kZXggPT09IG1hdGNoLmluZGV4KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgc2VwYXJhdG9yLmxhc3RJbmRleCsrOyAvLyBBdm9pZCBhbiBpbmZpbml0ZSBsb29wXG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgaWYgKGxhc3RMYXN0SW5kZXggPT09IHN0ci5sZW5ndGgpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChsYXN0TGVuZ3RoIHx8ICFzZXBhcmF0b3IudGVzdChcIlwiKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIG91dHB1dC5wdXNoKFwiXCIpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgb3V0cHV0LnB1c2goc3RyLnNsaWNlKGxhc3RMYXN0SW5kZXgpKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICByZXR1cm4gb3V0cHV0Lmxlbmd0aCA+IGxpbWl0ID8gb3V0cHV0LnNsaWNlKDAsIGxpbWl0KSA6IG91dHB1dDtcbiAgICAgICAgICAgICAgICB9O1xuXG4gICAgICAgICAgICAgICAgcmV0dXJuIHNlbGY7XG4gICAgICAgICAgICB9KSgpO1xuICAgICAgICB9LCB7fV0sIDY6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7fSwge31dLCA3OiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge1xuICAgICAgICAgICAgXCJ1c2Ugc3RyaWN0XCI7XG5cbiAgICAgICAgICAgIHZhciBPbmVWZXJzaW9uQ29uc3RyYWludCA9IHJlcXVpcmUoXCJpbmRpdmlkdWFsL29uZS12ZXJzaW9uXCIpO1xuXG4gICAgICAgICAgICB2YXIgTVlfVkVSU0lPTiA9IFwiN1wiO1xuICAgICAgICAgICAgT25lVmVyc2lvbkNvbnN0cmFpbnQoXCJldi1zdG9yZVwiLCBNWV9WRVJTSU9OKTtcblxuICAgICAgICAgICAgdmFyIGhhc2hLZXkgPSBcIl9fRVZfU1RPUkVfS0VZQFwiICsgTVlfVkVSU0lPTjtcblxuICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBFdlN0b3JlO1xuXG4gICAgICAgICAgICBmdW5jdGlvbiBFdlN0b3JlKGVsZW0pIHtcbiAgICAgICAgICAgICAgICB2YXIgaGFzaCA9IGVsZW1baGFzaEtleV07XG5cbiAgICAgICAgICAgICAgICBpZiAoIWhhc2gpIHtcbiAgICAgICAgICAgICAgICAgICAgaGFzaCA9IGVsZW1baGFzaEtleV0gPSB7fTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICByZXR1cm4gaGFzaDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSwgeyBcImluZGl2aWR1YWwvb25lLXZlcnNpb25cIjogOSB9XSwgODogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHtcbiAgICAgICAgICAgIChmdW5jdGlvbiAoZ2xvYmFsKSB7XG4gICAgICAgICAgICAgICAgXCJ1c2Ugc3RyaWN0XCI7XG5cbiAgICAgICAgICAgICAgICAvKmdsb2JhbCB3aW5kb3csIGdsb2JhbCovXG5cbiAgICAgICAgICAgICAgICB2YXIgcm9vdCA9IHR5cGVvZiB3aW5kb3cgIT09IFwidW5kZWZpbmVkXCIgPyB3aW5kb3cgOiB0eXBlb2YgZ2xvYmFsICE9PSBcInVuZGVmaW5lZFwiID8gZ2xvYmFsIDoge307XG5cbiAgICAgICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IEluZGl2aWR1YWw7XG5cbiAgICAgICAgICAgICAgICBmdW5jdGlvbiBJbmRpdmlkdWFsKGtleSwgdmFsdWUpIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKGtleSBpbiByb290KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gcm9vdFtrZXldO1xuICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgcm9vdFtrZXldID0gdmFsdWU7XG5cbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHZhbHVlO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0pLmNhbGwodGhpcywgdHlwZW9mIGdsb2JhbCAhPT0gXCJ1bmRlZmluZWRcIiA/IGdsb2JhbCA6IHR5cGVvZiBzZWxmICE9PSBcInVuZGVmaW5lZFwiID8gc2VsZiA6IHR5cGVvZiB3aW5kb3cgIT09IFwidW5kZWZpbmVkXCIgPyB3aW5kb3cgOiB7fSk7XG4gICAgICAgIH0sIHt9XSwgOTogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHtcbiAgICAgICAgICAgIFwidXNlIHN0cmljdFwiO1xuXG4gICAgICAgICAgICB2YXIgSW5kaXZpZHVhbCA9IHJlcXVpcmUoXCIuL2luZGV4LmpzXCIpO1xuXG4gICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IE9uZVZlcnNpb247XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIE9uZVZlcnNpb24obW9kdWxlTmFtZSwgdmVyc2lvbiwgZGVmYXVsdFZhbHVlKSB7XG4gICAgICAgICAgICAgICAgdmFyIGtleSA9IFwiX19JTkRJVklEVUFMX09ORV9WRVJTSU9OX1wiICsgbW9kdWxlTmFtZTtcbiAgICAgICAgICAgICAgICB2YXIgZW5mb3JjZUtleSA9IGtleSArIFwiX0VORk9SQ0VfU0lOR0xFVE9OXCI7XG5cbiAgICAgICAgICAgICAgICB2YXIgdmVyc2lvblZhbHVlID0gSW5kaXZpZHVhbChlbmZvcmNlS2V5LCB2ZXJzaW9uKTtcblxuICAgICAgICAgICAgICAgIGlmICh2ZXJzaW9uVmFsdWUgIT09IHZlcnNpb24pIHtcbiAgICAgICAgICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKFwiQ2FuIG9ubHkgaGF2ZSBvbmUgY29weSBvZiBcIiArIG1vZHVsZU5hbWUgKyBcIi5cXG5cIiArIFwiWW91IGFscmVhZHkgaGF2ZSB2ZXJzaW9uIFwiICsgdmVyc2lvblZhbHVlICsgXCIgaW5zdGFsbGVkLlxcblwiICsgXCJUaGlzIG1lYW5zIHlvdSBjYW5ub3QgaW5zdGFsbCB2ZXJzaW9uIFwiICsgdmVyc2lvbik7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgcmV0dXJuIEluZGl2aWR1YWwoa2V5LCBkZWZhdWx0VmFsdWUpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9LCB7IFwiLi9pbmRleC5qc1wiOiA4IH1dLCAxMDogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHtcbiAgICAgICAgICAgIChmdW5jdGlvbiAoZ2xvYmFsKSB7XG4gICAgICAgICAgICAgICAgdmFyIHRvcExldmVsID0gdHlwZW9mIGdsb2JhbCAhPT0gXCJ1bmRlZmluZWRcIiA/IGdsb2JhbCA6IHR5cGVvZiB3aW5kb3cgIT09IFwidW5kZWZpbmVkXCIgPyB3aW5kb3cgOiB7fTtcbiAgICAgICAgICAgICAgICB2YXIgbWluRG9jID0gcmVxdWlyZShcIm1pbi1kb2N1bWVudFwiKTtcblxuICAgICAgICAgICAgICAgIGlmICh0eXBlb2YgZG9jdW1lbnQgIT09IFwidW5kZWZpbmVkXCIpIHtcbiAgICAgICAgICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBkb2N1bWVudDtcbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICB2YXIgZG9jY3kgPSB0b3BMZXZlbFtcIl9fR0xPQkFMX0RPQ1VNRU5UX0NBQ0hFQDRcIl07XG5cbiAgICAgICAgICAgICAgICAgICAgaWYgKCFkb2NjeSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgZG9jY3kgPSB0b3BMZXZlbFtcIl9fR0xPQkFMX0RPQ1VNRU5UX0NBQ0hFQDRcIl0gPSBtaW5Eb2M7XG4gICAgICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IGRvY2N5O1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0pLmNhbGwodGhpcywgdHlwZW9mIGdsb2JhbCAhPT0gXCJ1bmRlZmluZWRcIiA/IGdsb2JhbCA6IHR5cGVvZiBzZWxmICE9PSBcInVuZGVmaW5lZFwiID8gc2VsZiA6IHR5cGVvZiB3aW5kb3cgIT09IFwidW5kZWZpbmVkXCIgPyB3aW5kb3cgOiB7fSk7XG4gICAgICAgIH0sIHsgXCJtaW4tZG9jdW1lbnRcIjogNiB9XSwgMTE6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICBcInVzZSBzdHJpY3RcIjtcblxuICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiBpc09iamVjdCh4KSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHR5cGVvZiB4ID09PSBcIm9iamVjdFwiICYmIHggIT09IG51bGw7XG4gICAgICAgICAgICB9O1xuICAgICAgICB9LCB7fV0sIDEyOiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge1xuICAgICAgICAgICAgdmFyIG5hdGl2ZUlzQXJyYXkgPSBBcnJheS5pc0FycmF5O1xuICAgICAgICAgICAgdmFyIHRvU3RyaW5nID0gT2JqZWN0LnByb3RvdHlwZS50b1N0cmluZztcblxuICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBuYXRpdmVJc0FycmF5IHx8IGlzQXJyYXk7XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIGlzQXJyYXkob2JqKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHRvU3RyaW5nLmNhbGwob2JqKSA9PT0gXCJbb2JqZWN0IEFycmF5XVwiO1xuICAgICAgICAgICAgfVxuICAgICAgICB9LCB7fV0sIDEzOiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge1xuICAgICAgICAgICAgdmFyIHBhdGNoID0gcmVxdWlyZShcIi4vdmRvbS9wYXRjaC5qc1wiKTtcblxuICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBwYXRjaDtcbiAgICAgICAgfSwgeyBcIi4vdmRvbS9wYXRjaC5qc1wiOiAxOCB9XSwgMTQ6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICB2YXIgaXNPYmplY3QgPSByZXF1aXJlKFwiaXMtb2JqZWN0XCIpO1xuICAgICAgICAgICAgdmFyIGlzSG9vayA9IHJlcXVpcmUoXCIuLi92bm9kZS9pcy12aG9vay5qc1wiKTtcblxuICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBhcHBseVByb3BlcnRpZXM7XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIGFwcGx5UHJvcGVydGllcyhub2RlLCBwcm9wcywgcHJldmlvdXMpIHtcbiAgICAgICAgICAgICAgICBmb3IgKHZhciBwcm9wTmFtZSBpbiBwcm9wcykge1xuICAgICAgICAgICAgICAgICAgICB2YXIgcHJvcFZhbHVlID0gcHJvcHNbcHJvcE5hbWVdO1xuXG4gICAgICAgICAgICAgICAgICAgIGlmIChwcm9wVmFsdWUgPT09IHVuZGVmaW5lZCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgcmVtb3ZlUHJvcGVydHkobm9kZSwgcHJvcE5hbWUsIHByb3BWYWx1ZSwgcHJldmlvdXMpO1xuICAgICAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKGlzSG9vayhwcm9wVmFsdWUpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICByZW1vdmVQcm9wZXJ0eShub2RlLCBwcm9wTmFtZSwgcHJvcFZhbHVlLCBwcmV2aW91cyk7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAocHJvcFZhbHVlLmhvb2spIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBwcm9wVmFsdWUuaG9vayhub2RlLCBwcm9wTmFtZSwgcHJldmlvdXMgPyBwcmV2aW91c1twcm9wTmFtZV0gOiB1bmRlZmluZWQpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGlzT2JqZWN0KHByb3BWYWx1ZSkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBwYXRjaE9iamVjdChub2RlLCBwcm9wcywgcHJldmlvdXMsIHByb3BOYW1lLCBwcm9wVmFsdWUpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBub2RlW3Byb3BOYW1lXSA9IHByb3BWYWx1ZTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZnVuY3Rpb24gcmVtb3ZlUHJvcGVydHkobm9kZSwgcHJvcE5hbWUsIHByb3BWYWx1ZSwgcHJldmlvdXMpIHtcbiAgICAgICAgICAgICAgICBpZiAocHJldmlvdXMpIHtcbiAgICAgICAgICAgICAgICAgICAgdmFyIHByZXZpb3VzVmFsdWUgPSBwcmV2aW91c1twcm9wTmFtZV07XG5cbiAgICAgICAgICAgICAgICAgICAgaWYgKCFpc0hvb2socHJldmlvdXNWYWx1ZSkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChwcm9wTmFtZSA9PT0gXCJhdHRyaWJ1dGVzXCIpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBmb3IgKHZhciBhdHRyTmFtZSBpbiBwcmV2aW91c1ZhbHVlKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG5vZGUucmVtb3ZlQXR0cmlidXRlKGF0dHJOYW1lKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKHByb3BOYW1lID09PSBcInN0eWxlXCIpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBmb3IgKHZhciBpIGluIHByZXZpb3VzVmFsdWUpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbm9kZS5zdHlsZVtpXSA9IFwiXCI7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIGlmICh0eXBlb2YgcHJldmlvdXNWYWx1ZSA9PT0gXCJzdHJpbmdcIikge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIG5vZGVbcHJvcE5hbWVdID0gXCJcIjtcbiAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgbm9kZVtwcm9wTmFtZV0gPSBudWxsO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKHByZXZpb3VzVmFsdWUudW5ob29rKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBwcmV2aW91c1ZhbHVlLnVuaG9vayhub2RlLCBwcm9wTmFtZSwgcHJvcFZhbHVlKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZnVuY3Rpb24gcGF0Y2hPYmplY3Qobm9kZSwgcHJvcHMsIHByZXZpb3VzLCBwcm9wTmFtZSwgcHJvcFZhbHVlKSB7XG4gICAgICAgICAgICAgICAgdmFyIHByZXZpb3VzVmFsdWUgPSBwcmV2aW91cyA/IHByZXZpb3VzW3Byb3BOYW1lXSA6IHVuZGVmaW5lZDtcblxuICAgICAgICAgICAgICAgIC8vIFNldCBhdHRyaWJ1dGVzXG4gICAgICAgICAgICAgICAgaWYgKHByb3BOYW1lID09PSBcImF0dHJpYnV0ZXNcIikge1xuICAgICAgICAgICAgICAgICAgICBmb3IgKHZhciBhdHRyTmFtZSBpbiBwcm9wVmFsdWUpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHZhciBhdHRyVmFsdWUgPSBwcm9wVmFsdWVbYXR0ck5hbWVdO1xuXG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoYXR0clZhbHVlID09PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBub2RlLnJlbW92ZUF0dHJpYnV0ZShhdHRyTmFtZSk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIG5vZGUuc2V0QXR0cmlidXRlKGF0dHJOYW1lLCBhdHRyVmFsdWUpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIGlmIChwcmV2aW91c1ZhbHVlICYmIGlzT2JqZWN0KHByZXZpb3VzVmFsdWUpICYmIGdldFByb3RvdHlwZShwcmV2aW91c1ZhbHVlKSAhPT0gZ2V0UHJvdG90eXBlKHByb3BWYWx1ZSkpIHtcbiAgICAgICAgICAgICAgICAgICAgbm9kZVtwcm9wTmFtZV0gPSBwcm9wVmFsdWU7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICBpZiAoIWlzT2JqZWN0KG5vZGVbcHJvcE5hbWVdKSkge1xuICAgICAgICAgICAgICAgICAgICBub2RlW3Byb3BOYW1lXSA9IHt9O1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHZhciByZXBsYWNlciA9IHByb3BOYW1lID09PSBcInN0eWxlXCIgPyBcIlwiIDogdW5kZWZpbmVkO1xuXG4gICAgICAgICAgICAgICAgZm9yICh2YXIgayBpbiBwcm9wVmFsdWUpIHtcbiAgICAgICAgICAgICAgICAgICAgdmFyIHZhbHVlID0gcHJvcFZhbHVlW2tdO1xuICAgICAgICAgICAgICAgICAgICBub2RlW3Byb3BOYW1lXVtrXSA9IHZhbHVlID09PSB1bmRlZmluZWQgPyByZXBsYWNlciA6IHZhbHVlO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZnVuY3Rpb24gZ2V0UHJvdG90eXBlKHZhbHVlKSB7XG4gICAgICAgICAgICAgICAgaWYgKE9iamVjdC5nZXRQcm90b3R5cGVPZikge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gT2JqZWN0LmdldFByb3RvdHlwZU9mKHZhbHVlKTtcbiAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKHZhbHVlLl9fcHJvdG9fXykge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gdmFsdWUuX19wcm90b19fO1xuICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAodmFsdWUuY29uc3RydWN0b3IpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHZhbHVlLmNvbnN0cnVjdG9yLnByb3RvdHlwZTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH0sIHsgXCIuLi92bm9kZS9pcy12aG9vay5qc1wiOiAyNiwgXCJpcy1vYmplY3RcIjogMTEgfV0sIDE1OiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge1xuICAgICAgICAgICAgdmFyIGRvY3VtZW50ID0gcmVxdWlyZShcImdsb2JhbC9kb2N1bWVudFwiKTtcblxuICAgICAgICAgICAgdmFyIGFwcGx5UHJvcGVydGllcyA9IHJlcXVpcmUoXCIuL2FwcGx5LXByb3BlcnRpZXNcIik7XG5cbiAgICAgICAgICAgIHZhciBpc1ZOb2RlID0gcmVxdWlyZShcIi4uL3Zub2RlL2lzLXZub2RlLmpzXCIpO1xuICAgICAgICAgICAgdmFyIGlzVlRleHQgPSByZXF1aXJlKFwiLi4vdm5vZGUvaXMtdnRleHQuanNcIik7XG4gICAgICAgICAgICB2YXIgaXNXaWRnZXQgPSByZXF1aXJlKFwiLi4vdm5vZGUvaXMtd2lkZ2V0LmpzXCIpO1xuICAgICAgICAgICAgdmFyIGhhbmRsZVRodW5rID0gcmVxdWlyZShcIi4uL3Zub2RlL2hhbmRsZS10aHVuay5qc1wiKTtcblxuICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBjcmVhdGVFbGVtZW50O1xuXG4gICAgICAgICAgICBmdW5jdGlvbiBjcmVhdGVFbGVtZW50KHZub2RlLCBvcHRzKSB7XG4gICAgICAgICAgICAgICAgdmFyIGRvYyA9IG9wdHMgPyBvcHRzLmRvY3VtZW50IHx8IGRvY3VtZW50IDogZG9jdW1lbnQ7XG4gICAgICAgICAgICAgICAgdmFyIHdhcm4gPSBvcHRzID8gb3B0cy53YXJuIDogbnVsbDtcblxuICAgICAgICAgICAgICAgIHZub2RlID0gaGFuZGxlVGh1bmsodm5vZGUpLmE7XG5cbiAgICAgICAgICAgICAgICBpZiAoaXNXaWRnZXQodm5vZGUpKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiB2bm9kZS5pbml0KCk7XG4gICAgICAgICAgICAgICAgfSBlbHNlIGlmIChpc1ZUZXh0KHZub2RlKSkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gZG9jLmNyZWF0ZVRleHROb2RlKHZub2RlLnRleHQpO1xuICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoIWlzVk5vZGUodm5vZGUpKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmICh3YXJuKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICB3YXJuKFwiSXRlbSBpcyBub3QgYSB2YWxpZCB2aXJ0dWFsIGRvbSBub2RlXCIsIHZub2RlKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICByZXR1cm4gbnVsbDtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICB2YXIgbm9kZSA9IHZub2RlLm5hbWVzcGFjZSA9PT0gbnVsbCA/IGRvYy5jcmVhdGVFbGVtZW50KHZub2RlLnRhZ05hbWUpIDogZG9jLmNyZWF0ZUVsZW1lbnROUyh2bm9kZS5uYW1lc3BhY2UsIHZub2RlLnRhZ05hbWUpO1xuXG4gICAgICAgICAgICAgICAgdmFyIHByb3BzID0gdm5vZGUucHJvcGVydGllcztcbiAgICAgICAgICAgICAgICBhcHBseVByb3BlcnRpZXMobm9kZSwgcHJvcHMpO1xuXG4gICAgICAgICAgICAgICAgdmFyIGNoaWxkcmVuID0gdm5vZGUuY2hpbGRyZW47XG5cbiAgICAgICAgICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IGNoaWxkcmVuLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciBjaGlsZE5vZGUgPSBjcmVhdGVFbGVtZW50KGNoaWxkcmVuW2ldLCBvcHRzKTtcbiAgICAgICAgICAgICAgICAgICAgaWYgKGNoaWxkTm9kZSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgbm9kZS5hcHBlbmRDaGlsZChjaGlsZE5vZGUpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgcmV0dXJuIG5vZGU7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0sIHsgXCIuLi92bm9kZS9oYW5kbGUtdGh1bmsuanNcIjogMjQsIFwiLi4vdm5vZGUvaXMtdm5vZGUuanNcIjogMjcsIFwiLi4vdm5vZGUvaXMtdnRleHQuanNcIjogMjgsIFwiLi4vdm5vZGUvaXMtd2lkZ2V0LmpzXCI6IDI5LCBcIi4vYXBwbHktcHJvcGVydGllc1wiOiAxNCwgXCJnbG9iYWwvZG9jdW1lbnRcIjogMTAgfV0sIDE2OiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge1xuICAgICAgICAgICAgLy8gTWFwcyBhIHZpcnR1YWwgRE9NIHRyZWUgb250byBhIHJlYWwgRE9NIHRyZWUgaW4gYW4gZWZmaWNpZW50IG1hbm5lci5cbiAgICAgICAgICAgIC8vIFdlIGRvbid0IHdhbnQgdG8gcmVhZCBhbGwgb2YgdGhlIERPTSBub2RlcyBpbiB0aGUgdHJlZSBzbyB3ZSB1c2VcbiAgICAgICAgICAgIC8vIHRoZSBpbi1vcmRlciB0cmVlIGluZGV4aW5nIHRvIGVsaW1pbmF0ZSByZWN1cnNpb24gZG93biBjZXJ0YWluIGJyYW5jaGVzLlxuICAgICAgICAgICAgLy8gV2Ugb25seSByZWN1cnNlIGludG8gYSBET00gbm9kZSBpZiB3ZSBrbm93IHRoYXQgaXQgY29udGFpbnMgYSBjaGlsZCBvZlxuICAgICAgICAgICAgLy8gaW50ZXJlc3QuXG5cbiAgICAgICAgICAgIHZhciBub0NoaWxkID0ge307XG5cbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gZG9tSW5kZXg7XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIGRvbUluZGV4KHJvb3ROb2RlLCB0cmVlLCBpbmRpY2VzLCBub2Rlcykge1xuICAgICAgICAgICAgICAgIGlmICghaW5kaWNlcyB8fCBpbmRpY2VzLmxlbmd0aCA9PT0gMCkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4ge307XG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgaW5kaWNlcy5zb3J0KGFzY2VuZGluZyk7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiByZWN1cnNlKHJvb3ROb2RlLCB0cmVlLCBpbmRpY2VzLCBub2RlcywgMCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBmdW5jdGlvbiByZWN1cnNlKHJvb3ROb2RlLCB0cmVlLCBpbmRpY2VzLCBub2Rlcywgcm9vdEluZGV4KSB7XG4gICAgICAgICAgICAgICAgbm9kZXMgPSBub2RlcyB8fCB7fTtcblxuICAgICAgICAgICAgICAgIGlmIChyb290Tm9kZSkge1xuICAgICAgICAgICAgICAgICAgICBpZiAoaW5kZXhJblJhbmdlKGluZGljZXMsIHJvb3RJbmRleCwgcm9vdEluZGV4KSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgbm9kZXNbcm9vdEluZGV4XSA9IHJvb3ROb2RlO1xuICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgdmFyIHZDaGlsZHJlbiA9IHRyZWUuY2hpbGRyZW47XG5cbiAgICAgICAgICAgICAgICAgICAgaWYgKHZDaGlsZHJlbikge1xuXG4gICAgICAgICAgICAgICAgICAgICAgICB2YXIgY2hpbGROb2RlcyA9IHJvb3ROb2RlLmNoaWxkTm9kZXM7XG5cbiAgICAgICAgICAgICAgICAgICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgdHJlZS5jaGlsZHJlbi5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJvb3RJbmRleCArPSAxO1xuXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdmFyIHZDaGlsZCA9IHZDaGlsZHJlbltpXSB8fCBub0NoaWxkO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZhciBuZXh0SW5kZXggPSByb290SW5kZXggKyAodkNoaWxkLmNvdW50IHx8IDApO1xuXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gc2tpcCByZWN1cnNpb24gZG93biB0aGUgdHJlZSBpZiB0aGVyZSBhcmUgbm8gbm9kZXMgZG93biBoZXJlXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGluZGV4SW5SYW5nZShpbmRpY2VzLCByb290SW5kZXgsIG5leHRJbmRleCkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmVjdXJzZShjaGlsZE5vZGVzW2ldLCB2Q2hpbGQsIGluZGljZXMsIG5vZGVzLCByb290SW5kZXgpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJvb3RJbmRleCA9IG5leHRJbmRleDtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHJldHVybiBub2RlcztcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgLy8gQmluYXJ5IHNlYXJjaCBmb3IgYW4gaW5kZXggaW4gdGhlIGludGVydmFsIFtsZWZ0LCByaWdodF1cbiAgICAgICAgICAgIGZ1bmN0aW9uIGluZGV4SW5SYW5nZShpbmRpY2VzLCBsZWZ0LCByaWdodCkge1xuICAgICAgICAgICAgICAgIGlmIChpbmRpY2VzLmxlbmd0aCA9PT0gMCkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgdmFyIG1pbkluZGV4ID0gMDtcbiAgICAgICAgICAgICAgICB2YXIgbWF4SW5kZXggPSBpbmRpY2VzLmxlbmd0aCAtIDE7XG4gICAgICAgICAgICAgICAgdmFyIGN1cnJlbnRJbmRleDtcbiAgICAgICAgICAgICAgICB2YXIgY3VycmVudEl0ZW07XG5cbiAgICAgICAgICAgICAgICB3aGlsZSAobWluSW5kZXggPD0gbWF4SW5kZXgpIHtcbiAgICAgICAgICAgICAgICAgICAgY3VycmVudEluZGV4ID0gKG1heEluZGV4ICsgbWluSW5kZXgpIC8gMiA+PiAwO1xuICAgICAgICAgICAgICAgICAgICBjdXJyZW50SXRlbSA9IGluZGljZXNbY3VycmVudEluZGV4XTtcblxuICAgICAgICAgICAgICAgICAgICBpZiAobWluSW5kZXggPT09IG1heEluZGV4KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gY3VycmVudEl0ZW0gPj0gbGVmdCAmJiBjdXJyZW50SXRlbSA8PSByaWdodDtcbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIGlmIChjdXJyZW50SXRlbSA8IGxlZnQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIG1pbkluZGV4ID0gY3VycmVudEluZGV4ICsgMTtcbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIGlmIChjdXJyZW50SXRlbSA+IHJpZ2h0KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBtYXhJbmRleCA9IGN1cnJlbnRJbmRleCAtIDE7XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZnVuY3Rpb24gYXNjZW5kaW5nKGEsIGIpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gYSA+IGIgPyAxIDogLTE7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0sIHt9XSwgMTc6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICB2YXIgYXBwbHlQcm9wZXJ0aWVzID0gcmVxdWlyZShcIi4vYXBwbHktcHJvcGVydGllc1wiKTtcblxuICAgICAgICAgICAgdmFyIGlzV2lkZ2V0ID0gcmVxdWlyZShcIi4uL3Zub2RlL2lzLXdpZGdldC5qc1wiKTtcbiAgICAgICAgICAgIHZhciBWUGF0Y2ggPSByZXF1aXJlKFwiLi4vdm5vZGUvdnBhdGNoLmpzXCIpO1xuXG4gICAgICAgICAgICB2YXIgdXBkYXRlV2lkZ2V0ID0gcmVxdWlyZShcIi4vdXBkYXRlLXdpZGdldFwiKTtcblxuICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBhcHBseVBhdGNoO1xuXG4gICAgICAgICAgICBmdW5jdGlvbiBhcHBseVBhdGNoKHZwYXRjaCwgZG9tTm9kZSwgcmVuZGVyT3B0aW9ucykge1xuICAgICAgICAgICAgICAgIHZhciB0eXBlID0gdnBhdGNoLnR5cGU7XG4gICAgICAgICAgICAgICAgdmFyIHZOb2RlID0gdnBhdGNoLnZOb2RlO1xuICAgICAgICAgICAgICAgIHZhciBwYXRjaCA9IHZwYXRjaC5wYXRjaDtcblxuICAgICAgICAgICAgICAgIHN3aXRjaCAodHlwZSkge1xuICAgICAgICAgICAgICAgICAgICBjYXNlIFZQYXRjaC5SRU1PVkU6XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gcmVtb3ZlTm9kZShkb21Ob2RlLCB2Tm9kZSk7XG4gICAgICAgICAgICAgICAgICAgIGNhc2UgVlBhdGNoLklOU0VSVDpcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBpbnNlcnROb2RlKGRvbU5vZGUsIHBhdGNoLCByZW5kZXJPcHRpb25zKTtcbiAgICAgICAgICAgICAgICAgICAgY2FzZSBWUGF0Y2guVlRFWFQ6XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gc3RyaW5nUGF0Y2goZG9tTm9kZSwgdk5vZGUsIHBhdGNoLCByZW5kZXJPcHRpb25zKTtcbiAgICAgICAgICAgICAgICAgICAgY2FzZSBWUGF0Y2guV0lER0VUOlxuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHdpZGdldFBhdGNoKGRvbU5vZGUsIHZOb2RlLCBwYXRjaCwgcmVuZGVyT3B0aW9ucyk7XG4gICAgICAgICAgICAgICAgICAgIGNhc2UgVlBhdGNoLlZOT0RFOlxuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHZOb2RlUGF0Y2goZG9tTm9kZSwgdk5vZGUsIHBhdGNoLCByZW5kZXJPcHRpb25zKTtcbiAgICAgICAgICAgICAgICAgICAgY2FzZSBWUGF0Y2guT1JERVI6XG4gICAgICAgICAgICAgICAgICAgICAgICByZW9yZGVyQ2hpbGRyZW4oZG9tTm9kZSwgcGF0Y2gpO1xuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGRvbU5vZGU7XG4gICAgICAgICAgICAgICAgICAgIGNhc2UgVlBhdGNoLlBST1BTOlxuICAgICAgICAgICAgICAgICAgICAgICAgYXBwbHlQcm9wZXJ0aWVzKGRvbU5vZGUsIHBhdGNoLCB2Tm9kZS5wcm9wZXJ0aWVzKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBkb21Ob2RlO1xuICAgICAgICAgICAgICAgICAgICBjYXNlIFZQYXRjaC5USFVOSzpcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiByZXBsYWNlUm9vdChkb21Ob2RlLCByZW5kZXJPcHRpb25zLnBhdGNoKGRvbU5vZGUsIHBhdGNoLCByZW5kZXJPcHRpb25zKSk7XG4gICAgICAgICAgICAgICAgICAgIGRlZmF1bHQ6XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gZG9tTm9kZTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIHJlbW92ZU5vZGUoZG9tTm9kZSwgdk5vZGUpIHtcbiAgICAgICAgICAgICAgICB2YXIgcGFyZW50Tm9kZSA9IGRvbU5vZGUucGFyZW50Tm9kZTtcblxuICAgICAgICAgICAgICAgIGlmIChwYXJlbnROb2RlKSB7XG4gICAgICAgICAgICAgICAgICAgIHBhcmVudE5vZGUucmVtb3ZlQ2hpbGQoZG9tTm9kZSk7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgZGVzdHJveVdpZGdldChkb21Ob2RlLCB2Tm9kZSk7XG5cbiAgICAgICAgICAgICAgICByZXR1cm4gbnVsbDtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZnVuY3Rpb24gaW5zZXJ0Tm9kZShwYXJlbnROb2RlLCB2Tm9kZSwgcmVuZGVyT3B0aW9ucykge1xuICAgICAgICAgICAgICAgIHZhciBuZXdOb2RlID0gcmVuZGVyT3B0aW9ucy5yZW5kZXIodk5vZGUsIHJlbmRlck9wdGlvbnMpO1xuXG4gICAgICAgICAgICAgICAgaWYgKHBhcmVudE5vZGUpIHtcbiAgICAgICAgICAgICAgICAgICAgcGFyZW50Tm9kZS5hcHBlbmRDaGlsZChuZXdOb2RlKTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICByZXR1cm4gcGFyZW50Tm9kZTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZnVuY3Rpb24gc3RyaW5nUGF0Y2goZG9tTm9kZSwgbGVmdFZOb2RlLCB2VGV4dCwgcmVuZGVyT3B0aW9ucykge1xuICAgICAgICAgICAgICAgIHZhciBuZXdOb2RlO1xuXG4gICAgICAgICAgICAgICAgaWYgKGRvbU5vZGUubm9kZVR5cGUgPT09IDMpIHtcbiAgICAgICAgICAgICAgICAgICAgZG9tTm9kZS5yZXBsYWNlRGF0YSgwLCBkb21Ob2RlLmxlbmd0aCwgdlRleHQudGV4dCk7XG4gICAgICAgICAgICAgICAgICAgIG5ld05vZGUgPSBkb21Ob2RlO1xuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciBwYXJlbnROb2RlID0gZG9tTm9kZS5wYXJlbnROb2RlO1xuICAgICAgICAgICAgICAgICAgICBuZXdOb2RlID0gcmVuZGVyT3B0aW9ucy5yZW5kZXIodlRleHQsIHJlbmRlck9wdGlvbnMpO1xuXG4gICAgICAgICAgICAgICAgICAgIGlmIChwYXJlbnROb2RlICYmIG5ld05vZGUgIT09IGRvbU5vZGUpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHBhcmVudE5vZGUucmVwbGFjZUNoaWxkKG5ld05vZGUsIGRvbU5vZGUpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgcmV0dXJuIG5ld05vZGU7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIHdpZGdldFBhdGNoKGRvbU5vZGUsIGxlZnRWTm9kZSwgd2lkZ2V0LCByZW5kZXJPcHRpb25zKSB7XG4gICAgICAgICAgICAgICAgdmFyIHVwZGF0aW5nID0gdXBkYXRlV2lkZ2V0KGxlZnRWTm9kZSwgd2lkZ2V0KTtcbiAgICAgICAgICAgICAgICB2YXIgbmV3Tm9kZTtcblxuICAgICAgICAgICAgICAgIGlmICh1cGRhdGluZykge1xuICAgICAgICAgICAgICAgICAgICBuZXdOb2RlID0gd2lkZ2V0LnVwZGF0ZShsZWZ0Vk5vZGUsIGRvbU5vZGUpIHx8IGRvbU5vZGU7XG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgbmV3Tm9kZSA9IHJlbmRlck9wdGlvbnMucmVuZGVyKHdpZGdldCwgcmVuZGVyT3B0aW9ucyk7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgdmFyIHBhcmVudE5vZGUgPSBkb21Ob2RlLnBhcmVudE5vZGU7XG5cbiAgICAgICAgICAgICAgICBpZiAocGFyZW50Tm9kZSAmJiBuZXdOb2RlICE9PSBkb21Ob2RlKSB7XG4gICAgICAgICAgICAgICAgICAgIHBhcmVudE5vZGUucmVwbGFjZUNoaWxkKG5ld05vZGUsIGRvbU5vZGUpO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIGlmICghdXBkYXRpbmcpIHtcbiAgICAgICAgICAgICAgICAgICAgZGVzdHJveVdpZGdldChkb21Ob2RlLCBsZWZ0Vk5vZGUpO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHJldHVybiBuZXdOb2RlO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBmdW5jdGlvbiB2Tm9kZVBhdGNoKGRvbU5vZGUsIGxlZnRWTm9kZSwgdk5vZGUsIHJlbmRlck9wdGlvbnMpIHtcbiAgICAgICAgICAgICAgICB2YXIgcGFyZW50Tm9kZSA9IGRvbU5vZGUucGFyZW50Tm9kZTtcbiAgICAgICAgICAgICAgICB2YXIgbmV3Tm9kZSA9IHJlbmRlck9wdGlvbnMucmVuZGVyKHZOb2RlLCByZW5kZXJPcHRpb25zKTtcblxuICAgICAgICAgICAgICAgIGlmIChwYXJlbnROb2RlICYmIG5ld05vZGUgIT09IGRvbU5vZGUpIHtcbiAgICAgICAgICAgICAgICAgICAgcGFyZW50Tm9kZS5yZXBsYWNlQ2hpbGQobmV3Tm9kZSwgZG9tTm9kZSk7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgcmV0dXJuIG5ld05vZGU7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIGRlc3Ryb3lXaWRnZXQoZG9tTm9kZSwgdykge1xuICAgICAgICAgICAgICAgIGlmICh0eXBlb2Ygdy5kZXN0cm95ID09PSBcImZ1bmN0aW9uXCIgJiYgaXNXaWRnZXQodykpIHtcbiAgICAgICAgICAgICAgICAgICAgdy5kZXN0cm95KGRvbU5vZGUpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZnVuY3Rpb24gcmVvcmRlckNoaWxkcmVuKGRvbU5vZGUsIG1vdmVzKSB7XG4gICAgICAgICAgICAgICAgdmFyIGNoaWxkTm9kZXMgPSBkb21Ob2RlLmNoaWxkTm9kZXM7XG4gICAgICAgICAgICAgICAgdmFyIGtleU1hcCA9IHt9O1xuICAgICAgICAgICAgICAgIHZhciBub2RlO1xuICAgICAgICAgICAgICAgIHZhciByZW1vdmU7XG4gICAgICAgICAgICAgICAgdmFyIGluc2VydDtcblxuICAgICAgICAgICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgbW92ZXMucmVtb3Zlcy5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgICAgICAgICByZW1vdmUgPSBtb3Zlcy5yZW1vdmVzW2ldO1xuICAgICAgICAgICAgICAgICAgICBub2RlID0gY2hpbGROb2Rlc1tyZW1vdmUuZnJvbV07XG4gICAgICAgICAgICAgICAgICAgIGlmIChyZW1vdmUua2V5KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBrZXlNYXBbcmVtb3ZlLmtleV0gPSBub2RlO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIGRvbU5vZGUucmVtb3ZlQ2hpbGQobm9kZSk7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgdmFyIGxlbmd0aCA9IGNoaWxkTm9kZXMubGVuZ3RoO1xuICAgICAgICAgICAgICAgIGZvciAodmFyIGogPSAwOyBqIDwgbW92ZXMuaW5zZXJ0cy5sZW5ndGg7IGorKykge1xuICAgICAgICAgICAgICAgICAgICBpbnNlcnQgPSBtb3Zlcy5pbnNlcnRzW2pdO1xuICAgICAgICAgICAgICAgICAgICBub2RlID0ga2V5TWFwW2luc2VydC5rZXldO1xuICAgICAgICAgICAgICAgICAgICAvLyB0aGlzIGlzIHRoZSB3ZWlyZGVzdCBidWcgaSd2ZSBldmVyIHNlZW4gaW4gd2Via2l0XG4gICAgICAgICAgICAgICAgICAgIGRvbU5vZGUuaW5zZXJ0QmVmb3JlKG5vZGUsIGluc2VydC50byA+PSBsZW5ndGgrKyA/IG51bGwgOiBjaGlsZE5vZGVzW2luc2VydC50b10pO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZnVuY3Rpb24gcmVwbGFjZVJvb3Qob2xkUm9vdCwgbmV3Um9vdCkge1xuICAgICAgICAgICAgICAgIGlmIChvbGRSb290ICYmIG5ld1Jvb3QgJiYgb2xkUm9vdCAhPT0gbmV3Um9vdCAmJiBvbGRSb290LnBhcmVudE5vZGUpIHtcbiAgICAgICAgICAgICAgICAgICAgb2xkUm9vdC5wYXJlbnROb2RlLnJlcGxhY2VDaGlsZChuZXdSb290LCBvbGRSb290KTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICByZXR1cm4gbmV3Um9vdDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSwgeyBcIi4uL3Zub2RlL2lzLXdpZGdldC5qc1wiOiAyOSwgXCIuLi92bm9kZS92cGF0Y2guanNcIjogMzIsIFwiLi9hcHBseS1wcm9wZXJ0aWVzXCI6IDE0LCBcIi4vdXBkYXRlLXdpZGdldFwiOiAxOSB9XSwgMTg6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICB2YXIgZG9jdW1lbnQgPSByZXF1aXJlKFwiZ2xvYmFsL2RvY3VtZW50XCIpO1xuICAgICAgICAgICAgdmFyIGlzQXJyYXkgPSByZXF1aXJlKFwieC1pcy1hcnJheVwiKTtcblxuICAgICAgICAgICAgdmFyIHJlbmRlciA9IHJlcXVpcmUoXCIuL2NyZWF0ZS1lbGVtZW50XCIpO1xuICAgICAgICAgICAgdmFyIGRvbUluZGV4ID0gcmVxdWlyZShcIi4vZG9tLWluZGV4XCIpO1xuICAgICAgICAgICAgdmFyIHBhdGNoT3AgPSByZXF1aXJlKFwiLi9wYXRjaC1vcFwiKTtcbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gcGF0Y2g7XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIHBhdGNoKHJvb3ROb2RlLCBwYXRjaGVzLCByZW5kZXJPcHRpb25zKSB7XG4gICAgICAgICAgICAgICAgcmVuZGVyT3B0aW9ucyA9IHJlbmRlck9wdGlvbnMgfHwge307XG4gICAgICAgICAgICAgICAgcmVuZGVyT3B0aW9ucy5wYXRjaCA9IHJlbmRlck9wdGlvbnMucGF0Y2ggJiYgcmVuZGVyT3B0aW9ucy5wYXRjaCAhPT0gcGF0Y2ggPyByZW5kZXJPcHRpb25zLnBhdGNoIDogcGF0Y2hSZWN1cnNpdmU7XG4gICAgICAgICAgICAgICAgcmVuZGVyT3B0aW9ucy5yZW5kZXIgPSByZW5kZXJPcHRpb25zLnJlbmRlciB8fCByZW5kZXI7XG5cbiAgICAgICAgICAgICAgICByZXR1cm4gcmVuZGVyT3B0aW9ucy5wYXRjaChyb290Tm9kZSwgcGF0Y2hlcywgcmVuZGVyT3B0aW9ucyk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIHBhdGNoUmVjdXJzaXZlKHJvb3ROb2RlLCBwYXRjaGVzLCByZW5kZXJPcHRpb25zKSB7XG4gICAgICAgICAgICAgICAgdmFyIGluZGljZXMgPSBwYXRjaEluZGljZXMocGF0Y2hlcyk7XG5cbiAgICAgICAgICAgICAgICBpZiAoaW5kaWNlcy5sZW5ndGggPT09IDApIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHJvb3ROb2RlO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHZhciBpbmRleCA9IGRvbUluZGV4KHJvb3ROb2RlLCBwYXRjaGVzLmEsIGluZGljZXMpO1xuICAgICAgICAgICAgICAgIHZhciBvd25lckRvY3VtZW50ID0gcm9vdE5vZGUub3duZXJEb2N1bWVudDtcblxuICAgICAgICAgICAgICAgIGlmICghcmVuZGVyT3B0aW9ucy5kb2N1bWVudCAmJiBvd25lckRvY3VtZW50ICE9PSBkb2N1bWVudCkge1xuICAgICAgICAgICAgICAgICAgICByZW5kZXJPcHRpb25zLmRvY3VtZW50ID0gb3duZXJEb2N1bWVudDtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IGluZGljZXMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgICAgICAgICAgdmFyIG5vZGVJbmRleCA9IGluZGljZXNbaV07XG4gICAgICAgICAgICAgICAgICAgIHJvb3ROb2RlID0gYXBwbHlQYXRjaChyb290Tm9kZSwgaW5kZXhbbm9kZUluZGV4XSwgcGF0Y2hlc1tub2RlSW5kZXhdLCByZW5kZXJPcHRpb25zKTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICByZXR1cm4gcm9vdE5vZGU7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIGFwcGx5UGF0Y2gocm9vdE5vZGUsIGRvbU5vZGUsIHBhdGNoTGlzdCwgcmVuZGVyT3B0aW9ucykge1xuICAgICAgICAgICAgICAgIGlmICghZG9tTm9kZSkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gcm9vdE5vZGU7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgdmFyIG5ld05vZGU7XG5cbiAgICAgICAgICAgICAgICBpZiAoaXNBcnJheShwYXRjaExpc3QpKSB7XG4gICAgICAgICAgICAgICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgcGF0Y2hMaXN0Lmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBuZXdOb2RlID0gcGF0Y2hPcChwYXRjaExpc3RbaV0sIGRvbU5vZGUsIHJlbmRlck9wdGlvbnMpO1xuXG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoZG9tTm9kZSA9PT0gcm9vdE5vZGUpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICByb290Tm9kZSA9IG5ld05vZGU7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICBuZXdOb2RlID0gcGF0Y2hPcChwYXRjaExpc3QsIGRvbU5vZGUsIHJlbmRlck9wdGlvbnMpO1xuXG4gICAgICAgICAgICAgICAgICAgIGlmIChkb21Ob2RlID09PSByb290Tm9kZSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgcm9vdE5vZGUgPSBuZXdOb2RlO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgcmV0dXJuIHJvb3ROb2RlO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBmdW5jdGlvbiBwYXRjaEluZGljZXMocGF0Y2hlcykge1xuICAgICAgICAgICAgICAgIHZhciBpbmRpY2VzID0gW107XG5cbiAgICAgICAgICAgICAgICBmb3IgKHZhciBrZXkgaW4gcGF0Y2hlcykge1xuICAgICAgICAgICAgICAgICAgICBpZiAoa2V5ICE9PSBcImFcIikge1xuICAgICAgICAgICAgICAgICAgICAgICAgaW5kaWNlcy5wdXNoKE51bWJlcihrZXkpKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHJldHVybiBpbmRpY2VzO1xuICAgICAgICAgICAgfVxuICAgICAgICB9LCB7IFwiLi9jcmVhdGUtZWxlbWVudFwiOiAxNSwgXCIuL2RvbS1pbmRleFwiOiAxNiwgXCIuL3BhdGNoLW9wXCI6IDE3LCBcImdsb2JhbC9kb2N1bWVudFwiOiAxMCwgXCJ4LWlzLWFycmF5XCI6IDEyIH1dLCAxOTogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHtcbiAgICAgICAgICAgIHZhciBpc1dpZGdldCA9IHJlcXVpcmUoXCIuLi92bm9kZS9pcy13aWRnZXQuanNcIik7XG5cbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gdXBkYXRlV2lkZ2V0O1xuXG4gICAgICAgICAgICBmdW5jdGlvbiB1cGRhdGVXaWRnZXQoYSwgYikge1xuICAgICAgICAgICAgICAgIGlmIChpc1dpZGdldChhKSAmJiBpc1dpZGdldChiKSkge1xuICAgICAgICAgICAgICAgICAgICBpZiAoXCJuYW1lXCIgaW4gYSAmJiBcIm5hbWVcIiBpbiBiKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gYS5pZCA9PT0gYi5pZDtcbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBhLmluaXQgPT09IGIuaW5pdDtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSwgeyBcIi4uL3Zub2RlL2lzLXdpZGdldC5qc1wiOiAyOSB9XSwgMjA6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICBcInVzZSBzdHJpY3RcIjtcblxuICAgICAgICAgICAgdmFyIEV2U3RvcmUgPSByZXF1aXJlKFwiZXYtc3RvcmVcIik7XG5cbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gRXZIb29rO1xuXG4gICAgICAgICAgICBmdW5jdGlvbiBFdkhvb2sodmFsdWUpIHtcbiAgICAgICAgICAgICAgICBpZiAoISh0aGlzIGluc3RhbmNlb2YgRXZIb29rKSkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gbmV3IEV2SG9vayh2YWx1ZSk7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgdGhpcy52YWx1ZSA9IHZhbHVlO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBFdkhvb2sucHJvdG90eXBlLmhvb2sgPSBmdW5jdGlvbiAobm9kZSwgcHJvcGVydHlOYW1lKSB7XG4gICAgICAgICAgICAgICAgdmFyIGVzID0gRXZTdG9yZShub2RlKTtcbiAgICAgICAgICAgICAgICB2YXIgcHJvcE5hbWUgPSBwcm9wZXJ0eU5hbWUuc3Vic3RyKDMpO1xuXG4gICAgICAgICAgICAgICAgZXNbcHJvcE5hbWVdID0gdGhpcy52YWx1ZTtcbiAgICAgICAgICAgIH07XG5cbiAgICAgICAgICAgIEV2SG9vay5wcm90b3R5cGUudW5ob29rID0gZnVuY3Rpb24gKG5vZGUsIHByb3BlcnR5TmFtZSkge1xuICAgICAgICAgICAgICAgIHZhciBlcyA9IEV2U3RvcmUobm9kZSk7XG4gICAgICAgICAgICAgICAgdmFyIHByb3BOYW1lID0gcHJvcGVydHlOYW1lLnN1YnN0cigzKTtcblxuICAgICAgICAgICAgICAgIGVzW3Byb3BOYW1lXSA9IHVuZGVmaW5lZDtcbiAgICAgICAgICAgIH07XG4gICAgICAgIH0sIHsgXCJldi1zdG9yZVwiOiA3IH1dLCAyMTogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHtcbiAgICAgICAgICAgIFwidXNlIHN0cmljdFwiO1xuXG4gICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IFNvZnRTZXRIb29rO1xuXG4gICAgICAgICAgICBmdW5jdGlvbiBTb2Z0U2V0SG9vayh2YWx1ZSkge1xuICAgICAgICAgICAgICAgIGlmICghKHRoaXMgaW5zdGFuY2VvZiBTb2Z0U2V0SG9vaykpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIG5ldyBTb2Z0U2V0SG9vayh2YWx1ZSk7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgdGhpcy52YWx1ZSA9IHZhbHVlO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBTb2Z0U2V0SG9vay5wcm90b3R5cGUuaG9vayA9IGZ1bmN0aW9uIChub2RlLCBwcm9wZXJ0eU5hbWUpIHtcbiAgICAgICAgICAgICAgICBpZiAobm9kZVtwcm9wZXJ0eU5hbWVdICE9PSB0aGlzLnZhbHVlKSB7XG4gICAgICAgICAgICAgICAgICAgIG5vZGVbcHJvcGVydHlOYW1lXSA9IHRoaXMudmFsdWU7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfTtcbiAgICAgICAgfSwge31dLCAyMjogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHtcbiAgICAgICAgICAgIFwidXNlIHN0cmljdFwiO1xuXG4gICAgICAgICAgICB2YXIgaXNBcnJheSA9IHJlcXVpcmUoXCJ4LWlzLWFycmF5XCIpO1xuXG4gICAgICAgICAgICB2YXIgVk5vZGUgPSByZXF1aXJlKFwiLi4vdm5vZGUvdm5vZGUuanNcIik7XG4gICAgICAgICAgICB2YXIgVlRleHQgPSByZXF1aXJlKFwiLi4vdm5vZGUvdnRleHQuanNcIik7XG4gICAgICAgICAgICB2YXIgaXNWTm9kZSA9IHJlcXVpcmUoXCIuLi92bm9kZS9pcy12bm9kZVwiKTtcbiAgICAgICAgICAgIHZhciBpc1ZUZXh0ID0gcmVxdWlyZShcIi4uL3Zub2RlL2lzLXZ0ZXh0XCIpO1xuICAgICAgICAgICAgdmFyIGlzV2lkZ2V0ID0gcmVxdWlyZShcIi4uL3Zub2RlL2lzLXdpZGdldFwiKTtcbiAgICAgICAgICAgIHZhciBpc0hvb2sgPSByZXF1aXJlKFwiLi4vdm5vZGUvaXMtdmhvb2tcIik7XG4gICAgICAgICAgICB2YXIgaXNWVGh1bmsgPSByZXF1aXJlKFwiLi4vdm5vZGUvaXMtdGh1bmtcIik7XG5cbiAgICAgICAgICAgIHZhciBwYXJzZVRhZyA9IHJlcXVpcmUoXCIuL3BhcnNlLXRhZy5qc1wiKTtcbiAgICAgICAgICAgIHZhciBzb2Z0U2V0SG9vayA9IHJlcXVpcmUoXCIuL2hvb2tzL3NvZnQtc2V0LWhvb2suanNcIik7XG4gICAgICAgICAgICB2YXIgZXZIb29rID0gcmVxdWlyZShcIi4vaG9va3MvZXYtaG9vay5qc1wiKTtcblxuICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBoO1xuXG4gICAgICAgICAgICBmdW5jdGlvbiBoKHRhZ05hbWUsIHByb3BlcnRpZXMsIGNoaWxkcmVuKSB7XG4gICAgICAgICAgICAgICAgdmFyIGNoaWxkTm9kZXMgPSBbXTtcbiAgICAgICAgICAgICAgICB2YXIgdGFnLCBwcm9wcywga2V5LCBuYW1lc3BhY2U7XG5cbiAgICAgICAgICAgICAgICBpZiAoIWNoaWxkcmVuICYmIGlzQ2hpbGRyZW4ocHJvcGVydGllcykpIHtcbiAgICAgICAgICAgICAgICAgICAgY2hpbGRyZW4gPSBwcm9wZXJ0aWVzO1xuICAgICAgICAgICAgICAgICAgICBwcm9wcyA9IHt9O1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHByb3BzID0gcHJvcHMgfHwgcHJvcGVydGllcyB8fCB7fTtcbiAgICAgICAgICAgICAgICB0YWcgPSBwYXJzZVRhZyh0YWdOYW1lLCBwcm9wcyk7XG5cbiAgICAgICAgICAgICAgICAvLyBzdXBwb3J0IGtleXNcbiAgICAgICAgICAgICAgICBpZiAocHJvcHMuaGFzT3duUHJvcGVydHkoXCJrZXlcIikpIHtcbiAgICAgICAgICAgICAgICAgICAga2V5ID0gcHJvcHMua2V5O1xuICAgICAgICAgICAgICAgICAgICBwcm9wcy5rZXkgPSB1bmRlZmluZWQ7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgLy8gc3VwcG9ydCBuYW1lc3BhY2VcbiAgICAgICAgICAgICAgICBpZiAocHJvcHMuaGFzT3duUHJvcGVydHkoXCJuYW1lc3BhY2VcIikpIHtcbiAgICAgICAgICAgICAgICAgICAgbmFtZXNwYWNlID0gcHJvcHMubmFtZXNwYWNlO1xuICAgICAgICAgICAgICAgICAgICBwcm9wcy5uYW1lc3BhY2UgPSB1bmRlZmluZWQ7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgLy8gZml4IGN1cnNvciBidWdcbiAgICAgICAgICAgICAgICBpZiAodGFnID09PSBcIklOUFVUXCIgJiYgIW5hbWVzcGFjZSAmJiBwcm9wcy5oYXNPd25Qcm9wZXJ0eShcInZhbHVlXCIpICYmIHByb3BzLnZhbHVlICE9PSB1bmRlZmluZWQgJiYgIWlzSG9vayhwcm9wcy52YWx1ZSkpIHtcbiAgICAgICAgICAgICAgICAgICAgcHJvcHMudmFsdWUgPSBzb2Z0U2V0SG9vayhwcm9wcy52YWx1ZSk7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgdHJhbnNmb3JtUHJvcGVydGllcyhwcm9wcyk7XG5cbiAgICAgICAgICAgICAgICBpZiAoY2hpbGRyZW4gIT09IHVuZGVmaW5lZCAmJiBjaGlsZHJlbiAhPT0gbnVsbCkge1xuICAgICAgICAgICAgICAgICAgICBhZGRDaGlsZChjaGlsZHJlbiwgY2hpbGROb2RlcywgdGFnLCBwcm9wcyk7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgcmV0dXJuIG5ldyBWTm9kZSh0YWcsIHByb3BzLCBjaGlsZE5vZGVzLCBrZXksIG5hbWVzcGFjZSk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIGFkZENoaWxkKGMsIGNoaWxkTm9kZXMsIHRhZywgcHJvcHMpIHtcbiAgICAgICAgICAgICAgICBpZiAodHlwZW9mIGMgPT09IFwic3RyaW5nXCIpIHtcbiAgICAgICAgICAgICAgICAgICAgY2hpbGROb2Rlcy5wdXNoKG5ldyBWVGV4dChjKSk7XG4gICAgICAgICAgICAgICAgfSBlbHNlIGlmICh0eXBlb2YgYyA9PT0gXCJudW1iZXJcIikge1xuICAgICAgICAgICAgICAgICAgICBjaGlsZE5vZGVzLnB1c2gobmV3IFZUZXh0KFN0cmluZyhjKSkpO1xuICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoaXNDaGlsZChjKSkge1xuICAgICAgICAgICAgICAgICAgICBjaGlsZE5vZGVzLnB1c2goYyk7XG4gICAgICAgICAgICAgICAgfSBlbHNlIGlmIChpc0FycmF5KGMpKSB7XG4gICAgICAgICAgICAgICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgYy5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgICAgICAgICAgICAgYWRkQ2hpbGQoY1tpXSwgY2hpbGROb2RlcywgdGFnLCBwcm9wcyk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKGMgPT09IG51bGwgfHwgYyA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICB0aHJvdyBVbmV4cGVjdGVkVmlydHVhbEVsZW1lbnQoe1xuICAgICAgICAgICAgICAgICAgICAgICAgZm9yZWlnbk9iamVjdDogYyxcbiAgICAgICAgICAgICAgICAgICAgICAgIHBhcmVudFZub2RlOiB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdGFnTmFtZTogdGFnLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHByb3BlcnRpZXM6IHByb3BzXG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZnVuY3Rpb24gdHJhbnNmb3JtUHJvcGVydGllcyhwcm9wcykge1xuICAgICAgICAgICAgICAgIGZvciAodmFyIHByb3BOYW1lIGluIHByb3BzKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmIChwcm9wcy5oYXNPd25Qcm9wZXJ0eShwcm9wTmFtZSkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHZhciB2YWx1ZSA9IHByb3BzW3Byb3BOYW1lXTtcblxuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGlzSG9vayh2YWx1ZSkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb250aW51ZTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHByb3BOYW1lLnN1YnN0cigwLCAzKSA9PT0gXCJldi1cIikge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIGFkZCBldi1mb28gc3VwcG9ydFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHByb3BzW3Byb3BOYW1lXSA9IGV2SG9vayh2YWx1ZSk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIGlzQ2hpbGQoeCkge1xuICAgICAgICAgICAgICAgIHJldHVybiBpc1ZOb2RlKHgpIHx8IGlzVlRleHQoeCkgfHwgaXNXaWRnZXQoeCkgfHwgaXNWVGh1bmsoeCk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIGlzQ2hpbGRyZW4oeCkge1xuICAgICAgICAgICAgICAgIHJldHVybiB0eXBlb2YgeCA9PT0gXCJzdHJpbmdcIiB8fCBpc0FycmF5KHgpIHx8IGlzQ2hpbGQoeCk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIFVuZXhwZWN0ZWRWaXJ0dWFsRWxlbWVudChkYXRhKSB7XG4gICAgICAgICAgICAgICAgdmFyIGVyciA9IG5ldyBFcnJvcigpO1xuXG4gICAgICAgICAgICAgICAgZXJyLnR5cGUgPSBcInZpcnR1YWwtaHlwZXJzY3JpcHQudW5leHBlY3RlZC52aXJ0dWFsLWVsZW1lbnRcIjtcbiAgICAgICAgICAgICAgICBlcnIubWVzc2FnZSA9IFwiVW5leHBlY3RlZCB2aXJ0dWFsIGNoaWxkIHBhc3NlZCB0byBoKCkuXFxuXCIgKyBcIkV4cGVjdGVkIGEgVk5vZGUgLyBWdGh1bmsgLyBWV2lkZ2V0IC8gc3RyaW5nIGJ1dDpcXG5cIiArIFwiZ290OlxcblwiICsgZXJyb3JTdHJpbmcoZGF0YS5mb3JlaWduT2JqZWN0KSArIFwiLlxcblwiICsgXCJUaGUgcGFyZW50IHZub2RlIGlzOlxcblwiICsgZXJyb3JTdHJpbmcoZGF0YS5wYXJlbnRWbm9kZSk7XG4gICAgICAgICAgICAgICAgXCJcXG5cIiArIFwiU3VnZ2VzdGVkIGZpeDogY2hhbmdlIHlvdXIgYGgoLi4uLCBbIC4uLiBdKWAgY2FsbHNpdGUuXCI7XG4gICAgICAgICAgICAgICAgZXJyLmZvcmVpZ25PYmplY3QgPSBkYXRhLmZvcmVpZ25PYmplY3Q7XG4gICAgICAgICAgICAgICAgZXJyLnBhcmVudFZub2RlID0gZGF0YS5wYXJlbnRWbm9kZTtcblxuICAgICAgICAgICAgICAgIHJldHVybiBlcnI7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIGVycm9yU3RyaW5nKG9iaikge1xuICAgICAgICAgICAgICAgIHRyeSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBKU09OLnN0cmluZ2lmeShvYmosIG51bGwsIFwiICAgIFwiKTtcbiAgICAgICAgICAgICAgICB9IGNhdGNoIChlKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBTdHJpbmcob2JqKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH0sIHsgXCIuLi92bm9kZS9pcy10aHVua1wiOiAyNSwgXCIuLi92bm9kZS9pcy12aG9va1wiOiAyNiwgXCIuLi92bm9kZS9pcy12bm9kZVwiOiAyNywgXCIuLi92bm9kZS9pcy12dGV4dFwiOiAyOCwgXCIuLi92bm9kZS9pcy13aWRnZXRcIjogMjksIFwiLi4vdm5vZGUvdm5vZGUuanNcIjogMzEsIFwiLi4vdm5vZGUvdnRleHQuanNcIjogMzMsIFwiLi9ob29rcy9ldi1ob29rLmpzXCI6IDIwLCBcIi4vaG9va3Mvc29mdC1zZXQtaG9vay5qc1wiOiAyMSwgXCIuL3BhcnNlLXRhZy5qc1wiOiAyMywgXCJ4LWlzLWFycmF5XCI6IDEyIH1dLCAyMzogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHtcbiAgICAgICAgICAgIFwidXNlIHN0cmljdFwiO1xuXG4gICAgICAgICAgICB2YXIgc3BsaXQgPSByZXF1aXJlKFwiYnJvd3Nlci1zcGxpdFwiKTtcblxuICAgICAgICAgICAgdmFyIGNsYXNzSWRTcGxpdCA9IC8oW1xcLiNdP1thLXpBLVowLTlcXHUwMDdGLVxcdUZGRkZfOi1dKykvO1xuICAgICAgICAgICAgdmFyIG5vdENsYXNzSWQgPSAvXlxcLnwjLztcblxuICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBwYXJzZVRhZztcblxuICAgICAgICAgICAgZnVuY3Rpb24gcGFyc2VUYWcodGFnLCBwcm9wcykge1xuICAgICAgICAgICAgICAgIGlmICghdGFnKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBcIkRJVlwiO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHZhciBub0lkID0gIXByb3BzLmhhc093blByb3BlcnR5KFwiaWRcIik7XG5cbiAgICAgICAgICAgICAgICB2YXIgdGFnUGFydHMgPSBzcGxpdCh0YWcsIGNsYXNzSWRTcGxpdCk7XG4gICAgICAgICAgICAgICAgdmFyIHRhZ05hbWUgPSBudWxsO1xuXG4gICAgICAgICAgICAgICAgaWYgKG5vdENsYXNzSWQudGVzdCh0YWdQYXJ0c1sxXSkpIHtcbiAgICAgICAgICAgICAgICAgICAgdGFnTmFtZSA9IFwiRElWXCI7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgdmFyIGNsYXNzZXMsIHBhcnQsIHR5cGUsIGk7XG5cbiAgICAgICAgICAgICAgICBmb3IgKGkgPSAwOyBpIDwgdGFnUGFydHMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgICAgICAgICAgcGFydCA9IHRhZ1BhcnRzW2ldO1xuXG4gICAgICAgICAgICAgICAgICAgIGlmICghcGFydCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgY29udGludWU7XG4gICAgICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgICAgICB0eXBlID0gcGFydC5jaGFyQXQoMCk7XG5cbiAgICAgICAgICAgICAgICAgICAgaWYgKCF0YWdOYW1lKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICB0YWdOYW1lID0gcGFydDtcbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIGlmICh0eXBlID09PSBcIi5cIikge1xuICAgICAgICAgICAgICAgICAgICAgICAgY2xhc3NlcyA9IGNsYXNzZXMgfHwgW107XG4gICAgICAgICAgICAgICAgICAgICAgICBjbGFzc2VzLnB1c2gocGFydC5zdWJzdHJpbmcoMSwgcGFydC5sZW5ndGgpKTtcbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIGlmICh0eXBlID09PSBcIiNcIiAmJiBub0lkKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBwcm9wcy5pZCA9IHBhcnQuc3Vic3RyaW5nKDEsIHBhcnQubGVuZ3RoKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIGlmIChjbGFzc2VzKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmIChwcm9wcy5jbGFzc05hbWUpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGNsYXNzZXMucHVzaChwcm9wcy5jbGFzc05hbWUpO1xuICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgcHJvcHMuY2xhc3NOYW1lID0gY2xhc3Nlcy5qb2luKFwiIFwiKTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICByZXR1cm4gcHJvcHMubmFtZXNwYWNlID8gdGFnTmFtZSA6IHRhZ05hbWUudG9VcHBlckNhc2UoKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSwgeyBcImJyb3dzZXItc3BsaXRcIjogNSB9XSwgMjQ6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICB2YXIgaXNWTm9kZSA9IHJlcXVpcmUoXCIuL2lzLXZub2RlXCIpO1xuICAgICAgICAgICAgdmFyIGlzVlRleHQgPSByZXF1aXJlKFwiLi9pcy12dGV4dFwiKTtcbiAgICAgICAgICAgIHZhciBpc1dpZGdldCA9IHJlcXVpcmUoXCIuL2lzLXdpZGdldFwiKTtcbiAgICAgICAgICAgIHZhciBpc1RodW5rID0gcmVxdWlyZShcIi4vaXMtdGh1bmtcIik7XG5cbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gaGFuZGxlVGh1bms7XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIGhhbmRsZVRodW5rKGEsIGIpIHtcbiAgICAgICAgICAgICAgICB2YXIgcmVuZGVyZWRBID0gYTtcbiAgICAgICAgICAgICAgICB2YXIgcmVuZGVyZWRCID0gYjtcblxuICAgICAgICAgICAgICAgIGlmIChpc1RodW5rKGIpKSB7XG4gICAgICAgICAgICAgICAgICAgIHJlbmRlcmVkQiA9IHJlbmRlclRodW5rKGIsIGEpO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIGlmIChpc1RodW5rKGEpKSB7XG4gICAgICAgICAgICAgICAgICAgIHJlbmRlcmVkQSA9IHJlbmRlclRodW5rKGEsIG51bGwpO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHJldHVybiB7XG4gICAgICAgICAgICAgICAgICAgIGE6IHJlbmRlcmVkQSxcbiAgICAgICAgICAgICAgICAgICAgYjogcmVuZGVyZWRCXG4gICAgICAgICAgICAgICAgfTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZnVuY3Rpb24gcmVuZGVyVGh1bmsodGh1bmssIHByZXZpb3VzKSB7XG4gICAgICAgICAgICAgICAgdmFyIHJlbmRlcmVkVGh1bmsgPSB0aHVuay52bm9kZTtcblxuICAgICAgICAgICAgICAgIGlmICghcmVuZGVyZWRUaHVuaykge1xuICAgICAgICAgICAgICAgICAgICByZW5kZXJlZFRodW5rID0gdGh1bmsudm5vZGUgPSB0aHVuay5yZW5kZXIocHJldmlvdXMpO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIGlmICghKGlzVk5vZGUocmVuZGVyZWRUaHVuaykgfHwgaXNWVGV4dChyZW5kZXJlZFRodW5rKSB8fCBpc1dpZGdldChyZW5kZXJlZFRodW5rKSkpIHtcbiAgICAgICAgICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKFwidGh1bmsgZGlkIG5vdCByZXR1cm4gYSB2YWxpZCBub2RlXCIpO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHJldHVybiByZW5kZXJlZFRodW5rO1xuICAgICAgICAgICAgfVxuICAgICAgICB9LCB7IFwiLi9pcy10aHVua1wiOiAyNSwgXCIuL2lzLXZub2RlXCI6IDI3LCBcIi4vaXMtdnRleHRcIjogMjgsIFwiLi9pcy13aWRnZXRcIjogMjkgfV0sIDI1OiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge1xuICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBpc1RodW5rO1xuXG4gICAgICAgICAgICBmdW5jdGlvbiBpc1RodW5rKHQpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gdCAmJiB0LnR5cGUgPT09IFwiVGh1bmtcIjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSwge31dLCAyNjogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHtcbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gaXNIb29rO1xuXG4gICAgICAgICAgICBmdW5jdGlvbiBpc0hvb2soaG9vaykge1xuICAgICAgICAgICAgICAgIHJldHVybiBob29rICYmICh0eXBlb2YgaG9vay5ob29rID09PSBcImZ1bmN0aW9uXCIgJiYgIWhvb2suaGFzT3duUHJvcGVydHkoXCJob29rXCIpIHx8IHR5cGVvZiBob29rLnVuaG9vayA9PT0gXCJmdW5jdGlvblwiICYmICFob29rLmhhc093blByb3BlcnR5KFwidW5ob29rXCIpKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSwge31dLCAyNzogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHtcbiAgICAgICAgICAgIHZhciB2ZXJzaW9uID0gcmVxdWlyZShcIi4vdmVyc2lvblwiKTtcblxuICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBpc1ZpcnR1YWxOb2RlO1xuXG4gICAgICAgICAgICBmdW5jdGlvbiBpc1ZpcnR1YWxOb2RlKHgpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4geCAmJiB4LnR5cGUgPT09IFwiVmlydHVhbE5vZGVcIiAmJiB4LnZlcnNpb24gPT09IHZlcnNpb247XG4gICAgICAgICAgICB9XG4gICAgICAgIH0sIHsgXCIuL3ZlcnNpb25cIjogMzAgfV0sIDI4OiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge1xuICAgICAgICAgICAgdmFyIHZlcnNpb24gPSByZXF1aXJlKFwiLi92ZXJzaW9uXCIpO1xuXG4gICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IGlzVmlydHVhbFRleHQ7XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIGlzVmlydHVhbFRleHQoeCkge1xuICAgICAgICAgICAgICAgIHJldHVybiB4ICYmIHgudHlwZSA9PT0gXCJWaXJ0dWFsVGV4dFwiICYmIHgudmVyc2lvbiA9PT0gdmVyc2lvbjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSwgeyBcIi4vdmVyc2lvblwiOiAzMCB9XSwgMjk6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IGlzV2lkZ2V0O1xuXG4gICAgICAgICAgICBmdW5jdGlvbiBpc1dpZGdldCh3KSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHcgJiYgdy50eXBlID09PSBcIldpZGdldFwiO1xuICAgICAgICAgICAgfVxuICAgICAgICB9LCB7fV0sIDMwOiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge1xuICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBcIjJcIjtcbiAgICAgICAgfSwge31dLCAzMTogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHtcbiAgICAgICAgICAgIHZhciB2ZXJzaW9uID0gcmVxdWlyZShcIi4vdmVyc2lvblwiKTtcbiAgICAgICAgICAgIHZhciBpc1ZOb2RlID0gcmVxdWlyZShcIi4vaXMtdm5vZGVcIik7XG4gICAgICAgICAgICB2YXIgaXNXaWRnZXQgPSByZXF1aXJlKFwiLi9pcy13aWRnZXRcIik7XG4gICAgICAgICAgICB2YXIgaXNUaHVuayA9IHJlcXVpcmUoXCIuL2lzLXRodW5rXCIpO1xuICAgICAgICAgICAgdmFyIGlzVkhvb2sgPSByZXF1aXJlKFwiLi9pcy12aG9va1wiKTtcblxuICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBWaXJ0dWFsTm9kZTtcblxuICAgICAgICAgICAgdmFyIG5vUHJvcGVydGllcyA9IHt9O1xuICAgICAgICAgICAgdmFyIG5vQ2hpbGRyZW4gPSBbXTtcblxuICAgICAgICAgICAgZnVuY3Rpb24gVmlydHVhbE5vZGUodGFnTmFtZSwgcHJvcGVydGllcywgY2hpbGRyZW4sIGtleSwgbmFtZXNwYWNlKSB7XG4gICAgICAgICAgICAgICAgdGhpcy50YWdOYW1lID0gdGFnTmFtZTtcbiAgICAgICAgICAgICAgICB0aGlzLnByb3BlcnRpZXMgPSBwcm9wZXJ0aWVzIHx8IG5vUHJvcGVydGllcztcbiAgICAgICAgICAgICAgICB0aGlzLmNoaWxkcmVuID0gY2hpbGRyZW4gfHwgbm9DaGlsZHJlbjtcbiAgICAgICAgICAgICAgICB0aGlzLmtleSA9IGtleSAhPSBudWxsID8gU3RyaW5nKGtleSkgOiB1bmRlZmluZWQ7XG4gICAgICAgICAgICAgICAgdGhpcy5uYW1lc3BhY2UgPSB0eXBlb2YgbmFtZXNwYWNlID09PSBcInN0cmluZ1wiID8gbmFtZXNwYWNlIDogbnVsbDtcblxuICAgICAgICAgICAgICAgIHZhciBjb3VudCA9IGNoaWxkcmVuICYmIGNoaWxkcmVuLmxlbmd0aCB8fCAwO1xuICAgICAgICAgICAgICAgIHZhciBkZXNjZW5kYW50cyA9IDA7XG4gICAgICAgICAgICAgICAgdmFyIGhhc1dpZGdldHMgPSBmYWxzZTtcbiAgICAgICAgICAgICAgICB2YXIgaGFzVGh1bmtzID0gZmFsc2U7XG4gICAgICAgICAgICAgICAgdmFyIGRlc2NlbmRhbnRIb29rcyA9IGZhbHNlO1xuICAgICAgICAgICAgICAgIHZhciBob29rcztcblxuICAgICAgICAgICAgICAgIGZvciAodmFyIHByb3BOYW1lIGluIHByb3BlcnRpZXMpIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKHByb3BlcnRpZXMuaGFzT3duUHJvcGVydHkocHJvcE5hbWUpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICB2YXIgcHJvcGVydHkgPSBwcm9wZXJ0aWVzW3Byb3BOYW1lXTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChpc1ZIb29rKHByb3BlcnR5KSAmJiBwcm9wZXJ0eS51bmhvb2spIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoIWhvb2tzKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGhvb2tzID0ge307XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaG9va3NbcHJvcE5hbWVdID0gcHJvcGVydHk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IGNvdW50OyBpKyspIHtcbiAgICAgICAgICAgICAgICAgICAgdmFyIGNoaWxkID0gY2hpbGRyZW5baV07XG4gICAgICAgICAgICAgICAgICAgIGlmIChpc1ZOb2RlKGNoaWxkKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgZGVzY2VuZGFudHMgKz0gY2hpbGQuY291bnQgfHwgMDtcblxuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKCFoYXNXaWRnZXRzICYmIGNoaWxkLmhhc1dpZGdldHMpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBoYXNXaWRnZXRzID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKCFoYXNUaHVua3MgJiYgY2hpbGQuaGFzVGh1bmtzKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaGFzVGh1bmtzID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKCFkZXNjZW5kYW50SG9va3MgJiYgKGNoaWxkLmhvb2tzIHx8IGNoaWxkLmRlc2NlbmRhbnRIb29rcykpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBkZXNjZW5kYW50SG9va3MgPSB0cnVlO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKCFoYXNXaWRnZXRzICYmIGlzV2lkZ2V0KGNoaWxkKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHR5cGVvZiBjaGlsZC5kZXN0cm95ID09PSBcImZ1bmN0aW9uXCIpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBoYXNXaWRnZXRzID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIGlmICghaGFzVGh1bmtzICYmIGlzVGh1bmsoY2hpbGQpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBoYXNUaHVua3MgPSB0cnVlO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgdGhpcy5jb3VudCA9IGNvdW50ICsgZGVzY2VuZGFudHM7XG4gICAgICAgICAgICAgICAgdGhpcy5oYXNXaWRnZXRzID0gaGFzV2lkZ2V0cztcbiAgICAgICAgICAgICAgICB0aGlzLmhhc1RodW5rcyA9IGhhc1RodW5rcztcbiAgICAgICAgICAgICAgICB0aGlzLmhvb2tzID0gaG9va3M7XG4gICAgICAgICAgICAgICAgdGhpcy5kZXNjZW5kYW50SG9va3MgPSBkZXNjZW5kYW50SG9va3M7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIFZpcnR1YWxOb2RlLnByb3RvdHlwZS52ZXJzaW9uID0gdmVyc2lvbjtcbiAgICAgICAgICAgIFZpcnR1YWxOb2RlLnByb3RvdHlwZS50eXBlID0gXCJWaXJ0dWFsTm9kZVwiO1xuICAgICAgICB9LCB7IFwiLi9pcy10aHVua1wiOiAyNSwgXCIuL2lzLXZob29rXCI6IDI2LCBcIi4vaXMtdm5vZGVcIjogMjcsIFwiLi9pcy13aWRnZXRcIjogMjksIFwiLi92ZXJzaW9uXCI6IDMwIH1dLCAzMjogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHtcbiAgICAgICAgICAgIHZhciB2ZXJzaW9uID0gcmVxdWlyZShcIi4vdmVyc2lvblwiKTtcblxuICAgICAgICAgICAgVmlydHVhbFBhdGNoLk5PTkUgPSAwO1xuICAgICAgICAgICAgVmlydHVhbFBhdGNoLlZURVhUID0gMTtcbiAgICAgICAgICAgIFZpcnR1YWxQYXRjaC5WTk9ERSA9IDI7XG4gICAgICAgICAgICBWaXJ0dWFsUGF0Y2guV0lER0VUID0gMztcbiAgICAgICAgICAgIFZpcnR1YWxQYXRjaC5QUk9QUyA9IDQ7XG4gICAgICAgICAgICBWaXJ0dWFsUGF0Y2guT1JERVIgPSA1O1xuICAgICAgICAgICAgVmlydHVhbFBhdGNoLklOU0VSVCA9IDY7XG4gICAgICAgICAgICBWaXJ0dWFsUGF0Y2guUkVNT1ZFID0gNztcbiAgICAgICAgICAgIFZpcnR1YWxQYXRjaC5USFVOSyA9IDg7XG5cbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gVmlydHVhbFBhdGNoO1xuXG4gICAgICAgICAgICBmdW5jdGlvbiBWaXJ0dWFsUGF0Y2godHlwZSwgdk5vZGUsIHBhdGNoKSB7XG4gICAgICAgICAgICAgICAgdGhpcy50eXBlID0gTnVtYmVyKHR5cGUpO1xuICAgICAgICAgICAgICAgIHRoaXMudk5vZGUgPSB2Tm9kZTtcbiAgICAgICAgICAgICAgICB0aGlzLnBhdGNoID0gcGF0Y2g7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIFZpcnR1YWxQYXRjaC5wcm90b3R5cGUudmVyc2lvbiA9IHZlcnNpb247XG4gICAgICAgICAgICBWaXJ0dWFsUGF0Y2gucHJvdG90eXBlLnR5cGUgPSBcIlZpcnR1YWxQYXRjaFwiO1xuICAgICAgICB9LCB7IFwiLi92ZXJzaW9uXCI6IDMwIH1dLCAzMzogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHtcbiAgICAgICAgICAgIHZhciB2ZXJzaW9uID0gcmVxdWlyZShcIi4vdmVyc2lvblwiKTtcblxuICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBWaXJ0dWFsVGV4dDtcblxuICAgICAgICAgICAgZnVuY3Rpb24gVmlydHVhbFRleHQodGV4dCkge1xuICAgICAgICAgICAgICAgIHRoaXMudGV4dCA9IFN0cmluZyh0ZXh0KTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgVmlydHVhbFRleHQucHJvdG90eXBlLnZlcnNpb24gPSB2ZXJzaW9uO1xuICAgICAgICAgICAgVmlydHVhbFRleHQucHJvdG90eXBlLnR5cGUgPSBcIlZpcnR1YWxUZXh0XCI7XG4gICAgICAgIH0sIHsgXCIuL3ZlcnNpb25cIjogMzAgfV0sIDM0OiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge1xuICAgICAgICAgICAgdmFyIGlzT2JqZWN0ID0gcmVxdWlyZShcImlzLW9iamVjdFwiKTtcbiAgICAgICAgICAgIHZhciBpc0hvb2sgPSByZXF1aXJlKFwiLi4vdm5vZGUvaXMtdmhvb2tcIik7XG5cbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gZGlmZlByb3BzO1xuXG4gICAgICAgICAgICBmdW5jdGlvbiBkaWZmUHJvcHMoYSwgYikge1xuICAgICAgICAgICAgICAgIHZhciBkaWZmO1xuXG4gICAgICAgICAgICAgICAgZm9yICh2YXIgYUtleSBpbiBhKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmICghKGFLZXkgaW4gYikpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGRpZmYgPSBkaWZmIHx8IHt9O1xuICAgICAgICAgICAgICAgICAgICAgICAgZGlmZlthS2V5XSA9IHVuZGVmaW5lZDtcbiAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgIHZhciBhVmFsdWUgPSBhW2FLZXldO1xuICAgICAgICAgICAgICAgICAgICB2YXIgYlZhbHVlID0gYlthS2V5XTtcblxuICAgICAgICAgICAgICAgICAgICBpZiAoYVZhbHVlID09PSBiVmFsdWUpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnRpbnVlO1xuICAgICAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKGlzT2JqZWN0KGFWYWx1ZSkgJiYgaXNPYmplY3QoYlZhbHVlKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGdldFByb3RvdHlwZShiVmFsdWUpICE9PSBnZXRQcm90b3R5cGUoYVZhbHVlKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRpZmYgPSBkaWZmIHx8IHt9O1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRpZmZbYUtleV0gPSBiVmFsdWU7XG4gICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKGlzSG9vayhiVmFsdWUpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgZGlmZiA9IGRpZmYgfHwge307XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgZGlmZlthS2V5XSA9IGJWYWx1ZTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdmFyIG9iamVjdERpZmYgPSBkaWZmUHJvcHMoYVZhbHVlLCBiVmFsdWUpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChvYmplY3REaWZmKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRpZmYgPSBkaWZmIHx8IHt9O1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBkaWZmW2FLZXldID0gb2JqZWN0RGlmZjtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBkaWZmID0gZGlmZiB8fCB7fTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGRpZmZbYUtleV0gPSBiVmFsdWU7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICBmb3IgKHZhciBiS2V5IGluIGIpIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKCEoYktleSBpbiBhKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgZGlmZiA9IGRpZmYgfHwge307XG4gICAgICAgICAgICAgICAgICAgICAgICBkaWZmW2JLZXldID0gYltiS2V5XTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHJldHVybiBkaWZmO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBmdW5jdGlvbiBnZXRQcm90b3R5cGUodmFsdWUpIHtcbiAgICAgICAgICAgICAgICBpZiAoT2JqZWN0LmdldFByb3RvdHlwZU9mKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBPYmplY3QuZ2V0UHJvdG90eXBlT2YodmFsdWUpO1xuICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAodmFsdWUuX19wcm90b19fKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiB2YWx1ZS5fX3Byb3RvX187XG4gICAgICAgICAgICAgICAgfSBlbHNlIGlmICh2YWx1ZS5jb25zdHJ1Y3Rvcikge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gdmFsdWUuY29uc3RydWN0b3IucHJvdG90eXBlO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgfSwgeyBcIi4uL3Zub2RlL2lzLXZob29rXCI6IDI2LCBcImlzLW9iamVjdFwiOiAxMSB9XSwgMzU6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICB2YXIgaXNBcnJheSA9IHJlcXVpcmUoXCJ4LWlzLWFycmF5XCIpO1xuXG4gICAgICAgICAgICB2YXIgVlBhdGNoID0gcmVxdWlyZShcIi4uL3Zub2RlL3ZwYXRjaFwiKTtcbiAgICAgICAgICAgIHZhciBpc1ZOb2RlID0gcmVxdWlyZShcIi4uL3Zub2RlL2lzLXZub2RlXCIpO1xuICAgICAgICAgICAgdmFyIGlzVlRleHQgPSByZXF1aXJlKFwiLi4vdm5vZGUvaXMtdnRleHRcIik7XG4gICAgICAgICAgICB2YXIgaXNXaWRnZXQgPSByZXF1aXJlKFwiLi4vdm5vZGUvaXMtd2lkZ2V0XCIpO1xuICAgICAgICAgICAgdmFyIGlzVGh1bmsgPSByZXF1aXJlKFwiLi4vdm5vZGUvaXMtdGh1bmtcIik7XG4gICAgICAgICAgICB2YXIgaGFuZGxlVGh1bmsgPSByZXF1aXJlKFwiLi4vdm5vZGUvaGFuZGxlLXRodW5rXCIpO1xuXG4gICAgICAgICAgICB2YXIgZGlmZlByb3BzID0gcmVxdWlyZShcIi4vZGlmZi1wcm9wc1wiKTtcblxuICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBkaWZmO1xuXG4gICAgICAgICAgICBmdW5jdGlvbiBkaWZmKGEsIGIpIHtcbiAgICAgICAgICAgICAgICB2YXIgcGF0Y2ggPSB7IGE6IGEgfTtcbiAgICAgICAgICAgICAgICB3YWxrKGEsIGIsIHBhdGNoLCAwKTtcbiAgICAgICAgICAgICAgICByZXR1cm4gcGF0Y2g7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIHdhbGsoYSwgYiwgcGF0Y2gsIGluZGV4KSB7XG4gICAgICAgICAgICAgICAgaWYgKGEgPT09IGIpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHZhciBhcHBseSA9IHBhdGNoW2luZGV4XTtcbiAgICAgICAgICAgICAgICB2YXIgYXBwbHlDbGVhciA9IGZhbHNlO1xuXG4gICAgICAgICAgICAgICAgaWYgKGlzVGh1bmsoYSkgfHwgaXNUaHVuayhiKSkge1xuICAgICAgICAgICAgICAgICAgICB0aHVua3MoYSwgYiwgcGF0Y2gsIGluZGV4KTtcbiAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKGIgPT0gbnVsbCkge1xuXG4gICAgICAgICAgICAgICAgICAgIC8vIElmIGEgaXMgYSB3aWRnZXQgd2Ugd2lsbCBhZGQgYSByZW1vdmUgcGF0Y2ggZm9yIGl0XG4gICAgICAgICAgICAgICAgICAgIC8vIE90aGVyd2lzZSBhbnkgY2hpbGQgd2lkZ2V0cy9ob29rcyBtdXN0IGJlIGRlc3Ryb3llZC5cbiAgICAgICAgICAgICAgICAgICAgLy8gVGhpcyBwcmV2ZW50cyBhZGRpbmcgdHdvIHJlbW92ZSBwYXRjaGVzIGZvciBhIHdpZGdldC5cbiAgICAgICAgICAgICAgICAgICAgaWYgKCFpc1dpZGdldChhKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgY2xlYXJTdGF0ZShhLCBwYXRjaCwgaW5kZXgpO1xuICAgICAgICAgICAgICAgICAgICAgICAgYXBwbHkgPSBwYXRjaFtpbmRleF07XG4gICAgICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgICAgICBhcHBseSA9IGFwcGVuZFBhdGNoKGFwcGx5LCBuZXcgVlBhdGNoKFZQYXRjaC5SRU1PVkUsIGEsIGIpKTtcbiAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKGlzVk5vZGUoYikpIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKGlzVk5vZGUoYSkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChhLnRhZ05hbWUgPT09IGIudGFnTmFtZSAmJiBhLm5hbWVzcGFjZSA9PT0gYi5uYW1lc3BhY2UgJiYgYS5rZXkgPT09IGIua2V5KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdmFyIHByb3BzUGF0Y2ggPSBkaWZmUHJvcHMoYS5wcm9wZXJ0aWVzLCBiLnByb3BlcnRpZXMpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChwcm9wc1BhdGNoKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGFwcGx5ID0gYXBwZW5kUGF0Y2goYXBwbHksIG5ldyBWUGF0Y2goVlBhdGNoLlBST1BTLCBhLCBwcm9wc1BhdGNoKSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGFwcGx5ID0gZGlmZkNoaWxkcmVuKGEsIGIsIHBhdGNoLCBhcHBseSwgaW5kZXgpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBhcHBseSA9IGFwcGVuZFBhdGNoKGFwcGx5LCBuZXcgVlBhdGNoKFZQYXRjaC5WTk9ERSwgYSwgYikpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGFwcGx5Q2xlYXIgPSB0cnVlO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgYXBwbHkgPSBhcHBlbmRQYXRjaChhcHBseSwgbmV3IFZQYXRjaChWUGF0Y2guVk5PREUsIGEsIGIpKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGFwcGx5Q2xlYXIgPSB0cnVlO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfSBlbHNlIGlmIChpc1ZUZXh0KGIpKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmICghaXNWVGV4dChhKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgYXBwbHkgPSBhcHBlbmRQYXRjaChhcHBseSwgbmV3IFZQYXRjaChWUGF0Y2guVlRFWFQsIGEsIGIpKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGFwcGx5Q2xlYXIgPSB0cnVlO1xuICAgICAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKGEudGV4dCAhPT0gYi50ZXh0KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBhcHBseSA9IGFwcGVuZFBhdGNoKGFwcGx5LCBuZXcgVlBhdGNoKFZQYXRjaC5WVEVYVCwgYSwgYikpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfSBlbHNlIGlmIChpc1dpZGdldChiKSkge1xuICAgICAgICAgICAgICAgICAgICBpZiAoIWlzV2lkZ2V0KGEpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBhcHBseUNsZWFyID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgIGFwcGx5ID0gYXBwZW5kUGF0Y2goYXBwbHksIG5ldyBWUGF0Y2goVlBhdGNoLldJREdFVCwgYSwgYikpO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIGlmIChhcHBseSkge1xuICAgICAgICAgICAgICAgICAgICBwYXRjaFtpbmRleF0gPSBhcHBseTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICBpZiAoYXBwbHlDbGVhcikge1xuICAgICAgICAgICAgICAgICAgICBjbGVhclN0YXRlKGEsIHBhdGNoLCBpbmRleCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBmdW5jdGlvbiBkaWZmQ2hpbGRyZW4oYSwgYiwgcGF0Y2gsIGFwcGx5LCBpbmRleCkge1xuICAgICAgICAgICAgICAgIHZhciBhQ2hpbGRyZW4gPSBhLmNoaWxkcmVuO1xuICAgICAgICAgICAgICAgIHZhciBvcmRlcmVkU2V0ID0gcmVvcmRlcihhQ2hpbGRyZW4sIGIuY2hpbGRyZW4pO1xuICAgICAgICAgICAgICAgIHZhciBiQ2hpbGRyZW4gPSBvcmRlcmVkU2V0LmNoaWxkcmVuO1xuXG4gICAgICAgICAgICAgICAgdmFyIGFMZW4gPSBhQ2hpbGRyZW4ubGVuZ3RoO1xuICAgICAgICAgICAgICAgIHZhciBiTGVuID0gYkNoaWxkcmVuLmxlbmd0aDtcbiAgICAgICAgICAgICAgICB2YXIgbGVuID0gYUxlbiA+IGJMZW4gPyBhTGVuIDogYkxlbjtcblxuICAgICAgICAgICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgbGVuOyBpKyspIHtcbiAgICAgICAgICAgICAgICAgICAgdmFyIGxlZnROb2RlID0gYUNoaWxkcmVuW2ldO1xuICAgICAgICAgICAgICAgICAgICB2YXIgcmlnaHROb2RlID0gYkNoaWxkcmVuW2ldO1xuICAgICAgICAgICAgICAgICAgICBpbmRleCArPSAxO1xuXG4gICAgICAgICAgICAgICAgICAgIGlmICghbGVmdE5vZGUpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChyaWdodE5vZGUpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBFeGNlc3Mgbm9kZXMgaW4gYiBuZWVkIHRvIGJlIGFkZGVkXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgYXBwbHkgPSBhcHBlbmRQYXRjaChhcHBseSwgbmV3IFZQYXRjaChWUGF0Y2guSU5TRVJULCBudWxsLCByaWdodE5vZGUpKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHdhbGsobGVmdE5vZGUsIHJpZ2h0Tm9kZSwgcGF0Y2gsIGluZGV4KTtcbiAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgIGlmIChpc1ZOb2RlKGxlZnROb2RlKSAmJiBsZWZ0Tm9kZS5jb3VudCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgaW5kZXggKz0gbGVmdE5vZGUuY291bnQ7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICBpZiAob3JkZXJlZFNldC5tb3Zlcykge1xuICAgICAgICAgICAgICAgICAgICAvLyBSZW9yZGVyIG5vZGVzIGxhc3RcbiAgICAgICAgICAgICAgICAgICAgYXBwbHkgPSBhcHBlbmRQYXRjaChhcHBseSwgbmV3IFZQYXRjaChWUGF0Y2guT1JERVIsIGEsIG9yZGVyZWRTZXQubW92ZXMpKTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICByZXR1cm4gYXBwbHk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIGNsZWFyU3RhdGUodk5vZGUsIHBhdGNoLCBpbmRleCkge1xuICAgICAgICAgICAgICAgIC8vIFRPRE86IE1ha2UgdGhpcyBhIHNpbmdsZSB3YWxrLCBub3QgdHdvXG4gICAgICAgICAgICAgICAgdW5ob29rKHZOb2RlLCBwYXRjaCwgaW5kZXgpO1xuICAgICAgICAgICAgICAgIGRlc3Ryb3lXaWRnZXRzKHZOb2RlLCBwYXRjaCwgaW5kZXgpO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAvLyBQYXRjaCByZWNvcmRzIGZvciBhbGwgZGVzdHJveWVkIHdpZGdldHMgbXVzdCBiZSBhZGRlZCBiZWNhdXNlIHdlIG5lZWRcbiAgICAgICAgICAgIC8vIGEgRE9NIG5vZGUgcmVmZXJlbmNlIGZvciB0aGUgZGVzdHJveSBmdW5jdGlvblxuICAgICAgICAgICAgZnVuY3Rpb24gZGVzdHJveVdpZGdldHModk5vZGUsIHBhdGNoLCBpbmRleCkge1xuICAgICAgICAgICAgICAgIGlmIChpc1dpZGdldCh2Tm9kZSkpIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKHR5cGVvZiB2Tm9kZS5kZXN0cm95ID09PSBcImZ1bmN0aW9uXCIpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHBhdGNoW2luZGV4XSA9IGFwcGVuZFBhdGNoKHBhdGNoW2luZGV4XSwgbmV3IFZQYXRjaChWUGF0Y2guUkVNT1ZFLCB2Tm9kZSwgbnVsbCkpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfSBlbHNlIGlmIChpc1ZOb2RlKHZOb2RlKSAmJiAodk5vZGUuaGFzV2lkZ2V0cyB8fCB2Tm9kZS5oYXNUaHVua3MpKSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciBjaGlsZHJlbiA9IHZOb2RlLmNoaWxkcmVuO1xuICAgICAgICAgICAgICAgICAgICB2YXIgbGVuID0gY2hpbGRyZW4ubGVuZ3RoO1xuICAgICAgICAgICAgICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IGxlbjsgaSsrKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICB2YXIgY2hpbGQgPSBjaGlsZHJlbltpXTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGluZGV4ICs9IDE7XG5cbiAgICAgICAgICAgICAgICAgICAgICAgIGRlc3Ryb3lXaWRnZXRzKGNoaWxkLCBwYXRjaCwgaW5kZXgpO1xuXG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoaXNWTm9kZShjaGlsZCkgJiYgY2hpbGQuY291bnQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpbmRleCArPSBjaGlsZC5jb3VudDtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoaXNUaHVuayh2Tm9kZSkpIHtcbiAgICAgICAgICAgICAgICAgICAgdGh1bmtzKHZOb2RlLCBudWxsLCBwYXRjaCwgaW5kZXgpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgLy8gQ3JlYXRlIGEgc3ViLXBhdGNoIGZvciB0aHVua3NcbiAgICAgICAgICAgIGZ1bmN0aW9uIHRodW5rcyhhLCBiLCBwYXRjaCwgaW5kZXgpIHtcbiAgICAgICAgICAgICAgICB2YXIgbm9kZXMgPSBoYW5kbGVUaHVuayhhLCBiKTtcbiAgICAgICAgICAgICAgICB2YXIgdGh1bmtQYXRjaCA9IGRpZmYobm9kZXMuYSwgbm9kZXMuYik7XG4gICAgICAgICAgICAgICAgaWYgKGhhc1BhdGNoZXModGh1bmtQYXRjaCkpIHtcbiAgICAgICAgICAgICAgICAgICAgcGF0Y2hbaW5kZXhdID0gbmV3IFZQYXRjaChWUGF0Y2guVEhVTkssIG51bGwsIHRodW5rUGF0Y2gpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZnVuY3Rpb24gaGFzUGF0Y2hlcyhwYXRjaCkge1xuICAgICAgICAgICAgICAgIGZvciAodmFyIGluZGV4IGluIHBhdGNoKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmIChpbmRleCAhPT0gXCJhXCIpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAvLyBFeGVjdXRlIGhvb2tzIHdoZW4gdHdvIG5vZGVzIGFyZSBpZGVudGljYWxcbiAgICAgICAgICAgIGZ1bmN0aW9uIHVuaG9vayh2Tm9kZSwgcGF0Y2gsIGluZGV4KSB7XG4gICAgICAgICAgICAgICAgaWYgKGlzVk5vZGUodk5vZGUpKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmICh2Tm9kZS5ob29rcykge1xuICAgICAgICAgICAgICAgICAgICAgICAgcGF0Y2hbaW5kZXhdID0gYXBwZW5kUGF0Y2gocGF0Y2hbaW5kZXhdLCBuZXcgVlBhdGNoKFZQYXRjaC5QUk9QUywgdk5vZGUsIHVuZGVmaW5lZEtleXModk5vZGUuaG9va3MpKSk7XG4gICAgICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgICAgICBpZiAodk5vZGUuZGVzY2VuZGFudEhvb2tzIHx8IHZOb2RlLmhhc1RodW5rcykge1xuICAgICAgICAgICAgICAgICAgICAgICAgdmFyIGNoaWxkcmVuID0gdk5vZGUuY2hpbGRyZW47XG4gICAgICAgICAgICAgICAgICAgICAgICB2YXIgbGVuID0gY2hpbGRyZW4ubGVuZ3RoO1xuICAgICAgICAgICAgICAgICAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCBsZW47IGkrKykge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZhciBjaGlsZCA9IGNoaWxkcmVuW2ldO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGluZGV4ICs9IDE7XG5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB1bmhvb2soY2hpbGQsIHBhdGNoLCBpbmRleCk7XG5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoaXNWTm9kZShjaGlsZCkgJiYgY2hpbGQuY291bnQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaW5kZXggKz0gY2hpbGQuY291bnQ7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfSBlbHNlIGlmIChpc1RodW5rKHZOb2RlKSkge1xuICAgICAgICAgICAgICAgICAgICB0aHVua3Modk5vZGUsIG51bGwsIHBhdGNoLCBpbmRleCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBmdW5jdGlvbiB1bmRlZmluZWRLZXlzKG9iaikge1xuICAgICAgICAgICAgICAgIHZhciByZXN1bHQgPSB7fTtcblxuICAgICAgICAgICAgICAgIGZvciAodmFyIGtleSBpbiBvYmopIHtcbiAgICAgICAgICAgICAgICAgICAgcmVzdWx0W2tleV0gPSB1bmRlZmluZWQ7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgcmV0dXJuIHJlc3VsdDtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgLy8gTGlzdCBkaWZmLCBuYWl2ZSBsZWZ0IHRvIHJpZ2h0IHJlb3JkZXJpbmdcbiAgICAgICAgICAgIGZ1bmN0aW9uIHJlb3JkZXIoYUNoaWxkcmVuLCBiQ2hpbGRyZW4pIHtcbiAgICAgICAgICAgICAgICAvLyBPKE0pIHRpbWUsIE8oTSkgbWVtb3J5XG4gICAgICAgICAgICAgICAgdmFyIGJDaGlsZEluZGV4ID0ga2V5SW5kZXgoYkNoaWxkcmVuKTtcbiAgICAgICAgICAgICAgICB2YXIgYktleXMgPSBiQ2hpbGRJbmRleC5rZXlzO1xuICAgICAgICAgICAgICAgIHZhciBiRnJlZSA9IGJDaGlsZEluZGV4LmZyZWU7XG5cbiAgICAgICAgICAgICAgICBpZiAoYkZyZWUubGVuZ3RoID09PSBiQ2hpbGRyZW4ubGVuZ3RoKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiB7XG4gICAgICAgICAgICAgICAgICAgICAgICBjaGlsZHJlbjogYkNoaWxkcmVuLFxuICAgICAgICAgICAgICAgICAgICAgICAgbW92ZXM6IG51bGxcbiAgICAgICAgICAgICAgICAgICAgfTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAvLyBPKE4pIHRpbWUsIE8oTikgbWVtb3J5XG4gICAgICAgICAgICAgICAgdmFyIGFDaGlsZEluZGV4ID0ga2V5SW5kZXgoYUNoaWxkcmVuKTtcbiAgICAgICAgICAgICAgICB2YXIgYUtleXMgPSBhQ2hpbGRJbmRleC5rZXlzO1xuICAgICAgICAgICAgICAgIHZhciBhRnJlZSA9IGFDaGlsZEluZGV4LmZyZWU7XG5cbiAgICAgICAgICAgICAgICBpZiAoYUZyZWUubGVuZ3RoID09PSBhQ2hpbGRyZW4ubGVuZ3RoKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiB7XG4gICAgICAgICAgICAgICAgICAgICAgICBjaGlsZHJlbjogYkNoaWxkcmVuLFxuICAgICAgICAgICAgICAgICAgICAgICAgbW92ZXM6IG51bGxcbiAgICAgICAgICAgICAgICAgICAgfTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAvLyBPKE1BWChOLCBNKSkgbWVtb3J5XG4gICAgICAgICAgICAgICAgdmFyIG5ld0NoaWxkcmVuID0gW107XG5cbiAgICAgICAgICAgICAgICB2YXIgZnJlZUluZGV4ID0gMDtcbiAgICAgICAgICAgICAgICB2YXIgZnJlZUNvdW50ID0gYkZyZWUubGVuZ3RoO1xuICAgICAgICAgICAgICAgIHZhciBkZWxldGVkSXRlbXMgPSAwO1xuXG4gICAgICAgICAgICAgICAgLy8gSXRlcmF0ZSB0aHJvdWdoIGEgYW5kIG1hdGNoIGEgbm9kZSBpbiBiXG4gICAgICAgICAgICAgICAgLy8gTyhOKSB0aW1lLFxuICAgICAgICAgICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgYUNoaWxkcmVuLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciBhSXRlbSA9IGFDaGlsZHJlbltpXTtcbiAgICAgICAgICAgICAgICAgICAgdmFyIGl0ZW1JbmRleDtcblxuICAgICAgICAgICAgICAgICAgICBpZiAoYUl0ZW0ua2V5KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoYktleXMuaGFzT3duUHJvcGVydHkoYUl0ZW0ua2V5KSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIE1hdGNoIHVwIHRoZSBvbGQga2V5c1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGl0ZW1JbmRleCA9IGJLZXlzW2FJdGVtLmtleV07XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgbmV3Q2hpbGRyZW4ucHVzaChiQ2hpbGRyZW5baXRlbUluZGV4XSk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIFJlbW92ZSBvbGQga2V5ZWQgaXRlbXNcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpdGVtSW5kZXggPSBpIC0gZGVsZXRlZEl0ZW1zKys7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgbmV3Q2hpbGRyZW4ucHVzaChudWxsKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIE1hdGNoIHRoZSBpdGVtIGluIGEgd2l0aCB0aGUgbmV4dCBmcmVlIGl0ZW0gaW4gYlxuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGZyZWVJbmRleCA8IGZyZWVDb3VudCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGl0ZW1JbmRleCA9IGJGcmVlW2ZyZWVJbmRleCsrXTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBuZXdDaGlsZHJlbi5wdXNoKGJDaGlsZHJlbltpdGVtSW5kZXhdKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gVGhlcmUgYXJlIG5vIGZyZWUgaXRlbXMgaW4gYiB0byBtYXRjaCB3aXRoXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gdGhlIGZyZWUgaXRlbXMgaW4gYSwgc28gdGhlIGV4dHJhIGZyZWUgbm9kZXNcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBhcmUgZGVsZXRlZC5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpdGVtSW5kZXggPSBpIC0gZGVsZXRlZEl0ZW1zKys7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgbmV3Q2hpbGRyZW4ucHVzaChudWxsKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHZhciBsYXN0RnJlZUluZGV4ID0gZnJlZUluZGV4ID49IGJGcmVlLmxlbmd0aCA/IGJDaGlsZHJlbi5sZW5ndGggOiBiRnJlZVtmcmVlSW5kZXhdO1xuXG4gICAgICAgICAgICAgICAgLy8gSXRlcmF0ZSB0aHJvdWdoIGIgYW5kIGFwcGVuZCBhbnkgbmV3IGtleXNcbiAgICAgICAgICAgICAgICAvLyBPKE0pIHRpbWVcbiAgICAgICAgICAgICAgICBmb3IgKHZhciBqID0gMDsgaiA8IGJDaGlsZHJlbi5sZW5ndGg7IGorKykge1xuICAgICAgICAgICAgICAgICAgICB2YXIgbmV3SXRlbSA9IGJDaGlsZHJlbltqXTtcblxuICAgICAgICAgICAgICAgICAgICBpZiAobmV3SXRlbS5rZXkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmICghYUtleXMuaGFzT3duUHJvcGVydHkobmV3SXRlbS5rZXkpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gQWRkIGFueSBuZXcga2V5ZWQgaXRlbXNcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBXZSBhcmUgYWRkaW5nIG5ldyBpdGVtcyB0byB0aGUgZW5kIGFuZCB0aGVuIHNvcnRpbmcgdGhlbVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIGluIHBsYWNlLiBJbiBmdXR1cmUgd2Ugc2hvdWxkIGluc2VydCBuZXcgaXRlbXMgaW4gcGxhY2UuXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgbmV3Q2hpbGRyZW4ucHVzaChuZXdJdGVtKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIGlmIChqID49IGxhc3RGcmVlSW5kZXgpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIEFkZCBhbnkgbGVmdG92ZXIgbm9uLWtleWVkIGl0ZW1zXG4gICAgICAgICAgICAgICAgICAgICAgICBuZXdDaGlsZHJlbi5wdXNoKG5ld0l0ZW0pO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgdmFyIHNpbXVsYXRlID0gbmV3Q2hpbGRyZW4uc2xpY2UoKTtcbiAgICAgICAgICAgICAgICB2YXIgc2ltdWxhdGVJbmRleCA9IDA7XG4gICAgICAgICAgICAgICAgdmFyIHJlbW92ZXMgPSBbXTtcbiAgICAgICAgICAgICAgICB2YXIgaW5zZXJ0cyA9IFtdO1xuICAgICAgICAgICAgICAgIHZhciBzaW11bGF0ZUl0ZW07XG5cbiAgICAgICAgICAgICAgICBmb3IgKHZhciBrID0gMDsgayA8IGJDaGlsZHJlbi5sZW5ndGg7KSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciB3YW50ZWRJdGVtID0gYkNoaWxkcmVuW2tdO1xuICAgICAgICAgICAgICAgICAgICBzaW11bGF0ZUl0ZW0gPSBzaW11bGF0ZVtzaW11bGF0ZUluZGV4XTtcblxuICAgICAgICAgICAgICAgICAgICAvLyByZW1vdmUgaXRlbXNcbiAgICAgICAgICAgICAgICAgICAgd2hpbGUgKHNpbXVsYXRlSXRlbSA9PT0gbnVsbCAmJiBzaW11bGF0ZS5sZW5ndGgpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJlbW92ZXMucHVzaChyZW1vdmUoc2ltdWxhdGUsIHNpbXVsYXRlSW5kZXgsIG51bGwpKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIHNpbXVsYXRlSXRlbSA9IHNpbXVsYXRlW3NpbXVsYXRlSW5kZXhdO1xuICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgaWYgKCFzaW11bGF0ZUl0ZW0gfHwgc2ltdWxhdGVJdGVtLmtleSAhPT0gd2FudGVkSXRlbS5rZXkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIGlmIHdlIG5lZWQgYSBrZXkgaW4gdGhpcyBwb3NpdGlvbi4uLlxuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHdhbnRlZEl0ZW0ua2V5KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHNpbXVsYXRlSXRlbSAmJiBzaW11bGF0ZUl0ZW0ua2V5KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIGlmIGFuIGluc2VydCBkb2Vzbid0IHB1dCB0aGlzIGtleSBpbiBwbGFjZSwgaXQgbmVlZHMgdG8gbW92ZVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoYktleXNbc2ltdWxhdGVJdGVtLmtleV0gIT09IGsgKyAxKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICByZW1vdmVzLnB1c2gocmVtb3ZlKHNpbXVsYXRlLCBzaW11bGF0ZUluZGV4LCBzaW11bGF0ZUl0ZW0ua2V5KSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzaW11bGF0ZUl0ZW0gPSBzaW11bGF0ZVtzaW11bGF0ZUluZGV4XTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIGlmIHRoZSByZW1vdmUgZGlkbid0IHB1dCB0aGUgd2FudGVkIGl0ZW0gaW4gcGxhY2UsIHdlIG5lZWQgdG8gaW5zZXJ0IGl0XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoIXNpbXVsYXRlSXRlbSB8fCBzaW11bGF0ZUl0ZW0ua2V5ICE9PSB3YW50ZWRJdGVtLmtleSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGluc2VydHMucHVzaCh7IGtleTogd2FudGVkSXRlbS5rZXksIHRvOiBrIH0pO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gaXRlbXMgYXJlIG1hdGNoaW5nLCBzbyBza2lwIGFoZWFkXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzaW11bGF0ZUluZGV4Kys7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpbnNlcnRzLnB1c2goeyBrZXk6IHdhbnRlZEl0ZW0ua2V5LCB0bzogayB9KTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGluc2VydHMucHVzaCh7IGtleTogd2FudGVkSXRlbS5rZXksIHRvOiBrIH0pO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBrKys7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAvLyBhIGtleSBpbiBzaW11bGF0ZSBoYXMgbm8gbWF0Y2hpbmcgd2FudGVkIGtleSwgcmVtb3ZlIGl0XG4gICAgICAgICAgICAgICAgICAgICAgICBlbHNlIGlmIChzaW11bGF0ZUl0ZW0gJiYgc2ltdWxhdGVJdGVtLmtleSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlbW92ZXMucHVzaChyZW1vdmUoc2ltdWxhdGUsIHNpbXVsYXRlSW5kZXgsIHNpbXVsYXRlSXRlbS5rZXkpKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHNpbXVsYXRlSW5kZXgrKztcbiAgICAgICAgICAgICAgICAgICAgICAgIGsrKztcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIC8vIHJlbW92ZSBhbGwgdGhlIHJlbWFpbmluZyBub2RlcyBmcm9tIHNpbXVsYXRlXG4gICAgICAgICAgICAgICAgd2hpbGUgKHNpbXVsYXRlSW5kZXggPCBzaW11bGF0ZS5sZW5ndGgpIHtcbiAgICAgICAgICAgICAgICAgICAgc2ltdWxhdGVJdGVtID0gc2ltdWxhdGVbc2ltdWxhdGVJbmRleF07XG4gICAgICAgICAgICAgICAgICAgIHJlbW92ZXMucHVzaChyZW1vdmUoc2ltdWxhdGUsIHNpbXVsYXRlSW5kZXgsIHNpbXVsYXRlSXRlbSAmJiBzaW11bGF0ZUl0ZW0ua2V5KSk7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgLy8gSWYgdGhlIG9ubHkgbW92ZXMgd2UgaGF2ZSBhcmUgZGVsZXRlcyB0aGVuIHdlIGNhbiBqdXN0XG4gICAgICAgICAgICAgICAgLy8gbGV0IHRoZSBkZWxldGUgcGF0Y2ggcmVtb3ZlIHRoZXNlIGl0ZW1zLlxuICAgICAgICAgICAgICAgIGlmIChyZW1vdmVzLmxlbmd0aCA9PT0gZGVsZXRlZEl0ZW1zICYmICFpbnNlcnRzLmxlbmd0aCkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgICAgICAgICAgICAgY2hpbGRyZW46IG5ld0NoaWxkcmVuLFxuICAgICAgICAgICAgICAgICAgICAgICAgbW92ZXM6IG51bGxcbiAgICAgICAgICAgICAgICAgICAgfTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgICAgICAgICBjaGlsZHJlbjogbmV3Q2hpbGRyZW4sXG4gICAgICAgICAgICAgICAgICAgIG1vdmVzOiB7XG4gICAgICAgICAgICAgICAgICAgICAgICByZW1vdmVzOiByZW1vdmVzLFxuICAgICAgICAgICAgICAgICAgICAgICAgaW5zZXJ0czogaW5zZXJ0c1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZnVuY3Rpb24gcmVtb3ZlKGFyciwgaW5kZXgsIGtleSkge1xuICAgICAgICAgICAgICAgIGFyci5zcGxpY2UoaW5kZXgsIDEpO1xuXG4gICAgICAgICAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgICAgICAgICAgZnJvbTogaW5kZXgsXG4gICAgICAgICAgICAgICAgICAgIGtleToga2V5XG4gICAgICAgICAgICAgICAgfTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZnVuY3Rpb24ga2V5SW5kZXgoY2hpbGRyZW4pIHtcbiAgICAgICAgICAgICAgICB2YXIga2V5cyA9IHt9O1xuICAgICAgICAgICAgICAgIHZhciBmcmVlID0gW107XG4gICAgICAgICAgICAgICAgdmFyIGxlbmd0aCA9IGNoaWxkcmVuLmxlbmd0aDtcblxuICAgICAgICAgICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgbGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgICAgICAgICAgdmFyIGNoaWxkID0gY2hpbGRyZW5baV07XG5cbiAgICAgICAgICAgICAgICAgICAgaWYgKGNoaWxkLmtleSkge1xuICAgICAgICAgICAgICAgICAgICAgICAga2V5c1tjaGlsZC5rZXldID0gaTtcbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGZyZWUucHVzaChpKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHJldHVybiB7XG4gICAgICAgICAgICAgICAgICAgIGtleXM6IGtleXMsIC8vIEEgaGFzaCBvZiBrZXkgbmFtZSB0byBpbmRleFxuICAgICAgICAgICAgICAgICAgICBmcmVlOiBmcmVlIC8vIEFuIGFycmF5IG9mIHVua2V5ZWQgaXRlbSBpbmRpY2VzXG4gICAgICAgICAgICAgICAgfTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZnVuY3Rpb24gYXBwZW5kUGF0Y2goYXBwbHksIHBhdGNoKSB7XG4gICAgICAgICAgICAgICAgaWYgKGFwcGx5KSB7XG4gICAgICAgICAgICAgICAgICAgIGlmIChpc0FycmF5KGFwcGx5KSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgYXBwbHkucHVzaChwYXRjaCk7XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBhcHBseSA9IFthcHBseSwgcGF0Y2hdO1xuICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGFwcGx5O1xuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBwYXRjaDtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH0sIHsgXCIuLi92bm9kZS9oYW5kbGUtdGh1bmtcIjogMjQsIFwiLi4vdm5vZGUvaXMtdGh1bmtcIjogMjUsIFwiLi4vdm5vZGUvaXMtdm5vZGVcIjogMjcsIFwiLi4vdm5vZGUvaXMtdnRleHRcIjogMjgsIFwiLi4vdm5vZGUvaXMtd2lkZ2V0XCI6IDI5LCBcIi4uL3Zub2RlL3ZwYXRjaFwiOiAzMiwgXCIuL2RpZmYtcHJvcHNcIjogMzQsIFwieC1pcy1hcnJheVwiOiAxMiB9XSB9LCB7fSwgWzRdKSg0KTtcbn0pO1xuXG5jb25zdCBzdGFydCA9IGZ1bmN0aW9uIChkb21Sb290LCByZW5kZXJGbiwgaW5pdGlhbFN0YXRlLCBvcHRpb25zID0gW10pIHtcbiAgbGV0IHBpZCA9IHNlbGYucHJvY2Vzc2VzLnNwYXduKCk7XG5cbiAgaWYgKEtleXdvcmQuaGFzX2tleV9fcW1fXyhvcHRpb25zLCBLZXJuZWwuU3BlY2lhbEZvcm1zLmF0b20oJ25hbWUnKSkpIHtcbiAgICBwaWQgPSBzZWxmLnByb2Nlc3Nlcy5yZWdpc3RlcihLZXl3b3JkLmdldChvcHRpb25zLCBLZXJuZWwuU3BlY2lhbEZvcm1zLmF0b20oJ25hbWUnKSksIHBpZCk7XG4gIH1cblxuICBjb25zdCB0cmVlID0gcmVuZGVyRm4uYXBwbHkodGhpcywgaW5pdGlhbFN0YXRlKTtcbiAgY29uc3Qgcm9vdE5vZGUgPSBWaXJ0dWFsRE9NLmNyZWF0ZSh0cmVlKTtcblxuICBkb21Sb290LmFwcGVuZENoaWxkKHJvb3ROb2RlKTtcblxuICBzZWxmLnByb2Nlc3Nlcy5wdXQocGlkLCAnc3RhdGUnLCBLZXJuZWwuU3BlY2lhbEZvcm1zLnR1cGxlKHJvb3ROb2RlLCB0cmVlLCByZW5kZXJGbikpO1xuICByZXR1cm4gS2VybmVsLlNwZWNpYWxGb3Jtcy50dXBsZShLZXJuZWwuU3BlY2lhbEZvcm1zLmF0b20oJ29rJyksIHBpZCk7XG59O1xuXG5jb25zdCBzdG9wID0gZnVuY3Rpb24gKGFnZW50LCB0aW1lb3V0ID0gNTAwMCkge1xuICBzZWxmLnByb2Nlc3Nlcy5leGl0KGFnZW50KTtcbiAgcmV0dXJuIEtlcm5lbC5TcGVjaWFsRm9ybXMuYXRvbSgnb2snKTtcbn07XG5cbmNvbnN0IHJlbmRlciA9IGZ1bmN0aW9uIChhZ2VudCwgc3RhdGUpIHtcblxuICBjb25zdCBjdXJyZW50X3N0YXRlID0gc2VsZi5wcm9jZXNzZXMuZ2V0KGFnZW50LCAnc3RhdGUnKTtcblxuICBsZXQgcm9vdE5vZGUgPSBLZXJuZWwuZWxlbShjdXJyZW50X3N0YXRlLCAwKTtcbiAgbGV0IHRyZWUgPSBLZXJuZWwuZWxlbShjdXJyZW50X3N0YXRlLCAxKTtcbiAgbGV0IHJlbmRlckZuID0gS2VybmVsLmVsZW0oY3VycmVudF9zdGF0ZSwgMik7XG5cbiAgbGV0IG5ld1RyZWUgPSByZW5kZXJGbi5hcHBseSh0aGlzLCBzdGF0ZSk7XG5cbiAgbGV0IHBhdGNoZXMgPSBWaXJ0dWFsRE9NLmRpZmYodHJlZSwgbmV3VHJlZSk7XG4gIHJvb3ROb2RlID0gVmlydHVhbERPTS5wYXRjaChyb290Tm9kZSwgcGF0Y2hlcyk7XG5cbiAgc2VsZi5wcm9jZXNzZXMucHV0KGFnZW50LCAnc3RhdGUnLCBLZXJuZWwuU3BlY2lhbEZvcm1zLnR1cGxlKHJvb3ROb2RlLCBuZXdUcmVlLCByZW5kZXJGbikpO1xuXG4gIHJldHVybiBLZXJuZWwuU3BlY2lhbEZvcm1zLmF0b20oJ29rJyk7XG59O1xuXG52YXIgdmlldyA9IHtcbiAgc3RhcnQsXG4gIHN0b3AsXG4gIHJlbmRlclxufTtcblxuc2VsZi5wcm9jZXNzZXMgPSBzZWxmLnByb2Nlc3NlcyB8fCBuZXcgUHJvY2Vzc1N5c3RlbSgpO1xuXG5leHBvcnQgeyBDb3JlLCBQYXR0ZXJucywgQml0U3RyaW5nLCBLZXJuZWwsIEF0b20sIEVudW0sIEludGVnZXIsIGpzIGFzIEpTLCBMaXN0LCBSYW5nZSwgVHVwbGUsIEFnZW50LCBLZXl3b3JkLCBiYXNlIGFzIEJhc2UsIFN0cmluZyQxIGFzIFN0cmluZywgYml0d2lzZSBhcyBCaXR3aXNlLCBFbnVtZXJhYmxlLCBDb2xsZWN0YWJsZSwgSW5zcGVjdCwgbWFwIGFzIE1hcCwgc2V0IGFzIFNldCwgTWFwU2V0LCBJbnRlZ2VyVHlwZSwgRmxvYXRUeXBlLCBWaXJ0dWFsRE9NLCB2aWV3IGFzIFZpZXcgfTsiXSwiZmlsZSI6ImVsaXhpci5qcyIsInNvdXJjZVJvb3QiOiIvc291cmNlLyJ9 \ No newline at end of file diff --git a/src/javascript/elixir.js b/src/javascript/elixir.js index b996befe..41b33761 100644 --- a/src/javascript/elixir.js +++ b/src/javascript/elixir.js @@ -1,7 +1,8 @@ -import PostOffice from './lib/post_office'; +import {ProcessSystem} from './lib/core'; -self.post_office = self.post_office || new PostOffice(); +self.processes = self.processes || new ProcessSystem(); +export { Core } from './lib/core'; export { default as Patterns } from './lib/patterns/patterns'; export { default as BitString } from './lib/bit_string'; export { default as Kernel } from './lib/kernel'; diff --git a/src/javascript/lib/agent.js b/src/javascript/lib/agent.js index fe72f2b3..7d79dd77 100644 --- a/src/javascript/lib/agent.js +++ b/src/javascript/lib/agent.js @@ -4,37 +4,39 @@ import Keyword from './keyword'; let Agent = {}; Agent.start = function(fun, options = []){ - const name = Keyword.has_key__qm__(options, Kernel.SpecialForms.atom("name")) ? Keyword.get(options, Kernel.SpecialForms.atom("name")) : Symbol(); - - self.post_office.add_mailbox(name); - self.post_office.send(name, fun()); + let pid = self.processes.spawn(); - return Kernel.SpecialForms.tuple(Kernel.SpecialForms.atom("ok"), name); + if(Keyword.has_key__qm__(options, Kernel.SpecialForms.atom("name"))){ + pid = self.processes.register(Keyword.get(options, Kernel.SpecialForms.atom("name")), pid) + } + + self.processes.put(pid, "state", fun()); + return Kernel.SpecialForms.tuple(Kernel.SpecialForms.atom("ok"), pid); } Agent.stop = function(agent, timeout = 5000){ - self.post_office.remove_mailbox(agent); + self.processes.exit(agent); return Kernel.SpecialForms.atom("ok"); } Agent.update = function(agent, fun, timeout = 5000){ - const current_state = self.post_office.receive(agent); - self.post_office.send(agent, fun(current_state)); + const current_state = self.processes.get(agent, "state"); + self.processes.put(agent, "state", fun(current_state)); return Kernel.SpecialForms.atom("ok"); } Agent.get = function(agent, fun, timeout = 5000){ - return fun(self.post_office.peek(agent)); + return fun(self.processes.get(agent, "state")); } Agent.get_and_update = function(agent, fun, timeout = 5000){ - const get_and_update_tuple = fun(self.post_office.receive(agent)); - self.post_office.send(agent, Kernel.elem(get_and_update_tuple, 1)); + const get_and_update_tuple = fun(self.processes.get(agent, "state")); + self.processes.put(agent, "state", Kernel.elem(get_and_update_tuple, 1)); return Kernel.elem(get_and_update_tuple, 0); } -export default Agent; \ No newline at end of file +export default Agent; diff --git a/src/javascript/lib/core.js b/src/javascript/lib/core.js new file mode 100644 index 00000000..c7625a73 --- /dev/null +++ b/src/javascript/lib/core.js @@ -0,0 +1,2 @@ +export { default as ProcessSystem } from './core/process_system'; +export { default as Core } from './core/primitives'; diff --git a/src/javascript/lib/processes/processes/mailbox.js b/src/javascript/lib/core/mailbox.js similarity index 100% rename from src/javascript/lib/processes/processes/mailbox.js rename to src/javascript/lib/core/mailbox.js diff --git a/src/javascript/lib/core/primitives.js b/src/javascript/lib/core/primitives.js new file mode 100644 index 00000000..dca6a5a3 --- /dev/null +++ b/src/javascript/lib/core/primitives.js @@ -0,0 +1,47 @@ +class Tuple { + + constructor(...args){ + this.values = Object.freeze(args); + } + + get(index) { + return this.values[index]; + } + + count() { + return this.values.length; + } + + [Symbol.iterator]() { + return this.values[Symbol.iterator](); + } + + toString() { + var i, s = ""; + for (i = 0; i < this.values.length; i++) { + if (s !== "") { + s += ", "; + } + s += this.values[i].toString(); + } + + return "{" + s + "}"; + } + +} + + +let process_counter = -1; + +class PID { + constructor(){ + process_counter = process_counter + 1; + this.id = process_counter; + } + + toString(){ + return "PID#<0." + this.id + ".0>"; + } +} + +export default { PID, Tuple }; diff --git a/src/javascript/lib/core/process.js b/src/javascript/lib/core/process.js new file mode 100644 index 00000000..abe9ddf8 --- /dev/null +++ b/src/javascript/lib/core/process.js @@ -0,0 +1,20 @@ +"use strict"; + +/* @flow */ +import Mailbox from "./mailbox"; +import States from "./states"; + +class Process { + pid: Number; + mailbox: Mailbox; + dict: Object; + + constructor(pid: Number, mailbox: Mailbox){ + this.pid = pid; + this.mailbox = mailbox; + this.status = States.STOPPED; + this.dict = {}; + } +} + +export default Process; diff --git a/src/javascript/lib/core/process_system.js b/src/javascript/lib/core/process_system.js new file mode 100644 index 00000000..cf006455 --- /dev/null +++ b/src/javascript/lib/core/process_system.js @@ -0,0 +1,158 @@ +/* @flow */ +"use strict"; + +import Mailbox from "./mailbox"; +import Process from "./process"; +import States from "./states"; +import Core from "./primitives"; + +class ProcessSystem { + + constructor(){ + this.pids = new Map(); + this.mailboxes = new Map(); + this.names = new Map(); + this.links = new Map(); + + this.current_process = null; + this.suspended = new Map(); + + this.main_process_pid = this.spawn(); + this.set_current(this.main_process_pid); + } + + spawn(){ + return this.add_proc(false).pid; + } + + spawn_link(){ + return this.add_proc(true).pid; + } + + link(pid){ + this.links.get(this.pid()).add(pid); + this.links.get(pid).add(this.pid()); + } + + unlink(pid){ + this.links.get(this.pid()).delete(pid); + this.links.get(pid).delete(this.pid()); + } + + set_current(id){ + let pid = this.pidof(id); + if(pid !== null){ + this.current_process = this.pids.get(pid); + this.current_process.status = States.RUNNING; + } + } + + add_proc(linked){ + let newpid = new Core.PID(); + let mailbox = new Mailbox(); + let newproc = new Process(newpid, mailbox); + + this.pids.set(newpid, newproc); + this.mailboxes.set(newpid, mailbox); + this.links.set(newpid, new Set()); + + if(linked){ + this.link(newpid); + } + + return newproc; + } + + remove_proc(pid){ + this.pids.delete(pid); + this.unregister(pid); + + if(this.links.has(pid)){ + for (let linkpid of this.links.get(pid)) { + this.links.get(linkpid).delete(pid); + } + + this.links.delete(pid); + } + } + + exit(id){ + let pid = this.pidof(id); + this.remove_proc(id); + } + + register(name, pid){ + if(!this.names.has(name)){ + this.names.set(name, pid) + return name; + }else{ + throw new Error("Name is already registered to another process"); + } + } + + registered(name){ + return this.names.has(name) ? this.names.get(name) : null; + } + + unregister(pid){ + for(let name of this.names.keys()){ + if(this.names.has(name) && this.names.get(name) === pid){ + this.names.delete(name); + } + } + } + + pid(){ + return this.current_process.pid; + } + + pidof(id){ + if (id instanceof Core.PID) { + return this.pids.has(id) ? id : null; + } else if (id instanceof Process) { + return id.pid; + } else { + let pid = this.registered(id); + if (pid === null) + throw("Process name not registered: " + id + " (" + typeof(id) + ")"); + return pid; + } + } + + put(id, key, value){ + let pid = this.pidof(id); + let process = this.pids.get(pid); + process.dict[key] = value; + } + + get(id, key){ + let pid = this.pidof(id); + let process = this.pids.get(pid); + + if(key != null){ + return process.dict[key]; + }else{ + return process.dict; + } + } + + get_keys(id){ + let pid = this.pidof(id); + let process = this.pids.get(pid); + + return Object.keys(process.dict); + } + + erase(id, key){ + let pid = this.pidof(id); + let process = this.pids.get(pid); + + if(key != null){ + delete process.dict[key]; + }else{ + process.dict = {}; + } + } +} + +export default ProcessSystem; diff --git a/src/javascript/lib/processes/processes/states.js b/src/javascript/lib/core/states.js similarity index 100% rename from src/javascript/lib/processes/processes/states.js rename to src/javascript/lib/core/states.js diff --git a/src/javascript/lib/kernel.js b/src/javascript/lib/kernel.js index 6ad534ec..8741d856 100644 --- a/src/javascript/lib/kernel.js +++ b/src/javascript/lib/kernel.js @@ -1,9 +1,9 @@ import SpecialForms from './kernel/special_forms'; import Patterns from './patterns/patterns'; -import Tuple from './tuple'; +import { Core } from "./core"; +import Tuple from "./tuple"; import BitString from './bit_string'; import { Protocol } from './protocol'; -import { PID } from './processes/processes'; function tl(list){ return SpecialForms.list(...list.slice(1)); @@ -54,7 +54,7 @@ function is_number(x){ } function is_tuple(x){ - return x instanceof Tuple; + return x instanceof Core.Tuple; } function length(x){ @@ -62,7 +62,7 @@ function length(x){ } function is_pid(x){ - return x instanceof PID; + return x instanceof Core.PID; } function is_port(x){ diff --git a/src/javascript/lib/kernel/special_forms.js b/src/javascript/lib/kernel/special_forms.js index 4d7cbf8b..addf88ce 100644 --- a/src/javascript/lib/kernel/special_forms.js +++ b/src/javascript/lib/kernel/special_forms.js @@ -1,5 +1,5 @@ import BitString from '../bit_string'; -import Tuple from '../tuple'; +import { Core } from '../core'; import Enum from '../enum'; import * as Patterns from '../patterns/patterns'; @@ -125,7 +125,7 @@ let SpecialForms = { }, tuple: function(...args){ - return new Tuple(...args); + return new Core.Tuple(...args); }, diff --git a/src/javascript/lib/patterns/patterns.js b/src/javascript/lib/patterns/patterns.js index c586d86f..2978dbc2 100644 --- a/src/javascript/lib/patterns/patterns.js +++ b/src/javascript/lib/patterns/patterns.js @@ -5,10 +5,7 @@ import { variable, wildcard, startsWith, capture, headTail, type, bound } from " export default { - defmatch, match, MatchError, match_no_throw, patternMap, - variable, wildcard, startsWith, + defmatch, match, MatchError, match_no_throw, + variable, wildcard, startsWith, capture, headTail, type, bound, Case, make_case }; - - - diff --git a/src/javascript/lib/post_office.js b/src/javascript/lib/post_office.js deleted file mode 100644 index 84021656..00000000 --- a/src/javascript/lib/post_office.js +++ /dev/null @@ -1,98 +0,0 @@ -/* @flow */ -import Signal from './signals'; - -function update(map: Map, key: Symbol, value: any): Map { - let m = new Map(map); - m.set(key, value); - return m; -} - -function remove(map: Map, key: Symbol): Map { - let m = new Map(map); - m.delete(key); - return m; -} - -class MailBox { - signal: Signal; - messages: Array; - - constructor(context: any = this){ - this.signal = new Signal(); - this.signal.add((...params) => this.messages = this.messages.concat(params), context); - this.messages = []; - } - - receive(...messages){ - this.signal.dispatch(...messages); - } - - peek(){ - if(this.messages.length === 0){ - return null; - } - - return this.messages[0]; - } - - read(){ - let result = this.messages[0]; - this.messages = this.messages.slice(1); - - return result; - } - - add_subscriber(fn: Function, context: any = this){ - this.signal.add(fn, context); - } - - remove_subscriber(fn: Function){ - this.signal.remove(fn); - } - - dispose(){ - this.signal.dispose(); - this.messages = null; - } -} - - -class PostOffice { - mailboxes: Map; - - constructor(){ - this.mailboxes = new Map(); - } - - send(address: Symbol, message: any): void { - this.mailboxes.get(address).receive(message); - } - - receive(address: Symbol): any { - return this.mailboxes.get(address).read(); - } - - peek(address: Symbol): any { - return this.mailboxes.get(address).peek(); - } - - add_mailbox(address: Symbol = Symbol(), context: any = this): Symbol { - this.mailboxes = update(this.mailboxes, address, new MailBox()); - return address; - } - - remove_mailbox(address: Symbol): void { - this.mailboxes.get(address).dispose(); - this.mailboxes = remove(this.mailboxes, address); - } - - subscribe(address: Symbol, subscribtion_fn: Function, context: any = this ): void { - this.mailboxes.get(address).add_subscriber(subscribtion_fn, context); - } - - unsubscribe(address: Symbol, subscribtion_fn: Function): void { - this.mailboxes.get(address).remove_subscriber(subscribtion_fn); - } -} - -export default PostOffice \ No newline at end of file diff --git a/src/javascript/lib/processes/processes.js b/src/javascript/lib/processes/processes.js deleted file mode 100644 index fadb605d..00000000 --- a/src/javascript/lib/processes/processes.js +++ /dev/null @@ -1,5 +0,0 @@ -export { default as ProcessSystem } from "./processes/process_system"; -export { default as GenServer } from "./processes/otp/gen_server"; -export { default as GenEvent } from "./processes/otp/gen_event"; -export { default as Application } from "./processes/otp/application"; -export { default as PID } from "./processes/pid"; diff --git a/src/javascript/lib/processes/processes/otp/application.js b/src/javascript/lib/processes/processes/otp/application.js deleted file mode 100644 index 15fdad25..00000000 --- a/src/javascript/lib/processes/processes/otp/application.js +++ /dev/null @@ -1,5 +0,0 @@ -function start(app, type = Symbol.for("temporary")){ - return app.start(type, []); -} - -export default { start }; \ No newline at end of file diff --git a/src/javascript/lib/processes/processes/otp/gen_event.js b/src/javascript/lib/processes/processes/otp/gen_event.js deleted file mode 100644 index 3f82bb69..00000000 --- a/src/javascript/lib/processes/processes/otp/gen_event.js +++ /dev/null @@ -1,38 +0,0 @@ -function start(options = []){ - return [Symbol.for("ok"), self.system.spawn(start_process())]; -} - -function start_link(options = []){ - return [Symbol.for("ok"), self.system.spawn_link(start_process())]; -} - -function start_process(){ - return function*(){ - while(true){ - yield self.system.receive(function(args){ - switch(args[0]){ - case "add_handler": - break; - case "notify": - break; - case "call": - break; - } - }); - } - } -} - -function* add_handler(manager, handler, args){ - -} - -function* call(manager, handler, request, timeout = 5000){ - -} - -function* notify(manager, event){ - -} - -export default { start, start_link, call, add_handler, notify }; \ No newline at end of file diff --git a/src/javascript/lib/processes/processes/otp/gen_server.js b/src/javascript/lib/processes/processes/otp/gen_server.js deleted file mode 100644 index 57d73090..00000000 --- a/src/javascript/lib/processes/processes/otp/gen_server.js +++ /dev/null @@ -1,74 +0,0 @@ -function start(module, args){ - return [Symbol.for("ok"), self.system.spawn(start_process(module, args))]; -} - -function start_link(module, args){ - return [Symbol.for("ok"), self.system.spawn_link(start_process(module, args))]; -} - -function start_process(module, args){ - return function*(){ - let [ok, state] = module.init.apply(null, [args]); - yield self.system.put("state", state); - - try{ - while(true){ - yield self.system.receive(function(args){ - let command = args[0]; - - switch(command){ - case "call": - var request = args[1]; - var sender = args[2]; - - var [reply, response, new_state] = module.handle_call(request, sender, self.system.get("state")); - self.system.put("state", new_state); - - self.system.send(sender, response); - break; - - case "cast": - var request = args[1]; - var sender = args[2]; - - var [reply, new_state] = module.handle_cast(request, self.system.get("state")); - - self.system.put("state", new_state); - self.system.send(args[2], Symbol.for("ok")); - - break; - - case "stop": - throw "stop"; - } - }); - } - }catch(e){ - if(e !== "stop"){ - throw e; - } - } - } -} - -function* call(server, request){ - self.system.send(server, ["call", request, self.system.pid()]); - - return yield self.system.receive(function(args){ - return args; - }); -} - -function* cast(server, request){ - self.system.send(server, ["cast", request, self.system.pid()]); - - return yield self.system.receive(function(args){ - return args; - }); -} - -function stop(server){ - self.system.send(server, ["stop"]); -} - -export default { start, start_link, call, cast, stop }; \ No newline at end of file diff --git a/src/javascript/lib/processes/processes/pid.js b/src/javascript/lib/processes/processes/pid.js deleted file mode 100644 index da45857c..00000000 --- a/src/javascript/lib/processes/processes/pid.js +++ /dev/null @@ -1,18 +0,0 @@ -"use strict"; -/* @flow */ - -let process_counter = -1; - -class PID { - constructor(){ - process_counter = process_counter + 1; - this.id = process_counter; - } - - toString(){ - return "PID#<0." + this.id + ".0>"; - } -} - - -export default PID; \ No newline at end of file diff --git a/src/javascript/lib/processes/processes/process.js b/src/javascript/lib/processes/processes/process.js deleted file mode 100644 index 007fa730..00000000 --- a/src/javascript/lib/processes/processes/process.js +++ /dev/null @@ -1,147 +0,0 @@ -"use strict"; - -/* @flow */ -import Mailbox from "./mailbox"; -import ProcessSystem from "./process_system"; -import States from "./states"; - -function is_sleep(value){ - return Array.isArray(value) && value[0] === States.SLEEP; -} - -function is_receive(value){ - return Array.isArray(value) && value[0] === States.RECEIVE; -} - -function receive_timed_out(value){ - return value[2] != null && value[2] < Date.now(); -} - -class Process { - pid: Number; - mailbox: Mailbox; - func: Function; - args: Array; - system: ProcessSystem; - status: Symbol; - dict: Object; - flags: Object; - - constructor(pid: Number, func: Function, args: Array, mailbox: Mailbox, system: ProcessSystem){ - this.pid = pid; - this.func = func; - this.args = args; - this.mailbox = mailbox; - this.system = system; - this.status = States.STOPPED; - this.dict = {}; - this.flags = {}; - } - - start(){ - const function_scope = this; - let machine = this.main(); - - this.system.schedule(function() { - function_scope.system.set_current(function_scope.pid); - function_scope.run(machine, machine.next()); - }, this.pid); - } - - *main() { - let retval = States.NORMAL; - - try { - yield* this.func.apply(null, this.args); - } catch(e) { - console.error(e); - retval = e; - } - - this.system.exit(retval); - } - - process_flag(flag, value){ - this.flags[flag] = value; - } - - is_trapping_exits(){ - return this.flags[Symbol.for("trap_exit")] && this.flags[Symbol.for("trap_exit")] == true; - } - - signal(reason){ - if(reason !== States.NORMAL){ - console.error(reason); - } - - this.system.remove_proc(this.pid, reason); - } - - receive(fun){ - let value = States.NOMATCH; - let messages = this.mailbox.get(); - - for(let i = 0; i < messages.length; i++){ - try{ - value = fun(messages[i]); - if(value !== States.NOMATCH){ - this.mailbox.removeAt(i); - break; - } - }catch(e){ - this.exit(e); - } - } - - return value; - } - - run(machine, step){ - const function_scope = this; - - if(!step.done){ - let value = step.value; - - if(is_sleep(value)){ - - this.system.delay(function() { - function_scope.system.set_current(function_scope.pid); - function_scope.run(machine, machine.next()); - }, value[1]); - - }else if(is_receive(value) && receive_timed_out(value)){ - - let result = value[3](); - - this.system.schedule(function() { - function_scope.system.set_current(function_scope.pid); - function_scope.run(machine, machine.next(result)); - }); - - }else if(is_receive(value)){ - - let result = function_scope.receive(value[1]); - - if(result === States.NOMATCH){ - this.system.suspend(function() { - function_scope.system.set_current(function_scope.pid); - function_scope.run(machine, step); - }); - }else{ - this.system.schedule(function() { - function_scope.system.set_current(function_scope.pid); - function_scope.run(machine, machine.next(result)); - }); - } - - }else{ - this.system.schedule(function() { - function_scope.system.set_current(function_scope.pid); - function_scope.run(machine, machine.next(value)); - }); - } - } - } -} - -export default Process; \ No newline at end of file diff --git a/src/javascript/lib/processes/processes/process_system.js b/src/javascript/lib/processes/processes/process_system.js deleted file mode 100644 index f67288af..00000000 --- a/src/javascript/lib/processes/processes/process_system.js +++ /dev/null @@ -1,257 +0,0 @@ -/* @flow */ -"use strict"; - -import Mailbox from "./mailbox"; -import Process from "./process"; -import States from "./states"; -import Scheduler from "./scheduler"; -import PID from "./pid"; - -class ProcessSystem { - - constructor(){ - this.pids = new Map(); - this.mailboxes = new Map(); - this.names = new Map(); - this.links = new Map(); - - const throttle = 5; //ms between scheduled tasks - this.current_process = null; - this.scheduler = new Scheduler(throttle); - this.suspended = new Map(); - - let process_system_scope = this; - this.main_process_pid = this.spawn(function*(){ - while(true){ - yield process_system_scope.sleep(10000); - } - }); - this.set_current(this.main_process_pid); - } - - static * run(fun, args, context = null){ - if(fun.constructor.name === "GeneratorFunction"){ - return yield* fun.apply(context, args); - }else{ - return fun.apply(context, args); - } - } - - spawn(...args){ - if(args.length === 1){ - let fun = args[0]; - return this.add_proc(fun, [], false).pid; - - }else if(args.length === 3){ - let mod = args[0]; - let fun = args[1]; - let the_args = args[2]; - - return this.add_proc(mod[fun], the_args, false).pid; - } - } - - spawn_link(...args){ - if(args.length === 1){ - let fun = args[0]; - return this.add_proc(fun, [], true).pid; - - }else if(args.length === 3){ - let mod = args[0]; - let fun = args[1]; - let the_args = args[2]; - - return this.add_proc(mod[fun], the_args, true).pid; - } - } - - link(pid){ - this.links.get(this.pid()).add(pid); - this.links.get(pid).add(this.pid()); - } - - unlink(pid){ - this.links.get(this.pid()).delete(pid); - this.links.get(pid).delete(this.pid()); - } - - set_current(id){ - let pid = this.pidof(id); - if(pid !== null){ - this.current_process = this.pids.get(pid); - this.current_process.status = States.RUNNING; - } - } - - add_proc(fun, args, linked){ - let newpid = new PID(); - let mailbox = new Mailbox(); - let newproc = new Process(newpid, fun, args, mailbox, this); - - this.pids.set(newpid, newproc); - this.mailboxes.set(newpid, mailbox); - this.links.set(newpid, new Set()); - - if(linked){ - this.link(newpid); - } - - newproc.start(); - return newproc; - } - - remove_proc(pid, exitreason){ - this.pids.delete(pid); - this.unregister(pid); - this.scheduler.removePid(pid); - - if(this.links.has(pid)){ - for (let linkpid of this.links.get(pid)) { - this.exit(linkpid, exitreason); - this.links.get(linkpid).delete(pid); - } - - this.links.delete(pid); - } - } - - register(name, pid){ - if(!this.names.has(name)){ - this.names.set(name, pid) - }else{ - throw new Error("Name is already registered to another process"); - } - } - - registered(name){ - return this.names.has(name) ? this.names.get(name) : null; - } - - unregister(pid){ - for(let name of this.names.keys()){ - if(this.names.has(name) && this.names.get(name) === pid){ - this.names.delete(name); - } - } - } - - pid(){ - return this.current_process.pid; - } - - pidof(id){ - if (id instanceof PID) { - return this.pids.has(id) ? id : null; - } else if (id instanceof Process) { - return id.pid; - } else { - let pid = this.registered(id); - if (pid === null) - throw("Process name not registered: " + id + " (" + typeof(id) + ")"); - return pid; - } - } - - send(id, msg) { - const pid = this.pidof(id); - - if(pid){ - this.mailboxes.get(pid).deliver(msg); - - if(this.suspended.has(pid)){ - let fun = this.suspended.get(pid); - this.suspended.delete(pid); - this.schedule(fun); - } - } - - return msg; - } - - receive(fun, timeout = 0, timeoutFn = () => true ) { - let DateTimeout = null; - - if(timeout === 0 || timeout === Infinity){ - DateTimeout = null; - }else{ - DateTimeout = Date.now() + timeout; - } - - return [ - States.RECEIVE, - fun, - DateTimeout, - timeoutFn - ]; - } - - sleep(duration){ - return [States.SLEEP, duration]; - } - - suspend(fun){ - this.current_process.status = States.SUSPENDED; - this.suspended.set(this.current_process.pid, fun); - } - - delay(fun, time){ - this.current_process.status = States.SLEEPING; - this.scheduler.scheduleFuture(this.current_process.pid, time, fun); - } - - schedule(fun, pid){ - const the_pid = pid != null ? pid : this.current_process.pid; - this.scheduler.schedule(the_pid, fun); - } - - exit(one, two){ - if(two){ - let pid = one; - let reason = two; - - let process = this.pids.get(this.pidof(pid)); - if((process && process.is_trapping_exits()) || reason === States.KILL || reason === States.NORMAL){ - this.mailboxes.get(process.pid).deliver([States.EXIT, this.pid(), reason ]); - }else{ - process.signal(reason); - } - }else{ - let reason = one; - this.current_process.signal(reason); - } - } - - error(reason){ - this.current_process.signal(reason); - } - - process_flag(flag, value){ - this.current_process.process_flag(flag, value); - } - - put(key, value){ - this.current_process.dict[key] = value; - } - - get(key){ - if(key != null){ - return this.current_process.dict[key]; - }else{ - return this.current_process.dict; - } - } - - get_keys(){ - return Object.keys(this.current_process.dict); - } - - erase(key){ - if(key != null){ - delete this.current_process.dict[key]; - }else{ - this.current_process.dict = {}; - } - } -} - -export default ProcessSystem; \ No newline at end of file diff --git a/src/javascript/lib/processes/processes/scheduler.js b/src/javascript/lib/processes/processes/scheduler.js deleted file mode 100644 index c7cec538..00000000 --- a/src/javascript/lib/processes/processes/scheduler.js +++ /dev/null @@ -1,103 +0,0 @@ -"use strict"; - -// A reduction is equal to a function call -const MAX_REDUCTIONS_PER_PROCESS = 8; - -class ProcessQueue { - constructor(pid){ - this.pid = pid; - this.tasks = []; - } - - empty(){ - return this.tasks.length === 0; - } - - add(task){ - this.tasks.push(task); - } - - next(){ - return this.tasks.shift(); - } -} - -class Scheduler { - constructor(throttle = 0){ - this.isRunning = false; - this.invokeLater = function (callback) { setTimeout(callback, throttle); } - this.queues = new Map(); - this.run(); - } - - addToQueue(pid, task){ - if(!this.queues.has(pid)){ - this.queues.set(pid, new ProcessQueue(pid)); - } - - this.queues.get(pid).add(task); - } - - removePid(pid){ - this.isRunning = true; - - this.queues.delete(pid); - - this.isRunning = false; - } - - run(){ - if (this.isRunning) { - this.invokeLater(() => { this.run(); }); - } else { - for(let [pid, queue] of this.queues){ - let reductions = 0; - while(queue && !queue.empty() && reductions < MAX_REDUCTIONS_PER_PROCESS){ - let task = queue.next(); - this.isRunning = true; - - let result; - - try{ - result = task(); - }catch(e){ - console.error(e); - result = e; - } - - this.isRunning = false; - - if (result instanceof Error) { - throw result; - } - - reductions++; - } - } - - this.invokeLater(() => { this.run(); }); - } - } - - addToScheduler(pid, task, dueTime = 0) { - if(dueTime === 0){ - this.invokeLater(() => { - this.addToQueue(pid, task); - }); - }else{ - setTimeout(() => { - this.addToQueue(pid, task); - }, dueTime); - } - }; - - schedule(pid, task){ - this.addToScheduler(pid, () => { task(); }); - } - - scheduleFuture(pid, dueTime, task){ - this.addToScheduler(pid, () => { task(); }, dueTime); - } -} - -export default Scheduler; \ No newline at end of file diff --git a/src/javascript/lib/signals.js b/src/javascript/lib/signals.js deleted file mode 100644 index 076f44f3..00000000 --- a/src/javascript/lib/signals.js +++ /dev/null @@ -1,61 +0,0 @@ -/* @flow */ - -import SpecialForms from './kernel/special_forms'; -import List from './list'; -import Enum from './enum'; - -class Signal { - bindings: Array; - - constructor() { - this.bindings = SpecialForms.list(); - } - - add(listener: Function, context: any = this): void { - this.bindings = List.append(this.bindings, new SignalBinding(this, listener, context)); - } - - remove(listener: Function): void { - this.bindings = Enum.filter(this.bindings, function(binding){ - return binding.listener !== listener; - }); - } - - dispatch(...params: Array): void { - for(let binding of this.bindings){ - binding.execute(...params); - } - } - - dispose(): void { - for(let binding of this.bindings){ - binding.dispose(); - } - - this.bindings = null; - } -} - -class SignalBinding { - listener: Function; - signal: Signal; - context: any; - - constructor(signal: Signal, listener: Function, context: any){ - this.listener = listener; - this.signal = signal; - this.context = context; - } - - execute(...params: Array): void { - this.listener.apply(this.context, params); - } - - dispose(): void { - this.listener = null; - this.signal = null; - this.context = null; - } -} - -export default Signal; \ No newline at end of file diff --git a/src/javascript/lib/string/chars.js b/src/javascript/lib/string/chars.js index 9a4318f1..a25ca004 100644 --- a/src/javascript/lib/string/chars.js +++ b/src/javascript/lib/string/chars.js @@ -2,6 +2,7 @@ import Kernel from "../kernel"; import Atom from "../atom"; import Integer from "../integer"; import List from "../list"; +import { Core } from "../core"; import Tuple from "../tuple"; import BitString from "../bit_string"; import { IntegerType, FloatType } from "../protocol"; @@ -48,7 +49,7 @@ Kernel.defimpl(Chars, Array, { } }); -Kernel.defimpl(Chars, Tuple, { +Kernel.defimpl(Chars, Core.Tuple, { to_string: function(thing){ return Tuple.to_string(thing); } diff --git a/src/javascript/lib/tuple.js b/src/javascript/lib/tuple.js index 08c4d17e..a334beca 100644 --- a/src/javascript/lib/tuple.js +++ b/src/javascript/lib/tuple.js @@ -1,90 +1,66 @@ import Kernel from './kernel'; -class Tuple { - - constructor(...args){ - this.values = Object.freeze(args); - } - - get(index) { - return this.values[index]; - } - - count() { - return this.values.length; - } +function to_string(tuple){ + return tuple.toString(); +}; - [Symbol.iterator]() { - return this.values[Symbol.iterator](); - } +function delete_at(tuple, index){ + let new_list = []; - toString() { - var i, s = ""; - for (i = 0; i < this.values.length; i++) { - if (s !== "") { - s += ", "; - } - s += this.values[i].toString(); + for (var i = 0; i < tuple.count(); i++) { + if(i !== index){ + new_list.push(tuple.get(i)); } - - return "{" + s + "}"; } - static to_string(tuple){ - return tuple.toString(); - }; + return Kernel.SpecialForms.tuple.apply(null, new_list); +}; - static delete_at(tuple, index){ - let new_list = []; - - for (var i = 0; i < tuple.count(); i++) { - if(i !== index){ - new_list.push(tuple.get(i)); - } - } +function duplicate(data, size){ + let array = []; - return Kernel.SpecialForms.tuple.apply(null, new_list); - }; - - static duplicate(data, size){ - let array = []; - - for (var i = size - 1; i >= 0; i--) { - array.push(data); - } + for (var i = size - 1; i >= 0; i--) { + array.push(data); + } - return Kernel.SpecialForms.tuple.apply(null, array); - }; + return Kernel.SpecialForms.tuple.apply(null, array); +}; - static insert_at(tuple, index, term){ - let new_tuple = []; +function insert_at(tuple, index, term){ + let new_tuple = []; - for (var i = 0; i <= tuple.count(); i++) { - if(i === index){ - new_tuple.push(term); - i++; - new_tuple.push(tuple.get(i)); - }else{ - new_tuple.push(tuple.get(i)); - } + for (var i = 0; i <= tuple.count(); i++) { + if(i === index){ + new_tuple.push(term); + i++; + new_tuple.push(tuple.get(i)); + }else{ + new_tuple.push(tuple.get(i)); } + } - return Kernel.SpecialForms.tuple.apply(null, new_tuple); - }; - - static from_list(list){ - return Kernel.SpecialForms.tuple.apply(null, list); - }; + return Kernel.SpecialForms.tuple.apply(null, new_tuple); +}; - static to_list(tuple){ - let new_list = []; +function from_list(list){ + return Kernel.SpecialForms.tuple.apply(null, list); +}; - for (var i = 0; i < tuple.count(); i++) { - new_list.push(tuple.get(i)); - } +function to_list(tuple){ + let new_list = []; - return Kernel.SpecialForms.list(...new_list); - }; -} + for (var i = 0; i < tuple.count(); i++) { + new_list.push(tuple.get(i)); + } -export default Tuple; \ No newline at end of file + return Kernel.SpecialForms.list(...new_list); +}; + +export default { + to_string, + delete_at, + duplicate, + insert_at, + from_list, + to_list +}; diff --git a/src/javascript/lib/view.js b/src/javascript/lib/view.js index 109001c9..64095f58 100644 --- a/src/javascript/lib/view.js +++ b/src/javascript/lib/view.js @@ -4,27 +4,29 @@ import VirtualDOM from './virtual-dom'; const start = function(domRoot, renderFn, initialState, options = []){ - const name = Keyword.has_key__qm__(options, Kernel.SpecialForms.atom("name")) ? Keyword.get(options, Kernel.SpecialForms.atom("name")) : Symbol(); + let pid = self.processes.spawn(); - self.post_office.add_mailbox(name); + if(Keyword.has_key__qm__(options, Kernel.SpecialForms.atom("name"))){ + pid = self.processes.register(Keyword.get(options, Kernel.SpecialForms.atom("name")), pid) + } const tree = renderFn.apply(this, initialState); const rootNode = VirtualDOM.create(tree); domRoot.appendChild(rootNode); - self.post_office.send(name, Kernel.SpecialForms.tuple(rootNode, tree, renderFn)); - return Kernel.SpecialForms.tuple(Kernel.SpecialForms.atom("ok"), name); + self.processes.put(pid, "state", Kernel.SpecialForms.tuple(rootNode, tree, renderFn)); + return Kernel.SpecialForms.tuple(Kernel.SpecialForms.atom("ok"), pid); } const stop = function(agent, timeout = 5000){ - self.post_office.remove_mailbox(agent); + self.processes.exit(agent); return Kernel.SpecialForms.atom("ok"); } const render = function(agent, state){ - const current_state = self.post_office.receive(agent); + const current_state = self.processes.get(agent, "state"); let rootNode = Kernel.elem(current_state, 0); let tree = Kernel.elem(current_state, 1); @@ -36,7 +38,7 @@ const render = function(agent, state){ rootNode = VirtualDOM.patch(rootNode, patches) - self.post_office.send(agent, Kernel.SpecialForms.tuple(rootNode, newTree, renderFn)); + self.processes.put(agent, "state", Kernel.SpecialForms.tuple(rootNode, newTree, renderFn)); return Kernel.SpecialForms.atom("ok"); } diff --git a/src/javascript/lib/virtual-dom.js b/src/javascript/lib/virtual-dom.js index af4bd974..f3238bc7 100644 --- a/src/javascript/lib/virtual-dom.js +++ b/src/javascript/lib/virtual-dom.js @@ -1,4 +1,4 @@ -let virtualDom = function(e) { +let VirtualDOM = function(e) { return e(); }(function() { var define, module, exports; @@ -1696,4 +1696,4 @@ function appendPatch(apply, patch) { },{"../vnode/handle-thunk":24,"../vnode/is-thunk":25,"../vnode/is-vnode":27,"../vnode/is-vtext":28,"../vnode/is-widget":29,"../vnode/vpatch":32,"./diff-props":34,"x-is-array":12}]},{},[4])(4) }); -export default virtualDom; +export default VirtualDOM; diff --git a/src/javascript/tests/patterns/defmatch.spec.js b/src/javascript/tests/patterns/defmatch.spec.js index 6bae9d39..4a1b4af2 100644 --- a/src/javascript/tests/patterns/defmatch.spec.js +++ b/src/javascript/tests/patterns/defmatch.spec.js @@ -1,6 +1,6 @@ var expect = require('chai').expect; var Patterns = require("../../lib/patterns/patterns"); -var Tuple = require("../../lib/tuple"); +var Tuple = require("../../lib/core").Core.Tuple; const _ = Patterns.wildcard(); const $ = Patterns.variable(); diff --git a/src/javascript/tests/string.chars.spec.js b/src/javascript/tests/string.chars.spec.js index 0f92c147..a68dc060 100644 --- a/src/javascript/tests/string.chars.spec.js +++ b/src/javascript/tests/string.chars.spec.js @@ -1,5 +1,5 @@ var String = require('../lib/string'); -var Tuple = require('../lib/tuple'); +var Tuple = require('../lib/core').Core.Tuple; var expect = require('chai').expect; describe('String.Chars', function(){ @@ -11,4 +11,4 @@ describe('String.Chars', function(){ expect(String.Chars.to_string([1, 2, 3])).to.equal("1,2,3"); }); -}); \ No newline at end of file +}); diff --git a/test/translator/assignment_test.exs b/test/translator/assignment_test.exs index 375285ef..d6fddcdb 100644 --- a/test/translator/assignment_test.exs +++ b/test/translator/assignment_test.exs @@ -19,7 +19,7 @@ defmodule ElixirScript.Translator.Assignment.Test do {a, b} = {1, 2} end js_code = """ - let [a, b] = Elixir.Patterns.match(Elixir.Patterns.type(Elixir.Tuple, { + let [a, b] = Elixir.Patterns.match(Elixir.Patterns.type(Elixir.Core.Tuple, { values: [Elixir.Patterns.variable(), Elixir.Patterns.variable()] }), Elixir.Kernel.SpecialForms.tuple(1, 2)); let _ref = Elixir.Kernel.SpecialForms.tuple(a, b); @@ -29,7 +29,7 @@ defmodule ElixirScript.Translator.Assignment.Test do ex_ast = quote do: {a, _, c} = {1, 2, 3} js_code = """ - let [a, undefined, c] = Elixir.Patterns.match(Elixir.Patterns.type(Elixir.Tuple, { + let [a, undefined, c] = Elixir.Patterns.match(Elixir.Patterns.type(Elixir.Core.Tuple, { values: [Elixir.Patterns.variable(), Elixir.Patterns.wildcard(), Elixir.Patterns.variable()] }), Elixir.Kernel.SpecialForms.tuple(1, 2, 3)); let _ref = Elixir.Kernel.SpecialForms.tuple(a, undefined, c); @@ -40,7 +40,7 @@ defmodule ElixirScript.Translator.Assignment.Test do ex_ast = quote do: {^a, _, c} = {1, 2, 3} js_code = """ - let [, undefined, c] = Elixir.Patterns.match(Elixir.Patterns.type(Elixir.Tuple, { + let [, undefined, c] = Elixir.Patterns.match(Elixir.Patterns.type(Elixir.Core.Tuple, { values: [Elixir.Patterns.bound(a), Elixir.Patterns.wildcard(), Elixir.Patterns.variable()] }), Elixir.Kernel.SpecialForms.tuple(1, 2, 3)); let _ref = Elixir.Kernel.SpecialForms.tuple(undefined, undefined, c); diff --git a/test/translator/case_test.exs b/test/translator/case_test.exs index fdc533b9..8ce15f99 100644 --- a/test/translator/case_test.exs +++ b/test/translator/case_test.exs @@ -118,7 +118,7 @@ defmodule ElixirScript.Translator.Case.Test do end js_code = """ - Elixir.Patterns.defmatch(Elixir.Patterns.make_case([Elixir.Patterns.type(Elixir.Tuple, { + Elixir.Patterns.defmatch(Elixir.Patterns.make_case([Elixir.Patterns.type(Elixir.Core.Tuple, { values: [Elixir.Patterns.variable(), Elixir.Patterns.variable()] })], function(one, two) { return console.info(one); @@ -141,8 +141,8 @@ defmodule ElixirScript.Translator.Case.Test do end js_code = """ - Elixir.Patterns.defmatch(Elixir.Patterns.make_case([Elixir.Patterns.type(Elixir.Tuple, { - values: [Elixir.Patterns.type(Elixir.Tuple, { + Elixir.Patterns.defmatch(Elixir.Patterns.make_case([Elixir.Patterns.type(Elixir.Core.Tuple, { + values: [Elixir.Patterns.type(Elixir.Core.Tuple, { values: [Elixir.Patterns.variable(), Elixir.Patterns.variable()] }), Elixir.Patterns.variable()] })], function(one, two, three) { @@ -164,8 +164,8 @@ defmodule ElixirScript.Translator.Case.Test do end js_code = """ - Elixir.Patterns.defmatch(Elixir.Patterns.make_case([Elixir.Patterns.type(Elixir.Tuple, { - values: [Elixir.Patterns.variable(), Elixir.Patterns.type(Elixir.Tuple, { + Elixir.Patterns.defmatch(Elixir.Patterns.make_case([Elixir.Patterns.type(Elixir.Core.Tuple, { + values: [Elixir.Patterns.variable(), Elixir.Patterns.type(Elixir.Core.Tuple, { values: [Elixir.Patterns.variable(), Elixir.Patterns.variable()] })] })], function(one, two, three) { diff --git a/test/translator/for_test.exs b/test/translator/for_test.exs index 73f49d76..236fad8b 100644 --- a/test/translator/for_test.exs +++ b/test/translator/for_test.exs @@ -110,7 +110,7 @@ defmodule ElixirScript.Translator.For.Test do end js_code = """ - Elixir.Kernel.SpecialForms._for(Elixir.Kernel.SpecialForms.list(Elixir.Kernel.SpecialForms.list(Elixir.Patterns.type(Elixir.Tuple,{ + Elixir.Kernel.SpecialForms._for(Elixir.Kernel.SpecialForms.list(Elixir.Kernel.SpecialForms.list(Elixir.Patterns.type(Elixir.Core.Tuple,{ values: [Elixir.Kernel.SpecialForms.atom('user'), Elixir.Patterns.variable()] }),Elixir.Kernel.SpecialForms.list(Elixir.Kernel.SpecialForms.tuple(Elixir.Kernel.SpecialForms.atom('user'),'john'),Elixir.Kernel.SpecialForms.tuple(Elixir.Kernel.SpecialForms.atom('admin'),'john'),Elixir.Kernel.SpecialForms.tuple(Elixir.Kernel.SpecialForms.atom('user'),'meg')))),function(name) { return Elixir.String.upcase(name); diff --git a/test/translator/function_test.exs b/test/translator/function_test.exs index 2ce50f8a..ed26e804 100644 --- a/test/translator/function_test.exs +++ b/test/translator/function_test.exs @@ -141,7 +141,7 @@ defmodule ElixirScript.Translator.Function.Test do js_code = """ const test1 = Elixir.Patterns.defmatch(Elixir.Patterns.make_case([Elixir.Patterns.variable(), Elixir.Patterns.variable()], function(alpha, beta) { - let [a0, b0] = Elixir.Patterns.match(Elixir.Patterns.type(Elixir.Tuple, { + let [a0, b0] = Elixir.Patterns.match(Elixir.Patterns.type(Elixir.Core.Tuple, { values: [Elixir.Patterns.variable(), Elixir.Patterns.variable()] }), Elixir.Kernel.SpecialForms.tuple(1, 2)); let _ref = Elixir.Kernel.SpecialForms.tuple(a0, b0); @@ -495,7 +495,7 @@ defmodule ElixirScript.Translator.Function.Test do js_code = """ - const something = Elixir.Patterns.defmatch(Elixir.Patterns.make_case([Elixir.Patterns.type(Elixir.Tuple, { + const something = Elixir.Patterns.defmatch(Elixir.Patterns.make_case([Elixir.Patterns.type(Elixir.Core.Tuple, { values: [Elixir.Patterns.variable(), Elixir.Patterns.variable()] })], function(apple, fruits) { return null; From 8c8cacc45b16eab215b3b022c1d730f9907bedeb Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Fri, 4 Dec 2015 12:54:37 -0600 Subject: [PATCH 069/860] Moved non-elixir standard library code to core module --- lib/elixir_script/pattern_matching/match.ex | 57 +++----- lib/elixir_script/translator/assignment.ex | 19 +-- lib/elixir_script/translator/bitstring.ex | 60 ++++---- lib/elixir_script/translator/function.ex | 39 +++-- lib/elixir_script/translator/primitive.ex | 7 - lib/elixir_script/translator/protocol.ex | 5 +- src/javascript/elixir.js | 9 +- src/javascript/lib/collectable.js | 3 +- src/javascript/lib/core.js | 18 ++- src/javascript/lib/{ => core}/bit_string.js | 0 .../lib/{js.js => core/functions.js} | 0 .../lib/{patterns => core}/patterns.js | 0 .../lib/{patterns => core}/patterns/checks.js | 0 .../{patterns => core}/patterns/defmatch.js | 0 .../lib/{patterns => core}/patterns/match.js | 0 .../lib/core/patterns/patterns/checks.js | 86 +++++++++++ .../{patterns => core}/patterns/resolvers.js | 0 .../lib/{patterns => core}/patterns/types.js | 0 src/javascript/lib/core/primitives.js | 5 +- src/javascript/lib/kernel.js | 10 +- src/javascript/lib/kernel/special_forms.js | 22 ++- src/javascript/lib/list/chars.js | 13 +- src/javascript/lib/protocol.js | 17 +-- src/javascript/lib/string/chars.js | 5 +- src/javascript/tests/bit_string.spec.js | 3 +- src/javascript/tests/for.spec.js | 4 +- .../tests/patterns/defmatch.spec.js | 4 +- src/javascript/tests/patterns/match.spec.js | 2 +- src/javascript/tests/string.chars.spec.js | 2 +- test/elixir_script_test.exs | 12 +- test/translator/assignment_test.exs | 22 +-- test/translator/bitstring_test.exs | 26 ++-- test/translator/bug_test.exs | 20 +-- test/translator/capture_test.exs | 16 +-- test/translator/case_test.exs | 68 ++++----- test/translator/cond_test.exs | 6 +- test/translator/defmodule_test.exs | 34 ++--- test/translator/for_test.exs | 18 +-- test/translator/function_test.exs | 136 +++++++++--------- test/translator/list_test.exs | 4 +- test/translator/protocol_test.exs | 20 +-- test/translator/receive_test.exs | 14 +- test/translator/struct_test.exs | 8 +- test/translator/try_test.exs | 22 +-- 44 files changed, 450 insertions(+), 366 deletions(-) rename src/javascript/lib/{ => core}/bit_string.js (100%) rename src/javascript/lib/{js.js => core/functions.js} (100%) rename src/javascript/lib/{patterns => core}/patterns.js (100%) rename src/javascript/lib/{patterns => core}/patterns/checks.js (100%) rename src/javascript/lib/{patterns => core}/patterns/defmatch.js (100%) rename src/javascript/lib/{patterns => core}/patterns/match.js (100%) create mode 100644 src/javascript/lib/core/patterns/patterns/checks.js rename src/javascript/lib/{patterns => core}/patterns/resolvers.js (100%) rename src/javascript/lib/{patterns => core}/patterns/types.js (100%) diff --git a/lib/elixir_script/pattern_matching/match.ex b/lib/elixir_script/pattern_matching/match.ex index 0749c489..e2c05403 100644 --- a/lib/elixir_script/pattern_matching/match.ex +++ b/lib/elixir_script/pattern_matching/match.ex @@ -8,60 +8,47 @@ defmodule ElixirScript.PatternMatching.Match do alias ElixirScript.Translator.Map alias ElixirScript.Translator.Struct - @wildcard JS.member_expression( - JS.identifier("Elixir"), + @patterns JS.member_expression( JS.member_expression( - JS.identifier(:Patterns), - JS.identifier(:wildcard) - ) + JS.identifier("Elixir"), + JS.identifier("Core") + ), + JS.identifier("Patterns") + ) + + @wildcard JS.member_expression( + @patterns, + JS.identifier(:wildcard) ) @parameter JS.member_expression( - JS.identifier("Elixir"), - JS.member_expression( - JS.identifier(:Patterns), - JS.identifier(:variable) - ) + @patterns, + JS.identifier(:variable) ) @head_tail JS.member_expression( - JS.identifier("Elixir"), - JS.member_expression( - JS.identifier(:Patterns), - JS.identifier(:headTail) - ) + @patterns, + JS.identifier(:headTail) ) @starts_with JS.member_expression( - JS.identifier("Elixir"), - JS.member_expression( - JS.identifier(:Patterns), - JS.identifier(:startsWith) - ) + @patterns, + JS.identifier(:startsWith) ) @capture JS.member_expression( - JS.identifier("Elixir"), - JS.member_expression( - JS.identifier(:Patterns), - JS.identifier(:capture) - ) + @patterns, + JS.identifier(:capture) ) @bound JS.member_expression( - JS.identifier("Elixir"), - JS.member_expression( - JS.identifier(:Patterns), - JS.identifier(:bound) - ) + @patterns, + JS.identifier(:bound) ) @_type JS.member_expression( - JS.identifier("Elixir"), - JS.member_expression( - JS.identifier(:Patterns), - JS.identifier(:type) - ) + @patterns, + JS.identifier(:type) ) def wildcard() do diff --git a/lib/elixir_script/translator/assignment.ex b/lib/elixir_script/translator/assignment.ex index 7511d06f..455a9a21 100644 --- a/lib/elixir_script/translator/assignment.ex +++ b/lib/elixir_script/translator/assignment.ex @@ -12,11 +12,14 @@ defmodule ElixirScript.Translator.Assignment do JS.array_pattern(params), JS.call_expression( JS.member_expression( - JS.identifier("Elixir"), JS.member_expression( - JS.identifier("Patterns"), - JS.identifier("match") - ) + JS.member_expression( + JS.identifier("Elixir"), + JS.identifier("Core") + ), + JS.identifier("Patterns") + ), + JS.identifier("match") ), [hd(patterns), Translator.translate(right, env)] ) @@ -32,7 +35,7 @@ defmodule ElixirScript.Translator.Assignment do {:{}, _, _} -> make_ref(array_pattern, params, "tuple") _ -> - array_pattern + array_pattern end end @@ -52,10 +55,10 @@ defmodule ElixirScript.Translator.Assignment do JS.identifier(type) ), params - ) + ) ) ref_declaration = JS.variable_declaration([ref_declarator], :let) - %ElixirScript.Translator.Group{ body: [array_pattern, ref_declaration] } + %ElixirScript.Translator.Group{ body: [array_pattern, ref_declaration] } end -end \ No newline at end of file +end diff --git a/lib/elixir_script/translator/bitstring.ex b/lib/elixir_script/translator/bitstring.ex index 101e1a7f..1b42cc7a 100644 --- a/lib/elixir_script/translator/bitstring.ex +++ b/lib/elixir_script/translator/bitstring.ex @@ -1,26 +1,26 @@ defmodule ElixirScript.Translator.Bitstring do @moduledoc false - alias ESTree.Tools.Builder + alias ESTree.Tools.Builder, as: JS alias ElixirScript.Translator alias ElixirScript.Translator.Primitive - + def make_bitstring(elements, env) do - Builder.call_expression( - Builder.member_expression( + JS.call_expression( + JS.member_expression( Primitive.special_forms(), - Builder.identifier("bitstring") + JS.identifier("bitstring") ), Enum.map(elements, &make_bitstring_element(&1, env)) ) end defp make_bitstring_element(element, env) when is_number(element) do - do_make_bitstring_element({:integer, Translator.translate(element, env)}) + do_make_bitstring_element({:integer, Translator.translate(element, env)}) end defp make_bitstring_element(element, env) when is_binary(element) do - do_make_bitstring_element({:binary, Translator.translate(element, env)}) + do_make_bitstring_element({:binary, Translator.translate(element, env)}) end defp make_bitstring_element({:<<>>, [], elements}, env) do @@ -28,24 +28,24 @@ defmodule ElixirScript.Translator.Bitstring do end defp make_bitstring_element({:::, _, [element, {type, _, _}]}, env) when type in [:integer, :float, :bitstring, :bits, :binary, :bytes, :utf8, :utf16, :utf32] do - do_make_bitstring_element({type, Translator.translate(element, env)}) + do_make_bitstring_element({type, Translator.translate(element, env)}) end defp make_bitstring_element({:::, _, [element, {type, _, params}]}, env) when type in [:size, :unit] do - do_make_bitstring_element({type, Translator.translate(element, env), Enum.map(params, &Translator.translate(&1, env))}) + do_make_bitstring_element({type, Translator.translate(element, env), Enum.map(params, &Translator.translate(&1, env))}) end defp make_bitstring_element({:::, _, [element, {:*, _, [size, unit]}]}, env) do size_ast = do_make_bitstring_element({:size, Translator.translate(element, env), [Translator.translate(size, env)]}) - do_make_bitstring_element({:unit, size_ast, [Translator.translate(unit, env)]}) + do_make_bitstring_element({:unit, size_ast, [Translator.translate(unit, env)]}) end defp make_bitstring_element({:::, _, [element, {:-, _, types}]}, env) do - handle_type_adjectives({:-, [], types}, Translator.translate(element, env), env) + handle_type_adjectives({:-, [], types}, Translator.translate(element, env), env) end defp make_bitstring_element({:::, _, [element, size]}, env) do - do_make_bitstring_element({:size, Translator.translate(element, env), [Translator.translate(size, env)]}) + do_make_bitstring_element({:size, Translator.translate(element, env), [Translator.translate(size, env)]}) end defp handle_type_adjectives({:-, _, types}, ast, env) do @@ -64,28 +64,38 @@ defmodule ElixirScript.Translator.Bitstring do end) end + defp bitstring_class() do + JS.member_expression( + JS.member_expression( + JS.identifier("Elixir"), + JS.identifier("Core") + ), + JS.identifier("BitString") + ) + end + defp do_make_bitstring_element({type, ast}) do - Builder.call_expression( - Builder.member_expression( - Builder.identifier("BitString"), - Builder.identifier(type) + JS.call_expression( + JS.member_expression( + bitstring_class, + JS.identifier(type) ), [ ast ] - ) + ) end defp do_make_bitstring_element({type, ast, params}) when is_list(params) do - Builder.call_expression( - Builder.member_expression( - Builder.identifier("BitString"), - Builder.identifier(type) + JS.call_expression( + JS.member_expression( + bitstring_class, + JS.identifier(type) ), [ ast ] ++ params - ) + ) end def make_interpolated_string(elements, env) do @@ -98,7 +108,7 @@ defmodule ElixirScript.Translator.Bitstring do end end) - do_make_interpolated_string(tl(translated_elements), hd(translated_elements), env) + do_make_interpolated_string(tl(translated_elements), hd(translated_elements), env) end def do_make_interpolated_string([], ast, _) do @@ -106,11 +116,11 @@ defmodule ElixirScript.Translator.Bitstring do end def do_make_interpolated_string(elements, ast, env) do - Builder.binary_expression( + JS.binary_expression( :+, ast, do_make_interpolated_string(tl(elements), hd(elements), env) ) end -end \ No newline at end of file +end diff --git a/lib/elixir_script/translator/function.ex b/lib/elixir_script/translator/function.ex index a08b38ad..6790624b 100644 --- a/lib/elixir_script/translator/function.ex +++ b/lib/elixir_script/translator/function.ex @@ -6,9 +6,17 @@ defmodule ElixirScript.Translator.Function do alias ElixirScript.PatternMatching.Match alias ElixirScript.Preprocess.Variables + @patterns JS.member_expression( + JS.member_expression( + JS.identifier("Elixir"), + JS.identifier("Core") + ), + JS.identifier("Patterns") + ) + @standard_libs [ :Patterns, :Kernel, :Atom, :Enum, :Integer, :JS, - :List, :Range, :Tuple, :Agent, :Keyword, :BitString, + :List, :Range, :Tuple, :Agent, :Keyword, :Base, :String, :Bitwise, :Collectable, :Enumerable, :Inspect, :Map, :MapSet, :Set, :VirtualDom, :View ] @@ -103,11 +111,8 @@ defmodule ElixirScript.Translator.Function do def make_defmatch(clauses) do JS.call_expression( JS.member_expression( - JS.identifier("Elixir"), - JS.member_expression( - JS.identifier("Patterns"), - JS.identifier("defmatch") - ) + @patterns, + JS.identifier("defmatch") ), clauses ) @@ -143,11 +148,8 @@ defmodule ElixirScript.Translator.Function do def do_make_function_clause(patterns, params, body, guard_body) do JS.call_expression( JS.member_expression( - JS.identifier("Elixir"), - JS.member_expression( - JS.identifier("Patterns"), - JS.identifier("make_case") - ) + @patterns, + JS.identifier("make_case") ), [ JS.array_expression(patterns), @@ -160,11 +162,8 @@ defmodule ElixirScript.Translator.Function do def do_make_function_clause(patterns, params, body) do JS.call_expression( JS.member_expression( - JS.identifier("Elixir"), - JS.member_expression( - JS.identifier("Patterns"), - JS.identifier("make_case") - ) + @patterns, + JS.identifier("make_case") ), [ JS.array_expression(patterns), @@ -192,11 +191,11 @@ defmodule ElixirScript.Translator.Function do JS.call_expression( JS.member_expression( - JS.identifier("Elixir"), JS.member_expression( - JS.identifier("JS"), - JS.identifier("call_property") - ) + JS.identifier("Elixir"), + JS.identifier("Core") + ), + JS.identifier("call_property") ), [ Utils.make_module_expression_tree(the_name, false, env), diff --git a/lib/elixir_script/translator/primitive.ex b/lib/elixir_script/translator/primitive.ex index 53c46aaa..d4b3f8e3 100644 --- a/lib/elixir_script/translator/primitive.ex +++ b/lib/elixir_script/translator/primitive.ex @@ -32,13 +32,6 @@ defmodule ElixirScript.Translator.Primitive do ) end - def make_wildcard() do - JS.member_expression( - JS.identifier("fun"), - JS.identifier("wildcard") - ) - end - def make_identifier({:__aliases__, _, aliases}) do Utils.make_module_expression_tree(aliases, false, __ENV__) end diff --git a/lib/elixir_script/translator/protocol.ex b/lib/elixir_script/translator/protocol.ex index 63e8acbd..9c85a5c6 100644 --- a/lib/elixir_script/translator/protocol.ex +++ b/lib/elixir_script/translator/protocol.ex @@ -207,7 +207,10 @@ defmodule ElixirScript.Translator.Protocol do defp map_to_js({:__aliases__, _, [:BitString]}) do JS.member_expression( - JS.identifier(:Elixir), + JS.member_expression( + JS.identifier(:Elixir), + JS.identifier(:Core) + ), JS.identifier(:BitString) ) end diff --git a/src/javascript/elixir.js b/src/javascript/elixir.js index 41b33761..a81e366a 100644 --- a/src/javascript/elixir.js +++ b/src/javascript/elixir.js @@ -1,15 +1,13 @@ -import {ProcessSystem} from './lib/core'; +import * as Core from "./lib/core"; -self.processes = self.processes || new ProcessSystem(); +self.processes = self.processes || new Core.ProcessSystem(); -export { Core } from './lib/core'; +export Core; export { default as Patterns } from './lib/patterns/patterns'; -export { default as BitString } from './lib/bit_string'; export { default as Kernel } from './lib/kernel'; export { default as Atom } from './lib/atom'; export { default as Enum } from './lib/enum'; export { default as Integer } from './lib/integer'; -export { default as JS } from './lib/js'; export { default as List } from './lib/list'; export { default as Range } from './lib/range'; export { default as Tuple } from './lib/tuple'; @@ -24,6 +22,5 @@ export { default as Inspect } from './lib/inspect'; export { default as Map } from './lib/map'; export { default as Set } from './lib/set'; export { default as MapSet } from './lib/map_set'; -export { IntegerType, FloatType } from './lib/protocol'; export { default as VirtualDOM } from './lib/virtual-dom'; export { default as View } from './lib/view'; diff --git a/src/javascript/lib/collectable.js b/src/javascript/lib/collectable.js index 6462da3a..20c97abf 100644 --- a/src/javascript/lib/collectable.js +++ b/src/javascript/lib/collectable.js @@ -1,9 +1,8 @@ import Kernel from "./kernel"; -import Patterns from "./patterns/patterns"; import List from "./list"; let Collectable = Kernel.defprotocol({ into: function(collectable){} }); -export default Collectable; \ No newline at end of file +export default Collectable; diff --git a/src/javascript/lib/core.js b/src/javascript/lib/core.js index c7625a73..278bbf93 100644 --- a/src/javascript/lib/core.js +++ b/src/javascript/lib/core.js @@ -1,2 +1,16 @@ -export { default as ProcessSystem } from './core/process_system'; -export { default as Core } from './core/primitives'; +import ProcessSystem from './core/process_system'; +import { Tuple, PID, IntegerType, FloatType } from './core/primitives'; +import BitString from './core/bit_string'; +import * as Patterns from './core/patterns'; +import { call_property } from './core/functions'; + +export { + ProcessSystem, + Tuple, + PID, + BitString, + Patterns, + IntegerType, + FloatType, + call_property +} diff --git a/src/javascript/lib/bit_string.js b/src/javascript/lib/core/bit_string.js similarity index 100% rename from src/javascript/lib/bit_string.js rename to src/javascript/lib/core/bit_string.js diff --git a/src/javascript/lib/js.js b/src/javascript/lib/core/functions.js similarity index 100% rename from src/javascript/lib/js.js rename to src/javascript/lib/core/functions.js diff --git a/src/javascript/lib/patterns/patterns.js b/src/javascript/lib/core/patterns.js similarity index 100% rename from src/javascript/lib/patterns/patterns.js rename to src/javascript/lib/core/patterns.js diff --git a/src/javascript/lib/patterns/patterns/checks.js b/src/javascript/lib/core/patterns/checks.js similarity index 100% rename from src/javascript/lib/patterns/patterns/checks.js rename to src/javascript/lib/core/patterns/checks.js diff --git a/src/javascript/lib/patterns/patterns/defmatch.js b/src/javascript/lib/core/patterns/defmatch.js similarity index 100% rename from src/javascript/lib/patterns/patterns/defmatch.js rename to src/javascript/lib/core/patterns/defmatch.js diff --git a/src/javascript/lib/patterns/patterns/match.js b/src/javascript/lib/core/patterns/match.js similarity index 100% rename from src/javascript/lib/patterns/patterns/match.js rename to src/javascript/lib/core/patterns/match.js diff --git a/src/javascript/lib/core/patterns/patterns/checks.js b/src/javascript/lib/core/patterns/patterns/checks.js new file mode 100644 index 00000000..1840e5c4 --- /dev/null +++ b/src/javascript/lib/core/patterns/patterns/checks.js @@ -0,0 +1,86 @@ +/* @flow */ + +import { Variable, Wildcard, HeadTail, Capture, Type, StartsWith, Bound } from "./types"; + +function is_number(value: any): boolean { + return typeof value === 'number'; +} + +function is_string(value: any): boolean{ + return typeof value === 'string'; +} + +function is_boolean(value: any): boolean { + return typeof value === 'boolean'; +} + +function is_symbol(value: any): boolean { + return typeof value === 'symbol'; +} + +function is_null(value: any): boolean { + return value === null; +} + +function is_undefined(value: any): boolean { + return typeof value === 'undefined'; +} + +function is_function(value: any): boolean { + return Object.prototype.toString.call(value) == '[object Function]'; +} + +function is_variable(value: any): boolean { + return value instanceof Variable; +} + +function is_wildcard(value: any): boolean { + return value instanceof Wildcard; +} + +function is_headTail(value: any): boolean { + return value instanceof HeadTail; +} + +function is_capture(value: any): boolean { + return value instanceof Capture; +} + +function is_type(value: any): boolean { + return value instanceof Type; +} + +function is_startsWith(value: any): boolean { + return value instanceof StartsWith; +} + +function is_bound(value: any): boolean { + return value instanceof Bound; +} + +function is_object(value: any): boolean { + return typeof value === 'object'; +} + +function is_array(value: any): boolean { + return Array.isArray(value); +} + +export default { + is_number, + is_string, + is_boolean, + is_symbol, + is_null, + is_undefined, + is_function, + is_variable, + is_wildcard, + is_headTail, + is_capture, + is_type, + is_startsWith, + is_bound, + is_object, + is_array +}; diff --git a/src/javascript/lib/patterns/patterns/resolvers.js b/src/javascript/lib/core/patterns/resolvers.js similarity index 100% rename from src/javascript/lib/patterns/patterns/resolvers.js rename to src/javascript/lib/core/patterns/resolvers.js diff --git a/src/javascript/lib/patterns/patterns/types.js b/src/javascript/lib/core/patterns/types.js similarity index 100% rename from src/javascript/lib/patterns/patterns/types.js rename to src/javascript/lib/core/patterns/types.js diff --git a/src/javascript/lib/core/primitives.js b/src/javascript/lib/core/primitives.js index dca6a5a3..6781e57a 100644 --- a/src/javascript/lib/core/primitives.js +++ b/src/javascript/lib/core/primitives.js @@ -44,4 +44,7 @@ class PID { } } -export default { PID, Tuple }; +class IntegerType {} +class FloatType {} + +export default { PID, Tuple, IntegerType, FloatType }; diff --git a/src/javascript/lib/kernel.js b/src/javascript/lib/kernel.js index 8741d856..c634f7b6 100644 --- a/src/javascript/lib/kernel.js +++ b/src/javascript/lib/kernel.js @@ -1,9 +1,7 @@ import SpecialForms from './kernel/special_forms'; -import Patterns from './patterns/patterns'; -import { Core } from "./core"; +import * as Core from './core'; import Tuple from "./tuple"; -import BitString from './bit_string'; -import { Protocol } from './protocol'; +import Protocol from './protocol'; function tl(list){ return SpecialForms.list(...list.slice(1)); @@ -74,7 +72,7 @@ function is_reference(x){ } function is_bitstring(x){ - return is_binary(x) || x instanceof BitString; + return is_binary(x) || x instanceof Core.BitString; } function __in__(left, right){ @@ -146,7 +144,7 @@ function to_string(arg){ } function match__qmark__(pattern, expr, guard = () => true){ - return Patterns.match_no_throw(pattern, expr, guard) != null; + return Core.Patterns.match_no_throw(pattern, expr, guard) != null; } function defstruct(defaults){ diff --git a/src/javascript/lib/kernel/special_forms.js b/src/javascript/lib/kernel/special_forms.js index addf88ce..ad4e7bef 100644 --- a/src/javascript/lib/kernel/special_forms.js +++ b/src/javascript/lib/kernel/special_forms.js @@ -1,7 +1,5 @@ -import BitString from '../bit_string'; -import { Core } from '../core'; +import * as Core from '../core'; import Enum from '../enum'; -import * as Patterns from '../patterns/patterns'; let SpecialForms = { @@ -26,15 +24,15 @@ let SpecialForms = { }, bitstring: function(...args){ - return new BitString(...args); + return new Core.BitString(...args); }, bound: function(_var){ - return Patterns.bound(_var); + return Core.Patterns.bound(_var); }, _case: function(condition, clauses){ - return Patterns.defmatch(...clauses)(condition); + return Core.Patterns.defmatch(...clauses)(condition); }, cond: function(clauses){ @@ -48,7 +46,7 @@ let SpecialForms = { }, fn: function(clauses){ - return Patterns.defmatch(clauses); + return Core.Patterns.defmatch(clauses); }, map: function(obj){ @@ -70,7 +68,7 @@ let SpecialForms = { if(collections.length === 1){ for(let elem of collection){ - let r = Patterns.match_no_throw(pattern, elem); + let r = Core.Patterns.match_no_throw(pattern, elem); let args = previousValues.concat(r); if(r && filter.apply(this, args)){ @@ -83,7 +81,7 @@ let SpecialForms = { let _into = [] for(let elem of collection){ - let r = Patterns.match_no_throw(pattern, elem); + let r = Core.Patterns.match_no_throw(pattern, elem); if(r){ _into = Enum.into(this._for(collections.slice(1), fun, filter, _into, previousValues.concat(r)), into); } @@ -142,7 +140,7 @@ let SpecialForms = { ex_result = rescue_function(e); return ex_result; }catch(ex){ - if(ex instanceof Patterns.MatchError){ + if(ex instanceof Core.Patterns.MatchError){ throw ex; } } @@ -153,7 +151,7 @@ let SpecialForms = { ex_result = catch_fun(e); return ex_result; }catch(ex){ - if(ex instanceof Patterns.MatchError){ + if(ex instanceof Core.Patterns.MatchError){ throw ex; } } @@ -171,7 +169,7 @@ let SpecialForms = { try{ return else_function(result); }catch(ex){ - if(ex instanceof Patterns.MatchError){ + if(ex instanceof Core.Patterns.MatchError){ throw new Error("No Match Found in Else"); } diff --git a/src/javascript/lib/list/chars.js b/src/javascript/lib/list/chars.js index 03bf1bda..842e384b 100644 --- a/src/javascript/lib/list/chars.js +++ b/src/javascript/lib/list/chars.js @@ -1,14 +1,15 @@ import Kernel from "../kernel"; import Atom from "../atom"; import Integer from "../integer"; -import List from "../list"; import String from "../string"; +import * as Core from '../core'; +import { IntegerType, FloatType } from "../protocol"; let Chars = Kernel.defprotocol({ to_char_list: function(thing){} }); -Kernel.defimpl(Chars, Kernel.is_bitstring, { +Kernel.defimpl(Chars, Core.BitString, { to_char_list: function(thing){ if(Kernel.is_binary(thing)){ return String.to_char_list(thing); @@ -18,23 +19,23 @@ Kernel.defimpl(Chars, Kernel.is_bitstring, { } }); -Kernel.defimpl(Chars, Kernel.is_atom, { +Kernel.defimpl(Chars, Symbol, { to_char_list: function(thing){ return Atom.to_char_list(thing); } }); -Kernel.defimpl(Chars, Kernel.is_integer, { +Kernel.defimpl(Chars, IntegerType, { to_char_list: function(thing){ return Integer.to_char_list(thing); } }); -Kernel.defimpl(Chars, Kernel.is_list, { +Kernel.defimpl(Chars, Array, { to_char_list: function(thing){ return thing; } }); -export default Chars; \ No newline at end of file +export default Chars; diff --git a/src/javascript/lib/protocol.js b/src/javascript/lib/protocol.js index 29cfe0ff..e135b385 100644 --- a/src/javascript/lib/protocol.js +++ b/src/javascript/lib/protocol.js @@ -1,5 +1,4 @@ -class IntegerType {} -class FloatType {} +import * as Core from './core'; //https://github.com/airportyh/protomorphism class Protocol{ @@ -17,10 +16,10 @@ class Protocol{ let thing = args[0]; let fun = null; - if(Number.isInteger(thing) && this.hasImplementation(IntegerType)){ - fun = this.registry.get(IntegerType)[funName]; - }else if(typeof thing === "number" && !Number.isInteger(thing) && this.hasImplementation(FloatType)){ - fun = this.registry.get(FloatType)[funName]; + if(Number.isInteger(thing) && this.hasImplementation(Core.IntegerType)){ + fun = this.registry.get(Core.IntegerType)[funName]; + }else if(typeof thing === "number" && !Number.isInteger(thing) && this.hasImplementation(Core.FloatType)){ + fun = this.registry.get(Core.FloatType)[funName]; }else if(this.hasImplementation(thing)){ fun = this.registry.get(thing.constructor)[funName]; }else if(this.fallback){ @@ -51,8 +50,4 @@ class Protocol{ } -export { - Protocol, - IntegerType, - FloatType -} +export default Protocol; diff --git a/src/javascript/lib/string/chars.js b/src/javascript/lib/string/chars.js index a25ca004..f68f6907 100644 --- a/src/javascript/lib/string/chars.js +++ b/src/javascript/lib/string/chars.js @@ -2,16 +2,15 @@ import Kernel from "../kernel"; import Atom from "../atom"; import Integer from "../integer"; import List from "../list"; -import { Core } from "../core"; +import * as Core from '../core'; import Tuple from "../tuple"; -import BitString from "../bit_string"; import { IntegerType, FloatType } from "../protocol"; let Chars = Kernel.defprotocol({ to_string: function(thing){} }); -Kernel.defimpl(Chars, BitString, { +Kernel.defimpl(Chars, Core.BitString, { to_string: function(thing){ if(Kernel.is_binary(thing)){ return thing; diff --git a/src/javascript/tests/bit_string.spec.js b/src/javascript/tests/bit_string.spec.js index 9ba94106..f1d8f642 100644 --- a/src/javascript/tests/bit_string.spec.js +++ b/src/javascript/tests/bit_string.spec.js @@ -1,4 +1,4 @@ -var BitString = require('../lib/bit_string'); +var BitString = require('../lib/core').BitString; var Kernel = require('../lib/kernel'); var expect = require('chai').expect; @@ -52,4 +52,3 @@ describe('BitString', function(){ }); }); }); - diff --git a/src/javascript/tests/for.spec.js b/src/javascript/tests/for.spec.js index 7045a78c..7bee1b0e 100644 --- a/src/javascript/tests/for.spec.js +++ b/src/javascript/tests/for.spec.js @@ -1,4 +1,4 @@ -var Patterns = require("../lib/patterns/patterns"); +var Patterns = require("../lib/core").Patterns; var Enum = require('../lib/enum'); var Kernel = require('../lib/kernel'); var expect = require('chai').expect; @@ -52,4 +52,4 @@ describe('for', () => { expect(result).to.eql(["JOHN", "MEG"]); }); -}); \ No newline at end of file +}); diff --git a/src/javascript/tests/patterns/defmatch.spec.js b/src/javascript/tests/patterns/defmatch.spec.js index 4a1b4af2..fcc74c85 100644 --- a/src/javascript/tests/patterns/defmatch.spec.js +++ b/src/javascript/tests/patterns/defmatch.spec.js @@ -1,6 +1,6 @@ var expect = require('chai').expect; -var Patterns = require("../../lib/patterns/patterns"); -var Tuple = require("../../lib/core").Core.Tuple; +var Patterns = require("../../lib/core").Patterns; +var Tuple = require("../../lib/core").Tuple; const _ = Patterns.wildcard(); const $ = Patterns.variable(); diff --git a/src/javascript/tests/patterns/match.spec.js b/src/javascript/tests/patterns/match.spec.js index 85f40631..13045e82 100644 --- a/src/javascript/tests/patterns/match.spec.js +++ b/src/javascript/tests/patterns/match.spec.js @@ -1,5 +1,5 @@ var expect = require('chai').expect; -var Patterns = require("../../lib/patterns/patterns"); +var Patterns = require("../../lib/core").Patterns; const _ = Patterns.wildcard(); const $ = Patterns.variable(); diff --git a/src/javascript/tests/string.chars.spec.js b/src/javascript/tests/string.chars.spec.js index a68dc060..3932aa96 100644 --- a/src/javascript/tests/string.chars.spec.js +++ b/src/javascript/tests/string.chars.spec.js @@ -1,5 +1,5 @@ var String = require('../lib/string'); -var Tuple = require('../lib/core').Core.Tuple; +var Tuple = require('../lib/core').Tuple; var expect = require('chai').expect; describe('String.Chars', function(){ diff --git a/test/elixir_script_test.exs b/test/elixir_script_test.exs index 4d7dbe42..d7dc6625 100644 --- a/test/elixir_script_test.exs +++ b/test/elixir_script_test.exs @@ -36,10 +36,10 @@ defmodule ElixirScript.Test do assert_js_matches """ import * as Elixir from 'elixir'; const __MODULE__ = Elixir.Kernel.SpecialForms.atom('Elephant'); - const something_else = Elixir.Patterns.defmatch(Elixir.Patterns.make_case([],function() { + const something_else = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([],function() { return Elixir.String.Chars.to_string(10); })); - const something = Elixir.Patterns.defmatch(Elixir.Patterns.make_case([],function() { + const something = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([],function() { return ul; })); const ul = JQuery('#todo-list'); @@ -107,10 +107,10 @@ defmodule ElixirScript.Test do assert_js_matches """ import * as Elixir from 'elixir'; const __MODULE__ = Elixir.Kernel.SpecialForms.atom('Animals'); - const something_else = Elixir.Patterns.defmatch(Elixir.Patterns.make_case([],function() { + const something_else = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([],function() { return 1 * 1; })); - const sandwich = Elixir.Patterns.defmatch(Elixir.Patterns.make_case([],function() { + const sandwich = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([],function() { return null; })); export { @@ -158,10 +158,10 @@ defmodule ElixirScript.Test do assert_js_matches """ import * as Elixir from 'elixirscript'; const __MODULE__ = Elixir.Kernel.SpecialForms.atom('Animals'); - const something_else = Elixir.Patterns.defmatch(Elixir.Patterns.make_case([],function() { + const something_else = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([],function() { return 1 * 1; })); - const sandwich = Elixir.Patterns.defmatch(Elixir.Patterns.make_case([],function() { + const sandwich = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([],function() { return null; })); export { diff --git a/test/translator/assignment_test.exs b/test/translator/assignment_test.exs index d6fddcdb..1c588a4e 100644 --- a/test/translator/assignment_test.exs +++ b/test/translator/assignment_test.exs @@ -4,12 +4,12 @@ defmodule ElixirScript.Translator.Assignment.Test do should "translate simple assignment" do ex_ast = quote do: a = 1 - js_code = "let [a] = Elixir.Patterns.match(Elixir.Patterns.variable(), 1);" + js_code = "let [a] = Elixir.Core.Patterns.match(Elixir.Core.Patterns.variable(), 1);" assert_translation(ex_ast, js_code) ex_ast = quote do: a = :atom - js_code = "let [a] = Elixir.Patterns.match(Elixir.Patterns.variable(), Elixir.Kernel.SpecialForms.atom('atom'));" + js_code = "let [a] = Elixir.Core.Patterns.match(Elixir.Core.Patterns.variable(), Elixir.Kernel.SpecialForms.atom('atom'));" assert_translation(ex_ast, js_code) end @@ -19,8 +19,8 @@ defmodule ElixirScript.Translator.Assignment.Test do {a, b} = {1, 2} end js_code = """ - let [a, b] = Elixir.Patterns.match(Elixir.Patterns.type(Elixir.Core.Tuple, { - values: [Elixir.Patterns.variable(), Elixir.Patterns.variable()] + let [a, b] = Elixir.Core.Patterns.match(Elixir.Core.Patterns.type(Elixir.Core.Tuple, { + values: [Elixir.Core.Patterns.variable(), Elixir.Core.Patterns.variable()] }), Elixir.Kernel.SpecialForms.tuple(1, 2)); let _ref = Elixir.Kernel.SpecialForms.tuple(a, b); """ @@ -29,8 +29,8 @@ defmodule ElixirScript.Translator.Assignment.Test do ex_ast = quote do: {a, _, c} = {1, 2, 3} js_code = """ - let [a, undefined, c] = Elixir.Patterns.match(Elixir.Patterns.type(Elixir.Core.Tuple, { - values: [Elixir.Patterns.variable(), Elixir.Patterns.wildcard(), Elixir.Patterns.variable()] + let [a, undefined, c] = Elixir.Core.Patterns.match(Elixir.Core.Patterns.type(Elixir.Core.Tuple, { + values: [Elixir.Core.Patterns.variable(), Elixir.Core.Patterns.wildcard(), Elixir.Core.Patterns.variable()] }), Elixir.Kernel.SpecialForms.tuple(1, 2, 3)); let _ref = Elixir.Kernel.SpecialForms.tuple(a, undefined, c); """ @@ -40,8 +40,8 @@ defmodule ElixirScript.Translator.Assignment.Test do ex_ast = quote do: {^a, _, c} = {1, 2, 3} js_code = """ - let [, undefined, c] = Elixir.Patterns.match(Elixir.Patterns.type(Elixir.Core.Tuple, { - values: [Elixir.Patterns.bound(a), Elixir.Patterns.wildcard(), Elixir.Patterns.variable()] + let [, undefined, c] = Elixir.Core.Patterns.match(Elixir.Core.Patterns.type(Elixir.Core.Tuple, { + values: [Elixir.Core.Patterns.bound(a), Elixir.Core.Patterns.wildcard(), Elixir.Core.Patterns.variable()] }), Elixir.Kernel.SpecialForms.tuple(1, 2, 3)); let _ref = Elixir.Kernel.SpecialForms.tuple(undefined, undefined, c); """ @@ -52,7 +52,7 @@ defmodule ElixirScript.Translator.Assignment.Test do should "translate bound assignment" do ex_ast = quote do: ^a = 1 js_code = """ - let [] = Elixir.Patterns.match(Elixir.Patterns.bound(a),1); + let [] = Elixir.Core.Patterns.match(Elixir.Core.Patterns.bound(a),1); """ assert_translation(ex_ast, js_code) @@ -61,7 +61,7 @@ defmodule ElixirScript.Translator.Assignment.Test do should "translate list assignment" do ex_ast = quote do: [a, b] = [1, 2] js_code = """ - let [a, b] = Elixir.Patterns.match(Elixir.Kernel.SpecialForms.list(Elixir.Patterns.variable(), Elixir.Patterns.variable()), Elixir.Kernel.SpecialForms.list(1, 2)); + let [a, b] = Elixir.Core.Patterns.match(Elixir.Kernel.SpecialForms.list(Elixir.Core.Patterns.variable(), Elixir.Core.Patterns.variable()), Elixir.Kernel.SpecialForms.list(1, 2)); let _ref = Elixir.Kernel.SpecialForms.list(a, b); """ @@ -71,7 +71,7 @@ defmodule ElixirScript.Translator.Assignment.Test do should "translate head/tail assignment" do ex_ast = quote do: [a | b] = [1, 2, 3, 4] js_code = """ - let [a,b] = Elixir.Patterns.match(Elixir.Patterns.headTail(),Elixir.Kernel.SpecialForms.list(1,2,3,4)); + let [a,b] = Elixir.Core.Patterns.match(Elixir.Core.Patterns.headTail(),Elixir.Kernel.SpecialForms.list(1,2,3,4)); let _ref = Elixir.Kernel.SpecialForms.list(a,b); """ diff --git a/test/translator/bitstring_test.exs b/test/translator/bitstring_test.exs index be7c3e24..d2e1a335 100644 --- a/test/translator/bitstring_test.exs +++ b/test/translator/bitstring_test.exs @@ -4,39 +4,39 @@ defmodule ElixirScript.Translator.Bitstring.Test do should "translate bitstring" do ex_ast = quote do: <<1, 2, 3>> - assert_translation(ex_ast, "Elixir.Kernel.SpecialForms.bitstring(BitString.integer(1), BitString.integer(2), BitString.integer(3))") + assert_translation(ex_ast, "Elixir.Kernel.SpecialForms.bitstring(Elixir.Core.BitString.integer(1), Elixir.Core.BitString.integer(2), Elixir.Core.BitString.integer(3))") ex_ast = quote do: <<1, "foo">> - assert_translation(ex_ast, "Elixir.Kernel.SpecialForms.bitstring(BitString.integer(1), BitString.binary('foo'))") + assert_translation(ex_ast, "Elixir.Kernel.SpecialForms.bitstring(Elixir.Core.BitString.integer(1), Elixir.Core.BitString.binary('foo'))") ex_ast = quote do: <<1, "foo" :: binary>> - assert_translation(ex_ast, "Elixir.Kernel.SpecialForms.bitstring(BitString.integer(1), BitString.binary('foo'))") + assert_translation(ex_ast, "Elixir.Kernel.SpecialForms.bitstring(Elixir.Core.BitString.integer(1), Elixir.Core.BitString.binary('foo'))") ex_ast = quote do: <<1, "foo" :: utf8, "bar" :: utf32>> - assert_translation(ex_ast, "Elixir.Kernel.SpecialForms.bitstring(BitString.integer(1), BitString.utf8('foo'), BitString.utf32('bar'))") + assert_translation(ex_ast, "Elixir.Kernel.SpecialForms.bitstring(Elixir.Core.BitString.integer(1), Elixir.Core.BitString.utf8('foo'), Elixir.Core.BitString.utf32('bar'))") ex_ast = quote do: <<102 :: integer-native, rest :: binary>> - assert_translation(ex_ast, "Elixir.Kernel.SpecialForms.bitstring(BitString.native(BitString.integer(102)), BitString.binary(rest))") + assert_translation(ex_ast, "Elixir.Kernel.SpecialForms.bitstring(Elixir.Core.BitString.native(Elixir.Core.BitString.integer(102)), Elixir.Core.BitString.binary(rest))") ex_ast = quote do: <<102 :: unsigned-big-integer, rest :: binary>> - assert_translation(ex_ast, "Elixir.Kernel.SpecialForms.bitstring(BitString.integer(BitString.big(BitString.unsigned(102))), BitString.binary(rest))") + assert_translation(ex_ast, "Elixir.Kernel.SpecialForms.bitstring(Elixir.Core.BitString.integer(Elixir.Core.BitString.big(Elixir.Core.BitString.unsigned(102))), Elixir.Core.BitString.binary(rest))") ex_ast = quote do: <<102, _rest :: size(16)>> - assert_translation(ex_ast, "Elixir.Kernel.SpecialForms.bitstring(BitString.integer(102), BitString.size(_rest, 16))") + assert_translation(ex_ast, "Elixir.Kernel.SpecialForms.bitstring(Elixir.Core.BitString.integer(102), Elixir.Core.BitString.size(_rest, 16))") ex_ast = quote do: <<102, _rest :: size(16)-unit(4)>> - assert_translation(ex_ast, "Elixir.Kernel.SpecialForms.bitstring(BitString.integer(102), BitString.unit(BitString.size(_rest, 16), 4))") + assert_translation(ex_ast, "Elixir.Kernel.SpecialForms.bitstring(Elixir.Core.BitString.integer(102), Elixir.Core.BitString.unit(Elixir.Core.BitString.size(_rest, 16), 4))") ex_ast = quote do: <<102, _rest :: 16 * 4>> - assert_translation(ex_ast, "Elixir.Kernel.SpecialForms.bitstring(BitString.integer(102), BitString.unit(BitString.size(_rest, 16), 4))") + assert_translation(ex_ast, "Elixir.Kernel.SpecialForms.bitstring(Elixir.Core.BitString.integer(102), Elixir.Core.BitString.unit(Elixir.Core.BitString.size(_rest, 16), 4))") ex_ast = quote do: <<102, _rest :: _ * 4>> - assert_translation(ex_ast, "Elixir.Kernel.SpecialForms.bitstring(BitString.integer(102), BitString.unit(BitString.size(_rest, undefined), 4))") + assert_translation(ex_ast, "Elixir.Kernel.SpecialForms.bitstring(Elixir.Core.BitString.integer(102), Elixir.Core.BitString.unit(Elixir.Core.BitString.size(_rest, undefined), 4))") ex_ast = quote do: <<102, _rest :: 16>> - assert_translation(ex_ast, "Elixir.Kernel.SpecialForms.bitstring(BitString.integer(102), BitString.size(_rest, 16))") + assert_translation(ex_ast, "Elixir.Kernel.SpecialForms.bitstring(Elixir.Core.BitString.integer(102), Elixir.Core.BitString.size(_rest, 16))") ex_ast = quote do: << 1, <<2>> >> - assert_translation(ex_ast, "Elixir.Kernel.SpecialForms.bitstring(BitString.integer(1), Elixir.Kernel.SpecialForms.bitstring(BitString.integer(2)))") + assert_translation(ex_ast, "Elixir.Kernel.SpecialForms.bitstring(Elixir.Core.BitString.integer(1), Elixir.Kernel.SpecialForms.bitstring(Elixir.Core.BitString.integer(2)))") end -end \ No newline at end of file +end diff --git a/test/translator/bug_test.exs b/test/translator/bug_test.exs index c43a3bde..5d110643 100644 --- a/test/translator/bug_test.exs +++ b/test/translator/bug_test.exs @@ -10,7 +10,7 @@ defmodule ElixirScript.Translator.Bug.Test do end js_code = """ - const test = Elixir.Patterns.defmatch(Elixir.Patterns.make_case([],function(){ + const test = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([],function(){ return Elixir.Kernel.SpecialForms.atom('atom'); })); """ @@ -29,7 +29,7 @@ defmodule ElixirScript.Translator.Bug.Test do js_code = """ React.createElement(React.Text,Elixir.Kernel.SpecialForms.map({ - style: Elixir.JS.call_property(styles,'welcome') + style: Elixir.Core.call_property(styles,'welcome') }),'Welcome to React Native!') """ @@ -49,7 +49,7 @@ defmodule ElixirScript.Translator.Bug.Test do import { default as JQuery } from 'jquery'; const __MODULE__ = Elixir.Kernel.SpecialForms.atom('App.Todo'); - JQuery(Elixir.JS.call_property(e, 'target')); + JQuery(Elixir.Core.call_property(e, 'target')); export {}; """ @@ -62,7 +62,7 @@ defmodule ElixirScript.Translator.Bug.Test do end js_code = """ - const graphic_store = Elixir.JS.call_property(App.Stores.GraphicStore, 'create_store'); + const graphic_store = Elixir.Core.call_property(App.Stores.GraphicStore, 'create_store'); """ @@ -87,7 +87,7 @@ defmodule ElixirScript.Translator.Bug.Test do end js_code = """ - Elixir.JS.call_property(this, 'getRawCanvas').getContext('2d') + Elixir.Core.call_property(this, 'getRawCanvas').getContext('2d') """ assert_translation(ex_ast, js_code) @@ -118,15 +118,15 @@ defmodule ElixirScript.Translator.Bug.Test do js_code = """ - const getDispatcher = Elixir.Patterns.defmatch(Elixir.Patterns.make_case([],function() { + const getDispatcher = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([],function() { return DeLorean.Flux.createDispatcher(Elixir.Kernel.SpecialForms.map({ - [Elixir.Kernel.SpecialForms.atom('startPainting')]: Elixir.Patterns.defmatch(Elixir.Patterns.make_case([],function() { + [Elixir.Kernel.SpecialForms.atom('startPainting')]: Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([],function() { return this.dispatch('startPainting'); - })), [Elixir.Kernel.SpecialForms.atom('stopPainting')]: Elixir.Patterns.defmatch(Elixir.Patterns.make_case([],function() { + })), [Elixir.Kernel.SpecialForms.atom('stopPainting')]: Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([],function() { return this.dispatch('stopPainting'); - })), [Elixir.Kernel.SpecialForms.atom('addPoint')]: Elixir.Patterns.defmatch(Elixir.Patterns.make_case([Elixir.Patterns.variable()],function(data) { + })), [Elixir.Kernel.SpecialForms.atom('addPoint')]: Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable()],function(data) { return this.dispatch('addPoint',data); - })), [Elixir.Kernel.SpecialForms.atom('getStores')]: Elixir.Patterns.defmatch(Elixir.Patterns.make_case([],function() { + })), [Elixir.Kernel.SpecialForms.atom('getStores')]: Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([],function() { return Elixir.Kernel.SpecialForms.map({ [Elixir.Kernel.SpecialForms.atom('graphic')]: GraphicStore }); diff --git a/test/translator/capture_test.exs b/test/translator/capture_test.exs index add658ca..c291b304 100644 --- a/test/translator/capture_test.exs +++ b/test/translator/capture_test.exs @@ -8,7 +8,7 @@ defmodule ElixirScript.Translator.Capture.Test do end js_code = """ - let [fun] = Elixir.Patterns.match(Elixir.Patterns.variable(),Elixir.Patterns.defmatch(Elixir.Patterns.make_case([Elixir.Patterns.variable()],function(__1) { + let [fun] = Elixir.Core.Patterns.match(Elixir.Core.Patterns.variable(),Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable()],function(__1) { return Elixir.Kernel.is_atom(__1); }))); """ @@ -24,7 +24,7 @@ defmodule ElixirScript.Translator.Capture.Test do end js_code = """ - let [fun] = Elixir.Patterns.match(Elixir.Patterns.variable(),Elixir.Patterns.defmatch(Elixir.Patterns.make_case([Elixir.Patterns.variable()],function(__1) { + let [fun] = Elixir.Core.Patterns.match(Elixir.Core.Patterns.variable(),Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable()],function(__1) { return Elixir.Kernel.is_atom(__1); }))); """ @@ -41,7 +41,7 @@ defmodule ElixirScript.Translator.Capture.Test do end js_code = """ - let [fun] = Elixir.Patterns.match(Elixir.Patterns.variable(),Elixir.Patterns.defmatch(Elixir.Patterns.make_case([Elixir.Patterns.variable()],function(__1) { + let [fun] = Elixir.Core.Patterns.match(Elixir.Core.Patterns.variable(),Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable()],function(__1) { return local_function(__1); }))); """ @@ -57,7 +57,7 @@ defmodule ElixirScript.Translator.Capture.Test do end js_code = """ - let [fun] = Elixir.Patterns.match(Elixir.Patterns.variable(),Elixir.Patterns.defmatch(Elixir.Patterns.make_case([Elixir.Patterns.variable()],function(__1) { + let [fun] = Elixir.Core.Patterns.match(Elixir.Core.Patterns.variable(),Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable()],function(__1) { return __1 * 2; }))); """ @@ -73,7 +73,7 @@ defmodule ElixirScript.Translator.Capture.Test do end js_code = """ - let [fun] = Elixir.Patterns.match(Elixir.Patterns.variable(),Elixir.Patterns.defmatch(Elixir.Patterns.make_case([Elixir.Patterns.variable(), Elixir.Patterns.variable()],function(__1,__2) { + let [fun] = Elixir.Core.Patterns.match(Elixir.Core.Patterns.variable(),Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable(), Elixir.Core.Patterns.variable()],function(__1,__2) { return Elixir.Kernel.SpecialForms.tuple(__1,__2); }))); """ @@ -85,7 +85,7 @@ defmodule ElixirScript.Translator.Capture.Test do end js_code = """ - let [fun] = Elixir.Patterns.match(Elixir.Patterns.variable(),Elixir.Patterns.defmatch(Elixir.Patterns.make_case([Elixir.Patterns.variable(), Elixir.Patterns.variable(), Elixir.Patterns.variable()],function(__1,__2,__3) { + let [fun] = Elixir.Core.Patterns.match(Elixir.Core.Patterns.variable(),Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable(), Elixir.Core.Patterns.variable(), Elixir.Core.Patterns.variable()],function(__1,__2,__3) { return Elixir.Kernel.SpecialForms.tuple(__1,__2,__3); }))); """ @@ -102,7 +102,7 @@ defmodule ElixirScript.Translator.Capture.Test do end js_code = """ - Elixir.Enum.map(items,Elixir.Patterns.defmatch(Elixir.Patterns.make_case([Elixir.Patterns.variable()],function(__1) { + Elixir.Enum.map(items,Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable()],function(__1) { return process(__1); }))) """ @@ -115,7 +115,7 @@ defmodule ElixirScript.Translator.Capture.Test do end js_code = """ - elem.keypress(Elixir.Patterns.defmatch(Elixir.Patterns.make_case([Elixir.Patterns.variable()],function(__1) { + elem.keypress(Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable()],function(__1) { return process_event(__1); }))) """ diff --git a/test/translator/case_test.exs b/test/translator/case_test.exs index 8ce15f99..0192a804 100644 --- a/test/translator/case_test.exs +++ b/test/translator/case_test.exs @@ -12,9 +12,9 @@ defmodule ElixirScript.Translator.Case.Test do end js_code = """ - Elixir.Patterns.defmatch(Elixir.Patterns.make_case([Elixir.Kernel.SpecialForms.atom('ok')],function() { + Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Kernel.SpecialForms.atom('ok')],function() { return value; - }),Elixir.Patterns.make_case([Elixir.Kernel.SpecialForms.atom('error')],function() { + }),Elixir.Core.Patterns.make_case([Elixir.Kernel.SpecialForms.atom('error')],function() { return null; })).call(this,data) """ @@ -29,10 +29,10 @@ defmodule ElixirScript.Translator.Case.Test do end js_code = """ - Elixir.Patterns.defmatch(Elixir.Patterns.make_case([false],function() { - let [value0] = Elixir.Patterns.match(Elixir.Patterns.variable(),13); + Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([false],function() { + let [value0] = Elixir.Core.Patterns.match(Elixir.Core.Patterns.variable(),13); return value0; - }),Elixir.Patterns.make_case([true],function() { + }),Elixir.Core.Patterns.make_case([true],function() { return true; })).call(this,data) """ @@ -49,10 +49,10 @@ defmodule ElixirScript.Translator.Case.Test do end js_code = """ - Elixir.Patterns.defmatch(Elixir.Patterns.make_case([false],function() { - let [value0] = Elixir.Patterns.match(Elixir.Patterns.variable(),13); + Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([false],function() { + let [value0] = Elixir.Core.Patterns.match(Elixir.Core.Patterns.variable(),13); return value0; - }),Elixir.Patterns.make_case([Elixir.Patterns.wildcard()],function() { + }),Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.wildcard()],function() { return true; })).call(this,data) """ @@ -71,12 +71,12 @@ defmodule ElixirScript.Translator.Case.Test do end js_code = """ - Elixir.Patterns.defmatch(Elixir.Patterns.make_case([Elixir.Patterns.variable()],function(number) { - let [value0] = Elixir.Patterns.match(Elixir.Patterns.variable(),13); + Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable()],function(number) { + let [value0] = Elixir.Core.Patterns.match(Elixir.Core.Patterns.variable(),13); return value0; },function(number) { return Elixir.Kernel.in(number,Elixir.Kernel.SpecialForms.list(1,2,3,4)); - }),Elixir.Patterns.make_case([Elixir.Patterns.wildcard()],function() { + }),Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.wildcard()],function() { return true; })).call(this,data) """ @@ -96,10 +96,10 @@ defmodule ElixirScript.Translator.Case.Test do end js_code = """ - Elixir.Patterns.defmatch(Elixir.Patterns.make_case([Elixir.Kernel.SpecialForms.atom('ok')],function() { + Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Kernel.SpecialForms.atom('ok')],function() { console.info('info'); return Todo.add(data); - }),Elixir.Patterns.make_case([Elixir.Kernel.SpecialForms.atom('error')],function() { + }),Elixir.Core.Patterns.make_case([Elixir.Kernel.SpecialForms.atom('error')],function() { return null; })).call(this,data) """ @@ -118,11 +118,11 @@ defmodule ElixirScript.Translator.Case.Test do end js_code = """ - Elixir.Patterns.defmatch(Elixir.Patterns.make_case([Elixir.Patterns.type(Elixir.Core.Tuple, { - values: [Elixir.Patterns.variable(), Elixir.Patterns.variable()] + Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.type(Elixir.Core.Tuple, { + values: [Elixir.Core.Patterns.variable(), Elixir.Core.Patterns.variable()] })], function(one, two) { return console.info(one); - }), Elixir.Patterns.make_case([Elixir.Kernel.SpecialForms.atom('error')], function() { + }), Elixir.Core.Patterns.make_case([Elixir.Kernel.SpecialForms.atom('error')], function() { return null; })).call(this, data) """ @@ -141,13 +141,13 @@ defmodule ElixirScript.Translator.Case.Test do end js_code = """ - Elixir.Patterns.defmatch(Elixir.Patterns.make_case([Elixir.Patterns.type(Elixir.Core.Tuple, { - values: [Elixir.Patterns.type(Elixir.Core.Tuple, { - values: [Elixir.Patterns.variable(), Elixir.Patterns.variable()] - }), Elixir.Patterns.variable()] + Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.type(Elixir.Core.Tuple, { + values: [Elixir.Core.Patterns.type(Elixir.Core.Tuple, { + values: [Elixir.Core.Patterns.variable(), Elixir.Core.Patterns.variable()] + }), Elixir.Core.Patterns.variable()] })], function(one, two, three) { return console.info(one); - }), Elixir.Patterns.make_case([Elixir.Kernel.SpecialForms.atom('error')], function() { + }), Elixir.Core.Patterns.make_case([Elixir.Kernel.SpecialForms.atom('error')], function() { return null; })).call(this, data) """ @@ -164,13 +164,13 @@ defmodule ElixirScript.Translator.Case.Test do end js_code = """ - Elixir.Patterns.defmatch(Elixir.Patterns.make_case([Elixir.Patterns.type(Elixir.Core.Tuple, { - values: [Elixir.Patterns.variable(), Elixir.Patterns.type(Elixir.Core.Tuple, { - values: [Elixir.Patterns.variable(), Elixir.Patterns.variable()] + Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.type(Elixir.Core.Tuple, { + values: [Elixir.Core.Patterns.variable(), Elixir.Core.Patterns.type(Elixir.Core.Tuple, { + values: [Elixir.Core.Patterns.variable(), Elixir.Core.Patterns.variable()] })] })], function(one, two, three) { return console.info(one); - }), Elixir.Patterns.make_case([Elixir.Kernel.SpecialForms.atom('error')], function() { + }), Elixir.Core.Patterns.make_case([Elixir.Kernel.SpecialForms.atom('error')], function() { return null; })).call(this, data) """ @@ -188,13 +188,13 @@ defmodule ElixirScript.Translator.Case.Test do end js_code = """ - Elixir.Patterns.defmatch(Elixir.Patterns.make_case([Elixir.Patterns.type(AStruct, { - [Elixir.Kernel.SpecialForms.atom('key')]: Elixir.Patterns.type(BStruct, { - [Elixir.Kernel.SpecialForms.atom('key2')]: Elixir.Patterns.variable() + Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.type(AStruct, { + [Elixir.Kernel.SpecialForms.atom('key')]: Elixir.Core.Patterns.type(BStruct, { + [Elixir.Kernel.SpecialForms.atom('key2')]: Elixir.Core.Patterns.variable() }) })], function(value) { return console.info(value); - }), Elixir.Patterns.make_case([Elixir.Kernel.SpecialForms.atom('error')], function() { + }), Elixir.Core.Patterns.make_case([Elixir.Kernel.SpecialForms.atom('error')], function() { return null; })).call(this, data) """ @@ -212,15 +212,15 @@ defmodule ElixirScript.Translator.Case.Test do end js_code = """ - Elixir.Patterns.defmatch(Elixir.Patterns.make_case([Elixir.Patterns.type(AStruct, { - [Elixir.Kernel.SpecialForms.atom('key')]: Elixir.Patterns.type(BStruct, { - [Elixir.Kernel.SpecialForms.atom('key2')]: Elixir.Patterns.variable(), [Elixir.Kernel.SpecialForms.atom('key3')]: Elixir.Patterns.type(CStruct, { - [Elixir.Kernel.SpecialForms.atom('key4')]: Elixir.Patterns.variable() + Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.type(AStruct, { + [Elixir.Kernel.SpecialForms.atom('key')]: Elixir.Core.Patterns.type(BStruct, { + [Elixir.Kernel.SpecialForms.atom('key2')]: Elixir.Core.Patterns.variable(), [Elixir.Kernel.SpecialForms.atom('key3')]: Elixir.Core.Patterns.type(CStruct, { + [Elixir.Kernel.SpecialForms.atom('key4')]: Elixir.Core.Patterns.variable() }) }) })], function(value, value2) { return console.info(value); - }), Elixir.Patterns.make_case([Elixir.Kernel.SpecialForms.atom('error')], function() { + }), Elixir.Core.Patterns.make_case([Elixir.Kernel.SpecialForms.atom('error')], function() { return null; })).call(this, data) """ diff --git a/test/translator/cond_test.exs b/test/translator/cond_test.exs index 5fb0815a..a6e3d364 100644 --- a/test/translator/cond_test.exs +++ b/test/translator/cond_test.exs @@ -42,13 +42,13 @@ defmodule ElixirScript.Translator.Cond.Test do js_code = """ Elixir.Kernel.SpecialForms.cond(Elixir.Kernel.SpecialForms.list(1 + 1 == 1,function() { - let [a] = Elixir.Patterns.match(Elixir.Patterns.variable(),1); + let [a] = Elixir.Core.Patterns.match(Elixir.Core.Patterns.variable(),1); return 'This will never match'; }),Elixir.Kernel.SpecialForms.list(2 * 2 != 4,function() { - let [a] = Elixir.Patterns.match(Elixir.Patterns.variable(),2); + let [a] = Elixir.Core.Patterns.match(Elixir.Core.Patterns.variable(),2); return 'Nor this'; }),Elixir.Kernel.SpecialForms.list(true,function() { - let [a] = Elixir.Patterns.match(Elixir.Patterns.variable(),3); + let [a] = Elixir.Core.Patterns.match(Elixir.Core.Patterns.variable(),3); return 'This will'; })) """ diff --git a/test/translator/defmodule_test.exs b/test/translator/defmodule_test.exs index 6b6ee4a2..05117c30 100644 --- a/test/translator/defmodule_test.exs +++ b/test/translator/defmodule_test.exs @@ -32,10 +32,10 @@ defmodule ElixirScript.Translator.Defmodule.Test do js_code = """ const __MODULE__ = Elixir.Kernel.SpecialForms.atom('Elephant'); - const something_else = Elixir.Patterns.defmatch(Elixir.Patterns.make_case([],function() { + const something_else = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([],function() { return null; })); - const something = Elixir.Patterns.defmatch(Elixir.Patterns.make_case([],function() { + const something = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([],function() { return ul; })); const ul = JQuery('#todo-list'); @@ -61,10 +61,10 @@ defmodule ElixirScript.Translator.Defmodule.Test do js_code = """ import * as Crane from 'icabod/crane'; const __MODULE__ = Elixir.Kernel.SpecialForms.atom('Elephant'); - const something_else = Elixir.Patterns.defmatch(Elixir.Patterns.make_case([],function() { + const something_else = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([],function() { return null; })); - const something = Elixir.Patterns.defmatch(Elixir.Patterns.make_case([],function() { + const something = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([],function() { return null; })); export { @@ -105,10 +105,10 @@ defmodule ElixirScript.Translator.Defmodule.Test do import * as Elephant from 'animals/elephant'; const __MODULE__ = Elixir.Kernel.SpecialForms.atom('Animals'); - const something_else = Elixir.Patterns.defmatch(Elixir.Patterns.make_case([], function() { + const something_else = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([], function() { return null; })); - const something = Elixir.Patterns.defmatch(Elixir.Patterns.make_case([], function() { + const something = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([], function() { return Elephant.Elephant.create(Elixir.Kernel.SpecialForms.map({})); })); export { @@ -174,10 +174,10 @@ defmodule ElixirScript.Translator.Defmodule.Test do import * as Elephant from 'animals/elephant'; const __MODULE__ = Elixir.Kernel.SpecialForms.atom('Animals'); - const something_else = Elixir.Patterns.defmatch(Elixir.Patterns.make_case([], function() { + const something_else = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([], function() { return null; })); - const something = Elixir.Patterns.defmatch(Elixir.Patterns.make_case([], function() { + const something = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([], function() { return Elephant.Elephant.create(Elixir.Kernel.SpecialForms.map({})); })); export { @@ -219,11 +219,11 @@ defmodule ElixirScript.Translator.Defmodule.Test do js_code = """ import * as Tigers from 'lions/tigers'; const __MODULE__ = Elixir.Kernel.SpecialForms.atom('Animals'); - Elixir.JS.call_property(Tigers,'oh_my'); + Elixir.Core.call_property(Tigers,'oh_my'); export {}; const __MODULE__ = Elixir.Kernel.SpecialForms.atom('Lions.Tigers'); - Elixir.JS.call_property(Lions.Tigers.Bears,'oh_my'); + Elixir.Core.call_property(Lions.Tigers.Bears,'oh_my'); export {}; """ @@ -248,17 +248,17 @@ defmodule ElixirScript.Translator.Defmodule.Test do js_code = """ const __MODULE__ = Elixir.Kernel.SpecialForms.atom('Lions.Tigers'); - const oh_my = Elixir.Patterns.defmatch(Elixir.Patterns.make_case([],function() { + const oh_my = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([],function() { return null; })); - Elixir.JS.call_property(Lions.Tigers.Bears,'oh_my'); + Elixir.Core.call_property(Lions.Tigers.Bears,'oh_my'); export { oh_my }; import * as Tigers from 'lions/tigers'; const __MODULE__ = Elixir.Kernel.SpecialForms.atom('Animals'); - Elixir.JS.call_property(Tigers,'oh_my'); + Elixir.Core.call_property(Tigers,'oh_my'); export {}; """ @@ -291,10 +291,10 @@ defmodule ElixirScript.Translator.Defmodule.Test do const __MODULE__ = Elixir.Kernel.SpecialForms.atom('Lions.Tigers'); - const oh_my2 = Elixir.Patterns.defmatch(Elixir.Patterns.make_case([], function() { + const oh_my2 = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([], function() { return null; })); - const oh_my = Elixir.Patterns.defmatch(Elixir.Patterns.make_case([], function() { + const oh_my = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([], function() { return null; })); export { @@ -333,11 +333,11 @@ defmodule ElixirScript.Translator.Defmodule.Test do const __MODULE__ = Elixir.Kernel.SpecialForms.atom('Lions.Tigers'); - const oh_my2 = Elixir.Patterns.defmatch(Elixir.Patterns.make_case([], function() { + const oh_my2 = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([], function() { return null; })); - const oh_my = Elixir.Patterns.defmatch(Elixir.Patterns.make_case([], function() { + const oh_my = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([], function() { return null; })); diff --git a/test/translator/for_test.exs b/test/translator/for_test.exs index 236fad8b..40c4da9b 100644 --- a/test/translator/for_test.exs +++ b/test/translator/for_test.exs @@ -8,7 +8,7 @@ defmodule ElixirScript.Translator.For.Test do end js_code = """ - Elixir.Kernel.SpecialForms._for(Elixir.Kernel.SpecialForms.list(Elixir.Kernel.SpecialForms.list(Elixir.Patterns.variable(),Elixir.Kernel.SpecialForms.list(1,2,3,4))),function(n) { + Elixir.Kernel.SpecialForms._for(Elixir.Kernel.SpecialForms.list(Elixir.Kernel.SpecialForms.list(Elixir.Core.Patterns.variable(),Elixir.Kernel.SpecialForms.list(1,2,3,4))),function(n) { return n * 2; },function() { return true; @@ -24,7 +24,7 @@ defmodule ElixirScript.Translator.For.Test do end js_code = """ - Elixir.Kernel.SpecialForms._for(Elixir.Kernel.SpecialForms.list(Elixir.Kernel.SpecialForms.list(Elixir.Patterns.variable(),Elixir.Kernel.SpecialForms.list(1,2,3,4))),function(n) { + Elixir.Kernel.SpecialForms._for(Elixir.Kernel.SpecialForms.list(Elixir.Kernel.SpecialForms.list(Elixir.Core.Patterns.variable(),Elixir.Kernel.SpecialForms.list(1,2,3,4))),function(n) { return n * 2; },function() { return true; @@ -40,7 +40,7 @@ defmodule ElixirScript.Translator.For.Test do end js_code = """ - Elixir.Kernel.SpecialForms._for(Elixir.Kernel.SpecialForms.list(Elixir.Kernel.SpecialForms.list(Elixir.Patterns.variable(),'Opera')),function(n) { + Elixir.Kernel.SpecialForms._for(Elixir.Kernel.SpecialForms.list(Elixir.Kernel.SpecialForms.list(Elixir.Core.Patterns.variable(),'Opera')),function(n) { return n; },function() { return true; @@ -57,8 +57,8 @@ defmodule ElixirScript.Translator.For.Test do js_code = """ Elixir.Kernel.SpecialForms._for(Elixir.Kernel.SpecialForms.list( - Elixir.Kernel.SpecialForms.list(Elixir.Patterns.variable(), Elixir.Kernel.SpecialForms.list(1,2)), - Elixir.Kernel.SpecialForms.list(Elixir.Patterns.variable(), Elixir.Kernel.SpecialForms.list(2,3))), function(x,y) { + Elixir.Kernel.SpecialForms.list(Elixir.Core.Patterns.variable(), Elixir.Kernel.SpecialForms.list(1,2)), + Elixir.Kernel.SpecialForms.list(Elixir.Core.Patterns.variable(), Elixir.Kernel.SpecialForms.list(2,3))), function(x,y) { return x * y; },function() { return true; @@ -76,7 +76,7 @@ defmodule ElixirScript.Translator.For.Test do end js_code = """ - let [r] = Elixir.Patterns.match(Elixir.Patterns.variable(),Elixir.Kernel.SpecialForms._for(Elixir.Kernel.SpecialForms.list(Elixir.Kernel.SpecialForms.list(Elixir.Patterns.variable(),Elixir.Kernel.SpecialForms.list(1,2)),Elixir.Kernel.SpecialForms.list(Elixir.Patterns.variable(),Elixir.Kernel.SpecialForms.list(2,3))),function(x,y) { + let [r] = Elixir.Core.Patterns.match(Elixir.Core.Patterns.variable(),Elixir.Kernel.SpecialForms._for(Elixir.Kernel.SpecialForms.list(Elixir.Kernel.SpecialForms.list(Elixir.Core.Patterns.variable(),Elixir.Kernel.SpecialForms.list(1,2)),Elixir.Kernel.SpecialForms.list(Elixir.Core.Patterns.variable(),Elixir.Kernel.SpecialForms.list(2,3))),function(x,y) { return x * y; },function() { return true; @@ -92,7 +92,7 @@ defmodule ElixirScript.Translator.For.Test do end js_code = """ - Elixir.Kernel.SpecialForms._for(Elixir.Kernel.SpecialForms.list(Elixir.Kernel.SpecialForms.list(Elixir.Patterns.variable(),Elixir.Kernel.SpecialForms.list(1,2,3,4,5,6))),function(n) { + Elixir.Kernel.SpecialForms._for(Elixir.Kernel.SpecialForms.list(Elixir.Kernel.SpecialForms.list(Elixir.Core.Patterns.variable(),Elixir.Kernel.SpecialForms.list(1,2,3,4,5,6))),function(n) { return n; },function(n) { return n % 2 == 0; @@ -110,8 +110,8 @@ defmodule ElixirScript.Translator.For.Test do end js_code = """ - Elixir.Kernel.SpecialForms._for(Elixir.Kernel.SpecialForms.list(Elixir.Kernel.SpecialForms.list(Elixir.Patterns.type(Elixir.Core.Tuple,{ - values: [Elixir.Kernel.SpecialForms.atom('user'), Elixir.Patterns.variable()] + Elixir.Kernel.SpecialForms._for(Elixir.Kernel.SpecialForms.list(Elixir.Kernel.SpecialForms.list(Elixir.Core.Patterns.type(Elixir.Core.Tuple,{ + values: [Elixir.Kernel.SpecialForms.atom('user'), Elixir.Core.Patterns.variable()] }),Elixir.Kernel.SpecialForms.list(Elixir.Kernel.SpecialForms.tuple(Elixir.Kernel.SpecialForms.atom('user'),'john'),Elixir.Kernel.SpecialForms.tuple(Elixir.Kernel.SpecialForms.atom('admin'),'john'),Elixir.Kernel.SpecialForms.tuple(Elixir.Kernel.SpecialForms.atom('user'),'meg')))),function(name) { return Elixir.String.upcase(name); },function() { diff --git a/test/translator/function_test.exs b/test/translator/function_test.exs index ed26e804..41503dff 100644 --- a/test/translator/function_test.exs +++ b/test/translator/function_test.exs @@ -24,7 +24,7 @@ defmodule ElixirScript.Translator.Function.Test do end js_code = """ - const test1 = Elixir.Patterns.defmatch(Elixir.Patterns.make_case([],function() { + const test1 = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([],function() { return 1 * 1; })); """ @@ -39,7 +39,7 @@ defmodule ElixirScript.Translator.Function.Test do end js_code = """ - const test1 = Elixir.Patterns.defmatch(Elixir.Patterns.make_case([],function() { + const test1 = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([],function() { return null; })); """ @@ -52,7 +52,7 @@ defmodule ElixirScript.Translator.Function.Test do end js_code = """ - const test1 = Elixir.Patterns.defmatch(Elixir.Patterns.make_case([Elixir.Patterns.variable(), Elixir.Patterns.variable()],function(alpha,beta) { + const test1 = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable(), Elixir.Core.Patterns.variable()],function(alpha,beta) { return null; })); """ @@ -66,8 +66,8 @@ defmodule ElixirScript.Translator.Function.Test do end js_code = """ - const test1 = Elixir.Patterns.defmatch(Elixir.Patterns.make_case([Elixir.Patterns.variable(), Elixir.Patterns.variable()],function(alpha,beta) { - let [a0] = Elixir.Patterns.match(Elixir.Patterns.variable(),alpha); + const test1 = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable(), Elixir.Core.Patterns.variable()],function(alpha,beta) { + let [a0] = Elixir.Core.Patterns.match(Elixir.Core.Patterns.variable(),alpha); return a0; })); """ @@ -85,12 +85,12 @@ defmodule ElixirScript.Translator.Function.Test do end js_code = """ - const test1 = Elixir.Patterns.defmatch(Elixir.Patterns.make_case([Elixir.Patterns.variable(), Elixir.Patterns.variable()],function(alpha,beta) { - return Elixir.Patterns.defmatch(Elixir.Patterns.make_case([Elixir.Patterns.variable()],function(x) { + const test1 = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable(), Elixir.Core.Patterns.variable()],function(alpha,beta) { + return Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable()],function(x) { return 2; },function(x) { return Elixir.Kernel.in(x,Elixir.Kernel.SpecialForms.list(false,null)); - }),Elixir.Patterns.make_case([Elixir.Patterns.wildcard()],function() { + }),Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.wildcard()],function() { return 1; })).call(this,1 == 1); })); @@ -113,18 +113,18 @@ defmodule ElixirScript.Translator.Function.Test do end js_code = """ - const test1 = Elixir.Patterns.defmatch(Elixir.Patterns.make_case([Elixir.Patterns.variable(), Elixir.Patterns.variable()],function(alpha,beta) { - return Elixir.Patterns.defmatch(Elixir.Patterns.make_case([Elixir.Patterns.variable()],function(x) { + const test1 = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable(), Elixir.Core.Patterns.variable()],function(alpha,beta) { + return Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable()],function(x) { return 2; },function(x) { return Elixir.Kernel.in(x,Elixir.Kernel.SpecialForms.list(false,null)); - }),Elixir.Patterns.make_case([Elixir.Patterns.wildcard()],function() { - return Elixir.Patterns.defmatch(Elixir.Patterns.make_case([Elixir.Patterns.variable()],function(x) { - let [a000] = Elixir.Patterns.match(Elixir.Patterns.variable(),1); + }),Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.wildcard()],function() { + return Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable()],function(x) { + let [a000] = Elixir.Core.Patterns.match(Elixir.Core.Patterns.variable(),1); return a000; },function(x) { return Elixir.Kernel.in(x,Elixir.Kernel.SpecialForms.list(false,null)); - }),Elixir.Patterns.make_case([Elixir.Patterns.wildcard()],function() { + }),Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.wildcard()],function() { return 4; })).call(this,2 == 2); })).call(this,1 == 1); @@ -140,9 +140,9 @@ defmodule ElixirScript.Translator.Function.Test do end js_code = """ - const test1 = Elixir.Patterns.defmatch(Elixir.Patterns.make_case([Elixir.Patterns.variable(), Elixir.Patterns.variable()], function(alpha, beta) { - let [a0, b0] = Elixir.Patterns.match(Elixir.Patterns.type(Elixir.Core.Tuple, { - values: [Elixir.Patterns.variable(), Elixir.Patterns.variable()] + const test1 = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable(), Elixir.Core.Patterns.variable()], function(alpha, beta) { + let [a0, b0] = Elixir.Core.Patterns.match(Elixir.Core.Patterns.type(Elixir.Core.Tuple, { + values: [Elixir.Core.Patterns.variable(), Elixir.Core.Patterns.variable()] }), Elixir.Kernel.SpecialForms.tuple(1, 2)); let _ref = Elixir.Kernel.SpecialForms.tuple(a0, b0); return _ref; @@ -181,7 +181,7 @@ defmodule ElixirScript.Translator.Function.Test do Taco.test1() end - js_code = "Elixir.JS.call_property(Taco, 'test1')" + js_code = "Elixir.Core.call_property(Taco, 'test1')" assert_translation(ex_ast, js_code) @@ -209,7 +209,7 @@ defmodule ElixirScript.Translator.Function.Test do end js_code = """ - Elixir.Enum.map(list,Elixir.Patterns.defmatch(Elixir.Patterns.make_case([Elixir.Patterns.variable()],function(x) { + Elixir.Enum.map(list,Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable()],function(x) { return x * 2; }))) """ @@ -240,15 +240,15 @@ defmodule ElixirScript.Translator.Function.Test do js_code = """ const __MODULE__ = Elixir.Kernel.SpecialForms.atom('Example'); - const example = Elixir.Patterns.defmatch(Elixir.Patterns.make_case([],function() { + const example = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([],function() { return null; - }),Elixir.Patterns.make_case([Elixir.Patterns.variable()],function(oneArg) { + }),Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable()],function(oneArg) { return null; - }),Elixir.Patterns.make_case([Elixir.Patterns.variable(), Elixir.Patterns.variable()],function(oneArg,twoArg) { + }),Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable(), Elixir.Core.Patterns.variable()],function(oneArg,twoArg) { return null; - }),Elixir.Patterns.make_case([Elixir.Patterns.variable(), Elixir.Patterns.variable(), Elixir.Patterns.variable()],function(oneArg,twoArg,redArg) { + }),Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable(), Elixir.Core.Patterns.variable(), Elixir.Core.Patterns.variable()],function(oneArg,twoArg,redArg) { return null; - }),Elixir.Patterns.make_case([Elixir.Patterns.variable(), Elixir.Patterns.variable(), Elixir.Patterns.variable(), Elixir.Patterns.variable()],function(oneArg,twoArg,redArg,blueArg) { + }),Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable(), Elixir.Core.Patterns.variable(), Elixir.Core.Patterns.variable(), Elixir.Core.Patterns.variable()],function(oneArg,twoArg,redArg,blueArg) { return null; })); export {}; @@ -277,15 +277,15 @@ defmodule ElixirScript.Translator.Function.Test do js_code = """ const __MODULE__ = Elixir.Kernel.SpecialForms.atom('Example'); - const example = Elixir.Patterns.defmatch(Elixir.Patterns.make_case([],function() { + const example = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([],function() { return null; - }),Elixir.Patterns.make_case([Elixir.Patterns.variable()],function(oneArg) { + }),Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable()],function(oneArg) { return null; - }),Elixir.Patterns.make_case([Elixir.Patterns.variable(), Elixir.Patterns.variable()],function(oneArg,twoArg) { + }),Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable(), Elixir.Core.Patterns.variable()],function(oneArg,twoArg) { return null; - }),Elixir.Patterns.make_case([Elixir.Patterns.variable(), Elixir.Patterns.variable(), Elixir.Patterns.variable()],function(oneArg,twoArg,redArg) { + }),Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable(), Elixir.Core.Patterns.variable(), Elixir.Core.Patterns.variable()],function(oneArg,twoArg,redArg) { return null; - }),Elixir.Patterns.make_case([Elixir.Patterns.variable(), Elixir.Patterns.variable(), Elixir.Patterns.variable(), Elixir.Patterns.variable()],function(oneArg,twoArg,redArg,blueArg) { + }),Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable(), Elixir.Core.Patterns.variable(), Elixir.Core.Patterns.variable(), Elixir.Core.Patterns.variable()],function(oneArg,twoArg,redArg,blueArg) { return null; })); export { @@ -304,7 +304,7 @@ defmodule ElixirScript.Translator.Function.Test do js_code = """ const __MODULE__ = Elixir.Kernel.SpecialForms.atom('Example'); - const example = Elixir.Patterns.defmatch(Elixir.Patterns.make_case([Elixir.Patterns.variable()],function(oneArg) { + const example = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable()],function(oneArg) { return null; })); export { @@ -352,7 +352,7 @@ defmodule ElixirScript.Translator.Function.Test do js_code = """ - const something = Elixir.Patterns.defmatch(Elixir.Patterns.make_case([Elixir.Patterns.variable()],function(one) { + const something = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable()],function(one) { return null; },function(one) { return Elixir.Kernel.is_number(one); @@ -369,7 +369,7 @@ defmodule ElixirScript.Translator.Function.Test do js_code = """ - const something = Elixir.Patterns.defmatch(Elixir.Patterns.make_case([Elixir.Patterns.variable()],function(one) { + const something = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable()],function(one) { return null; },function(one) { return Elixir.Kernel.is_number(one) || Elixir.Kernel.is_atom(one); @@ -385,7 +385,7 @@ defmodule ElixirScript.Translator.Function.Test do js_code = """ - const something = Elixir.Patterns.defmatch(Elixir.Patterns.make_case([Elixir.Patterns.variable()],function(one) { + const something = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable()],function(one) { return null; },function(one) { return Elixir.Kernel.is_number(one) || Elixir.Kernel.is_atom(one); @@ -401,7 +401,7 @@ defmodule ElixirScript.Translator.Function.Test do js_code = """ - const something = Elixir.Patterns.defmatch(Elixir.Patterns.make_case([Elixir.Patterns.variable(), Elixir.Patterns.variable()],function(one,two) { + const something = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable(), Elixir.Core.Patterns.variable()],function(one,two) { return null; },function(one,two) { return Elixir.Kernel.in(one,Elixir.Kernel.SpecialForms.list(1,2,3)); @@ -422,11 +422,11 @@ defmodule ElixirScript.Translator.Function.Test do js_code = """ const __MODULE__ = Elixir.Kernel.SpecialForms.atom('Example'); - const something = Elixir.Patterns.defmatch(Elixir.Patterns.make_case([Elixir.Patterns.variable()],function(one) { + const something = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable()],function(one) { return null; },function(one) { return Elixir.Kernel.in(one,Elixir.Kernel.SpecialForms.list(1,2,3)); - }),Elixir.Patterns.make_case([Elixir.Patterns.variable()],function(one) { + }),Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable()],function(one) { return null; },function(one) { return Elixir.Kernel.is_number(one) || Elixir.Kernel.is_atom(one); @@ -447,7 +447,7 @@ defmodule ElixirScript.Translator.Function.Test do js_code = """ - const something = Elixir.Patterns.defmatch(Elixir.Patterns.make_case([1],function() { + const something = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([1],function() { return null; })); """ @@ -463,7 +463,7 @@ defmodule ElixirScript.Translator.Function.Test do js_code = """ - const something = Elixir.Patterns.defmatch(Elixir.Patterns.make_case([Elixir.Patterns.headTail()],function(apple,fruits) { + const something = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.headTail()],function(apple,fruits) { return null; })); """ @@ -479,7 +479,7 @@ defmodule ElixirScript.Translator.Function.Test do js_code = """ - const something = Elixir.Patterns.defmatch(Elixir.Patterns.make_case([Elixir.Kernel.SpecialForms.list(Elixir.Patterns.variable(),Elixir.Patterns.variable(),Elixir.Patterns.variable())],function(apple,pear,banana) { + const something = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Kernel.SpecialForms.list(Elixir.Core.Patterns.variable(),Elixir.Core.Patterns.variable(),Elixir.Core.Patterns.variable())],function(apple,pear,banana) { return null; })); """ @@ -495,8 +495,8 @@ defmodule ElixirScript.Translator.Function.Test do js_code = """ - const something = Elixir.Patterns.defmatch(Elixir.Patterns.make_case([Elixir.Patterns.type(Elixir.Core.Tuple, { - values: [Elixir.Patterns.variable(), Elixir.Patterns.variable()] + const something = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.type(Elixir.Core.Tuple, { + values: [Elixir.Core.Patterns.variable(), Elixir.Core.Patterns.variable()] })], function(apple, fruits) { return null; })); @@ -513,7 +513,7 @@ defmodule ElixirScript.Translator.Function.Test do js_code = """ - const something = Elixir.Patterns.defmatch(Elixir.Patterns.make_case([Elixir.Patterns.type(AStruct, {})], function() { + const something = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.type(AStruct, {})], function() { return null; })); """ @@ -528,7 +528,7 @@ defmodule ElixirScript.Translator.Function.Test do end js_code = """ - const something = Elixir.Patterns.defmatch(Elixir.Patterns.make_case([Elixir.Patterns.capture(Elixir.Patterns.type(AStruct, {}))], function(a) { + const something = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.capture(Elixir.Core.Patterns.type(AStruct, {}))], function(a) { return null; })); """ @@ -542,7 +542,7 @@ defmodule ElixirScript.Translator.Function.Test do end js_code = """ - const something = Elixir.Patterns.defmatch(Elixir.Patterns.make_case([Elixir.Patterns.capture({ + const something = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.capture({ [Elixir.Kernel.SpecialForms.atom('which')]: 13 })],function(a) { return null; @@ -560,8 +560,8 @@ defmodule ElixirScript.Translator.Function.Test do js_code = """ - const something = Elixir.Patterns.defmatch(Elixir.Patterns.make_case([Elixir.Patterns.type(AStruct, { - [Elixir.Kernel.SpecialForms.atom('key')]: Elixir.Patterns.variable(), [Elixir.Kernel.SpecialForms.atom('key1')]: 2 + const something = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.type(AStruct, { + [Elixir.Kernel.SpecialForms.atom('key')]: Elixir.Core.Patterns.variable(), [Elixir.Kernel.SpecialForms.atom('key1')]: 2 })], function(value) { return null; })); @@ -576,8 +576,8 @@ defmodule ElixirScript.Translator.Function.Test do js_code = """ - const something = Elixir.Patterns.defmatch(Elixir.Patterns.make_case([Elixir.Patterns.type(AStruct, { - [Elixir.Kernel.SpecialForms.atom('key')]: Elixir.Patterns.variable(), [Elixir.Kernel.SpecialForms.atom('key1')]: 2 + const something = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.type(AStruct, { + [Elixir.Kernel.SpecialForms.atom('key')]: Elixir.Core.Patterns.variable(), [Elixir.Kernel.SpecialForms.atom('key1')]: 2 })], function(value) { return null; }, function(value) { @@ -596,7 +596,7 @@ defmodule ElixirScript.Translator.Function.Test do js_code = """ - const something = Elixir.Patterns.defmatch(Elixir.Patterns.make_case([Elixir.Patterns.startsWith('Bearer ')],function(token) { + const something = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.startsWith('Bearer ')],function(token) { return null; })); """ @@ -610,7 +610,7 @@ defmodule ElixirScript.Translator.Function.Test do js_code = """ - const something = Elixir.Patterns.defmatch(Elixir.Patterns.make_case([Elixir.Patterns.startsWith('Bearer '), Elixir.Patterns.variable()],function(token,hotel) { + const something = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.startsWith('Bearer '), Elixir.Core.Patterns.variable()],function(token,hotel) { return null; })); """ @@ -624,7 +624,7 @@ defmodule ElixirScript.Translator.Function.Test do js_code = """ - const something = Elixir.Patterns.defmatch(Elixir.Patterns.make_case([Elixir.Patterns.startsWith('Bearer '), Elixir.Patterns.variable(), 1],function(token,hotel) { + const something = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.startsWith('Bearer '), Elixir.Core.Patterns.variable(), 1],function(token,hotel) { return null; })); """ @@ -653,15 +653,15 @@ defmodule ElixirScript.Translator.Function.Test do js_code = """ const __MODULE__ = Elixir.Kernel.SpecialForms.atom('Example'); - const something = Elixir.Patterns.defmatch(Elixir.Patterns.make_case([1],function() { + const something = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([1],function() { return null; - }),Elixir.Patterns.make_case([2],function() { + }),Elixir.Core.Patterns.make_case([2],function() { return null; - }),Elixir.Patterns.make_case([Elixir.Patterns.variable()],function(one) { + }),Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable()],function(one) { return null; },function(one) { return Elixir.Kernel.is_binary(one); - }),Elixir.Patterns.make_case([Elixir.Patterns.variable()],function(one) { + }),Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable()],function(one) { return null; })); export { @@ -682,9 +682,9 @@ defmodule ElixirScript.Translator.Function.Test do end js_code = """ - const test1 = Elixir.Patterns.defmatch(Elixir.Patterns.make_case([Elixir.Patterns.variable(), Elixir.Patterns.variable()],function(alpha,beta) { - let [a0] = Elixir.Patterns.match(Elixir.Patterns.variable(),1); - let [a1] = Elixir.Patterns.match(Elixir.Patterns.variable(),2); + const test1 = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable(), Elixir.Core.Patterns.variable()],function(alpha,beta) { + let [a0] = Elixir.Core.Patterns.match(Elixir.Core.Patterns.variable(),1); + let [a1] = Elixir.Core.Patterns.match(Elixir.Core.Patterns.variable(),2); return a1; })); """ @@ -700,10 +700,10 @@ defmodule ElixirScript.Translator.Function.Test do end js_code = """ - const test1 = Elixir.Patterns.defmatch(Elixir.Patterns.make_case([Elixir.Patterns.variable(), Elixir.Patterns.variable()],function(alpha,beta) { - let [a0] = Elixir.Patterns.match(Elixir.Patterns.variable(),1); - let [a1] = Elixir.Patterns.match(Elixir.Patterns.variable(),a0); - let [a2] = Elixir.Patterns.match(Elixir.Patterns.variable(),2); + const test1 = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable(), Elixir.Core.Patterns.variable()],function(alpha,beta) { + let [a0] = Elixir.Core.Patterns.match(Elixir.Core.Patterns.variable(),1); + let [a1] = Elixir.Core.Patterns.match(Elixir.Core.Patterns.variable(),a0); + let [a2] = Elixir.Core.Patterns.match(Elixir.Core.Patterns.variable(),2); return a2; })); """ @@ -718,9 +718,9 @@ defmodule ElixirScript.Translator.Function.Test do end js_code = """ - const test1 = Elixir.Patterns.defmatch(Elixir.Patterns.make_case([Elixir.Patterns.variable(), Elixir.Patterns.variable()],function(alpha,beta) { - let [a0] = Elixir.Patterns.match(Elixir.Patterns.variable(),1); - let [a1,b0,c0] = Elixir.Patterns.match(Elixir.Kernel.SpecialForms.list(Elixir.Patterns.variable(),Elixir.Patterns.variable(),Elixir.Patterns.variable()),Elixir.Kernel.SpecialForms.list(a0,2,3)); + const test1 = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable(), Elixir.Core.Patterns.variable()],function(alpha,beta) { + let [a0] = Elixir.Core.Patterns.match(Elixir.Core.Patterns.variable(),1); + let [a1,b0,c0] = Elixir.Core.Patterns.match(Elixir.Kernel.SpecialForms.list(Elixir.Core.Patterns.variable(),Elixir.Core.Patterns.variable(),Elixir.Core.Patterns.variable()),Elixir.Kernel.SpecialForms.list(a0,2,3)); let _ref = Elixir.Kernel.SpecialForms.list(a1,b0,c0); return _ref; })); @@ -739,9 +739,9 @@ defmodule ElixirScript.Translator.Function.Test do end js_code = """ - const test1 = Elixir.Patterns.defmatch(Elixir.Patterns.make_case([Elixir.Patterns.variable(), Elixir.Patterns.variable()],function(alpha__qmark__,beta__emark__) { - let [a__qmark__0] = Elixir.Patterns.match(Elixir.Patterns.variable(),1); - let [b__emark__0] = Elixir.Patterns.match(Elixir.Patterns.variable(),2); + const test1 = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable(), Elixir.Core.Patterns.variable()],function(alpha__qmark__,beta__emark__) { + let [a__qmark__0] = Elixir.Core.Patterns.match(Elixir.Core.Patterns.variable(),1); + let [b__emark__0] = Elixir.Core.Patterns.match(Elixir.Core.Patterns.variable(),2); return b__emark__0; })); """ diff --git a/test/translator/list_test.exs b/test/translator/list_test.exs index 05e5244b..14b84d56 100644 --- a/test/translator/list_test.exs +++ b/test/translator/list_test.exs @@ -31,7 +31,7 @@ defmodule ElixirScript.Translator.List.Test do assert_translation(ex_ast, js_code) ex_ast = quote do: this.list ++ [4, 5, 6] - js_code = "Elixir.JS.call_property(this,'list').concat(Elixir.Kernel.SpecialForms.list(4,5,6))" + js_code = "Elixir.Core.call_property(this,'list').concat(Elixir.Kernel.SpecialForms.list(4,5,6))" assert_translation(ex_ast, js_code) end @@ -50,7 +50,7 @@ defmodule ElixirScript.Translator.List.Test do end js_code = """ - Elixir.Patterns.defmatch(Elixir.Patterns.make_case([Elixir.Patterns.wildcard()],function(){ + Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.wildcard()],function(){ return Elixir.List.prepend(list, x); })) """ diff --git a/test/translator/protocol_test.exs b/test/translator/protocol_test.exs index 6ea8bd64..8a279e5c 100644 --- a/test/translator/protocol_test.exs +++ b/test/translator/protocol_test.exs @@ -13,8 +13,8 @@ defmodule ElixirScript.Translator.Protocol.Test do const __MODULE__ = Elixir.Kernel.SpecialForms.atom('ElixirScript.Collectable'); let Collectable = Elixir.Kernel.defprotocol({ - into: Elixir.Patterns.defmatch( - Elixir.Patterns.make_case([Elixir.Patterns.variable()], function(collectable){ + into: Elixir.Core.Patterns.defmatch( + Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable()], function(collectable){ return null; }) ) @@ -35,7 +35,7 @@ defmodule ElixirScript.Translator.Protocol.Test do js_code = """ Elixir.Kernel.defimpl(Elixir.String.Chars, Duck, { - to_string: Elixir.Patterns.defmatch(Elixir.Patterns.make_case([Elixir.Patterns.variable()],function(duck) { + to_string: Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable()],function(duck) { return 'quack'; })) }) @@ -70,28 +70,28 @@ defmodule ElixirScript.Translator.Protocol.Test do js_code = """ const __MODULE__ = Elixir.Kernel.SpecialForms.atom('Blank'); let Blank = Elixir.Kernel.defprotocol({ - blank__qmark__: Elixir.Patterns.defmatch(Elixir.Patterns.make_case([Elixir.Patterns.variable()],function(data) { + blank__qmark__: Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable()],function(data) { return null; })) }); Elixir.Kernel.defimpl(Blank, Array,{ - blank__qmark__: Elixir.Patterns.defmatch(Elixir.Patterns.make_case([Elixir.Kernel.SpecialForms.list()],function() { + blank__qmark__: Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Kernel.SpecialForms.list()],function() { return true; - }),Elixir.Patterns.make_case([Elixir.Patterns.wildcard()],function() { + }),Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.wildcard()],function() { return false; })) }) Elixir.Kernel.defimpl(Blank,Symbol,{ - blank__qmark__: Elixir.Patterns.defmatch(Elixir.Patterns.make_case([false],function() { + blank__qmark__: Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([false],function() { return true; - }),Elixir.Patterns.make_case([null],function() { + }),Elixir.Core.Patterns.make_case([null],function() { return true; - }),Elixir.Patterns.make_case([Elixir.Patterns.wildcard()],function() { + }),Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.wildcard()],function() { return false; })) }) Elixir.Kernel.defimpl(Blank,Elixir.IntegerType,{ - blank__qmark__: Elixir.Patterns.defmatch(Elixir.Patterns.make_case([Elixir.Patterns.variable()],function(number) { + blank__qmark__: Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable()],function(number) { return false; })) }) diff --git a/test/translator/receive_test.exs b/test/translator/receive_test.exs index 1b4da1c3..868eed33 100644 --- a/test/translator/receive_test.exs +++ b/test/translator/receive_test.exs @@ -16,11 +16,11 @@ defmodule ElixirScript.Translator.Receive.Test do js_code = """ yield self.system.receive(function(message) { - return Elixir.Patterns.defmatch(Elixir.Patterns.make_case([Elixir.Kernel.SpecialForms.atom('ok')],function() { + return Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Kernel.SpecialForms.atom('ok')],function() { return value; - }),Elixir.Patterns.make_case([Elixir.Kernel.SpecialForms.atom('error')],function() { + }),Elixir.Core.Patterns.make_case([Elixir.Kernel.SpecialForms.atom('error')],function() { return value; - }),Elixir.Patterns.make_case([Elixir.Patterns.wildcard()],function() { + }),Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.wildcard()],function() { return IO.puts('Unexpected message received'); })).call(this,message); }) @@ -46,14 +46,14 @@ defmodule ElixirScript.Translator.Receive.Test do js_code = """ yield self.system.receive(function(message) { - return Elixir.Patterns.defmatch(Elixir.Patterns.make_case([Elixir.Kernel.SpecialForms.atom('ok')],function() { + return Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Kernel.SpecialForms.atom('ok')],function() { return value; - }),Elixir.Patterns.make_case([Elixir.Kernel.SpecialForms.atom('error')],function() { + }),Elixir.Core.Patterns.make_case([Elixir.Kernel.SpecialForms.atom('error')],function() { return value; - }),Elixir.Patterns.make_case([Elixir.Patterns.wildcard()],function() { + }),Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.wildcard()],function() { return IO.puts('Unexpected message received'); })).call(this,message); - },5000,Elixir.Patterns.defmatch(Elixir.Patterns.make_case([5000],function() { + },5000,Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([5000],function() { return IO.puts('No message in 5 seconds'); }))) """ diff --git a/test/translator/struct_test.exs b/test/translator/struct_test.exs index dfa0ceba..dc765a27 100644 --- a/test/translator/struct_test.exs +++ b/test/translator/struct_test.exs @@ -69,7 +69,7 @@ defmodule ElixirScript.Translator.Struct.Test do User: defstruct }; - let [user] = Elixir.Patterns.match(Elixir.Patterns.variable(), User.User.create(Elixir.Kernel.SpecialForms.map({}))); + let [user] = Elixir.Core.Patterns.match(Elixir.Core.Patterns.variable(), User.User.create(Elixir.Kernel.SpecialForms.map({}))); """ assert_translation(ex_ast, js_code) @@ -93,7 +93,7 @@ defmodule ElixirScript.Translator.Struct.Test do User: defstruct }; - let [user] = Elixir.Patterns.match(Elixir.Patterns.variable(), User.User.create(Elixir.Kernel.SpecialForms.map({ + let [user] = Elixir.Core.Patterns.match(Elixir.Core.Patterns.variable(), User.User.create(Elixir.Kernel.SpecialForms.map({ [Elixir.Kernel.SpecialForms.atom('name')]: 'John' }))); """ @@ -107,7 +107,7 @@ defmodule ElixirScript.Translator.Struct.Test do end js_code = """ - let [user] = Elixir.Patterns.match(Elixir.Patterns.variable(),Elixir.Kernel.SpecialForms.map_update(map,{ + let [user] = Elixir.Core.Patterns.match(Elixir.Core.Patterns.variable(),Elixir.Kernel.SpecialForms.map_update(map,{ [Elixir.Kernel.SpecialForms.atom('key')]: value })); """ @@ -120,7 +120,7 @@ defmodule ElixirScript.Translator.Struct.Test do end js_code = """ - let [user] = Elixir.Patterns.match(Elixir.Patterns.variable(),Elixir.Kernel.SpecialForms.map_update(map,{ + let [user] = Elixir.Core.Patterns.match(Elixir.Core.Patterns.variable(),Elixir.Kernel.SpecialForms.map_update(map,{ [Elixir.Kernel.SpecialForms.atom('key')]: value, [Elixir.Kernel.SpecialForms.atom('key1')]: value1 })); """ diff --git a/test/translator/try_test.exs b/test/translator/try_test.exs index feee98d7..5c506248 100644 --- a/test/translator/try_test.exs +++ b/test/translator/try_test.exs @@ -15,7 +15,7 @@ defmodule ElixirScript.Translator.Try.Test do js_code = """ Elixir.Kernel.SpecialForms._try(function() { return do_something_that_may_fail(some_arg); - }, Elixir.Patterns.defmatch(Elixir.Patterns.make_case([Elixir.Patterns.type(ArgumentError, {})], function() { + }, Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.type(ArgumentError, {})], function() { return IO.puts('Invalid argument given'); })), null, null, null) """ @@ -36,7 +36,7 @@ defmodule ElixirScript.Translator.Try.Test do js_code = """ Elixir.Kernel.SpecialForms._try(function() { return do_something_that_may_fail(some_arg); - }, Elixir.Patterns.defmatch(Elixir.Patterns.make_case([Elixir.Patterns.type(ArgumentError, {})], function() { + }, Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.type(ArgumentError, {})], function() { return IO.puts('Invalid argument given'); })), null, null, null) """ @@ -57,7 +57,7 @@ defmodule ElixirScript.Translator.Try.Test do js_code = """ Elixir.Kernel.SpecialForms._try(function() { return do_something_that_may_fail(some_arg); - }, Elixir.Patterns.defmatch(Elixir.Patterns.make_case([Elixir.Patterns.variable()], function(x) { + }, Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable()], function(x) { return IO.puts('Invalid argument given'); }, function(x) { return Elixir.Kernel.in(x, Elixir.Kernel.SpecialForms.list(ArgumentError.create(Elixir.Kernel.SpecialForms.map({})))); @@ -80,7 +80,7 @@ defmodule ElixirScript.Translator.Try.Test do js_code = """ Elixir.Kernel.SpecialForms._try(function() { return do_something_that_may_fail(some_arg); - },Elixir.Patterns.defmatch(Elixir.Patterns.make_case([Elixir.Patterns.variable()],function(x) { + },Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable()],function(x) { return IO.puts('Invalid argument given'); })),null,null,null) """ @@ -104,9 +104,9 @@ defmodule ElixirScript.Translator.Try.Test do js_code = """ Elixir.Kernel.SpecialForms._try(function() { return do_something_that_may_fail(some_arg); - }, Elixir.Patterns.defmatch(Elixir.Patterns.make_case([Elixir.Patterns.type(ArgumentError, {})], function() { + }, Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.type(ArgumentError, {})], function() { return IO.puts('ArgumentError'); - }), Elixir.Patterns.make_case([Elixir.Patterns.variable()], function(x) { + }), Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable()], function(x) { return IO.puts('x'); })), null, null, null) """ @@ -129,7 +129,7 @@ defmodule ElixirScript.Translator.Try.Test do js_code = """ Elixir.Kernel.SpecialForms._try(function() { return do_something_that_may_fail(some_arg); - }, Elixir.Patterns.defmatch(Elixir.Patterns.make_case([Elixir.Patterns.type(ArgumentError, {})], function() { + }, Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.type(ArgumentError, {})], function() { return IO.puts('Invalid argument given'); })), null, null, function() { return IO.puts('This is printed regardless if it failed or succeed'); @@ -174,11 +174,11 @@ defmodule ElixirScript.Translator.Try.Test do js_code = """ Elixir.Kernel.SpecialForms._try(function() { return 1 / x; - },null,null,Elixir.Patterns.defmatch(Elixir.Patterns.make_case([Elixir.Patterns.variable()],function(y) { + },null,null,Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable()],function(y) { return Elixir.Kernel.SpecialForms.atom('small'); },function(y) { return (y < 1) && (y > -1); - }),Elixir.Patterns.make_case([Elixir.Patterns.wildcard()],function() { + }),Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.wildcard()],function() { return Elixir.Kernel.SpecialForms.atom('large'); })),null) """ @@ -202,9 +202,9 @@ defmodule ElixirScript.Translator.Try.Test do js_code = """ Elixir.Kernel.SpecialForms._try(function() { return do_something_that_may_fail(some_arg); - }, Elixir.Patterns.defmatch(Elixir.Patterns.make_case([Elixir.Patterns.type(ArgumentError, {})], function() { + }, Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.type(ArgumentError, {})], function() { return IO.puts('Invalid argument given'); - })), Elixir.Patterns.defmatch(Elixir.Patterns.make_case([Elixir.Kernel.SpecialForms.atom('throw'), Elixir.Kernel.SpecialForms.atom('Error')], function() { + })), Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Kernel.SpecialForms.atom('throw'), Elixir.Kernel.SpecialForms.atom('Error')], function() { return IO.puts('caught error'); })), null, null) """ From 4758363b8d1d276f0247580c7fb3f422cadfb97c Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Fri, 4 Dec 2015 15:32:25 -0600 Subject: [PATCH 070/860] Fixed export issues --- priv/elixir.js | 498 +++++++++++----------- src/javascript/elixir.js | 9 +- src/javascript/lib/core/functions.js | 2 +- src/javascript/lib/core/patterns.js | 2 +- src/javascript/lib/core/primitives.js | 3 +- src/javascript/lib/core/process_system.js | 6 +- src/javascript/lib/list/chars.js | 3 +- src/javascript/lib/string/chars.js | 5 +- 8 files changed, 265 insertions(+), 263 deletions(-) diff --git a/priv/elixir.js b/priv/elixir.js index d7a8b4ce..850df9c3 100644 --- a/priv/elixir.js +++ b/priv/elixir.js @@ -1,53 +1,21 @@ -/* @flow */ - -class Mailbox { - - constructor() { - this.messages = []; - } - - deliver(message) { - this.messages.push(message); - return message; - } - - get() { - return this.messages; - } - - isEmpty() { - return this.messages.length === 0; - } - - removeAt(index) { - this.messages.splice(index, 1); +function call_property(item, property) { + if (property in item) { + item[property]; + if (item[property] instanceof Function) { + return item[property](); + } else { + return item[property]; + } + } else if (Symbol.for(property) in item) { + let prop = Symbol.for(property); + if (item[prop] instanceof Function) { + return item[prop](); + } else { + return item[prop]; + } } -} - -var States = { - NORMAL: Symbol.for("normal"), - KILL: Symbol.for("kill"), - SUSPEND: Symbol.for("suspend"), - CONTINUE: Symbol.for("continue"), - RECEIVE: Symbol.for("receive"), - SEND: Symbol.for("send"), - SLEEPING: Symbol.for("sleeping"), - RUNNING: Symbol.for("running"), - SUSPENDED: Symbol.for("suspended"), - STOPPED: Symbol.for("stopped"), - SLEEP: Symbol.for("sleep"), - EXIT: Symbol.for("exit"), - NOMATCH: Symbol.for("no_match") -}; -class Process { - - constructor(pid, mailbox) { - this.pid = pid; - this.mailbox = mailbox; - this.status = States.STOPPED; - this.dict = {}; - } + throw new Error(`Property ${ property } not found in ${ item }`); } class Tuple$1 { @@ -96,155 +64,9 @@ class PID { } } -var Core = { PID, Tuple: Tuple$1 }; - -class ProcessSystem { - - constructor() { - this.pids = new Map(); - this.mailboxes = new Map(); - this.names = new Map(); - this.links = new Map(); - - this.current_process = null; - this.suspended = new Map(); - - this.main_process_pid = this.spawn(); - this.set_current(this.main_process_pid); - } - - spawn() { - return this.add_proc(false).pid; - } - - spawn_link() { - return this.add_proc(true).pid; - } - - link(pid) { - this.links.get(this.pid()).add(pid); - this.links.get(pid).add(this.pid()); - } - - unlink(pid) { - this.links.get(this.pid()).delete(pid); - this.links.get(pid).delete(this.pid()); - } - - set_current(id) { - let pid = this.pidof(id); - if (pid !== null) { - this.current_process = this.pids.get(pid); - this.current_process.status = States.RUNNING; - } - } - - add_proc(linked) { - let newpid = new Core.PID(); - let mailbox = new Mailbox(); - let newproc = new Process(newpid, mailbox); - - this.pids.set(newpid, newproc); - this.mailboxes.set(newpid, mailbox); - this.links.set(newpid, new Set()); - - if (linked) { - this.link(newpid); - } - - return newproc; - } - - remove_proc(pid) { - this.pids.delete(pid); - this.unregister(pid); - - if (this.links.has(pid)) { - for (let linkpid of this.links.get(pid)) { - this.links.get(linkpid).delete(pid); - } - - this.links.delete(pid); - } - } - - exit(id) { - let pid = this.pidof(id); - this.remove_proc(id); - } - - register(name, pid) { - if (!this.names.has(name)) { - this.names.set(name, pid); - return name; - } else { - throw new Error("Name is already registered to another process"); - } - } - - registered(name) { - return this.names.has(name) ? this.names.get(name) : null; - } - - unregister(pid) { - for (let name of this.names.keys()) { - if (this.names.has(name) && this.names.get(name) === pid) { - this.names.delete(name); - } - } - } - - pid() { - return this.current_process.pid; - } - - pidof(id) { - if (id instanceof Core.PID) { - return this.pids.has(id) ? id : null; - } else if (id instanceof Process) { - return id.pid; - } else { - let pid = this.registered(id); - if (pid === null) throw "Process name not registered: " + id + " (" + typeof id + ")"; - return pid; - } - } - - put(id, key, value) { - let pid = this.pidof(id); - let process = this.pids.get(pid); - process.dict[key] = value; - } - - get(id, key) { - let pid = this.pidof(id); - let process = this.pids.get(pid); - - if (key != null) { - return process.dict[key]; - } else { - return process.dict; - } - } - - get_keys(id) { - let pid = this.pidof(id); - let process = this.pids.get(pid); - - return Object.keys(process.dict); - } - - erase(id, key) { - let pid = this.pidof(id); - let process = this.pids.get(pid); +class IntegerType {} - if (key != null) { - delete process.dict[key]; - } else { - process.dict = {}; - } - } -} +class FloatType {} /* @flow */ @@ -708,12 +530,6 @@ function match_no_throw(pattern, expr, guard = () => true) { } } -var Patterns = { - defmatch, match, MatchError, match_no_throw, - variable, wildcard, startsWith, - capture, headTail, type, bound, Case, make_case -}; - class BitString { constructor(...args) { this.raw_value = function () { @@ -1007,6 +823,217 @@ class BitString { } } +/* @flow */ + +class Mailbox { + + constructor() { + this.messages = []; + } + + deliver(message) { + this.messages.push(message); + return message; + } + + get() { + return this.messages; + } + + isEmpty() { + return this.messages.length === 0; + } + + removeAt(index) { + this.messages.splice(index, 1); + } +} + +var States = { + NORMAL: Symbol.for("normal"), + KILL: Symbol.for("kill"), + SUSPEND: Symbol.for("suspend"), + CONTINUE: Symbol.for("continue"), + RECEIVE: Symbol.for("receive"), + SEND: Symbol.for("send"), + SLEEPING: Symbol.for("sleeping"), + RUNNING: Symbol.for("running"), + SUSPENDED: Symbol.for("suspended"), + STOPPED: Symbol.for("stopped"), + SLEEP: Symbol.for("sleep"), + EXIT: Symbol.for("exit"), + NOMATCH: Symbol.for("no_match") +}; + +class Process { + + constructor(pid, mailbox) { + this.pid = pid; + this.mailbox = mailbox; + this.status = States.STOPPED; + this.dict = {}; + } +} + +class ProcessSystem { + + constructor() { + this.pids = new Map(); + this.mailboxes = new Map(); + this.names = new Map(); + this.links = new Map(); + + this.current_process = null; + this.suspended = new Map(); + + this.main_process_pid = this.spawn(); + this.set_current(this.main_process_pid); + } + + spawn() { + return this.add_proc(false).pid; + } + + spawn_link() { + return this.add_proc(true).pid; + } + + link(pid) { + this.links.get(this.pid()).add(pid); + this.links.get(pid).add(this.pid()); + } + + unlink(pid) { + this.links.get(this.pid()).delete(pid); + this.links.get(pid).delete(this.pid()); + } + + set_current(id) { + let pid = this.pidof(id); + if (pid !== null) { + this.current_process = this.pids.get(pid); + this.current_process.status = States.RUNNING; + } + } + + add_proc(linked) { + let newpid = new PID(); + let mailbox = new Mailbox(); + let newproc = new Process(newpid, mailbox); + + this.pids.set(newpid, newproc); + this.mailboxes.set(newpid, mailbox); + this.links.set(newpid, new Set()); + + if (linked) { + this.link(newpid); + } + + return newproc; + } + + remove_proc(pid) { + this.pids.delete(pid); + this.unregister(pid); + + if (this.links.has(pid)) { + for (let linkpid of this.links.get(pid)) { + this.links.get(linkpid).delete(pid); + } + + this.links.delete(pid); + } + } + + exit(id) { + let pid = this.pidof(id); + this.remove_proc(id); + } + + register(name, pid) { + if (!this.names.has(name)) { + this.names.set(name, pid); + return name; + } else { + throw new Error("Name is already registered to another process"); + } + } + + registered(name) { + return this.names.has(name) ? this.names.get(name) : null; + } + + unregister(pid) { + for (let name of this.names.keys()) { + if (this.names.has(name) && this.names.get(name) === pid) { + this.names.delete(name); + } + } + } + + pid() { + return this.current_process.pid; + } + + pidof(id) { + if (id instanceof PID) { + return this.pids.has(id) ? id : null; + } else if (id instanceof Process) { + return id.pid; + } else { + let pid = this.registered(id); + if (pid === null) throw "Process name not registered: " + id + " (" + typeof id + ")"; + return pid; + } + } + + put(id, key, value) { + let pid = this.pidof(id); + let process = this.pids.get(pid); + process.dict[key] = value; + } + + get(id, key) { + let pid = this.pidof(id); + let process = this.pids.get(pid); + + if (key != null) { + return process.dict[key]; + } else { + return process.dict; + } + } + + get_keys(id) { + let pid = this.pidof(id); + let process = this.pids.get(pid); + + return Object.keys(process.dict); + } + + erase(id, key) { + let pid = this.pidof(id); + let process = this.pids.get(pid); + + if (key != null) { + delete process.dict[key]; + } else { + process.dict = {}; + } + } +} + +var C = Object.freeze({ + ProcessSystem: ProcessSystem, + Tuple: Tuple$1, + PID: PID, + BitString: BitString, + Patterns: null$1, + IntegerType: IntegerType, + FloatType: FloatType, + call_property: call_property +}); + let Enum = { all__qmark__: function (collection, fun = x => x) { @@ -1234,11 +1261,11 @@ let SpecialForms = { }, bound: function (_var) { - return undefined(_var); + return bound(_var); }, _case: function (condition, clauses) { - return undefined(...clauses)(condition); + return defmatch(...clauses)(condition); }, cond: function (clauses) { @@ -1252,7 +1279,7 @@ let SpecialForms = { }, fn: function (clauses) { - return undefined(clauses); + return defmatch(clauses); }, map: function (obj) { @@ -1270,7 +1297,7 @@ let SpecialForms = { if (collections.length === 1) { for (let elem of collection) { - let r = undefined(pattern, elem); + let r = match_no_throw(pattern, elem); let args = previousValues.concat(r); if (r && filter.apply(this, args)) { @@ -1283,7 +1310,7 @@ let SpecialForms = { let _into = []; for (let elem of collection) { - let r = undefined(pattern, elem); + let r = match_no_throw(pattern, elem); if (r) { _into = Enum.into(this._for(collections.slice(1), fun, filter, _into, previousValues.concat(r)), into); } @@ -1325,7 +1352,7 @@ let SpecialForms = { }, tuple: function (...args) { - return new Core.Tuple(...args); + return new Tuple$1(...args); }, _try: function (do_fun, rescue_function, catch_fun, else_function, after_function) { @@ -1341,7 +1368,7 @@ let SpecialForms = { ex_result = rescue_function(e); return ex_result; } catch (ex) { - if (ex instanceof undefined) { + if (ex instanceof MatchError) { throw ex; } } @@ -1352,7 +1379,7 @@ let SpecialForms = { ex_result = catch_fun(e); return ex_result; } catch (ex) { - if (ex instanceof undefined) { + if (ex instanceof MatchError) { throw ex; } } @@ -1369,7 +1396,7 @@ let SpecialForms = { try { return else_function(result); } catch (ex) { - if (ex instanceof undefined) { + if (ex instanceof MatchError) { throw new Error('No Match Found in Else'); } @@ -1447,9 +1474,6 @@ var Tuple = { to_list }; -class IntegerType {} -class FloatType {} - //https://github.com/airportyh/protomorphism class Protocol { constructor(spec) { @@ -1548,7 +1572,7 @@ function is_number(x) { } function is_tuple(x) { - return x instanceof Core.Tuple; + return x instanceof Tuple$1; } function length(x) { @@ -1556,7 +1580,7 @@ function length(x) { } function is_pid(x) { - return x instanceof Core.PID; + return x instanceof PID; } function is_port(x) { @@ -1640,7 +1664,7 @@ function to_string(arg) { } function match__qmark__(pattern, expr, guard = () => true) { - return Patterns.match_no_throw(pattern, expr, guard) != null; + return match_no_throw(pattern, expr, guard) != null; } function defstruct(defaults) { @@ -1747,30 +1771,6 @@ let Integer = { } }; -function call_property(item, property) { - if (property in item) { - item[property]; - if (item[property] instanceof Function) { - return item[property](); - } else { - return item[property]; - } - } else if (Symbol.for(property) in item) { - let prop = Symbol.for(property); - if (item[prop] instanceof Function) { - return item[prop](); - } else { - return item[prop]; - } - } - - throw new Error(`Property ${ property } not found in ${ item }`); -} - -var js = { - call_property -}; - let Chars$1 = Kernel.defprotocol({ to_string: function (thing) {} }); @@ -1813,7 +1813,7 @@ Kernel.defimpl(Chars$1, Array, { } }); -Kernel.defimpl(Chars$1, Core.Tuple, { +Kernel.defimpl(Chars$1, Tuple$1, { to_string: function (thing) { return Tuple.to_string(thing); } @@ -2013,7 +2013,7 @@ let Chars = Kernel.defprotocol({ to_char_list: function (thing) {} }); -Kernel.defimpl(Chars, Kernel.is_bitstring, { +Kernel.defimpl(Chars, BitString, { to_char_list: function (thing) { if (Kernel.is_binary(thing)) { return String$1.to_char_list(thing); @@ -2023,19 +2023,19 @@ Kernel.defimpl(Chars, Kernel.is_bitstring, { } }); -Kernel.defimpl(Chars, Kernel.is_atom, { +Kernel.defimpl(Chars, Symbol, { to_char_list: function (thing) { return Atom.to_char_list(thing); } }); -Kernel.defimpl(Chars, Kernel.is_integer, { +Kernel.defimpl(Chars, IntegerType, { to_char_list: function (thing) { return Integer.to_char_list(thing); } }); -Kernel.defimpl(Chars, Kernel.is_list, { +Kernel.defimpl(Chars, Array, { to_char_list: function (thing) { return thing; } @@ -4558,5 +4558,7 @@ var view = { self.processes = self.processes || new ProcessSystem(); -export { Core, Patterns, BitString, Kernel, Atom, Enum, Integer, js as JS, List, Range, Tuple, Agent, Keyword, base as Base, String$1 as String, bitwise as Bitwise, Enumerable, Collectable, Inspect, map as Map, set as Set, MapSet, IntegerType, FloatType, VirtualDOM, view as View }; -//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiIiwic291cmNlcyI6WyJlbGl4aXIuanMiXSwic291cmNlc0NvbnRlbnQiOlsiLyogQGZsb3cgKi9cblxuY2xhc3MgTWFpbGJveCB7XG5cbiAgY29uc3RydWN0b3IoKSB7XG4gICAgdGhpcy5tZXNzYWdlcyA9IFtdO1xuICB9XG5cbiAgZGVsaXZlcihtZXNzYWdlKSB7XG4gICAgdGhpcy5tZXNzYWdlcy5wdXNoKG1lc3NhZ2UpO1xuICAgIHJldHVybiBtZXNzYWdlO1xuICB9XG5cbiAgZ2V0KCkge1xuICAgIHJldHVybiB0aGlzLm1lc3NhZ2VzO1xuICB9XG5cbiAgaXNFbXB0eSgpIHtcbiAgICByZXR1cm4gdGhpcy5tZXNzYWdlcy5sZW5ndGggPT09IDA7XG4gIH1cblxuICByZW1vdmVBdChpbmRleCkge1xuICAgIHRoaXMubWVzc2FnZXMuc3BsaWNlKGluZGV4LCAxKTtcbiAgfVxufVxuXG52YXIgU3RhdGVzID0ge1xuICBOT1JNQUw6IFN5bWJvbC5mb3IoXCJub3JtYWxcIiksXG4gIEtJTEw6IFN5bWJvbC5mb3IoXCJraWxsXCIpLFxuICBTVVNQRU5EOiBTeW1ib2wuZm9yKFwic3VzcGVuZFwiKSxcbiAgQ09OVElOVUU6IFN5bWJvbC5mb3IoXCJjb250aW51ZVwiKSxcbiAgUkVDRUlWRTogU3ltYm9sLmZvcihcInJlY2VpdmVcIiksXG4gIFNFTkQ6IFN5bWJvbC5mb3IoXCJzZW5kXCIpLFxuICBTTEVFUElORzogU3ltYm9sLmZvcihcInNsZWVwaW5nXCIpLFxuICBSVU5OSU5HOiBTeW1ib2wuZm9yKFwicnVubmluZ1wiKSxcbiAgU1VTUEVOREVEOiBTeW1ib2wuZm9yKFwic3VzcGVuZGVkXCIpLFxuICBTVE9QUEVEOiBTeW1ib2wuZm9yKFwic3RvcHBlZFwiKSxcbiAgU0xFRVA6IFN5bWJvbC5mb3IoXCJzbGVlcFwiKSxcbiAgRVhJVDogU3ltYm9sLmZvcihcImV4aXRcIiksXG4gIE5PTUFUQ0g6IFN5bWJvbC5mb3IoXCJub19tYXRjaFwiKVxufTtcblxuY2xhc3MgUHJvY2VzcyB7XG5cbiAgY29uc3RydWN0b3IocGlkLCBtYWlsYm94KSB7XG4gICAgdGhpcy5waWQgPSBwaWQ7XG4gICAgdGhpcy5tYWlsYm94ID0gbWFpbGJveDtcbiAgICB0aGlzLnN0YXR1cyA9IFN0YXRlcy5TVE9QUEVEO1xuICAgIHRoaXMuZGljdCA9IHt9O1xuICB9XG59XG5cbmNsYXNzIFR1cGxlJDEge1xuXG4gIGNvbnN0cnVjdG9yKC4uLmFyZ3MpIHtcbiAgICB0aGlzLnZhbHVlcyA9IE9iamVjdC5mcmVlemUoYXJncyk7XG4gIH1cblxuICBnZXQoaW5kZXgpIHtcbiAgICByZXR1cm4gdGhpcy52YWx1ZXNbaW5kZXhdO1xuICB9XG5cbiAgY291bnQoKSB7XG4gICAgcmV0dXJuIHRoaXMudmFsdWVzLmxlbmd0aDtcbiAgfVxuXG4gIFtTeW1ib2wuaXRlcmF0b3JdKCkge1xuICAgIHJldHVybiB0aGlzLnZhbHVlc1tTeW1ib2wuaXRlcmF0b3JdKCk7XG4gIH1cblxuICB0b1N0cmluZygpIHtcbiAgICB2YXIgaSxcbiAgICAgICAgcyA9IFwiXCI7XG4gICAgZm9yIChpID0gMDsgaSA8IHRoaXMudmFsdWVzLmxlbmd0aDsgaSsrKSB7XG4gICAgICBpZiAocyAhPT0gXCJcIikge1xuICAgICAgICBzICs9IFwiLCBcIjtcbiAgICAgIH1cbiAgICAgIHMgKz0gdGhpcy52YWx1ZXNbaV0udG9TdHJpbmcoKTtcbiAgICB9XG5cbiAgICByZXR1cm4gXCJ7XCIgKyBzICsgXCJ9XCI7XG4gIH1cblxufVxuXG5sZXQgcHJvY2Vzc19jb3VudGVyID0gLTE7XG5cbmNsYXNzIFBJRCB7XG4gIGNvbnN0cnVjdG9yKCkge1xuICAgIHByb2Nlc3NfY291bnRlciA9IHByb2Nlc3NfY291bnRlciArIDE7XG4gICAgdGhpcy5pZCA9IHByb2Nlc3NfY291bnRlcjtcbiAgfVxuXG4gIHRvU3RyaW5nKCkge1xuICAgIHJldHVybiBcIlBJRCM8MC5cIiArIHRoaXMuaWQgKyBcIi4wPlwiO1xuICB9XG59XG5cbnZhciBDb3JlID0geyBQSUQsIFR1cGxlOiBUdXBsZSQxIH07XG5cbmNsYXNzIFByb2Nlc3NTeXN0ZW0ge1xuXG4gIGNvbnN0cnVjdG9yKCkge1xuICAgIHRoaXMucGlkcyA9IG5ldyBNYXAoKTtcbiAgICB0aGlzLm1haWxib3hlcyA9IG5ldyBNYXAoKTtcbiAgICB0aGlzLm5hbWVzID0gbmV3IE1hcCgpO1xuICAgIHRoaXMubGlua3MgPSBuZXcgTWFwKCk7XG5cbiAgICB0aGlzLmN1cnJlbnRfcHJvY2VzcyA9IG51bGw7XG4gICAgdGhpcy5zdXNwZW5kZWQgPSBuZXcgTWFwKCk7XG5cbiAgICB0aGlzLm1haW5fcHJvY2Vzc19waWQgPSB0aGlzLnNwYXduKCk7XG4gICAgdGhpcy5zZXRfY3VycmVudCh0aGlzLm1haW5fcHJvY2Vzc19waWQpO1xuICB9XG5cbiAgc3Bhd24oKSB7XG4gICAgcmV0dXJuIHRoaXMuYWRkX3Byb2MoZmFsc2UpLnBpZDtcbiAgfVxuXG4gIHNwYXduX2xpbmsoKSB7XG4gICAgcmV0dXJuIHRoaXMuYWRkX3Byb2ModHJ1ZSkucGlkO1xuICB9XG5cbiAgbGluayhwaWQpIHtcbiAgICB0aGlzLmxpbmtzLmdldCh0aGlzLnBpZCgpKS5hZGQocGlkKTtcbiAgICB0aGlzLmxpbmtzLmdldChwaWQpLmFkZCh0aGlzLnBpZCgpKTtcbiAgfVxuXG4gIHVubGluayhwaWQpIHtcbiAgICB0aGlzLmxpbmtzLmdldCh0aGlzLnBpZCgpKS5kZWxldGUocGlkKTtcbiAgICB0aGlzLmxpbmtzLmdldChwaWQpLmRlbGV0ZSh0aGlzLnBpZCgpKTtcbiAgfVxuXG4gIHNldF9jdXJyZW50KGlkKSB7XG4gICAgbGV0IHBpZCA9IHRoaXMucGlkb2YoaWQpO1xuICAgIGlmIChwaWQgIT09IG51bGwpIHtcbiAgICAgIHRoaXMuY3VycmVudF9wcm9jZXNzID0gdGhpcy5waWRzLmdldChwaWQpO1xuICAgICAgdGhpcy5jdXJyZW50X3Byb2Nlc3Muc3RhdHVzID0gU3RhdGVzLlJVTk5JTkc7XG4gICAgfVxuICB9XG5cbiAgYWRkX3Byb2MobGlua2VkKSB7XG4gICAgbGV0IG5ld3BpZCA9IG5ldyBDb3JlLlBJRCgpO1xuICAgIGxldCBtYWlsYm94ID0gbmV3IE1haWxib3goKTtcbiAgICBsZXQgbmV3cHJvYyA9IG5ldyBQcm9jZXNzKG5ld3BpZCwgbWFpbGJveCk7XG5cbiAgICB0aGlzLnBpZHMuc2V0KG5ld3BpZCwgbmV3cHJvYyk7XG4gICAgdGhpcy5tYWlsYm94ZXMuc2V0KG5ld3BpZCwgbWFpbGJveCk7XG4gICAgdGhpcy5saW5rcy5zZXQobmV3cGlkLCBuZXcgU2V0KCkpO1xuXG4gICAgaWYgKGxpbmtlZCkge1xuICAgICAgdGhpcy5saW5rKG5ld3BpZCk7XG4gICAgfVxuXG4gICAgcmV0dXJuIG5ld3Byb2M7XG4gIH1cblxuICByZW1vdmVfcHJvYyhwaWQpIHtcbiAgICB0aGlzLnBpZHMuZGVsZXRlKHBpZCk7XG4gICAgdGhpcy51bnJlZ2lzdGVyKHBpZCk7XG5cbiAgICBpZiAodGhpcy5saW5rcy5oYXMocGlkKSkge1xuICAgICAgZm9yIChsZXQgbGlua3BpZCBvZiB0aGlzLmxpbmtzLmdldChwaWQpKSB7XG4gICAgICAgIHRoaXMubGlua3MuZ2V0KGxpbmtwaWQpLmRlbGV0ZShwaWQpO1xuICAgICAgfVxuXG4gICAgICB0aGlzLmxpbmtzLmRlbGV0ZShwaWQpO1xuICAgIH1cbiAgfVxuXG4gIGV4aXQoaWQpIHtcbiAgICBsZXQgcGlkID0gdGhpcy5waWRvZihpZCk7XG4gICAgdGhpcy5yZW1vdmVfcHJvYyhpZCk7XG4gIH1cblxuICByZWdpc3RlcihuYW1lLCBwaWQpIHtcbiAgICBpZiAoIXRoaXMubmFtZXMuaGFzKG5hbWUpKSB7XG4gICAgICB0aGlzLm5hbWVzLnNldChuYW1lLCBwaWQpO1xuICAgICAgcmV0dXJuIG5hbWU7XG4gICAgfSBlbHNlIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcihcIk5hbWUgaXMgYWxyZWFkeSByZWdpc3RlcmVkIHRvIGFub3RoZXIgcHJvY2Vzc1wiKTtcbiAgICB9XG4gIH1cblxuICByZWdpc3RlcmVkKG5hbWUpIHtcbiAgICByZXR1cm4gdGhpcy5uYW1lcy5oYXMobmFtZSkgPyB0aGlzLm5hbWVzLmdldChuYW1lKSA6IG51bGw7XG4gIH1cblxuICB1bnJlZ2lzdGVyKHBpZCkge1xuICAgIGZvciAobGV0IG5hbWUgb2YgdGhpcy5uYW1lcy5rZXlzKCkpIHtcbiAgICAgIGlmICh0aGlzLm5hbWVzLmhhcyhuYW1lKSAmJiB0aGlzLm5hbWVzLmdldChuYW1lKSA9PT0gcGlkKSB7XG4gICAgICAgIHRoaXMubmFtZXMuZGVsZXRlKG5hbWUpO1xuICAgICAgfVxuICAgIH1cbiAgfVxuXG4gIHBpZCgpIHtcbiAgICByZXR1cm4gdGhpcy5jdXJyZW50X3Byb2Nlc3MucGlkO1xuICB9XG5cbiAgcGlkb2YoaWQpIHtcbiAgICBpZiAoaWQgaW5zdGFuY2VvZiBDb3JlLlBJRCkge1xuICAgICAgcmV0dXJuIHRoaXMucGlkcy5oYXMoaWQpID8gaWQgOiBudWxsO1xuICAgIH0gZWxzZSBpZiAoaWQgaW5zdGFuY2VvZiBQcm9jZXNzKSB7XG4gICAgICByZXR1cm4gaWQucGlkO1xuICAgIH0gZWxzZSB7XG4gICAgICBsZXQgcGlkID0gdGhpcy5yZWdpc3RlcmVkKGlkKTtcbiAgICAgIGlmIChwaWQgPT09IG51bGwpIHRocm93IFwiUHJvY2VzcyBuYW1lIG5vdCByZWdpc3RlcmVkOiBcIiArIGlkICsgXCIgKFwiICsgdHlwZW9mIGlkICsgXCIpXCI7XG4gICAgICByZXR1cm4gcGlkO1xuICAgIH1cbiAgfVxuXG4gIHB1dChpZCwga2V5LCB2YWx1ZSkge1xuICAgIGxldCBwaWQgPSB0aGlzLnBpZG9mKGlkKTtcbiAgICBsZXQgcHJvY2VzcyA9IHRoaXMucGlkcy5nZXQocGlkKTtcbiAgICBwcm9jZXNzLmRpY3Rba2V5XSA9IHZhbHVlO1xuICB9XG5cbiAgZ2V0KGlkLCBrZXkpIHtcbiAgICBsZXQgcGlkID0gdGhpcy5waWRvZihpZCk7XG4gICAgbGV0IHByb2Nlc3MgPSB0aGlzLnBpZHMuZ2V0KHBpZCk7XG5cbiAgICBpZiAoa2V5ICE9IG51bGwpIHtcbiAgICAgIHJldHVybiBwcm9jZXNzLmRpY3Rba2V5XTtcbiAgICB9IGVsc2Uge1xuICAgICAgcmV0dXJuIHByb2Nlc3MuZGljdDtcbiAgICB9XG4gIH1cblxuICBnZXRfa2V5cyhpZCkge1xuICAgIGxldCBwaWQgPSB0aGlzLnBpZG9mKGlkKTtcbiAgICBsZXQgcHJvY2VzcyA9IHRoaXMucGlkcy5nZXQocGlkKTtcblxuICAgIHJldHVybiBPYmplY3Qua2V5cyhwcm9jZXNzLmRpY3QpO1xuICB9XG5cbiAgZXJhc2UoaWQsIGtleSkge1xuICAgIGxldCBwaWQgPSB0aGlzLnBpZG9mKGlkKTtcbiAgICBsZXQgcHJvY2VzcyA9IHRoaXMucGlkcy5nZXQocGlkKTtcblxuICAgIGlmIChrZXkgIT0gbnVsbCkge1xuICAgICAgZGVsZXRlIHByb2Nlc3MuZGljdFtrZXldO1xuICAgIH0gZWxzZSB7XG4gICAgICBwcm9jZXNzLmRpY3QgPSB7fTtcbiAgICB9XG4gIH1cbn1cblxuLyogQGZsb3cgKi9cblxuY2xhc3MgVmFyaWFibGUge1xuXG4gIGNvbnN0cnVjdG9yKG5hbWUgPSBudWxsKSB7XG4gICAgdGhpcy5uYW1lID0gbmFtZTtcbiAgfVxufVxuXG5jbGFzcyBXaWxkY2FyZCB7XG4gIGNvbnN0cnVjdG9yKCkge31cbn1cblxuY2xhc3MgU3RhcnRzV2l0aCB7XG5cbiAgY29uc3RydWN0b3IocHJlZml4KSB7XG4gICAgdGhpcy5wcmVmaXggPSBwcmVmaXg7XG4gIH1cbn1cblxuY2xhc3MgQ2FwdHVyZSB7XG5cbiAgY29uc3RydWN0b3IodmFsdWUpIHtcbiAgICB0aGlzLnZhbHVlID0gdmFsdWU7XG4gIH1cbn1cblxuY2xhc3MgSGVhZFRhaWwge1xuICBjb25zdHJ1Y3RvcigpIHt9XG59XG5cbmNsYXNzIFR5cGUge1xuXG4gIGNvbnN0cnVjdG9yKHR5cGUsIG9ialBhdHRlcm4gPSB7fSkge1xuICAgIHRoaXMudHlwZSA9IHR5cGU7XG4gICAgdGhpcy5vYmpQYXR0ZXJuID0gb2JqUGF0dGVybjtcbiAgfVxufVxuXG5jbGFzcyBCb3VuZCB7XG5cbiAgY29uc3RydWN0b3IodmFsdWUpIHtcbiAgICB0aGlzLnZhbHVlID0gdmFsdWU7XG4gIH1cbn1cblxuZnVuY3Rpb24gdmFyaWFibGUobmFtZSA9IG51bGwpIHtcbiAgcmV0dXJuIG5ldyBWYXJpYWJsZShuYW1lKTtcbn1cblxuZnVuY3Rpb24gd2lsZGNhcmQoKSB7XG4gIHJldHVybiBuZXcgV2lsZGNhcmQoKTtcbn1cblxuZnVuY3Rpb24gc3RhcnRzV2l0aChwcmVmaXgpIHtcbiAgcmV0dXJuIG5ldyBTdGFydHNXaXRoKHByZWZpeCk7XG59XG5cbmZ1bmN0aW9uIGNhcHR1cmUodmFsdWUpIHtcbiAgcmV0dXJuIG5ldyBDYXB0dXJlKHZhbHVlKTtcbn1cblxuZnVuY3Rpb24gaGVhZFRhaWwoKSB7XG4gIHJldHVybiBuZXcgSGVhZFRhaWwoKTtcbn1cblxuZnVuY3Rpb24gdHlwZSh0eXBlLCBvYmpQYXR0ZXJuID0ge30pIHtcbiAgcmV0dXJuIG5ldyBUeXBlKHR5cGUsIG9ialBhdHRlcm4pO1xufVxuXG5mdW5jdGlvbiBib3VuZCh2YWx1ZSkge1xuICByZXR1cm4gbmV3IEJvdW5kKHZhbHVlKTtcbn1cblxuZnVuY3Rpb24gaXNfbnVtYmVyJDEodmFsdWUpIHtcbiAgcmV0dXJuIHR5cGVvZiB2YWx1ZSA9PT0gJ251bWJlcic7XG59XG5cbmZ1bmN0aW9uIGlzX3N0cmluZyh2YWx1ZSkge1xuICByZXR1cm4gdHlwZW9mIHZhbHVlID09PSAnc3RyaW5nJztcbn1cblxuZnVuY3Rpb24gaXNfYm9vbGVhbiQxKHZhbHVlKSB7XG4gIHJldHVybiB0eXBlb2YgdmFsdWUgPT09ICdib29sZWFuJztcbn1cblxuZnVuY3Rpb24gaXNfc3ltYm9sKHZhbHVlKSB7XG4gIHJldHVybiB0eXBlb2YgdmFsdWUgPT09ICdzeW1ib2wnO1xufVxuXG5mdW5jdGlvbiBpc19udWxsKHZhbHVlKSB7XG4gIHJldHVybiB2YWx1ZSA9PT0gbnVsbDtcbn1cblxuZnVuY3Rpb24gaXNfdW5kZWZpbmVkKHZhbHVlKSB7XG4gIHJldHVybiB0eXBlb2YgdmFsdWUgPT09ICd1bmRlZmluZWQnO1xufVxuXG5mdW5jdGlvbiBpc19mdW5jdGlvbiQxKHZhbHVlKSB7XG4gIHJldHVybiBPYmplY3QucHJvdG90eXBlLnRvU3RyaW5nLmNhbGwodmFsdWUpID09ICdbb2JqZWN0IEZ1bmN0aW9uXSc7XG59XG5cbmZ1bmN0aW9uIGlzX3ZhcmlhYmxlKHZhbHVlKSB7XG4gIHJldHVybiB2YWx1ZSBpbnN0YW5jZW9mIFZhcmlhYmxlO1xufVxuXG5mdW5jdGlvbiBpc193aWxkY2FyZCh2YWx1ZSkge1xuICByZXR1cm4gdmFsdWUgaW5zdGFuY2VvZiBXaWxkY2FyZDtcbn1cblxuZnVuY3Rpb24gaXNfaGVhZFRhaWwodmFsdWUpIHtcbiAgcmV0dXJuIHZhbHVlIGluc3RhbmNlb2YgSGVhZFRhaWw7XG59XG5cbmZ1bmN0aW9uIGlzX2NhcHR1cmUodmFsdWUpIHtcbiAgcmV0dXJuIHZhbHVlIGluc3RhbmNlb2YgQ2FwdHVyZTtcbn1cblxuZnVuY3Rpb24gaXNfdHlwZSh2YWx1ZSkge1xuICByZXR1cm4gdmFsdWUgaW5zdGFuY2VvZiBUeXBlO1xufVxuXG5mdW5jdGlvbiBpc19zdGFydHNXaXRoKHZhbHVlKSB7XG4gIHJldHVybiB2YWx1ZSBpbnN0YW5jZW9mIFN0YXJ0c1dpdGg7XG59XG5cbmZ1bmN0aW9uIGlzX2JvdW5kKHZhbHVlKSB7XG4gIHJldHVybiB2YWx1ZSBpbnN0YW5jZW9mIEJvdW5kO1xufVxuXG5mdW5jdGlvbiBpc19vYmplY3QodmFsdWUpIHtcbiAgcmV0dXJuIHR5cGVvZiB2YWx1ZSA9PT0gJ29iamVjdCc7XG59XG5cbmZ1bmN0aW9uIGlzX2FycmF5KHZhbHVlKSB7XG4gIHJldHVybiBBcnJheS5pc0FycmF5KHZhbHVlKTtcbn1cblxudmFyIENoZWNrcyA9IHtcbiAgaXNfbnVtYmVyOiBpc19udW1iZXIkMSxcbiAgaXNfc3RyaW5nLFxuICBpc19ib29sZWFuOiBpc19ib29sZWFuJDEsXG4gIGlzX3N5bWJvbCxcbiAgaXNfbnVsbCxcbiAgaXNfdW5kZWZpbmVkLFxuICBpc19mdW5jdGlvbjogaXNfZnVuY3Rpb24kMSxcbiAgaXNfdmFyaWFibGUsXG4gIGlzX3dpbGRjYXJkLFxuICBpc19oZWFkVGFpbCxcbiAgaXNfY2FwdHVyZSxcbiAgaXNfdHlwZSxcbiAgaXNfc3RhcnRzV2l0aCxcbiAgaXNfYm91bmQsXG4gIGlzX29iamVjdCxcbiAgaXNfYXJyYXlcbn07XG5cbmZ1bmN0aW9uIHJlc29sdmVTeW1ib2wocGF0dGVybikge1xuICByZXR1cm4gZnVuY3Rpb24gKHZhbHVlKSB7XG4gICAgcmV0dXJuIENoZWNrcy5pc19zeW1ib2wodmFsdWUpICYmIHZhbHVlID09PSBwYXR0ZXJuO1xuICB9O1xufVxuXG5mdW5jdGlvbiByZXNvbHZlU3RyaW5nKHBhdHRlcm4pIHtcbiAgcmV0dXJuIGZ1bmN0aW9uICh2YWx1ZSkge1xuICAgIHJldHVybiBDaGVja3MuaXNfc3RyaW5nKHZhbHVlKSAmJiB2YWx1ZSA9PT0gcGF0dGVybjtcbiAgfTtcbn1cblxuZnVuY3Rpb24gcmVzb2x2ZU51bWJlcihwYXR0ZXJuKSB7XG4gIHJldHVybiBmdW5jdGlvbiAodmFsdWUpIHtcbiAgICByZXR1cm4gQ2hlY2tzLmlzX251bWJlcih2YWx1ZSkgJiYgdmFsdWUgPT09IHBhdHRlcm47XG4gIH07XG59XG5cbmZ1bmN0aW9uIHJlc29sdmVCb29sZWFuKHBhdHRlcm4pIHtcbiAgcmV0dXJuIGZ1bmN0aW9uICh2YWx1ZSkge1xuICAgIHJldHVybiBDaGVja3MuaXNfYm9vbGVhbih2YWx1ZSkgJiYgdmFsdWUgPT09IHBhdHRlcm47XG4gIH07XG59XG5cbmZ1bmN0aW9uIHJlc29sdmVGdW5jdGlvbihwYXR0ZXJuKSB7XG4gIHJldHVybiBmdW5jdGlvbiAodmFsdWUpIHtcbiAgICByZXR1cm4gQ2hlY2tzLmlzX2Z1bmN0aW9uKHZhbHVlKSAmJiB2YWx1ZSA9PT0gcGF0dGVybjtcbiAgfTtcbn1cblxuZnVuY3Rpb24gcmVzb2x2ZU51bGwocGF0dGVybikge1xuICByZXR1cm4gZnVuY3Rpb24gKHZhbHVlKSB7XG4gICAgcmV0dXJuIENoZWNrcy5pc19udWxsKHZhbHVlKTtcbiAgfTtcbn1cblxuZnVuY3Rpb24gcmVzb2x2ZUJvdW5kKHBhdHRlcm4pIHtcbiAgcmV0dXJuIGZ1bmN0aW9uICh2YWx1ZSwgYXJncykge1xuICAgIGlmICh0eXBlb2YgdmFsdWUgPT09IHR5cGVvZiBwYXR0ZXJuLnZhbHVlICYmIHZhbHVlID09PSBwYXR0ZXJuLnZhbHVlKSB7XG4gICAgICBhcmdzLnB1c2godmFsdWUpO1xuICAgICAgcmV0dXJuIHRydWU7XG4gICAgfVxuXG4gICAgcmV0dXJuIGZhbHNlO1xuICB9O1xufVxuXG5mdW5jdGlvbiByZXNvbHZlV2lsZGNhcmQoKSB7XG4gIHJldHVybiBmdW5jdGlvbiAoKSB7XG4gICAgcmV0dXJuIHRydWU7XG4gIH07XG59XG5cbmZ1bmN0aW9uIHJlc29sdmVWYXJpYWJsZSgpIHtcbiAgcmV0dXJuIGZ1bmN0aW9uICh2YWx1ZSwgYXJncykge1xuICAgIGFyZ3MucHVzaCh2YWx1ZSk7XG4gICAgcmV0dXJuIHRydWU7XG4gIH07XG59XG5cbmZ1bmN0aW9uIHJlc29sdmVIZWFkVGFpbCgpIHtcbiAgcmV0dXJuIGZ1bmN0aW9uICh2YWx1ZSwgYXJncykge1xuICAgIGlmICghQ2hlY2tzLmlzX2FycmF5KHZhbHVlKSB8fCB2YWx1ZS5sZW5ndGggPCAyKSB7XG4gICAgICByZXR1cm4gZmFsc2U7XG4gICAgfVxuXG4gICAgY29uc3QgaGVhZCA9IHZhbHVlWzBdO1xuICAgIGNvbnN0IHRhaWwgPSB2YWx1ZS5zbGljZSgxKTtcblxuICAgIGFyZ3MucHVzaChoZWFkKTtcbiAgICBhcmdzLnB1c2godGFpbCk7XG5cbiAgICByZXR1cm4gdHJ1ZTtcbiAgfTtcbn1cblxuZnVuY3Rpb24gcmVzb2x2ZUNhcHR1cmUocGF0dGVybikge1xuICBjb25zdCBtYXRjaGVzID0gYnVpbGRNYXRjaChwYXR0ZXJuLnZhbHVlKTtcblxuICByZXR1cm4gZnVuY3Rpb24gKHZhbHVlLCBhcmdzKSB7XG4gICAgaWYgKG1hdGNoZXModmFsdWUsIGFyZ3MpKSB7XG4gICAgICBhcmdzLnB1c2godmFsdWUpO1xuICAgICAgcmV0dXJuIHRydWU7XG4gICAgfVxuXG4gICAgcmV0dXJuIGZhbHNlO1xuICB9O1xufVxuXG5mdW5jdGlvbiByZXNvbHZlU3RhcnRzV2l0aChwYXR0ZXJuKSB7XG4gIGNvbnN0IHByZWZpeCA9IHBhdHRlcm4ucHJlZml4O1xuXG4gIHJldHVybiBmdW5jdGlvbiAodmFsdWUsIGFyZ3MpIHtcbiAgICBpZiAoQ2hlY2tzLmlzX3N0cmluZyh2YWx1ZSkgJiYgdmFsdWUuc3RhcnRzV2l0aChwcmVmaXgpKSB7XG4gICAgICBhcmdzLnB1c2godmFsdWUuc3Vic3RyaW5nKHByZWZpeC5sZW5ndGgpKTtcbiAgICAgIHJldHVybiB0cnVlO1xuICAgIH1cblxuICAgIHJldHVybiBmYWxzZTtcbiAgfTtcbn1cblxuZnVuY3Rpb24gcmVzb2x2ZVR5cGUocGF0dGVybikge1xuICByZXR1cm4gZnVuY3Rpb24gKHZhbHVlLCBhcmdzKSB7XG4gICAgaWYgKHZhbHVlIGluc3RhbmNlb2YgcGF0dGVybi50eXBlKSB7XG4gICAgICBjb25zdCBtYXRjaGVzID0gYnVpbGRNYXRjaChwYXR0ZXJuLm9ialBhdHRlcm4pO1xuICAgICAgcmV0dXJuIG1hdGNoZXModmFsdWUsIGFyZ3MpICYmIGFyZ3MucHVzaCh2YWx1ZSkgPiAwO1xuICAgIH1cblxuICAgIHJldHVybiBmYWxzZTtcbiAgfTtcbn1cblxuZnVuY3Rpb24gcmVzb2x2ZUFycmF5KHBhdHRlcm4pIHtcbiAgY29uc3QgbWF0Y2hlcyA9IHBhdHRlcm4ubWFwKHggPT4gYnVpbGRNYXRjaCh4KSk7XG5cbiAgcmV0dXJuIGZ1bmN0aW9uICh2YWx1ZSwgYXJncykge1xuICAgIGlmICghQ2hlY2tzLmlzX2FycmF5KHZhbHVlKSB8fCB2YWx1ZS5sZW5ndGggIT0gcGF0dGVybi5sZW5ndGgpIHtcbiAgICAgIHJldHVybiBmYWxzZTtcbiAgICB9XG5cbiAgICByZXR1cm4gdmFsdWUuZXZlcnkoZnVuY3Rpb24gKHYsIGkpIHtcbiAgICAgIHJldHVybiBtYXRjaGVzW2ldKHZhbHVlW2ldLCBhcmdzKTtcbiAgICB9KTtcbiAgfTtcbn1cblxuZnVuY3Rpb24gcmVzb2x2ZU9iamVjdChwYXR0ZXJuKSB7XG4gIGxldCBtYXRjaGVzID0ge307XG5cbiAgZm9yIChsZXQga2V5IG9mIE9iamVjdC5rZXlzKHBhdHRlcm4pKSB7XG4gICAgbWF0Y2hlc1trZXldID0gYnVpbGRNYXRjaChwYXR0ZXJuW2tleV0pO1xuICB9XG5cbiAgcmV0dXJuIGZ1bmN0aW9uICh2YWx1ZSwgYXJncykge1xuICAgIGlmICghQ2hlY2tzLmlzX29iamVjdCh2YWx1ZSkgfHwgcGF0dGVybi5sZW5ndGggPiB2YWx1ZS5sZW5ndGgpIHtcbiAgICAgIHJldHVybiBmYWxzZTtcbiAgICB9XG5cbiAgICBmb3IgKGxldCBrZXkgb2YgT2JqZWN0LmtleXMocGF0dGVybikpIHtcbiAgICAgIGlmICghKGtleSBpbiB2YWx1ZSkgfHwgIW1hdGNoZXNba2V5XSh2YWx1ZVtrZXldLCBhcmdzKSkge1xuICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICB9XG4gICAgfVxuXG4gICAgcmV0dXJuIHRydWU7XG4gIH07XG59XG5cbmZ1bmN0aW9uIHJlc29sdmVOb01hdGNoKCkge1xuICByZXR1cm4gZnVuY3Rpb24gKCkge1xuICAgIHJldHVybiBmYWxzZTtcbiAgfTtcbn1cblxudmFyIFJlc29sdmVycyA9IHtcbiAgcmVzb2x2ZUJvdW5kLFxuICByZXNvbHZlV2lsZGNhcmQsXG4gIHJlc29sdmVWYXJpYWJsZSxcbiAgcmVzb2x2ZUhlYWRUYWlsLFxuICByZXNvbHZlQ2FwdHVyZSxcbiAgcmVzb2x2ZVN0YXJ0c1dpdGgsXG4gIHJlc29sdmVUeXBlLFxuICByZXNvbHZlQXJyYXksXG4gIHJlc29sdmVPYmplY3QsXG4gIHJlc29sdmVOb01hdGNoLFxuICByZXNvbHZlU3ltYm9sLFxuICByZXNvbHZlU3RyaW5nLFxuICByZXNvbHZlTnVtYmVyLFxuICByZXNvbHZlQm9vbGVhbixcbiAgcmVzb2x2ZUZ1bmN0aW9uLFxuICByZXNvbHZlTnVsbFxufTtcblxuZnVuY3Rpb24gYnVpbGRNYXRjaChwYXR0ZXJuKSB7XG5cbiAgaWYgKENoZWNrcy5pc192YXJpYWJsZShwYXR0ZXJuKSkge1xuICAgIHJldHVybiBSZXNvbHZlcnMucmVzb2x2ZVZhcmlhYmxlKHBhdHRlcm4pO1xuICB9XG5cbiAgaWYgKENoZWNrcy5pc193aWxkY2FyZChwYXR0ZXJuKSkge1xuICAgIHJldHVybiBSZXNvbHZlcnMucmVzb2x2ZVdpbGRjYXJkKHBhdHRlcm4pO1xuICB9XG5cbiAgaWYgKENoZWNrcy5pc191bmRlZmluZWQocGF0dGVybikpIHtcbiAgICByZXR1cm4gUmVzb2x2ZXJzLnJlc29sdmVXaWxkY2FyZChwYXR0ZXJuKTtcbiAgfVxuXG4gIGlmIChDaGVja3MuaXNfaGVhZFRhaWwocGF0dGVybikpIHtcbiAgICByZXR1cm4gUmVzb2x2ZXJzLnJlc29sdmVIZWFkVGFpbChwYXR0ZXJuKTtcbiAgfVxuXG4gIGlmIChDaGVja3MuaXNfc3RhcnRzV2l0aChwYXR0ZXJuKSkge1xuICAgIHJldHVybiBSZXNvbHZlcnMucmVzb2x2ZVN0YXJ0c1dpdGgocGF0dGVybik7XG4gIH1cblxuICBpZiAoQ2hlY2tzLmlzX2NhcHR1cmUocGF0dGVybikpIHtcbiAgICByZXR1cm4gUmVzb2x2ZXJzLnJlc29sdmVDYXB0dXJlKHBhdHRlcm4pO1xuICB9XG5cbiAgaWYgKENoZWNrcy5pc19ib3VuZChwYXR0ZXJuKSkge1xuICAgIHJldHVybiBSZXNvbHZlcnMucmVzb2x2ZUJvdW5kKHBhdHRlcm4pO1xuICB9XG5cbiAgaWYgKENoZWNrcy5pc190eXBlKHBhdHRlcm4pKSB7XG4gICAgcmV0dXJuIFJlc29sdmVycy5yZXNvbHZlVHlwZShwYXR0ZXJuKTtcbiAgfVxuXG4gIGlmIChDaGVja3MuaXNfYXJyYXkocGF0dGVybikpIHtcbiAgICByZXR1cm4gUmVzb2x2ZXJzLnJlc29sdmVBcnJheShwYXR0ZXJuKTtcbiAgfVxuXG4gIGlmIChDaGVja3MuaXNfbnVtYmVyKHBhdHRlcm4pKSB7XG4gICAgcmV0dXJuIFJlc29sdmVycy5yZXNvbHZlTnVtYmVyKHBhdHRlcm4pO1xuICB9XG5cbiAgaWYgKENoZWNrcy5pc19zdHJpbmcocGF0dGVybikpIHtcbiAgICByZXR1cm4gUmVzb2x2ZXJzLnJlc29sdmVTdHJpbmcocGF0dGVybik7XG4gIH1cblxuICBpZiAoQ2hlY2tzLmlzX2Jvb2xlYW4ocGF0dGVybikpIHtcbiAgICByZXR1cm4gUmVzb2x2ZXJzLnJlc29sdmVCb29sZWFuKHBhdHRlcm4pO1xuICB9XG5cbiAgaWYgKENoZWNrcy5pc19zeW1ib2wocGF0dGVybikpIHtcbiAgICByZXR1cm4gUmVzb2x2ZXJzLnJlc29sdmVTeW1ib2wocGF0dGVybik7XG4gIH1cblxuICBpZiAoQ2hlY2tzLmlzX251bGwocGF0dGVybikpIHtcbiAgICByZXR1cm4gUmVzb2x2ZXJzLnJlc29sdmVOdWxsKHBhdHRlcm4pO1xuICB9XG5cbiAgaWYgKENoZWNrcy5pc19vYmplY3QocGF0dGVybikpIHtcbiAgICByZXR1cm4gUmVzb2x2ZXJzLnJlc29sdmVPYmplY3QocGF0dGVybik7XG4gIH1cblxuICByZXR1cm4gUmVzb2x2ZXJzLnJlc29sdmVOb01hdGNoKCk7XG59XG5cbmNsYXNzIE1hdGNoRXJyb3IgZXh0ZW5kcyBFcnJvciB7XG4gIGNvbnN0cnVjdG9yKGFyZykge1xuICAgIHN1cGVyKCk7XG5cbiAgICBpZiAodHlwZW9mIGFyZyA9PT0gJ3N5bWJvbCcpIHtcbiAgICAgIHRoaXMubWVzc2FnZSA9ICdObyBtYXRjaCBmb3I6ICcgKyBhcmcudG9TdHJpbmcoKTtcbiAgICB9IGVsc2UgaWYgKEFycmF5LmlzQXJyYXkoYXJnKSkge1xuICAgICAgbGV0IG1hcHBlZFZhbHVlcyA9IGFyZy5tYXAoeCA9PiB4LnRvU3RyaW5nKCkpO1xuICAgICAgdGhpcy5tZXNzYWdlID0gJ05vIG1hdGNoIGZvcjogJyArIG1hcHBlZFZhbHVlcztcbiAgICB9IGVsc2Uge1xuICAgICAgdGhpcy5tZXNzYWdlID0gJ05vIG1hdGNoIGZvcjogJyArIGFyZztcbiAgICB9XG5cbiAgICB0aGlzLnN0YWNrID0gbmV3IEVycm9yKCkuc3RhY2s7XG4gICAgdGhpcy5uYW1lID0gdGhpcy5jb25zdHJ1Y3Rvci5uYW1lO1xuICB9XG59XG5cbmNsYXNzIENhc2Uge1xuXG4gIGNvbnN0cnVjdG9yKHBhdHRlcm4sIGZuLCBndWFyZCA9ICgpID0+IHRydWUpIHtcbiAgICB0aGlzLnBhdHRlcm4gPSBidWlsZE1hdGNoKHBhdHRlcm4pO1xuICAgIHRoaXMuZm4gPSBmbjtcbiAgICB0aGlzLmd1YXJkID0gZ3VhcmQ7XG4gIH1cbn1cblxuZnVuY3Rpb24gbWFrZV9jYXNlKHBhdHRlcm4sIGZuLCBndWFyZCA9ICgpID0+IHRydWUpIHtcbiAgcmV0dXJuIG5ldyBDYXNlKHBhdHRlcm4sIGZuLCBndWFyZCk7XG59XG5cbmZ1bmN0aW9uIGRlZm1hdGNoKC4uLmNhc2VzKSB7XG4gIHJldHVybiBmdW5jdGlvbiAoLi4uYXJncykge1xuICAgIGZvciAobGV0IHByb2Nlc3NlZENhc2Ugb2YgY2FzZXMpIHtcbiAgICAgIGxldCByZXN1bHQgPSBbXTtcbiAgICAgIGlmIChwcm9jZXNzZWRDYXNlLnBhdHRlcm4oYXJncywgcmVzdWx0KSAmJiBwcm9jZXNzZWRDYXNlLmd1YXJkLmFwcGx5KHRoaXMsIHJlc3VsdCkpIHtcbiAgICAgICAgcmV0dXJuIHByb2Nlc3NlZENhc2UuZm4uYXBwbHkodGhpcywgcmVzdWx0KTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICB0aHJvdyBuZXcgTWF0Y2hFcnJvcihhcmdzKTtcbiAgfTtcbn1cblxuZnVuY3Rpb24gbWF0Y2gocGF0dGVybiwgZXhwciwgZ3VhcmQgPSAoKSA9PiB0cnVlKSB7XG4gIGxldCByZXN1bHQgPSBbXTtcbiAgbGV0IHByb2Nlc3NlZFBhdHRlcm4gPSBidWlsZE1hdGNoKHBhdHRlcm4pO1xuICBpZiAocHJvY2Vzc2VkUGF0dGVybihleHByLCByZXN1bHQpICYmIGd1YXJkLmFwcGx5KHRoaXMsIHJlc3VsdCkpIHtcbiAgICByZXR1cm4gcmVzdWx0O1xuICB9IGVsc2Uge1xuICAgIHRocm93IG5ldyBNYXRjaEVycm9yKGV4cHIpO1xuICB9XG59XG5cbmZ1bmN0aW9uIG1hdGNoX25vX3Rocm93KHBhdHRlcm4sIGV4cHIsIGd1YXJkID0gKCkgPT4gdHJ1ZSkge1xuICB0cnkge1xuICAgIHJldHVybiBtYXRjaChwYXR0ZXJuLCBleHByLCBndWFyZCk7XG4gIH0gY2F0Y2ggKGUpIHtcbiAgICBpZiAoZSBpbnN0YW5jZW9mIE1hdGNoRXJyb3IpIHtcbiAgICAgIHJldHVybiBudWxsO1xuICAgIH1cblxuICAgIHRocm93IGU7XG4gIH1cbn1cblxudmFyIFBhdHRlcm5zID0ge1xuICBkZWZtYXRjaCwgbWF0Y2gsIE1hdGNoRXJyb3IsIG1hdGNoX25vX3Rocm93LFxuICB2YXJpYWJsZSwgd2lsZGNhcmQsIHN0YXJ0c1dpdGgsXG4gIGNhcHR1cmUsIGhlYWRUYWlsLCB0eXBlLCBib3VuZCwgQ2FzZSwgbWFrZV9jYXNlXG59O1xuXG5jbGFzcyBCaXRTdHJpbmcge1xuICBjb25zdHJ1Y3RvciguLi5hcmdzKSB7XG4gICAgdGhpcy5yYXdfdmFsdWUgPSBmdW5jdGlvbiAoKSB7XG4gICAgICByZXR1cm4gT2JqZWN0LmZyZWV6ZShhcmdzKTtcbiAgICB9O1xuXG4gICAgdGhpcy52YWx1ZSA9IE9iamVjdC5mcmVlemUodGhpcy5wcm9jZXNzKGFyZ3MpKTtcbiAgfVxuXG4gIGdldChpbmRleCkge1xuICAgIHJldHVybiB0aGlzLnZhbHVlW2luZGV4XTtcbiAgfVxuXG4gIGNvdW50KCkge1xuICAgIHJldHVybiB0aGlzLnZhbHVlLmxlbmd0aDtcbiAgfVxuXG4gIFtTeW1ib2wuaXRlcmF0b3JdKCkge1xuICAgIHJldHVybiB0aGlzLnZhbHVlW1N5bWJvbC5pdGVyYXRvcl0oKTtcbiAgfVxuXG4gIHRvU3RyaW5nKCkge1xuICAgIHZhciBpLFxuICAgICAgICBzID0gXCJcIjtcbiAgICBmb3IgKGkgPSAwOyBpIDwgdGhpcy5jb3VudCgpOyBpKyspIHtcbiAgICAgIGlmIChzICE9PSBcIlwiKSB7XG4gICAgICAgIHMgKz0gXCIsIFwiO1xuICAgICAgfVxuICAgICAgcyArPSB0aGlzW2ldLnRvU3RyaW5nKCk7XG4gICAgfVxuXG4gICAgcmV0dXJuIFwiPDxcIiArIHMgKyBcIj4+XCI7XG4gIH1cblxuICBwcm9jZXNzKCkge1xuICAgIGxldCBwcm9jZXNzZWRfdmFsdWVzID0gW107XG5cbiAgICB2YXIgaTtcbiAgICBmb3IgKGkgPSAwOyBpIDwgdGhpcy5yYXdfdmFsdWUoKS5sZW5ndGg7IGkrKykge1xuICAgICAgbGV0IHByb2Nlc3NlZF92YWx1ZSA9IHRoaXNbXCJwcm9jZXNzX1wiICsgdGhpcy5yYXdfdmFsdWUoKVtpXS50eXBlXSh0aGlzLnJhd192YWx1ZSgpW2ldKTtcblxuICAgICAgZm9yIChsZXQgYXR0ciBvZiB0aGlzLnJhd192YWx1ZSgpW2ldLmF0dHJpYnV0ZXMpIHtcbiAgICAgICAgcHJvY2Vzc2VkX3ZhbHVlID0gdGhpc1tcInByb2Nlc3NfXCIgKyBhdHRyXShwcm9jZXNzZWRfdmFsdWUpO1xuICAgICAgfVxuXG4gICAgICBwcm9jZXNzZWRfdmFsdWVzID0gcHJvY2Vzc2VkX3ZhbHVlcy5jb25jYXQocHJvY2Vzc2VkX3ZhbHVlKTtcbiAgICB9XG5cbiAgICByZXR1cm4gcHJvY2Vzc2VkX3ZhbHVlcztcbiAgfVxuXG4gIHByb2Nlc3NfaW50ZWdlcih2YWx1ZSkge1xuICAgIHJldHVybiB2YWx1ZS52YWx1ZTtcbiAgfVxuXG4gIHByb2Nlc3NfZmxvYXQodmFsdWUpIHtcbiAgICBpZiAodmFsdWUuc2l6ZSA9PT0gNjQpIHtcbiAgICAgIHJldHVybiBCaXRTdHJpbmcuZmxvYXQ2NFRvQnl0ZXModmFsdWUudmFsdWUpO1xuICAgIH0gZWxzZSBpZiAodmFsdWUuc2l6ZSA9PT0gMzIpIHtcbiAgICAgIHJldHVybiBCaXRTdHJpbmcuZmxvYXQzMlRvQnl0ZXModmFsdWUudmFsdWUpO1xuICAgIH1cblxuICAgIHRocm93IG5ldyBFcnJvcihcIkludmFsaWQgc2l6ZSBmb3IgZmxvYXRcIik7XG4gIH1cblxuICBwcm9jZXNzX2JpdHN0cmluZyh2YWx1ZSkge1xuICAgIHJldHVybiB2YWx1ZS52YWx1ZS52YWx1ZTtcbiAgfVxuXG4gIHByb2Nlc3NfYmluYXJ5KHZhbHVlKSB7XG4gICAgcmV0dXJuIEJpdFN0cmluZy50b1VURjhBcnJheSh2YWx1ZS52YWx1ZSk7XG4gIH1cblxuICBwcm9jZXNzX3V0ZjgodmFsdWUpIHtcbiAgICByZXR1cm4gQml0U3RyaW5nLnRvVVRGOEFycmF5KHZhbHVlLnZhbHVlKTtcbiAgfVxuXG4gIHByb2Nlc3NfdXRmMTYodmFsdWUpIHtcbiAgICByZXR1cm4gQml0U3RyaW5nLnRvVVRGMTZBcnJheSh2YWx1ZS52YWx1ZSk7XG4gIH1cblxuICBwcm9jZXNzX3V0ZjMyKHZhbHVlKSB7XG4gICAgcmV0dXJuIEJpdFN0cmluZy50b1VURjMyQXJyYXkodmFsdWUudmFsdWUpO1xuICB9XG5cbiAgcHJvY2Vzc19zaWduZWQodmFsdWUpIHtcbiAgICByZXR1cm4gbmV3IFVpbnQ4QXJyYXkoW3ZhbHVlXSlbMF07XG4gIH1cblxuICBwcm9jZXNzX3Vuc2lnbmVkKHZhbHVlKSB7XG4gICAgcmV0dXJuIHZhbHVlO1xuICB9XG5cbiAgcHJvY2Vzc19uYXRpdmUodmFsdWUpIHtcbiAgICByZXR1cm4gdmFsdWU7XG4gIH1cblxuICBwcm9jZXNzX2JpZyh2YWx1ZSkge1xuICAgIHJldHVybiB2YWx1ZTtcbiAgfVxuXG4gIHByb2Nlc3NfbGl0dGxlKHZhbHVlKSB7XG4gICAgcmV0dXJuIHZhbHVlLnJldmVyc2UoKTtcbiAgfVxuXG4gIHByb2Nlc3Nfc2l6ZSh2YWx1ZSkge1xuICAgIHJldHVybiB2YWx1ZTtcbiAgfVxuXG4gIHByb2Nlc3NfdW5pdCh2YWx1ZSkge1xuICAgIHJldHVybiB2YWx1ZTtcbiAgfVxuXG4gIHN0YXRpYyBpbnRlZ2VyKHZhbHVlKSB7XG4gICAgcmV0dXJuIEJpdFN0cmluZy53cmFwKHZhbHVlLCB7IFwidHlwZVwiOiBcImludGVnZXJcIiwgXCJ1bml0XCI6IDEsIFwic2l6ZVwiOiA4IH0pO1xuICB9XG5cbiAgc3RhdGljIGZsb2F0KHZhbHVlKSB7XG4gICAgcmV0dXJuIEJpdFN0cmluZy53cmFwKHZhbHVlLCB7IFwidHlwZVwiOiBcImZsb2F0XCIsIFwidW5pdFwiOiAxLCBcInNpemVcIjogNjQgfSk7XG4gIH1cblxuICBzdGF0aWMgYml0c3RyaW5nKHZhbHVlKSB7XG4gICAgcmV0dXJuIEJpdFN0cmluZy53cmFwKHZhbHVlLCB7IFwidHlwZVwiOiBcImJpdHN0cmluZ1wiLCBcInVuaXRcIjogMSwgXCJzaXplXCI6IHZhbHVlLmxlbmd0aCB9KTtcbiAgfVxuXG4gIHN0YXRpYyBiaXRzKHZhbHVlKSB7XG4gICAgcmV0dXJuIEJpdFN0cmluZy5iaXRzdHJpbmcodmFsdWUpO1xuICB9XG5cbiAgc3RhdGljIGJpbmFyeSh2YWx1ZSkge1xuICAgIHJldHVybiBCaXRTdHJpbmcud3JhcCh2YWx1ZSwgeyBcInR5cGVcIjogXCJiaW5hcnlcIiwgXCJ1bml0XCI6IDgsIFwic2l6ZVwiOiB2YWx1ZS5sZW5ndGggfSk7XG4gIH1cblxuICBzdGF0aWMgYnl0ZXModmFsdWUpIHtcbiAgICByZXR1cm4gQml0U3RyaW5nLmJpbmFyeSh2YWx1ZSk7XG4gIH1cblxuICBzdGF0aWMgdXRmOCh2YWx1ZSkge1xuICAgIHJldHVybiBCaXRTdHJpbmcud3JhcCh2YWx1ZSwgeyBcInR5cGVcIjogXCJ1dGY4XCIgfSk7XG4gIH1cblxuICBzdGF0aWMgdXRmMTYodmFsdWUpIHtcbiAgICByZXR1cm4gQml0U3RyaW5nLndyYXAodmFsdWUsIHsgXCJ0eXBlXCI6IFwidXRmMTZcIiB9KTtcbiAgfVxuXG4gIHN0YXRpYyB1dGYzMih2YWx1ZSkge1xuICAgIHJldHVybiBCaXRTdHJpbmcud3JhcCh2YWx1ZSwgeyBcInR5cGVcIjogXCJ1dGYzMlwiIH0pO1xuICB9XG5cbiAgc3RhdGljIHNpZ25lZCh2YWx1ZSkge1xuICAgIHJldHVybiBCaXRTdHJpbmcud3JhcCh2YWx1ZSwge30sIFwic2lnbmVkXCIpO1xuICB9XG5cbiAgc3RhdGljIHVuc2lnbmVkKHZhbHVlKSB7XG4gICAgcmV0dXJuIEJpdFN0cmluZy53cmFwKHZhbHVlLCB7fSwgXCJ1bnNpZ25lZFwiKTtcbiAgfVxuXG4gIHN0YXRpYyBuYXRpdmUodmFsdWUpIHtcbiAgICByZXR1cm4gQml0U3RyaW5nLndyYXAodmFsdWUsIHt9LCBcIm5hdGl2ZVwiKTtcbiAgfVxuXG4gIHN0YXRpYyBiaWcodmFsdWUpIHtcbiAgICByZXR1cm4gQml0U3RyaW5nLndyYXAodmFsdWUsIHt9LCBcImJpZ1wiKTtcbiAgfVxuXG4gIHN0YXRpYyBsaXR0bGUodmFsdWUpIHtcbiAgICByZXR1cm4gQml0U3RyaW5nLndyYXAodmFsdWUsIHt9LCBcImxpdHRsZVwiKTtcbiAgfVxuXG4gIHN0YXRpYyBzaXplKHZhbHVlLCBjb3VudCkge1xuICAgIHJldHVybiBCaXRTdHJpbmcud3JhcCh2YWx1ZSwgeyBcInNpemVcIjogY291bnQgfSk7XG4gIH1cblxuICBzdGF0aWMgdW5pdCh2YWx1ZSwgY291bnQpIHtcbiAgICByZXR1cm4gQml0U3RyaW5nLndyYXAodmFsdWUsIHsgXCJ1bml0XCI6IGNvdW50IH0pO1xuICB9XG5cbiAgc3RhdGljIHdyYXAodmFsdWUsIG9wdCwgbmV3X2F0dHJpYnV0ZSA9IG51bGwpIHtcbiAgICBsZXQgdGhlX3ZhbHVlID0gdmFsdWU7XG5cbiAgICBpZiAoISh2YWx1ZSBpbnN0YW5jZW9mIE9iamVjdCkpIHtcbiAgICAgIHRoZV92YWx1ZSA9IHsgXCJ2YWx1ZVwiOiB2YWx1ZSwgXCJhdHRyaWJ1dGVzXCI6IFtdIH07XG4gICAgfVxuXG4gICAgdGhlX3ZhbHVlID0gT2JqZWN0LmFzc2lnbih0aGVfdmFsdWUsIG9wdCk7XG5cbiAgICBpZiAobmV3X2F0dHJpYnV0ZSkge1xuICAgICAgdGhlX3ZhbHVlLmF0dHJpYnV0ZXMucHVzaChuZXdfYXR0cmlidXRlKTtcbiAgICB9XG5cbiAgICByZXR1cm4gdGhlX3ZhbHVlO1xuICB9XG5cbiAgc3RhdGljIHRvVVRGOEFycmF5KHN0cikge1xuICAgIHZhciB1dGY4ID0gW107XG4gICAgZm9yICh2YXIgaSA9IDA7IGkgPCBzdHIubGVuZ3RoOyBpKyspIHtcbiAgICAgIHZhciBjaGFyY29kZSA9IHN0ci5jaGFyQ29kZUF0KGkpO1xuICAgICAgaWYgKGNoYXJjb2RlIDwgMTI4KSB7XG4gICAgICAgIHV0ZjgucHVzaChjaGFyY29kZSk7XG4gICAgICB9IGVsc2UgaWYgKGNoYXJjb2RlIDwgMjA0OCkge1xuICAgICAgICB1dGY4LnB1c2goMTkyIHwgY2hhcmNvZGUgPj4gNiwgMTI4IHwgY2hhcmNvZGUgJiA2Myk7XG4gICAgICB9IGVsc2UgaWYgKGNoYXJjb2RlIDwgNTUyOTYgfHwgY2hhcmNvZGUgPj0gNTczNDQpIHtcbiAgICAgICAgdXRmOC5wdXNoKDIyNCB8IGNoYXJjb2RlID4+IDEyLCAxMjggfCBjaGFyY29kZSA+PiA2ICYgNjMsIDEyOCB8IGNoYXJjb2RlICYgNjMpO1xuICAgICAgfVxuICAgICAgLy8gc3Vycm9nYXRlIHBhaXJcbiAgICAgIGVsc2Uge1xuICAgICAgICBpKys7XG4gICAgICAgIC8vIFVURi0xNiBlbmNvZGVzIDB4MTAwMDAtMHgxMEZGRkYgYnlcbiAgICAgICAgLy8gc3VidHJhY3RpbmcgMHgxMDAwMCBhbmQgc3BsaXR0aW5nIHRoZVxuICAgICAgICAvLyAyMCBiaXRzIG9mIDB4MC0weEZGRkZGIGludG8gdHdvIGhhbHZlc1xuICAgICAgICBjaGFyY29kZSA9IDY1NTM2ICsgKChjaGFyY29kZSAmIDEwMjMpIDw8IDEwIHwgc3RyLmNoYXJDb2RlQXQoaSkgJiAxMDIzKTtcbiAgICAgICAgdXRmOC5wdXNoKDI0MCB8IGNoYXJjb2RlID4+IDE4LCAxMjggfCBjaGFyY29kZSA+PiAxMiAmIDYzLCAxMjggfCBjaGFyY29kZSA+PiA2ICYgNjMsIDEyOCB8IGNoYXJjb2RlICYgNjMpO1xuICAgICAgfVxuICAgIH1cbiAgICByZXR1cm4gdXRmODtcbiAgfVxuXG4gIHN0YXRpYyB0b1VURjE2QXJyYXkoc3RyKSB7XG4gICAgdmFyIHV0ZjE2ID0gW107XG4gICAgZm9yICh2YXIgaSA9IDA7IGkgPCBzdHIubGVuZ3RoOyBpKyspIHtcbiAgICAgIHZhciBjb2RlUG9pbnQgPSBzdHIuY29kZVBvaW50QXQoaSk7XG5cbiAgICAgIGlmIChjb2RlUG9pbnQgPD0gMjU1KSB7XG4gICAgICAgIHV0ZjE2LnB1c2goMCk7XG4gICAgICAgIHV0ZjE2LnB1c2goY29kZVBvaW50KTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHV0ZjE2LnB1c2goY29kZVBvaW50ID4+IDggJiAyNTUpO1xuICAgICAgICB1dGYxNi5wdXNoKGNvZGVQb2ludCAmIDI1NSk7XG4gICAgICB9XG4gICAgfVxuICAgIHJldHVybiB1dGYxNjtcbiAgfVxuXG4gIHN0YXRpYyB0b1VURjMyQXJyYXkoc3RyKSB7XG4gICAgdmFyIHV0ZjMyID0gW107XG4gICAgZm9yICh2YXIgaSA9IDA7IGkgPCBzdHIubGVuZ3RoOyBpKyspIHtcbiAgICAgIHZhciBjb2RlUG9pbnQgPSBzdHIuY29kZVBvaW50QXQoaSk7XG5cbiAgICAgIGlmIChjb2RlUG9pbnQgPD0gMjU1KSB7XG4gICAgICAgIHV0ZjMyLnB1c2goMCk7XG4gICAgICAgIHV0ZjMyLnB1c2goMCk7XG4gICAgICAgIHV0ZjMyLnB1c2goMCk7XG4gICAgICAgIHV0ZjMyLnB1c2goY29kZVBvaW50KTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHV0ZjMyLnB1c2goMCk7XG4gICAgICAgIHV0ZjMyLnB1c2goMCk7XG4gICAgICAgIHV0ZjMyLnB1c2goY29kZVBvaW50ID4+IDggJiAyNTUpO1xuICAgICAgICB1dGYzMi5wdXNoKGNvZGVQb2ludCAmIDI1NSk7XG4gICAgICB9XG4gICAgfVxuICAgIHJldHVybiB1dGYzMjtcbiAgfVxuXG4gIC8vaHR0cDovL3N0YWNrb3ZlcmZsb3cuY29tL3F1ZXN0aW9ucy8yMDAzNDkzL2phdmFzY3JpcHQtZmxvYXQtZnJvbS10by1iaXRzXG4gIHN0YXRpYyBmbG9hdDMyVG9CeXRlcyhmKSB7XG4gICAgdmFyIGJ5dGVzID0gW107XG5cbiAgICB2YXIgYnVmID0gbmV3IEFycmF5QnVmZmVyKDQpO1xuICAgIG5ldyBGbG9hdDMyQXJyYXkoYnVmKVswXSA9IGY7XG5cbiAgICBsZXQgaW50VmVyc2lvbiA9IG5ldyBVaW50MzJBcnJheShidWYpWzBdO1xuXG4gICAgYnl0ZXMucHVzaChpbnRWZXJzaW9uID4+IDI0ICYgMjU1KTtcbiAgICBieXRlcy5wdXNoKGludFZlcnNpb24gPj4gMTYgJiAyNTUpO1xuICAgIGJ5dGVzLnB1c2goaW50VmVyc2lvbiA+PiA4ICYgMjU1KTtcbiAgICBieXRlcy5wdXNoKGludFZlcnNpb24gJiAyNTUpO1xuXG4gICAgcmV0dXJuIGJ5dGVzO1xuICB9XG5cbiAgc3RhdGljIGZsb2F0NjRUb0J5dGVzKGYpIHtcbiAgICB2YXIgYnl0ZXMgPSBbXTtcblxuICAgIHZhciBidWYgPSBuZXcgQXJyYXlCdWZmZXIoOCk7XG4gICAgbmV3IEZsb2F0NjRBcnJheShidWYpWzBdID0gZjtcblxuICAgIHZhciBpbnRWZXJzaW9uMSA9IG5ldyBVaW50MzJBcnJheShidWYpWzBdO1xuICAgIHZhciBpbnRWZXJzaW9uMiA9IG5ldyBVaW50MzJBcnJheShidWYpWzFdO1xuXG4gICAgYnl0ZXMucHVzaChpbnRWZXJzaW9uMiA+PiAyNCAmIDI1NSk7XG4gICAgYnl0ZXMucHVzaChpbnRWZXJzaW9uMiA+PiAxNiAmIDI1NSk7XG4gICAgYnl0ZXMucHVzaChpbnRWZXJzaW9uMiA+PiA4ICYgMjU1KTtcbiAgICBieXRlcy5wdXNoKGludFZlcnNpb24yICYgMjU1KTtcblxuICAgIGJ5dGVzLnB1c2goaW50VmVyc2lvbjEgPj4gMjQgJiAyNTUpO1xuICAgIGJ5dGVzLnB1c2goaW50VmVyc2lvbjEgPj4gMTYgJiAyNTUpO1xuICAgIGJ5dGVzLnB1c2goaW50VmVyc2lvbjEgPj4gOCAmIDI1NSk7XG4gICAgYnl0ZXMucHVzaChpbnRWZXJzaW9uMSAmIDI1NSk7XG5cbiAgICByZXR1cm4gYnl0ZXM7XG4gIH1cbn1cblxubGV0IEVudW0gPSB7XG5cbiAgYWxsX19xbWFya19fOiBmdW5jdGlvbiAoY29sbGVjdGlvbiwgZnVuID0geCA9PiB4KSB7XG4gICAgZm9yIChsZXQgZWxlbSBvZiBjb2xsZWN0aW9uKSB7XG4gICAgICBpZiAoIWZ1bihlbGVtKSkge1xuICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICB9XG4gICAgfVxuXG4gICAgcmV0dXJuIHRydWU7XG4gIH0sXG5cbiAgYW55X19xbWFya19fOiBmdW5jdGlvbiAoY29sbGVjdGlvbiwgZnVuID0geCA9PiB4KSB7XG4gICAgZm9yIChsZXQgZWxlbSBvZiBjb2xsZWN0aW9uKSB7XG4gICAgICBpZiAoZnVuKGVsZW0pKSB7XG4gICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgfVxuICAgIH1cblxuICAgIHJldHVybiBmYWxzZTtcbiAgfSxcblxuICBhdDogZnVuY3Rpb24gKGNvbGxlY3Rpb24sIG4sIHRoZV9kZWZhdWx0ID0gbnVsbCkge1xuICAgIGlmIChuID4gdGhpcy5jb3VudChjb2xsZWN0aW9uKSB8fCBuIDwgMCkge1xuICAgICAgcmV0dXJuIHRoZV9kZWZhdWx0O1xuICAgIH1cblxuICAgIHJldHVybiBjb2xsZWN0aW9uW25dO1xuICB9LFxuXG4gIGNvbmNhdDogZnVuY3Rpb24gKC4uLmVudW1hYmxlcykge1xuICAgIHJldHVybiBlbnVtYWJsZXNbMF0uY29uY2F0KGVudW1hYmxlc1sxXSk7XG4gIH0sXG5cbiAgY291bnQ6IGZ1bmN0aW9uIChjb2xsZWN0aW9uLCBmdW4gPSBudWxsKSB7XG4gICAgaWYgKGZ1biA9PSBudWxsKSB7XG4gICAgICByZXR1cm4gY29sbGVjdGlvbi5sZW5ndGg7XG4gICAgfSBlbHNlIHtcbiAgICAgIHJldHVybiBjb2xsZWN0aW9uLmZpbHRlcihmdW4pLmxlbmd0aDtcbiAgICB9XG4gIH0sXG5cbiAgZHJvcDogZnVuY3Rpb24gKGNvbGxlY3Rpb24sIGNvdW50KSB7XG4gICAgcmV0dXJuIGNvbGxlY3Rpb24uc2xpY2UoY291bnQpO1xuICB9LFxuXG4gIGRyb3Bfd2hpbGU6IGZ1bmN0aW9uIChjb2xsZWN0aW9uLCBmdW4pIHtcbiAgICBsZXQgY291bnQgPSAwO1xuXG4gICAgZm9yIChsZXQgZWxlbSBvZiBjb2xsZWN0aW9uKSB7XG4gICAgICBpZiAoZnVuKGVsZW0pKSB7XG4gICAgICAgIGNvdW50ID0gY291bnQgKyAxO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgYnJlYWs7XG4gICAgICB9XG4gICAgfVxuXG4gICAgcmV0dXJuIGNvbGxlY3Rpb24uc2xpY2UoY291bnQpO1xuICB9LFxuXG4gIGVhY2g6IGZ1bmN0aW9uIChjb2xsZWN0aW9uLCBmdW4pIHtcbiAgICBmb3IgKGxldCBlbGVtIG9mIGNvbGxlY3Rpb24pIHtcbiAgICAgIGZ1bihlbGVtKTtcbiAgICB9XG4gIH0sXG5cbiAgZW1wdHlfX3FtYXJrX186IGZ1bmN0aW9uIChjb2xsZWN0aW9uKSB7XG4gICAgcmV0dXJuIGNvbGxlY3Rpb24ubGVuZ3RoID09PSAwO1xuICB9LFxuXG4gIGZldGNoOiBmdW5jdGlvbiAoY29sbGVjdGlvbiwgbikge1xuICAgIGlmIChLZXJuZWwuaXNfbGlzdChjb2xsZWN0aW9uKSkge1xuICAgICAgaWYgKG4gPCB0aGlzLmNvdW50KGNvbGxlY3Rpb24pICYmIG4gPj0gMCkge1xuICAgICAgICByZXR1cm4gS2VybmVsLlNwZWNpYWxGb3Jtcy50dXBsZShLZXJuZWwuU3BlY2lhbEZvcm1zLmF0b20oXCJva1wiKSwgY29sbGVjdGlvbltuXSk7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICByZXR1cm4gS2VybmVsLlNwZWNpYWxGb3Jtcy5hdG9tKFwiZXJyb3JcIik7XG4gICAgICB9XG4gICAgfVxuXG4gICAgdGhyb3cgbmV3IEVycm9yKFwiY29sbGVjdGlvbiBpcyBub3QgYW4gRW51bWVyYWJsZVwiKTtcbiAgfSxcblxuICBmZXRjaF9fZW1hcmtfXzogZnVuY3Rpb24gKGNvbGxlY3Rpb24sIG4pIHtcbiAgICBpZiAoS2VybmVsLmlzX2xpc3QoY29sbGVjdGlvbikpIHtcbiAgICAgIGlmIChuIDwgdGhpcy5jb3VudChjb2xsZWN0aW9uKSAmJiBuID49IDApIHtcbiAgICAgICAgcmV0dXJuIGNvbGxlY3Rpb25bbl07XG4gICAgICB9IGVsc2Uge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoXCJvdXQgb2YgYm91bmRzIGVycm9yXCIpO1xuICAgICAgfVxuICAgIH1cblxuICAgIHRocm93IG5ldyBFcnJvcihcImNvbGxlY3Rpb24gaXMgbm90IGFuIEVudW1lcmFibGVcIik7XG4gIH0sXG5cbiAgZmlsdGVyOiBmdW5jdGlvbiAoY29sbGVjdGlvbiwgZnVuKSB7XG4gICAgbGV0IHJlc3VsdCA9IFtdO1xuXG4gICAgZm9yIChsZXQgZWxlbSBvZiBjb2xsZWN0aW9uKSB7XG4gICAgICBpZiAoZnVuKGVsZW0pKSB7XG4gICAgICAgIHJlc3VsdC5wdXNoKGVsZW0pO1xuICAgICAgfVxuICAgIH1cblxuICAgIHJldHVybiByZXN1bHQ7XG4gIH0sXG5cbiAgZmlsdGVyX21hcDogZnVuY3Rpb24gKGNvbGxlY3Rpb24sIGZpbHRlciwgbWFwcGVyKSB7XG4gICAgcmV0dXJuIEVudW0ubWFwKEVudW0uZmlsdGVyKGNvbGxlY3Rpb24sIGZpbHRlciksIG1hcHBlcik7XG4gIH0sXG5cbiAgZmluZDogZnVuY3Rpb24gKGNvbGxlY3Rpb24sIGlmX25vbmUgPSBudWxsLCBmdW4pIHtcbiAgICBmb3IgKGxldCBlbGVtIG9mIGNvbGxlY3Rpb24pIHtcbiAgICAgIGlmIChmdW4oZWxlbSkpIHtcbiAgICAgICAgcmV0dXJuIGVsZW07XG4gICAgICB9XG4gICAgfVxuXG4gICAgcmV0dXJuIGlmX25vbmU7XG4gIH0sXG5cbiAgaW50bzogZnVuY3Rpb24gKGNvbGxlY3Rpb24sIGxpc3QpIHtcbiAgICByZXR1cm4gbGlzdC5jb25jYXQoY29sbGVjdGlvbik7XG4gIH0sXG5cbiAgbWFwOiBmdW5jdGlvbiAoY29sbGVjdGlvbiwgZnVuKSB7XG4gICAgbGV0IHJlc3VsdCA9IFtdO1xuXG4gICAgZm9yIChsZXQgZWxlbSBvZiBjb2xsZWN0aW9uKSB7XG4gICAgICByZXN1bHQucHVzaChmdW4oZWxlbSkpO1xuICAgIH1cblxuICAgIHJldHVybiByZXN1bHQ7XG4gIH0sXG5cbiAgbWFwX3JlZHVjZTogZnVuY3Rpb24gKGNvbGxlY3Rpb24sIGFjYywgZnVuKSB7XG4gICAgbGV0IG1hcHBlZCA9IEtlcm5lbC5TcGVjaWFsRm9ybXMubGlzdCgpO1xuICAgIGxldCB0aGVfYWNjID0gYWNjO1xuXG4gICAgZm9yICh2YXIgaSA9IDA7IGkgPCB0aGlzLmNvdW50KGNvbGxlY3Rpb24pOyBpKyspIHtcbiAgICAgIGxldCB0dXBsZSA9IGZ1bihjb2xsZWN0aW9uW2ldLCB0aGVfYWNjKTtcblxuICAgICAgdGhlX2FjYyA9IEtlcm5lbC5lbGVtKHR1cGxlLCAxKTtcbiAgICAgIG1hcHBlZCA9IEtlcm5lbC5TcGVjaWFsRm9ybXMubGlzdCguLi5tYXBwZWQuY29uY2F0KFtLZXJuZWwuZWxlbSh0dXBsZSwgMCldKSk7XG4gICAgfVxuXG4gICAgcmV0dXJuIEtlcm5lbC5TcGVjaWFsRm9ybXMudHVwbGUobWFwcGVkLCB0aGVfYWNjKTtcbiAgfSxcblxuICBtZW1iZXI6IGZ1bmN0aW9uIChjb2xsZWN0aW9uLCB2YWx1ZSkge1xuICAgIHJldHVybiBjb2xsZWN0aW9uLmluY2x1ZGVzKHZhbHVlKTtcbiAgfSxcblxuICByZWR1Y2U6IGZ1bmN0aW9uIChjb2xsZWN0aW9uLCBhY2MsIGZ1bikge1xuICAgIGxldCB0aGVfYWNjID0gYWNjO1xuXG4gICAgZm9yICh2YXIgaSA9IDA7IGkgPCB0aGlzLmNvdW50KGNvbGxlY3Rpb24pOyBpKyspIHtcbiAgICAgIGxldCB0dXBsZSA9IGZ1bihjb2xsZWN0aW9uW2ldLCB0aGVfYWNjKTtcblxuICAgICAgdGhlX2FjYyA9IEtlcm5lbC5lbGVtKHR1cGxlLCAxKTtcbiAgICB9XG5cbiAgICByZXR1cm4gdGhlX2FjYztcbiAgfSxcblxuICB0YWtlOiBmdW5jdGlvbiAoY29sbGVjdGlvbiwgY291bnQpIHtcbiAgICByZXR1cm4gY29sbGVjdGlvbi5zbGljZSgwLCBjb3VudCk7XG4gIH0sXG5cbiAgdGFrZV9ldmVyeTogZnVuY3Rpb24gKGNvbGxlY3Rpb24sIG50aCkge1xuICAgIGxldCByZXN1bHQgPSBbXTtcbiAgICBsZXQgaW5kZXggPSAwO1xuXG4gICAgZm9yIChsZXQgZWxlbSBvZiBjb2xsZWN0aW9uKSB7XG4gICAgICBpZiAoaW5kZXggJSBudGggPT09IDApIHtcbiAgICAgICAgcmVzdWx0LnB1c2goZWxlbSk7XG4gICAgICB9XG4gICAgfVxuXG4gICAgcmV0dXJuIEtlcm5lbC5TcGVjaWFsRm9ybXMubGlzdCguLi5yZXN1bHQpO1xuICB9LFxuXG4gIHRha2Vfd2hpbGU6IGZ1bmN0aW9uIChjb2xsZWN0aW9uLCBmdW4pIHtcbiAgICBsZXQgY291bnQgPSAwO1xuXG4gICAgZm9yIChsZXQgZWxlbSBvZiBjb2xsZWN0aW9uKSB7XG4gICAgICBpZiAoZnVuKGVsZW0pKSB7XG4gICAgICAgIGNvdW50ID0gY291bnQgKyAxO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgYnJlYWs7XG4gICAgICB9XG4gICAgfVxuXG4gICAgcmV0dXJuIGNvbGxlY3Rpb24uc2xpY2UoMCwgY291bnQpO1xuICB9LFxuXG4gIHRvX2xpc3Q6IGZ1bmN0aW9uIChjb2xsZWN0aW9uKSB7XG4gICAgcmV0dXJuIGNvbGxlY3Rpb247XG4gIH1cbn07XG5cbmxldCBTcGVjaWFsRm9ybXMgPSB7XG5cbiAgX19ESVJfXzogZnVuY3Rpb24gKCkge1xuICAgIGlmIChfX2Rpcm5hbWUpIHtcbiAgICAgIHJldHVybiBfX2Rpcm5hbWU7XG4gICAgfVxuXG4gICAgaWYgKGRvY3VtZW50LmN1cnJlbnRTY3JpcHQpIHtcbiAgICAgIHJldHVybiBkb2N1bWVudC5jdXJyZW50U2NyaXB0LnNyYztcbiAgICB9XG5cbiAgICByZXR1cm4gbnVsbDtcbiAgfSxcblxuICBhdG9tOiBmdW5jdGlvbiAoX3ZhbHVlKSB7XG4gICAgcmV0dXJuIFN5bWJvbC5mb3IoX3ZhbHVlKTtcbiAgfSxcblxuICBsaXN0OiBmdW5jdGlvbiAoLi4uYXJncykge1xuICAgIHJldHVybiBPYmplY3QuZnJlZXplKGFyZ3MpO1xuICB9LFxuXG4gIGJpdHN0cmluZzogZnVuY3Rpb24gKC4uLmFyZ3MpIHtcbiAgICByZXR1cm4gbmV3IEJpdFN0cmluZyguLi5hcmdzKTtcbiAgfSxcblxuICBib3VuZDogZnVuY3Rpb24gKF92YXIpIHtcbiAgICByZXR1cm4gdW5kZWZpbmVkKF92YXIpO1xuICB9LFxuXG4gIF9jYXNlOiBmdW5jdGlvbiAoY29uZGl0aW9uLCBjbGF1c2VzKSB7XG4gICAgcmV0dXJuIHVuZGVmaW5lZCguLi5jbGF1c2VzKShjb25kaXRpb24pO1xuICB9LFxuXG4gIGNvbmQ6IGZ1bmN0aW9uIChjbGF1c2VzKSB7XG4gICAgZm9yIChsZXQgY2xhdXNlIG9mIGNsYXVzZXMpIHtcbiAgICAgIGlmIChjbGF1c2VbMF0pIHtcbiAgICAgICAgcmV0dXJuIGNsYXVzZVsxXSgpO1xuICAgICAgfVxuICAgIH1cblxuICAgIHRocm93IG5ldyBFcnJvcigpO1xuICB9LFxuXG4gIGZuOiBmdW5jdGlvbiAoY2xhdXNlcykge1xuICAgIHJldHVybiB1bmRlZmluZWQoY2xhdXNlcyk7XG4gIH0sXG5cbiAgbWFwOiBmdW5jdGlvbiAob2JqKSB7XG4gICAgcmV0dXJuIE9iamVjdC5mcmVlemUob2JqKTtcbiAgfSxcblxuICBtYXBfdXBkYXRlOiBmdW5jdGlvbiAobWFwLCB2YWx1ZXMpIHtcbiAgICByZXR1cm4gT2JqZWN0LmZyZWV6ZShPYmplY3QuYXNzaWduKE9iamVjdC5jcmVhdGUobWFwLmNvbnN0cnVjdG9yLnByb3RvdHlwZSksIG1hcCwgdmFsdWVzKSk7XG4gIH0sXG5cbiAgX2ZvcjogZnVuY3Rpb24gKGNvbGxlY3Rpb25zLCBmdW4sIGZpbHRlciA9ICgpID0+IHRydWUsIGludG8gPSBbXSwgcHJldmlvdXNWYWx1ZXMgPSBbXSkge1xuICAgIGxldCBwYXR0ZXJuID0gY29sbGVjdGlvbnNbMF1bMF07XG4gICAgbGV0IGNvbGxlY3Rpb24gPSBjb2xsZWN0aW9uc1swXVsxXTtcblxuICAgIGlmIChjb2xsZWN0aW9ucy5sZW5ndGggPT09IDEpIHtcblxuICAgICAgZm9yIChsZXQgZWxlbSBvZiBjb2xsZWN0aW9uKSB7XG4gICAgICAgIGxldCByID0gdW5kZWZpbmVkKHBhdHRlcm4sIGVsZW0pO1xuICAgICAgICBsZXQgYXJncyA9IHByZXZpb3VzVmFsdWVzLmNvbmNhdChyKTtcblxuICAgICAgICBpZiAociAmJiBmaWx0ZXIuYXBwbHkodGhpcywgYXJncykpIHtcbiAgICAgICAgICBpbnRvID0gRW51bS5pbnRvKFtmdW4uYXBwbHkodGhpcywgYXJncyldLCBpbnRvKTtcbiAgICAgICAgfVxuICAgICAgfVxuXG4gICAgICByZXR1cm4gaW50bztcbiAgICB9IGVsc2Uge1xuICAgICAgbGV0IF9pbnRvID0gW107XG5cbiAgICAgIGZvciAobGV0IGVsZW0gb2YgY29sbGVjdGlvbikge1xuICAgICAgICBsZXQgciA9IHVuZGVmaW5lZChwYXR0ZXJuLCBlbGVtKTtcbiAgICAgICAgaWYgKHIpIHtcbiAgICAgICAgICBfaW50byA9IEVudW0uaW50byh0aGlzLl9mb3IoY29sbGVjdGlvbnMuc2xpY2UoMSksIGZ1biwgZmlsdGVyLCBfaW50bywgcHJldmlvdXNWYWx1ZXMuY29uY2F0KHIpKSwgaW50byk7XG4gICAgICAgIH1cbiAgICAgIH1cblxuICAgICAgcmV0dXJuIF9pbnRvO1xuICAgIH1cbiAgfSxcblxuICByZWNlaXZlOiBmdW5jdGlvbiAocmVjZWl2ZV9mdW4sIHRpbWVvdXRfaW5fbXMgPSBudWxsLCB0aW1lb3V0X2ZuID0gdGltZSA9PiB0cnVlKSB7XG4gICAgaWYgKHRpbWVvdXRfaW5fbXMgPT0gbnVsbCB8fCB0aW1lb3V0X2luX21zID09PSBTeXN0ZW0uZm9yKCdpbmZpbml0eScpKSB7XG4gICAgICB3aGlsZSAodHJ1ZSkge1xuICAgICAgICBpZiAoc2VsZi5tYWlsYm94Lmxlbmd0aCAhPT0gMCkge1xuICAgICAgICAgIGxldCBtZXNzYWdlID0gc2VsZi5tYWlsYm94WzBdO1xuICAgICAgICAgIHNlbGYubWFpbGJveCA9IHNlbGYubWFpbGJveC5zbGljZSgxKTtcbiAgICAgICAgICByZXR1cm4gcmVjZWl2ZV9mdW4obWVzc2FnZSk7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9IGVsc2UgaWYgKHRpbWVvdXRfaW5fbXMgPT09IDApIHtcbiAgICAgIGlmIChzZWxmLm1haWxib3gubGVuZ3RoICE9PSAwKSB7XG4gICAgICAgIGxldCBtZXNzYWdlID0gc2VsZi5tYWlsYm94WzBdO1xuICAgICAgICBzZWxmLm1haWxib3ggPSBzZWxmLm1haWxib3guc2xpY2UoMSk7XG4gICAgICAgIHJldHVybiByZWNlaXZlX2Z1bihtZXNzYWdlKTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHJldHVybiBudWxsO1xuICAgICAgfVxuICAgIH0gZWxzZSB7XG4gICAgICBsZXQgbm93ID0gRGF0ZS5ub3coKTtcbiAgICAgIHdoaWxlIChEYXRlLm5vdygpIDwgbm93ICsgdGltZW91dF9pbl9tcykge1xuICAgICAgICBpZiAoc2VsZi5tYWlsYm94Lmxlbmd0aCAhPT0gMCkge1xuICAgICAgICAgIGxldCBtZXNzYWdlID0gc2VsZi5tYWlsYm94WzBdO1xuICAgICAgICAgIHNlbGYubWFpbGJveCA9IHNlbGYubWFpbGJveC5zbGljZSgxKTtcbiAgICAgICAgICByZXR1cm4gcmVjZWl2ZV9mdW4obWVzc2FnZSk7XG4gICAgICAgIH1cbiAgICAgIH1cblxuICAgICAgcmV0dXJuIHRpbWVvdXRfZm4odGltZW91dF9pbl9tcyk7XG4gICAgfVxuICB9LFxuXG4gIHR1cGxlOiBmdW5jdGlvbiAoLi4uYXJncykge1xuICAgIHJldHVybiBuZXcgQ29yZS5UdXBsZSguLi5hcmdzKTtcbiAgfSxcblxuICBfdHJ5OiBmdW5jdGlvbiAoZG9fZnVuLCByZXNjdWVfZnVuY3Rpb24sIGNhdGNoX2Z1biwgZWxzZV9mdW5jdGlvbiwgYWZ0ZXJfZnVuY3Rpb24pIHtcbiAgICBsZXQgcmVzdWx0ID0gbnVsbDtcblxuICAgIHRyeSB7XG4gICAgICByZXN1bHQgPSBkb19mdW4oKTtcbiAgICB9IGNhdGNoIChlKSB7XG4gICAgICBsZXQgZXhfcmVzdWx0ID0gbnVsbDtcblxuICAgICAgaWYgKHJlc2N1ZV9mdW5jdGlvbikge1xuICAgICAgICB0cnkge1xuICAgICAgICAgIGV4X3Jlc3VsdCA9IHJlc2N1ZV9mdW5jdGlvbihlKTtcbiAgICAgICAgICByZXR1cm4gZXhfcmVzdWx0O1xuICAgICAgICB9IGNhdGNoIChleCkge1xuICAgICAgICAgIGlmIChleCBpbnN0YW5jZW9mIHVuZGVmaW5lZCkge1xuICAgICAgICAgICAgdGhyb3cgZXg7XG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICB9XG5cbiAgICAgIGlmIChjYXRjaF9mdW4pIHtcbiAgICAgICAgdHJ5IHtcbiAgICAgICAgICBleF9yZXN1bHQgPSBjYXRjaF9mdW4oZSk7XG4gICAgICAgICAgcmV0dXJuIGV4X3Jlc3VsdDtcbiAgICAgICAgfSBjYXRjaCAoZXgpIHtcbiAgICAgICAgICBpZiAoZXggaW5zdGFuY2VvZiB1bmRlZmluZWQpIHtcbiAgICAgICAgICAgIHRocm93IGV4O1xuICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgfVxuXG4gICAgICB0aHJvdyBlO1xuICAgIH0gZmluYWxseSB7XG4gICAgICBpZiAoYWZ0ZXJfZnVuY3Rpb24pIHtcbiAgICAgICAgYWZ0ZXJfZnVuY3Rpb24oKTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICBpZiAoZWxzZV9mdW5jdGlvbikge1xuICAgICAgdHJ5IHtcbiAgICAgICAgcmV0dXJuIGVsc2VfZnVuY3Rpb24ocmVzdWx0KTtcbiAgICAgIH0gY2F0Y2ggKGV4KSB7XG4gICAgICAgIGlmIChleCBpbnN0YW5jZW9mIHVuZGVmaW5lZCkge1xuICAgICAgICAgIHRocm93IG5ldyBFcnJvcignTm8gTWF0Y2ggRm91bmQgaW4gRWxzZScpO1xuICAgICAgICB9XG5cbiAgICAgICAgdGhyb3cgZXg7XG4gICAgICB9XG4gICAgfSBlbHNlIHtcbiAgICAgIHJldHVybiByZXN1bHQ7XG4gICAgfVxuICB9XG5cbn07XG5cbmZ1bmN0aW9uIHRvX3N0cmluZyQxKHR1cGxlKSB7XG4gIHJldHVybiB0dXBsZS50b1N0cmluZygpO1xufTtcblxuZnVuY3Rpb24gZGVsZXRlX2F0KHR1cGxlLCBpbmRleCkge1xuICBsZXQgbmV3X2xpc3QgPSBbXTtcblxuICBmb3IgKHZhciBpID0gMDsgaSA8IHR1cGxlLmNvdW50KCk7IGkrKykge1xuICAgIGlmIChpICE9PSBpbmRleCkge1xuICAgICAgbmV3X2xpc3QucHVzaCh0dXBsZS5nZXQoaSkpO1xuICAgIH1cbiAgfVxuXG4gIHJldHVybiBLZXJuZWwuU3BlY2lhbEZvcm1zLnR1cGxlLmFwcGx5KG51bGwsIG5ld19saXN0KTtcbn07XG5cbmZ1bmN0aW9uIGR1cGxpY2F0ZShkYXRhLCBzaXplKSB7XG4gIGxldCBhcnJheSA9IFtdO1xuXG4gIGZvciAodmFyIGkgPSBzaXplIC0gMTsgaSA+PSAwOyBpLS0pIHtcbiAgICBhcnJheS5wdXNoKGRhdGEpO1xuICB9XG5cbiAgcmV0dXJuIEtlcm5lbC5TcGVjaWFsRm9ybXMudHVwbGUuYXBwbHkobnVsbCwgYXJyYXkpO1xufTtcblxuZnVuY3Rpb24gaW5zZXJ0X2F0KHR1cGxlLCBpbmRleCwgdGVybSkge1xuICBsZXQgbmV3X3R1cGxlID0gW107XG5cbiAgZm9yICh2YXIgaSA9IDA7IGkgPD0gdHVwbGUuY291bnQoKTsgaSsrKSB7XG4gICAgaWYgKGkgPT09IGluZGV4KSB7XG4gICAgICBuZXdfdHVwbGUucHVzaCh0ZXJtKTtcbiAgICAgIGkrKztcbiAgICAgIG5ld190dXBsZS5wdXNoKHR1cGxlLmdldChpKSk7XG4gICAgfSBlbHNlIHtcbiAgICAgIG5ld190dXBsZS5wdXNoKHR1cGxlLmdldChpKSk7XG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIEtlcm5lbC5TcGVjaWFsRm9ybXMudHVwbGUuYXBwbHkobnVsbCwgbmV3X3R1cGxlKTtcbn07XG5cbmZ1bmN0aW9uIGZyb21fbGlzdChsaXN0KSB7XG4gIHJldHVybiBLZXJuZWwuU3BlY2lhbEZvcm1zLnR1cGxlLmFwcGx5KG51bGwsIGxpc3QpO1xufTtcblxuZnVuY3Rpb24gdG9fbGlzdCh0dXBsZSkge1xuICBsZXQgbmV3X2xpc3QgPSBbXTtcblxuICBmb3IgKHZhciBpID0gMDsgaSA8IHR1cGxlLmNvdW50KCk7IGkrKykge1xuICAgIG5ld19saXN0LnB1c2godHVwbGUuZ2V0KGkpKTtcbiAgfVxuXG4gIHJldHVybiBLZXJuZWwuU3BlY2lhbEZvcm1zLmxpc3QoLi4ubmV3X2xpc3QpO1xufTtcblxudmFyIFR1cGxlID0ge1xuICB0b19zdHJpbmc6IHRvX3N0cmluZyQxLFxuICBkZWxldGVfYXQsXG4gIGR1cGxpY2F0ZSxcbiAgaW5zZXJ0X2F0LFxuICBmcm9tX2xpc3QsXG4gIHRvX2xpc3Rcbn07XG5cbmNsYXNzIEludGVnZXJUeXBlIHt9XG5jbGFzcyBGbG9hdFR5cGUge31cblxuLy9odHRwczovL2dpdGh1Yi5jb20vYWlycG9ydHloL3Byb3RvbW9ycGhpc21cbmNsYXNzIFByb3RvY29sIHtcbiAgY29uc3RydWN0b3Ioc3BlYykge1xuICAgIHRoaXMucmVnaXN0cnkgPSBuZXcgTWFwKCk7XG4gICAgdGhpcy5mYWxsYmFjayA9IG51bGw7XG5cbiAgICBmb3IgKGxldCBmdW5OYW1lIGluIHNwZWMpIHtcbiAgICAgIHRoaXNbZnVuTmFtZV0gPSBjcmVhdGVGdW4oZnVuTmFtZSkuYmluZCh0aGlzKTtcbiAgICB9XG5cbiAgICBmdW5jdGlvbiBjcmVhdGVGdW4oZnVuTmFtZSkge1xuXG4gICAgICByZXR1cm4gZnVuY3Rpb24gKC4uLmFyZ3MpIHtcbiAgICAgICAgbGV0IHRoaW5nID0gYXJnc1swXTtcbiAgICAgICAgbGV0IGZ1biA9IG51bGw7XG5cbiAgICAgICAgaWYgKE51bWJlci5pc0ludGVnZXIodGhpbmcpICYmIHRoaXMuaGFzSW1wbGVtZW50YXRpb24oSW50ZWdlclR5cGUpKSB7XG4gICAgICAgICAgZnVuID0gdGhpcy5yZWdpc3RyeS5nZXQoSW50ZWdlclR5cGUpW2Z1bk5hbWVdO1xuICAgICAgICB9IGVsc2UgaWYgKHR5cGVvZiB0aGluZyA9PT0gXCJudW1iZXJcIiAmJiAhTnVtYmVyLmlzSW50ZWdlcih0aGluZykgJiYgdGhpcy5oYXNJbXBsZW1lbnRhdGlvbihGbG9hdFR5cGUpKSB7XG4gICAgICAgICAgZnVuID0gdGhpcy5yZWdpc3RyeS5nZXQoRmxvYXRUeXBlKVtmdW5OYW1lXTtcbiAgICAgICAgfSBlbHNlIGlmICh0aGlzLmhhc0ltcGxlbWVudGF0aW9uKHRoaW5nKSkge1xuICAgICAgICAgIGZ1biA9IHRoaXMucmVnaXN0cnkuZ2V0KHRoaW5nLmNvbnN0cnVjdG9yKVtmdW5OYW1lXTtcbiAgICAgICAgfSBlbHNlIGlmICh0aGlzLmZhbGxiYWNrKSB7XG4gICAgICAgICAgZnVuID0gdGhpcy5mYWxsYmFja1tmdW5OYW1lXTtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmIChmdW4gIT0gbnVsbCkge1xuICAgICAgICAgIGxldCByZXR2YWwgPSBmdW4uYXBwbHkodGhpcywgYXJncyk7XG4gICAgICAgICAgcmV0dXJuIHJldHZhbDtcbiAgICAgICAgfVxuXG4gICAgICAgIHRocm93IG5ldyBFcnJvcihcIk5vIGltcGxlbWVudGF0aW9uIGZvdW5kIGZvciBcIiArIHRoaW5nKTtcbiAgICAgIH07XG4gICAgfVxuICB9XG5cbiAgaW1wbGVtZW50YXRpb24odHlwZSwgaW1wbGVtZW50YXRpb24pIHtcbiAgICBpZiAodHlwZSA9PT0gbnVsbCkge1xuICAgICAgdGhpcy5mYWxsYmFjayA9IGltcGxlbWVudGF0aW9uO1xuICAgIH0gZWxzZSB7XG4gICAgICB0aGlzLnJlZ2lzdHJ5LnNldCh0eXBlLCBpbXBsZW1lbnRhdGlvbik7XG4gICAgfVxuICB9XG5cbiAgaGFzSW1wbGVtZW50YXRpb24odGhpbmcpIHtcbiAgICByZXR1cm4gdGhpcy5yZWdpc3RyeS5oYXModGhpbmcuY29uc3RydWN0b3IpO1xuICB9XG59XG5cbmZ1bmN0aW9uIHRsKGxpc3QpIHtcbiAgcmV0dXJuIFNwZWNpYWxGb3Jtcy5saXN0KC4uLmxpc3Quc2xpY2UoMSkpO1xufVxuXG5mdW5jdGlvbiBoZChsaXN0KSB7XG4gIHJldHVybiBsaXN0WzBdO1xufVxuXG5mdW5jdGlvbiBpc19uaWwoeCkge1xuICByZXR1cm4geCA9PT0gbnVsbDtcbn1cblxuZnVuY3Rpb24gaXNfYXRvbSh4KSB7XG4gIHJldHVybiB0eXBlb2YgeCA9PT0gJ3N5bWJvbCc7XG59XG5cbmZ1bmN0aW9uIGlzX2JpbmFyeSh4KSB7XG4gIHJldHVybiB0eXBlb2YgeCA9PT0gJ3N0cmluZycgfHwgeCBpbnN0YW5jZW9mIFN0cmluZztcbn1cblxuZnVuY3Rpb24gaXNfYm9vbGVhbih4KSB7XG4gIHJldHVybiB0eXBlb2YgeCA9PT0gJ2Jvb2xlYW4nIHx8IHggaW5zdGFuY2VvZiBCb29sZWFuO1xufVxuXG5mdW5jdGlvbiBpc19mdW5jdGlvbih4LCBhcml0eSA9IC0xKSB7XG4gIHJldHVybiB0eXBlb2YgeCA9PT0gJ2Z1bmN0aW9uJyB8fCB4IGluc3RhbmNlb2YgRnVuY3Rpb247XG59XG5cbmZ1bmN0aW9uIGlzX2Zsb2F0KHgpIHtcbiAgcmV0dXJuIGlzX251bWJlcih4KSAmJiAhTnVtYmVyLmlzSW50ZWdlcih4KTtcbn1cblxuZnVuY3Rpb24gaXNfaW50ZWdlcih4KSB7XG4gIHJldHVybiBOdW1iZXIuaXNJbnRlZ2VyKHgpO1xufVxuXG5mdW5jdGlvbiBpc19saXN0KHgpIHtcbiAgcmV0dXJuIHggaW5zdGFuY2VvZiBBcnJheTtcbn1cblxuZnVuY3Rpb24gaXNfbWFwKHgpIHtcbiAgcmV0dXJuIHR5cGVvZiB4ID09PSAnb2JqZWN0JyB8fCB4IGluc3RhbmNlb2YgT2JqZWN0O1xufVxuXG5mdW5jdGlvbiBpc19udW1iZXIoeCkge1xuICByZXR1cm4gdHlwZW9mIHggPT09ICdudW1iZXInO1xufVxuXG5mdW5jdGlvbiBpc190dXBsZSh4KSB7XG4gIHJldHVybiB4IGluc3RhbmNlb2YgQ29yZS5UdXBsZTtcbn1cblxuZnVuY3Rpb24gbGVuZ3RoKHgpIHtcbiAgcmV0dXJuIHgubGVuZ3RoO1xufVxuXG5mdW5jdGlvbiBpc19waWQoeCkge1xuICByZXR1cm4geCBpbnN0YW5jZW9mIENvcmUuUElEO1xufVxuXG5mdW5jdGlvbiBpc19wb3J0KHgpIHtcbiAgcmV0dXJuIGZhbHNlO1xufVxuXG5mdW5jdGlvbiBpc19yZWZlcmVuY2UoeCkge1xuICByZXR1cm4gZmFsc2U7XG59XG5cbmZ1bmN0aW9uIGlzX2JpdHN0cmluZyh4KSB7XG4gIHJldHVybiBpc19iaW5hcnkoeCkgfHwgeCBpbnN0YW5jZW9mIEJpdFN0cmluZztcbn1cblxuZnVuY3Rpb24gX19pbl9fKGxlZnQsIHJpZ2h0KSB7XG4gIGZvciAobGV0IHggb2YgcmlnaHQpIHtcbiAgICBpZiAobWF0Y2hfX3FtYXJrX18obGVmdCwgeCkpIHtcbiAgICAgIHJldHVybiB0cnVlO1xuICAgIH1cbiAgfVxuXG4gIHJldHVybiBmYWxzZTtcbn1cblxuZnVuY3Rpb24gYWJzKG51bWJlcikge1xuICByZXR1cm4gTWF0aC5hYnMobnVtYmVyKTtcbn1cblxuZnVuY3Rpb24gcm91bmQobnVtYmVyKSB7XG4gIHJldHVybiBNYXRoLnJvdW5kKG51bWJlcik7XG59XG5cbmZ1bmN0aW9uIGVsZW0odHVwbGUsIGluZGV4KSB7XG4gIGlmIChpc19saXN0KHR1cGxlKSkge1xuICAgIHJldHVybiB0dXBsZVtpbmRleF07XG4gIH1cblxuICByZXR1cm4gdHVwbGUuZ2V0KGluZGV4KTtcbn1cblxuZnVuY3Rpb24gcmVtKGxlZnQsIHJpZ2h0KSB7XG4gIHJldHVybiBsZWZ0ICUgcmlnaHQ7XG59XG5cbmZ1bmN0aW9uIGRpdihsZWZ0LCByaWdodCkge1xuICByZXR1cm4gbGVmdCAvIHJpZ2h0O1xufVxuXG5mdW5jdGlvbiBhbmQobGVmdCwgcmlnaHQpIHtcbiAgcmV0dXJuIGxlZnQgJiYgcmlnaHQ7XG59XG5cbmZ1bmN0aW9uIG9yKGxlZnQsIHJpZ2h0KSB7XG4gIHJldHVybiBsZWZ0IHx8IHJpZ2h0O1xufVxuXG5mdW5jdGlvbiBub3QoYXJnKSB7XG4gIHJldHVybiAhYXJnO1xufVxuXG5mdW5jdGlvbiBhcHBseSguLi5hcmdzKSB7XG4gIGlmIChhcmdzLmxlbmd0aCA9PT0gMykge1xuICAgIGxldCBtb2QgPSBhcmdzWzBdO1xuICAgIGxldCBmdW5jID0gYXJnc1sxXTtcbiAgICBsZXQgZnVuY19hcmdzID0gYXJnc1syXTtcbiAgICByZXR1cm4gbW9kW2Z1bmNdLmFwcGx5KG51bGwsIGZ1bmNfYXJncyk7XG4gIH0gZWxzZSB7XG4gICAgbGV0IGZ1bmMgPSBhcmdzWzBdO1xuICAgIGxldCBmdW5jX2FyZ3MgPSBhcmdzWzFdO1xuXG4gICAgcmV0dXJuIGZ1bmMuYXBwbHkobnVsbCwgZnVuY19hcmdzKTtcbiAgfVxufVxuXG5mdW5jdGlvbiB0b19zdHJpbmcoYXJnKSB7XG4gIGlmIChpc190dXBsZShhcmcpKSB7XG4gICAgcmV0dXJuIFR1cGxlLnRvX3N0cmluZyhhcmcpO1xuICB9XG5cbiAgcmV0dXJuIGFyZy50b1N0cmluZygpO1xufVxuXG5mdW5jdGlvbiBtYXRjaF9fcW1hcmtfXyhwYXR0ZXJuLCBleHByLCBndWFyZCA9ICgpID0+IHRydWUpIHtcbiAgcmV0dXJuIFBhdHRlcm5zLm1hdGNoX25vX3Rocm93KHBhdHRlcm4sIGV4cHIsIGd1YXJkKSAhPSBudWxsO1xufVxuXG5mdW5jdGlvbiBkZWZzdHJ1Y3QoZGVmYXVsdHMpIHtcbiAgcmV0dXJuIGNsYXNzIHtcbiAgICBjb25zdHJ1Y3Rvcih1cGRhdGUgPSB7fSkge1xuICAgICAgbGV0IHRoZV92YWx1ZXMgPSBPYmplY3QuYXNzaWduKGRlZmF1bHRzLCB1cGRhdGUpO1xuICAgICAgT2JqZWN0LmFzc2lnbih0aGlzLCB0aGVfdmFsdWVzKTtcbiAgICB9XG5cbiAgICBzdGF0aWMgY3JlYXRlKHVwZGF0ZXMgPSB7fSkge1xuICAgICAgbGV0IHggPSBuZXcgdGhpcyh1cGRhdGVzKTtcbiAgICAgIHJldHVybiBPYmplY3QuZnJlZXplKHgpO1xuICAgIH1cbiAgfTtcbn1cblxuZnVuY3Rpb24gZGVmcHJvdG9jb2woc3BlYykge1xuICByZXR1cm4gbmV3IFByb3RvY29sKHNwZWMpO1xufVxuXG5mdW5jdGlvbiBkZWZpbXBsKHByb3RvY29sLCB0eXBlLCBpbXBsKSB7XG4gIHByb3RvY29sLmltcGxlbWVudGF0aW9uKHR5cGUsIGltcGwpO1xufVxuXG52YXIgS2VybmVsID0ge1xuICBTcGVjaWFsRm9ybXMsXG4gIHRsLFxuICBoZCxcbiAgaXNfbmlsLFxuICBpc19hdG9tLFxuICBpc19iaW5hcnksXG4gIGlzX2Jvb2xlYW4sXG4gIGlzX2Z1bmN0aW9uLFxuICBpc19mbG9hdCxcbiAgaXNfaW50ZWdlcixcbiAgaXNfbGlzdCxcbiAgaXNfbWFwLFxuICBpc19udW1iZXIsXG4gIGlzX3R1cGxlLFxuICBsZW5ndGgsXG4gIGlzX3BpZCxcbiAgaXNfcG9ydCxcbiAgaXNfcmVmZXJlbmNlLFxuICBpc19iaXRzdHJpbmcsXG4gIGluOiBfX2luX18sXG4gIGFicyxcbiAgcm91bmQsXG4gIGVsZW0sXG4gIHJlbSxcbiAgZGl2LFxuICBhbmQsXG4gIG9yLFxuICBub3QsXG4gIGFwcGx5LFxuICB0b19zdHJpbmcsXG4gIG1hdGNoX19xbWFya19fLFxuICBkZWZzdHJ1Y3QsXG4gIGRlZnByb3RvY29sLFxuICBkZWZpbXBsXG59O1xuXG5sZXQgQXRvbSA9IHt9O1xuXG5BdG9tLnRvX3N0cmluZyA9IGZ1bmN0aW9uIChhdG9tKSB7XG4gIHJldHVybiBTeW1ib2wua2V5Rm9yKGF0b20pO1xufTtcblxuQXRvbS50b19jaGFyX2xpc3QgPSBmdW5jdGlvbiAoYXRvbSkge1xuICByZXR1cm4gQXRvbS50b19zdHJpbmcoYXRvbSkuc3BsaXQoJycpO1xufTtcblxubGV0IEludGVnZXIgPSB7XG5cbiAgaXNfZXZlbjogZnVuY3Rpb24gKG4pIHtcbiAgICByZXR1cm4gbiAlIDIgPT09IDA7XG4gIH0sXG5cbiAgaXNfb2RkOiBmdW5jdGlvbiAobikge1xuICAgIHJldHVybiBuICUgMiAhPT0gMDtcbiAgfSxcblxuICBwYXJzZTogZnVuY3Rpb24gKGJpbikge1xuICAgIGxldCByZXN1bHQgPSBwYXJzZUludChiaW4pO1xuXG4gICAgaWYgKGlzTmFOKHJlc3VsdCkpIHtcbiAgICAgIHJldHVybiBLZXJuZWwuU3BlY2lhbEZvcm1zLmF0b20oXCJlcnJvclwiKTtcbiAgICB9XG5cbiAgICBsZXQgaW5kZXhPZkRvdCA9IGJpbi5pbmRleE9mKFwiLlwiKTtcblxuICAgIGlmIChpbmRleE9mRG90ID49IDApIHtcbiAgICAgIHJldHVybiBLZXJuZWwuU3BlY2lhbEZvcm1zLnR1cGxlKHJlc3VsdCwgYmluLnN1YnN0cmluZyhpbmRleE9mRG90KSk7XG4gICAgfVxuXG4gICAgcmV0dXJuIEtlcm5lbC5TcGVjaWFsRm9ybXMudHVwbGUocmVzdWx0LCBcIlwiKTtcbiAgfSxcblxuICB0b19jaGFyX2xpc3Q6IGZ1bmN0aW9uIChudW1iZXIsIGJhc2UgPSAxMCkge1xuICAgIHJldHVybiBudW1iZXIudG9TdHJpbmcoYmFzZSkuc3BsaXQoXCJcIik7XG4gIH0sXG5cbiAgdG9fc3RyaW5nOiBmdW5jdGlvbiAobnVtYmVyLCBiYXNlID0gMTApIHtcbiAgICByZXR1cm4gbnVtYmVyLnRvU3RyaW5nKGJhc2UpO1xuICB9XG59O1xuXG5mdW5jdGlvbiBjYWxsX3Byb3BlcnR5KGl0ZW0sIHByb3BlcnR5KSB7XG4gIGlmIChwcm9wZXJ0eSBpbiBpdGVtKSB7XG4gICAgaXRlbVtwcm9wZXJ0eV07XG4gICAgaWYgKGl0ZW1bcHJvcGVydHldIGluc3RhbmNlb2YgRnVuY3Rpb24pIHtcbiAgICAgIHJldHVybiBpdGVtW3Byb3BlcnR5XSgpO1xuICAgIH0gZWxzZSB7XG4gICAgICByZXR1cm4gaXRlbVtwcm9wZXJ0eV07XG4gICAgfVxuICB9IGVsc2UgaWYgKFN5bWJvbC5mb3IocHJvcGVydHkpIGluIGl0ZW0pIHtcbiAgICBsZXQgcHJvcCA9IFN5bWJvbC5mb3IocHJvcGVydHkpO1xuICAgIGlmIChpdGVtW3Byb3BdIGluc3RhbmNlb2YgRnVuY3Rpb24pIHtcbiAgICAgIHJldHVybiBpdGVtW3Byb3BdKCk7XG4gICAgfSBlbHNlIHtcbiAgICAgIHJldHVybiBpdGVtW3Byb3BdO1xuICAgIH1cbiAgfVxuXG4gIHRocm93IG5ldyBFcnJvcihgUHJvcGVydHkgJHsgcHJvcGVydHkgfSBub3QgZm91bmQgaW4gJHsgaXRlbSB9YCk7XG59XG5cbnZhciBqcyA9IHtcbiAgY2FsbF9wcm9wZXJ0eVxufTtcblxubGV0IENoYXJzJDEgPSBLZXJuZWwuZGVmcHJvdG9jb2woe1xuICB0b19zdHJpbmc6IGZ1bmN0aW9uICh0aGluZykge31cbn0pO1xuXG5LZXJuZWwuZGVmaW1wbChDaGFycyQxLCBCaXRTdHJpbmcsIHtcbiAgdG9fc3RyaW5nOiBmdW5jdGlvbiAodGhpbmcpIHtcbiAgICBpZiAoS2VybmVsLmlzX2JpbmFyeSh0aGluZykpIHtcbiAgICAgIHJldHVybiB0aGluZztcbiAgICB9XG5cbiAgICByZXR1cm4gdGhpbmcudG9TdHJpbmcoKTtcbiAgfVxufSk7XG5cbktlcm5lbC5kZWZpbXBsKENoYXJzJDEsIFN5bWJvbCwge1xuICB0b19zdHJpbmc6IGZ1bmN0aW9uICh0aGluZykge1xuICAgIGlmIChuaWwpIHtcbiAgICAgIHJldHVybiBcIlwiO1xuICAgIH1cblxuICAgIHJldHVybiBBdG9tLnRvX3N0cmluZyh0aGluZyk7XG4gIH1cbn0pO1xuXG5LZXJuZWwuZGVmaW1wbChDaGFycyQxLCBJbnRlZ2VyVHlwZSwge1xuICB0b19zdHJpbmc6IGZ1bmN0aW9uICh0aGluZykge1xuICAgIHJldHVybiBJbnRlZ2VyLnRvX3N0cmluZyh0aGluZyk7XG4gIH1cbn0pO1xuXG5LZXJuZWwuZGVmaW1wbChDaGFycyQxLCBGbG9hdFR5cGUsIHtcbiAgdG9fc3RyaW5nOiBmdW5jdGlvbiAodGhpbmcpIHtcbiAgICByZXR1cm4gdGhpbmcudG9TdHJpbmc7XG4gIH1cbn0pO1xuXG5LZXJuZWwuZGVmaW1wbChDaGFycyQxLCBBcnJheSwge1xuICB0b19zdHJpbmc6IGZ1bmN0aW9uICh0aGluZykge1xuICAgIHJldHVybiB0aGluZy50b1N0cmluZygpO1xuICB9XG59KTtcblxuS2VybmVsLmRlZmltcGwoQ2hhcnMkMSwgQ29yZS5UdXBsZSwge1xuICB0b19zdHJpbmc6IGZ1bmN0aW9uICh0aGluZykge1xuICAgIHJldHVybiBUdXBsZS50b19zdHJpbmcodGhpbmcpO1xuICB9XG59KTtcblxuS2VybmVsLmRlZmltcGwoQ2hhcnMkMSwgbnVsbCwge1xuICB0b19zdHJpbmc6IGZ1bmN0aW9uICh0aGluZykge1xuICAgIHJldHVybiB0aGluZy50b1N0cmluZygpO1xuICB9XG59KTtcblxuZnVuY3Rpb24gdG9fYXRvbShzdHJpbmcpIHtcbiAgcmV0dXJuIFN5bWJvbC5mb3Ioc3RyaW5nKTtcbn1cblxuZnVuY3Rpb24gdG9fZXhpc3RpbmdfYXRvbShzdHJpbmcpIHtcbiAgcmV0dXJuIFN5bWJvbC5mb3Ioc3RyaW5nKTtcbn1cblxuZnVuY3Rpb24gdG9fY2hhcl9saXN0KHN0cmluZykge1xuICByZXR1cm4gc3RyaW5nLnNwbGl0KCcnKTtcbn1cblxuZnVuY3Rpb24gdG9fZmxvYXQoc3RyaW5nKSB7XG4gIHJldHVybiBwYXJzZUZsb2F0KHN0cmluZyk7XG59XG5cbmZ1bmN0aW9uIHRvX2ludGVnZXIoc3RyaW5nLCBiYXNlID0gMTApIHtcbiAgcmV0dXJuIHBhcnNlSW50KHN0cmluZywgYmFzZSk7XG59XG5cbmZ1bmN0aW9uIHVwY2FzZShiaW5hcnkpIHtcbiAgcmV0dXJuIGJpbmFyeS50b1VwcGVyQ2FzZSgpO1xufVxuXG5mdW5jdGlvbiBkb3duY2FzZShiaW5hcnkpIHtcbiAgcmV0dXJuIGJpbmFyeS50b0xvd2VyQ2FzZSgpO1xufVxuXG5mdW5jdGlvbiBhdChzdHJpbmcsIHBvc2l0aW9uKSB7XG4gIGlmIChwb3NpdGlvbiA+IHN0cmluZy5sZW5ndGggLSAxKSB7XG4gICAgcmV0dXJuIG51bGw7XG4gIH1cblxuICByZXR1cm4gc3RyaW5nW3Bvc2l0aW9uXTtcbn1cblxuZnVuY3Rpb24gY2FwaXRhbGl6ZShzdHJpbmcpIHtcbiAgbGV0IHJldHVyblN0cmluZyA9ICcnO1xuXG4gIGZvciAobGV0IGkgPSAwOyBpIDwgc3RyaW5nLmxlbmd0aDsgaSsrKSB7XG4gICAgaWYgKGkgPT09IDApIHtcbiAgICAgIHJldHVyblN0cmluZyA9IHJldHVyblN0cmluZyArIHN0cmluZ1tpXS50b1VwcGVyQ2FzZSgpO1xuICAgIH0gZWxzZSB7XG4gICAgICByZXR1cm5TdHJpbmcgPSByZXR1cm5TdHJpbmcgKyBzdHJpbmdbaV0udG9Mb3dlckNhc2UoKTtcbiAgICB9XG4gIH1cblxuICByZXR1cm4gcmV0dXJuU3RyaW5nO1xufVxuXG5mdW5jdGlvbiBjb2RlcG9pbnRzKHN0cmluZykge1xuICByZXR1cm4gdG9fY2hhcl9saXN0KHN0cmluZykubWFwKGZ1bmN0aW9uIChjKSB7XG4gICAgcmV0dXJuIGMuY29kZVBvaW50QXQoMCk7XG4gIH0pO1xufVxuXG5mdW5jdGlvbiBjb250YWluc19fcW1fXyhzdHJpbmcsIGNvbnRhaW5zKSB7XG4gIGlmIChBcnJheS5pc0FycmF5KGNvbnRhaW5zKSkge1xuICAgIHJldHVybiBjb250YWlucy5zb21lKGZ1bmN0aW9uIChzKSB7XG4gICAgICByZXR1cm4gc3RyaW5nLmluZGV4T2YocykgPiAtMTtcbiAgICB9KTtcbiAgfVxuXG4gIHJldHVybiBzdHJpbmcuaW5kZXhPZihjb250YWlucykgPiAtMTtcbn1cblxuZnVuY3Rpb24gZHVwbGljYXRlJDEoc3ViamVjdCwgbikge1xuICByZXR1cm4gc3ViamVjdC5yZXBlYXQobik7XG59XG5cbmZ1bmN0aW9uIGVuZHNfd2l0aF9fcW1fXyhzdHJpbmcsIHN1ZmZpeGVzKSB7XG4gIGlmIChBcnJheS5pc0FycmF5KHN1ZmZpeGVzKSkge1xuICAgIHJldHVybiBzdWZmaXhlcy5zb21lKGZ1bmN0aW9uIChzKSB7XG4gICAgICByZXR1cm4gc3RyaW5nLmVuZHNXaXRoKHMpO1xuICAgIH0pO1xuICB9XG5cbiAgcmV0dXJuIHN0cmluZy5lbmRzV2l0aChzdWZmaXhlcyk7XG59XG5cbmZ1bmN0aW9uIGZpcnN0KHN0cmluZykge1xuICBpZiAoIXN0cmluZykge1xuICAgIHJldHVybiBudWxsO1xuICB9XG5cbiAgcmV0dXJuIHN0cmluZ1swXTtcbn1cblxuZnVuY3Rpb24gZ3JhcGhlbWVzKHN0cmluZykge1xuICByZXR1cm4gc3RyaW5nLnNwbGl0KCcnKTtcbn1cblxuZnVuY3Rpb24gbGFzdChzdHJpbmcpIHtcbiAgaWYgKCFzdHJpbmcpIHtcbiAgICByZXR1cm4gbnVsbDtcbiAgfVxuXG4gIHJldHVybiBzdHJpbmdbc3RyaW5nLmxlbmd0aCAtIDFdO1xufVxuXG5mdW5jdGlvbiBsZW5ndGgkMShzdHJpbmcpIHtcbiAgcmV0dXJuIHN0cmluZy5sZW5ndGg7XG59XG5cbmZ1bmN0aW9uIG1hdGNoX19xbV9fKHN0cmluZywgcmVnZXgpIHtcbiAgcmV0dXJuIHN0cmluZy5tYXRjaChyZWdleCkgIT0gbnVsbDtcbn1cblxuZnVuY3Rpb24gbmV4dF9jb2RlcG9pbnQoc3RyaW5nKSB7XG4gIGlmICghc3RyaW5nIHx8IHN0cmluZyA9PT0gJycpIHtcbiAgICByZXR1cm4gbnVsbDtcbiAgfVxuXG4gIHJldHVybiBLZXJuZWwuU3BlY2lhbEZvcm1zLnR1cGxlKHN0cmluZ1swXS5jb2RlUG9pbnRBdCgwKSwgc3RyaW5nLnN1YnN0cigxKSk7XG59XG5cbmZ1bmN0aW9uIG5leHRfZ3JhcGhlbWUoc3RyaW5nKSB7XG4gIGlmICghc3RyaW5nIHx8IHN0cmluZyA9PT0gJycpIHtcbiAgICByZXR1cm4gbnVsbDtcbiAgfVxuXG4gIHJldHVybiBLZXJuZWwuU3BlY2lhbEZvcm1zLnR1cGxlKHN0cmluZ1swXSwgc3RyaW5nLnN1YnN0cigxKSk7XG59XG5cbmZ1bmN0aW9uIHJldmVyc2Uoc3RyaW5nKSB7XG4gIGxldCByZXR1cm5WYWx1ZSA9ICcnO1xuXG4gIGZvciAodmFyIGkgPSBzdHJpbmcubGVuZ3RoIC0gMTsgaSA+PSAwOyBpLS0pIHtcbiAgICByZXR1cm5WYWx1ZSA9IHJldHVyblZhbHVlICsgc3RyaW5nW2ldO1xuICB9O1xuXG4gIHJldHVybiByZXR1cm5WYWx1ZTtcbn1cblxuZnVuY3Rpb24gc3BsaXQoc3RyaW5nKSB7XG4gIHJldHVybiBzdHJpbmcuc3BsaXQoKTtcbn1cblxuZnVuY3Rpb24gc3RhcnRzX3dpdGhfX3FtX18oc3RyaW5nLCBwcmVmaXhlcykge1xuICBpZiAoQXJyYXkuaXNBcnJheShwcmVmaXhlcykpIHtcbiAgICByZXR1cm4gcHJlZml4ZXMuc29tZShmdW5jdGlvbiAocykge1xuICAgICAgcmV0dXJuIHN0cmluZy5zdGFydHNXaXRoKHMpO1xuICAgIH0pO1xuICB9XG5cbiAgcmV0dXJuIHN0cmluZy5zdGFydHNXaXRoKHByZWZpeGVzKTtcbn1cblxuZnVuY3Rpb24gdmFsaWRfY2hhcmFjdGVyX19xbV9fKGNvZGVwb2ludCkge1xuICB0cnkge1xuICAgIHJldHVybiBTdHJpbmcuZnJvbUNvZGVQb2ludChjb2RlcG9pbnQpICE9IG51bGw7XG4gIH0gY2F0Y2ggKGUpIHtcbiAgICByZXR1cm4gZmFsc2U7XG4gIH1cbn1cblxudmFyIFN0cmluZyQxID0ge1xuICBhdCxcbiAgY2FwaXRhbGl6ZSxcbiAgY29kZXBvaW50cyxcbiAgY29udGFpbnNfX3FtX18sXG4gIGRvd25jYXNlLFxuICBkdXBsaWNhdGU6IGR1cGxpY2F0ZSQxLFxuICBlbmRzX3dpdGhfX3FtX18sXG4gIGZpcnN0LFxuICBncmFwaGVtZXMsXG4gIGxhc3QsXG4gIGxlbmd0aDogbGVuZ3RoJDEsXG4gIG1hdGNoX19xbV9fLFxuICBuZXh0X2NvZGVwb2ludCxcbiAgbmV4dF9ncmFwaGVtZSxcbiAgcmV2ZXJzZSxcbiAgc3BsaXQsXG4gIHN0YXJ0c193aXRoX19xbV9fLFxuICB0b19hdG9tLFxuICB0b19jaGFyX2xpc3QsXG4gIHRvX2V4aXN0aW5nX2F0b20sXG4gIHRvX2Zsb2F0LFxuICB0b19pbnRlZ2VyLFxuICB1cGNhc2UsXG4gIHZhbGlkX2NoYXJhY3Rlcl9fcW1fXyxcbiAgQ2hhcnM6IENoYXJzJDFcbn07XG5cbmxldCBDaGFycyA9IEtlcm5lbC5kZWZwcm90b2NvbCh7XG4gIHRvX2NoYXJfbGlzdDogZnVuY3Rpb24gKHRoaW5nKSB7fVxufSk7XG5cbktlcm5lbC5kZWZpbXBsKENoYXJzLCBLZXJuZWwuaXNfYml0c3RyaW5nLCB7XG4gIHRvX2NoYXJfbGlzdDogZnVuY3Rpb24gKHRoaW5nKSB7XG4gICAgaWYgKEtlcm5lbC5pc19iaW5hcnkodGhpbmcpKSB7XG4gICAgICByZXR1cm4gU3RyaW5nJDEudG9fY2hhcl9saXN0KHRoaW5nKTtcbiAgICB9XG5cbiAgICByZXR1cm4gdGhpbmcudG9TdHJpbmcoKTtcbiAgfVxufSk7XG5cbktlcm5lbC5kZWZpbXBsKENoYXJzLCBLZXJuZWwuaXNfYXRvbSwge1xuICB0b19jaGFyX2xpc3Q6IGZ1bmN0aW9uICh0aGluZykge1xuICAgIHJldHVybiBBdG9tLnRvX2NoYXJfbGlzdCh0aGluZyk7XG4gIH1cbn0pO1xuXG5LZXJuZWwuZGVmaW1wbChDaGFycywgS2VybmVsLmlzX2ludGVnZXIsIHtcbiAgdG9fY2hhcl9saXN0OiBmdW5jdGlvbiAodGhpbmcpIHtcbiAgICByZXR1cm4gSW50ZWdlci50b19jaGFyX2xpc3QodGhpbmcpO1xuICB9XG59KTtcblxuS2VybmVsLmRlZmltcGwoQ2hhcnMsIEtlcm5lbC5pc19saXN0LCB7XG4gIHRvX2NoYXJfbGlzdDogZnVuY3Rpb24gKHRoaW5nKSB7XG4gICAgcmV0dXJuIHRoaW5nO1xuICB9XG59KTtcblxubGV0IExpc3QgPSB7fTtcblxuTGlzdC5DaGFycyA9IENoYXJzO1xuXG5MaXN0LmRlbGV0ZSA9IGZ1bmN0aW9uIChsaXN0LCBpdGVtKSB7XG4gIGxldCBuZXdfdmFsdWUgPSBbXTtcbiAgbGV0IHZhbHVlX2ZvdW5kID0gZmFsc2U7XG5cbiAgZm9yIChsZXQgeCBvZiBsaXN0KSB7XG4gICAgaWYgKHggPT09IGl0ZW0gJiYgdmFsdWVfZm91bmQgIT09IGZhbHNlKSB7XG4gICAgICBuZXdfdmFsdWUucHVzaCh4KTtcbiAgICAgIHZhbHVlX2ZvdW5kID0gdHJ1ZTtcbiAgICB9IGVsc2UgaWYgKHggIT09IGl0ZW0pIHtcbiAgICAgIG5ld192YWx1ZS5wdXNoKHgpO1xuICAgIH1cbiAgfVxuXG4gIHJldHVybiBLZXJuZWwuU3BlY2lhbEZvcm1zLmxpc3QoLi4ubmV3X3ZhbHVlKTtcbn07XG5cbkxpc3QuZGVsZXRlX2F0ID0gZnVuY3Rpb24gKGxpc3QsIGluZGV4KSB7XG4gIGxldCBuZXdfdmFsdWUgPSBbXTtcblxuICBmb3IgKGxldCBpID0gMDsgaSA8IGxpc3QubGVuZ3RoOyBpKyspIHtcbiAgICBpZiAoaSAhPT0gaW5kZXgpIHtcbiAgICAgIG5ld192YWx1ZS5wdXNoKGxpc3RbaV0pO1xuICAgIH1cbiAgfVxuXG4gIHJldHVybiBLZXJuZWwuU3BlY2lhbEZvcm1zLmxpc3QoLi4ubmV3X3ZhbHVlKTtcbn07XG5cbkxpc3QuZHVwbGljYXRlID0gZnVuY3Rpb24gKGVsZW0sIG4pIHtcbiAgbGV0IG5ld192YWx1ZSA9IFtdO1xuXG4gIGZvciAodmFyIGkgPSAwOyBpIDwgbjsgaSsrKSB7XG4gICAgbmV3X3ZhbHVlLnB1c2goZWxlbSk7XG4gIH1cblxuICByZXR1cm4gS2VybmVsLlNwZWNpYWxGb3Jtcy5saXN0KC4uLm5ld192YWx1ZSk7XG59O1xuXG5MaXN0LmZpcnN0ID0gZnVuY3Rpb24gKGxpc3QpIHtcbiAgcmV0dXJuIGxpc3RbMF07XG59O1xuXG5MaXN0LmZsYXR0ZW4gPSBmdW5jdGlvbiAobGlzdCwgdGFpbCA9IEtlcm5lbC5TcGVjaWFsRm9ybXMubGlzdCgpKSB7XG4gIGxldCBuZXdfdmFsdWUgPSBbXTtcblxuICBmb3IgKGxldCB4IG9mIGxpc3QpIHtcbiAgICBpZiAoS2VybmVsLmlzX2xpc3QoeCkpIHtcbiAgICAgIG5ld192YWx1ZSA9IG5ld192YWx1ZS5jb25jYXQoTGlzdC5mbGF0dGVuKHgpKTtcbiAgICB9IGVsc2Uge1xuICAgICAgbmV3X3ZhbHVlLnB1c2goeCk7XG4gICAgfVxuICB9XG5cbiAgbmV3X3ZhbHVlID0gbmV3X3ZhbHVlLmNvbmNhdCh0YWlsKTtcblxuICByZXR1cm4gS2VybmVsLlNwZWNpYWxGb3Jtcy5saXN0KC4uLm5ld192YWx1ZSk7XG59O1xuXG5MaXN0LmZvbGRsID0gZnVuY3Rpb24gKGxpc3QsIGFjYywgZnVuYykge1xuICByZXR1cm4gbGlzdC5yZWR1Y2UoZnVuYywgYWNjKTtcbn07XG5cbkxpc3QuZm9sZHIgPSBmdW5jdGlvbiAobGlzdCwgYWNjLCBmdW5jKSB7XG4gIGxldCBuZXdfYWNjID0gYWNjO1xuXG4gIGZvciAodmFyIGkgPSBsaXN0Lmxlbmd0aCAtIDE7IGkgPj0gMDsgaS0tKSB7XG4gICAgbmV3X2FjYyA9IGZ1bmMobGlzdFtpXSwgbmV3X2FjYyk7XG4gIH1cblxuICByZXR1cm4gbmV3X2FjYztcbn07XG5cbkxpc3QuaW5zZXJ0X2F0ID0gZnVuY3Rpb24gKGxpc3QsIGluZGV4LCB2YWx1ZSkge1xuICBsZXQgbmV3X3ZhbHVlID0gW107XG5cbiAgZm9yIChsZXQgaSA9IDA7IGkgPCBsaXN0Lmxlbmd0aDsgaSsrKSB7XG4gICAgaWYgKGkgPT09IGluZGV4KSB7XG4gICAgICBuZXdfdmFsdWUucHVzaCh2YWx1ZSk7XG4gICAgICBuZXdfdmFsdWUucHVzaChsaXN0W2ldKTtcbiAgICB9IGVsc2Uge1xuICAgICAgbmV3X3ZhbHVlLnB1c2gobGlzdFtpXSk7XG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIEtlcm5lbC5TcGVjaWFsRm9ybXMubGlzdCguLi5uZXdfdmFsdWUpO1xufTtcblxuTGlzdC5rZXlkZWxldGUgPSBmdW5jdGlvbiAobGlzdCwga2V5LCBwb3NpdGlvbikge1xuICBsZXQgbmV3X2xpc3QgPSBbXTtcblxuICBmb3IgKGxldCBpID0gMDsgaSA8IGxpc3QubGVuZ3RoOyBpKyspIHtcbiAgICBpZiAoIUtlcm5lbC5tYXRjaF9fcW1hcmtfXyhsaXN0W2ldW3Bvc2l0aW9uXSwga2V5KSkge1xuICAgICAgbmV3X2xpc3QucHVzaChsaXN0W2ldKTtcbiAgICB9XG4gIH1cblxuICByZXR1cm4gS2VybmVsLlNwZWNpYWxGb3Jtcy5saXN0KC4uLm5ld19saXN0KTtcbn07XG5cbkxpc3Qua2V5ZmluZCA9IGZ1bmN0aW9uIChsaXN0LCBrZXksIHBvc2l0aW9uLCBfZGVmYXVsdCA9IG51bGwpIHtcblxuICBmb3IgKGxldCBpID0gMDsgaSA8IGxpc3QubGVuZ3RoOyBpKyspIHtcbiAgICBpZiAoS2VybmVsLm1hdGNoX19xbWFya19fKGxpc3RbaV1bcG9zaXRpb25dLCBrZXkpKSB7XG4gICAgICByZXR1cm4gbGlzdFtpXTtcbiAgICB9XG4gIH1cblxuICByZXR1cm4gX2RlZmF1bHQ7XG59O1xuXG5MaXN0LmtleW1lbWJlcl9fcW1hcmtfXyA9IGZ1bmN0aW9uIChsaXN0LCBrZXksIHBvc2l0aW9uKSB7XG5cbiAgZm9yIChsZXQgaSA9IDA7IGkgPCBsaXN0Lmxlbmd0aDsgaSsrKSB7XG4gICAgaWYgKEtlcm5lbC5tYXRjaF9fcW1hcmtfXyhsaXN0W2ldW3Bvc2l0aW9uXSwga2V5KSkge1xuICAgICAgcmV0dXJuIHRydWU7XG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIGZhbHNlO1xufTtcblxuTGlzdC5rZXlyZXBsYWNlID0gZnVuY3Rpb24gKGxpc3QsIGtleSwgcG9zaXRpb24sIG5ld190dXBsZSkge1xuICBsZXQgbmV3X2xpc3QgPSBbXTtcblxuICBmb3IgKGxldCBpID0gMDsgaSA8IGxpc3QubGVuZ3RoOyBpKyspIHtcbiAgICBpZiAoIUtlcm5lbC5tYXRjaF9fcW1hcmtfXyhsaXN0W2ldW3Bvc2l0aW9uXSwga2V5KSkge1xuICAgICAgbmV3X2xpc3QucHVzaChsaXN0W2ldKTtcbiAgICB9IGVsc2Uge1xuICAgICAgbmV3X2xpc3QucHVzaChuZXdfdHVwbGUpO1xuICAgIH1cbiAgfVxuXG4gIHJldHVybiBLZXJuZWwuU3BlY2lhbEZvcm1zLmxpc3QoLi4ubmV3X2xpc3QpO1xufTtcblxuTGlzdC5rZXlzb3J0ID0gZnVuY3Rpb24gKGxpc3QsIHBvc2l0aW9uKSB7XG4gIGxldCBuZXdfbGlzdCA9IGxpc3Q7XG5cbiAgbmV3X2xpc3Quc29ydChmdW5jdGlvbiAoYSwgYikge1xuICAgIGlmIChwb3NpdGlvbiA9PT0gMCkge1xuICAgICAgaWYgKGFbcG9zaXRpb25dLnZhbHVlIDwgYltwb3NpdGlvbl0udmFsdWUpIHtcbiAgICAgICAgcmV0dXJuIC0xO1xuICAgICAgfVxuXG4gICAgICBpZiAoYVtwb3NpdGlvbl0udmFsdWUgPiBiW3Bvc2l0aW9uXS52YWx1ZSkge1xuICAgICAgICByZXR1cm4gMTtcbiAgICAgIH1cblxuICAgICAgcmV0dXJuIDA7XG4gICAgfSBlbHNlIHtcbiAgICAgIGlmIChhW3Bvc2l0aW9uXSA8IGJbcG9zaXRpb25dKSB7XG4gICAgICAgIHJldHVybiAtMTtcbiAgICAgIH1cblxuICAgICAgaWYgKGFbcG9zaXRpb25dID4gYltwb3NpdGlvbl0pIHtcbiAgICAgICAgcmV0dXJuIDE7XG4gICAgICB9XG5cbiAgICAgIHJldHVybiAwO1xuICAgIH1cbiAgfSk7XG5cbiAgcmV0dXJuIEtlcm5lbC5TcGVjaWFsRm9ybXMubGlzdCguLi5uZXdfbGlzdCk7XG59O1xuXG5MaXN0LmtleXN0b3JlID0gZnVuY3Rpb24gKGxpc3QsIGtleSwgcG9zaXRpb24sIG5ld190dXBsZSkge1xuICBsZXQgbmV3X2xpc3QgPSBbXTtcbiAgbGV0IHJlcGxhY2VkID0gZmFsc2U7XG5cbiAgZm9yIChsZXQgaSA9IDA7IGkgPCBsaXN0Lmxlbmd0aDsgaSsrKSB7XG4gICAgaWYgKCFLZXJuZWwubWF0Y2hfX3FtYXJrX18obGlzdFtpXVtwb3NpdGlvbl0sIGtleSkpIHtcbiAgICAgIG5ld19saXN0LnB1c2gobGlzdFtpXSk7XG4gICAgfSBlbHNlIHtcbiAgICAgIG5ld19saXN0LnB1c2gobmV3X3R1cGxlKTtcbiAgICAgIHJlcGxhY2VkID0gdHJ1ZTtcbiAgICB9XG4gIH1cblxuICBpZiAoIXJlcGxhY2VkKSB7XG4gICAgbmV3X2xpc3QucHVzaChuZXdfdHVwbGUpO1xuICB9XG5cbiAgcmV0dXJuIEtlcm5lbC5TcGVjaWFsRm9ybXMubGlzdCguLi5uZXdfbGlzdCk7XG59O1xuXG5MaXN0Lmxhc3QgPSBmdW5jdGlvbiAobGlzdCkge1xuICByZXR1cm4gbGlzdFtsaXN0Lmxlbmd0aCAtIDFdO1xufTtcblxuTGlzdC5yZXBsYWNlX2F0ID0gZnVuY3Rpb24gKGxpc3QsIGluZGV4LCB2YWx1ZSkge1xuICBsZXQgbmV3X3ZhbHVlID0gW107XG5cbiAgZm9yIChsZXQgaSA9IDA7IGkgPCBsaXN0Lmxlbmd0aDsgaSsrKSB7XG4gICAgaWYgKGkgPT09IGluZGV4KSB7XG4gICAgICBuZXdfdmFsdWUucHVzaCh2YWx1ZSk7XG4gICAgfSBlbHNlIHtcbiAgICAgIG5ld192YWx1ZS5wdXNoKGxpc3RbaV0pO1xuICAgIH1cbiAgfVxuXG4gIHJldHVybiBLZXJuZWwuU3BlY2lhbEZvcm1zLmxpc3QoLi4ubmV3X3ZhbHVlKTtcbn07XG5cbkxpc3QudXBkYXRlX2F0ID0gZnVuY3Rpb24gKGxpc3QsIGluZGV4LCBmdW4pIHtcbiAgbGV0IG5ld192YWx1ZSA9IFtdO1xuXG4gIGZvciAobGV0IGkgPSAwOyBpIDwgbGlzdC5jb3VudCgpOyBpKyspIHtcbiAgICBpZiAoaSA9PT0gaW5kZXgpIHtcbiAgICAgIG5ld192YWx1ZS5wdXNoKGZ1bihsaXN0LmdldChpKSkpO1xuICAgIH0gZWxzZSB7XG4gICAgICBuZXdfdmFsdWUucHVzaChsaXN0LmdldChpKSk7XG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIG5ld192YWx1ZTtcbn07XG5cbkxpc3Qud3JhcCA9IGZ1bmN0aW9uIChsaXN0KSB7XG4gIGlmIChLZXJuZWwuaXNfbGlzdChsaXN0KSkge1xuICAgIHJldHVybiBsaXN0O1xuICB9IGVsc2UgaWYgKGxpc3QgPT0gbnVsbCkge1xuICAgIHJldHVybiBLZXJuZWwuU3BlY2lhbEZvcm1zLmxpc3QoKTtcbiAgfSBlbHNlIHtcbiAgICByZXR1cm4gS2VybmVsLlNwZWNpYWxGb3Jtcy5saXN0KGxpc3QpO1xuICB9XG59O1xuXG5MaXN0LnppcCA9IGZ1bmN0aW9uIChsaXN0X29mX2xpc3RzKSB7XG4gIGlmIChsaXN0X29mX2xpc3RzLmxlbmd0aCA9PT0gMCkge1xuICAgIHJldHVybiBLZXJuZWwuU3BlY2lhbEZvcm1zLmxpc3QoKTtcbiAgfVxuXG4gIGxldCBuZXdfdmFsdWUgPSBbXTtcbiAgbGV0IHNtYWxsZXN0X2xlbmd0aCA9IGxpc3Rfb2ZfbGlzdHNbMF07XG5cbiAgZm9yIChsZXQgeCBvZiBsaXN0X29mX2xpc3RzKSB7XG4gICAgaWYgKHgubGVuZ3RoIDwgc21hbGxlc3RfbGVuZ3RoKSB7XG4gICAgICBzbWFsbGVzdF9sZW5ndGggPSB4Lmxlbmd0aDtcbiAgICB9XG4gIH1cblxuICBmb3IgKGxldCBpID0gMDsgaSA8IHNtYWxsZXN0X2xlbmd0aDsgaSsrKSB7XG4gICAgbGV0IGN1cnJlbnRfdmFsdWUgPSBbXTtcbiAgICBmb3IgKGxldCBqID0gMDsgaiA8IGxpc3Rfb2ZfbGlzdHMubGVuZ3RoOyBqKyspIHtcbiAgICAgIGN1cnJlbnRfdmFsdWUucHVzaChsaXN0X29mX2xpc3RzW2pdW2ldKTtcbiAgICB9XG5cbiAgICBuZXdfdmFsdWUucHVzaChLZXJuZWwuU3BlY2lhbEZvcm1zLnR1cGxlKC4uLmN1cnJlbnRfdmFsdWUpKTtcbiAgfVxuXG4gIHJldHVybiBLZXJuZWwuU3BlY2lhbEZvcm1zLmxpc3QoLi4ubmV3X3ZhbHVlKTtcbn07XG5cbkxpc3QudG9fdHVwbGUgPSBmdW5jdGlvbiAobGlzdCkge1xuICByZXR1cm4gS2VybmVsLlNwZWNpYWxGb3Jtcy50dXBsZS5hcHBseShudWxsLCBsaXN0KTtcbn07XG5cbkxpc3QuYXBwZW5kID0gZnVuY3Rpb24gKGxpc3QsIHZhbHVlKSB7XG4gIHJldHVybiBLZXJuZWwuU3BlY2lhbEZvcm1zLmxpc3QoLi4ubGlzdC5jb25jYXQoW3ZhbHVlXSkpO1xufTtcblxuTGlzdC5wcmVwZW5kID0gZnVuY3Rpb24gKGxpc3QsIHZhbHVlKSB7XG4gIHJldHVybiBLZXJuZWwuU3BlY2lhbEZvcm1zLmxpc3QoLi4uW3ZhbHVlXS5jb25jYXQobGlzdCkpO1xufTtcblxuTGlzdC5jb25jYXQgPSBmdW5jdGlvbiAobGVmdCwgcmlnaHQpIHtcbiAgcmV0dXJuIGxlZnQuY29uY2F0KHJpZ2h0KTtcbn07XG5cbmxldCBSYW5nZSA9IGZ1bmN0aW9uIChfZmlyc3QsIF9sYXN0KSB7XG4gIGlmICghKHRoaXMgaW5zdGFuY2VvZiBSYW5nZSkpIHtcbiAgICByZXR1cm4gbmV3IFJhbmdlKF9maXJzdCwgX2xhc3QpO1xuICB9XG5cbiAgdGhpcy5maXJzdCA9IGZ1bmN0aW9uICgpIHtcbiAgICByZXR1cm4gX2ZpcnN0O1xuICB9O1xuXG4gIHRoaXMubGFzdCA9IGZ1bmN0aW9uICgpIHtcbiAgICByZXR1cm4gX2xhc3Q7XG4gIH07XG5cbiAgbGV0IF9yYW5nZSA9IFtdO1xuXG4gIGZvciAobGV0IGkgPSBfZmlyc3Q7IGkgPD0gX2xhc3Q7IGkrKykge1xuICAgIF9yYW5nZS5wdXNoKGkpO1xuICB9XG5cbiAgX3JhbmdlID0gT2JqZWN0LmZyZWV6ZShfcmFuZ2UpO1xuXG4gIHRoaXMudmFsdWUgPSBmdW5jdGlvbiAoKSB7XG4gICAgcmV0dXJuIF9yYW5nZTtcbiAgfTtcblxuICB0aGlzLmxlbmd0aCA9IGZ1bmN0aW9uICgpIHtcbiAgICByZXR1cm4gX3JhbmdlLmxlbmd0aDtcbiAgfTtcblxuICByZXR1cm4gdGhpcztcbn07XG5cblJhbmdlLnByb3RvdHlwZVtTeW1ib2wuaXRlcmF0b3JdID0gZnVuY3Rpb24gKCkge1xuICByZXR1cm4gdGhpcy52YWx1ZSgpW1N5bWJvbC5pdGVyYXRvcl0oKTtcbn07XG5cblJhbmdlLm5ldyA9IGZ1bmN0aW9uIChmaXJzdCwgbGFzdCkge1xuICByZXR1cm4gUmFuZ2UoZmlyc3QsIGxhc3QpO1xufTtcblxuUmFuZ2UucmFuZ2VfX3FtYXJrX18gPSBmdW5jdGlvbiAocmFuZ2UpIHtcbiAgcmV0dXJuIHJhbmdlIGluc3RhbmNlb2YgUmFuZ2U7XG59O1xuXG5sZXQgS2V5d29yZCA9IHt9O1xuXG5LZXl3b3JkLmhhc19rZXlfX3FtX18gPSBmdW5jdGlvbiAoa2V5d29yZHMsIGtleSkge1xuICBmb3IgKGxldCBrZXl3b3JkIG9mIGtleXdvcmRzKSB7XG4gICAgaWYgKEtlcm5lbC5lbGVtKGtleXdvcmQsIDApID09IGtleSkge1xuICAgICAgcmV0dXJuIHRydWU7XG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIGZhbHNlO1xufTtcblxuS2V5d29yZC5nZXQgPSBmdW5jdGlvbiAoa2V5d29yZHMsIGtleSwgdGhlX2RlZmF1bHQgPSBudWxsKSB7XG4gIGZvciAobGV0IGtleXdvcmQgb2Yga2V5d29yZHMpIHtcbiAgICBpZiAoS2VybmVsLmVsZW0oa2V5d29yZCwgMCkgPT0ga2V5KSB7XG4gICAgICByZXR1cm4gS2VybmVsLmVsZW0oa2V5d29yZCwgMSk7XG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIHRoZV9kZWZhdWx0O1xufTtcblxubGV0IEFnZW50ID0ge307XG5cbkFnZW50LnN0YXJ0ID0gZnVuY3Rpb24gKGZ1biwgb3B0aW9ucyA9IFtdKSB7XG4gIGxldCBwaWQgPSBzZWxmLnByb2Nlc3Nlcy5zcGF3bigpO1xuXG4gIGlmIChLZXl3b3JkLmhhc19rZXlfX3FtX18ob3B0aW9ucywgS2VybmVsLlNwZWNpYWxGb3Jtcy5hdG9tKCduYW1lJykpKSB7XG4gICAgcGlkID0gc2VsZi5wcm9jZXNzZXMucmVnaXN0ZXIoS2V5d29yZC5nZXQob3B0aW9ucywgS2VybmVsLlNwZWNpYWxGb3Jtcy5hdG9tKCduYW1lJykpLCBwaWQpO1xuICB9XG5cbiAgc2VsZi5wcm9jZXNzZXMucHV0KHBpZCwgJ3N0YXRlJywgZnVuKCkpO1xuICByZXR1cm4gS2VybmVsLlNwZWNpYWxGb3Jtcy50dXBsZShLZXJuZWwuU3BlY2lhbEZvcm1zLmF0b20oJ29rJyksIHBpZCk7XG59O1xuXG5BZ2VudC5zdG9wID0gZnVuY3Rpb24gKGFnZW50LCB0aW1lb3V0ID0gNTAwMCkge1xuICBzZWxmLnByb2Nlc3Nlcy5leGl0KGFnZW50KTtcbiAgcmV0dXJuIEtlcm5lbC5TcGVjaWFsRm9ybXMuYXRvbSgnb2snKTtcbn07XG5cbkFnZW50LnVwZGF0ZSA9IGZ1bmN0aW9uIChhZ2VudCwgZnVuLCB0aW1lb3V0ID0gNTAwMCkge1xuXG4gIGNvbnN0IGN1cnJlbnRfc3RhdGUgPSBzZWxmLnByb2Nlc3Nlcy5nZXQoYWdlbnQsICdzdGF0ZScpO1xuICBzZWxmLnByb2Nlc3Nlcy5wdXQoYWdlbnQsICdzdGF0ZScsIGZ1bihjdXJyZW50X3N0YXRlKSk7XG5cbiAgcmV0dXJuIEtlcm5lbC5TcGVjaWFsRm9ybXMuYXRvbSgnb2snKTtcbn07XG5cbkFnZW50LmdldCA9IGZ1bmN0aW9uIChhZ2VudCwgZnVuLCB0aW1lb3V0ID0gNTAwMCkge1xuICByZXR1cm4gZnVuKHNlbGYucHJvY2Vzc2VzLmdldChhZ2VudCwgJ3N0YXRlJykpO1xufTtcblxuQWdlbnQuZ2V0X2FuZF91cGRhdGUgPSBmdW5jdGlvbiAoYWdlbnQsIGZ1biwgdGltZW91dCA9IDUwMDApIHtcblxuICBjb25zdCBnZXRfYW5kX3VwZGF0ZV90dXBsZSA9IGZ1bihzZWxmLnByb2Nlc3Nlcy5nZXQoYWdlbnQsICdzdGF0ZScpKTtcbiAgc2VsZi5wcm9jZXNzZXMucHV0KGFnZW50LCAnc3RhdGUnLCBLZXJuZWwuZWxlbShnZXRfYW5kX3VwZGF0ZV90dXBsZSwgMSkpO1xuXG4gIHJldHVybiBLZXJuZWwuZWxlbShnZXRfYW5kX3VwZGF0ZV90dXBsZSwgMCk7XG59O1xuXG4vL2h0dHBzOi8vZGV2ZWxvcGVyLm1vemlsbGEub3JnL2VuLVVTL2RvY3MvV2ViL0FQSS9XaW5kb3dCYXNlNjQvQmFzZTY0X2VuY29kaW5nX2FuZF9kZWNvZGluZyNTb2x1dGlvbl8yXyVFMiU4MCU5M19yZXdyaXRlX3RoZV9ET01zX2F0b2IoKV9hbmRfYnRvYSgpX3VzaW5nX0phdmFTY3JpcHQnc19UeXBlZEFycmF5c19hbmRfVVRGLThcbmZ1bmN0aW9uIGI2NEVuY29kZVVuaWNvZGUoc3RyKSB7XG4gIHJldHVybiBidG9hKGVuY29kZVVSSUNvbXBvbmVudChzdHIpLnJlcGxhY2UoLyUoWzAtOUEtRl17Mn0pL2csIGZ1bmN0aW9uIChtYXRjaCwgcDEpIHtcbiAgICByZXR1cm4gU3RyaW5nLmZyb21DaGFyQ29kZSgnMHgnICsgcDEpO1xuICB9KSk7XG59XG5cbmZ1bmN0aW9uIGVuY29kZTY0KGRhdGEpIHtcbiAgcmV0dXJuIGI2NEVuY29kZVVuaWNvZGUoZGF0YSk7XG59XG5cbmZ1bmN0aW9uIGRlY29kZTY0KGRhdGEpIHtcbiAgdHJ5IHtcbiAgICByZXR1cm4gS2VybmVsLlNwZWNpYWxGb3Jtcy50dXBsZShLZXJuZWwuU3BlY2lhbEZvcm1zLmF0b20oJ29rJyksIGF0b2IoZGF0YSkpO1xuICB9IGNhdGNoIChlKSB7XG4gICAgcmV0dXJuIEtlcm5lbC5TcGVjaWFsRm9ybXMuYXRvbSgnZXJyb3InKTtcbiAgfVxuICByZXR1cm4gYnRvYShkYXRhKTtcbn1cblxuZnVuY3Rpb24gZGVjb2RlNjRfX2VtX18oZGF0YSkge1xuICByZXR1cm4gYXRvYihkYXRhKTtcbn1cblxudmFyIGJhc2UgPSB7XG4gIGVuY29kZTY0LFxuICBkZWNvZGU2NCxcbiAgZGVjb2RlNjRfX2VtX19cbn07XG5cbmZ1bmN0aW9uIGJub3QoZXhwcikge1xuICByZXR1cm4gfmV4cHI7XG59XG5cbmZ1bmN0aW9uIGJhbmQobGVmdCwgcmlnaHQpIHtcbiAgcmV0dXJuIGxlZnQgJiByaWdodDtcbn1cblxuZnVuY3Rpb24gYm9yKGxlZnQsIHJpZ2h0KSB7XG4gIHJldHVybiBsZWZ0IHwgcmlnaHQ7XG59XG5cbmZ1bmN0aW9uIGJzbChsZWZ0LCByaWdodCkge1xuICByZXR1cm4gbGVmdCA8PCByaWdodDtcbn1cblxuZnVuY3Rpb24gYnNyKGxlZnQsIHJpZ2h0KSB7XG4gIHJldHVybiBsZWZ0ID4+IHJpZ2h0O1xufVxuXG5mdW5jdGlvbiBieG9yKGxlZnQsIHJpZ2h0KSB7XG4gIHJldHVybiBsZWZ0IF4gcmlnaHQ7XG59XG5cbnZhciBiaXR3aXNlID0ge1xuICBibm90LFxuICBiYW5kLFxuICBib3IsXG4gIGJzbCxcbiAgYnNyLFxuICBieG9yXG59O1xuXG5sZXQgRW51bWVyYWJsZSA9IEtlcm5lbC5kZWZwcm90b2NvbCh7XG4gIGNvdW50OiBmdW5jdGlvbiAoY29sbGVjdGlvbikge30sXG4gIG1lbWJlcl9xbWFya19fOiBmdW5jdGlvbiAoY29sbGVjdGlvbiwgdmFsdWUpIHt9LFxuICByZWR1Y2U6IGZ1bmN0aW9uIChjb2xsZWN0aW9uLCBhY2MsIGZ1bikge31cbn0pO1xuXG5sZXQgQ29sbGVjdGFibGUgPSBLZXJuZWwuZGVmcHJvdG9jb2woe1xuICBpbnRvOiBmdW5jdGlvbiAoY29sbGVjdGFibGUpIHt9XG59KTtcblxubGV0IEluc3BlY3QgPSBLZXJuZWwuZGVmcHJvdG9jb2woe1xuICBpbnNwZWN0OiBmdW5jdGlvbiAodGhpbmcsIG9wdHMpIHt9XG59KTtcblxuZnVuY3Rpb24gX19uZXdfXygpIHtcbiAgcmV0dXJuIFNwZWNpYWxGb3Jtcy5tYXAoe30pO1xufVxuXG5mdW5jdGlvbiBrZXlzKG1hcCkge1xuICByZXR1cm4gT2JqZWN0LmtleXMobWFwKTtcbn1cblxuZnVuY3Rpb24gc2l6ZShtYXApIHtcbiAgcmV0dXJuIGtleXMobWFwKS5sZW5ndGg7XG59XG5cbmZ1bmN0aW9uIHRvX2xpc3QkMShtYXApIHtcbiAgbGV0IG1hcF9rZXlzID0ga2V5cyhtYXApO1xuICBsZXQgbGlzdCA9IFtdO1xuXG4gIGZvciAobGV0IGtleSBvZiBtYXBfa2V5cykge1xuICAgIGxpc3QucHVzaChTcGVjaWFsRm9ybXMudHVwbGUoa2V5LCBtYXBba2V5XSkpO1xuICB9XG5cbiAgcmV0dXJuIFNwZWNpYWxGb3Jtcy5saXN0KC4uLmxpc3QpO1xufVxuXG5mdW5jdGlvbiB2YWx1ZXMobWFwKSB7XG4gIGxldCBtYXBfa2V5cyA9IGtleXMobWFwKTtcbiAgbGV0IGxpc3QgPSBbXTtcblxuICBmb3IgKGxldCBrZXkgb2YgbWFwX2tleXMpIHtcbiAgICBsaXN0LnB1c2gobWFwW2tleV0pO1xuICB9XG5cbiAgcmV0dXJuIFNwZWNpYWxGb3Jtcy5saXN0KC4uLmxpc3QpO1xufVxuXG5mdW5jdGlvbiBmcm9tX3N0cnVjdChzdHJ1Y3QpIHtcbiAgbGV0IG1hcCA9IE9iamVjdC5hc3NpZ24oe30sIHN0cnVjdCk7XG4gIGRlbGV0ZSBtYXBbU3ltYm9sLmZvcihcIl9fc3RydWN0X19cIildO1xuXG4gIHJldHVybiBTcGVjaWFsRm9ybXMubWFwKG1hcCk7XG59XG5cbmZ1bmN0aW9uIF9fZGVsZXRlX18obWFwLCBrZXkpIHtcbiAgbGV0IG5ld19tYXAgPSBPYmplY3QuYXNzaWduKHt9LCBtYXApO1xuXG4gIGRlbGV0ZSBuZXdfbWFwW2tleV07XG5cbiAgcmV0dXJuIFNwZWNpYWxGb3Jtcy5tYXAobmV3X21hcCk7XG59XG5cbmZ1bmN0aW9uIGVxdWFsX19xbWFya19fKG1hcDEsIG1hcDIpIHtcbiAgcmV0dXJuIG1hcDEgPT09IG1hcDI7XG59XG5cbmZ1bmN0aW9uIGZldGNoX19lbWFya19fKG1hcCwga2V5KSB7XG4gIGlmIChrZXkgaW4gbWFwKSB7XG4gICAgcmV0dXJuIG1hcFtrZXldO1xuICB9XG5cbiAgdGhyb3cgbmV3IEVycm9yKFwiS2V5IG5vdCBmb3VuZC5cIik7XG59XG5cbmZ1bmN0aW9uIGZldGNoKG1hcCwga2V5KSB7XG4gIGlmIChrZXkgaW4gbWFwKSB7XG4gICAgcmV0dXJuIFNwZWNpYWxGb3Jtcy50dXBsZShTcGVjaWFsRm9ybXMuYXRvbShcIm9rXCIpLCBtYXBba2V5XSk7XG4gIH1cblxuICByZXR1cm4gU3BlY2lhbEZvcm1zLmF0b20oXCJlcnJvclwiKTtcbn1cblxuZnVuY3Rpb24gaGFzX2tleV9fcW1hcmtfXyhtYXAsIGtleSkge1xuICByZXR1cm4ga2V5IGluIG1hcDtcbn1cblxuZnVuY3Rpb24gc3BsaXQkMShtYXAsIGtleXMpIHtcbiAgbGV0IHNwbGl0MSA9IHt9O1xuICBsZXQgc3BsaXQyID0ge307XG5cbiAgZm9yIChsZXQga2V5IG9mIE9iamVjdC5rZXlzKG1hcCkpIHtcbiAgICBpZiAoa2V5cy5pbmRleE9mKGtleSkgPiAtMSkge1xuICAgICAgc3BsaXQxW2tleV0gPSBtYXBba2V5XTtcbiAgICB9IGVsc2Uge1xuICAgICAgc3BsaXQyW2tleV0gPSBtYXBba2V5XTtcbiAgICB9XG4gIH1cblxuICByZXR1cm4gU3BlY2lhbEZvcm1zLnR1cGxlKFNwZWNpYWxGb3Jtcy5tYXAoc3BsaXQxKSwgU3BlY2lhbEZvcm1zLm1hcChzcGxpdDIpKTtcbn1cblxuZnVuY3Rpb24gdGFrZShtYXAsIGtleXMpIHtcbiAgbGV0IHNwbGl0MSA9IHt9O1xuXG4gIGZvciAobGV0IGtleSBvZiBPYmplY3Qua2V5cyhtYXApKSB7XG4gICAgaWYgKGtleXMuaW5kZXhPZihrZXkpID4gLTEpIHtcbiAgICAgIHNwbGl0MVtrZXldID0gbWFwW2tleV07XG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIFNwZWNpYWxGb3Jtcy5tYXAoc3BsaXQxKTtcbn1cblxuZnVuY3Rpb24gZHJvcChtYXAsIGtleXMpIHtcbiAgbGV0IHNwbGl0MSA9IHt9O1xuXG4gIGZvciAobGV0IGtleSBvZiBPYmplY3Qua2V5cyhtYXApKSB7XG4gICAgaWYgKGtleXMuaW5kZXhPZihrZXkpID09PSAtMSkge1xuICAgICAgc3BsaXQxW2tleV0gPSBtYXBba2V5XTtcbiAgICB9XG4gIH1cblxuICByZXR1cm4gU3BlY2lhbEZvcm1zLm1hcChzcGxpdDEpO1xufVxuXG5mdW5jdGlvbiBwdXRfbmV3KG1hcCwga2V5LCB2YWx1ZSkge1xuICBpZiAoa2V5IGluIG1hcCkge1xuICAgIHJldHVybiBtYXA7XG4gIH1cblxuICBsZXQgbmV3X21hcCA9IE9iamVjdC5hc3NpZ24oe30sIG1hcCk7XG4gIG5ld19tYXBba2V5XSA9IHZhbHVlO1xuXG4gIHJldHVybiBTcGVjaWFsRm9ybXMubWFwKG5ld19tYXApO1xufVxuXG5mdW5jdGlvbiBwdXRfbmV3X2xhenkobWFwLCBrZXksIGZ1bikge1xuICBpZiAoa2V5IGluIG1hcCkge1xuICAgIHJldHVybiBtYXA7XG4gIH1cblxuICBsZXQgbmV3X21hcCA9IE9iamVjdC5hc3NpZ24oe30sIG1hcCk7XG4gIG5ld19tYXBba2V5XSA9IGZ1bigpO1xuXG4gIHJldHVybiBTcGVjaWFsRm9ybXMubWFwKG5ld19tYXApO1xufVxuXG5mdW5jdGlvbiBnZXRfYW5kX3VwZGF0ZShtYXAsIGtleSwgZnVuKSB7XG4gIGlmIChrZXkgaW4gbWFwKSB7XG4gICAgcmV0dXJuIG1hcDtcbiAgfVxuXG4gIGxldCBuZXdfbWFwID0gT2JqZWN0LmFzc2lnbih7fSwgbWFwKTtcbiAgbmV3X21hcFtrZXldID0gZnVuKG1hcFtrZXldKTtcblxuICByZXR1cm4gU3BlY2lhbEZvcm1zLm1hcChuZXdfbWFwKTtcbn1cblxuZnVuY3Rpb24gcG9wX2xhenkobWFwLCBrZXksIGZ1bikge1xuICBpZiAoIWtleSBpbiBtYXApIHtcbiAgICByZXR1cm4gU3BlY2lhbEZvcm1zLnR1cGxlKGZ1bigpLCBtYXApO1xuICB9XG5cbiAgbGV0IG5ld19tYXAgPSBPYmplY3QuYXNzaWduKHt9LCBtYXApO1xuICBsZXQgdmFsdWUgPSBmdW4obmV3X21hcFtrZXldKTtcbiAgZGVsZXRlIG5ld19tYXBba2V5XTtcblxuICByZXR1cm4gU3BlY2lhbEZvcm1zLnR1cGxlKHZhbHVlLCBuZXdfbWFwKTtcbn1cblxuZnVuY3Rpb24gcG9wKG1hcCwga2V5LCBfZGVmYXVsdCA9IG51bGwpIHtcbiAgaWYgKCFrZXkgaW4gbWFwKSB7XG4gICAgcmV0dXJuIFNwZWNpYWxGb3Jtcy50dXBsZShfZGVmYXVsdCwgbWFwKTtcbiAgfVxuXG4gIGxldCBuZXdfbWFwID0gT2JqZWN0LmFzc2lnbih7fSwgbWFwKTtcbiAgbGV0IHZhbHVlID0gbmV3X21hcFtrZXldO1xuICBkZWxldGUgbmV3X21hcFtrZXldO1xuXG4gIHJldHVybiBTcGVjaWFsRm9ybXMudHVwbGUodmFsdWUsIG5ld19tYXApO1xufVxuXG5mdW5jdGlvbiBnZXRfbGF6eShtYXAsIGtleSwgZnVuKSB7XG4gIGlmICgha2V5IGluIG1hcCkge1xuICAgIHJldHVybiBmdW4oKTtcbiAgfVxuXG4gIHJldHVybiBmdW4obWFwW2tleV0pO1xufVxuXG5mdW5jdGlvbiBnZXQobWFwLCBrZXksIF9kZWZhdWx0ID0gbnVsbCkge1xuICBpZiAoIWtleSBpbiBtYXApIHtcbiAgICByZXR1cm4gX2RlZmF1bHQ7XG4gIH1cblxuICByZXR1cm4gbWFwW2tleV07XG59XG5cbmZ1bmN0aW9uIHB1dChtYXAsIGtleSwgdmFsKSB7XG4gIGxldCBuZXdfbWFwID0gT2JqZWN0KHt9LCBtYXApO1xuICBuZXdfbWFwW2tleV0gPSB2YWw7XG5cbiAgcmV0dXJuIFNwZWNpYWxGb3Jtcy5tYXAobmV3X21hcCk7XG59XG5cbmZ1bmN0aW9uIHVwZGF0ZV9fZW1hcmtfXyhtYXAsIGtleSwgZnVuKSB7XG4gIGlmICgha2V5IGluIG1hcCkge1xuICAgIHRocm93IG5ldyBFcnJvcihcIktleSBub3QgZm91bmRcIik7XG4gIH1cblxuICBsZXQgbmV3X21hcCA9IE9iamVjdCh7fSwgbWFwKTtcbiAgbmV3X21hcFtrZXldID0gZnVuKG1hcFtrZXldKTtcblxuICByZXR1cm4gU3BlY2lhbEZvcm1zLm1hcChuZXdfbWFwKTtcbn1cblxuZnVuY3Rpb24gdXBkYXRlKG1hcCwga2V5LCBpbml0aWFsLCBmdW4pIHtcbiAgbGV0IG5ld19tYXAgPSBPYmplY3Qoe30sIG1hcCk7XG5cbiAgaWYgKCFrZXkgaW4gbWFwKSB7XG4gICAgbmV3X21hcFtrZXldID0gaW5pdGlhbDtcbiAgfSBlbHNlIHtcbiAgICBuZXdfbWFwW2tleV0gPSBmdW4obWFwW2tleV0pO1xuICB9XG5cbiAgcmV0dXJuIFNwZWNpYWxGb3Jtcy5tYXAobmV3X21hcCk7XG59XG5cbnZhciBtYXAgPSB7XG4gIG5ldzogX19uZXdfXyxcbiAga2V5cyxcbiAgc2l6ZSxcbiAgdG9fbGlzdDogdG9fbGlzdCQxLFxuICB2YWx1ZXMsXG4gIGZyb21fc3RydWN0LFxuICBkZWxldGU6IF9fZGVsZXRlX18sXG4gIGRyb3AsXG4gIGVxdWFsX19xbWFya19fLFxuICBmZXRjaF9fZW1hcmtfXyxcbiAgZmV0Y2gsXG4gIGhhc19rZXlfX3FtYXJrX18sXG4gIHNwbGl0OiBzcGxpdCQxLFxuICB0YWtlLFxuICBwdXRfbmV3LFxuICBwdXRfbmV3X2xhenksXG4gIGdldF9hbmRfdXBkYXRlLFxuICBwb3BfbGF6eSxcbiAgcG9wLFxuICBnZXRfbGF6eSxcbiAgZ2V0LFxuICBwdXQsXG4gIHVwZGF0ZV9fZW1hcmtfXyxcbiAgdXBkYXRlXG59O1xuXG5mdW5jdGlvbiBfX25ld19fJDEoKSB7XG4gIHJldHVybiBTcGVjaWFsRm9ybXMubWFwKHsgW1N5bWJvbC5mb3IoJ19fc3RydWN0X18nKV06IFN5bWJvbC5mb3IoJ01hcFNldCcpLCBzZXQ6IFNwZWNpYWxGb3Jtcy5saXN0KCkgfSk7XG59XG5cbmZ1bmN0aW9uIHNpemUkMihtYXApIHtcbiAgcmV0dXJuIG1hcC5zZXQubGVuZ3RoO1xufVxuXG5mdW5jdGlvbiB0b19saXN0JDMobWFwKSB7XG4gIHJldHVybiBtYXAuc2V0O1xufVxuXG5mdW5jdGlvbiBfX2RlbGV0ZV9fJDIoc2V0LCB0ZXJtKSB7XG4gIGxldCBuZXdfbGlzdCA9IExpc3QuZGVsZXRlKHNldC5zZXQsIHRlcm0pO1xuXG4gIGxldCBuZXdfbWFwID0gT2JqZWN0LmFzc2lnbih7fSwgc2V0KTtcbiAgbmV3X21hcC5zZXQgPSBuZXdfbGlzdDtcbiAgcmV0dXJuIFNwZWNpYWxGb3Jtcy5tYXAobmV3X21hcCk7XG59XG5cbmZ1bmN0aW9uIHB1dCQyKHNldCwgdGVybSkge1xuICBpZiAoc2V0LnNldC5pbmRleE9mKHRlcm0pID09PSAtMSkge1xuICAgIGxldCBuZXdfbGlzdCA9IExpc3QuYXBwZW5kKHNldC5zZXQsIHRlcm0pO1xuXG4gICAgbGV0IG5ld19tYXAgPSBPYmplY3QuYXNzaWduKHt9LCBzZXQpO1xuICAgIG5ld19tYXAuc2V0ID0gbmV3X2xpc3Q7XG4gICAgcmV0dXJuIFNwZWNpYWxGb3Jtcy5tYXAobmV3X21hcCk7XG4gIH1cblxuICByZXR1cm4gc2V0O1xufVxuXG5mdW5jdGlvbiBkaWZmZXJlbmNlJDEoc2V0MSwgc2V0Mikge1xuICBsZXQgbmV3X21hcCA9IE9iamVjdC5hc3NpZ24oe30sIHNldDEpO1xuXG4gIGZvciAobGV0IHZhbCBvZiBzZXQxLnNldCkge1xuICAgIGlmIChtZW1iZXJfX3FtYXJrX18kMShzZXQyLCB2YWwpKSB7XG4gICAgICBuZXdfbWFwLnNldCA9IExpc3QuZGVsZXRlKG5ld19tYXAuc2V0LCB2YWwpO1xuICAgIH1cbiAgfVxuXG4gIHJldHVybiBTcGVjaWFsRm9ybXMubWFwKG5ld19tYXApO1xufVxuXG5mdW5jdGlvbiBpbnRlcnNlY3Rpb24kMShzZXQxLCBzZXQyKSB7XG4gIGxldCBuZXdfbWFwID0gT2JqZWN0LmFzc2lnbih7fSwgc2V0MSk7XG5cbiAgZm9yIChsZXQgdmFsIG9mIHNldDEuc2V0KSB7XG4gICAgaWYgKCFtZW1iZXJfX3FtYXJrX18kMShzZXQyLCB2YWwpKSB7XG4gICAgICBuZXdfbWFwLnNldCA9IExpc3QuZGVsZXRlKG5ld19tYXAuc2V0LCB2YWwpO1xuICAgIH1cbiAgfVxuXG4gIHJldHVybiBTcGVjaWFsRm9ybXMubWFwKG5ld19tYXApO1xufVxuXG5mdW5jdGlvbiB1bmlvbiQxKHNldDEsIHNldDIpIHtcbiAgbGV0IG5ld19tYXAgPSBzZXQxO1xuXG4gIGZvciAobGV0IHZhbCBvZiBzZXQyLnNldCkge1xuICAgIG5ld19tYXAgPSBwdXQkMihuZXdfbWFwLCB2YWwpO1xuICB9XG5cbiAgcmV0dXJuIFNwZWNpYWxGb3Jtcy5tYXAobmV3X21hcCk7XG59XG5cbmZ1bmN0aW9uIGRpc2pvaW5fX3FtYXJrX18kMShzZXQxLCBzZXQyKSB7XG4gIGZvciAobGV0IHZhbCBvZiBzZXQxLnNldCkge1xuICAgIGlmIChtZW1iZXJfX3FtYXJrX18kMShzZXQyLCB2YWwpKSB7XG4gICAgICByZXR1cm4gZmFsc2U7XG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIHRydWU7XG59XG5cbmZ1bmN0aW9uIG1lbWJlcl9fcW1hcmtfXyQxKHNldCwgdmFsdWUpIHtcbiAgcmV0dXJuIHNldC5zZXQuaW5kZXhPZih2YWx1ZSkgPj0gMDtcbn1cblxuZnVuY3Rpb24gZXF1YWxfX3FtYXJrX18kMihzZXQxLCBzZXQyKSB7XG4gIHJldHVybiBzZXQxLnNldCA9PT0gc2V0Mi5zZXQ7XG59XG5cbmZ1bmN0aW9uIHN1YnNldF9fcW1hcmtfXyQxKHNldDEsIHNldDIpIHtcbiAgZm9yIChsZXQgdmFsIG9mIHNldDEuc2V0KSB7XG4gICAgaWYgKCFtZW1iZXJfX3FtYXJrX18kMShzZXQyLCB2YWwpKSB7XG4gICAgICByZXR1cm4gZmFsc2U7XG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIHRydWU7XG59XG5cbnZhciBNYXBTZXQgPSB7XG4gIG5ldzogX19uZXdfXyQxLFxuICBzaXplOiBzaXplJDIsXG4gIHRvX2xpc3Q6IHRvX2xpc3QkMyxcbiAgZGlzam9pbl9fcW1hcmtfXzogZGlzam9pbl9fcW1hcmtfXyQxLFxuICBkZWxldGU6IF9fZGVsZXRlX18kMixcbiAgc3Vic2V0X19xbWFya19fOiBzdWJzZXRfX3FtYXJrX18kMSxcbiAgZXF1YWxfX3FtYXJrX186IGVxdWFsX19xbWFya19fJDIsXG4gIG1lbWJlcl9fcW1hcmtfXzogbWVtYmVyX19xbWFya19fJDEsXG4gIHB1dDogcHV0JDIsXG4gIHVuaW9uOiB1bmlvbiQxLFxuICBpbnRlcnNlY3Rpb246IGludGVyc2VjdGlvbiQxLFxuICBkaWZmZXJlbmNlOiBkaWZmZXJlbmNlJDFcbn07XG5cbmZ1bmN0aW9uIHNpemUkMShtYXApIHtcbiAgcmV0dXJuIE1hcFNldC5zaXplKG1hcCk7XG59XG5cbmZ1bmN0aW9uIHRvX2xpc3QkMihtYXApIHtcbiAgcmV0dXJuIE1hcFNldC50b19saXN0KG1hcCk7XG59XG5cbmZ1bmN0aW9uIF9fZGVsZXRlX18kMShzZXQsIHRlcm0pIHtcbiAgcmV0dXJuIE1hcFNldC5kZWxldGUoc2V0LCB0ZXJtKTtcbn1cblxuZnVuY3Rpb24gcHV0JDEoc2V0LCB0ZXJtKSB7XG4gIHJldHVybiBNYXBTZXQucHV0KHNldCwgdGVybSk7XG59XG5cbmZ1bmN0aW9uIGRpZmZlcmVuY2Uoc2V0MSwgc2V0Mikge1xuICByZXR1cm4gTWFwU2V0LmRpZmZlcmVuY2Uoc2V0MSwgc2V0Mik7XG59XG5cbmZ1bmN0aW9uIGludGVyc2VjdGlvbihzZXQxLCBzZXQyKSB7XG4gIHJldHVybiBNYXBTZXQuaW50ZXJzZWN0aW9uKHNldDEsIHNldDIpO1xufVxuXG5mdW5jdGlvbiB1bmlvbihzZXQxLCBzZXQyKSB7XG4gIHJldHVybiBNYXBTZXQudW5pb24oc2V0MSwgc2V0Mik7XG59XG5cbmZ1bmN0aW9uIGRpc2pvaW5fX3FtYXJrX18oc2V0MSwgc2V0Mikge1xuICByZXR1cm4gTWFwU2V0LmRpc2pvaW5fX3FtYXJrX18oc2V0MSwgc2V0Mik7XG59XG5cbmZ1bmN0aW9uIG1lbWJlcl9fcW1hcmtfXyhzZXQsIHZhbHVlKSB7XG4gIHJldHVybiBNYXBTZXQubWVtYmVyX19xbWFya19fKHNldDEsIHNldDIpO1xufVxuXG5mdW5jdGlvbiBlcXVhbF9fcW1hcmtfXyQxKHNldDEsIHNldDIpIHtcbiAgcmV0dXJuIE1hcFNldC5lcXVhbF9fcW1hcmtfXyhzZXQxLCBzZXQyKTtcbn1cblxuZnVuY3Rpb24gc3Vic2V0X19xbWFya19fKHNldDEsIHNldDIpIHtcbiAgcmV0dXJuIE1hcFNldC5zdWJzZXRfX3FtYXJrX18oc2V0MSwgc2V0Mik7XG59XG5cbnZhciBzZXQgPSB7XG4gIHNpemU6IHNpemUkMSxcbiAgdG9fbGlzdDogdG9fbGlzdCQyLFxuICBkaXNqb2luX19xbWFya19fLFxuICBkZWxldGU6IF9fZGVsZXRlX18kMSxcbiAgc3Vic2V0X19xbWFya19fLFxuICBlcXVhbF9fcW1hcmtfXzogZXF1YWxfX3FtYXJrX18kMSxcbiAgbWVtYmVyX19xbWFya19fLFxuICBwdXQ6IHB1dCQxLFxuICB1bmlvbixcbiAgaW50ZXJzZWN0aW9uLFxuICBkaWZmZXJlbmNlXG59O1xuXG5sZXQgVmlydHVhbERPTSA9IChmdW5jdGlvbiAoZSkge1xuICAgIHJldHVybiBlKCk7XG59KShmdW5jdGlvbiAoKSB7XG4gICAgdmFyIGRlZmluZSwgbW9kdWxlLCBleHBvcnRzO1xuICAgIHJldHVybiAoZnVuY3Rpb24gZSh0LCBuLCByKSB7XG4gICAgICAgIGZ1bmN0aW9uIHMobywgdSkge1xuICAgICAgICAgICAgaWYgKCFuW29dKSB7XG4gICAgICAgICAgICAgICAgaWYgKCF0W29dKSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciBhID0gdHlwZW9mIHJlcXVpcmUgPT0gXCJmdW5jdGlvblwiICYmIHJlcXVpcmU7XG4gICAgICAgICAgICAgICAgICAgIGlmICghdSAmJiBhKSByZXR1cm4gYShvLCAhMCk7XG4gICAgICAgICAgICAgICAgICAgIGlmIChpKSByZXR1cm4gaShvLCAhMCk7XG4gICAgICAgICAgICAgICAgICAgIHZhciBmID0gbmV3IEVycm9yKFwiQ2Fubm90IGZpbmQgbW9kdWxlICdcIiArIG8gKyBcIidcIik7XG4gICAgICAgICAgICAgICAgICAgIHRocm93IChmLmNvZGUgPSBcIk1PRFVMRV9OT1RfRk9VTkRcIiwgZik7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHZhciBsID0gbltvXSA9IHtcbiAgICAgICAgICAgICAgICAgICAgZXhwb3J0czoge31cbiAgICAgICAgICAgICAgICB9O1xuICAgICAgICAgICAgICAgIHRbb11bMF0uY2FsbChsLmV4cG9ydHMsIGZ1bmN0aW9uIChlKSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciBuID0gdFtvXVsxXVtlXTtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHMobiA/IG4gOiBlKTtcbiAgICAgICAgICAgICAgICB9LCBsLCBsLmV4cG9ydHMsIGUsIHQsIG4sIHIpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmV0dXJuIG5bb10uZXhwb3J0cztcbiAgICAgICAgfVxuICAgICAgICB2YXIgaSA9IHR5cGVvZiByZXF1aXJlID09IFwiZnVuY3Rpb25cIiAmJiByZXF1aXJlO1xuICAgICAgICBmb3IgKHZhciBvID0gMDsgbyA8IHIubGVuZ3RoOyBvKyspIHMocltvXSk7XG4gICAgICAgIHJldHVybiBzO1xuICAgIH0pKHtcbiAgICAgICAgMTogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHtcblxuICAgICAgICAgICAgdmFyIGNyZWF0ZUVsZW1lbnQgPSByZXF1aXJlKFwiLi92ZG9tL2NyZWF0ZS1lbGVtZW50LmpzXCIpO1xuXG4gICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IGNyZWF0ZUVsZW1lbnQ7XG4gICAgICAgIH0sIHsgXCIuL3Zkb20vY3JlYXRlLWVsZW1lbnQuanNcIjogMTUgfV0sIDI6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICB2YXIgZGlmZiA9IHJlcXVpcmUoXCIuL3Z0cmVlL2RpZmYuanNcIik7XG5cbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gZGlmZjtcbiAgICAgICAgfSwgeyBcIi4vdnRyZWUvZGlmZi5qc1wiOiAzNSB9XSwgMzogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHtcbiAgICAgICAgICAgIHZhciBoID0gcmVxdWlyZShcIi4vdmlydHVhbC1oeXBlcnNjcmlwdC9pbmRleC5qc1wiKTtcblxuICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBoO1xuICAgICAgICB9LCB7IFwiLi92aXJ0dWFsLWh5cGVyc2NyaXB0L2luZGV4LmpzXCI6IDIyIH1dLCA0OiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge1xuICAgICAgICAgICAgdmFyIGRpZmYgPSByZXF1aXJlKFwiLi9kaWZmLmpzXCIpO1xuICAgICAgICAgICAgdmFyIHBhdGNoID0gcmVxdWlyZShcIi4vcGF0Y2guanNcIik7XG4gICAgICAgICAgICB2YXIgaCA9IHJlcXVpcmUoXCIuL2guanNcIik7XG4gICAgICAgICAgICB2YXIgY3JlYXRlID0gcmVxdWlyZShcIi4vY3JlYXRlLWVsZW1lbnQuanNcIik7XG4gICAgICAgICAgICB2YXIgVk5vZGUgPSByZXF1aXJlKFwiLi92bm9kZS92bm9kZS5qc1wiKTtcbiAgICAgICAgICAgIHZhciBWVGV4dCA9IHJlcXVpcmUoXCIuL3Zub2RlL3Z0ZXh0LmpzXCIpO1xuXG4gICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IHtcbiAgICAgICAgICAgICAgICBkaWZmOiBkaWZmLFxuICAgICAgICAgICAgICAgIHBhdGNoOiBwYXRjaCxcbiAgICAgICAgICAgICAgICBoOiBoLFxuICAgICAgICAgICAgICAgIGNyZWF0ZTogY3JlYXRlLFxuICAgICAgICAgICAgICAgIFZOb2RlOiBWTm9kZSxcbiAgICAgICAgICAgICAgICBWVGV4dDogVlRleHRcbiAgICAgICAgICAgIH07XG4gICAgICAgIH0sIHsgXCIuL2NyZWF0ZS1lbGVtZW50LmpzXCI6IDEsIFwiLi9kaWZmLmpzXCI6IDIsIFwiLi9oLmpzXCI6IDMsIFwiLi9wYXRjaC5qc1wiOiAxMywgXCIuL3Zub2RlL3Zub2RlLmpzXCI6IDMxLCBcIi4vdm5vZGUvdnRleHQuanNcIjogMzMgfV0sIDU6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICAvKiFcbiAgICAgICAgICAgICAqIENyb3NzLUJyb3dzZXIgU3BsaXQgMS4xLjFcbiAgICAgICAgICAgICAqIENvcHlyaWdodCAyMDA3LTIwMTIgU3RldmVuIExldml0aGFuIDxzdGV2ZW5sZXZpdGhhbi5jb20+XG4gICAgICAgICAgICAgKiBBdmFpbGFibGUgdW5kZXIgdGhlIE1JVCBMaWNlbnNlXG4gICAgICAgICAgICAgKiBFQ01BU2NyaXB0IGNvbXBsaWFudCwgdW5pZm9ybSBjcm9zcy1icm93c2VyIHNwbGl0IG1ldGhvZFxuICAgICAgICAgICAgICovXG5cbiAgICAgICAgICAgIC8qKlxuICAgICAgICAgICAgICogU3BsaXRzIGEgc3RyaW5nIGludG8gYW4gYXJyYXkgb2Ygc3RyaW5ncyB1c2luZyBhIHJlZ2V4IG9yIHN0cmluZyBzZXBhcmF0b3IuIE1hdGNoZXMgb2YgdGhlXG4gICAgICAgICAgICAgKiBzZXBhcmF0b3IgYXJlIG5vdCBpbmNsdWRlZCBpbiB0aGUgcmVzdWx0IGFycmF5LiBIb3dldmVyLCBpZiBgc2VwYXJhdG9yYCBpcyBhIHJlZ2V4IHRoYXQgY29udGFpbnNcbiAgICAgICAgICAgICAqIGNhcHR1cmluZyBncm91cHMsIGJhY2tyZWZlcmVuY2VzIGFyZSBzcGxpY2VkIGludG8gdGhlIHJlc3VsdCBlYWNoIHRpbWUgYHNlcGFyYXRvcmAgaXMgbWF0Y2hlZC5cbiAgICAgICAgICAgICAqIEZpeGVzIGJyb3dzZXIgYnVncyBjb21wYXJlZCB0byB0aGUgbmF0aXZlIGBTdHJpbmcucHJvdG90eXBlLnNwbGl0YCBhbmQgY2FuIGJlIHVzZWQgcmVsaWFibHlcbiAgICAgICAgICAgICAqIGNyb3NzLWJyb3dzZXIuXG4gICAgICAgICAgICAgKiBAcGFyYW0ge1N0cmluZ30gc3RyIFN0cmluZyB0byBzcGxpdC5cbiAgICAgICAgICAgICAqIEBwYXJhbSB7UmVnRXhwfFN0cmluZ30gc2VwYXJhdG9yIFJlZ2V4IG9yIHN0cmluZyB0byB1c2UgZm9yIHNlcGFyYXRpbmcgdGhlIHN0cmluZy5cbiAgICAgICAgICAgICAqIEBwYXJhbSB7TnVtYmVyfSBbbGltaXRdIE1heGltdW0gbnVtYmVyIG9mIGl0ZW1zIHRvIGluY2x1ZGUgaW4gdGhlIHJlc3VsdCBhcnJheS5cbiAgICAgICAgICAgICAqIEByZXR1cm5zIHtBcnJheX0gQXJyYXkgb2Ygc3Vic3RyaW5ncy5cbiAgICAgICAgICAgICAqIEBleGFtcGxlXG4gICAgICAgICAgICAgKlxuICAgICAgICAgICAgICogLy8gQmFzaWMgdXNlXG4gICAgICAgICAgICAgKiBzcGxpdCgnYSBiIGMgZCcsICcgJyk7XG4gICAgICAgICAgICAgKiAvLyAtPiBbJ2EnLCAnYicsICdjJywgJ2QnXVxuICAgICAgICAgICAgICpcbiAgICAgICAgICAgICAqIC8vIFdpdGggbGltaXRcbiAgICAgICAgICAgICAqIHNwbGl0KCdhIGIgYyBkJywgJyAnLCAyKTtcbiAgICAgICAgICAgICAqIC8vIC0+IFsnYScsICdiJ11cbiAgICAgICAgICAgICAqXG4gICAgICAgICAgICAgKiAvLyBCYWNrcmVmZXJlbmNlcyBpbiByZXN1bHQgYXJyYXlcbiAgICAgICAgICAgICAqIHNwbGl0KCcuLndvcmQxIHdvcmQyLi4nLCAvKFthLXpdKykoXFxkKykvaSk7XG4gICAgICAgICAgICAgKiAvLyAtPiBbJy4uJywgJ3dvcmQnLCAnMScsICcgJywgJ3dvcmQnLCAnMicsICcuLiddXG4gICAgICAgICAgICAgKi9cbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gKGZ1bmN0aW9uIHNwbGl0KHVuZGVmKSB7XG5cbiAgICAgICAgICAgICAgICB2YXIgbmF0aXZlU3BsaXQgPSBTdHJpbmcucHJvdG90eXBlLnNwbGl0LFxuICAgICAgICAgICAgICAgICAgICBjb21wbGlhbnRFeGVjTnBjZyA9IC8oKT8/Ly5leGVjKFwiXCIpWzFdID09PSB1bmRlZixcblxuICAgICAgICAgICAgICAgIC8vIE5QQ0c6IG5vbnBhcnRpY2lwYXRpbmcgY2FwdHVyaW5nIGdyb3VwXG4gICAgICAgICAgICAgICAgc2VsZjtcblxuICAgICAgICAgICAgICAgIHNlbGYgPSBmdW5jdGlvbiAoc3RyLCBzZXBhcmF0b3IsIGxpbWl0KSB7XG4gICAgICAgICAgICAgICAgICAgIC8vIElmIGBzZXBhcmF0b3JgIGlzIG5vdCBhIHJlZ2V4LCB1c2UgYG5hdGl2ZVNwbGl0YFxuICAgICAgICAgICAgICAgICAgICBpZiAoT2JqZWN0LnByb3RvdHlwZS50b1N0cmluZy5jYWxsKHNlcGFyYXRvcikgIT09IFwiW29iamVjdCBSZWdFeHBdXCIpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBuYXRpdmVTcGxpdC5jYWxsKHN0ciwgc2VwYXJhdG9yLCBsaW1pdCk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgdmFyIG91dHB1dCA9IFtdLFxuICAgICAgICAgICAgICAgICAgICAgICAgZmxhZ3MgPSAoc2VwYXJhdG9yLmlnbm9yZUNhc2UgPyBcImlcIiA6IFwiXCIpICsgKHNlcGFyYXRvci5tdWx0aWxpbmUgPyBcIm1cIiA6IFwiXCIpICsgKHNlcGFyYXRvci5leHRlbmRlZCA/IFwieFwiIDogXCJcIikgKyAoc2VwYXJhdG9yLnN0aWNreSA/IFwieVwiIDogXCJcIiksXG5cbiAgICAgICAgICAgICAgICAgICAgLy8gRmlyZWZveCAzK1xuICAgICAgICAgICAgICAgICAgICBsYXN0TGFzdEluZGV4ID0gMCxcblxuICAgICAgICAgICAgICAgICAgICAvLyBNYWtlIGBnbG9iYWxgIGFuZCBhdm9pZCBgbGFzdEluZGV4YCBpc3N1ZXMgYnkgd29ya2luZyB3aXRoIGEgY29weVxuICAgICAgICAgICAgICAgICAgICBzZXBhcmF0b3IgPSBuZXcgUmVnRXhwKHNlcGFyYXRvci5zb3VyY2UsIGZsYWdzICsgXCJnXCIpLFxuICAgICAgICAgICAgICAgICAgICAgICAgc2VwYXJhdG9yMixcbiAgICAgICAgICAgICAgICAgICAgICAgIG1hdGNoLFxuICAgICAgICAgICAgICAgICAgICAgICAgbGFzdEluZGV4LFxuICAgICAgICAgICAgICAgICAgICAgICAgbGFzdExlbmd0aDtcbiAgICAgICAgICAgICAgICAgICAgc3RyICs9IFwiXCI7IC8vIFR5cGUtY29udmVydFxuICAgICAgICAgICAgICAgICAgICBpZiAoIWNvbXBsaWFudEV4ZWNOcGNnKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAvLyBEb2Vzbid0IG5lZWQgZmxhZ3MgZ3ksIGJ1dCB0aGV5IGRvbid0IGh1cnRcbiAgICAgICAgICAgICAgICAgICAgICAgIHNlcGFyYXRvcjIgPSBuZXcgUmVnRXhwKFwiXlwiICsgc2VwYXJhdG9yLnNvdXJjZSArIFwiJCg/IVxcXFxzKVwiLCBmbGFncyk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgLyogVmFsdWVzIGZvciBgbGltaXRgLCBwZXIgdGhlIHNwZWM6XG4gICAgICAgICAgICAgICAgICAgICAqIElmIHVuZGVmaW5lZDogNDI5NDk2NzI5NSAvLyBNYXRoLnBvdygyLCAzMikgLSAxXG4gICAgICAgICAgICAgICAgICAgICAqIElmIDAsIEluZmluaXR5LCBvciBOYU46IDBcbiAgICAgICAgICAgICAgICAgICAgICogSWYgcG9zaXRpdmUgbnVtYmVyOiBsaW1pdCA9IE1hdGguZmxvb3IobGltaXQpOyBpZiAobGltaXQgPiA0Mjk0OTY3Mjk1KSBsaW1pdCAtPSA0Mjk0OTY3Mjk2O1xuICAgICAgICAgICAgICAgICAgICAgKiBJZiBuZWdhdGl2ZSBudW1iZXI6IDQyOTQ5NjcyOTYgLSBNYXRoLmZsb29yKE1hdGguYWJzKGxpbWl0KSlcbiAgICAgICAgICAgICAgICAgICAgICogSWYgb3RoZXI6IFR5cGUtY29udmVydCwgdGhlbiB1c2UgdGhlIGFib3ZlIHJ1bGVzXG4gICAgICAgICAgICAgICAgICAgICAqL1xuICAgICAgICAgICAgICAgICAgICBsaW1pdCA9IGxpbWl0ID09PSB1bmRlZiA/IC0xID4+PiAwIDogLy8gTWF0aC5wb3coMiwgMzIpIC0gMVxuICAgICAgICAgICAgICAgICAgICBsaW1pdCA+Pj4gMDsgLy8gVG9VaW50MzIobGltaXQpXG4gICAgICAgICAgICAgICAgICAgIHdoaWxlIChtYXRjaCA9IHNlcGFyYXRvci5leGVjKHN0cikpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIGBzZXBhcmF0b3IubGFzdEluZGV4YCBpcyBub3QgcmVsaWFibGUgY3Jvc3MtYnJvd3NlclxuICAgICAgICAgICAgICAgICAgICAgICAgbGFzdEluZGV4ID0gbWF0Y2guaW5kZXggKyBtYXRjaFswXS5sZW5ndGg7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAobGFzdEluZGV4ID4gbGFzdExhc3RJbmRleCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIG91dHB1dC5wdXNoKHN0ci5zbGljZShsYXN0TGFzdEluZGV4LCBtYXRjaC5pbmRleCkpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIEZpeCBicm93c2VycyB3aG9zZSBgZXhlY2AgbWV0aG9kcyBkb24ndCBjb25zaXN0ZW50bHkgcmV0dXJuIGB1bmRlZmluZWRgIGZvclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIG5vbnBhcnRpY2lwYXRpbmcgY2FwdHVyaW5nIGdyb3Vwc1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmICghY29tcGxpYW50RXhlY05wY2cgJiYgbWF0Y2gubGVuZ3RoID4gMSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBtYXRjaFswXS5yZXBsYWNlKHNlcGFyYXRvcjIsIGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZvciAodmFyIGkgPSAxOyBpIDwgYXJndW1lbnRzLmxlbmd0aCAtIDI7IGkrKykge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChhcmd1bWVudHNbaV0gPT09IHVuZGVmKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1hdGNoW2ldID0gdW5kZWY7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKG1hdGNoLmxlbmd0aCA+IDEgJiYgbWF0Y2guaW5kZXggPCBzdHIubGVuZ3RoKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIEFycmF5LnByb3RvdHlwZS5wdXNoLmFwcGx5KG91dHB1dCwgbWF0Y2guc2xpY2UoMSkpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBsYXN0TGVuZ3RoID0gbWF0Y2hbMF0ubGVuZ3RoO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxhc3RMYXN0SW5kZXggPSBsYXN0SW5kZXg7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKG91dHB1dC5sZW5ndGggPj0gbGltaXQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHNlcGFyYXRvci5sYXN0SW5kZXggPT09IG1hdGNoLmluZGV4KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgc2VwYXJhdG9yLmxhc3RJbmRleCsrOyAvLyBBdm9pZCBhbiBpbmZpbml0ZSBsb29wXG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgaWYgKGxhc3RMYXN0SW5kZXggPT09IHN0ci5sZW5ndGgpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChsYXN0TGVuZ3RoIHx8ICFzZXBhcmF0b3IudGVzdChcIlwiKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIG91dHB1dC5wdXNoKFwiXCIpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgb3V0cHV0LnB1c2goc3RyLnNsaWNlKGxhc3RMYXN0SW5kZXgpKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICByZXR1cm4gb3V0cHV0Lmxlbmd0aCA+IGxpbWl0ID8gb3V0cHV0LnNsaWNlKDAsIGxpbWl0KSA6IG91dHB1dDtcbiAgICAgICAgICAgICAgICB9O1xuXG4gICAgICAgICAgICAgICAgcmV0dXJuIHNlbGY7XG4gICAgICAgICAgICB9KSgpO1xuICAgICAgICB9LCB7fV0sIDY6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7fSwge31dLCA3OiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge1xuICAgICAgICAgICAgXCJ1c2Ugc3RyaWN0XCI7XG5cbiAgICAgICAgICAgIHZhciBPbmVWZXJzaW9uQ29uc3RyYWludCA9IHJlcXVpcmUoXCJpbmRpdmlkdWFsL29uZS12ZXJzaW9uXCIpO1xuXG4gICAgICAgICAgICB2YXIgTVlfVkVSU0lPTiA9IFwiN1wiO1xuICAgICAgICAgICAgT25lVmVyc2lvbkNvbnN0cmFpbnQoXCJldi1zdG9yZVwiLCBNWV9WRVJTSU9OKTtcblxuICAgICAgICAgICAgdmFyIGhhc2hLZXkgPSBcIl9fRVZfU1RPUkVfS0VZQFwiICsgTVlfVkVSU0lPTjtcblxuICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBFdlN0b3JlO1xuXG4gICAgICAgICAgICBmdW5jdGlvbiBFdlN0b3JlKGVsZW0pIHtcbiAgICAgICAgICAgICAgICB2YXIgaGFzaCA9IGVsZW1baGFzaEtleV07XG5cbiAgICAgICAgICAgICAgICBpZiAoIWhhc2gpIHtcbiAgICAgICAgICAgICAgICAgICAgaGFzaCA9IGVsZW1baGFzaEtleV0gPSB7fTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICByZXR1cm4gaGFzaDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSwgeyBcImluZGl2aWR1YWwvb25lLXZlcnNpb25cIjogOSB9XSwgODogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHtcbiAgICAgICAgICAgIChmdW5jdGlvbiAoZ2xvYmFsKSB7XG4gICAgICAgICAgICAgICAgXCJ1c2Ugc3RyaWN0XCI7XG5cbiAgICAgICAgICAgICAgICAvKmdsb2JhbCB3aW5kb3csIGdsb2JhbCovXG5cbiAgICAgICAgICAgICAgICB2YXIgcm9vdCA9IHR5cGVvZiB3aW5kb3cgIT09IFwidW5kZWZpbmVkXCIgPyB3aW5kb3cgOiB0eXBlb2YgZ2xvYmFsICE9PSBcInVuZGVmaW5lZFwiID8gZ2xvYmFsIDoge307XG5cbiAgICAgICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IEluZGl2aWR1YWw7XG5cbiAgICAgICAgICAgICAgICBmdW5jdGlvbiBJbmRpdmlkdWFsKGtleSwgdmFsdWUpIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKGtleSBpbiByb290KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gcm9vdFtrZXldO1xuICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgcm9vdFtrZXldID0gdmFsdWU7XG5cbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHZhbHVlO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0pLmNhbGwodGhpcywgdHlwZW9mIGdsb2JhbCAhPT0gXCJ1bmRlZmluZWRcIiA/IGdsb2JhbCA6IHR5cGVvZiBzZWxmICE9PSBcInVuZGVmaW5lZFwiID8gc2VsZiA6IHR5cGVvZiB3aW5kb3cgIT09IFwidW5kZWZpbmVkXCIgPyB3aW5kb3cgOiB7fSk7XG4gICAgICAgIH0sIHt9XSwgOTogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHtcbiAgICAgICAgICAgIFwidXNlIHN0cmljdFwiO1xuXG4gICAgICAgICAgICB2YXIgSW5kaXZpZHVhbCA9IHJlcXVpcmUoXCIuL2luZGV4LmpzXCIpO1xuXG4gICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IE9uZVZlcnNpb247XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIE9uZVZlcnNpb24obW9kdWxlTmFtZSwgdmVyc2lvbiwgZGVmYXVsdFZhbHVlKSB7XG4gICAgICAgICAgICAgICAgdmFyIGtleSA9IFwiX19JTkRJVklEVUFMX09ORV9WRVJTSU9OX1wiICsgbW9kdWxlTmFtZTtcbiAgICAgICAgICAgICAgICB2YXIgZW5mb3JjZUtleSA9IGtleSArIFwiX0VORk9SQ0VfU0lOR0xFVE9OXCI7XG5cbiAgICAgICAgICAgICAgICB2YXIgdmVyc2lvblZhbHVlID0gSW5kaXZpZHVhbChlbmZvcmNlS2V5LCB2ZXJzaW9uKTtcblxuICAgICAgICAgICAgICAgIGlmICh2ZXJzaW9uVmFsdWUgIT09IHZlcnNpb24pIHtcbiAgICAgICAgICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKFwiQ2FuIG9ubHkgaGF2ZSBvbmUgY29weSBvZiBcIiArIG1vZHVsZU5hbWUgKyBcIi5cXG5cIiArIFwiWW91IGFscmVhZHkgaGF2ZSB2ZXJzaW9uIFwiICsgdmVyc2lvblZhbHVlICsgXCIgaW5zdGFsbGVkLlxcblwiICsgXCJUaGlzIG1lYW5zIHlvdSBjYW5ub3QgaW5zdGFsbCB2ZXJzaW9uIFwiICsgdmVyc2lvbik7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgcmV0dXJuIEluZGl2aWR1YWwoa2V5LCBkZWZhdWx0VmFsdWUpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9LCB7IFwiLi9pbmRleC5qc1wiOiA4IH1dLCAxMDogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHtcbiAgICAgICAgICAgIChmdW5jdGlvbiAoZ2xvYmFsKSB7XG4gICAgICAgICAgICAgICAgdmFyIHRvcExldmVsID0gdHlwZW9mIGdsb2JhbCAhPT0gXCJ1bmRlZmluZWRcIiA/IGdsb2JhbCA6IHR5cGVvZiB3aW5kb3cgIT09IFwidW5kZWZpbmVkXCIgPyB3aW5kb3cgOiB7fTtcbiAgICAgICAgICAgICAgICB2YXIgbWluRG9jID0gcmVxdWlyZShcIm1pbi1kb2N1bWVudFwiKTtcblxuICAgICAgICAgICAgICAgIGlmICh0eXBlb2YgZG9jdW1lbnQgIT09IFwidW5kZWZpbmVkXCIpIHtcbiAgICAgICAgICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBkb2N1bWVudDtcbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICB2YXIgZG9jY3kgPSB0b3BMZXZlbFtcIl9fR0xPQkFMX0RPQ1VNRU5UX0NBQ0hFQDRcIl07XG5cbiAgICAgICAgICAgICAgICAgICAgaWYgKCFkb2NjeSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgZG9jY3kgPSB0b3BMZXZlbFtcIl9fR0xPQkFMX0RPQ1VNRU5UX0NBQ0hFQDRcIl0gPSBtaW5Eb2M7XG4gICAgICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IGRvY2N5O1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0pLmNhbGwodGhpcywgdHlwZW9mIGdsb2JhbCAhPT0gXCJ1bmRlZmluZWRcIiA/IGdsb2JhbCA6IHR5cGVvZiBzZWxmICE9PSBcInVuZGVmaW5lZFwiID8gc2VsZiA6IHR5cGVvZiB3aW5kb3cgIT09IFwidW5kZWZpbmVkXCIgPyB3aW5kb3cgOiB7fSk7XG4gICAgICAgIH0sIHsgXCJtaW4tZG9jdW1lbnRcIjogNiB9XSwgMTE6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICBcInVzZSBzdHJpY3RcIjtcblxuICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiBpc09iamVjdCh4KSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHR5cGVvZiB4ID09PSBcIm9iamVjdFwiICYmIHggIT09IG51bGw7XG4gICAgICAgICAgICB9O1xuICAgICAgICB9LCB7fV0sIDEyOiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge1xuICAgICAgICAgICAgdmFyIG5hdGl2ZUlzQXJyYXkgPSBBcnJheS5pc0FycmF5O1xuICAgICAgICAgICAgdmFyIHRvU3RyaW5nID0gT2JqZWN0LnByb3RvdHlwZS50b1N0cmluZztcblxuICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBuYXRpdmVJc0FycmF5IHx8IGlzQXJyYXk7XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIGlzQXJyYXkob2JqKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHRvU3RyaW5nLmNhbGwob2JqKSA9PT0gXCJbb2JqZWN0IEFycmF5XVwiO1xuICAgICAgICAgICAgfVxuICAgICAgICB9LCB7fV0sIDEzOiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge1xuICAgICAgICAgICAgdmFyIHBhdGNoID0gcmVxdWlyZShcIi4vdmRvbS9wYXRjaC5qc1wiKTtcblxuICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBwYXRjaDtcbiAgICAgICAgfSwgeyBcIi4vdmRvbS9wYXRjaC5qc1wiOiAxOCB9XSwgMTQ6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICB2YXIgaXNPYmplY3QgPSByZXF1aXJlKFwiaXMtb2JqZWN0XCIpO1xuICAgICAgICAgICAgdmFyIGlzSG9vayA9IHJlcXVpcmUoXCIuLi92bm9kZS9pcy12aG9vay5qc1wiKTtcblxuICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBhcHBseVByb3BlcnRpZXM7XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIGFwcGx5UHJvcGVydGllcyhub2RlLCBwcm9wcywgcHJldmlvdXMpIHtcbiAgICAgICAgICAgICAgICBmb3IgKHZhciBwcm9wTmFtZSBpbiBwcm9wcykge1xuICAgICAgICAgICAgICAgICAgICB2YXIgcHJvcFZhbHVlID0gcHJvcHNbcHJvcE5hbWVdO1xuXG4gICAgICAgICAgICAgICAgICAgIGlmIChwcm9wVmFsdWUgPT09IHVuZGVmaW5lZCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgcmVtb3ZlUHJvcGVydHkobm9kZSwgcHJvcE5hbWUsIHByb3BWYWx1ZSwgcHJldmlvdXMpO1xuICAgICAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKGlzSG9vayhwcm9wVmFsdWUpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICByZW1vdmVQcm9wZXJ0eShub2RlLCBwcm9wTmFtZSwgcHJvcFZhbHVlLCBwcmV2aW91cyk7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAocHJvcFZhbHVlLmhvb2spIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBwcm9wVmFsdWUuaG9vayhub2RlLCBwcm9wTmFtZSwgcHJldmlvdXMgPyBwcmV2aW91c1twcm9wTmFtZV0gOiB1bmRlZmluZWQpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGlzT2JqZWN0KHByb3BWYWx1ZSkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBwYXRjaE9iamVjdChub2RlLCBwcm9wcywgcHJldmlvdXMsIHByb3BOYW1lLCBwcm9wVmFsdWUpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBub2RlW3Byb3BOYW1lXSA9IHByb3BWYWx1ZTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZnVuY3Rpb24gcmVtb3ZlUHJvcGVydHkobm9kZSwgcHJvcE5hbWUsIHByb3BWYWx1ZSwgcHJldmlvdXMpIHtcbiAgICAgICAgICAgICAgICBpZiAocHJldmlvdXMpIHtcbiAgICAgICAgICAgICAgICAgICAgdmFyIHByZXZpb3VzVmFsdWUgPSBwcmV2aW91c1twcm9wTmFtZV07XG5cbiAgICAgICAgICAgICAgICAgICAgaWYgKCFpc0hvb2socHJldmlvdXNWYWx1ZSkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChwcm9wTmFtZSA9PT0gXCJhdHRyaWJ1dGVzXCIpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBmb3IgKHZhciBhdHRyTmFtZSBpbiBwcmV2aW91c1ZhbHVlKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG5vZGUucmVtb3ZlQXR0cmlidXRlKGF0dHJOYW1lKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKHByb3BOYW1lID09PSBcInN0eWxlXCIpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBmb3IgKHZhciBpIGluIHByZXZpb3VzVmFsdWUpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbm9kZS5zdHlsZVtpXSA9IFwiXCI7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIGlmICh0eXBlb2YgcHJldmlvdXNWYWx1ZSA9PT0gXCJzdHJpbmdcIikge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIG5vZGVbcHJvcE5hbWVdID0gXCJcIjtcbiAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgbm9kZVtwcm9wTmFtZV0gPSBudWxsO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKHByZXZpb3VzVmFsdWUudW5ob29rKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBwcmV2aW91c1ZhbHVlLnVuaG9vayhub2RlLCBwcm9wTmFtZSwgcHJvcFZhbHVlKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZnVuY3Rpb24gcGF0Y2hPYmplY3Qobm9kZSwgcHJvcHMsIHByZXZpb3VzLCBwcm9wTmFtZSwgcHJvcFZhbHVlKSB7XG4gICAgICAgICAgICAgICAgdmFyIHByZXZpb3VzVmFsdWUgPSBwcmV2aW91cyA/IHByZXZpb3VzW3Byb3BOYW1lXSA6IHVuZGVmaW5lZDtcblxuICAgICAgICAgICAgICAgIC8vIFNldCBhdHRyaWJ1dGVzXG4gICAgICAgICAgICAgICAgaWYgKHByb3BOYW1lID09PSBcImF0dHJpYnV0ZXNcIikge1xuICAgICAgICAgICAgICAgICAgICBmb3IgKHZhciBhdHRyTmFtZSBpbiBwcm9wVmFsdWUpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHZhciBhdHRyVmFsdWUgPSBwcm9wVmFsdWVbYXR0ck5hbWVdO1xuXG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoYXR0clZhbHVlID09PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBub2RlLnJlbW92ZUF0dHJpYnV0ZShhdHRyTmFtZSk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIG5vZGUuc2V0QXR0cmlidXRlKGF0dHJOYW1lLCBhdHRyVmFsdWUpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIGlmIChwcmV2aW91c1ZhbHVlICYmIGlzT2JqZWN0KHByZXZpb3VzVmFsdWUpICYmIGdldFByb3RvdHlwZShwcmV2aW91c1ZhbHVlKSAhPT0gZ2V0UHJvdG90eXBlKHByb3BWYWx1ZSkpIHtcbiAgICAgICAgICAgICAgICAgICAgbm9kZVtwcm9wTmFtZV0gPSBwcm9wVmFsdWU7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICBpZiAoIWlzT2JqZWN0KG5vZGVbcHJvcE5hbWVdKSkge1xuICAgICAgICAgICAgICAgICAgICBub2RlW3Byb3BOYW1lXSA9IHt9O1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHZhciByZXBsYWNlciA9IHByb3BOYW1lID09PSBcInN0eWxlXCIgPyBcIlwiIDogdW5kZWZpbmVkO1xuXG4gICAgICAgICAgICAgICAgZm9yICh2YXIgayBpbiBwcm9wVmFsdWUpIHtcbiAgICAgICAgICAgICAgICAgICAgdmFyIHZhbHVlID0gcHJvcFZhbHVlW2tdO1xuICAgICAgICAgICAgICAgICAgICBub2RlW3Byb3BOYW1lXVtrXSA9IHZhbHVlID09PSB1bmRlZmluZWQgPyByZXBsYWNlciA6IHZhbHVlO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZnVuY3Rpb24gZ2V0UHJvdG90eXBlKHZhbHVlKSB7XG4gICAgICAgICAgICAgICAgaWYgKE9iamVjdC5nZXRQcm90b3R5cGVPZikge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gT2JqZWN0LmdldFByb3RvdHlwZU9mKHZhbHVlKTtcbiAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKHZhbHVlLl9fcHJvdG9fXykge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gdmFsdWUuX19wcm90b19fO1xuICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAodmFsdWUuY29uc3RydWN0b3IpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHZhbHVlLmNvbnN0cnVjdG9yLnByb3RvdHlwZTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH0sIHsgXCIuLi92bm9kZS9pcy12aG9vay5qc1wiOiAyNiwgXCJpcy1vYmplY3RcIjogMTEgfV0sIDE1OiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge1xuICAgICAgICAgICAgdmFyIGRvY3VtZW50ID0gcmVxdWlyZShcImdsb2JhbC9kb2N1bWVudFwiKTtcblxuICAgICAgICAgICAgdmFyIGFwcGx5UHJvcGVydGllcyA9IHJlcXVpcmUoXCIuL2FwcGx5LXByb3BlcnRpZXNcIik7XG5cbiAgICAgICAgICAgIHZhciBpc1ZOb2RlID0gcmVxdWlyZShcIi4uL3Zub2RlL2lzLXZub2RlLmpzXCIpO1xuICAgICAgICAgICAgdmFyIGlzVlRleHQgPSByZXF1aXJlKFwiLi4vdm5vZGUvaXMtdnRleHQuanNcIik7XG4gICAgICAgICAgICB2YXIgaXNXaWRnZXQgPSByZXF1aXJlKFwiLi4vdm5vZGUvaXMtd2lkZ2V0LmpzXCIpO1xuICAgICAgICAgICAgdmFyIGhhbmRsZVRodW5rID0gcmVxdWlyZShcIi4uL3Zub2RlL2hhbmRsZS10aHVuay5qc1wiKTtcblxuICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBjcmVhdGVFbGVtZW50O1xuXG4gICAgICAgICAgICBmdW5jdGlvbiBjcmVhdGVFbGVtZW50KHZub2RlLCBvcHRzKSB7XG4gICAgICAgICAgICAgICAgdmFyIGRvYyA9IG9wdHMgPyBvcHRzLmRvY3VtZW50IHx8IGRvY3VtZW50IDogZG9jdW1lbnQ7XG4gICAgICAgICAgICAgICAgdmFyIHdhcm4gPSBvcHRzID8gb3B0cy53YXJuIDogbnVsbDtcblxuICAgICAgICAgICAgICAgIHZub2RlID0gaGFuZGxlVGh1bmsodm5vZGUpLmE7XG5cbiAgICAgICAgICAgICAgICBpZiAoaXNXaWRnZXQodm5vZGUpKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiB2bm9kZS5pbml0KCk7XG4gICAgICAgICAgICAgICAgfSBlbHNlIGlmIChpc1ZUZXh0KHZub2RlKSkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gZG9jLmNyZWF0ZVRleHROb2RlKHZub2RlLnRleHQpO1xuICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoIWlzVk5vZGUodm5vZGUpKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmICh3YXJuKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICB3YXJuKFwiSXRlbSBpcyBub3QgYSB2YWxpZCB2aXJ0dWFsIGRvbSBub2RlXCIsIHZub2RlKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICByZXR1cm4gbnVsbDtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICB2YXIgbm9kZSA9IHZub2RlLm5hbWVzcGFjZSA9PT0gbnVsbCA/IGRvYy5jcmVhdGVFbGVtZW50KHZub2RlLnRhZ05hbWUpIDogZG9jLmNyZWF0ZUVsZW1lbnROUyh2bm9kZS5uYW1lc3BhY2UsIHZub2RlLnRhZ05hbWUpO1xuXG4gICAgICAgICAgICAgICAgdmFyIHByb3BzID0gdm5vZGUucHJvcGVydGllcztcbiAgICAgICAgICAgICAgICBhcHBseVByb3BlcnRpZXMobm9kZSwgcHJvcHMpO1xuXG4gICAgICAgICAgICAgICAgdmFyIGNoaWxkcmVuID0gdm5vZGUuY2hpbGRyZW47XG5cbiAgICAgICAgICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IGNoaWxkcmVuLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciBjaGlsZE5vZGUgPSBjcmVhdGVFbGVtZW50KGNoaWxkcmVuW2ldLCBvcHRzKTtcbiAgICAgICAgICAgICAgICAgICAgaWYgKGNoaWxkTm9kZSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgbm9kZS5hcHBlbmRDaGlsZChjaGlsZE5vZGUpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgcmV0dXJuIG5vZGU7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0sIHsgXCIuLi92bm9kZS9oYW5kbGUtdGh1bmsuanNcIjogMjQsIFwiLi4vdm5vZGUvaXMtdm5vZGUuanNcIjogMjcsIFwiLi4vdm5vZGUvaXMtdnRleHQuanNcIjogMjgsIFwiLi4vdm5vZGUvaXMtd2lkZ2V0LmpzXCI6IDI5LCBcIi4vYXBwbHktcHJvcGVydGllc1wiOiAxNCwgXCJnbG9iYWwvZG9jdW1lbnRcIjogMTAgfV0sIDE2OiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge1xuICAgICAgICAgICAgLy8gTWFwcyBhIHZpcnR1YWwgRE9NIHRyZWUgb250byBhIHJlYWwgRE9NIHRyZWUgaW4gYW4gZWZmaWNpZW50IG1hbm5lci5cbiAgICAgICAgICAgIC8vIFdlIGRvbid0IHdhbnQgdG8gcmVhZCBhbGwgb2YgdGhlIERPTSBub2RlcyBpbiB0aGUgdHJlZSBzbyB3ZSB1c2VcbiAgICAgICAgICAgIC8vIHRoZSBpbi1vcmRlciB0cmVlIGluZGV4aW5nIHRvIGVsaW1pbmF0ZSByZWN1cnNpb24gZG93biBjZXJ0YWluIGJyYW5jaGVzLlxuICAgICAgICAgICAgLy8gV2Ugb25seSByZWN1cnNlIGludG8gYSBET00gbm9kZSBpZiB3ZSBrbm93IHRoYXQgaXQgY29udGFpbnMgYSBjaGlsZCBvZlxuICAgICAgICAgICAgLy8gaW50ZXJlc3QuXG5cbiAgICAgICAgICAgIHZhciBub0NoaWxkID0ge307XG5cbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gZG9tSW5kZXg7XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIGRvbUluZGV4KHJvb3ROb2RlLCB0cmVlLCBpbmRpY2VzLCBub2Rlcykge1xuICAgICAgICAgICAgICAgIGlmICghaW5kaWNlcyB8fCBpbmRpY2VzLmxlbmd0aCA9PT0gMCkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4ge307XG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgaW5kaWNlcy5zb3J0KGFzY2VuZGluZyk7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiByZWN1cnNlKHJvb3ROb2RlLCB0cmVlLCBpbmRpY2VzLCBub2RlcywgMCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBmdW5jdGlvbiByZWN1cnNlKHJvb3ROb2RlLCB0cmVlLCBpbmRpY2VzLCBub2Rlcywgcm9vdEluZGV4KSB7XG4gICAgICAgICAgICAgICAgbm9kZXMgPSBub2RlcyB8fCB7fTtcblxuICAgICAgICAgICAgICAgIGlmIChyb290Tm9kZSkge1xuICAgICAgICAgICAgICAgICAgICBpZiAoaW5kZXhJblJhbmdlKGluZGljZXMsIHJvb3RJbmRleCwgcm9vdEluZGV4KSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgbm9kZXNbcm9vdEluZGV4XSA9IHJvb3ROb2RlO1xuICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgdmFyIHZDaGlsZHJlbiA9IHRyZWUuY2hpbGRyZW47XG5cbiAgICAgICAgICAgICAgICAgICAgaWYgKHZDaGlsZHJlbikge1xuXG4gICAgICAgICAgICAgICAgICAgICAgICB2YXIgY2hpbGROb2RlcyA9IHJvb3ROb2RlLmNoaWxkTm9kZXM7XG5cbiAgICAgICAgICAgICAgICAgICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgdHJlZS5jaGlsZHJlbi5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJvb3RJbmRleCArPSAxO1xuXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdmFyIHZDaGlsZCA9IHZDaGlsZHJlbltpXSB8fCBub0NoaWxkO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZhciBuZXh0SW5kZXggPSByb290SW5kZXggKyAodkNoaWxkLmNvdW50IHx8IDApO1xuXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gc2tpcCByZWN1cnNpb24gZG93biB0aGUgdHJlZSBpZiB0aGVyZSBhcmUgbm8gbm9kZXMgZG93biBoZXJlXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGluZGV4SW5SYW5nZShpbmRpY2VzLCByb290SW5kZXgsIG5leHRJbmRleCkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmVjdXJzZShjaGlsZE5vZGVzW2ldLCB2Q2hpbGQsIGluZGljZXMsIG5vZGVzLCByb290SW5kZXgpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJvb3RJbmRleCA9IG5leHRJbmRleDtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHJldHVybiBub2RlcztcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgLy8gQmluYXJ5IHNlYXJjaCBmb3IgYW4gaW5kZXggaW4gdGhlIGludGVydmFsIFtsZWZ0LCByaWdodF1cbiAgICAgICAgICAgIGZ1bmN0aW9uIGluZGV4SW5SYW5nZShpbmRpY2VzLCBsZWZ0LCByaWdodCkge1xuICAgICAgICAgICAgICAgIGlmIChpbmRpY2VzLmxlbmd0aCA9PT0gMCkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgdmFyIG1pbkluZGV4ID0gMDtcbiAgICAgICAgICAgICAgICB2YXIgbWF4SW5kZXggPSBpbmRpY2VzLmxlbmd0aCAtIDE7XG4gICAgICAgICAgICAgICAgdmFyIGN1cnJlbnRJbmRleDtcbiAgICAgICAgICAgICAgICB2YXIgY3VycmVudEl0ZW07XG5cbiAgICAgICAgICAgICAgICB3aGlsZSAobWluSW5kZXggPD0gbWF4SW5kZXgpIHtcbiAgICAgICAgICAgICAgICAgICAgY3VycmVudEluZGV4ID0gKG1heEluZGV4ICsgbWluSW5kZXgpIC8gMiA+PiAwO1xuICAgICAgICAgICAgICAgICAgICBjdXJyZW50SXRlbSA9IGluZGljZXNbY3VycmVudEluZGV4XTtcblxuICAgICAgICAgICAgICAgICAgICBpZiAobWluSW5kZXggPT09IG1heEluZGV4KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gY3VycmVudEl0ZW0gPj0gbGVmdCAmJiBjdXJyZW50SXRlbSA8PSByaWdodDtcbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIGlmIChjdXJyZW50SXRlbSA8IGxlZnQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIG1pbkluZGV4ID0gY3VycmVudEluZGV4ICsgMTtcbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIGlmIChjdXJyZW50SXRlbSA+IHJpZ2h0KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBtYXhJbmRleCA9IGN1cnJlbnRJbmRleCAtIDE7XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZnVuY3Rpb24gYXNjZW5kaW5nKGEsIGIpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gYSA+IGIgPyAxIDogLTE7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0sIHt9XSwgMTc6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICB2YXIgYXBwbHlQcm9wZXJ0aWVzID0gcmVxdWlyZShcIi4vYXBwbHktcHJvcGVydGllc1wiKTtcblxuICAgICAgICAgICAgdmFyIGlzV2lkZ2V0ID0gcmVxdWlyZShcIi4uL3Zub2RlL2lzLXdpZGdldC5qc1wiKTtcbiAgICAgICAgICAgIHZhciBWUGF0Y2ggPSByZXF1aXJlKFwiLi4vdm5vZGUvdnBhdGNoLmpzXCIpO1xuXG4gICAgICAgICAgICB2YXIgdXBkYXRlV2lkZ2V0ID0gcmVxdWlyZShcIi4vdXBkYXRlLXdpZGdldFwiKTtcblxuICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBhcHBseVBhdGNoO1xuXG4gICAgICAgICAgICBmdW5jdGlvbiBhcHBseVBhdGNoKHZwYXRjaCwgZG9tTm9kZSwgcmVuZGVyT3B0aW9ucykge1xuICAgICAgICAgICAgICAgIHZhciB0eXBlID0gdnBhdGNoLnR5cGU7XG4gICAgICAgICAgICAgICAgdmFyIHZOb2RlID0gdnBhdGNoLnZOb2RlO1xuICAgICAgICAgICAgICAgIHZhciBwYXRjaCA9IHZwYXRjaC5wYXRjaDtcblxuICAgICAgICAgICAgICAgIHN3aXRjaCAodHlwZSkge1xuICAgICAgICAgICAgICAgICAgICBjYXNlIFZQYXRjaC5SRU1PVkU6XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gcmVtb3ZlTm9kZShkb21Ob2RlLCB2Tm9kZSk7XG4gICAgICAgICAgICAgICAgICAgIGNhc2UgVlBhdGNoLklOU0VSVDpcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBpbnNlcnROb2RlKGRvbU5vZGUsIHBhdGNoLCByZW5kZXJPcHRpb25zKTtcbiAgICAgICAgICAgICAgICAgICAgY2FzZSBWUGF0Y2guVlRFWFQ6XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gc3RyaW5nUGF0Y2goZG9tTm9kZSwgdk5vZGUsIHBhdGNoLCByZW5kZXJPcHRpb25zKTtcbiAgICAgICAgICAgICAgICAgICAgY2FzZSBWUGF0Y2guV0lER0VUOlxuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHdpZGdldFBhdGNoKGRvbU5vZGUsIHZOb2RlLCBwYXRjaCwgcmVuZGVyT3B0aW9ucyk7XG4gICAgICAgICAgICAgICAgICAgIGNhc2UgVlBhdGNoLlZOT0RFOlxuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHZOb2RlUGF0Y2goZG9tTm9kZSwgdk5vZGUsIHBhdGNoLCByZW5kZXJPcHRpb25zKTtcbiAgICAgICAgICAgICAgICAgICAgY2FzZSBWUGF0Y2guT1JERVI6XG4gICAgICAgICAgICAgICAgICAgICAgICByZW9yZGVyQ2hpbGRyZW4oZG9tTm9kZSwgcGF0Y2gpO1xuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGRvbU5vZGU7XG4gICAgICAgICAgICAgICAgICAgIGNhc2UgVlBhdGNoLlBST1BTOlxuICAgICAgICAgICAgICAgICAgICAgICAgYXBwbHlQcm9wZXJ0aWVzKGRvbU5vZGUsIHBhdGNoLCB2Tm9kZS5wcm9wZXJ0aWVzKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBkb21Ob2RlO1xuICAgICAgICAgICAgICAgICAgICBjYXNlIFZQYXRjaC5USFVOSzpcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiByZXBsYWNlUm9vdChkb21Ob2RlLCByZW5kZXJPcHRpb25zLnBhdGNoKGRvbU5vZGUsIHBhdGNoLCByZW5kZXJPcHRpb25zKSk7XG4gICAgICAgICAgICAgICAgICAgIGRlZmF1bHQ6XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gZG9tTm9kZTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIHJlbW92ZU5vZGUoZG9tTm9kZSwgdk5vZGUpIHtcbiAgICAgICAgICAgICAgICB2YXIgcGFyZW50Tm9kZSA9IGRvbU5vZGUucGFyZW50Tm9kZTtcblxuICAgICAgICAgICAgICAgIGlmIChwYXJlbnROb2RlKSB7XG4gICAgICAgICAgICAgICAgICAgIHBhcmVudE5vZGUucmVtb3ZlQ2hpbGQoZG9tTm9kZSk7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgZGVzdHJveVdpZGdldChkb21Ob2RlLCB2Tm9kZSk7XG5cbiAgICAgICAgICAgICAgICByZXR1cm4gbnVsbDtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZnVuY3Rpb24gaW5zZXJ0Tm9kZShwYXJlbnROb2RlLCB2Tm9kZSwgcmVuZGVyT3B0aW9ucykge1xuICAgICAgICAgICAgICAgIHZhciBuZXdOb2RlID0gcmVuZGVyT3B0aW9ucy5yZW5kZXIodk5vZGUsIHJlbmRlck9wdGlvbnMpO1xuXG4gICAgICAgICAgICAgICAgaWYgKHBhcmVudE5vZGUpIHtcbiAgICAgICAgICAgICAgICAgICAgcGFyZW50Tm9kZS5hcHBlbmRDaGlsZChuZXdOb2RlKTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICByZXR1cm4gcGFyZW50Tm9kZTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZnVuY3Rpb24gc3RyaW5nUGF0Y2goZG9tTm9kZSwgbGVmdFZOb2RlLCB2VGV4dCwgcmVuZGVyT3B0aW9ucykge1xuICAgICAgICAgICAgICAgIHZhciBuZXdOb2RlO1xuXG4gICAgICAgICAgICAgICAgaWYgKGRvbU5vZGUubm9kZVR5cGUgPT09IDMpIHtcbiAgICAgICAgICAgICAgICAgICAgZG9tTm9kZS5yZXBsYWNlRGF0YSgwLCBkb21Ob2RlLmxlbmd0aCwgdlRleHQudGV4dCk7XG4gICAgICAgICAgICAgICAgICAgIG5ld05vZGUgPSBkb21Ob2RlO1xuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciBwYXJlbnROb2RlID0gZG9tTm9kZS5wYXJlbnROb2RlO1xuICAgICAgICAgICAgICAgICAgICBuZXdOb2RlID0gcmVuZGVyT3B0aW9ucy5yZW5kZXIodlRleHQsIHJlbmRlck9wdGlvbnMpO1xuXG4gICAgICAgICAgICAgICAgICAgIGlmIChwYXJlbnROb2RlICYmIG5ld05vZGUgIT09IGRvbU5vZGUpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHBhcmVudE5vZGUucmVwbGFjZUNoaWxkKG5ld05vZGUsIGRvbU5vZGUpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgcmV0dXJuIG5ld05vZGU7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIHdpZGdldFBhdGNoKGRvbU5vZGUsIGxlZnRWTm9kZSwgd2lkZ2V0LCByZW5kZXJPcHRpb25zKSB7XG4gICAgICAgICAgICAgICAgdmFyIHVwZGF0aW5nID0gdXBkYXRlV2lkZ2V0KGxlZnRWTm9kZSwgd2lkZ2V0KTtcbiAgICAgICAgICAgICAgICB2YXIgbmV3Tm9kZTtcblxuICAgICAgICAgICAgICAgIGlmICh1cGRhdGluZykge1xuICAgICAgICAgICAgICAgICAgICBuZXdOb2RlID0gd2lkZ2V0LnVwZGF0ZShsZWZ0Vk5vZGUsIGRvbU5vZGUpIHx8IGRvbU5vZGU7XG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgbmV3Tm9kZSA9IHJlbmRlck9wdGlvbnMucmVuZGVyKHdpZGdldCwgcmVuZGVyT3B0aW9ucyk7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgdmFyIHBhcmVudE5vZGUgPSBkb21Ob2RlLnBhcmVudE5vZGU7XG5cbiAgICAgICAgICAgICAgICBpZiAocGFyZW50Tm9kZSAmJiBuZXdOb2RlICE9PSBkb21Ob2RlKSB7XG4gICAgICAgICAgICAgICAgICAgIHBhcmVudE5vZGUucmVwbGFjZUNoaWxkKG5ld05vZGUsIGRvbU5vZGUpO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIGlmICghdXBkYXRpbmcpIHtcbiAgICAgICAgICAgICAgICAgICAgZGVzdHJveVdpZGdldChkb21Ob2RlLCBsZWZ0Vk5vZGUpO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHJldHVybiBuZXdOb2RlO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBmdW5jdGlvbiB2Tm9kZVBhdGNoKGRvbU5vZGUsIGxlZnRWTm9kZSwgdk5vZGUsIHJlbmRlck9wdGlvbnMpIHtcbiAgICAgICAgICAgICAgICB2YXIgcGFyZW50Tm9kZSA9IGRvbU5vZGUucGFyZW50Tm9kZTtcbiAgICAgICAgICAgICAgICB2YXIgbmV3Tm9kZSA9IHJlbmRlck9wdGlvbnMucmVuZGVyKHZOb2RlLCByZW5kZXJPcHRpb25zKTtcblxuICAgICAgICAgICAgICAgIGlmIChwYXJlbnROb2RlICYmIG5ld05vZGUgIT09IGRvbU5vZGUpIHtcbiAgICAgICAgICAgICAgICAgICAgcGFyZW50Tm9kZS5yZXBsYWNlQ2hpbGQobmV3Tm9kZSwgZG9tTm9kZSk7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgcmV0dXJuIG5ld05vZGU7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIGRlc3Ryb3lXaWRnZXQoZG9tTm9kZSwgdykge1xuICAgICAgICAgICAgICAgIGlmICh0eXBlb2Ygdy5kZXN0cm95ID09PSBcImZ1bmN0aW9uXCIgJiYgaXNXaWRnZXQodykpIHtcbiAgICAgICAgICAgICAgICAgICAgdy5kZXN0cm95KGRvbU5vZGUpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZnVuY3Rpb24gcmVvcmRlckNoaWxkcmVuKGRvbU5vZGUsIG1vdmVzKSB7XG4gICAgICAgICAgICAgICAgdmFyIGNoaWxkTm9kZXMgPSBkb21Ob2RlLmNoaWxkTm9kZXM7XG4gICAgICAgICAgICAgICAgdmFyIGtleU1hcCA9IHt9O1xuICAgICAgICAgICAgICAgIHZhciBub2RlO1xuICAgICAgICAgICAgICAgIHZhciByZW1vdmU7XG4gICAgICAgICAgICAgICAgdmFyIGluc2VydDtcblxuICAgICAgICAgICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgbW92ZXMucmVtb3Zlcy5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgICAgICAgICByZW1vdmUgPSBtb3Zlcy5yZW1vdmVzW2ldO1xuICAgICAgICAgICAgICAgICAgICBub2RlID0gY2hpbGROb2Rlc1tyZW1vdmUuZnJvbV07XG4gICAgICAgICAgICAgICAgICAgIGlmIChyZW1vdmUua2V5KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBrZXlNYXBbcmVtb3ZlLmtleV0gPSBub2RlO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIGRvbU5vZGUucmVtb3ZlQ2hpbGQobm9kZSk7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgdmFyIGxlbmd0aCA9IGNoaWxkTm9kZXMubGVuZ3RoO1xuICAgICAgICAgICAgICAgIGZvciAodmFyIGogPSAwOyBqIDwgbW92ZXMuaW5zZXJ0cy5sZW5ndGg7IGorKykge1xuICAgICAgICAgICAgICAgICAgICBpbnNlcnQgPSBtb3Zlcy5pbnNlcnRzW2pdO1xuICAgICAgICAgICAgICAgICAgICBub2RlID0ga2V5TWFwW2luc2VydC5rZXldO1xuICAgICAgICAgICAgICAgICAgICAvLyB0aGlzIGlzIHRoZSB3ZWlyZGVzdCBidWcgaSd2ZSBldmVyIHNlZW4gaW4gd2Via2l0XG4gICAgICAgICAgICAgICAgICAgIGRvbU5vZGUuaW5zZXJ0QmVmb3JlKG5vZGUsIGluc2VydC50byA+PSBsZW5ndGgrKyA/IG51bGwgOiBjaGlsZE5vZGVzW2luc2VydC50b10pO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZnVuY3Rpb24gcmVwbGFjZVJvb3Qob2xkUm9vdCwgbmV3Um9vdCkge1xuICAgICAgICAgICAgICAgIGlmIChvbGRSb290ICYmIG5ld1Jvb3QgJiYgb2xkUm9vdCAhPT0gbmV3Um9vdCAmJiBvbGRSb290LnBhcmVudE5vZGUpIHtcbiAgICAgICAgICAgICAgICAgICAgb2xkUm9vdC5wYXJlbnROb2RlLnJlcGxhY2VDaGlsZChuZXdSb290LCBvbGRSb290KTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICByZXR1cm4gbmV3Um9vdDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSwgeyBcIi4uL3Zub2RlL2lzLXdpZGdldC5qc1wiOiAyOSwgXCIuLi92bm9kZS92cGF0Y2guanNcIjogMzIsIFwiLi9hcHBseS1wcm9wZXJ0aWVzXCI6IDE0LCBcIi4vdXBkYXRlLXdpZGdldFwiOiAxOSB9XSwgMTg6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICB2YXIgZG9jdW1lbnQgPSByZXF1aXJlKFwiZ2xvYmFsL2RvY3VtZW50XCIpO1xuICAgICAgICAgICAgdmFyIGlzQXJyYXkgPSByZXF1aXJlKFwieC1pcy1hcnJheVwiKTtcblxuICAgICAgICAgICAgdmFyIHJlbmRlciA9IHJlcXVpcmUoXCIuL2NyZWF0ZS1lbGVtZW50XCIpO1xuICAgICAgICAgICAgdmFyIGRvbUluZGV4ID0gcmVxdWlyZShcIi4vZG9tLWluZGV4XCIpO1xuICAgICAgICAgICAgdmFyIHBhdGNoT3AgPSByZXF1aXJlKFwiLi9wYXRjaC1vcFwiKTtcbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gcGF0Y2g7XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIHBhdGNoKHJvb3ROb2RlLCBwYXRjaGVzLCByZW5kZXJPcHRpb25zKSB7XG4gICAgICAgICAgICAgICAgcmVuZGVyT3B0aW9ucyA9IHJlbmRlck9wdGlvbnMgfHwge307XG4gICAgICAgICAgICAgICAgcmVuZGVyT3B0aW9ucy5wYXRjaCA9IHJlbmRlck9wdGlvbnMucGF0Y2ggJiYgcmVuZGVyT3B0aW9ucy5wYXRjaCAhPT0gcGF0Y2ggPyByZW5kZXJPcHRpb25zLnBhdGNoIDogcGF0Y2hSZWN1cnNpdmU7XG4gICAgICAgICAgICAgICAgcmVuZGVyT3B0aW9ucy5yZW5kZXIgPSByZW5kZXJPcHRpb25zLnJlbmRlciB8fCByZW5kZXI7XG5cbiAgICAgICAgICAgICAgICByZXR1cm4gcmVuZGVyT3B0aW9ucy5wYXRjaChyb290Tm9kZSwgcGF0Y2hlcywgcmVuZGVyT3B0aW9ucyk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIHBhdGNoUmVjdXJzaXZlKHJvb3ROb2RlLCBwYXRjaGVzLCByZW5kZXJPcHRpb25zKSB7XG4gICAgICAgICAgICAgICAgdmFyIGluZGljZXMgPSBwYXRjaEluZGljZXMocGF0Y2hlcyk7XG5cbiAgICAgICAgICAgICAgICBpZiAoaW5kaWNlcy5sZW5ndGggPT09IDApIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHJvb3ROb2RlO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHZhciBpbmRleCA9IGRvbUluZGV4KHJvb3ROb2RlLCBwYXRjaGVzLmEsIGluZGljZXMpO1xuICAgICAgICAgICAgICAgIHZhciBvd25lckRvY3VtZW50ID0gcm9vdE5vZGUub3duZXJEb2N1bWVudDtcblxuICAgICAgICAgICAgICAgIGlmICghcmVuZGVyT3B0aW9ucy5kb2N1bWVudCAmJiBvd25lckRvY3VtZW50ICE9PSBkb2N1bWVudCkge1xuICAgICAgICAgICAgICAgICAgICByZW5kZXJPcHRpb25zLmRvY3VtZW50ID0gb3duZXJEb2N1bWVudDtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IGluZGljZXMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgICAgICAgICAgdmFyIG5vZGVJbmRleCA9IGluZGljZXNbaV07XG4gICAgICAgICAgICAgICAgICAgIHJvb3ROb2RlID0gYXBwbHlQYXRjaChyb290Tm9kZSwgaW5kZXhbbm9kZUluZGV4XSwgcGF0Y2hlc1tub2RlSW5kZXhdLCByZW5kZXJPcHRpb25zKTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICByZXR1cm4gcm9vdE5vZGU7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIGFwcGx5UGF0Y2gocm9vdE5vZGUsIGRvbU5vZGUsIHBhdGNoTGlzdCwgcmVuZGVyT3B0aW9ucykge1xuICAgICAgICAgICAgICAgIGlmICghZG9tTm9kZSkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gcm9vdE5vZGU7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgdmFyIG5ld05vZGU7XG5cbiAgICAgICAgICAgICAgICBpZiAoaXNBcnJheShwYXRjaExpc3QpKSB7XG4gICAgICAgICAgICAgICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgcGF0Y2hMaXN0Lmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBuZXdOb2RlID0gcGF0Y2hPcChwYXRjaExpc3RbaV0sIGRvbU5vZGUsIHJlbmRlck9wdGlvbnMpO1xuXG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoZG9tTm9kZSA9PT0gcm9vdE5vZGUpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICByb290Tm9kZSA9IG5ld05vZGU7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICBuZXdOb2RlID0gcGF0Y2hPcChwYXRjaExpc3QsIGRvbU5vZGUsIHJlbmRlck9wdGlvbnMpO1xuXG4gICAgICAgICAgICAgICAgICAgIGlmIChkb21Ob2RlID09PSByb290Tm9kZSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgcm9vdE5vZGUgPSBuZXdOb2RlO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgcmV0dXJuIHJvb3ROb2RlO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBmdW5jdGlvbiBwYXRjaEluZGljZXMocGF0Y2hlcykge1xuICAgICAgICAgICAgICAgIHZhciBpbmRpY2VzID0gW107XG5cbiAgICAgICAgICAgICAgICBmb3IgKHZhciBrZXkgaW4gcGF0Y2hlcykge1xuICAgICAgICAgICAgICAgICAgICBpZiAoa2V5ICE9PSBcImFcIikge1xuICAgICAgICAgICAgICAgICAgICAgICAgaW5kaWNlcy5wdXNoKE51bWJlcihrZXkpKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHJldHVybiBpbmRpY2VzO1xuICAgICAgICAgICAgfVxuICAgICAgICB9LCB7IFwiLi9jcmVhdGUtZWxlbWVudFwiOiAxNSwgXCIuL2RvbS1pbmRleFwiOiAxNiwgXCIuL3BhdGNoLW9wXCI6IDE3LCBcImdsb2JhbC9kb2N1bWVudFwiOiAxMCwgXCJ4LWlzLWFycmF5XCI6IDEyIH1dLCAxOTogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHtcbiAgICAgICAgICAgIHZhciBpc1dpZGdldCA9IHJlcXVpcmUoXCIuLi92bm9kZS9pcy13aWRnZXQuanNcIik7XG5cbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gdXBkYXRlV2lkZ2V0O1xuXG4gICAgICAgICAgICBmdW5jdGlvbiB1cGRhdGVXaWRnZXQoYSwgYikge1xuICAgICAgICAgICAgICAgIGlmIChpc1dpZGdldChhKSAmJiBpc1dpZGdldChiKSkge1xuICAgICAgICAgICAgICAgICAgICBpZiAoXCJuYW1lXCIgaW4gYSAmJiBcIm5hbWVcIiBpbiBiKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gYS5pZCA9PT0gYi5pZDtcbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBhLmluaXQgPT09IGIuaW5pdDtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSwgeyBcIi4uL3Zub2RlL2lzLXdpZGdldC5qc1wiOiAyOSB9XSwgMjA6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICBcInVzZSBzdHJpY3RcIjtcblxuICAgICAgICAgICAgdmFyIEV2U3RvcmUgPSByZXF1aXJlKFwiZXYtc3RvcmVcIik7XG5cbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gRXZIb29rO1xuXG4gICAgICAgICAgICBmdW5jdGlvbiBFdkhvb2sodmFsdWUpIHtcbiAgICAgICAgICAgICAgICBpZiAoISh0aGlzIGluc3RhbmNlb2YgRXZIb29rKSkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gbmV3IEV2SG9vayh2YWx1ZSk7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgdGhpcy52YWx1ZSA9IHZhbHVlO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBFdkhvb2sucHJvdG90eXBlLmhvb2sgPSBmdW5jdGlvbiAobm9kZSwgcHJvcGVydHlOYW1lKSB7XG4gICAgICAgICAgICAgICAgdmFyIGVzID0gRXZTdG9yZShub2RlKTtcbiAgICAgICAgICAgICAgICB2YXIgcHJvcE5hbWUgPSBwcm9wZXJ0eU5hbWUuc3Vic3RyKDMpO1xuXG4gICAgICAgICAgICAgICAgZXNbcHJvcE5hbWVdID0gdGhpcy52YWx1ZTtcbiAgICAgICAgICAgIH07XG5cbiAgICAgICAgICAgIEV2SG9vay5wcm90b3R5cGUudW5ob29rID0gZnVuY3Rpb24gKG5vZGUsIHByb3BlcnR5TmFtZSkge1xuICAgICAgICAgICAgICAgIHZhciBlcyA9IEV2U3RvcmUobm9kZSk7XG4gICAgICAgICAgICAgICAgdmFyIHByb3BOYW1lID0gcHJvcGVydHlOYW1lLnN1YnN0cigzKTtcblxuICAgICAgICAgICAgICAgIGVzW3Byb3BOYW1lXSA9IHVuZGVmaW5lZDtcbiAgICAgICAgICAgIH07XG4gICAgICAgIH0sIHsgXCJldi1zdG9yZVwiOiA3IH1dLCAyMTogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHtcbiAgICAgICAgICAgIFwidXNlIHN0cmljdFwiO1xuXG4gICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IFNvZnRTZXRIb29rO1xuXG4gICAgICAgICAgICBmdW5jdGlvbiBTb2Z0U2V0SG9vayh2YWx1ZSkge1xuICAgICAgICAgICAgICAgIGlmICghKHRoaXMgaW5zdGFuY2VvZiBTb2Z0U2V0SG9vaykpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIG5ldyBTb2Z0U2V0SG9vayh2YWx1ZSk7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgdGhpcy52YWx1ZSA9IHZhbHVlO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBTb2Z0U2V0SG9vay5wcm90b3R5cGUuaG9vayA9IGZ1bmN0aW9uIChub2RlLCBwcm9wZXJ0eU5hbWUpIHtcbiAgICAgICAgICAgICAgICBpZiAobm9kZVtwcm9wZXJ0eU5hbWVdICE9PSB0aGlzLnZhbHVlKSB7XG4gICAgICAgICAgICAgICAgICAgIG5vZGVbcHJvcGVydHlOYW1lXSA9IHRoaXMudmFsdWU7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfTtcbiAgICAgICAgfSwge31dLCAyMjogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHtcbiAgICAgICAgICAgIFwidXNlIHN0cmljdFwiO1xuXG4gICAgICAgICAgICB2YXIgaXNBcnJheSA9IHJlcXVpcmUoXCJ4LWlzLWFycmF5XCIpO1xuXG4gICAgICAgICAgICB2YXIgVk5vZGUgPSByZXF1aXJlKFwiLi4vdm5vZGUvdm5vZGUuanNcIik7XG4gICAgICAgICAgICB2YXIgVlRleHQgPSByZXF1aXJlKFwiLi4vdm5vZGUvdnRleHQuanNcIik7XG4gICAgICAgICAgICB2YXIgaXNWTm9kZSA9IHJlcXVpcmUoXCIuLi92bm9kZS9pcy12bm9kZVwiKTtcbiAgICAgICAgICAgIHZhciBpc1ZUZXh0ID0gcmVxdWlyZShcIi4uL3Zub2RlL2lzLXZ0ZXh0XCIpO1xuICAgICAgICAgICAgdmFyIGlzV2lkZ2V0ID0gcmVxdWlyZShcIi4uL3Zub2RlL2lzLXdpZGdldFwiKTtcbiAgICAgICAgICAgIHZhciBpc0hvb2sgPSByZXF1aXJlKFwiLi4vdm5vZGUvaXMtdmhvb2tcIik7XG4gICAgICAgICAgICB2YXIgaXNWVGh1bmsgPSByZXF1aXJlKFwiLi4vdm5vZGUvaXMtdGh1bmtcIik7XG5cbiAgICAgICAgICAgIHZhciBwYXJzZVRhZyA9IHJlcXVpcmUoXCIuL3BhcnNlLXRhZy5qc1wiKTtcbiAgICAgICAgICAgIHZhciBzb2Z0U2V0SG9vayA9IHJlcXVpcmUoXCIuL2hvb2tzL3NvZnQtc2V0LWhvb2suanNcIik7XG4gICAgICAgICAgICB2YXIgZXZIb29rID0gcmVxdWlyZShcIi4vaG9va3MvZXYtaG9vay5qc1wiKTtcblxuICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBoO1xuXG4gICAgICAgICAgICBmdW5jdGlvbiBoKHRhZ05hbWUsIHByb3BlcnRpZXMsIGNoaWxkcmVuKSB7XG4gICAgICAgICAgICAgICAgdmFyIGNoaWxkTm9kZXMgPSBbXTtcbiAgICAgICAgICAgICAgICB2YXIgdGFnLCBwcm9wcywga2V5LCBuYW1lc3BhY2U7XG5cbiAgICAgICAgICAgICAgICBpZiAoIWNoaWxkcmVuICYmIGlzQ2hpbGRyZW4ocHJvcGVydGllcykpIHtcbiAgICAgICAgICAgICAgICAgICAgY2hpbGRyZW4gPSBwcm9wZXJ0aWVzO1xuICAgICAgICAgICAgICAgICAgICBwcm9wcyA9IHt9O1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHByb3BzID0gcHJvcHMgfHwgcHJvcGVydGllcyB8fCB7fTtcbiAgICAgICAgICAgICAgICB0YWcgPSBwYXJzZVRhZyh0YWdOYW1lLCBwcm9wcyk7XG5cbiAgICAgICAgICAgICAgICAvLyBzdXBwb3J0IGtleXNcbiAgICAgICAgICAgICAgICBpZiAocHJvcHMuaGFzT3duUHJvcGVydHkoXCJrZXlcIikpIHtcbiAgICAgICAgICAgICAgICAgICAga2V5ID0gcHJvcHMua2V5O1xuICAgICAgICAgICAgICAgICAgICBwcm9wcy5rZXkgPSB1bmRlZmluZWQ7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgLy8gc3VwcG9ydCBuYW1lc3BhY2VcbiAgICAgICAgICAgICAgICBpZiAocHJvcHMuaGFzT3duUHJvcGVydHkoXCJuYW1lc3BhY2VcIikpIHtcbiAgICAgICAgICAgICAgICAgICAgbmFtZXNwYWNlID0gcHJvcHMubmFtZXNwYWNlO1xuICAgICAgICAgICAgICAgICAgICBwcm9wcy5uYW1lc3BhY2UgPSB1bmRlZmluZWQ7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgLy8gZml4IGN1cnNvciBidWdcbiAgICAgICAgICAgICAgICBpZiAodGFnID09PSBcIklOUFVUXCIgJiYgIW5hbWVzcGFjZSAmJiBwcm9wcy5oYXNPd25Qcm9wZXJ0eShcInZhbHVlXCIpICYmIHByb3BzLnZhbHVlICE9PSB1bmRlZmluZWQgJiYgIWlzSG9vayhwcm9wcy52YWx1ZSkpIHtcbiAgICAgICAgICAgICAgICAgICAgcHJvcHMudmFsdWUgPSBzb2Z0U2V0SG9vayhwcm9wcy52YWx1ZSk7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgdHJhbnNmb3JtUHJvcGVydGllcyhwcm9wcyk7XG5cbiAgICAgICAgICAgICAgICBpZiAoY2hpbGRyZW4gIT09IHVuZGVmaW5lZCAmJiBjaGlsZHJlbiAhPT0gbnVsbCkge1xuICAgICAgICAgICAgICAgICAgICBhZGRDaGlsZChjaGlsZHJlbiwgY2hpbGROb2RlcywgdGFnLCBwcm9wcyk7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgcmV0dXJuIG5ldyBWTm9kZSh0YWcsIHByb3BzLCBjaGlsZE5vZGVzLCBrZXksIG5hbWVzcGFjZSk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIGFkZENoaWxkKGMsIGNoaWxkTm9kZXMsIHRhZywgcHJvcHMpIHtcbiAgICAgICAgICAgICAgICBpZiAodHlwZW9mIGMgPT09IFwic3RyaW5nXCIpIHtcbiAgICAgICAgICAgICAgICAgICAgY2hpbGROb2Rlcy5wdXNoKG5ldyBWVGV4dChjKSk7XG4gICAgICAgICAgICAgICAgfSBlbHNlIGlmICh0eXBlb2YgYyA9PT0gXCJudW1iZXJcIikge1xuICAgICAgICAgICAgICAgICAgICBjaGlsZE5vZGVzLnB1c2gobmV3IFZUZXh0KFN0cmluZyhjKSkpO1xuICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoaXNDaGlsZChjKSkge1xuICAgICAgICAgICAgICAgICAgICBjaGlsZE5vZGVzLnB1c2goYyk7XG4gICAgICAgICAgICAgICAgfSBlbHNlIGlmIChpc0FycmF5KGMpKSB7XG4gICAgICAgICAgICAgICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgYy5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgICAgICAgICAgICAgYWRkQ2hpbGQoY1tpXSwgY2hpbGROb2RlcywgdGFnLCBwcm9wcyk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKGMgPT09IG51bGwgfHwgYyA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICB0aHJvdyBVbmV4cGVjdGVkVmlydHVhbEVsZW1lbnQoe1xuICAgICAgICAgICAgICAgICAgICAgICAgZm9yZWlnbk9iamVjdDogYyxcbiAgICAgICAgICAgICAgICAgICAgICAgIHBhcmVudFZub2RlOiB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdGFnTmFtZTogdGFnLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHByb3BlcnRpZXM6IHByb3BzXG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZnVuY3Rpb24gdHJhbnNmb3JtUHJvcGVydGllcyhwcm9wcykge1xuICAgICAgICAgICAgICAgIGZvciAodmFyIHByb3BOYW1lIGluIHByb3BzKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmIChwcm9wcy5oYXNPd25Qcm9wZXJ0eShwcm9wTmFtZSkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHZhciB2YWx1ZSA9IHByb3BzW3Byb3BOYW1lXTtcblxuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGlzSG9vayh2YWx1ZSkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb250aW51ZTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHByb3BOYW1lLnN1YnN0cigwLCAzKSA9PT0gXCJldi1cIikge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIGFkZCBldi1mb28gc3VwcG9ydFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHByb3BzW3Byb3BOYW1lXSA9IGV2SG9vayh2YWx1ZSk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIGlzQ2hpbGQoeCkge1xuICAgICAgICAgICAgICAgIHJldHVybiBpc1ZOb2RlKHgpIHx8IGlzVlRleHQoeCkgfHwgaXNXaWRnZXQoeCkgfHwgaXNWVGh1bmsoeCk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIGlzQ2hpbGRyZW4oeCkge1xuICAgICAgICAgICAgICAgIHJldHVybiB0eXBlb2YgeCA9PT0gXCJzdHJpbmdcIiB8fCBpc0FycmF5KHgpIHx8IGlzQ2hpbGQoeCk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIFVuZXhwZWN0ZWRWaXJ0dWFsRWxlbWVudChkYXRhKSB7XG4gICAgICAgICAgICAgICAgdmFyIGVyciA9IG5ldyBFcnJvcigpO1xuXG4gICAgICAgICAgICAgICAgZXJyLnR5cGUgPSBcInZpcnR1YWwtaHlwZXJzY3JpcHQudW5leHBlY3RlZC52aXJ0dWFsLWVsZW1lbnRcIjtcbiAgICAgICAgICAgICAgICBlcnIubWVzc2FnZSA9IFwiVW5leHBlY3RlZCB2aXJ0dWFsIGNoaWxkIHBhc3NlZCB0byBoKCkuXFxuXCIgKyBcIkV4cGVjdGVkIGEgVk5vZGUgLyBWdGh1bmsgLyBWV2lkZ2V0IC8gc3RyaW5nIGJ1dDpcXG5cIiArIFwiZ290OlxcblwiICsgZXJyb3JTdHJpbmcoZGF0YS5mb3JlaWduT2JqZWN0KSArIFwiLlxcblwiICsgXCJUaGUgcGFyZW50IHZub2RlIGlzOlxcblwiICsgZXJyb3JTdHJpbmcoZGF0YS5wYXJlbnRWbm9kZSk7XG4gICAgICAgICAgICAgICAgXCJcXG5cIiArIFwiU3VnZ2VzdGVkIGZpeDogY2hhbmdlIHlvdXIgYGgoLi4uLCBbIC4uLiBdKWAgY2FsbHNpdGUuXCI7XG4gICAgICAgICAgICAgICAgZXJyLmZvcmVpZ25PYmplY3QgPSBkYXRhLmZvcmVpZ25PYmplY3Q7XG4gICAgICAgICAgICAgICAgZXJyLnBhcmVudFZub2RlID0gZGF0YS5wYXJlbnRWbm9kZTtcblxuICAgICAgICAgICAgICAgIHJldHVybiBlcnI7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIGVycm9yU3RyaW5nKG9iaikge1xuICAgICAgICAgICAgICAgIHRyeSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBKU09OLnN0cmluZ2lmeShvYmosIG51bGwsIFwiICAgIFwiKTtcbiAgICAgICAgICAgICAgICB9IGNhdGNoIChlKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBTdHJpbmcob2JqKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH0sIHsgXCIuLi92bm9kZS9pcy10aHVua1wiOiAyNSwgXCIuLi92bm9kZS9pcy12aG9va1wiOiAyNiwgXCIuLi92bm9kZS9pcy12bm9kZVwiOiAyNywgXCIuLi92bm9kZS9pcy12dGV4dFwiOiAyOCwgXCIuLi92bm9kZS9pcy13aWRnZXRcIjogMjksIFwiLi4vdm5vZGUvdm5vZGUuanNcIjogMzEsIFwiLi4vdm5vZGUvdnRleHQuanNcIjogMzMsIFwiLi9ob29rcy9ldi1ob29rLmpzXCI6IDIwLCBcIi4vaG9va3Mvc29mdC1zZXQtaG9vay5qc1wiOiAyMSwgXCIuL3BhcnNlLXRhZy5qc1wiOiAyMywgXCJ4LWlzLWFycmF5XCI6IDEyIH1dLCAyMzogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHtcbiAgICAgICAgICAgIFwidXNlIHN0cmljdFwiO1xuXG4gICAgICAgICAgICB2YXIgc3BsaXQgPSByZXF1aXJlKFwiYnJvd3Nlci1zcGxpdFwiKTtcblxuICAgICAgICAgICAgdmFyIGNsYXNzSWRTcGxpdCA9IC8oW1xcLiNdP1thLXpBLVowLTlcXHUwMDdGLVxcdUZGRkZfOi1dKykvO1xuICAgICAgICAgICAgdmFyIG5vdENsYXNzSWQgPSAvXlxcLnwjLztcblxuICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBwYXJzZVRhZztcblxuICAgICAgICAgICAgZnVuY3Rpb24gcGFyc2VUYWcodGFnLCBwcm9wcykge1xuICAgICAgICAgICAgICAgIGlmICghdGFnKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBcIkRJVlwiO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHZhciBub0lkID0gIXByb3BzLmhhc093blByb3BlcnR5KFwiaWRcIik7XG5cbiAgICAgICAgICAgICAgICB2YXIgdGFnUGFydHMgPSBzcGxpdCh0YWcsIGNsYXNzSWRTcGxpdCk7XG4gICAgICAgICAgICAgICAgdmFyIHRhZ05hbWUgPSBudWxsO1xuXG4gICAgICAgICAgICAgICAgaWYgKG5vdENsYXNzSWQudGVzdCh0YWdQYXJ0c1sxXSkpIHtcbiAgICAgICAgICAgICAgICAgICAgdGFnTmFtZSA9IFwiRElWXCI7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgdmFyIGNsYXNzZXMsIHBhcnQsIHR5cGUsIGk7XG5cbiAgICAgICAgICAgICAgICBmb3IgKGkgPSAwOyBpIDwgdGFnUGFydHMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgICAgICAgICAgcGFydCA9IHRhZ1BhcnRzW2ldO1xuXG4gICAgICAgICAgICAgICAgICAgIGlmICghcGFydCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgY29udGludWU7XG4gICAgICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgICAgICB0eXBlID0gcGFydC5jaGFyQXQoMCk7XG5cbiAgICAgICAgICAgICAgICAgICAgaWYgKCF0YWdOYW1lKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICB0YWdOYW1lID0gcGFydDtcbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIGlmICh0eXBlID09PSBcIi5cIikge1xuICAgICAgICAgICAgICAgICAgICAgICAgY2xhc3NlcyA9IGNsYXNzZXMgfHwgW107XG4gICAgICAgICAgICAgICAgICAgICAgICBjbGFzc2VzLnB1c2gocGFydC5zdWJzdHJpbmcoMSwgcGFydC5sZW5ndGgpKTtcbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIGlmICh0eXBlID09PSBcIiNcIiAmJiBub0lkKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBwcm9wcy5pZCA9IHBhcnQuc3Vic3RyaW5nKDEsIHBhcnQubGVuZ3RoKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIGlmIChjbGFzc2VzKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmIChwcm9wcy5jbGFzc05hbWUpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGNsYXNzZXMucHVzaChwcm9wcy5jbGFzc05hbWUpO1xuICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgcHJvcHMuY2xhc3NOYW1lID0gY2xhc3Nlcy5qb2luKFwiIFwiKTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICByZXR1cm4gcHJvcHMubmFtZXNwYWNlID8gdGFnTmFtZSA6IHRhZ05hbWUudG9VcHBlckNhc2UoKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSwgeyBcImJyb3dzZXItc3BsaXRcIjogNSB9XSwgMjQ6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICB2YXIgaXNWTm9kZSA9IHJlcXVpcmUoXCIuL2lzLXZub2RlXCIpO1xuICAgICAgICAgICAgdmFyIGlzVlRleHQgPSByZXF1aXJlKFwiLi9pcy12dGV4dFwiKTtcbiAgICAgICAgICAgIHZhciBpc1dpZGdldCA9IHJlcXVpcmUoXCIuL2lzLXdpZGdldFwiKTtcbiAgICAgICAgICAgIHZhciBpc1RodW5rID0gcmVxdWlyZShcIi4vaXMtdGh1bmtcIik7XG5cbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gaGFuZGxlVGh1bms7XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIGhhbmRsZVRodW5rKGEsIGIpIHtcbiAgICAgICAgICAgICAgICB2YXIgcmVuZGVyZWRBID0gYTtcbiAgICAgICAgICAgICAgICB2YXIgcmVuZGVyZWRCID0gYjtcblxuICAgICAgICAgICAgICAgIGlmIChpc1RodW5rKGIpKSB7XG4gICAgICAgICAgICAgICAgICAgIHJlbmRlcmVkQiA9IHJlbmRlclRodW5rKGIsIGEpO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIGlmIChpc1RodW5rKGEpKSB7XG4gICAgICAgICAgICAgICAgICAgIHJlbmRlcmVkQSA9IHJlbmRlclRodW5rKGEsIG51bGwpO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHJldHVybiB7XG4gICAgICAgICAgICAgICAgICAgIGE6IHJlbmRlcmVkQSxcbiAgICAgICAgICAgICAgICAgICAgYjogcmVuZGVyZWRCXG4gICAgICAgICAgICAgICAgfTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZnVuY3Rpb24gcmVuZGVyVGh1bmsodGh1bmssIHByZXZpb3VzKSB7XG4gICAgICAgICAgICAgICAgdmFyIHJlbmRlcmVkVGh1bmsgPSB0aHVuay52bm9kZTtcblxuICAgICAgICAgICAgICAgIGlmICghcmVuZGVyZWRUaHVuaykge1xuICAgICAgICAgICAgICAgICAgICByZW5kZXJlZFRodW5rID0gdGh1bmsudm5vZGUgPSB0aHVuay5yZW5kZXIocHJldmlvdXMpO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIGlmICghKGlzVk5vZGUocmVuZGVyZWRUaHVuaykgfHwgaXNWVGV4dChyZW5kZXJlZFRodW5rKSB8fCBpc1dpZGdldChyZW5kZXJlZFRodW5rKSkpIHtcbiAgICAgICAgICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKFwidGh1bmsgZGlkIG5vdCByZXR1cm4gYSB2YWxpZCBub2RlXCIpO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHJldHVybiByZW5kZXJlZFRodW5rO1xuICAgICAgICAgICAgfVxuICAgICAgICB9LCB7IFwiLi9pcy10aHVua1wiOiAyNSwgXCIuL2lzLXZub2RlXCI6IDI3LCBcIi4vaXMtdnRleHRcIjogMjgsIFwiLi9pcy13aWRnZXRcIjogMjkgfV0sIDI1OiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge1xuICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBpc1RodW5rO1xuXG4gICAgICAgICAgICBmdW5jdGlvbiBpc1RodW5rKHQpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gdCAmJiB0LnR5cGUgPT09IFwiVGh1bmtcIjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSwge31dLCAyNjogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHtcbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gaXNIb29rO1xuXG4gICAgICAgICAgICBmdW5jdGlvbiBpc0hvb2soaG9vaykge1xuICAgICAgICAgICAgICAgIHJldHVybiBob29rICYmICh0eXBlb2YgaG9vay5ob29rID09PSBcImZ1bmN0aW9uXCIgJiYgIWhvb2suaGFzT3duUHJvcGVydHkoXCJob29rXCIpIHx8IHR5cGVvZiBob29rLnVuaG9vayA9PT0gXCJmdW5jdGlvblwiICYmICFob29rLmhhc093blByb3BlcnR5KFwidW5ob29rXCIpKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSwge31dLCAyNzogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHtcbiAgICAgICAgICAgIHZhciB2ZXJzaW9uID0gcmVxdWlyZShcIi4vdmVyc2lvblwiKTtcblxuICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBpc1ZpcnR1YWxOb2RlO1xuXG4gICAgICAgICAgICBmdW5jdGlvbiBpc1ZpcnR1YWxOb2RlKHgpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4geCAmJiB4LnR5cGUgPT09IFwiVmlydHVhbE5vZGVcIiAmJiB4LnZlcnNpb24gPT09IHZlcnNpb247XG4gICAgICAgICAgICB9XG4gICAgICAgIH0sIHsgXCIuL3ZlcnNpb25cIjogMzAgfV0sIDI4OiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge1xuICAgICAgICAgICAgdmFyIHZlcnNpb24gPSByZXF1aXJlKFwiLi92ZXJzaW9uXCIpO1xuXG4gICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IGlzVmlydHVhbFRleHQ7XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIGlzVmlydHVhbFRleHQoeCkge1xuICAgICAgICAgICAgICAgIHJldHVybiB4ICYmIHgudHlwZSA9PT0gXCJWaXJ0dWFsVGV4dFwiICYmIHgudmVyc2lvbiA9PT0gdmVyc2lvbjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSwgeyBcIi4vdmVyc2lvblwiOiAzMCB9XSwgMjk6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IGlzV2lkZ2V0O1xuXG4gICAgICAgICAgICBmdW5jdGlvbiBpc1dpZGdldCh3KSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHcgJiYgdy50eXBlID09PSBcIldpZGdldFwiO1xuICAgICAgICAgICAgfVxuICAgICAgICB9LCB7fV0sIDMwOiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge1xuICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBcIjJcIjtcbiAgICAgICAgfSwge31dLCAzMTogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHtcbiAgICAgICAgICAgIHZhciB2ZXJzaW9uID0gcmVxdWlyZShcIi4vdmVyc2lvblwiKTtcbiAgICAgICAgICAgIHZhciBpc1ZOb2RlID0gcmVxdWlyZShcIi4vaXMtdm5vZGVcIik7XG4gICAgICAgICAgICB2YXIgaXNXaWRnZXQgPSByZXF1aXJlKFwiLi9pcy13aWRnZXRcIik7XG4gICAgICAgICAgICB2YXIgaXNUaHVuayA9IHJlcXVpcmUoXCIuL2lzLXRodW5rXCIpO1xuICAgICAgICAgICAgdmFyIGlzVkhvb2sgPSByZXF1aXJlKFwiLi9pcy12aG9va1wiKTtcblxuICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBWaXJ0dWFsTm9kZTtcblxuICAgICAgICAgICAgdmFyIG5vUHJvcGVydGllcyA9IHt9O1xuICAgICAgICAgICAgdmFyIG5vQ2hpbGRyZW4gPSBbXTtcblxuICAgICAgICAgICAgZnVuY3Rpb24gVmlydHVhbE5vZGUodGFnTmFtZSwgcHJvcGVydGllcywgY2hpbGRyZW4sIGtleSwgbmFtZXNwYWNlKSB7XG4gICAgICAgICAgICAgICAgdGhpcy50YWdOYW1lID0gdGFnTmFtZTtcbiAgICAgICAgICAgICAgICB0aGlzLnByb3BlcnRpZXMgPSBwcm9wZXJ0aWVzIHx8IG5vUHJvcGVydGllcztcbiAgICAgICAgICAgICAgICB0aGlzLmNoaWxkcmVuID0gY2hpbGRyZW4gfHwgbm9DaGlsZHJlbjtcbiAgICAgICAgICAgICAgICB0aGlzLmtleSA9IGtleSAhPSBudWxsID8gU3RyaW5nKGtleSkgOiB1bmRlZmluZWQ7XG4gICAgICAgICAgICAgICAgdGhpcy5uYW1lc3BhY2UgPSB0eXBlb2YgbmFtZXNwYWNlID09PSBcInN0cmluZ1wiID8gbmFtZXNwYWNlIDogbnVsbDtcblxuICAgICAgICAgICAgICAgIHZhciBjb3VudCA9IGNoaWxkcmVuICYmIGNoaWxkcmVuLmxlbmd0aCB8fCAwO1xuICAgICAgICAgICAgICAgIHZhciBkZXNjZW5kYW50cyA9IDA7XG4gICAgICAgICAgICAgICAgdmFyIGhhc1dpZGdldHMgPSBmYWxzZTtcbiAgICAgICAgICAgICAgICB2YXIgaGFzVGh1bmtzID0gZmFsc2U7XG4gICAgICAgICAgICAgICAgdmFyIGRlc2NlbmRhbnRIb29rcyA9IGZhbHNlO1xuICAgICAgICAgICAgICAgIHZhciBob29rcztcblxuICAgICAgICAgICAgICAgIGZvciAodmFyIHByb3BOYW1lIGluIHByb3BlcnRpZXMpIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKHByb3BlcnRpZXMuaGFzT3duUHJvcGVydHkocHJvcE5hbWUpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICB2YXIgcHJvcGVydHkgPSBwcm9wZXJ0aWVzW3Byb3BOYW1lXTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChpc1ZIb29rKHByb3BlcnR5KSAmJiBwcm9wZXJ0eS51bmhvb2spIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoIWhvb2tzKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGhvb2tzID0ge307XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaG9va3NbcHJvcE5hbWVdID0gcHJvcGVydHk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IGNvdW50OyBpKyspIHtcbiAgICAgICAgICAgICAgICAgICAgdmFyIGNoaWxkID0gY2hpbGRyZW5baV07XG4gICAgICAgICAgICAgICAgICAgIGlmIChpc1ZOb2RlKGNoaWxkKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgZGVzY2VuZGFudHMgKz0gY2hpbGQuY291bnQgfHwgMDtcblxuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKCFoYXNXaWRnZXRzICYmIGNoaWxkLmhhc1dpZGdldHMpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBoYXNXaWRnZXRzID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKCFoYXNUaHVua3MgJiYgY2hpbGQuaGFzVGh1bmtzKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaGFzVGh1bmtzID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKCFkZXNjZW5kYW50SG9va3MgJiYgKGNoaWxkLmhvb2tzIHx8IGNoaWxkLmRlc2NlbmRhbnRIb29rcykpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBkZXNjZW5kYW50SG9va3MgPSB0cnVlO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKCFoYXNXaWRnZXRzICYmIGlzV2lkZ2V0KGNoaWxkKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHR5cGVvZiBjaGlsZC5kZXN0cm95ID09PSBcImZ1bmN0aW9uXCIpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBoYXNXaWRnZXRzID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIGlmICghaGFzVGh1bmtzICYmIGlzVGh1bmsoY2hpbGQpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBoYXNUaHVua3MgPSB0cnVlO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgdGhpcy5jb3VudCA9IGNvdW50ICsgZGVzY2VuZGFudHM7XG4gICAgICAgICAgICAgICAgdGhpcy5oYXNXaWRnZXRzID0gaGFzV2lkZ2V0cztcbiAgICAgICAgICAgICAgICB0aGlzLmhhc1RodW5rcyA9IGhhc1RodW5rcztcbiAgICAgICAgICAgICAgICB0aGlzLmhvb2tzID0gaG9va3M7XG4gICAgICAgICAgICAgICAgdGhpcy5kZXNjZW5kYW50SG9va3MgPSBkZXNjZW5kYW50SG9va3M7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIFZpcnR1YWxOb2RlLnByb3RvdHlwZS52ZXJzaW9uID0gdmVyc2lvbjtcbiAgICAgICAgICAgIFZpcnR1YWxOb2RlLnByb3RvdHlwZS50eXBlID0gXCJWaXJ0dWFsTm9kZVwiO1xuICAgICAgICB9LCB7IFwiLi9pcy10aHVua1wiOiAyNSwgXCIuL2lzLXZob29rXCI6IDI2LCBcIi4vaXMtdm5vZGVcIjogMjcsIFwiLi9pcy13aWRnZXRcIjogMjksIFwiLi92ZXJzaW9uXCI6IDMwIH1dLCAzMjogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHtcbiAgICAgICAgICAgIHZhciB2ZXJzaW9uID0gcmVxdWlyZShcIi4vdmVyc2lvblwiKTtcblxuICAgICAgICAgICAgVmlydHVhbFBhdGNoLk5PTkUgPSAwO1xuICAgICAgICAgICAgVmlydHVhbFBhdGNoLlZURVhUID0gMTtcbiAgICAgICAgICAgIFZpcnR1YWxQYXRjaC5WTk9ERSA9IDI7XG4gICAgICAgICAgICBWaXJ0dWFsUGF0Y2guV0lER0VUID0gMztcbiAgICAgICAgICAgIFZpcnR1YWxQYXRjaC5QUk9QUyA9IDQ7XG4gICAgICAgICAgICBWaXJ0dWFsUGF0Y2guT1JERVIgPSA1O1xuICAgICAgICAgICAgVmlydHVhbFBhdGNoLklOU0VSVCA9IDY7XG4gICAgICAgICAgICBWaXJ0dWFsUGF0Y2guUkVNT1ZFID0gNztcbiAgICAgICAgICAgIFZpcnR1YWxQYXRjaC5USFVOSyA9IDg7XG5cbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gVmlydHVhbFBhdGNoO1xuXG4gICAgICAgICAgICBmdW5jdGlvbiBWaXJ0dWFsUGF0Y2godHlwZSwgdk5vZGUsIHBhdGNoKSB7XG4gICAgICAgICAgICAgICAgdGhpcy50eXBlID0gTnVtYmVyKHR5cGUpO1xuICAgICAgICAgICAgICAgIHRoaXMudk5vZGUgPSB2Tm9kZTtcbiAgICAgICAgICAgICAgICB0aGlzLnBhdGNoID0gcGF0Y2g7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIFZpcnR1YWxQYXRjaC5wcm90b3R5cGUudmVyc2lvbiA9IHZlcnNpb247XG4gICAgICAgICAgICBWaXJ0dWFsUGF0Y2gucHJvdG90eXBlLnR5cGUgPSBcIlZpcnR1YWxQYXRjaFwiO1xuICAgICAgICB9LCB7IFwiLi92ZXJzaW9uXCI6IDMwIH1dLCAzMzogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHtcbiAgICAgICAgICAgIHZhciB2ZXJzaW9uID0gcmVxdWlyZShcIi4vdmVyc2lvblwiKTtcblxuICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBWaXJ0dWFsVGV4dDtcblxuICAgICAgICAgICAgZnVuY3Rpb24gVmlydHVhbFRleHQodGV4dCkge1xuICAgICAgICAgICAgICAgIHRoaXMudGV4dCA9IFN0cmluZyh0ZXh0KTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgVmlydHVhbFRleHQucHJvdG90eXBlLnZlcnNpb24gPSB2ZXJzaW9uO1xuICAgICAgICAgICAgVmlydHVhbFRleHQucHJvdG90eXBlLnR5cGUgPSBcIlZpcnR1YWxUZXh0XCI7XG4gICAgICAgIH0sIHsgXCIuL3ZlcnNpb25cIjogMzAgfV0sIDM0OiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge1xuICAgICAgICAgICAgdmFyIGlzT2JqZWN0ID0gcmVxdWlyZShcImlzLW9iamVjdFwiKTtcbiAgICAgICAgICAgIHZhciBpc0hvb2sgPSByZXF1aXJlKFwiLi4vdm5vZGUvaXMtdmhvb2tcIik7XG5cbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gZGlmZlByb3BzO1xuXG4gICAgICAgICAgICBmdW5jdGlvbiBkaWZmUHJvcHMoYSwgYikge1xuICAgICAgICAgICAgICAgIHZhciBkaWZmO1xuXG4gICAgICAgICAgICAgICAgZm9yICh2YXIgYUtleSBpbiBhKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmICghKGFLZXkgaW4gYikpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGRpZmYgPSBkaWZmIHx8IHt9O1xuICAgICAgICAgICAgICAgICAgICAgICAgZGlmZlthS2V5XSA9IHVuZGVmaW5lZDtcbiAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgIHZhciBhVmFsdWUgPSBhW2FLZXldO1xuICAgICAgICAgICAgICAgICAgICB2YXIgYlZhbHVlID0gYlthS2V5XTtcblxuICAgICAgICAgICAgICAgICAgICBpZiAoYVZhbHVlID09PSBiVmFsdWUpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnRpbnVlO1xuICAgICAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKGlzT2JqZWN0KGFWYWx1ZSkgJiYgaXNPYmplY3QoYlZhbHVlKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGdldFByb3RvdHlwZShiVmFsdWUpICE9PSBnZXRQcm90b3R5cGUoYVZhbHVlKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRpZmYgPSBkaWZmIHx8IHt9O1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRpZmZbYUtleV0gPSBiVmFsdWU7XG4gICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKGlzSG9vayhiVmFsdWUpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgZGlmZiA9IGRpZmYgfHwge307XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgZGlmZlthS2V5XSA9IGJWYWx1ZTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdmFyIG9iamVjdERpZmYgPSBkaWZmUHJvcHMoYVZhbHVlLCBiVmFsdWUpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChvYmplY3REaWZmKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRpZmYgPSBkaWZmIHx8IHt9O1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBkaWZmW2FLZXldID0gb2JqZWN0RGlmZjtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBkaWZmID0gZGlmZiB8fCB7fTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGRpZmZbYUtleV0gPSBiVmFsdWU7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICBmb3IgKHZhciBiS2V5IGluIGIpIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKCEoYktleSBpbiBhKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgZGlmZiA9IGRpZmYgfHwge307XG4gICAgICAgICAgICAgICAgICAgICAgICBkaWZmW2JLZXldID0gYltiS2V5XTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHJldHVybiBkaWZmO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBmdW5jdGlvbiBnZXRQcm90b3R5cGUodmFsdWUpIHtcbiAgICAgICAgICAgICAgICBpZiAoT2JqZWN0LmdldFByb3RvdHlwZU9mKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBPYmplY3QuZ2V0UHJvdG90eXBlT2YodmFsdWUpO1xuICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAodmFsdWUuX19wcm90b19fKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiB2YWx1ZS5fX3Byb3RvX187XG4gICAgICAgICAgICAgICAgfSBlbHNlIGlmICh2YWx1ZS5jb25zdHJ1Y3Rvcikge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gdmFsdWUuY29uc3RydWN0b3IucHJvdG90eXBlO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgfSwgeyBcIi4uL3Zub2RlL2lzLXZob29rXCI6IDI2LCBcImlzLW9iamVjdFwiOiAxMSB9XSwgMzU6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICB2YXIgaXNBcnJheSA9IHJlcXVpcmUoXCJ4LWlzLWFycmF5XCIpO1xuXG4gICAgICAgICAgICB2YXIgVlBhdGNoID0gcmVxdWlyZShcIi4uL3Zub2RlL3ZwYXRjaFwiKTtcbiAgICAgICAgICAgIHZhciBpc1ZOb2RlID0gcmVxdWlyZShcIi4uL3Zub2RlL2lzLXZub2RlXCIpO1xuICAgICAgICAgICAgdmFyIGlzVlRleHQgPSByZXF1aXJlKFwiLi4vdm5vZGUvaXMtdnRleHRcIik7XG4gICAgICAgICAgICB2YXIgaXNXaWRnZXQgPSByZXF1aXJlKFwiLi4vdm5vZGUvaXMtd2lkZ2V0XCIpO1xuICAgICAgICAgICAgdmFyIGlzVGh1bmsgPSByZXF1aXJlKFwiLi4vdm5vZGUvaXMtdGh1bmtcIik7XG4gICAgICAgICAgICB2YXIgaGFuZGxlVGh1bmsgPSByZXF1aXJlKFwiLi4vdm5vZGUvaGFuZGxlLXRodW5rXCIpO1xuXG4gICAgICAgICAgICB2YXIgZGlmZlByb3BzID0gcmVxdWlyZShcIi4vZGlmZi1wcm9wc1wiKTtcblxuICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBkaWZmO1xuXG4gICAgICAgICAgICBmdW5jdGlvbiBkaWZmKGEsIGIpIHtcbiAgICAgICAgICAgICAgICB2YXIgcGF0Y2ggPSB7IGE6IGEgfTtcbiAgICAgICAgICAgICAgICB3YWxrKGEsIGIsIHBhdGNoLCAwKTtcbiAgICAgICAgICAgICAgICByZXR1cm4gcGF0Y2g7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIHdhbGsoYSwgYiwgcGF0Y2gsIGluZGV4KSB7XG4gICAgICAgICAgICAgICAgaWYgKGEgPT09IGIpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHZhciBhcHBseSA9IHBhdGNoW2luZGV4XTtcbiAgICAgICAgICAgICAgICB2YXIgYXBwbHlDbGVhciA9IGZhbHNlO1xuXG4gICAgICAgICAgICAgICAgaWYgKGlzVGh1bmsoYSkgfHwgaXNUaHVuayhiKSkge1xuICAgICAgICAgICAgICAgICAgICB0aHVua3MoYSwgYiwgcGF0Y2gsIGluZGV4KTtcbiAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKGIgPT0gbnVsbCkge1xuXG4gICAgICAgICAgICAgICAgICAgIC8vIElmIGEgaXMgYSB3aWRnZXQgd2Ugd2lsbCBhZGQgYSByZW1vdmUgcGF0Y2ggZm9yIGl0XG4gICAgICAgICAgICAgICAgICAgIC8vIE90aGVyd2lzZSBhbnkgY2hpbGQgd2lkZ2V0cy9ob29rcyBtdXN0IGJlIGRlc3Ryb3llZC5cbiAgICAgICAgICAgICAgICAgICAgLy8gVGhpcyBwcmV2ZW50cyBhZGRpbmcgdHdvIHJlbW92ZSBwYXRjaGVzIGZvciBhIHdpZGdldC5cbiAgICAgICAgICAgICAgICAgICAgaWYgKCFpc1dpZGdldChhKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgY2xlYXJTdGF0ZShhLCBwYXRjaCwgaW5kZXgpO1xuICAgICAgICAgICAgICAgICAgICAgICAgYXBwbHkgPSBwYXRjaFtpbmRleF07XG4gICAgICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgICAgICBhcHBseSA9IGFwcGVuZFBhdGNoKGFwcGx5LCBuZXcgVlBhdGNoKFZQYXRjaC5SRU1PVkUsIGEsIGIpKTtcbiAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKGlzVk5vZGUoYikpIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKGlzVk5vZGUoYSkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChhLnRhZ05hbWUgPT09IGIudGFnTmFtZSAmJiBhLm5hbWVzcGFjZSA9PT0gYi5uYW1lc3BhY2UgJiYgYS5rZXkgPT09IGIua2V5KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdmFyIHByb3BzUGF0Y2ggPSBkaWZmUHJvcHMoYS5wcm9wZXJ0aWVzLCBiLnByb3BlcnRpZXMpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChwcm9wc1BhdGNoKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGFwcGx5ID0gYXBwZW5kUGF0Y2goYXBwbHksIG5ldyBWUGF0Y2goVlBhdGNoLlBST1BTLCBhLCBwcm9wc1BhdGNoKSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGFwcGx5ID0gZGlmZkNoaWxkcmVuKGEsIGIsIHBhdGNoLCBhcHBseSwgaW5kZXgpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBhcHBseSA9IGFwcGVuZFBhdGNoKGFwcGx5LCBuZXcgVlBhdGNoKFZQYXRjaC5WTk9ERSwgYSwgYikpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGFwcGx5Q2xlYXIgPSB0cnVlO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgYXBwbHkgPSBhcHBlbmRQYXRjaChhcHBseSwgbmV3IFZQYXRjaChWUGF0Y2guVk5PREUsIGEsIGIpKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGFwcGx5Q2xlYXIgPSB0cnVlO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfSBlbHNlIGlmIChpc1ZUZXh0KGIpKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmICghaXNWVGV4dChhKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgYXBwbHkgPSBhcHBlbmRQYXRjaChhcHBseSwgbmV3IFZQYXRjaChWUGF0Y2guVlRFWFQsIGEsIGIpKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGFwcGx5Q2xlYXIgPSB0cnVlO1xuICAgICAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKGEudGV4dCAhPT0gYi50ZXh0KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBhcHBseSA9IGFwcGVuZFBhdGNoKGFwcGx5LCBuZXcgVlBhdGNoKFZQYXRjaC5WVEVYVCwgYSwgYikpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfSBlbHNlIGlmIChpc1dpZGdldChiKSkge1xuICAgICAgICAgICAgICAgICAgICBpZiAoIWlzV2lkZ2V0KGEpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBhcHBseUNsZWFyID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgIGFwcGx5ID0gYXBwZW5kUGF0Y2goYXBwbHksIG5ldyBWUGF0Y2goVlBhdGNoLldJREdFVCwgYSwgYikpO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIGlmIChhcHBseSkge1xuICAgICAgICAgICAgICAgICAgICBwYXRjaFtpbmRleF0gPSBhcHBseTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICBpZiAoYXBwbHlDbGVhcikge1xuICAgICAgICAgICAgICAgICAgICBjbGVhclN0YXRlKGEsIHBhdGNoLCBpbmRleCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBmdW5jdGlvbiBkaWZmQ2hpbGRyZW4oYSwgYiwgcGF0Y2gsIGFwcGx5LCBpbmRleCkge1xuICAgICAgICAgICAgICAgIHZhciBhQ2hpbGRyZW4gPSBhLmNoaWxkcmVuO1xuICAgICAgICAgICAgICAgIHZhciBvcmRlcmVkU2V0ID0gcmVvcmRlcihhQ2hpbGRyZW4sIGIuY2hpbGRyZW4pO1xuICAgICAgICAgICAgICAgIHZhciBiQ2hpbGRyZW4gPSBvcmRlcmVkU2V0LmNoaWxkcmVuO1xuXG4gICAgICAgICAgICAgICAgdmFyIGFMZW4gPSBhQ2hpbGRyZW4ubGVuZ3RoO1xuICAgICAgICAgICAgICAgIHZhciBiTGVuID0gYkNoaWxkcmVuLmxlbmd0aDtcbiAgICAgICAgICAgICAgICB2YXIgbGVuID0gYUxlbiA+IGJMZW4gPyBhTGVuIDogYkxlbjtcblxuICAgICAgICAgICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgbGVuOyBpKyspIHtcbiAgICAgICAgICAgICAgICAgICAgdmFyIGxlZnROb2RlID0gYUNoaWxkcmVuW2ldO1xuICAgICAgICAgICAgICAgICAgICB2YXIgcmlnaHROb2RlID0gYkNoaWxkcmVuW2ldO1xuICAgICAgICAgICAgICAgICAgICBpbmRleCArPSAxO1xuXG4gICAgICAgICAgICAgICAgICAgIGlmICghbGVmdE5vZGUpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChyaWdodE5vZGUpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBFeGNlc3Mgbm9kZXMgaW4gYiBuZWVkIHRvIGJlIGFkZGVkXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgYXBwbHkgPSBhcHBlbmRQYXRjaChhcHBseSwgbmV3IFZQYXRjaChWUGF0Y2guSU5TRVJULCBudWxsLCByaWdodE5vZGUpKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHdhbGsobGVmdE5vZGUsIHJpZ2h0Tm9kZSwgcGF0Y2gsIGluZGV4KTtcbiAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgIGlmIChpc1ZOb2RlKGxlZnROb2RlKSAmJiBsZWZ0Tm9kZS5jb3VudCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgaW5kZXggKz0gbGVmdE5vZGUuY291bnQ7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICBpZiAob3JkZXJlZFNldC5tb3Zlcykge1xuICAgICAgICAgICAgICAgICAgICAvLyBSZW9yZGVyIG5vZGVzIGxhc3RcbiAgICAgICAgICAgICAgICAgICAgYXBwbHkgPSBhcHBlbmRQYXRjaChhcHBseSwgbmV3IFZQYXRjaChWUGF0Y2guT1JERVIsIGEsIG9yZGVyZWRTZXQubW92ZXMpKTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICByZXR1cm4gYXBwbHk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIGNsZWFyU3RhdGUodk5vZGUsIHBhdGNoLCBpbmRleCkge1xuICAgICAgICAgICAgICAgIC8vIFRPRE86IE1ha2UgdGhpcyBhIHNpbmdsZSB3YWxrLCBub3QgdHdvXG4gICAgICAgICAgICAgICAgdW5ob29rKHZOb2RlLCBwYXRjaCwgaW5kZXgpO1xuICAgICAgICAgICAgICAgIGRlc3Ryb3lXaWRnZXRzKHZOb2RlLCBwYXRjaCwgaW5kZXgpO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAvLyBQYXRjaCByZWNvcmRzIGZvciBhbGwgZGVzdHJveWVkIHdpZGdldHMgbXVzdCBiZSBhZGRlZCBiZWNhdXNlIHdlIG5lZWRcbiAgICAgICAgICAgIC8vIGEgRE9NIG5vZGUgcmVmZXJlbmNlIGZvciB0aGUgZGVzdHJveSBmdW5jdGlvblxuICAgICAgICAgICAgZnVuY3Rpb24gZGVzdHJveVdpZGdldHModk5vZGUsIHBhdGNoLCBpbmRleCkge1xuICAgICAgICAgICAgICAgIGlmIChpc1dpZGdldCh2Tm9kZSkpIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKHR5cGVvZiB2Tm9kZS5kZXN0cm95ID09PSBcImZ1bmN0aW9uXCIpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHBhdGNoW2luZGV4XSA9IGFwcGVuZFBhdGNoKHBhdGNoW2luZGV4XSwgbmV3IFZQYXRjaChWUGF0Y2guUkVNT1ZFLCB2Tm9kZSwgbnVsbCkpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfSBlbHNlIGlmIChpc1ZOb2RlKHZOb2RlKSAmJiAodk5vZGUuaGFzV2lkZ2V0cyB8fCB2Tm9kZS5oYXNUaHVua3MpKSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciBjaGlsZHJlbiA9IHZOb2RlLmNoaWxkcmVuO1xuICAgICAgICAgICAgICAgICAgICB2YXIgbGVuID0gY2hpbGRyZW4ubGVuZ3RoO1xuICAgICAgICAgICAgICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IGxlbjsgaSsrKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICB2YXIgY2hpbGQgPSBjaGlsZHJlbltpXTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGluZGV4ICs9IDE7XG5cbiAgICAgICAgICAgICAgICAgICAgICAgIGRlc3Ryb3lXaWRnZXRzKGNoaWxkLCBwYXRjaCwgaW5kZXgpO1xuXG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoaXNWTm9kZShjaGlsZCkgJiYgY2hpbGQuY291bnQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpbmRleCArPSBjaGlsZC5jb3VudDtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoaXNUaHVuayh2Tm9kZSkpIHtcbiAgICAgICAgICAgICAgICAgICAgdGh1bmtzKHZOb2RlLCBudWxsLCBwYXRjaCwgaW5kZXgpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgLy8gQ3JlYXRlIGEgc3ViLXBhdGNoIGZvciB0aHVua3NcbiAgICAgICAgICAgIGZ1bmN0aW9uIHRodW5rcyhhLCBiLCBwYXRjaCwgaW5kZXgpIHtcbiAgICAgICAgICAgICAgICB2YXIgbm9kZXMgPSBoYW5kbGVUaHVuayhhLCBiKTtcbiAgICAgICAgICAgICAgICB2YXIgdGh1bmtQYXRjaCA9IGRpZmYobm9kZXMuYSwgbm9kZXMuYik7XG4gICAgICAgICAgICAgICAgaWYgKGhhc1BhdGNoZXModGh1bmtQYXRjaCkpIHtcbiAgICAgICAgICAgICAgICAgICAgcGF0Y2hbaW5kZXhdID0gbmV3IFZQYXRjaChWUGF0Y2guVEhVTkssIG51bGwsIHRodW5rUGF0Y2gpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZnVuY3Rpb24gaGFzUGF0Y2hlcyhwYXRjaCkge1xuICAgICAgICAgICAgICAgIGZvciAodmFyIGluZGV4IGluIHBhdGNoKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmIChpbmRleCAhPT0gXCJhXCIpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAvLyBFeGVjdXRlIGhvb2tzIHdoZW4gdHdvIG5vZGVzIGFyZSBpZGVudGljYWxcbiAgICAgICAgICAgIGZ1bmN0aW9uIHVuaG9vayh2Tm9kZSwgcGF0Y2gsIGluZGV4KSB7XG4gICAgICAgICAgICAgICAgaWYgKGlzVk5vZGUodk5vZGUpKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmICh2Tm9kZS5ob29rcykge1xuICAgICAgICAgICAgICAgICAgICAgICAgcGF0Y2hbaW5kZXhdID0gYXBwZW5kUGF0Y2gocGF0Y2hbaW5kZXhdLCBuZXcgVlBhdGNoKFZQYXRjaC5QUk9QUywgdk5vZGUsIHVuZGVmaW5lZEtleXModk5vZGUuaG9va3MpKSk7XG4gICAgICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgICAgICBpZiAodk5vZGUuZGVzY2VuZGFudEhvb2tzIHx8IHZOb2RlLmhhc1RodW5rcykge1xuICAgICAgICAgICAgICAgICAgICAgICAgdmFyIGNoaWxkcmVuID0gdk5vZGUuY2hpbGRyZW47XG4gICAgICAgICAgICAgICAgICAgICAgICB2YXIgbGVuID0gY2hpbGRyZW4ubGVuZ3RoO1xuICAgICAgICAgICAgICAgICAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCBsZW47IGkrKykge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZhciBjaGlsZCA9IGNoaWxkcmVuW2ldO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGluZGV4ICs9IDE7XG5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB1bmhvb2soY2hpbGQsIHBhdGNoLCBpbmRleCk7XG5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoaXNWTm9kZShjaGlsZCkgJiYgY2hpbGQuY291bnQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaW5kZXggKz0gY2hpbGQuY291bnQ7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfSBlbHNlIGlmIChpc1RodW5rKHZOb2RlKSkge1xuICAgICAgICAgICAgICAgICAgICB0aHVua3Modk5vZGUsIG51bGwsIHBhdGNoLCBpbmRleCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBmdW5jdGlvbiB1bmRlZmluZWRLZXlzKG9iaikge1xuICAgICAgICAgICAgICAgIHZhciByZXN1bHQgPSB7fTtcblxuICAgICAgICAgICAgICAgIGZvciAodmFyIGtleSBpbiBvYmopIHtcbiAgICAgICAgICAgICAgICAgICAgcmVzdWx0W2tleV0gPSB1bmRlZmluZWQ7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgcmV0dXJuIHJlc3VsdDtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgLy8gTGlzdCBkaWZmLCBuYWl2ZSBsZWZ0IHRvIHJpZ2h0IHJlb3JkZXJpbmdcbiAgICAgICAgICAgIGZ1bmN0aW9uIHJlb3JkZXIoYUNoaWxkcmVuLCBiQ2hpbGRyZW4pIHtcbiAgICAgICAgICAgICAgICAvLyBPKE0pIHRpbWUsIE8oTSkgbWVtb3J5XG4gICAgICAgICAgICAgICAgdmFyIGJDaGlsZEluZGV4ID0ga2V5SW5kZXgoYkNoaWxkcmVuKTtcbiAgICAgICAgICAgICAgICB2YXIgYktleXMgPSBiQ2hpbGRJbmRleC5rZXlzO1xuICAgICAgICAgICAgICAgIHZhciBiRnJlZSA9IGJDaGlsZEluZGV4LmZyZWU7XG5cbiAgICAgICAgICAgICAgICBpZiAoYkZyZWUubGVuZ3RoID09PSBiQ2hpbGRyZW4ubGVuZ3RoKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiB7XG4gICAgICAgICAgICAgICAgICAgICAgICBjaGlsZHJlbjogYkNoaWxkcmVuLFxuICAgICAgICAgICAgICAgICAgICAgICAgbW92ZXM6IG51bGxcbiAgICAgICAgICAgICAgICAgICAgfTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAvLyBPKE4pIHRpbWUsIE8oTikgbWVtb3J5XG4gICAgICAgICAgICAgICAgdmFyIGFDaGlsZEluZGV4ID0ga2V5SW5kZXgoYUNoaWxkcmVuKTtcbiAgICAgICAgICAgICAgICB2YXIgYUtleXMgPSBhQ2hpbGRJbmRleC5rZXlzO1xuICAgICAgICAgICAgICAgIHZhciBhRnJlZSA9IGFDaGlsZEluZGV4LmZyZWU7XG5cbiAgICAgICAgICAgICAgICBpZiAoYUZyZWUubGVuZ3RoID09PSBhQ2hpbGRyZW4ubGVuZ3RoKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiB7XG4gICAgICAgICAgICAgICAgICAgICAgICBjaGlsZHJlbjogYkNoaWxkcmVuLFxuICAgICAgICAgICAgICAgICAgICAgICAgbW92ZXM6IG51bGxcbiAgICAgICAgICAgICAgICAgICAgfTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAvLyBPKE1BWChOLCBNKSkgbWVtb3J5XG4gICAgICAgICAgICAgICAgdmFyIG5ld0NoaWxkcmVuID0gW107XG5cbiAgICAgICAgICAgICAgICB2YXIgZnJlZUluZGV4ID0gMDtcbiAgICAgICAgICAgICAgICB2YXIgZnJlZUNvdW50ID0gYkZyZWUubGVuZ3RoO1xuICAgICAgICAgICAgICAgIHZhciBkZWxldGVkSXRlbXMgPSAwO1xuXG4gICAgICAgICAgICAgICAgLy8gSXRlcmF0ZSB0aHJvdWdoIGEgYW5kIG1hdGNoIGEgbm9kZSBpbiBiXG4gICAgICAgICAgICAgICAgLy8gTyhOKSB0aW1lLFxuICAgICAgICAgICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgYUNoaWxkcmVuLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciBhSXRlbSA9IGFDaGlsZHJlbltpXTtcbiAgICAgICAgICAgICAgICAgICAgdmFyIGl0ZW1JbmRleDtcblxuICAgICAgICAgICAgICAgICAgICBpZiAoYUl0ZW0ua2V5KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoYktleXMuaGFzT3duUHJvcGVydHkoYUl0ZW0ua2V5KSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIE1hdGNoIHVwIHRoZSBvbGQga2V5c1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGl0ZW1JbmRleCA9IGJLZXlzW2FJdGVtLmtleV07XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgbmV3Q2hpbGRyZW4ucHVzaChiQ2hpbGRyZW5baXRlbUluZGV4XSk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIFJlbW92ZSBvbGQga2V5ZWQgaXRlbXNcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpdGVtSW5kZXggPSBpIC0gZGVsZXRlZEl0ZW1zKys7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgbmV3Q2hpbGRyZW4ucHVzaChudWxsKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIE1hdGNoIHRoZSBpdGVtIGluIGEgd2l0aCB0aGUgbmV4dCBmcmVlIGl0ZW0gaW4gYlxuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGZyZWVJbmRleCA8IGZyZWVDb3VudCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGl0ZW1JbmRleCA9IGJGcmVlW2ZyZWVJbmRleCsrXTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBuZXdDaGlsZHJlbi5wdXNoKGJDaGlsZHJlbltpdGVtSW5kZXhdKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gVGhlcmUgYXJlIG5vIGZyZWUgaXRlbXMgaW4gYiB0byBtYXRjaCB3aXRoXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gdGhlIGZyZWUgaXRlbXMgaW4gYSwgc28gdGhlIGV4dHJhIGZyZWUgbm9kZXNcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBhcmUgZGVsZXRlZC5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpdGVtSW5kZXggPSBpIC0gZGVsZXRlZEl0ZW1zKys7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgbmV3Q2hpbGRyZW4ucHVzaChudWxsKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHZhciBsYXN0RnJlZUluZGV4ID0gZnJlZUluZGV4ID49IGJGcmVlLmxlbmd0aCA/IGJDaGlsZHJlbi5sZW5ndGggOiBiRnJlZVtmcmVlSW5kZXhdO1xuXG4gICAgICAgICAgICAgICAgLy8gSXRlcmF0ZSB0aHJvdWdoIGIgYW5kIGFwcGVuZCBhbnkgbmV3IGtleXNcbiAgICAgICAgICAgICAgICAvLyBPKE0pIHRpbWVcbiAgICAgICAgICAgICAgICBmb3IgKHZhciBqID0gMDsgaiA8IGJDaGlsZHJlbi5sZW5ndGg7IGorKykge1xuICAgICAgICAgICAgICAgICAgICB2YXIgbmV3SXRlbSA9IGJDaGlsZHJlbltqXTtcblxuICAgICAgICAgICAgICAgICAgICBpZiAobmV3SXRlbS5rZXkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmICghYUtleXMuaGFzT3duUHJvcGVydHkobmV3SXRlbS5rZXkpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gQWRkIGFueSBuZXcga2V5ZWQgaXRlbXNcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBXZSBhcmUgYWRkaW5nIG5ldyBpdGVtcyB0byB0aGUgZW5kIGFuZCB0aGVuIHNvcnRpbmcgdGhlbVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIGluIHBsYWNlLiBJbiBmdXR1cmUgd2Ugc2hvdWxkIGluc2VydCBuZXcgaXRlbXMgaW4gcGxhY2UuXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgbmV3Q2hpbGRyZW4ucHVzaChuZXdJdGVtKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIGlmIChqID49IGxhc3RGcmVlSW5kZXgpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIEFkZCBhbnkgbGVmdG92ZXIgbm9uLWtleWVkIGl0ZW1zXG4gICAgICAgICAgICAgICAgICAgICAgICBuZXdDaGlsZHJlbi5wdXNoKG5ld0l0ZW0pO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgdmFyIHNpbXVsYXRlID0gbmV3Q2hpbGRyZW4uc2xpY2UoKTtcbiAgICAgICAgICAgICAgICB2YXIgc2ltdWxhdGVJbmRleCA9IDA7XG4gICAgICAgICAgICAgICAgdmFyIHJlbW92ZXMgPSBbXTtcbiAgICAgICAgICAgICAgICB2YXIgaW5zZXJ0cyA9IFtdO1xuICAgICAgICAgICAgICAgIHZhciBzaW11bGF0ZUl0ZW07XG5cbiAgICAgICAgICAgICAgICBmb3IgKHZhciBrID0gMDsgayA8IGJDaGlsZHJlbi5sZW5ndGg7KSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciB3YW50ZWRJdGVtID0gYkNoaWxkcmVuW2tdO1xuICAgICAgICAgICAgICAgICAgICBzaW11bGF0ZUl0ZW0gPSBzaW11bGF0ZVtzaW11bGF0ZUluZGV4XTtcblxuICAgICAgICAgICAgICAgICAgICAvLyByZW1vdmUgaXRlbXNcbiAgICAgICAgICAgICAgICAgICAgd2hpbGUgKHNpbXVsYXRlSXRlbSA9PT0gbnVsbCAmJiBzaW11bGF0ZS5sZW5ndGgpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJlbW92ZXMucHVzaChyZW1vdmUoc2ltdWxhdGUsIHNpbXVsYXRlSW5kZXgsIG51bGwpKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIHNpbXVsYXRlSXRlbSA9IHNpbXVsYXRlW3NpbXVsYXRlSW5kZXhdO1xuICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgaWYgKCFzaW11bGF0ZUl0ZW0gfHwgc2ltdWxhdGVJdGVtLmtleSAhPT0gd2FudGVkSXRlbS5rZXkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIGlmIHdlIG5lZWQgYSBrZXkgaW4gdGhpcyBwb3NpdGlvbi4uLlxuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHdhbnRlZEl0ZW0ua2V5KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHNpbXVsYXRlSXRlbSAmJiBzaW11bGF0ZUl0ZW0ua2V5KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIGlmIGFuIGluc2VydCBkb2Vzbid0IHB1dCB0aGlzIGtleSBpbiBwbGFjZSwgaXQgbmVlZHMgdG8gbW92ZVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoYktleXNbc2ltdWxhdGVJdGVtLmtleV0gIT09IGsgKyAxKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICByZW1vdmVzLnB1c2gocmVtb3ZlKHNpbXVsYXRlLCBzaW11bGF0ZUluZGV4LCBzaW11bGF0ZUl0ZW0ua2V5KSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzaW11bGF0ZUl0ZW0gPSBzaW11bGF0ZVtzaW11bGF0ZUluZGV4XTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIGlmIHRoZSByZW1vdmUgZGlkbid0IHB1dCB0aGUgd2FudGVkIGl0ZW0gaW4gcGxhY2UsIHdlIG5lZWQgdG8gaW5zZXJ0IGl0XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoIXNpbXVsYXRlSXRlbSB8fCBzaW11bGF0ZUl0ZW0ua2V5ICE9PSB3YW50ZWRJdGVtLmtleSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGluc2VydHMucHVzaCh7IGtleTogd2FudGVkSXRlbS5rZXksIHRvOiBrIH0pO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gaXRlbXMgYXJlIG1hdGNoaW5nLCBzbyBza2lwIGFoZWFkXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzaW11bGF0ZUluZGV4Kys7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpbnNlcnRzLnB1c2goeyBrZXk6IHdhbnRlZEl0ZW0ua2V5LCB0bzogayB9KTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGluc2VydHMucHVzaCh7IGtleTogd2FudGVkSXRlbS5rZXksIHRvOiBrIH0pO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBrKys7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAvLyBhIGtleSBpbiBzaW11bGF0ZSBoYXMgbm8gbWF0Y2hpbmcgd2FudGVkIGtleSwgcmVtb3ZlIGl0XG4gICAgICAgICAgICAgICAgICAgICAgICBlbHNlIGlmIChzaW11bGF0ZUl0ZW0gJiYgc2ltdWxhdGVJdGVtLmtleSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlbW92ZXMucHVzaChyZW1vdmUoc2ltdWxhdGUsIHNpbXVsYXRlSW5kZXgsIHNpbXVsYXRlSXRlbS5rZXkpKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHNpbXVsYXRlSW5kZXgrKztcbiAgICAgICAgICAgICAgICAgICAgICAgIGsrKztcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIC8vIHJlbW92ZSBhbGwgdGhlIHJlbWFpbmluZyBub2RlcyBmcm9tIHNpbXVsYXRlXG4gICAgICAgICAgICAgICAgd2hpbGUgKHNpbXVsYXRlSW5kZXggPCBzaW11bGF0ZS5sZW5ndGgpIHtcbiAgICAgICAgICAgICAgICAgICAgc2ltdWxhdGVJdGVtID0gc2ltdWxhdGVbc2ltdWxhdGVJbmRleF07XG4gICAgICAgICAgICAgICAgICAgIHJlbW92ZXMucHVzaChyZW1vdmUoc2ltdWxhdGUsIHNpbXVsYXRlSW5kZXgsIHNpbXVsYXRlSXRlbSAmJiBzaW11bGF0ZUl0ZW0ua2V5KSk7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgLy8gSWYgdGhlIG9ubHkgbW92ZXMgd2UgaGF2ZSBhcmUgZGVsZXRlcyB0aGVuIHdlIGNhbiBqdXN0XG4gICAgICAgICAgICAgICAgLy8gbGV0IHRoZSBkZWxldGUgcGF0Y2ggcmVtb3ZlIHRoZXNlIGl0ZW1zLlxuICAgICAgICAgICAgICAgIGlmIChyZW1vdmVzLmxlbmd0aCA9PT0gZGVsZXRlZEl0ZW1zICYmICFpbnNlcnRzLmxlbmd0aCkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgICAgICAgICAgICAgY2hpbGRyZW46IG5ld0NoaWxkcmVuLFxuICAgICAgICAgICAgICAgICAgICAgICAgbW92ZXM6IG51bGxcbiAgICAgICAgICAgICAgICAgICAgfTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgICAgICAgICBjaGlsZHJlbjogbmV3Q2hpbGRyZW4sXG4gICAgICAgICAgICAgICAgICAgIG1vdmVzOiB7XG4gICAgICAgICAgICAgICAgICAgICAgICByZW1vdmVzOiByZW1vdmVzLFxuICAgICAgICAgICAgICAgICAgICAgICAgaW5zZXJ0czogaW5zZXJ0c1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZnVuY3Rpb24gcmVtb3ZlKGFyciwgaW5kZXgsIGtleSkge1xuICAgICAgICAgICAgICAgIGFyci5zcGxpY2UoaW5kZXgsIDEpO1xuXG4gICAgICAgICAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgICAgICAgICAgZnJvbTogaW5kZXgsXG4gICAgICAgICAgICAgICAgICAgIGtleToga2V5XG4gICAgICAgICAgICAgICAgfTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZnVuY3Rpb24ga2V5SW5kZXgoY2hpbGRyZW4pIHtcbiAgICAgICAgICAgICAgICB2YXIga2V5cyA9IHt9O1xuICAgICAgICAgICAgICAgIHZhciBmcmVlID0gW107XG4gICAgICAgICAgICAgICAgdmFyIGxlbmd0aCA9IGNoaWxkcmVuLmxlbmd0aDtcblxuICAgICAgICAgICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgbGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgICAgICAgICAgdmFyIGNoaWxkID0gY2hpbGRyZW5baV07XG5cbiAgICAgICAgICAgICAgICAgICAgaWYgKGNoaWxkLmtleSkge1xuICAgICAgICAgICAgICAgICAgICAgICAga2V5c1tjaGlsZC5rZXldID0gaTtcbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGZyZWUucHVzaChpKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHJldHVybiB7XG4gICAgICAgICAgICAgICAgICAgIGtleXM6IGtleXMsIC8vIEEgaGFzaCBvZiBrZXkgbmFtZSB0byBpbmRleFxuICAgICAgICAgICAgICAgICAgICBmcmVlOiBmcmVlIC8vIEFuIGFycmF5IG9mIHVua2V5ZWQgaXRlbSBpbmRpY2VzXG4gICAgICAgICAgICAgICAgfTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZnVuY3Rpb24gYXBwZW5kUGF0Y2goYXBwbHksIHBhdGNoKSB7XG4gICAgICAgICAgICAgICAgaWYgKGFwcGx5KSB7XG4gICAgICAgICAgICAgICAgICAgIGlmIChpc0FycmF5KGFwcGx5KSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgYXBwbHkucHVzaChwYXRjaCk7XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBhcHBseSA9IFthcHBseSwgcGF0Y2hdO1xuICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGFwcGx5O1xuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBwYXRjaDtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH0sIHsgXCIuLi92bm9kZS9oYW5kbGUtdGh1bmtcIjogMjQsIFwiLi4vdm5vZGUvaXMtdGh1bmtcIjogMjUsIFwiLi4vdm5vZGUvaXMtdm5vZGVcIjogMjcsIFwiLi4vdm5vZGUvaXMtdnRleHRcIjogMjgsIFwiLi4vdm5vZGUvaXMtd2lkZ2V0XCI6IDI5LCBcIi4uL3Zub2RlL3ZwYXRjaFwiOiAzMiwgXCIuL2RpZmYtcHJvcHNcIjogMzQsIFwieC1pcy1hcnJheVwiOiAxMiB9XSB9LCB7fSwgWzRdKSg0KTtcbn0pO1xuXG5jb25zdCBzdGFydCA9IGZ1bmN0aW9uIChkb21Sb290LCByZW5kZXJGbiwgaW5pdGlhbFN0YXRlLCBvcHRpb25zID0gW10pIHtcbiAgbGV0IHBpZCA9IHNlbGYucHJvY2Vzc2VzLnNwYXduKCk7XG5cbiAgaWYgKEtleXdvcmQuaGFzX2tleV9fcW1fXyhvcHRpb25zLCBLZXJuZWwuU3BlY2lhbEZvcm1zLmF0b20oJ25hbWUnKSkpIHtcbiAgICBwaWQgPSBzZWxmLnByb2Nlc3Nlcy5yZWdpc3RlcihLZXl3b3JkLmdldChvcHRpb25zLCBLZXJuZWwuU3BlY2lhbEZvcm1zLmF0b20oJ25hbWUnKSksIHBpZCk7XG4gIH1cblxuICBjb25zdCB0cmVlID0gcmVuZGVyRm4uYXBwbHkodGhpcywgaW5pdGlhbFN0YXRlKTtcbiAgY29uc3Qgcm9vdE5vZGUgPSBWaXJ0dWFsRE9NLmNyZWF0ZSh0cmVlKTtcblxuICBkb21Sb290LmFwcGVuZENoaWxkKHJvb3ROb2RlKTtcblxuICBzZWxmLnByb2Nlc3Nlcy5wdXQocGlkLCAnc3RhdGUnLCBLZXJuZWwuU3BlY2lhbEZvcm1zLnR1cGxlKHJvb3ROb2RlLCB0cmVlLCByZW5kZXJGbikpO1xuICByZXR1cm4gS2VybmVsLlNwZWNpYWxGb3Jtcy50dXBsZShLZXJuZWwuU3BlY2lhbEZvcm1zLmF0b20oJ29rJyksIHBpZCk7XG59O1xuXG5jb25zdCBzdG9wID0gZnVuY3Rpb24gKGFnZW50LCB0aW1lb3V0ID0gNTAwMCkge1xuICBzZWxmLnByb2Nlc3Nlcy5leGl0KGFnZW50KTtcbiAgcmV0dXJuIEtlcm5lbC5TcGVjaWFsRm9ybXMuYXRvbSgnb2snKTtcbn07XG5cbmNvbnN0IHJlbmRlciA9IGZ1bmN0aW9uIChhZ2VudCwgc3RhdGUpIHtcblxuICBjb25zdCBjdXJyZW50X3N0YXRlID0gc2VsZi5wcm9jZXNzZXMuZ2V0KGFnZW50LCAnc3RhdGUnKTtcblxuICBsZXQgcm9vdE5vZGUgPSBLZXJuZWwuZWxlbShjdXJyZW50X3N0YXRlLCAwKTtcbiAgbGV0IHRyZWUgPSBLZXJuZWwuZWxlbShjdXJyZW50X3N0YXRlLCAxKTtcbiAgbGV0IHJlbmRlckZuID0gS2VybmVsLmVsZW0oY3VycmVudF9zdGF0ZSwgMik7XG5cbiAgbGV0IG5ld1RyZWUgPSByZW5kZXJGbi5hcHBseSh0aGlzLCBzdGF0ZSk7XG5cbiAgbGV0IHBhdGNoZXMgPSBWaXJ0dWFsRE9NLmRpZmYodHJlZSwgbmV3VHJlZSk7XG4gIHJvb3ROb2RlID0gVmlydHVhbERPTS5wYXRjaChyb290Tm9kZSwgcGF0Y2hlcyk7XG5cbiAgc2VsZi5wcm9jZXNzZXMucHV0KGFnZW50LCAnc3RhdGUnLCBLZXJuZWwuU3BlY2lhbEZvcm1zLnR1cGxlKHJvb3ROb2RlLCBuZXdUcmVlLCByZW5kZXJGbikpO1xuXG4gIHJldHVybiBLZXJuZWwuU3BlY2lhbEZvcm1zLmF0b20oJ29rJyk7XG59O1xuXG52YXIgdmlldyA9IHtcbiAgc3RhcnQsXG4gIHN0b3AsXG4gIHJlbmRlclxufTtcblxuc2VsZi5wcm9jZXNzZXMgPSBzZWxmLnByb2Nlc3NlcyB8fCBuZXcgUHJvY2Vzc1N5c3RlbSgpO1xuXG5leHBvcnQgeyBDb3JlLCBQYXR0ZXJucywgQml0U3RyaW5nLCBLZXJuZWwsIEF0b20sIEVudW0sIEludGVnZXIsIGpzIGFzIEpTLCBMaXN0LCBSYW5nZSwgVHVwbGUsIEFnZW50LCBLZXl3b3JkLCBiYXNlIGFzIEJhc2UsIFN0cmluZyQxIGFzIFN0cmluZywgYml0d2lzZSBhcyBCaXR3aXNlLCBFbnVtZXJhYmxlLCBDb2xsZWN0YWJsZSwgSW5zcGVjdCwgbWFwIGFzIE1hcCwgc2V0IGFzIFNldCwgTWFwU2V0LCBJbnRlZ2VyVHlwZSwgRmxvYXRUeXBlLCBWaXJ0dWFsRE9NLCB2aWV3IGFzIFZpZXcgfTsiXSwiZmlsZSI6ImVsaXhpci5qcyIsInNvdXJjZVJvb3QiOiIvc291cmNlLyJ9 \ No newline at end of file +const Core = C; + +export { Core, Kernel, Atom, Enum, Integer, List, Range, Tuple, Agent, Keyword, base as Base, String$1 as String, bitwise as Bitwise, Enumerable, Collectable, Inspect, map as Map, set as Set, MapSet, VirtualDOM, view as View }; +//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiIiwic291cmNlcyI6WyJlbGl4aXIuanMiXSwic291cmNlc0NvbnRlbnQiOlsiZnVuY3Rpb24gY2FsbF9wcm9wZXJ0eShpdGVtLCBwcm9wZXJ0eSkge1xuICBpZiAocHJvcGVydHkgaW4gaXRlbSkge1xuICAgIGl0ZW1bcHJvcGVydHldO1xuICAgIGlmIChpdGVtW3Byb3BlcnR5XSBpbnN0YW5jZW9mIEZ1bmN0aW9uKSB7XG4gICAgICByZXR1cm4gaXRlbVtwcm9wZXJ0eV0oKTtcbiAgICB9IGVsc2Uge1xuICAgICAgcmV0dXJuIGl0ZW1bcHJvcGVydHldO1xuICAgIH1cbiAgfSBlbHNlIGlmIChTeW1ib2wuZm9yKHByb3BlcnR5KSBpbiBpdGVtKSB7XG4gICAgbGV0IHByb3AgPSBTeW1ib2wuZm9yKHByb3BlcnR5KTtcbiAgICBpZiAoaXRlbVtwcm9wXSBpbnN0YW5jZW9mIEZ1bmN0aW9uKSB7XG4gICAgICByZXR1cm4gaXRlbVtwcm9wXSgpO1xuICAgIH0gZWxzZSB7XG4gICAgICByZXR1cm4gaXRlbVtwcm9wXTtcbiAgICB9XG4gIH1cblxuICB0aHJvdyBuZXcgRXJyb3IoYFByb3BlcnR5ICR7IHByb3BlcnR5IH0gbm90IGZvdW5kIGluICR7IGl0ZW0gfWApO1xufVxuXG5jbGFzcyBUdXBsZSQxIHtcblxuICBjb25zdHJ1Y3RvciguLi5hcmdzKSB7XG4gICAgdGhpcy52YWx1ZXMgPSBPYmplY3QuZnJlZXplKGFyZ3MpO1xuICB9XG5cbiAgZ2V0KGluZGV4KSB7XG4gICAgcmV0dXJuIHRoaXMudmFsdWVzW2luZGV4XTtcbiAgfVxuXG4gIGNvdW50KCkge1xuICAgIHJldHVybiB0aGlzLnZhbHVlcy5sZW5ndGg7XG4gIH1cblxuICBbU3ltYm9sLml0ZXJhdG9yXSgpIHtcbiAgICByZXR1cm4gdGhpcy52YWx1ZXNbU3ltYm9sLml0ZXJhdG9yXSgpO1xuICB9XG5cbiAgdG9TdHJpbmcoKSB7XG4gICAgdmFyIGksXG4gICAgICAgIHMgPSBcIlwiO1xuICAgIGZvciAoaSA9IDA7IGkgPCB0aGlzLnZhbHVlcy5sZW5ndGg7IGkrKykge1xuICAgICAgaWYgKHMgIT09IFwiXCIpIHtcbiAgICAgICAgcyArPSBcIiwgXCI7XG4gICAgICB9XG4gICAgICBzICs9IHRoaXMudmFsdWVzW2ldLnRvU3RyaW5nKCk7XG4gICAgfVxuXG4gICAgcmV0dXJuIFwie1wiICsgcyArIFwifVwiO1xuICB9XG5cbn1cblxubGV0IHByb2Nlc3NfY291bnRlciA9IC0xO1xuXG5jbGFzcyBQSUQge1xuICBjb25zdHJ1Y3RvcigpIHtcbiAgICBwcm9jZXNzX2NvdW50ZXIgPSBwcm9jZXNzX2NvdW50ZXIgKyAxO1xuICAgIHRoaXMuaWQgPSBwcm9jZXNzX2NvdW50ZXI7XG4gIH1cblxuICB0b1N0cmluZygpIHtcbiAgICByZXR1cm4gXCJQSUQjPDAuXCIgKyB0aGlzLmlkICsgXCIuMD5cIjtcbiAgfVxufVxuXG5jbGFzcyBJbnRlZ2VyVHlwZSB7fVxuXG5jbGFzcyBGbG9hdFR5cGUge31cblxuLyogQGZsb3cgKi9cblxuY2xhc3MgVmFyaWFibGUge1xuXG4gIGNvbnN0cnVjdG9yKG5hbWUgPSBudWxsKSB7XG4gICAgdGhpcy5uYW1lID0gbmFtZTtcbiAgfVxufVxuXG5jbGFzcyBXaWxkY2FyZCB7XG4gIGNvbnN0cnVjdG9yKCkge31cbn1cblxuY2xhc3MgU3RhcnRzV2l0aCB7XG5cbiAgY29uc3RydWN0b3IocHJlZml4KSB7XG4gICAgdGhpcy5wcmVmaXggPSBwcmVmaXg7XG4gIH1cbn1cblxuY2xhc3MgQ2FwdHVyZSB7XG5cbiAgY29uc3RydWN0b3IodmFsdWUpIHtcbiAgICB0aGlzLnZhbHVlID0gdmFsdWU7XG4gIH1cbn1cblxuY2xhc3MgSGVhZFRhaWwge1xuICBjb25zdHJ1Y3RvcigpIHt9XG59XG5cbmNsYXNzIFR5cGUge1xuXG4gIGNvbnN0cnVjdG9yKHR5cGUsIG9ialBhdHRlcm4gPSB7fSkge1xuICAgIHRoaXMudHlwZSA9IHR5cGU7XG4gICAgdGhpcy5vYmpQYXR0ZXJuID0gb2JqUGF0dGVybjtcbiAgfVxufVxuXG5jbGFzcyBCb3VuZCB7XG5cbiAgY29uc3RydWN0b3IodmFsdWUpIHtcbiAgICB0aGlzLnZhbHVlID0gdmFsdWU7XG4gIH1cbn1cblxuZnVuY3Rpb24gdmFyaWFibGUobmFtZSA9IG51bGwpIHtcbiAgcmV0dXJuIG5ldyBWYXJpYWJsZShuYW1lKTtcbn1cblxuZnVuY3Rpb24gd2lsZGNhcmQoKSB7XG4gIHJldHVybiBuZXcgV2lsZGNhcmQoKTtcbn1cblxuZnVuY3Rpb24gc3RhcnRzV2l0aChwcmVmaXgpIHtcbiAgcmV0dXJuIG5ldyBTdGFydHNXaXRoKHByZWZpeCk7XG59XG5cbmZ1bmN0aW9uIGNhcHR1cmUodmFsdWUpIHtcbiAgcmV0dXJuIG5ldyBDYXB0dXJlKHZhbHVlKTtcbn1cblxuZnVuY3Rpb24gaGVhZFRhaWwoKSB7XG4gIHJldHVybiBuZXcgSGVhZFRhaWwoKTtcbn1cblxuZnVuY3Rpb24gdHlwZSh0eXBlLCBvYmpQYXR0ZXJuID0ge30pIHtcbiAgcmV0dXJuIG5ldyBUeXBlKHR5cGUsIG9ialBhdHRlcm4pO1xufVxuXG5mdW5jdGlvbiBib3VuZCh2YWx1ZSkge1xuICByZXR1cm4gbmV3IEJvdW5kKHZhbHVlKTtcbn1cblxuZnVuY3Rpb24gaXNfbnVtYmVyJDEodmFsdWUpIHtcbiAgcmV0dXJuIHR5cGVvZiB2YWx1ZSA9PT0gJ251bWJlcic7XG59XG5cbmZ1bmN0aW9uIGlzX3N0cmluZyh2YWx1ZSkge1xuICByZXR1cm4gdHlwZW9mIHZhbHVlID09PSAnc3RyaW5nJztcbn1cblxuZnVuY3Rpb24gaXNfYm9vbGVhbiQxKHZhbHVlKSB7XG4gIHJldHVybiB0eXBlb2YgdmFsdWUgPT09ICdib29sZWFuJztcbn1cblxuZnVuY3Rpb24gaXNfc3ltYm9sKHZhbHVlKSB7XG4gIHJldHVybiB0eXBlb2YgdmFsdWUgPT09ICdzeW1ib2wnO1xufVxuXG5mdW5jdGlvbiBpc19udWxsKHZhbHVlKSB7XG4gIHJldHVybiB2YWx1ZSA9PT0gbnVsbDtcbn1cblxuZnVuY3Rpb24gaXNfdW5kZWZpbmVkKHZhbHVlKSB7XG4gIHJldHVybiB0eXBlb2YgdmFsdWUgPT09ICd1bmRlZmluZWQnO1xufVxuXG5mdW5jdGlvbiBpc19mdW5jdGlvbiQxKHZhbHVlKSB7XG4gIHJldHVybiBPYmplY3QucHJvdG90eXBlLnRvU3RyaW5nLmNhbGwodmFsdWUpID09ICdbb2JqZWN0IEZ1bmN0aW9uXSc7XG59XG5cbmZ1bmN0aW9uIGlzX3ZhcmlhYmxlKHZhbHVlKSB7XG4gIHJldHVybiB2YWx1ZSBpbnN0YW5jZW9mIFZhcmlhYmxlO1xufVxuXG5mdW5jdGlvbiBpc193aWxkY2FyZCh2YWx1ZSkge1xuICByZXR1cm4gdmFsdWUgaW5zdGFuY2VvZiBXaWxkY2FyZDtcbn1cblxuZnVuY3Rpb24gaXNfaGVhZFRhaWwodmFsdWUpIHtcbiAgcmV0dXJuIHZhbHVlIGluc3RhbmNlb2YgSGVhZFRhaWw7XG59XG5cbmZ1bmN0aW9uIGlzX2NhcHR1cmUodmFsdWUpIHtcbiAgcmV0dXJuIHZhbHVlIGluc3RhbmNlb2YgQ2FwdHVyZTtcbn1cblxuZnVuY3Rpb24gaXNfdHlwZSh2YWx1ZSkge1xuICByZXR1cm4gdmFsdWUgaW5zdGFuY2VvZiBUeXBlO1xufVxuXG5mdW5jdGlvbiBpc19zdGFydHNXaXRoKHZhbHVlKSB7XG4gIHJldHVybiB2YWx1ZSBpbnN0YW5jZW9mIFN0YXJ0c1dpdGg7XG59XG5cbmZ1bmN0aW9uIGlzX2JvdW5kKHZhbHVlKSB7XG4gIHJldHVybiB2YWx1ZSBpbnN0YW5jZW9mIEJvdW5kO1xufVxuXG5mdW5jdGlvbiBpc19vYmplY3QodmFsdWUpIHtcbiAgcmV0dXJuIHR5cGVvZiB2YWx1ZSA9PT0gJ29iamVjdCc7XG59XG5cbmZ1bmN0aW9uIGlzX2FycmF5KHZhbHVlKSB7XG4gIHJldHVybiBBcnJheS5pc0FycmF5KHZhbHVlKTtcbn1cblxudmFyIENoZWNrcyA9IHtcbiAgaXNfbnVtYmVyOiBpc19udW1iZXIkMSxcbiAgaXNfc3RyaW5nLFxuICBpc19ib29sZWFuOiBpc19ib29sZWFuJDEsXG4gIGlzX3N5bWJvbCxcbiAgaXNfbnVsbCxcbiAgaXNfdW5kZWZpbmVkLFxuICBpc19mdW5jdGlvbjogaXNfZnVuY3Rpb24kMSxcbiAgaXNfdmFyaWFibGUsXG4gIGlzX3dpbGRjYXJkLFxuICBpc19oZWFkVGFpbCxcbiAgaXNfY2FwdHVyZSxcbiAgaXNfdHlwZSxcbiAgaXNfc3RhcnRzV2l0aCxcbiAgaXNfYm91bmQsXG4gIGlzX29iamVjdCxcbiAgaXNfYXJyYXlcbn07XG5cbmZ1bmN0aW9uIHJlc29sdmVTeW1ib2wocGF0dGVybikge1xuICByZXR1cm4gZnVuY3Rpb24gKHZhbHVlKSB7XG4gICAgcmV0dXJuIENoZWNrcy5pc19zeW1ib2wodmFsdWUpICYmIHZhbHVlID09PSBwYXR0ZXJuO1xuICB9O1xufVxuXG5mdW5jdGlvbiByZXNvbHZlU3RyaW5nKHBhdHRlcm4pIHtcbiAgcmV0dXJuIGZ1bmN0aW9uICh2YWx1ZSkge1xuICAgIHJldHVybiBDaGVja3MuaXNfc3RyaW5nKHZhbHVlKSAmJiB2YWx1ZSA9PT0gcGF0dGVybjtcbiAgfTtcbn1cblxuZnVuY3Rpb24gcmVzb2x2ZU51bWJlcihwYXR0ZXJuKSB7XG4gIHJldHVybiBmdW5jdGlvbiAodmFsdWUpIHtcbiAgICByZXR1cm4gQ2hlY2tzLmlzX251bWJlcih2YWx1ZSkgJiYgdmFsdWUgPT09IHBhdHRlcm47XG4gIH07XG59XG5cbmZ1bmN0aW9uIHJlc29sdmVCb29sZWFuKHBhdHRlcm4pIHtcbiAgcmV0dXJuIGZ1bmN0aW9uICh2YWx1ZSkge1xuICAgIHJldHVybiBDaGVja3MuaXNfYm9vbGVhbih2YWx1ZSkgJiYgdmFsdWUgPT09IHBhdHRlcm47XG4gIH07XG59XG5cbmZ1bmN0aW9uIHJlc29sdmVGdW5jdGlvbihwYXR0ZXJuKSB7XG4gIHJldHVybiBmdW5jdGlvbiAodmFsdWUpIHtcbiAgICByZXR1cm4gQ2hlY2tzLmlzX2Z1bmN0aW9uKHZhbHVlKSAmJiB2YWx1ZSA9PT0gcGF0dGVybjtcbiAgfTtcbn1cblxuZnVuY3Rpb24gcmVzb2x2ZU51bGwocGF0dGVybikge1xuICByZXR1cm4gZnVuY3Rpb24gKHZhbHVlKSB7XG4gICAgcmV0dXJuIENoZWNrcy5pc19udWxsKHZhbHVlKTtcbiAgfTtcbn1cblxuZnVuY3Rpb24gcmVzb2x2ZUJvdW5kKHBhdHRlcm4pIHtcbiAgcmV0dXJuIGZ1bmN0aW9uICh2YWx1ZSwgYXJncykge1xuICAgIGlmICh0eXBlb2YgdmFsdWUgPT09IHR5cGVvZiBwYXR0ZXJuLnZhbHVlICYmIHZhbHVlID09PSBwYXR0ZXJuLnZhbHVlKSB7XG4gICAgICBhcmdzLnB1c2godmFsdWUpO1xuICAgICAgcmV0dXJuIHRydWU7XG4gICAgfVxuXG4gICAgcmV0dXJuIGZhbHNlO1xuICB9O1xufVxuXG5mdW5jdGlvbiByZXNvbHZlV2lsZGNhcmQoKSB7XG4gIHJldHVybiBmdW5jdGlvbiAoKSB7XG4gICAgcmV0dXJuIHRydWU7XG4gIH07XG59XG5cbmZ1bmN0aW9uIHJlc29sdmVWYXJpYWJsZSgpIHtcbiAgcmV0dXJuIGZ1bmN0aW9uICh2YWx1ZSwgYXJncykge1xuICAgIGFyZ3MucHVzaCh2YWx1ZSk7XG4gICAgcmV0dXJuIHRydWU7XG4gIH07XG59XG5cbmZ1bmN0aW9uIHJlc29sdmVIZWFkVGFpbCgpIHtcbiAgcmV0dXJuIGZ1bmN0aW9uICh2YWx1ZSwgYXJncykge1xuICAgIGlmICghQ2hlY2tzLmlzX2FycmF5KHZhbHVlKSB8fCB2YWx1ZS5sZW5ndGggPCAyKSB7XG4gICAgICByZXR1cm4gZmFsc2U7XG4gICAgfVxuXG4gICAgY29uc3QgaGVhZCA9IHZhbHVlWzBdO1xuICAgIGNvbnN0IHRhaWwgPSB2YWx1ZS5zbGljZSgxKTtcblxuICAgIGFyZ3MucHVzaChoZWFkKTtcbiAgICBhcmdzLnB1c2godGFpbCk7XG5cbiAgICByZXR1cm4gdHJ1ZTtcbiAgfTtcbn1cblxuZnVuY3Rpb24gcmVzb2x2ZUNhcHR1cmUocGF0dGVybikge1xuICBjb25zdCBtYXRjaGVzID0gYnVpbGRNYXRjaChwYXR0ZXJuLnZhbHVlKTtcblxuICByZXR1cm4gZnVuY3Rpb24gKHZhbHVlLCBhcmdzKSB7XG4gICAgaWYgKG1hdGNoZXModmFsdWUsIGFyZ3MpKSB7XG4gICAgICBhcmdzLnB1c2godmFsdWUpO1xuICAgICAgcmV0dXJuIHRydWU7XG4gICAgfVxuXG4gICAgcmV0dXJuIGZhbHNlO1xuICB9O1xufVxuXG5mdW5jdGlvbiByZXNvbHZlU3RhcnRzV2l0aChwYXR0ZXJuKSB7XG4gIGNvbnN0IHByZWZpeCA9IHBhdHRlcm4ucHJlZml4O1xuXG4gIHJldHVybiBmdW5jdGlvbiAodmFsdWUsIGFyZ3MpIHtcbiAgICBpZiAoQ2hlY2tzLmlzX3N0cmluZyh2YWx1ZSkgJiYgdmFsdWUuc3RhcnRzV2l0aChwcmVmaXgpKSB7XG4gICAgICBhcmdzLnB1c2godmFsdWUuc3Vic3RyaW5nKHByZWZpeC5sZW5ndGgpKTtcbiAgICAgIHJldHVybiB0cnVlO1xuICAgIH1cblxuICAgIHJldHVybiBmYWxzZTtcbiAgfTtcbn1cblxuZnVuY3Rpb24gcmVzb2x2ZVR5cGUocGF0dGVybikge1xuICByZXR1cm4gZnVuY3Rpb24gKHZhbHVlLCBhcmdzKSB7XG4gICAgaWYgKHZhbHVlIGluc3RhbmNlb2YgcGF0dGVybi50eXBlKSB7XG4gICAgICBjb25zdCBtYXRjaGVzID0gYnVpbGRNYXRjaChwYXR0ZXJuLm9ialBhdHRlcm4pO1xuICAgICAgcmV0dXJuIG1hdGNoZXModmFsdWUsIGFyZ3MpICYmIGFyZ3MucHVzaCh2YWx1ZSkgPiAwO1xuICAgIH1cblxuICAgIHJldHVybiBmYWxzZTtcbiAgfTtcbn1cblxuZnVuY3Rpb24gcmVzb2x2ZUFycmF5KHBhdHRlcm4pIHtcbiAgY29uc3QgbWF0Y2hlcyA9IHBhdHRlcm4ubWFwKHggPT4gYnVpbGRNYXRjaCh4KSk7XG5cbiAgcmV0dXJuIGZ1bmN0aW9uICh2YWx1ZSwgYXJncykge1xuICAgIGlmICghQ2hlY2tzLmlzX2FycmF5KHZhbHVlKSB8fCB2YWx1ZS5sZW5ndGggIT0gcGF0dGVybi5sZW5ndGgpIHtcbiAgICAgIHJldHVybiBmYWxzZTtcbiAgICB9XG5cbiAgICByZXR1cm4gdmFsdWUuZXZlcnkoZnVuY3Rpb24gKHYsIGkpIHtcbiAgICAgIHJldHVybiBtYXRjaGVzW2ldKHZhbHVlW2ldLCBhcmdzKTtcbiAgICB9KTtcbiAgfTtcbn1cblxuZnVuY3Rpb24gcmVzb2x2ZU9iamVjdChwYXR0ZXJuKSB7XG4gIGxldCBtYXRjaGVzID0ge307XG5cbiAgZm9yIChsZXQga2V5IG9mIE9iamVjdC5rZXlzKHBhdHRlcm4pKSB7XG4gICAgbWF0Y2hlc1trZXldID0gYnVpbGRNYXRjaChwYXR0ZXJuW2tleV0pO1xuICB9XG5cbiAgcmV0dXJuIGZ1bmN0aW9uICh2YWx1ZSwgYXJncykge1xuICAgIGlmICghQ2hlY2tzLmlzX29iamVjdCh2YWx1ZSkgfHwgcGF0dGVybi5sZW5ndGggPiB2YWx1ZS5sZW5ndGgpIHtcbiAgICAgIHJldHVybiBmYWxzZTtcbiAgICB9XG5cbiAgICBmb3IgKGxldCBrZXkgb2YgT2JqZWN0LmtleXMocGF0dGVybikpIHtcbiAgICAgIGlmICghKGtleSBpbiB2YWx1ZSkgfHwgIW1hdGNoZXNba2V5XSh2YWx1ZVtrZXldLCBhcmdzKSkge1xuICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICB9XG4gICAgfVxuXG4gICAgcmV0dXJuIHRydWU7XG4gIH07XG59XG5cbmZ1bmN0aW9uIHJlc29sdmVOb01hdGNoKCkge1xuICByZXR1cm4gZnVuY3Rpb24gKCkge1xuICAgIHJldHVybiBmYWxzZTtcbiAgfTtcbn1cblxudmFyIFJlc29sdmVycyA9IHtcbiAgcmVzb2x2ZUJvdW5kLFxuICByZXNvbHZlV2lsZGNhcmQsXG4gIHJlc29sdmVWYXJpYWJsZSxcbiAgcmVzb2x2ZUhlYWRUYWlsLFxuICByZXNvbHZlQ2FwdHVyZSxcbiAgcmVzb2x2ZVN0YXJ0c1dpdGgsXG4gIHJlc29sdmVUeXBlLFxuICByZXNvbHZlQXJyYXksXG4gIHJlc29sdmVPYmplY3QsXG4gIHJlc29sdmVOb01hdGNoLFxuICByZXNvbHZlU3ltYm9sLFxuICByZXNvbHZlU3RyaW5nLFxuICByZXNvbHZlTnVtYmVyLFxuICByZXNvbHZlQm9vbGVhbixcbiAgcmVzb2x2ZUZ1bmN0aW9uLFxuICByZXNvbHZlTnVsbFxufTtcblxuZnVuY3Rpb24gYnVpbGRNYXRjaChwYXR0ZXJuKSB7XG5cbiAgaWYgKENoZWNrcy5pc192YXJpYWJsZShwYXR0ZXJuKSkge1xuICAgIHJldHVybiBSZXNvbHZlcnMucmVzb2x2ZVZhcmlhYmxlKHBhdHRlcm4pO1xuICB9XG5cbiAgaWYgKENoZWNrcy5pc193aWxkY2FyZChwYXR0ZXJuKSkge1xuICAgIHJldHVybiBSZXNvbHZlcnMucmVzb2x2ZVdpbGRjYXJkKHBhdHRlcm4pO1xuICB9XG5cbiAgaWYgKENoZWNrcy5pc191bmRlZmluZWQocGF0dGVybikpIHtcbiAgICByZXR1cm4gUmVzb2x2ZXJzLnJlc29sdmVXaWxkY2FyZChwYXR0ZXJuKTtcbiAgfVxuXG4gIGlmIChDaGVja3MuaXNfaGVhZFRhaWwocGF0dGVybikpIHtcbiAgICByZXR1cm4gUmVzb2x2ZXJzLnJlc29sdmVIZWFkVGFpbChwYXR0ZXJuKTtcbiAgfVxuXG4gIGlmIChDaGVja3MuaXNfc3RhcnRzV2l0aChwYXR0ZXJuKSkge1xuICAgIHJldHVybiBSZXNvbHZlcnMucmVzb2x2ZVN0YXJ0c1dpdGgocGF0dGVybik7XG4gIH1cblxuICBpZiAoQ2hlY2tzLmlzX2NhcHR1cmUocGF0dGVybikpIHtcbiAgICByZXR1cm4gUmVzb2x2ZXJzLnJlc29sdmVDYXB0dXJlKHBhdHRlcm4pO1xuICB9XG5cbiAgaWYgKENoZWNrcy5pc19ib3VuZChwYXR0ZXJuKSkge1xuICAgIHJldHVybiBSZXNvbHZlcnMucmVzb2x2ZUJvdW5kKHBhdHRlcm4pO1xuICB9XG5cbiAgaWYgKENoZWNrcy5pc190eXBlKHBhdHRlcm4pKSB7XG4gICAgcmV0dXJuIFJlc29sdmVycy5yZXNvbHZlVHlwZShwYXR0ZXJuKTtcbiAgfVxuXG4gIGlmIChDaGVja3MuaXNfYXJyYXkocGF0dGVybikpIHtcbiAgICByZXR1cm4gUmVzb2x2ZXJzLnJlc29sdmVBcnJheShwYXR0ZXJuKTtcbiAgfVxuXG4gIGlmIChDaGVja3MuaXNfbnVtYmVyKHBhdHRlcm4pKSB7XG4gICAgcmV0dXJuIFJlc29sdmVycy5yZXNvbHZlTnVtYmVyKHBhdHRlcm4pO1xuICB9XG5cbiAgaWYgKENoZWNrcy5pc19zdHJpbmcocGF0dGVybikpIHtcbiAgICByZXR1cm4gUmVzb2x2ZXJzLnJlc29sdmVTdHJpbmcocGF0dGVybik7XG4gIH1cblxuICBpZiAoQ2hlY2tzLmlzX2Jvb2xlYW4ocGF0dGVybikpIHtcbiAgICByZXR1cm4gUmVzb2x2ZXJzLnJlc29sdmVCb29sZWFuKHBhdHRlcm4pO1xuICB9XG5cbiAgaWYgKENoZWNrcy5pc19zeW1ib2wocGF0dGVybikpIHtcbiAgICByZXR1cm4gUmVzb2x2ZXJzLnJlc29sdmVTeW1ib2wocGF0dGVybik7XG4gIH1cblxuICBpZiAoQ2hlY2tzLmlzX251bGwocGF0dGVybikpIHtcbiAgICByZXR1cm4gUmVzb2x2ZXJzLnJlc29sdmVOdWxsKHBhdHRlcm4pO1xuICB9XG5cbiAgaWYgKENoZWNrcy5pc19vYmplY3QocGF0dGVybikpIHtcbiAgICByZXR1cm4gUmVzb2x2ZXJzLnJlc29sdmVPYmplY3QocGF0dGVybik7XG4gIH1cblxuICByZXR1cm4gUmVzb2x2ZXJzLnJlc29sdmVOb01hdGNoKCk7XG59XG5cbmNsYXNzIE1hdGNoRXJyb3IgZXh0ZW5kcyBFcnJvciB7XG4gIGNvbnN0cnVjdG9yKGFyZykge1xuICAgIHN1cGVyKCk7XG5cbiAgICBpZiAodHlwZW9mIGFyZyA9PT0gJ3N5bWJvbCcpIHtcbiAgICAgIHRoaXMubWVzc2FnZSA9ICdObyBtYXRjaCBmb3I6ICcgKyBhcmcudG9TdHJpbmcoKTtcbiAgICB9IGVsc2UgaWYgKEFycmF5LmlzQXJyYXkoYXJnKSkge1xuICAgICAgbGV0IG1hcHBlZFZhbHVlcyA9IGFyZy5tYXAoeCA9PiB4LnRvU3RyaW5nKCkpO1xuICAgICAgdGhpcy5tZXNzYWdlID0gJ05vIG1hdGNoIGZvcjogJyArIG1hcHBlZFZhbHVlcztcbiAgICB9IGVsc2Uge1xuICAgICAgdGhpcy5tZXNzYWdlID0gJ05vIG1hdGNoIGZvcjogJyArIGFyZztcbiAgICB9XG5cbiAgICB0aGlzLnN0YWNrID0gbmV3IEVycm9yKCkuc3RhY2s7XG4gICAgdGhpcy5uYW1lID0gdGhpcy5jb25zdHJ1Y3Rvci5uYW1lO1xuICB9XG59XG5cbmNsYXNzIENhc2Uge1xuXG4gIGNvbnN0cnVjdG9yKHBhdHRlcm4sIGZuLCBndWFyZCA9ICgpID0+IHRydWUpIHtcbiAgICB0aGlzLnBhdHRlcm4gPSBidWlsZE1hdGNoKHBhdHRlcm4pO1xuICAgIHRoaXMuZm4gPSBmbjtcbiAgICB0aGlzLmd1YXJkID0gZ3VhcmQ7XG4gIH1cbn1cblxuZnVuY3Rpb24gbWFrZV9jYXNlKHBhdHRlcm4sIGZuLCBndWFyZCA9ICgpID0+IHRydWUpIHtcbiAgcmV0dXJuIG5ldyBDYXNlKHBhdHRlcm4sIGZuLCBndWFyZCk7XG59XG5cbmZ1bmN0aW9uIGRlZm1hdGNoKC4uLmNhc2VzKSB7XG4gIHJldHVybiBmdW5jdGlvbiAoLi4uYXJncykge1xuICAgIGZvciAobGV0IHByb2Nlc3NlZENhc2Ugb2YgY2FzZXMpIHtcbiAgICAgIGxldCByZXN1bHQgPSBbXTtcbiAgICAgIGlmIChwcm9jZXNzZWRDYXNlLnBhdHRlcm4oYXJncywgcmVzdWx0KSAmJiBwcm9jZXNzZWRDYXNlLmd1YXJkLmFwcGx5KHRoaXMsIHJlc3VsdCkpIHtcbiAgICAgICAgcmV0dXJuIHByb2Nlc3NlZENhc2UuZm4uYXBwbHkodGhpcywgcmVzdWx0KTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICB0aHJvdyBuZXcgTWF0Y2hFcnJvcihhcmdzKTtcbiAgfTtcbn1cblxuZnVuY3Rpb24gbWF0Y2gocGF0dGVybiwgZXhwciwgZ3VhcmQgPSAoKSA9PiB0cnVlKSB7XG4gIGxldCByZXN1bHQgPSBbXTtcbiAgbGV0IHByb2Nlc3NlZFBhdHRlcm4gPSBidWlsZE1hdGNoKHBhdHRlcm4pO1xuICBpZiAocHJvY2Vzc2VkUGF0dGVybihleHByLCByZXN1bHQpICYmIGd1YXJkLmFwcGx5KHRoaXMsIHJlc3VsdCkpIHtcbiAgICByZXR1cm4gcmVzdWx0O1xuICB9IGVsc2Uge1xuICAgIHRocm93IG5ldyBNYXRjaEVycm9yKGV4cHIpO1xuICB9XG59XG5cbmZ1bmN0aW9uIG1hdGNoX25vX3Rocm93KHBhdHRlcm4sIGV4cHIsIGd1YXJkID0gKCkgPT4gdHJ1ZSkge1xuICB0cnkge1xuICAgIHJldHVybiBtYXRjaChwYXR0ZXJuLCBleHByLCBndWFyZCk7XG4gIH0gY2F0Y2ggKGUpIHtcbiAgICBpZiAoZSBpbnN0YW5jZW9mIE1hdGNoRXJyb3IpIHtcbiAgICAgIHJldHVybiBudWxsO1xuICAgIH1cblxuICAgIHRocm93IGU7XG4gIH1cbn1cblxuY2xhc3MgQml0U3RyaW5nIHtcbiAgY29uc3RydWN0b3IoLi4uYXJncykge1xuICAgIHRoaXMucmF3X3ZhbHVlID0gZnVuY3Rpb24gKCkge1xuICAgICAgcmV0dXJuIE9iamVjdC5mcmVlemUoYXJncyk7XG4gICAgfTtcblxuICAgIHRoaXMudmFsdWUgPSBPYmplY3QuZnJlZXplKHRoaXMucHJvY2VzcyhhcmdzKSk7XG4gIH1cblxuICBnZXQoaW5kZXgpIHtcbiAgICByZXR1cm4gdGhpcy52YWx1ZVtpbmRleF07XG4gIH1cblxuICBjb3VudCgpIHtcbiAgICByZXR1cm4gdGhpcy52YWx1ZS5sZW5ndGg7XG4gIH1cblxuICBbU3ltYm9sLml0ZXJhdG9yXSgpIHtcbiAgICByZXR1cm4gdGhpcy52YWx1ZVtTeW1ib2wuaXRlcmF0b3JdKCk7XG4gIH1cblxuICB0b1N0cmluZygpIHtcbiAgICB2YXIgaSxcbiAgICAgICAgcyA9IFwiXCI7XG4gICAgZm9yIChpID0gMDsgaSA8IHRoaXMuY291bnQoKTsgaSsrKSB7XG4gICAgICBpZiAocyAhPT0gXCJcIikge1xuICAgICAgICBzICs9IFwiLCBcIjtcbiAgICAgIH1cbiAgICAgIHMgKz0gdGhpc1tpXS50b1N0cmluZygpO1xuICAgIH1cblxuICAgIHJldHVybiBcIjw8XCIgKyBzICsgXCI+PlwiO1xuICB9XG5cbiAgcHJvY2VzcygpIHtcbiAgICBsZXQgcHJvY2Vzc2VkX3ZhbHVlcyA9IFtdO1xuXG4gICAgdmFyIGk7XG4gICAgZm9yIChpID0gMDsgaSA8IHRoaXMucmF3X3ZhbHVlKCkubGVuZ3RoOyBpKyspIHtcbiAgICAgIGxldCBwcm9jZXNzZWRfdmFsdWUgPSB0aGlzW1wicHJvY2Vzc19cIiArIHRoaXMucmF3X3ZhbHVlKClbaV0udHlwZV0odGhpcy5yYXdfdmFsdWUoKVtpXSk7XG5cbiAgICAgIGZvciAobGV0IGF0dHIgb2YgdGhpcy5yYXdfdmFsdWUoKVtpXS5hdHRyaWJ1dGVzKSB7XG4gICAgICAgIHByb2Nlc3NlZF92YWx1ZSA9IHRoaXNbXCJwcm9jZXNzX1wiICsgYXR0cl0ocHJvY2Vzc2VkX3ZhbHVlKTtcbiAgICAgIH1cblxuICAgICAgcHJvY2Vzc2VkX3ZhbHVlcyA9IHByb2Nlc3NlZF92YWx1ZXMuY29uY2F0KHByb2Nlc3NlZF92YWx1ZSk7XG4gICAgfVxuXG4gICAgcmV0dXJuIHByb2Nlc3NlZF92YWx1ZXM7XG4gIH1cblxuICBwcm9jZXNzX2ludGVnZXIodmFsdWUpIHtcbiAgICByZXR1cm4gdmFsdWUudmFsdWU7XG4gIH1cblxuICBwcm9jZXNzX2Zsb2F0KHZhbHVlKSB7XG4gICAgaWYgKHZhbHVlLnNpemUgPT09IDY0KSB7XG4gICAgICByZXR1cm4gQml0U3RyaW5nLmZsb2F0NjRUb0J5dGVzKHZhbHVlLnZhbHVlKTtcbiAgICB9IGVsc2UgaWYgKHZhbHVlLnNpemUgPT09IDMyKSB7XG4gICAgICByZXR1cm4gQml0U3RyaW5nLmZsb2F0MzJUb0J5dGVzKHZhbHVlLnZhbHVlKTtcbiAgICB9XG5cbiAgICB0aHJvdyBuZXcgRXJyb3IoXCJJbnZhbGlkIHNpemUgZm9yIGZsb2F0XCIpO1xuICB9XG5cbiAgcHJvY2Vzc19iaXRzdHJpbmcodmFsdWUpIHtcbiAgICByZXR1cm4gdmFsdWUudmFsdWUudmFsdWU7XG4gIH1cblxuICBwcm9jZXNzX2JpbmFyeSh2YWx1ZSkge1xuICAgIHJldHVybiBCaXRTdHJpbmcudG9VVEY4QXJyYXkodmFsdWUudmFsdWUpO1xuICB9XG5cbiAgcHJvY2Vzc191dGY4KHZhbHVlKSB7XG4gICAgcmV0dXJuIEJpdFN0cmluZy50b1VURjhBcnJheSh2YWx1ZS52YWx1ZSk7XG4gIH1cblxuICBwcm9jZXNzX3V0ZjE2KHZhbHVlKSB7XG4gICAgcmV0dXJuIEJpdFN0cmluZy50b1VURjE2QXJyYXkodmFsdWUudmFsdWUpO1xuICB9XG5cbiAgcHJvY2Vzc191dGYzMih2YWx1ZSkge1xuICAgIHJldHVybiBCaXRTdHJpbmcudG9VVEYzMkFycmF5KHZhbHVlLnZhbHVlKTtcbiAgfVxuXG4gIHByb2Nlc3Nfc2lnbmVkKHZhbHVlKSB7XG4gICAgcmV0dXJuIG5ldyBVaW50OEFycmF5KFt2YWx1ZV0pWzBdO1xuICB9XG5cbiAgcHJvY2Vzc191bnNpZ25lZCh2YWx1ZSkge1xuICAgIHJldHVybiB2YWx1ZTtcbiAgfVxuXG4gIHByb2Nlc3NfbmF0aXZlKHZhbHVlKSB7XG4gICAgcmV0dXJuIHZhbHVlO1xuICB9XG5cbiAgcHJvY2Vzc19iaWcodmFsdWUpIHtcbiAgICByZXR1cm4gdmFsdWU7XG4gIH1cblxuICBwcm9jZXNzX2xpdHRsZSh2YWx1ZSkge1xuICAgIHJldHVybiB2YWx1ZS5yZXZlcnNlKCk7XG4gIH1cblxuICBwcm9jZXNzX3NpemUodmFsdWUpIHtcbiAgICByZXR1cm4gdmFsdWU7XG4gIH1cblxuICBwcm9jZXNzX3VuaXQodmFsdWUpIHtcbiAgICByZXR1cm4gdmFsdWU7XG4gIH1cblxuICBzdGF0aWMgaW50ZWdlcih2YWx1ZSkge1xuICAgIHJldHVybiBCaXRTdHJpbmcud3JhcCh2YWx1ZSwgeyBcInR5cGVcIjogXCJpbnRlZ2VyXCIsIFwidW5pdFwiOiAxLCBcInNpemVcIjogOCB9KTtcbiAgfVxuXG4gIHN0YXRpYyBmbG9hdCh2YWx1ZSkge1xuICAgIHJldHVybiBCaXRTdHJpbmcud3JhcCh2YWx1ZSwgeyBcInR5cGVcIjogXCJmbG9hdFwiLCBcInVuaXRcIjogMSwgXCJzaXplXCI6IDY0IH0pO1xuICB9XG5cbiAgc3RhdGljIGJpdHN0cmluZyh2YWx1ZSkge1xuICAgIHJldHVybiBCaXRTdHJpbmcud3JhcCh2YWx1ZSwgeyBcInR5cGVcIjogXCJiaXRzdHJpbmdcIiwgXCJ1bml0XCI6IDEsIFwic2l6ZVwiOiB2YWx1ZS5sZW5ndGggfSk7XG4gIH1cblxuICBzdGF0aWMgYml0cyh2YWx1ZSkge1xuICAgIHJldHVybiBCaXRTdHJpbmcuYml0c3RyaW5nKHZhbHVlKTtcbiAgfVxuXG4gIHN0YXRpYyBiaW5hcnkodmFsdWUpIHtcbiAgICByZXR1cm4gQml0U3RyaW5nLndyYXAodmFsdWUsIHsgXCJ0eXBlXCI6IFwiYmluYXJ5XCIsIFwidW5pdFwiOiA4LCBcInNpemVcIjogdmFsdWUubGVuZ3RoIH0pO1xuICB9XG5cbiAgc3RhdGljIGJ5dGVzKHZhbHVlKSB7XG4gICAgcmV0dXJuIEJpdFN0cmluZy5iaW5hcnkodmFsdWUpO1xuICB9XG5cbiAgc3RhdGljIHV0ZjgodmFsdWUpIHtcbiAgICByZXR1cm4gQml0U3RyaW5nLndyYXAodmFsdWUsIHsgXCJ0eXBlXCI6IFwidXRmOFwiIH0pO1xuICB9XG5cbiAgc3RhdGljIHV0ZjE2KHZhbHVlKSB7XG4gICAgcmV0dXJuIEJpdFN0cmluZy53cmFwKHZhbHVlLCB7IFwidHlwZVwiOiBcInV0ZjE2XCIgfSk7XG4gIH1cblxuICBzdGF0aWMgdXRmMzIodmFsdWUpIHtcbiAgICByZXR1cm4gQml0U3RyaW5nLndyYXAodmFsdWUsIHsgXCJ0eXBlXCI6IFwidXRmMzJcIiB9KTtcbiAgfVxuXG4gIHN0YXRpYyBzaWduZWQodmFsdWUpIHtcbiAgICByZXR1cm4gQml0U3RyaW5nLndyYXAodmFsdWUsIHt9LCBcInNpZ25lZFwiKTtcbiAgfVxuXG4gIHN0YXRpYyB1bnNpZ25lZCh2YWx1ZSkge1xuICAgIHJldHVybiBCaXRTdHJpbmcud3JhcCh2YWx1ZSwge30sIFwidW5zaWduZWRcIik7XG4gIH1cblxuICBzdGF0aWMgbmF0aXZlKHZhbHVlKSB7XG4gICAgcmV0dXJuIEJpdFN0cmluZy53cmFwKHZhbHVlLCB7fSwgXCJuYXRpdmVcIik7XG4gIH1cblxuICBzdGF0aWMgYmlnKHZhbHVlKSB7XG4gICAgcmV0dXJuIEJpdFN0cmluZy53cmFwKHZhbHVlLCB7fSwgXCJiaWdcIik7XG4gIH1cblxuICBzdGF0aWMgbGl0dGxlKHZhbHVlKSB7XG4gICAgcmV0dXJuIEJpdFN0cmluZy53cmFwKHZhbHVlLCB7fSwgXCJsaXR0bGVcIik7XG4gIH1cblxuICBzdGF0aWMgc2l6ZSh2YWx1ZSwgY291bnQpIHtcbiAgICByZXR1cm4gQml0U3RyaW5nLndyYXAodmFsdWUsIHsgXCJzaXplXCI6IGNvdW50IH0pO1xuICB9XG5cbiAgc3RhdGljIHVuaXQodmFsdWUsIGNvdW50KSB7XG4gICAgcmV0dXJuIEJpdFN0cmluZy53cmFwKHZhbHVlLCB7IFwidW5pdFwiOiBjb3VudCB9KTtcbiAgfVxuXG4gIHN0YXRpYyB3cmFwKHZhbHVlLCBvcHQsIG5ld19hdHRyaWJ1dGUgPSBudWxsKSB7XG4gICAgbGV0IHRoZV92YWx1ZSA9IHZhbHVlO1xuXG4gICAgaWYgKCEodmFsdWUgaW5zdGFuY2VvZiBPYmplY3QpKSB7XG4gICAgICB0aGVfdmFsdWUgPSB7IFwidmFsdWVcIjogdmFsdWUsIFwiYXR0cmlidXRlc1wiOiBbXSB9O1xuICAgIH1cblxuICAgIHRoZV92YWx1ZSA9IE9iamVjdC5hc3NpZ24odGhlX3ZhbHVlLCBvcHQpO1xuXG4gICAgaWYgKG5ld19hdHRyaWJ1dGUpIHtcbiAgICAgIHRoZV92YWx1ZS5hdHRyaWJ1dGVzLnB1c2gobmV3X2F0dHJpYnV0ZSk7XG4gICAgfVxuXG4gICAgcmV0dXJuIHRoZV92YWx1ZTtcbiAgfVxuXG4gIHN0YXRpYyB0b1VURjhBcnJheShzdHIpIHtcbiAgICB2YXIgdXRmOCA9IFtdO1xuICAgIGZvciAodmFyIGkgPSAwOyBpIDwgc3RyLmxlbmd0aDsgaSsrKSB7XG4gICAgICB2YXIgY2hhcmNvZGUgPSBzdHIuY2hhckNvZGVBdChpKTtcbiAgICAgIGlmIChjaGFyY29kZSA8IDEyOCkge1xuICAgICAgICB1dGY4LnB1c2goY2hhcmNvZGUpO1xuICAgICAgfSBlbHNlIGlmIChjaGFyY29kZSA8IDIwNDgpIHtcbiAgICAgICAgdXRmOC5wdXNoKDE5MiB8IGNoYXJjb2RlID4+IDYsIDEyOCB8IGNoYXJjb2RlICYgNjMpO1xuICAgICAgfSBlbHNlIGlmIChjaGFyY29kZSA8IDU1Mjk2IHx8IGNoYXJjb2RlID49IDU3MzQ0KSB7XG4gICAgICAgIHV0ZjgucHVzaCgyMjQgfCBjaGFyY29kZSA+PiAxMiwgMTI4IHwgY2hhcmNvZGUgPj4gNiAmIDYzLCAxMjggfCBjaGFyY29kZSAmIDYzKTtcbiAgICAgIH1cbiAgICAgIC8vIHN1cnJvZ2F0ZSBwYWlyXG4gICAgICBlbHNlIHtcbiAgICAgICAgaSsrO1xuICAgICAgICAvLyBVVEYtMTYgZW5jb2RlcyAweDEwMDAwLTB4MTBGRkZGIGJ5XG4gICAgICAgIC8vIHN1YnRyYWN0aW5nIDB4MTAwMDAgYW5kIHNwbGl0dGluZyB0aGVcbiAgICAgICAgLy8gMjAgYml0cyBvZiAweDAtMHhGRkZGRiBpbnRvIHR3byBoYWx2ZXNcbiAgICAgICAgY2hhcmNvZGUgPSA2NTUzNiArICgoY2hhcmNvZGUgJiAxMDIzKSA8PCAxMCB8IHN0ci5jaGFyQ29kZUF0KGkpICYgMTAyMyk7XG4gICAgICAgIHV0ZjgucHVzaCgyNDAgfCBjaGFyY29kZSA+PiAxOCwgMTI4IHwgY2hhcmNvZGUgPj4gMTIgJiA2MywgMTI4IHwgY2hhcmNvZGUgPj4gNiAmIDYzLCAxMjggfCBjaGFyY29kZSAmIDYzKTtcbiAgICAgIH1cbiAgICB9XG4gICAgcmV0dXJuIHV0Zjg7XG4gIH1cblxuICBzdGF0aWMgdG9VVEYxNkFycmF5KHN0cikge1xuICAgIHZhciB1dGYxNiA9IFtdO1xuICAgIGZvciAodmFyIGkgPSAwOyBpIDwgc3RyLmxlbmd0aDsgaSsrKSB7XG4gICAgICB2YXIgY29kZVBvaW50ID0gc3RyLmNvZGVQb2ludEF0KGkpO1xuXG4gICAgICBpZiAoY29kZVBvaW50IDw9IDI1NSkge1xuICAgICAgICB1dGYxNi5wdXNoKDApO1xuICAgICAgICB1dGYxNi5wdXNoKGNvZGVQb2ludCk7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICB1dGYxNi5wdXNoKGNvZGVQb2ludCA+PiA4ICYgMjU1KTtcbiAgICAgICAgdXRmMTYucHVzaChjb2RlUG9pbnQgJiAyNTUpO1xuICAgICAgfVxuICAgIH1cbiAgICByZXR1cm4gdXRmMTY7XG4gIH1cblxuICBzdGF0aWMgdG9VVEYzMkFycmF5KHN0cikge1xuICAgIHZhciB1dGYzMiA9IFtdO1xuICAgIGZvciAodmFyIGkgPSAwOyBpIDwgc3RyLmxlbmd0aDsgaSsrKSB7XG4gICAgICB2YXIgY29kZVBvaW50ID0gc3RyLmNvZGVQb2ludEF0KGkpO1xuXG4gICAgICBpZiAoY29kZVBvaW50IDw9IDI1NSkge1xuICAgICAgICB1dGYzMi5wdXNoKDApO1xuICAgICAgICB1dGYzMi5wdXNoKDApO1xuICAgICAgICB1dGYzMi5wdXNoKDApO1xuICAgICAgICB1dGYzMi5wdXNoKGNvZGVQb2ludCk7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICB1dGYzMi5wdXNoKDApO1xuICAgICAgICB1dGYzMi5wdXNoKDApO1xuICAgICAgICB1dGYzMi5wdXNoKGNvZGVQb2ludCA+PiA4ICYgMjU1KTtcbiAgICAgICAgdXRmMzIucHVzaChjb2RlUG9pbnQgJiAyNTUpO1xuICAgICAgfVxuICAgIH1cbiAgICByZXR1cm4gdXRmMzI7XG4gIH1cblxuICAvL2h0dHA6Ly9zdGFja292ZXJmbG93LmNvbS9xdWVzdGlvbnMvMjAwMzQ5My9qYXZhc2NyaXB0LWZsb2F0LWZyb20tdG8tYml0c1xuICBzdGF0aWMgZmxvYXQzMlRvQnl0ZXMoZikge1xuICAgIHZhciBieXRlcyA9IFtdO1xuXG4gICAgdmFyIGJ1ZiA9IG5ldyBBcnJheUJ1ZmZlcig0KTtcbiAgICBuZXcgRmxvYXQzMkFycmF5KGJ1ZilbMF0gPSBmO1xuXG4gICAgbGV0IGludFZlcnNpb24gPSBuZXcgVWludDMyQXJyYXkoYnVmKVswXTtcblxuICAgIGJ5dGVzLnB1c2goaW50VmVyc2lvbiA+PiAyNCAmIDI1NSk7XG4gICAgYnl0ZXMucHVzaChpbnRWZXJzaW9uID4+IDE2ICYgMjU1KTtcbiAgICBieXRlcy5wdXNoKGludFZlcnNpb24gPj4gOCAmIDI1NSk7XG4gICAgYnl0ZXMucHVzaChpbnRWZXJzaW9uICYgMjU1KTtcblxuICAgIHJldHVybiBieXRlcztcbiAgfVxuXG4gIHN0YXRpYyBmbG9hdDY0VG9CeXRlcyhmKSB7XG4gICAgdmFyIGJ5dGVzID0gW107XG5cbiAgICB2YXIgYnVmID0gbmV3IEFycmF5QnVmZmVyKDgpO1xuICAgIG5ldyBGbG9hdDY0QXJyYXkoYnVmKVswXSA9IGY7XG5cbiAgICB2YXIgaW50VmVyc2lvbjEgPSBuZXcgVWludDMyQXJyYXkoYnVmKVswXTtcbiAgICB2YXIgaW50VmVyc2lvbjIgPSBuZXcgVWludDMyQXJyYXkoYnVmKVsxXTtcblxuICAgIGJ5dGVzLnB1c2goaW50VmVyc2lvbjIgPj4gMjQgJiAyNTUpO1xuICAgIGJ5dGVzLnB1c2goaW50VmVyc2lvbjIgPj4gMTYgJiAyNTUpO1xuICAgIGJ5dGVzLnB1c2goaW50VmVyc2lvbjIgPj4gOCAmIDI1NSk7XG4gICAgYnl0ZXMucHVzaChpbnRWZXJzaW9uMiAmIDI1NSk7XG5cbiAgICBieXRlcy5wdXNoKGludFZlcnNpb24xID4+IDI0ICYgMjU1KTtcbiAgICBieXRlcy5wdXNoKGludFZlcnNpb24xID4+IDE2ICYgMjU1KTtcbiAgICBieXRlcy5wdXNoKGludFZlcnNpb24xID4+IDggJiAyNTUpO1xuICAgIGJ5dGVzLnB1c2goaW50VmVyc2lvbjEgJiAyNTUpO1xuXG4gICAgcmV0dXJuIGJ5dGVzO1xuICB9XG59XG5cbi8qIEBmbG93ICovXG5cbmNsYXNzIE1haWxib3gge1xuXG4gIGNvbnN0cnVjdG9yKCkge1xuICAgIHRoaXMubWVzc2FnZXMgPSBbXTtcbiAgfVxuXG4gIGRlbGl2ZXIobWVzc2FnZSkge1xuICAgIHRoaXMubWVzc2FnZXMucHVzaChtZXNzYWdlKTtcbiAgICByZXR1cm4gbWVzc2FnZTtcbiAgfVxuXG4gIGdldCgpIHtcbiAgICByZXR1cm4gdGhpcy5tZXNzYWdlcztcbiAgfVxuXG4gIGlzRW1wdHkoKSB7XG4gICAgcmV0dXJuIHRoaXMubWVzc2FnZXMubGVuZ3RoID09PSAwO1xuICB9XG5cbiAgcmVtb3ZlQXQoaW5kZXgpIHtcbiAgICB0aGlzLm1lc3NhZ2VzLnNwbGljZShpbmRleCwgMSk7XG4gIH1cbn1cblxudmFyIFN0YXRlcyA9IHtcbiAgTk9STUFMOiBTeW1ib2wuZm9yKFwibm9ybWFsXCIpLFxuICBLSUxMOiBTeW1ib2wuZm9yKFwia2lsbFwiKSxcbiAgU1VTUEVORDogU3ltYm9sLmZvcihcInN1c3BlbmRcIiksXG4gIENPTlRJTlVFOiBTeW1ib2wuZm9yKFwiY29udGludWVcIiksXG4gIFJFQ0VJVkU6IFN5bWJvbC5mb3IoXCJyZWNlaXZlXCIpLFxuICBTRU5EOiBTeW1ib2wuZm9yKFwic2VuZFwiKSxcbiAgU0xFRVBJTkc6IFN5bWJvbC5mb3IoXCJzbGVlcGluZ1wiKSxcbiAgUlVOTklORzogU3ltYm9sLmZvcihcInJ1bm5pbmdcIiksXG4gIFNVU1BFTkRFRDogU3ltYm9sLmZvcihcInN1c3BlbmRlZFwiKSxcbiAgU1RPUFBFRDogU3ltYm9sLmZvcihcInN0b3BwZWRcIiksXG4gIFNMRUVQOiBTeW1ib2wuZm9yKFwic2xlZXBcIiksXG4gIEVYSVQ6IFN5bWJvbC5mb3IoXCJleGl0XCIpLFxuICBOT01BVENIOiBTeW1ib2wuZm9yKFwibm9fbWF0Y2hcIilcbn07XG5cbmNsYXNzIFByb2Nlc3Mge1xuXG4gIGNvbnN0cnVjdG9yKHBpZCwgbWFpbGJveCkge1xuICAgIHRoaXMucGlkID0gcGlkO1xuICAgIHRoaXMubWFpbGJveCA9IG1haWxib3g7XG4gICAgdGhpcy5zdGF0dXMgPSBTdGF0ZXMuU1RPUFBFRDtcbiAgICB0aGlzLmRpY3QgPSB7fTtcbiAgfVxufVxuXG5jbGFzcyBQcm9jZXNzU3lzdGVtIHtcblxuICBjb25zdHJ1Y3RvcigpIHtcbiAgICB0aGlzLnBpZHMgPSBuZXcgTWFwKCk7XG4gICAgdGhpcy5tYWlsYm94ZXMgPSBuZXcgTWFwKCk7XG4gICAgdGhpcy5uYW1lcyA9IG5ldyBNYXAoKTtcbiAgICB0aGlzLmxpbmtzID0gbmV3IE1hcCgpO1xuXG4gICAgdGhpcy5jdXJyZW50X3Byb2Nlc3MgPSBudWxsO1xuICAgIHRoaXMuc3VzcGVuZGVkID0gbmV3IE1hcCgpO1xuXG4gICAgdGhpcy5tYWluX3Byb2Nlc3NfcGlkID0gdGhpcy5zcGF3bigpO1xuICAgIHRoaXMuc2V0X2N1cnJlbnQodGhpcy5tYWluX3Byb2Nlc3NfcGlkKTtcbiAgfVxuXG4gIHNwYXduKCkge1xuICAgIHJldHVybiB0aGlzLmFkZF9wcm9jKGZhbHNlKS5waWQ7XG4gIH1cblxuICBzcGF3bl9saW5rKCkge1xuICAgIHJldHVybiB0aGlzLmFkZF9wcm9jKHRydWUpLnBpZDtcbiAgfVxuXG4gIGxpbmsocGlkKSB7XG4gICAgdGhpcy5saW5rcy5nZXQodGhpcy5waWQoKSkuYWRkKHBpZCk7XG4gICAgdGhpcy5saW5rcy5nZXQocGlkKS5hZGQodGhpcy5waWQoKSk7XG4gIH1cblxuICB1bmxpbmsocGlkKSB7XG4gICAgdGhpcy5saW5rcy5nZXQodGhpcy5waWQoKSkuZGVsZXRlKHBpZCk7XG4gICAgdGhpcy5saW5rcy5nZXQocGlkKS5kZWxldGUodGhpcy5waWQoKSk7XG4gIH1cblxuICBzZXRfY3VycmVudChpZCkge1xuICAgIGxldCBwaWQgPSB0aGlzLnBpZG9mKGlkKTtcbiAgICBpZiAocGlkICE9PSBudWxsKSB7XG4gICAgICB0aGlzLmN1cnJlbnRfcHJvY2VzcyA9IHRoaXMucGlkcy5nZXQocGlkKTtcbiAgICAgIHRoaXMuY3VycmVudF9wcm9jZXNzLnN0YXR1cyA9IFN0YXRlcy5SVU5OSU5HO1xuICAgIH1cbiAgfVxuXG4gIGFkZF9wcm9jKGxpbmtlZCkge1xuICAgIGxldCBuZXdwaWQgPSBuZXcgUElEKCk7XG4gICAgbGV0IG1haWxib3ggPSBuZXcgTWFpbGJveCgpO1xuICAgIGxldCBuZXdwcm9jID0gbmV3IFByb2Nlc3MobmV3cGlkLCBtYWlsYm94KTtcblxuICAgIHRoaXMucGlkcy5zZXQobmV3cGlkLCBuZXdwcm9jKTtcbiAgICB0aGlzLm1haWxib3hlcy5zZXQobmV3cGlkLCBtYWlsYm94KTtcbiAgICB0aGlzLmxpbmtzLnNldChuZXdwaWQsIG5ldyBTZXQoKSk7XG5cbiAgICBpZiAobGlua2VkKSB7XG4gICAgICB0aGlzLmxpbmsobmV3cGlkKTtcbiAgICB9XG5cbiAgICByZXR1cm4gbmV3cHJvYztcbiAgfVxuXG4gIHJlbW92ZV9wcm9jKHBpZCkge1xuICAgIHRoaXMucGlkcy5kZWxldGUocGlkKTtcbiAgICB0aGlzLnVucmVnaXN0ZXIocGlkKTtcblxuICAgIGlmICh0aGlzLmxpbmtzLmhhcyhwaWQpKSB7XG4gICAgICBmb3IgKGxldCBsaW5rcGlkIG9mIHRoaXMubGlua3MuZ2V0KHBpZCkpIHtcbiAgICAgICAgdGhpcy5saW5rcy5nZXQobGlua3BpZCkuZGVsZXRlKHBpZCk7XG4gICAgICB9XG5cbiAgICAgIHRoaXMubGlua3MuZGVsZXRlKHBpZCk7XG4gICAgfVxuICB9XG5cbiAgZXhpdChpZCkge1xuICAgIGxldCBwaWQgPSB0aGlzLnBpZG9mKGlkKTtcbiAgICB0aGlzLnJlbW92ZV9wcm9jKGlkKTtcbiAgfVxuXG4gIHJlZ2lzdGVyKG5hbWUsIHBpZCkge1xuICAgIGlmICghdGhpcy5uYW1lcy5oYXMobmFtZSkpIHtcbiAgICAgIHRoaXMubmFtZXMuc2V0KG5hbWUsIHBpZCk7XG4gICAgICByZXR1cm4gbmFtZTtcbiAgICB9IGVsc2Uge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKFwiTmFtZSBpcyBhbHJlYWR5IHJlZ2lzdGVyZWQgdG8gYW5vdGhlciBwcm9jZXNzXCIpO1xuICAgIH1cbiAgfVxuXG4gIHJlZ2lzdGVyZWQobmFtZSkge1xuICAgIHJldHVybiB0aGlzLm5hbWVzLmhhcyhuYW1lKSA/IHRoaXMubmFtZXMuZ2V0KG5hbWUpIDogbnVsbDtcbiAgfVxuXG4gIHVucmVnaXN0ZXIocGlkKSB7XG4gICAgZm9yIChsZXQgbmFtZSBvZiB0aGlzLm5hbWVzLmtleXMoKSkge1xuICAgICAgaWYgKHRoaXMubmFtZXMuaGFzKG5hbWUpICYmIHRoaXMubmFtZXMuZ2V0KG5hbWUpID09PSBwaWQpIHtcbiAgICAgICAgdGhpcy5uYW1lcy5kZWxldGUobmFtZSk7XG4gICAgICB9XG4gICAgfVxuICB9XG5cbiAgcGlkKCkge1xuICAgIHJldHVybiB0aGlzLmN1cnJlbnRfcHJvY2Vzcy5waWQ7XG4gIH1cblxuICBwaWRvZihpZCkge1xuICAgIGlmIChpZCBpbnN0YW5jZW9mIFBJRCkge1xuICAgICAgcmV0dXJuIHRoaXMucGlkcy5oYXMoaWQpID8gaWQgOiBudWxsO1xuICAgIH0gZWxzZSBpZiAoaWQgaW5zdGFuY2VvZiBQcm9jZXNzKSB7XG4gICAgICByZXR1cm4gaWQucGlkO1xuICAgIH0gZWxzZSB7XG4gICAgICBsZXQgcGlkID0gdGhpcy5yZWdpc3RlcmVkKGlkKTtcbiAgICAgIGlmIChwaWQgPT09IG51bGwpIHRocm93IFwiUHJvY2VzcyBuYW1lIG5vdCByZWdpc3RlcmVkOiBcIiArIGlkICsgXCIgKFwiICsgdHlwZW9mIGlkICsgXCIpXCI7XG4gICAgICByZXR1cm4gcGlkO1xuICAgIH1cbiAgfVxuXG4gIHB1dChpZCwga2V5LCB2YWx1ZSkge1xuICAgIGxldCBwaWQgPSB0aGlzLnBpZG9mKGlkKTtcbiAgICBsZXQgcHJvY2VzcyA9IHRoaXMucGlkcy5nZXQocGlkKTtcbiAgICBwcm9jZXNzLmRpY3Rba2V5XSA9IHZhbHVlO1xuICB9XG5cbiAgZ2V0KGlkLCBrZXkpIHtcbiAgICBsZXQgcGlkID0gdGhpcy5waWRvZihpZCk7XG4gICAgbGV0IHByb2Nlc3MgPSB0aGlzLnBpZHMuZ2V0KHBpZCk7XG5cbiAgICBpZiAoa2V5ICE9IG51bGwpIHtcbiAgICAgIHJldHVybiBwcm9jZXNzLmRpY3Rba2V5XTtcbiAgICB9IGVsc2Uge1xuICAgICAgcmV0dXJuIHByb2Nlc3MuZGljdDtcbiAgICB9XG4gIH1cblxuICBnZXRfa2V5cyhpZCkge1xuICAgIGxldCBwaWQgPSB0aGlzLnBpZG9mKGlkKTtcbiAgICBsZXQgcHJvY2VzcyA9IHRoaXMucGlkcy5nZXQocGlkKTtcblxuICAgIHJldHVybiBPYmplY3Qua2V5cyhwcm9jZXNzLmRpY3QpO1xuICB9XG5cbiAgZXJhc2UoaWQsIGtleSkge1xuICAgIGxldCBwaWQgPSB0aGlzLnBpZG9mKGlkKTtcbiAgICBsZXQgcHJvY2VzcyA9IHRoaXMucGlkcy5nZXQocGlkKTtcblxuICAgIGlmIChrZXkgIT0gbnVsbCkge1xuICAgICAgZGVsZXRlIHByb2Nlc3MuZGljdFtrZXldO1xuICAgIH0gZWxzZSB7XG4gICAgICBwcm9jZXNzLmRpY3QgPSB7fTtcbiAgICB9XG4gIH1cbn1cblxudmFyIEMgPSBPYmplY3QuZnJlZXplKHtcblx0UHJvY2Vzc1N5c3RlbTogUHJvY2Vzc1N5c3RlbSxcblx0VHVwbGU6IFR1cGxlJDEsXG5cdFBJRDogUElELFxuXHRCaXRTdHJpbmc6IEJpdFN0cmluZyxcblx0UGF0dGVybnM6IG51bGwkMSxcblx0SW50ZWdlclR5cGU6IEludGVnZXJUeXBlLFxuXHRGbG9hdFR5cGU6IEZsb2F0VHlwZSxcblx0Y2FsbF9wcm9wZXJ0eTogY2FsbF9wcm9wZXJ0eVxufSk7XG5cbmxldCBFbnVtID0ge1xuXG4gIGFsbF9fcW1hcmtfXzogZnVuY3Rpb24gKGNvbGxlY3Rpb24sIGZ1biA9IHggPT4geCkge1xuICAgIGZvciAobGV0IGVsZW0gb2YgY29sbGVjdGlvbikge1xuICAgICAgaWYgKCFmdW4oZWxlbSkpIHtcbiAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgfVxuICAgIH1cblxuICAgIHJldHVybiB0cnVlO1xuICB9LFxuXG4gIGFueV9fcW1hcmtfXzogZnVuY3Rpb24gKGNvbGxlY3Rpb24sIGZ1biA9IHggPT4geCkge1xuICAgIGZvciAobGV0IGVsZW0gb2YgY29sbGVjdGlvbikge1xuICAgICAgaWYgKGZ1bihlbGVtKSkge1xuICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICByZXR1cm4gZmFsc2U7XG4gIH0sXG5cbiAgYXQ6IGZ1bmN0aW9uIChjb2xsZWN0aW9uLCBuLCB0aGVfZGVmYXVsdCA9IG51bGwpIHtcbiAgICBpZiAobiA+IHRoaXMuY291bnQoY29sbGVjdGlvbikgfHwgbiA8IDApIHtcbiAgICAgIHJldHVybiB0aGVfZGVmYXVsdDtcbiAgICB9XG5cbiAgICByZXR1cm4gY29sbGVjdGlvbltuXTtcbiAgfSxcblxuICBjb25jYXQ6IGZ1bmN0aW9uICguLi5lbnVtYWJsZXMpIHtcbiAgICByZXR1cm4gZW51bWFibGVzWzBdLmNvbmNhdChlbnVtYWJsZXNbMV0pO1xuICB9LFxuXG4gIGNvdW50OiBmdW5jdGlvbiAoY29sbGVjdGlvbiwgZnVuID0gbnVsbCkge1xuICAgIGlmIChmdW4gPT0gbnVsbCkge1xuICAgICAgcmV0dXJuIGNvbGxlY3Rpb24ubGVuZ3RoO1xuICAgIH0gZWxzZSB7XG4gICAgICByZXR1cm4gY29sbGVjdGlvbi5maWx0ZXIoZnVuKS5sZW5ndGg7XG4gICAgfVxuICB9LFxuXG4gIGRyb3A6IGZ1bmN0aW9uIChjb2xsZWN0aW9uLCBjb3VudCkge1xuICAgIHJldHVybiBjb2xsZWN0aW9uLnNsaWNlKGNvdW50KTtcbiAgfSxcblxuICBkcm9wX3doaWxlOiBmdW5jdGlvbiAoY29sbGVjdGlvbiwgZnVuKSB7XG4gICAgbGV0IGNvdW50ID0gMDtcblxuICAgIGZvciAobGV0IGVsZW0gb2YgY29sbGVjdGlvbikge1xuICAgICAgaWYgKGZ1bihlbGVtKSkge1xuICAgICAgICBjb3VudCA9IGNvdW50ICsgMTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIGJyZWFrO1xuICAgICAgfVxuICAgIH1cblxuICAgIHJldHVybiBjb2xsZWN0aW9uLnNsaWNlKGNvdW50KTtcbiAgfSxcblxuICBlYWNoOiBmdW5jdGlvbiAoY29sbGVjdGlvbiwgZnVuKSB7XG4gICAgZm9yIChsZXQgZWxlbSBvZiBjb2xsZWN0aW9uKSB7XG4gICAgICBmdW4oZWxlbSk7XG4gICAgfVxuICB9LFxuXG4gIGVtcHR5X19xbWFya19fOiBmdW5jdGlvbiAoY29sbGVjdGlvbikge1xuICAgIHJldHVybiBjb2xsZWN0aW9uLmxlbmd0aCA9PT0gMDtcbiAgfSxcblxuICBmZXRjaDogZnVuY3Rpb24gKGNvbGxlY3Rpb24sIG4pIHtcbiAgICBpZiAoS2VybmVsLmlzX2xpc3QoY29sbGVjdGlvbikpIHtcbiAgICAgIGlmIChuIDwgdGhpcy5jb3VudChjb2xsZWN0aW9uKSAmJiBuID49IDApIHtcbiAgICAgICAgcmV0dXJuIEtlcm5lbC5TcGVjaWFsRm9ybXMudHVwbGUoS2VybmVsLlNwZWNpYWxGb3Jtcy5hdG9tKFwib2tcIiksIGNvbGxlY3Rpb25bbl0pO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgcmV0dXJuIEtlcm5lbC5TcGVjaWFsRm9ybXMuYXRvbShcImVycm9yXCIpO1xuICAgICAgfVxuICAgIH1cblxuICAgIHRocm93IG5ldyBFcnJvcihcImNvbGxlY3Rpb24gaXMgbm90IGFuIEVudW1lcmFibGVcIik7XG4gIH0sXG5cbiAgZmV0Y2hfX2VtYXJrX186IGZ1bmN0aW9uIChjb2xsZWN0aW9uLCBuKSB7XG4gICAgaWYgKEtlcm5lbC5pc19saXN0KGNvbGxlY3Rpb24pKSB7XG4gICAgICBpZiAobiA8IHRoaXMuY291bnQoY29sbGVjdGlvbikgJiYgbiA+PSAwKSB7XG4gICAgICAgIHJldHVybiBjb2xsZWN0aW9uW25dO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKFwib3V0IG9mIGJvdW5kcyBlcnJvclwiKTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICB0aHJvdyBuZXcgRXJyb3IoXCJjb2xsZWN0aW9uIGlzIG5vdCBhbiBFbnVtZXJhYmxlXCIpO1xuICB9LFxuXG4gIGZpbHRlcjogZnVuY3Rpb24gKGNvbGxlY3Rpb24sIGZ1bikge1xuICAgIGxldCByZXN1bHQgPSBbXTtcblxuICAgIGZvciAobGV0IGVsZW0gb2YgY29sbGVjdGlvbikge1xuICAgICAgaWYgKGZ1bihlbGVtKSkge1xuICAgICAgICByZXN1bHQucHVzaChlbGVtKTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICByZXR1cm4gcmVzdWx0O1xuICB9LFxuXG4gIGZpbHRlcl9tYXA6IGZ1bmN0aW9uIChjb2xsZWN0aW9uLCBmaWx0ZXIsIG1hcHBlcikge1xuICAgIHJldHVybiBFbnVtLm1hcChFbnVtLmZpbHRlcihjb2xsZWN0aW9uLCBmaWx0ZXIpLCBtYXBwZXIpO1xuICB9LFxuXG4gIGZpbmQ6IGZ1bmN0aW9uIChjb2xsZWN0aW9uLCBpZl9ub25lID0gbnVsbCwgZnVuKSB7XG4gICAgZm9yIChsZXQgZWxlbSBvZiBjb2xsZWN0aW9uKSB7XG4gICAgICBpZiAoZnVuKGVsZW0pKSB7XG4gICAgICAgIHJldHVybiBlbGVtO1xuICAgICAgfVxuICAgIH1cblxuICAgIHJldHVybiBpZl9ub25lO1xuICB9LFxuXG4gIGludG86IGZ1bmN0aW9uIChjb2xsZWN0aW9uLCBsaXN0KSB7XG4gICAgcmV0dXJuIGxpc3QuY29uY2F0KGNvbGxlY3Rpb24pO1xuICB9LFxuXG4gIG1hcDogZnVuY3Rpb24gKGNvbGxlY3Rpb24sIGZ1bikge1xuICAgIGxldCByZXN1bHQgPSBbXTtcblxuICAgIGZvciAobGV0IGVsZW0gb2YgY29sbGVjdGlvbikge1xuICAgICAgcmVzdWx0LnB1c2goZnVuKGVsZW0pKTtcbiAgICB9XG5cbiAgICByZXR1cm4gcmVzdWx0O1xuICB9LFxuXG4gIG1hcF9yZWR1Y2U6IGZ1bmN0aW9uIChjb2xsZWN0aW9uLCBhY2MsIGZ1bikge1xuICAgIGxldCBtYXBwZWQgPSBLZXJuZWwuU3BlY2lhbEZvcm1zLmxpc3QoKTtcbiAgICBsZXQgdGhlX2FjYyA9IGFjYztcblxuICAgIGZvciAodmFyIGkgPSAwOyBpIDwgdGhpcy5jb3VudChjb2xsZWN0aW9uKTsgaSsrKSB7XG4gICAgICBsZXQgdHVwbGUgPSBmdW4oY29sbGVjdGlvbltpXSwgdGhlX2FjYyk7XG5cbiAgICAgIHRoZV9hY2MgPSBLZXJuZWwuZWxlbSh0dXBsZSwgMSk7XG4gICAgICBtYXBwZWQgPSBLZXJuZWwuU3BlY2lhbEZvcm1zLmxpc3QoLi4ubWFwcGVkLmNvbmNhdChbS2VybmVsLmVsZW0odHVwbGUsIDApXSkpO1xuICAgIH1cblxuICAgIHJldHVybiBLZXJuZWwuU3BlY2lhbEZvcm1zLnR1cGxlKG1hcHBlZCwgdGhlX2FjYyk7XG4gIH0sXG5cbiAgbWVtYmVyOiBmdW5jdGlvbiAoY29sbGVjdGlvbiwgdmFsdWUpIHtcbiAgICByZXR1cm4gY29sbGVjdGlvbi5pbmNsdWRlcyh2YWx1ZSk7XG4gIH0sXG5cbiAgcmVkdWNlOiBmdW5jdGlvbiAoY29sbGVjdGlvbiwgYWNjLCBmdW4pIHtcbiAgICBsZXQgdGhlX2FjYyA9IGFjYztcblxuICAgIGZvciAodmFyIGkgPSAwOyBpIDwgdGhpcy5jb3VudChjb2xsZWN0aW9uKTsgaSsrKSB7XG4gICAgICBsZXQgdHVwbGUgPSBmdW4oY29sbGVjdGlvbltpXSwgdGhlX2FjYyk7XG5cbiAgICAgIHRoZV9hY2MgPSBLZXJuZWwuZWxlbSh0dXBsZSwgMSk7XG4gICAgfVxuXG4gICAgcmV0dXJuIHRoZV9hY2M7XG4gIH0sXG5cbiAgdGFrZTogZnVuY3Rpb24gKGNvbGxlY3Rpb24sIGNvdW50KSB7XG4gICAgcmV0dXJuIGNvbGxlY3Rpb24uc2xpY2UoMCwgY291bnQpO1xuICB9LFxuXG4gIHRha2VfZXZlcnk6IGZ1bmN0aW9uIChjb2xsZWN0aW9uLCBudGgpIHtcbiAgICBsZXQgcmVzdWx0ID0gW107XG4gICAgbGV0IGluZGV4ID0gMDtcblxuICAgIGZvciAobGV0IGVsZW0gb2YgY29sbGVjdGlvbikge1xuICAgICAgaWYgKGluZGV4ICUgbnRoID09PSAwKSB7XG4gICAgICAgIHJlc3VsdC5wdXNoKGVsZW0pO1xuICAgICAgfVxuICAgIH1cblxuICAgIHJldHVybiBLZXJuZWwuU3BlY2lhbEZvcm1zLmxpc3QoLi4ucmVzdWx0KTtcbiAgfSxcblxuICB0YWtlX3doaWxlOiBmdW5jdGlvbiAoY29sbGVjdGlvbiwgZnVuKSB7XG4gICAgbGV0IGNvdW50ID0gMDtcblxuICAgIGZvciAobGV0IGVsZW0gb2YgY29sbGVjdGlvbikge1xuICAgICAgaWYgKGZ1bihlbGVtKSkge1xuICAgICAgICBjb3VudCA9IGNvdW50ICsgMTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIGJyZWFrO1xuICAgICAgfVxuICAgIH1cblxuICAgIHJldHVybiBjb2xsZWN0aW9uLnNsaWNlKDAsIGNvdW50KTtcbiAgfSxcblxuICB0b19saXN0OiBmdW5jdGlvbiAoY29sbGVjdGlvbikge1xuICAgIHJldHVybiBjb2xsZWN0aW9uO1xuICB9XG59O1xuXG5sZXQgU3BlY2lhbEZvcm1zID0ge1xuXG4gIF9fRElSX186IGZ1bmN0aW9uICgpIHtcbiAgICBpZiAoX19kaXJuYW1lKSB7XG4gICAgICByZXR1cm4gX19kaXJuYW1lO1xuICAgIH1cblxuICAgIGlmIChkb2N1bWVudC5jdXJyZW50U2NyaXB0KSB7XG4gICAgICByZXR1cm4gZG9jdW1lbnQuY3VycmVudFNjcmlwdC5zcmM7XG4gICAgfVxuXG4gICAgcmV0dXJuIG51bGw7XG4gIH0sXG5cbiAgYXRvbTogZnVuY3Rpb24gKF92YWx1ZSkge1xuICAgIHJldHVybiBTeW1ib2wuZm9yKF92YWx1ZSk7XG4gIH0sXG5cbiAgbGlzdDogZnVuY3Rpb24gKC4uLmFyZ3MpIHtcbiAgICByZXR1cm4gT2JqZWN0LmZyZWV6ZShhcmdzKTtcbiAgfSxcblxuICBiaXRzdHJpbmc6IGZ1bmN0aW9uICguLi5hcmdzKSB7XG4gICAgcmV0dXJuIG5ldyBCaXRTdHJpbmcoLi4uYXJncyk7XG4gIH0sXG5cbiAgYm91bmQ6IGZ1bmN0aW9uIChfdmFyKSB7XG4gICAgcmV0dXJuIGJvdW5kKF92YXIpO1xuICB9LFxuXG4gIF9jYXNlOiBmdW5jdGlvbiAoY29uZGl0aW9uLCBjbGF1c2VzKSB7XG4gICAgcmV0dXJuIGRlZm1hdGNoKC4uLmNsYXVzZXMpKGNvbmRpdGlvbik7XG4gIH0sXG5cbiAgY29uZDogZnVuY3Rpb24gKGNsYXVzZXMpIHtcbiAgICBmb3IgKGxldCBjbGF1c2Ugb2YgY2xhdXNlcykge1xuICAgICAgaWYgKGNsYXVzZVswXSkge1xuICAgICAgICByZXR1cm4gY2xhdXNlWzFdKCk7XG4gICAgICB9XG4gICAgfVxuXG4gICAgdGhyb3cgbmV3IEVycm9yKCk7XG4gIH0sXG5cbiAgZm46IGZ1bmN0aW9uIChjbGF1c2VzKSB7XG4gICAgcmV0dXJuIGRlZm1hdGNoKGNsYXVzZXMpO1xuICB9LFxuXG4gIG1hcDogZnVuY3Rpb24gKG9iaikge1xuICAgIHJldHVybiBPYmplY3QuZnJlZXplKG9iaik7XG4gIH0sXG5cbiAgbWFwX3VwZGF0ZTogZnVuY3Rpb24gKG1hcCwgdmFsdWVzKSB7XG4gICAgcmV0dXJuIE9iamVjdC5mcmVlemUoT2JqZWN0LmFzc2lnbihPYmplY3QuY3JlYXRlKG1hcC5jb25zdHJ1Y3Rvci5wcm90b3R5cGUpLCBtYXAsIHZhbHVlcykpO1xuICB9LFxuXG4gIF9mb3I6IGZ1bmN0aW9uIChjb2xsZWN0aW9ucywgZnVuLCBmaWx0ZXIgPSAoKSA9PiB0cnVlLCBpbnRvID0gW10sIHByZXZpb3VzVmFsdWVzID0gW10pIHtcbiAgICBsZXQgcGF0dGVybiA9IGNvbGxlY3Rpb25zWzBdWzBdO1xuICAgIGxldCBjb2xsZWN0aW9uID0gY29sbGVjdGlvbnNbMF1bMV07XG5cbiAgICBpZiAoY29sbGVjdGlvbnMubGVuZ3RoID09PSAxKSB7XG5cbiAgICAgIGZvciAobGV0IGVsZW0gb2YgY29sbGVjdGlvbikge1xuICAgICAgICBsZXQgciA9IG1hdGNoX25vX3Rocm93KHBhdHRlcm4sIGVsZW0pO1xuICAgICAgICBsZXQgYXJncyA9IHByZXZpb3VzVmFsdWVzLmNvbmNhdChyKTtcblxuICAgICAgICBpZiAociAmJiBmaWx0ZXIuYXBwbHkodGhpcywgYXJncykpIHtcbiAgICAgICAgICBpbnRvID0gRW51bS5pbnRvKFtmdW4uYXBwbHkodGhpcywgYXJncyldLCBpbnRvKTtcbiAgICAgICAgfVxuICAgICAgfVxuXG4gICAgICByZXR1cm4gaW50bztcbiAgICB9IGVsc2Uge1xuICAgICAgbGV0IF9pbnRvID0gW107XG5cbiAgICAgIGZvciAobGV0IGVsZW0gb2YgY29sbGVjdGlvbikge1xuICAgICAgICBsZXQgciA9IG1hdGNoX25vX3Rocm93KHBhdHRlcm4sIGVsZW0pO1xuICAgICAgICBpZiAocikge1xuICAgICAgICAgIF9pbnRvID0gRW51bS5pbnRvKHRoaXMuX2Zvcihjb2xsZWN0aW9ucy5zbGljZSgxKSwgZnVuLCBmaWx0ZXIsIF9pbnRvLCBwcmV2aW91c1ZhbHVlcy5jb25jYXQocikpLCBpbnRvKTtcbiAgICAgICAgfVxuICAgICAgfVxuXG4gICAgICByZXR1cm4gX2ludG87XG4gICAgfVxuICB9LFxuXG4gIHJlY2VpdmU6IGZ1bmN0aW9uIChyZWNlaXZlX2Z1biwgdGltZW91dF9pbl9tcyA9IG51bGwsIHRpbWVvdXRfZm4gPSB0aW1lID0+IHRydWUpIHtcbiAgICBpZiAodGltZW91dF9pbl9tcyA9PSBudWxsIHx8IHRpbWVvdXRfaW5fbXMgPT09IFN5c3RlbS5mb3IoJ2luZmluaXR5JykpIHtcbiAgICAgIHdoaWxlICh0cnVlKSB7XG4gICAgICAgIGlmIChzZWxmLm1haWxib3gubGVuZ3RoICE9PSAwKSB7XG4gICAgICAgICAgbGV0IG1lc3NhZ2UgPSBzZWxmLm1haWxib3hbMF07XG4gICAgICAgICAgc2VsZi5tYWlsYm94ID0gc2VsZi5tYWlsYm94LnNsaWNlKDEpO1xuICAgICAgICAgIHJldHVybiByZWNlaXZlX2Z1bihtZXNzYWdlKTtcbiAgICAgICAgfVxuICAgICAgfVxuICAgIH0gZWxzZSBpZiAodGltZW91dF9pbl9tcyA9PT0gMCkge1xuICAgICAgaWYgKHNlbGYubWFpbGJveC5sZW5ndGggIT09IDApIHtcbiAgICAgICAgbGV0IG1lc3NhZ2UgPSBzZWxmLm1haWxib3hbMF07XG4gICAgICAgIHNlbGYubWFpbGJveCA9IHNlbGYubWFpbGJveC5zbGljZSgxKTtcbiAgICAgICAgcmV0dXJuIHJlY2VpdmVfZnVuKG1lc3NhZ2UpO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgcmV0dXJuIG51bGw7XG4gICAgICB9XG4gICAgfSBlbHNlIHtcbiAgICAgIGxldCBub3cgPSBEYXRlLm5vdygpO1xuICAgICAgd2hpbGUgKERhdGUubm93KCkgPCBub3cgKyB0aW1lb3V0X2luX21zKSB7XG4gICAgICAgIGlmIChzZWxmLm1haWxib3gubGVuZ3RoICE9PSAwKSB7XG4gICAgICAgICAgbGV0IG1lc3NhZ2UgPSBzZWxmLm1haWxib3hbMF07XG4gICAgICAgICAgc2VsZi5tYWlsYm94ID0gc2VsZi5tYWlsYm94LnNsaWNlKDEpO1xuICAgICAgICAgIHJldHVybiByZWNlaXZlX2Z1bihtZXNzYWdlKTtcbiAgICAgICAgfVxuICAgICAgfVxuXG4gICAgICByZXR1cm4gdGltZW91dF9mbih0aW1lb3V0X2luX21zKTtcbiAgICB9XG4gIH0sXG5cbiAgdHVwbGU6IGZ1bmN0aW9uICguLi5hcmdzKSB7XG4gICAgcmV0dXJuIG5ldyBUdXBsZSQxKC4uLmFyZ3MpO1xuICB9LFxuXG4gIF90cnk6IGZ1bmN0aW9uIChkb19mdW4sIHJlc2N1ZV9mdW5jdGlvbiwgY2F0Y2hfZnVuLCBlbHNlX2Z1bmN0aW9uLCBhZnRlcl9mdW5jdGlvbikge1xuICAgIGxldCByZXN1bHQgPSBudWxsO1xuXG4gICAgdHJ5IHtcbiAgICAgIHJlc3VsdCA9IGRvX2Z1bigpO1xuICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgIGxldCBleF9yZXN1bHQgPSBudWxsO1xuXG4gICAgICBpZiAocmVzY3VlX2Z1bmN0aW9uKSB7XG4gICAgICAgIHRyeSB7XG4gICAgICAgICAgZXhfcmVzdWx0ID0gcmVzY3VlX2Z1bmN0aW9uKGUpO1xuICAgICAgICAgIHJldHVybiBleF9yZXN1bHQ7XG4gICAgICAgIH0gY2F0Y2ggKGV4KSB7XG4gICAgICAgICAgaWYgKGV4IGluc3RhbmNlb2YgTWF0Y2hFcnJvcikge1xuICAgICAgICAgICAgdGhyb3cgZXg7XG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICB9XG5cbiAgICAgIGlmIChjYXRjaF9mdW4pIHtcbiAgICAgICAgdHJ5IHtcbiAgICAgICAgICBleF9yZXN1bHQgPSBjYXRjaF9mdW4oZSk7XG4gICAgICAgICAgcmV0dXJuIGV4X3Jlc3VsdDtcbiAgICAgICAgfSBjYXRjaCAoZXgpIHtcbiAgICAgICAgICBpZiAoZXggaW5zdGFuY2VvZiBNYXRjaEVycm9yKSB7XG4gICAgICAgICAgICB0aHJvdyBleDtcbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgIH1cblxuICAgICAgdGhyb3cgZTtcbiAgICB9IGZpbmFsbHkge1xuICAgICAgaWYgKGFmdGVyX2Z1bmN0aW9uKSB7XG4gICAgICAgIGFmdGVyX2Z1bmN0aW9uKCk7XG4gICAgICB9XG4gICAgfVxuXG4gICAgaWYgKGVsc2VfZnVuY3Rpb24pIHtcbiAgICAgIHRyeSB7XG4gICAgICAgIHJldHVybiBlbHNlX2Z1bmN0aW9uKHJlc3VsdCk7XG4gICAgICB9IGNhdGNoIChleCkge1xuICAgICAgICBpZiAoZXggaW5zdGFuY2VvZiBNYXRjaEVycm9yKSB7XG4gICAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdObyBNYXRjaCBGb3VuZCBpbiBFbHNlJyk7XG4gICAgICAgIH1cblxuICAgICAgICB0aHJvdyBleDtcbiAgICAgIH1cbiAgICB9IGVsc2Uge1xuICAgICAgcmV0dXJuIHJlc3VsdDtcbiAgICB9XG4gIH1cblxufTtcblxuZnVuY3Rpb24gdG9fc3RyaW5nJDEodHVwbGUpIHtcbiAgcmV0dXJuIHR1cGxlLnRvU3RyaW5nKCk7XG59O1xuXG5mdW5jdGlvbiBkZWxldGVfYXQodHVwbGUsIGluZGV4KSB7XG4gIGxldCBuZXdfbGlzdCA9IFtdO1xuXG4gIGZvciAodmFyIGkgPSAwOyBpIDwgdHVwbGUuY291bnQoKTsgaSsrKSB7XG4gICAgaWYgKGkgIT09IGluZGV4KSB7XG4gICAgICBuZXdfbGlzdC5wdXNoKHR1cGxlLmdldChpKSk7XG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIEtlcm5lbC5TcGVjaWFsRm9ybXMudHVwbGUuYXBwbHkobnVsbCwgbmV3X2xpc3QpO1xufTtcblxuZnVuY3Rpb24gZHVwbGljYXRlKGRhdGEsIHNpemUpIHtcbiAgbGV0IGFycmF5ID0gW107XG5cbiAgZm9yICh2YXIgaSA9IHNpemUgLSAxOyBpID49IDA7IGktLSkge1xuICAgIGFycmF5LnB1c2goZGF0YSk7XG4gIH1cblxuICByZXR1cm4gS2VybmVsLlNwZWNpYWxGb3Jtcy50dXBsZS5hcHBseShudWxsLCBhcnJheSk7XG59O1xuXG5mdW5jdGlvbiBpbnNlcnRfYXQodHVwbGUsIGluZGV4LCB0ZXJtKSB7XG4gIGxldCBuZXdfdHVwbGUgPSBbXTtcblxuICBmb3IgKHZhciBpID0gMDsgaSA8PSB0dXBsZS5jb3VudCgpOyBpKyspIHtcbiAgICBpZiAoaSA9PT0gaW5kZXgpIHtcbiAgICAgIG5ld190dXBsZS5wdXNoKHRlcm0pO1xuICAgICAgaSsrO1xuICAgICAgbmV3X3R1cGxlLnB1c2godHVwbGUuZ2V0KGkpKTtcbiAgICB9IGVsc2Uge1xuICAgICAgbmV3X3R1cGxlLnB1c2godHVwbGUuZ2V0KGkpKTtcbiAgICB9XG4gIH1cblxuICByZXR1cm4gS2VybmVsLlNwZWNpYWxGb3Jtcy50dXBsZS5hcHBseShudWxsLCBuZXdfdHVwbGUpO1xufTtcblxuZnVuY3Rpb24gZnJvbV9saXN0KGxpc3QpIHtcbiAgcmV0dXJuIEtlcm5lbC5TcGVjaWFsRm9ybXMudHVwbGUuYXBwbHkobnVsbCwgbGlzdCk7XG59O1xuXG5mdW5jdGlvbiB0b19saXN0KHR1cGxlKSB7XG4gIGxldCBuZXdfbGlzdCA9IFtdO1xuXG4gIGZvciAodmFyIGkgPSAwOyBpIDwgdHVwbGUuY291bnQoKTsgaSsrKSB7XG4gICAgbmV3X2xpc3QucHVzaCh0dXBsZS5nZXQoaSkpO1xuICB9XG5cbiAgcmV0dXJuIEtlcm5lbC5TcGVjaWFsRm9ybXMubGlzdCguLi5uZXdfbGlzdCk7XG59O1xuXG52YXIgVHVwbGUgPSB7XG4gIHRvX3N0cmluZzogdG9fc3RyaW5nJDEsXG4gIGRlbGV0ZV9hdCxcbiAgZHVwbGljYXRlLFxuICBpbnNlcnRfYXQsXG4gIGZyb21fbGlzdCxcbiAgdG9fbGlzdFxufTtcblxuLy9odHRwczovL2dpdGh1Yi5jb20vYWlycG9ydHloL3Byb3RvbW9ycGhpc21cbmNsYXNzIFByb3RvY29sIHtcbiAgY29uc3RydWN0b3Ioc3BlYykge1xuICAgIHRoaXMucmVnaXN0cnkgPSBuZXcgTWFwKCk7XG4gICAgdGhpcy5mYWxsYmFjayA9IG51bGw7XG5cbiAgICBmb3IgKGxldCBmdW5OYW1lIGluIHNwZWMpIHtcbiAgICAgIHRoaXNbZnVuTmFtZV0gPSBjcmVhdGVGdW4oZnVuTmFtZSkuYmluZCh0aGlzKTtcbiAgICB9XG5cbiAgICBmdW5jdGlvbiBjcmVhdGVGdW4oZnVuTmFtZSkge1xuXG4gICAgICByZXR1cm4gZnVuY3Rpb24gKC4uLmFyZ3MpIHtcbiAgICAgICAgbGV0IHRoaW5nID0gYXJnc1swXTtcbiAgICAgICAgbGV0IGZ1biA9IG51bGw7XG5cbiAgICAgICAgaWYgKE51bWJlci5pc0ludGVnZXIodGhpbmcpICYmIHRoaXMuaGFzSW1wbGVtZW50YXRpb24oSW50ZWdlclR5cGUpKSB7XG4gICAgICAgICAgZnVuID0gdGhpcy5yZWdpc3RyeS5nZXQoSW50ZWdlclR5cGUpW2Z1bk5hbWVdO1xuICAgICAgICB9IGVsc2UgaWYgKHR5cGVvZiB0aGluZyA9PT0gXCJudW1iZXJcIiAmJiAhTnVtYmVyLmlzSW50ZWdlcih0aGluZykgJiYgdGhpcy5oYXNJbXBsZW1lbnRhdGlvbihGbG9hdFR5cGUpKSB7XG4gICAgICAgICAgZnVuID0gdGhpcy5yZWdpc3RyeS5nZXQoRmxvYXRUeXBlKVtmdW5OYW1lXTtcbiAgICAgICAgfSBlbHNlIGlmICh0aGlzLmhhc0ltcGxlbWVudGF0aW9uKHRoaW5nKSkge1xuICAgICAgICAgIGZ1biA9IHRoaXMucmVnaXN0cnkuZ2V0KHRoaW5nLmNvbnN0cnVjdG9yKVtmdW5OYW1lXTtcbiAgICAgICAgfSBlbHNlIGlmICh0aGlzLmZhbGxiYWNrKSB7XG4gICAgICAgICAgZnVuID0gdGhpcy5mYWxsYmFja1tmdW5OYW1lXTtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmIChmdW4gIT0gbnVsbCkge1xuICAgICAgICAgIGxldCByZXR2YWwgPSBmdW4uYXBwbHkodGhpcywgYXJncyk7XG4gICAgICAgICAgcmV0dXJuIHJldHZhbDtcbiAgICAgICAgfVxuXG4gICAgICAgIHRocm93IG5ldyBFcnJvcihcIk5vIGltcGxlbWVudGF0aW9uIGZvdW5kIGZvciBcIiArIHRoaW5nKTtcbiAgICAgIH07XG4gICAgfVxuICB9XG5cbiAgaW1wbGVtZW50YXRpb24odHlwZSwgaW1wbGVtZW50YXRpb24pIHtcbiAgICBpZiAodHlwZSA9PT0gbnVsbCkge1xuICAgICAgdGhpcy5mYWxsYmFjayA9IGltcGxlbWVudGF0aW9uO1xuICAgIH0gZWxzZSB7XG4gICAgICB0aGlzLnJlZ2lzdHJ5LnNldCh0eXBlLCBpbXBsZW1lbnRhdGlvbik7XG4gICAgfVxuICB9XG5cbiAgaGFzSW1wbGVtZW50YXRpb24odGhpbmcpIHtcbiAgICByZXR1cm4gdGhpcy5yZWdpc3RyeS5oYXModGhpbmcuY29uc3RydWN0b3IpO1xuICB9XG59XG5cbmZ1bmN0aW9uIHRsKGxpc3QpIHtcbiAgcmV0dXJuIFNwZWNpYWxGb3Jtcy5saXN0KC4uLmxpc3Quc2xpY2UoMSkpO1xufVxuXG5mdW5jdGlvbiBoZChsaXN0KSB7XG4gIHJldHVybiBsaXN0WzBdO1xufVxuXG5mdW5jdGlvbiBpc19uaWwoeCkge1xuICByZXR1cm4geCA9PT0gbnVsbDtcbn1cblxuZnVuY3Rpb24gaXNfYXRvbSh4KSB7XG4gIHJldHVybiB0eXBlb2YgeCA9PT0gJ3N5bWJvbCc7XG59XG5cbmZ1bmN0aW9uIGlzX2JpbmFyeSh4KSB7XG4gIHJldHVybiB0eXBlb2YgeCA9PT0gJ3N0cmluZycgfHwgeCBpbnN0YW5jZW9mIFN0cmluZztcbn1cblxuZnVuY3Rpb24gaXNfYm9vbGVhbih4KSB7XG4gIHJldHVybiB0eXBlb2YgeCA9PT0gJ2Jvb2xlYW4nIHx8IHggaW5zdGFuY2VvZiBCb29sZWFuO1xufVxuXG5mdW5jdGlvbiBpc19mdW5jdGlvbih4LCBhcml0eSA9IC0xKSB7XG4gIHJldHVybiB0eXBlb2YgeCA9PT0gJ2Z1bmN0aW9uJyB8fCB4IGluc3RhbmNlb2YgRnVuY3Rpb247XG59XG5cbmZ1bmN0aW9uIGlzX2Zsb2F0KHgpIHtcbiAgcmV0dXJuIGlzX251bWJlcih4KSAmJiAhTnVtYmVyLmlzSW50ZWdlcih4KTtcbn1cblxuZnVuY3Rpb24gaXNfaW50ZWdlcih4KSB7XG4gIHJldHVybiBOdW1iZXIuaXNJbnRlZ2VyKHgpO1xufVxuXG5mdW5jdGlvbiBpc19saXN0KHgpIHtcbiAgcmV0dXJuIHggaW5zdGFuY2VvZiBBcnJheTtcbn1cblxuZnVuY3Rpb24gaXNfbWFwKHgpIHtcbiAgcmV0dXJuIHR5cGVvZiB4ID09PSAnb2JqZWN0JyB8fCB4IGluc3RhbmNlb2YgT2JqZWN0O1xufVxuXG5mdW5jdGlvbiBpc19udW1iZXIoeCkge1xuICByZXR1cm4gdHlwZW9mIHggPT09ICdudW1iZXInO1xufVxuXG5mdW5jdGlvbiBpc190dXBsZSh4KSB7XG4gIHJldHVybiB4IGluc3RhbmNlb2YgVHVwbGUkMTtcbn1cblxuZnVuY3Rpb24gbGVuZ3RoKHgpIHtcbiAgcmV0dXJuIHgubGVuZ3RoO1xufVxuXG5mdW5jdGlvbiBpc19waWQoeCkge1xuICByZXR1cm4geCBpbnN0YW5jZW9mIFBJRDtcbn1cblxuZnVuY3Rpb24gaXNfcG9ydCh4KSB7XG4gIHJldHVybiBmYWxzZTtcbn1cblxuZnVuY3Rpb24gaXNfcmVmZXJlbmNlKHgpIHtcbiAgcmV0dXJuIGZhbHNlO1xufVxuXG5mdW5jdGlvbiBpc19iaXRzdHJpbmcoeCkge1xuICByZXR1cm4gaXNfYmluYXJ5KHgpIHx8IHggaW5zdGFuY2VvZiBCaXRTdHJpbmc7XG59XG5cbmZ1bmN0aW9uIF9faW5fXyhsZWZ0LCByaWdodCkge1xuICBmb3IgKGxldCB4IG9mIHJpZ2h0KSB7XG4gICAgaWYgKG1hdGNoX19xbWFya19fKGxlZnQsIHgpKSB7XG4gICAgICByZXR1cm4gdHJ1ZTtcbiAgICB9XG4gIH1cblxuICByZXR1cm4gZmFsc2U7XG59XG5cbmZ1bmN0aW9uIGFicyhudW1iZXIpIHtcbiAgcmV0dXJuIE1hdGguYWJzKG51bWJlcik7XG59XG5cbmZ1bmN0aW9uIHJvdW5kKG51bWJlcikge1xuICByZXR1cm4gTWF0aC5yb3VuZChudW1iZXIpO1xufVxuXG5mdW5jdGlvbiBlbGVtKHR1cGxlLCBpbmRleCkge1xuICBpZiAoaXNfbGlzdCh0dXBsZSkpIHtcbiAgICByZXR1cm4gdHVwbGVbaW5kZXhdO1xuICB9XG5cbiAgcmV0dXJuIHR1cGxlLmdldChpbmRleCk7XG59XG5cbmZ1bmN0aW9uIHJlbShsZWZ0LCByaWdodCkge1xuICByZXR1cm4gbGVmdCAlIHJpZ2h0O1xufVxuXG5mdW5jdGlvbiBkaXYobGVmdCwgcmlnaHQpIHtcbiAgcmV0dXJuIGxlZnQgLyByaWdodDtcbn1cblxuZnVuY3Rpb24gYW5kKGxlZnQsIHJpZ2h0KSB7XG4gIHJldHVybiBsZWZ0ICYmIHJpZ2h0O1xufVxuXG5mdW5jdGlvbiBvcihsZWZ0LCByaWdodCkge1xuICByZXR1cm4gbGVmdCB8fCByaWdodDtcbn1cblxuZnVuY3Rpb24gbm90KGFyZykge1xuICByZXR1cm4gIWFyZztcbn1cblxuZnVuY3Rpb24gYXBwbHkoLi4uYXJncykge1xuICBpZiAoYXJncy5sZW5ndGggPT09IDMpIHtcbiAgICBsZXQgbW9kID0gYXJnc1swXTtcbiAgICBsZXQgZnVuYyA9IGFyZ3NbMV07XG4gICAgbGV0IGZ1bmNfYXJncyA9IGFyZ3NbMl07XG4gICAgcmV0dXJuIG1vZFtmdW5jXS5hcHBseShudWxsLCBmdW5jX2FyZ3MpO1xuICB9IGVsc2Uge1xuICAgIGxldCBmdW5jID0gYXJnc1swXTtcbiAgICBsZXQgZnVuY19hcmdzID0gYXJnc1sxXTtcblxuICAgIHJldHVybiBmdW5jLmFwcGx5KG51bGwsIGZ1bmNfYXJncyk7XG4gIH1cbn1cblxuZnVuY3Rpb24gdG9fc3RyaW5nKGFyZykge1xuICBpZiAoaXNfdHVwbGUoYXJnKSkge1xuICAgIHJldHVybiBUdXBsZS50b19zdHJpbmcoYXJnKTtcbiAgfVxuXG4gIHJldHVybiBhcmcudG9TdHJpbmcoKTtcbn1cblxuZnVuY3Rpb24gbWF0Y2hfX3FtYXJrX18ocGF0dGVybiwgZXhwciwgZ3VhcmQgPSAoKSA9PiB0cnVlKSB7XG4gIHJldHVybiBtYXRjaF9ub190aHJvdyhwYXR0ZXJuLCBleHByLCBndWFyZCkgIT0gbnVsbDtcbn1cblxuZnVuY3Rpb24gZGVmc3RydWN0KGRlZmF1bHRzKSB7XG4gIHJldHVybiBjbGFzcyB7XG4gICAgY29uc3RydWN0b3IodXBkYXRlID0ge30pIHtcbiAgICAgIGxldCB0aGVfdmFsdWVzID0gT2JqZWN0LmFzc2lnbihkZWZhdWx0cywgdXBkYXRlKTtcbiAgICAgIE9iamVjdC5hc3NpZ24odGhpcywgdGhlX3ZhbHVlcyk7XG4gICAgfVxuXG4gICAgc3RhdGljIGNyZWF0ZSh1cGRhdGVzID0ge30pIHtcbiAgICAgIGxldCB4ID0gbmV3IHRoaXModXBkYXRlcyk7XG4gICAgICByZXR1cm4gT2JqZWN0LmZyZWV6ZSh4KTtcbiAgICB9XG4gIH07XG59XG5cbmZ1bmN0aW9uIGRlZnByb3RvY29sKHNwZWMpIHtcbiAgcmV0dXJuIG5ldyBQcm90b2NvbChzcGVjKTtcbn1cblxuZnVuY3Rpb24gZGVmaW1wbChwcm90b2NvbCwgdHlwZSwgaW1wbCkge1xuICBwcm90b2NvbC5pbXBsZW1lbnRhdGlvbih0eXBlLCBpbXBsKTtcbn1cblxudmFyIEtlcm5lbCA9IHtcbiAgU3BlY2lhbEZvcm1zLFxuICB0bCxcbiAgaGQsXG4gIGlzX25pbCxcbiAgaXNfYXRvbSxcbiAgaXNfYmluYXJ5LFxuICBpc19ib29sZWFuLFxuICBpc19mdW5jdGlvbixcbiAgaXNfZmxvYXQsXG4gIGlzX2ludGVnZXIsXG4gIGlzX2xpc3QsXG4gIGlzX21hcCxcbiAgaXNfbnVtYmVyLFxuICBpc190dXBsZSxcbiAgbGVuZ3RoLFxuICBpc19waWQsXG4gIGlzX3BvcnQsXG4gIGlzX3JlZmVyZW5jZSxcbiAgaXNfYml0c3RyaW5nLFxuICBpbjogX19pbl9fLFxuICBhYnMsXG4gIHJvdW5kLFxuICBlbGVtLFxuICByZW0sXG4gIGRpdixcbiAgYW5kLFxuICBvcixcbiAgbm90LFxuICBhcHBseSxcbiAgdG9fc3RyaW5nLFxuICBtYXRjaF9fcW1hcmtfXyxcbiAgZGVmc3RydWN0LFxuICBkZWZwcm90b2NvbCxcbiAgZGVmaW1wbFxufTtcblxubGV0IEF0b20gPSB7fTtcblxuQXRvbS50b19zdHJpbmcgPSBmdW5jdGlvbiAoYXRvbSkge1xuICByZXR1cm4gU3ltYm9sLmtleUZvcihhdG9tKTtcbn07XG5cbkF0b20udG9fY2hhcl9saXN0ID0gZnVuY3Rpb24gKGF0b20pIHtcbiAgcmV0dXJuIEF0b20udG9fc3RyaW5nKGF0b20pLnNwbGl0KCcnKTtcbn07XG5cbmxldCBJbnRlZ2VyID0ge1xuXG4gIGlzX2V2ZW46IGZ1bmN0aW9uIChuKSB7XG4gICAgcmV0dXJuIG4gJSAyID09PSAwO1xuICB9LFxuXG4gIGlzX29kZDogZnVuY3Rpb24gKG4pIHtcbiAgICByZXR1cm4gbiAlIDIgIT09IDA7XG4gIH0sXG5cbiAgcGFyc2U6IGZ1bmN0aW9uIChiaW4pIHtcbiAgICBsZXQgcmVzdWx0ID0gcGFyc2VJbnQoYmluKTtcblxuICAgIGlmIChpc05hTihyZXN1bHQpKSB7XG4gICAgICByZXR1cm4gS2VybmVsLlNwZWNpYWxGb3Jtcy5hdG9tKFwiZXJyb3JcIik7XG4gICAgfVxuXG4gICAgbGV0IGluZGV4T2ZEb3QgPSBiaW4uaW5kZXhPZihcIi5cIik7XG5cbiAgICBpZiAoaW5kZXhPZkRvdCA+PSAwKSB7XG4gICAgICByZXR1cm4gS2VybmVsLlNwZWNpYWxGb3Jtcy50dXBsZShyZXN1bHQsIGJpbi5zdWJzdHJpbmcoaW5kZXhPZkRvdCkpO1xuICAgIH1cblxuICAgIHJldHVybiBLZXJuZWwuU3BlY2lhbEZvcm1zLnR1cGxlKHJlc3VsdCwgXCJcIik7XG4gIH0sXG5cbiAgdG9fY2hhcl9saXN0OiBmdW5jdGlvbiAobnVtYmVyLCBiYXNlID0gMTApIHtcbiAgICByZXR1cm4gbnVtYmVyLnRvU3RyaW5nKGJhc2UpLnNwbGl0KFwiXCIpO1xuICB9LFxuXG4gIHRvX3N0cmluZzogZnVuY3Rpb24gKG51bWJlciwgYmFzZSA9IDEwKSB7XG4gICAgcmV0dXJuIG51bWJlci50b1N0cmluZyhiYXNlKTtcbiAgfVxufTtcblxubGV0IENoYXJzJDEgPSBLZXJuZWwuZGVmcHJvdG9jb2woe1xuICB0b19zdHJpbmc6IGZ1bmN0aW9uICh0aGluZykge31cbn0pO1xuXG5LZXJuZWwuZGVmaW1wbChDaGFycyQxLCBCaXRTdHJpbmcsIHtcbiAgdG9fc3RyaW5nOiBmdW5jdGlvbiAodGhpbmcpIHtcbiAgICBpZiAoS2VybmVsLmlzX2JpbmFyeSh0aGluZykpIHtcbiAgICAgIHJldHVybiB0aGluZztcbiAgICB9XG5cbiAgICByZXR1cm4gdGhpbmcudG9TdHJpbmcoKTtcbiAgfVxufSk7XG5cbktlcm5lbC5kZWZpbXBsKENoYXJzJDEsIFN5bWJvbCwge1xuICB0b19zdHJpbmc6IGZ1bmN0aW9uICh0aGluZykge1xuICAgIGlmIChuaWwpIHtcbiAgICAgIHJldHVybiBcIlwiO1xuICAgIH1cblxuICAgIHJldHVybiBBdG9tLnRvX3N0cmluZyh0aGluZyk7XG4gIH1cbn0pO1xuXG5LZXJuZWwuZGVmaW1wbChDaGFycyQxLCBJbnRlZ2VyVHlwZSwge1xuICB0b19zdHJpbmc6IGZ1bmN0aW9uICh0aGluZykge1xuICAgIHJldHVybiBJbnRlZ2VyLnRvX3N0cmluZyh0aGluZyk7XG4gIH1cbn0pO1xuXG5LZXJuZWwuZGVmaW1wbChDaGFycyQxLCBGbG9hdFR5cGUsIHtcbiAgdG9fc3RyaW5nOiBmdW5jdGlvbiAodGhpbmcpIHtcbiAgICByZXR1cm4gdGhpbmcudG9TdHJpbmc7XG4gIH1cbn0pO1xuXG5LZXJuZWwuZGVmaW1wbChDaGFycyQxLCBBcnJheSwge1xuICB0b19zdHJpbmc6IGZ1bmN0aW9uICh0aGluZykge1xuICAgIHJldHVybiB0aGluZy50b1N0cmluZygpO1xuICB9XG59KTtcblxuS2VybmVsLmRlZmltcGwoQ2hhcnMkMSwgVHVwbGUkMSwge1xuICB0b19zdHJpbmc6IGZ1bmN0aW9uICh0aGluZykge1xuICAgIHJldHVybiBUdXBsZS50b19zdHJpbmcodGhpbmcpO1xuICB9XG59KTtcblxuS2VybmVsLmRlZmltcGwoQ2hhcnMkMSwgbnVsbCwge1xuICB0b19zdHJpbmc6IGZ1bmN0aW9uICh0aGluZykge1xuICAgIHJldHVybiB0aGluZy50b1N0cmluZygpO1xuICB9XG59KTtcblxuZnVuY3Rpb24gdG9fYXRvbShzdHJpbmcpIHtcbiAgcmV0dXJuIFN5bWJvbC5mb3Ioc3RyaW5nKTtcbn1cblxuZnVuY3Rpb24gdG9fZXhpc3RpbmdfYXRvbShzdHJpbmcpIHtcbiAgcmV0dXJuIFN5bWJvbC5mb3Ioc3RyaW5nKTtcbn1cblxuZnVuY3Rpb24gdG9fY2hhcl9saXN0KHN0cmluZykge1xuICByZXR1cm4gc3RyaW5nLnNwbGl0KCcnKTtcbn1cblxuZnVuY3Rpb24gdG9fZmxvYXQoc3RyaW5nKSB7XG4gIHJldHVybiBwYXJzZUZsb2F0KHN0cmluZyk7XG59XG5cbmZ1bmN0aW9uIHRvX2ludGVnZXIoc3RyaW5nLCBiYXNlID0gMTApIHtcbiAgcmV0dXJuIHBhcnNlSW50KHN0cmluZywgYmFzZSk7XG59XG5cbmZ1bmN0aW9uIHVwY2FzZShiaW5hcnkpIHtcbiAgcmV0dXJuIGJpbmFyeS50b1VwcGVyQ2FzZSgpO1xufVxuXG5mdW5jdGlvbiBkb3duY2FzZShiaW5hcnkpIHtcbiAgcmV0dXJuIGJpbmFyeS50b0xvd2VyQ2FzZSgpO1xufVxuXG5mdW5jdGlvbiBhdChzdHJpbmcsIHBvc2l0aW9uKSB7XG4gIGlmIChwb3NpdGlvbiA+IHN0cmluZy5sZW5ndGggLSAxKSB7XG4gICAgcmV0dXJuIG51bGw7XG4gIH1cblxuICByZXR1cm4gc3RyaW5nW3Bvc2l0aW9uXTtcbn1cblxuZnVuY3Rpb24gY2FwaXRhbGl6ZShzdHJpbmcpIHtcbiAgbGV0IHJldHVyblN0cmluZyA9ICcnO1xuXG4gIGZvciAobGV0IGkgPSAwOyBpIDwgc3RyaW5nLmxlbmd0aDsgaSsrKSB7XG4gICAgaWYgKGkgPT09IDApIHtcbiAgICAgIHJldHVyblN0cmluZyA9IHJldHVyblN0cmluZyArIHN0cmluZ1tpXS50b1VwcGVyQ2FzZSgpO1xuICAgIH0gZWxzZSB7XG4gICAgICByZXR1cm5TdHJpbmcgPSByZXR1cm5TdHJpbmcgKyBzdHJpbmdbaV0udG9Mb3dlckNhc2UoKTtcbiAgICB9XG4gIH1cblxuICByZXR1cm4gcmV0dXJuU3RyaW5nO1xufVxuXG5mdW5jdGlvbiBjb2RlcG9pbnRzKHN0cmluZykge1xuICByZXR1cm4gdG9fY2hhcl9saXN0KHN0cmluZykubWFwKGZ1bmN0aW9uIChjKSB7XG4gICAgcmV0dXJuIGMuY29kZVBvaW50QXQoMCk7XG4gIH0pO1xufVxuXG5mdW5jdGlvbiBjb250YWluc19fcW1fXyhzdHJpbmcsIGNvbnRhaW5zKSB7XG4gIGlmIChBcnJheS5pc0FycmF5KGNvbnRhaW5zKSkge1xuICAgIHJldHVybiBjb250YWlucy5zb21lKGZ1bmN0aW9uIChzKSB7XG4gICAgICByZXR1cm4gc3RyaW5nLmluZGV4T2YocykgPiAtMTtcbiAgICB9KTtcbiAgfVxuXG4gIHJldHVybiBzdHJpbmcuaW5kZXhPZihjb250YWlucykgPiAtMTtcbn1cblxuZnVuY3Rpb24gZHVwbGljYXRlJDEoc3ViamVjdCwgbikge1xuICByZXR1cm4gc3ViamVjdC5yZXBlYXQobik7XG59XG5cbmZ1bmN0aW9uIGVuZHNfd2l0aF9fcW1fXyhzdHJpbmcsIHN1ZmZpeGVzKSB7XG4gIGlmIChBcnJheS5pc0FycmF5KHN1ZmZpeGVzKSkge1xuICAgIHJldHVybiBzdWZmaXhlcy5zb21lKGZ1bmN0aW9uIChzKSB7XG4gICAgICByZXR1cm4gc3RyaW5nLmVuZHNXaXRoKHMpO1xuICAgIH0pO1xuICB9XG5cbiAgcmV0dXJuIHN0cmluZy5lbmRzV2l0aChzdWZmaXhlcyk7XG59XG5cbmZ1bmN0aW9uIGZpcnN0KHN0cmluZykge1xuICBpZiAoIXN0cmluZykge1xuICAgIHJldHVybiBudWxsO1xuICB9XG5cbiAgcmV0dXJuIHN0cmluZ1swXTtcbn1cblxuZnVuY3Rpb24gZ3JhcGhlbWVzKHN0cmluZykge1xuICByZXR1cm4gc3RyaW5nLnNwbGl0KCcnKTtcbn1cblxuZnVuY3Rpb24gbGFzdChzdHJpbmcpIHtcbiAgaWYgKCFzdHJpbmcpIHtcbiAgICByZXR1cm4gbnVsbDtcbiAgfVxuXG4gIHJldHVybiBzdHJpbmdbc3RyaW5nLmxlbmd0aCAtIDFdO1xufVxuXG5mdW5jdGlvbiBsZW5ndGgkMShzdHJpbmcpIHtcbiAgcmV0dXJuIHN0cmluZy5sZW5ndGg7XG59XG5cbmZ1bmN0aW9uIG1hdGNoX19xbV9fKHN0cmluZywgcmVnZXgpIHtcbiAgcmV0dXJuIHN0cmluZy5tYXRjaChyZWdleCkgIT0gbnVsbDtcbn1cblxuZnVuY3Rpb24gbmV4dF9jb2RlcG9pbnQoc3RyaW5nKSB7XG4gIGlmICghc3RyaW5nIHx8IHN0cmluZyA9PT0gJycpIHtcbiAgICByZXR1cm4gbnVsbDtcbiAgfVxuXG4gIHJldHVybiBLZXJuZWwuU3BlY2lhbEZvcm1zLnR1cGxlKHN0cmluZ1swXS5jb2RlUG9pbnRBdCgwKSwgc3RyaW5nLnN1YnN0cigxKSk7XG59XG5cbmZ1bmN0aW9uIG5leHRfZ3JhcGhlbWUoc3RyaW5nKSB7XG4gIGlmICghc3RyaW5nIHx8IHN0cmluZyA9PT0gJycpIHtcbiAgICByZXR1cm4gbnVsbDtcbiAgfVxuXG4gIHJldHVybiBLZXJuZWwuU3BlY2lhbEZvcm1zLnR1cGxlKHN0cmluZ1swXSwgc3RyaW5nLnN1YnN0cigxKSk7XG59XG5cbmZ1bmN0aW9uIHJldmVyc2Uoc3RyaW5nKSB7XG4gIGxldCByZXR1cm5WYWx1ZSA9ICcnO1xuXG4gIGZvciAodmFyIGkgPSBzdHJpbmcubGVuZ3RoIC0gMTsgaSA+PSAwOyBpLS0pIHtcbiAgICByZXR1cm5WYWx1ZSA9IHJldHVyblZhbHVlICsgc3RyaW5nW2ldO1xuICB9O1xuXG4gIHJldHVybiByZXR1cm5WYWx1ZTtcbn1cblxuZnVuY3Rpb24gc3BsaXQoc3RyaW5nKSB7XG4gIHJldHVybiBzdHJpbmcuc3BsaXQoKTtcbn1cblxuZnVuY3Rpb24gc3RhcnRzX3dpdGhfX3FtX18oc3RyaW5nLCBwcmVmaXhlcykge1xuICBpZiAoQXJyYXkuaXNBcnJheShwcmVmaXhlcykpIHtcbiAgICByZXR1cm4gcHJlZml4ZXMuc29tZShmdW5jdGlvbiAocykge1xuICAgICAgcmV0dXJuIHN0cmluZy5zdGFydHNXaXRoKHMpO1xuICAgIH0pO1xuICB9XG5cbiAgcmV0dXJuIHN0cmluZy5zdGFydHNXaXRoKHByZWZpeGVzKTtcbn1cblxuZnVuY3Rpb24gdmFsaWRfY2hhcmFjdGVyX19xbV9fKGNvZGVwb2ludCkge1xuICB0cnkge1xuICAgIHJldHVybiBTdHJpbmcuZnJvbUNvZGVQb2ludChjb2RlcG9pbnQpICE9IG51bGw7XG4gIH0gY2F0Y2ggKGUpIHtcbiAgICByZXR1cm4gZmFsc2U7XG4gIH1cbn1cblxudmFyIFN0cmluZyQxID0ge1xuICBhdCxcbiAgY2FwaXRhbGl6ZSxcbiAgY29kZXBvaW50cyxcbiAgY29udGFpbnNfX3FtX18sXG4gIGRvd25jYXNlLFxuICBkdXBsaWNhdGU6IGR1cGxpY2F0ZSQxLFxuICBlbmRzX3dpdGhfX3FtX18sXG4gIGZpcnN0LFxuICBncmFwaGVtZXMsXG4gIGxhc3QsXG4gIGxlbmd0aDogbGVuZ3RoJDEsXG4gIG1hdGNoX19xbV9fLFxuICBuZXh0X2NvZGVwb2ludCxcbiAgbmV4dF9ncmFwaGVtZSxcbiAgcmV2ZXJzZSxcbiAgc3BsaXQsXG4gIHN0YXJ0c193aXRoX19xbV9fLFxuICB0b19hdG9tLFxuICB0b19jaGFyX2xpc3QsXG4gIHRvX2V4aXN0aW5nX2F0b20sXG4gIHRvX2Zsb2F0LFxuICB0b19pbnRlZ2VyLFxuICB1cGNhc2UsXG4gIHZhbGlkX2NoYXJhY3Rlcl9fcW1fXyxcbiAgQ2hhcnM6IENoYXJzJDFcbn07XG5cbmxldCBDaGFycyA9IEtlcm5lbC5kZWZwcm90b2NvbCh7XG4gIHRvX2NoYXJfbGlzdDogZnVuY3Rpb24gKHRoaW5nKSB7fVxufSk7XG5cbktlcm5lbC5kZWZpbXBsKENoYXJzLCBCaXRTdHJpbmcsIHtcbiAgdG9fY2hhcl9saXN0OiBmdW5jdGlvbiAodGhpbmcpIHtcbiAgICBpZiAoS2VybmVsLmlzX2JpbmFyeSh0aGluZykpIHtcbiAgICAgIHJldHVybiBTdHJpbmckMS50b19jaGFyX2xpc3QodGhpbmcpO1xuICAgIH1cblxuICAgIHJldHVybiB0aGluZy50b1N0cmluZygpO1xuICB9XG59KTtcblxuS2VybmVsLmRlZmltcGwoQ2hhcnMsIFN5bWJvbCwge1xuICB0b19jaGFyX2xpc3Q6IGZ1bmN0aW9uICh0aGluZykge1xuICAgIHJldHVybiBBdG9tLnRvX2NoYXJfbGlzdCh0aGluZyk7XG4gIH1cbn0pO1xuXG5LZXJuZWwuZGVmaW1wbChDaGFycywgSW50ZWdlclR5cGUsIHtcbiAgdG9fY2hhcl9saXN0OiBmdW5jdGlvbiAodGhpbmcpIHtcbiAgICByZXR1cm4gSW50ZWdlci50b19jaGFyX2xpc3QodGhpbmcpO1xuICB9XG59KTtcblxuS2VybmVsLmRlZmltcGwoQ2hhcnMsIEFycmF5LCB7XG4gIHRvX2NoYXJfbGlzdDogZnVuY3Rpb24gKHRoaW5nKSB7XG4gICAgcmV0dXJuIHRoaW5nO1xuICB9XG59KTtcblxubGV0IExpc3QgPSB7fTtcblxuTGlzdC5DaGFycyA9IENoYXJzO1xuXG5MaXN0LmRlbGV0ZSA9IGZ1bmN0aW9uIChsaXN0LCBpdGVtKSB7XG4gIGxldCBuZXdfdmFsdWUgPSBbXTtcbiAgbGV0IHZhbHVlX2ZvdW5kID0gZmFsc2U7XG5cbiAgZm9yIChsZXQgeCBvZiBsaXN0KSB7XG4gICAgaWYgKHggPT09IGl0ZW0gJiYgdmFsdWVfZm91bmQgIT09IGZhbHNlKSB7XG4gICAgICBuZXdfdmFsdWUucHVzaCh4KTtcbiAgICAgIHZhbHVlX2ZvdW5kID0gdHJ1ZTtcbiAgICB9IGVsc2UgaWYgKHggIT09IGl0ZW0pIHtcbiAgICAgIG5ld192YWx1ZS5wdXNoKHgpO1xuICAgIH1cbiAgfVxuXG4gIHJldHVybiBLZXJuZWwuU3BlY2lhbEZvcm1zLmxpc3QoLi4ubmV3X3ZhbHVlKTtcbn07XG5cbkxpc3QuZGVsZXRlX2F0ID0gZnVuY3Rpb24gKGxpc3QsIGluZGV4KSB7XG4gIGxldCBuZXdfdmFsdWUgPSBbXTtcblxuICBmb3IgKGxldCBpID0gMDsgaSA8IGxpc3QubGVuZ3RoOyBpKyspIHtcbiAgICBpZiAoaSAhPT0gaW5kZXgpIHtcbiAgICAgIG5ld192YWx1ZS5wdXNoKGxpc3RbaV0pO1xuICAgIH1cbiAgfVxuXG4gIHJldHVybiBLZXJuZWwuU3BlY2lhbEZvcm1zLmxpc3QoLi4ubmV3X3ZhbHVlKTtcbn07XG5cbkxpc3QuZHVwbGljYXRlID0gZnVuY3Rpb24gKGVsZW0sIG4pIHtcbiAgbGV0IG5ld192YWx1ZSA9IFtdO1xuXG4gIGZvciAodmFyIGkgPSAwOyBpIDwgbjsgaSsrKSB7XG4gICAgbmV3X3ZhbHVlLnB1c2goZWxlbSk7XG4gIH1cblxuICByZXR1cm4gS2VybmVsLlNwZWNpYWxGb3Jtcy5saXN0KC4uLm5ld192YWx1ZSk7XG59O1xuXG5MaXN0LmZpcnN0ID0gZnVuY3Rpb24gKGxpc3QpIHtcbiAgcmV0dXJuIGxpc3RbMF07XG59O1xuXG5MaXN0LmZsYXR0ZW4gPSBmdW5jdGlvbiAobGlzdCwgdGFpbCA9IEtlcm5lbC5TcGVjaWFsRm9ybXMubGlzdCgpKSB7XG4gIGxldCBuZXdfdmFsdWUgPSBbXTtcblxuICBmb3IgKGxldCB4IG9mIGxpc3QpIHtcbiAgICBpZiAoS2VybmVsLmlzX2xpc3QoeCkpIHtcbiAgICAgIG5ld192YWx1ZSA9IG5ld192YWx1ZS5jb25jYXQoTGlzdC5mbGF0dGVuKHgpKTtcbiAgICB9IGVsc2Uge1xuICAgICAgbmV3X3ZhbHVlLnB1c2goeCk7XG4gICAgfVxuICB9XG5cbiAgbmV3X3ZhbHVlID0gbmV3X3ZhbHVlLmNvbmNhdCh0YWlsKTtcblxuICByZXR1cm4gS2VybmVsLlNwZWNpYWxGb3Jtcy5saXN0KC4uLm5ld192YWx1ZSk7XG59O1xuXG5MaXN0LmZvbGRsID0gZnVuY3Rpb24gKGxpc3QsIGFjYywgZnVuYykge1xuICByZXR1cm4gbGlzdC5yZWR1Y2UoZnVuYywgYWNjKTtcbn07XG5cbkxpc3QuZm9sZHIgPSBmdW5jdGlvbiAobGlzdCwgYWNjLCBmdW5jKSB7XG4gIGxldCBuZXdfYWNjID0gYWNjO1xuXG4gIGZvciAodmFyIGkgPSBsaXN0Lmxlbmd0aCAtIDE7IGkgPj0gMDsgaS0tKSB7XG4gICAgbmV3X2FjYyA9IGZ1bmMobGlzdFtpXSwgbmV3X2FjYyk7XG4gIH1cblxuICByZXR1cm4gbmV3X2FjYztcbn07XG5cbkxpc3QuaW5zZXJ0X2F0ID0gZnVuY3Rpb24gKGxpc3QsIGluZGV4LCB2YWx1ZSkge1xuICBsZXQgbmV3X3ZhbHVlID0gW107XG5cbiAgZm9yIChsZXQgaSA9IDA7IGkgPCBsaXN0Lmxlbmd0aDsgaSsrKSB7XG4gICAgaWYgKGkgPT09IGluZGV4KSB7XG4gICAgICBuZXdfdmFsdWUucHVzaCh2YWx1ZSk7XG4gICAgICBuZXdfdmFsdWUucHVzaChsaXN0W2ldKTtcbiAgICB9IGVsc2Uge1xuICAgICAgbmV3X3ZhbHVlLnB1c2gobGlzdFtpXSk7XG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIEtlcm5lbC5TcGVjaWFsRm9ybXMubGlzdCguLi5uZXdfdmFsdWUpO1xufTtcblxuTGlzdC5rZXlkZWxldGUgPSBmdW5jdGlvbiAobGlzdCwga2V5LCBwb3NpdGlvbikge1xuICBsZXQgbmV3X2xpc3QgPSBbXTtcblxuICBmb3IgKGxldCBpID0gMDsgaSA8IGxpc3QubGVuZ3RoOyBpKyspIHtcbiAgICBpZiAoIUtlcm5lbC5tYXRjaF9fcW1hcmtfXyhsaXN0W2ldW3Bvc2l0aW9uXSwga2V5KSkge1xuICAgICAgbmV3X2xpc3QucHVzaChsaXN0W2ldKTtcbiAgICB9XG4gIH1cblxuICByZXR1cm4gS2VybmVsLlNwZWNpYWxGb3Jtcy5saXN0KC4uLm5ld19saXN0KTtcbn07XG5cbkxpc3Qua2V5ZmluZCA9IGZ1bmN0aW9uIChsaXN0LCBrZXksIHBvc2l0aW9uLCBfZGVmYXVsdCA9IG51bGwpIHtcblxuICBmb3IgKGxldCBpID0gMDsgaSA8IGxpc3QubGVuZ3RoOyBpKyspIHtcbiAgICBpZiAoS2VybmVsLm1hdGNoX19xbWFya19fKGxpc3RbaV1bcG9zaXRpb25dLCBrZXkpKSB7XG4gICAgICByZXR1cm4gbGlzdFtpXTtcbiAgICB9XG4gIH1cblxuICByZXR1cm4gX2RlZmF1bHQ7XG59O1xuXG5MaXN0LmtleW1lbWJlcl9fcW1hcmtfXyA9IGZ1bmN0aW9uIChsaXN0LCBrZXksIHBvc2l0aW9uKSB7XG5cbiAgZm9yIChsZXQgaSA9IDA7IGkgPCBsaXN0Lmxlbmd0aDsgaSsrKSB7XG4gICAgaWYgKEtlcm5lbC5tYXRjaF9fcW1hcmtfXyhsaXN0W2ldW3Bvc2l0aW9uXSwga2V5KSkge1xuICAgICAgcmV0dXJuIHRydWU7XG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIGZhbHNlO1xufTtcblxuTGlzdC5rZXlyZXBsYWNlID0gZnVuY3Rpb24gKGxpc3QsIGtleSwgcG9zaXRpb24sIG5ld190dXBsZSkge1xuICBsZXQgbmV3X2xpc3QgPSBbXTtcblxuICBmb3IgKGxldCBpID0gMDsgaSA8IGxpc3QubGVuZ3RoOyBpKyspIHtcbiAgICBpZiAoIUtlcm5lbC5tYXRjaF9fcW1hcmtfXyhsaXN0W2ldW3Bvc2l0aW9uXSwga2V5KSkge1xuICAgICAgbmV3X2xpc3QucHVzaChsaXN0W2ldKTtcbiAgICB9IGVsc2Uge1xuICAgICAgbmV3X2xpc3QucHVzaChuZXdfdHVwbGUpO1xuICAgIH1cbiAgfVxuXG4gIHJldHVybiBLZXJuZWwuU3BlY2lhbEZvcm1zLmxpc3QoLi4ubmV3X2xpc3QpO1xufTtcblxuTGlzdC5rZXlzb3J0ID0gZnVuY3Rpb24gKGxpc3QsIHBvc2l0aW9uKSB7XG4gIGxldCBuZXdfbGlzdCA9IGxpc3Q7XG5cbiAgbmV3X2xpc3Quc29ydChmdW5jdGlvbiAoYSwgYikge1xuICAgIGlmIChwb3NpdGlvbiA9PT0gMCkge1xuICAgICAgaWYgKGFbcG9zaXRpb25dLnZhbHVlIDwgYltwb3NpdGlvbl0udmFsdWUpIHtcbiAgICAgICAgcmV0dXJuIC0xO1xuICAgICAgfVxuXG4gICAgICBpZiAoYVtwb3NpdGlvbl0udmFsdWUgPiBiW3Bvc2l0aW9uXS52YWx1ZSkge1xuICAgICAgICByZXR1cm4gMTtcbiAgICAgIH1cblxuICAgICAgcmV0dXJuIDA7XG4gICAgfSBlbHNlIHtcbiAgICAgIGlmIChhW3Bvc2l0aW9uXSA8IGJbcG9zaXRpb25dKSB7XG4gICAgICAgIHJldHVybiAtMTtcbiAgICAgIH1cblxuICAgICAgaWYgKGFbcG9zaXRpb25dID4gYltwb3NpdGlvbl0pIHtcbiAgICAgICAgcmV0dXJuIDE7XG4gICAgICB9XG5cbiAgICAgIHJldHVybiAwO1xuICAgIH1cbiAgfSk7XG5cbiAgcmV0dXJuIEtlcm5lbC5TcGVjaWFsRm9ybXMubGlzdCguLi5uZXdfbGlzdCk7XG59O1xuXG5MaXN0LmtleXN0b3JlID0gZnVuY3Rpb24gKGxpc3QsIGtleSwgcG9zaXRpb24sIG5ld190dXBsZSkge1xuICBsZXQgbmV3X2xpc3QgPSBbXTtcbiAgbGV0IHJlcGxhY2VkID0gZmFsc2U7XG5cbiAgZm9yIChsZXQgaSA9IDA7IGkgPCBsaXN0Lmxlbmd0aDsgaSsrKSB7XG4gICAgaWYgKCFLZXJuZWwubWF0Y2hfX3FtYXJrX18obGlzdFtpXVtwb3NpdGlvbl0sIGtleSkpIHtcbiAgICAgIG5ld19saXN0LnB1c2gobGlzdFtpXSk7XG4gICAgfSBlbHNlIHtcbiAgICAgIG5ld19saXN0LnB1c2gobmV3X3R1cGxlKTtcbiAgICAgIHJlcGxhY2VkID0gdHJ1ZTtcbiAgICB9XG4gIH1cblxuICBpZiAoIXJlcGxhY2VkKSB7XG4gICAgbmV3X2xpc3QucHVzaChuZXdfdHVwbGUpO1xuICB9XG5cbiAgcmV0dXJuIEtlcm5lbC5TcGVjaWFsRm9ybXMubGlzdCguLi5uZXdfbGlzdCk7XG59O1xuXG5MaXN0Lmxhc3QgPSBmdW5jdGlvbiAobGlzdCkge1xuICByZXR1cm4gbGlzdFtsaXN0Lmxlbmd0aCAtIDFdO1xufTtcblxuTGlzdC5yZXBsYWNlX2F0ID0gZnVuY3Rpb24gKGxpc3QsIGluZGV4LCB2YWx1ZSkge1xuICBsZXQgbmV3X3ZhbHVlID0gW107XG5cbiAgZm9yIChsZXQgaSA9IDA7IGkgPCBsaXN0Lmxlbmd0aDsgaSsrKSB7XG4gICAgaWYgKGkgPT09IGluZGV4KSB7XG4gICAgICBuZXdfdmFsdWUucHVzaCh2YWx1ZSk7XG4gICAgfSBlbHNlIHtcbiAgICAgIG5ld192YWx1ZS5wdXNoKGxpc3RbaV0pO1xuICAgIH1cbiAgfVxuXG4gIHJldHVybiBLZXJuZWwuU3BlY2lhbEZvcm1zLmxpc3QoLi4ubmV3X3ZhbHVlKTtcbn07XG5cbkxpc3QudXBkYXRlX2F0ID0gZnVuY3Rpb24gKGxpc3QsIGluZGV4LCBmdW4pIHtcbiAgbGV0IG5ld192YWx1ZSA9IFtdO1xuXG4gIGZvciAobGV0IGkgPSAwOyBpIDwgbGlzdC5jb3VudCgpOyBpKyspIHtcbiAgICBpZiAoaSA9PT0gaW5kZXgpIHtcbiAgICAgIG5ld192YWx1ZS5wdXNoKGZ1bihsaXN0LmdldChpKSkpO1xuICAgIH0gZWxzZSB7XG4gICAgICBuZXdfdmFsdWUucHVzaChsaXN0LmdldChpKSk7XG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIG5ld192YWx1ZTtcbn07XG5cbkxpc3Qud3JhcCA9IGZ1bmN0aW9uIChsaXN0KSB7XG4gIGlmIChLZXJuZWwuaXNfbGlzdChsaXN0KSkge1xuICAgIHJldHVybiBsaXN0O1xuICB9IGVsc2UgaWYgKGxpc3QgPT0gbnVsbCkge1xuICAgIHJldHVybiBLZXJuZWwuU3BlY2lhbEZvcm1zLmxpc3QoKTtcbiAgfSBlbHNlIHtcbiAgICByZXR1cm4gS2VybmVsLlNwZWNpYWxGb3Jtcy5saXN0KGxpc3QpO1xuICB9XG59O1xuXG5MaXN0LnppcCA9IGZ1bmN0aW9uIChsaXN0X29mX2xpc3RzKSB7XG4gIGlmIChsaXN0X29mX2xpc3RzLmxlbmd0aCA9PT0gMCkge1xuICAgIHJldHVybiBLZXJuZWwuU3BlY2lhbEZvcm1zLmxpc3QoKTtcbiAgfVxuXG4gIGxldCBuZXdfdmFsdWUgPSBbXTtcbiAgbGV0IHNtYWxsZXN0X2xlbmd0aCA9IGxpc3Rfb2ZfbGlzdHNbMF07XG5cbiAgZm9yIChsZXQgeCBvZiBsaXN0X29mX2xpc3RzKSB7XG4gICAgaWYgKHgubGVuZ3RoIDwgc21hbGxlc3RfbGVuZ3RoKSB7XG4gICAgICBzbWFsbGVzdF9sZW5ndGggPSB4Lmxlbmd0aDtcbiAgICB9XG4gIH1cblxuICBmb3IgKGxldCBpID0gMDsgaSA8IHNtYWxsZXN0X2xlbmd0aDsgaSsrKSB7XG4gICAgbGV0IGN1cnJlbnRfdmFsdWUgPSBbXTtcbiAgICBmb3IgKGxldCBqID0gMDsgaiA8IGxpc3Rfb2ZfbGlzdHMubGVuZ3RoOyBqKyspIHtcbiAgICAgIGN1cnJlbnRfdmFsdWUucHVzaChsaXN0X29mX2xpc3RzW2pdW2ldKTtcbiAgICB9XG5cbiAgICBuZXdfdmFsdWUucHVzaChLZXJuZWwuU3BlY2lhbEZvcm1zLnR1cGxlKC4uLmN1cnJlbnRfdmFsdWUpKTtcbiAgfVxuXG4gIHJldHVybiBLZXJuZWwuU3BlY2lhbEZvcm1zLmxpc3QoLi4ubmV3X3ZhbHVlKTtcbn07XG5cbkxpc3QudG9fdHVwbGUgPSBmdW5jdGlvbiAobGlzdCkge1xuICByZXR1cm4gS2VybmVsLlNwZWNpYWxGb3Jtcy50dXBsZS5hcHBseShudWxsLCBsaXN0KTtcbn07XG5cbkxpc3QuYXBwZW5kID0gZnVuY3Rpb24gKGxpc3QsIHZhbHVlKSB7XG4gIHJldHVybiBLZXJuZWwuU3BlY2lhbEZvcm1zLmxpc3QoLi4ubGlzdC5jb25jYXQoW3ZhbHVlXSkpO1xufTtcblxuTGlzdC5wcmVwZW5kID0gZnVuY3Rpb24gKGxpc3QsIHZhbHVlKSB7XG4gIHJldHVybiBLZXJuZWwuU3BlY2lhbEZvcm1zLmxpc3QoLi4uW3ZhbHVlXS5jb25jYXQobGlzdCkpO1xufTtcblxuTGlzdC5jb25jYXQgPSBmdW5jdGlvbiAobGVmdCwgcmlnaHQpIHtcbiAgcmV0dXJuIGxlZnQuY29uY2F0KHJpZ2h0KTtcbn07XG5cbmxldCBSYW5nZSA9IGZ1bmN0aW9uIChfZmlyc3QsIF9sYXN0KSB7XG4gIGlmICghKHRoaXMgaW5zdGFuY2VvZiBSYW5nZSkpIHtcbiAgICByZXR1cm4gbmV3IFJhbmdlKF9maXJzdCwgX2xhc3QpO1xuICB9XG5cbiAgdGhpcy5maXJzdCA9IGZ1bmN0aW9uICgpIHtcbiAgICByZXR1cm4gX2ZpcnN0O1xuICB9O1xuXG4gIHRoaXMubGFzdCA9IGZ1bmN0aW9uICgpIHtcbiAgICByZXR1cm4gX2xhc3Q7XG4gIH07XG5cbiAgbGV0IF9yYW5nZSA9IFtdO1xuXG4gIGZvciAobGV0IGkgPSBfZmlyc3Q7IGkgPD0gX2xhc3Q7IGkrKykge1xuICAgIF9yYW5nZS5wdXNoKGkpO1xuICB9XG5cbiAgX3JhbmdlID0gT2JqZWN0LmZyZWV6ZShfcmFuZ2UpO1xuXG4gIHRoaXMudmFsdWUgPSBmdW5jdGlvbiAoKSB7XG4gICAgcmV0dXJuIF9yYW5nZTtcbiAgfTtcblxuICB0aGlzLmxlbmd0aCA9IGZ1bmN0aW9uICgpIHtcbiAgICByZXR1cm4gX3JhbmdlLmxlbmd0aDtcbiAgfTtcblxuICByZXR1cm4gdGhpcztcbn07XG5cblJhbmdlLnByb3RvdHlwZVtTeW1ib2wuaXRlcmF0b3JdID0gZnVuY3Rpb24gKCkge1xuICByZXR1cm4gdGhpcy52YWx1ZSgpW1N5bWJvbC5pdGVyYXRvcl0oKTtcbn07XG5cblJhbmdlLm5ldyA9IGZ1bmN0aW9uIChmaXJzdCwgbGFzdCkge1xuICByZXR1cm4gUmFuZ2UoZmlyc3QsIGxhc3QpO1xufTtcblxuUmFuZ2UucmFuZ2VfX3FtYXJrX18gPSBmdW5jdGlvbiAocmFuZ2UpIHtcbiAgcmV0dXJuIHJhbmdlIGluc3RhbmNlb2YgUmFuZ2U7XG59O1xuXG5sZXQgS2V5d29yZCA9IHt9O1xuXG5LZXl3b3JkLmhhc19rZXlfX3FtX18gPSBmdW5jdGlvbiAoa2V5d29yZHMsIGtleSkge1xuICBmb3IgKGxldCBrZXl3b3JkIG9mIGtleXdvcmRzKSB7XG4gICAgaWYgKEtlcm5lbC5lbGVtKGtleXdvcmQsIDApID09IGtleSkge1xuICAgICAgcmV0dXJuIHRydWU7XG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIGZhbHNlO1xufTtcblxuS2V5d29yZC5nZXQgPSBmdW5jdGlvbiAoa2V5d29yZHMsIGtleSwgdGhlX2RlZmF1bHQgPSBudWxsKSB7XG4gIGZvciAobGV0IGtleXdvcmQgb2Yga2V5d29yZHMpIHtcbiAgICBpZiAoS2VybmVsLmVsZW0oa2V5d29yZCwgMCkgPT0ga2V5KSB7XG4gICAgICByZXR1cm4gS2VybmVsLmVsZW0oa2V5d29yZCwgMSk7XG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIHRoZV9kZWZhdWx0O1xufTtcblxubGV0IEFnZW50ID0ge307XG5cbkFnZW50LnN0YXJ0ID0gZnVuY3Rpb24gKGZ1biwgb3B0aW9ucyA9IFtdKSB7XG4gIGxldCBwaWQgPSBzZWxmLnByb2Nlc3Nlcy5zcGF3bigpO1xuXG4gIGlmIChLZXl3b3JkLmhhc19rZXlfX3FtX18ob3B0aW9ucywgS2VybmVsLlNwZWNpYWxGb3Jtcy5hdG9tKCduYW1lJykpKSB7XG4gICAgcGlkID0gc2VsZi5wcm9jZXNzZXMucmVnaXN0ZXIoS2V5d29yZC5nZXQob3B0aW9ucywgS2VybmVsLlNwZWNpYWxGb3Jtcy5hdG9tKCduYW1lJykpLCBwaWQpO1xuICB9XG5cbiAgc2VsZi5wcm9jZXNzZXMucHV0KHBpZCwgJ3N0YXRlJywgZnVuKCkpO1xuICByZXR1cm4gS2VybmVsLlNwZWNpYWxGb3Jtcy50dXBsZShLZXJuZWwuU3BlY2lhbEZvcm1zLmF0b20oJ29rJyksIHBpZCk7XG59O1xuXG5BZ2VudC5zdG9wID0gZnVuY3Rpb24gKGFnZW50LCB0aW1lb3V0ID0gNTAwMCkge1xuICBzZWxmLnByb2Nlc3Nlcy5leGl0KGFnZW50KTtcbiAgcmV0dXJuIEtlcm5lbC5TcGVjaWFsRm9ybXMuYXRvbSgnb2snKTtcbn07XG5cbkFnZW50LnVwZGF0ZSA9IGZ1bmN0aW9uIChhZ2VudCwgZnVuLCB0aW1lb3V0ID0gNTAwMCkge1xuXG4gIGNvbnN0IGN1cnJlbnRfc3RhdGUgPSBzZWxmLnByb2Nlc3Nlcy5nZXQoYWdlbnQsICdzdGF0ZScpO1xuICBzZWxmLnByb2Nlc3Nlcy5wdXQoYWdlbnQsICdzdGF0ZScsIGZ1bihjdXJyZW50X3N0YXRlKSk7XG5cbiAgcmV0dXJuIEtlcm5lbC5TcGVjaWFsRm9ybXMuYXRvbSgnb2snKTtcbn07XG5cbkFnZW50LmdldCA9IGZ1bmN0aW9uIChhZ2VudCwgZnVuLCB0aW1lb3V0ID0gNTAwMCkge1xuICByZXR1cm4gZnVuKHNlbGYucHJvY2Vzc2VzLmdldChhZ2VudCwgJ3N0YXRlJykpO1xufTtcblxuQWdlbnQuZ2V0X2FuZF91cGRhdGUgPSBmdW5jdGlvbiAoYWdlbnQsIGZ1biwgdGltZW91dCA9IDUwMDApIHtcblxuICBjb25zdCBnZXRfYW5kX3VwZGF0ZV90dXBsZSA9IGZ1bihzZWxmLnByb2Nlc3Nlcy5nZXQoYWdlbnQsICdzdGF0ZScpKTtcbiAgc2VsZi5wcm9jZXNzZXMucHV0KGFnZW50LCAnc3RhdGUnLCBLZXJuZWwuZWxlbShnZXRfYW5kX3VwZGF0ZV90dXBsZSwgMSkpO1xuXG4gIHJldHVybiBLZXJuZWwuZWxlbShnZXRfYW5kX3VwZGF0ZV90dXBsZSwgMCk7XG59O1xuXG4vL2h0dHBzOi8vZGV2ZWxvcGVyLm1vemlsbGEub3JnL2VuLVVTL2RvY3MvV2ViL0FQSS9XaW5kb3dCYXNlNjQvQmFzZTY0X2VuY29kaW5nX2FuZF9kZWNvZGluZyNTb2x1dGlvbl8yXyVFMiU4MCU5M19yZXdyaXRlX3RoZV9ET01zX2F0b2IoKV9hbmRfYnRvYSgpX3VzaW5nX0phdmFTY3JpcHQnc19UeXBlZEFycmF5c19hbmRfVVRGLThcbmZ1bmN0aW9uIGI2NEVuY29kZVVuaWNvZGUoc3RyKSB7XG4gIHJldHVybiBidG9hKGVuY29kZVVSSUNvbXBvbmVudChzdHIpLnJlcGxhY2UoLyUoWzAtOUEtRl17Mn0pL2csIGZ1bmN0aW9uIChtYXRjaCwgcDEpIHtcbiAgICByZXR1cm4gU3RyaW5nLmZyb21DaGFyQ29kZSgnMHgnICsgcDEpO1xuICB9KSk7XG59XG5cbmZ1bmN0aW9uIGVuY29kZTY0KGRhdGEpIHtcbiAgcmV0dXJuIGI2NEVuY29kZVVuaWNvZGUoZGF0YSk7XG59XG5cbmZ1bmN0aW9uIGRlY29kZTY0KGRhdGEpIHtcbiAgdHJ5IHtcbiAgICByZXR1cm4gS2VybmVsLlNwZWNpYWxGb3Jtcy50dXBsZShLZXJuZWwuU3BlY2lhbEZvcm1zLmF0b20oJ29rJyksIGF0b2IoZGF0YSkpO1xuICB9IGNhdGNoIChlKSB7XG4gICAgcmV0dXJuIEtlcm5lbC5TcGVjaWFsRm9ybXMuYXRvbSgnZXJyb3InKTtcbiAgfVxuICByZXR1cm4gYnRvYShkYXRhKTtcbn1cblxuZnVuY3Rpb24gZGVjb2RlNjRfX2VtX18oZGF0YSkge1xuICByZXR1cm4gYXRvYihkYXRhKTtcbn1cblxudmFyIGJhc2UgPSB7XG4gIGVuY29kZTY0LFxuICBkZWNvZGU2NCxcbiAgZGVjb2RlNjRfX2VtX19cbn07XG5cbmZ1bmN0aW9uIGJub3QoZXhwcikge1xuICByZXR1cm4gfmV4cHI7XG59XG5cbmZ1bmN0aW9uIGJhbmQobGVmdCwgcmlnaHQpIHtcbiAgcmV0dXJuIGxlZnQgJiByaWdodDtcbn1cblxuZnVuY3Rpb24gYm9yKGxlZnQsIHJpZ2h0KSB7XG4gIHJldHVybiBsZWZ0IHwgcmlnaHQ7XG59XG5cbmZ1bmN0aW9uIGJzbChsZWZ0LCByaWdodCkge1xuICByZXR1cm4gbGVmdCA8PCByaWdodDtcbn1cblxuZnVuY3Rpb24gYnNyKGxlZnQsIHJpZ2h0KSB7XG4gIHJldHVybiBsZWZ0ID4+IHJpZ2h0O1xufVxuXG5mdW5jdGlvbiBieG9yKGxlZnQsIHJpZ2h0KSB7XG4gIHJldHVybiBsZWZ0IF4gcmlnaHQ7XG59XG5cbnZhciBiaXR3aXNlID0ge1xuICBibm90LFxuICBiYW5kLFxuICBib3IsXG4gIGJzbCxcbiAgYnNyLFxuICBieG9yXG59O1xuXG5sZXQgRW51bWVyYWJsZSA9IEtlcm5lbC5kZWZwcm90b2NvbCh7XG4gIGNvdW50OiBmdW5jdGlvbiAoY29sbGVjdGlvbikge30sXG4gIG1lbWJlcl9xbWFya19fOiBmdW5jdGlvbiAoY29sbGVjdGlvbiwgdmFsdWUpIHt9LFxuICByZWR1Y2U6IGZ1bmN0aW9uIChjb2xsZWN0aW9uLCBhY2MsIGZ1bikge31cbn0pO1xuXG5sZXQgQ29sbGVjdGFibGUgPSBLZXJuZWwuZGVmcHJvdG9jb2woe1xuICBpbnRvOiBmdW5jdGlvbiAoY29sbGVjdGFibGUpIHt9XG59KTtcblxubGV0IEluc3BlY3QgPSBLZXJuZWwuZGVmcHJvdG9jb2woe1xuICBpbnNwZWN0OiBmdW5jdGlvbiAodGhpbmcsIG9wdHMpIHt9XG59KTtcblxuZnVuY3Rpb24gX19uZXdfXygpIHtcbiAgcmV0dXJuIFNwZWNpYWxGb3Jtcy5tYXAoe30pO1xufVxuXG5mdW5jdGlvbiBrZXlzKG1hcCkge1xuICByZXR1cm4gT2JqZWN0LmtleXMobWFwKTtcbn1cblxuZnVuY3Rpb24gc2l6ZShtYXApIHtcbiAgcmV0dXJuIGtleXMobWFwKS5sZW5ndGg7XG59XG5cbmZ1bmN0aW9uIHRvX2xpc3QkMShtYXApIHtcbiAgbGV0IG1hcF9rZXlzID0ga2V5cyhtYXApO1xuICBsZXQgbGlzdCA9IFtdO1xuXG4gIGZvciAobGV0IGtleSBvZiBtYXBfa2V5cykge1xuICAgIGxpc3QucHVzaChTcGVjaWFsRm9ybXMudHVwbGUoa2V5LCBtYXBba2V5XSkpO1xuICB9XG5cbiAgcmV0dXJuIFNwZWNpYWxGb3Jtcy5saXN0KC4uLmxpc3QpO1xufVxuXG5mdW5jdGlvbiB2YWx1ZXMobWFwKSB7XG4gIGxldCBtYXBfa2V5cyA9IGtleXMobWFwKTtcbiAgbGV0IGxpc3QgPSBbXTtcblxuICBmb3IgKGxldCBrZXkgb2YgbWFwX2tleXMpIHtcbiAgICBsaXN0LnB1c2gobWFwW2tleV0pO1xuICB9XG5cbiAgcmV0dXJuIFNwZWNpYWxGb3Jtcy5saXN0KC4uLmxpc3QpO1xufVxuXG5mdW5jdGlvbiBmcm9tX3N0cnVjdChzdHJ1Y3QpIHtcbiAgbGV0IG1hcCA9IE9iamVjdC5hc3NpZ24oe30sIHN0cnVjdCk7XG4gIGRlbGV0ZSBtYXBbU3ltYm9sLmZvcihcIl9fc3RydWN0X19cIildO1xuXG4gIHJldHVybiBTcGVjaWFsRm9ybXMubWFwKG1hcCk7XG59XG5cbmZ1bmN0aW9uIF9fZGVsZXRlX18obWFwLCBrZXkpIHtcbiAgbGV0IG5ld19tYXAgPSBPYmplY3QuYXNzaWduKHt9LCBtYXApO1xuXG4gIGRlbGV0ZSBuZXdfbWFwW2tleV07XG5cbiAgcmV0dXJuIFNwZWNpYWxGb3Jtcy5tYXAobmV3X21hcCk7XG59XG5cbmZ1bmN0aW9uIGVxdWFsX19xbWFya19fKG1hcDEsIG1hcDIpIHtcbiAgcmV0dXJuIG1hcDEgPT09IG1hcDI7XG59XG5cbmZ1bmN0aW9uIGZldGNoX19lbWFya19fKG1hcCwga2V5KSB7XG4gIGlmIChrZXkgaW4gbWFwKSB7XG4gICAgcmV0dXJuIG1hcFtrZXldO1xuICB9XG5cbiAgdGhyb3cgbmV3IEVycm9yKFwiS2V5IG5vdCBmb3VuZC5cIik7XG59XG5cbmZ1bmN0aW9uIGZldGNoKG1hcCwga2V5KSB7XG4gIGlmIChrZXkgaW4gbWFwKSB7XG4gICAgcmV0dXJuIFNwZWNpYWxGb3Jtcy50dXBsZShTcGVjaWFsRm9ybXMuYXRvbShcIm9rXCIpLCBtYXBba2V5XSk7XG4gIH1cblxuICByZXR1cm4gU3BlY2lhbEZvcm1zLmF0b20oXCJlcnJvclwiKTtcbn1cblxuZnVuY3Rpb24gaGFzX2tleV9fcW1hcmtfXyhtYXAsIGtleSkge1xuICByZXR1cm4ga2V5IGluIG1hcDtcbn1cblxuZnVuY3Rpb24gc3BsaXQkMShtYXAsIGtleXMpIHtcbiAgbGV0IHNwbGl0MSA9IHt9O1xuICBsZXQgc3BsaXQyID0ge307XG5cbiAgZm9yIChsZXQga2V5IG9mIE9iamVjdC5rZXlzKG1hcCkpIHtcbiAgICBpZiAoa2V5cy5pbmRleE9mKGtleSkgPiAtMSkge1xuICAgICAgc3BsaXQxW2tleV0gPSBtYXBba2V5XTtcbiAgICB9IGVsc2Uge1xuICAgICAgc3BsaXQyW2tleV0gPSBtYXBba2V5XTtcbiAgICB9XG4gIH1cblxuICByZXR1cm4gU3BlY2lhbEZvcm1zLnR1cGxlKFNwZWNpYWxGb3Jtcy5tYXAoc3BsaXQxKSwgU3BlY2lhbEZvcm1zLm1hcChzcGxpdDIpKTtcbn1cblxuZnVuY3Rpb24gdGFrZShtYXAsIGtleXMpIHtcbiAgbGV0IHNwbGl0MSA9IHt9O1xuXG4gIGZvciAobGV0IGtleSBvZiBPYmplY3Qua2V5cyhtYXApKSB7XG4gICAgaWYgKGtleXMuaW5kZXhPZihrZXkpID4gLTEpIHtcbiAgICAgIHNwbGl0MVtrZXldID0gbWFwW2tleV07XG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIFNwZWNpYWxGb3Jtcy5tYXAoc3BsaXQxKTtcbn1cblxuZnVuY3Rpb24gZHJvcChtYXAsIGtleXMpIHtcbiAgbGV0IHNwbGl0MSA9IHt9O1xuXG4gIGZvciAobGV0IGtleSBvZiBPYmplY3Qua2V5cyhtYXApKSB7XG4gICAgaWYgKGtleXMuaW5kZXhPZihrZXkpID09PSAtMSkge1xuICAgICAgc3BsaXQxW2tleV0gPSBtYXBba2V5XTtcbiAgICB9XG4gIH1cblxuICByZXR1cm4gU3BlY2lhbEZvcm1zLm1hcChzcGxpdDEpO1xufVxuXG5mdW5jdGlvbiBwdXRfbmV3KG1hcCwga2V5LCB2YWx1ZSkge1xuICBpZiAoa2V5IGluIG1hcCkge1xuICAgIHJldHVybiBtYXA7XG4gIH1cblxuICBsZXQgbmV3X21hcCA9IE9iamVjdC5hc3NpZ24oe30sIG1hcCk7XG4gIG5ld19tYXBba2V5XSA9IHZhbHVlO1xuXG4gIHJldHVybiBTcGVjaWFsRm9ybXMubWFwKG5ld19tYXApO1xufVxuXG5mdW5jdGlvbiBwdXRfbmV3X2xhenkobWFwLCBrZXksIGZ1bikge1xuICBpZiAoa2V5IGluIG1hcCkge1xuICAgIHJldHVybiBtYXA7XG4gIH1cblxuICBsZXQgbmV3X21hcCA9IE9iamVjdC5hc3NpZ24oe30sIG1hcCk7XG4gIG5ld19tYXBba2V5XSA9IGZ1bigpO1xuXG4gIHJldHVybiBTcGVjaWFsRm9ybXMubWFwKG5ld19tYXApO1xufVxuXG5mdW5jdGlvbiBnZXRfYW5kX3VwZGF0ZShtYXAsIGtleSwgZnVuKSB7XG4gIGlmIChrZXkgaW4gbWFwKSB7XG4gICAgcmV0dXJuIG1hcDtcbiAgfVxuXG4gIGxldCBuZXdfbWFwID0gT2JqZWN0LmFzc2lnbih7fSwgbWFwKTtcbiAgbmV3X21hcFtrZXldID0gZnVuKG1hcFtrZXldKTtcblxuICByZXR1cm4gU3BlY2lhbEZvcm1zLm1hcChuZXdfbWFwKTtcbn1cblxuZnVuY3Rpb24gcG9wX2xhenkobWFwLCBrZXksIGZ1bikge1xuICBpZiAoIWtleSBpbiBtYXApIHtcbiAgICByZXR1cm4gU3BlY2lhbEZvcm1zLnR1cGxlKGZ1bigpLCBtYXApO1xuICB9XG5cbiAgbGV0IG5ld19tYXAgPSBPYmplY3QuYXNzaWduKHt9LCBtYXApO1xuICBsZXQgdmFsdWUgPSBmdW4obmV3X21hcFtrZXldKTtcbiAgZGVsZXRlIG5ld19tYXBba2V5XTtcblxuICByZXR1cm4gU3BlY2lhbEZvcm1zLnR1cGxlKHZhbHVlLCBuZXdfbWFwKTtcbn1cblxuZnVuY3Rpb24gcG9wKG1hcCwga2V5LCBfZGVmYXVsdCA9IG51bGwpIHtcbiAgaWYgKCFrZXkgaW4gbWFwKSB7XG4gICAgcmV0dXJuIFNwZWNpYWxGb3Jtcy50dXBsZShfZGVmYXVsdCwgbWFwKTtcbiAgfVxuXG4gIGxldCBuZXdfbWFwID0gT2JqZWN0LmFzc2lnbih7fSwgbWFwKTtcbiAgbGV0IHZhbHVlID0gbmV3X21hcFtrZXldO1xuICBkZWxldGUgbmV3X21hcFtrZXldO1xuXG4gIHJldHVybiBTcGVjaWFsRm9ybXMudHVwbGUodmFsdWUsIG5ld19tYXApO1xufVxuXG5mdW5jdGlvbiBnZXRfbGF6eShtYXAsIGtleSwgZnVuKSB7XG4gIGlmICgha2V5IGluIG1hcCkge1xuICAgIHJldHVybiBmdW4oKTtcbiAgfVxuXG4gIHJldHVybiBmdW4obWFwW2tleV0pO1xufVxuXG5mdW5jdGlvbiBnZXQobWFwLCBrZXksIF9kZWZhdWx0ID0gbnVsbCkge1xuICBpZiAoIWtleSBpbiBtYXApIHtcbiAgICByZXR1cm4gX2RlZmF1bHQ7XG4gIH1cblxuICByZXR1cm4gbWFwW2tleV07XG59XG5cbmZ1bmN0aW9uIHB1dChtYXAsIGtleSwgdmFsKSB7XG4gIGxldCBuZXdfbWFwID0gT2JqZWN0KHt9LCBtYXApO1xuICBuZXdfbWFwW2tleV0gPSB2YWw7XG5cbiAgcmV0dXJuIFNwZWNpYWxGb3Jtcy5tYXAobmV3X21hcCk7XG59XG5cbmZ1bmN0aW9uIHVwZGF0ZV9fZW1hcmtfXyhtYXAsIGtleSwgZnVuKSB7XG4gIGlmICgha2V5IGluIG1hcCkge1xuICAgIHRocm93IG5ldyBFcnJvcihcIktleSBub3QgZm91bmRcIik7XG4gIH1cblxuICBsZXQgbmV3X21hcCA9IE9iamVjdCh7fSwgbWFwKTtcbiAgbmV3X21hcFtrZXldID0gZnVuKG1hcFtrZXldKTtcblxuICByZXR1cm4gU3BlY2lhbEZvcm1zLm1hcChuZXdfbWFwKTtcbn1cblxuZnVuY3Rpb24gdXBkYXRlKG1hcCwga2V5LCBpbml0aWFsLCBmdW4pIHtcbiAgbGV0IG5ld19tYXAgPSBPYmplY3Qoe30sIG1hcCk7XG5cbiAgaWYgKCFrZXkgaW4gbWFwKSB7XG4gICAgbmV3X21hcFtrZXldID0gaW5pdGlhbDtcbiAgfSBlbHNlIHtcbiAgICBuZXdfbWFwW2tleV0gPSBmdW4obWFwW2tleV0pO1xuICB9XG5cbiAgcmV0dXJuIFNwZWNpYWxGb3Jtcy5tYXAobmV3X21hcCk7XG59XG5cbnZhciBtYXAgPSB7XG4gIG5ldzogX19uZXdfXyxcbiAga2V5cyxcbiAgc2l6ZSxcbiAgdG9fbGlzdDogdG9fbGlzdCQxLFxuICB2YWx1ZXMsXG4gIGZyb21fc3RydWN0LFxuICBkZWxldGU6IF9fZGVsZXRlX18sXG4gIGRyb3AsXG4gIGVxdWFsX19xbWFya19fLFxuICBmZXRjaF9fZW1hcmtfXyxcbiAgZmV0Y2gsXG4gIGhhc19rZXlfX3FtYXJrX18sXG4gIHNwbGl0OiBzcGxpdCQxLFxuICB0YWtlLFxuICBwdXRfbmV3LFxuICBwdXRfbmV3X2xhenksXG4gIGdldF9hbmRfdXBkYXRlLFxuICBwb3BfbGF6eSxcbiAgcG9wLFxuICBnZXRfbGF6eSxcbiAgZ2V0LFxuICBwdXQsXG4gIHVwZGF0ZV9fZW1hcmtfXyxcbiAgdXBkYXRlXG59O1xuXG5mdW5jdGlvbiBfX25ld19fJDEoKSB7XG4gIHJldHVybiBTcGVjaWFsRm9ybXMubWFwKHsgW1N5bWJvbC5mb3IoJ19fc3RydWN0X18nKV06IFN5bWJvbC5mb3IoJ01hcFNldCcpLCBzZXQ6IFNwZWNpYWxGb3Jtcy5saXN0KCkgfSk7XG59XG5cbmZ1bmN0aW9uIHNpemUkMihtYXApIHtcbiAgcmV0dXJuIG1hcC5zZXQubGVuZ3RoO1xufVxuXG5mdW5jdGlvbiB0b19saXN0JDMobWFwKSB7XG4gIHJldHVybiBtYXAuc2V0O1xufVxuXG5mdW5jdGlvbiBfX2RlbGV0ZV9fJDIoc2V0LCB0ZXJtKSB7XG4gIGxldCBuZXdfbGlzdCA9IExpc3QuZGVsZXRlKHNldC5zZXQsIHRlcm0pO1xuXG4gIGxldCBuZXdfbWFwID0gT2JqZWN0LmFzc2lnbih7fSwgc2V0KTtcbiAgbmV3X21hcC5zZXQgPSBuZXdfbGlzdDtcbiAgcmV0dXJuIFNwZWNpYWxGb3Jtcy5tYXAobmV3X21hcCk7XG59XG5cbmZ1bmN0aW9uIHB1dCQyKHNldCwgdGVybSkge1xuICBpZiAoc2V0LnNldC5pbmRleE9mKHRlcm0pID09PSAtMSkge1xuICAgIGxldCBuZXdfbGlzdCA9IExpc3QuYXBwZW5kKHNldC5zZXQsIHRlcm0pO1xuXG4gICAgbGV0IG5ld19tYXAgPSBPYmplY3QuYXNzaWduKHt9LCBzZXQpO1xuICAgIG5ld19tYXAuc2V0ID0gbmV3X2xpc3Q7XG4gICAgcmV0dXJuIFNwZWNpYWxGb3Jtcy5tYXAobmV3X21hcCk7XG4gIH1cblxuICByZXR1cm4gc2V0O1xufVxuXG5mdW5jdGlvbiBkaWZmZXJlbmNlJDEoc2V0MSwgc2V0Mikge1xuICBsZXQgbmV3X21hcCA9IE9iamVjdC5hc3NpZ24oe30sIHNldDEpO1xuXG4gIGZvciAobGV0IHZhbCBvZiBzZXQxLnNldCkge1xuICAgIGlmIChtZW1iZXJfX3FtYXJrX18kMShzZXQyLCB2YWwpKSB7XG4gICAgICBuZXdfbWFwLnNldCA9IExpc3QuZGVsZXRlKG5ld19tYXAuc2V0LCB2YWwpO1xuICAgIH1cbiAgfVxuXG4gIHJldHVybiBTcGVjaWFsRm9ybXMubWFwKG5ld19tYXApO1xufVxuXG5mdW5jdGlvbiBpbnRlcnNlY3Rpb24kMShzZXQxLCBzZXQyKSB7XG4gIGxldCBuZXdfbWFwID0gT2JqZWN0LmFzc2lnbih7fSwgc2V0MSk7XG5cbiAgZm9yIChsZXQgdmFsIG9mIHNldDEuc2V0KSB7XG4gICAgaWYgKCFtZW1iZXJfX3FtYXJrX18kMShzZXQyLCB2YWwpKSB7XG4gICAgICBuZXdfbWFwLnNldCA9IExpc3QuZGVsZXRlKG5ld19tYXAuc2V0LCB2YWwpO1xuICAgIH1cbiAgfVxuXG4gIHJldHVybiBTcGVjaWFsRm9ybXMubWFwKG5ld19tYXApO1xufVxuXG5mdW5jdGlvbiB1bmlvbiQxKHNldDEsIHNldDIpIHtcbiAgbGV0IG5ld19tYXAgPSBzZXQxO1xuXG4gIGZvciAobGV0IHZhbCBvZiBzZXQyLnNldCkge1xuICAgIG5ld19tYXAgPSBwdXQkMihuZXdfbWFwLCB2YWwpO1xuICB9XG5cbiAgcmV0dXJuIFNwZWNpYWxGb3Jtcy5tYXAobmV3X21hcCk7XG59XG5cbmZ1bmN0aW9uIGRpc2pvaW5fX3FtYXJrX18kMShzZXQxLCBzZXQyKSB7XG4gIGZvciAobGV0IHZhbCBvZiBzZXQxLnNldCkge1xuICAgIGlmIChtZW1iZXJfX3FtYXJrX18kMShzZXQyLCB2YWwpKSB7XG4gICAgICByZXR1cm4gZmFsc2U7XG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIHRydWU7XG59XG5cbmZ1bmN0aW9uIG1lbWJlcl9fcW1hcmtfXyQxKHNldCwgdmFsdWUpIHtcbiAgcmV0dXJuIHNldC5zZXQuaW5kZXhPZih2YWx1ZSkgPj0gMDtcbn1cblxuZnVuY3Rpb24gZXF1YWxfX3FtYXJrX18kMihzZXQxLCBzZXQyKSB7XG4gIHJldHVybiBzZXQxLnNldCA9PT0gc2V0Mi5zZXQ7XG59XG5cbmZ1bmN0aW9uIHN1YnNldF9fcW1hcmtfXyQxKHNldDEsIHNldDIpIHtcbiAgZm9yIChsZXQgdmFsIG9mIHNldDEuc2V0KSB7XG4gICAgaWYgKCFtZW1iZXJfX3FtYXJrX18kMShzZXQyLCB2YWwpKSB7XG4gICAgICByZXR1cm4gZmFsc2U7XG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIHRydWU7XG59XG5cbnZhciBNYXBTZXQgPSB7XG4gIG5ldzogX19uZXdfXyQxLFxuICBzaXplOiBzaXplJDIsXG4gIHRvX2xpc3Q6IHRvX2xpc3QkMyxcbiAgZGlzam9pbl9fcW1hcmtfXzogZGlzam9pbl9fcW1hcmtfXyQxLFxuICBkZWxldGU6IF9fZGVsZXRlX18kMixcbiAgc3Vic2V0X19xbWFya19fOiBzdWJzZXRfX3FtYXJrX18kMSxcbiAgZXF1YWxfX3FtYXJrX186IGVxdWFsX19xbWFya19fJDIsXG4gIG1lbWJlcl9fcW1hcmtfXzogbWVtYmVyX19xbWFya19fJDEsXG4gIHB1dDogcHV0JDIsXG4gIHVuaW9uOiB1bmlvbiQxLFxuICBpbnRlcnNlY3Rpb246IGludGVyc2VjdGlvbiQxLFxuICBkaWZmZXJlbmNlOiBkaWZmZXJlbmNlJDFcbn07XG5cbmZ1bmN0aW9uIHNpemUkMShtYXApIHtcbiAgcmV0dXJuIE1hcFNldC5zaXplKG1hcCk7XG59XG5cbmZ1bmN0aW9uIHRvX2xpc3QkMihtYXApIHtcbiAgcmV0dXJuIE1hcFNldC50b19saXN0KG1hcCk7XG59XG5cbmZ1bmN0aW9uIF9fZGVsZXRlX18kMShzZXQsIHRlcm0pIHtcbiAgcmV0dXJuIE1hcFNldC5kZWxldGUoc2V0LCB0ZXJtKTtcbn1cblxuZnVuY3Rpb24gcHV0JDEoc2V0LCB0ZXJtKSB7XG4gIHJldHVybiBNYXBTZXQucHV0KHNldCwgdGVybSk7XG59XG5cbmZ1bmN0aW9uIGRpZmZlcmVuY2Uoc2V0MSwgc2V0Mikge1xuICByZXR1cm4gTWFwU2V0LmRpZmZlcmVuY2Uoc2V0MSwgc2V0Mik7XG59XG5cbmZ1bmN0aW9uIGludGVyc2VjdGlvbihzZXQxLCBzZXQyKSB7XG4gIHJldHVybiBNYXBTZXQuaW50ZXJzZWN0aW9uKHNldDEsIHNldDIpO1xufVxuXG5mdW5jdGlvbiB1bmlvbihzZXQxLCBzZXQyKSB7XG4gIHJldHVybiBNYXBTZXQudW5pb24oc2V0MSwgc2V0Mik7XG59XG5cbmZ1bmN0aW9uIGRpc2pvaW5fX3FtYXJrX18oc2V0MSwgc2V0Mikge1xuICByZXR1cm4gTWFwU2V0LmRpc2pvaW5fX3FtYXJrX18oc2V0MSwgc2V0Mik7XG59XG5cbmZ1bmN0aW9uIG1lbWJlcl9fcW1hcmtfXyhzZXQsIHZhbHVlKSB7XG4gIHJldHVybiBNYXBTZXQubWVtYmVyX19xbWFya19fKHNldDEsIHNldDIpO1xufVxuXG5mdW5jdGlvbiBlcXVhbF9fcW1hcmtfXyQxKHNldDEsIHNldDIpIHtcbiAgcmV0dXJuIE1hcFNldC5lcXVhbF9fcW1hcmtfXyhzZXQxLCBzZXQyKTtcbn1cblxuZnVuY3Rpb24gc3Vic2V0X19xbWFya19fKHNldDEsIHNldDIpIHtcbiAgcmV0dXJuIE1hcFNldC5zdWJzZXRfX3FtYXJrX18oc2V0MSwgc2V0Mik7XG59XG5cbnZhciBzZXQgPSB7XG4gIHNpemU6IHNpemUkMSxcbiAgdG9fbGlzdDogdG9fbGlzdCQyLFxuICBkaXNqb2luX19xbWFya19fLFxuICBkZWxldGU6IF9fZGVsZXRlX18kMSxcbiAgc3Vic2V0X19xbWFya19fLFxuICBlcXVhbF9fcW1hcmtfXzogZXF1YWxfX3FtYXJrX18kMSxcbiAgbWVtYmVyX19xbWFya19fLFxuICBwdXQ6IHB1dCQxLFxuICB1bmlvbixcbiAgaW50ZXJzZWN0aW9uLFxuICBkaWZmZXJlbmNlXG59O1xuXG5sZXQgVmlydHVhbERPTSA9IChmdW5jdGlvbiAoZSkge1xuICAgIHJldHVybiBlKCk7XG59KShmdW5jdGlvbiAoKSB7XG4gICAgdmFyIGRlZmluZSwgbW9kdWxlLCBleHBvcnRzO1xuICAgIHJldHVybiAoZnVuY3Rpb24gZSh0LCBuLCByKSB7XG4gICAgICAgIGZ1bmN0aW9uIHMobywgdSkge1xuICAgICAgICAgICAgaWYgKCFuW29dKSB7XG4gICAgICAgICAgICAgICAgaWYgKCF0W29dKSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciBhID0gdHlwZW9mIHJlcXVpcmUgPT0gXCJmdW5jdGlvblwiICYmIHJlcXVpcmU7XG4gICAgICAgICAgICAgICAgICAgIGlmICghdSAmJiBhKSByZXR1cm4gYShvLCAhMCk7XG4gICAgICAgICAgICAgICAgICAgIGlmIChpKSByZXR1cm4gaShvLCAhMCk7XG4gICAgICAgICAgICAgICAgICAgIHZhciBmID0gbmV3IEVycm9yKFwiQ2Fubm90IGZpbmQgbW9kdWxlICdcIiArIG8gKyBcIidcIik7XG4gICAgICAgICAgICAgICAgICAgIHRocm93IChmLmNvZGUgPSBcIk1PRFVMRV9OT1RfRk9VTkRcIiwgZik7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHZhciBsID0gbltvXSA9IHtcbiAgICAgICAgICAgICAgICAgICAgZXhwb3J0czoge31cbiAgICAgICAgICAgICAgICB9O1xuICAgICAgICAgICAgICAgIHRbb11bMF0uY2FsbChsLmV4cG9ydHMsIGZ1bmN0aW9uIChlKSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciBuID0gdFtvXVsxXVtlXTtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHMobiA/IG4gOiBlKTtcbiAgICAgICAgICAgICAgICB9LCBsLCBsLmV4cG9ydHMsIGUsIHQsIG4sIHIpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmV0dXJuIG5bb10uZXhwb3J0cztcbiAgICAgICAgfVxuICAgICAgICB2YXIgaSA9IHR5cGVvZiByZXF1aXJlID09IFwiZnVuY3Rpb25cIiAmJiByZXF1aXJlO1xuICAgICAgICBmb3IgKHZhciBvID0gMDsgbyA8IHIubGVuZ3RoOyBvKyspIHMocltvXSk7XG4gICAgICAgIHJldHVybiBzO1xuICAgIH0pKHtcbiAgICAgICAgMTogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHtcblxuICAgICAgICAgICAgdmFyIGNyZWF0ZUVsZW1lbnQgPSByZXF1aXJlKFwiLi92ZG9tL2NyZWF0ZS1lbGVtZW50LmpzXCIpO1xuXG4gICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IGNyZWF0ZUVsZW1lbnQ7XG4gICAgICAgIH0sIHsgXCIuL3Zkb20vY3JlYXRlLWVsZW1lbnQuanNcIjogMTUgfV0sIDI6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICB2YXIgZGlmZiA9IHJlcXVpcmUoXCIuL3Z0cmVlL2RpZmYuanNcIik7XG5cbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gZGlmZjtcbiAgICAgICAgfSwgeyBcIi4vdnRyZWUvZGlmZi5qc1wiOiAzNSB9XSwgMzogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHtcbiAgICAgICAgICAgIHZhciBoID0gcmVxdWlyZShcIi4vdmlydHVhbC1oeXBlcnNjcmlwdC9pbmRleC5qc1wiKTtcblxuICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBoO1xuICAgICAgICB9LCB7IFwiLi92aXJ0dWFsLWh5cGVyc2NyaXB0L2luZGV4LmpzXCI6IDIyIH1dLCA0OiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge1xuICAgICAgICAgICAgdmFyIGRpZmYgPSByZXF1aXJlKFwiLi9kaWZmLmpzXCIpO1xuICAgICAgICAgICAgdmFyIHBhdGNoID0gcmVxdWlyZShcIi4vcGF0Y2guanNcIik7XG4gICAgICAgICAgICB2YXIgaCA9IHJlcXVpcmUoXCIuL2guanNcIik7XG4gICAgICAgICAgICB2YXIgY3JlYXRlID0gcmVxdWlyZShcIi4vY3JlYXRlLWVsZW1lbnQuanNcIik7XG4gICAgICAgICAgICB2YXIgVk5vZGUgPSByZXF1aXJlKFwiLi92bm9kZS92bm9kZS5qc1wiKTtcbiAgICAgICAgICAgIHZhciBWVGV4dCA9IHJlcXVpcmUoXCIuL3Zub2RlL3Z0ZXh0LmpzXCIpO1xuXG4gICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IHtcbiAgICAgICAgICAgICAgICBkaWZmOiBkaWZmLFxuICAgICAgICAgICAgICAgIHBhdGNoOiBwYXRjaCxcbiAgICAgICAgICAgICAgICBoOiBoLFxuICAgICAgICAgICAgICAgIGNyZWF0ZTogY3JlYXRlLFxuICAgICAgICAgICAgICAgIFZOb2RlOiBWTm9kZSxcbiAgICAgICAgICAgICAgICBWVGV4dDogVlRleHRcbiAgICAgICAgICAgIH07XG4gICAgICAgIH0sIHsgXCIuL2NyZWF0ZS1lbGVtZW50LmpzXCI6IDEsIFwiLi9kaWZmLmpzXCI6IDIsIFwiLi9oLmpzXCI6IDMsIFwiLi9wYXRjaC5qc1wiOiAxMywgXCIuL3Zub2RlL3Zub2RlLmpzXCI6IDMxLCBcIi4vdm5vZGUvdnRleHQuanNcIjogMzMgfV0sIDU6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICAvKiFcbiAgICAgICAgICAgICAqIENyb3NzLUJyb3dzZXIgU3BsaXQgMS4xLjFcbiAgICAgICAgICAgICAqIENvcHlyaWdodCAyMDA3LTIwMTIgU3RldmVuIExldml0aGFuIDxzdGV2ZW5sZXZpdGhhbi5jb20+XG4gICAgICAgICAgICAgKiBBdmFpbGFibGUgdW5kZXIgdGhlIE1JVCBMaWNlbnNlXG4gICAgICAgICAgICAgKiBFQ01BU2NyaXB0IGNvbXBsaWFudCwgdW5pZm9ybSBjcm9zcy1icm93c2VyIHNwbGl0IG1ldGhvZFxuICAgICAgICAgICAgICovXG5cbiAgICAgICAgICAgIC8qKlxuICAgICAgICAgICAgICogU3BsaXRzIGEgc3RyaW5nIGludG8gYW4gYXJyYXkgb2Ygc3RyaW5ncyB1c2luZyBhIHJlZ2V4IG9yIHN0cmluZyBzZXBhcmF0b3IuIE1hdGNoZXMgb2YgdGhlXG4gICAgICAgICAgICAgKiBzZXBhcmF0b3IgYXJlIG5vdCBpbmNsdWRlZCBpbiB0aGUgcmVzdWx0IGFycmF5LiBIb3dldmVyLCBpZiBgc2VwYXJhdG9yYCBpcyBhIHJlZ2V4IHRoYXQgY29udGFpbnNcbiAgICAgICAgICAgICAqIGNhcHR1cmluZyBncm91cHMsIGJhY2tyZWZlcmVuY2VzIGFyZSBzcGxpY2VkIGludG8gdGhlIHJlc3VsdCBlYWNoIHRpbWUgYHNlcGFyYXRvcmAgaXMgbWF0Y2hlZC5cbiAgICAgICAgICAgICAqIEZpeGVzIGJyb3dzZXIgYnVncyBjb21wYXJlZCB0byB0aGUgbmF0aXZlIGBTdHJpbmcucHJvdG90eXBlLnNwbGl0YCBhbmQgY2FuIGJlIHVzZWQgcmVsaWFibHlcbiAgICAgICAgICAgICAqIGNyb3NzLWJyb3dzZXIuXG4gICAgICAgICAgICAgKiBAcGFyYW0ge1N0cmluZ30gc3RyIFN0cmluZyB0byBzcGxpdC5cbiAgICAgICAgICAgICAqIEBwYXJhbSB7UmVnRXhwfFN0cmluZ30gc2VwYXJhdG9yIFJlZ2V4IG9yIHN0cmluZyB0byB1c2UgZm9yIHNlcGFyYXRpbmcgdGhlIHN0cmluZy5cbiAgICAgICAgICAgICAqIEBwYXJhbSB7TnVtYmVyfSBbbGltaXRdIE1heGltdW0gbnVtYmVyIG9mIGl0ZW1zIHRvIGluY2x1ZGUgaW4gdGhlIHJlc3VsdCBhcnJheS5cbiAgICAgICAgICAgICAqIEByZXR1cm5zIHtBcnJheX0gQXJyYXkgb2Ygc3Vic3RyaW5ncy5cbiAgICAgICAgICAgICAqIEBleGFtcGxlXG4gICAgICAgICAgICAgKlxuICAgICAgICAgICAgICogLy8gQmFzaWMgdXNlXG4gICAgICAgICAgICAgKiBzcGxpdCgnYSBiIGMgZCcsICcgJyk7XG4gICAgICAgICAgICAgKiAvLyAtPiBbJ2EnLCAnYicsICdjJywgJ2QnXVxuICAgICAgICAgICAgICpcbiAgICAgICAgICAgICAqIC8vIFdpdGggbGltaXRcbiAgICAgICAgICAgICAqIHNwbGl0KCdhIGIgYyBkJywgJyAnLCAyKTtcbiAgICAgICAgICAgICAqIC8vIC0+IFsnYScsICdiJ11cbiAgICAgICAgICAgICAqXG4gICAgICAgICAgICAgKiAvLyBCYWNrcmVmZXJlbmNlcyBpbiByZXN1bHQgYXJyYXlcbiAgICAgICAgICAgICAqIHNwbGl0KCcuLndvcmQxIHdvcmQyLi4nLCAvKFthLXpdKykoXFxkKykvaSk7XG4gICAgICAgICAgICAgKiAvLyAtPiBbJy4uJywgJ3dvcmQnLCAnMScsICcgJywgJ3dvcmQnLCAnMicsICcuLiddXG4gICAgICAgICAgICAgKi9cbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gKGZ1bmN0aW9uIHNwbGl0KHVuZGVmKSB7XG5cbiAgICAgICAgICAgICAgICB2YXIgbmF0aXZlU3BsaXQgPSBTdHJpbmcucHJvdG90eXBlLnNwbGl0LFxuICAgICAgICAgICAgICAgICAgICBjb21wbGlhbnRFeGVjTnBjZyA9IC8oKT8/Ly5leGVjKFwiXCIpWzFdID09PSB1bmRlZixcblxuICAgICAgICAgICAgICAgIC8vIE5QQ0c6IG5vbnBhcnRpY2lwYXRpbmcgY2FwdHVyaW5nIGdyb3VwXG4gICAgICAgICAgICAgICAgc2VsZjtcblxuICAgICAgICAgICAgICAgIHNlbGYgPSBmdW5jdGlvbiAoc3RyLCBzZXBhcmF0b3IsIGxpbWl0KSB7XG4gICAgICAgICAgICAgICAgICAgIC8vIElmIGBzZXBhcmF0b3JgIGlzIG5vdCBhIHJlZ2V4LCB1c2UgYG5hdGl2ZVNwbGl0YFxuICAgICAgICAgICAgICAgICAgICBpZiAoT2JqZWN0LnByb3RvdHlwZS50b1N0cmluZy5jYWxsKHNlcGFyYXRvcikgIT09IFwiW29iamVjdCBSZWdFeHBdXCIpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBuYXRpdmVTcGxpdC5jYWxsKHN0ciwgc2VwYXJhdG9yLCBsaW1pdCk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgdmFyIG91dHB1dCA9IFtdLFxuICAgICAgICAgICAgICAgICAgICAgICAgZmxhZ3MgPSAoc2VwYXJhdG9yLmlnbm9yZUNhc2UgPyBcImlcIiA6IFwiXCIpICsgKHNlcGFyYXRvci5tdWx0aWxpbmUgPyBcIm1cIiA6IFwiXCIpICsgKHNlcGFyYXRvci5leHRlbmRlZCA/IFwieFwiIDogXCJcIikgKyAoc2VwYXJhdG9yLnN0aWNreSA/IFwieVwiIDogXCJcIiksXG5cbiAgICAgICAgICAgICAgICAgICAgLy8gRmlyZWZveCAzK1xuICAgICAgICAgICAgICAgICAgICBsYXN0TGFzdEluZGV4ID0gMCxcblxuICAgICAgICAgICAgICAgICAgICAvLyBNYWtlIGBnbG9iYWxgIGFuZCBhdm9pZCBgbGFzdEluZGV4YCBpc3N1ZXMgYnkgd29ya2luZyB3aXRoIGEgY29weVxuICAgICAgICAgICAgICAgICAgICBzZXBhcmF0b3IgPSBuZXcgUmVnRXhwKHNlcGFyYXRvci5zb3VyY2UsIGZsYWdzICsgXCJnXCIpLFxuICAgICAgICAgICAgICAgICAgICAgICAgc2VwYXJhdG9yMixcbiAgICAgICAgICAgICAgICAgICAgICAgIG1hdGNoLFxuICAgICAgICAgICAgICAgICAgICAgICAgbGFzdEluZGV4LFxuICAgICAgICAgICAgICAgICAgICAgICAgbGFzdExlbmd0aDtcbiAgICAgICAgICAgICAgICAgICAgc3RyICs9IFwiXCI7IC8vIFR5cGUtY29udmVydFxuICAgICAgICAgICAgICAgICAgICBpZiAoIWNvbXBsaWFudEV4ZWNOcGNnKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAvLyBEb2Vzbid0IG5lZWQgZmxhZ3MgZ3ksIGJ1dCB0aGV5IGRvbid0IGh1cnRcbiAgICAgICAgICAgICAgICAgICAgICAgIHNlcGFyYXRvcjIgPSBuZXcgUmVnRXhwKFwiXlwiICsgc2VwYXJhdG9yLnNvdXJjZSArIFwiJCg/IVxcXFxzKVwiLCBmbGFncyk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgLyogVmFsdWVzIGZvciBgbGltaXRgLCBwZXIgdGhlIHNwZWM6XG4gICAgICAgICAgICAgICAgICAgICAqIElmIHVuZGVmaW5lZDogNDI5NDk2NzI5NSAvLyBNYXRoLnBvdygyLCAzMikgLSAxXG4gICAgICAgICAgICAgICAgICAgICAqIElmIDAsIEluZmluaXR5LCBvciBOYU46IDBcbiAgICAgICAgICAgICAgICAgICAgICogSWYgcG9zaXRpdmUgbnVtYmVyOiBsaW1pdCA9IE1hdGguZmxvb3IobGltaXQpOyBpZiAobGltaXQgPiA0Mjk0OTY3Mjk1KSBsaW1pdCAtPSA0Mjk0OTY3Mjk2O1xuICAgICAgICAgICAgICAgICAgICAgKiBJZiBuZWdhdGl2ZSBudW1iZXI6IDQyOTQ5NjcyOTYgLSBNYXRoLmZsb29yKE1hdGguYWJzKGxpbWl0KSlcbiAgICAgICAgICAgICAgICAgICAgICogSWYgb3RoZXI6IFR5cGUtY29udmVydCwgdGhlbiB1c2UgdGhlIGFib3ZlIHJ1bGVzXG4gICAgICAgICAgICAgICAgICAgICAqL1xuICAgICAgICAgICAgICAgICAgICBsaW1pdCA9IGxpbWl0ID09PSB1bmRlZiA/IC0xID4+PiAwIDogLy8gTWF0aC5wb3coMiwgMzIpIC0gMVxuICAgICAgICAgICAgICAgICAgICBsaW1pdCA+Pj4gMDsgLy8gVG9VaW50MzIobGltaXQpXG4gICAgICAgICAgICAgICAgICAgIHdoaWxlIChtYXRjaCA9IHNlcGFyYXRvci5leGVjKHN0cikpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIGBzZXBhcmF0b3IubGFzdEluZGV4YCBpcyBub3QgcmVsaWFibGUgY3Jvc3MtYnJvd3NlclxuICAgICAgICAgICAgICAgICAgICAgICAgbGFzdEluZGV4ID0gbWF0Y2guaW5kZXggKyBtYXRjaFswXS5sZW5ndGg7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAobGFzdEluZGV4ID4gbGFzdExhc3RJbmRleCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIG91dHB1dC5wdXNoKHN0ci5zbGljZShsYXN0TGFzdEluZGV4LCBtYXRjaC5pbmRleCkpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIEZpeCBicm93c2VycyB3aG9zZSBgZXhlY2AgbWV0aG9kcyBkb24ndCBjb25zaXN0ZW50bHkgcmV0dXJuIGB1bmRlZmluZWRgIGZvclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIG5vbnBhcnRpY2lwYXRpbmcgY2FwdHVyaW5nIGdyb3Vwc1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmICghY29tcGxpYW50RXhlY05wY2cgJiYgbWF0Y2gubGVuZ3RoID4gMSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBtYXRjaFswXS5yZXBsYWNlKHNlcGFyYXRvcjIsIGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZvciAodmFyIGkgPSAxOyBpIDwgYXJndW1lbnRzLmxlbmd0aCAtIDI7IGkrKykge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChhcmd1bWVudHNbaV0gPT09IHVuZGVmKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1hdGNoW2ldID0gdW5kZWY7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKG1hdGNoLmxlbmd0aCA+IDEgJiYgbWF0Y2guaW5kZXggPCBzdHIubGVuZ3RoKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIEFycmF5LnByb3RvdHlwZS5wdXNoLmFwcGx5KG91dHB1dCwgbWF0Y2guc2xpY2UoMSkpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBsYXN0TGVuZ3RoID0gbWF0Y2hbMF0ubGVuZ3RoO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxhc3RMYXN0SW5kZXggPSBsYXN0SW5kZXg7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKG91dHB1dC5sZW5ndGggPj0gbGltaXQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHNlcGFyYXRvci5sYXN0SW5kZXggPT09IG1hdGNoLmluZGV4KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgc2VwYXJhdG9yLmxhc3RJbmRleCsrOyAvLyBBdm9pZCBhbiBpbmZpbml0ZSBsb29wXG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgaWYgKGxhc3RMYXN0SW5kZXggPT09IHN0ci5sZW5ndGgpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChsYXN0TGVuZ3RoIHx8ICFzZXBhcmF0b3IudGVzdChcIlwiKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIG91dHB1dC5wdXNoKFwiXCIpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgb3V0cHV0LnB1c2goc3RyLnNsaWNlKGxhc3RMYXN0SW5kZXgpKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICByZXR1cm4gb3V0cHV0Lmxlbmd0aCA+IGxpbWl0ID8gb3V0cHV0LnNsaWNlKDAsIGxpbWl0KSA6IG91dHB1dDtcbiAgICAgICAgICAgICAgICB9O1xuXG4gICAgICAgICAgICAgICAgcmV0dXJuIHNlbGY7XG4gICAgICAgICAgICB9KSgpO1xuICAgICAgICB9LCB7fV0sIDY6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7fSwge31dLCA3OiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge1xuICAgICAgICAgICAgXCJ1c2Ugc3RyaWN0XCI7XG5cbiAgICAgICAgICAgIHZhciBPbmVWZXJzaW9uQ29uc3RyYWludCA9IHJlcXVpcmUoXCJpbmRpdmlkdWFsL29uZS12ZXJzaW9uXCIpO1xuXG4gICAgICAgICAgICB2YXIgTVlfVkVSU0lPTiA9IFwiN1wiO1xuICAgICAgICAgICAgT25lVmVyc2lvbkNvbnN0cmFpbnQoXCJldi1zdG9yZVwiLCBNWV9WRVJTSU9OKTtcblxuICAgICAgICAgICAgdmFyIGhhc2hLZXkgPSBcIl9fRVZfU1RPUkVfS0VZQFwiICsgTVlfVkVSU0lPTjtcblxuICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBFdlN0b3JlO1xuXG4gICAgICAgICAgICBmdW5jdGlvbiBFdlN0b3JlKGVsZW0pIHtcbiAgICAgICAgICAgICAgICB2YXIgaGFzaCA9IGVsZW1baGFzaEtleV07XG5cbiAgICAgICAgICAgICAgICBpZiAoIWhhc2gpIHtcbiAgICAgICAgICAgICAgICAgICAgaGFzaCA9IGVsZW1baGFzaEtleV0gPSB7fTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICByZXR1cm4gaGFzaDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSwgeyBcImluZGl2aWR1YWwvb25lLXZlcnNpb25cIjogOSB9XSwgODogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHtcbiAgICAgICAgICAgIChmdW5jdGlvbiAoZ2xvYmFsKSB7XG4gICAgICAgICAgICAgICAgXCJ1c2Ugc3RyaWN0XCI7XG5cbiAgICAgICAgICAgICAgICAvKmdsb2JhbCB3aW5kb3csIGdsb2JhbCovXG5cbiAgICAgICAgICAgICAgICB2YXIgcm9vdCA9IHR5cGVvZiB3aW5kb3cgIT09IFwidW5kZWZpbmVkXCIgPyB3aW5kb3cgOiB0eXBlb2YgZ2xvYmFsICE9PSBcInVuZGVmaW5lZFwiID8gZ2xvYmFsIDoge307XG5cbiAgICAgICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IEluZGl2aWR1YWw7XG5cbiAgICAgICAgICAgICAgICBmdW5jdGlvbiBJbmRpdmlkdWFsKGtleSwgdmFsdWUpIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKGtleSBpbiByb290KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gcm9vdFtrZXldO1xuICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgcm9vdFtrZXldID0gdmFsdWU7XG5cbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHZhbHVlO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0pLmNhbGwodGhpcywgdHlwZW9mIGdsb2JhbCAhPT0gXCJ1bmRlZmluZWRcIiA/IGdsb2JhbCA6IHR5cGVvZiBzZWxmICE9PSBcInVuZGVmaW5lZFwiID8gc2VsZiA6IHR5cGVvZiB3aW5kb3cgIT09IFwidW5kZWZpbmVkXCIgPyB3aW5kb3cgOiB7fSk7XG4gICAgICAgIH0sIHt9XSwgOTogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHtcbiAgICAgICAgICAgIFwidXNlIHN0cmljdFwiO1xuXG4gICAgICAgICAgICB2YXIgSW5kaXZpZHVhbCA9IHJlcXVpcmUoXCIuL2luZGV4LmpzXCIpO1xuXG4gICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IE9uZVZlcnNpb247XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIE9uZVZlcnNpb24obW9kdWxlTmFtZSwgdmVyc2lvbiwgZGVmYXVsdFZhbHVlKSB7XG4gICAgICAgICAgICAgICAgdmFyIGtleSA9IFwiX19JTkRJVklEVUFMX09ORV9WRVJTSU9OX1wiICsgbW9kdWxlTmFtZTtcbiAgICAgICAgICAgICAgICB2YXIgZW5mb3JjZUtleSA9IGtleSArIFwiX0VORk9SQ0VfU0lOR0xFVE9OXCI7XG5cbiAgICAgICAgICAgICAgICB2YXIgdmVyc2lvblZhbHVlID0gSW5kaXZpZHVhbChlbmZvcmNlS2V5LCB2ZXJzaW9uKTtcblxuICAgICAgICAgICAgICAgIGlmICh2ZXJzaW9uVmFsdWUgIT09IHZlcnNpb24pIHtcbiAgICAgICAgICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKFwiQ2FuIG9ubHkgaGF2ZSBvbmUgY29weSBvZiBcIiArIG1vZHVsZU5hbWUgKyBcIi5cXG5cIiArIFwiWW91IGFscmVhZHkgaGF2ZSB2ZXJzaW9uIFwiICsgdmVyc2lvblZhbHVlICsgXCIgaW5zdGFsbGVkLlxcblwiICsgXCJUaGlzIG1lYW5zIHlvdSBjYW5ub3QgaW5zdGFsbCB2ZXJzaW9uIFwiICsgdmVyc2lvbik7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgcmV0dXJuIEluZGl2aWR1YWwoa2V5LCBkZWZhdWx0VmFsdWUpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9LCB7IFwiLi9pbmRleC5qc1wiOiA4IH1dLCAxMDogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHtcbiAgICAgICAgICAgIChmdW5jdGlvbiAoZ2xvYmFsKSB7XG4gICAgICAgICAgICAgICAgdmFyIHRvcExldmVsID0gdHlwZW9mIGdsb2JhbCAhPT0gXCJ1bmRlZmluZWRcIiA/IGdsb2JhbCA6IHR5cGVvZiB3aW5kb3cgIT09IFwidW5kZWZpbmVkXCIgPyB3aW5kb3cgOiB7fTtcbiAgICAgICAgICAgICAgICB2YXIgbWluRG9jID0gcmVxdWlyZShcIm1pbi1kb2N1bWVudFwiKTtcblxuICAgICAgICAgICAgICAgIGlmICh0eXBlb2YgZG9jdW1lbnQgIT09IFwidW5kZWZpbmVkXCIpIHtcbiAgICAgICAgICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBkb2N1bWVudDtcbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICB2YXIgZG9jY3kgPSB0b3BMZXZlbFtcIl9fR0xPQkFMX0RPQ1VNRU5UX0NBQ0hFQDRcIl07XG5cbiAgICAgICAgICAgICAgICAgICAgaWYgKCFkb2NjeSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgZG9jY3kgPSB0b3BMZXZlbFtcIl9fR0xPQkFMX0RPQ1VNRU5UX0NBQ0hFQDRcIl0gPSBtaW5Eb2M7XG4gICAgICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IGRvY2N5O1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0pLmNhbGwodGhpcywgdHlwZW9mIGdsb2JhbCAhPT0gXCJ1bmRlZmluZWRcIiA/IGdsb2JhbCA6IHR5cGVvZiBzZWxmICE9PSBcInVuZGVmaW5lZFwiID8gc2VsZiA6IHR5cGVvZiB3aW5kb3cgIT09IFwidW5kZWZpbmVkXCIgPyB3aW5kb3cgOiB7fSk7XG4gICAgICAgIH0sIHsgXCJtaW4tZG9jdW1lbnRcIjogNiB9XSwgMTE6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICBcInVzZSBzdHJpY3RcIjtcblxuICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiBpc09iamVjdCh4KSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHR5cGVvZiB4ID09PSBcIm9iamVjdFwiICYmIHggIT09IG51bGw7XG4gICAgICAgICAgICB9O1xuICAgICAgICB9LCB7fV0sIDEyOiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge1xuICAgICAgICAgICAgdmFyIG5hdGl2ZUlzQXJyYXkgPSBBcnJheS5pc0FycmF5O1xuICAgICAgICAgICAgdmFyIHRvU3RyaW5nID0gT2JqZWN0LnByb3RvdHlwZS50b1N0cmluZztcblxuICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBuYXRpdmVJc0FycmF5IHx8IGlzQXJyYXk7XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIGlzQXJyYXkob2JqKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHRvU3RyaW5nLmNhbGwob2JqKSA9PT0gXCJbb2JqZWN0IEFycmF5XVwiO1xuICAgICAgICAgICAgfVxuICAgICAgICB9LCB7fV0sIDEzOiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge1xuICAgICAgICAgICAgdmFyIHBhdGNoID0gcmVxdWlyZShcIi4vdmRvbS9wYXRjaC5qc1wiKTtcblxuICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBwYXRjaDtcbiAgICAgICAgfSwgeyBcIi4vdmRvbS9wYXRjaC5qc1wiOiAxOCB9XSwgMTQ6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICB2YXIgaXNPYmplY3QgPSByZXF1aXJlKFwiaXMtb2JqZWN0XCIpO1xuICAgICAgICAgICAgdmFyIGlzSG9vayA9IHJlcXVpcmUoXCIuLi92bm9kZS9pcy12aG9vay5qc1wiKTtcblxuICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBhcHBseVByb3BlcnRpZXM7XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIGFwcGx5UHJvcGVydGllcyhub2RlLCBwcm9wcywgcHJldmlvdXMpIHtcbiAgICAgICAgICAgICAgICBmb3IgKHZhciBwcm9wTmFtZSBpbiBwcm9wcykge1xuICAgICAgICAgICAgICAgICAgICB2YXIgcHJvcFZhbHVlID0gcHJvcHNbcHJvcE5hbWVdO1xuXG4gICAgICAgICAgICAgICAgICAgIGlmIChwcm9wVmFsdWUgPT09IHVuZGVmaW5lZCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgcmVtb3ZlUHJvcGVydHkobm9kZSwgcHJvcE5hbWUsIHByb3BWYWx1ZSwgcHJldmlvdXMpO1xuICAgICAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKGlzSG9vayhwcm9wVmFsdWUpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICByZW1vdmVQcm9wZXJ0eShub2RlLCBwcm9wTmFtZSwgcHJvcFZhbHVlLCBwcmV2aW91cyk7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAocHJvcFZhbHVlLmhvb2spIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBwcm9wVmFsdWUuaG9vayhub2RlLCBwcm9wTmFtZSwgcHJldmlvdXMgPyBwcmV2aW91c1twcm9wTmFtZV0gOiB1bmRlZmluZWQpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGlzT2JqZWN0KHByb3BWYWx1ZSkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBwYXRjaE9iamVjdChub2RlLCBwcm9wcywgcHJldmlvdXMsIHByb3BOYW1lLCBwcm9wVmFsdWUpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBub2RlW3Byb3BOYW1lXSA9IHByb3BWYWx1ZTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZnVuY3Rpb24gcmVtb3ZlUHJvcGVydHkobm9kZSwgcHJvcE5hbWUsIHByb3BWYWx1ZSwgcHJldmlvdXMpIHtcbiAgICAgICAgICAgICAgICBpZiAocHJldmlvdXMpIHtcbiAgICAgICAgICAgICAgICAgICAgdmFyIHByZXZpb3VzVmFsdWUgPSBwcmV2aW91c1twcm9wTmFtZV07XG5cbiAgICAgICAgICAgICAgICAgICAgaWYgKCFpc0hvb2socHJldmlvdXNWYWx1ZSkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChwcm9wTmFtZSA9PT0gXCJhdHRyaWJ1dGVzXCIpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBmb3IgKHZhciBhdHRyTmFtZSBpbiBwcmV2aW91c1ZhbHVlKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG5vZGUucmVtb3ZlQXR0cmlidXRlKGF0dHJOYW1lKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKHByb3BOYW1lID09PSBcInN0eWxlXCIpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBmb3IgKHZhciBpIGluIHByZXZpb3VzVmFsdWUpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbm9kZS5zdHlsZVtpXSA9IFwiXCI7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIGlmICh0eXBlb2YgcHJldmlvdXNWYWx1ZSA9PT0gXCJzdHJpbmdcIikge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIG5vZGVbcHJvcE5hbWVdID0gXCJcIjtcbiAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgbm9kZVtwcm9wTmFtZV0gPSBudWxsO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKHByZXZpb3VzVmFsdWUudW5ob29rKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBwcmV2aW91c1ZhbHVlLnVuaG9vayhub2RlLCBwcm9wTmFtZSwgcHJvcFZhbHVlKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZnVuY3Rpb24gcGF0Y2hPYmplY3Qobm9kZSwgcHJvcHMsIHByZXZpb3VzLCBwcm9wTmFtZSwgcHJvcFZhbHVlKSB7XG4gICAgICAgICAgICAgICAgdmFyIHByZXZpb3VzVmFsdWUgPSBwcmV2aW91cyA/IHByZXZpb3VzW3Byb3BOYW1lXSA6IHVuZGVmaW5lZDtcblxuICAgICAgICAgICAgICAgIC8vIFNldCBhdHRyaWJ1dGVzXG4gICAgICAgICAgICAgICAgaWYgKHByb3BOYW1lID09PSBcImF0dHJpYnV0ZXNcIikge1xuICAgICAgICAgICAgICAgICAgICBmb3IgKHZhciBhdHRyTmFtZSBpbiBwcm9wVmFsdWUpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHZhciBhdHRyVmFsdWUgPSBwcm9wVmFsdWVbYXR0ck5hbWVdO1xuXG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoYXR0clZhbHVlID09PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBub2RlLnJlbW92ZUF0dHJpYnV0ZShhdHRyTmFtZSk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIG5vZGUuc2V0QXR0cmlidXRlKGF0dHJOYW1lLCBhdHRyVmFsdWUpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIGlmIChwcmV2aW91c1ZhbHVlICYmIGlzT2JqZWN0KHByZXZpb3VzVmFsdWUpICYmIGdldFByb3RvdHlwZShwcmV2aW91c1ZhbHVlKSAhPT0gZ2V0UHJvdG90eXBlKHByb3BWYWx1ZSkpIHtcbiAgICAgICAgICAgICAgICAgICAgbm9kZVtwcm9wTmFtZV0gPSBwcm9wVmFsdWU7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICBpZiAoIWlzT2JqZWN0KG5vZGVbcHJvcE5hbWVdKSkge1xuICAgICAgICAgICAgICAgICAgICBub2RlW3Byb3BOYW1lXSA9IHt9O1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHZhciByZXBsYWNlciA9IHByb3BOYW1lID09PSBcInN0eWxlXCIgPyBcIlwiIDogdW5kZWZpbmVkO1xuXG4gICAgICAgICAgICAgICAgZm9yICh2YXIgayBpbiBwcm9wVmFsdWUpIHtcbiAgICAgICAgICAgICAgICAgICAgdmFyIHZhbHVlID0gcHJvcFZhbHVlW2tdO1xuICAgICAgICAgICAgICAgICAgICBub2RlW3Byb3BOYW1lXVtrXSA9IHZhbHVlID09PSB1bmRlZmluZWQgPyByZXBsYWNlciA6IHZhbHVlO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZnVuY3Rpb24gZ2V0UHJvdG90eXBlKHZhbHVlKSB7XG4gICAgICAgICAgICAgICAgaWYgKE9iamVjdC5nZXRQcm90b3R5cGVPZikge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gT2JqZWN0LmdldFByb3RvdHlwZU9mKHZhbHVlKTtcbiAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKHZhbHVlLl9fcHJvdG9fXykge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gdmFsdWUuX19wcm90b19fO1xuICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAodmFsdWUuY29uc3RydWN0b3IpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHZhbHVlLmNvbnN0cnVjdG9yLnByb3RvdHlwZTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH0sIHsgXCIuLi92bm9kZS9pcy12aG9vay5qc1wiOiAyNiwgXCJpcy1vYmplY3RcIjogMTEgfV0sIDE1OiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge1xuICAgICAgICAgICAgdmFyIGRvY3VtZW50ID0gcmVxdWlyZShcImdsb2JhbC9kb2N1bWVudFwiKTtcblxuICAgICAgICAgICAgdmFyIGFwcGx5UHJvcGVydGllcyA9IHJlcXVpcmUoXCIuL2FwcGx5LXByb3BlcnRpZXNcIik7XG5cbiAgICAgICAgICAgIHZhciBpc1ZOb2RlID0gcmVxdWlyZShcIi4uL3Zub2RlL2lzLXZub2RlLmpzXCIpO1xuICAgICAgICAgICAgdmFyIGlzVlRleHQgPSByZXF1aXJlKFwiLi4vdm5vZGUvaXMtdnRleHQuanNcIik7XG4gICAgICAgICAgICB2YXIgaXNXaWRnZXQgPSByZXF1aXJlKFwiLi4vdm5vZGUvaXMtd2lkZ2V0LmpzXCIpO1xuICAgICAgICAgICAgdmFyIGhhbmRsZVRodW5rID0gcmVxdWlyZShcIi4uL3Zub2RlL2hhbmRsZS10aHVuay5qc1wiKTtcblxuICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBjcmVhdGVFbGVtZW50O1xuXG4gICAgICAgICAgICBmdW5jdGlvbiBjcmVhdGVFbGVtZW50KHZub2RlLCBvcHRzKSB7XG4gICAgICAgICAgICAgICAgdmFyIGRvYyA9IG9wdHMgPyBvcHRzLmRvY3VtZW50IHx8IGRvY3VtZW50IDogZG9jdW1lbnQ7XG4gICAgICAgICAgICAgICAgdmFyIHdhcm4gPSBvcHRzID8gb3B0cy53YXJuIDogbnVsbDtcblxuICAgICAgICAgICAgICAgIHZub2RlID0gaGFuZGxlVGh1bmsodm5vZGUpLmE7XG5cbiAgICAgICAgICAgICAgICBpZiAoaXNXaWRnZXQodm5vZGUpKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiB2bm9kZS5pbml0KCk7XG4gICAgICAgICAgICAgICAgfSBlbHNlIGlmIChpc1ZUZXh0KHZub2RlKSkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gZG9jLmNyZWF0ZVRleHROb2RlKHZub2RlLnRleHQpO1xuICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoIWlzVk5vZGUodm5vZGUpKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmICh3YXJuKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICB3YXJuKFwiSXRlbSBpcyBub3QgYSB2YWxpZCB2aXJ0dWFsIGRvbSBub2RlXCIsIHZub2RlKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICByZXR1cm4gbnVsbDtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICB2YXIgbm9kZSA9IHZub2RlLm5hbWVzcGFjZSA9PT0gbnVsbCA/IGRvYy5jcmVhdGVFbGVtZW50KHZub2RlLnRhZ05hbWUpIDogZG9jLmNyZWF0ZUVsZW1lbnROUyh2bm9kZS5uYW1lc3BhY2UsIHZub2RlLnRhZ05hbWUpO1xuXG4gICAgICAgICAgICAgICAgdmFyIHByb3BzID0gdm5vZGUucHJvcGVydGllcztcbiAgICAgICAgICAgICAgICBhcHBseVByb3BlcnRpZXMobm9kZSwgcHJvcHMpO1xuXG4gICAgICAgICAgICAgICAgdmFyIGNoaWxkcmVuID0gdm5vZGUuY2hpbGRyZW47XG5cbiAgICAgICAgICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IGNoaWxkcmVuLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciBjaGlsZE5vZGUgPSBjcmVhdGVFbGVtZW50KGNoaWxkcmVuW2ldLCBvcHRzKTtcbiAgICAgICAgICAgICAgICAgICAgaWYgKGNoaWxkTm9kZSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgbm9kZS5hcHBlbmRDaGlsZChjaGlsZE5vZGUpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgcmV0dXJuIG5vZGU7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0sIHsgXCIuLi92bm9kZS9oYW5kbGUtdGh1bmsuanNcIjogMjQsIFwiLi4vdm5vZGUvaXMtdm5vZGUuanNcIjogMjcsIFwiLi4vdm5vZGUvaXMtdnRleHQuanNcIjogMjgsIFwiLi4vdm5vZGUvaXMtd2lkZ2V0LmpzXCI6IDI5LCBcIi4vYXBwbHktcHJvcGVydGllc1wiOiAxNCwgXCJnbG9iYWwvZG9jdW1lbnRcIjogMTAgfV0sIDE2OiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge1xuICAgICAgICAgICAgLy8gTWFwcyBhIHZpcnR1YWwgRE9NIHRyZWUgb250byBhIHJlYWwgRE9NIHRyZWUgaW4gYW4gZWZmaWNpZW50IG1hbm5lci5cbiAgICAgICAgICAgIC8vIFdlIGRvbid0IHdhbnQgdG8gcmVhZCBhbGwgb2YgdGhlIERPTSBub2RlcyBpbiB0aGUgdHJlZSBzbyB3ZSB1c2VcbiAgICAgICAgICAgIC8vIHRoZSBpbi1vcmRlciB0cmVlIGluZGV4aW5nIHRvIGVsaW1pbmF0ZSByZWN1cnNpb24gZG93biBjZXJ0YWluIGJyYW5jaGVzLlxuICAgICAgICAgICAgLy8gV2Ugb25seSByZWN1cnNlIGludG8gYSBET00gbm9kZSBpZiB3ZSBrbm93IHRoYXQgaXQgY29udGFpbnMgYSBjaGlsZCBvZlxuICAgICAgICAgICAgLy8gaW50ZXJlc3QuXG5cbiAgICAgICAgICAgIHZhciBub0NoaWxkID0ge307XG5cbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gZG9tSW5kZXg7XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIGRvbUluZGV4KHJvb3ROb2RlLCB0cmVlLCBpbmRpY2VzLCBub2Rlcykge1xuICAgICAgICAgICAgICAgIGlmICghaW5kaWNlcyB8fCBpbmRpY2VzLmxlbmd0aCA9PT0gMCkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4ge307XG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgaW5kaWNlcy5zb3J0KGFzY2VuZGluZyk7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiByZWN1cnNlKHJvb3ROb2RlLCB0cmVlLCBpbmRpY2VzLCBub2RlcywgMCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBmdW5jdGlvbiByZWN1cnNlKHJvb3ROb2RlLCB0cmVlLCBpbmRpY2VzLCBub2Rlcywgcm9vdEluZGV4KSB7XG4gICAgICAgICAgICAgICAgbm9kZXMgPSBub2RlcyB8fCB7fTtcblxuICAgICAgICAgICAgICAgIGlmIChyb290Tm9kZSkge1xuICAgICAgICAgICAgICAgICAgICBpZiAoaW5kZXhJblJhbmdlKGluZGljZXMsIHJvb3RJbmRleCwgcm9vdEluZGV4KSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgbm9kZXNbcm9vdEluZGV4XSA9IHJvb3ROb2RlO1xuICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgdmFyIHZDaGlsZHJlbiA9IHRyZWUuY2hpbGRyZW47XG5cbiAgICAgICAgICAgICAgICAgICAgaWYgKHZDaGlsZHJlbikge1xuXG4gICAgICAgICAgICAgICAgICAgICAgICB2YXIgY2hpbGROb2RlcyA9IHJvb3ROb2RlLmNoaWxkTm9kZXM7XG5cbiAgICAgICAgICAgICAgICAgICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgdHJlZS5jaGlsZHJlbi5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJvb3RJbmRleCArPSAxO1xuXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdmFyIHZDaGlsZCA9IHZDaGlsZHJlbltpXSB8fCBub0NoaWxkO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZhciBuZXh0SW5kZXggPSByb290SW5kZXggKyAodkNoaWxkLmNvdW50IHx8IDApO1xuXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gc2tpcCByZWN1cnNpb24gZG93biB0aGUgdHJlZSBpZiB0aGVyZSBhcmUgbm8gbm9kZXMgZG93biBoZXJlXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGluZGV4SW5SYW5nZShpbmRpY2VzLCByb290SW5kZXgsIG5leHRJbmRleCkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmVjdXJzZShjaGlsZE5vZGVzW2ldLCB2Q2hpbGQsIGluZGljZXMsIG5vZGVzLCByb290SW5kZXgpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJvb3RJbmRleCA9IG5leHRJbmRleDtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHJldHVybiBub2RlcztcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgLy8gQmluYXJ5IHNlYXJjaCBmb3IgYW4gaW5kZXggaW4gdGhlIGludGVydmFsIFtsZWZ0LCByaWdodF1cbiAgICAgICAgICAgIGZ1bmN0aW9uIGluZGV4SW5SYW5nZShpbmRpY2VzLCBsZWZ0LCByaWdodCkge1xuICAgICAgICAgICAgICAgIGlmIChpbmRpY2VzLmxlbmd0aCA9PT0gMCkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgdmFyIG1pbkluZGV4ID0gMDtcbiAgICAgICAgICAgICAgICB2YXIgbWF4SW5kZXggPSBpbmRpY2VzLmxlbmd0aCAtIDE7XG4gICAgICAgICAgICAgICAgdmFyIGN1cnJlbnRJbmRleDtcbiAgICAgICAgICAgICAgICB2YXIgY3VycmVudEl0ZW07XG5cbiAgICAgICAgICAgICAgICB3aGlsZSAobWluSW5kZXggPD0gbWF4SW5kZXgpIHtcbiAgICAgICAgICAgICAgICAgICAgY3VycmVudEluZGV4ID0gKG1heEluZGV4ICsgbWluSW5kZXgpIC8gMiA+PiAwO1xuICAgICAgICAgICAgICAgICAgICBjdXJyZW50SXRlbSA9IGluZGljZXNbY3VycmVudEluZGV4XTtcblxuICAgICAgICAgICAgICAgICAgICBpZiAobWluSW5kZXggPT09IG1heEluZGV4KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gY3VycmVudEl0ZW0gPj0gbGVmdCAmJiBjdXJyZW50SXRlbSA8PSByaWdodDtcbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIGlmIChjdXJyZW50SXRlbSA8IGxlZnQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIG1pbkluZGV4ID0gY3VycmVudEluZGV4ICsgMTtcbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIGlmIChjdXJyZW50SXRlbSA+IHJpZ2h0KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBtYXhJbmRleCA9IGN1cnJlbnRJbmRleCAtIDE7XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZnVuY3Rpb24gYXNjZW5kaW5nKGEsIGIpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gYSA+IGIgPyAxIDogLTE7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0sIHt9XSwgMTc6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICB2YXIgYXBwbHlQcm9wZXJ0aWVzID0gcmVxdWlyZShcIi4vYXBwbHktcHJvcGVydGllc1wiKTtcblxuICAgICAgICAgICAgdmFyIGlzV2lkZ2V0ID0gcmVxdWlyZShcIi4uL3Zub2RlL2lzLXdpZGdldC5qc1wiKTtcbiAgICAgICAgICAgIHZhciBWUGF0Y2ggPSByZXF1aXJlKFwiLi4vdm5vZGUvdnBhdGNoLmpzXCIpO1xuXG4gICAgICAgICAgICB2YXIgdXBkYXRlV2lkZ2V0ID0gcmVxdWlyZShcIi4vdXBkYXRlLXdpZGdldFwiKTtcblxuICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBhcHBseVBhdGNoO1xuXG4gICAgICAgICAgICBmdW5jdGlvbiBhcHBseVBhdGNoKHZwYXRjaCwgZG9tTm9kZSwgcmVuZGVyT3B0aW9ucykge1xuICAgICAgICAgICAgICAgIHZhciB0eXBlID0gdnBhdGNoLnR5cGU7XG4gICAgICAgICAgICAgICAgdmFyIHZOb2RlID0gdnBhdGNoLnZOb2RlO1xuICAgICAgICAgICAgICAgIHZhciBwYXRjaCA9IHZwYXRjaC5wYXRjaDtcblxuICAgICAgICAgICAgICAgIHN3aXRjaCAodHlwZSkge1xuICAgICAgICAgICAgICAgICAgICBjYXNlIFZQYXRjaC5SRU1PVkU6XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gcmVtb3ZlTm9kZShkb21Ob2RlLCB2Tm9kZSk7XG4gICAgICAgICAgICAgICAgICAgIGNhc2UgVlBhdGNoLklOU0VSVDpcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBpbnNlcnROb2RlKGRvbU5vZGUsIHBhdGNoLCByZW5kZXJPcHRpb25zKTtcbiAgICAgICAgICAgICAgICAgICAgY2FzZSBWUGF0Y2guVlRFWFQ6XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gc3RyaW5nUGF0Y2goZG9tTm9kZSwgdk5vZGUsIHBhdGNoLCByZW5kZXJPcHRpb25zKTtcbiAgICAgICAgICAgICAgICAgICAgY2FzZSBWUGF0Y2guV0lER0VUOlxuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHdpZGdldFBhdGNoKGRvbU5vZGUsIHZOb2RlLCBwYXRjaCwgcmVuZGVyT3B0aW9ucyk7XG4gICAgICAgICAgICAgICAgICAgIGNhc2UgVlBhdGNoLlZOT0RFOlxuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHZOb2RlUGF0Y2goZG9tTm9kZSwgdk5vZGUsIHBhdGNoLCByZW5kZXJPcHRpb25zKTtcbiAgICAgICAgICAgICAgICAgICAgY2FzZSBWUGF0Y2guT1JERVI6XG4gICAgICAgICAgICAgICAgICAgICAgICByZW9yZGVyQ2hpbGRyZW4oZG9tTm9kZSwgcGF0Y2gpO1xuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGRvbU5vZGU7XG4gICAgICAgICAgICAgICAgICAgIGNhc2UgVlBhdGNoLlBST1BTOlxuICAgICAgICAgICAgICAgICAgICAgICAgYXBwbHlQcm9wZXJ0aWVzKGRvbU5vZGUsIHBhdGNoLCB2Tm9kZS5wcm9wZXJ0aWVzKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBkb21Ob2RlO1xuICAgICAgICAgICAgICAgICAgICBjYXNlIFZQYXRjaC5USFVOSzpcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiByZXBsYWNlUm9vdChkb21Ob2RlLCByZW5kZXJPcHRpb25zLnBhdGNoKGRvbU5vZGUsIHBhdGNoLCByZW5kZXJPcHRpb25zKSk7XG4gICAgICAgICAgICAgICAgICAgIGRlZmF1bHQ6XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gZG9tTm9kZTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIHJlbW92ZU5vZGUoZG9tTm9kZSwgdk5vZGUpIHtcbiAgICAgICAgICAgICAgICB2YXIgcGFyZW50Tm9kZSA9IGRvbU5vZGUucGFyZW50Tm9kZTtcblxuICAgICAgICAgICAgICAgIGlmIChwYXJlbnROb2RlKSB7XG4gICAgICAgICAgICAgICAgICAgIHBhcmVudE5vZGUucmVtb3ZlQ2hpbGQoZG9tTm9kZSk7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgZGVzdHJveVdpZGdldChkb21Ob2RlLCB2Tm9kZSk7XG5cbiAgICAgICAgICAgICAgICByZXR1cm4gbnVsbDtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZnVuY3Rpb24gaW5zZXJ0Tm9kZShwYXJlbnROb2RlLCB2Tm9kZSwgcmVuZGVyT3B0aW9ucykge1xuICAgICAgICAgICAgICAgIHZhciBuZXdOb2RlID0gcmVuZGVyT3B0aW9ucy5yZW5kZXIodk5vZGUsIHJlbmRlck9wdGlvbnMpO1xuXG4gICAgICAgICAgICAgICAgaWYgKHBhcmVudE5vZGUpIHtcbiAgICAgICAgICAgICAgICAgICAgcGFyZW50Tm9kZS5hcHBlbmRDaGlsZChuZXdOb2RlKTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICByZXR1cm4gcGFyZW50Tm9kZTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZnVuY3Rpb24gc3RyaW5nUGF0Y2goZG9tTm9kZSwgbGVmdFZOb2RlLCB2VGV4dCwgcmVuZGVyT3B0aW9ucykge1xuICAgICAgICAgICAgICAgIHZhciBuZXdOb2RlO1xuXG4gICAgICAgICAgICAgICAgaWYgKGRvbU5vZGUubm9kZVR5cGUgPT09IDMpIHtcbiAgICAgICAgICAgICAgICAgICAgZG9tTm9kZS5yZXBsYWNlRGF0YSgwLCBkb21Ob2RlLmxlbmd0aCwgdlRleHQudGV4dCk7XG4gICAgICAgICAgICAgICAgICAgIG5ld05vZGUgPSBkb21Ob2RlO1xuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciBwYXJlbnROb2RlID0gZG9tTm9kZS5wYXJlbnROb2RlO1xuICAgICAgICAgICAgICAgICAgICBuZXdOb2RlID0gcmVuZGVyT3B0aW9ucy5yZW5kZXIodlRleHQsIHJlbmRlck9wdGlvbnMpO1xuXG4gICAgICAgICAgICAgICAgICAgIGlmIChwYXJlbnROb2RlICYmIG5ld05vZGUgIT09IGRvbU5vZGUpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHBhcmVudE5vZGUucmVwbGFjZUNoaWxkKG5ld05vZGUsIGRvbU5vZGUpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgcmV0dXJuIG5ld05vZGU7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIHdpZGdldFBhdGNoKGRvbU5vZGUsIGxlZnRWTm9kZSwgd2lkZ2V0LCByZW5kZXJPcHRpb25zKSB7XG4gICAgICAgICAgICAgICAgdmFyIHVwZGF0aW5nID0gdXBkYXRlV2lkZ2V0KGxlZnRWTm9kZSwgd2lkZ2V0KTtcbiAgICAgICAgICAgICAgICB2YXIgbmV3Tm9kZTtcblxuICAgICAgICAgICAgICAgIGlmICh1cGRhdGluZykge1xuICAgICAgICAgICAgICAgICAgICBuZXdOb2RlID0gd2lkZ2V0LnVwZGF0ZShsZWZ0Vk5vZGUsIGRvbU5vZGUpIHx8IGRvbU5vZGU7XG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgbmV3Tm9kZSA9IHJlbmRlck9wdGlvbnMucmVuZGVyKHdpZGdldCwgcmVuZGVyT3B0aW9ucyk7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgdmFyIHBhcmVudE5vZGUgPSBkb21Ob2RlLnBhcmVudE5vZGU7XG5cbiAgICAgICAgICAgICAgICBpZiAocGFyZW50Tm9kZSAmJiBuZXdOb2RlICE9PSBkb21Ob2RlKSB7XG4gICAgICAgICAgICAgICAgICAgIHBhcmVudE5vZGUucmVwbGFjZUNoaWxkKG5ld05vZGUsIGRvbU5vZGUpO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIGlmICghdXBkYXRpbmcpIHtcbiAgICAgICAgICAgICAgICAgICAgZGVzdHJveVdpZGdldChkb21Ob2RlLCBsZWZ0Vk5vZGUpO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHJldHVybiBuZXdOb2RlO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBmdW5jdGlvbiB2Tm9kZVBhdGNoKGRvbU5vZGUsIGxlZnRWTm9kZSwgdk5vZGUsIHJlbmRlck9wdGlvbnMpIHtcbiAgICAgICAgICAgICAgICB2YXIgcGFyZW50Tm9kZSA9IGRvbU5vZGUucGFyZW50Tm9kZTtcbiAgICAgICAgICAgICAgICB2YXIgbmV3Tm9kZSA9IHJlbmRlck9wdGlvbnMucmVuZGVyKHZOb2RlLCByZW5kZXJPcHRpb25zKTtcblxuICAgICAgICAgICAgICAgIGlmIChwYXJlbnROb2RlICYmIG5ld05vZGUgIT09IGRvbU5vZGUpIHtcbiAgICAgICAgICAgICAgICAgICAgcGFyZW50Tm9kZS5yZXBsYWNlQ2hpbGQobmV3Tm9kZSwgZG9tTm9kZSk7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgcmV0dXJuIG5ld05vZGU7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIGRlc3Ryb3lXaWRnZXQoZG9tTm9kZSwgdykge1xuICAgICAgICAgICAgICAgIGlmICh0eXBlb2Ygdy5kZXN0cm95ID09PSBcImZ1bmN0aW9uXCIgJiYgaXNXaWRnZXQodykpIHtcbiAgICAgICAgICAgICAgICAgICAgdy5kZXN0cm95KGRvbU5vZGUpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZnVuY3Rpb24gcmVvcmRlckNoaWxkcmVuKGRvbU5vZGUsIG1vdmVzKSB7XG4gICAgICAgICAgICAgICAgdmFyIGNoaWxkTm9kZXMgPSBkb21Ob2RlLmNoaWxkTm9kZXM7XG4gICAgICAgICAgICAgICAgdmFyIGtleU1hcCA9IHt9O1xuICAgICAgICAgICAgICAgIHZhciBub2RlO1xuICAgICAgICAgICAgICAgIHZhciByZW1vdmU7XG4gICAgICAgICAgICAgICAgdmFyIGluc2VydDtcblxuICAgICAgICAgICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgbW92ZXMucmVtb3Zlcy5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgICAgICAgICByZW1vdmUgPSBtb3Zlcy5yZW1vdmVzW2ldO1xuICAgICAgICAgICAgICAgICAgICBub2RlID0gY2hpbGROb2Rlc1tyZW1vdmUuZnJvbV07XG4gICAgICAgICAgICAgICAgICAgIGlmIChyZW1vdmUua2V5KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBrZXlNYXBbcmVtb3ZlLmtleV0gPSBub2RlO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIGRvbU5vZGUucmVtb3ZlQ2hpbGQobm9kZSk7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgdmFyIGxlbmd0aCA9IGNoaWxkTm9kZXMubGVuZ3RoO1xuICAgICAgICAgICAgICAgIGZvciAodmFyIGogPSAwOyBqIDwgbW92ZXMuaW5zZXJ0cy5sZW5ndGg7IGorKykge1xuICAgICAgICAgICAgICAgICAgICBpbnNlcnQgPSBtb3Zlcy5pbnNlcnRzW2pdO1xuICAgICAgICAgICAgICAgICAgICBub2RlID0ga2V5TWFwW2luc2VydC5rZXldO1xuICAgICAgICAgICAgICAgICAgICAvLyB0aGlzIGlzIHRoZSB3ZWlyZGVzdCBidWcgaSd2ZSBldmVyIHNlZW4gaW4gd2Via2l0XG4gICAgICAgICAgICAgICAgICAgIGRvbU5vZGUuaW5zZXJ0QmVmb3JlKG5vZGUsIGluc2VydC50byA+PSBsZW5ndGgrKyA/IG51bGwgOiBjaGlsZE5vZGVzW2luc2VydC50b10pO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZnVuY3Rpb24gcmVwbGFjZVJvb3Qob2xkUm9vdCwgbmV3Um9vdCkge1xuICAgICAgICAgICAgICAgIGlmIChvbGRSb290ICYmIG5ld1Jvb3QgJiYgb2xkUm9vdCAhPT0gbmV3Um9vdCAmJiBvbGRSb290LnBhcmVudE5vZGUpIHtcbiAgICAgICAgICAgICAgICAgICAgb2xkUm9vdC5wYXJlbnROb2RlLnJlcGxhY2VDaGlsZChuZXdSb290LCBvbGRSb290KTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICByZXR1cm4gbmV3Um9vdDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSwgeyBcIi4uL3Zub2RlL2lzLXdpZGdldC5qc1wiOiAyOSwgXCIuLi92bm9kZS92cGF0Y2guanNcIjogMzIsIFwiLi9hcHBseS1wcm9wZXJ0aWVzXCI6IDE0LCBcIi4vdXBkYXRlLXdpZGdldFwiOiAxOSB9XSwgMTg6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICB2YXIgZG9jdW1lbnQgPSByZXF1aXJlKFwiZ2xvYmFsL2RvY3VtZW50XCIpO1xuICAgICAgICAgICAgdmFyIGlzQXJyYXkgPSByZXF1aXJlKFwieC1pcy1hcnJheVwiKTtcblxuICAgICAgICAgICAgdmFyIHJlbmRlciA9IHJlcXVpcmUoXCIuL2NyZWF0ZS1lbGVtZW50XCIpO1xuICAgICAgICAgICAgdmFyIGRvbUluZGV4ID0gcmVxdWlyZShcIi4vZG9tLWluZGV4XCIpO1xuICAgICAgICAgICAgdmFyIHBhdGNoT3AgPSByZXF1aXJlKFwiLi9wYXRjaC1vcFwiKTtcbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gcGF0Y2g7XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIHBhdGNoKHJvb3ROb2RlLCBwYXRjaGVzLCByZW5kZXJPcHRpb25zKSB7XG4gICAgICAgICAgICAgICAgcmVuZGVyT3B0aW9ucyA9IHJlbmRlck9wdGlvbnMgfHwge307XG4gICAgICAgICAgICAgICAgcmVuZGVyT3B0aW9ucy5wYXRjaCA9IHJlbmRlck9wdGlvbnMucGF0Y2ggJiYgcmVuZGVyT3B0aW9ucy5wYXRjaCAhPT0gcGF0Y2ggPyByZW5kZXJPcHRpb25zLnBhdGNoIDogcGF0Y2hSZWN1cnNpdmU7XG4gICAgICAgICAgICAgICAgcmVuZGVyT3B0aW9ucy5yZW5kZXIgPSByZW5kZXJPcHRpb25zLnJlbmRlciB8fCByZW5kZXI7XG5cbiAgICAgICAgICAgICAgICByZXR1cm4gcmVuZGVyT3B0aW9ucy5wYXRjaChyb290Tm9kZSwgcGF0Y2hlcywgcmVuZGVyT3B0aW9ucyk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIHBhdGNoUmVjdXJzaXZlKHJvb3ROb2RlLCBwYXRjaGVzLCByZW5kZXJPcHRpb25zKSB7XG4gICAgICAgICAgICAgICAgdmFyIGluZGljZXMgPSBwYXRjaEluZGljZXMocGF0Y2hlcyk7XG5cbiAgICAgICAgICAgICAgICBpZiAoaW5kaWNlcy5sZW5ndGggPT09IDApIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHJvb3ROb2RlO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHZhciBpbmRleCA9IGRvbUluZGV4KHJvb3ROb2RlLCBwYXRjaGVzLmEsIGluZGljZXMpO1xuICAgICAgICAgICAgICAgIHZhciBvd25lckRvY3VtZW50ID0gcm9vdE5vZGUub3duZXJEb2N1bWVudDtcblxuICAgICAgICAgICAgICAgIGlmICghcmVuZGVyT3B0aW9ucy5kb2N1bWVudCAmJiBvd25lckRvY3VtZW50ICE9PSBkb2N1bWVudCkge1xuICAgICAgICAgICAgICAgICAgICByZW5kZXJPcHRpb25zLmRvY3VtZW50ID0gb3duZXJEb2N1bWVudDtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IGluZGljZXMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgICAgICAgICAgdmFyIG5vZGVJbmRleCA9IGluZGljZXNbaV07XG4gICAgICAgICAgICAgICAgICAgIHJvb3ROb2RlID0gYXBwbHlQYXRjaChyb290Tm9kZSwgaW5kZXhbbm9kZUluZGV4XSwgcGF0Y2hlc1tub2RlSW5kZXhdLCByZW5kZXJPcHRpb25zKTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICByZXR1cm4gcm9vdE5vZGU7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIGFwcGx5UGF0Y2gocm9vdE5vZGUsIGRvbU5vZGUsIHBhdGNoTGlzdCwgcmVuZGVyT3B0aW9ucykge1xuICAgICAgICAgICAgICAgIGlmICghZG9tTm9kZSkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gcm9vdE5vZGU7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgdmFyIG5ld05vZGU7XG5cbiAgICAgICAgICAgICAgICBpZiAoaXNBcnJheShwYXRjaExpc3QpKSB7XG4gICAgICAgICAgICAgICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgcGF0Y2hMaXN0Lmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBuZXdOb2RlID0gcGF0Y2hPcChwYXRjaExpc3RbaV0sIGRvbU5vZGUsIHJlbmRlck9wdGlvbnMpO1xuXG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoZG9tTm9kZSA9PT0gcm9vdE5vZGUpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICByb290Tm9kZSA9IG5ld05vZGU7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICBuZXdOb2RlID0gcGF0Y2hPcChwYXRjaExpc3QsIGRvbU5vZGUsIHJlbmRlck9wdGlvbnMpO1xuXG4gICAgICAgICAgICAgICAgICAgIGlmIChkb21Ob2RlID09PSByb290Tm9kZSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgcm9vdE5vZGUgPSBuZXdOb2RlO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgcmV0dXJuIHJvb3ROb2RlO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBmdW5jdGlvbiBwYXRjaEluZGljZXMocGF0Y2hlcykge1xuICAgICAgICAgICAgICAgIHZhciBpbmRpY2VzID0gW107XG5cbiAgICAgICAgICAgICAgICBmb3IgKHZhciBrZXkgaW4gcGF0Y2hlcykge1xuICAgICAgICAgICAgICAgICAgICBpZiAoa2V5ICE9PSBcImFcIikge1xuICAgICAgICAgICAgICAgICAgICAgICAgaW5kaWNlcy5wdXNoKE51bWJlcihrZXkpKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHJldHVybiBpbmRpY2VzO1xuICAgICAgICAgICAgfVxuICAgICAgICB9LCB7IFwiLi9jcmVhdGUtZWxlbWVudFwiOiAxNSwgXCIuL2RvbS1pbmRleFwiOiAxNiwgXCIuL3BhdGNoLW9wXCI6IDE3LCBcImdsb2JhbC9kb2N1bWVudFwiOiAxMCwgXCJ4LWlzLWFycmF5XCI6IDEyIH1dLCAxOTogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHtcbiAgICAgICAgICAgIHZhciBpc1dpZGdldCA9IHJlcXVpcmUoXCIuLi92bm9kZS9pcy13aWRnZXQuanNcIik7XG5cbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gdXBkYXRlV2lkZ2V0O1xuXG4gICAgICAgICAgICBmdW5jdGlvbiB1cGRhdGVXaWRnZXQoYSwgYikge1xuICAgICAgICAgICAgICAgIGlmIChpc1dpZGdldChhKSAmJiBpc1dpZGdldChiKSkge1xuICAgICAgICAgICAgICAgICAgICBpZiAoXCJuYW1lXCIgaW4gYSAmJiBcIm5hbWVcIiBpbiBiKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gYS5pZCA9PT0gYi5pZDtcbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBhLmluaXQgPT09IGIuaW5pdDtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSwgeyBcIi4uL3Zub2RlL2lzLXdpZGdldC5qc1wiOiAyOSB9XSwgMjA6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICBcInVzZSBzdHJpY3RcIjtcblxuICAgICAgICAgICAgdmFyIEV2U3RvcmUgPSByZXF1aXJlKFwiZXYtc3RvcmVcIik7XG5cbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gRXZIb29rO1xuXG4gICAgICAgICAgICBmdW5jdGlvbiBFdkhvb2sodmFsdWUpIHtcbiAgICAgICAgICAgICAgICBpZiAoISh0aGlzIGluc3RhbmNlb2YgRXZIb29rKSkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gbmV3IEV2SG9vayh2YWx1ZSk7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgdGhpcy52YWx1ZSA9IHZhbHVlO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBFdkhvb2sucHJvdG90eXBlLmhvb2sgPSBmdW5jdGlvbiAobm9kZSwgcHJvcGVydHlOYW1lKSB7XG4gICAgICAgICAgICAgICAgdmFyIGVzID0gRXZTdG9yZShub2RlKTtcbiAgICAgICAgICAgICAgICB2YXIgcHJvcE5hbWUgPSBwcm9wZXJ0eU5hbWUuc3Vic3RyKDMpO1xuXG4gICAgICAgICAgICAgICAgZXNbcHJvcE5hbWVdID0gdGhpcy52YWx1ZTtcbiAgICAgICAgICAgIH07XG5cbiAgICAgICAgICAgIEV2SG9vay5wcm90b3R5cGUudW5ob29rID0gZnVuY3Rpb24gKG5vZGUsIHByb3BlcnR5TmFtZSkge1xuICAgICAgICAgICAgICAgIHZhciBlcyA9IEV2U3RvcmUobm9kZSk7XG4gICAgICAgICAgICAgICAgdmFyIHByb3BOYW1lID0gcHJvcGVydHlOYW1lLnN1YnN0cigzKTtcblxuICAgICAgICAgICAgICAgIGVzW3Byb3BOYW1lXSA9IHVuZGVmaW5lZDtcbiAgICAgICAgICAgIH07XG4gICAgICAgIH0sIHsgXCJldi1zdG9yZVwiOiA3IH1dLCAyMTogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHtcbiAgICAgICAgICAgIFwidXNlIHN0cmljdFwiO1xuXG4gICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IFNvZnRTZXRIb29rO1xuXG4gICAgICAgICAgICBmdW5jdGlvbiBTb2Z0U2V0SG9vayh2YWx1ZSkge1xuICAgICAgICAgICAgICAgIGlmICghKHRoaXMgaW5zdGFuY2VvZiBTb2Z0U2V0SG9vaykpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIG5ldyBTb2Z0U2V0SG9vayh2YWx1ZSk7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgdGhpcy52YWx1ZSA9IHZhbHVlO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBTb2Z0U2V0SG9vay5wcm90b3R5cGUuaG9vayA9IGZ1bmN0aW9uIChub2RlLCBwcm9wZXJ0eU5hbWUpIHtcbiAgICAgICAgICAgICAgICBpZiAobm9kZVtwcm9wZXJ0eU5hbWVdICE9PSB0aGlzLnZhbHVlKSB7XG4gICAgICAgICAgICAgICAgICAgIG5vZGVbcHJvcGVydHlOYW1lXSA9IHRoaXMudmFsdWU7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfTtcbiAgICAgICAgfSwge31dLCAyMjogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHtcbiAgICAgICAgICAgIFwidXNlIHN0cmljdFwiO1xuXG4gICAgICAgICAgICB2YXIgaXNBcnJheSA9IHJlcXVpcmUoXCJ4LWlzLWFycmF5XCIpO1xuXG4gICAgICAgICAgICB2YXIgVk5vZGUgPSByZXF1aXJlKFwiLi4vdm5vZGUvdm5vZGUuanNcIik7XG4gICAgICAgICAgICB2YXIgVlRleHQgPSByZXF1aXJlKFwiLi4vdm5vZGUvdnRleHQuanNcIik7XG4gICAgICAgICAgICB2YXIgaXNWTm9kZSA9IHJlcXVpcmUoXCIuLi92bm9kZS9pcy12bm9kZVwiKTtcbiAgICAgICAgICAgIHZhciBpc1ZUZXh0ID0gcmVxdWlyZShcIi4uL3Zub2RlL2lzLXZ0ZXh0XCIpO1xuICAgICAgICAgICAgdmFyIGlzV2lkZ2V0ID0gcmVxdWlyZShcIi4uL3Zub2RlL2lzLXdpZGdldFwiKTtcbiAgICAgICAgICAgIHZhciBpc0hvb2sgPSByZXF1aXJlKFwiLi4vdm5vZGUvaXMtdmhvb2tcIik7XG4gICAgICAgICAgICB2YXIgaXNWVGh1bmsgPSByZXF1aXJlKFwiLi4vdm5vZGUvaXMtdGh1bmtcIik7XG5cbiAgICAgICAgICAgIHZhciBwYXJzZVRhZyA9IHJlcXVpcmUoXCIuL3BhcnNlLXRhZy5qc1wiKTtcbiAgICAgICAgICAgIHZhciBzb2Z0U2V0SG9vayA9IHJlcXVpcmUoXCIuL2hvb2tzL3NvZnQtc2V0LWhvb2suanNcIik7XG4gICAgICAgICAgICB2YXIgZXZIb29rID0gcmVxdWlyZShcIi4vaG9va3MvZXYtaG9vay5qc1wiKTtcblxuICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBoO1xuXG4gICAgICAgICAgICBmdW5jdGlvbiBoKHRhZ05hbWUsIHByb3BlcnRpZXMsIGNoaWxkcmVuKSB7XG4gICAgICAgICAgICAgICAgdmFyIGNoaWxkTm9kZXMgPSBbXTtcbiAgICAgICAgICAgICAgICB2YXIgdGFnLCBwcm9wcywga2V5LCBuYW1lc3BhY2U7XG5cbiAgICAgICAgICAgICAgICBpZiAoIWNoaWxkcmVuICYmIGlzQ2hpbGRyZW4ocHJvcGVydGllcykpIHtcbiAgICAgICAgICAgICAgICAgICAgY2hpbGRyZW4gPSBwcm9wZXJ0aWVzO1xuICAgICAgICAgICAgICAgICAgICBwcm9wcyA9IHt9O1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHByb3BzID0gcHJvcHMgfHwgcHJvcGVydGllcyB8fCB7fTtcbiAgICAgICAgICAgICAgICB0YWcgPSBwYXJzZVRhZyh0YWdOYW1lLCBwcm9wcyk7XG5cbiAgICAgICAgICAgICAgICAvLyBzdXBwb3J0IGtleXNcbiAgICAgICAgICAgICAgICBpZiAocHJvcHMuaGFzT3duUHJvcGVydHkoXCJrZXlcIikpIHtcbiAgICAgICAgICAgICAgICAgICAga2V5ID0gcHJvcHMua2V5O1xuICAgICAgICAgICAgICAgICAgICBwcm9wcy5rZXkgPSB1bmRlZmluZWQ7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgLy8gc3VwcG9ydCBuYW1lc3BhY2VcbiAgICAgICAgICAgICAgICBpZiAocHJvcHMuaGFzT3duUHJvcGVydHkoXCJuYW1lc3BhY2VcIikpIHtcbiAgICAgICAgICAgICAgICAgICAgbmFtZXNwYWNlID0gcHJvcHMubmFtZXNwYWNlO1xuICAgICAgICAgICAgICAgICAgICBwcm9wcy5uYW1lc3BhY2UgPSB1bmRlZmluZWQ7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgLy8gZml4IGN1cnNvciBidWdcbiAgICAgICAgICAgICAgICBpZiAodGFnID09PSBcIklOUFVUXCIgJiYgIW5hbWVzcGFjZSAmJiBwcm9wcy5oYXNPd25Qcm9wZXJ0eShcInZhbHVlXCIpICYmIHByb3BzLnZhbHVlICE9PSB1bmRlZmluZWQgJiYgIWlzSG9vayhwcm9wcy52YWx1ZSkpIHtcbiAgICAgICAgICAgICAgICAgICAgcHJvcHMudmFsdWUgPSBzb2Z0U2V0SG9vayhwcm9wcy52YWx1ZSk7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgdHJhbnNmb3JtUHJvcGVydGllcyhwcm9wcyk7XG5cbiAgICAgICAgICAgICAgICBpZiAoY2hpbGRyZW4gIT09IHVuZGVmaW5lZCAmJiBjaGlsZHJlbiAhPT0gbnVsbCkge1xuICAgICAgICAgICAgICAgICAgICBhZGRDaGlsZChjaGlsZHJlbiwgY2hpbGROb2RlcywgdGFnLCBwcm9wcyk7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgcmV0dXJuIG5ldyBWTm9kZSh0YWcsIHByb3BzLCBjaGlsZE5vZGVzLCBrZXksIG5hbWVzcGFjZSk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIGFkZENoaWxkKGMsIGNoaWxkTm9kZXMsIHRhZywgcHJvcHMpIHtcbiAgICAgICAgICAgICAgICBpZiAodHlwZW9mIGMgPT09IFwic3RyaW5nXCIpIHtcbiAgICAgICAgICAgICAgICAgICAgY2hpbGROb2Rlcy5wdXNoKG5ldyBWVGV4dChjKSk7XG4gICAgICAgICAgICAgICAgfSBlbHNlIGlmICh0eXBlb2YgYyA9PT0gXCJudW1iZXJcIikge1xuICAgICAgICAgICAgICAgICAgICBjaGlsZE5vZGVzLnB1c2gobmV3IFZUZXh0KFN0cmluZyhjKSkpO1xuICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoaXNDaGlsZChjKSkge1xuICAgICAgICAgICAgICAgICAgICBjaGlsZE5vZGVzLnB1c2goYyk7XG4gICAgICAgICAgICAgICAgfSBlbHNlIGlmIChpc0FycmF5KGMpKSB7XG4gICAgICAgICAgICAgICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgYy5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgICAgICAgICAgICAgYWRkQ2hpbGQoY1tpXSwgY2hpbGROb2RlcywgdGFnLCBwcm9wcyk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKGMgPT09IG51bGwgfHwgYyA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICB0aHJvdyBVbmV4cGVjdGVkVmlydHVhbEVsZW1lbnQoe1xuICAgICAgICAgICAgICAgICAgICAgICAgZm9yZWlnbk9iamVjdDogYyxcbiAgICAgICAgICAgICAgICAgICAgICAgIHBhcmVudFZub2RlOiB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdGFnTmFtZTogdGFnLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHByb3BlcnRpZXM6IHByb3BzXG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZnVuY3Rpb24gdHJhbnNmb3JtUHJvcGVydGllcyhwcm9wcykge1xuICAgICAgICAgICAgICAgIGZvciAodmFyIHByb3BOYW1lIGluIHByb3BzKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmIChwcm9wcy5oYXNPd25Qcm9wZXJ0eShwcm9wTmFtZSkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHZhciB2YWx1ZSA9IHByb3BzW3Byb3BOYW1lXTtcblxuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGlzSG9vayh2YWx1ZSkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb250aW51ZTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHByb3BOYW1lLnN1YnN0cigwLCAzKSA9PT0gXCJldi1cIikge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIGFkZCBldi1mb28gc3VwcG9ydFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHByb3BzW3Byb3BOYW1lXSA9IGV2SG9vayh2YWx1ZSk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIGlzQ2hpbGQoeCkge1xuICAgICAgICAgICAgICAgIHJldHVybiBpc1ZOb2RlKHgpIHx8IGlzVlRleHQoeCkgfHwgaXNXaWRnZXQoeCkgfHwgaXNWVGh1bmsoeCk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIGlzQ2hpbGRyZW4oeCkge1xuICAgICAgICAgICAgICAgIHJldHVybiB0eXBlb2YgeCA9PT0gXCJzdHJpbmdcIiB8fCBpc0FycmF5KHgpIHx8IGlzQ2hpbGQoeCk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIFVuZXhwZWN0ZWRWaXJ0dWFsRWxlbWVudChkYXRhKSB7XG4gICAgICAgICAgICAgICAgdmFyIGVyciA9IG5ldyBFcnJvcigpO1xuXG4gICAgICAgICAgICAgICAgZXJyLnR5cGUgPSBcInZpcnR1YWwtaHlwZXJzY3JpcHQudW5leHBlY3RlZC52aXJ0dWFsLWVsZW1lbnRcIjtcbiAgICAgICAgICAgICAgICBlcnIubWVzc2FnZSA9IFwiVW5leHBlY3RlZCB2aXJ0dWFsIGNoaWxkIHBhc3NlZCB0byBoKCkuXFxuXCIgKyBcIkV4cGVjdGVkIGEgVk5vZGUgLyBWdGh1bmsgLyBWV2lkZ2V0IC8gc3RyaW5nIGJ1dDpcXG5cIiArIFwiZ290OlxcblwiICsgZXJyb3JTdHJpbmcoZGF0YS5mb3JlaWduT2JqZWN0KSArIFwiLlxcblwiICsgXCJUaGUgcGFyZW50IHZub2RlIGlzOlxcblwiICsgZXJyb3JTdHJpbmcoZGF0YS5wYXJlbnRWbm9kZSk7XG4gICAgICAgICAgICAgICAgXCJcXG5cIiArIFwiU3VnZ2VzdGVkIGZpeDogY2hhbmdlIHlvdXIgYGgoLi4uLCBbIC4uLiBdKWAgY2FsbHNpdGUuXCI7XG4gICAgICAgICAgICAgICAgZXJyLmZvcmVpZ25PYmplY3QgPSBkYXRhLmZvcmVpZ25PYmplY3Q7XG4gICAgICAgICAgICAgICAgZXJyLnBhcmVudFZub2RlID0gZGF0YS5wYXJlbnRWbm9kZTtcblxuICAgICAgICAgICAgICAgIHJldHVybiBlcnI7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIGVycm9yU3RyaW5nKG9iaikge1xuICAgICAgICAgICAgICAgIHRyeSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBKU09OLnN0cmluZ2lmeShvYmosIG51bGwsIFwiICAgIFwiKTtcbiAgICAgICAgICAgICAgICB9IGNhdGNoIChlKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBTdHJpbmcob2JqKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH0sIHsgXCIuLi92bm9kZS9pcy10aHVua1wiOiAyNSwgXCIuLi92bm9kZS9pcy12aG9va1wiOiAyNiwgXCIuLi92bm9kZS9pcy12bm9kZVwiOiAyNywgXCIuLi92bm9kZS9pcy12dGV4dFwiOiAyOCwgXCIuLi92bm9kZS9pcy13aWRnZXRcIjogMjksIFwiLi4vdm5vZGUvdm5vZGUuanNcIjogMzEsIFwiLi4vdm5vZGUvdnRleHQuanNcIjogMzMsIFwiLi9ob29rcy9ldi1ob29rLmpzXCI6IDIwLCBcIi4vaG9va3Mvc29mdC1zZXQtaG9vay5qc1wiOiAyMSwgXCIuL3BhcnNlLXRhZy5qc1wiOiAyMywgXCJ4LWlzLWFycmF5XCI6IDEyIH1dLCAyMzogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHtcbiAgICAgICAgICAgIFwidXNlIHN0cmljdFwiO1xuXG4gICAgICAgICAgICB2YXIgc3BsaXQgPSByZXF1aXJlKFwiYnJvd3Nlci1zcGxpdFwiKTtcblxuICAgICAgICAgICAgdmFyIGNsYXNzSWRTcGxpdCA9IC8oW1xcLiNdP1thLXpBLVowLTlcXHUwMDdGLVxcdUZGRkZfOi1dKykvO1xuICAgICAgICAgICAgdmFyIG5vdENsYXNzSWQgPSAvXlxcLnwjLztcblxuICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBwYXJzZVRhZztcblxuICAgICAgICAgICAgZnVuY3Rpb24gcGFyc2VUYWcodGFnLCBwcm9wcykge1xuICAgICAgICAgICAgICAgIGlmICghdGFnKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBcIkRJVlwiO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHZhciBub0lkID0gIXByb3BzLmhhc093blByb3BlcnR5KFwiaWRcIik7XG5cbiAgICAgICAgICAgICAgICB2YXIgdGFnUGFydHMgPSBzcGxpdCh0YWcsIGNsYXNzSWRTcGxpdCk7XG4gICAgICAgICAgICAgICAgdmFyIHRhZ05hbWUgPSBudWxsO1xuXG4gICAgICAgICAgICAgICAgaWYgKG5vdENsYXNzSWQudGVzdCh0YWdQYXJ0c1sxXSkpIHtcbiAgICAgICAgICAgICAgICAgICAgdGFnTmFtZSA9IFwiRElWXCI7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgdmFyIGNsYXNzZXMsIHBhcnQsIHR5cGUsIGk7XG5cbiAgICAgICAgICAgICAgICBmb3IgKGkgPSAwOyBpIDwgdGFnUGFydHMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgICAgICAgICAgcGFydCA9IHRhZ1BhcnRzW2ldO1xuXG4gICAgICAgICAgICAgICAgICAgIGlmICghcGFydCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgY29udGludWU7XG4gICAgICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgICAgICB0eXBlID0gcGFydC5jaGFyQXQoMCk7XG5cbiAgICAgICAgICAgICAgICAgICAgaWYgKCF0YWdOYW1lKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICB0YWdOYW1lID0gcGFydDtcbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIGlmICh0eXBlID09PSBcIi5cIikge1xuICAgICAgICAgICAgICAgICAgICAgICAgY2xhc3NlcyA9IGNsYXNzZXMgfHwgW107XG4gICAgICAgICAgICAgICAgICAgICAgICBjbGFzc2VzLnB1c2gocGFydC5zdWJzdHJpbmcoMSwgcGFydC5sZW5ndGgpKTtcbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIGlmICh0eXBlID09PSBcIiNcIiAmJiBub0lkKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBwcm9wcy5pZCA9IHBhcnQuc3Vic3RyaW5nKDEsIHBhcnQubGVuZ3RoKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIGlmIChjbGFzc2VzKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmIChwcm9wcy5jbGFzc05hbWUpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGNsYXNzZXMucHVzaChwcm9wcy5jbGFzc05hbWUpO1xuICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgcHJvcHMuY2xhc3NOYW1lID0gY2xhc3Nlcy5qb2luKFwiIFwiKTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICByZXR1cm4gcHJvcHMubmFtZXNwYWNlID8gdGFnTmFtZSA6IHRhZ05hbWUudG9VcHBlckNhc2UoKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSwgeyBcImJyb3dzZXItc3BsaXRcIjogNSB9XSwgMjQ6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICB2YXIgaXNWTm9kZSA9IHJlcXVpcmUoXCIuL2lzLXZub2RlXCIpO1xuICAgICAgICAgICAgdmFyIGlzVlRleHQgPSByZXF1aXJlKFwiLi9pcy12dGV4dFwiKTtcbiAgICAgICAgICAgIHZhciBpc1dpZGdldCA9IHJlcXVpcmUoXCIuL2lzLXdpZGdldFwiKTtcbiAgICAgICAgICAgIHZhciBpc1RodW5rID0gcmVxdWlyZShcIi4vaXMtdGh1bmtcIik7XG5cbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gaGFuZGxlVGh1bms7XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIGhhbmRsZVRodW5rKGEsIGIpIHtcbiAgICAgICAgICAgICAgICB2YXIgcmVuZGVyZWRBID0gYTtcbiAgICAgICAgICAgICAgICB2YXIgcmVuZGVyZWRCID0gYjtcblxuICAgICAgICAgICAgICAgIGlmIChpc1RodW5rKGIpKSB7XG4gICAgICAgICAgICAgICAgICAgIHJlbmRlcmVkQiA9IHJlbmRlclRodW5rKGIsIGEpO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIGlmIChpc1RodW5rKGEpKSB7XG4gICAgICAgICAgICAgICAgICAgIHJlbmRlcmVkQSA9IHJlbmRlclRodW5rKGEsIG51bGwpO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHJldHVybiB7XG4gICAgICAgICAgICAgICAgICAgIGE6IHJlbmRlcmVkQSxcbiAgICAgICAgICAgICAgICAgICAgYjogcmVuZGVyZWRCXG4gICAgICAgICAgICAgICAgfTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZnVuY3Rpb24gcmVuZGVyVGh1bmsodGh1bmssIHByZXZpb3VzKSB7XG4gICAgICAgICAgICAgICAgdmFyIHJlbmRlcmVkVGh1bmsgPSB0aHVuay52bm9kZTtcblxuICAgICAgICAgICAgICAgIGlmICghcmVuZGVyZWRUaHVuaykge1xuICAgICAgICAgICAgICAgICAgICByZW5kZXJlZFRodW5rID0gdGh1bmsudm5vZGUgPSB0aHVuay5yZW5kZXIocHJldmlvdXMpO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIGlmICghKGlzVk5vZGUocmVuZGVyZWRUaHVuaykgfHwgaXNWVGV4dChyZW5kZXJlZFRodW5rKSB8fCBpc1dpZGdldChyZW5kZXJlZFRodW5rKSkpIHtcbiAgICAgICAgICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKFwidGh1bmsgZGlkIG5vdCByZXR1cm4gYSB2YWxpZCBub2RlXCIpO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHJldHVybiByZW5kZXJlZFRodW5rO1xuICAgICAgICAgICAgfVxuICAgICAgICB9LCB7IFwiLi9pcy10aHVua1wiOiAyNSwgXCIuL2lzLXZub2RlXCI6IDI3LCBcIi4vaXMtdnRleHRcIjogMjgsIFwiLi9pcy13aWRnZXRcIjogMjkgfV0sIDI1OiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge1xuICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBpc1RodW5rO1xuXG4gICAgICAgICAgICBmdW5jdGlvbiBpc1RodW5rKHQpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gdCAmJiB0LnR5cGUgPT09IFwiVGh1bmtcIjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSwge31dLCAyNjogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHtcbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gaXNIb29rO1xuXG4gICAgICAgICAgICBmdW5jdGlvbiBpc0hvb2soaG9vaykge1xuICAgICAgICAgICAgICAgIHJldHVybiBob29rICYmICh0eXBlb2YgaG9vay5ob29rID09PSBcImZ1bmN0aW9uXCIgJiYgIWhvb2suaGFzT3duUHJvcGVydHkoXCJob29rXCIpIHx8IHR5cGVvZiBob29rLnVuaG9vayA9PT0gXCJmdW5jdGlvblwiICYmICFob29rLmhhc093blByb3BlcnR5KFwidW5ob29rXCIpKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSwge31dLCAyNzogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHtcbiAgICAgICAgICAgIHZhciB2ZXJzaW9uID0gcmVxdWlyZShcIi4vdmVyc2lvblwiKTtcblxuICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBpc1ZpcnR1YWxOb2RlO1xuXG4gICAgICAgICAgICBmdW5jdGlvbiBpc1ZpcnR1YWxOb2RlKHgpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4geCAmJiB4LnR5cGUgPT09IFwiVmlydHVhbE5vZGVcIiAmJiB4LnZlcnNpb24gPT09IHZlcnNpb247XG4gICAgICAgICAgICB9XG4gICAgICAgIH0sIHsgXCIuL3ZlcnNpb25cIjogMzAgfV0sIDI4OiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge1xuICAgICAgICAgICAgdmFyIHZlcnNpb24gPSByZXF1aXJlKFwiLi92ZXJzaW9uXCIpO1xuXG4gICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IGlzVmlydHVhbFRleHQ7XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIGlzVmlydHVhbFRleHQoeCkge1xuICAgICAgICAgICAgICAgIHJldHVybiB4ICYmIHgudHlwZSA9PT0gXCJWaXJ0dWFsVGV4dFwiICYmIHgudmVyc2lvbiA9PT0gdmVyc2lvbjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSwgeyBcIi4vdmVyc2lvblwiOiAzMCB9XSwgMjk6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IGlzV2lkZ2V0O1xuXG4gICAgICAgICAgICBmdW5jdGlvbiBpc1dpZGdldCh3KSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHcgJiYgdy50eXBlID09PSBcIldpZGdldFwiO1xuICAgICAgICAgICAgfVxuICAgICAgICB9LCB7fV0sIDMwOiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge1xuICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBcIjJcIjtcbiAgICAgICAgfSwge31dLCAzMTogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHtcbiAgICAgICAgICAgIHZhciB2ZXJzaW9uID0gcmVxdWlyZShcIi4vdmVyc2lvblwiKTtcbiAgICAgICAgICAgIHZhciBpc1ZOb2RlID0gcmVxdWlyZShcIi4vaXMtdm5vZGVcIik7XG4gICAgICAgICAgICB2YXIgaXNXaWRnZXQgPSByZXF1aXJlKFwiLi9pcy13aWRnZXRcIik7XG4gICAgICAgICAgICB2YXIgaXNUaHVuayA9IHJlcXVpcmUoXCIuL2lzLXRodW5rXCIpO1xuICAgICAgICAgICAgdmFyIGlzVkhvb2sgPSByZXF1aXJlKFwiLi9pcy12aG9va1wiKTtcblxuICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBWaXJ0dWFsTm9kZTtcblxuICAgICAgICAgICAgdmFyIG5vUHJvcGVydGllcyA9IHt9O1xuICAgICAgICAgICAgdmFyIG5vQ2hpbGRyZW4gPSBbXTtcblxuICAgICAgICAgICAgZnVuY3Rpb24gVmlydHVhbE5vZGUodGFnTmFtZSwgcHJvcGVydGllcywgY2hpbGRyZW4sIGtleSwgbmFtZXNwYWNlKSB7XG4gICAgICAgICAgICAgICAgdGhpcy50YWdOYW1lID0gdGFnTmFtZTtcbiAgICAgICAgICAgICAgICB0aGlzLnByb3BlcnRpZXMgPSBwcm9wZXJ0aWVzIHx8IG5vUHJvcGVydGllcztcbiAgICAgICAgICAgICAgICB0aGlzLmNoaWxkcmVuID0gY2hpbGRyZW4gfHwgbm9DaGlsZHJlbjtcbiAgICAgICAgICAgICAgICB0aGlzLmtleSA9IGtleSAhPSBudWxsID8gU3RyaW5nKGtleSkgOiB1bmRlZmluZWQ7XG4gICAgICAgICAgICAgICAgdGhpcy5uYW1lc3BhY2UgPSB0eXBlb2YgbmFtZXNwYWNlID09PSBcInN0cmluZ1wiID8gbmFtZXNwYWNlIDogbnVsbDtcblxuICAgICAgICAgICAgICAgIHZhciBjb3VudCA9IGNoaWxkcmVuICYmIGNoaWxkcmVuLmxlbmd0aCB8fCAwO1xuICAgICAgICAgICAgICAgIHZhciBkZXNjZW5kYW50cyA9IDA7XG4gICAgICAgICAgICAgICAgdmFyIGhhc1dpZGdldHMgPSBmYWxzZTtcbiAgICAgICAgICAgICAgICB2YXIgaGFzVGh1bmtzID0gZmFsc2U7XG4gICAgICAgICAgICAgICAgdmFyIGRlc2NlbmRhbnRIb29rcyA9IGZhbHNlO1xuICAgICAgICAgICAgICAgIHZhciBob29rcztcblxuICAgICAgICAgICAgICAgIGZvciAodmFyIHByb3BOYW1lIGluIHByb3BlcnRpZXMpIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKHByb3BlcnRpZXMuaGFzT3duUHJvcGVydHkocHJvcE5hbWUpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICB2YXIgcHJvcGVydHkgPSBwcm9wZXJ0aWVzW3Byb3BOYW1lXTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChpc1ZIb29rKHByb3BlcnR5KSAmJiBwcm9wZXJ0eS51bmhvb2spIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoIWhvb2tzKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGhvb2tzID0ge307XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaG9va3NbcHJvcE5hbWVdID0gcHJvcGVydHk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IGNvdW50OyBpKyspIHtcbiAgICAgICAgICAgICAgICAgICAgdmFyIGNoaWxkID0gY2hpbGRyZW5baV07XG4gICAgICAgICAgICAgICAgICAgIGlmIChpc1ZOb2RlKGNoaWxkKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgZGVzY2VuZGFudHMgKz0gY2hpbGQuY291bnQgfHwgMDtcblxuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKCFoYXNXaWRnZXRzICYmIGNoaWxkLmhhc1dpZGdldHMpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBoYXNXaWRnZXRzID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKCFoYXNUaHVua3MgJiYgY2hpbGQuaGFzVGh1bmtzKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaGFzVGh1bmtzID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKCFkZXNjZW5kYW50SG9va3MgJiYgKGNoaWxkLmhvb2tzIHx8IGNoaWxkLmRlc2NlbmRhbnRIb29rcykpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBkZXNjZW5kYW50SG9va3MgPSB0cnVlO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKCFoYXNXaWRnZXRzICYmIGlzV2lkZ2V0KGNoaWxkKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHR5cGVvZiBjaGlsZC5kZXN0cm95ID09PSBcImZ1bmN0aW9uXCIpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBoYXNXaWRnZXRzID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIGlmICghaGFzVGh1bmtzICYmIGlzVGh1bmsoY2hpbGQpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBoYXNUaHVua3MgPSB0cnVlO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgdGhpcy5jb3VudCA9IGNvdW50ICsgZGVzY2VuZGFudHM7XG4gICAgICAgICAgICAgICAgdGhpcy5oYXNXaWRnZXRzID0gaGFzV2lkZ2V0cztcbiAgICAgICAgICAgICAgICB0aGlzLmhhc1RodW5rcyA9IGhhc1RodW5rcztcbiAgICAgICAgICAgICAgICB0aGlzLmhvb2tzID0gaG9va3M7XG4gICAgICAgICAgICAgICAgdGhpcy5kZXNjZW5kYW50SG9va3MgPSBkZXNjZW5kYW50SG9va3M7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIFZpcnR1YWxOb2RlLnByb3RvdHlwZS52ZXJzaW9uID0gdmVyc2lvbjtcbiAgICAgICAgICAgIFZpcnR1YWxOb2RlLnByb3RvdHlwZS50eXBlID0gXCJWaXJ0dWFsTm9kZVwiO1xuICAgICAgICB9LCB7IFwiLi9pcy10aHVua1wiOiAyNSwgXCIuL2lzLXZob29rXCI6IDI2LCBcIi4vaXMtdm5vZGVcIjogMjcsIFwiLi9pcy13aWRnZXRcIjogMjksIFwiLi92ZXJzaW9uXCI6IDMwIH1dLCAzMjogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHtcbiAgICAgICAgICAgIHZhciB2ZXJzaW9uID0gcmVxdWlyZShcIi4vdmVyc2lvblwiKTtcblxuICAgICAgICAgICAgVmlydHVhbFBhdGNoLk5PTkUgPSAwO1xuICAgICAgICAgICAgVmlydHVhbFBhdGNoLlZURVhUID0gMTtcbiAgICAgICAgICAgIFZpcnR1YWxQYXRjaC5WTk9ERSA9IDI7XG4gICAgICAgICAgICBWaXJ0dWFsUGF0Y2guV0lER0VUID0gMztcbiAgICAgICAgICAgIFZpcnR1YWxQYXRjaC5QUk9QUyA9IDQ7XG4gICAgICAgICAgICBWaXJ0dWFsUGF0Y2guT1JERVIgPSA1O1xuICAgICAgICAgICAgVmlydHVhbFBhdGNoLklOU0VSVCA9IDY7XG4gICAgICAgICAgICBWaXJ0dWFsUGF0Y2guUkVNT1ZFID0gNztcbiAgICAgICAgICAgIFZpcnR1YWxQYXRjaC5USFVOSyA9IDg7XG5cbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gVmlydHVhbFBhdGNoO1xuXG4gICAgICAgICAgICBmdW5jdGlvbiBWaXJ0dWFsUGF0Y2godHlwZSwgdk5vZGUsIHBhdGNoKSB7XG4gICAgICAgICAgICAgICAgdGhpcy50eXBlID0gTnVtYmVyKHR5cGUpO1xuICAgICAgICAgICAgICAgIHRoaXMudk5vZGUgPSB2Tm9kZTtcbiAgICAgICAgICAgICAgICB0aGlzLnBhdGNoID0gcGF0Y2g7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIFZpcnR1YWxQYXRjaC5wcm90b3R5cGUudmVyc2lvbiA9IHZlcnNpb247XG4gICAgICAgICAgICBWaXJ0dWFsUGF0Y2gucHJvdG90eXBlLnR5cGUgPSBcIlZpcnR1YWxQYXRjaFwiO1xuICAgICAgICB9LCB7IFwiLi92ZXJzaW9uXCI6IDMwIH1dLCAzMzogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHtcbiAgICAgICAgICAgIHZhciB2ZXJzaW9uID0gcmVxdWlyZShcIi4vdmVyc2lvblwiKTtcblxuICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBWaXJ0dWFsVGV4dDtcblxuICAgICAgICAgICAgZnVuY3Rpb24gVmlydHVhbFRleHQodGV4dCkge1xuICAgICAgICAgICAgICAgIHRoaXMudGV4dCA9IFN0cmluZyh0ZXh0KTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgVmlydHVhbFRleHQucHJvdG90eXBlLnZlcnNpb24gPSB2ZXJzaW9uO1xuICAgICAgICAgICAgVmlydHVhbFRleHQucHJvdG90eXBlLnR5cGUgPSBcIlZpcnR1YWxUZXh0XCI7XG4gICAgICAgIH0sIHsgXCIuL3ZlcnNpb25cIjogMzAgfV0sIDM0OiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge1xuICAgICAgICAgICAgdmFyIGlzT2JqZWN0ID0gcmVxdWlyZShcImlzLW9iamVjdFwiKTtcbiAgICAgICAgICAgIHZhciBpc0hvb2sgPSByZXF1aXJlKFwiLi4vdm5vZGUvaXMtdmhvb2tcIik7XG5cbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gZGlmZlByb3BzO1xuXG4gICAgICAgICAgICBmdW5jdGlvbiBkaWZmUHJvcHMoYSwgYikge1xuICAgICAgICAgICAgICAgIHZhciBkaWZmO1xuXG4gICAgICAgICAgICAgICAgZm9yICh2YXIgYUtleSBpbiBhKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmICghKGFLZXkgaW4gYikpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGRpZmYgPSBkaWZmIHx8IHt9O1xuICAgICAgICAgICAgICAgICAgICAgICAgZGlmZlthS2V5XSA9IHVuZGVmaW5lZDtcbiAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgIHZhciBhVmFsdWUgPSBhW2FLZXldO1xuICAgICAgICAgICAgICAgICAgICB2YXIgYlZhbHVlID0gYlthS2V5XTtcblxuICAgICAgICAgICAgICAgICAgICBpZiAoYVZhbHVlID09PSBiVmFsdWUpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnRpbnVlO1xuICAgICAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKGlzT2JqZWN0KGFWYWx1ZSkgJiYgaXNPYmplY3QoYlZhbHVlKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGdldFByb3RvdHlwZShiVmFsdWUpICE9PSBnZXRQcm90b3R5cGUoYVZhbHVlKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRpZmYgPSBkaWZmIHx8IHt9O1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRpZmZbYUtleV0gPSBiVmFsdWU7XG4gICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKGlzSG9vayhiVmFsdWUpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgZGlmZiA9IGRpZmYgfHwge307XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgZGlmZlthS2V5XSA9IGJWYWx1ZTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdmFyIG9iamVjdERpZmYgPSBkaWZmUHJvcHMoYVZhbHVlLCBiVmFsdWUpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChvYmplY3REaWZmKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRpZmYgPSBkaWZmIHx8IHt9O1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBkaWZmW2FLZXldID0gb2JqZWN0RGlmZjtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBkaWZmID0gZGlmZiB8fCB7fTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGRpZmZbYUtleV0gPSBiVmFsdWU7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICBmb3IgKHZhciBiS2V5IGluIGIpIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKCEoYktleSBpbiBhKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgZGlmZiA9IGRpZmYgfHwge307XG4gICAgICAgICAgICAgICAgICAgICAgICBkaWZmW2JLZXldID0gYltiS2V5XTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHJldHVybiBkaWZmO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBmdW5jdGlvbiBnZXRQcm90b3R5cGUodmFsdWUpIHtcbiAgICAgICAgICAgICAgICBpZiAoT2JqZWN0LmdldFByb3RvdHlwZU9mKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBPYmplY3QuZ2V0UHJvdG90eXBlT2YodmFsdWUpO1xuICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAodmFsdWUuX19wcm90b19fKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiB2YWx1ZS5fX3Byb3RvX187XG4gICAgICAgICAgICAgICAgfSBlbHNlIGlmICh2YWx1ZS5jb25zdHJ1Y3Rvcikge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gdmFsdWUuY29uc3RydWN0b3IucHJvdG90eXBlO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgfSwgeyBcIi4uL3Zub2RlL2lzLXZob29rXCI6IDI2LCBcImlzLW9iamVjdFwiOiAxMSB9XSwgMzU6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICB2YXIgaXNBcnJheSA9IHJlcXVpcmUoXCJ4LWlzLWFycmF5XCIpO1xuXG4gICAgICAgICAgICB2YXIgVlBhdGNoID0gcmVxdWlyZShcIi4uL3Zub2RlL3ZwYXRjaFwiKTtcbiAgICAgICAgICAgIHZhciBpc1ZOb2RlID0gcmVxdWlyZShcIi4uL3Zub2RlL2lzLXZub2RlXCIpO1xuICAgICAgICAgICAgdmFyIGlzVlRleHQgPSByZXF1aXJlKFwiLi4vdm5vZGUvaXMtdnRleHRcIik7XG4gICAgICAgICAgICB2YXIgaXNXaWRnZXQgPSByZXF1aXJlKFwiLi4vdm5vZGUvaXMtd2lkZ2V0XCIpO1xuICAgICAgICAgICAgdmFyIGlzVGh1bmsgPSByZXF1aXJlKFwiLi4vdm5vZGUvaXMtdGh1bmtcIik7XG4gICAgICAgICAgICB2YXIgaGFuZGxlVGh1bmsgPSByZXF1aXJlKFwiLi4vdm5vZGUvaGFuZGxlLXRodW5rXCIpO1xuXG4gICAgICAgICAgICB2YXIgZGlmZlByb3BzID0gcmVxdWlyZShcIi4vZGlmZi1wcm9wc1wiKTtcblxuICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBkaWZmO1xuXG4gICAgICAgICAgICBmdW5jdGlvbiBkaWZmKGEsIGIpIHtcbiAgICAgICAgICAgICAgICB2YXIgcGF0Y2ggPSB7IGE6IGEgfTtcbiAgICAgICAgICAgICAgICB3YWxrKGEsIGIsIHBhdGNoLCAwKTtcbiAgICAgICAgICAgICAgICByZXR1cm4gcGF0Y2g7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIHdhbGsoYSwgYiwgcGF0Y2gsIGluZGV4KSB7XG4gICAgICAgICAgICAgICAgaWYgKGEgPT09IGIpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHZhciBhcHBseSA9IHBhdGNoW2luZGV4XTtcbiAgICAgICAgICAgICAgICB2YXIgYXBwbHlDbGVhciA9IGZhbHNlO1xuXG4gICAgICAgICAgICAgICAgaWYgKGlzVGh1bmsoYSkgfHwgaXNUaHVuayhiKSkge1xuICAgICAgICAgICAgICAgICAgICB0aHVua3MoYSwgYiwgcGF0Y2gsIGluZGV4KTtcbiAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKGIgPT0gbnVsbCkge1xuXG4gICAgICAgICAgICAgICAgICAgIC8vIElmIGEgaXMgYSB3aWRnZXQgd2Ugd2lsbCBhZGQgYSByZW1vdmUgcGF0Y2ggZm9yIGl0XG4gICAgICAgICAgICAgICAgICAgIC8vIE90aGVyd2lzZSBhbnkgY2hpbGQgd2lkZ2V0cy9ob29rcyBtdXN0IGJlIGRlc3Ryb3llZC5cbiAgICAgICAgICAgICAgICAgICAgLy8gVGhpcyBwcmV2ZW50cyBhZGRpbmcgdHdvIHJlbW92ZSBwYXRjaGVzIGZvciBhIHdpZGdldC5cbiAgICAgICAgICAgICAgICAgICAgaWYgKCFpc1dpZGdldChhKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgY2xlYXJTdGF0ZShhLCBwYXRjaCwgaW5kZXgpO1xuICAgICAgICAgICAgICAgICAgICAgICAgYXBwbHkgPSBwYXRjaFtpbmRleF07XG4gICAgICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgICAgICBhcHBseSA9IGFwcGVuZFBhdGNoKGFwcGx5LCBuZXcgVlBhdGNoKFZQYXRjaC5SRU1PVkUsIGEsIGIpKTtcbiAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKGlzVk5vZGUoYikpIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKGlzVk5vZGUoYSkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChhLnRhZ05hbWUgPT09IGIudGFnTmFtZSAmJiBhLm5hbWVzcGFjZSA9PT0gYi5uYW1lc3BhY2UgJiYgYS5rZXkgPT09IGIua2V5KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdmFyIHByb3BzUGF0Y2ggPSBkaWZmUHJvcHMoYS5wcm9wZXJ0aWVzLCBiLnByb3BlcnRpZXMpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChwcm9wc1BhdGNoKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGFwcGx5ID0gYXBwZW5kUGF0Y2goYXBwbHksIG5ldyBWUGF0Y2goVlBhdGNoLlBST1BTLCBhLCBwcm9wc1BhdGNoKSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGFwcGx5ID0gZGlmZkNoaWxkcmVuKGEsIGIsIHBhdGNoLCBhcHBseSwgaW5kZXgpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBhcHBseSA9IGFwcGVuZFBhdGNoKGFwcGx5LCBuZXcgVlBhdGNoKFZQYXRjaC5WTk9ERSwgYSwgYikpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGFwcGx5Q2xlYXIgPSB0cnVlO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgYXBwbHkgPSBhcHBlbmRQYXRjaChhcHBseSwgbmV3IFZQYXRjaChWUGF0Y2guVk5PREUsIGEsIGIpKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGFwcGx5Q2xlYXIgPSB0cnVlO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfSBlbHNlIGlmIChpc1ZUZXh0KGIpKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmICghaXNWVGV4dChhKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgYXBwbHkgPSBhcHBlbmRQYXRjaChhcHBseSwgbmV3IFZQYXRjaChWUGF0Y2guVlRFWFQsIGEsIGIpKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGFwcGx5Q2xlYXIgPSB0cnVlO1xuICAgICAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKGEudGV4dCAhPT0gYi50ZXh0KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBhcHBseSA9IGFwcGVuZFBhdGNoKGFwcGx5LCBuZXcgVlBhdGNoKFZQYXRjaC5WVEVYVCwgYSwgYikpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfSBlbHNlIGlmIChpc1dpZGdldChiKSkge1xuICAgICAgICAgICAgICAgICAgICBpZiAoIWlzV2lkZ2V0KGEpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBhcHBseUNsZWFyID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgIGFwcGx5ID0gYXBwZW5kUGF0Y2goYXBwbHksIG5ldyBWUGF0Y2goVlBhdGNoLldJREdFVCwgYSwgYikpO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIGlmIChhcHBseSkge1xuICAgICAgICAgICAgICAgICAgICBwYXRjaFtpbmRleF0gPSBhcHBseTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICBpZiAoYXBwbHlDbGVhcikge1xuICAgICAgICAgICAgICAgICAgICBjbGVhclN0YXRlKGEsIHBhdGNoLCBpbmRleCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBmdW5jdGlvbiBkaWZmQ2hpbGRyZW4oYSwgYiwgcGF0Y2gsIGFwcGx5LCBpbmRleCkge1xuICAgICAgICAgICAgICAgIHZhciBhQ2hpbGRyZW4gPSBhLmNoaWxkcmVuO1xuICAgICAgICAgICAgICAgIHZhciBvcmRlcmVkU2V0ID0gcmVvcmRlcihhQ2hpbGRyZW4sIGIuY2hpbGRyZW4pO1xuICAgICAgICAgICAgICAgIHZhciBiQ2hpbGRyZW4gPSBvcmRlcmVkU2V0LmNoaWxkcmVuO1xuXG4gICAgICAgICAgICAgICAgdmFyIGFMZW4gPSBhQ2hpbGRyZW4ubGVuZ3RoO1xuICAgICAgICAgICAgICAgIHZhciBiTGVuID0gYkNoaWxkcmVuLmxlbmd0aDtcbiAgICAgICAgICAgICAgICB2YXIgbGVuID0gYUxlbiA+IGJMZW4gPyBhTGVuIDogYkxlbjtcblxuICAgICAgICAgICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgbGVuOyBpKyspIHtcbiAgICAgICAgICAgICAgICAgICAgdmFyIGxlZnROb2RlID0gYUNoaWxkcmVuW2ldO1xuICAgICAgICAgICAgICAgICAgICB2YXIgcmlnaHROb2RlID0gYkNoaWxkcmVuW2ldO1xuICAgICAgICAgICAgICAgICAgICBpbmRleCArPSAxO1xuXG4gICAgICAgICAgICAgICAgICAgIGlmICghbGVmdE5vZGUpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChyaWdodE5vZGUpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBFeGNlc3Mgbm9kZXMgaW4gYiBuZWVkIHRvIGJlIGFkZGVkXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgYXBwbHkgPSBhcHBlbmRQYXRjaChhcHBseSwgbmV3IFZQYXRjaChWUGF0Y2guSU5TRVJULCBudWxsLCByaWdodE5vZGUpKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHdhbGsobGVmdE5vZGUsIHJpZ2h0Tm9kZSwgcGF0Y2gsIGluZGV4KTtcbiAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgIGlmIChpc1ZOb2RlKGxlZnROb2RlKSAmJiBsZWZ0Tm9kZS5jb3VudCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgaW5kZXggKz0gbGVmdE5vZGUuY291bnQ7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICBpZiAob3JkZXJlZFNldC5tb3Zlcykge1xuICAgICAgICAgICAgICAgICAgICAvLyBSZW9yZGVyIG5vZGVzIGxhc3RcbiAgICAgICAgICAgICAgICAgICAgYXBwbHkgPSBhcHBlbmRQYXRjaChhcHBseSwgbmV3IFZQYXRjaChWUGF0Y2guT1JERVIsIGEsIG9yZGVyZWRTZXQubW92ZXMpKTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICByZXR1cm4gYXBwbHk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIGNsZWFyU3RhdGUodk5vZGUsIHBhdGNoLCBpbmRleCkge1xuICAgICAgICAgICAgICAgIC8vIFRPRE86IE1ha2UgdGhpcyBhIHNpbmdsZSB3YWxrLCBub3QgdHdvXG4gICAgICAgICAgICAgICAgdW5ob29rKHZOb2RlLCBwYXRjaCwgaW5kZXgpO1xuICAgICAgICAgICAgICAgIGRlc3Ryb3lXaWRnZXRzKHZOb2RlLCBwYXRjaCwgaW5kZXgpO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAvLyBQYXRjaCByZWNvcmRzIGZvciBhbGwgZGVzdHJveWVkIHdpZGdldHMgbXVzdCBiZSBhZGRlZCBiZWNhdXNlIHdlIG5lZWRcbiAgICAgICAgICAgIC8vIGEgRE9NIG5vZGUgcmVmZXJlbmNlIGZvciB0aGUgZGVzdHJveSBmdW5jdGlvblxuICAgICAgICAgICAgZnVuY3Rpb24gZGVzdHJveVdpZGdldHModk5vZGUsIHBhdGNoLCBpbmRleCkge1xuICAgICAgICAgICAgICAgIGlmIChpc1dpZGdldCh2Tm9kZSkpIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKHR5cGVvZiB2Tm9kZS5kZXN0cm95ID09PSBcImZ1bmN0aW9uXCIpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHBhdGNoW2luZGV4XSA9IGFwcGVuZFBhdGNoKHBhdGNoW2luZGV4XSwgbmV3IFZQYXRjaChWUGF0Y2guUkVNT1ZFLCB2Tm9kZSwgbnVsbCkpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfSBlbHNlIGlmIChpc1ZOb2RlKHZOb2RlKSAmJiAodk5vZGUuaGFzV2lkZ2V0cyB8fCB2Tm9kZS5oYXNUaHVua3MpKSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciBjaGlsZHJlbiA9IHZOb2RlLmNoaWxkcmVuO1xuICAgICAgICAgICAgICAgICAgICB2YXIgbGVuID0gY2hpbGRyZW4ubGVuZ3RoO1xuICAgICAgICAgICAgICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IGxlbjsgaSsrKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICB2YXIgY2hpbGQgPSBjaGlsZHJlbltpXTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGluZGV4ICs9IDE7XG5cbiAgICAgICAgICAgICAgICAgICAgICAgIGRlc3Ryb3lXaWRnZXRzKGNoaWxkLCBwYXRjaCwgaW5kZXgpO1xuXG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoaXNWTm9kZShjaGlsZCkgJiYgY2hpbGQuY291bnQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpbmRleCArPSBjaGlsZC5jb3VudDtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoaXNUaHVuayh2Tm9kZSkpIHtcbiAgICAgICAgICAgICAgICAgICAgdGh1bmtzKHZOb2RlLCBudWxsLCBwYXRjaCwgaW5kZXgpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgLy8gQ3JlYXRlIGEgc3ViLXBhdGNoIGZvciB0aHVua3NcbiAgICAgICAgICAgIGZ1bmN0aW9uIHRodW5rcyhhLCBiLCBwYXRjaCwgaW5kZXgpIHtcbiAgICAgICAgICAgICAgICB2YXIgbm9kZXMgPSBoYW5kbGVUaHVuayhhLCBiKTtcbiAgICAgICAgICAgICAgICB2YXIgdGh1bmtQYXRjaCA9IGRpZmYobm9kZXMuYSwgbm9kZXMuYik7XG4gICAgICAgICAgICAgICAgaWYgKGhhc1BhdGNoZXModGh1bmtQYXRjaCkpIHtcbiAgICAgICAgICAgICAgICAgICAgcGF0Y2hbaW5kZXhdID0gbmV3IFZQYXRjaChWUGF0Y2guVEhVTkssIG51bGwsIHRodW5rUGF0Y2gpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZnVuY3Rpb24gaGFzUGF0Y2hlcyhwYXRjaCkge1xuICAgICAgICAgICAgICAgIGZvciAodmFyIGluZGV4IGluIHBhdGNoKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmIChpbmRleCAhPT0gXCJhXCIpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAvLyBFeGVjdXRlIGhvb2tzIHdoZW4gdHdvIG5vZGVzIGFyZSBpZGVudGljYWxcbiAgICAgICAgICAgIGZ1bmN0aW9uIHVuaG9vayh2Tm9kZSwgcGF0Y2gsIGluZGV4KSB7XG4gICAgICAgICAgICAgICAgaWYgKGlzVk5vZGUodk5vZGUpKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmICh2Tm9kZS5ob29rcykge1xuICAgICAgICAgICAgICAgICAgICAgICAgcGF0Y2hbaW5kZXhdID0gYXBwZW5kUGF0Y2gocGF0Y2hbaW5kZXhdLCBuZXcgVlBhdGNoKFZQYXRjaC5QUk9QUywgdk5vZGUsIHVuZGVmaW5lZEtleXModk5vZGUuaG9va3MpKSk7XG4gICAgICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgICAgICBpZiAodk5vZGUuZGVzY2VuZGFudEhvb2tzIHx8IHZOb2RlLmhhc1RodW5rcykge1xuICAgICAgICAgICAgICAgICAgICAgICAgdmFyIGNoaWxkcmVuID0gdk5vZGUuY2hpbGRyZW47XG4gICAgICAgICAgICAgICAgICAgICAgICB2YXIgbGVuID0gY2hpbGRyZW4ubGVuZ3RoO1xuICAgICAgICAgICAgICAgICAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCBsZW47IGkrKykge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZhciBjaGlsZCA9IGNoaWxkcmVuW2ldO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGluZGV4ICs9IDE7XG5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB1bmhvb2soY2hpbGQsIHBhdGNoLCBpbmRleCk7XG5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoaXNWTm9kZShjaGlsZCkgJiYgY2hpbGQuY291bnQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaW5kZXggKz0gY2hpbGQuY291bnQ7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfSBlbHNlIGlmIChpc1RodW5rKHZOb2RlKSkge1xuICAgICAgICAgICAgICAgICAgICB0aHVua3Modk5vZGUsIG51bGwsIHBhdGNoLCBpbmRleCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBmdW5jdGlvbiB1bmRlZmluZWRLZXlzKG9iaikge1xuICAgICAgICAgICAgICAgIHZhciByZXN1bHQgPSB7fTtcblxuICAgICAgICAgICAgICAgIGZvciAodmFyIGtleSBpbiBvYmopIHtcbiAgICAgICAgICAgICAgICAgICAgcmVzdWx0W2tleV0gPSB1bmRlZmluZWQ7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgcmV0dXJuIHJlc3VsdDtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgLy8gTGlzdCBkaWZmLCBuYWl2ZSBsZWZ0IHRvIHJpZ2h0IHJlb3JkZXJpbmdcbiAgICAgICAgICAgIGZ1bmN0aW9uIHJlb3JkZXIoYUNoaWxkcmVuLCBiQ2hpbGRyZW4pIHtcbiAgICAgICAgICAgICAgICAvLyBPKE0pIHRpbWUsIE8oTSkgbWVtb3J5XG4gICAgICAgICAgICAgICAgdmFyIGJDaGlsZEluZGV4ID0ga2V5SW5kZXgoYkNoaWxkcmVuKTtcbiAgICAgICAgICAgICAgICB2YXIgYktleXMgPSBiQ2hpbGRJbmRleC5rZXlzO1xuICAgICAgICAgICAgICAgIHZhciBiRnJlZSA9IGJDaGlsZEluZGV4LmZyZWU7XG5cbiAgICAgICAgICAgICAgICBpZiAoYkZyZWUubGVuZ3RoID09PSBiQ2hpbGRyZW4ubGVuZ3RoKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiB7XG4gICAgICAgICAgICAgICAgICAgICAgICBjaGlsZHJlbjogYkNoaWxkcmVuLFxuICAgICAgICAgICAgICAgICAgICAgICAgbW92ZXM6IG51bGxcbiAgICAgICAgICAgICAgICAgICAgfTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAvLyBPKE4pIHRpbWUsIE8oTikgbWVtb3J5XG4gICAgICAgICAgICAgICAgdmFyIGFDaGlsZEluZGV4ID0ga2V5SW5kZXgoYUNoaWxkcmVuKTtcbiAgICAgICAgICAgICAgICB2YXIgYUtleXMgPSBhQ2hpbGRJbmRleC5rZXlzO1xuICAgICAgICAgICAgICAgIHZhciBhRnJlZSA9IGFDaGlsZEluZGV4LmZyZWU7XG5cbiAgICAgICAgICAgICAgICBpZiAoYUZyZWUubGVuZ3RoID09PSBhQ2hpbGRyZW4ubGVuZ3RoKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiB7XG4gICAgICAgICAgICAgICAgICAgICAgICBjaGlsZHJlbjogYkNoaWxkcmVuLFxuICAgICAgICAgICAgICAgICAgICAgICAgbW92ZXM6IG51bGxcbiAgICAgICAgICAgICAgICAgICAgfTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAvLyBPKE1BWChOLCBNKSkgbWVtb3J5XG4gICAgICAgICAgICAgICAgdmFyIG5ld0NoaWxkcmVuID0gW107XG5cbiAgICAgICAgICAgICAgICB2YXIgZnJlZUluZGV4ID0gMDtcbiAgICAgICAgICAgICAgICB2YXIgZnJlZUNvdW50ID0gYkZyZWUubGVuZ3RoO1xuICAgICAgICAgICAgICAgIHZhciBkZWxldGVkSXRlbXMgPSAwO1xuXG4gICAgICAgICAgICAgICAgLy8gSXRlcmF0ZSB0aHJvdWdoIGEgYW5kIG1hdGNoIGEgbm9kZSBpbiBiXG4gICAgICAgICAgICAgICAgLy8gTyhOKSB0aW1lLFxuICAgICAgICAgICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgYUNoaWxkcmVuLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciBhSXRlbSA9IGFDaGlsZHJlbltpXTtcbiAgICAgICAgICAgICAgICAgICAgdmFyIGl0ZW1JbmRleDtcblxuICAgICAgICAgICAgICAgICAgICBpZiAoYUl0ZW0ua2V5KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoYktleXMuaGFzT3duUHJvcGVydHkoYUl0ZW0ua2V5KSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIE1hdGNoIHVwIHRoZSBvbGQga2V5c1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGl0ZW1JbmRleCA9IGJLZXlzW2FJdGVtLmtleV07XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgbmV3Q2hpbGRyZW4ucHVzaChiQ2hpbGRyZW5baXRlbUluZGV4XSk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIFJlbW92ZSBvbGQga2V5ZWQgaXRlbXNcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpdGVtSW5kZXggPSBpIC0gZGVsZXRlZEl0ZW1zKys7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgbmV3Q2hpbGRyZW4ucHVzaChudWxsKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIE1hdGNoIHRoZSBpdGVtIGluIGEgd2l0aCB0aGUgbmV4dCBmcmVlIGl0ZW0gaW4gYlxuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGZyZWVJbmRleCA8IGZyZWVDb3VudCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGl0ZW1JbmRleCA9IGJGcmVlW2ZyZWVJbmRleCsrXTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBuZXdDaGlsZHJlbi5wdXNoKGJDaGlsZHJlbltpdGVtSW5kZXhdKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gVGhlcmUgYXJlIG5vIGZyZWUgaXRlbXMgaW4gYiB0byBtYXRjaCB3aXRoXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gdGhlIGZyZWUgaXRlbXMgaW4gYSwgc28gdGhlIGV4dHJhIGZyZWUgbm9kZXNcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBhcmUgZGVsZXRlZC5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpdGVtSW5kZXggPSBpIC0gZGVsZXRlZEl0ZW1zKys7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgbmV3Q2hpbGRyZW4ucHVzaChudWxsKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHZhciBsYXN0RnJlZUluZGV4ID0gZnJlZUluZGV4ID49IGJGcmVlLmxlbmd0aCA/IGJDaGlsZHJlbi5sZW5ndGggOiBiRnJlZVtmcmVlSW5kZXhdO1xuXG4gICAgICAgICAgICAgICAgLy8gSXRlcmF0ZSB0aHJvdWdoIGIgYW5kIGFwcGVuZCBhbnkgbmV3IGtleXNcbiAgICAgICAgICAgICAgICAvLyBPKE0pIHRpbWVcbiAgICAgICAgICAgICAgICBmb3IgKHZhciBqID0gMDsgaiA8IGJDaGlsZHJlbi5sZW5ndGg7IGorKykge1xuICAgICAgICAgICAgICAgICAgICB2YXIgbmV3SXRlbSA9IGJDaGlsZHJlbltqXTtcblxuICAgICAgICAgICAgICAgICAgICBpZiAobmV3SXRlbS5rZXkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmICghYUtleXMuaGFzT3duUHJvcGVydHkobmV3SXRlbS5rZXkpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gQWRkIGFueSBuZXcga2V5ZWQgaXRlbXNcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBXZSBhcmUgYWRkaW5nIG5ldyBpdGVtcyB0byB0aGUgZW5kIGFuZCB0aGVuIHNvcnRpbmcgdGhlbVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIGluIHBsYWNlLiBJbiBmdXR1cmUgd2Ugc2hvdWxkIGluc2VydCBuZXcgaXRlbXMgaW4gcGxhY2UuXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgbmV3Q2hpbGRyZW4ucHVzaChuZXdJdGVtKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIGlmIChqID49IGxhc3RGcmVlSW5kZXgpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIEFkZCBhbnkgbGVmdG92ZXIgbm9uLWtleWVkIGl0ZW1zXG4gICAgICAgICAgICAgICAgICAgICAgICBuZXdDaGlsZHJlbi5wdXNoKG5ld0l0ZW0pO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgdmFyIHNpbXVsYXRlID0gbmV3Q2hpbGRyZW4uc2xpY2UoKTtcbiAgICAgICAgICAgICAgICB2YXIgc2ltdWxhdGVJbmRleCA9IDA7XG4gICAgICAgICAgICAgICAgdmFyIHJlbW92ZXMgPSBbXTtcbiAgICAgICAgICAgICAgICB2YXIgaW5zZXJ0cyA9IFtdO1xuICAgICAgICAgICAgICAgIHZhciBzaW11bGF0ZUl0ZW07XG5cbiAgICAgICAgICAgICAgICBmb3IgKHZhciBrID0gMDsgayA8IGJDaGlsZHJlbi5sZW5ndGg7KSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciB3YW50ZWRJdGVtID0gYkNoaWxkcmVuW2tdO1xuICAgICAgICAgICAgICAgICAgICBzaW11bGF0ZUl0ZW0gPSBzaW11bGF0ZVtzaW11bGF0ZUluZGV4XTtcblxuICAgICAgICAgICAgICAgICAgICAvLyByZW1vdmUgaXRlbXNcbiAgICAgICAgICAgICAgICAgICAgd2hpbGUgKHNpbXVsYXRlSXRlbSA9PT0gbnVsbCAmJiBzaW11bGF0ZS5sZW5ndGgpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJlbW92ZXMucHVzaChyZW1vdmUoc2ltdWxhdGUsIHNpbXVsYXRlSW5kZXgsIG51bGwpKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIHNpbXVsYXRlSXRlbSA9IHNpbXVsYXRlW3NpbXVsYXRlSW5kZXhdO1xuICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgaWYgKCFzaW11bGF0ZUl0ZW0gfHwgc2ltdWxhdGVJdGVtLmtleSAhPT0gd2FudGVkSXRlbS5rZXkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIGlmIHdlIG5lZWQgYSBrZXkgaW4gdGhpcyBwb3NpdGlvbi4uLlxuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHdhbnRlZEl0ZW0ua2V5KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHNpbXVsYXRlSXRlbSAmJiBzaW11bGF0ZUl0ZW0ua2V5KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIGlmIGFuIGluc2VydCBkb2Vzbid0IHB1dCB0aGlzIGtleSBpbiBwbGFjZSwgaXQgbmVlZHMgdG8gbW92ZVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoYktleXNbc2ltdWxhdGVJdGVtLmtleV0gIT09IGsgKyAxKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICByZW1vdmVzLnB1c2gocmVtb3ZlKHNpbXVsYXRlLCBzaW11bGF0ZUluZGV4LCBzaW11bGF0ZUl0ZW0ua2V5KSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzaW11bGF0ZUl0ZW0gPSBzaW11bGF0ZVtzaW11bGF0ZUluZGV4XTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIGlmIHRoZSByZW1vdmUgZGlkbid0IHB1dCB0aGUgd2FudGVkIGl0ZW0gaW4gcGxhY2UsIHdlIG5lZWQgdG8gaW5zZXJ0IGl0XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoIXNpbXVsYXRlSXRlbSB8fCBzaW11bGF0ZUl0ZW0ua2V5ICE9PSB3YW50ZWRJdGVtLmtleSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGluc2VydHMucHVzaCh7IGtleTogd2FudGVkSXRlbS5rZXksIHRvOiBrIH0pO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gaXRlbXMgYXJlIG1hdGNoaW5nLCBzbyBza2lwIGFoZWFkXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzaW11bGF0ZUluZGV4Kys7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpbnNlcnRzLnB1c2goeyBrZXk6IHdhbnRlZEl0ZW0ua2V5LCB0bzogayB9KTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGluc2VydHMucHVzaCh7IGtleTogd2FudGVkSXRlbS5rZXksIHRvOiBrIH0pO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBrKys7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAvLyBhIGtleSBpbiBzaW11bGF0ZSBoYXMgbm8gbWF0Y2hpbmcgd2FudGVkIGtleSwgcmVtb3ZlIGl0XG4gICAgICAgICAgICAgICAgICAgICAgICBlbHNlIGlmIChzaW11bGF0ZUl0ZW0gJiYgc2ltdWxhdGVJdGVtLmtleSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlbW92ZXMucHVzaChyZW1vdmUoc2ltdWxhdGUsIHNpbXVsYXRlSW5kZXgsIHNpbXVsYXRlSXRlbS5rZXkpKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHNpbXVsYXRlSW5kZXgrKztcbiAgICAgICAgICAgICAgICAgICAgICAgIGsrKztcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIC8vIHJlbW92ZSBhbGwgdGhlIHJlbWFpbmluZyBub2RlcyBmcm9tIHNpbXVsYXRlXG4gICAgICAgICAgICAgICAgd2hpbGUgKHNpbXVsYXRlSW5kZXggPCBzaW11bGF0ZS5sZW5ndGgpIHtcbiAgICAgICAgICAgICAgICAgICAgc2ltdWxhdGVJdGVtID0gc2ltdWxhdGVbc2ltdWxhdGVJbmRleF07XG4gICAgICAgICAgICAgICAgICAgIHJlbW92ZXMucHVzaChyZW1vdmUoc2ltdWxhdGUsIHNpbXVsYXRlSW5kZXgsIHNpbXVsYXRlSXRlbSAmJiBzaW11bGF0ZUl0ZW0ua2V5KSk7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgLy8gSWYgdGhlIG9ubHkgbW92ZXMgd2UgaGF2ZSBhcmUgZGVsZXRlcyB0aGVuIHdlIGNhbiBqdXN0XG4gICAgICAgICAgICAgICAgLy8gbGV0IHRoZSBkZWxldGUgcGF0Y2ggcmVtb3ZlIHRoZXNlIGl0ZW1zLlxuICAgICAgICAgICAgICAgIGlmIChyZW1vdmVzLmxlbmd0aCA9PT0gZGVsZXRlZEl0ZW1zICYmICFpbnNlcnRzLmxlbmd0aCkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgICAgICAgICAgICAgY2hpbGRyZW46IG5ld0NoaWxkcmVuLFxuICAgICAgICAgICAgICAgICAgICAgICAgbW92ZXM6IG51bGxcbiAgICAgICAgICAgICAgICAgICAgfTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgICAgICAgICBjaGlsZHJlbjogbmV3Q2hpbGRyZW4sXG4gICAgICAgICAgICAgICAgICAgIG1vdmVzOiB7XG4gICAgICAgICAgICAgICAgICAgICAgICByZW1vdmVzOiByZW1vdmVzLFxuICAgICAgICAgICAgICAgICAgICAgICAgaW5zZXJ0czogaW5zZXJ0c1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZnVuY3Rpb24gcmVtb3ZlKGFyciwgaW5kZXgsIGtleSkge1xuICAgICAgICAgICAgICAgIGFyci5zcGxpY2UoaW5kZXgsIDEpO1xuXG4gICAgICAgICAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgICAgICAgICAgZnJvbTogaW5kZXgsXG4gICAgICAgICAgICAgICAgICAgIGtleToga2V5XG4gICAgICAgICAgICAgICAgfTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZnVuY3Rpb24ga2V5SW5kZXgoY2hpbGRyZW4pIHtcbiAgICAgICAgICAgICAgICB2YXIga2V5cyA9IHt9O1xuICAgICAgICAgICAgICAgIHZhciBmcmVlID0gW107XG4gICAgICAgICAgICAgICAgdmFyIGxlbmd0aCA9IGNoaWxkcmVuLmxlbmd0aDtcblxuICAgICAgICAgICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgbGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgICAgICAgICAgdmFyIGNoaWxkID0gY2hpbGRyZW5baV07XG5cbiAgICAgICAgICAgICAgICAgICAgaWYgKGNoaWxkLmtleSkge1xuICAgICAgICAgICAgICAgICAgICAgICAga2V5c1tjaGlsZC5rZXldID0gaTtcbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGZyZWUucHVzaChpKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHJldHVybiB7XG4gICAgICAgICAgICAgICAgICAgIGtleXM6IGtleXMsIC8vIEEgaGFzaCBvZiBrZXkgbmFtZSB0byBpbmRleFxuICAgICAgICAgICAgICAgICAgICBmcmVlOiBmcmVlIC8vIEFuIGFycmF5IG9mIHVua2V5ZWQgaXRlbSBpbmRpY2VzXG4gICAgICAgICAgICAgICAgfTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZnVuY3Rpb24gYXBwZW5kUGF0Y2goYXBwbHksIHBhdGNoKSB7XG4gICAgICAgICAgICAgICAgaWYgKGFwcGx5KSB7XG4gICAgICAgICAgICAgICAgICAgIGlmIChpc0FycmF5KGFwcGx5KSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgYXBwbHkucHVzaChwYXRjaCk7XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBhcHBseSA9IFthcHBseSwgcGF0Y2hdO1xuICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGFwcGx5O1xuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBwYXRjaDtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH0sIHsgXCIuLi92bm9kZS9oYW5kbGUtdGh1bmtcIjogMjQsIFwiLi4vdm5vZGUvaXMtdGh1bmtcIjogMjUsIFwiLi4vdm5vZGUvaXMtdm5vZGVcIjogMjcsIFwiLi4vdm5vZGUvaXMtdnRleHRcIjogMjgsIFwiLi4vdm5vZGUvaXMtd2lkZ2V0XCI6IDI5LCBcIi4uL3Zub2RlL3ZwYXRjaFwiOiAzMiwgXCIuL2RpZmYtcHJvcHNcIjogMzQsIFwieC1pcy1hcnJheVwiOiAxMiB9XSB9LCB7fSwgWzRdKSg0KTtcbn0pO1xuXG5jb25zdCBzdGFydCA9IGZ1bmN0aW9uIChkb21Sb290LCByZW5kZXJGbiwgaW5pdGlhbFN0YXRlLCBvcHRpb25zID0gW10pIHtcbiAgbGV0IHBpZCA9IHNlbGYucHJvY2Vzc2VzLnNwYXduKCk7XG5cbiAgaWYgKEtleXdvcmQuaGFzX2tleV9fcW1fXyhvcHRpb25zLCBLZXJuZWwuU3BlY2lhbEZvcm1zLmF0b20oJ25hbWUnKSkpIHtcbiAgICBwaWQgPSBzZWxmLnByb2Nlc3Nlcy5yZWdpc3RlcihLZXl3b3JkLmdldChvcHRpb25zLCBLZXJuZWwuU3BlY2lhbEZvcm1zLmF0b20oJ25hbWUnKSksIHBpZCk7XG4gIH1cblxuICBjb25zdCB0cmVlID0gcmVuZGVyRm4uYXBwbHkodGhpcywgaW5pdGlhbFN0YXRlKTtcbiAgY29uc3Qgcm9vdE5vZGUgPSBWaXJ0dWFsRE9NLmNyZWF0ZSh0cmVlKTtcblxuICBkb21Sb290LmFwcGVuZENoaWxkKHJvb3ROb2RlKTtcblxuICBzZWxmLnByb2Nlc3Nlcy5wdXQocGlkLCAnc3RhdGUnLCBLZXJuZWwuU3BlY2lhbEZvcm1zLnR1cGxlKHJvb3ROb2RlLCB0cmVlLCByZW5kZXJGbikpO1xuICByZXR1cm4gS2VybmVsLlNwZWNpYWxGb3Jtcy50dXBsZShLZXJuZWwuU3BlY2lhbEZvcm1zLmF0b20oJ29rJyksIHBpZCk7XG59O1xuXG5jb25zdCBzdG9wID0gZnVuY3Rpb24gKGFnZW50LCB0aW1lb3V0ID0gNTAwMCkge1xuICBzZWxmLnByb2Nlc3Nlcy5leGl0KGFnZW50KTtcbiAgcmV0dXJuIEtlcm5lbC5TcGVjaWFsRm9ybXMuYXRvbSgnb2snKTtcbn07XG5cbmNvbnN0IHJlbmRlciA9IGZ1bmN0aW9uIChhZ2VudCwgc3RhdGUpIHtcblxuICBjb25zdCBjdXJyZW50X3N0YXRlID0gc2VsZi5wcm9jZXNzZXMuZ2V0KGFnZW50LCAnc3RhdGUnKTtcblxuICBsZXQgcm9vdE5vZGUgPSBLZXJuZWwuZWxlbShjdXJyZW50X3N0YXRlLCAwKTtcbiAgbGV0IHRyZWUgPSBLZXJuZWwuZWxlbShjdXJyZW50X3N0YXRlLCAxKTtcbiAgbGV0IHJlbmRlckZuID0gS2VybmVsLmVsZW0oY3VycmVudF9zdGF0ZSwgMik7XG5cbiAgbGV0IG5ld1RyZWUgPSByZW5kZXJGbi5hcHBseSh0aGlzLCBzdGF0ZSk7XG5cbiAgbGV0IHBhdGNoZXMgPSBWaXJ0dWFsRE9NLmRpZmYodHJlZSwgbmV3VHJlZSk7XG4gIHJvb3ROb2RlID0gVmlydHVhbERPTS5wYXRjaChyb290Tm9kZSwgcGF0Y2hlcyk7XG5cbiAgc2VsZi5wcm9jZXNzZXMucHV0KGFnZW50LCAnc3RhdGUnLCBLZXJuZWwuU3BlY2lhbEZvcm1zLnR1cGxlKHJvb3ROb2RlLCBuZXdUcmVlLCByZW5kZXJGbikpO1xuXG4gIHJldHVybiBLZXJuZWwuU3BlY2lhbEZvcm1zLmF0b20oJ29rJyk7XG59O1xuXG52YXIgdmlldyA9IHtcbiAgc3RhcnQsXG4gIHN0b3AsXG4gIHJlbmRlclxufTtcblxuc2VsZi5wcm9jZXNzZXMgPSBzZWxmLnByb2Nlc3NlcyB8fCBuZXcgUHJvY2Vzc1N5c3RlbSgpO1xuXG5jb25zdCBDb3JlID0gQztcblxuZXhwb3J0IHsgQ29yZSwgS2VybmVsLCBBdG9tLCBFbnVtLCBJbnRlZ2VyLCBMaXN0LCBSYW5nZSwgVHVwbGUsIEFnZW50LCBLZXl3b3JkLCBiYXNlIGFzIEJhc2UsIFN0cmluZyQxIGFzIFN0cmluZywgYml0d2lzZSBhcyBCaXR3aXNlLCBFbnVtZXJhYmxlLCBDb2xsZWN0YWJsZSwgSW5zcGVjdCwgbWFwIGFzIE1hcCwgc2V0IGFzIFNldCwgTWFwU2V0LCBWaXJ0dWFsRE9NLCB2aWV3IGFzIFZpZXcgfTsiXSwiZmlsZSI6ImVsaXhpci5qcyIsInNvdXJjZVJvb3QiOiIvc291cmNlLyJ9 \ No newline at end of file diff --git a/src/javascript/elixir.js b/src/javascript/elixir.js index a81e366a..7c06cdff 100644 --- a/src/javascript/elixir.js +++ b/src/javascript/elixir.js @@ -1,9 +1,10 @@ -import * as Core from "./lib/core"; +import * as C from './lib/core'; -self.processes = self.processes || new Core.ProcessSystem(); +self.processes = self.processes || new C.ProcessSystem(); -export Core; -export { default as Patterns } from './lib/patterns/patterns'; + + +export const Core = C; export { default as Kernel } from './lib/kernel'; export { default as Atom } from './lib/atom'; export { default as Enum } from './lib/enum'; diff --git a/src/javascript/lib/core/functions.js b/src/javascript/lib/core/functions.js index 261c4bfe..ca31c75b 100644 --- a/src/javascript/lib/core/functions.js +++ b/src/javascript/lib/core/functions.js @@ -19,6 +19,6 @@ function call_property(item, property){ throw new Error(`Property ${property} not found in ${item}`); } -export default { +export { call_property }; diff --git a/src/javascript/lib/core/patterns.js b/src/javascript/lib/core/patterns.js index 2978dbc2..8d455b04 100644 --- a/src/javascript/lib/core/patterns.js +++ b/src/javascript/lib/core/patterns.js @@ -4,7 +4,7 @@ import { defmatch, match, MatchError, match_no_throw, patternMap, Case, make_cas import { variable, wildcard, startsWith, capture, headTail, type, bound } from "./patterns/types"; -export default { +export { defmatch, match, MatchError, match_no_throw, variable, wildcard, startsWith, capture, headTail, type, bound, Case, make_case diff --git a/src/javascript/lib/core/primitives.js b/src/javascript/lib/core/primitives.js index 6781e57a..b3d1f74f 100644 --- a/src/javascript/lib/core/primitives.js +++ b/src/javascript/lib/core/primitives.js @@ -45,6 +45,7 @@ class PID { } class IntegerType {} + class FloatType {} -export default { PID, Tuple, IntegerType, FloatType }; +export { PID, Tuple, IntegerType, FloatType }; diff --git a/src/javascript/lib/core/process_system.js b/src/javascript/lib/core/process_system.js index cf006455..582e0289 100644 --- a/src/javascript/lib/core/process_system.js +++ b/src/javascript/lib/core/process_system.js @@ -4,7 +4,7 @@ import Mailbox from "./mailbox"; import Process from "./process"; import States from "./states"; -import Core from "./primitives"; +import * as Primitives from "./primitives"; class ProcessSystem { @@ -48,7 +48,7 @@ class ProcessSystem { } add_proc(linked){ - let newpid = new Core.PID(); + let newpid = new Primitives.PID(); let mailbox = new Mailbox(); let newproc = new Process(newpid, mailbox); @@ -107,7 +107,7 @@ class ProcessSystem { } pidof(id){ - if (id instanceof Core.PID) { + if (id instanceof Primitives.PID) { return this.pids.has(id) ? id : null; } else if (id instanceof Process) { return id.pid; diff --git a/src/javascript/lib/list/chars.js b/src/javascript/lib/list/chars.js index 842e384b..a7463cdb 100644 --- a/src/javascript/lib/list/chars.js +++ b/src/javascript/lib/list/chars.js @@ -3,7 +3,6 @@ import Atom from "../atom"; import Integer from "../integer"; import String from "../string"; import * as Core from '../core'; -import { IntegerType, FloatType } from "../protocol"; let Chars = Kernel.defprotocol({ to_char_list: function(thing){} @@ -25,7 +24,7 @@ Kernel.defimpl(Chars, Symbol, { } }); -Kernel.defimpl(Chars, IntegerType, { +Kernel.defimpl(Chars, Core.IntegerType, { to_char_list: function(thing){ return Integer.to_char_list(thing); } diff --git a/src/javascript/lib/string/chars.js b/src/javascript/lib/string/chars.js index f68f6907..19b6f2f3 100644 --- a/src/javascript/lib/string/chars.js +++ b/src/javascript/lib/string/chars.js @@ -4,7 +4,6 @@ import Integer from "../integer"; import List from "../list"; import * as Core from '../core'; import Tuple from "../tuple"; -import { IntegerType, FloatType } from "../protocol"; let Chars = Kernel.defprotocol({ to_string: function(thing){} @@ -30,13 +29,13 @@ Kernel.defimpl(Chars, Symbol, { } }); -Kernel.defimpl(Chars, IntegerType, { +Kernel.defimpl(Chars, Core.IntegerType, { to_string: function(thing){ return Integer.to_string(thing); } }); -Kernel.defimpl(Chars, FloatType, { +Kernel.defimpl(Chars, Core.FloatType, { to_string: function(thing){ return thing.toString; } From 167580e467ebeb5abd3e3d6a30c28a6468a5fc4f Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Fri, 4 Dec 2015 15:39:57 -0600 Subject: [PATCH 071/860] Fixed exports this time for real --- priv/elixir.js | 28 +++++++++++++++++----------- src/javascript/lib/core.js | 2 +- src/javascript/lib/core/patterns.js | 2 +- 3 files changed, 19 insertions(+), 13 deletions(-) diff --git a/priv/elixir.js b/priv/elixir.js index 850df9c3..a248f8a1 100644 --- a/priv/elixir.js +++ b/priv/elixir.js @@ -530,6 +530,12 @@ function match_no_throw(pattern, expr, guard = () => true) { } } +var Patterns = { + defmatch, match, MatchError, match_no_throw, + variable, wildcard, startsWith, + capture, headTail, type, bound, Case, make_case +}; + class BitString { constructor(...args) { this.raw_value = function () { @@ -1028,7 +1034,7 @@ var C = Object.freeze({ Tuple: Tuple$1, PID: PID, BitString: BitString, - Patterns: null$1, + Patterns: Patterns, IntegerType: IntegerType, FloatType: FloatType, call_property: call_property @@ -1261,11 +1267,11 @@ let SpecialForms = { }, bound: function (_var) { - return bound(_var); + return Patterns.bound(_var); }, _case: function (condition, clauses) { - return defmatch(...clauses)(condition); + return Patterns.defmatch(...clauses)(condition); }, cond: function (clauses) { @@ -1279,7 +1285,7 @@ let SpecialForms = { }, fn: function (clauses) { - return defmatch(clauses); + return Patterns.defmatch(clauses); }, map: function (obj) { @@ -1297,7 +1303,7 @@ let SpecialForms = { if (collections.length === 1) { for (let elem of collection) { - let r = match_no_throw(pattern, elem); + let r = Patterns.match_no_throw(pattern, elem); let args = previousValues.concat(r); if (r && filter.apply(this, args)) { @@ -1310,7 +1316,7 @@ let SpecialForms = { let _into = []; for (let elem of collection) { - let r = match_no_throw(pattern, elem); + let r = Patterns.match_no_throw(pattern, elem); if (r) { _into = Enum.into(this._for(collections.slice(1), fun, filter, _into, previousValues.concat(r)), into); } @@ -1368,7 +1374,7 @@ let SpecialForms = { ex_result = rescue_function(e); return ex_result; } catch (ex) { - if (ex instanceof MatchError) { + if (ex instanceof Patterns.MatchError) { throw ex; } } @@ -1379,7 +1385,7 @@ let SpecialForms = { ex_result = catch_fun(e); return ex_result; } catch (ex) { - if (ex instanceof MatchError) { + if (ex instanceof Patterns.MatchError) { throw ex; } } @@ -1396,7 +1402,7 @@ let SpecialForms = { try { return else_function(result); } catch (ex) { - if (ex instanceof MatchError) { + if (ex instanceof Patterns.MatchError) { throw new Error('No Match Found in Else'); } @@ -1664,7 +1670,7 @@ function to_string(arg) { } function match__qmark__(pattern, expr, guard = () => true) { - return match_no_throw(pattern, expr, guard) != null; + return Patterns.match_no_throw(pattern, expr, guard) != null; } function defstruct(defaults) { @@ -4561,4 +4567,4 @@ self.processes = self.processes || new ProcessSystem(); const Core = C; export { Core, Kernel, Atom, Enum, Integer, List, Range, Tuple, Agent, Keyword, base as Base, String$1 as String, bitwise as Bitwise, Enumerable, Collectable, Inspect, map as Map, set as Set, MapSet, VirtualDOM, view as View }; -//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiIiwic291cmNlcyI6WyJlbGl4aXIuanMiXSwic291cmNlc0NvbnRlbnQiOlsiZnVuY3Rpb24gY2FsbF9wcm9wZXJ0eShpdGVtLCBwcm9wZXJ0eSkge1xuICBpZiAocHJvcGVydHkgaW4gaXRlbSkge1xuICAgIGl0ZW1bcHJvcGVydHldO1xuICAgIGlmIChpdGVtW3Byb3BlcnR5XSBpbnN0YW5jZW9mIEZ1bmN0aW9uKSB7XG4gICAgICByZXR1cm4gaXRlbVtwcm9wZXJ0eV0oKTtcbiAgICB9IGVsc2Uge1xuICAgICAgcmV0dXJuIGl0ZW1bcHJvcGVydHldO1xuICAgIH1cbiAgfSBlbHNlIGlmIChTeW1ib2wuZm9yKHByb3BlcnR5KSBpbiBpdGVtKSB7XG4gICAgbGV0IHByb3AgPSBTeW1ib2wuZm9yKHByb3BlcnR5KTtcbiAgICBpZiAoaXRlbVtwcm9wXSBpbnN0YW5jZW9mIEZ1bmN0aW9uKSB7XG4gICAgICByZXR1cm4gaXRlbVtwcm9wXSgpO1xuICAgIH0gZWxzZSB7XG4gICAgICByZXR1cm4gaXRlbVtwcm9wXTtcbiAgICB9XG4gIH1cblxuICB0aHJvdyBuZXcgRXJyb3IoYFByb3BlcnR5ICR7IHByb3BlcnR5IH0gbm90IGZvdW5kIGluICR7IGl0ZW0gfWApO1xufVxuXG5jbGFzcyBUdXBsZSQxIHtcblxuICBjb25zdHJ1Y3RvciguLi5hcmdzKSB7XG4gICAgdGhpcy52YWx1ZXMgPSBPYmplY3QuZnJlZXplKGFyZ3MpO1xuICB9XG5cbiAgZ2V0KGluZGV4KSB7XG4gICAgcmV0dXJuIHRoaXMudmFsdWVzW2luZGV4XTtcbiAgfVxuXG4gIGNvdW50KCkge1xuICAgIHJldHVybiB0aGlzLnZhbHVlcy5sZW5ndGg7XG4gIH1cblxuICBbU3ltYm9sLml0ZXJhdG9yXSgpIHtcbiAgICByZXR1cm4gdGhpcy52YWx1ZXNbU3ltYm9sLml0ZXJhdG9yXSgpO1xuICB9XG5cbiAgdG9TdHJpbmcoKSB7XG4gICAgdmFyIGksXG4gICAgICAgIHMgPSBcIlwiO1xuICAgIGZvciAoaSA9IDA7IGkgPCB0aGlzLnZhbHVlcy5sZW5ndGg7IGkrKykge1xuICAgICAgaWYgKHMgIT09IFwiXCIpIHtcbiAgICAgICAgcyArPSBcIiwgXCI7XG4gICAgICB9XG4gICAgICBzICs9IHRoaXMudmFsdWVzW2ldLnRvU3RyaW5nKCk7XG4gICAgfVxuXG4gICAgcmV0dXJuIFwie1wiICsgcyArIFwifVwiO1xuICB9XG5cbn1cblxubGV0IHByb2Nlc3NfY291bnRlciA9IC0xO1xuXG5jbGFzcyBQSUQge1xuICBjb25zdHJ1Y3RvcigpIHtcbiAgICBwcm9jZXNzX2NvdW50ZXIgPSBwcm9jZXNzX2NvdW50ZXIgKyAxO1xuICAgIHRoaXMuaWQgPSBwcm9jZXNzX2NvdW50ZXI7XG4gIH1cblxuICB0b1N0cmluZygpIHtcbiAgICByZXR1cm4gXCJQSUQjPDAuXCIgKyB0aGlzLmlkICsgXCIuMD5cIjtcbiAgfVxufVxuXG5jbGFzcyBJbnRlZ2VyVHlwZSB7fVxuXG5jbGFzcyBGbG9hdFR5cGUge31cblxuLyogQGZsb3cgKi9cblxuY2xhc3MgVmFyaWFibGUge1xuXG4gIGNvbnN0cnVjdG9yKG5hbWUgPSBudWxsKSB7XG4gICAgdGhpcy5uYW1lID0gbmFtZTtcbiAgfVxufVxuXG5jbGFzcyBXaWxkY2FyZCB7XG4gIGNvbnN0cnVjdG9yKCkge31cbn1cblxuY2xhc3MgU3RhcnRzV2l0aCB7XG5cbiAgY29uc3RydWN0b3IocHJlZml4KSB7XG4gICAgdGhpcy5wcmVmaXggPSBwcmVmaXg7XG4gIH1cbn1cblxuY2xhc3MgQ2FwdHVyZSB7XG5cbiAgY29uc3RydWN0b3IodmFsdWUpIHtcbiAgICB0aGlzLnZhbHVlID0gdmFsdWU7XG4gIH1cbn1cblxuY2xhc3MgSGVhZFRhaWwge1xuICBjb25zdHJ1Y3RvcigpIHt9XG59XG5cbmNsYXNzIFR5cGUge1xuXG4gIGNvbnN0cnVjdG9yKHR5cGUsIG9ialBhdHRlcm4gPSB7fSkge1xuICAgIHRoaXMudHlwZSA9IHR5cGU7XG4gICAgdGhpcy5vYmpQYXR0ZXJuID0gb2JqUGF0dGVybjtcbiAgfVxufVxuXG5jbGFzcyBCb3VuZCB7XG5cbiAgY29uc3RydWN0b3IodmFsdWUpIHtcbiAgICB0aGlzLnZhbHVlID0gdmFsdWU7XG4gIH1cbn1cblxuZnVuY3Rpb24gdmFyaWFibGUobmFtZSA9IG51bGwpIHtcbiAgcmV0dXJuIG5ldyBWYXJpYWJsZShuYW1lKTtcbn1cblxuZnVuY3Rpb24gd2lsZGNhcmQoKSB7XG4gIHJldHVybiBuZXcgV2lsZGNhcmQoKTtcbn1cblxuZnVuY3Rpb24gc3RhcnRzV2l0aChwcmVmaXgpIHtcbiAgcmV0dXJuIG5ldyBTdGFydHNXaXRoKHByZWZpeCk7XG59XG5cbmZ1bmN0aW9uIGNhcHR1cmUodmFsdWUpIHtcbiAgcmV0dXJuIG5ldyBDYXB0dXJlKHZhbHVlKTtcbn1cblxuZnVuY3Rpb24gaGVhZFRhaWwoKSB7XG4gIHJldHVybiBuZXcgSGVhZFRhaWwoKTtcbn1cblxuZnVuY3Rpb24gdHlwZSh0eXBlLCBvYmpQYXR0ZXJuID0ge30pIHtcbiAgcmV0dXJuIG5ldyBUeXBlKHR5cGUsIG9ialBhdHRlcm4pO1xufVxuXG5mdW5jdGlvbiBib3VuZCh2YWx1ZSkge1xuICByZXR1cm4gbmV3IEJvdW5kKHZhbHVlKTtcbn1cblxuZnVuY3Rpb24gaXNfbnVtYmVyJDEodmFsdWUpIHtcbiAgcmV0dXJuIHR5cGVvZiB2YWx1ZSA9PT0gJ251bWJlcic7XG59XG5cbmZ1bmN0aW9uIGlzX3N0cmluZyh2YWx1ZSkge1xuICByZXR1cm4gdHlwZW9mIHZhbHVlID09PSAnc3RyaW5nJztcbn1cblxuZnVuY3Rpb24gaXNfYm9vbGVhbiQxKHZhbHVlKSB7XG4gIHJldHVybiB0eXBlb2YgdmFsdWUgPT09ICdib29sZWFuJztcbn1cblxuZnVuY3Rpb24gaXNfc3ltYm9sKHZhbHVlKSB7XG4gIHJldHVybiB0eXBlb2YgdmFsdWUgPT09ICdzeW1ib2wnO1xufVxuXG5mdW5jdGlvbiBpc19udWxsKHZhbHVlKSB7XG4gIHJldHVybiB2YWx1ZSA9PT0gbnVsbDtcbn1cblxuZnVuY3Rpb24gaXNfdW5kZWZpbmVkKHZhbHVlKSB7XG4gIHJldHVybiB0eXBlb2YgdmFsdWUgPT09ICd1bmRlZmluZWQnO1xufVxuXG5mdW5jdGlvbiBpc19mdW5jdGlvbiQxKHZhbHVlKSB7XG4gIHJldHVybiBPYmplY3QucHJvdG90eXBlLnRvU3RyaW5nLmNhbGwodmFsdWUpID09ICdbb2JqZWN0IEZ1bmN0aW9uXSc7XG59XG5cbmZ1bmN0aW9uIGlzX3ZhcmlhYmxlKHZhbHVlKSB7XG4gIHJldHVybiB2YWx1ZSBpbnN0YW5jZW9mIFZhcmlhYmxlO1xufVxuXG5mdW5jdGlvbiBpc193aWxkY2FyZCh2YWx1ZSkge1xuICByZXR1cm4gdmFsdWUgaW5zdGFuY2VvZiBXaWxkY2FyZDtcbn1cblxuZnVuY3Rpb24gaXNfaGVhZFRhaWwodmFsdWUpIHtcbiAgcmV0dXJuIHZhbHVlIGluc3RhbmNlb2YgSGVhZFRhaWw7XG59XG5cbmZ1bmN0aW9uIGlzX2NhcHR1cmUodmFsdWUpIHtcbiAgcmV0dXJuIHZhbHVlIGluc3RhbmNlb2YgQ2FwdHVyZTtcbn1cblxuZnVuY3Rpb24gaXNfdHlwZSh2YWx1ZSkge1xuICByZXR1cm4gdmFsdWUgaW5zdGFuY2VvZiBUeXBlO1xufVxuXG5mdW5jdGlvbiBpc19zdGFydHNXaXRoKHZhbHVlKSB7XG4gIHJldHVybiB2YWx1ZSBpbnN0YW5jZW9mIFN0YXJ0c1dpdGg7XG59XG5cbmZ1bmN0aW9uIGlzX2JvdW5kKHZhbHVlKSB7XG4gIHJldHVybiB2YWx1ZSBpbnN0YW5jZW9mIEJvdW5kO1xufVxuXG5mdW5jdGlvbiBpc19vYmplY3QodmFsdWUpIHtcbiAgcmV0dXJuIHR5cGVvZiB2YWx1ZSA9PT0gJ29iamVjdCc7XG59XG5cbmZ1bmN0aW9uIGlzX2FycmF5KHZhbHVlKSB7XG4gIHJldHVybiBBcnJheS5pc0FycmF5KHZhbHVlKTtcbn1cblxudmFyIENoZWNrcyA9IHtcbiAgaXNfbnVtYmVyOiBpc19udW1iZXIkMSxcbiAgaXNfc3RyaW5nLFxuICBpc19ib29sZWFuOiBpc19ib29sZWFuJDEsXG4gIGlzX3N5bWJvbCxcbiAgaXNfbnVsbCxcbiAgaXNfdW5kZWZpbmVkLFxuICBpc19mdW5jdGlvbjogaXNfZnVuY3Rpb24kMSxcbiAgaXNfdmFyaWFibGUsXG4gIGlzX3dpbGRjYXJkLFxuICBpc19oZWFkVGFpbCxcbiAgaXNfY2FwdHVyZSxcbiAgaXNfdHlwZSxcbiAgaXNfc3RhcnRzV2l0aCxcbiAgaXNfYm91bmQsXG4gIGlzX29iamVjdCxcbiAgaXNfYXJyYXlcbn07XG5cbmZ1bmN0aW9uIHJlc29sdmVTeW1ib2wocGF0dGVybikge1xuICByZXR1cm4gZnVuY3Rpb24gKHZhbHVlKSB7XG4gICAgcmV0dXJuIENoZWNrcy5pc19zeW1ib2wodmFsdWUpICYmIHZhbHVlID09PSBwYXR0ZXJuO1xuICB9O1xufVxuXG5mdW5jdGlvbiByZXNvbHZlU3RyaW5nKHBhdHRlcm4pIHtcbiAgcmV0dXJuIGZ1bmN0aW9uICh2YWx1ZSkge1xuICAgIHJldHVybiBDaGVja3MuaXNfc3RyaW5nKHZhbHVlKSAmJiB2YWx1ZSA9PT0gcGF0dGVybjtcbiAgfTtcbn1cblxuZnVuY3Rpb24gcmVzb2x2ZU51bWJlcihwYXR0ZXJuKSB7XG4gIHJldHVybiBmdW5jdGlvbiAodmFsdWUpIHtcbiAgICByZXR1cm4gQ2hlY2tzLmlzX251bWJlcih2YWx1ZSkgJiYgdmFsdWUgPT09IHBhdHRlcm47XG4gIH07XG59XG5cbmZ1bmN0aW9uIHJlc29sdmVCb29sZWFuKHBhdHRlcm4pIHtcbiAgcmV0dXJuIGZ1bmN0aW9uICh2YWx1ZSkge1xuICAgIHJldHVybiBDaGVja3MuaXNfYm9vbGVhbih2YWx1ZSkgJiYgdmFsdWUgPT09IHBhdHRlcm47XG4gIH07XG59XG5cbmZ1bmN0aW9uIHJlc29sdmVGdW5jdGlvbihwYXR0ZXJuKSB7XG4gIHJldHVybiBmdW5jdGlvbiAodmFsdWUpIHtcbiAgICByZXR1cm4gQ2hlY2tzLmlzX2Z1bmN0aW9uKHZhbHVlKSAmJiB2YWx1ZSA9PT0gcGF0dGVybjtcbiAgfTtcbn1cblxuZnVuY3Rpb24gcmVzb2x2ZU51bGwocGF0dGVybikge1xuICByZXR1cm4gZnVuY3Rpb24gKHZhbHVlKSB7XG4gICAgcmV0dXJuIENoZWNrcy5pc19udWxsKHZhbHVlKTtcbiAgfTtcbn1cblxuZnVuY3Rpb24gcmVzb2x2ZUJvdW5kKHBhdHRlcm4pIHtcbiAgcmV0dXJuIGZ1bmN0aW9uICh2YWx1ZSwgYXJncykge1xuICAgIGlmICh0eXBlb2YgdmFsdWUgPT09IHR5cGVvZiBwYXR0ZXJuLnZhbHVlICYmIHZhbHVlID09PSBwYXR0ZXJuLnZhbHVlKSB7XG4gICAgICBhcmdzLnB1c2godmFsdWUpO1xuICAgICAgcmV0dXJuIHRydWU7XG4gICAgfVxuXG4gICAgcmV0dXJuIGZhbHNlO1xuICB9O1xufVxuXG5mdW5jdGlvbiByZXNvbHZlV2lsZGNhcmQoKSB7XG4gIHJldHVybiBmdW5jdGlvbiAoKSB7XG4gICAgcmV0dXJuIHRydWU7XG4gIH07XG59XG5cbmZ1bmN0aW9uIHJlc29sdmVWYXJpYWJsZSgpIHtcbiAgcmV0dXJuIGZ1bmN0aW9uICh2YWx1ZSwgYXJncykge1xuICAgIGFyZ3MucHVzaCh2YWx1ZSk7XG4gICAgcmV0dXJuIHRydWU7XG4gIH07XG59XG5cbmZ1bmN0aW9uIHJlc29sdmVIZWFkVGFpbCgpIHtcbiAgcmV0dXJuIGZ1bmN0aW9uICh2YWx1ZSwgYXJncykge1xuICAgIGlmICghQ2hlY2tzLmlzX2FycmF5KHZhbHVlKSB8fCB2YWx1ZS5sZW5ndGggPCAyKSB7XG4gICAgICByZXR1cm4gZmFsc2U7XG4gICAgfVxuXG4gICAgY29uc3QgaGVhZCA9IHZhbHVlWzBdO1xuICAgIGNvbnN0IHRhaWwgPSB2YWx1ZS5zbGljZSgxKTtcblxuICAgIGFyZ3MucHVzaChoZWFkKTtcbiAgICBhcmdzLnB1c2godGFpbCk7XG5cbiAgICByZXR1cm4gdHJ1ZTtcbiAgfTtcbn1cblxuZnVuY3Rpb24gcmVzb2x2ZUNhcHR1cmUocGF0dGVybikge1xuICBjb25zdCBtYXRjaGVzID0gYnVpbGRNYXRjaChwYXR0ZXJuLnZhbHVlKTtcblxuICByZXR1cm4gZnVuY3Rpb24gKHZhbHVlLCBhcmdzKSB7XG4gICAgaWYgKG1hdGNoZXModmFsdWUsIGFyZ3MpKSB7XG4gICAgICBhcmdzLnB1c2godmFsdWUpO1xuICAgICAgcmV0dXJuIHRydWU7XG4gICAgfVxuXG4gICAgcmV0dXJuIGZhbHNlO1xuICB9O1xufVxuXG5mdW5jdGlvbiByZXNvbHZlU3RhcnRzV2l0aChwYXR0ZXJuKSB7XG4gIGNvbnN0IHByZWZpeCA9IHBhdHRlcm4ucHJlZml4O1xuXG4gIHJldHVybiBmdW5jdGlvbiAodmFsdWUsIGFyZ3MpIHtcbiAgICBpZiAoQ2hlY2tzLmlzX3N0cmluZyh2YWx1ZSkgJiYgdmFsdWUuc3RhcnRzV2l0aChwcmVmaXgpKSB7XG4gICAgICBhcmdzLnB1c2godmFsdWUuc3Vic3RyaW5nKHByZWZpeC5sZW5ndGgpKTtcbiAgICAgIHJldHVybiB0cnVlO1xuICAgIH1cblxuICAgIHJldHVybiBmYWxzZTtcbiAgfTtcbn1cblxuZnVuY3Rpb24gcmVzb2x2ZVR5cGUocGF0dGVybikge1xuICByZXR1cm4gZnVuY3Rpb24gKHZhbHVlLCBhcmdzKSB7XG4gICAgaWYgKHZhbHVlIGluc3RhbmNlb2YgcGF0dGVybi50eXBlKSB7XG4gICAgICBjb25zdCBtYXRjaGVzID0gYnVpbGRNYXRjaChwYXR0ZXJuLm9ialBhdHRlcm4pO1xuICAgICAgcmV0dXJuIG1hdGNoZXModmFsdWUsIGFyZ3MpICYmIGFyZ3MucHVzaCh2YWx1ZSkgPiAwO1xuICAgIH1cblxuICAgIHJldHVybiBmYWxzZTtcbiAgfTtcbn1cblxuZnVuY3Rpb24gcmVzb2x2ZUFycmF5KHBhdHRlcm4pIHtcbiAgY29uc3QgbWF0Y2hlcyA9IHBhdHRlcm4ubWFwKHggPT4gYnVpbGRNYXRjaCh4KSk7XG5cbiAgcmV0dXJuIGZ1bmN0aW9uICh2YWx1ZSwgYXJncykge1xuICAgIGlmICghQ2hlY2tzLmlzX2FycmF5KHZhbHVlKSB8fCB2YWx1ZS5sZW5ndGggIT0gcGF0dGVybi5sZW5ndGgpIHtcbiAgICAgIHJldHVybiBmYWxzZTtcbiAgICB9XG5cbiAgICByZXR1cm4gdmFsdWUuZXZlcnkoZnVuY3Rpb24gKHYsIGkpIHtcbiAgICAgIHJldHVybiBtYXRjaGVzW2ldKHZhbHVlW2ldLCBhcmdzKTtcbiAgICB9KTtcbiAgfTtcbn1cblxuZnVuY3Rpb24gcmVzb2x2ZU9iamVjdChwYXR0ZXJuKSB7XG4gIGxldCBtYXRjaGVzID0ge307XG5cbiAgZm9yIChsZXQga2V5IG9mIE9iamVjdC5rZXlzKHBhdHRlcm4pKSB7XG4gICAgbWF0Y2hlc1trZXldID0gYnVpbGRNYXRjaChwYXR0ZXJuW2tleV0pO1xuICB9XG5cbiAgcmV0dXJuIGZ1bmN0aW9uICh2YWx1ZSwgYXJncykge1xuICAgIGlmICghQ2hlY2tzLmlzX29iamVjdCh2YWx1ZSkgfHwgcGF0dGVybi5sZW5ndGggPiB2YWx1ZS5sZW5ndGgpIHtcbiAgICAgIHJldHVybiBmYWxzZTtcbiAgICB9XG5cbiAgICBmb3IgKGxldCBrZXkgb2YgT2JqZWN0LmtleXMocGF0dGVybikpIHtcbiAgICAgIGlmICghKGtleSBpbiB2YWx1ZSkgfHwgIW1hdGNoZXNba2V5XSh2YWx1ZVtrZXldLCBhcmdzKSkge1xuICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICB9XG4gICAgfVxuXG4gICAgcmV0dXJuIHRydWU7XG4gIH07XG59XG5cbmZ1bmN0aW9uIHJlc29sdmVOb01hdGNoKCkge1xuICByZXR1cm4gZnVuY3Rpb24gKCkge1xuICAgIHJldHVybiBmYWxzZTtcbiAgfTtcbn1cblxudmFyIFJlc29sdmVycyA9IHtcbiAgcmVzb2x2ZUJvdW5kLFxuICByZXNvbHZlV2lsZGNhcmQsXG4gIHJlc29sdmVWYXJpYWJsZSxcbiAgcmVzb2x2ZUhlYWRUYWlsLFxuICByZXNvbHZlQ2FwdHVyZSxcbiAgcmVzb2x2ZVN0YXJ0c1dpdGgsXG4gIHJlc29sdmVUeXBlLFxuICByZXNvbHZlQXJyYXksXG4gIHJlc29sdmVPYmplY3QsXG4gIHJlc29sdmVOb01hdGNoLFxuICByZXNvbHZlU3ltYm9sLFxuICByZXNvbHZlU3RyaW5nLFxuICByZXNvbHZlTnVtYmVyLFxuICByZXNvbHZlQm9vbGVhbixcbiAgcmVzb2x2ZUZ1bmN0aW9uLFxuICByZXNvbHZlTnVsbFxufTtcblxuZnVuY3Rpb24gYnVpbGRNYXRjaChwYXR0ZXJuKSB7XG5cbiAgaWYgKENoZWNrcy5pc192YXJpYWJsZShwYXR0ZXJuKSkge1xuICAgIHJldHVybiBSZXNvbHZlcnMucmVzb2x2ZVZhcmlhYmxlKHBhdHRlcm4pO1xuICB9XG5cbiAgaWYgKENoZWNrcy5pc193aWxkY2FyZChwYXR0ZXJuKSkge1xuICAgIHJldHVybiBSZXNvbHZlcnMucmVzb2x2ZVdpbGRjYXJkKHBhdHRlcm4pO1xuICB9XG5cbiAgaWYgKENoZWNrcy5pc191bmRlZmluZWQocGF0dGVybikpIHtcbiAgICByZXR1cm4gUmVzb2x2ZXJzLnJlc29sdmVXaWxkY2FyZChwYXR0ZXJuKTtcbiAgfVxuXG4gIGlmIChDaGVja3MuaXNfaGVhZFRhaWwocGF0dGVybikpIHtcbiAgICByZXR1cm4gUmVzb2x2ZXJzLnJlc29sdmVIZWFkVGFpbChwYXR0ZXJuKTtcbiAgfVxuXG4gIGlmIChDaGVja3MuaXNfc3RhcnRzV2l0aChwYXR0ZXJuKSkge1xuICAgIHJldHVybiBSZXNvbHZlcnMucmVzb2x2ZVN0YXJ0c1dpdGgocGF0dGVybik7XG4gIH1cblxuICBpZiAoQ2hlY2tzLmlzX2NhcHR1cmUocGF0dGVybikpIHtcbiAgICByZXR1cm4gUmVzb2x2ZXJzLnJlc29sdmVDYXB0dXJlKHBhdHRlcm4pO1xuICB9XG5cbiAgaWYgKENoZWNrcy5pc19ib3VuZChwYXR0ZXJuKSkge1xuICAgIHJldHVybiBSZXNvbHZlcnMucmVzb2x2ZUJvdW5kKHBhdHRlcm4pO1xuICB9XG5cbiAgaWYgKENoZWNrcy5pc190eXBlKHBhdHRlcm4pKSB7XG4gICAgcmV0dXJuIFJlc29sdmVycy5yZXNvbHZlVHlwZShwYXR0ZXJuKTtcbiAgfVxuXG4gIGlmIChDaGVja3MuaXNfYXJyYXkocGF0dGVybikpIHtcbiAgICByZXR1cm4gUmVzb2x2ZXJzLnJlc29sdmVBcnJheShwYXR0ZXJuKTtcbiAgfVxuXG4gIGlmIChDaGVja3MuaXNfbnVtYmVyKHBhdHRlcm4pKSB7XG4gICAgcmV0dXJuIFJlc29sdmVycy5yZXNvbHZlTnVtYmVyKHBhdHRlcm4pO1xuICB9XG5cbiAgaWYgKENoZWNrcy5pc19zdHJpbmcocGF0dGVybikpIHtcbiAgICByZXR1cm4gUmVzb2x2ZXJzLnJlc29sdmVTdHJpbmcocGF0dGVybik7XG4gIH1cblxuICBpZiAoQ2hlY2tzLmlzX2Jvb2xlYW4ocGF0dGVybikpIHtcbiAgICByZXR1cm4gUmVzb2x2ZXJzLnJlc29sdmVCb29sZWFuKHBhdHRlcm4pO1xuICB9XG5cbiAgaWYgKENoZWNrcy5pc19zeW1ib2wocGF0dGVybikpIHtcbiAgICByZXR1cm4gUmVzb2x2ZXJzLnJlc29sdmVTeW1ib2wocGF0dGVybik7XG4gIH1cblxuICBpZiAoQ2hlY2tzLmlzX251bGwocGF0dGVybikpIHtcbiAgICByZXR1cm4gUmVzb2x2ZXJzLnJlc29sdmVOdWxsKHBhdHRlcm4pO1xuICB9XG5cbiAgaWYgKENoZWNrcy5pc19vYmplY3QocGF0dGVybikpIHtcbiAgICByZXR1cm4gUmVzb2x2ZXJzLnJlc29sdmVPYmplY3QocGF0dGVybik7XG4gIH1cblxuICByZXR1cm4gUmVzb2x2ZXJzLnJlc29sdmVOb01hdGNoKCk7XG59XG5cbmNsYXNzIE1hdGNoRXJyb3IgZXh0ZW5kcyBFcnJvciB7XG4gIGNvbnN0cnVjdG9yKGFyZykge1xuICAgIHN1cGVyKCk7XG5cbiAgICBpZiAodHlwZW9mIGFyZyA9PT0gJ3N5bWJvbCcpIHtcbiAgICAgIHRoaXMubWVzc2FnZSA9ICdObyBtYXRjaCBmb3I6ICcgKyBhcmcudG9TdHJpbmcoKTtcbiAgICB9IGVsc2UgaWYgKEFycmF5LmlzQXJyYXkoYXJnKSkge1xuICAgICAgbGV0IG1hcHBlZFZhbHVlcyA9IGFyZy5tYXAoeCA9PiB4LnRvU3RyaW5nKCkpO1xuICAgICAgdGhpcy5tZXNzYWdlID0gJ05vIG1hdGNoIGZvcjogJyArIG1hcHBlZFZhbHVlcztcbiAgICB9IGVsc2Uge1xuICAgICAgdGhpcy5tZXNzYWdlID0gJ05vIG1hdGNoIGZvcjogJyArIGFyZztcbiAgICB9XG5cbiAgICB0aGlzLnN0YWNrID0gbmV3IEVycm9yKCkuc3RhY2s7XG4gICAgdGhpcy5uYW1lID0gdGhpcy5jb25zdHJ1Y3Rvci5uYW1lO1xuICB9XG59XG5cbmNsYXNzIENhc2Uge1xuXG4gIGNvbnN0cnVjdG9yKHBhdHRlcm4sIGZuLCBndWFyZCA9ICgpID0+IHRydWUpIHtcbiAgICB0aGlzLnBhdHRlcm4gPSBidWlsZE1hdGNoKHBhdHRlcm4pO1xuICAgIHRoaXMuZm4gPSBmbjtcbiAgICB0aGlzLmd1YXJkID0gZ3VhcmQ7XG4gIH1cbn1cblxuZnVuY3Rpb24gbWFrZV9jYXNlKHBhdHRlcm4sIGZuLCBndWFyZCA9ICgpID0+IHRydWUpIHtcbiAgcmV0dXJuIG5ldyBDYXNlKHBhdHRlcm4sIGZuLCBndWFyZCk7XG59XG5cbmZ1bmN0aW9uIGRlZm1hdGNoKC4uLmNhc2VzKSB7XG4gIHJldHVybiBmdW5jdGlvbiAoLi4uYXJncykge1xuICAgIGZvciAobGV0IHByb2Nlc3NlZENhc2Ugb2YgY2FzZXMpIHtcbiAgICAgIGxldCByZXN1bHQgPSBbXTtcbiAgICAgIGlmIChwcm9jZXNzZWRDYXNlLnBhdHRlcm4oYXJncywgcmVzdWx0KSAmJiBwcm9jZXNzZWRDYXNlLmd1YXJkLmFwcGx5KHRoaXMsIHJlc3VsdCkpIHtcbiAgICAgICAgcmV0dXJuIHByb2Nlc3NlZENhc2UuZm4uYXBwbHkodGhpcywgcmVzdWx0KTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICB0aHJvdyBuZXcgTWF0Y2hFcnJvcihhcmdzKTtcbiAgfTtcbn1cblxuZnVuY3Rpb24gbWF0Y2gocGF0dGVybiwgZXhwciwgZ3VhcmQgPSAoKSA9PiB0cnVlKSB7XG4gIGxldCByZXN1bHQgPSBbXTtcbiAgbGV0IHByb2Nlc3NlZFBhdHRlcm4gPSBidWlsZE1hdGNoKHBhdHRlcm4pO1xuICBpZiAocHJvY2Vzc2VkUGF0dGVybihleHByLCByZXN1bHQpICYmIGd1YXJkLmFwcGx5KHRoaXMsIHJlc3VsdCkpIHtcbiAgICByZXR1cm4gcmVzdWx0O1xuICB9IGVsc2Uge1xuICAgIHRocm93IG5ldyBNYXRjaEVycm9yKGV4cHIpO1xuICB9XG59XG5cbmZ1bmN0aW9uIG1hdGNoX25vX3Rocm93KHBhdHRlcm4sIGV4cHIsIGd1YXJkID0gKCkgPT4gdHJ1ZSkge1xuICB0cnkge1xuICAgIHJldHVybiBtYXRjaChwYXR0ZXJuLCBleHByLCBndWFyZCk7XG4gIH0gY2F0Y2ggKGUpIHtcbiAgICBpZiAoZSBpbnN0YW5jZW9mIE1hdGNoRXJyb3IpIHtcbiAgICAgIHJldHVybiBudWxsO1xuICAgIH1cblxuICAgIHRocm93IGU7XG4gIH1cbn1cblxuY2xhc3MgQml0U3RyaW5nIHtcbiAgY29uc3RydWN0b3IoLi4uYXJncykge1xuICAgIHRoaXMucmF3X3ZhbHVlID0gZnVuY3Rpb24gKCkge1xuICAgICAgcmV0dXJuIE9iamVjdC5mcmVlemUoYXJncyk7XG4gICAgfTtcblxuICAgIHRoaXMudmFsdWUgPSBPYmplY3QuZnJlZXplKHRoaXMucHJvY2VzcyhhcmdzKSk7XG4gIH1cblxuICBnZXQoaW5kZXgpIHtcbiAgICByZXR1cm4gdGhpcy52YWx1ZVtpbmRleF07XG4gIH1cblxuICBjb3VudCgpIHtcbiAgICByZXR1cm4gdGhpcy52YWx1ZS5sZW5ndGg7XG4gIH1cblxuICBbU3ltYm9sLml0ZXJhdG9yXSgpIHtcbiAgICByZXR1cm4gdGhpcy52YWx1ZVtTeW1ib2wuaXRlcmF0b3JdKCk7XG4gIH1cblxuICB0b1N0cmluZygpIHtcbiAgICB2YXIgaSxcbiAgICAgICAgcyA9IFwiXCI7XG4gICAgZm9yIChpID0gMDsgaSA8IHRoaXMuY291bnQoKTsgaSsrKSB7XG4gICAgICBpZiAocyAhPT0gXCJcIikge1xuICAgICAgICBzICs9IFwiLCBcIjtcbiAgICAgIH1cbiAgICAgIHMgKz0gdGhpc1tpXS50b1N0cmluZygpO1xuICAgIH1cblxuICAgIHJldHVybiBcIjw8XCIgKyBzICsgXCI+PlwiO1xuICB9XG5cbiAgcHJvY2VzcygpIHtcbiAgICBsZXQgcHJvY2Vzc2VkX3ZhbHVlcyA9IFtdO1xuXG4gICAgdmFyIGk7XG4gICAgZm9yIChpID0gMDsgaSA8IHRoaXMucmF3X3ZhbHVlKCkubGVuZ3RoOyBpKyspIHtcbiAgICAgIGxldCBwcm9jZXNzZWRfdmFsdWUgPSB0aGlzW1wicHJvY2Vzc19cIiArIHRoaXMucmF3X3ZhbHVlKClbaV0udHlwZV0odGhpcy5yYXdfdmFsdWUoKVtpXSk7XG5cbiAgICAgIGZvciAobGV0IGF0dHIgb2YgdGhpcy5yYXdfdmFsdWUoKVtpXS5hdHRyaWJ1dGVzKSB7XG4gICAgICAgIHByb2Nlc3NlZF92YWx1ZSA9IHRoaXNbXCJwcm9jZXNzX1wiICsgYXR0cl0ocHJvY2Vzc2VkX3ZhbHVlKTtcbiAgICAgIH1cblxuICAgICAgcHJvY2Vzc2VkX3ZhbHVlcyA9IHByb2Nlc3NlZF92YWx1ZXMuY29uY2F0KHByb2Nlc3NlZF92YWx1ZSk7XG4gICAgfVxuXG4gICAgcmV0dXJuIHByb2Nlc3NlZF92YWx1ZXM7XG4gIH1cblxuICBwcm9jZXNzX2ludGVnZXIodmFsdWUpIHtcbiAgICByZXR1cm4gdmFsdWUudmFsdWU7XG4gIH1cblxuICBwcm9jZXNzX2Zsb2F0KHZhbHVlKSB7XG4gICAgaWYgKHZhbHVlLnNpemUgPT09IDY0KSB7XG4gICAgICByZXR1cm4gQml0U3RyaW5nLmZsb2F0NjRUb0J5dGVzKHZhbHVlLnZhbHVlKTtcbiAgICB9IGVsc2UgaWYgKHZhbHVlLnNpemUgPT09IDMyKSB7XG4gICAgICByZXR1cm4gQml0U3RyaW5nLmZsb2F0MzJUb0J5dGVzKHZhbHVlLnZhbHVlKTtcbiAgICB9XG5cbiAgICB0aHJvdyBuZXcgRXJyb3IoXCJJbnZhbGlkIHNpemUgZm9yIGZsb2F0XCIpO1xuICB9XG5cbiAgcHJvY2Vzc19iaXRzdHJpbmcodmFsdWUpIHtcbiAgICByZXR1cm4gdmFsdWUudmFsdWUudmFsdWU7XG4gIH1cblxuICBwcm9jZXNzX2JpbmFyeSh2YWx1ZSkge1xuICAgIHJldHVybiBCaXRTdHJpbmcudG9VVEY4QXJyYXkodmFsdWUudmFsdWUpO1xuICB9XG5cbiAgcHJvY2Vzc191dGY4KHZhbHVlKSB7XG4gICAgcmV0dXJuIEJpdFN0cmluZy50b1VURjhBcnJheSh2YWx1ZS52YWx1ZSk7XG4gIH1cblxuICBwcm9jZXNzX3V0ZjE2KHZhbHVlKSB7XG4gICAgcmV0dXJuIEJpdFN0cmluZy50b1VURjE2QXJyYXkodmFsdWUudmFsdWUpO1xuICB9XG5cbiAgcHJvY2Vzc191dGYzMih2YWx1ZSkge1xuICAgIHJldHVybiBCaXRTdHJpbmcudG9VVEYzMkFycmF5KHZhbHVlLnZhbHVlKTtcbiAgfVxuXG4gIHByb2Nlc3Nfc2lnbmVkKHZhbHVlKSB7XG4gICAgcmV0dXJuIG5ldyBVaW50OEFycmF5KFt2YWx1ZV0pWzBdO1xuICB9XG5cbiAgcHJvY2Vzc191bnNpZ25lZCh2YWx1ZSkge1xuICAgIHJldHVybiB2YWx1ZTtcbiAgfVxuXG4gIHByb2Nlc3NfbmF0aXZlKHZhbHVlKSB7XG4gICAgcmV0dXJuIHZhbHVlO1xuICB9XG5cbiAgcHJvY2Vzc19iaWcodmFsdWUpIHtcbiAgICByZXR1cm4gdmFsdWU7XG4gIH1cblxuICBwcm9jZXNzX2xpdHRsZSh2YWx1ZSkge1xuICAgIHJldHVybiB2YWx1ZS5yZXZlcnNlKCk7XG4gIH1cblxuICBwcm9jZXNzX3NpemUodmFsdWUpIHtcbiAgICByZXR1cm4gdmFsdWU7XG4gIH1cblxuICBwcm9jZXNzX3VuaXQodmFsdWUpIHtcbiAgICByZXR1cm4gdmFsdWU7XG4gIH1cblxuICBzdGF0aWMgaW50ZWdlcih2YWx1ZSkge1xuICAgIHJldHVybiBCaXRTdHJpbmcud3JhcCh2YWx1ZSwgeyBcInR5cGVcIjogXCJpbnRlZ2VyXCIsIFwidW5pdFwiOiAxLCBcInNpemVcIjogOCB9KTtcbiAgfVxuXG4gIHN0YXRpYyBmbG9hdCh2YWx1ZSkge1xuICAgIHJldHVybiBCaXRTdHJpbmcud3JhcCh2YWx1ZSwgeyBcInR5cGVcIjogXCJmbG9hdFwiLCBcInVuaXRcIjogMSwgXCJzaXplXCI6IDY0IH0pO1xuICB9XG5cbiAgc3RhdGljIGJpdHN0cmluZyh2YWx1ZSkge1xuICAgIHJldHVybiBCaXRTdHJpbmcud3JhcCh2YWx1ZSwgeyBcInR5cGVcIjogXCJiaXRzdHJpbmdcIiwgXCJ1bml0XCI6IDEsIFwic2l6ZVwiOiB2YWx1ZS5sZW5ndGggfSk7XG4gIH1cblxuICBzdGF0aWMgYml0cyh2YWx1ZSkge1xuICAgIHJldHVybiBCaXRTdHJpbmcuYml0c3RyaW5nKHZhbHVlKTtcbiAgfVxuXG4gIHN0YXRpYyBiaW5hcnkodmFsdWUpIHtcbiAgICByZXR1cm4gQml0U3RyaW5nLndyYXAodmFsdWUsIHsgXCJ0eXBlXCI6IFwiYmluYXJ5XCIsIFwidW5pdFwiOiA4LCBcInNpemVcIjogdmFsdWUubGVuZ3RoIH0pO1xuICB9XG5cbiAgc3RhdGljIGJ5dGVzKHZhbHVlKSB7XG4gICAgcmV0dXJuIEJpdFN0cmluZy5iaW5hcnkodmFsdWUpO1xuICB9XG5cbiAgc3RhdGljIHV0ZjgodmFsdWUpIHtcbiAgICByZXR1cm4gQml0U3RyaW5nLndyYXAodmFsdWUsIHsgXCJ0eXBlXCI6IFwidXRmOFwiIH0pO1xuICB9XG5cbiAgc3RhdGljIHV0ZjE2KHZhbHVlKSB7XG4gICAgcmV0dXJuIEJpdFN0cmluZy53cmFwKHZhbHVlLCB7IFwidHlwZVwiOiBcInV0ZjE2XCIgfSk7XG4gIH1cblxuICBzdGF0aWMgdXRmMzIodmFsdWUpIHtcbiAgICByZXR1cm4gQml0U3RyaW5nLndyYXAodmFsdWUsIHsgXCJ0eXBlXCI6IFwidXRmMzJcIiB9KTtcbiAgfVxuXG4gIHN0YXRpYyBzaWduZWQodmFsdWUpIHtcbiAgICByZXR1cm4gQml0U3RyaW5nLndyYXAodmFsdWUsIHt9LCBcInNpZ25lZFwiKTtcbiAgfVxuXG4gIHN0YXRpYyB1bnNpZ25lZCh2YWx1ZSkge1xuICAgIHJldHVybiBCaXRTdHJpbmcud3JhcCh2YWx1ZSwge30sIFwidW5zaWduZWRcIik7XG4gIH1cblxuICBzdGF0aWMgbmF0aXZlKHZhbHVlKSB7XG4gICAgcmV0dXJuIEJpdFN0cmluZy53cmFwKHZhbHVlLCB7fSwgXCJuYXRpdmVcIik7XG4gIH1cblxuICBzdGF0aWMgYmlnKHZhbHVlKSB7XG4gICAgcmV0dXJuIEJpdFN0cmluZy53cmFwKHZhbHVlLCB7fSwgXCJiaWdcIik7XG4gIH1cblxuICBzdGF0aWMgbGl0dGxlKHZhbHVlKSB7XG4gICAgcmV0dXJuIEJpdFN0cmluZy53cmFwKHZhbHVlLCB7fSwgXCJsaXR0bGVcIik7XG4gIH1cblxuICBzdGF0aWMgc2l6ZSh2YWx1ZSwgY291bnQpIHtcbiAgICByZXR1cm4gQml0U3RyaW5nLndyYXAodmFsdWUsIHsgXCJzaXplXCI6IGNvdW50IH0pO1xuICB9XG5cbiAgc3RhdGljIHVuaXQodmFsdWUsIGNvdW50KSB7XG4gICAgcmV0dXJuIEJpdFN0cmluZy53cmFwKHZhbHVlLCB7IFwidW5pdFwiOiBjb3VudCB9KTtcbiAgfVxuXG4gIHN0YXRpYyB3cmFwKHZhbHVlLCBvcHQsIG5ld19hdHRyaWJ1dGUgPSBudWxsKSB7XG4gICAgbGV0IHRoZV92YWx1ZSA9IHZhbHVlO1xuXG4gICAgaWYgKCEodmFsdWUgaW5zdGFuY2VvZiBPYmplY3QpKSB7XG4gICAgICB0aGVfdmFsdWUgPSB7IFwidmFsdWVcIjogdmFsdWUsIFwiYXR0cmlidXRlc1wiOiBbXSB9O1xuICAgIH1cblxuICAgIHRoZV92YWx1ZSA9IE9iamVjdC5hc3NpZ24odGhlX3ZhbHVlLCBvcHQpO1xuXG4gICAgaWYgKG5ld19hdHRyaWJ1dGUpIHtcbiAgICAgIHRoZV92YWx1ZS5hdHRyaWJ1dGVzLnB1c2gobmV3X2F0dHJpYnV0ZSk7XG4gICAgfVxuXG4gICAgcmV0dXJuIHRoZV92YWx1ZTtcbiAgfVxuXG4gIHN0YXRpYyB0b1VURjhBcnJheShzdHIpIHtcbiAgICB2YXIgdXRmOCA9IFtdO1xuICAgIGZvciAodmFyIGkgPSAwOyBpIDwgc3RyLmxlbmd0aDsgaSsrKSB7XG4gICAgICB2YXIgY2hhcmNvZGUgPSBzdHIuY2hhckNvZGVBdChpKTtcbiAgICAgIGlmIChjaGFyY29kZSA8IDEyOCkge1xuICAgICAgICB1dGY4LnB1c2goY2hhcmNvZGUpO1xuICAgICAgfSBlbHNlIGlmIChjaGFyY29kZSA8IDIwNDgpIHtcbiAgICAgICAgdXRmOC5wdXNoKDE5MiB8IGNoYXJjb2RlID4+IDYsIDEyOCB8IGNoYXJjb2RlICYgNjMpO1xuICAgICAgfSBlbHNlIGlmIChjaGFyY29kZSA8IDU1Mjk2IHx8IGNoYXJjb2RlID49IDU3MzQ0KSB7XG4gICAgICAgIHV0ZjgucHVzaCgyMjQgfCBjaGFyY29kZSA+PiAxMiwgMTI4IHwgY2hhcmNvZGUgPj4gNiAmIDYzLCAxMjggfCBjaGFyY29kZSAmIDYzKTtcbiAgICAgIH1cbiAgICAgIC8vIHN1cnJvZ2F0ZSBwYWlyXG4gICAgICBlbHNlIHtcbiAgICAgICAgaSsrO1xuICAgICAgICAvLyBVVEYtMTYgZW5jb2RlcyAweDEwMDAwLTB4MTBGRkZGIGJ5XG4gICAgICAgIC8vIHN1YnRyYWN0aW5nIDB4MTAwMDAgYW5kIHNwbGl0dGluZyB0aGVcbiAgICAgICAgLy8gMjAgYml0cyBvZiAweDAtMHhGRkZGRiBpbnRvIHR3byBoYWx2ZXNcbiAgICAgICAgY2hhcmNvZGUgPSA2NTUzNiArICgoY2hhcmNvZGUgJiAxMDIzKSA8PCAxMCB8IHN0ci5jaGFyQ29kZUF0KGkpICYgMTAyMyk7XG4gICAgICAgIHV0ZjgucHVzaCgyNDAgfCBjaGFyY29kZSA+PiAxOCwgMTI4IHwgY2hhcmNvZGUgPj4gMTIgJiA2MywgMTI4IHwgY2hhcmNvZGUgPj4gNiAmIDYzLCAxMjggfCBjaGFyY29kZSAmIDYzKTtcbiAgICAgIH1cbiAgICB9XG4gICAgcmV0dXJuIHV0Zjg7XG4gIH1cblxuICBzdGF0aWMgdG9VVEYxNkFycmF5KHN0cikge1xuICAgIHZhciB1dGYxNiA9IFtdO1xuICAgIGZvciAodmFyIGkgPSAwOyBpIDwgc3RyLmxlbmd0aDsgaSsrKSB7XG4gICAgICB2YXIgY29kZVBvaW50ID0gc3RyLmNvZGVQb2ludEF0KGkpO1xuXG4gICAgICBpZiAoY29kZVBvaW50IDw9IDI1NSkge1xuICAgICAgICB1dGYxNi5wdXNoKDApO1xuICAgICAgICB1dGYxNi5wdXNoKGNvZGVQb2ludCk7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICB1dGYxNi5wdXNoKGNvZGVQb2ludCA+PiA4ICYgMjU1KTtcbiAgICAgICAgdXRmMTYucHVzaChjb2RlUG9pbnQgJiAyNTUpO1xuICAgICAgfVxuICAgIH1cbiAgICByZXR1cm4gdXRmMTY7XG4gIH1cblxuICBzdGF0aWMgdG9VVEYzMkFycmF5KHN0cikge1xuICAgIHZhciB1dGYzMiA9IFtdO1xuICAgIGZvciAodmFyIGkgPSAwOyBpIDwgc3RyLmxlbmd0aDsgaSsrKSB7XG4gICAgICB2YXIgY29kZVBvaW50ID0gc3RyLmNvZGVQb2ludEF0KGkpO1xuXG4gICAgICBpZiAoY29kZVBvaW50IDw9IDI1NSkge1xuICAgICAgICB1dGYzMi5wdXNoKDApO1xuICAgICAgICB1dGYzMi5wdXNoKDApO1xuICAgICAgICB1dGYzMi5wdXNoKDApO1xuICAgICAgICB1dGYzMi5wdXNoKGNvZGVQb2ludCk7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICB1dGYzMi5wdXNoKDApO1xuICAgICAgICB1dGYzMi5wdXNoKDApO1xuICAgICAgICB1dGYzMi5wdXNoKGNvZGVQb2ludCA+PiA4ICYgMjU1KTtcbiAgICAgICAgdXRmMzIucHVzaChjb2RlUG9pbnQgJiAyNTUpO1xuICAgICAgfVxuICAgIH1cbiAgICByZXR1cm4gdXRmMzI7XG4gIH1cblxuICAvL2h0dHA6Ly9zdGFja292ZXJmbG93LmNvbS9xdWVzdGlvbnMvMjAwMzQ5My9qYXZhc2NyaXB0LWZsb2F0LWZyb20tdG8tYml0c1xuICBzdGF0aWMgZmxvYXQzMlRvQnl0ZXMoZikge1xuICAgIHZhciBieXRlcyA9IFtdO1xuXG4gICAgdmFyIGJ1ZiA9IG5ldyBBcnJheUJ1ZmZlcig0KTtcbiAgICBuZXcgRmxvYXQzMkFycmF5KGJ1ZilbMF0gPSBmO1xuXG4gICAgbGV0IGludFZlcnNpb24gPSBuZXcgVWludDMyQXJyYXkoYnVmKVswXTtcblxuICAgIGJ5dGVzLnB1c2goaW50VmVyc2lvbiA+PiAyNCAmIDI1NSk7XG4gICAgYnl0ZXMucHVzaChpbnRWZXJzaW9uID4+IDE2ICYgMjU1KTtcbiAgICBieXRlcy5wdXNoKGludFZlcnNpb24gPj4gOCAmIDI1NSk7XG4gICAgYnl0ZXMucHVzaChpbnRWZXJzaW9uICYgMjU1KTtcblxuICAgIHJldHVybiBieXRlcztcbiAgfVxuXG4gIHN0YXRpYyBmbG9hdDY0VG9CeXRlcyhmKSB7XG4gICAgdmFyIGJ5dGVzID0gW107XG5cbiAgICB2YXIgYnVmID0gbmV3IEFycmF5QnVmZmVyKDgpO1xuICAgIG5ldyBGbG9hdDY0QXJyYXkoYnVmKVswXSA9IGY7XG5cbiAgICB2YXIgaW50VmVyc2lvbjEgPSBuZXcgVWludDMyQXJyYXkoYnVmKVswXTtcbiAgICB2YXIgaW50VmVyc2lvbjIgPSBuZXcgVWludDMyQXJyYXkoYnVmKVsxXTtcblxuICAgIGJ5dGVzLnB1c2goaW50VmVyc2lvbjIgPj4gMjQgJiAyNTUpO1xuICAgIGJ5dGVzLnB1c2goaW50VmVyc2lvbjIgPj4gMTYgJiAyNTUpO1xuICAgIGJ5dGVzLnB1c2goaW50VmVyc2lvbjIgPj4gOCAmIDI1NSk7XG4gICAgYnl0ZXMucHVzaChpbnRWZXJzaW9uMiAmIDI1NSk7XG5cbiAgICBieXRlcy5wdXNoKGludFZlcnNpb24xID4+IDI0ICYgMjU1KTtcbiAgICBieXRlcy5wdXNoKGludFZlcnNpb24xID4+IDE2ICYgMjU1KTtcbiAgICBieXRlcy5wdXNoKGludFZlcnNpb24xID4+IDggJiAyNTUpO1xuICAgIGJ5dGVzLnB1c2goaW50VmVyc2lvbjEgJiAyNTUpO1xuXG4gICAgcmV0dXJuIGJ5dGVzO1xuICB9XG59XG5cbi8qIEBmbG93ICovXG5cbmNsYXNzIE1haWxib3gge1xuXG4gIGNvbnN0cnVjdG9yKCkge1xuICAgIHRoaXMubWVzc2FnZXMgPSBbXTtcbiAgfVxuXG4gIGRlbGl2ZXIobWVzc2FnZSkge1xuICAgIHRoaXMubWVzc2FnZXMucHVzaChtZXNzYWdlKTtcbiAgICByZXR1cm4gbWVzc2FnZTtcbiAgfVxuXG4gIGdldCgpIHtcbiAgICByZXR1cm4gdGhpcy5tZXNzYWdlcztcbiAgfVxuXG4gIGlzRW1wdHkoKSB7XG4gICAgcmV0dXJuIHRoaXMubWVzc2FnZXMubGVuZ3RoID09PSAwO1xuICB9XG5cbiAgcmVtb3ZlQXQoaW5kZXgpIHtcbiAgICB0aGlzLm1lc3NhZ2VzLnNwbGljZShpbmRleCwgMSk7XG4gIH1cbn1cblxudmFyIFN0YXRlcyA9IHtcbiAgTk9STUFMOiBTeW1ib2wuZm9yKFwibm9ybWFsXCIpLFxuICBLSUxMOiBTeW1ib2wuZm9yKFwia2lsbFwiKSxcbiAgU1VTUEVORDogU3ltYm9sLmZvcihcInN1c3BlbmRcIiksXG4gIENPTlRJTlVFOiBTeW1ib2wuZm9yKFwiY29udGludWVcIiksXG4gIFJFQ0VJVkU6IFN5bWJvbC5mb3IoXCJyZWNlaXZlXCIpLFxuICBTRU5EOiBTeW1ib2wuZm9yKFwic2VuZFwiKSxcbiAgU0xFRVBJTkc6IFN5bWJvbC5mb3IoXCJzbGVlcGluZ1wiKSxcbiAgUlVOTklORzogU3ltYm9sLmZvcihcInJ1bm5pbmdcIiksXG4gIFNVU1BFTkRFRDogU3ltYm9sLmZvcihcInN1c3BlbmRlZFwiKSxcbiAgU1RPUFBFRDogU3ltYm9sLmZvcihcInN0b3BwZWRcIiksXG4gIFNMRUVQOiBTeW1ib2wuZm9yKFwic2xlZXBcIiksXG4gIEVYSVQ6IFN5bWJvbC5mb3IoXCJleGl0XCIpLFxuICBOT01BVENIOiBTeW1ib2wuZm9yKFwibm9fbWF0Y2hcIilcbn07XG5cbmNsYXNzIFByb2Nlc3Mge1xuXG4gIGNvbnN0cnVjdG9yKHBpZCwgbWFpbGJveCkge1xuICAgIHRoaXMucGlkID0gcGlkO1xuICAgIHRoaXMubWFpbGJveCA9IG1haWxib3g7XG4gICAgdGhpcy5zdGF0dXMgPSBTdGF0ZXMuU1RPUFBFRDtcbiAgICB0aGlzLmRpY3QgPSB7fTtcbiAgfVxufVxuXG5jbGFzcyBQcm9jZXNzU3lzdGVtIHtcblxuICBjb25zdHJ1Y3RvcigpIHtcbiAgICB0aGlzLnBpZHMgPSBuZXcgTWFwKCk7XG4gICAgdGhpcy5tYWlsYm94ZXMgPSBuZXcgTWFwKCk7XG4gICAgdGhpcy5uYW1lcyA9IG5ldyBNYXAoKTtcbiAgICB0aGlzLmxpbmtzID0gbmV3IE1hcCgpO1xuXG4gICAgdGhpcy5jdXJyZW50X3Byb2Nlc3MgPSBudWxsO1xuICAgIHRoaXMuc3VzcGVuZGVkID0gbmV3IE1hcCgpO1xuXG4gICAgdGhpcy5tYWluX3Byb2Nlc3NfcGlkID0gdGhpcy5zcGF3bigpO1xuICAgIHRoaXMuc2V0X2N1cnJlbnQodGhpcy5tYWluX3Byb2Nlc3NfcGlkKTtcbiAgfVxuXG4gIHNwYXduKCkge1xuICAgIHJldHVybiB0aGlzLmFkZF9wcm9jKGZhbHNlKS5waWQ7XG4gIH1cblxuICBzcGF3bl9saW5rKCkge1xuICAgIHJldHVybiB0aGlzLmFkZF9wcm9jKHRydWUpLnBpZDtcbiAgfVxuXG4gIGxpbmsocGlkKSB7XG4gICAgdGhpcy5saW5rcy5nZXQodGhpcy5waWQoKSkuYWRkKHBpZCk7XG4gICAgdGhpcy5saW5rcy5nZXQocGlkKS5hZGQodGhpcy5waWQoKSk7XG4gIH1cblxuICB1bmxpbmsocGlkKSB7XG4gICAgdGhpcy5saW5rcy5nZXQodGhpcy5waWQoKSkuZGVsZXRlKHBpZCk7XG4gICAgdGhpcy5saW5rcy5nZXQocGlkKS5kZWxldGUodGhpcy5waWQoKSk7XG4gIH1cblxuICBzZXRfY3VycmVudChpZCkge1xuICAgIGxldCBwaWQgPSB0aGlzLnBpZG9mKGlkKTtcbiAgICBpZiAocGlkICE9PSBudWxsKSB7XG4gICAgICB0aGlzLmN1cnJlbnRfcHJvY2VzcyA9IHRoaXMucGlkcy5nZXQocGlkKTtcbiAgICAgIHRoaXMuY3VycmVudF9wcm9jZXNzLnN0YXR1cyA9IFN0YXRlcy5SVU5OSU5HO1xuICAgIH1cbiAgfVxuXG4gIGFkZF9wcm9jKGxpbmtlZCkge1xuICAgIGxldCBuZXdwaWQgPSBuZXcgUElEKCk7XG4gICAgbGV0IG1haWxib3ggPSBuZXcgTWFpbGJveCgpO1xuICAgIGxldCBuZXdwcm9jID0gbmV3IFByb2Nlc3MobmV3cGlkLCBtYWlsYm94KTtcblxuICAgIHRoaXMucGlkcy5zZXQobmV3cGlkLCBuZXdwcm9jKTtcbiAgICB0aGlzLm1haWxib3hlcy5zZXQobmV3cGlkLCBtYWlsYm94KTtcbiAgICB0aGlzLmxpbmtzLnNldChuZXdwaWQsIG5ldyBTZXQoKSk7XG5cbiAgICBpZiAobGlua2VkKSB7XG4gICAgICB0aGlzLmxpbmsobmV3cGlkKTtcbiAgICB9XG5cbiAgICByZXR1cm4gbmV3cHJvYztcbiAgfVxuXG4gIHJlbW92ZV9wcm9jKHBpZCkge1xuICAgIHRoaXMucGlkcy5kZWxldGUocGlkKTtcbiAgICB0aGlzLnVucmVnaXN0ZXIocGlkKTtcblxuICAgIGlmICh0aGlzLmxpbmtzLmhhcyhwaWQpKSB7XG4gICAgICBmb3IgKGxldCBsaW5rcGlkIG9mIHRoaXMubGlua3MuZ2V0KHBpZCkpIHtcbiAgICAgICAgdGhpcy5saW5rcy5nZXQobGlua3BpZCkuZGVsZXRlKHBpZCk7XG4gICAgICB9XG5cbiAgICAgIHRoaXMubGlua3MuZGVsZXRlKHBpZCk7XG4gICAgfVxuICB9XG5cbiAgZXhpdChpZCkge1xuICAgIGxldCBwaWQgPSB0aGlzLnBpZG9mKGlkKTtcbiAgICB0aGlzLnJlbW92ZV9wcm9jKGlkKTtcbiAgfVxuXG4gIHJlZ2lzdGVyKG5hbWUsIHBpZCkge1xuICAgIGlmICghdGhpcy5uYW1lcy5oYXMobmFtZSkpIHtcbiAgICAgIHRoaXMubmFtZXMuc2V0KG5hbWUsIHBpZCk7XG4gICAgICByZXR1cm4gbmFtZTtcbiAgICB9IGVsc2Uge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKFwiTmFtZSBpcyBhbHJlYWR5IHJlZ2lzdGVyZWQgdG8gYW5vdGhlciBwcm9jZXNzXCIpO1xuICAgIH1cbiAgfVxuXG4gIHJlZ2lzdGVyZWQobmFtZSkge1xuICAgIHJldHVybiB0aGlzLm5hbWVzLmhhcyhuYW1lKSA/IHRoaXMubmFtZXMuZ2V0KG5hbWUpIDogbnVsbDtcbiAgfVxuXG4gIHVucmVnaXN0ZXIocGlkKSB7XG4gICAgZm9yIChsZXQgbmFtZSBvZiB0aGlzLm5hbWVzLmtleXMoKSkge1xuICAgICAgaWYgKHRoaXMubmFtZXMuaGFzKG5hbWUpICYmIHRoaXMubmFtZXMuZ2V0KG5hbWUpID09PSBwaWQpIHtcbiAgICAgICAgdGhpcy5uYW1lcy5kZWxldGUobmFtZSk7XG4gICAgICB9XG4gICAgfVxuICB9XG5cbiAgcGlkKCkge1xuICAgIHJldHVybiB0aGlzLmN1cnJlbnRfcHJvY2Vzcy5waWQ7XG4gIH1cblxuICBwaWRvZihpZCkge1xuICAgIGlmIChpZCBpbnN0YW5jZW9mIFBJRCkge1xuICAgICAgcmV0dXJuIHRoaXMucGlkcy5oYXMoaWQpID8gaWQgOiBudWxsO1xuICAgIH0gZWxzZSBpZiAoaWQgaW5zdGFuY2VvZiBQcm9jZXNzKSB7XG4gICAgICByZXR1cm4gaWQucGlkO1xuICAgIH0gZWxzZSB7XG4gICAgICBsZXQgcGlkID0gdGhpcy5yZWdpc3RlcmVkKGlkKTtcbiAgICAgIGlmIChwaWQgPT09IG51bGwpIHRocm93IFwiUHJvY2VzcyBuYW1lIG5vdCByZWdpc3RlcmVkOiBcIiArIGlkICsgXCIgKFwiICsgdHlwZW9mIGlkICsgXCIpXCI7XG4gICAgICByZXR1cm4gcGlkO1xuICAgIH1cbiAgfVxuXG4gIHB1dChpZCwga2V5LCB2YWx1ZSkge1xuICAgIGxldCBwaWQgPSB0aGlzLnBpZG9mKGlkKTtcbiAgICBsZXQgcHJvY2VzcyA9IHRoaXMucGlkcy5nZXQocGlkKTtcbiAgICBwcm9jZXNzLmRpY3Rba2V5XSA9IHZhbHVlO1xuICB9XG5cbiAgZ2V0KGlkLCBrZXkpIHtcbiAgICBsZXQgcGlkID0gdGhpcy5waWRvZihpZCk7XG4gICAgbGV0IHByb2Nlc3MgPSB0aGlzLnBpZHMuZ2V0KHBpZCk7XG5cbiAgICBpZiAoa2V5ICE9IG51bGwpIHtcbiAgICAgIHJldHVybiBwcm9jZXNzLmRpY3Rba2V5XTtcbiAgICB9IGVsc2Uge1xuICAgICAgcmV0dXJuIHByb2Nlc3MuZGljdDtcbiAgICB9XG4gIH1cblxuICBnZXRfa2V5cyhpZCkge1xuICAgIGxldCBwaWQgPSB0aGlzLnBpZG9mKGlkKTtcbiAgICBsZXQgcHJvY2VzcyA9IHRoaXMucGlkcy5nZXQocGlkKTtcblxuICAgIHJldHVybiBPYmplY3Qua2V5cyhwcm9jZXNzLmRpY3QpO1xuICB9XG5cbiAgZXJhc2UoaWQsIGtleSkge1xuICAgIGxldCBwaWQgPSB0aGlzLnBpZG9mKGlkKTtcbiAgICBsZXQgcHJvY2VzcyA9IHRoaXMucGlkcy5nZXQocGlkKTtcblxuICAgIGlmIChrZXkgIT0gbnVsbCkge1xuICAgICAgZGVsZXRlIHByb2Nlc3MuZGljdFtrZXldO1xuICAgIH0gZWxzZSB7XG4gICAgICBwcm9jZXNzLmRpY3QgPSB7fTtcbiAgICB9XG4gIH1cbn1cblxudmFyIEMgPSBPYmplY3QuZnJlZXplKHtcblx0UHJvY2Vzc1N5c3RlbTogUHJvY2Vzc1N5c3RlbSxcblx0VHVwbGU6IFR1cGxlJDEsXG5cdFBJRDogUElELFxuXHRCaXRTdHJpbmc6IEJpdFN0cmluZyxcblx0UGF0dGVybnM6IG51bGwkMSxcblx0SW50ZWdlclR5cGU6IEludGVnZXJUeXBlLFxuXHRGbG9hdFR5cGU6IEZsb2F0VHlwZSxcblx0Y2FsbF9wcm9wZXJ0eTogY2FsbF9wcm9wZXJ0eVxufSk7XG5cbmxldCBFbnVtID0ge1xuXG4gIGFsbF9fcW1hcmtfXzogZnVuY3Rpb24gKGNvbGxlY3Rpb24sIGZ1biA9IHggPT4geCkge1xuICAgIGZvciAobGV0IGVsZW0gb2YgY29sbGVjdGlvbikge1xuICAgICAgaWYgKCFmdW4oZWxlbSkpIHtcbiAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgfVxuICAgIH1cblxuICAgIHJldHVybiB0cnVlO1xuICB9LFxuXG4gIGFueV9fcW1hcmtfXzogZnVuY3Rpb24gKGNvbGxlY3Rpb24sIGZ1biA9IHggPT4geCkge1xuICAgIGZvciAobGV0IGVsZW0gb2YgY29sbGVjdGlvbikge1xuICAgICAgaWYgKGZ1bihlbGVtKSkge1xuICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICByZXR1cm4gZmFsc2U7XG4gIH0sXG5cbiAgYXQ6IGZ1bmN0aW9uIChjb2xsZWN0aW9uLCBuLCB0aGVfZGVmYXVsdCA9IG51bGwpIHtcbiAgICBpZiAobiA+IHRoaXMuY291bnQoY29sbGVjdGlvbikgfHwgbiA8IDApIHtcbiAgICAgIHJldHVybiB0aGVfZGVmYXVsdDtcbiAgICB9XG5cbiAgICByZXR1cm4gY29sbGVjdGlvbltuXTtcbiAgfSxcblxuICBjb25jYXQ6IGZ1bmN0aW9uICguLi5lbnVtYWJsZXMpIHtcbiAgICByZXR1cm4gZW51bWFibGVzWzBdLmNvbmNhdChlbnVtYWJsZXNbMV0pO1xuICB9LFxuXG4gIGNvdW50OiBmdW5jdGlvbiAoY29sbGVjdGlvbiwgZnVuID0gbnVsbCkge1xuICAgIGlmIChmdW4gPT0gbnVsbCkge1xuICAgICAgcmV0dXJuIGNvbGxlY3Rpb24ubGVuZ3RoO1xuICAgIH0gZWxzZSB7XG4gICAgICByZXR1cm4gY29sbGVjdGlvbi5maWx0ZXIoZnVuKS5sZW5ndGg7XG4gICAgfVxuICB9LFxuXG4gIGRyb3A6IGZ1bmN0aW9uIChjb2xsZWN0aW9uLCBjb3VudCkge1xuICAgIHJldHVybiBjb2xsZWN0aW9uLnNsaWNlKGNvdW50KTtcbiAgfSxcblxuICBkcm9wX3doaWxlOiBmdW5jdGlvbiAoY29sbGVjdGlvbiwgZnVuKSB7XG4gICAgbGV0IGNvdW50ID0gMDtcblxuICAgIGZvciAobGV0IGVsZW0gb2YgY29sbGVjdGlvbikge1xuICAgICAgaWYgKGZ1bihlbGVtKSkge1xuICAgICAgICBjb3VudCA9IGNvdW50ICsgMTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIGJyZWFrO1xuICAgICAgfVxuICAgIH1cblxuICAgIHJldHVybiBjb2xsZWN0aW9uLnNsaWNlKGNvdW50KTtcbiAgfSxcblxuICBlYWNoOiBmdW5jdGlvbiAoY29sbGVjdGlvbiwgZnVuKSB7XG4gICAgZm9yIChsZXQgZWxlbSBvZiBjb2xsZWN0aW9uKSB7XG4gICAgICBmdW4oZWxlbSk7XG4gICAgfVxuICB9LFxuXG4gIGVtcHR5X19xbWFya19fOiBmdW5jdGlvbiAoY29sbGVjdGlvbikge1xuICAgIHJldHVybiBjb2xsZWN0aW9uLmxlbmd0aCA9PT0gMDtcbiAgfSxcblxuICBmZXRjaDogZnVuY3Rpb24gKGNvbGxlY3Rpb24sIG4pIHtcbiAgICBpZiAoS2VybmVsLmlzX2xpc3QoY29sbGVjdGlvbikpIHtcbiAgICAgIGlmIChuIDwgdGhpcy5jb3VudChjb2xsZWN0aW9uKSAmJiBuID49IDApIHtcbiAgICAgICAgcmV0dXJuIEtlcm5lbC5TcGVjaWFsRm9ybXMudHVwbGUoS2VybmVsLlNwZWNpYWxGb3Jtcy5hdG9tKFwib2tcIiksIGNvbGxlY3Rpb25bbl0pO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgcmV0dXJuIEtlcm5lbC5TcGVjaWFsRm9ybXMuYXRvbShcImVycm9yXCIpO1xuICAgICAgfVxuICAgIH1cblxuICAgIHRocm93IG5ldyBFcnJvcihcImNvbGxlY3Rpb24gaXMgbm90IGFuIEVudW1lcmFibGVcIik7XG4gIH0sXG5cbiAgZmV0Y2hfX2VtYXJrX186IGZ1bmN0aW9uIChjb2xsZWN0aW9uLCBuKSB7XG4gICAgaWYgKEtlcm5lbC5pc19saXN0KGNvbGxlY3Rpb24pKSB7XG4gICAgICBpZiAobiA8IHRoaXMuY291bnQoY29sbGVjdGlvbikgJiYgbiA+PSAwKSB7XG4gICAgICAgIHJldHVybiBjb2xsZWN0aW9uW25dO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKFwib3V0IG9mIGJvdW5kcyBlcnJvclwiKTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICB0aHJvdyBuZXcgRXJyb3IoXCJjb2xsZWN0aW9uIGlzIG5vdCBhbiBFbnVtZXJhYmxlXCIpO1xuICB9LFxuXG4gIGZpbHRlcjogZnVuY3Rpb24gKGNvbGxlY3Rpb24sIGZ1bikge1xuICAgIGxldCByZXN1bHQgPSBbXTtcblxuICAgIGZvciAobGV0IGVsZW0gb2YgY29sbGVjdGlvbikge1xuICAgICAgaWYgKGZ1bihlbGVtKSkge1xuICAgICAgICByZXN1bHQucHVzaChlbGVtKTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICByZXR1cm4gcmVzdWx0O1xuICB9LFxuXG4gIGZpbHRlcl9tYXA6IGZ1bmN0aW9uIChjb2xsZWN0aW9uLCBmaWx0ZXIsIG1hcHBlcikge1xuICAgIHJldHVybiBFbnVtLm1hcChFbnVtLmZpbHRlcihjb2xsZWN0aW9uLCBmaWx0ZXIpLCBtYXBwZXIpO1xuICB9LFxuXG4gIGZpbmQ6IGZ1bmN0aW9uIChjb2xsZWN0aW9uLCBpZl9ub25lID0gbnVsbCwgZnVuKSB7XG4gICAgZm9yIChsZXQgZWxlbSBvZiBjb2xsZWN0aW9uKSB7XG4gICAgICBpZiAoZnVuKGVsZW0pKSB7XG4gICAgICAgIHJldHVybiBlbGVtO1xuICAgICAgfVxuICAgIH1cblxuICAgIHJldHVybiBpZl9ub25lO1xuICB9LFxuXG4gIGludG86IGZ1bmN0aW9uIChjb2xsZWN0aW9uLCBsaXN0KSB7XG4gICAgcmV0dXJuIGxpc3QuY29uY2F0KGNvbGxlY3Rpb24pO1xuICB9LFxuXG4gIG1hcDogZnVuY3Rpb24gKGNvbGxlY3Rpb24sIGZ1bikge1xuICAgIGxldCByZXN1bHQgPSBbXTtcblxuICAgIGZvciAobGV0IGVsZW0gb2YgY29sbGVjdGlvbikge1xuICAgICAgcmVzdWx0LnB1c2goZnVuKGVsZW0pKTtcbiAgICB9XG5cbiAgICByZXR1cm4gcmVzdWx0O1xuICB9LFxuXG4gIG1hcF9yZWR1Y2U6IGZ1bmN0aW9uIChjb2xsZWN0aW9uLCBhY2MsIGZ1bikge1xuICAgIGxldCBtYXBwZWQgPSBLZXJuZWwuU3BlY2lhbEZvcm1zLmxpc3QoKTtcbiAgICBsZXQgdGhlX2FjYyA9IGFjYztcblxuICAgIGZvciAodmFyIGkgPSAwOyBpIDwgdGhpcy5jb3VudChjb2xsZWN0aW9uKTsgaSsrKSB7XG4gICAgICBsZXQgdHVwbGUgPSBmdW4oY29sbGVjdGlvbltpXSwgdGhlX2FjYyk7XG5cbiAgICAgIHRoZV9hY2MgPSBLZXJuZWwuZWxlbSh0dXBsZSwgMSk7XG4gICAgICBtYXBwZWQgPSBLZXJuZWwuU3BlY2lhbEZvcm1zLmxpc3QoLi4ubWFwcGVkLmNvbmNhdChbS2VybmVsLmVsZW0odHVwbGUsIDApXSkpO1xuICAgIH1cblxuICAgIHJldHVybiBLZXJuZWwuU3BlY2lhbEZvcm1zLnR1cGxlKG1hcHBlZCwgdGhlX2FjYyk7XG4gIH0sXG5cbiAgbWVtYmVyOiBmdW5jdGlvbiAoY29sbGVjdGlvbiwgdmFsdWUpIHtcbiAgICByZXR1cm4gY29sbGVjdGlvbi5pbmNsdWRlcyh2YWx1ZSk7XG4gIH0sXG5cbiAgcmVkdWNlOiBmdW5jdGlvbiAoY29sbGVjdGlvbiwgYWNjLCBmdW4pIHtcbiAgICBsZXQgdGhlX2FjYyA9IGFjYztcblxuICAgIGZvciAodmFyIGkgPSAwOyBpIDwgdGhpcy5jb3VudChjb2xsZWN0aW9uKTsgaSsrKSB7XG4gICAgICBsZXQgdHVwbGUgPSBmdW4oY29sbGVjdGlvbltpXSwgdGhlX2FjYyk7XG5cbiAgICAgIHRoZV9hY2MgPSBLZXJuZWwuZWxlbSh0dXBsZSwgMSk7XG4gICAgfVxuXG4gICAgcmV0dXJuIHRoZV9hY2M7XG4gIH0sXG5cbiAgdGFrZTogZnVuY3Rpb24gKGNvbGxlY3Rpb24sIGNvdW50KSB7XG4gICAgcmV0dXJuIGNvbGxlY3Rpb24uc2xpY2UoMCwgY291bnQpO1xuICB9LFxuXG4gIHRha2VfZXZlcnk6IGZ1bmN0aW9uIChjb2xsZWN0aW9uLCBudGgpIHtcbiAgICBsZXQgcmVzdWx0ID0gW107XG4gICAgbGV0IGluZGV4ID0gMDtcblxuICAgIGZvciAobGV0IGVsZW0gb2YgY29sbGVjdGlvbikge1xuICAgICAgaWYgKGluZGV4ICUgbnRoID09PSAwKSB7XG4gICAgICAgIHJlc3VsdC5wdXNoKGVsZW0pO1xuICAgICAgfVxuICAgIH1cblxuICAgIHJldHVybiBLZXJuZWwuU3BlY2lhbEZvcm1zLmxpc3QoLi4ucmVzdWx0KTtcbiAgfSxcblxuICB0YWtlX3doaWxlOiBmdW5jdGlvbiAoY29sbGVjdGlvbiwgZnVuKSB7XG4gICAgbGV0IGNvdW50ID0gMDtcblxuICAgIGZvciAobGV0IGVsZW0gb2YgY29sbGVjdGlvbikge1xuICAgICAgaWYgKGZ1bihlbGVtKSkge1xuICAgICAgICBjb3VudCA9IGNvdW50ICsgMTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIGJyZWFrO1xuICAgICAgfVxuICAgIH1cblxuICAgIHJldHVybiBjb2xsZWN0aW9uLnNsaWNlKDAsIGNvdW50KTtcbiAgfSxcblxuICB0b19saXN0OiBmdW5jdGlvbiAoY29sbGVjdGlvbikge1xuICAgIHJldHVybiBjb2xsZWN0aW9uO1xuICB9XG59O1xuXG5sZXQgU3BlY2lhbEZvcm1zID0ge1xuXG4gIF9fRElSX186IGZ1bmN0aW9uICgpIHtcbiAgICBpZiAoX19kaXJuYW1lKSB7XG4gICAgICByZXR1cm4gX19kaXJuYW1lO1xuICAgIH1cblxuICAgIGlmIChkb2N1bWVudC5jdXJyZW50U2NyaXB0KSB7XG4gICAgICByZXR1cm4gZG9jdW1lbnQuY3VycmVudFNjcmlwdC5zcmM7XG4gICAgfVxuXG4gICAgcmV0dXJuIG51bGw7XG4gIH0sXG5cbiAgYXRvbTogZnVuY3Rpb24gKF92YWx1ZSkge1xuICAgIHJldHVybiBTeW1ib2wuZm9yKF92YWx1ZSk7XG4gIH0sXG5cbiAgbGlzdDogZnVuY3Rpb24gKC4uLmFyZ3MpIHtcbiAgICByZXR1cm4gT2JqZWN0LmZyZWV6ZShhcmdzKTtcbiAgfSxcblxuICBiaXRzdHJpbmc6IGZ1bmN0aW9uICguLi5hcmdzKSB7XG4gICAgcmV0dXJuIG5ldyBCaXRTdHJpbmcoLi4uYXJncyk7XG4gIH0sXG5cbiAgYm91bmQ6IGZ1bmN0aW9uIChfdmFyKSB7XG4gICAgcmV0dXJuIGJvdW5kKF92YXIpO1xuICB9LFxuXG4gIF9jYXNlOiBmdW5jdGlvbiAoY29uZGl0aW9uLCBjbGF1c2VzKSB7XG4gICAgcmV0dXJuIGRlZm1hdGNoKC4uLmNsYXVzZXMpKGNvbmRpdGlvbik7XG4gIH0sXG5cbiAgY29uZDogZnVuY3Rpb24gKGNsYXVzZXMpIHtcbiAgICBmb3IgKGxldCBjbGF1c2Ugb2YgY2xhdXNlcykge1xuICAgICAgaWYgKGNsYXVzZVswXSkge1xuICAgICAgICByZXR1cm4gY2xhdXNlWzFdKCk7XG4gICAgICB9XG4gICAgfVxuXG4gICAgdGhyb3cgbmV3IEVycm9yKCk7XG4gIH0sXG5cbiAgZm46IGZ1bmN0aW9uIChjbGF1c2VzKSB7XG4gICAgcmV0dXJuIGRlZm1hdGNoKGNsYXVzZXMpO1xuICB9LFxuXG4gIG1hcDogZnVuY3Rpb24gKG9iaikge1xuICAgIHJldHVybiBPYmplY3QuZnJlZXplKG9iaik7XG4gIH0sXG5cbiAgbWFwX3VwZGF0ZTogZnVuY3Rpb24gKG1hcCwgdmFsdWVzKSB7XG4gICAgcmV0dXJuIE9iamVjdC5mcmVlemUoT2JqZWN0LmFzc2lnbihPYmplY3QuY3JlYXRlKG1hcC5jb25zdHJ1Y3Rvci5wcm90b3R5cGUpLCBtYXAsIHZhbHVlcykpO1xuICB9LFxuXG4gIF9mb3I6IGZ1bmN0aW9uIChjb2xsZWN0aW9ucywgZnVuLCBmaWx0ZXIgPSAoKSA9PiB0cnVlLCBpbnRvID0gW10sIHByZXZpb3VzVmFsdWVzID0gW10pIHtcbiAgICBsZXQgcGF0dGVybiA9IGNvbGxlY3Rpb25zWzBdWzBdO1xuICAgIGxldCBjb2xsZWN0aW9uID0gY29sbGVjdGlvbnNbMF1bMV07XG5cbiAgICBpZiAoY29sbGVjdGlvbnMubGVuZ3RoID09PSAxKSB7XG5cbiAgICAgIGZvciAobGV0IGVsZW0gb2YgY29sbGVjdGlvbikge1xuICAgICAgICBsZXQgciA9IG1hdGNoX25vX3Rocm93KHBhdHRlcm4sIGVsZW0pO1xuICAgICAgICBsZXQgYXJncyA9IHByZXZpb3VzVmFsdWVzLmNvbmNhdChyKTtcblxuICAgICAgICBpZiAociAmJiBmaWx0ZXIuYXBwbHkodGhpcywgYXJncykpIHtcbiAgICAgICAgICBpbnRvID0gRW51bS5pbnRvKFtmdW4uYXBwbHkodGhpcywgYXJncyldLCBpbnRvKTtcbiAgICAgICAgfVxuICAgICAgfVxuXG4gICAgICByZXR1cm4gaW50bztcbiAgICB9IGVsc2Uge1xuICAgICAgbGV0IF9pbnRvID0gW107XG5cbiAgICAgIGZvciAobGV0IGVsZW0gb2YgY29sbGVjdGlvbikge1xuICAgICAgICBsZXQgciA9IG1hdGNoX25vX3Rocm93KHBhdHRlcm4sIGVsZW0pO1xuICAgICAgICBpZiAocikge1xuICAgICAgICAgIF9pbnRvID0gRW51bS5pbnRvKHRoaXMuX2Zvcihjb2xsZWN0aW9ucy5zbGljZSgxKSwgZnVuLCBmaWx0ZXIsIF9pbnRvLCBwcmV2aW91c1ZhbHVlcy5jb25jYXQocikpLCBpbnRvKTtcbiAgICAgICAgfVxuICAgICAgfVxuXG4gICAgICByZXR1cm4gX2ludG87XG4gICAgfVxuICB9LFxuXG4gIHJlY2VpdmU6IGZ1bmN0aW9uIChyZWNlaXZlX2Z1biwgdGltZW91dF9pbl9tcyA9IG51bGwsIHRpbWVvdXRfZm4gPSB0aW1lID0+IHRydWUpIHtcbiAgICBpZiAodGltZW91dF9pbl9tcyA9PSBudWxsIHx8IHRpbWVvdXRfaW5fbXMgPT09IFN5c3RlbS5mb3IoJ2luZmluaXR5JykpIHtcbiAgICAgIHdoaWxlICh0cnVlKSB7XG4gICAgICAgIGlmIChzZWxmLm1haWxib3gubGVuZ3RoICE9PSAwKSB7XG4gICAgICAgICAgbGV0IG1lc3NhZ2UgPSBzZWxmLm1haWxib3hbMF07XG4gICAgICAgICAgc2VsZi5tYWlsYm94ID0gc2VsZi5tYWlsYm94LnNsaWNlKDEpO1xuICAgICAgICAgIHJldHVybiByZWNlaXZlX2Z1bihtZXNzYWdlKTtcbiAgICAgICAgfVxuICAgICAgfVxuICAgIH0gZWxzZSBpZiAodGltZW91dF9pbl9tcyA9PT0gMCkge1xuICAgICAgaWYgKHNlbGYubWFpbGJveC5sZW5ndGggIT09IDApIHtcbiAgICAgICAgbGV0IG1lc3NhZ2UgPSBzZWxmLm1haWxib3hbMF07XG4gICAgICAgIHNlbGYubWFpbGJveCA9IHNlbGYubWFpbGJveC5zbGljZSgxKTtcbiAgICAgICAgcmV0dXJuIHJlY2VpdmVfZnVuKG1lc3NhZ2UpO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgcmV0dXJuIG51bGw7XG4gICAgICB9XG4gICAgfSBlbHNlIHtcbiAgICAgIGxldCBub3cgPSBEYXRlLm5vdygpO1xuICAgICAgd2hpbGUgKERhdGUubm93KCkgPCBub3cgKyB0aW1lb3V0X2luX21zKSB7XG4gICAgICAgIGlmIChzZWxmLm1haWxib3gubGVuZ3RoICE9PSAwKSB7XG4gICAgICAgICAgbGV0IG1lc3NhZ2UgPSBzZWxmLm1haWxib3hbMF07XG4gICAgICAgICAgc2VsZi5tYWlsYm94ID0gc2VsZi5tYWlsYm94LnNsaWNlKDEpO1xuICAgICAgICAgIHJldHVybiByZWNlaXZlX2Z1bihtZXNzYWdlKTtcbiAgICAgICAgfVxuICAgICAgfVxuXG4gICAgICByZXR1cm4gdGltZW91dF9mbih0aW1lb3V0X2luX21zKTtcbiAgICB9XG4gIH0sXG5cbiAgdHVwbGU6IGZ1bmN0aW9uICguLi5hcmdzKSB7XG4gICAgcmV0dXJuIG5ldyBUdXBsZSQxKC4uLmFyZ3MpO1xuICB9LFxuXG4gIF90cnk6IGZ1bmN0aW9uIChkb19mdW4sIHJlc2N1ZV9mdW5jdGlvbiwgY2F0Y2hfZnVuLCBlbHNlX2Z1bmN0aW9uLCBhZnRlcl9mdW5jdGlvbikge1xuICAgIGxldCByZXN1bHQgPSBudWxsO1xuXG4gICAgdHJ5IHtcbiAgICAgIHJlc3VsdCA9IGRvX2Z1bigpO1xuICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgIGxldCBleF9yZXN1bHQgPSBudWxsO1xuXG4gICAgICBpZiAocmVzY3VlX2Z1bmN0aW9uKSB7XG4gICAgICAgIHRyeSB7XG4gICAgICAgICAgZXhfcmVzdWx0ID0gcmVzY3VlX2Z1bmN0aW9uKGUpO1xuICAgICAgICAgIHJldHVybiBleF9yZXN1bHQ7XG4gICAgICAgIH0gY2F0Y2ggKGV4KSB7XG4gICAgICAgICAgaWYgKGV4IGluc3RhbmNlb2YgTWF0Y2hFcnJvcikge1xuICAgICAgICAgICAgdGhyb3cgZXg7XG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICB9XG5cbiAgICAgIGlmIChjYXRjaF9mdW4pIHtcbiAgICAgICAgdHJ5IHtcbiAgICAgICAgICBleF9yZXN1bHQgPSBjYXRjaF9mdW4oZSk7XG4gICAgICAgICAgcmV0dXJuIGV4X3Jlc3VsdDtcbiAgICAgICAgfSBjYXRjaCAoZXgpIHtcbiAgICAgICAgICBpZiAoZXggaW5zdGFuY2VvZiBNYXRjaEVycm9yKSB7XG4gICAgICAgICAgICB0aHJvdyBleDtcbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgIH1cblxuICAgICAgdGhyb3cgZTtcbiAgICB9IGZpbmFsbHkge1xuICAgICAgaWYgKGFmdGVyX2Z1bmN0aW9uKSB7XG4gICAgICAgIGFmdGVyX2Z1bmN0aW9uKCk7XG4gICAgICB9XG4gICAgfVxuXG4gICAgaWYgKGVsc2VfZnVuY3Rpb24pIHtcbiAgICAgIHRyeSB7XG4gICAgICAgIHJldHVybiBlbHNlX2Z1bmN0aW9uKHJlc3VsdCk7XG4gICAgICB9IGNhdGNoIChleCkge1xuICAgICAgICBpZiAoZXggaW5zdGFuY2VvZiBNYXRjaEVycm9yKSB7XG4gICAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdObyBNYXRjaCBGb3VuZCBpbiBFbHNlJyk7XG4gICAgICAgIH1cblxuICAgICAgICB0aHJvdyBleDtcbiAgICAgIH1cbiAgICB9IGVsc2Uge1xuICAgICAgcmV0dXJuIHJlc3VsdDtcbiAgICB9XG4gIH1cblxufTtcblxuZnVuY3Rpb24gdG9fc3RyaW5nJDEodHVwbGUpIHtcbiAgcmV0dXJuIHR1cGxlLnRvU3RyaW5nKCk7XG59O1xuXG5mdW5jdGlvbiBkZWxldGVfYXQodHVwbGUsIGluZGV4KSB7XG4gIGxldCBuZXdfbGlzdCA9IFtdO1xuXG4gIGZvciAodmFyIGkgPSAwOyBpIDwgdHVwbGUuY291bnQoKTsgaSsrKSB7XG4gICAgaWYgKGkgIT09IGluZGV4KSB7XG4gICAgICBuZXdfbGlzdC5wdXNoKHR1cGxlLmdldChpKSk7XG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIEtlcm5lbC5TcGVjaWFsRm9ybXMudHVwbGUuYXBwbHkobnVsbCwgbmV3X2xpc3QpO1xufTtcblxuZnVuY3Rpb24gZHVwbGljYXRlKGRhdGEsIHNpemUpIHtcbiAgbGV0IGFycmF5ID0gW107XG5cbiAgZm9yICh2YXIgaSA9IHNpemUgLSAxOyBpID49IDA7IGktLSkge1xuICAgIGFycmF5LnB1c2goZGF0YSk7XG4gIH1cblxuICByZXR1cm4gS2VybmVsLlNwZWNpYWxGb3Jtcy50dXBsZS5hcHBseShudWxsLCBhcnJheSk7XG59O1xuXG5mdW5jdGlvbiBpbnNlcnRfYXQodHVwbGUsIGluZGV4LCB0ZXJtKSB7XG4gIGxldCBuZXdfdHVwbGUgPSBbXTtcblxuICBmb3IgKHZhciBpID0gMDsgaSA8PSB0dXBsZS5jb3VudCgpOyBpKyspIHtcbiAgICBpZiAoaSA9PT0gaW5kZXgpIHtcbiAgICAgIG5ld190dXBsZS5wdXNoKHRlcm0pO1xuICAgICAgaSsrO1xuICAgICAgbmV3X3R1cGxlLnB1c2godHVwbGUuZ2V0KGkpKTtcbiAgICB9IGVsc2Uge1xuICAgICAgbmV3X3R1cGxlLnB1c2godHVwbGUuZ2V0KGkpKTtcbiAgICB9XG4gIH1cblxuICByZXR1cm4gS2VybmVsLlNwZWNpYWxGb3Jtcy50dXBsZS5hcHBseShudWxsLCBuZXdfdHVwbGUpO1xufTtcblxuZnVuY3Rpb24gZnJvbV9saXN0KGxpc3QpIHtcbiAgcmV0dXJuIEtlcm5lbC5TcGVjaWFsRm9ybXMudHVwbGUuYXBwbHkobnVsbCwgbGlzdCk7XG59O1xuXG5mdW5jdGlvbiB0b19saXN0KHR1cGxlKSB7XG4gIGxldCBuZXdfbGlzdCA9IFtdO1xuXG4gIGZvciAodmFyIGkgPSAwOyBpIDwgdHVwbGUuY291bnQoKTsgaSsrKSB7XG4gICAgbmV3X2xpc3QucHVzaCh0dXBsZS5nZXQoaSkpO1xuICB9XG5cbiAgcmV0dXJuIEtlcm5lbC5TcGVjaWFsRm9ybXMubGlzdCguLi5uZXdfbGlzdCk7XG59O1xuXG52YXIgVHVwbGUgPSB7XG4gIHRvX3N0cmluZzogdG9fc3RyaW5nJDEsXG4gIGRlbGV0ZV9hdCxcbiAgZHVwbGljYXRlLFxuICBpbnNlcnRfYXQsXG4gIGZyb21fbGlzdCxcbiAgdG9fbGlzdFxufTtcblxuLy9odHRwczovL2dpdGh1Yi5jb20vYWlycG9ydHloL3Byb3RvbW9ycGhpc21cbmNsYXNzIFByb3RvY29sIHtcbiAgY29uc3RydWN0b3Ioc3BlYykge1xuICAgIHRoaXMucmVnaXN0cnkgPSBuZXcgTWFwKCk7XG4gICAgdGhpcy5mYWxsYmFjayA9IG51bGw7XG5cbiAgICBmb3IgKGxldCBmdW5OYW1lIGluIHNwZWMpIHtcbiAgICAgIHRoaXNbZnVuTmFtZV0gPSBjcmVhdGVGdW4oZnVuTmFtZSkuYmluZCh0aGlzKTtcbiAgICB9XG5cbiAgICBmdW5jdGlvbiBjcmVhdGVGdW4oZnVuTmFtZSkge1xuXG4gICAgICByZXR1cm4gZnVuY3Rpb24gKC4uLmFyZ3MpIHtcbiAgICAgICAgbGV0IHRoaW5nID0gYXJnc1swXTtcbiAgICAgICAgbGV0IGZ1biA9IG51bGw7XG5cbiAgICAgICAgaWYgKE51bWJlci5pc0ludGVnZXIodGhpbmcpICYmIHRoaXMuaGFzSW1wbGVtZW50YXRpb24oSW50ZWdlclR5cGUpKSB7XG4gICAgICAgICAgZnVuID0gdGhpcy5yZWdpc3RyeS5nZXQoSW50ZWdlclR5cGUpW2Z1bk5hbWVdO1xuICAgICAgICB9IGVsc2UgaWYgKHR5cGVvZiB0aGluZyA9PT0gXCJudW1iZXJcIiAmJiAhTnVtYmVyLmlzSW50ZWdlcih0aGluZykgJiYgdGhpcy5oYXNJbXBsZW1lbnRhdGlvbihGbG9hdFR5cGUpKSB7XG4gICAgICAgICAgZnVuID0gdGhpcy5yZWdpc3RyeS5nZXQoRmxvYXRUeXBlKVtmdW5OYW1lXTtcbiAgICAgICAgfSBlbHNlIGlmICh0aGlzLmhhc0ltcGxlbWVudGF0aW9uKHRoaW5nKSkge1xuICAgICAgICAgIGZ1biA9IHRoaXMucmVnaXN0cnkuZ2V0KHRoaW5nLmNvbnN0cnVjdG9yKVtmdW5OYW1lXTtcbiAgICAgICAgfSBlbHNlIGlmICh0aGlzLmZhbGxiYWNrKSB7XG4gICAgICAgICAgZnVuID0gdGhpcy5mYWxsYmFja1tmdW5OYW1lXTtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmIChmdW4gIT0gbnVsbCkge1xuICAgICAgICAgIGxldCByZXR2YWwgPSBmdW4uYXBwbHkodGhpcywgYXJncyk7XG4gICAgICAgICAgcmV0dXJuIHJldHZhbDtcbiAgICAgICAgfVxuXG4gICAgICAgIHRocm93IG5ldyBFcnJvcihcIk5vIGltcGxlbWVudGF0aW9uIGZvdW5kIGZvciBcIiArIHRoaW5nKTtcbiAgICAgIH07XG4gICAgfVxuICB9XG5cbiAgaW1wbGVtZW50YXRpb24odHlwZSwgaW1wbGVtZW50YXRpb24pIHtcbiAgICBpZiAodHlwZSA9PT0gbnVsbCkge1xuICAgICAgdGhpcy5mYWxsYmFjayA9IGltcGxlbWVudGF0aW9uO1xuICAgIH0gZWxzZSB7XG4gICAgICB0aGlzLnJlZ2lzdHJ5LnNldCh0eXBlLCBpbXBsZW1lbnRhdGlvbik7XG4gICAgfVxuICB9XG5cbiAgaGFzSW1wbGVtZW50YXRpb24odGhpbmcpIHtcbiAgICByZXR1cm4gdGhpcy5yZWdpc3RyeS5oYXModGhpbmcuY29uc3RydWN0b3IpO1xuICB9XG59XG5cbmZ1bmN0aW9uIHRsKGxpc3QpIHtcbiAgcmV0dXJuIFNwZWNpYWxGb3Jtcy5saXN0KC4uLmxpc3Quc2xpY2UoMSkpO1xufVxuXG5mdW5jdGlvbiBoZChsaXN0KSB7XG4gIHJldHVybiBsaXN0WzBdO1xufVxuXG5mdW5jdGlvbiBpc19uaWwoeCkge1xuICByZXR1cm4geCA9PT0gbnVsbDtcbn1cblxuZnVuY3Rpb24gaXNfYXRvbSh4KSB7XG4gIHJldHVybiB0eXBlb2YgeCA9PT0gJ3N5bWJvbCc7XG59XG5cbmZ1bmN0aW9uIGlzX2JpbmFyeSh4KSB7XG4gIHJldHVybiB0eXBlb2YgeCA9PT0gJ3N0cmluZycgfHwgeCBpbnN0YW5jZW9mIFN0cmluZztcbn1cblxuZnVuY3Rpb24gaXNfYm9vbGVhbih4KSB7XG4gIHJldHVybiB0eXBlb2YgeCA9PT0gJ2Jvb2xlYW4nIHx8IHggaW5zdGFuY2VvZiBCb29sZWFuO1xufVxuXG5mdW5jdGlvbiBpc19mdW5jdGlvbih4LCBhcml0eSA9IC0xKSB7XG4gIHJldHVybiB0eXBlb2YgeCA9PT0gJ2Z1bmN0aW9uJyB8fCB4IGluc3RhbmNlb2YgRnVuY3Rpb247XG59XG5cbmZ1bmN0aW9uIGlzX2Zsb2F0KHgpIHtcbiAgcmV0dXJuIGlzX251bWJlcih4KSAmJiAhTnVtYmVyLmlzSW50ZWdlcih4KTtcbn1cblxuZnVuY3Rpb24gaXNfaW50ZWdlcih4KSB7XG4gIHJldHVybiBOdW1iZXIuaXNJbnRlZ2VyKHgpO1xufVxuXG5mdW5jdGlvbiBpc19saXN0KHgpIHtcbiAgcmV0dXJuIHggaW5zdGFuY2VvZiBBcnJheTtcbn1cblxuZnVuY3Rpb24gaXNfbWFwKHgpIHtcbiAgcmV0dXJuIHR5cGVvZiB4ID09PSAnb2JqZWN0JyB8fCB4IGluc3RhbmNlb2YgT2JqZWN0O1xufVxuXG5mdW5jdGlvbiBpc19udW1iZXIoeCkge1xuICByZXR1cm4gdHlwZW9mIHggPT09ICdudW1iZXInO1xufVxuXG5mdW5jdGlvbiBpc190dXBsZSh4KSB7XG4gIHJldHVybiB4IGluc3RhbmNlb2YgVHVwbGUkMTtcbn1cblxuZnVuY3Rpb24gbGVuZ3RoKHgpIHtcbiAgcmV0dXJuIHgubGVuZ3RoO1xufVxuXG5mdW5jdGlvbiBpc19waWQoeCkge1xuICByZXR1cm4geCBpbnN0YW5jZW9mIFBJRDtcbn1cblxuZnVuY3Rpb24gaXNfcG9ydCh4KSB7XG4gIHJldHVybiBmYWxzZTtcbn1cblxuZnVuY3Rpb24gaXNfcmVmZXJlbmNlKHgpIHtcbiAgcmV0dXJuIGZhbHNlO1xufVxuXG5mdW5jdGlvbiBpc19iaXRzdHJpbmcoeCkge1xuICByZXR1cm4gaXNfYmluYXJ5KHgpIHx8IHggaW5zdGFuY2VvZiBCaXRTdHJpbmc7XG59XG5cbmZ1bmN0aW9uIF9faW5fXyhsZWZ0LCByaWdodCkge1xuICBmb3IgKGxldCB4IG9mIHJpZ2h0KSB7XG4gICAgaWYgKG1hdGNoX19xbWFya19fKGxlZnQsIHgpKSB7XG4gICAgICByZXR1cm4gdHJ1ZTtcbiAgICB9XG4gIH1cblxuICByZXR1cm4gZmFsc2U7XG59XG5cbmZ1bmN0aW9uIGFicyhudW1iZXIpIHtcbiAgcmV0dXJuIE1hdGguYWJzKG51bWJlcik7XG59XG5cbmZ1bmN0aW9uIHJvdW5kKG51bWJlcikge1xuICByZXR1cm4gTWF0aC5yb3VuZChudW1iZXIpO1xufVxuXG5mdW5jdGlvbiBlbGVtKHR1cGxlLCBpbmRleCkge1xuICBpZiAoaXNfbGlzdCh0dXBsZSkpIHtcbiAgICByZXR1cm4gdHVwbGVbaW5kZXhdO1xuICB9XG5cbiAgcmV0dXJuIHR1cGxlLmdldChpbmRleCk7XG59XG5cbmZ1bmN0aW9uIHJlbShsZWZ0LCByaWdodCkge1xuICByZXR1cm4gbGVmdCAlIHJpZ2h0O1xufVxuXG5mdW5jdGlvbiBkaXYobGVmdCwgcmlnaHQpIHtcbiAgcmV0dXJuIGxlZnQgLyByaWdodDtcbn1cblxuZnVuY3Rpb24gYW5kKGxlZnQsIHJpZ2h0KSB7XG4gIHJldHVybiBsZWZ0ICYmIHJpZ2h0O1xufVxuXG5mdW5jdGlvbiBvcihsZWZ0LCByaWdodCkge1xuICByZXR1cm4gbGVmdCB8fCByaWdodDtcbn1cblxuZnVuY3Rpb24gbm90KGFyZykge1xuICByZXR1cm4gIWFyZztcbn1cblxuZnVuY3Rpb24gYXBwbHkoLi4uYXJncykge1xuICBpZiAoYXJncy5sZW5ndGggPT09IDMpIHtcbiAgICBsZXQgbW9kID0gYXJnc1swXTtcbiAgICBsZXQgZnVuYyA9IGFyZ3NbMV07XG4gICAgbGV0IGZ1bmNfYXJncyA9IGFyZ3NbMl07XG4gICAgcmV0dXJuIG1vZFtmdW5jXS5hcHBseShudWxsLCBmdW5jX2FyZ3MpO1xuICB9IGVsc2Uge1xuICAgIGxldCBmdW5jID0gYXJnc1swXTtcbiAgICBsZXQgZnVuY19hcmdzID0gYXJnc1sxXTtcblxuICAgIHJldHVybiBmdW5jLmFwcGx5KG51bGwsIGZ1bmNfYXJncyk7XG4gIH1cbn1cblxuZnVuY3Rpb24gdG9fc3RyaW5nKGFyZykge1xuICBpZiAoaXNfdHVwbGUoYXJnKSkge1xuICAgIHJldHVybiBUdXBsZS50b19zdHJpbmcoYXJnKTtcbiAgfVxuXG4gIHJldHVybiBhcmcudG9TdHJpbmcoKTtcbn1cblxuZnVuY3Rpb24gbWF0Y2hfX3FtYXJrX18ocGF0dGVybiwgZXhwciwgZ3VhcmQgPSAoKSA9PiB0cnVlKSB7XG4gIHJldHVybiBtYXRjaF9ub190aHJvdyhwYXR0ZXJuLCBleHByLCBndWFyZCkgIT0gbnVsbDtcbn1cblxuZnVuY3Rpb24gZGVmc3RydWN0KGRlZmF1bHRzKSB7XG4gIHJldHVybiBjbGFzcyB7XG4gICAgY29uc3RydWN0b3IodXBkYXRlID0ge30pIHtcbiAgICAgIGxldCB0aGVfdmFsdWVzID0gT2JqZWN0LmFzc2lnbihkZWZhdWx0cywgdXBkYXRlKTtcbiAgICAgIE9iamVjdC5hc3NpZ24odGhpcywgdGhlX3ZhbHVlcyk7XG4gICAgfVxuXG4gICAgc3RhdGljIGNyZWF0ZSh1cGRhdGVzID0ge30pIHtcbiAgICAgIGxldCB4ID0gbmV3IHRoaXModXBkYXRlcyk7XG4gICAgICByZXR1cm4gT2JqZWN0LmZyZWV6ZSh4KTtcbiAgICB9XG4gIH07XG59XG5cbmZ1bmN0aW9uIGRlZnByb3RvY29sKHNwZWMpIHtcbiAgcmV0dXJuIG5ldyBQcm90b2NvbChzcGVjKTtcbn1cblxuZnVuY3Rpb24gZGVmaW1wbChwcm90b2NvbCwgdHlwZSwgaW1wbCkge1xuICBwcm90b2NvbC5pbXBsZW1lbnRhdGlvbih0eXBlLCBpbXBsKTtcbn1cblxudmFyIEtlcm5lbCA9IHtcbiAgU3BlY2lhbEZvcm1zLFxuICB0bCxcbiAgaGQsXG4gIGlzX25pbCxcbiAgaXNfYXRvbSxcbiAgaXNfYmluYXJ5LFxuICBpc19ib29sZWFuLFxuICBpc19mdW5jdGlvbixcbiAgaXNfZmxvYXQsXG4gIGlzX2ludGVnZXIsXG4gIGlzX2xpc3QsXG4gIGlzX21hcCxcbiAgaXNfbnVtYmVyLFxuICBpc190dXBsZSxcbiAgbGVuZ3RoLFxuICBpc19waWQsXG4gIGlzX3BvcnQsXG4gIGlzX3JlZmVyZW5jZSxcbiAgaXNfYml0c3RyaW5nLFxuICBpbjogX19pbl9fLFxuICBhYnMsXG4gIHJvdW5kLFxuICBlbGVtLFxuICByZW0sXG4gIGRpdixcbiAgYW5kLFxuICBvcixcbiAgbm90LFxuICBhcHBseSxcbiAgdG9fc3RyaW5nLFxuICBtYXRjaF9fcW1hcmtfXyxcbiAgZGVmc3RydWN0LFxuICBkZWZwcm90b2NvbCxcbiAgZGVmaW1wbFxufTtcblxubGV0IEF0b20gPSB7fTtcblxuQXRvbS50b19zdHJpbmcgPSBmdW5jdGlvbiAoYXRvbSkge1xuICByZXR1cm4gU3ltYm9sLmtleUZvcihhdG9tKTtcbn07XG5cbkF0b20udG9fY2hhcl9saXN0ID0gZnVuY3Rpb24gKGF0b20pIHtcbiAgcmV0dXJuIEF0b20udG9fc3RyaW5nKGF0b20pLnNwbGl0KCcnKTtcbn07XG5cbmxldCBJbnRlZ2VyID0ge1xuXG4gIGlzX2V2ZW46IGZ1bmN0aW9uIChuKSB7XG4gICAgcmV0dXJuIG4gJSAyID09PSAwO1xuICB9LFxuXG4gIGlzX29kZDogZnVuY3Rpb24gKG4pIHtcbiAgICByZXR1cm4gbiAlIDIgIT09IDA7XG4gIH0sXG5cbiAgcGFyc2U6IGZ1bmN0aW9uIChiaW4pIHtcbiAgICBsZXQgcmVzdWx0ID0gcGFyc2VJbnQoYmluKTtcblxuICAgIGlmIChpc05hTihyZXN1bHQpKSB7XG4gICAgICByZXR1cm4gS2VybmVsLlNwZWNpYWxGb3Jtcy5hdG9tKFwiZXJyb3JcIik7XG4gICAgfVxuXG4gICAgbGV0IGluZGV4T2ZEb3QgPSBiaW4uaW5kZXhPZihcIi5cIik7XG5cbiAgICBpZiAoaW5kZXhPZkRvdCA+PSAwKSB7XG4gICAgICByZXR1cm4gS2VybmVsLlNwZWNpYWxGb3Jtcy50dXBsZShyZXN1bHQsIGJpbi5zdWJzdHJpbmcoaW5kZXhPZkRvdCkpO1xuICAgIH1cblxuICAgIHJldHVybiBLZXJuZWwuU3BlY2lhbEZvcm1zLnR1cGxlKHJlc3VsdCwgXCJcIik7XG4gIH0sXG5cbiAgdG9fY2hhcl9saXN0OiBmdW5jdGlvbiAobnVtYmVyLCBiYXNlID0gMTApIHtcbiAgICByZXR1cm4gbnVtYmVyLnRvU3RyaW5nKGJhc2UpLnNwbGl0KFwiXCIpO1xuICB9LFxuXG4gIHRvX3N0cmluZzogZnVuY3Rpb24gKG51bWJlciwgYmFzZSA9IDEwKSB7XG4gICAgcmV0dXJuIG51bWJlci50b1N0cmluZyhiYXNlKTtcbiAgfVxufTtcblxubGV0IENoYXJzJDEgPSBLZXJuZWwuZGVmcHJvdG9jb2woe1xuICB0b19zdHJpbmc6IGZ1bmN0aW9uICh0aGluZykge31cbn0pO1xuXG5LZXJuZWwuZGVmaW1wbChDaGFycyQxLCBCaXRTdHJpbmcsIHtcbiAgdG9fc3RyaW5nOiBmdW5jdGlvbiAodGhpbmcpIHtcbiAgICBpZiAoS2VybmVsLmlzX2JpbmFyeSh0aGluZykpIHtcbiAgICAgIHJldHVybiB0aGluZztcbiAgICB9XG5cbiAgICByZXR1cm4gdGhpbmcudG9TdHJpbmcoKTtcbiAgfVxufSk7XG5cbktlcm5lbC5kZWZpbXBsKENoYXJzJDEsIFN5bWJvbCwge1xuICB0b19zdHJpbmc6IGZ1bmN0aW9uICh0aGluZykge1xuICAgIGlmIChuaWwpIHtcbiAgICAgIHJldHVybiBcIlwiO1xuICAgIH1cblxuICAgIHJldHVybiBBdG9tLnRvX3N0cmluZyh0aGluZyk7XG4gIH1cbn0pO1xuXG5LZXJuZWwuZGVmaW1wbChDaGFycyQxLCBJbnRlZ2VyVHlwZSwge1xuICB0b19zdHJpbmc6IGZ1bmN0aW9uICh0aGluZykge1xuICAgIHJldHVybiBJbnRlZ2VyLnRvX3N0cmluZyh0aGluZyk7XG4gIH1cbn0pO1xuXG5LZXJuZWwuZGVmaW1wbChDaGFycyQxLCBGbG9hdFR5cGUsIHtcbiAgdG9fc3RyaW5nOiBmdW5jdGlvbiAodGhpbmcpIHtcbiAgICByZXR1cm4gdGhpbmcudG9TdHJpbmc7XG4gIH1cbn0pO1xuXG5LZXJuZWwuZGVmaW1wbChDaGFycyQxLCBBcnJheSwge1xuICB0b19zdHJpbmc6IGZ1bmN0aW9uICh0aGluZykge1xuICAgIHJldHVybiB0aGluZy50b1N0cmluZygpO1xuICB9XG59KTtcblxuS2VybmVsLmRlZmltcGwoQ2hhcnMkMSwgVHVwbGUkMSwge1xuICB0b19zdHJpbmc6IGZ1bmN0aW9uICh0aGluZykge1xuICAgIHJldHVybiBUdXBsZS50b19zdHJpbmcodGhpbmcpO1xuICB9XG59KTtcblxuS2VybmVsLmRlZmltcGwoQ2hhcnMkMSwgbnVsbCwge1xuICB0b19zdHJpbmc6IGZ1bmN0aW9uICh0aGluZykge1xuICAgIHJldHVybiB0aGluZy50b1N0cmluZygpO1xuICB9XG59KTtcblxuZnVuY3Rpb24gdG9fYXRvbShzdHJpbmcpIHtcbiAgcmV0dXJuIFN5bWJvbC5mb3Ioc3RyaW5nKTtcbn1cblxuZnVuY3Rpb24gdG9fZXhpc3RpbmdfYXRvbShzdHJpbmcpIHtcbiAgcmV0dXJuIFN5bWJvbC5mb3Ioc3RyaW5nKTtcbn1cblxuZnVuY3Rpb24gdG9fY2hhcl9saXN0KHN0cmluZykge1xuICByZXR1cm4gc3RyaW5nLnNwbGl0KCcnKTtcbn1cblxuZnVuY3Rpb24gdG9fZmxvYXQoc3RyaW5nKSB7XG4gIHJldHVybiBwYXJzZUZsb2F0KHN0cmluZyk7XG59XG5cbmZ1bmN0aW9uIHRvX2ludGVnZXIoc3RyaW5nLCBiYXNlID0gMTApIHtcbiAgcmV0dXJuIHBhcnNlSW50KHN0cmluZywgYmFzZSk7XG59XG5cbmZ1bmN0aW9uIHVwY2FzZShiaW5hcnkpIHtcbiAgcmV0dXJuIGJpbmFyeS50b1VwcGVyQ2FzZSgpO1xufVxuXG5mdW5jdGlvbiBkb3duY2FzZShiaW5hcnkpIHtcbiAgcmV0dXJuIGJpbmFyeS50b0xvd2VyQ2FzZSgpO1xufVxuXG5mdW5jdGlvbiBhdChzdHJpbmcsIHBvc2l0aW9uKSB7XG4gIGlmIChwb3NpdGlvbiA+IHN0cmluZy5sZW5ndGggLSAxKSB7XG4gICAgcmV0dXJuIG51bGw7XG4gIH1cblxuICByZXR1cm4gc3RyaW5nW3Bvc2l0aW9uXTtcbn1cblxuZnVuY3Rpb24gY2FwaXRhbGl6ZShzdHJpbmcpIHtcbiAgbGV0IHJldHVyblN0cmluZyA9ICcnO1xuXG4gIGZvciAobGV0IGkgPSAwOyBpIDwgc3RyaW5nLmxlbmd0aDsgaSsrKSB7XG4gICAgaWYgKGkgPT09IDApIHtcbiAgICAgIHJldHVyblN0cmluZyA9IHJldHVyblN0cmluZyArIHN0cmluZ1tpXS50b1VwcGVyQ2FzZSgpO1xuICAgIH0gZWxzZSB7XG4gICAgICByZXR1cm5TdHJpbmcgPSByZXR1cm5TdHJpbmcgKyBzdHJpbmdbaV0udG9Mb3dlckNhc2UoKTtcbiAgICB9XG4gIH1cblxuICByZXR1cm4gcmV0dXJuU3RyaW5nO1xufVxuXG5mdW5jdGlvbiBjb2RlcG9pbnRzKHN0cmluZykge1xuICByZXR1cm4gdG9fY2hhcl9saXN0KHN0cmluZykubWFwKGZ1bmN0aW9uIChjKSB7XG4gICAgcmV0dXJuIGMuY29kZVBvaW50QXQoMCk7XG4gIH0pO1xufVxuXG5mdW5jdGlvbiBjb250YWluc19fcW1fXyhzdHJpbmcsIGNvbnRhaW5zKSB7XG4gIGlmIChBcnJheS5pc0FycmF5KGNvbnRhaW5zKSkge1xuICAgIHJldHVybiBjb250YWlucy5zb21lKGZ1bmN0aW9uIChzKSB7XG4gICAgICByZXR1cm4gc3RyaW5nLmluZGV4T2YocykgPiAtMTtcbiAgICB9KTtcbiAgfVxuXG4gIHJldHVybiBzdHJpbmcuaW5kZXhPZihjb250YWlucykgPiAtMTtcbn1cblxuZnVuY3Rpb24gZHVwbGljYXRlJDEoc3ViamVjdCwgbikge1xuICByZXR1cm4gc3ViamVjdC5yZXBlYXQobik7XG59XG5cbmZ1bmN0aW9uIGVuZHNfd2l0aF9fcW1fXyhzdHJpbmcsIHN1ZmZpeGVzKSB7XG4gIGlmIChBcnJheS5pc0FycmF5KHN1ZmZpeGVzKSkge1xuICAgIHJldHVybiBzdWZmaXhlcy5zb21lKGZ1bmN0aW9uIChzKSB7XG4gICAgICByZXR1cm4gc3RyaW5nLmVuZHNXaXRoKHMpO1xuICAgIH0pO1xuICB9XG5cbiAgcmV0dXJuIHN0cmluZy5lbmRzV2l0aChzdWZmaXhlcyk7XG59XG5cbmZ1bmN0aW9uIGZpcnN0KHN0cmluZykge1xuICBpZiAoIXN0cmluZykge1xuICAgIHJldHVybiBudWxsO1xuICB9XG5cbiAgcmV0dXJuIHN0cmluZ1swXTtcbn1cblxuZnVuY3Rpb24gZ3JhcGhlbWVzKHN0cmluZykge1xuICByZXR1cm4gc3RyaW5nLnNwbGl0KCcnKTtcbn1cblxuZnVuY3Rpb24gbGFzdChzdHJpbmcpIHtcbiAgaWYgKCFzdHJpbmcpIHtcbiAgICByZXR1cm4gbnVsbDtcbiAgfVxuXG4gIHJldHVybiBzdHJpbmdbc3RyaW5nLmxlbmd0aCAtIDFdO1xufVxuXG5mdW5jdGlvbiBsZW5ndGgkMShzdHJpbmcpIHtcbiAgcmV0dXJuIHN0cmluZy5sZW5ndGg7XG59XG5cbmZ1bmN0aW9uIG1hdGNoX19xbV9fKHN0cmluZywgcmVnZXgpIHtcbiAgcmV0dXJuIHN0cmluZy5tYXRjaChyZWdleCkgIT0gbnVsbDtcbn1cblxuZnVuY3Rpb24gbmV4dF9jb2RlcG9pbnQoc3RyaW5nKSB7XG4gIGlmICghc3RyaW5nIHx8IHN0cmluZyA9PT0gJycpIHtcbiAgICByZXR1cm4gbnVsbDtcbiAgfVxuXG4gIHJldHVybiBLZXJuZWwuU3BlY2lhbEZvcm1zLnR1cGxlKHN0cmluZ1swXS5jb2RlUG9pbnRBdCgwKSwgc3RyaW5nLnN1YnN0cigxKSk7XG59XG5cbmZ1bmN0aW9uIG5leHRfZ3JhcGhlbWUoc3RyaW5nKSB7XG4gIGlmICghc3RyaW5nIHx8IHN0cmluZyA9PT0gJycpIHtcbiAgICByZXR1cm4gbnVsbDtcbiAgfVxuXG4gIHJldHVybiBLZXJuZWwuU3BlY2lhbEZvcm1zLnR1cGxlKHN0cmluZ1swXSwgc3RyaW5nLnN1YnN0cigxKSk7XG59XG5cbmZ1bmN0aW9uIHJldmVyc2Uoc3RyaW5nKSB7XG4gIGxldCByZXR1cm5WYWx1ZSA9ICcnO1xuXG4gIGZvciAodmFyIGkgPSBzdHJpbmcubGVuZ3RoIC0gMTsgaSA+PSAwOyBpLS0pIHtcbiAgICByZXR1cm5WYWx1ZSA9IHJldHVyblZhbHVlICsgc3RyaW5nW2ldO1xuICB9O1xuXG4gIHJldHVybiByZXR1cm5WYWx1ZTtcbn1cblxuZnVuY3Rpb24gc3BsaXQoc3RyaW5nKSB7XG4gIHJldHVybiBzdHJpbmcuc3BsaXQoKTtcbn1cblxuZnVuY3Rpb24gc3RhcnRzX3dpdGhfX3FtX18oc3RyaW5nLCBwcmVmaXhlcykge1xuICBpZiAoQXJyYXkuaXNBcnJheShwcmVmaXhlcykpIHtcbiAgICByZXR1cm4gcHJlZml4ZXMuc29tZShmdW5jdGlvbiAocykge1xuICAgICAgcmV0dXJuIHN0cmluZy5zdGFydHNXaXRoKHMpO1xuICAgIH0pO1xuICB9XG5cbiAgcmV0dXJuIHN0cmluZy5zdGFydHNXaXRoKHByZWZpeGVzKTtcbn1cblxuZnVuY3Rpb24gdmFsaWRfY2hhcmFjdGVyX19xbV9fKGNvZGVwb2ludCkge1xuICB0cnkge1xuICAgIHJldHVybiBTdHJpbmcuZnJvbUNvZGVQb2ludChjb2RlcG9pbnQpICE9IG51bGw7XG4gIH0gY2F0Y2ggKGUpIHtcbiAgICByZXR1cm4gZmFsc2U7XG4gIH1cbn1cblxudmFyIFN0cmluZyQxID0ge1xuICBhdCxcbiAgY2FwaXRhbGl6ZSxcbiAgY29kZXBvaW50cyxcbiAgY29udGFpbnNfX3FtX18sXG4gIGRvd25jYXNlLFxuICBkdXBsaWNhdGU6IGR1cGxpY2F0ZSQxLFxuICBlbmRzX3dpdGhfX3FtX18sXG4gIGZpcnN0LFxuICBncmFwaGVtZXMsXG4gIGxhc3QsXG4gIGxlbmd0aDogbGVuZ3RoJDEsXG4gIG1hdGNoX19xbV9fLFxuICBuZXh0X2NvZGVwb2ludCxcbiAgbmV4dF9ncmFwaGVtZSxcbiAgcmV2ZXJzZSxcbiAgc3BsaXQsXG4gIHN0YXJ0c193aXRoX19xbV9fLFxuICB0b19hdG9tLFxuICB0b19jaGFyX2xpc3QsXG4gIHRvX2V4aXN0aW5nX2F0b20sXG4gIHRvX2Zsb2F0LFxuICB0b19pbnRlZ2VyLFxuICB1cGNhc2UsXG4gIHZhbGlkX2NoYXJhY3Rlcl9fcW1fXyxcbiAgQ2hhcnM6IENoYXJzJDFcbn07XG5cbmxldCBDaGFycyA9IEtlcm5lbC5kZWZwcm90b2NvbCh7XG4gIHRvX2NoYXJfbGlzdDogZnVuY3Rpb24gKHRoaW5nKSB7fVxufSk7XG5cbktlcm5lbC5kZWZpbXBsKENoYXJzLCBCaXRTdHJpbmcsIHtcbiAgdG9fY2hhcl9saXN0OiBmdW5jdGlvbiAodGhpbmcpIHtcbiAgICBpZiAoS2VybmVsLmlzX2JpbmFyeSh0aGluZykpIHtcbiAgICAgIHJldHVybiBTdHJpbmckMS50b19jaGFyX2xpc3QodGhpbmcpO1xuICAgIH1cblxuICAgIHJldHVybiB0aGluZy50b1N0cmluZygpO1xuICB9XG59KTtcblxuS2VybmVsLmRlZmltcGwoQ2hhcnMsIFN5bWJvbCwge1xuICB0b19jaGFyX2xpc3Q6IGZ1bmN0aW9uICh0aGluZykge1xuICAgIHJldHVybiBBdG9tLnRvX2NoYXJfbGlzdCh0aGluZyk7XG4gIH1cbn0pO1xuXG5LZXJuZWwuZGVmaW1wbChDaGFycywgSW50ZWdlclR5cGUsIHtcbiAgdG9fY2hhcl9saXN0OiBmdW5jdGlvbiAodGhpbmcpIHtcbiAgICByZXR1cm4gSW50ZWdlci50b19jaGFyX2xpc3QodGhpbmcpO1xuICB9XG59KTtcblxuS2VybmVsLmRlZmltcGwoQ2hhcnMsIEFycmF5LCB7XG4gIHRvX2NoYXJfbGlzdDogZnVuY3Rpb24gKHRoaW5nKSB7XG4gICAgcmV0dXJuIHRoaW5nO1xuICB9XG59KTtcblxubGV0IExpc3QgPSB7fTtcblxuTGlzdC5DaGFycyA9IENoYXJzO1xuXG5MaXN0LmRlbGV0ZSA9IGZ1bmN0aW9uIChsaXN0LCBpdGVtKSB7XG4gIGxldCBuZXdfdmFsdWUgPSBbXTtcbiAgbGV0IHZhbHVlX2ZvdW5kID0gZmFsc2U7XG5cbiAgZm9yIChsZXQgeCBvZiBsaXN0KSB7XG4gICAgaWYgKHggPT09IGl0ZW0gJiYgdmFsdWVfZm91bmQgIT09IGZhbHNlKSB7XG4gICAgICBuZXdfdmFsdWUucHVzaCh4KTtcbiAgICAgIHZhbHVlX2ZvdW5kID0gdHJ1ZTtcbiAgICB9IGVsc2UgaWYgKHggIT09IGl0ZW0pIHtcbiAgICAgIG5ld192YWx1ZS5wdXNoKHgpO1xuICAgIH1cbiAgfVxuXG4gIHJldHVybiBLZXJuZWwuU3BlY2lhbEZvcm1zLmxpc3QoLi4ubmV3X3ZhbHVlKTtcbn07XG5cbkxpc3QuZGVsZXRlX2F0ID0gZnVuY3Rpb24gKGxpc3QsIGluZGV4KSB7XG4gIGxldCBuZXdfdmFsdWUgPSBbXTtcblxuICBmb3IgKGxldCBpID0gMDsgaSA8IGxpc3QubGVuZ3RoOyBpKyspIHtcbiAgICBpZiAoaSAhPT0gaW5kZXgpIHtcbiAgICAgIG5ld192YWx1ZS5wdXNoKGxpc3RbaV0pO1xuICAgIH1cbiAgfVxuXG4gIHJldHVybiBLZXJuZWwuU3BlY2lhbEZvcm1zLmxpc3QoLi4ubmV3X3ZhbHVlKTtcbn07XG5cbkxpc3QuZHVwbGljYXRlID0gZnVuY3Rpb24gKGVsZW0sIG4pIHtcbiAgbGV0IG5ld192YWx1ZSA9IFtdO1xuXG4gIGZvciAodmFyIGkgPSAwOyBpIDwgbjsgaSsrKSB7XG4gICAgbmV3X3ZhbHVlLnB1c2goZWxlbSk7XG4gIH1cblxuICByZXR1cm4gS2VybmVsLlNwZWNpYWxGb3Jtcy5saXN0KC4uLm5ld192YWx1ZSk7XG59O1xuXG5MaXN0LmZpcnN0ID0gZnVuY3Rpb24gKGxpc3QpIHtcbiAgcmV0dXJuIGxpc3RbMF07XG59O1xuXG5MaXN0LmZsYXR0ZW4gPSBmdW5jdGlvbiAobGlzdCwgdGFpbCA9IEtlcm5lbC5TcGVjaWFsRm9ybXMubGlzdCgpKSB7XG4gIGxldCBuZXdfdmFsdWUgPSBbXTtcblxuICBmb3IgKGxldCB4IG9mIGxpc3QpIHtcbiAgICBpZiAoS2VybmVsLmlzX2xpc3QoeCkpIHtcbiAgICAgIG5ld192YWx1ZSA9IG5ld192YWx1ZS5jb25jYXQoTGlzdC5mbGF0dGVuKHgpKTtcbiAgICB9IGVsc2Uge1xuICAgICAgbmV3X3ZhbHVlLnB1c2goeCk7XG4gICAgfVxuICB9XG5cbiAgbmV3X3ZhbHVlID0gbmV3X3ZhbHVlLmNvbmNhdCh0YWlsKTtcblxuICByZXR1cm4gS2VybmVsLlNwZWNpYWxGb3Jtcy5saXN0KC4uLm5ld192YWx1ZSk7XG59O1xuXG5MaXN0LmZvbGRsID0gZnVuY3Rpb24gKGxpc3QsIGFjYywgZnVuYykge1xuICByZXR1cm4gbGlzdC5yZWR1Y2UoZnVuYywgYWNjKTtcbn07XG5cbkxpc3QuZm9sZHIgPSBmdW5jdGlvbiAobGlzdCwgYWNjLCBmdW5jKSB7XG4gIGxldCBuZXdfYWNjID0gYWNjO1xuXG4gIGZvciAodmFyIGkgPSBsaXN0Lmxlbmd0aCAtIDE7IGkgPj0gMDsgaS0tKSB7XG4gICAgbmV3X2FjYyA9IGZ1bmMobGlzdFtpXSwgbmV3X2FjYyk7XG4gIH1cblxuICByZXR1cm4gbmV3X2FjYztcbn07XG5cbkxpc3QuaW5zZXJ0X2F0ID0gZnVuY3Rpb24gKGxpc3QsIGluZGV4LCB2YWx1ZSkge1xuICBsZXQgbmV3X3ZhbHVlID0gW107XG5cbiAgZm9yIChsZXQgaSA9IDA7IGkgPCBsaXN0Lmxlbmd0aDsgaSsrKSB7XG4gICAgaWYgKGkgPT09IGluZGV4KSB7XG4gICAgICBuZXdfdmFsdWUucHVzaCh2YWx1ZSk7XG4gICAgICBuZXdfdmFsdWUucHVzaChsaXN0W2ldKTtcbiAgICB9IGVsc2Uge1xuICAgICAgbmV3X3ZhbHVlLnB1c2gobGlzdFtpXSk7XG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIEtlcm5lbC5TcGVjaWFsRm9ybXMubGlzdCguLi5uZXdfdmFsdWUpO1xufTtcblxuTGlzdC5rZXlkZWxldGUgPSBmdW5jdGlvbiAobGlzdCwga2V5LCBwb3NpdGlvbikge1xuICBsZXQgbmV3X2xpc3QgPSBbXTtcblxuICBmb3IgKGxldCBpID0gMDsgaSA8IGxpc3QubGVuZ3RoOyBpKyspIHtcbiAgICBpZiAoIUtlcm5lbC5tYXRjaF9fcW1hcmtfXyhsaXN0W2ldW3Bvc2l0aW9uXSwga2V5KSkge1xuICAgICAgbmV3X2xpc3QucHVzaChsaXN0W2ldKTtcbiAgICB9XG4gIH1cblxuICByZXR1cm4gS2VybmVsLlNwZWNpYWxGb3Jtcy5saXN0KC4uLm5ld19saXN0KTtcbn07XG5cbkxpc3Qua2V5ZmluZCA9IGZ1bmN0aW9uIChsaXN0LCBrZXksIHBvc2l0aW9uLCBfZGVmYXVsdCA9IG51bGwpIHtcblxuICBmb3IgKGxldCBpID0gMDsgaSA8IGxpc3QubGVuZ3RoOyBpKyspIHtcbiAgICBpZiAoS2VybmVsLm1hdGNoX19xbWFya19fKGxpc3RbaV1bcG9zaXRpb25dLCBrZXkpKSB7XG4gICAgICByZXR1cm4gbGlzdFtpXTtcbiAgICB9XG4gIH1cblxuICByZXR1cm4gX2RlZmF1bHQ7XG59O1xuXG5MaXN0LmtleW1lbWJlcl9fcW1hcmtfXyA9IGZ1bmN0aW9uIChsaXN0LCBrZXksIHBvc2l0aW9uKSB7XG5cbiAgZm9yIChsZXQgaSA9IDA7IGkgPCBsaXN0Lmxlbmd0aDsgaSsrKSB7XG4gICAgaWYgKEtlcm5lbC5tYXRjaF9fcW1hcmtfXyhsaXN0W2ldW3Bvc2l0aW9uXSwga2V5KSkge1xuICAgICAgcmV0dXJuIHRydWU7XG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIGZhbHNlO1xufTtcblxuTGlzdC5rZXlyZXBsYWNlID0gZnVuY3Rpb24gKGxpc3QsIGtleSwgcG9zaXRpb24sIG5ld190dXBsZSkge1xuICBsZXQgbmV3X2xpc3QgPSBbXTtcblxuICBmb3IgKGxldCBpID0gMDsgaSA8IGxpc3QubGVuZ3RoOyBpKyspIHtcbiAgICBpZiAoIUtlcm5lbC5tYXRjaF9fcW1hcmtfXyhsaXN0W2ldW3Bvc2l0aW9uXSwga2V5KSkge1xuICAgICAgbmV3X2xpc3QucHVzaChsaXN0W2ldKTtcbiAgICB9IGVsc2Uge1xuICAgICAgbmV3X2xpc3QucHVzaChuZXdfdHVwbGUpO1xuICAgIH1cbiAgfVxuXG4gIHJldHVybiBLZXJuZWwuU3BlY2lhbEZvcm1zLmxpc3QoLi4ubmV3X2xpc3QpO1xufTtcblxuTGlzdC5rZXlzb3J0ID0gZnVuY3Rpb24gKGxpc3QsIHBvc2l0aW9uKSB7XG4gIGxldCBuZXdfbGlzdCA9IGxpc3Q7XG5cbiAgbmV3X2xpc3Quc29ydChmdW5jdGlvbiAoYSwgYikge1xuICAgIGlmIChwb3NpdGlvbiA9PT0gMCkge1xuICAgICAgaWYgKGFbcG9zaXRpb25dLnZhbHVlIDwgYltwb3NpdGlvbl0udmFsdWUpIHtcbiAgICAgICAgcmV0dXJuIC0xO1xuICAgICAgfVxuXG4gICAgICBpZiAoYVtwb3NpdGlvbl0udmFsdWUgPiBiW3Bvc2l0aW9uXS52YWx1ZSkge1xuICAgICAgICByZXR1cm4gMTtcbiAgICAgIH1cblxuICAgICAgcmV0dXJuIDA7XG4gICAgfSBlbHNlIHtcbiAgICAgIGlmIChhW3Bvc2l0aW9uXSA8IGJbcG9zaXRpb25dKSB7XG4gICAgICAgIHJldHVybiAtMTtcbiAgICAgIH1cblxuICAgICAgaWYgKGFbcG9zaXRpb25dID4gYltwb3NpdGlvbl0pIHtcbiAgICAgICAgcmV0dXJuIDE7XG4gICAgICB9XG5cbiAgICAgIHJldHVybiAwO1xuICAgIH1cbiAgfSk7XG5cbiAgcmV0dXJuIEtlcm5lbC5TcGVjaWFsRm9ybXMubGlzdCguLi5uZXdfbGlzdCk7XG59O1xuXG5MaXN0LmtleXN0b3JlID0gZnVuY3Rpb24gKGxpc3QsIGtleSwgcG9zaXRpb24sIG5ld190dXBsZSkge1xuICBsZXQgbmV3X2xpc3QgPSBbXTtcbiAgbGV0IHJlcGxhY2VkID0gZmFsc2U7XG5cbiAgZm9yIChsZXQgaSA9IDA7IGkgPCBsaXN0Lmxlbmd0aDsgaSsrKSB7XG4gICAgaWYgKCFLZXJuZWwubWF0Y2hfX3FtYXJrX18obGlzdFtpXVtwb3NpdGlvbl0sIGtleSkpIHtcbiAgICAgIG5ld19saXN0LnB1c2gobGlzdFtpXSk7XG4gICAgfSBlbHNlIHtcbiAgICAgIG5ld19saXN0LnB1c2gobmV3X3R1cGxlKTtcbiAgICAgIHJlcGxhY2VkID0gdHJ1ZTtcbiAgICB9XG4gIH1cblxuICBpZiAoIXJlcGxhY2VkKSB7XG4gICAgbmV3X2xpc3QucHVzaChuZXdfdHVwbGUpO1xuICB9XG5cbiAgcmV0dXJuIEtlcm5lbC5TcGVjaWFsRm9ybXMubGlzdCguLi5uZXdfbGlzdCk7XG59O1xuXG5MaXN0Lmxhc3QgPSBmdW5jdGlvbiAobGlzdCkge1xuICByZXR1cm4gbGlzdFtsaXN0Lmxlbmd0aCAtIDFdO1xufTtcblxuTGlzdC5yZXBsYWNlX2F0ID0gZnVuY3Rpb24gKGxpc3QsIGluZGV4LCB2YWx1ZSkge1xuICBsZXQgbmV3X3ZhbHVlID0gW107XG5cbiAgZm9yIChsZXQgaSA9IDA7IGkgPCBsaXN0Lmxlbmd0aDsgaSsrKSB7XG4gICAgaWYgKGkgPT09IGluZGV4KSB7XG4gICAgICBuZXdfdmFsdWUucHVzaCh2YWx1ZSk7XG4gICAgfSBlbHNlIHtcbiAgICAgIG5ld192YWx1ZS5wdXNoKGxpc3RbaV0pO1xuICAgIH1cbiAgfVxuXG4gIHJldHVybiBLZXJuZWwuU3BlY2lhbEZvcm1zLmxpc3QoLi4ubmV3X3ZhbHVlKTtcbn07XG5cbkxpc3QudXBkYXRlX2F0ID0gZnVuY3Rpb24gKGxpc3QsIGluZGV4LCBmdW4pIHtcbiAgbGV0IG5ld192YWx1ZSA9IFtdO1xuXG4gIGZvciAobGV0IGkgPSAwOyBpIDwgbGlzdC5jb3VudCgpOyBpKyspIHtcbiAgICBpZiAoaSA9PT0gaW5kZXgpIHtcbiAgICAgIG5ld192YWx1ZS5wdXNoKGZ1bihsaXN0LmdldChpKSkpO1xuICAgIH0gZWxzZSB7XG4gICAgICBuZXdfdmFsdWUucHVzaChsaXN0LmdldChpKSk7XG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIG5ld192YWx1ZTtcbn07XG5cbkxpc3Qud3JhcCA9IGZ1bmN0aW9uIChsaXN0KSB7XG4gIGlmIChLZXJuZWwuaXNfbGlzdChsaXN0KSkge1xuICAgIHJldHVybiBsaXN0O1xuICB9IGVsc2UgaWYgKGxpc3QgPT0gbnVsbCkge1xuICAgIHJldHVybiBLZXJuZWwuU3BlY2lhbEZvcm1zLmxpc3QoKTtcbiAgfSBlbHNlIHtcbiAgICByZXR1cm4gS2VybmVsLlNwZWNpYWxGb3Jtcy5saXN0KGxpc3QpO1xuICB9XG59O1xuXG5MaXN0LnppcCA9IGZ1bmN0aW9uIChsaXN0X29mX2xpc3RzKSB7XG4gIGlmIChsaXN0X29mX2xpc3RzLmxlbmd0aCA9PT0gMCkge1xuICAgIHJldHVybiBLZXJuZWwuU3BlY2lhbEZvcm1zLmxpc3QoKTtcbiAgfVxuXG4gIGxldCBuZXdfdmFsdWUgPSBbXTtcbiAgbGV0IHNtYWxsZXN0X2xlbmd0aCA9IGxpc3Rfb2ZfbGlzdHNbMF07XG5cbiAgZm9yIChsZXQgeCBvZiBsaXN0X29mX2xpc3RzKSB7XG4gICAgaWYgKHgubGVuZ3RoIDwgc21hbGxlc3RfbGVuZ3RoKSB7XG4gICAgICBzbWFsbGVzdF9sZW5ndGggPSB4Lmxlbmd0aDtcbiAgICB9XG4gIH1cblxuICBmb3IgKGxldCBpID0gMDsgaSA8IHNtYWxsZXN0X2xlbmd0aDsgaSsrKSB7XG4gICAgbGV0IGN1cnJlbnRfdmFsdWUgPSBbXTtcbiAgICBmb3IgKGxldCBqID0gMDsgaiA8IGxpc3Rfb2ZfbGlzdHMubGVuZ3RoOyBqKyspIHtcbiAgICAgIGN1cnJlbnRfdmFsdWUucHVzaChsaXN0X29mX2xpc3RzW2pdW2ldKTtcbiAgICB9XG5cbiAgICBuZXdfdmFsdWUucHVzaChLZXJuZWwuU3BlY2lhbEZvcm1zLnR1cGxlKC4uLmN1cnJlbnRfdmFsdWUpKTtcbiAgfVxuXG4gIHJldHVybiBLZXJuZWwuU3BlY2lhbEZvcm1zLmxpc3QoLi4ubmV3X3ZhbHVlKTtcbn07XG5cbkxpc3QudG9fdHVwbGUgPSBmdW5jdGlvbiAobGlzdCkge1xuICByZXR1cm4gS2VybmVsLlNwZWNpYWxGb3Jtcy50dXBsZS5hcHBseShudWxsLCBsaXN0KTtcbn07XG5cbkxpc3QuYXBwZW5kID0gZnVuY3Rpb24gKGxpc3QsIHZhbHVlKSB7XG4gIHJldHVybiBLZXJuZWwuU3BlY2lhbEZvcm1zLmxpc3QoLi4ubGlzdC5jb25jYXQoW3ZhbHVlXSkpO1xufTtcblxuTGlzdC5wcmVwZW5kID0gZnVuY3Rpb24gKGxpc3QsIHZhbHVlKSB7XG4gIHJldHVybiBLZXJuZWwuU3BlY2lhbEZvcm1zLmxpc3QoLi4uW3ZhbHVlXS5jb25jYXQobGlzdCkpO1xufTtcblxuTGlzdC5jb25jYXQgPSBmdW5jdGlvbiAobGVmdCwgcmlnaHQpIHtcbiAgcmV0dXJuIGxlZnQuY29uY2F0KHJpZ2h0KTtcbn07XG5cbmxldCBSYW5nZSA9IGZ1bmN0aW9uIChfZmlyc3QsIF9sYXN0KSB7XG4gIGlmICghKHRoaXMgaW5zdGFuY2VvZiBSYW5nZSkpIHtcbiAgICByZXR1cm4gbmV3IFJhbmdlKF9maXJzdCwgX2xhc3QpO1xuICB9XG5cbiAgdGhpcy5maXJzdCA9IGZ1bmN0aW9uICgpIHtcbiAgICByZXR1cm4gX2ZpcnN0O1xuICB9O1xuXG4gIHRoaXMubGFzdCA9IGZ1bmN0aW9uICgpIHtcbiAgICByZXR1cm4gX2xhc3Q7XG4gIH07XG5cbiAgbGV0IF9yYW5nZSA9IFtdO1xuXG4gIGZvciAobGV0IGkgPSBfZmlyc3Q7IGkgPD0gX2xhc3Q7IGkrKykge1xuICAgIF9yYW5nZS5wdXNoKGkpO1xuICB9XG5cbiAgX3JhbmdlID0gT2JqZWN0LmZyZWV6ZShfcmFuZ2UpO1xuXG4gIHRoaXMudmFsdWUgPSBmdW5jdGlvbiAoKSB7XG4gICAgcmV0dXJuIF9yYW5nZTtcbiAgfTtcblxuICB0aGlzLmxlbmd0aCA9IGZ1bmN0aW9uICgpIHtcbiAgICByZXR1cm4gX3JhbmdlLmxlbmd0aDtcbiAgfTtcblxuICByZXR1cm4gdGhpcztcbn07XG5cblJhbmdlLnByb3RvdHlwZVtTeW1ib2wuaXRlcmF0b3JdID0gZnVuY3Rpb24gKCkge1xuICByZXR1cm4gdGhpcy52YWx1ZSgpW1N5bWJvbC5pdGVyYXRvcl0oKTtcbn07XG5cblJhbmdlLm5ldyA9IGZ1bmN0aW9uIChmaXJzdCwgbGFzdCkge1xuICByZXR1cm4gUmFuZ2UoZmlyc3QsIGxhc3QpO1xufTtcblxuUmFuZ2UucmFuZ2VfX3FtYXJrX18gPSBmdW5jdGlvbiAocmFuZ2UpIHtcbiAgcmV0dXJuIHJhbmdlIGluc3RhbmNlb2YgUmFuZ2U7XG59O1xuXG5sZXQgS2V5d29yZCA9IHt9O1xuXG5LZXl3b3JkLmhhc19rZXlfX3FtX18gPSBmdW5jdGlvbiAoa2V5d29yZHMsIGtleSkge1xuICBmb3IgKGxldCBrZXl3b3JkIG9mIGtleXdvcmRzKSB7XG4gICAgaWYgKEtlcm5lbC5lbGVtKGtleXdvcmQsIDApID09IGtleSkge1xuICAgICAgcmV0dXJuIHRydWU7XG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIGZhbHNlO1xufTtcblxuS2V5d29yZC5nZXQgPSBmdW5jdGlvbiAoa2V5d29yZHMsIGtleSwgdGhlX2RlZmF1bHQgPSBudWxsKSB7XG4gIGZvciAobGV0IGtleXdvcmQgb2Yga2V5d29yZHMpIHtcbiAgICBpZiAoS2VybmVsLmVsZW0oa2V5d29yZCwgMCkgPT0ga2V5KSB7XG4gICAgICByZXR1cm4gS2VybmVsLmVsZW0oa2V5d29yZCwgMSk7XG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIHRoZV9kZWZhdWx0O1xufTtcblxubGV0IEFnZW50ID0ge307XG5cbkFnZW50LnN0YXJ0ID0gZnVuY3Rpb24gKGZ1biwgb3B0aW9ucyA9IFtdKSB7XG4gIGxldCBwaWQgPSBzZWxmLnByb2Nlc3Nlcy5zcGF3bigpO1xuXG4gIGlmIChLZXl3b3JkLmhhc19rZXlfX3FtX18ob3B0aW9ucywgS2VybmVsLlNwZWNpYWxGb3Jtcy5hdG9tKCduYW1lJykpKSB7XG4gICAgcGlkID0gc2VsZi5wcm9jZXNzZXMucmVnaXN0ZXIoS2V5d29yZC5nZXQob3B0aW9ucywgS2VybmVsLlNwZWNpYWxGb3Jtcy5hdG9tKCduYW1lJykpLCBwaWQpO1xuICB9XG5cbiAgc2VsZi5wcm9jZXNzZXMucHV0KHBpZCwgJ3N0YXRlJywgZnVuKCkpO1xuICByZXR1cm4gS2VybmVsLlNwZWNpYWxGb3Jtcy50dXBsZShLZXJuZWwuU3BlY2lhbEZvcm1zLmF0b20oJ29rJyksIHBpZCk7XG59O1xuXG5BZ2VudC5zdG9wID0gZnVuY3Rpb24gKGFnZW50LCB0aW1lb3V0ID0gNTAwMCkge1xuICBzZWxmLnByb2Nlc3Nlcy5leGl0KGFnZW50KTtcbiAgcmV0dXJuIEtlcm5lbC5TcGVjaWFsRm9ybXMuYXRvbSgnb2snKTtcbn07XG5cbkFnZW50LnVwZGF0ZSA9IGZ1bmN0aW9uIChhZ2VudCwgZnVuLCB0aW1lb3V0ID0gNTAwMCkge1xuXG4gIGNvbnN0IGN1cnJlbnRfc3RhdGUgPSBzZWxmLnByb2Nlc3Nlcy5nZXQoYWdlbnQsICdzdGF0ZScpO1xuICBzZWxmLnByb2Nlc3Nlcy5wdXQoYWdlbnQsICdzdGF0ZScsIGZ1bihjdXJyZW50X3N0YXRlKSk7XG5cbiAgcmV0dXJuIEtlcm5lbC5TcGVjaWFsRm9ybXMuYXRvbSgnb2snKTtcbn07XG5cbkFnZW50LmdldCA9IGZ1bmN0aW9uIChhZ2VudCwgZnVuLCB0aW1lb3V0ID0gNTAwMCkge1xuICByZXR1cm4gZnVuKHNlbGYucHJvY2Vzc2VzLmdldChhZ2VudCwgJ3N0YXRlJykpO1xufTtcblxuQWdlbnQuZ2V0X2FuZF91cGRhdGUgPSBmdW5jdGlvbiAoYWdlbnQsIGZ1biwgdGltZW91dCA9IDUwMDApIHtcblxuICBjb25zdCBnZXRfYW5kX3VwZGF0ZV90dXBsZSA9IGZ1bihzZWxmLnByb2Nlc3Nlcy5nZXQoYWdlbnQsICdzdGF0ZScpKTtcbiAgc2VsZi5wcm9jZXNzZXMucHV0KGFnZW50LCAnc3RhdGUnLCBLZXJuZWwuZWxlbShnZXRfYW5kX3VwZGF0ZV90dXBsZSwgMSkpO1xuXG4gIHJldHVybiBLZXJuZWwuZWxlbShnZXRfYW5kX3VwZGF0ZV90dXBsZSwgMCk7XG59O1xuXG4vL2h0dHBzOi8vZGV2ZWxvcGVyLm1vemlsbGEub3JnL2VuLVVTL2RvY3MvV2ViL0FQSS9XaW5kb3dCYXNlNjQvQmFzZTY0X2VuY29kaW5nX2FuZF9kZWNvZGluZyNTb2x1dGlvbl8yXyVFMiU4MCU5M19yZXdyaXRlX3RoZV9ET01zX2F0b2IoKV9hbmRfYnRvYSgpX3VzaW5nX0phdmFTY3JpcHQnc19UeXBlZEFycmF5c19hbmRfVVRGLThcbmZ1bmN0aW9uIGI2NEVuY29kZVVuaWNvZGUoc3RyKSB7XG4gIHJldHVybiBidG9hKGVuY29kZVVSSUNvbXBvbmVudChzdHIpLnJlcGxhY2UoLyUoWzAtOUEtRl17Mn0pL2csIGZ1bmN0aW9uIChtYXRjaCwgcDEpIHtcbiAgICByZXR1cm4gU3RyaW5nLmZyb21DaGFyQ29kZSgnMHgnICsgcDEpO1xuICB9KSk7XG59XG5cbmZ1bmN0aW9uIGVuY29kZTY0KGRhdGEpIHtcbiAgcmV0dXJuIGI2NEVuY29kZVVuaWNvZGUoZGF0YSk7XG59XG5cbmZ1bmN0aW9uIGRlY29kZTY0KGRhdGEpIHtcbiAgdHJ5IHtcbiAgICByZXR1cm4gS2VybmVsLlNwZWNpYWxGb3Jtcy50dXBsZShLZXJuZWwuU3BlY2lhbEZvcm1zLmF0b20oJ29rJyksIGF0b2IoZGF0YSkpO1xuICB9IGNhdGNoIChlKSB7XG4gICAgcmV0dXJuIEtlcm5lbC5TcGVjaWFsRm9ybXMuYXRvbSgnZXJyb3InKTtcbiAgfVxuICByZXR1cm4gYnRvYShkYXRhKTtcbn1cblxuZnVuY3Rpb24gZGVjb2RlNjRfX2VtX18oZGF0YSkge1xuICByZXR1cm4gYXRvYihkYXRhKTtcbn1cblxudmFyIGJhc2UgPSB7XG4gIGVuY29kZTY0LFxuICBkZWNvZGU2NCxcbiAgZGVjb2RlNjRfX2VtX19cbn07XG5cbmZ1bmN0aW9uIGJub3QoZXhwcikge1xuICByZXR1cm4gfmV4cHI7XG59XG5cbmZ1bmN0aW9uIGJhbmQobGVmdCwgcmlnaHQpIHtcbiAgcmV0dXJuIGxlZnQgJiByaWdodDtcbn1cblxuZnVuY3Rpb24gYm9yKGxlZnQsIHJpZ2h0KSB7XG4gIHJldHVybiBsZWZ0IHwgcmlnaHQ7XG59XG5cbmZ1bmN0aW9uIGJzbChsZWZ0LCByaWdodCkge1xuICByZXR1cm4gbGVmdCA8PCByaWdodDtcbn1cblxuZnVuY3Rpb24gYnNyKGxlZnQsIHJpZ2h0KSB7XG4gIHJldHVybiBsZWZ0ID4+IHJpZ2h0O1xufVxuXG5mdW5jdGlvbiBieG9yKGxlZnQsIHJpZ2h0KSB7XG4gIHJldHVybiBsZWZ0IF4gcmlnaHQ7XG59XG5cbnZhciBiaXR3aXNlID0ge1xuICBibm90LFxuICBiYW5kLFxuICBib3IsXG4gIGJzbCxcbiAgYnNyLFxuICBieG9yXG59O1xuXG5sZXQgRW51bWVyYWJsZSA9IEtlcm5lbC5kZWZwcm90b2NvbCh7XG4gIGNvdW50OiBmdW5jdGlvbiAoY29sbGVjdGlvbikge30sXG4gIG1lbWJlcl9xbWFya19fOiBmdW5jdGlvbiAoY29sbGVjdGlvbiwgdmFsdWUpIHt9LFxuICByZWR1Y2U6IGZ1bmN0aW9uIChjb2xsZWN0aW9uLCBhY2MsIGZ1bikge31cbn0pO1xuXG5sZXQgQ29sbGVjdGFibGUgPSBLZXJuZWwuZGVmcHJvdG9jb2woe1xuICBpbnRvOiBmdW5jdGlvbiAoY29sbGVjdGFibGUpIHt9XG59KTtcblxubGV0IEluc3BlY3QgPSBLZXJuZWwuZGVmcHJvdG9jb2woe1xuICBpbnNwZWN0OiBmdW5jdGlvbiAodGhpbmcsIG9wdHMpIHt9XG59KTtcblxuZnVuY3Rpb24gX19uZXdfXygpIHtcbiAgcmV0dXJuIFNwZWNpYWxGb3Jtcy5tYXAoe30pO1xufVxuXG5mdW5jdGlvbiBrZXlzKG1hcCkge1xuICByZXR1cm4gT2JqZWN0LmtleXMobWFwKTtcbn1cblxuZnVuY3Rpb24gc2l6ZShtYXApIHtcbiAgcmV0dXJuIGtleXMobWFwKS5sZW5ndGg7XG59XG5cbmZ1bmN0aW9uIHRvX2xpc3QkMShtYXApIHtcbiAgbGV0IG1hcF9rZXlzID0ga2V5cyhtYXApO1xuICBsZXQgbGlzdCA9IFtdO1xuXG4gIGZvciAobGV0IGtleSBvZiBtYXBfa2V5cykge1xuICAgIGxpc3QucHVzaChTcGVjaWFsRm9ybXMudHVwbGUoa2V5LCBtYXBba2V5XSkpO1xuICB9XG5cbiAgcmV0dXJuIFNwZWNpYWxGb3Jtcy5saXN0KC4uLmxpc3QpO1xufVxuXG5mdW5jdGlvbiB2YWx1ZXMobWFwKSB7XG4gIGxldCBtYXBfa2V5cyA9IGtleXMobWFwKTtcbiAgbGV0IGxpc3QgPSBbXTtcblxuICBmb3IgKGxldCBrZXkgb2YgbWFwX2tleXMpIHtcbiAgICBsaXN0LnB1c2gobWFwW2tleV0pO1xuICB9XG5cbiAgcmV0dXJuIFNwZWNpYWxGb3Jtcy5saXN0KC4uLmxpc3QpO1xufVxuXG5mdW5jdGlvbiBmcm9tX3N0cnVjdChzdHJ1Y3QpIHtcbiAgbGV0IG1hcCA9IE9iamVjdC5hc3NpZ24oe30sIHN0cnVjdCk7XG4gIGRlbGV0ZSBtYXBbU3ltYm9sLmZvcihcIl9fc3RydWN0X19cIildO1xuXG4gIHJldHVybiBTcGVjaWFsRm9ybXMubWFwKG1hcCk7XG59XG5cbmZ1bmN0aW9uIF9fZGVsZXRlX18obWFwLCBrZXkpIHtcbiAgbGV0IG5ld19tYXAgPSBPYmplY3QuYXNzaWduKHt9LCBtYXApO1xuXG4gIGRlbGV0ZSBuZXdfbWFwW2tleV07XG5cbiAgcmV0dXJuIFNwZWNpYWxGb3Jtcy5tYXAobmV3X21hcCk7XG59XG5cbmZ1bmN0aW9uIGVxdWFsX19xbWFya19fKG1hcDEsIG1hcDIpIHtcbiAgcmV0dXJuIG1hcDEgPT09IG1hcDI7XG59XG5cbmZ1bmN0aW9uIGZldGNoX19lbWFya19fKG1hcCwga2V5KSB7XG4gIGlmIChrZXkgaW4gbWFwKSB7XG4gICAgcmV0dXJuIG1hcFtrZXldO1xuICB9XG5cbiAgdGhyb3cgbmV3IEVycm9yKFwiS2V5IG5vdCBmb3VuZC5cIik7XG59XG5cbmZ1bmN0aW9uIGZldGNoKG1hcCwga2V5KSB7XG4gIGlmIChrZXkgaW4gbWFwKSB7XG4gICAgcmV0dXJuIFNwZWNpYWxGb3Jtcy50dXBsZShTcGVjaWFsRm9ybXMuYXRvbShcIm9rXCIpLCBtYXBba2V5XSk7XG4gIH1cblxuICByZXR1cm4gU3BlY2lhbEZvcm1zLmF0b20oXCJlcnJvclwiKTtcbn1cblxuZnVuY3Rpb24gaGFzX2tleV9fcW1hcmtfXyhtYXAsIGtleSkge1xuICByZXR1cm4ga2V5IGluIG1hcDtcbn1cblxuZnVuY3Rpb24gc3BsaXQkMShtYXAsIGtleXMpIHtcbiAgbGV0IHNwbGl0MSA9IHt9O1xuICBsZXQgc3BsaXQyID0ge307XG5cbiAgZm9yIChsZXQga2V5IG9mIE9iamVjdC5rZXlzKG1hcCkpIHtcbiAgICBpZiAoa2V5cy5pbmRleE9mKGtleSkgPiAtMSkge1xuICAgICAgc3BsaXQxW2tleV0gPSBtYXBba2V5XTtcbiAgICB9IGVsc2Uge1xuICAgICAgc3BsaXQyW2tleV0gPSBtYXBba2V5XTtcbiAgICB9XG4gIH1cblxuICByZXR1cm4gU3BlY2lhbEZvcm1zLnR1cGxlKFNwZWNpYWxGb3Jtcy5tYXAoc3BsaXQxKSwgU3BlY2lhbEZvcm1zLm1hcChzcGxpdDIpKTtcbn1cblxuZnVuY3Rpb24gdGFrZShtYXAsIGtleXMpIHtcbiAgbGV0IHNwbGl0MSA9IHt9O1xuXG4gIGZvciAobGV0IGtleSBvZiBPYmplY3Qua2V5cyhtYXApKSB7XG4gICAgaWYgKGtleXMuaW5kZXhPZihrZXkpID4gLTEpIHtcbiAgICAgIHNwbGl0MVtrZXldID0gbWFwW2tleV07XG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIFNwZWNpYWxGb3Jtcy5tYXAoc3BsaXQxKTtcbn1cblxuZnVuY3Rpb24gZHJvcChtYXAsIGtleXMpIHtcbiAgbGV0IHNwbGl0MSA9IHt9O1xuXG4gIGZvciAobGV0IGtleSBvZiBPYmplY3Qua2V5cyhtYXApKSB7XG4gICAgaWYgKGtleXMuaW5kZXhPZihrZXkpID09PSAtMSkge1xuICAgICAgc3BsaXQxW2tleV0gPSBtYXBba2V5XTtcbiAgICB9XG4gIH1cblxuICByZXR1cm4gU3BlY2lhbEZvcm1zLm1hcChzcGxpdDEpO1xufVxuXG5mdW5jdGlvbiBwdXRfbmV3KG1hcCwga2V5LCB2YWx1ZSkge1xuICBpZiAoa2V5IGluIG1hcCkge1xuICAgIHJldHVybiBtYXA7XG4gIH1cblxuICBsZXQgbmV3X21hcCA9IE9iamVjdC5hc3NpZ24oe30sIG1hcCk7XG4gIG5ld19tYXBba2V5XSA9IHZhbHVlO1xuXG4gIHJldHVybiBTcGVjaWFsRm9ybXMubWFwKG5ld19tYXApO1xufVxuXG5mdW5jdGlvbiBwdXRfbmV3X2xhenkobWFwLCBrZXksIGZ1bikge1xuICBpZiAoa2V5IGluIG1hcCkge1xuICAgIHJldHVybiBtYXA7XG4gIH1cblxuICBsZXQgbmV3X21hcCA9IE9iamVjdC5hc3NpZ24oe30sIG1hcCk7XG4gIG5ld19tYXBba2V5XSA9IGZ1bigpO1xuXG4gIHJldHVybiBTcGVjaWFsRm9ybXMubWFwKG5ld19tYXApO1xufVxuXG5mdW5jdGlvbiBnZXRfYW5kX3VwZGF0ZShtYXAsIGtleSwgZnVuKSB7XG4gIGlmIChrZXkgaW4gbWFwKSB7XG4gICAgcmV0dXJuIG1hcDtcbiAgfVxuXG4gIGxldCBuZXdfbWFwID0gT2JqZWN0LmFzc2lnbih7fSwgbWFwKTtcbiAgbmV3X21hcFtrZXldID0gZnVuKG1hcFtrZXldKTtcblxuICByZXR1cm4gU3BlY2lhbEZvcm1zLm1hcChuZXdfbWFwKTtcbn1cblxuZnVuY3Rpb24gcG9wX2xhenkobWFwLCBrZXksIGZ1bikge1xuICBpZiAoIWtleSBpbiBtYXApIHtcbiAgICByZXR1cm4gU3BlY2lhbEZvcm1zLnR1cGxlKGZ1bigpLCBtYXApO1xuICB9XG5cbiAgbGV0IG5ld19tYXAgPSBPYmplY3QuYXNzaWduKHt9LCBtYXApO1xuICBsZXQgdmFsdWUgPSBmdW4obmV3X21hcFtrZXldKTtcbiAgZGVsZXRlIG5ld19tYXBba2V5XTtcblxuICByZXR1cm4gU3BlY2lhbEZvcm1zLnR1cGxlKHZhbHVlLCBuZXdfbWFwKTtcbn1cblxuZnVuY3Rpb24gcG9wKG1hcCwga2V5LCBfZGVmYXVsdCA9IG51bGwpIHtcbiAgaWYgKCFrZXkgaW4gbWFwKSB7XG4gICAgcmV0dXJuIFNwZWNpYWxGb3Jtcy50dXBsZShfZGVmYXVsdCwgbWFwKTtcbiAgfVxuXG4gIGxldCBuZXdfbWFwID0gT2JqZWN0LmFzc2lnbih7fSwgbWFwKTtcbiAgbGV0IHZhbHVlID0gbmV3X21hcFtrZXldO1xuICBkZWxldGUgbmV3X21hcFtrZXldO1xuXG4gIHJldHVybiBTcGVjaWFsRm9ybXMudHVwbGUodmFsdWUsIG5ld19tYXApO1xufVxuXG5mdW5jdGlvbiBnZXRfbGF6eShtYXAsIGtleSwgZnVuKSB7XG4gIGlmICgha2V5IGluIG1hcCkge1xuICAgIHJldHVybiBmdW4oKTtcbiAgfVxuXG4gIHJldHVybiBmdW4obWFwW2tleV0pO1xufVxuXG5mdW5jdGlvbiBnZXQobWFwLCBrZXksIF9kZWZhdWx0ID0gbnVsbCkge1xuICBpZiAoIWtleSBpbiBtYXApIHtcbiAgICByZXR1cm4gX2RlZmF1bHQ7XG4gIH1cblxuICByZXR1cm4gbWFwW2tleV07XG59XG5cbmZ1bmN0aW9uIHB1dChtYXAsIGtleSwgdmFsKSB7XG4gIGxldCBuZXdfbWFwID0gT2JqZWN0KHt9LCBtYXApO1xuICBuZXdfbWFwW2tleV0gPSB2YWw7XG5cbiAgcmV0dXJuIFNwZWNpYWxGb3Jtcy5tYXAobmV3X21hcCk7XG59XG5cbmZ1bmN0aW9uIHVwZGF0ZV9fZW1hcmtfXyhtYXAsIGtleSwgZnVuKSB7XG4gIGlmICgha2V5IGluIG1hcCkge1xuICAgIHRocm93IG5ldyBFcnJvcihcIktleSBub3QgZm91bmRcIik7XG4gIH1cblxuICBsZXQgbmV3X21hcCA9IE9iamVjdCh7fSwgbWFwKTtcbiAgbmV3X21hcFtrZXldID0gZnVuKG1hcFtrZXldKTtcblxuICByZXR1cm4gU3BlY2lhbEZvcm1zLm1hcChuZXdfbWFwKTtcbn1cblxuZnVuY3Rpb24gdXBkYXRlKG1hcCwga2V5LCBpbml0aWFsLCBmdW4pIHtcbiAgbGV0IG5ld19tYXAgPSBPYmplY3Qoe30sIG1hcCk7XG5cbiAgaWYgKCFrZXkgaW4gbWFwKSB7XG4gICAgbmV3X21hcFtrZXldID0gaW5pdGlhbDtcbiAgfSBlbHNlIHtcbiAgICBuZXdfbWFwW2tleV0gPSBmdW4obWFwW2tleV0pO1xuICB9XG5cbiAgcmV0dXJuIFNwZWNpYWxGb3Jtcy5tYXAobmV3X21hcCk7XG59XG5cbnZhciBtYXAgPSB7XG4gIG5ldzogX19uZXdfXyxcbiAga2V5cyxcbiAgc2l6ZSxcbiAgdG9fbGlzdDogdG9fbGlzdCQxLFxuICB2YWx1ZXMsXG4gIGZyb21fc3RydWN0LFxuICBkZWxldGU6IF9fZGVsZXRlX18sXG4gIGRyb3AsXG4gIGVxdWFsX19xbWFya19fLFxuICBmZXRjaF9fZW1hcmtfXyxcbiAgZmV0Y2gsXG4gIGhhc19rZXlfX3FtYXJrX18sXG4gIHNwbGl0OiBzcGxpdCQxLFxuICB0YWtlLFxuICBwdXRfbmV3LFxuICBwdXRfbmV3X2xhenksXG4gIGdldF9hbmRfdXBkYXRlLFxuICBwb3BfbGF6eSxcbiAgcG9wLFxuICBnZXRfbGF6eSxcbiAgZ2V0LFxuICBwdXQsXG4gIHVwZGF0ZV9fZW1hcmtfXyxcbiAgdXBkYXRlXG59O1xuXG5mdW5jdGlvbiBfX25ld19fJDEoKSB7XG4gIHJldHVybiBTcGVjaWFsRm9ybXMubWFwKHsgW1N5bWJvbC5mb3IoJ19fc3RydWN0X18nKV06IFN5bWJvbC5mb3IoJ01hcFNldCcpLCBzZXQ6IFNwZWNpYWxGb3Jtcy5saXN0KCkgfSk7XG59XG5cbmZ1bmN0aW9uIHNpemUkMihtYXApIHtcbiAgcmV0dXJuIG1hcC5zZXQubGVuZ3RoO1xufVxuXG5mdW5jdGlvbiB0b19saXN0JDMobWFwKSB7XG4gIHJldHVybiBtYXAuc2V0O1xufVxuXG5mdW5jdGlvbiBfX2RlbGV0ZV9fJDIoc2V0LCB0ZXJtKSB7XG4gIGxldCBuZXdfbGlzdCA9IExpc3QuZGVsZXRlKHNldC5zZXQsIHRlcm0pO1xuXG4gIGxldCBuZXdfbWFwID0gT2JqZWN0LmFzc2lnbih7fSwgc2V0KTtcbiAgbmV3X21hcC5zZXQgPSBuZXdfbGlzdDtcbiAgcmV0dXJuIFNwZWNpYWxGb3Jtcy5tYXAobmV3X21hcCk7XG59XG5cbmZ1bmN0aW9uIHB1dCQyKHNldCwgdGVybSkge1xuICBpZiAoc2V0LnNldC5pbmRleE9mKHRlcm0pID09PSAtMSkge1xuICAgIGxldCBuZXdfbGlzdCA9IExpc3QuYXBwZW5kKHNldC5zZXQsIHRlcm0pO1xuXG4gICAgbGV0IG5ld19tYXAgPSBPYmplY3QuYXNzaWduKHt9LCBzZXQpO1xuICAgIG5ld19tYXAuc2V0ID0gbmV3X2xpc3Q7XG4gICAgcmV0dXJuIFNwZWNpYWxGb3Jtcy5tYXAobmV3X21hcCk7XG4gIH1cblxuICByZXR1cm4gc2V0O1xufVxuXG5mdW5jdGlvbiBkaWZmZXJlbmNlJDEoc2V0MSwgc2V0Mikge1xuICBsZXQgbmV3X21hcCA9IE9iamVjdC5hc3NpZ24oe30sIHNldDEpO1xuXG4gIGZvciAobGV0IHZhbCBvZiBzZXQxLnNldCkge1xuICAgIGlmIChtZW1iZXJfX3FtYXJrX18kMShzZXQyLCB2YWwpKSB7XG4gICAgICBuZXdfbWFwLnNldCA9IExpc3QuZGVsZXRlKG5ld19tYXAuc2V0LCB2YWwpO1xuICAgIH1cbiAgfVxuXG4gIHJldHVybiBTcGVjaWFsRm9ybXMubWFwKG5ld19tYXApO1xufVxuXG5mdW5jdGlvbiBpbnRlcnNlY3Rpb24kMShzZXQxLCBzZXQyKSB7XG4gIGxldCBuZXdfbWFwID0gT2JqZWN0LmFzc2lnbih7fSwgc2V0MSk7XG5cbiAgZm9yIChsZXQgdmFsIG9mIHNldDEuc2V0KSB7XG4gICAgaWYgKCFtZW1iZXJfX3FtYXJrX18kMShzZXQyLCB2YWwpKSB7XG4gICAgICBuZXdfbWFwLnNldCA9IExpc3QuZGVsZXRlKG5ld19tYXAuc2V0LCB2YWwpO1xuICAgIH1cbiAgfVxuXG4gIHJldHVybiBTcGVjaWFsRm9ybXMubWFwKG5ld19tYXApO1xufVxuXG5mdW5jdGlvbiB1bmlvbiQxKHNldDEsIHNldDIpIHtcbiAgbGV0IG5ld19tYXAgPSBzZXQxO1xuXG4gIGZvciAobGV0IHZhbCBvZiBzZXQyLnNldCkge1xuICAgIG5ld19tYXAgPSBwdXQkMihuZXdfbWFwLCB2YWwpO1xuICB9XG5cbiAgcmV0dXJuIFNwZWNpYWxGb3Jtcy5tYXAobmV3X21hcCk7XG59XG5cbmZ1bmN0aW9uIGRpc2pvaW5fX3FtYXJrX18kMShzZXQxLCBzZXQyKSB7XG4gIGZvciAobGV0IHZhbCBvZiBzZXQxLnNldCkge1xuICAgIGlmIChtZW1iZXJfX3FtYXJrX18kMShzZXQyLCB2YWwpKSB7XG4gICAgICByZXR1cm4gZmFsc2U7XG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIHRydWU7XG59XG5cbmZ1bmN0aW9uIG1lbWJlcl9fcW1hcmtfXyQxKHNldCwgdmFsdWUpIHtcbiAgcmV0dXJuIHNldC5zZXQuaW5kZXhPZih2YWx1ZSkgPj0gMDtcbn1cblxuZnVuY3Rpb24gZXF1YWxfX3FtYXJrX18kMihzZXQxLCBzZXQyKSB7XG4gIHJldHVybiBzZXQxLnNldCA9PT0gc2V0Mi5zZXQ7XG59XG5cbmZ1bmN0aW9uIHN1YnNldF9fcW1hcmtfXyQxKHNldDEsIHNldDIpIHtcbiAgZm9yIChsZXQgdmFsIG9mIHNldDEuc2V0KSB7XG4gICAgaWYgKCFtZW1iZXJfX3FtYXJrX18kMShzZXQyLCB2YWwpKSB7XG4gICAgICByZXR1cm4gZmFsc2U7XG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIHRydWU7XG59XG5cbnZhciBNYXBTZXQgPSB7XG4gIG5ldzogX19uZXdfXyQxLFxuICBzaXplOiBzaXplJDIsXG4gIHRvX2xpc3Q6IHRvX2xpc3QkMyxcbiAgZGlzam9pbl9fcW1hcmtfXzogZGlzam9pbl9fcW1hcmtfXyQxLFxuICBkZWxldGU6IF9fZGVsZXRlX18kMixcbiAgc3Vic2V0X19xbWFya19fOiBzdWJzZXRfX3FtYXJrX18kMSxcbiAgZXF1YWxfX3FtYXJrX186IGVxdWFsX19xbWFya19fJDIsXG4gIG1lbWJlcl9fcW1hcmtfXzogbWVtYmVyX19xbWFya19fJDEsXG4gIHB1dDogcHV0JDIsXG4gIHVuaW9uOiB1bmlvbiQxLFxuICBpbnRlcnNlY3Rpb246IGludGVyc2VjdGlvbiQxLFxuICBkaWZmZXJlbmNlOiBkaWZmZXJlbmNlJDFcbn07XG5cbmZ1bmN0aW9uIHNpemUkMShtYXApIHtcbiAgcmV0dXJuIE1hcFNldC5zaXplKG1hcCk7XG59XG5cbmZ1bmN0aW9uIHRvX2xpc3QkMihtYXApIHtcbiAgcmV0dXJuIE1hcFNldC50b19saXN0KG1hcCk7XG59XG5cbmZ1bmN0aW9uIF9fZGVsZXRlX18kMShzZXQsIHRlcm0pIHtcbiAgcmV0dXJuIE1hcFNldC5kZWxldGUoc2V0LCB0ZXJtKTtcbn1cblxuZnVuY3Rpb24gcHV0JDEoc2V0LCB0ZXJtKSB7XG4gIHJldHVybiBNYXBTZXQucHV0KHNldCwgdGVybSk7XG59XG5cbmZ1bmN0aW9uIGRpZmZlcmVuY2Uoc2V0MSwgc2V0Mikge1xuICByZXR1cm4gTWFwU2V0LmRpZmZlcmVuY2Uoc2V0MSwgc2V0Mik7XG59XG5cbmZ1bmN0aW9uIGludGVyc2VjdGlvbihzZXQxLCBzZXQyKSB7XG4gIHJldHVybiBNYXBTZXQuaW50ZXJzZWN0aW9uKHNldDEsIHNldDIpO1xufVxuXG5mdW5jdGlvbiB1bmlvbihzZXQxLCBzZXQyKSB7XG4gIHJldHVybiBNYXBTZXQudW5pb24oc2V0MSwgc2V0Mik7XG59XG5cbmZ1bmN0aW9uIGRpc2pvaW5fX3FtYXJrX18oc2V0MSwgc2V0Mikge1xuICByZXR1cm4gTWFwU2V0LmRpc2pvaW5fX3FtYXJrX18oc2V0MSwgc2V0Mik7XG59XG5cbmZ1bmN0aW9uIG1lbWJlcl9fcW1hcmtfXyhzZXQsIHZhbHVlKSB7XG4gIHJldHVybiBNYXBTZXQubWVtYmVyX19xbWFya19fKHNldDEsIHNldDIpO1xufVxuXG5mdW5jdGlvbiBlcXVhbF9fcW1hcmtfXyQxKHNldDEsIHNldDIpIHtcbiAgcmV0dXJuIE1hcFNldC5lcXVhbF9fcW1hcmtfXyhzZXQxLCBzZXQyKTtcbn1cblxuZnVuY3Rpb24gc3Vic2V0X19xbWFya19fKHNldDEsIHNldDIpIHtcbiAgcmV0dXJuIE1hcFNldC5zdWJzZXRfX3FtYXJrX18oc2V0MSwgc2V0Mik7XG59XG5cbnZhciBzZXQgPSB7XG4gIHNpemU6IHNpemUkMSxcbiAgdG9fbGlzdDogdG9fbGlzdCQyLFxuICBkaXNqb2luX19xbWFya19fLFxuICBkZWxldGU6IF9fZGVsZXRlX18kMSxcbiAgc3Vic2V0X19xbWFya19fLFxuICBlcXVhbF9fcW1hcmtfXzogZXF1YWxfX3FtYXJrX18kMSxcbiAgbWVtYmVyX19xbWFya19fLFxuICBwdXQ6IHB1dCQxLFxuICB1bmlvbixcbiAgaW50ZXJzZWN0aW9uLFxuICBkaWZmZXJlbmNlXG59O1xuXG5sZXQgVmlydHVhbERPTSA9IChmdW5jdGlvbiAoZSkge1xuICAgIHJldHVybiBlKCk7XG59KShmdW5jdGlvbiAoKSB7XG4gICAgdmFyIGRlZmluZSwgbW9kdWxlLCBleHBvcnRzO1xuICAgIHJldHVybiAoZnVuY3Rpb24gZSh0LCBuLCByKSB7XG4gICAgICAgIGZ1bmN0aW9uIHMobywgdSkge1xuICAgICAgICAgICAgaWYgKCFuW29dKSB7XG4gICAgICAgICAgICAgICAgaWYgKCF0W29dKSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciBhID0gdHlwZW9mIHJlcXVpcmUgPT0gXCJmdW5jdGlvblwiICYmIHJlcXVpcmU7XG4gICAgICAgICAgICAgICAgICAgIGlmICghdSAmJiBhKSByZXR1cm4gYShvLCAhMCk7XG4gICAgICAgICAgICAgICAgICAgIGlmIChpKSByZXR1cm4gaShvLCAhMCk7XG4gICAgICAgICAgICAgICAgICAgIHZhciBmID0gbmV3IEVycm9yKFwiQ2Fubm90IGZpbmQgbW9kdWxlICdcIiArIG8gKyBcIidcIik7XG4gICAgICAgICAgICAgICAgICAgIHRocm93IChmLmNvZGUgPSBcIk1PRFVMRV9OT1RfRk9VTkRcIiwgZik7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHZhciBsID0gbltvXSA9IHtcbiAgICAgICAgICAgICAgICAgICAgZXhwb3J0czoge31cbiAgICAgICAgICAgICAgICB9O1xuICAgICAgICAgICAgICAgIHRbb11bMF0uY2FsbChsLmV4cG9ydHMsIGZ1bmN0aW9uIChlKSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciBuID0gdFtvXVsxXVtlXTtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHMobiA/IG4gOiBlKTtcbiAgICAgICAgICAgICAgICB9LCBsLCBsLmV4cG9ydHMsIGUsIHQsIG4sIHIpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmV0dXJuIG5bb10uZXhwb3J0cztcbiAgICAgICAgfVxuICAgICAgICB2YXIgaSA9IHR5cGVvZiByZXF1aXJlID09IFwiZnVuY3Rpb25cIiAmJiByZXF1aXJlO1xuICAgICAgICBmb3IgKHZhciBvID0gMDsgbyA8IHIubGVuZ3RoOyBvKyspIHMocltvXSk7XG4gICAgICAgIHJldHVybiBzO1xuICAgIH0pKHtcbiAgICAgICAgMTogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHtcblxuICAgICAgICAgICAgdmFyIGNyZWF0ZUVsZW1lbnQgPSByZXF1aXJlKFwiLi92ZG9tL2NyZWF0ZS1lbGVtZW50LmpzXCIpO1xuXG4gICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IGNyZWF0ZUVsZW1lbnQ7XG4gICAgICAgIH0sIHsgXCIuL3Zkb20vY3JlYXRlLWVsZW1lbnQuanNcIjogMTUgfV0sIDI6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICB2YXIgZGlmZiA9IHJlcXVpcmUoXCIuL3Z0cmVlL2RpZmYuanNcIik7XG5cbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gZGlmZjtcbiAgICAgICAgfSwgeyBcIi4vdnRyZWUvZGlmZi5qc1wiOiAzNSB9XSwgMzogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHtcbiAgICAgICAgICAgIHZhciBoID0gcmVxdWlyZShcIi4vdmlydHVhbC1oeXBlcnNjcmlwdC9pbmRleC5qc1wiKTtcblxuICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBoO1xuICAgICAgICB9LCB7IFwiLi92aXJ0dWFsLWh5cGVyc2NyaXB0L2luZGV4LmpzXCI6IDIyIH1dLCA0OiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge1xuICAgICAgICAgICAgdmFyIGRpZmYgPSByZXF1aXJlKFwiLi9kaWZmLmpzXCIpO1xuICAgICAgICAgICAgdmFyIHBhdGNoID0gcmVxdWlyZShcIi4vcGF0Y2guanNcIik7XG4gICAgICAgICAgICB2YXIgaCA9IHJlcXVpcmUoXCIuL2guanNcIik7XG4gICAgICAgICAgICB2YXIgY3JlYXRlID0gcmVxdWlyZShcIi4vY3JlYXRlLWVsZW1lbnQuanNcIik7XG4gICAgICAgICAgICB2YXIgVk5vZGUgPSByZXF1aXJlKFwiLi92bm9kZS92bm9kZS5qc1wiKTtcbiAgICAgICAgICAgIHZhciBWVGV4dCA9IHJlcXVpcmUoXCIuL3Zub2RlL3Z0ZXh0LmpzXCIpO1xuXG4gICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IHtcbiAgICAgICAgICAgICAgICBkaWZmOiBkaWZmLFxuICAgICAgICAgICAgICAgIHBhdGNoOiBwYXRjaCxcbiAgICAgICAgICAgICAgICBoOiBoLFxuICAgICAgICAgICAgICAgIGNyZWF0ZTogY3JlYXRlLFxuICAgICAgICAgICAgICAgIFZOb2RlOiBWTm9kZSxcbiAgICAgICAgICAgICAgICBWVGV4dDogVlRleHRcbiAgICAgICAgICAgIH07XG4gICAgICAgIH0sIHsgXCIuL2NyZWF0ZS1lbGVtZW50LmpzXCI6IDEsIFwiLi9kaWZmLmpzXCI6IDIsIFwiLi9oLmpzXCI6IDMsIFwiLi9wYXRjaC5qc1wiOiAxMywgXCIuL3Zub2RlL3Zub2RlLmpzXCI6IDMxLCBcIi4vdm5vZGUvdnRleHQuanNcIjogMzMgfV0sIDU6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICAvKiFcbiAgICAgICAgICAgICAqIENyb3NzLUJyb3dzZXIgU3BsaXQgMS4xLjFcbiAgICAgICAgICAgICAqIENvcHlyaWdodCAyMDA3LTIwMTIgU3RldmVuIExldml0aGFuIDxzdGV2ZW5sZXZpdGhhbi5jb20+XG4gICAgICAgICAgICAgKiBBdmFpbGFibGUgdW5kZXIgdGhlIE1JVCBMaWNlbnNlXG4gICAgICAgICAgICAgKiBFQ01BU2NyaXB0IGNvbXBsaWFudCwgdW5pZm9ybSBjcm9zcy1icm93c2VyIHNwbGl0IG1ldGhvZFxuICAgICAgICAgICAgICovXG5cbiAgICAgICAgICAgIC8qKlxuICAgICAgICAgICAgICogU3BsaXRzIGEgc3RyaW5nIGludG8gYW4gYXJyYXkgb2Ygc3RyaW5ncyB1c2luZyBhIHJlZ2V4IG9yIHN0cmluZyBzZXBhcmF0b3IuIE1hdGNoZXMgb2YgdGhlXG4gICAgICAgICAgICAgKiBzZXBhcmF0b3IgYXJlIG5vdCBpbmNsdWRlZCBpbiB0aGUgcmVzdWx0IGFycmF5LiBIb3dldmVyLCBpZiBgc2VwYXJhdG9yYCBpcyBhIHJlZ2V4IHRoYXQgY29udGFpbnNcbiAgICAgICAgICAgICAqIGNhcHR1cmluZyBncm91cHMsIGJhY2tyZWZlcmVuY2VzIGFyZSBzcGxpY2VkIGludG8gdGhlIHJlc3VsdCBlYWNoIHRpbWUgYHNlcGFyYXRvcmAgaXMgbWF0Y2hlZC5cbiAgICAgICAgICAgICAqIEZpeGVzIGJyb3dzZXIgYnVncyBjb21wYXJlZCB0byB0aGUgbmF0aXZlIGBTdHJpbmcucHJvdG90eXBlLnNwbGl0YCBhbmQgY2FuIGJlIHVzZWQgcmVsaWFibHlcbiAgICAgICAgICAgICAqIGNyb3NzLWJyb3dzZXIuXG4gICAgICAgICAgICAgKiBAcGFyYW0ge1N0cmluZ30gc3RyIFN0cmluZyB0byBzcGxpdC5cbiAgICAgICAgICAgICAqIEBwYXJhbSB7UmVnRXhwfFN0cmluZ30gc2VwYXJhdG9yIFJlZ2V4IG9yIHN0cmluZyB0byB1c2UgZm9yIHNlcGFyYXRpbmcgdGhlIHN0cmluZy5cbiAgICAgICAgICAgICAqIEBwYXJhbSB7TnVtYmVyfSBbbGltaXRdIE1heGltdW0gbnVtYmVyIG9mIGl0ZW1zIHRvIGluY2x1ZGUgaW4gdGhlIHJlc3VsdCBhcnJheS5cbiAgICAgICAgICAgICAqIEByZXR1cm5zIHtBcnJheX0gQXJyYXkgb2Ygc3Vic3RyaW5ncy5cbiAgICAgICAgICAgICAqIEBleGFtcGxlXG4gICAgICAgICAgICAgKlxuICAgICAgICAgICAgICogLy8gQmFzaWMgdXNlXG4gICAgICAgICAgICAgKiBzcGxpdCgnYSBiIGMgZCcsICcgJyk7XG4gICAgICAgICAgICAgKiAvLyAtPiBbJ2EnLCAnYicsICdjJywgJ2QnXVxuICAgICAgICAgICAgICpcbiAgICAgICAgICAgICAqIC8vIFdpdGggbGltaXRcbiAgICAgICAgICAgICAqIHNwbGl0KCdhIGIgYyBkJywgJyAnLCAyKTtcbiAgICAgICAgICAgICAqIC8vIC0+IFsnYScsICdiJ11cbiAgICAgICAgICAgICAqXG4gICAgICAgICAgICAgKiAvLyBCYWNrcmVmZXJlbmNlcyBpbiByZXN1bHQgYXJyYXlcbiAgICAgICAgICAgICAqIHNwbGl0KCcuLndvcmQxIHdvcmQyLi4nLCAvKFthLXpdKykoXFxkKykvaSk7XG4gICAgICAgICAgICAgKiAvLyAtPiBbJy4uJywgJ3dvcmQnLCAnMScsICcgJywgJ3dvcmQnLCAnMicsICcuLiddXG4gICAgICAgICAgICAgKi9cbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gKGZ1bmN0aW9uIHNwbGl0KHVuZGVmKSB7XG5cbiAgICAgICAgICAgICAgICB2YXIgbmF0aXZlU3BsaXQgPSBTdHJpbmcucHJvdG90eXBlLnNwbGl0LFxuICAgICAgICAgICAgICAgICAgICBjb21wbGlhbnRFeGVjTnBjZyA9IC8oKT8/Ly5leGVjKFwiXCIpWzFdID09PSB1bmRlZixcblxuICAgICAgICAgICAgICAgIC8vIE5QQ0c6IG5vbnBhcnRpY2lwYXRpbmcgY2FwdHVyaW5nIGdyb3VwXG4gICAgICAgICAgICAgICAgc2VsZjtcblxuICAgICAgICAgICAgICAgIHNlbGYgPSBmdW5jdGlvbiAoc3RyLCBzZXBhcmF0b3IsIGxpbWl0KSB7XG4gICAgICAgICAgICAgICAgICAgIC8vIElmIGBzZXBhcmF0b3JgIGlzIG5vdCBhIHJlZ2V4LCB1c2UgYG5hdGl2ZVNwbGl0YFxuICAgICAgICAgICAgICAgICAgICBpZiAoT2JqZWN0LnByb3RvdHlwZS50b1N0cmluZy5jYWxsKHNlcGFyYXRvcikgIT09IFwiW29iamVjdCBSZWdFeHBdXCIpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBuYXRpdmVTcGxpdC5jYWxsKHN0ciwgc2VwYXJhdG9yLCBsaW1pdCk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgdmFyIG91dHB1dCA9IFtdLFxuICAgICAgICAgICAgICAgICAgICAgICAgZmxhZ3MgPSAoc2VwYXJhdG9yLmlnbm9yZUNhc2UgPyBcImlcIiA6IFwiXCIpICsgKHNlcGFyYXRvci5tdWx0aWxpbmUgPyBcIm1cIiA6IFwiXCIpICsgKHNlcGFyYXRvci5leHRlbmRlZCA/IFwieFwiIDogXCJcIikgKyAoc2VwYXJhdG9yLnN0aWNreSA/IFwieVwiIDogXCJcIiksXG5cbiAgICAgICAgICAgICAgICAgICAgLy8gRmlyZWZveCAzK1xuICAgICAgICAgICAgICAgICAgICBsYXN0TGFzdEluZGV4ID0gMCxcblxuICAgICAgICAgICAgICAgICAgICAvLyBNYWtlIGBnbG9iYWxgIGFuZCBhdm9pZCBgbGFzdEluZGV4YCBpc3N1ZXMgYnkgd29ya2luZyB3aXRoIGEgY29weVxuICAgICAgICAgICAgICAgICAgICBzZXBhcmF0b3IgPSBuZXcgUmVnRXhwKHNlcGFyYXRvci5zb3VyY2UsIGZsYWdzICsgXCJnXCIpLFxuICAgICAgICAgICAgICAgICAgICAgICAgc2VwYXJhdG9yMixcbiAgICAgICAgICAgICAgICAgICAgICAgIG1hdGNoLFxuICAgICAgICAgICAgICAgICAgICAgICAgbGFzdEluZGV4LFxuICAgICAgICAgICAgICAgICAgICAgICAgbGFzdExlbmd0aDtcbiAgICAgICAgICAgICAgICAgICAgc3RyICs9IFwiXCI7IC8vIFR5cGUtY29udmVydFxuICAgICAgICAgICAgICAgICAgICBpZiAoIWNvbXBsaWFudEV4ZWNOcGNnKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAvLyBEb2Vzbid0IG5lZWQgZmxhZ3MgZ3ksIGJ1dCB0aGV5IGRvbid0IGh1cnRcbiAgICAgICAgICAgICAgICAgICAgICAgIHNlcGFyYXRvcjIgPSBuZXcgUmVnRXhwKFwiXlwiICsgc2VwYXJhdG9yLnNvdXJjZSArIFwiJCg/IVxcXFxzKVwiLCBmbGFncyk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgLyogVmFsdWVzIGZvciBgbGltaXRgLCBwZXIgdGhlIHNwZWM6XG4gICAgICAgICAgICAgICAgICAgICAqIElmIHVuZGVmaW5lZDogNDI5NDk2NzI5NSAvLyBNYXRoLnBvdygyLCAzMikgLSAxXG4gICAgICAgICAgICAgICAgICAgICAqIElmIDAsIEluZmluaXR5LCBvciBOYU46IDBcbiAgICAgICAgICAgICAgICAgICAgICogSWYgcG9zaXRpdmUgbnVtYmVyOiBsaW1pdCA9IE1hdGguZmxvb3IobGltaXQpOyBpZiAobGltaXQgPiA0Mjk0OTY3Mjk1KSBsaW1pdCAtPSA0Mjk0OTY3Mjk2O1xuICAgICAgICAgICAgICAgICAgICAgKiBJZiBuZWdhdGl2ZSBudW1iZXI6IDQyOTQ5NjcyOTYgLSBNYXRoLmZsb29yKE1hdGguYWJzKGxpbWl0KSlcbiAgICAgICAgICAgICAgICAgICAgICogSWYgb3RoZXI6IFR5cGUtY29udmVydCwgdGhlbiB1c2UgdGhlIGFib3ZlIHJ1bGVzXG4gICAgICAgICAgICAgICAgICAgICAqL1xuICAgICAgICAgICAgICAgICAgICBsaW1pdCA9IGxpbWl0ID09PSB1bmRlZiA/IC0xID4+PiAwIDogLy8gTWF0aC5wb3coMiwgMzIpIC0gMVxuICAgICAgICAgICAgICAgICAgICBsaW1pdCA+Pj4gMDsgLy8gVG9VaW50MzIobGltaXQpXG4gICAgICAgICAgICAgICAgICAgIHdoaWxlIChtYXRjaCA9IHNlcGFyYXRvci5leGVjKHN0cikpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIGBzZXBhcmF0b3IubGFzdEluZGV4YCBpcyBub3QgcmVsaWFibGUgY3Jvc3MtYnJvd3NlclxuICAgICAgICAgICAgICAgICAgICAgICAgbGFzdEluZGV4ID0gbWF0Y2guaW5kZXggKyBtYXRjaFswXS5sZW5ndGg7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAobGFzdEluZGV4ID4gbGFzdExhc3RJbmRleCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIG91dHB1dC5wdXNoKHN0ci5zbGljZShsYXN0TGFzdEluZGV4LCBtYXRjaC5pbmRleCkpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIEZpeCBicm93c2VycyB3aG9zZSBgZXhlY2AgbWV0aG9kcyBkb24ndCBjb25zaXN0ZW50bHkgcmV0dXJuIGB1bmRlZmluZWRgIGZvclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIG5vbnBhcnRpY2lwYXRpbmcgY2FwdHVyaW5nIGdyb3Vwc1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmICghY29tcGxpYW50RXhlY05wY2cgJiYgbWF0Y2gubGVuZ3RoID4gMSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBtYXRjaFswXS5yZXBsYWNlKHNlcGFyYXRvcjIsIGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZvciAodmFyIGkgPSAxOyBpIDwgYXJndW1lbnRzLmxlbmd0aCAtIDI7IGkrKykge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChhcmd1bWVudHNbaV0gPT09IHVuZGVmKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1hdGNoW2ldID0gdW5kZWY7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKG1hdGNoLmxlbmd0aCA+IDEgJiYgbWF0Y2guaW5kZXggPCBzdHIubGVuZ3RoKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIEFycmF5LnByb3RvdHlwZS5wdXNoLmFwcGx5KG91dHB1dCwgbWF0Y2guc2xpY2UoMSkpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBsYXN0TGVuZ3RoID0gbWF0Y2hbMF0ubGVuZ3RoO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxhc3RMYXN0SW5kZXggPSBsYXN0SW5kZXg7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKG91dHB1dC5sZW5ndGggPj0gbGltaXQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHNlcGFyYXRvci5sYXN0SW5kZXggPT09IG1hdGNoLmluZGV4KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgc2VwYXJhdG9yLmxhc3RJbmRleCsrOyAvLyBBdm9pZCBhbiBpbmZpbml0ZSBsb29wXG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgaWYgKGxhc3RMYXN0SW5kZXggPT09IHN0ci5sZW5ndGgpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChsYXN0TGVuZ3RoIHx8ICFzZXBhcmF0b3IudGVzdChcIlwiKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIG91dHB1dC5wdXNoKFwiXCIpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgb3V0cHV0LnB1c2goc3RyLnNsaWNlKGxhc3RMYXN0SW5kZXgpKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICByZXR1cm4gb3V0cHV0Lmxlbmd0aCA+IGxpbWl0ID8gb3V0cHV0LnNsaWNlKDAsIGxpbWl0KSA6IG91dHB1dDtcbiAgICAgICAgICAgICAgICB9O1xuXG4gICAgICAgICAgICAgICAgcmV0dXJuIHNlbGY7XG4gICAgICAgICAgICB9KSgpO1xuICAgICAgICB9LCB7fV0sIDY6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7fSwge31dLCA3OiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge1xuICAgICAgICAgICAgXCJ1c2Ugc3RyaWN0XCI7XG5cbiAgICAgICAgICAgIHZhciBPbmVWZXJzaW9uQ29uc3RyYWludCA9IHJlcXVpcmUoXCJpbmRpdmlkdWFsL29uZS12ZXJzaW9uXCIpO1xuXG4gICAgICAgICAgICB2YXIgTVlfVkVSU0lPTiA9IFwiN1wiO1xuICAgICAgICAgICAgT25lVmVyc2lvbkNvbnN0cmFpbnQoXCJldi1zdG9yZVwiLCBNWV9WRVJTSU9OKTtcblxuICAgICAgICAgICAgdmFyIGhhc2hLZXkgPSBcIl9fRVZfU1RPUkVfS0VZQFwiICsgTVlfVkVSU0lPTjtcblxuICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBFdlN0b3JlO1xuXG4gICAgICAgICAgICBmdW5jdGlvbiBFdlN0b3JlKGVsZW0pIHtcbiAgICAgICAgICAgICAgICB2YXIgaGFzaCA9IGVsZW1baGFzaEtleV07XG5cbiAgICAgICAgICAgICAgICBpZiAoIWhhc2gpIHtcbiAgICAgICAgICAgICAgICAgICAgaGFzaCA9IGVsZW1baGFzaEtleV0gPSB7fTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICByZXR1cm4gaGFzaDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSwgeyBcImluZGl2aWR1YWwvb25lLXZlcnNpb25cIjogOSB9XSwgODogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHtcbiAgICAgICAgICAgIChmdW5jdGlvbiAoZ2xvYmFsKSB7XG4gICAgICAgICAgICAgICAgXCJ1c2Ugc3RyaWN0XCI7XG5cbiAgICAgICAgICAgICAgICAvKmdsb2JhbCB3aW5kb3csIGdsb2JhbCovXG5cbiAgICAgICAgICAgICAgICB2YXIgcm9vdCA9IHR5cGVvZiB3aW5kb3cgIT09IFwidW5kZWZpbmVkXCIgPyB3aW5kb3cgOiB0eXBlb2YgZ2xvYmFsICE9PSBcInVuZGVmaW5lZFwiID8gZ2xvYmFsIDoge307XG5cbiAgICAgICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IEluZGl2aWR1YWw7XG5cbiAgICAgICAgICAgICAgICBmdW5jdGlvbiBJbmRpdmlkdWFsKGtleSwgdmFsdWUpIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKGtleSBpbiByb290KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gcm9vdFtrZXldO1xuICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgcm9vdFtrZXldID0gdmFsdWU7XG5cbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHZhbHVlO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0pLmNhbGwodGhpcywgdHlwZW9mIGdsb2JhbCAhPT0gXCJ1bmRlZmluZWRcIiA/IGdsb2JhbCA6IHR5cGVvZiBzZWxmICE9PSBcInVuZGVmaW5lZFwiID8gc2VsZiA6IHR5cGVvZiB3aW5kb3cgIT09IFwidW5kZWZpbmVkXCIgPyB3aW5kb3cgOiB7fSk7XG4gICAgICAgIH0sIHt9XSwgOTogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHtcbiAgICAgICAgICAgIFwidXNlIHN0cmljdFwiO1xuXG4gICAgICAgICAgICB2YXIgSW5kaXZpZHVhbCA9IHJlcXVpcmUoXCIuL2luZGV4LmpzXCIpO1xuXG4gICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IE9uZVZlcnNpb247XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIE9uZVZlcnNpb24obW9kdWxlTmFtZSwgdmVyc2lvbiwgZGVmYXVsdFZhbHVlKSB7XG4gICAgICAgICAgICAgICAgdmFyIGtleSA9IFwiX19JTkRJVklEVUFMX09ORV9WRVJTSU9OX1wiICsgbW9kdWxlTmFtZTtcbiAgICAgICAgICAgICAgICB2YXIgZW5mb3JjZUtleSA9IGtleSArIFwiX0VORk9SQ0VfU0lOR0xFVE9OXCI7XG5cbiAgICAgICAgICAgICAgICB2YXIgdmVyc2lvblZhbHVlID0gSW5kaXZpZHVhbChlbmZvcmNlS2V5LCB2ZXJzaW9uKTtcblxuICAgICAgICAgICAgICAgIGlmICh2ZXJzaW9uVmFsdWUgIT09IHZlcnNpb24pIHtcbiAgICAgICAgICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKFwiQ2FuIG9ubHkgaGF2ZSBvbmUgY29weSBvZiBcIiArIG1vZHVsZU5hbWUgKyBcIi5cXG5cIiArIFwiWW91IGFscmVhZHkgaGF2ZSB2ZXJzaW9uIFwiICsgdmVyc2lvblZhbHVlICsgXCIgaW5zdGFsbGVkLlxcblwiICsgXCJUaGlzIG1lYW5zIHlvdSBjYW5ub3QgaW5zdGFsbCB2ZXJzaW9uIFwiICsgdmVyc2lvbik7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgcmV0dXJuIEluZGl2aWR1YWwoa2V5LCBkZWZhdWx0VmFsdWUpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9LCB7IFwiLi9pbmRleC5qc1wiOiA4IH1dLCAxMDogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHtcbiAgICAgICAgICAgIChmdW5jdGlvbiAoZ2xvYmFsKSB7XG4gICAgICAgICAgICAgICAgdmFyIHRvcExldmVsID0gdHlwZW9mIGdsb2JhbCAhPT0gXCJ1bmRlZmluZWRcIiA/IGdsb2JhbCA6IHR5cGVvZiB3aW5kb3cgIT09IFwidW5kZWZpbmVkXCIgPyB3aW5kb3cgOiB7fTtcbiAgICAgICAgICAgICAgICB2YXIgbWluRG9jID0gcmVxdWlyZShcIm1pbi1kb2N1bWVudFwiKTtcblxuICAgICAgICAgICAgICAgIGlmICh0eXBlb2YgZG9jdW1lbnQgIT09IFwidW5kZWZpbmVkXCIpIHtcbiAgICAgICAgICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBkb2N1bWVudDtcbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICB2YXIgZG9jY3kgPSB0b3BMZXZlbFtcIl9fR0xPQkFMX0RPQ1VNRU5UX0NBQ0hFQDRcIl07XG5cbiAgICAgICAgICAgICAgICAgICAgaWYgKCFkb2NjeSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgZG9jY3kgPSB0b3BMZXZlbFtcIl9fR0xPQkFMX0RPQ1VNRU5UX0NBQ0hFQDRcIl0gPSBtaW5Eb2M7XG4gICAgICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IGRvY2N5O1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0pLmNhbGwodGhpcywgdHlwZW9mIGdsb2JhbCAhPT0gXCJ1bmRlZmluZWRcIiA/IGdsb2JhbCA6IHR5cGVvZiBzZWxmICE9PSBcInVuZGVmaW5lZFwiID8gc2VsZiA6IHR5cGVvZiB3aW5kb3cgIT09IFwidW5kZWZpbmVkXCIgPyB3aW5kb3cgOiB7fSk7XG4gICAgICAgIH0sIHsgXCJtaW4tZG9jdW1lbnRcIjogNiB9XSwgMTE6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICBcInVzZSBzdHJpY3RcIjtcblxuICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiBpc09iamVjdCh4KSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHR5cGVvZiB4ID09PSBcIm9iamVjdFwiICYmIHggIT09IG51bGw7XG4gICAgICAgICAgICB9O1xuICAgICAgICB9LCB7fV0sIDEyOiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge1xuICAgICAgICAgICAgdmFyIG5hdGl2ZUlzQXJyYXkgPSBBcnJheS5pc0FycmF5O1xuICAgICAgICAgICAgdmFyIHRvU3RyaW5nID0gT2JqZWN0LnByb3RvdHlwZS50b1N0cmluZztcblxuICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBuYXRpdmVJc0FycmF5IHx8IGlzQXJyYXk7XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIGlzQXJyYXkob2JqKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHRvU3RyaW5nLmNhbGwob2JqKSA9PT0gXCJbb2JqZWN0IEFycmF5XVwiO1xuICAgICAgICAgICAgfVxuICAgICAgICB9LCB7fV0sIDEzOiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge1xuICAgICAgICAgICAgdmFyIHBhdGNoID0gcmVxdWlyZShcIi4vdmRvbS9wYXRjaC5qc1wiKTtcblxuICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBwYXRjaDtcbiAgICAgICAgfSwgeyBcIi4vdmRvbS9wYXRjaC5qc1wiOiAxOCB9XSwgMTQ6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICB2YXIgaXNPYmplY3QgPSByZXF1aXJlKFwiaXMtb2JqZWN0XCIpO1xuICAgICAgICAgICAgdmFyIGlzSG9vayA9IHJlcXVpcmUoXCIuLi92bm9kZS9pcy12aG9vay5qc1wiKTtcblxuICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBhcHBseVByb3BlcnRpZXM7XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIGFwcGx5UHJvcGVydGllcyhub2RlLCBwcm9wcywgcHJldmlvdXMpIHtcbiAgICAgICAgICAgICAgICBmb3IgKHZhciBwcm9wTmFtZSBpbiBwcm9wcykge1xuICAgICAgICAgICAgICAgICAgICB2YXIgcHJvcFZhbHVlID0gcHJvcHNbcHJvcE5hbWVdO1xuXG4gICAgICAgICAgICAgICAgICAgIGlmIChwcm9wVmFsdWUgPT09IHVuZGVmaW5lZCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgcmVtb3ZlUHJvcGVydHkobm9kZSwgcHJvcE5hbWUsIHByb3BWYWx1ZSwgcHJldmlvdXMpO1xuICAgICAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKGlzSG9vayhwcm9wVmFsdWUpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICByZW1vdmVQcm9wZXJ0eShub2RlLCBwcm9wTmFtZSwgcHJvcFZhbHVlLCBwcmV2aW91cyk7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAocHJvcFZhbHVlLmhvb2spIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBwcm9wVmFsdWUuaG9vayhub2RlLCBwcm9wTmFtZSwgcHJldmlvdXMgPyBwcmV2aW91c1twcm9wTmFtZV0gOiB1bmRlZmluZWQpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGlzT2JqZWN0KHByb3BWYWx1ZSkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBwYXRjaE9iamVjdChub2RlLCBwcm9wcywgcHJldmlvdXMsIHByb3BOYW1lLCBwcm9wVmFsdWUpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBub2RlW3Byb3BOYW1lXSA9IHByb3BWYWx1ZTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZnVuY3Rpb24gcmVtb3ZlUHJvcGVydHkobm9kZSwgcHJvcE5hbWUsIHByb3BWYWx1ZSwgcHJldmlvdXMpIHtcbiAgICAgICAgICAgICAgICBpZiAocHJldmlvdXMpIHtcbiAgICAgICAgICAgICAgICAgICAgdmFyIHByZXZpb3VzVmFsdWUgPSBwcmV2aW91c1twcm9wTmFtZV07XG5cbiAgICAgICAgICAgICAgICAgICAgaWYgKCFpc0hvb2socHJldmlvdXNWYWx1ZSkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChwcm9wTmFtZSA9PT0gXCJhdHRyaWJ1dGVzXCIpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBmb3IgKHZhciBhdHRyTmFtZSBpbiBwcmV2aW91c1ZhbHVlKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG5vZGUucmVtb3ZlQXR0cmlidXRlKGF0dHJOYW1lKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKHByb3BOYW1lID09PSBcInN0eWxlXCIpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBmb3IgKHZhciBpIGluIHByZXZpb3VzVmFsdWUpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbm9kZS5zdHlsZVtpXSA9IFwiXCI7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIGlmICh0eXBlb2YgcHJldmlvdXNWYWx1ZSA9PT0gXCJzdHJpbmdcIikge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIG5vZGVbcHJvcE5hbWVdID0gXCJcIjtcbiAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgbm9kZVtwcm9wTmFtZV0gPSBudWxsO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKHByZXZpb3VzVmFsdWUudW5ob29rKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBwcmV2aW91c1ZhbHVlLnVuaG9vayhub2RlLCBwcm9wTmFtZSwgcHJvcFZhbHVlKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZnVuY3Rpb24gcGF0Y2hPYmplY3Qobm9kZSwgcHJvcHMsIHByZXZpb3VzLCBwcm9wTmFtZSwgcHJvcFZhbHVlKSB7XG4gICAgICAgICAgICAgICAgdmFyIHByZXZpb3VzVmFsdWUgPSBwcmV2aW91cyA/IHByZXZpb3VzW3Byb3BOYW1lXSA6IHVuZGVmaW5lZDtcblxuICAgICAgICAgICAgICAgIC8vIFNldCBhdHRyaWJ1dGVzXG4gICAgICAgICAgICAgICAgaWYgKHByb3BOYW1lID09PSBcImF0dHJpYnV0ZXNcIikge1xuICAgICAgICAgICAgICAgICAgICBmb3IgKHZhciBhdHRyTmFtZSBpbiBwcm9wVmFsdWUpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHZhciBhdHRyVmFsdWUgPSBwcm9wVmFsdWVbYXR0ck5hbWVdO1xuXG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoYXR0clZhbHVlID09PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBub2RlLnJlbW92ZUF0dHJpYnV0ZShhdHRyTmFtZSk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIG5vZGUuc2V0QXR0cmlidXRlKGF0dHJOYW1lLCBhdHRyVmFsdWUpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIGlmIChwcmV2aW91c1ZhbHVlICYmIGlzT2JqZWN0KHByZXZpb3VzVmFsdWUpICYmIGdldFByb3RvdHlwZShwcmV2aW91c1ZhbHVlKSAhPT0gZ2V0UHJvdG90eXBlKHByb3BWYWx1ZSkpIHtcbiAgICAgICAgICAgICAgICAgICAgbm9kZVtwcm9wTmFtZV0gPSBwcm9wVmFsdWU7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICBpZiAoIWlzT2JqZWN0KG5vZGVbcHJvcE5hbWVdKSkge1xuICAgICAgICAgICAgICAgICAgICBub2RlW3Byb3BOYW1lXSA9IHt9O1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHZhciByZXBsYWNlciA9IHByb3BOYW1lID09PSBcInN0eWxlXCIgPyBcIlwiIDogdW5kZWZpbmVkO1xuXG4gICAgICAgICAgICAgICAgZm9yICh2YXIgayBpbiBwcm9wVmFsdWUpIHtcbiAgICAgICAgICAgICAgICAgICAgdmFyIHZhbHVlID0gcHJvcFZhbHVlW2tdO1xuICAgICAgICAgICAgICAgICAgICBub2RlW3Byb3BOYW1lXVtrXSA9IHZhbHVlID09PSB1bmRlZmluZWQgPyByZXBsYWNlciA6IHZhbHVlO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZnVuY3Rpb24gZ2V0UHJvdG90eXBlKHZhbHVlKSB7XG4gICAgICAgICAgICAgICAgaWYgKE9iamVjdC5nZXRQcm90b3R5cGVPZikge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gT2JqZWN0LmdldFByb3RvdHlwZU9mKHZhbHVlKTtcbiAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKHZhbHVlLl9fcHJvdG9fXykge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gdmFsdWUuX19wcm90b19fO1xuICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAodmFsdWUuY29uc3RydWN0b3IpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHZhbHVlLmNvbnN0cnVjdG9yLnByb3RvdHlwZTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH0sIHsgXCIuLi92bm9kZS9pcy12aG9vay5qc1wiOiAyNiwgXCJpcy1vYmplY3RcIjogMTEgfV0sIDE1OiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge1xuICAgICAgICAgICAgdmFyIGRvY3VtZW50ID0gcmVxdWlyZShcImdsb2JhbC9kb2N1bWVudFwiKTtcblxuICAgICAgICAgICAgdmFyIGFwcGx5UHJvcGVydGllcyA9IHJlcXVpcmUoXCIuL2FwcGx5LXByb3BlcnRpZXNcIik7XG5cbiAgICAgICAgICAgIHZhciBpc1ZOb2RlID0gcmVxdWlyZShcIi4uL3Zub2RlL2lzLXZub2RlLmpzXCIpO1xuICAgICAgICAgICAgdmFyIGlzVlRleHQgPSByZXF1aXJlKFwiLi4vdm5vZGUvaXMtdnRleHQuanNcIik7XG4gICAgICAgICAgICB2YXIgaXNXaWRnZXQgPSByZXF1aXJlKFwiLi4vdm5vZGUvaXMtd2lkZ2V0LmpzXCIpO1xuICAgICAgICAgICAgdmFyIGhhbmRsZVRodW5rID0gcmVxdWlyZShcIi4uL3Zub2RlL2hhbmRsZS10aHVuay5qc1wiKTtcblxuICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBjcmVhdGVFbGVtZW50O1xuXG4gICAgICAgICAgICBmdW5jdGlvbiBjcmVhdGVFbGVtZW50KHZub2RlLCBvcHRzKSB7XG4gICAgICAgICAgICAgICAgdmFyIGRvYyA9IG9wdHMgPyBvcHRzLmRvY3VtZW50IHx8IGRvY3VtZW50IDogZG9jdW1lbnQ7XG4gICAgICAgICAgICAgICAgdmFyIHdhcm4gPSBvcHRzID8gb3B0cy53YXJuIDogbnVsbDtcblxuICAgICAgICAgICAgICAgIHZub2RlID0gaGFuZGxlVGh1bmsodm5vZGUpLmE7XG5cbiAgICAgICAgICAgICAgICBpZiAoaXNXaWRnZXQodm5vZGUpKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiB2bm9kZS5pbml0KCk7XG4gICAgICAgICAgICAgICAgfSBlbHNlIGlmIChpc1ZUZXh0KHZub2RlKSkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gZG9jLmNyZWF0ZVRleHROb2RlKHZub2RlLnRleHQpO1xuICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoIWlzVk5vZGUodm5vZGUpKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmICh3YXJuKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICB3YXJuKFwiSXRlbSBpcyBub3QgYSB2YWxpZCB2aXJ0dWFsIGRvbSBub2RlXCIsIHZub2RlKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICByZXR1cm4gbnVsbDtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICB2YXIgbm9kZSA9IHZub2RlLm5hbWVzcGFjZSA9PT0gbnVsbCA/IGRvYy5jcmVhdGVFbGVtZW50KHZub2RlLnRhZ05hbWUpIDogZG9jLmNyZWF0ZUVsZW1lbnROUyh2bm9kZS5uYW1lc3BhY2UsIHZub2RlLnRhZ05hbWUpO1xuXG4gICAgICAgICAgICAgICAgdmFyIHByb3BzID0gdm5vZGUucHJvcGVydGllcztcbiAgICAgICAgICAgICAgICBhcHBseVByb3BlcnRpZXMobm9kZSwgcHJvcHMpO1xuXG4gICAgICAgICAgICAgICAgdmFyIGNoaWxkcmVuID0gdm5vZGUuY2hpbGRyZW47XG5cbiAgICAgICAgICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IGNoaWxkcmVuLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciBjaGlsZE5vZGUgPSBjcmVhdGVFbGVtZW50KGNoaWxkcmVuW2ldLCBvcHRzKTtcbiAgICAgICAgICAgICAgICAgICAgaWYgKGNoaWxkTm9kZSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgbm9kZS5hcHBlbmRDaGlsZChjaGlsZE5vZGUpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgcmV0dXJuIG5vZGU7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0sIHsgXCIuLi92bm9kZS9oYW5kbGUtdGh1bmsuanNcIjogMjQsIFwiLi4vdm5vZGUvaXMtdm5vZGUuanNcIjogMjcsIFwiLi4vdm5vZGUvaXMtdnRleHQuanNcIjogMjgsIFwiLi4vdm5vZGUvaXMtd2lkZ2V0LmpzXCI6IDI5LCBcIi4vYXBwbHktcHJvcGVydGllc1wiOiAxNCwgXCJnbG9iYWwvZG9jdW1lbnRcIjogMTAgfV0sIDE2OiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge1xuICAgICAgICAgICAgLy8gTWFwcyBhIHZpcnR1YWwgRE9NIHRyZWUgb250byBhIHJlYWwgRE9NIHRyZWUgaW4gYW4gZWZmaWNpZW50IG1hbm5lci5cbiAgICAgICAgICAgIC8vIFdlIGRvbid0IHdhbnQgdG8gcmVhZCBhbGwgb2YgdGhlIERPTSBub2RlcyBpbiB0aGUgdHJlZSBzbyB3ZSB1c2VcbiAgICAgICAgICAgIC8vIHRoZSBpbi1vcmRlciB0cmVlIGluZGV4aW5nIHRvIGVsaW1pbmF0ZSByZWN1cnNpb24gZG93biBjZXJ0YWluIGJyYW5jaGVzLlxuICAgICAgICAgICAgLy8gV2Ugb25seSByZWN1cnNlIGludG8gYSBET00gbm9kZSBpZiB3ZSBrbm93IHRoYXQgaXQgY29udGFpbnMgYSBjaGlsZCBvZlxuICAgICAgICAgICAgLy8gaW50ZXJlc3QuXG5cbiAgICAgICAgICAgIHZhciBub0NoaWxkID0ge307XG5cbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gZG9tSW5kZXg7XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIGRvbUluZGV4KHJvb3ROb2RlLCB0cmVlLCBpbmRpY2VzLCBub2Rlcykge1xuICAgICAgICAgICAgICAgIGlmICghaW5kaWNlcyB8fCBpbmRpY2VzLmxlbmd0aCA9PT0gMCkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4ge307XG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgaW5kaWNlcy5zb3J0KGFzY2VuZGluZyk7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiByZWN1cnNlKHJvb3ROb2RlLCB0cmVlLCBpbmRpY2VzLCBub2RlcywgMCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBmdW5jdGlvbiByZWN1cnNlKHJvb3ROb2RlLCB0cmVlLCBpbmRpY2VzLCBub2Rlcywgcm9vdEluZGV4KSB7XG4gICAgICAgICAgICAgICAgbm9kZXMgPSBub2RlcyB8fCB7fTtcblxuICAgICAgICAgICAgICAgIGlmIChyb290Tm9kZSkge1xuICAgICAgICAgICAgICAgICAgICBpZiAoaW5kZXhJblJhbmdlKGluZGljZXMsIHJvb3RJbmRleCwgcm9vdEluZGV4KSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgbm9kZXNbcm9vdEluZGV4XSA9IHJvb3ROb2RlO1xuICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgdmFyIHZDaGlsZHJlbiA9IHRyZWUuY2hpbGRyZW47XG5cbiAgICAgICAgICAgICAgICAgICAgaWYgKHZDaGlsZHJlbikge1xuXG4gICAgICAgICAgICAgICAgICAgICAgICB2YXIgY2hpbGROb2RlcyA9IHJvb3ROb2RlLmNoaWxkTm9kZXM7XG5cbiAgICAgICAgICAgICAgICAgICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgdHJlZS5jaGlsZHJlbi5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJvb3RJbmRleCArPSAxO1xuXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdmFyIHZDaGlsZCA9IHZDaGlsZHJlbltpXSB8fCBub0NoaWxkO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZhciBuZXh0SW5kZXggPSByb290SW5kZXggKyAodkNoaWxkLmNvdW50IHx8IDApO1xuXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gc2tpcCByZWN1cnNpb24gZG93biB0aGUgdHJlZSBpZiB0aGVyZSBhcmUgbm8gbm9kZXMgZG93biBoZXJlXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGluZGV4SW5SYW5nZShpbmRpY2VzLCByb290SW5kZXgsIG5leHRJbmRleCkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmVjdXJzZShjaGlsZE5vZGVzW2ldLCB2Q2hpbGQsIGluZGljZXMsIG5vZGVzLCByb290SW5kZXgpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJvb3RJbmRleCA9IG5leHRJbmRleDtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHJldHVybiBub2RlcztcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgLy8gQmluYXJ5IHNlYXJjaCBmb3IgYW4gaW5kZXggaW4gdGhlIGludGVydmFsIFtsZWZ0LCByaWdodF1cbiAgICAgICAgICAgIGZ1bmN0aW9uIGluZGV4SW5SYW5nZShpbmRpY2VzLCBsZWZ0LCByaWdodCkge1xuICAgICAgICAgICAgICAgIGlmIChpbmRpY2VzLmxlbmd0aCA9PT0gMCkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgdmFyIG1pbkluZGV4ID0gMDtcbiAgICAgICAgICAgICAgICB2YXIgbWF4SW5kZXggPSBpbmRpY2VzLmxlbmd0aCAtIDE7XG4gICAgICAgICAgICAgICAgdmFyIGN1cnJlbnRJbmRleDtcbiAgICAgICAgICAgICAgICB2YXIgY3VycmVudEl0ZW07XG5cbiAgICAgICAgICAgICAgICB3aGlsZSAobWluSW5kZXggPD0gbWF4SW5kZXgpIHtcbiAgICAgICAgICAgICAgICAgICAgY3VycmVudEluZGV4ID0gKG1heEluZGV4ICsgbWluSW5kZXgpIC8gMiA+PiAwO1xuICAgICAgICAgICAgICAgICAgICBjdXJyZW50SXRlbSA9IGluZGljZXNbY3VycmVudEluZGV4XTtcblxuICAgICAgICAgICAgICAgICAgICBpZiAobWluSW5kZXggPT09IG1heEluZGV4KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gY3VycmVudEl0ZW0gPj0gbGVmdCAmJiBjdXJyZW50SXRlbSA8PSByaWdodDtcbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIGlmIChjdXJyZW50SXRlbSA8IGxlZnQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIG1pbkluZGV4ID0gY3VycmVudEluZGV4ICsgMTtcbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIGlmIChjdXJyZW50SXRlbSA+IHJpZ2h0KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBtYXhJbmRleCA9IGN1cnJlbnRJbmRleCAtIDE7XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZnVuY3Rpb24gYXNjZW5kaW5nKGEsIGIpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gYSA+IGIgPyAxIDogLTE7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0sIHt9XSwgMTc6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICB2YXIgYXBwbHlQcm9wZXJ0aWVzID0gcmVxdWlyZShcIi4vYXBwbHktcHJvcGVydGllc1wiKTtcblxuICAgICAgICAgICAgdmFyIGlzV2lkZ2V0ID0gcmVxdWlyZShcIi4uL3Zub2RlL2lzLXdpZGdldC5qc1wiKTtcbiAgICAgICAgICAgIHZhciBWUGF0Y2ggPSByZXF1aXJlKFwiLi4vdm5vZGUvdnBhdGNoLmpzXCIpO1xuXG4gICAgICAgICAgICB2YXIgdXBkYXRlV2lkZ2V0ID0gcmVxdWlyZShcIi4vdXBkYXRlLXdpZGdldFwiKTtcblxuICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBhcHBseVBhdGNoO1xuXG4gICAgICAgICAgICBmdW5jdGlvbiBhcHBseVBhdGNoKHZwYXRjaCwgZG9tTm9kZSwgcmVuZGVyT3B0aW9ucykge1xuICAgICAgICAgICAgICAgIHZhciB0eXBlID0gdnBhdGNoLnR5cGU7XG4gICAgICAgICAgICAgICAgdmFyIHZOb2RlID0gdnBhdGNoLnZOb2RlO1xuICAgICAgICAgICAgICAgIHZhciBwYXRjaCA9IHZwYXRjaC5wYXRjaDtcblxuICAgICAgICAgICAgICAgIHN3aXRjaCAodHlwZSkge1xuICAgICAgICAgICAgICAgICAgICBjYXNlIFZQYXRjaC5SRU1PVkU6XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gcmVtb3ZlTm9kZShkb21Ob2RlLCB2Tm9kZSk7XG4gICAgICAgICAgICAgICAgICAgIGNhc2UgVlBhdGNoLklOU0VSVDpcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBpbnNlcnROb2RlKGRvbU5vZGUsIHBhdGNoLCByZW5kZXJPcHRpb25zKTtcbiAgICAgICAgICAgICAgICAgICAgY2FzZSBWUGF0Y2guVlRFWFQ6XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gc3RyaW5nUGF0Y2goZG9tTm9kZSwgdk5vZGUsIHBhdGNoLCByZW5kZXJPcHRpb25zKTtcbiAgICAgICAgICAgICAgICAgICAgY2FzZSBWUGF0Y2guV0lER0VUOlxuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHdpZGdldFBhdGNoKGRvbU5vZGUsIHZOb2RlLCBwYXRjaCwgcmVuZGVyT3B0aW9ucyk7XG4gICAgICAgICAgICAgICAgICAgIGNhc2UgVlBhdGNoLlZOT0RFOlxuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHZOb2RlUGF0Y2goZG9tTm9kZSwgdk5vZGUsIHBhdGNoLCByZW5kZXJPcHRpb25zKTtcbiAgICAgICAgICAgICAgICAgICAgY2FzZSBWUGF0Y2guT1JERVI6XG4gICAgICAgICAgICAgICAgICAgICAgICByZW9yZGVyQ2hpbGRyZW4oZG9tTm9kZSwgcGF0Y2gpO1xuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGRvbU5vZGU7XG4gICAgICAgICAgICAgICAgICAgIGNhc2UgVlBhdGNoLlBST1BTOlxuICAgICAgICAgICAgICAgICAgICAgICAgYXBwbHlQcm9wZXJ0aWVzKGRvbU5vZGUsIHBhdGNoLCB2Tm9kZS5wcm9wZXJ0aWVzKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBkb21Ob2RlO1xuICAgICAgICAgICAgICAgICAgICBjYXNlIFZQYXRjaC5USFVOSzpcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiByZXBsYWNlUm9vdChkb21Ob2RlLCByZW5kZXJPcHRpb25zLnBhdGNoKGRvbU5vZGUsIHBhdGNoLCByZW5kZXJPcHRpb25zKSk7XG4gICAgICAgICAgICAgICAgICAgIGRlZmF1bHQ6XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gZG9tTm9kZTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIHJlbW92ZU5vZGUoZG9tTm9kZSwgdk5vZGUpIHtcbiAgICAgICAgICAgICAgICB2YXIgcGFyZW50Tm9kZSA9IGRvbU5vZGUucGFyZW50Tm9kZTtcblxuICAgICAgICAgICAgICAgIGlmIChwYXJlbnROb2RlKSB7XG4gICAgICAgICAgICAgICAgICAgIHBhcmVudE5vZGUucmVtb3ZlQ2hpbGQoZG9tTm9kZSk7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgZGVzdHJveVdpZGdldChkb21Ob2RlLCB2Tm9kZSk7XG5cbiAgICAgICAgICAgICAgICByZXR1cm4gbnVsbDtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZnVuY3Rpb24gaW5zZXJ0Tm9kZShwYXJlbnROb2RlLCB2Tm9kZSwgcmVuZGVyT3B0aW9ucykge1xuICAgICAgICAgICAgICAgIHZhciBuZXdOb2RlID0gcmVuZGVyT3B0aW9ucy5yZW5kZXIodk5vZGUsIHJlbmRlck9wdGlvbnMpO1xuXG4gICAgICAgICAgICAgICAgaWYgKHBhcmVudE5vZGUpIHtcbiAgICAgICAgICAgICAgICAgICAgcGFyZW50Tm9kZS5hcHBlbmRDaGlsZChuZXdOb2RlKTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICByZXR1cm4gcGFyZW50Tm9kZTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZnVuY3Rpb24gc3RyaW5nUGF0Y2goZG9tTm9kZSwgbGVmdFZOb2RlLCB2VGV4dCwgcmVuZGVyT3B0aW9ucykge1xuICAgICAgICAgICAgICAgIHZhciBuZXdOb2RlO1xuXG4gICAgICAgICAgICAgICAgaWYgKGRvbU5vZGUubm9kZVR5cGUgPT09IDMpIHtcbiAgICAgICAgICAgICAgICAgICAgZG9tTm9kZS5yZXBsYWNlRGF0YSgwLCBkb21Ob2RlLmxlbmd0aCwgdlRleHQudGV4dCk7XG4gICAgICAgICAgICAgICAgICAgIG5ld05vZGUgPSBkb21Ob2RlO1xuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciBwYXJlbnROb2RlID0gZG9tTm9kZS5wYXJlbnROb2RlO1xuICAgICAgICAgICAgICAgICAgICBuZXdOb2RlID0gcmVuZGVyT3B0aW9ucy5yZW5kZXIodlRleHQsIHJlbmRlck9wdGlvbnMpO1xuXG4gICAgICAgICAgICAgICAgICAgIGlmIChwYXJlbnROb2RlICYmIG5ld05vZGUgIT09IGRvbU5vZGUpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHBhcmVudE5vZGUucmVwbGFjZUNoaWxkKG5ld05vZGUsIGRvbU5vZGUpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgcmV0dXJuIG5ld05vZGU7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIHdpZGdldFBhdGNoKGRvbU5vZGUsIGxlZnRWTm9kZSwgd2lkZ2V0LCByZW5kZXJPcHRpb25zKSB7XG4gICAgICAgICAgICAgICAgdmFyIHVwZGF0aW5nID0gdXBkYXRlV2lkZ2V0KGxlZnRWTm9kZSwgd2lkZ2V0KTtcbiAgICAgICAgICAgICAgICB2YXIgbmV3Tm9kZTtcblxuICAgICAgICAgICAgICAgIGlmICh1cGRhdGluZykge1xuICAgICAgICAgICAgICAgICAgICBuZXdOb2RlID0gd2lkZ2V0LnVwZGF0ZShsZWZ0Vk5vZGUsIGRvbU5vZGUpIHx8IGRvbU5vZGU7XG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgbmV3Tm9kZSA9IHJlbmRlck9wdGlvbnMucmVuZGVyKHdpZGdldCwgcmVuZGVyT3B0aW9ucyk7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgdmFyIHBhcmVudE5vZGUgPSBkb21Ob2RlLnBhcmVudE5vZGU7XG5cbiAgICAgICAgICAgICAgICBpZiAocGFyZW50Tm9kZSAmJiBuZXdOb2RlICE9PSBkb21Ob2RlKSB7XG4gICAgICAgICAgICAgICAgICAgIHBhcmVudE5vZGUucmVwbGFjZUNoaWxkKG5ld05vZGUsIGRvbU5vZGUpO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIGlmICghdXBkYXRpbmcpIHtcbiAgICAgICAgICAgICAgICAgICAgZGVzdHJveVdpZGdldChkb21Ob2RlLCBsZWZ0Vk5vZGUpO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHJldHVybiBuZXdOb2RlO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBmdW5jdGlvbiB2Tm9kZVBhdGNoKGRvbU5vZGUsIGxlZnRWTm9kZSwgdk5vZGUsIHJlbmRlck9wdGlvbnMpIHtcbiAgICAgICAgICAgICAgICB2YXIgcGFyZW50Tm9kZSA9IGRvbU5vZGUucGFyZW50Tm9kZTtcbiAgICAgICAgICAgICAgICB2YXIgbmV3Tm9kZSA9IHJlbmRlck9wdGlvbnMucmVuZGVyKHZOb2RlLCByZW5kZXJPcHRpb25zKTtcblxuICAgICAgICAgICAgICAgIGlmIChwYXJlbnROb2RlICYmIG5ld05vZGUgIT09IGRvbU5vZGUpIHtcbiAgICAgICAgICAgICAgICAgICAgcGFyZW50Tm9kZS5yZXBsYWNlQ2hpbGQobmV3Tm9kZSwgZG9tTm9kZSk7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgcmV0dXJuIG5ld05vZGU7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIGRlc3Ryb3lXaWRnZXQoZG9tTm9kZSwgdykge1xuICAgICAgICAgICAgICAgIGlmICh0eXBlb2Ygdy5kZXN0cm95ID09PSBcImZ1bmN0aW9uXCIgJiYgaXNXaWRnZXQodykpIHtcbiAgICAgICAgICAgICAgICAgICAgdy5kZXN0cm95KGRvbU5vZGUpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZnVuY3Rpb24gcmVvcmRlckNoaWxkcmVuKGRvbU5vZGUsIG1vdmVzKSB7XG4gICAgICAgICAgICAgICAgdmFyIGNoaWxkTm9kZXMgPSBkb21Ob2RlLmNoaWxkTm9kZXM7XG4gICAgICAgICAgICAgICAgdmFyIGtleU1hcCA9IHt9O1xuICAgICAgICAgICAgICAgIHZhciBub2RlO1xuICAgICAgICAgICAgICAgIHZhciByZW1vdmU7XG4gICAgICAgICAgICAgICAgdmFyIGluc2VydDtcblxuICAgICAgICAgICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgbW92ZXMucmVtb3Zlcy5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgICAgICAgICByZW1vdmUgPSBtb3Zlcy5yZW1vdmVzW2ldO1xuICAgICAgICAgICAgICAgICAgICBub2RlID0gY2hpbGROb2Rlc1tyZW1vdmUuZnJvbV07XG4gICAgICAgICAgICAgICAgICAgIGlmIChyZW1vdmUua2V5KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBrZXlNYXBbcmVtb3ZlLmtleV0gPSBub2RlO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIGRvbU5vZGUucmVtb3ZlQ2hpbGQobm9kZSk7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgdmFyIGxlbmd0aCA9IGNoaWxkTm9kZXMubGVuZ3RoO1xuICAgICAgICAgICAgICAgIGZvciAodmFyIGogPSAwOyBqIDwgbW92ZXMuaW5zZXJ0cy5sZW5ndGg7IGorKykge1xuICAgICAgICAgICAgICAgICAgICBpbnNlcnQgPSBtb3Zlcy5pbnNlcnRzW2pdO1xuICAgICAgICAgICAgICAgICAgICBub2RlID0ga2V5TWFwW2luc2VydC5rZXldO1xuICAgICAgICAgICAgICAgICAgICAvLyB0aGlzIGlzIHRoZSB3ZWlyZGVzdCBidWcgaSd2ZSBldmVyIHNlZW4gaW4gd2Via2l0XG4gICAgICAgICAgICAgICAgICAgIGRvbU5vZGUuaW5zZXJ0QmVmb3JlKG5vZGUsIGluc2VydC50byA+PSBsZW5ndGgrKyA/IG51bGwgOiBjaGlsZE5vZGVzW2luc2VydC50b10pO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZnVuY3Rpb24gcmVwbGFjZVJvb3Qob2xkUm9vdCwgbmV3Um9vdCkge1xuICAgICAgICAgICAgICAgIGlmIChvbGRSb290ICYmIG5ld1Jvb3QgJiYgb2xkUm9vdCAhPT0gbmV3Um9vdCAmJiBvbGRSb290LnBhcmVudE5vZGUpIHtcbiAgICAgICAgICAgICAgICAgICAgb2xkUm9vdC5wYXJlbnROb2RlLnJlcGxhY2VDaGlsZChuZXdSb290LCBvbGRSb290KTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICByZXR1cm4gbmV3Um9vdDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSwgeyBcIi4uL3Zub2RlL2lzLXdpZGdldC5qc1wiOiAyOSwgXCIuLi92bm9kZS92cGF0Y2guanNcIjogMzIsIFwiLi9hcHBseS1wcm9wZXJ0aWVzXCI6IDE0LCBcIi4vdXBkYXRlLXdpZGdldFwiOiAxOSB9XSwgMTg6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICB2YXIgZG9jdW1lbnQgPSByZXF1aXJlKFwiZ2xvYmFsL2RvY3VtZW50XCIpO1xuICAgICAgICAgICAgdmFyIGlzQXJyYXkgPSByZXF1aXJlKFwieC1pcy1hcnJheVwiKTtcblxuICAgICAgICAgICAgdmFyIHJlbmRlciA9IHJlcXVpcmUoXCIuL2NyZWF0ZS1lbGVtZW50XCIpO1xuICAgICAgICAgICAgdmFyIGRvbUluZGV4ID0gcmVxdWlyZShcIi4vZG9tLWluZGV4XCIpO1xuICAgICAgICAgICAgdmFyIHBhdGNoT3AgPSByZXF1aXJlKFwiLi9wYXRjaC1vcFwiKTtcbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gcGF0Y2g7XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIHBhdGNoKHJvb3ROb2RlLCBwYXRjaGVzLCByZW5kZXJPcHRpb25zKSB7XG4gICAgICAgICAgICAgICAgcmVuZGVyT3B0aW9ucyA9IHJlbmRlck9wdGlvbnMgfHwge307XG4gICAgICAgICAgICAgICAgcmVuZGVyT3B0aW9ucy5wYXRjaCA9IHJlbmRlck9wdGlvbnMucGF0Y2ggJiYgcmVuZGVyT3B0aW9ucy5wYXRjaCAhPT0gcGF0Y2ggPyByZW5kZXJPcHRpb25zLnBhdGNoIDogcGF0Y2hSZWN1cnNpdmU7XG4gICAgICAgICAgICAgICAgcmVuZGVyT3B0aW9ucy5yZW5kZXIgPSByZW5kZXJPcHRpb25zLnJlbmRlciB8fCByZW5kZXI7XG5cbiAgICAgICAgICAgICAgICByZXR1cm4gcmVuZGVyT3B0aW9ucy5wYXRjaChyb290Tm9kZSwgcGF0Y2hlcywgcmVuZGVyT3B0aW9ucyk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIHBhdGNoUmVjdXJzaXZlKHJvb3ROb2RlLCBwYXRjaGVzLCByZW5kZXJPcHRpb25zKSB7XG4gICAgICAgICAgICAgICAgdmFyIGluZGljZXMgPSBwYXRjaEluZGljZXMocGF0Y2hlcyk7XG5cbiAgICAgICAgICAgICAgICBpZiAoaW5kaWNlcy5sZW5ndGggPT09IDApIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHJvb3ROb2RlO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHZhciBpbmRleCA9IGRvbUluZGV4KHJvb3ROb2RlLCBwYXRjaGVzLmEsIGluZGljZXMpO1xuICAgICAgICAgICAgICAgIHZhciBvd25lckRvY3VtZW50ID0gcm9vdE5vZGUub3duZXJEb2N1bWVudDtcblxuICAgICAgICAgICAgICAgIGlmICghcmVuZGVyT3B0aW9ucy5kb2N1bWVudCAmJiBvd25lckRvY3VtZW50ICE9PSBkb2N1bWVudCkge1xuICAgICAgICAgICAgICAgICAgICByZW5kZXJPcHRpb25zLmRvY3VtZW50ID0gb3duZXJEb2N1bWVudDtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IGluZGljZXMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgICAgICAgICAgdmFyIG5vZGVJbmRleCA9IGluZGljZXNbaV07XG4gICAgICAgICAgICAgICAgICAgIHJvb3ROb2RlID0gYXBwbHlQYXRjaChyb290Tm9kZSwgaW5kZXhbbm9kZUluZGV4XSwgcGF0Y2hlc1tub2RlSW5kZXhdLCByZW5kZXJPcHRpb25zKTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICByZXR1cm4gcm9vdE5vZGU7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIGFwcGx5UGF0Y2gocm9vdE5vZGUsIGRvbU5vZGUsIHBhdGNoTGlzdCwgcmVuZGVyT3B0aW9ucykge1xuICAgICAgICAgICAgICAgIGlmICghZG9tTm9kZSkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gcm9vdE5vZGU7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgdmFyIG5ld05vZGU7XG5cbiAgICAgICAgICAgICAgICBpZiAoaXNBcnJheShwYXRjaExpc3QpKSB7XG4gICAgICAgICAgICAgICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgcGF0Y2hMaXN0Lmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBuZXdOb2RlID0gcGF0Y2hPcChwYXRjaExpc3RbaV0sIGRvbU5vZGUsIHJlbmRlck9wdGlvbnMpO1xuXG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoZG9tTm9kZSA9PT0gcm9vdE5vZGUpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICByb290Tm9kZSA9IG5ld05vZGU7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICBuZXdOb2RlID0gcGF0Y2hPcChwYXRjaExpc3QsIGRvbU5vZGUsIHJlbmRlck9wdGlvbnMpO1xuXG4gICAgICAgICAgICAgICAgICAgIGlmIChkb21Ob2RlID09PSByb290Tm9kZSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgcm9vdE5vZGUgPSBuZXdOb2RlO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgcmV0dXJuIHJvb3ROb2RlO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBmdW5jdGlvbiBwYXRjaEluZGljZXMocGF0Y2hlcykge1xuICAgICAgICAgICAgICAgIHZhciBpbmRpY2VzID0gW107XG5cbiAgICAgICAgICAgICAgICBmb3IgKHZhciBrZXkgaW4gcGF0Y2hlcykge1xuICAgICAgICAgICAgICAgICAgICBpZiAoa2V5ICE9PSBcImFcIikge1xuICAgICAgICAgICAgICAgICAgICAgICAgaW5kaWNlcy5wdXNoKE51bWJlcihrZXkpKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHJldHVybiBpbmRpY2VzO1xuICAgICAgICAgICAgfVxuICAgICAgICB9LCB7IFwiLi9jcmVhdGUtZWxlbWVudFwiOiAxNSwgXCIuL2RvbS1pbmRleFwiOiAxNiwgXCIuL3BhdGNoLW9wXCI6IDE3LCBcImdsb2JhbC9kb2N1bWVudFwiOiAxMCwgXCJ4LWlzLWFycmF5XCI6IDEyIH1dLCAxOTogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHtcbiAgICAgICAgICAgIHZhciBpc1dpZGdldCA9IHJlcXVpcmUoXCIuLi92bm9kZS9pcy13aWRnZXQuanNcIik7XG5cbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gdXBkYXRlV2lkZ2V0O1xuXG4gICAgICAgICAgICBmdW5jdGlvbiB1cGRhdGVXaWRnZXQoYSwgYikge1xuICAgICAgICAgICAgICAgIGlmIChpc1dpZGdldChhKSAmJiBpc1dpZGdldChiKSkge1xuICAgICAgICAgICAgICAgICAgICBpZiAoXCJuYW1lXCIgaW4gYSAmJiBcIm5hbWVcIiBpbiBiKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gYS5pZCA9PT0gYi5pZDtcbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBhLmluaXQgPT09IGIuaW5pdDtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSwgeyBcIi4uL3Zub2RlL2lzLXdpZGdldC5qc1wiOiAyOSB9XSwgMjA6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICBcInVzZSBzdHJpY3RcIjtcblxuICAgICAgICAgICAgdmFyIEV2U3RvcmUgPSByZXF1aXJlKFwiZXYtc3RvcmVcIik7XG5cbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gRXZIb29rO1xuXG4gICAgICAgICAgICBmdW5jdGlvbiBFdkhvb2sodmFsdWUpIHtcbiAgICAgICAgICAgICAgICBpZiAoISh0aGlzIGluc3RhbmNlb2YgRXZIb29rKSkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gbmV3IEV2SG9vayh2YWx1ZSk7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgdGhpcy52YWx1ZSA9IHZhbHVlO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBFdkhvb2sucHJvdG90eXBlLmhvb2sgPSBmdW5jdGlvbiAobm9kZSwgcHJvcGVydHlOYW1lKSB7XG4gICAgICAgICAgICAgICAgdmFyIGVzID0gRXZTdG9yZShub2RlKTtcbiAgICAgICAgICAgICAgICB2YXIgcHJvcE5hbWUgPSBwcm9wZXJ0eU5hbWUuc3Vic3RyKDMpO1xuXG4gICAgICAgICAgICAgICAgZXNbcHJvcE5hbWVdID0gdGhpcy52YWx1ZTtcbiAgICAgICAgICAgIH07XG5cbiAgICAgICAgICAgIEV2SG9vay5wcm90b3R5cGUudW5ob29rID0gZnVuY3Rpb24gKG5vZGUsIHByb3BlcnR5TmFtZSkge1xuICAgICAgICAgICAgICAgIHZhciBlcyA9IEV2U3RvcmUobm9kZSk7XG4gICAgICAgICAgICAgICAgdmFyIHByb3BOYW1lID0gcHJvcGVydHlOYW1lLnN1YnN0cigzKTtcblxuICAgICAgICAgICAgICAgIGVzW3Byb3BOYW1lXSA9IHVuZGVmaW5lZDtcbiAgICAgICAgICAgIH07XG4gICAgICAgIH0sIHsgXCJldi1zdG9yZVwiOiA3IH1dLCAyMTogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHtcbiAgICAgICAgICAgIFwidXNlIHN0cmljdFwiO1xuXG4gICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IFNvZnRTZXRIb29rO1xuXG4gICAgICAgICAgICBmdW5jdGlvbiBTb2Z0U2V0SG9vayh2YWx1ZSkge1xuICAgICAgICAgICAgICAgIGlmICghKHRoaXMgaW5zdGFuY2VvZiBTb2Z0U2V0SG9vaykpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIG5ldyBTb2Z0U2V0SG9vayh2YWx1ZSk7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgdGhpcy52YWx1ZSA9IHZhbHVlO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBTb2Z0U2V0SG9vay5wcm90b3R5cGUuaG9vayA9IGZ1bmN0aW9uIChub2RlLCBwcm9wZXJ0eU5hbWUpIHtcbiAgICAgICAgICAgICAgICBpZiAobm9kZVtwcm9wZXJ0eU5hbWVdICE9PSB0aGlzLnZhbHVlKSB7XG4gICAgICAgICAgICAgICAgICAgIG5vZGVbcHJvcGVydHlOYW1lXSA9IHRoaXMudmFsdWU7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfTtcbiAgICAgICAgfSwge31dLCAyMjogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHtcbiAgICAgICAgICAgIFwidXNlIHN0cmljdFwiO1xuXG4gICAgICAgICAgICB2YXIgaXNBcnJheSA9IHJlcXVpcmUoXCJ4LWlzLWFycmF5XCIpO1xuXG4gICAgICAgICAgICB2YXIgVk5vZGUgPSByZXF1aXJlKFwiLi4vdm5vZGUvdm5vZGUuanNcIik7XG4gICAgICAgICAgICB2YXIgVlRleHQgPSByZXF1aXJlKFwiLi4vdm5vZGUvdnRleHQuanNcIik7XG4gICAgICAgICAgICB2YXIgaXNWTm9kZSA9IHJlcXVpcmUoXCIuLi92bm9kZS9pcy12bm9kZVwiKTtcbiAgICAgICAgICAgIHZhciBpc1ZUZXh0ID0gcmVxdWlyZShcIi4uL3Zub2RlL2lzLXZ0ZXh0XCIpO1xuICAgICAgICAgICAgdmFyIGlzV2lkZ2V0ID0gcmVxdWlyZShcIi4uL3Zub2RlL2lzLXdpZGdldFwiKTtcbiAgICAgICAgICAgIHZhciBpc0hvb2sgPSByZXF1aXJlKFwiLi4vdm5vZGUvaXMtdmhvb2tcIik7XG4gICAgICAgICAgICB2YXIgaXNWVGh1bmsgPSByZXF1aXJlKFwiLi4vdm5vZGUvaXMtdGh1bmtcIik7XG5cbiAgICAgICAgICAgIHZhciBwYXJzZVRhZyA9IHJlcXVpcmUoXCIuL3BhcnNlLXRhZy5qc1wiKTtcbiAgICAgICAgICAgIHZhciBzb2Z0U2V0SG9vayA9IHJlcXVpcmUoXCIuL2hvb2tzL3NvZnQtc2V0LWhvb2suanNcIik7XG4gICAgICAgICAgICB2YXIgZXZIb29rID0gcmVxdWlyZShcIi4vaG9va3MvZXYtaG9vay5qc1wiKTtcblxuICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBoO1xuXG4gICAgICAgICAgICBmdW5jdGlvbiBoKHRhZ05hbWUsIHByb3BlcnRpZXMsIGNoaWxkcmVuKSB7XG4gICAgICAgICAgICAgICAgdmFyIGNoaWxkTm9kZXMgPSBbXTtcbiAgICAgICAgICAgICAgICB2YXIgdGFnLCBwcm9wcywga2V5LCBuYW1lc3BhY2U7XG5cbiAgICAgICAgICAgICAgICBpZiAoIWNoaWxkcmVuICYmIGlzQ2hpbGRyZW4ocHJvcGVydGllcykpIHtcbiAgICAgICAgICAgICAgICAgICAgY2hpbGRyZW4gPSBwcm9wZXJ0aWVzO1xuICAgICAgICAgICAgICAgICAgICBwcm9wcyA9IHt9O1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHByb3BzID0gcHJvcHMgfHwgcHJvcGVydGllcyB8fCB7fTtcbiAgICAgICAgICAgICAgICB0YWcgPSBwYXJzZVRhZyh0YWdOYW1lLCBwcm9wcyk7XG5cbiAgICAgICAgICAgICAgICAvLyBzdXBwb3J0IGtleXNcbiAgICAgICAgICAgICAgICBpZiAocHJvcHMuaGFzT3duUHJvcGVydHkoXCJrZXlcIikpIHtcbiAgICAgICAgICAgICAgICAgICAga2V5ID0gcHJvcHMua2V5O1xuICAgICAgICAgICAgICAgICAgICBwcm9wcy5rZXkgPSB1bmRlZmluZWQ7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgLy8gc3VwcG9ydCBuYW1lc3BhY2VcbiAgICAgICAgICAgICAgICBpZiAocHJvcHMuaGFzT3duUHJvcGVydHkoXCJuYW1lc3BhY2VcIikpIHtcbiAgICAgICAgICAgICAgICAgICAgbmFtZXNwYWNlID0gcHJvcHMubmFtZXNwYWNlO1xuICAgICAgICAgICAgICAgICAgICBwcm9wcy5uYW1lc3BhY2UgPSB1bmRlZmluZWQ7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgLy8gZml4IGN1cnNvciBidWdcbiAgICAgICAgICAgICAgICBpZiAodGFnID09PSBcIklOUFVUXCIgJiYgIW5hbWVzcGFjZSAmJiBwcm9wcy5oYXNPd25Qcm9wZXJ0eShcInZhbHVlXCIpICYmIHByb3BzLnZhbHVlICE9PSB1bmRlZmluZWQgJiYgIWlzSG9vayhwcm9wcy52YWx1ZSkpIHtcbiAgICAgICAgICAgICAgICAgICAgcHJvcHMudmFsdWUgPSBzb2Z0U2V0SG9vayhwcm9wcy52YWx1ZSk7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgdHJhbnNmb3JtUHJvcGVydGllcyhwcm9wcyk7XG5cbiAgICAgICAgICAgICAgICBpZiAoY2hpbGRyZW4gIT09IHVuZGVmaW5lZCAmJiBjaGlsZHJlbiAhPT0gbnVsbCkge1xuICAgICAgICAgICAgICAgICAgICBhZGRDaGlsZChjaGlsZHJlbiwgY2hpbGROb2RlcywgdGFnLCBwcm9wcyk7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgcmV0dXJuIG5ldyBWTm9kZSh0YWcsIHByb3BzLCBjaGlsZE5vZGVzLCBrZXksIG5hbWVzcGFjZSk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIGFkZENoaWxkKGMsIGNoaWxkTm9kZXMsIHRhZywgcHJvcHMpIHtcbiAgICAgICAgICAgICAgICBpZiAodHlwZW9mIGMgPT09IFwic3RyaW5nXCIpIHtcbiAgICAgICAgICAgICAgICAgICAgY2hpbGROb2Rlcy5wdXNoKG5ldyBWVGV4dChjKSk7XG4gICAgICAgICAgICAgICAgfSBlbHNlIGlmICh0eXBlb2YgYyA9PT0gXCJudW1iZXJcIikge1xuICAgICAgICAgICAgICAgICAgICBjaGlsZE5vZGVzLnB1c2gobmV3IFZUZXh0KFN0cmluZyhjKSkpO1xuICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoaXNDaGlsZChjKSkge1xuICAgICAgICAgICAgICAgICAgICBjaGlsZE5vZGVzLnB1c2goYyk7XG4gICAgICAgICAgICAgICAgfSBlbHNlIGlmIChpc0FycmF5KGMpKSB7XG4gICAgICAgICAgICAgICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgYy5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgICAgICAgICAgICAgYWRkQ2hpbGQoY1tpXSwgY2hpbGROb2RlcywgdGFnLCBwcm9wcyk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKGMgPT09IG51bGwgfHwgYyA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICB0aHJvdyBVbmV4cGVjdGVkVmlydHVhbEVsZW1lbnQoe1xuICAgICAgICAgICAgICAgICAgICAgICAgZm9yZWlnbk9iamVjdDogYyxcbiAgICAgICAgICAgICAgICAgICAgICAgIHBhcmVudFZub2RlOiB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdGFnTmFtZTogdGFnLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHByb3BlcnRpZXM6IHByb3BzXG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZnVuY3Rpb24gdHJhbnNmb3JtUHJvcGVydGllcyhwcm9wcykge1xuICAgICAgICAgICAgICAgIGZvciAodmFyIHByb3BOYW1lIGluIHByb3BzKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmIChwcm9wcy5oYXNPd25Qcm9wZXJ0eShwcm9wTmFtZSkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHZhciB2YWx1ZSA9IHByb3BzW3Byb3BOYW1lXTtcblxuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGlzSG9vayh2YWx1ZSkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb250aW51ZTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHByb3BOYW1lLnN1YnN0cigwLCAzKSA9PT0gXCJldi1cIikge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIGFkZCBldi1mb28gc3VwcG9ydFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHByb3BzW3Byb3BOYW1lXSA9IGV2SG9vayh2YWx1ZSk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIGlzQ2hpbGQoeCkge1xuICAgICAgICAgICAgICAgIHJldHVybiBpc1ZOb2RlKHgpIHx8IGlzVlRleHQoeCkgfHwgaXNXaWRnZXQoeCkgfHwgaXNWVGh1bmsoeCk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIGlzQ2hpbGRyZW4oeCkge1xuICAgICAgICAgICAgICAgIHJldHVybiB0eXBlb2YgeCA9PT0gXCJzdHJpbmdcIiB8fCBpc0FycmF5KHgpIHx8IGlzQ2hpbGQoeCk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIFVuZXhwZWN0ZWRWaXJ0dWFsRWxlbWVudChkYXRhKSB7XG4gICAgICAgICAgICAgICAgdmFyIGVyciA9IG5ldyBFcnJvcigpO1xuXG4gICAgICAgICAgICAgICAgZXJyLnR5cGUgPSBcInZpcnR1YWwtaHlwZXJzY3JpcHQudW5leHBlY3RlZC52aXJ0dWFsLWVsZW1lbnRcIjtcbiAgICAgICAgICAgICAgICBlcnIubWVzc2FnZSA9IFwiVW5leHBlY3RlZCB2aXJ0dWFsIGNoaWxkIHBhc3NlZCB0byBoKCkuXFxuXCIgKyBcIkV4cGVjdGVkIGEgVk5vZGUgLyBWdGh1bmsgLyBWV2lkZ2V0IC8gc3RyaW5nIGJ1dDpcXG5cIiArIFwiZ290OlxcblwiICsgZXJyb3JTdHJpbmcoZGF0YS5mb3JlaWduT2JqZWN0KSArIFwiLlxcblwiICsgXCJUaGUgcGFyZW50IHZub2RlIGlzOlxcblwiICsgZXJyb3JTdHJpbmcoZGF0YS5wYXJlbnRWbm9kZSk7XG4gICAgICAgICAgICAgICAgXCJcXG5cIiArIFwiU3VnZ2VzdGVkIGZpeDogY2hhbmdlIHlvdXIgYGgoLi4uLCBbIC4uLiBdKWAgY2FsbHNpdGUuXCI7XG4gICAgICAgICAgICAgICAgZXJyLmZvcmVpZ25PYmplY3QgPSBkYXRhLmZvcmVpZ25PYmplY3Q7XG4gICAgICAgICAgICAgICAgZXJyLnBhcmVudFZub2RlID0gZGF0YS5wYXJlbnRWbm9kZTtcblxuICAgICAgICAgICAgICAgIHJldHVybiBlcnI7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIGVycm9yU3RyaW5nKG9iaikge1xuICAgICAgICAgICAgICAgIHRyeSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBKU09OLnN0cmluZ2lmeShvYmosIG51bGwsIFwiICAgIFwiKTtcbiAgICAgICAgICAgICAgICB9IGNhdGNoIChlKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBTdHJpbmcob2JqKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH0sIHsgXCIuLi92bm9kZS9pcy10aHVua1wiOiAyNSwgXCIuLi92bm9kZS9pcy12aG9va1wiOiAyNiwgXCIuLi92bm9kZS9pcy12bm9kZVwiOiAyNywgXCIuLi92bm9kZS9pcy12dGV4dFwiOiAyOCwgXCIuLi92bm9kZS9pcy13aWRnZXRcIjogMjksIFwiLi4vdm5vZGUvdm5vZGUuanNcIjogMzEsIFwiLi4vdm5vZGUvdnRleHQuanNcIjogMzMsIFwiLi9ob29rcy9ldi1ob29rLmpzXCI6IDIwLCBcIi4vaG9va3Mvc29mdC1zZXQtaG9vay5qc1wiOiAyMSwgXCIuL3BhcnNlLXRhZy5qc1wiOiAyMywgXCJ4LWlzLWFycmF5XCI6IDEyIH1dLCAyMzogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHtcbiAgICAgICAgICAgIFwidXNlIHN0cmljdFwiO1xuXG4gICAgICAgICAgICB2YXIgc3BsaXQgPSByZXF1aXJlKFwiYnJvd3Nlci1zcGxpdFwiKTtcblxuICAgICAgICAgICAgdmFyIGNsYXNzSWRTcGxpdCA9IC8oW1xcLiNdP1thLXpBLVowLTlcXHUwMDdGLVxcdUZGRkZfOi1dKykvO1xuICAgICAgICAgICAgdmFyIG5vdENsYXNzSWQgPSAvXlxcLnwjLztcblxuICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBwYXJzZVRhZztcblxuICAgICAgICAgICAgZnVuY3Rpb24gcGFyc2VUYWcodGFnLCBwcm9wcykge1xuICAgICAgICAgICAgICAgIGlmICghdGFnKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBcIkRJVlwiO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHZhciBub0lkID0gIXByb3BzLmhhc093blByb3BlcnR5KFwiaWRcIik7XG5cbiAgICAgICAgICAgICAgICB2YXIgdGFnUGFydHMgPSBzcGxpdCh0YWcsIGNsYXNzSWRTcGxpdCk7XG4gICAgICAgICAgICAgICAgdmFyIHRhZ05hbWUgPSBudWxsO1xuXG4gICAgICAgICAgICAgICAgaWYgKG5vdENsYXNzSWQudGVzdCh0YWdQYXJ0c1sxXSkpIHtcbiAgICAgICAgICAgICAgICAgICAgdGFnTmFtZSA9IFwiRElWXCI7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgdmFyIGNsYXNzZXMsIHBhcnQsIHR5cGUsIGk7XG5cbiAgICAgICAgICAgICAgICBmb3IgKGkgPSAwOyBpIDwgdGFnUGFydHMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgICAgICAgICAgcGFydCA9IHRhZ1BhcnRzW2ldO1xuXG4gICAgICAgICAgICAgICAgICAgIGlmICghcGFydCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgY29udGludWU7XG4gICAgICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgICAgICB0eXBlID0gcGFydC5jaGFyQXQoMCk7XG5cbiAgICAgICAgICAgICAgICAgICAgaWYgKCF0YWdOYW1lKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICB0YWdOYW1lID0gcGFydDtcbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIGlmICh0eXBlID09PSBcIi5cIikge1xuICAgICAgICAgICAgICAgICAgICAgICAgY2xhc3NlcyA9IGNsYXNzZXMgfHwgW107XG4gICAgICAgICAgICAgICAgICAgICAgICBjbGFzc2VzLnB1c2gocGFydC5zdWJzdHJpbmcoMSwgcGFydC5sZW5ndGgpKTtcbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIGlmICh0eXBlID09PSBcIiNcIiAmJiBub0lkKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBwcm9wcy5pZCA9IHBhcnQuc3Vic3RyaW5nKDEsIHBhcnQubGVuZ3RoKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIGlmIChjbGFzc2VzKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmIChwcm9wcy5jbGFzc05hbWUpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGNsYXNzZXMucHVzaChwcm9wcy5jbGFzc05hbWUpO1xuICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgcHJvcHMuY2xhc3NOYW1lID0gY2xhc3Nlcy5qb2luKFwiIFwiKTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICByZXR1cm4gcHJvcHMubmFtZXNwYWNlID8gdGFnTmFtZSA6IHRhZ05hbWUudG9VcHBlckNhc2UoKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSwgeyBcImJyb3dzZXItc3BsaXRcIjogNSB9XSwgMjQ6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICB2YXIgaXNWTm9kZSA9IHJlcXVpcmUoXCIuL2lzLXZub2RlXCIpO1xuICAgICAgICAgICAgdmFyIGlzVlRleHQgPSByZXF1aXJlKFwiLi9pcy12dGV4dFwiKTtcbiAgICAgICAgICAgIHZhciBpc1dpZGdldCA9IHJlcXVpcmUoXCIuL2lzLXdpZGdldFwiKTtcbiAgICAgICAgICAgIHZhciBpc1RodW5rID0gcmVxdWlyZShcIi4vaXMtdGh1bmtcIik7XG5cbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gaGFuZGxlVGh1bms7XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIGhhbmRsZVRodW5rKGEsIGIpIHtcbiAgICAgICAgICAgICAgICB2YXIgcmVuZGVyZWRBID0gYTtcbiAgICAgICAgICAgICAgICB2YXIgcmVuZGVyZWRCID0gYjtcblxuICAgICAgICAgICAgICAgIGlmIChpc1RodW5rKGIpKSB7XG4gICAgICAgICAgICAgICAgICAgIHJlbmRlcmVkQiA9IHJlbmRlclRodW5rKGIsIGEpO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIGlmIChpc1RodW5rKGEpKSB7XG4gICAgICAgICAgICAgICAgICAgIHJlbmRlcmVkQSA9IHJlbmRlclRodW5rKGEsIG51bGwpO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHJldHVybiB7XG4gICAgICAgICAgICAgICAgICAgIGE6IHJlbmRlcmVkQSxcbiAgICAgICAgICAgICAgICAgICAgYjogcmVuZGVyZWRCXG4gICAgICAgICAgICAgICAgfTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZnVuY3Rpb24gcmVuZGVyVGh1bmsodGh1bmssIHByZXZpb3VzKSB7XG4gICAgICAgICAgICAgICAgdmFyIHJlbmRlcmVkVGh1bmsgPSB0aHVuay52bm9kZTtcblxuICAgICAgICAgICAgICAgIGlmICghcmVuZGVyZWRUaHVuaykge1xuICAgICAgICAgICAgICAgICAgICByZW5kZXJlZFRodW5rID0gdGh1bmsudm5vZGUgPSB0aHVuay5yZW5kZXIocHJldmlvdXMpO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIGlmICghKGlzVk5vZGUocmVuZGVyZWRUaHVuaykgfHwgaXNWVGV4dChyZW5kZXJlZFRodW5rKSB8fCBpc1dpZGdldChyZW5kZXJlZFRodW5rKSkpIHtcbiAgICAgICAgICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKFwidGh1bmsgZGlkIG5vdCByZXR1cm4gYSB2YWxpZCBub2RlXCIpO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHJldHVybiByZW5kZXJlZFRodW5rO1xuICAgICAgICAgICAgfVxuICAgICAgICB9LCB7IFwiLi9pcy10aHVua1wiOiAyNSwgXCIuL2lzLXZub2RlXCI6IDI3LCBcIi4vaXMtdnRleHRcIjogMjgsIFwiLi9pcy13aWRnZXRcIjogMjkgfV0sIDI1OiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge1xuICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBpc1RodW5rO1xuXG4gICAgICAgICAgICBmdW5jdGlvbiBpc1RodW5rKHQpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gdCAmJiB0LnR5cGUgPT09IFwiVGh1bmtcIjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSwge31dLCAyNjogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHtcbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gaXNIb29rO1xuXG4gICAgICAgICAgICBmdW5jdGlvbiBpc0hvb2soaG9vaykge1xuICAgICAgICAgICAgICAgIHJldHVybiBob29rICYmICh0eXBlb2YgaG9vay5ob29rID09PSBcImZ1bmN0aW9uXCIgJiYgIWhvb2suaGFzT3duUHJvcGVydHkoXCJob29rXCIpIHx8IHR5cGVvZiBob29rLnVuaG9vayA9PT0gXCJmdW5jdGlvblwiICYmICFob29rLmhhc093blByb3BlcnR5KFwidW5ob29rXCIpKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSwge31dLCAyNzogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHtcbiAgICAgICAgICAgIHZhciB2ZXJzaW9uID0gcmVxdWlyZShcIi4vdmVyc2lvblwiKTtcblxuICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBpc1ZpcnR1YWxOb2RlO1xuXG4gICAgICAgICAgICBmdW5jdGlvbiBpc1ZpcnR1YWxOb2RlKHgpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4geCAmJiB4LnR5cGUgPT09IFwiVmlydHVhbE5vZGVcIiAmJiB4LnZlcnNpb24gPT09IHZlcnNpb247XG4gICAgICAgICAgICB9XG4gICAgICAgIH0sIHsgXCIuL3ZlcnNpb25cIjogMzAgfV0sIDI4OiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge1xuICAgICAgICAgICAgdmFyIHZlcnNpb24gPSByZXF1aXJlKFwiLi92ZXJzaW9uXCIpO1xuXG4gICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IGlzVmlydHVhbFRleHQ7XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIGlzVmlydHVhbFRleHQoeCkge1xuICAgICAgICAgICAgICAgIHJldHVybiB4ICYmIHgudHlwZSA9PT0gXCJWaXJ0dWFsVGV4dFwiICYmIHgudmVyc2lvbiA9PT0gdmVyc2lvbjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSwgeyBcIi4vdmVyc2lvblwiOiAzMCB9XSwgMjk6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IGlzV2lkZ2V0O1xuXG4gICAgICAgICAgICBmdW5jdGlvbiBpc1dpZGdldCh3KSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHcgJiYgdy50eXBlID09PSBcIldpZGdldFwiO1xuICAgICAgICAgICAgfVxuICAgICAgICB9LCB7fV0sIDMwOiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge1xuICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBcIjJcIjtcbiAgICAgICAgfSwge31dLCAzMTogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHtcbiAgICAgICAgICAgIHZhciB2ZXJzaW9uID0gcmVxdWlyZShcIi4vdmVyc2lvblwiKTtcbiAgICAgICAgICAgIHZhciBpc1ZOb2RlID0gcmVxdWlyZShcIi4vaXMtdm5vZGVcIik7XG4gICAgICAgICAgICB2YXIgaXNXaWRnZXQgPSByZXF1aXJlKFwiLi9pcy13aWRnZXRcIik7XG4gICAgICAgICAgICB2YXIgaXNUaHVuayA9IHJlcXVpcmUoXCIuL2lzLXRodW5rXCIpO1xuICAgICAgICAgICAgdmFyIGlzVkhvb2sgPSByZXF1aXJlKFwiLi9pcy12aG9va1wiKTtcblxuICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBWaXJ0dWFsTm9kZTtcblxuICAgICAgICAgICAgdmFyIG5vUHJvcGVydGllcyA9IHt9O1xuICAgICAgICAgICAgdmFyIG5vQ2hpbGRyZW4gPSBbXTtcblxuICAgICAgICAgICAgZnVuY3Rpb24gVmlydHVhbE5vZGUodGFnTmFtZSwgcHJvcGVydGllcywgY2hpbGRyZW4sIGtleSwgbmFtZXNwYWNlKSB7XG4gICAgICAgICAgICAgICAgdGhpcy50YWdOYW1lID0gdGFnTmFtZTtcbiAgICAgICAgICAgICAgICB0aGlzLnByb3BlcnRpZXMgPSBwcm9wZXJ0aWVzIHx8IG5vUHJvcGVydGllcztcbiAgICAgICAgICAgICAgICB0aGlzLmNoaWxkcmVuID0gY2hpbGRyZW4gfHwgbm9DaGlsZHJlbjtcbiAgICAgICAgICAgICAgICB0aGlzLmtleSA9IGtleSAhPSBudWxsID8gU3RyaW5nKGtleSkgOiB1bmRlZmluZWQ7XG4gICAgICAgICAgICAgICAgdGhpcy5uYW1lc3BhY2UgPSB0eXBlb2YgbmFtZXNwYWNlID09PSBcInN0cmluZ1wiID8gbmFtZXNwYWNlIDogbnVsbDtcblxuICAgICAgICAgICAgICAgIHZhciBjb3VudCA9IGNoaWxkcmVuICYmIGNoaWxkcmVuLmxlbmd0aCB8fCAwO1xuICAgICAgICAgICAgICAgIHZhciBkZXNjZW5kYW50cyA9IDA7XG4gICAgICAgICAgICAgICAgdmFyIGhhc1dpZGdldHMgPSBmYWxzZTtcbiAgICAgICAgICAgICAgICB2YXIgaGFzVGh1bmtzID0gZmFsc2U7XG4gICAgICAgICAgICAgICAgdmFyIGRlc2NlbmRhbnRIb29rcyA9IGZhbHNlO1xuICAgICAgICAgICAgICAgIHZhciBob29rcztcblxuICAgICAgICAgICAgICAgIGZvciAodmFyIHByb3BOYW1lIGluIHByb3BlcnRpZXMpIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKHByb3BlcnRpZXMuaGFzT3duUHJvcGVydHkocHJvcE5hbWUpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICB2YXIgcHJvcGVydHkgPSBwcm9wZXJ0aWVzW3Byb3BOYW1lXTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChpc1ZIb29rKHByb3BlcnR5KSAmJiBwcm9wZXJ0eS51bmhvb2spIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoIWhvb2tzKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGhvb2tzID0ge307XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaG9va3NbcHJvcE5hbWVdID0gcHJvcGVydHk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IGNvdW50OyBpKyspIHtcbiAgICAgICAgICAgICAgICAgICAgdmFyIGNoaWxkID0gY2hpbGRyZW5baV07XG4gICAgICAgICAgICAgICAgICAgIGlmIChpc1ZOb2RlKGNoaWxkKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgZGVzY2VuZGFudHMgKz0gY2hpbGQuY291bnQgfHwgMDtcblxuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKCFoYXNXaWRnZXRzICYmIGNoaWxkLmhhc1dpZGdldHMpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBoYXNXaWRnZXRzID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKCFoYXNUaHVua3MgJiYgY2hpbGQuaGFzVGh1bmtzKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaGFzVGh1bmtzID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKCFkZXNjZW5kYW50SG9va3MgJiYgKGNoaWxkLmhvb2tzIHx8IGNoaWxkLmRlc2NlbmRhbnRIb29rcykpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBkZXNjZW5kYW50SG9va3MgPSB0cnVlO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKCFoYXNXaWRnZXRzICYmIGlzV2lkZ2V0KGNoaWxkKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHR5cGVvZiBjaGlsZC5kZXN0cm95ID09PSBcImZ1bmN0aW9uXCIpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBoYXNXaWRnZXRzID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIGlmICghaGFzVGh1bmtzICYmIGlzVGh1bmsoY2hpbGQpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBoYXNUaHVua3MgPSB0cnVlO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgdGhpcy5jb3VudCA9IGNvdW50ICsgZGVzY2VuZGFudHM7XG4gICAgICAgICAgICAgICAgdGhpcy5oYXNXaWRnZXRzID0gaGFzV2lkZ2V0cztcbiAgICAgICAgICAgICAgICB0aGlzLmhhc1RodW5rcyA9IGhhc1RodW5rcztcbiAgICAgICAgICAgICAgICB0aGlzLmhvb2tzID0gaG9va3M7XG4gICAgICAgICAgICAgICAgdGhpcy5kZXNjZW5kYW50SG9va3MgPSBkZXNjZW5kYW50SG9va3M7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIFZpcnR1YWxOb2RlLnByb3RvdHlwZS52ZXJzaW9uID0gdmVyc2lvbjtcbiAgICAgICAgICAgIFZpcnR1YWxOb2RlLnByb3RvdHlwZS50eXBlID0gXCJWaXJ0dWFsTm9kZVwiO1xuICAgICAgICB9LCB7IFwiLi9pcy10aHVua1wiOiAyNSwgXCIuL2lzLXZob29rXCI6IDI2LCBcIi4vaXMtdm5vZGVcIjogMjcsIFwiLi9pcy13aWRnZXRcIjogMjksIFwiLi92ZXJzaW9uXCI6IDMwIH1dLCAzMjogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHtcbiAgICAgICAgICAgIHZhciB2ZXJzaW9uID0gcmVxdWlyZShcIi4vdmVyc2lvblwiKTtcblxuICAgICAgICAgICAgVmlydHVhbFBhdGNoLk5PTkUgPSAwO1xuICAgICAgICAgICAgVmlydHVhbFBhdGNoLlZURVhUID0gMTtcbiAgICAgICAgICAgIFZpcnR1YWxQYXRjaC5WTk9ERSA9IDI7XG4gICAgICAgICAgICBWaXJ0dWFsUGF0Y2guV0lER0VUID0gMztcbiAgICAgICAgICAgIFZpcnR1YWxQYXRjaC5QUk9QUyA9IDQ7XG4gICAgICAgICAgICBWaXJ0dWFsUGF0Y2guT1JERVIgPSA1O1xuICAgICAgICAgICAgVmlydHVhbFBhdGNoLklOU0VSVCA9IDY7XG4gICAgICAgICAgICBWaXJ0dWFsUGF0Y2guUkVNT1ZFID0gNztcbiAgICAgICAgICAgIFZpcnR1YWxQYXRjaC5USFVOSyA9IDg7XG5cbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gVmlydHVhbFBhdGNoO1xuXG4gICAgICAgICAgICBmdW5jdGlvbiBWaXJ0dWFsUGF0Y2godHlwZSwgdk5vZGUsIHBhdGNoKSB7XG4gICAgICAgICAgICAgICAgdGhpcy50eXBlID0gTnVtYmVyKHR5cGUpO1xuICAgICAgICAgICAgICAgIHRoaXMudk5vZGUgPSB2Tm9kZTtcbiAgICAgICAgICAgICAgICB0aGlzLnBhdGNoID0gcGF0Y2g7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIFZpcnR1YWxQYXRjaC5wcm90b3R5cGUudmVyc2lvbiA9IHZlcnNpb247XG4gICAgICAgICAgICBWaXJ0dWFsUGF0Y2gucHJvdG90eXBlLnR5cGUgPSBcIlZpcnR1YWxQYXRjaFwiO1xuICAgICAgICB9LCB7IFwiLi92ZXJzaW9uXCI6IDMwIH1dLCAzMzogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHtcbiAgICAgICAgICAgIHZhciB2ZXJzaW9uID0gcmVxdWlyZShcIi4vdmVyc2lvblwiKTtcblxuICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBWaXJ0dWFsVGV4dDtcblxuICAgICAgICAgICAgZnVuY3Rpb24gVmlydHVhbFRleHQodGV4dCkge1xuICAgICAgICAgICAgICAgIHRoaXMudGV4dCA9IFN0cmluZyh0ZXh0KTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgVmlydHVhbFRleHQucHJvdG90eXBlLnZlcnNpb24gPSB2ZXJzaW9uO1xuICAgICAgICAgICAgVmlydHVhbFRleHQucHJvdG90eXBlLnR5cGUgPSBcIlZpcnR1YWxUZXh0XCI7XG4gICAgICAgIH0sIHsgXCIuL3ZlcnNpb25cIjogMzAgfV0sIDM0OiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge1xuICAgICAgICAgICAgdmFyIGlzT2JqZWN0ID0gcmVxdWlyZShcImlzLW9iamVjdFwiKTtcbiAgICAgICAgICAgIHZhciBpc0hvb2sgPSByZXF1aXJlKFwiLi4vdm5vZGUvaXMtdmhvb2tcIik7XG5cbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gZGlmZlByb3BzO1xuXG4gICAgICAgICAgICBmdW5jdGlvbiBkaWZmUHJvcHMoYSwgYikge1xuICAgICAgICAgICAgICAgIHZhciBkaWZmO1xuXG4gICAgICAgICAgICAgICAgZm9yICh2YXIgYUtleSBpbiBhKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmICghKGFLZXkgaW4gYikpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGRpZmYgPSBkaWZmIHx8IHt9O1xuICAgICAgICAgICAgICAgICAgICAgICAgZGlmZlthS2V5XSA9IHVuZGVmaW5lZDtcbiAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgIHZhciBhVmFsdWUgPSBhW2FLZXldO1xuICAgICAgICAgICAgICAgICAgICB2YXIgYlZhbHVlID0gYlthS2V5XTtcblxuICAgICAgICAgICAgICAgICAgICBpZiAoYVZhbHVlID09PSBiVmFsdWUpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnRpbnVlO1xuICAgICAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKGlzT2JqZWN0KGFWYWx1ZSkgJiYgaXNPYmplY3QoYlZhbHVlKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGdldFByb3RvdHlwZShiVmFsdWUpICE9PSBnZXRQcm90b3R5cGUoYVZhbHVlKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRpZmYgPSBkaWZmIHx8IHt9O1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRpZmZbYUtleV0gPSBiVmFsdWU7XG4gICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKGlzSG9vayhiVmFsdWUpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgZGlmZiA9IGRpZmYgfHwge307XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgZGlmZlthS2V5XSA9IGJWYWx1ZTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdmFyIG9iamVjdERpZmYgPSBkaWZmUHJvcHMoYVZhbHVlLCBiVmFsdWUpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChvYmplY3REaWZmKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRpZmYgPSBkaWZmIHx8IHt9O1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBkaWZmW2FLZXldID0gb2JqZWN0RGlmZjtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBkaWZmID0gZGlmZiB8fCB7fTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGRpZmZbYUtleV0gPSBiVmFsdWU7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICBmb3IgKHZhciBiS2V5IGluIGIpIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKCEoYktleSBpbiBhKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgZGlmZiA9IGRpZmYgfHwge307XG4gICAgICAgICAgICAgICAgICAgICAgICBkaWZmW2JLZXldID0gYltiS2V5XTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHJldHVybiBkaWZmO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBmdW5jdGlvbiBnZXRQcm90b3R5cGUodmFsdWUpIHtcbiAgICAgICAgICAgICAgICBpZiAoT2JqZWN0LmdldFByb3RvdHlwZU9mKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBPYmplY3QuZ2V0UHJvdG90eXBlT2YodmFsdWUpO1xuICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAodmFsdWUuX19wcm90b19fKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiB2YWx1ZS5fX3Byb3RvX187XG4gICAgICAgICAgICAgICAgfSBlbHNlIGlmICh2YWx1ZS5jb25zdHJ1Y3Rvcikge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gdmFsdWUuY29uc3RydWN0b3IucHJvdG90eXBlO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgfSwgeyBcIi4uL3Zub2RlL2lzLXZob29rXCI6IDI2LCBcImlzLW9iamVjdFwiOiAxMSB9XSwgMzU6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICB2YXIgaXNBcnJheSA9IHJlcXVpcmUoXCJ4LWlzLWFycmF5XCIpO1xuXG4gICAgICAgICAgICB2YXIgVlBhdGNoID0gcmVxdWlyZShcIi4uL3Zub2RlL3ZwYXRjaFwiKTtcbiAgICAgICAgICAgIHZhciBpc1ZOb2RlID0gcmVxdWlyZShcIi4uL3Zub2RlL2lzLXZub2RlXCIpO1xuICAgICAgICAgICAgdmFyIGlzVlRleHQgPSByZXF1aXJlKFwiLi4vdm5vZGUvaXMtdnRleHRcIik7XG4gICAgICAgICAgICB2YXIgaXNXaWRnZXQgPSByZXF1aXJlKFwiLi4vdm5vZGUvaXMtd2lkZ2V0XCIpO1xuICAgICAgICAgICAgdmFyIGlzVGh1bmsgPSByZXF1aXJlKFwiLi4vdm5vZGUvaXMtdGh1bmtcIik7XG4gICAgICAgICAgICB2YXIgaGFuZGxlVGh1bmsgPSByZXF1aXJlKFwiLi4vdm5vZGUvaGFuZGxlLXRodW5rXCIpO1xuXG4gICAgICAgICAgICB2YXIgZGlmZlByb3BzID0gcmVxdWlyZShcIi4vZGlmZi1wcm9wc1wiKTtcblxuICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBkaWZmO1xuXG4gICAgICAgICAgICBmdW5jdGlvbiBkaWZmKGEsIGIpIHtcbiAgICAgICAgICAgICAgICB2YXIgcGF0Y2ggPSB7IGE6IGEgfTtcbiAgICAgICAgICAgICAgICB3YWxrKGEsIGIsIHBhdGNoLCAwKTtcbiAgICAgICAgICAgICAgICByZXR1cm4gcGF0Y2g7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIHdhbGsoYSwgYiwgcGF0Y2gsIGluZGV4KSB7XG4gICAgICAgICAgICAgICAgaWYgKGEgPT09IGIpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHZhciBhcHBseSA9IHBhdGNoW2luZGV4XTtcbiAgICAgICAgICAgICAgICB2YXIgYXBwbHlDbGVhciA9IGZhbHNlO1xuXG4gICAgICAgICAgICAgICAgaWYgKGlzVGh1bmsoYSkgfHwgaXNUaHVuayhiKSkge1xuICAgICAgICAgICAgICAgICAgICB0aHVua3MoYSwgYiwgcGF0Y2gsIGluZGV4KTtcbiAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKGIgPT0gbnVsbCkge1xuXG4gICAgICAgICAgICAgICAgICAgIC8vIElmIGEgaXMgYSB3aWRnZXQgd2Ugd2lsbCBhZGQgYSByZW1vdmUgcGF0Y2ggZm9yIGl0XG4gICAgICAgICAgICAgICAgICAgIC8vIE90aGVyd2lzZSBhbnkgY2hpbGQgd2lkZ2V0cy9ob29rcyBtdXN0IGJlIGRlc3Ryb3llZC5cbiAgICAgICAgICAgICAgICAgICAgLy8gVGhpcyBwcmV2ZW50cyBhZGRpbmcgdHdvIHJlbW92ZSBwYXRjaGVzIGZvciBhIHdpZGdldC5cbiAgICAgICAgICAgICAgICAgICAgaWYgKCFpc1dpZGdldChhKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgY2xlYXJTdGF0ZShhLCBwYXRjaCwgaW5kZXgpO1xuICAgICAgICAgICAgICAgICAgICAgICAgYXBwbHkgPSBwYXRjaFtpbmRleF07XG4gICAgICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgICAgICBhcHBseSA9IGFwcGVuZFBhdGNoKGFwcGx5LCBuZXcgVlBhdGNoKFZQYXRjaC5SRU1PVkUsIGEsIGIpKTtcbiAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKGlzVk5vZGUoYikpIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKGlzVk5vZGUoYSkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChhLnRhZ05hbWUgPT09IGIudGFnTmFtZSAmJiBhLm5hbWVzcGFjZSA9PT0gYi5uYW1lc3BhY2UgJiYgYS5rZXkgPT09IGIua2V5KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdmFyIHByb3BzUGF0Y2ggPSBkaWZmUHJvcHMoYS5wcm9wZXJ0aWVzLCBiLnByb3BlcnRpZXMpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChwcm9wc1BhdGNoKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGFwcGx5ID0gYXBwZW5kUGF0Y2goYXBwbHksIG5ldyBWUGF0Y2goVlBhdGNoLlBST1BTLCBhLCBwcm9wc1BhdGNoKSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGFwcGx5ID0gZGlmZkNoaWxkcmVuKGEsIGIsIHBhdGNoLCBhcHBseSwgaW5kZXgpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBhcHBseSA9IGFwcGVuZFBhdGNoKGFwcGx5LCBuZXcgVlBhdGNoKFZQYXRjaC5WTk9ERSwgYSwgYikpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGFwcGx5Q2xlYXIgPSB0cnVlO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgYXBwbHkgPSBhcHBlbmRQYXRjaChhcHBseSwgbmV3IFZQYXRjaChWUGF0Y2guVk5PREUsIGEsIGIpKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGFwcGx5Q2xlYXIgPSB0cnVlO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfSBlbHNlIGlmIChpc1ZUZXh0KGIpKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmICghaXNWVGV4dChhKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgYXBwbHkgPSBhcHBlbmRQYXRjaChhcHBseSwgbmV3IFZQYXRjaChWUGF0Y2guVlRFWFQsIGEsIGIpKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGFwcGx5Q2xlYXIgPSB0cnVlO1xuICAgICAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKGEudGV4dCAhPT0gYi50ZXh0KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBhcHBseSA9IGFwcGVuZFBhdGNoKGFwcGx5LCBuZXcgVlBhdGNoKFZQYXRjaC5WVEVYVCwgYSwgYikpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfSBlbHNlIGlmIChpc1dpZGdldChiKSkge1xuICAgICAgICAgICAgICAgICAgICBpZiAoIWlzV2lkZ2V0KGEpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBhcHBseUNsZWFyID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgIGFwcGx5ID0gYXBwZW5kUGF0Y2goYXBwbHksIG5ldyBWUGF0Y2goVlBhdGNoLldJREdFVCwgYSwgYikpO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIGlmIChhcHBseSkge1xuICAgICAgICAgICAgICAgICAgICBwYXRjaFtpbmRleF0gPSBhcHBseTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICBpZiAoYXBwbHlDbGVhcikge1xuICAgICAgICAgICAgICAgICAgICBjbGVhclN0YXRlKGEsIHBhdGNoLCBpbmRleCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBmdW5jdGlvbiBkaWZmQ2hpbGRyZW4oYSwgYiwgcGF0Y2gsIGFwcGx5LCBpbmRleCkge1xuICAgICAgICAgICAgICAgIHZhciBhQ2hpbGRyZW4gPSBhLmNoaWxkcmVuO1xuICAgICAgICAgICAgICAgIHZhciBvcmRlcmVkU2V0ID0gcmVvcmRlcihhQ2hpbGRyZW4sIGIuY2hpbGRyZW4pO1xuICAgICAgICAgICAgICAgIHZhciBiQ2hpbGRyZW4gPSBvcmRlcmVkU2V0LmNoaWxkcmVuO1xuXG4gICAgICAgICAgICAgICAgdmFyIGFMZW4gPSBhQ2hpbGRyZW4ubGVuZ3RoO1xuICAgICAgICAgICAgICAgIHZhciBiTGVuID0gYkNoaWxkcmVuLmxlbmd0aDtcbiAgICAgICAgICAgICAgICB2YXIgbGVuID0gYUxlbiA+IGJMZW4gPyBhTGVuIDogYkxlbjtcblxuICAgICAgICAgICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgbGVuOyBpKyspIHtcbiAgICAgICAgICAgICAgICAgICAgdmFyIGxlZnROb2RlID0gYUNoaWxkcmVuW2ldO1xuICAgICAgICAgICAgICAgICAgICB2YXIgcmlnaHROb2RlID0gYkNoaWxkcmVuW2ldO1xuICAgICAgICAgICAgICAgICAgICBpbmRleCArPSAxO1xuXG4gICAgICAgICAgICAgICAgICAgIGlmICghbGVmdE5vZGUpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChyaWdodE5vZGUpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBFeGNlc3Mgbm9kZXMgaW4gYiBuZWVkIHRvIGJlIGFkZGVkXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgYXBwbHkgPSBhcHBlbmRQYXRjaChhcHBseSwgbmV3IFZQYXRjaChWUGF0Y2guSU5TRVJULCBudWxsLCByaWdodE5vZGUpKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHdhbGsobGVmdE5vZGUsIHJpZ2h0Tm9kZSwgcGF0Y2gsIGluZGV4KTtcbiAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgIGlmIChpc1ZOb2RlKGxlZnROb2RlKSAmJiBsZWZ0Tm9kZS5jb3VudCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgaW5kZXggKz0gbGVmdE5vZGUuY291bnQ7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICBpZiAob3JkZXJlZFNldC5tb3Zlcykge1xuICAgICAgICAgICAgICAgICAgICAvLyBSZW9yZGVyIG5vZGVzIGxhc3RcbiAgICAgICAgICAgICAgICAgICAgYXBwbHkgPSBhcHBlbmRQYXRjaChhcHBseSwgbmV3IFZQYXRjaChWUGF0Y2guT1JERVIsIGEsIG9yZGVyZWRTZXQubW92ZXMpKTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICByZXR1cm4gYXBwbHk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIGNsZWFyU3RhdGUodk5vZGUsIHBhdGNoLCBpbmRleCkge1xuICAgICAgICAgICAgICAgIC8vIFRPRE86IE1ha2UgdGhpcyBhIHNpbmdsZSB3YWxrLCBub3QgdHdvXG4gICAgICAgICAgICAgICAgdW5ob29rKHZOb2RlLCBwYXRjaCwgaW5kZXgpO1xuICAgICAgICAgICAgICAgIGRlc3Ryb3lXaWRnZXRzKHZOb2RlLCBwYXRjaCwgaW5kZXgpO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAvLyBQYXRjaCByZWNvcmRzIGZvciBhbGwgZGVzdHJveWVkIHdpZGdldHMgbXVzdCBiZSBhZGRlZCBiZWNhdXNlIHdlIG5lZWRcbiAgICAgICAgICAgIC8vIGEgRE9NIG5vZGUgcmVmZXJlbmNlIGZvciB0aGUgZGVzdHJveSBmdW5jdGlvblxuICAgICAgICAgICAgZnVuY3Rpb24gZGVzdHJveVdpZGdldHModk5vZGUsIHBhdGNoLCBpbmRleCkge1xuICAgICAgICAgICAgICAgIGlmIChpc1dpZGdldCh2Tm9kZSkpIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKHR5cGVvZiB2Tm9kZS5kZXN0cm95ID09PSBcImZ1bmN0aW9uXCIpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHBhdGNoW2luZGV4XSA9IGFwcGVuZFBhdGNoKHBhdGNoW2luZGV4XSwgbmV3IFZQYXRjaChWUGF0Y2guUkVNT1ZFLCB2Tm9kZSwgbnVsbCkpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfSBlbHNlIGlmIChpc1ZOb2RlKHZOb2RlKSAmJiAodk5vZGUuaGFzV2lkZ2V0cyB8fCB2Tm9kZS5oYXNUaHVua3MpKSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciBjaGlsZHJlbiA9IHZOb2RlLmNoaWxkcmVuO1xuICAgICAgICAgICAgICAgICAgICB2YXIgbGVuID0gY2hpbGRyZW4ubGVuZ3RoO1xuICAgICAgICAgICAgICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IGxlbjsgaSsrKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICB2YXIgY2hpbGQgPSBjaGlsZHJlbltpXTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGluZGV4ICs9IDE7XG5cbiAgICAgICAgICAgICAgICAgICAgICAgIGRlc3Ryb3lXaWRnZXRzKGNoaWxkLCBwYXRjaCwgaW5kZXgpO1xuXG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoaXNWTm9kZShjaGlsZCkgJiYgY2hpbGQuY291bnQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpbmRleCArPSBjaGlsZC5jb3VudDtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoaXNUaHVuayh2Tm9kZSkpIHtcbiAgICAgICAgICAgICAgICAgICAgdGh1bmtzKHZOb2RlLCBudWxsLCBwYXRjaCwgaW5kZXgpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgLy8gQ3JlYXRlIGEgc3ViLXBhdGNoIGZvciB0aHVua3NcbiAgICAgICAgICAgIGZ1bmN0aW9uIHRodW5rcyhhLCBiLCBwYXRjaCwgaW5kZXgpIHtcbiAgICAgICAgICAgICAgICB2YXIgbm9kZXMgPSBoYW5kbGVUaHVuayhhLCBiKTtcbiAgICAgICAgICAgICAgICB2YXIgdGh1bmtQYXRjaCA9IGRpZmYobm9kZXMuYSwgbm9kZXMuYik7XG4gICAgICAgICAgICAgICAgaWYgKGhhc1BhdGNoZXModGh1bmtQYXRjaCkpIHtcbiAgICAgICAgICAgICAgICAgICAgcGF0Y2hbaW5kZXhdID0gbmV3IFZQYXRjaChWUGF0Y2guVEhVTkssIG51bGwsIHRodW5rUGF0Y2gpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZnVuY3Rpb24gaGFzUGF0Y2hlcyhwYXRjaCkge1xuICAgICAgICAgICAgICAgIGZvciAodmFyIGluZGV4IGluIHBhdGNoKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmIChpbmRleCAhPT0gXCJhXCIpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAvLyBFeGVjdXRlIGhvb2tzIHdoZW4gdHdvIG5vZGVzIGFyZSBpZGVudGljYWxcbiAgICAgICAgICAgIGZ1bmN0aW9uIHVuaG9vayh2Tm9kZSwgcGF0Y2gsIGluZGV4KSB7XG4gICAgICAgICAgICAgICAgaWYgKGlzVk5vZGUodk5vZGUpKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmICh2Tm9kZS5ob29rcykge1xuICAgICAgICAgICAgICAgICAgICAgICAgcGF0Y2hbaW5kZXhdID0gYXBwZW5kUGF0Y2gocGF0Y2hbaW5kZXhdLCBuZXcgVlBhdGNoKFZQYXRjaC5QUk9QUywgdk5vZGUsIHVuZGVmaW5lZEtleXModk5vZGUuaG9va3MpKSk7XG4gICAgICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgICAgICBpZiAodk5vZGUuZGVzY2VuZGFudEhvb2tzIHx8IHZOb2RlLmhhc1RodW5rcykge1xuICAgICAgICAgICAgICAgICAgICAgICAgdmFyIGNoaWxkcmVuID0gdk5vZGUuY2hpbGRyZW47XG4gICAgICAgICAgICAgICAgICAgICAgICB2YXIgbGVuID0gY2hpbGRyZW4ubGVuZ3RoO1xuICAgICAgICAgICAgICAgICAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCBsZW47IGkrKykge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZhciBjaGlsZCA9IGNoaWxkcmVuW2ldO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGluZGV4ICs9IDE7XG5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB1bmhvb2soY2hpbGQsIHBhdGNoLCBpbmRleCk7XG5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoaXNWTm9kZShjaGlsZCkgJiYgY2hpbGQuY291bnQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaW5kZXggKz0gY2hpbGQuY291bnQ7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfSBlbHNlIGlmIChpc1RodW5rKHZOb2RlKSkge1xuICAgICAgICAgICAgICAgICAgICB0aHVua3Modk5vZGUsIG51bGwsIHBhdGNoLCBpbmRleCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBmdW5jdGlvbiB1bmRlZmluZWRLZXlzKG9iaikge1xuICAgICAgICAgICAgICAgIHZhciByZXN1bHQgPSB7fTtcblxuICAgICAgICAgICAgICAgIGZvciAodmFyIGtleSBpbiBvYmopIHtcbiAgICAgICAgICAgICAgICAgICAgcmVzdWx0W2tleV0gPSB1bmRlZmluZWQ7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgcmV0dXJuIHJlc3VsdDtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgLy8gTGlzdCBkaWZmLCBuYWl2ZSBsZWZ0IHRvIHJpZ2h0IHJlb3JkZXJpbmdcbiAgICAgICAgICAgIGZ1bmN0aW9uIHJlb3JkZXIoYUNoaWxkcmVuLCBiQ2hpbGRyZW4pIHtcbiAgICAgICAgICAgICAgICAvLyBPKE0pIHRpbWUsIE8oTSkgbWVtb3J5XG4gICAgICAgICAgICAgICAgdmFyIGJDaGlsZEluZGV4ID0ga2V5SW5kZXgoYkNoaWxkcmVuKTtcbiAgICAgICAgICAgICAgICB2YXIgYktleXMgPSBiQ2hpbGRJbmRleC5rZXlzO1xuICAgICAgICAgICAgICAgIHZhciBiRnJlZSA9IGJDaGlsZEluZGV4LmZyZWU7XG5cbiAgICAgICAgICAgICAgICBpZiAoYkZyZWUubGVuZ3RoID09PSBiQ2hpbGRyZW4ubGVuZ3RoKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiB7XG4gICAgICAgICAgICAgICAgICAgICAgICBjaGlsZHJlbjogYkNoaWxkcmVuLFxuICAgICAgICAgICAgICAgICAgICAgICAgbW92ZXM6IG51bGxcbiAgICAgICAgICAgICAgICAgICAgfTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAvLyBPKE4pIHRpbWUsIE8oTikgbWVtb3J5XG4gICAgICAgICAgICAgICAgdmFyIGFDaGlsZEluZGV4ID0ga2V5SW5kZXgoYUNoaWxkcmVuKTtcbiAgICAgICAgICAgICAgICB2YXIgYUtleXMgPSBhQ2hpbGRJbmRleC5rZXlzO1xuICAgICAgICAgICAgICAgIHZhciBhRnJlZSA9IGFDaGlsZEluZGV4LmZyZWU7XG5cbiAgICAgICAgICAgICAgICBpZiAoYUZyZWUubGVuZ3RoID09PSBhQ2hpbGRyZW4ubGVuZ3RoKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiB7XG4gICAgICAgICAgICAgICAgICAgICAgICBjaGlsZHJlbjogYkNoaWxkcmVuLFxuICAgICAgICAgICAgICAgICAgICAgICAgbW92ZXM6IG51bGxcbiAgICAgICAgICAgICAgICAgICAgfTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAvLyBPKE1BWChOLCBNKSkgbWVtb3J5XG4gICAgICAgICAgICAgICAgdmFyIG5ld0NoaWxkcmVuID0gW107XG5cbiAgICAgICAgICAgICAgICB2YXIgZnJlZUluZGV4ID0gMDtcbiAgICAgICAgICAgICAgICB2YXIgZnJlZUNvdW50ID0gYkZyZWUubGVuZ3RoO1xuICAgICAgICAgICAgICAgIHZhciBkZWxldGVkSXRlbXMgPSAwO1xuXG4gICAgICAgICAgICAgICAgLy8gSXRlcmF0ZSB0aHJvdWdoIGEgYW5kIG1hdGNoIGEgbm9kZSBpbiBiXG4gICAgICAgICAgICAgICAgLy8gTyhOKSB0aW1lLFxuICAgICAgICAgICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgYUNoaWxkcmVuLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciBhSXRlbSA9IGFDaGlsZHJlbltpXTtcbiAgICAgICAgICAgICAgICAgICAgdmFyIGl0ZW1JbmRleDtcblxuICAgICAgICAgICAgICAgICAgICBpZiAoYUl0ZW0ua2V5KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoYktleXMuaGFzT3duUHJvcGVydHkoYUl0ZW0ua2V5KSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIE1hdGNoIHVwIHRoZSBvbGQga2V5c1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGl0ZW1JbmRleCA9IGJLZXlzW2FJdGVtLmtleV07XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgbmV3Q2hpbGRyZW4ucHVzaChiQ2hpbGRyZW5baXRlbUluZGV4XSk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIFJlbW92ZSBvbGQga2V5ZWQgaXRlbXNcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpdGVtSW5kZXggPSBpIC0gZGVsZXRlZEl0ZW1zKys7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgbmV3Q2hpbGRyZW4ucHVzaChudWxsKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIE1hdGNoIHRoZSBpdGVtIGluIGEgd2l0aCB0aGUgbmV4dCBmcmVlIGl0ZW0gaW4gYlxuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGZyZWVJbmRleCA8IGZyZWVDb3VudCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGl0ZW1JbmRleCA9IGJGcmVlW2ZyZWVJbmRleCsrXTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBuZXdDaGlsZHJlbi5wdXNoKGJDaGlsZHJlbltpdGVtSW5kZXhdKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gVGhlcmUgYXJlIG5vIGZyZWUgaXRlbXMgaW4gYiB0byBtYXRjaCB3aXRoXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gdGhlIGZyZWUgaXRlbXMgaW4gYSwgc28gdGhlIGV4dHJhIGZyZWUgbm9kZXNcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBhcmUgZGVsZXRlZC5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpdGVtSW5kZXggPSBpIC0gZGVsZXRlZEl0ZW1zKys7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgbmV3Q2hpbGRyZW4ucHVzaChudWxsKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHZhciBsYXN0RnJlZUluZGV4ID0gZnJlZUluZGV4ID49IGJGcmVlLmxlbmd0aCA/IGJDaGlsZHJlbi5sZW5ndGggOiBiRnJlZVtmcmVlSW5kZXhdO1xuXG4gICAgICAgICAgICAgICAgLy8gSXRlcmF0ZSB0aHJvdWdoIGIgYW5kIGFwcGVuZCBhbnkgbmV3IGtleXNcbiAgICAgICAgICAgICAgICAvLyBPKE0pIHRpbWVcbiAgICAgICAgICAgICAgICBmb3IgKHZhciBqID0gMDsgaiA8IGJDaGlsZHJlbi5sZW5ndGg7IGorKykge1xuICAgICAgICAgICAgICAgICAgICB2YXIgbmV3SXRlbSA9IGJDaGlsZHJlbltqXTtcblxuICAgICAgICAgICAgICAgICAgICBpZiAobmV3SXRlbS5rZXkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmICghYUtleXMuaGFzT3duUHJvcGVydHkobmV3SXRlbS5rZXkpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gQWRkIGFueSBuZXcga2V5ZWQgaXRlbXNcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBXZSBhcmUgYWRkaW5nIG5ldyBpdGVtcyB0byB0aGUgZW5kIGFuZCB0aGVuIHNvcnRpbmcgdGhlbVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIGluIHBsYWNlLiBJbiBmdXR1cmUgd2Ugc2hvdWxkIGluc2VydCBuZXcgaXRlbXMgaW4gcGxhY2UuXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgbmV3Q2hpbGRyZW4ucHVzaChuZXdJdGVtKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIGlmIChqID49IGxhc3RGcmVlSW5kZXgpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIEFkZCBhbnkgbGVmdG92ZXIgbm9uLWtleWVkIGl0ZW1zXG4gICAgICAgICAgICAgICAgICAgICAgICBuZXdDaGlsZHJlbi5wdXNoKG5ld0l0ZW0pO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgdmFyIHNpbXVsYXRlID0gbmV3Q2hpbGRyZW4uc2xpY2UoKTtcbiAgICAgICAgICAgICAgICB2YXIgc2ltdWxhdGVJbmRleCA9IDA7XG4gICAgICAgICAgICAgICAgdmFyIHJlbW92ZXMgPSBbXTtcbiAgICAgICAgICAgICAgICB2YXIgaW5zZXJ0cyA9IFtdO1xuICAgICAgICAgICAgICAgIHZhciBzaW11bGF0ZUl0ZW07XG5cbiAgICAgICAgICAgICAgICBmb3IgKHZhciBrID0gMDsgayA8IGJDaGlsZHJlbi5sZW5ndGg7KSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciB3YW50ZWRJdGVtID0gYkNoaWxkcmVuW2tdO1xuICAgICAgICAgICAgICAgICAgICBzaW11bGF0ZUl0ZW0gPSBzaW11bGF0ZVtzaW11bGF0ZUluZGV4XTtcblxuICAgICAgICAgICAgICAgICAgICAvLyByZW1vdmUgaXRlbXNcbiAgICAgICAgICAgICAgICAgICAgd2hpbGUgKHNpbXVsYXRlSXRlbSA9PT0gbnVsbCAmJiBzaW11bGF0ZS5sZW5ndGgpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJlbW92ZXMucHVzaChyZW1vdmUoc2ltdWxhdGUsIHNpbXVsYXRlSW5kZXgsIG51bGwpKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIHNpbXVsYXRlSXRlbSA9IHNpbXVsYXRlW3NpbXVsYXRlSW5kZXhdO1xuICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgaWYgKCFzaW11bGF0ZUl0ZW0gfHwgc2ltdWxhdGVJdGVtLmtleSAhPT0gd2FudGVkSXRlbS5rZXkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIGlmIHdlIG5lZWQgYSBrZXkgaW4gdGhpcyBwb3NpdGlvbi4uLlxuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHdhbnRlZEl0ZW0ua2V5KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHNpbXVsYXRlSXRlbSAmJiBzaW11bGF0ZUl0ZW0ua2V5KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIGlmIGFuIGluc2VydCBkb2Vzbid0IHB1dCB0aGlzIGtleSBpbiBwbGFjZSwgaXQgbmVlZHMgdG8gbW92ZVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoYktleXNbc2ltdWxhdGVJdGVtLmtleV0gIT09IGsgKyAxKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICByZW1vdmVzLnB1c2gocmVtb3ZlKHNpbXVsYXRlLCBzaW11bGF0ZUluZGV4LCBzaW11bGF0ZUl0ZW0ua2V5KSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzaW11bGF0ZUl0ZW0gPSBzaW11bGF0ZVtzaW11bGF0ZUluZGV4XTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIGlmIHRoZSByZW1vdmUgZGlkbid0IHB1dCB0aGUgd2FudGVkIGl0ZW0gaW4gcGxhY2UsIHdlIG5lZWQgdG8gaW5zZXJ0IGl0XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoIXNpbXVsYXRlSXRlbSB8fCBzaW11bGF0ZUl0ZW0ua2V5ICE9PSB3YW50ZWRJdGVtLmtleSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGluc2VydHMucHVzaCh7IGtleTogd2FudGVkSXRlbS5rZXksIHRvOiBrIH0pO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gaXRlbXMgYXJlIG1hdGNoaW5nLCBzbyBza2lwIGFoZWFkXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzaW11bGF0ZUluZGV4Kys7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpbnNlcnRzLnB1c2goeyBrZXk6IHdhbnRlZEl0ZW0ua2V5LCB0bzogayB9KTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGluc2VydHMucHVzaCh7IGtleTogd2FudGVkSXRlbS5rZXksIHRvOiBrIH0pO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBrKys7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAvLyBhIGtleSBpbiBzaW11bGF0ZSBoYXMgbm8gbWF0Y2hpbmcgd2FudGVkIGtleSwgcmVtb3ZlIGl0XG4gICAgICAgICAgICAgICAgICAgICAgICBlbHNlIGlmIChzaW11bGF0ZUl0ZW0gJiYgc2ltdWxhdGVJdGVtLmtleSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlbW92ZXMucHVzaChyZW1vdmUoc2ltdWxhdGUsIHNpbXVsYXRlSW5kZXgsIHNpbXVsYXRlSXRlbS5rZXkpKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHNpbXVsYXRlSW5kZXgrKztcbiAgICAgICAgICAgICAgICAgICAgICAgIGsrKztcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIC8vIHJlbW92ZSBhbGwgdGhlIHJlbWFpbmluZyBub2RlcyBmcm9tIHNpbXVsYXRlXG4gICAgICAgICAgICAgICAgd2hpbGUgKHNpbXVsYXRlSW5kZXggPCBzaW11bGF0ZS5sZW5ndGgpIHtcbiAgICAgICAgICAgICAgICAgICAgc2ltdWxhdGVJdGVtID0gc2ltdWxhdGVbc2ltdWxhdGVJbmRleF07XG4gICAgICAgICAgICAgICAgICAgIHJlbW92ZXMucHVzaChyZW1vdmUoc2ltdWxhdGUsIHNpbXVsYXRlSW5kZXgsIHNpbXVsYXRlSXRlbSAmJiBzaW11bGF0ZUl0ZW0ua2V5KSk7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgLy8gSWYgdGhlIG9ubHkgbW92ZXMgd2UgaGF2ZSBhcmUgZGVsZXRlcyB0aGVuIHdlIGNhbiBqdXN0XG4gICAgICAgICAgICAgICAgLy8gbGV0IHRoZSBkZWxldGUgcGF0Y2ggcmVtb3ZlIHRoZXNlIGl0ZW1zLlxuICAgICAgICAgICAgICAgIGlmIChyZW1vdmVzLmxlbmd0aCA9PT0gZGVsZXRlZEl0ZW1zICYmICFpbnNlcnRzLmxlbmd0aCkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgICAgICAgICAgICAgY2hpbGRyZW46IG5ld0NoaWxkcmVuLFxuICAgICAgICAgICAgICAgICAgICAgICAgbW92ZXM6IG51bGxcbiAgICAgICAgICAgICAgICAgICAgfTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgICAgICAgICBjaGlsZHJlbjogbmV3Q2hpbGRyZW4sXG4gICAgICAgICAgICAgICAgICAgIG1vdmVzOiB7XG4gICAgICAgICAgICAgICAgICAgICAgICByZW1vdmVzOiByZW1vdmVzLFxuICAgICAgICAgICAgICAgICAgICAgICAgaW5zZXJ0czogaW5zZXJ0c1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZnVuY3Rpb24gcmVtb3ZlKGFyciwgaW5kZXgsIGtleSkge1xuICAgICAgICAgICAgICAgIGFyci5zcGxpY2UoaW5kZXgsIDEpO1xuXG4gICAgICAgICAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgICAgICAgICAgZnJvbTogaW5kZXgsXG4gICAgICAgICAgICAgICAgICAgIGtleToga2V5XG4gICAgICAgICAgICAgICAgfTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZnVuY3Rpb24ga2V5SW5kZXgoY2hpbGRyZW4pIHtcbiAgICAgICAgICAgICAgICB2YXIga2V5cyA9IHt9O1xuICAgICAgICAgICAgICAgIHZhciBmcmVlID0gW107XG4gICAgICAgICAgICAgICAgdmFyIGxlbmd0aCA9IGNoaWxkcmVuLmxlbmd0aDtcblxuICAgICAgICAgICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgbGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgICAgICAgICAgdmFyIGNoaWxkID0gY2hpbGRyZW5baV07XG5cbiAgICAgICAgICAgICAgICAgICAgaWYgKGNoaWxkLmtleSkge1xuICAgICAgICAgICAgICAgICAgICAgICAga2V5c1tjaGlsZC5rZXldID0gaTtcbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGZyZWUucHVzaChpKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHJldHVybiB7XG4gICAgICAgICAgICAgICAgICAgIGtleXM6IGtleXMsIC8vIEEgaGFzaCBvZiBrZXkgbmFtZSB0byBpbmRleFxuICAgICAgICAgICAgICAgICAgICBmcmVlOiBmcmVlIC8vIEFuIGFycmF5IG9mIHVua2V5ZWQgaXRlbSBpbmRpY2VzXG4gICAgICAgICAgICAgICAgfTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZnVuY3Rpb24gYXBwZW5kUGF0Y2goYXBwbHksIHBhdGNoKSB7XG4gICAgICAgICAgICAgICAgaWYgKGFwcGx5KSB7XG4gICAgICAgICAgICAgICAgICAgIGlmIChpc0FycmF5KGFwcGx5KSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgYXBwbHkucHVzaChwYXRjaCk7XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBhcHBseSA9IFthcHBseSwgcGF0Y2hdO1xuICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGFwcGx5O1xuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBwYXRjaDtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH0sIHsgXCIuLi92bm9kZS9oYW5kbGUtdGh1bmtcIjogMjQsIFwiLi4vdm5vZGUvaXMtdGh1bmtcIjogMjUsIFwiLi4vdm5vZGUvaXMtdm5vZGVcIjogMjcsIFwiLi4vdm5vZGUvaXMtdnRleHRcIjogMjgsIFwiLi4vdm5vZGUvaXMtd2lkZ2V0XCI6IDI5LCBcIi4uL3Zub2RlL3ZwYXRjaFwiOiAzMiwgXCIuL2RpZmYtcHJvcHNcIjogMzQsIFwieC1pcy1hcnJheVwiOiAxMiB9XSB9LCB7fSwgWzRdKSg0KTtcbn0pO1xuXG5jb25zdCBzdGFydCA9IGZ1bmN0aW9uIChkb21Sb290LCByZW5kZXJGbiwgaW5pdGlhbFN0YXRlLCBvcHRpb25zID0gW10pIHtcbiAgbGV0IHBpZCA9IHNlbGYucHJvY2Vzc2VzLnNwYXduKCk7XG5cbiAgaWYgKEtleXdvcmQuaGFzX2tleV9fcW1fXyhvcHRpb25zLCBLZXJuZWwuU3BlY2lhbEZvcm1zLmF0b20oJ25hbWUnKSkpIHtcbiAgICBwaWQgPSBzZWxmLnByb2Nlc3Nlcy5yZWdpc3RlcihLZXl3b3JkLmdldChvcHRpb25zLCBLZXJuZWwuU3BlY2lhbEZvcm1zLmF0b20oJ25hbWUnKSksIHBpZCk7XG4gIH1cblxuICBjb25zdCB0cmVlID0gcmVuZGVyRm4uYXBwbHkodGhpcywgaW5pdGlhbFN0YXRlKTtcbiAgY29uc3Qgcm9vdE5vZGUgPSBWaXJ0dWFsRE9NLmNyZWF0ZSh0cmVlKTtcblxuICBkb21Sb290LmFwcGVuZENoaWxkKHJvb3ROb2RlKTtcblxuICBzZWxmLnByb2Nlc3Nlcy5wdXQocGlkLCAnc3RhdGUnLCBLZXJuZWwuU3BlY2lhbEZvcm1zLnR1cGxlKHJvb3ROb2RlLCB0cmVlLCByZW5kZXJGbikpO1xuICByZXR1cm4gS2VybmVsLlNwZWNpYWxGb3Jtcy50dXBsZShLZXJuZWwuU3BlY2lhbEZvcm1zLmF0b20oJ29rJyksIHBpZCk7XG59O1xuXG5jb25zdCBzdG9wID0gZnVuY3Rpb24gKGFnZW50LCB0aW1lb3V0ID0gNTAwMCkge1xuICBzZWxmLnByb2Nlc3Nlcy5leGl0KGFnZW50KTtcbiAgcmV0dXJuIEtlcm5lbC5TcGVjaWFsRm9ybXMuYXRvbSgnb2snKTtcbn07XG5cbmNvbnN0IHJlbmRlciA9IGZ1bmN0aW9uIChhZ2VudCwgc3RhdGUpIHtcblxuICBjb25zdCBjdXJyZW50X3N0YXRlID0gc2VsZi5wcm9jZXNzZXMuZ2V0KGFnZW50LCAnc3RhdGUnKTtcblxuICBsZXQgcm9vdE5vZGUgPSBLZXJuZWwuZWxlbShjdXJyZW50X3N0YXRlLCAwKTtcbiAgbGV0IHRyZWUgPSBLZXJuZWwuZWxlbShjdXJyZW50X3N0YXRlLCAxKTtcbiAgbGV0IHJlbmRlckZuID0gS2VybmVsLmVsZW0oY3VycmVudF9zdGF0ZSwgMik7XG5cbiAgbGV0IG5ld1RyZWUgPSByZW5kZXJGbi5hcHBseSh0aGlzLCBzdGF0ZSk7XG5cbiAgbGV0IHBhdGNoZXMgPSBWaXJ0dWFsRE9NLmRpZmYodHJlZSwgbmV3VHJlZSk7XG4gIHJvb3ROb2RlID0gVmlydHVhbERPTS5wYXRjaChyb290Tm9kZSwgcGF0Y2hlcyk7XG5cbiAgc2VsZi5wcm9jZXNzZXMucHV0KGFnZW50LCAnc3RhdGUnLCBLZXJuZWwuU3BlY2lhbEZvcm1zLnR1cGxlKHJvb3ROb2RlLCBuZXdUcmVlLCByZW5kZXJGbikpO1xuXG4gIHJldHVybiBLZXJuZWwuU3BlY2lhbEZvcm1zLmF0b20oJ29rJyk7XG59O1xuXG52YXIgdmlldyA9IHtcbiAgc3RhcnQsXG4gIHN0b3AsXG4gIHJlbmRlclxufTtcblxuc2VsZi5wcm9jZXNzZXMgPSBzZWxmLnByb2Nlc3NlcyB8fCBuZXcgUHJvY2Vzc1N5c3RlbSgpO1xuXG5jb25zdCBDb3JlID0gQztcblxuZXhwb3J0IHsgQ29yZSwgS2VybmVsLCBBdG9tLCBFbnVtLCBJbnRlZ2VyLCBMaXN0LCBSYW5nZSwgVHVwbGUsIEFnZW50LCBLZXl3b3JkLCBiYXNlIGFzIEJhc2UsIFN0cmluZyQxIGFzIFN0cmluZywgYml0d2lzZSBhcyBCaXR3aXNlLCBFbnVtZXJhYmxlLCBDb2xsZWN0YWJsZSwgSW5zcGVjdCwgbWFwIGFzIE1hcCwgc2V0IGFzIFNldCwgTWFwU2V0LCBWaXJ0dWFsRE9NLCB2aWV3IGFzIFZpZXcgfTsiXSwiZmlsZSI6ImVsaXhpci5qcyIsInNvdXJjZVJvb3QiOiIvc291cmNlLyJ9 \ No newline at end of file +//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiIiwic291cmNlcyI6WyJlbGl4aXIuanMiXSwic291cmNlc0NvbnRlbnQiOlsiZnVuY3Rpb24gY2FsbF9wcm9wZXJ0eShpdGVtLCBwcm9wZXJ0eSkge1xuICBpZiAocHJvcGVydHkgaW4gaXRlbSkge1xuICAgIGl0ZW1bcHJvcGVydHldO1xuICAgIGlmIChpdGVtW3Byb3BlcnR5XSBpbnN0YW5jZW9mIEZ1bmN0aW9uKSB7XG4gICAgICByZXR1cm4gaXRlbVtwcm9wZXJ0eV0oKTtcbiAgICB9IGVsc2Uge1xuICAgICAgcmV0dXJuIGl0ZW1bcHJvcGVydHldO1xuICAgIH1cbiAgfSBlbHNlIGlmIChTeW1ib2wuZm9yKHByb3BlcnR5KSBpbiBpdGVtKSB7XG4gICAgbGV0IHByb3AgPSBTeW1ib2wuZm9yKHByb3BlcnR5KTtcbiAgICBpZiAoaXRlbVtwcm9wXSBpbnN0YW5jZW9mIEZ1bmN0aW9uKSB7XG4gICAgICByZXR1cm4gaXRlbVtwcm9wXSgpO1xuICAgIH0gZWxzZSB7XG4gICAgICByZXR1cm4gaXRlbVtwcm9wXTtcbiAgICB9XG4gIH1cblxuICB0aHJvdyBuZXcgRXJyb3IoYFByb3BlcnR5ICR7IHByb3BlcnR5IH0gbm90IGZvdW5kIGluICR7IGl0ZW0gfWApO1xufVxuXG5jbGFzcyBUdXBsZSQxIHtcblxuICBjb25zdHJ1Y3RvciguLi5hcmdzKSB7XG4gICAgdGhpcy52YWx1ZXMgPSBPYmplY3QuZnJlZXplKGFyZ3MpO1xuICB9XG5cbiAgZ2V0KGluZGV4KSB7XG4gICAgcmV0dXJuIHRoaXMudmFsdWVzW2luZGV4XTtcbiAgfVxuXG4gIGNvdW50KCkge1xuICAgIHJldHVybiB0aGlzLnZhbHVlcy5sZW5ndGg7XG4gIH1cblxuICBbU3ltYm9sLml0ZXJhdG9yXSgpIHtcbiAgICByZXR1cm4gdGhpcy52YWx1ZXNbU3ltYm9sLml0ZXJhdG9yXSgpO1xuICB9XG5cbiAgdG9TdHJpbmcoKSB7XG4gICAgdmFyIGksXG4gICAgICAgIHMgPSBcIlwiO1xuICAgIGZvciAoaSA9IDA7IGkgPCB0aGlzLnZhbHVlcy5sZW5ndGg7IGkrKykge1xuICAgICAgaWYgKHMgIT09IFwiXCIpIHtcbiAgICAgICAgcyArPSBcIiwgXCI7XG4gICAgICB9XG4gICAgICBzICs9IHRoaXMudmFsdWVzW2ldLnRvU3RyaW5nKCk7XG4gICAgfVxuXG4gICAgcmV0dXJuIFwie1wiICsgcyArIFwifVwiO1xuICB9XG5cbn1cblxubGV0IHByb2Nlc3NfY291bnRlciA9IC0xO1xuXG5jbGFzcyBQSUQge1xuICBjb25zdHJ1Y3RvcigpIHtcbiAgICBwcm9jZXNzX2NvdW50ZXIgPSBwcm9jZXNzX2NvdW50ZXIgKyAxO1xuICAgIHRoaXMuaWQgPSBwcm9jZXNzX2NvdW50ZXI7XG4gIH1cblxuICB0b1N0cmluZygpIHtcbiAgICByZXR1cm4gXCJQSUQjPDAuXCIgKyB0aGlzLmlkICsgXCIuMD5cIjtcbiAgfVxufVxuXG5jbGFzcyBJbnRlZ2VyVHlwZSB7fVxuXG5jbGFzcyBGbG9hdFR5cGUge31cblxuLyogQGZsb3cgKi9cblxuY2xhc3MgVmFyaWFibGUge1xuXG4gIGNvbnN0cnVjdG9yKG5hbWUgPSBudWxsKSB7XG4gICAgdGhpcy5uYW1lID0gbmFtZTtcbiAgfVxufVxuXG5jbGFzcyBXaWxkY2FyZCB7XG4gIGNvbnN0cnVjdG9yKCkge31cbn1cblxuY2xhc3MgU3RhcnRzV2l0aCB7XG5cbiAgY29uc3RydWN0b3IocHJlZml4KSB7XG4gICAgdGhpcy5wcmVmaXggPSBwcmVmaXg7XG4gIH1cbn1cblxuY2xhc3MgQ2FwdHVyZSB7XG5cbiAgY29uc3RydWN0b3IodmFsdWUpIHtcbiAgICB0aGlzLnZhbHVlID0gdmFsdWU7XG4gIH1cbn1cblxuY2xhc3MgSGVhZFRhaWwge1xuICBjb25zdHJ1Y3RvcigpIHt9XG59XG5cbmNsYXNzIFR5cGUge1xuXG4gIGNvbnN0cnVjdG9yKHR5cGUsIG9ialBhdHRlcm4gPSB7fSkge1xuICAgIHRoaXMudHlwZSA9IHR5cGU7XG4gICAgdGhpcy5vYmpQYXR0ZXJuID0gb2JqUGF0dGVybjtcbiAgfVxufVxuXG5jbGFzcyBCb3VuZCB7XG5cbiAgY29uc3RydWN0b3IodmFsdWUpIHtcbiAgICB0aGlzLnZhbHVlID0gdmFsdWU7XG4gIH1cbn1cblxuZnVuY3Rpb24gdmFyaWFibGUobmFtZSA9IG51bGwpIHtcbiAgcmV0dXJuIG5ldyBWYXJpYWJsZShuYW1lKTtcbn1cblxuZnVuY3Rpb24gd2lsZGNhcmQoKSB7XG4gIHJldHVybiBuZXcgV2lsZGNhcmQoKTtcbn1cblxuZnVuY3Rpb24gc3RhcnRzV2l0aChwcmVmaXgpIHtcbiAgcmV0dXJuIG5ldyBTdGFydHNXaXRoKHByZWZpeCk7XG59XG5cbmZ1bmN0aW9uIGNhcHR1cmUodmFsdWUpIHtcbiAgcmV0dXJuIG5ldyBDYXB0dXJlKHZhbHVlKTtcbn1cblxuZnVuY3Rpb24gaGVhZFRhaWwoKSB7XG4gIHJldHVybiBuZXcgSGVhZFRhaWwoKTtcbn1cblxuZnVuY3Rpb24gdHlwZSh0eXBlLCBvYmpQYXR0ZXJuID0ge30pIHtcbiAgcmV0dXJuIG5ldyBUeXBlKHR5cGUsIG9ialBhdHRlcm4pO1xufVxuXG5mdW5jdGlvbiBib3VuZCh2YWx1ZSkge1xuICByZXR1cm4gbmV3IEJvdW5kKHZhbHVlKTtcbn1cblxuZnVuY3Rpb24gaXNfbnVtYmVyJDEodmFsdWUpIHtcbiAgcmV0dXJuIHR5cGVvZiB2YWx1ZSA9PT0gJ251bWJlcic7XG59XG5cbmZ1bmN0aW9uIGlzX3N0cmluZyh2YWx1ZSkge1xuICByZXR1cm4gdHlwZW9mIHZhbHVlID09PSAnc3RyaW5nJztcbn1cblxuZnVuY3Rpb24gaXNfYm9vbGVhbiQxKHZhbHVlKSB7XG4gIHJldHVybiB0eXBlb2YgdmFsdWUgPT09ICdib29sZWFuJztcbn1cblxuZnVuY3Rpb24gaXNfc3ltYm9sKHZhbHVlKSB7XG4gIHJldHVybiB0eXBlb2YgdmFsdWUgPT09ICdzeW1ib2wnO1xufVxuXG5mdW5jdGlvbiBpc19udWxsKHZhbHVlKSB7XG4gIHJldHVybiB2YWx1ZSA9PT0gbnVsbDtcbn1cblxuZnVuY3Rpb24gaXNfdW5kZWZpbmVkKHZhbHVlKSB7XG4gIHJldHVybiB0eXBlb2YgdmFsdWUgPT09ICd1bmRlZmluZWQnO1xufVxuXG5mdW5jdGlvbiBpc19mdW5jdGlvbiQxKHZhbHVlKSB7XG4gIHJldHVybiBPYmplY3QucHJvdG90eXBlLnRvU3RyaW5nLmNhbGwodmFsdWUpID09ICdbb2JqZWN0IEZ1bmN0aW9uXSc7XG59XG5cbmZ1bmN0aW9uIGlzX3ZhcmlhYmxlKHZhbHVlKSB7XG4gIHJldHVybiB2YWx1ZSBpbnN0YW5jZW9mIFZhcmlhYmxlO1xufVxuXG5mdW5jdGlvbiBpc193aWxkY2FyZCh2YWx1ZSkge1xuICByZXR1cm4gdmFsdWUgaW5zdGFuY2VvZiBXaWxkY2FyZDtcbn1cblxuZnVuY3Rpb24gaXNfaGVhZFRhaWwodmFsdWUpIHtcbiAgcmV0dXJuIHZhbHVlIGluc3RhbmNlb2YgSGVhZFRhaWw7XG59XG5cbmZ1bmN0aW9uIGlzX2NhcHR1cmUodmFsdWUpIHtcbiAgcmV0dXJuIHZhbHVlIGluc3RhbmNlb2YgQ2FwdHVyZTtcbn1cblxuZnVuY3Rpb24gaXNfdHlwZSh2YWx1ZSkge1xuICByZXR1cm4gdmFsdWUgaW5zdGFuY2VvZiBUeXBlO1xufVxuXG5mdW5jdGlvbiBpc19zdGFydHNXaXRoKHZhbHVlKSB7XG4gIHJldHVybiB2YWx1ZSBpbnN0YW5jZW9mIFN0YXJ0c1dpdGg7XG59XG5cbmZ1bmN0aW9uIGlzX2JvdW5kKHZhbHVlKSB7XG4gIHJldHVybiB2YWx1ZSBpbnN0YW5jZW9mIEJvdW5kO1xufVxuXG5mdW5jdGlvbiBpc19vYmplY3QodmFsdWUpIHtcbiAgcmV0dXJuIHR5cGVvZiB2YWx1ZSA9PT0gJ29iamVjdCc7XG59XG5cbmZ1bmN0aW9uIGlzX2FycmF5KHZhbHVlKSB7XG4gIHJldHVybiBBcnJheS5pc0FycmF5KHZhbHVlKTtcbn1cblxudmFyIENoZWNrcyA9IHtcbiAgaXNfbnVtYmVyOiBpc19udW1iZXIkMSxcbiAgaXNfc3RyaW5nLFxuICBpc19ib29sZWFuOiBpc19ib29sZWFuJDEsXG4gIGlzX3N5bWJvbCxcbiAgaXNfbnVsbCxcbiAgaXNfdW5kZWZpbmVkLFxuICBpc19mdW5jdGlvbjogaXNfZnVuY3Rpb24kMSxcbiAgaXNfdmFyaWFibGUsXG4gIGlzX3dpbGRjYXJkLFxuICBpc19oZWFkVGFpbCxcbiAgaXNfY2FwdHVyZSxcbiAgaXNfdHlwZSxcbiAgaXNfc3RhcnRzV2l0aCxcbiAgaXNfYm91bmQsXG4gIGlzX29iamVjdCxcbiAgaXNfYXJyYXlcbn07XG5cbmZ1bmN0aW9uIHJlc29sdmVTeW1ib2wocGF0dGVybikge1xuICByZXR1cm4gZnVuY3Rpb24gKHZhbHVlKSB7XG4gICAgcmV0dXJuIENoZWNrcy5pc19zeW1ib2wodmFsdWUpICYmIHZhbHVlID09PSBwYXR0ZXJuO1xuICB9O1xufVxuXG5mdW5jdGlvbiByZXNvbHZlU3RyaW5nKHBhdHRlcm4pIHtcbiAgcmV0dXJuIGZ1bmN0aW9uICh2YWx1ZSkge1xuICAgIHJldHVybiBDaGVja3MuaXNfc3RyaW5nKHZhbHVlKSAmJiB2YWx1ZSA9PT0gcGF0dGVybjtcbiAgfTtcbn1cblxuZnVuY3Rpb24gcmVzb2x2ZU51bWJlcihwYXR0ZXJuKSB7XG4gIHJldHVybiBmdW5jdGlvbiAodmFsdWUpIHtcbiAgICByZXR1cm4gQ2hlY2tzLmlzX251bWJlcih2YWx1ZSkgJiYgdmFsdWUgPT09IHBhdHRlcm47XG4gIH07XG59XG5cbmZ1bmN0aW9uIHJlc29sdmVCb29sZWFuKHBhdHRlcm4pIHtcbiAgcmV0dXJuIGZ1bmN0aW9uICh2YWx1ZSkge1xuICAgIHJldHVybiBDaGVja3MuaXNfYm9vbGVhbih2YWx1ZSkgJiYgdmFsdWUgPT09IHBhdHRlcm47XG4gIH07XG59XG5cbmZ1bmN0aW9uIHJlc29sdmVGdW5jdGlvbihwYXR0ZXJuKSB7XG4gIHJldHVybiBmdW5jdGlvbiAodmFsdWUpIHtcbiAgICByZXR1cm4gQ2hlY2tzLmlzX2Z1bmN0aW9uKHZhbHVlKSAmJiB2YWx1ZSA9PT0gcGF0dGVybjtcbiAgfTtcbn1cblxuZnVuY3Rpb24gcmVzb2x2ZU51bGwocGF0dGVybikge1xuICByZXR1cm4gZnVuY3Rpb24gKHZhbHVlKSB7XG4gICAgcmV0dXJuIENoZWNrcy5pc19udWxsKHZhbHVlKTtcbiAgfTtcbn1cblxuZnVuY3Rpb24gcmVzb2x2ZUJvdW5kKHBhdHRlcm4pIHtcbiAgcmV0dXJuIGZ1bmN0aW9uICh2YWx1ZSwgYXJncykge1xuICAgIGlmICh0eXBlb2YgdmFsdWUgPT09IHR5cGVvZiBwYXR0ZXJuLnZhbHVlICYmIHZhbHVlID09PSBwYXR0ZXJuLnZhbHVlKSB7XG4gICAgICBhcmdzLnB1c2godmFsdWUpO1xuICAgICAgcmV0dXJuIHRydWU7XG4gICAgfVxuXG4gICAgcmV0dXJuIGZhbHNlO1xuICB9O1xufVxuXG5mdW5jdGlvbiByZXNvbHZlV2lsZGNhcmQoKSB7XG4gIHJldHVybiBmdW5jdGlvbiAoKSB7XG4gICAgcmV0dXJuIHRydWU7XG4gIH07XG59XG5cbmZ1bmN0aW9uIHJlc29sdmVWYXJpYWJsZSgpIHtcbiAgcmV0dXJuIGZ1bmN0aW9uICh2YWx1ZSwgYXJncykge1xuICAgIGFyZ3MucHVzaCh2YWx1ZSk7XG4gICAgcmV0dXJuIHRydWU7XG4gIH07XG59XG5cbmZ1bmN0aW9uIHJlc29sdmVIZWFkVGFpbCgpIHtcbiAgcmV0dXJuIGZ1bmN0aW9uICh2YWx1ZSwgYXJncykge1xuICAgIGlmICghQ2hlY2tzLmlzX2FycmF5KHZhbHVlKSB8fCB2YWx1ZS5sZW5ndGggPCAyKSB7XG4gICAgICByZXR1cm4gZmFsc2U7XG4gICAgfVxuXG4gICAgY29uc3QgaGVhZCA9IHZhbHVlWzBdO1xuICAgIGNvbnN0IHRhaWwgPSB2YWx1ZS5zbGljZSgxKTtcblxuICAgIGFyZ3MucHVzaChoZWFkKTtcbiAgICBhcmdzLnB1c2godGFpbCk7XG5cbiAgICByZXR1cm4gdHJ1ZTtcbiAgfTtcbn1cblxuZnVuY3Rpb24gcmVzb2x2ZUNhcHR1cmUocGF0dGVybikge1xuICBjb25zdCBtYXRjaGVzID0gYnVpbGRNYXRjaChwYXR0ZXJuLnZhbHVlKTtcblxuICByZXR1cm4gZnVuY3Rpb24gKHZhbHVlLCBhcmdzKSB7XG4gICAgaWYgKG1hdGNoZXModmFsdWUsIGFyZ3MpKSB7XG4gICAgICBhcmdzLnB1c2godmFsdWUpO1xuICAgICAgcmV0dXJuIHRydWU7XG4gICAgfVxuXG4gICAgcmV0dXJuIGZhbHNlO1xuICB9O1xufVxuXG5mdW5jdGlvbiByZXNvbHZlU3RhcnRzV2l0aChwYXR0ZXJuKSB7XG4gIGNvbnN0IHByZWZpeCA9IHBhdHRlcm4ucHJlZml4O1xuXG4gIHJldHVybiBmdW5jdGlvbiAodmFsdWUsIGFyZ3MpIHtcbiAgICBpZiAoQ2hlY2tzLmlzX3N0cmluZyh2YWx1ZSkgJiYgdmFsdWUuc3RhcnRzV2l0aChwcmVmaXgpKSB7XG4gICAgICBhcmdzLnB1c2godmFsdWUuc3Vic3RyaW5nKHByZWZpeC5sZW5ndGgpKTtcbiAgICAgIHJldHVybiB0cnVlO1xuICAgIH1cblxuICAgIHJldHVybiBmYWxzZTtcbiAgfTtcbn1cblxuZnVuY3Rpb24gcmVzb2x2ZVR5cGUocGF0dGVybikge1xuICByZXR1cm4gZnVuY3Rpb24gKHZhbHVlLCBhcmdzKSB7XG4gICAgaWYgKHZhbHVlIGluc3RhbmNlb2YgcGF0dGVybi50eXBlKSB7XG4gICAgICBjb25zdCBtYXRjaGVzID0gYnVpbGRNYXRjaChwYXR0ZXJuLm9ialBhdHRlcm4pO1xuICAgICAgcmV0dXJuIG1hdGNoZXModmFsdWUsIGFyZ3MpICYmIGFyZ3MucHVzaCh2YWx1ZSkgPiAwO1xuICAgIH1cblxuICAgIHJldHVybiBmYWxzZTtcbiAgfTtcbn1cblxuZnVuY3Rpb24gcmVzb2x2ZUFycmF5KHBhdHRlcm4pIHtcbiAgY29uc3QgbWF0Y2hlcyA9IHBhdHRlcm4ubWFwKHggPT4gYnVpbGRNYXRjaCh4KSk7XG5cbiAgcmV0dXJuIGZ1bmN0aW9uICh2YWx1ZSwgYXJncykge1xuICAgIGlmICghQ2hlY2tzLmlzX2FycmF5KHZhbHVlKSB8fCB2YWx1ZS5sZW5ndGggIT0gcGF0dGVybi5sZW5ndGgpIHtcbiAgICAgIHJldHVybiBmYWxzZTtcbiAgICB9XG5cbiAgICByZXR1cm4gdmFsdWUuZXZlcnkoZnVuY3Rpb24gKHYsIGkpIHtcbiAgICAgIHJldHVybiBtYXRjaGVzW2ldKHZhbHVlW2ldLCBhcmdzKTtcbiAgICB9KTtcbiAgfTtcbn1cblxuZnVuY3Rpb24gcmVzb2x2ZU9iamVjdChwYXR0ZXJuKSB7XG4gIGxldCBtYXRjaGVzID0ge307XG5cbiAgZm9yIChsZXQga2V5IG9mIE9iamVjdC5rZXlzKHBhdHRlcm4pKSB7XG4gICAgbWF0Y2hlc1trZXldID0gYnVpbGRNYXRjaChwYXR0ZXJuW2tleV0pO1xuICB9XG5cbiAgcmV0dXJuIGZ1bmN0aW9uICh2YWx1ZSwgYXJncykge1xuICAgIGlmICghQ2hlY2tzLmlzX29iamVjdCh2YWx1ZSkgfHwgcGF0dGVybi5sZW5ndGggPiB2YWx1ZS5sZW5ndGgpIHtcbiAgICAgIHJldHVybiBmYWxzZTtcbiAgICB9XG5cbiAgICBmb3IgKGxldCBrZXkgb2YgT2JqZWN0LmtleXMocGF0dGVybikpIHtcbiAgICAgIGlmICghKGtleSBpbiB2YWx1ZSkgfHwgIW1hdGNoZXNba2V5XSh2YWx1ZVtrZXldLCBhcmdzKSkge1xuICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICB9XG4gICAgfVxuXG4gICAgcmV0dXJuIHRydWU7XG4gIH07XG59XG5cbmZ1bmN0aW9uIHJlc29sdmVOb01hdGNoKCkge1xuICByZXR1cm4gZnVuY3Rpb24gKCkge1xuICAgIHJldHVybiBmYWxzZTtcbiAgfTtcbn1cblxudmFyIFJlc29sdmVycyA9IHtcbiAgcmVzb2x2ZUJvdW5kLFxuICByZXNvbHZlV2lsZGNhcmQsXG4gIHJlc29sdmVWYXJpYWJsZSxcbiAgcmVzb2x2ZUhlYWRUYWlsLFxuICByZXNvbHZlQ2FwdHVyZSxcbiAgcmVzb2x2ZVN0YXJ0c1dpdGgsXG4gIHJlc29sdmVUeXBlLFxuICByZXNvbHZlQXJyYXksXG4gIHJlc29sdmVPYmplY3QsXG4gIHJlc29sdmVOb01hdGNoLFxuICByZXNvbHZlU3ltYm9sLFxuICByZXNvbHZlU3RyaW5nLFxuICByZXNvbHZlTnVtYmVyLFxuICByZXNvbHZlQm9vbGVhbixcbiAgcmVzb2x2ZUZ1bmN0aW9uLFxuICByZXNvbHZlTnVsbFxufTtcblxuZnVuY3Rpb24gYnVpbGRNYXRjaChwYXR0ZXJuKSB7XG5cbiAgaWYgKENoZWNrcy5pc192YXJpYWJsZShwYXR0ZXJuKSkge1xuICAgIHJldHVybiBSZXNvbHZlcnMucmVzb2x2ZVZhcmlhYmxlKHBhdHRlcm4pO1xuICB9XG5cbiAgaWYgKENoZWNrcy5pc193aWxkY2FyZChwYXR0ZXJuKSkge1xuICAgIHJldHVybiBSZXNvbHZlcnMucmVzb2x2ZVdpbGRjYXJkKHBhdHRlcm4pO1xuICB9XG5cbiAgaWYgKENoZWNrcy5pc191bmRlZmluZWQocGF0dGVybikpIHtcbiAgICByZXR1cm4gUmVzb2x2ZXJzLnJlc29sdmVXaWxkY2FyZChwYXR0ZXJuKTtcbiAgfVxuXG4gIGlmIChDaGVja3MuaXNfaGVhZFRhaWwocGF0dGVybikpIHtcbiAgICByZXR1cm4gUmVzb2x2ZXJzLnJlc29sdmVIZWFkVGFpbChwYXR0ZXJuKTtcbiAgfVxuXG4gIGlmIChDaGVja3MuaXNfc3RhcnRzV2l0aChwYXR0ZXJuKSkge1xuICAgIHJldHVybiBSZXNvbHZlcnMucmVzb2x2ZVN0YXJ0c1dpdGgocGF0dGVybik7XG4gIH1cblxuICBpZiAoQ2hlY2tzLmlzX2NhcHR1cmUocGF0dGVybikpIHtcbiAgICByZXR1cm4gUmVzb2x2ZXJzLnJlc29sdmVDYXB0dXJlKHBhdHRlcm4pO1xuICB9XG5cbiAgaWYgKENoZWNrcy5pc19ib3VuZChwYXR0ZXJuKSkge1xuICAgIHJldHVybiBSZXNvbHZlcnMucmVzb2x2ZUJvdW5kKHBhdHRlcm4pO1xuICB9XG5cbiAgaWYgKENoZWNrcy5pc190eXBlKHBhdHRlcm4pKSB7XG4gICAgcmV0dXJuIFJlc29sdmVycy5yZXNvbHZlVHlwZShwYXR0ZXJuKTtcbiAgfVxuXG4gIGlmIChDaGVja3MuaXNfYXJyYXkocGF0dGVybikpIHtcbiAgICByZXR1cm4gUmVzb2x2ZXJzLnJlc29sdmVBcnJheShwYXR0ZXJuKTtcbiAgfVxuXG4gIGlmIChDaGVja3MuaXNfbnVtYmVyKHBhdHRlcm4pKSB7XG4gICAgcmV0dXJuIFJlc29sdmVycy5yZXNvbHZlTnVtYmVyKHBhdHRlcm4pO1xuICB9XG5cbiAgaWYgKENoZWNrcy5pc19zdHJpbmcocGF0dGVybikpIHtcbiAgICByZXR1cm4gUmVzb2x2ZXJzLnJlc29sdmVTdHJpbmcocGF0dGVybik7XG4gIH1cblxuICBpZiAoQ2hlY2tzLmlzX2Jvb2xlYW4ocGF0dGVybikpIHtcbiAgICByZXR1cm4gUmVzb2x2ZXJzLnJlc29sdmVCb29sZWFuKHBhdHRlcm4pO1xuICB9XG5cbiAgaWYgKENoZWNrcy5pc19zeW1ib2wocGF0dGVybikpIHtcbiAgICByZXR1cm4gUmVzb2x2ZXJzLnJlc29sdmVTeW1ib2wocGF0dGVybik7XG4gIH1cblxuICBpZiAoQ2hlY2tzLmlzX251bGwocGF0dGVybikpIHtcbiAgICByZXR1cm4gUmVzb2x2ZXJzLnJlc29sdmVOdWxsKHBhdHRlcm4pO1xuICB9XG5cbiAgaWYgKENoZWNrcy5pc19vYmplY3QocGF0dGVybikpIHtcbiAgICByZXR1cm4gUmVzb2x2ZXJzLnJlc29sdmVPYmplY3QocGF0dGVybik7XG4gIH1cblxuICByZXR1cm4gUmVzb2x2ZXJzLnJlc29sdmVOb01hdGNoKCk7XG59XG5cbmNsYXNzIE1hdGNoRXJyb3IgZXh0ZW5kcyBFcnJvciB7XG4gIGNvbnN0cnVjdG9yKGFyZykge1xuICAgIHN1cGVyKCk7XG5cbiAgICBpZiAodHlwZW9mIGFyZyA9PT0gJ3N5bWJvbCcpIHtcbiAgICAgIHRoaXMubWVzc2FnZSA9ICdObyBtYXRjaCBmb3I6ICcgKyBhcmcudG9TdHJpbmcoKTtcbiAgICB9IGVsc2UgaWYgKEFycmF5LmlzQXJyYXkoYXJnKSkge1xuICAgICAgbGV0IG1hcHBlZFZhbHVlcyA9IGFyZy5tYXAoeCA9PiB4LnRvU3RyaW5nKCkpO1xuICAgICAgdGhpcy5tZXNzYWdlID0gJ05vIG1hdGNoIGZvcjogJyArIG1hcHBlZFZhbHVlcztcbiAgICB9IGVsc2Uge1xuICAgICAgdGhpcy5tZXNzYWdlID0gJ05vIG1hdGNoIGZvcjogJyArIGFyZztcbiAgICB9XG5cbiAgICB0aGlzLnN0YWNrID0gbmV3IEVycm9yKCkuc3RhY2s7XG4gICAgdGhpcy5uYW1lID0gdGhpcy5jb25zdHJ1Y3Rvci5uYW1lO1xuICB9XG59XG5cbmNsYXNzIENhc2Uge1xuXG4gIGNvbnN0cnVjdG9yKHBhdHRlcm4sIGZuLCBndWFyZCA9ICgpID0+IHRydWUpIHtcbiAgICB0aGlzLnBhdHRlcm4gPSBidWlsZE1hdGNoKHBhdHRlcm4pO1xuICAgIHRoaXMuZm4gPSBmbjtcbiAgICB0aGlzLmd1YXJkID0gZ3VhcmQ7XG4gIH1cbn1cblxuZnVuY3Rpb24gbWFrZV9jYXNlKHBhdHRlcm4sIGZuLCBndWFyZCA9ICgpID0+IHRydWUpIHtcbiAgcmV0dXJuIG5ldyBDYXNlKHBhdHRlcm4sIGZuLCBndWFyZCk7XG59XG5cbmZ1bmN0aW9uIGRlZm1hdGNoKC4uLmNhc2VzKSB7XG4gIHJldHVybiBmdW5jdGlvbiAoLi4uYXJncykge1xuICAgIGZvciAobGV0IHByb2Nlc3NlZENhc2Ugb2YgY2FzZXMpIHtcbiAgICAgIGxldCByZXN1bHQgPSBbXTtcbiAgICAgIGlmIChwcm9jZXNzZWRDYXNlLnBhdHRlcm4oYXJncywgcmVzdWx0KSAmJiBwcm9jZXNzZWRDYXNlLmd1YXJkLmFwcGx5KHRoaXMsIHJlc3VsdCkpIHtcbiAgICAgICAgcmV0dXJuIHByb2Nlc3NlZENhc2UuZm4uYXBwbHkodGhpcywgcmVzdWx0KTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICB0aHJvdyBuZXcgTWF0Y2hFcnJvcihhcmdzKTtcbiAgfTtcbn1cblxuZnVuY3Rpb24gbWF0Y2gocGF0dGVybiwgZXhwciwgZ3VhcmQgPSAoKSA9PiB0cnVlKSB7XG4gIGxldCByZXN1bHQgPSBbXTtcbiAgbGV0IHByb2Nlc3NlZFBhdHRlcm4gPSBidWlsZE1hdGNoKHBhdHRlcm4pO1xuICBpZiAocHJvY2Vzc2VkUGF0dGVybihleHByLCByZXN1bHQpICYmIGd1YXJkLmFwcGx5KHRoaXMsIHJlc3VsdCkpIHtcbiAgICByZXR1cm4gcmVzdWx0O1xuICB9IGVsc2Uge1xuICAgIHRocm93IG5ldyBNYXRjaEVycm9yKGV4cHIpO1xuICB9XG59XG5cbmZ1bmN0aW9uIG1hdGNoX25vX3Rocm93KHBhdHRlcm4sIGV4cHIsIGd1YXJkID0gKCkgPT4gdHJ1ZSkge1xuICB0cnkge1xuICAgIHJldHVybiBtYXRjaChwYXR0ZXJuLCBleHByLCBndWFyZCk7XG4gIH0gY2F0Y2ggKGUpIHtcbiAgICBpZiAoZSBpbnN0YW5jZW9mIE1hdGNoRXJyb3IpIHtcbiAgICAgIHJldHVybiBudWxsO1xuICAgIH1cblxuICAgIHRocm93IGU7XG4gIH1cbn1cblxudmFyIFBhdHRlcm5zID0ge1xuICBkZWZtYXRjaCwgbWF0Y2gsIE1hdGNoRXJyb3IsIG1hdGNoX25vX3Rocm93LFxuICB2YXJpYWJsZSwgd2lsZGNhcmQsIHN0YXJ0c1dpdGgsXG4gIGNhcHR1cmUsIGhlYWRUYWlsLCB0eXBlLCBib3VuZCwgQ2FzZSwgbWFrZV9jYXNlXG59O1xuXG5jbGFzcyBCaXRTdHJpbmcge1xuICBjb25zdHJ1Y3RvciguLi5hcmdzKSB7XG4gICAgdGhpcy5yYXdfdmFsdWUgPSBmdW5jdGlvbiAoKSB7XG4gICAgICByZXR1cm4gT2JqZWN0LmZyZWV6ZShhcmdzKTtcbiAgICB9O1xuXG4gICAgdGhpcy52YWx1ZSA9IE9iamVjdC5mcmVlemUodGhpcy5wcm9jZXNzKGFyZ3MpKTtcbiAgfVxuXG4gIGdldChpbmRleCkge1xuICAgIHJldHVybiB0aGlzLnZhbHVlW2luZGV4XTtcbiAgfVxuXG4gIGNvdW50KCkge1xuICAgIHJldHVybiB0aGlzLnZhbHVlLmxlbmd0aDtcbiAgfVxuXG4gIFtTeW1ib2wuaXRlcmF0b3JdKCkge1xuICAgIHJldHVybiB0aGlzLnZhbHVlW1N5bWJvbC5pdGVyYXRvcl0oKTtcbiAgfVxuXG4gIHRvU3RyaW5nKCkge1xuICAgIHZhciBpLFxuICAgICAgICBzID0gXCJcIjtcbiAgICBmb3IgKGkgPSAwOyBpIDwgdGhpcy5jb3VudCgpOyBpKyspIHtcbiAgICAgIGlmIChzICE9PSBcIlwiKSB7XG4gICAgICAgIHMgKz0gXCIsIFwiO1xuICAgICAgfVxuICAgICAgcyArPSB0aGlzW2ldLnRvU3RyaW5nKCk7XG4gICAgfVxuXG4gICAgcmV0dXJuIFwiPDxcIiArIHMgKyBcIj4+XCI7XG4gIH1cblxuICBwcm9jZXNzKCkge1xuICAgIGxldCBwcm9jZXNzZWRfdmFsdWVzID0gW107XG5cbiAgICB2YXIgaTtcbiAgICBmb3IgKGkgPSAwOyBpIDwgdGhpcy5yYXdfdmFsdWUoKS5sZW5ndGg7IGkrKykge1xuICAgICAgbGV0IHByb2Nlc3NlZF92YWx1ZSA9IHRoaXNbXCJwcm9jZXNzX1wiICsgdGhpcy5yYXdfdmFsdWUoKVtpXS50eXBlXSh0aGlzLnJhd192YWx1ZSgpW2ldKTtcblxuICAgICAgZm9yIChsZXQgYXR0ciBvZiB0aGlzLnJhd192YWx1ZSgpW2ldLmF0dHJpYnV0ZXMpIHtcbiAgICAgICAgcHJvY2Vzc2VkX3ZhbHVlID0gdGhpc1tcInByb2Nlc3NfXCIgKyBhdHRyXShwcm9jZXNzZWRfdmFsdWUpO1xuICAgICAgfVxuXG4gICAgICBwcm9jZXNzZWRfdmFsdWVzID0gcHJvY2Vzc2VkX3ZhbHVlcy5jb25jYXQocHJvY2Vzc2VkX3ZhbHVlKTtcbiAgICB9XG5cbiAgICByZXR1cm4gcHJvY2Vzc2VkX3ZhbHVlcztcbiAgfVxuXG4gIHByb2Nlc3NfaW50ZWdlcih2YWx1ZSkge1xuICAgIHJldHVybiB2YWx1ZS52YWx1ZTtcbiAgfVxuXG4gIHByb2Nlc3NfZmxvYXQodmFsdWUpIHtcbiAgICBpZiAodmFsdWUuc2l6ZSA9PT0gNjQpIHtcbiAgICAgIHJldHVybiBCaXRTdHJpbmcuZmxvYXQ2NFRvQnl0ZXModmFsdWUudmFsdWUpO1xuICAgIH0gZWxzZSBpZiAodmFsdWUuc2l6ZSA9PT0gMzIpIHtcbiAgICAgIHJldHVybiBCaXRTdHJpbmcuZmxvYXQzMlRvQnl0ZXModmFsdWUudmFsdWUpO1xuICAgIH1cblxuICAgIHRocm93IG5ldyBFcnJvcihcIkludmFsaWQgc2l6ZSBmb3IgZmxvYXRcIik7XG4gIH1cblxuICBwcm9jZXNzX2JpdHN0cmluZyh2YWx1ZSkge1xuICAgIHJldHVybiB2YWx1ZS52YWx1ZS52YWx1ZTtcbiAgfVxuXG4gIHByb2Nlc3NfYmluYXJ5KHZhbHVlKSB7XG4gICAgcmV0dXJuIEJpdFN0cmluZy50b1VURjhBcnJheSh2YWx1ZS52YWx1ZSk7XG4gIH1cblxuICBwcm9jZXNzX3V0ZjgodmFsdWUpIHtcbiAgICByZXR1cm4gQml0U3RyaW5nLnRvVVRGOEFycmF5KHZhbHVlLnZhbHVlKTtcbiAgfVxuXG4gIHByb2Nlc3NfdXRmMTYodmFsdWUpIHtcbiAgICByZXR1cm4gQml0U3RyaW5nLnRvVVRGMTZBcnJheSh2YWx1ZS52YWx1ZSk7XG4gIH1cblxuICBwcm9jZXNzX3V0ZjMyKHZhbHVlKSB7XG4gICAgcmV0dXJuIEJpdFN0cmluZy50b1VURjMyQXJyYXkodmFsdWUudmFsdWUpO1xuICB9XG5cbiAgcHJvY2Vzc19zaWduZWQodmFsdWUpIHtcbiAgICByZXR1cm4gbmV3IFVpbnQ4QXJyYXkoW3ZhbHVlXSlbMF07XG4gIH1cblxuICBwcm9jZXNzX3Vuc2lnbmVkKHZhbHVlKSB7XG4gICAgcmV0dXJuIHZhbHVlO1xuICB9XG5cbiAgcHJvY2Vzc19uYXRpdmUodmFsdWUpIHtcbiAgICByZXR1cm4gdmFsdWU7XG4gIH1cblxuICBwcm9jZXNzX2JpZyh2YWx1ZSkge1xuICAgIHJldHVybiB2YWx1ZTtcbiAgfVxuXG4gIHByb2Nlc3NfbGl0dGxlKHZhbHVlKSB7XG4gICAgcmV0dXJuIHZhbHVlLnJldmVyc2UoKTtcbiAgfVxuXG4gIHByb2Nlc3Nfc2l6ZSh2YWx1ZSkge1xuICAgIHJldHVybiB2YWx1ZTtcbiAgfVxuXG4gIHByb2Nlc3NfdW5pdCh2YWx1ZSkge1xuICAgIHJldHVybiB2YWx1ZTtcbiAgfVxuXG4gIHN0YXRpYyBpbnRlZ2VyKHZhbHVlKSB7XG4gICAgcmV0dXJuIEJpdFN0cmluZy53cmFwKHZhbHVlLCB7IFwidHlwZVwiOiBcImludGVnZXJcIiwgXCJ1bml0XCI6IDEsIFwic2l6ZVwiOiA4IH0pO1xuICB9XG5cbiAgc3RhdGljIGZsb2F0KHZhbHVlKSB7XG4gICAgcmV0dXJuIEJpdFN0cmluZy53cmFwKHZhbHVlLCB7IFwidHlwZVwiOiBcImZsb2F0XCIsIFwidW5pdFwiOiAxLCBcInNpemVcIjogNjQgfSk7XG4gIH1cblxuICBzdGF0aWMgYml0c3RyaW5nKHZhbHVlKSB7XG4gICAgcmV0dXJuIEJpdFN0cmluZy53cmFwKHZhbHVlLCB7IFwidHlwZVwiOiBcImJpdHN0cmluZ1wiLCBcInVuaXRcIjogMSwgXCJzaXplXCI6IHZhbHVlLmxlbmd0aCB9KTtcbiAgfVxuXG4gIHN0YXRpYyBiaXRzKHZhbHVlKSB7XG4gICAgcmV0dXJuIEJpdFN0cmluZy5iaXRzdHJpbmcodmFsdWUpO1xuICB9XG5cbiAgc3RhdGljIGJpbmFyeSh2YWx1ZSkge1xuICAgIHJldHVybiBCaXRTdHJpbmcud3JhcCh2YWx1ZSwgeyBcInR5cGVcIjogXCJiaW5hcnlcIiwgXCJ1bml0XCI6IDgsIFwic2l6ZVwiOiB2YWx1ZS5sZW5ndGggfSk7XG4gIH1cblxuICBzdGF0aWMgYnl0ZXModmFsdWUpIHtcbiAgICByZXR1cm4gQml0U3RyaW5nLmJpbmFyeSh2YWx1ZSk7XG4gIH1cblxuICBzdGF0aWMgdXRmOCh2YWx1ZSkge1xuICAgIHJldHVybiBCaXRTdHJpbmcud3JhcCh2YWx1ZSwgeyBcInR5cGVcIjogXCJ1dGY4XCIgfSk7XG4gIH1cblxuICBzdGF0aWMgdXRmMTYodmFsdWUpIHtcbiAgICByZXR1cm4gQml0U3RyaW5nLndyYXAodmFsdWUsIHsgXCJ0eXBlXCI6IFwidXRmMTZcIiB9KTtcbiAgfVxuXG4gIHN0YXRpYyB1dGYzMih2YWx1ZSkge1xuICAgIHJldHVybiBCaXRTdHJpbmcud3JhcCh2YWx1ZSwgeyBcInR5cGVcIjogXCJ1dGYzMlwiIH0pO1xuICB9XG5cbiAgc3RhdGljIHNpZ25lZCh2YWx1ZSkge1xuICAgIHJldHVybiBCaXRTdHJpbmcud3JhcCh2YWx1ZSwge30sIFwic2lnbmVkXCIpO1xuICB9XG5cbiAgc3RhdGljIHVuc2lnbmVkKHZhbHVlKSB7XG4gICAgcmV0dXJuIEJpdFN0cmluZy53cmFwKHZhbHVlLCB7fSwgXCJ1bnNpZ25lZFwiKTtcbiAgfVxuXG4gIHN0YXRpYyBuYXRpdmUodmFsdWUpIHtcbiAgICByZXR1cm4gQml0U3RyaW5nLndyYXAodmFsdWUsIHt9LCBcIm5hdGl2ZVwiKTtcbiAgfVxuXG4gIHN0YXRpYyBiaWcodmFsdWUpIHtcbiAgICByZXR1cm4gQml0U3RyaW5nLndyYXAodmFsdWUsIHt9LCBcImJpZ1wiKTtcbiAgfVxuXG4gIHN0YXRpYyBsaXR0bGUodmFsdWUpIHtcbiAgICByZXR1cm4gQml0U3RyaW5nLndyYXAodmFsdWUsIHt9LCBcImxpdHRsZVwiKTtcbiAgfVxuXG4gIHN0YXRpYyBzaXplKHZhbHVlLCBjb3VudCkge1xuICAgIHJldHVybiBCaXRTdHJpbmcud3JhcCh2YWx1ZSwgeyBcInNpemVcIjogY291bnQgfSk7XG4gIH1cblxuICBzdGF0aWMgdW5pdCh2YWx1ZSwgY291bnQpIHtcbiAgICByZXR1cm4gQml0U3RyaW5nLndyYXAodmFsdWUsIHsgXCJ1bml0XCI6IGNvdW50IH0pO1xuICB9XG5cbiAgc3RhdGljIHdyYXAodmFsdWUsIG9wdCwgbmV3X2F0dHJpYnV0ZSA9IG51bGwpIHtcbiAgICBsZXQgdGhlX3ZhbHVlID0gdmFsdWU7XG5cbiAgICBpZiAoISh2YWx1ZSBpbnN0YW5jZW9mIE9iamVjdCkpIHtcbiAgICAgIHRoZV92YWx1ZSA9IHsgXCJ2YWx1ZVwiOiB2YWx1ZSwgXCJhdHRyaWJ1dGVzXCI6IFtdIH07XG4gICAgfVxuXG4gICAgdGhlX3ZhbHVlID0gT2JqZWN0LmFzc2lnbih0aGVfdmFsdWUsIG9wdCk7XG5cbiAgICBpZiAobmV3X2F0dHJpYnV0ZSkge1xuICAgICAgdGhlX3ZhbHVlLmF0dHJpYnV0ZXMucHVzaChuZXdfYXR0cmlidXRlKTtcbiAgICB9XG5cbiAgICByZXR1cm4gdGhlX3ZhbHVlO1xuICB9XG5cbiAgc3RhdGljIHRvVVRGOEFycmF5KHN0cikge1xuICAgIHZhciB1dGY4ID0gW107XG4gICAgZm9yICh2YXIgaSA9IDA7IGkgPCBzdHIubGVuZ3RoOyBpKyspIHtcbiAgICAgIHZhciBjaGFyY29kZSA9IHN0ci5jaGFyQ29kZUF0KGkpO1xuICAgICAgaWYgKGNoYXJjb2RlIDwgMTI4KSB7XG4gICAgICAgIHV0ZjgucHVzaChjaGFyY29kZSk7XG4gICAgICB9IGVsc2UgaWYgKGNoYXJjb2RlIDwgMjA0OCkge1xuICAgICAgICB1dGY4LnB1c2goMTkyIHwgY2hhcmNvZGUgPj4gNiwgMTI4IHwgY2hhcmNvZGUgJiA2Myk7XG4gICAgICB9IGVsc2UgaWYgKGNoYXJjb2RlIDwgNTUyOTYgfHwgY2hhcmNvZGUgPj0gNTczNDQpIHtcbiAgICAgICAgdXRmOC5wdXNoKDIyNCB8IGNoYXJjb2RlID4+IDEyLCAxMjggfCBjaGFyY29kZSA+PiA2ICYgNjMsIDEyOCB8IGNoYXJjb2RlICYgNjMpO1xuICAgICAgfVxuICAgICAgLy8gc3Vycm9nYXRlIHBhaXJcbiAgICAgIGVsc2Uge1xuICAgICAgICBpKys7XG4gICAgICAgIC8vIFVURi0xNiBlbmNvZGVzIDB4MTAwMDAtMHgxMEZGRkYgYnlcbiAgICAgICAgLy8gc3VidHJhY3RpbmcgMHgxMDAwMCBhbmQgc3BsaXR0aW5nIHRoZVxuICAgICAgICAvLyAyMCBiaXRzIG9mIDB4MC0weEZGRkZGIGludG8gdHdvIGhhbHZlc1xuICAgICAgICBjaGFyY29kZSA9IDY1NTM2ICsgKChjaGFyY29kZSAmIDEwMjMpIDw8IDEwIHwgc3RyLmNoYXJDb2RlQXQoaSkgJiAxMDIzKTtcbiAgICAgICAgdXRmOC5wdXNoKDI0MCB8IGNoYXJjb2RlID4+IDE4LCAxMjggfCBjaGFyY29kZSA+PiAxMiAmIDYzLCAxMjggfCBjaGFyY29kZSA+PiA2ICYgNjMsIDEyOCB8IGNoYXJjb2RlICYgNjMpO1xuICAgICAgfVxuICAgIH1cbiAgICByZXR1cm4gdXRmODtcbiAgfVxuXG4gIHN0YXRpYyB0b1VURjE2QXJyYXkoc3RyKSB7XG4gICAgdmFyIHV0ZjE2ID0gW107XG4gICAgZm9yICh2YXIgaSA9IDA7IGkgPCBzdHIubGVuZ3RoOyBpKyspIHtcbiAgICAgIHZhciBjb2RlUG9pbnQgPSBzdHIuY29kZVBvaW50QXQoaSk7XG5cbiAgICAgIGlmIChjb2RlUG9pbnQgPD0gMjU1KSB7XG4gICAgICAgIHV0ZjE2LnB1c2goMCk7XG4gICAgICAgIHV0ZjE2LnB1c2goY29kZVBvaW50KTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHV0ZjE2LnB1c2goY29kZVBvaW50ID4+IDggJiAyNTUpO1xuICAgICAgICB1dGYxNi5wdXNoKGNvZGVQb2ludCAmIDI1NSk7XG4gICAgICB9XG4gICAgfVxuICAgIHJldHVybiB1dGYxNjtcbiAgfVxuXG4gIHN0YXRpYyB0b1VURjMyQXJyYXkoc3RyKSB7XG4gICAgdmFyIHV0ZjMyID0gW107XG4gICAgZm9yICh2YXIgaSA9IDA7IGkgPCBzdHIubGVuZ3RoOyBpKyspIHtcbiAgICAgIHZhciBjb2RlUG9pbnQgPSBzdHIuY29kZVBvaW50QXQoaSk7XG5cbiAgICAgIGlmIChjb2RlUG9pbnQgPD0gMjU1KSB7XG4gICAgICAgIHV0ZjMyLnB1c2goMCk7XG4gICAgICAgIHV0ZjMyLnB1c2goMCk7XG4gICAgICAgIHV0ZjMyLnB1c2goMCk7XG4gICAgICAgIHV0ZjMyLnB1c2goY29kZVBvaW50KTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHV0ZjMyLnB1c2goMCk7XG4gICAgICAgIHV0ZjMyLnB1c2goMCk7XG4gICAgICAgIHV0ZjMyLnB1c2goY29kZVBvaW50ID4+IDggJiAyNTUpO1xuICAgICAgICB1dGYzMi5wdXNoKGNvZGVQb2ludCAmIDI1NSk7XG4gICAgICB9XG4gICAgfVxuICAgIHJldHVybiB1dGYzMjtcbiAgfVxuXG4gIC8vaHR0cDovL3N0YWNrb3ZlcmZsb3cuY29tL3F1ZXN0aW9ucy8yMDAzNDkzL2phdmFzY3JpcHQtZmxvYXQtZnJvbS10by1iaXRzXG4gIHN0YXRpYyBmbG9hdDMyVG9CeXRlcyhmKSB7XG4gICAgdmFyIGJ5dGVzID0gW107XG5cbiAgICB2YXIgYnVmID0gbmV3IEFycmF5QnVmZmVyKDQpO1xuICAgIG5ldyBGbG9hdDMyQXJyYXkoYnVmKVswXSA9IGY7XG5cbiAgICBsZXQgaW50VmVyc2lvbiA9IG5ldyBVaW50MzJBcnJheShidWYpWzBdO1xuXG4gICAgYnl0ZXMucHVzaChpbnRWZXJzaW9uID4+IDI0ICYgMjU1KTtcbiAgICBieXRlcy5wdXNoKGludFZlcnNpb24gPj4gMTYgJiAyNTUpO1xuICAgIGJ5dGVzLnB1c2goaW50VmVyc2lvbiA+PiA4ICYgMjU1KTtcbiAgICBieXRlcy5wdXNoKGludFZlcnNpb24gJiAyNTUpO1xuXG4gICAgcmV0dXJuIGJ5dGVzO1xuICB9XG5cbiAgc3RhdGljIGZsb2F0NjRUb0J5dGVzKGYpIHtcbiAgICB2YXIgYnl0ZXMgPSBbXTtcblxuICAgIHZhciBidWYgPSBuZXcgQXJyYXlCdWZmZXIoOCk7XG4gICAgbmV3IEZsb2F0NjRBcnJheShidWYpWzBdID0gZjtcblxuICAgIHZhciBpbnRWZXJzaW9uMSA9IG5ldyBVaW50MzJBcnJheShidWYpWzBdO1xuICAgIHZhciBpbnRWZXJzaW9uMiA9IG5ldyBVaW50MzJBcnJheShidWYpWzFdO1xuXG4gICAgYnl0ZXMucHVzaChpbnRWZXJzaW9uMiA+PiAyNCAmIDI1NSk7XG4gICAgYnl0ZXMucHVzaChpbnRWZXJzaW9uMiA+PiAxNiAmIDI1NSk7XG4gICAgYnl0ZXMucHVzaChpbnRWZXJzaW9uMiA+PiA4ICYgMjU1KTtcbiAgICBieXRlcy5wdXNoKGludFZlcnNpb24yICYgMjU1KTtcblxuICAgIGJ5dGVzLnB1c2goaW50VmVyc2lvbjEgPj4gMjQgJiAyNTUpO1xuICAgIGJ5dGVzLnB1c2goaW50VmVyc2lvbjEgPj4gMTYgJiAyNTUpO1xuICAgIGJ5dGVzLnB1c2goaW50VmVyc2lvbjEgPj4gOCAmIDI1NSk7XG4gICAgYnl0ZXMucHVzaChpbnRWZXJzaW9uMSAmIDI1NSk7XG5cbiAgICByZXR1cm4gYnl0ZXM7XG4gIH1cbn1cblxuLyogQGZsb3cgKi9cblxuY2xhc3MgTWFpbGJveCB7XG5cbiAgY29uc3RydWN0b3IoKSB7XG4gICAgdGhpcy5tZXNzYWdlcyA9IFtdO1xuICB9XG5cbiAgZGVsaXZlcihtZXNzYWdlKSB7XG4gICAgdGhpcy5tZXNzYWdlcy5wdXNoKG1lc3NhZ2UpO1xuICAgIHJldHVybiBtZXNzYWdlO1xuICB9XG5cbiAgZ2V0KCkge1xuICAgIHJldHVybiB0aGlzLm1lc3NhZ2VzO1xuICB9XG5cbiAgaXNFbXB0eSgpIHtcbiAgICByZXR1cm4gdGhpcy5tZXNzYWdlcy5sZW5ndGggPT09IDA7XG4gIH1cblxuICByZW1vdmVBdChpbmRleCkge1xuICAgIHRoaXMubWVzc2FnZXMuc3BsaWNlKGluZGV4LCAxKTtcbiAgfVxufVxuXG52YXIgU3RhdGVzID0ge1xuICBOT1JNQUw6IFN5bWJvbC5mb3IoXCJub3JtYWxcIiksXG4gIEtJTEw6IFN5bWJvbC5mb3IoXCJraWxsXCIpLFxuICBTVVNQRU5EOiBTeW1ib2wuZm9yKFwic3VzcGVuZFwiKSxcbiAgQ09OVElOVUU6IFN5bWJvbC5mb3IoXCJjb250aW51ZVwiKSxcbiAgUkVDRUlWRTogU3ltYm9sLmZvcihcInJlY2VpdmVcIiksXG4gIFNFTkQ6IFN5bWJvbC5mb3IoXCJzZW5kXCIpLFxuICBTTEVFUElORzogU3ltYm9sLmZvcihcInNsZWVwaW5nXCIpLFxuICBSVU5OSU5HOiBTeW1ib2wuZm9yKFwicnVubmluZ1wiKSxcbiAgU1VTUEVOREVEOiBTeW1ib2wuZm9yKFwic3VzcGVuZGVkXCIpLFxuICBTVE9QUEVEOiBTeW1ib2wuZm9yKFwic3RvcHBlZFwiKSxcbiAgU0xFRVA6IFN5bWJvbC5mb3IoXCJzbGVlcFwiKSxcbiAgRVhJVDogU3ltYm9sLmZvcihcImV4aXRcIiksXG4gIE5PTUFUQ0g6IFN5bWJvbC5mb3IoXCJub19tYXRjaFwiKVxufTtcblxuY2xhc3MgUHJvY2VzcyB7XG5cbiAgY29uc3RydWN0b3IocGlkLCBtYWlsYm94KSB7XG4gICAgdGhpcy5waWQgPSBwaWQ7XG4gICAgdGhpcy5tYWlsYm94ID0gbWFpbGJveDtcbiAgICB0aGlzLnN0YXR1cyA9IFN0YXRlcy5TVE9QUEVEO1xuICAgIHRoaXMuZGljdCA9IHt9O1xuICB9XG59XG5cbmNsYXNzIFByb2Nlc3NTeXN0ZW0ge1xuXG4gIGNvbnN0cnVjdG9yKCkge1xuICAgIHRoaXMucGlkcyA9IG5ldyBNYXAoKTtcbiAgICB0aGlzLm1haWxib3hlcyA9IG5ldyBNYXAoKTtcbiAgICB0aGlzLm5hbWVzID0gbmV3IE1hcCgpO1xuICAgIHRoaXMubGlua3MgPSBuZXcgTWFwKCk7XG5cbiAgICB0aGlzLmN1cnJlbnRfcHJvY2VzcyA9IG51bGw7XG4gICAgdGhpcy5zdXNwZW5kZWQgPSBuZXcgTWFwKCk7XG5cbiAgICB0aGlzLm1haW5fcHJvY2Vzc19waWQgPSB0aGlzLnNwYXduKCk7XG4gICAgdGhpcy5zZXRfY3VycmVudCh0aGlzLm1haW5fcHJvY2Vzc19waWQpO1xuICB9XG5cbiAgc3Bhd24oKSB7XG4gICAgcmV0dXJuIHRoaXMuYWRkX3Byb2MoZmFsc2UpLnBpZDtcbiAgfVxuXG4gIHNwYXduX2xpbmsoKSB7XG4gICAgcmV0dXJuIHRoaXMuYWRkX3Byb2ModHJ1ZSkucGlkO1xuICB9XG5cbiAgbGluayhwaWQpIHtcbiAgICB0aGlzLmxpbmtzLmdldCh0aGlzLnBpZCgpKS5hZGQocGlkKTtcbiAgICB0aGlzLmxpbmtzLmdldChwaWQpLmFkZCh0aGlzLnBpZCgpKTtcbiAgfVxuXG4gIHVubGluayhwaWQpIHtcbiAgICB0aGlzLmxpbmtzLmdldCh0aGlzLnBpZCgpKS5kZWxldGUocGlkKTtcbiAgICB0aGlzLmxpbmtzLmdldChwaWQpLmRlbGV0ZSh0aGlzLnBpZCgpKTtcbiAgfVxuXG4gIHNldF9jdXJyZW50KGlkKSB7XG4gICAgbGV0IHBpZCA9IHRoaXMucGlkb2YoaWQpO1xuICAgIGlmIChwaWQgIT09IG51bGwpIHtcbiAgICAgIHRoaXMuY3VycmVudF9wcm9jZXNzID0gdGhpcy5waWRzLmdldChwaWQpO1xuICAgICAgdGhpcy5jdXJyZW50X3Byb2Nlc3Muc3RhdHVzID0gU3RhdGVzLlJVTk5JTkc7XG4gICAgfVxuICB9XG5cbiAgYWRkX3Byb2MobGlua2VkKSB7XG4gICAgbGV0IG5ld3BpZCA9IG5ldyBQSUQoKTtcbiAgICBsZXQgbWFpbGJveCA9IG5ldyBNYWlsYm94KCk7XG4gICAgbGV0IG5ld3Byb2MgPSBuZXcgUHJvY2VzcyhuZXdwaWQsIG1haWxib3gpO1xuXG4gICAgdGhpcy5waWRzLnNldChuZXdwaWQsIG5ld3Byb2MpO1xuICAgIHRoaXMubWFpbGJveGVzLnNldChuZXdwaWQsIG1haWxib3gpO1xuICAgIHRoaXMubGlua3Muc2V0KG5ld3BpZCwgbmV3IFNldCgpKTtcblxuICAgIGlmIChsaW5rZWQpIHtcbiAgICAgIHRoaXMubGluayhuZXdwaWQpO1xuICAgIH1cblxuICAgIHJldHVybiBuZXdwcm9jO1xuICB9XG5cbiAgcmVtb3ZlX3Byb2MocGlkKSB7XG4gICAgdGhpcy5waWRzLmRlbGV0ZShwaWQpO1xuICAgIHRoaXMudW5yZWdpc3RlcihwaWQpO1xuXG4gICAgaWYgKHRoaXMubGlua3MuaGFzKHBpZCkpIHtcbiAgICAgIGZvciAobGV0IGxpbmtwaWQgb2YgdGhpcy5saW5rcy5nZXQocGlkKSkge1xuICAgICAgICB0aGlzLmxpbmtzLmdldChsaW5rcGlkKS5kZWxldGUocGlkKTtcbiAgICAgIH1cblxuICAgICAgdGhpcy5saW5rcy5kZWxldGUocGlkKTtcbiAgICB9XG4gIH1cblxuICBleGl0KGlkKSB7XG4gICAgbGV0IHBpZCA9IHRoaXMucGlkb2YoaWQpO1xuICAgIHRoaXMucmVtb3ZlX3Byb2MoaWQpO1xuICB9XG5cbiAgcmVnaXN0ZXIobmFtZSwgcGlkKSB7XG4gICAgaWYgKCF0aGlzLm5hbWVzLmhhcyhuYW1lKSkge1xuICAgICAgdGhpcy5uYW1lcy5zZXQobmFtZSwgcGlkKTtcbiAgICAgIHJldHVybiBuYW1lO1xuICAgIH0gZWxzZSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoXCJOYW1lIGlzIGFscmVhZHkgcmVnaXN0ZXJlZCB0byBhbm90aGVyIHByb2Nlc3NcIik7XG4gICAgfVxuICB9XG5cbiAgcmVnaXN0ZXJlZChuYW1lKSB7XG4gICAgcmV0dXJuIHRoaXMubmFtZXMuaGFzKG5hbWUpID8gdGhpcy5uYW1lcy5nZXQobmFtZSkgOiBudWxsO1xuICB9XG5cbiAgdW5yZWdpc3RlcihwaWQpIHtcbiAgICBmb3IgKGxldCBuYW1lIG9mIHRoaXMubmFtZXMua2V5cygpKSB7XG4gICAgICBpZiAodGhpcy5uYW1lcy5oYXMobmFtZSkgJiYgdGhpcy5uYW1lcy5nZXQobmFtZSkgPT09IHBpZCkge1xuICAgICAgICB0aGlzLm5hbWVzLmRlbGV0ZShuYW1lKTtcbiAgICAgIH1cbiAgICB9XG4gIH1cblxuICBwaWQoKSB7XG4gICAgcmV0dXJuIHRoaXMuY3VycmVudF9wcm9jZXNzLnBpZDtcbiAgfVxuXG4gIHBpZG9mKGlkKSB7XG4gICAgaWYgKGlkIGluc3RhbmNlb2YgUElEKSB7XG4gICAgICByZXR1cm4gdGhpcy5waWRzLmhhcyhpZCkgPyBpZCA6IG51bGw7XG4gICAgfSBlbHNlIGlmIChpZCBpbnN0YW5jZW9mIFByb2Nlc3MpIHtcbiAgICAgIHJldHVybiBpZC5waWQ7XG4gICAgfSBlbHNlIHtcbiAgICAgIGxldCBwaWQgPSB0aGlzLnJlZ2lzdGVyZWQoaWQpO1xuICAgICAgaWYgKHBpZCA9PT0gbnVsbCkgdGhyb3cgXCJQcm9jZXNzIG5hbWUgbm90IHJlZ2lzdGVyZWQ6IFwiICsgaWQgKyBcIiAoXCIgKyB0eXBlb2YgaWQgKyBcIilcIjtcbiAgICAgIHJldHVybiBwaWQ7XG4gICAgfVxuICB9XG5cbiAgcHV0KGlkLCBrZXksIHZhbHVlKSB7XG4gICAgbGV0IHBpZCA9IHRoaXMucGlkb2YoaWQpO1xuICAgIGxldCBwcm9jZXNzID0gdGhpcy5waWRzLmdldChwaWQpO1xuICAgIHByb2Nlc3MuZGljdFtrZXldID0gdmFsdWU7XG4gIH1cblxuICBnZXQoaWQsIGtleSkge1xuICAgIGxldCBwaWQgPSB0aGlzLnBpZG9mKGlkKTtcbiAgICBsZXQgcHJvY2VzcyA9IHRoaXMucGlkcy5nZXQocGlkKTtcblxuICAgIGlmIChrZXkgIT0gbnVsbCkge1xuICAgICAgcmV0dXJuIHByb2Nlc3MuZGljdFtrZXldO1xuICAgIH0gZWxzZSB7XG4gICAgICByZXR1cm4gcHJvY2Vzcy5kaWN0O1xuICAgIH1cbiAgfVxuXG4gIGdldF9rZXlzKGlkKSB7XG4gICAgbGV0IHBpZCA9IHRoaXMucGlkb2YoaWQpO1xuICAgIGxldCBwcm9jZXNzID0gdGhpcy5waWRzLmdldChwaWQpO1xuXG4gICAgcmV0dXJuIE9iamVjdC5rZXlzKHByb2Nlc3MuZGljdCk7XG4gIH1cblxuICBlcmFzZShpZCwga2V5KSB7XG4gICAgbGV0IHBpZCA9IHRoaXMucGlkb2YoaWQpO1xuICAgIGxldCBwcm9jZXNzID0gdGhpcy5waWRzLmdldChwaWQpO1xuXG4gICAgaWYgKGtleSAhPSBudWxsKSB7XG4gICAgICBkZWxldGUgcHJvY2Vzcy5kaWN0W2tleV07XG4gICAgfSBlbHNlIHtcbiAgICAgIHByb2Nlc3MuZGljdCA9IHt9O1xuICAgIH1cbiAgfVxufVxuXG52YXIgQyA9IE9iamVjdC5mcmVlemUoe1xuXHRQcm9jZXNzU3lzdGVtOiBQcm9jZXNzU3lzdGVtLFxuXHRUdXBsZTogVHVwbGUkMSxcblx0UElEOiBQSUQsXG5cdEJpdFN0cmluZzogQml0U3RyaW5nLFxuXHRQYXR0ZXJuczogUGF0dGVybnMsXG5cdEludGVnZXJUeXBlOiBJbnRlZ2VyVHlwZSxcblx0RmxvYXRUeXBlOiBGbG9hdFR5cGUsXG5cdGNhbGxfcHJvcGVydHk6IGNhbGxfcHJvcGVydHlcbn0pO1xuXG5sZXQgRW51bSA9IHtcblxuICBhbGxfX3FtYXJrX186IGZ1bmN0aW9uIChjb2xsZWN0aW9uLCBmdW4gPSB4ID0+IHgpIHtcbiAgICBmb3IgKGxldCBlbGVtIG9mIGNvbGxlY3Rpb24pIHtcbiAgICAgIGlmICghZnVuKGVsZW0pKSB7XG4gICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICByZXR1cm4gdHJ1ZTtcbiAgfSxcblxuICBhbnlfX3FtYXJrX186IGZ1bmN0aW9uIChjb2xsZWN0aW9uLCBmdW4gPSB4ID0+IHgpIHtcbiAgICBmb3IgKGxldCBlbGVtIG9mIGNvbGxlY3Rpb24pIHtcbiAgICAgIGlmIChmdW4oZWxlbSkpIHtcbiAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICB9XG4gICAgfVxuXG4gICAgcmV0dXJuIGZhbHNlO1xuICB9LFxuXG4gIGF0OiBmdW5jdGlvbiAoY29sbGVjdGlvbiwgbiwgdGhlX2RlZmF1bHQgPSBudWxsKSB7XG4gICAgaWYgKG4gPiB0aGlzLmNvdW50KGNvbGxlY3Rpb24pIHx8IG4gPCAwKSB7XG4gICAgICByZXR1cm4gdGhlX2RlZmF1bHQ7XG4gICAgfVxuXG4gICAgcmV0dXJuIGNvbGxlY3Rpb25bbl07XG4gIH0sXG5cbiAgY29uY2F0OiBmdW5jdGlvbiAoLi4uZW51bWFibGVzKSB7XG4gICAgcmV0dXJuIGVudW1hYmxlc1swXS5jb25jYXQoZW51bWFibGVzWzFdKTtcbiAgfSxcblxuICBjb3VudDogZnVuY3Rpb24gKGNvbGxlY3Rpb24sIGZ1biA9IG51bGwpIHtcbiAgICBpZiAoZnVuID09IG51bGwpIHtcbiAgICAgIHJldHVybiBjb2xsZWN0aW9uLmxlbmd0aDtcbiAgICB9IGVsc2Uge1xuICAgICAgcmV0dXJuIGNvbGxlY3Rpb24uZmlsdGVyKGZ1bikubGVuZ3RoO1xuICAgIH1cbiAgfSxcblxuICBkcm9wOiBmdW5jdGlvbiAoY29sbGVjdGlvbiwgY291bnQpIHtcbiAgICByZXR1cm4gY29sbGVjdGlvbi5zbGljZShjb3VudCk7XG4gIH0sXG5cbiAgZHJvcF93aGlsZTogZnVuY3Rpb24gKGNvbGxlY3Rpb24sIGZ1bikge1xuICAgIGxldCBjb3VudCA9IDA7XG5cbiAgICBmb3IgKGxldCBlbGVtIG9mIGNvbGxlY3Rpb24pIHtcbiAgICAgIGlmIChmdW4oZWxlbSkpIHtcbiAgICAgICAgY291bnQgPSBjb3VudCArIDE7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBicmVhaztcbiAgICAgIH1cbiAgICB9XG5cbiAgICByZXR1cm4gY29sbGVjdGlvbi5zbGljZShjb3VudCk7XG4gIH0sXG5cbiAgZWFjaDogZnVuY3Rpb24gKGNvbGxlY3Rpb24sIGZ1bikge1xuICAgIGZvciAobGV0IGVsZW0gb2YgY29sbGVjdGlvbikge1xuICAgICAgZnVuKGVsZW0pO1xuICAgIH1cbiAgfSxcblxuICBlbXB0eV9fcW1hcmtfXzogZnVuY3Rpb24gKGNvbGxlY3Rpb24pIHtcbiAgICByZXR1cm4gY29sbGVjdGlvbi5sZW5ndGggPT09IDA7XG4gIH0sXG5cbiAgZmV0Y2g6IGZ1bmN0aW9uIChjb2xsZWN0aW9uLCBuKSB7XG4gICAgaWYgKEtlcm5lbC5pc19saXN0KGNvbGxlY3Rpb24pKSB7XG4gICAgICBpZiAobiA8IHRoaXMuY291bnQoY29sbGVjdGlvbikgJiYgbiA+PSAwKSB7XG4gICAgICAgIHJldHVybiBLZXJuZWwuU3BlY2lhbEZvcm1zLnR1cGxlKEtlcm5lbC5TcGVjaWFsRm9ybXMuYXRvbShcIm9rXCIpLCBjb2xsZWN0aW9uW25dKTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHJldHVybiBLZXJuZWwuU3BlY2lhbEZvcm1zLmF0b20oXCJlcnJvclwiKTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICB0aHJvdyBuZXcgRXJyb3IoXCJjb2xsZWN0aW9uIGlzIG5vdCBhbiBFbnVtZXJhYmxlXCIpO1xuICB9LFxuXG4gIGZldGNoX19lbWFya19fOiBmdW5jdGlvbiAoY29sbGVjdGlvbiwgbikge1xuICAgIGlmIChLZXJuZWwuaXNfbGlzdChjb2xsZWN0aW9uKSkge1xuICAgICAgaWYgKG4gPCB0aGlzLmNvdW50KGNvbGxlY3Rpb24pICYmIG4gPj0gMCkge1xuICAgICAgICByZXR1cm4gY29sbGVjdGlvbltuXTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcihcIm91dCBvZiBib3VuZHMgZXJyb3JcIik7XG4gICAgICB9XG4gICAgfVxuXG4gICAgdGhyb3cgbmV3IEVycm9yKFwiY29sbGVjdGlvbiBpcyBub3QgYW4gRW51bWVyYWJsZVwiKTtcbiAgfSxcblxuICBmaWx0ZXI6IGZ1bmN0aW9uIChjb2xsZWN0aW9uLCBmdW4pIHtcbiAgICBsZXQgcmVzdWx0ID0gW107XG5cbiAgICBmb3IgKGxldCBlbGVtIG9mIGNvbGxlY3Rpb24pIHtcbiAgICAgIGlmIChmdW4oZWxlbSkpIHtcbiAgICAgICAgcmVzdWx0LnB1c2goZWxlbSk7XG4gICAgICB9XG4gICAgfVxuXG4gICAgcmV0dXJuIHJlc3VsdDtcbiAgfSxcblxuICBmaWx0ZXJfbWFwOiBmdW5jdGlvbiAoY29sbGVjdGlvbiwgZmlsdGVyLCBtYXBwZXIpIHtcbiAgICByZXR1cm4gRW51bS5tYXAoRW51bS5maWx0ZXIoY29sbGVjdGlvbiwgZmlsdGVyKSwgbWFwcGVyKTtcbiAgfSxcblxuICBmaW5kOiBmdW5jdGlvbiAoY29sbGVjdGlvbiwgaWZfbm9uZSA9IG51bGwsIGZ1bikge1xuICAgIGZvciAobGV0IGVsZW0gb2YgY29sbGVjdGlvbikge1xuICAgICAgaWYgKGZ1bihlbGVtKSkge1xuICAgICAgICByZXR1cm4gZWxlbTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICByZXR1cm4gaWZfbm9uZTtcbiAgfSxcblxuICBpbnRvOiBmdW5jdGlvbiAoY29sbGVjdGlvbiwgbGlzdCkge1xuICAgIHJldHVybiBsaXN0LmNvbmNhdChjb2xsZWN0aW9uKTtcbiAgfSxcblxuICBtYXA6IGZ1bmN0aW9uIChjb2xsZWN0aW9uLCBmdW4pIHtcbiAgICBsZXQgcmVzdWx0ID0gW107XG5cbiAgICBmb3IgKGxldCBlbGVtIG9mIGNvbGxlY3Rpb24pIHtcbiAgICAgIHJlc3VsdC5wdXNoKGZ1bihlbGVtKSk7XG4gICAgfVxuXG4gICAgcmV0dXJuIHJlc3VsdDtcbiAgfSxcblxuICBtYXBfcmVkdWNlOiBmdW5jdGlvbiAoY29sbGVjdGlvbiwgYWNjLCBmdW4pIHtcbiAgICBsZXQgbWFwcGVkID0gS2VybmVsLlNwZWNpYWxGb3Jtcy5saXN0KCk7XG4gICAgbGV0IHRoZV9hY2MgPSBhY2M7XG5cbiAgICBmb3IgKHZhciBpID0gMDsgaSA8IHRoaXMuY291bnQoY29sbGVjdGlvbik7IGkrKykge1xuICAgICAgbGV0IHR1cGxlID0gZnVuKGNvbGxlY3Rpb25baV0sIHRoZV9hY2MpO1xuXG4gICAgICB0aGVfYWNjID0gS2VybmVsLmVsZW0odHVwbGUsIDEpO1xuICAgICAgbWFwcGVkID0gS2VybmVsLlNwZWNpYWxGb3Jtcy5saXN0KC4uLm1hcHBlZC5jb25jYXQoW0tlcm5lbC5lbGVtKHR1cGxlLCAwKV0pKTtcbiAgICB9XG5cbiAgICByZXR1cm4gS2VybmVsLlNwZWNpYWxGb3Jtcy50dXBsZShtYXBwZWQsIHRoZV9hY2MpO1xuICB9LFxuXG4gIG1lbWJlcjogZnVuY3Rpb24gKGNvbGxlY3Rpb24sIHZhbHVlKSB7XG4gICAgcmV0dXJuIGNvbGxlY3Rpb24uaW5jbHVkZXModmFsdWUpO1xuICB9LFxuXG4gIHJlZHVjZTogZnVuY3Rpb24gKGNvbGxlY3Rpb24sIGFjYywgZnVuKSB7XG4gICAgbGV0IHRoZV9hY2MgPSBhY2M7XG5cbiAgICBmb3IgKHZhciBpID0gMDsgaSA8IHRoaXMuY291bnQoY29sbGVjdGlvbik7IGkrKykge1xuICAgICAgbGV0IHR1cGxlID0gZnVuKGNvbGxlY3Rpb25baV0sIHRoZV9hY2MpO1xuXG4gICAgICB0aGVfYWNjID0gS2VybmVsLmVsZW0odHVwbGUsIDEpO1xuICAgIH1cblxuICAgIHJldHVybiB0aGVfYWNjO1xuICB9LFxuXG4gIHRha2U6IGZ1bmN0aW9uIChjb2xsZWN0aW9uLCBjb3VudCkge1xuICAgIHJldHVybiBjb2xsZWN0aW9uLnNsaWNlKDAsIGNvdW50KTtcbiAgfSxcblxuICB0YWtlX2V2ZXJ5OiBmdW5jdGlvbiAoY29sbGVjdGlvbiwgbnRoKSB7XG4gICAgbGV0IHJlc3VsdCA9IFtdO1xuICAgIGxldCBpbmRleCA9IDA7XG5cbiAgICBmb3IgKGxldCBlbGVtIG9mIGNvbGxlY3Rpb24pIHtcbiAgICAgIGlmIChpbmRleCAlIG50aCA9PT0gMCkge1xuICAgICAgICByZXN1bHQucHVzaChlbGVtKTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICByZXR1cm4gS2VybmVsLlNwZWNpYWxGb3Jtcy5saXN0KC4uLnJlc3VsdCk7XG4gIH0sXG5cbiAgdGFrZV93aGlsZTogZnVuY3Rpb24gKGNvbGxlY3Rpb24sIGZ1bikge1xuICAgIGxldCBjb3VudCA9IDA7XG5cbiAgICBmb3IgKGxldCBlbGVtIG9mIGNvbGxlY3Rpb24pIHtcbiAgICAgIGlmIChmdW4oZWxlbSkpIHtcbiAgICAgICAgY291bnQgPSBjb3VudCArIDE7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBicmVhaztcbiAgICAgIH1cbiAgICB9XG5cbiAgICByZXR1cm4gY29sbGVjdGlvbi5zbGljZSgwLCBjb3VudCk7XG4gIH0sXG5cbiAgdG9fbGlzdDogZnVuY3Rpb24gKGNvbGxlY3Rpb24pIHtcbiAgICByZXR1cm4gY29sbGVjdGlvbjtcbiAgfVxufTtcblxubGV0IFNwZWNpYWxGb3JtcyA9IHtcblxuICBfX0RJUl9fOiBmdW5jdGlvbiAoKSB7XG4gICAgaWYgKF9fZGlybmFtZSkge1xuICAgICAgcmV0dXJuIF9fZGlybmFtZTtcbiAgICB9XG5cbiAgICBpZiAoZG9jdW1lbnQuY3VycmVudFNjcmlwdCkge1xuICAgICAgcmV0dXJuIGRvY3VtZW50LmN1cnJlbnRTY3JpcHQuc3JjO1xuICAgIH1cblxuICAgIHJldHVybiBudWxsO1xuICB9LFxuXG4gIGF0b206IGZ1bmN0aW9uIChfdmFsdWUpIHtcbiAgICByZXR1cm4gU3ltYm9sLmZvcihfdmFsdWUpO1xuICB9LFxuXG4gIGxpc3Q6IGZ1bmN0aW9uICguLi5hcmdzKSB7XG4gICAgcmV0dXJuIE9iamVjdC5mcmVlemUoYXJncyk7XG4gIH0sXG5cbiAgYml0c3RyaW5nOiBmdW5jdGlvbiAoLi4uYXJncykge1xuICAgIHJldHVybiBuZXcgQml0U3RyaW5nKC4uLmFyZ3MpO1xuICB9LFxuXG4gIGJvdW5kOiBmdW5jdGlvbiAoX3Zhcikge1xuICAgIHJldHVybiBQYXR0ZXJucy5ib3VuZChfdmFyKTtcbiAgfSxcblxuICBfY2FzZTogZnVuY3Rpb24gKGNvbmRpdGlvbiwgY2xhdXNlcykge1xuICAgIHJldHVybiBQYXR0ZXJucy5kZWZtYXRjaCguLi5jbGF1c2VzKShjb25kaXRpb24pO1xuICB9LFxuXG4gIGNvbmQ6IGZ1bmN0aW9uIChjbGF1c2VzKSB7XG4gICAgZm9yIChsZXQgY2xhdXNlIG9mIGNsYXVzZXMpIHtcbiAgICAgIGlmIChjbGF1c2VbMF0pIHtcbiAgICAgICAgcmV0dXJuIGNsYXVzZVsxXSgpO1xuICAgICAgfVxuICAgIH1cblxuICAgIHRocm93IG5ldyBFcnJvcigpO1xuICB9LFxuXG4gIGZuOiBmdW5jdGlvbiAoY2xhdXNlcykge1xuICAgIHJldHVybiBQYXR0ZXJucy5kZWZtYXRjaChjbGF1c2VzKTtcbiAgfSxcblxuICBtYXA6IGZ1bmN0aW9uIChvYmopIHtcbiAgICByZXR1cm4gT2JqZWN0LmZyZWV6ZShvYmopO1xuICB9LFxuXG4gIG1hcF91cGRhdGU6IGZ1bmN0aW9uIChtYXAsIHZhbHVlcykge1xuICAgIHJldHVybiBPYmplY3QuZnJlZXplKE9iamVjdC5hc3NpZ24oT2JqZWN0LmNyZWF0ZShtYXAuY29uc3RydWN0b3IucHJvdG90eXBlKSwgbWFwLCB2YWx1ZXMpKTtcbiAgfSxcblxuICBfZm9yOiBmdW5jdGlvbiAoY29sbGVjdGlvbnMsIGZ1biwgZmlsdGVyID0gKCkgPT4gdHJ1ZSwgaW50byA9IFtdLCBwcmV2aW91c1ZhbHVlcyA9IFtdKSB7XG4gICAgbGV0IHBhdHRlcm4gPSBjb2xsZWN0aW9uc1swXVswXTtcbiAgICBsZXQgY29sbGVjdGlvbiA9IGNvbGxlY3Rpb25zWzBdWzFdO1xuXG4gICAgaWYgKGNvbGxlY3Rpb25zLmxlbmd0aCA9PT0gMSkge1xuXG4gICAgICBmb3IgKGxldCBlbGVtIG9mIGNvbGxlY3Rpb24pIHtcbiAgICAgICAgbGV0IHIgPSBQYXR0ZXJucy5tYXRjaF9ub190aHJvdyhwYXR0ZXJuLCBlbGVtKTtcbiAgICAgICAgbGV0IGFyZ3MgPSBwcmV2aW91c1ZhbHVlcy5jb25jYXQocik7XG5cbiAgICAgICAgaWYgKHIgJiYgZmlsdGVyLmFwcGx5KHRoaXMsIGFyZ3MpKSB7XG4gICAgICAgICAgaW50byA9IEVudW0uaW50byhbZnVuLmFwcGx5KHRoaXMsIGFyZ3MpXSwgaW50byk7XG4gICAgICAgIH1cbiAgICAgIH1cblxuICAgICAgcmV0dXJuIGludG87XG4gICAgfSBlbHNlIHtcbiAgICAgIGxldCBfaW50byA9IFtdO1xuXG4gICAgICBmb3IgKGxldCBlbGVtIG9mIGNvbGxlY3Rpb24pIHtcbiAgICAgICAgbGV0IHIgPSBQYXR0ZXJucy5tYXRjaF9ub190aHJvdyhwYXR0ZXJuLCBlbGVtKTtcbiAgICAgICAgaWYgKHIpIHtcbiAgICAgICAgICBfaW50byA9IEVudW0uaW50byh0aGlzLl9mb3IoY29sbGVjdGlvbnMuc2xpY2UoMSksIGZ1biwgZmlsdGVyLCBfaW50bywgcHJldmlvdXNWYWx1ZXMuY29uY2F0KHIpKSwgaW50byk7XG4gICAgICAgIH1cbiAgICAgIH1cblxuICAgICAgcmV0dXJuIF9pbnRvO1xuICAgIH1cbiAgfSxcblxuICByZWNlaXZlOiBmdW5jdGlvbiAocmVjZWl2ZV9mdW4sIHRpbWVvdXRfaW5fbXMgPSBudWxsLCB0aW1lb3V0X2ZuID0gdGltZSA9PiB0cnVlKSB7XG4gICAgaWYgKHRpbWVvdXRfaW5fbXMgPT0gbnVsbCB8fCB0aW1lb3V0X2luX21zID09PSBTeXN0ZW0uZm9yKCdpbmZpbml0eScpKSB7XG4gICAgICB3aGlsZSAodHJ1ZSkge1xuICAgICAgICBpZiAoc2VsZi5tYWlsYm94Lmxlbmd0aCAhPT0gMCkge1xuICAgICAgICAgIGxldCBtZXNzYWdlID0gc2VsZi5tYWlsYm94WzBdO1xuICAgICAgICAgIHNlbGYubWFpbGJveCA9IHNlbGYubWFpbGJveC5zbGljZSgxKTtcbiAgICAgICAgICByZXR1cm4gcmVjZWl2ZV9mdW4obWVzc2FnZSk7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9IGVsc2UgaWYgKHRpbWVvdXRfaW5fbXMgPT09IDApIHtcbiAgICAgIGlmIChzZWxmLm1haWxib3gubGVuZ3RoICE9PSAwKSB7XG4gICAgICAgIGxldCBtZXNzYWdlID0gc2VsZi5tYWlsYm94WzBdO1xuICAgICAgICBzZWxmLm1haWxib3ggPSBzZWxmLm1haWxib3guc2xpY2UoMSk7XG4gICAgICAgIHJldHVybiByZWNlaXZlX2Z1bihtZXNzYWdlKTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHJldHVybiBudWxsO1xuICAgICAgfVxuICAgIH0gZWxzZSB7XG4gICAgICBsZXQgbm93ID0gRGF0ZS5ub3coKTtcbiAgICAgIHdoaWxlIChEYXRlLm5vdygpIDwgbm93ICsgdGltZW91dF9pbl9tcykge1xuICAgICAgICBpZiAoc2VsZi5tYWlsYm94Lmxlbmd0aCAhPT0gMCkge1xuICAgICAgICAgIGxldCBtZXNzYWdlID0gc2VsZi5tYWlsYm94WzBdO1xuICAgICAgICAgIHNlbGYubWFpbGJveCA9IHNlbGYubWFpbGJveC5zbGljZSgxKTtcbiAgICAgICAgICByZXR1cm4gcmVjZWl2ZV9mdW4obWVzc2FnZSk7XG4gICAgICAgIH1cbiAgICAgIH1cblxuICAgICAgcmV0dXJuIHRpbWVvdXRfZm4odGltZW91dF9pbl9tcyk7XG4gICAgfVxuICB9LFxuXG4gIHR1cGxlOiBmdW5jdGlvbiAoLi4uYXJncykge1xuICAgIHJldHVybiBuZXcgVHVwbGUkMSguLi5hcmdzKTtcbiAgfSxcblxuICBfdHJ5OiBmdW5jdGlvbiAoZG9fZnVuLCByZXNjdWVfZnVuY3Rpb24sIGNhdGNoX2Z1biwgZWxzZV9mdW5jdGlvbiwgYWZ0ZXJfZnVuY3Rpb24pIHtcbiAgICBsZXQgcmVzdWx0ID0gbnVsbDtcblxuICAgIHRyeSB7XG4gICAgICByZXN1bHQgPSBkb19mdW4oKTtcbiAgICB9IGNhdGNoIChlKSB7XG4gICAgICBsZXQgZXhfcmVzdWx0ID0gbnVsbDtcblxuICAgICAgaWYgKHJlc2N1ZV9mdW5jdGlvbikge1xuICAgICAgICB0cnkge1xuICAgICAgICAgIGV4X3Jlc3VsdCA9IHJlc2N1ZV9mdW5jdGlvbihlKTtcbiAgICAgICAgICByZXR1cm4gZXhfcmVzdWx0O1xuICAgICAgICB9IGNhdGNoIChleCkge1xuICAgICAgICAgIGlmIChleCBpbnN0YW5jZW9mIFBhdHRlcm5zLk1hdGNoRXJyb3IpIHtcbiAgICAgICAgICAgIHRocm93IGV4O1xuICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgfVxuXG4gICAgICBpZiAoY2F0Y2hfZnVuKSB7XG4gICAgICAgIHRyeSB7XG4gICAgICAgICAgZXhfcmVzdWx0ID0gY2F0Y2hfZnVuKGUpO1xuICAgICAgICAgIHJldHVybiBleF9yZXN1bHQ7XG4gICAgICAgIH0gY2F0Y2ggKGV4KSB7XG4gICAgICAgICAgaWYgKGV4IGluc3RhbmNlb2YgUGF0dGVybnMuTWF0Y2hFcnJvcikge1xuICAgICAgICAgICAgdGhyb3cgZXg7XG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICB9XG5cbiAgICAgIHRocm93IGU7XG4gICAgfSBmaW5hbGx5IHtcbiAgICAgIGlmIChhZnRlcl9mdW5jdGlvbikge1xuICAgICAgICBhZnRlcl9mdW5jdGlvbigpO1xuICAgICAgfVxuICAgIH1cblxuICAgIGlmIChlbHNlX2Z1bmN0aW9uKSB7XG4gICAgICB0cnkge1xuICAgICAgICByZXR1cm4gZWxzZV9mdW5jdGlvbihyZXN1bHQpO1xuICAgICAgfSBjYXRjaCAoZXgpIHtcbiAgICAgICAgaWYgKGV4IGluc3RhbmNlb2YgUGF0dGVybnMuTWF0Y2hFcnJvcikge1xuICAgICAgICAgIHRocm93IG5ldyBFcnJvcignTm8gTWF0Y2ggRm91bmQgaW4gRWxzZScpO1xuICAgICAgICB9XG5cbiAgICAgICAgdGhyb3cgZXg7XG4gICAgICB9XG4gICAgfSBlbHNlIHtcbiAgICAgIHJldHVybiByZXN1bHQ7XG4gICAgfVxuICB9XG5cbn07XG5cbmZ1bmN0aW9uIHRvX3N0cmluZyQxKHR1cGxlKSB7XG4gIHJldHVybiB0dXBsZS50b1N0cmluZygpO1xufTtcblxuZnVuY3Rpb24gZGVsZXRlX2F0KHR1cGxlLCBpbmRleCkge1xuICBsZXQgbmV3X2xpc3QgPSBbXTtcblxuICBmb3IgKHZhciBpID0gMDsgaSA8IHR1cGxlLmNvdW50KCk7IGkrKykge1xuICAgIGlmIChpICE9PSBpbmRleCkge1xuICAgICAgbmV3X2xpc3QucHVzaCh0dXBsZS5nZXQoaSkpO1xuICAgIH1cbiAgfVxuXG4gIHJldHVybiBLZXJuZWwuU3BlY2lhbEZvcm1zLnR1cGxlLmFwcGx5KG51bGwsIG5ld19saXN0KTtcbn07XG5cbmZ1bmN0aW9uIGR1cGxpY2F0ZShkYXRhLCBzaXplKSB7XG4gIGxldCBhcnJheSA9IFtdO1xuXG4gIGZvciAodmFyIGkgPSBzaXplIC0gMTsgaSA+PSAwOyBpLS0pIHtcbiAgICBhcnJheS5wdXNoKGRhdGEpO1xuICB9XG5cbiAgcmV0dXJuIEtlcm5lbC5TcGVjaWFsRm9ybXMudHVwbGUuYXBwbHkobnVsbCwgYXJyYXkpO1xufTtcblxuZnVuY3Rpb24gaW5zZXJ0X2F0KHR1cGxlLCBpbmRleCwgdGVybSkge1xuICBsZXQgbmV3X3R1cGxlID0gW107XG5cbiAgZm9yICh2YXIgaSA9IDA7IGkgPD0gdHVwbGUuY291bnQoKTsgaSsrKSB7XG4gICAgaWYgKGkgPT09IGluZGV4KSB7XG4gICAgICBuZXdfdHVwbGUucHVzaCh0ZXJtKTtcbiAgICAgIGkrKztcbiAgICAgIG5ld190dXBsZS5wdXNoKHR1cGxlLmdldChpKSk7XG4gICAgfSBlbHNlIHtcbiAgICAgIG5ld190dXBsZS5wdXNoKHR1cGxlLmdldChpKSk7XG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIEtlcm5lbC5TcGVjaWFsRm9ybXMudHVwbGUuYXBwbHkobnVsbCwgbmV3X3R1cGxlKTtcbn07XG5cbmZ1bmN0aW9uIGZyb21fbGlzdChsaXN0KSB7XG4gIHJldHVybiBLZXJuZWwuU3BlY2lhbEZvcm1zLnR1cGxlLmFwcGx5KG51bGwsIGxpc3QpO1xufTtcblxuZnVuY3Rpb24gdG9fbGlzdCh0dXBsZSkge1xuICBsZXQgbmV3X2xpc3QgPSBbXTtcblxuICBmb3IgKHZhciBpID0gMDsgaSA8IHR1cGxlLmNvdW50KCk7IGkrKykge1xuICAgIG5ld19saXN0LnB1c2godHVwbGUuZ2V0KGkpKTtcbiAgfVxuXG4gIHJldHVybiBLZXJuZWwuU3BlY2lhbEZvcm1zLmxpc3QoLi4ubmV3X2xpc3QpO1xufTtcblxudmFyIFR1cGxlID0ge1xuICB0b19zdHJpbmc6IHRvX3N0cmluZyQxLFxuICBkZWxldGVfYXQsXG4gIGR1cGxpY2F0ZSxcbiAgaW5zZXJ0X2F0LFxuICBmcm9tX2xpc3QsXG4gIHRvX2xpc3Rcbn07XG5cbi8vaHR0cHM6Ly9naXRodWIuY29tL2FpcnBvcnR5aC9wcm90b21vcnBoaXNtXG5jbGFzcyBQcm90b2NvbCB7XG4gIGNvbnN0cnVjdG9yKHNwZWMpIHtcbiAgICB0aGlzLnJlZ2lzdHJ5ID0gbmV3IE1hcCgpO1xuICAgIHRoaXMuZmFsbGJhY2sgPSBudWxsO1xuXG4gICAgZm9yIChsZXQgZnVuTmFtZSBpbiBzcGVjKSB7XG4gICAgICB0aGlzW2Z1bk5hbWVdID0gY3JlYXRlRnVuKGZ1bk5hbWUpLmJpbmQodGhpcyk7XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gY3JlYXRlRnVuKGZ1bk5hbWUpIHtcblxuICAgICAgcmV0dXJuIGZ1bmN0aW9uICguLi5hcmdzKSB7XG4gICAgICAgIGxldCB0aGluZyA9IGFyZ3NbMF07XG4gICAgICAgIGxldCBmdW4gPSBudWxsO1xuXG4gICAgICAgIGlmIChOdW1iZXIuaXNJbnRlZ2VyKHRoaW5nKSAmJiB0aGlzLmhhc0ltcGxlbWVudGF0aW9uKEludGVnZXJUeXBlKSkge1xuICAgICAgICAgIGZ1biA9IHRoaXMucmVnaXN0cnkuZ2V0KEludGVnZXJUeXBlKVtmdW5OYW1lXTtcbiAgICAgICAgfSBlbHNlIGlmICh0eXBlb2YgdGhpbmcgPT09IFwibnVtYmVyXCIgJiYgIU51bWJlci5pc0ludGVnZXIodGhpbmcpICYmIHRoaXMuaGFzSW1wbGVtZW50YXRpb24oRmxvYXRUeXBlKSkge1xuICAgICAgICAgIGZ1biA9IHRoaXMucmVnaXN0cnkuZ2V0KEZsb2F0VHlwZSlbZnVuTmFtZV07XG4gICAgICAgIH0gZWxzZSBpZiAodGhpcy5oYXNJbXBsZW1lbnRhdGlvbih0aGluZykpIHtcbiAgICAgICAgICBmdW4gPSB0aGlzLnJlZ2lzdHJ5LmdldCh0aGluZy5jb25zdHJ1Y3RvcilbZnVuTmFtZV07XG4gICAgICAgIH0gZWxzZSBpZiAodGhpcy5mYWxsYmFjaykge1xuICAgICAgICAgIGZ1biA9IHRoaXMuZmFsbGJhY2tbZnVuTmFtZV07XG4gICAgICAgIH1cblxuICAgICAgICBpZiAoZnVuICE9IG51bGwpIHtcbiAgICAgICAgICBsZXQgcmV0dmFsID0gZnVuLmFwcGx5KHRoaXMsIGFyZ3MpO1xuICAgICAgICAgIHJldHVybiByZXR2YWw7XG4gICAgICAgIH1cblxuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoXCJObyBpbXBsZW1lbnRhdGlvbiBmb3VuZCBmb3IgXCIgKyB0aGluZyk7XG4gICAgICB9O1xuICAgIH1cbiAgfVxuXG4gIGltcGxlbWVudGF0aW9uKHR5cGUsIGltcGxlbWVudGF0aW9uKSB7XG4gICAgaWYgKHR5cGUgPT09IG51bGwpIHtcbiAgICAgIHRoaXMuZmFsbGJhY2sgPSBpbXBsZW1lbnRhdGlvbjtcbiAgICB9IGVsc2Uge1xuICAgICAgdGhpcy5yZWdpc3RyeS5zZXQodHlwZSwgaW1wbGVtZW50YXRpb24pO1xuICAgIH1cbiAgfVxuXG4gIGhhc0ltcGxlbWVudGF0aW9uKHRoaW5nKSB7XG4gICAgcmV0dXJuIHRoaXMucmVnaXN0cnkuaGFzKHRoaW5nLmNvbnN0cnVjdG9yKTtcbiAgfVxufVxuXG5mdW5jdGlvbiB0bChsaXN0KSB7XG4gIHJldHVybiBTcGVjaWFsRm9ybXMubGlzdCguLi5saXN0LnNsaWNlKDEpKTtcbn1cblxuZnVuY3Rpb24gaGQobGlzdCkge1xuICByZXR1cm4gbGlzdFswXTtcbn1cblxuZnVuY3Rpb24gaXNfbmlsKHgpIHtcbiAgcmV0dXJuIHggPT09IG51bGw7XG59XG5cbmZ1bmN0aW9uIGlzX2F0b20oeCkge1xuICByZXR1cm4gdHlwZW9mIHggPT09ICdzeW1ib2wnO1xufVxuXG5mdW5jdGlvbiBpc19iaW5hcnkoeCkge1xuICByZXR1cm4gdHlwZW9mIHggPT09ICdzdHJpbmcnIHx8IHggaW5zdGFuY2VvZiBTdHJpbmc7XG59XG5cbmZ1bmN0aW9uIGlzX2Jvb2xlYW4oeCkge1xuICByZXR1cm4gdHlwZW9mIHggPT09ICdib29sZWFuJyB8fCB4IGluc3RhbmNlb2YgQm9vbGVhbjtcbn1cblxuZnVuY3Rpb24gaXNfZnVuY3Rpb24oeCwgYXJpdHkgPSAtMSkge1xuICByZXR1cm4gdHlwZW9mIHggPT09ICdmdW5jdGlvbicgfHwgeCBpbnN0YW5jZW9mIEZ1bmN0aW9uO1xufVxuXG5mdW5jdGlvbiBpc19mbG9hdCh4KSB7XG4gIHJldHVybiBpc19udW1iZXIoeCkgJiYgIU51bWJlci5pc0ludGVnZXIoeCk7XG59XG5cbmZ1bmN0aW9uIGlzX2ludGVnZXIoeCkge1xuICByZXR1cm4gTnVtYmVyLmlzSW50ZWdlcih4KTtcbn1cblxuZnVuY3Rpb24gaXNfbGlzdCh4KSB7XG4gIHJldHVybiB4IGluc3RhbmNlb2YgQXJyYXk7XG59XG5cbmZ1bmN0aW9uIGlzX21hcCh4KSB7XG4gIHJldHVybiB0eXBlb2YgeCA9PT0gJ29iamVjdCcgfHwgeCBpbnN0YW5jZW9mIE9iamVjdDtcbn1cblxuZnVuY3Rpb24gaXNfbnVtYmVyKHgpIHtcbiAgcmV0dXJuIHR5cGVvZiB4ID09PSAnbnVtYmVyJztcbn1cblxuZnVuY3Rpb24gaXNfdHVwbGUoeCkge1xuICByZXR1cm4geCBpbnN0YW5jZW9mIFR1cGxlJDE7XG59XG5cbmZ1bmN0aW9uIGxlbmd0aCh4KSB7XG4gIHJldHVybiB4Lmxlbmd0aDtcbn1cblxuZnVuY3Rpb24gaXNfcGlkKHgpIHtcbiAgcmV0dXJuIHggaW5zdGFuY2VvZiBQSUQ7XG59XG5cbmZ1bmN0aW9uIGlzX3BvcnQoeCkge1xuICByZXR1cm4gZmFsc2U7XG59XG5cbmZ1bmN0aW9uIGlzX3JlZmVyZW5jZSh4KSB7XG4gIHJldHVybiBmYWxzZTtcbn1cblxuZnVuY3Rpb24gaXNfYml0c3RyaW5nKHgpIHtcbiAgcmV0dXJuIGlzX2JpbmFyeSh4KSB8fCB4IGluc3RhbmNlb2YgQml0U3RyaW5nO1xufVxuXG5mdW5jdGlvbiBfX2luX18obGVmdCwgcmlnaHQpIHtcbiAgZm9yIChsZXQgeCBvZiByaWdodCkge1xuICAgIGlmIChtYXRjaF9fcW1hcmtfXyhsZWZ0LCB4KSkge1xuICAgICAgcmV0dXJuIHRydWU7XG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIGZhbHNlO1xufVxuXG5mdW5jdGlvbiBhYnMobnVtYmVyKSB7XG4gIHJldHVybiBNYXRoLmFicyhudW1iZXIpO1xufVxuXG5mdW5jdGlvbiByb3VuZChudW1iZXIpIHtcbiAgcmV0dXJuIE1hdGgucm91bmQobnVtYmVyKTtcbn1cblxuZnVuY3Rpb24gZWxlbSh0dXBsZSwgaW5kZXgpIHtcbiAgaWYgKGlzX2xpc3QodHVwbGUpKSB7XG4gICAgcmV0dXJuIHR1cGxlW2luZGV4XTtcbiAgfVxuXG4gIHJldHVybiB0dXBsZS5nZXQoaW5kZXgpO1xufVxuXG5mdW5jdGlvbiByZW0obGVmdCwgcmlnaHQpIHtcbiAgcmV0dXJuIGxlZnQgJSByaWdodDtcbn1cblxuZnVuY3Rpb24gZGl2KGxlZnQsIHJpZ2h0KSB7XG4gIHJldHVybiBsZWZ0IC8gcmlnaHQ7XG59XG5cbmZ1bmN0aW9uIGFuZChsZWZ0LCByaWdodCkge1xuICByZXR1cm4gbGVmdCAmJiByaWdodDtcbn1cblxuZnVuY3Rpb24gb3IobGVmdCwgcmlnaHQpIHtcbiAgcmV0dXJuIGxlZnQgfHwgcmlnaHQ7XG59XG5cbmZ1bmN0aW9uIG5vdChhcmcpIHtcbiAgcmV0dXJuICFhcmc7XG59XG5cbmZ1bmN0aW9uIGFwcGx5KC4uLmFyZ3MpIHtcbiAgaWYgKGFyZ3MubGVuZ3RoID09PSAzKSB7XG4gICAgbGV0IG1vZCA9IGFyZ3NbMF07XG4gICAgbGV0IGZ1bmMgPSBhcmdzWzFdO1xuICAgIGxldCBmdW5jX2FyZ3MgPSBhcmdzWzJdO1xuICAgIHJldHVybiBtb2RbZnVuY10uYXBwbHkobnVsbCwgZnVuY19hcmdzKTtcbiAgfSBlbHNlIHtcbiAgICBsZXQgZnVuYyA9IGFyZ3NbMF07XG4gICAgbGV0IGZ1bmNfYXJncyA9IGFyZ3NbMV07XG5cbiAgICByZXR1cm4gZnVuYy5hcHBseShudWxsLCBmdW5jX2FyZ3MpO1xuICB9XG59XG5cbmZ1bmN0aW9uIHRvX3N0cmluZyhhcmcpIHtcbiAgaWYgKGlzX3R1cGxlKGFyZykpIHtcbiAgICByZXR1cm4gVHVwbGUudG9fc3RyaW5nKGFyZyk7XG4gIH1cblxuICByZXR1cm4gYXJnLnRvU3RyaW5nKCk7XG59XG5cbmZ1bmN0aW9uIG1hdGNoX19xbWFya19fKHBhdHRlcm4sIGV4cHIsIGd1YXJkID0gKCkgPT4gdHJ1ZSkge1xuICByZXR1cm4gUGF0dGVybnMubWF0Y2hfbm9fdGhyb3cocGF0dGVybiwgZXhwciwgZ3VhcmQpICE9IG51bGw7XG59XG5cbmZ1bmN0aW9uIGRlZnN0cnVjdChkZWZhdWx0cykge1xuICByZXR1cm4gY2xhc3Mge1xuICAgIGNvbnN0cnVjdG9yKHVwZGF0ZSA9IHt9KSB7XG4gICAgICBsZXQgdGhlX3ZhbHVlcyA9IE9iamVjdC5hc3NpZ24oZGVmYXVsdHMsIHVwZGF0ZSk7XG4gICAgICBPYmplY3QuYXNzaWduKHRoaXMsIHRoZV92YWx1ZXMpO1xuICAgIH1cblxuICAgIHN0YXRpYyBjcmVhdGUodXBkYXRlcyA9IHt9KSB7XG4gICAgICBsZXQgeCA9IG5ldyB0aGlzKHVwZGF0ZXMpO1xuICAgICAgcmV0dXJuIE9iamVjdC5mcmVlemUoeCk7XG4gICAgfVxuICB9O1xufVxuXG5mdW5jdGlvbiBkZWZwcm90b2NvbChzcGVjKSB7XG4gIHJldHVybiBuZXcgUHJvdG9jb2woc3BlYyk7XG59XG5cbmZ1bmN0aW9uIGRlZmltcGwocHJvdG9jb2wsIHR5cGUsIGltcGwpIHtcbiAgcHJvdG9jb2wuaW1wbGVtZW50YXRpb24odHlwZSwgaW1wbCk7XG59XG5cbnZhciBLZXJuZWwgPSB7XG4gIFNwZWNpYWxGb3JtcyxcbiAgdGwsXG4gIGhkLFxuICBpc19uaWwsXG4gIGlzX2F0b20sXG4gIGlzX2JpbmFyeSxcbiAgaXNfYm9vbGVhbixcbiAgaXNfZnVuY3Rpb24sXG4gIGlzX2Zsb2F0LFxuICBpc19pbnRlZ2VyLFxuICBpc19saXN0LFxuICBpc19tYXAsXG4gIGlzX251bWJlcixcbiAgaXNfdHVwbGUsXG4gIGxlbmd0aCxcbiAgaXNfcGlkLFxuICBpc19wb3J0LFxuICBpc19yZWZlcmVuY2UsXG4gIGlzX2JpdHN0cmluZyxcbiAgaW46IF9faW5fXyxcbiAgYWJzLFxuICByb3VuZCxcbiAgZWxlbSxcbiAgcmVtLFxuICBkaXYsXG4gIGFuZCxcbiAgb3IsXG4gIG5vdCxcbiAgYXBwbHksXG4gIHRvX3N0cmluZyxcbiAgbWF0Y2hfX3FtYXJrX18sXG4gIGRlZnN0cnVjdCxcbiAgZGVmcHJvdG9jb2wsXG4gIGRlZmltcGxcbn07XG5cbmxldCBBdG9tID0ge307XG5cbkF0b20udG9fc3RyaW5nID0gZnVuY3Rpb24gKGF0b20pIHtcbiAgcmV0dXJuIFN5bWJvbC5rZXlGb3IoYXRvbSk7XG59O1xuXG5BdG9tLnRvX2NoYXJfbGlzdCA9IGZ1bmN0aW9uIChhdG9tKSB7XG4gIHJldHVybiBBdG9tLnRvX3N0cmluZyhhdG9tKS5zcGxpdCgnJyk7XG59O1xuXG5sZXQgSW50ZWdlciA9IHtcblxuICBpc19ldmVuOiBmdW5jdGlvbiAobikge1xuICAgIHJldHVybiBuICUgMiA9PT0gMDtcbiAgfSxcblxuICBpc19vZGQ6IGZ1bmN0aW9uIChuKSB7XG4gICAgcmV0dXJuIG4gJSAyICE9PSAwO1xuICB9LFxuXG4gIHBhcnNlOiBmdW5jdGlvbiAoYmluKSB7XG4gICAgbGV0IHJlc3VsdCA9IHBhcnNlSW50KGJpbik7XG5cbiAgICBpZiAoaXNOYU4ocmVzdWx0KSkge1xuICAgICAgcmV0dXJuIEtlcm5lbC5TcGVjaWFsRm9ybXMuYXRvbShcImVycm9yXCIpO1xuICAgIH1cblxuICAgIGxldCBpbmRleE9mRG90ID0gYmluLmluZGV4T2YoXCIuXCIpO1xuXG4gICAgaWYgKGluZGV4T2ZEb3QgPj0gMCkge1xuICAgICAgcmV0dXJuIEtlcm5lbC5TcGVjaWFsRm9ybXMudHVwbGUocmVzdWx0LCBiaW4uc3Vic3RyaW5nKGluZGV4T2ZEb3QpKTtcbiAgICB9XG5cbiAgICByZXR1cm4gS2VybmVsLlNwZWNpYWxGb3Jtcy50dXBsZShyZXN1bHQsIFwiXCIpO1xuICB9LFxuXG4gIHRvX2NoYXJfbGlzdDogZnVuY3Rpb24gKG51bWJlciwgYmFzZSA9IDEwKSB7XG4gICAgcmV0dXJuIG51bWJlci50b1N0cmluZyhiYXNlKS5zcGxpdChcIlwiKTtcbiAgfSxcblxuICB0b19zdHJpbmc6IGZ1bmN0aW9uIChudW1iZXIsIGJhc2UgPSAxMCkge1xuICAgIHJldHVybiBudW1iZXIudG9TdHJpbmcoYmFzZSk7XG4gIH1cbn07XG5cbmxldCBDaGFycyQxID0gS2VybmVsLmRlZnByb3RvY29sKHtcbiAgdG9fc3RyaW5nOiBmdW5jdGlvbiAodGhpbmcpIHt9XG59KTtcblxuS2VybmVsLmRlZmltcGwoQ2hhcnMkMSwgQml0U3RyaW5nLCB7XG4gIHRvX3N0cmluZzogZnVuY3Rpb24gKHRoaW5nKSB7XG4gICAgaWYgKEtlcm5lbC5pc19iaW5hcnkodGhpbmcpKSB7XG4gICAgICByZXR1cm4gdGhpbmc7XG4gICAgfVxuXG4gICAgcmV0dXJuIHRoaW5nLnRvU3RyaW5nKCk7XG4gIH1cbn0pO1xuXG5LZXJuZWwuZGVmaW1wbChDaGFycyQxLCBTeW1ib2wsIHtcbiAgdG9fc3RyaW5nOiBmdW5jdGlvbiAodGhpbmcpIHtcbiAgICBpZiAobmlsKSB7XG4gICAgICByZXR1cm4gXCJcIjtcbiAgICB9XG5cbiAgICByZXR1cm4gQXRvbS50b19zdHJpbmcodGhpbmcpO1xuICB9XG59KTtcblxuS2VybmVsLmRlZmltcGwoQ2hhcnMkMSwgSW50ZWdlclR5cGUsIHtcbiAgdG9fc3RyaW5nOiBmdW5jdGlvbiAodGhpbmcpIHtcbiAgICByZXR1cm4gSW50ZWdlci50b19zdHJpbmcodGhpbmcpO1xuICB9XG59KTtcblxuS2VybmVsLmRlZmltcGwoQ2hhcnMkMSwgRmxvYXRUeXBlLCB7XG4gIHRvX3N0cmluZzogZnVuY3Rpb24gKHRoaW5nKSB7XG4gICAgcmV0dXJuIHRoaW5nLnRvU3RyaW5nO1xuICB9XG59KTtcblxuS2VybmVsLmRlZmltcGwoQ2hhcnMkMSwgQXJyYXksIHtcbiAgdG9fc3RyaW5nOiBmdW5jdGlvbiAodGhpbmcpIHtcbiAgICByZXR1cm4gdGhpbmcudG9TdHJpbmcoKTtcbiAgfVxufSk7XG5cbktlcm5lbC5kZWZpbXBsKENoYXJzJDEsIFR1cGxlJDEsIHtcbiAgdG9fc3RyaW5nOiBmdW5jdGlvbiAodGhpbmcpIHtcbiAgICByZXR1cm4gVHVwbGUudG9fc3RyaW5nKHRoaW5nKTtcbiAgfVxufSk7XG5cbktlcm5lbC5kZWZpbXBsKENoYXJzJDEsIG51bGwsIHtcbiAgdG9fc3RyaW5nOiBmdW5jdGlvbiAodGhpbmcpIHtcbiAgICByZXR1cm4gdGhpbmcudG9TdHJpbmcoKTtcbiAgfVxufSk7XG5cbmZ1bmN0aW9uIHRvX2F0b20oc3RyaW5nKSB7XG4gIHJldHVybiBTeW1ib2wuZm9yKHN0cmluZyk7XG59XG5cbmZ1bmN0aW9uIHRvX2V4aXN0aW5nX2F0b20oc3RyaW5nKSB7XG4gIHJldHVybiBTeW1ib2wuZm9yKHN0cmluZyk7XG59XG5cbmZ1bmN0aW9uIHRvX2NoYXJfbGlzdChzdHJpbmcpIHtcbiAgcmV0dXJuIHN0cmluZy5zcGxpdCgnJyk7XG59XG5cbmZ1bmN0aW9uIHRvX2Zsb2F0KHN0cmluZykge1xuICByZXR1cm4gcGFyc2VGbG9hdChzdHJpbmcpO1xufVxuXG5mdW5jdGlvbiB0b19pbnRlZ2VyKHN0cmluZywgYmFzZSA9IDEwKSB7XG4gIHJldHVybiBwYXJzZUludChzdHJpbmcsIGJhc2UpO1xufVxuXG5mdW5jdGlvbiB1cGNhc2UoYmluYXJ5KSB7XG4gIHJldHVybiBiaW5hcnkudG9VcHBlckNhc2UoKTtcbn1cblxuZnVuY3Rpb24gZG93bmNhc2UoYmluYXJ5KSB7XG4gIHJldHVybiBiaW5hcnkudG9Mb3dlckNhc2UoKTtcbn1cblxuZnVuY3Rpb24gYXQoc3RyaW5nLCBwb3NpdGlvbikge1xuICBpZiAocG9zaXRpb24gPiBzdHJpbmcubGVuZ3RoIC0gMSkge1xuICAgIHJldHVybiBudWxsO1xuICB9XG5cbiAgcmV0dXJuIHN0cmluZ1twb3NpdGlvbl07XG59XG5cbmZ1bmN0aW9uIGNhcGl0YWxpemUoc3RyaW5nKSB7XG4gIGxldCByZXR1cm5TdHJpbmcgPSAnJztcblxuICBmb3IgKGxldCBpID0gMDsgaSA8IHN0cmluZy5sZW5ndGg7IGkrKykge1xuICAgIGlmIChpID09PSAwKSB7XG4gICAgICByZXR1cm5TdHJpbmcgPSByZXR1cm5TdHJpbmcgKyBzdHJpbmdbaV0udG9VcHBlckNhc2UoKTtcbiAgICB9IGVsc2Uge1xuICAgICAgcmV0dXJuU3RyaW5nID0gcmV0dXJuU3RyaW5nICsgc3RyaW5nW2ldLnRvTG93ZXJDYXNlKCk7XG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIHJldHVyblN0cmluZztcbn1cblxuZnVuY3Rpb24gY29kZXBvaW50cyhzdHJpbmcpIHtcbiAgcmV0dXJuIHRvX2NoYXJfbGlzdChzdHJpbmcpLm1hcChmdW5jdGlvbiAoYykge1xuICAgIHJldHVybiBjLmNvZGVQb2ludEF0KDApO1xuICB9KTtcbn1cblxuZnVuY3Rpb24gY29udGFpbnNfX3FtX18oc3RyaW5nLCBjb250YWlucykge1xuICBpZiAoQXJyYXkuaXNBcnJheShjb250YWlucykpIHtcbiAgICByZXR1cm4gY29udGFpbnMuc29tZShmdW5jdGlvbiAocykge1xuICAgICAgcmV0dXJuIHN0cmluZy5pbmRleE9mKHMpID4gLTE7XG4gICAgfSk7XG4gIH1cblxuICByZXR1cm4gc3RyaW5nLmluZGV4T2YoY29udGFpbnMpID4gLTE7XG59XG5cbmZ1bmN0aW9uIGR1cGxpY2F0ZSQxKHN1YmplY3QsIG4pIHtcbiAgcmV0dXJuIHN1YmplY3QucmVwZWF0KG4pO1xufVxuXG5mdW5jdGlvbiBlbmRzX3dpdGhfX3FtX18oc3RyaW5nLCBzdWZmaXhlcykge1xuICBpZiAoQXJyYXkuaXNBcnJheShzdWZmaXhlcykpIHtcbiAgICByZXR1cm4gc3VmZml4ZXMuc29tZShmdW5jdGlvbiAocykge1xuICAgICAgcmV0dXJuIHN0cmluZy5lbmRzV2l0aChzKTtcbiAgICB9KTtcbiAgfVxuXG4gIHJldHVybiBzdHJpbmcuZW5kc1dpdGgoc3VmZml4ZXMpO1xufVxuXG5mdW5jdGlvbiBmaXJzdChzdHJpbmcpIHtcbiAgaWYgKCFzdHJpbmcpIHtcbiAgICByZXR1cm4gbnVsbDtcbiAgfVxuXG4gIHJldHVybiBzdHJpbmdbMF07XG59XG5cbmZ1bmN0aW9uIGdyYXBoZW1lcyhzdHJpbmcpIHtcbiAgcmV0dXJuIHN0cmluZy5zcGxpdCgnJyk7XG59XG5cbmZ1bmN0aW9uIGxhc3Qoc3RyaW5nKSB7XG4gIGlmICghc3RyaW5nKSB7XG4gICAgcmV0dXJuIG51bGw7XG4gIH1cblxuICByZXR1cm4gc3RyaW5nW3N0cmluZy5sZW5ndGggLSAxXTtcbn1cblxuZnVuY3Rpb24gbGVuZ3RoJDEoc3RyaW5nKSB7XG4gIHJldHVybiBzdHJpbmcubGVuZ3RoO1xufVxuXG5mdW5jdGlvbiBtYXRjaF9fcW1fXyhzdHJpbmcsIHJlZ2V4KSB7XG4gIHJldHVybiBzdHJpbmcubWF0Y2gocmVnZXgpICE9IG51bGw7XG59XG5cbmZ1bmN0aW9uIG5leHRfY29kZXBvaW50KHN0cmluZykge1xuICBpZiAoIXN0cmluZyB8fCBzdHJpbmcgPT09ICcnKSB7XG4gICAgcmV0dXJuIG51bGw7XG4gIH1cblxuICByZXR1cm4gS2VybmVsLlNwZWNpYWxGb3Jtcy50dXBsZShzdHJpbmdbMF0uY29kZVBvaW50QXQoMCksIHN0cmluZy5zdWJzdHIoMSkpO1xufVxuXG5mdW5jdGlvbiBuZXh0X2dyYXBoZW1lKHN0cmluZykge1xuICBpZiAoIXN0cmluZyB8fCBzdHJpbmcgPT09ICcnKSB7XG4gICAgcmV0dXJuIG51bGw7XG4gIH1cblxuICByZXR1cm4gS2VybmVsLlNwZWNpYWxGb3Jtcy50dXBsZShzdHJpbmdbMF0sIHN0cmluZy5zdWJzdHIoMSkpO1xufVxuXG5mdW5jdGlvbiByZXZlcnNlKHN0cmluZykge1xuICBsZXQgcmV0dXJuVmFsdWUgPSAnJztcblxuICBmb3IgKHZhciBpID0gc3RyaW5nLmxlbmd0aCAtIDE7IGkgPj0gMDsgaS0tKSB7XG4gICAgcmV0dXJuVmFsdWUgPSByZXR1cm5WYWx1ZSArIHN0cmluZ1tpXTtcbiAgfTtcblxuICByZXR1cm4gcmV0dXJuVmFsdWU7XG59XG5cbmZ1bmN0aW9uIHNwbGl0KHN0cmluZykge1xuICByZXR1cm4gc3RyaW5nLnNwbGl0KCk7XG59XG5cbmZ1bmN0aW9uIHN0YXJ0c193aXRoX19xbV9fKHN0cmluZywgcHJlZml4ZXMpIHtcbiAgaWYgKEFycmF5LmlzQXJyYXkocHJlZml4ZXMpKSB7XG4gICAgcmV0dXJuIHByZWZpeGVzLnNvbWUoZnVuY3Rpb24gKHMpIHtcbiAgICAgIHJldHVybiBzdHJpbmcuc3RhcnRzV2l0aChzKTtcbiAgICB9KTtcbiAgfVxuXG4gIHJldHVybiBzdHJpbmcuc3RhcnRzV2l0aChwcmVmaXhlcyk7XG59XG5cbmZ1bmN0aW9uIHZhbGlkX2NoYXJhY3Rlcl9fcW1fXyhjb2RlcG9pbnQpIHtcbiAgdHJ5IHtcbiAgICByZXR1cm4gU3RyaW5nLmZyb21Db2RlUG9pbnQoY29kZXBvaW50KSAhPSBudWxsO1xuICB9IGNhdGNoIChlKSB7XG4gICAgcmV0dXJuIGZhbHNlO1xuICB9XG59XG5cbnZhciBTdHJpbmckMSA9IHtcbiAgYXQsXG4gIGNhcGl0YWxpemUsXG4gIGNvZGVwb2ludHMsXG4gIGNvbnRhaW5zX19xbV9fLFxuICBkb3duY2FzZSxcbiAgZHVwbGljYXRlOiBkdXBsaWNhdGUkMSxcbiAgZW5kc193aXRoX19xbV9fLFxuICBmaXJzdCxcbiAgZ3JhcGhlbWVzLFxuICBsYXN0LFxuICBsZW5ndGg6IGxlbmd0aCQxLFxuICBtYXRjaF9fcW1fXyxcbiAgbmV4dF9jb2RlcG9pbnQsXG4gIG5leHRfZ3JhcGhlbWUsXG4gIHJldmVyc2UsXG4gIHNwbGl0LFxuICBzdGFydHNfd2l0aF9fcW1fXyxcbiAgdG9fYXRvbSxcbiAgdG9fY2hhcl9saXN0LFxuICB0b19leGlzdGluZ19hdG9tLFxuICB0b19mbG9hdCxcbiAgdG9faW50ZWdlcixcbiAgdXBjYXNlLFxuICB2YWxpZF9jaGFyYWN0ZXJfX3FtX18sXG4gIENoYXJzOiBDaGFycyQxXG59O1xuXG5sZXQgQ2hhcnMgPSBLZXJuZWwuZGVmcHJvdG9jb2woe1xuICB0b19jaGFyX2xpc3Q6IGZ1bmN0aW9uICh0aGluZykge31cbn0pO1xuXG5LZXJuZWwuZGVmaW1wbChDaGFycywgQml0U3RyaW5nLCB7XG4gIHRvX2NoYXJfbGlzdDogZnVuY3Rpb24gKHRoaW5nKSB7XG4gICAgaWYgKEtlcm5lbC5pc19iaW5hcnkodGhpbmcpKSB7XG4gICAgICByZXR1cm4gU3RyaW5nJDEudG9fY2hhcl9saXN0KHRoaW5nKTtcbiAgICB9XG5cbiAgICByZXR1cm4gdGhpbmcudG9TdHJpbmcoKTtcbiAgfVxufSk7XG5cbktlcm5lbC5kZWZpbXBsKENoYXJzLCBTeW1ib2wsIHtcbiAgdG9fY2hhcl9saXN0OiBmdW5jdGlvbiAodGhpbmcpIHtcbiAgICByZXR1cm4gQXRvbS50b19jaGFyX2xpc3QodGhpbmcpO1xuICB9XG59KTtcblxuS2VybmVsLmRlZmltcGwoQ2hhcnMsIEludGVnZXJUeXBlLCB7XG4gIHRvX2NoYXJfbGlzdDogZnVuY3Rpb24gKHRoaW5nKSB7XG4gICAgcmV0dXJuIEludGVnZXIudG9fY2hhcl9saXN0KHRoaW5nKTtcbiAgfVxufSk7XG5cbktlcm5lbC5kZWZpbXBsKENoYXJzLCBBcnJheSwge1xuICB0b19jaGFyX2xpc3Q6IGZ1bmN0aW9uICh0aGluZykge1xuICAgIHJldHVybiB0aGluZztcbiAgfVxufSk7XG5cbmxldCBMaXN0ID0ge307XG5cbkxpc3QuQ2hhcnMgPSBDaGFycztcblxuTGlzdC5kZWxldGUgPSBmdW5jdGlvbiAobGlzdCwgaXRlbSkge1xuICBsZXQgbmV3X3ZhbHVlID0gW107XG4gIGxldCB2YWx1ZV9mb3VuZCA9IGZhbHNlO1xuXG4gIGZvciAobGV0IHggb2YgbGlzdCkge1xuICAgIGlmICh4ID09PSBpdGVtICYmIHZhbHVlX2ZvdW5kICE9PSBmYWxzZSkge1xuICAgICAgbmV3X3ZhbHVlLnB1c2goeCk7XG4gICAgICB2YWx1ZV9mb3VuZCA9IHRydWU7XG4gICAgfSBlbHNlIGlmICh4ICE9PSBpdGVtKSB7XG4gICAgICBuZXdfdmFsdWUucHVzaCh4KTtcbiAgICB9XG4gIH1cblxuICByZXR1cm4gS2VybmVsLlNwZWNpYWxGb3Jtcy5saXN0KC4uLm5ld192YWx1ZSk7XG59O1xuXG5MaXN0LmRlbGV0ZV9hdCA9IGZ1bmN0aW9uIChsaXN0LCBpbmRleCkge1xuICBsZXQgbmV3X3ZhbHVlID0gW107XG5cbiAgZm9yIChsZXQgaSA9IDA7IGkgPCBsaXN0Lmxlbmd0aDsgaSsrKSB7XG4gICAgaWYgKGkgIT09IGluZGV4KSB7XG4gICAgICBuZXdfdmFsdWUucHVzaChsaXN0W2ldKTtcbiAgICB9XG4gIH1cblxuICByZXR1cm4gS2VybmVsLlNwZWNpYWxGb3Jtcy5saXN0KC4uLm5ld192YWx1ZSk7XG59O1xuXG5MaXN0LmR1cGxpY2F0ZSA9IGZ1bmN0aW9uIChlbGVtLCBuKSB7XG4gIGxldCBuZXdfdmFsdWUgPSBbXTtcblxuICBmb3IgKHZhciBpID0gMDsgaSA8IG47IGkrKykge1xuICAgIG5ld192YWx1ZS5wdXNoKGVsZW0pO1xuICB9XG5cbiAgcmV0dXJuIEtlcm5lbC5TcGVjaWFsRm9ybXMubGlzdCguLi5uZXdfdmFsdWUpO1xufTtcblxuTGlzdC5maXJzdCA9IGZ1bmN0aW9uIChsaXN0KSB7XG4gIHJldHVybiBsaXN0WzBdO1xufTtcblxuTGlzdC5mbGF0dGVuID0gZnVuY3Rpb24gKGxpc3QsIHRhaWwgPSBLZXJuZWwuU3BlY2lhbEZvcm1zLmxpc3QoKSkge1xuICBsZXQgbmV3X3ZhbHVlID0gW107XG5cbiAgZm9yIChsZXQgeCBvZiBsaXN0KSB7XG4gICAgaWYgKEtlcm5lbC5pc19saXN0KHgpKSB7XG4gICAgICBuZXdfdmFsdWUgPSBuZXdfdmFsdWUuY29uY2F0KExpc3QuZmxhdHRlbih4KSk7XG4gICAgfSBlbHNlIHtcbiAgICAgIG5ld192YWx1ZS5wdXNoKHgpO1xuICAgIH1cbiAgfVxuXG4gIG5ld192YWx1ZSA9IG5ld192YWx1ZS5jb25jYXQodGFpbCk7XG5cbiAgcmV0dXJuIEtlcm5lbC5TcGVjaWFsRm9ybXMubGlzdCguLi5uZXdfdmFsdWUpO1xufTtcblxuTGlzdC5mb2xkbCA9IGZ1bmN0aW9uIChsaXN0LCBhY2MsIGZ1bmMpIHtcbiAgcmV0dXJuIGxpc3QucmVkdWNlKGZ1bmMsIGFjYyk7XG59O1xuXG5MaXN0LmZvbGRyID0gZnVuY3Rpb24gKGxpc3QsIGFjYywgZnVuYykge1xuICBsZXQgbmV3X2FjYyA9IGFjYztcblxuICBmb3IgKHZhciBpID0gbGlzdC5sZW5ndGggLSAxOyBpID49IDA7IGktLSkge1xuICAgIG5ld19hY2MgPSBmdW5jKGxpc3RbaV0sIG5ld19hY2MpO1xuICB9XG5cbiAgcmV0dXJuIG5ld19hY2M7XG59O1xuXG5MaXN0Lmluc2VydF9hdCA9IGZ1bmN0aW9uIChsaXN0LCBpbmRleCwgdmFsdWUpIHtcbiAgbGV0IG5ld192YWx1ZSA9IFtdO1xuXG4gIGZvciAobGV0IGkgPSAwOyBpIDwgbGlzdC5sZW5ndGg7IGkrKykge1xuICAgIGlmIChpID09PSBpbmRleCkge1xuICAgICAgbmV3X3ZhbHVlLnB1c2godmFsdWUpO1xuICAgICAgbmV3X3ZhbHVlLnB1c2gobGlzdFtpXSk7XG4gICAgfSBlbHNlIHtcbiAgICAgIG5ld192YWx1ZS5wdXNoKGxpc3RbaV0pO1xuICAgIH1cbiAgfVxuXG4gIHJldHVybiBLZXJuZWwuU3BlY2lhbEZvcm1zLmxpc3QoLi4ubmV3X3ZhbHVlKTtcbn07XG5cbkxpc3Qua2V5ZGVsZXRlID0gZnVuY3Rpb24gKGxpc3QsIGtleSwgcG9zaXRpb24pIHtcbiAgbGV0IG5ld19saXN0ID0gW107XG5cbiAgZm9yIChsZXQgaSA9IDA7IGkgPCBsaXN0Lmxlbmd0aDsgaSsrKSB7XG4gICAgaWYgKCFLZXJuZWwubWF0Y2hfX3FtYXJrX18obGlzdFtpXVtwb3NpdGlvbl0sIGtleSkpIHtcbiAgICAgIG5ld19saXN0LnB1c2gobGlzdFtpXSk7XG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIEtlcm5lbC5TcGVjaWFsRm9ybXMubGlzdCguLi5uZXdfbGlzdCk7XG59O1xuXG5MaXN0LmtleWZpbmQgPSBmdW5jdGlvbiAobGlzdCwga2V5LCBwb3NpdGlvbiwgX2RlZmF1bHQgPSBudWxsKSB7XG5cbiAgZm9yIChsZXQgaSA9IDA7IGkgPCBsaXN0Lmxlbmd0aDsgaSsrKSB7XG4gICAgaWYgKEtlcm5lbC5tYXRjaF9fcW1hcmtfXyhsaXN0W2ldW3Bvc2l0aW9uXSwga2V5KSkge1xuICAgICAgcmV0dXJuIGxpc3RbaV07XG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIF9kZWZhdWx0O1xufTtcblxuTGlzdC5rZXltZW1iZXJfX3FtYXJrX18gPSBmdW5jdGlvbiAobGlzdCwga2V5LCBwb3NpdGlvbikge1xuXG4gIGZvciAobGV0IGkgPSAwOyBpIDwgbGlzdC5sZW5ndGg7IGkrKykge1xuICAgIGlmIChLZXJuZWwubWF0Y2hfX3FtYXJrX18obGlzdFtpXVtwb3NpdGlvbl0sIGtleSkpIHtcbiAgICAgIHJldHVybiB0cnVlO1xuICAgIH1cbiAgfVxuXG4gIHJldHVybiBmYWxzZTtcbn07XG5cbkxpc3Qua2V5cmVwbGFjZSA9IGZ1bmN0aW9uIChsaXN0LCBrZXksIHBvc2l0aW9uLCBuZXdfdHVwbGUpIHtcbiAgbGV0IG5ld19saXN0ID0gW107XG5cbiAgZm9yIChsZXQgaSA9IDA7IGkgPCBsaXN0Lmxlbmd0aDsgaSsrKSB7XG4gICAgaWYgKCFLZXJuZWwubWF0Y2hfX3FtYXJrX18obGlzdFtpXVtwb3NpdGlvbl0sIGtleSkpIHtcbiAgICAgIG5ld19saXN0LnB1c2gobGlzdFtpXSk7XG4gICAgfSBlbHNlIHtcbiAgICAgIG5ld19saXN0LnB1c2gobmV3X3R1cGxlKTtcbiAgICB9XG4gIH1cblxuICByZXR1cm4gS2VybmVsLlNwZWNpYWxGb3Jtcy5saXN0KC4uLm5ld19saXN0KTtcbn07XG5cbkxpc3Qua2V5c29ydCA9IGZ1bmN0aW9uIChsaXN0LCBwb3NpdGlvbikge1xuICBsZXQgbmV3X2xpc3QgPSBsaXN0O1xuXG4gIG5ld19saXN0LnNvcnQoZnVuY3Rpb24gKGEsIGIpIHtcbiAgICBpZiAocG9zaXRpb24gPT09IDApIHtcbiAgICAgIGlmIChhW3Bvc2l0aW9uXS52YWx1ZSA8IGJbcG9zaXRpb25dLnZhbHVlKSB7XG4gICAgICAgIHJldHVybiAtMTtcbiAgICAgIH1cblxuICAgICAgaWYgKGFbcG9zaXRpb25dLnZhbHVlID4gYltwb3NpdGlvbl0udmFsdWUpIHtcbiAgICAgICAgcmV0dXJuIDE7XG4gICAgICB9XG5cbiAgICAgIHJldHVybiAwO1xuICAgIH0gZWxzZSB7XG4gICAgICBpZiAoYVtwb3NpdGlvbl0gPCBiW3Bvc2l0aW9uXSkge1xuICAgICAgICByZXR1cm4gLTE7XG4gICAgICB9XG5cbiAgICAgIGlmIChhW3Bvc2l0aW9uXSA+IGJbcG9zaXRpb25dKSB7XG4gICAgICAgIHJldHVybiAxO1xuICAgICAgfVxuXG4gICAgICByZXR1cm4gMDtcbiAgICB9XG4gIH0pO1xuXG4gIHJldHVybiBLZXJuZWwuU3BlY2lhbEZvcm1zLmxpc3QoLi4ubmV3X2xpc3QpO1xufTtcblxuTGlzdC5rZXlzdG9yZSA9IGZ1bmN0aW9uIChsaXN0LCBrZXksIHBvc2l0aW9uLCBuZXdfdHVwbGUpIHtcbiAgbGV0IG5ld19saXN0ID0gW107XG4gIGxldCByZXBsYWNlZCA9IGZhbHNlO1xuXG4gIGZvciAobGV0IGkgPSAwOyBpIDwgbGlzdC5sZW5ndGg7IGkrKykge1xuICAgIGlmICghS2VybmVsLm1hdGNoX19xbWFya19fKGxpc3RbaV1bcG9zaXRpb25dLCBrZXkpKSB7XG4gICAgICBuZXdfbGlzdC5wdXNoKGxpc3RbaV0pO1xuICAgIH0gZWxzZSB7XG4gICAgICBuZXdfbGlzdC5wdXNoKG5ld190dXBsZSk7XG4gICAgICByZXBsYWNlZCA9IHRydWU7XG4gICAgfVxuICB9XG5cbiAgaWYgKCFyZXBsYWNlZCkge1xuICAgIG5ld19saXN0LnB1c2gobmV3X3R1cGxlKTtcbiAgfVxuXG4gIHJldHVybiBLZXJuZWwuU3BlY2lhbEZvcm1zLmxpc3QoLi4ubmV3X2xpc3QpO1xufTtcblxuTGlzdC5sYXN0ID0gZnVuY3Rpb24gKGxpc3QpIHtcbiAgcmV0dXJuIGxpc3RbbGlzdC5sZW5ndGggLSAxXTtcbn07XG5cbkxpc3QucmVwbGFjZV9hdCA9IGZ1bmN0aW9uIChsaXN0LCBpbmRleCwgdmFsdWUpIHtcbiAgbGV0IG5ld192YWx1ZSA9IFtdO1xuXG4gIGZvciAobGV0IGkgPSAwOyBpIDwgbGlzdC5sZW5ndGg7IGkrKykge1xuICAgIGlmIChpID09PSBpbmRleCkge1xuICAgICAgbmV3X3ZhbHVlLnB1c2godmFsdWUpO1xuICAgIH0gZWxzZSB7XG4gICAgICBuZXdfdmFsdWUucHVzaChsaXN0W2ldKTtcbiAgICB9XG4gIH1cblxuICByZXR1cm4gS2VybmVsLlNwZWNpYWxGb3Jtcy5saXN0KC4uLm5ld192YWx1ZSk7XG59O1xuXG5MaXN0LnVwZGF0ZV9hdCA9IGZ1bmN0aW9uIChsaXN0LCBpbmRleCwgZnVuKSB7XG4gIGxldCBuZXdfdmFsdWUgPSBbXTtcblxuICBmb3IgKGxldCBpID0gMDsgaSA8IGxpc3QuY291bnQoKTsgaSsrKSB7XG4gICAgaWYgKGkgPT09IGluZGV4KSB7XG4gICAgICBuZXdfdmFsdWUucHVzaChmdW4obGlzdC5nZXQoaSkpKTtcbiAgICB9IGVsc2Uge1xuICAgICAgbmV3X3ZhbHVlLnB1c2gobGlzdC5nZXQoaSkpO1xuICAgIH1cbiAgfVxuXG4gIHJldHVybiBuZXdfdmFsdWU7XG59O1xuXG5MaXN0LndyYXAgPSBmdW5jdGlvbiAobGlzdCkge1xuICBpZiAoS2VybmVsLmlzX2xpc3QobGlzdCkpIHtcbiAgICByZXR1cm4gbGlzdDtcbiAgfSBlbHNlIGlmIChsaXN0ID09IG51bGwpIHtcbiAgICByZXR1cm4gS2VybmVsLlNwZWNpYWxGb3Jtcy5saXN0KCk7XG4gIH0gZWxzZSB7XG4gICAgcmV0dXJuIEtlcm5lbC5TcGVjaWFsRm9ybXMubGlzdChsaXN0KTtcbiAgfVxufTtcblxuTGlzdC56aXAgPSBmdW5jdGlvbiAobGlzdF9vZl9saXN0cykge1xuICBpZiAobGlzdF9vZl9saXN0cy5sZW5ndGggPT09IDApIHtcbiAgICByZXR1cm4gS2VybmVsLlNwZWNpYWxGb3Jtcy5saXN0KCk7XG4gIH1cblxuICBsZXQgbmV3X3ZhbHVlID0gW107XG4gIGxldCBzbWFsbGVzdF9sZW5ndGggPSBsaXN0X29mX2xpc3RzWzBdO1xuXG4gIGZvciAobGV0IHggb2YgbGlzdF9vZl9saXN0cykge1xuICAgIGlmICh4Lmxlbmd0aCA8IHNtYWxsZXN0X2xlbmd0aCkge1xuICAgICAgc21hbGxlc3RfbGVuZ3RoID0geC5sZW5ndGg7XG4gICAgfVxuICB9XG5cbiAgZm9yIChsZXQgaSA9IDA7IGkgPCBzbWFsbGVzdF9sZW5ndGg7IGkrKykge1xuICAgIGxldCBjdXJyZW50X3ZhbHVlID0gW107XG4gICAgZm9yIChsZXQgaiA9IDA7IGogPCBsaXN0X29mX2xpc3RzLmxlbmd0aDsgaisrKSB7XG4gICAgICBjdXJyZW50X3ZhbHVlLnB1c2gobGlzdF9vZl9saXN0c1tqXVtpXSk7XG4gICAgfVxuXG4gICAgbmV3X3ZhbHVlLnB1c2goS2VybmVsLlNwZWNpYWxGb3Jtcy50dXBsZSguLi5jdXJyZW50X3ZhbHVlKSk7XG4gIH1cblxuICByZXR1cm4gS2VybmVsLlNwZWNpYWxGb3Jtcy5saXN0KC4uLm5ld192YWx1ZSk7XG59O1xuXG5MaXN0LnRvX3R1cGxlID0gZnVuY3Rpb24gKGxpc3QpIHtcbiAgcmV0dXJuIEtlcm5lbC5TcGVjaWFsRm9ybXMudHVwbGUuYXBwbHkobnVsbCwgbGlzdCk7XG59O1xuXG5MaXN0LmFwcGVuZCA9IGZ1bmN0aW9uIChsaXN0LCB2YWx1ZSkge1xuICByZXR1cm4gS2VybmVsLlNwZWNpYWxGb3Jtcy5saXN0KC4uLmxpc3QuY29uY2F0KFt2YWx1ZV0pKTtcbn07XG5cbkxpc3QucHJlcGVuZCA9IGZ1bmN0aW9uIChsaXN0LCB2YWx1ZSkge1xuICByZXR1cm4gS2VybmVsLlNwZWNpYWxGb3Jtcy5saXN0KC4uLlt2YWx1ZV0uY29uY2F0KGxpc3QpKTtcbn07XG5cbkxpc3QuY29uY2F0ID0gZnVuY3Rpb24gKGxlZnQsIHJpZ2h0KSB7XG4gIHJldHVybiBsZWZ0LmNvbmNhdChyaWdodCk7XG59O1xuXG5sZXQgUmFuZ2UgPSBmdW5jdGlvbiAoX2ZpcnN0LCBfbGFzdCkge1xuICBpZiAoISh0aGlzIGluc3RhbmNlb2YgUmFuZ2UpKSB7XG4gICAgcmV0dXJuIG5ldyBSYW5nZShfZmlyc3QsIF9sYXN0KTtcbiAgfVxuXG4gIHRoaXMuZmlyc3QgPSBmdW5jdGlvbiAoKSB7XG4gICAgcmV0dXJuIF9maXJzdDtcbiAgfTtcblxuICB0aGlzLmxhc3QgPSBmdW5jdGlvbiAoKSB7XG4gICAgcmV0dXJuIF9sYXN0O1xuICB9O1xuXG4gIGxldCBfcmFuZ2UgPSBbXTtcblxuICBmb3IgKGxldCBpID0gX2ZpcnN0OyBpIDw9IF9sYXN0OyBpKyspIHtcbiAgICBfcmFuZ2UucHVzaChpKTtcbiAgfVxuXG4gIF9yYW5nZSA9IE9iamVjdC5mcmVlemUoX3JhbmdlKTtcblxuICB0aGlzLnZhbHVlID0gZnVuY3Rpb24gKCkge1xuICAgIHJldHVybiBfcmFuZ2U7XG4gIH07XG5cbiAgdGhpcy5sZW5ndGggPSBmdW5jdGlvbiAoKSB7XG4gICAgcmV0dXJuIF9yYW5nZS5sZW5ndGg7XG4gIH07XG5cbiAgcmV0dXJuIHRoaXM7XG59O1xuXG5SYW5nZS5wcm90b3R5cGVbU3ltYm9sLml0ZXJhdG9yXSA9IGZ1bmN0aW9uICgpIHtcbiAgcmV0dXJuIHRoaXMudmFsdWUoKVtTeW1ib2wuaXRlcmF0b3JdKCk7XG59O1xuXG5SYW5nZS5uZXcgPSBmdW5jdGlvbiAoZmlyc3QsIGxhc3QpIHtcbiAgcmV0dXJuIFJhbmdlKGZpcnN0LCBsYXN0KTtcbn07XG5cblJhbmdlLnJhbmdlX19xbWFya19fID0gZnVuY3Rpb24gKHJhbmdlKSB7XG4gIHJldHVybiByYW5nZSBpbnN0YW5jZW9mIFJhbmdlO1xufTtcblxubGV0IEtleXdvcmQgPSB7fTtcblxuS2V5d29yZC5oYXNfa2V5X19xbV9fID0gZnVuY3Rpb24gKGtleXdvcmRzLCBrZXkpIHtcbiAgZm9yIChsZXQga2V5d29yZCBvZiBrZXl3b3Jkcykge1xuICAgIGlmIChLZXJuZWwuZWxlbShrZXl3b3JkLCAwKSA9PSBrZXkpIHtcbiAgICAgIHJldHVybiB0cnVlO1xuICAgIH1cbiAgfVxuXG4gIHJldHVybiBmYWxzZTtcbn07XG5cbktleXdvcmQuZ2V0ID0gZnVuY3Rpb24gKGtleXdvcmRzLCBrZXksIHRoZV9kZWZhdWx0ID0gbnVsbCkge1xuICBmb3IgKGxldCBrZXl3b3JkIG9mIGtleXdvcmRzKSB7XG4gICAgaWYgKEtlcm5lbC5lbGVtKGtleXdvcmQsIDApID09IGtleSkge1xuICAgICAgcmV0dXJuIEtlcm5lbC5lbGVtKGtleXdvcmQsIDEpO1xuICAgIH1cbiAgfVxuXG4gIHJldHVybiB0aGVfZGVmYXVsdDtcbn07XG5cbmxldCBBZ2VudCA9IHt9O1xuXG5BZ2VudC5zdGFydCA9IGZ1bmN0aW9uIChmdW4sIG9wdGlvbnMgPSBbXSkge1xuICBsZXQgcGlkID0gc2VsZi5wcm9jZXNzZXMuc3Bhd24oKTtcblxuICBpZiAoS2V5d29yZC5oYXNfa2V5X19xbV9fKG9wdGlvbnMsIEtlcm5lbC5TcGVjaWFsRm9ybXMuYXRvbSgnbmFtZScpKSkge1xuICAgIHBpZCA9IHNlbGYucHJvY2Vzc2VzLnJlZ2lzdGVyKEtleXdvcmQuZ2V0KG9wdGlvbnMsIEtlcm5lbC5TcGVjaWFsRm9ybXMuYXRvbSgnbmFtZScpKSwgcGlkKTtcbiAgfVxuXG4gIHNlbGYucHJvY2Vzc2VzLnB1dChwaWQsICdzdGF0ZScsIGZ1bigpKTtcbiAgcmV0dXJuIEtlcm5lbC5TcGVjaWFsRm9ybXMudHVwbGUoS2VybmVsLlNwZWNpYWxGb3Jtcy5hdG9tKCdvaycpLCBwaWQpO1xufTtcblxuQWdlbnQuc3RvcCA9IGZ1bmN0aW9uIChhZ2VudCwgdGltZW91dCA9IDUwMDApIHtcbiAgc2VsZi5wcm9jZXNzZXMuZXhpdChhZ2VudCk7XG4gIHJldHVybiBLZXJuZWwuU3BlY2lhbEZvcm1zLmF0b20oJ29rJyk7XG59O1xuXG5BZ2VudC51cGRhdGUgPSBmdW5jdGlvbiAoYWdlbnQsIGZ1biwgdGltZW91dCA9IDUwMDApIHtcblxuICBjb25zdCBjdXJyZW50X3N0YXRlID0gc2VsZi5wcm9jZXNzZXMuZ2V0KGFnZW50LCAnc3RhdGUnKTtcbiAgc2VsZi5wcm9jZXNzZXMucHV0KGFnZW50LCAnc3RhdGUnLCBmdW4oY3VycmVudF9zdGF0ZSkpO1xuXG4gIHJldHVybiBLZXJuZWwuU3BlY2lhbEZvcm1zLmF0b20oJ29rJyk7XG59O1xuXG5BZ2VudC5nZXQgPSBmdW5jdGlvbiAoYWdlbnQsIGZ1biwgdGltZW91dCA9IDUwMDApIHtcbiAgcmV0dXJuIGZ1bihzZWxmLnByb2Nlc3Nlcy5nZXQoYWdlbnQsICdzdGF0ZScpKTtcbn07XG5cbkFnZW50LmdldF9hbmRfdXBkYXRlID0gZnVuY3Rpb24gKGFnZW50LCBmdW4sIHRpbWVvdXQgPSA1MDAwKSB7XG5cbiAgY29uc3QgZ2V0X2FuZF91cGRhdGVfdHVwbGUgPSBmdW4oc2VsZi5wcm9jZXNzZXMuZ2V0KGFnZW50LCAnc3RhdGUnKSk7XG4gIHNlbGYucHJvY2Vzc2VzLnB1dChhZ2VudCwgJ3N0YXRlJywgS2VybmVsLmVsZW0oZ2V0X2FuZF91cGRhdGVfdHVwbGUsIDEpKTtcblxuICByZXR1cm4gS2VybmVsLmVsZW0oZ2V0X2FuZF91cGRhdGVfdHVwbGUsIDApO1xufTtcblxuLy9odHRwczovL2RldmVsb3Blci5tb3ppbGxhLm9yZy9lbi1VUy9kb2NzL1dlYi9BUEkvV2luZG93QmFzZTY0L0Jhc2U2NF9lbmNvZGluZ19hbmRfZGVjb2RpbmcjU29sdXRpb25fMl8lRTIlODAlOTNfcmV3cml0ZV90aGVfRE9Nc19hdG9iKClfYW5kX2J0b2EoKV91c2luZ19KYXZhU2NyaXB0J3NfVHlwZWRBcnJheXNfYW5kX1VURi04XG5mdW5jdGlvbiBiNjRFbmNvZGVVbmljb2RlKHN0cikge1xuICByZXR1cm4gYnRvYShlbmNvZGVVUklDb21wb25lbnQoc3RyKS5yZXBsYWNlKC8lKFswLTlBLUZdezJ9KS9nLCBmdW5jdGlvbiAobWF0Y2gsIHAxKSB7XG4gICAgcmV0dXJuIFN0cmluZy5mcm9tQ2hhckNvZGUoJzB4JyArIHAxKTtcbiAgfSkpO1xufVxuXG5mdW5jdGlvbiBlbmNvZGU2NChkYXRhKSB7XG4gIHJldHVybiBiNjRFbmNvZGVVbmljb2RlKGRhdGEpO1xufVxuXG5mdW5jdGlvbiBkZWNvZGU2NChkYXRhKSB7XG4gIHRyeSB7XG4gICAgcmV0dXJuIEtlcm5lbC5TcGVjaWFsRm9ybXMudHVwbGUoS2VybmVsLlNwZWNpYWxGb3Jtcy5hdG9tKCdvaycpLCBhdG9iKGRhdGEpKTtcbiAgfSBjYXRjaCAoZSkge1xuICAgIHJldHVybiBLZXJuZWwuU3BlY2lhbEZvcm1zLmF0b20oJ2Vycm9yJyk7XG4gIH1cbiAgcmV0dXJuIGJ0b2EoZGF0YSk7XG59XG5cbmZ1bmN0aW9uIGRlY29kZTY0X19lbV9fKGRhdGEpIHtcbiAgcmV0dXJuIGF0b2IoZGF0YSk7XG59XG5cbnZhciBiYXNlID0ge1xuICBlbmNvZGU2NCxcbiAgZGVjb2RlNjQsXG4gIGRlY29kZTY0X19lbV9fXG59O1xuXG5mdW5jdGlvbiBibm90KGV4cHIpIHtcbiAgcmV0dXJuIH5leHByO1xufVxuXG5mdW5jdGlvbiBiYW5kKGxlZnQsIHJpZ2h0KSB7XG4gIHJldHVybiBsZWZ0ICYgcmlnaHQ7XG59XG5cbmZ1bmN0aW9uIGJvcihsZWZ0LCByaWdodCkge1xuICByZXR1cm4gbGVmdCB8IHJpZ2h0O1xufVxuXG5mdW5jdGlvbiBic2wobGVmdCwgcmlnaHQpIHtcbiAgcmV0dXJuIGxlZnQgPDwgcmlnaHQ7XG59XG5cbmZ1bmN0aW9uIGJzcihsZWZ0LCByaWdodCkge1xuICByZXR1cm4gbGVmdCA+PiByaWdodDtcbn1cblxuZnVuY3Rpb24gYnhvcihsZWZ0LCByaWdodCkge1xuICByZXR1cm4gbGVmdCBeIHJpZ2h0O1xufVxuXG52YXIgYml0d2lzZSA9IHtcbiAgYm5vdCxcbiAgYmFuZCxcbiAgYm9yLFxuICBic2wsXG4gIGJzcixcbiAgYnhvclxufTtcblxubGV0IEVudW1lcmFibGUgPSBLZXJuZWwuZGVmcHJvdG9jb2woe1xuICBjb3VudDogZnVuY3Rpb24gKGNvbGxlY3Rpb24pIHt9LFxuICBtZW1iZXJfcW1hcmtfXzogZnVuY3Rpb24gKGNvbGxlY3Rpb24sIHZhbHVlKSB7fSxcbiAgcmVkdWNlOiBmdW5jdGlvbiAoY29sbGVjdGlvbiwgYWNjLCBmdW4pIHt9XG59KTtcblxubGV0IENvbGxlY3RhYmxlID0gS2VybmVsLmRlZnByb3RvY29sKHtcbiAgaW50bzogZnVuY3Rpb24gKGNvbGxlY3RhYmxlKSB7fVxufSk7XG5cbmxldCBJbnNwZWN0ID0gS2VybmVsLmRlZnByb3RvY29sKHtcbiAgaW5zcGVjdDogZnVuY3Rpb24gKHRoaW5nLCBvcHRzKSB7fVxufSk7XG5cbmZ1bmN0aW9uIF9fbmV3X18oKSB7XG4gIHJldHVybiBTcGVjaWFsRm9ybXMubWFwKHt9KTtcbn1cblxuZnVuY3Rpb24ga2V5cyhtYXApIHtcbiAgcmV0dXJuIE9iamVjdC5rZXlzKG1hcCk7XG59XG5cbmZ1bmN0aW9uIHNpemUobWFwKSB7XG4gIHJldHVybiBrZXlzKG1hcCkubGVuZ3RoO1xufVxuXG5mdW5jdGlvbiB0b19saXN0JDEobWFwKSB7XG4gIGxldCBtYXBfa2V5cyA9IGtleXMobWFwKTtcbiAgbGV0IGxpc3QgPSBbXTtcblxuICBmb3IgKGxldCBrZXkgb2YgbWFwX2tleXMpIHtcbiAgICBsaXN0LnB1c2goU3BlY2lhbEZvcm1zLnR1cGxlKGtleSwgbWFwW2tleV0pKTtcbiAgfVxuXG4gIHJldHVybiBTcGVjaWFsRm9ybXMubGlzdCguLi5saXN0KTtcbn1cblxuZnVuY3Rpb24gdmFsdWVzKG1hcCkge1xuICBsZXQgbWFwX2tleXMgPSBrZXlzKG1hcCk7XG4gIGxldCBsaXN0ID0gW107XG5cbiAgZm9yIChsZXQga2V5IG9mIG1hcF9rZXlzKSB7XG4gICAgbGlzdC5wdXNoKG1hcFtrZXldKTtcbiAgfVxuXG4gIHJldHVybiBTcGVjaWFsRm9ybXMubGlzdCguLi5saXN0KTtcbn1cblxuZnVuY3Rpb24gZnJvbV9zdHJ1Y3Qoc3RydWN0KSB7XG4gIGxldCBtYXAgPSBPYmplY3QuYXNzaWduKHt9LCBzdHJ1Y3QpO1xuICBkZWxldGUgbWFwW1N5bWJvbC5mb3IoXCJfX3N0cnVjdF9fXCIpXTtcblxuICByZXR1cm4gU3BlY2lhbEZvcm1zLm1hcChtYXApO1xufVxuXG5mdW5jdGlvbiBfX2RlbGV0ZV9fKG1hcCwga2V5KSB7XG4gIGxldCBuZXdfbWFwID0gT2JqZWN0LmFzc2lnbih7fSwgbWFwKTtcblxuICBkZWxldGUgbmV3X21hcFtrZXldO1xuXG4gIHJldHVybiBTcGVjaWFsRm9ybXMubWFwKG5ld19tYXApO1xufVxuXG5mdW5jdGlvbiBlcXVhbF9fcW1hcmtfXyhtYXAxLCBtYXAyKSB7XG4gIHJldHVybiBtYXAxID09PSBtYXAyO1xufVxuXG5mdW5jdGlvbiBmZXRjaF9fZW1hcmtfXyhtYXAsIGtleSkge1xuICBpZiAoa2V5IGluIG1hcCkge1xuICAgIHJldHVybiBtYXBba2V5XTtcbiAgfVxuXG4gIHRocm93IG5ldyBFcnJvcihcIktleSBub3QgZm91bmQuXCIpO1xufVxuXG5mdW5jdGlvbiBmZXRjaChtYXAsIGtleSkge1xuICBpZiAoa2V5IGluIG1hcCkge1xuICAgIHJldHVybiBTcGVjaWFsRm9ybXMudHVwbGUoU3BlY2lhbEZvcm1zLmF0b20oXCJva1wiKSwgbWFwW2tleV0pO1xuICB9XG5cbiAgcmV0dXJuIFNwZWNpYWxGb3Jtcy5hdG9tKFwiZXJyb3JcIik7XG59XG5cbmZ1bmN0aW9uIGhhc19rZXlfX3FtYXJrX18obWFwLCBrZXkpIHtcbiAgcmV0dXJuIGtleSBpbiBtYXA7XG59XG5cbmZ1bmN0aW9uIHNwbGl0JDEobWFwLCBrZXlzKSB7XG4gIGxldCBzcGxpdDEgPSB7fTtcbiAgbGV0IHNwbGl0MiA9IHt9O1xuXG4gIGZvciAobGV0IGtleSBvZiBPYmplY3Qua2V5cyhtYXApKSB7XG4gICAgaWYgKGtleXMuaW5kZXhPZihrZXkpID4gLTEpIHtcbiAgICAgIHNwbGl0MVtrZXldID0gbWFwW2tleV07XG4gICAgfSBlbHNlIHtcbiAgICAgIHNwbGl0MltrZXldID0gbWFwW2tleV07XG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIFNwZWNpYWxGb3Jtcy50dXBsZShTcGVjaWFsRm9ybXMubWFwKHNwbGl0MSksIFNwZWNpYWxGb3Jtcy5tYXAoc3BsaXQyKSk7XG59XG5cbmZ1bmN0aW9uIHRha2UobWFwLCBrZXlzKSB7XG4gIGxldCBzcGxpdDEgPSB7fTtcblxuICBmb3IgKGxldCBrZXkgb2YgT2JqZWN0LmtleXMobWFwKSkge1xuICAgIGlmIChrZXlzLmluZGV4T2Yoa2V5KSA+IC0xKSB7XG4gICAgICBzcGxpdDFba2V5XSA9IG1hcFtrZXldO1xuICAgIH1cbiAgfVxuXG4gIHJldHVybiBTcGVjaWFsRm9ybXMubWFwKHNwbGl0MSk7XG59XG5cbmZ1bmN0aW9uIGRyb3AobWFwLCBrZXlzKSB7XG4gIGxldCBzcGxpdDEgPSB7fTtcblxuICBmb3IgKGxldCBrZXkgb2YgT2JqZWN0LmtleXMobWFwKSkge1xuICAgIGlmIChrZXlzLmluZGV4T2Yoa2V5KSA9PT0gLTEpIHtcbiAgICAgIHNwbGl0MVtrZXldID0gbWFwW2tleV07XG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIFNwZWNpYWxGb3Jtcy5tYXAoc3BsaXQxKTtcbn1cblxuZnVuY3Rpb24gcHV0X25ldyhtYXAsIGtleSwgdmFsdWUpIHtcbiAgaWYgKGtleSBpbiBtYXApIHtcbiAgICByZXR1cm4gbWFwO1xuICB9XG5cbiAgbGV0IG5ld19tYXAgPSBPYmplY3QuYXNzaWduKHt9LCBtYXApO1xuICBuZXdfbWFwW2tleV0gPSB2YWx1ZTtcblxuICByZXR1cm4gU3BlY2lhbEZvcm1zLm1hcChuZXdfbWFwKTtcbn1cblxuZnVuY3Rpb24gcHV0X25ld19sYXp5KG1hcCwga2V5LCBmdW4pIHtcbiAgaWYgKGtleSBpbiBtYXApIHtcbiAgICByZXR1cm4gbWFwO1xuICB9XG5cbiAgbGV0IG5ld19tYXAgPSBPYmplY3QuYXNzaWduKHt9LCBtYXApO1xuICBuZXdfbWFwW2tleV0gPSBmdW4oKTtcblxuICByZXR1cm4gU3BlY2lhbEZvcm1zLm1hcChuZXdfbWFwKTtcbn1cblxuZnVuY3Rpb24gZ2V0X2FuZF91cGRhdGUobWFwLCBrZXksIGZ1bikge1xuICBpZiAoa2V5IGluIG1hcCkge1xuICAgIHJldHVybiBtYXA7XG4gIH1cblxuICBsZXQgbmV3X21hcCA9IE9iamVjdC5hc3NpZ24oe30sIG1hcCk7XG4gIG5ld19tYXBba2V5XSA9IGZ1bihtYXBba2V5XSk7XG5cbiAgcmV0dXJuIFNwZWNpYWxGb3Jtcy5tYXAobmV3X21hcCk7XG59XG5cbmZ1bmN0aW9uIHBvcF9sYXp5KG1hcCwga2V5LCBmdW4pIHtcbiAgaWYgKCFrZXkgaW4gbWFwKSB7XG4gICAgcmV0dXJuIFNwZWNpYWxGb3Jtcy50dXBsZShmdW4oKSwgbWFwKTtcbiAgfVxuXG4gIGxldCBuZXdfbWFwID0gT2JqZWN0LmFzc2lnbih7fSwgbWFwKTtcbiAgbGV0IHZhbHVlID0gZnVuKG5ld19tYXBba2V5XSk7XG4gIGRlbGV0ZSBuZXdfbWFwW2tleV07XG5cbiAgcmV0dXJuIFNwZWNpYWxGb3Jtcy50dXBsZSh2YWx1ZSwgbmV3X21hcCk7XG59XG5cbmZ1bmN0aW9uIHBvcChtYXAsIGtleSwgX2RlZmF1bHQgPSBudWxsKSB7XG4gIGlmICgha2V5IGluIG1hcCkge1xuICAgIHJldHVybiBTcGVjaWFsRm9ybXMudHVwbGUoX2RlZmF1bHQsIG1hcCk7XG4gIH1cblxuICBsZXQgbmV3X21hcCA9IE9iamVjdC5hc3NpZ24oe30sIG1hcCk7XG4gIGxldCB2YWx1ZSA9IG5ld19tYXBba2V5XTtcbiAgZGVsZXRlIG5ld19tYXBba2V5XTtcblxuICByZXR1cm4gU3BlY2lhbEZvcm1zLnR1cGxlKHZhbHVlLCBuZXdfbWFwKTtcbn1cblxuZnVuY3Rpb24gZ2V0X2xhenkobWFwLCBrZXksIGZ1bikge1xuICBpZiAoIWtleSBpbiBtYXApIHtcbiAgICByZXR1cm4gZnVuKCk7XG4gIH1cblxuICByZXR1cm4gZnVuKG1hcFtrZXldKTtcbn1cblxuZnVuY3Rpb24gZ2V0KG1hcCwga2V5LCBfZGVmYXVsdCA9IG51bGwpIHtcbiAgaWYgKCFrZXkgaW4gbWFwKSB7XG4gICAgcmV0dXJuIF9kZWZhdWx0O1xuICB9XG5cbiAgcmV0dXJuIG1hcFtrZXldO1xufVxuXG5mdW5jdGlvbiBwdXQobWFwLCBrZXksIHZhbCkge1xuICBsZXQgbmV3X21hcCA9IE9iamVjdCh7fSwgbWFwKTtcbiAgbmV3X21hcFtrZXldID0gdmFsO1xuXG4gIHJldHVybiBTcGVjaWFsRm9ybXMubWFwKG5ld19tYXApO1xufVxuXG5mdW5jdGlvbiB1cGRhdGVfX2VtYXJrX18obWFwLCBrZXksIGZ1bikge1xuICBpZiAoIWtleSBpbiBtYXApIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoXCJLZXkgbm90IGZvdW5kXCIpO1xuICB9XG5cbiAgbGV0IG5ld19tYXAgPSBPYmplY3Qoe30sIG1hcCk7XG4gIG5ld19tYXBba2V5XSA9IGZ1bihtYXBba2V5XSk7XG5cbiAgcmV0dXJuIFNwZWNpYWxGb3Jtcy5tYXAobmV3X21hcCk7XG59XG5cbmZ1bmN0aW9uIHVwZGF0ZShtYXAsIGtleSwgaW5pdGlhbCwgZnVuKSB7XG4gIGxldCBuZXdfbWFwID0gT2JqZWN0KHt9LCBtYXApO1xuXG4gIGlmICgha2V5IGluIG1hcCkge1xuICAgIG5ld19tYXBba2V5XSA9IGluaXRpYWw7XG4gIH0gZWxzZSB7XG4gICAgbmV3X21hcFtrZXldID0gZnVuKG1hcFtrZXldKTtcbiAgfVxuXG4gIHJldHVybiBTcGVjaWFsRm9ybXMubWFwKG5ld19tYXApO1xufVxuXG52YXIgbWFwID0ge1xuICBuZXc6IF9fbmV3X18sXG4gIGtleXMsXG4gIHNpemUsXG4gIHRvX2xpc3Q6IHRvX2xpc3QkMSxcbiAgdmFsdWVzLFxuICBmcm9tX3N0cnVjdCxcbiAgZGVsZXRlOiBfX2RlbGV0ZV9fLFxuICBkcm9wLFxuICBlcXVhbF9fcW1hcmtfXyxcbiAgZmV0Y2hfX2VtYXJrX18sXG4gIGZldGNoLFxuICBoYXNfa2V5X19xbWFya19fLFxuICBzcGxpdDogc3BsaXQkMSxcbiAgdGFrZSxcbiAgcHV0X25ldyxcbiAgcHV0X25ld19sYXp5LFxuICBnZXRfYW5kX3VwZGF0ZSxcbiAgcG9wX2xhenksXG4gIHBvcCxcbiAgZ2V0X2xhenksXG4gIGdldCxcbiAgcHV0LFxuICB1cGRhdGVfX2VtYXJrX18sXG4gIHVwZGF0ZVxufTtcblxuZnVuY3Rpb24gX19uZXdfXyQxKCkge1xuICByZXR1cm4gU3BlY2lhbEZvcm1zLm1hcCh7IFtTeW1ib2wuZm9yKCdfX3N0cnVjdF9fJyldOiBTeW1ib2wuZm9yKCdNYXBTZXQnKSwgc2V0OiBTcGVjaWFsRm9ybXMubGlzdCgpIH0pO1xufVxuXG5mdW5jdGlvbiBzaXplJDIobWFwKSB7XG4gIHJldHVybiBtYXAuc2V0Lmxlbmd0aDtcbn1cblxuZnVuY3Rpb24gdG9fbGlzdCQzKG1hcCkge1xuICByZXR1cm4gbWFwLnNldDtcbn1cblxuZnVuY3Rpb24gX19kZWxldGVfXyQyKHNldCwgdGVybSkge1xuICBsZXQgbmV3X2xpc3QgPSBMaXN0LmRlbGV0ZShzZXQuc2V0LCB0ZXJtKTtcblxuICBsZXQgbmV3X21hcCA9IE9iamVjdC5hc3NpZ24oe30sIHNldCk7XG4gIG5ld19tYXAuc2V0ID0gbmV3X2xpc3Q7XG4gIHJldHVybiBTcGVjaWFsRm9ybXMubWFwKG5ld19tYXApO1xufVxuXG5mdW5jdGlvbiBwdXQkMihzZXQsIHRlcm0pIHtcbiAgaWYgKHNldC5zZXQuaW5kZXhPZih0ZXJtKSA9PT0gLTEpIHtcbiAgICBsZXQgbmV3X2xpc3QgPSBMaXN0LmFwcGVuZChzZXQuc2V0LCB0ZXJtKTtcblxuICAgIGxldCBuZXdfbWFwID0gT2JqZWN0LmFzc2lnbih7fSwgc2V0KTtcbiAgICBuZXdfbWFwLnNldCA9IG5ld19saXN0O1xuICAgIHJldHVybiBTcGVjaWFsRm9ybXMubWFwKG5ld19tYXApO1xuICB9XG5cbiAgcmV0dXJuIHNldDtcbn1cblxuZnVuY3Rpb24gZGlmZmVyZW5jZSQxKHNldDEsIHNldDIpIHtcbiAgbGV0IG5ld19tYXAgPSBPYmplY3QuYXNzaWduKHt9LCBzZXQxKTtcblxuICBmb3IgKGxldCB2YWwgb2Ygc2V0MS5zZXQpIHtcbiAgICBpZiAobWVtYmVyX19xbWFya19fJDEoc2V0MiwgdmFsKSkge1xuICAgICAgbmV3X21hcC5zZXQgPSBMaXN0LmRlbGV0ZShuZXdfbWFwLnNldCwgdmFsKTtcbiAgICB9XG4gIH1cblxuICByZXR1cm4gU3BlY2lhbEZvcm1zLm1hcChuZXdfbWFwKTtcbn1cblxuZnVuY3Rpb24gaW50ZXJzZWN0aW9uJDEoc2V0MSwgc2V0Mikge1xuICBsZXQgbmV3X21hcCA9IE9iamVjdC5hc3NpZ24oe30sIHNldDEpO1xuXG4gIGZvciAobGV0IHZhbCBvZiBzZXQxLnNldCkge1xuICAgIGlmICghbWVtYmVyX19xbWFya19fJDEoc2V0MiwgdmFsKSkge1xuICAgICAgbmV3X21hcC5zZXQgPSBMaXN0LmRlbGV0ZShuZXdfbWFwLnNldCwgdmFsKTtcbiAgICB9XG4gIH1cblxuICByZXR1cm4gU3BlY2lhbEZvcm1zLm1hcChuZXdfbWFwKTtcbn1cblxuZnVuY3Rpb24gdW5pb24kMShzZXQxLCBzZXQyKSB7XG4gIGxldCBuZXdfbWFwID0gc2V0MTtcblxuICBmb3IgKGxldCB2YWwgb2Ygc2V0Mi5zZXQpIHtcbiAgICBuZXdfbWFwID0gcHV0JDIobmV3X21hcCwgdmFsKTtcbiAgfVxuXG4gIHJldHVybiBTcGVjaWFsRm9ybXMubWFwKG5ld19tYXApO1xufVxuXG5mdW5jdGlvbiBkaXNqb2luX19xbWFya19fJDEoc2V0MSwgc2V0Mikge1xuICBmb3IgKGxldCB2YWwgb2Ygc2V0MS5zZXQpIHtcbiAgICBpZiAobWVtYmVyX19xbWFya19fJDEoc2V0MiwgdmFsKSkge1xuICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH1cbiAgfVxuXG4gIHJldHVybiB0cnVlO1xufVxuXG5mdW5jdGlvbiBtZW1iZXJfX3FtYXJrX18kMShzZXQsIHZhbHVlKSB7XG4gIHJldHVybiBzZXQuc2V0LmluZGV4T2YodmFsdWUpID49IDA7XG59XG5cbmZ1bmN0aW9uIGVxdWFsX19xbWFya19fJDIoc2V0MSwgc2V0Mikge1xuICByZXR1cm4gc2V0MS5zZXQgPT09IHNldDIuc2V0O1xufVxuXG5mdW5jdGlvbiBzdWJzZXRfX3FtYXJrX18kMShzZXQxLCBzZXQyKSB7XG4gIGZvciAobGV0IHZhbCBvZiBzZXQxLnNldCkge1xuICAgIGlmICghbWVtYmVyX19xbWFya19fJDEoc2V0MiwgdmFsKSkge1xuICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH1cbiAgfVxuXG4gIHJldHVybiB0cnVlO1xufVxuXG52YXIgTWFwU2V0ID0ge1xuICBuZXc6IF9fbmV3X18kMSxcbiAgc2l6ZTogc2l6ZSQyLFxuICB0b19saXN0OiB0b19saXN0JDMsXG4gIGRpc2pvaW5fX3FtYXJrX186IGRpc2pvaW5fX3FtYXJrX18kMSxcbiAgZGVsZXRlOiBfX2RlbGV0ZV9fJDIsXG4gIHN1YnNldF9fcW1hcmtfXzogc3Vic2V0X19xbWFya19fJDEsXG4gIGVxdWFsX19xbWFya19fOiBlcXVhbF9fcW1hcmtfXyQyLFxuICBtZW1iZXJfX3FtYXJrX186IG1lbWJlcl9fcW1hcmtfXyQxLFxuICBwdXQ6IHB1dCQyLFxuICB1bmlvbjogdW5pb24kMSxcbiAgaW50ZXJzZWN0aW9uOiBpbnRlcnNlY3Rpb24kMSxcbiAgZGlmZmVyZW5jZTogZGlmZmVyZW5jZSQxXG59O1xuXG5mdW5jdGlvbiBzaXplJDEobWFwKSB7XG4gIHJldHVybiBNYXBTZXQuc2l6ZShtYXApO1xufVxuXG5mdW5jdGlvbiB0b19saXN0JDIobWFwKSB7XG4gIHJldHVybiBNYXBTZXQudG9fbGlzdChtYXApO1xufVxuXG5mdW5jdGlvbiBfX2RlbGV0ZV9fJDEoc2V0LCB0ZXJtKSB7XG4gIHJldHVybiBNYXBTZXQuZGVsZXRlKHNldCwgdGVybSk7XG59XG5cbmZ1bmN0aW9uIHB1dCQxKHNldCwgdGVybSkge1xuICByZXR1cm4gTWFwU2V0LnB1dChzZXQsIHRlcm0pO1xufVxuXG5mdW5jdGlvbiBkaWZmZXJlbmNlKHNldDEsIHNldDIpIHtcbiAgcmV0dXJuIE1hcFNldC5kaWZmZXJlbmNlKHNldDEsIHNldDIpO1xufVxuXG5mdW5jdGlvbiBpbnRlcnNlY3Rpb24oc2V0MSwgc2V0Mikge1xuICByZXR1cm4gTWFwU2V0LmludGVyc2VjdGlvbihzZXQxLCBzZXQyKTtcbn1cblxuZnVuY3Rpb24gdW5pb24oc2V0MSwgc2V0Mikge1xuICByZXR1cm4gTWFwU2V0LnVuaW9uKHNldDEsIHNldDIpO1xufVxuXG5mdW5jdGlvbiBkaXNqb2luX19xbWFya19fKHNldDEsIHNldDIpIHtcbiAgcmV0dXJuIE1hcFNldC5kaXNqb2luX19xbWFya19fKHNldDEsIHNldDIpO1xufVxuXG5mdW5jdGlvbiBtZW1iZXJfX3FtYXJrX18oc2V0LCB2YWx1ZSkge1xuICByZXR1cm4gTWFwU2V0Lm1lbWJlcl9fcW1hcmtfXyhzZXQxLCBzZXQyKTtcbn1cblxuZnVuY3Rpb24gZXF1YWxfX3FtYXJrX18kMShzZXQxLCBzZXQyKSB7XG4gIHJldHVybiBNYXBTZXQuZXF1YWxfX3FtYXJrX18oc2V0MSwgc2V0Mik7XG59XG5cbmZ1bmN0aW9uIHN1YnNldF9fcW1hcmtfXyhzZXQxLCBzZXQyKSB7XG4gIHJldHVybiBNYXBTZXQuc3Vic2V0X19xbWFya19fKHNldDEsIHNldDIpO1xufVxuXG52YXIgc2V0ID0ge1xuICBzaXplOiBzaXplJDEsXG4gIHRvX2xpc3Q6IHRvX2xpc3QkMixcbiAgZGlzam9pbl9fcW1hcmtfXyxcbiAgZGVsZXRlOiBfX2RlbGV0ZV9fJDEsXG4gIHN1YnNldF9fcW1hcmtfXyxcbiAgZXF1YWxfX3FtYXJrX186IGVxdWFsX19xbWFya19fJDEsXG4gIG1lbWJlcl9fcW1hcmtfXyxcbiAgcHV0OiBwdXQkMSxcbiAgdW5pb24sXG4gIGludGVyc2VjdGlvbixcbiAgZGlmZmVyZW5jZVxufTtcblxubGV0IFZpcnR1YWxET00gPSAoZnVuY3Rpb24gKGUpIHtcbiAgICByZXR1cm4gZSgpO1xufSkoZnVuY3Rpb24gKCkge1xuICAgIHZhciBkZWZpbmUsIG1vZHVsZSwgZXhwb3J0cztcbiAgICByZXR1cm4gKGZ1bmN0aW9uIGUodCwgbiwgcikge1xuICAgICAgICBmdW5jdGlvbiBzKG8sIHUpIHtcbiAgICAgICAgICAgIGlmICghbltvXSkge1xuICAgICAgICAgICAgICAgIGlmICghdFtvXSkge1xuICAgICAgICAgICAgICAgICAgICB2YXIgYSA9IHR5cGVvZiByZXF1aXJlID09IFwiZnVuY3Rpb25cIiAmJiByZXF1aXJlO1xuICAgICAgICAgICAgICAgICAgICBpZiAoIXUgJiYgYSkgcmV0dXJuIGEobywgITApO1xuICAgICAgICAgICAgICAgICAgICBpZiAoaSkgcmV0dXJuIGkobywgITApO1xuICAgICAgICAgICAgICAgICAgICB2YXIgZiA9IG5ldyBFcnJvcihcIkNhbm5vdCBmaW5kIG1vZHVsZSAnXCIgKyBvICsgXCInXCIpO1xuICAgICAgICAgICAgICAgICAgICB0aHJvdyAoZi5jb2RlID0gXCJNT0RVTEVfTk9UX0ZPVU5EXCIsIGYpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB2YXIgbCA9IG5bb10gPSB7XG4gICAgICAgICAgICAgICAgICAgIGV4cG9ydHM6IHt9XG4gICAgICAgICAgICAgICAgfTtcbiAgICAgICAgICAgICAgICB0W29dWzBdLmNhbGwobC5leHBvcnRzLCBmdW5jdGlvbiAoZSkge1xuICAgICAgICAgICAgICAgICAgICB2YXIgbiA9IHRbb11bMV1bZV07XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBzKG4gPyBuIDogZSk7XG4gICAgICAgICAgICAgICAgfSwgbCwgbC5leHBvcnRzLCBlLCB0LCBuLCByKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJldHVybiBuW29dLmV4cG9ydHM7XG4gICAgICAgIH1cbiAgICAgICAgdmFyIGkgPSB0eXBlb2YgcmVxdWlyZSA9PSBcImZ1bmN0aW9uXCIgJiYgcmVxdWlyZTtcbiAgICAgICAgZm9yICh2YXIgbyA9IDA7IG8gPCByLmxlbmd0aDsgbysrKSBzKHJbb10pO1xuICAgICAgICByZXR1cm4gcztcbiAgICB9KSh7XG4gICAgICAgIDE6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG5cbiAgICAgICAgICAgIHZhciBjcmVhdGVFbGVtZW50ID0gcmVxdWlyZShcIi4vdmRvbS9jcmVhdGUtZWxlbWVudC5qc1wiKTtcblxuICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBjcmVhdGVFbGVtZW50O1xuICAgICAgICB9LCB7IFwiLi92ZG9tL2NyZWF0ZS1lbGVtZW50LmpzXCI6IDE1IH1dLCAyOiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge1xuICAgICAgICAgICAgdmFyIGRpZmYgPSByZXF1aXJlKFwiLi92dHJlZS9kaWZmLmpzXCIpO1xuXG4gICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IGRpZmY7XG4gICAgICAgIH0sIHsgXCIuL3Z0cmVlL2RpZmYuanNcIjogMzUgfV0sIDM6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICB2YXIgaCA9IHJlcXVpcmUoXCIuL3ZpcnR1YWwtaHlwZXJzY3JpcHQvaW5kZXguanNcIik7XG5cbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gaDtcbiAgICAgICAgfSwgeyBcIi4vdmlydHVhbC1oeXBlcnNjcmlwdC9pbmRleC5qc1wiOiAyMiB9XSwgNDogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHtcbiAgICAgICAgICAgIHZhciBkaWZmID0gcmVxdWlyZShcIi4vZGlmZi5qc1wiKTtcbiAgICAgICAgICAgIHZhciBwYXRjaCA9IHJlcXVpcmUoXCIuL3BhdGNoLmpzXCIpO1xuICAgICAgICAgICAgdmFyIGggPSByZXF1aXJlKFwiLi9oLmpzXCIpO1xuICAgICAgICAgICAgdmFyIGNyZWF0ZSA9IHJlcXVpcmUoXCIuL2NyZWF0ZS1lbGVtZW50LmpzXCIpO1xuICAgICAgICAgICAgdmFyIFZOb2RlID0gcmVxdWlyZShcIi4vdm5vZGUvdm5vZGUuanNcIik7XG4gICAgICAgICAgICB2YXIgVlRleHQgPSByZXF1aXJlKFwiLi92bm9kZS92dGV4dC5qc1wiKTtcblxuICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSB7XG4gICAgICAgICAgICAgICAgZGlmZjogZGlmZixcbiAgICAgICAgICAgICAgICBwYXRjaDogcGF0Y2gsXG4gICAgICAgICAgICAgICAgaDogaCxcbiAgICAgICAgICAgICAgICBjcmVhdGU6IGNyZWF0ZSxcbiAgICAgICAgICAgICAgICBWTm9kZTogVk5vZGUsXG4gICAgICAgICAgICAgICAgVlRleHQ6IFZUZXh0XG4gICAgICAgICAgICB9O1xuICAgICAgICB9LCB7IFwiLi9jcmVhdGUtZWxlbWVudC5qc1wiOiAxLCBcIi4vZGlmZi5qc1wiOiAyLCBcIi4vaC5qc1wiOiAzLCBcIi4vcGF0Y2guanNcIjogMTMsIFwiLi92bm9kZS92bm9kZS5qc1wiOiAzMSwgXCIuL3Zub2RlL3Z0ZXh0LmpzXCI6IDMzIH1dLCA1OiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge1xuICAgICAgICAgICAgLyohXG4gICAgICAgICAgICAgKiBDcm9zcy1Ccm93c2VyIFNwbGl0IDEuMS4xXG4gICAgICAgICAgICAgKiBDb3B5cmlnaHQgMjAwNy0yMDEyIFN0ZXZlbiBMZXZpdGhhbiA8c3RldmVubGV2aXRoYW4uY29tPlxuICAgICAgICAgICAgICogQXZhaWxhYmxlIHVuZGVyIHRoZSBNSVQgTGljZW5zZVxuICAgICAgICAgICAgICogRUNNQVNjcmlwdCBjb21wbGlhbnQsIHVuaWZvcm0gY3Jvc3MtYnJvd3NlciBzcGxpdCBtZXRob2RcbiAgICAgICAgICAgICAqL1xuXG4gICAgICAgICAgICAvKipcbiAgICAgICAgICAgICAqIFNwbGl0cyBhIHN0cmluZyBpbnRvIGFuIGFycmF5IG9mIHN0cmluZ3MgdXNpbmcgYSByZWdleCBvciBzdHJpbmcgc2VwYXJhdG9yLiBNYXRjaGVzIG9mIHRoZVxuICAgICAgICAgICAgICogc2VwYXJhdG9yIGFyZSBub3QgaW5jbHVkZWQgaW4gdGhlIHJlc3VsdCBhcnJheS4gSG93ZXZlciwgaWYgYHNlcGFyYXRvcmAgaXMgYSByZWdleCB0aGF0IGNvbnRhaW5zXG4gICAgICAgICAgICAgKiBjYXB0dXJpbmcgZ3JvdXBzLCBiYWNrcmVmZXJlbmNlcyBhcmUgc3BsaWNlZCBpbnRvIHRoZSByZXN1bHQgZWFjaCB0aW1lIGBzZXBhcmF0b3JgIGlzIG1hdGNoZWQuXG4gICAgICAgICAgICAgKiBGaXhlcyBicm93c2VyIGJ1Z3MgY29tcGFyZWQgdG8gdGhlIG5hdGl2ZSBgU3RyaW5nLnByb3RvdHlwZS5zcGxpdGAgYW5kIGNhbiBiZSB1c2VkIHJlbGlhYmx5XG4gICAgICAgICAgICAgKiBjcm9zcy1icm93c2VyLlxuICAgICAgICAgICAgICogQHBhcmFtIHtTdHJpbmd9IHN0ciBTdHJpbmcgdG8gc3BsaXQuXG4gICAgICAgICAgICAgKiBAcGFyYW0ge1JlZ0V4cHxTdHJpbmd9IHNlcGFyYXRvciBSZWdleCBvciBzdHJpbmcgdG8gdXNlIGZvciBzZXBhcmF0aW5nIHRoZSBzdHJpbmcuXG4gICAgICAgICAgICAgKiBAcGFyYW0ge051bWJlcn0gW2xpbWl0XSBNYXhpbXVtIG51bWJlciBvZiBpdGVtcyB0byBpbmNsdWRlIGluIHRoZSByZXN1bHQgYXJyYXkuXG4gICAgICAgICAgICAgKiBAcmV0dXJucyB7QXJyYXl9IEFycmF5IG9mIHN1YnN0cmluZ3MuXG4gICAgICAgICAgICAgKiBAZXhhbXBsZVxuICAgICAgICAgICAgICpcbiAgICAgICAgICAgICAqIC8vIEJhc2ljIHVzZVxuICAgICAgICAgICAgICogc3BsaXQoJ2EgYiBjIGQnLCAnICcpO1xuICAgICAgICAgICAgICogLy8gLT4gWydhJywgJ2InLCAnYycsICdkJ11cbiAgICAgICAgICAgICAqXG4gICAgICAgICAgICAgKiAvLyBXaXRoIGxpbWl0XG4gICAgICAgICAgICAgKiBzcGxpdCgnYSBiIGMgZCcsICcgJywgMik7XG4gICAgICAgICAgICAgKiAvLyAtPiBbJ2EnLCAnYiddXG4gICAgICAgICAgICAgKlxuICAgICAgICAgICAgICogLy8gQmFja3JlZmVyZW5jZXMgaW4gcmVzdWx0IGFycmF5XG4gICAgICAgICAgICAgKiBzcGxpdCgnLi53b3JkMSB3b3JkMi4uJywgLyhbYS16XSspKFxcZCspL2kpO1xuICAgICAgICAgICAgICogLy8gLT4gWycuLicsICd3b3JkJywgJzEnLCAnICcsICd3b3JkJywgJzInLCAnLi4nXVxuICAgICAgICAgICAgICovXG4gICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IChmdW5jdGlvbiBzcGxpdCh1bmRlZikge1xuXG4gICAgICAgICAgICAgICAgdmFyIG5hdGl2ZVNwbGl0ID0gU3RyaW5nLnByb3RvdHlwZS5zcGxpdCxcbiAgICAgICAgICAgICAgICAgICAgY29tcGxpYW50RXhlY05wY2cgPSAvKCk/Py8uZXhlYyhcIlwiKVsxXSA9PT0gdW5kZWYsXG5cbiAgICAgICAgICAgICAgICAvLyBOUENHOiBub25wYXJ0aWNpcGF0aW5nIGNhcHR1cmluZyBncm91cFxuICAgICAgICAgICAgICAgIHNlbGY7XG5cbiAgICAgICAgICAgICAgICBzZWxmID0gZnVuY3Rpb24gKHN0ciwgc2VwYXJhdG9yLCBsaW1pdCkge1xuICAgICAgICAgICAgICAgICAgICAvLyBJZiBgc2VwYXJhdG9yYCBpcyBub3QgYSByZWdleCwgdXNlIGBuYXRpdmVTcGxpdGBcbiAgICAgICAgICAgICAgICAgICAgaWYgKE9iamVjdC5wcm90b3R5cGUudG9TdHJpbmcuY2FsbChzZXBhcmF0b3IpICE9PSBcIltvYmplY3QgUmVnRXhwXVwiKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gbmF0aXZlU3BsaXQuY2FsbChzdHIsIHNlcGFyYXRvciwgbGltaXQpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIHZhciBvdXRwdXQgPSBbXSxcbiAgICAgICAgICAgICAgICAgICAgICAgIGZsYWdzID0gKHNlcGFyYXRvci5pZ25vcmVDYXNlID8gXCJpXCIgOiBcIlwiKSArIChzZXBhcmF0b3IubXVsdGlsaW5lID8gXCJtXCIgOiBcIlwiKSArIChzZXBhcmF0b3IuZXh0ZW5kZWQgPyBcInhcIiA6IFwiXCIpICsgKHNlcGFyYXRvci5zdGlja3kgPyBcInlcIiA6IFwiXCIpLFxuXG4gICAgICAgICAgICAgICAgICAgIC8vIEZpcmVmb3ggMytcbiAgICAgICAgICAgICAgICAgICAgbGFzdExhc3RJbmRleCA9IDAsXG5cbiAgICAgICAgICAgICAgICAgICAgLy8gTWFrZSBgZ2xvYmFsYCBhbmQgYXZvaWQgYGxhc3RJbmRleGAgaXNzdWVzIGJ5IHdvcmtpbmcgd2l0aCBhIGNvcHlcbiAgICAgICAgICAgICAgICAgICAgc2VwYXJhdG9yID0gbmV3IFJlZ0V4cChzZXBhcmF0b3Iuc291cmNlLCBmbGFncyArIFwiZ1wiKSxcbiAgICAgICAgICAgICAgICAgICAgICAgIHNlcGFyYXRvcjIsXG4gICAgICAgICAgICAgICAgICAgICAgICBtYXRjaCxcbiAgICAgICAgICAgICAgICAgICAgICAgIGxhc3RJbmRleCxcbiAgICAgICAgICAgICAgICAgICAgICAgIGxhc3RMZW5ndGg7XG4gICAgICAgICAgICAgICAgICAgIHN0ciArPSBcIlwiOyAvLyBUeXBlLWNvbnZlcnRcbiAgICAgICAgICAgICAgICAgICAgaWYgKCFjb21wbGlhbnRFeGVjTnBjZykge1xuICAgICAgICAgICAgICAgICAgICAgICAgLy8gRG9lc24ndCBuZWVkIGZsYWdzIGd5LCBidXQgdGhleSBkb24ndCBodXJ0XG4gICAgICAgICAgICAgICAgICAgICAgICBzZXBhcmF0b3IyID0gbmV3IFJlZ0V4cChcIl5cIiArIHNlcGFyYXRvci5zb3VyY2UgKyBcIiQoPyFcXFxccylcIiwgZmxhZ3MpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIC8qIFZhbHVlcyBmb3IgYGxpbWl0YCwgcGVyIHRoZSBzcGVjOlxuICAgICAgICAgICAgICAgICAgICAgKiBJZiB1bmRlZmluZWQ6IDQyOTQ5NjcyOTUgLy8gTWF0aC5wb3coMiwgMzIpIC0gMVxuICAgICAgICAgICAgICAgICAgICAgKiBJZiAwLCBJbmZpbml0eSwgb3IgTmFOOiAwXG4gICAgICAgICAgICAgICAgICAgICAqIElmIHBvc2l0aXZlIG51bWJlcjogbGltaXQgPSBNYXRoLmZsb29yKGxpbWl0KTsgaWYgKGxpbWl0ID4gNDI5NDk2NzI5NSkgbGltaXQgLT0gNDI5NDk2NzI5NjtcbiAgICAgICAgICAgICAgICAgICAgICogSWYgbmVnYXRpdmUgbnVtYmVyOiA0Mjk0OTY3Mjk2IC0gTWF0aC5mbG9vcihNYXRoLmFicyhsaW1pdCkpXG4gICAgICAgICAgICAgICAgICAgICAqIElmIG90aGVyOiBUeXBlLWNvbnZlcnQsIHRoZW4gdXNlIHRoZSBhYm92ZSBydWxlc1xuICAgICAgICAgICAgICAgICAgICAgKi9cbiAgICAgICAgICAgICAgICAgICAgbGltaXQgPSBsaW1pdCA9PT0gdW5kZWYgPyAtMSA+Pj4gMCA6IC8vIE1hdGgucG93KDIsIDMyKSAtIDFcbiAgICAgICAgICAgICAgICAgICAgbGltaXQgPj4+IDA7IC8vIFRvVWludDMyKGxpbWl0KVxuICAgICAgICAgICAgICAgICAgICB3aGlsZSAobWF0Y2ggPSBzZXBhcmF0b3IuZXhlYyhzdHIpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAvLyBgc2VwYXJhdG9yLmxhc3RJbmRleGAgaXMgbm90IHJlbGlhYmxlIGNyb3NzLWJyb3dzZXJcbiAgICAgICAgICAgICAgICAgICAgICAgIGxhc3RJbmRleCA9IG1hdGNoLmluZGV4ICsgbWF0Y2hbMF0ubGVuZ3RoO1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGxhc3RJbmRleCA+IGxhc3RMYXN0SW5kZXgpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBvdXRwdXQucHVzaChzdHIuc2xpY2UobGFzdExhc3RJbmRleCwgbWF0Y2guaW5kZXgpKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBGaXggYnJvd3NlcnMgd2hvc2UgYGV4ZWNgIG1ldGhvZHMgZG9uJ3QgY29uc2lzdGVudGx5IHJldHVybiBgdW5kZWZpbmVkYCBmb3JcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBub25wYXJ0aWNpcGF0aW5nIGNhcHR1cmluZyBncm91cHNcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoIWNvbXBsaWFudEV4ZWNOcGNnICYmIG1hdGNoLmxlbmd0aCA+IDEpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbWF0Y2hbMF0ucmVwbGFjZShzZXBhcmF0b3IyLCBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBmb3IgKHZhciBpID0gMTsgaSA8IGFyZ3VtZW50cy5sZW5ndGggLSAyOyBpKyspIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoYXJndW1lbnRzW2ldID09PSB1bmRlZikge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBtYXRjaFtpXSA9IHVuZGVmO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChtYXRjaC5sZW5ndGggPiAxICYmIG1hdGNoLmluZGV4IDwgc3RyLmxlbmd0aCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBBcnJheS5wcm90b3R5cGUucHVzaC5hcHBseShvdXRwdXQsIG1hdGNoLnNsaWNlKDEpKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgbGFzdExlbmd0aCA9IG1hdGNoWzBdLmxlbmd0aDtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBsYXN0TGFzdEluZGV4ID0gbGFzdEluZGV4O1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChvdXRwdXQubGVuZ3RoID49IGxpbWl0KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChzZXBhcmF0b3IubGFzdEluZGV4ID09PSBtYXRjaC5pbmRleCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNlcGFyYXRvci5sYXN0SW5kZXgrKzsgLy8gQXZvaWQgYW4gaW5maW5pdGUgbG9vcFxuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIGlmIChsYXN0TGFzdEluZGV4ID09PSBzdHIubGVuZ3RoKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAobGFzdExlbmd0aCB8fCAhc2VwYXJhdG9yLnRlc3QoXCJcIikpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBvdXRwdXQucHVzaChcIlwiKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIG91dHB1dC5wdXNoKHN0ci5zbGljZShsYXN0TGFzdEluZGV4KSk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIG91dHB1dC5sZW5ndGggPiBsaW1pdCA/IG91dHB1dC5zbGljZSgwLCBsaW1pdCkgOiBvdXRwdXQ7XG4gICAgICAgICAgICAgICAgfTtcblxuICAgICAgICAgICAgICAgIHJldHVybiBzZWxmO1xuICAgICAgICAgICAgfSkoKTtcbiAgICAgICAgfSwge31dLCA2OiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge30sIHt9XSwgNzogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHtcbiAgICAgICAgICAgIFwidXNlIHN0cmljdFwiO1xuXG4gICAgICAgICAgICB2YXIgT25lVmVyc2lvbkNvbnN0cmFpbnQgPSByZXF1aXJlKFwiaW5kaXZpZHVhbC9vbmUtdmVyc2lvblwiKTtcblxuICAgICAgICAgICAgdmFyIE1ZX1ZFUlNJT04gPSBcIjdcIjtcbiAgICAgICAgICAgIE9uZVZlcnNpb25Db25zdHJhaW50KFwiZXYtc3RvcmVcIiwgTVlfVkVSU0lPTik7XG5cbiAgICAgICAgICAgIHZhciBoYXNoS2V5ID0gXCJfX0VWX1NUT1JFX0tFWUBcIiArIE1ZX1ZFUlNJT047XG5cbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gRXZTdG9yZTtcblxuICAgICAgICAgICAgZnVuY3Rpb24gRXZTdG9yZShlbGVtKSB7XG4gICAgICAgICAgICAgICAgdmFyIGhhc2ggPSBlbGVtW2hhc2hLZXldO1xuXG4gICAgICAgICAgICAgICAgaWYgKCFoYXNoKSB7XG4gICAgICAgICAgICAgICAgICAgIGhhc2ggPSBlbGVtW2hhc2hLZXldID0ge307XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgcmV0dXJuIGhhc2g7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0sIHsgXCJpbmRpdmlkdWFsL29uZS12ZXJzaW9uXCI6IDkgfV0sIDg6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICAoZnVuY3Rpb24gKGdsb2JhbCkge1xuICAgICAgICAgICAgICAgIFwidXNlIHN0cmljdFwiO1xuXG4gICAgICAgICAgICAgICAgLypnbG9iYWwgd2luZG93LCBnbG9iYWwqL1xuXG4gICAgICAgICAgICAgICAgdmFyIHJvb3QgPSB0eXBlb2Ygd2luZG93ICE9PSBcInVuZGVmaW5lZFwiID8gd2luZG93IDogdHlwZW9mIGdsb2JhbCAhPT0gXCJ1bmRlZmluZWRcIiA/IGdsb2JhbCA6IHt9O1xuXG4gICAgICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBJbmRpdmlkdWFsO1xuXG4gICAgICAgICAgICAgICAgZnVuY3Rpb24gSW5kaXZpZHVhbChrZXksIHZhbHVlKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmIChrZXkgaW4gcm9vdCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHJvb3Rba2V5XTtcbiAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgIHJvb3Rba2V5XSA9IHZhbHVlO1xuXG4gICAgICAgICAgICAgICAgICAgIHJldHVybiB2YWx1ZTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9KS5jYWxsKHRoaXMsIHR5cGVvZiBnbG9iYWwgIT09IFwidW5kZWZpbmVkXCIgPyBnbG9iYWwgOiB0eXBlb2Ygc2VsZiAhPT0gXCJ1bmRlZmluZWRcIiA/IHNlbGYgOiB0eXBlb2Ygd2luZG93ICE9PSBcInVuZGVmaW5lZFwiID8gd2luZG93IDoge30pO1xuICAgICAgICB9LCB7fV0sIDk6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICBcInVzZSBzdHJpY3RcIjtcblxuICAgICAgICAgICAgdmFyIEluZGl2aWR1YWwgPSByZXF1aXJlKFwiLi9pbmRleC5qc1wiKTtcblxuICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBPbmVWZXJzaW9uO1xuXG4gICAgICAgICAgICBmdW5jdGlvbiBPbmVWZXJzaW9uKG1vZHVsZU5hbWUsIHZlcnNpb24sIGRlZmF1bHRWYWx1ZSkge1xuICAgICAgICAgICAgICAgIHZhciBrZXkgPSBcIl9fSU5ESVZJRFVBTF9PTkVfVkVSU0lPTl9cIiArIG1vZHVsZU5hbWU7XG4gICAgICAgICAgICAgICAgdmFyIGVuZm9yY2VLZXkgPSBrZXkgKyBcIl9FTkZPUkNFX1NJTkdMRVRPTlwiO1xuXG4gICAgICAgICAgICAgICAgdmFyIHZlcnNpb25WYWx1ZSA9IEluZGl2aWR1YWwoZW5mb3JjZUtleSwgdmVyc2lvbik7XG5cbiAgICAgICAgICAgICAgICBpZiAodmVyc2lvblZhbHVlICE9PSB2ZXJzaW9uKSB7XG4gICAgICAgICAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcihcIkNhbiBvbmx5IGhhdmUgb25lIGNvcHkgb2YgXCIgKyBtb2R1bGVOYW1lICsgXCIuXFxuXCIgKyBcIllvdSBhbHJlYWR5IGhhdmUgdmVyc2lvbiBcIiArIHZlcnNpb25WYWx1ZSArIFwiIGluc3RhbGxlZC5cXG5cIiArIFwiVGhpcyBtZWFucyB5b3UgY2Fubm90IGluc3RhbGwgdmVyc2lvbiBcIiArIHZlcnNpb24pO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHJldHVybiBJbmRpdmlkdWFsKGtleSwgZGVmYXVsdFZhbHVlKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSwgeyBcIi4vaW5kZXguanNcIjogOCB9XSwgMTA6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICAoZnVuY3Rpb24gKGdsb2JhbCkge1xuICAgICAgICAgICAgICAgIHZhciB0b3BMZXZlbCA9IHR5cGVvZiBnbG9iYWwgIT09IFwidW5kZWZpbmVkXCIgPyBnbG9iYWwgOiB0eXBlb2Ygd2luZG93ICE9PSBcInVuZGVmaW5lZFwiID8gd2luZG93IDoge307XG4gICAgICAgICAgICAgICAgdmFyIG1pbkRvYyA9IHJlcXVpcmUoXCJtaW4tZG9jdW1lbnRcIik7XG5cbiAgICAgICAgICAgICAgICBpZiAodHlwZW9mIGRvY3VtZW50ICE9PSBcInVuZGVmaW5lZFwiKSB7XG4gICAgICAgICAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gZG9jdW1lbnQ7XG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgdmFyIGRvY2N5ID0gdG9wTGV2ZWxbXCJfX0dMT0JBTF9ET0NVTUVOVF9DQUNIRUA0XCJdO1xuXG4gICAgICAgICAgICAgICAgICAgIGlmICghZG9jY3kpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGRvY2N5ID0gdG9wTGV2ZWxbXCJfX0dMT0JBTF9ET0NVTUVOVF9DQUNIRUA0XCJdID0gbWluRG9jO1xuICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBkb2NjeTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9KS5jYWxsKHRoaXMsIHR5cGVvZiBnbG9iYWwgIT09IFwidW5kZWZpbmVkXCIgPyBnbG9iYWwgOiB0eXBlb2Ygc2VsZiAhPT0gXCJ1bmRlZmluZWRcIiA/IHNlbGYgOiB0eXBlb2Ygd2luZG93ICE9PSBcInVuZGVmaW5lZFwiID8gd2luZG93IDoge30pO1xuICAgICAgICB9LCB7IFwibWluLWRvY3VtZW50XCI6IDYgfV0sIDExOiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge1xuICAgICAgICAgICAgXCJ1c2Ugc3RyaWN0XCI7XG5cbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gaXNPYmplY3QoeCkge1xuICAgICAgICAgICAgICAgIHJldHVybiB0eXBlb2YgeCA9PT0gXCJvYmplY3RcIiAmJiB4ICE9PSBudWxsO1xuICAgICAgICAgICAgfTtcbiAgICAgICAgfSwge31dLCAxMjogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHtcbiAgICAgICAgICAgIHZhciBuYXRpdmVJc0FycmF5ID0gQXJyYXkuaXNBcnJheTtcbiAgICAgICAgICAgIHZhciB0b1N0cmluZyA9IE9iamVjdC5wcm90b3R5cGUudG9TdHJpbmc7XG5cbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gbmF0aXZlSXNBcnJheSB8fCBpc0FycmF5O1xuXG4gICAgICAgICAgICBmdW5jdGlvbiBpc0FycmF5KG9iaikge1xuICAgICAgICAgICAgICAgIHJldHVybiB0b1N0cmluZy5jYWxsKG9iaikgPT09IFwiW29iamVjdCBBcnJheV1cIjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSwge31dLCAxMzogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHtcbiAgICAgICAgICAgIHZhciBwYXRjaCA9IHJlcXVpcmUoXCIuL3Zkb20vcGF0Y2guanNcIik7XG5cbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gcGF0Y2g7XG4gICAgICAgIH0sIHsgXCIuL3Zkb20vcGF0Y2guanNcIjogMTggfV0sIDE0OiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge1xuICAgICAgICAgICAgdmFyIGlzT2JqZWN0ID0gcmVxdWlyZShcImlzLW9iamVjdFwiKTtcbiAgICAgICAgICAgIHZhciBpc0hvb2sgPSByZXF1aXJlKFwiLi4vdm5vZGUvaXMtdmhvb2suanNcIik7XG5cbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gYXBwbHlQcm9wZXJ0aWVzO1xuXG4gICAgICAgICAgICBmdW5jdGlvbiBhcHBseVByb3BlcnRpZXMobm9kZSwgcHJvcHMsIHByZXZpb3VzKSB7XG4gICAgICAgICAgICAgICAgZm9yICh2YXIgcHJvcE5hbWUgaW4gcHJvcHMpIHtcbiAgICAgICAgICAgICAgICAgICAgdmFyIHByb3BWYWx1ZSA9IHByb3BzW3Byb3BOYW1lXTtcblxuICAgICAgICAgICAgICAgICAgICBpZiAocHJvcFZhbHVlID09PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJlbW92ZVByb3BlcnR5KG5vZGUsIHByb3BOYW1lLCBwcm9wVmFsdWUsIHByZXZpb3VzKTtcbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIGlmIChpc0hvb2socHJvcFZhbHVlKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgcmVtb3ZlUHJvcGVydHkobm9kZSwgcHJvcE5hbWUsIHByb3BWYWx1ZSwgcHJldmlvdXMpO1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHByb3BWYWx1ZS5ob29rKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcHJvcFZhbHVlLmhvb2sobm9kZSwgcHJvcE5hbWUsIHByZXZpb3VzID8gcHJldmlvdXNbcHJvcE5hbWVdIDogdW5kZWZpbmVkKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChpc09iamVjdChwcm9wVmFsdWUpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcGF0Y2hPYmplY3Qobm9kZSwgcHJvcHMsIHByZXZpb3VzLCBwcm9wTmFtZSwgcHJvcFZhbHVlKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgbm9kZVtwcm9wTmFtZV0gPSBwcm9wVmFsdWU7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIHJlbW92ZVByb3BlcnR5KG5vZGUsIHByb3BOYW1lLCBwcm9wVmFsdWUsIHByZXZpb3VzKSB7XG4gICAgICAgICAgICAgICAgaWYgKHByZXZpb3VzKSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciBwcmV2aW91c1ZhbHVlID0gcHJldmlvdXNbcHJvcE5hbWVdO1xuXG4gICAgICAgICAgICAgICAgICAgIGlmICghaXNIb29rKHByZXZpb3VzVmFsdWUpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAocHJvcE5hbWUgPT09IFwiYXR0cmlidXRlc1wiKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgZm9yICh2YXIgYXR0ck5hbWUgaW4gcHJldmlvdXNWYWx1ZSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBub2RlLnJlbW92ZUF0dHJpYnV0ZShhdHRyTmFtZSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIGlmIChwcm9wTmFtZSA9PT0gXCJzdHlsZVwiKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgZm9yICh2YXIgaSBpbiBwcmV2aW91c1ZhbHVlKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG5vZGUuc3R5bGVbaV0gPSBcIlwiO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAodHlwZW9mIHByZXZpb3VzVmFsdWUgPT09IFwic3RyaW5nXCIpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBub2RlW3Byb3BOYW1lXSA9IFwiXCI7XG4gICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIG5vZGVbcHJvcE5hbWVdID0gbnVsbDtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIGlmIChwcmV2aW91c1ZhbHVlLnVuaG9vaykge1xuICAgICAgICAgICAgICAgICAgICAgICAgcHJldmlvdXNWYWx1ZS51bmhvb2sobm9kZSwgcHJvcE5hbWUsIHByb3BWYWx1ZSk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIHBhdGNoT2JqZWN0KG5vZGUsIHByb3BzLCBwcmV2aW91cywgcHJvcE5hbWUsIHByb3BWYWx1ZSkge1xuICAgICAgICAgICAgICAgIHZhciBwcmV2aW91c1ZhbHVlID0gcHJldmlvdXMgPyBwcmV2aW91c1twcm9wTmFtZV0gOiB1bmRlZmluZWQ7XG5cbiAgICAgICAgICAgICAgICAvLyBTZXQgYXR0cmlidXRlc1xuICAgICAgICAgICAgICAgIGlmIChwcm9wTmFtZSA9PT0gXCJhdHRyaWJ1dGVzXCIpIHtcbiAgICAgICAgICAgICAgICAgICAgZm9yICh2YXIgYXR0ck5hbWUgaW4gcHJvcFZhbHVlKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICB2YXIgYXR0clZhbHVlID0gcHJvcFZhbHVlW2F0dHJOYW1lXTtcblxuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGF0dHJWYWx1ZSA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgbm9kZS5yZW1vdmVBdHRyaWJ1dGUoYXR0ck5hbWUpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBub2RlLnNldEF0dHJpYnV0ZShhdHRyTmFtZSwgYXR0clZhbHVlKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICBpZiAocHJldmlvdXNWYWx1ZSAmJiBpc09iamVjdChwcmV2aW91c1ZhbHVlKSAmJiBnZXRQcm90b3R5cGUocHJldmlvdXNWYWx1ZSkgIT09IGdldFByb3RvdHlwZShwcm9wVmFsdWUpKSB7XG4gICAgICAgICAgICAgICAgICAgIG5vZGVbcHJvcE5hbWVdID0gcHJvcFZhbHVlO1xuICAgICAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgaWYgKCFpc09iamVjdChub2RlW3Byb3BOYW1lXSkpIHtcbiAgICAgICAgICAgICAgICAgICAgbm9kZVtwcm9wTmFtZV0gPSB7fTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICB2YXIgcmVwbGFjZXIgPSBwcm9wTmFtZSA9PT0gXCJzdHlsZVwiID8gXCJcIiA6IHVuZGVmaW5lZDtcblxuICAgICAgICAgICAgICAgIGZvciAodmFyIGsgaW4gcHJvcFZhbHVlKSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciB2YWx1ZSA9IHByb3BWYWx1ZVtrXTtcbiAgICAgICAgICAgICAgICAgICAgbm9kZVtwcm9wTmFtZV1ba10gPSB2YWx1ZSA9PT0gdW5kZWZpbmVkID8gcmVwbGFjZXIgOiB2YWx1ZTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIGdldFByb3RvdHlwZSh2YWx1ZSkge1xuICAgICAgICAgICAgICAgIGlmIChPYmplY3QuZ2V0UHJvdG90eXBlT2YpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIE9iamVjdC5nZXRQcm90b3R5cGVPZih2YWx1ZSk7XG4gICAgICAgICAgICAgICAgfSBlbHNlIGlmICh2YWx1ZS5fX3Byb3RvX18pIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHZhbHVlLl9fcHJvdG9fXztcbiAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKHZhbHVlLmNvbnN0cnVjdG9yKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiB2YWx1ZS5jb25zdHJ1Y3Rvci5wcm90b3R5cGU7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9LCB7IFwiLi4vdm5vZGUvaXMtdmhvb2suanNcIjogMjYsIFwiaXMtb2JqZWN0XCI6IDExIH1dLCAxNTogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHtcbiAgICAgICAgICAgIHZhciBkb2N1bWVudCA9IHJlcXVpcmUoXCJnbG9iYWwvZG9jdW1lbnRcIik7XG5cbiAgICAgICAgICAgIHZhciBhcHBseVByb3BlcnRpZXMgPSByZXF1aXJlKFwiLi9hcHBseS1wcm9wZXJ0aWVzXCIpO1xuXG4gICAgICAgICAgICB2YXIgaXNWTm9kZSA9IHJlcXVpcmUoXCIuLi92bm9kZS9pcy12bm9kZS5qc1wiKTtcbiAgICAgICAgICAgIHZhciBpc1ZUZXh0ID0gcmVxdWlyZShcIi4uL3Zub2RlL2lzLXZ0ZXh0LmpzXCIpO1xuICAgICAgICAgICAgdmFyIGlzV2lkZ2V0ID0gcmVxdWlyZShcIi4uL3Zub2RlL2lzLXdpZGdldC5qc1wiKTtcbiAgICAgICAgICAgIHZhciBoYW5kbGVUaHVuayA9IHJlcXVpcmUoXCIuLi92bm9kZS9oYW5kbGUtdGh1bmsuanNcIik7XG5cbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gY3JlYXRlRWxlbWVudDtcblxuICAgICAgICAgICAgZnVuY3Rpb24gY3JlYXRlRWxlbWVudCh2bm9kZSwgb3B0cykge1xuICAgICAgICAgICAgICAgIHZhciBkb2MgPSBvcHRzID8gb3B0cy5kb2N1bWVudCB8fCBkb2N1bWVudCA6IGRvY3VtZW50O1xuICAgICAgICAgICAgICAgIHZhciB3YXJuID0gb3B0cyA/IG9wdHMud2FybiA6IG51bGw7XG5cbiAgICAgICAgICAgICAgICB2bm9kZSA9IGhhbmRsZVRodW5rKHZub2RlKS5hO1xuXG4gICAgICAgICAgICAgICAgaWYgKGlzV2lkZ2V0KHZub2RlKSkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gdm5vZGUuaW5pdCgpO1xuICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoaXNWVGV4dCh2bm9kZSkpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGRvYy5jcmVhdGVUZXh0Tm9kZSh2bm9kZS50ZXh0KTtcbiAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKCFpc1ZOb2RlKHZub2RlKSkge1xuICAgICAgICAgICAgICAgICAgICBpZiAod2Fybikge1xuICAgICAgICAgICAgICAgICAgICAgICAgd2FybihcIkl0ZW0gaXMgbm90IGEgdmFsaWQgdmlydHVhbCBkb20gbm9kZVwiLCB2bm9kZSk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIG51bGw7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgdmFyIG5vZGUgPSB2bm9kZS5uYW1lc3BhY2UgPT09IG51bGwgPyBkb2MuY3JlYXRlRWxlbWVudCh2bm9kZS50YWdOYW1lKSA6IGRvYy5jcmVhdGVFbGVtZW50TlModm5vZGUubmFtZXNwYWNlLCB2bm9kZS50YWdOYW1lKTtcblxuICAgICAgICAgICAgICAgIHZhciBwcm9wcyA9IHZub2RlLnByb3BlcnRpZXM7XG4gICAgICAgICAgICAgICAgYXBwbHlQcm9wZXJ0aWVzKG5vZGUsIHByb3BzKTtcblxuICAgICAgICAgICAgICAgIHZhciBjaGlsZHJlbiA9IHZub2RlLmNoaWxkcmVuO1xuXG4gICAgICAgICAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCBjaGlsZHJlbi5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgICAgICAgICB2YXIgY2hpbGROb2RlID0gY3JlYXRlRWxlbWVudChjaGlsZHJlbltpXSwgb3B0cyk7XG4gICAgICAgICAgICAgICAgICAgIGlmIChjaGlsZE5vZGUpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIG5vZGUuYXBwZW5kQ2hpbGQoY2hpbGROb2RlKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHJldHVybiBub2RlO1xuICAgICAgICAgICAgfVxuICAgICAgICB9LCB7IFwiLi4vdm5vZGUvaGFuZGxlLXRodW5rLmpzXCI6IDI0LCBcIi4uL3Zub2RlL2lzLXZub2RlLmpzXCI6IDI3LCBcIi4uL3Zub2RlL2lzLXZ0ZXh0LmpzXCI6IDI4LCBcIi4uL3Zub2RlL2lzLXdpZGdldC5qc1wiOiAyOSwgXCIuL2FwcGx5LXByb3BlcnRpZXNcIjogMTQsIFwiZ2xvYmFsL2RvY3VtZW50XCI6IDEwIH1dLCAxNjogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHtcbiAgICAgICAgICAgIC8vIE1hcHMgYSB2aXJ0dWFsIERPTSB0cmVlIG9udG8gYSByZWFsIERPTSB0cmVlIGluIGFuIGVmZmljaWVudCBtYW5uZXIuXG4gICAgICAgICAgICAvLyBXZSBkb24ndCB3YW50IHRvIHJlYWQgYWxsIG9mIHRoZSBET00gbm9kZXMgaW4gdGhlIHRyZWUgc28gd2UgdXNlXG4gICAgICAgICAgICAvLyB0aGUgaW4tb3JkZXIgdHJlZSBpbmRleGluZyB0byBlbGltaW5hdGUgcmVjdXJzaW9uIGRvd24gY2VydGFpbiBicmFuY2hlcy5cbiAgICAgICAgICAgIC8vIFdlIG9ubHkgcmVjdXJzZSBpbnRvIGEgRE9NIG5vZGUgaWYgd2Uga25vdyB0aGF0IGl0IGNvbnRhaW5zIGEgY2hpbGQgb2ZcbiAgICAgICAgICAgIC8vIGludGVyZXN0LlxuXG4gICAgICAgICAgICB2YXIgbm9DaGlsZCA9IHt9O1xuXG4gICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IGRvbUluZGV4O1xuXG4gICAgICAgICAgICBmdW5jdGlvbiBkb21JbmRleChyb290Tm9kZSwgdHJlZSwgaW5kaWNlcywgbm9kZXMpIHtcbiAgICAgICAgICAgICAgICBpZiAoIWluZGljZXMgfHwgaW5kaWNlcy5sZW5ndGggPT09IDApIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHt9O1xuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIGluZGljZXMuc29ydChhc2NlbmRpbmcpO1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gcmVjdXJzZShyb290Tm9kZSwgdHJlZSwgaW5kaWNlcywgbm9kZXMsIDApO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZnVuY3Rpb24gcmVjdXJzZShyb290Tm9kZSwgdHJlZSwgaW5kaWNlcywgbm9kZXMsIHJvb3RJbmRleCkge1xuICAgICAgICAgICAgICAgIG5vZGVzID0gbm9kZXMgfHwge307XG5cbiAgICAgICAgICAgICAgICBpZiAocm9vdE5vZGUpIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKGluZGV4SW5SYW5nZShpbmRpY2VzLCByb290SW5kZXgsIHJvb3RJbmRleCkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIG5vZGVzW3Jvb3RJbmRleF0gPSByb290Tm9kZTtcbiAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgIHZhciB2Q2hpbGRyZW4gPSB0cmVlLmNoaWxkcmVuO1xuXG4gICAgICAgICAgICAgICAgICAgIGlmICh2Q2hpbGRyZW4pIHtcblxuICAgICAgICAgICAgICAgICAgICAgICAgdmFyIGNoaWxkTm9kZXMgPSByb290Tm9kZS5jaGlsZE5vZGVzO1xuXG4gICAgICAgICAgICAgICAgICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IHRyZWUuY2hpbGRyZW4ubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICByb290SW5kZXggKz0gMTtcblxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZhciB2Q2hpbGQgPSB2Q2hpbGRyZW5baV0gfHwgbm9DaGlsZDtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB2YXIgbmV4dEluZGV4ID0gcm9vdEluZGV4ICsgKHZDaGlsZC5jb3VudCB8fCAwKTtcblxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIHNraXAgcmVjdXJzaW9uIGRvd24gdGhlIHRyZWUgaWYgdGhlcmUgYXJlIG5vIG5vZGVzIGRvd24gaGVyZVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChpbmRleEluUmFuZ2UoaW5kaWNlcywgcm9vdEluZGV4LCBuZXh0SW5kZXgpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlY3Vyc2UoY2hpbGROb2Rlc1tpXSwgdkNoaWxkLCBpbmRpY2VzLCBub2Rlcywgcm9vdEluZGV4KTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICByb290SW5kZXggPSBuZXh0SW5kZXg7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICByZXR1cm4gbm9kZXM7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIC8vIEJpbmFyeSBzZWFyY2ggZm9yIGFuIGluZGV4IGluIHRoZSBpbnRlcnZhbCBbbGVmdCwgcmlnaHRdXG4gICAgICAgICAgICBmdW5jdGlvbiBpbmRleEluUmFuZ2UoaW5kaWNlcywgbGVmdCwgcmlnaHQpIHtcbiAgICAgICAgICAgICAgICBpZiAoaW5kaWNlcy5sZW5ndGggPT09IDApIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHZhciBtaW5JbmRleCA9IDA7XG4gICAgICAgICAgICAgICAgdmFyIG1heEluZGV4ID0gaW5kaWNlcy5sZW5ndGggLSAxO1xuICAgICAgICAgICAgICAgIHZhciBjdXJyZW50SW5kZXg7XG4gICAgICAgICAgICAgICAgdmFyIGN1cnJlbnRJdGVtO1xuXG4gICAgICAgICAgICAgICAgd2hpbGUgKG1pbkluZGV4IDw9IG1heEluZGV4KSB7XG4gICAgICAgICAgICAgICAgICAgIGN1cnJlbnRJbmRleCA9IChtYXhJbmRleCArIG1pbkluZGV4KSAvIDIgPj4gMDtcbiAgICAgICAgICAgICAgICAgICAgY3VycmVudEl0ZW0gPSBpbmRpY2VzW2N1cnJlbnRJbmRleF07XG5cbiAgICAgICAgICAgICAgICAgICAgaWYgKG1pbkluZGV4ID09PSBtYXhJbmRleCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGN1cnJlbnRJdGVtID49IGxlZnQgJiYgY3VycmVudEl0ZW0gPD0gcmlnaHQ7XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoY3VycmVudEl0ZW0gPCBsZWZ0KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBtaW5JbmRleCA9IGN1cnJlbnRJbmRleCArIDE7XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoY3VycmVudEl0ZW0gPiByaWdodCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgbWF4SW5kZXggPSBjdXJyZW50SW5kZXggLSAxO1xuICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIGFzY2VuZGluZyhhLCBiKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGEgPiBiID8gMSA6IC0xO1xuICAgICAgICAgICAgfVxuICAgICAgICB9LCB7fV0sIDE3OiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge1xuICAgICAgICAgICAgdmFyIGFwcGx5UHJvcGVydGllcyA9IHJlcXVpcmUoXCIuL2FwcGx5LXByb3BlcnRpZXNcIik7XG5cbiAgICAgICAgICAgIHZhciBpc1dpZGdldCA9IHJlcXVpcmUoXCIuLi92bm9kZS9pcy13aWRnZXQuanNcIik7XG4gICAgICAgICAgICB2YXIgVlBhdGNoID0gcmVxdWlyZShcIi4uL3Zub2RlL3ZwYXRjaC5qc1wiKTtcblxuICAgICAgICAgICAgdmFyIHVwZGF0ZVdpZGdldCA9IHJlcXVpcmUoXCIuL3VwZGF0ZS13aWRnZXRcIik7XG5cbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gYXBwbHlQYXRjaDtcblxuICAgICAgICAgICAgZnVuY3Rpb24gYXBwbHlQYXRjaCh2cGF0Y2gsIGRvbU5vZGUsIHJlbmRlck9wdGlvbnMpIHtcbiAgICAgICAgICAgICAgICB2YXIgdHlwZSA9IHZwYXRjaC50eXBlO1xuICAgICAgICAgICAgICAgIHZhciB2Tm9kZSA9IHZwYXRjaC52Tm9kZTtcbiAgICAgICAgICAgICAgICB2YXIgcGF0Y2ggPSB2cGF0Y2gucGF0Y2g7XG5cbiAgICAgICAgICAgICAgICBzd2l0Y2ggKHR5cGUpIHtcbiAgICAgICAgICAgICAgICAgICAgY2FzZSBWUGF0Y2guUkVNT1ZFOlxuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHJlbW92ZU5vZGUoZG9tTm9kZSwgdk5vZGUpO1xuICAgICAgICAgICAgICAgICAgICBjYXNlIFZQYXRjaC5JTlNFUlQ6XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gaW5zZXJ0Tm9kZShkb21Ob2RlLCBwYXRjaCwgcmVuZGVyT3B0aW9ucyk7XG4gICAgICAgICAgICAgICAgICAgIGNhc2UgVlBhdGNoLlZURVhUOlxuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHN0cmluZ1BhdGNoKGRvbU5vZGUsIHZOb2RlLCBwYXRjaCwgcmVuZGVyT3B0aW9ucyk7XG4gICAgICAgICAgICAgICAgICAgIGNhc2UgVlBhdGNoLldJREdFVDpcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiB3aWRnZXRQYXRjaChkb21Ob2RlLCB2Tm9kZSwgcGF0Y2gsIHJlbmRlck9wdGlvbnMpO1xuICAgICAgICAgICAgICAgICAgICBjYXNlIFZQYXRjaC5WTk9ERTpcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiB2Tm9kZVBhdGNoKGRvbU5vZGUsIHZOb2RlLCBwYXRjaCwgcmVuZGVyT3B0aW9ucyk7XG4gICAgICAgICAgICAgICAgICAgIGNhc2UgVlBhdGNoLk9SREVSOlxuICAgICAgICAgICAgICAgICAgICAgICAgcmVvcmRlckNoaWxkcmVuKGRvbU5vZGUsIHBhdGNoKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBkb21Ob2RlO1xuICAgICAgICAgICAgICAgICAgICBjYXNlIFZQYXRjaC5QUk9QUzpcbiAgICAgICAgICAgICAgICAgICAgICAgIGFwcGx5UHJvcGVydGllcyhkb21Ob2RlLCBwYXRjaCwgdk5vZGUucHJvcGVydGllcyk7XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gZG9tTm9kZTtcbiAgICAgICAgICAgICAgICAgICAgY2FzZSBWUGF0Y2guVEhVTks6XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gcmVwbGFjZVJvb3QoZG9tTm9kZSwgcmVuZGVyT3B0aW9ucy5wYXRjaChkb21Ob2RlLCBwYXRjaCwgcmVuZGVyT3B0aW9ucykpO1xuICAgICAgICAgICAgICAgICAgICBkZWZhdWx0OlxuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGRvbU5vZGU7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBmdW5jdGlvbiByZW1vdmVOb2RlKGRvbU5vZGUsIHZOb2RlKSB7XG4gICAgICAgICAgICAgICAgdmFyIHBhcmVudE5vZGUgPSBkb21Ob2RlLnBhcmVudE5vZGU7XG5cbiAgICAgICAgICAgICAgICBpZiAocGFyZW50Tm9kZSkge1xuICAgICAgICAgICAgICAgICAgICBwYXJlbnROb2RlLnJlbW92ZUNoaWxkKGRvbU5vZGUpO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIGRlc3Ryb3lXaWRnZXQoZG9tTm9kZSwgdk5vZGUpO1xuXG4gICAgICAgICAgICAgICAgcmV0dXJuIG51bGw7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIGluc2VydE5vZGUocGFyZW50Tm9kZSwgdk5vZGUsIHJlbmRlck9wdGlvbnMpIHtcbiAgICAgICAgICAgICAgICB2YXIgbmV3Tm9kZSA9IHJlbmRlck9wdGlvbnMucmVuZGVyKHZOb2RlLCByZW5kZXJPcHRpb25zKTtcblxuICAgICAgICAgICAgICAgIGlmIChwYXJlbnROb2RlKSB7XG4gICAgICAgICAgICAgICAgICAgIHBhcmVudE5vZGUuYXBwZW5kQ2hpbGQobmV3Tm9kZSk7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgcmV0dXJuIHBhcmVudE5vZGU7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIHN0cmluZ1BhdGNoKGRvbU5vZGUsIGxlZnRWTm9kZSwgdlRleHQsIHJlbmRlck9wdGlvbnMpIHtcbiAgICAgICAgICAgICAgICB2YXIgbmV3Tm9kZTtcblxuICAgICAgICAgICAgICAgIGlmIChkb21Ob2RlLm5vZGVUeXBlID09PSAzKSB7XG4gICAgICAgICAgICAgICAgICAgIGRvbU5vZGUucmVwbGFjZURhdGEoMCwgZG9tTm9kZS5sZW5ndGgsIHZUZXh0LnRleHQpO1xuICAgICAgICAgICAgICAgICAgICBuZXdOb2RlID0gZG9tTm9kZTtcbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICB2YXIgcGFyZW50Tm9kZSA9IGRvbU5vZGUucGFyZW50Tm9kZTtcbiAgICAgICAgICAgICAgICAgICAgbmV3Tm9kZSA9IHJlbmRlck9wdGlvbnMucmVuZGVyKHZUZXh0LCByZW5kZXJPcHRpb25zKTtcblxuICAgICAgICAgICAgICAgICAgICBpZiAocGFyZW50Tm9kZSAmJiBuZXdOb2RlICE9PSBkb21Ob2RlKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBwYXJlbnROb2RlLnJlcGxhY2VDaGlsZChuZXdOb2RlLCBkb21Ob2RlKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHJldHVybiBuZXdOb2RlO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBmdW5jdGlvbiB3aWRnZXRQYXRjaChkb21Ob2RlLCBsZWZ0Vk5vZGUsIHdpZGdldCwgcmVuZGVyT3B0aW9ucykge1xuICAgICAgICAgICAgICAgIHZhciB1cGRhdGluZyA9IHVwZGF0ZVdpZGdldChsZWZ0Vk5vZGUsIHdpZGdldCk7XG4gICAgICAgICAgICAgICAgdmFyIG5ld05vZGU7XG5cbiAgICAgICAgICAgICAgICBpZiAodXBkYXRpbmcpIHtcbiAgICAgICAgICAgICAgICAgICAgbmV3Tm9kZSA9IHdpZGdldC51cGRhdGUobGVmdFZOb2RlLCBkb21Ob2RlKSB8fCBkb21Ob2RlO1xuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIG5ld05vZGUgPSByZW5kZXJPcHRpb25zLnJlbmRlcih3aWRnZXQsIHJlbmRlck9wdGlvbnMpO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHZhciBwYXJlbnROb2RlID0gZG9tTm9kZS5wYXJlbnROb2RlO1xuXG4gICAgICAgICAgICAgICAgaWYgKHBhcmVudE5vZGUgJiYgbmV3Tm9kZSAhPT0gZG9tTm9kZSkge1xuICAgICAgICAgICAgICAgICAgICBwYXJlbnROb2RlLnJlcGxhY2VDaGlsZChuZXdOb2RlLCBkb21Ob2RlKTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICBpZiAoIXVwZGF0aW5nKSB7XG4gICAgICAgICAgICAgICAgICAgIGRlc3Ryb3lXaWRnZXQoZG9tTm9kZSwgbGVmdFZOb2RlKTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICByZXR1cm4gbmV3Tm9kZTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZnVuY3Rpb24gdk5vZGVQYXRjaChkb21Ob2RlLCBsZWZ0Vk5vZGUsIHZOb2RlLCByZW5kZXJPcHRpb25zKSB7XG4gICAgICAgICAgICAgICAgdmFyIHBhcmVudE5vZGUgPSBkb21Ob2RlLnBhcmVudE5vZGU7XG4gICAgICAgICAgICAgICAgdmFyIG5ld05vZGUgPSByZW5kZXJPcHRpb25zLnJlbmRlcih2Tm9kZSwgcmVuZGVyT3B0aW9ucyk7XG5cbiAgICAgICAgICAgICAgICBpZiAocGFyZW50Tm9kZSAmJiBuZXdOb2RlICE9PSBkb21Ob2RlKSB7XG4gICAgICAgICAgICAgICAgICAgIHBhcmVudE5vZGUucmVwbGFjZUNoaWxkKG5ld05vZGUsIGRvbU5vZGUpO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHJldHVybiBuZXdOb2RlO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBmdW5jdGlvbiBkZXN0cm95V2lkZ2V0KGRvbU5vZGUsIHcpIHtcbiAgICAgICAgICAgICAgICBpZiAodHlwZW9mIHcuZGVzdHJveSA9PT0gXCJmdW5jdGlvblwiICYmIGlzV2lkZ2V0KHcpKSB7XG4gICAgICAgICAgICAgICAgICAgIHcuZGVzdHJveShkb21Ob2RlKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIHJlb3JkZXJDaGlsZHJlbihkb21Ob2RlLCBtb3Zlcykge1xuICAgICAgICAgICAgICAgIHZhciBjaGlsZE5vZGVzID0gZG9tTm9kZS5jaGlsZE5vZGVzO1xuICAgICAgICAgICAgICAgIHZhciBrZXlNYXAgPSB7fTtcbiAgICAgICAgICAgICAgICB2YXIgbm9kZTtcbiAgICAgICAgICAgICAgICB2YXIgcmVtb3ZlO1xuICAgICAgICAgICAgICAgIHZhciBpbnNlcnQ7XG5cbiAgICAgICAgICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IG1vdmVzLnJlbW92ZXMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgICAgICAgICAgcmVtb3ZlID0gbW92ZXMucmVtb3Zlc1tpXTtcbiAgICAgICAgICAgICAgICAgICAgbm9kZSA9IGNoaWxkTm9kZXNbcmVtb3ZlLmZyb21dO1xuICAgICAgICAgICAgICAgICAgICBpZiAocmVtb3ZlLmtleSkge1xuICAgICAgICAgICAgICAgICAgICAgICAga2V5TWFwW3JlbW92ZS5rZXldID0gbm9kZTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICBkb21Ob2RlLnJlbW92ZUNoaWxkKG5vZGUpO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHZhciBsZW5ndGggPSBjaGlsZE5vZGVzLmxlbmd0aDtcbiAgICAgICAgICAgICAgICBmb3IgKHZhciBqID0gMDsgaiA8IG1vdmVzLmluc2VydHMubGVuZ3RoOyBqKyspIHtcbiAgICAgICAgICAgICAgICAgICAgaW5zZXJ0ID0gbW92ZXMuaW5zZXJ0c1tqXTtcbiAgICAgICAgICAgICAgICAgICAgbm9kZSA9IGtleU1hcFtpbnNlcnQua2V5XTtcbiAgICAgICAgICAgICAgICAgICAgLy8gdGhpcyBpcyB0aGUgd2VpcmRlc3QgYnVnIGkndmUgZXZlciBzZWVuIGluIHdlYmtpdFxuICAgICAgICAgICAgICAgICAgICBkb21Ob2RlLmluc2VydEJlZm9yZShub2RlLCBpbnNlcnQudG8gPj0gbGVuZ3RoKysgPyBudWxsIDogY2hpbGROb2Rlc1tpbnNlcnQudG9dKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIHJlcGxhY2VSb290KG9sZFJvb3QsIG5ld1Jvb3QpIHtcbiAgICAgICAgICAgICAgICBpZiAob2xkUm9vdCAmJiBuZXdSb290ICYmIG9sZFJvb3QgIT09IG5ld1Jvb3QgJiYgb2xkUm9vdC5wYXJlbnROb2RlKSB7XG4gICAgICAgICAgICAgICAgICAgIG9sZFJvb3QucGFyZW50Tm9kZS5yZXBsYWNlQ2hpbGQobmV3Um9vdCwgb2xkUm9vdCk7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgcmV0dXJuIG5ld1Jvb3Q7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0sIHsgXCIuLi92bm9kZS9pcy13aWRnZXQuanNcIjogMjksIFwiLi4vdm5vZGUvdnBhdGNoLmpzXCI6IDMyLCBcIi4vYXBwbHktcHJvcGVydGllc1wiOiAxNCwgXCIuL3VwZGF0ZS13aWRnZXRcIjogMTkgfV0sIDE4OiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge1xuICAgICAgICAgICAgdmFyIGRvY3VtZW50ID0gcmVxdWlyZShcImdsb2JhbC9kb2N1bWVudFwiKTtcbiAgICAgICAgICAgIHZhciBpc0FycmF5ID0gcmVxdWlyZShcIngtaXMtYXJyYXlcIik7XG5cbiAgICAgICAgICAgIHZhciByZW5kZXIgPSByZXF1aXJlKFwiLi9jcmVhdGUtZWxlbWVudFwiKTtcbiAgICAgICAgICAgIHZhciBkb21JbmRleCA9IHJlcXVpcmUoXCIuL2RvbS1pbmRleFwiKTtcbiAgICAgICAgICAgIHZhciBwYXRjaE9wID0gcmVxdWlyZShcIi4vcGF0Y2gtb3BcIik7XG4gICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IHBhdGNoO1xuXG4gICAgICAgICAgICBmdW5jdGlvbiBwYXRjaChyb290Tm9kZSwgcGF0Y2hlcywgcmVuZGVyT3B0aW9ucykge1xuICAgICAgICAgICAgICAgIHJlbmRlck9wdGlvbnMgPSByZW5kZXJPcHRpb25zIHx8IHt9O1xuICAgICAgICAgICAgICAgIHJlbmRlck9wdGlvbnMucGF0Y2ggPSByZW5kZXJPcHRpb25zLnBhdGNoICYmIHJlbmRlck9wdGlvbnMucGF0Y2ggIT09IHBhdGNoID8gcmVuZGVyT3B0aW9ucy5wYXRjaCA6IHBhdGNoUmVjdXJzaXZlO1xuICAgICAgICAgICAgICAgIHJlbmRlck9wdGlvbnMucmVuZGVyID0gcmVuZGVyT3B0aW9ucy5yZW5kZXIgfHwgcmVuZGVyO1xuXG4gICAgICAgICAgICAgICAgcmV0dXJuIHJlbmRlck9wdGlvbnMucGF0Y2gocm9vdE5vZGUsIHBhdGNoZXMsIHJlbmRlck9wdGlvbnMpO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBmdW5jdGlvbiBwYXRjaFJlY3Vyc2l2ZShyb290Tm9kZSwgcGF0Y2hlcywgcmVuZGVyT3B0aW9ucykge1xuICAgICAgICAgICAgICAgIHZhciBpbmRpY2VzID0gcGF0Y2hJbmRpY2VzKHBhdGNoZXMpO1xuXG4gICAgICAgICAgICAgICAgaWYgKGluZGljZXMubGVuZ3RoID09PSAwKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiByb290Tm9kZTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICB2YXIgaW5kZXggPSBkb21JbmRleChyb290Tm9kZSwgcGF0Y2hlcy5hLCBpbmRpY2VzKTtcbiAgICAgICAgICAgICAgICB2YXIgb3duZXJEb2N1bWVudCA9IHJvb3ROb2RlLm93bmVyRG9jdW1lbnQ7XG5cbiAgICAgICAgICAgICAgICBpZiAoIXJlbmRlck9wdGlvbnMuZG9jdW1lbnQgJiYgb3duZXJEb2N1bWVudCAhPT0gZG9jdW1lbnQpIHtcbiAgICAgICAgICAgICAgICAgICAgcmVuZGVyT3B0aW9ucy5kb2N1bWVudCA9IG93bmVyRG9jdW1lbnQ7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCBpbmRpY2VzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciBub2RlSW5kZXggPSBpbmRpY2VzW2ldO1xuICAgICAgICAgICAgICAgICAgICByb290Tm9kZSA9IGFwcGx5UGF0Y2gocm9vdE5vZGUsIGluZGV4W25vZGVJbmRleF0sIHBhdGNoZXNbbm9kZUluZGV4XSwgcmVuZGVyT3B0aW9ucyk7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgcmV0dXJuIHJvb3ROb2RlO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBmdW5jdGlvbiBhcHBseVBhdGNoKHJvb3ROb2RlLCBkb21Ob2RlLCBwYXRjaExpc3QsIHJlbmRlck9wdGlvbnMpIHtcbiAgICAgICAgICAgICAgICBpZiAoIWRvbU5vZGUpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHJvb3ROb2RlO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHZhciBuZXdOb2RlO1xuXG4gICAgICAgICAgICAgICAgaWYgKGlzQXJyYXkocGF0Y2hMaXN0KSkge1xuICAgICAgICAgICAgICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IHBhdGNoTGlzdC5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgICAgICAgICAgICAgbmV3Tm9kZSA9IHBhdGNoT3AocGF0Y2hMaXN0W2ldLCBkb21Ob2RlLCByZW5kZXJPcHRpb25zKTtcblxuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGRvbU5vZGUgPT09IHJvb3ROb2RlKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcm9vdE5vZGUgPSBuZXdOb2RlO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgbmV3Tm9kZSA9IHBhdGNoT3AocGF0Y2hMaXN0LCBkb21Ob2RlLCByZW5kZXJPcHRpb25zKTtcblxuICAgICAgICAgICAgICAgICAgICBpZiAoZG9tTm9kZSA9PT0gcm9vdE5vZGUpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJvb3ROb2RlID0gbmV3Tm9kZTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHJldHVybiByb290Tm9kZTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZnVuY3Rpb24gcGF0Y2hJbmRpY2VzKHBhdGNoZXMpIHtcbiAgICAgICAgICAgICAgICB2YXIgaW5kaWNlcyA9IFtdO1xuXG4gICAgICAgICAgICAgICAgZm9yICh2YXIga2V5IGluIHBhdGNoZXMpIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKGtleSAhPT0gXCJhXCIpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGluZGljZXMucHVzaChOdW1iZXIoa2V5KSk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICByZXR1cm4gaW5kaWNlcztcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSwgeyBcIi4vY3JlYXRlLWVsZW1lbnRcIjogMTUsIFwiLi9kb20taW5kZXhcIjogMTYsIFwiLi9wYXRjaC1vcFwiOiAxNywgXCJnbG9iYWwvZG9jdW1lbnRcIjogMTAsIFwieC1pcy1hcnJheVwiOiAxMiB9XSwgMTk6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICB2YXIgaXNXaWRnZXQgPSByZXF1aXJlKFwiLi4vdm5vZGUvaXMtd2lkZ2V0LmpzXCIpO1xuXG4gICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IHVwZGF0ZVdpZGdldDtcblxuICAgICAgICAgICAgZnVuY3Rpb24gdXBkYXRlV2lkZ2V0KGEsIGIpIHtcbiAgICAgICAgICAgICAgICBpZiAoaXNXaWRnZXQoYSkgJiYgaXNXaWRnZXQoYikpIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKFwibmFtZVwiIGluIGEgJiYgXCJuYW1lXCIgaW4gYikge1xuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGEuaWQgPT09IGIuaWQ7XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gYS5pbml0ID09PSBiLmluaXQ7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0sIHsgXCIuLi92bm9kZS9pcy13aWRnZXQuanNcIjogMjkgfV0sIDIwOiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge1xuICAgICAgICAgICAgXCJ1c2Ugc3RyaWN0XCI7XG5cbiAgICAgICAgICAgIHZhciBFdlN0b3JlID0gcmVxdWlyZShcImV2LXN0b3JlXCIpO1xuXG4gICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IEV2SG9vaztcblxuICAgICAgICAgICAgZnVuY3Rpb24gRXZIb29rKHZhbHVlKSB7XG4gICAgICAgICAgICAgICAgaWYgKCEodGhpcyBpbnN0YW5jZW9mIEV2SG9vaykpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIG5ldyBFdkhvb2sodmFsdWUpO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHRoaXMudmFsdWUgPSB2YWx1ZTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgRXZIb29rLnByb3RvdHlwZS5ob29rID0gZnVuY3Rpb24gKG5vZGUsIHByb3BlcnR5TmFtZSkge1xuICAgICAgICAgICAgICAgIHZhciBlcyA9IEV2U3RvcmUobm9kZSk7XG4gICAgICAgICAgICAgICAgdmFyIHByb3BOYW1lID0gcHJvcGVydHlOYW1lLnN1YnN0cigzKTtcblxuICAgICAgICAgICAgICAgIGVzW3Byb3BOYW1lXSA9IHRoaXMudmFsdWU7XG4gICAgICAgICAgICB9O1xuXG4gICAgICAgICAgICBFdkhvb2sucHJvdG90eXBlLnVuaG9vayA9IGZ1bmN0aW9uIChub2RlLCBwcm9wZXJ0eU5hbWUpIHtcbiAgICAgICAgICAgICAgICB2YXIgZXMgPSBFdlN0b3JlKG5vZGUpO1xuICAgICAgICAgICAgICAgIHZhciBwcm9wTmFtZSA9IHByb3BlcnR5TmFtZS5zdWJzdHIoMyk7XG5cbiAgICAgICAgICAgICAgICBlc1twcm9wTmFtZV0gPSB1bmRlZmluZWQ7XG4gICAgICAgICAgICB9O1xuICAgICAgICB9LCB7IFwiZXYtc3RvcmVcIjogNyB9XSwgMjE6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICBcInVzZSBzdHJpY3RcIjtcblxuICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBTb2Z0U2V0SG9vaztcblxuICAgICAgICAgICAgZnVuY3Rpb24gU29mdFNldEhvb2sodmFsdWUpIHtcbiAgICAgICAgICAgICAgICBpZiAoISh0aGlzIGluc3RhbmNlb2YgU29mdFNldEhvb2spKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBuZXcgU29mdFNldEhvb2sodmFsdWUpO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHRoaXMudmFsdWUgPSB2YWx1ZTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgU29mdFNldEhvb2sucHJvdG90eXBlLmhvb2sgPSBmdW5jdGlvbiAobm9kZSwgcHJvcGVydHlOYW1lKSB7XG4gICAgICAgICAgICAgICAgaWYgKG5vZGVbcHJvcGVydHlOYW1lXSAhPT0gdGhpcy52YWx1ZSkge1xuICAgICAgICAgICAgICAgICAgICBub2RlW3Byb3BlcnR5TmFtZV0gPSB0aGlzLnZhbHVlO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH07XG4gICAgICAgIH0sIHt9XSwgMjI6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICBcInVzZSBzdHJpY3RcIjtcblxuICAgICAgICAgICAgdmFyIGlzQXJyYXkgPSByZXF1aXJlKFwieC1pcy1hcnJheVwiKTtcblxuICAgICAgICAgICAgdmFyIFZOb2RlID0gcmVxdWlyZShcIi4uL3Zub2RlL3Zub2RlLmpzXCIpO1xuICAgICAgICAgICAgdmFyIFZUZXh0ID0gcmVxdWlyZShcIi4uL3Zub2RlL3Z0ZXh0LmpzXCIpO1xuICAgICAgICAgICAgdmFyIGlzVk5vZGUgPSByZXF1aXJlKFwiLi4vdm5vZGUvaXMtdm5vZGVcIik7XG4gICAgICAgICAgICB2YXIgaXNWVGV4dCA9IHJlcXVpcmUoXCIuLi92bm9kZS9pcy12dGV4dFwiKTtcbiAgICAgICAgICAgIHZhciBpc1dpZGdldCA9IHJlcXVpcmUoXCIuLi92bm9kZS9pcy13aWRnZXRcIik7XG4gICAgICAgICAgICB2YXIgaXNIb29rID0gcmVxdWlyZShcIi4uL3Zub2RlL2lzLXZob29rXCIpO1xuICAgICAgICAgICAgdmFyIGlzVlRodW5rID0gcmVxdWlyZShcIi4uL3Zub2RlL2lzLXRodW5rXCIpO1xuXG4gICAgICAgICAgICB2YXIgcGFyc2VUYWcgPSByZXF1aXJlKFwiLi9wYXJzZS10YWcuanNcIik7XG4gICAgICAgICAgICB2YXIgc29mdFNldEhvb2sgPSByZXF1aXJlKFwiLi9ob29rcy9zb2Z0LXNldC1ob29rLmpzXCIpO1xuICAgICAgICAgICAgdmFyIGV2SG9vayA9IHJlcXVpcmUoXCIuL2hvb2tzL2V2LWhvb2suanNcIik7XG5cbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gaDtcblxuICAgICAgICAgICAgZnVuY3Rpb24gaCh0YWdOYW1lLCBwcm9wZXJ0aWVzLCBjaGlsZHJlbikge1xuICAgICAgICAgICAgICAgIHZhciBjaGlsZE5vZGVzID0gW107XG4gICAgICAgICAgICAgICAgdmFyIHRhZywgcHJvcHMsIGtleSwgbmFtZXNwYWNlO1xuXG4gICAgICAgICAgICAgICAgaWYgKCFjaGlsZHJlbiAmJiBpc0NoaWxkcmVuKHByb3BlcnRpZXMpKSB7XG4gICAgICAgICAgICAgICAgICAgIGNoaWxkcmVuID0gcHJvcGVydGllcztcbiAgICAgICAgICAgICAgICAgICAgcHJvcHMgPSB7fTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICBwcm9wcyA9IHByb3BzIHx8IHByb3BlcnRpZXMgfHwge307XG4gICAgICAgICAgICAgICAgdGFnID0gcGFyc2VUYWcodGFnTmFtZSwgcHJvcHMpO1xuXG4gICAgICAgICAgICAgICAgLy8gc3VwcG9ydCBrZXlzXG4gICAgICAgICAgICAgICAgaWYgKHByb3BzLmhhc093blByb3BlcnR5KFwia2V5XCIpKSB7XG4gICAgICAgICAgICAgICAgICAgIGtleSA9IHByb3BzLmtleTtcbiAgICAgICAgICAgICAgICAgICAgcHJvcHMua2V5ID0gdW5kZWZpbmVkO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIC8vIHN1cHBvcnQgbmFtZXNwYWNlXG4gICAgICAgICAgICAgICAgaWYgKHByb3BzLmhhc093blByb3BlcnR5KFwibmFtZXNwYWNlXCIpKSB7XG4gICAgICAgICAgICAgICAgICAgIG5hbWVzcGFjZSA9IHByb3BzLm5hbWVzcGFjZTtcbiAgICAgICAgICAgICAgICAgICAgcHJvcHMubmFtZXNwYWNlID0gdW5kZWZpbmVkO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIC8vIGZpeCBjdXJzb3IgYnVnXG4gICAgICAgICAgICAgICAgaWYgKHRhZyA9PT0gXCJJTlBVVFwiICYmICFuYW1lc3BhY2UgJiYgcHJvcHMuaGFzT3duUHJvcGVydHkoXCJ2YWx1ZVwiKSAmJiBwcm9wcy52YWx1ZSAhPT0gdW5kZWZpbmVkICYmICFpc0hvb2socHJvcHMudmFsdWUpKSB7XG4gICAgICAgICAgICAgICAgICAgIHByb3BzLnZhbHVlID0gc29mdFNldEhvb2socHJvcHMudmFsdWUpO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHRyYW5zZm9ybVByb3BlcnRpZXMocHJvcHMpO1xuXG4gICAgICAgICAgICAgICAgaWYgKGNoaWxkcmVuICE9PSB1bmRlZmluZWQgJiYgY2hpbGRyZW4gIT09IG51bGwpIHtcbiAgICAgICAgICAgICAgICAgICAgYWRkQ2hpbGQoY2hpbGRyZW4sIGNoaWxkTm9kZXMsIHRhZywgcHJvcHMpO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHJldHVybiBuZXcgVk5vZGUodGFnLCBwcm9wcywgY2hpbGROb2Rlcywga2V5LCBuYW1lc3BhY2UpO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBmdW5jdGlvbiBhZGRDaGlsZChjLCBjaGlsZE5vZGVzLCB0YWcsIHByb3BzKSB7XG4gICAgICAgICAgICAgICAgaWYgKHR5cGVvZiBjID09PSBcInN0cmluZ1wiKSB7XG4gICAgICAgICAgICAgICAgICAgIGNoaWxkTm9kZXMucHVzaChuZXcgVlRleHQoYykpO1xuICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAodHlwZW9mIGMgPT09IFwibnVtYmVyXCIpIHtcbiAgICAgICAgICAgICAgICAgICAgY2hpbGROb2Rlcy5wdXNoKG5ldyBWVGV4dChTdHJpbmcoYykpKTtcbiAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKGlzQ2hpbGQoYykpIHtcbiAgICAgICAgICAgICAgICAgICAgY2hpbGROb2Rlcy5wdXNoKGMpO1xuICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoaXNBcnJheShjKSkge1xuICAgICAgICAgICAgICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IGMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGFkZENoaWxkKGNbaV0sIGNoaWxkTm9kZXMsIHRhZywgcHJvcHMpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfSBlbHNlIGlmIChjID09PSBudWxsIHx8IGMgPT09IHVuZGVmaW5lZCkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgdGhyb3cgVW5leHBlY3RlZFZpcnR1YWxFbGVtZW50KHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGZvcmVpZ25PYmplY3Q6IGMsXG4gICAgICAgICAgICAgICAgICAgICAgICBwYXJlbnRWbm9kZToge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRhZ05hbWU6IHRhZyxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBwcm9wZXJ0aWVzOiBwcm9wc1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIHRyYW5zZm9ybVByb3BlcnRpZXMocHJvcHMpIHtcbiAgICAgICAgICAgICAgICBmb3IgKHZhciBwcm9wTmFtZSBpbiBwcm9wcykge1xuICAgICAgICAgICAgICAgICAgICBpZiAocHJvcHMuaGFzT3duUHJvcGVydHkocHJvcE5hbWUpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICB2YXIgdmFsdWUgPSBwcm9wc1twcm9wTmFtZV07XG5cbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChpc0hvb2sodmFsdWUpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgY29udGludWU7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChwcm9wTmFtZS5zdWJzdHIoMCwgMykgPT09IFwiZXYtXCIpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBhZGQgZXYtZm9vIHN1cHBvcnRcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBwcm9wc1twcm9wTmFtZV0gPSBldkhvb2sodmFsdWUpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBmdW5jdGlvbiBpc0NoaWxkKHgpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gaXNWTm9kZSh4KSB8fCBpc1ZUZXh0KHgpIHx8IGlzV2lkZ2V0KHgpIHx8IGlzVlRodW5rKHgpO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBmdW5jdGlvbiBpc0NoaWxkcmVuKHgpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gdHlwZW9mIHggPT09IFwic3RyaW5nXCIgfHwgaXNBcnJheSh4KSB8fCBpc0NoaWxkKHgpO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBmdW5jdGlvbiBVbmV4cGVjdGVkVmlydHVhbEVsZW1lbnQoZGF0YSkge1xuICAgICAgICAgICAgICAgIHZhciBlcnIgPSBuZXcgRXJyb3IoKTtcblxuICAgICAgICAgICAgICAgIGVyci50eXBlID0gXCJ2aXJ0dWFsLWh5cGVyc2NyaXB0LnVuZXhwZWN0ZWQudmlydHVhbC1lbGVtZW50XCI7XG4gICAgICAgICAgICAgICAgZXJyLm1lc3NhZ2UgPSBcIlVuZXhwZWN0ZWQgdmlydHVhbCBjaGlsZCBwYXNzZWQgdG8gaCgpLlxcblwiICsgXCJFeHBlY3RlZCBhIFZOb2RlIC8gVnRodW5rIC8gVldpZGdldCAvIHN0cmluZyBidXQ6XFxuXCIgKyBcImdvdDpcXG5cIiArIGVycm9yU3RyaW5nKGRhdGEuZm9yZWlnbk9iamVjdCkgKyBcIi5cXG5cIiArIFwiVGhlIHBhcmVudCB2bm9kZSBpczpcXG5cIiArIGVycm9yU3RyaW5nKGRhdGEucGFyZW50Vm5vZGUpO1xuICAgICAgICAgICAgICAgIFwiXFxuXCIgKyBcIlN1Z2dlc3RlZCBmaXg6IGNoYW5nZSB5b3VyIGBoKC4uLiwgWyAuLi4gXSlgIGNhbGxzaXRlLlwiO1xuICAgICAgICAgICAgICAgIGVyci5mb3JlaWduT2JqZWN0ID0gZGF0YS5mb3JlaWduT2JqZWN0O1xuICAgICAgICAgICAgICAgIGVyci5wYXJlbnRWbm9kZSA9IGRhdGEucGFyZW50Vm5vZGU7XG5cbiAgICAgICAgICAgICAgICByZXR1cm4gZXJyO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBmdW5jdGlvbiBlcnJvclN0cmluZyhvYmopIHtcbiAgICAgICAgICAgICAgICB0cnkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gSlNPTi5zdHJpbmdpZnkob2JqLCBudWxsLCBcIiAgICBcIik7XG4gICAgICAgICAgICAgICAgfSBjYXRjaCAoZSkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gU3RyaW5nKG9iaik7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9LCB7IFwiLi4vdm5vZGUvaXMtdGh1bmtcIjogMjUsIFwiLi4vdm5vZGUvaXMtdmhvb2tcIjogMjYsIFwiLi4vdm5vZGUvaXMtdm5vZGVcIjogMjcsIFwiLi4vdm5vZGUvaXMtdnRleHRcIjogMjgsIFwiLi4vdm5vZGUvaXMtd2lkZ2V0XCI6IDI5LCBcIi4uL3Zub2RlL3Zub2RlLmpzXCI6IDMxLCBcIi4uL3Zub2RlL3Z0ZXh0LmpzXCI6IDMzLCBcIi4vaG9va3MvZXYtaG9vay5qc1wiOiAyMCwgXCIuL2hvb2tzL3NvZnQtc2V0LWhvb2suanNcIjogMjEsIFwiLi9wYXJzZS10YWcuanNcIjogMjMsIFwieC1pcy1hcnJheVwiOiAxMiB9XSwgMjM6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICBcInVzZSBzdHJpY3RcIjtcblxuICAgICAgICAgICAgdmFyIHNwbGl0ID0gcmVxdWlyZShcImJyb3dzZXItc3BsaXRcIik7XG5cbiAgICAgICAgICAgIHZhciBjbGFzc0lkU3BsaXQgPSAvKFtcXC4jXT9bYS16QS1aMC05XFx1MDA3Ri1cXHVGRkZGXzotXSspLztcbiAgICAgICAgICAgIHZhciBub3RDbGFzc0lkID0gL15cXC58Iy87XG5cbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gcGFyc2VUYWc7XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIHBhcnNlVGFnKHRhZywgcHJvcHMpIHtcbiAgICAgICAgICAgICAgICBpZiAoIXRhZykge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gXCJESVZcIjtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICB2YXIgbm9JZCA9ICFwcm9wcy5oYXNPd25Qcm9wZXJ0eShcImlkXCIpO1xuXG4gICAgICAgICAgICAgICAgdmFyIHRhZ1BhcnRzID0gc3BsaXQodGFnLCBjbGFzc0lkU3BsaXQpO1xuICAgICAgICAgICAgICAgIHZhciB0YWdOYW1lID0gbnVsbDtcblxuICAgICAgICAgICAgICAgIGlmIChub3RDbGFzc0lkLnRlc3QodGFnUGFydHNbMV0pKSB7XG4gICAgICAgICAgICAgICAgICAgIHRhZ05hbWUgPSBcIkRJVlwiO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHZhciBjbGFzc2VzLCBwYXJ0LCB0eXBlLCBpO1xuXG4gICAgICAgICAgICAgICAgZm9yIChpID0gMDsgaSA8IHRhZ1BhcnRzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICAgICAgICAgIHBhcnQgPSB0YWdQYXJ0c1tpXTtcblxuICAgICAgICAgICAgICAgICAgICBpZiAoIXBhcnQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnRpbnVlO1xuICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgdHlwZSA9IHBhcnQuY2hhckF0KDApO1xuXG4gICAgICAgICAgICAgICAgICAgIGlmICghdGFnTmFtZSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgdGFnTmFtZSA9IHBhcnQ7XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAodHlwZSA9PT0gXCIuXCIpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGNsYXNzZXMgPSBjbGFzc2VzIHx8IFtdO1xuICAgICAgICAgICAgICAgICAgICAgICAgY2xhc3Nlcy5wdXNoKHBhcnQuc3Vic3RyaW5nKDEsIHBhcnQubGVuZ3RoKSk7XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAodHlwZSA9PT0gXCIjXCIgJiYgbm9JZCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgcHJvcHMuaWQgPSBwYXJ0LnN1YnN0cmluZygxLCBwYXJ0Lmxlbmd0aCk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICBpZiAoY2xhc3Nlcykge1xuICAgICAgICAgICAgICAgICAgICBpZiAocHJvcHMuY2xhc3NOYW1lKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBjbGFzc2VzLnB1c2gocHJvcHMuY2xhc3NOYW1lKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgIHByb3BzLmNsYXNzTmFtZSA9IGNsYXNzZXMuam9pbihcIiBcIik7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgcmV0dXJuIHByb3BzLm5hbWVzcGFjZSA/IHRhZ05hbWUgOiB0YWdOYW1lLnRvVXBwZXJDYXNlKCk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0sIHsgXCJicm93c2VyLXNwbGl0XCI6IDUgfV0sIDI0OiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge1xuICAgICAgICAgICAgdmFyIGlzVk5vZGUgPSByZXF1aXJlKFwiLi9pcy12bm9kZVwiKTtcbiAgICAgICAgICAgIHZhciBpc1ZUZXh0ID0gcmVxdWlyZShcIi4vaXMtdnRleHRcIik7XG4gICAgICAgICAgICB2YXIgaXNXaWRnZXQgPSByZXF1aXJlKFwiLi9pcy13aWRnZXRcIik7XG4gICAgICAgICAgICB2YXIgaXNUaHVuayA9IHJlcXVpcmUoXCIuL2lzLXRodW5rXCIpO1xuXG4gICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IGhhbmRsZVRodW5rO1xuXG4gICAgICAgICAgICBmdW5jdGlvbiBoYW5kbGVUaHVuayhhLCBiKSB7XG4gICAgICAgICAgICAgICAgdmFyIHJlbmRlcmVkQSA9IGE7XG4gICAgICAgICAgICAgICAgdmFyIHJlbmRlcmVkQiA9IGI7XG5cbiAgICAgICAgICAgICAgICBpZiAoaXNUaHVuayhiKSkge1xuICAgICAgICAgICAgICAgICAgICByZW5kZXJlZEIgPSByZW5kZXJUaHVuayhiLCBhKTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICBpZiAoaXNUaHVuayhhKSkge1xuICAgICAgICAgICAgICAgICAgICByZW5kZXJlZEEgPSByZW5kZXJUaHVuayhhLCBudWxsKTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgICAgICAgICBhOiByZW5kZXJlZEEsXG4gICAgICAgICAgICAgICAgICAgIGI6IHJlbmRlcmVkQlxuICAgICAgICAgICAgICAgIH07XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIHJlbmRlclRodW5rKHRodW5rLCBwcmV2aW91cykge1xuICAgICAgICAgICAgICAgIHZhciByZW5kZXJlZFRodW5rID0gdGh1bmsudm5vZGU7XG5cbiAgICAgICAgICAgICAgICBpZiAoIXJlbmRlcmVkVGh1bmspIHtcbiAgICAgICAgICAgICAgICAgICAgcmVuZGVyZWRUaHVuayA9IHRodW5rLnZub2RlID0gdGh1bmsucmVuZGVyKHByZXZpb3VzKTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICBpZiAoIShpc1ZOb2RlKHJlbmRlcmVkVGh1bmspIHx8IGlzVlRleHQocmVuZGVyZWRUaHVuaykgfHwgaXNXaWRnZXQocmVuZGVyZWRUaHVuaykpKSB7XG4gICAgICAgICAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcihcInRodW5rIGRpZCBub3QgcmV0dXJuIGEgdmFsaWQgbm9kZVwiKTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICByZXR1cm4gcmVuZGVyZWRUaHVuaztcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSwgeyBcIi4vaXMtdGh1bmtcIjogMjUsIFwiLi9pcy12bm9kZVwiOiAyNywgXCIuL2lzLXZ0ZXh0XCI6IDI4LCBcIi4vaXMtd2lkZ2V0XCI6IDI5IH1dLCAyNTogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHtcbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gaXNUaHVuaztcblxuICAgICAgICAgICAgZnVuY3Rpb24gaXNUaHVuayh0KSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHQgJiYgdC50eXBlID09PSBcIlRodW5rXCI7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0sIHt9XSwgMjY6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IGlzSG9vaztcblxuICAgICAgICAgICAgZnVuY3Rpb24gaXNIb29rKGhvb2spIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gaG9vayAmJiAodHlwZW9mIGhvb2suaG9vayA9PT0gXCJmdW5jdGlvblwiICYmICFob29rLmhhc093blByb3BlcnR5KFwiaG9va1wiKSB8fCB0eXBlb2YgaG9vay51bmhvb2sgPT09IFwiZnVuY3Rpb25cIiAmJiAhaG9vay5oYXNPd25Qcm9wZXJ0eShcInVuaG9va1wiKSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0sIHt9XSwgMjc6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICB2YXIgdmVyc2lvbiA9IHJlcXVpcmUoXCIuL3ZlcnNpb25cIik7XG5cbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gaXNWaXJ0dWFsTm9kZTtcblxuICAgICAgICAgICAgZnVuY3Rpb24gaXNWaXJ0dWFsTm9kZSh4KSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHggJiYgeC50eXBlID09PSBcIlZpcnR1YWxOb2RlXCIgJiYgeC52ZXJzaW9uID09PSB2ZXJzaW9uO1xuICAgICAgICAgICAgfVxuICAgICAgICB9LCB7IFwiLi92ZXJzaW9uXCI6IDMwIH1dLCAyODogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHtcbiAgICAgICAgICAgIHZhciB2ZXJzaW9uID0gcmVxdWlyZShcIi4vdmVyc2lvblwiKTtcblxuICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBpc1ZpcnR1YWxUZXh0O1xuXG4gICAgICAgICAgICBmdW5jdGlvbiBpc1ZpcnR1YWxUZXh0KHgpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4geCAmJiB4LnR5cGUgPT09IFwiVmlydHVhbFRleHRcIiAmJiB4LnZlcnNpb24gPT09IHZlcnNpb247XG4gICAgICAgICAgICB9XG4gICAgICAgIH0sIHsgXCIuL3ZlcnNpb25cIjogMzAgfV0sIDI5OiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge1xuICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBpc1dpZGdldDtcblxuICAgICAgICAgICAgZnVuY3Rpb24gaXNXaWRnZXQodykge1xuICAgICAgICAgICAgICAgIHJldHVybiB3ICYmIHcudHlwZSA9PT0gXCJXaWRnZXRcIjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSwge31dLCAzMDogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHtcbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gXCIyXCI7XG4gICAgICAgIH0sIHt9XSwgMzE6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICB2YXIgdmVyc2lvbiA9IHJlcXVpcmUoXCIuL3ZlcnNpb25cIik7XG4gICAgICAgICAgICB2YXIgaXNWTm9kZSA9IHJlcXVpcmUoXCIuL2lzLXZub2RlXCIpO1xuICAgICAgICAgICAgdmFyIGlzV2lkZ2V0ID0gcmVxdWlyZShcIi4vaXMtd2lkZ2V0XCIpO1xuICAgICAgICAgICAgdmFyIGlzVGh1bmsgPSByZXF1aXJlKFwiLi9pcy10aHVua1wiKTtcbiAgICAgICAgICAgIHZhciBpc1ZIb29rID0gcmVxdWlyZShcIi4vaXMtdmhvb2tcIik7XG5cbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gVmlydHVhbE5vZGU7XG5cbiAgICAgICAgICAgIHZhciBub1Byb3BlcnRpZXMgPSB7fTtcbiAgICAgICAgICAgIHZhciBub0NoaWxkcmVuID0gW107XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIFZpcnR1YWxOb2RlKHRhZ05hbWUsIHByb3BlcnRpZXMsIGNoaWxkcmVuLCBrZXksIG5hbWVzcGFjZSkge1xuICAgICAgICAgICAgICAgIHRoaXMudGFnTmFtZSA9IHRhZ05hbWU7XG4gICAgICAgICAgICAgICAgdGhpcy5wcm9wZXJ0aWVzID0gcHJvcGVydGllcyB8fCBub1Byb3BlcnRpZXM7XG4gICAgICAgICAgICAgICAgdGhpcy5jaGlsZHJlbiA9IGNoaWxkcmVuIHx8IG5vQ2hpbGRyZW47XG4gICAgICAgICAgICAgICAgdGhpcy5rZXkgPSBrZXkgIT0gbnVsbCA/IFN0cmluZyhrZXkpIDogdW5kZWZpbmVkO1xuICAgICAgICAgICAgICAgIHRoaXMubmFtZXNwYWNlID0gdHlwZW9mIG5hbWVzcGFjZSA9PT0gXCJzdHJpbmdcIiA/IG5hbWVzcGFjZSA6IG51bGw7XG5cbiAgICAgICAgICAgICAgICB2YXIgY291bnQgPSBjaGlsZHJlbiAmJiBjaGlsZHJlbi5sZW5ndGggfHwgMDtcbiAgICAgICAgICAgICAgICB2YXIgZGVzY2VuZGFudHMgPSAwO1xuICAgICAgICAgICAgICAgIHZhciBoYXNXaWRnZXRzID0gZmFsc2U7XG4gICAgICAgICAgICAgICAgdmFyIGhhc1RodW5rcyA9IGZhbHNlO1xuICAgICAgICAgICAgICAgIHZhciBkZXNjZW5kYW50SG9va3MgPSBmYWxzZTtcbiAgICAgICAgICAgICAgICB2YXIgaG9va3M7XG5cbiAgICAgICAgICAgICAgICBmb3IgKHZhciBwcm9wTmFtZSBpbiBwcm9wZXJ0aWVzKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmIChwcm9wZXJ0aWVzLmhhc093blByb3BlcnR5KHByb3BOYW1lKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgdmFyIHByb3BlcnR5ID0gcHJvcGVydGllc1twcm9wTmFtZV07XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoaXNWSG9vayhwcm9wZXJ0eSkgJiYgcHJvcGVydHkudW5ob29rKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKCFob29rcykge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBob29rcyA9IHt9O1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGhvb2tzW3Byb3BOYW1lXSA9IHByb3BlcnR5O1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCBjb3VudDsgaSsrKSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciBjaGlsZCA9IGNoaWxkcmVuW2ldO1xuICAgICAgICAgICAgICAgICAgICBpZiAoaXNWTm9kZShjaGlsZCkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGRlc2NlbmRhbnRzICs9IGNoaWxkLmNvdW50IHx8IDA7XG5cbiAgICAgICAgICAgICAgICAgICAgICAgIGlmICghaGFzV2lkZ2V0cyAmJiBjaGlsZC5oYXNXaWRnZXRzKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaGFzV2lkZ2V0cyA9IHRydWU7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgICAgIGlmICghaGFzVGh1bmtzICYmIGNoaWxkLmhhc1RodW5rcykge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGhhc1RodW5rcyA9IHRydWU7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgICAgIGlmICghZGVzY2VuZGFudEhvb2tzICYmIChjaGlsZC5ob29rcyB8fCBjaGlsZC5kZXNjZW5kYW50SG9va3MpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgZGVzY2VuZGFudEhvb2tzID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIGlmICghaGFzV2lkZ2V0cyAmJiBpc1dpZGdldChjaGlsZCkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmICh0eXBlb2YgY2hpbGQuZGVzdHJveSA9PT0gXCJmdW5jdGlvblwiKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaGFzV2lkZ2V0cyA9IHRydWU7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoIWhhc1RodW5rcyAmJiBpc1RodW5rKGNoaWxkKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgaGFzVGh1bmtzID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHRoaXMuY291bnQgPSBjb3VudCArIGRlc2NlbmRhbnRzO1xuICAgICAgICAgICAgICAgIHRoaXMuaGFzV2lkZ2V0cyA9IGhhc1dpZGdldHM7XG4gICAgICAgICAgICAgICAgdGhpcy5oYXNUaHVua3MgPSBoYXNUaHVua3M7XG4gICAgICAgICAgICAgICAgdGhpcy5ob29rcyA9IGhvb2tzO1xuICAgICAgICAgICAgICAgIHRoaXMuZGVzY2VuZGFudEhvb2tzID0gZGVzY2VuZGFudEhvb2tzO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBWaXJ0dWFsTm9kZS5wcm90b3R5cGUudmVyc2lvbiA9IHZlcnNpb247XG4gICAgICAgICAgICBWaXJ0dWFsTm9kZS5wcm90b3R5cGUudHlwZSA9IFwiVmlydHVhbE5vZGVcIjtcbiAgICAgICAgfSwgeyBcIi4vaXMtdGh1bmtcIjogMjUsIFwiLi9pcy12aG9va1wiOiAyNiwgXCIuL2lzLXZub2RlXCI6IDI3LCBcIi4vaXMtd2lkZ2V0XCI6IDI5LCBcIi4vdmVyc2lvblwiOiAzMCB9XSwgMzI6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICB2YXIgdmVyc2lvbiA9IHJlcXVpcmUoXCIuL3ZlcnNpb25cIik7XG5cbiAgICAgICAgICAgIFZpcnR1YWxQYXRjaC5OT05FID0gMDtcbiAgICAgICAgICAgIFZpcnR1YWxQYXRjaC5WVEVYVCA9IDE7XG4gICAgICAgICAgICBWaXJ0dWFsUGF0Y2guVk5PREUgPSAyO1xuICAgICAgICAgICAgVmlydHVhbFBhdGNoLldJREdFVCA9IDM7XG4gICAgICAgICAgICBWaXJ0dWFsUGF0Y2guUFJPUFMgPSA0O1xuICAgICAgICAgICAgVmlydHVhbFBhdGNoLk9SREVSID0gNTtcbiAgICAgICAgICAgIFZpcnR1YWxQYXRjaC5JTlNFUlQgPSA2O1xuICAgICAgICAgICAgVmlydHVhbFBhdGNoLlJFTU9WRSA9IDc7XG4gICAgICAgICAgICBWaXJ0dWFsUGF0Y2guVEhVTksgPSA4O1xuXG4gICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IFZpcnR1YWxQYXRjaDtcblxuICAgICAgICAgICAgZnVuY3Rpb24gVmlydHVhbFBhdGNoKHR5cGUsIHZOb2RlLCBwYXRjaCkge1xuICAgICAgICAgICAgICAgIHRoaXMudHlwZSA9IE51bWJlcih0eXBlKTtcbiAgICAgICAgICAgICAgICB0aGlzLnZOb2RlID0gdk5vZGU7XG4gICAgICAgICAgICAgICAgdGhpcy5wYXRjaCA9IHBhdGNoO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBWaXJ0dWFsUGF0Y2gucHJvdG90eXBlLnZlcnNpb24gPSB2ZXJzaW9uO1xuICAgICAgICAgICAgVmlydHVhbFBhdGNoLnByb3RvdHlwZS50eXBlID0gXCJWaXJ0dWFsUGF0Y2hcIjtcbiAgICAgICAgfSwgeyBcIi4vdmVyc2lvblwiOiAzMCB9XSwgMzM6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICB2YXIgdmVyc2lvbiA9IHJlcXVpcmUoXCIuL3ZlcnNpb25cIik7XG5cbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gVmlydHVhbFRleHQ7XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIFZpcnR1YWxUZXh0KHRleHQpIHtcbiAgICAgICAgICAgICAgICB0aGlzLnRleHQgPSBTdHJpbmcodGV4dCk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIFZpcnR1YWxUZXh0LnByb3RvdHlwZS52ZXJzaW9uID0gdmVyc2lvbjtcbiAgICAgICAgICAgIFZpcnR1YWxUZXh0LnByb3RvdHlwZS50eXBlID0gXCJWaXJ0dWFsVGV4dFwiO1xuICAgICAgICB9LCB7IFwiLi92ZXJzaW9uXCI6IDMwIH1dLCAzNDogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHtcbiAgICAgICAgICAgIHZhciBpc09iamVjdCA9IHJlcXVpcmUoXCJpcy1vYmplY3RcIik7XG4gICAgICAgICAgICB2YXIgaXNIb29rID0gcmVxdWlyZShcIi4uL3Zub2RlL2lzLXZob29rXCIpO1xuXG4gICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IGRpZmZQcm9wcztcblxuICAgICAgICAgICAgZnVuY3Rpb24gZGlmZlByb3BzKGEsIGIpIHtcbiAgICAgICAgICAgICAgICB2YXIgZGlmZjtcblxuICAgICAgICAgICAgICAgIGZvciAodmFyIGFLZXkgaW4gYSkge1xuICAgICAgICAgICAgICAgICAgICBpZiAoIShhS2V5IGluIGIpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBkaWZmID0gZGlmZiB8fCB7fTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGRpZmZbYUtleV0gPSB1bmRlZmluZWQ7XG4gICAgICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgICAgICB2YXIgYVZhbHVlID0gYVthS2V5XTtcbiAgICAgICAgICAgICAgICAgICAgdmFyIGJWYWx1ZSA9IGJbYUtleV07XG5cbiAgICAgICAgICAgICAgICAgICAgaWYgKGFWYWx1ZSA9PT0gYlZhbHVlKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBjb250aW51ZTtcbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIGlmIChpc09iamVjdChhVmFsdWUpICYmIGlzT2JqZWN0KGJWYWx1ZSkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChnZXRQcm90b3R5cGUoYlZhbHVlKSAhPT0gZ2V0UHJvdG90eXBlKGFWYWx1ZSkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBkaWZmID0gZGlmZiB8fCB7fTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBkaWZmW2FLZXldID0gYlZhbHVlO1xuICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIGlmIChpc0hvb2soYlZhbHVlKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRpZmYgPSBkaWZmIHx8IHt9O1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRpZmZbYUtleV0gPSBiVmFsdWU7XG4gICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZhciBvYmplY3REaWZmID0gZGlmZlByb3BzKGFWYWx1ZSwgYlZhbHVlKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAob2JqZWN0RGlmZikge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBkaWZmID0gZGlmZiB8fCB7fTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZGlmZlthS2V5XSA9IG9iamVjdERpZmY7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgZGlmZiA9IGRpZmYgfHwge307XG4gICAgICAgICAgICAgICAgICAgICAgICBkaWZmW2FLZXldID0gYlZhbHVlO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgZm9yICh2YXIgYktleSBpbiBiKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmICghKGJLZXkgaW4gYSkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGRpZmYgPSBkaWZmIHx8IHt9O1xuICAgICAgICAgICAgICAgICAgICAgICAgZGlmZltiS2V5XSA9IGJbYktleV07XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICByZXR1cm4gZGlmZjtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZnVuY3Rpb24gZ2V0UHJvdG90eXBlKHZhbHVlKSB7XG4gICAgICAgICAgICAgICAgaWYgKE9iamVjdC5nZXRQcm90b3R5cGVPZikge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gT2JqZWN0LmdldFByb3RvdHlwZU9mKHZhbHVlKTtcbiAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKHZhbHVlLl9fcHJvdG9fXykge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gdmFsdWUuX19wcm90b19fO1xuICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAodmFsdWUuY29uc3RydWN0b3IpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHZhbHVlLmNvbnN0cnVjdG9yLnByb3RvdHlwZTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH0sIHsgXCIuLi92bm9kZS9pcy12aG9va1wiOiAyNiwgXCJpcy1vYmplY3RcIjogMTEgfV0sIDM1OiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge1xuICAgICAgICAgICAgdmFyIGlzQXJyYXkgPSByZXF1aXJlKFwieC1pcy1hcnJheVwiKTtcblxuICAgICAgICAgICAgdmFyIFZQYXRjaCA9IHJlcXVpcmUoXCIuLi92bm9kZS92cGF0Y2hcIik7XG4gICAgICAgICAgICB2YXIgaXNWTm9kZSA9IHJlcXVpcmUoXCIuLi92bm9kZS9pcy12bm9kZVwiKTtcbiAgICAgICAgICAgIHZhciBpc1ZUZXh0ID0gcmVxdWlyZShcIi4uL3Zub2RlL2lzLXZ0ZXh0XCIpO1xuICAgICAgICAgICAgdmFyIGlzV2lkZ2V0ID0gcmVxdWlyZShcIi4uL3Zub2RlL2lzLXdpZGdldFwiKTtcbiAgICAgICAgICAgIHZhciBpc1RodW5rID0gcmVxdWlyZShcIi4uL3Zub2RlL2lzLXRodW5rXCIpO1xuICAgICAgICAgICAgdmFyIGhhbmRsZVRodW5rID0gcmVxdWlyZShcIi4uL3Zub2RlL2hhbmRsZS10aHVua1wiKTtcblxuICAgICAgICAgICAgdmFyIGRpZmZQcm9wcyA9IHJlcXVpcmUoXCIuL2RpZmYtcHJvcHNcIik7XG5cbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gZGlmZjtcblxuICAgICAgICAgICAgZnVuY3Rpb24gZGlmZihhLCBiKSB7XG4gICAgICAgICAgICAgICAgdmFyIHBhdGNoID0geyBhOiBhIH07XG4gICAgICAgICAgICAgICAgd2FsayhhLCBiLCBwYXRjaCwgMCk7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHBhdGNoO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBmdW5jdGlvbiB3YWxrKGEsIGIsIHBhdGNoLCBpbmRleCkge1xuICAgICAgICAgICAgICAgIGlmIChhID09PSBiKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICB2YXIgYXBwbHkgPSBwYXRjaFtpbmRleF07XG4gICAgICAgICAgICAgICAgdmFyIGFwcGx5Q2xlYXIgPSBmYWxzZTtcblxuICAgICAgICAgICAgICAgIGlmIChpc1RodW5rKGEpIHx8IGlzVGh1bmsoYikpIHtcbiAgICAgICAgICAgICAgICAgICAgdGh1bmtzKGEsIGIsIHBhdGNoLCBpbmRleCk7XG4gICAgICAgICAgICAgICAgfSBlbHNlIGlmIChiID09IG51bGwpIHtcblxuICAgICAgICAgICAgICAgICAgICAvLyBJZiBhIGlzIGEgd2lkZ2V0IHdlIHdpbGwgYWRkIGEgcmVtb3ZlIHBhdGNoIGZvciBpdFxuICAgICAgICAgICAgICAgICAgICAvLyBPdGhlcndpc2UgYW55IGNoaWxkIHdpZGdldHMvaG9va3MgbXVzdCBiZSBkZXN0cm95ZWQuXG4gICAgICAgICAgICAgICAgICAgIC8vIFRoaXMgcHJldmVudHMgYWRkaW5nIHR3byByZW1vdmUgcGF0Y2hlcyBmb3IgYSB3aWRnZXQuXG4gICAgICAgICAgICAgICAgICAgIGlmICghaXNXaWRnZXQoYSkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGNsZWFyU3RhdGUoYSwgcGF0Y2gsIGluZGV4KTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGFwcGx5ID0gcGF0Y2hbaW5kZXhdO1xuICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgYXBwbHkgPSBhcHBlbmRQYXRjaChhcHBseSwgbmV3IFZQYXRjaChWUGF0Y2guUkVNT1ZFLCBhLCBiKSk7XG4gICAgICAgICAgICAgICAgfSBlbHNlIGlmIChpc1ZOb2RlKGIpKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmIChpc1ZOb2RlKGEpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoYS50YWdOYW1lID09PSBiLnRhZ05hbWUgJiYgYS5uYW1lc3BhY2UgPT09IGIubmFtZXNwYWNlICYmIGEua2V5ID09PSBiLmtleSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZhciBwcm9wc1BhdGNoID0gZGlmZlByb3BzKGEucHJvcGVydGllcywgYi5wcm9wZXJ0aWVzKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAocHJvcHNQYXRjaCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBhcHBseSA9IGFwcGVuZFBhdGNoKGFwcGx5LCBuZXcgVlBhdGNoKFZQYXRjaC5QUk9QUywgYSwgcHJvcHNQYXRjaCkpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBhcHBseSA9IGRpZmZDaGlsZHJlbihhLCBiLCBwYXRjaCwgYXBwbHksIGluZGV4KTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgYXBwbHkgPSBhcHBlbmRQYXRjaChhcHBseSwgbmV3IFZQYXRjaChWUGF0Y2guVk5PREUsIGEsIGIpKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBhcHBseUNsZWFyID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGFwcGx5ID0gYXBwZW5kUGF0Y2goYXBwbHksIG5ldyBWUGF0Y2goVlBhdGNoLlZOT0RFLCBhLCBiKSk7XG4gICAgICAgICAgICAgICAgICAgICAgICBhcHBseUNsZWFyID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoaXNWVGV4dChiKSkge1xuICAgICAgICAgICAgICAgICAgICBpZiAoIWlzVlRleHQoYSkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGFwcGx5ID0gYXBwZW5kUGF0Y2goYXBwbHksIG5ldyBWUGF0Y2goVlBhdGNoLlZURVhULCBhLCBiKSk7XG4gICAgICAgICAgICAgICAgICAgICAgICBhcHBseUNsZWFyID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIGlmIChhLnRleHQgIT09IGIudGV4dCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgYXBwbHkgPSBhcHBlbmRQYXRjaChhcHBseSwgbmV3IFZQYXRjaChWUGF0Y2guVlRFWFQsIGEsIGIpKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoaXNXaWRnZXQoYikpIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKCFpc1dpZGdldChhKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgYXBwbHlDbGVhciA9IHRydWU7XG4gICAgICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgICAgICBhcHBseSA9IGFwcGVuZFBhdGNoKGFwcGx5LCBuZXcgVlBhdGNoKFZQYXRjaC5XSURHRVQsIGEsIGIpKTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICBpZiAoYXBwbHkpIHtcbiAgICAgICAgICAgICAgICAgICAgcGF0Y2hbaW5kZXhdID0gYXBwbHk7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgaWYgKGFwcGx5Q2xlYXIpIHtcbiAgICAgICAgICAgICAgICAgICAgY2xlYXJTdGF0ZShhLCBwYXRjaCwgaW5kZXgpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZnVuY3Rpb24gZGlmZkNoaWxkcmVuKGEsIGIsIHBhdGNoLCBhcHBseSwgaW5kZXgpIHtcbiAgICAgICAgICAgICAgICB2YXIgYUNoaWxkcmVuID0gYS5jaGlsZHJlbjtcbiAgICAgICAgICAgICAgICB2YXIgb3JkZXJlZFNldCA9IHJlb3JkZXIoYUNoaWxkcmVuLCBiLmNoaWxkcmVuKTtcbiAgICAgICAgICAgICAgICB2YXIgYkNoaWxkcmVuID0gb3JkZXJlZFNldC5jaGlsZHJlbjtcblxuICAgICAgICAgICAgICAgIHZhciBhTGVuID0gYUNoaWxkcmVuLmxlbmd0aDtcbiAgICAgICAgICAgICAgICB2YXIgYkxlbiA9IGJDaGlsZHJlbi5sZW5ndGg7XG4gICAgICAgICAgICAgICAgdmFyIGxlbiA9IGFMZW4gPiBiTGVuID8gYUxlbiA6IGJMZW47XG5cbiAgICAgICAgICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IGxlbjsgaSsrKSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciBsZWZ0Tm9kZSA9IGFDaGlsZHJlbltpXTtcbiAgICAgICAgICAgICAgICAgICAgdmFyIHJpZ2h0Tm9kZSA9IGJDaGlsZHJlbltpXTtcbiAgICAgICAgICAgICAgICAgICAgaW5kZXggKz0gMTtcblxuICAgICAgICAgICAgICAgICAgICBpZiAoIWxlZnROb2RlKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAocmlnaHROb2RlKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gRXhjZXNzIG5vZGVzIGluIGIgbmVlZCB0byBiZSBhZGRlZFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGFwcGx5ID0gYXBwZW5kUGF0Y2goYXBwbHksIG5ldyBWUGF0Y2goVlBhdGNoLklOU0VSVCwgbnVsbCwgcmlnaHROb2RlKSk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICB3YWxrKGxlZnROb2RlLCByaWdodE5vZGUsIHBhdGNoLCBpbmRleCk7XG4gICAgICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgICAgICBpZiAoaXNWTm9kZShsZWZ0Tm9kZSkgJiYgbGVmdE5vZGUuY291bnQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGluZGV4ICs9IGxlZnROb2RlLmNvdW50O1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgaWYgKG9yZGVyZWRTZXQubW92ZXMpIHtcbiAgICAgICAgICAgICAgICAgICAgLy8gUmVvcmRlciBub2RlcyBsYXN0XG4gICAgICAgICAgICAgICAgICAgIGFwcGx5ID0gYXBwZW5kUGF0Y2goYXBwbHksIG5ldyBWUGF0Y2goVlBhdGNoLk9SREVSLCBhLCBvcmRlcmVkU2V0Lm1vdmVzKSk7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgcmV0dXJuIGFwcGx5O1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBmdW5jdGlvbiBjbGVhclN0YXRlKHZOb2RlLCBwYXRjaCwgaW5kZXgpIHtcbiAgICAgICAgICAgICAgICAvLyBUT0RPOiBNYWtlIHRoaXMgYSBzaW5nbGUgd2Fsaywgbm90IHR3b1xuICAgICAgICAgICAgICAgIHVuaG9vayh2Tm9kZSwgcGF0Y2gsIGluZGV4KTtcbiAgICAgICAgICAgICAgICBkZXN0cm95V2lkZ2V0cyh2Tm9kZSwgcGF0Y2gsIGluZGV4KTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgLy8gUGF0Y2ggcmVjb3JkcyBmb3IgYWxsIGRlc3Ryb3llZCB3aWRnZXRzIG11c3QgYmUgYWRkZWQgYmVjYXVzZSB3ZSBuZWVkXG4gICAgICAgICAgICAvLyBhIERPTSBub2RlIHJlZmVyZW5jZSBmb3IgdGhlIGRlc3Ryb3kgZnVuY3Rpb25cbiAgICAgICAgICAgIGZ1bmN0aW9uIGRlc3Ryb3lXaWRnZXRzKHZOb2RlLCBwYXRjaCwgaW5kZXgpIHtcbiAgICAgICAgICAgICAgICBpZiAoaXNXaWRnZXQodk5vZGUpKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmICh0eXBlb2Ygdk5vZGUuZGVzdHJveSA9PT0gXCJmdW5jdGlvblwiKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBwYXRjaFtpbmRleF0gPSBhcHBlbmRQYXRjaChwYXRjaFtpbmRleF0sIG5ldyBWUGF0Y2goVlBhdGNoLlJFTU9WRSwgdk5vZGUsIG51bGwpKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoaXNWTm9kZSh2Tm9kZSkgJiYgKHZOb2RlLmhhc1dpZGdldHMgfHwgdk5vZGUuaGFzVGh1bmtzKSkge1xuICAgICAgICAgICAgICAgICAgICB2YXIgY2hpbGRyZW4gPSB2Tm9kZS5jaGlsZHJlbjtcbiAgICAgICAgICAgICAgICAgICAgdmFyIGxlbiA9IGNoaWxkcmVuLmxlbmd0aDtcbiAgICAgICAgICAgICAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCBsZW47IGkrKykge1xuICAgICAgICAgICAgICAgICAgICAgICAgdmFyIGNoaWxkID0gY2hpbGRyZW5baV07XG4gICAgICAgICAgICAgICAgICAgICAgICBpbmRleCArPSAxO1xuXG4gICAgICAgICAgICAgICAgICAgICAgICBkZXN0cm95V2lkZ2V0cyhjaGlsZCwgcGF0Y2gsIGluZGV4KTtcblxuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGlzVk5vZGUoY2hpbGQpICYmIGNoaWxkLmNvdW50KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaW5kZXggKz0gY2hpbGQuY291bnQ7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKGlzVGh1bmsodk5vZGUpKSB7XG4gICAgICAgICAgICAgICAgICAgIHRodW5rcyh2Tm9kZSwgbnVsbCwgcGF0Y2gsIGluZGV4KTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIC8vIENyZWF0ZSBhIHN1Yi1wYXRjaCBmb3IgdGh1bmtzXG4gICAgICAgICAgICBmdW5jdGlvbiB0aHVua3MoYSwgYiwgcGF0Y2gsIGluZGV4KSB7XG4gICAgICAgICAgICAgICAgdmFyIG5vZGVzID0gaGFuZGxlVGh1bmsoYSwgYik7XG4gICAgICAgICAgICAgICAgdmFyIHRodW5rUGF0Y2ggPSBkaWZmKG5vZGVzLmEsIG5vZGVzLmIpO1xuICAgICAgICAgICAgICAgIGlmIChoYXNQYXRjaGVzKHRodW5rUGF0Y2gpKSB7XG4gICAgICAgICAgICAgICAgICAgIHBhdGNoW2luZGV4XSA9IG5ldyBWUGF0Y2goVlBhdGNoLlRIVU5LLCBudWxsLCB0aHVua1BhdGNoKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIGhhc1BhdGNoZXMocGF0Y2gpIHtcbiAgICAgICAgICAgICAgICBmb3IgKHZhciBpbmRleCBpbiBwYXRjaCkge1xuICAgICAgICAgICAgICAgICAgICBpZiAoaW5kZXggIT09IFwiYVwiKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgLy8gRXhlY3V0ZSBob29rcyB3aGVuIHR3byBub2RlcyBhcmUgaWRlbnRpY2FsXG4gICAgICAgICAgICBmdW5jdGlvbiB1bmhvb2sodk5vZGUsIHBhdGNoLCBpbmRleCkge1xuICAgICAgICAgICAgICAgIGlmIChpc1ZOb2RlKHZOb2RlKSkge1xuICAgICAgICAgICAgICAgICAgICBpZiAodk5vZGUuaG9va3MpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHBhdGNoW2luZGV4XSA9IGFwcGVuZFBhdGNoKHBhdGNoW2luZGV4XSwgbmV3IFZQYXRjaChWUGF0Y2guUFJPUFMsIHZOb2RlLCB1bmRlZmluZWRLZXlzKHZOb2RlLmhvb2tzKSkpO1xuICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgaWYgKHZOb2RlLmRlc2NlbmRhbnRIb29rcyB8fCB2Tm9kZS5oYXNUaHVua3MpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHZhciBjaGlsZHJlbiA9IHZOb2RlLmNoaWxkcmVuO1xuICAgICAgICAgICAgICAgICAgICAgICAgdmFyIGxlbiA9IGNoaWxkcmVuLmxlbmd0aDtcbiAgICAgICAgICAgICAgICAgICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgbGVuOyBpKyspIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB2YXIgY2hpbGQgPSBjaGlsZHJlbltpXTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpbmRleCArPSAxO1xuXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdW5ob29rKGNoaWxkLCBwYXRjaCwgaW5kZXgpO1xuXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGlzVk5vZGUoY2hpbGQpICYmIGNoaWxkLmNvdW50KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGluZGV4ICs9IGNoaWxkLmNvdW50O1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoaXNUaHVuayh2Tm9kZSkpIHtcbiAgICAgICAgICAgICAgICAgICAgdGh1bmtzKHZOb2RlLCBudWxsLCBwYXRjaCwgaW5kZXgpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZnVuY3Rpb24gdW5kZWZpbmVkS2V5cyhvYmopIHtcbiAgICAgICAgICAgICAgICB2YXIgcmVzdWx0ID0ge307XG5cbiAgICAgICAgICAgICAgICBmb3IgKHZhciBrZXkgaW4gb2JqKSB7XG4gICAgICAgICAgICAgICAgICAgIHJlc3VsdFtrZXldID0gdW5kZWZpbmVkO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHJldHVybiByZXN1bHQ7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIC8vIExpc3QgZGlmZiwgbmFpdmUgbGVmdCB0byByaWdodCByZW9yZGVyaW5nXG4gICAgICAgICAgICBmdW5jdGlvbiByZW9yZGVyKGFDaGlsZHJlbiwgYkNoaWxkcmVuKSB7XG4gICAgICAgICAgICAgICAgLy8gTyhNKSB0aW1lLCBPKE0pIG1lbW9yeVxuICAgICAgICAgICAgICAgIHZhciBiQ2hpbGRJbmRleCA9IGtleUluZGV4KGJDaGlsZHJlbik7XG4gICAgICAgICAgICAgICAgdmFyIGJLZXlzID0gYkNoaWxkSW5kZXgua2V5cztcbiAgICAgICAgICAgICAgICB2YXIgYkZyZWUgPSBiQ2hpbGRJbmRleC5mcmVlO1xuXG4gICAgICAgICAgICAgICAgaWYgKGJGcmVlLmxlbmd0aCA9PT0gYkNoaWxkcmVuLmxlbmd0aCkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgICAgICAgICAgICAgY2hpbGRyZW46IGJDaGlsZHJlbixcbiAgICAgICAgICAgICAgICAgICAgICAgIG1vdmVzOiBudWxsXG4gICAgICAgICAgICAgICAgICAgIH07XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgLy8gTyhOKSB0aW1lLCBPKE4pIG1lbW9yeVxuICAgICAgICAgICAgICAgIHZhciBhQ2hpbGRJbmRleCA9IGtleUluZGV4KGFDaGlsZHJlbik7XG4gICAgICAgICAgICAgICAgdmFyIGFLZXlzID0gYUNoaWxkSW5kZXgua2V5cztcbiAgICAgICAgICAgICAgICB2YXIgYUZyZWUgPSBhQ2hpbGRJbmRleC5mcmVlO1xuXG4gICAgICAgICAgICAgICAgaWYgKGFGcmVlLmxlbmd0aCA9PT0gYUNoaWxkcmVuLmxlbmd0aCkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgICAgICAgICAgICAgY2hpbGRyZW46IGJDaGlsZHJlbixcbiAgICAgICAgICAgICAgICAgICAgICAgIG1vdmVzOiBudWxsXG4gICAgICAgICAgICAgICAgICAgIH07XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgLy8gTyhNQVgoTiwgTSkpIG1lbW9yeVxuICAgICAgICAgICAgICAgIHZhciBuZXdDaGlsZHJlbiA9IFtdO1xuXG4gICAgICAgICAgICAgICAgdmFyIGZyZWVJbmRleCA9IDA7XG4gICAgICAgICAgICAgICAgdmFyIGZyZWVDb3VudCA9IGJGcmVlLmxlbmd0aDtcbiAgICAgICAgICAgICAgICB2YXIgZGVsZXRlZEl0ZW1zID0gMDtcblxuICAgICAgICAgICAgICAgIC8vIEl0ZXJhdGUgdGhyb3VnaCBhIGFuZCBtYXRjaCBhIG5vZGUgaW4gYlxuICAgICAgICAgICAgICAgIC8vIE8oTikgdGltZSxcbiAgICAgICAgICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IGFDaGlsZHJlbi5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgICAgICAgICB2YXIgYUl0ZW0gPSBhQ2hpbGRyZW5baV07XG4gICAgICAgICAgICAgICAgICAgIHZhciBpdGVtSW5kZXg7XG5cbiAgICAgICAgICAgICAgICAgICAgaWYgKGFJdGVtLmtleSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGJLZXlzLmhhc093blByb3BlcnR5KGFJdGVtLmtleSkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBNYXRjaCB1cCB0aGUgb2xkIGtleXNcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpdGVtSW5kZXggPSBiS2V5c1thSXRlbS5rZXldO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIG5ld0NoaWxkcmVuLnB1c2goYkNoaWxkcmVuW2l0ZW1JbmRleF0pO1xuICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBSZW1vdmUgb2xkIGtleWVkIGl0ZW1zXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaXRlbUluZGV4ID0gaSAtIGRlbGV0ZWRJdGVtcysrO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIG5ld0NoaWxkcmVuLnB1c2gobnVsbCk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAvLyBNYXRjaCB0aGUgaXRlbSBpbiBhIHdpdGggdGhlIG5leHQgZnJlZSBpdGVtIGluIGJcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChmcmVlSW5kZXggPCBmcmVlQ291bnQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpdGVtSW5kZXggPSBiRnJlZVtmcmVlSW5kZXgrK107XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgbmV3Q2hpbGRyZW4ucHVzaChiQ2hpbGRyZW5baXRlbUluZGV4XSk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIFRoZXJlIGFyZSBubyBmcmVlIGl0ZW1zIGluIGIgdG8gbWF0Y2ggd2l0aFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIHRoZSBmcmVlIGl0ZW1zIGluIGEsIHNvIHRoZSBleHRyYSBmcmVlIG5vZGVzXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gYXJlIGRlbGV0ZWQuXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaXRlbUluZGV4ID0gaSAtIGRlbGV0ZWRJdGVtcysrO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIG5ld0NoaWxkcmVuLnB1c2gobnVsbCk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICB2YXIgbGFzdEZyZWVJbmRleCA9IGZyZWVJbmRleCA+PSBiRnJlZS5sZW5ndGggPyBiQ2hpbGRyZW4ubGVuZ3RoIDogYkZyZWVbZnJlZUluZGV4XTtcblxuICAgICAgICAgICAgICAgIC8vIEl0ZXJhdGUgdGhyb3VnaCBiIGFuZCBhcHBlbmQgYW55IG5ldyBrZXlzXG4gICAgICAgICAgICAgICAgLy8gTyhNKSB0aW1lXG4gICAgICAgICAgICAgICAgZm9yICh2YXIgaiA9IDA7IGogPCBiQ2hpbGRyZW4ubGVuZ3RoOyBqKyspIHtcbiAgICAgICAgICAgICAgICAgICAgdmFyIG5ld0l0ZW0gPSBiQ2hpbGRyZW5bal07XG5cbiAgICAgICAgICAgICAgICAgICAgaWYgKG5ld0l0ZW0ua2V5KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoIWFLZXlzLmhhc093blByb3BlcnR5KG5ld0l0ZW0ua2V5KSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIEFkZCBhbnkgbmV3IGtleWVkIGl0ZW1zXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gV2UgYXJlIGFkZGluZyBuZXcgaXRlbXMgdG8gdGhlIGVuZCBhbmQgdGhlbiBzb3J0aW5nIHRoZW1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBpbiBwbGFjZS4gSW4gZnV0dXJlIHdlIHNob3VsZCBpbnNlcnQgbmV3IGl0ZW1zIGluIHBsYWNlLlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIG5ld0NoaWxkcmVuLnB1c2gobmV3SXRlbSk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoaiA+PSBsYXN0RnJlZUluZGV4KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAvLyBBZGQgYW55IGxlZnRvdmVyIG5vbi1rZXllZCBpdGVtc1xuICAgICAgICAgICAgICAgICAgICAgICAgbmV3Q2hpbGRyZW4ucHVzaChuZXdJdGVtKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHZhciBzaW11bGF0ZSA9IG5ld0NoaWxkcmVuLnNsaWNlKCk7XG4gICAgICAgICAgICAgICAgdmFyIHNpbXVsYXRlSW5kZXggPSAwO1xuICAgICAgICAgICAgICAgIHZhciByZW1vdmVzID0gW107XG4gICAgICAgICAgICAgICAgdmFyIGluc2VydHMgPSBbXTtcbiAgICAgICAgICAgICAgICB2YXIgc2ltdWxhdGVJdGVtO1xuXG4gICAgICAgICAgICAgICAgZm9yICh2YXIgayA9IDA7IGsgPCBiQ2hpbGRyZW4ubGVuZ3RoOykge1xuICAgICAgICAgICAgICAgICAgICB2YXIgd2FudGVkSXRlbSA9IGJDaGlsZHJlbltrXTtcbiAgICAgICAgICAgICAgICAgICAgc2ltdWxhdGVJdGVtID0gc2ltdWxhdGVbc2ltdWxhdGVJbmRleF07XG5cbiAgICAgICAgICAgICAgICAgICAgLy8gcmVtb3ZlIGl0ZW1zXG4gICAgICAgICAgICAgICAgICAgIHdoaWxlIChzaW11bGF0ZUl0ZW0gPT09IG51bGwgJiYgc2ltdWxhdGUubGVuZ3RoKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICByZW1vdmVzLnB1c2gocmVtb3ZlKHNpbXVsYXRlLCBzaW11bGF0ZUluZGV4LCBudWxsKSk7XG4gICAgICAgICAgICAgICAgICAgICAgICBzaW11bGF0ZUl0ZW0gPSBzaW11bGF0ZVtzaW11bGF0ZUluZGV4XTtcbiAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgIGlmICghc2ltdWxhdGVJdGVtIHx8IHNpbXVsYXRlSXRlbS5rZXkgIT09IHdhbnRlZEl0ZW0ua2V5KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAvLyBpZiB3ZSBuZWVkIGEga2V5IGluIHRoaXMgcG9zaXRpb24uLi5cbiAgICAgICAgICAgICAgICAgICAgICAgIGlmICh3YW50ZWRJdGVtLmtleSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChzaW11bGF0ZUl0ZW0gJiYgc2ltdWxhdGVJdGVtLmtleSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBpZiBhbiBpbnNlcnQgZG9lc24ndCBwdXQgdGhpcyBrZXkgaW4gcGxhY2UsIGl0IG5lZWRzIHRvIG1vdmVcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGJLZXlzW3NpbXVsYXRlSXRlbS5rZXldICE9PSBrICsgMSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmVtb3Zlcy5wdXNoKHJlbW92ZShzaW11bGF0ZSwgc2ltdWxhdGVJbmRleCwgc2ltdWxhdGVJdGVtLmtleSkpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc2ltdWxhdGVJdGVtID0gc2ltdWxhdGVbc2ltdWxhdGVJbmRleF07XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBpZiB0aGUgcmVtb3ZlIGRpZG4ndCBwdXQgdGhlIHdhbnRlZCBpdGVtIGluIHBsYWNlLCB3ZSBuZWVkIHRvIGluc2VydCBpdFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKCFzaW11bGF0ZUl0ZW0gfHwgc2ltdWxhdGVJdGVtLmtleSAhPT0gd2FudGVkSXRlbS5rZXkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpbnNlcnRzLnB1c2goeyBrZXk6IHdhbnRlZEl0ZW0ua2V5LCB0bzogayB9KTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIGl0ZW1zIGFyZSBtYXRjaGluZywgc28gc2tpcCBhaGVhZFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc2ltdWxhdGVJbmRleCsrO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaW5zZXJ0cy5wdXNoKHsga2V5OiB3YW50ZWRJdGVtLmtleSwgdG86IGsgfSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpbnNlcnRzLnB1c2goeyBrZXk6IHdhbnRlZEl0ZW0ua2V5LCB0bzogayB9KTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaysrO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgLy8gYSBrZXkgaW4gc2ltdWxhdGUgaGFzIG5vIG1hdGNoaW5nIHdhbnRlZCBrZXksIHJlbW92ZSBpdFxuICAgICAgICAgICAgICAgICAgICAgICAgZWxzZSBpZiAoc2ltdWxhdGVJdGVtICYmIHNpbXVsYXRlSXRlbS5rZXkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICByZW1vdmVzLnB1c2gocmVtb3ZlKHNpbXVsYXRlLCBzaW11bGF0ZUluZGV4LCBzaW11bGF0ZUl0ZW0ua2V5KSk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBzaW11bGF0ZUluZGV4Kys7XG4gICAgICAgICAgICAgICAgICAgICAgICBrKys7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAvLyByZW1vdmUgYWxsIHRoZSByZW1haW5pbmcgbm9kZXMgZnJvbSBzaW11bGF0ZVxuICAgICAgICAgICAgICAgIHdoaWxlIChzaW11bGF0ZUluZGV4IDwgc2ltdWxhdGUubGVuZ3RoKSB7XG4gICAgICAgICAgICAgICAgICAgIHNpbXVsYXRlSXRlbSA9IHNpbXVsYXRlW3NpbXVsYXRlSW5kZXhdO1xuICAgICAgICAgICAgICAgICAgICByZW1vdmVzLnB1c2gocmVtb3ZlKHNpbXVsYXRlLCBzaW11bGF0ZUluZGV4LCBzaW11bGF0ZUl0ZW0gJiYgc2ltdWxhdGVJdGVtLmtleSkpO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIC8vIElmIHRoZSBvbmx5IG1vdmVzIHdlIGhhdmUgYXJlIGRlbGV0ZXMgdGhlbiB3ZSBjYW4ganVzdFxuICAgICAgICAgICAgICAgIC8vIGxldCB0aGUgZGVsZXRlIHBhdGNoIHJlbW92ZSB0aGVzZSBpdGVtcy5cbiAgICAgICAgICAgICAgICBpZiAocmVtb3Zlcy5sZW5ndGggPT09IGRlbGV0ZWRJdGVtcyAmJiAhaW5zZXJ0cy5sZW5ndGgpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGNoaWxkcmVuOiBuZXdDaGlsZHJlbixcbiAgICAgICAgICAgICAgICAgICAgICAgIG1vdmVzOiBudWxsXG4gICAgICAgICAgICAgICAgICAgIH07XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgICAgICAgICAgY2hpbGRyZW46IG5ld0NoaWxkcmVuLFxuICAgICAgICAgICAgICAgICAgICBtb3Zlczoge1xuICAgICAgICAgICAgICAgICAgICAgICAgcmVtb3ZlczogcmVtb3ZlcyxcbiAgICAgICAgICAgICAgICAgICAgICAgIGluc2VydHM6IGluc2VydHNcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH07XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIHJlbW92ZShhcnIsIGluZGV4LCBrZXkpIHtcbiAgICAgICAgICAgICAgICBhcnIuc3BsaWNlKGluZGV4LCAxKTtcblxuICAgICAgICAgICAgICAgIHJldHVybiB7XG4gICAgICAgICAgICAgICAgICAgIGZyb206IGluZGV4LFxuICAgICAgICAgICAgICAgICAgICBrZXk6IGtleVxuICAgICAgICAgICAgICAgIH07XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIGtleUluZGV4KGNoaWxkcmVuKSB7XG4gICAgICAgICAgICAgICAgdmFyIGtleXMgPSB7fTtcbiAgICAgICAgICAgICAgICB2YXIgZnJlZSA9IFtdO1xuICAgICAgICAgICAgICAgIHZhciBsZW5ndGggPSBjaGlsZHJlbi5sZW5ndGg7XG5cbiAgICAgICAgICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IGxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciBjaGlsZCA9IGNoaWxkcmVuW2ldO1xuXG4gICAgICAgICAgICAgICAgICAgIGlmIChjaGlsZC5rZXkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGtleXNbY2hpbGQua2V5XSA9IGk7XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBmcmVlLnB1c2goaSk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgICAgICAgICBrZXlzOiBrZXlzLCAvLyBBIGhhc2ggb2Yga2V5IG5hbWUgdG8gaW5kZXhcbiAgICAgICAgICAgICAgICAgICAgZnJlZTogZnJlZSAvLyBBbiBhcnJheSBvZiB1bmtleWVkIGl0ZW0gaW5kaWNlc1xuICAgICAgICAgICAgICAgIH07XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIGFwcGVuZFBhdGNoKGFwcGx5LCBwYXRjaCkge1xuICAgICAgICAgICAgICAgIGlmIChhcHBseSkge1xuICAgICAgICAgICAgICAgICAgICBpZiAoaXNBcnJheShhcHBseSkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGFwcGx5LnB1c2gocGF0Y2gpO1xuICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgYXBwbHkgPSBbYXBwbHksIHBhdGNoXTtcbiAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBhcHBseTtcbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gcGF0Y2g7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9LCB7IFwiLi4vdm5vZGUvaGFuZGxlLXRodW5rXCI6IDI0LCBcIi4uL3Zub2RlL2lzLXRodW5rXCI6IDI1LCBcIi4uL3Zub2RlL2lzLXZub2RlXCI6IDI3LCBcIi4uL3Zub2RlL2lzLXZ0ZXh0XCI6IDI4LCBcIi4uL3Zub2RlL2lzLXdpZGdldFwiOiAyOSwgXCIuLi92bm9kZS92cGF0Y2hcIjogMzIsIFwiLi9kaWZmLXByb3BzXCI6IDM0LCBcIngtaXMtYXJyYXlcIjogMTIgfV0gfSwge30sIFs0XSkoNCk7XG59KTtcblxuY29uc3Qgc3RhcnQgPSBmdW5jdGlvbiAoZG9tUm9vdCwgcmVuZGVyRm4sIGluaXRpYWxTdGF0ZSwgb3B0aW9ucyA9IFtdKSB7XG4gIGxldCBwaWQgPSBzZWxmLnByb2Nlc3Nlcy5zcGF3bigpO1xuXG4gIGlmIChLZXl3b3JkLmhhc19rZXlfX3FtX18ob3B0aW9ucywgS2VybmVsLlNwZWNpYWxGb3Jtcy5hdG9tKCduYW1lJykpKSB7XG4gICAgcGlkID0gc2VsZi5wcm9jZXNzZXMucmVnaXN0ZXIoS2V5d29yZC5nZXQob3B0aW9ucywgS2VybmVsLlNwZWNpYWxGb3Jtcy5hdG9tKCduYW1lJykpLCBwaWQpO1xuICB9XG5cbiAgY29uc3QgdHJlZSA9IHJlbmRlckZuLmFwcGx5KHRoaXMsIGluaXRpYWxTdGF0ZSk7XG4gIGNvbnN0IHJvb3ROb2RlID0gVmlydHVhbERPTS5jcmVhdGUodHJlZSk7XG5cbiAgZG9tUm9vdC5hcHBlbmRDaGlsZChyb290Tm9kZSk7XG5cbiAgc2VsZi5wcm9jZXNzZXMucHV0KHBpZCwgJ3N0YXRlJywgS2VybmVsLlNwZWNpYWxGb3Jtcy50dXBsZShyb290Tm9kZSwgdHJlZSwgcmVuZGVyRm4pKTtcbiAgcmV0dXJuIEtlcm5lbC5TcGVjaWFsRm9ybXMudHVwbGUoS2VybmVsLlNwZWNpYWxGb3Jtcy5hdG9tKCdvaycpLCBwaWQpO1xufTtcblxuY29uc3Qgc3RvcCA9IGZ1bmN0aW9uIChhZ2VudCwgdGltZW91dCA9IDUwMDApIHtcbiAgc2VsZi5wcm9jZXNzZXMuZXhpdChhZ2VudCk7XG4gIHJldHVybiBLZXJuZWwuU3BlY2lhbEZvcm1zLmF0b20oJ29rJyk7XG59O1xuXG5jb25zdCByZW5kZXIgPSBmdW5jdGlvbiAoYWdlbnQsIHN0YXRlKSB7XG5cbiAgY29uc3QgY3VycmVudF9zdGF0ZSA9IHNlbGYucHJvY2Vzc2VzLmdldChhZ2VudCwgJ3N0YXRlJyk7XG5cbiAgbGV0IHJvb3ROb2RlID0gS2VybmVsLmVsZW0oY3VycmVudF9zdGF0ZSwgMCk7XG4gIGxldCB0cmVlID0gS2VybmVsLmVsZW0oY3VycmVudF9zdGF0ZSwgMSk7XG4gIGxldCByZW5kZXJGbiA9IEtlcm5lbC5lbGVtKGN1cnJlbnRfc3RhdGUsIDIpO1xuXG4gIGxldCBuZXdUcmVlID0gcmVuZGVyRm4uYXBwbHkodGhpcywgc3RhdGUpO1xuXG4gIGxldCBwYXRjaGVzID0gVmlydHVhbERPTS5kaWZmKHRyZWUsIG5ld1RyZWUpO1xuICByb290Tm9kZSA9IFZpcnR1YWxET00ucGF0Y2gocm9vdE5vZGUsIHBhdGNoZXMpO1xuXG4gIHNlbGYucHJvY2Vzc2VzLnB1dChhZ2VudCwgJ3N0YXRlJywgS2VybmVsLlNwZWNpYWxGb3Jtcy50dXBsZShyb290Tm9kZSwgbmV3VHJlZSwgcmVuZGVyRm4pKTtcblxuICByZXR1cm4gS2VybmVsLlNwZWNpYWxGb3Jtcy5hdG9tKCdvaycpO1xufTtcblxudmFyIHZpZXcgPSB7XG4gIHN0YXJ0LFxuICBzdG9wLFxuICByZW5kZXJcbn07XG5cbnNlbGYucHJvY2Vzc2VzID0gc2VsZi5wcm9jZXNzZXMgfHwgbmV3IFByb2Nlc3NTeXN0ZW0oKTtcblxuY29uc3QgQ29yZSA9IEM7XG5cbmV4cG9ydCB7IENvcmUsIEtlcm5lbCwgQXRvbSwgRW51bSwgSW50ZWdlciwgTGlzdCwgUmFuZ2UsIFR1cGxlLCBBZ2VudCwgS2V5d29yZCwgYmFzZSBhcyBCYXNlLCBTdHJpbmckMSBhcyBTdHJpbmcsIGJpdHdpc2UgYXMgQml0d2lzZSwgRW51bWVyYWJsZSwgQ29sbGVjdGFibGUsIEluc3BlY3QsIG1hcCBhcyBNYXAsIHNldCBhcyBTZXQsIE1hcFNldCwgVmlydHVhbERPTSwgdmlldyBhcyBWaWV3IH07Il0sImZpbGUiOiJlbGl4aXIuanMiLCJzb3VyY2VSb290IjoiL3NvdXJjZS8ifQ== \ No newline at end of file diff --git a/src/javascript/lib/core.js b/src/javascript/lib/core.js index 278bbf93..014cd50a 100644 --- a/src/javascript/lib/core.js +++ b/src/javascript/lib/core.js @@ -1,7 +1,7 @@ import ProcessSystem from './core/process_system'; import { Tuple, PID, IntegerType, FloatType } from './core/primitives'; import BitString from './core/bit_string'; -import * as Patterns from './core/patterns'; +import Patterns from './core/patterns'; import { call_property } from './core/functions'; export { diff --git a/src/javascript/lib/core/patterns.js b/src/javascript/lib/core/patterns.js index 8d455b04..2978dbc2 100644 --- a/src/javascript/lib/core/patterns.js +++ b/src/javascript/lib/core/patterns.js @@ -4,7 +4,7 @@ import { defmatch, match, MatchError, match_no_throw, patternMap, Case, make_cas import { variable, wildcard, startsWith, capture, headTail, type, bound } from "./patterns/types"; -export { +export default { defmatch, match, MatchError, match_no_throw, variable, wildcard, startsWith, capture, headTail, type, bound, Case, make_case From 2007202acb2670683b0412320eae6d24cca0c21a Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Fri, 4 Dec 2015 15:42:20 -0600 Subject: [PATCH 072/860] Fixed broken tests --- src/javascript/tests/case.spec.js | 6 +++--- src/javascript/tests/cond.spec.js | 4 ++-- src/javascript/tests/try.spec.js | 4 ++-- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/src/javascript/tests/case.spec.js b/src/javascript/tests/case.spec.js index 7a2d7bb4..921f4a40 100644 --- a/src/javascript/tests/case.spec.js +++ b/src/javascript/tests/case.spec.js @@ -1,4 +1,4 @@ -var Patterns = require("../lib/patterns/patterns"); +var Patterns = require("../lib/core/patterns"); var Enum = require('../lib/enum'); var Kernel = require('../lib/kernel'); var expect = require('chai').expect; @@ -16,7 +16,7 @@ describe('case', () => { Patterns.make_case( [Patterns.variable()], function(value){ return value; } - ) + ) ]; let result = Kernel.SpecialForms._case("thing", clauses); @@ -24,4 +24,4 @@ describe('case', () => { expect(result).to.equal("thing"); }); -}); \ No newline at end of file +}); diff --git a/src/javascript/tests/cond.spec.js b/src/javascript/tests/cond.spec.js index 7f777756..64de0089 100644 --- a/src/javascript/tests/cond.spec.js +++ b/src/javascript/tests/cond.spec.js @@ -1,4 +1,4 @@ -var Patterns = require("../lib/patterns/patterns"); +var Patterns = require("../lib/core/patterns"); var Enum = require('../lib/enum'); var Kernel = require('../lib/kernel'); var expect = require('chai').expect; @@ -18,4 +18,4 @@ describe('cond', () => { expect(result).to.equal("This will"); }); -}); \ No newline at end of file +}); diff --git a/src/javascript/tests/try.spec.js b/src/javascript/tests/try.spec.js index b0d1ba7d..88e1dd5e 100644 --- a/src/javascript/tests/try.spec.js +++ b/src/javascript/tests/try.spec.js @@ -1,4 +1,4 @@ -var Patterns = require("../lib/patterns/patterns"); +var Patterns = require("../lib/core/patterns"); var Enum = require('../lib/enum'); var Kernel = require('../lib/kernel'); var expect = require('chai').expect; @@ -34,4 +34,4 @@ describe('try', () => { expect(value).to.equal(Kernel.SpecialForms.atom('large')); }); -}); \ No newline at end of file +}); From 447b4bbea97a99d16debaf61897e077d87a4d501 Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Fri, 4 Dec 2015 20:28:58 -0600 Subject: [PATCH 073/860] Added View module for documentation --- lib/elixir_script/lib/html.ex | 4 +++- lib/elixir_script/lib/view.ex | 41 +++++++++++++++++++++++++++++++++++ 2 files changed, 44 insertions(+), 1 deletion(-) create mode 100644 lib/elixir_script/lib/view.ex diff --git a/lib/elixir_script/lib/html.ex b/lib/elixir_script/lib/html.ex index 17b2e4ce..e2f3f35d 100644 --- a/lib/elixir_script/lib/html.ex +++ b/lib/elixir_script/lib/html.ex @@ -2,7 +2,7 @@ defmodule ElixirScript.Html do @moduledoc """ Defines macros for HTML elements to be used to build up a virtual dom tree. The virtual dom tree defined here can then be used with macros defined in the - VDom module + VDom module or with the View module tree = Html.div [id: "hello"] do Html.span do @@ -19,6 +19,8 @@ defmodule ElixirScript.Html do patches = VDom.diff(tree, newTree) rootNode = VDom.patch(rootNode, patches) + Instead of patching and diffing manually, the `View` module can also be used + instead. """ @external_resource tags_path = Path.join([__DIR__, "tags.txt"]) diff --git a/lib/elixir_script/lib/view.ex b/lib/elixir_script/lib/view.ex new file mode 100644 index 00000000..2e6d1fda --- /dev/null +++ b/lib/elixir_script/lib/view.ex @@ -0,0 +1,41 @@ +defmodule ElixirScript.View do + @moduledoc """ + Defines a module to handle view state. Handles the diffing and patching + normally done manually using the `VDom` module. + + def render(id) do + Html.div [id: "hello"] do + Html.span do + "Hello" + end + end + end + + #Starts View state and renders initial view + {:ok, view} = View.start(:document.body, &render/1, ["hello"]) + + #Updates the view with the new args + View.render(view, ["world"]) + """ + + + @doc """ + Starts the View state. This will render the initial view using the + render_func and the args + """ + defmacro start(dom_root, render_func, args, options \\ []) do + end + + @doc """ + Stops the View state + """ + defmacro stop(view) do + end + + @doc """ + Updates the view by passing the args to the render_func + """ + defmacro render(view, args) do + end + +end From f961f5328b5eac117789b563ea4a858a13a632fa Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Fri, 4 Dec 2015 20:30:34 -0600 Subject: [PATCH 074/860] Turned View macros into functions --- lib/elixir_script/lib/view.ex | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/lib/elixir_script/lib/view.ex b/lib/elixir_script/lib/view.ex index 2e6d1fda..5c484430 100644 --- a/lib/elixir_script/lib/view.ex +++ b/lib/elixir_script/lib/view.ex @@ -23,19 +23,19 @@ defmodule ElixirScript.View do Starts the View state. This will render the initial view using the render_func and the args """ - defmacro start(dom_root, render_func, args, options \\ []) do + def start(dom_root, render_func, args, options \\ []) do end @doc """ Stops the View state """ - defmacro stop(view) do + def stop(view) do end @doc """ Updates the view by passing the args to the render_func """ - defmacro render(view, args) do + def render(view, args) do end end From 3659255cea720de4a4367312d82af8ab28204130 Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Fri, 4 Dec 2015 20:33:04 -0600 Subject: [PATCH 075/860] Updated CHANGELOG.md --- CHANGELOG.md | 2 ++ GettingStarted.md | 4 ++-- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 33ea116a..0c1f045e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,6 +10,8 @@ using the ElixirScript.Html module * Added `stdlib_path` compiler option to specify the es6 path to the standard library. If used, elixir.js will not be exported with the compiled modules + * Moved non-elixir JavaScript code into `core` es6 module. This will hopefully + make it so ElixirScript Standard Library modules can be defined in Elixir soon. # v0.13.0 diff --git a/GettingStarted.md b/GettingStarted.md index 76fbd63d..263d3058 100644 --- a/GettingStarted.md +++ b/GettingStarted.md @@ -142,7 +142,7 @@ The intent of this guide is to get you started with ElixirScript. It will give y * `:root` - a binary path prepended to the path of the standard lib imports if needed * `:env` - a Macro.env struct to use. This is most useful when using macros. Make sure that the given env has the macros required. Defaults to `__ENV__`. - You may notice the mention of macros. Using the module in your code allows you to use macros. As long as you pass in an evironment with the macros loaded. By default, it uses the current environment. + You may notice the mention of macros. Using the module in your code allows you to use macros. As long as you pass in an environment with the macros loaded. By default, it uses the current environment. For example, if I have a module with a macro in it @@ -210,4 +210,4 @@ I am a gulp user and I use elixirscript with gulp. Here is a snippet of how I my }); ``` -This is also the setup I use when using ElixirScript with Phoenix. If you are a brunch user, there is n [ElixirScript runch plugin](https://www.npmjs.com/package/elixirscript-brunch) +This is also the setup I use when using ElixirScript with Phoenix. If you are a brunch user, there is n [ElixirScript brunch plugin](https://www.npmjs.com/package/elixirscript-brunch) From 04dc3a1ea6e60d643b110482465d36d0a4e79400 Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Sat, 5 Dec 2015 11:19:52 -0600 Subject: [PATCH 076/860] Fixed some warnings --- lib/elixir_script.ex | 5 +- lib/elixir_script/lib/js.ex | 15 ++-- lib/elixir_script/module.ex | 8 +- lib/elixir_script/translator.ex | 4 +- lib/elixir_script/translator/cond.ex | 5 +- lib/elixir_script/translator/for.ex | 11 ++- lib/elixir_script/translator/import.ex | 109 ----------------------- lib/elixir_script/translator/js.ex | 28 +++--- lib/elixir_script/translator/kernel.ex | 10 +-- lib/elixir_script/translator/map.ex | 23 +++-- lib/elixir_script/translator/protocol.ex | 4 +- lib/elixir_script/translator/quote.ex | 8 +- mix.exs | 4 +- mix.lock | 10 +-- 14 files changed, 67 insertions(+), 177 deletions(-) diff --git a/lib/elixir_script.ex b/lib/elixir_script.ex index 004d0f3d..50b1291f 100644 --- a/lib/elixir_script.ex +++ b/lib/elixir_script.ex @@ -150,7 +150,7 @@ defmodule ElixirScript do |> process_include_path(include_path) end - defp process_module(%JSModule{} = module, root, env, import_standard_libs, stdlib_path) do + defp process_module(%JSModule{} = module, root, _, import_standard_libs, stdlib_path) do file_path = create_file_name(module) standard_libs_import = @@ -167,9 +167,6 @@ defmodule ElixirScript do {file_path, program} end - defp process_module(module, _root, _, _), - do: {"", module} - defp create_file_name(%JSModule{name: module_list}) do name = ElixirScript.Translator.Import.make_file_path(module_list) "#{name}.js" diff --git a/lib/elixir_script/lib/js.ex b/lib/elixir_script/lib/js.ex index 29e1125a..4ba5d7c3 100644 --- a/lib/elixir_script/lib/js.ex +++ b/lib/elixir_script/lib/js.ex @@ -6,7 +6,8 @@ defmodule ElixirScript.JS do ex: JS.new User, ["first_name", "last_name"] """ - defmacro new(module, params) + defmacro new(module, params) do + end @doc """ @@ -15,7 +16,8 @@ defmodule ElixirScript.JS do ex: JS.update elem, "width", 100 """ - defmacro update(object, property, value) + defmacro update(object, property, value) do + end @doc """ @@ -33,18 +35,21 @@ defmodule ElixirScript.JS do JS.import [A, B, C], "a" #translates to "import {A, B, C} from 'a'" """ - defmacro import(module, from) + defmacro import(module, from) do + end @doc """ Turns an ElixirScript data structure into a JavaScript one. """ - defmacro to_js(value) + defmacro to_js(value) do + end @doc """ Turns an ElixirScript data structure into JSON. """ - defmacro to_json(value) + defmacro to_json(value) do + end end diff --git a/lib/elixir_script/module.ex b/lib/elixir_script/module.ex index a25f0d49..ad64f191 100644 --- a/lib/elixir_script/module.ex +++ b/lib/elixir_script/module.ex @@ -51,12 +51,12 @@ defmodule ElixirScript.Module do end def imported?(module, function_name) do - imports = Enum.find(module.imports, fn({_, functions}) -> - Enum.member?(functions, function_name) + imported_modules = Enum.find(module.imports, fn({_, funcs}) -> + Enum.member?(funcs, function_name) end) - if imports do - elem(imports, 0) + if imported_modules do + elem(imported_modules, 0) end end diff --git a/lib/elixir_script/translator.ex b/lib/elixir_script/translator.ex index 4904d378..f1eb0777 100644 --- a/lib/elixir_script/translator.ex +++ b/lib/elixir_script/translator.ex @@ -312,9 +312,9 @@ defmodule ElixirScript.Translator do %ElixirScript.Translator.Group{} end - defp do_translate({:|, _, [elem, list]}, env) do + defp do_translate({:|, _, [item, list]}, env) do quoted = quote do - List.prepend(unquote(list), unquote(elem)) + List.prepend(unquote(list), unquote(item)) end translate(quoted, env) diff --git a/lib/elixir_script/translator/cond.ex b/lib/elixir_script/translator/cond.ex index 819e03cd..0a3c2f79 100644 --- a/lib/elixir_script/translator/cond.ex +++ b/lib/elixir_script/translator/cond.ex @@ -5,7 +5,6 @@ defmodule ElixirScript.Translator.Cond do alias ElixirScript.Translator alias ElixirScript.Translator.Primitive alias ElixirScript.Translator.Function - alias ElixirScript.Translator.Utils def make_cond(clauses, env) do JS.call_expression( @@ -27,5 +26,5 @@ defmodule ElixirScript.Translator.Cond do Primitive.make_list_no_translate([translated_clause, function]) end) end - -end \ No newline at end of file + +end diff --git a/lib/elixir_script/translator/for.ex b/lib/elixir_script/translator/for.ex index 1f9d0d05..65874561 100644 --- a/lib/elixir_script/translator/for.ex +++ b/lib/elixir_script/translator/for.ex @@ -2,7 +2,6 @@ defmodule ElixirScript.Translator.For do @moduledoc false alias ESTree.Tools.Builder, as: JS alias ElixirScript.Translator - alias ElixirScript.Translator.Utils alias ElixirScript.PatternMatching.Match alias ElixirScript.Translator.Primitive alias ElixirScript.Translator.Function @@ -40,7 +39,7 @@ defmodule ElixirScript.Translator.For do state.args, [], Function.make_function_body(expression2, env) - ) + ) %{ state | into: Translator.translate(expression, env), fun: fun } @@ -50,7 +49,7 @@ defmodule ElixirScript.Translator.For do state.args, [], Function.make_function_body(expression, env) - ) + ) %{ state | fun: fun } (filter, state) -> @@ -60,7 +59,7 @@ defmodule ElixirScript.Translator.For do Function.make_function_body(filter, env) ) - %{ state | filter: fun } + %{ state | filter: fun } end) - end -end \ No newline at end of file + end +end diff --git a/lib/elixir_script/translator/import.ex b/lib/elixir_script/translator/import.ex index eb7ad17d..21c7d37f 100644 --- a/lib/elixir_script/translator/import.ex +++ b/lib/elixir_script/translator/import.ex @@ -48,115 +48,6 @@ defmodule ElixirScript.Translator.Import do ) end - def make_import(module_name_list, [], _) do - module = State.get_module(module_name_list) - functions = ElixirScript.Module.functions(module) - - functions = Enum.map(functions, fn - ({name, _arity}) -> - name - (name) -> - name - end) - - specifiers = Enum.map(functions, fn - ({name, _arity}) -> - name = JS.identifier(name) - JS.import_specifier( - name, - name - ) - (name) -> - name = JS.identifier(name) - JS.import_specifier( - name, - name - ) - end) - - import_path = make_source(module_name_list) - - JS.import_declaration(specifiers, JS.identifier(import_path)) - end - - def make_import(module_name_list, [only: :functions], _) do - module = State.get_module(module_name_list) - functions = ElixirScript.Module.functions(module) - - functions = Enum.map(functions, fn - ({name, _arity}) -> - name - (name) -> - name - end) - - specifiers = Enum.map(functions, fn - (name) -> - name = JS.identifier(name) - JS.import_specifier( - name, - name - ) - end) - - import_path = make_source(module_name_list) - - JS.import_declaration(specifiers, JS.identifier(import_path)) - end - - def make_import(module_name_list, [only: only], _) do - only = Enum.map(only, fn - ({name, _arity}) -> - name - (name) -> - name - end) - - module = State.get_module(module_name_list) - - functions = ElixirScript.Module.functions(module) - |> get_functions_from_module([only: only]) - - specifiers = Enum.map(functions, fn - (name) -> - name = JS.identifier(name) - JS.import_specifier( - name, - name - ) - end) - - import_path = make_source(module_name_list) - - JS.import_declaration(specifiers, JS.identifier(import_path)) - end - - def make_import(module_name_list, [except: except], _) do - except = Enum.map(except, fn - ({name, _arity}) -> - name - (name) -> - name - end) - - module = State.get_module(module_name_list) - functions = ElixirScript.Module.functions(module) - |> get_functions_from_module([except: except]) - - specifiers = Enum.map(functions, fn - (name) -> - name = JS.identifier(name) - JS.import_specifier( - name, - name - ) - end) - - import_path = make_source(module_name_list) - - JS.import_declaration(specifiers, JS.identifier(import_path)) - end - defp make_source(name) do root = ElixirScript.State.get().root "'#{make_root(root)}#{make_file_path(name)}'" diff --git a/lib/elixir_script/translator/js.ex b/lib/elixir_script/translator/js.ex index 23154f71..606af69c 100644 --- a/lib/elixir_script/translator/js.ex +++ b/lib/elixir_script/translator/js.ex @@ -1,6 +1,6 @@ defmodule ElixirScript.Translator.JS do @moduledoc false - + alias ESTree.Tools.Builder alias ElixirScript.Translator alias ElixirScript.Translator.Utils @@ -30,14 +30,14 @@ defmodule ElixirScript.Translator.JS do Builder.member_expression( Translator.translate(object, env), Translator.translate(property, env), - true + true ), Translator.translate(value, env) ) end defp do_translate({:import, _, [module_names, from]}, env) when is_list(module_names) do - import_specifiers = Enum.map(module_names, fn(x) -> + import_specifiers = Enum.map(module_names, fn(x) -> Builder.import_specifier( Translator.translate(x, env), Translator.translate(x, env) @@ -57,16 +57,8 @@ defmodule ElixirScript.Translator.JS do build_import_declaration([import_specifier], from) end - defp build_import_declaration(import_specifiers, from) do - Builder.import_declaration( - import_specifiers, - Builder.identifier("'#{from}'") - ) - end - - defp do_translate({:to_js, _, [value]}, env) do - quoted = quote do + quoted = quote do if is_list(unquote(value)) || is_map(unquote(value)) || is_tuple(unquote(value)) do value.toJS() else @@ -79,11 +71,19 @@ defmodule ElixirScript.Translator.JS do defp do_translate({:to_json, _, [value]}, env) do - quoted = quote do + quoted = quote do JSON.stringify(JS.to_js(unquote(value))) end Translator.translate(quoted, env) end -end \ No newline at end of file + + defp build_import_declaration(import_specifiers, from) do + Builder.import_declaration( + import_specifiers, + Builder.identifier("'#{from}'") + ) + end + +end diff --git a/lib/elixir_script/translator/kernel.ex b/lib/elixir_script/translator/kernel.ex index be57aeaa..92fae8e7 100644 --- a/lib/elixir_script/translator/kernel.ex +++ b/lib/elixir_script/translator/kernel.ex @@ -216,16 +216,16 @@ defmodule ElixirScript.Translator.Kernel do |> Translator.translate(env) end - defp do_translate({:throw, _, [params]} = ast, env) do + defp do_translate({:throw, _, [params]}, env) do JS.throw_statement(Translator.translate(params, env)) end defp do_translate({:|>, _, [left, right]}, env) do case right do {{:., meta, [module, fun]}, meta2, params} -> - Translator.translate({{:., meta, [module, fun]}, meta2, [left] ++ params}, env) + Translator.translate({{:., meta, [module, fun]}, meta2, [left] ++ params}, env) {fun, meta, params} -> - Translator.translate({fun, meta, [left] ++ params}, env) + Translator.translate({fun, meta, [left] ++ params}, env) end end @@ -292,7 +292,7 @@ defmodule ElixirScript.Translator.Kernel do end defp do_translate({name, _, params}, env) do - Function.make_function_call({:__aliases__, [], [:Elixir, :Kernel]}, name, params, env) + Function.make_function_call({:__aliases__, [], [:Elixir, :Kernel]}, name, params, env) end -end \ No newline at end of file +end diff --git a/lib/elixir_script/translator/map.ex b/lib/elixir_script/translator/map.ex index 2c86e200..a309591f 100644 --- a/lib/elixir_script/translator/map.ex +++ b/lib/elixir_script/translator/map.ex @@ -3,7 +3,6 @@ defmodule ElixirScript.Translator.Map do alias ESTree.Tools.Builder, as: JS alias ElixirScript.Translator alias ElixirScript.Translator.Primitive - alias ElixirScript.Translator.Utils def make_map(object_expression) do JS.call_expression( @@ -24,38 +23,38 @@ defmodule ElixirScript.Translator.Map do end def make_object(properties, env) do - object = properties + properties |> Enum.map(fn - ({x, {:__aliases__, _, [value]}}) -> make_property(Translator.translate(x, env), JS.identifier(value)) - ({x, y}) -> make_property(Translator.translate(x, env), Translator.translate(y, env)) + ({x, {:__aliases__, _, [value]}}) -> make_property(Translator.translate(x, env), JS.identifier(value)) + ({x, y}) -> make_property(Translator.translate(x, env), Translator.translate(y, env)) end) |> JS.object_expression |> make_map end def make_property(%ESTree.Identifier{} = key, value) do - JS.property(key, value) + JS.property(key, value) end - def make_property(%ESTree.Literal{value: k} = key, value) when is_binary(k) do - JS.property(JS.identifier(k), value) + def make_property(%ESTree.Literal{value: k}, value) when is_binary(k) do + JS.property(JS.identifier(k), value) end def make_property(key, value) do - JS.property(key, value, :init, false, false, true) + JS.property(key, value, :init, false, false, true) end def make_shorthand_property(%ESTree.Identifier{} = key) do - JS.property(key, key, :init, true) + JS.property(key, key, :init, true) end def make_map_update(map, data, env) do map = Translator.translate(map, env) map_update = JS.object_expression( - Enum.map(data, - fn({key, value}) -> - make_property(Translator.translate(key, env), Translator.translate(value, env)) + Enum.map(data, + fn({key, value}) -> + make_property(Translator.translate(key, env), Translator.translate(value, env)) end ) ) diff --git a/lib/elixir_script/translator/protocol.ex b/lib/elixir_script/translator/protocol.ex index 9c85a5c6..a7e9dff7 100644 --- a/lib/elixir_script/translator/protocol.ex +++ b/lib/elixir_script/translator/protocol.ex @@ -263,9 +263,9 @@ defmodule ElixirScript.Translator.Protocol do end - defp map_to_js({:__aliases__, _, struct}) do + defp map_to_js({:__aliases__, _, module}) do ElixirScript.Translator.Struct.get_struct_class( - struct, + module, ElixirScript.State.get().env ) end diff --git a/lib/elixir_script/translator/quote.ex b/lib/elixir_script/translator/quote.ex index 815355c7..e3932d61 100644 --- a/lib/elixir_script/translator/quote.ex +++ b/lib/elixir_script/translator/quote.ex @@ -12,7 +12,7 @@ defmodule ElixirScript.Translator.Quote do def make_quote(opts, expr, env) when is_list(expr) do has_unquote_splicing = Enum.any?(expr, fn ({:unquote_splicing, _, _}) -> true - (_) -> false + (_) -> false end) if(has_unquote_splicing) do @@ -47,8 +47,8 @@ defmodule ElixirScript.Translator.Quote do Primitive.make_tuple_quoted(opts, [:unquote, context, params], env) end - def make_quote(_, {:alias!, _, [_alias]}, _) do - _alias + def make_quote(_, {:alias!, _, [the_alias]}, _) do + the_alias end def make_quote(_, {:unquote, _, [param]}, env) do @@ -79,4 +79,4 @@ defmodule ElixirScript.Translator.Quote do binds[name] != nil end -end \ No newline at end of file +end diff --git a/mix.exs b/mix.exs index aa0cb0e7..55d2dbff 100644 --- a/mix.exs +++ b/mix.exs @@ -34,8 +34,8 @@ defmodule ElixirScript.Mixfile do {:earmark, "~> 0.1", only: :dev }, {:ex_doc, "~> 0.10", only: :dev }, {:benchfella, "~> 0.2", only: :test}, - {:excoveralls, "~> 0.3", only: :test}, - {:credo, "~> 0.1.9", only: [:dev, :test]} + {:excoveralls, "~> 0.4", only: :test}, + {:credo, "~> 0.1.0", only: [:dev, :test]} ] end diff --git a/mix.lock b/mix.lock index 134aeb57..19126311 100644 --- a/mix.lock +++ b/mix.lock @@ -1,14 +1,14 @@ -%{"benchfella": {:hex, :benchfella, "0.2.1"}, +%{"benchfella": {:hex, :benchfella, "0.3.0"}, "bunt": {:hex, :bunt, "0.1.4"}, - "certifi": {:hex, :certifi, "0.1.1"}, + "certifi": {:hex, :certifi, "0.3.0"}, "credo": {:hex, :credo, "0.1.10"}, "dogma": {:hex, :dogma, "0.0.7"}, "earmark": {:hex, :earmark, "0.1.19"}, "estree": {:hex, :estree, "2.1.1"}, - "ex_doc": {:hex, :ex_doc, "0.10.0"}, - "excoveralls": {:hex, :excoveralls, "0.4.2"}, + "ex_doc": {:hex, :ex_doc, "0.11.1"}, + "excoveralls": {:hex, :excoveralls, "0.4.3"}, "exjsx": {:hex, :exjsx, "3.2.0"}, - "hackney": {:hex, :hackney, "1.4.4"}, + "hackney": {:hex, :hackney, "1.4.6"}, "idna": {:hex, :idna, "1.0.2"}, "inflex": {:hex, :inflex, "1.5.0"}, "jsx": {:hex, :jsx, "2.6.2"}, From f56dcbd0c396e04e6a215ded5e9c46ebc9c6cd5f Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Sat, 5 Dec 2015 11:26:58 -0600 Subject: [PATCH 077/860] Renamed IntegerType and FloatType to Integer and Float --- lib/elixir_script/translator/protocol.ex | 14 ++++++++++---- src/javascript/lib/core.js | 6 +++--- src/javascript/lib/core/primitives.js | 7 +++---- src/javascript/lib/list/chars.js | 2 +- src/javascript/lib/protocol.js | 8 ++++---- src/javascript/lib/string/chars.js | 4 ++-- test/translator/protocol_test.exs | 2 +- 7 files changed, 24 insertions(+), 19 deletions(-) diff --git a/lib/elixir_script/translator/protocol.ex b/lib/elixir_script/translator/protocol.ex index a7e9dff7..7c782eba 100644 --- a/lib/elixir_script/translator/protocol.ex +++ b/lib/elixir_script/translator/protocol.ex @@ -182,8 +182,11 @@ defmodule ElixirScript.Translator.Protocol do defp map_to_js({:__aliases__, _, [:Integer]}) do JS.member_expression( - JS.identifier(:Elixir), - JS.identifier(:IntegerType) + JS.member_expression( + JS.identifier(:Elixir), + JS.identifier(:Core) + ), + JS.identifier(:Integer) ) end @@ -217,8 +220,11 @@ defmodule ElixirScript.Translator.Protocol do defp map_to_js({:__aliases__, _, [:Float]}) do JS.member_expression( - JS.identifier(:Elixir), - JS.identifier(:FloatType) + JS.member_expression( + JS.identifier(:Elixir), + JS.identifier(:Core) + ), + JS.identifier(:Float) ) end diff --git a/src/javascript/lib/core.js b/src/javascript/lib/core.js index 014cd50a..1f0edbe2 100644 --- a/src/javascript/lib/core.js +++ b/src/javascript/lib/core.js @@ -1,5 +1,5 @@ import ProcessSystem from './core/process_system'; -import { Tuple, PID, IntegerType, FloatType } from './core/primitives'; +import { Tuple, PID, Integer, Float } from './core/primitives'; import BitString from './core/bit_string'; import Patterns from './core/patterns'; import { call_property } from './core/functions'; @@ -10,7 +10,7 @@ export { PID, BitString, Patterns, - IntegerType, - FloatType, + Integer, + Float, call_property } diff --git a/src/javascript/lib/core/primitives.js b/src/javascript/lib/core/primitives.js index b3d1f74f..d222905d 100644 --- a/src/javascript/lib/core/primitives.js +++ b/src/javascript/lib/core/primitives.js @@ -44,8 +44,7 @@ class PID { } } -class IntegerType {} +class Integer {} +class Float {} -class FloatType {} - -export { PID, Tuple, IntegerType, FloatType }; +export { PID, Tuple, Integer, Float }; diff --git a/src/javascript/lib/list/chars.js b/src/javascript/lib/list/chars.js index a7463cdb..44a8059a 100644 --- a/src/javascript/lib/list/chars.js +++ b/src/javascript/lib/list/chars.js @@ -24,7 +24,7 @@ Kernel.defimpl(Chars, Symbol, { } }); -Kernel.defimpl(Chars, Core.IntegerType, { +Kernel.defimpl(Chars, Core.Integer, { to_char_list: function(thing){ return Integer.to_char_list(thing); } diff --git a/src/javascript/lib/protocol.js b/src/javascript/lib/protocol.js index e135b385..81876675 100644 --- a/src/javascript/lib/protocol.js +++ b/src/javascript/lib/protocol.js @@ -16,10 +16,10 @@ class Protocol{ let thing = args[0]; let fun = null; - if(Number.isInteger(thing) && this.hasImplementation(Core.IntegerType)){ - fun = this.registry.get(Core.IntegerType)[funName]; - }else if(typeof thing === "number" && !Number.isInteger(thing) && this.hasImplementation(Core.FloatType)){ - fun = this.registry.get(Core.FloatType)[funName]; + if(Number.isInteger(thing) && this.hasImplementation(Core.Integer)){ + fun = this.registry.get(Core.Integer)[funName]; + }else if(typeof thing === "number" && !Number.isInteger(thing) && this.hasImplementation(Core.Float)){ + fun = this.registry.get(Core.Float)[funName]; }else if(this.hasImplementation(thing)){ fun = this.registry.get(thing.constructor)[funName]; }else if(this.fallback){ diff --git a/src/javascript/lib/string/chars.js b/src/javascript/lib/string/chars.js index 19b6f2f3..26f14ce4 100644 --- a/src/javascript/lib/string/chars.js +++ b/src/javascript/lib/string/chars.js @@ -29,13 +29,13 @@ Kernel.defimpl(Chars, Symbol, { } }); -Kernel.defimpl(Chars, Core.IntegerType, { +Kernel.defimpl(Chars, Core.Integer, { to_string: function(thing){ return Integer.to_string(thing); } }); -Kernel.defimpl(Chars, Core.FloatType, { +Kernel.defimpl(Chars, Core.Float, { to_string: function(thing){ return thing.toString; } diff --git a/test/translator/protocol_test.exs b/test/translator/protocol_test.exs index 8a279e5c..d475b5fa 100644 --- a/test/translator/protocol_test.exs +++ b/test/translator/protocol_test.exs @@ -90,7 +90,7 @@ defmodule ElixirScript.Translator.Protocol.Test do return false; })) }) - Elixir.Kernel.defimpl(Blank,Elixir.IntegerType,{ + Elixir.Kernel.defimpl(Blank, Elixir.Core.Integer, { blank__qmark__: Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable()],function(number) { return false; })) From 7d252e941090b3e25134f931e2b1cbcfc24c6681 Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Sat, 5 Dec 2015 11:35:02 -0600 Subject: [PATCH 078/860] Updated package description --- mix.exs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mix.exs b/mix.exs index 55d2dbff..06f24187 100644 --- a/mix.exs +++ b/mix.exs @@ -45,7 +45,7 @@ defmodule ElixirScript.Mixfile do defp description do """ - converts Elixir to JavaScript + ElixirScript: compiles Elixir code to JavaScript """ end From 695451d1c2e6cdce58f335ff2d54c6c47f84e211 Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Sun, 6 Dec 2015 09:41:36 -0600 Subject: [PATCH 079/860] Removed dev status from version --- CHANGELOG.md | 13 ++++++++++--- mix.exs | 2 +- priv/elixir.js | 25 ++++++++++++------------- 3 files changed, 23 insertions(+), 17 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 0c1f045e..dd7231f9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,13 +1,20 @@ -# v0.14.0-dev +# v0.14.0 * Enhancements * Structs are now translated into classes * Structs and Tuples now match on their types - * Can now match on JavaScript classes + * Can now match on JavaScript classes. Works just like matching on structs: + ```elixir + def my_func(%HTMLElement{id: "myId"}) + ``` * Can now implement protocols using JavaScript types + ```elixir + defimpl MyProtocol, for: HTMLElement + ``` * Added virtual-dom JavaScript library * Added ElixirScript.Html module for defining a virtual-dom tree * Added ElixirScript.VDom module for manipulating the virtual-dom tree created using the ElixirScript.Html module + * Added ElixirScript.View module for handling view state and rendering virtual-dom * Added `stdlib_path` compiler option to specify the es6 path to the standard library. If used, elixir.js will not be exported with the compiled modules * Moved non-elixir JavaScript code into `core` es6 module. This will hopefully @@ -149,7 +156,7 @@ * Logger * Implemented language features: - * All primatives except bitstrings + * All primitives except bitstrings * defmodule * import, alias, and require * case, cond, if diff --git a/mix.exs b/mix.exs index 06f24187..ee583be5 100644 --- a/mix.exs +++ b/mix.exs @@ -4,7 +4,7 @@ defmodule ElixirScript.Mixfile do def project do [ app: :elixir_script, - version: "0.14.0-dev", + version: "0.14.0", elixir: "~> 1.0", escript: escript_config, deps: deps, diff --git a/priv/elixir.js b/priv/elixir.js index a248f8a1..e2ad175d 100644 --- a/priv/elixir.js +++ b/priv/elixir.js @@ -64,9 +64,8 @@ class PID { } } -class IntegerType {} - -class FloatType {} +class Integer$1 {} +class Float {} /* @flow */ @@ -1035,8 +1034,8 @@ var C = Object.freeze({ PID: PID, BitString: BitString, Patterns: Patterns, - IntegerType: IntegerType, - FloatType: FloatType, + Integer: Integer$1, + Float: Float, call_property: call_property }); @@ -1496,10 +1495,10 @@ class Protocol { let thing = args[0]; let fun = null; - if (Number.isInteger(thing) && this.hasImplementation(IntegerType)) { - fun = this.registry.get(IntegerType)[funName]; - } else if (typeof thing === "number" && !Number.isInteger(thing) && this.hasImplementation(FloatType)) { - fun = this.registry.get(FloatType)[funName]; + if (Number.isInteger(thing) && this.hasImplementation(Integer$1)) { + fun = this.registry.get(Integer$1)[funName]; + } else if (typeof thing === "number" && !Number.isInteger(thing) && this.hasImplementation(Float)) { + fun = this.registry.get(Float)[funName]; } else if (this.hasImplementation(thing)) { fun = this.registry.get(thing.constructor)[funName]; } else if (this.fallback) { @@ -1801,13 +1800,13 @@ Kernel.defimpl(Chars$1, Symbol, { } }); -Kernel.defimpl(Chars$1, IntegerType, { +Kernel.defimpl(Chars$1, Integer$1, { to_string: function (thing) { return Integer.to_string(thing); } }); -Kernel.defimpl(Chars$1, FloatType, { +Kernel.defimpl(Chars$1, Float, { to_string: function (thing) { return thing.toString; } @@ -2035,7 +2034,7 @@ Kernel.defimpl(Chars, Symbol, { } }); -Kernel.defimpl(Chars, IntegerType, { +Kernel.defimpl(Chars, Integer$1, { to_char_list: function (thing) { return Integer.to_char_list(thing); } @@ -4567,4 +4566,4 @@ self.processes = self.processes || new ProcessSystem(); const Core = C; export { Core, Kernel, Atom, Enum, Integer, List, Range, Tuple, Agent, Keyword, base as Base, String$1 as String, bitwise as Bitwise, Enumerable, Collectable, Inspect, map as Map, set as Set, MapSet, VirtualDOM, view as View }; -//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiIiwic291cmNlcyI6WyJlbGl4aXIuanMiXSwic291cmNlc0NvbnRlbnQiOlsiZnVuY3Rpb24gY2FsbF9wcm9wZXJ0eShpdGVtLCBwcm9wZXJ0eSkge1xuICBpZiAocHJvcGVydHkgaW4gaXRlbSkge1xuICAgIGl0ZW1bcHJvcGVydHldO1xuICAgIGlmIChpdGVtW3Byb3BlcnR5XSBpbnN0YW5jZW9mIEZ1bmN0aW9uKSB7XG4gICAgICByZXR1cm4gaXRlbVtwcm9wZXJ0eV0oKTtcbiAgICB9IGVsc2Uge1xuICAgICAgcmV0dXJuIGl0ZW1bcHJvcGVydHldO1xuICAgIH1cbiAgfSBlbHNlIGlmIChTeW1ib2wuZm9yKHByb3BlcnR5KSBpbiBpdGVtKSB7XG4gICAgbGV0IHByb3AgPSBTeW1ib2wuZm9yKHByb3BlcnR5KTtcbiAgICBpZiAoaXRlbVtwcm9wXSBpbnN0YW5jZW9mIEZ1bmN0aW9uKSB7XG4gICAgICByZXR1cm4gaXRlbVtwcm9wXSgpO1xuICAgIH0gZWxzZSB7XG4gICAgICByZXR1cm4gaXRlbVtwcm9wXTtcbiAgICB9XG4gIH1cblxuICB0aHJvdyBuZXcgRXJyb3IoYFByb3BlcnR5ICR7IHByb3BlcnR5IH0gbm90IGZvdW5kIGluICR7IGl0ZW0gfWApO1xufVxuXG5jbGFzcyBUdXBsZSQxIHtcblxuICBjb25zdHJ1Y3RvciguLi5hcmdzKSB7XG4gICAgdGhpcy52YWx1ZXMgPSBPYmplY3QuZnJlZXplKGFyZ3MpO1xuICB9XG5cbiAgZ2V0KGluZGV4KSB7XG4gICAgcmV0dXJuIHRoaXMudmFsdWVzW2luZGV4XTtcbiAgfVxuXG4gIGNvdW50KCkge1xuICAgIHJldHVybiB0aGlzLnZhbHVlcy5sZW5ndGg7XG4gIH1cblxuICBbU3ltYm9sLml0ZXJhdG9yXSgpIHtcbiAgICByZXR1cm4gdGhpcy52YWx1ZXNbU3ltYm9sLml0ZXJhdG9yXSgpO1xuICB9XG5cbiAgdG9TdHJpbmcoKSB7XG4gICAgdmFyIGksXG4gICAgICAgIHMgPSBcIlwiO1xuICAgIGZvciAoaSA9IDA7IGkgPCB0aGlzLnZhbHVlcy5sZW5ndGg7IGkrKykge1xuICAgICAgaWYgKHMgIT09IFwiXCIpIHtcbiAgICAgICAgcyArPSBcIiwgXCI7XG4gICAgICB9XG4gICAgICBzICs9IHRoaXMudmFsdWVzW2ldLnRvU3RyaW5nKCk7XG4gICAgfVxuXG4gICAgcmV0dXJuIFwie1wiICsgcyArIFwifVwiO1xuICB9XG5cbn1cblxubGV0IHByb2Nlc3NfY291bnRlciA9IC0xO1xuXG5jbGFzcyBQSUQge1xuICBjb25zdHJ1Y3RvcigpIHtcbiAgICBwcm9jZXNzX2NvdW50ZXIgPSBwcm9jZXNzX2NvdW50ZXIgKyAxO1xuICAgIHRoaXMuaWQgPSBwcm9jZXNzX2NvdW50ZXI7XG4gIH1cblxuICB0b1N0cmluZygpIHtcbiAgICByZXR1cm4gXCJQSUQjPDAuXCIgKyB0aGlzLmlkICsgXCIuMD5cIjtcbiAgfVxufVxuXG5jbGFzcyBJbnRlZ2VyVHlwZSB7fVxuXG5jbGFzcyBGbG9hdFR5cGUge31cblxuLyogQGZsb3cgKi9cblxuY2xhc3MgVmFyaWFibGUge1xuXG4gIGNvbnN0cnVjdG9yKG5hbWUgPSBudWxsKSB7XG4gICAgdGhpcy5uYW1lID0gbmFtZTtcbiAgfVxufVxuXG5jbGFzcyBXaWxkY2FyZCB7XG4gIGNvbnN0cnVjdG9yKCkge31cbn1cblxuY2xhc3MgU3RhcnRzV2l0aCB7XG5cbiAgY29uc3RydWN0b3IocHJlZml4KSB7XG4gICAgdGhpcy5wcmVmaXggPSBwcmVmaXg7XG4gIH1cbn1cblxuY2xhc3MgQ2FwdHVyZSB7XG5cbiAgY29uc3RydWN0b3IodmFsdWUpIHtcbiAgICB0aGlzLnZhbHVlID0gdmFsdWU7XG4gIH1cbn1cblxuY2xhc3MgSGVhZFRhaWwge1xuICBjb25zdHJ1Y3RvcigpIHt9XG59XG5cbmNsYXNzIFR5cGUge1xuXG4gIGNvbnN0cnVjdG9yKHR5cGUsIG9ialBhdHRlcm4gPSB7fSkge1xuICAgIHRoaXMudHlwZSA9IHR5cGU7XG4gICAgdGhpcy5vYmpQYXR0ZXJuID0gb2JqUGF0dGVybjtcbiAgfVxufVxuXG5jbGFzcyBCb3VuZCB7XG5cbiAgY29uc3RydWN0b3IodmFsdWUpIHtcbiAgICB0aGlzLnZhbHVlID0gdmFsdWU7XG4gIH1cbn1cblxuZnVuY3Rpb24gdmFyaWFibGUobmFtZSA9IG51bGwpIHtcbiAgcmV0dXJuIG5ldyBWYXJpYWJsZShuYW1lKTtcbn1cblxuZnVuY3Rpb24gd2lsZGNhcmQoKSB7XG4gIHJldHVybiBuZXcgV2lsZGNhcmQoKTtcbn1cblxuZnVuY3Rpb24gc3RhcnRzV2l0aChwcmVmaXgpIHtcbiAgcmV0dXJuIG5ldyBTdGFydHNXaXRoKHByZWZpeCk7XG59XG5cbmZ1bmN0aW9uIGNhcHR1cmUodmFsdWUpIHtcbiAgcmV0dXJuIG5ldyBDYXB0dXJlKHZhbHVlKTtcbn1cblxuZnVuY3Rpb24gaGVhZFRhaWwoKSB7XG4gIHJldHVybiBuZXcgSGVhZFRhaWwoKTtcbn1cblxuZnVuY3Rpb24gdHlwZSh0eXBlLCBvYmpQYXR0ZXJuID0ge30pIHtcbiAgcmV0dXJuIG5ldyBUeXBlKHR5cGUsIG9ialBhdHRlcm4pO1xufVxuXG5mdW5jdGlvbiBib3VuZCh2YWx1ZSkge1xuICByZXR1cm4gbmV3IEJvdW5kKHZhbHVlKTtcbn1cblxuZnVuY3Rpb24gaXNfbnVtYmVyJDEodmFsdWUpIHtcbiAgcmV0dXJuIHR5cGVvZiB2YWx1ZSA9PT0gJ251bWJlcic7XG59XG5cbmZ1bmN0aW9uIGlzX3N0cmluZyh2YWx1ZSkge1xuICByZXR1cm4gdHlwZW9mIHZhbHVlID09PSAnc3RyaW5nJztcbn1cblxuZnVuY3Rpb24gaXNfYm9vbGVhbiQxKHZhbHVlKSB7XG4gIHJldHVybiB0eXBlb2YgdmFsdWUgPT09ICdib29sZWFuJztcbn1cblxuZnVuY3Rpb24gaXNfc3ltYm9sKHZhbHVlKSB7XG4gIHJldHVybiB0eXBlb2YgdmFsdWUgPT09ICdzeW1ib2wnO1xufVxuXG5mdW5jdGlvbiBpc19udWxsKHZhbHVlKSB7XG4gIHJldHVybiB2YWx1ZSA9PT0gbnVsbDtcbn1cblxuZnVuY3Rpb24gaXNfdW5kZWZpbmVkKHZhbHVlKSB7XG4gIHJldHVybiB0eXBlb2YgdmFsdWUgPT09ICd1bmRlZmluZWQnO1xufVxuXG5mdW5jdGlvbiBpc19mdW5jdGlvbiQxKHZhbHVlKSB7XG4gIHJldHVybiBPYmplY3QucHJvdG90eXBlLnRvU3RyaW5nLmNhbGwodmFsdWUpID09ICdbb2JqZWN0IEZ1bmN0aW9uXSc7XG59XG5cbmZ1bmN0aW9uIGlzX3ZhcmlhYmxlKHZhbHVlKSB7XG4gIHJldHVybiB2YWx1ZSBpbnN0YW5jZW9mIFZhcmlhYmxlO1xufVxuXG5mdW5jdGlvbiBpc193aWxkY2FyZCh2YWx1ZSkge1xuICByZXR1cm4gdmFsdWUgaW5zdGFuY2VvZiBXaWxkY2FyZDtcbn1cblxuZnVuY3Rpb24gaXNfaGVhZFRhaWwodmFsdWUpIHtcbiAgcmV0dXJuIHZhbHVlIGluc3RhbmNlb2YgSGVhZFRhaWw7XG59XG5cbmZ1bmN0aW9uIGlzX2NhcHR1cmUodmFsdWUpIHtcbiAgcmV0dXJuIHZhbHVlIGluc3RhbmNlb2YgQ2FwdHVyZTtcbn1cblxuZnVuY3Rpb24gaXNfdHlwZSh2YWx1ZSkge1xuICByZXR1cm4gdmFsdWUgaW5zdGFuY2VvZiBUeXBlO1xufVxuXG5mdW5jdGlvbiBpc19zdGFydHNXaXRoKHZhbHVlKSB7XG4gIHJldHVybiB2YWx1ZSBpbnN0YW5jZW9mIFN0YXJ0c1dpdGg7XG59XG5cbmZ1bmN0aW9uIGlzX2JvdW5kKHZhbHVlKSB7XG4gIHJldHVybiB2YWx1ZSBpbnN0YW5jZW9mIEJvdW5kO1xufVxuXG5mdW5jdGlvbiBpc19vYmplY3QodmFsdWUpIHtcbiAgcmV0dXJuIHR5cGVvZiB2YWx1ZSA9PT0gJ29iamVjdCc7XG59XG5cbmZ1bmN0aW9uIGlzX2FycmF5KHZhbHVlKSB7XG4gIHJldHVybiBBcnJheS5pc0FycmF5KHZhbHVlKTtcbn1cblxudmFyIENoZWNrcyA9IHtcbiAgaXNfbnVtYmVyOiBpc19udW1iZXIkMSxcbiAgaXNfc3RyaW5nLFxuICBpc19ib29sZWFuOiBpc19ib29sZWFuJDEsXG4gIGlzX3N5bWJvbCxcbiAgaXNfbnVsbCxcbiAgaXNfdW5kZWZpbmVkLFxuICBpc19mdW5jdGlvbjogaXNfZnVuY3Rpb24kMSxcbiAgaXNfdmFyaWFibGUsXG4gIGlzX3dpbGRjYXJkLFxuICBpc19oZWFkVGFpbCxcbiAgaXNfY2FwdHVyZSxcbiAgaXNfdHlwZSxcbiAgaXNfc3RhcnRzV2l0aCxcbiAgaXNfYm91bmQsXG4gIGlzX29iamVjdCxcbiAgaXNfYXJyYXlcbn07XG5cbmZ1bmN0aW9uIHJlc29sdmVTeW1ib2wocGF0dGVybikge1xuICByZXR1cm4gZnVuY3Rpb24gKHZhbHVlKSB7XG4gICAgcmV0dXJuIENoZWNrcy5pc19zeW1ib2wodmFsdWUpICYmIHZhbHVlID09PSBwYXR0ZXJuO1xuICB9O1xufVxuXG5mdW5jdGlvbiByZXNvbHZlU3RyaW5nKHBhdHRlcm4pIHtcbiAgcmV0dXJuIGZ1bmN0aW9uICh2YWx1ZSkge1xuICAgIHJldHVybiBDaGVja3MuaXNfc3RyaW5nKHZhbHVlKSAmJiB2YWx1ZSA9PT0gcGF0dGVybjtcbiAgfTtcbn1cblxuZnVuY3Rpb24gcmVzb2x2ZU51bWJlcihwYXR0ZXJuKSB7XG4gIHJldHVybiBmdW5jdGlvbiAodmFsdWUpIHtcbiAgICByZXR1cm4gQ2hlY2tzLmlzX251bWJlcih2YWx1ZSkgJiYgdmFsdWUgPT09IHBhdHRlcm47XG4gIH07XG59XG5cbmZ1bmN0aW9uIHJlc29sdmVCb29sZWFuKHBhdHRlcm4pIHtcbiAgcmV0dXJuIGZ1bmN0aW9uICh2YWx1ZSkge1xuICAgIHJldHVybiBDaGVja3MuaXNfYm9vbGVhbih2YWx1ZSkgJiYgdmFsdWUgPT09IHBhdHRlcm47XG4gIH07XG59XG5cbmZ1bmN0aW9uIHJlc29sdmVGdW5jdGlvbihwYXR0ZXJuKSB7XG4gIHJldHVybiBmdW5jdGlvbiAodmFsdWUpIHtcbiAgICByZXR1cm4gQ2hlY2tzLmlzX2Z1bmN0aW9uKHZhbHVlKSAmJiB2YWx1ZSA9PT0gcGF0dGVybjtcbiAgfTtcbn1cblxuZnVuY3Rpb24gcmVzb2x2ZU51bGwocGF0dGVybikge1xuICByZXR1cm4gZnVuY3Rpb24gKHZhbHVlKSB7XG4gICAgcmV0dXJuIENoZWNrcy5pc19udWxsKHZhbHVlKTtcbiAgfTtcbn1cblxuZnVuY3Rpb24gcmVzb2x2ZUJvdW5kKHBhdHRlcm4pIHtcbiAgcmV0dXJuIGZ1bmN0aW9uICh2YWx1ZSwgYXJncykge1xuICAgIGlmICh0eXBlb2YgdmFsdWUgPT09IHR5cGVvZiBwYXR0ZXJuLnZhbHVlICYmIHZhbHVlID09PSBwYXR0ZXJuLnZhbHVlKSB7XG4gICAgICBhcmdzLnB1c2godmFsdWUpO1xuICAgICAgcmV0dXJuIHRydWU7XG4gICAgfVxuXG4gICAgcmV0dXJuIGZhbHNlO1xuICB9O1xufVxuXG5mdW5jdGlvbiByZXNvbHZlV2lsZGNhcmQoKSB7XG4gIHJldHVybiBmdW5jdGlvbiAoKSB7XG4gICAgcmV0dXJuIHRydWU7XG4gIH07XG59XG5cbmZ1bmN0aW9uIHJlc29sdmVWYXJpYWJsZSgpIHtcbiAgcmV0dXJuIGZ1bmN0aW9uICh2YWx1ZSwgYXJncykge1xuICAgIGFyZ3MucHVzaCh2YWx1ZSk7XG4gICAgcmV0dXJuIHRydWU7XG4gIH07XG59XG5cbmZ1bmN0aW9uIHJlc29sdmVIZWFkVGFpbCgpIHtcbiAgcmV0dXJuIGZ1bmN0aW9uICh2YWx1ZSwgYXJncykge1xuICAgIGlmICghQ2hlY2tzLmlzX2FycmF5KHZhbHVlKSB8fCB2YWx1ZS5sZW5ndGggPCAyKSB7XG4gICAgICByZXR1cm4gZmFsc2U7XG4gICAgfVxuXG4gICAgY29uc3QgaGVhZCA9IHZhbHVlWzBdO1xuICAgIGNvbnN0IHRhaWwgPSB2YWx1ZS5zbGljZSgxKTtcblxuICAgIGFyZ3MucHVzaChoZWFkKTtcbiAgICBhcmdzLnB1c2godGFpbCk7XG5cbiAgICByZXR1cm4gdHJ1ZTtcbiAgfTtcbn1cblxuZnVuY3Rpb24gcmVzb2x2ZUNhcHR1cmUocGF0dGVybikge1xuICBjb25zdCBtYXRjaGVzID0gYnVpbGRNYXRjaChwYXR0ZXJuLnZhbHVlKTtcblxuICByZXR1cm4gZnVuY3Rpb24gKHZhbHVlLCBhcmdzKSB7XG4gICAgaWYgKG1hdGNoZXModmFsdWUsIGFyZ3MpKSB7XG4gICAgICBhcmdzLnB1c2godmFsdWUpO1xuICAgICAgcmV0dXJuIHRydWU7XG4gICAgfVxuXG4gICAgcmV0dXJuIGZhbHNlO1xuICB9O1xufVxuXG5mdW5jdGlvbiByZXNvbHZlU3RhcnRzV2l0aChwYXR0ZXJuKSB7XG4gIGNvbnN0IHByZWZpeCA9IHBhdHRlcm4ucHJlZml4O1xuXG4gIHJldHVybiBmdW5jdGlvbiAodmFsdWUsIGFyZ3MpIHtcbiAgICBpZiAoQ2hlY2tzLmlzX3N0cmluZyh2YWx1ZSkgJiYgdmFsdWUuc3RhcnRzV2l0aChwcmVmaXgpKSB7XG4gICAgICBhcmdzLnB1c2godmFsdWUuc3Vic3RyaW5nKHByZWZpeC5sZW5ndGgpKTtcbiAgICAgIHJldHVybiB0cnVlO1xuICAgIH1cblxuICAgIHJldHVybiBmYWxzZTtcbiAgfTtcbn1cblxuZnVuY3Rpb24gcmVzb2x2ZVR5cGUocGF0dGVybikge1xuICByZXR1cm4gZnVuY3Rpb24gKHZhbHVlLCBhcmdzKSB7XG4gICAgaWYgKHZhbHVlIGluc3RhbmNlb2YgcGF0dGVybi50eXBlKSB7XG4gICAgICBjb25zdCBtYXRjaGVzID0gYnVpbGRNYXRjaChwYXR0ZXJuLm9ialBhdHRlcm4pO1xuICAgICAgcmV0dXJuIG1hdGNoZXModmFsdWUsIGFyZ3MpICYmIGFyZ3MucHVzaCh2YWx1ZSkgPiAwO1xuICAgIH1cblxuICAgIHJldHVybiBmYWxzZTtcbiAgfTtcbn1cblxuZnVuY3Rpb24gcmVzb2x2ZUFycmF5KHBhdHRlcm4pIHtcbiAgY29uc3QgbWF0Y2hlcyA9IHBhdHRlcm4ubWFwKHggPT4gYnVpbGRNYXRjaCh4KSk7XG5cbiAgcmV0dXJuIGZ1bmN0aW9uICh2YWx1ZSwgYXJncykge1xuICAgIGlmICghQ2hlY2tzLmlzX2FycmF5KHZhbHVlKSB8fCB2YWx1ZS5sZW5ndGggIT0gcGF0dGVybi5sZW5ndGgpIHtcbiAgICAgIHJldHVybiBmYWxzZTtcbiAgICB9XG5cbiAgICByZXR1cm4gdmFsdWUuZXZlcnkoZnVuY3Rpb24gKHYsIGkpIHtcbiAgICAgIHJldHVybiBtYXRjaGVzW2ldKHZhbHVlW2ldLCBhcmdzKTtcbiAgICB9KTtcbiAgfTtcbn1cblxuZnVuY3Rpb24gcmVzb2x2ZU9iamVjdChwYXR0ZXJuKSB7XG4gIGxldCBtYXRjaGVzID0ge307XG5cbiAgZm9yIChsZXQga2V5IG9mIE9iamVjdC5rZXlzKHBhdHRlcm4pKSB7XG4gICAgbWF0Y2hlc1trZXldID0gYnVpbGRNYXRjaChwYXR0ZXJuW2tleV0pO1xuICB9XG5cbiAgcmV0dXJuIGZ1bmN0aW9uICh2YWx1ZSwgYXJncykge1xuICAgIGlmICghQ2hlY2tzLmlzX29iamVjdCh2YWx1ZSkgfHwgcGF0dGVybi5sZW5ndGggPiB2YWx1ZS5sZW5ndGgpIHtcbiAgICAgIHJldHVybiBmYWxzZTtcbiAgICB9XG5cbiAgICBmb3IgKGxldCBrZXkgb2YgT2JqZWN0LmtleXMocGF0dGVybikpIHtcbiAgICAgIGlmICghKGtleSBpbiB2YWx1ZSkgfHwgIW1hdGNoZXNba2V5XSh2YWx1ZVtrZXldLCBhcmdzKSkge1xuICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICB9XG4gICAgfVxuXG4gICAgcmV0dXJuIHRydWU7XG4gIH07XG59XG5cbmZ1bmN0aW9uIHJlc29sdmVOb01hdGNoKCkge1xuICByZXR1cm4gZnVuY3Rpb24gKCkge1xuICAgIHJldHVybiBmYWxzZTtcbiAgfTtcbn1cblxudmFyIFJlc29sdmVycyA9IHtcbiAgcmVzb2x2ZUJvdW5kLFxuICByZXNvbHZlV2lsZGNhcmQsXG4gIHJlc29sdmVWYXJpYWJsZSxcbiAgcmVzb2x2ZUhlYWRUYWlsLFxuICByZXNvbHZlQ2FwdHVyZSxcbiAgcmVzb2x2ZVN0YXJ0c1dpdGgsXG4gIHJlc29sdmVUeXBlLFxuICByZXNvbHZlQXJyYXksXG4gIHJlc29sdmVPYmplY3QsXG4gIHJlc29sdmVOb01hdGNoLFxuICByZXNvbHZlU3ltYm9sLFxuICByZXNvbHZlU3RyaW5nLFxuICByZXNvbHZlTnVtYmVyLFxuICByZXNvbHZlQm9vbGVhbixcbiAgcmVzb2x2ZUZ1bmN0aW9uLFxuICByZXNvbHZlTnVsbFxufTtcblxuZnVuY3Rpb24gYnVpbGRNYXRjaChwYXR0ZXJuKSB7XG5cbiAgaWYgKENoZWNrcy5pc192YXJpYWJsZShwYXR0ZXJuKSkge1xuICAgIHJldHVybiBSZXNvbHZlcnMucmVzb2x2ZVZhcmlhYmxlKHBhdHRlcm4pO1xuICB9XG5cbiAgaWYgKENoZWNrcy5pc193aWxkY2FyZChwYXR0ZXJuKSkge1xuICAgIHJldHVybiBSZXNvbHZlcnMucmVzb2x2ZVdpbGRjYXJkKHBhdHRlcm4pO1xuICB9XG5cbiAgaWYgKENoZWNrcy5pc191bmRlZmluZWQocGF0dGVybikpIHtcbiAgICByZXR1cm4gUmVzb2x2ZXJzLnJlc29sdmVXaWxkY2FyZChwYXR0ZXJuKTtcbiAgfVxuXG4gIGlmIChDaGVja3MuaXNfaGVhZFRhaWwocGF0dGVybikpIHtcbiAgICByZXR1cm4gUmVzb2x2ZXJzLnJlc29sdmVIZWFkVGFpbChwYXR0ZXJuKTtcbiAgfVxuXG4gIGlmIChDaGVja3MuaXNfc3RhcnRzV2l0aChwYXR0ZXJuKSkge1xuICAgIHJldHVybiBSZXNvbHZlcnMucmVzb2x2ZVN0YXJ0c1dpdGgocGF0dGVybik7XG4gIH1cblxuICBpZiAoQ2hlY2tzLmlzX2NhcHR1cmUocGF0dGVybikpIHtcbiAgICByZXR1cm4gUmVzb2x2ZXJzLnJlc29sdmVDYXB0dXJlKHBhdHRlcm4pO1xuICB9XG5cbiAgaWYgKENoZWNrcy5pc19ib3VuZChwYXR0ZXJuKSkge1xuICAgIHJldHVybiBSZXNvbHZlcnMucmVzb2x2ZUJvdW5kKHBhdHRlcm4pO1xuICB9XG5cbiAgaWYgKENoZWNrcy5pc190eXBlKHBhdHRlcm4pKSB7XG4gICAgcmV0dXJuIFJlc29sdmVycy5yZXNvbHZlVHlwZShwYXR0ZXJuKTtcbiAgfVxuXG4gIGlmIChDaGVja3MuaXNfYXJyYXkocGF0dGVybikpIHtcbiAgICByZXR1cm4gUmVzb2x2ZXJzLnJlc29sdmVBcnJheShwYXR0ZXJuKTtcbiAgfVxuXG4gIGlmIChDaGVja3MuaXNfbnVtYmVyKHBhdHRlcm4pKSB7XG4gICAgcmV0dXJuIFJlc29sdmVycy5yZXNvbHZlTnVtYmVyKHBhdHRlcm4pO1xuICB9XG5cbiAgaWYgKENoZWNrcy5pc19zdHJpbmcocGF0dGVybikpIHtcbiAgICByZXR1cm4gUmVzb2x2ZXJzLnJlc29sdmVTdHJpbmcocGF0dGVybik7XG4gIH1cblxuICBpZiAoQ2hlY2tzLmlzX2Jvb2xlYW4ocGF0dGVybikpIHtcbiAgICByZXR1cm4gUmVzb2x2ZXJzLnJlc29sdmVCb29sZWFuKHBhdHRlcm4pO1xuICB9XG5cbiAgaWYgKENoZWNrcy5pc19zeW1ib2wocGF0dGVybikpIHtcbiAgICByZXR1cm4gUmVzb2x2ZXJzLnJlc29sdmVTeW1ib2wocGF0dGVybik7XG4gIH1cblxuICBpZiAoQ2hlY2tzLmlzX251bGwocGF0dGVybikpIHtcbiAgICByZXR1cm4gUmVzb2x2ZXJzLnJlc29sdmVOdWxsKHBhdHRlcm4pO1xuICB9XG5cbiAgaWYgKENoZWNrcy5pc19vYmplY3QocGF0dGVybikpIHtcbiAgICByZXR1cm4gUmVzb2x2ZXJzLnJlc29sdmVPYmplY3QocGF0dGVybik7XG4gIH1cblxuICByZXR1cm4gUmVzb2x2ZXJzLnJlc29sdmVOb01hdGNoKCk7XG59XG5cbmNsYXNzIE1hdGNoRXJyb3IgZXh0ZW5kcyBFcnJvciB7XG4gIGNvbnN0cnVjdG9yKGFyZykge1xuICAgIHN1cGVyKCk7XG5cbiAgICBpZiAodHlwZW9mIGFyZyA9PT0gJ3N5bWJvbCcpIHtcbiAgICAgIHRoaXMubWVzc2FnZSA9ICdObyBtYXRjaCBmb3I6ICcgKyBhcmcudG9TdHJpbmcoKTtcbiAgICB9IGVsc2UgaWYgKEFycmF5LmlzQXJyYXkoYXJnKSkge1xuICAgICAgbGV0IG1hcHBlZFZhbHVlcyA9IGFyZy5tYXAoeCA9PiB4LnRvU3RyaW5nKCkpO1xuICAgICAgdGhpcy5tZXNzYWdlID0gJ05vIG1hdGNoIGZvcjogJyArIG1hcHBlZFZhbHVlcztcbiAgICB9IGVsc2Uge1xuICAgICAgdGhpcy5tZXNzYWdlID0gJ05vIG1hdGNoIGZvcjogJyArIGFyZztcbiAgICB9XG5cbiAgICB0aGlzLnN0YWNrID0gbmV3IEVycm9yKCkuc3RhY2s7XG4gICAgdGhpcy5uYW1lID0gdGhpcy5jb25zdHJ1Y3Rvci5uYW1lO1xuICB9XG59XG5cbmNsYXNzIENhc2Uge1xuXG4gIGNvbnN0cnVjdG9yKHBhdHRlcm4sIGZuLCBndWFyZCA9ICgpID0+IHRydWUpIHtcbiAgICB0aGlzLnBhdHRlcm4gPSBidWlsZE1hdGNoKHBhdHRlcm4pO1xuICAgIHRoaXMuZm4gPSBmbjtcbiAgICB0aGlzLmd1YXJkID0gZ3VhcmQ7XG4gIH1cbn1cblxuZnVuY3Rpb24gbWFrZV9jYXNlKHBhdHRlcm4sIGZuLCBndWFyZCA9ICgpID0+IHRydWUpIHtcbiAgcmV0dXJuIG5ldyBDYXNlKHBhdHRlcm4sIGZuLCBndWFyZCk7XG59XG5cbmZ1bmN0aW9uIGRlZm1hdGNoKC4uLmNhc2VzKSB7XG4gIHJldHVybiBmdW5jdGlvbiAoLi4uYXJncykge1xuICAgIGZvciAobGV0IHByb2Nlc3NlZENhc2Ugb2YgY2FzZXMpIHtcbiAgICAgIGxldCByZXN1bHQgPSBbXTtcbiAgICAgIGlmIChwcm9jZXNzZWRDYXNlLnBhdHRlcm4oYXJncywgcmVzdWx0KSAmJiBwcm9jZXNzZWRDYXNlLmd1YXJkLmFwcGx5KHRoaXMsIHJlc3VsdCkpIHtcbiAgICAgICAgcmV0dXJuIHByb2Nlc3NlZENhc2UuZm4uYXBwbHkodGhpcywgcmVzdWx0KTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICB0aHJvdyBuZXcgTWF0Y2hFcnJvcihhcmdzKTtcbiAgfTtcbn1cblxuZnVuY3Rpb24gbWF0Y2gocGF0dGVybiwgZXhwciwgZ3VhcmQgPSAoKSA9PiB0cnVlKSB7XG4gIGxldCByZXN1bHQgPSBbXTtcbiAgbGV0IHByb2Nlc3NlZFBhdHRlcm4gPSBidWlsZE1hdGNoKHBhdHRlcm4pO1xuICBpZiAocHJvY2Vzc2VkUGF0dGVybihleHByLCByZXN1bHQpICYmIGd1YXJkLmFwcGx5KHRoaXMsIHJlc3VsdCkpIHtcbiAgICByZXR1cm4gcmVzdWx0O1xuICB9IGVsc2Uge1xuICAgIHRocm93IG5ldyBNYXRjaEVycm9yKGV4cHIpO1xuICB9XG59XG5cbmZ1bmN0aW9uIG1hdGNoX25vX3Rocm93KHBhdHRlcm4sIGV4cHIsIGd1YXJkID0gKCkgPT4gdHJ1ZSkge1xuICB0cnkge1xuICAgIHJldHVybiBtYXRjaChwYXR0ZXJuLCBleHByLCBndWFyZCk7XG4gIH0gY2F0Y2ggKGUpIHtcbiAgICBpZiAoZSBpbnN0YW5jZW9mIE1hdGNoRXJyb3IpIHtcbiAgICAgIHJldHVybiBudWxsO1xuICAgIH1cblxuICAgIHRocm93IGU7XG4gIH1cbn1cblxudmFyIFBhdHRlcm5zID0ge1xuICBkZWZtYXRjaCwgbWF0Y2gsIE1hdGNoRXJyb3IsIG1hdGNoX25vX3Rocm93LFxuICB2YXJpYWJsZSwgd2lsZGNhcmQsIHN0YXJ0c1dpdGgsXG4gIGNhcHR1cmUsIGhlYWRUYWlsLCB0eXBlLCBib3VuZCwgQ2FzZSwgbWFrZV9jYXNlXG59O1xuXG5jbGFzcyBCaXRTdHJpbmcge1xuICBjb25zdHJ1Y3RvciguLi5hcmdzKSB7XG4gICAgdGhpcy5yYXdfdmFsdWUgPSBmdW5jdGlvbiAoKSB7XG4gICAgICByZXR1cm4gT2JqZWN0LmZyZWV6ZShhcmdzKTtcbiAgICB9O1xuXG4gICAgdGhpcy52YWx1ZSA9IE9iamVjdC5mcmVlemUodGhpcy5wcm9jZXNzKGFyZ3MpKTtcbiAgfVxuXG4gIGdldChpbmRleCkge1xuICAgIHJldHVybiB0aGlzLnZhbHVlW2luZGV4XTtcbiAgfVxuXG4gIGNvdW50KCkge1xuICAgIHJldHVybiB0aGlzLnZhbHVlLmxlbmd0aDtcbiAgfVxuXG4gIFtTeW1ib2wuaXRlcmF0b3JdKCkge1xuICAgIHJldHVybiB0aGlzLnZhbHVlW1N5bWJvbC5pdGVyYXRvcl0oKTtcbiAgfVxuXG4gIHRvU3RyaW5nKCkge1xuICAgIHZhciBpLFxuICAgICAgICBzID0gXCJcIjtcbiAgICBmb3IgKGkgPSAwOyBpIDwgdGhpcy5jb3VudCgpOyBpKyspIHtcbiAgICAgIGlmIChzICE9PSBcIlwiKSB7XG4gICAgICAgIHMgKz0gXCIsIFwiO1xuICAgICAgfVxuICAgICAgcyArPSB0aGlzW2ldLnRvU3RyaW5nKCk7XG4gICAgfVxuXG4gICAgcmV0dXJuIFwiPDxcIiArIHMgKyBcIj4+XCI7XG4gIH1cblxuICBwcm9jZXNzKCkge1xuICAgIGxldCBwcm9jZXNzZWRfdmFsdWVzID0gW107XG5cbiAgICB2YXIgaTtcbiAgICBmb3IgKGkgPSAwOyBpIDwgdGhpcy5yYXdfdmFsdWUoKS5sZW5ndGg7IGkrKykge1xuICAgICAgbGV0IHByb2Nlc3NlZF92YWx1ZSA9IHRoaXNbXCJwcm9jZXNzX1wiICsgdGhpcy5yYXdfdmFsdWUoKVtpXS50eXBlXSh0aGlzLnJhd192YWx1ZSgpW2ldKTtcblxuICAgICAgZm9yIChsZXQgYXR0ciBvZiB0aGlzLnJhd192YWx1ZSgpW2ldLmF0dHJpYnV0ZXMpIHtcbiAgICAgICAgcHJvY2Vzc2VkX3ZhbHVlID0gdGhpc1tcInByb2Nlc3NfXCIgKyBhdHRyXShwcm9jZXNzZWRfdmFsdWUpO1xuICAgICAgfVxuXG4gICAgICBwcm9jZXNzZWRfdmFsdWVzID0gcHJvY2Vzc2VkX3ZhbHVlcy5jb25jYXQocHJvY2Vzc2VkX3ZhbHVlKTtcbiAgICB9XG5cbiAgICByZXR1cm4gcHJvY2Vzc2VkX3ZhbHVlcztcbiAgfVxuXG4gIHByb2Nlc3NfaW50ZWdlcih2YWx1ZSkge1xuICAgIHJldHVybiB2YWx1ZS52YWx1ZTtcbiAgfVxuXG4gIHByb2Nlc3NfZmxvYXQodmFsdWUpIHtcbiAgICBpZiAodmFsdWUuc2l6ZSA9PT0gNjQpIHtcbiAgICAgIHJldHVybiBCaXRTdHJpbmcuZmxvYXQ2NFRvQnl0ZXModmFsdWUudmFsdWUpO1xuICAgIH0gZWxzZSBpZiAodmFsdWUuc2l6ZSA9PT0gMzIpIHtcbiAgICAgIHJldHVybiBCaXRTdHJpbmcuZmxvYXQzMlRvQnl0ZXModmFsdWUudmFsdWUpO1xuICAgIH1cblxuICAgIHRocm93IG5ldyBFcnJvcihcIkludmFsaWQgc2l6ZSBmb3IgZmxvYXRcIik7XG4gIH1cblxuICBwcm9jZXNzX2JpdHN0cmluZyh2YWx1ZSkge1xuICAgIHJldHVybiB2YWx1ZS52YWx1ZS52YWx1ZTtcbiAgfVxuXG4gIHByb2Nlc3NfYmluYXJ5KHZhbHVlKSB7XG4gICAgcmV0dXJuIEJpdFN0cmluZy50b1VURjhBcnJheSh2YWx1ZS52YWx1ZSk7XG4gIH1cblxuICBwcm9jZXNzX3V0ZjgodmFsdWUpIHtcbiAgICByZXR1cm4gQml0U3RyaW5nLnRvVVRGOEFycmF5KHZhbHVlLnZhbHVlKTtcbiAgfVxuXG4gIHByb2Nlc3NfdXRmMTYodmFsdWUpIHtcbiAgICByZXR1cm4gQml0U3RyaW5nLnRvVVRGMTZBcnJheSh2YWx1ZS52YWx1ZSk7XG4gIH1cblxuICBwcm9jZXNzX3V0ZjMyKHZhbHVlKSB7XG4gICAgcmV0dXJuIEJpdFN0cmluZy50b1VURjMyQXJyYXkodmFsdWUudmFsdWUpO1xuICB9XG5cbiAgcHJvY2Vzc19zaWduZWQodmFsdWUpIHtcbiAgICByZXR1cm4gbmV3IFVpbnQ4QXJyYXkoW3ZhbHVlXSlbMF07XG4gIH1cblxuICBwcm9jZXNzX3Vuc2lnbmVkKHZhbHVlKSB7XG4gICAgcmV0dXJuIHZhbHVlO1xuICB9XG5cbiAgcHJvY2Vzc19uYXRpdmUodmFsdWUpIHtcbiAgICByZXR1cm4gdmFsdWU7XG4gIH1cblxuICBwcm9jZXNzX2JpZyh2YWx1ZSkge1xuICAgIHJldHVybiB2YWx1ZTtcbiAgfVxuXG4gIHByb2Nlc3NfbGl0dGxlKHZhbHVlKSB7XG4gICAgcmV0dXJuIHZhbHVlLnJldmVyc2UoKTtcbiAgfVxuXG4gIHByb2Nlc3Nfc2l6ZSh2YWx1ZSkge1xuICAgIHJldHVybiB2YWx1ZTtcbiAgfVxuXG4gIHByb2Nlc3NfdW5pdCh2YWx1ZSkge1xuICAgIHJldHVybiB2YWx1ZTtcbiAgfVxuXG4gIHN0YXRpYyBpbnRlZ2VyKHZhbHVlKSB7XG4gICAgcmV0dXJuIEJpdFN0cmluZy53cmFwKHZhbHVlLCB7IFwidHlwZVwiOiBcImludGVnZXJcIiwgXCJ1bml0XCI6IDEsIFwic2l6ZVwiOiA4IH0pO1xuICB9XG5cbiAgc3RhdGljIGZsb2F0KHZhbHVlKSB7XG4gICAgcmV0dXJuIEJpdFN0cmluZy53cmFwKHZhbHVlLCB7IFwidHlwZVwiOiBcImZsb2F0XCIsIFwidW5pdFwiOiAxLCBcInNpemVcIjogNjQgfSk7XG4gIH1cblxuICBzdGF0aWMgYml0c3RyaW5nKHZhbHVlKSB7XG4gICAgcmV0dXJuIEJpdFN0cmluZy53cmFwKHZhbHVlLCB7IFwidHlwZVwiOiBcImJpdHN0cmluZ1wiLCBcInVuaXRcIjogMSwgXCJzaXplXCI6IHZhbHVlLmxlbmd0aCB9KTtcbiAgfVxuXG4gIHN0YXRpYyBiaXRzKHZhbHVlKSB7XG4gICAgcmV0dXJuIEJpdFN0cmluZy5iaXRzdHJpbmcodmFsdWUpO1xuICB9XG5cbiAgc3RhdGljIGJpbmFyeSh2YWx1ZSkge1xuICAgIHJldHVybiBCaXRTdHJpbmcud3JhcCh2YWx1ZSwgeyBcInR5cGVcIjogXCJiaW5hcnlcIiwgXCJ1bml0XCI6IDgsIFwic2l6ZVwiOiB2YWx1ZS5sZW5ndGggfSk7XG4gIH1cblxuICBzdGF0aWMgYnl0ZXModmFsdWUpIHtcbiAgICByZXR1cm4gQml0U3RyaW5nLmJpbmFyeSh2YWx1ZSk7XG4gIH1cblxuICBzdGF0aWMgdXRmOCh2YWx1ZSkge1xuICAgIHJldHVybiBCaXRTdHJpbmcud3JhcCh2YWx1ZSwgeyBcInR5cGVcIjogXCJ1dGY4XCIgfSk7XG4gIH1cblxuICBzdGF0aWMgdXRmMTYodmFsdWUpIHtcbiAgICByZXR1cm4gQml0U3RyaW5nLndyYXAodmFsdWUsIHsgXCJ0eXBlXCI6IFwidXRmMTZcIiB9KTtcbiAgfVxuXG4gIHN0YXRpYyB1dGYzMih2YWx1ZSkge1xuICAgIHJldHVybiBCaXRTdHJpbmcud3JhcCh2YWx1ZSwgeyBcInR5cGVcIjogXCJ1dGYzMlwiIH0pO1xuICB9XG5cbiAgc3RhdGljIHNpZ25lZCh2YWx1ZSkge1xuICAgIHJldHVybiBCaXRTdHJpbmcud3JhcCh2YWx1ZSwge30sIFwic2lnbmVkXCIpO1xuICB9XG5cbiAgc3RhdGljIHVuc2lnbmVkKHZhbHVlKSB7XG4gICAgcmV0dXJuIEJpdFN0cmluZy53cmFwKHZhbHVlLCB7fSwgXCJ1bnNpZ25lZFwiKTtcbiAgfVxuXG4gIHN0YXRpYyBuYXRpdmUodmFsdWUpIHtcbiAgICByZXR1cm4gQml0U3RyaW5nLndyYXAodmFsdWUsIHt9LCBcIm5hdGl2ZVwiKTtcbiAgfVxuXG4gIHN0YXRpYyBiaWcodmFsdWUpIHtcbiAgICByZXR1cm4gQml0U3RyaW5nLndyYXAodmFsdWUsIHt9LCBcImJpZ1wiKTtcbiAgfVxuXG4gIHN0YXRpYyBsaXR0bGUodmFsdWUpIHtcbiAgICByZXR1cm4gQml0U3RyaW5nLndyYXAodmFsdWUsIHt9LCBcImxpdHRsZVwiKTtcbiAgfVxuXG4gIHN0YXRpYyBzaXplKHZhbHVlLCBjb3VudCkge1xuICAgIHJldHVybiBCaXRTdHJpbmcud3JhcCh2YWx1ZSwgeyBcInNpemVcIjogY291bnQgfSk7XG4gIH1cblxuICBzdGF0aWMgdW5pdCh2YWx1ZSwgY291bnQpIHtcbiAgICByZXR1cm4gQml0U3RyaW5nLndyYXAodmFsdWUsIHsgXCJ1bml0XCI6IGNvdW50IH0pO1xuICB9XG5cbiAgc3RhdGljIHdyYXAodmFsdWUsIG9wdCwgbmV3X2F0dHJpYnV0ZSA9IG51bGwpIHtcbiAgICBsZXQgdGhlX3ZhbHVlID0gdmFsdWU7XG5cbiAgICBpZiAoISh2YWx1ZSBpbnN0YW5jZW9mIE9iamVjdCkpIHtcbiAgICAgIHRoZV92YWx1ZSA9IHsgXCJ2YWx1ZVwiOiB2YWx1ZSwgXCJhdHRyaWJ1dGVzXCI6IFtdIH07XG4gICAgfVxuXG4gICAgdGhlX3ZhbHVlID0gT2JqZWN0LmFzc2lnbih0aGVfdmFsdWUsIG9wdCk7XG5cbiAgICBpZiAobmV3X2F0dHJpYnV0ZSkge1xuICAgICAgdGhlX3ZhbHVlLmF0dHJpYnV0ZXMucHVzaChuZXdfYXR0cmlidXRlKTtcbiAgICB9XG5cbiAgICByZXR1cm4gdGhlX3ZhbHVlO1xuICB9XG5cbiAgc3RhdGljIHRvVVRGOEFycmF5KHN0cikge1xuICAgIHZhciB1dGY4ID0gW107XG4gICAgZm9yICh2YXIgaSA9IDA7IGkgPCBzdHIubGVuZ3RoOyBpKyspIHtcbiAgICAgIHZhciBjaGFyY29kZSA9IHN0ci5jaGFyQ29kZUF0KGkpO1xuICAgICAgaWYgKGNoYXJjb2RlIDwgMTI4KSB7XG4gICAgICAgIHV0ZjgucHVzaChjaGFyY29kZSk7XG4gICAgICB9IGVsc2UgaWYgKGNoYXJjb2RlIDwgMjA0OCkge1xuICAgICAgICB1dGY4LnB1c2goMTkyIHwgY2hhcmNvZGUgPj4gNiwgMTI4IHwgY2hhcmNvZGUgJiA2Myk7XG4gICAgICB9IGVsc2UgaWYgKGNoYXJjb2RlIDwgNTUyOTYgfHwgY2hhcmNvZGUgPj0gNTczNDQpIHtcbiAgICAgICAgdXRmOC5wdXNoKDIyNCB8IGNoYXJjb2RlID4+IDEyLCAxMjggfCBjaGFyY29kZSA+PiA2ICYgNjMsIDEyOCB8IGNoYXJjb2RlICYgNjMpO1xuICAgICAgfVxuICAgICAgLy8gc3Vycm9nYXRlIHBhaXJcbiAgICAgIGVsc2Uge1xuICAgICAgICBpKys7XG4gICAgICAgIC8vIFVURi0xNiBlbmNvZGVzIDB4MTAwMDAtMHgxMEZGRkYgYnlcbiAgICAgICAgLy8gc3VidHJhY3RpbmcgMHgxMDAwMCBhbmQgc3BsaXR0aW5nIHRoZVxuICAgICAgICAvLyAyMCBiaXRzIG9mIDB4MC0weEZGRkZGIGludG8gdHdvIGhhbHZlc1xuICAgICAgICBjaGFyY29kZSA9IDY1NTM2ICsgKChjaGFyY29kZSAmIDEwMjMpIDw8IDEwIHwgc3RyLmNoYXJDb2RlQXQoaSkgJiAxMDIzKTtcbiAgICAgICAgdXRmOC5wdXNoKDI0MCB8IGNoYXJjb2RlID4+IDE4LCAxMjggfCBjaGFyY29kZSA+PiAxMiAmIDYzLCAxMjggfCBjaGFyY29kZSA+PiA2ICYgNjMsIDEyOCB8IGNoYXJjb2RlICYgNjMpO1xuICAgICAgfVxuICAgIH1cbiAgICByZXR1cm4gdXRmODtcbiAgfVxuXG4gIHN0YXRpYyB0b1VURjE2QXJyYXkoc3RyKSB7XG4gICAgdmFyIHV0ZjE2ID0gW107XG4gICAgZm9yICh2YXIgaSA9IDA7IGkgPCBzdHIubGVuZ3RoOyBpKyspIHtcbiAgICAgIHZhciBjb2RlUG9pbnQgPSBzdHIuY29kZVBvaW50QXQoaSk7XG5cbiAgICAgIGlmIChjb2RlUG9pbnQgPD0gMjU1KSB7XG4gICAgICAgIHV0ZjE2LnB1c2goMCk7XG4gICAgICAgIHV0ZjE2LnB1c2goY29kZVBvaW50KTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHV0ZjE2LnB1c2goY29kZVBvaW50ID4+IDggJiAyNTUpO1xuICAgICAgICB1dGYxNi5wdXNoKGNvZGVQb2ludCAmIDI1NSk7XG4gICAgICB9XG4gICAgfVxuICAgIHJldHVybiB1dGYxNjtcbiAgfVxuXG4gIHN0YXRpYyB0b1VURjMyQXJyYXkoc3RyKSB7XG4gICAgdmFyIHV0ZjMyID0gW107XG4gICAgZm9yICh2YXIgaSA9IDA7IGkgPCBzdHIubGVuZ3RoOyBpKyspIHtcbiAgICAgIHZhciBjb2RlUG9pbnQgPSBzdHIuY29kZVBvaW50QXQoaSk7XG5cbiAgICAgIGlmIChjb2RlUG9pbnQgPD0gMjU1KSB7XG4gICAgICAgIHV0ZjMyLnB1c2goMCk7XG4gICAgICAgIHV0ZjMyLnB1c2goMCk7XG4gICAgICAgIHV0ZjMyLnB1c2goMCk7XG4gICAgICAgIHV0ZjMyLnB1c2goY29kZVBvaW50KTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHV0ZjMyLnB1c2goMCk7XG4gICAgICAgIHV0ZjMyLnB1c2goMCk7XG4gICAgICAgIHV0ZjMyLnB1c2goY29kZVBvaW50ID4+IDggJiAyNTUpO1xuICAgICAgICB1dGYzMi5wdXNoKGNvZGVQb2ludCAmIDI1NSk7XG4gICAgICB9XG4gICAgfVxuICAgIHJldHVybiB1dGYzMjtcbiAgfVxuXG4gIC8vaHR0cDovL3N0YWNrb3ZlcmZsb3cuY29tL3F1ZXN0aW9ucy8yMDAzNDkzL2phdmFzY3JpcHQtZmxvYXQtZnJvbS10by1iaXRzXG4gIHN0YXRpYyBmbG9hdDMyVG9CeXRlcyhmKSB7XG4gICAgdmFyIGJ5dGVzID0gW107XG5cbiAgICB2YXIgYnVmID0gbmV3IEFycmF5QnVmZmVyKDQpO1xuICAgIG5ldyBGbG9hdDMyQXJyYXkoYnVmKVswXSA9IGY7XG5cbiAgICBsZXQgaW50VmVyc2lvbiA9IG5ldyBVaW50MzJBcnJheShidWYpWzBdO1xuXG4gICAgYnl0ZXMucHVzaChpbnRWZXJzaW9uID4+IDI0ICYgMjU1KTtcbiAgICBieXRlcy5wdXNoKGludFZlcnNpb24gPj4gMTYgJiAyNTUpO1xuICAgIGJ5dGVzLnB1c2goaW50VmVyc2lvbiA+PiA4ICYgMjU1KTtcbiAgICBieXRlcy5wdXNoKGludFZlcnNpb24gJiAyNTUpO1xuXG4gICAgcmV0dXJuIGJ5dGVzO1xuICB9XG5cbiAgc3RhdGljIGZsb2F0NjRUb0J5dGVzKGYpIHtcbiAgICB2YXIgYnl0ZXMgPSBbXTtcblxuICAgIHZhciBidWYgPSBuZXcgQXJyYXlCdWZmZXIoOCk7XG4gICAgbmV3IEZsb2F0NjRBcnJheShidWYpWzBdID0gZjtcblxuICAgIHZhciBpbnRWZXJzaW9uMSA9IG5ldyBVaW50MzJBcnJheShidWYpWzBdO1xuICAgIHZhciBpbnRWZXJzaW9uMiA9IG5ldyBVaW50MzJBcnJheShidWYpWzFdO1xuXG4gICAgYnl0ZXMucHVzaChpbnRWZXJzaW9uMiA+PiAyNCAmIDI1NSk7XG4gICAgYnl0ZXMucHVzaChpbnRWZXJzaW9uMiA+PiAxNiAmIDI1NSk7XG4gICAgYnl0ZXMucHVzaChpbnRWZXJzaW9uMiA+PiA4ICYgMjU1KTtcbiAgICBieXRlcy5wdXNoKGludFZlcnNpb24yICYgMjU1KTtcblxuICAgIGJ5dGVzLnB1c2goaW50VmVyc2lvbjEgPj4gMjQgJiAyNTUpO1xuICAgIGJ5dGVzLnB1c2goaW50VmVyc2lvbjEgPj4gMTYgJiAyNTUpO1xuICAgIGJ5dGVzLnB1c2goaW50VmVyc2lvbjEgPj4gOCAmIDI1NSk7XG4gICAgYnl0ZXMucHVzaChpbnRWZXJzaW9uMSAmIDI1NSk7XG5cbiAgICByZXR1cm4gYnl0ZXM7XG4gIH1cbn1cblxuLyogQGZsb3cgKi9cblxuY2xhc3MgTWFpbGJveCB7XG5cbiAgY29uc3RydWN0b3IoKSB7XG4gICAgdGhpcy5tZXNzYWdlcyA9IFtdO1xuICB9XG5cbiAgZGVsaXZlcihtZXNzYWdlKSB7XG4gICAgdGhpcy5tZXNzYWdlcy5wdXNoKG1lc3NhZ2UpO1xuICAgIHJldHVybiBtZXNzYWdlO1xuICB9XG5cbiAgZ2V0KCkge1xuICAgIHJldHVybiB0aGlzLm1lc3NhZ2VzO1xuICB9XG5cbiAgaXNFbXB0eSgpIHtcbiAgICByZXR1cm4gdGhpcy5tZXNzYWdlcy5sZW5ndGggPT09IDA7XG4gIH1cblxuICByZW1vdmVBdChpbmRleCkge1xuICAgIHRoaXMubWVzc2FnZXMuc3BsaWNlKGluZGV4LCAxKTtcbiAgfVxufVxuXG52YXIgU3RhdGVzID0ge1xuICBOT1JNQUw6IFN5bWJvbC5mb3IoXCJub3JtYWxcIiksXG4gIEtJTEw6IFN5bWJvbC5mb3IoXCJraWxsXCIpLFxuICBTVVNQRU5EOiBTeW1ib2wuZm9yKFwic3VzcGVuZFwiKSxcbiAgQ09OVElOVUU6IFN5bWJvbC5mb3IoXCJjb250aW51ZVwiKSxcbiAgUkVDRUlWRTogU3ltYm9sLmZvcihcInJlY2VpdmVcIiksXG4gIFNFTkQ6IFN5bWJvbC5mb3IoXCJzZW5kXCIpLFxuICBTTEVFUElORzogU3ltYm9sLmZvcihcInNsZWVwaW5nXCIpLFxuICBSVU5OSU5HOiBTeW1ib2wuZm9yKFwicnVubmluZ1wiKSxcbiAgU1VTUEVOREVEOiBTeW1ib2wuZm9yKFwic3VzcGVuZGVkXCIpLFxuICBTVE9QUEVEOiBTeW1ib2wuZm9yKFwic3RvcHBlZFwiKSxcbiAgU0xFRVA6IFN5bWJvbC5mb3IoXCJzbGVlcFwiKSxcbiAgRVhJVDogU3ltYm9sLmZvcihcImV4aXRcIiksXG4gIE5PTUFUQ0g6IFN5bWJvbC5mb3IoXCJub19tYXRjaFwiKVxufTtcblxuY2xhc3MgUHJvY2VzcyB7XG5cbiAgY29uc3RydWN0b3IocGlkLCBtYWlsYm94KSB7XG4gICAgdGhpcy5waWQgPSBwaWQ7XG4gICAgdGhpcy5tYWlsYm94ID0gbWFpbGJveDtcbiAgICB0aGlzLnN0YXR1cyA9IFN0YXRlcy5TVE9QUEVEO1xuICAgIHRoaXMuZGljdCA9IHt9O1xuICB9XG59XG5cbmNsYXNzIFByb2Nlc3NTeXN0ZW0ge1xuXG4gIGNvbnN0cnVjdG9yKCkge1xuICAgIHRoaXMucGlkcyA9IG5ldyBNYXAoKTtcbiAgICB0aGlzLm1haWxib3hlcyA9IG5ldyBNYXAoKTtcbiAgICB0aGlzLm5hbWVzID0gbmV3IE1hcCgpO1xuICAgIHRoaXMubGlua3MgPSBuZXcgTWFwKCk7XG5cbiAgICB0aGlzLmN1cnJlbnRfcHJvY2VzcyA9IG51bGw7XG4gICAgdGhpcy5zdXNwZW5kZWQgPSBuZXcgTWFwKCk7XG5cbiAgICB0aGlzLm1haW5fcHJvY2Vzc19waWQgPSB0aGlzLnNwYXduKCk7XG4gICAgdGhpcy5zZXRfY3VycmVudCh0aGlzLm1haW5fcHJvY2Vzc19waWQpO1xuICB9XG5cbiAgc3Bhd24oKSB7XG4gICAgcmV0dXJuIHRoaXMuYWRkX3Byb2MoZmFsc2UpLnBpZDtcbiAgfVxuXG4gIHNwYXduX2xpbmsoKSB7XG4gICAgcmV0dXJuIHRoaXMuYWRkX3Byb2ModHJ1ZSkucGlkO1xuICB9XG5cbiAgbGluayhwaWQpIHtcbiAgICB0aGlzLmxpbmtzLmdldCh0aGlzLnBpZCgpKS5hZGQocGlkKTtcbiAgICB0aGlzLmxpbmtzLmdldChwaWQpLmFkZCh0aGlzLnBpZCgpKTtcbiAgfVxuXG4gIHVubGluayhwaWQpIHtcbiAgICB0aGlzLmxpbmtzLmdldCh0aGlzLnBpZCgpKS5kZWxldGUocGlkKTtcbiAgICB0aGlzLmxpbmtzLmdldChwaWQpLmRlbGV0ZSh0aGlzLnBpZCgpKTtcbiAgfVxuXG4gIHNldF9jdXJyZW50KGlkKSB7XG4gICAgbGV0IHBpZCA9IHRoaXMucGlkb2YoaWQpO1xuICAgIGlmIChwaWQgIT09IG51bGwpIHtcbiAgICAgIHRoaXMuY3VycmVudF9wcm9jZXNzID0gdGhpcy5waWRzLmdldChwaWQpO1xuICAgICAgdGhpcy5jdXJyZW50X3Byb2Nlc3Muc3RhdHVzID0gU3RhdGVzLlJVTk5JTkc7XG4gICAgfVxuICB9XG5cbiAgYWRkX3Byb2MobGlua2VkKSB7XG4gICAgbGV0IG5ld3BpZCA9IG5ldyBQSUQoKTtcbiAgICBsZXQgbWFpbGJveCA9IG5ldyBNYWlsYm94KCk7XG4gICAgbGV0IG5ld3Byb2MgPSBuZXcgUHJvY2VzcyhuZXdwaWQsIG1haWxib3gpO1xuXG4gICAgdGhpcy5waWRzLnNldChuZXdwaWQsIG5ld3Byb2MpO1xuICAgIHRoaXMubWFpbGJveGVzLnNldChuZXdwaWQsIG1haWxib3gpO1xuICAgIHRoaXMubGlua3Muc2V0KG5ld3BpZCwgbmV3IFNldCgpKTtcblxuICAgIGlmIChsaW5rZWQpIHtcbiAgICAgIHRoaXMubGluayhuZXdwaWQpO1xuICAgIH1cblxuICAgIHJldHVybiBuZXdwcm9jO1xuICB9XG5cbiAgcmVtb3ZlX3Byb2MocGlkKSB7XG4gICAgdGhpcy5waWRzLmRlbGV0ZShwaWQpO1xuICAgIHRoaXMudW5yZWdpc3RlcihwaWQpO1xuXG4gICAgaWYgKHRoaXMubGlua3MuaGFzKHBpZCkpIHtcbiAgICAgIGZvciAobGV0IGxpbmtwaWQgb2YgdGhpcy5saW5rcy5nZXQocGlkKSkge1xuICAgICAgICB0aGlzLmxpbmtzLmdldChsaW5rcGlkKS5kZWxldGUocGlkKTtcbiAgICAgIH1cblxuICAgICAgdGhpcy5saW5rcy5kZWxldGUocGlkKTtcbiAgICB9XG4gIH1cblxuICBleGl0KGlkKSB7XG4gICAgbGV0IHBpZCA9IHRoaXMucGlkb2YoaWQpO1xuICAgIHRoaXMucmVtb3ZlX3Byb2MoaWQpO1xuICB9XG5cbiAgcmVnaXN0ZXIobmFtZSwgcGlkKSB7XG4gICAgaWYgKCF0aGlzLm5hbWVzLmhhcyhuYW1lKSkge1xuICAgICAgdGhpcy5uYW1lcy5zZXQobmFtZSwgcGlkKTtcbiAgICAgIHJldHVybiBuYW1lO1xuICAgIH0gZWxzZSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoXCJOYW1lIGlzIGFscmVhZHkgcmVnaXN0ZXJlZCB0byBhbm90aGVyIHByb2Nlc3NcIik7XG4gICAgfVxuICB9XG5cbiAgcmVnaXN0ZXJlZChuYW1lKSB7XG4gICAgcmV0dXJuIHRoaXMubmFtZXMuaGFzKG5hbWUpID8gdGhpcy5uYW1lcy5nZXQobmFtZSkgOiBudWxsO1xuICB9XG5cbiAgdW5yZWdpc3RlcihwaWQpIHtcbiAgICBmb3IgKGxldCBuYW1lIG9mIHRoaXMubmFtZXMua2V5cygpKSB7XG4gICAgICBpZiAodGhpcy5uYW1lcy5oYXMobmFtZSkgJiYgdGhpcy5uYW1lcy5nZXQobmFtZSkgPT09IHBpZCkge1xuICAgICAgICB0aGlzLm5hbWVzLmRlbGV0ZShuYW1lKTtcbiAgICAgIH1cbiAgICB9XG4gIH1cblxuICBwaWQoKSB7XG4gICAgcmV0dXJuIHRoaXMuY3VycmVudF9wcm9jZXNzLnBpZDtcbiAgfVxuXG4gIHBpZG9mKGlkKSB7XG4gICAgaWYgKGlkIGluc3RhbmNlb2YgUElEKSB7XG4gICAgICByZXR1cm4gdGhpcy5waWRzLmhhcyhpZCkgPyBpZCA6IG51bGw7XG4gICAgfSBlbHNlIGlmIChpZCBpbnN0YW5jZW9mIFByb2Nlc3MpIHtcbiAgICAgIHJldHVybiBpZC5waWQ7XG4gICAgfSBlbHNlIHtcbiAgICAgIGxldCBwaWQgPSB0aGlzLnJlZ2lzdGVyZWQoaWQpO1xuICAgICAgaWYgKHBpZCA9PT0gbnVsbCkgdGhyb3cgXCJQcm9jZXNzIG5hbWUgbm90IHJlZ2lzdGVyZWQ6IFwiICsgaWQgKyBcIiAoXCIgKyB0eXBlb2YgaWQgKyBcIilcIjtcbiAgICAgIHJldHVybiBwaWQ7XG4gICAgfVxuICB9XG5cbiAgcHV0KGlkLCBrZXksIHZhbHVlKSB7XG4gICAgbGV0IHBpZCA9IHRoaXMucGlkb2YoaWQpO1xuICAgIGxldCBwcm9jZXNzID0gdGhpcy5waWRzLmdldChwaWQpO1xuICAgIHByb2Nlc3MuZGljdFtrZXldID0gdmFsdWU7XG4gIH1cblxuICBnZXQoaWQsIGtleSkge1xuICAgIGxldCBwaWQgPSB0aGlzLnBpZG9mKGlkKTtcbiAgICBsZXQgcHJvY2VzcyA9IHRoaXMucGlkcy5nZXQocGlkKTtcblxuICAgIGlmIChrZXkgIT0gbnVsbCkge1xuICAgICAgcmV0dXJuIHByb2Nlc3MuZGljdFtrZXldO1xuICAgIH0gZWxzZSB7XG4gICAgICByZXR1cm4gcHJvY2Vzcy5kaWN0O1xuICAgIH1cbiAgfVxuXG4gIGdldF9rZXlzKGlkKSB7XG4gICAgbGV0IHBpZCA9IHRoaXMucGlkb2YoaWQpO1xuICAgIGxldCBwcm9jZXNzID0gdGhpcy5waWRzLmdldChwaWQpO1xuXG4gICAgcmV0dXJuIE9iamVjdC5rZXlzKHByb2Nlc3MuZGljdCk7XG4gIH1cblxuICBlcmFzZShpZCwga2V5KSB7XG4gICAgbGV0IHBpZCA9IHRoaXMucGlkb2YoaWQpO1xuICAgIGxldCBwcm9jZXNzID0gdGhpcy5waWRzLmdldChwaWQpO1xuXG4gICAgaWYgKGtleSAhPSBudWxsKSB7XG4gICAgICBkZWxldGUgcHJvY2Vzcy5kaWN0W2tleV07XG4gICAgfSBlbHNlIHtcbiAgICAgIHByb2Nlc3MuZGljdCA9IHt9O1xuICAgIH1cbiAgfVxufVxuXG52YXIgQyA9IE9iamVjdC5mcmVlemUoe1xuXHRQcm9jZXNzU3lzdGVtOiBQcm9jZXNzU3lzdGVtLFxuXHRUdXBsZTogVHVwbGUkMSxcblx0UElEOiBQSUQsXG5cdEJpdFN0cmluZzogQml0U3RyaW5nLFxuXHRQYXR0ZXJuczogUGF0dGVybnMsXG5cdEludGVnZXJUeXBlOiBJbnRlZ2VyVHlwZSxcblx0RmxvYXRUeXBlOiBGbG9hdFR5cGUsXG5cdGNhbGxfcHJvcGVydHk6IGNhbGxfcHJvcGVydHlcbn0pO1xuXG5sZXQgRW51bSA9IHtcblxuICBhbGxfX3FtYXJrX186IGZ1bmN0aW9uIChjb2xsZWN0aW9uLCBmdW4gPSB4ID0+IHgpIHtcbiAgICBmb3IgKGxldCBlbGVtIG9mIGNvbGxlY3Rpb24pIHtcbiAgICAgIGlmICghZnVuKGVsZW0pKSB7XG4gICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICByZXR1cm4gdHJ1ZTtcbiAgfSxcblxuICBhbnlfX3FtYXJrX186IGZ1bmN0aW9uIChjb2xsZWN0aW9uLCBmdW4gPSB4ID0+IHgpIHtcbiAgICBmb3IgKGxldCBlbGVtIG9mIGNvbGxlY3Rpb24pIHtcbiAgICAgIGlmIChmdW4oZWxlbSkpIHtcbiAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICB9XG4gICAgfVxuXG4gICAgcmV0dXJuIGZhbHNlO1xuICB9LFxuXG4gIGF0OiBmdW5jdGlvbiAoY29sbGVjdGlvbiwgbiwgdGhlX2RlZmF1bHQgPSBudWxsKSB7XG4gICAgaWYgKG4gPiB0aGlzLmNvdW50KGNvbGxlY3Rpb24pIHx8IG4gPCAwKSB7XG4gICAgICByZXR1cm4gdGhlX2RlZmF1bHQ7XG4gICAgfVxuXG4gICAgcmV0dXJuIGNvbGxlY3Rpb25bbl07XG4gIH0sXG5cbiAgY29uY2F0OiBmdW5jdGlvbiAoLi4uZW51bWFibGVzKSB7XG4gICAgcmV0dXJuIGVudW1hYmxlc1swXS5jb25jYXQoZW51bWFibGVzWzFdKTtcbiAgfSxcblxuICBjb3VudDogZnVuY3Rpb24gKGNvbGxlY3Rpb24sIGZ1biA9IG51bGwpIHtcbiAgICBpZiAoZnVuID09IG51bGwpIHtcbiAgICAgIHJldHVybiBjb2xsZWN0aW9uLmxlbmd0aDtcbiAgICB9IGVsc2Uge1xuICAgICAgcmV0dXJuIGNvbGxlY3Rpb24uZmlsdGVyKGZ1bikubGVuZ3RoO1xuICAgIH1cbiAgfSxcblxuICBkcm9wOiBmdW5jdGlvbiAoY29sbGVjdGlvbiwgY291bnQpIHtcbiAgICByZXR1cm4gY29sbGVjdGlvbi5zbGljZShjb3VudCk7XG4gIH0sXG5cbiAgZHJvcF93aGlsZTogZnVuY3Rpb24gKGNvbGxlY3Rpb24sIGZ1bikge1xuICAgIGxldCBjb3VudCA9IDA7XG5cbiAgICBmb3IgKGxldCBlbGVtIG9mIGNvbGxlY3Rpb24pIHtcbiAgICAgIGlmIChmdW4oZWxlbSkpIHtcbiAgICAgICAgY291bnQgPSBjb3VudCArIDE7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBicmVhaztcbiAgICAgIH1cbiAgICB9XG5cbiAgICByZXR1cm4gY29sbGVjdGlvbi5zbGljZShjb3VudCk7XG4gIH0sXG5cbiAgZWFjaDogZnVuY3Rpb24gKGNvbGxlY3Rpb24sIGZ1bikge1xuICAgIGZvciAobGV0IGVsZW0gb2YgY29sbGVjdGlvbikge1xuICAgICAgZnVuKGVsZW0pO1xuICAgIH1cbiAgfSxcblxuICBlbXB0eV9fcW1hcmtfXzogZnVuY3Rpb24gKGNvbGxlY3Rpb24pIHtcbiAgICByZXR1cm4gY29sbGVjdGlvbi5sZW5ndGggPT09IDA7XG4gIH0sXG5cbiAgZmV0Y2g6IGZ1bmN0aW9uIChjb2xsZWN0aW9uLCBuKSB7XG4gICAgaWYgKEtlcm5lbC5pc19saXN0KGNvbGxlY3Rpb24pKSB7XG4gICAgICBpZiAobiA8IHRoaXMuY291bnQoY29sbGVjdGlvbikgJiYgbiA+PSAwKSB7XG4gICAgICAgIHJldHVybiBLZXJuZWwuU3BlY2lhbEZvcm1zLnR1cGxlKEtlcm5lbC5TcGVjaWFsRm9ybXMuYXRvbShcIm9rXCIpLCBjb2xsZWN0aW9uW25dKTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHJldHVybiBLZXJuZWwuU3BlY2lhbEZvcm1zLmF0b20oXCJlcnJvclwiKTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICB0aHJvdyBuZXcgRXJyb3IoXCJjb2xsZWN0aW9uIGlzIG5vdCBhbiBFbnVtZXJhYmxlXCIpO1xuICB9LFxuXG4gIGZldGNoX19lbWFya19fOiBmdW5jdGlvbiAoY29sbGVjdGlvbiwgbikge1xuICAgIGlmIChLZXJuZWwuaXNfbGlzdChjb2xsZWN0aW9uKSkge1xuICAgICAgaWYgKG4gPCB0aGlzLmNvdW50KGNvbGxlY3Rpb24pICYmIG4gPj0gMCkge1xuICAgICAgICByZXR1cm4gY29sbGVjdGlvbltuXTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcihcIm91dCBvZiBib3VuZHMgZXJyb3JcIik7XG4gICAgICB9XG4gICAgfVxuXG4gICAgdGhyb3cgbmV3IEVycm9yKFwiY29sbGVjdGlvbiBpcyBub3QgYW4gRW51bWVyYWJsZVwiKTtcbiAgfSxcblxuICBmaWx0ZXI6IGZ1bmN0aW9uIChjb2xsZWN0aW9uLCBmdW4pIHtcbiAgICBsZXQgcmVzdWx0ID0gW107XG5cbiAgICBmb3IgKGxldCBlbGVtIG9mIGNvbGxlY3Rpb24pIHtcbiAgICAgIGlmIChmdW4oZWxlbSkpIHtcbiAgICAgICAgcmVzdWx0LnB1c2goZWxlbSk7XG4gICAgICB9XG4gICAgfVxuXG4gICAgcmV0dXJuIHJlc3VsdDtcbiAgfSxcblxuICBmaWx0ZXJfbWFwOiBmdW5jdGlvbiAoY29sbGVjdGlvbiwgZmlsdGVyLCBtYXBwZXIpIHtcbiAgICByZXR1cm4gRW51bS5tYXAoRW51bS5maWx0ZXIoY29sbGVjdGlvbiwgZmlsdGVyKSwgbWFwcGVyKTtcbiAgfSxcblxuICBmaW5kOiBmdW5jdGlvbiAoY29sbGVjdGlvbiwgaWZfbm9uZSA9IG51bGwsIGZ1bikge1xuICAgIGZvciAobGV0IGVsZW0gb2YgY29sbGVjdGlvbikge1xuICAgICAgaWYgKGZ1bihlbGVtKSkge1xuICAgICAgICByZXR1cm4gZWxlbTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICByZXR1cm4gaWZfbm9uZTtcbiAgfSxcblxuICBpbnRvOiBmdW5jdGlvbiAoY29sbGVjdGlvbiwgbGlzdCkge1xuICAgIHJldHVybiBsaXN0LmNvbmNhdChjb2xsZWN0aW9uKTtcbiAgfSxcblxuICBtYXA6IGZ1bmN0aW9uIChjb2xsZWN0aW9uLCBmdW4pIHtcbiAgICBsZXQgcmVzdWx0ID0gW107XG5cbiAgICBmb3IgKGxldCBlbGVtIG9mIGNvbGxlY3Rpb24pIHtcbiAgICAgIHJlc3VsdC5wdXNoKGZ1bihlbGVtKSk7XG4gICAgfVxuXG4gICAgcmV0dXJuIHJlc3VsdDtcbiAgfSxcblxuICBtYXBfcmVkdWNlOiBmdW5jdGlvbiAoY29sbGVjdGlvbiwgYWNjLCBmdW4pIHtcbiAgICBsZXQgbWFwcGVkID0gS2VybmVsLlNwZWNpYWxGb3Jtcy5saXN0KCk7XG4gICAgbGV0IHRoZV9hY2MgPSBhY2M7XG5cbiAgICBmb3IgKHZhciBpID0gMDsgaSA8IHRoaXMuY291bnQoY29sbGVjdGlvbik7IGkrKykge1xuICAgICAgbGV0IHR1cGxlID0gZnVuKGNvbGxlY3Rpb25baV0sIHRoZV9hY2MpO1xuXG4gICAgICB0aGVfYWNjID0gS2VybmVsLmVsZW0odHVwbGUsIDEpO1xuICAgICAgbWFwcGVkID0gS2VybmVsLlNwZWNpYWxGb3Jtcy5saXN0KC4uLm1hcHBlZC5jb25jYXQoW0tlcm5lbC5lbGVtKHR1cGxlLCAwKV0pKTtcbiAgICB9XG5cbiAgICByZXR1cm4gS2VybmVsLlNwZWNpYWxGb3Jtcy50dXBsZShtYXBwZWQsIHRoZV9hY2MpO1xuICB9LFxuXG4gIG1lbWJlcjogZnVuY3Rpb24gKGNvbGxlY3Rpb24sIHZhbHVlKSB7XG4gICAgcmV0dXJuIGNvbGxlY3Rpb24uaW5jbHVkZXModmFsdWUpO1xuICB9LFxuXG4gIHJlZHVjZTogZnVuY3Rpb24gKGNvbGxlY3Rpb24sIGFjYywgZnVuKSB7XG4gICAgbGV0IHRoZV9hY2MgPSBhY2M7XG5cbiAgICBmb3IgKHZhciBpID0gMDsgaSA8IHRoaXMuY291bnQoY29sbGVjdGlvbik7IGkrKykge1xuICAgICAgbGV0IHR1cGxlID0gZnVuKGNvbGxlY3Rpb25baV0sIHRoZV9hY2MpO1xuXG4gICAgICB0aGVfYWNjID0gS2VybmVsLmVsZW0odHVwbGUsIDEpO1xuICAgIH1cblxuICAgIHJldHVybiB0aGVfYWNjO1xuICB9LFxuXG4gIHRha2U6IGZ1bmN0aW9uIChjb2xsZWN0aW9uLCBjb3VudCkge1xuICAgIHJldHVybiBjb2xsZWN0aW9uLnNsaWNlKDAsIGNvdW50KTtcbiAgfSxcblxuICB0YWtlX2V2ZXJ5OiBmdW5jdGlvbiAoY29sbGVjdGlvbiwgbnRoKSB7XG4gICAgbGV0IHJlc3VsdCA9IFtdO1xuICAgIGxldCBpbmRleCA9IDA7XG5cbiAgICBmb3IgKGxldCBlbGVtIG9mIGNvbGxlY3Rpb24pIHtcbiAgICAgIGlmIChpbmRleCAlIG50aCA9PT0gMCkge1xuICAgICAgICByZXN1bHQucHVzaChlbGVtKTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICByZXR1cm4gS2VybmVsLlNwZWNpYWxGb3Jtcy5saXN0KC4uLnJlc3VsdCk7XG4gIH0sXG5cbiAgdGFrZV93aGlsZTogZnVuY3Rpb24gKGNvbGxlY3Rpb24sIGZ1bikge1xuICAgIGxldCBjb3VudCA9IDA7XG5cbiAgICBmb3IgKGxldCBlbGVtIG9mIGNvbGxlY3Rpb24pIHtcbiAgICAgIGlmIChmdW4oZWxlbSkpIHtcbiAgICAgICAgY291bnQgPSBjb3VudCArIDE7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBicmVhaztcbiAgICAgIH1cbiAgICB9XG5cbiAgICByZXR1cm4gY29sbGVjdGlvbi5zbGljZSgwLCBjb3VudCk7XG4gIH0sXG5cbiAgdG9fbGlzdDogZnVuY3Rpb24gKGNvbGxlY3Rpb24pIHtcbiAgICByZXR1cm4gY29sbGVjdGlvbjtcbiAgfVxufTtcblxubGV0IFNwZWNpYWxGb3JtcyA9IHtcblxuICBfX0RJUl9fOiBmdW5jdGlvbiAoKSB7XG4gICAgaWYgKF9fZGlybmFtZSkge1xuICAgICAgcmV0dXJuIF9fZGlybmFtZTtcbiAgICB9XG5cbiAgICBpZiAoZG9jdW1lbnQuY3VycmVudFNjcmlwdCkge1xuICAgICAgcmV0dXJuIGRvY3VtZW50LmN1cnJlbnRTY3JpcHQuc3JjO1xuICAgIH1cblxuICAgIHJldHVybiBudWxsO1xuICB9LFxuXG4gIGF0b206IGZ1bmN0aW9uIChfdmFsdWUpIHtcbiAgICByZXR1cm4gU3ltYm9sLmZvcihfdmFsdWUpO1xuICB9LFxuXG4gIGxpc3Q6IGZ1bmN0aW9uICguLi5hcmdzKSB7XG4gICAgcmV0dXJuIE9iamVjdC5mcmVlemUoYXJncyk7XG4gIH0sXG5cbiAgYml0c3RyaW5nOiBmdW5jdGlvbiAoLi4uYXJncykge1xuICAgIHJldHVybiBuZXcgQml0U3RyaW5nKC4uLmFyZ3MpO1xuICB9LFxuXG4gIGJvdW5kOiBmdW5jdGlvbiAoX3Zhcikge1xuICAgIHJldHVybiBQYXR0ZXJucy5ib3VuZChfdmFyKTtcbiAgfSxcblxuICBfY2FzZTogZnVuY3Rpb24gKGNvbmRpdGlvbiwgY2xhdXNlcykge1xuICAgIHJldHVybiBQYXR0ZXJucy5kZWZtYXRjaCguLi5jbGF1c2VzKShjb25kaXRpb24pO1xuICB9LFxuXG4gIGNvbmQ6IGZ1bmN0aW9uIChjbGF1c2VzKSB7XG4gICAgZm9yIChsZXQgY2xhdXNlIG9mIGNsYXVzZXMpIHtcbiAgICAgIGlmIChjbGF1c2VbMF0pIHtcbiAgICAgICAgcmV0dXJuIGNsYXVzZVsxXSgpO1xuICAgICAgfVxuICAgIH1cblxuICAgIHRocm93IG5ldyBFcnJvcigpO1xuICB9LFxuXG4gIGZuOiBmdW5jdGlvbiAoY2xhdXNlcykge1xuICAgIHJldHVybiBQYXR0ZXJucy5kZWZtYXRjaChjbGF1c2VzKTtcbiAgfSxcblxuICBtYXA6IGZ1bmN0aW9uIChvYmopIHtcbiAgICByZXR1cm4gT2JqZWN0LmZyZWV6ZShvYmopO1xuICB9LFxuXG4gIG1hcF91cGRhdGU6IGZ1bmN0aW9uIChtYXAsIHZhbHVlcykge1xuICAgIHJldHVybiBPYmplY3QuZnJlZXplKE9iamVjdC5hc3NpZ24oT2JqZWN0LmNyZWF0ZShtYXAuY29uc3RydWN0b3IucHJvdG90eXBlKSwgbWFwLCB2YWx1ZXMpKTtcbiAgfSxcblxuICBfZm9yOiBmdW5jdGlvbiAoY29sbGVjdGlvbnMsIGZ1biwgZmlsdGVyID0gKCkgPT4gdHJ1ZSwgaW50byA9IFtdLCBwcmV2aW91c1ZhbHVlcyA9IFtdKSB7XG4gICAgbGV0IHBhdHRlcm4gPSBjb2xsZWN0aW9uc1swXVswXTtcbiAgICBsZXQgY29sbGVjdGlvbiA9IGNvbGxlY3Rpb25zWzBdWzFdO1xuXG4gICAgaWYgKGNvbGxlY3Rpb25zLmxlbmd0aCA9PT0gMSkge1xuXG4gICAgICBmb3IgKGxldCBlbGVtIG9mIGNvbGxlY3Rpb24pIHtcbiAgICAgICAgbGV0IHIgPSBQYXR0ZXJucy5tYXRjaF9ub190aHJvdyhwYXR0ZXJuLCBlbGVtKTtcbiAgICAgICAgbGV0IGFyZ3MgPSBwcmV2aW91c1ZhbHVlcy5jb25jYXQocik7XG5cbiAgICAgICAgaWYgKHIgJiYgZmlsdGVyLmFwcGx5KHRoaXMsIGFyZ3MpKSB7XG4gICAgICAgICAgaW50byA9IEVudW0uaW50byhbZnVuLmFwcGx5KHRoaXMsIGFyZ3MpXSwgaW50byk7XG4gICAgICAgIH1cbiAgICAgIH1cblxuICAgICAgcmV0dXJuIGludG87XG4gICAgfSBlbHNlIHtcbiAgICAgIGxldCBfaW50byA9IFtdO1xuXG4gICAgICBmb3IgKGxldCBlbGVtIG9mIGNvbGxlY3Rpb24pIHtcbiAgICAgICAgbGV0IHIgPSBQYXR0ZXJucy5tYXRjaF9ub190aHJvdyhwYXR0ZXJuLCBlbGVtKTtcbiAgICAgICAgaWYgKHIpIHtcbiAgICAgICAgICBfaW50byA9IEVudW0uaW50byh0aGlzLl9mb3IoY29sbGVjdGlvbnMuc2xpY2UoMSksIGZ1biwgZmlsdGVyLCBfaW50bywgcHJldmlvdXNWYWx1ZXMuY29uY2F0KHIpKSwgaW50byk7XG4gICAgICAgIH1cbiAgICAgIH1cblxuICAgICAgcmV0dXJuIF9pbnRvO1xuICAgIH1cbiAgfSxcblxuICByZWNlaXZlOiBmdW5jdGlvbiAocmVjZWl2ZV9mdW4sIHRpbWVvdXRfaW5fbXMgPSBudWxsLCB0aW1lb3V0X2ZuID0gdGltZSA9PiB0cnVlKSB7XG4gICAgaWYgKHRpbWVvdXRfaW5fbXMgPT0gbnVsbCB8fCB0aW1lb3V0X2luX21zID09PSBTeXN0ZW0uZm9yKCdpbmZpbml0eScpKSB7XG4gICAgICB3aGlsZSAodHJ1ZSkge1xuICAgICAgICBpZiAoc2VsZi5tYWlsYm94Lmxlbmd0aCAhPT0gMCkge1xuICAgICAgICAgIGxldCBtZXNzYWdlID0gc2VsZi5tYWlsYm94WzBdO1xuICAgICAgICAgIHNlbGYubWFpbGJveCA9IHNlbGYubWFpbGJveC5zbGljZSgxKTtcbiAgICAgICAgICByZXR1cm4gcmVjZWl2ZV9mdW4obWVzc2FnZSk7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9IGVsc2UgaWYgKHRpbWVvdXRfaW5fbXMgPT09IDApIHtcbiAgICAgIGlmIChzZWxmLm1haWxib3gubGVuZ3RoICE9PSAwKSB7XG4gICAgICAgIGxldCBtZXNzYWdlID0gc2VsZi5tYWlsYm94WzBdO1xuICAgICAgICBzZWxmLm1haWxib3ggPSBzZWxmLm1haWxib3guc2xpY2UoMSk7XG4gICAgICAgIHJldHVybiByZWNlaXZlX2Z1bihtZXNzYWdlKTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHJldHVybiBudWxsO1xuICAgICAgfVxuICAgIH0gZWxzZSB7XG4gICAgICBsZXQgbm93ID0gRGF0ZS5ub3coKTtcbiAgICAgIHdoaWxlIChEYXRlLm5vdygpIDwgbm93ICsgdGltZW91dF9pbl9tcykge1xuICAgICAgICBpZiAoc2VsZi5tYWlsYm94Lmxlbmd0aCAhPT0gMCkge1xuICAgICAgICAgIGxldCBtZXNzYWdlID0gc2VsZi5tYWlsYm94WzBdO1xuICAgICAgICAgIHNlbGYubWFpbGJveCA9IHNlbGYubWFpbGJveC5zbGljZSgxKTtcbiAgICAgICAgICByZXR1cm4gcmVjZWl2ZV9mdW4obWVzc2FnZSk7XG4gICAgICAgIH1cbiAgICAgIH1cblxuICAgICAgcmV0dXJuIHRpbWVvdXRfZm4odGltZW91dF9pbl9tcyk7XG4gICAgfVxuICB9LFxuXG4gIHR1cGxlOiBmdW5jdGlvbiAoLi4uYXJncykge1xuICAgIHJldHVybiBuZXcgVHVwbGUkMSguLi5hcmdzKTtcbiAgfSxcblxuICBfdHJ5OiBmdW5jdGlvbiAoZG9fZnVuLCByZXNjdWVfZnVuY3Rpb24sIGNhdGNoX2Z1biwgZWxzZV9mdW5jdGlvbiwgYWZ0ZXJfZnVuY3Rpb24pIHtcbiAgICBsZXQgcmVzdWx0ID0gbnVsbDtcblxuICAgIHRyeSB7XG4gICAgICByZXN1bHQgPSBkb19mdW4oKTtcbiAgICB9IGNhdGNoIChlKSB7XG4gICAgICBsZXQgZXhfcmVzdWx0ID0gbnVsbDtcblxuICAgICAgaWYgKHJlc2N1ZV9mdW5jdGlvbikge1xuICAgICAgICB0cnkge1xuICAgICAgICAgIGV4X3Jlc3VsdCA9IHJlc2N1ZV9mdW5jdGlvbihlKTtcbiAgICAgICAgICByZXR1cm4gZXhfcmVzdWx0O1xuICAgICAgICB9IGNhdGNoIChleCkge1xuICAgICAgICAgIGlmIChleCBpbnN0YW5jZW9mIFBhdHRlcm5zLk1hdGNoRXJyb3IpIHtcbiAgICAgICAgICAgIHRocm93IGV4O1xuICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgfVxuXG4gICAgICBpZiAoY2F0Y2hfZnVuKSB7XG4gICAgICAgIHRyeSB7XG4gICAgICAgICAgZXhfcmVzdWx0ID0gY2F0Y2hfZnVuKGUpO1xuICAgICAgICAgIHJldHVybiBleF9yZXN1bHQ7XG4gICAgICAgIH0gY2F0Y2ggKGV4KSB7XG4gICAgICAgICAgaWYgKGV4IGluc3RhbmNlb2YgUGF0dGVybnMuTWF0Y2hFcnJvcikge1xuICAgICAgICAgICAgdGhyb3cgZXg7XG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICB9XG5cbiAgICAgIHRocm93IGU7XG4gICAgfSBmaW5hbGx5IHtcbiAgICAgIGlmIChhZnRlcl9mdW5jdGlvbikge1xuICAgICAgICBhZnRlcl9mdW5jdGlvbigpO1xuICAgICAgfVxuICAgIH1cblxuICAgIGlmIChlbHNlX2Z1bmN0aW9uKSB7XG4gICAgICB0cnkge1xuICAgICAgICByZXR1cm4gZWxzZV9mdW5jdGlvbihyZXN1bHQpO1xuICAgICAgfSBjYXRjaCAoZXgpIHtcbiAgICAgICAgaWYgKGV4IGluc3RhbmNlb2YgUGF0dGVybnMuTWF0Y2hFcnJvcikge1xuICAgICAgICAgIHRocm93IG5ldyBFcnJvcignTm8gTWF0Y2ggRm91bmQgaW4gRWxzZScpO1xuICAgICAgICB9XG5cbiAgICAgICAgdGhyb3cgZXg7XG4gICAgICB9XG4gICAgfSBlbHNlIHtcbiAgICAgIHJldHVybiByZXN1bHQ7XG4gICAgfVxuICB9XG5cbn07XG5cbmZ1bmN0aW9uIHRvX3N0cmluZyQxKHR1cGxlKSB7XG4gIHJldHVybiB0dXBsZS50b1N0cmluZygpO1xufTtcblxuZnVuY3Rpb24gZGVsZXRlX2F0KHR1cGxlLCBpbmRleCkge1xuICBsZXQgbmV3X2xpc3QgPSBbXTtcblxuICBmb3IgKHZhciBpID0gMDsgaSA8IHR1cGxlLmNvdW50KCk7IGkrKykge1xuICAgIGlmIChpICE9PSBpbmRleCkge1xuICAgICAgbmV3X2xpc3QucHVzaCh0dXBsZS5nZXQoaSkpO1xuICAgIH1cbiAgfVxuXG4gIHJldHVybiBLZXJuZWwuU3BlY2lhbEZvcm1zLnR1cGxlLmFwcGx5KG51bGwsIG5ld19saXN0KTtcbn07XG5cbmZ1bmN0aW9uIGR1cGxpY2F0ZShkYXRhLCBzaXplKSB7XG4gIGxldCBhcnJheSA9IFtdO1xuXG4gIGZvciAodmFyIGkgPSBzaXplIC0gMTsgaSA+PSAwOyBpLS0pIHtcbiAgICBhcnJheS5wdXNoKGRhdGEpO1xuICB9XG5cbiAgcmV0dXJuIEtlcm5lbC5TcGVjaWFsRm9ybXMudHVwbGUuYXBwbHkobnVsbCwgYXJyYXkpO1xufTtcblxuZnVuY3Rpb24gaW5zZXJ0X2F0KHR1cGxlLCBpbmRleCwgdGVybSkge1xuICBsZXQgbmV3X3R1cGxlID0gW107XG5cbiAgZm9yICh2YXIgaSA9IDA7IGkgPD0gdHVwbGUuY291bnQoKTsgaSsrKSB7XG4gICAgaWYgKGkgPT09IGluZGV4KSB7XG4gICAgICBuZXdfdHVwbGUucHVzaCh0ZXJtKTtcbiAgICAgIGkrKztcbiAgICAgIG5ld190dXBsZS5wdXNoKHR1cGxlLmdldChpKSk7XG4gICAgfSBlbHNlIHtcbiAgICAgIG5ld190dXBsZS5wdXNoKHR1cGxlLmdldChpKSk7XG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIEtlcm5lbC5TcGVjaWFsRm9ybXMudHVwbGUuYXBwbHkobnVsbCwgbmV3X3R1cGxlKTtcbn07XG5cbmZ1bmN0aW9uIGZyb21fbGlzdChsaXN0KSB7XG4gIHJldHVybiBLZXJuZWwuU3BlY2lhbEZvcm1zLnR1cGxlLmFwcGx5KG51bGwsIGxpc3QpO1xufTtcblxuZnVuY3Rpb24gdG9fbGlzdCh0dXBsZSkge1xuICBsZXQgbmV3X2xpc3QgPSBbXTtcblxuICBmb3IgKHZhciBpID0gMDsgaSA8IHR1cGxlLmNvdW50KCk7IGkrKykge1xuICAgIG5ld19saXN0LnB1c2godHVwbGUuZ2V0KGkpKTtcbiAgfVxuXG4gIHJldHVybiBLZXJuZWwuU3BlY2lhbEZvcm1zLmxpc3QoLi4ubmV3X2xpc3QpO1xufTtcblxudmFyIFR1cGxlID0ge1xuICB0b19zdHJpbmc6IHRvX3N0cmluZyQxLFxuICBkZWxldGVfYXQsXG4gIGR1cGxpY2F0ZSxcbiAgaW5zZXJ0X2F0LFxuICBmcm9tX2xpc3QsXG4gIHRvX2xpc3Rcbn07XG5cbi8vaHR0cHM6Ly9naXRodWIuY29tL2FpcnBvcnR5aC9wcm90b21vcnBoaXNtXG5jbGFzcyBQcm90b2NvbCB7XG4gIGNvbnN0cnVjdG9yKHNwZWMpIHtcbiAgICB0aGlzLnJlZ2lzdHJ5ID0gbmV3IE1hcCgpO1xuICAgIHRoaXMuZmFsbGJhY2sgPSBudWxsO1xuXG4gICAgZm9yIChsZXQgZnVuTmFtZSBpbiBzcGVjKSB7XG4gICAgICB0aGlzW2Z1bk5hbWVdID0gY3JlYXRlRnVuKGZ1bk5hbWUpLmJpbmQodGhpcyk7XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gY3JlYXRlRnVuKGZ1bk5hbWUpIHtcblxuICAgICAgcmV0dXJuIGZ1bmN0aW9uICguLi5hcmdzKSB7XG4gICAgICAgIGxldCB0aGluZyA9IGFyZ3NbMF07XG4gICAgICAgIGxldCBmdW4gPSBudWxsO1xuXG4gICAgICAgIGlmIChOdW1iZXIuaXNJbnRlZ2VyKHRoaW5nKSAmJiB0aGlzLmhhc0ltcGxlbWVudGF0aW9uKEludGVnZXJUeXBlKSkge1xuICAgICAgICAgIGZ1biA9IHRoaXMucmVnaXN0cnkuZ2V0KEludGVnZXJUeXBlKVtmdW5OYW1lXTtcbiAgICAgICAgfSBlbHNlIGlmICh0eXBlb2YgdGhpbmcgPT09IFwibnVtYmVyXCIgJiYgIU51bWJlci5pc0ludGVnZXIodGhpbmcpICYmIHRoaXMuaGFzSW1wbGVtZW50YXRpb24oRmxvYXRUeXBlKSkge1xuICAgICAgICAgIGZ1biA9IHRoaXMucmVnaXN0cnkuZ2V0KEZsb2F0VHlwZSlbZnVuTmFtZV07XG4gICAgICAgIH0gZWxzZSBpZiAodGhpcy5oYXNJbXBsZW1lbnRhdGlvbih0aGluZykpIHtcbiAgICAgICAgICBmdW4gPSB0aGlzLnJlZ2lzdHJ5LmdldCh0aGluZy5jb25zdHJ1Y3RvcilbZnVuTmFtZV07XG4gICAgICAgIH0gZWxzZSBpZiAodGhpcy5mYWxsYmFjaykge1xuICAgICAgICAgIGZ1biA9IHRoaXMuZmFsbGJhY2tbZnVuTmFtZV07XG4gICAgICAgIH1cblxuICAgICAgICBpZiAoZnVuICE9IG51bGwpIHtcbiAgICAgICAgICBsZXQgcmV0dmFsID0gZnVuLmFwcGx5KHRoaXMsIGFyZ3MpO1xuICAgICAgICAgIHJldHVybiByZXR2YWw7XG4gICAgICAgIH1cblxuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoXCJObyBpbXBsZW1lbnRhdGlvbiBmb3VuZCBmb3IgXCIgKyB0aGluZyk7XG4gICAgICB9O1xuICAgIH1cbiAgfVxuXG4gIGltcGxlbWVudGF0aW9uKHR5cGUsIGltcGxlbWVudGF0aW9uKSB7XG4gICAgaWYgKHR5cGUgPT09IG51bGwpIHtcbiAgICAgIHRoaXMuZmFsbGJhY2sgPSBpbXBsZW1lbnRhdGlvbjtcbiAgICB9IGVsc2Uge1xuICAgICAgdGhpcy5yZWdpc3RyeS5zZXQodHlwZSwgaW1wbGVtZW50YXRpb24pO1xuICAgIH1cbiAgfVxuXG4gIGhhc0ltcGxlbWVudGF0aW9uKHRoaW5nKSB7XG4gICAgcmV0dXJuIHRoaXMucmVnaXN0cnkuaGFzKHRoaW5nLmNvbnN0cnVjdG9yKTtcbiAgfVxufVxuXG5mdW5jdGlvbiB0bChsaXN0KSB7XG4gIHJldHVybiBTcGVjaWFsRm9ybXMubGlzdCguLi5saXN0LnNsaWNlKDEpKTtcbn1cblxuZnVuY3Rpb24gaGQobGlzdCkge1xuICByZXR1cm4gbGlzdFswXTtcbn1cblxuZnVuY3Rpb24gaXNfbmlsKHgpIHtcbiAgcmV0dXJuIHggPT09IG51bGw7XG59XG5cbmZ1bmN0aW9uIGlzX2F0b20oeCkge1xuICByZXR1cm4gdHlwZW9mIHggPT09ICdzeW1ib2wnO1xufVxuXG5mdW5jdGlvbiBpc19iaW5hcnkoeCkge1xuICByZXR1cm4gdHlwZW9mIHggPT09ICdzdHJpbmcnIHx8IHggaW5zdGFuY2VvZiBTdHJpbmc7XG59XG5cbmZ1bmN0aW9uIGlzX2Jvb2xlYW4oeCkge1xuICByZXR1cm4gdHlwZW9mIHggPT09ICdib29sZWFuJyB8fCB4IGluc3RhbmNlb2YgQm9vbGVhbjtcbn1cblxuZnVuY3Rpb24gaXNfZnVuY3Rpb24oeCwgYXJpdHkgPSAtMSkge1xuICByZXR1cm4gdHlwZW9mIHggPT09ICdmdW5jdGlvbicgfHwgeCBpbnN0YW5jZW9mIEZ1bmN0aW9uO1xufVxuXG5mdW5jdGlvbiBpc19mbG9hdCh4KSB7XG4gIHJldHVybiBpc19udW1iZXIoeCkgJiYgIU51bWJlci5pc0ludGVnZXIoeCk7XG59XG5cbmZ1bmN0aW9uIGlzX2ludGVnZXIoeCkge1xuICByZXR1cm4gTnVtYmVyLmlzSW50ZWdlcih4KTtcbn1cblxuZnVuY3Rpb24gaXNfbGlzdCh4KSB7XG4gIHJldHVybiB4IGluc3RhbmNlb2YgQXJyYXk7XG59XG5cbmZ1bmN0aW9uIGlzX21hcCh4KSB7XG4gIHJldHVybiB0eXBlb2YgeCA9PT0gJ29iamVjdCcgfHwgeCBpbnN0YW5jZW9mIE9iamVjdDtcbn1cblxuZnVuY3Rpb24gaXNfbnVtYmVyKHgpIHtcbiAgcmV0dXJuIHR5cGVvZiB4ID09PSAnbnVtYmVyJztcbn1cblxuZnVuY3Rpb24gaXNfdHVwbGUoeCkge1xuICByZXR1cm4geCBpbnN0YW5jZW9mIFR1cGxlJDE7XG59XG5cbmZ1bmN0aW9uIGxlbmd0aCh4KSB7XG4gIHJldHVybiB4Lmxlbmd0aDtcbn1cblxuZnVuY3Rpb24gaXNfcGlkKHgpIHtcbiAgcmV0dXJuIHggaW5zdGFuY2VvZiBQSUQ7XG59XG5cbmZ1bmN0aW9uIGlzX3BvcnQoeCkge1xuICByZXR1cm4gZmFsc2U7XG59XG5cbmZ1bmN0aW9uIGlzX3JlZmVyZW5jZSh4KSB7XG4gIHJldHVybiBmYWxzZTtcbn1cblxuZnVuY3Rpb24gaXNfYml0c3RyaW5nKHgpIHtcbiAgcmV0dXJuIGlzX2JpbmFyeSh4KSB8fCB4IGluc3RhbmNlb2YgQml0U3RyaW5nO1xufVxuXG5mdW5jdGlvbiBfX2luX18obGVmdCwgcmlnaHQpIHtcbiAgZm9yIChsZXQgeCBvZiByaWdodCkge1xuICAgIGlmIChtYXRjaF9fcW1hcmtfXyhsZWZ0LCB4KSkge1xuICAgICAgcmV0dXJuIHRydWU7XG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIGZhbHNlO1xufVxuXG5mdW5jdGlvbiBhYnMobnVtYmVyKSB7XG4gIHJldHVybiBNYXRoLmFicyhudW1iZXIpO1xufVxuXG5mdW5jdGlvbiByb3VuZChudW1iZXIpIHtcbiAgcmV0dXJuIE1hdGgucm91bmQobnVtYmVyKTtcbn1cblxuZnVuY3Rpb24gZWxlbSh0dXBsZSwgaW5kZXgpIHtcbiAgaWYgKGlzX2xpc3QodHVwbGUpKSB7XG4gICAgcmV0dXJuIHR1cGxlW2luZGV4XTtcbiAgfVxuXG4gIHJldHVybiB0dXBsZS5nZXQoaW5kZXgpO1xufVxuXG5mdW5jdGlvbiByZW0obGVmdCwgcmlnaHQpIHtcbiAgcmV0dXJuIGxlZnQgJSByaWdodDtcbn1cblxuZnVuY3Rpb24gZGl2KGxlZnQsIHJpZ2h0KSB7XG4gIHJldHVybiBsZWZ0IC8gcmlnaHQ7XG59XG5cbmZ1bmN0aW9uIGFuZChsZWZ0LCByaWdodCkge1xuICByZXR1cm4gbGVmdCAmJiByaWdodDtcbn1cblxuZnVuY3Rpb24gb3IobGVmdCwgcmlnaHQpIHtcbiAgcmV0dXJuIGxlZnQgfHwgcmlnaHQ7XG59XG5cbmZ1bmN0aW9uIG5vdChhcmcpIHtcbiAgcmV0dXJuICFhcmc7XG59XG5cbmZ1bmN0aW9uIGFwcGx5KC4uLmFyZ3MpIHtcbiAgaWYgKGFyZ3MubGVuZ3RoID09PSAzKSB7XG4gICAgbGV0IG1vZCA9IGFyZ3NbMF07XG4gICAgbGV0IGZ1bmMgPSBhcmdzWzFdO1xuICAgIGxldCBmdW5jX2FyZ3MgPSBhcmdzWzJdO1xuICAgIHJldHVybiBtb2RbZnVuY10uYXBwbHkobnVsbCwgZnVuY19hcmdzKTtcbiAgfSBlbHNlIHtcbiAgICBsZXQgZnVuYyA9IGFyZ3NbMF07XG4gICAgbGV0IGZ1bmNfYXJncyA9IGFyZ3NbMV07XG5cbiAgICByZXR1cm4gZnVuYy5hcHBseShudWxsLCBmdW5jX2FyZ3MpO1xuICB9XG59XG5cbmZ1bmN0aW9uIHRvX3N0cmluZyhhcmcpIHtcbiAgaWYgKGlzX3R1cGxlKGFyZykpIHtcbiAgICByZXR1cm4gVHVwbGUudG9fc3RyaW5nKGFyZyk7XG4gIH1cblxuICByZXR1cm4gYXJnLnRvU3RyaW5nKCk7XG59XG5cbmZ1bmN0aW9uIG1hdGNoX19xbWFya19fKHBhdHRlcm4sIGV4cHIsIGd1YXJkID0gKCkgPT4gdHJ1ZSkge1xuICByZXR1cm4gUGF0dGVybnMubWF0Y2hfbm9fdGhyb3cocGF0dGVybiwgZXhwciwgZ3VhcmQpICE9IG51bGw7XG59XG5cbmZ1bmN0aW9uIGRlZnN0cnVjdChkZWZhdWx0cykge1xuICByZXR1cm4gY2xhc3Mge1xuICAgIGNvbnN0cnVjdG9yKHVwZGF0ZSA9IHt9KSB7XG4gICAgICBsZXQgdGhlX3ZhbHVlcyA9IE9iamVjdC5hc3NpZ24oZGVmYXVsdHMsIHVwZGF0ZSk7XG4gICAgICBPYmplY3QuYXNzaWduKHRoaXMsIHRoZV92YWx1ZXMpO1xuICAgIH1cblxuICAgIHN0YXRpYyBjcmVhdGUodXBkYXRlcyA9IHt9KSB7XG4gICAgICBsZXQgeCA9IG5ldyB0aGlzKHVwZGF0ZXMpO1xuICAgICAgcmV0dXJuIE9iamVjdC5mcmVlemUoeCk7XG4gICAgfVxuICB9O1xufVxuXG5mdW5jdGlvbiBkZWZwcm90b2NvbChzcGVjKSB7XG4gIHJldHVybiBuZXcgUHJvdG9jb2woc3BlYyk7XG59XG5cbmZ1bmN0aW9uIGRlZmltcGwocHJvdG9jb2wsIHR5cGUsIGltcGwpIHtcbiAgcHJvdG9jb2wuaW1wbGVtZW50YXRpb24odHlwZSwgaW1wbCk7XG59XG5cbnZhciBLZXJuZWwgPSB7XG4gIFNwZWNpYWxGb3JtcyxcbiAgdGwsXG4gIGhkLFxuICBpc19uaWwsXG4gIGlzX2F0b20sXG4gIGlzX2JpbmFyeSxcbiAgaXNfYm9vbGVhbixcbiAgaXNfZnVuY3Rpb24sXG4gIGlzX2Zsb2F0LFxuICBpc19pbnRlZ2VyLFxuICBpc19saXN0LFxuICBpc19tYXAsXG4gIGlzX251bWJlcixcbiAgaXNfdHVwbGUsXG4gIGxlbmd0aCxcbiAgaXNfcGlkLFxuICBpc19wb3J0LFxuICBpc19yZWZlcmVuY2UsXG4gIGlzX2JpdHN0cmluZyxcbiAgaW46IF9faW5fXyxcbiAgYWJzLFxuICByb3VuZCxcbiAgZWxlbSxcbiAgcmVtLFxuICBkaXYsXG4gIGFuZCxcbiAgb3IsXG4gIG5vdCxcbiAgYXBwbHksXG4gIHRvX3N0cmluZyxcbiAgbWF0Y2hfX3FtYXJrX18sXG4gIGRlZnN0cnVjdCxcbiAgZGVmcHJvdG9jb2wsXG4gIGRlZmltcGxcbn07XG5cbmxldCBBdG9tID0ge307XG5cbkF0b20udG9fc3RyaW5nID0gZnVuY3Rpb24gKGF0b20pIHtcbiAgcmV0dXJuIFN5bWJvbC5rZXlGb3IoYXRvbSk7XG59O1xuXG5BdG9tLnRvX2NoYXJfbGlzdCA9IGZ1bmN0aW9uIChhdG9tKSB7XG4gIHJldHVybiBBdG9tLnRvX3N0cmluZyhhdG9tKS5zcGxpdCgnJyk7XG59O1xuXG5sZXQgSW50ZWdlciA9IHtcblxuICBpc19ldmVuOiBmdW5jdGlvbiAobikge1xuICAgIHJldHVybiBuICUgMiA9PT0gMDtcbiAgfSxcblxuICBpc19vZGQ6IGZ1bmN0aW9uIChuKSB7XG4gICAgcmV0dXJuIG4gJSAyICE9PSAwO1xuICB9LFxuXG4gIHBhcnNlOiBmdW5jdGlvbiAoYmluKSB7XG4gICAgbGV0IHJlc3VsdCA9IHBhcnNlSW50KGJpbik7XG5cbiAgICBpZiAoaXNOYU4ocmVzdWx0KSkge1xuICAgICAgcmV0dXJuIEtlcm5lbC5TcGVjaWFsRm9ybXMuYXRvbShcImVycm9yXCIpO1xuICAgIH1cblxuICAgIGxldCBpbmRleE9mRG90ID0gYmluLmluZGV4T2YoXCIuXCIpO1xuXG4gICAgaWYgKGluZGV4T2ZEb3QgPj0gMCkge1xuICAgICAgcmV0dXJuIEtlcm5lbC5TcGVjaWFsRm9ybXMudHVwbGUocmVzdWx0LCBiaW4uc3Vic3RyaW5nKGluZGV4T2ZEb3QpKTtcbiAgICB9XG5cbiAgICByZXR1cm4gS2VybmVsLlNwZWNpYWxGb3Jtcy50dXBsZShyZXN1bHQsIFwiXCIpO1xuICB9LFxuXG4gIHRvX2NoYXJfbGlzdDogZnVuY3Rpb24gKG51bWJlciwgYmFzZSA9IDEwKSB7XG4gICAgcmV0dXJuIG51bWJlci50b1N0cmluZyhiYXNlKS5zcGxpdChcIlwiKTtcbiAgfSxcblxuICB0b19zdHJpbmc6IGZ1bmN0aW9uIChudW1iZXIsIGJhc2UgPSAxMCkge1xuICAgIHJldHVybiBudW1iZXIudG9TdHJpbmcoYmFzZSk7XG4gIH1cbn07XG5cbmxldCBDaGFycyQxID0gS2VybmVsLmRlZnByb3RvY29sKHtcbiAgdG9fc3RyaW5nOiBmdW5jdGlvbiAodGhpbmcpIHt9XG59KTtcblxuS2VybmVsLmRlZmltcGwoQ2hhcnMkMSwgQml0U3RyaW5nLCB7XG4gIHRvX3N0cmluZzogZnVuY3Rpb24gKHRoaW5nKSB7XG4gICAgaWYgKEtlcm5lbC5pc19iaW5hcnkodGhpbmcpKSB7XG4gICAgICByZXR1cm4gdGhpbmc7XG4gICAgfVxuXG4gICAgcmV0dXJuIHRoaW5nLnRvU3RyaW5nKCk7XG4gIH1cbn0pO1xuXG5LZXJuZWwuZGVmaW1wbChDaGFycyQxLCBTeW1ib2wsIHtcbiAgdG9fc3RyaW5nOiBmdW5jdGlvbiAodGhpbmcpIHtcbiAgICBpZiAobmlsKSB7XG4gICAgICByZXR1cm4gXCJcIjtcbiAgICB9XG5cbiAgICByZXR1cm4gQXRvbS50b19zdHJpbmcodGhpbmcpO1xuICB9XG59KTtcblxuS2VybmVsLmRlZmltcGwoQ2hhcnMkMSwgSW50ZWdlclR5cGUsIHtcbiAgdG9fc3RyaW5nOiBmdW5jdGlvbiAodGhpbmcpIHtcbiAgICByZXR1cm4gSW50ZWdlci50b19zdHJpbmcodGhpbmcpO1xuICB9XG59KTtcblxuS2VybmVsLmRlZmltcGwoQ2hhcnMkMSwgRmxvYXRUeXBlLCB7XG4gIHRvX3N0cmluZzogZnVuY3Rpb24gKHRoaW5nKSB7XG4gICAgcmV0dXJuIHRoaW5nLnRvU3RyaW5nO1xuICB9XG59KTtcblxuS2VybmVsLmRlZmltcGwoQ2hhcnMkMSwgQXJyYXksIHtcbiAgdG9fc3RyaW5nOiBmdW5jdGlvbiAodGhpbmcpIHtcbiAgICByZXR1cm4gdGhpbmcudG9TdHJpbmcoKTtcbiAgfVxufSk7XG5cbktlcm5lbC5kZWZpbXBsKENoYXJzJDEsIFR1cGxlJDEsIHtcbiAgdG9fc3RyaW5nOiBmdW5jdGlvbiAodGhpbmcpIHtcbiAgICByZXR1cm4gVHVwbGUudG9fc3RyaW5nKHRoaW5nKTtcbiAgfVxufSk7XG5cbktlcm5lbC5kZWZpbXBsKENoYXJzJDEsIG51bGwsIHtcbiAgdG9fc3RyaW5nOiBmdW5jdGlvbiAodGhpbmcpIHtcbiAgICByZXR1cm4gdGhpbmcudG9TdHJpbmcoKTtcbiAgfVxufSk7XG5cbmZ1bmN0aW9uIHRvX2F0b20oc3RyaW5nKSB7XG4gIHJldHVybiBTeW1ib2wuZm9yKHN0cmluZyk7XG59XG5cbmZ1bmN0aW9uIHRvX2V4aXN0aW5nX2F0b20oc3RyaW5nKSB7XG4gIHJldHVybiBTeW1ib2wuZm9yKHN0cmluZyk7XG59XG5cbmZ1bmN0aW9uIHRvX2NoYXJfbGlzdChzdHJpbmcpIHtcbiAgcmV0dXJuIHN0cmluZy5zcGxpdCgnJyk7XG59XG5cbmZ1bmN0aW9uIHRvX2Zsb2F0KHN0cmluZykge1xuICByZXR1cm4gcGFyc2VGbG9hdChzdHJpbmcpO1xufVxuXG5mdW5jdGlvbiB0b19pbnRlZ2VyKHN0cmluZywgYmFzZSA9IDEwKSB7XG4gIHJldHVybiBwYXJzZUludChzdHJpbmcsIGJhc2UpO1xufVxuXG5mdW5jdGlvbiB1cGNhc2UoYmluYXJ5KSB7XG4gIHJldHVybiBiaW5hcnkudG9VcHBlckNhc2UoKTtcbn1cblxuZnVuY3Rpb24gZG93bmNhc2UoYmluYXJ5KSB7XG4gIHJldHVybiBiaW5hcnkudG9Mb3dlckNhc2UoKTtcbn1cblxuZnVuY3Rpb24gYXQoc3RyaW5nLCBwb3NpdGlvbikge1xuICBpZiAocG9zaXRpb24gPiBzdHJpbmcubGVuZ3RoIC0gMSkge1xuICAgIHJldHVybiBudWxsO1xuICB9XG5cbiAgcmV0dXJuIHN0cmluZ1twb3NpdGlvbl07XG59XG5cbmZ1bmN0aW9uIGNhcGl0YWxpemUoc3RyaW5nKSB7XG4gIGxldCByZXR1cm5TdHJpbmcgPSAnJztcblxuICBmb3IgKGxldCBpID0gMDsgaSA8IHN0cmluZy5sZW5ndGg7IGkrKykge1xuICAgIGlmIChpID09PSAwKSB7XG4gICAgICByZXR1cm5TdHJpbmcgPSByZXR1cm5TdHJpbmcgKyBzdHJpbmdbaV0udG9VcHBlckNhc2UoKTtcbiAgICB9IGVsc2Uge1xuICAgICAgcmV0dXJuU3RyaW5nID0gcmV0dXJuU3RyaW5nICsgc3RyaW5nW2ldLnRvTG93ZXJDYXNlKCk7XG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIHJldHVyblN0cmluZztcbn1cblxuZnVuY3Rpb24gY29kZXBvaW50cyhzdHJpbmcpIHtcbiAgcmV0dXJuIHRvX2NoYXJfbGlzdChzdHJpbmcpLm1hcChmdW5jdGlvbiAoYykge1xuICAgIHJldHVybiBjLmNvZGVQb2ludEF0KDApO1xuICB9KTtcbn1cblxuZnVuY3Rpb24gY29udGFpbnNfX3FtX18oc3RyaW5nLCBjb250YWlucykge1xuICBpZiAoQXJyYXkuaXNBcnJheShjb250YWlucykpIHtcbiAgICByZXR1cm4gY29udGFpbnMuc29tZShmdW5jdGlvbiAocykge1xuICAgICAgcmV0dXJuIHN0cmluZy5pbmRleE9mKHMpID4gLTE7XG4gICAgfSk7XG4gIH1cblxuICByZXR1cm4gc3RyaW5nLmluZGV4T2YoY29udGFpbnMpID4gLTE7XG59XG5cbmZ1bmN0aW9uIGR1cGxpY2F0ZSQxKHN1YmplY3QsIG4pIHtcbiAgcmV0dXJuIHN1YmplY3QucmVwZWF0KG4pO1xufVxuXG5mdW5jdGlvbiBlbmRzX3dpdGhfX3FtX18oc3RyaW5nLCBzdWZmaXhlcykge1xuICBpZiAoQXJyYXkuaXNBcnJheShzdWZmaXhlcykpIHtcbiAgICByZXR1cm4gc3VmZml4ZXMuc29tZShmdW5jdGlvbiAocykge1xuICAgICAgcmV0dXJuIHN0cmluZy5lbmRzV2l0aChzKTtcbiAgICB9KTtcbiAgfVxuXG4gIHJldHVybiBzdHJpbmcuZW5kc1dpdGgoc3VmZml4ZXMpO1xufVxuXG5mdW5jdGlvbiBmaXJzdChzdHJpbmcpIHtcbiAgaWYgKCFzdHJpbmcpIHtcbiAgICByZXR1cm4gbnVsbDtcbiAgfVxuXG4gIHJldHVybiBzdHJpbmdbMF07XG59XG5cbmZ1bmN0aW9uIGdyYXBoZW1lcyhzdHJpbmcpIHtcbiAgcmV0dXJuIHN0cmluZy5zcGxpdCgnJyk7XG59XG5cbmZ1bmN0aW9uIGxhc3Qoc3RyaW5nKSB7XG4gIGlmICghc3RyaW5nKSB7XG4gICAgcmV0dXJuIG51bGw7XG4gIH1cblxuICByZXR1cm4gc3RyaW5nW3N0cmluZy5sZW5ndGggLSAxXTtcbn1cblxuZnVuY3Rpb24gbGVuZ3RoJDEoc3RyaW5nKSB7XG4gIHJldHVybiBzdHJpbmcubGVuZ3RoO1xufVxuXG5mdW5jdGlvbiBtYXRjaF9fcW1fXyhzdHJpbmcsIHJlZ2V4KSB7XG4gIHJldHVybiBzdHJpbmcubWF0Y2gocmVnZXgpICE9IG51bGw7XG59XG5cbmZ1bmN0aW9uIG5leHRfY29kZXBvaW50KHN0cmluZykge1xuICBpZiAoIXN0cmluZyB8fCBzdHJpbmcgPT09ICcnKSB7XG4gICAgcmV0dXJuIG51bGw7XG4gIH1cblxuICByZXR1cm4gS2VybmVsLlNwZWNpYWxGb3Jtcy50dXBsZShzdHJpbmdbMF0uY29kZVBvaW50QXQoMCksIHN0cmluZy5zdWJzdHIoMSkpO1xufVxuXG5mdW5jdGlvbiBuZXh0X2dyYXBoZW1lKHN0cmluZykge1xuICBpZiAoIXN0cmluZyB8fCBzdHJpbmcgPT09ICcnKSB7XG4gICAgcmV0dXJuIG51bGw7XG4gIH1cblxuICByZXR1cm4gS2VybmVsLlNwZWNpYWxGb3Jtcy50dXBsZShzdHJpbmdbMF0sIHN0cmluZy5zdWJzdHIoMSkpO1xufVxuXG5mdW5jdGlvbiByZXZlcnNlKHN0cmluZykge1xuICBsZXQgcmV0dXJuVmFsdWUgPSAnJztcblxuICBmb3IgKHZhciBpID0gc3RyaW5nLmxlbmd0aCAtIDE7IGkgPj0gMDsgaS0tKSB7XG4gICAgcmV0dXJuVmFsdWUgPSByZXR1cm5WYWx1ZSArIHN0cmluZ1tpXTtcbiAgfTtcblxuICByZXR1cm4gcmV0dXJuVmFsdWU7XG59XG5cbmZ1bmN0aW9uIHNwbGl0KHN0cmluZykge1xuICByZXR1cm4gc3RyaW5nLnNwbGl0KCk7XG59XG5cbmZ1bmN0aW9uIHN0YXJ0c193aXRoX19xbV9fKHN0cmluZywgcHJlZml4ZXMpIHtcbiAgaWYgKEFycmF5LmlzQXJyYXkocHJlZml4ZXMpKSB7XG4gICAgcmV0dXJuIHByZWZpeGVzLnNvbWUoZnVuY3Rpb24gKHMpIHtcbiAgICAgIHJldHVybiBzdHJpbmcuc3RhcnRzV2l0aChzKTtcbiAgICB9KTtcbiAgfVxuXG4gIHJldHVybiBzdHJpbmcuc3RhcnRzV2l0aChwcmVmaXhlcyk7XG59XG5cbmZ1bmN0aW9uIHZhbGlkX2NoYXJhY3Rlcl9fcW1fXyhjb2RlcG9pbnQpIHtcbiAgdHJ5IHtcbiAgICByZXR1cm4gU3RyaW5nLmZyb21Db2RlUG9pbnQoY29kZXBvaW50KSAhPSBudWxsO1xuICB9IGNhdGNoIChlKSB7XG4gICAgcmV0dXJuIGZhbHNlO1xuICB9XG59XG5cbnZhciBTdHJpbmckMSA9IHtcbiAgYXQsXG4gIGNhcGl0YWxpemUsXG4gIGNvZGVwb2ludHMsXG4gIGNvbnRhaW5zX19xbV9fLFxuICBkb3duY2FzZSxcbiAgZHVwbGljYXRlOiBkdXBsaWNhdGUkMSxcbiAgZW5kc193aXRoX19xbV9fLFxuICBmaXJzdCxcbiAgZ3JhcGhlbWVzLFxuICBsYXN0LFxuICBsZW5ndGg6IGxlbmd0aCQxLFxuICBtYXRjaF9fcW1fXyxcbiAgbmV4dF9jb2RlcG9pbnQsXG4gIG5leHRfZ3JhcGhlbWUsXG4gIHJldmVyc2UsXG4gIHNwbGl0LFxuICBzdGFydHNfd2l0aF9fcW1fXyxcbiAgdG9fYXRvbSxcbiAgdG9fY2hhcl9saXN0LFxuICB0b19leGlzdGluZ19hdG9tLFxuICB0b19mbG9hdCxcbiAgdG9faW50ZWdlcixcbiAgdXBjYXNlLFxuICB2YWxpZF9jaGFyYWN0ZXJfX3FtX18sXG4gIENoYXJzOiBDaGFycyQxXG59O1xuXG5sZXQgQ2hhcnMgPSBLZXJuZWwuZGVmcHJvdG9jb2woe1xuICB0b19jaGFyX2xpc3Q6IGZ1bmN0aW9uICh0aGluZykge31cbn0pO1xuXG5LZXJuZWwuZGVmaW1wbChDaGFycywgQml0U3RyaW5nLCB7XG4gIHRvX2NoYXJfbGlzdDogZnVuY3Rpb24gKHRoaW5nKSB7XG4gICAgaWYgKEtlcm5lbC5pc19iaW5hcnkodGhpbmcpKSB7XG4gICAgICByZXR1cm4gU3RyaW5nJDEudG9fY2hhcl9saXN0KHRoaW5nKTtcbiAgICB9XG5cbiAgICByZXR1cm4gdGhpbmcudG9TdHJpbmcoKTtcbiAgfVxufSk7XG5cbktlcm5lbC5kZWZpbXBsKENoYXJzLCBTeW1ib2wsIHtcbiAgdG9fY2hhcl9saXN0OiBmdW5jdGlvbiAodGhpbmcpIHtcbiAgICByZXR1cm4gQXRvbS50b19jaGFyX2xpc3QodGhpbmcpO1xuICB9XG59KTtcblxuS2VybmVsLmRlZmltcGwoQ2hhcnMsIEludGVnZXJUeXBlLCB7XG4gIHRvX2NoYXJfbGlzdDogZnVuY3Rpb24gKHRoaW5nKSB7XG4gICAgcmV0dXJuIEludGVnZXIudG9fY2hhcl9saXN0KHRoaW5nKTtcbiAgfVxufSk7XG5cbktlcm5lbC5kZWZpbXBsKENoYXJzLCBBcnJheSwge1xuICB0b19jaGFyX2xpc3Q6IGZ1bmN0aW9uICh0aGluZykge1xuICAgIHJldHVybiB0aGluZztcbiAgfVxufSk7XG5cbmxldCBMaXN0ID0ge307XG5cbkxpc3QuQ2hhcnMgPSBDaGFycztcblxuTGlzdC5kZWxldGUgPSBmdW5jdGlvbiAobGlzdCwgaXRlbSkge1xuICBsZXQgbmV3X3ZhbHVlID0gW107XG4gIGxldCB2YWx1ZV9mb3VuZCA9IGZhbHNlO1xuXG4gIGZvciAobGV0IHggb2YgbGlzdCkge1xuICAgIGlmICh4ID09PSBpdGVtICYmIHZhbHVlX2ZvdW5kICE9PSBmYWxzZSkge1xuICAgICAgbmV3X3ZhbHVlLnB1c2goeCk7XG4gICAgICB2YWx1ZV9mb3VuZCA9IHRydWU7XG4gICAgfSBlbHNlIGlmICh4ICE9PSBpdGVtKSB7XG4gICAgICBuZXdfdmFsdWUucHVzaCh4KTtcbiAgICB9XG4gIH1cblxuICByZXR1cm4gS2VybmVsLlNwZWNpYWxGb3Jtcy5saXN0KC4uLm5ld192YWx1ZSk7XG59O1xuXG5MaXN0LmRlbGV0ZV9hdCA9IGZ1bmN0aW9uIChsaXN0LCBpbmRleCkge1xuICBsZXQgbmV3X3ZhbHVlID0gW107XG5cbiAgZm9yIChsZXQgaSA9IDA7IGkgPCBsaXN0Lmxlbmd0aDsgaSsrKSB7XG4gICAgaWYgKGkgIT09IGluZGV4KSB7XG4gICAgICBuZXdfdmFsdWUucHVzaChsaXN0W2ldKTtcbiAgICB9XG4gIH1cblxuICByZXR1cm4gS2VybmVsLlNwZWNpYWxGb3Jtcy5saXN0KC4uLm5ld192YWx1ZSk7XG59O1xuXG5MaXN0LmR1cGxpY2F0ZSA9IGZ1bmN0aW9uIChlbGVtLCBuKSB7XG4gIGxldCBuZXdfdmFsdWUgPSBbXTtcblxuICBmb3IgKHZhciBpID0gMDsgaSA8IG47IGkrKykge1xuICAgIG5ld192YWx1ZS5wdXNoKGVsZW0pO1xuICB9XG5cbiAgcmV0dXJuIEtlcm5lbC5TcGVjaWFsRm9ybXMubGlzdCguLi5uZXdfdmFsdWUpO1xufTtcblxuTGlzdC5maXJzdCA9IGZ1bmN0aW9uIChsaXN0KSB7XG4gIHJldHVybiBsaXN0WzBdO1xufTtcblxuTGlzdC5mbGF0dGVuID0gZnVuY3Rpb24gKGxpc3QsIHRhaWwgPSBLZXJuZWwuU3BlY2lhbEZvcm1zLmxpc3QoKSkge1xuICBsZXQgbmV3X3ZhbHVlID0gW107XG5cbiAgZm9yIChsZXQgeCBvZiBsaXN0KSB7XG4gICAgaWYgKEtlcm5lbC5pc19saXN0KHgpKSB7XG4gICAgICBuZXdfdmFsdWUgPSBuZXdfdmFsdWUuY29uY2F0KExpc3QuZmxhdHRlbih4KSk7XG4gICAgfSBlbHNlIHtcbiAgICAgIG5ld192YWx1ZS5wdXNoKHgpO1xuICAgIH1cbiAgfVxuXG4gIG5ld192YWx1ZSA9IG5ld192YWx1ZS5jb25jYXQodGFpbCk7XG5cbiAgcmV0dXJuIEtlcm5lbC5TcGVjaWFsRm9ybXMubGlzdCguLi5uZXdfdmFsdWUpO1xufTtcblxuTGlzdC5mb2xkbCA9IGZ1bmN0aW9uIChsaXN0LCBhY2MsIGZ1bmMpIHtcbiAgcmV0dXJuIGxpc3QucmVkdWNlKGZ1bmMsIGFjYyk7XG59O1xuXG5MaXN0LmZvbGRyID0gZnVuY3Rpb24gKGxpc3QsIGFjYywgZnVuYykge1xuICBsZXQgbmV3X2FjYyA9IGFjYztcblxuICBmb3IgKHZhciBpID0gbGlzdC5sZW5ndGggLSAxOyBpID49IDA7IGktLSkge1xuICAgIG5ld19hY2MgPSBmdW5jKGxpc3RbaV0sIG5ld19hY2MpO1xuICB9XG5cbiAgcmV0dXJuIG5ld19hY2M7XG59O1xuXG5MaXN0Lmluc2VydF9hdCA9IGZ1bmN0aW9uIChsaXN0LCBpbmRleCwgdmFsdWUpIHtcbiAgbGV0IG5ld192YWx1ZSA9IFtdO1xuXG4gIGZvciAobGV0IGkgPSAwOyBpIDwgbGlzdC5sZW5ndGg7IGkrKykge1xuICAgIGlmIChpID09PSBpbmRleCkge1xuICAgICAgbmV3X3ZhbHVlLnB1c2godmFsdWUpO1xuICAgICAgbmV3X3ZhbHVlLnB1c2gobGlzdFtpXSk7XG4gICAgfSBlbHNlIHtcbiAgICAgIG5ld192YWx1ZS5wdXNoKGxpc3RbaV0pO1xuICAgIH1cbiAgfVxuXG4gIHJldHVybiBLZXJuZWwuU3BlY2lhbEZvcm1zLmxpc3QoLi4ubmV3X3ZhbHVlKTtcbn07XG5cbkxpc3Qua2V5ZGVsZXRlID0gZnVuY3Rpb24gKGxpc3QsIGtleSwgcG9zaXRpb24pIHtcbiAgbGV0IG5ld19saXN0ID0gW107XG5cbiAgZm9yIChsZXQgaSA9IDA7IGkgPCBsaXN0Lmxlbmd0aDsgaSsrKSB7XG4gICAgaWYgKCFLZXJuZWwubWF0Y2hfX3FtYXJrX18obGlzdFtpXVtwb3NpdGlvbl0sIGtleSkpIHtcbiAgICAgIG5ld19saXN0LnB1c2gobGlzdFtpXSk7XG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIEtlcm5lbC5TcGVjaWFsRm9ybXMubGlzdCguLi5uZXdfbGlzdCk7XG59O1xuXG5MaXN0LmtleWZpbmQgPSBmdW5jdGlvbiAobGlzdCwga2V5LCBwb3NpdGlvbiwgX2RlZmF1bHQgPSBudWxsKSB7XG5cbiAgZm9yIChsZXQgaSA9IDA7IGkgPCBsaXN0Lmxlbmd0aDsgaSsrKSB7XG4gICAgaWYgKEtlcm5lbC5tYXRjaF9fcW1hcmtfXyhsaXN0W2ldW3Bvc2l0aW9uXSwga2V5KSkge1xuICAgICAgcmV0dXJuIGxpc3RbaV07XG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIF9kZWZhdWx0O1xufTtcblxuTGlzdC5rZXltZW1iZXJfX3FtYXJrX18gPSBmdW5jdGlvbiAobGlzdCwga2V5LCBwb3NpdGlvbikge1xuXG4gIGZvciAobGV0IGkgPSAwOyBpIDwgbGlzdC5sZW5ndGg7IGkrKykge1xuICAgIGlmIChLZXJuZWwubWF0Y2hfX3FtYXJrX18obGlzdFtpXVtwb3NpdGlvbl0sIGtleSkpIHtcbiAgICAgIHJldHVybiB0cnVlO1xuICAgIH1cbiAgfVxuXG4gIHJldHVybiBmYWxzZTtcbn07XG5cbkxpc3Qua2V5cmVwbGFjZSA9IGZ1bmN0aW9uIChsaXN0LCBrZXksIHBvc2l0aW9uLCBuZXdfdHVwbGUpIHtcbiAgbGV0IG5ld19saXN0ID0gW107XG5cbiAgZm9yIChsZXQgaSA9IDA7IGkgPCBsaXN0Lmxlbmd0aDsgaSsrKSB7XG4gICAgaWYgKCFLZXJuZWwubWF0Y2hfX3FtYXJrX18obGlzdFtpXVtwb3NpdGlvbl0sIGtleSkpIHtcbiAgICAgIG5ld19saXN0LnB1c2gobGlzdFtpXSk7XG4gICAgfSBlbHNlIHtcbiAgICAgIG5ld19saXN0LnB1c2gobmV3X3R1cGxlKTtcbiAgICB9XG4gIH1cblxuICByZXR1cm4gS2VybmVsLlNwZWNpYWxGb3Jtcy5saXN0KC4uLm5ld19saXN0KTtcbn07XG5cbkxpc3Qua2V5c29ydCA9IGZ1bmN0aW9uIChsaXN0LCBwb3NpdGlvbikge1xuICBsZXQgbmV3X2xpc3QgPSBsaXN0O1xuXG4gIG5ld19saXN0LnNvcnQoZnVuY3Rpb24gKGEsIGIpIHtcbiAgICBpZiAocG9zaXRpb24gPT09IDApIHtcbiAgICAgIGlmIChhW3Bvc2l0aW9uXS52YWx1ZSA8IGJbcG9zaXRpb25dLnZhbHVlKSB7XG4gICAgICAgIHJldHVybiAtMTtcbiAgICAgIH1cblxuICAgICAgaWYgKGFbcG9zaXRpb25dLnZhbHVlID4gYltwb3NpdGlvbl0udmFsdWUpIHtcbiAgICAgICAgcmV0dXJuIDE7XG4gICAgICB9XG5cbiAgICAgIHJldHVybiAwO1xuICAgIH0gZWxzZSB7XG4gICAgICBpZiAoYVtwb3NpdGlvbl0gPCBiW3Bvc2l0aW9uXSkge1xuICAgICAgICByZXR1cm4gLTE7XG4gICAgICB9XG5cbiAgICAgIGlmIChhW3Bvc2l0aW9uXSA+IGJbcG9zaXRpb25dKSB7XG4gICAgICAgIHJldHVybiAxO1xuICAgICAgfVxuXG4gICAgICByZXR1cm4gMDtcbiAgICB9XG4gIH0pO1xuXG4gIHJldHVybiBLZXJuZWwuU3BlY2lhbEZvcm1zLmxpc3QoLi4ubmV3X2xpc3QpO1xufTtcblxuTGlzdC5rZXlzdG9yZSA9IGZ1bmN0aW9uIChsaXN0LCBrZXksIHBvc2l0aW9uLCBuZXdfdHVwbGUpIHtcbiAgbGV0IG5ld19saXN0ID0gW107XG4gIGxldCByZXBsYWNlZCA9IGZhbHNlO1xuXG4gIGZvciAobGV0IGkgPSAwOyBpIDwgbGlzdC5sZW5ndGg7IGkrKykge1xuICAgIGlmICghS2VybmVsLm1hdGNoX19xbWFya19fKGxpc3RbaV1bcG9zaXRpb25dLCBrZXkpKSB7XG4gICAgICBuZXdfbGlzdC5wdXNoKGxpc3RbaV0pO1xuICAgIH0gZWxzZSB7XG4gICAgICBuZXdfbGlzdC5wdXNoKG5ld190dXBsZSk7XG4gICAgICByZXBsYWNlZCA9IHRydWU7XG4gICAgfVxuICB9XG5cbiAgaWYgKCFyZXBsYWNlZCkge1xuICAgIG5ld19saXN0LnB1c2gobmV3X3R1cGxlKTtcbiAgfVxuXG4gIHJldHVybiBLZXJuZWwuU3BlY2lhbEZvcm1zLmxpc3QoLi4ubmV3X2xpc3QpO1xufTtcblxuTGlzdC5sYXN0ID0gZnVuY3Rpb24gKGxpc3QpIHtcbiAgcmV0dXJuIGxpc3RbbGlzdC5sZW5ndGggLSAxXTtcbn07XG5cbkxpc3QucmVwbGFjZV9hdCA9IGZ1bmN0aW9uIChsaXN0LCBpbmRleCwgdmFsdWUpIHtcbiAgbGV0IG5ld192YWx1ZSA9IFtdO1xuXG4gIGZvciAobGV0IGkgPSAwOyBpIDwgbGlzdC5sZW5ndGg7IGkrKykge1xuICAgIGlmIChpID09PSBpbmRleCkge1xuICAgICAgbmV3X3ZhbHVlLnB1c2godmFsdWUpO1xuICAgIH0gZWxzZSB7XG4gICAgICBuZXdfdmFsdWUucHVzaChsaXN0W2ldKTtcbiAgICB9XG4gIH1cblxuICByZXR1cm4gS2VybmVsLlNwZWNpYWxGb3Jtcy5saXN0KC4uLm5ld192YWx1ZSk7XG59O1xuXG5MaXN0LnVwZGF0ZV9hdCA9IGZ1bmN0aW9uIChsaXN0LCBpbmRleCwgZnVuKSB7XG4gIGxldCBuZXdfdmFsdWUgPSBbXTtcblxuICBmb3IgKGxldCBpID0gMDsgaSA8IGxpc3QuY291bnQoKTsgaSsrKSB7XG4gICAgaWYgKGkgPT09IGluZGV4KSB7XG4gICAgICBuZXdfdmFsdWUucHVzaChmdW4obGlzdC5nZXQoaSkpKTtcbiAgICB9IGVsc2Uge1xuICAgICAgbmV3X3ZhbHVlLnB1c2gobGlzdC5nZXQoaSkpO1xuICAgIH1cbiAgfVxuXG4gIHJldHVybiBuZXdfdmFsdWU7XG59O1xuXG5MaXN0LndyYXAgPSBmdW5jdGlvbiAobGlzdCkge1xuICBpZiAoS2VybmVsLmlzX2xpc3QobGlzdCkpIHtcbiAgICByZXR1cm4gbGlzdDtcbiAgfSBlbHNlIGlmIChsaXN0ID09IG51bGwpIHtcbiAgICByZXR1cm4gS2VybmVsLlNwZWNpYWxGb3Jtcy5saXN0KCk7XG4gIH0gZWxzZSB7XG4gICAgcmV0dXJuIEtlcm5lbC5TcGVjaWFsRm9ybXMubGlzdChsaXN0KTtcbiAgfVxufTtcblxuTGlzdC56aXAgPSBmdW5jdGlvbiAobGlzdF9vZl9saXN0cykge1xuICBpZiAobGlzdF9vZl9saXN0cy5sZW5ndGggPT09IDApIHtcbiAgICByZXR1cm4gS2VybmVsLlNwZWNpYWxGb3Jtcy5saXN0KCk7XG4gIH1cblxuICBsZXQgbmV3X3ZhbHVlID0gW107XG4gIGxldCBzbWFsbGVzdF9sZW5ndGggPSBsaXN0X29mX2xpc3RzWzBdO1xuXG4gIGZvciAobGV0IHggb2YgbGlzdF9vZl9saXN0cykge1xuICAgIGlmICh4Lmxlbmd0aCA8IHNtYWxsZXN0X2xlbmd0aCkge1xuICAgICAgc21hbGxlc3RfbGVuZ3RoID0geC5sZW5ndGg7XG4gICAgfVxuICB9XG5cbiAgZm9yIChsZXQgaSA9IDA7IGkgPCBzbWFsbGVzdF9sZW5ndGg7IGkrKykge1xuICAgIGxldCBjdXJyZW50X3ZhbHVlID0gW107XG4gICAgZm9yIChsZXQgaiA9IDA7IGogPCBsaXN0X29mX2xpc3RzLmxlbmd0aDsgaisrKSB7XG4gICAgICBjdXJyZW50X3ZhbHVlLnB1c2gobGlzdF9vZl9saXN0c1tqXVtpXSk7XG4gICAgfVxuXG4gICAgbmV3X3ZhbHVlLnB1c2goS2VybmVsLlNwZWNpYWxGb3Jtcy50dXBsZSguLi5jdXJyZW50X3ZhbHVlKSk7XG4gIH1cblxuICByZXR1cm4gS2VybmVsLlNwZWNpYWxGb3Jtcy5saXN0KC4uLm5ld192YWx1ZSk7XG59O1xuXG5MaXN0LnRvX3R1cGxlID0gZnVuY3Rpb24gKGxpc3QpIHtcbiAgcmV0dXJuIEtlcm5lbC5TcGVjaWFsRm9ybXMudHVwbGUuYXBwbHkobnVsbCwgbGlzdCk7XG59O1xuXG5MaXN0LmFwcGVuZCA9IGZ1bmN0aW9uIChsaXN0LCB2YWx1ZSkge1xuICByZXR1cm4gS2VybmVsLlNwZWNpYWxGb3Jtcy5saXN0KC4uLmxpc3QuY29uY2F0KFt2YWx1ZV0pKTtcbn07XG5cbkxpc3QucHJlcGVuZCA9IGZ1bmN0aW9uIChsaXN0LCB2YWx1ZSkge1xuICByZXR1cm4gS2VybmVsLlNwZWNpYWxGb3Jtcy5saXN0KC4uLlt2YWx1ZV0uY29uY2F0KGxpc3QpKTtcbn07XG5cbkxpc3QuY29uY2F0ID0gZnVuY3Rpb24gKGxlZnQsIHJpZ2h0KSB7XG4gIHJldHVybiBsZWZ0LmNvbmNhdChyaWdodCk7XG59O1xuXG5sZXQgUmFuZ2UgPSBmdW5jdGlvbiAoX2ZpcnN0LCBfbGFzdCkge1xuICBpZiAoISh0aGlzIGluc3RhbmNlb2YgUmFuZ2UpKSB7XG4gICAgcmV0dXJuIG5ldyBSYW5nZShfZmlyc3QsIF9sYXN0KTtcbiAgfVxuXG4gIHRoaXMuZmlyc3QgPSBmdW5jdGlvbiAoKSB7XG4gICAgcmV0dXJuIF9maXJzdDtcbiAgfTtcblxuICB0aGlzLmxhc3QgPSBmdW5jdGlvbiAoKSB7XG4gICAgcmV0dXJuIF9sYXN0O1xuICB9O1xuXG4gIGxldCBfcmFuZ2UgPSBbXTtcblxuICBmb3IgKGxldCBpID0gX2ZpcnN0OyBpIDw9IF9sYXN0OyBpKyspIHtcbiAgICBfcmFuZ2UucHVzaChpKTtcbiAgfVxuXG4gIF9yYW5nZSA9IE9iamVjdC5mcmVlemUoX3JhbmdlKTtcblxuICB0aGlzLnZhbHVlID0gZnVuY3Rpb24gKCkge1xuICAgIHJldHVybiBfcmFuZ2U7XG4gIH07XG5cbiAgdGhpcy5sZW5ndGggPSBmdW5jdGlvbiAoKSB7XG4gICAgcmV0dXJuIF9yYW5nZS5sZW5ndGg7XG4gIH07XG5cbiAgcmV0dXJuIHRoaXM7XG59O1xuXG5SYW5nZS5wcm90b3R5cGVbU3ltYm9sLml0ZXJhdG9yXSA9IGZ1bmN0aW9uICgpIHtcbiAgcmV0dXJuIHRoaXMudmFsdWUoKVtTeW1ib2wuaXRlcmF0b3JdKCk7XG59O1xuXG5SYW5nZS5uZXcgPSBmdW5jdGlvbiAoZmlyc3QsIGxhc3QpIHtcbiAgcmV0dXJuIFJhbmdlKGZpcnN0LCBsYXN0KTtcbn07XG5cblJhbmdlLnJhbmdlX19xbWFya19fID0gZnVuY3Rpb24gKHJhbmdlKSB7XG4gIHJldHVybiByYW5nZSBpbnN0YW5jZW9mIFJhbmdlO1xufTtcblxubGV0IEtleXdvcmQgPSB7fTtcblxuS2V5d29yZC5oYXNfa2V5X19xbV9fID0gZnVuY3Rpb24gKGtleXdvcmRzLCBrZXkpIHtcbiAgZm9yIChsZXQga2V5d29yZCBvZiBrZXl3b3Jkcykge1xuICAgIGlmIChLZXJuZWwuZWxlbShrZXl3b3JkLCAwKSA9PSBrZXkpIHtcbiAgICAgIHJldHVybiB0cnVlO1xuICAgIH1cbiAgfVxuXG4gIHJldHVybiBmYWxzZTtcbn07XG5cbktleXdvcmQuZ2V0ID0gZnVuY3Rpb24gKGtleXdvcmRzLCBrZXksIHRoZV9kZWZhdWx0ID0gbnVsbCkge1xuICBmb3IgKGxldCBrZXl3b3JkIG9mIGtleXdvcmRzKSB7XG4gICAgaWYgKEtlcm5lbC5lbGVtKGtleXdvcmQsIDApID09IGtleSkge1xuICAgICAgcmV0dXJuIEtlcm5lbC5lbGVtKGtleXdvcmQsIDEpO1xuICAgIH1cbiAgfVxuXG4gIHJldHVybiB0aGVfZGVmYXVsdDtcbn07XG5cbmxldCBBZ2VudCA9IHt9O1xuXG5BZ2VudC5zdGFydCA9IGZ1bmN0aW9uIChmdW4sIG9wdGlvbnMgPSBbXSkge1xuICBsZXQgcGlkID0gc2VsZi5wcm9jZXNzZXMuc3Bhd24oKTtcblxuICBpZiAoS2V5d29yZC5oYXNfa2V5X19xbV9fKG9wdGlvbnMsIEtlcm5lbC5TcGVjaWFsRm9ybXMuYXRvbSgnbmFtZScpKSkge1xuICAgIHBpZCA9IHNlbGYucHJvY2Vzc2VzLnJlZ2lzdGVyKEtleXdvcmQuZ2V0KG9wdGlvbnMsIEtlcm5lbC5TcGVjaWFsRm9ybXMuYXRvbSgnbmFtZScpKSwgcGlkKTtcbiAgfVxuXG4gIHNlbGYucHJvY2Vzc2VzLnB1dChwaWQsICdzdGF0ZScsIGZ1bigpKTtcbiAgcmV0dXJuIEtlcm5lbC5TcGVjaWFsRm9ybXMudHVwbGUoS2VybmVsLlNwZWNpYWxGb3Jtcy5hdG9tKCdvaycpLCBwaWQpO1xufTtcblxuQWdlbnQuc3RvcCA9IGZ1bmN0aW9uIChhZ2VudCwgdGltZW91dCA9IDUwMDApIHtcbiAgc2VsZi5wcm9jZXNzZXMuZXhpdChhZ2VudCk7XG4gIHJldHVybiBLZXJuZWwuU3BlY2lhbEZvcm1zLmF0b20oJ29rJyk7XG59O1xuXG5BZ2VudC51cGRhdGUgPSBmdW5jdGlvbiAoYWdlbnQsIGZ1biwgdGltZW91dCA9IDUwMDApIHtcblxuICBjb25zdCBjdXJyZW50X3N0YXRlID0gc2VsZi5wcm9jZXNzZXMuZ2V0KGFnZW50LCAnc3RhdGUnKTtcbiAgc2VsZi5wcm9jZXNzZXMucHV0KGFnZW50LCAnc3RhdGUnLCBmdW4oY3VycmVudF9zdGF0ZSkpO1xuXG4gIHJldHVybiBLZXJuZWwuU3BlY2lhbEZvcm1zLmF0b20oJ29rJyk7XG59O1xuXG5BZ2VudC5nZXQgPSBmdW5jdGlvbiAoYWdlbnQsIGZ1biwgdGltZW91dCA9IDUwMDApIHtcbiAgcmV0dXJuIGZ1bihzZWxmLnByb2Nlc3Nlcy5nZXQoYWdlbnQsICdzdGF0ZScpKTtcbn07XG5cbkFnZW50LmdldF9hbmRfdXBkYXRlID0gZnVuY3Rpb24gKGFnZW50LCBmdW4sIHRpbWVvdXQgPSA1MDAwKSB7XG5cbiAgY29uc3QgZ2V0X2FuZF91cGRhdGVfdHVwbGUgPSBmdW4oc2VsZi5wcm9jZXNzZXMuZ2V0KGFnZW50LCAnc3RhdGUnKSk7XG4gIHNlbGYucHJvY2Vzc2VzLnB1dChhZ2VudCwgJ3N0YXRlJywgS2VybmVsLmVsZW0oZ2V0X2FuZF91cGRhdGVfdHVwbGUsIDEpKTtcblxuICByZXR1cm4gS2VybmVsLmVsZW0oZ2V0X2FuZF91cGRhdGVfdHVwbGUsIDApO1xufTtcblxuLy9odHRwczovL2RldmVsb3Blci5tb3ppbGxhLm9yZy9lbi1VUy9kb2NzL1dlYi9BUEkvV2luZG93QmFzZTY0L0Jhc2U2NF9lbmNvZGluZ19hbmRfZGVjb2RpbmcjU29sdXRpb25fMl8lRTIlODAlOTNfcmV3cml0ZV90aGVfRE9Nc19hdG9iKClfYW5kX2J0b2EoKV91c2luZ19KYXZhU2NyaXB0J3NfVHlwZWRBcnJheXNfYW5kX1VURi04XG5mdW5jdGlvbiBiNjRFbmNvZGVVbmljb2RlKHN0cikge1xuICByZXR1cm4gYnRvYShlbmNvZGVVUklDb21wb25lbnQoc3RyKS5yZXBsYWNlKC8lKFswLTlBLUZdezJ9KS9nLCBmdW5jdGlvbiAobWF0Y2gsIHAxKSB7XG4gICAgcmV0dXJuIFN0cmluZy5mcm9tQ2hhckNvZGUoJzB4JyArIHAxKTtcbiAgfSkpO1xufVxuXG5mdW5jdGlvbiBlbmNvZGU2NChkYXRhKSB7XG4gIHJldHVybiBiNjRFbmNvZGVVbmljb2RlKGRhdGEpO1xufVxuXG5mdW5jdGlvbiBkZWNvZGU2NChkYXRhKSB7XG4gIHRyeSB7XG4gICAgcmV0dXJuIEtlcm5lbC5TcGVjaWFsRm9ybXMudHVwbGUoS2VybmVsLlNwZWNpYWxGb3Jtcy5hdG9tKCdvaycpLCBhdG9iKGRhdGEpKTtcbiAgfSBjYXRjaCAoZSkge1xuICAgIHJldHVybiBLZXJuZWwuU3BlY2lhbEZvcm1zLmF0b20oJ2Vycm9yJyk7XG4gIH1cbiAgcmV0dXJuIGJ0b2EoZGF0YSk7XG59XG5cbmZ1bmN0aW9uIGRlY29kZTY0X19lbV9fKGRhdGEpIHtcbiAgcmV0dXJuIGF0b2IoZGF0YSk7XG59XG5cbnZhciBiYXNlID0ge1xuICBlbmNvZGU2NCxcbiAgZGVjb2RlNjQsXG4gIGRlY29kZTY0X19lbV9fXG59O1xuXG5mdW5jdGlvbiBibm90KGV4cHIpIHtcbiAgcmV0dXJuIH5leHByO1xufVxuXG5mdW5jdGlvbiBiYW5kKGxlZnQsIHJpZ2h0KSB7XG4gIHJldHVybiBsZWZ0ICYgcmlnaHQ7XG59XG5cbmZ1bmN0aW9uIGJvcihsZWZ0LCByaWdodCkge1xuICByZXR1cm4gbGVmdCB8IHJpZ2h0O1xufVxuXG5mdW5jdGlvbiBic2wobGVmdCwgcmlnaHQpIHtcbiAgcmV0dXJuIGxlZnQgPDwgcmlnaHQ7XG59XG5cbmZ1bmN0aW9uIGJzcihsZWZ0LCByaWdodCkge1xuICByZXR1cm4gbGVmdCA+PiByaWdodDtcbn1cblxuZnVuY3Rpb24gYnhvcihsZWZ0LCByaWdodCkge1xuICByZXR1cm4gbGVmdCBeIHJpZ2h0O1xufVxuXG52YXIgYml0d2lzZSA9IHtcbiAgYm5vdCxcbiAgYmFuZCxcbiAgYm9yLFxuICBic2wsXG4gIGJzcixcbiAgYnhvclxufTtcblxubGV0IEVudW1lcmFibGUgPSBLZXJuZWwuZGVmcHJvdG9jb2woe1xuICBjb3VudDogZnVuY3Rpb24gKGNvbGxlY3Rpb24pIHt9LFxuICBtZW1iZXJfcW1hcmtfXzogZnVuY3Rpb24gKGNvbGxlY3Rpb24sIHZhbHVlKSB7fSxcbiAgcmVkdWNlOiBmdW5jdGlvbiAoY29sbGVjdGlvbiwgYWNjLCBmdW4pIHt9XG59KTtcblxubGV0IENvbGxlY3RhYmxlID0gS2VybmVsLmRlZnByb3RvY29sKHtcbiAgaW50bzogZnVuY3Rpb24gKGNvbGxlY3RhYmxlKSB7fVxufSk7XG5cbmxldCBJbnNwZWN0ID0gS2VybmVsLmRlZnByb3RvY29sKHtcbiAgaW5zcGVjdDogZnVuY3Rpb24gKHRoaW5nLCBvcHRzKSB7fVxufSk7XG5cbmZ1bmN0aW9uIF9fbmV3X18oKSB7XG4gIHJldHVybiBTcGVjaWFsRm9ybXMubWFwKHt9KTtcbn1cblxuZnVuY3Rpb24ga2V5cyhtYXApIHtcbiAgcmV0dXJuIE9iamVjdC5rZXlzKG1hcCk7XG59XG5cbmZ1bmN0aW9uIHNpemUobWFwKSB7XG4gIHJldHVybiBrZXlzKG1hcCkubGVuZ3RoO1xufVxuXG5mdW5jdGlvbiB0b19saXN0JDEobWFwKSB7XG4gIGxldCBtYXBfa2V5cyA9IGtleXMobWFwKTtcbiAgbGV0IGxpc3QgPSBbXTtcblxuICBmb3IgKGxldCBrZXkgb2YgbWFwX2tleXMpIHtcbiAgICBsaXN0LnB1c2goU3BlY2lhbEZvcm1zLnR1cGxlKGtleSwgbWFwW2tleV0pKTtcbiAgfVxuXG4gIHJldHVybiBTcGVjaWFsRm9ybXMubGlzdCguLi5saXN0KTtcbn1cblxuZnVuY3Rpb24gdmFsdWVzKG1hcCkge1xuICBsZXQgbWFwX2tleXMgPSBrZXlzKG1hcCk7XG4gIGxldCBsaXN0ID0gW107XG5cbiAgZm9yIChsZXQga2V5IG9mIG1hcF9rZXlzKSB7XG4gICAgbGlzdC5wdXNoKG1hcFtrZXldKTtcbiAgfVxuXG4gIHJldHVybiBTcGVjaWFsRm9ybXMubGlzdCguLi5saXN0KTtcbn1cblxuZnVuY3Rpb24gZnJvbV9zdHJ1Y3Qoc3RydWN0KSB7XG4gIGxldCBtYXAgPSBPYmplY3QuYXNzaWduKHt9LCBzdHJ1Y3QpO1xuICBkZWxldGUgbWFwW1N5bWJvbC5mb3IoXCJfX3N0cnVjdF9fXCIpXTtcblxuICByZXR1cm4gU3BlY2lhbEZvcm1zLm1hcChtYXApO1xufVxuXG5mdW5jdGlvbiBfX2RlbGV0ZV9fKG1hcCwga2V5KSB7XG4gIGxldCBuZXdfbWFwID0gT2JqZWN0LmFzc2lnbih7fSwgbWFwKTtcblxuICBkZWxldGUgbmV3X21hcFtrZXldO1xuXG4gIHJldHVybiBTcGVjaWFsRm9ybXMubWFwKG5ld19tYXApO1xufVxuXG5mdW5jdGlvbiBlcXVhbF9fcW1hcmtfXyhtYXAxLCBtYXAyKSB7XG4gIHJldHVybiBtYXAxID09PSBtYXAyO1xufVxuXG5mdW5jdGlvbiBmZXRjaF9fZW1hcmtfXyhtYXAsIGtleSkge1xuICBpZiAoa2V5IGluIG1hcCkge1xuICAgIHJldHVybiBtYXBba2V5XTtcbiAgfVxuXG4gIHRocm93IG5ldyBFcnJvcihcIktleSBub3QgZm91bmQuXCIpO1xufVxuXG5mdW5jdGlvbiBmZXRjaChtYXAsIGtleSkge1xuICBpZiAoa2V5IGluIG1hcCkge1xuICAgIHJldHVybiBTcGVjaWFsRm9ybXMudHVwbGUoU3BlY2lhbEZvcm1zLmF0b20oXCJva1wiKSwgbWFwW2tleV0pO1xuICB9XG5cbiAgcmV0dXJuIFNwZWNpYWxGb3Jtcy5hdG9tKFwiZXJyb3JcIik7XG59XG5cbmZ1bmN0aW9uIGhhc19rZXlfX3FtYXJrX18obWFwLCBrZXkpIHtcbiAgcmV0dXJuIGtleSBpbiBtYXA7XG59XG5cbmZ1bmN0aW9uIHNwbGl0JDEobWFwLCBrZXlzKSB7XG4gIGxldCBzcGxpdDEgPSB7fTtcbiAgbGV0IHNwbGl0MiA9IHt9O1xuXG4gIGZvciAobGV0IGtleSBvZiBPYmplY3Qua2V5cyhtYXApKSB7XG4gICAgaWYgKGtleXMuaW5kZXhPZihrZXkpID4gLTEpIHtcbiAgICAgIHNwbGl0MVtrZXldID0gbWFwW2tleV07XG4gICAgfSBlbHNlIHtcbiAgICAgIHNwbGl0MltrZXldID0gbWFwW2tleV07XG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIFNwZWNpYWxGb3Jtcy50dXBsZShTcGVjaWFsRm9ybXMubWFwKHNwbGl0MSksIFNwZWNpYWxGb3Jtcy5tYXAoc3BsaXQyKSk7XG59XG5cbmZ1bmN0aW9uIHRha2UobWFwLCBrZXlzKSB7XG4gIGxldCBzcGxpdDEgPSB7fTtcblxuICBmb3IgKGxldCBrZXkgb2YgT2JqZWN0LmtleXMobWFwKSkge1xuICAgIGlmIChrZXlzLmluZGV4T2Yoa2V5KSA+IC0xKSB7XG4gICAgICBzcGxpdDFba2V5XSA9IG1hcFtrZXldO1xuICAgIH1cbiAgfVxuXG4gIHJldHVybiBTcGVjaWFsRm9ybXMubWFwKHNwbGl0MSk7XG59XG5cbmZ1bmN0aW9uIGRyb3AobWFwLCBrZXlzKSB7XG4gIGxldCBzcGxpdDEgPSB7fTtcblxuICBmb3IgKGxldCBrZXkgb2YgT2JqZWN0LmtleXMobWFwKSkge1xuICAgIGlmIChrZXlzLmluZGV4T2Yoa2V5KSA9PT0gLTEpIHtcbiAgICAgIHNwbGl0MVtrZXldID0gbWFwW2tleV07XG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIFNwZWNpYWxGb3Jtcy5tYXAoc3BsaXQxKTtcbn1cblxuZnVuY3Rpb24gcHV0X25ldyhtYXAsIGtleSwgdmFsdWUpIHtcbiAgaWYgKGtleSBpbiBtYXApIHtcbiAgICByZXR1cm4gbWFwO1xuICB9XG5cbiAgbGV0IG5ld19tYXAgPSBPYmplY3QuYXNzaWduKHt9LCBtYXApO1xuICBuZXdfbWFwW2tleV0gPSB2YWx1ZTtcblxuICByZXR1cm4gU3BlY2lhbEZvcm1zLm1hcChuZXdfbWFwKTtcbn1cblxuZnVuY3Rpb24gcHV0X25ld19sYXp5KG1hcCwga2V5LCBmdW4pIHtcbiAgaWYgKGtleSBpbiBtYXApIHtcbiAgICByZXR1cm4gbWFwO1xuICB9XG5cbiAgbGV0IG5ld19tYXAgPSBPYmplY3QuYXNzaWduKHt9LCBtYXApO1xuICBuZXdfbWFwW2tleV0gPSBmdW4oKTtcblxuICByZXR1cm4gU3BlY2lhbEZvcm1zLm1hcChuZXdfbWFwKTtcbn1cblxuZnVuY3Rpb24gZ2V0X2FuZF91cGRhdGUobWFwLCBrZXksIGZ1bikge1xuICBpZiAoa2V5IGluIG1hcCkge1xuICAgIHJldHVybiBtYXA7XG4gIH1cblxuICBsZXQgbmV3X21hcCA9IE9iamVjdC5hc3NpZ24oe30sIG1hcCk7XG4gIG5ld19tYXBba2V5XSA9IGZ1bihtYXBba2V5XSk7XG5cbiAgcmV0dXJuIFNwZWNpYWxGb3Jtcy5tYXAobmV3X21hcCk7XG59XG5cbmZ1bmN0aW9uIHBvcF9sYXp5KG1hcCwga2V5LCBmdW4pIHtcbiAgaWYgKCFrZXkgaW4gbWFwKSB7XG4gICAgcmV0dXJuIFNwZWNpYWxGb3Jtcy50dXBsZShmdW4oKSwgbWFwKTtcbiAgfVxuXG4gIGxldCBuZXdfbWFwID0gT2JqZWN0LmFzc2lnbih7fSwgbWFwKTtcbiAgbGV0IHZhbHVlID0gZnVuKG5ld19tYXBba2V5XSk7XG4gIGRlbGV0ZSBuZXdfbWFwW2tleV07XG5cbiAgcmV0dXJuIFNwZWNpYWxGb3Jtcy50dXBsZSh2YWx1ZSwgbmV3X21hcCk7XG59XG5cbmZ1bmN0aW9uIHBvcChtYXAsIGtleSwgX2RlZmF1bHQgPSBudWxsKSB7XG4gIGlmICgha2V5IGluIG1hcCkge1xuICAgIHJldHVybiBTcGVjaWFsRm9ybXMudHVwbGUoX2RlZmF1bHQsIG1hcCk7XG4gIH1cblxuICBsZXQgbmV3X21hcCA9IE9iamVjdC5hc3NpZ24oe30sIG1hcCk7XG4gIGxldCB2YWx1ZSA9IG5ld19tYXBba2V5XTtcbiAgZGVsZXRlIG5ld19tYXBba2V5XTtcblxuICByZXR1cm4gU3BlY2lhbEZvcm1zLnR1cGxlKHZhbHVlLCBuZXdfbWFwKTtcbn1cblxuZnVuY3Rpb24gZ2V0X2xhenkobWFwLCBrZXksIGZ1bikge1xuICBpZiAoIWtleSBpbiBtYXApIHtcbiAgICByZXR1cm4gZnVuKCk7XG4gIH1cblxuICByZXR1cm4gZnVuKG1hcFtrZXldKTtcbn1cblxuZnVuY3Rpb24gZ2V0KG1hcCwga2V5LCBfZGVmYXVsdCA9IG51bGwpIHtcbiAgaWYgKCFrZXkgaW4gbWFwKSB7XG4gICAgcmV0dXJuIF9kZWZhdWx0O1xuICB9XG5cbiAgcmV0dXJuIG1hcFtrZXldO1xufVxuXG5mdW5jdGlvbiBwdXQobWFwLCBrZXksIHZhbCkge1xuICBsZXQgbmV3X21hcCA9IE9iamVjdCh7fSwgbWFwKTtcbiAgbmV3X21hcFtrZXldID0gdmFsO1xuXG4gIHJldHVybiBTcGVjaWFsRm9ybXMubWFwKG5ld19tYXApO1xufVxuXG5mdW5jdGlvbiB1cGRhdGVfX2VtYXJrX18obWFwLCBrZXksIGZ1bikge1xuICBpZiAoIWtleSBpbiBtYXApIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoXCJLZXkgbm90IGZvdW5kXCIpO1xuICB9XG5cbiAgbGV0IG5ld19tYXAgPSBPYmplY3Qoe30sIG1hcCk7XG4gIG5ld19tYXBba2V5XSA9IGZ1bihtYXBba2V5XSk7XG5cbiAgcmV0dXJuIFNwZWNpYWxGb3Jtcy5tYXAobmV3X21hcCk7XG59XG5cbmZ1bmN0aW9uIHVwZGF0ZShtYXAsIGtleSwgaW5pdGlhbCwgZnVuKSB7XG4gIGxldCBuZXdfbWFwID0gT2JqZWN0KHt9LCBtYXApO1xuXG4gIGlmICgha2V5IGluIG1hcCkge1xuICAgIG5ld19tYXBba2V5XSA9IGluaXRpYWw7XG4gIH0gZWxzZSB7XG4gICAgbmV3X21hcFtrZXldID0gZnVuKG1hcFtrZXldKTtcbiAgfVxuXG4gIHJldHVybiBTcGVjaWFsRm9ybXMubWFwKG5ld19tYXApO1xufVxuXG52YXIgbWFwID0ge1xuICBuZXc6IF9fbmV3X18sXG4gIGtleXMsXG4gIHNpemUsXG4gIHRvX2xpc3Q6IHRvX2xpc3QkMSxcbiAgdmFsdWVzLFxuICBmcm9tX3N0cnVjdCxcbiAgZGVsZXRlOiBfX2RlbGV0ZV9fLFxuICBkcm9wLFxuICBlcXVhbF9fcW1hcmtfXyxcbiAgZmV0Y2hfX2VtYXJrX18sXG4gIGZldGNoLFxuICBoYXNfa2V5X19xbWFya19fLFxuICBzcGxpdDogc3BsaXQkMSxcbiAgdGFrZSxcbiAgcHV0X25ldyxcbiAgcHV0X25ld19sYXp5LFxuICBnZXRfYW5kX3VwZGF0ZSxcbiAgcG9wX2xhenksXG4gIHBvcCxcbiAgZ2V0X2xhenksXG4gIGdldCxcbiAgcHV0LFxuICB1cGRhdGVfX2VtYXJrX18sXG4gIHVwZGF0ZVxufTtcblxuZnVuY3Rpb24gX19uZXdfXyQxKCkge1xuICByZXR1cm4gU3BlY2lhbEZvcm1zLm1hcCh7IFtTeW1ib2wuZm9yKCdfX3N0cnVjdF9fJyldOiBTeW1ib2wuZm9yKCdNYXBTZXQnKSwgc2V0OiBTcGVjaWFsRm9ybXMubGlzdCgpIH0pO1xufVxuXG5mdW5jdGlvbiBzaXplJDIobWFwKSB7XG4gIHJldHVybiBtYXAuc2V0Lmxlbmd0aDtcbn1cblxuZnVuY3Rpb24gdG9fbGlzdCQzKG1hcCkge1xuICByZXR1cm4gbWFwLnNldDtcbn1cblxuZnVuY3Rpb24gX19kZWxldGVfXyQyKHNldCwgdGVybSkge1xuICBsZXQgbmV3X2xpc3QgPSBMaXN0LmRlbGV0ZShzZXQuc2V0LCB0ZXJtKTtcblxuICBsZXQgbmV3X21hcCA9IE9iamVjdC5hc3NpZ24oe30sIHNldCk7XG4gIG5ld19tYXAuc2V0ID0gbmV3X2xpc3Q7XG4gIHJldHVybiBTcGVjaWFsRm9ybXMubWFwKG5ld19tYXApO1xufVxuXG5mdW5jdGlvbiBwdXQkMihzZXQsIHRlcm0pIHtcbiAgaWYgKHNldC5zZXQuaW5kZXhPZih0ZXJtKSA9PT0gLTEpIHtcbiAgICBsZXQgbmV3X2xpc3QgPSBMaXN0LmFwcGVuZChzZXQuc2V0LCB0ZXJtKTtcblxuICAgIGxldCBuZXdfbWFwID0gT2JqZWN0LmFzc2lnbih7fSwgc2V0KTtcbiAgICBuZXdfbWFwLnNldCA9IG5ld19saXN0O1xuICAgIHJldHVybiBTcGVjaWFsRm9ybXMubWFwKG5ld19tYXApO1xuICB9XG5cbiAgcmV0dXJuIHNldDtcbn1cblxuZnVuY3Rpb24gZGlmZmVyZW5jZSQxKHNldDEsIHNldDIpIHtcbiAgbGV0IG5ld19tYXAgPSBPYmplY3QuYXNzaWduKHt9LCBzZXQxKTtcblxuICBmb3IgKGxldCB2YWwgb2Ygc2V0MS5zZXQpIHtcbiAgICBpZiAobWVtYmVyX19xbWFya19fJDEoc2V0MiwgdmFsKSkge1xuICAgICAgbmV3X21hcC5zZXQgPSBMaXN0LmRlbGV0ZShuZXdfbWFwLnNldCwgdmFsKTtcbiAgICB9XG4gIH1cblxuICByZXR1cm4gU3BlY2lhbEZvcm1zLm1hcChuZXdfbWFwKTtcbn1cblxuZnVuY3Rpb24gaW50ZXJzZWN0aW9uJDEoc2V0MSwgc2V0Mikge1xuICBsZXQgbmV3X21hcCA9IE9iamVjdC5hc3NpZ24oe30sIHNldDEpO1xuXG4gIGZvciAobGV0IHZhbCBvZiBzZXQxLnNldCkge1xuICAgIGlmICghbWVtYmVyX19xbWFya19fJDEoc2V0MiwgdmFsKSkge1xuICAgICAgbmV3X21hcC5zZXQgPSBMaXN0LmRlbGV0ZShuZXdfbWFwLnNldCwgdmFsKTtcbiAgICB9XG4gIH1cblxuICByZXR1cm4gU3BlY2lhbEZvcm1zLm1hcChuZXdfbWFwKTtcbn1cblxuZnVuY3Rpb24gdW5pb24kMShzZXQxLCBzZXQyKSB7XG4gIGxldCBuZXdfbWFwID0gc2V0MTtcblxuICBmb3IgKGxldCB2YWwgb2Ygc2V0Mi5zZXQpIHtcbiAgICBuZXdfbWFwID0gcHV0JDIobmV3X21hcCwgdmFsKTtcbiAgfVxuXG4gIHJldHVybiBTcGVjaWFsRm9ybXMubWFwKG5ld19tYXApO1xufVxuXG5mdW5jdGlvbiBkaXNqb2luX19xbWFya19fJDEoc2V0MSwgc2V0Mikge1xuICBmb3IgKGxldCB2YWwgb2Ygc2V0MS5zZXQpIHtcbiAgICBpZiAobWVtYmVyX19xbWFya19fJDEoc2V0MiwgdmFsKSkge1xuICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH1cbiAgfVxuXG4gIHJldHVybiB0cnVlO1xufVxuXG5mdW5jdGlvbiBtZW1iZXJfX3FtYXJrX18kMShzZXQsIHZhbHVlKSB7XG4gIHJldHVybiBzZXQuc2V0LmluZGV4T2YodmFsdWUpID49IDA7XG59XG5cbmZ1bmN0aW9uIGVxdWFsX19xbWFya19fJDIoc2V0MSwgc2V0Mikge1xuICByZXR1cm4gc2V0MS5zZXQgPT09IHNldDIuc2V0O1xufVxuXG5mdW5jdGlvbiBzdWJzZXRfX3FtYXJrX18kMShzZXQxLCBzZXQyKSB7XG4gIGZvciAobGV0IHZhbCBvZiBzZXQxLnNldCkge1xuICAgIGlmICghbWVtYmVyX19xbWFya19fJDEoc2V0MiwgdmFsKSkge1xuICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH1cbiAgfVxuXG4gIHJldHVybiB0cnVlO1xufVxuXG52YXIgTWFwU2V0ID0ge1xuICBuZXc6IF9fbmV3X18kMSxcbiAgc2l6ZTogc2l6ZSQyLFxuICB0b19saXN0OiB0b19saXN0JDMsXG4gIGRpc2pvaW5fX3FtYXJrX186IGRpc2pvaW5fX3FtYXJrX18kMSxcbiAgZGVsZXRlOiBfX2RlbGV0ZV9fJDIsXG4gIHN1YnNldF9fcW1hcmtfXzogc3Vic2V0X19xbWFya19fJDEsXG4gIGVxdWFsX19xbWFya19fOiBlcXVhbF9fcW1hcmtfXyQyLFxuICBtZW1iZXJfX3FtYXJrX186IG1lbWJlcl9fcW1hcmtfXyQxLFxuICBwdXQ6IHB1dCQyLFxuICB1bmlvbjogdW5pb24kMSxcbiAgaW50ZXJzZWN0aW9uOiBpbnRlcnNlY3Rpb24kMSxcbiAgZGlmZmVyZW5jZTogZGlmZmVyZW5jZSQxXG59O1xuXG5mdW5jdGlvbiBzaXplJDEobWFwKSB7XG4gIHJldHVybiBNYXBTZXQuc2l6ZShtYXApO1xufVxuXG5mdW5jdGlvbiB0b19saXN0JDIobWFwKSB7XG4gIHJldHVybiBNYXBTZXQudG9fbGlzdChtYXApO1xufVxuXG5mdW5jdGlvbiBfX2RlbGV0ZV9fJDEoc2V0LCB0ZXJtKSB7XG4gIHJldHVybiBNYXBTZXQuZGVsZXRlKHNldCwgdGVybSk7XG59XG5cbmZ1bmN0aW9uIHB1dCQxKHNldCwgdGVybSkge1xuICByZXR1cm4gTWFwU2V0LnB1dChzZXQsIHRlcm0pO1xufVxuXG5mdW5jdGlvbiBkaWZmZXJlbmNlKHNldDEsIHNldDIpIHtcbiAgcmV0dXJuIE1hcFNldC5kaWZmZXJlbmNlKHNldDEsIHNldDIpO1xufVxuXG5mdW5jdGlvbiBpbnRlcnNlY3Rpb24oc2V0MSwgc2V0Mikge1xuICByZXR1cm4gTWFwU2V0LmludGVyc2VjdGlvbihzZXQxLCBzZXQyKTtcbn1cblxuZnVuY3Rpb24gdW5pb24oc2V0MSwgc2V0Mikge1xuICByZXR1cm4gTWFwU2V0LnVuaW9uKHNldDEsIHNldDIpO1xufVxuXG5mdW5jdGlvbiBkaXNqb2luX19xbWFya19fKHNldDEsIHNldDIpIHtcbiAgcmV0dXJuIE1hcFNldC5kaXNqb2luX19xbWFya19fKHNldDEsIHNldDIpO1xufVxuXG5mdW5jdGlvbiBtZW1iZXJfX3FtYXJrX18oc2V0LCB2YWx1ZSkge1xuICByZXR1cm4gTWFwU2V0Lm1lbWJlcl9fcW1hcmtfXyhzZXQxLCBzZXQyKTtcbn1cblxuZnVuY3Rpb24gZXF1YWxfX3FtYXJrX18kMShzZXQxLCBzZXQyKSB7XG4gIHJldHVybiBNYXBTZXQuZXF1YWxfX3FtYXJrX18oc2V0MSwgc2V0Mik7XG59XG5cbmZ1bmN0aW9uIHN1YnNldF9fcW1hcmtfXyhzZXQxLCBzZXQyKSB7XG4gIHJldHVybiBNYXBTZXQuc3Vic2V0X19xbWFya19fKHNldDEsIHNldDIpO1xufVxuXG52YXIgc2V0ID0ge1xuICBzaXplOiBzaXplJDEsXG4gIHRvX2xpc3Q6IHRvX2xpc3QkMixcbiAgZGlzam9pbl9fcW1hcmtfXyxcbiAgZGVsZXRlOiBfX2RlbGV0ZV9fJDEsXG4gIHN1YnNldF9fcW1hcmtfXyxcbiAgZXF1YWxfX3FtYXJrX186IGVxdWFsX19xbWFya19fJDEsXG4gIG1lbWJlcl9fcW1hcmtfXyxcbiAgcHV0OiBwdXQkMSxcbiAgdW5pb24sXG4gIGludGVyc2VjdGlvbixcbiAgZGlmZmVyZW5jZVxufTtcblxubGV0IFZpcnR1YWxET00gPSAoZnVuY3Rpb24gKGUpIHtcbiAgICByZXR1cm4gZSgpO1xufSkoZnVuY3Rpb24gKCkge1xuICAgIHZhciBkZWZpbmUsIG1vZHVsZSwgZXhwb3J0cztcbiAgICByZXR1cm4gKGZ1bmN0aW9uIGUodCwgbiwgcikge1xuICAgICAgICBmdW5jdGlvbiBzKG8sIHUpIHtcbiAgICAgICAgICAgIGlmICghbltvXSkge1xuICAgICAgICAgICAgICAgIGlmICghdFtvXSkge1xuICAgICAgICAgICAgICAgICAgICB2YXIgYSA9IHR5cGVvZiByZXF1aXJlID09IFwiZnVuY3Rpb25cIiAmJiByZXF1aXJlO1xuICAgICAgICAgICAgICAgICAgICBpZiAoIXUgJiYgYSkgcmV0dXJuIGEobywgITApO1xuICAgICAgICAgICAgICAgICAgICBpZiAoaSkgcmV0dXJuIGkobywgITApO1xuICAgICAgICAgICAgICAgICAgICB2YXIgZiA9IG5ldyBFcnJvcihcIkNhbm5vdCBmaW5kIG1vZHVsZSAnXCIgKyBvICsgXCInXCIpO1xuICAgICAgICAgICAgICAgICAgICB0aHJvdyAoZi5jb2RlID0gXCJNT0RVTEVfTk9UX0ZPVU5EXCIsIGYpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB2YXIgbCA9IG5bb10gPSB7XG4gICAgICAgICAgICAgICAgICAgIGV4cG9ydHM6IHt9XG4gICAgICAgICAgICAgICAgfTtcbiAgICAgICAgICAgICAgICB0W29dWzBdLmNhbGwobC5leHBvcnRzLCBmdW5jdGlvbiAoZSkge1xuICAgICAgICAgICAgICAgICAgICB2YXIgbiA9IHRbb11bMV1bZV07XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBzKG4gPyBuIDogZSk7XG4gICAgICAgICAgICAgICAgfSwgbCwgbC5leHBvcnRzLCBlLCB0LCBuLCByKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJldHVybiBuW29dLmV4cG9ydHM7XG4gICAgICAgIH1cbiAgICAgICAgdmFyIGkgPSB0eXBlb2YgcmVxdWlyZSA9PSBcImZ1bmN0aW9uXCIgJiYgcmVxdWlyZTtcbiAgICAgICAgZm9yICh2YXIgbyA9IDA7IG8gPCByLmxlbmd0aDsgbysrKSBzKHJbb10pO1xuICAgICAgICByZXR1cm4gcztcbiAgICB9KSh7XG4gICAgICAgIDE6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG5cbiAgICAgICAgICAgIHZhciBjcmVhdGVFbGVtZW50ID0gcmVxdWlyZShcIi4vdmRvbS9jcmVhdGUtZWxlbWVudC5qc1wiKTtcblxuICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBjcmVhdGVFbGVtZW50O1xuICAgICAgICB9LCB7IFwiLi92ZG9tL2NyZWF0ZS1lbGVtZW50LmpzXCI6IDE1IH1dLCAyOiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge1xuICAgICAgICAgICAgdmFyIGRpZmYgPSByZXF1aXJlKFwiLi92dHJlZS9kaWZmLmpzXCIpO1xuXG4gICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IGRpZmY7XG4gICAgICAgIH0sIHsgXCIuL3Z0cmVlL2RpZmYuanNcIjogMzUgfV0sIDM6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICB2YXIgaCA9IHJlcXVpcmUoXCIuL3ZpcnR1YWwtaHlwZXJzY3JpcHQvaW5kZXguanNcIik7XG5cbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gaDtcbiAgICAgICAgfSwgeyBcIi4vdmlydHVhbC1oeXBlcnNjcmlwdC9pbmRleC5qc1wiOiAyMiB9XSwgNDogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHtcbiAgICAgICAgICAgIHZhciBkaWZmID0gcmVxdWlyZShcIi4vZGlmZi5qc1wiKTtcbiAgICAgICAgICAgIHZhciBwYXRjaCA9IHJlcXVpcmUoXCIuL3BhdGNoLmpzXCIpO1xuICAgICAgICAgICAgdmFyIGggPSByZXF1aXJlKFwiLi9oLmpzXCIpO1xuICAgICAgICAgICAgdmFyIGNyZWF0ZSA9IHJlcXVpcmUoXCIuL2NyZWF0ZS1lbGVtZW50LmpzXCIpO1xuICAgICAgICAgICAgdmFyIFZOb2RlID0gcmVxdWlyZShcIi4vdm5vZGUvdm5vZGUuanNcIik7XG4gICAgICAgICAgICB2YXIgVlRleHQgPSByZXF1aXJlKFwiLi92bm9kZS92dGV4dC5qc1wiKTtcblxuICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSB7XG4gICAgICAgICAgICAgICAgZGlmZjogZGlmZixcbiAgICAgICAgICAgICAgICBwYXRjaDogcGF0Y2gsXG4gICAgICAgICAgICAgICAgaDogaCxcbiAgICAgICAgICAgICAgICBjcmVhdGU6IGNyZWF0ZSxcbiAgICAgICAgICAgICAgICBWTm9kZTogVk5vZGUsXG4gICAgICAgICAgICAgICAgVlRleHQ6IFZUZXh0XG4gICAgICAgICAgICB9O1xuICAgICAgICB9LCB7IFwiLi9jcmVhdGUtZWxlbWVudC5qc1wiOiAxLCBcIi4vZGlmZi5qc1wiOiAyLCBcIi4vaC5qc1wiOiAzLCBcIi4vcGF0Y2guanNcIjogMTMsIFwiLi92bm9kZS92bm9kZS5qc1wiOiAzMSwgXCIuL3Zub2RlL3Z0ZXh0LmpzXCI6IDMzIH1dLCA1OiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge1xuICAgICAgICAgICAgLyohXG4gICAgICAgICAgICAgKiBDcm9zcy1Ccm93c2VyIFNwbGl0IDEuMS4xXG4gICAgICAgICAgICAgKiBDb3B5cmlnaHQgMjAwNy0yMDEyIFN0ZXZlbiBMZXZpdGhhbiA8c3RldmVubGV2aXRoYW4uY29tPlxuICAgICAgICAgICAgICogQXZhaWxhYmxlIHVuZGVyIHRoZSBNSVQgTGljZW5zZVxuICAgICAgICAgICAgICogRUNNQVNjcmlwdCBjb21wbGlhbnQsIHVuaWZvcm0gY3Jvc3MtYnJvd3NlciBzcGxpdCBtZXRob2RcbiAgICAgICAgICAgICAqL1xuXG4gICAgICAgICAgICAvKipcbiAgICAgICAgICAgICAqIFNwbGl0cyBhIHN0cmluZyBpbnRvIGFuIGFycmF5IG9mIHN0cmluZ3MgdXNpbmcgYSByZWdleCBvciBzdHJpbmcgc2VwYXJhdG9yLiBNYXRjaGVzIG9mIHRoZVxuICAgICAgICAgICAgICogc2VwYXJhdG9yIGFyZSBub3QgaW5jbHVkZWQgaW4gdGhlIHJlc3VsdCBhcnJheS4gSG93ZXZlciwgaWYgYHNlcGFyYXRvcmAgaXMgYSByZWdleCB0aGF0IGNvbnRhaW5zXG4gICAgICAgICAgICAgKiBjYXB0dXJpbmcgZ3JvdXBzLCBiYWNrcmVmZXJlbmNlcyBhcmUgc3BsaWNlZCBpbnRvIHRoZSByZXN1bHQgZWFjaCB0aW1lIGBzZXBhcmF0b3JgIGlzIG1hdGNoZWQuXG4gICAgICAgICAgICAgKiBGaXhlcyBicm93c2VyIGJ1Z3MgY29tcGFyZWQgdG8gdGhlIG5hdGl2ZSBgU3RyaW5nLnByb3RvdHlwZS5zcGxpdGAgYW5kIGNhbiBiZSB1c2VkIHJlbGlhYmx5XG4gICAgICAgICAgICAgKiBjcm9zcy1icm93c2VyLlxuICAgICAgICAgICAgICogQHBhcmFtIHtTdHJpbmd9IHN0ciBTdHJpbmcgdG8gc3BsaXQuXG4gICAgICAgICAgICAgKiBAcGFyYW0ge1JlZ0V4cHxTdHJpbmd9IHNlcGFyYXRvciBSZWdleCBvciBzdHJpbmcgdG8gdXNlIGZvciBzZXBhcmF0aW5nIHRoZSBzdHJpbmcuXG4gICAgICAgICAgICAgKiBAcGFyYW0ge051bWJlcn0gW2xpbWl0XSBNYXhpbXVtIG51bWJlciBvZiBpdGVtcyB0byBpbmNsdWRlIGluIHRoZSByZXN1bHQgYXJyYXkuXG4gICAgICAgICAgICAgKiBAcmV0dXJucyB7QXJyYXl9IEFycmF5IG9mIHN1YnN0cmluZ3MuXG4gICAgICAgICAgICAgKiBAZXhhbXBsZVxuICAgICAgICAgICAgICpcbiAgICAgICAgICAgICAqIC8vIEJhc2ljIHVzZVxuICAgICAgICAgICAgICogc3BsaXQoJ2EgYiBjIGQnLCAnICcpO1xuICAgICAgICAgICAgICogLy8gLT4gWydhJywgJ2InLCAnYycsICdkJ11cbiAgICAgICAgICAgICAqXG4gICAgICAgICAgICAgKiAvLyBXaXRoIGxpbWl0XG4gICAgICAgICAgICAgKiBzcGxpdCgnYSBiIGMgZCcsICcgJywgMik7XG4gICAgICAgICAgICAgKiAvLyAtPiBbJ2EnLCAnYiddXG4gICAgICAgICAgICAgKlxuICAgICAgICAgICAgICogLy8gQmFja3JlZmVyZW5jZXMgaW4gcmVzdWx0IGFycmF5XG4gICAgICAgICAgICAgKiBzcGxpdCgnLi53b3JkMSB3b3JkMi4uJywgLyhbYS16XSspKFxcZCspL2kpO1xuICAgICAgICAgICAgICogLy8gLT4gWycuLicsICd3b3JkJywgJzEnLCAnICcsICd3b3JkJywgJzInLCAnLi4nXVxuICAgICAgICAgICAgICovXG4gICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IChmdW5jdGlvbiBzcGxpdCh1bmRlZikge1xuXG4gICAgICAgICAgICAgICAgdmFyIG5hdGl2ZVNwbGl0ID0gU3RyaW5nLnByb3RvdHlwZS5zcGxpdCxcbiAgICAgICAgICAgICAgICAgICAgY29tcGxpYW50RXhlY05wY2cgPSAvKCk/Py8uZXhlYyhcIlwiKVsxXSA9PT0gdW5kZWYsXG5cbiAgICAgICAgICAgICAgICAvLyBOUENHOiBub25wYXJ0aWNpcGF0aW5nIGNhcHR1cmluZyBncm91cFxuICAgICAgICAgICAgICAgIHNlbGY7XG5cbiAgICAgICAgICAgICAgICBzZWxmID0gZnVuY3Rpb24gKHN0ciwgc2VwYXJhdG9yLCBsaW1pdCkge1xuICAgICAgICAgICAgICAgICAgICAvLyBJZiBgc2VwYXJhdG9yYCBpcyBub3QgYSByZWdleCwgdXNlIGBuYXRpdmVTcGxpdGBcbiAgICAgICAgICAgICAgICAgICAgaWYgKE9iamVjdC5wcm90b3R5cGUudG9TdHJpbmcuY2FsbChzZXBhcmF0b3IpICE9PSBcIltvYmplY3QgUmVnRXhwXVwiKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gbmF0aXZlU3BsaXQuY2FsbChzdHIsIHNlcGFyYXRvciwgbGltaXQpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIHZhciBvdXRwdXQgPSBbXSxcbiAgICAgICAgICAgICAgICAgICAgICAgIGZsYWdzID0gKHNlcGFyYXRvci5pZ25vcmVDYXNlID8gXCJpXCIgOiBcIlwiKSArIChzZXBhcmF0b3IubXVsdGlsaW5lID8gXCJtXCIgOiBcIlwiKSArIChzZXBhcmF0b3IuZXh0ZW5kZWQgPyBcInhcIiA6IFwiXCIpICsgKHNlcGFyYXRvci5zdGlja3kgPyBcInlcIiA6IFwiXCIpLFxuXG4gICAgICAgICAgICAgICAgICAgIC8vIEZpcmVmb3ggMytcbiAgICAgICAgICAgICAgICAgICAgbGFzdExhc3RJbmRleCA9IDAsXG5cbiAgICAgICAgICAgICAgICAgICAgLy8gTWFrZSBgZ2xvYmFsYCBhbmQgYXZvaWQgYGxhc3RJbmRleGAgaXNzdWVzIGJ5IHdvcmtpbmcgd2l0aCBhIGNvcHlcbiAgICAgICAgICAgICAgICAgICAgc2VwYXJhdG9yID0gbmV3IFJlZ0V4cChzZXBhcmF0b3Iuc291cmNlLCBmbGFncyArIFwiZ1wiKSxcbiAgICAgICAgICAgICAgICAgICAgICAgIHNlcGFyYXRvcjIsXG4gICAgICAgICAgICAgICAgICAgICAgICBtYXRjaCxcbiAgICAgICAgICAgICAgICAgICAgICAgIGxhc3RJbmRleCxcbiAgICAgICAgICAgICAgICAgICAgICAgIGxhc3RMZW5ndGg7XG4gICAgICAgICAgICAgICAgICAgIHN0ciArPSBcIlwiOyAvLyBUeXBlLWNvbnZlcnRcbiAgICAgICAgICAgICAgICAgICAgaWYgKCFjb21wbGlhbnRFeGVjTnBjZykge1xuICAgICAgICAgICAgICAgICAgICAgICAgLy8gRG9lc24ndCBuZWVkIGZsYWdzIGd5LCBidXQgdGhleSBkb24ndCBodXJ0XG4gICAgICAgICAgICAgICAgICAgICAgICBzZXBhcmF0b3IyID0gbmV3IFJlZ0V4cChcIl5cIiArIHNlcGFyYXRvci5zb3VyY2UgKyBcIiQoPyFcXFxccylcIiwgZmxhZ3MpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIC8qIFZhbHVlcyBmb3IgYGxpbWl0YCwgcGVyIHRoZSBzcGVjOlxuICAgICAgICAgICAgICAgICAgICAgKiBJZiB1bmRlZmluZWQ6IDQyOTQ5NjcyOTUgLy8gTWF0aC5wb3coMiwgMzIpIC0gMVxuICAgICAgICAgICAgICAgICAgICAgKiBJZiAwLCBJbmZpbml0eSwgb3IgTmFOOiAwXG4gICAgICAgICAgICAgICAgICAgICAqIElmIHBvc2l0aXZlIG51bWJlcjogbGltaXQgPSBNYXRoLmZsb29yKGxpbWl0KTsgaWYgKGxpbWl0ID4gNDI5NDk2NzI5NSkgbGltaXQgLT0gNDI5NDk2NzI5NjtcbiAgICAgICAgICAgICAgICAgICAgICogSWYgbmVnYXRpdmUgbnVtYmVyOiA0Mjk0OTY3Mjk2IC0gTWF0aC5mbG9vcihNYXRoLmFicyhsaW1pdCkpXG4gICAgICAgICAgICAgICAgICAgICAqIElmIG90aGVyOiBUeXBlLWNvbnZlcnQsIHRoZW4gdXNlIHRoZSBhYm92ZSBydWxlc1xuICAgICAgICAgICAgICAgICAgICAgKi9cbiAgICAgICAgICAgICAgICAgICAgbGltaXQgPSBsaW1pdCA9PT0gdW5kZWYgPyAtMSA+Pj4gMCA6IC8vIE1hdGgucG93KDIsIDMyKSAtIDFcbiAgICAgICAgICAgICAgICAgICAgbGltaXQgPj4+IDA7IC8vIFRvVWludDMyKGxpbWl0KVxuICAgICAgICAgICAgICAgICAgICB3aGlsZSAobWF0Y2ggPSBzZXBhcmF0b3IuZXhlYyhzdHIpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAvLyBgc2VwYXJhdG9yLmxhc3RJbmRleGAgaXMgbm90IHJlbGlhYmxlIGNyb3NzLWJyb3dzZXJcbiAgICAgICAgICAgICAgICAgICAgICAgIGxhc3RJbmRleCA9IG1hdGNoLmluZGV4ICsgbWF0Y2hbMF0ubGVuZ3RoO1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGxhc3RJbmRleCA+IGxhc3RMYXN0SW5kZXgpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBvdXRwdXQucHVzaChzdHIuc2xpY2UobGFzdExhc3RJbmRleCwgbWF0Y2guaW5kZXgpKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBGaXggYnJvd3NlcnMgd2hvc2UgYGV4ZWNgIG1ldGhvZHMgZG9uJ3QgY29uc2lzdGVudGx5IHJldHVybiBgdW5kZWZpbmVkYCBmb3JcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBub25wYXJ0aWNpcGF0aW5nIGNhcHR1cmluZyBncm91cHNcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoIWNvbXBsaWFudEV4ZWNOcGNnICYmIG1hdGNoLmxlbmd0aCA+IDEpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbWF0Y2hbMF0ucmVwbGFjZShzZXBhcmF0b3IyLCBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBmb3IgKHZhciBpID0gMTsgaSA8IGFyZ3VtZW50cy5sZW5ndGggLSAyOyBpKyspIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoYXJndW1lbnRzW2ldID09PSB1bmRlZikge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBtYXRjaFtpXSA9IHVuZGVmO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChtYXRjaC5sZW5ndGggPiAxICYmIG1hdGNoLmluZGV4IDwgc3RyLmxlbmd0aCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBBcnJheS5wcm90b3R5cGUucHVzaC5hcHBseShvdXRwdXQsIG1hdGNoLnNsaWNlKDEpKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgbGFzdExlbmd0aCA9IG1hdGNoWzBdLmxlbmd0aDtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBsYXN0TGFzdEluZGV4ID0gbGFzdEluZGV4O1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChvdXRwdXQubGVuZ3RoID49IGxpbWl0KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChzZXBhcmF0b3IubGFzdEluZGV4ID09PSBtYXRjaC5pbmRleCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNlcGFyYXRvci5sYXN0SW5kZXgrKzsgLy8gQXZvaWQgYW4gaW5maW5pdGUgbG9vcFxuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIGlmIChsYXN0TGFzdEluZGV4ID09PSBzdHIubGVuZ3RoKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAobGFzdExlbmd0aCB8fCAhc2VwYXJhdG9yLnRlc3QoXCJcIikpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBvdXRwdXQucHVzaChcIlwiKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIG91dHB1dC5wdXNoKHN0ci5zbGljZShsYXN0TGFzdEluZGV4KSk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIG91dHB1dC5sZW5ndGggPiBsaW1pdCA/IG91dHB1dC5zbGljZSgwLCBsaW1pdCkgOiBvdXRwdXQ7XG4gICAgICAgICAgICAgICAgfTtcblxuICAgICAgICAgICAgICAgIHJldHVybiBzZWxmO1xuICAgICAgICAgICAgfSkoKTtcbiAgICAgICAgfSwge31dLCA2OiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge30sIHt9XSwgNzogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHtcbiAgICAgICAgICAgIFwidXNlIHN0cmljdFwiO1xuXG4gICAgICAgICAgICB2YXIgT25lVmVyc2lvbkNvbnN0cmFpbnQgPSByZXF1aXJlKFwiaW5kaXZpZHVhbC9vbmUtdmVyc2lvblwiKTtcblxuICAgICAgICAgICAgdmFyIE1ZX1ZFUlNJT04gPSBcIjdcIjtcbiAgICAgICAgICAgIE9uZVZlcnNpb25Db25zdHJhaW50KFwiZXYtc3RvcmVcIiwgTVlfVkVSU0lPTik7XG5cbiAgICAgICAgICAgIHZhciBoYXNoS2V5ID0gXCJfX0VWX1NUT1JFX0tFWUBcIiArIE1ZX1ZFUlNJT047XG5cbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gRXZTdG9yZTtcblxuICAgICAgICAgICAgZnVuY3Rpb24gRXZTdG9yZShlbGVtKSB7XG4gICAgICAgICAgICAgICAgdmFyIGhhc2ggPSBlbGVtW2hhc2hLZXldO1xuXG4gICAgICAgICAgICAgICAgaWYgKCFoYXNoKSB7XG4gICAgICAgICAgICAgICAgICAgIGhhc2ggPSBlbGVtW2hhc2hLZXldID0ge307XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgcmV0dXJuIGhhc2g7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0sIHsgXCJpbmRpdmlkdWFsL29uZS12ZXJzaW9uXCI6IDkgfV0sIDg6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICAoZnVuY3Rpb24gKGdsb2JhbCkge1xuICAgICAgICAgICAgICAgIFwidXNlIHN0cmljdFwiO1xuXG4gICAgICAgICAgICAgICAgLypnbG9iYWwgd2luZG93LCBnbG9iYWwqL1xuXG4gICAgICAgICAgICAgICAgdmFyIHJvb3QgPSB0eXBlb2Ygd2luZG93ICE9PSBcInVuZGVmaW5lZFwiID8gd2luZG93IDogdHlwZW9mIGdsb2JhbCAhPT0gXCJ1bmRlZmluZWRcIiA/IGdsb2JhbCA6IHt9O1xuXG4gICAgICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBJbmRpdmlkdWFsO1xuXG4gICAgICAgICAgICAgICAgZnVuY3Rpb24gSW5kaXZpZHVhbChrZXksIHZhbHVlKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmIChrZXkgaW4gcm9vdCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHJvb3Rba2V5XTtcbiAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgIHJvb3Rba2V5XSA9IHZhbHVlO1xuXG4gICAgICAgICAgICAgICAgICAgIHJldHVybiB2YWx1ZTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9KS5jYWxsKHRoaXMsIHR5cGVvZiBnbG9iYWwgIT09IFwidW5kZWZpbmVkXCIgPyBnbG9iYWwgOiB0eXBlb2Ygc2VsZiAhPT0gXCJ1bmRlZmluZWRcIiA/IHNlbGYgOiB0eXBlb2Ygd2luZG93ICE9PSBcInVuZGVmaW5lZFwiID8gd2luZG93IDoge30pO1xuICAgICAgICB9LCB7fV0sIDk6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICBcInVzZSBzdHJpY3RcIjtcblxuICAgICAgICAgICAgdmFyIEluZGl2aWR1YWwgPSByZXF1aXJlKFwiLi9pbmRleC5qc1wiKTtcblxuICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBPbmVWZXJzaW9uO1xuXG4gICAgICAgICAgICBmdW5jdGlvbiBPbmVWZXJzaW9uKG1vZHVsZU5hbWUsIHZlcnNpb24sIGRlZmF1bHRWYWx1ZSkge1xuICAgICAgICAgICAgICAgIHZhciBrZXkgPSBcIl9fSU5ESVZJRFVBTF9PTkVfVkVSU0lPTl9cIiArIG1vZHVsZU5hbWU7XG4gICAgICAgICAgICAgICAgdmFyIGVuZm9yY2VLZXkgPSBrZXkgKyBcIl9FTkZPUkNFX1NJTkdMRVRPTlwiO1xuXG4gICAgICAgICAgICAgICAgdmFyIHZlcnNpb25WYWx1ZSA9IEluZGl2aWR1YWwoZW5mb3JjZUtleSwgdmVyc2lvbik7XG5cbiAgICAgICAgICAgICAgICBpZiAodmVyc2lvblZhbHVlICE9PSB2ZXJzaW9uKSB7XG4gICAgICAgICAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcihcIkNhbiBvbmx5IGhhdmUgb25lIGNvcHkgb2YgXCIgKyBtb2R1bGVOYW1lICsgXCIuXFxuXCIgKyBcIllvdSBhbHJlYWR5IGhhdmUgdmVyc2lvbiBcIiArIHZlcnNpb25WYWx1ZSArIFwiIGluc3RhbGxlZC5cXG5cIiArIFwiVGhpcyBtZWFucyB5b3UgY2Fubm90IGluc3RhbGwgdmVyc2lvbiBcIiArIHZlcnNpb24pO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHJldHVybiBJbmRpdmlkdWFsKGtleSwgZGVmYXVsdFZhbHVlKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSwgeyBcIi4vaW5kZXguanNcIjogOCB9XSwgMTA6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICAoZnVuY3Rpb24gKGdsb2JhbCkge1xuICAgICAgICAgICAgICAgIHZhciB0b3BMZXZlbCA9IHR5cGVvZiBnbG9iYWwgIT09IFwidW5kZWZpbmVkXCIgPyBnbG9iYWwgOiB0eXBlb2Ygd2luZG93ICE9PSBcInVuZGVmaW5lZFwiID8gd2luZG93IDoge307XG4gICAgICAgICAgICAgICAgdmFyIG1pbkRvYyA9IHJlcXVpcmUoXCJtaW4tZG9jdW1lbnRcIik7XG5cbiAgICAgICAgICAgICAgICBpZiAodHlwZW9mIGRvY3VtZW50ICE9PSBcInVuZGVmaW5lZFwiKSB7XG4gICAgICAgICAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gZG9jdW1lbnQ7XG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgdmFyIGRvY2N5ID0gdG9wTGV2ZWxbXCJfX0dMT0JBTF9ET0NVTUVOVF9DQUNIRUA0XCJdO1xuXG4gICAgICAgICAgICAgICAgICAgIGlmICghZG9jY3kpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGRvY2N5ID0gdG9wTGV2ZWxbXCJfX0dMT0JBTF9ET0NVTUVOVF9DQUNIRUA0XCJdID0gbWluRG9jO1xuICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBkb2NjeTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9KS5jYWxsKHRoaXMsIHR5cGVvZiBnbG9iYWwgIT09IFwidW5kZWZpbmVkXCIgPyBnbG9iYWwgOiB0eXBlb2Ygc2VsZiAhPT0gXCJ1bmRlZmluZWRcIiA/IHNlbGYgOiB0eXBlb2Ygd2luZG93ICE9PSBcInVuZGVmaW5lZFwiID8gd2luZG93IDoge30pO1xuICAgICAgICB9LCB7IFwibWluLWRvY3VtZW50XCI6IDYgfV0sIDExOiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge1xuICAgICAgICAgICAgXCJ1c2Ugc3RyaWN0XCI7XG5cbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gaXNPYmplY3QoeCkge1xuICAgICAgICAgICAgICAgIHJldHVybiB0eXBlb2YgeCA9PT0gXCJvYmplY3RcIiAmJiB4ICE9PSBudWxsO1xuICAgICAgICAgICAgfTtcbiAgICAgICAgfSwge31dLCAxMjogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHtcbiAgICAgICAgICAgIHZhciBuYXRpdmVJc0FycmF5ID0gQXJyYXkuaXNBcnJheTtcbiAgICAgICAgICAgIHZhciB0b1N0cmluZyA9IE9iamVjdC5wcm90b3R5cGUudG9TdHJpbmc7XG5cbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gbmF0aXZlSXNBcnJheSB8fCBpc0FycmF5O1xuXG4gICAgICAgICAgICBmdW5jdGlvbiBpc0FycmF5KG9iaikge1xuICAgICAgICAgICAgICAgIHJldHVybiB0b1N0cmluZy5jYWxsKG9iaikgPT09IFwiW29iamVjdCBBcnJheV1cIjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSwge31dLCAxMzogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHtcbiAgICAgICAgICAgIHZhciBwYXRjaCA9IHJlcXVpcmUoXCIuL3Zkb20vcGF0Y2guanNcIik7XG5cbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gcGF0Y2g7XG4gICAgICAgIH0sIHsgXCIuL3Zkb20vcGF0Y2guanNcIjogMTggfV0sIDE0OiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge1xuICAgICAgICAgICAgdmFyIGlzT2JqZWN0ID0gcmVxdWlyZShcImlzLW9iamVjdFwiKTtcbiAgICAgICAgICAgIHZhciBpc0hvb2sgPSByZXF1aXJlKFwiLi4vdm5vZGUvaXMtdmhvb2suanNcIik7XG5cbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gYXBwbHlQcm9wZXJ0aWVzO1xuXG4gICAgICAgICAgICBmdW5jdGlvbiBhcHBseVByb3BlcnRpZXMobm9kZSwgcHJvcHMsIHByZXZpb3VzKSB7XG4gICAgICAgICAgICAgICAgZm9yICh2YXIgcHJvcE5hbWUgaW4gcHJvcHMpIHtcbiAgICAgICAgICAgICAgICAgICAgdmFyIHByb3BWYWx1ZSA9IHByb3BzW3Byb3BOYW1lXTtcblxuICAgICAgICAgICAgICAgICAgICBpZiAocHJvcFZhbHVlID09PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJlbW92ZVByb3BlcnR5KG5vZGUsIHByb3BOYW1lLCBwcm9wVmFsdWUsIHByZXZpb3VzKTtcbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIGlmIChpc0hvb2socHJvcFZhbHVlKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgcmVtb3ZlUHJvcGVydHkobm9kZSwgcHJvcE5hbWUsIHByb3BWYWx1ZSwgcHJldmlvdXMpO1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHByb3BWYWx1ZS5ob29rKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcHJvcFZhbHVlLmhvb2sobm9kZSwgcHJvcE5hbWUsIHByZXZpb3VzID8gcHJldmlvdXNbcHJvcE5hbWVdIDogdW5kZWZpbmVkKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChpc09iamVjdChwcm9wVmFsdWUpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcGF0Y2hPYmplY3Qobm9kZSwgcHJvcHMsIHByZXZpb3VzLCBwcm9wTmFtZSwgcHJvcFZhbHVlKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgbm9kZVtwcm9wTmFtZV0gPSBwcm9wVmFsdWU7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIHJlbW92ZVByb3BlcnR5KG5vZGUsIHByb3BOYW1lLCBwcm9wVmFsdWUsIHByZXZpb3VzKSB7XG4gICAgICAgICAgICAgICAgaWYgKHByZXZpb3VzKSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciBwcmV2aW91c1ZhbHVlID0gcHJldmlvdXNbcHJvcE5hbWVdO1xuXG4gICAgICAgICAgICAgICAgICAgIGlmICghaXNIb29rKHByZXZpb3VzVmFsdWUpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAocHJvcE5hbWUgPT09IFwiYXR0cmlidXRlc1wiKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgZm9yICh2YXIgYXR0ck5hbWUgaW4gcHJldmlvdXNWYWx1ZSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBub2RlLnJlbW92ZUF0dHJpYnV0ZShhdHRyTmFtZSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIGlmIChwcm9wTmFtZSA9PT0gXCJzdHlsZVwiKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgZm9yICh2YXIgaSBpbiBwcmV2aW91c1ZhbHVlKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG5vZGUuc3R5bGVbaV0gPSBcIlwiO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAodHlwZW9mIHByZXZpb3VzVmFsdWUgPT09IFwic3RyaW5nXCIpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBub2RlW3Byb3BOYW1lXSA9IFwiXCI7XG4gICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIG5vZGVbcHJvcE5hbWVdID0gbnVsbDtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIGlmIChwcmV2aW91c1ZhbHVlLnVuaG9vaykge1xuICAgICAgICAgICAgICAgICAgICAgICAgcHJldmlvdXNWYWx1ZS51bmhvb2sobm9kZSwgcHJvcE5hbWUsIHByb3BWYWx1ZSk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIHBhdGNoT2JqZWN0KG5vZGUsIHByb3BzLCBwcmV2aW91cywgcHJvcE5hbWUsIHByb3BWYWx1ZSkge1xuICAgICAgICAgICAgICAgIHZhciBwcmV2aW91c1ZhbHVlID0gcHJldmlvdXMgPyBwcmV2aW91c1twcm9wTmFtZV0gOiB1bmRlZmluZWQ7XG5cbiAgICAgICAgICAgICAgICAvLyBTZXQgYXR0cmlidXRlc1xuICAgICAgICAgICAgICAgIGlmIChwcm9wTmFtZSA9PT0gXCJhdHRyaWJ1dGVzXCIpIHtcbiAgICAgICAgICAgICAgICAgICAgZm9yICh2YXIgYXR0ck5hbWUgaW4gcHJvcFZhbHVlKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICB2YXIgYXR0clZhbHVlID0gcHJvcFZhbHVlW2F0dHJOYW1lXTtcblxuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGF0dHJWYWx1ZSA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgbm9kZS5yZW1vdmVBdHRyaWJ1dGUoYXR0ck5hbWUpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBub2RlLnNldEF0dHJpYnV0ZShhdHRyTmFtZSwgYXR0clZhbHVlKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICBpZiAocHJldmlvdXNWYWx1ZSAmJiBpc09iamVjdChwcmV2aW91c1ZhbHVlKSAmJiBnZXRQcm90b3R5cGUocHJldmlvdXNWYWx1ZSkgIT09IGdldFByb3RvdHlwZShwcm9wVmFsdWUpKSB7XG4gICAgICAgICAgICAgICAgICAgIG5vZGVbcHJvcE5hbWVdID0gcHJvcFZhbHVlO1xuICAgICAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgaWYgKCFpc09iamVjdChub2RlW3Byb3BOYW1lXSkpIHtcbiAgICAgICAgICAgICAgICAgICAgbm9kZVtwcm9wTmFtZV0gPSB7fTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICB2YXIgcmVwbGFjZXIgPSBwcm9wTmFtZSA9PT0gXCJzdHlsZVwiID8gXCJcIiA6IHVuZGVmaW5lZDtcblxuICAgICAgICAgICAgICAgIGZvciAodmFyIGsgaW4gcHJvcFZhbHVlKSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciB2YWx1ZSA9IHByb3BWYWx1ZVtrXTtcbiAgICAgICAgICAgICAgICAgICAgbm9kZVtwcm9wTmFtZV1ba10gPSB2YWx1ZSA9PT0gdW5kZWZpbmVkID8gcmVwbGFjZXIgOiB2YWx1ZTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIGdldFByb3RvdHlwZSh2YWx1ZSkge1xuICAgICAgICAgICAgICAgIGlmIChPYmplY3QuZ2V0UHJvdG90eXBlT2YpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIE9iamVjdC5nZXRQcm90b3R5cGVPZih2YWx1ZSk7XG4gICAgICAgICAgICAgICAgfSBlbHNlIGlmICh2YWx1ZS5fX3Byb3RvX18pIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHZhbHVlLl9fcHJvdG9fXztcbiAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKHZhbHVlLmNvbnN0cnVjdG9yKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiB2YWx1ZS5jb25zdHJ1Y3Rvci5wcm90b3R5cGU7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9LCB7IFwiLi4vdm5vZGUvaXMtdmhvb2suanNcIjogMjYsIFwiaXMtb2JqZWN0XCI6IDExIH1dLCAxNTogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHtcbiAgICAgICAgICAgIHZhciBkb2N1bWVudCA9IHJlcXVpcmUoXCJnbG9iYWwvZG9jdW1lbnRcIik7XG5cbiAgICAgICAgICAgIHZhciBhcHBseVByb3BlcnRpZXMgPSByZXF1aXJlKFwiLi9hcHBseS1wcm9wZXJ0aWVzXCIpO1xuXG4gICAgICAgICAgICB2YXIgaXNWTm9kZSA9IHJlcXVpcmUoXCIuLi92bm9kZS9pcy12bm9kZS5qc1wiKTtcbiAgICAgICAgICAgIHZhciBpc1ZUZXh0ID0gcmVxdWlyZShcIi4uL3Zub2RlL2lzLXZ0ZXh0LmpzXCIpO1xuICAgICAgICAgICAgdmFyIGlzV2lkZ2V0ID0gcmVxdWlyZShcIi4uL3Zub2RlL2lzLXdpZGdldC5qc1wiKTtcbiAgICAgICAgICAgIHZhciBoYW5kbGVUaHVuayA9IHJlcXVpcmUoXCIuLi92bm9kZS9oYW5kbGUtdGh1bmsuanNcIik7XG5cbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gY3JlYXRlRWxlbWVudDtcblxuICAgICAgICAgICAgZnVuY3Rpb24gY3JlYXRlRWxlbWVudCh2bm9kZSwgb3B0cykge1xuICAgICAgICAgICAgICAgIHZhciBkb2MgPSBvcHRzID8gb3B0cy5kb2N1bWVudCB8fCBkb2N1bWVudCA6IGRvY3VtZW50O1xuICAgICAgICAgICAgICAgIHZhciB3YXJuID0gb3B0cyA/IG9wdHMud2FybiA6IG51bGw7XG5cbiAgICAgICAgICAgICAgICB2bm9kZSA9IGhhbmRsZVRodW5rKHZub2RlKS5hO1xuXG4gICAgICAgICAgICAgICAgaWYgKGlzV2lkZ2V0KHZub2RlKSkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gdm5vZGUuaW5pdCgpO1xuICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoaXNWVGV4dCh2bm9kZSkpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGRvYy5jcmVhdGVUZXh0Tm9kZSh2bm9kZS50ZXh0KTtcbiAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKCFpc1ZOb2RlKHZub2RlKSkge1xuICAgICAgICAgICAgICAgICAgICBpZiAod2Fybikge1xuICAgICAgICAgICAgICAgICAgICAgICAgd2FybihcIkl0ZW0gaXMgbm90IGEgdmFsaWQgdmlydHVhbCBkb20gbm9kZVwiLCB2bm9kZSk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIG51bGw7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgdmFyIG5vZGUgPSB2bm9kZS5uYW1lc3BhY2UgPT09IG51bGwgPyBkb2MuY3JlYXRlRWxlbWVudCh2bm9kZS50YWdOYW1lKSA6IGRvYy5jcmVhdGVFbGVtZW50TlModm5vZGUubmFtZXNwYWNlLCB2bm9kZS50YWdOYW1lKTtcblxuICAgICAgICAgICAgICAgIHZhciBwcm9wcyA9IHZub2RlLnByb3BlcnRpZXM7XG4gICAgICAgICAgICAgICAgYXBwbHlQcm9wZXJ0aWVzKG5vZGUsIHByb3BzKTtcblxuICAgICAgICAgICAgICAgIHZhciBjaGlsZHJlbiA9IHZub2RlLmNoaWxkcmVuO1xuXG4gICAgICAgICAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCBjaGlsZHJlbi5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgICAgICAgICB2YXIgY2hpbGROb2RlID0gY3JlYXRlRWxlbWVudChjaGlsZHJlbltpXSwgb3B0cyk7XG4gICAgICAgICAgICAgICAgICAgIGlmIChjaGlsZE5vZGUpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIG5vZGUuYXBwZW5kQ2hpbGQoY2hpbGROb2RlKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHJldHVybiBub2RlO1xuICAgICAgICAgICAgfVxuICAgICAgICB9LCB7IFwiLi4vdm5vZGUvaGFuZGxlLXRodW5rLmpzXCI6IDI0LCBcIi4uL3Zub2RlL2lzLXZub2RlLmpzXCI6IDI3LCBcIi4uL3Zub2RlL2lzLXZ0ZXh0LmpzXCI6IDI4LCBcIi4uL3Zub2RlL2lzLXdpZGdldC5qc1wiOiAyOSwgXCIuL2FwcGx5LXByb3BlcnRpZXNcIjogMTQsIFwiZ2xvYmFsL2RvY3VtZW50XCI6IDEwIH1dLCAxNjogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHtcbiAgICAgICAgICAgIC8vIE1hcHMgYSB2aXJ0dWFsIERPTSB0cmVlIG9udG8gYSByZWFsIERPTSB0cmVlIGluIGFuIGVmZmljaWVudCBtYW5uZXIuXG4gICAgICAgICAgICAvLyBXZSBkb24ndCB3YW50IHRvIHJlYWQgYWxsIG9mIHRoZSBET00gbm9kZXMgaW4gdGhlIHRyZWUgc28gd2UgdXNlXG4gICAgICAgICAgICAvLyB0aGUgaW4tb3JkZXIgdHJlZSBpbmRleGluZyB0byBlbGltaW5hdGUgcmVjdXJzaW9uIGRvd24gY2VydGFpbiBicmFuY2hlcy5cbiAgICAgICAgICAgIC8vIFdlIG9ubHkgcmVjdXJzZSBpbnRvIGEgRE9NIG5vZGUgaWYgd2Uga25vdyB0aGF0IGl0IGNvbnRhaW5zIGEgY2hpbGQgb2ZcbiAgICAgICAgICAgIC8vIGludGVyZXN0LlxuXG4gICAgICAgICAgICB2YXIgbm9DaGlsZCA9IHt9O1xuXG4gICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IGRvbUluZGV4O1xuXG4gICAgICAgICAgICBmdW5jdGlvbiBkb21JbmRleChyb290Tm9kZSwgdHJlZSwgaW5kaWNlcywgbm9kZXMpIHtcbiAgICAgICAgICAgICAgICBpZiAoIWluZGljZXMgfHwgaW5kaWNlcy5sZW5ndGggPT09IDApIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHt9O1xuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIGluZGljZXMuc29ydChhc2NlbmRpbmcpO1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gcmVjdXJzZShyb290Tm9kZSwgdHJlZSwgaW5kaWNlcywgbm9kZXMsIDApO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZnVuY3Rpb24gcmVjdXJzZShyb290Tm9kZSwgdHJlZSwgaW5kaWNlcywgbm9kZXMsIHJvb3RJbmRleCkge1xuICAgICAgICAgICAgICAgIG5vZGVzID0gbm9kZXMgfHwge307XG5cbiAgICAgICAgICAgICAgICBpZiAocm9vdE5vZGUpIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKGluZGV4SW5SYW5nZShpbmRpY2VzLCByb290SW5kZXgsIHJvb3RJbmRleCkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIG5vZGVzW3Jvb3RJbmRleF0gPSByb290Tm9kZTtcbiAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgIHZhciB2Q2hpbGRyZW4gPSB0cmVlLmNoaWxkcmVuO1xuXG4gICAgICAgICAgICAgICAgICAgIGlmICh2Q2hpbGRyZW4pIHtcblxuICAgICAgICAgICAgICAgICAgICAgICAgdmFyIGNoaWxkTm9kZXMgPSByb290Tm9kZS5jaGlsZE5vZGVzO1xuXG4gICAgICAgICAgICAgICAgICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IHRyZWUuY2hpbGRyZW4ubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICByb290SW5kZXggKz0gMTtcblxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZhciB2Q2hpbGQgPSB2Q2hpbGRyZW5baV0gfHwgbm9DaGlsZDtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB2YXIgbmV4dEluZGV4ID0gcm9vdEluZGV4ICsgKHZDaGlsZC5jb3VudCB8fCAwKTtcblxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIHNraXAgcmVjdXJzaW9uIGRvd24gdGhlIHRyZWUgaWYgdGhlcmUgYXJlIG5vIG5vZGVzIGRvd24gaGVyZVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChpbmRleEluUmFuZ2UoaW5kaWNlcywgcm9vdEluZGV4LCBuZXh0SW5kZXgpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlY3Vyc2UoY2hpbGROb2Rlc1tpXSwgdkNoaWxkLCBpbmRpY2VzLCBub2Rlcywgcm9vdEluZGV4KTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICByb290SW5kZXggPSBuZXh0SW5kZXg7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICByZXR1cm4gbm9kZXM7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIC8vIEJpbmFyeSBzZWFyY2ggZm9yIGFuIGluZGV4IGluIHRoZSBpbnRlcnZhbCBbbGVmdCwgcmlnaHRdXG4gICAgICAgICAgICBmdW5jdGlvbiBpbmRleEluUmFuZ2UoaW5kaWNlcywgbGVmdCwgcmlnaHQpIHtcbiAgICAgICAgICAgICAgICBpZiAoaW5kaWNlcy5sZW5ndGggPT09IDApIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHZhciBtaW5JbmRleCA9IDA7XG4gICAgICAgICAgICAgICAgdmFyIG1heEluZGV4ID0gaW5kaWNlcy5sZW5ndGggLSAxO1xuICAgICAgICAgICAgICAgIHZhciBjdXJyZW50SW5kZXg7XG4gICAgICAgICAgICAgICAgdmFyIGN1cnJlbnRJdGVtO1xuXG4gICAgICAgICAgICAgICAgd2hpbGUgKG1pbkluZGV4IDw9IG1heEluZGV4KSB7XG4gICAgICAgICAgICAgICAgICAgIGN1cnJlbnRJbmRleCA9IChtYXhJbmRleCArIG1pbkluZGV4KSAvIDIgPj4gMDtcbiAgICAgICAgICAgICAgICAgICAgY3VycmVudEl0ZW0gPSBpbmRpY2VzW2N1cnJlbnRJbmRleF07XG5cbiAgICAgICAgICAgICAgICAgICAgaWYgKG1pbkluZGV4ID09PSBtYXhJbmRleCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGN1cnJlbnRJdGVtID49IGxlZnQgJiYgY3VycmVudEl0ZW0gPD0gcmlnaHQ7XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoY3VycmVudEl0ZW0gPCBsZWZ0KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBtaW5JbmRleCA9IGN1cnJlbnRJbmRleCArIDE7XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoY3VycmVudEl0ZW0gPiByaWdodCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgbWF4SW5kZXggPSBjdXJyZW50SW5kZXggLSAxO1xuICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIGFzY2VuZGluZyhhLCBiKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGEgPiBiID8gMSA6IC0xO1xuICAgICAgICAgICAgfVxuICAgICAgICB9LCB7fV0sIDE3OiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge1xuICAgICAgICAgICAgdmFyIGFwcGx5UHJvcGVydGllcyA9IHJlcXVpcmUoXCIuL2FwcGx5LXByb3BlcnRpZXNcIik7XG5cbiAgICAgICAgICAgIHZhciBpc1dpZGdldCA9IHJlcXVpcmUoXCIuLi92bm9kZS9pcy13aWRnZXQuanNcIik7XG4gICAgICAgICAgICB2YXIgVlBhdGNoID0gcmVxdWlyZShcIi4uL3Zub2RlL3ZwYXRjaC5qc1wiKTtcblxuICAgICAgICAgICAgdmFyIHVwZGF0ZVdpZGdldCA9IHJlcXVpcmUoXCIuL3VwZGF0ZS13aWRnZXRcIik7XG5cbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gYXBwbHlQYXRjaDtcblxuICAgICAgICAgICAgZnVuY3Rpb24gYXBwbHlQYXRjaCh2cGF0Y2gsIGRvbU5vZGUsIHJlbmRlck9wdGlvbnMpIHtcbiAgICAgICAgICAgICAgICB2YXIgdHlwZSA9IHZwYXRjaC50eXBlO1xuICAgICAgICAgICAgICAgIHZhciB2Tm9kZSA9IHZwYXRjaC52Tm9kZTtcbiAgICAgICAgICAgICAgICB2YXIgcGF0Y2ggPSB2cGF0Y2gucGF0Y2g7XG5cbiAgICAgICAgICAgICAgICBzd2l0Y2ggKHR5cGUpIHtcbiAgICAgICAgICAgICAgICAgICAgY2FzZSBWUGF0Y2guUkVNT1ZFOlxuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHJlbW92ZU5vZGUoZG9tTm9kZSwgdk5vZGUpO1xuICAgICAgICAgICAgICAgICAgICBjYXNlIFZQYXRjaC5JTlNFUlQ6XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gaW5zZXJ0Tm9kZShkb21Ob2RlLCBwYXRjaCwgcmVuZGVyT3B0aW9ucyk7XG4gICAgICAgICAgICAgICAgICAgIGNhc2UgVlBhdGNoLlZURVhUOlxuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHN0cmluZ1BhdGNoKGRvbU5vZGUsIHZOb2RlLCBwYXRjaCwgcmVuZGVyT3B0aW9ucyk7XG4gICAgICAgICAgICAgICAgICAgIGNhc2UgVlBhdGNoLldJREdFVDpcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiB3aWRnZXRQYXRjaChkb21Ob2RlLCB2Tm9kZSwgcGF0Y2gsIHJlbmRlck9wdGlvbnMpO1xuICAgICAgICAgICAgICAgICAgICBjYXNlIFZQYXRjaC5WTk9ERTpcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiB2Tm9kZVBhdGNoKGRvbU5vZGUsIHZOb2RlLCBwYXRjaCwgcmVuZGVyT3B0aW9ucyk7XG4gICAgICAgICAgICAgICAgICAgIGNhc2UgVlBhdGNoLk9SREVSOlxuICAgICAgICAgICAgICAgICAgICAgICAgcmVvcmRlckNoaWxkcmVuKGRvbU5vZGUsIHBhdGNoKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBkb21Ob2RlO1xuICAgICAgICAgICAgICAgICAgICBjYXNlIFZQYXRjaC5QUk9QUzpcbiAgICAgICAgICAgICAgICAgICAgICAgIGFwcGx5UHJvcGVydGllcyhkb21Ob2RlLCBwYXRjaCwgdk5vZGUucHJvcGVydGllcyk7XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gZG9tTm9kZTtcbiAgICAgICAgICAgICAgICAgICAgY2FzZSBWUGF0Y2guVEhVTks6XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gcmVwbGFjZVJvb3QoZG9tTm9kZSwgcmVuZGVyT3B0aW9ucy5wYXRjaChkb21Ob2RlLCBwYXRjaCwgcmVuZGVyT3B0aW9ucykpO1xuICAgICAgICAgICAgICAgICAgICBkZWZhdWx0OlxuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGRvbU5vZGU7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBmdW5jdGlvbiByZW1vdmVOb2RlKGRvbU5vZGUsIHZOb2RlKSB7XG4gICAgICAgICAgICAgICAgdmFyIHBhcmVudE5vZGUgPSBkb21Ob2RlLnBhcmVudE5vZGU7XG5cbiAgICAgICAgICAgICAgICBpZiAocGFyZW50Tm9kZSkge1xuICAgICAgICAgICAgICAgICAgICBwYXJlbnROb2RlLnJlbW92ZUNoaWxkKGRvbU5vZGUpO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIGRlc3Ryb3lXaWRnZXQoZG9tTm9kZSwgdk5vZGUpO1xuXG4gICAgICAgICAgICAgICAgcmV0dXJuIG51bGw7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIGluc2VydE5vZGUocGFyZW50Tm9kZSwgdk5vZGUsIHJlbmRlck9wdGlvbnMpIHtcbiAgICAgICAgICAgICAgICB2YXIgbmV3Tm9kZSA9IHJlbmRlck9wdGlvbnMucmVuZGVyKHZOb2RlLCByZW5kZXJPcHRpb25zKTtcblxuICAgICAgICAgICAgICAgIGlmIChwYXJlbnROb2RlKSB7XG4gICAgICAgICAgICAgICAgICAgIHBhcmVudE5vZGUuYXBwZW5kQ2hpbGQobmV3Tm9kZSk7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgcmV0dXJuIHBhcmVudE5vZGU7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIHN0cmluZ1BhdGNoKGRvbU5vZGUsIGxlZnRWTm9kZSwgdlRleHQsIHJlbmRlck9wdGlvbnMpIHtcbiAgICAgICAgICAgICAgICB2YXIgbmV3Tm9kZTtcblxuICAgICAgICAgICAgICAgIGlmIChkb21Ob2RlLm5vZGVUeXBlID09PSAzKSB7XG4gICAgICAgICAgICAgICAgICAgIGRvbU5vZGUucmVwbGFjZURhdGEoMCwgZG9tTm9kZS5sZW5ndGgsIHZUZXh0LnRleHQpO1xuICAgICAgICAgICAgICAgICAgICBuZXdOb2RlID0gZG9tTm9kZTtcbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICB2YXIgcGFyZW50Tm9kZSA9IGRvbU5vZGUucGFyZW50Tm9kZTtcbiAgICAgICAgICAgICAgICAgICAgbmV3Tm9kZSA9IHJlbmRlck9wdGlvbnMucmVuZGVyKHZUZXh0LCByZW5kZXJPcHRpb25zKTtcblxuICAgICAgICAgICAgICAgICAgICBpZiAocGFyZW50Tm9kZSAmJiBuZXdOb2RlICE9PSBkb21Ob2RlKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBwYXJlbnROb2RlLnJlcGxhY2VDaGlsZChuZXdOb2RlLCBkb21Ob2RlKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHJldHVybiBuZXdOb2RlO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBmdW5jdGlvbiB3aWRnZXRQYXRjaChkb21Ob2RlLCBsZWZ0Vk5vZGUsIHdpZGdldCwgcmVuZGVyT3B0aW9ucykge1xuICAgICAgICAgICAgICAgIHZhciB1cGRhdGluZyA9IHVwZGF0ZVdpZGdldChsZWZ0Vk5vZGUsIHdpZGdldCk7XG4gICAgICAgICAgICAgICAgdmFyIG5ld05vZGU7XG5cbiAgICAgICAgICAgICAgICBpZiAodXBkYXRpbmcpIHtcbiAgICAgICAgICAgICAgICAgICAgbmV3Tm9kZSA9IHdpZGdldC51cGRhdGUobGVmdFZOb2RlLCBkb21Ob2RlKSB8fCBkb21Ob2RlO1xuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIG5ld05vZGUgPSByZW5kZXJPcHRpb25zLnJlbmRlcih3aWRnZXQsIHJlbmRlck9wdGlvbnMpO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHZhciBwYXJlbnROb2RlID0gZG9tTm9kZS5wYXJlbnROb2RlO1xuXG4gICAgICAgICAgICAgICAgaWYgKHBhcmVudE5vZGUgJiYgbmV3Tm9kZSAhPT0gZG9tTm9kZSkge1xuICAgICAgICAgICAgICAgICAgICBwYXJlbnROb2RlLnJlcGxhY2VDaGlsZChuZXdOb2RlLCBkb21Ob2RlKTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICBpZiAoIXVwZGF0aW5nKSB7XG4gICAgICAgICAgICAgICAgICAgIGRlc3Ryb3lXaWRnZXQoZG9tTm9kZSwgbGVmdFZOb2RlKTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICByZXR1cm4gbmV3Tm9kZTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZnVuY3Rpb24gdk5vZGVQYXRjaChkb21Ob2RlLCBsZWZ0Vk5vZGUsIHZOb2RlLCByZW5kZXJPcHRpb25zKSB7XG4gICAgICAgICAgICAgICAgdmFyIHBhcmVudE5vZGUgPSBkb21Ob2RlLnBhcmVudE5vZGU7XG4gICAgICAgICAgICAgICAgdmFyIG5ld05vZGUgPSByZW5kZXJPcHRpb25zLnJlbmRlcih2Tm9kZSwgcmVuZGVyT3B0aW9ucyk7XG5cbiAgICAgICAgICAgICAgICBpZiAocGFyZW50Tm9kZSAmJiBuZXdOb2RlICE9PSBkb21Ob2RlKSB7XG4gICAgICAgICAgICAgICAgICAgIHBhcmVudE5vZGUucmVwbGFjZUNoaWxkKG5ld05vZGUsIGRvbU5vZGUpO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHJldHVybiBuZXdOb2RlO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBmdW5jdGlvbiBkZXN0cm95V2lkZ2V0KGRvbU5vZGUsIHcpIHtcbiAgICAgICAgICAgICAgICBpZiAodHlwZW9mIHcuZGVzdHJveSA9PT0gXCJmdW5jdGlvblwiICYmIGlzV2lkZ2V0KHcpKSB7XG4gICAgICAgICAgICAgICAgICAgIHcuZGVzdHJveShkb21Ob2RlKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIHJlb3JkZXJDaGlsZHJlbihkb21Ob2RlLCBtb3Zlcykge1xuICAgICAgICAgICAgICAgIHZhciBjaGlsZE5vZGVzID0gZG9tTm9kZS5jaGlsZE5vZGVzO1xuICAgICAgICAgICAgICAgIHZhciBrZXlNYXAgPSB7fTtcbiAgICAgICAgICAgICAgICB2YXIgbm9kZTtcbiAgICAgICAgICAgICAgICB2YXIgcmVtb3ZlO1xuICAgICAgICAgICAgICAgIHZhciBpbnNlcnQ7XG5cbiAgICAgICAgICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IG1vdmVzLnJlbW92ZXMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgICAgICAgICAgcmVtb3ZlID0gbW92ZXMucmVtb3Zlc1tpXTtcbiAgICAgICAgICAgICAgICAgICAgbm9kZSA9IGNoaWxkTm9kZXNbcmVtb3ZlLmZyb21dO1xuICAgICAgICAgICAgICAgICAgICBpZiAocmVtb3ZlLmtleSkge1xuICAgICAgICAgICAgICAgICAgICAgICAga2V5TWFwW3JlbW92ZS5rZXldID0gbm9kZTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICBkb21Ob2RlLnJlbW92ZUNoaWxkKG5vZGUpO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHZhciBsZW5ndGggPSBjaGlsZE5vZGVzLmxlbmd0aDtcbiAgICAgICAgICAgICAgICBmb3IgKHZhciBqID0gMDsgaiA8IG1vdmVzLmluc2VydHMubGVuZ3RoOyBqKyspIHtcbiAgICAgICAgICAgICAgICAgICAgaW5zZXJ0ID0gbW92ZXMuaW5zZXJ0c1tqXTtcbiAgICAgICAgICAgICAgICAgICAgbm9kZSA9IGtleU1hcFtpbnNlcnQua2V5XTtcbiAgICAgICAgICAgICAgICAgICAgLy8gdGhpcyBpcyB0aGUgd2VpcmRlc3QgYnVnIGkndmUgZXZlciBzZWVuIGluIHdlYmtpdFxuICAgICAgICAgICAgICAgICAgICBkb21Ob2RlLmluc2VydEJlZm9yZShub2RlLCBpbnNlcnQudG8gPj0gbGVuZ3RoKysgPyBudWxsIDogY2hpbGROb2Rlc1tpbnNlcnQudG9dKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIHJlcGxhY2VSb290KG9sZFJvb3QsIG5ld1Jvb3QpIHtcbiAgICAgICAgICAgICAgICBpZiAob2xkUm9vdCAmJiBuZXdSb290ICYmIG9sZFJvb3QgIT09IG5ld1Jvb3QgJiYgb2xkUm9vdC5wYXJlbnROb2RlKSB7XG4gICAgICAgICAgICAgICAgICAgIG9sZFJvb3QucGFyZW50Tm9kZS5yZXBsYWNlQ2hpbGQobmV3Um9vdCwgb2xkUm9vdCk7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgcmV0dXJuIG5ld1Jvb3Q7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0sIHsgXCIuLi92bm9kZS9pcy13aWRnZXQuanNcIjogMjksIFwiLi4vdm5vZGUvdnBhdGNoLmpzXCI6IDMyLCBcIi4vYXBwbHktcHJvcGVydGllc1wiOiAxNCwgXCIuL3VwZGF0ZS13aWRnZXRcIjogMTkgfV0sIDE4OiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge1xuICAgICAgICAgICAgdmFyIGRvY3VtZW50ID0gcmVxdWlyZShcImdsb2JhbC9kb2N1bWVudFwiKTtcbiAgICAgICAgICAgIHZhciBpc0FycmF5ID0gcmVxdWlyZShcIngtaXMtYXJyYXlcIik7XG5cbiAgICAgICAgICAgIHZhciByZW5kZXIgPSByZXF1aXJlKFwiLi9jcmVhdGUtZWxlbWVudFwiKTtcbiAgICAgICAgICAgIHZhciBkb21JbmRleCA9IHJlcXVpcmUoXCIuL2RvbS1pbmRleFwiKTtcbiAgICAgICAgICAgIHZhciBwYXRjaE9wID0gcmVxdWlyZShcIi4vcGF0Y2gtb3BcIik7XG4gICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IHBhdGNoO1xuXG4gICAgICAgICAgICBmdW5jdGlvbiBwYXRjaChyb290Tm9kZSwgcGF0Y2hlcywgcmVuZGVyT3B0aW9ucykge1xuICAgICAgICAgICAgICAgIHJlbmRlck9wdGlvbnMgPSByZW5kZXJPcHRpb25zIHx8IHt9O1xuICAgICAgICAgICAgICAgIHJlbmRlck9wdGlvbnMucGF0Y2ggPSByZW5kZXJPcHRpb25zLnBhdGNoICYmIHJlbmRlck9wdGlvbnMucGF0Y2ggIT09IHBhdGNoID8gcmVuZGVyT3B0aW9ucy5wYXRjaCA6IHBhdGNoUmVjdXJzaXZlO1xuICAgICAgICAgICAgICAgIHJlbmRlck9wdGlvbnMucmVuZGVyID0gcmVuZGVyT3B0aW9ucy5yZW5kZXIgfHwgcmVuZGVyO1xuXG4gICAgICAgICAgICAgICAgcmV0dXJuIHJlbmRlck9wdGlvbnMucGF0Y2gocm9vdE5vZGUsIHBhdGNoZXMsIHJlbmRlck9wdGlvbnMpO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBmdW5jdGlvbiBwYXRjaFJlY3Vyc2l2ZShyb290Tm9kZSwgcGF0Y2hlcywgcmVuZGVyT3B0aW9ucykge1xuICAgICAgICAgICAgICAgIHZhciBpbmRpY2VzID0gcGF0Y2hJbmRpY2VzKHBhdGNoZXMpO1xuXG4gICAgICAgICAgICAgICAgaWYgKGluZGljZXMubGVuZ3RoID09PSAwKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiByb290Tm9kZTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICB2YXIgaW5kZXggPSBkb21JbmRleChyb290Tm9kZSwgcGF0Y2hlcy5hLCBpbmRpY2VzKTtcbiAgICAgICAgICAgICAgICB2YXIgb3duZXJEb2N1bWVudCA9IHJvb3ROb2RlLm93bmVyRG9jdW1lbnQ7XG5cbiAgICAgICAgICAgICAgICBpZiAoIXJlbmRlck9wdGlvbnMuZG9jdW1lbnQgJiYgb3duZXJEb2N1bWVudCAhPT0gZG9jdW1lbnQpIHtcbiAgICAgICAgICAgICAgICAgICAgcmVuZGVyT3B0aW9ucy5kb2N1bWVudCA9IG93bmVyRG9jdW1lbnQ7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCBpbmRpY2VzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciBub2RlSW5kZXggPSBpbmRpY2VzW2ldO1xuICAgICAgICAgICAgICAgICAgICByb290Tm9kZSA9IGFwcGx5UGF0Y2gocm9vdE5vZGUsIGluZGV4W25vZGVJbmRleF0sIHBhdGNoZXNbbm9kZUluZGV4XSwgcmVuZGVyT3B0aW9ucyk7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgcmV0dXJuIHJvb3ROb2RlO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBmdW5jdGlvbiBhcHBseVBhdGNoKHJvb3ROb2RlLCBkb21Ob2RlLCBwYXRjaExpc3QsIHJlbmRlck9wdGlvbnMpIHtcbiAgICAgICAgICAgICAgICBpZiAoIWRvbU5vZGUpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHJvb3ROb2RlO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHZhciBuZXdOb2RlO1xuXG4gICAgICAgICAgICAgICAgaWYgKGlzQXJyYXkocGF0Y2hMaXN0KSkge1xuICAgICAgICAgICAgICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IHBhdGNoTGlzdC5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgICAgICAgICAgICAgbmV3Tm9kZSA9IHBhdGNoT3AocGF0Y2hMaXN0W2ldLCBkb21Ob2RlLCByZW5kZXJPcHRpb25zKTtcblxuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGRvbU5vZGUgPT09IHJvb3ROb2RlKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcm9vdE5vZGUgPSBuZXdOb2RlO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgbmV3Tm9kZSA9IHBhdGNoT3AocGF0Y2hMaXN0LCBkb21Ob2RlLCByZW5kZXJPcHRpb25zKTtcblxuICAgICAgICAgICAgICAgICAgICBpZiAoZG9tTm9kZSA9PT0gcm9vdE5vZGUpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJvb3ROb2RlID0gbmV3Tm9kZTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHJldHVybiByb290Tm9kZTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZnVuY3Rpb24gcGF0Y2hJbmRpY2VzKHBhdGNoZXMpIHtcbiAgICAgICAgICAgICAgICB2YXIgaW5kaWNlcyA9IFtdO1xuXG4gICAgICAgICAgICAgICAgZm9yICh2YXIga2V5IGluIHBhdGNoZXMpIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKGtleSAhPT0gXCJhXCIpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGluZGljZXMucHVzaChOdW1iZXIoa2V5KSk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICByZXR1cm4gaW5kaWNlcztcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSwgeyBcIi4vY3JlYXRlLWVsZW1lbnRcIjogMTUsIFwiLi9kb20taW5kZXhcIjogMTYsIFwiLi9wYXRjaC1vcFwiOiAxNywgXCJnbG9iYWwvZG9jdW1lbnRcIjogMTAsIFwieC1pcy1hcnJheVwiOiAxMiB9XSwgMTk6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICB2YXIgaXNXaWRnZXQgPSByZXF1aXJlKFwiLi4vdm5vZGUvaXMtd2lkZ2V0LmpzXCIpO1xuXG4gICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IHVwZGF0ZVdpZGdldDtcblxuICAgICAgICAgICAgZnVuY3Rpb24gdXBkYXRlV2lkZ2V0KGEsIGIpIHtcbiAgICAgICAgICAgICAgICBpZiAoaXNXaWRnZXQoYSkgJiYgaXNXaWRnZXQoYikpIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKFwibmFtZVwiIGluIGEgJiYgXCJuYW1lXCIgaW4gYikge1xuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGEuaWQgPT09IGIuaWQ7XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gYS5pbml0ID09PSBiLmluaXQ7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0sIHsgXCIuLi92bm9kZS9pcy13aWRnZXQuanNcIjogMjkgfV0sIDIwOiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge1xuICAgICAgICAgICAgXCJ1c2Ugc3RyaWN0XCI7XG5cbiAgICAgICAgICAgIHZhciBFdlN0b3JlID0gcmVxdWlyZShcImV2LXN0b3JlXCIpO1xuXG4gICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IEV2SG9vaztcblxuICAgICAgICAgICAgZnVuY3Rpb24gRXZIb29rKHZhbHVlKSB7XG4gICAgICAgICAgICAgICAgaWYgKCEodGhpcyBpbnN0YW5jZW9mIEV2SG9vaykpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIG5ldyBFdkhvb2sodmFsdWUpO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHRoaXMudmFsdWUgPSB2YWx1ZTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgRXZIb29rLnByb3RvdHlwZS5ob29rID0gZnVuY3Rpb24gKG5vZGUsIHByb3BlcnR5TmFtZSkge1xuICAgICAgICAgICAgICAgIHZhciBlcyA9IEV2U3RvcmUobm9kZSk7XG4gICAgICAgICAgICAgICAgdmFyIHByb3BOYW1lID0gcHJvcGVydHlOYW1lLnN1YnN0cigzKTtcblxuICAgICAgICAgICAgICAgIGVzW3Byb3BOYW1lXSA9IHRoaXMudmFsdWU7XG4gICAgICAgICAgICB9O1xuXG4gICAgICAgICAgICBFdkhvb2sucHJvdG90eXBlLnVuaG9vayA9IGZ1bmN0aW9uIChub2RlLCBwcm9wZXJ0eU5hbWUpIHtcbiAgICAgICAgICAgICAgICB2YXIgZXMgPSBFdlN0b3JlKG5vZGUpO1xuICAgICAgICAgICAgICAgIHZhciBwcm9wTmFtZSA9IHByb3BlcnR5TmFtZS5zdWJzdHIoMyk7XG5cbiAgICAgICAgICAgICAgICBlc1twcm9wTmFtZV0gPSB1bmRlZmluZWQ7XG4gICAgICAgICAgICB9O1xuICAgICAgICB9LCB7IFwiZXYtc3RvcmVcIjogNyB9XSwgMjE6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICBcInVzZSBzdHJpY3RcIjtcblxuICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBTb2Z0U2V0SG9vaztcblxuICAgICAgICAgICAgZnVuY3Rpb24gU29mdFNldEhvb2sodmFsdWUpIHtcbiAgICAgICAgICAgICAgICBpZiAoISh0aGlzIGluc3RhbmNlb2YgU29mdFNldEhvb2spKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBuZXcgU29mdFNldEhvb2sodmFsdWUpO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHRoaXMudmFsdWUgPSB2YWx1ZTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgU29mdFNldEhvb2sucHJvdG90eXBlLmhvb2sgPSBmdW5jdGlvbiAobm9kZSwgcHJvcGVydHlOYW1lKSB7XG4gICAgICAgICAgICAgICAgaWYgKG5vZGVbcHJvcGVydHlOYW1lXSAhPT0gdGhpcy52YWx1ZSkge1xuICAgICAgICAgICAgICAgICAgICBub2RlW3Byb3BlcnR5TmFtZV0gPSB0aGlzLnZhbHVlO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH07XG4gICAgICAgIH0sIHt9XSwgMjI6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICBcInVzZSBzdHJpY3RcIjtcblxuICAgICAgICAgICAgdmFyIGlzQXJyYXkgPSByZXF1aXJlKFwieC1pcy1hcnJheVwiKTtcblxuICAgICAgICAgICAgdmFyIFZOb2RlID0gcmVxdWlyZShcIi4uL3Zub2RlL3Zub2RlLmpzXCIpO1xuICAgICAgICAgICAgdmFyIFZUZXh0ID0gcmVxdWlyZShcIi4uL3Zub2RlL3Z0ZXh0LmpzXCIpO1xuICAgICAgICAgICAgdmFyIGlzVk5vZGUgPSByZXF1aXJlKFwiLi4vdm5vZGUvaXMtdm5vZGVcIik7XG4gICAgICAgICAgICB2YXIgaXNWVGV4dCA9IHJlcXVpcmUoXCIuLi92bm9kZS9pcy12dGV4dFwiKTtcbiAgICAgICAgICAgIHZhciBpc1dpZGdldCA9IHJlcXVpcmUoXCIuLi92bm9kZS9pcy13aWRnZXRcIik7XG4gICAgICAgICAgICB2YXIgaXNIb29rID0gcmVxdWlyZShcIi4uL3Zub2RlL2lzLXZob29rXCIpO1xuICAgICAgICAgICAgdmFyIGlzVlRodW5rID0gcmVxdWlyZShcIi4uL3Zub2RlL2lzLXRodW5rXCIpO1xuXG4gICAgICAgICAgICB2YXIgcGFyc2VUYWcgPSByZXF1aXJlKFwiLi9wYXJzZS10YWcuanNcIik7XG4gICAgICAgICAgICB2YXIgc29mdFNldEhvb2sgPSByZXF1aXJlKFwiLi9ob29rcy9zb2Z0LXNldC1ob29rLmpzXCIpO1xuICAgICAgICAgICAgdmFyIGV2SG9vayA9IHJlcXVpcmUoXCIuL2hvb2tzL2V2LWhvb2suanNcIik7XG5cbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gaDtcblxuICAgICAgICAgICAgZnVuY3Rpb24gaCh0YWdOYW1lLCBwcm9wZXJ0aWVzLCBjaGlsZHJlbikge1xuICAgICAgICAgICAgICAgIHZhciBjaGlsZE5vZGVzID0gW107XG4gICAgICAgICAgICAgICAgdmFyIHRhZywgcHJvcHMsIGtleSwgbmFtZXNwYWNlO1xuXG4gICAgICAgICAgICAgICAgaWYgKCFjaGlsZHJlbiAmJiBpc0NoaWxkcmVuKHByb3BlcnRpZXMpKSB7XG4gICAgICAgICAgICAgICAgICAgIGNoaWxkcmVuID0gcHJvcGVydGllcztcbiAgICAgICAgICAgICAgICAgICAgcHJvcHMgPSB7fTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICBwcm9wcyA9IHByb3BzIHx8IHByb3BlcnRpZXMgfHwge307XG4gICAgICAgICAgICAgICAgdGFnID0gcGFyc2VUYWcodGFnTmFtZSwgcHJvcHMpO1xuXG4gICAgICAgICAgICAgICAgLy8gc3VwcG9ydCBrZXlzXG4gICAgICAgICAgICAgICAgaWYgKHByb3BzLmhhc093blByb3BlcnR5KFwia2V5XCIpKSB7XG4gICAgICAgICAgICAgICAgICAgIGtleSA9IHByb3BzLmtleTtcbiAgICAgICAgICAgICAgICAgICAgcHJvcHMua2V5ID0gdW5kZWZpbmVkO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIC8vIHN1cHBvcnQgbmFtZXNwYWNlXG4gICAgICAgICAgICAgICAgaWYgKHByb3BzLmhhc093blByb3BlcnR5KFwibmFtZXNwYWNlXCIpKSB7XG4gICAgICAgICAgICAgICAgICAgIG5hbWVzcGFjZSA9IHByb3BzLm5hbWVzcGFjZTtcbiAgICAgICAgICAgICAgICAgICAgcHJvcHMubmFtZXNwYWNlID0gdW5kZWZpbmVkO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIC8vIGZpeCBjdXJzb3IgYnVnXG4gICAgICAgICAgICAgICAgaWYgKHRhZyA9PT0gXCJJTlBVVFwiICYmICFuYW1lc3BhY2UgJiYgcHJvcHMuaGFzT3duUHJvcGVydHkoXCJ2YWx1ZVwiKSAmJiBwcm9wcy52YWx1ZSAhPT0gdW5kZWZpbmVkICYmICFpc0hvb2socHJvcHMudmFsdWUpKSB7XG4gICAgICAgICAgICAgICAgICAgIHByb3BzLnZhbHVlID0gc29mdFNldEhvb2socHJvcHMudmFsdWUpO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHRyYW5zZm9ybVByb3BlcnRpZXMocHJvcHMpO1xuXG4gICAgICAgICAgICAgICAgaWYgKGNoaWxkcmVuICE9PSB1bmRlZmluZWQgJiYgY2hpbGRyZW4gIT09IG51bGwpIHtcbiAgICAgICAgICAgICAgICAgICAgYWRkQ2hpbGQoY2hpbGRyZW4sIGNoaWxkTm9kZXMsIHRhZywgcHJvcHMpO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHJldHVybiBuZXcgVk5vZGUodGFnLCBwcm9wcywgY2hpbGROb2Rlcywga2V5LCBuYW1lc3BhY2UpO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBmdW5jdGlvbiBhZGRDaGlsZChjLCBjaGlsZE5vZGVzLCB0YWcsIHByb3BzKSB7XG4gICAgICAgICAgICAgICAgaWYgKHR5cGVvZiBjID09PSBcInN0cmluZ1wiKSB7XG4gICAgICAgICAgICAgICAgICAgIGNoaWxkTm9kZXMucHVzaChuZXcgVlRleHQoYykpO1xuICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAodHlwZW9mIGMgPT09IFwibnVtYmVyXCIpIHtcbiAgICAgICAgICAgICAgICAgICAgY2hpbGROb2Rlcy5wdXNoKG5ldyBWVGV4dChTdHJpbmcoYykpKTtcbiAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKGlzQ2hpbGQoYykpIHtcbiAgICAgICAgICAgICAgICAgICAgY2hpbGROb2Rlcy5wdXNoKGMpO1xuICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoaXNBcnJheShjKSkge1xuICAgICAgICAgICAgICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IGMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGFkZENoaWxkKGNbaV0sIGNoaWxkTm9kZXMsIHRhZywgcHJvcHMpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfSBlbHNlIGlmIChjID09PSBudWxsIHx8IGMgPT09IHVuZGVmaW5lZCkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgdGhyb3cgVW5leHBlY3RlZFZpcnR1YWxFbGVtZW50KHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGZvcmVpZ25PYmplY3Q6IGMsXG4gICAgICAgICAgICAgICAgICAgICAgICBwYXJlbnRWbm9kZToge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRhZ05hbWU6IHRhZyxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBwcm9wZXJ0aWVzOiBwcm9wc1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIHRyYW5zZm9ybVByb3BlcnRpZXMocHJvcHMpIHtcbiAgICAgICAgICAgICAgICBmb3IgKHZhciBwcm9wTmFtZSBpbiBwcm9wcykge1xuICAgICAgICAgICAgICAgICAgICBpZiAocHJvcHMuaGFzT3duUHJvcGVydHkocHJvcE5hbWUpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICB2YXIgdmFsdWUgPSBwcm9wc1twcm9wTmFtZV07XG5cbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChpc0hvb2sodmFsdWUpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgY29udGludWU7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChwcm9wTmFtZS5zdWJzdHIoMCwgMykgPT09IFwiZXYtXCIpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBhZGQgZXYtZm9vIHN1cHBvcnRcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBwcm9wc1twcm9wTmFtZV0gPSBldkhvb2sodmFsdWUpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBmdW5jdGlvbiBpc0NoaWxkKHgpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gaXNWTm9kZSh4KSB8fCBpc1ZUZXh0KHgpIHx8IGlzV2lkZ2V0KHgpIHx8IGlzVlRodW5rKHgpO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBmdW5jdGlvbiBpc0NoaWxkcmVuKHgpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gdHlwZW9mIHggPT09IFwic3RyaW5nXCIgfHwgaXNBcnJheSh4KSB8fCBpc0NoaWxkKHgpO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBmdW5jdGlvbiBVbmV4cGVjdGVkVmlydHVhbEVsZW1lbnQoZGF0YSkge1xuICAgICAgICAgICAgICAgIHZhciBlcnIgPSBuZXcgRXJyb3IoKTtcblxuICAgICAgICAgICAgICAgIGVyci50eXBlID0gXCJ2aXJ0dWFsLWh5cGVyc2NyaXB0LnVuZXhwZWN0ZWQudmlydHVhbC1lbGVtZW50XCI7XG4gICAgICAgICAgICAgICAgZXJyLm1lc3NhZ2UgPSBcIlVuZXhwZWN0ZWQgdmlydHVhbCBjaGlsZCBwYXNzZWQgdG8gaCgpLlxcblwiICsgXCJFeHBlY3RlZCBhIFZOb2RlIC8gVnRodW5rIC8gVldpZGdldCAvIHN0cmluZyBidXQ6XFxuXCIgKyBcImdvdDpcXG5cIiArIGVycm9yU3RyaW5nKGRhdGEuZm9yZWlnbk9iamVjdCkgKyBcIi5cXG5cIiArIFwiVGhlIHBhcmVudCB2bm9kZSBpczpcXG5cIiArIGVycm9yU3RyaW5nKGRhdGEucGFyZW50Vm5vZGUpO1xuICAgICAgICAgICAgICAgIFwiXFxuXCIgKyBcIlN1Z2dlc3RlZCBmaXg6IGNoYW5nZSB5b3VyIGBoKC4uLiwgWyAuLi4gXSlgIGNhbGxzaXRlLlwiO1xuICAgICAgICAgICAgICAgIGVyci5mb3JlaWduT2JqZWN0ID0gZGF0YS5mb3JlaWduT2JqZWN0O1xuICAgICAgICAgICAgICAgIGVyci5wYXJlbnRWbm9kZSA9IGRhdGEucGFyZW50Vm5vZGU7XG5cbiAgICAgICAgICAgICAgICByZXR1cm4gZXJyO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBmdW5jdGlvbiBlcnJvclN0cmluZyhvYmopIHtcbiAgICAgICAgICAgICAgICB0cnkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gSlNPTi5zdHJpbmdpZnkob2JqLCBudWxsLCBcIiAgICBcIik7XG4gICAgICAgICAgICAgICAgfSBjYXRjaCAoZSkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gU3RyaW5nKG9iaik7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9LCB7IFwiLi4vdm5vZGUvaXMtdGh1bmtcIjogMjUsIFwiLi4vdm5vZGUvaXMtdmhvb2tcIjogMjYsIFwiLi4vdm5vZGUvaXMtdm5vZGVcIjogMjcsIFwiLi4vdm5vZGUvaXMtdnRleHRcIjogMjgsIFwiLi4vdm5vZGUvaXMtd2lkZ2V0XCI6IDI5LCBcIi4uL3Zub2RlL3Zub2RlLmpzXCI6IDMxLCBcIi4uL3Zub2RlL3Z0ZXh0LmpzXCI6IDMzLCBcIi4vaG9va3MvZXYtaG9vay5qc1wiOiAyMCwgXCIuL2hvb2tzL3NvZnQtc2V0LWhvb2suanNcIjogMjEsIFwiLi9wYXJzZS10YWcuanNcIjogMjMsIFwieC1pcy1hcnJheVwiOiAxMiB9XSwgMjM6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICBcInVzZSBzdHJpY3RcIjtcblxuICAgICAgICAgICAgdmFyIHNwbGl0ID0gcmVxdWlyZShcImJyb3dzZXItc3BsaXRcIik7XG5cbiAgICAgICAgICAgIHZhciBjbGFzc0lkU3BsaXQgPSAvKFtcXC4jXT9bYS16QS1aMC05XFx1MDA3Ri1cXHVGRkZGXzotXSspLztcbiAgICAgICAgICAgIHZhciBub3RDbGFzc0lkID0gL15cXC58Iy87XG5cbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gcGFyc2VUYWc7XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIHBhcnNlVGFnKHRhZywgcHJvcHMpIHtcbiAgICAgICAgICAgICAgICBpZiAoIXRhZykge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gXCJESVZcIjtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICB2YXIgbm9JZCA9ICFwcm9wcy5oYXNPd25Qcm9wZXJ0eShcImlkXCIpO1xuXG4gICAgICAgICAgICAgICAgdmFyIHRhZ1BhcnRzID0gc3BsaXQodGFnLCBjbGFzc0lkU3BsaXQpO1xuICAgICAgICAgICAgICAgIHZhciB0YWdOYW1lID0gbnVsbDtcblxuICAgICAgICAgICAgICAgIGlmIChub3RDbGFzc0lkLnRlc3QodGFnUGFydHNbMV0pKSB7XG4gICAgICAgICAgICAgICAgICAgIHRhZ05hbWUgPSBcIkRJVlwiO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHZhciBjbGFzc2VzLCBwYXJ0LCB0eXBlLCBpO1xuXG4gICAgICAgICAgICAgICAgZm9yIChpID0gMDsgaSA8IHRhZ1BhcnRzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICAgICAgICAgIHBhcnQgPSB0YWdQYXJ0c1tpXTtcblxuICAgICAgICAgICAgICAgICAgICBpZiAoIXBhcnQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnRpbnVlO1xuICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgdHlwZSA9IHBhcnQuY2hhckF0KDApO1xuXG4gICAgICAgICAgICAgICAgICAgIGlmICghdGFnTmFtZSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgdGFnTmFtZSA9IHBhcnQ7XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAodHlwZSA9PT0gXCIuXCIpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGNsYXNzZXMgPSBjbGFzc2VzIHx8IFtdO1xuICAgICAgICAgICAgICAgICAgICAgICAgY2xhc3Nlcy5wdXNoKHBhcnQuc3Vic3RyaW5nKDEsIHBhcnQubGVuZ3RoKSk7XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAodHlwZSA9PT0gXCIjXCIgJiYgbm9JZCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgcHJvcHMuaWQgPSBwYXJ0LnN1YnN0cmluZygxLCBwYXJ0Lmxlbmd0aCk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICBpZiAoY2xhc3Nlcykge1xuICAgICAgICAgICAgICAgICAgICBpZiAocHJvcHMuY2xhc3NOYW1lKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBjbGFzc2VzLnB1c2gocHJvcHMuY2xhc3NOYW1lKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgIHByb3BzLmNsYXNzTmFtZSA9IGNsYXNzZXMuam9pbihcIiBcIik7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgcmV0dXJuIHByb3BzLm5hbWVzcGFjZSA/IHRhZ05hbWUgOiB0YWdOYW1lLnRvVXBwZXJDYXNlKCk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0sIHsgXCJicm93c2VyLXNwbGl0XCI6IDUgfV0sIDI0OiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge1xuICAgICAgICAgICAgdmFyIGlzVk5vZGUgPSByZXF1aXJlKFwiLi9pcy12bm9kZVwiKTtcbiAgICAgICAgICAgIHZhciBpc1ZUZXh0ID0gcmVxdWlyZShcIi4vaXMtdnRleHRcIik7XG4gICAgICAgICAgICB2YXIgaXNXaWRnZXQgPSByZXF1aXJlKFwiLi9pcy13aWRnZXRcIik7XG4gICAgICAgICAgICB2YXIgaXNUaHVuayA9IHJlcXVpcmUoXCIuL2lzLXRodW5rXCIpO1xuXG4gICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IGhhbmRsZVRodW5rO1xuXG4gICAgICAgICAgICBmdW5jdGlvbiBoYW5kbGVUaHVuayhhLCBiKSB7XG4gICAgICAgICAgICAgICAgdmFyIHJlbmRlcmVkQSA9IGE7XG4gICAgICAgICAgICAgICAgdmFyIHJlbmRlcmVkQiA9IGI7XG5cbiAgICAgICAgICAgICAgICBpZiAoaXNUaHVuayhiKSkge1xuICAgICAgICAgICAgICAgICAgICByZW5kZXJlZEIgPSByZW5kZXJUaHVuayhiLCBhKTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICBpZiAoaXNUaHVuayhhKSkge1xuICAgICAgICAgICAgICAgICAgICByZW5kZXJlZEEgPSByZW5kZXJUaHVuayhhLCBudWxsKTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgICAgICAgICBhOiByZW5kZXJlZEEsXG4gICAgICAgICAgICAgICAgICAgIGI6IHJlbmRlcmVkQlxuICAgICAgICAgICAgICAgIH07XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIHJlbmRlclRodW5rKHRodW5rLCBwcmV2aW91cykge1xuICAgICAgICAgICAgICAgIHZhciByZW5kZXJlZFRodW5rID0gdGh1bmsudm5vZGU7XG5cbiAgICAgICAgICAgICAgICBpZiAoIXJlbmRlcmVkVGh1bmspIHtcbiAgICAgICAgICAgICAgICAgICAgcmVuZGVyZWRUaHVuayA9IHRodW5rLnZub2RlID0gdGh1bmsucmVuZGVyKHByZXZpb3VzKTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICBpZiAoIShpc1ZOb2RlKHJlbmRlcmVkVGh1bmspIHx8IGlzVlRleHQocmVuZGVyZWRUaHVuaykgfHwgaXNXaWRnZXQocmVuZGVyZWRUaHVuaykpKSB7XG4gICAgICAgICAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcihcInRodW5rIGRpZCBub3QgcmV0dXJuIGEgdmFsaWQgbm9kZVwiKTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICByZXR1cm4gcmVuZGVyZWRUaHVuaztcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSwgeyBcIi4vaXMtdGh1bmtcIjogMjUsIFwiLi9pcy12bm9kZVwiOiAyNywgXCIuL2lzLXZ0ZXh0XCI6IDI4LCBcIi4vaXMtd2lkZ2V0XCI6IDI5IH1dLCAyNTogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHtcbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gaXNUaHVuaztcblxuICAgICAgICAgICAgZnVuY3Rpb24gaXNUaHVuayh0KSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHQgJiYgdC50eXBlID09PSBcIlRodW5rXCI7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0sIHt9XSwgMjY6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IGlzSG9vaztcblxuICAgICAgICAgICAgZnVuY3Rpb24gaXNIb29rKGhvb2spIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gaG9vayAmJiAodHlwZW9mIGhvb2suaG9vayA9PT0gXCJmdW5jdGlvblwiICYmICFob29rLmhhc093blByb3BlcnR5KFwiaG9va1wiKSB8fCB0eXBlb2YgaG9vay51bmhvb2sgPT09IFwiZnVuY3Rpb25cIiAmJiAhaG9vay5oYXNPd25Qcm9wZXJ0eShcInVuaG9va1wiKSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0sIHt9XSwgMjc6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICB2YXIgdmVyc2lvbiA9IHJlcXVpcmUoXCIuL3ZlcnNpb25cIik7XG5cbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gaXNWaXJ0dWFsTm9kZTtcblxuICAgICAgICAgICAgZnVuY3Rpb24gaXNWaXJ0dWFsTm9kZSh4KSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHggJiYgeC50eXBlID09PSBcIlZpcnR1YWxOb2RlXCIgJiYgeC52ZXJzaW9uID09PSB2ZXJzaW9uO1xuICAgICAgICAgICAgfVxuICAgICAgICB9LCB7IFwiLi92ZXJzaW9uXCI6IDMwIH1dLCAyODogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHtcbiAgICAgICAgICAgIHZhciB2ZXJzaW9uID0gcmVxdWlyZShcIi4vdmVyc2lvblwiKTtcblxuICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBpc1ZpcnR1YWxUZXh0O1xuXG4gICAgICAgICAgICBmdW5jdGlvbiBpc1ZpcnR1YWxUZXh0KHgpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4geCAmJiB4LnR5cGUgPT09IFwiVmlydHVhbFRleHRcIiAmJiB4LnZlcnNpb24gPT09IHZlcnNpb247XG4gICAgICAgICAgICB9XG4gICAgICAgIH0sIHsgXCIuL3ZlcnNpb25cIjogMzAgfV0sIDI5OiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge1xuICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBpc1dpZGdldDtcblxuICAgICAgICAgICAgZnVuY3Rpb24gaXNXaWRnZXQodykge1xuICAgICAgICAgICAgICAgIHJldHVybiB3ICYmIHcudHlwZSA9PT0gXCJXaWRnZXRcIjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSwge31dLCAzMDogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHtcbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gXCIyXCI7XG4gICAgICAgIH0sIHt9XSwgMzE6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICB2YXIgdmVyc2lvbiA9IHJlcXVpcmUoXCIuL3ZlcnNpb25cIik7XG4gICAgICAgICAgICB2YXIgaXNWTm9kZSA9IHJlcXVpcmUoXCIuL2lzLXZub2RlXCIpO1xuICAgICAgICAgICAgdmFyIGlzV2lkZ2V0ID0gcmVxdWlyZShcIi4vaXMtd2lkZ2V0XCIpO1xuICAgICAgICAgICAgdmFyIGlzVGh1bmsgPSByZXF1aXJlKFwiLi9pcy10aHVua1wiKTtcbiAgICAgICAgICAgIHZhciBpc1ZIb29rID0gcmVxdWlyZShcIi4vaXMtdmhvb2tcIik7XG5cbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gVmlydHVhbE5vZGU7XG5cbiAgICAgICAgICAgIHZhciBub1Byb3BlcnRpZXMgPSB7fTtcbiAgICAgICAgICAgIHZhciBub0NoaWxkcmVuID0gW107XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIFZpcnR1YWxOb2RlKHRhZ05hbWUsIHByb3BlcnRpZXMsIGNoaWxkcmVuLCBrZXksIG5hbWVzcGFjZSkge1xuICAgICAgICAgICAgICAgIHRoaXMudGFnTmFtZSA9IHRhZ05hbWU7XG4gICAgICAgICAgICAgICAgdGhpcy5wcm9wZXJ0aWVzID0gcHJvcGVydGllcyB8fCBub1Byb3BlcnRpZXM7XG4gICAgICAgICAgICAgICAgdGhpcy5jaGlsZHJlbiA9IGNoaWxkcmVuIHx8IG5vQ2hpbGRyZW47XG4gICAgICAgICAgICAgICAgdGhpcy5rZXkgPSBrZXkgIT0gbnVsbCA/IFN0cmluZyhrZXkpIDogdW5kZWZpbmVkO1xuICAgICAgICAgICAgICAgIHRoaXMubmFtZXNwYWNlID0gdHlwZW9mIG5hbWVzcGFjZSA9PT0gXCJzdHJpbmdcIiA/IG5hbWVzcGFjZSA6IG51bGw7XG5cbiAgICAgICAgICAgICAgICB2YXIgY291bnQgPSBjaGlsZHJlbiAmJiBjaGlsZHJlbi5sZW5ndGggfHwgMDtcbiAgICAgICAgICAgICAgICB2YXIgZGVzY2VuZGFudHMgPSAwO1xuICAgICAgICAgICAgICAgIHZhciBoYXNXaWRnZXRzID0gZmFsc2U7XG4gICAgICAgICAgICAgICAgdmFyIGhhc1RodW5rcyA9IGZhbHNlO1xuICAgICAgICAgICAgICAgIHZhciBkZXNjZW5kYW50SG9va3MgPSBmYWxzZTtcbiAgICAgICAgICAgICAgICB2YXIgaG9va3M7XG5cbiAgICAgICAgICAgICAgICBmb3IgKHZhciBwcm9wTmFtZSBpbiBwcm9wZXJ0aWVzKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmIChwcm9wZXJ0aWVzLmhhc093blByb3BlcnR5KHByb3BOYW1lKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgdmFyIHByb3BlcnR5ID0gcHJvcGVydGllc1twcm9wTmFtZV07XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoaXNWSG9vayhwcm9wZXJ0eSkgJiYgcHJvcGVydHkudW5ob29rKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKCFob29rcykge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBob29rcyA9IHt9O1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGhvb2tzW3Byb3BOYW1lXSA9IHByb3BlcnR5O1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCBjb3VudDsgaSsrKSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciBjaGlsZCA9IGNoaWxkcmVuW2ldO1xuICAgICAgICAgICAgICAgICAgICBpZiAoaXNWTm9kZShjaGlsZCkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGRlc2NlbmRhbnRzICs9IGNoaWxkLmNvdW50IHx8IDA7XG5cbiAgICAgICAgICAgICAgICAgICAgICAgIGlmICghaGFzV2lkZ2V0cyAmJiBjaGlsZC5oYXNXaWRnZXRzKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaGFzV2lkZ2V0cyA9IHRydWU7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgICAgIGlmICghaGFzVGh1bmtzICYmIGNoaWxkLmhhc1RodW5rcykge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGhhc1RodW5rcyA9IHRydWU7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgICAgIGlmICghZGVzY2VuZGFudEhvb2tzICYmIChjaGlsZC5ob29rcyB8fCBjaGlsZC5kZXNjZW5kYW50SG9va3MpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgZGVzY2VuZGFudEhvb2tzID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIGlmICghaGFzV2lkZ2V0cyAmJiBpc1dpZGdldChjaGlsZCkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmICh0eXBlb2YgY2hpbGQuZGVzdHJveSA9PT0gXCJmdW5jdGlvblwiKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaGFzV2lkZ2V0cyA9IHRydWU7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoIWhhc1RodW5rcyAmJiBpc1RodW5rKGNoaWxkKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgaGFzVGh1bmtzID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHRoaXMuY291bnQgPSBjb3VudCArIGRlc2NlbmRhbnRzO1xuICAgICAgICAgICAgICAgIHRoaXMuaGFzV2lkZ2V0cyA9IGhhc1dpZGdldHM7XG4gICAgICAgICAgICAgICAgdGhpcy5oYXNUaHVua3MgPSBoYXNUaHVua3M7XG4gICAgICAgICAgICAgICAgdGhpcy5ob29rcyA9IGhvb2tzO1xuICAgICAgICAgICAgICAgIHRoaXMuZGVzY2VuZGFudEhvb2tzID0gZGVzY2VuZGFudEhvb2tzO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBWaXJ0dWFsTm9kZS5wcm90b3R5cGUudmVyc2lvbiA9IHZlcnNpb247XG4gICAgICAgICAgICBWaXJ0dWFsTm9kZS5wcm90b3R5cGUudHlwZSA9IFwiVmlydHVhbE5vZGVcIjtcbiAgICAgICAgfSwgeyBcIi4vaXMtdGh1bmtcIjogMjUsIFwiLi9pcy12aG9va1wiOiAyNiwgXCIuL2lzLXZub2RlXCI6IDI3LCBcIi4vaXMtd2lkZ2V0XCI6IDI5LCBcIi4vdmVyc2lvblwiOiAzMCB9XSwgMzI6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICB2YXIgdmVyc2lvbiA9IHJlcXVpcmUoXCIuL3ZlcnNpb25cIik7XG5cbiAgICAgICAgICAgIFZpcnR1YWxQYXRjaC5OT05FID0gMDtcbiAgICAgICAgICAgIFZpcnR1YWxQYXRjaC5WVEVYVCA9IDE7XG4gICAgICAgICAgICBWaXJ0dWFsUGF0Y2guVk5PREUgPSAyO1xuICAgICAgICAgICAgVmlydHVhbFBhdGNoLldJREdFVCA9IDM7XG4gICAgICAgICAgICBWaXJ0dWFsUGF0Y2guUFJPUFMgPSA0O1xuICAgICAgICAgICAgVmlydHVhbFBhdGNoLk9SREVSID0gNTtcbiAgICAgICAgICAgIFZpcnR1YWxQYXRjaC5JTlNFUlQgPSA2O1xuICAgICAgICAgICAgVmlydHVhbFBhdGNoLlJFTU9WRSA9IDc7XG4gICAgICAgICAgICBWaXJ0dWFsUGF0Y2guVEhVTksgPSA4O1xuXG4gICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IFZpcnR1YWxQYXRjaDtcblxuICAgICAgICAgICAgZnVuY3Rpb24gVmlydHVhbFBhdGNoKHR5cGUsIHZOb2RlLCBwYXRjaCkge1xuICAgICAgICAgICAgICAgIHRoaXMudHlwZSA9IE51bWJlcih0eXBlKTtcbiAgICAgICAgICAgICAgICB0aGlzLnZOb2RlID0gdk5vZGU7XG4gICAgICAgICAgICAgICAgdGhpcy5wYXRjaCA9IHBhdGNoO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBWaXJ0dWFsUGF0Y2gucHJvdG90eXBlLnZlcnNpb24gPSB2ZXJzaW9uO1xuICAgICAgICAgICAgVmlydHVhbFBhdGNoLnByb3RvdHlwZS50eXBlID0gXCJWaXJ0dWFsUGF0Y2hcIjtcbiAgICAgICAgfSwgeyBcIi4vdmVyc2lvblwiOiAzMCB9XSwgMzM6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICB2YXIgdmVyc2lvbiA9IHJlcXVpcmUoXCIuL3ZlcnNpb25cIik7XG5cbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gVmlydHVhbFRleHQ7XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIFZpcnR1YWxUZXh0KHRleHQpIHtcbiAgICAgICAgICAgICAgICB0aGlzLnRleHQgPSBTdHJpbmcodGV4dCk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIFZpcnR1YWxUZXh0LnByb3RvdHlwZS52ZXJzaW9uID0gdmVyc2lvbjtcbiAgICAgICAgICAgIFZpcnR1YWxUZXh0LnByb3RvdHlwZS50eXBlID0gXCJWaXJ0dWFsVGV4dFwiO1xuICAgICAgICB9LCB7IFwiLi92ZXJzaW9uXCI6IDMwIH1dLCAzNDogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHtcbiAgICAgICAgICAgIHZhciBpc09iamVjdCA9IHJlcXVpcmUoXCJpcy1vYmplY3RcIik7XG4gICAgICAgICAgICB2YXIgaXNIb29rID0gcmVxdWlyZShcIi4uL3Zub2RlL2lzLXZob29rXCIpO1xuXG4gICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IGRpZmZQcm9wcztcblxuICAgICAgICAgICAgZnVuY3Rpb24gZGlmZlByb3BzKGEsIGIpIHtcbiAgICAgICAgICAgICAgICB2YXIgZGlmZjtcblxuICAgICAgICAgICAgICAgIGZvciAodmFyIGFLZXkgaW4gYSkge1xuICAgICAgICAgICAgICAgICAgICBpZiAoIShhS2V5IGluIGIpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBkaWZmID0gZGlmZiB8fCB7fTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGRpZmZbYUtleV0gPSB1bmRlZmluZWQ7XG4gICAgICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgICAgICB2YXIgYVZhbHVlID0gYVthS2V5XTtcbiAgICAgICAgICAgICAgICAgICAgdmFyIGJWYWx1ZSA9IGJbYUtleV07XG5cbiAgICAgICAgICAgICAgICAgICAgaWYgKGFWYWx1ZSA9PT0gYlZhbHVlKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBjb250aW51ZTtcbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIGlmIChpc09iamVjdChhVmFsdWUpICYmIGlzT2JqZWN0KGJWYWx1ZSkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChnZXRQcm90b3R5cGUoYlZhbHVlKSAhPT0gZ2V0UHJvdG90eXBlKGFWYWx1ZSkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBkaWZmID0gZGlmZiB8fCB7fTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBkaWZmW2FLZXldID0gYlZhbHVlO1xuICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIGlmIChpc0hvb2soYlZhbHVlKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRpZmYgPSBkaWZmIHx8IHt9O1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRpZmZbYUtleV0gPSBiVmFsdWU7XG4gICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZhciBvYmplY3REaWZmID0gZGlmZlByb3BzKGFWYWx1ZSwgYlZhbHVlKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAob2JqZWN0RGlmZikge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBkaWZmID0gZGlmZiB8fCB7fTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZGlmZlthS2V5XSA9IG9iamVjdERpZmY7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgZGlmZiA9IGRpZmYgfHwge307XG4gICAgICAgICAgICAgICAgICAgICAgICBkaWZmW2FLZXldID0gYlZhbHVlO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgZm9yICh2YXIgYktleSBpbiBiKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmICghKGJLZXkgaW4gYSkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGRpZmYgPSBkaWZmIHx8IHt9O1xuICAgICAgICAgICAgICAgICAgICAgICAgZGlmZltiS2V5XSA9IGJbYktleV07XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICByZXR1cm4gZGlmZjtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZnVuY3Rpb24gZ2V0UHJvdG90eXBlKHZhbHVlKSB7XG4gICAgICAgICAgICAgICAgaWYgKE9iamVjdC5nZXRQcm90b3R5cGVPZikge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gT2JqZWN0LmdldFByb3RvdHlwZU9mKHZhbHVlKTtcbiAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKHZhbHVlLl9fcHJvdG9fXykge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gdmFsdWUuX19wcm90b19fO1xuICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAodmFsdWUuY29uc3RydWN0b3IpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHZhbHVlLmNvbnN0cnVjdG9yLnByb3RvdHlwZTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH0sIHsgXCIuLi92bm9kZS9pcy12aG9va1wiOiAyNiwgXCJpcy1vYmplY3RcIjogMTEgfV0sIDM1OiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge1xuICAgICAgICAgICAgdmFyIGlzQXJyYXkgPSByZXF1aXJlKFwieC1pcy1hcnJheVwiKTtcblxuICAgICAgICAgICAgdmFyIFZQYXRjaCA9IHJlcXVpcmUoXCIuLi92bm9kZS92cGF0Y2hcIik7XG4gICAgICAgICAgICB2YXIgaXNWTm9kZSA9IHJlcXVpcmUoXCIuLi92bm9kZS9pcy12bm9kZVwiKTtcbiAgICAgICAgICAgIHZhciBpc1ZUZXh0ID0gcmVxdWlyZShcIi4uL3Zub2RlL2lzLXZ0ZXh0XCIpO1xuICAgICAgICAgICAgdmFyIGlzV2lkZ2V0ID0gcmVxdWlyZShcIi4uL3Zub2RlL2lzLXdpZGdldFwiKTtcbiAgICAgICAgICAgIHZhciBpc1RodW5rID0gcmVxdWlyZShcIi4uL3Zub2RlL2lzLXRodW5rXCIpO1xuICAgICAgICAgICAgdmFyIGhhbmRsZVRodW5rID0gcmVxdWlyZShcIi4uL3Zub2RlL2hhbmRsZS10aHVua1wiKTtcblxuICAgICAgICAgICAgdmFyIGRpZmZQcm9wcyA9IHJlcXVpcmUoXCIuL2RpZmYtcHJvcHNcIik7XG5cbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gZGlmZjtcblxuICAgICAgICAgICAgZnVuY3Rpb24gZGlmZihhLCBiKSB7XG4gICAgICAgICAgICAgICAgdmFyIHBhdGNoID0geyBhOiBhIH07XG4gICAgICAgICAgICAgICAgd2FsayhhLCBiLCBwYXRjaCwgMCk7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHBhdGNoO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBmdW5jdGlvbiB3YWxrKGEsIGIsIHBhdGNoLCBpbmRleCkge1xuICAgICAgICAgICAgICAgIGlmIChhID09PSBiKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICB2YXIgYXBwbHkgPSBwYXRjaFtpbmRleF07XG4gICAgICAgICAgICAgICAgdmFyIGFwcGx5Q2xlYXIgPSBmYWxzZTtcblxuICAgICAgICAgICAgICAgIGlmIChpc1RodW5rKGEpIHx8IGlzVGh1bmsoYikpIHtcbiAgICAgICAgICAgICAgICAgICAgdGh1bmtzKGEsIGIsIHBhdGNoLCBpbmRleCk7XG4gICAgICAgICAgICAgICAgfSBlbHNlIGlmIChiID09IG51bGwpIHtcblxuICAgICAgICAgICAgICAgICAgICAvLyBJZiBhIGlzIGEgd2lkZ2V0IHdlIHdpbGwgYWRkIGEgcmVtb3ZlIHBhdGNoIGZvciBpdFxuICAgICAgICAgICAgICAgICAgICAvLyBPdGhlcndpc2UgYW55IGNoaWxkIHdpZGdldHMvaG9va3MgbXVzdCBiZSBkZXN0cm95ZWQuXG4gICAgICAgICAgICAgICAgICAgIC8vIFRoaXMgcHJldmVudHMgYWRkaW5nIHR3byByZW1vdmUgcGF0Y2hlcyBmb3IgYSB3aWRnZXQuXG4gICAgICAgICAgICAgICAgICAgIGlmICghaXNXaWRnZXQoYSkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGNsZWFyU3RhdGUoYSwgcGF0Y2gsIGluZGV4KTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGFwcGx5ID0gcGF0Y2hbaW5kZXhdO1xuICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgYXBwbHkgPSBhcHBlbmRQYXRjaChhcHBseSwgbmV3IFZQYXRjaChWUGF0Y2guUkVNT1ZFLCBhLCBiKSk7XG4gICAgICAgICAgICAgICAgfSBlbHNlIGlmIChpc1ZOb2RlKGIpKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmIChpc1ZOb2RlKGEpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoYS50YWdOYW1lID09PSBiLnRhZ05hbWUgJiYgYS5uYW1lc3BhY2UgPT09IGIubmFtZXNwYWNlICYmIGEua2V5ID09PSBiLmtleSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZhciBwcm9wc1BhdGNoID0gZGlmZlByb3BzKGEucHJvcGVydGllcywgYi5wcm9wZXJ0aWVzKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAocHJvcHNQYXRjaCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBhcHBseSA9IGFwcGVuZFBhdGNoKGFwcGx5LCBuZXcgVlBhdGNoKFZQYXRjaC5QUk9QUywgYSwgcHJvcHNQYXRjaCkpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBhcHBseSA9IGRpZmZDaGlsZHJlbihhLCBiLCBwYXRjaCwgYXBwbHksIGluZGV4KTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgYXBwbHkgPSBhcHBlbmRQYXRjaChhcHBseSwgbmV3IFZQYXRjaChWUGF0Y2guVk5PREUsIGEsIGIpKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBhcHBseUNsZWFyID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGFwcGx5ID0gYXBwZW5kUGF0Y2goYXBwbHksIG5ldyBWUGF0Y2goVlBhdGNoLlZOT0RFLCBhLCBiKSk7XG4gICAgICAgICAgICAgICAgICAgICAgICBhcHBseUNsZWFyID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoaXNWVGV4dChiKSkge1xuICAgICAgICAgICAgICAgICAgICBpZiAoIWlzVlRleHQoYSkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGFwcGx5ID0gYXBwZW5kUGF0Y2goYXBwbHksIG5ldyBWUGF0Y2goVlBhdGNoLlZURVhULCBhLCBiKSk7XG4gICAgICAgICAgICAgICAgICAgICAgICBhcHBseUNsZWFyID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIGlmIChhLnRleHQgIT09IGIudGV4dCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgYXBwbHkgPSBhcHBlbmRQYXRjaChhcHBseSwgbmV3IFZQYXRjaChWUGF0Y2guVlRFWFQsIGEsIGIpKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoaXNXaWRnZXQoYikpIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKCFpc1dpZGdldChhKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgYXBwbHlDbGVhciA9IHRydWU7XG4gICAgICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgICAgICBhcHBseSA9IGFwcGVuZFBhdGNoKGFwcGx5LCBuZXcgVlBhdGNoKFZQYXRjaC5XSURHRVQsIGEsIGIpKTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICBpZiAoYXBwbHkpIHtcbiAgICAgICAgICAgICAgICAgICAgcGF0Y2hbaW5kZXhdID0gYXBwbHk7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgaWYgKGFwcGx5Q2xlYXIpIHtcbiAgICAgICAgICAgICAgICAgICAgY2xlYXJTdGF0ZShhLCBwYXRjaCwgaW5kZXgpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZnVuY3Rpb24gZGlmZkNoaWxkcmVuKGEsIGIsIHBhdGNoLCBhcHBseSwgaW5kZXgpIHtcbiAgICAgICAgICAgICAgICB2YXIgYUNoaWxkcmVuID0gYS5jaGlsZHJlbjtcbiAgICAgICAgICAgICAgICB2YXIgb3JkZXJlZFNldCA9IHJlb3JkZXIoYUNoaWxkcmVuLCBiLmNoaWxkcmVuKTtcbiAgICAgICAgICAgICAgICB2YXIgYkNoaWxkcmVuID0gb3JkZXJlZFNldC5jaGlsZHJlbjtcblxuICAgICAgICAgICAgICAgIHZhciBhTGVuID0gYUNoaWxkcmVuLmxlbmd0aDtcbiAgICAgICAgICAgICAgICB2YXIgYkxlbiA9IGJDaGlsZHJlbi5sZW5ndGg7XG4gICAgICAgICAgICAgICAgdmFyIGxlbiA9IGFMZW4gPiBiTGVuID8gYUxlbiA6IGJMZW47XG5cbiAgICAgICAgICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IGxlbjsgaSsrKSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciBsZWZ0Tm9kZSA9IGFDaGlsZHJlbltpXTtcbiAgICAgICAgICAgICAgICAgICAgdmFyIHJpZ2h0Tm9kZSA9IGJDaGlsZHJlbltpXTtcbiAgICAgICAgICAgICAgICAgICAgaW5kZXggKz0gMTtcblxuICAgICAgICAgICAgICAgICAgICBpZiAoIWxlZnROb2RlKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAocmlnaHROb2RlKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gRXhjZXNzIG5vZGVzIGluIGIgbmVlZCB0byBiZSBhZGRlZFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGFwcGx5ID0gYXBwZW5kUGF0Y2goYXBwbHksIG5ldyBWUGF0Y2goVlBhdGNoLklOU0VSVCwgbnVsbCwgcmlnaHROb2RlKSk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICB3YWxrKGxlZnROb2RlLCByaWdodE5vZGUsIHBhdGNoLCBpbmRleCk7XG4gICAgICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgICAgICBpZiAoaXNWTm9kZShsZWZ0Tm9kZSkgJiYgbGVmdE5vZGUuY291bnQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGluZGV4ICs9IGxlZnROb2RlLmNvdW50O1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgaWYgKG9yZGVyZWRTZXQubW92ZXMpIHtcbiAgICAgICAgICAgICAgICAgICAgLy8gUmVvcmRlciBub2RlcyBsYXN0XG4gICAgICAgICAgICAgICAgICAgIGFwcGx5ID0gYXBwZW5kUGF0Y2goYXBwbHksIG5ldyBWUGF0Y2goVlBhdGNoLk9SREVSLCBhLCBvcmRlcmVkU2V0Lm1vdmVzKSk7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgcmV0dXJuIGFwcGx5O1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBmdW5jdGlvbiBjbGVhclN0YXRlKHZOb2RlLCBwYXRjaCwgaW5kZXgpIHtcbiAgICAgICAgICAgICAgICAvLyBUT0RPOiBNYWtlIHRoaXMgYSBzaW5nbGUgd2Fsaywgbm90IHR3b1xuICAgICAgICAgICAgICAgIHVuaG9vayh2Tm9kZSwgcGF0Y2gsIGluZGV4KTtcbiAgICAgICAgICAgICAgICBkZXN0cm95V2lkZ2V0cyh2Tm9kZSwgcGF0Y2gsIGluZGV4KTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgLy8gUGF0Y2ggcmVjb3JkcyBmb3IgYWxsIGRlc3Ryb3llZCB3aWRnZXRzIG11c3QgYmUgYWRkZWQgYmVjYXVzZSB3ZSBuZWVkXG4gICAgICAgICAgICAvLyBhIERPTSBub2RlIHJlZmVyZW5jZSBmb3IgdGhlIGRlc3Ryb3kgZnVuY3Rpb25cbiAgICAgICAgICAgIGZ1bmN0aW9uIGRlc3Ryb3lXaWRnZXRzKHZOb2RlLCBwYXRjaCwgaW5kZXgpIHtcbiAgICAgICAgICAgICAgICBpZiAoaXNXaWRnZXQodk5vZGUpKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmICh0eXBlb2Ygdk5vZGUuZGVzdHJveSA9PT0gXCJmdW5jdGlvblwiKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBwYXRjaFtpbmRleF0gPSBhcHBlbmRQYXRjaChwYXRjaFtpbmRleF0sIG5ldyBWUGF0Y2goVlBhdGNoLlJFTU9WRSwgdk5vZGUsIG51bGwpKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoaXNWTm9kZSh2Tm9kZSkgJiYgKHZOb2RlLmhhc1dpZGdldHMgfHwgdk5vZGUuaGFzVGh1bmtzKSkge1xuICAgICAgICAgICAgICAgICAgICB2YXIgY2hpbGRyZW4gPSB2Tm9kZS5jaGlsZHJlbjtcbiAgICAgICAgICAgICAgICAgICAgdmFyIGxlbiA9IGNoaWxkcmVuLmxlbmd0aDtcbiAgICAgICAgICAgICAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCBsZW47IGkrKykge1xuICAgICAgICAgICAgICAgICAgICAgICAgdmFyIGNoaWxkID0gY2hpbGRyZW5baV07XG4gICAgICAgICAgICAgICAgICAgICAgICBpbmRleCArPSAxO1xuXG4gICAgICAgICAgICAgICAgICAgICAgICBkZXN0cm95V2lkZ2V0cyhjaGlsZCwgcGF0Y2gsIGluZGV4KTtcblxuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGlzVk5vZGUoY2hpbGQpICYmIGNoaWxkLmNvdW50KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaW5kZXggKz0gY2hpbGQuY291bnQ7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKGlzVGh1bmsodk5vZGUpKSB7XG4gICAgICAgICAgICAgICAgICAgIHRodW5rcyh2Tm9kZSwgbnVsbCwgcGF0Y2gsIGluZGV4KTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIC8vIENyZWF0ZSBhIHN1Yi1wYXRjaCBmb3IgdGh1bmtzXG4gICAgICAgICAgICBmdW5jdGlvbiB0aHVua3MoYSwgYiwgcGF0Y2gsIGluZGV4KSB7XG4gICAgICAgICAgICAgICAgdmFyIG5vZGVzID0gaGFuZGxlVGh1bmsoYSwgYik7XG4gICAgICAgICAgICAgICAgdmFyIHRodW5rUGF0Y2ggPSBkaWZmKG5vZGVzLmEsIG5vZGVzLmIpO1xuICAgICAgICAgICAgICAgIGlmIChoYXNQYXRjaGVzKHRodW5rUGF0Y2gpKSB7XG4gICAgICAgICAgICAgICAgICAgIHBhdGNoW2luZGV4XSA9IG5ldyBWUGF0Y2goVlBhdGNoLlRIVU5LLCBudWxsLCB0aHVua1BhdGNoKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIGhhc1BhdGNoZXMocGF0Y2gpIHtcbiAgICAgICAgICAgICAgICBmb3IgKHZhciBpbmRleCBpbiBwYXRjaCkge1xuICAgICAgICAgICAgICAgICAgICBpZiAoaW5kZXggIT09IFwiYVwiKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgLy8gRXhlY3V0ZSBob29rcyB3aGVuIHR3byBub2RlcyBhcmUgaWRlbnRpY2FsXG4gICAgICAgICAgICBmdW5jdGlvbiB1bmhvb2sodk5vZGUsIHBhdGNoLCBpbmRleCkge1xuICAgICAgICAgICAgICAgIGlmIChpc1ZOb2RlKHZOb2RlKSkge1xuICAgICAgICAgICAgICAgICAgICBpZiAodk5vZGUuaG9va3MpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHBhdGNoW2luZGV4XSA9IGFwcGVuZFBhdGNoKHBhdGNoW2luZGV4XSwgbmV3IFZQYXRjaChWUGF0Y2guUFJPUFMsIHZOb2RlLCB1bmRlZmluZWRLZXlzKHZOb2RlLmhvb2tzKSkpO1xuICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgaWYgKHZOb2RlLmRlc2NlbmRhbnRIb29rcyB8fCB2Tm9kZS5oYXNUaHVua3MpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHZhciBjaGlsZHJlbiA9IHZOb2RlLmNoaWxkcmVuO1xuICAgICAgICAgICAgICAgICAgICAgICAgdmFyIGxlbiA9IGNoaWxkcmVuLmxlbmd0aDtcbiAgICAgICAgICAgICAgICAgICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgbGVuOyBpKyspIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB2YXIgY2hpbGQgPSBjaGlsZHJlbltpXTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpbmRleCArPSAxO1xuXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdW5ob29rKGNoaWxkLCBwYXRjaCwgaW5kZXgpO1xuXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGlzVk5vZGUoY2hpbGQpICYmIGNoaWxkLmNvdW50KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGluZGV4ICs9IGNoaWxkLmNvdW50O1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoaXNUaHVuayh2Tm9kZSkpIHtcbiAgICAgICAgICAgICAgICAgICAgdGh1bmtzKHZOb2RlLCBudWxsLCBwYXRjaCwgaW5kZXgpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZnVuY3Rpb24gdW5kZWZpbmVkS2V5cyhvYmopIHtcbiAgICAgICAgICAgICAgICB2YXIgcmVzdWx0ID0ge307XG5cbiAgICAgICAgICAgICAgICBmb3IgKHZhciBrZXkgaW4gb2JqKSB7XG4gICAgICAgICAgICAgICAgICAgIHJlc3VsdFtrZXldID0gdW5kZWZpbmVkO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHJldHVybiByZXN1bHQ7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIC8vIExpc3QgZGlmZiwgbmFpdmUgbGVmdCB0byByaWdodCByZW9yZGVyaW5nXG4gICAgICAgICAgICBmdW5jdGlvbiByZW9yZGVyKGFDaGlsZHJlbiwgYkNoaWxkcmVuKSB7XG4gICAgICAgICAgICAgICAgLy8gTyhNKSB0aW1lLCBPKE0pIG1lbW9yeVxuICAgICAgICAgICAgICAgIHZhciBiQ2hpbGRJbmRleCA9IGtleUluZGV4KGJDaGlsZHJlbik7XG4gICAgICAgICAgICAgICAgdmFyIGJLZXlzID0gYkNoaWxkSW5kZXgua2V5cztcbiAgICAgICAgICAgICAgICB2YXIgYkZyZWUgPSBiQ2hpbGRJbmRleC5mcmVlO1xuXG4gICAgICAgICAgICAgICAgaWYgKGJGcmVlLmxlbmd0aCA9PT0gYkNoaWxkcmVuLmxlbmd0aCkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgICAgICAgICAgICAgY2hpbGRyZW46IGJDaGlsZHJlbixcbiAgICAgICAgICAgICAgICAgICAgICAgIG1vdmVzOiBudWxsXG4gICAgICAgICAgICAgICAgICAgIH07XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgLy8gTyhOKSB0aW1lLCBPKE4pIG1lbW9yeVxuICAgICAgICAgICAgICAgIHZhciBhQ2hpbGRJbmRleCA9IGtleUluZGV4KGFDaGlsZHJlbik7XG4gICAgICAgICAgICAgICAgdmFyIGFLZXlzID0gYUNoaWxkSW5kZXgua2V5cztcbiAgICAgICAgICAgICAgICB2YXIgYUZyZWUgPSBhQ2hpbGRJbmRleC5mcmVlO1xuXG4gICAgICAgICAgICAgICAgaWYgKGFGcmVlLmxlbmd0aCA9PT0gYUNoaWxkcmVuLmxlbmd0aCkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgICAgICAgICAgICAgY2hpbGRyZW46IGJDaGlsZHJlbixcbiAgICAgICAgICAgICAgICAgICAgICAgIG1vdmVzOiBudWxsXG4gICAgICAgICAgICAgICAgICAgIH07XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgLy8gTyhNQVgoTiwgTSkpIG1lbW9yeVxuICAgICAgICAgICAgICAgIHZhciBuZXdDaGlsZHJlbiA9IFtdO1xuXG4gICAgICAgICAgICAgICAgdmFyIGZyZWVJbmRleCA9IDA7XG4gICAgICAgICAgICAgICAgdmFyIGZyZWVDb3VudCA9IGJGcmVlLmxlbmd0aDtcbiAgICAgICAgICAgICAgICB2YXIgZGVsZXRlZEl0ZW1zID0gMDtcblxuICAgICAgICAgICAgICAgIC8vIEl0ZXJhdGUgdGhyb3VnaCBhIGFuZCBtYXRjaCBhIG5vZGUgaW4gYlxuICAgICAgICAgICAgICAgIC8vIE8oTikgdGltZSxcbiAgICAgICAgICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IGFDaGlsZHJlbi5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgICAgICAgICB2YXIgYUl0ZW0gPSBhQ2hpbGRyZW5baV07XG4gICAgICAgICAgICAgICAgICAgIHZhciBpdGVtSW5kZXg7XG5cbiAgICAgICAgICAgICAgICAgICAgaWYgKGFJdGVtLmtleSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGJLZXlzLmhhc093blByb3BlcnR5KGFJdGVtLmtleSkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBNYXRjaCB1cCB0aGUgb2xkIGtleXNcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpdGVtSW5kZXggPSBiS2V5c1thSXRlbS5rZXldO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIG5ld0NoaWxkcmVuLnB1c2goYkNoaWxkcmVuW2l0ZW1JbmRleF0pO1xuICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBSZW1vdmUgb2xkIGtleWVkIGl0ZW1zXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaXRlbUluZGV4ID0gaSAtIGRlbGV0ZWRJdGVtcysrO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIG5ld0NoaWxkcmVuLnB1c2gobnVsbCk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAvLyBNYXRjaCB0aGUgaXRlbSBpbiBhIHdpdGggdGhlIG5leHQgZnJlZSBpdGVtIGluIGJcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChmcmVlSW5kZXggPCBmcmVlQ291bnQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpdGVtSW5kZXggPSBiRnJlZVtmcmVlSW5kZXgrK107XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgbmV3Q2hpbGRyZW4ucHVzaChiQ2hpbGRyZW5baXRlbUluZGV4XSk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIFRoZXJlIGFyZSBubyBmcmVlIGl0ZW1zIGluIGIgdG8gbWF0Y2ggd2l0aFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIHRoZSBmcmVlIGl0ZW1zIGluIGEsIHNvIHRoZSBleHRyYSBmcmVlIG5vZGVzXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gYXJlIGRlbGV0ZWQuXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaXRlbUluZGV4ID0gaSAtIGRlbGV0ZWRJdGVtcysrO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIG5ld0NoaWxkcmVuLnB1c2gobnVsbCk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICB2YXIgbGFzdEZyZWVJbmRleCA9IGZyZWVJbmRleCA+PSBiRnJlZS5sZW5ndGggPyBiQ2hpbGRyZW4ubGVuZ3RoIDogYkZyZWVbZnJlZUluZGV4XTtcblxuICAgICAgICAgICAgICAgIC8vIEl0ZXJhdGUgdGhyb3VnaCBiIGFuZCBhcHBlbmQgYW55IG5ldyBrZXlzXG4gICAgICAgICAgICAgICAgLy8gTyhNKSB0aW1lXG4gICAgICAgICAgICAgICAgZm9yICh2YXIgaiA9IDA7IGogPCBiQ2hpbGRyZW4ubGVuZ3RoOyBqKyspIHtcbiAgICAgICAgICAgICAgICAgICAgdmFyIG5ld0l0ZW0gPSBiQ2hpbGRyZW5bal07XG5cbiAgICAgICAgICAgICAgICAgICAgaWYgKG5ld0l0ZW0ua2V5KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoIWFLZXlzLmhhc093blByb3BlcnR5KG5ld0l0ZW0ua2V5KSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIEFkZCBhbnkgbmV3IGtleWVkIGl0ZW1zXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gV2UgYXJlIGFkZGluZyBuZXcgaXRlbXMgdG8gdGhlIGVuZCBhbmQgdGhlbiBzb3J0aW5nIHRoZW1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBpbiBwbGFjZS4gSW4gZnV0dXJlIHdlIHNob3VsZCBpbnNlcnQgbmV3IGl0ZW1zIGluIHBsYWNlLlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIG5ld0NoaWxkcmVuLnB1c2gobmV3SXRlbSk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoaiA+PSBsYXN0RnJlZUluZGV4KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAvLyBBZGQgYW55IGxlZnRvdmVyIG5vbi1rZXllZCBpdGVtc1xuICAgICAgICAgICAgICAgICAgICAgICAgbmV3Q2hpbGRyZW4ucHVzaChuZXdJdGVtKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHZhciBzaW11bGF0ZSA9IG5ld0NoaWxkcmVuLnNsaWNlKCk7XG4gICAgICAgICAgICAgICAgdmFyIHNpbXVsYXRlSW5kZXggPSAwO1xuICAgICAgICAgICAgICAgIHZhciByZW1vdmVzID0gW107XG4gICAgICAgICAgICAgICAgdmFyIGluc2VydHMgPSBbXTtcbiAgICAgICAgICAgICAgICB2YXIgc2ltdWxhdGVJdGVtO1xuXG4gICAgICAgICAgICAgICAgZm9yICh2YXIgayA9IDA7IGsgPCBiQ2hpbGRyZW4ubGVuZ3RoOykge1xuICAgICAgICAgICAgICAgICAgICB2YXIgd2FudGVkSXRlbSA9IGJDaGlsZHJlbltrXTtcbiAgICAgICAgICAgICAgICAgICAgc2ltdWxhdGVJdGVtID0gc2ltdWxhdGVbc2ltdWxhdGVJbmRleF07XG5cbiAgICAgICAgICAgICAgICAgICAgLy8gcmVtb3ZlIGl0ZW1zXG4gICAgICAgICAgICAgICAgICAgIHdoaWxlIChzaW11bGF0ZUl0ZW0gPT09IG51bGwgJiYgc2ltdWxhdGUubGVuZ3RoKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICByZW1vdmVzLnB1c2gocmVtb3ZlKHNpbXVsYXRlLCBzaW11bGF0ZUluZGV4LCBudWxsKSk7XG4gICAgICAgICAgICAgICAgICAgICAgICBzaW11bGF0ZUl0ZW0gPSBzaW11bGF0ZVtzaW11bGF0ZUluZGV4XTtcbiAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgIGlmICghc2ltdWxhdGVJdGVtIHx8IHNpbXVsYXRlSXRlbS5rZXkgIT09IHdhbnRlZEl0ZW0ua2V5KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAvLyBpZiB3ZSBuZWVkIGEga2V5IGluIHRoaXMgcG9zaXRpb24uLi5cbiAgICAgICAgICAgICAgICAgICAgICAgIGlmICh3YW50ZWRJdGVtLmtleSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChzaW11bGF0ZUl0ZW0gJiYgc2ltdWxhdGVJdGVtLmtleSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBpZiBhbiBpbnNlcnQgZG9lc24ndCBwdXQgdGhpcyBrZXkgaW4gcGxhY2UsIGl0IG5lZWRzIHRvIG1vdmVcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGJLZXlzW3NpbXVsYXRlSXRlbS5rZXldICE9PSBrICsgMSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmVtb3Zlcy5wdXNoKHJlbW92ZShzaW11bGF0ZSwgc2ltdWxhdGVJbmRleCwgc2ltdWxhdGVJdGVtLmtleSkpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc2ltdWxhdGVJdGVtID0gc2ltdWxhdGVbc2ltdWxhdGVJbmRleF07XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBpZiB0aGUgcmVtb3ZlIGRpZG4ndCBwdXQgdGhlIHdhbnRlZCBpdGVtIGluIHBsYWNlLCB3ZSBuZWVkIHRvIGluc2VydCBpdFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKCFzaW11bGF0ZUl0ZW0gfHwgc2ltdWxhdGVJdGVtLmtleSAhPT0gd2FudGVkSXRlbS5rZXkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpbnNlcnRzLnB1c2goeyBrZXk6IHdhbnRlZEl0ZW0ua2V5LCB0bzogayB9KTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIGl0ZW1zIGFyZSBtYXRjaGluZywgc28gc2tpcCBhaGVhZFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc2ltdWxhdGVJbmRleCsrO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaW5zZXJ0cy5wdXNoKHsga2V5OiB3YW50ZWRJdGVtLmtleSwgdG86IGsgfSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpbnNlcnRzLnB1c2goeyBrZXk6IHdhbnRlZEl0ZW0ua2V5LCB0bzogayB9KTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaysrO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgLy8gYSBrZXkgaW4gc2ltdWxhdGUgaGFzIG5vIG1hdGNoaW5nIHdhbnRlZCBrZXksIHJlbW92ZSBpdFxuICAgICAgICAgICAgICAgICAgICAgICAgZWxzZSBpZiAoc2ltdWxhdGVJdGVtICYmIHNpbXVsYXRlSXRlbS5rZXkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICByZW1vdmVzLnB1c2gocmVtb3ZlKHNpbXVsYXRlLCBzaW11bGF0ZUluZGV4LCBzaW11bGF0ZUl0ZW0ua2V5KSk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBzaW11bGF0ZUluZGV4Kys7XG4gICAgICAgICAgICAgICAgICAgICAgICBrKys7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAvLyByZW1vdmUgYWxsIHRoZSByZW1haW5pbmcgbm9kZXMgZnJvbSBzaW11bGF0ZVxuICAgICAgICAgICAgICAgIHdoaWxlIChzaW11bGF0ZUluZGV4IDwgc2ltdWxhdGUubGVuZ3RoKSB7XG4gICAgICAgICAgICAgICAgICAgIHNpbXVsYXRlSXRlbSA9IHNpbXVsYXRlW3NpbXVsYXRlSW5kZXhdO1xuICAgICAgICAgICAgICAgICAgICByZW1vdmVzLnB1c2gocmVtb3ZlKHNpbXVsYXRlLCBzaW11bGF0ZUluZGV4LCBzaW11bGF0ZUl0ZW0gJiYgc2ltdWxhdGVJdGVtLmtleSkpO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIC8vIElmIHRoZSBvbmx5IG1vdmVzIHdlIGhhdmUgYXJlIGRlbGV0ZXMgdGhlbiB3ZSBjYW4ganVzdFxuICAgICAgICAgICAgICAgIC8vIGxldCB0aGUgZGVsZXRlIHBhdGNoIHJlbW92ZSB0aGVzZSBpdGVtcy5cbiAgICAgICAgICAgICAgICBpZiAocmVtb3Zlcy5sZW5ndGggPT09IGRlbGV0ZWRJdGVtcyAmJiAhaW5zZXJ0cy5sZW5ndGgpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGNoaWxkcmVuOiBuZXdDaGlsZHJlbixcbiAgICAgICAgICAgICAgICAgICAgICAgIG1vdmVzOiBudWxsXG4gICAgICAgICAgICAgICAgICAgIH07XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgICAgICAgICAgY2hpbGRyZW46IG5ld0NoaWxkcmVuLFxuICAgICAgICAgICAgICAgICAgICBtb3Zlczoge1xuICAgICAgICAgICAgICAgICAgICAgICAgcmVtb3ZlczogcmVtb3ZlcyxcbiAgICAgICAgICAgICAgICAgICAgICAgIGluc2VydHM6IGluc2VydHNcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH07XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIHJlbW92ZShhcnIsIGluZGV4LCBrZXkpIHtcbiAgICAgICAgICAgICAgICBhcnIuc3BsaWNlKGluZGV4LCAxKTtcblxuICAgICAgICAgICAgICAgIHJldHVybiB7XG4gICAgICAgICAgICAgICAgICAgIGZyb206IGluZGV4LFxuICAgICAgICAgICAgICAgICAgICBrZXk6IGtleVxuICAgICAgICAgICAgICAgIH07XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIGtleUluZGV4KGNoaWxkcmVuKSB7XG4gICAgICAgICAgICAgICAgdmFyIGtleXMgPSB7fTtcbiAgICAgICAgICAgICAgICB2YXIgZnJlZSA9IFtdO1xuICAgICAgICAgICAgICAgIHZhciBsZW5ndGggPSBjaGlsZHJlbi5sZW5ndGg7XG5cbiAgICAgICAgICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IGxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciBjaGlsZCA9IGNoaWxkcmVuW2ldO1xuXG4gICAgICAgICAgICAgICAgICAgIGlmIChjaGlsZC5rZXkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGtleXNbY2hpbGQua2V5XSA9IGk7XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBmcmVlLnB1c2goaSk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgICAgICAgICBrZXlzOiBrZXlzLCAvLyBBIGhhc2ggb2Yga2V5IG5hbWUgdG8gaW5kZXhcbiAgICAgICAgICAgICAgICAgICAgZnJlZTogZnJlZSAvLyBBbiBhcnJheSBvZiB1bmtleWVkIGl0ZW0gaW5kaWNlc1xuICAgICAgICAgICAgICAgIH07XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIGFwcGVuZFBhdGNoKGFwcGx5LCBwYXRjaCkge1xuICAgICAgICAgICAgICAgIGlmIChhcHBseSkge1xuICAgICAgICAgICAgICAgICAgICBpZiAoaXNBcnJheShhcHBseSkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGFwcGx5LnB1c2gocGF0Y2gpO1xuICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgYXBwbHkgPSBbYXBwbHksIHBhdGNoXTtcbiAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBhcHBseTtcbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gcGF0Y2g7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9LCB7IFwiLi4vdm5vZGUvaGFuZGxlLXRodW5rXCI6IDI0LCBcIi4uL3Zub2RlL2lzLXRodW5rXCI6IDI1LCBcIi4uL3Zub2RlL2lzLXZub2RlXCI6IDI3LCBcIi4uL3Zub2RlL2lzLXZ0ZXh0XCI6IDI4LCBcIi4uL3Zub2RlL2lzLXdpZGdldFwiOiAyOSwgXCIuLi92bm9kZS92cGF0Y2hcIjogMzIsIFwiLi9kaWZmLXByb3BzXCI6IDM0LCBcIngtaXMtYXJyYXlcIjogMTIgfV0gfSwge30sIFs0XSkoNCk7XG59KTtcblxuY29uc3Qgc3RhcnQgPSBmdW5jdGlvbiAoZG9tUm9vdCwgcmVuZGVyRm4sIGluaXRpYWxTdGF0ZSwgb3B0aW9ucyA9IFtdKSB7XG4gIGxldCBwaWQgPSBzZWxmLnByb2Nlc3Nlcy5zcGF3bigpO1xuXG4gIGlmIChLZXl3b3JkLmhhc19rZXlfX3FtX18ob3B0aW9ucywgS2VybmVsLlNwZWNpYWxGb3Jtcy5hdG9tKCduYW1lJykpKSB7XG4gICAgcGlkID0gc2VsZi5wcm9jZXNzZXMucmVnaXN0ZXIoS2V5d29yZC5nZXQob3B0aW9ucywgS2VybmVsLlNwZWNpYWxGb3Jtcy5hdG9tKCduYW1lJykpLCBwaWQpO1xuICB9XG5cbiAgY29uc3QgdHJlZSA9IHJlbmRlckZuLmFwcGx5KHRoaXMsIGluaXRpYWxTdGF0ZSk7XG4gIGNvbnN0IHJvb3ROb2RlID0gVmlydHVhbERPTS5jcmVhdGUodHJlZSk7XG5cbiAgZG9tUm9vdC5hcHBlbmRDaGlsZChyb290Tm9kZSk7XG5cbiAgc2VsZi5wcm9jZXNzZXMucHV0KHBpZCwgJ3N0YXRlJywgS2VybmVsLlNwZWNpYWxGb3Jtcy50dXBsZShyb290Tm9kZSwgdHJlZSwgcmVuZGVyRm4pKTtcbiAgcmV0dXJuIEtlcm5lbC5TcGVjaWFsRm9ybXMudHVwbGUoS2VybmVsLlNwZWNpYWxGb3Jtcy5hdG9tKCdvaycpLCBwaWQpO1xufTtcblxuY29uc3Qgc3RvcCA9IGZ1bmN0aW9uIChhZ2VudCwgdGltZW91dCA9IDUwMDApIHtcbiAgc2VsZi5wcm9jZXNzZXMuZXhpdChhZ2VudCk7XG4gIHJldHVybiBLZXJuZWwuU3BlY2lhbEZvcm1zLmF0b20oJ29rJyk7XG59O1xuXG5jb25zdCByZW5kZXIgPSBmdW5jdGlvbiAoYWdlbnQsIHN0YXRlKSB7XG5cbiAgY29uc3QgY3VycmVudF9zdGF0ZSA9IHNlbGYucHJvY2Vzc2VzLmdldChhZ2VudCwgJ3N0YXRlJyk7XG5cbiAgbGV0IHJvb3ROb2RlID0gS2VybmVsLmVsZW0oY3VycmVudF9zdGF0ZSwgMCk7XG4gIGxldCB0cmVlID0gS2VybmVsLmVsZW0oY3VycmVudF9zdGF0ZSwgMSk7XG4gIGxldCByZW5kZXJGbiA9IEtlcm5lbC5lbGVtKGN1cnJlbnRfc3RhdGUsIDIpO1xuXG4gIGxldCBuZXdUcmVlID0gcmVuZGVyRm4uYXBwbHkodGhpcywgc3RhdGUpO1xuXG4gIGxldCBwYXRjaGVzID0gVmlydHVhbERPTS5kaWZmKHRyZWUsIG5ld1RyZWUpO1xuICByb290Tm9kZSA9IFZpcnR1YWxET00ucGF0Y2gocm9vdE5vZGUsIHBhdGNoZXMpO1xuXG4gIHNlbGYucHJvY2Vzc2VzLnB1dChhZ2VudCwgJ3N0YXRlJywgS2VybmVsLlNwZWNpYWxGb3Jtcy50dXBsZShyb290Tm9kZSwgbmV3VHJlZSwgcmVuZGVyRm4pKTtcblxuICByZXR1cm4gS2VybmVsLlNwZWNpYWxGb3Jtcy5hdG9tKCdvaycpO1xufTtcblxudmFyIHZpZXcgPSB7XG4gIHN0YXJ0LFxuICBzdG9wLFxuICByZW5kZXJcbn07XG5cbnNlbGYucHJvY2Vzc2VzID0gc2VsZi5wcm9jZXNzZXMgfHwgbmV3IFByb2Nlc3NTeXN0ZW0oKTtcblxuY29uc3QgQ29yZSA9IEM7XG5cbmV4cG9ydCB7IENvcmUsIEtlcm5lbCwgQXRvbSwgRW51bSwgSW50ZWdlciwgTGlzdCwgUmFuZ2UsIFR1cGxlLCBBZ2VudCwgS2V5d29yZCwgYmFzZSBhcyBCYXNlLCBTdHJpbmckMSBhcyBTdHJpbmcsIGJpdHdpc2UgYXMgQml0d2lzZSwgRW51bWVyYWJsZSwgQ29sbGVjdGFibGUsIEluc3BlY3QsIG1hcCBhcyBNYXAsIHNldCBhcyBTZXQsIE1hcFNldCwgVmlydHVhbERPTSwgdmlldyBhcyBWaWV3IH07Il0sImZpbGUiOiJlbGl4aXIuanMiLCJzb3VyY2VSb290IjoiL3NvdXJjZS8ifQ== \ No newline at end of file +//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiIiwic291cmNlcyI6WyJlbGl4aXIuanMiXSwic291cmNlc0NvbnRlbnQiOlsiZnVuY3Rpb24gY2FsbF9wcm9wZXJ0eShpdGVtLCBwcm9wZXJ0eSkge1xuICBpZiAocHJvcGVydHkgaW4gaXRlbSkge1xuICAgIGl0ZW1bcHJvcGVydHldO1xuICAgIGlmIChpdGVtW3Byb3BlcnR5XSBpbnN0YW5jZW9mIEZ1bmN0aW9uKSB7XG4gICAgICByZXR1cm4gaXRlbVtwcm9wZXJ0eV0oKTtcbiAgICB9IGVsc2Uge1xuICAgICAgcmV0dXJuIGl0ZW1bcHJvcGVydHldO1xuICAgIH1cbiAgfSBlbHNlIGlmIChTeW1ib2wuZm9yKHByb3BlcnR5KSBpbiBpdGVtKSB7XG4gICAgbGV0IHByb3AgPSBTeW1ib2wuZm9yKHByb3BlcnR5KTtcbiAgICBpZiAoaXRlbVtwcm9wXSBpbnN0YW5jZW9mIEZ1bmN0aW9uKSB7XG4gICAgICByZXR1cm4gaXRlbVtwcm9wXSgpO1xuICAgIH0gZWxzZSB7XG4gICAgICByZXR1cm4gaXRlbVtwcm9wXTtcbiAgICB9XG4gIH1cblxuICB0aHJvdyBuZXcgRXJyb3IoYFByb3BlcnR5ICR7IHByb3BlcnR5IH0gbm90IGZvdW5kIGluICR7IGl0ZW0gfWApO1xufVxuXG5jbGFzcyBUdXBsZSQxIHtcblxuICBjb25zdHJ1Y3RvciguLi5hcmdzKSB7XG4gICAgdGhpcy52YWx1ZXMgPSBPYmplY3QuZnJlZXplKGFyZ3MpO1xuICB9XG5cbiAgZ2V0KGluZGV4KSB7XG4gICAgcmV0dXJuIHRoaXMudmFsdWVzW2luZGV4XTtcbiAgfVxuXG4gIGNvdW50KCkge1xuICAgIHJldHVybiB0aGlzLnZhbHVlcy5sZW5ndGg7XG4gIH1cblxuICBbU3ltYm9sLml0ZXJhdG9yXSgpIHtcbiAgICByZXR1cm4gdGhpcy52YWx1ZXNbU3ltYm9sLml0ZXJhdG9yXSgpO1xuICB9XG5cbiAgdG9TdHJpbmcoKSB7XG4gICAgdmFyIGksXG4gICAgICAgIHMgPSBcIlwiO1xuICAgIGZvciAoaSA9IDA7IGkgPCB0aGlzLnZhbHVlcy5sZW5ndGg7IGkrKykge1xuICAgICAgaWYgKHMgIT09IFwiXCIpIHtcbiAgICAgICAgcyArPSBcIiwgXCI7XG4gICAgICB9XG4gICAgICBzICs9IHRoaXMudmFsdWVzW2ldLnRvU3RyaW5nKCk7XG4gICAgfVxuXG4gICAgcmV0dXJuIFwie1wiICsgcyArIFwifVwiO1xuICB9XG5cbn1cblxubGV0IHByb2Nlc3NfY291bnRlciA9IC0xO1xuXG5jbGFzcyBQSUQge1xuICBjb25zdHJ1Y3RvcigpIHtcbiAgICBwcm9jZXNzX2NvdW50ZXIgPSBwcm9jZXNzX2NvdW50ZXIgKyAxO1xuICAgIHRoaXMuaWQgPSBwcm9jZXNzX2NvdW50ZXI7XG4gIH1cblxuICB0b1N0cmluZygpIHtcbiAgICByZXR1cm4gXCJQSUQjPDAuXCIgKyB0aGlzLmlkICsgXCIuMD5cIjtcbiAgfVxufVxuXG5jbGFzcyBJbnRlZ2VyJDEge31cbmNsYXNzIEZsb2F0IHt9XG5cbi8qIEBmbG93ICovXG5cbmNsYXNzIFZhcmlhYmxlIHtcblxuICBjb25zdHJ1Y3RvcihuYW1lID0gbnVsbCkge1xuICAgIHRoaXMubmFtZSA9IG5hbWU7XG4gIH1cbn1cblxuY2xhc3MgV2lsZGNhcmQge1xuICBjb25zdHJ1Y3RvcigpIHt9XG59XG5cbmNsYXNzIFN0YXJ0c1dpdGgge1xuXG4gIGNvbnN0cnVjdG9yKHByZWZpeCkge1xuICAgIHRoaXMucHJlZml4ID0gcHJlZml4O1xuICB9XG59XG5cbmNsYXNzIENhcHR1cmUge1xuXG4gIGNvbnN0cnVjdG9yKHZhbHVlKSB7XG4gICAgdGhpcy52YWx1ZSA9IHZhbHVlO1xuICB9XG59XG5cbmNsYXNzIEhlYWRUYWlsIHtcbiAgY29uc3RydWN0b3IoKSB7fVxufVxuXG5jbGFzcyBUeXBlIHtcblxuICBjb25zdHJ1Y3Rvcih0eXBlLCBvYmpQYXR0ZXJuID0ge30pIHtcbiAgICB0aGlzLnR5cGUgPSB0eXBlO1xuICAgIHRoaXMub2JqUGF0dGVybiA9IG9ialBhdHRlcm47XG4gIH1cbn1cblxuY2xhc3MgQm91bmQge1xuXG4gIGNvbnN0cnVjdG9yKHZhbHVlKSB7XG4gICAgdGhpcy52YWx1ZSA9IHZhbHVlO1xuICB9XG59XG5cbmZ1bmN0aW9uIHZhcmlhYmxlKG5hbWUgPSBudWxsKSB7XG4gIHJldHVybiBuZXcgVmFyaWFibGUobmFtZSk7XG59XG5cbmZ1bmN0aW9uIHdpbGRjYXJkKCkge1xuICByZXR1cm4gbmV3IFdpbGRjYXJkKCk7XG59XG5cbmZ1bmN0aW9uIHN0YXJ0c1dpdGgocHJlZml4KSB7XG4gIHJldHVybiBuZXcgU3RhcnRzV2l0aChwcmVmaXgpO1xufVxuXG5mdW5jdGlvbiBjYXB0dXJlKHZhbHVlKSB7XG4gIHJldHVybiBuZXcgQ2FwdHVyZSh2YWx1ZSk7XG59XG5cbmZ1bmN0aW9uIGhlYWRUYWlsKCkge1xuICByZXR1cm4gbmV3IEhlYWRUYWlsKCk7XG59XG5cbmZ1bmN0aW9uIHR5cGUodHlwZSwgb2JqUGF0dGVybiA9IHt9KSB7XG4gIHJldHVybiBuZXcgVHlwZSh0eXBlLCBvYmpQYXR0ZXJuKTtcbn1cblxuZnVuY3Rpb24gYm91bmQodmFsdWUpIHtcbiAgcmV0dXJuIG5ldyBCb3VuZCh2YWx1ZSk7XG59XG5cbmZ1bmN0aW9uIGlzX251bWJlciQxKHZhbHVlKSB7XG4gIHJldHVybiB0eXBlb2YgdmFsdWUgPT09ICdudW1iZXInO1xufVxuXG5mdW5jdGlvbiBpc19zdHJpbmcodmFsdWUpIHtcbiAgcmV0dXJuIHR5cGVvZiB2YWx1ZSA9PT0gJ3N0cmluZyc7XG59XG5cbmZ1bmN0aW9uIGlzX2Jvb2xlYW4kMSh2YWx1ZSkge1xuICByZXR1cm4gdHlwZW9mIHZhbHVlID09PSAnYm9vbGVhbic7XG59XG5cbmZ1bmN0aW9uIGlzX3N5bWJvbCh2YWx1ZSkge1xuICByZXR1cm4gdHlwZW9mIHZhbHVlID09PSAnc3ltYm9sJztcbn1cblxuZnVuY3Rpb24gaXNfbnVsbCh2YWx1ZSkge1xuICByZXR1cm4gdmFsdWUgPT09IG51bGw7XG59XG5cbmZ1bmN0aW9uIGlzX3VuZGVmaW5lZCh2YWx1ZSkge1xuICByZXR1cm4gdHlwZW9mIHZhbHVlID09PSAndW5kZWZpbmVkJztcbn1cblxuZnVuY3Rpb24gaXNfZnVuY3Rpb24kMSh2YWx1ZSkge1xuICByZXR1cm4gT2JqZWN0LnByb3RvdHlwZS50b1N0cmluZy5jYWxsKHZhbHVlKSA9PSAnW29iamVjdCBGdW5jdGlvbl0nO1xufVxuXG5mdW5jdGlvbiBpc192YXJpYWJsZSh2YWx1ZSkge1xuICByZXR1cm4gdmFsdWUgaW5zdGFuY2VvZiBWYXJpYWJsZTtcbn1cblxuZnVuY3Rpb24gaXNfd2lsZGNhcmQodmFsdWUpIHtcbiAgcmV0dXJuIHZhbHVlIGluc3RhbmNlb2YgV2lsZGNhcmQ7XG59XG5cbmZ1bmN0aW9uIGlzX2hlYWRUYWlsKHZhbHVlKSB7XG4gIHJldHVybiB2YWx1ZSBpbnN0YW5jZW9mIEhlYWRUYWlsO1xufVxuXG5mdW5jdGlvbiBpc19jYXB0dXJlKHZhbHVlKSB7XG4gIHJldHVybiB2YWx1ZSBpbnN0YW5jZW9mIENhcHR1cmU7XG59XG5cbmZ1bmN0aW9uIGlzX3R5cGUodmFsdWUpIHtcbiAgcmV0dXJuIHZhbHVlIGluc3RhbmNlb2YgVHlwZTtcbn1cblxuZnVuY3Rpb24gaXNfc3RhcnRzV2l0aCh2YWx1ZSkge1xuICByZXR1cm4gdmFsdWUgaW5zdGFuY2VvZiBTdGFydHNXaXRoO1xufVxuXG5mdW5jdGlvbiBpc19ib3VuZCh2YWx1ZSkge1xuICByZXR1cm4gdmFsdWUgaW5zdGFuY2VvZiBCb3VuZDtcbn1cblxuZnVuY3Rpb24gaXNfb2JqZWN0KHZhbHVlKSB7XG4gIHJldHVybiB0eXBlb2YgdmFsdWUgPT09ICdvYmplY3QnO1xufVxuXG5mdW5jdGlvbiBpc19hcnJheSh2YWx1ZSkge1xuICByZXR1cm4gQXJyYXkuaXNBcnJheSh2YWx1ZSk7XG59XG5cbnZhciBDaGVja3MgPSB7XG4gIGlzX251bWJlcjogaXNfbnVtYmVyJDEsXG4gIGlzX3N0cmluZyxcbiAgaXNfYm9vbGVhbjogaXNfYm9vbGVhbiQxLFxuICBpc19zeW1ib2wsXG4gIGlzX251bGwsXG4gIGlzX3VuZGVmaW5lZCxcbiAgaXNfZnVuY3Rpb246IGlzX2Z1bmN0aW9uJDEsXG4gIGlzX3ZhcmlhYmxlLFxuICBpc193aWxkY2FyZCxcbiAgaXNfaGVhZFRhaWwsXG4gIGlzX2NhcHR1cmUsXG4gIGlzX3R5cGUsXG4gIGlzX3N0YXJ0c1dpdGgsXG4gIGlzX2JvdW5kLFxuICBpc19vYmplY3QsXG4gIGlzX2FycmF5XG59O1xuXG5mdW5jdGlvbiByZXNvbHZlU3ltYm9sKHBhdHRlcm4pIHtcbiAgcmV0dXJuIGZ1bmN0aW9uICh2YWx1ZSkge1xuICAgIHJldHVybiBDaGVja3MuaXNfc3ltYm9sKHZhbHVlKSAmJiB2YWx1ZSA9PT0gcGF0dGVybjtcbiAgfTtcbn1cblxuZnVuY3Rpb24gcmVzb2x2ZVN0cmluZyhwYXR0ZXJuKSB7XG4gIHJldHVybiBmdW5jdGlvbiAodmFsdWUpIHtcbiAgICByZXR1cm4gQ2hlY2tzLmlzX3N0cmluZyh2YWx1ZSkgJiYgdmFsdWUgPT09IHBhdHRlcm47XG4gIH07XG59XG5cbmZ1bmN0aW9uIHJlc29sdmVOdW1iZXIocGF0dGVybikge1xuICByZXR1cm4gZnVuY3Rpb24gKHZhbHVlKSB7XG4gICAgcmV0dXJuIENoZWNrcy5pc19udW1iZXIodmFsdWUpICYmIHZhbHVlID09PSBwYXR0ZXJuO1xuICB9O1xufVxuXG5mdW5jdGlvbiByZXNvbHZlQm9vbGVhbihwYXR0ZXJuKSB7XG4gIHJldHVybiBmdW5jdGlvbiAodmFsdWUpIHtcbiAgICByZXR1cm4gQ2hlY2tzLmlzX2Jvb2xlYW4odmFsdWUpICYmIHZhbHVlID09PSBwYXR0ZXJuO1xuICB9O1xufVxuXG5mdW5jdGlvbiByZXNvbHZlRnVuY3Rpb24ocGF0dGVybikge1xuICByZXR1cm4gZnVuY3Rpb24gKHZhbHVlKSB7XG4gICAgcmV0dXJuIENoZWNrcy5pc19mdW5jdGlvbih2YWx1ZSkgJiYgdmFsdWUgPT09IHBhdHRlcm47XG4gIH07XG59XG5cbmZ1bmN0aW9uIHJlc29sdmVOdWxsKHBhdHRlcm4pIHtcbiAgcmV0dXJuIGZ1bmN0aW9uICh2YWx1ZSkge1xuICAgIHJldHVybiBDaGVja3MuaXNfbnVsbCh2YWx1ZSk7XG4gIH07XG59XG5cbmZ1bmN0aW9uIHJlc29sdmVCb3VuZChwYXR0ZXJuKSB7XG4gIHJldHVybiBmdW5jdGlvbiAodmFsdWUsIGFyZ3MpIHtcbiAgICBpZiAodHlwZW9mIHZhbHVlID09PSB0eXBlb2YgcGF0dGVybi52YWx1ZSAmJiB2YWx1ZSA9PT0gcGF0dGVybi52YWx1ZSkge1xuICAgICAgYXJncy5wdXNoKHZhbHVlKTtcbiAgICAgIHJldHVybiB0cnVlO1xuICAgIH1cblxuICAgIHJldHVybiBmYWxzZTtcbiAgfTtcbn1cblxuZnVuY3Rpb24gcmVzb2x2ZVdpbGRjYXJkKCkge1xuICByZXR1cm4gZnVuY3Rpb24gKCkge1xuICAgIHJldHVybiB0cnVlO1xuICB9O1xufVxuXG5mdW5jdGlvbiByZXNvbHZlVmFyaWFibGUoKSB7XG4gIHJldHVybiBmdW5jdGlvbiAodmFsdWUsIGFyZ3MpIHtcbiAgICBhcmdzLnB1c2godmFsdWUpO1xuICAgIHJldHVybiB0cnVlO1xuICB9O1xufVxuXG5mdW5jdGlvbiByZXNvbHZlSGVhZFRhaWwoKSB7XG4gIHJldHVybiBmdW5jdGlvbiAodmFsdWUsIGFyZ3MpIHtcbiAgICBpZiAoIUNoZWNrcy5pc19hcnJheSh2YWx1ZSkgfHwgdmFsdWUubGVuZ3RoIDwgMikge1xuICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH1cblxuICAgIGNvbnN0IGhlYWQgPSB2YWx1ZVswXTtcbiAgICBjb25zdCB0YWlsID0gdmFsdWUuc2xpY2UoMSk7XG5cbiAgICBhcmdzLnB1c2goaGVhZCk7XG4gICAgYXJncy5wdXNoKHRhaWwpO1xuXG4gICAgcmV0dXJuIHRydWU7XG4gIH07XG59XG5cbmZ1bmN0aW9uIHJlc29sdmVDYXB0dXJlKHBhdHRlcm4pIHtcbiAgY29uc3QgbWF0Y2hlcyA9IGJ1aWxkTWF0Y2gocGF0dGVybi52YWx1ZSk7XG5cbiAgcmV0dXJuIGZ1bmN0aW9uICh2YWx1ZSwgYXJncykge1xuICAgIGlmIChtYXRjaGVzKHZhbHVlLCBhcmdzKSkge1xuICAgICAgYXJncy5wdXNoKHZhbHVlKTtcbiAgICAgIHJldHVybiB0cnVlO1xuICAgIH1cblxuICAgIHJldHVybiBmYWxzZTtcbiAgfTtcbn1cblxuZnVuY3Rpb24gcmVzb2x2ZVN0YXJ0c1dpdGgocGF0dGVybikge1xuICBjb25zdCBwcmVmaXggPSBwYXR0ZXJuLnByZWZpeDtcblxuICByZXR1cm4gZnVuY3Rpb24gKHZhbHVlLCBhcmdzKSB7XG4gICAgaWYgKENoZWNrcy5pc19zdHJpbmcodmFsdWUpICYmIHZhbHVlLnN0YXJ0c1dpdGgocHJlZml4KSkge1xuICAgICAgYXJncy5wdXNoKHZhbHVlLnN1YnN0cmluZyhwcmVmaXgubGVuZ3RoKSk7XG4gICAgICByZXR1cm4gdHJ1ZTtcbiAgICB9XG5cbiAgICByZXR1cm4gZmFsc2U7XG4gIH07XG59XG5cbmZ1bmN0aW9uIHJlc29sdmVUeXBlKHBhdHRlcm4pIHtcbiAgcmV0dXJuIGZ1bmN0aW9uICh2YWx1ZSwgYXJncykge1xuICAgIGlmICh2YWx1ZSBpbnN0YW5jZW9mIHBhdHRlcm4udHlwZSkge1xuICAgICAgY29uc3QgbWF0Y2hlcyA9IGJ1aWxkTWF0Y2gocGF0dGVybi5vYmpQYXR0ZXJuKTtcbiAgICAgIHJldHVybiBtYXRjaGVzKHZhbHVlLCBhcmdzKSAmJiBhcmdzLnB1c2godmFsdWUpID4gMDtcbiAgICB9XG5cbiAgICByZXR1cm4gZmFsc2U7XG4gIH07XG59XG5cbmZ1bmN0aW9uIHJlc29sdmVBcnJheShwYXR0ZXJuKSB7XG4gIGNvbnN0IG1hdGNoZXMgPSBwYXR0ZXJuLm1hcCh4ID0+IGJ1aWxkTWF0Y2goeCkpO1xuXG4gIHJldHVybiBmdW5jdGlvbiAodmFsdWUsIGFyZ3MpIHtcbiAgICBpZiAoIUNoZWNrcy5pc19hcnJheSh2YWx1ZSkgfHwgdmFsdWUubGVuZ3RoICE9IHBhdHRlcm4ubGVuZ3RoKSB7XG4gICAgICByZXR1cm4gZmFsc2U7XG4gICAgfVxuXG4gICAgcmV0dXJuIHZhbHVlLmV2ZXJ5KGZ1bmN0aW9uICh2LCBpKSB7XG4gICAgICByZXR1cm4gbWF0Y2hlc1tpXSh2YWx1ZVtpXSwgYXJncyk7XG4gICAgfSk7XG4gIH07XG59XG5cbmZ1bmN0aW9uIHJlc29sdmVPYmplY3QocGF0dGVybikge1xuICBsZXQgbWF0Y2hlcyA9IHt9O1xuXG4gIGZvciAobGV0IGtleSBvZiBPYmplY3Qua2V5cyhwYXR0ZXJuKSkge1xuICAgIG1hdGNoZXNba2V5XSA9IGJ1aWxkTWF0Y2gocGF0dGVybltrZXldKTtcbiAgfVxuXG4gIHJldHVybiBmdW5jdGlvbiAodmFsdWUsIGFyZ3MpIHtcbiAgICBpZiAoIUNoZWNrcy5pc19vYmplY3QodmFsdWUpIHx8IHBhdHRlcm4ubGVuZ3RoID4gdmFsdWUubGVuZ3RoKSB7XG4gICAgICByZXR1cm4gZmFsc2U7XG4gICAgfVxuXG4gICAgZm9yIChsZXQga2V5IG9mIE9iamVjdC5rZXlzKHBhdHRlcm4pKSB7XG4gICAgICBpZiAoIShrZXkgaW4gdmFsdWUpIHx8ICFtYXRjaGVzW2tleV0odmFsdWVba2V5XSwgYXJncykpIHtcbiAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgfVxuICAgIH1cblxuICAgIHJldHVybiB0cnVlO1xuICB9O1xufVxuXG5mdW5jdGlvbiByZXNvbHZlTm9NYXRjaCgpIHtcbiAgcmV0dXJuIGZ1bmN0aW9uICgpIHtcbiAgICByZXR1cm4gZmFsc2U7XG4gIH07XG59XG5cbnZhciBSZXNvbHZlcnMgPSB7XG4gIHJlc29sdmVCb3VuZCxcbiAgcmVzb2x2ZVdpbGRjYXJkLFxuICByZXNvbHZlVmFyaWFibGUsXG4gIHJlc29sdmVIZWFkVGFpbCxcbiAgcmVzb2x2ZUNhcHR1cmUsXG4gIHJlc29sdmVTdGFydHNXaXRoLFxuICByZXNvbHZlVHlwZSxcbiAgcmVzb2x2ZUFycmF5LFxuICByZXNvbHZlT2JqZWN0LFxuICByZXNvbHZlTm9NYXRjaCxcbiAgcmVzb2x2ZVN5bWJvbCxcbiAgcmVzb2x2ZVN0cmluZyxcbiAgcmVzb2x2ZU51bWJlcixcbiAgcmVzb2x2ZUJvb2xlYW4sXG4gIHJlc29sdmVGdW5jdGlvbixcbiAgcmVzb2x2ZU51bGxcbn07XG5cbmZ1bmN0aW9uIGJ1aWxkTWF0Y2gocGF0dGVybikge1xuXG4gIGlmIChDaGVja3MuaXNfdmFyaWFibGUocGF0dGVybikpIHtcbiAgICByZXR1cm4gUmVzb2x2ZXJzLnJlc29sdmVWYXJpYWJsZShwYXR0ZXJuKTtcbiAgfVxuXG4gIGlmIChDaGVja3MuaXNfd2lsZGNhcmQocGF0dGVybikpIHtcbiAgICByZXR1cm4gUmVzb2x2ZXJzLnJlc29sdmVXaWxkY2FyZChwYXR0ZXJuKTtcbiAgfVxuXG4gIGlmIChDaGVja3MuaXNfdW5kZWZpbmVkKHBhdHRlcm4pKSB7XG4gICAgcmV0dXJuIFJlc29sdmVycy5yZXNvbHZlV2lsZGNhcmQocGF0dGVybik7XG4gIH1cblxuICBpZiAoQ2hlY2tzLmlzX2hlYWRUYWlsKHBhdHRlcm4pKSB7XG4gICAgcmV0dXJuIFJlc29sdmVycy5yZXNvbHZlSGVhZFRhaWwocGF0dGVybik7XG4gIH1cblxuICBpZiAoQ2hlY2tzLmlzX3N0YXJ0c1dpdGgocGF0dGVybikpIHtcbiAgICByZXR1cm4gUmVzb2x2ZXJzLnJlc29sdmVTdGFydHNXaXRoKHBhdHRlcm4pO1xuICB9XG5cbiAgaWYgKENoZWNrcy5pc19jYXB0dXJlKHBhdHRlcm4pKSB7XG4gICAgcmV0dXJuIFJlc29sdmVycy5yZXNvbHZlQ2FwdHVyZShwYXR0ZXJuKTtcbiAgfVxuXG4gIGlmIChDaGVja3MuaXNfYm91bmQocGF0dGVybikpIHtcbiAgICByZXR1cm4gUmVzb2x2ZXJzLnJlc29sdmVCb3VuZChwYXR0ZXJuKTtcbiAgfVxuXG4gIGlmIChDaGVja3MuaXNfdHlwZShwYXR0ZXJuKSkge1xuICAgIHJldHVybiBSZXNvbHZlcnMucmVzb2x2ZVR5cGUocGF0dGVybik7XG4gIH1cblxuICBpZiAoQ2hlY2tzLmlzX2FycmF5KHBhdHRlcm4pKSB7XG4gICAgcmV0dXJuIFJlc29sdmVycy5yZXNvbHZlQXJyYXkocGF0dGVybik7XG4gIH1cblxuICBpZiAoQ2hlY2tzLmlzX251bWJlcihwYXR0ZXJuKSkge1xuICAgIHJldHVybiBSZXNvbHZlcnMucmVzb2x2ZU51bWJlcihwYXR0ZXJuKTtcbiAgfVxuXG4gIGlmIChDaGVja3MuaXNfc3RyaW5nKHBhdHRlcm4pKSB7XG4gICAgcmV0dXJuIFJlc29sdmVycy5yZXNvbHZlU3RyaW5nKHBhdHRlcm4pO1xuICB9XG5cbiAgaWYgKENoZWNrcy5pc19ib29sZWFuKHBhdHRlcm4pKSB7XG4gICAgcmV0dXJuIFJlc29sdmVycy5yZXNvbHZlQm9vbGVhbihwYXR0ZXJuKTtcbiAgfVxuXG4gIGlmIChDaGVja3MuaXNfc3ltYm9sKHBhdHRlcm4pKSB7XG4gICAgcmV0dXJuIFJlc29sdmVycy5yZXNvbHZlU3ltYm9sKHBhdHRlcm4pO1xuICB9XG5cbiAgaWYgKENoZWNrcy5pc19udWxsKHBhdHRlcm4pKSB7XG4gICAgcmV0dXJuIFJlc29sdmVycy5yZXNvbHZlTnVsbChwYXR0ZXJuKTtcbiAgfVxuXG4gIGlmIChDaGVja3MuaXNfb2JqZWN0KHBhdHRlcm4pKSB7XG4gICAgcmV0dXJuIFJlc29sdmVycy5yZXNvbHZlT2JqZWN0KHBhdHRlcm4pO1xuICB9XG5cbiAgcmV0dXJuIFJlc29sdmVycy5yZXNvbHZlTm9NYXRjaCgpO1xufVxuXG5jbGFzcyBNYXRjaEVycm9yIGV4dGVuZHMgRXJyb3Ige1xuICBjb25zdHJ1Y3RvcihhcmcpIHtcbiAgICBzdXBlcigpO1xuXG4gICAgaWYgKHR5cGVvZiBhcmcgPT09ICdzeW1ib2wnKSB7XG4gICAgICB0aGlzLm1lc3NhZ2UgPSAnTm8gbWF0Y2ggZm9yOiAnICsgYXJnLnRvU3RyaW5nKCk7XG4gICAgfSBlbHNlIGlmIChBcnJheS5pc0FycmF5KGFyZykpIHtcbiAgICAgIGxldCBtYXBwZWRWYWx1ZXMgPSBhcmcubWFwKHggPT4geC50b1N0cmluZygpKTtcbiAgICAgIHRoaXMubWVzc2FnZSA9ICdObyBtYXRjaCBmb3I6ICcgKyBtYXBwZWRWYWx1ZXM7XG4gICAgfSBlbHNlIHtcbiAgICAgIHRoaXMubWVzc2FnZSA9ICdObyBtYXRjaCBmb3I6ICcgKyBhcmc7XG4gICAgfVxuXG4gICAgdGhpcy5zdGFjayA9IG5ldyBFcnJvcigpLnN0YWNrO1xuICAgIHRoaXMubmFtZSA9IHRoaXMuY29uc3RydWN0b3IubmFtZTtcbiAgfVxufVxuXG5jbGFzcyBDYXNlIHtcblxuICBjb25zdHJ1Y3RvcihwYXR0ZXJuLCBmbiwgZ3VhcmQgPSAoKSA9PiB0cnVlKSB7XG4gICAgdGhpcy5wYXR0ZXJuID0gYnVpbGRNYXRjaChwYXR0ZXJuKTtcbiAgICB0aGlzLmZuID0gZm47XG4gICAgdGhpcy5ndWFyZCA9IGd1YXJkO1xuICB9XG59XG5cbmZ1bmN0aW9uIG1ha2VfY2FzZShwYXR0ZXJuLCBmbiwgZ3VhcmQgPSAoKSA9PiB0cnVlKSB7XG4gIHJldHVybiBuZXcgQ2FzZShwYXR0ZXJuLCBmbiwgZ3VhcmQpO1xufVxuXG5mdW5jdGlvbiBkZWZtYXRjaCguLi5jYXNlcykge1xuICByZXR1cm4gZnVuY3Rpb24gKC4uLmFyZ3MpIHtcbiAgICBmb3IgKGxldCBwcm9jZXNzZWRDYXNlIG9mIGNhc2VzKSB7XG4gICAgICBsZXQgcmVzdWx0ID0gW107XG4gICAgICBpZiAocHJvY2Vzc2VkQ2FzZS5wYXR0ZXJuKGFyZ3MsIHJlc3VsdCkgJiYgcHJvY2Vzc2VkQ2FzZS5ndWFyZC5hcHBseSh0aGlzLCByZXN1bHQpKSB7XG4gICAgICAgIHJldHVybiBwcm9jZXNzZWRDYXNlLmZuLmFwcGx5KHRoaXMsIHJlc3VsdCk7XG4gICAgICB9XG4gICAgfVxuXG4gICAgdGhyb3cgbmV3IE1hdGNoRXJyb3IoYXJncyk7XG4gIH07XG59XG5cbmZ1bmN0aW9uIG1hdGNoKHBhdHRlcm4sIGV4cHIsIGd1YXJkID0gKCkgPT4gdHJ1ZSkge1xuICBsZXQgcmVzdWx0ID0gW107XG4gIGxldCBwcm9jZXNzZWRQYXR0ZXJuID0gYnVpbGRNYXRjaChwYXR0ZXJuKTtcbiAgaWYgKHByb2Nlc3NlZFBhdHRlcm4oZXhwciwgcmVzdWx0KSAmJiBndWFyZC5hcHBseSh0aGlzLCByZXN1bHQpKSB7XG4gICAgcmV0dXJuIHJlc3VsdDtcbiAgfSBlbHNlIHtcbiAgICB0aHJvdyBuZXcgTWF0Y2hFcnJvcihleHByKTtcbiAgfVxufVxuXG5mdW5jdGlvbiBtYXRjaF9ub190aHJvdyhwYXR0ZXJuLCBleHByLCBndWFyZCA9ICgpID0+IHRydWUpIHtcbiAgdHJ5IHtcbiAgICByZXR1cm4gbWF0Y2gocGF0dGVybiwgZXhwciwgZ3VhcmQpO1xuICB9IGNhdGNoIChlKSB7XG4gICAgaWYgKGUgaW5zdGFuY2VvZiBNYXRjaEVycm9yKSB7XG4gICAgICByZXR1cm4gbnVsbDtcbiAgICB9XG5cbiAgICB0aHJvdyBlO1xuICB9XG59XG5cbnZhciBQYXR0ZXJucyA9IHtcbiAgZGVmbWF0Y2gsIG1hdGNoLCBNYXRjaEVycm9yLCBtYXRjaF9ub190aHJvdyxcbiAgdmFyaWFibGUsIHdpbGRjYXJkLCBzdGFydHNXaXRoLFxuICBjYXB0dXJlLCBoZWFkVGFpbCwgdHlwZSwgYm91bmQsIENhc2UsIG1ha2VfY2FzZVxufTtcblxuY2xhc3MgQml0U3RyaW5nIHtcbiAgY29uc3RydWN0b3IoLi4uYXJncykge1xuICAgIHRoaXMucmF3X3ZhbHVlID0gZnVuY3Rpb24gKCkge1xuICAgICAgcmV0dXJuIE9iamVjdC5mcmVlemUoYXJncyk7XG4gICAgfTtcblxuICAgIHRoaXMudmFsdWUgPSBPYmplY3QuZnJlZXplKHRoaXMucHJvY2VzcyhhcmdzKSk7XG4gIH1cblxuICBnZXQoaW5kZXgpIHtcbiAgICByZXR1cm4gdGhpcy52YWx1ZVtpbmRleF07XG4gIH1cblxuICBjb3VudCgpIHtcbiAgICByZXR1cm4gdGhpcy52YWx1ZS5sZW5ndGg7XG4gIH1cblxuICBbU3ltYm9sLml0ZXJhdG9yXSgpIHtcbiAgICByZXR1cm4gdGhpcy52YWx1ZVtTeW1ib2wuaXRlcmF0b3JdKCk7XG4gIH1cblxuICB0b1N0cmluZygpIHtcbiAgICB2YXIgaSxcbiAgICAgICAgcyA9IFwiXCI7XG4gICAgZm9yIChpID0gMDsgaSA8IHRoaXMuY291bnQoKTsgaSsrKSB7XG4gICAgICBpZiAocyAhPT0gXCJcIikge1xuICAgICAgICBzICs9IFwiLCBcIjtcbiAgICAgIH1cbiAgICAgIHMgKz0gdGhpc1tpXS50b1N0cmluZygpO1xuICAgIH1cblxuICAgIHJldHVybiBcIjw8XCIgKyBzICsgXCI+PlwiO1xuICB9XG5cbiAgcHJvY2VzcygpIHtcbiAgICBsZXQgcHJvY2Vzc2VkX3ZhbHVlcyA9IFtdO1xuXG4gICAgdmFyIGk7XG4gICAgZm9yIChpID0gMDsgaSA8IHRoaXMucmF3X3ZhbHVlKCkubGVuZ3RoOyBpKyspIHtcbiAgICAgIGxldCBwcm9jZXNzZWRfdmFsdWUgPSB0aGlzW1wicHJvY2Vzc19cIiArIHRoaXMucmF3X3ZhbHVlKClbaV0udHlwZV0odGhpcy5yYXdfdmFsdWUoKVtpXSk7XG5cbiAgICAgIGZvciAobGV0IGF0dHIgb2YgdGhpcy5yYXdfdmFsdWUoKVtpXS5hdHRyaWJ1dGVzKSB7XG4gICAgICAgIHByb2Nlc3NlZF92YWx1ZSA9IHRoaXNbXCJwcm9jZXNzX1wiICsgYXR0cl0ocHJvY2Vzc2VkX3ZhbHVlKTtcbiAgICAgIH1cblxuICAgICAgcHJvY2Vzc2VkX3ZhbHVlcyA9IHByb2Nlc3NlZF92YWx1ZXMuY29uY2F0KHByb2Nlc3NlZF92YWx1ZSk7XG4gICAgfVxuXG4gICAgcmV0dXJuIHByb2Nlc3NlZF92YWx1ZXM7XG4gIH1cblxuICBwcm9jZXNzX2ludGVnZXIodmFsdWUpIHtcbiAgICByZXR1cm4gdmFsdWUudmFsdWU7XG4gIH1cblxuICBwcm9jZXNzX2Zsb2F0KHZhbHVlKSB7XG4gICAgaWYgKHZhbHVlLnNpemUgPT09IDY0KSB7XG4gICAgICByZXR1cm4gQml0U3RyaW5nLmZsb2F0NjRUb0J5dGVzKHZhbHVlLnZhbHVlKTtcbiAgICB9IGVsc2UgaWYgKHZhbHVlLnNpemUgPT09IDMyKSB7XG4gICAgICByZXR1cm4gQml0U3RyaW5nLmZsb2F0MzJUb0J5dGVzKHZhbHVlLnZhbHVlKTtcbiAgICB9XG5cbiAgICB0aHJvdyBuZXcgRXJyb3IoXCJJbnZhbGlkIHNpemUgZm9yIGZsb2F0XCIpO1xuICB9XG5cbiAgcHJvY2Vzc19iaXRzdHJpbmcodmFsdWUpIHtcbiAgICByZXR1cm4gdmFsdWUudmFsdWUudmFsdWU7XG4gIH1cblxuICBwcm9jZXNzX2JpbmFyeSh2YWx1ZSkge1xuICAgIHJldHVybiBCaXRTdHJpbmcudG9VVEY4QXJyYXkodmFsdWUudmFsdWUpO1xuICB9XG5cbiAgcHJvY2Vzc191dGY4KHZhbHVlKSB7XG4gICAgcmV0dXJuIEJpdFN0cmluZy50b1VURjhBcnJheSh2YWx1ZS52YWx1ZSk7XG4gIH1cblxuICBwcm9jZXNzX3V0ZjE2KHZhbHVlKSB7XG4gICAgcmV0dXJuIEJpdFN0cmluZy50b1VURjE2QXJyYXkodmFsdWUudmFsdWUpO1xuICB9XG5cbiAgcHJvY2Vzc191dGYzMih2YWx1ZSkge1xuICAgIHJldHVybiBCaXRTdHJpbmcudG9VVEYzMkFycmF5KHZhbHVlLnZhbHVlKTtcbiAgfVxuXG4gIHByb2Nlc3Nfc2lnbmVkKHZhbHVlKSB7XG4gICAgcmV0dXJuIG5ldyBVaW50OEFycmF5KFt2YWx1ZV0pWzBdO1xuICB9XG5cbiAgcHJvY2Vzc191bnNpZ25lZCh2YWx1ZSkge1xuICAgIHJldHVybiB2YWx1ZTtcbiAgfVxuXG4gIHByb2Nlc3NfbmF0aXZlKHZhbHVlKSB7XG4gICAgcmV0dXJuIHZhbHVlO1xuICB9XG5cbiAgcHJvY2Vzc19iaWcodmFsdWUpIHtcbiAgICByZXR1cm4gdmFsdWU7XG4gIH1cblxuICBwcm9jZXNzX2xpdHRsZSh2YWx1ZSkge1xuICAgIHJldHVybiB2YWx1ZS5yZXZlcnNlKCk7XG4gIH1cblxuICBwcm9jZXNzX3NpemUodmFsdWUpIHtcbiAgICByZXR1cm4gdmFsdWU7XG4gIH1cblxuICBwcm9jZXNzX3VuaXQodmFsdWUpIHtcbiAgICByZXR1cm4gdmFsdWU7XG4gIH1cblxuICBzdGF0aWMgaW50ZWdlcih2YWx1ZSkge1xuICAgIHJldHVybiBCaXRTdHJpbmcud3JhcCh2YWx1ZSwgeyBcInR5cGVcIjogXCJpbnRlZ2VyXCIsIFwidW5pdFwiOiAxLCBcInNpemVcIjogOCB9KTtcbiAgfVxuXG4gIHN0YXRpYyBmbG9hdCh2YWx1ZSkge1xuICAgIHJldHVybiBCaXRTdHJpbmcud3JhcCh2YWx1ZSwgeyBcInR5cGVcIjogXCJmbG9hdFwiLCBcInVuaXRcIjogMSwgXCJzaXplXCI6IDY0IH0pO1xuICB9XG5cbiAgc3RhdGljIGJpdHN0cmluZyh2YWx1ZSkge1xuICAgIHJldHVybiBCaXRTdHJpbmcud3JhcCh2YWx1ZSwgeyBcInR5cGVcIjogXCJiaXRzdHJpbmdcIiwgXCJ1bml0XCI6IDEsIFwic2l6ZVwiOiB2YWx1ZS5sZW5ndGggfSk7XG4gIH1cblxuICBzdGF0aWMgYml0cyh2YWx1ZSkge1xuICAgIHJldHVybiBCaXRTdHJpbmcuYml0c3RyaW5nKHZhbHVlKTtcbiAgfVxuXG4gIHN0YXRpYyBiaW5hcnkodmFsdWUpIHtcbiAgICByZXR1cm4gQml0U3RyaW5nLndyYXAodmFsdWUsIHsgXCJ0eXBlXCI6IFwiYmluYXJ5XCIsIFwidW5pdFwiOiA4LCBcInNpemVcIjogdmFsdWUubGVuZ3RoIH0pO1xuICB9XG5cbiAgc3RhdGljIGJ5dGVzKHZhbHVlKSB7XG4gICAgcmV0dXJuIEJpdFN0cmluZy5iaW5hcnkodmFsdWUpO1xuICB9XG5cbiAgc3RhdGljIHV0ZjgodmFsdWUpIHtcbiAgICByZXR1cm4gQml0U3RyaW5nLndyYXAodmFsdWUsIHsgXCJ0eXBlXCI6IFwidXRmOFwiIH0pO1xuICB9XG5cbiAgc3RhdGljIHV0ZjE2KHZhbHVlKSB7XG4gICAgcmV0dXJuIEJpdFN0cmluZy53cmFwKHZhbHVlLCB7IFwidHlwZVwiOiBcInV0ZjE2XCIgfSk7XG4gIH1cblxuICBzdGF0aWMgdXRmMzIodmFsdWUpIHtcbiAgICByZXR1cm4gQml0U3RyaW5nLndyYXAodmFsdWUsIHsgXCJ0eXBlXCI6IFwidXRmMzJcIiB9KTtcbiAgfVxuXG4gIHN0YXRpYyBzaWduZWQodmFsdWUpIHtcbiAgICByZXR1cm4gQml0U3RyaW5nLndyYXAodmFsdWUsIHt9LCBcInNpZ25lZFwiKTtcbiAgfVxuXG4gIHN0YXRpYyB1bnNpZ25lZCh2YWx1ZSkge1xuICAgIHJldHVybiBCaXRTdHJpbmcud3JhcCh2YWx1ZSwge30sIFwidW5zaWduZWRcIik7XG4gIH1cblxuICBzdGF0aWMgbmF0aXZlKHZhbHVlKSB7XG4gICAgcmV0dXJuIEJpdFN0cmluZy53cmFwKHZhbHVlLCB7fSwgXCJuYXRpdmVcIik7XG4gIH1cblxuICBzdGF0aWMgYmlnKHZhbHVlKSB7XG4gICAgcmV0dXJuIEJpdFN0cmluZy53cmFwKHZhbHVlLCB7fSwgXCJiaWdcIik7XG4gIH1cblxuICBzdGF0aWMgbGl0dGxlKHZhbHVlKSB7XG4gICAgcmV0dXJuIEJpdFN0cmluZy53cmFwKHZhbHVlLCB7fSwgXCJsaXR0bGVcIik7XG4gIH1cblxuICBzdGF0aWMgc2l6ZSh2YWx1ZSwgY291bnQpIHtcbiAgICByZXR1cm4gQml0U3RyaW5nLndyYXAodmFsdWUsIHsgXCJzaXplXCI6IGNvdW50IH0pO1xuICB9XG5cbiAgc3RhdGljIHVuaXQodmFsdWUsIGNvdW50KSB7XG4gICAgcmV0dXJuIEJpdFN0cmluZy53cmFwKHZhbHVlLCB7IFwidW5pdFwiOiBjb3VudCB9KTtcbiAgfVxuXG4gIHN0YXRpYyB3cmFwKHZhbHVlLCBvcHQsIG5ld19hdHRyaWJ1dGUgPSBudWxsKSB7XG4gICAgbGV0IHRoZV92YWx1ZSA9IHZhbHVlO1xuXG4gICAgaWYgKCEodmFsdWUgaW5zdGFuY2VvZiBPYmplY3QpKSB7XG4gICAgICB0aGVfdmFsdWUgPSB7IFwidmFsdWVcIjogdmFsdWUsIFwiYXR0cmlidXRlc1wiOiBbXSB9O1xuICAgIH1cblxuICAgIHRoZV92YWx1ZSA9IE9iamVjdC5hc3NpZ24odGhlX3ZhbHVlLCBvcHQpO1xuXG4gICAgaWYgKG5ld19hdHRyaWJ1dGUpIHtcbiAgICAgIHRoZV92YWx1ZS5hdHRyaWJ1dGVzLnB1c2gobmV3X2F0dHJpYnV0ZSk7XG4gICAgfVxuXG4gICAgcmV0dXJuIHRoZV92YWx1ZTtcbiAgfVxuXG4gIHN0YXRpYyB0b1VURjhBcnJheShzdHIpIHtcbiAgICB2YXIgdXRmOCA9IFtdO1xuICAgIGZvciAodmFyIGkgPSAwOyBpIDwgc3RyLmxlbmd0aDsgaSsrKSB7XG4gICAgICB2YXIgY2hhcmNvZGUgPSBzdHIuY2hhckNvZGVBdChpKTtcbiAgICAgIGlmIChjaGFyY29kZSA8IDEyOCkge1xuICAgICAgICB1dGY4LnB1c2goY2hhcmNvZGUpO1xuICAgICAgfSBlbHNlIGlmIChjaGFyY29kZSA8IDIwNDgpIHtcbiAgICAgICAgdXRmOC5wdXNoKDE5MiB8IGNoYXJjb2RlID4+IDYsIDEyOCB8IGNoYXJjb2RlICYgNjMpO1xuICAgICAgfSBlbHNlIGlmIChjaGFyY29kZSA8IDU1Mjk2IHx8IGNoYXJjb2RlID49IDU3MzQ0KSB7XG4gICAgICAgIHV0ZjgucHVzaCgyMjQgfCBjaGFyY29kZSA+PiAxMiwgMTI4IHwgY2hhcmNvZGUgPj4gNiAmIDYzLCAxMjggfCBjaGFyY29kZSAmIDYzKTtcbiAgICAgIH1cbiAgICAgIC8vIHN1cnJvZ2F0ZSBwYWlyXG4gICAgICBlbHNlIHtcbiAgICAgICAgaSsrO1xuICAgICAgICAvLyBVVEYtMTYgZW5jb2RlcyAweDEwMDAwLTB4MTBGRkZGIGJ5XG4gICAgICAgIC8vIHN1YnRyYWN0aW5nIDB4MTAwMDAgYW5kIHNwbGl0dGluZyB0aGVcbiAgICAgICAgLy8gMjAgYml0cyBvZiAweDAtMHhGRkZGRiBpbnRvIHR3byBoYWx2ZXNcbiAgICAgICAgY2hhcmNvZGUgPSA2NTUzNiArICgoY2hhcmNvZGUgJiAxMDIzKSA8PCAxMCB8IHN0ci5jaGFyQ29kZUF0KGkpICYgMTAyMyk7XG4gICAgICAgIHV0ZjgucHVzaCgyNDAgfCBjaGFyY29kZSA+PiAxOCwgMTI4IHwgY2hhcmNvZGUgPj4gMTIgJiA2MywgMTI4IHwgY2hhcmNvZGUgPj4gNiAmIDYzLCAxMjggfCBjaGFyY29kZSAmIDYzKTtcbiAgICAgIH1cbiAgICB9XG4gICAgcmV0dXJuIHV0Zjg7XG4gIH1cblxuICBzdGF0aWMgdG9VVEYxNkFycmF5KHN0cikge1xuICAgIHZhciB1dGYxNiA9IFtdO1xuICAgIGZvciAodmFyIGkgPSAwOyBpIDwgc3RyLmxlbmd0aDsgaSsrKSB7XG4gICAgICB2YXIgY29kZVBvaW50ID0gc3RyLmNvZGVQb2ludEF0KGkpO1xuXG4gICAgICBpZiAoY29kZVBvaW50IDw9IDI1NSkge1xuICAgICAgICB1dGYxNi5wdXNoKDApO1xuICAgICAgICB1dGYxNi5wdXNoKGNvZGVQb2ludCk7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICB1dGYxNi5wdXNoKGNvZGVQb2ludCA+PiA4ICYgMjU1KTtcbiAgICAgICAgdXRmMTYucHVzaChjb2RlUG9pbnQgJiAyNTUpO1xuICAgICAgfVxuICAgIH1cbiAgICByZXR1cm4gdXRmMTY7XG4gIH1cblxuICBzdGF0aWMgdG9VVEYzMkFycmF5KHN0cikge1xuICAgIHZhciB1dGYzMiA9IFtdO1xuICAgIGZvciAodmFyIGkgPSAwOyBpIDwgc3RyLmxlbmd0aDsgaSsrKSB7XG4gICAgICB2YXIgY29kZVBvaW50ID0gc3RyLmNvZGVQb2ludEF0KGkpO1xuXG4gICAgICBpZiAoY29kZVBvaW50IDw9IDI1NSkge1xuICAgICAgICB1dGYzMi5wdXNoKDApO1xuICAgICAgICB1dGYzMi5wdXNoKDApO1xuICAgICAgICB1dGYzMi5wdXNoKDApO1xuICAgICAgICB1dGYzMi5wdXNoKGNvZGVQb2ludCk7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICB1dGYzMi5wdXNoKDApO1xuICAgICAgICB1dGYzMi5wdXNoKDApO1xuICAgICAgICB1dGYzMi5wdXNoKGNvZGVQb2ludCA+PiA4ICYgMjU1KTtcbiAgICAgICAgdXRmMzIucHVzaChjb2RlUG9pbnQgJiAyNTUpO1xuICAgICAgfVxuICAgIH1cbiAgICByZXR1cm4gdXRmMzI7XG4gIH1cblxuICAvL2h0dHA6Ly9zdGFja292ZXJmbG93LmNvbS9xdWVzdGlvbnMvMjAwMzQ5My9qYXZhc2NyaXB0LWZsb2F0LWZyb20tdG8tYml0c1xuICBzdGF0aWMgZmxvYXQzMlRvQnl0ZXMoZikge1xuICAgIHZhciBieXRlcyA9IFtdO1xuXG4gICAgdmFyIGJ1ZiA9IG5ldyBBcnJheUJ1ZmZlcig0KTtcbiAgICBuZXcgRmxvYXQzMkFycmF5KGJ1ZilbMF0gPSBmO1xuXG4gICAgbGV0IGludFZlcnNpb24gPSBuZXcgVWludDMyQXJyYXkoYnVmKVswXTtcblxuICAgIGJ5dGVzLnB1c2goaW50VmVyc2lvbiA+PiAyNCAmIDI1NSk7XG4gICAgYnl0ZXMucHVzaChpbnRWZXJzaW9uID4+IDE2ICYgMjU1KTtcbiAgICBieXRlcy5wdXNoKGludFZlcnNpb24gPj4gOCAmIDI1NSk7XG4gICAgYnl0ZXMucHVzaChpbnRWZXJzaW9uICYgMjU1KTtcblxuICAgIHJldHVybiBieXRlcztcbiAgfVxuXG4gIHN0YXRpYyBmbG9hdDY0VG9CeXRlcyhmKSB7XG4gICAgdmFyIGJ5dGVzID0gW107XG5cbiAgICB2YXIgYnVmID0gbmV3IEFycmF5QnVmZmVyKDgpO1xuICAgIG5ldyBGbG9hdDY0QXJyYXkoYnVmKVswXSA9IGY7XG5cbiAgICB2YXIgaW50VmVyc2lvbjEgPSBuZXcgVWludDMyQXJyYXkoYnVmKVswXTtcbiAgICB2YXIgaW50VmVyc2lvbjIgPSBuZXcgVWludDMyQXJyYXkoYnVmKVsxXTtcblxuICAgIGJ5dGVzLnB1c2goaW50VmVyc2lvbjIgPj4gMjQgJiAyNTUpO1xuICAgIGJ5dGVzLnB1c2goaW50VmVyc2lvbjIgPj4gMTYgJiAyNTUpO1xuICAgIGJ5dGVzLnB1c2goaW50VmVyc2lvbjIgPj4gOCAmIDI1NSk7XG4gICAgYnl0ZXMucHVzaChpbnRWZXJzaW9uMiAmIDI1NSk7XG5cbiAgICBieXRlcy5wdXNoKGludFZlcnNpb24xID4+IDI0ICYgMjU1KTtcbiAgICBieXRlcy5wdXNoKGludFZlcnNpb24xID4+IDE2ICYgMjU1KTtcbiAgICBieXRlcy5wdXNoKGludFZlcnNpb24xID4+IDggJiAyNTUpO1xuICAgIGJ5dGVzLnB1c2goaW50VmVyc2lvbjEgJiAyNTUpO1xuXG4gICAgcmV0dXJuIGJ5dGVzO1xuICB9XG59XG5cbi8qIEBmbG93ICovXG5cbmNsYXNzIE1haWxib3gge1xuXG4gIGNvbnN0cnVjdG9yKCkge1xuICAgIHRoaXMubWVzc2FnZXMgPSBbXTtcbiAgfVxuXG4gIGRlbGl2ZXIobWVzc2FnZSkge1xuICAgIHRoaXMubWVzc2FnZXMucHVzaChtZXNzYWdlKTtcbiAgICByZXR1cm4gbWVzc2FnZTtcbiAgfVxuXG4gIGdldCgpIHtcbiAgICByZXR1cm4gdGhpcy5tZXNzYWdlcztcbiAgfVxuXG4gIGlzRW1wdHkoKSB7XG4gICAgcmV0dXJuIHRoaXMubWVzc2FnZXMubGVuZ3RoID09PSAwO1xuICB9XG5cbiAgcmVtb3ZlQXQoaW5kZXgpIHtcbiAgICB0aGlzLm1lc3NhZ2VzLnNwbGljZShpbmRleCwgMSk7XG4gIH1cbn1cblxudmFyIFN0YXRlcyA9IHtcbiAgTk9STUFMOiBTeW1ib2wuZm9yKFwibm9ybWFsXCIpLFxuICBLSUxMOiBTeW1ib2wuZm9yKFwia2lsbFwiKSxcbiAgU1VTUEVORDogU3ltYm9sLmZvcihcInN1c3BlbmRcIiksXG4gIENPTlRJTlVFOiBTeW1ib2wuZm9yKFwiY29udGludWVcIiksXG4gIFJFQ0VJVkU6IFN5bWJvbC5mb3IoXCJyZWNlaXZlXCIpLFxuICBTRU5EOiBTeW1ib2wuZm9yKFwic2VuZFwiKSxcbiAgU0xFRVBJTkc6IFN5bWJvbC5mb3IoXCJzbGVlcGluZ1wiKSxcbiAgUlVOTklORzogU3ltYm9sLmZvcihcInJ1bm5pbmdcIiksXG4gIFNVU1BFTkRFRDogU3ltYm9sLmZvcihcInN1c3BlbmRlZFwiKSxcbiAgU1RPUFBFRDogU3ltYm9sLmZvcihcInN0b3BwZWRcIiksXG4gIFNMRUVQOiBTeW1ib2wuZm9yKFwic2xlZXBcIiksXG4gIEVYSVQ6IFN5bWJvbC5mb3IoXCJleGl0XCIpLFxuICBOT01BVENIOiBTeW1ib2wuZm9yKFwibm9fbWF0Y2hcIilcbn07XG5cbmNsYXNzIFByb2Nlc3Mge1xuXG4gIGNvbnN0cnVjdG9yKHBpZCwgbWFpbGJveCkge1xuICAgIHRoaXMucGlkID0gcGlkO1xuICAgIHRoaXMubWFpbGJveCA9IG1haWxib3g7XG4gICAgdGhpcy5zdGF0dXMgPSBTdGF0ZXMuU1RPUFBFRDtcbiAgICB0aGlzLmRpY3QgPSB7fTtcbiAgfVxufVxuXG5jbGFzcyBQcm9jZXNzU3lzdGVtIHtcblxuICBjb25zdHJ1Y3RvcigpIHtcbiAgICB0aGlzLnBpZHMgPSBuZXcgTWFwKCk7XG4gICAgdGhpcy5tYWlsYm94ZXMgPSBuZXcgTWFwKCk7XG4gICAgdGhpcy5uYW1lcyA9IG5ldyBNYXAoKTtcbiAgICB0aGlzLmxpbmtzID0gbmV3IE1hcCgpO1xuXG4gICAgdGhpcy5jdXJyZW50X3Byb2Nlc3MgPSBudWxsO1xuICAgIHRoaXMuc3VzcGVuZGVkID0gbmV3IE1hcCgpO1xuXG4gICAgdGhpcy5tYWluX3Byb2Nlc3NfcGlkID0gdGhpcy5zcGF3bigpO1xuICAgIHRoaXMuc2V0X2N1cnJlbnQodGhpcy5tYWluX3Byb2Nlc3NfcGlkKTtcbiAgfVxuXG4gIHNwYXduKCkge1xuICAgIHJldHVybiB0aGlzLmFkZF9wcm9jKGZhbHNlKS5waWQ7XG4gIH1cblxuICBzcGF3bl9saW5rKCkge1xuICAgIHJldHVybiB0aGlzLmFkZF9wcm9jKHRydWUpLnBpZDtcbiAgfVxuXG4gIGxpbmsocGlkKSB7XG4gICAgdGhpcy5saW5rcy5nZXQodGhpcy5waWQoKSkuYWRkKHBpZCk7XG4gICAgdGhpcy5saW5rcy5nZXQocGlkKS5hZGQodGhpcy5waWQoKSk7XG4gIH1cblxuICB1bmxpbmsocGlkKSB7XG4gICAgdGhpcy5saW5rcy5nZXQodGhpcy5waWQoKSkuZGVsZXRlKHBpZCk7XG4gICAgdGhpcy5saW5rcy5nZXQocGlkKS5kZWxldGUodGhpcy5waWQoKSk7XG4gIH1cblxuICBzZXRfY3VycmVudChpZCkge1xuICAgIGxldCBwaWQgPSB0aGlzLnBpZG9mKGlkKTtcbiAgICBpZiAocGlkICE9PSBudWxsKSB7XG4gICAgICB0aGlzLmN1cnJlbnRfcHJvY2VzcyA9IHRoaXMucGlkcy5nZXQocGlkKTtcbiAgICAgIHRoaXMuY3VycmVudF9wcm9jZXNzLnN0YXR1cyA9IFN0YXRlcy5SVU5OSU5HO1xuICAgIH1cbiAgfVxuXG4gIGFkZF9wcm9jKGxpbmtlZCkge1xuICAgIGxldCBuZXdwaWQgPSBuZXcgUElEKCk7XG4gICAgbGV0IG1haWxib3ggPSBuZXcgTWFpbGJveCgpO1xuICAgIGxldCBuZXdwcm9jID0gbmV3IFByb2Nlc3MobmV3cGlkLCBtYWlsYm94KTtcblxuICAgIHRoaXMucGlkcy5zZXQobmV3cGlkLCBuZXdwcm9jKTtcbiAgICB0aGlzLm1haWxib3hlcy5zZXQobmV3cGlkLCBtYWlsYm94KTtcbiAgICB0aGlzLmxpbmtzLnNldChuZXdwaWQsIG5ldyBTZXQoKSk7XG5cbiAgICBpZiAobGlua2VkKSB7XG4gICAgICB0aGlzLmxpbmsobmV3cGlkKTtcbiAgICB9XG5cbiAgICByZXR1cm4gbmV3cHJvYztcbiAgfVxuXG4gIHJlbW92ZV9wcm9jKHBpZCkge1xuICAgIHRoaXMucGlkcy5kZWxldGUocGlkKTtcbiAgICB0aGlzLnVucmVnaXN0ZXIocGlkKTtcblxuICAgIGlmICh0aGlzLmxpbmtzLmhhcyhwaWQpKSB7XG4gICAgICBmb3IgKGxldCBsaW5rcGlkIG9mIHRoaXMubGlua3MuZ2V0KHBpZCkpIHtcbiAgICAgICAgdGhpcy5saW5rcy5nZXQobGlua3BpZCkuZGVsZXRlKHBpZCk7XG4gICAgICB9XG5cbiAgICAgIHRoaXMubGlua3MuZGVsZXRlKHBpZCk7XG4gICAgfVxuICB9XG5cbiAgZXhpdChpZCkge1xuICAgIGxldCBwaWQgPSB0aGlzLnBpZG9mKGlkKTtcbiAgICB0aGlzLnJlbW92ZV9wcm9jKGlkKTtcbiAgfVxuXG4gIHJlZ2lzdGVyKG5hbWUsIHBpZCkge1xuICAgIGlmICghdGhpcy5uYW1lcy5oYXMobmFtZSkpIHtcbiAgICAgIHRoaXMubmFtZXMuc2V0KG5hbWUsIHBpZCk7XG4gICAgICByZXR1cm4gbmFtZTtcbiAgICB9IGVsc2Uge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKFwiTmFtZSBpcyBhbHJlYWR5IHJlZ2lzdGVyZWQgdG8gYW5vdGhlciBwcm9jZXNzXCIpO1xuICAgIH1cbiAgfVxuXG4gIHJlZ2lzdGVyZWQobmFtZSkge1xuICAgIHJldHVybiB0aGlzLm5hbWVzLmhhcyhuYW1lKSA/IHRoaXMubmFtZXMuZ2V0KG5hbWUpIDogbnVsbDtcbiAgfVxuXG4gIHVucmVnaXN0ZXIocGlkKSB7XG4gICAgZm9yIChsZXQgbmFtZSBvZiB0aGlzLm5hbWVzLmtleXMoKSkge1xuICAgICAgaWYgKHRoaXMubmFtZXMuaGFzKG5hbWUpICYmIHRoaXMubmFtZXMuZ2V0KG5hbWUpID09PSBwaWQpIHtcbiAgICAgICAgdGhpcy5uYW1lcy5kZWxldGUobmFtZSk7XG4gICAgICB9XG4gICAgfVxuICB9XG5cbiAgcGlkKCkge1xuICAgIHJldHVybiB0aGlzLmN1cnJlbnRfcHJvY2Vzcy5waWQ7XG4gIH1cblxuICBwaWRvZihpZCkge1xuICAgIGlmIChpZCBpbnN0YW5jZW9mIFBJRCkge1xuICAgICAgcmV0dXJuIHRoaXMucGlkcy5oYXMoaWQpID8gaWQgOiBudWxsO1xuICAgIH0gZWxzZSBpZiAoaWQgaW5zdGFuY2VvZiBQcm9jZXNzKSB7XG4gICAgICByZXR1cm4gaWQucGlkO1xuICAgIH0gZWxzZSB7XG4gICAgICBsZXQgcGlkID0gdGhpcy5yZWdpc3RlcmVkKGlkKTtcbiAgICAgIGlmIChwaWQgPT09IG51bGwpIHRocm93IFwiUHJvY2VzcyBuYW1lIG5vdCByZWdpc3RlcmVkOiBcIiArIGlkICsgXCIgKFwiICsgdHlwZW9mIGlkICsgXCIpXCI7XG4gICAgICByZXR1cm4gcGlkO1xuICAgIH1cbiAgfVxuXG4gIHB1dChpZCwga2V5LCB2YWx1ZSkge1xuICAgIGxldCBwaWQgPSB0aGlzLnBpZG9mKGlkKTtcbiAgICBsZXQgcHJvY2VzcyA9IHRoaXMucGlkcy5nZXQocGlkKTtcbiAgICBwcm9jZXNzLmRpY3Rba2V5XSA9IHZhbHVlO1xuICB9XG5cbiAgZ2V0KGlkLCBrZXkpIHtcbiAgICBsZXQgcGlkID0gdGhpcy5waWRvZihpZCk7XG4gICAgbGV0IHByb2Nlc3MgPSB0aGlzLnBpZHMuZ2V0KHBpZCk7XG5cbiAgICBpZiAoa2V5ICE9IG51bGwpIHtcbiAgICAgIHJldHVybiBwcm9jZXNzLmRpY3Rba2V5XTtcbiAgICB9IGVsc2Uge1xuICAgICAgcmV0dXJuIHByb2Nlc3MuZGljdDtcbiAgICB9XG4gIH1cblxuICBnZXRfa2V5cyhpZCkge1xuICAgIGxldCBwaWQgPSB0aGlzLnBpZG9mKGlkKTtcbiAgICBsZXQgcHJvY2VzcyA9IHRoaXMucGlkcy5nZXQocGlkKTtcblxuICAgIHJldHVybiBPYmplY3Qua2V5cyhwcm9jZXNzLmRpY3QpO1xuICB9XG5cbiAgZXJhc2UoaWQsIGtleSkge1xuICAgIGxldCBwaWQgPSB0aGlzLnBpZG9mKGlkKTtcbiAgICBsZXQgcHJvY2VzcyA9IHRoaXMucGlkcy5nZXQocGlkKTtcblxuICAgIGlmIChrZXkgIT0gbnVsbCkge1xuICAgICAgZGVsZXRlIHByb2Nlc3MuZGljdFtrZXldO1xuICAgIH0gZWxzZSB7XG4gICAgICBwcm9jZXNzLmRpY3QgPSB7fTtcbiAgICB9XG4gIH1cbn1cblxudmFyIEMgPSBPYmplY3QuZnJlZXplKHtcblx0UHJvY2Vzc1N5c3RlbTogUHJvY2Vzc1N5c3RlbSxcblx0VHVwbGU6IFR1cGxlJDEsXG5cdFBJRDogUElELFxuXHRCaXRTdHJpbmc6IEJpdFN0cmluZyxcblx0UGF0dGVybnM6IFBhdHRlcm5zLFxuXHRJbnRlZ2VyOiBJbnRlZ2VyJDEsXG5cdEZsb2F0OiBGbG9hdCxcblx0Y2FsbF9wcm9wZXJ0eTogY2FsbF9wcm9wZXJ0eVxufSk7XG5cbmxldCBFbnVtID0ge1xuXG4gIGFsbF9fcW1hcmtfXzogZnVuY3Rpb24gKGNvbGxlY3Rpb24sIGZ1biA9IHggPT4geCkge1xuICAgIGZvciAobGV0IGVsZW0gb2YgY29sbGVjdGlvbikge1xuICAgICAgaWYgKCFmdW4oZWxlbSkpIHtcbiAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgfVxuICAgIH1cblxuICAgIHJldHVybiB0cnVlO1xuICB9LFxuXG4gIGFueV9fcW1hcmtfXzogZnVuY3Rpb24gKGNvbGxlY3Rpb24sIGZ1biA9IHggPT4geCkge1xuICAgIGZvciAobGV0IGVsZW0gb2YgY29sbGVjdGlvbikge1xuICAgICAgaWYgKGZ1bihlbGVtKSkge1xuICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICByZXR1cm4gZmFsc2U7XG4gIH0sXG5cbiAgYXQ6IGZ1bmN0aW9uIChjb2xsZWN0aW9uLCBuLCB0aGVfZGVmYXVsdCA9IG51bGwpIHtcbiAgICBpZiAobiA+IHRoaXMuY291bnQoY29sbGVjdGlvbikgfHwgbiA8IDApIHtcbiAgICAgIHJldHVybiB0aGVfZGVmYXVsdDtcbiAgICB9XG5cbiAgICByZXR1cm4gY29sbGVjdGlvbltuXTtcbiAgfSxcblxuICBjb25jYXQ6IGZ1bmN0aW9uICguLi5lbnVtYWJsZXMpIHtcbiAgICByZXR1cm4gZW51bWFibGVzWzBdLmNvbmNhdChlbnVtYWJsZXNbMV0pO1xuICB9LFxuXG4gIGNvdW50OiBmdW5jdGlvbiAoY29sbGVjdGlvbiwgZnVuID0gbnVsbCkge1xuICAgIGlmIChmdW4gPT0gbnVsbCkge1xuICAgICAgcmV0dXJuIGNvbGxlY3Rpb24ubGVuZ3RoO1xuICAgIH0gZWxzZSB7XG4gICAgICByZXR1cm4gY29sbGVjdGlvbi5maWx0ZXIoZnVuKS5sZW5ndGg7XG4gICAgfVxuICB9LFxuXG4gIGRyb3A6IGZ1bmN0aW9uIChjb2xsZWN0aW9uLCBjb3VudCkge1xuICAgIHJldHVybiBjb2xsZWN0aW9uLnNsaWNlKGNvdW50KTtcbiAgfSxcblxuICBkcm9wX3doaWxlOiBmdW5jdGlvbiAoY29sbGVjdGlvbiwgZnVuKSB7XG4gICAgbGV0IGNvdW50ID0gMDtcblxuICAgIGZvciAobGV0IGVsZW0gb2YgY29sbGVjdGlvbikge1xuICAgICAgaWYgKGZ1bihlbGVtKSkge1xuICAgICAgICBjb3VudCA9IGNvdW50ICsgMTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIGJyZWFrO1xuICAgICAgfVxuICAgIH1cblxuICAgIHJldHVybiBjb2xsZWN0aW9uLnNsaWNlKGNvdW50KTtcbiAgfSxcblxuICBlYWNoOiBmdW5jdGlvbiAoY29sbGVjdGlvbiwgZnVuKSB7XG4gICAgZm9yIChsZXQgZWxlbSBvZiBjb2xsZWN0aW9uKSB7XG4gICAgICBmdW4oZWxlbSk7XG4gICAgfVxuICB9LFxuXG4gIGVtcHR5X19xbWFya19fOiBmdW5jdGlvbiAoY29sbGVjdGlvbikge1xuICAgIHJldHVybiBjb2xsZWN0aW9uLmxlbmd0aCA9PT0gMDtcbiAgfSxcblxuICBmZXRjaDogZnVuY3Rpb24gKGNvbGxlY3Rpb24sIG4pIHtcbiAgICBpZiAoS2VybmVsLmlzX2xpc3QoY29sbGVjdGlvbikpIHtcbiAgICAgIGlmIChuIDwgdGhpcy5jb3VudChjb2xsZWN0aW9uKSAmJiBuID49IDApIHtcbiAgICAgICAgcmV0dXJuIEtlcm5lbC5TcGVjaWFsRm9ybXMudHVwbGUoS2VybmVsLlNwZWNpYWxGb3Jtcy5hdG9tKFwib2tcIiksIGNvbGxlY3Rpb25bbl0pO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgcmV0dXJuIEtlcm5lbC5TcGVjaWFsRm9ybXMuYXRvbShcImVycm9yXCIpO1xuICAgICAgfVxuICAgIH1cblxuICAgIHRocm93IG5ldyBFcnJvcihcImNvbGxlY3Rpb24gaXMgbm90IGFuIEVudW1lcmFibGVcIik7XG4gIH0sXG5cbiAgZmV0Y2hfX2VtYXJrX186IGZ1bmN0aW9uIChjb2xsZWN0aW9uLCBuKSB7XG4gICAgaWYgKEtlcm5lbC5pc19saXN0KGNvbGxlY3Rpb24pKSB7XG4gICAgICBpZiAobiA8IHRoaXMuY291bnQoY29sbGVjdGlvbikgJiYgbiA+PSAwKSB7XG4gICAgICAgIHJldHVybiBjb2xsZWN0aW9uW25dO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKFwib3V0IG9mIGJvdW5kcyBlcnJvclwiKTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICB0aHJvdyBuZXcgRXJyb3IoXCJjb2xsZWN0aW9uIGlzIG5vdCBhbiBFbnVtZXJhYmxlXCIpO1xuICB9LFxuXG4gIGZpbHRlcjogZnVuY3Rpb24gKGNvbGxlY3Rpb24sIGZ1bikge1xuICAgIGxldCByZXN1bHQgPSBbXTtcblxuICAgIGZvciAobGV0IGVsZW0gb2YgY29sbGVjdGlvbikge1xuICAgICAgaWYgKGZ1bihlbGVtKSkge1xuICAgICAgICByZXN1bHQucHVzaChlbGVtKTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICByZXR1cm4gcmVzdWx0O1xuICB9LFxuXG4gIGZpbHRlcl9tYXA6IGZ1bmN0aW9uIChjb2xsZWN0aW9uLCBmaWx0ZXIsIG1hcHBlcikge1xuICAgIHJldHVybiBFbnVtLm1hcChFbnVtLmZpbHRlcihjb2xsZWN0aW9uLCBmaWx0ZXIpLCBtYXBwZXIpO1xuICB9LFxuXG4gIGZpbmQ6IGZ1bmN0aW9uIChjb2xsZWN0aW9uLCBpZl9ub25lID0gbnVsbCwgZnVuKSB7XG4gICAgZm9yIChsZXQgZWxlbSBvZiBjb2xsZWN0aW9uKSB7XG4gICAgICBpZiAoZnVuKGVsZW0pKSB7XG4gICAgICAgIHJldHVybiBlbGVtO1xuICAgICAgfVxuICAgIH1cblxuICAgIHJldHVybiBpZl9ub25lO1xuICB9LFxuXG4gIGludG86IGZ1bmN0aW9uIChjb2xsZWN0aW9uLCBsaXN0KSB7XG4gICAgcmV0dXJuIGxpc3QuY29uY2F0KGNvbGxlY3Rpb24pO1xuICB9LFxuXG4gIG1hcDogZnVuY3Rpb24gKGNvbGxlY3Rpb24sIGZ1bikge1xuICAgIGxldCByZXN1bHQgPSBbXTtcblxuICAgIGZvciAobGV0IGVsZW0gb2YgY29sbGVjdGlvbikge1xuICAgICAgcmVzdWx0LnB1c2goZnVuKGVsZW0pKTtcbiAgICB9XG5cbiAgICByZXR1cm4gcmVzdWx0O1xuICB9LFxuXG4gIG1hcF9yZWR1Y2U6IGZ1bmN0aW9uIChjb2xsZWN0aW9uLCBhY2MsIGZ1bikge1xuICAgIGxldCBtYXBwZWQgPSBLZXJuZWwuU3BlY2lhbEZvcm1zLmxpc3QoKTtcbiAgICBsZXQgdGhlX2FjYyA9IGFjYztcblxuICAgIGZvciAodmFyIGkgPSAwOyBpIDwgdGhpcy5jb3VudChjb2xsZWN0aW9uKTsgaSsrKSB7XG4gICAgICBsZXQgdHVwbGUgPSBmdW4oY29sbGVjdGlvbltpXSwgdGhlX2FjYyk7XG5cbiAgICAgIHRoZV9hY2MgPSBLZXJuZWwuZWxlbSh0dXBsZSwgMSk7XG4gICAgICBtYXBwZWQgPSBLZXJuZWwuU3BlY2lhbEZvcm1zLmxpc3QoLi4ubWFwcGVkLmNvbmNhdChbS2VybmVsLmVsZW0odHVwbGUsIDApXSkpO1xuICAgIH1cblxuICAgIHJldHVybiBLZXJuZWwuU3BlY2lhbEZvcm1zLnR1cGxlKG1hcHBlZCwgdGhlX2FjYyk7XG4gIH0sXG5cbiAgbWVtYmVyOiBmdW5jdGlvbiAoY29sbGVjdGlvbiwgdmFsdWUpIHtcbiAgICByZXR1cm4gY29sbGVjdGlvbi5pbmNsdWRlcyh2YWx1ZSk7XG4gIH0sXG5cbiAgcmVkdWNlOiBmdW5jdGlvbiAoY29sbGVjdGlvbiwgYWNjLCBmdW4pIHtcbiAgICBsZXQgdGhlX2FjYyA9IGFjYztcblxuICAgIGZvciAodmFyIGkgPSAwOyBpIDwgdGhpcy5jb3VudChjb2xsZWN0aW9uKTsgaSsrKSB7XG4gICAgICBsZXQgdHVwbGUgPSBmdW4oY29sbGVjdGlvbltpXSwgdGhlX2FjYyk7XG5cbiAgICAgIHRoZV9hY2MgPSBLZXJuZWwuZWxlbSh0dXBsZSwgMSk7XG4gICAgfVxuXG4gICAgcmV0dXJuIHRoZV9hY2M7XG4gIH0sXG5cbiAgdGFrZTogZnVuY3Rpb24gKGNvbGxlY3Rpb24sIGNvdW50KSB7XG4gICAgcmV0dXJuIGNvbGxlY3Rpb24uc2xpY2UoMCwgY291bnQpO1xuICB9LFxuXG4gIHRha2VfZXZlcnk6IGZ1bmN0aW9uIChjb2xsZWN0aW9uLCBudGgpIHtcbiAgICBsZXQgcmVzdWx0ID0gW107XG4gICAgbGV0IGluZGV4ID0gMDtcblxuICAgIGZvciAobGV0IGVsZW0gb2YgY29sbGVjdGlvbikge1xuICAgICAgaWYgKGluZGV4ICUgbnRoID09PSAwKSB7XG4gICAgICAgIHJlc3VsdC5wdXNoKGVsZW0pO1xuICAgICAgfVxuICAgIH1cblxuICAgIHJldHVybiBLZXJuZWwuU3BlY2lhbEZvcm1zLmxpc3QoLi4ucmVzdWx0KTtcbiAgfSxcblxuICB0YWtlX3doaWxlOiBmdW5jdGlvbiAoY29sbGVjdGlvbiwgZnVuKSB7XG4gICAgbGV0IGNvdW50ID0gMDtcblxuICAgIGZvciAobGV0IGVsZW0gb2YgY29sbGVjdGlvbikge1xuICAgICAgaWYgKGZ1bihlbGVtKSkge1xuICAgICAgICBjb3VudCA9IGNvdW50ICsgMTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIGJyZWFrO1xuICAgICAgfVxuICAgIH1cblxuICAgIHJldHVybiBjb2xsZWN0aW9uLnNsaWNlKDAsIGNvdW50KTtcbiAgfSxcblxuICB0b19saXN0OiBmdW5jdGlvbiAoY29sbGVjdGlvbikge1xuICAgIHJldHVybiBjb2xsZWN0aW9uO1xuICB9XG59O1xuXG5sZXQgU3BlY2lhbEZvcm1zID0ge1xuXG4gIF9fRElSX186IGZ1bmN0aW9uICgpIHtcbiAgICBpZiAoX19kaXJuYW1lKSB7XG4gICAgICByZXR1cm4gX19kaXJuYW1lO1xuICAgIH1cblxuICAgIGlmIChkb2N1bWVudC5jdXJyZW50U2NyaXB0KSB7XG4gICAgICByZXR1cm4gZG9jdW1lbnQuY3VycmVudFNjcmlwdC5zcmM7XG4gICAgfVxuXG4gICAgcmV0dXJuIG51bGw7XG4gIH0sXG5cbiAgYXRvbTogZnVuY3Rpb24gKF92YWx1ZSkge1xuICAgIHJldHVybiBTeW1ib2wuZm9yKF92YWx1ZSk7XG4gIH0sXG5cbiAgbGlzdDogZnVuY3Rpb24gKC4uLmFyZ3MpIHtcbiAgICByZXR1cm4gT2JqZWN0LmZyZWV6ZShhcmdzKTtcbiAgfSxcblxuICBiaXRzdHJpbmc6IGZ1bmN0aW9uICguLi5hcmdzKSB7XG4gICAgcmV0dXJuIG5ldyBCaXRTdHJpbmcoLi4uYXJncyk7XG4gIH0sXG5cbiAgYm91bmQ6IGZ1bmN0aW9uIChfdmFyKSB7XG4gICAgcmV0dXJuIFBhdHRlcm5zLmJvdW5kKF92YXIpO1xuICB9LFxuXG4gIF9jYXNlOiBmdW5jdGlvbiAoY29uZGl0aW9uLCBjbGF1c2VzKSB7XG4gICAgcmV0dXJuIFBhdHRlcm5zLmRlZm1hdGNoKC4uLmNsYXVzZXMpKGNvbmRpdGlvbik7XG4gIH0sXG5cbiAgY29uZDogZnVuY3Rpb24gKGNsYXVzZXMpIHtcbiAgICBmb3IgKGxldCBjbGF1c2Ugb2YgY2xhdXNlcykge1xuICAgICAgaWYgKGNsYXVzZVswXSkge1xuICAgICAgICByZXR1cm4gY2xhdXNlWzFdKCk7XG4gICAgICB9XG4gICAgfVxuXG4gICAgdGhyb3cgbmV3IEVycm9yKCk7XG4gIH0sXG5cbiAgZm46IGZ1bmN0aW9uIChjbGF1c2VzKSB7XG4gICAgcmV0dXJuIFBhdHRlcm5zLmRlZm1hdGNoKGNsYXVzZXMpO1xuICB9LFxuXG4gIG1hcDogZnVuY3Rpb24gKG9iaikge1xuICAgIHJldHVybiBPYmplY3QuZnJlZXplKG9iaik7XG4gIH0sXG5cbiAgbWFwX3VwZGF0ZTogZnVuY3Rpb24gKG1hcCwgdmFsdWVzKSB7XG4gICAgcmV0dXJuIE9iamVjdC5mcmVlemUoT2JqZWN0LmFzc2lnbihPYmplY3QuY3JlYXRlKG1hcC5jb25zdHJ1Y3Rvci5wcm90b3R5cGUpLCBtYXAsIHZhbHVlcykpO1xuICB9LFxuXG4gIF9mb3I6IGZ1bmN0aW9uIChjb2xsZWN0aW9ucywgZnVuLCBmaWx0ZXIgPSAoKSA9PiB0cnVlLCBpbnRvID0gW10sIHByZXZpb3VzVmFsdWVzID0gW10pIHtcbiAgICBsZXQgcGF0dGVybiA9IGNvbGxlY3Rpb25zWzBdWzBdO1xuICAgIGxldCBjb2xsZWN0aW9uID0gY29sbGVjdGlvbnNbMF1bMV07XG5cbiAgICBpZiAoY29sbGVjdGlvbnMubGVuZ3RoID09PSAxKSB7XG5cbiAgICAgIGZvciAobGV0IGVsZW0gb2YgY29sbGVjdGlvbikge1xuICAgICAgICBsZXQgciA9IFBhdHRlcm5zLm1hdGNoX25vX3Rocm93KHBhdHRlcm4sIGVsZW0pO1xuICAgICAgICBsZXQgYXJncyA9IHByZXZpb3VzVmFsdWVzLmNvbmNhdChyKTtcblxuICAgICAgICBpZiAociAmJiBmaWx0ZXIuYXBwbHkodGhpcywgYXJncykpIHtcbiAgICAgICAgICBpbnRvID0gRW51bS5pbnRvKFtmdW4uYXBwbHkodGhpcywgYXJncyldLCBpbnRvKTtcbiAgICAgICAgfVxuICAgICAgfVxuXG4gICAgICByZXR1cm4gaW50bztcbiAgICB9IGVsc2Uge1xuICAgICAgbGV0IF9pbnRvID0gW107XG5cbiAgICAgIGZvciAobGV0IGVsZW0gb2YgY29sbGVjdGlvbikge1xuICAgICAgICBsZXQgciA9IFBhdHRlcm5zLm1hdGNoX25vX3Rocm93KHBhdHRlcm4sIGVsZW0pO1xuICAgICAgICBpZiAocikge1xuICAgICAgICAgIF9pbnRvID0gRW51bS5pbnRvKHRoaXMuX2Zvcihjb2xsZWN0aW9ucy5zbGljZSgxKSwgZnVuLCBmaWx0ZXIsIF9pbnRvLCBwcmV2aW91c1ZhbHVlcy5jb25jYXQocikpLCBpbnRvKTtcbiAgICAgICAgfVxuICAgICAgfVxuXG4gICAgICByZXR1cm4gX2ludG87XG4gICAgfVxuICB9LFxuXG4gIHJlY2VpdmU6IGZ1bmN0aW9uIChyZWNlaXZlX2Z1biwgdGltZW91dF9pbl9tcyA9IG51bGwsIHRpbWVvdXRfZm4gPSB0aW1lID0+IHRydWUpIHtcbiAgICBpZiAodGltZW91dF9pbl9tcyA9PSBudWxsIHx8IHRpbWVvdXRfaW5fbXMgPT09IFN5c3RlbS5mb3IoJ2luZmluaXR5JykpIHtcbiAgICAgIHdoaWxlICh0cnVlKSB7XG4gICAgICAgIGlmIChzZWxmLm1haWxib3gubGVuZ3RoICE9PSAwKSB7XG4gICAgICAgICAgbGV0IG1lc3NhZ2UgPSBzZWxmLm1haWxib3hbMF07XG4gICAgICAgICAgc2VsZi5tYWlsYm94ID0gc2VsZi5tYWlsYm94LnNsaWNlKDEpO1xuICAgICAgICAgIHJldHVybiByZWNlaXZlX2Z1bihtZXNzYWdlKTtcbiAgICAgICAgfVxuICAgICAgfVxuICAgIH0gZWxzZSBpZiAodGltZW91dF9pbl9tcyA9PT0gMCkge1xuICAgICAgaWYgKHNlbGYubWFpbGJveC5sZW5ndGggIT09IDApIHtcbiAgICAgICAgbGV0IG1lc3NhZ2UgPSBzZWxmLm1haWxib3hbMF07XG4gICAgICAgIHNlbGYubWFpbGJveCA9IHNlbGYubWFpbGJveC5zbGljZSgxKTtcbiAgICAgICAgcmV0dXJuIHJlY2VpdmVfZnVuKG1lc3NhZ2UpO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgcmV0dXJuIG51bGw7XG4gICAgICB9XG4gICAgfSBlbHNlIHtcbiAgICAgIGxldCBub3cgPSBEYXRlLm5vdygpO1xuICAgICAgd2hpbGUgKERhdGUubm93KCkgPCBub3cgKyB0aW1lb3V0X2luX21zKSB7XG4gICAgICAgIGlmIChzZWxmLm1haWxib3gubGVuZ3RoICE9PSAwKSB7XG4gICAgICAgICAgbGV0IG1lc3NhZ2UgPSBzZWxmLm1haWxib3hbMF07XG4gICAgICAgICAgc2VsZi5tYWlsYm94ID0gc2VsZi5tYWlsYm94LnNsaWNlKDEpO1xuICAgICAgICAgIHJldHVybiByZWNlaXZlX2Z1bihtZXNzYWdlKTtcbiAgICAgICAgfVxuICAgICAgfVxuXG4gICAgICByZXR1cm4gdGltZW91dF9mbih0aW1lb3V0X2luX21zKTtcbiAgICB9XG4gIH0sXG5cbiAgdHVwbGU6IGZ1bmN0aW9uICguLi5hcmdzKSB7XG4gICAgcmV0dXJuIG5ldyBUdXBsZSQxKC4uLmFyZ3MpO1xuICB9LFxuXG4gIF90cnk6IGZ1bmN0aW9uIChkb19mdW4sIHJlc2N1ZV9mdW5jdGlvbiwgY2F0Y2hfZnVuLCBlbHNlX2Z1bmN0aW9uLCBhZnRlcl9mdW5jdGlvbikge1xuICAgIGxldCByZXN1bHQgPSBudWxsO1xuXG4gICAgdHJ5IHtcbiAgICAgIHJlc3VsdCA9IGRvX2Z1bigpO1xuICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgIGxldCBleF9yZXN1bHQgPSBudWxsO1xuXG4gICAgICBpZiAocmVzY3VlX2Z1bmN0aW9uKSB7XG4gICAgICAgIHRyeSB7XG4gICAgICAgICAgZXhfcmVzdWx0ID0gcmVzY3VlX2Z1bmN0aW9uKGUpO1xuICAgICAgICAgIHJldHVybiBleF9yZXN1bHQ7XG4gICAgICAgIH0gY2F0Y2ggKGV4KSB7XG4gICAgICAgICAgaWYgKGV4IGluc3RhbmNlb2YgUGF0dGVybnMuTWF0Y2hFcnJvcikge1xuICAgICAgICAgICAgdGhyb3cgZXg7XG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICB9XG5cbiAgICAgIGlmIChjYXRjaF9mdW4pIHtcbiAgICAgICAgdHJ5IHtcbiAgICAgICAgICBleF9yZXN1bHQgPSBjYXRjaF9mdW4oZSk7XG4gICAgICAgICAgcmV0dXJuIGV4X3Jlc3VsdDtcbiAgICAgICAgfSBjYXRjaCAoZXgpIHtcbiAgICAgICAgICBpZiAoZXggaW5zdGFuY2VvZiBQYXR0ZXJucy5NYXRjaEVycm9yKSB7XG4gICAgICAgICAgICB0aHJvdyBleDtcbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgIH1cblxuICAgICAgdGhyb3cgZTtcbiAgICB9IGZpbmFsbHkge1xuICAgICAgaWYgKGFmdGVyX2Z1bmN0aW9uKSB7XG4gICAgICAgIGFmdGVyX2Z1bmN0aW9uKCk7XG4gICAgICB9XG4gICAgfVxuXG4gICAgaWYgKGVsc2VfZnVuY3Rpb24pIHtcbiAgICAgIHRyeSB7XG4gICAgICAgIHJldHVybiBlbHNlX2Z1bmN0aW9uKHJlc3VsdCk7XG4gICAgICB9IGNhdGNoIChleCkge1xuICAgICAgICBpZiAoZXggaW5zdGFuY2VvZiBQYXR0ZXJucy5NYXRjaEVycm9yKSB7XG4gICAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdObyBNYXRjaCBGb3VuZCBpbiBFbHNlJyk7XG4gICAgICAgIH1cblxuICAgICAgICB0aHJvdyBleDtcbiAgICAgIH1cbiAgICB9IGVsc2Uge1xuICAgICAgcmV0dXJuIHJlc3VsdDtcbiAgICB9XG4gIH1cblxufTtcblxuZnVuY3Rpb24gdG9fc3RyaW5nJDEodHVwbGUpIHtcbiAgcmV0dXJuIHR1cGxlLnRvU3RyaW5nKCk7XG59O1xuXG5mdW5jdGlvbiBkZWxldGVfYXQodHVwbGUsIGluZGV4KSB7XG4gIGxldCBuZXdfbGlzdCA9IFtdO1xuXG4gIGZvciAodmFyIGkgPSAwOyBpIDwgdHVwbGUuY291bnQoKTsgaSsrKSB7XG4gICAgaWYgKGkgIT09IGluZGV4KSB7XG4gICAgICBuZXdfbGlzdC5wdXNoKHR1cGxlLmdldChpKSk7XG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIEtlcm5lbC5TcGVjaWFsRm9ybXMudHVwbGUuYXBwbHkobnVsbCwgbmV3X2xpc3QpO1xufTtcblxuZnVuY3Rpb24gZHVwbGljYXRlKGRhdGEsIHNpemUpIHtcbiAgbGV0IGFycmF5ID0gW107XG5cbiAgZm9yICh2YXIgaSA9IHNpemUgLSAxOyBpID49IDA7IGktLSkge1xuICAgIGFycmF5LnB1c2goZGF0YSk7XG4gIH1cblxuICByZXR1cm4gS2VybmVsLlNwZWNpYWxGb3Jtcy50dXBsZS5hcHBseShudWxsLCBhcnJheSk7XG59O1xuXG5mdW5jdGlvbiBpbnNlcnRfYXQodHVwbGUsIGluZGV4LCB0ZXJtKSB7XG4gIGxldCBuZXdfdHVwbGUgPSBbXTtcblxuICBmb3IgKHZhciBpID0gMDsgaSA8PSB0dXBsZS5jb3VudCgpOyBpKyspIHtcbiAgICBpZiAoaSA9PT0gaW5kZXgpIHtcbiAgICAgIG5ld190dXBsZS5wdXNoKHRlcm0pO1xuICAgICAgaSsrO1xuICAgICAgbmV3X3R1cGxlLnB1c2godHVwbGUuZ2V0KGkpKTtcbiAgICB9IGVsc2Uge1xuICAgICAgbmV3X3R1cGxlLnB1c2godHVwbGUuZ2V0KGkpKTtcbiAgICB9XG4gIH1cblxuICByZXR1cm4gS2VybmVsLlNwZWNpYWxGb3Jtcy50dXBsZS5hcHBseShudWxsLCBuZXdfdHVwbGUpO1xufTtcblxuZnVuY3Rpb24gZnJvbV9saXN0KGxpc3QpIHtcbiAgcmV0dXJuIEtlcm5lbC5TcGVjaWFsRm9ybXMudHVwbGUuYXBwbHkobnVsbCwgbGlzdCk7XG59O1xuXG5mdW5jdGlvbiB0b19saXN0KHR1cGxlKSB7XG4gIGxldCBuZXdfbGlzdCA9IFtdO1xuXG4gIGZvciAodmFyIGkgPSAwOyBpIDwgdHVwbGUuY291bnQoKTsgaSsrKSB7XG4gICAgbmV3X2xpc3QucHVzaCh0dXBsZS5nZXQoaSkpO1xuICB9XG5cbiAgcmV0dXJuIEtlcm5lbC5TcGVjaWFsRm9ybXMubGlzdCguLi5uZXdfbGlzdCk7XG59O1xuXG52YXIgVHVwbGUgPSB7XG4gIHRvX3N0cmluZzogdG9fc3RyaW5nJDEsXG4gIGRlbGV0ZV9hdCxcbiAgZHVwbGljYXRlLFxuICBpbnNlcnRfYXQsXG4gIGZyb21fbGlzdCxcbiAgdG9fbGlzdFxufTtcblxuLy9odHRwczovL2dpdGh1Yi5jb20vYWlycG9ydHloL3Byb3RvbW9ycGhpc21cbmNsYXNzIFByb3RvY29sIHtcbiAgY29uc3RydWN0b3Ioc3BlYykge1xuICAgIHRoaXMucmVnaXN0cnkgPSBuZXcgTWFwKCk7XG4gICAgdGhpcy5mYWxsYmFjayA9IG51bGw7XG5cbiAgICBmb3IgKGxldCBmdW5OYW1lIGluIHNwZWMpIHtcbiAgICAgIHRoaXNbZnVuTmFtZV0gPSBjcmVhdGVGdW4oZnVuTmFtZSkuYmluZCh0aGlzKTtcbiAgICB9XG5cbiAgICBmdW5jdGlvbiBjcmVhdGVGdW4oZnVuTmFtZSkge1xuXG4gICAgICByZXR1cm4gZnVuY3Rpb24gKC4uLmFyZ3MpIHtcbiAgICAgICAgbGV0IHRoaW5nID0gYXJnc1swXTtcbiAgICAgICAgbGV0IGZ1biA9IG51bGw7XG5cbiAgICAgICAgaWYgKE51bWJlci5pc0ludGVnZXIodGhpbmcpICYmIHRoaXMuaGFzSW1wbGVtZW50YXRpb24oSW50ZWdlciQxKSkge1xuICAgICAgICAgIGZ1biA9IHRoaXMucmVnaXN0cnkuZ2V0KEludGVnZXIkMSlbZnVuTmFtZV07XG4gICAgICAgIH0gZWxzZSBpZiAodHlwZW9mIHRoaW5nID09PSBcIm51bWJlclwiICYmICFOdW1iZXIuaXNJbnRlZ2VyKHRoaW5nKSAmJiB0aGlzLmhhc0ltcGxlbWVudGF0aW9uKEZsb2F0KSkge1xuICAgICAgICAgIGZ1biA9IHRoaXMucmVnaXN0cnkuZ2V0KEZsb2F0KVtmdW5OYW1lXTtcbiAgICAgICAgfSBlbHNlIGlmICh0aGlzLmhhc0ltcGxlbWVudGF0aW9uKHRoaW5nKSkge1xuICAgICAgICAgIGZ1biA9IHRoaXMucmVnaXN0cnkuZ2V0KHRoaW5nLmNvbnN0cnVjdG9yKVtmdW5OYW1lXTtcbiAgICAgICAgfSBlbHNlIGlmICh0aGlzLmZhbGxiYWNrKSB7XG4gICAgICAgICAgZnVuID0gdGhpcy5mYWxsYmFja1tmdW5OYW1lXTtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmIChmdW4gIT0gbnVsbCkge1xuICAgICAgICAgIGxldCByZXR2YWwgPSBmdW4uYXBwbHkodGhpcywgYXJncyk7XG4gICAgICAgICAgcmV0dXJuIHJldHZhbDtcbiAgICAgICAgfVxuXG4gICAgICAgIHRocm93IG5ldyBFcnJvcihcIk5vIGltcGxlbWVudGF0aW9uIGZvdW5kIGZvciBcIiArIHRoaW5nKTtcbiAgICAgIH07XG4gICAgfVxuICB9XG5cbiAgaW1wbGVtZW50YXRpb24odHlwZSwgaW1wbGVtZW50YXRpb24pIHtcbiAgICBpZiAodHlwZSA9PT0gbnVsbCkge1xuICAgICAgdGhpcy5mYWxsYmFjayA9IGltcGxlbWVudGF0aW9uO1xuICAgIH0gZWxzZSB7XG4gICAgICB0aGlzLnJlZ2lzdHJ5LnNldCh0eXBlLCBpbXBsZW1lbnRhdGlvbik7XG4gICAgfVxuICB9XG5cbiAgaGFzSW1wbGVtZW50YXRpb24odGhpbmcpIHtcbiAgICByZXR1cm4gdGhpcy5yZWdpc3RyeS5oYXModGhpbmcuY29uc3RydWN0b3IpO1xuICB9XG59XG5cbmZ1bmN0aW9uIHRsKGxpc3QpIHtcbiAgcmV0dXJuIFNwZWNpYWxGb3Jtcy5saXN0KC4uLmxpc3Quc2xpY2UoMSkpO1xufVxuXG5mdW5jdGlvbiBoZChsaXN0KSB7XG4gIHJldHVybiBsaXN0WzBdO1xufVxuXG5mdW5jdGlvbiBpc19uaWwoeCkge1xuICByZXR1cm4geCA9PT0gbnVsbDtcbn1cblxuZnVuY3Rpb24gaXNfYXRvbSh4KSB7XG4gIHJldHVybiB0eXBlb2YgeCA9PT0gJ3N5bWJvbCc7XG59XG5cbmZ1bmN0aW9uIGlzX2JpbmFyeSh4KSB7XG4gIHJldHVybiB0eXBlb2YgeCA9PT0gJ3N0cmluZycgfHwgeCBpbnN0YW5jZW9mIFN0cmluZztcbn1cblxuZnVuY3Rpb24gaXNfYm9vbGVhbih4KSB7XG4gIHJldHVybiB0eXBlb2YgeCA9PT0gJ2Jvb2xlYW4nIHx8IHggaW5zdGFuY2VvZiBCb29sZWFuO1xufVxuXG5mdW5jdGlvbiBpc19mdW5jdGlvbih4LCBhcml0eSA9IC0xKSB7XG4gIHJldHVybiB0eXBlb2YgeCA9PT0gJ2Z1bmN0aW9uJyB8fCB4IGluc3RhbmNlb2YgRnVuY3Rpb247XG59XG5cbmZ1bmN0aW9uIGlzX2Zsb2F0KHgpIHtcbiAgcmV0dXJuIGlzX251bWJlcih4KSAmJiAhTnVtYmVyLmlzSW50ZWdlcih4KTtcbn1cblxuZnVuY3Rpb24gaXNfaW50ZWdlcih4KSB7XG4gIHJldHVybiBOdW1iZXIuaXNJbnRlZ2VyKHgpO1xufVxuXG5mdW5jdGlvbiBpc19saXN0KHgpIHtcbiAgcmV0dXJuIHggaW5zdGFuY2VvZiBBcnJheTtcbn1cblxuZnVuY3Rpb24gaXNfbWFwKHgpIHtcbiAgcmV0dXJuIHR5cGVvZiB4ID09PSAnb2JqZWN0JyB8fCB4IGluc3RhbmNlb2YgT2JqZWN0O1xufVxuXG5mdW5jdGlvbiBpc19udW1iZXIoeCkge1xuICByZXR1cm4gdHlwZW9mIHggPT09ICdudW1iZXInO1xufVxuXG5mdW5jdGlvbiBpc190dXBsZSh4KSB7XG4gIHJldHVybiB4IGluc3RhbmNlb2YgVHVwbGUkMTtcbn1cblxuZnVuY3Rpb24gbGVuZ3RoKHgpIHtcbiAgcmV0dXJuIHgubGVuZ3RoO1xufVxuXG5mdW5jdGlvbiBpc19waWQoeCkge1xuICByZXR1cm4geCBpbnN0YW5jZW9mIFBJRDtcbn1cblxuZnVuY3Rpb24gaXNfcG9ydCh4KSB7XG4gIHJldHVybiBmYWxzZTtcbn1cblxuZnVuY3Rpb24gaXNfcmVmZXJlbmNlKHgpIHtcbiAgcmV0dXJuIGZhbHNlO1xufVxuXG5mdW5jdGlvbiBpc19iaXRzdHJpbmcoeCkge1xuICByZXR1cm4gaXNfYmluYXJ5KHgpIHx8IHggaW5zdGFuY2VvZiBCaXRTdHJpbmc7XG59XG5cbmZ1bmN0aW9uIF9faW5fXyhsZWZ0LCByaWdodCkge1xuICBmb3IgKGxldCB4IG9mIHJpZ2h0KSB7XG4gICAgaWYgKG1hdGNoX19xbWFya19fKGxlZnQsIHgpKSB7XG4gICAgICByZXR1cm4gdHJ1ZTtcbiAgICB9XG4gIH1cblxuICByZXR1cm4gZmFsc2U7XG59XG5cbmZ1bmN0aW9uIGFicyhudW1iZXIpIHtcbiAgcmV0dXJuIE1hdGguYWJzKG51bWJlcik7XG59XG5cbmZ1bmN0aW9uIHJvdW5kKG51bWJlcikge1xuICByZXR1cm4gTWF0aC5yb3VuZChudW1iZXIpO1xufVxuXG5mdW5jdGlvbiBlbGVtKHR1cGxlLCBpbmRleCkge1xuICBpZiAoaXNfbGlzdCh0dXBsZSkpIHtcbiAgICByZXR1cm4gdHVwbGVbaW5kZXhdO1xuICB9XG5cbiAgcmV0dXJuIHR1cGxlLmdldChpbmRleCk7XG59XG5cbmZ1bmN0aW9uIHJlbShsZWZ0LCByaWdodCkge1xuICByZXR1cm4gbGVmdCAlIHJpZ2h0O1xufVxuXG5mdW5jdGlvbiBkaXYobGVmdCwgcmlnaHQpIHtcbiAgcmV0dXJuIGxlZnQgLyByaWdodDtcbn1cblxuZnVuY3Rpb24gYW5kKGxlZnQsIHJpZ2h0KSB7XG4gIHJldHVybiBsZWZ0ICYmIHJpZ2h0O1xufVxuXG5mdW5jdGlvbiBvcihsZWZ0LCByaWdodCkge1xuICByZXR1cm4gbGVmdCB8fCByaWdodDtcbn1cblxuZnVuY3Rpb24gbm90KGFyZykge1xuICByZXR1cm4gIWFyZztcbn1cblxuZnVuY3Rpb24gYXBwbHkoLi4uYXJncykge1xuICBpZiAoYXJncy5sZW5ndGggPT09IDMpIHtcbiAgICBsZXQgbW9kID0gYXJnc1swXTtcbiAgICBsZXQgZnVuYyA9IGFyZ3NbMV07XG4gICAgbGV0IGZ1bmNfYXJncyA9IGFyZ3NbMl07XG4gICAgcmV0dXJuIG1vZFtmdW5jXS5hcHBseShudWxsLCBmdW5jX2FyZ3MpO1xuICB9IGVsc2Uge1xuICAgIGxldCBmdW5jID0gYXJnc1swXTtcbiAgICBsZXQgZnVuY19hcmdzID0gYXJnc1sxXTtcblxuICAgIHJldHVybiBmdW5jLmFwcGx5KG51bGwsIGZ1bmNfYXJncyk7XG4gIH1cbn1cblxuZnVuY3Rpb24gdG9fc3RyaW5nKGFyZykge1xuICBpZiAoaXNfdHVwbGUoYXJnKSkge1xuICAgIHJldHVybiBUdXBsZS50b19zdHJpbmcoYXJnKTtcbiAgfVxuXG4gIHJldHVybiBhcmcudG9TdHJpbmcoKTtcbn1cblxuZnVuY3Rpb24gbWF0Y2hfX3FtYXJrX18ocGF0dGVybiwgZXhwciwgZ3VhcmQgPSAoKSA9PiB0cnVlKSB7XG4gIHJldHVybiBQYXR0ZXJucy5tYXRjaF9ub190aHJvdyhwYXR0ZXJuLCBleHByLCBndWFyZCkgIT0gbnVsbDtcbn1cblxuZnVuY3Rpb24gZGVmc3RydWN0KGRlZmF1bHRzKSB7XG4gIHJldHVybiBjbGFzcyB7XG4gICAgY29uc3RydWN0b3IodXBkYXRlID0ge30pIHtcbiAgICAgIGxldCB0aGVfdmFsdWVzID0gT2JqZWN0LmFzc2lnbihkZWZhdWx0cywgdXBkYXRlKTtcbiAgICAgIE9iamVjdC5hc3NpZ24odGhpcywgdGhlX3ZhbHVlcyk7XG4gICAgfVxuXG4gICAgc3RhdGljIGNyZWF0ZSh1cGRhdGVzID0ge30pIHtcbiAgICAgIGxldCB4ID0gbmV3IHRoaXModXBkYXRlcyk7XG4gICAgICByZXR1cm4gT2JqZWN0LmZyZWV6ZSh4KTtcbiAgICB9XG4gIH07XG59XG5cbmZ1bmN0aW9uIGRlZnByb3RvY29sKHNwZWMpIHtcbiAgcmV0dXJuIG5ldyBQcm90b2NvbChzcGVjKTtcbn1cblxuZnVuY3Rpb24gZGVmaW1wbChwcm90b2NvbCwgdHlwZSwgaW1wbCkge1xuICBwcm90b2NvbC5pbXBsZW1lbnRhdGlvbih0eXBlLCBpbXBsKTtcbn1cblxudmFyIEtlcm5lbCA9IHtcbiAgU3BlY2lhbEZvcm1zLFxuICB0bCxcbiAgaGQsXG4gIGlzX25pbCxcbiAgaXNfYXRvbSxcbiAgaXNfYmluYXJ5LFxuICBpc19ib29sZWFuLFxuICBpc19mdW5jdGlvbixcbiAgaXNfZmxvYXQsXG4gIGlzX2ludGVnZXIsXG4gIGlzX2xpc3QsXG4gIGlzX21hcCxcbiAgaXNfbnVtYmVyLFxuICBpc190dXBsZSxcbiAgbGVuZ3RoLFxuICBpc19waWQsXG4gIGlzX3BvcnQsXG4gIGlzX3JlZmVyZW5jZSxcbiAgaXNfYml0c3RyaW5nLFxuICBpbjogX19pbl9fLFxuICBhYnMsXG4gIHJvdW5kLFxuICBlbGVtLFxuICByZW0sXG4gIGRpdixcbiAgYW5kLFxuICBvcixcbiAgbm90LFxuICBhcHBseSxcbiAgdG9fc3RyaW5nLFxuICBtYXRjaF9fcW1hcmtfXyxcbiAgZGVmc3RydWN0LFxuICBkZWZwcm90b2NvbCxcbiAgZGVmaW1wbFxufTtcblxubGV0IEF0b20gPSB7fTtcblxuQXRvbS50b19zdHJpbmcgPSBmdW5jdGlvbiAoYXRvbSkge1xuICByZXR1cm4gU3ltYm9sLmtleUZvcihhdG9tKTtcbn07XG5cbkF0b20udG9fY2hhcl9saXN0ID0gZnVuY3Rpb24gKGF0b20pIHtcbiAgcmV0dXJuIEF0b20udG9fc3RyaW5nKGF0b20pLnNwbGl0KCcnKTtcbn07XG5cbmxldCBJbnRlZ2VyID0ge1xuXG4gIGlzX2V2ZW46IGZ1bmN0aW9uIChuKSB7XG4gICAgcmV0dXJuIG4gJSAyID09PSAwO1xuICB9LFxuXG4gIGlzX29kZDogZnVuY3Rpb24gKG4pIHtcbiAgICByZXR1cm4gbiAlIDIgIT09IDA7XG4gIH0sXG5cbiAgcGFyc2U6IGZ1bmN0aW9uIChiaW4pIHtcbiAgICBsZXQgcmVzdWx0ID0gcGFyc2VJbnQoYmluKTtcblxuICAgIGlmIChpc05hTihyZXN1bHQpKSB7XG4gICAgICByZXR1cm4gS2VybmVsLlNwZWNpYWxGb3Jtcy5hdG9tKFwiZXJyb3JcIik7XG4gICAgfVxuXG4gICAgbGV0IGluZGV4T2ZEb3QgPSBiaW4uaW5kZXhPZihcIi5cIik7XG5cbiAgICBpZiAoaW5kZXhPZkRvdCA+PSAwKSB7XG4gICAgICByZXR1cm4gS2VybmVsLlNwZWNpYWxGb3Jtcy50dXBsZShyZXN1bHQsIGJpbi5zdWJzdHJpbmcoaW5kZXhPZkRvdCkpO1xuICAgIH1cblxuICAgIHJldHVybiBLZXJuZWwuU3BlY2lhbEZvcm1zLnR1cGxlKHJlc3VsdCwgXCJcIik7XG4gIH0sXG5cbiAgdG9fY2hhcl9saXN0OiBmdW5jdGlvbiAobnVtYmVyLCBiYXNlID0gMTApIHtcbiAgICByZXR1cm4gbnVtYmVyLnRvU3RyaW5nKGJhc2UpLnNwbGl0KFwiXCIpO1xuICB9LFxuXG4gIHRvX3N0cmluZzogZnVuY3Rpb24gKG51bWJlciwgYmFzZSA9IDEwKSB7XG4gICAgcmV0dXJuIG51bWJlci50b1N0cmluZyhiYXNlKTtcbiAgfVxufTtcblxubGV0IENoYXJzJDEgPSBLZXJuZWwuZGVmcHJvdG9jb2woe1xuICB0b19zdHJpbmc6IGZ1bmN0aW9uICh0aGluZykge31cbn0pO1xuXG5LZXJuZWwuZGVmaW1wbChDaGFycyQxLCBCaXRTdHJpbmcsIHtcbiAgdG9fc3RyaW5nOiBmdW5jdGlvbiAodGhpbmcpIHtcbiAgICBpZiAoS2VybmVsLmlzX2JpbmFyeSh0aGluZykpIHtcbiAgICAgIHJldHVybiB0aGluZztcbiAgICB9XG5cbiAgICByZXR1cm4gdGhpbmcudG9TdHJpbmcoKTtcbiAgfVxufSk7XG5cbktlcm5lbC5kZWZpbXBsKENoYXJzJDEsIFN5bWJvbCwge1xuICB0b19zdHJpbmc6IGZ1bmN0aW9uICh0aGluZykge1xuICAgIGlmIChuaWwpIHtcbiAgICAgIHJldHVybiBcIlwiO1xuICAgIH1cblxuICAgIHJldHVybiBBdG9tLnRvX3N0cmluZyh0aGluZyk7XG4gIH1cbn0pO1xuXG5LZXJuZWwuZGVmaW1wbChDaGFycyQxLCBJbnRlZ2VyJDEsIHtcbiAgdG9fc3RyaW5nOiBmdW5jdGlvbiAodGhpbmcpIHtcbiAgICByZXR1cm4gSW50ZWdlci50b19zdHJpbmcodGhpbmcpO1xuICB9XG59KTtcblxuS2VybmVsLmRlZmltcGwoQ2hhcnMkMSwgRmxvYXQsIHtcbiAgdG9fc3RyaW5nOiBmdW5jdGlvbiAodGhpbmcpIHtcbiAgICByZXR1cm4gdGhpbmcudG9TdHJpbmc7XG4gIH1cbn0pO1xuXG5LZXJuZWwuZGVmaW1wbChDaGFycyQxLCBBcnJheSwge1xuICB0b19zdHJpbmc6IGZ1bmN0aW9uICh0aGluZykge1xuICAgIHJldHVybiB0aGluZy50b1N0cmluZygpO1xuICB9XG59KTtcblxuS2VybmVsLmRlZmltcGwoQ2hhcnMkMSwgVHVwbGUkMSwge1xuICB0b19zdHJpbmc6IGZ1bmN0aW9uICh0aGluZykge1xuICAgIHJldHVybiBUdXBsZS50b19zdHJpbmcodGhpbmcpO1xuICB9XG59KTtcblxuS2VybmVsLmRlZmltcGwoQ2hhcnMkMSwgbnVsbCwge1xuICB0b19zdHJpbmc6IGZ1bmN0aW9uICh0aGluZykge1xuICAgIHJldHVybiB0aGluZy50b1N0cmluZygpO1xuICB9XG59KTtcblxuZnVuY3Rpb24gdG9fYXRvbShzdHJpbmcpIHtcbiAgcmV0dXJuIFN5bWJvbC5mb3Ioc3RyaW5nKTtcbn1cblxuZnVuY3Rpb24gdG9fZXhpc3RpbmdfYXRvbShzdHJpbmcpIHtcbiAgcmV0dXJuIFN5bWJvbC5mb3Ioc3RyaW5nKTtcbn1cblxuZnVuY3Rpb24gdG9fY2hhcl9saXN0KHN0cmluZykge1xuICByZXR1cm4gc3RyaW5nLnNwbGl0KCcnKTtcbn1cblxuZnVuY3Rpb24gdG9fZmxvYXQoc3RyaW5nKSB7XG4gIHJldHVybiBwYXJzZUZsb2F0KHN0cmluZyk7XG59XG5cbmZ1bmN0aW9uIHRvX2ludGVnZXIoc3RyaW5nLCBiYXNlID0gMTApIHtcbiAgcmV0dXJuIHBhcnNlSW50KHN0cmluZywgYmFzZSk7XG59XG5cbmZ1bmN0aW9uIHVwY2FzZShiaW5hcnkpIHtcbiAgcmV0dXJuIGJpbmFyeS50b1VwcGVyQ2FzZSgpO1xufVxuXG5mdW5jdGlvbiBkb3duY2FzZShiaW5hcnkpIHtcbiAgcmV0dXJuIGJpbmFyeS50b0xvd2VyQ2FzZSgpO1xufVxuXG5mdW5jdGlvbiBhdChzdHJpbmcsIHBvc2l0aW9uKSB7XG4gIGlmIChwb3NpdGlvbiA+IHN0cmluZy5sZW5ndGggLSAxKSB7XG4gICAgcmV0dXJuIG51bGw7XG4gIH1cblxuICByZXR1cm4gc3RyaW5nW3Bvc2l0aW9uXTtcbn1cblxuZnVuY3Rpb24gY2FwaXRhbGl6ZShzdHJpbmcpIHtcbiAgbGV0IHJldHVyblN0cmluZyA9ICcnO1xuXG4gIGZvciAobGV0IGkgPSAwOyBpIDwgc3RyaW5nLmxlbmd0aDsgaSsrKSB7XG4gICAgaWYgKGkgPT09IDApIHtcbiAgICAgIHJldHVyblN0cmluZyA9IHJldHVyblN0cmluZyArIHN0cmluZ1tpXS50b1VwcGVyQ2FzZSgpO1xuICAgIH0gZWxzZSB7XG4gICAgICByZXR1cm5TdHJpbmcgPSByZXR1cm5TdHJpbmcgKyBzdHJpbmdbaV0udG9Mb3dlckNhc2UoKTtcbiAgICB9XG4gIH1cblxuICByZXR1cm4gcmV0dXJuU3RyaW5nO1xufVxuXG5mdW5jdGlvbiBjb2RlcG9pbnRzKHN0cmluZykge1xuICByZXR1cm4gdG9fY2hhcl9saXN0KHN0cmluZykubWFwKGZ1bmN0aW9uIChjKSB7XG4gICAgcmV0dXJuIGMuY29kZVBvaW50QXQoMCk7XG4gIH0pO1xufVxuXG5mdW5jdGlvbiBjb250YWluc19fcW1fXyhzdHJpbmcsIGNvbnRhaW5zKSB7XG4gIGlmIChBcnJheS5pc0FycmF5KGNvbnRhaW5zKSkge1xuICAgIHJldHVybiBjb250YWlucy5zb21lKGZ1bmN0aW9uIChzKSB7XG4gICAgICByZXR1cm4gc3RyaW5nLmluZGV4T2YocykgPiAtMTtcbiAgICB9KTtcbiAgfVxuXG4gIHJldHVybiBzdHJpbmcuaW5kZXhPZihjb250YWlucykgPiAtMTtcbn1cblxuZnVuY3Rpb24gZHVwbGljYXRlJDEoc3ViamVjdCwgbikge1xuICByZXR1cm4gc3ViamVjdC5yZXBlYXQobik7XG59XG5cbmZ1bmN0aW9uIGVuZHNfd2l0aF9fcW1fXyhzdHJpbmcsIHN1ZmZpeGVzKSB7XG4gIGlmIChBcnJheS5pc0FycmF5KHN1ZmZpeGVzKSkge1xuICAgIHJldHVybiBzdWZmaXhlcy5zb21lKGZ1bmN0aW9uIChzKSB7XG4gICAgICByZXR1cm4gc3RyaW5nLmVuZHNXaXRoKHMpO1xuICAgIH0pO1xuICB9XG5cbiAgcmV0dXJuIHN0cmluZy5lbmRzV2l0aChzdWZmaXhlcyk7XG59XG5cbmZ1bmN0aW9uIGZpcnN0KHN0cmluZykge1xuICBpZiAoIXN0cmluZykge1xuICAgIHJldHVybiBudWxsO1xuICB9XG5cbiAgcmV0dXJuIHN0cmluZ1swXTtcbn1cblxuZnVuY3Rpb24gZ3JhcGhlbWVzKHN0cmluZykge1xuICByZXR1cm4gc3RyaW5nLnNwbGl0KCcnKTtcbn1cblxuZnVuY3Rpb24gbGFzdChzdHJpbmcpIHtcbiAgaWYgKCFzdHJpbmcpIHtcbiAgICByZXR1cm4gbnVsbDtcbiAgfVxuXG4gIHJldHVybiBzdHJpbmdbc3RyaW5nLmxlbmd0aCAtIDFdO1xufVxuXG5mdW5jdGlvbiBsZW5ndGgkMShzdHJpbmcpIHtcbiAgcmV0dXJuIHN0cmluZy5sZW5ndGg7XG59XG5cbmZ1bmN0aW9uIG1hdGNoX19xbV9fKHN0cmluZywgcmVnZXgpIHtcbiAgcmV0dXJuIHN0cmluZy5tYXRjaChyZWdleCkgIT0gbnVsbDtcbn1cblxuZnVuY3Rpb24gbmV4dF9jb2RlcG9pbnQoc3RyaW5nKSB7XG4gIGlmICghc3RyaW5nIHx8IHN0cmluZyA9PT0gJycpIHtcbiAgICByZXR1cm4gbnVsbDtcbiAgfVxuXG4gIHJldHVybiBLZXJuZWwuU3BlY2lhbEZvcm1zLnR1cGxlKHN0cmluZ1swXS5jb2RlUG9pbnRBdCgwKSwgc3RyaW5nLnN1YnN0cigxKSk7XG59XG5cbmZ1bmN0aW9uIG5leHRfZ3JhcGhlbWUoc3RyaW5nKSB7XG4gIGlmICghc3RyaW5nIHx8IHN0cmluZyA9PT0gJycpIHtcbiAgICByZXR1cm4gbnVsbDtcbiAgfVxuXG4gIHJldHVybiBLZXJuZWwuU3BlY2lhbEZvcm1zLnR1cGxlKHN0cmluZ1swXSwgc3RyaW5nLnN1YnN0cigxKSk7XG59XG5cbmZ1bmN0aW9uIHJldmVyc2Uoc3RyaW5nKSB7XG4gIGxldCByZXR1cm5WYWx1ZSA9ICcnO1xuXG4gIGZvciAodmFyIGkgPSBzdHJpbmcubGVuZ3RoIC0gMTsgaSA+PSAwOyBpLS0pIHtcbiAgICByZXR1cm5WYWx1ZSA9IHJldHVyblZhbHVlICsgc3RyaW5nW2ldO1xuICB9O1xuXG4gIHJldHVybiByZXR1cm5WYWx1ZTtcbn1cblxuZnVuY3Rpb24gc3BsaXQoc3RyaW5nKSB7XG4gIHJldHVybiBzdHJpbmcuc3BsaXQoKTtcbn1cblxuZnVuY3Rpb24gc3RhcnRzX3dpdGhfX3FtX18oc3RyaW5nLCBwcmVmaXhlcykge1xuICBpZiAoQXJyYXkuaXNBcnJheShwcmVmaXhlcykpIHtcbiAgICByZXR1cm4gcHJlZml4ZXMuc29tZShmdW5jdGlvbiAocykge1xuICAgICAgcmV0dXJuIHN0cmluZy5zdGFydHNXaXRoKHMpO1xuICAgIH0pO1xuICB9XG5cbiAgcmV0dXJuIHN0cmluZy5zdGFydHNXaXRoKHByZWZpeGVzKTtcbn1cblxuZnVuY3Rpb24gdmFsaWRfY2hhcmFjdGVyX19xbV9fKGNvZGVwb2ludCkge1xuICB0cnkge1xuICAgIHJldHVybiBTdHJpbmcuZnJvbUNvZGVQb2ludChjb2RlcG9pbnQpICE9IG51bGw7XG4gIH0gY2F0Y2ggKGUpIHtcbiAgICByZXR1cm4gZmFsc2U7XG4gIH1cbn1cblxudmFyIFN0cmluZyQxID0ge1xuICBhdCxcbiAgY2FwaXRhbGl6ZSxcbiAgY29kZXBvaW50cyxcbiAgY29udGFpbnNfX3FtX18sXG4gIGRvd25jYXNlLFxuICBkdXBsaWNhdGU6IGR1cGxpY2F0ZSQxLFxuICBlbmRzX3dpdGhfX3FtX18sXG4gIGZpcnN0LFxuICBncmFwaGVtZXMsXG4gIGxhc3QsXG4gIGxlbmd0aDogbGVuZ3RoJDEsXG4gIG1hdGNoX19xbV9fLFxuICBuZXh0X2NvZGVwb2ludCxcbiAgbmV4dF9ncmFwaGVtZSxcbiAgcmV2ZXJzZSxcbiAgc3BsaXQsXG4gIHN0YXJ0c193aXRoX19xbV9fLFxuICB0b19hdG9tLFxuICB0b19jaGFyX2xpc3QsXG4gIHRvX2V4aXN0aW5nX2F0b20sXG4gIHRvX2Zsb2F0LFxuICB0b19pbnRlZ2VyLFxuICB1cGNhc2UsXG4gIHZhbGlkX2NoYXJhY3Rlcl9fcW1fXyxcbiAgQ2hhcnM6IENoYXJzJDFcbn07XG5cbmxldCBDaGFycyA9IEtlcm5lbC5kZWZwcm90b2NvbCh7XG4gIHRvX2NoYXJfbGlzdDogZnVuY3Rpb24gKHRoaW5nKSB7fVxufSk7XG5cbktlcm5lbC5kZWZpbXBsKENoYXJzLCBCaXRTdHJpbmcsIHtcbiAgdG9fY2hhcl9saXN0OiBmdW5jdGlvbiAodGhpbmcpIHtcbiAgICBpZiAoS2VybmVsLmlzX2JpbmFyeSh0aGluZykpIHtcbiAgICAgIHJldHVybiBTdHJpbmckMS50b19jaGFyX2xpc3QodGhpbmcpO1xuICAgIH1cblxuICAgIHJldHVybiB0aGluZy50b1N0cmluZygpO1xuICB9XG59KTtcblxuS2VybmVsLmRlZmltcGwoQ2hhcnMsIFN5bWJvbCwge1xuICB0b19jaGFyX2xpc3Q6IGZ1bmN0aW9uICh0aGluZykge1xuICAgIHJldHVybiBBdG9tLnRvX2NoYXJfbGlzdCh0aGluZyk7XG4gIH1cbn0pO1xuXG5LZXJuZWwuZGVmaW1wbChDaGFycywgSW50ZWdlciQxLCB7XG4gIHRvX2NoYXJfbGlzdDogZnVuY3Rpb24gKHRoaW5nKSB7XG4gICAgcmV0dXJuIEludGVnZXIudG9fY2hhcl9saXN0KHRoaW5nKTtcbiAgfVxufSk7XG5cbktlcm5lbC5kZWZpbXBsKENoYXJzLCBBcnJheSwge1xuICB0b19jaGFyX2xpc3Q6IGZ1bmN0aW9uICh0aGluZykge1xuICAgIHJldHVybiB0aGluZztcbiAgfVxufSk7XG5cbmxldCBMaXN0ID0ge307XG5cbkxpc3QuQ2hhcnMgPSBDaGFycztcblxuTGlzdC5kZWxldGUgPSBmdW5jdGlvbiAobGlzdCwgaXRlbSkge1xuICBsZXQgbmV3X3ZhbHVlID0gW107XG4gIGxldCB2YWx1ZV9mb3VuZCA9IGZhbHNlO1xuXG4gIGZvciAobGV0IHggb2YgbGlzdCkge1xuICAgIGlmICh4ID09PSBpdGVtICYmIHZhbHVlX2ZvdW5kICE9PSBmYWxzZSkge1xuICAgICAgbmV3X3ZhbHVlLnB1c2goeCk7XG4gICAgICB2YWx1ZV9mb3VuZCA9IHRydWU7XG4gICAgfSBlbHNlIGlmICh4ICE9PSBpdGVtKSB7XG4gICAgICBuZXdfdmFsdWUucHVzaCh4KTtcbiAgICB9XG4gIH1cblxuICByZXR1cm4gS2VybmVsLlNwZWNpYWxGb3Jtcy5saXN0KC4uLm5ld192YWx1ZSk7XG59O1xuXG5MaXN0LmRlbGV0ZV9hdCA9IGZ1bmN0aW9uIChsaXN0LCBpbmRleCkge1xuICBsZXQgbmV3X3ZhbHVlID0gW107XG5cbiAgZm9yIChsZXQgaSA9IDA7IGkgPCBsaXN0Lmxlbmd0aDsgaSsrKSB7XG4gICAgaWYgKGkgIT09IGluZGV4KSB7XG4gICAgICBuZXdfdmFsdWUucHVzaChsaXN0W2ldKTtcbiAgICB9XG4gIH1cblxuICByZXR1cm4gS2VybmVsLlNwZWNpYWxGb3Jtcy5saXN0KC4uLm5ld192YWx1ZSk7XG59O1xuXG5MaXN0LmR1cGxpY2F0ZSA9IGZ1bmN0aW9uIChlbGVtLCBuKSB7XG4gIGxldCBuZXdfdmFsdWUgPSBbXTtcblxuICBmb3IgKHZhciBpID0gMDsgaSA8IG47IGkrKykge1xuICAgIG5ld192YWx1ZS5wdXNoKGVsZW0pO1xuICB9XG5cbiAgcmV0dXJuIEtlcm5lbC5TcGVjaWFsRm9ybXMubGlzdCguLi5uZXdfdmFsdWUpO1xufTtcblxuTGlzdC5maXJzdCA9IGZ1bmN0aW9uIChsaXN0KSB7XG4gIHJldHVybiBsaXN0WzBdO1xufTtcblxuTGlzdC5mbGF0dGVuID0gZnVuY3Rpb24gKGxpc3QsIHRhaWwgPSBLZXJuZWwuU3BlY2lhbEZvcm1zLmxpc3QoKSkge1xuICBsZXQgbmV3X3ZhbHVlID0gW107XG5cbiAgZm9yIChsZXQgeCBvZiBsaXN0KSB7XG4gICAgaWYgKEtlcm5lbC5pc19saXN0KHgpKSB7XG4gICAgICBuZXdfdmFsdWUgPSBuZXdfdmFsdWUuY29uY2F0KExpc3QuZmxhdHRlbih4KSk7XG4gICAgfSBlbHNlIHtcbiAgICAgIG5ld192YWx1ZS5wdXNoKHgpO1xuICAgIH1cbiAgfVxuXG4gIG5ld192YWx1ZSA9IG5ld192YWx1ZS5jb25jYXQodGFpbCk7XG5cbiAgcmV0dXJuIEtlcm5lbC5TcGVjaWFsRm9ybXMubGlzdCguLi5uZXdfdmFsdWUpO1xufTtcblxuTGlzdC5mb2xkbCA9IGZ1bmN0aW9uIChsaXN0LCBhY2MsIGZ1bmMpIHtcbiAgcmV0dXJuIGxpc3QucmVkdWNlKGZ1bmMsIGFjYyk7XG59O1xuXG5MaXN0LmZvbGRyID0gZnVuY3Rpb24gKGxpc3QsIGFjYywgZnVuYykge1xuICBsZXQgbmV3X2FjYyA9IGFjYztcblxuICBmb3IgKHZhciBpID0gbGlzdC5sZW5ndGggLSAxOyBpID49IDA7IGktLSkge1xuICAgIG5ld19hY2MgPSBmdW5jKGxpc3RbaV0sIG5ld19hY2MpO1xuICB9XG5cbiAgcmV0dXJuIG5ld19hY2M7XG59O1xuXG5MaXN0Lmluc2VydF9hdCA9IGZ1bmN0aW9uIChsaXN0LCBpbmRleCwgdmFsdWUpIHtcbiAgbGV0IG5ld192YWx1ZSA9IFtdO1xuXG4gIGZvciAobGV0IGkgPSAwOyBpIDwgbGlzdC5sZW5ndGg7IGkrKykge1xuICAgIGlmIChpID09PSBpbmRleCkge1xuICAgICAgbmV3X3ZhbHVlLnB1c2godmFsdWUpO1xuICAgICAgbmV3X3ZhbHVlLnB1c2gobGlzdFtpXSk7XG4gICAgfSBlbHNlIHtcbiAgICAgIG5ld192YWx1ZS5wdXNoKGxpc3RbaV0pO1xuICAgIH1cbiAgfVxuXG4gIHJldHVybiBLZXJuZWwuU3BlY2lhbEZvcm1zLmxpc3QoLi4ubmV3X3ZhbHVlKTtcbn07XG5cbkxpc3Qua2V5ZGVsZXRlID0gZnVuY3Rpb24gKGxpc3QsIGtleSwgcG9zaXRpb24pIHtcbiAgbGV0IG5ld19saXN0ID0gW107XG5cbiAgZm9yIChsZXQgaSA9IDA7IGkgPCBsaXN0Lmxlbmd0aDsgaSsrKSB7XG4gICAgaWYgKCFLZXJuZWwubWF0Y2hfX3FtYXJrX18obGlzdFtpXVtwb3NpdGlvbl0sIGtleSkpIHtcbiAgICAgIG5ld19saXN0LnB1c2gobGlzdFtpXSk7XG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIEtlcm5lbC5TcGVjaWFsRm9ybXMubGlzdCguLi5uZXdfbGlzdCk7XG59O1xuXG5MaXN0LmtleWZpbmQgPSBmdW5jdGlvbiAobGlzdCwga2V5LCBwb3NpdGlvbiwgX2RlZmF1bHQgPSBudWxsKSB7XG5cbiAgZm9yIChsZXQgaSA9IDA7IGkgPCBsaXN0Lmxlbmd0aDsgaSsrKSB7XG4gICAgaWYgKEtlcm5lbC5tYXRjaF9fcW1hcmtfXyhsaXN0W2ldW3Bvc2l0aW9uXSwga2V5KSkge1xuICAgICAgcmV0dXJuIGxpc3RbaV07XG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIF9kZWZhdWx0O1xufTtcblxuTGlzdC5rZXltZW1iZXJfX3FtYXJrX18gPSBmdW5jdGlvbiAobGlzdCwga2V5LCBwb3NpdGlvbikge1xuXG4gIGZvciAobGV0IGkgPSAwOyBpIDwgbGlzdC5sZW5ndGg7IGkrKykge1xuICAgIGlmIChLZXJuZWwubWF0Y2hfX3FtYXJrX18obGlzdFtpXVtwb3NpdGlvbl0sIGtleSkpIHtcbiAgICAgIHJldHVybiB0cnVlO1xuICAgIH1cbiAgfVxuXG4gIHJldHVybiBmYWxzZTtcbn07XG5cbkxpc3Qua2V5cmVwbGFjZSA9IGZ1bmN0aW9uIChsaXN0LCBrZXksIHBvc2l0aW9uLCBuZXdfdHVwbGUpIHtcbiAgbGV0IG5ld19saXN0ID0gW107XG5cbiAgZm9yIChsZXQgaSA9IDA7IGkgPCBsaXN0Lmxlbmd0aDsgaSsrKSB7XG4gICAgaWYgKCFLZXJuZWwubWF0Y2hfX3FtYXJrX18obGlzdFtpXVtwb3NpdGlvbl0sIGtleSkpIHtcbiAgICAgIG5ld19saXN0LnB1c2gobGlzdFtpXSk7XG4gICAgfSBlbHNlIHtcbiAgICAgIG5ld19saXN0LnB1c2gobmV3X3R1cGxlKTtcbiAgICB9XG4gIH1cblxuICByZXR1cm4gS2VybmVsLlNwZWNpYWxGb3Jtcy5saXN0KC4uLm5ld19saXN0KTtcbn07XG5cbkxpc3Qua2V5c29ydCA9IGZ1bmN0aW9uIChsaXN0LCBwb3NpdGlvbikge1xuICBsZXQgbmV3X2xpc3QgPSBsaXN0O1xuXG4gIG5ld19saXN0LnNvcnQoZnVuY3Rpb24gKGEsIGIpIHtcbiAgICBpZiAocG9zaXRpb24gPT09IDApIHtcbiAgICAgIGlmIChhW3Bvc2l0aW9uXS52YWx1ZSA8IGJbcG9zaXRpb25dLnZhbHVlKSB7XG4gICAgICAgIHJldHVybiAtMTtcbiAgICAgIH1cblxuICAgICAgaWYgKGFbcG9zaXRpb25dLnZhbHVlID4gYltwb3NpdGlvbl0udmFsdWUpIHtcbiAgICAgICAgcmV0dXJuIDE7XG4gICAgICB9XG5cbiAgICAgIHJldHVybiAwO1xuICAgIH0gZWxzZSB7XG4gICAgICBpZiAoYVtwb3NpdGlvbl0gPCBiW3Bvc2l0aW9uXSkge1xuICAgICAgICByZXR1cm4gLTE7XG4gICAgICB9XG5cbiAgICAgIGlmIChhW3Bvc2l0aW9uXSA+IGJbcG9zaXRpb25dKSB7XG4gICAgICAgIHJldHVybiAxO1xuICAgICAgfVxuXG4gICAgICByZXR1cm4gMDtcbiAgICB9XG4gIH0pO1xuXG4gIHJldHVybiBLZXJuZWwuU3BlY2lhbEZvcm1zLmxpc3QoLi4ubmV3X2xpc3QpO1xufTtcblxuTGlzdC5rZXlzdG9yZSA9IGZ1bmN0aW9uIChsaXN0LCBrZXksIHBvc2l0aW9uLCBuZXdfdHVwbGUpIHtcbiAgbGV0IG5ld19saXN0ID0gW107XG4gIGxldCByZXBsYWNlZCA9IGZhbHNlO1xuXG4gIGZvciAobGV0IGkgPSAwOyBpIDwgbGlzdC5sZW5ndGg7IGkrKykge1xuICAgIGlmICghS2VybmVsLm1hdGNoX19xbWFya19fKGxpc3RbaV1bcG9zaXRpb25dLCBrZXkpKSB7XG4gICAgICBuZXdfbGlzdC5wdXNoKGxpc3RbaV0pO1xuICAgIH0gZWxzZSB7XG4gICAgICBuZXdfbGlzdC5wdXNoKG5ld190dXBsZSk7XG4gICAgICByZXBsYWNlZCA9IHRydWU7XG4gICAgfVxuICB9XG5cbiAgaWYgKCFyZXBsYWNlZCkge1xuICAgIG5ld19saXN0LnB1c2gobmV3X3R1cGxlKTtcbiAgfVxuXG4gIHJldHVybiBLZXJuZWwuU3BlY2lhbEZvcm1zLmxpc3QoLi4ubmV3X2xpc3QpO1xufTtcblxuTGlzdC5sYXN0ID0gZnVuY3Rpb24gKGxpc3QpIHtcbiAgcmV0dXJuIGxpc3RbbGlzdC5sZW5ndGggLSAxXTtcbn07XG5cbkxpc3QucmVwbGFjZV9hdCA9IGZ1bmN0aW9uIChsaXN0LCBpbmRleCwgdmFsdWUpIHtcbiAgbGV0IG5ld192YWx1ZSA9IFtdO1xuXG4gIGZvciAobGV0IGkgPSAwOyBpIDwgbGlzdC5sZW5ndGg7IGkrKykge1xuICAgIGlmIChpID09PSBpbmRleCkge1xuICAgICAgbmV3X3ZhbHVlLnB1c2godmFsdWUpO1xuICAgIH0gZWxzZSB7XG4gICAgICBuZXdfdmFsdWUucHVzaChsaXN0W2ldKTtcbiAgICB9XG4gIH1cblxuICByZXR1cm4gS2VybmVsLlNwZWNpYWxGb3Jtcy5saXN0KC4uLm5ld192YWx1ZSk7XG59O1xuXG5MaXN0LnVwZGF0ZV9hdCA9IGZ1bmN0aW9uIChsaXN0LCBpbmRleCwgZnVuKSB7XG4gIGxldCBuZXdfdmFsdWUgPSBbXTtcblxuICBmb3IgKGxldCBpID0gMDsgaSA8IGxpc3QuY291bnQoKTsgaSsrKSB7XG4gICAgaWYgKGkgPT09IGluZGV4KSB7XG4gICAgICBuZXdfdmFsdWUucHVzaChmdW4obGlzdC5nZXQoaSkpKTtcbiAgICB9IGVsc2Uge1xuICAgICAgbmV3X3ZhbHVlLnB1c2gobGlzdC5nZXQoaSkpO1xuICAgIH1cbiAgfVxuXG4gIHJldHVybiBuZXdfdmFsdWU7XG59O1xuXG5MaXN0LndyYXAgPSBmdW5jdGlvbiAobGlzdCkge1xuICBpZiAoS2VybmVsLmlzX2xpc3QobGlzdCkpIHtcbiAgICByZXR1cm4gbGlzdDtcbiAgfSBlbHNlIGlmIChsaXN0ID09IG51bGwpIHtcbiAgICByZXR1cm4gS2VybmVsLlNwZWNpYWxGb3Jtcy5saXN0KCk7XG4gIH0gZWxzZSB7XG4gICAgcmV0dXJuIEtlcm5lbC5TcGVjaWFsRm9ybXMubGlzdChsaXN0KTtcbiAgfVxufTtcblxuTGlzdC56aXAgPSBmdW5jdGlvbiAobGlzdF9vZl9saXN0cykge1xuICBpZiAobGlzdF9vZl9saXN0cy5sZW5ndGggPT09IDApIHtcbiAgICByZXR1cm4gS2VybmVsLlNwZWNpYWxGb3Jtcy5saXN0KCk7XG4gIH1cblxuICBsZXQgbmV3X3ZhbHVlID0gW107XG4gIGxldCBzbWFsbGVzdF9sZW5ndGggPSBsaXN0X29mX2xpc3RzWzBdO1xuXG4gIGZvciAobGV0IHggb2YgbGlzdF9vZl9saXN0cykge1xuICAgIGlmICh4Lmxlbmd0aCA8IHNtYWxsZXN0X2xlbmd0aCkge1xuICAgICAgc21hbGxlc3RfbGVuZ3RoID0geC5sZW5ndGg7XG4gICAgfVxuICB9XG5cbiAgZm9yIChsZXQgaSA9IDA7IGkgPCBzbWFsbGVzdF9sZW5ndGg7IGkrKykge1xuICAgIGxldCBjdXJyZW50X3ZhbHVlID0gW107XG4gICAgZm9yIChsZXQgaiA9IDA7IGogPCBsaXN0X29mX2xpc3RzLmxlbmd0aDsgaisrKSB7XG4gICAgICBjdXJyZW50X3ZhbHVlLnB1c2gobGlzdF9vZl9saXN0c1tqXVtpXSk7XG4gICAgfVxuXG4gICAgbmV3X3ZhbHVlLnB1c2goS2VybmVsLlNwZWNpYWxGb3Jtcy50dXBsZSguLi5jdXJyZW50X3ZhbHVlKSk7XG4gIH1cblxuICByZXR1cm4gS2VybmVsLlNwZWNpYWxGb3Jtcy5saXN0KC4uLm5ld192YWx1ZSk7XG59O1xuXG5MaXN0LnRvX3R1cGxlID0gZnVuY3Rpb24gKGxpc3QpIHtcbiAgcmV0dXJuIEtlcm5lbC5TcGVjaWFsRm9ybXMudHVwbGUuYXBwbHkobnVsbCwgbGlzdCk7XG59O1xuXG5MaXN0LmFwcGVuZCA9IGZ1bmN0aW9uIChsaXN0LCB2YWx1ZSkge1xuICByZXR1cm4gS2VybmVsLlNwZWNpYWxGb3Jtcy5saXN0KC4uLmxpc3QuY29uY2F0KFt2YWx1ZV0pKTtcbn07XG5cbkxpc3QucHJlcGVuZCA9IGZ1bmN0aW9uIChsaXN0LCB2YWx1ZSkge1xuICByZXR1cm4gS2VybmVsLlNwZWNpYWxGb3Jtcy5saXN0KC4uLlt2YWx1ZV0uY29uY2F0KGxpc3QpKTtcbn07XG5cbkxpc3QuY29uY2F0ID0gZnVuY3Rpb24gKGxlZnQsIHJpZ2h0KSB7XG4gIHJldHVybiBsZWZ0LmNvbmNhdChyaWdodCk7XG59O1xuXG5sZXQgUmFuZ2UgPSBmdW5jdGlvbiAoX2ZpcnN0LCBfbGFzdCkge1xuICBpZiAoISh0aGlzIGluc3RhbmNlb2YgUmFuZ2UpKSB7XG4gICAgcmV0dXJuIG5ldyBSYW5nZShfZmlyc3QsIF9sYXN0KTtcbiAgfVxuXG4gIHRoaXMuZmlyc3QgPSBmdW5jdGlvbiAoKSB7XG4gICAgcmV0dXJuIF9maXJzdDtcbiAgfTtcblxuICB0aGlzLmxhc3QgPSBmdW5jdGlvbiAoKSB7XG4gICAgcmV0dXJuIF9sYXN0O1xuICB9O1xuXG4gIGxldCBfcmFuZ2UgPSBbXTtcblxuICBmb3IgKGxldCBpID0gX2ZpcnN0OyBpIDw9IF9sYXN0OyBpKyspIHtcbiAgICBfcmFuZ2UucHVzaChpKTtcbiAgfVxuXG4gIF9yYW5nZSA9IE9iamVjdC5mcmVlemUoX3JhbmdlKTtcblxuICB0aGlzLnZhbHVlID0gZnVuY3Rpb24gKCkge1xuICAgIHJldHVybiBfcmFuZ2U7XG4gIH07XG5cbiAgdGhpcy5sZW5ndGggPSBmdW5jdGlvbiAoKSB7XG4gICAgcmV0dXJuIF9yYW5nZS5sZW5ndGg7XG4gIH07XG5cbiAgcmV0dXJuIHRoaXM7XG59O1xuXG5SYW5nZS5wcm90b3R5cGVbU3ltYm9sLml0ZXJhdG9yXSA9IGZ1bmN0aW9uICgpIHtcbiAgcmV0dXJuIHRoaXMudmFsdWUoKVtTeW1ib2wuaXRlcmF0b3JdKCk7XG59O1xuXG5SYW5nZS5uZXcgPSBmdW5jdGlvbiAoZmlyc3QsIGxhc3QpIHtcbiAgcmV0dXJuIFJhbmdlKGZpcnN0LCBsYXN0KTtcbn07XG5cblJhbmdlLnJhbmdlX19xbWFya19fID0gZnVuY3Rpb24gKHJhbmdlKSB7XG4gIHJldHVybiByYW5nZSBpbnN0YW5jZW9mIFJhbmdlO1xufTtcblxubGV0IEtleXdvcmQgPSB7fTtcblxuS2V5d29yZC5oYXNfa2V5X19xbV9fID0gZnVuY3Rpb24gKGtleXdvcmRzLCBrZXkpIHtcbiAgZm9yIChsZXQga2V5d29yZCBvZiBrZXl3b3Jkcykge1xuICAgIGlmIChLZXJuZWwuZWxlbShrZXl3b3JkLCAwKSA9PSBrZXkpIHtcbiAgICAgIHJldHVybiB0cnVlO1xuICAgIH1cbiAgfVxuXG4gIHJldHVybiBmYWxzZTtcbn07XG5cbktleXdvcmQuZ2V0ID0gZnVuY3Rpb24gKGtleXdvcmRzLCBrZXksIHRoZV9kZWZhdWx0ID0gbnVsbCkge1xuICBmb3IgKGxldCBrZXl3b3JkIG9mIGtleXdvcmRzKSB7XG4gICAgaWYgKEtlcm5lbC5lbGVtKGtleXdvcmQsIDApID09IGtleSkge1xuICAgICAgcmV0dXJuIEtlcm5lbC5lbGVtKGtleXdvcmQsIDEpO1xuICAgIH1cbiAgfVxuXG4gIHJldHVybiB0aGVfZGVmYXVsdDtcbn07XG5cbmxldCBBZ2VudCA9IHt9O1xuXG5BZ2VudC5zdGFydCA9IGZ1bmN0aW9uIChmdW4sIG9wdGlvbnMgPSBbXSkge1xuICBsZXQgcGlkID0gc2VsZi5wcm9jZXNzZXMuc3Bhd24oKTtcblxuICBpZiAoS2V5d29yZC5oYXNfa2V5X19xbV9fKG9wdGlvbnMsIEtlcm5lbC5TcGVjaWFsRm9ybXMuYXRvbSgnbmFtZScpKSkge1xuICAgIHBpZCA9IHNlbGYucHJvY2Vzc2VzLnJlZ2lzdGVyKEtleXdvcmQuZ2V0KG9wdGlvbnMsIEtlcm5lbC5TcGVjaWFsRm9ybXMuYXRvbSgnbmFtZScpKSwgcGlkKTtcbiAgfVxuXG4gIHNlbGYucHJvY2Vzc2VzLnB1dChwaWQsICdzdGF0ZScsIGZ1bigpKTtcbiAgcmV0dXJuIEtlcm5lbC5TcGVjaWFsRm9ybXMudHVwbGUoS2VybmVsLlNwZWNpYWxGb3Jtcy5hdG9tKCdvaycpLCBwaWQpO1xufTtcblxuQWdlbnQuc3RvcCA9IGZ1bmN0aW9uIChhZ2VudCwgdGltZW91dCA9IDUwMDApIHtcbiAgc2VsZi5wcm9jZXNzZXMuZXhpdChhZ2VudCk7XG4gIHJldHVybiBLZXJuZWwuU3BlY2lhbEZvcm1zLmF0b20oJ29rJyk7XG59O1xuXG5BZ2VudC51cGRhdGUgPSBmdW5jdGlvbiAoYWdlbnQsIGZ1biwgdGltZW91dCA9IDUwMDApIHtcblxuICBjb25zdCBjdXJyZW50X3N0YXRlID0gc2VsZi5wcm9jZXNzZXMuZ2V0KGFnZW50LCAnc3RhdGUnKTtcbiAgc2VsZi5wcm9jZXNzZXMucHV0KGFnZW50LCAnc3RhdGUnLCBmdW4oY3VycmVudF9zdGF0ZSkpO1xuXG4gIHJldHVybiBLZXJuZWwuU3BlY2lhbEZvcm1zLmF0b20oJ29rJyk7XG59O1xuXG5BZ2VudC5nZXQgPSBmdW5jdGlvbiAoYWdlbnQsIGZ1biwgdGltZW91dCA9IDUwMDApIHtcbiAgcmV0dXJuIGZ1bihzZWxmLnByb2Nlc3Nlcy5nZXQoYWdlbnQsICdzdGF0ZScpKTtcbn07XG5cbkFnZW50LmdldF9hbmRfdXBkYXRlID0gZnVuY3Rpb24gKGFnZW50LCBmdW4sIHRpbWVvdXQgPSA1MDAwKSB7XG5cbiAgY29uc3QgZ2V0X2FuZF91cGRhdGVfdHVwbGUgPSBmdW4oc2VsZi5wcm9jZXNzZXMuZ2V0KGFnZW50LCAnc3RhdGUnKSk7XG4gIHNlbGYucHJvY2Vzc2VzLnB1dChhZ2VudCwgJ3N0YXRlJywgS2VybmVsLmVsZW0oZ2V0X2FuZF91cGRhdGVfdHVwbGUsIDEpKTtcblxuICByZXR1cm4gS2VybmVsLmVsZW0oZ2V0X2FuZF91cGRhdGVfdHVwbGUsIDApO1xufTtcblxuLy9odHRwczovL2RldmVsb3Blci5tb3ppbGxhLm9yZy9lbi1VUy9kb2NzL1dlYi9BUEkvV2luZG93QmFzZTY0L0Jhc2U2NF9lbmNvZGluZ19hbmRfZGVjb2RpbmcjU29sdXRpb25fMl8lRTIlODAlOTNfcmV3cml0ZV90aGVfRE9Nc19hdG9iKClfYW5kX2J0b2EoKV91c2luZ19KYXZhU2NyaXB0J3NfVHlwZWRBcnJheXNfYW5kX1VURi04XG5mdW5jdGlvbiBiNjRFbmNvZGVVbmljb2RlKHN0cikge1xuICByZXR1cm4gYnRvYShlbmNvZGVVUklDb21wb25lbnQoc3RyKS5yZXBsYWNlKC8lKFswLTlBLUZdezJ9KS9nLCBmdW5jdGlvbiAobWF0Y2gsIHAxKSB7XG4gICAgcmV0dXJuIFN0cmluZy5mcm9tQ2hhckNvZGUoJzB4JyArIHAxKTtcbiAgfSkpO1xufVxuXG5mdW5jdGlvbiBlbmNvZGU2NChkYXRhKSB7XG4gIHJldHVybiBiNjRFbmNvZGVVbmljb2RlKGRhdGEpO1xufVxuXG5mdW5jdGlvbiBkZWNvZGU2NChkYXRhKSB7XG4gIHRyeSB7XG4gICAgcmV0dXJuIEtlcm5lbC5TcGVjaWFsRm9ybXMudHVwbGUoS2VybmVsLlNwZWNpYWxGb3Jtcy5hdG9tKCdvaycpLCBhdG9iKGRhdGEpKTtcbiAgfSBjYXRjaCAoZSkge1xuICAgIHJldHVybiBLZXJuZWwuU3BlY2lhbEZvcm1zLmF0b20oJ2Vycm9yJyk7XG4gIH1cbiAgcmV0dXJuIGJ0b2EoZGF0YSk7XG59XG5cbmZ1bmN0aW9uIGRlY29kZTY0X19lbV9fKGRhdGEpIHtcbiAgcmV0dXJuIGF0b2IoZGF0YSk7XG59XG5cbnZhciBiYXNlID0ge1xuICBlbmNvZGU2NCxcbiAgZGVjb2RlNjQsXG4gIGRlY29kZTY0X19lbV9fXG59O1xuXG5mdW5jdGlvbiBibm90KGV4cHIpIHtcbiAgcmV0dXJuIH5leHByO1xufVxuXG5mdW5jdGlvbiBiYW5kKGxlZnQsIHJpZ2h0KSB7XG4gIHJldHVybiBsZWZ0ICYgcmlnaHQ7XG59XG5cbmZ1bmN0aW9uIGJvcihsZWZ0LCByaWdodCkge1xuICByZXR1cm4gbGVmdCB8IHJpZ2h0O1xufVxuXG5mdW5jdGlvbiBic2wobGVmdCwgcmlnaHQpIHtcbiAgcmV0dXJuIGxlZnQgPDwgcmlnaHQ7XG59XG5cbmZ1bmN0aW9uIGJzcihsZWZ0LCByaWdodCkge1xuICByZXR1cm4gbGVmdCA+PiByaWdodDtcbn1cblxuZnVuY3Rpb24gYnhvcihsZWZ0LCByaWdodCkge1xuICByZXR1cm4gbGVmdCBeIHJpZ2h0O1xufVxuXG52YXIgYml0d2lzZSA9IHtcbiAgYm5vdCxcbiAgYmFuZCxcbiAgYm9yLFxuICBic2wsXG4gIGJzcixcbiAgYnhvclxufTtcblxubGV0IEVudW1lcmFibGUgPSBLZXJuZWwuZGVmcHJvdG9jb2woe1xuICBjb3VudDogZnVuY3Rpb24gKGNvbGxlY3Rpb24pIHt9LFxuICBtZW1iZXJfcW1hcmtfXzogZnVuY3Rpb24gKGNvbGxlY3Rpb24sIHZhbHVlKSB7fSxcbiAgcmVkdWNlOiBmdW5jdGlvbiAoY29sbGVjdGlvbiwgYWNjLCBmdW4pIHt9XG59KTtcblxubGV0IENvbGxlY3RhYmxlID0gS2VybmVsLmRlZnByb3RvY29sKHtcbiAgaW50bzogZnVuY3Rpb24gKGNvbGxlY3RhYmxlKSB7fVxufSk7XG5cbmxldCBJbnNwZWN0ID0gS2VybmVsLmRlZnByb3RvY29sKHtcbiAgaW5zcGVjdDogZnVuY3Rpb24gKHRoaW5nLCBvcHRzKSB7fVxufSk7XG5cbmZ1bmN0aW9uIF9fbmV3X18oKSB7XG4gIHJldHVybiBTcGVjaWFsRm9ybXMubWFwKHt9KTtcbn1cblxuZnVuY3Rpb24ga2V5cyhtYXApIHtcbiAgcmV0dXJuIE9iamVjdC5rZXlzKG1hcCk7XG59XG5cbmZ1bmN0aW9uIHNpemUobWFwKSB7XG4gIHJldHVybiBrZXlzKG1hcCkubGVuZ3RoO1xufVxuXG5mdW5jdGlvbiB0b19saXN0JDEobWFwKSB7XG4gIGxldCBtYXBfa2V5cyA9IGtleXMobWFwKTtcbiAgbGV0IGxpc3QgPSBbXTtcblxuICBmb3IgKGxldCBrZXkgb2YgbWFwX2tleXMpIHtcbiAgICBsaXN0LnB1c2goU3BlY2lhbEZvcm1zLnR1cGxlKGtleSwgbWFwW2tleV0pKTtcbiAgfVxuXG4gIHJldHVybiBTcGVjaWFsRm9ybXMubGlzdCguLi5saXN0KTtcbn1cblxuZnVuY3Rpb24gdmFsdWVzKG1hcCkge1xuICBsZXQgbWFwX2tleXMgPSBrZXlzKG1hcCk7XG4gIGxldCBsaXN0ID0gW107XG5cbiAgZm9yIChsZXQga2V5IG9mIG1hcF9rZXlzKSB7XG4gICAgbGlzdC5wdXNoKG1hcFtrZXldKTtcbiAgfVxuXG4gIHJldHVybiBTcGVjaWFsRm9ybXMubGlzdCguLi5saXN0KTtcbn1cblxuZnVuY3Rpb24gZnJvbV9zdHJ1Y3Qoc3RydWN0KSB7XG4gIGxldCBtYXAgPSBPYmplY3QuYXNzaWduKHt9LCBzdHJ1Y3QpO1xuICBkZWxldGUgbWFwW1N5bWJvbC5mb3IoXCJfX3N0cnVjdF9fXCIpXTtcblxuICByZXR1cm4gU3BlY2lhbEZvcm1zLm1hcChtYXApO1xufVxuXG5mdW5jdGlvbiBfX2RlbGV0ZV9fKG1hcCwga2V5KSB7XG4gIGxldCBuZXdfbWFwID0gT2JqZWN0LmFzc2lnbih7fSwgbWFwKTtcblxuICBkZWxldGUgbmV3X21hcFtrZXldO1xuXG4gIHJldHVybiBTcGVjaWFsRm9ybXMubWFwKG5ld19tYXApO1xufVxuXG5mdW5jdGlvbiBlcXVhbF9fcW1hcmtfXyhtYXAxLCBtYXAyKSB7XG4gIHJldHVybiBtYXAxID09PSBtYXAyO1xufVxuXG5mdW5jdGlvbiBmZXRjaF9fZW1hcmtfXyhtYXAsIGtleSkge1xuICBpZiAoa2V5IGluIG1hcCkge1xuICAgIHJldHVybiBtYXBba2V5XTtcbiAgfVxuXG4gIHRocm93IG5ldyBFcnJvcihcIktleSBub3QgZm91bmQuXCIpO1xufVxuXG5mdW5jdGlvbiBmZXRjaChtYXAsIGtleSkge1xuICBpZiAoa2V5IGluIG1hcCkge1xuICAgIHJldHVybiBTcGVjaWFsRm9ybXMudHVwbGUoU3BlY2lhbEZvcm1zLmF0b20oXCJva1wiKSwgbWFwW2tleV0pO1xuICB9XG5cbiAgcmV0dXJuIFNwZWNpYWxGb3Jtcy5hdG9tKFwiZXJyb3JcIik7XG59XG5cbmZ1bmN0aW9uIGhhc19rZXlfX3FtYXJrX18obWFwLCBrZXkpIHtcbiAgcmV0dXJuIGtleSBpbiBtYXA7XG59XG5cbmZ1bmN0aW9uIHNwbGl0JDEobWFwLCBrZXlzKSB7XG4gIGxldCBzcGxpdDEgPSB7fTtcbiAgbGV0IHNwbGl0MiA9IHt9O1xuXG4gIGZvciAobGV0IGtleSBvZiBPYmplY3Qua2V5cyhtYXApKSB7XG4gICAgaWYgKGtleXMuaW5kZXhPZihrZXkpID4gLTEpIHtcbiAgICAgIHNwbGl0MVtrZXldID0gbWFwW2tleV07XG4gICAgfSBlbHNlIHtcbiAgICAgIHNwbGl0MltrZXldID0gbWFwW2tleV07XG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIFNwZWNpYWxGb3Jtcy50dXBsZShTcGVjaWFsRm9ybXMubWFwKHNwbGl0MSksIFNwZWNpYWxGb3Jtcy5tYXAoc3BsaXQyKSk7XG59XG5cbmZ1bmN0aW9uIHRha2UobWFwLCBrZXlzKSB7XG4gIGxldCBzcGxpdDEgPSB7fTtcblxuICBmb3IgKGxldCBrZXkgb2YgT2JqZWN0LmtleXMobWFwKSkge1xuICAgIGlmIChrZXlzLmluZGV4T2Yoa2V5KSA+IC0xKSB7XG4gICAgICBzcGxpdDFba2V5XSA9IG1hcFtrZXldO1xuICAgIH1cbiAgfVxuXG4gIHJldHVybiBTcGVjaWFsRm9ybXMubWFwKHNwbGl0MSk7XG59XG5cbmZ1bmN0aW9uIGRyb3AobWFwLCBrZXlzKSB7XG4gIGxldCBzcGxpdDEgPSB7fTtcblxuICBmb3IgKGxldCBrZXkgb2YgT2JqZWN0LmtleXMobWFwKSkge1xuICAgIGlmIChrZXlzLmluZGV4T2Yoa2V5KSA9PT0gLTEpIHtcbiAgICAgIHNwbGl0MVtrZXldID0gbWFwW2tleV07XG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIFNwZWNpYWxGb3Jtcy5tYXAoc3BsaXQxKTtcbn1cblxuZnVuY3Rpb24gcHV0X25ldyhtYXAsIGtleSwgdmFsdWUpIHtcbiAgaWYgKGtleSBpbiBtYXApIHtcbiAgICByZXR1cm4gbWFwO1xuICB9XG5cbiAgbGV0IG5ld19tYXAgPSBPYmplY3QuYXNzaWduKHt9LCBtYXApO1xuICBuZXdfbWFwW2tleV0gPSB2YWx1ZTtcblxuICByZXR1cm4gU3BlY2lhbEZvcm1zLm1hcChuZXdfbWFwKTtcbn1cblxuZnVuY3Rpb24gcHV0X25ld19sYXp5KG1hcCwga2V5LCBmdW4pIHtcbiAgaWYgKGtleSBpbiBtYXApIHtcbiAgICByZXR1cm4gbWFwO1xuICB9XG5cbiAgbGV0IG5ld19tYXAgPSBPYmplY3QuYXNzaWduKHt9LCBtYXApO1xuICBuZXdfbWFwW2tleV0gPSBmdW4oKTtcblxuICByZXR1cm4gU3BlY2lhbEZvcm1zLm1hcChuZXdfbWFwKTtcbn1cblxuZnVuY3Rpb24gZ2V0X2FuZF91cGRhdGUobWFwLCBrZXksIGZ1bikge1xuICBpZiAoa2V5IGluIG1hcCkge1xuICAgIHJldHVybiBtYXA7XG4gIH1cblxuICBsZXQgbmV3X21hcCA9IE9iamVjdC5hc3NpZ24oe30sIG1hcCk7XG4gIG5ld19tYXBba2V5XSA9IGZ1bihtYXBba2V5XSk7XG5cbiAgcmV0dXJuIFNwZWNpYWxGb3Jtcy5tYXAobmV3X21hcCk7XG59XG5cbmZ1bmN0aW9uIHBvcF9sYXp5KG1hcCwga2V5LCBmdW4pIHtcbiAgaWYgKCFrZXkgaW4gbWFwKSB7XG4gICAgcmV0dXJuIFNwZWNpYWxGb3Jtcy50dXBsZShmdW4oKSwgbWFwKTtcbiAgfVxuXG4gIGxldCBuZXdfbWFwID0gT2JqZWN0LmFzc2lnbih7fSwgbWFwKTtcbiAgbGV0IHZhbHVlID0gZnVuKG5ld19tYXBba2V5XSk7XG4gIGRlbGV0ZSBuZXdfbWFwW2tleV07XG5cbiAgcmV0dXJuIFNwZWNpYWxGb3Jtcy50dXBsZSh2YWx1ZSwgbmV3X21hcCk7XG59XG5cbmZ1bmN0aW9uIHBvcChtYXAsIGtleSwgX2RlZmF1bHQgPSBudWxsKSB7XG4gIGlmICgha2V5IGluIG1hcCkge1xuICAgIHJldHVybiBTcGVjaWFsRm9ybXMudHVwbGUoX2RlZmF1bHQsIG1hcCk7XG4gIH1cblxuICBsZXQgbmV3X21hcCA9IE9iamVjdC5hc3NpZ24oe30sIG1hcCk7XG4gIGxldCB2YWx1ZSA9IG5ld19tYXBba2V5XTtcbiAgZGVsZXRlIG5ld19tYXBba2V5XTtcblxuICByZXR1cm4gU3BlY2lhbEZvcm1zLnR1cGxlKHZhbHVlLCBuZXdfbWFwKTtcbn1cblxuZnVuY3Rpb24gZ2V0X2xhenkobWFwLCBrZXksIGZ1bikge1xuICBpZiAoIWtleSBpbiBtYXApIHtcbiAgICByZXR1cm4gZnVuKCk7XG4gIH1cblxuICByZXR1cm4gZnVuKG1hcFtrZXldKTtcbn1cblxuZnVuY3Rpb24gZ2V0KG1hcCwga2V5LCBfZGVmYXVsdCA9IG51bGwpIHtcbiAgaWYgKCFrZXkgaW4gbWFwKSB7XG4gICAgcmV0dXJuIF9kZWZhdWx0O1xuICB9XG5cbiAgcmV0dXJuIG1hcFtrZXldO1xufVxuXG5mdW5jdGlvbiBwdXQobWFwLCBrZXksIHZhbCkge1xuICBsZXQgbmV3X21hcCA9IE9iamVjdCh7fSwgbWFwKTtcbiAgbmV3X21hcFtrZXldID0gdmFsO1xuXG4gIHJldHVybiBTcGVjaWFsRm9ybXMubWFwKG5ld19tYXApO1xufVxuXG5mdW5jdGlvbiB1cGRhdGVfX2VtYXJrX18obWFwLCBrZXksIGZ1bikge1xuICBpZiAoIWtleSBpbiBtYXApIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoXCJLZXkgbm90IGZvdW5kXCIpO1xuICB9XG5cbiAgbGV0IG5ld19tYXAgPSBPYmplY3Qoe30sIG1hcCk7XG4gIG5ld19tYXBba2V5XSA9IGZ1bihtYXBba2V5XSk7XG5cbiAgcmV0dXJuIFNwZWNpYWxGb3Jtcy5tYXAobmV3X21hcCk7XG59XG5cbmZ1bmN0aW9uIHVwZGF0ZShtYXAsIGtleSwgaW5pdGlhbCwgZnVuKSB7XG4gIGxldCBuZXdfbWFwID0gT2JqZWN0KHt9LCBtYXApO1xuXG4gIGlmICgha2V5IGluIG1hcCkge1xuICAgIG5ld19tYXBba2V5XSA9IGluaXRpYWw7XG4gIH0gZWxzZSB7XG4gICAgbmV3X21hcFtrZXldID0gZnVuKG1hcFtrZXldKTtcbiAgfVxuXG4gIHJldHVybiBTcGVjaWFsRm9ybXMubWFwKG5ld19tYXApO1xufVxuXG52YXIgbWFwID0ge1xuICBuZXc6IF9fbmV3X18sXG4gIGtleXMsXG4gIHNpemUsXG4gIHRvX2xpc3Q6IHRvX2xpc3QkMSxcbiAgdmFsdWVzLFxuICBmcm9tX3N0cnVjdCxcbiAgZGVsZXRlOiBfX2RlbGV0ZV9fLFxuICBkcm9wLFxuICBlcXVhbF9fcW1hcmtfXyxcbiAgZmV0Y2hfX2VtYXJrX18sXG4gIGZldGNoLFxuICBoYXNfa2V5X19xbWFya19fLFxuICBzcGxpdDogc3BsaXQkMSxcbiAgdGFrZSxcbiAgcHV0X25ldyxcbiAgcHV0X25ld19sYXp5LFxuICBnZXRfYW5kX3VwZGF0ZSxcbiAgcG9wX2xhenksXG4gIHBvcCxcbiAgZ2V0X2xhenksXG4gIGdldCxcbiAgcHV0LFxuICB1cGRhdGVfX2VtYXJrX18sXG4gIHVwZGF0ZVxufTtcblxuZnVuY3Rpb24gX19uZXdfXyQxKCkge1xuICByZXR1cm4gU3BlY2lhbEZvcm1zLm1hcCh7IFtTeW1ib2wuZm9yKCdfX3N0cnVjdF9fJyldOiBTeW1ib2wuZm9yKCdNYXBTZXQnKSwgc2V0OiBTcGVjaWFsRm9ybXMubGlzdCgpIH0pO1xufVxuXG5mdW5jdGlvbiBzaXplJDIobWFwKSB7XG4gIHJldHVybiBtYXAuc2V0Lmxlbmd0aDtcbn1cblxuZnVuY3Rpb24gdG9fbGlzdCQzKG1hcCkge1xuICByZXR1cm4gbWFwLnNldDtcbn1cblxuZnVuY3Rpb24gX19kZWxldGVfXyQyKHNldCwgdGVybSkge1xuICBsZXQgbmV3X2xpc3QgPSBMaXN0LmRlbGV0ZShzZXQuc2V0LCB0ZXJtKTtcblxuICBsZXQgbmV3X21hcCA9IE9iamVjdC5hc3NpZ24oe30sIHNldCk7XG4gIG5ld19tYXAuc2V0ID0gbmV3X2xpc3Q7XG4gIHJldHVybiBTcGVjaWFsRm9ybXMubWFwKG5ld19tYXApO1xufVxuXG5mdW5jdGlvbiBwdXQkMihzZXQsIHRlcm0pIHtcbiAgaWYgKHNldC5zZXQuaW5kZXhPZih0ZXJtKSA9PT0gLTEpIHtcbiAgICBsZXQgbmV3X2xpc3QgPSBMaXN0LmFwcGVuZChzZXQuc2V0LCB0ZXJtKTtcblxuICAgIGxldCBuZXdfbWFwID0gT2JqZWN0LmFzc2lnbih7fSwgc2V0KTtcbiAgICBuZXdfbWFwLnNldCA9IG5ld19saXN0O1xuICAgIHJldHVybiBTcGVjaWFsRm9ybXMubWFwKG5ld19tYXApO1xuICB9XG5cbiAgcmV0dXJuIHNldDtcbn1cblxuZnVuY3Rpb24gZGlmZmVyZW5jZSQxKHNldDEsIHNldDIpIHtcbiAgbGV0IG5ld19tYXAgPSBPYmplY3QuYXNzaWduKHt9LCBzZXQxKTtcblxuICBmb3IgKGxldCB2YWwgb2Ygc2V0MS5zZXQpIHtcbiAgICBpZiAobWVtYmVyX19xbWFya19fJDEoc2V0MiwgdmFsKSkge1xuICAgICAgbmV3X21hcC5zZXQgPSBMaXN0LmRlbGV0ZShuZXdfbWFwLnNldCwgdmFsKTtcbiAgICB9XG4gIH1cblxuICByZXR1cm4gU3BlY2lhbEZvcm1zLm1hcChuZXdfbWFwKTtcbn1cblxuZnVuY3Rpb24gaW50ZXJzZWN0aW9uJDEoc2V0MSwgc2V0Mikge1xuICBsZXQgbmV3X21hcCA9IE9iamVjdC5hc3NpZ24oe30sIHNldDEpO1xuXG4gIGZvciAobGV0IHZhbCBvZiBzZXQxLnNldCkge1xuICAgIGlmICghbWVtYmVyX19xbWFya19fJDEoc2V0MiwgdmFsKSkge1xuICAgICAgbmV3X21hcC5zZXQgPSBMaXN0LmRlbGV0ZShuZXdfbWFwLnNldCwgdmFsKTtcbiAgICB9XG4gIH1cblxuICByZXR1cm4gU3BlY2lhbEZvcm1zLm1hcChuZXdfbWFwKTtcbn1cblxuZnVuY3Rpb24gdW5pb24kMShzZXQxLCBzZXQyKSB7XG4gIGxldCBuZXdfbWFwID0gc2V0MTtcblxuICBmb3IgKGxldCB2YWwgb2Ygc2V0Mi5zZXQpIHtcbiAgICBuZXdfbWFwID0gcHV0JDIobmV3X21hcCwgdmFsKTtcbiAgfVxuXG4gIHJldHVybiBTcGVjaWFsRm9ybXMubWFwKG5ld19tYXApO1xufVxuXG5mdW5jdGlvbiBkaXNqb2luX19xbWFya19fJDEoc2V0MSwgc2V0Mikge1xuICBmb3IgKGxldCB2YWwgb2Ygc2V0MS5zZXQpIHtcbiAgICBpZiAobWVtYmVyX19xbWFya19fJDEoc2V0MiwgdmFsKSkge1xuICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH1cbiAgfVxuXG4gIHJldHVybiB0cnVlO1xufVxuXG5mdW5jdGlvbiBtZW1iZXJfX3FtYXJrX18kMShzZXQsIHZhbHVlKSB7XG4gIHJldHVybiBzZXQuc2V0LmluZGV4T2YodmFsdWUpID49IDA7XG59XG5cbmZ1bmN0aW9uIGVxdWFsX19xbWFya19fJDIoc2V0MSwgc2V0Mikge1xuICByZXR1cm4gc2V0MS5zZXQgPT09IHNldDIuc2V0O1xufVxuXG5mdW5jdGlvbiBzdWJzZXRfX3FtYXJrX18kMShzZXQxLCBzZXQyKSB7XG4gIGZvciAobGV0IHZhbCBvZiBzZXQxLnNldCkge1xuICAgIGlmICghbWVtYmVyX19xbWFya19fJDEoc2V0MiwgdmFsKSkge1xuICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH1cbiAgfVxuXG4gIHJldHVybiB0cnVlO1xufVxuXG52YXIgTWFwU2V0ID0ge1xuICBuZXc6IF9fbmV3X18kMSxcbiAgc2l6ZTogc2l6ZSQyLFxuICB0b19saXN0OiB0b19saXN0JDMsXG4gIGRpc2pvaW5fX3FtYXJrX186IGRpc2pvaW5fX3FtYXJrX18kMSxcbiAgZGVsZXRlOiBfX2RlbGV0ZV9fJDIsXG4gIHN1YnNldF9fcW1hcmtfXzogc3Vic2V0X19xbWFya19fJDEsXG4gIGVxdWFsX19xbWFya19fOiBlcXVhbF9fcW1hcmtfXyQyLFxuICBtZW1iZXJfX3FtYXJrX186IG1lbWJlcl9fcW1hcmtfXyQxLFxuICBwdXQ6IHB1dCQyLFxuICB1bmlvbjogdW5pb24kMSxcbiAgaW50ZXJzZWN0aW9uOiBpbnRlcnNlY3Rpb24kMSxcbiAgZGlmZmVyZW5jZTogZGlmZmVyZW5jZSQxXG59O1xuXG5mdW5jdGlvbiBzaXplJDEobWFwKSB7XG4gIHJldHVybiBNYXBTZXQuc2l6ZShtYXApO1xufVxuXG5mdW5jdGlvbiB0b19saXN0JDIobWFwKSB7XG4gIHJldHVybiBNYXBTZXQudG9fbGlzdChtYXApO1xufVxuXG5mdW5jdGlvbiBfX2RlbGV0ZV9fJDEoc2V0LCB0ZXJtKSB7XG4gIHJldHVybiBNYXBTZXQuZGVsZXRlKHNldCwgdGVybSk7XG59XG5cbmZ1bmN0aW9uIHB1dCQxKHNldCwgdGVybSkge1xuICByZXR1cm4gTWFwU2V0LnB1dChzZXQsIHRlcm0pO1xufVxuXG5mdW5jdGlvbiBkaWZmZXJlbmNlKHNldDEsIHNldDIpIHtcbiAgcmV0dXJuIE1hcFNldC5kaWZmZXJlbmNlKHNldDEsIHNldDIpO1xufVxuXG5mdW5jdGlvbiBpbnRlcnNlY3Rpb24oc2V0MSwgc2V0Mikge1xuICByZXR1cm4gTWFwU2V0LmludGVyc2VjdGlvbihzZXQxLCBzZXQyKTtcbn1cblxuZnVuY3Rpb24gdW5pb24oc2V0MSwgc2V0Mikge1xuICByZXR1cm4gTWFwU2V0LnVuaW9uKHNldDEsIHNldDIpO1xufVxuXG5mdW5jdGlvbiBkaXNqb2luX19xbWFya19fKHNldDEsIHNldDIpIHtcbiAgcmV0dXJuIE1hcFNldC5kaXNqb2luX19xbWFya19fKHNldDEsIHNldDIpO1xufVxuXG5mdW5jdGlvbiBtZW1iZXJfX3FtYXJrX18oc2V0LCB2YWx1ZSkge1xuICByZXR1cm4gTWFwU2V0Lm1lbWJlcl9fcW1hcmtfXyhzZXQxLCBzZXQyKTtcbn1cblxuZnVuY3Rpb24gZXF1YWxfX3FtYXJrX18kMShzZXQxLCBzZXQyKSB7XG4gIHJldHVybiBNYXBTZXQuZXF1YWxfX3FtYXJrX18oc2V0MSwgc2V0Mik7XG59XG5cbmZ1bmN0aW9uIHN1YnNldF9fcW1hcmtfXyhzZXQxLCBzZXQyKSB7XG4gIHJldHVybiBNYXBTZXQuc3Vic2V0X19xbWFya19fKHNldDEsIHNldDIpO1xufVxuXG52YXIgc2V0ID0ge1xuICBzaXplOiBzaXplJDEsXG4gIHRvX2xpc3Q6IHRvX2xpc3QkMixcbiAgZGlzam9pbl9fcW1hcmtfXyxcbiAgZGVsZXRlOiBfX2RlbGV0ZV9fJDEsXG4gIHN1YnNldF9fcW1hcmtfXyxcbiAgZXF1YWxfX3FtYXJrX186IGVxdWFsX19xbWFya19fJDEsXG4gIG1lbWJlcl9fcW1hcmtfXyxcbiAgcHV0OiBwdXQkMSxcbiAgdW5pb24sXG4gIGludGVyc2VjdGlvbixcbiAgZGlmZmVyZW5jZVxufTtcblxubGV0IFZpcnR1YWxET00gPSAoZnVuY3Rpb24gKGUpIHtcbiAgICByZXR1cm4gZSgpO1xufSkoZnVuY3Rpb24gKCkge1xuICAgIHZhciBkZWZpbmUsIG1vZHVsZSwgZXhwb3J0cztcbiAgICByZXR1cm4gKGZ1bmN0aW9uIGUodCwgbiwgcikge1xuICAgICAgICBmdW5jdGlvbiBzKG8sIHUpIHtcbiAgICAgICAgICAgIGlmICghbltvXSkge1xuICAgICAgICAgICAgICAgIGlmICghdFtvXSkge1xuICAgICAgICAgICAgICAgICAgICB2YXIgYSA9IHR5cGVvZiByZXF1aXJlID09IFwiZnVuY3Rpb25cIiAmJiByZXF1aXJlO1xuICAgICAgICAgICAgICAgICAgICBpZiAoIXUgJiYgYSkgcmV0dXJuIGEobywgITApO1xuICAgICAgICAgICAgICAgICAgICBpZiAoaSkgcmV0dXJuIGkobywgITApO1xuICAgICAgICAgICAgICAgICAgICB2YXIgZiA9IG5ldyBFcnJvcihcIkNhbm5vdCBmaW5kIG1vZHVsZSAnXCIgKyBvICsgXCInXCIpO1xuICAgICAgICAgICAgICAgICAgICB0aHJvdyAoZi5jb2RlID0gXCJNT0RVTEVfTk9UX0ZPVU5EXCIsIGYpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB2YXIgbCA9IG5bb10gPSB7XG4gICAgICAgICAgICAgICAgICAgIGV4cG9ydHM6IHt9XG4gICAgICAgICAgICAgICAgfTtcbiAgICAgICAgICAgICAgICB0W29dWzBdLmNhbGwobC5leHBvcnRzLCBmdW5jdGlvbiAoZSkge1xuICAgICAgICAgICAgICAgICAgICB2YXIgbiA9IHRbb11bMV1bZV07XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBzKG4gPyBuIDogZSk7XG4gICAgICAgICAgICAgICAgfSwgbCwgbC5leHBvcnRzLCBlLCB0LCBuLCByKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJldHVybiBuW29dLmV4cG9ydHM7XG4gICAgICAgIH1cbiAgICAgICAgdmFyIGkgPSB0eXBlb2YgcmVxdWlyZSA9PSBcImZ1bmN0aW9uXCIgJiYgcmVxdWlyZTtcbiAgICAgICAgZm9yICh2YXIgbyA9IDA7IG8gPCByLmxlbmd0aDsgbysrKSBzKHJbb10pO1xuICAgICAgICByZXR1cm4gcztcbiAgICB9KSh7XG4gICAgICAgIDE6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG5cbiAgICAgICAgICAgIHZhciBjcmVhdGVFbGVtZW50ID0gcmVxdWlyZShcIi4vdmRvbS9jcmVhdGUtZWxlbWVudC5qc1wiKTtcblxuICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBjcmVhdGVFbGVtZW50O1xuICAgICAgICB9LCB7IFwiLi92ZG9tL2NyZWF0ZS1lbGVtZW50LmpzXCI6IDE1IH1dLCAyOiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge1xuICAgICAgICAgICAgdmFyIGRpZmYgPSByZXF1aXJlKFwiLi92dHJlZS9kaWZmLmpzXCIpO1xuXG4gICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IGRpZmY7XG4gICAgICAgIH0sIHsgXCIuL3Z0cmVlL2RpZmYuanNcIjogMzUgfV0sIDM6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICB2YXIgaCA9IHJlcXVpcmUoXCIuL3ZpcnR1YWwtaHlwZXJzY3JpcHQvaW5kZXguanNcIik7XG5cbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gaDtcbiAgICAgICAgfSwgeyBcIi4vdmlydHVhbC1oeXBlcnNjcmlwdC9pbmRleC5qc1wiOiAyMiB9XSwgNDogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHtcbiAgICAgICAgICAgIHZhciBkaWZmID0gcmVxdWlyZShcIi4vZGlmZi5qc1wiKTtcbiAgICAgICAgICAgIHZhciBwYXRjaCA9IHJlcXVpcmUoXCIuL3BhdGNoLmpzXCIpO1xuICAgICAgICAgICAgdmFyIGggPSByZXF1aXJlKFwiLi9oLmpzXCIpO1xuICAgICAgICAgICAgdmFyIGNyZWF0ZSA9IHJlcXVpcmUoXCIuL2NyZWF0ZS1lbGVtZW50LmpzXCIpO1xuICAgICAgICAgICAgdmFyIFZOb2RlID0gcmVxdWlyZShcIi4vdm5vZGUvdm5vZGUuanNcIik7XG4gICAgICAgICAgICB2YXIgVlRleHQgPSByZXF1aXJlKFwiLi92bm9kZS92dGV4dC5qc1wiKTtcblxuICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSB7XG4gICAgICAgICAgICAgICAgZGlmZjogZGlmZixcbiAgICAgICAgICAgICAgICBwYXRjaDogcGF0Y2gsXG4gICAgICAgICAgICAgICAgaDogaCxcbiAgICAgICAgICAgICAgICBjcmVhdGU6IGNyZWF0ZSxcbiAgICAgICAgICAgICAgICBWTm9kZTogVk5vZGUsXG4gICAgICAgICAgICAgICAgVlRleHQ6IFZUZXh0XG4gICAgICAgICAgICB9O1xuICAgICAgICB9LCB7IFwiLi9jcmVhdGUtZWxlbWVudC5qc1wiOiAxLCBcIi4vZGlmZi5qc1wiOiAyLCBcIi4vaC5qc1wiOiAzLCBcIi4vcGF0Y2guanNcIjogMTMsIFwiLi92bm9kZS92bm9kZS5qc1wiOiAzMSwgXCIuL3Zub2RlL3Z0ZXh0LmpzXCI6IDMzIH1dLCA1OiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge1xuICAgICAgICAgICAgLyohXG4gICAgICAgICAgICAgKiBDcm9zcy1Ccm93c2VyIFNwbGl0IDEuMS4xXG4gICAgICAgICAgICAgKiBDb3B5cmlnaHQgMjAwNy0yMDEyIFN0ZXZlbiBMZXZpdGhhbiA8c3RldmVubGV2aXRoYW4uY29tPlxuICAgICAgICAgICAgICogQXZhaWxhYmxlIHVuZGVyIHRoZSBNSVQgTGljZW5zZVxuICAgICAgICAgICAgICogRUNNQVNjcmlwdCBjb21wbGlhbnQsIHVuaWZvcm0gY3Jvc3MtYnJvd3NlciBzcGxpdCBtZXRob2RcbiAgICAgICAgICAgICAqL1xuXG4gICAgICAgICAgICAvKipcbiAgICAgICAgICAgICAqIFNwbGl0cyBhIHN0cmluZyBpbnRvIGFuIGFycmF5IG9mIHN0cmluZ3MgdXNpbmcgYSByZWdleCBvciBzdHJpbmcgc2VwYXJhdG9yLiBNYXRjaGVzIG9mIHRoZVxuICAgICAgICAgICAgICogc2VwYXJhdG9yIGFyZSBub3QgaW5jbHVkZWQgaW4gdGhlIHJlc3VsdCBhcnJheS4gSG93ZXZlciwgaWYgYHNlcGFyYXRvcmAgaXMgYSByZWdleCB0aGF0IGNvbnRhaW5zXG4gICAgICAgICAgICAgKiBjYXB0dXJpbmcgZ3JvdXBzLCBiYWNrcmVmZXJlbmNlcyBhcmUgc3BsaWNlZCBpbnRvIHRoZSByZXN1bHQgZWFjaCB0aW1lIGBzZXBhcmF0b3JgIGlzIG1hdGNoZWQuXG4gICAgICAgICAgICAgKiBGaXhlcyBicm93c2VyIGJ1Z3MgY29tcGFyZWQgdG8gdGhlIG5hdGl2ZSBgU3RyaW5nLnByb3RvdHlwZS5zcGxpdGAgYW5kIGNhbiBiZSB1c2VkIHJlbGlhYmx5XG4gICAgICAgICAgICAgKiBjcm9zcy1icm93c2VyLlxuICAgICAgICAgICAgICogQHBhcmFtIHtTdHJpbmd9IHN0ciBTdHJpbmcgdG8gc3BsaXQuXG4gICAgICAgICAgICAgKiBAcGFyYW0ge1JlZ0V4cHxTdHJpbmd9IHNlcGFyYXRvciBSZWdleCBvciBzdHJpbmcgdG8gdXNlIGZvciBzZXBhcmF0aW5nIHRoZSBzdHJpbmcuXG4gICAgICAgICAgICAgKiBAcGFyYW0ge051bWJlcn0gW2xpbWl0XSBNYXhpbXVtIG51bWJlciBvZiBpdGVtcyB0byBpbmNsdWRlIGluIHRoZSByZXN1bHQgYXJyYXkuXG4gICAgICAgICAgICAgKiBAcmV0dXJucyB7QXJyYXl9IEFycmF5IG9mIHN1YnN0cmluZ3MuXG4gICAgICAgICAgICAgKiBAZXhhbXBsZVxuICAgICAgICAgICAgICpcbiAgICAgICAgICAgICAqIC8vIEJhc2ljIHVzZVxuICAgICAgICAgICAgICogc3BsaXQoJ2EgYiBjIGQnLCAnICcpO1xuICAgICAgICAgICAgICogLy8gLT4gWydhJywgJ2InLCAnYycsICdkJ11cbiAgICAgICAgICAgICAqXG4gICAgICAgICAgICAgKiAvLyBXaXRoIGxpbWl0XG4gICAgICAgICAgICAgKiBzcGxpdCgnYSBiIGMgZCcsICcgJywgMik7XG4gICAgICAgICAgICAgKiAvLyAtPiBbJ2EnLCAnYiddXG4gICAgICAgICAgICAgKlxuICAgICAgICAgICAgICogLy8gQmFja3JlZmVyZW5jZXMgaW4gcmVzdWx0IGFycmF5XG4gICAgICAgICAgICAgKiBzcGxpdCgnLi53b3JkMSB3b3JkMi4uJywgLyhbYS16XSspKFxcZCspL2kpO1xuICAgICAgICAgICAgICogLy8gLT4gWycuLicsICd3b3JkJywgJzEnLCAnICcsICd3b3JkJywgJzInLCAnLi4nXVxuICAgICAgICAgICAgICovXG4gICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IChmdW5jdGlvbiBzcGxpdCh1bmRlZikge1xuXG4gICAgICAgICAgICAgICAgdmFyIG5hdGl2ZVNwbGl0ID0gU3RyaW5nLnByb3RvdHlwZS5zcGxpdCxcbiAgICAgICAgICAgICAgICAgICAgY29tcGxpYW50RXhlY05wY2cgPSAvKCk/Py8uZXhlYyhcIlwiKVsxXSA9PT0gdW5kZWYsXG5cbiAgICAgICAgICAgICAgICAvLyBOUENHOiBub25wYXJ0aWNpcGF0aW5nIGNhcHR1cmluZyBncm91cFxuICAgICAgICAgICAgICAgIHNlbGY7XG5cbiAgICAgICAgICAgICAgICBzZWxmID0gZnVuY3Rpb24gKHN0ciwgc2VwYXJhdG9yLCBsaW1pdCkge1xuICAgICAgICAgICAgICAgICAgICAvLyBJZiBgc2VwYXJhdG9yYCBpcyBub3QgYSByZWdleCwgdXNlIGBuYXRpdmVTcGxpdGBcbiAgICAgICAgICAgICAgICAgICAgaWYgKE9iamVjdC5wcm90b3R5cGUudG9TdHJpbmcuY2FsbChzZXBhcmF0b3IpICE9PSBcIltvYmplY3QgUmVnRXhwXVwiKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gbmF0aXZlU3BsaXQuY2FsbChzdHIsIHNlcGFyYXRvciwgbGltaXQpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIHZhciBvdXRwdXQgPSBbXSxcbiAgICAgICAgICAgICAgICAgICAgICAgIGZsYWdzID0gKHNlcGFyYXRvci5pZ25vcmVDYXNlID8gXCJpXCIgOiBcIlwiKSArIChzZXBhcmF0b3IubXVsdGlsaW5lID8gXCJtXCIgOiBcIlwiKSArIChzZXBhcmF0b3IuZXh0ZW5kZWQgPyBcInhcIiA6IFwiXCIpICsgKHNlcGFyYXRvci5zdGlja3kgPyBcInlcIiA6IFwiXCIpLFxuXG4gICAgICAgICAgICAgICAgICAgIC8vIEZpcmVmb3ggMytcbiAgICAgICAgICAgICAgICAgICAgbGFzdExhc3RJbmRleCA9IDAsXG5cbiAgICAgICAgICAgICAgICAgICAgLy8gTWFrZSBgZ2xvYmFsYCBhbmQgYXZvaWQgYGxhc3RJbmRleGAgaXNzdWVzIGJ5IHdvcmtpbmcgd2l0aCBhIGNvcHlcbiAgICAgICAgICAgICAgICAgICAgc2VwYXJhdG9yID0gbmV3IFJlZ0V4cChzZXBhcmF0b3Iuc291cmNlLCBmbGFncyArIFwiZ1wiKSxcbiAgICAgICAgICAgICAgICAgICAgICAgIHNlcGFyYXRvcjIsXG4gICAgICAgICAgICAgICAgICAgICAgICBtYXRjaCxcbiAgICAgICAgICAgICAgICAgICAgICAgIGxhc3RJbmRleCxcbiAgICAgICAgICAgICAgICAgICAgICAgIGxhc3RMZW5ndGg7XG4gICAgICAgICAgICAgICAgICAgIHN0ciArPSBcIlwiOyAvLyBUeXBlLWNvbnZlcnRcbiAgICAgICAgICAgICAgICAgICAgaWYgKCFjb21wbGlhbnRFeGVjTnBjZykge1xuICAgICAgICAgICAgICAgICAgICAgICAgLy8gRG9lc24ndCBuZWVkIGZsYWdzIGd5LCBidXQgdGhleSBkb24ndCBodXJ0XG4gICAgICAgICAgICAgICAgICAgICAgICBzZXBhcmF0b3IyID0gbmV3IFJlZ0V4cChcIl5cIiArIHNlcGFyYXRvci5zb3VyY2UgKyBcIiQoPyFcXFxccylcIiwgZmxhZ3MpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIC8qIFZhbHVlcyBmb3IgYGxpbWl0YCwgcGVyIHRoZSBzcGVjOlxuICAgICAgICAgICAgICAgICAgICAgKiBJZiB1bmRlZmluZWQ6IDQyOTQ5NjcyOTUgLy8gTWF0aC5wb3coMiwgMzIpIC0gMVxuICAgICAgICAgICAgICAgICAgICAgKiBJZiAwLCBJbmZpbml0eSwgb3IgTmFOOiAwXG4gICAgICAgICAgICAgICAgICAgICAqIElmIHBvc2l0aXZlIG51bWJlcjogbGltaXQgPSBNYXRoLmZsb29yKGxpbWl0KTsgaWYgKGxpbWl0ID4gNDI5NDk2NzI5NSkgbGltaXQgLT0gNDI5NDk2NzI5NjtcbiAgICAgICAgICAgICAgICAgICAgICogSWYgbmVnYXRpdmUgbnVtYmVyOiA0Mjk0OTY3Mjk2IC0gTWF0aC5mbG9vcihNYXRoLmFicyhsaW1pdCkpXG4gICAgICAgICAgICAgICAgICAgICAqIElmIG90aGVyOiBUeXBlLWNvbnZlcnQsIHRoZW4gdXNlIHRoZSBhYm92ZSBydWxlc1xuICAgICAgICAgICAgICAgICAgICAgKi9cbiAgICAgICAgICAgICAgICAgICAgbGltaXQgPSBsaW1pdCA9PT0gdW5kZWYgPyAtMSA+Pj4gMCA6IC8vIE1hdGgucG93KDIsIDMyKSAtIDFcbiAgICAgICAgICAgICAgICAgICAgbGltaXQgPj4+IDA7IC8vIFRvVWludDMyKGxpbWl0KVxuICAgICAgICAgICAgICAgICAgICB3aGlsZSAobWF0Y2ggPSBzZXBhcmF0b3IuZXhlYyhzdHIpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAvLyBgc2VwYXJhdG9yLmxhc3RJbmRleGAgaXMgbm90IHJlbGlhYmxlIGNyb3NzLWJyb3dzZXJcbiAgICAgICAgICAgICAgICAgICAgICAgIGxhc3RJbmRleCA9IG1hdGNoLmluZGV4ICsgbWF0Y2hbMF0ubGVuZ3RoO1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGxhc3RJbmRleCA+IGxhc3RMYXN0SW5kZXgpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBvdXRwdXQucHVzaChzdHIuc2xpY2UobGFzdExhc3RJbmRleCwgbWF0Y2guaW5kZXgpKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBGaXggYnJvd3NlcnMgd2hvc2UgYGV4ZWNgIG1ldGhvZHMgZG9uJ3QgY29uc2lzdGVudGx5IHJldHVybiBgdW5kZWZpbmVkYCBmb3JcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBub25wYXJ0aWNpcGF0aW5nIGNhcHR1cmluZyBncm91cHNcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoIWNvbXBsaWFudEV4ZWNOcGNnICYmIG1hdGNoLmxlbmd0aCA+IDEpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbWF0Y2hbMF0ucmVwbGFjZShzZXBhcmF0b3IyLCBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBmb3IgKHZhciBpID0gMTsgaSA8IGFyZ3VtZW50cy5sZW5ndGggLSAyOyBpKyspIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoYXJndW1lbnRzW2ldID09PSB1bmRlZikge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBtYXRjaFtpXSA9IHVuZGVmO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChtYXRjaC5sZW5ndGggPiAxICYmIG1hdGNoLmluZGV4IDwgc3RyLmxlbmd0aCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBBcnJheS5wcm90b3R5cGUucHVzaC5hcHBseShvdXRwdXQsIG1hdGNoLnNsaWNlKDEpKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgbGFzdExlbmd0aCA9IG1hdGNoWzBdLmxlbmd0aDtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBsYXN0TGFzdEluZGV4ID0gbGFzdEluZGV4O1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChvdXRwdXQubGVuZ3RoID49IGxpbWl0KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChzZXBhcmF0b3IubGFzdEluZGV4ID09PSBtYXRjaC5pbmRleCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNlcGFyYXRvci5sYXN0SW5kZXgrKzsgLy8gQXZvaWQgYW4gaW5maW5pdGUgbG9vcFxuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIGlmIChsYXN0TGFzdEluZGV4ID09PSBzdHIubGVuZ3RoKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAobGFzdExlbmd0aCB8fCAhc2VwYXJhdG9yLnRlc3QoXCJcIikpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBvdXRwdXQucHVzaChcIlwiKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIG91dHB1dC5wdXNoKHN0ci5zbGljZShsYXN0TGFzdEluZGV4KSk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIG91dHB1dC5sZW5ndGggPiBsaW1pdCA/IG91dHB1dC5zbGljZSgwLCBsaW1pdCkgOiBvdXRwdXQ7XG4gICAgICAgICAgICAgICAgfTtcblxuICAgICAgICAgICAgICAgIHJldHVybiBzZWxmO1xuICAgICAgICAgICAgfSkoKTtcbiAgICAgICAgfSwge31dLCA2OiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge30sIHt9XSwgNzogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHtcbiAgICAgICAgICAgIFwidXNlIHN0cmljdFwiO1xuXG4gICAgICAgICAgICB2YXIgT25lVmVyc2lvbkNvbnN0cmFpbnQgPSByZXF1aXJlKFwiaW5kaXZpZHVhbC9vbmUtdmVyc2lvblwiKTtcblxuICAgICAgICAgICAgdmFyIE1ZX1ZFUlNJT04gPSBcIjdcIjtcbiAgICAgICAgICAgIE9uZVZlcnNpb25Db25zdHJhaW50KFwiZXYtc3RvcmVcIiwgTVlfVkVSU0lPTik7XG5cbiAgICAgICAgICAgIHZhciBoYXNoS2V5ID0gXCJfX0VWX1NUT1JFX0tFWUBcIiArIE1ZX1ZFUlNJT047XG5cbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gRXZTdG9yZTtcblxuICAgICAgICAgICAgZnVuY3Rpb24gRXZTdG9yZShlbGVtKSB7XG4gICAgICAgICAgICAgICAgdmFyIGhhc2ggPSBlbGVtW2hhc2hLZXldO1xuXG4gICAgICAgICAgICAgICAgaWYgKCFoYXNoKSB7XG4gICAgICAgICAgICAgICAgICAgIGhhc2ggPSBlbGVtW2hhc2hLZXldID0ge307XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgcmV0dXJuIGhhc2g7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0sIHsgXCJpbmRpdmlkdWFsL29uZS12ZXJzaW9uXCI6IDkgfV0sIDg6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICAoZnVuY3Rpb24gKGdsb2JhbCkge1xuICAgICAgICAgICAgICAgIFwidXNlIHN0cmljdFwiO1xuXG4gICAgICAgICAgICAgICAgLypnbG9iYWwgd2luZG93LCBnbG9iYWwqL1xuXG4gICAgICAgICAgICAgICAgdmFyIHJvb3QgPSB0eXBlb2Ygd2luZG93ICE9PSBcInVuZGVmaW5lZFwiID8gd2luZG93IDogdHlwZW9mIGdsb2JhbCAhPT0gXCJ1bmRlZmluZWRcIiA/IGdsb2JhbCA6IHt9O1xuXG4gICAgICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBJbmRpdmlkdWFsO1xuXG4gICAgICAgICAgICAgICAgZnVuY3Rpb24gSW5kaXZpZHVhbChrZXksIHZhbHVlKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmIChrZXkgaW4gcm9vdCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHJvb3Rba2V5XTtcbiAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgIHJvb3Rba2V5XSA9IHZhbHVlO1xuXG4gICAgICAgICAgICAgICAgICAgIHJldHVybiB2YWx1ZTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9KS5jYWxsKHRoaXMsIHR5cGVvZiBnbG9iYWwgIT09IFwidW5kZWZpbmVkXCIgPyBnbG9iYWwgOiB0eXBlb2Ygc2VsZiAhPT0gXCJ1bmRlZmluZWRcIiA/IHNlbGYgOiB0eXBlb2Ygd2luZG93ICE9PSBcInVuZGVmaW5lZFwiID8gd2luZG93IDoge30pO1xuICAgICAgICB9LCB7fV0sIDk6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICBcInVzZSBzdHJpY3RcIjtcblxuICAgICAgICAgICAgdmFyIEluZGl2aWR1YWwgPSByZXF1aXJlKFwiLi9pbmRleC5qc1wiKTtcblxuICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBPbmVWZXJzaW9uO1xuXG4gICAgICAgICAgICBmdW5jdGlvbiBPbmVWZXJzaW9uKG1vZHVsZU5hbWUsIHZlcnNpb24sIGRlZmF1bHRWYWx1ZSkge1xuICAgICAgICAgICAgICAgIHZhciBrZXkgPSBcIl9fSU5ESVZJRFVBTF9PTkVfVkVSU0lPTl9cIiArIG1vZHVsZU5hbWU7XG4gICAgICAgICAgICAgICAgdmFyIGVuZm9yY2VLZXkgPSBrZXkgKyBcIl9FTkZPUkNFX1NJTkdMRVRPTlwiO1xuXG4gICAgICAgICAgICAgICAgdmFyIHZlcnNpb25WYWx1ZSA9IEluZGl2aWR1YWwoZW5mb3JjZUtleSwgdmVyc2lvbik7XG5cbiAgICAgICAgICAgICAgICBpZiAodmVyc2lvblZhbHVlICE9PSB2ZXJzaW9uKSB7XG4gICAgICAgICAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcihcIkNhbiBvbmx5IGhhdmUgb25lIGNvcHkgb2YgXCIgKyBtb2R1bGVOYW1lICsgXCIuXFxuXCIgKyBcIllvdSBhbHJlYWR5IGhhdmUgdmVyc2lvbiBcIiArIHZlcnNpb25WYWx1ZSArIFwiIGluc3RhbGxlZC5cXG5cIiArIFwiVGhpcyBtZWFucyB5b3UgY2Fubm90IGluc3RhbGwgdmVyc2lvbiBcIiArIHZlcnNpb24pO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHJldHVybiBJbmRpdmlkdWFsKGtleSwgZGVmYXVsdFZhbHVlKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSwgeyBcIi4vaW5kZXguanNcIjogOCB9XSwgMTA6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICAoZnVuY3Rpb24gKGdsb2JhbCkge1xuICAgICAgICAgICAgICAgIHZhciB0b3BMZXZlbCA9IHR5cGVvZiBnbG9iYWwgIT09IFwidW5kZWZpbmVkXCIgPyBnbG9iYWwgOiB0eXBlb2Ygd2luZG93ICE9PSBcInVuZGVmaW5lZFwiID8gd2luZG93IDoge307XG4gICAgICAgICAgICAgICAgdmFyIG1pbkRvYyA9IHJlcXVpcmUoXCJtaW4tZG9jdW1lbnRcIik7XG5cbiAgICAgICAgICAgICAgICBpZiAodHlwZW9mIGRvY3VtZW50ICE9PSBcInVuZGVmaW5lZFwiKSB7XG4gICAgICAgICAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gZG9jdW1lbnQ7XG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgdmFyIGRvY2N5ID0gdG9wTGV2ZWxbXCJfX0dMT0JBTF9ET0NVTUVOVF9DQUNIRUA0XCJdO1xuXG4gICAgICAgICAgICAgICAgICAgIGlmICghZG9jY3kpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGRvY2N5ID0gdG9wTGV2ZWxbXCJfX0dMT0JBTF9ET0NVTUVOVF9DQUNIRUA0XCJdID0gbWluRG9jO1xuICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBkb2NjeTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9KS5jYWxsKHRoaXMsIHR5cGVvZiBnbG9iYWwgIT09IFwidW5kZWZpbmVkXCIgPyBnbG9iYWwgOiB0eXBlb2Ygc2VsZiAhPT0gXCJ1bmRlZmluZWRcIiA/IHNlbGYgOiB0eXBlb2Ygd2luZG93ICE9PSBcInVuZGVmaW5lZFwiID8gd2luZG93IDoge30pO1xuICAgICAgICB9LCB7IFwibWluLWRvY3VtZW50XCI6IDYgfV0sIDExOiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge1xuICAgICAgICAgICAgXCJ1c2Ugc3RyaWN0XCI7XG5cbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gaXNPYmplY3QoeCkge1xuICAgICAgICAgICAgICAgIHJldHVybiB0eXBlb2YgeCA9PT0gXCJvYmplY3RcIiAmJiB4ICE9PSBudWxsO1xuICAgICAgICAgICAgfTtcbiAgICAgICAgfSwge31dLCAxMjogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHtcbiAgICAgICAgICAgIHZhciBuYXRpdmVJc0FycmF5ID0gQXJyYXkuaXNBcnJheTtcbiAgICAgICAgICAgIHZhciB0b1N0cmluZyA9IE9iamVjdC5wcm90b3R5cGUudG9TdHJpbmc7XG5cbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gbmF0aXZlSXNBcnJheSB8fCBpc0FycmF5O1xuXG4gICAgICAgICAgICBmdW5jdGlvbiBpc0FycmF5KG9iaikge1xuICAgICAgICAgICAgICAgIHJldHVybiB0b1N0cmluZy5jYWxsKG9iaikgPT09IFwiW29iamVjdCBBcnJheV1cIjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSwge31dLCAxMzogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHtcbiAgICAgICAgICAgIHZhciBwYXRjaCA9IHJlcXVpcmUoXCIuL3Zkb20vcGF0Y2guanNcIik7XG5cbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gcGF0Y2g7XG4gICAgICAgIH0sIHsgXCIuL3Zkb20vcGF0Y2guanNcIjogMTggfV0sIDE0OiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge1xuICAgICAgICAgICAgdmFyIGlzT2JqZWN0ID0gcmVxdWlyZShcImlzLW9iamVjdFwiKTtcbiAgICAgICAgICAgIHZhciBpc0hvb2sgPSByZXF1aXJlKFwiLi4vdm5vZGUvaXMtdmhvb2suanNcIik7XG5cbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gYXBwbHlQcm9wZXJ0aWVzO1xuXG4gICAgICAgICAgICBmdW5jdGlvbiBhcHBseVByb3BlcnRpZXMobm9kZSwgcHJvcHMsIHByZXZpb3VzKSB7XG4gICAgICAgICAgICAgICAgZm9yICh2YXIgcHJvcE5hbWUgaW4gcHJvcHMpIHtcbiAgICAgICAgICAgICAgICAgICAgdmFyIHByb3BWYWx1ZSA9IHByb3BzW3Byb3BOYW1lXTtcblxuICAgICAgICAgICAgICAgICAgICBpZiAocHJvcFZhbHVlID09PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJlbW92ZVByb3BlcnR5KG5vZGUsIHByb3BOYW1lLCBwcm9wVmFsdWUsIHByZXZpb3VzKTtcbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIGlmIChpc0hvb2socHJvcFZhbHVlKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgcmVtb3ZlUHJvcGVydHkobm9kZSwgcHJvcE5hbWUsIHByb3BWYWx1ZSwgcHJldmlvdXMpO1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHByb3BWYWx1ZS5ob29rKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcHJvcFZhbHVlLmhvb2sobm9kZSwgcHJvcE5hbWUsIHByZXZpb3VzID8gcHJldmlvdXNbcHJvcE5hbWVdIDogdW5kZWZpbmVkKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChpc09iamVjdChwcm9wVmFsdWUpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcGF0Y2hPYmplY3Qobm9kZSwgcHJvcHMsIHByZXZpb3VzLCBwcm9wTmFtZSwgcHJvcFZhbHVlKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgbm9kZVtwcm9wTmFtZV0gPSBwcm9wVmFsdWU7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIHJlbW92ZVByb3BlcnR5KG5vZGUsIHByb3BOYW1lLCBwcm9wVmFsdWUsIHByZXZpb3VzKSB7XG4gICAgICAgICAgICAgICAgaWYgKHByZXZpb3VzKSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciBwcmV2aW91c1ZhbHVlID0gcHJldmlvdXNbcHJvcE5hbWVdO1xuXG4gICAgICAgICAgICAgICAgICAgIGlmICghaXNIb29rKHByZXZpb3VzVmFsdWUpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAocHJvcE5hbWUgPT09IFwiYXR0cmlidXRlc1wiKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgZm9yICh2YXIgYXR0ck5hbWUgaW4gcHJldmlvdXNWYWx1ZSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBub2RlLnJlbW92ZUF0dHJpYnV0ZShhdHRyTmFtZSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIGlmIChwcm9wTmFtZSA9PT0gXCJzdHlsZVwiKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgZm9yICh2YXIgaSBpbiBwcmV2aW91c1ZhbHVlKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG5vZGUuc3R5bGVbaV0gPSBcIlwiO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAodHlwZW9mIHByZXZpb3VzVmFsdWUgPT09IFwic3RyaW5nXCIpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBub2RlW3Byb3BOYW1lXSA9IFwiXCI7XG4gICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIG5vZGVbcHJvcE5hbWVdID0gbnVsbDtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIGlmIChwcmV2aW91c1ZhbHVlLnVuaG9vaykge1xuICAgICAgICAgICAgICAgICAgICAgICAgcHJldmlvdXNWYWx1ZS51bmhvb2sobm9kZSwgcHJvcE5hbWUsIHByb3BWYWx1ZSk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIHBhdGNoT2JqZWN0KG5vZGUsIHByb3BzLCBwcmV2aW91cywgcHJvcE5hbWUsIHByb3BWYWx1ZSkge1xuICAgICAgICAgICAgICAgIHZhciBwcmV2aW91c1ZhbHVlID0gcHJldmlvdXMgPyBwcmV2aW91c1twcm9wTmFtZV0gOiB1bmRlZmluZWQ7XG5cbiAgICAgICAgICAgICAgICAvLyBTZXQgYXR0cmlidXRlc1xuICAgICAgICAgICAgICAgIGlmIChwcm9wTmFtZSA9PT0gXCJhdHRyaWJ1dGVzXCIpIHtcbiAgICAgICAgICAgICAgICAgICAgZm9yICh2YXIgYXR0ck5hbWUgaW4gcHJvcFZhbHVlKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICB2YXIgYXR0clZhbHVlID0gcHJvcFZhbHVlW2F0dHJOYW1lXTtcblxuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGF0dHJWYWx1ZSA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgbm9kZS5yZW1vdmVBdHRyaWJ1dGUoYXR0ck5hbWUpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBub2RlLnNldEF0dHJpYnV0ZShhdHRyTmFtZSwgYXR0clZhbHVlKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICBpZiAocHJldmlvdXNWYWx1ZSAmJiBpc09iamVjdChwcmV2aW91c1ZhbHVlKSAmJiBnZXRQcm90b3R5cGUocHJldmlvdXNWYWx1ZSkgIT09IGdldFByb3RvdHlwZShwcm9wVmFsdWUpKSB7XG4gICAgICAgICAgICAgICAgICAgIG5vZGVbcHJvcE5hbWVdID0gcHJvcFZhbHVlO1xuICAgICAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgaWYgKCFpc09iamVjdChub2RlW3Byb3BOYW1lXSkpIHtcbiAgICAgICAgICAgICAgICAgICAgbm9kZVtwcm9wTmFtZV0gPSB7fTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICB2YXIgcmVwbGFjZXIgPSBwcm9wTmFtZSA9PT0gXCJzdHlsZVwiID8gXCJcIiA6IHVuZGVmaW5lZDtcblxuICAgICAgICAgICAgICAgIGZvciAodmFyIGsgaW4gcHJvcFZhbHVlKSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciB2YWx1ZSA9IHByb3BWYWx1ZVtrXTtcbiAgICAgICAgICAgICAgICAgICAgbm9kZVtwcm9wTmFtZV1ba10gPSB2YWx1ZSA9PT0gdW5kZWZpbmVkID8gcmVwbGFjZXIgOiB2YWx1ZTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIGdldFByb3RvdHlwZSh2YWx1ZSkge1xuICAgICAgICAgICAgICAgIGlmIChPYmplY3QuZ2V0UHJvdG90eXBlT2YpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIE9iamVjdC5nZXRQcm90b3R5cGVPZih2YWx1ZSk7XG4gICAgICAgICAgICAgICAgfSBlbHNlIGlmICh2YWx1ZS5fX3Byb3RvX18pIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHZhbHVlLl9fcHJvdG9fXztcbiAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKHZhbHVlLmNvbnN0cnVjdG9yKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiB2YWx1ZS5jb25zdHJ1Y3Rvci5wcm90b3R5cGU7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9LCB7IFwiLi4vdm5vZGUvaXMtdmhvb2suanNcIjogMjYsIFwiaXMtb2JqZWN0XCI6IDExIH1dLCAxNTogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHtcbiAgICAgICAgICAgIHZhciBkb2N1bWVudCA9IHJlcXVpcmUoXCJnbG9iYWwvZG9jdW1lbnRcIik7XG5cbiAgICAgICAgICAgIHZhciBhcHBseVByb3BlcnRpZXMgPSByZXF1aXJlKFwiLi9hcHBseS1wcm9wZXJ0aWVzXCIpO1xuXG4gICAgICAgICAgICB2YXIgaXNWTm9kZSA9IHJlcXVpcmUoXCIuLi92bm9kZS9pcy12bm9kZS5qc1wiKTtcbiAgICAgICAgICAgIHZhciBpc1ZUZXh0ID0gcmVxdWlyZShcIi4uL3Zub2RlL2lzLXZ0ZXh0LmpzXCIpO1xuICAgICAgICAgICAgdmFyIGlzV2lkZ2V0ID0gcmVxdWlyZShcIi4uL3Zub2RlL2lzLXdpZGdldC5qc1wiKTtcbiAgICAgICAgICAgIHZhciBoYW5kbGVUaHVuayA9IHJlcXVpcmUoXCIuLi92bm9kZS9oYW5kbGUtdGh1bmsuanNcIik7XG5cbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gY3JlYXRlRWxlbWVudDtcblxuICAgICAgICAgICAgZnVuY3Rpb24gY3JlYXRlRWxlbWVudCh2bm9kZSwgb3B0cykge1xuICAgICAgICAgICAgICAgIHZhciBkb2MgPSBvcHRzID8gb3B0cy5kb2N1bWVudCB8fCBkb2N1bWVudCA6IGRvY3VtZW50O1xuICAgICAgICAgICAgICAgIHZhciB3YXJuID0gb3B0cyA/IG9wdHMud2FybiA6IG51bGw7XG5cbiAgICAgICAgICAgICAgICB2bm9kZSA9IGhhbmRsZVRodW5rKHZub2RlKS5hO1xuXG4gICAgICAgICAgICAgICAgaWYgKGlzV2lkZ2V0KHZub2RlKSkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gdm5vZGUuaW5pdCgpO1xuICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoaXNWVGV4dCh2bm9kZSkpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGRvYy5jcmVhdGVUZXh0Tm9kZSh2bm9kZS50ZXh0KTtcbiAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKCFpc1ZOb2RlKHZub2RlKSkge1xuICAgICAgICAgICAgICAgICAgICBpZiAod2Fybikge1xuICAgICAgICAgICAgICAgICAgICAgICAgd2FybihcIkl0ZW0gaXMgbm90IGEgdmFsaWQgdmlydHVhbCBkb20gbm9kZVwiLCB2bm9kZSk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIG51bGw7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgdmFyIG5vZGUgPSB2bm9kZS5uYW1lc3BhY2UgPT09IG51bGwgPyBkb2MuY3JlYXRlRWxlbWVudCh2bm9kZS50YWdOYW1lKSA6IGRvYy5jcmVhdGVFbGVtZW50TlModm5vZGUubmFtZXNwYWNlLCB2bm9kZS50YWdOYW1lKTtcblxuICAgICAgICAgICAgICAgIHZhciBwcm9wcyA9IHZub2RlLnByb3BlcnRpZXM7XG4gICAgICAgICAgICAgICAgYXBwbHlQcm9wZXJ0aWVzKG5vZGUsIHByb3BzKTtcblxuICAgICAgICAgICAgICAgIHZhciBjaGlsZHJlbiA9IHZub2RlLmNoaWxkcmVuO1xuXG4gICAgICAgICAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCBjaGlsZHJlbi5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgICAgICAgICB2YXIgY2hpbGROb2RlID0gY3JlYXRlRWxlbWVudChjaGlsZHJlbltpXSwgb3B0cyk7XG4gICAgICAgICAgICAgICAgICAgIGlmIChjaGlsZE5vZGUpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIG5vZGUuYXBwZW5kQ2hpbGQoY2hpbGROb2RlKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHJldHVybiBub2RlO1xuICAgICAgICAgICAgfVxuICAgICAgICB9LCB7IFwiLi4vdm5vZGUvaGFuZGxlLXRodW5rLmpzXCI6IDI0LCBcIi4uL3Zub2RlL2lzLXZub2RlLmpzXCI6IDI3LCBcIi4uL3Zub2RlL2lzLXZ0ZXh0LmpzXCI6IDI4LCBcIi4uL3Zub2RlL2lzLXdpZGdldC5qc1wiOiAyOSwgXCIuL2FwcGx5LXByb3BlcnRpZXNcIjogMTQsIFwiZ2xvYmFsL2RvY3VtZW50XCI6IDEwIH1dLCAxNjogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHtcbiAgICAgICAgICAgIC8vIE1hcHMgYSB2aXJ0dWFsIERPTSB0cmVlIG9udG8gYSByZWFsIERPTSB0cmVlIGluIGFuIGVmZmljaWVudCBtYW5uZXIuXG4gICAgICAgICAgICAvLyBXZSBkb24ndCB3YW50IHRvIHJlYWQgYWxsIG9mIHRoZSBET00gbm9kZXMgaW4gdGhlIHRyZWUgc28gd2UgdXNlXG4gICAgICAgICAgICAvLyB0aGUgaW4tb3JkZXIgdHJlZSBpbmRleGluZyB0byBlbGltaW5hdGUgcmVjdXJzaW9uIGRvd24gY2VydGFpbiBicmFuY2hlcy5cbiAgICAgICAgICAgIC8vIFdlIG9ubHkgcmVjdXJzZSBpbnRvIGEgRE9NIG5vZGUgaWYgd2Uga25vdyB0aGF0IGl0IGNvbnRhaW5zIGEgY2hpbGQgb2ZcbiAgICAgICAgICAgIC8vIGludGVyZXN0LlxuXG4gICAgICAgICAgICB2YXIgbm9DaGlsZCA9IHt9O1xuXG4gICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IGRvbUluZGV4O1xuXG4gICAgICAgICAgICBmdW5jdGlvbiBkb21JbmRleChyb290Tm9kZSwgdHJlZSwgaW5kaWNlcywgbm9kZXMpIHtcbiAgICAgICAgICAgICAgICBpZiAoIWluZGljZXMgfHwgaW5kaWNlcy5sZW5ndGggPT09IDApIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHt9O1xuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIGluZGljZXMuc29ydChhc2NlbmRpbmcpO1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gcmVjdXJzZShyb290Tm9kZSwgdHJlZSwgaW5kaWNlcywgbm9kZXMsIDApO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZnVuY3Rpb24gcmVjdXJzZShyb290Tm9kZSwgdHJlZSwgaW5kaWNlcywgbm9kZXMsIHJvb3RJbmRleCkge1xuICAgICAgICAgICAgICAgIG5vZGVzID0gbm9kZXMgfHwge307XG5cbiAgICAgICAgICAgICAgICBpZiAocm9vdE5vZGUpIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKGluZGV4SW5SYW5nZShpbmRpY2VzLCByb290SW5kZXgsIHJvb3RJbmRleCkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIG5vZGVzW3Jvb3RJbmRleF0gPSByb290Tm9kZTtcbiAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgIHZhciB2Q2hpbGRyZW4gPSB0cmVlLmNoaWxkcmVuO1xuXG4gICAgICAgICAgICAgICAgICAgIGlmICh2Q2hpbGRyZW4pIHtcblxuICAgICAgICAgICAgICAgICAgICAgICAgdmFyIGNoaWxkTm9kZXMgPSByb290Tm9kZS5jaGlsZE5vZGVzO1xuXG4gICAgICAgICAgICAgICAgICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IHRyZWUuY2hpbGRyZW4ubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICByb290SW5kZXggKz0gMTtcblxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZhciB2Q2hpbGQgPSB2Q2hpbGRyZW5baV0gfHwgbm9DaGlsZDtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB2YXIgbmV4dEluZGV4ID0gcm9vdEluZGV4ICsgKHZDaGlsZC5jb3VudCB8fCAwKTtcblxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIHNraXAgcmVjdXJzaW9uIGRvd24gdGhlIHRyZWUgaWYgdGhlcmUgYXJlIG5vIG5vZGVzIGRvd24gaGVyZVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChpbmRleEluUmFuZ2UoaW5kaWNlcywgcm9vdEluZGV4LCBuZXh0SW5kZXgpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlY3Vyc2UoY2hpbGROb2Rlc1tpXSwgdkNoaWxkLCBpbmRpY2VzLCBub2Rlcywgcm9vdEluZGV4KTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICByb290SW5kZXggPSBuZXh0SW5kZXg7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICByZXR1cm4gbm9kZXM7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIC8vIEJpbmFyeSBzZWFyY2ggZm9yIGFuIGluZGV4IGluIHRoZSBpbnRlcnZhbCBbbGVmdCwgcmlnaHRdXG4gICAgICAgICAgICBmdW5jdGlvbiBpbmRleEluUmFuZ2UoaW5kaWNlcywgbGVmdCwgcmlnaHQpIHtcbiAgICAgICAgICAgICAgICBpZiAoaW5kaWNlcy5sZW5ndGggPT09IDApIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHZhciBtaW5JbmRleCA9IDA7XG4gICAgICAgICAgICAgICAgdmFyIG1heEluZGV4ID0gaW5kaWNlcy5sZW5ndGggLSAxO1xuICAgICAgICAgICAgICAgIHZhciBjdXJyZW50SW5kZXg7XG4gICAgICAgICAgICAgICAgdmFyIGN1cnJlbnRJdGVtO1xuXG4gICAgICAgICAgICAgICAgd2hpbGUgKG1pbkluZGV4IDw9IG1heEluZGV4KSB7XG4gICAgICAgICAgICAgICAgICAgIGN1cnJlbnRJbmRleCA9IChtYXhJbmRleCArIG1pbkluZGV4KSAvIDIgPj4gMDtcbiAgICAgICAgICAgICAgICAgICAgY3VycmVudEl0ZW0gPSBpbmRpY2VzW2N1cnJlbnRJbmRleF07XG5cbiAgICAgICAgICAgICAgICAgICAgaWYgKG1pbkluZGV4ID09PSBtYXhJbmRleCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGN1cnJlbnRJdGVtID49IGxlZnQgJiYgY3VycmVudEl0ZW0gPD0gcmlnaHQ7XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoY3VycmVudEl0ZW0gPCBsZWZ0KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBtaW5JbmRleCA9IGN1cnJlbnRJbmRleCArIDE7XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoY3VycmVudEl0ZW0gPiByaWdodCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgbWF4SW5kZXggPSBjdXJyZW50SW5kZXggLSAxO1xuICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIGFzY2VuZGluZyhhLCBiKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGEgPiBiID8gMSA6IC0xO1xuICAgICAgICAgICAgfVxuICAgICAgICB9LCB7fV0sIDE3OiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge1xuICAgICAgICAgICAgdmFyIGFwcGx5UHJvcGVydGllcyA9IHJlcXVpcmUoXCIuL2FwcGx5LXByb3BlcnRpZXNcIik7XG5cbiAgICAgICAgICAgIHZhciBpc1dpZGdldCA9IHJlcXVpcmUoXCIuLi92bm9kZS9pcy13aWRnZXQuanNcIik7XG4gICAgICAgICAgICB2YXIgVlBhdGNoID0gcmVxdWlyZShcIi4uL3Zub2RlL3ZwYXRjaC5qc1wiKTtcblxuICAgICAgICAgICAgdmFyIHVwZGF0ZVdpZGdldCA9IHJlcXVpcmUoXCIuL3VwZGF0ZS13aWRnZXRcIik7XG5cbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gYXBwbHlQYXRjaDtcblxuICAgICAgICAgICAgZnVuY3Rpb24gYXBwbHlQYXRjaCh2cGF0Y2gsIGRvbU5vZGUsIHJlbmRlck9wdGlvbnMpIHtcbiAgICAgICAgICAgICAgICB2YXIgdHlwZSA9IHZwYXRjaC50eXBlO1xuICAgICAgICAgICAgICAgIHZhciB2Tm9kZSA9IHZwYXRjaC52Tm9kZTtcbiAgICAgICAgICAgICAgICB2YXIgcGF0Y2ggPSB2cGF0Y2gucGF0Y2g7XG5cbiAgICAgICAgICAgICAgICBzd2l0Y2ggKHR5cGUpIHtcbiAgICAgICAgICAgICAgICAgICAgY2FzZSBWUGF0Y2guUkVNT1ZFOlxuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHJlbW92ZU5vZGUoZG9tTm9kZSwgdk5vZGUpO1xuICAgICAgICAgICAgICAgICAgICBjYXNlIFZQYXRjaC5JTlNFUlQ6XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gaW5zZXJ0Tm9kZShkb21Ob2RlLCBwYXRjaCwgcmVuZGVyT3B0aW9ucyk7XG4gICAgICAgICAgICAgICAgICAgIGNhc2UgVlBhdGNoLlZURVhUOlxuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHN0cmluZ1BhdGNoKGRvbU5vZGUsIHZOb2RlLCBwYXRjaCwgcmVuZGVyT3B0aW9ucyk7XG4gICAgICAgICAgICAgICAgICAgIGNhc2UgVlBhdGNoLldJREdFVDpcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiB3aWRnZXRQYXRjaChkb21Ob2RlLCB2Tm9kZSwgcGF0Y2gsIHJlbmRlck9wdGlvbnMpO1xuICAgICAgICAgICAgICAgICAgICBjYXNlIFZQYXRjaC5WTk9ERTpcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiB2Tm9kZVBhdGNoKGRvbU5vZGUsIHZOb2RlLCBwYXRjaCwgcmVuZGVyT3B0aW9ucyk7XG4gICAgICAgICAgICAgICAgICAgIGNhc2UgVlBhdGNoLk9SREVSOlxuICAgICAgICAgICAgICAgICAgICAgICAgcmVvcmRlckNoaWxkcmVuKGRvbU5vZGUsIHBhdGNoKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBkb21Ob2RlO1xuICAgICAgICAgICAgICAgICAgICBjYXNlIFZQYXRjaC5QUk9QUzpcbiAgICAgICAgICAgICAgICAgICAgICAgIGFwcGx5UHJvcGVydGllcyhkb21Ob2RlLCBwYXRjaCwgdk5vZGUucHJvcGVydGllcyk7XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gZG9tTm9kZTtcbiAgICAgICAgICAgICAgICAgICAgY2FzZSBWUGF0Y2guVEhVTks6XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gcmVwbGFjZVJvb3QoZG9tTm9kZSwgcmVuZGVyT3B0aW9ucy5wYXRjaChkb21Ob2RlLCBwYXRjaCwgcmVuZGVyT3B0aW9ucykpO1xuICAgICAgICAgICAgICAgICAgICBkZWZhdWx0OlxuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGRvbU5vZGU7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBmdW5jdGlvbiByZW1vdmVOb2RlKGRvbU5vZGUsIHZOb2RlKSB7XG4gICAgICAgICAgICAgICAgdmFyIHBhcmVudE5vZGUgPSBkb21Ob2RlLnBhcmVudE5vZGU7XG5cbiAgICAgICAgICAgICAgICBpZiAocGFyZW50Tm9kZSkge1xuICAgICAgICAgICAgICAgICAgICBwYXJlbnROb2RlLnJlbW92ZUNoaWxkKGRvbU5vZGUpO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIGRlc3Ryb3lXaWRnZXQoZG9tTm9kZSwgdk5vZGUpO1xuXG4gICAgICAgICAgICAgICAgcmV0dXJuIG51bGw7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIGluc2VydE5vZGUocGFyZW50Tm9kZSwgdk5vZGUsIHJlbmRlck9wdGlvbnMpIHtcbiAgICAgICAgICAgICAgICB2YXIgbmV3Tm9kZSA9IHJlbmRlck9wdGlvbnMucmVuZGVyKHZOb2RlLCByZW5kZXJPcHRpb25zKTtcblxuICAgICAgICAgICAgICAgIGlmIChwYXJlbnROb2RlKSB7XG4gICAgICAgICAgICAgICAgICAgIHBhcmVudE5vZGUuYXBwZW5kQ2hpbGQobmV3Tm9kZSk7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgcmV0dXJuIHBhcmVudE5vZGU7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIHN0cmluZ1BhdGNoKGRvbU5vZGUsIGxlZnRWTm9kZSwgdlRleHQsIHJlbmRlck9wdGlvbnMpIHtcbiAgICAgICAgICAgICAgICB2YXIgbmV3Tm9kZTtcblxuICAgICAgICAgICAgICAgIGlmIChkb21Ob2RlLm5vZGVUeXBlID09PSAzKSB7XG4gICAgICAgICAgICAgICAgICAgIGRvbU5vZGUucmVwbGFjZURhdGEoMCwgZG9tTm9kZS5sZW5ndGgsIHZUZXh0LnRleHQpO1xuICAgICAgICAgICAgICAgICAgICBuZXdOb2RlID0gZG9tTm9kZTtcbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICB2YXIgcGFyZW50Tm9kZSA9IGRvbU5vZGUucGFyZW50Tm9kZTtcbiAgICAgICAgICAgICAgICAgICAgbmV3Tm9kZSA9IHJlbmRlck9wdGlvbnMucmVuZGVyKHZUZXh0LCByZW5kZXJPcHRpb25zKTtcblxuICAgICAgICAgICAgICAgICAgICBpZiAocGFyZW50Tm9kZSAmJiBuZXdOb2RlICE9PSBkb21Ob2RlKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBwYXJlbnROb2RlLnJlcGxhY2VDaGlsZChuZXdOb2RlLCBkb21Ob2RlKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHJldHVybiBuZXdOb2RlO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBmdW5jdGlvbiB3aWRnZXRQYXRjaChkb21Ob2RlLCBsZWZ0Vk5vZGUsIHdpZGdldCwgcmVuZGVyT3B0aW9ucykge1xuICAgICAgICAgICAgICAgIHZhciB1cGRhdGluZyA9IHVwZGF0ZVdpZGdldChsZWZ0Vk5vZGUsIHdpZGdldCk7XG4gICAgICAgICAgICAgICAgdmFyIG5ld05vZGU7XG5cbiAgICAgICAgICAgICAgICBpZiAodXBkYXRpbmcpIHtcbiAgICAgICAgICAgICAgICAgICAgbmV3Tm9kZSA9IHdpZGdldC51cGRhdGUobGVmdFZOb2RlLCBkb21Ob2RlKSB8fCBkb21Ob2RlO1xuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIG5ld05vZGUgPSByZW5kZXJPcHRpb25zLnJlbmRlcih3aWRnZXQsIHJlbmRlck9wdGlvbnMpO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHZhciBwYXJlbnROb2RlID0gZG9tTm9kZS5wYXJlbnROb2RlO1xuXG4gICAgICAgICAgICAgICAgaWYgKHBhcmVudE5vZGUgJiYgbmV3Tm9kZSAhPT0gZG9tTm9kZSkge1xuICAgICAgICAgICAgICAgICAgICBwYXJlbnROb2RlLnJlcGxhY2VDaGlsZChuZXdOb2RlLCBkb21Ob2RlKTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICBpZiAoIXVwZGF0aW5nKSB7XG4gICAgICAgICAgICAgICAgICAgIGRlc3Ryb3lXaWRnZXQoZG9tTm9kZSwgbGVmdFZOb2RlKTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICByZXR1cm4gbmV3Tm9kZTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZnVuY3Rpb24gdk5vZGVQYXRjaChkb21Ob2RlLCBsZWZ0Vk5vZGUsIHZOb2RlLCByZW5kZXJPcHRpb25zKSB7XG4gICAgICAgICAgICAgICAgdmFyIHBhcmVudE5vZGUgPSBkb21Ob2RlLnBhcmVudE5vZGU7XG4gICAgICAgICAgICAgICAgdmFyIG5ld05vZGUgPSByZW5kZXJPcHRpb25zLnJlbmRlcih2Tm9kZSwgcmVuZGVyT3B0aW9ucyk7XG5cbiAgICAgICAgICAgICAgICBpZiAocGFyZW50Tm9kZSAmJiBuZXdOb2RlICE9PSBkb21Ob2RlKSB7XG4gICAgICAgICAgICAgICAgICAgIHBhcmVudE5vZGUucmVwbGFjZUNoaWxkKG5ld05vZGUsIGRvbU5vZGUpO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHJldHVybiBuZXdOb2RlO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBmdW5jdGlvbiBkZXN0cm95V2lkZ2V0KGRvbU5vZGUsIHcpIHtcbiAgICAgICAgICAgICAgICBpZiAodHlwZW9mIHcuZGVzdHJveSA9PT0gXCJmdW5jdGlvblwiICYmIGlzV2lkZ2V0KHcpKSB7XG4gICAgICAgICAgICAgICAgICAgIHcuZGVzdHJveShkb21Ob2RlKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIHJlb3JkZXJDaGlsZHJlbihkb21Ob2RlLCBtb3Zlcykge1xuICAgICAgICAgICAgICAgIHZhciBjaGlsZE5vZGVzID0gZG9tTm9kZS5jaGlsZE5vZGVzO1xuICAgICAgICAgICAgICAgIHZhciBrZXlNYXAgPSB7fTtcbiAgICAgICAgICAgICAgICB2YXIgbm9kZTtcbiAgICAgICAgICAgICAgICB2YXIgcmVtb3ZlO1xuICAgICAgICAgICAgICAgIHZhciBpbnNlcnQ7XG5cbiAgICAgICAgICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IG1vdmVzLnJlbW92ZXMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgICAgICAgICAgcmVtb3ZlID0gbW92ZXMucmVtb3Zlc1tpXTtcbiAgICAgICAgICAgICAgICAgICAgbm9kZSA9IGNoaWxkTm9kZXNbcmVtb3ZlLmZyb21dO1xuICAgICAgICAgICAgICAgICAgICBpZiAocmVtb3ZlLmtleSkge1xuICAgICAgICAgICAgICAgICAgICAgICAga2V5TWFwW3JlbW92ZS5rZXldID0gbm9kZTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICBkb21Ob2RlLnJlbW92ZUNoaWxkKG5vZGUpO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHZhciBsZW5ndGggPSBjaGlsZE5vZGVzLmxlbmd0aDtcbiAgICAgICAgICAgICAgICBmb3IgKHZhciBqID0gMDsgaiA8IG1vdmVzLmluc2VydHMubGVuZ3RoOyBqKyspIHtcbiAgICAgICAgICAgICAgICAgICAgaW5zZXJ0ID0gbW92ZXMuaW5zZXJ0c1tqXTtcbiAgICAgICAgICAgICAgICAgICAgbm9kZSA9IGtleU1hcFtpbnNlcnQua2V5XTtcbiAgICAgICAgICAgICAgICAgICAgLy8gdGhpcyBpcyB0aGUgd2VpcmRlc3QgYnVnIGkndmUgZXZlciBzZWVuIGluIHdlYmtpdFxuICAgICAgICAgICAgICAgICAgICBkb21Ob2RlLmluc2VydEJlZm9yZShub2RlLCBpbnNlcnQudG8gPj0gbGVuZ3RoKysgPyBudWxsIDogY2hpbGROb2Rlc1tpbnNlcnQudG9dKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIHJlcGxhY2VSb290KG9sZFJvb3QsIG5ld1Jvb3QpIHtcbiAgICAgICAgICAgICAgICBpZiAob2xkUm9vdCAmJiBuZXdSb290ICYmIG9sZFJvb3QgIT09IG5ld1Jvb3QgJiYgb2xkUm9vdC5wYXJlbnROb2RlKSB7XG4gICAgICAgICAgICAgICAgICAgIG9sZFJvb3QucGFyZW50Tm9kZS5yZXBsYWNlQ2hpbGQobmV3Um9vdCwgb2xkUm9vdCk7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgcmV0dXJuIG5ld1Jvb3Q7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0sIHsgXCIuLi92bm9kZS9pcy13aWRnZXQuanNcIjogMjksIFwiLi4vdm5vZGUvdnBhdGNoLmpzXCI6IDMyLCBcIi4vYXBwbHktcHJvcGVydGllc1wiOiAxNCwgXCIuL3VwZGF0ZS13aWRnZXRcIjogMTkgfV0sIDE4OiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge1xuICAgICAgICAgICAgdmFyIGRvY3VtZW50ID0gcmVxdWlyZShcImdsb2JhbC9kb2N1bWVudFwiKTtcbiAgICAgICAgICAgIHZhciBpc0FycmF5ID0gcmVxdWlyZShcIngtaXMtYXJyYXlcIik7XG5cbiAgICAgICAgICAgIHZhciByZW5kZXIgPSByZXF1aXJlKFwiLi9jcmVhdGUtZWxlbWVudFwiKTtcbiAgICAgICAgICAgIHZhciBkb21JbmRleCA9IHJlcXVpcmUoXCIuL2RvbS1pbmRleFwiKTtcbiAgICAgICAgICAgIHZhciBwYXRjaE9wID0gcmVxdWlyZShcIi4vcGF0Y2gtb3BcIik7XG4gICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IHBhdGNoO1xuXG4gICAgICAgICAgICBmdW5jdGlvbiBwYXRjaChyb290Tm9kZSwgcGF0Y2hlcywgcmVuZGVyT3B0aW9ucykge1xuICAgICAgICAgICAgICAgIHJlbmRlck9wdGlvbnMgPSByZW5kZXJPcHRpb25zIHx8IHt9O1xuICAgICAgICAgICAgICAgIHJlbmRlck9wdGlvbnMucGF0Y2ggPSByZW5kZXJPcHRpb25zLnBhdGNoICYmIHJlbmRlck9wdGlvbnMucGF0Y2ggIT09IHBhdGNoID8gcmVuZGVyT3B0aW9ucy5wYXRjaCA6IHBhdGNoUmVjdXJzaXZlO1xuICAgICAgICAgICAgICAgIHJlbmRlck9wdGlvbnMucmVuZGVyID0gcmVuZGVyT3B0aW9ucy5yZW5kZXIgfHwgcmVuZGVyO1xuXG4gICAgICAgICAgICAgICAgcmV0dXJuIHJlbmRlck9wdGlvbnMucGF0Y2gocm9vdE5vZGUsIHBhdGNoZXMsIHJlbmRlck9wdGlvbnMpO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBmdW5jdGlvbiBwYXRjaFJlY3Vyc2l2ZShyb290Tm9kZSwgcGF0Y2hlcywgcmVuZGVyT3B0aW9ucykge1xuICAgICAgICAgICAgICAgIHZhciBpbmRpY2VzID0gcGF0Y2hJbmRpY2VzKHBhdGNoZXMpO1xuXG4gICAgICAgICAgICAgICAgaWYgKGluZGljZXMubGVuZ3RoID09PSAwKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiByb290Tm9kZTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICB2YXIgaW5kZXggPSBkb21JbmRleChyb290Tm9kZSwgcGF0Y2hlcy5hLCBpbmRpY2VzKTtcbiAgICAgICAgICAgICAgICB2YXIgb3duZXJEb2N1bWVudCA9IHJvb3ROb2RlLm93bmVyRG9jdW1lbnQ7XG5cbiAgICAgICAgICAgICAgICBpZiAoIXJlbmRlck9wdGlvbnMuZG9jdW1lbnQgJiYgb3duZXJEb2N1bWVudCAhPT0gZG9jdW1lbnQpIHtcbiAgICAgICAgICAgICAgICAgICAgcmVuZGVyT3B0aW9ucy5kb2N1bWVudCA9IG93bmVyRG9jdW1lbnQ7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCBpbmRpY2VzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciBub2RlSW5kZXggPSBpbmRpY2VzW2ldO1xuICAgICAgICAgICAgICAgICAgICByb290Tm9kZSA9IGFwcGx5UGF0Y2gocm9vdE5vZGUsIGluZGV4W25vZGVJbmRleF0sIHBhdGNoZXNbbm9kZUluZGV4XSwgcmVuZGVyT3B0aW9ucyk7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgcmV0dXJuIHJvb3ROb2RlO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBmdW5jdGlvbiBhcHBseVBhdGNoKHJvb3ROb2RlLCBkb21Ob2RlLCBwYXRjaExpc3QsIHJlbmRlck9wdGlvbnMpIHtcbiAgICAgICAgICAgICAgICBpZiAoIWRvbU5vZGUpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHJvb3ROb2RlO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHZhciBuZXdOb2RlO1xuXG4gICAgICAgICAgICAgICAgaWYgKGlzQXJyYXkocGF0Y2hMaXN0KSkge1xuICAgICAgICAgICAgICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IHBhdGNoTGlzdC5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgICAgICAgICAgICAgbmV3Tm9kZSA9IHBhdGNoT3AocGF0Y2hMaXN0W2ldLCBkb21Ob2RlLCByZW5kZXJPcHRpb25zKTtcblxuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGRvbU5vZGUgPT09IHJvb3ROb2RlKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcm9vdE5vZGUgPSBuZXdOb2RlO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgbmV3Tm9kZSA9IHBhdGNoT3AocGF0Y2hMaXN0LCBkb21Ob2RlLCByZW5kZXJPcHRpb25zKTtcblxuICAgICAgICAgICAgICAgICAgICBpZiAoZG9tTm9kZSA9PT0gcm9vdE5vZGUpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJvb3ROb2RlID0gbmV3Tm9kZTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHJldHVybiByb290Tm9kZTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZnVuY3Rpb24gcGF0Y2hJbmRpY2VzKHBhdGNoZXMpIHtcbiAgICAgICAgICAgICAgICB2YXIgaW5kaWNlcyA9IFtdO1xuXG4gICAgICAgICAgICAgICAgZm9yICh2YXIga2V5IGluIHBhdGNoZXMpIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKGtleSAhPT0gXCJhXCIpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGluZGljZXMucHVzaChOdW1iZXIoa2V5KSk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICByZXR1cm4gaW5kaWNlcztcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSwgeyBcIi4vY3JlYXRlLWVsZW1lbnRcIjogMTUsIFwiLi9kb20taW5kZXhcIjogMTYsIFwiLi9wYXRjaC1vcFwiOiAxNywgXCJnbG9iYWwvZG9jdW1lbnRcIjogMTAsIFwieC1pcy1hcnJheVwiOiAxMiB9XSwgMTk6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICB2YXIgaXNXaWRnZXQgPSByZXF1aXJlKFwiLi4vdm5vZGUvaXMtd2lkZ2V0LmpzXCIpO1xuXG4gICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IHVwZGF0ZVdpZGdldDtcblxuICAgICAgICAgICAgZnVuY3Rpb24gdXBkYXRlV2lkZ2V0KGEsIGIpIHtcbiAgICAgICAgICAgICAgICBpZiAoaXNXaWRnZXQoYSkgJiYgaXNXaWRnZXQoYikpIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKFwibmFtZVwiIGluIGEgJiYgXCJuYW1lXCIgaW4gYikge1xuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGEuaWQgPT09IGIuaWQ7XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gYS5pbml0ID09PSBiLmluaXQ7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0sIHsgXCIuLi92bm9kZS9pcy13aWRnZXQuanNcIjogMjkgfV0sIDIwOiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge1xuICAgICAgICAgICAgXCJ1c2Ugc3RyaWN0XCI7XG5cbiAgICAgICAgICAgIHZhciBFdlN0b3JlID0gcmVxdWlyZShcImV2LXN0b3JlXCIpO1xuXG4gICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IEV2SG9vaztcblxuICAgICAgICAgICAgZnVuY3Rpb24gRXZIb29rKHZhbHVlKSB7XG4gICAgICAgICAgICAgICAgaWYgKCEodGhpcyBpbnN0YW5jZW9mIEV2SG9vaykpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIG5ldyBFdkhvb2sodmFsdWUpO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHRoaXMudmFsdWUgPSB2YWx1ZTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgRXZIb29rLnByb3RvdHlwZS5ob29rID0gZnVuY3Rpb24gKG5vZGUsIHByb3BlcnR5TmFtZSkge1xuICAgICAgICAgICAgICAgIHZhciBlcyA9IEV2U3RvcmUobm9kZSk7XG4gICAgICAgICAgICAgICAgdmFyIHByb3BOYW1lID0gcHJvcGVydHlOYW1lLnN1YnN0cigzKTtcblxuICAgICAgICAgICAgICAgIGVzW3Byb3BOYW1lXSA9IHRoaXMudmFsdWU7XG4gICAgICAgICAgICB9O1xuXG4gICAgICAgICAgICBFdkhvb2sucHJvdG90eXBlLnVuaG9vayA9IGZ1bmN0aW9uIChub2RlLCBwcm9wZXJ0eU5hbWUpIHtcbiAgICAgICAgICAgICAgICB2YXIgZXMgPSBFdlN0b3JlKG5vZGUpO1xuICAgICAgICAgICAgICAgIHZhciBwcm9wTmFtZSA9IHByb3BlcnR5TmFtZS5zdWJzdHIoMyk7XG5cbiAgICAgICAgICAgICAgICBlc1twcm9wTmFtZV0gPSB1bmRlZmluZWQ7XG4gICAgICAgICAgICB9O1xuICAgICAgICB9LCB7IFwiZXYtc3RvcmVcIjogNyB9XSwgMjE6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICBcInVzZSBzdHJpY3RcIjtcblxuICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBTb2Z0U2V0SG9vaztcblxuICAgICAgICAgICAgZnVuY3Rpb24gU29mdFNldEhvb2sodmFsdWUpIHtcbiAgICAgICAgICAgICAgICBpZiAoISh0aGlzIGluc3RhbmNlb2YgU29mdFNldEhvb2spKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBuZXcgU29mdFNldEhvb2sodmFsdWUpO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHRoaXMudmFsdWUgPSB2YWx1ZTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgU29mdFNldEhvb2sucHJvdG90eXBlLmhvb2sgPSBmdW5jdGlvbiAobm9kZSwgcHJvcGVydHlOYW1lKSB7XG4gICAgICAgICAgICAgICAgaWYgKG5vZGVbcHJvcGVydHlOYW1lXSAhPT0gdGhpcy52YWx1ZSkge1xuICAgICAgICAgICAgICAgICAgICBub2RlW3Byb3BlcnR5TmFtZV0gPSB0aGlzLnZhbHVlO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH07XG4gICAgICAgIH0sIHt9XSwgMjI6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICBcInVzZSBzdHJpY3RcIjtcblxuICAgICAgICAgICAgdmFyIGlzQXJyYXkgPSByZXF1aXJlKFwieC1pcy1hcnJheVwiKTtcblxuICAgICAgICAgICAgdmFyIFZOb2RlID0gcmVxdWlyZShcIi4uL3Zub2RlL3Zub2RlLmpzXCIpO1xuICAgICAgICAgICAgdmFyIFZUZXh0ID0gcmVxdWlyZShcIi4uL3Zub2RlL3Z0ZXh0LmpzXCIpO1xuICAgICAgICAgICAgdmFyIGlzVk5vZGUgPSByZXF1aXJlKFwiLi4vdm5vZGUvaXMtdm5vZGVcIik7XG4gICAgICAgICAgICB2YXIgaXNWVGV4dCA9IHJlcXVpcmUoXCIuLi92bm9kZS9pcy12dGV4dFwiKTtcbiAgICAgICAgICAgIHZhciBpc1dpZGdldCA9IHJlcXVpcmUoXCIuLi92bm9kZS9pcy13aWRnZXRcIik7XG4gICAgICAgICAgICB2YXIgaXNIb29rID0gcmVxdWlyZShcIi4uL3Zub2RlL2lzLXZob29rXCIpO1xuICAgICAgICAgICAgdmFyIGlzVlRodW5rID0gcmVxdWlyZShcIi4uL3Zub2RlL2lzLXRodW5rXCIpO1xuXG4gICAgICAgICAgICB2YXIgcGFyc2VUYWcgPSByZXF1aXJlKFwiLi9wYXJzZS10YWcuanNcIik7XG4gICAgICAgICAgICB2YXIgc29mdFNldEhvb2sgPSByZXF1aXJlKFwiLi9ob29rcy9zb2Z0LXNldC1ob29rLmpzXCIpO1xuICAgICAgICAgICAgdmFyIGV2SG9vayA9IHJlcXVpcmUoXCIuL2hvb2tzL2V2LWhvb2suanNcIik7XG5cbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gaDtcblxuICAgICAgICAgICAgZnVuY3Rpb24gaCh0YWdOYW1lLCBwcm9wZXJ0aWVzLCBjaGlsZHJlbikge1xuICAgICAgICAgICAgICAgIHZhciBjaGlsZE5vZGVzID0gW107XG4gICAgICAgICAgICAgICAgdmFyIHRhZywgcHJvcHMsIGtleSwgbmFtZXNwYWNlO1xuXG4gICAgICAgICAgICAgICAgaWYgKCFjaGlsZHJlbiAmJiBpc0NoaWxkcmVuKHByb3BlcnRpZXMpKSB7XG4gICAgICAgICAgICAgICAgICAgIGNoaWxkcmVuID0gcHJvcGVydGllcztcbiAgICAgICAgICAgICAgICAgICAgcHJvcHMgPSB7fTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICBwcm9wcyA9IHByb3BzIHx8IHByb3BlcnRpZXMgfHwge307XG4gICAgICAgICAgICAgICAgdGFnID0gcGFyc2VUYWcodGFnTmFtZSwgcHJvcHMpO1xuXG4gICAgICAgICAgICAgICAgLy8gc3VwcG9ydCBrZXlzXG4gICAgICAgICAgICAgICAgaWYgKHByb3BzLmhhc093blByb3BlcnR5KFwia2V5XCIpKSB7XG4gICAgICAgICAgICAgICAgICAgIGtleSA9IHByb3BzLmtleTtcbiAgICAgICAgICAgICAgICAgICAgcHJvcHMua2V5ID0gdW5kZWZpbmVkO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIC8vIHN1cHBvcnQgbmFtZXNwYWNlXG4gICAgICAgICAgICAgICAgaWYgKHByb3BzLmhhc093blByb3BlcnR5KFwibmFtZXNwYWNlXCIpKSB7XG4gICAgICAgICAgICAgICAgICAgIG5hbWVzcGFjZSA9IHByb3BzLm5hbWVzcGFjZTtcbiAgICAgICAgICAgICAgICAgICAgcHJvcHMubmFtZXNwYWNlID0gdW5kZWZpbmVkO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIC8vIGZpeCBjdXJzb3IgYnVnXG4gICAgICAgICAgICAgICAgaWYgKHRhZyA9PT0gXCJJTlBVVFwiICYmICFuYW1lc3BhY2UgJiYgcHJvcHMuaGFzT3duUHJvcGVydHkoXCJ2YWx1ZVwiKSAmJiBwcm9wcy52YWx1ZSAhPT0gdW5kZWZpbmVkICYmICFpc0hvb2socHJvcHMudmFsdWUpKSB7XG4gICAgICAgICAgICAgICAgICAgIHByb3BzLnZhbHVlID0gc29mdFNldEhvb2socHJvcHMudmFsdWUpO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHRyYW5zZm9ybVByb3BlcnRpZXMocHJvcHMpO1xuXG4gICAgICAgICAgICAgICAgaWYgKGNoaWxkcmVuICE9PSB1bmRlZmluZWQgJiYgY2hpbGRyZW4gIT09IG51bGwpIHtcbiAgICAgICAgICAgICAgICAgICAgYWRkQ2hpbGQoY2hpbGRyZW4sIGNoaWxkTm9kZXMsIHRhZywgcHJvcHMpO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHJldHVybiBuZXcgVk5vZGUodGFnLCBwcm9wcywgY2hpbGROb2Rlcywga2V5LCBuYW1lc3BhY2UpO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBmdW5jdGlvbiBhZGRDaGlsZChjLCBjaGlsZE5vZGVzLCB0YWcsIHByb3BzKSB7XG4gICAgICAgICAgICAgICAgaWYgKHR5cGVvZiBjID09PSBcInN0cmluZ1wiKSB7XG4gICAgICAgICAgICAgICAgICAgIGNoaWxkTm9kZXMucHVzaChuZXcgVlRleHQoYykpO1xuICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAodHlwZW9mIGMgPT09IFwibnVtYmVyXCIpIHtcbiAgICAgICAgICAgICAgICAgICAgY2hpbGROb2Rlcy5wdXNoKG5ldyBWVGV4dChTdHJpbmcoYykpKTtcbiAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKGlzQ2hpbGQoYykpIHtcbiAgICAgICAgICAgICAgICAgICAgY2hpbGROb2Rlcy5wdXNoKGMpO1xuICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoaXNBcnJheShjKSkge1xuICAgICAgICAgICAgICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IGMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGFkZENoaWxkKGNbaV0sIGNoaWxkTm9kZXMsIHRhZywgcHJvcHMpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfSBlbHNlIGlmIChjID09PSBudWxsIHx8IGMgPT09IHVuZGVmaW5lZCkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgdGhyb3cgVW5leHBlY3RlZFZpcnR1YWxFbGVtZW50KHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGZvcmVpZ25PYmplY3Q6IGMsXG4gICAgICAgICAgICAgICAgICAgICAgICBwYXJlbnRWbm9kZToge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRhZ05hbWU6IHRhZyxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBwcm9wZXJ0aWVzOiBwcm9wc1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIHRyYW5zZm9ybVByb3BlcnRpZXMocHJvcHMpIHtcbiAgICAgICAgICAgICAgICBmb3IgKHZhciBwcm9wTmFtZSBpbiBwcm9wcykge1xuICAgICAgICAgICAgICAgICAgICBpZiAocHJvcHMuaGFzT3duUHJvcGVydHkocHJvcE5hbWUpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICB2YXIgdmFsdWUgPSBwcm9wc1twcm9wTmFtZV07XG5cbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChpc0hvb2sodmFsdWUpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgY29udGludWU7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChwcm9wTmFtZS5zdWJzdHIoMCwgMykgPT09IFwiZXYtXCIpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBhZGQgZXYtZm9vIHN1cHBvcnRcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBwcm9wc1twcm9wTmFtZV0gPSBldkhvb2sodmFsdWUpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBmdW5jdGlvbiBpc0NoaWxkKHgpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gaXNWTm9kZSh4KSB8fCBpc1ZUZXh0KHgpIHx8IGlzV2lkZ2V0KHgpIHx8IGlzVlRodW5rKHgpO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBmdW5jdGlvbiBpc0NoaWxkcmVuKHgpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gdHlwZW9mIHggPT09IFwic3RyaW5nXCIgfHwgaXNBcnJheSh4KSB8fCBpc0NoaWxkKHgpO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBmdW5jdGlvbiBVbmV4cGVjdGVkVmlydHVhbEVsZW1lbnQoZGF0YSkge1xuICAgICAgICAgICAgICAgIHZhciBlcnIgPSBuZXcgRXJyb3IoKTtcblxuICAgICAgICAgICAgICAgIGVyci50eXBlID0gXCJ2aXJ0dWFsLWh5cGVyc2NyaXB0LnVuZXhwZWN0ZWQudmlydHVhbC1lbGVtZW50XCI7XG4gICAgICAgICAgICAgICAgZXJyLm1lc3NhZ2UgPSBcIlVuZXhwZWN0ZWQgdmlydHVhbCBjaGlsZCBwYXNzZWQgdG8gaCgpLlxcblwiICsgXCJFeHBlY3RlZCBhIFZOb2RlIC8gVnRodW5rIC8gVldpZGdldCAvIHN0cmluZyBidXQ6XFxuXCIgKyBcImdvdDpcXG5cIiArIGVycm9yU3RyaW5nKGRhdGEuZm9yZWlnbk9iamVjdCkgKyBcIi5cXG5cIiArIFwiVGhlIHBhcmVudCB2bm9kZSBpczpcXG5cIiArIGVycm9yU3RyaW5nKGRhdGEucGFyZW50Vm5vZGUpO1xuICAgICAgICAgICAgICAgIFwiXFxuXCIgKyBcIlN1Z2dlc3RlZCBmaXg6IGNoYW5nZSB5b3VyIGBoKC4uLiwgWyAuLi4gXSlgIGNhbGxzaXRlLlwiO1xuICAgICAgICAgICAgICAgIGVyci5mb3JlaWduT2JqZWN0ID0gZGF0YS5mb3JlaWduT2JqZWN0O1xuICAgICAgICAgICAgICAgIGVyci5wYXJlbnRWbm9kZSA9IGRhdGEucGFyZW50Vm5vZGU7XG5cbiAgICAgICAgICAgICAgICByZXR1cm4gZXJyO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBmdW5jdGlvbiBlcnJvclN0cmluZyhvYmopIHtcbiAgICAgICAgICAgICAgICB0cnkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gSlNPTi5zdHJpbmdpZnkob2JqLCBudWxsLCBcIiAgICBcIik7XG4gICAgICAgICAgICAgICAgfSBjYXRjaCAoZSkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gU3RyaW5nKG9iaik7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9LCB7IFwiLi4vdm5vZGUvaXMtdGh1bmtcIjogMjUsIFwiLi4vdm5vZGUvaXMtdmhvb2tcIjogMjYsIFwiLi4vdm5vZGUvaXMtdm5vZGVcIjogMjcsIFwiLi4vdm5vZGUvaXMtdnRleHRcIjogMjgsIFwiLi4vdm5vZGUvaXMtd2lkZ2V0XCI6IDI5LCBcIi4uL3Zub2RlL3Zub2RlLmpzXCI6IDMxLCBcIi4uL3Zub2RlL3Z0ZXh0LmpzXCI6IDMzLCBcIi4vaG9va3MvZXYtaG9vay5qc1wiOiAyMCwgXCIuL2hvb2tzL3NvZnQtc2V0LWhvb2suanNcIjogMjEsIFwiLi9wYXJzZS10YWcuanNcIjogMjMsIFwieC1pcy1hcnJheVwiOiAxMiB9XSwgMjM6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICBcInVzZSBzdHJpY3RcIjtcblxuICAgICAgICAgICAgdmFyIHNwbGl0ID0gcmVxdWlyZShcImJyb3dzZXItc3BsaXRcIik7XG5cbiAgICAgICAgICAgIHZhciBjbGFzc0lkU3BsaXQgPSAvKFtcXC4jXT9bYS16QS1aMC05XFx1MDA3Ri1cXHVGRkZGXzotXSspLztcbiAgICAgICAgICAgIHZhciBub3RDbGFzc0lkID0gL15cXC58Iy87XG5cbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gcGFyc2VUYWc7XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIHBhcnNlVGFnKHRhZywgcHJvcHMpIHtcbiAgICAgICAgICAgICAgICBpZiAoIXRhZykge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gXCJESVZcIjtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICB2YXIgbm9JZCA9ICFwcm9wcy5oYXNPd25Qcm9wZXJ0eShcImlkXCIpO1xuXG4gICAgICAgICAgICAgICAgdmFyIHRhZ1BhcnRzID0gc3BsaXQodGFnLCBjbGFzc0lkU3BsaXQpO1xuICAgICAgICAgICAgICAgIHZhciB0YWdOYW1lID0gbnVsbDtcblxuICAgICAgICAgICAgICAgIGlmIChub3RDbGFzc0lkLnRlc3QodGFnUGFydHNbMV0pKSB7XG4gICAgICAgICAgICAgICAgICAgIHRhZ05hbWUgPSBcIkRJVlwiO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHZhciBjbGFzc2VzLCBwYXJ0LCB0eXBlLCBpO1xuXG4gICAgICAgICAgICAgICAgZm9yIChpID0gMDsgaSA8IHRhZ1BhcnRzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICAgICAgICAgIHBhcnQgPSB0YWdQYXJ0c1tpXTtcblxuICAgICAgICAgICAgICAgICAgICBpZiAoIXBhcnQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnRpbnVlO1xuICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgdHlwZSA9IHBhcnQuY2hhckF0KDApO1xuXG4gICAgICAgICAgICAgICAgICAgIGlmICghdGFnTmFtZSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgdGFnTmFtZSA9IHBhcnQ7XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAodHlwZSA9PT0gXCIuXCIpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGNsYXNzZXMgPSBjbGFzc2VzIHx8IFtdO1xuICAgICAgICAgICAgICAgICAgICAgICAgY2xhc3Nlcy5wdXNoKHBhcnQuc3Vic3RyaW5nKDEsIHBhcnQubGVuZ3RoKSk7XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAodHlwZSA9PT0gXCIjXCIgJiYgbm9JZCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgcHJvcHMuaWQgPSBwYXJ0LnN1YnN0cmluZygxLCBwYXJ0Lmxlbmd0aCk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICBpZiAoY2xhc3Nlcykge1xuICAgICAgICAgICAgICAgICAgICBpZiAocHJvcHMuY2xhc3NOYW1lKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBjbGFzc2VzLnB1c2gocHJvcHMuY2xhc3NOYW1lKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgIHByb3BzLmNsYXNzTmFtZSA9IGNsYXNzZXMuam9pbihcIiBcIik7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgcmV0dXJuIHByb3BzLm5hbWVzcGFjZSA/IHRhZ05hbWUgOiB0YWdOYW1lLnRvVXBwZXJDYXNlKCk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0sIHsgXCJicm93c2VyLXNwbGl0XCI6IDUgfV0sIDI0OiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge1xuICAgICAgICAgICAgdmFyIGlzVk5vZGUgPSByZXF1aXJlKFwiLi9pcy12bm9kZVwiKTtcbiAgICAgICAgICAgIHZhciBpc1ZUZXh0ID0gcmVxdWlyZShcIi4vaXMtdnRleHRcIik7XG4gICAgICAgICAgICB2YXIgaXNXaWRnZXQgPSByZXF1aXJlKFwiLi9pcy13aWRnZXRcIik7XG4gICAgICAgICAgICB2YXIgaXNUaHVuayA9IHJlcXVpcmUoXCIuL2lzLXRodW5rXCIpO1xuXG4gICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IGhhbmRsZVRodW5rO1xuXG4gICAgICAgICAgICBmdW5jdGlvbiBoYW5kbGVUaHVuayhhLCBiKSB7XG4gICAgICAgICAgICAgICAgdmFyIHJlbmRlcmVkQSA9IGE7XG4gICAgICAgICAgICAgICAgdmFyIHJlbmRlcmVkQiA9IGI7XG5cbiAgICAgICAgICAgICAgICBpZiAoaXNUaHVuayhiKSkge1xuICAgICAgICAgICAgICAgICAgICByZW5kZXJlZEIgPSByZW5kZXJUaHVuayhiLCBhKTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICBpZiAoaXNUaHVuayhhKSkge1xuICAgICAgICAgICAgICAgICAgICByZW5kZXJlZEEgPSByZW5kZXJUaHVuayhhLCBudWxsKTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgICAgICAgICBhOiByZW5kZXJlZEEsXG4gICAgICAgICAgICAgICAgICAgIGI6IHJlbmRlcmVkQlxuICAgICAgICAgICAgICAgIH07XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIHJlbmRlclRodW5rKHRodW5rLCBwcmV2aW91cykge1xuICAgICAgICAgICAgICAgIHZhciByZW5kZXJlZFRodW5rID0gdGh1bmsudm5vZGU7XG5cbiAgICAgICAgICAgICAgICBpZiAoIXJlbmRlcmVkVGh1bmspIHtcbiAgICAgICAgICAgICAgICAgICAgcmVuZGVyZWRUaHVuayA9IHRodW5rLnZub2RlID0gdGh1bmsucmVuZGVyKHByZXZpb3VzKTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICBpZiAoIShpc1ZOb2RlKHJlbmRlcmVkVGh1bmspIHx8IGlzVlRleHQocmVuZGVyZWRUaHVuaykgfHwgaXNXaWRnZXQocmVuZGVyZWRUaHVuaykpKSB7XG4gICAgICAgICAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcihcInRodW5rIGRpZCBub3QgcmV0dXJuIGEgdmFsaWQgbm9kZVwiKTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICByZXR1cm4gcmVuZGVyZWRUaHVuaztcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSwgeyBcIi4vaXMtdGh1bmtcIjogMjUsIFwiLi9pcy12bm9kZVwiOiAyNywgXCIuL2lzLXZ0ZXh0XCI6IDI4LCBcIi4vaXMtd2lkZ2V0XCI6IDI5IH1dLCAyNTogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHtcbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gaXNUaHVuaztcblxuICAgICAgICAgICAgZnVuY3Rpb24gaXNUaHVuayh0KSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHQgJiYgdC50eXBlID09PSBcIlRodW5rXCI7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0sIHt9XSwgMjY6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IGlzSG9vaztcblxuICAgICAgICAgICAgZnVuY3Rpb24gaXNIb29rKGhvb2spIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gaG9vayAmJiAodHlwZW9mIGhvb2suaG9vayA9PT0gXCJmdW5jdGlvblwiICYmICFob29rLmhhc093blByb3BlcnR5KFwiaG9va1wiKSB8fCB0eXBlb2YgaG9vay51bmhvb2sgPT09IFwiZnVuY3Rpb25cIiAmJiAhaG9vay5oYXNPd25Qcm9wZXJ0eShcInVuaG9va1wiKSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0sIHt9XSwgMjc6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICB2YXIgdmVyc2lvbiA9IHJlcXVpcmUoXCIuL3ZlcnNpb25cIik7XG5cbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gaXNWaXJ0dWFsTm9kZTtcblxuICAgICAgICAgICAgZnVuY3Rpb24gaXNWaXJ0dWFsTm9kZSh4KSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHggJiYgeC50eXBlID09PSBcIlZpcnR1YWxOb2RlXCIgJiYgeC52ZXJzaW9uID09PSB2ZXJzaW9uO1xuICAgICAgICAgICAgfVxuICAgICAgICB9LCB7IFwiLi92ZXJzaW9uXCI6IDMwIH1dLCAyODogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHtcbiAgICAgICAgICAgIHZhciB2ZXJzaW9uID0gcmVxdWlyZShcIi4vdmVyc2lvblwiKTtcblxuICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBpc1ZpcnR1YWxUZXh0O1xuXG4gICAgICAgICAgICBmdW5jdGlvbiBpc1ZpcnR1YWxUZXh0KHgpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4geCAmJiB4LnR5cGUgPT09IFwiVmlydHVhbFRleHRcIiAmJiB4LnZlcnNpb24gPT09IHZlcnNpb247XG4gICAgICAgICAgICB9XG4gICAgICAgIH0sIHsgXCIuL3ZlcnNpb25cIjogMzAgfV0sIDI5OiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge1xuICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBpc1dpZGdldDtcblxuICAgICAgICAgICAgZnVuY3Rpb24gaXNXaWRnZXQodykge1xuICAgICAgICAgICAgICAgIHJldHVybiB3ICYmIHcudHlwZSA9PT0gXCJXaWRnZXRcIjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSwge31dLCAzMDogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHtcbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gXCIyXCI7XG4gICAgICAgIH0sIHt9XSwgMzE6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICB2YXIgdmVyc2lvbiA9IHJlcXVpcmUoXCIuL3ZlcnNpb25cIik7XG4gICAgICAgICAgICB2YXIgaXNWTm9kZSA9IHJlcXVpcmUoXCIuL2lzLXZub2RlXCIpO1xuICAgICAgICAgICAgdmFyIGlzV2lkZ2V0ID0gcmVxdWlyZShcIi4vaXMtd2lkZ2V0XCIpO1xuICAgICAgICAgICAgdmFyIGlzVGh1bmsgPSByZXF1aXJlKFwiLi9pcy10aHVua1wiKTtcbiAgICAgICAgICAgIHZhciBpc1ZIb29rID0gcmVxdWlyZShcIi4vaXMtdmhvb2tcIik7XG5cbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gVmlydHVhbE5vZGU7XG5cbiAgICAgICAgICAgIHZhciBub1Byb3BlcnRpZXMgPSB7fTtcbiAgICAgICAgICAgIHZhciBub0NoaWxkcmVuID0gW107XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIFZpcnR1YWxOb2RlKHRhZ05hbWUsIHByb3BlcnRpZXMsIGNoaWxkcmVuLCBrZXksIG5hbWVzcGFjZSkge1xuICAgICAgICAgICAgICAgIHRoaXMudGFnTmFtZSA9IHRhZ05hbWU7XG4gICAgICAgICAgICAgICAgdGhpcy5wcm9wZXJ0aWVzID0gcHJvcGVydGllcyB8fCBub1Byb3BlcnRpZXM7XG4gICAgICAgICAgICAgICAgdGhpcy5jaGlsZHJlbiA9IGNoaWxkcmVuIHx8IG5vQ2hpbGRyZW47XG4gICAgICAgICAgICAgICAgdGhpcy5rZXkgPSBrZXkgIT0gbnVsbCA/IFN0cmluZyhrZXkpIDogdW5kZWZpbmVkO1xuICAgICAgICAgICAgICAgIHRoaXMubmFtZXNwYWNlID0gdHlwZW9mIG5hbWVzcGFjZSA9PT0gXCJzdHJpbmdcIiA/IG5hbWVzcGFjZSA6IG51bGw7XG5cbiAgICAgICAgICAgICAgICB2YXIgY291bnQgPSBjaGlsZHJlbiAmJiBjaGlsZHJlbi5sZW5ndGggfHwgMDtcbiAgICAgICAgICAgICAgICB2YXIgZGVzY2VuZGFudHMgPSAwO1xuICAgICAgICAgICAgICAgIHZhciBoYXNXaWRnZXRzID0gZmFsc2U7XG4gICAgICAgICAgICAgICAgdmFyIGhhc1RodW5rcyA9IGZhbHNlO1xuICAgICAgICAgICAgICAgIHZhciBkZXNjZW5kYW50SG9va3MgPSBmYWxzZTtcbiAgICAgICAgICAgICAgICB2YXIgaG9va3M7XG5cbiAgICAgICAgICAgICAgICBmb3IgKHZhciBwcm9wTmFtZSBpbiBwcm9wZXJ0aWVzKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmIChwcm9wZXJ0aWVzLmhhc093blByb3BlcnR5KHByb3BOYW1lKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgdmFyIHByb3BlcnR5ID0gcHJvcGVydGllc1twcm9wTmFtZV07XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoaXNWSG9vayhwcm9wZXJ0eSkgJiYgcHJvcGVydHkudW5ob29rKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKCFob29rcykge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBob29rcyA9IHt9O1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGhvb2tzW3Byb3BOYW1lXSA9IHByb3BlcnR5O1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCBjb3VudDsgaSsrKSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciBjaGlsZCA9IGNoaWxkcmVuW2ldO1xuICAgICAgICAgICAgICAgICAgICBpZiAoaXNWTm9kZShjaGlsZCkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGRlc2NlbmRhbnRzICs9IGNoaWxkLmNvdW50IHx8IDA7XG5cbiAgICAgICAgICAgICAgICAgICAgICAgIGlmICghaGFzV2lkZ2V0cyAmJiBjaGlsZC5oYXNXaWRnZXRzKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaGFzV2lkZ2V0cyA9IHRydWU7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgICAgIGlmICghaGFzVGh1bmtzICYmIGNoaWxkLmhhc1RodW5rcykge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGhhc1RodW5rcyA9IHRydWU7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgICAgIGlmICghZGVzY2VuZGFudEhvb2tzICYmIChjaGlsZC5ob29rcyB8fCBjaGlsZC5kZXNjZW5kYW50SG9va3MpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgZGVzY2VuZGFudEhvb2tzID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIGlmICghaGFzV2lkZ2V0cyAmJiBpc1dpZGdldChjaGlsZCkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmICh0eXBlb2YgY2hpbGQuZGVzdHJveSA9PT0gXCJmdW5jdGlvblwiKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaGFzV2lkZ2V0cyA9IHRydWU7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoIWhhc1RodW5rcyAmJiBpc1RodW5rKGNoaWxkKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgaGFzVGh1bmtzID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHRoaXMuY291bnQgPSBjb3VudCArIGRlc2NlbmRhbnRzO1xuICAgICAgICAgICAgICAgIHRoaXMuaGFzV2lkZ2V0cyA9IGhhc1dpZGdldHM7XG4gICAgICAgICAgICAgICAgdGhpcy5oYXNUaHVua3MgPSBoYXNUaHVua3M7XG4gICAgICAgICAgICAgICAgdGhpcy5ob29rcyA9IGhvb2tzO1xuICAgICAgICAgICAgICAgIHRoaXMuZGVzY2VuZGFudEhvb2tzID0gZGVzY2VuZGFudEhvb2tzO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBWaXJ0dWFsTm9kZS5wcm90b3R5cGUudmVyc2lvbiA9IHZlcnNpb247XG4gICAgICAgICAgICBWaXJ0dWFsTm9kZS5wcm90b3R5cGUudHlwZSA9IFwiVmlydHVhbE5vZGVcIjtcbiAgICAgICAgfSwgeyBcIi4vaXMtdGh1bmtcIjogMjUsIFwiLi9pcy12aG9va1wiOiAyNiwgXCIuL2lzLXZub2RlXCI6IDI3LCBcIi4vaXMtd2lkZ2V0XCI6IDI5LCBcIi4vdmVyc2lvblwiOiAzMCB9XSwgMzI6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICB2YXIgdmVyc2lvbiA9IHJlcXVpcmUoXCIuL3ZlcnNpb25cIik7XG5cbiAgICAgICAgICAgIFZpcnR1YWxQYXRjaC5OT05FID0gMDtcbiAgICAgICAgICAgIFZpcnR1YWxQYXRjaC5WVEVYVCA9IDE7XG4gICAgICAgICAgICBWaXJ0dWFsUGF0Y2guVk5PREUgPSAyO1xuICAgICAgICAgICAgVmlydHVhbFBhdGNoLldJREdFVCA9IDM7XG4gICAgICAgICAgICBWaXJ0dWFsUGF0Y2guUFJPUFMgPSA0O1xuICAgICAgICAgICAgVmlydHVhbFBhdGNoLk9SREVSID0gNTtcbiAgICAgICAgICAgIFZpcnR1YWxQYXRjaC5JTlNFUlQgPSA2O1xuICAgICAgICAgICAgVmlydHVhbFBhdGNoLlJFTU9WRSA9IDc7XG4gICAgICAgICAgICBWaXJ0dWFsUGF0Y2guVEhVTksgPSA4O1xuXG4gICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IFZpcnR1YWxQYXRjaDtcblxuICAgICAgICAgICAgZnVuY3Rpb24gVmlydHVhbFBhdGNoKHR5cGUsIHZOb2RlLCBwYXRjaCkge1xuICAgICAgICAgICAgICAgIHRoaXMudHlwZSA9IE51bWJlcih0eXBlKTtcbiAgICAgICAgICAgICAgICB0aGlzLnZOb2RlID0gdk5vZGU7XG4gICAgICAgICAgICAgICAgdGhpcy5wYXRjaCA9IHBhdGNoO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBWaXJ0dWFsUGF0Y2gucHJvdG90eXBlLnZlcnNpb24gPSB2ZXJzaW9uO1xuICAgICAgICAgICAgVmlydHVhbFBhdGNoLnByb3RvdHlwZS50eXBlID0gXCJWaXJ0dWFsUGF0Y2hcIjtcbiAgICAgICAgfSwgeyBcIi4vdmVyc2lvblwiOiAzMCB9XSwgMzM6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICB2YXIgdmVyc2lvbiA9IHJlcXVpcmUoXCIuL3ZlcnNpb25cIik7XG5cbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gVmlydHVhbFRleHQ7XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIFZpcnR1YWxUZXh0KHRleHQpIHtcbiAgICAgICAgICAgICAgICB0aGlzLnRleHQgPSBTdHJpbmcodGV4dCk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIFZpcnR1YWxUZXh0LnByb3RvdHlwZS52ZXJzaW9uID0gdmVyc2lvbjtcbiAgICAgICAgICAgIFZpcnR1YWxUZXh0LnByb3RvdHlwZS50eXBlID0gXCJWaXJ0dWFsVGV4dFwiO1xuICAgICAgICB9LCB7IFwiLi92ZXJzaW9uXCI6IDMwIH1dLCAzNDogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHtcbiAgICAgICAgICAgIHZhciBpc09iamVjdCA9IHJlcXVpcmUoXCJpcy1vYmplY3RcIik7XG4gICAgICAgICAgICB2YXIgaXNIb29rID0gcmVxdWlyZShcIi4uL3Zub2RlL2lzLXZob29rXCIpO1xuXG4gICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IGRpZmZQcm9wcztcblxuICAgICAgICAgICAgZnVuY3Rpb24gZGlmZlByb3BzKGEsIGIpIHtcbiAgICAgICAgICAgICAgICB2YXIgZGlmZjtcblxuICAgICAgICAgICAgICAgIGZvciAodmFyIGFLZXkgaW4gYSkge1xuICAgICAgICAgICAgICAgICAgICBpZiAoIShhS2V5IGluIGIpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBkaWZmID0gZGlmZiB8fCB7fTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGRpZmZbYUtleV0gPSB1bmRlZmluZWQ7XG4gICAgICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgICAgICB2YXIgYVZhbHVlID0gYVthS2V5XTtcbiAgICAgICAgICAgICAgICAgICAgdmFyIGJWYWx1ZSA9IGJbYUtleV07XG5cbiAgICAgICAgICAgICAgICAgICAgaWYgKGFWYWx1ZSA9PT0gYlZhbHVlKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBjb250aW51ZTtcbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIGlmIChpc09iamVjdChhVmFsdWUpICYmIGlzT2JqZWN0KGJWYWx1ZSkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChnZXRQcm90b3R5cGUoYlZhbHVlKSAhPT0gZ2V0UHJvdG90eXBlKGFWYWx1ZSkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBkaWZmID0gZGlmZiB8fCB7fTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBkaWZmW2FLZXldID0gYlZhbHVlO1xuICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIGlmIChpc0hvb2soYlZhbHVlKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRpZmYgPSBkaWZmIHx8IHt9O1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRpZmZbYUtleV0gPSBiVmFsdWU7XG4gICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZhciBvYmplY3REaWZmID0gZGlmZlByb3BzKGFWYWx1ZSwgYlZhbHVlKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAob2JqZWN0RGlmZikge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBkaWZmID0gZGlmZiB8fCB7fTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZGlmZlthS2V5XSA9IG9iamVjdERpZmY7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgZGlmZiA9IGRpZmYgfHwge307XG4gICAgICAgICAgICAgICAgICAgICAgICBkaWZmW2FLZXldID0gYlZhbHVlO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgZm9yICh2YXIgYktleSBpbiBiKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmICghKGJLZXkgaW4gYSkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGRpZmYgPSBkaWZmIHx8IHt9O1xuICAgICAgICAgICAgICAgICAgICAgICAgZGlmZltiS2V5XSA9IGJbYktleV07XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICByZXR1cm4gZGlmZjtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZnVuY3Rpb24gZ2V0UHJvdG90eXBlKHZhbHVlKSB7XG4gICAgICAgICAgICAgICAgaWYgKE9iamVjdC5nZXRQcm90b3R5cGVPZikge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gT2JqZWN0LmdldFByb3RvdHlwZU9mKHZhbHVlKTtcbiAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKHZhbHVlLl9fcHJvdG9fXykge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gdmFsdWUuX19wcm90b19fO1xuICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAodmFsdWUuY29uc3RydWN0b3IpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHZhbHVlLmNvbnN0cnVjdG9yLnByb3RvdHlwZTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH0sIHsgXCIuLi92bm9kZS9pcy12aG9va1wiOiAyNiwgXCJpcy1vYmplY3RcIjogMTEgfV0sIDM1OiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge1xuICAgICAgICAgICAgdmFyIGlzQXJyYXkgPSByZXF1aXJlKFwieC1pcy1hcnJheVwiKTtcblxuICAgICAgICAgICAgdmFyIFZQYXRjaCA9IHJlcXVpcmUoXCIuLi92bm9kZS92cGF0Y2hcIik7XG4gICAgICAgICAgICB2YXIgaXNWTm9kZSA9IHJlcXVpcmUoXCIuLi92bm9kZS9pcy12bm9kZVwiKTtcbiAgICAgICAgICAgIHZhciBpc1ZUZXh0ID0gcmVxdWlyZShcIi4uL3Zub2RlL2lzLXZ0ZXh0XCIpO1xuICAgICAgICAgICAgdmFyIGlzV2lkZ2V0ID0gcmVxdWlyZShcIi4uL3Zub2RlL2lzLXdpZGdldFwiKTtcbiAgICAgICAgICAgIHZhciBpc1RodW5rID0gcmVxdWlyZShcIi4uL3Zub2RlL2lzLXRodW5rXCIpO1xuICAgICAgICAgICAgdmFyIGhhbmRsZVRodW5rID0gcmVxdWlyZShcIi4uL3Zub2RlL2hhbmRsZS10aHVua1wiKTtcblxuICAgICAgICAgICAgdmFyIGRpZmZQcm9wcyA9IHJlcXVpcmUoXCIuL2RpZmYtcHJvcHNcIik7XG5cbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gZGlmZjtcblxuICAgICAgICAgICAgZnVuY3Rpb24gZGlmZihhLCBiKSB7XG4gICAgICAgICAgICAgICAgdmFyIHBhdGNoID0geyBhOiBhIH07XG4gICAgICAgICAgICAgICAgd2FsayhhLCBiLCBwYXRjaCwgMCk7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHBhdGNoO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBmdW5jdGlvbiB3YWxrKGEsIGIsIHBhdGNoLCBpbmRleCkge1xuICAgICAgICAgICAgICAgIGlmIChhID09PSBiKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICB2YXIgYXBwbHkgPSBwYXRjaFtpbmRleF07XG4gICAgICAgICAgICAgICAgdmFyIGFwcGx5Q2xlYXIgPSBmYWxzZTtcblxuICAgICAgICAgICAgICAgIGlmIChpc1RodW5rKGEpIHx8IGlzVGh1bmsoYikpIHtcbiAgICAgICAgICAgICAgICAgICAgdGh1bmtzKGEsIGIsIHBhdGNoLCBpbmRleCk7XG4gICAgICAgICAgICAgICAgfSBlbHNlIGlmIChiID09IG51bGwpIHtcblxuICAgICAgICAgICAgICAgICAgICAvLyBJZiBhIGlzIGEgd2lkZ2V0IHdlIHdpbGwgYWRkIGEgcmVtb3ZlIHBhdGNoIGZvciBpdFxuICAgICAgICAgICAgICAgICAgICAvLyBPdGhlcndpc2UgYW55IGNoaWxkIHdpZGdldHMvaG9va3MgbXVzdCBiZSBkZXN0cm95ZWQuXG4gICAgICAgICAgICAgICAgICAgIC8vIFRoaXMgcHJldmVudHMgYWRkaW5nIHR3byByZW1vdmUgcGF0Y2hlcyBmb3IgYSB3aWRnZXQuXG4gICAgICAgICAgICAgICAgICAgIGlmICghaXNXaWRnZXQoYSkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGNsZWFyU3RhdGUoYSwgcGF0Y2gsIGluZGV4KTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGFwcGx5ID0gcGF0Y2hbaW5kZXhdO1xuICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgYXBwbHkgPSBhcHBlbmRQYXRjaChhcHBseSwgbmV3IFZQYXRjaChWUGF0Y2guUkVNT1ZFLCBhLCBiKSk7XG4gICAgICAgICAgICAgICAgfSBlbHNlIGlmIChpc1ZOb2RlKGIpKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmIChpc1ZOb2RlKGEpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoYS50YWdOYW1lID09PSBiLnRhZ05hbWUgJiYgYS5uYW1lc3BhY2UgPT09IGIubmFtZXNwYWNlICYmIGEua2V5ID09PSBiLmtleSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZhciBwcm9wc1BhdGNoID0gZGlmZlByb3BzKGEucHJvcGVydGllcywgYi5wcm9wZXJ0aWVzKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAocHJvcHNQYXRjaCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBhcHBseSA9IGFwcGVuZFBhdGNoKGFwcGx5LCBuZXcgVlBhdGNoKFZQYXRjaC5QUk9QUywgYSwgcHJvcHNQYXRjaCkpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBhcHBseSA9IGRpZmZDaGlsZHJlbihhLCBiLCBwYXRjaCwgYXBwbHksIGluZGV4KTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgYXBwbHkgPSBhcHBlbmRQYXRjaChhcHBseSwgbmV3IFZQYXRjaChWUGF0Y2guVk5PREUsIGEsIGIpKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBhcHBseUNsZWFyID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGFwcGx5ID0gYXBwZW5kUGF0Y2goYXBwbHksIG5ldyBWUGF0Y2goVlBhdGNoLlZOT0RFLCBhLCBiKSk7XG4gICAgICAgICAgICAgICAgICAgICAgICBhcHBseUNsZWFyID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoaXNWVGV4dChiKSkge1xuICAgICAgICAgICAgICAgICAgICBpZiAoIWlzVlRleHQoYSkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGFwcGx5ID0gYXBwZW5kUGF0Y2goYXBwbHksIG5ldyBWUGF0Y2goVlBhdGNoLlZURVhULCBhLCBiKSk7XG4gICAgICAgICAgICAgICAgICAgICAgICBhcHBseUNsZWFyID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIGlmIChhLnRleHQgIT09IGIudGV4dCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgYXBwbHkgPSBhcHBlbmRQYXRjaChhcHBseSwgbmV3IFZQYXRjaChWUGF0Y2guVlRFWFQsIGEsIGIpKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoaXNXaWRnZXQoYikpIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKCFpc1dpZGdldChhKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgYXBwbHlDbGVhciA9IHRydWU7XG4gICAgICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgICAgICBhcHBseSA9IGFwcGVuZFBhdGNoKGFwcGx5LCBuZXcgVlBhdGNoKFZQYXRjaC5XSURHRVQsIGEsIGIpKTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICBpZiAoYXBwbHkpIHtcbiAgICAgICAgICAgICAgICAgICAgcGF0Y2hbaW5kZXhdID0gYXBwbHk7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgaWYgKGFwcGx5Q2xlYXIpIHtcbiAgICAgICAgICAgICAgICAgICAgY2xlYXJTdGF0ZShhLCBwYXRjaCwgaW5kZXgpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZnVuY3Rpb24gZGlmZkNoaWxkcmVuKGEsIGIsIHBhdGNoLCBhcHBseSwgaW5kZXgpIHtcbiAgICAgICAgICAgICAgICB2YXIgYUNoaWxkcmVuID0gYS5jaGlsZHJlbjtcbiAgICAgICAgICAgICAgICB2YXIgb3JkZXJlZFNldCA9IHJlb3JkZXIoYUNoaWxkcmVuLCBiLmNoaWxkcmVuKTtcbiAgICAgICAgICAgICAgICB2YXIgYkNoaWxkcmVuID0gb3JkZXJlZFNldC5jaGlsZHJlbjtcblxuICAgICAgICAgICAgICAgIHZhciBhTGVuID0gYUNoaWxkcmVuLmxlbmd0aDtcbiAgICAgICAgICAgICAgICB2YXIgYkxlbiA9IGJDaGlsZHJlbi5sZW5ndGg7XG4gICAgICAgICAgICAgICAgdmFyIGxlbiA9IGFMZW4gPiBiTGVuID8gYUxlbiA6IGJMZW47XG5cbiAgICAgICAgICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IGxlbjsgaSsrKSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciBsZWZ0Tm9kZSA9IGFDaGlsZHJlbltpXTtcbiAgICAgICAgICAgICAgICAgICAgdmFyIHJpZ2h0Tm9kZSA9IGJDaGlsZHJlbltpXTtcbiAgICAgICAgICAgICAgICAgICAgaW5kZXggKz0gMTtcblxuICAgICAgICAgICAgICAgICAgICBpZiAoIWxlZnROb2RlKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAocmlnaHROb2RlKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gRXhjZXNzIG5vZGVzIGluIGIgbmVlZCB0byBiZSBhZGRlZFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGFwcGx5ID0gYXBwZW5kUGF0Y2goYXBwbHksIG5ldyBWUGF0Y2goVlBhdGNoLklOU0VSVCwgbnVsbCwgcmlnaHROb2RlKSk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICB3YWxrKGxlZnROb2RlLCByaWdodE5vZGUsIHBhdGNoLCBpbmRleCk7XG4gICAgICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgICAgICBpZiAoaXNWTm9kZShsZWZ0Tm9kZSkgJiYgbGVmdE5vZGUuY291bnQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGluZGV4ICs9IGxlZnROb2RlLmNvdW50O1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgaWYgKG9yZGVyZWRTZXQubW92ZXMpIHtcbiAgICAgICAgICAgICAgICAgICAgLy8gUmVvcmRlciBub2RlcyBsYXN0XG4gICAgICAgICAgICAgICAgICAgIGFwcGx5ID0gYXBwZW5kUGF0Y2goYXBwbHksIG5ldyBWUGF0Y2goVlBhdGNoLk9SREVSLCBhLCBvcmRlcmVkU2V0Lm1vdmVzKSk7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgcmV0dXJuIGFwcGx5O1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBmdW5jdGlvbiBjbGVhclN0YXRlKHZOb2RlLCBwYXRjaCwgaW5kZXgpIHtcbiAgICAgICAgICAgICAgICAvLyBUT0RPOiBNYWtlIHRoaXMgYSBzaW5nbGUgd2Fsaywgbm90IHR3b1xuICAgICAgICAgICAgICAgIHVuaG9vayh2Tm9kZSwgcGF0Y2gsIGluZGV4KTtcbiAgICAgICAgICAgICAgICBkZXN0cm95V2lkZ2V0cyh2Tm9kZSwgcGF0Y2gsIGluZGV4KTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgLy8gUGF0Y2ggcmVjb3JkcyBmb3IgYWxsIGRlc3Ryb3llZCB3aWRnZXRzIG11c3QgYmUgYWRkZWQgYmVjYXVzZSB3ZSBuZWVkXG4gICAgICAgICAgICAvLyBhIERPTSBub2RlIHJlZmVyZW5jZSBmb3IgdGhlIGRlc3Ryb3kgZnVuY3Rpb25cbiAgICAgICAgICAgIGZ1bmN0aW9uIGRlc3Ryb3lXaWRnZXRzKHZOb2RlLCBwYXRjaCwgaW5kZXgpIHtcbiAgICAgICAgICAgICAgICBpZiAoaXNXaWRnZXQodk5vZGUpKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmICh0eXBlb2Ygdk5vZGUuZGVzdHJveSA9PT0gXCJmdW5jdGlvblwiKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBwYXRjaFtpbmRleF0gPSBhcHBlbmRQYXRjaChwYXRjaFtpbmRleF0sIG5ldyBWUGF0Y2goVlBhdGNoLlJFTU9WRSwgdk5vZGUsIG51bGwpKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoaXNWTm9kZSh2Tm9kZSkgJiYgKHZOb2RlLmhhc1dpZGdldHMgfHwgdk5vZGUuaGFzVGh1bmtzKSkge1xuICAgICAgICAgICAgICAgICAgICB2YXIgY2hpbGRyZW4gPSB2Tm9kZS5jaGlsZHJlbjtcbiAgICAgICAgICAgICAgICAgICAgdmFyIGxlbiA9IGNoaWxkcmVuLmxlbmd0aDtcbiAgICAgICAgICAgICAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCBsZW47IGkrKykge1xuICAgICAgICAgICAgICAgICAgICAgICAgdmFyIGNoaWxkID0gY2hpbGRyZW5baV07XG4gICAgICAgICAgICAgICAgICAgICAgICBpbmRleCArPSAxO1xuXG4gICAgICAgICAgICAgICAgICAgICAgICBkZXN0cm95V2lkZ2V0cyhjaGlsZCwgcGF0Y2gsIGluZGV4KTtcblxuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGlzVk5vZGUoY2hpbGQpICYmIGNoaWxkLmNvdW50KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaW5kZXggKz0gY2hpbGQuY291bnQ7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKGlzVGh1bmsodk5vZGUpKSB7XG4gICAgICAgICAgICAgICAgICAgIHRodW5rcyh2Tm9kZSwgbnVsbCwgcGF0Y2gsIGluZGV4KTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIC8vIENyZWF0ZSBhIHN1Yi1wYXRjaCBmb3IgdGh1bmtzXG4gICAgICAgICAgICBmdW5jdGlvbiB0aHVua3MoYSwgYiwgcGF0Y2gsIGluZGV4KSB7XG4gICAgICAgICAgICAgICAgdmFyIG5vZGVzID0gaGFuZGxlVGh1bmsoYSwgYik7XG4gICAgICAgICAgICAgICAgdmFyIHRodW5rUGF0Y2ggPSBkaWZmKG5vZGVzLmEsIG5vZGVzLmIpO1xuICAgICAgICAgICAgICAgIGlmIChoYXNQYXRjaGVzKHRodW5rUGF0Y2gpKSB7XG4gICAgICAgICAgICAgICAgICAgIHBhdGNoW2luZGV4XSA9IG5ldyBWUGF0Y2goVlBhdGNoLlRIVU5LLCBudWxsLCB0aHVua1BhdGNoKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIGhhc1BhdGNoZXMocGF0Y2gpIHtcbiAgICAgICAgICAgICAgICBmb3IgKHZhciBpbmRleCBpbiBwYXRjaCkge1xuICAgICAgICAgICAgICAgICAgICBpZiAoaW5kZXggIT09IFwiYVwiKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgLy8gRXhlY3V0ZSBob29rcyB3aGVuIHR3byBub2RlcyBhcmUgaWRlbnRpY2FsXG4gICAgICAgICAgICBmdW5jdGlvbiB1bmhvb2sodk5vZGUsIHBhdGNoLCBpbmRleCkge1xuICAgICAgICAgICAgICAgIGlmIChpc1ZOb2RlKHZOb2RlKSkge1xuICAgICAgICAgICAgICAgICAgICBpZiAodk5vZGUuaG9va3MpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHBhdGNoW2luZGV4XSA9IGFwcGVuZFBhdGNoKHBhdGNoW2luZGV4XSwgbmV3IFZQYXRjaChWUGF0Y2guUFJPUFMsIHZOb2RlLCB1bmRlZmluZWRLZXlzKHZOb2RlLmhvb2tzKSkpO1xuICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgaWYgKHZOb2RlLmRlc2NlbmRhbnRIb29rcyB8fCB2Tm9kZS5oYXNUaHVua3MpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHZhciBjaGlsZHJlbiA9IHZOb2RlLmNoaWxkcmVuO1xuICAgICAgICAgICAgICAgICAgICAgICAgdmFyIGxlbiA9IGNoaWxkcmVuLmxlbmd0aDtcbiAgICAgICAgICAgICAgICAgICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgbGVuOyBpKyspIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB2YXIgY2hpbGQgPSBjaGlsZHJlbltpXTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpbmRleCArPSAxO1xuXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdW5ob29rKGNoaWxkLCBwYXRjaCwgaW5kZXgpO1xuXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGlzVk5vZGUoY2hpbGQpICYmIGNoaWxkLmNvdW50KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGluZGV4ICs9IGNoaWxkLmNvdW50O1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoaXNUaHVuayh2Tm9kZSkpIHtcbiAgICAgICAgICAgICAgICAgICAgdGh1bmtzKHZOb2RlLCBudWxsLCBwYXRjaCwgaW5kZXgpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZnVuY3Rpb24gdW5kZWZpbmVkS2V5cyhvYmopIHtcbiAgICAgICAgICAgICAgICB2YXIgcmVzdWx0ID0ge307XG5cbiAgICAgICAgICAgICAgICBmb3IgKHZhciBrZXkgaW4gb2JqKSB7XG4gICAgICAgICAgICAgICAgICAgIHJlc3VsdFtrZXldID0gdW5kZWZpbmVkO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHJldHVybiByZXN1bHQ7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIC8vIExpc3QgZGlmZiwgbmFpdmUgbGVmdCB0byByaWdodCByZW9yZGVyaW5nXG4gICAgICAgICAgICBmdW5jdGlvbiByZW9yZGVyKGFDaGlsZHJlbiwgYkNoaWxkcmVuKSB7XG4gICAgICAgICAgICAgICAgLy8gTyhNKSB0aW1lLCBPKE0pIG1lbW9yeVxuICAgICAgICAgICAgICAgIHZhciBiQ2hpbGRJbmRleCA9IGtleUluZGV4KGJDaGlsZHJlbik7XG4gICAgICAgICAgICAgICAgdmFyIGJLZXlzID0gYkNoaWxkSW5kZXgua2V5cztcbiAgICAgICAgICAgICAgICB2YXIgYkZyZWUgPSBiQ2hpbGRJbmRleC5mcmVlO1xuXG4gICAgICAgICAgICAgICAgaWYgKGJGcmVlLmxlbmd0aCA9PT0gYkNoaWxkcmVuLmxlbmd0aCkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgICAgICAgICAgICAgY2hpbGRyZW46IGJDaGlsZHJlbixcbiAgICAgICAgICAgICAgICAgICAgICAgIG1vdmVzOiBudWxsXG4gICAgICAgICAgICAgICAgICAgIH07XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgLy8gTyhOKSB0aW1lLCBPKE4pIG1lbW9yeVxuICAgICAgICAgICAgICAgIHZhciBhQ2hpbGRJbmRleCA9IGtleUluZGV4KGFDaGlsZHJlbik7XG4gICAgICAgICAgICAgICAgdmFyIGFLZXlzID0gYUNoaWxkSW5kZXgua2V5cztcbiAgICAgICAgICAgICAgICB2YXIgYUZyZWUgPSBhQ2hpbGRJbmRleC5mcmVlO1xuXG4gICAgICAgICAgICAgICAgaWYgKGFGcmVlLmxlbmd0aCA9PT0gYUNoaWxkcmVuLmxlbmd0aCkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgICAgICAgICAgICAgY2hpbGRyZW46IGJDaGlsZHJlbixcbiAgICAgICAgICAgICAgICAgICAgICAgIG1vdmVzOiBudWxsXG4gICAgICAgICAgICAgICAgICAgIH07XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgLy8gTyhNQVgoTiwgTSkpIG1lbW9yeVxuICAgICAgICAgICAgICAgIHZhciBuZXdDaGlsZHJlbiA9IFtdO1xuXG4gICAgICAgICAgICAgICAgdmFyIGZyZWVJbmRleCA9IDA7XG4gICAgICAgICAgICAgICAgdmFyIGZyZWVDb3VudCA9IGJGcmVlLmxlbmd0aDtcbiAgICAgICAgICAgICAgICB2YXIgZGVsZXRlZEl0ZW1zID0gMDtcblxuICAgICAgICAgICAgICAgIC8vIEl0ZXJhdGUgdGhyb3VnaCBhIGFuZCBtYXRjaCBhIG5vZGUgaW4gYlxuICAgICAgICAgICAgICAgIC8vIE8oTikgdGltZSxcbiAgICAgICAgICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IGFDaGlsZHJlbi5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgICAgICAgICB2YXIgYUl0ZW0gPSBhQ2hpbGRyZW5baV07XG4gICAgICAgICAgICAgICAgICAgIHZhciBpdGVtSW5kZXg7XG5cbiAgICAgICAgICAgICAgICAgICAgaWYgKGFJdGVtLmtleSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGJLZXlzLmhhc093blByb3BlcnR5KGFJdGVtLmtleSkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBNYXRjaCB1cCB0aGUgb2xkIGtleXNcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpdGVtSW5kZXggPSBiS2V5c1thSXRlbS5rZXldO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIG5ld0NoaWxkcmVuLnB1c2goYkNoaWxkcmVuW2l0ZW1JbmRleF0pO1xuICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBSZW1vdmUgb2xkIGtleWVkIGl0ZW1zXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaXRlbUluZGV4ID0gaSAtIGRlbGV0ZWRJdGVtcysrO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIG5ld0NoaWxkcmVuLnB1c2gobnVsbCk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAvLyBNYXRjaCB0aGUgaXRlbSBpbiBhIHdpdGggdGhlIG5leHQgZnJlZSBpdGVtIGluIGJcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChmcmVlSW5kZXggPCBmcmVlQ291bnQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpdGVtSW5kZXggPSBiRnJlZVtmcmVlSW5kZXgrK107XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgbmV3Q2hpbGRyZW4ucHVzaChiQ2hpbGRyZW5baXRlbUluZGV4XSk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIFRoZXJlIGFyZSBubyBmcmVlIGl0ZW1zIGluIGIgdG8gbWF0Y2ggd2l0aFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIHRoZSBmcmVlIGl0ZW1zIGluIGEsIHNvIHRoZSBleHRyYSBmcmVlIG5vZGVzXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gYXJlIGRlbGV0ZWQuXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaXRlbUluZGV4ID0gaSAtIGRlbGV0ZWRJdGVtcysrO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIG5ld0NoaWxkcmVuLnB1c2gobnVsbCk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICB2YXIgbGFzdEZyZWVJbmRleCA9IGZyZWVJbmRleCA+PSBiRnJlZS5sZW5ndGggPyBiQ2hpbGRyZW4ubGVuZ3RoIDogYkZyZWVbZnJlZUluZGV4XTtcblxuICAgICAgICAgICAgICAgIC8vIEl0ZXJhdGUgdGhyb3VnaCBiIGFuZCBhcHBlbmQgYW55IG5ldyBrZXlzXG4gICAgICAgICAgICAgICAgLy8gTyhNKSB0aW1lXG4gICAgICAgICAgICAgICAgZm9yICh2YXIgaiA9IDA7IGogPCBiQ2hpbGRyZW4ubGVuZ3RoOyBqKyspIHtcbiAgICAgICAgICAgICAgICAgICAgdmFyIG5ld0l0ZW0gPSBiQ2hpbGRyZW5bal07XG5cbiAgICAgICAgICAgICAgICAgICAgaWYgKG5ld0l0ZW0ua2V5KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoIWFLZXlzLmhhc093blByb3BlcnR5KG5ld0l0ZW0ua2V5KSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIEFkZCBhbnkgbmV3IGtleWVkIGl0ZW1zXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gV2UgYXJlIGFkZGluZyBuZXcgaXRlbXMgdG8gdGhlIGVuZCBhbmQgdGhlbiBzb3J0aW5nIHRoZW1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBpbiBwbGFjZS4gSW4gZnV0dXJlIHdlIHNob3VsZCBpbnNlcnQgbmV3IGl0ZW1zIGluIHBsYWNlLlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIG5ld0NoaWxkcmVuLnB1c2gobmV3SXRlbSk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoaiA+PSBsYXN0RnJlZUluZGV4KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAvLyBBZGQgYW55IGxlZnRvdmVyIG5vbi1rZXllZCBpdGVtc1xuICAgICAgICAgICAgICAgICAgICAgICAgbmV3Q2hpbGRyZW4ucHVzaChuZXdJdGVtKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHZhciBzaW11bGF0ZSA9IG5ld0NoaWxkcmVuLnNsaWNlKCk7XG4gICAgICAgICAgICAgICAgdmFyIHNpbXVsYXRlSW5kZXggPSAwO1xuICAgICAgICAgICAgICAgIHZhciByZW1vdmVzID0gW107XG4gICAgICAgICAgICAgICAgdmFyIGluc2VydHMgPSBbXTtcbiAgICAgICAgICAgICAgICB2YXIgc2ltdWxhdGVJdGVtO1xuXG4gICAgICAgICAgICAgICAgZm9yICh2YXIgayA9IDA7IGsgPCBiQ2hpbGRyZW4ubGVuZ3RoOykge1xuICAgICAgICAgICAgICAgICAgICB2YXIgd2FudGVkSXRlbSA9IGJDaGlsZHJlbltrXTtcbiAgICAgICAgICAgICAgICAgICAgc2ltdWxhdGVJdGVtID0gc2ltdWxhdGVbc2ltdWxhdGVJbmRleF07XG5cbiAgICAgICAgICAgICAgICAgICAgLy8gcmVtb3ZlIGl0ZW1zXG4gICAgICAgICAgICAgICAgICAgIHdoaWxlIChzaW11bGF0ZUl0ZW0gPT09IG51bGwgJiYgc2ltdWxhdGUubGVuZ3RoKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICByZW1vdmVzLnB1c2gocmVtb3ZlKHNpbXVsYXRlLCBzaW11bGF0ZUluZGV4LCBudWxsKSk7XG4gICAgICAgICAgICAgICAgICAgICAgICBzaW11bGF0ZUl0ZW0gPSBzaW11bGF0ZVtzaW11bGF0ZUluZGV4XTtcbiAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgIGlmICghc2ltdWxhdGVJdGVtIHx8IHNpbXVsYXRlSXRlbS5rZXkgIT09IHdhbnRlZEl0ZW0ua2V5KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAvLyBpZiB3ZSBuZWVkIGEga2V5IGluIHRoaXMgcG9zaXRpb24uLi5cbiAgICAgICAgICAgICAgICAgICAgICAgIGlmICh3YW50ZWRJdGVtLmtleSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChzaW11bGF0ZUl0ZW0gJiYgc2ltdWxhdGVJdGVtLmtleSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBpZiBhbiBpbnNlcnQgZG9lc24ndCBwdXQgdGhpcyBrZXkgaW4gcGxhY2UsIGl0IG5lZWRzIHRvIG1vdmVcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGJLZXlzW3NpbXVsYXRlSXRlbS5rZXldICE9PSBrICsgMSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmVtb3Zlcy5wdXNoKHJlbW92ZShzaW11bGF0ZSwgc2ltdWxhdGVJbmRleCwgc2ltdWxhdGVJdGVtLmtleSkpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc2ltdWxhdGVJdGVtID0gc2ltdWxhdGVbc2ltdWxhdGVJbmRleF07XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBpZiB0aGUgcmVtb3ZlIGRpZG4ndCBwdXQgdGhlIHdhbnRlZCBpdGVtIGluIHBsYWNlLCB3ZSBuZWVkIHRvIGluc2VydCBpdFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKCFzaW11bGF0ZUl0ZW0gfHwgc2ltdWxhdGVJdGVtLmtleSAhPT0gd2FudGVkSXRlbS5rZXkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpbnNlcnRzLnB1c2goeyBrZXk6IHdhbnRlZEl0ZW0ua2V5LCB0bzogayB9KTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIGl0ZW1zIGFyZSBtYXRjaGluZywgc28gc2tpcCBhaGVhZFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc2ltdWxhdGVJbmRleCsrO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaW5zZXJ0cy5wdXNoKHsga2V5OiB3YW50ZWRJdGVtLmtleSwgdG86IGsgfSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpbnNlcnRzLnB1c2goeyBrZXk6IHdhbnRlZEl0ZW0ua2V5LCB0bzogayB9KTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaysrO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgLy8gYSBrZXkgaW4gc2ltdWxhdGUgaGFzIG5vIG1hdGNoaW5nIHdhbnRlZCBrZXksIHJlbW92ZSBpdFxuICAgICAgICAgICAgICAgICAgICAgICAgZWxzZSBpZiAoc2ltdWxhdGVJdGVtICYmIHNpbXVsYXRlSXRlbS5rZXkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICByZW1vdmVzLnB1c2gocmVtb3ZlKHNpbXVsYXRlLCBzaW11bGF0ZUluZGV4LCBzaW11bGF0ZUl0ZW0ua2V5KSk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBzaW11bGF0ZUluZGV4Kys7XG4gICAgICAgICAgICAgICAgICAgICAgICBrKys7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAvLyByZW1vdmUgYWxsIHRoZSByZW1haW5pbmcgbm9kZXMgZnJvbSBzaW11bGF0ZVxuICAgICAgICAgICAgICAgIHdoaWxlIChzaW11bGF0ZUluZGV4IDwgc2ltdWxhdGUubGVuZ3RoKSB7XG4gICAgICAgICAgICAgICAgICAgIHNpbXVsYXRlSXRlbSA9IHNpbXVsYXRlW3NpbXVsYXRlSW5kZXhdO1xuICAgICAgICAgICAgICAgICAgICByZW1vdmVzLnB1c2gocmVtb3ZlKHNpbXVsYXRlLCBzaW11bGF0ZUluZGV4LCBzaW11bGF0ZUl0ZW0gJiYgc2ltdWxhdGVJdGVtLmtleSkpO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIC8vIElmIHRoZSBvbmx5IG1vdmVzIHdlIGhhdmUgYXJlIGRlbGV0ZXMgdGhlbiB3ZSBjYW4ganVzdFxuICAgICAgICAgICAgICAgIC8vIGxldCB0aGUgZGVsZXRlIHBhdGNoIHJlbW92ZSB0aGVzZSBpdGVtcy5cbiAgICAgICAgICAgICAgICBpZiAocmVtb3Zlcy5sZW5ndGggPT09IGRlbGV0ZWRJdGVtcyAmJiAhaW5zZXJ0cy5sZW5ndGgpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGNoaWxkcmVuOiBuZXdDaGlsZHJlbixcbiAgICAgICAgICAgICAgICAgICAgICAgIG1vdmVzOiBudWxsXG4gICAgICAgICAgICAgICAgICAgIH07XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgICAgICAgICAgY2hpbGRyZW46IG5ld0NoaWxkcmVuLFxuICAgICAgICAgICAgICAgICAgICBtb3Zlczoge1xuICAgICAgICAgICAgICAgICAgICAgICAgcmVtb3ZlczogcmVtb3ZlcyxcbiAgICAgICAgICAgICAgICAgICAgICAgIGluc2VydHM6IGluc2VydHNcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH07XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIHJlbW92ZShhcnIsIGluZGV4LCBrZXkpIHtcbiAgICAgICAgICAgICAgICBhcnIuc3BsaWNlKGluZGV4LCAxKTtcblxuICAgICAgICAgICAgICAgIHJldHVybiB7XG4gICAgICAgICAgICAgICAgICAgIGZyb206IGluZGV4LFxuICAgICAgICAgICAgICAgICAgICBrZXk6IGtleVxuICAgICAgICAgICAgICAgIH07XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIGtleUluZGV4KGNoaWxkcmVuKSB7XG4gICAgICAgICAgICAgICAgdmFyIGtleXMgPSB7fTtcbiAgICAgICAgICAgICAgICB2YXIgZnJlZSA9IFtdO1xuICAgICAgICAgICAgICAgIHZhciBsZW5ndGggPSBjaGlsZHJlbi5sZW5ndGg7XG5cbiAgICAgICAgICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IGxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciBjaGlsZCA9IGNoaWxkcmVuW2ldO1xuXG4gICAgICAgICAgICAgICAgICAgIGlmIChjaGlsZC5rZXkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGtleXNbY2hpbGQua2V5XSA9IGk7XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBmcmVlLnB1c2goaSk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgICAgICAgICBrZXlzOiBrZXlzLCAvLyBBIGhhc2ggb2Yga2V5IG5hbWUgdG8gaW5kZXhcbiAgICAgICAgICAgICAgICAgICAgZnJlZTogZnJlZSAvLyBBbiBhcnJheSBvZiB1bmtleWVkIGl0ZW0gaW5kaWNlc1xuICAgICAgICAgICAgICAgIH07XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIGFwcGVuZFBhdGNoKGFwcGx5LCBwYXRjaCkge1xuICAgICAgICAgICAgICAgIGlmIChhcHBseSkge1xuICAgICAgICAgICAgICAgICAgICBpZiAoaXNBcnJheShhcHBseSkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGFwcGx5LnB1c2gocGF0Y2gpO1xuICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgYXBwbHkgPSBbYXBwbHksIHBhdGNoXTtcbiAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBhcHBseTtcbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gcGF0Y2g7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9LCB7IFwiLi4vdm5vZGUvaGFuZGxlLXRodW5rXCI6IDI0LCBcIi4uL3Zub2RlL2lzLXRodW5rXCI6IDI1LCBcIi4uL3Zub2RlL2lzLXZub2RlXCI6IDI3LCBcIi4uL3Zub2RlL2lzLXZ0ZXh0XCI6IDI4LCBcIi4uL3Zub2RlL2lzLXdpZGdldFwiOiAyOSwgXCIuLi92bm9kZS92cGF0Y2hcIjogMzIsIFwiLi9kaWZmLXByb3BzXCI6IDM0LCBcIngtaXMtYXJyYXlcIjogMTIgfV0gfSwge30sIFs0XSkoNCk7XG59KTtcblxuY29uc3Qgc3RhcnQgPSBmdW5jdGlvbiAoZG9tUm9vdCwgcmVuZGVyRm4sIGluaXRpYWxTdGF0ZSwgb3B0aW9ucyA9IFtdKSB7XG4gIGxldCBwaWQgPSBzZWxmLnByb2Nlc3Nlcy5zcGF3bigpO1xuXG4gIGlmIChLZXl3b3JkLmhhc19rZXlfX3FtX18ob3B0aW9ucywgS2VybmVsLlNwZWNpYWxGb3Jtcy5hdG9tKCduYW1lJykpKSB7XG4gICAgcGlkID0gc2VsZi5wcm9jZXNzZXMucmVnaXN0ZXIoS2V5d29yZC5nZXQob3B0aW9ucywgS2VybmVsLlNwZWNpYWxGb3Jtcy5hdG9tKCduYW1lJykpLCBwaWQpO1xuICB9XG5cbiAgY29uc3QgdHJlZSA9IHJlbmRlckZuLmFwcGx5KHRoaXMsIGluaXRpYWxTdGF0ZSk7XG4gIGNvbnN0IHJvb3ROb2RlID0gVmlydHVhbERPTS5jcmVhdGUodHJlZSk7XG5cbiAgZG9tUm9vdC5hcHBlbmRDaGlsZChyb290Tm9kZSk7XG5cbiAgc2VsZi5wcm9jZXNzZXMucHV0KHBpZCwgJ3N0YXRlJywgS2VybmVsLlNwZWNpYWxGb3Jtcy50dXBsZShyb290Tm9kZSwgdHJlZSwgcmVuZGVyRm4pKTtcbiAgcmV0dXJuIEtlcm5lbC5TcGVjaWFsRm9ybXMudHVwbGUoS2VybmVsLlNwZWNpYWxGb3Jtcy5hdG9tKCdvaycpLCBwaWQpO1xufTtcblxuY29uc3Qgc3RvcCA9IGZ1bmN0aW9uIChhZ2VudCwgdGltZW91dCA9IDUwMDApIHtcbiAgc2VsZi5wcm9jZXNzZXMuZXhpdChhZ2VudCk7XG4gIHJldHVybiBLZXJuZWwuU3BlY2lhbEZvcm1zLmF0b20oJ29rJyk7XG59O1xuXG5jb25zdCByZW5kZXIgPSBmdW5jdGlvbiAoYWdlbnQsIHN0YXRlKSB7XG5cbiAgY29uc3QgY3VycmVudF9zdGF0ZSA9IHNlbGYucHJvY2Vzc2VzLmdldChhZ2VudCwgJ3N0YXRlJyk7XG5cbiAgbGV0IHJvb3ROb2RlID0gS2VybmVsLmVsZW0oY3VycmVudF9zdGF0ZSwgMCk7XG4gIGxldCB0cmVlID0gS2VybmVsLmVsZW0oY3VycmVudF9zdGF0ZSwgMSk7XG4gIGxldCByZW5kZXJGbiA9IEtlcm5lbC5lbGVtKGN1cnJlbnRfc3RhdGUsIDIpO1xuXG4gIGxldCBuZXdUcmVlID0gcmVuZGVyRm4uYXBwbHkodGhpcywgc3RhdGUpO1xuXG4gIGxldCBwYXRjaGVzID0gVmlydHVhbERPTS5kaWZmKHRyZWUsIG5ld1RyZWUpO1xuICByb290Tm9kZSA9IFZpcnR1YWxET00ucGF0Y2gocm9vdE5vZGUsIHBhdGNoZXMpO1xuXG4gIHNlbGYucHJvY2Vzc2VzLnB1dChhZ2VudCwgJ3N0YXRlJywgS2VybmVsLlNwZWNpYWxGb3Jtcy50dXBsZShyb290Tm9kZSwgbmV3VHJlZSwgcmVuZGVyRm4pKTtcblxuICByZXR1cm4gS2VybmVsLlNwZWNpYWxGb3Jtcy5hdG9tKCdvaycpO1xufTtcblxudmFyIHZpZXcgPSB7XG4gIHN0YXJ0LFxuICBzdG9wLFxuICByZW5kZXJcbn07XG5cbnNlbGYucHJvY2Vzc2VzID0gc2VsZi5wcm9jZXNzZXMgfHwgbmV3IFByb2Nlc3NTeXN0ZW0oKTtcblxuY29uc3QgQ29yZSA9IEM7XG5cbmV4cG9ydCB7IENvcmUsIEtlcm5lbCwgQXRvbSwgRW51bSwgSW50ZWdlciwgTGlzdCwgUmFuZ2UsIFR1cGxlLCBBZ2VudCwgS2V5d29yZCwgYmFzZSBhcyBCYXNlLCBTdHJpbmckMSBhcyBTdHJpbmcsIGJpdHdpc2UgYXMgQml0d2lzZSwgRW51bWVyYWJsZSwgQ29sbGVjdGFibGUsIEluc3BlY3QsIG1hcCBhcyBNYXAsIHNldCBhcyBTZXQsIE1hcFNldCwgVmlydHVhbERPTSwgdmlldyBhcyBWaWV3IH07Il0sImZpbGUiOiJlbGl4aXIuanMiLCJzb3VyY2VSb290IjoiL3NvdXJjZS8ifQ== \ No newline at end of file From 399187eae31e1e0e03821d31cf4ba80c0c28aaf2 Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Sun, 6 Dec 2015 09:45:54 -0600 Subject: [PATCH 080/860] Updated the CHANGELOG --- CHANGELOG.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index dd7231f9..50284109 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,4 +1,7 @@ # v0.14.0 +* Breaking + * Renamed `ex2js` to `elixirscript`. This effects the escript as well as the + mix task * Enhancements * Structs are now translated into classes * Structs and Tuples now match on their types From 2f3fc1ff53ebdfd2be92daac6e6e361b38ad3c8d Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Sun, 6 Dec 2015 15:55:54 -0600 Subject: [PATCH 081/860] renamed import names. Update module struct name property to be the module's atom name. flattened js output --- gulpfile.js | 2 +- lib/elixir_script.ex | 14 ++--- lib/elixir_script/cli.ex | 4 +- lib/elixir_script/module.ex | 50 ++++++++++++++---- lib/elixir_script/preprocess/aliases.ex | 4 +- lib/elixir_script/preprocess/modules.ex | 41 ++++++--------- lib/elixir_script/state.ex | 65 ++++++++++++++---------- lib/elixir_script/translator.ex | 21 +++----- lib/elixir_script/translator/function.ex | 61 +++++++++++++++------- lib/elixir_script/translator/import.ex | 12 +++++ lib/elixir_script/translator/module.ex | 46 +++++++---------- lib/elixir_script/translator/protocol.ex | 6 +-- lib/elixir_script/translator/struct.ex | 15 ++---- lib/elixir_script/translator/utils.ex | 10 ++-- mix.exs | 10 ++-- priv/elixir.js | 2 +- test/elixir_script_test.exs | 10 ++-- test/translator/alias_test.exs | 41 --------------- test/translator/bug_test.exs | 2 +- test/translator/defmodule_test.exs | 38 +++++++------- test/translator/function_test.exs | 10 ++-- test/translator/protocol_test.exs | 4 +- test/translator/require_test.exs | 28 ---------- test/translator/struct_test.exs | 12 ++--- 24 files changed, 240 insertions(+), 268 deletions(-) delete mode 100644 test/translator/alias_test.exs delete mode 100644 test/translator/require_test.exs diff --git a/gulpfile.js b/gulpfile.js index afe4f73f..90c08076 100644 --- a/gulpfile.js +++ b/gulpfile.js @@ -44,7 +44,7 @@ gulp.task('dist_build', function() { }); gulp.task('dist_add_source_map', function() { - return gulp.src(['./priv/elixir.js']) + return gulp.src(['./priv/Elixir.js']) .pipe(sourcemaps.init()) .pipe(sourcemaps.write()) .pipe(gulp.dest('./priv')); diff --git a/lib/elixir_script.ex b/lib/elixir_script.ex index 50b1291f..de50b300 100644 --- a/lib/elixir_script.ex +++ b/lib/elixir_script.ex @@ -20,7 +20,7 @@ defmodule ElixirScript do * `:root` - a binary path prepended to the path of the standard lib imports if needed * `:env` - a Macro.env struct to use. This is most useful when using macros. Make sure that the * `:stdlib_path` - The es6 import path used to import the elixirscript standard lib. - When using this option, the elixir.js file is not exported + When using this option, the Elixir.js file is not exported """ @doc """ @@ -42,7 +42,7 @@ defmodule ElixirScript do root = Dict.get(opts, :root) env = Dict.get(opts, :env, custom_env) import_standard_libs? = Dict.get(opts, :import_standard_libs, true) - stdlib_path = Dict.get(opts, :stdlib_path, "elixir") + stdlib_path = Dict.get(opts, :stdlib_path, "Elixir") ElixirScript.State.start_link(root, env) @@ -58,7 +58,7 @@ defmodule ElixirScript do include_path = Dict.get(opts, :include_path, false) root = Dict.get(opts, :root) env = Dict.get(opts, :env, custom_env) - stdlib_path = Dict.get(opts, :stdlib_path, "elixir") + stdlib_path = Dict.get(opts, :stdlib_path, "Elixir") ElixirScript.State.start_link(root, env) @@ -133,14 +133,14 @@ defmodule ElixirScript do to the specified location """ def copy_standard_libs_to_destination(destination) do - File.cp_r!(operating_path, destination) + File.cp!(operating_path <> "/Elixir.js", destination <> "/Elixir.js") end @doc """ Returns the standard lib js code """ def standard_libs() do - File.read!(operating_path <> "/elixir.js") + File.read!(operating_path <> "/Elixir.js") end defp convert_to_code(js_ast, root, include_path, env, import_standard_libs, stdlib_path) do @@ -167,8 +167,8 @@ defmodule ElixirScript do {file_path, program} end - defp create_file_name(%JSModule{name: module_list}) do - name = ElixirScript.Translator.Import.make_file_path(module_list) + defp create_file_name(%JSModule{name: module}) do + name = ElixirScript.Module.name_to_js_file_name(module) "#{name}.js" end diff --git a/lib/elixir_script/cli.ex b/lib/elixir_script/cli.ex index 82d2e5bc..3323cbfa 100644 --- a/lib/elixir_script/cli.ex +++ b/lib/elixir_script/cli.ex @@ -39,7 +39,7 @@ defmodule ElixirScript.CLI do -r --root [path] root import path for all exported modules -st --stdlib outputs the standard lib js file -stp --stdlib_path es6 import path to the elixirscript standard lib - only used with the [output] option. When used, elixir.js is not exported + only used with the [output] option. When used, Elixir.js is not exported -h --help this message """ end @@ -60,7 +60,7 @@ defmodule ElixirScript.CLI do compile_opts = [ root: options[:root], include_path: options[:output] != nil, - stdlib_path: Dict.get(options, :stdlib_path, "elixir") + stdlib_path: Dict.get(options, :stdlib_path, "Elixir") ] compile_output = case options[:elixir] do diff --git a/lib/elixir_script/module.ex b/lib/elixir_script/module.ex index ad64f191..9f3ca8a9 100644 --- a/lib/elixir_script/module.ex +++ b/lib/elixir_script/module.ex @@ -2,7 +2,7 @@ defmodule ElixirScript.Module do @moduledoc false defstruct name: nil, functions: Keyword.new, macros: Keyword.new, body: nil, - aliases: [], requires: [], imports: [], js_imports: [] + aliases: [], requires: [], imports: [], js_imports: [], module_refs: [] def functions(module) do Keyword.keys(module.functions) |> Enum.uniq @@ -24,13 +24,13 @@ defmodule ElixirScript.Module do module.imports end - def has_alias?(module, {:__aliases__, _, _} = ast) do - { name, _ } = Code.eval_quoted(ast) - has_alias?(module, name) - end - def has_alias?(module, name) do - List.keymember?(Set.to_list(module.aliases), name, 0) + case module.aliases do + aliases when is_list(aliases) -> + List.keymember?(module.aliases, name, 0) + _ -> + List.keymember?(Set.to_list(module.aliases), name, 0) + end end def get_alias(nil, _) do @@ -38,18 +38,21 @@ defmodule ElixirScript.Module do end def get_alias(module, name) when is_list(name) do - name = {:__aliases__, [], name } + name = {:__aliases__, [], name } |> quoted_to_name get_alias(module, name) end - def get_alias(module, {:__aliases__, _, _} = ast) do - { name, _ } = Code.eval_quoted(ast) - + def get_alias(module, name) when is_atom(name) do Enum.find(module.aliases, fn({the_alias, _}) -> name == the_alias end) end + def get_alias(module, {:__aliases__, _, _} = ast) do + name = quoted_to_name(ast) + get_alias(module, name) + end + def imported?(module, function_name) do imported_modules = Enum.find(module.imports, fn({_, funcs}) -> Enum.member?(funcs, function_name) @@ -60,4 +63,29 @@ defmodule ElixirScript.Module do end end + def quoted_to_name(the_alias) do + {name, _} = Code.eval_quoted(the_alias) + name + end + + def name_to_quoted(name) do + name = name + |> Atom.to_string + |> String.split(".") + |> tl + |> Enum.map(fn x -> String.to_atom(x) end) + + { :__aliases__, [], name } + end + + def name_to_js_name(name) do + { :__aliases__, _, name } = name_to_quoted(name) + Enum.join([:Elixir] ++ name, "$") + end + + def name_to_js_file_name(name) do + { :__aliases__, _, name } = name_to_quoted(name) + Enum.join([:Elixir] ++ name, ".") + end + end diff --git a/lib/elixir_script/preprocess/aliases.ex b/lib/elixir_script/preprocess/aliases.ex index 6a5b8fd4..14da4ae2 100644 --- a/lib/elixir_script/preprocess/aliases.ex +++ b/lib/elixir_script/preprocess/aliases.ex @@ -29,7 +29,7 @@ defmodule ElixirScript.Preprocess.Aliases do def process_aliases({{:., meta1, [{:__aliases__, meta2, aliases}, function]}, meta3, params}, _, module_name_list) when aliases in [[:Collectable], [:Enumerable], [:Inspect], [:List, :Chars], [:String, :Chars]] do new_ast = {{:., meta1, [{:__aliases__, meta2, List.last(aliases) |> List.wrap }, function]}, meta3, params} - ElixirScript.State.add_alias(module_name_list, {:__aliases__, meta2, [:Elixir] ++ aliases}) + ElixirScript.State.add_alias(ElixirScript.Module.quoted_to_name({:__aliases__, [], module_name_list}), {:__aliases__, meta2, [:Elixir] ++ aliases}) new_ast end @@ -41,7 +41,7 @@ defmodule ElixirScript.Preprocess.Aliases do module = ElixirScript.State.get_module(module_name_list) if !ElixirScript.Module.has_alias?(module, {:__aliases__, meta2, List.last(aliases) |> List.wrap }) do - ElixirScript.State.add_alias(module_name_list, {:__aliases__, meta2, aliases}) + ElixirScript.State.add_alias(ElixirScript.Module.quoted_to_name({:__aliases__, [], module_name_list}), {:__aliases__, meta2, aliases}) end new_ast diff --git a/lib/elixir_script/preprocess/modules.ex b/lib/elixir_script/preprocess/modules.ex index a6071aac..ed512957 100644 --- a/lib/elixir_script/preprocess/modules.ex +++ b/lib/elixir_script/preprocess/modules.ex @@ -41,20 +41,20 @@ defmodule ElixirScript.Preprocess.Modules do end) end - def do_get_info({:defprotocol, _, [{:__aliases__, _, name}, [do: {:__block__, context, spec}]]}) do - ElixirScript.State.add_protocol(name, {:__block__, context, spec}) + def do_get_info({:defprotocol, _, [{:__aliases__, _, _} = the_alias, [do: {:__block__, context, spec}]]}) do + ElixirScript.State.add_protocol(ElixirScript.Module.quoted_to_name(the_alias), {:__block__, context, spec}) end - def do_get_info({:defprotocol, _, [{:__aliases__, _, name}, [do: spec]]}) do - ElixirScript.State.add_protocol(name, {:__block__, [], [spec]}) + def do_get_info({:defprotocol, _, [{:__aliases__, _, _} = the_alias, [do: spec]]}) do + ElixirScript.State.add_protocol(ElixirScript.Module.quoted_to_name(the_alias), {:__block__, [], [spec]}) end - def do_get_info({:defimpl, _, [ {:__aliases__, _, protocol}, [for: type], [do: {:__block__, context, spec}] ]}) when not protocol in @standard_lib_protocols do - ElixirScript.State.add_protocol_impl(protocol, type, {:__block__, context, spec}) + def do_get_info({:defimpl, _, [ {:__aliases__, _, protocol} = the_alias, [for: type], [do: {:__block__, context, spec}] ]}) when not protocol in @standard_lib_protocols do + ElixirScript.State.add_protocol_impl(ElixirScript.Module.quoted_to_name(the_alias), type, {:__block__, context, spec}) end - def do_get_info({:defimpl, _, [ {:__aliases__, _, protocol}, [for: type], [do: spec] ]}) when not protocol in @standard_lib_protocols do - ElixirScript.State.add_protocol_impl(protocol, type, {:__block__, [], [spec]}) + def do_get_info({:defimpl, _, [ {:__aliases__, _, protocol} = the_alias, [for: type], [do: spec] ]}) when not protocol in @standard_lib_protocols do + ElixirScript.State.add_protocol_impl(ElixirScript.Module.quoted_to_name(the_alias), type, {:__block__, [], [spec]}) end def do_get_info({:defmodule, _, [{:__aliases__, _, [:ElixirScript, :Temp]}, [do: body]]} = ast) do @@ -65,7 +65,7 @@ defmodule ElixirScript.Preprocess.Modules do body end - mod = %ElixirScript.Module{ name: [:ElixirScript, :Temp] , body: body } + mod = %ElixirScript.Module{ name: ElixirScript.Temp , body: body } State.add_module(mod) ast @@ -89,8 +89,7 @@ defmodule ElixirScript.Preprocess.Modules do end aliases = Set.union(aliases, requires.aliases) |> Set.union(imports.aliases) - - mod = %ElixirScript.Module{ name: module_name_list, body: body, + mod = %ElixirScript.Module{ name: ElixirScript.Module.quoted_to_name({:__aliases__, [], module_name_list}) , body: body, functions: functions, macros: macros, aliases: aliases, requires: requires.requires, imports: imports.imports, js_imports: js_imports } @@ -114,11 +113,9 @@ defmodule ElixirScript.Preprocess.Modules do case x do {:defmodule, _, [{:__aliases__, _, module_name_list2}, [do: body2]]} -> body2 = make_inner_module_aliases(module_name_list2, body2) - inner_alias = add_module_to_state(module_name_list, module_name_list2, body2) + add_module_to_state(module_name_list, module_name_list2, body2) - [ - inner_alias - ] + [] _ -> x end @@ -128,12 +125,9 @@ defmodule ElixirScript.Preprocess.Modules do {:__block__, meta2, list2} {:defmodule, _, [{:__aliases__, meta2, module_name_list2}, [do: body2]]} -> body2 = make_inner_module_aliases(module_name_list2, body2) - inner_alias = add_module_to_state(module_name_list, module_name_list2, body2) + add_module_to_state(module_name_list, module_name_list2, body2) - {:__block__, meta2, [ - inner_alias - ] - } + {:__block__, meta2, [] } _ -> body end @@ -147,13 +141,12 @@ defmodule ElixirScript.Preprocess.Modules do imports = get_imports_from_module(body2) js_imports = get_js_imports_from_module(body2) - inner_alias = {:alias, [], [{:__aliases__, [alias: false], module_name_list ++ module_name_list2}]} {inner_alias_atom, _ } = Code.eval_quoted({:__aliases__, [alias: false], module_name_list ++ module_name_list2}) aliases = Set.put(aliases, {inner_alias_atom, inner_alias_atom}) aliases = Set.union(aliases, requires.aliases) |> Set.union(imports.aliases) - mod = %ElixirScript.Module{ name: module_name_list2, body: body2, + mod = %ElixirScript.Module{ name: ElixirScript.Module.quoted_to_name({:__aliases__, [], module_name_list2}), body: body2, functions: functions, macros: macros, aliases: aliases, requires: requires.requires, imports: imports.imports, js_imports: js_imports } @@ -161,13 +154,11 @@ defmodule ElixirScript.Preprocess.Modules do State.delete_module(mod) end - mod = %ElixirScript.Module{ name: module_name_list ++ module_name_list2, body: body2, + mod = %ElixirScript.Module{ name: ElixirScript.Module.quoted_to_name({:__aliases__, [], module_name_list ++ module_name_list2}), body: body2, functions: functions, macros: macros, aliases: aliases, requires: requires.requires } State.add_module(mod) - - inner_alias end diff --git a/lib/elixir_script/state.ex b/lib/elixir_script/state.ex index 853e822f..31bf1a76 100644 --- a/lib/elixir_script/state.ex +++ b/lib/elixir_script/state.ex @@ -77,52 +77,53 @@ defmodule ElixirScript.State do end def get_module(module) when is_atom(module) do - module - |> Atom.to_string - |> String.split(".") - |> tl - |> Enum.map(fn x -> String.to_atom(x) end) - |> get_module - end - - - def get_module(module_name_list) do state = Agent.get(__MODULE__, &(&1)) - do_get_module(state, module_name_list) + do_get_module(state, module) end - defp do_get_module(state, module) when is_atom(module) do - module_name_list = - module - |> Atom.to_string - |> String.split(".") - |> tl - |> Enum.map(fn x -> String.to_atom(x) end) - do_get_module(state, module_name_list) + def get_module(module_name_list) when is_list(module_name_list) do + state = Agent.get(__MODULE__, &(&1)) + do_get_module(state, ElixirScript.Module.quoted_to_name({:__aliases__, [], module_name_list})) end - defp do_get_module(state, module_name_list) do + defp do_get_module(state, name) do Enum.find(Set.to_list(state.modules), fn x -> - x.name == module_name_list + x.name == name end) end - def add_alias(module_name_list, name) do - module = get_module(module_name_list) + def add_alias(module_name, module_alias) do + module = get_module(module_name) if module do - {main, _} = Code.eval_quoted(name) - {:__aliases__, _, aliases } = name - {the_alias, _} = Code.eval_quoted({:__aliases__, [alias: false], List.last(aliases) |> List.wrap }) - delete_module(module) + module = %{module | aliases: Set.put(module.aliases, {module_alias, module_name}) } + add_module(module) + end + end - module = %{module | aliases: Set.put(module.aliases, {the_alias, main}) } + def add_module_reference(module_name, module_ref) do + module = get_module(module_name) + + if module do + delete_module(module) + module = %{ module | module_refs: module.module_refs ++ [module_ref] } add_module(module) end end + def get_module_references(module_name) do + module = get_module(module_name) + + if module do + module.module_refs + |> Enum.uniq + else + [] + end + end + def process_imports do Agent.update(__MODULE__, fn state -> modules = @@ -163,6 +164,14 @@ defmodule ElixirScript.State do ElixirScript.Module.functions(module) ++ ElixirScript.Module.macros(module) -- Keyword.keys(list) end + def list_modules() do + Agent.get(__MODULE__, fn(x) -> + Enum.map(x.modules, fn(y) -> + y.name + end) + end) + end + def stop do Agent.stop(__MODULE__) end diff --git a/lib/elixir_script/translator.ex b/lib/elixir_script/translator.ex index f1eb0777..f235da69 100644 --- a/lib/elixir_script/translator.ex +++ b/lib/elixir_script/translator.ex @@ -93,8 +93,7 @@ defmodule ElixirScript.Translator do end defp do_translate({:%, _, [alias_info, data]}, env) do - {_, _, name} = alias_info - Struct.new_struct(name, data, env) + Struct.new_struct(alias_info, data, env) end defp do_translate({:%{}, _, [{:|, _, [map, data]}]}, env) do @@ -236,20 +235,12 @@ defmodule ElixirScript.Translator do %ElixirScript.Translator.Group{} end - defp do_translate({:alias, _, [alias_info, options]}, _) when is_tuple(alias_info) do - Import.make_alias_import(alias_info, options) - end - - defp do_translate({:alias, _, [alias_info]}, _) when is_tuple(alias_info) do - Import.make_alias_import(alias_info, []) - end - - defp do_translate({:require, _, [alias_info, options]}, _) do - Import.make_alias_import(alias_info, options) + defp do_translate({:alias, _, _}, _) do + %ElixirScript.Translator.Group{} end - defp do_translate({:require, _, [alias_info]}, _) do - Import.make_alias_import(alias_info, []) + defp do_translate({:require, _, _}, _) do + %ElixirScript.Translator.Group{} end defp do_translate({:case, _, [condition, [do: clauses]]}, env) do @@ -331,7 +322,7 @@ defmodule ElixirScript.Translator do if imported_module do imported_module = ElixirScript.State.get_module(imported_module) - Function.make_function_call({:__aliases__, [], List.last(imported_module.name) |> List.wrap }, name, params, env) + Function.make_function_call(ElixirScript.Module.name_to_quoted(imported_module.name) , name, params, env) else Function.make_function_call(name, params, env) end diff --git a/lib/elixir_script/translator/function.ex b/lib/elixir_script/translator/function.ex index 6790624b..a974acfd 100644 --- a/lib/elixir_script/translator/function.ex +++ b/lib/elixir_script/translator/function.ex @@ -174,19 +174,18 @@ defmodule ElixirScript.Translator.Function do def make_function_or_property_call(module_name, function_name, env) do the_name = case update_alias(module_name) do - {:__aliases__, _, name} -> - name + {:__aliases__, _, _} = name -> + module_name = ElixirScript.Module.quoted_to_name(name) + get_name_js_ast(module_name) + {name, _, _} when is_atom(name) -> - name + get_name_js_ast(name) + {{:., _, [_module_name, _function_name]}, _, _params } = ast -> ast + name -> - case to_string(name) do - "Elixir." <> actual_name -> - actual_name - _ -> - name - end + name end JS.call_expression( @@ -215,20 +214,16 @@ defmodule ElixirScript.Translator.Function do def make_function_call(module_name, function_name, params, env) do the_name = case update_alias(module_name) do {:__aliases__, _, name} -> - name + module_name = ElixirScript.Module.quoted_to_name(name) + get_name_js_ast(module_name) {name, _, _} when is_atom(name) -> - name + get_name_js_ast(name) {{:., _, [_, _]}, _, _ } = ast -> ast {{:., _, [{:__aliases__, _, _}]}, _, _} = ast -> ast name -> - case to_string(name) do - "Elixir." <> actual_name -> - actual_name - _ -> - name - end + name end Utils.make_call_expression(the_name, Utils.filter_name(function_name), params, env) @@ -313,4 +308,36 @@ defmodule ElixirScript.Translator.Function do list ++ [last_item] end end + + defp get_name_js_ast([Elixir | _] = list) do + list + end + + defp get_name_js_ast(module_name) when is_list(module_name) do + ElixirScript.Module.quoted_to_name({:__aliases__, [], module_name}) + |> get_name_js_ast + end + + defp get_name_js_ast(module_name) do + cond do + ElixirScript.State.get_module(module_name) -> + ElixirScript.State.add_module_reference(Process.get(:current_module), module_name) + ElixirScript.Module.name_to_js_name(module_name) + + ElixirScript.Module.has_alias?(ElixirScript.State.get_module(Process.get(:current_module)), module_name) -> + module = ElixirScript.State.get_module(Process.get(:current_module)) + {_, module_name } = ElixirScript.Module.get_alias(module, module_name) + ElixirScript.State.add_module_reference(Process.get(:current_module), module_name) + ElixirScript.Module.name_to_js_name(module_name) + + true -> + case Atom.to_string(module_name) do + "Elixir." <> _ -> + {:__aliases__, _, name } = ElixirScript.Module.name_to_quoted(module_name) + name + _ -> + module_name + end + end + end end diff --git a/lib/elixir_script/translator/import.ex b/lib/elixir_script/translator/import.ex index 21c7d37f..36187203 100644 --- a/lib/elixir_script/translator/import.ex +++ b/lib/elixir_script/translator/import.ex @@ -3,7 +3,19 @@ defmodule ElixirScript.Translator.Import do alias ESTree.Tools.Builder, as: JS alias ElixirScript.State + def make_import(module_name) do + import_specifier = JS.import_namespace_specifier( + JS.identifier(ElixirScript.Module.name_to_js_name(module_name)) + ) + + JS.import_declaration( + [import_specifier], + JS.literal("#{ElixirScript.Module.name_to_js_file_name(module_name)}") + ) + end + def make_alias_import(alias_info, options) do + {_, _, name} = alias_info default = Dict.get(options, :default, false) diff --git a/lib/elixir_script/translator/module.ex b/lib/elixir_script/translator/module.ex index 474025fa..bc222541 100644 --- a/lib/elixir_script/translator/module.ex +++ b/lib/elixir_script/translator/module.ex @@ -9,29 +9,29 @@ defmodule ElixirScript.Translator.Module do alias ElixirScript.Translator.Function alias ElixirScript.Translator.Primitive - def make_module([:ElixirScript, :Temp], body, env) do - [%JSModule{ name: [:ElixirScript, :Temp], body: translate_body(body, env) |> Utils.inflate_groups }] + def make_module(ElixirScript.Temp, body, env) do + [%JSModule{ name: ElixirScript.Temp, body: translate_body(body, env) |> Utils.inflate_groups }] end - def make_module(module_name_list, nil, env) do - [%JSModule{ name: module_name_list, body: List.wrap(create__module__(module_name_list, env)) }] + def make_module(module, nil, env) do + [%JSModule{ name: module, body: List.wrap(create__module__(module, env)) }] end - def make_module(module_name_list, body, env) do + def make_module(module, body, env) do body = Using.process(body, env) - { body, aliases } = Aliases.process(module_name_list, body, env) - { body, functions } = extract_functions_from_module(body) { exported_functions, private_functions } = process_functions(functions, env) body = translate_body(body, env) + modules_refs = ElixirScript.State.get_module_references(module) + {imports, body} = extract_imports_from_body(body) {structs, body} = extract_structs_from_body(body) #Add imports found from walking the ast #and make sure to only put one declaration per alias - imports = process_imports(imports, aliases) + imports = process_imports(imports, modules_refs) imports = imports.imports #Collect all the functions so that we can process their arity @@ -47,7 +47,7 @@ defmodule ElixirScript.Translator.Module do body = Utils.inflate_groups(body) exported_object = JS.object_expression( - make_defstruct_property(module_name_list, structs) ++ + make_defstruct_property(module, structs) ++ Enum.map(exported_functions, fn({key, _value}) -> JS.property(JS.identifier(key), JS.identifier(key), :init, true) end) @@ -68,8 +68,8 @@ defmodule ElixirScript.Translator.Module do result = [ %JSModule{ - name: module_name_list, - body: imports ++ List.wrap(create__module__(module_name_list, env)) ++ structs ++ private_functions ++ exported_functions ++ body ++ [default] + name: ElixirScript.Module.quoted_to_name({:__aliases__, [], module }), + body: imports ++ List.wrap(create__module__(module, env)) ++ structs ++ private_functions ++ exported_functions ++ body ++ [default] } ] ++ List.flatten(modules) @@ -155,12 +155,12 @@ defmodule ElixirScript.Translator.Module do defp make_defstruct_property(module_name, [the_struct]) do case the_struct do %ESTree.VariableDeclaration{declarations: [%ESTree.VariableDeclarator{id: %ESTree.Identifier{name: name} } ] } when name in [:defstruct, :defexception] -> - [JS.property(JS.identifier(List.last(module_name)), JS.identifier(name), :init)] + [JS.property(JS.identifier(ElixirScript.Module.name_to_js_name(module_name)), JS.identifier(name), :init)] end end - def process_imports(imports, aliases) do - imports ++ make_imports(aliases) + def process_imports(imports, module_refs) do + imports ++ make_imports(module_refs) |> Enum.into(HashSet.new) |> Enum.reduce(HashSet.new, fn(x, acc)-> HashSet.put(acc, x) @@ -209,29 +209,17 @@ defmodule ElixirScript.Translator.Module do JS.variable_declaration([declarator], :const) end - def create__module__(module_name_list, _) do - module_name = Enum.map(module_name_list, &Atom.to_string(&1)) - |> Enum.join(".") - |> String.to_atom - + def create__module__(module, _) do declarator = JS.variable_declarator( JS.identifier(:__MODULE__), - Primitive.make_atom(module_name) + Primitive.make_atom(module) ) JS.variable_declaration([declarator], :const) end def make_imports(enum) do - Enum.map(enum, fn - - {as, name} -> - name = Atom.to_string(name) |> String.split(".") |> tl |> Enum.map(fn(x) -> String.to_atom(x) end) - as = Atom.to_string(as) |> String.split(".") |> tl |> Enum.map(fn(x) -> String.to_atom(x) end) - ElixirScript.Translator.Import.make_alias_import({ nil, nil, name }, [as: { nil, nil, as }]) - x -> - ElixirScript.Translator.Import.make_alias_import({ nil, nil, List.wrap(x) }, []) - end) + Enum.map(enum, fn(x) -> ElixirScript.Translator.Import.make_import(x) end) end end diff --git a/lib/elixir_script/translator/protocol.ex b/lib/elixir_script/translator/protocol.ex index 7c782eba..472b3055 100644 --- a/lib/elixir_script/translator/protocol.ex +++ b/lib/elixir_script/translator/protocol.ex @@ -53,7 +53,7 @@ defmodule ElixirScript.Translator.Protocol do |> JS.object_expression declarator = JS.variable_declarator( - JS.identifier(List.last(name)), + JS.identifier(ElixirScript.Module.name_to_js_name(name)), JS.call_expression( JS.member_expression( JS.identifier(:Elixir), @@ -100,7 +100,7 @@ defmodule ElixirScript.Translator.Protocol do JS.identifier(:defimpl) ) ), - [JS.identifier(List.last(name)), type, object] + [JS.identifier(ElixirScript.Module.name_to_js_name(name)), type, object] ) {imports, body, [impl]} @@ -140,7 +140,7 @@ defmodule ElixirScript.Translator.Protocol do end defp create_module(name, spec, impls, imports, body, env) do - default = JS.export_default_declaration(JS.identifier(List.last(name))) + default = JS.export_default_declaration(JS.identifier(ElixirScript.Module.name_to_js_name(name))) %JSModule{ name: name, diff --git a/lib/elixir_script/translator/struct.ex b/lib/elixir_script/translator/struct.ex index 17a8c326..5519d52f 100644 --- a/lib/elixir_script/translator/struct.ex +++ b/lib/elixir_script/translator/struct.ex @@ -8,24 +8,19 @@ defmodule ElixirScript.Translator.Struct do def get_struct_class(module_name, env) do current_module = ElixirScript.State.get_module(Process.get(:current_module)) - name = List.last(module_name) - - the_alias = ElixirScript.Module.get_alias(current_module, module_name) + name = ElixirScript.Module.quoted_to_name(module_name) + the_alias = ElixirScript.Module.get_alias(current_module, name) if the_alias do { _, name } = the_alias - - name = Atom.to_string(name) - |> String.split(".") - |> List.last end - if the_alias == nil && ElixirScript.State.get_module(module_name) == nil do + if the_alias == nil && ElixirScript.State.get_module(ElixirScript.Module.quoted_to_name(module_name)) == nil do Utils.make_module_expression_tree(module_name, false, env) else JS.member_expression( - JS.identifier(List.last(module_name)), - JS.identifier(name) + JS.identifier(ElixirScript.Module.name_to_js_name(name)), + JS.identifier(ElixirScript.Module.name_to_js_name(name)) ) end diff --git a/lib/elixir_script/translator/utils.ex b/lib/elixir_script/translator/utils.ex index 7387e384..94c16b60 100644 --- a/lib/elixir_script/translator/utils.ex +++ b/lib/elixir_script/translator/utils.ex @@ -4,7 +4,7 @@ defmodule ElixirScript.Translator.Utils do alias ElixirScript.Translator def inflate_groups(body) do - Enum.map(body, fn(x) -> + Enum.map(body, fn(x) -> case x do %ElixirScript.Translator.Group{body: group_body} -> group_body @@ -102,26 +102,26 @@ defmodule ElixirScript.Translator.Utils do JS.member_expression( Translator.translate(ast, env), build_function_name_ast(function_name), - computed + computed ) {{:., _, [{:__aliases__, _, _}]}, _, _} = ast -> JS.member_expression( Translator.translate(ast, env), build_function_name_ast(function_name), - computed + computed ) {:., _, _} = ast -> JS.member_expression( Translator.translate(ast, env), build_function_name_ast(function_name), - computed + computed ) _ -> JS.member_expression( JS.identifier(module_name), build_function_name_ast(function_name), computed - ) + ) end end diff --git a/mix.exs b/mix.exs index ee583be5..5052e2d9 100644 --- a/mix.exs +++ b/mix.exs @@ -51,7 +51,7 @@ defmodule ElixirScript.Mixfile do defp package do [ - files: ["lib", "priv/elixir.js", "mix.exs", "README*", "readme*", "LICENSE*", "license*", "CHANGELOG*"], + files: ["lib", "priv/Elixir.js", "mix.exs", "README*", "readme*", "LICENSE*", "license*", "CHANGELOG*"], maintainers: ["Bryan Joseph"], licenses: ["MIT"], links: %{ @@ -80,14 +80,14 @@ defmodule ElixirScript.Mixfile do end { _ , _ } = System.cmd("node", ["node_modules/gulp/bin/gulp.js", "dist_build"]) - { elixir_js, _ } = System.cmd("node", ["node_modules/rollup/bin/rollup", "./src/javascript/dist_build/elixir.js"]) - File.write!("priv/elixir.js", elixir_js) + { elixir_js, _ } = System.cmd("node", ["node_modules/rollup/bin/rollup", "./src/javascript/dist_build/Elixir.js"]) + File.write!("priv/Elixir.js", elixir_js) { _ , _ } = System.cmd("node", ["node_modules/gulp/bin/gulp.js", "dist_add_source_map"]) File.mkdir_p(folder_name <> "/bin") File.cp!("elixirscript", "#{folder_name}/bin/elixirscript") - File.cp_r!("priv", "#{folder_name}") - File.cp_r!("LICENSE", "#{folder_name}/LICENSE") + File.cp!("priv/Elixir.js", "#{folder_name}/Elixir.js") + File.cp!("LICENSE", "#{folder_name}/LICENSE") System.cmd("tar", ["czf", archive_file_name, folder_name]) diff --git a/priv/elixir.js b/priv/elixir.js index e2ad175d..07d90f1b 100644 --- a/priv/elixir.js +++ b/priv/elixir.js @@ -4566,4 +4566,4 @@ self.processes = self.processes || new ProcessSystem(); const Core = C; export { Core, Kernel, Atom, Enum, Integer, List, Range, Tuple, Agent, Keyword, base as Base, String$1 as String, bitwise as Bitwise, Enumerable, Collectable, Inspect, map as Map, set as Set, MapSet, VirtualDOM, view as View }; -//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiIiwic291cmNlcyI6WyJlbGl4aXIuanMiXSwic291cmNlc0NvbnRlbnQiOlsiZnVuY3Rpb24gY2FsbF9wcm9wZXJ0eShpdGVtLCBwcm9wZXJ0eSkge1xuICBpZiAocHJvcGVydHkgaW4gaXRlbSkge1xuICAgIGl0ZW1bcHJvcGVydHldO1xuICAgIGlmIChpdGVtW3Byb3BlcnR5XSBpbnN0YW5jZW9mIEZ1bmN0aW9uKSB7XG4gICAgICByZXR1cm4gaXRlbVtwcm9wZXJ0eV0oKTtcbiAgICB9IGVsc2Uge1xuICAgICAgcmV0dXJuIGl0ZW1bcHJvcGVydHldO1xuICAgIH1cbiAgfSBlbHNlIGlmIChTeW1ib2wuZm9yKHByb3BlcnR5KSBpbiBpdGVtKSB7XG4gICAgbGV0IHByb3AgPSBTeW1ib2wuZm9yKHByb3BlcnR5KTtcbiAgICBpZiAoaXRlbVtwcm9wXSBpbnN0YW5jZW9mIEZ1bmN0aW9uKSB7XG4gICAgICByZXR1cm4gaXRlbVtwcm9wXSgpO1xuICAgIH0gZWxzZSB7XG4gICAgICByZXR1cm4gaXRlbVtwcm9wXTtcbiAgICB9XG4gIH1cblxuICB0aHJvdyBuZXcgRXJyb3IoYFByb3BlcnR5ICR7IHByb3BlcnR5IH0gbm90IGZvdW5kIGluICR7IGl0ZW0gfWApO1xufVxuXG5jbGFzcyBUdXBsZSQxIHtcblxuICBjb25zdHJ1Y3RvciguLi5hcmdzKSB7XG4gICAgdGhpcy52YWx1ZXMgPSBPYmplY3QuZnJlZXplKGFyZ3MpO1xuICB9XG5cbiAgZ2V0KGluZGV4KSB7XG4gICAgcmV0dXJuIHRoaXMudmFsdWVzW2luZGV4XTtcbiAgfVxuXG4gIGNvdW50KCkge1xuICAgIHJldHVybiB0aGlzLnZhbHVlcy5sZW5ndGg7XG4gIH1cblxuICBbU3ltYm9sLml0ZXJhdG9yXSgpIHtcbiAgICByZXR1cm4gdGhpcy52YWx1ZXNbU3ltYm9sLml0ZXJhdG9yXSgpO1xuICB9XG5cbiAgdG9TdHJpbmcoKSB7XG4gICAgdmFyIGksXG4gICAgICAgIHMgPSBcIlwiO1xuICAgIGZvciAoaSA9IDA7IGkgPCB0aGlzLnZhbHVlcy5sZW5ndGg7IGkrKykge1xuICAgICAgaWYgKHMgIT09IFwiXCIpIHtcbiAgICAgICAgcyArPSBcIiwgXCI7XG4gICAgICB9XG4gICAgICBzICs9IHRoaXMudmFsdWVzW2ldLnRvU3RyaW5nKCk7XG4gICAgfVxuXG4gICAgcmV0dXJuIFwie1wiICsgcyArIFwifVwiO1xuICB9XG5cbn1cblxubGV0IHByb2Nlc3NfY291bnRlciA9IC0xO1xuXG5jbGFzcyBQSUQge1xuICBjb25zdHJ1Y3RvcigpIHtcbiAgICBwcm9jZXNzX2NvdW50ZXIgPSBwcm9jZXNzX2NvdW50ZXIgKyAxO1xuICAgIHRoaXMuaWQgPSBwcm9jZXNzX2NvdW50ZXI7XG4gIH1cblxuICB0b1N0cmluZygpIHtcbiAgICByZXR1cm4gXCJQSUQjPDAuXCIgKyB0aGlzLmlkICsgXCIuMD5cIjtcbiAgfVxufVxuXG5jbGFzcyBJbnRlZ2VyJDEge31cbmNsYXNzIEZsb2F0IHt9XG5cbi8qIEBmbG93ICovXG5cbmNsYXNzIFZhcmlhYmxlIHtcblxuICBjb25zdHJ1Y3RvcihuYW1lID0gbnVsbCkge1xuICAgIHRoaXMubmFtZSA9IG5hbWU7XG4gIH1cbn1cblxuY2xhc3MgV2lsZGNhcmQge1xuICBjb25zdHJ1Y3RvcigpIHt9XG59XG5cbmNsYXNzIFN0YXJ0c1dpdGgge1xuXG4gIGNvbnN0cnVjdG9yKHByZWZpeCkge1xuICAgIHRoaXMucHJlZml4ID0gcHJlZml4O1xuICB9XG59XG5cbmNsYXNzIENhcHR1cmUge1xuXG4gIGNvbnN0cnVjdG9yKHZhbHVlKSB7XG4gICAgdGhpcy52YWx1ZSA9IHZhbHVlO1xuICB9XG59XG5cbmNsYXNzIEhlYWRUYWlsIHtcbiAgY29uc3RydWN0b3IoKSB7fVxufVxuXG5jbGFzcyBUeXBlIHtcblxuICBjb25zdHJ1Y3Rvcih0eXBlLCBvYmpQYXR0ZXJuID0ge30pIHtcbiAgICB0aGlzLnR5cGUgPSB0eXBlO1xuICAgIHRoaXMub2JqUGF0dGVybiA9IG9ialBhdHRlcm47XG4gIH1cbn1cblxuY2xhc3MgQm91bmQge1xuXG4gIGNvbnN0cnVjdG9yKHZhbHVlKSB7XG4gICAgdGhpcy52YWx1ZSA9IHZhbHVlO1xuICB9XG59XG5cbmZ1bmN0aW9uIHZhcmlhYmxlKG5hbWUgPSBudWxsKSB7XG4gIHJldHVybiBuZXcgVmFyaWFibGUobmFtZSk7XG59XG5cbmZ1bmN0aW9uIHdpbGRjYXJkKCkge1xuICByZXR1cm4gbmV3IFdpbGRjYXJkKCk7XG59XG5cbmZ1bmN0aW9uIHN0YXJ0c1dpdGgocHJlZml4KSB7XG4gIHJldHVybiBuZXcgU3RhcnRzV2l0aChwcmVmaXgpO1xufVxuXG5mdW5jdGlvbiBjYXB0dXJlKHZhbHVlKSB7XG4gIHJldHVybiBuZXcgQ2FwdHVyZSh2YWx1ZSk7XG59XG5cbmZ1bmN0aW9uIGhlYWRUYWlsKCkge1xuICByZXR1cm4gbmV3IEhlYWRUYWlsKCk7XG59XG5cbmZ1bmN0aW9uIHR5cGUodHlwZSwgb2JqUGF0dGVybiA9IHt9KSB7XG4gIHJldHVybiBuZXcgVHlwZSh0eXBlLCBvYmpQYXR0ZXJuKTtcbn1cblxuZnVuY3Rpb24gYm91bmQodmFsdWUpIHtcbiAgcmV0dXJuIG5ldyBCb3VuZCh2YWx1ZSk7XG59XG5cbmZ1bmN0aW9uIGlzX251bWJlciQxKHZhbHVlKSB7XG4gIHJldHVybiB0eXBlb2YgdmFsdWUgPT09ICdudW1iZXInO1xufVxuXG5mdW5jdGlvbiBpc19zdHJpbmcodmFsdWUpIHtcbiAgcmV0dXJuIHR5cGVvZiB2YWx1ZSA9PT0gJ3N0cmluZyc7XG59XG5cbmZ1bmN0aW9uIGlzX2Jvb2xlYW4kMSh2YWx1ZSkge1xuICByZXR1cm4gdHlwZW9mIHZhbHVlID09PSAnYm9vbGVhbic7XG59XG5cbmZ1bmN0aW9uIGlzX3N5bWJvbCh2YWx1ZSkge1xuICByZXR1cm4gdHlwZW9mIHZhbHVlID09PSAnc3ltYm9sJztcbn1cblxuZnVuY3Rpb24gaXNfbnVsbCh2YWx1ZSkge1xuICByZXR1cm4gdmFsdWUgPT09IG51bGw7XG59XG5cbmZ1bmN0aW9uIGlzX3VuZGVmaW5lZCh2YWx1ZSkge1xuICByZXR1cm4gdHlwZW9mIHZhbHVlID09PSAndW5kZWZpbmVkJztcbn1cblxuZnVuY3Rpb24gaXNfZnVuY3Rpb24kMSh2YWx1ZSkge1xuICByZXR1cm4gT2JqZWN0LnByb3RvdHlwZS50b1N0cmluZy5jYWxsKHZhbHVlKSA9PSAnW29iamVjdCBGdW5jdGlvbl0nO1xufVxuXG5mdW5jdGlvbiBpc192YXJpYWJsZSh2YWx1ZSkge1xuICByZXR1cm4gdmFsdWUgaW5zdGFuY2VvZiBWYXJpYWJsZTtcbn1cblxuZnVuY3Rpb24gaXNfd2lsZGNhcmQodmFsdWUpIHtcbiAgcmV0dXJuIHZhbHVlIGluc3RhbmNlb2YgV2lsZGNhcmQ7XG59XG5cbmZ1bmN0aW9uIGlzX2hlYWRUYWlsKHZhbHVlKSB7XG4gIHJldHVybiB2YWx1ZSBpbnN0YW5jZW9mIEhlYWRUYWlsO1xufVxuXG5mdW5jdGlvbiBpc19jYXB0dXJlKHZhbHVlKSB7XG4gIHJldHVybiB2YWx1ZSBpbnN0YW5jZW9mIENhcHR1cmU7XG59XG5cbmZ1bmN0aW9uIGlzX3R5cGUodmFsdWUpIHtcbiAgcmV0dXJuIHZhbHVlIGluc3RhbmNlb2YgVHlwZTtcbn1cblxuZnVuY3Rpb24gaXNfc3RhcnRzV2l0aCh2YWx1ZSkge1xuICByZXR1cm4gdmFsdWUgaW5zdGFuY2VvZiBTdGFydHNXaXRoO1xufVxuXG5mdW5jdGlvbiBpc19ib3VuZCh2YWx1ZSkge1xuICByZXR1cm4gdmFsdWUgaW5zdGFuY2VvZiBCb3VuZDtcbn1cblxuZnVuY3Rpb24gaXNfb2JqZWN0KHZhbHVlKSB7XG4gIHJldHVybiB0eXBlb2YgdmFsdWUgPT09ICdvYmplY3QnO1xufVxuXG5mdW5jdGlvbiBpc19hcnJheSh2YWx1ZSkge1xuICByZXR1cm4gQXJyYXkuaXNBcnJheSh2YWx1ZSk7XG59XG5cbnZhciBDaGVja3MgPSB7XG4gIGlzX251bWJlcjogaXNfbnVtYmVyJDEsXG4gIGlzX3N0cmluZyxcbiAgaXNfYm9vbGVhbjogaXNfYm9vbGVhbiQxLFxuICBpc19zeW1ib2wsXG4gIGlzX251bGwsXG4gIGlzX3VuZGVmaW5lZCxcbiAgaXNfZnVuY3Rpb246IGlzX2Z1bmN0aW9uJDEsXG4gIGlzX3ZhcmlhYmxlLFxuICBpc193aWxkY2FyZCxcbiAgaXNfaGVhZFRhaWwsXG4gIGlzX2NhcHR1cmUsXG4gIGlzX3R5cGUsXG4gIGlzX3N0YXJ0c1dpdGgsXG4gIGlzX2JvdW5kLFxuICBpc19vYmplY3QsXG4gIGlzX2FycmF5XG59O1xuXG5mdW5jdGlvbiByZXNvbHZlU3ltYm9sKHBhdHRlcm4pIHtcbiAgcmV0dXJuIGZ1bmN0aW9uICh2YWx1ZSkge1xuICAgIHJldHVybiBDaGVja3MuaXNfc3ltYm9sKHZhbHVlKSAmJiB2YWx1ZSA9PT0gcGF0dGVybjtcbiAgfTtcbn1cblxuZnVuY3Rpb24gcmVzb2x2ZVN0cmluZyhwYXR0ZXJuKSB7XG4gIHJldHVybiBmdW5jdGlvbiAodmFsdWUpIHtcbiAgICByZXR1cm4gQ2hlY2tzLmlzX3N0cmluZyh2YWx1ZSkgJiYgdmFsdWUgPT09IHBhdHRlcm47XG4gIH07XG59XG5cbmZ1bmN0aW9uIHJlc29sdmVOdW1iZXIocGF0dGVybikge1xuICByZXR1cm4gZnVuY3Rpb24gKHZhbHVlKSB7XG4gICAgcmV0dXJuIENoZWNrcy5pc19udW1iZXIodmFsdWUpICYmIHZhbHVlID09PSBwYXR0ZXJuO1xuICB9O1xufVxuXG5mdW5jdGlvbiByZXNvbHZlQm9vbGVhbihwYXR0ZXJuKSB7XG4gIHJldHVybiBmdW5jdGlvbiAodmFsdWUpIHtcbiAgICByZXR1cm4gQ2hlY2tzLmlzX2Jvb2xlYW4odmFsdWUpICYmIHZhbHVlID09PSBwYXR0ZXJuO1xuICB9O1xufVxuXG5mdW5jdGlvbiByZXNvbHZlRnVuY3Rpb24ocGF0dGVybikge1xuICByZXR1cm4gZnVuY3Rpb24gKHZhbHVlKSB7XG4gICAgcmV0dXJuIENoZWNrcy5pc19mdW5jdGlvbih2YWx1ZSkgJiYgdmFsdWUgPT09IHBhdHRlcm47XG4gIH07XG59XG5cbmZ1bmN0aW9uIHJlc29sdmVOdWxsKHBhdHRlcm4pIHtcbiAgcmV0dXJuIGZ1bmN0aW9uICh2YWx1ZSkge1xuICAgIHJldHVybiBDaGVja3MuaXNfbnVsbCh2YWx1ZSk7XG4gIH07XG59XG5cbmZ1bmN0aW9uIHJlc29sdmVCb3VuZChwYXR0ZXJuKSB7XG4gIHJldHVybiBmdW5jdGlvbiAodmFsdWUsIGFyZ3MpIHtcbiAgICBpZiAodHlwZW9mIHZhbHVlID09PSB0eXBlb2YgcGF0dGVybi52YWx1ZSAmJiB2YWx1ZSA9PT0gcGF0dGVybi52YWx1ZSkge1xuICAgICAgYXJncy5wdXNoKHZhbHVlKTtcbiAgICAgIHJldHVybiB0cnVlO1xuICAgIH1cblxuICAgIHJldHVybiBmYWxzZTtcbiAgfTtcbn1cblxuZnVuY3Rpb24gcmVzb2x2ZVdpbGRjYXJkKCkge1xuICByZXR1cm4gZnVuY3Rpb24gKCkge1xuICAgIHJldHVybiB0cnVlO1xuICB9O1xufVxuXG5mdW5jdGlvbiByZXNvbHZlVmFyaWFibGUoKSB7XG4gIHJldHVybiBmdW5jdGlvbiAodmFsdWUsIGFyZ3MpIHtcbiAgICBhcmdzLnB1c2godmFsdWUpO1xuICAgIHJldHVybiB0cnVlO1xuICB9O1xufVxuXG5mdW5jdGlvbiByZXNvbHZlSGVhZFRhaWwoKSB7XG4gIHJldHVybiBmdW5jdGlvbiAodmFsdWUsIGFyZ3MpIHtcbiAgICBpZiAoIUNoZWNrcy5pc19hcnJheSh2YWx1ZSkgfHwgdmFsdWUubGVuZ3RoIDwgMikge1xuICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH1cblxuICAgIGNvbnN0IGhlYWQgPSB2YWx1ZVswXTtcbiAgICBjb25zdCB0YWlsID0gdmFsdWUuc2xpY2UoMSk7XG5cbiAgICBhcmdzLnB1c2goaGVhZCk7XG4gICAgYXJncy5wdXNoKHRhaWwpO1xuXG4gICAgcmV0dXJuIHRydWU7XG4gIH07XG59XG5cbmZ1bmN0aW9uIHJlc29sdmVDYXB0dXJlKHBhdHRlcm4pIHtcbiAgY29uc3QgbWF0Y2hlcyA9IGJ1aWxkTWF0Y2gocGF0dGVybi52YWx1ZSk7XG5cbiAgcmV0dXJuIGZ1bmN0aW9uICh2YWx1ZSwgYXJncykge1xuICAgIGlmIChtYXRjaGVzKHZhbHVlLCBhcmdzKSkge1xuICAgICAgYXJncy5wdXNoKHZhbHVlKTtcbiAgICAgIHJldHVybiB0cnVlO1xuICAgIH1cblxuICAgIHJldHVybiBmYWxzZTtcbiAgfTtcbn1cblxuZnVuY3Rpb24gcmVzb2x2ZVN0YXJ0c1dpdGgocGF0dGVybikge1xuICBjb25zdCBwcmVmaXggPSBwYXR0ZXJuLnByZWZpeDtcblxuICByZXR1cm4gZnVuY3Rpb24gKHZhbHVlLCBhcmdzKSB7XG4gICAgaWYgKENoZWNrcy5pc19zdHJpbmcodmFsdWUpICYmIHZhbHVlLnN0YXJ0c1dpdGgocHJlZml4KSkge1xuICAgICAgYXJncy5wdXNoKHZhbHVlLnN1YnN0cmluZyhwcmVmaXgubGVuZ3RoKSk7XG4gICAgICByZXR1cm4gdHJ1ZTtcbiAgICB9XG5cbiAgICByZXR1cm4gZmFsc2U7XG4gIH07XG59XG5cbmZ1bmN0aW9uIHJlc29sdmVUeXBlKHBhdHRlcm4pIHtcbiAgcmV0dXJuIGZ1bmN0aW9uICh2YWx1ZSwgYXJncykge1xuICAgIGlmICh2YWx1ZSBpbnN0YW5jZW9mIHBhdHRlcm4udHlwZSkge1xuICAgICAgY29uc3QgbWF0Y2hlcyA9IGJ1aWxkTWF0Y2gocGF0dGVybi5vYmpQYXR0ZXJuKTtcbiAgICAgIHJldHVybiBtYXRjaGVzKHZhbHVlLCBhcmdzKSAmJiBhcmdzLnB1c2godmFsdWUpID4gMDtcbiAgICB9XG5cbiAgICByZXR1cm4gZmFsc2U7XG4gIH07XG59XG5cbmZ1bmN0aW9uIHJlc29sdmVBcnJheShwYXR0ZXJuKSB7XG4gIGNvbnN0IG1hdGNoZXMgPSBwYXR0ZXJuLm1hcCh4ID0+IGJ1aWxkTWF0Y2goeCkpO1xuXG4gIHJldHVybiBmdW5jdGlvbiAodmFsdWUsIGFyZ3MpIHtcbiAgICBpZiAoIUNoZWNrcy5pc19hcnJheSh2YWx1ZSkgfHwgdmFsdWUubGVuZ3RoICE9IHBhdHRlcm4ubGVuZ3RoKSB7XG4gICAgICByZXR1cm4gZmFsc2U7XG4gICAgfVxuXG4gICAgcmV0dXJuIHZhbHVlLmV2ZXJ5KGZ1bmN0aW9uICh2LCBpKSB7XG4gICAgICByZXR1cm4gbWF0Y2hlc1tpXSh2YWx1ZVtpXSwgYXJncyk7XG4gICAgfSk7XG4gIH07XG59XG5cbmZ1bmN0aW9uIHJlc29sdmVPYmplY3QocGF0dGVybikge1xuICBsZXQgbWF0Y2hlcyA9IHt9O1xuXG4gIGZvciAobGV0IGtleSBvZiBPYmplY3Qua2V5cyhwYXR0ZXJuKSkge1xuICAgIG1hdGNoZXNba2V5XSA9IGJ1aWxkTWF0Y2gocGF0dGVybltrZXldKTtcbiAgfVxuXG4gIHJldHVybiBmdW5jdGlvbiAodmFsdWUsIGFyZ3MpIHtcbiAgICBpZiAoIUNoZWNrcy5pc19vYmplY3QodmFsdWUpIHx8IHBhdHRlcm4ubGVuZ3RoID4gdmFsdWUubGVuZ3RoKSB7XG4gICAgICByZXR1cm4gZmFsc2U7XG4gICAgfVxuXG4gICAgZm9yIChsZXQga2V5IG9mIE9iamVjdC5rZXlzKHBhdHRlcm4pKSB7XG4gICAgICBpZiAoIShrZXkgaW4gdmFsdWUpIHx8ICFtYXRjaGVzW2tleV0odmFsdWVba2V5XSwgYXJncykpIHtcbiAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgfVxuICAgIH1cblxuICAgIHJldHVybiB0cnVlO1xuICB9O1xufVxuXG5mdW5jdGlvbiByZXNvbHZlTm9NYXRjaCgpIHtcbiAgcmV0dXJuIGZ1bmN0aW9uICgpIHtcbiAgICByZXR1cm4gZmFsc2U7XG4gIH07XG59XG5cbnZhciBSZXNvbHZlcnMgPSB7XG4gIHJlc29sdmVCb3VuZCxcbiAgcmVzb2x2ZVdpbGRjYXJkLFxuICByZXNvbHZlVmFyaWFibGUsXG4gIHJlc29sdmVIZWFkVGFpbCxcbiAgcmVzb2x2ZUNhcHR1cmUsXG4gIHJlc29sdmVTdGFydHNXaXRoLFxuICByZXNvbHZlVHlwZSxcbiAgcmVzb2x2ZUFycmF5LFxuICByZXNvbHZlT2JqZWN0LFxuICByZXNvbHZlTm9NYXRjaCxcbiAgcmVzb2x2ZVN5bWJvbCxcbiAgcmVzb2x2ZVN0cmluZyxcbiAgcmVzb2x2ZU51bWJlcixcbiAgcmVzb2x2ZUJvb2xlYW4sXG4gIHJlc29sdmVGdW5jdGlvbixcbiAgcmVzb2x2ZU51bGxcbn07XG5cbmZ1bmN0aW9uIGJ1aWxkTWF0Y2gocGF0dGVybikge1xuXG4gIGlmIChDaGVja3MuaXNfdmFyaWFibGUocGF0dGVybikpIHtcbiAgICByZXR1cm4gUmVzb2x2ZXJzLnJlc29sdmVWYXJpYWJsZShwYXR0ZXJuKTtcbiAgfVxuXG4gIGlmIChDaGVja3MuaXNfd2lsZGNhcmQocGF0dGVybikpIHtcbiAgICByZXR1cm4gUmVzb2x2ZXJzLnJlc29sdmVXaWxkY2FyZChwYXR0ZXJuKTtcbiAgfVxuXG4gIGlmIChDaGVja3MuaXNfdW5kZWZpbmVkKHBhdHRlcm4pKSB7XG4gICAgcmV0dXJuIFJlc29sdmVycy5yZXNvbHZlV2lsZGNhcmQocGF0dGVybik7XG4gIH1cblxuICBpZiAoQ2hlY2tzLmlzX2hlYWRUYWlsKHBhdHRlcm4pKSB7XG4gICAgcmV0dXJuIFJlc29sdmVycy5yZXNvbHZlSGVhZFRhaWwocGF0dGVybik7XG4gIH1cblxuICBpZiAoQ2hlY2tzLmlzX3N0YXJ0c1dpdGgocGF0dGVybikpIHtcbiAgICByZXR1cm4gUmVzb2x2ZXJzLnJlc29sdmVTdGFydHNXaXRoKHBhdHRlcm4pO1xuICB9XG5cbiAgaWYgKENoZWNrcy5pc19jYXB0dXJlKHBhdHRlcm4pKSB7XG4gICAgcmV0dXJuIFJlc29sdmVycy5yZXNvbHZlQ2FwdHVyZShwYXR0ZXJuKTtcbiAgfVxuXG4gIGlmIChDaGVja3MuaXNfYm91bmQocGF0dGVybikpIHtcbiAgICByZXR1cm4gUmVzb2x2ZXJzLnJlc29sdmVCb3VuZChwYXR0ZXJuKTtcbiAgfVxuXG4gIGlmIChDaGVja3MuaXNfdHlwZShwYXR0ZXJuKSkge1xuICAgIHJldHVybiBSZXNvbHZlcnMucmVzb2x2ZVR5cGUocGF0dGVybik7XG4gIH1cblxuICBpZiAoQ2hlY2tzLmlzX2FycmF5KHBhdHRlcm4pKSB7XG4gICAgcmV0dXJuIFJlc29sdmVycy5yZXNvbHZlQXJyYXkocGF0dGVybik7XG4gIH1cblxuICBpZiAoQ2hlY2tzLmlzX251bWJlcihwYXR0ZXJuKSkge1xuICAgIHJldHVybiBSZXNvbHZlcnMucmVzb2x2ZU51bWJlcihwYXR0ZXJuKTtcbiAgfVxuXG4gIGlmIChDaGVja3MuaXNfc3RyaW5nKHBhdHRlcm4pKSB7XG4gICAgcmV0dXJuIFJlc29sdmVycy5yZXNvbHZlU3RyaW5nKHBhdHRlcm4pO1xuICB9XG5cbiAgaWYgKENoZWNrcy5pc19ib29sZWFuKHBhdHRlcm4pKSB7XG4gICAgcmV0dXJuIFJlc29sdmVycy5yZXNvbHZlQm9vbGVhbihwYXR0ZXJuKTtcbiAgfVxuXG4gIGlmIChDaGVja3MuaXNfc3ltYm9sKHBhdHRlcm4pKSB7XG4gICAgcmV0dXJuIFJlc29sdmVycy5yZXNvbHZlU3ltYm9sKHBhdHRlcm4pO1xuICB9XG5cbiAgaWYgKENoZWNrcy5pc19udWxsKHBhdHRlcm4pKSB7XG4gICAgcmV0dXJuIFJlc29sdmVycy5yZXNvbHZlTnVsbChwYXR0ZXJuKTtcbiAgfVxuXG4gIGlmIChDaGVja3MuaXNfb2JqZWN0KHBhdHRlcm4pKSB7XG4gICAgcmV0dXJuIFJlc29sdmVycy5yZXNvbHZlT2JqZWN0KHBhdHRlcm4pO1xuICB9XG5cbiAgcmV0dXJuIFJlc29sdmVycy5yZXNvbHZlTm9NYXRjaCgpO1xufVxuXG5jbGFzcyBNYXRjaEVycm9yIGV4dGVuZHMgRXJyb3Ige1xuICBjb25zdHJ1Y3RvcihhcmcpIHtcbiAgICBzdXBlcigpO1xuXG4gICAgaWYgKHR5cGVvZiBhcmcgPT09ICdzeW1ib2wnKSB7XG4gICAgICB0aGlzLm1lc3NhZ2UgPSAnTm8gbWF0Y2ggZm9yOiAnICsgYXJnLnRvU3RyaW5nKCk7XG4gICAgfSBlbHNlIGlmIChBcnJheS5pc0FycmF5KGFyZykpIHtcbiAgICAgIGxldCBtYXBwZWRWYWx1ZXMgPSBhcmcubWFwKHggPT4geC50b1N0cmluZygpKTtcbiAgICAgIHRoaXMubWVzc2FnZSA9ICdObyBtYXRjaCBmb3I6ICcgKyBtYXBwZWRWYWx1ZXM7XG4gICAgfSBlbHNlIHtcbiAgICAgIHRoaXMubWVzc2FnZSA9ICdObyBtYXRjaCBmb3I6ICcgKyBhcmc7XG4gICAgfVxuXG4gICAgdGhpcy5zdGFjayA9IG5ldyBFcnJvcigpLnN0YWNrO1xuICAgIHRoaXMubmFtZSA9IHRoaXMuY29uc3RydWN0b3IubmFtZTtcbiAgfVxufVxuXG5jbGFzcyBDYXNlIHtcblxuICBjb25zdHJ1Y3RvcihwYXR0ZXJuLCBmbiwgZ3VhcmQgPSAoKSA9PiB0cnVlKSB7XG4gICAgdGhpcy5wYXR0ZXJuID0gYnVpbGRNYXRjaChwYXR0ZXJuKTtcbiAgICB0aGlzLmZuID0gZm47XG4gICAgdGhpcy5ndWFyZCA9IGd1YXJkO1xuICB9XG59XG5cbmZ1bmN0aW9uIG1ha2VfY2FzZShwYXR0ZXJuLCBmbiwgZ3VhcmQgPSAoKSA9PiB0cnVlKSB7XG4gIHJldHVybiBuZXcgQ2FzZShwYXR0ZXJuLCBmbiwgZ3VhcmQpO1xufVxuXG5mdW5jdGlvbiBkZWZtYXRjaCguLi5jYXNlcykge1xuICByZXR1cm4gZnVuY3Rpb24gKC4uLmFyZ3MpIHtcbiAgICBmb3IgKGxldCBwcm9jZXNzZWRDYXNlIG9mIGNhc2VzKSB7XG4gICAgICBsZXQgcmVzdWx0ID0gW107XG4gICAgICBpZiAocHJvY2Vzc2VkQ2FzZS5wYXR0ZXJuKGFyZ3MsIHJlc3VsdCkgJiYgcHJvY2Vzc2VkQ2FzZS5ndWFyZC5hcHBseSh0aGlzLCByZXN1bHQpKSB7XG4gICAgICAgIHJldHVybiBwcm9jZXNzZWRDYXNlLmZuLmFwcGx5KHRoaXMsIHJlc3VsdCk7XG4gICAgICB9XG4gICAgfVxuXG4gICAgdGhyb3cgbmV3IE1hdGNoRXJyb3IoYXJncyk7XG4gIH07XG59XG5cbmZ1bmN0aW9uIG1hdGNoKHBhdHRlcm4sIGV4cHIsIGd1YXJkID0gKCkgPT4gdHJ1ZSkge1xuICBsZXQgcmVzdWx0ID0gW107XG4gIGxldCBwcm9jZXNzZWRQYXR0ZXJuID0gYnVpbGRNYXRjaChwYXR0ZXJuKTtcbiAgaWYgKHByb2Nlc3NlZFBhdHRlcm4oZXhwciwgcmVzdWx0KSAmJiBndWFyZC5hcHBseSh0aGlzLCByZXN1bHQpKSB7XG4gICAgcmV0dXJuIHJlc3VsdDtcbiAgfSBlbHNlIHtcbiAgICB0aHJvdyBuZXcgTWF0Y2hFcnJvcihleHByKTtcbiAgfVxufVxuXG5mdW5jdGlvbiBtYXRjaF9ub190aHJvdyhwYXR0ZXJuLCBleHByLCBndWFyZCA9ICgpID0+IHRydWUpIHtcbiAgdHJ5IHtcbiAgICByZXR1cm4gbWF0Y2gocGF0dGVybiwgZXhwciwgZ3VhcmQpO1xuICB9IGNhdGNoIChlKSB7XG4gICAgaWYgKGUgaW5zdGFuY2VvZiBNYXRjaEVycm9yKSB7XG4gICAgICByZXR1cm4gbnVsbDtcbiAgICB9XG5cbiAgICB0aHJvdyBlO1xuICB9XG59XG5cbnZhciBQYXR0ZXJucyA9IHtcbiAgZGVmbWF0Y2gsIG1hdGNoLCBNYXRjaEVycm9yLCBtYXRjaF9ub190aHJvdyxcbiAgdmFyaWFibGUsIHdpbGRjYXJkLCBzdGFydHNXaXRoLFxuICBjYXB0dXJlLCBoZWFkVGFpbCwgdHlwZSwgYm91bmQsIENhc2UsIG1ha2VfY2FzZVxufTtcblxuY2xhc3MgQml0U3RyaW5nIHtcbiAgY29uc3RydWN0b3IoLi4uYXJncykge1xuICAgIHRoaXMucmF3X3ZhbHVlID0gZnVuY3Rpb24gKCkge1xuICAgICAgcmV0dXJuIE9iamVjdC5mcmVlemUoYXJncyk7XG4gICAgfTtcblxuICAgIHRoaXMudmFsdWUgPSBPYmplY3QuZnJlZXplKHRoaXMucHJvY2VzcyhhcmdzKSk7XG4gIH1cblxuICBnZXQoaW5kZXgpIHtcbiAgICByZXR1cm4gdGhpcy52YWx1ZVtpbmRleF07XG4gIH1cblxuICBjb3VudCgpIHtcbiAgICByZXR1cm4gdGhpcy52YWx1ZS5sZW5ndGg7XG4gIH1cblxuICBbU3ltYm9sLml0ZXJhdG9yXSgpIHtcbiAgICByZXR1cm4gdGhpcy52YWx1ZVtTeW1ib2wuaXRlcmF0b3JdKCk7XG4gIH1cblxuICB0b1N0cmluZygpIHtcbiAgICB2YXIgaSxcbiAgICAgICAgcyA9IFwiXCI7XG4gICAgZm9yIChpID0gMDsgaSA8IHRoaXMuY291bnQoKTsgaSsrKSB7XG4gICAgICBpZiAocyAhPT0gXCJcIikge1xuICAgICAgICBzICs9IFwiLCBcIjtcbiAgICAgIH1cbiAgICAgIHMgKz0gdGhpc1tpXS50b1N0cmluZygpO1xuICAgIH1cblxuICAgIHJldHVybiBcIjw8XCIgKyBzICsgXCI+PlwiO1xuICB9XG5cbiAgcHJvY2VzcygpIHtcbiAgICBsZXQgcHJvY2Vzc2VkX3ZhbHVlcyA9IFtdO1xuXG4gICAgdmFyIGk7XG4gICAgZm9yIChpID0gMDsgaSA8IHRoaXMucmF3X3ZhbHVlKCkubGVuZ3RoOyBpKyspIHtcbiAgICAgIGxldCBwcm9jZXNzZWRfdmFsdWUgPSB0aGlzW1wicHJvY2Vzc19cIiArIHRoaXMucmF3X3ZhbHVlKClbaV0udHlwZV0odGhpcy5yYXdfdmFsdWUoKVtpXSk7XG5cbiAgICAgIGZvciAobGV0IGF0dHIgb2YgdGhpcy5yYXdfdmFsdWUoKVtpXS5hdHRyaWJ1dGVzKSB7XG4gICAgICAgIHByb2Nlc3NlZF92YWx1ZSA9IHRoaXNbXCJwcm9jZXNzX1wiICsgYXR0cl0ocHJvY2Vzc2VkX3ZhbHVlKTtcbiAgICAgIH1cblxuICAgICAgcHJvY2Vzc2VkX3ZhbHVlcyA9IHByb2Nlc3NlZF92YWx1ZXMuY29uY2F0KHByb2Nlc3NlZF92YWx1ZSk7XG4gICAgfVxuXG4gICAgcmV0dXJuIHByb2Nlc3NlZF92YWx1ZXM7XG4gIH1cblxuICBwcm9jZXNzX2ludGVnZXIodmFsdWUpIHtcbiAgICByZXR1cm4gdmFsdWUudmFsdWU7XG4gIH1cblxuICBwcm9jZXNzX2Zsb2F0KHZhbHVlKSB7XG4gICAgaWYgKHZhbHVlLnNpemUgPT09IDY0KSB7XG4gICAgICByZXR1cm4gQml0U3RyaW5nLmZsb2F0NjRUb0J5dGVzKHZhbHVlLnZhbHVlKTtcbiAgICB9IGVsc2UgaWYgKHZhbHVlLnNpemUgPT09IDMyKSB7XG4gICAgICByZXR1cm4gQml0U3RyaW5nLmZsb2F0MzJUb0J5dGVzKHZhbHVlLnZhbHVlKTtcbiAgICB9XG5cbiAgICB0aHJvdyBuZXcgRXJyb3IoXCJJbnZhbGlkIHNpemUgZm9yIGZsb2F0XCIpO1xuICB9XG5cbiAgcHJvY2Vzc19iaXRzdHJpbmcodmFsdWUpIHtcbiAgICByZXR1cm4gdmFsdWUudmFsdWUudmFsdWU7XG4gIH1cblxuICBwcm9jZXNzX2JpbmFyeSh2YWx1ZSkge1xuICAgIHJldHVybiBCaXRTdHJpbmcudG9VVEY4QXJyYXkodmFsdWUudmFsdWUpO1xuICB9XG5cbiAgcHJvY2Vzc191dGY4KHZhbHVlKSB7XG4gICAgcmV0dXJuIEJpdFN0cmluZy50b1VURjhBcnJheSh2YWx1ZS52YWx1ZSk7XG4gIH1cblxuICBwcm9jZXNzX3V0ZjE2KHZhbHVlKSB7XG4gICAgcmV0dXJuIEJpdFN0cmluZy50b1VURjE2QXJyYXkodmFsdWUudmFsdWUpO1xuICB9XG5cbiAgcHJvY2Vzc191dGYzMih2YWx1ZSkge1xuICAgIHJldHVybiBCaXRTdHJpbmcudG9VVEYzMkFycmF5KHZhbHVlLnZhbHVlKTtcbiAgfVxuXG4gIHByb2Nlc3Nfc2lnbmVkKHZhbHVlKSB7XG4gICAgcmV0dXJuIG5ldyBVaW50OEFycmF5KFt2YWx1ZV0pWzBdO1xuICB9XG5cbiAgcHJvY2Vzc191bnNpZ25lZCh2YWx1ZSkge1xuICAgIHJldHVybiB2YWx1ZTtcbiAgfVxuXG4gIHByb2Nlc3NfbmF0aXZlKHZhbHVlKSB7XG4gICAgcmV0dXJuIHZhbHVlO1xuICB9XG5cbiAgcHJvY2Vzc19iaWcodmFsdWUpIHtcbiAgICByZXR1cm4gdmFsdWU7XG4gIH1cblxuICBwcm9jZXNzX2xpdHRsZSh2YWx1ZSkge1xuICAgIHJldHVybiB2YWx1ZS5yZXZlcnNlKCk7XG4gIH1cblxuICBwcm9jZXNzX3NpemUodmFsdWUpIHtcbiAgICByZXR1cm4gdmFsdWU7XG4gIH1cblxuICBwcm9jZXNzX3VuaXQodmFsdWUpIHtcbiAgICByZXR1cm4gdmFsdWU7XG4gIH1cblxuICBzdGF0aWMgaW50ZWdlcih2YWx1ZSkge1xuICAgIHJldHVybiBCaXRTdHJpbmcud3JhcCh2YWx1ZSwgeyBcInR5cGVcIjogXCJpbnRlZ2VyXCIsIFwidW5pdFwiOiAxLCBcInNpemVcIjogOCB9KTtcbiAgfVxuXG4gIHN0YXRpYyBmbG9hdCh2YWx1ZSkge1xuICAgIHJldHVybiBCaXRTdHJpbmcud3JhcCh2YWx1ZSwgeyBcInR5cGVcIjogXCJmbG9hdFwiLCBcInVuaXRcIjogMSwgXCJzaXplXCI6IDY0IH0pO1xuICB9XG5cbiAgc3RhdGljIGJpdHN0cmluZyh2YWx1ZSkge1xuICAgIHJldHVybiBCaXRTdHJpbmcud3JhcCh2YWx1ZSwgeyBcInR5cGVcIjogXCJiaXRzdHJpbmdcIiwgXCJ1bml0XCI6IDEsIFwic2l6ZVwiOiB2YWx1ZS5sZW5ndGggfSk7XG4gIH1cblxuICBzdGF0aWMgYml0cyh2YWx1ZSkge1xuICAgIHJldHVybiBCaXRTdHJpbmcuYml0c3RyaW5nKHZhbHVlKTtcbiAgfVxuXG4gIHN0YXRpYyBiaW5hcnkodmFsdWUpIHtcbiAgICByZXR1cm4gQml0U3RyaW5nLndyYXAodmFsdWUsIHsgXCJ0eXBlXCI6IFwiYmluYXJ5XCIsIFwidW5pdFwiOiA4LCBcInNpemVcIjogdmFsdWUubGVuZ3RoIH0pO1xuICB9XG5cbiAgc3RhdGljIGJ5dGVzKHZhbHVlKSB7XG4gICAgcmV0dXJuIEJpdFN0cmluZy5iaW5hcnkodmFsdWUpO1xuICB9XG5cbiAgc3RhdGljIHV0ZjgodmFsdWUpIHtcbiAgICByZXR1cm4gQml0U3RyaW5nLndyYXAodmFsdWUsIHsgXCJ0eXBlXCI6IFwidXRmOFwiIH0pO1xuICB9XG5cbiAgc3RhdGljIHV0ZjE2KHZhbHVlKSB7XG4gICAgcmV0dXJuIEJpdFN0cmluZy53cmFwKHZhbHVlLCB7IFwidHlwZVwiOiBcInV0ZjE2XCIgfSk7XG4gIH1cblxuICBzdGF0aWMgdXRmMzIodmFsdWUpIHtcbiAgICByZXR1cm4gQml0U3RyaW5nLndyYXAodmFsdWUsIHsgXCJ0eXBlXCI6IFwidXRmMzJcIiB9KTtcbiAgfVxuXG4gIHN0YXRpYyBzaWduZWQodmFsdWUpIHtcbiAgICByZXR1cm4gQml0U3RyaW5nLndyYXAodmFsdWUsIHt9LCBcInNpZ25lZFwiKTtcbiAgfVxuXG4gIHN0YXRpYyB1bnNpZ25lZCh2YWx1ZSkge1xuICAgIHJldHVybiBCaXRTdHJpbmcud3JhcCh2YWx1ZSwge30sIFwidW5zaWduZWRcIik7XG4gIH1cblxuICBzdGF0aWMgbmF0aXZlKHZhbHVlKSB7XG4gICAgcmV0dXJuIEJpdFN0cmluZy53cmFwKHZhbHVlLCB7fSwgXCJuYXRpdmVcIik7XG4gIH1cblxuICBzdGF0aWMgYmlnKHZhbHVlKSB7XG4gICAgcmV0dXJuIEJpdFN0cmluZy53cmFwKHZhbHVlLCB7fSwgXCJiaWdcIik7XG4gIH1cblxuICBzdGF0aWMgbGl0dGxlKHZhbHVlKSB7XG4gICAgcmV0dXJuIEJpdFN0cmluZy53cmFwKHZhbHVlLCB7fSwgXCJsaXR0bGVcIik7XG4gIH1cblxuICBzdGF0aWMgc2l6ZSh2YWx1ZSwgY291bnQpIHtcbiAgICByZXR1cm4gQml0U3RyaW5nLndyYXAodmFsdWUsIHsgXCJzaXplXCI6IGNvdW50IH0pO1xuICB9XG5cbiAgc3RhdGljIHVuaXQodmFsdWUsIGNvdW50KSB7XG4gICAgcmV0dXJuIEJpdFN0cmluZy53cmFwKHZhbHVlLCB7IFwidW5pdFwiOiBjb3VudCB9KTtcbiAgfVxuXG4gIHN0YXRpYyB3cmFwKHZhbHVlLCBvcHQsIG5ld19hdHRyaWJ1dGUgPSBudWxsKSB7XG4gICAgbGV0IHRoZV92YWx1ZSA9IHZhbHVlO1xuXG4gICAgaWYgKCEodmFsdWUgaW5zdGFuY2VvZiBPYmplY3QpKSB7XG4gICAgICB0aGVfdmFsdWUgPSB7IFwidmFsdWVcIjogdmFsdWUsIFwiYXR0cmlidXRlc1wiOiBbXSB9O1xuICAgIH1cblxuICAgIHRoZV92YWx1ZSA9IE9iamVjdC5hc3NpZ24odGhlX3ZhbHVlLCBvcHQpO1xuXG4gICAgaWYgKG5ld19hdHRyaWJ1dGUpIHtcbiAgICAgIHRoZV92YWx1ZS5hdHRyaWJ1dGVzLnB1c2gobmV3X2F0dHJpYnV0ZSk7XG4gICAgfVxuXG4gICAgcmV0dXJuIHRoZV92YWx1ZTtcbiAgfVxuXG4gIHN0YXRpYyB0b1VURjhBcnJheShzdHIpIHtcbiAgICB2YXIgdXRmOCA9IFtdO1xuICAgIGZvciAodmFyIGkgPSAwOyBpIDwgc3RyLmxlbmd0aDsgaSsrKSB7XG4gICAgICB2YXIgY2hhcmNvZGUgPSBzdHIuY2hhckNvZGVBdChpKTtcbiAgICAgIGlmIChjaGFyY29kZSA8IDEyOCkge1xuICAgICAgICB1dGY4LnB1c2goY2hhcmNvZGUpO1xuICAgICAgfSBlbHNlIGlmIChjaGFyY29kZSA8IDIwNDgpIHtcbiAgICAgICAgdXRmOC5wdXNoKDE5MiB8IGNoYXJjb2RlID4+IDYsIDEyOCB8IGNoYXJjb2RlICYgNjMpO1xuICAgICAgfSBlbHNlIGlmIChjaGFyY29kZSA8IDU1Mjk2IHx8IGNoYXJjb2RlID49IDU3MzQ0KSB7XG4gICAgICAgIHV0ZjgucHVzaCgyMjQgfCBjaGFyY29kZSA+PiAxMiwgMTI4IHwgY2hhcmNvZGUgPj4gNiAmIDYzLCAxMjggfCBjaGFyY29kZSAmIDYzKTtcbiAgICAgIH1cbiAgICAgIC8vIHN1cnJvZ2F0ZSBwYWlyXG4gICAgICBlbHNlIHtcbiAgICAgICAgaSsrO1xuICAgICAgICAvLyBVVEYtMTYgZW5jb2RlcyAweDEwMDAwLTB4MTBGRkZGIGJ5XG4gICAgICAgIC8vIHN1YnRyYWN0aW5nIDB4MTAwMDAgYW5kIHNwbGl0dGluZyB0aGVcbiAgICAgICAgLy8gMjAgYml0cyBvZiAweDAtMHhGRkZGRiBpbnRvIHR3byBoYWx2ZXNcbiAgICAgICAgY2hhcmNvZGUgPSA2NTUzNiArICgoY2hhcmNvZGUgJiAxMDIzKSA8PCAxMCB8IHN0ci5jaGFyQ29kZUF0KGkpICYgMTAyMyk7XG4gICAgICAgIHV0ZjgucHVzaCgyNDAgfCBjaGFyY29kZSA+PiAxOCwgMTI4IHwgY2hhcmNvZGUgPj4gMTIgJiA2MywgMTI4IHwgY2hhcmNvZGUgPj4gNiAmIDYzLCAxMjggfCBjaGFyY29kZSAmIDYzKTtcbiAgICAgIH1cbiAgICB9XG4gICAgcmV0dXJuIHV0Zjg7XG4gIH1cblxuICBzdGF0aWMgdG9VVEYxNkFycmF5KHN0cikge1xuICAgIHZhciB1dGYxNiA9IFtdO1xuICAgIGZvciAodmFyIGkgPSAwOyBpIDwgc3RyLmxlbmd0aDsgaSsrKSB7XG4gICAgICB2YXIgY29kZVBvaW50ID0gc3RyLmNvZGVQb2ludEF0KGkpO1xuXG4gICAgICBpZiAoY29kZVBvaW50IDw9IDI1NSkge1xuICAgICAgICB1dGYxNi5wdXNoKDApO1xuICAgICAgICB1dGYxNi5wdXNoKGNvZGVQb2ludCk7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICB1dGYxNi5wdXNoKGNvZGVQb2ludCA+PiA4ICYgMjU1KTtcbiAgICAgICAgdXRmMTYucHVzaChjb2RlUG9pbnQgJiAyNTUpO1xuICAgICAgfVxuICAgIH1cbiAgICByZXR1cm4gdXRmMTY7XG4gIH1cblxuICBzdGF0aWMgdG9VVEYzMkFycmF5KHN0cikge1xuICAgIHZhciB1dGYzMiA9IFtdO1xuICAgIGZvciAodmFyIGkgPSAwOyBpIDwgc3RyLmxlbmd0aDsgaSsrKSB7XG4gICAgICB2YXIgY29kZVBvaW50ID0gc3RyLmNvZGVQb2ludEF0KGkpO1xuXG4gICAgICBpZiAoY29kZVBvaW50IDw9IDI1NSkge1xuICAgICAgICB1dGYzMi5wdXNoKDApO1xuICAgICAgICB1dGYzMi5wdXNoKDApO1xuICAgICAgICB1dGYzMi5wdXNoKDApO1xuICAgICAgICB1dGYzMi5wdXNoKGNvZGVQb2ludCk7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICB1dGYzMi5wdXNoKDApO1xuICAgICAgICB1dGYzMi5wdXNoKDApO1xuICAgICAgICB1dGYzMi5wdXNoKGNvZGVQb2ludCA+PiA4ICYgMjU1KTtcbiAgICAgICAgdXRmMzIucHVzaChjb2RlUG9pbnQgJiAyNTUpO1xuICAgICAgfVxuICAgIH1cbiAgICByZXR1cm4gdXRmMzI7XG4gIH1cblxuICAvL2h0dHA6Ly9zdGFja292ZXJmbG93LmNvbS9xdWVzdGlvbnMvMjAwMzQ5My9qYXZhc2NyaXB0LWZsb2F0LWZyb20tdG8tYml0c1xuICBzdGF0aWMgZmxvYXQzMlRvQnl0ZXMoZikge1xuICAgIHZhciBieXRlcyA9IFtdO1xuXG4gICAgdmFyIGJ1ZiA9IG5ldyBBcnJheUJ1ZmZlcig0KTtcbiAgICBuZXcgRmxvYXQzMkFycmF5KGJ1ZilbMF0gPSBmO1xuXG4gICAgbGV0IGludFZlcnNpb24gPSBuZXcgVWludDMyQXJyYXkoYnVmKVswXTtcblxuICAgIGJ5dGVzLnB1c2goaW50VmVyc2lvbiA+PiAyNCAmIDI1NSk7XG4gICAgYnl0ZXMucHVzaChpbnRWZXJzaW9uID4+IDE2ICYgMjU1KTtcbiAgICBieXRlcy5wdXNoKGludFZlcnNpb24gPj4gOCAmIDI1NSk7XG4gICAgYnl0ZXMucHVzaChpbnRWZXJzaW9uICYgMjU1KTtcblxuICAgIHJldHVybiBieXRlcztcbiAgfVxuXG4gIHN0YXRpYyBmbG9hdDY0VG9CeXRlcyhmKSB7XG4gICAgdmFyIGJ5dGVzID0gW107XG5cbiAgICB2YXIgYnVmID0gbmV3IEFycmF5QnVmZmVyKDgpO1xuICAgIG5ldyBGbG9hdDY0QXJyYXkoYnVmKVswXSA9IGY7XG5cbiAgICB2YXIgaW50VmVyc2lvbjEgPSBuZXcgVWludDMyQXJyYXkoYnVmKVswXTtcbiAgICB2YXIgaW50VmVyc2lvbjIgPSBuZXcgVWludDMyQXJyYXkoYnVmKVsxXTtcblxuICAgIGJ5dGVzLnB1c2goaW50VmVyc2lvbjIgPj4gMjQgJiAyNTUpO1xuICAgIGJ5dGVzLnB1c2goaW50VmVyc2lvbjIgPj4gMTYgJiAyNTUpO1xuICAgIGJ5dGVzLnB1c2goaW50VmVyc2lvbjIgPj4gOCAmIDI1NSk7XG4gICAgYnl0ZXMucHVzaChpbnRWZXJzaW9uMiAmIDI1NSk7XG5cbiAgICBieXRlcy5wdXNoKGludFZlcnNpb24xID4+IDI0ICYgMjU1KTtcbiAgICBieXRlcy5wdXNoKGludFZlcnNpb24xID4+IDE2ICYgMjU1KTtcbiAgICBieXRlcy5wdXNoKGludFZlcnNpb24xID4+IDggJiAyNTUpO1xuICAgIGJ5dGVzLnB1c2goaW50VmVyc2lvbjEgJiAyNTUpO1xuXG4gICAgcmV0dXJuIGJ5dGVzO1xuICB9XG59XG5cbi8qIEBmbG93ICovXG5cbmNsYXNzIE1haWxib3gge1xuXG4gIGNvbnN0cnVjdG9yKCkge1xuICAgIHRoaXMubWVzc2FnZXMgPSBbXTtcbiAgfVxuXG4gIGRlbGl2ZXIobWVzc2FnZSkge1xuICAgIHRoaXMubWVzc2FnZXMucHVzaChtZXNzYWdlKTtcbiAgICByZXR1cm4gbWVzc2FnZTtcbiAgfVxuXG4gIGdldCgpIHtcbiAgICByZXR1cm4gdGhpcy5tZXNzYWdlcztcbiAgfVxuXG4gIGlzRW1wdHkoKSB7XG4gICAgcmV0dXJuIHRoaXMubWVzc2FnZXMubGVuZ3RoID09PSAwO1xuICB9XG5cbiAgcmVtb3ZlQXQoaW5kZXgpIHtcbiAgICB0aGlzLm1lc3NhZ2VzLnNwbGljZShpbmRleCwgMSk7XG4gIH1cbn1cblxudmFyIFN0YXRlcyA9IHtcbiAgTk9STUFMOiBTeW1ib2wuZm9yKFwibm9ybWFsXCIpLFxuICBLSUxMOiBTeW1ib2wuZm9yKFwia2lsbFwiKSxcbiAgU1VTUEVORDogU3ltYm9sLmZvcihcInN1c3BlbmRcIiksXG4gIENPTlRJTlVFOiBTeW1ib2wuZm9yKFwiY29udGludWVcIiksXG4gIFJFQ0VJVkU6IFN5bWJvbC5mb3IoXCJyZWNlaXZlXCIpLFxuICBTRU5EOiBTeW1ib2wuZm9yKFwic2VuZFwiKSxcbiAgU0xFRVBJTkc6IFN5bWJvbC5mb3IoXCJzbGVlcGluZ1wiKSxcbiAgUlVOTklORzogU3ltYm9sLmZvcihcInJ1bm5pbmdcIiksXG4gIFNVU1BFTkRFRDogU3ltYm9sLmZvcihcInN1c3BlbmRlZFwiKSxcbiAgU1RPUFBFRDogU3ltYm9sLmZvcihcInN0b3BwZWRcIiksXG4gIFNMRUVQOiBTeW1ib2wuZm9yKFwic2xlZXBcIiksXG4gIEVYSVQ6IFN5bWJvbC5mb3IoXCJleGl0XCIpLFxuICBOT01BVENIOiBTeW1ib2wuZm9yKFwibm9fbWF0Y2hcIilcbn07XG5cbmNsYXNzIFByb2Nlc3Mge1xuXG4gIGNvbnN0cnVjdG9yKHBpZCwgbWFpbGJveCkge1xuICAgIHRoaXMucGlkID0gcGlkO1xuICAgIHRoaXMubWFpbGJveCA9IG1haWxib3g7XG4gICAgdGhpcy5zdGF0dXMgPSBTdGF0ZXMuU1RPUFBFRDtcbiAgICB0aGlzLmRpY3QgPSB7fTtcbiAgfVxufVxuXG5jbGFzcyBQcm9jZXNzU3lzdGVtIHtcblxuICBjb25zdHJ1Y3RvcigpIHtcbiAgICB0aGlzLnBpZHMgPSBuZXcgTWFwKCk7XG4gICAgdGhpcy5tYWlsYm94ZXMgPSBuZXcgTWFwKCk7XG4gICAgdGhpcy5uYW1lcyA9IG5ldyBNYXAoKTtcbiAgICB0aGlzLmxpbmtzID0gbmV3IE1hcCgpO1xuXG4gICAgdGhpcy5jdXJyZW50X3Byb2Nlc3MgPSBudWxsO1xuICAgIHRoaXMuc3VzcGVuZGVkID0gbmV3IE1hcCgpO1xuXG4gICAgdGhpcy5tYWluX3Byb2Nlc3NfcGlkID0gdGhpcy5zcGF3bigpO1xuICAgIHRoaXMuc2V0X2N1cnJlbnQodGhpcy5tYWluX3Byb2Nlc3NfcGlkKTtcbiAgfVxuXG4gIHNwYXduKCkge1xuICAgIHJldHVybiB0aGlzLmFkZF9wcm9jKGZhbHNlKS5waWQ7XG4gIH1cblxuICBzcGF3bl9saW5rKCkge1xuICAgIHJldHVybiB0aGlzLmFkZF9wcm9jKHRydWUpLnBpZDtcbiAgfVxuXG4gIGxpbmsocGlkKSB7XG4gICAgdGhpcy5saW5rcy5nZXQodGhpcy5waWQoKSkuYWRkKHBpZCk7XG4gICAgdGhpcy5saW5rcy5nZXQocGlkKS5hZGQodGhpcy5waWQoKSk7XG4gIH1cblxuICB1bmxpbmsocGlkKSB7XG4gICAgdGhpcy5saW5rcy5nZXQodGhpcy5waWQoKSkuZGVsZXRlKHBpZCk7XG4gICAgdGhpcy5saW5rcy5nZXQocGlkKS5kZWxldGUodGhpcy5waWQoKSk7XG4gIH1cblxuICBzZXRfY3VycmVudChpZCkge1xuICAgIGxldCBwaWQgPSB0aGlzLnBpZG9mKGlkKTtcbiAgICBpZiAocGlkICE9PSBudWxsKSB7XG4gICAgICB0aGlzLmN1cnJlbnRfcHJvY2VzcyA9IHRoaXMucGlkcy5nZXQocGlkKTtcbiAgICAgIHRoaXMuY3VycmVudF9wcm9jZXNzLnN0YXR1cyA9IFN0YXRlcy5SVU5OSU5HO1xuICAgIH1cbiAgfVxuXG4gIGFkZF9wcm9jKGxpbmtlZCkge1xuICAgIGxldCBuZXdwaWQgPSBuZXcgUElEKCk7XG4gICAgbGV0IG1haWxib3ggPSBuZXcgTWFpbGJveCgpO1xuICAgIGxldCBuZXdwcm9jID0gbmV3IFByb2Nlc3MobmV3cGlkLCBtYWlsYm94KTtcblxuICAgIHRoaXMucGlkcy5zZXQobmV3cGlkLCBuZXdwcm9jKTtcbiAgICB0aGlzLm1haWxib3hlcy5zZXQobmV3cGlkLCBtYWlsYm94KTtcbiAgICB0aGlzLmxpbmtzLnNldChuZXdwaWQsIG5ldyBTZXQoKSk7XG5cbiAgICBpZiAobGlua2VkKSB7XG4gICAgICB0aGlzLmxpbmsobmV3cGlkKTtcbiAgICB9XG5cbiAgICByZXR1cm4gbmV3cHJvYztcbiAgfVxuXG4gIHJlbW92ZV9wcm9jKHBpZCkge1xuICAgIHRoaXMucGlkcy5kZWxldGUocGlkKTtcbiAgICB0aGlzLnVucmVnaXN0ZXIocGlkKTtcblxuICAgIGlmICh0aGlzLmxpbmtzLmhhcyhwaWQpKSB7XG4gICAgICBmb3IgKGxldCBsaW5rcGlkIG9mIHRoaXMubGlua3MuZ2V0KHBpZCkpIHtcbiAgICAgICAgdGhpcy5saW5rcy5nZXQobGlua3BpZCkuZGVsZXRlKHBpZCk7XG4gICAgICB9XG5cbiAgICAgIHRoaXMubGlua3MuZGVsZXRlKHBpZCk7XG4gICAgfVxuICB9XG5cbiAgZXhpdChpZCkge1xuICAgIGxldCBwaWQgPSB0aGlzLnBpZG9mKGlkKTtcbiAgICB0aGlzLnJlbW92ZV9wcm9jKGlkKTtcbiAgfVxuXG4gIHJlZ2lzdGVyKG5hbWUsIHBpZCkge1xuICAgIGlmICghdGhpcy5uYW1lcy5oYXMobmFtZSkpIHtcbiAgICAgIHRoaXMubmFtZXMuc2V0KG5hbWUsIHBpZCk7XG4gICAgICByZXR1cm4gbmFtZTtcbiAgICB9IGVsc2Uge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKFwiTmFtZSBpcyBhbHJlYWR5IHJlZ2lzdGVyZWQgdG8gYW5vdGhlciBwcm9jZXNzXCIpO1xuICAgIH1cbiAgfVxuXG4gIHJlZ2lzdGVyZWQobmFtZSkge1xuICAgIHJldHVybiB0aGlzLm5hbWVzLmhhcyhuYW1lKSA/IHRoaXMubmFtZXMuZ2V0KG5hbWUpIDogbnVsbDtcbiAgfVxuXG4gIHVucmVnaXN0ZXIocGlkKSB7XG4gICAgZm9yIChsZXQgbmFtZSBvZiB0aGlzLm5hbWVzLmtleXMoKSkge1xuICAgICAgaWYgKHRoaXMubmFtZXMuaGFzKG5hbWUpICYmIHRoaXMubmFtZXMuZ2V0KG5hbWUpID09PSBwaWQpIHtcbiAgICAgICAgdGhpcy5uYW1lcy5kZWxldGUobmFtZSk7XG4gICAgICB9XG4gICAgfVxuICB9XG5cbiAgcGlkKCkge1xuICAgIHJldHVybiB0aGlzLmN1cnJlbnRfcHJvY2Vzcy5waWQ7XG4gIH1cblxuICBwaWRvZihpZCkge1xuICAgIGlmIChpZCBpbnN0YW5jZW9mIFBJRCkge1xuICAgICAgcmV0dXJuIHRoaXMucGlkcy5oYXMoaWQpID8gaWQgOiBudWxsO1xuICAgIH0gZWxzZSBpZiAoaWQgaW5zdGFuY2VvZiBQcm9jZXNzKSB7XG4gICAgICByZXR1cm4gaWQucGlkO1xuICAgIH0gZWxzZSB7XG4gICAgICBsZXQgcGlkID0gdGhpcy5yZWdpc3RlcmVkKGlkKTtcbiAgICAgIGlmIChwaWQgPT09IG51bGwpIHRocm93IFwiUHJvY2VzcyBuYW1lIG5vdCByZWdpc3RlcmVkOiBcIiArIGlkICsgXCIgKFwiICsgdHlwZW9mIGlkICsgXCIpXCI7XG4gICAgICByZXR1cm4gcGlkO1xuICAgIH1cbiAgfVxuXG4gIHB1dChpZCwga2V5LCB2YWx1ZSkge1xuICAgIGxldCBwaWQgPSB0aGlzLnBpZG9mKGlkKTtcbiAgICBsZXQgcHJvY2VzcyA9IHRoaXMucGlkcy5nZXQocGlkKTtcbiAgICBwcm9jZXNzLmRpY3Rba2V5XSA9IHZhbHVlO1xuICB9XG5cbiAgZ2V0KGlkLCBrZXkpIHtcbiAgICBsZXQgcGlkID0gdGhpcy5waWRvZihpZCk7XG4gICAgbGV0IHByb2Nlc3MgPSB0aGlzLnBpZHMuZ2V0KHBpZCk7XG5cbiAgICBpZiAoa2V5ICE9IG51bGwpIHtcbiAgICAgIHJldHVybiBwcm9jZXNzLmRpY3Rba2V5XTtcbiAgICB9IGVsc2Uge1xuICAgICAgcmV0dXJuIHByb2Nlc3MuZGljdDtcbiAgICB9XG4gIH1cblxuICBnZXRfa2V5cyhpZCkge1xuICAgIGxldCBwaWQgPSB0aGlzLnBpZG9mKGlkKTtcbiAgICBsZXQgcHJvY2VzcyA9IHRoaXMucGlkcy5nZXQocGlkKTtcblxuICAgIHJldHVybiBPYmplY3Qua2V5cyhwcm9jZXNzLmRpY3QpO1xuICB9XG5cbiAgZXJhc2UoaWQsIGtleSkge1xuICAgIGxldCBwaWQgPSB0aGlzLnBpZG9mKGlkKTtcbiAgICBsZXQgcHJvY2VzcyA9IHRoaXMucGlkcy5nZXQocGlkKTtcblxuICAgIGlmIChrZXkgIT0gbnVsbCkge1xuICAgICAgZGVsZXRlIHByb2Nlc3MuZGljdFtrZXldO1xuICAgIH0gZWxzZSB7XG4gICAgICBwcm9jZXNzLmRpY3QgPSB7fTtcbiAgICB9XG4gIH1cbn1cblxudmFyIEMgPSBPYmplY3QuZnJlZXplKHtcblx0UHJvY2Vzc1N5c3RlbTogUHJvY2Vzc1N5c3RlbSxcblx0VHVwbGU6IFR1cGxlJDEsXG5cdFBJRDogUElELFxuXHRCaXRTdHJpbmc6IEJpdFN0cmluZyxcblx0UGF0dGVybnM6IFBhdHRlcm5zLFxuXHRJbnRlZ2VyOiBJbnRlZ2VyJDEsXG5cdEZsb2F0OiBGbG9hdCxcblx0Y2FsbF9wcm9wZXJ0eTogY2FsbF9wcm9wZXJ0eVxufSk7XG5cbmxldCBFbnVtID0ge1xuXG4gIGFsbF9fcW1hcmtfXzogZnVuY3Rpb24gKGNvbGxlY3Rpb24sIGZ1biA9IHggPT4geCkge1xuICAgIGZvciAobGV0IGVsZW0gb2YgY29sbGVjdGlvbikge1xuICAgICAgaWYgKCFmdW4oZWxlbSkpIHtcbiAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgfVxuICAgIH1cblxuICAgIHJldHVybiB0cnVlO1xuICB9LFxuXG4gIGFueV9fcW1hcmtfXzogZnVuY3Rpb24gKGNvbGxlY3Rpb24sIGZ1biA9IHggPT4geCkge1xuICAgIGZvciAobGV0IGVsZW0gb2YgY29sbGVjdGlvbikge1xuICAgICAgaWYgKGZ1bihlbGVtKSkge1xuICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICByZXR1cm4gZmFsc2U7XG4gIH0sXG5cbiAgYXQ6IGZ1bmN0aW9uIChjb2xsZWN0aW9uLCBuLCB0aGVfZGVmYXVsdCA9IG51bGwpIHtcbiAgICBpZiAobiA+IHRoaXMuY291bnQoY29sbGVjdGlvbikgfHwgbiA8IDApIHtcbiAgICAgIHJldHVybiB0aGVfZGVmYXVsdDtcbiAgICB9XG5cbiAgICByZXR1cm4gY29sbGVjdGlvbltuXTtcbiAgfSxcblxuICBjb25jYXQ6IGZ1bmN0aW9uICguLi5lbnVtYWJsZXMpIHtcbiAgICByZXR1cm4gZW51bWFibGVzWzBdLmNvbmNhdChlbnVtYWJsZXNbMV0pO1xuICB9LFxuXG4gIGNvdW50OiBmdW5jdGlvbiAoY29sbGVjdGlvbiwgZnVuID0gbnVsbCkge1xuICAgIGlmIChmdW4gPT0gbnVsbCkge1xuICAgICAgcmV0dXJuIGNvbGxlY3Rpb24ubGVuZ3RoO1xuICAgIH0gZWxzZSB7XG4gICAgICByZXR1cm4gY29sbGVjdGlvbi5maWx0ZXIoZnVuKS5sZW5ndGg7XG4gICAgfVxuICB9LFxuXG4gIGRyb3A6IGZ1bmN0aW9uIChjb2xsZWN0aW9uLCBjb3VudCkge1xuICAgIHJldHVybiBjb2xsZWN0aW9uLnNsaWNlKGNvdW50KTtcbiAgfSxcblxuICBkcm9wX3doaWxlOiBmdW5jdGlvbiAoY29sbGVjdGlvbiwgZnVuKSB7XG4gICAgbGV0IGNvdW50ID0gMDtcblxuICAgIGZvciAobGV0IGVsZW0gb2YgY29sbGVjdGlvbikge1xuICAgICAgaWYgKGZ1bihlbGVtKSkge1xuICAgICAgICBjb3VudCA9IGNvdW50ICsgMTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIGJyZWFrO1xuICAgICAgfVxuICAgIH1cblxuICAgIHJldHVybiBjb2xsZWN0aW9uLnNsaWNlKGNvdW50KTtcbiAgfSxcblxuICBlYWNoOiBmdW5jdGlvbiAoY29sbGVjdGlvbiwgZnVuKSB7XG4gICAgZm9yIChsZXQgZWxlbSBvZiBjb2xsZWN0aW9uKSB7XG4gICAgICBmdW4oZWxlbSk7XG4gICAgfVxuICB9LFxuXG4gIGVtcHR5X19xbWFya19fOiBmdW5jdGlvbiAoY29sbGVjdGlvbikge1xuICAgIHJldHVybiBjb2xsZWN0aW9uLmxlbmd0aCA9PT0gMDtcbiAgfSxcblxuICBmZXRjaDogZnVuY3Rpb24gKGNvbGxlY3Rpb24sIG4pIHtcbiAgICBpZiAoS2VybmVsLmlzX2xpc3QoY29sbGVjdGlvbikpIHtcbiAgICAgIGlmIChuIDwgdGhpcy5jb3VudChjb2xsZWN0aW9uKSAmJiBuID49IDApIHtcbiAgICAgICAgcmV0dXJuIEtlcm5lbC5TcGVjaWFsRm9ybXMudHVwbGUoS2VybmVsLlNwZWNpYWxGb3Jtcy5hdG9tKFwib2tcIiksIGNvbGxlY3Rpb25bbl0pO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgcmV0dXJuIEtlcm5lbC5TcGVjaWFsRm9ybXMuYXRvbShcImVycm9yXCIpO1xuICAgICAgfVxuICAgIH1cblxuICAgIHRocm93IG5ldyBFcnJvcihcImNvbGxlY3Rpb24gaXMgbm90IGFuIEVudW1lcmFibGVcIik7XG4gIH0sXG5cbiAgZmV0Y2hfX2VtYXJrX186IGZ1bmN0aW9uIChjb2xsZWN0aW9uLCBuKSB7XG4gICAgaWYgKEtlcm5lbC5pc19saXN0KGNvbGxlY3Rpb24pKSB7XG4gICAgICBpZiAobiA8IHRoaXMuY291bnQoY29sbGVjdGlvbikgJiYgbiA+PSAwKSB7XG4gICAgICAgIHJldHVybiBjb2xsZWN0aW9uW25dO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKFwib3V0IG9mIGJvdW5kcyBlcnJvclwiKTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICB0aHJvdyBuZXcgRXJyb3IoXCJjb2xsZWN0aW9uIGlzIG5vdCBhbiBFbnVtZXJhYmxlXCIpO1xuICB9LFxuXG4gIGZpbHRlcjogZnVuY3Rpb24gKGNvbGxlY3Rpb24sIGZ1bikge1xuICAgIGxldCByZXN1bHQgPSBbXTtcblxuICAgIGZvciAobGV0IGVsZW0gb2YgY29sbGVjdGlvbikge1xuICAgICAgaWYgKGZ1bihlbGVtKSkge1xuICAgICAgICByZXN1bHQucHVzaChlbGVtKTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICByZXR1cm4gcmVzdWx0O1xuICB9LFxuXG4gIGZpbHRlcl9tYXA6IGZ1bmN0aW9uIChjb2xsZWN0aW9uLCBmaWx0ZXIsIG1hcHBlcikge1xuICAgIHJldHVybiBFbnVtLm1hcChFbnVtLmZpbHRlcihjb2xsZWN0aW9uLCBmaWx0ZXIpLCBtYXBwZXIpO1xuICB9LFxuXG4gIGZpbmQ6IGZ1bmN0aW9uIChjb2xsZWN0aW9uLCBpZl9ub25lID0gbnVsbCwgZnVuKSB7XG4gICAgZm9yIChsZXQgZWxlbSBvZiBjb2xsZWN0aW9uKSB7XG4gICAgICBpZiAoZnVuKGVsZW0pKSB7XG4gICAgICAgIHJldHVybiBlbGVtO1xuICAgICAgfVxuICAgIH1cblxuICAgIHJldHVybiBpZl9ub25lO1xuICB9LFxuXG4gIGludG86IGZ1bmN0aW9uIChjb2xsZWN0aW9uLCBsaXN0KSB7XG4gICAgcmV0dXJuIGxpc3QuY29uY2F0KGNvbGxlY3Rpb24pO1xuICB9LFxuXG4gIG1hcDogZnVuY3Rpb24gKGNvbGxlY3Rpb24sIGZ1bikge1xuICAgIGxldCByZXN1bHQgPSBbXTtcblxuICAgIGZvciAobGV0IGVsZW0gb2YgY29sbGVjdGlvbikge1xuICAgICAgcmVzdWx0LnB1c2goZnVuKGVsZW0pKTtcbiAgICB9XG5cbiAgICByZXR1cm4gcmVzdWx0O1xuICB9LFxuXG4gIG1hcF9yZWR1Y2U6IGZ1bmN0aW9uIChjb2xsZWN0aW9uLCBhY2MsIGZ1bikge1xuICAgIGxldCBtYXBwZWQgPSBLZXJuZWwuU3BlY2lhbEZvcm1zLmxpc3QoKTtcbiAgICBsZXQgdGhlX2FjYyA9IGFjYztcblxuICAgIGZvciAodmFyIGkgPSAwOyBpIDwgdGhpcy5jb3VudChjb2xsZWN0aW9uKTsgaSsrKSB7XG4gICAgICBsZXQgdHVwbGUgPSBmdW4oY29sbGVjdGlvbltpXSwgdGhlX2FjYyk7XG5cbiAgICAgIHRoZV9hY2MgPSBLZXJuZWwuZWxlbSh0dXBsZSwgMSk7XG4gICAgICBtYXBwZWQgPSBLZXJuZWwuU3BlY2lhbEZvcm1zLmxpc3QoLi4ubWFwcGVkLmNvbmNhdChbS2VybmVsLmVsZW0odHVwbGUsIDApXSkpO1xuICAgIH1cblxuICAgIHJldHVybiBLZXJuZWwuU3BlY2lhbEZvcm1zLnR1cGxlKG1hcHBlZCwgdGhlX2FjYyk7XG4gIH0sXG5cbiAgbWVtYmVyOiBmdW5jdGlvbiAoY29sbGVjdGlvbiwgdmFsdWUpIHtcbiAgICByZXR1cm4gY29sbGVjdGlvbi5pbmNsdWRlcyh2YWx1ZSk7XG4gIH0sXG5cbiAgcmVkdWNlOiBmdW5jdGlvbiAoY29sbGVjdGlvbiwgYWNjLCBmdW4pIHtcbiAgICBsZXQgdGhlX2FjYyA9IGFjYztcblxuICAgIGZvciAodmFyIGkgPSAwOyBpIDwgdGhpcy5jb3VudChjb2xsZWN0aW9uKTsgaSsrKSB7XG4gICAgICBsZXQgdHVwbGUgPSBmdW4oY29sbGVjdGlvbltpXSwgdGhlX2FjYyk7XG5cbiAgICAgIHRoZV9hY2MgPSBLZXJuZWwuZWxlbSh0dXBsZSwgMSk7XG4gICAgfVxuXG4gICAgcmV0dXJuIHRoZV9hY2M7XG4gIH0sXG5cbiAgdGFrZTogZnVuY3Rpb24gKGNvbGxlY3Rpb24sIGNvdW50KSB7XG4gICAgcmV0dXJuIGNvbGxlY3Rpb24uc2xpY2UoMCwgY291bnQpO1xuICB9LFxuXG4gIHRha2VfZXZlcnk6IGZ1bmN0aW9uIChjb2xsZWN0aW9uLCBudGgpIHtcbiAgICBsZXQgcmVzdWx0ID0gW107XG4gICAgbGV0IGluZGV4ID0gMDtcblxuICAgIGZvciAobGV0IGVsZW0gb2YgY29sbGVjdGlvbikge1xuICAgICAgaWYgKGluZGV4ICUgbnRoID09PSAwKSB7XG4gICAgICAgIHJlc3VsdC5wdXNoKGVsZW0pO1xuICAgICAgfVxuICAgIH1cblxuICAgIHJldHVybiBLZXJuZWwuU3BlY2lhbEZvcm1zLmxpc3QoLi4ucmVzdWx0KTtcbiAgfSxcblxuICB0YWtlX3doaWxlOiBmdW5jdGlvbiAoY29sbGVjdGlvbiwgZnVuKSB7XG4gICAgbGV0IGNvdW50ID0gMDtcblxuICAgIGZvciAobGV0IGVsZW0gb2YgY29sbGVjdGlvbikge1xuICAgICAgaWYgKGZ1bihlbGVtKSkge1xuICAgICAgICBjb3VudCA9IGNvdW50ICsgMTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIGJyZWFrO1xuICAgICAgfVxuICAgIH1cblxuICAgIHJldHVybiBjb2xsZWN0aW9uLnNsaWNlKDAsIGNvdW50KTtcbiAgfSxcblxuICB0b19saXN0OiBmdW5jdGlvbiAoY29sbGVjdGlvbikge1xuICAgIHJldHVybiBjb2xsZWN0aW9uO1xuICB9XG59O1xuXG5sZXQgU3BlY2lhbEZvcm1zID0ge1xuXG4gIF9fRElSX186IGZ1bmN0aW9uICgpIHtcbiAgICBpZiAoX19kaXJuYW1lKSB7XG4gICAgICByZXR1cm4gX19kaXJuYW1lO1xuICAgIH1cblxuICAgIGlmIChkb2N1bWVudC5jdXJyZW50U2NyaXB0KSB7XG4gICAgICByZXR1cm4gZG9jdW1lbnQuY3VycmVudFNjcmlwdC5zcmM7XG4gICAgfVxuXG4gICAgcmV0dXJuIG51bGw7XG4gIH0sXG5cbiAgYXRvbTogZnVuY3Rpb24gKF92YWx1ZSkge1xuICAgIHJldHVybiBTeW1ib2wuZm9yKF92YWx1ZSk7XG4gIH0sXG5cbiAgbGlzdDogZnVuY3Rpb24gKC4uLmFyZ3MpIHtcbiAgICByZXR1cm4gT2JqZWN0LmZyZWV6ZShhcmdzKTtcbiAgfSxcblxuICBiaXRzdHJpbmc6IGZ1bmN0aW9uICguLi5hcmdzKSB7XG4gICAgcmV0dXJuIG5ldyBCaXRTdHJpbmcoLi4uYXJncyk7XG4gIH0sXG5cbiAgYm91bmQ6IGZ1bmN0aW9uIChfdmFyKSB7XG4gICAgcmV0dXJuIFBhdHRlcm5zLmJvdW5kKF92YXIpO1xuICB9LFxuXG4gIF9jYXNlOiBmdW5jdGlvbiAoY29uZGl0aW9uLCBjbGF1c2VzKSB7XG4gICAgcmV0dXJuIFBhdHRlcm5zLmRlZm1hdGNoKC4uLmNsYXVzZXMpKGNvbmRpdGlvbik7XG4gIH0sXG5cbiAgY29uZDogZnVuY3Rpb24gKGNsYXVzZXMpIHtcbiAgICBmb3IgKGxldCBjbGF1c2Ugb2YgY2xhdXNlcykge1xuICAgICAgaWYgKGNsYXVzZVswXSkge1xuICAgICAgICByZXR1cm4gY2xhdXNlWzFdKCk7XG4gICAgICB9XG4gICAgfVxuXG4gICAgdGhyb3cgbmV3IEVycm9yKCk7XG4gIH0sXG5cbiAgZm46IGZ1bmN0aW9uIChjbGF1c2VzKSB7XG4gICAgcmV0dXJuIFBhdHRlcm5zLmRlZm1hdGNoKGNsYXVzZXMpO1xuICB9LFxuXG4gIG1hcDogZnVuY3Rpb24gKG9iaikge1xuICAgIHJldHVybiBPYmplY3QuZnJlZXplKG9iaik7XG4gIH0sXG5cbiAgbWFwX3VwZGF0ZTogZnVuY3Rpb24gKG1hcCwgdmFsdWVzKSB7XG4gICAgcmV0dXJuIE9iamVjdC5mcmVlemUoT2JqZWN0LmFzc2lnbihPYmplY3QuY3JlYXRlKG1hcC5jb25zdHJ1Y3Rvci5wcm90b3R5cGUpLCBtYXAsIHZhbHVlcykpO1xuICB9LFxuXG4gIF9mb3I6IGZ1bmN0aW9uIChjb2xsZWN0aW9ucywgZnVuLCBmaWx0ZXIgPSAoKSA9PiB0cnVlLCBpbnRvID0gW10sIHByZXZpb3VzVmFsdWVzID0gW10pIHtcbiAgICBsZXQgcGF0dGVybiA9IGNvbGxlY3Rpb25zWzBdWzBdO1xuICAgIGxldCBjb2xsZWN0aW9uID0gY29sbGVjdGlvbnNbMF1bMV07XG5cbiAgICBpZiAoY29sbGVjdGlvbnMubGVuZ3RoID09PSAxKSB7XG5cbiAgICAgIGZvciAobGV0IGVsZW0gb2YgY29sbGVjdGlvbikge1xuICAgICAgICBsZXQgciA9IFBhdHRlcm5zLm1hdGNoX25vX3Rocm93KHBhdHRlcm4sIGVsZW0pO1xuICAgICAgICBsZXQgYXJncyA9IHByZXZpb3VzVmFsdWVzLmNvbmNhdChyKTtcblxuICAgICAgICBpZiAociAmJiBmaWx0ZXIuYXBwbHkodGhpcywgYXJncykpIHtcbiAgICAgICAgICBpbnRvID0gRW51bS5pbnRvKFtmdW4uYXBwbHkodGhpcywgYXJncyldLCBpbnRvKTtcbiAgICAgICAgfVxuICAgICAgfVxuXG4gICAgICByZXR1cm4gaW50bztcbiAgICB9IGVsc2Uge1xuICAgICAgbGV0IF9pbnRvID0gW107XG5cbiAgICAgIGZvciAobGV0IGVsZW0gb2YgY29sbGVjdGlvbikge1xuICAgICAgICBsZXQgciA9IFBhdHRlcm5zLm1hdGNoX25vX3Rocm93KHBhdHRlcm4sIGVsZW0pO1xuICAgICAgICBpZiAocikge1xuICAgICAgICAgIF9pbnRvID0gRW51bS5pbnRvKHRoaXMuX2Zvcihjb2xsZWN0aW9ucy5zbGljZSgxKSwgZnVuLCBmaWx0ZXIsIF9pbnRvLCBwcmV2aW91c1ZhbHVlcy5jb25jYXQocikpLCBpbnRvKTtcbiAgICAgICAgfVxuICAgICAgfVxuXG4gICAgICByZXR1cm4gX2ludG87XG4gICAgfVxuICB9LFxuXG4gIHJlY2VpdmU6IGZ1bmN0aW9uIChyZWNlaXZlX2Z1biwgdGltZW91dF9pbl9tcyA9IG51bGwsIHRpbWVvdXRfZm4gPSB0aW1lID0+IHRydWUpIHtcbiAgICBpZiAodGltZW91dF9pbl9tcyA9PSBudWxsIHx8IHRpbWVvdXRfaW5fbXMgPT09IFN5c3RlbS5mb3IoJ2luZmluaXR5JykpIHtcbiAgICAgIHdoaWxlICh0cnVlKSB7XG4gICAgICAgIGlmIChzZWxmLm1haWxib3gubGVuZ3RoICE9PSAwKSB7XG4gICAgICAgICAgbGV0IG1lc3NhZ2UgPSBzZWxmLm1haWxib3hbMF07XG4gICAgICAgICAgc2VsZi5tYWlsYm94ID0gc2VsZi5tYWlsYm94LnNsaWNlKDEpO1xuICAgICAgICAgIHJldHVybiByZWNlaXZlX2Z1bihtZXNzYWdlKTtcbiAgICAgICAgfVxuICAgICAgfVxuICAgIH0gZWxzZSBpZiAodGltZW91dF9pbl9tcyA9PT0gMCkge1xuICAgICAgaWYgKHNlbGYubWFpbGJveC5sZW5ndGggIT09IDApIHtcbiAgICAgICAgbGV0IG1lc3NhZ2UgPSBzZWxmLm1haWxib3hbMF07XG4gICAgICAgIHNlbGYubWFpbGJveCA9IHNlbGYubWFpbGJveC5zbGljZSgxKTtcbiAgICAgICAgcmV0dXJuIHJlY2VpdmVfZnVuKG1lc3NhZ2UpO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgcmV0dXJuIG51bGw7XG4gICAgICB9XG4gICAgfSBlbHNlIHtcbiAgICAgIGxldCBub3cgPSBEYXRlLm5vdygpO1xuICAgICAgd2hpbGUgKERhdGUubm93KCkgPCBub3cgKyB0aW1lb3V0X2luX21zKSB7XG4gICAgICAgIGlmIChzZWxmLm1haWxib3gubGVuZ3RoICE9PSAwKSB7XG4gICAgICAgICAgbGV0IG1lc3NhZ2UgPSBzZWxmLm1haWxib3hbMF07XG4gICAgICAgICAgc2VsZi5tYWlsYm94ID0gc2VsZi5tYWlsYm94LnNsaWNlKDEpO1xuICAgICAgICAgIHJldHVybiByZWNlaXZlX2Z1bihtZXNzYWdlKTtcbiAgICAgICAgfVxuICAgICAgfVxuXG4gICAgICByZXR1cm4gdGltZW91dF9mbih0aW1lb3V0X2luX21zKTtcbiAgICB9XG4gIH0sXG5cbiAgdHVwbGU6IGZ1bmN0aW9uICguLi5hcmdzKSB7XG4gICAgcmV0dXJuIG5ldyBUdXBsZSQxKC4uLmFyZ3MpO1xuICB9LFxuXG4gIF90cnk6IGZ1bmN0aW9uIChkb19mdW4sIHJlc2N1ZV9mdW5jdGlvbiwgY2F0Y2hfZnVuLCBlbHNlX2Z1bmN0aW9uLCBhZnRlcl9mdW5jdGlvbikge1xuICAgIGxldCByZXN1bHQgPSBudWxsO1xuXG4gICAgdHJ5IHtcbiAgICAgIHJlc3VsdCA9IGRvX2Z1bigpO1xuICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgIGxldCBleF9yZXN1bHQgPSBudWxsO1xuXG4gICAgICBpZiAocmVzY3VlX2Z1bmN0aW9uKSB7XG4gICAgICAgIHRyeSB7XG4gICAgICAgICAgZXhfcmVzdWx0ID0gcmVzY3VlX2Z1bmN0aW9uKGUpO1xuICAgICAgICAgIHJldHVybiBleF9yZXN1bHQ7XG4gICAgICAgIH0gY2F0Y2ggKGV4KSB7XG4gICAgICAgICAgaWYgKGV4IGluc3RhbmNlb2YgUGF0dGVybnMuTWF0Y2hFcnJvcikge1xuICAgICAgICAgICAgdGhyb3cgZXg7XG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICB9XG5cbiAgICAgIGlmIChjYXRjaF9mdW4pIHtcbiAgICAgICAgdHJ5IHtcbiAgICAgICAgICBleF9yZXN1bHQgPSBjYXRjaF9mdW4oZSk7XG4gICAgICAgICAgcmV0dXJuIGV4X3Jlc3VsdDtcbiAgICAgICAgfSBjYXRjaCAoZXgpIHtcbiAgICAgICAgICBpZiAoZXggaW5zdGFuY2VvZiBQYXR0ZXJucy5NYXRjaEVycm9yKSB7XG4gICAgICAgICAgICB0aHJvdyBleDtcbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgIH1cblxuICAgICAgdGhyb3cgZTtcbiAgICB9IGZpbmFsbHkge1xuICAgICAgaWYgKGFmdGVyX2Z1bmN0aW9uKSB7XG4gICAgICAgIGFmdGVyX2Z1bmN0aW9uKCk7XG4gICAgICB9XG4gICAgfVxuXG4gICAgaWYgKGVsc2VfZnVuY3Rpb24pIHtcbiAgICAgIHRyeSB7XG4gICAgICAgIHJldHVybiBlbHNlX2Z1bmN0aW9uKHJlc3VsdCk7XG4gICAgICB9IGNhdGNoIChleCkge1xuICAgICAgICBpZiAoZXggaW5zdGFuY2VvZiBQYXR0ZXJucy5NYXRjaEVycm9yKSB7XG4gICAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdObyBNYXRjaCBGb3VuZCBpbiBFbHNlJyk7XG4gICAgICAgIH1cblxuICAgICAgICB0aHJvdyBleDtcbiAgICAgIH1cbiAgICB9IGVsc2Uge1xuICAgICAgcmV0dXJuIHJlc3VsdDtcbiAgICB9XG4gIH1cblxufTtcblxuZnVuY3Rpb24gdG9fc3RyaW5nJDEodHVwbGUpIHtcbiAgcmV0dXJuIHR1cGxlLnRvU3RyaW5nKCk7XG59O1xuXG5mdW5jdGlvbiBkZWxldGVfYXQodHVwbGUsIGluZGV4KSB7XG4gIGxldCBuZXdfbGlzdCA9IFtdO1xuXG4gIGZvciAodmFyIGkgPSAwOyBpIDwgdHVwbGUuY291bnQoKTsgaSsrKSB7XG4gICAgaWYgKGkgIT09IGluZGV4KSB7XG4gICAgICBuZXdfbGlzdC5wdXNoKHR1cGxlLmdldChpKSk7XG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIEtlcm5lbC5TcGVjaWFsRm9ybXMudHVwbGUuYXBwbHkobnVsbCwgbmV3X2xpc3QpO1xufTtcblxuZnVuY3Rpb24gZHVwbGljYXRlKGRhdGEsIHNpemUpIHtcbiAgbGV0IGFycmF5ID0gW107XG5cbiAgZm9yICh2YXIgaSA9IHNpemUgLSAxOyBpID49IDA7IGktLSkge1xuICAgIGFycmF5LnB1c2goZGF0YSk7XG4gIH1cblxuICByZXR1cm4gS2VybmVsLlNwZWNpYWxGb3Jtcy50dXBsZS5hcHBseShudWxsLCBhcnJheSk7XG59O1xuXG5mdW5jdGlvbiBpbnNlcnRfYXQodHVwbGUsIGluZGV4LCB0ZXJtKSB7XG4gIGxldCBuZXdfdHVwbGUgPSBbXTtcblxuICBmb3IgKHZhciBpID0gMDsgaSA8PSB0dXBsZS5jb3VudCgpOyBpKyspIHtcbiAgICBpZiAoaSA9PT0gaW5kZXgpIHtcbiAgICAgIG5ld190dXBsZS5wdXNoKHRlcm0pO1xuICAgICAgaSsrO1xuICAgICAgbmV3X3R1cGxlLnB1c2godHVwbGUuZ2V0KGkpKTtcbiAgICB9IGVsc2Uge1xuICAgICAgbmV3X3R1cGxlLnB1c2godHVwbGUuZ2V0KGkpKTtcbiAgICB9XG4gIH1cblxuICByZXR1cm4gS2VybmVsLlNwZWNpYWxGb3Jtcy50dXBsZS5hcHBseShudWxsLCBuZXdfdHVwbGUpO1xufTtcblxuZnVuY3Rpb24gZnJvbV9saXN0KGxpc3QpIHtcbiAgcmV0dXJuIEtlcm5lbC5TcGVjaWFsRm9ybXMudHVwbGUuYXBwbHkobnVsbCwgbGlzdCk7XG59O1xuXG5mdW5jdGlvbiB0b19saXN0KHR1cGxlKSB7XG4gIGxldCBuZXdfbGlzdCA9IFtdO1xuXG4gIGZvciAodmFyIGkgPSAwOyBpIDwgdHVwbGUuY291bnQoKTsgaSsrKSB7XG4gICAgbmV3X2xpc3QucHVzaCh0dXBsZS5nZXQoaSkpO1xuICB9XG5cbiAgcmV0dXJuIEtlcm5lbC5TcGVjaWFsRm9ybXMubGlzdCguLi5uZXdfbGlzdCk7XG59O1xuXG52YXIgVHVwbGUgPSB7XG4gIHRvX3N0cmluZzogdG9fc3RyaW5nJDEsXG4gIGRlbGV0ZV9hdCxcbiAgZHVwbGljYXRlLFxuICBpbnNlcnRfYXQsXG4gIGZyb21fbGlzdCxcbiAgdG9fbGlzdFxufTtcblxuLy9odHRwczovL2dpdGh1Yi5jb20vYWlycG9ydHloL3Byb3RvbW9ycGhpc21cbmNsYXNzIFByb3RvY29sIHtcbiAgY29uc3RydWN0b3Ioc3BlYykge1xuICAgIHRoaXMucmVnaXN0cnkgPSBuZXcgTWFwKCk7XG4gICAgdGhpcy5mYWxsYmFjayA9IG51bGw7XG5cbiAgICBmb3IgKGxldCBmdW5OYW1lIGluIHNwZWMpIHtcbiAgICAgIHRoaXNbZnVuTmFtZV0gPSBjcmVhdGVGdW4oZnVuTmFtZSkuYmluZCh0aGlzKTtcbiAgICB9XG5cbiAgICBmdW5jdGlvbiBjcmVhdGVGdW4oZnVuTmFtZSkge1xuXG4gICAgICByZXR1cm4gZnVuY3Rpb24gKC4uLmFyZ3MpIHtcbiAgICAgICAgbGV0IHRoaW5nID0gYXJnc1swXTtcbiAgICAgICAgbGV0IGZ1biA9IG51bGw7XG5cbiAgICAgICAgaWYgKE51bWJlci5pc0ludGVnZXIodGhpbmcpICYmIHRoaXMuaGFzSW1wbGVtZW50YXRpb24oSW50ZWdlciQxKSkge1xuICAgICAgICAgIGZ1biA9IHRoaXMucmVnaXN0cnkuZ2V0KEludGVnZXIkMSlbZnVuTmFtZV07XG4gICAgICAgIH0gZWxzZSBpZiAodHlwZW9mIHRoaW5nID09PSBcIm51bWJlclwiICYmICFOdW1iZXIuaXNJbnRlZ2VyKHRoaW5nKSAmJiB0aGlzLmhhc0ltcGxlbWVudGF0aW9uKEZsb2F0KSkge1xuICAgICAgICAgIGZ1biA9IHRoaXMucmVnaXN0cnkuZ2V0KEZsb2F0KVtmdW5OYW1lXTtcbiAgICAgICAgfSBlbHNlIGlmICh0aGlzLmhhc0ltcGxlbWVudGF0aW9uKHRoaW5nKSkge1xuICAgICAgICAgIGZ1biA9IHRoaXMucmVnaXN0cnkuZ2V0KHRoaW5nLmNvbnN0cnVjdG9yKVtmdW5OYW1lXTtcbiAgICAgICAgfSBlbHNlIGlmICh0aGlzLmZhbGxiYWNrKSB7XG4gICAgICAgICAgZnVuID0gdGhpcy5mYWxsYmFja1tmdW5OYW1lXTtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmIChmdW4gIT0gbnVsbCkge1xuICAgICAgICAgIGxldCByZXR2YWwgPSBmdW4uYXBwbHkodGhpcywgYXJncyk7XG4gICAgICAgICAgcmV0dXJuIHJldHZhbDtcbiAgICAgICAgfVxuXG4gICAgICAgIHRocm93IG5ldyBFcnJvcihcIk5vIGltcGxlbWVudGF0aW9uIGZvdW5kIGZvciBcIiArIHRoaW5nKTtcbiAgICAgIH07XG4gICAgfVxuICB9XG5cbiAgaW1wbGVtZW50YXRpb24odHlwZSwgaW1wbGVtZW50YXRpb24pIHtcbiAgICBpZiAodHlwZSA9PT0gbnVsbCkge1xuICAgICAgdGhpcy5mYWxsYmFjayA9IGltcGxlbWVudGF0aW9uO1xuICAgIH0gZWxzZSB7XG4gICAgICB0aGlzLnJlZ2lzdHJ5LnNldCh0eXBlLCBpbXBsZW1lbnRhdGlvbik7XG4gICAgfVxuICB9XG5cbiAgaGFzSW1wbGVtZW50YXRpb24odGhpbmcpIHtcbiAgICByZXR1cm4gdGhpcy5yZWdpc3RyeS5oYXModGhpbmcuY29uc3RydWN0b3IpO1xuICB9XG59XG5cbmZ1bmN0aW9uIHRsKGxpc3QpIHtcbiAgcmV0dXJuIFNwZWNpYWxGb3Jtcy5saXN0KC4uLmxpc3Quc2xpY2UoMSkpO1xufVxuXG5mdW5jdGlvbiBoZChsaXN0KSB7XG4gIHJldHVybiBsaXN0WzBdO1xufVxuXG5mdW5jdGlvbiBpc19uaWwoeCkge1xuICByZXR1cm4geCA9PT0gbnVsbDtcbn1cblxuZnVuY3Rpb24gaXNfYXRvbSh4KSB7XG4gIHJldHVybiB0eXBlb2YgeCA9PT0gJ3N5bWJvbCc7XG59XG5cbmZ1bmN0aW9uIGlzX2JpbmFyeSh4KSB7XG4gIHJldHVybiB0eXBlb2YgeCA9PT0gJ3N0cmluZycgfHwgeCBpbnN0YW5jZW9mIFN0cmluZztcbn1cblxuZnVuY3Rpb24gaXNfYm9vbGVhbih4KSB7XG4gIHJldHVybiB0eXBlb2YgeCA9PT0gJ2Jvb2xlYW4nIHx8IHggaW5zdGFuY2VvZiBCb29sZWFuO1xufVxuXG5mdW5jdGlvbiBpc19mdW5jdGlvbih4LCBhcml0eSA9IC0xKSB7XG4gIHJldHVybiB0eXBlb2YgeCA9PT0gJ2Z1bmN0aW9uJyB8fCB4IGluc3RhbmNlb2YgRnVuY3Rpb247XG59XG5cbmZ1bmN0aW9uIGlzX2Zsb2F0KHgpIHtcbiAgcmV0dXJuIGlzX251bWJlcih4KSAmJiAhTnVtYmVyLmlzSW50ZWdlcih4KTtcbn1cblxuZnVuY3Rpb24gaXNfaW50ZWdlcih4KSB7XG4gIHJldHVybiBOdW1iZXIuaXNJbnRlZ2VyKHgpO1xufVxuXG5mdW5jdGlvbiBpc19saXN0KHgpIHtcbiAgcmV0dXJuIHggaW5zdGFuY2VvZiBBcnJheTtcbn1cblxuZnVuY3Rpb24gaXNfbWFwKHgpIHtcbiAgcmV0dXJuIHR5cGVvZiB4ID09PSAnb2JqZWN0JyB8fCB4IGluc3RhbmNlb2YgT2JqZWN0O1xufVxuXG5mdW5jdGlvbiBpc19udW1iZXIoeCkge1xuICByZXR1cm4gdHlwZW9mIHggPT09ICdudW1iZXInO1xufVxuXG5mdW5jdGlvbiBpc190dXBsZSh4KSB7XG4gIHJldHVybiB4IGluc3RhbmNlb2YgVHVwbGUkMTtcbn1cblxuZnVuY3Rpb24gbGVuZ3RoKHgpIHtcbiAgcmV0dXJuIHgubGVuZ3RoO1xufVxuXG5mdW5jdGlvbiBpc19waWQoeCkge1xuICByZXR1cm4geCBpbnN0YW5jZW9mIFBJRDtcbn1cblxuZnVuY3Rpb24gaXNfcG9ydCh4KSB7XG4gIHJldHVybiBmYWxzZTtcbn1cblxuZnVuY3Rpb24gaXNfcmVmZXJlbmNlKHgpIHtcbiAgcmV0dXJuIGZhbHNlO1xufVxuXG5mdW5jdGlvbiBpc19iaXRzdHJpbmcoeCkge1xuICByZXR1cm4gaXNfYmluYXJ5KHgpIHx8IHggaW5zdGFuY2VvZiBCaXRTdHJpbmc7XG59XG5cbmZ1bmN0aW9uIF9faW5fXyhsZWZ0LCByaWdodCkge1xuICBmb3IgKGxldCB4IG9mIHJpZ2h0KSB7XG4gICAgaWYgKG1hdGNoX19xbWFya19fKGxlZnQsIHgpKSB7XG4gICAgICByZXR1cm4gdHJ1ZTtcbiAgICB9XG4gIH1cblxuICByZXR1cm4gZmFsc2U7XG59XG5cbmZ1bmN0aW9uIGFicyhudW1iZXIpIHtcbiAgcmV0dXJuIE1hdGguYWJzKG51bWJlcik7XG59XG5cbmZ1bmN0aW9uIHJvdW5kKG51bWJlcikge1xuICByZXR1cm4gTWF0aC5yb3VuZChudW1iZXIpO1xufVxuXG5mdW5jdGlvbiBlbGVtKHR1cGxlLCBpbmRleCkge1xuICBpZiAoaXNfbGlzdCh0dXBsZSkpIHtcbiAgICByZXR1cm4gdHVwbGVbaW5kZXhdO1xuICB9XG5cbiAgcmV0dXJuIHR1cGxlLmdldChpbmRleCk7XG59XG5cbmZ1bmN0aW9uIHJlbShsZWZ0LCByaWdodCkge1xuICByZXR1cm4gbGVmdCAlIHJpZ2h0O1xufVxuXG5mdW5jdGlvbiBkaXYobGVmdCwgcmlnaHQpIHtcbiAgcmV0dXJuIGxlZnQgLyByaWdodDtcbn1cblxuZnVuY3Rpb24gYW5kKGxlZnQsIHJpZ2h0KSB7XG4gIHJldHVybiBsZWZ0ICYmIHJpZ2h0O1xufVxuXG5mdW5jdGlvbiBvcihsZWZ0LCByaWdodCkge1xuICByZXR1cm4gbGVmdCB8fCByaWdodDtcbn1cblxuZnVuY3Rpb24gbm90KGFyZykge1xuICByZXR1cm4gIWFyZztcbn1cblxuZnVuY3Rpb24gYXBwbHkoLi4uYXJncykge1xuICBpZiAoYXJncy5sZW5ndGggPT09IDMpIHtcbiAgICBsZXQgbW9kID0gYXJnc1swXTtcbiAgICBsZXQgZnVuYyA9IGFyZ3NbMV07XG4gICAgbGV0IGZ1bmNfYXJncyA9IGFyZ3NbMl07XG4gICAgcmV0dXJuIG1vZFtmdW5jXS5hcHBseShudWxsLCBmdW5jX2FyZ3MpO1xuICB9IGVsc2Uge1xuICAgIGxldCBmdW5jID0gYXJnc1swXTtcbiAgICBsZXQgZnVuY19hcmdzID0gYXJnc1sxXTtcblxuICAgIHJldHVybiBmdW5jLmFwcGx5KG51bGwsIGZ1bmNfYXJncyk7XG4gIH1cbn1cblxuZnVuY3Rpb24gdG9fc3RyaW5nKGFyZykge1xuICBpZiAoaXNfdHVwbGUoYXJnKSkge1xuICAgIHJldHVybiBUdXBsZS50b19zdHJpbmcoYXJnKTtcbiAgfVxuXG4gIHJldHVybiBhcmcudG9TdHJpbmcoKTtcbn1cblxuZnVuY3Rpb24gbWF0Y2hfX3FtYXJrX18ocGF0dGVybiwgZXhwciwgZ3VhcmQgPSAoKSA9PiB0cnVlKSB7XG4gIHJldHVybiBQYXR0ZXJucy5tYXRjaF9ub190aHJvdyhwYXR0ZXJuLCBleHByLCBndWFyZCkgIT0gbnVsbDtcbn1cblxuZnVuY3Rpb24gZGVmc3RydWN0KGRlZmF1bHRzKSB7XG4gIHJldHVybiBjbGFzcyB7XG4gICAgY29uc3RydWN0b3IodXBkYXRlID0ge30pIHtcbiAgICAgIGxldCB0aGVfdmFsdWVzID0gT2JqZWN0LmFzc2lnbihkZWZhdWx0cywgdXBkYXRlKTtcbiAgICAgIE9iamVjdC5hc3NpZ24odGhpcywgdGhlX3ZhbHVlcyk7XG4gICAgfVxuXG4gICAgc3RhdGljIGNyZWF0ZSh1cGRhdGVzID0ge30pIHtcbiAgICAgIGxldCB4ID0gbmV3IHRoaXModXBkYXRlcyk7XG4gICAgICByZXR1cm4gT2JqZWN0LmZyZWV6ZSh4KTtcbiAgICB9XG4gIH07XG59XG5cbmZ1bmN0aW9uIGRlZnByb3RvY29sKHNwZWMpIHtcbiAgcmV0dXJuIG5ldyBQcm90b2NvbChzcGVjKTtcbn1cblxuZnVuY3Rpb24gZGVmaW1wbChwcm90b2NvbCwgdHlwZSwgaW1wbCkge1xuICBwcm90b2NvbC5pbXBsZW1lbnRhdGlvbih0eXBlLCBpbXBsKTtcbn1cblxudmFyIEtlcm5lbCA9IHtcbiAgU3BlY2lhbEZvcm1zLFxuICB0bCxcbiAgaGQsXG4gIGlzX25pbCxcbiAgaXNfYXRvbSxcbiAgaXNfYmluYXJ5LFxuICBpc19ib29sZWFuLFxuICBpc19mdW5jdGlvbixcbiAgaXNfZmxvYXQsXG4gIGlzX2ludGVnZXIsXG4gIGlzX2xpc3QsXG4gIGlzX21hcCxcbiAgaXNfbnVtYmVyLFxuICBpc190dXBsZSxcbiAgbGVuZ3RoLFxuICBpc19waWQsXG4gIGlzX3BvcnQsXG4gIGlzX3JlZmVyZW5jZSxcbiAgaXNfYml0c3RyaW5nLFxuICBpbjogX19pbl9fLFxuICBhYnMsXG4gIHJvdW5kLFxuICBlbGVtLFxuICByZW0sXG4gIGRpdixcbiAgYW5kLFxuICBvcixcbiAgbm90LFxuICBhcHBseSxcbiAgdG9fc3RyaW5nLFxuICBtYXRjaF9fcW1hcmtfXyxcbiAgZGVmc3RydWN0LFxuICBkZWZwcm90b2NvbCxcbiAgZGVmaW1wbFxufTtcblxubGV0IEF0b20gPSB7fTtcblxuQXRvbS50b19zdHJpbmcgPSBmdW5jdGlvbiAoYXRvbSkge1xuICByZXR1cm4gU3ltYm9sLmtleUZvcihhdG9tKTtcbn07XG5cbkF0b20udG9fY2hhcl9saXN0ID0gZnVuY3Rpb24gKGF0b20pIHtcbiAgcmV0dXJuIEF0b20udG9fc3RyaW5nKGF0b20pLnNwbGl0KCcnKTtcbn07XG5cbmxldCBJbnRlZ2VyID0ge1xuXG4gIGlzX2V2ZW46IGZ1bmN0aW9uIChuKSB7XG4gICAgcmV0dXJuIG4gJSAyID09PSAwO1xuICB9LFxuXG4gIGlzX29kZDogZnVuY3Rpb24gKG4pIHtcbiAgICByZXR1cm4gbiAlIDIgIT09IDA7XG4gIH0sXG5cbiAgcGFyc2U6IGZ1bmN0aW9uIChiaW4pIHtcbiAgICBsZXQgcmVzdWx0ID0gcGFyc2VJbnQoYmluKTtcblxuICAgIGlmIChpc05hTihyZXN1bHQpKSB7XG4gICAgICByZXR1cm4gS2VybmVsLlNwZWNpYWxGb3Jtcy5hdG9tKFwiZXJyb3JcIik7XG4gICAgfVxuXG4gICAgbGV0IGluZGV4T2ZEb3QgPSBiaW4uaW5kZXhPZihcIi5cIik7XG5cbiAgICBpZiAoaW5kZXhPZkRvdCA+PSAwKSB7XG4gICAgICByZXR1cm4gS2VybmVsLlNwZWNpYWxGb3Jtcy50dXBsZShyZXN1bHQsIGJpbi5zdWJzdHJpbmcoaW5kZXhPZkRvdCkpO1xuICAgIH1cblxuICAgIHJldHVybiBLZXJuZWwuU3BlY2lhbEZvcm1zLnR1cGxlKHJlc3VsdCwgXCJcIik7XG4gIH0sXG5cbiAgdG9fY2hhcl9saXN0OiBmdW5jdGlvbiAobnVtYmVyLCBiYXNlID0gMTApIHtcbiAgICByZXR1cm4gbnVtYmVyLnRvU3RyaW5nKGJhc2UpLnNwbGl0KFwiXCIpO1xuICB9LFxuXG4gIHRvX3N0cmluZzogZnVuY3Rpb24gKG51bWJlciwgYmFzZSA9IDEwKSB7XG4gICAgcmV0dXJuIG51bWJlci50b1N0cmluZyhiYXNlKTtcbiAgfVxufTtcblxubGV0IENoYXJzJDEgPSBLZXJuZWwuZGVmcHJvdG9jb2woe1xuICB0b19zdHJpbmc6IGZ1bmN0aW9uICh0aGluZykge31cbn0pO1xuXG5LZXJuZWwuZGVmaW1wbChDaGFycyQxLCBCaXRTdHJpbmcsIHtcbiAgdG9fc3RyaW5nOiBmdW5jdGlvbiAodGhpbmcpIHtcbiAgICBpZiAoS2VybmVsLmlzX2JpbmFyeSh0aGluZykpIHtcbiAgICAgIHJldHVybiB0aGluZztcbiAgICB9XG5cbiAgICByZXR1cm4gdGhpbmcudG9TdHJpbmcoKTtcbiAgfVxufSk7XG5cbktlcm5lbC5kZWZpbXBsKENoYXJzJDEsIFN5bWJvbCwge1xuICB0b19zdHJpbmc6IGZ1bmN0aW9uICh0aGluZykge1xuICAgIGlmIChuaWwpIHtcbiAgICAgIHJldHVybiBcIlwiO1xuICAgIH1cblxuICAgIHJldHVybiBBdG9tLnRvX3N0cmluZyh0aGluZyk7XG4gIH1cbn0pO1xuXG5LZXJuZWwuZGVmaW1wbChDaGFycyQxLCBJbnRlZ2VyJDEsIHtcbiAgdG9fc3RyaW5nOiBmdW5jdGlvbiAodGhpbmcpIHtcbiAgICByZXR1cm4gSW50ZWdlci50b19zdHJpbmcodGhpbmcpO1xuICB9XG59KTtcblxuS2VybmVsLmRlZmltcGwoQ2hhcnMkMSwgRmxvYXQsIHtcbiAgdG9fc3RyaW5nOiBmdW5jdGlvbiAodGhpbmcpIHtcbiAgICByZXR1cm4gdGhpbmcudG9TdHJpbmc7XG4gIH1cbn0pO1xuXG5LZXJuZWwuZGVmaW1wbChDaGFycyQxLCBBcnJheSwge1xuICB0b19zdHJpbmc6IGZ1bmN0aW9uICh0aGluZykge1xuICAgIHJldHVybiB0aGluZy50b1N0cmluZygpO1xuICB9XG59KTtcblxuS2VybmVsLmRlZmltcGwoQ2hhcnMkMSwgVHVwbGUkMSwge1xuICB0b19zdHJpbmc6IGZ1bmN0aW9uICh0aGluZykge1xuICAgIHJldHVybiBUdXBsZS50b19zdHJpbmcodGhpbmcpO1xuICB9XG59KTtcblxuS2VybmVsLmRlZmltcGwoQ2hhcnMkMSwgbnVsbCwge1xuICB0b19zdHJpbmc6IGZ1bmN0aW9uICh0aGluZykge1xuICAgIHJldHVybiB0aGluZy50b1N0cmluZygpO1xuICB9XG59KTtcblxuZnVuY3Rpb24gdG9fYXRvbShzdHJpbmcpIHtcbiAgcmV0dXJuIFN5bWJvbC5mb3Ioc3RyaW5nKTtcbn1cblxuZnVuY3Rpb24gdG9fZXhpc3RpbmdfYXRvbShzdHJpbmcpIHtcbiAgcmV0dXJuIFN5bWJvbC5mb3Ioc3RyaW5nKTtcbn1cblxuZnVuY3Rpb24gdG9fY2hhcl9saXN0KHN0cmluZykge1xuICByZXR1cm4gc3RyaW5nLnNwbGl0KCcnKTtcbn1cblxuZnVuY3Rpb24gdG9fZmxvYXQoc3RyaW5nKSB7XG4gIHJldHVybiBwYXJzZUZsb2F0KHN0cmluZyk7XG59XG5cbmZ1bmN0aW9uIHRvX2ludGVnZXIoc3RyaW5nLCBiYXNlID0gMTApIHtcbiAgcmV0dXJuIHBhcnNlSW50KHN0cmluZywgYmFzZSk7XG59XG5cbmZ1bmN0aW9uIHVwY2FzZShiaW5hcnkpIHtcbiAgcmV0dXJuIGJpbmFyeS50b1VwcGVyQ2FzZSgpO1xufVxuXG5mdW5jdGlvbiBkb3duY2FzZShiaW5hcnkpIHtcbiAgcmV0dXJuIGJpbmFyeS50b0xvd2VyQ2FzZSgpO1xufVxuXG5mdW5jdGlvbiBhdChzdHJpbmcsIHBvc2l0aW9uKSB7XG4gIGlmIChwb3NpdGlvbiA+IHN0cmluZy5sZW5ndGggLSAxKSB7XG4gICAgcmV0dXJuIG51bGw7XG4gIH1cblxuICByZXR1cm4gc3RyaW5nW3Bvc2l0aW9uXTtcbn1cblxuZnVuY3Rpb24gY2FwaXRhbGl6ZShzdHJpbmcpIHtcbiAgbGV0IHJldHVyblN0cmluZyA9ICcnO1xuXG4gIGZvciAobGV0IGkgPSAwOyBpIDwgc3RyaW5nLmxlbmd0aDsgaSsrKSB7XG4gICAgaWYgKGkgPT09IDApIHtcbiAgICAgIHJldHVyblN0cmluZyA9IHJldHVyblN0cmluZyArIHN0cmluZ1tpXS50b1VwcGVyQ2FzZSgpO1xuICAgIH0gZWxzZSB7XG4gICAgICByZXR1cm5TdHJpbmcgPSByZXR1cm5TdHJpbmcgKyBzdHJpbmdbaV0udG9Mb3dlckNhc2UoKTtcbiAgICB9XG4gIH1cblxuICByZXR1cm4gcmV0dXJuU3RyaW5nO1xufVxuXG5mdW5jdGlvbiBjb2RlcG9pbnRzKHN0cmluZykge1xuICByZXR1cm4gdG9fY2hhcl9saXN0KHN0cmluZykubWFwKGZ1bmN0aW9uIChjKSB7XG4gICAgcmV0dXJuIGMuY29kZVBvaW50QXQoMCk7XG4gIH0pO1xufVxuXG5mdW5jdGlvbiBjb250YWluc19fcW1fXyhzdHJpbmcsIGNvbnRhaW5zKSB7XG4gIGlmIChBcnJheS5pc0FycmF5KGNvbnRhaW5zKSkge1xuICAgIHJldHVybiBjb250YWlucy5zb21lKGZ1bmN0aW9uIChzKSB7XG4gICAgICByZXR1cm4gc3RyaW5nLmluZGV4T2YocykgPiAtMTtcbiAgICB9KTtcbiAgfVxuXG4gIHJldHVybiBzdHJpbmcuaW5kZXhPZihjb250YWlucykgPiAtMTtcbn1cblxuZnVuY3Rpb24gZHVwbGljYXRlJDEoc3ViamVjdCwgbikge1xuICByZXR1cm4gc3ViamVjdC5yZXBlYXQobik7XG59XG5cbmZ1bmN0aW9uIGVuZHNfd2l0aF9fcW1fXyhzdHJpbmcsIHN1ZmZpeGVzKSB7XG4gIGlmIChBcnJheS5pc0FycmF5KHN1ZmZpeGVzKSkge1xuICAgIHJldHVybiBzdWZmaXhlcy5zb21lKGZ1bmN0aW9uIChzKSB7XG4gICAgICByZXR1cm4gc3RyaW5nLmVuZHNXaXRoKHMpO1xuICAgIH0pO1xuICB9XG5cbiAgcmV0dXJuIHN0cmluZy5lbmRzV2l0aChzdWZmaXhlcyk7XG59XG5cbmZ1bmN0aW9uIGZpcnN0KHN0cmluZykge1xuICBpZiAoIXN0cmluZykge1xuICAgIHJldHVybiBudWxsO1xuICB9XG5cbiAgcmV0dXJuIHN0cmluZ1swXTtcbn1cblxuZnVuY3Rpb24gZ3JhcGhlbWVzKHN0cmluZykge1xuICByZXR1cm4gc3RyaW5nLnNwbGl0KCcnKTtcbn1cblxuZnVuY3Rpb24gbGFzdChzdHJpbmcpIHtcbiAgaWYgKCFzdHJpbmcpIHtcbiAgICByZXR1cm4gbnVsbDtcbiAgfVxuXG4gIHJldHVybiBzdHJpbmdbc3RyaW5nLmxlbmd0aCAtIDFdO1xufVxuXG5mdW5jdGlvbiBsZW5ndGgkMShzdHJpbmcpIHtcbiAgcmV0dXJuIHN0cmluZy5sZW5ndGg7XG59XG5cbmZ1bmN0aW9uIG1hdGNoX19xbV9fKHN0cmluZywgcmVnZXgpIHtcbiAgcmV0dXJuIHN0cmluZy5tYXRjaChyZWdleCkgIT0gbnVsbDtcbn1cblxuZnVuY3Rpb24gbmV4dF9jb2RlcG9pbnQoc3RyaW5nKSB7XG4gIGlmICghc3RyaW5nIHx8IHN0cmluZyA9PT0gJycpIHtcbiAgICByZXR1cm4gbnVsbDtcbiAgfVxuXG4gIHJldHVybiBLZXJuZWwuU3BlY2lhbEZvcm1zLnR1cGxlKHN0cmluZ1swXS5jb2RlUG9pbnRBdCgwKSwgc3RyaW5nLnN1YnN0cigxKSk7XG59XG5cbmZ1bmN0aW9uIG5leHRfZ3JhcGhlbWUoc3RyaW5nKSB7XG4gIGlmICghc3RyaW5nIHx8IHN0cmluZyA9PT0gJycpIHtcbiAgICByZXR1cm4gbnVsbDtcbiAgfVxuXG4gIHJldHVybiBLZXJuZWwuU3BlY2lhbEZvcm1zLnR1cGxlKHN0cmluZ1swXSwgc3RyaW5nLnN1YnN0cigxKSk7XG59XG5cbmZ1bmN0aW9uIHJldmVyc2Uoc3RyaW5nKSB7XG4gIGxldCByZXR1cm5WYWx1ZSA9ICcnO1xuXG4gIGZvciAodmFyIGkgPSBzdHJpbmcubGVuZ3RoIC0gMTsgaSA+PSAwOyBpLS0pIHtcbiAgICByZXR1cm5WYWx1ZSA9IHJldHVyblZhbHVlICsgc3RyaW5nW2ldO1xuICB9O1xuXG4gIHJldHVybiByZXR1cm5WYWx1ZTtcbn1cblxuZnVuY3Rpb24gc3BsaXQoc3RyaW5nKSB7XG4gIHJldHVybiBzdHJpbmcuc3BsaXQoKTtcbn1cblxuZnVuY3Rpb24gc3RhcnRzX3dpdGhfX3FtX18oc3RyaW5nLCBwcmVmaXhlcykge1xuICBpZiAoQXJyYXkuaXNBcnJheShwcmVmaXhlcykpIHtcbiAgICByZXR1cm4gcHJlZml4ZXMuc29tZShmdW5jdGlvbiAocykge1xuICAgICAgcmV0dXJuIHN0cmluZy5zdGFydHNXaXRoKHMpO1xuICAgIH0pO1xuICB9XG5cbiAgcmV0dXJuIHN0cmluZy5zdGFydHNXaXRoKHByZWZpeGVzKTtcbn1cblxuZnVuY3Rpb24gdmFsaWRfY2hhcmFjdGVyX19xbV9fKGNvZGVwb2ludCkge1xuICB0cnkge1xuICAgIHJldHVybiBTdHJpbmcuZnJvbUNvZGVQb2ludChjb2RlcG9pbnQpICE9IG51bGw7XG4gIH0gY2F0Y2ggKGUpIHtcbiAgICByZXR1cm4gZmFsc2U7XG4gIH1cbn1cblxudmFyIFN0cmluZyQxID0ge1xuICBhdCxcbiAgY2FwaXRhbGl6ZSxcbiAgY29kZXBvaW50cyxcbiAgY29udGFpbnNfX3FtX18sXG4gIGRvd25jYXNlLFxuICBkdXBsaWNhdGU6IGR1cGxpY2F0ZSQxLFxuICBlbmRzX3dpdGhfX3FtX18sXG4gIGZpcnN0LFxuICBncmFwaGVtZXMsXG4gIGxhc3QsXG4gIGxlbmd0aDogbGVuZ3RoJDEsXG4gIG1hdGNoX19xbV9fLFxuICBuZXh0X2NvZGVwb2ludCxcbiAgbmV4dF9ncmFwaGVtZSxcbiAgcmV2ZXJzZSxcbiAgc3BsaXQsXG4gIHN0YXJ0c193aXRoX19xbV9fLFxuICB0b19hdG9tLFxuICB0b19jaGFyX2xpc3QsXG4gIHRvX2V4aXN0aW5nX2F0b20sXG4gIHRvX2Zsb2F0LFxuICB0b19pbnRlZ2VyLFxuICB1cGNhc2UsXG4gIHZhbGlkX2NoYXJhY3Rlcl9fcW1fXyxcbiAgQ2hhcnM6IENoYXJzJDFcbn07XG5cbmxldCBDaGFycyA9IEtlcm5lbC5kZWZwcm90b2NvbCh7XG4gIHRvX2NoYXJfbGlzdDogZnVuY3Rpb24gKHRoaW5nKSB7fVxufSk7XG5cbktlcm5lbC5kZWZpbXBsKENoYXJzLCBCaXRTdHJpbmcsIHtcbiAgdG9fY2hhcl9saXN0OiBmdW5jdGlvbiAodGhpbmcpIHtcbiAgICBpZiAoS2VybmVsLmlzX2JpbmFyeSh0aGluZykpIHtcbiAgICAgIHJldHVybiBTdHJpbmckMS50b19jaGFyX2xpc3QodGhpbmcpO1xuICAgIH1cblxuICAgIHJldHVybiB0aGluZy50b1N0cmluZygpO1xuICB9XG59KTtcblxuS2VybmVsLmRlZmltcGwoQ2hhcnMsIFN5bWJvbCwge1xuICB0b19jaGFyX2xpc3Q6IGZ1bmN0aW9uICh0aGluZykge1xuICAgIHJldHVybiBBdG9tLnRvX2NoYXJfbGlzdCh0aGluZyk7XG4gIH1cbn0pO1xuXG5LZXJuZWwuZGVmaW1wbChDaGFycywgSW50ZWdlciQxLCB7XG4gIHRvX2NoYXJfbGlzdDogZnVuY3Rpb24gKHRoaW5nKSB7XG4gICAgcmV0dXJuIEludGVnZXIudG9fY2hhcl9saXN0KHRoaW5nKTtcbiAgfVxufSk7XG5cbktlcm5lbC5kZWZpbXBsKENoYXJzLCBBcnJheSwge1xuICB0b19jaGFyX2xpc3Q6IGZ1bmN0aW9uICh0aGluZykge1xuICAgIHJldHVybiB0aGluZztcbiAgfVxufSk7XG5cbmxldCBMaXN0ID0ge307XG5cbkxpc3QuQ2hhcnMgPSBDaGFycztcblxuTGlzdC5kZWxldGUgPSBmdW5jdGlvbiAobGlzdCwgaXRlbSkge1xuICBsZXQgbmV3X3ZhbHVlID0gW107XG4gIGxldCB2YWx1ZV9mb3VuZCA9IGZhbHNlO1xuXG4gIGZvciAobGV0IHggb2YgbGlzdCkge1xuICAgIGlmICh4ID09PSBpdGVtICYmIHZhbHVlX2ZvdW5kICE9PSBmYWxzZSkge1xuICAgICAgbmV3X3ZhbHVlLnB1c2goeCk7XG4gICAgICB2YWx1ZV9mb3VuZCA9IHRydWU7XG4gICAgfSBlbHNlIGlmICh4ICE9PSBpdGVtKSB7XG4gICAgICBuZXdfdmFsdWUucHVzaCh4KTtcbiAgICB9XG4gIH1cblxuICByZXR1cm4gS2VybmVsLlNwZWNpYWxGb3Jtcy5saXN0KC4uLm5ld192YWx1ZSk7XG59O1xuXG5MaXN0LmRlbGV0ZV9hdCA9IGZ1bmN0aW9uIChsaXN0LCBpbmRleCkge1xuICBsZXQgbmV3X3ZhbHVlID0gW107XG5cbiAgZm9yIChsZXQgaSA9IDA7IGkgPCBsaXN0Lmxlbmd0aDsgaSsrKSB7XG4gICAgaWYgKGkgIT09IGluZGV4KSB7XG4gICAgICBuZXdfdmFsdWUucHVzaChsaXN0W2ldKTtcbiAgICB9XG4gIH1cblxuICByZXR1cm4gS2VybmVsLlNwZWNpYWxGb3Jtcy5saXN0KC4uLm5ld192YWx1ZSk7XG59O1xuXG5MaXN0LmR1cGxpY2F0ZSA9IGZ1bmN0aW9uIChlbGVtLCBuKSB7XG4gIGxldCBuZXdfdmFsdWUgPSBbXTtcblxuICBmb3IgKHZhciBpID0gMDsgaSA8IG47IGkrKykge1xuICAgIG5ld192YWx1ZS5wdXNoKGVsZW0pO1xuICB9XG5cbiAgcmV0dXJuIEtlcm5lbC5TcGVjaWFsRm9ybXMubGlzdCguLi5uZXdfdmFsdWUpO1xufTtcblxuTGlzdC5maXJzdCA9IGZ1bmN0aW9uIChsaXN0KSB7XG4gIHJldHVybiBsaXN0WzBdO1xufTtcblxuTGlzdC5mbGF0dGVuID0gZnVuY3Rpb24gKGxpc3QsIHRhaWwgPSBLZXJuZWwuU3BlY2lhbEZvcm1zLmxpc3QoKSkge1xuICBsZXQgbmV3X3ZhbHVlID0gW107XG5cbiAgZm9yIChsZXQgeCBvZiBsaXN0KSB7XG4gICAgaWYgKEtlcm5lbC5pc19saXN0KHgpKSB7XG4gICAgICBuZXdfdmFsdWUgPSBuZXdfdmFsdWUuY29uY2F0KExpc3QuZmxhdHRlbih4KSk7XG4gICAgfSBlbHNlIHtcbiAgICAgIG5ld192YWx1ZS5wdXNoKHgpO1xuICAgIH1cbiAgfVxuXG4gIG5ld192YWx1ZSA9IG5ld192YWx1ZS5jb25jYXQodGFpbCk7XG5cbiAgcmV0dXJuIEtlcm5lbC5TcGVjaWFsRm9ybXMubGlzdCguLi5uZXdfdmFsdWUpO1xufTtcblxuTGlzdC5mb2xkbCA9IGZ1bmN0aW9uIChsaXN0LCBhY2MsIGZ1bmMpIHtcbiAgcmV0dXJuIGxpc3QucmVkdWNlKGZ1bmMsIGFjYyk7XG59O1xuXG5MaXN0LmZvbGRyID0gZnVuY3Rpb24gKGxpc3QsIGFjYywgZnVuYykge1xuICBsZXQgbmV3X2FjYyA9IGFjYztcblxuICBmb3IgKHZhciBpID0gbGlzdC5sZW5ndGggLSAxOyBpID49IDA7IGktLSkge1xuICAgIG5ld19hY2MgPSBmdW5jKGxpc3RbaV0sIG5ld19hY2MpO1xuICB9XG5cbiAgcmV0dXJuIG5ld19hY2M7XG59O1xuXG5MaXN0Lmluc2VydF9hdCA9IGZ1bmN0aW9uIChsaXN0LCBpbmRleCwgdmFsdWUpIHtcbiAgbGV0IG5ld192YWx1ZSA9IFtdO1xuXG4gIGZvciAobGV0IGkgPSAwOyBpIDwgbGlzdC5sZW5ndGg7IGkrKykge1xuICAgIGlmIChpID09PSBpbmRleCkge1xuICAgICAgbmV3X3ZhbHVlLnB1c2godmFsdWUpO1xuICAgICAgbmV3X3ZhbHVlLnB1c2gobGlzdFtpXSk7XG4gICAgfSBlbHNlIHtcbiAgICAgIG5ld192YWx1ZS5wdXNoKGxpc3RbaV0pO1xuICAgIH1cbiAgfVxuXG4gIHJldHVybiBLZXJuZWwuU3BlY2lhbEZvcm1zLmxpc3QoLi4ubmV3X3ZhbHVlKTtcbn07XG5cbkxpc3Qua2V5ZGVsZXRlID0gZnVuY3Rpb24gKGxpc3QsIGtleSwgcG9zaXRpb24pIHtcbiAgbGV0IG5ld19saXN0ID0gW107XG5cbiAgZm9yIChsZXQgaSA9IDA7IGkgPCBsaXN0Lmxlbmd0aDsgaSsrKSB7XG4gICAgaWYgKCFLZXJuZWwubWF0Y2hfX3FtYXJrX18obGlzdFtpXVtwb3NpdGlvbl0sIGtleSkpIHtcbiAgICAgIG5ld19saXN0LnB1c2gobGlzdFtpXSk7XG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIEtlcm5lbC5TcGVjaWFsRm9ybXMubGlzdCguLi5uZXdfbGlzdCk7XG59O1xuXG5MaXN0LmtleWZpbmQgPSBmdW5jdGlvbiAobGlzdCwga2V5LCBwb3NpdGlvbiwgX2RlZmF1bHQgPSBudWxsKSB7XG5cbiAgZm9yIChsZXQgaSA9IDA7IGkgPCBsaXN0Lmxlbmd0aDsgaSsrKSB7XG4gICAgaWYgKEtlcm5lbC5tYXRjaF9fcW1hcmtfXyhsaXN0W2ldW3Bvc2l0aW9uXSwga2V5KSkge1xuICAgICAgcmV0dXJuIGxpc3RbaV07XG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIF9kZWZhdWx0O1xufTtcblxuTGlzdC5rZXltZW1iZXJfX3FtYXJrX18gPSBmdW5jdGlvbiAobGlzdCwga2V5LCBwb3NpdGlvbikge1xuXG4gIGZvciAobGV0IGkgPSAwOyBpIDwgbGlzdC5sZW5ndGg7IGkrKykge1xuICAgIGlmIChLZXJuZWwubWF0Y2hfX3FtYXJrX18obGlzdFtpXVtwb3NpdGlvbl0sIGtleSkpIHtcbiAgICAgIHJldHVybiB0cnVlO1xuICAgIH1cbiAgfVxuXG4gIHJldHVybiBmYWxzZTtcbn07XG5cbkxpc3Qua2V5cmVwbGFjZSA9IGZ1bmN0aW9uIChsaXN0LCBrZXksIHBvc2l0aW9uLCBuZXdfdHVwbGUpIHtcbiAgbGV0IG5ld19saXN0ID0gW107XG5cbiAgZm9yIChsZXQgaSA9IDA7IGkgPCBsaXN0Lmxlbmd0aDsgaSsrKSB7XG4gICAgaWYgKCFLZXJuZWwubWF0Y2hfX3FtYXJrX18obGlzdFtpXVtwb3NpdGlvbl0sIGtleSkpIHtcbiAgICAgIG5ld19saXN0LnB1c2gobGlzdFtpXSk7XG4gICAgfSBlbHNlIHtcbiAgICAgIG5ld19saXN0LnB1c2gobmV3X3R1cGxlKTtcbiAgICB9XG4gIH1cblxuICByZXR1cm4gS2VybmVsLlNwZWNpYWxGb3Jtcy5saXN0KC4uLm5ld19saXN0KTtcbn07XG5cbkxpc3Qua2V5c29ydCA9IGZ1bmN0aW9uIChsaXN0LCBwb3NpdGlvbikge1xuICBsZXQgbmV3X2xpc3QgPSBsaXN0O1xuXG4gIG5ld19saXN0LnNvcnQoZnVuY3Rpb24gKGEsIGIpIHtcbiAgICBpZiAocG9zaXRpb24gPT09IDApIHtcbiAgICAgIGlmIChhW3Bvc2l0aW9uXS52YWx1ZSA8IGJbcG9zaXRpb25dLnZhbHVlKSB7XG4gICAgICAgIHJldHVybiAtMTtcbiAgICAgIH1cblxuICAgICAgaWYgKGFbcG9zaXRpb25dLnZhbHVlID4gYltwb3NpdGlvbl0udmFsdWUpIHtcbiAgICAgICAgcmV0dXJuIDE7XG4gICAgICB9XG5cbiAgICAgIHJldHVybiAwO1xuICAgIH0gZWxzZSB7XG4gICAgICBpZiAoYVtwb3NpdGlvbl0gPCBiW3Bvc2l0aW9uXSkge1xuICAgICAgICByZXR1cm4gLTE7XG4gICAgICB9XG5cbiAgICAgIGlmIChhW3Bvc2l0aW9uXSA+IGJbcG9zaXRpb25dKSB7XG4gICAgICAgIHJldHVybiAxO1xuICAgICAgfVxuXG4gICAgICByZXR1cm4gMDtcbiAgICB9XG4gIH0pO1xuXG4gIHJldHVybiBLZXJuZWwuU3BlY2lhbEZvcm1zLmxpc3QoLi4ubmV3X2xpc3QpO1xufTtcblxuTGlzdC5rZXlzdG9yZSA9IGZ1bmN0aW9uIChsaXN0LCBrZXksIHBvc2l0aW9uLCBuZXdfdHVwbGUpIHtcbiAgbGV0IG5ld19saXN0ID0gW107XG4gIGxldCByZXBsYWNlZCA9IGZhbHNlO1xuXG4gIGZvciAobGV0IGkgPSAwOyBpIDwgbGlzdC5sZW5ndGg7IGkrKykge1xuICAgIGlmICghS2VybmVsLm1hdGNoX19xbWFya19fKGxpc3RbaV1bcG9zaXRpb25dLCBrZXkpKSB7XG4gICAgICBuZXdfbGlzdC5wdXNoKGxpc3RbaV0pO1xuICAgIH0gZWxzZSB7XG4gICAgICBuZXdfbGlzdC5wdXNoKG5ld190dXBsZSk7XG4gICAgICByZXBsYWNlZCA9IHRydWU7XG4gICAgfVxuICB9XG5cbiAgaWYgKCFyZXBsYWNlZCkge1xuICAgIG5ld19saXN0LnB1c2gobmV3X3R1cGxlKTtcbiAgfVxuXG4gIHJldHVybiBLZXJuZWwuU3BlY2lhbEZvcm1zLmxpc3QoLi4ubmV3X2xpc3QpO1xufTtcblxuTGlzdC5sYXN0ID0gZnVuY3Rpb24gKGxpc3QpIHtcbiAgcmV0dXJuIGxpc3RbbGlzdC5sZW5ndGggLSAxXTtcbn07XG5cbkxpc3QucmVwbGFjZV9hdCA9IGZ1bmN0aW9uIChsaXN0LCBpbmRleCwgdmFsdWUpIHtcbiAgbGV0IG5ld192YWx1ZSA9IFtdO1xuXG4gIGZvciAobGV0IGkgPSAwOyBpIDwgbGlzdC5sZW5ndGg7IGkrKykge1xuICAgIGlmIChpID09PSBpbmRleCkge1xuICAgICAgbmV3X3ZhbHVlLnB1c2godmFsdWUpO1xuICAgIH0gZWxzZSB7XG4gICAgICBuZXdfdmFsdWUucHVzaChsaXN0W2ldKTtcbiAgICB9XG4gIH1cblxuICByZXR1cm4gS2VybmVsLlNwZWNpYWxGb3Jtcy5saXN0KC4uLm5ld192YWx1ZSk7XG59O1xuXG5MaXN0LnVwZGF0ZV9hdCA9IGZ1bmN0aW9uIChsaXN0LCBpbmRleCwgZnVuKSB7XG4gIGxldCBuZXdfdmFsdWUgPSBbXTtcblxuICBmb3IgKGxldCBpID0gMDsgaSA8IGxpc3QuY291bnQoKTsgaSsrKSB7XG4gICAgaWYgKGkgPT09IGluZGV4KSB7XG4gICAgICBuZXdfdmFsdWUucHVzaChmdW4obGlzdC5nZXQoaSkpKTtcbiAgICB9IGVsc2Uge1xuICAgICAgbmV3X3ZhbHVlLnB1c2gobGlzdC5nZXQoaSkpO1xuICAgIH1cbiAgfVxuXG4gIHJldHVybiBuZXdfdmFsdWU7XG59O1xuXG5MaXN0LndyYXAgPSBmdW5jdGlvbiAobGlzdCkge1xuICBpZiAoS2VybmVsLmlzX2xpc3QobGlzdCkpIHtcbiAgICByZXR1cm4gbGlzdDtcbiAgfSBlbHNlIGlmIChsaXN0ID09IG51bGwpIHtcbiAgICByZXR1cm4gS2VybmVsLlNwZWNpYWxGb3Jtcy5saXN0KCk7XG4gIH0gZWxzZSB7XG4gICAgcmV0dXJuIEtlcm5lbC5TcGVjaWFsRm9ybXMubGlzdChsaXN0KTtcbiAgfVxufTtcblxuTGlzdC56aXAgPSBmdW5jdGlvbiAobGlzdF9vZl9saXN0cykge1xuICBpZiAobGlzdF9vZl9saXN0cy5sZW5ndGggPT09IDApIHtcbiAgICByZXR1cm4gS2VybmVsLlNwZWNpYWxGb3Jtcy5saXN0KCk7XG4gIH1cblxuICBsZXQgbmV3X3ZhbHVlID0gW107XG4gIGxldCBzbWFsbGVzdF9sZW5ndGggPSBsaXN0X29mX2xpc3RzWzBdO1xuXG4gIGZvciAobGV0IHggb2YgbGlzdF9vZl9saXN0cykge1xuICAgIGlmICh4Lmxlbmd0aCA8IHNtYWxsZXN0X2xlbmd0aCkge1xuICAgICAgc21hbGxlc3RfbGVuZ3RoID0geC5sZW5ndGg7XG4gICAgfVxuICB9XG5cbiAgZm9yIChsZXQgaSA9IDA7IGkgPCBzbWFsbGVzdF9sZW5ndGg7IGkrKykge1xuICAgIGxldCBjdXJyZW50X3ZhbHVlID0gW107XG4gICAgZm9yIChsZXQgaiA9IDA7IGogPCBsaXN0X29mX2xpc3RzLmxlbmd0aDsgaisrKSB7XG4gICAgICBjdXJyZW50X3ZhbHVlLnB1c2gobGlzdF9vZl9saXN0c1tqXVtpXSk7XG4gICAgfVxuXG4gICAgbmV3X3ZhbHVlLnB1c2goS2VybmVsLlNwZWNpYWxGb3Jtcy50dXBsZSguLi5jdXJyZW50X3ZhbHVlKSk7XG4gIH1cblxuICByZXR1cm4gS2VybmVsLlNwZWNpYWxGb3Jtcy5saXN0KC4uLm5ld192YWx1ZSk7XG59O1xuXG5MaXN0LnRvX3R1cGxlID0gZnVuY3Rpb24gKGxpc3QpIHtcbiAgcmV0dXJuIEtlcm5lbC5TcGVjaWFsRm9ybXMudHVwbGUuYXBwbHkobnVsbCwgbGlzdCk7XG59O1xuXG5MaXN0LmFwcGVuZCA9IGZ1bmN0aW9uIChsaXN0LCB2YWx1ZSkge1xuICByZXR1cm4gS2VybmVsLlNwZWNpYWxGb3Jtcy5saXN0KC4uLmxpc3QuY29uY2F0KFt2YWx1ZV0pKTtcbn07XG5cbkxpc3QucHJlcGVuZCA9IGZ1bmN0aW9uIChsaXN0LCB2YWx1ZSkge1xuICByZXR1cm4gS2VybmVsLlNwZWNpYWxGb3Jtcy5saXN0KC4uLlt2YWx1ZV0uY29uY2F0KGxpc3QpKTtcbn07XG5cbkxpc3QuY29uY2F0ID0gZnVuY3Rpb24gKGxlZnQsIHJpZ2h0KSB7XG4gIHJldHVybiBsZWZ0LmNvbmNhdChyaWdodCk7XG59O1xuXG5sZXQgUmFuZ2UgPSBmdW5jdGlvbiAoX2ZpcnN0LCBfbGFzdCkge1xuICBpZiAoISh0aGlzIGluc3RhbmNlb2YgUmFuZ2UpKSB7XG4gICAgcmV0dXJuIG5ldyBSYW5nZShfZmlyc3QsIF9sYXN0KTtcbiAgfVxuXG4gIHRoaXMuZmlyc3QgPSBmdW5jdGlvbiAoKSB7XG4gICAgcmV0dXJuIF9maXJzdDtcbiAgfTtcblxuICB0aGlzLmxhc3QgPSBmdW5jdGlvbiAoKSB7XG4gICAgcmV0dXJuIF9sYXN0O1xuICB9O1xuXG4gIGxldCBfcmFuZ2UgPSBbXTtcblxuICBmb3IgKGxldCBpID0gX2ZpcnN0OyBpIDw9IF9sYXN0OyBpKyspIHtcbiAgICBfcmFuZ2UucHVzaChpKTtcbiAgfVxuXG4gIF9yYW5nZSA9IE9iamVjdC5mcmVlemUoX3JhbmdlKTtcblxuICB0aGlzLnZhbHVlID0gZnVuY3Rpb24gKCkge1xuICAgIHJldHVybiBfcmFuZ2U7XG4gIH07XG5cbiAgdGhpcy5sZW5ndGggPSBmdW5jdGlvbiAoKSB7XG4gICAgcmV0dXJuIF9yYW5nZS5sZW5ndGg7XG4gIH07XG5cbiAgcmV0dXJuIHRoaXM7XG59O1xuXG5SYW5nZS5wcm90b3R5cGVbU3ltYm9sLml0ZXJhdG9yXSA9IGZ1bmN0aW9uICgpIHtcbiAgcmV0dXJuIHRoaXMudmFsdWUoKVtTeW1ib2wuaXRlcmF0b3JdKCk7XG59O1xuXG5SYW5nZS5uZXcgPSBmdW5jdGlvbiAoZmlyc3QsIGxhc3QpIHtcbiAgcmV0dXJuIFJhbmdlKGZpcnN0LCBsYXN0KTtcbn07XG5cblJhbmdlLnJhbmdlX19xbWFya19fID0gZnVuY3Rpb24gKHJhbmdlKSB7XG4gIHJldHVybiByYW5nZSBpbnN0YW5jZW9mIFJhbmdlO1xufTtcblxubGV0IEtleXdvcmQgPSB7fTtcblxuS2V5d29yZC5oYXNfa2V5X19xbV9fID0gZnVuY3Rpb24gKGtleXdvcmRzLCBrZXkpIHtcbiAgZm9yIChsZXQga2V5d29yZCBvZiBrZXl3b3Jkcykge1xuICAgIGlmIChLZXJuZWwuZWxlbShrZXl3b3JkLCAwKSA9PSBrZXkpIHtcbiAgICAgIHJldHVybiB0cnVlO1xuICAgIH1cbiAgfVxuXG4gIHJldHVybiBmYWxzZTtcbn07XG5cbktleXdvcmQuZ2V0ID0gZnVuY3Rpb24gKGtleXdvcmRzLCBrZXksIHRoZV9kZWZhdWx0ID0gbnVsbCkge1xuICBmb3IgKGxldCBrZXl3b3JkIG9mIGtleXdvcmRzKSB7XG4gICAgaWYgKEtlcm5lbC5lbGVtKGtleXdvcmQsIDApID09IGtleSkge1xuICAgICAgcmV0dXJuIEtlcm5lbC5lbGVtKGtleXdvcmQsIDEpO1xuICAgIH1cbiAgfVxuXG4gIHJldHVybiB0aGVfZGVmYXVsdDtcbn07XG5cbmxldCBBZ2VudCA9IHt9O1xuXG5BZ2VudC5zdGFydCA9IGZ1bmN0aW9uIChmdW4sIG9wdGlvbnMgPSBbXSkge1xuICBsZXQgcGlkID0gc2VsZi5wcm9jZXNzZXMuc3Bhd24oKTtcblxuICBpZiAoS2V5d29yZC5oYXNfa2V5X19xbV9fKG9wdGlvbnMsIEtlcm5lbC5TcGVjaWFsRm9ybXMuYXRvbSgnbmFtZScpKSkge1xuICAgIHBpZCA9IHNlbGYucHJvY2Vzc2VzLnJlZ2lzdGVyKEtleXdvcmQuZ2V0KG9wdGlvbnMsIEtlcm5lbC5TcGVjaWFsRm9ybXMuYXRvbSgnbmFtZScpKSwgcGlkKTtcbiAgfVxuXG4gIHNlbGYucHJvY2Vzc2VzLnB1dChwaWQsICdzdGF0ZScsIGZ1bigpKTtcbiAgcmV0dXJuIEtlcm5lbC5TcGVjaWFsRm9ybXMudHVwbGUoS2VybmVsLlNwZWNpYWxGb3Jtcy5hdG9tKCdvaycpLCBwaWQpO1xufTtcblxuQWdlbnQuc3RvcCA9IGZ1bmN0aW9uIChhZ2VudCwgdGltZW91dCA9IDUwMDApIHtcbiAgc2VsZi5wcm9jZXNzZXMuZXhpdChhZ2VudCk7XG4gIHJldHVybiBLZXJuZWwuU3BlY2lhbEZvcm1zLmF0b20oJ29rJyk7XG59O1xuXG5BZ2VudC51cGRhdGUgPSBmdW5jdGlvbiAoYWdlbnQsIGZ1biwgdGltZW91dCA9IDUwMDApIHtcblxuICBjb25zdCBjdXJyZW50X3N0YXRlID0gc2VsZi5wcm9jZXNzZXMuZ2V0KGFnZW50LCAnc3RhdGUnKTtcbiAgc2VsZi5wcm9jZXNzZXMucHV0KGFnZW50LCAnc3RhdGUnLCBmdW4oY3VycmVudF9zdGF0ZSkpO1xuXG4gIHJldHVybiBLZXJuZWwuU3BlY2lhbEZvcm1zLmF0b20oJ29rJyk7XG59O1xuXG5BZ2VudC5nZXQgPSBmdW5jdGlvbiAoYWdlbnQsIGZ1biwgdGltZW91dCA9IDUwMDApIHtcbiAgcmV0dXJuIGZ1bihzZWxmLnByb2Nlc3Nlcy5nZXQoYWdlbnQsICdzdGF0ZScpKTtcbn07XG5cbkFnZW50LmdldF9hbmRfdXBkYXRlID0gZnVuY3Rpb24gKGFnZW50LCBmdW4sIHRpbWVvdXQgPSA1MDAwKSB7XG5cbiAgY29uc3QgZ2V0X2FuZF91cGRhdGVfdHVwbGUgPSBmdW4oc2VsZi5wcm9jZXNzZXMuZ2V0KGFnZW50LCAnc3RhdGUnKSk7XG4gIHNlbGYucHJvY2Vzc2VzLnB1dChhZ2VudCwgJ3N0YXRlJywgS2VybmVsLmVsZW0oZ2V0X2FuZF91cGRhdGVfdHVwbGUsIDEpKTtcblxuICByZXR1cm4gS2VybmVsLmVsZW0oZ2V0X2FuZF91cGRhdGVfdHVwbGUsIDApO1xufTtcblxuLy9odHRwczovL2RldmVsb3Blci5tb3ppbGxhLm9yZy9lbi1VUy9kb2NzL1dlYi9BUEkvV2luZG93QmFzZTY0L0Jhc2U2NF9lbmNvZGluZ19hbmRfZGVjb2RpbmcjU29sdXRpb25fMl8lRTIlODAlOTNfcmV3cml0ZV90aGVfRE9Nc19hdG9iKClfYW5kX2J0b2EoKV91c2luZ19KYXZhU2NyaXB0J3NfVHlwZWRBcnJheXNfYW5kX1VURi04XG5mdW5jdGlvbiBiNjRFbmNvZGVVbmljb2RlKHN0cikge1xuICByZXR1cm4gYnRvYShlbmNvZGVVUklDb21wb25lbnQoc3RyKS5yZXBsYWNlKC8lKFswLTlBLUZdezJ9KS9nLCBmdW5jdGlvbiAobWF0Y2gsIHAxKSB7XG4gICAgcmV0dXJuIFN0cmluZy5mcm9tQ2hhckNvZGUoJzB4JyArIHAxKTtcbiAgfSkpO1xufVxuXG5mdW5jdGlvbiBlbmNvZGU2NChkYXRhKSB7XG4gIHJldHVybiBiNjRFbmNvZGVVbmljb2RlKGRhdGEpO1xufVxuXG5mdW5jdGlvbiBkZWNvZGU2NChkYXRhKSB7XG4gIHRyeSB7XG4gICAgcmV0dXJuIEtlcm5lbC5TcGVjaWFsRm9ybXMudHVwbGUoS2VybmVsLlNwZWNpYWxGb3Jtcy5hdG9tKCdvaycpLCBhdG9iKGRhdGEpKTtcbiAgfSBjYXRjaCAoZSkge1xuICAgIHJldHVybiBLZXJuZWwuU3BlY2lhbEZvcm1zLmF0b20oJ2Vycm9yJyk7XG4gIH1cbiAgcmV0dXJuIGJ0b2EoZGF0YSk7XG59XG5cbmZ1bmN0aW9uIGRlY29kZTY0X19lbV9fKGRhdGEpIHtcbiAgcmV0dXJuIGF0b2IoZGF0YSk7XG59XG5cbnZhciBiYXNlID0ge1xuICBlbmNvZGU2NCxcbiAgZGVjb2RlNjQsXG4gIGRlY29kZTY0X19lbV9fXG59O1xuXG5mdW5jdGlvbiBibm90KGV4cHIpIHtcbiAgcmV0dXJuIH5leHByO1xufVxuXG5mdW5jdGlvbiBiYW5kKGxlZnQsIHJpZ2h0KSB7XG4gIHJldHVybiBsZWZ0ICYgcmlnaHQ7XG59XG5cbmZ1bmN0aW9uIGJvcihsZWZ0LCByaWdodCkge1xuICByZXR1cm4gbGVmdCB8IHJpZ2h0O1xufVxuXG5mdW5jdGlvbiBic2wobGVmdCwgcmlnaHQpIHtcbiAgcmV0dXJuIGxlZnQgPDwgcmlnaHQ7XG59XG5cbmZ1bmN0aW9uIGJzcihsZWZ0LCByaWdodCkge1xuICByZXR1cm4gbGVmdCA+PiByaWdodDtcbn1cblxuZnVuY3Rpb24gYnhvcihsZWZ0LCByaWdodCkge1xuICByZXR1cm4gbGVmdCBeIHJpZ2h0O1xufVxuXG52YXIgYml0d2lzZSA9IHtcbiAgYm5vdCxcbiAgYmFuZCxcbiAgYm9yLFxuICBic2wsXG4gIGJzcixcbiAgYnhvclxufTtcblxubGV0IEVudW1lcmFibGUgPSBLZXJuZWwuZGVmcHJvdG9jb2woe1xuICBjb3VudDogZnVuY3Rpb24gKGNvbGxlY3Rpb24pIHt9LFxuICBtZW1iZXJfcW1hcmtfXzogZnVuY3Rpb24gKGNvbGxlY3Rpb24sIHZhbHVlKSB7fSxcbiAgcmVkdWNlOiBmdW5jdGlvbiAoY29sbGVjdGlvbiwgYWNjLCBmdW4pIHt9XG59KTtcblxubGV0IENvbGxlY3RhYmxlID0gS2VybmVsLmRlZnByb3RvY29sKHtcbiAgaW50bzogZnVuY3Rpb24gKGNvbGxlY3RhYmxlKSB7fVxufSk7XG5cbmxldCBJbnNwZWN0ID0gS2VybmVsLmRlZnByb3RvY29sKHtcbiAgaW5zcGVjdDogZnVuY3Rpb24gKHRoaW5nLCBvcHRzKSB7fVxufSk7XG5cbmZ1bmN0aW9uIF9fbmV3X18oKSB7XG4gIHJldHVybiBTcGVjaWFsRm9ybXMubWFwKHt9KTtcbn1cblxuZnVuY3Rpb24ga2V5cyhtYXApIHtcbiAgcmV0dXJuIE9iamVjdC5rZXlzKG1hcCk7XG59XG5cbmZ1bmN0aW9uIHNpemUobWFwKSB7XG4gIHJldHVybiBrZXlzKG1hcCkubGVuZ3RoO1xufVxuXG5mdW5jdGlvbiB0b19saXN0JDEobWFwKSB7XG4gIGxldCBtYXBfa2V5cyA9IGtleXMobWFwKTtcbiAgbGV0IGxpc3QgPSBbXTtcblxuICBmb3IgKGxldCBrZXkgb2YgbWFwX2tleXMpIHtcbiAgICBsaXN0LnB1c2goU3BlY2lhbEZvcm1zLnR1cGxlKGtleSwgbWFwW2tleV0pKTtcbiAgfVxuXG4gIHJldHVybiBTcGVjaWFsRm9ybXMubGlzdCguLi5saXN0KTtcbn1cblxuZnVuY3Rpb24gdmFsdWVzKG1hcCkge1xuICBsZXQgbWFwX2tleXMgPSBrZXlzKG1hcCk7XG4gIGxldCBsaXN0ID0gW107XG5cbiAgZm9yIChsZXQga2V5IG9mIG1hcF9rZXlzKSB7XG4gICAgbGlzdC5wdXNoKG1hcFtrZXldKTtcbiAgfVxuXG4gIHJldHVybiBTcGVjaWFsRm9ybXMubGlzdCguLi5saXN0KTtcbn1cblxuZnVuY3Rpb24gZnJvbV9zdHJ1Y3Qoc3RydWN0KSB7XG4gIGxldCBtYXAgPSBPYmplY3QuYXNzaWduKHt9LCBzdHJ1Y3QpO1xuICBkZWxldGUgbWFwW1N5bWJvbC5mb3IoXCJfX3N0cnVjdF9fXCIpXTtcblxuICByZXR1cm4gU3BlY2lhbEZvcm1zLm1hcChtYXApO1xufVxuXG5mdW5jdGlvbiBfX2RlbGV0ZV9fKG1hcCwga2V5KSB7XG4gIGxldCBuZXdfbWFwID0gT2JqZWN0LmFzc2lnbih7fSwgbWFwKTtcblxuICBkZWxldGUgbmV3X21hcFtrZXldO1xuXG4gIHJldHVybiBTcGVjaWFsRm9ybXMubWFwKG5ld19tYXApO1xufVxuXG5mdW5jdGlvbiBlcXVhbF9fcW1hcmtfXyhtYXAxLCBtYXAyKSB7XG4gIHJldHVybiBtYXAxID09PSBtYXAyO1xufVxuXG5mdW5jdGlvbiBmZXRjaF9fZW1hcmtfXyhtYXAsIGtleSkge1xuICBpZiAoa2V5IGluIG1hcCkge1xuICAgIHJldHVybiBtYXBba2V5XTtcbiAgfVxuXG4gIHRocm93IG5ldyBFcnJvcihcIktleSBub3QgZm91bmQuXCIpO1xufVxuXG5mdW5jdGlvbiBmZXRjaChtYXAsIGtleSkge1xuICBpZiAoa2V5IGluIG1hcCkge1xuICAgIHJldHVybiBTcGVjaWFsRm9ybXMudHVwbGUoU3BlY2lhbEZvcm1zLmF0b20oXCJva1wiKSwgbWFwW2tleV0pO1xuICB9XG5cbiAgcmV0dXJuIFNwZWNpYWxGb3Jtcy5hdG9tKFwiZXJyb3JcIik7XG59XG5cbmZ1bmN0aW9uIGhhc19rZXlfX3FtYXJrX18obWFwLCBrZXkpIHtcbiAgcmV0dXJuIGtleSBpbiBtYXA7XG59XG5cbmZ1bmN0aW9uIHNwbGl0JDEobWFwLCBrZXlzKSB7XG4gIGxldCBzcGxpdDEgPSB7fTtcbiAgbGV0IHNwbGl0MiA9IHt9O1xuXG4gIGZvciAobGV0IGtleSBvZiBPYmplY3Qua2V5cyhtYXApKSB7XG4gICAgaWYgKGtleXMuaW5kZXhPZihrZXkpID4gLTEpIHtcbiAgICAgIHNwbGl0MVtrZXldID0gbWFwW2tleV07XG4gICAgfSBlbHNlIHtcbiAgICAgIHNwbGl0MltrZXldID0gbWFwW2tleV07XG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIFNwZWNpYWxGb3Jtcy50dXBsZShTcGVjaWFsRm9ybXMubWFwKHNwbGl0MSksIFNwZWNpYWxGb3Jtcy5tYXAoc3BsaXQyKSk7XG59XG5cbmZ1bmN0aW9uIHRha2UobWFwLCBrZXlzKSB7XG4gIGxldCBzcGxpdDEgPSB7fTtcblxuICBmb3IgKGxldCBrZXkgb2YgT2JqZWN0LmtleXMobWFwKSkge1xuICAgIGlmIChrZXlzLmluZGV4T2Yoa2V5KSA+IC0xKSB7XG4gICAgICBzcGxpdDFba2V5XSA9IG1hcFtrZXldO1xuICAgIH1cbiAgfVxuXG4gIHJldHVybiBTcGVjaWFsRm9ybXMubWFwKHNwbGl0MSk7XG59XG5cbmZ1bmN0aW9uIGRyb3AobWFwLCBrZXlzKSB7XG4gIGxldCBzcGxpdDEgPSB7fTtcblxuICBmb3IgKGxldCBrZXkgb2YgT2JqZWN0LmtleXMobWFwKSkge1xuICAgIGlmIChrZXlzLmluZGV4T2Yoa2V5KSA9PT0gLTEpIHtcbiAgICAgIHNwbGl0MVtrZXldID0gbWFwW2tleV07XG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIFNwZWNpYWxGb3Jtcy5tYXAoc3BsaXQxKTtcbn1cblxuZnVuY3Rpb24gcHV0X25ldyhtYXAsIGtleSwgdmFsdWUpIHtcbiAgaWYgKGtleSBpbiBtYXApIHtcbiAgICByZXR1cm4gbWFwO1xuICB9XG5cbiAgbGV0IG5ld19tYXAgPSBPYmplY3QuYXNzaWduKHt9LCBtYXApO1xuICBuZXdfbWFwW2tleV0gPSB2YWx1ZTtcblxuICByZXR1cm4gU3BlY2lhbEZvcm1zLm1hcChuZXdfbWFwKTtcbn1cblxuZnVuY3Rpb24gcHV0X25ld19sYXp5KG1hcCwga2V5LCBmdW4pIHtcbiAgaWYgKGtleSBpbiBtYXApIHtcbiAgICByZXR1cm4gbWFwO1xuICB9XG5cbiAgbGV0IG5ld19tYXAgPSBPYmplY3QuYXNzaWduKHt9LCBtYXApO1xuICBuZXdfbWFwW2tleV0gPSBmdW4oKTtcblxuICByZXR1cm4gU3BlY2lhbEZvcm1zLm1hcChuZXdfbWFwKTtcbn1cblxuZnVuY3Rpb24gZ2V0X2FuZF91cGRhdGUobWFwLCBrZXksIGZ1bikge1xuICBpZiAoa2V5IGluIG1hcCkge1xuICAgIHJldHVybiBtYXA7XG4gIH1cblxuICBsZXQgbmV3X21hcCA9IE9iamVjdC5hc3NpZ24oe30sIG1hcCk7XG4gIG5ld19tYXBba2V5XSA9IGZ1bihtYXBba2V5XSk7XG5cbiAgcmV0dXJuIFNwZWNpYWxGb3Jtcy5tYXAobmV3X21hcCk7XG59XG5cbmZ1bmN0aW9uIHBvcF9sYXp5KG1hcCwga2V5LCBmdW4pIHtcbiAgaWYgKCFrZXkgaW4gbWFwKSB7XG4gICAgcmV0dXJuIFNwZWNpYWxGb3Jtcy50dXBsZShmdW4oKSwgbWFwKTtcbiAgfVxuXG4gIGxldCBuZXdfbWFwID0gT2JqZWN0LmFzc2lnbih7fSwgbWFwKTtcbiAgbGV0IHZhbHVlID0gZnVuKG5ld19tYXBba2V5XSk7XG4gIGRlbGV0ZSBuZXdfbWFwW2tleV07XG5cbiAgcmV0dXJuIFNwZWNpYWxGb3Jtcy50dXBsZSh2YWx1ZSwgbmV3X21hcCk7XG59XG5cbmZ1bmN0aW9uIHBvcChtYXAsIGtleSwgX2RlZmF1bHQgPSBudWxsKSB7XG4gIGlmICgha2V5IGluIG1hcCkge1xuICAgIHJldHVybiBTcGVjaWFsRm9ybXMudHVwbGUoX2RlZmF1bHQsIG1hcCk7XG4gIH1cblxuICBsZXQgbmV3X21hcCA9IE9iamVjdC5hc3NpZ24oe30sIG1hcCk7XG4gIGxldCB2YWx1ZSA9IG5ld19tYXBba2V5XTtcbiAgZGVsZXRlIG5ld19tYXBba2V5XTtcblxuICByZXR1cm4gU3BlY2lhbEZvcm1zLnR1cGxlKHZhbHVlLCBuZXdfbWFwKTtcbn1cblxuZnVuY3Rpb24gZ2V0X2xhenkobWFwLCBrZXksIGZ1bikge1xuICBpZiAoIWtleSBpbiBtYXApIHtcbiAgICByZXR1cm4gZnVuKCk7XG4gIH1cblxuICByZXR1cm4gZnVuKG1hcFtrZXldKTtcbn1cblxuZnVuY3Rpb24gZ2V0KG1hcCwga2V5LCBfZGVmYXVsdCA9IG51bGwpIHtcbiAgaWYgKCFrZXkgaW4gbWFwKSB7XG4gICAgcmV0dXJuIF9kZWZhdWx0O1xuICB9XG5cbiAgcmV0dXJuIG1hcFtrZXldO1xufVxuXG5mdW5jdGlvbiBwdXQobWFwLCBrZXksIHZhbCkge1xuICBsZXQgbmV3X21hcCA9IE9iamVjdCh7fSwgbWFwKTtcbiAgbmV3X21hcFtrZXldID0gdmFsO1xuXG4gIHJldHVybiBTcGVjaWFsRm9ybXMubWFwKG5ld19tYXApO1xufVxuXG5mdW5jdGlvbiB1cGRhdGVfX2VtYXJrX18obWFwLCBrZXksIGZ1bikge1xuICBpZiAoIWtleSBpbiBtYXApIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoXCJLZXkgbm90IGZvdW5kXCIpO1xuICB9XG5cbiAgbGV0IG5ld19tYXAgPSBPYmplY3Qoe30sIG1hcCk7XG4gIG5ld19tYXBba2V5XSA9IGZ1bihtYXBba2V5XSk7XG5cbiAgcmV0dXJuIFNwZWNpYWxGb3Jtcy5tYXAobmV3X21hcCk7XG59XG5cbmZ1bmN0aW9uIHVwZGF0ZShtYXAsIGtleSwgaW5pdGlhbCwgZnVuKSB7XG4gIGxldCBuZXdfbWFwID0gT2JqZWN0KHt9LCBtYXApO1xuXG4gIGlmICgha2V5IGluIG1hcCkge1xuICAgIG5ld19tYXBba2V5XSA9IGluaXRpYWw7XG4gIH0gZWxzZSB7XG4gICAgbmV3X21hcFtrZXldID0gZnVuKG1hcFtrZXldKTtcbiAgfVxuXG4gIHJldHVybiBTcGVjaWFsRm9ybXMubWFwKG5ld19tYXApO1xufVxuXG52YXIgbWFwID0ge1xuICBuZXc6IF9fbmV3X18sXG4gIGtleXMsXG4gIHNpemUsXG4gIHRvX2xpc3Q6IHRvX2xpc3QkMSxcbiAgdmFsdWVzLFxuICBmcm9tX3N0cnVjdCxcbiAgZGVsZXRlOiBfX2RlbGV0ZV9fLFxuICBkcm9wLFxuICBlcXVhbF9fcW1hcmtfXyxcbiAgZmV0Y2hfX2VtYXJrX18sXG4gIGZldGNoLFxuICBoYXNfa2V5X19xbWFya19fLFxuICBzcGxpdDogc3BsaXQkMSxcbiAgdGFrZSxcbiAgcHV0X25ldyxcbiAgcHV0X25ld19sYXp5LFxuICBnZXRfYW5kX3VwZGF0ZSxcbiAgcG9wX2xhenksXG4gIHBvcCxcbiAgZ2V0X2xhenksXG4gIGdldCxcbiAgcHV0LFxuICB1cGRhdGVfX2VtYXJrX18sXG4gIHVwZGF0ZVxufTtcblxuZnVuY3Rpb24gX19uZXdfXyQxKCkge1xuICByZXR1cm4gU3BlY2lhbEZvcm1zLm1hcCh7IFtTeW1ib2wuZm9yKCdfX3N0cnVjdF9fJyldOiBTeW1ib2wuZm9yKCdNYXBTZXQnKSwgc2V0OiBTcGVjaWFsRm9ybXMubGlzdCgpIH0pO1xufVxuXG5mdW5jdGlvbiBzaXplJDIobWFwKSB7XG4gIHJldHVybiBtYXAuc2V0Lmxlbmd0aDtcbn1cblxuZnVuY3Rpb24gdG9fbGlzdCQzKG1hcCkge1xuICByZXR1cm4gbWFwLnNldDtcbn1cblxuZnVuY3Rpb24gX19kZWxldGVfXyQyKHNldCwgdGVybSkge1xuICBsZXQgbmV3X2xpc3QgPSBMaXN0LmRlbGV0ZShzZXQuc2V0LCB0ZXJtKTtcblxuICBsZXQgbmV3X21hcCA9IE9iamVjdC5hc3NpZ24oe30sIHNldCk7XG4gIG5ld19tYXAuc2V0ID0gbmV3X2xpc3Q7XG4gIHJldHVybiBTcGVjaWFsRm9ybXMubWFwKG5ld19tYXApO1xufVxuXG5mdW5jdGlvbiBwdXQkMihzZXQsIHRlcm0pIHtcbiAgaWYgKHNldC5zZXQuaW5kZXhPZih0ZXJtKSA9PT0gLTEpIHtcbiAgICBsZXQgbmV3X2xpc3QgPSBMaXN0LmFwcGVuZChzZXQuc2V0LCB0ZXJtKTtcblxuICAgIGxldCBuZXdfbWFwID0gT2JqZWN0LmFzc2lnbih7fSwgc2V0KTtcbiAgICBuZXdfbWFwLnNldCA9IG5ld19saXN0O1xuICAgIHJldHVybiBTcGVjaWFsRm9ybXMubWFwKG5ld19tYXApO1xuICB9XG5cbiAgcmV0dXJuIHNldDtcbn1cblxuZnVuY3Rpb24gZGlmZmVyZW5jZSQxKHNldDEsIHNldDIpIHtcbiAgbGV0IG5ld19tYXAgPSBPYmplY3QuYXNzaWduKHt9LCBzZXQxKTtcblxuICBmb3IgKGxldCB2YWwgb2Ygc2V0MS5zZXQpIHtcbiAgICBpZiAobWVtYmVyX19xbWFya19fJDEoc2V0MiwgdmFsKSkge1xuICAgICAgbmV3X21hcC5zZXQgPSBMaXN0LmRlbGV0ZShuZXdfbWFwLnNldCwgdmFsKTtcbiAgICB9XG4gIH1cblxuICByZXR1cm4gU3BlY2lhbEZvcm1zLm1hcChuZXdfbWFwKTtcbn1cblxuZnVuY3Rpb24gaW50ZXJzZWN0aW9uJDEoc2V0MSwgc2V0Mikge1xuICBsZXQgbmV3X21hcCA9IE9iamVjdC5hc3NpZ24oe30sIHNldDEpO1xuXG4gIGZvciAobGV0IHZhbCBvZiBzZXQxLnNldCkge1xuICAgIGlmICghbWVtYmVyX19xbWFya19fJDEoc2V0MiwgdmFsKSkge1xuICAgICAgbmV3X21hcC5zZXQgPSBMaXN0LmRlbGV0ZShuZXdfbWFwLnNldCwgdmFsKTtcbiAgICB9XG4gIH1cblxuICByZXR1cm4gU3BlY2lhbEZvcm1zLm1hcChuZXdfbWFwKTtcbn1cblxuZnVuY3Rpb24gdW5pb24kMShzZXQxLCBzZXQyKSB7XG4gIGxldCBuZXdfbWFwID0gc2V0MTtcblxuICBmb3IgKGxldCB2YWwgb2Ygc2V0Mi5zZXQpIHtcbiAgICBuZXdfbWFwID0gcHV0JDIobmV3X21hcCwgdmFsKTtcbiAgfVxuXG4gIHJldHVybiBTcGVjaWFsRm9ybXMubWFwKG5ld19tYXApO1xufVxuXG5mdW5jdGlvbiBkaXNqb2luX19xbWFya19fJDEoc2V0MSwgc2V0Mikge1xuICBmb3IgKGxldCB2YWwgb2Ygc2V0MS5zZXQpIHtcbiAgICBpZiAobWVtYmVyX19xbWFya19fJDEoc2V0MiwgdmFsKSkge1xuICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH1cbiAgfVxuXG4gIHJldHVybiB0cnVlO1xufVxuXG5mdW5jdGlvbiBtZW1iZXJfX3FtYXJrX18kMShzZXQsIHZhbHVlKSB7XG4gIHJldHVybiBzZXQuc2V0LmluZGV4T2YodmFsdWUpID49IDA7XG59XG5cbmZ1bmN0aW9uIGVxdWFsX19xbWFya19fJDIoc2V0MSwgc2V0Mikge1xuICByZXR1cm4gc2V0MS5zZXQgPT09IHNldDIuc2V0O1xufVxuXG5mdW5jdGlvbiBzdWJzZXRfX3FtYXJrX18kMShzZXQxLCBzZXQyKSB7XG4gIGZvciAobGV0IHZhbCBvZiBzZXQxLnNldCkge1xuICAgIGlmICghbWVtYmVyX19xbWFya19fJDEoc2V0MiwgdmFsKSkge1xuICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH1cbiAgfVxuXG4gIHJldHVybiB0cnVlO1xufVxuXG52YXIgTWFwU2V0ID0ge1xuICBuZXc6IF9fbmV3X18kMSxcbiAgc2l6ZTogc2l6ZSQyLFxuICB0b19saXN0OiB0b19saXN0JDMsXG4gIGRpc2pvaW5fX3FtYXJrX186IGRpc2pvaW5fX3FtYXJrX18kMSxcbiAgZGVsZXRlOiBfX2RlbGV0ZV9fJDIsXG4gIHN1YnNldF9fcW1hcmtfXzogc3Vic2V0X19xbWFya19fJDEsXG4gIGVxdWFsX19xbWFya19fOiBlcXVhbF9fcW1hcmtfXyQyLFxuICBtZW1iZXJfX3FtYXJrX186IG1lbWJlcl9fcW1hcmtfXyQxLFxuICBwdXQ6IHB1dCQyLFxuICB1bmlvbjogdW5pb24kMSxcbiAgaW50ZXJzZWN0aW9uOiBpbnRlcnNlY3Rpb24kMSxcbiAgZGlmZmVyZW5jZTogZGlmZmVyZW5jZSQxXG59O1xuXG5mdW5jdGlvbiBzaXplJDEobWFwKSB7XG4gIHJldHVybiBNYXBTZXQuc2l6ZShtYXApO1xufVxuXG5mdW5jdGlvbiB0b19saXN0JDIobWFwKSB7XG4gIHJldHVybiBNYXBTZXQudG9fbGlzdChtYXApO1xufVxuXG5mdW5jdGlvbiBfX2RlbGV0ZV9fJDEoc2V0LCB0ZXJtKSB7XG4gIHJldHVybiBNYXBTZXQuZGVsZXRlKHNldCwgdGVybSk7XG59XG5cbmZ1bmN0aW9uIHB1dCQxKHNldCwgdGVybSkge1xuICByZXR1cm4gTWFwU2V0LnB1dChzZXQsIHRlcm0pO1xufVxuXG5mdW5jdGlvbiBkaWZmZXJlbmNlKHNldDEsIHNldDIpIHtcbiAgcmV0dXJuIE1hcFNldC5kaWZmZXJlbmNlKHNldDEsIHNldDIpO1xufVxuXG5mdW5jdGlvbiBpbnRlcnNlY3Rpb24oc2V0MSwgc2V0Mikge1xuICByZXR1cm4gTWFwU2V0LmludGVyc2VjdGlvbihzZXQxLCBzZXQyKTtcbn1cblxuZnVuY3Rpb24gdW5pb24oc2V0MSwgc2V0Mikge1xuICByZXR1cm4gTWFwU2V0LnVuaW9uKHNldDEsIHNldDIpO1xufVxuXG5mdW5jdGlvbiBkaXNqb2luX19xbWFya19fKHNldDEsIHNldDIpIHtcbiAgcmV0dXJuIE1hcFNldC5kaXNqb2luX19xbWFya19fKHNldDEsIHNldDIpO1xufVxuXG5mdW5jdGlvbiBtZW1iZXJfX3FtYXJrX18oc2V0LCB2YWx1ZSkge1xuICByZXR1cm4gTWFwU2V0Lm1lbWJlcl9fcW1hcmtfXyhzZXQxLCBzZXQyKTtcbn1cblxuZnVuY3Rpb24gZXF1YWxfX3FtYXJrX18kMShzZXQxLCBzZXQyKSB7XG4gIHJldHVybiBNYXBTZXQuZXF1YWxfX3FtYXJrX18oc2V0MSwgc2V0Mik7XG59XG5cbmZ1bmN0aW9uIHN1YnNldF9fcW1hcmtfXyhzZXQxLCBzZXQyKSB7XG4gIHJldHVybiBNYXBTZXQuc3Vic2V0X19xbWFya19fKHNldDEsIHNldDIpO1xufVxuXG52YXIgc2V0ID0ge1xuICBzaXplOiBzaXplJDEsXG4gIHRvX2xpc3Q6IHRvX2xpc3QkMixcbiAgZGlzam9pbl9fcW1hcmtfXyxcbiAgZGVsZXRlOiBfX2RlbGV0ZV9fJDEsXG4gIHN1YnNldF9fcW1hcmtfXyxcbiAgZXF1YWxfX3FtYXJrX186IGVxdWFsX19xbWFya19fJDEsXG4gIG1lbWJlcl9fcW1hcmtfXyxcbiAgcHV0OiBwdXQkMSxcbiAgdW5pb24sXG4gIGludGVyc2VjdGlvbixcbiAgZGlmZmVyZW5jZVxufTtcblxubGV0IFZpcnR1YWxET00gPSAoZnVuY3Rpb24gKGUpIHtcbiAgICByZXR1cm4gZSgpO1xufSkoZnVuY3Rpb24gKCkge1xuICAgIHZhciBkZWZpbmUsIG1vZHVsZSwgZXhwb3J0cztcbiAgICByZXR1cm4gKGZ1bmN0aW9uIGUodCwgbiwgcikge1xuICAgICAgICBmdW5jdGlvbiBzKG8sIHUpIHtcbiAgICAgICAgICAgIGlmICghbltvXSkge1xuICAgICAgICAgICAgICAgIGlmICghdFtvXSkge1xuICAgICAgICAgICAgICAgICAgICB2YXIgYSA9IHR5cGVvZiByZXF1aXJlID09IFwiZnVuY3Rpb25cIiAmJiByZXF1aXJlO1xuICAgICAgICAgICAgICAgICAgICBpZiAoIXUgJiYgYSkgcmV0dXJuIGEobywgITApO1xuICAgICAgICAgICAgICAgICAgICBpZiAoaSkgcmV0dXJuIGkobywgITApO1xuICAgICAgICAgICAgICAgICAgICB2YXIgZiA9IG5ldyBFcnJvcihcIkNhbm5vdCBmaW5kIG1vZHVsZSAnXCIgKyBvICsgXCInXCIpO1xuICAgICAgICAgICAgICAgICAgICB0aHJvdyAoZi5jb2RlID0gXCJNT0RVTEVfTk9UX0ZPVU5EXCIsIGYpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB2YXIgbCA9IG5bb10gPSB7XG4gICAgICAgICAgICAgICAgICAgIGV4cG9ydHM6IHt9XG4gICAgICAgICAgICAgICAgfTtcbiAgICAgICAgICAgICAgICB0W29dWzBdLmNhbGwobC5leHBvcnRzLCBmdW5jdGlvbiAoZSkge1xuICAgICAgICAgICAgICAgICAgICB2YXIgbiA9IHRbb11bMV1bZV07XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBzKG4gPyBuIDogZSk7XG4gICAgICAgICAgICAgICAgfSwgbCwgbC5leHBvcnRzLCBlLCB0LCBuLCByKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJldHVybiBuW29dLmV4cG9ydHM7XG4gICAgICAgIH1cbiAgICAgICAgdmFyIGkgPSB0eXBlb2YgcmVxdWlyZSA9PSBcImZ1bmN0aW9uXCIgJiYgcmVxdWlyZTtcbiAgICAgICAgZm9yICh2YXIgbyA9IDA7IG8gPCByLmxlbmd0aDsgbysrKSBzKHJbb10pO1xuICAgICAgICByZXR1cm4gcztcbiAgICB9KSh7XG4gICAgICAgIDE6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG5cbiAgICAgICAgICAgIHZhciBjcmVhdGVFbGVtZW50ID0gcmVxdWlyZShcIi4vdmRvbS9jcmVhdGUtZWxlbWVudC5qc1wiKTtcblxuICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBjcmVhdGVFbGVtZW50O1xuICAgICAgICB9LCB7IFwiLi92ZG9tL2NyZWF0ZS1lbGVtZW50LmpzXCI6IDE1IH1dLCAyOiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge1xuICAgICAgICAgICAgdmFyIGRpZmYgPSByZXF1aXJlKFwiLi92dHJlZS9kaWZmLmpzXCIpO1xuXG4gICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IGRpZmY7XG4gICAgICAgIH0sIHsgXCIuL3Z0cmVlL2RpZmYuanNcIjogMzUgfV0sIDM6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICB2YXIgaCA9IHJlcXVpcmUoXCIuL3ZpcnR1YWwtaHlwZXJzY3JpcHQvaW5kZXguanNcIik7XG5cbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gaDtcbiAgICAgICAgfSwgeyBcIi4vdmlydHVhbC1oeXBlcnNjcmlwdC9pbmRleC5qc1wiOiAyMiB9XSwgNDogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHtcbiAgICAgICAgICAgIHZhciBkaWZmID0gcmVxdWlyZShcIi4vZGlmZi5qc1wiKTtcbiAgICAgICAgICAgIHZhciBwYXRjaCA9IHJlcXVpcmUoXCIuL3BhdGNoLmpzXCIpO1xuICAgICAgICAgICAgdmFyIGggPSByZXF1aXJlKFwiLi9oLmpzXCIpO1xuICAgICAgICAgICAgdmFyIGNyZWF0ZSA9IHJlcXVpcmUoXCIuL2NyZWF0ZS1lbGVtZW50LmpzXCIpO1xuICAgICAgICAgICAgdmFyIFZOb2RlID0gcmVxdWlyZShcIi4vdm5vZGUvdm5vZGUuanNcIik7XG4gICAgICAgICAgICB2YXIgVlRleHQgPSByZXF1aXJlKFwiLi92bm9kZS92dGV4dC5qc1wiKTtcblxuICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSB7XG4gICAgICAgICAgICAgICAgZGlmZjogZGlmZixcbiAgICAgICAgICAgICAgICBwYXRjaDogcGF0Y2gsXG4gICAgICAgICAgICAgICAgaDogaCxcbiAgICAgICAgICAgICAgICBjcmVhdGU6IGNyZWF0ZSxcbiAgICAgICAgICAgICAgICBWTm9kZTogVk5vZGUsXG4gICAgICAgICAgICAgICAgVlRleHQ6IFZUZXh0XG4gICAgICAgICAgICB9O1xuICAgICAgICB9LCB7IFwiLi9jcmVhdGUtZWxlbWVudC5qc1wiOiAxLCBcIi4vZGlmZi5qc1wiOiAyLCBcIi4vaC5qc1wiOiAzLCBcIi4vcGF0Y2guanNcIjogMTMsIFwiLi92bm9kZS92bm9kZS5qc1wiOiAzMSwgXCIuL3Zub2RlL3Z0ZXh0LmpzXCI6IDMzIH1dLCA1OiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge1xuICAgICAgICAgICAgLyohXG4gICAgICAgICAgICAgKiBDcm9zcy1Ccm93c2VyIFNwbGl0IDEuMS4xXG4gICAgICAgICAgICAgKiBDb3B5cmlnaHQgMjAwNy0yMDEyIFN0ZXZlbiBMZXZpdGhhbiA8c3RldmVubGV2aXRoYW4uY29tPlxuICAgICAgICAgICAgICogQXZhaWxhYmxlIHVuZGVyIHRoZSBNSVQgTGljZW5zZVxuICAgICAgICAgICAgICogRUNNQVNjcmlwdCBjb21wbGlhbnQsIHVuaWZvcm0gY3Jvc3MtYnJvd3NlciBzcGxpdCBtZXRob2RcbiAgICAgICAgICAgICAqL1xuXG4gICAgICAgICAgICAvKipcbiAgICAgICAgICAgICAqIFNwbGl0cyBhIHN0cmluZyBpbnRvIGFuIGFycmF5IG9mIHN0cmluZ3MgdXNpbmcgYSByZWdleCBvciBzdHJpbmcgc2VwYXJhdG9yLiBNYXRjaGVzIG9mIHRoZVxuICAgICAgICAgICAgICogc2VwYXJhdG9yIGFyZSBub3QgaW5jbHVkZWQgaW4gdGhlIHJlc3VsdCBhcnJheS4gSG93ZXZlciwgaWYgYHNlcGFyYXRvcmAgaXMgYSByZWdleCB0aGF0IGNvbnRhaW5zXG4gICAgICAgICAgICAgKiBjYXB0dXJpbmcgZ3JvdXBzLCBiYWNrcmVmZXJlbmNlcyBhcmUgc3BsaWNlZCBpbnRvIHRoZSByZXN1bHQgZWFjaCB0aW1lIGBzZXBhcmF0b3JgIGlzIG1hdGNoZWQuXG4gICAgICAgICAgICAgKiBGaXhlcyBicm93c2VyIGJ1Z3MgY29tcGFyZWQgdG8gdGhlIG5hdGl2ZSBgU3RyaW5nLnByb3RvdHlwZS5zcGxpdGAgYW5kIGNhbiBiZSB1c2VkIHJlbGlhYmx5XG4gICAgICAgICAgICAgKiBjcm9zcy1icm93c2VyLlxuICAgICAgICAgICAgICogQHBhcmFtIHtTdHJpbmd9IHN0ciBTdHJpbmcgdG8gc3BsaXQuXG4gICAgICAgICAgICAgKiBAcGFyYW0ge1JlZ0V4cHxTdHJpbmd9IHNlcGFyYXRvciBSZWdleCBvciBzdHJpbmcgdG8gdXNlIGZvciBzZXBhcmF0aW5nIHRoZSBzdHJpbmcuXG4gICAgICAgICAgICAgKiBAcGFyYW0ge051bWJlcn0gW2xpbWl0XSBNYXhpbXVtIG51bWJlciBvZiBpdGVtcyB0byBpbmNsdWRlIGluIHRoZSByZXN1bHQgYXJyYXkuXG4gICAgICAgICAgICAgKiBAcmV0dXJucyB7QXJyYXl9IEFycmF5IG9mIHN1YnN0cmluZ3MuXG4gICAgICAgICAgICAgKiBAZXhhbXBsZVxuICAgICAgICAgICAgICpcbiAgICAgICAgICAgICAqIC8vIEJhc2ljIHVzZVxuICAgICAgICAgICAgICogc3BsaXQoJ2EgYiBjIGQnLCAnICcpO1xuICAgICAgICAgICAgICogLy8gLT4gWydhJywgJ2InLCAnYycsICdkJ11cbiAgICAgICAgICAgICAqXG4gICAgICAgICAgICAgKiAvLyBXaXRoIGxpbWl0XG4gICAgICAgICAgICAgKiBzcGxpdCgnYSBiIGMgZCcsICcgJywgMik7XG4gICAgICAgICAgICAgKiAvLyAtPiBbJ2EnLCAnYiddXG4gICAgICAgICAgICAgKlxuICAgICAgICAgICAgICogLy8gQmFja3JlZmVyZW5jZXMgaW4gcmVzdWx0IGFycmF5XG4gICAgICAgICAgICAgKiBzcGxpdCgnLi53b3JkMSB3b3JkMi4uJywgLyhbYS16XSspKFxcZCspL2kpO1xuICAgICAgICAgICAgICogLy8gLT4gWycuLicsICd3b3JkJywgJzEnLCAnICcsICd3b3JkJywgJzInLCAnLi4nXVxuICAgICAgICAgICAgICovXG4gICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IChmdW5jdGlvbiBzcGxpdCh1bmRlZikge1xuXG4gICAgICAgICAgICAgICAgdmFyIG5hdGl2ZVNwbGl0ID0gU3RyaW5nLnByb3RvdHlwZS5zcGxpdCxcbiAgICAgICAgICAgICAgICAgICAgY29tcGxpYW50RXhlY05wY2cgPSAvKCk/Py8uZXhlYyhcIlwiKVsxXSA9PT0gdW5kZWYsXG5cbiAgICAgICAgICAgICAgICAvLyBOUENHOiBub25wYXJ0aWNpcGF0aW5nIGNhcHR1cmluZyBncm91cFxuICAgICAgICAgICAgICAgIHNlbGY7XG5cbiAgICAgICAgICAgICAgICBzZWxmID0gZnVuY3Rpb24gKHN0ciwgc2VwYXJhdG9yLCBsaW1pdCkge1xuICAgICAgICAgICAgICAgICAgICAvLyBJZiBgc2VwYXJhdG9yYCBpcyBub3QgYSByZWdleCwgdXNlIGBuYXRpdmVTcGxpdGBcbiAgICAgICAgICAgICAgICAgICAgaWYgKE9iamVjdC5wcm90b3R5cGUudG9TdHJpbmcuY2FsbChzZXBhcmF0b3IpICE9PSBcIltvYmplY3QgUmVnRXhwXVwiKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gbmF0aXZlU3BsaXQuY2FsbChzdHIsIHNlcGFyYXRvciwgbGltaXQpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIHZhciBvdXRwdXQgPSBbXSxcbiAgICAgICAgICAgICAgICAgICAgICAgIGZsYWdzID0gKHNlcGFyYXRvci5pZ25vcmVDYXNlID8gXCJpXCIgOiBcIlwiKSArIChzZXBhcmF0b3IubXVsdGlsaW5lID8gXCJtXCIgOiBcIlwiKSArIChzZXBhcmF0b3IuZXh0ZW5kZWQgPyBcInhcIiA6IFwiXCIpICsgKHNlcGFyYXRvci5zdGlja3kgPyBcInlcIiA6IFwiXCIpLFxuXG4gICAgICAgICAgICAgICAgICAgIC8vIEZpcmVmb3ggMytcbiAgICAgICAgICAgICAgICAgICAgbGFzdExhc3RJbmRleCA9IDAsXG5cbiAgICAgICAgICAgICAgICAgICAgLy8gTWFrZSBgZ2xvYmFsYCBhbmQgYXZvaWQgYGxhc3RJbmRleGAgaXNzdWVzIGJ5IHdvcmtpbmcgd2l0aCBhIGNvcHlcbiAgICAgICAgICAgICAgICAgICAgc2VwYXJhdG9yID0gbmV3IFJlZ0V4cChzZXBhcmF0b3Iuc291cmNlLCBmbGFncyArIFwiZ1wiKSxcbiAgICAgICAgICAgICAgICAgICAgICAgIHNlcGFyYXRvcjIsXG4gICAgICAgICAgICAgICAgICAgICAgICBtYXRjaCxcbiAgICAgICAgICAgICAgICAgICAgICAgIGxhc3RJbmRleCxcbiAgICAgICAgICAgICAgICAgICAgICAgIGxhc3RMZW5ndGg7XG4gICAgICAgICAgICAgICAgICAgIHN0ciArPSBcIlwiOyAvLyBUeXBlLWNvbnZlcnRcbiAgICAgICAgICAgICAgICAgICAgaWYgKCFjb21wbGlhbnRFeGVjTnBjZykge1xuICAgICAgICAgICAgICAgICAgICAgICAgLy8gRG9lc24ndCBuZWVkIGZsYWdzIGd5LCBidXQgdGhleSBkb24ndCBodXJ0XG4gICAgICAgICAgICAgICAgICAgICAgICBzZXBhcmF0b3IyID0gbmV3IFJlZ0V4cChcIl5cIiArIHNlcGFyYXRvci5zb3VyY2UgKyBcIiQoPyFcXFxccylcIiwgZmxhZ3MpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIC8qIFZhbHVlcyBmb3IgYGxpbWl0YCwgcGVyIHRoZSBzcGVjOlxuICAgICAgICAgICAgICAgICAgICAgKiBJZiB1bmRlZmluZWQ6IDQyOTQ5NjcyOTUgLy8gTWF0aC5wb3coMiwgMzIpIC0gMVxuICAgICAgICAgICAgICAgICAgICAgKiBJZiAwLCBJbmZpbml0eSwgb3IgTmFOOiAwXG4gICAgICAgICAgICAgICAgICAgICAqIElmIHBvc2l0aXZlIG51bWJlcjogbGltaXQgPSBNYXRoLmZsb29yKGxpbWl0KTsgaWYgKGxpbWl0ID4gNDI5NDk2NzI5NSkgbGltaXQgLT0gNDI5NDk2NzI5NjtcbiAgICAgICAgICAgICAgICAgICAgICogSWYgbmVnYXRpdmUgbnVtYmVyOiA0Mjk0OTY3Mjk2IC0gTWF0aC5mbG9vcihNYXRoLmFicyhsaW1pdCkpXG4gICAgICAgICAgICAgICAgICAgICAqIElmIG90aGVyOiBUeXBlLWNvbnZlcnQsIHRoZW4gdXNlIHRoZSBhYm92ZSBydWxlc1xuICAgICAgICAgICAgICAgICAgICAgKi9cbiAgICAgICAgICAgICAgICAgICAgbGltaXQgPSBsaW1pdCA9PT0gdW5kZWYgPyAtMSA+Pj4gMCA6IC8vIE1hdGgucG93KDIsIDMyKSAtIDFcbiAgICAgICAgICAgICAgICAgICAgbGltaXQgPj4+IDA7IC8vIFRvVWludDMyKGxpbWl0KVxuICAgICAgICAgICAgICAgICAgICB3aGlsZSAobWF0Y2ggPSBzZXBhcmF0b3IuZXhlYyhzdHIpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAvLyBgc2VwYXJhdG9yLmxhc3RJbmRleGAgaXMgbm90IHJlbGlhYmxlIGNyb3NzLWJyb3dzZXJcbiAgICAgICAgICAgICAgICAgICAgICAgIGxhc3RJbmRleCA9IG1hdGNoLmluZGV4ICsgbWF0Y2hbMF0ubGVuZ3RoO1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGxhc3RJbmRleCA+IGxhc3RMYXN0SW5kZXgpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBvdXRwdXQucHVzaChzdHIuc2xpY2UobGFzdExhc3RJbmRleCwgbWF0Y2guaW5kZXgpKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBGaXggYnJvd3NlcnMgd2hvc2UgYGV4ZWNgIG1ldGhvZHMgZG9uJ3QgY29uc2lzdGVudGx5IHJldHVybiBgdW5kZWZpbmVkYCBmb3JcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBub25wYXJ0aWNpcGF0aW5nIGNhcHR1cmluZyBncm91cHNcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoIWNvbXBsaWFudEV4ZWNOcGNnICYmIG1hdGNoLmxlbmd0aCA+IDEpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbWF0Y2hbMF0ucmVwbGFjZShzZXBhcmF0b3IyLCBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBmb3IgKHZhciBpID0gMTsgaSA8IGFyZ3VtZW50cy5sZW5ndGggLSAyOyBpKyspIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoYXJndW1lbnRzW2ldID09PSB1bmRlZikge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBtYXRjaFtpXSA9IHVuZGVmO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChtYXRjaC5sZW5ndGggPiAxICYmIG1hdGNoLmluZGV4IDwgc3RyLmxlbmd0aCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBBcnJheS5wcm90b3R5cGUucHVzaC5hcHBseShvdXRwdXQsIG1hdGNoLnNsaWNlKDEpKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgbGFzdExlbmd0aCA9IG1hdGNoWzBdLmxlbmd0aDtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBsYXN0TGFzdEluZGV4ID0gbGFzdEluZGV4O1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChvdXRwdXQubGVuZ3RoID49IGxpbWl0KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChzZXBhcmF0b3IubGFzdEluZGV4ID09PSBtYXRjaC5pbmRleCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNlcGFyYXRvci5sYXN0SW5kZXgrKzsgLy8gQXZvaWQgYW4gaW5maW5pdGUgbG9vcFxuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIGlmIChsYXN0TGFzdEluZGV4ID09PSBzdHIubGVuZ3RoKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAobGFzdExlbmd0aCB8fCAhc2VwYXJhdG9yLnRlc3QoXCJcIikpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBvdXRwdXQucHVzaChcIlwiKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIG91dHB1dC5wdXNoKHN0ci5zbGljZShsYXN0TGFzdEluZGV4KSk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIG91dHB1dC5sZW5ndGggPiBsaW1pdCA/IG91dHB1dC5zbGljZSgwLCBsaW1pdCkgOiBvdXRwdXQ7XG4gICAgICAgICAgICAgICAgfTtcblxuICAgICAgICAgICAgICAgIHJldHVybiBzZWxmO1xuICAgICAgICAgICAgfSkoKTtcbiAgICAgICAgfSwge31dLCA2OiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge30sIHt9XSwgNzogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHtcbiAgICAgICAgICAgIFwidXNlIHN0cmljdFwiO1xuXG4gICAgICAgICAgICB2YXIgT25lVmVyc2lvbkNvbnN0cmFpbnQgPSByZXF1aXJlKFwiaW5kaXZpZHVhbC9vbmUtdmVyc2lvblwiKTtcblxuICAgICAgICAgICAgdmFyIE1ZX1ZFUlNJT04gPSBcIjdcIjtcbiAgICAgICAgICAgIE9uZVZlcnNpb25Db25zdHJhaW50KFwiZXYtc3RvcmVcIiwgTVlfVkVSU0lPTik7XG5cbiAgICAgICAgICAgIHZhciBoYXNoS2V5ID0gXCJfX0VWX1NUT1JFX0tFWUBcIiArIE1ZX1ZFUlNJT047XG5cbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gRXZTdG9yZTtcblxuICAgICAgICAgICAgZnVuY3Rpb24gRXZTdG9yZShlbGVtKSB7XG4gICAgICAgICAgICAgICAgdmFyIGhhc2ggPSBlbGVtW2hhc2hLZXldO1xuXG4gICAgICAgICAgICAgICAgaWYgKCFoYXNoKSB7XG4gICAgICAgICAgICAgICAgICAgIGhhc2ggPSBlbGVtW2hhc2hLZXldID0ge307XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgcmV0dXJuIGhhc2g7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0sIHsgXCJpbmRpdmlkdWFsL29uZS12ZXJzaW9uXCI6IDkgfV0sIDg6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICAoZnVuY3Rpb24gKGdsb2JhbCkge1xuICAgICAgICAgICAgICAgIFwidXNlIHN0cmljdFwiO1xuXG4gICAgICAgICAgICAgICAgLypnbG9iYWwgd2luZG93LCBnbG9iYWwqL1xuXG4gICAgICAgICAgICAgICAgdmFyIHJvb3QgPSB0eXBlb2Ygd2luZG93ICE9PSBcInVuZGVmaW5lZFwiID8gd2luZG93IDogdHlwZW9mIGdsb2JhbCAhPT0gXCJ1bmRlZmluZWRcIiA/IGdsb2JhbCA6IHt9O1xuXG4gICAgICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBJbmRpdmlkdWFsO1xuXG4gICAgICAgICAgICAgICAgZnVuY3Rpb24gSW5kaXZpZHVhbChrZXksIHZhbHVlKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmIChrZXkgaW4gcm9vdCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHJvb3Rba2V5XTtcbiAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgIHJvb3Rba2V5XSA9IHZhbHVlO1xuXG4gICAgICAgICAgICAgICAgICAgIHJldHVybiB2YWx1ZTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9KS5jYWxsKHRoaXMsIHR5cGVvZiBnbG9iYWwgIT09IFwidW5kZWZpbmVkXCIgPyBnbG9iYWwgOiB0eXBlb2Ygc2VsZiAhPT0gXCJ1bmRlZmluZWRcIiA/IHNlbGYgOiB0eXBlb2Ygd2luZG93ICE9PSBcInVuZGVmaW5lZFwiID8gd2luZG93IDoge30pO1xuICAgICAgICB9LCB7fV0sIDk6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICBcInVzZSBzdHJpY3RcIjtcblxuICAgICAgICAgICAgdmFyIEluZGl2aWR1YWwgPSByZXF1aXJlKFwiLi9pbmRleC5qc1wiKTtcblxuICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBPbmVWZXJzaW9uO1xuXG4gICAgICAgICAgICBmdW5jdGlvbiBPbmVWZXJzaW9uKG1vZHVsZU5hbWUsIHZlcnNpb24sIGRlZmF1bHRWYWx1ZSkge1xuICAgICAgICAgICAgICAgIHZhciBrZXkgPSBcIl9fSU5ESVZJRFVBTF9PTkVfVkVSU0lPTl9cIiArIG1vZHVsZU5hbWU7XG4gICAgICAgICAgICAgICAgdmFyIGVuZm9yY2VLZXkgPSBrZXkgKyBcIl9FTkZPUkNFX1NJTkdMRVRPTlwiO1xuXG4gICAgICAgICAgICAgICAgdmFyIHZlcnNpb25WYWx1ZSA9IEluZGl2aWR1YWwoZW5mb3JjZUtleSwgdmVyc2lvbik7XG5cbiAgICAgICAgICAgICAgICBpZiAodmVyc2lvblZhbHVlICE9PSB2ZXJzaW9uKSB7XG4gICAgICAgICAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcihcIkNhbiBvbmx5IGhhdmUgb25lIGNvcHkgb2YgXCIgKyBtb2R1bGVOYW1lICsgXCIuXFxuXCIgKyBcIllvdSBhbHJlYWR5IGhhdmUgdmVyc2lvbiBcIiArIHZlcnNpb25WYWx1ZSArIFwiIGluc3RhbGxlZC5cXG5cIiArIFwiVGhpcyBtZWFucyB5b3UgY2Fubm90IGluc3RhbGwgdmVyc2lvbiBcIiArIHZlcnNpb24pO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHJldHVybiBJbmRpdmlkdWFsKGtleSwgZGVmYXVsdFZhbHVlKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSwgeyBcIi4vaW5kZXguanNcIjogOCB9XSwgMTA6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICAoZnVuY3Rpb24gKGdsb2JhbCkge1xuICAgICAgICAgICAgICAgIHZhciB0b3BMZXZlbCA9IHR5cGVvZiBnbG9iYWwgIT09IFwidW5kZWZpbmVkXCIgPyBnbG9iYWwgOiB0eXBlb2Ygd2luZG93ICE9PSBcInVuZGVmaW5lZFwiID8gd2luZG93IDoge307XG4gICAgICAgICAgICAgICAgdmFyIG1pbkRvYyA9IHJlcXVpcmUoXCJtaW4tZG9jdW1lbnRcIik7XG5cbiAgICAgICAgICAgICAgICBpZiAodHlwZW9mIGRvY3VtZW50ICE9PSBcInVuZGVmaW5lZFwiKSB7XG4gICAgICAgICAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gZG9jdW1lbnQ7XG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgdmFyIGRvY2N5ID0gdG9wTGV2ZWxbXCJfX0dMT0JBTF9ET0NVTUVOVF9DQUNIRUA0XCJdO1xuXG4gICAgICAgICAgICAgICAgICAgIGlmICghZG9jY3kpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGRvY2N5ID0gdG9wTGV2ZWxbXCJfX0dMT0JBTF9ET0NVTUVOVF9DQUNIRUA0XCJdID0gbWluRG9jO1xuICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBkb2NjeTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9KS5jYWxsKHRoaXMsIHR5cGVvZiBnbG9iYWwgIT09IFwidW5kZWZpbmVkXCIgPyBnbG9iYWwgOiB0eXBlb2Ygc2VsZiAhPT0gXCJ1bmRlZmluZWRcIiA/IHNlbGYgOiB0eXBlb2Ygd2luZG93ICE9PSBcInVuZGVmaW5lZFwiID8gd2luZG93IDoge30pO1xuICAgICAgICB9LCB7IFwibWluLWRvY3VtZW50XCI6IDYgfV0sIDExOiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge1xuICAgICAgICAgICAgXCJ1c2Ugc3RyaWN0XCI7XG5cbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gaXNPYmplY3QoeCkge1xuICAgICAgICAgICAgICAgIHJldHVybiB0eXBlb2YgeCA9PT0gXCJvYmplY3RcIiAmJiB4ICE9PSBudWxsO1xuICAgICAgICAgICAgfTtcbiAgICAgICAgfSwge31dLCAxMjogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHtcbiAgICAgICAgICAgIHZhciBuYXRpdmVJc0FycmF5ID0gQXJyYXkuaXNBcnJheTtcbiAgICAgICAgICAgIHZhciB0b1N0cmluZyA9IE9iamVjdC5wcm90b3R5cGUudG9TdHJpbmc7XG5cbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gbmF0aXZlSXNBcnJheSB8fCBpc0FycmF5O1xuXG4gICAgICAgICAgICBmdW5jdGlvbiBpc0FycmF5KG9iaikge1xuICAgICAgICAgICAgICAgIHJldHVybiB0b1N0cmluZy5jYWxsKG9iaikgPT09IFwiW29iamVjdCBBcnJheV1cIjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSwge31dLCAxMzogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHtcbiAgICAgICAgICAgIHZhciBwYXRjaCA9IHJlcXVpcmUoXCIuL3Zkb20vcGF0Y2guanNcIik7XG5cbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gcGF0Y2g7XG4gICAgICAgIH0sIHsgXCIuL3Zkb20vcGF0Y2guanNcIjogMTggfV0sIDE0OiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge1xuICAgICAgICAgICAgdmFyIGlzT2JqZWN0ID0gcmVxdWlyZShcImlzLW9iamVjdFwiKTtcbiAgICAgICAgICAgIHZhciBpc0hvb2sgPSByZXF1aXJlKFwiLi4vdm5vZGUvaXMtdmhvb2suanNcIik7XG5cbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gYXBwbHlQcm9wZXJ0aWVzO1xuXG4gICAgICAgICAgICBmdW5jdGlvbiBhcHBseVByb3BlcnRpZXMobm9kZSwgcHJvcHMsIHByZXZpb3VzKSB7XG4gICAgICAgICAgICAgICAgZm9yICh2YXIgcHJvcE5hbWUgaW4gcHJvcHMpIHtcbiAgICAgICAgICAgICAgICAgICAgdmFyIHByb3BWYWx1ZSA9IHByb3BzW3Byb3BOYW1lXTtcblxuICAgICAgICAgICAgICAgICAgICBpZiAocHJvcFZhbHVlID09PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJlbW92ZVByb3BlcnR5KG5vZGUsIHByb3BOYW1lLCBwcm9wVmFsdWUsIHByZXZpb3VzKTtcbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIGlmIChpc0hvb2socHJvcFZhbHVlKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgcmVtb3ZlUHJvcGVydHkobm9kZSwgcHJvcE5hbWUsIHByb3BWYWx1ZSwgcHJldmlvdXMpO1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHByb3BWYWx1ZS5ob29rKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcHJvcFZhbHVlLmhvb2sobm9kZSwgcHJvcE5hbWUsIHByZXZpb3VzID8gcHJldmlvdXNbcHJvcE5hbWVdIDogdW5kZWZpbmVkKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChpc09iamVjdChwcm9wVmFsdWUpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcGF0Y2hPYmplY3Qobm9kZSwgcHJvcHMsIHByZXZpb3VzLCBwcm9wTmFtZSwgcHJvcFZhbHVlKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgbm9kZVtwcm9wTmFtZV0gPSBwcm9wVmFsdWU7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIHJlbW92ZVByb3BlcnR5KG5vZGUsIHByb3BOYW1lLCBwcm9wVmFsdWUsIHByZXZpb3VzKSB7XG4gICAgICAgICAgICAgICAgaWYgKHByZXZpb3VzKSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciBwcmV2aW91c1ZhbHVlID0gcHJldmlvdXNbcHJvcE5hbWVdO1xuXG4gICAgICAgICAgICAgICAgICAgIGlmICghaXNIb29rKHByZXZpb3VzVmFsdWUpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAocHJvcE5hbWUgPT09IFwiYXR0cmlidXRlc1wiKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgZm9yICh2YXIgYXR0ck5hbWUgaW4gcHJldmlvdXNWYWx1ZSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBub2RlLnJlbW92ZUF0dHJpYnV0ZShhdHRyTmFtZSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIGlmIChwcm9wTmFtZSA9PT0gXCJzdHlsZVwiKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgZm9yICh2YXIgaSBpbiBwcmV2aW91c1ZhbHVlKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG5vZGUuc3R5bGVbaV0gPSBcIlwiO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAodHlwZW9mIHByZXZpb3VzVmFsdWUgPT09IFwic3RyaW5nXCIpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBub2RlW3Byb3BOYW1lXSA9IFwiXCI7XG4gICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIG5vZGVbcHJvcE5hbWVdID0gbnVsbDtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIGlmIChwcmV2aW91c1ZhbHVlLnVuaG9vaykge1xuICAgICAgICAgICAgICAgICAgICAgICAgcHJldmlvdXNWYWx1ZS51bmhvb2sobm9kZSwgcHJvcE5hbWUsIHByb3BWYWx1ZSk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIHBhdGNoT2JqZWN0KG5vZGUsIHByb3BzLCBwcmV2aW91cywgcHJvcE5hbWUsIHByb3BWYWx1ZSkge1xuICAgICAgICAgICAgICAgIHZhciBwcmV2aW91c1ZhbHVlID0gcHJldmlvdXMgPyBwcmV2aW91c1twcm9wTmFtZV0gOiB1bmRlZmluZWQ7XG5cbiAgICAgICAgICAgICAgICAvLyBTZXQgYXR0cmlidXRlc1xuICAgICAgICAgICAgICAgIGlmIChwcm9wTmFtZSA9PT0gXCJhdHRyaWJ1dGVzXCIpIHtcbiAgICAgICAgICAgICAgICAgICAgZm9yICh2YXIgYXR0ck5hbWUgaW4gcHJvcFZhbHVlKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICB2YXIgYXR0clZhbHVlID0gcHJvcFZhbHVlW2F0dHJOYW1lXTtcblxuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGF0dHJWYWx1ZSA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgbm9kZS5yZW1vdmVBdHRyaWJ1dGUoYXR0ck5hbWUpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBub2RlLnNldEF0dHJpYnV0ZShhdHRyTmFtZSwgYXR0clZhbHVlKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICBpZiAocHJldmlvdXNWYWx1ZSAmJiBpc09iamVjdChwcmV2aW91c1ZhbHVlKSAmJiBnZXRQcm90b3R5cGUocHJldmlvdXNWYWx1ZSkgIT09IGdldFByb3RvdHlwZShwcm9wVmFsdWUpKSB7XG4gICAgICAgICAgICAgICAgICAgIG5vZGVbcHJvcE5hbWVdID0gcHJvcFZhbHVlO1xuICAgICAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgaWYgKCFpc09iamVjdChub2RlW3Byb3BOYW1lXSkpIHtcbiAgICAgICAgICAgICAgICAgICAgbm9kZVtwcm9wTmFtZV0gPSB7fTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICB2YXIgcmVwbGFjZXIgPSBwcm9wTmFtZSA9PT0gXCJzdHlsZVwiID8gXCJcIiA6IHVuZGVmaW5lZDtcblxuICAgICAgICAgICAgICAgIGZvciAodmFyIGsgaW4gcHJvcFZhbHVlKSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciB2YWx1ZSA9IHByb3BWYWx1ZVtrXTtcbiAgICAgICAgICAgICAgICAgICAgbm9kZVtwcm9wTmFtZV1ba10gPSB2YWx1ZSA9PT0gdW5kZWZpbmVkID8gcmVwbGFjZXIgOiB2YWx1ZTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIGdldFByb3RvdHlwZSh2YWx1ZSkge1xuICAgICAgICAgICAgICAgIGlmIChPYmplY3QuZ2V0UHJvdG90eXBlT2YpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIE9iamVjdC5nZXRQcm90b3R5cGVPZih2YWx1ZSk7XG4gICAgICAgICAgICAgICAgfSBlbHNlIGlmICh2YWx1ZS5fX3Byb3RvX18pIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHZhbHVlLl9fcHJvdG9fXztcbiAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKHZhbHVlLmNvbnN0cnVjdG9yKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiB2YWx1ZS5jb25zdHJ1Y3Rvci5wcm90b3R5cGU7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9LCB7IFwiLi4vdm5vZGUvaXMtdmhvb2suanNcIjogMjYsIFwiaXMtb2JqZWN0XCI6IDExIH1dLCAxNTogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHtcbiAgICAgICAgICAgIHZhciBkb2N1bWVudCA9IHJlcXVpcmUoXCJnbG9iYWwvZG9jdW1lbnRcIik7XG5cbiAgICAgICAgICAgIHZhciBhcHBseVByb3BlcnRpZXMgPSByZXF1aXJlKFwiLi9hcHBseS1wcm9wZXJ0aWVzXCIpO1xuXG4gICAgICAgICAgICB2YXIgaXNWTm9kZSA9IHJlcXVpcmUoXCIuLi92bm9kZS9pcy12bm9kZS5qc1wiKTtcbiAgICAgICAgICAgIHZhciBpc1ZUZXh0ID0gcmVxdWlyZShcIi4uL3Zub2RlL2lzLXZ0ZXh0LmpzXCIpO1xuICAgICAgICAgICAgdmFyIGlzV2lkZ2V0ID0gcmVxdWlyZShcIi4uL3Zub2RlL2lzLXdpZGdldC5qc1wiKTtcbiAgICAgICAgICAgIHZhciBoYW5kbGVUaHVuayA9IHJlcXVpcmUoXCIuLi92bm9kZS9oYW5kbGUtdGh1bmsuanNcIik7XG5cbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gY3JlYXRlRWxlbWVudDtcblxuICAgICAgICAgICAgZnVuY3Rpb24gY3JlYXRlRWxlbWVudCh2bm9kZSwgb3B0cykge1xuICAgICAgICAgICAgICAgIHZhciBkb2MgPSBvcHRzID8gb3B0cy5kb2N1bWVudCB8fCBkb2N1bWVudCA6IGRvY3VtZW50O1xuICAgICAgICAgICAgICAgIHZhciB3YXJuID0gb3B0cyA/IG9wdHMud2FybiA6IG51bGw7XG5cbiAgICAgICAgICAgICAgICB2bm9kZSA9IGhhbmRsZVRodW5rKHZub2RlKS5hO1xuXG4gICAgICAgICAgICAgICAgaWYgKGlzV2lkZ2V0KHZub2RlKSkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gdm5vZGUuaW5pdCgpO1xuICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoaXNWVGV4dCh2bm9kZSkpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGRvYy5jcmVhdGVUZXh0Tm9kZSh2bm9kZS50ZXh0KTtcbiAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKCFpc1ZOb2RlKHZub2RlKSkge1xuICAgICAgICAgICAgICAgICAgICBpZiAod2Fybikge1xuICAgICAgICAgICAgICAgICAgICAgICAgd2FybihcIkl0ZW0gaXMgbm90IGEgdmFsaWQgdmlydHVhbCBkb20gbm9kZVwiLCB2bm9kZSk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIG51bGw7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgdmFyIG5vZGUgPSB2bm9kZS5uYW1lc3BhY2UgPT09IG51bGwgPyBkb2MuY3JlYXRlRWxlbWVudCh2bm9kZS50YWdOYW1lKSA6IGRvYy5jcmVhdGVFbGVtZW50TlModm5vZGUubmFtZXNwYWNlLCB2bm9kZS50YWdOYW1lKTtcblxuICAgICAgICAgICAgICAgIHZhciBwcm9wcyA9IHZub2RlLnByb3BlcnRpZXM7XG4gICAgICAgICAgICAgICAgYXBwbHlQcm9wZXJ0aWVzKG5vZGUsIHByb3BzKTtcblxuICAgICAgICAgICAgICAgIHZhciBjaGlsZHJlbiA9IHZub2RlLmNoaWxkcmVuO1xuXG4gICAgICAgICAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCBjaGlsZHJlbi5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgICAgICAgICB2YXIgY2hpbGROb2RlID0gY3JlYXRlRWxlbWVudChjaGlsZHJlbltpXSwgb3B0cyk7XG4gICAgICAgICAgICAgICAgICAgIGlmIChjaGlsZE5vZGUpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIG5vZGUuYXBwZW5kQ2hpbGQoY2hpbGROb2RlKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHJldHVybiBub2RlO1xuICAgICAgICAgICAgfVxuICAgICAgICB9LCB7IFwiLi4vdm5vZGUvaGFuZGxlLXRodW5rLmpzXCI6IDI0LCBcIi4uL3Zub2RlL2lzLXZub2RlLmpzXCI6IDI3LCBcIi4uL3Zub2RlL2lzLXZ0ZXh0LmpzXCI6IDI4LCBcIi4uL3Zub2RlL2lzLXdpZGdldC5qc1wiOiAyOSwgXCIuL2FwcGx5LXByb3BlcnRpZXNcIjogMTQsIFwiZ2xvYmFsL2RvY3VtZW50XCI6IDEwIH1dLCAxNjogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHtcbiAgICAgICAgICAgIC8vIE1hcHMgYSB2aXJ0dWFsIERPTSB0cmVlIG9udG8gYSByZWFsIERPTSB0cmVlIGluIGFuIGVmZmljaWVudCBtYW5uZXIuXG4gICAgICAgICAgICAvLyBXZSBkb24ndCB3YW50IHRvIHJlYWQgYWxsIG9mIHRoZSBET00gbm9kZXMgaW4gdGhlIHRyZWUgc28gd2UgdXNlXG4gICAgICAgICAgICAvLyB0aGUgaW4tb3JkZXIgdHJlZSBpbmRleGluZyB0byBlbGltaW5hdGUgcmVjdXJzaW9uIGRvd24gY2VydGFpbiBicmFuY2hlcy5cbiAgICAgICAgICAgIC8vIFdlIG9ubHkgcmVjdXJzZSBpbnRvIGEgRE9NIG5vZGUgaWYgd2Uga25vdyB0aGF0IGl0IGNvbnRhaW5zIGEgY2hpbGQgb2ZcbiAgICAgICAgICAgIC8vIGludGVyZXN0LlxuXG4gICAgICAgICAgICB2YXIgbm9DaGlsZCA9IHt9O1xuXG4gICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IGRvbUluZGV4O1xuXG4gICAgICAgICAgICBmdW5jdGlvbiBkb21JbmRleChyb290Tm9kZSwgdHJlZSwgaW5kaWNlcywgbm9kZXMpIHtcbiAgICAgICAgICAgICAgICBpZiAoIWluZGljZXMgfHwgaW5kaWNlcy5sZW5ndGggPT09IDApIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHt9O1xuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIGluZGljZXMuc29ydChhc2NlbmRpbmcpO1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gcmVjdXJzZShyb290Tm9kZSwgdHJlZSwgaW5kaWNlcywgbm9kZXMsIDApO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZnVuY3Rpb24gcmVjdXJzZShyb290Tm9kZSwgdHJlZSwgaW5kaWNlcywgbm9kZXMsIHJvb3RJbmRleCkge1xuICAgICAgICAgICAgICAgIG5vZGVzID0gbm9kZXMgfHwge307XG5cbiAgICAgICAgICAgICAgICBpZiAocm9vdE5vZGUpIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKGluZGV4SW5SYW5nZShpbmRpY2VzLCByb290SW5kZXgsIHJvb3RJbmRleCkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIG5vZGVzW3Jvb3RJbmRleF0gPSByb290Tm9kZTtcbiAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgIHZhciB2Q2hpbGRyZW4gPSB0cmVlLmNoaWxkcmVuO1xuXG4gICAgICAgICAgICAgICAgICAgIGlmICh2Q2hpbGRyZW4pIHtcblxuICAgICAgICAgICAgICAgICAgICAgICAgdmFyIGNoaWxkTm9kZXMgPSByb290Tm9kZS5jaGlsZE5vZGVzO1xuXG4gICAgICAgICAgICAgICAgICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IHRyZWUuY2hpbGRyZW4ubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICByb290SW5kZXggKz0gMTtcblxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZhciB2Q2hpbGQgPSB2Q2hpbGRyZW5baV0gfHwgbm9DaGlsZDtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB2YXIgbmV4dEluZGV4ID0gcm9vdEluZGV4ICsgKHZDaGlsZC5jb3VudCB8fCAwKTtcblxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIHNraXAgcmVjdXJzaW9uIGRvd24gdGhlIHRyZWUgaWYgdGhlcmUgYXJlIG5vIG5vZGVzIGRvd24gaGVyZVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChpbmRleEluUmFuZ2UoaW5kaWNlcywgcm9vdEluZGV4LCBuZXh0SW5kZXgpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlY3Vyc2UoY2hpbGROb2Rlc1tpXSwgdkNoaWxkLCBpbmRpY2VzLCBub2Rlcywgcm9vdEluZGV4KTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICByb290SW5kZXggPSBuZXh0SW5kZXg7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICByZXR1cm4gbm9kZXM7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIC8vIEJpbmFyeSBzZWFyY2ggZm9yIGFuIGluZGV4IGluIHRoZSBpbnRlcnZhbCBbbGVmdCwgcmlnaHRdXG4gICAgICAgICAgICBmdW5jdGlvbiBpbmRleEluUmFuZ2UoaW5kaWNlcywgbGVmdCwgcmlnaHQpIHtcbiAgICAgICAgICAgICAgICBpZiAoaW5kaWNlcy5sZW5ndGggPT09IDApIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHZhciBtaW5JbmRleCA9IDA7XG4gICAgICAgICAgICAgICAgdmFyIG1heEluZGV4ID0gaW5kaWNlcy5sZW5ndGggLSAxO1xuICAgICAgICAgICAgICAgIHZhciBjdXJyZW50SW5kZXg7XG4gICAgICAgICAgICAgICAgdmFyIGN1cnJlbnRJdGVtO1xuXG4gICAgICAgICAgICAgICAgd2hpbGUgKG1pbkluZGV4IDw9IG1heEluZGV4KSB7XG4gICAgICAgICAgICAgICAgICAgIGN1cnJlbnRJbmRleCA9IChtYXhJbmRleCArIG1pbkluZGV4KSAvIDIgPj4gMDtcbiAgICAgICAgICAgICAgICAgICAgY3VycmVudEl0ZW0gPSBpbmRpY2VzW2N1cnJlbnRJbmRleF07XG5cbiAgICAgICAgICAgICAgICAgICAgaWYgKG1pbkluZGV4ID09PSBtYXhJbmRleCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGN1cnJlbnRJdGVtID49IGxlZnQgJiYgY3VycmVudEl0ZW0gPD0gcmlnaHQ7XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoY3VycmVudEl0ZW0gPCBsZWZ0KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBtaW5JbmRleCA9IGN1cnJlbnRJbmRleCArIDE7XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoY3VycmVudEl0ZW0gPiByaWdodCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgbWF4SW5kZXggPSBjdXJyZW50SW5kZXggLSAxO1xuICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIGFzY2VuZGluZyhhLCBiKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGEgPiBiID8gMSA6IC0xO1xuICAgICAgICAgICAgfVxuICAgICAgICB9LCB7fV0sIDE3OiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge1xuICAgICAgICAgICAgdmFyIGFwcGx5UHJvcGVydGllcyA9IHJlcXVpcmUoXCIuL2FwcGx5LXByb3BlcnRpZXNcIik7XG5cbiAgICAgICAgICAgIHZhciBpc1dpZGdldCA9IHJlcXVpcmUoXCIuLi92bm9kZS9pcy13aWRnZXQuanNcIik7XG4gICAgICAgICAgICB2YXIgVlBhdGNoID0gcmVxdWlyZShcIi4uL3Zub2RlL3ZwYXRjaC5qc1wiKTtcblxuICAgICAgICAgICAgdmFyIHVwZGF0ZVdpZGdldCA9IHJlcXVpcmUoXCIuL3VwZGF0ZS13aWRnZXRcIik7XG5cbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gYXBwbHlQYXRjaDtcblxuICAgICAgICAgICAgZnVuY3Rpb24gYXBwbHlQYXRjaCh2cGF0Y2gsIGRvbU5vZGUsIHJlbmRlck9wdGlvbnMpIHtcbiAgICAgICAgICAgICAgICB2YXIgdHlwZSA9IHZwYXRjaC50eXBlO1xuICAgICAgICAgICAgICAgIHZhciB2Tm9kZSA9IHZwYXRjaC52Tm9kZTtcbiAgICAgICAgICAgICAgICB2YXIgcGF0Y2ggPSB2cGF0Y2gucGF0Y2g7XG5cbiAgICAgICAgICAgICAgICBzd2l0Y2ggKHR5cGUpIHtcbiAgICAgICAgICAgICAgICAgICAgY2FzZSBWUGF0Y2guUkVNT1ZFOlxuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHJlbW92ZU5vZGUoZG9tTm9kZSwgdk5vZGUpO1xuICAgICAgICAgICAgICAgICAgICBjYXNlIFZQYXRjaC5JTlNFUlQ6XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gaW5zZXJ0Tm9kZShkb21Ob2RlLCBwYXRjaCwgcmVuZGVyT3B0aW9ucyk7XG4gICAgICAgICAgICAgICAgICAgIGNhc2UgVlBhdGNoLlZURVhUOlxuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHN0cmluZ1BhdGNoKGRvbU5vZGUsIHZOb2RlLCBwYXRjaCwgcmVuZGVyT3B0aW9ucyk7XG4gICAgICAgICAgICAgICAgICAgIGNhc2UgVlBhdGNoLldJREdFVDpcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiB3aWRnZXRQYXRjaChkb21Ob2RlLCB2Tm9kZSwgcGF0Y2gsIHJlbmRlck9wdGlvbnMpO1xuICAgICAgICAgICAgICAgICAgICBjYXNlIFZQYXRjaC5WTk9ERTpcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiB2Tm9kZVBhdGNoKGRvbU5vZGUsIHZOb2RlLCBwYXRjaCwgcmVuZGVyT3B0aW9ucyk7XG4gICAgICAgICAgICAgICAgICAgIGNhc2UgVlBhdGNoLk9SREVSOlxuICAgICAgICAgICAgICAgICAgICAgICAgcmVvcmRlckNoaWxkcmVuKGRvbU5vZGUsIHBhdGNoKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBkb21Ob2RlO1xuICAgICAgICAgICAgICAgICAgICBjYXNlIFZQYXRjaC5QUk9QUzpcbiAgICAgICAgICAgICAgICAgICAgICAgIGFwcGx5UHJvcGVydGllcyhkb21Ob2RlLCBwYXRjaCwgdk5vZGUucHJvcGVydGllcyk7XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gZG9tTm9kZTtcbiAgICAgICAgICAgICAgICAgICAgY2FzZSBWUGF0Y2guVEhVTks6XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gcmVwbGFjZVJvb3QoZG9tTm9kZSwgcmVuZGVyT3B0aW9ucy5wYXRjaChkb21Ob2RlLCBwYXRjaCwgcmVuZGVyT3B0aW9ucykpO1xuICAgICAgICAgICAgICAgICAgICBkZWZhdWx0OlxuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGRvbU5vZGU7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBmdW5jdGlvbiByZW1vdmVOb2RlKGRvbU5vZGUsIHZOb2RlKSB7XG4gICAgICAgICAgICAgICAgdmFyIHBhcmVudE5vZGUgPSBkb21Ob2RlLnBhcmVudE5vZGU7XG5cbiAgICAgICAgICAgICAgICBpZiAocGFyZW50Tm9kZSkge1xuICAgICAgICAgICAgICAgICAgICBwYXJlbnROb2RlLnJlbW92ZUNoaWxkKGRvbU5vZGUpO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIGRlc3Ryb3lXaWRnZXQoZG9tTm9kZSwgdk5vZGUpO1xuXG4gICAgICAgICAgICAgICAgcmV0dXJuIG51bGw7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIGluc2VydE5vZGUocGFyZW50Tm9kZSwgdk5vZGUsIHJlbmRlck9wdGlvbnMpIHtcbiAgICAgICAgICAgICAgICB2YXIgbmV3Tm9kZSA9IHJlbmRlck9wdGlvbnMucmVuZGVyKHZOb2RlLCByZW5kZXJPcHRpb25zKTtcblxuICAgICAgICAgICAgICAgIGlmIChwYXJlbnROb2RlKSB7XG4gICAgICAgICAgICAgICAgICAgIHBhcmVudE5vZGUuYXBwZW5kQ2hpbGQobmV3Tm9kZSk7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgcmV0dXJuIHBhcmVudE5vZGU7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIHN0cmluZ1BhdGNoKGRvbU5vZGUsIGxlZnRWTm9kZSwgdlRleHQsIHJlbmRlck9wdGlvbnMpIHtcbiAgICAgICAgICAgICAgICB2YXIgbmV3Tm9kZTtcblxuICAgICAgICAgICAgICAgIGlmIChkb21Ob2RlLm5vZGVUeXBlID09PSAzKSB7XG4gICAgICAgICAgICAgICAgICAgIGRvbU5vZGUucmVwbGFjZURhdGEoMCwgZG9tTm9kZS5sZW5ndGgsIHZUZXh0LnRleHQpO1xuICAgICAgICAgICAgICAgICAgICBuZXdOb2RlID0gZG9tTm9kZTtcbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICB2YXIgcGFyZW50Tm9kZSA9IGRvbU5vZGUucGFyZW50Tm9kZTtcbiAgICAgICAgICAgICAgICAgICAgbmV3Tm9kZSA9IHJlbmRlck9wdGlvbnMucmVuZGVyKHZUZXh0LCByZW5kZXJPcHRpb25zKTtcblxuICAgICAgICAgICAgICAgICAgICBpZiAocGFyZW50Tm9kZSAmJiBuZXdOb2RlICE9PSBkb21Ob2RlKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBwYXJlbnROb2RlLnJlcGxhY2VDaGlsZChuZXdOb2RlLCBkb21Ob2RlKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHJldHVybiBuZXdOb2RlO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBmdW5jdGlvbiB3aWRnZXRQYXRjaChkb21Ob2RlLCBsZWZ0Vk5vZGUsIHdpZGdldCwgcmVuZGVyT3B0aW9ucykge1xuICAgICAgICAgICAgICAgIHZhciB1cGRhdGluZyA9IHVwZGF0ZVdpZGdldChsZWZ0Vk5vZGUsIHdpZGdldCk7XG4gICAgICAgICAgICAgICAgdmFyIG5ld05vZGU7XG5cbiAgICAgICAgICAgICAgICBpZiAodXBkYXRpbmcpIHtcbiAgICAgICAgICAgICAgICAgICAgbmV3Tm9kZSA9IHdpZGdldC51cGRhdGUobGVmdFZOb2RlLCBkb21Ob2RlKSB8fCBkb21Ob2RlO1xuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIG5ld05vZGUgPSByZW5kZXJPcHRpb25zLnJlbmRlcih3aWRnZXQsIHJlbmRlck9wdGlvbnMpO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHZhciBwYXJlbnROb2RlID0gZG9tTm9kZS5wYXJlbnROb2RlO1xuXG4gICAgICAgICAgICAgICAgaWYgKHBhcmVudE5vZGUgJiYgbmV3Tm9kZSAhPT0gZG9tTm9kZSkge1xuICAgICAgICAgICAgICAgICAgICBwYXJlbnROb2RlLnJlcGxhY2VDaGlsZChuZXdOb2RlLCBkb21Ob2RlKTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICBpZiAoIXVwZGF0aW5nKSB7XG4gICAgICAgICAgICAgICAgICAgIGRlc3Ryb3lXaWRnZXQoZG9tTm9kZSwgbGVmdFZOb2RlKTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICByZXR1cm4gbmV3Tm9kZTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZnVuY3Rpb24gdk5vZGVQYXRjaChkb21Ob2RlLCBsZWZ0Vk5vZGUsIHZOb2RlLCByZW5kZXJPcHRpb25zKSB7XG4gICAgICAgICAgICAgICAgdmFyIHBhcmVudE5vZGUgPSBkb21Ob2RlLnBhcmVudE5vZGU7XG4gICAgICAgICAgICAgICAgdmFyIG5ld05vZGUgPSByZW5kZXJPcHRpb25zLnJlbmRlcih2Tm9kZSwgcmVuZGVyT3B0aW9ucyk7XG5cbiAgICAgICAgICAgICAgICBpZiAocGFyZW50Tm9kZSAmJiBuZXdOb2RlICE9PSBkb21Ob2RlKSB7XG4gICAgICAgICAgICAgICAgICAgIHBhcmVudE5vZGUucmVwbGFjZUNoaWxkKG5ld05vZGUsIGRvbU5vZGUpO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHJldHVybiBuZXdOb2RlO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBmdW5jdGlvbiBkZXN0cm95V2lkZ2V0KGRvbU5vZGUsIHcpIHtcbiAgICAgICAgICAgICAgICBpZiAodHlwZW9mIHcuZGVzdHJveSA9PT0gXCJmdW5jdGlvblwiICYmIGlzV2lkZ2V0KHcpKSB7XG4gICAgICAgICAgICAgICAgICAgIHcuZGVzdHJveShkb21Ob2RlKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIHJlb3JkZXJDaGlsZHJlbihkb21Ob2RlLCBtb3Zlcykge1xuICAgICAgICAgICAgICAgIHZhciBjaGlsZE5vZGVzID0gZG9tTm9kZS5jaGlsZE5vZGVzO1xuICAgICAgICAgICAgICAgIHZhciBrZXlNYXAgPSB7fTtcbiAgICAgICAgICAgICAgICB2YXIgbm9kZTtcbiAgICAgICAgICAgICAgICB2YXIgcmVtb3ZlO1xuICAgICAgICAgICAgICAgIHZhciBpbnNlcnQ7XG5cbiAgICAgICAgICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IG1vdmVzLnJlbW92ZXMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgICAgICAgICAgcmVtb3ZlID0gbW92ZXMucmVtb3Zlc1tpXTtcbiAgICAgICAgICAgICAgICAgICAgbm9kZSA9IGNoaWxkTm9kZXNbcmVtb3ZlLmZyb21dO1xuICAgICAgICAgICAgICAgICAgICBpZiAocmVtb3ZlLmtleSkge1xuICAgICAgICAgICAgICAgICAgICAgICAga2V5TWFwW3JlbW92ZS5rZXldID0gbm9kZTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICBkb21Ob2RlLnJlbW92ZUNoaWxkKG5vZGUpO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHZhciBsZW5ndGggPSBjaGlsZE5vZGVzLmxlbmd0aDtcbiAgICAgICAgICAgICAgICBmb3IgKHZhciBqID0gMDsgaiA8IG1vdmVzLmluc2VydHMubGVuZ3RoOyBqKyspIHtcbiAgICAgICAgICAgICAgICAgICAgaW5zZXJ0ID0gbW92ZXMuaW5zZXJ0c1tqXTtcbiAgICAgICAgICAgICAgICAgICAgbm9kZSA9IGtleU1hcFtpbnNlcnQua2V5XTtcbiAgICAgICAgICAgICAgICAgICAgLy8gdGhpcyBpcyB0aGUgd2VpcmRlc3QgYnVnIGkndmUgZXZlciBzZWVuIGluIHdlYmtpdFxuICAgICAgICAgICAgICAgICAgICBkb21Ob2RlLmluc2VydEJlZm9yZShub2RlLCBpbnNlcnQudG8gPj0gbGVuZ3RoKysgPyBudWxsIDogY2hpbGROb2Rlc1tpbnNlcnQudG9dKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIHJlcGxhY2VSb290KG9sZFJvb3QsIG5ld1Jvb3QpIHtcbiAgICAgICAgICAgICAgICBpZiAob2xkUm9vdCAmJiBuZXdSb290ICYmIG9sZFJvb3QgIT09IG5ld1Jvb3QgJiYgb2xkUm9vdC5wYXJlbnROb2RlKSB7XG4gICAgICAgICAgICAgICAgICAgIG9sZFJvb3QucGFyZW50Tm9kZS5yZXBsYWNlQ2hpbGQobmV3Um9vdCwgb2xkUm9vdCk7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgcmV0dXJuIG5ld1Jvb3Q7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0sIHsgXCIuLi92bm9kZS9pcy13aWRnZXQuanNcIjogMjksIFwiLi4vdm5vZGUvdnBhdGNoLmpzXCI6IDMyLCBcIi4vYXBwbHktcHJvcGVydGllc1wiOiAxNCwgXCIuL3VwZGF0ZS13aWRnZXRcIjogMTkgfV0sIDE4OiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge1xuICAgICAgICAgICAgdmFyIGRvY3VtZW50ID0gcmVxdWlyZShcImdsb2JhbC9kb2N1bWVudFwiKTtcbiAgICAgICAgICAgIHZhciBpc0FycmF5ID0gcmVxdWlyZShcIngtaXMtYXJyYXlcIik7XG5cbiAgICAgICAgICAgIHZhciByZW5kZXIgPSByZXF1aXJlKFwiLi9jcmVhdGUtZWxlbWVudFwiKTtcbiAgICAgICAgICAgIHZhciBkb21JbmRleCA9IHJlcXVpcmUoXCIuL2RvbS1pbmRleFwiKTtcbiAgICAgICAgICAgIHZhciBwYXRjaE9wID0gcmVxdWlyZShcIi4vcGF0Y2gtb3BcIik7XG4gICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IHBhdGNoO1xuXG4gICAgICAgICAgICBmdW5jdGlvbiBwYXRjaChyb290Tm9kZSwgcGF0Y2hlcywgcmVuZGVyT3B0aW9ucykge1xuICAgICAgICAgICAgICAgIHJlbmRlck9wdGlvbnMgPSByZW5kZXJPcHRpb25zIHx8IHt9O1xuICAgICAgICAgICAgICAgIHJlbmRlck9wdGlvbnMucGF0Y2ggPSByZW5kZXJPcHRpb25zLnBhdGNoICYmIHJlbmRlck9wdGlvbnMucGF0Y2ggIT09IHBhdGNoID8gcmVuZGVyT3B0aW9ucy5wYXRjaCA6IHBhdGNoUmVjdXJzaXZlO1xuICAgICAgICAgICAgICAgIHJlbmRlck9wdGlvbnMucmVuZGVyID0gcmVuZGVyT3B0aW9ucy5yZW5kZXIgfHwgcmVuZGVyO1xuXG4gICAgICAgICAgICAgICAgcmV0dXJuIHJlbmRlck9wdGlvbnMucGF0Y2gocm9vdE5vZGUsIHBhdGNoZXMsIHJlbmRlck9wdGlvbnMpO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBmdW5jdGlvbiBwYXRjaFJlY3Vyc2l2ZShyb290Tm9kZSwgcGF0Y2hlcywgcmVuZGVyT3B0aW9ucykge1xuICAgICAgICAgICAgICAgIHZhciBpbmRpY2VzID0gcGF0Y2hJbmRpY2VzKHBhdGNoZXMpO1xuXG4gICAgICAgICAgICAgICAgaWYgKGluZGljZXMubGVuZ3RoID09PSAwKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiByb290Tm9kZTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICB2YXIgaW5kZXggPSBkb21JbmRleChyb290Tm9kZSwgcGF0Y2hlcy5hLCBpbmRpY2VzKTtcbiAgICAgICAgICAgICAgICB2YXIgb3duZXJEb2N1bWVudCA9IHJvb3ROb2RlLm93bmVyRG9jdW1lbnQ7XG5cbiAgICAgICAgICAgICAgICBpZiAoIXJlbmRlck9wdGlvbnMuZG9jdW1lbnQgJiYgb3duZXJEb2N1bWVudCAhPT0gZG9jdW1lbnQpIHtcbiAgICAgICAgICAgICAgICAgICAgcmVuZGVyT3B0aW9ucy5kb2N1bWVudCA9IG93bmVyRG9jdW1lbnQ7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCBpbmRpY2VzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciBub2RlSW5kZXggPSBpbmRpY2VzW2ldO1xuICAgICAgICAgICAgICAgICAgICByb290Tm9kZSA9IGFwcGx5UGF0Y2gocm9vdE5vZGUsIGluZGV4W25vZGVJbmRleF0sIHBhdGNoZXNbbm9kZUluZGV4XSwgcmVuZGVyT3B0aW9ucyk7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgcmV0dXJuIHJvb3ROb2RlO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBmdW5jdGlvbiBhcHBseVBhdGNoKHJvb3ROb2RlLCBkb21Ob2RlLCBwYXRjaExpc3QsIHJlbmRlck9wdGlvbnMpIHtcbiAgICAgICAgICAgICAgICBpZiAoIWRvbU5vZGUpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHJvb3ROb2RlO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHZhciBuZXdOb2RlO1xuXG4gICAgICAgICAgICAgICAgaWYgKGlzQXJyYXkocGF0Y2hMaXN0KSkge1xuICAgICAgICAgICAgICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IHBhdGNoTGlzdC5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgICAgICAgICAgICAgbmV3Tm9kZSA9IHBhdGNoT3AocGF0Y2hMaXN0W2ldLCBkb21Ob2RlLCByZW5kZXJPcHRpb25zKTtcblxuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGRvbU5vZGUgPT09IHJvb3ROb2RlKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcm9vdE5vZGUgPSBuZXdOb2RlO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgbmV3Tm9kZSA9IHBhdGNoT3AocGF0Y2hMaXN0LCBkb21Ob2RlLCByZW5kZXJPcHRpb25zKTtcblxuICAgICAgICAgICAgICAgICAgICBpZiAoZG9tTm9kZSA9PT0gcm9vdE5vZGUpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJvb3ROb2RlID0gbmV3Tm9kZTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHJldHVybiByb290Tm9kZTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZnVuY3Rpb24gcGF0Y2hJbmRpY2VzKHBhdGNoZXMpIHtcbiAgICAgICAgICAgICAgICB2YXIgaW5kaWNlcyA9IFtdO1xuXG4gICAgICAgICAgICAgICAgZm9yICh2YXIga2V5IGluIHBhdGNoZXMpIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKGtleSAhPT0gXCJhXCIpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGluZGljZXMucHVzaChOdW1iZXIoa2V5KSk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICByZXR1cm4gaW5kaWNlcztcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSwgeyBcIi4vY3JlYXRlLWVsZW1lbnRcIjogMTUsIFwiLi9kb20taW5kZXhcIjogMTYsIFwiLi9wYXRjaC1vcFwiOiAxNywgXCJnbG9iYWwvZG9jdW1lbnRcIjogMTAsIFwieC1pcy1hcnJheVwiOiAxMiB9XSwgMTk6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICB2YXIgaXNXaWRnZXQgPSByZXF1aXJlKFwiLi4vdm5vZGUvaXMtd2lkZ2V0LmpzXCIpO1xuXG4gICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IHVwZGF0ZVdpZGdldDtcblxuICAgICAgICAgICAgZnVuY3Rpb24gdXBkYXRlV2lkZ2V0KGEsIGIpIHtcbiAgICAgICAgICAgICAgICBpZiAoaXNXaWRnZXQoYSkgJiYgaXNXaWRnZXQoYikpIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKFwibmFtZVwiIGluIGEgJiYgXCJuYW1lXCIgaW4gYikge1xuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGEuaWQgPT09IGIuaWQ7XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gYS5pbml0ID09PSBiLmluaXQ7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0sIHsgXCIuLi92bm9kZS9pcy13aWRnZXQuanNcIjogMjkgfV0sIDIwOiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge1xuICAgICAgICAgICAgXCJ1c2Ugc3RyaWN0XCI7XG5cbiAgICAgICAgICAgIHZhciBFdlN0b3JlID0gcmVxdWlyZShcImV2LXN0b3JlXCIpO1xuXG4gICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IEV2SG9vaztcblxuICAgICAgICAgICAgZnVuY3Rpb24gRXZIb29rKHZhbHVlKSB7XG4gICAgICAgICAgICAgICAgaWYgKCEodGhpcyBpbnN0YW5jZW9mIEV2SG9vaykpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIG5ldyBFdkhvb2sodmFsdWUpO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHRoaXMudmFsdWUgPSB2YWx1ZTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgRXZIb29rLnByb3RvdHlwZS5ob29rID0gZnVuY3Rpb24gKG5vZGUsIHByb3BlcnR5TmFtZSkge1xuICAgICAgICAgICAgICAgIHZhciBlcyA9IEV2U3RvcmUobm9kZSk7XG4gICAgICAgICAgICAgICAgdmFyIHByb3BOYW1lID0gcHJvcGVydHlOYW1lLnN1YnN0cigzKTtcblxuICAgICAgICAgICAgICAgIGVzW3Byb3BOYW1lXSA9IHRoaXMudmFsdWU7XG4gICAgICAgICAgICB9O1xuXG4gICAgICAgICAgICBFdkhvb2sucHJvdG90eXBlLnVuaG9vayA9IGZ1bmN0aW9uIChub2RlLCBwcm9wZXJ0eU5hbWUpIHtcbiAgICAgICAgICAgICAgICB2YXIgZXMgPSBFdlN0b3JlKG5vZGUpO1xuICAgICAgICAgICAgICAgIHZhciBwcm9wTmFtZSA9IHByb3BlcnR5TmFtZS5zdWJzdHIoMyk7XG5cbiAgICAgICAgICAgICAgICBlc1twcm9wTmFtZV0gPSB1bmRlZmluZWQ7XG4gICAgICAgICAgICB9O1xuICAgICAgICB9LCB7IFwiZXYtc3RvcmVcIjogNyB9XSwgMjE6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICBcInVzZSBzdHJpY3RcIjtcblxuICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBTb2Z0U2V0SG9vaztcblxuICAgICAgICAgICAgZnVuY3Rpb24gU29mdFNldEhvb2sodmFsdWUpIHtcbiAgICAgICAgICAgICAgICBpZiAoISh0aGlzIGluc3RhbmNlb2YgU29mdFNldEhvb2spKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBuZXcgU29mdFNldEhvb2sodmFsdWUpO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHRoaXMudmFsdWUgPSB2YWx1ZTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgU29mdFNldEhvb2sucHJvdG90eXBlLmhvb2sgPSBmdW5jdGlvbiAobm9kZSwgcHJvcGVydHlOYW1lKSB7XG4gICAgICAgICAgICAgICAgaWYgKG5vZGVbcHJvcGVydHlOYW1lXSAhPT0gdGhpcy52YWx1ZSkge1xuICAgICAgICAgICAgICAgICAgICBub2RlW3Byb3BlcnR5TmFtZV0gPSB0aGlzLnZhbHVlO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH07XG4gICAgICAgIH0sIHt9XSwgMjI6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICBcInVzZSBzdHJpY3RcIjtcblxuICAgICAgICAgICAgdmFyIGlzQXJyYXkgPSByZXF1aXJlKFwieC1pcy1hcnJheVwiKTtcblxuICAgICAgICAgICAgdmFyIFZOb2RlID0gcmVxdWlyZShcIi4uL3Zub2RlL3Zub2RlLmpzXCIpO1xuICAgICAgICAgICAgdmFyIFZUZXh0ID0gcmVxdWlyZShcIi4uL3Zub2RlL3Z0ZXh0LmpzXCIpO1xuICAgICAgICAgICAgdmFyIGlzVk5vZGUgPSByZXF1aXJlKFwiLi4vdm5vZGUvaXMtdm5vZGVcIik7XG4gICAgICAgICAgICB2YXIgaXNWVGV4dCA9IHJlcXVpcmUoXCIuLi92bm9kZS9pcy12dGV4dFwiKTtcbiAgICAgICAgICAgIHZhciBpc1dpZGdldCA9IHJlcXVpcmUoXCIuLi92bm9kZS9pcy13aWRnZXRcIik7XG4gICAgICAgICAgICB2YXIgaXNIb29rID0gcmVxdWlyZShcIi4uL3Zub2RlL2lzLXZob29rXCIpO1xuICAgICAgICAgICAgdmFyIGlzVlRodW5rID0gcmVxdWlyZShcIi4uL3Zub2RlL2lzLXRodW5rXCIpO1xuXG4gICAgICAgICAgICB2YXIgcGFyc2VUYWcgPSByZXF1aXJlKFwiLi9wYXJzZS10YWcuanNcIik7XG4gICAgICAgICAgICB2YXIgc29mdFNldEhvb2sgPSByZXF1aXJlKFwiLi9ob29rcy9zb2Z0LXNldC1ob29rLmpzXCIpO1xuICAgICAgICAgICAgdmFyIGV2SG9vayA9IHJlcXVpcmUoXCIuL2hvb2tzL2V2LWhvb2suanNcIik7XG5cbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gaDtcblxuICAgICAgICAgICAgZnVuY3Rpb24gaCh0YWdOYW1lLCBwcm9wZXJ0aWVzLCBjaGlsZHJlbikge1xuICAgICAgICAgICAgICAgIHZhciBjaGlsZE5vZGVzID0gW107XG4gICAgICAgICAgICAgICAgdmFyIHRhZywgcHJvcHMsIGtleSwgbmFtZXNwYWNlO1xuXG4gICAgICAgICAgICAgICAgaWYgKCFjaGlsZHJlbiAmJiBpc0NoaWxkcmVuKHByb3BlcnRpZXMpKSB7XG4gICAgICAgICAgICAgICAgICAgIGNoaWxkcmVuID0gcHJvcGVydGllcztcbiAgICAgICAgICAgICAgICAgICAgcHJvcHMgPSB7fTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICBwcm9wcyA9IHByb3BzIHx8IHByb3BlcnRpZXMgfHwge307XG4gICAgICAgICAgICAgICAgdGFnID0gcGFyc2VUYWcodGFnTmFtZSwgcHJvcHMpO1xuXG4gICAgICAgICAgICAgICAgLy8gc3VwcG9ydCBrZXlzXG4gICAgICAgICAgICAgICAgaWYgKHByb3BzLmhhc093blByb3BlcnR5KFwia2V5XCIpKSB7XG4gICAgICAgICAgICAgICAgICAgIGtleSA9IHByb3BzLmtleTtcbiAgICAgICAgICAgICAgICAgICAgcHJvcHMua2V5ID0gdW5kZWZpbmVkO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIC8vIHN1cHBvcnQgbmFtZXNwYWNlXG4gICAgICAgICAgICAgICAgaWYgKHByb3BzLmhhc093blByb3BlcnR5KFwibmFtZXNwYWNlXCIpKSB7XG4gICAgICAgICAgICAgICAgICAgIG5hbWVzcGFjZSA9IHByb3BzLm5hbWVzcGFjZTtcbiAgICAgICAgICAgICAgICAgICAgcHJvcHMubmFtZXNwYWNlID0gdW5kZWZpbmVkO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIC8vIGZpeCBjdXJzb3IgYnVnXG4gICAgICAgICAgICAgICAgaWYgKHRhZyA9PT0gXCJJTlBVVFwiICYmICFuYW1lc3BhY2UgJiYgcHJvcHMuaGFzT3duUHJvcGVydHkoXCJ2YWx1ZVwiKSAmJiBwcm9wcy52YWx1ZSAhPT0gdW5kZWZpbmVkICYmICFpc0hvb2socHJvcHMudmFsdWUpKSB7XG4gICAgICAgICAgICAgICAgICAgIHByb3BzLnZhbHVlID0gc29mdFNldEhvb2socHJvcHMudmFsdWUpO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHRyYW5zZm9ybVByb3BlcnRpZXMocHJvcHMpO1xuXG4gICAgICAgICAgICAgICAgaWYgKGNoaWxkcmVuICE9PSB1bmRlZmluZWQgJiYgY2hpbGRyZW4gIT09IG51bGwpIHtcbiAgICAgICAgICAgICAgICAgICAgYWRkQ2hpbGQoY2hpbGRyZW4sIGNoaWxkTm9kZXMsIHRhZywgcHJvcHMpO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHJldHVybiBuZXcgVk5vZGUodGFnLCBwcm9wcywgY2hpbGROb2Rlcywga2V5LCBuYW1lc3BhY2UpO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBmdW5jdGlvbiBhZGRDaGlsZChjLCBjaGlsZE5vZGVzLCB0YWcsIHByb3BzKSB7XG4gICAgICAgICAgICAgICAgaWYgKHR5cGVvZiBjID09PSBcInN0cmluZ1wiKSB7XG4gICAgICAgICAgICAgICAgICAgIGNoaWxkTm9kZXMucHVzaChuZXcgVlRleHQoYykpO1xuICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAodHlwZW9mIGMgPT09IFwibnVtYmVyXCIpIHtcbiAgICAgICAgICAgICAgICAgICAgY2hpbGROb2Rlcy5wdXNoKG5ldyBWVGV4dChTdHJpbmcoYykpKTtcbiAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKGlzQ2hpbGQoYykpIHtcbiAgICAgICAgICAgICAgICAgICAgY2hpbGROb2Rlcy5wdXNoKGMpO1xuICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoaXNBcnJheShjKSkge1xuICAgICAgICAgICAgICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IGMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGFkZENoaWxkKGNbaV0sIGNoaWxkTm9kZXMsIHRhZywgcHJvcHMpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfSBlbHNlIGlmIChjID09PSBudWxsIHx8IGMgPT09IHVuZGVmaW5lZCkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgdGhyb3cgVW5leHBlY3RlZFZpcnR1YWxFbGVtZW50KHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGZvcmVpZ25PYmplY3Q6IGMsXG4gICAgICAgICAgICAgICAgICAgICAgICBwYXJlbnRWbm9kZToge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRhZ05hbWU6IHRhZyxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBwcm9wZXJ0aWVzOiBwcm9wc1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIHRyYW5zZm9ybVByb3BlcnRpZXMocHJvcHMpIHtcbiAgICAgICAgICAgICAgICBmb3IgKHZhciBwcm9wTmFtZSBpbiBwcm9wcykge1xuICAgICAgICAgICAgICAgICAgICBpZiAocHJvcHMuaGFzT3duUHJvcGVydHkocHJvcE5hbWUpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICB2YXIgdmFsdWUgPSBwcm9wc1twcm9wTmFtZV07XG5cbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChpc0hvb2sodmFsdWUpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgY29udGludWU7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChwcm9wTmFtZS5zdWJzdHIoMCwgMykgPT09IFwiZXYtXCIpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBhZGQgZXYtZm9vIHN1cHBvcnRcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBwcm9wc1twcm9wTmFtZV0gPSBldkhvb2sodmFsdWUpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBmdW5jdGlvbiBpc0NoaWxkKHgpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gaXNWTm9kZSh4KSB8fCBpc1ZUZXh0KHgpIHx8IGlzV2lkZ2V0KHgpIHx8IGlzVlRodW5rKHgpO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBmdW5jdGlvbiBpc0NoaWxkcmVuKHgpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gdHlwZW9mIHggPT09IFwic3RyaW5nXCIgfHwgaXNBcnJheSh4KSB8fCBpc0NoaWxkKHgpO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBmdW5jdGlvbiBVbmV4cGVjdGVkVmlydHVhbEVsZW1lbnQoZGF0YSkge1xuICAgICAgICAgICAgICAgIHZhciBlcnIgPSBuZXcgRXJyb3IoKTtcblxuICAgICAgICAgICAgICAgIGVyci50eXBlID0gXCJ2aXJ0dWFsLWh5cGVyc2NyaXB0LnVuZXhwZWN0ZWQudmlydHVhbC1lbGVtZW50XCI7XG4gICAgICAgICAgICAgICAgZXJyLm1lc3NhZ2UgPSBcIlVuZXhwZWN0ZWQgdmlydHVhbCBjaGlsZCBwYXNzZWQgdG8gaCgpLlxcblwiICsgXCJFeHBlY3RlZCBhIFZOb2RlIC8gVnRodW5rIC8gVldpZGdldCAvIHN0cmluZyBidXQ6XFxuXCIgKyBcImdvdDpcXG5cIiArIGVycm9yU3RyaW5nKGRhdGEuZm9yZWlnbk9iamVjdCkgKyBcIi5cXG5cIiArIFwiVGhlIHBhcmVudCB2bm9kZSBpczpcXG5cIiArIGVycm9yU3RyaW5nKGRhdGEucGFyZW50Vm5vZGUpO1xuICAgICAgICAgICAgICAgIFwiXFxuXCIgKyBcIlN1Z2dlc3RlZCBmaXg6IGNoYW5nZSB5b3VyIGBoKC4uLiwgWyAuLi4gXSlgIGNhbGxzaXRlLlwiO1xuICAgICAgICAgICAgICAgIGVyci5mb3JlaWduT2JqZWN0ID0gZGF0YS5mb3JlaWduT2JqZWN0O1xuICAgICAgICAgICAgICAgIGVyci5wYXJlbnRWbm9kZSA9IGRhdGEucGFyZW50Vm5vZGU7XG5cbiAgICAgICAgICAgICAgICByZXR1cm4gZXJyO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBmdW5jdGlvbiBlcnJvclN0cmluZyhvYmopIHtcbiAgICAgICAgICAgICAgICB0cnkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gSlNPTi5zdHJpbmdpZnkob2JqLCBudWxsLCBcIiAgICBcIik7XG4gICAgICAgICAgICAgICAgfSBjYXRjaCAoZSkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gU3RyaW5nKG9iaik7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9LCB7IFwiLi4vdm5vZGUvaXMtdGh1bmtcIjogMjUsIFwiLi4vdm5vZGUvaXMtdmhvb2tcIjogMjYsIFwiLi4vdm5vZGUvaXMtdm5vZGVcIjogMjcsIFwiLi4vdm5vZGUvaXMtdnRleHRcIjogMjgsIFwiLi4vdm5vZGUvaXMtd2lkZ2V0XCI6IDI5LCBcIi4uL3Zub2RlL3Zub2RlLmpzXCI6IDMxLCBcIi4uL3Zub2RlL3Z0ZXh0LmpzXCI6IDMzLCBcIi4vaG9va3MvZXYtaG9vay5qc1wiOiAyMCwgXCIuL2hvb2tzL3NvZnQtc2V0LWhvb2suanNcIjogMjEsIFwiLi9wYXJzZS10YWcuanNcIjogMjMsIFwieC1pcy1hcnJheVwiOiAxMiB9XSwgMjM6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICBcInVzZSBzdHJpY3RcIjtcblxuICAgICAgICAgICAgdmFyIHNwbGl0ID0gcmVxdWlyZShcImJyb3dzZXItc3BsaXRcIik7XG5cbiAgICAgICAgICAgIHZhciBjbGFzc0lkU3BsaXQgPSAvKFtcXC4jXT9bYS16QS1aMC05XFx1MDA3Ri1cXHVGRkZGXzotXSspLztcbiAgICAgICAgICAgIHZhciBub3RDbGFzc0lkID0gL15cXC58Iy87XG5cbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gcGFyc2VUYWc7XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIHBhcnNlVGFnKHRhZywgcHJvcHMpIHtcbiAgICAgICAgICAgICAgICBpZiAoIXRhZykge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gXCJESVZcIjtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICB2YXIgbm9JZCA9ICFwcm9wcy5oYXNPd25Qcm9wZXJ0eShcImlkXCIpO1xuXG4gICAgICAgICAgICAgICAgdmFyIHRhZ1BhcnRzID0gc3BsaXQodGFnLCBjbGFzc0lkU3BsaXQpO1xuICAgICAgICAgICAgICAgIHZhciB0YWdOYW1lID0gbnVsbDtcblxuICAgICAgICAgICAgICAgIGlmIChub3RDbGFzc0lkLnRlc3QodGFnUGFydHNbMV0pKSB7XG4gICAgICAgICAgICAgICAgICAgIHRhZ05hbWUgPSBcIkRJVlwiO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHZhciBjbGFzc2VzLCBwYXJ0LCB0eXBlLCBpO1xuXG4gICAgICAgICAgICAgICAgZm9yIChpID0gMDsgaSA8IHRhZ1BhcnRzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICAgICAgICAgIHBhcnQgPSB0YWdQYXJ0c1tpXTtcblxuICAgICAgICAgICAgICAgICAgICBpZiAoIXBhcnQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnRpbnVlO1xuICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgdHlwZSA9IHBhcnQuY2hhckF0KDApO1xuXG4gICAgICAgICAgICAgICAgICAgIGlmICghdGFnTmFtZSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgdGFnTmFtZSA9IHBhcnQ7XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAodHlwZSA9PT0gXCIuXCIpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGNsYXNzZXMgPSBjbGFzc2VzIHx8IFtdO1xuICAgICAgICAgICAgICAgICAgICAgICAgY2xhc3Nlcy5wdXNoKHBhcnQuc3Vic3RyaW5nKDEsIHBhcnQubGVuZ3RoKSk7XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAodHlwZSA9PT0gXCIjXCIgJiYgbm9JZCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgcHJvcHMuaWQgPSBwYXJ0LnN1YnN0cmluZygxLCBwYXJ0Lmxlbmd0aCk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICBpZiAoY2xhc3Nlcykge1xuICAgICAgICAgICAgICAgICAgICBpZiAocHJvcHMuY2xhc3NOYW1lKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBjbGFzc2VzLnB1c2gocHJvcHMuY2xhc3NOYW1lKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgIHByb3BzLmNsYXNzTmFtZSA9IGNsYXNzZXMuam9pbihcIiBcIik7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgcmV0dXJuIHByb3BzLm5hbWVzcGFjZSA/IHRhZ05hbWUgOiB0YWdOYW1lLnRvVXBwZXJDYXNlKCk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0sIHsgXCJicm93c2VyLXNwbGl0XCI6IDUgfV0sIDI0OiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge1xuICAgICAgICAgICAgdmFyIGlzVk5vZGUgPSByZXF1aXJlKFwiLi9pcy12bm9kZVwiKTtcbiAgICAgICAgICAgIHZhciBpc1ZUZXh0ID0gcmVxdWlyZShcIi4vaXMtdnRleHRcIik7XG4gICAgICAgICAgICB2YXIgaXNXaWRnZXQgPSByZXF1aXJlKFwiLi9pcy13aWRnZXRcIik7XG4gICAgICAgICAgICB2YXIgaXNUaHVuayA9IHJlcXVpcmUoXCIuL2lzLXRodW5rXCIpO1xuXG4gICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IGhhbmRsZVRodW5rO1xuXG4gICAgICAgICAgICBmdW5jdGlvbiBoYW5kbGVUaHVuayhhLCBiKSB7XG4gICAgICAgICAgICAgICAgdmFyIHJlbmRlcmVkQSA9IGE7XG4gICAgICAgICAgICAgICAgdmFyIHJlbmRlcmVkQiA9IGI7XG5cbiAgICAgICAgICAgICAgICBpZiAoaXNUaHVuayhiKSkge1xuICAgICAgICAgICAgICAgICAgICByZW5kZXJlZEIgPSByZW5kZXJUaHVuayhiLCBhKTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICBpZiAoaXNUaHVuayhhKSkge1xuICAgICAgICAgICAgICAgICAgICByZW5kZXJlZEEgPSByZW5kZXJUaHVuayhhLCBudWxsKTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgICAgICAgICBhOiByZW5kZXJlZEEsXG4gICAgICAgICAgICAgICAgICAgIGI6IHJlbmRlcmVkQlxuICAgICAgICAgICAgICAgIH07XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIHJlbmRlclRodW5rKHRodW5rLCBwcmV2aW91cykge1xuICAgICAgICAgICAgICAgIHZhciByZW5kZXJlZFRodW5rID0gdGh1bmsudm5vZGU7XG5cbiAgICAgICAgICAgICAgICBpZiAoIXJlbmRlcmVkVGh1bmspIHtcbiAgICAgICAgICAgICAgICAgICAgcmVuZGVyZWRUaHVuayA9IHRodW5rLnZub2RlID0gdGh1bmsucmVuZGVyKHByZXZpb3VzKTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICBpZiAoIShpc1ZOb2RlKHJlbmRlcmVkVGh1bmspIHx8IGlzVlRleHQocmVuZGVyZWRUaHVuaykgfHwgaXNXaWRnZXQocmVuZGVyZWRUaHVuaykpKSB7XG4gICAgICAgICAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcihcInRodW5rIGRpZCBub3QgcmV0dXJuIGEgdmFsaWQgbm9kZVwiKTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICByZXR1cm4gcmVuZGVyZWRUaHVuaztcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSwgeyBcIi4vaXMtdGh1bmtcIjogMjUsIFwiLi9pcy12bm9kZVwiOiAyNywgXCIuL2lzLXZ0ZXh0XCI6IDI4LCBcIi4vaXMtd2lkZ2V0XCI6IDI5IH1dLCAyNTogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHtcbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gaXNUaHVuaztcblxuICAgICAgICAgICAgZnVuY3Rpb24gaXNUaHVuayh0KSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHQgJiYgdC50eXBlID09PSBcIlRodW5rXCI7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0sIHt9XSwgMjY6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IGlzSG9vaztcblxuICAgICAgICAgICAgZnVuY3Rpb24gaXNIb29rKGhvb2spIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gaG9vayAmJiAodHlwZW9mIGhvb2suaG9vayA9PT0gXCJmdW5jdGlvblwiICYmICFob29rLmhhc093blByb3BlcnR5KFwiaG9va1wiKSB8fCB0eXBlb2YgaG9vay51bmhvb2sgPT09IFwiZnVuY3Rpb25cIiAmJiAhaG9vay5oYXNPd25Qcm9wZXJ0eShcInVuaG9va1wiKSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0sIHt9XSwgMjc6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICB2YXIgdmVyc2lvbiA9IHJlcXVpcmUoXCIuL3ZlcnNpb25cIik7XG5cbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gaXNWaXJ0dWFsTm9kZTtcblxuICAgICAgICAgICAgZnVuY3Rpb24gaXNWaXJ0dWFsTm9kZSh4KSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHggJiYgeC50eXBlID09PSBcIlZpcnR1YWxOb2RlXCIgJiYgeC52ZXJzaW9uID09PSB2ZXJzaW9uO1xuICAgICAgICAgICAgfVxuICAgICAgICB9LCB7IFwiLi92ZXJzaW9uXCI6IDMwIH1dLCAyODogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHtcbiAgICAgICAgICAgIHZhciB2ZXJzaW9uID0gcmVxdWlyZShcIi4vdmVyc2lvblwiKTtcblxuICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBpc1ZpcnR1YWxUZXh0O1xuXG4gICAgICAgICAgICBmdW5jdGlvbiBpc1ZpcnR1YWxUZXh0KHgpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4geCAmJiB4LnR5cGUgPT09IFwiVmlydHVhbFRleHRcIiAmJiB4LnZlcnNpb24gPT09IHZlcnNpb247XG4gICAgICAgICAgICB9XG4gICAgICAgIH0sIHsgXCIuL3ZlcnNpb25cIjogMzAgfV0sIDI5OiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge1xuICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBpc1dpZGdldDtcblxuICAgICAgICAgICAgZnVuY3Rpb24gaXNXaWRnZXQodykge1xuICAgICAgICAgICAgICAgIHJldHVybiB3ICYmIHcudHlwZSA9PT0gXCJXaWRnZXRcIjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSwge31dLCAzMDogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHtcbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gXCIyXCI7XG4gICAgICAgIH0sIHt9XSwgMzE6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICB2YXIgdmVyc2lvbiA9IHJlcXVpcmUoXCIuL3ZlcnNpb25cIik7XG4gICAgICAgICAgICB2YXIgaXNWTm9kZSA9IHJlcXVpcmUoXCIuL2lzLXZub2RlXCIpO1xuICAgICAgICAgICAgdmFyIGlzV2lkZ2V0ID0gcmVxdWlyZShcIi4vaXMtd2lkZ2V0XCIpO1xuICAgICAgICAgICAgdmFyIGlzVGh1bmsgPSByZXF1aXJlKFwiLi9pcy10aHVua1wiKTtcbiAgICAgICAgICAgIHZhciBpc1ZIb29rID0gcmVxdWlyZShcIi4vaXMtdmhvb2tcIik7XG5cbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gVmlydHVhbE5vZGU7XG5cbiAgICAgICAgICAgIHZhciBub1Byb3BlcnRpZXMgPSB7fTtcbiAgICAgICAgICAgIHZhciBub0NoaWxkcmVuID0gW107XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIFZpcnR1YWxOb2RlKHRhZ05hbWUsIHByb3BlcnRpZXMsIGNoaWxkcmVuLCBrZXksIG5hbWVzcGFjZSkge1xuICAgICAgICAgICAgICAgIHRoaXMudGFnTmFtZSA9IHRhZ05hbWU7XG4gICAgICAgICAgICAgICAgdGhpcy5wcm9wZXJ0aWVzID0gcHJvcGVydGllcyB8fCBub1Byb3BlcnRpZXM7XG4gICAgICAgICAgICAgICAgdGhpcy5jaGlsZHJlbiA9IGNoaWxkcmVuIHx8IG5vQ2hpbGRyZW47XG4gICAgICAgICAgICAgICAgdGhpcy5rZXkgPSBrZXkgIT0gbnVsbCA/IFN0cmluZyhrZXkpIDogdW5kZWZpbmVkO1xuICAgICAgICAgICAgICAgIHRoaXMubmFtZXNwYWNlID0gdHlwZW9mIG5hbWVzcGFjZSA9PT0gXCJzdHJpbmdcIiA/IG5hbWVzcGFjZSA6IG51bGw7XG5cbiAgICAgICAgICAgICAgICB2YXIgY291bnQgPSBjaGlsZHJlbiAmJiBjaGlsZHJlbi5sZW5ndGggfHwgMDtcbiAgICAgICAgICAgICAgICB2YXIgZGVzY2VuZGFudHMgPSAwO1xuICAgICAgICAgICAgICAgIHZhciBoYXNXaWRnZXRzID0gZmFsc2U7XG4gICAgICAgICAgICAgICAgdmFyIGhhc1RodW5rcyA9IGZhbHNlO1xuICAgICAgICAgICAgICAgIHZhciBkZXNjZW5kYW50SG9va3MgPSBmYWxzZTtcbiAgICAgICAgICAgICAgICB2YXIgaG9va3M7XG5cbiAgICAgICAgICAgICAgICBmb3IgKHZhciBwcm9wTmFtZSBpbiBwcm9wZXJ0aWVzKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmIChwcm9wZXJ0aWVzLmhhc093blByb3BlcnR5KHByb3BOYW1lKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgdmFyIHByb3BlcnR5ID0gcHJvcGVydGllc1twcm9wTmFtZV07XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoaXNWSG9vayhwcm9wZXJ0eSkgJiYgcHJvcGVydHkudW5ob29rKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKCFob29rcykge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBob29rcyA9IHt9O1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGhvb2tzW3Byb3BOYW1lXSA9IHByb3BlcnR5O1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCBjb3VudDsgaSsrKSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciBjaGlsZCA9IGNoaWxkcmVuW2ldO1xuICAgICAgICAgICAgICAgICAgICBpZiAoaXNWTm9kZShjaGlsZCkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGRlc2NlbmRhbnRzICs9IGNoaWxkLmNvdW50IHx8IDA7XG5cbiAgICAgICAgICAgICAgICAgICAgICAgIGlmICghaGFzV2lkZ2V0cyAmJiBjaGlsZC5oYXNXaWRnZXRzKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaGFzV2lkZ2V0cyA9IHRydWU7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgICAgIGlmICghaGFzVGh1bmtzICYmIGNoaWxkLmhhc1RodW5rcykge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGhhc1RodW5rcyA9IHRydWU7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgICAgIGlmICghZGVzY2VuZGFudEhvb2tzICYmIChjaGlsZC5ob29rcyB8fCBjaGlsZC5kZXNjZW5kYW50SG9va3MpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgZGVzY2VuZGFudEhvb2tzID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIGlmICghaGFzV2lkZ2V0cyAmJiBpc1dpZGdldChjaGlsZCkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmICh0eXBlb2YgY2hpbGQuZGVzdHJveSA9PT0gXCJmdW5jdGlvblwiKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaGFzV2lkZ2V0cyA9IHRydWU7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoIWhhc1RodW5rcyAmJiBpc1RodW5rKGNoaWxkKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgaGFzVGh1bmtzID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHRoaXMuY291bnQgPSBjb3VudCArIGRlc2NlbmRhbnRzO1xuICAgICAgICAgICAgICAgIHRoaXMuaGFzV2lkZ2V0cyA9IGhhc1dpZGdldHM7XG4gICAgICAgICAgICAgICAgdGhpcy5oYXNUaHVua3MgPSBoYXNUaHVua3M7XG4gICAgICAgICAgICAgICAgdGhpcy5ob29rcyA9IGhvb2tzO1xuICAgICAgICAgICAgICAgIHRoaXMuZGVzY2VuZGFudEhvb2tzID0gZGVzY2VuZGFudEhvb2tzO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBWaXJ0dWFsTm9kZS5wcm90b3R5cGUudmVyc2lvbiA9IHZlcnNpb247XG4gICAgICAgICAgICBWaXJ0dWFsTm9kZS5wcm90b3R5cGUudHlwZSA9IFwiVmlydHVhbE5vZGVcIjtcbiAgICAgICAgfSwgeyBcIi4vaXMtdGh1bmtcIjogMjUsIFwiLi9pcy12aG9va1wiOiAyNiwgXCIuL2lzLXZub2RlXCI6IDI3LCBcIi4vaXMtd2lkZ2V0XCI6IDI5LCBcIi4vdmVyc2lvblwiOiAzMCB9XSwgMzI6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICB2YXIgdmVyc2lvbiA9IHJlcXVpcmUoXCIuL3ZlcnNpb25cIik7XG5cbiAgICAgICAgICAgIFZpcnR1YWxQYXRjaC5OT05FID0gMDtcbiAgICAgICAgICAgIFZpcnR1YWxQYXRjaC5WVEVYVCA9IDE7XG4gICAgICAgICAgICBWaXJ0dWFsUGF0Y2guVk5PREUgPSAyO1xuICAgICAgICAgICAgVmlydHVhbFBhdGNoLldJREdFVCA9IDM7XG4gICAgICAgICAgICBWaXJ0dWFsUGF0Y2guUFJPUFMgPSA0O1xuICAgICAgICAgICAgVmlydHVhbFBhdGNoLk9SREVSID0gNTtcbiAgICAgICAgICAgIFZpcnR1YWxQYXRjaC5JTlNFUlQgPSA2O1xuICAgICAgICAgICAgVmlydHVhbFBhdGNoLlJFTU9WRSA9IDc7XG4gICAgICAgICAgICBWaXJ0dWFsUGF0Y2guVEhVTksgPSA4O1xuXG4gICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IFZpcnR1YWxQYXRjaDtcblxuICAgICAgICAgICAgZnVuY3Rpb24gVmlydHVhbFBhdGNoKHR5cGUsIHZOb2RlLCBwYXRjaCkge1xuICAgICAgICAgICAgICAgIHRoaXMudHlwZSA9IE51bWJlcih0eXBlKTtcbiAgICAgICAgICAgICAgICB0aGlzLnZOb2RlID0gdk5vZGU7XG4gICAgICAgICAgICAgICAgdGhpcy5wYXRjaCA9IHBhdGNoO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBWaXJ0dWFsUGF0Y2gucHJvdG90eXBlLnZlcnNpb24gPSB2ZXJzaW9uO1xuICAgICAgICAgICAgVmlydHVhbFBhdGNoLnByb3RvdHlwZS50eXBlID0gXCJWaXJ0dWFsUGF0Y2hcIjtcbiAgICAgICAgfSwgeyBcIi4vdmVyc2lvblwiOiAzMCB9XSwgMzM6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICB2YXIgdmVyc2lvbiA9IHJlcXVpcmUoXCIuL3ZlcnNpb25cIik7XG5cbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gVmlydHVhbFRleHQ7XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIFZpcnR1YWxUZXh0KHRleHQpIHtcbiAgICAgICAgICAgICAgICB0aGlzLnRleHQgPSBTdHJpbmcodGV4dCk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIFZpcnR1YWxUZXh0LnByb3RvdHlwZS52ZXJzaW9uID0gdmVyc2lvbjtcbiAgICAgICAgICAgIFZpcnR1YWxUZXh0LnByb3RvdHlwZS50eXBlID0gXCJWaXJ0dWFsVGV4dFwiO1xuICAgICAgICB9LCB7IFwiLi92ZXJzaW9uXCI6IDMwIH1dLCAzNDogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHtcbiAgICAgICAgICAgIHZhciBpc09iamVjdCA9IHJlcXVpcmUoXCJpcy1vYmplY3RcIik7XG4gICAgICAgICAgICB2YXIgaXNIb29rID0gcmVxdWlyZShcIi4uL3Zub2RlL2lzLXZob29rXCIpO1xuXG4gICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IGRpZmZQcm9wcztcblxuICAgICAgICAgICAgZnVuY3Rpb24gZGlmZlByb3BzKGEsIGIpIHtcbiAgICAgICAgICAgICAgICB2YXIgZGlmZjtcblxuICAgICAgICAgICAgICAgIGZvciAodmFyIGFLZXkgaW4gYSkge1xuICAgICAgICAgICAgICAgICAgICBpZiAoIShhS2V5IGluIGIpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBkaWZmID0gZGlmZiB8fCB7fTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGRpZmZbYUtleV0gPSB1bmRlZmluZWQ7XG4gICAgICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgICAgICB2YXIgYVZhbHVlID0gYVthS2V5XTtcbiAgICAgICAgICAgICAgICAgICAgdmFyIGJWYWx1ZSA9IGJbYUtleV07XG5cbiAgICAgICAgICAgICAgICAgICAgaWYgKGFWYWx1ZSA9PT0gYlZhbHVlKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBjb250aW51ZTtcbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIGlmIChpc09iamVjdChhVmFsdWUpICYmIGlzT2JqZWN0KGJWYWx1ZSkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChnZXRQcm90b3R5cGUoYlZhbHVlKSAhPT0gZ2V0UHJvdG90eXBlKGFWYWx1ZSkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBkaWZmID0gZGlmZiB8fCB7fTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBkaWZmW2FLZXldID0gYlZhbHVlO1xuICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIGlmIChpc0hvb2soYlZhbHVlKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRpZmYgPSBkaWZmIHx8IHt9O1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRpZmZbYUtleV0gPSBiVmFsdWU7XG4gICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZhciBvYmplY3REaWZmID0gZGlmZlByb3BzKGFWYWx1ZSwgYlZhbHVlKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAob2JqZWN0RGlmZikge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBkaWZmID0gZGlmZiB8fCB7fTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZGlmZlthS2V5XSA9IG9iamVjdERpZmY7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgZGlmZiA9IGRpZmYgfHwge307XG4gICAgICAgICAgICAgICAgICAgICAgICBkaWZmW2FLZXldID0gYlZhbHVlO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgZm9yICh2YXIgYktleSBpbiBiKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmICghKGJLZXkgaW4gYSkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGRpZmYgPSBkaWZmIHx8IHt9O1xuICAgICAgICAgICAgICAgICAgICAgICAgZGlmZltiS2V5XSA9IGJbYktleV07XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICByZXR1cm4gZGlmZjtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZnVuY3Rpb24gZ2V0UHJvdG90eXBlKHZhbHVlKSB7XG4gICAgICAgICAgICAgICAgaWYgKE9iamVjdC5nZXRQcm90b3R5cGVPZikge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gT2JqZWN0LmdldFByb3RvdHlwZU9mKHZhbHVlKTtcbiAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKHZhbHVlLl9fcHJvdG9fXykge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gdmFsdWUuX19wcm90b19fO1xuICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAodmFsdWUuY29uc3RydWN0b3IpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHZhbHVlLmNvbnN0cnVjdG9yLnByb3RvdHlwZTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH0sIHsgXCIuLi92bm9kZS9pcy12aG9va1wiOiAyNiwgXCJpcy1vYmplY3RcIjogMTEgfV0sIDM1OiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge1xuICAgICAgICAgICAgdmFyIGlzQXJyYXkgPSByZXF1aXJlKFwieC1pcy1hcnJheVwiKTtcblxuICAgICAgICAgICAgdmFyIFZQYXRjaCA9IHJlcXVpcmUoXCIuLi92bm9kZS92cGF0Y2hcIik7XG4gICAgICAgICAgICB2YXIgaXNWTm9kZSA9IHJlcXVpcmUoXCIuLi92bm9kZS9pcy12bm9kZVwiKTtcbiAgICAgICAgICAgIHZhciBpc1ZUZXh0ID0gcmVxdWlyZShcIi4uL3Zub2RlL2lzLXZ0ZXh0XCIpO1xuICAgICAgICAgICAgdmFyIGlzV2lkZ2V0ID0gcmVxdWlyZShcIi4uL3Zub2RlL2lzLXdpZGdldFwiKTtcbiAgICAgICAgICAgIHZhciBpc1RodW5rID0gcmVxdWlyZShcIi4uL3Zub2RlL2lzLXRodW5rXCIpO1xuICAgICAgICAgICAgdmFyIGhhbmRsZVRodW5rID0gcmVxdWlyZShcIi4uL3Zub2RlL2hhbmRsZS10aHVua1wiKTtcblxuICAgICAgICAgICAgdmFyIGRpZmZQcm9wcyA9IHJlcXVpcmUoXCIuL2RpZmYtcHJvcHNcIik7XG5cbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gZGlmZjtcblxuICAgICAgICAgICAgZnVuY3Rpb24gZGlmZihhLCBiKSB7XG4gICAgICAgICAgICAgICAgdmFyIHBhdGNoID0geyBhOiBhIH07XG4gICAgICAgICAgICAgICAgd2FsayhhLCBiLCBwYXRjaCwgMCk7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHBhdGNoO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBmdW5jdGlvbiB3YWxrKGEsIGIsIHBhdGNoLCBpbmRleCkge1xuICAgICAgICAgICAgICAgIGlmIChhID09PSBiKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICB2YXIgYXBwbHkgPSBwYXRjaFtpbmRleF07XG4gICAgICAgICAgICAgICAgdmFyIGFwcGx5Q2xlYXIgPSBmYWxzZTtcblxuICAgICAgICAgICAgICAgIGlmIChpc1RodW5rKGEpIHx8IGlzVGh1bmsoYikpIHtcbiAgICAgICAgICAgICAgICAgICAgdGh1bmtzKGEsIGIsIHBhdGNoLCBpbmRleCk7XG4gICAgICAgICAgICAgICAgfSBlbHNlIGlmIChiID09IG51bGwpIHtcblxuICAgICAgICAgICAgICAgICAgICAvLyBJZiBhIGlzIGEgd2lkZ2V0IHdlIHdpbGwgYWRkIGEgcmVtb3ZlIHBhdGNoIGZvciBpdFxuICAgICAgICAgICAgICAgICAgICAvLyBPdGhlcndpc2UgYW55IGNoaWxkIHdpZGdldHMvaG9va3MgbXVzdCBiZSBkZXN0cm95ZWQuXG4gICAgICAgICAgICAgICAgICAgIC8vIFRoaXMgcHJldmVudHMgYWRkaW5nIHR3byByZW1vdmUgcGF0Y2hlcyBmb3IgYSB3aWRnZXQuXG4gICAgICAgICAgICAgICAgICAgIGlmICghaXNXaWRnZXQoYSkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGNsZWFyU3RhdGUoYSwgcGF0Y2gsIGluZGV4KTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGFwcGx5ID0gcGF0Y2hbaW5kZXhdO1xuICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgYXBwbHkgPSBhcHBlbmRQYXRjaChhcHBseSwgbmV3IFZQYXRjaChWUGF0Y2guUkVNT1ZFLCBhLCBiKSk7XG4gICAgICAgICAgICAgICAgfSBlbHNlIGlmIChpc1ZOb2RlKGIpKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmIChpc1ZOb2RlKGEpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoYS50YWdOYW1lID09PSBiLnRhZ05hbWUgJiYgYS5uYW1lc3BhY2UgPT09IGIubmFtZXNwYWNlICYmIGEua2V5ID09PSBiLmtleSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZhciBwcm9wc1BhdGNoID0gZGlmZlByb3BzKGEucHJvcGVydGllcywgYi5wcm9wZXJ0aWVzKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAocHJvcHNQYXRjaCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBhcHBseSA9IGFwcGVuZFBhdGNoKGFwcGx5LCBuZXcgVlBhdGNoKFZQYXRjaC5QUk9QUywgYSwgcHJvcHNQYXRjaCkpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBhcHBseSA9IGRpZmZDaGlsZHJlbihhLCBiLCBwYXRjaCwgYXBwbHksIGluZGV4KTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgYXBwbHkgPSBhcHBlbmRQYXRjaChhcHBseSwgbmV3IFZQYXRjaChWUGF0Y2guVk5PREUsIGEsIGIpKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBhcHBseUNsZWFyID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGFwcGx5ID0gYXBwZW5kUGF0Y2goYXBwbHksIG5ldyBWUGF0Y2goVlBhdGNoLlZOT0RFLCBhLCBiKSk7XG4gICAgICAgICAgICAgICAgICAgICAgICBhcHBseUNsZWFyID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoaXNWVGV4dChiKSkge1xuICAgICAgICAgICAgICAgICAgICBpZiAoIWlzVlRleHQoYSkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGFwcGx5ID0gYXBwZW5kUGF0Y2goYXBwbHksIG5ldyBWUGF0Y2goVlBhdGNoLlZURVhULCBhLCBiKSk7XG4gICAgICAgICAgICAgICAgICAgICAgICBhcHBseUNsZWFyID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIGlmIChhLnRleHQgIT09IGIudGV4dCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgYXBwbHkgPSBhcHBlbmRQYXRjaChhcHBseSwgbmV3IFZQYXRjaChWUGF0Y2guVlRFWFQsIGEsIGIpKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoaXNXaWRnZXQoYikpIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKCFpc1dpZGdldChhKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgYXBwbHlDbGVhciA9IHRydWU7XG4gICAgICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgICAgICBhcHBseSA9IGFwcGVuZFBhdGNoKGFwcGx5LCBuZXcgVlBhdGNoKFZQYXRjaC5XSURHRVQsIGEsIGIpKTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICBpZiAoYXBwbHkpIHtcbiAgICAgICAgICAgICAgICAgICAgcGF0Y2hbaW5kZXhdID0gYXBwbHk7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgaWYgKGFwcGx5Q2xlYXIpIHtcbiAgICAgICAgICAgICAgICAgICAgY2xlYXJTdGF0ZShhLCBwYXRjaCwgaW5kZXgpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZnVuY3Rpb24gZGlmZkNoaWxkcmVuKGEsIGIsIHBhdGNoLCBhcHBseSwgaW5kZXgpIHtcbiAgICAgICAgICAgICAgICB2YXIgYUNoaWxkcmVuID0gYS5jaGlsZHJlbjtcbiAgICAgICAgICAgICAgICB2YXIgb3JkZXJlZFNldCA9IHJlb3JkZXIoYUNoaWxkcmVuLCBiLmNoaWxkcmVuKTtcbiAgICAgICAgICAgICAgICB2YXIgYkNoaWxkcmVuID0gb3JkZXJlZFNldC5jaGlsZHJlbjtcblxuICAgICAgICAgICAgICAgIHZhciBhTGVuID0gYUNoaWxkcmVuLmxlbmd0aDtcbiAgICAgICAgICAgICAgICB2YXIgYkxlbiA9IGJDaGlsZHJlbi5sZW5ndGg7XG4gICAgICAgICAgICAgICAgdmFyIGxlbiA9IGFMZW4gPiBiTGVuID8gYUxlbiA6IGJMZW47XG5cbiAgICAgICAgICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IGxlbjsgaSsrKSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciBsZWZ0Tm9kZSA9IGFDaGlsZHJlbltpXTtcbiAgICAgICAgICAgICAgICAgICAgdmFyIHJpZ2h0Tm9kZSA9IGJDaGlsZHJlbltpXTtcbiAgICAgICAgICAgICAgICAgICAgaW5kZXggKz0gMTtcblxuICAgICAgICAgICAgICAgICAgICBpZiAoIWxlZnROb2RlKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAocmlnaHROb2RlKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gRXhjZXNzIG5vZGVzIGluIGIgbmVlZCB0byBiZSBhZGRlZFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGFwcGx5ID0gYXBwZW5kUGF0Y2goYXBwbHksIG5ldyBWUGF0Y2goVlBhdGNoLklOU0VSVCwgbnVsbCwgcmlnaHROb2RlKSk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICB3YWxrKGxlZnROb2RlLCByaWdodE5vZGUsIHBhdGNoLCBpbmRleCk7XG4gICAgICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgICAgICBpZiAoaXNWTm9kZShsZWZ0Tm9kZSkgJiYgbGVmdE5vZGUuY291bnQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGluZGV4ICs9IGxlZnROb2RlLmNvdW50O1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgaWYgKG9yZGVyZWRTZXQubW92ZXMpIHtcbiAgICAgICAgICAgICAgICAgICAgLy8gUmVvcmRlciBub2RlcyBsYXN0XG4gICAgICAgICAgICAgICAgICAgIGFwcGx5ID0gYXBwZW5kUGF0Y2goYXBwbHksIG5ldyBWUGF0Y2goVlBhdGNoLk9SREVSLCBhLCBvcmRlcmVkU2V0Lm1vdmVzKSk7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgcmV0dXJuIGFwcGx5O1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBmdW5jdGlvbiBjbGVhclN0YXRlKHZOb2RlLCBwYXRjaCwgaW5kZXgpIHtcbiAgICAgICAgICAgICAgICAvLyBUT0RPOiBNYWtlIHRoaXMgYSBzaW5nbGUgd2Fsaywgbm90IHR3b1xuICAgICAgICAgICAgICAgIHVuaG9vayh2Tm9kZSwgcGF0Y2gsIGluZGV4KTtcbiAgICAgICAgICAgICAgICBkZXN0cm95V2lkZ2V0cyh2Tm9kZSwgcGF0Y2gsIGluZGV4KTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgLy8gUGF0Y2ggcmVjb3JkcyBmb3IgYWxsIGRlc3Ryb3llZCB3aWRnZXRzIG11c3QgYmUgYWRkZWQgYmVjYXVzZSB3ZSBuZWVkXG4gICAgICAgICAgICAvLyBhIERPTSBub2RlIHJlZmVyZW5jZSBmb3IgdGhlIGRlc3Ryb3kgZnVuY3Rpb25cbiAgICAgICAgICAgIGZ1bmN0aW9uIGRlc3Ryb3lXaWRnZXRzKHZOb2RlLCBwYXRjaCwgaW5kZXgpIHtcbiAgICAgICAgICAgICAgICBpZiAoaXNXaWRnZXQodk5vZGUpKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmICh0eXBlb2Ygdk5vZGUuZGVzdHJveSA9PT0gXCJmdW5jdGlvblwiKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBwYXRjaFtpbmRleF0gPSBhcHBlbmRQYXRjaChwYXRjaFtpbmRleF0sIG5ldyBWUGF0Y2goVlBhdGNoLlJFTU9WRSwgdk5vZGUsIG51bGwpKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoaXNWTm9kZSh2Tm9kZSkgJiYgKHZOb2RlLmhhc1dpZGdldHMgfHwgdk5vZGUuaGFzVGh1bmtzKSkge1xuICAgICAgICAgICAgICAgICAgICB2YXIgY2hpbGRyZW4gPSB2Tm9kZS5jaGlsZHJlbjtcbiAgICAgICAgICAgICAgICAgICAgdmFyIGxlbiA9IGNoaWxkcmVuLmxlbmd0aDtcbiAgICAgICAgICAgICAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCBsZW47IGkrKykge1xuICAgICAgICAgICAgICAgICAgICAgICAgdmFyIGNoaWxkID0gY2hpbGRyZW5baV07XG4gICAgICAgICAgICAgICAgICAgICAgICBpbmRleCArPSAxO1xuXG4gICAgICAgICAgICAgICAgICAgICAgICBkZXN0cm95V2lkZ2V0cyhjaGlsZCwgcGF0Y2gsIGluZGV4KTtcblxuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGlzVk5vZGUoY2hpbGQpICYmIGNoaWxkLmNvdW50KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaW5kZXggKz0gY2hpbGQuY291bnQ7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKGlzVGh1bmsodk5vZGUpKSB7XG4gICAgICAgICAgICAgICAgICAgIHRodW5rcyh2Tm9kZSwgbnVsbCwgcGF0Y2gsIGluZGV4KTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIC8vIENyZWF0ZSBhIHN1Yi1wYXRjaCBmb3IgdGh1bmtzXG4gICAgICAgICAgICBmdW5jdGlvbiB0aHVua3MoYSwgYiwgcGF0Y2gsIGluZGV4KSB7XG4gICAgICAgICAgICAgICAgdmFyIG5vZGVzID0gaGFuZGxlVGh1bmsoYSwgYik7XG4gICAgICAgICAgICAgICAgdmFyIHRodW5rUGF0Y2ggPSBkaWZmKG5vZGVzLmEsIG5vZGVzLmIpO1xuICAgICAgICAgICAgICAgIGlmIChoYXNQYXRjaGVzKHRodW5rUGF0Y2gpKSB7XG4gICAgICAgICAgICAgICAgICAgIHBhdGNoW2luZGV4XSA9IG5ldyBWUGF0Y2goVlBhdGNoLlRIVU5LLCBudWxsLCB0aHVua1BhdGNoKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIGhhc1BhdGNoZXMocGF0Y2gpIHtcbiAgICAgICAgICAgICAgICBmb3IgKHZhciBpbmRleCBpbiBwYXRjaCkge1xuICAgICAgICAgICAgICAgICAgICBpZiAoaW5kZXggIT09IFwiYVwiKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgLy8gRXhlY3V0ZSBob29rcyB3aGVuIHR3byBub2RlcyBhcmUgaWRlbnRpY2FsXG4gICAgICAgICAgICBmdW5jdGlvbiB1bmhvb2sodk5vZGUsIHBhdGNoLCBpbmRleCkge1xuICAgICAgICAgICAgICAgIGlmIChpc1ZOb2RlKHZOb2RlKSkge1xuICAgICAgICAgICAgICAgICAgICBpZiAodk5vZGUuaG9va3MpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHBhdGNoW2luZGV4XSA9IGFwcGVuZFBhdGNoKHBhdGNoW2luZGV4XSwgbmV3IFZQYXRjaChWUGF0Y2guUFJPUFMsIHZOb2RlLCB1bmRlZmluZWRLZXlzKHZOb2RlLmhvb2tzKSkpO1xuICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgaWYgKHZOb2RlLmRlc2NlbmRhbnRIb29rcyB8fCB2Tm9kZS5oYXNUaHVua3MpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHZhciBjaGlsZHJlbiA9IHZOb2RlLmNoaWxkcmVuO1xuICAgICAgICAgICAgICAgICAgICAgICAgdmFyIGxlbiA9IGNoaWxkcmVuLmxlbmd0aDtcbiAgICAgICAgICAgICAgICAgICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgbGVuOyBpKyspIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB2YXIgY2hpbGQgPSBjaGlsZHJlbltpXTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpbmRleCArPSAxO1xuXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdW5ob29rKGNoaWxkLCBwYXRjaCwgaW5kZXgpO1xuXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGlzVk5vZGUoY2hpbGQpICYmIGNoaWxkLmNvdW50KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGluZGV4ICs9IGNoaWxkLmNvdW50O1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoaXNUaHVuayh2Tm9kZSkpIHtcbiAgICAgICAgICAgICAgICAgICAgdGh1bmtzKHZOb2RlLCBudWxsLCBwYXRjaCwgaW5kZXgpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZnVuY3Rpb24gdW5kZWZpbmVkS2V5cyhvYmopIHtcbiAgICAgICAgICAgICAgICB2YXIgcmVzdWx0ID0ge307XG5cbiAgICAgICAgICAgICAgICBmb3IgKHZhciBrZXkgaW4gb2JqKSB7XG4gICAgICAgICAgICAgICAgICAgIHJlc3VsdFtrZXldID0gdW5kZWZpbmVkO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHJldHVybiByZXN1bHQ7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIC8vIExpc3QgZGlmZiwgbmFpdmUgbGVmdCB0byByaWdodCByZW9yZGVyaW5nXG4gICAgICAgICAgICBmdW5jdGlvbiByZW9yZGVyKGFDaGlsZHJlbiwgYkNoaWxkcmVuKSB7XG4gICAgICAgICAgICAgICAgLy8gTyhNKSB0aW1lLCBPKE0pIG1lbW9yeVxuICAgICAgICAgICAgICAgIHZhciBiQ2hpbGRJbmRleCA9IGtleUluZGV4KGJDaGlsZHJlbik7XG4gICAgICAgICAgICAgICAgdmFyIGJLZXlzID0gYkNoaWxkSW5kZXgua2V5cztcbiAgICAgICAgICAgICAgICB2YXIgYkZyZWUgPSBiQ2hpbGRJbmRleC5mcmVlO1xuXG4gICAgICAgICAgICAgICAgaWYgKGJGcmVlLmxlbmd0aCA9PT0gYkNoaWxkcmVuLmxlbmd0aCkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgICAgICAgICAgICAgY2hpbGRyZW46IGJDaGlsZHJlbixcbiAgICAgICAgICAgICAgICAgICAgICAgIG1vdmVzOiBudWxsXG4gICAgICAgICAgICAgICAgICAgIH07XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgLy8gTyhOKSB0aW1lLCBPKE4pIG1lbW9yeVxuICAgICAgICAgICAgICAgIHZhciBhQ2hpbGRJbmRleCA9IGtleUluZGV4KGFDaGlsZHJlbik7XG4gICAgICAgICAgICAgICAgdmFyIGFLZXlzID0gYUNoaWxkSW5kZXgua2V5cztcbiAgICAgICAgICAgICAgICB2YXIgYUZyZWUgPSBhQ2hpbGRJbmRleC5mcmVlO1xuXG4gICAgICAgICAgICAgICAgaWYgKGFGcmVlLmxlbmd0aCA9PT0gYUNoaWxkcmVuLmxlbmd0aCkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgICAgICAgICAgICAgY2hpbGRyZW46IGJDaGlsZHJlbixcbiAgICAgICAgICAgICAgICAgICAgICAgIG1vdmVzOiBudWxsXG4gICAgICAgICAgICAgICAgICAgIH07XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgLy8gTyhNQVgoTiwgTSkpIG1lbW9yeVxuICAgICAgICAgICAgICAgIHZhciBuZXdDaGlsZHJlbiA9IFtdO1xuXG4gICAgICAgICAgICAgICAgdmFyIGZyZWVJbmRleCA9IDA7XG4gICAgICAgICAgICAgICAgdmFyIGZyZWVDb3VudCA9IGJGcmVlLmxlbmd0aDtcbiAgICAgICAgICAgICAgICB2YXIgZGVsZXRlZEl0ZW1zID0gMDtcblxuICAgICAgICAgICAgICAgIC8vIEl0ZXJhdGUgdGhyb3VnaCBhIGFuZCBtYXRjaCBhIG5vZGUgaW4gYlxuICAgICAgICAgICAgICAgIC8vIE8oTikgdGltZSxcbiAgICAgICAgICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IGFDaGlsZHJlbi5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgICAgICAgICB2YXIgYUl0ZW0gPSBhQ2hpbGRyZW5baV07XG4gICAgICAgICAgICAgICAgICAgIHZhciBpdGVtSW5kZXg7XG5cbiAgICAgICAgICAgICAgICAgICAgaWYgKGFJdGVtLmtleSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGJLZXlzLmhhc093blByb3BlcnR5KGFJdGVtLmtleSkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBNYXRjaCB1cCB0aGUgb2xkIGtleXNcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpdGVtSW5kZXggPSBiS2V5c1thSXRlbS5rZXldO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIG5ld0NoaWxkcmVuLnB1c2goYkNoaWxkcmVuW2l0ZW1JbmRleF0pO1xuICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBSZW1vdmUgb2xkIGtleWVkIGl0ZW1zXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaXRlbUluZGV4ID0gaSAtIGRlbGV0ZWRJdGVtcysrO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIG5ld0NoaWxkcmVuLnB1c2gobnVsbCk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAvLyBNYXRjaCB0aGUgaXRlbSBpbiBhIHdpdGggdGhlIG5leHQgZnJlZSBpdGVtIGluIGJcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChmcmVlSW5kZXggPCBmcmVlQ291bnQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpdGVtSW5kZXggPSBiRnJlZVtmcmVlSW5kZXgrK107XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgbmV3Q2hpbGRyZW4ucHVzaChiQ2hpbGRyZW5baXRlbUluZGV4XSk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIFRoZXJlIGFyZSBubyBmcmVlIGl0ZW1zIGluIGIgdG8gbWF0Y2ggd2l0aFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIHRoZSBmcmVlIGl0ZW1zIGluIGEsIHNvIHRoZSBleHRyYSBmcmVlIG5vZGVzXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gYXJlIGRlbGV0ZWQuXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaXRlbUluZGV4ID0gaSAtIGRlbGV0ZWRJdGVtcysrO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIG5ld0NoaWxkcmVuLnB1c2gobnVsbCk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICB2YXIgbGFzdEZyZWVJbmRleCA9IGZyZWVJbmRleCA+PSBiRnJlZS5sZW5ndGggPyBiQ2hpbGRyZW4ubGVuZ3RoIDogYkZyZWVbZnJlZUluZGV4XTtcblxuICAgICAgICAgICAgICAgIC8vIEl0ZXJhdGUgdGhyb3VnaCBiIGFuZCBhcHBlbmQgYW55IG5ldyBrZXlzXG4gICAgICAgICAgICAgICAgLy8gTyhNKSB0aW1lXG4gICAgICAgICAgICAgICAgZm9yICh2YXIgaiA9IDA7IGogPCBiQ2hpbGRyZW4ubGVuZ3RoOyBqKyspIHtcbiAgICAgICAgICAgICAgICAgICAgdmFyIG5ld0l0ZW0gPSBiQ2hpbGRyZW5bal07XG5cbiAgICAgICAgICAgICAgICAgICAgaWYgKG5ld0l0ZW0ua2V5KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoIWFLZXlzLmhhc093blByb3BlcnR5KG5ld0l0ZW0ua2V5KSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIEFkZCBhbnkgbmV3IGtleWVkIGl0ZW1zXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gV2UgYXJlIGFkZGluZyBuZXcgaXRlbXMgdG8gdGhlIGVuZCBhbmQgdGhlbiBzb3J0aW5nIHRoZW1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBpbiBwbGFjZS4gSW4gZnV0dXJlIHdlIHNob3VsZCBpbnNlcnQgbmV3IGl0ZW1zIGluIHBsYWNlLlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIG5ld0NoaWxkcmVuLnB1c2gobmV3SXRlbSk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoaiA+PSBsYXN0RnJlZUluZGV4KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAvLyBBZGQgYW55IGxlZnRvdmVyIG5vbi1rZXllZCBpdGVtc1xuICAgICAgICAgICAgICAgICAgICAgICAgbmV3Q2hpbGRyZW4ucHVzaChuZXdJdGVtKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHZhciBzaW11bGF0ZSA9IG5ld0NoaWxkcmVuLnNsaWNlKCk7XG4gICAgICAgICAgICAgICAgdmFyIHNpbXVsYXRlSW5kZXggPSAwO1xuICAgICAgICAgICAgICAgIHZhciByZW1vdmVzID0gW107XG4gICAgICAgICAgICAgICAgdmFyIGluc2VydHMgPSBbXTtcbiAgICAgICAgICAgICAgICB2YXIgc2ltdWxhdGVJdGVtO1xuXG4gICAgICAgICAgICAgICAgZm9yICh2YXIgayA9IDA7IGsgPCBiQ2hpbGRyZW4ubGVuZ3RoOykge1xuICAgICAgICAgICAgICAgICAgICB2YXIgd2FudGVkSXRlbSA9IGJDaGlsZHJlbltrXTtcbiAgICAgICAgICAgICAgICAgICAgc2ltdWxhdGVJdGVtID0gc2ltdWxhdGVbc2ltdWxhdGVJbmRleF07XG5cbiAgICAgICAgICAgICAgICAgICAgLy8gcmVtb3ZlIGl0ZW1zXG4gICAgICAgICAgICAgICAgICAgIHdoaWxlIChzaW11bGF0ZUl0ZW0gPT09IG51bGwgJiYgc2ltdWxhdGUubGVuZ3RoKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICByZW1vdmVzLnB1c2gocmVtb3ZlKHNpbXVsYXRlLCBzaW11bGF0ZUluZGV4LCBudWxsKSk7XG4gICAgICAgICAgICAgICAgICAgICAgICBzaW11bGF0ZUl0ZW0gPSBzaW11bGF0ZVtzaW11bGF0ZUluZGV4XTtcbiAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgIGlmICghc2ltdWxhdGVJdGVtIHx8IHNpbXVsYXRlSXRlbS5rZXkgIT09IHdhbnRlZEl0ZW0ua2V5KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAvLyBpZiB3ZSBuZWVkIGEga2V5IGluIHRoaXMgcG9zaXRpb24uLi5cbiAgICAgICAgICAgICAgICAgICAgICAgIGlmICh3YW50ZWRJdGVtLmtleSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChzaW11bGF0ZUl0ZW0gJiYgc2ltdWxhdGVJdGVtLmtleSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBpZiBhbiBpbnNlcnQgZG9lc24ndCBwdXQgdGhpcyBrZXkgaW4gcGxhY2UsIGl0IG5lZWRzIHRvIG1vdmVcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGJLZXlzW3NpbXVsYXRlSXRlbS5rZXldICE9PSBrICsgMSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmVtb3Zlcy5wdXNoKHJlbW92ZShzaW11bGF0ZSwgc2ltdWxhdGVJbmRleCwgc2ltdWxhdGVJdGVtLmtleSkpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc2ltdWxhdGVJdGVtID0gc2ltdWxhdGVbc2ltdWxhdGVJbmRleF07XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBpZiB0aGUgcmVtb3ZlIGRpZG4ndCBwdXQgdGhlIHdhbnRlZCBpdGVtIGluIHBsYWNlLCB3ZSBuZWVkIHRvIGluc2VydCBpdFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKCFzaW11bGF0ZUl0ZW0gfHwgc2ltdWxhdGVJdGVtLmtleSAhPT0gd2FudGVkSXRlbS5rZXkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpbnNlcnRzLnB1c2goeyBrZXk6IHdhbnRlZEl0ZW0ua2V5LCB0bzogayB9KTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIGl0ZW1zIGFyZSBtYXRjaGluZywgc28gc2tpcCBhaGVhZFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc2ltdWxhdGVJbmRleCsrO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaW5zZXJ0cy5wdXNoKHsga2V5OiB3YW50ZWRJdGVtLmtleSwgdG86IGsgfSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpbnNlcnRzLnB1c2goeyBrZXk6IHdhbnRlZEl0ZW0ua2V5LCB0bzogayB9KTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaysrO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgLy8gYSBrZXkgaW4gc2ltdWxhdGUgaGFzIG5vIG1hdGNoaW5nIHdhbnRlZCBrZXksIHJlbW92ZSBpdFxuICAgICAgICAgICAgICAgICAgICAgICAgZWxzZSBpZiAoc2ltdWxhdGVJdGVtICYmIHNpbXVsYXRlSXRlbS5rZXkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICByZW1vdmVzLnB1c2gocmVtb3ZlKHNpbXVsYXRlLCBzaW11bGF0ZUluZGV4LCBzaW11bGF0ZUl0ZW0ua2V5KSk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBzaW11bGF0ZUluZGV4Kys7XG4gICAgICAgICAgICAgICAgICAgICAgICBrKys7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAvLyByZW1vdmUgYWxsIHRoZSByZW1haW5pbmcgbm9kZXMgZnJvbSBzaW11bGF0ZVxuICAgICAgICAgICAgICAgIHdoaWxlIChzaW11bGF0ZUluZGV4IDwgc2ltdWxhdGUubGVuZ3RoKSB7XG4gICAgICAgICAgICAgICAgICAgIHNpbXVsYXRlSXRlbSA9IHNpbXVsYXRlW3NpbXVsYXRlSW5kZXhdO1xuICAgICAgICAgICAgICAgICAgICByZW1vdmVzLnB1c2gocmVtb3ZlKHNpbXVsYXRlLCBzaW11bGF0ZUluZGV4LCBzaW11bGF0ZUl0ZW0gJiYgc2ltdWxhdGVJdGVtLmtleSkpO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIC8vIElmIHRoZSBvbmx5IG1vdmVzIHdlIGhhdmUgYXJlIGRlbGV0ZXMgdGhlbiB3ZSBjYW4ganVzdFxuICAgICAgICAgICAgICAgIC8vIGxldCB0aGUgZGVsZXRlIHBhdGNoIHJlbW92ZSB0aGVzZSBpdGVtcy5cbiAgICAgICAgICAgICAgICBpZiAocmVtb3Zlcy5sZW5ndGggPT09IGRlbGV0ZWRJdGVtcyAmJiAhaW5zZXJ0cy5sZW5ndGgpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGNoaWxkcmVuOiBuZXdDaGlsZHJlbixcbiAgICAgICAgICAgICAgICAgICAgICAgIG1vdmVzOiBudWxsXG4gICAgICAgICAgICAgICAgICAgIH07XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgICAgICAgICAgY2hpbGRyZW46IG5ld0NoaWxkcmVuLFxuICAgICAgICAgICAgICAgICAgICBtb3Zlczoge1xuICAgICAgICAgICAgICAgICAgICAgICAgcmVtb3ZlczogcmVtb3ZlcyxcbiAgICAgICAgICAgICAgICAgICAgICAgIGluc2VydHM6IGluc2VydHNcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH07XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIHJlbW92ZShhcnIsIGluZGV4LCBrZXkpIHtcbiAgICAgICAgICAgICAgICBhcnIuc3BsaWNlKGluZGV4LCAxKTtcblxuICAgICAgICAgICAgICAgIHJldHVybiB7XG4gICAgICAgICAgICAgICAgICAgIGZyb206IGluZGV4LFxuICAgICAgICAgICAgICAgICAgICBrZXk6IGtleVxuICAgICAgICAgICAgICAgIH07XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIGtleUluZGV4KGNoaWxkcmVuKSB7XG4gICAgICAgICAgICAgICAgdmFyIGtleXMgPSB7fTtcbiAgICAgICAgICAgICAgICB2YXIgZnJlZSA9IFtdO1xuICAgICAgICAgICAgICAgIHZhciBsZW5ndGggPSBjaGlsZHJlbi5sZW5ndGg7XG5cbiAgICAgICAgICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IGxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciBjaGlsZCA9IGNoaWxkcmVuW2ldO1xuXG4gICAgICAgICAgICAgICAgICAgIGlmIChjaGlsZC5rZXkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGtleXNbY2hpbGQua2V5XSA9IGk7XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBmcmVlLnB1c2goaSk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgICAgICAgICBrZXlzOiBrZXlzLCAvLyBBIGhhc2ggb2Yga2V5IG5hbWUgdG8gaW5kZXhcbiAgICAgICAgICAgICAgICAgICAgZnJlZTogZnJlZSAvLyBBbiBhcnJheSBvZiB1bmtleWVkIGl0ZW0gaW5kaWNlc1xuICAgICAgICAgICAgICAgIH07XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIGFwcGVuZFBhdGNoKGFwcGx5LCBwYXRjaCkge1xuICAgICAgICAgICAgICAgIGlmIChhcHBseSkge1xuICAgICAgICAgICAgICAgICAgICBpZiAoaXNBcnJheShhcHBseSkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGFwcGx5LnB1c2gocGF0Y2gpO1xuICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgYXBwbHkgPSBbYXBwbHksIHBhdGNoXTtcbiAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBhcHBseTtcbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gcGF0Y2g7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9LCB7IFwiLi4vdm5vZGUvaGFuZGxlLXRodW5rXCI6IDI0LCBcIi4uL3Zub2RlL2lzLXRodW5rXCI6IDI1LCBcIi4uL3Zub2RlL2lzLXZub2RlXCI6IDI3LCBcIi4uL3Zub2RlL2lzLXZ0ZXh0XCI6IDI4LCBcIi4uL3Zub2RlL2lzLXdpZGdldFwiOiAyOSwgXCIuLi92bm9kZS92cGF0Y2hcIjogMzIsIFwiLi9kaWZmLXByb3BzXCI6IDM0LCBcIngtaXMtYXJyYXlcIjogMTIgfV0gfSwge30sIFs0XSkoNCk7XG59KTtcblxuY29uc3Qgc3RhcnQgPSBmdW5jdGlvbiAoZG9tUm9vdCwgcmVuZGVyRm4sIGluaXRpYWxTdGF0ZSwgb3B0aW9ucyA9IFtdKSB7XG4gIGxldCBwaWQgPSBzZWxmLnByb2Nlc3Nlcy5zcGF3bigpO1xuXG4gIGlmIChLZXl3b3JkLmhhc19rZXlfX3FtX18ob3B0aW9ucywgS2VybmVsLlNwZWNpYWxGb3Jtcy5hdG9tKCduYW1lJykpKSB7XG4gICAgcGlkID0gc2VsZi5wcm9jZXNzZXMucmVnaXN0ZXIoS2V5d29yZC5nZXQob3B0aW9ucywgS2VybmVsLlNwZWNpYWxGb3Jtcy5hdG9tKCduYW1lJykpLCBwaWQpO1xuICB9XG5cbiAgY29uc3QgdHJlZSA9IHJlbmRlckZuLmFwcGx5KHRoaXMsIGluaXRpYWxTdGF0ZSk7XG4gIGNvbnN0IHJvb3ROb2RlID0gVmlydHVhbERPTS5jcmVhdGUodHJlZSk7XG5cbiAgZG9tUm9vdC5hcHBlbmRDaGlsZChyb290Tm9kZSk7XG5cbiAgc2VsZi5wcm9jZXNzZXMucHV0KHBpZCwgJ3N0YXRlJywgS2VybmVsLlNwZWNpYWxGb3Jtcy50dXBsZShyb290Tm9kZSwgdHJlZSwgcmVuZGVyRm4pKTtcbiAgcmV0dXJuIEtlcm5lbC5TcGVjaWFsRm9ybXMudHVwbGUoS2VybmVsLlNwZWNpYWxGb3Jtcy5hdG9tKCdvaycpLCBwaWQpO1xufTtcblxuY29uc3Qgc3RvcCA9IGZ1bmN0aW9uIChhZ2VudCwgdGltZW91dCA9IDUwMDApIHtcbiAgc2VsZi5wcm9jZXNzZXMuZXhpdChhZ2VudCk7XG4gIHJldHVybiBLZXJuZWwuU3BlY2lhbEZvcm1zLmF0b20oJ29rJyk7XG59O1xuXG5jb25zdCByZW5kZXIgPSBmdW5jdGlvbiAoYWdlbnQsIHN0YXRlKSB7XG5cbiAgY29uc3QgY3VycmVudF9zdGF0ZSA9IHNlbGYucHJvY2Vzc2VzLmdldChhZ2VudCwgJ3N0YXRlJyk7XG5cbiAgbGV0IHJvb3ROb2RlID0gS2VybmVsLmVsZW0oY3VycmVudF9zdGF0ZSwgMCk7XG4gIGxldCB0cmVlID0gS2VybmVsLmVsZW0oY3VycmVudF9zdGF0ZSwgMSk7XG4gIGxldCByZW5kZXJGbiA9IEtlcm5lbC5lbGVtKGN1cnJlbnRfc3RhdGUsIDIpO1xuXG4gIGxldCBuZXdUcmVlID0gcmVuZGVyRm4uYXBwbHkodGhpcywgc3RhdGUpO1xuXG4gIGxldCBwYXRjaGVzID0gVmlydHVhbERPTS5kaWZmKHRyZWUsIG5ld1RyZWUpO1xuICByb290Tm9kZSA9IFZpcnR1YWxET00ucGF0Y2gocm9vdE5vZGUsIHBhdGNoZXMpO1xuXG4gIHNlbGYucHJvY2Vzc2VzLnB1dChhZ2VudCwgJ3N0YXRlJywgS2VybmVsLlNwZWNpYWxGb3Jtcy50dXBsZShyb290Tm9kZSwgbmV3VHJlZSwgcmVuZGVyRm4pKTtcblxuICByZXR1cm4gS2VybmVsLlNwZWNpYWxGb3Jtcy5hdG9tKCdvaycpO1xufTtcblxudmFyIHZpZXcgPSB7XG4gIHN0YXJ0LFxuICBzdG9wLFxuICByZW5kZXJcbn07XG5cbnNlbGYucHJvY2Vzc2VzID0gc2VsZi5wcm9jZXNzZXMgfHwgbmV3IFByb2Nlc3NTeXN0ZW0oKTtcblxuY29uc3QgQ29yZSA9IEM7XG5cbmV4cG9ydCB7IENvcmUsIEtlcm5lbCwgQXRvbSwgRW51bSwgSW50ZWdlciwgTGlzdCwgUmFuZ2UsIFR1cGxlLCBBZ2VudCwgS2V5d29yZCwgYmFzZSBhcyBCYXNlLCBTdHJpbmckMSBhcyBTdHJpbmcsIGJpdHdpc2UgYXMgQml0d2lzZSwgRW51bWVyYWJsZSwgQ29sbGVjdGFibGUsIEluc3BlY3QsIG1hcCBhcyBNYXAsIHNldCBhcyBTZXQsIE1hcFNldCwgVmlydHVhbERPTSwgdmlldyBhcyBWaWV3IH07Il0sImZpbGUiOiJlbGl4aXIuanMiLCJzb3VyY2VSb290IjoiL3NvdXJjZS8ifQ== \ No newline at end of file +//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiIiwic291cmNlcyI6WyJFbGl4aXIuanMiXSwic291cmNlc0NvbnRlbnQiOlsiZnVuY3Rpb24gY2FsbF9wcm9wZXJ0eShpdGVtLCBwcm9wZXJ0eSkge1xuICBpZiAocHJvcGVydHkgaW4gaXRlbSkge1xuICAgIGl0ZW1bcHJvcGVydHldO1xuICAgIGlmIChpdGVtW3Byb3BlcnR5XSBpbnN0YW5jZW9mIEZ1bmN0aW9uKSB7XG4gICAgICByZXR1cm4gaXRlbVtwcm9wZXJ0eV0oKTtcbiAgICB9IGVsc2Uge1xuICAgICAgcmV0dXJuIGl0ZW1bcHJvcGVydHldO1xuICAgIH1cbiAgfSBlbHNlIGlmIChTeW1ib2wuZm9yKHByb3BlcnR5KSBpbiBpdGVtKSB7XG4gICAgbGV0IHByb3AgPSBTeW1ib2wuZm9yKHByb3BlcnR5KTtcbiAgICBpZiAoaXRlbVtwcm9wXSBpbnN0YW5jZW9mIEZ1bmN0aW9uKSB7XG4gICAgICByZXR1cm4gaXRlbVtwcm9wXSgpO1xuICAgIH0gZWxzZSB7XG4gICAgICByZXR1cm4gaXRlbVtwcm9wXTtcbiAgICB9XG4gIH1cblxuICB0aHJvdyBuZXcgRXJyb3IoYFByb3BlcnR5ICR7IHByb3BlcnR5IH0gbm90IGZvdW5kIGluICR7IGl0ZW0gfWApO1xufVxuXG5jbGFzcyBUdXBsZSQxIHtcblxuICBjb25zdHJ1Y3RvciguLi5hcmdzKSB7XG4gICAgdGhpcy52YWx1ZXMgPSBPYmplY3QuZnJlZXplKGFyZ3MpO1xuICB9XG5cbiAgZ2V0KGluZGV4KSB7XG4gICAgcmV0dXJuIHRoaXMudmFsdWVzW2luZGV4XTtcbiAgfVxuXG4gIGNvdW50KCkge1xuICAgIHJldHVybiB0aGlzLnZhbHVlcy5sZW5ndGg7XG4gIH1cblxuICBbU3ltYm9sLml0ZXJhdG9yXSgpIHtcbiAgICByZXR1cm4gdGhpcy52YWx1ZXNbU3ltYm9sLml0ZXJhdG9yXSgpO1xuICB9XG5cbiAgdG9TdHJpbmcoKSB7XG4gICAgdmFyIGksXG4gICAgICAgIHMgPSBcIlwiO1xuICAgIGZvciAoaSA9IDA7IGkgPCB0aGlzLnZhbHVlcy5sZW5ndGg7IGkrKykge1xuICAgICAgaWYgKHMgIT09IFwiXCIpIHtcbiAgICAgICAgcyArPSBcIiwgXCI7XG4gICAgICB9XG4gICAgICBzICs9IHRoaXMudmFsdWVzW2ldLnRvU3RyaW5nKCk7XG4gICAgfVxuXG4gICAgcmV0dXJuIFwie1wiICsgcyArIFwifVwiO1xuICB9XG5cbn1cblxubGV0IHByb2Nlc3NfY291bnRlciA9IC0xO1xuXG5jbGFzcyBQSUQge1xuICBjb25zdHJ1Y3RvcigpIHtcbiAgICBwcm9jZXNzX2NvdW50ZXIgPSBwcm9jZXNzX2NvdW50ZXIgKyAxO1xuICAgIHRoaXMuaWQgPSBwcm9jZXNzX2NvdW50ZXI7XG4gIH1cblxuICB0b1N0cmluZygpIHtcbiAgICByZXR1cm4gXCJQSUQjPDAuXCIgKyB0aGlzLmlkICsgXCIuMD5cIjtcbiAgfVxufVxuXG5jbGFzcyBJbnRlZ2VyJDEge31cbmNsYXNzIEZsb2F0IHt9XG5cbi8qIEBmbG93ICovXG5cbmNsYXNzIFZhcmlhYmxlIHtcblxuICBjb25zdHJ1Y3RvcihuYW1lID0gbnVsbCkge1xuICAgIHRoaXMubmFtZSA9IG5hbWU7XG4gIH1cbn1cblxuY2xhc3MgV2lsZGNhcmQge1xuICBjb25zdHJ1Y3RvcigpIHt9XG59XG5cbmNsYXNzIFN0YXJ0c1dpdGgge1xuXG4gIGNvbnN0cnVjdG9yKHByZWZpeCkge1xuICAgIHRoaXMucHJlZml4ID0gcHJlZml4O1xuICB9XG59XG5cbmNsYXNzIENhcHR1cmUge1xuXG4gIGNvbnN0cnVjdG9yKHZhbHVlKSB7XG4gICAgdGhpcy52YWx1ZSA9IHZhbHVlO1xuICB9XG59XG5cbmNsYXNzIEhlYWRUYWlsIHtcbiAgY29uc3RydWN0b3IoKSB7fVxufVxuXG5jbGFzcyBUeXBlIHtcblxuICBjb25zdHJ1Y3Rvcih0eXBlLCBvYmpQYXR0ZXJuID0ge30pIHtcbiAgICB0aGlzLnR5cGUgPSB0eXBlO1xuICAgIHRoaXMub2JqUGF0dGVybiA9IG9ialBhdHRlcm47XG4gIH1cbn1cblxuY2xhc3MgQm91bmQge1xuXG4gIGNvbnN0cnVjdG9yKHZhbHVlKSB7XG4gICAgdGhpcy52YWx1ZSA9IHZhbHVlO1xuICB9XG59XG5cbmZ1bmN0aW9uIHZhcmlhYmxlKG5hbWUgPSBudWxsKSB7XG4gIHJldHVybiBuZXcgVmFyaWFibGUobmFtZSk7XG59XG5cbmZ1bmN0aW9uIHdpbGRjYXJkKCkge1xuICByZXR1cm4gbmV3IFdpbGRjYXJkKCk7XG59XG5cbmZ1bmN0aW9uIHN0YXJ0c1dpdGgocHJlZml4KSB7XG4gIHJldHVybiBuZXcgU3RhcnRzV2l0aChwcmVmaXgpO1xufVxuXG5mdW5jdGlvbiBjYXB0dXJlKHZhbHVlKSB7XG4gIHJldHVybiBuZXcgQ2FwdHVyZSh2YWx1ZSk7XG59XG5cbmZ1bmN0aW9uIGhlYWRUYWlsKCkge1xuICByZXR1cm4gbmV3IEhlYWRUYWlsKCk7XG59XG5cbmZ1bmN0aW9uIHR5cGUodHlwZSwgb2JqUGF0dGVybiA9IHt9KSB7XG4gIHJldHVybiBuZXcgVHlwZSh0eXBlLCBvYmpQYXR0ZXJuKTtcbn1cblxuZnVuY3Rpb24gYm91bmQodmFsdWUpIHtcbiAgcmV0dXJuIG5ldyBCb3VuZCh2YWx1ZSk7XG59XG5cbmZ1bmN0aW9uIGlzX251bWJlciQxKHZhbHVlKSB7XG4gIHJldHVybiB0eXBlb2YgdmFsdWUgPT09ICdudW1iZXInO1xufVxuXG5mdW5jdGlvbiBpc19zdHJpbmcodmFsdWUpIHtcbiAgcmV0dXJuIHR5cGVvZiB2YWx1ZSA9PT0gJ3N0cmluZyc7XG59XG5cbmZ1bmN0aW9uIGlzX2Jvb2xlYW4kMSh2YWx1ZSkge1xuICByZXR1cm4gdHlwZW9mIHZhbHVlID09PSAnYm9vbGVhbic7XG59XG5cbmZ1bmN0aW9uIGlzX3N5bWJvbCh2YWx1ZSkge1xuICByZXR1cm4gdHlwZW9mIHZhbHVlID09PSAnc3ltYm9sJztcbn1cblxuZnVuY3Rpb24gaXNfbnVsbCh2YWx1ZSkge1xuICByZXR1cm4gdmFsdWUgPT09IG51bGw7XG59XG5cbmZ1bmN0aW9uIGlzX3VuZGVmaW5lZCh2YWx1ZSkge1xuICByZXR1cm4gdHlwZW9mIHZhbHVlID09PSAndW5kZWZpbmVkJztcbn1cblxuZnVuY3Rpb24gaXNfZnVuY3Rpb24kMSh2YWx1ZSkge1xuICByZXR1cm4gT2JqZWN0LnByb3RvdHlwZS50b1N0cmluZy5jYWxsKHZhbHVlKSA9PSAnW29iamVjdCBGdW5jdGlvbl0nO1xufVxuXG5mdW5jdGlvbiBpc192YXJpYWJsZSh2YWx1ZSkge1xuICByZXR1cm4gdmFsdWUgaW5zdGFuY2VvZiBWYXJpYWJsZTtcbn1cblxuZnVuY3Rpb24gaXNfd2lsZGNhcmQodmFsdWUpIHtcbiAgcmV0dXJuIHZhbHVlIGluc3RhbmNlb2YgV2lsZGNhcmQ7XG59XG5cbmZ1bmN0aW9uIGlzX2hlYWRUYWlsKHZhbHVlKSB7XG4gIHJldHVybiB2YWx1ZSBpbnN0YW5jZW9mIEhlYWRUYWlsO1xufVxuXG5mdW5jdGlvbiBpc19jYXB0dXJlKHZhbHVlKSB7XG4gIHJldHVybiB2YWx1ZSBpbnN0YW5jZW9mIENhcHR1cmU7XG59XG5cbmZ1bmN0aW9uIGlzX3R5cGUodmFsdWUpIHtcbiAgcmV0dXJuIHZhbHVlIGluc3RhbmNlb2YgVHlwZTtcbn1cblxuZnVuY3Rpb24gaXNfc3RhcnRzV2l0aCh2YWx1ZSkge1xuICByZXR1cm4gdmFsdWUgaW5zdGFuY2VvZiBTdGFydHNXaXRoO1xufVxuXG5mdW5jdGlvbiBpc19ib3VuZCh2YWx1ZSkge1xuICByZXR1cm4gdmFsdWUgaW5zdGFuY2VvZiBCb3VuZDtcbn1cblxuZnVuY3Rpb24gaXNfb2JqZWN0KHZhbHVlKSB7XG4gIHJldHVybiB0eXBlb2YgdmFsdWUgPT09ICdvYmplY3QnO1xufVxuXG5mdW5jdGlvbiBpc19hcnJheSh2YWx1ZSkge1xuICByZXR1cm4gQXJyYXkuaXNBcnJheSh2YWx1ZSk7XG59XG5cbnZhciBDaGVja3MgPSB7XG4gIGlzX251bWJlcjogaXNfbnVtYmVyJDEsXG4gIGlzX3N0cmluZyxcbiAgaXNfYm9vbGVhbjogaXNfYm9vbGVhbiQxLFxuICBpc19zeW1ib2wsXG4gIGlzX251bGwsXG4gIGlzX3VuZGVmaW5lZCxcbiAgaXNfZnVuY3Rpb246IGlzX2Z1bmN0aW9uJDEsXG4gIGlzX3ZhcmlhYmxlLFxuICBpc193aWxkY2FyZCxcbiAgaXNfaGVhZFRhaWwsXG4gIGlzX2NhcHR1cmUsXG4gIGlzX3R5cGUsXG4gIGlzX3N0YXJ0c1dpdGgsXG4gIGlzX2JvdW5kLFxuICBpc19vYmplY3QsXG4gIGlzX2FycmF5XG59O1xuXG5mdW5jdGlvbiByZXNvbHZlU3ltYm9sKHBhdHRlcm4pIHtcbiAgcmV0dXJuIGZ1bmN0aW9uICh2YWx1ZSkge1xuICAgIHJldHVybiBDaGVja3MuaXNfc3ltYm9sKHZhbHVlKSAmJiB2YWx1ZSA9PT0gcGF0dGVybjtcbiAgfTtcbn1cblxuZnVuY3Rpb24gcmVzb2x2ZVN0cmluZyhwYXR0ZXJuKSB7XG4gIHJldHVybiBmdW5jdGlvbiAodmFsdWUpIHtcbiAgICByZXR1cm4gQ2hlY2tzLmlzX3N0cmluZyh2YWx1ZSkgJiYgdmFsdWUgPT09IHBhdHRlcm47XG4gIH07XG59XG5cbmZ1bmN0aW9uIHJlc29sdmVOdW1iZXIocGF0dGVybikge1xuICByZXR1cm4gZnVuY3Rpb24gKHZhbHVlKSB7XG4gICAgcmV0dXJuIENoZWNrcy5pc19udW1iZXIodmFsdWUpICYmIHZhbHVlID09PSBwYXR0ZXJuO1xuICB9O1xufVxuXG5mdW5jdGlvbiByZXNvbHZlQm9vbGVhbihwYXR0ZXJuKSB7XG4gIHJldHVybiBmdW5jdGlvbiAodmFsdWUpIHtcbiAgICByZXR1cm4gQ2hlY2tzLmlzX2Jvb2xlYW4odmFsdWUpICYmIHZhbHVlID09PSBwYXR0ZXJuO1xuICB9O1xufVxuXG5mdW5jdGlvbiByZXNvbHZlRnVuY3Rpb24ocGF0dGVybikge1xuICByZXR1cm4gZnVuY3Rpb24gKHZhbHVlKSB7XG4gICAgcmV0dXJuIENoZWNrcy5pc19mdW5jdGlvbih2YWx1ZSkgJiYgdmFsdWUgPT09IHBhdHRlcm47XG4gIH07XG59XG5cbmZ1bmN0aW9uIHJlc29sdmVOdWxsKHBhdHRlcm4pIHtcbiAgcmV0dXJuIGZ1bmN0aW9uICh2YWx1ZSkge1xuICAgIHJldHVybiBDaGVja3MuaXNfbnVsbCh2YWx1ZSk7XG4gIH07XG59XG5cbmZ1bmN0aW9uIHJlc29sdmVCb3VuZChwYXR0ZXJuKSB7XG4gIHJldHVybiBmdW5jdGlvbiAodmFsdWUsIGFyZ3MpIHtcbiAgICBpZiAodHlwZW9mIHZhbHVlID09PSB0eXBlb2YgcGF0dGVybi52YWx1ZSAmJiB2YWx1ZSA9PT0gcGF0dGVybi52YWx1ZSkge1xuICAgICAgYXJncy5wdXNoKHZhbHVlKTtcbiAgICAgIHJldHVybiB0cnVlO1xuICAgIH1cblxuICAgIHJldHVybiBmYWxzZTtcbiAgfTtcbn1cblxuZnVuY3Rpb24gcmVzb2x2ZVdpbGRjYXJkKCkge1xuICByZXR1cm4gZnVuY3Rpb24gKCkge1xuICAgIHJldHVybiB0cnVlO1xuICB9O1xufVxuXG5mdW5jdGlvbiByZXNvbHZlVmFyaWFibGUoKSB7XG4gIHJldHVybiBmdW5jdGlvbiAodmFsdWUsIGFyZ3MpIHtcbiAgICBhcmdzLnB1c2godmFsdWUpO1xuICAgIHJldHVybiB0cnVlO1xuICB9O1xufVxuXG5mdW5jdGlvbiByZXNvbHZlSGVhZFRhaWwoKSB7XG4gIHJldHVybiBmdW5jdGlvbiAodmFsdWUsIGFyZ3MpIHtcbiAgICBpZiAoIUNoZWNrcy5pc19hcnJheSh2YWx1ZSkgfHwgdmFsdWUubGVuZ3RoIDwgMikge1xuICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH1cblxuICAgIGNvbnN0IGhlYWQgPSB2YWx1ZVswXTtcbiAgICBjb25zdCB0YWlsID0gdmFsdWUuc2xpY2UoMSk7XG5cbiAgICBhcmdzLnB1c2goaGVhZCk7XG4gICAgYXJncy5wdXNoKHRhaWwpO1xuXG4gICAgcmV0dXJuIHRydWU7XG4gIH07XG59XG5cbmZ1bmN0aW9uIHJlc29sdmVDYXB0dXJlKHBhdHRlcm4pIHtcbiAgY29uc3QgbWF0Y2hlcyA9IGJ1aWxkTWF0Y2gocGF0dGVybi52YWx1ZSk7XG5cbiAgcmV0dXJuIGZ1bmN0aW9uICh2YWx1ZSwgYXJncykge1xuICAgIGlmIChtYXRjaGVzKHZhbHVlLCBhcmdzKSkge1xuICAgICAgYXJncy5wdXNoKHZhbHVlKTtcbiAgICAgIHJldHVybiB0cnVlO1xuICAgIH1cblxuICAgIHJldHVybiBmYWxzZTtcbiAgfTtcbn1cblxuZnVuY3Rpb24gcmVzb2x2ZVN0YXJ0c1dpdGgocGF0dGVybikge1xuICBjb25zdCBwcmVmaXggPSBwYXR0ZXJuLnByZWZpeDtcblxuICByZXR1cm4gZnVuY3Rpb24gKHZhbHVlLCBhcmdzKSB7XG4gICAgaWYgKENoZWNrcy5pc19zdHJpbmcodmFsdWUpICYmIHZhbHVlLnN0YXJ0c1dpdGgocHJlZml4KSkge1xuICAgICAgYXJncy5wdXNoKHZhbHVlLnN1YnN0cmluZyhwcmVmaXgubGVuZ3RoKSk7XG4gICAgICByZXR1cm4gdHJ1ZTtcbiAgICB9XG5cbiAgICByZXR1cm4gZmFsc2U7XG4gIH07XG59XG5cbmZ1bmN0aW9uIHJlc29sdmVUeXBlKHBhdHRlcm4pIHtcbiAgcmV0dXJuIGZ1bmN0aW9uICh2YWx1ZSwgYXJncykge1xuICAgIGlmICh2YWx1ZSBpbnN0YW5jZW9mIHBhdHRlcm4udHlwZSkge1xuICAgICAgY29uc3QgbWF0Y2hlcyA9IGJ1aWxkTWF0Y2gocGF0dGVybi5vYmpQYXR0ZXJuKTtcbiAgICAgIHJldHVybiBtYXRjaGVzKHZhbHVlLCBhcmdzKSAmJiBhcmdzLnB1c2godmFsdWUpID4gMDtcbiAgICB9XG5cbiAgICByZXR1cm4gZmFsc2U7XG4gIH07XG59XG5cbmZ1bmN0aW9uIHJlc29sdmVBcnJheShwYXR0ZXJuKSB7XG4gIGNvbnN0IG1hdGNoZXMgPSBwYXR0ZXJuLm1hcCh4ID0+IGJ1aWxkTWF0Y2goeCkpO1xuXG4gIHJldHVybiBmdW5jdGlvbiAodmFsdWUsIGFyZ3MpIHtcbiAgICBpZiAoIUNoZWNrcy5pc19hcnJheSh2YWx1ZSkgfHwgdmFsdWUubGVuZ3RoICE9IHBhdHRlcm4ubGVuZ3RoKSB7XG4gICAgICByZXR1cm4gZmFsc2U7XG4gICAgfVxuXG4gICAgcmV0dXJuIHZhbHVlLmV2ZXJ5KGZ1bmN0aW9uICh2LCBpKSB7XG4gICAgICByZXR1cm4gbWF0Y2hlc1tpXSh2YWx1ZVtpXSwgYXJncyk7XG4gICAgfSk7XG4gIH07XG59XG5cbmZ1bmN0aW9uIHJlc29sdmVPYmplY3QocGF0dGVybikge1xuICBsZXQgbWF0Y2hlcyA9IHt9O1xuXG4gIGZvciAobGV0IGtleSBvZiBPYmplY3Qua2V5cyhwYXR0ZXJuKSkge1xuICAgIG1hdGNoZXNba2V5XSA9IGJ1aWxkTWF0Y2gocGF0dGVybltrZXldKTtcbiAgfVxuXG4gIHJldHVybiBmdW5jdGlvbiAodmFsdWUsIGFyZ3MpIHtcbiAgICBpZiAoIUNoZWNrcy5pc19vYmplY3QodmFsdWUpIHx8IHBhdHRlcm4ubGVuZ3RoID4gdmFsdWUubGVuZ3RoKSB7XG4gICAgICByZXR1cm4gZmFsc2U7XG4gICAgfVxuXG4gICAgZm9yIChsZXQga2V5IG9mIE9iamVjdC5rZXlzKHBhdHRlcm4pKSB7XG4gICAgICBpZiAoIShrZXkgaW4gdmFsdWUpIHx8ICFtYXRjaGVzW2tleV0odmFsdWVba2V5XSwgYXJncykpIHtcbiAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgfVxuICAgIH1cblxuICAgIHJldHVybiB0cnVlO1xuICB9O1xufVxuXG5mdW5jdGlvbiByZXNvbHZlTm9NYXRjaCgpIHtcbiAgcmV0dXJuIGZ1bmN0aW9uICgpIHtcbiAgICByZXR1cm4gZmFsc2U7XG4gIH07XG59XG5cbnZhciBSZXNvbHZlcnMgPSB7XG4gIHJlc29sdmVCb3VuZCxcbiAgcmVzb2x2ZVdpbGRjYXJkLFxuICByZXNvbHZlVmFyaWFibGUsXG4gIHJlc29sdmVIZWFkVGFpbCxcbiAgcmVzb2x2ZUNhcHR1cmUsXG4gIHJlc29sdmVTdGFydHNXaXRoLFxuICByZXNvbHZlVHlwZSxcbiAgcmVzb2x2ZUFycmF5LFxuICByZXNvbHZlT2JqZWN0LFxuICByZXNvbHZlTm9NYXRjaCxcbiAgcmVzb2x2ZVN5bWJvbCxcbiAgcmVzb2x2ZVN0cmluZyxcbiAgcmVzb2x2ZU51bWJlcixcbiAgcmVzb2x2ZUJvb2xlYW4sXG4gIHJlc29sdmVGdW5jdGlvbixcbiAgcmVzb2x2ZU51bGxcbn07XG5cbmZ1bmN0aW9uIGJ1aWxkTWF0Y2gocGF0dGVybikge1xuXG4gIGlmIChDaGVja3MuaXNfdmFyaWFibGUocGF0dGVybikpIHtcbiAgICByZXR1cm4gUmVzb2x2ZXJzLnJlc29sdmVWYXJpYWJsZShwYXR0ZXJuKTtcbiAgfVxuXG4gIGlmIChDaGVja3MuaXNfd2lsZGNhcmQocGF0dGVybikpIHtcbiAgICByZXR1cm4gUmVzb2x2ZXJzLnJlc29sdmVXaWxkY2FyZChwYXR0ZXJuKTtcbiAgfVxuXG4gIGlmIChDaGVja3MuaXNfdW5kZWZpbmVkKHBhdHRlcm4pKSB7XG4gICAgcmV0dXJuIFJlc29sdmVycy5yZXNvbHZlV2lsZGNhcmQocGF0dGVybik7XG4gIH1cblxuICBpZiAoQ2hlY2tzLmlzX2hlYWRUYWlsKHBhdHRlcm4pKSB7XG4gICAgcmV0dXJuIFJlc29sdmVycy5yZXNvbHZlSGVhZFRhaWwocGF0dGVybik7XG4gIH1cblxuICBpZiAoQ2hlY2tzLmlzX3N0YXJ0c1dpdGgocGF0dGVybikpIHtcbiAgICByZXR1cm4gUmVzb2x2ZXJzLnJlc29sdmVTdGFydHNXaXRoKHBhdHRlcm4pO1xuICB9XG5cbiAgaWYgKENoZWNrcy5pc19jYXB0dXJlKHBhdHRlcm4pKSB7XG4gICAgcmV0dXJuIFJlc29sdmVycy5yZXNvbHZlQ2FwdHVyZShwYXR0ZXJuKTtcbiAgfVxuXG4gIGlmIChDaGVja3MuaXNfYm91bmQocGF0dGVybikpIHtcbiAgICByZXR1cm4gUmVzb2x2ZXJzLnJlc29sdmVCb3VuZChwYXR0ZXJuKTtcbiAgfVxuXG4gIGlmIChDaGVja3MuaXNfdHlwZShwYXR0ZXJuKSkge1xuICAgIHJldHVybiBSZXNvbHZlcnMucmVzb2x2ZVR5cGUocGF0dGVybik7XG4gIH1cblxuICBpZiAoQ2hlY2tzLmlzX2FycmF5KHBhdHRlcm4pKSB7XG4gICAgcmV0dXJuIFJlc29sdmVycy5yZXNvbHZlQXJyYXkocGF0dGVybik7XG4gIH1cblxuICBpZiAoQ2hlY2tzLmlzX251bWJlcihwYXR0ZXJuKSkge1xuICAgIHJldHVybiBSZXNvbHZlcnMucmVzb2x2ZU51bWJlcihwYXR0ZXJuKTtcbiAgfVxuXG4gIGlmIChDaGVja3MuaXNfc3RyaW5nKHBhdHRlcm4pKSB7XG4gICAgcmV0dXJuIFJlc29sdmVycy5yZXNvbHZlU3RyaW5nKHBhdHRlcm4pO1xuICB9XG5cbiAgaWYgKENoZWNrcy5pc19ib29sZWFuKHBhdHRlcm4pKSB7XG4gICAgcmV0dXJuIFJlc29sdmVycy5yZXNvbHZlQm9vbGVhbihwYXR0ZXJuKTtcbiAgfVxuXG4gIGlmIChDaGVja3MuaXNfc3ltYm9sKHBhdHRlcm4pKSB7XG4gICAgcmV0dXJuIFJlc29sdmVycy5yZXNvbHZlU3ltYm9sKHBhdHRlcm4pO1xuICB9XG5cbiAgaWYgKENoZWNrcy5pc19udWxsKHBhdHRlcm4pKSB7XG4gICAgcmV0dXJuIFJlc29sdmVycy5yZXNvbHZlTnVsbChwYXR0ZXJuKTtcbiAgfVxuXG4gIGlmIChDaGVja3MuaXNfb2JqZWN0KHBhdHRlcm4pKSB7XG4gICAgcmV0dXJuIFJlc29sdmVycy5yZXNvbHZlT2JqZWN0KHBhdHRlcm4pO1xuICB9XG5cbiAgcmV0dXJuIFJlc29sdmVycy5yZXNvbHZlTm9NYXRjaCgpO1xufVxuXG5jbGFzcyBNYXRjaEVycm9yIGV4dGVuZHMgRXJyb3Ige1xuICBjb25zdHJ1Y3RvcihhcmcpIHtcbiAgICBzdXBlcigpO1xuXG4gICAgaWYgKHR5cGVvZiBhcmcgPT09ICdzeW1ib2wnKSB7XG4gICAgICB0aGlzLm1lc3NhZ2UgPSAnTm8gbWF0Y2ggZm9yOiAnICsgYXJnLnRvU3RyaW5nKCk7XG4gICAgfSBlbHNlIGlmIChBcnJheS5pc0FycmF5KGFyZykpIHtcbiAgICAgIGxldCBtYXBwZWRWYWx1ZXMgPSBhcmcubWFwKHggPT4geC50b1N0cmluZygpKTtcbiAgICAgIHRoaXMubWVzc2FnZSA9ICdObyBtYXRjaCBmb3I6ICcgKyBtYXBwZWRWYWx1ZXM7XG4gICAgfSBlbHNlIHtcbiAgICAgIHRoaXMubWVzc2FnZSA9ICdObyBtYXRjaCBmb3I6ICcgKyBhcmc7XG4gICAgfVxuXG4gICAgdGhpcy5zdGFjayA9IG5ldyBFcnJvcigpLnN0YWNrO1xuICAgIHRoaXMubmFtZSA9IHRoaXMuY29uc3RydWN0b3IubmFtZTtcbiAgfVxufVxuXG5jbGFzcyBDYXNlIHtcblxuICBjb25zdHJ1Y3RvcihwYXR0ZXJuLCBmbiwgZ3VhcmQgPSAoKSA9PiB0cnVlKSB7XG4gICAgdGhpcy5wYXR0ZXJuID0gYnVpbGRNYXRjaChwYXR0ZXJuKTtcbiAgICB0aGlzLmZuID0gZm47XG4gICAgdGhpcy5ndWFyZCA9IGd1YXJkO1xuICB9XG59XG5cbmZ1bmN0aW9uIG1ha2VfY2FzZShwYXR0ZXJuLCBmbiwgZ3VhcmQgPSAoKSA9PiB0cnVlKSB7XG4gIHJldHVybiBuZXcgQ2FzZShwYXR0ZXJuLCBmbiwgZ3VhcmQpO1xufVxuXG5mdW5jdGlvbiBkZWZtYXRjaCguLi5jYXNlcykge1xuICByZXR1cm4gZnVuY3Rpb24gKC4uLmFyZ3MpIHtcbiAgICBmb3IgKGxldCBwcm9jZXNzZWRDYXNlIG9mIGNhc2VzKSB7XG4gICAgICBsZXQgcmVzdWx0ID0gW107XG4gICAgICBpZiAocHJvY2Vzc2VkQ2FzZS5wYXR0ZXJuKGFyZ3MsIHJlc3VsdCkgJiYgcHJvY2Vzc2VkQ2FzZS5ndWFyZC5hcHBseSh0aGlzLCByZXN1bHQpKSB7XG4gICAgICAgIHJldHVybiBwcm9jZXNzZWRDYXNlLmZuLmFwcGx5KHRoaXMsIHJlc3VsdCk7XG4gICAgICB9XG4gICAgfVxuXG4gICAgdGhyb3cgbmV3IE1hdGNoRXJyb3IoYXJncyk7XG4gIH07XG59XG5cbmZ1bmN0aW9uIG1hdGNoKHBhdHRlcm4sIGV4cHIsIGd1YXJkID0gKCkgPT4gdHJ1ZSkge1xuICBsZXQgcmVzdWx0ID0gW107XG4gIGxldCBwcm9jZXNzZWRQYXR0ZXJuID0gYnVpbGRNYXRjaChwYXR0ZXJuKTtcbiAgaWYgKHByb2Nlc3NlZFBhdHRlcm4oZXhwciwgcmVzdWx0KSAmJiBndWFyZC5hcHBseSh0aGlzLCByZXN1bHQpKSB7XG4gICAgcmV0dXJuIHJlc3VsdDtcbiAgfSBlbHNlIHtcbiAgICB0aHJvdyBuZXcgTWF0Y2hFcnJvcihleHByKTtcbiAgfVxufVxuXG5mdW5jdGlvbiBtYXRjaF9ub190aHJvdyhwYXR0ZXJuLCBleHByLCBndWFyZCA9ICgpID0+IHRydWUpIHtcbiAgdHJ5IHtcbiAgICByZXR1cm4gbWF0Y2gocGF0dGVybiwgZXhwciwgZ3VhcmQpO1xuICB9IGNhdGNoIChlKSB7XG4gICAgaWYgKGUgaW5zdGFuY2VvZiBNYXRjaEVycm9yKSB7XG4gICAgICByZXR1cm4gbnVsbDtcbiAgICB9XG5cbiAgICB0aHJvdyBlO1xuICB9XG59XG5cbnZhciBQYXR0ZXJucyA9IHtcbiAgZGVmbWF0Y2gsIG1hdGNoLCBNYXRjaEVycm9yLCBtYXRjaF9ub190aHJvdyxcbiAgdmFyaWFibGUsIHdpbGRjYXJkLCBzdGFydHNXaXRoLFxuICBjYXB0dXJlLCBoZWFkVGFpbCwgdHlwZSwgYm91bmQsIENhc2UsIG1ha2VfY2FzZVxufTtcblxuY2xhc3MgQml0U3RyaW5nIHtcbiAgY29uc3RydWN0b3IoLi4uYXJncykge1xuICAgIHRoaXMucmF3X3ZhbHVlID0gZnVuY3Rpb24gKCkge1xuICAgICAgcmV0dXJuIE9iamVjdC5mcmVlemUoYXJncyk7XG4gICAgfTtcblxuICAgIHRoaXMudmFsdWUgPSBPYmplY3QuZnJlZXplKHRoaXMucHJvY2VzcyhhcmdzKSk7XG4gIH1cblxuICBnZXQoaW5kZXgpIHtcbiAgICByZXR1cm4gdGhpcy52YWx1ZVtpbmRleF07XG4gIH1cblxuICBjb3VudCgpIHtcbiAgICByZXR1cm4gdGhpcy52YWx1ZS5sZW5ndGg7XG4gIH1cblxuICBbU3ltYm9sLml0ZXJhdG9yXSgpIHtcbiAgICByZXR1cm4gdGhpcy52YWx1ZVtTeW1ib2wuaXRlcmF0b3JdKCk7XG4gIH1cblxuICB0b1N0cmluZygpIHtcbiAgICB2YXIgaSxcbiAgICAgICAgcyA9IFwiXCI7XG4gICAgZm9yIChpID0gMDsgaSA8IHRoaXMuY291bnQoKTsgaSsrKSB7XG4gICAgICBpZiAocyAhPT0gXCJcIikge1xuICAgICAgICBzICs9IFwiLCBcIjtcbiAgICAgIH1cbiAgICAgIHMgKz0gdGhpc1tpXS50b1N0cmluZygpO1xuICAgIH1cblxuICAgIHJldHVybiBcIjw8XCIgKyBzICsgXCI+PlwiO1xuICB9XG5cbiAgcHJvY2VzcygpIHtcbiAgICBsZXQgcHJvY2Vzc2VkX3ZhbHVlcyA9IFtdO1xuXG4gICAgdmFyIGk7XG4gICAgZm9yIChpID0gMDsgaSA8IHRoaXMucmF3X3ZhbHVlKCkubGVuZ3RoOyBpKyspIHtcbiAgICAgIGxldCBwcm9jZXNzZWRfdmFsdWUgPSB0aGlzW1wicHJvY2Vzc19cIiArIHRoaXMucmF3X3ZhbHVlKClbaV0udHlwZV0odGhpcy5yYXdfdmFsdWUoKVtpXSk7XG5cbiAgICAgIGZvciAobGV0IGF0dHIgb2YgdGhpcy5yYXdfdmFsdWUoKVtpXS5hdHRyaWJ1dGVzKSB7XG4gICAgICAgIHByb2Nlc3NlZF92YWx1ZSA9IHRoaXNbXCJwcm9jZXNzX1wiICsgYXR0cl0ocHJvY2Vzc2VkX3ZhbHVlKTtcbiAgICAgIH1cblxuICAgICAgcHJvY2Vzc2VkX3ZhbHVlcyA9IHByb2Nlc3NlZF92YWx1ZXMuY29uY2F0KHByb2Nlc3NlZF92YWx1ZSk7XG4gICAgfVxuXG4gICAgcmV0dXJuIHByb2Nlc3NlZF92YWx1ZXM7XG4gIH1cblxuICBwcm9jZXNzX2ludGVnZXIodmFsdWUpIHtcbiAgICByZXR1cm4gdmFsdWUudmFsdWU7XG4gIH1cblxuICBwcm9jZXNzX2Zsb2F0KHZhbHVlKSB7XG4gICAgaWYgKHZhbHVlLnNpemUgPT09IDY0KSB7XG4gICAgICByZXR1cm4gQml0U3RyaW5nLmZsb2F0NjRUb0J5dGVzKHZhbHVlLnZhbHVlKTtcbiAgICB9IGVsc2UgaWYgKHZhbHVlLnNpemUgPT09IDMyKSB7XG4gICAgICByZXR1cm4gQml0U3RyaW5nLmZsb2F0MzJUb0J5dGVzKHZhbHVlLnZhbHVlKTtcbiAgICB9XG5cbiAgICB0aHJvdyBuZXcgRXJyb3IoXCJJbnZhbGlkIHNpemUgZm9yIGZsb2F0XCIpO1xuICB9XG5cbiAgcHJvY2Vzc19iaXRzdHJpbmcodmFsdWUpIHtcbiAgICByZXR1cm4gdmFsdWUudmFsdWUudmFsdWU7XG4gIH1cblxuICBwcm9jZXNzX2JpbmFyeSh2YWx1ZSkge1xuICAgIHJldHVybiBCaXRTdHJpbmcudG9VVEY4QXJyYXkodmFsdWUudmFsdWUpO1xuICB9XG5cbiAgcHJvY2Vzc191dGY4KHZhbHVlKSB7XG4gICAgcmV0dXJuIEJpdFN0cmluZy50b1VURjhBcnJheSh2YWx1ZS52YWx1ZSk7XG4gIH1cblxuICBwcm9jZXNzX3V0ZjE2KHZhbHVlKSB7XG4gICAgcmV0dXJuIEJpdFN0cmluZy50b1VURjE2QXJyYXkodmFsdWUudmFsdWUpO1xuICB9XG5cbiAgcHJvY2Vzc191dGYzMih2YWx1ZSkge1xuICAgIHJldHVybiBCaXRTdHJpbmcudG9VVEYzMkFycmF5KHZhbHVlLnZhbHVlKTtcbiAgfVxuXG4gIHByb2Nlc3Nfc2lnbmVkKHZhbHVlKSB7XG4gICAgcmV0dXJuIG5ldyBVaW50OEFycmF5KFt2YWx1ZV0pWzBdO1xuICB9XG5cbiAgcHJvY2Vzc191bnNpZ25lZCh2YWx1ZSkge1xuICAgIHJldHVybiB2YWx1ZTtcbiAgfVxuXG4gIHByb2Nlc3NfbmF0aXZlKHZhbHVlKSB7XG4gICAgcmV0dXJuIHZhbHVlO1xuICB9XG5cbiAgcHJvY2Vzc19iaWcodmFsdWUpIHtcbiAgICByZXR1cm4gdmFsdWU7XG4gIH1cblxuICBwcm9jZXNzX2xpdHRsZSh2YWx1ZSkge1xuICAgIHJldHVybiB2YWx1ZS5yZXZlcnNlKCk7XG4gIH1cblxuICBwcm9jZXNzX3NpemUodmFsdWUpIHtcbiAgICByZXR1cm4gdmFsdWU7XG4gIH1cblxuICBwcm9jZXNzX3VuaXQodmFsdWUpIHtcbiAgICByZXR1cm4gdmFsdWU7XG4gIH1cblxuICBzdGF0aWMgaW50ZWdlcih2YWx1ZSkge1xuICAgIHJldHVybiBCaXRTdHJpbmcud3JhcCh2YWx1ZSwgeyBcInR5cGVcIjogXCJpbnRlZ2VyXCIsIFwidW5pdFwiOiAxLCBcInNpemVcIjogOCB9KTtcbiAgfVxuXG4gIHN0YXRpYyBmbG9hdCh2YWx1ZSkge1xuICAgIHJldHVybiBCaXRTdHJpbmcud3JhcCh2YWx1ZSwgeyBcInR5cGVcIjogXCJmbG9hdFwiLCBcInVuaXRcIjogMSwgXCJzaXplXCI6IDY0IH0pO1xuICB9XG5cbiAgc3RhdGljIGJpdHN0cmluZyh2YWx1ZSkge1xuICAgIHJldHVybiBCaXRTdHJpbmcud3JhcCh2YWx1ZSwgeyBcInR5cGVcIjogXCJiaXRzdHJpbmdcIiwgXCJ1bml0XCI6IDEsIFwic2l6ZVwiOiB2YWx1ZS5sZW5ndGggfSk7XG4gIH1cblxuICBzdGF0aWMgYml0cyh2YWx1ZSkge1xuICAgIHJldHVybiBCaXRTdHJpbmcuYml0c3RyaW5nKHZhbHVlKTtcbiAgfVxuXG4gIHN0YXRpYyBiaW5hcnkodmFsdWUpIHtcbiAgICByZXR1cm4gQml0U3RyaW5nLndyYXAodmFsdWUsIHsgXCJ0eXBlXCI6IFwiYmluYXJ5XCIsIFwidW5pdFwiOiA4LCBcInNpemVcIjogdmFsdWUubGVuZ3RoIH0pO1xuICB9XG5cbiAgc3RhdGljIGJ5dGVzKHZhbHVlKSB7XG4gICAgcmV0dXJuIEJpdFN0cmluZy5iaW5hcnkodmFsdWUpO1xuICB9XG5cbiAgc3RhdGljIHV0ZjgodmFsdWUpIHtcbiAgICByZXR1cm4gQml0U3RyaW5nLndyYXAodmFsdWUsIHsgXCJ0eXBlXCI6IFwidXRmOFwiIH0pO1xuICB9XG5cbiAgc3RhdGljIHV0ZjE2KHZhbHVlKSB7XG4gICAgcmV0dXJuIEJpdFN0cmluZy53cmFwKHZhbHVlLCB7IFwidHlwZVwiOiBcInV0ZjE2XCIgfSk7XG4gIH1cblxuICBzdGF0aWMgdXRmMzIodmFsdWUpIHtcbiAgICByZXR1cm4gQml0U3RyaW5nLndyYXAodmFsdWUsIHsgXCJ0eXBlXCI6IFwidXRmMzJcIiB9KTtcbiAgfVxuXG4gIHN0YXRpYyBzaWduZWQodmFsdWUpIHtcbiAgICByZXR1cm4gQml0U3RyaW5nLndyYXAodmFsdWUsIHt9LCBcInNpZ25lZFwiKTtcbiAgfVxuXG4gIHN0YXRpYyB1bnNpZ25lZCh2YWx1ZSkge1xuICAgIHJldHVybiBCaXRTdHJpbmcud3JhcCh2YWx1ZSwge30sIFwidW5zaWduZWRcIik7XG4gIH1cblxuICBzdGF0aWMgbmF0aXZlKHZhbHVlKSB7XG4gICAgcmV0dXJuIEJpdFN0cmluZy53cmFwKHZhbHVlLCB7fSwgXCJuYXRpdmVcIik7XG4gIH1cblxuICBzdGF0aWMgYmlnKHZhbHVlKSB7XG4gICAgcmV0dXJuIEJpdFN0cmluZy53cmFwKHZhbHVlLCB7fSwgXCJiaWdcIik7XG4gIH1cblxuICBzdGF0aWMgbGl0dGxlKHZhbHVlKSB7XG4gICAgcmV0dXJuIEJpdFN0cmluZy53cmFwKHZhbHVlLCB7fSwgXCJsaXR0bGVcIik7XG4gIH1cblxuICBzdGF0aWMgc2l6ZSh2YWx1ZSwgY291bnQpIHtcbiAgICByZXR1cm4gQml0U3RyaW5nLndyYXAodmFsdWUsIHsgXCJzaXplXCI6IGNvdW50IH0pO1xuICB9XG5cbiAgc3RhdGljIHVuaXQodmFsdWUsIGNvdW50KSB7XG4gICAgcmV0dXJuIEJpdFN0cmluZy53cmFwKHZhbHVlLCB7IFwidW5pdFwiOiBjb3VudCB9KTtcbiAgfVxuXG4gIHN0YXRpYyB3cmFwKHZhbHVlLCBvcHQsIG5ld19hdHRyaWJ1dGUgPSBudWxsKSB7XG4gICAgbGV0IHRoZV92YWx1ZSA9IHZhbHVlO1xuXG4gICAgaWYgKCEodmFsdWUgaW5zdGFuY2VvZiBPYmplY3QpKSB7XG4gICAgICB0aGVfdmFsdWUgPSB7IFwidmFsdWVcIjogdmFsdWUsIFwiYXR0cmlidXRlc1wiOiBbXSB9O1xuICAgIH1cblxuICAgIHRoZV92YWx1ZSA9IE9iamVjdC5hc3NpZ24odGhlX3ZhbHVlLCBvcHQpO1xuXG4gICAgaWYgKG5ld19hdHRyaWJ1dGUpIHtcbiAgICAgIHRoZV92YWx1ZS5hdHRyaWJ1dGVzLnB1c2gobmV3X2F0dHJpYnV0ZSk7XG4gICAgfVxuXG4gICAgcmV0dXJuIHRoZV92YWx1ZTtcbiAgfVxuXG4gIHN0YXRpYyB0b1VURjhBcnJheShzdHIpIHtcbiAgICB2YXIgdXRmOCA9IFtdO1xuICAgIGZvciAodmFyIGkgPSAwOyBpIDwgc3RyLmxlbmd0aDsgaSsrKSB7XG4gICAgICB2YXIgY2hhcmNvZGUgPSBzdHIuY2hhckNvZGVBdChpKTtcbiAgICAgIGlmIChjaGFyY29kZSA8IDEyOCkge1xuICAgICAgICB1dGY4LnB1c2goY2hhcmNvZGUpO1xuICAgICAgfSBlbHNlIGlmIChjaGFyY29kZSA8IDIwNDgpIHtcbiAgICAgICAgdXRmOC5wdXNoKDE5MiB8IGNoYXJjb2RlID4+IDYsIDEyOCB8IGNoYXJjb2RlICYgNjMpO1xuICAgICAgfSBlbHNlIGlmIChjaGFyY29kZSA8IDU1Mjk2IHx8IGNoYXJjb2RlID49IDU3MzQ0KSB7XG4gICAgICAgIHV0ZjgucHVzaCgyMjQgfCBjaGFyY29kZSA+PiAxMiwgMTI4IHwgY2hhcmNvZGUgPj4gNiAmIDYzLCAxMjggfCBjaGFyY29kZSAmIDYzKTtcbiAgICAgIH1cbiAgICAgIC8vIHN1cnJvZ2F0ZSBwYWlyXG4gICAgICBlbHNlIHtcbiAgICAgICAgaSsrO1xuICAgICAgICAvLyBVVEYtMTYgZW5jb2RlcyAweDEwMDAwLTB4MTBGRkZGIGJ5XG4gICAgICAgIC8vIHN1YnRyYWN0aW5nIDB4MTAwMDAgYW5kIHNwbGl0dGluZyB0aGVcbiAgICAgICAgLy8gMjAgYml0cyBvZiAweDAtMHhGRkZGRiBpbnRvIHR3byBoYWx2ZXNcbiAgICAgICAgY2hhcmNvZGUgPSA2NTUzNiArICgoY2hhcmNvZGUgJiAxMDIzKSA8PCAxMCB8IHN0ci5jaGFyQ29kZUF0KGkpICYgMTAyMyk7XG4gICAgICAgIHV0ZjgucHVzaCgyNDAgfCBjaGFyY29kZSA+PiAxOCwgMTI4IHwgY2hhcmNvZGUgPj4gMTIgJiA2MywgMTI4IHwgY2hhcmNvZGUgPj4gNiAmIDYzLCAxMjggfCBjaGFyY29kZSAmIDYzKTtcbiAgICAgIH1cbiAgICB9XG4gICAgcmV0dXJuIHV0Zjg7XG4gIH1cblxuICBzdGF0aWMgdG9VVEYxNkFycmF5KHN0cikge1xuICAgIHZhciB1dGYxNiA9IFtdO1xuICAgIGZvciAodmFyIGkgPSAwOyBpIDwgc3RyLmxlbmd0aDsgaSsrKSB7XG4gICAgICB2YXIgY29kZVBvaW50ID0gc3RyLmNvZGVQb2ludEF0KGkpO1xuXG4gICAgICBpZiAoY29kZVBvaW50IDw9IDI1NSkge1xuICAgICAgICB1dGYxNi5wdXNoKDApO1xuICAgICAgICB1dGYxNi5wdXNoKGNvZGVQb2ludCk7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICB1dGYxNi5wdXNoKGNvZGVQb2ludCA+PiA4ICYgMjU1KTtcbiAgICAgICAgdXRmMTYucHVzaChjb2RlUG9pbnQgJiAyNTUpO1xuICAgICAgfVxuICAgIH1cbiAgICByZXR1cm4gdXRmMTY7XG4gIH1cblxuICBzdGF0aWMgdG9VVEYzMkFycmF5KHN0cikge1xuICAgIHZhciB1dGYzMiA9IFtdO1xuICAgIGZvciAodmFyIGkgPSAwOyBpIDwgc3RyLmxlbmd0aDsgaSsrKSB7XG4gICAgICB2YXIgY29kZVBvaW50ID0gc3RyLmNvZGVQb2ludEF0KGkpO1xuXG4gICAgICBpZiAoY29kZVBvaW50IDw9IDI1NSkge1xuICAgICAgICB1dGYzMi5wdXNoKDApO1xuICAgICAgICB1dGYzMi5wdXNoKDApO1xuICAgICAgICB1dGYzMi5wdXNoKDApO1xuICAgICAgICB1dGYzMi5wdXNoKGNvZGVQb2ludCk7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICB1dGYzMi5wdXNoKDApO1xuICAgICAgICB1dGYzMi5wdXNoKDApO1xuICAgICAgICB1dGYzMi5wdXNoKGNvZGVQb2ludCA+PiA4ICYgMjU1KTtcbiAgICAgICAgdXRmMzIucHVzaChjb2RlUG9pbnQgJiAyNTUpO1xuICAgICAgfVxuICAgIH1cbiAgICByZXR1cm4gdXRmMzI7XG4gIH1cblxuICAvL2h0dHA6Ly9zdGFja292ZXJmbG93LmNvbS9xdWVzdGlvbnMvMjAwMzQ5My9qYXZhc2NyaXB0LWZsb2F0LWZyb20tdG8tYml0c1xuICBzdGF0aWMgZmxvYXQzMlRvQnl0ZXMoZikge1xuICAgIHZhciBieXRlcyA9IFtdO1xuXG4gICAgdmFyIGJ1ZiA9IG5ldyBBcnJheUJ1ZmZlcig0KTtcbiAgICBuZXcgRmxvYXQzMkFycmF5KGJ1ZilbMF0gPSBmO1xuXG4gICAgbGV0IGludFZlcnNpb24gPSBuZXcgVWludDMyQXJyYXkoYnVmKVswXTtcblxuICAgIGJ5dGVzLnB1c2goaW50VmVyc2lvbiA+PiAyNCAmIDI1NSk7XG4gICAgYnl0ZXMucHVzaChpbnRWZXJzaW9uID4+IDE2ICYgMjU1KTtcbiAgICBieXRlcy5wdXNoKGludFZlcnNpb24gPj4gOCAmIDI1NSk7XG4gICAgYnl0ZXMucHVzaChpbnRWZXJzaW9uICYgMjU1KTtcblxuICAgIHJldHVybiBieXRlcztcbiAgfVxuXG4gIHN0YXRpYyBmbG9hdDY0VG9CeXRlcyhmKSB7XG4gICAgdmFyIGJ5dGVzID0gW107XG5cbiAgICB2YXIgYnVmID0gbmV3IEFycmF5QnVmZmVyKDgpO1xuICAgIG5ldyBGbG9hdDY0QXJyYXkoYnVmKVswXSA9IGY7XG5cbiAgICB2YXIgaW50VmVyc2lvbjEgPSBuZXcgVWludDMyQXJyYXkoYnVmKVswXTtcbiAgICB2YXIgaW50VmVyc2lvbjIgPSBuZXcgVWludDMyQXJyYXkoYnVmKVsxXTtcblxuICAgIGJ5dGVzLnB1c2goaW50VmVyc2lvbjIgPj4gMjQgJiAyNTUpO1xuICAgIGJ5dGVzLnB1c2goaW50VmVyc2lvbjIgPj4gMTYgJiAyNTUpO1xuICAgIGJ5dGVzLnB1c2goaW50VmVyc2lvbjIgPj4gOCAmIDI1NSk7XG4gICAgYnl0ZXMucHVzaChpbnRWZXJzaW9uMiAmIDI1NSk7XG5cbiAgICBieXRlcy5wdXNoKGludFZlcnNpb24xID4+IDI0ICYgMjU1KTtcbiAgICBieXRlcy5wdXNoKGludFZlcnNpb24xID4+IDE2ICYgMjU1KTtcbiAgICBieXRlcy5wdXNoKGludFZlcnNpb24xID4+IDggJiAyNTUpO1xuICAgIGJ5dGVzLnB1c2goaW50VmVyc2lvbjEgJiAyNTUpO1xuXG4gICAgcmV0dXJuIGJ5dGVzO1xuICB9XG59XG5cbi8qIEBmbG93ICovXG5cbmNsYXNzIE1haWxib3gge1xuXG4gIGNvbnN0cnVjdG9yKCkge1xuICAgIHRoaXMubWVzc2FnZXMgPSBbXTtcbiAgfVxuXG4gIGRlbGl2ZXIobWVzc2FnZSkge1xuICAgIHRoaXMubWVzc2FnZXMucHVzaChtZXNzYWdlKTtcbiAgICByZXR1cm4gbWVzc2FnZTtcbiAgfVxuXG4gIGdldCgpIHtcbiAgICByZXR1cm4gdGhpcy5tZXNzYWdlcztcbiAgfVxuXG4gIGlzRW1wdHkoKSB7XG4gICAgcmV0dXJuIHRoaXMubWVzc2FnZXMubGVuZ3RoID09PSAwO1xuICB9XG5cbiAgcmVtb3ZlQXQoaW5kZXgpIHtcbiAgICB0aGlzLm1lc3NhZ2VzLnNwbGljZShpbmRleCwgMSk7XG4gIH1cbn1cblxudmFyIFN0YXRlcyA9IHtcbiAgTk9STUFMOiBTeW1ib2wuZm9yKFwibm9ybWFsXCIpLFxuICBLSUxMOiBTeW1ib2wuZm9yKFwia2lsbFwiKSxcbiAgU1VTUEVORDogU3ltYm9sLmZvcihcInN1c3BlbmRcIiksXG4gIENPTlRJTlVFOiBTeW1ib2wuZm9yKFwiY29udGludWVcIiksXG4gIFJFQ0VJVkU6IFN5bWJvbC5mb3IoXCJyZWNlaXZlXCIpLFxuICBTRU5EOiBTeW1ib2wuZm9yKFwic2VuZFwiKSxcbiAgU0xFRVBJTkc6IFN5bWJvbC5mb3IoXCJzbGVlcGluZ1wiKSxcbiAgUlVOTklORzogU3ltYm9sLmZvcihcInJ1bm5pbmdcIiksXG4gIFNVU1BFTkRFRDogU3ltYm9sLmZvcihcInN1c3BlbmRlZFwiKSxcbiAgU1RPUFBFRDogU3ltYm9sLmZvcihcInN0b3BwZWRcIiksXG4gIFNMRUVQOiBTeW1ib2wuZm9yKFwic2xlZXBcIiksXG4gIEVYSVQ6IFN5bWJvbC5mb3IoXCJleGl0XCIpLFxuICBOT01BVENIOiBTeW1ib2wuZm9yKFwibm9fbWF0Y2hcIilcbn07XG5cbmNsYXNzIFByb2Nlc3Mge1xuXG4gIGNvbnN0cnVjdG9yKHBpZCwgbWFpbGJveCkge1xuICAgIHRoaXMucGlkID0gcGlkO1xuICAgIHRoaXMubWFpbGJveCA9IG1haWxib3g7XG4gICAgdGhpcy5zdGF0dXMgPSBTdGF0ZXMuU1RPUFBFRDtcbiAgICB0aGlzLmRpY3QgPSB7fTtcbiAgfVxufVxuXG5jbGFzcyBQcm9jZXNzU3lzdGVtIHtcblxuICBjb25zdHJ1Y3RvcigpIHtcbiAgICB0aGlzLnBpZHMgPSBuZXcgTWFwKCk7XG4gICAgdGhpcy5tYWlsYm94ZXMgPSBuZXcgTWFwKCk7XG4gICAgdGhpcy5uYW1lcyA9IG5ldyBNYXAoKTtcbiAgICB0aGlzLmxpbmtzID0gbmV3IE1hcCgpO1xuXG4gICAgdGhpcy5jdXJyZW50X3Byb2Nlc3MgPSBudWxsO1xuICAgIHRoaXMuc3VzcGVuZGVkID0gbmV3IE1hcCgpO1xuXG4gICAgdGhpcy5tYWluX3Byb2Nlc3NfcGlkID0gdGhpcy5zcGF3bigpO1xuICAgIHRoaXMuc2V0X2N1cnJlbnQodGhpcy5tYWluX3Byb2Nlc3NfcGlkKTtcbiAgfVxuXG4gIHNwYXduKCkge1xuICAgIHJldHVybiB0aGlzLmFkZF9wcm9jKGZhbHNlKS5waWQ7XG4gIH1cblxuICBzcGF3bl9saW5rKCkge1xuICAgIHJldHVybiB0aGlzLmFkZF9wcm9jKHRydWUpLnBpZDtcbiAgfVxuXG4gIGxpbmsocGlkKSB7XG4gICAgdGhpcy5saW5rcy5nZXQodGhpcy5waWQoKSkuYWRkKHBpZCk7XG4gICAgdGhpcy5saW5rcy5nZXQocGlkKS5hZGQodGhpcy5waWQoKSk7XG4gIH1cblxuICB1bmxpbmsocGlkKSB7XG4gICAgdGhpcy5saW5rcy5nZXQodGhpcy5waWQoKSkuZGVsZXRlKHBpZCk7XG4gICAgdGhpcy5saW5rcy5nZXQocGlkKS5kZWxldGUodGhpcy5waWQoKSk7XG4gIH1cblxuICBzZXRfY3VycmVudChpZCkge1xuICAgIGxldCBwaWQgPSB0aGlzLnBpZG9mKGlkKTtcbiAgICBpZiAocGlkICE9PSBudWxsKSB7XG4gICAgICB0aGlzLmN1cnJlbnRfcHJvY2VzcyA9IHRoaXMucGlkcy5nZXQocGlkKTtcbiAgICAgIHRoaXMuY3VycmVudF9wcm9jZXNzLnN0YXR1cyA9IFN0YXRlcy5SVU5OSU5HO1xuICAgIH1cbiAgfVxuXG4gIGFkZF9wcm9jKGxpbmtlZCkge1xuICAgIGxldCBuZXdwaWQgPSBuZXcgUElEKCk7XG4gICAgbGV0IG1haWxib3ggPSBuZXcgTWFpbGJveCgpO1xuICAgIGxldCBuZXdwcm9jID0gbmV3IFByb2Nlc3MobmV3cGlkLCBtYWlsYm94KTtcblxuICAgIHRoaXMucGlkcy5zZXQobmV3cGlkLCBuZXdwcm9jKTtcbiAgICB0aGlzLm1haWxib3hlcy5zZXQobmV3cGlkLCBtYWlsYm94KTtcbiAgICB0aGlzLmxpbmtzLnNldChuZXdwaWQsIG5ldyBTZXQoKSk7XG5cbiAgICBpZiAobGlua2VkKSB7XG4gICAgICB0aGlzLmxpbmsobmV3cGlkKTtcbiAgICB9XG5cbiAgICByZXR1cm4gbmV3cHJvYztcbiAgfVxuXG4gIHJlbW92ZV9wcm9jKHBpZCkge1xuICAgIHRoaXMucGlkcy5kZWxldGUocGlkKTtcbiAgICB0aGlzLnVucmVnaXN0ZXIocGlkKTtcblxuICAgIGlmICh0aGlzLmxpbmtzLmhhcyhwaWQpKSB7XG4gICAgICBmb3IgKGxldCBsaW5rcGlkIG9mIHRoaXMubGlua3MuZ2V0KHBpZCkpIHtcbiAgICAgICAgdGhpcy5saW5rcy5nZXQobGlua3BpZCkuZGVsZXRlKHBpZCk7XG4gICAgICB9XG5cbiAgICAgIHRoaXMubGlua3MuZGVsZXRlKHBpZCk7XG4gICAgfVxuICB9XG5cbiAgZXhpdChpZCkge1xuICAgIGxldCBwaWQgPSB0aGlzLnBpZG9mKGlkKTtcbiAgICB0aGlzLnJlbW92ZV9wcm9jKGlkKTtcbiAgfVxuXG4gIHJlZ2lzdGVyKG5hbWUsIHBpZCkge1xuICAgIGlmICghdGhpcy5uYW1lcy5oYXMobmFtZSkpIHtcbiAgICAgIHRoaXMubmFtZXMuc2V0KG5hbWUsIHBpZCk7XG4gICAgICByZXR1cm4gbmFtZTtcbiAgICB9IGVsc2Uge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKFwiTmFtZSBpcyBhbHJlYWR5IHJlZ2lzdGVyZWQgdG8gYW5vdGhlciBwcm9jZXNzXCIpO1xuICAgIH1cbiAgfVxuXG4gIHJlZ2lzdGVyZWQobmFtZSkge1xuICAgIHJldHVybiB0aGlzLm5hbWVzLmhhcyhuYW1lKSA/IHRoaXMubmFtZXMuZ2V0KG5hbWUpIDogbnVsbDtcbiAgfVxuXG4gIHVucmVnaXN0ZXIocGlkKSB7XG4gICAgZm9yIChsZXQgbmFtZSBvZiB0aGlzLm5hbWVzLmtleXMoKSkge1xuICAgICAgaWYgKHRoaXMubmFtZXMuaGFzKG5hbWUpICYmIHRoaXMubmFtZXMuZ2V0KG5hbWUpID09PSBwaWQpIHtcbiAgICAgICAgdGhpcy5uYW1lcy5kZWxldGUobmFtZSk7XG4gICAgICB9XG4gICAgfVxuICB9XG5cbiAgcGlkKCkge1xuICAgIHJldHVybiB0aGlzLmN1cnJlbnRfcHJvY2Vzcy5waWQ7XG4gIH1cblxuICBwaWRvZihpZCkge1xuICAgIGlmIChpZCBpbnN0YW5jZW9mIFBJRCkge1xuICAgICAgcmV0dXJuIHRoaXMucGlkcy5oYXMoaWQpID8gaWQgOiBudWxsO1xuICAgIH0gZWxzZSBpZiAoaWQgaW5zdGFuY2VvZiBQcm9jZXNzKSB7XG4gICAgICByZXR1cm4gaWQucGlkO1xuICAgIH0gZWxzZSB7XG4gICAgICBsZXQgcGlkID0gdGhpcy5yZWdpc3RlcmVkKGlkKTtcbiAgICAgIGlmIChwaWQgPT09IG51bGwpIHRocm93IFwiUHJvY2VzcyBuYW1lIG5vdCByZWdpc3RlcmVkOiBcIiArIGlkICsgXCIgKFwiICsgdHlwZW9mIGlkICsgXCIpXCI7XG4gICAgICByZXR1cm4gcGlkO1xuICAgIH1cbiAgfVxuXG4gIHB1dChpZCwga2V5LCB2YWx1ZSkge1xuICAgIGxldCBwaWQgPSB0aGlzLnBpZG9mKGlkKTtcbiAgICBsZXQgcHJvY2VzcyA9IHRoaXMucGlkcy5nZXQocGlkKTtcbiAgICBwcm9jZXNzLmRpY3Rba2V5XSA9IHZhbHVlO1xuICB9XG5cbiAgZ2V0KGlkLCBrZXkpIHtcbiAgICBsZXQgcGlkID0gdGhpcy5waWRvZihpZCk7XG4gICAgbGV0IHByb2Nlc3MgPSB0aGlzLnBpZHMuZ2V0KHBpZCk7XG5cbiAgICBpZiAoa2V5ICE9IG51bGwpIHtcbiAgICAgIHJldHVybiBwcm9jZXNzLmRpY3Rba2V5XTtcbiAgICB9IGVsc2Uge1xuICAgICAgcmV0dXJuIHByb2Nlc3MuZGljdDtcbiAgICB9XG4gIH1cblxuICBnZXRfa2V5cyhpZCkge1xuICAgIGxldCBwaWQgPSB0aGlzLnBpZG9mKGlkKTtcbiAgICBsZXQgcHJvY2VzcyA9IHRoaXMucGlkcy5nZXQocGlkKTtcblxuICAgIHJldHVybiBPYmplY3Qua2V5cyhwcm9jZXNzLmRpY3QpO1xuICB9XG5cbiAgZXJhc2UoaWQsIGtleSkge1xuICAgIGxldCBwaWQgPSB0aGlzLnBpZG9mKGlkKTtcbiAgICBsZXQgcHJvY2VzcyA9IHRoaXMucGlkcy5nZXQocGlkKTtcblxuICAgIGlmIChrZXkgIT0gbnVsbCkge1xuICAgICAgZGVsZXRlIHByb2Nlc3MuZGljdFtrZXldO1xuICAgIH0gZWxzZSB7XG4gICAgICBwcm9jZXNzLmRpY3QgPSB7fTtcbiAgICB9XG4gIH1cbn1cblxudmFyIEMgPSBPYmplY3QuZnJlZXplKHtcblx0UHJvY2Vzc1N5c3RlbTogUHJvY2Vzc1N5c3RlbSxcblx0VHVwbGU6IFR1cGxlJDEsXG5cdFBJRDogUElELFxuXHRCaXRTdHJpbmc6IEJpdFN0cmluZyxcblx0UGF0dGVybnM6IFBhdHRlcm5zLFxuXHRJbnRlZ2VyOiBJbnRlZ2VyJDEsXG5cdEZsb2F0OiBGbG9hdCxcblx0Y2FsbF9wcm9wZXJ0eTogY2FsbF9wcm9wZXJ0eVxufSk7XG5cbmxldCBFbnVtID0ge1xuXG4gIGFsbF9fcW1hcmtfXzogZnVuY3Rpb24gKGNvbGxlY3Rpb24sIGZ1biA9IHggPT4geCkge1xuICAgIGZvciAobGV0IGVsZW0gb2YgY29sbGVjdGlvbikge1xuICAgICAgaWYgKCFmdW4oZWxlbSkpIHtcbiAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgfVxuICAgIH1cblxuICAgIHJldHVybiB0cnVlO1xuICB9LFxuXG4gIGFueV9fcW1hcmtfXzogZnVuY3Rpb24gKGNvbGxlY3Rpb24sIGZ1biA9IHggPT4geCkge1xuICAgIGZvciAobGV0IGVsZW0gb2YgY29sbGVjdGlvbikge1xuICAgICAgaWYgKGZ1bihlbGVtKSkge1xuICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICByZXR1cm4gZmFsc2U7XG4gIH0sXG5cbiAgYXQ6IGZ1bmN0aW9uIChjb2xsZWN0aW9uLCBuLCB0aGVfZGVmYXVsdCA9IG51bGwpIHtcbiAgICBpZiAobiA+IHRoaXMuY291bnQoY29sbGVjdGlvbikgfHwgbiA8IDApIHtcbiAgICAgIHJldHVybiB0aGVfZGVmYXVsdDtcbiAgICB9XG5cbiAgICByZXR1cm4gY29sbGVjdGlvbltuXTtcbiAgfSxcblxuICBjb25jYXQ6IGZ1bmN0aW9uICguLi5lbnVtYWJsZXMpIHtcbiAgICByZXR1cm4gZW51bWFibGVzWzBdLmNvbmNhdChlbnVtYWJsZXNbMV0pO1xuICB9LFxuXG4gIGNvdW50OiBmdW5jdGlvbiAoY29sbGVjdGlvbiwgZnVuID0gbnVsbCkge1xuICAgIGlmIChmdW4gPT0gbnVsbCkge1xuICAgICAgcmV0dXJuIGNvbGxlY3Rpb24ubGVuZ3RoO1xuICAgIH0gZWxzZSB7XG4gICAgICByZXR1cm4gY29sbGVjdGlvbi5maWx0ZXIoZnVuKS5sZW5ndGg7XG4gICAgfVxuICB9LFxuXG4gIGRyb3A6IGZ1bmN0aW9uIChjb2xsZWN0aW9uLCBjb3VudCkge1xuICAgIHJldHVybiBjb2xsZWN0aW9uLnNsaWNlKGNvdW50KTtcbiAgfSxcblxuICBkcm9wX3doaWxlOiBmdW5jdGlvbiAoY29sbGVjdGlvbiwgZnVuKSB7XG4gICAgbGV0IGNvdW50ID0gMDtcblxuICAgIGZvciAobGV0IGVsZW0gb2YgY29sbGVjdGlvbikge1xuICAgICAgaWYgKGZ1bihlbGVtKSkge1xuICAgICAgICBjb3VudCA9IGNvdW50ICsgMTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIGJyZWFrO1xuICAgICAgfVxuICAgIH1cblxuICAgIHJldHVybiBjb2xsZWN0aW9uLnNsaWNlKGNvdW50KTtcbiAgfSxcblxuICBlYWNoOiBmdW5jdGlvbiAoY29sbGVjdGlvbiwgZnVuKSB7XG4gICAgZm9yIChsZXQgZWxlbSBvZiBjb2xsZWN0aW9uKSB7XG4gICAgICBmdW4oZWxlbSk7XG4gICAgfVxuICB9LFxuXG4gIGVtcHR5X19xbWFya19fOiBmdW5jdGlvbiAoY29sbGVjdGlvbikge1xuICAgIHJldHVybiBjb2xsZWN0aW9uLmxlbmd0aCA9PT0gMDtcbiAgfSxcblxuICBmZXRjaDogZnVuY3Rpb24gKGNvbGxlY3Rpb24sIG4pIHtcbiAgICBpZiAoS2VybmVsLmlzX2xpc3QoY29sbGVjdGlvbikpIHtcbiAgICAgIGlmIChuIDwgdGhpcy5jb3VudChjb2xsZWN0aW9uKSAmJiBuID49IDApIHtcbiAgICAgICAgcmV0dXJuIEtlcm5lbC5TcGVjaWFsRm9ybXMudHVwbGUoS2VybmVsLlNwZWNpYWxGb3Jtcy5hdG9tKFwib2tcIiksIGNvbGxlY3Rpb25bbl0pO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgcmV0dXJuIEtlcm5lbC5TcGVjaWFsRm9ybXMuYXRvbShcImVycm9yXCIpO1xuICAgICAgfVxuICAgIH1cblxuICAgIHRocm93IG5ldyBFcnJvcihcImNvbGxlY3Rpb24gaXMgbm90IGFuIEVudW1lcmFibGVcIik7XG4gIH0sXG5cbiAgZmV0Y2hfX2VtYXJrX186IGZ1bmN0aW9uIChjb2xsZWN0aW9uLCBuKSB7XG4gICAgaWYgKEtlcm5lbC5pc19saXN0KGNvbGxlY3Rpb24pKSB7XG4gICAgICBpZiAobiA8IHRoaXMuY291bnQoY29sbGVjdGlvbikgJiYgbiA+PSAwKSB7XG4gICAgICAgIHJldHVybiBjb2xsZWN0aW9uW25dO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKFwib3V0IG9mIGJvdW5kcyBlcnJvclwiKTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICB0aHJvdyBuZXcgRXJyb3IoXCJjb2xsZWN0aW9uIGlzIG5vdCBhbiBFbnVtZXJhYmxlXCIpO1xuICB9LFxuXG4gIGZpbHRlcjogZnVuY3Rpb24gKGNvbGxlY3Rpb24sIGZ1bikge1xuICAgIGxldCByZXN1bHQgPSBbXTtcblxuICAgIGZvciAobGV0IGVsZW0gb2YgY29sbGVjdGlvbikge1xuICAgICAgaWYgKGZ1bihlbGVtKSkge1xuICAgICAgICByZXN1bHQucHVzaChlbGVtKTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICByZXR1cm4gcmVzdWx0O1xuICB9LFxuXG4gIGZpbHRlcl9tYXA6IGZ1bmN0aW9uIChjb2xsZWN0aW9uLCBmaWx0ZXIsIG1hcHBlcikge1xuICAgIHJldHVybiBFbnVtLm1hcChFbnVtLmZpbHRlcihjb2xsZWN0aW9uLCBmaWx0ZXIpLCBtYXBwZXIpO1xuICB9LFxuXG4gIGZpbmQ6IGZ1bmN0aW9uIChjb2xsZWN0aW9uLCBpZl9ub25lID0gbnVsbCwgZnVuKSB7XG4gICAgZm9yIChsZXQgZWxlbSBvZiBjb2xsZWN0aW9uKSB7XG4gICAgICBpZiAoZnVuKGVsZW0pKSB7XG4gICAgICAgIHJldHVybiBlbGVtO1xuICAgICAgfVxuICAgIH1cblxuICAgIHJldHVybiBpZl9ub25lO1xuICB9LFxuXG4gIGludG86IGZ1bmN0aW9uIChjb2xsZWN0aW9uLCBsaXN0KSB7XG4gICAgcmV0dXJuIGxpc3QuY29uY2F0KGNvbGxlY3Rpb24pO1xuICB9LFxuXG4gIG1hcDogZnVuY3Rpb24gKGNvbGxlY3Rpb24sIGZ1bikge1xuICAgIGxldCByZXN1bHQgPSBbXTtcblxuICAgIGZvciAobGV0IGVsZW0gb2YgY29sbGVjdGlvbikge1xuICAgICAgcmVzdWx0LnB1c2goZnVuKGVsZW0pKTtcbiAgICB9XG5cbiAgICByZXR1cm4gcmVzdWx0O1xuICB9LFxuXG4gIG1hcF9yZWR1Y2U6IGZ1bmN0aW9uIChjb2xsZWN0aW9uLCBhY2MsIGZ1bikge1xuICAgIGxldCBtYXBwZWQgPSBLZXJuZWwuU3BlY2lhbEZvcm1zLmxpc3QoKTtcbiAgICBsZXQgdGhlX2FjYyA9IGFjYztcblxuICAgIGZvciAodmFyIGkgPSAwOyBpIDwgdGhpcy5jb3VudChjb2xsZWN0aW9uKTsgaSsrKSB7XG4gICAgICBsZXQgdHVwbGUgPSBmdW4oY29sbGVjdGlvbltpXSwgdGhlX2FjYyk7XG5cbiAgICAgIHRoZV9hY2MgPSBLZXJuZWwuZWxlbSh0dXBsZSwgMSk7XG4gICAgICBtYXBwZWQgPSBLZXJuZWwuU3BlY2lhbEZvcm1zLmxpc3QoLi4ubWFwcGVkLmNvbmNhdChbS2VybmVsLmVsZW0odHVwbGUsIDApXSkpO1xuICAgIH1cblxuICAgIHJldHVybiBLZXJuZWwuU3BlY2lhbEZvcm1zLnR1cGxlKG1hcHBlZCwgdGhlX2FjYyk7XG4gIH0sXG5cbiAgbWVtYmVyOiBmdW5jdGlvbiAoY29sbGVjdGlvbiwgdmFsdWUpIHtcbiAgICByZXR1cm4gY29sbGVjdGlvbi5pbmNsdWRlcyh2YWx1ZSk7XG4gIH0sXG5cbiAgcmVkdWNlOiBmdW5jdGlvbiAoY29sbGVjdGlvbiwgYWNjLCBmdW4pIHtcbiAgICBsZXQgdGhlX2FjYyA9IGFjYztcblxuICAgIGZvciAodmFyIGkgPSAwOyBpIDwgdGhpcy5jb3VudChjb2xsZWN0aW9uKTsgaSsrKSB7XG4gICAgICBsZXQgdHVwbGUgPSBmdW4oY29sbGVjdGlvbltpXSwgdGhlX2FjYyk7XG5cbiAgICAgIHRoZV9hY2MgPSBLZXJuZWwuZWxlbSh0dXBsZSwgMSk7XG4gICAgfVxuXG4gICAgcmV0dXJuIHRoZV9hY2M7XG4gIH0sXG5cbiAgdGFrZTogZnVuY3Rpb24gKGNvbGxlY3Rpb24sIGNvdW50KSB7XG4gICAgcmV0dXJuIGNvbGxlY3Rpb24uc2xpY2UoMCwgY291bnQpO1xuICB9LFxuXG4gIHRha2VfZXZlcnk6IGZ1bmN0aW9uIChjb2xsZWN0aW9uLCBudGgpIHtcbiAgICBsZXQgcmVzdWx0ID0gW107XG4gICAgbGV0IGluZGV4ID0gMDtcblxuICAgIGZvciAobGV0IGVsZW0gb2YgY29sbGVjdGlvbikge1xuICAgICAgaWYgKGluZGV4ICUgbnRoID09PSAwKSB7XG4gICAgICAgIHJlc3VsdC5wdXNoKGVsZW0pO1xuICAgICAgfVxuICAgIH1cblxuICAgIHJldHVybiBLZXJuZWwuU3BlY2lhbEZvcm1zLmxpc3QoLi4ucmVzdWx0KTtcbiAgfSxcblxuICB0YWtlX3doaWxlOiBmdW5jdGlvbiAoY29sbGVjdGlvbiwgZnVuKSB7XG4gICAgbGV0IGNvdW50ID0gMDtcblxuICAgIGZvciAobGV0IGVsZW0gb2YgY29sbGVjdGlvbikge1xuICAgICAgaWYgKGZ1bihlbGVtKSkge1xuICAgICAgICBjb3VudCA9IGNvdW50ICsgMTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIGJyZWFrO1xuICAgICAgfVxuICAgIH1cblxuICAgIHJldHVybiBjb2xsZWN0aW9uLnNsaWNlKDAsIGNvdW50KTtcbiAgfSxcblxuICB0b19saXN0OiBmdW5jdGlvbiAoY29sbGVjdGlvbikge1xuICAgIHJldHVybiBjb2xsZWN0aW9uO1xuICB9XG59O1xuXG5sZXQgU3BlY2lhbEZvcm1zID0ge1xuXG4gIF9fRElSX186IGZ1bmN0aW9uICgpIHtcbiAgICBpZiAoX19kaXJuYW1lKSB7XG4gICAgICByZXR1cm4gX19kaXJuYW1lO1xuICAgIH1cblxuICAgIGlmIChkb2N1bWVudC5jdXJyZW50U2NyaXB0KSB7XG4gICAgICByZXR1cm4gZG9jdW1lbnQuY3VycmVudFNjcmlwdC5zcmM7XG4gICAgfVxuXG4gICAgcmV0dXJuIG51bGw7XG4gIH0sXG5cbiAgYXRvbTogZnVuY3Rpb24gKF92YWx1ZSkge1xuICAgIHJldHVybiBTeW1ib2wuZm9yKF92YWx1ZSk7XG4gIH0sXG5cbiAgbGlzdDogZnVuY3Rpb24gKC4uLmFyZ3MpIHtcbiAgICByZXR1cm4gT2JqZWN0LmZyZWV6ZShhcmdzKTtcbiAgfSxcblxuICBiaXRzdHJpbmc6IGZ1bmN0aW9uICguLi5hcmdzKSB7XG4gICAgcmV0dXJuIG5ldyBCaXRTdHJpbmcoLi4uYXJncyk7XG4gIH0sXG5cbiAgYm91bmQ6IGZ1bmN0aW9uIChfdmFyKSB7XG4gICAgcmV0dXJuIFBhdHRlcm5zLmJvdW5kKF92YXIpO1xuICB9LFxuXG4gIF9jYXNlOiBmdW5jdGlvbiAoY29uZGl0aW9uLCBjbGF1c2VzKSB7XG4gICAgcmV0dXJuIFBhdHRlcm5zLmRlZm1hdGNoKC4uLmNsYXVzZXMpKGNvbmRpdGlvbik7XG4gIH0sXG5cbiAgY29uZDogZnVuY3Rpb24gKGNsYXVzZXMpIHtcbiAgICBmb3IgKGxldCBjbGF1c2Ugb2YgY2xhdXNlcykge1xuICAgICAgaWYgKGNsYXVzZVswXSkge1xuICAgICAgICByZXR1cm4gY2xhdXNlWzFdKCk7XG4gICAgICB9XG4gICAgfVxuXG4gICAgdGhyb3cgbmV3IEVycm9yKCk7XG4gIH0sXG5cbiAgZm46IGZ1bmN0aW9uIChjbGF1c2VzKSB7XG4gICAgcmV0dXJuIFBhdHRlcm5zLmRlZm1hdGNoKGNsYXVzZXMpO1xuICB9LFxuXG4gIG1hcDogZnVuY3Rpb24gKG9iaikge1xuICAgIHJldHVybiBPYmplY3QuZnJlZXplKG9iaik7XG4gIH0sXG5cbiAgbWFwX3VwZGF0ZTogZnVuY3Rpb24gKG1hcCwgdmFsdWVzKSB7XG4gICAgcmV0dXJuIE9iamVjdC5mcmVlemUoT2JqZWN0LmFzc2lnbihPYmplY3QuY3JlYXRlKG1hcC5jb25zdHJ1Y3Rvci5wcm90b3R5cGUpLCBtYXAsIHZhbHVlcykpO1xuICB9LFxuXG4gIF9mb3I6IGZ1bmN0aW9uIChjb2xsZWN0aW9ucywgZnVuLCBmaWx0ZXIgPSAoKSA9PiB0cnVlLCBpbnRvID0gW10sIHByZXZpb3VzVmFsdWVzID0gW10pIHtcbiAgICBsZXQgcGF0dGVybiA9IGNvbGxlY3Rpb25zWzBdWzBdO1xuICAgIGxldCBjb2xsZWN0aW9uID0gY29sbGVjdGlvbnNbMF1bMV07XG5cbiAgICBpZiAoY29sbGVjdGlvbnMubGVuZ3RoID09PSAxKSB7XG5cbiAgICAgIGZvciAobGV0IGVsZW0gb2YgY29sbGVjdGlvbikge1xuICAgICAgICBsZXQgciA9IFBhdHRlcm5zLm1hdGNoX25vX3Rocm93KHBhdHRlcm4sIGVsZW0pO1xuICAgICAgICBsZXQgYXJncyA9IHByZXZpb3VzVmFsdWVzLmNvbmNhdChyKTtcblxuICAgICAgICBpZiAociAmJiBmaWx0ZXIuYXBwbHkodGhpcywgYXJncykpIHtcbiAgICAgICAgICBpbnRvID0gRW51bS5pbnRvKFtmdW4uYXBwbHkodGhpcywgYXJncyldLCBpbnRvKTtcbiAgICAgICAgfVxuICAgICAgfVxuXG4gICAgICByZXR1cm4gaW50bztcbiAgICB9IGVsc2Uge1xuICAgICAgbGV0IF9pbnRvID0gW107XG5cbiAgICAgIGZvciAobGV0IGVsZW0gb2YgY29sbGVjdGlvbikge1xuICAgICAgICBsZXQgciA9IFBhdHRlcm5zLm1hdGNoX25vX3Rocm93KHBhdHRlcm4sIGVsZW0pO1xuICAgICAgICBpZiAocikge1xuICAgICAgICAgIF9pbnRvID0gRW51bS5pbnRvKHRoaXMuX2Zvcihjb2xsZWN0aW9ucy5zbGljZSgxKSwgZnVuLCBmaWx0ZXIsIF9pbnRvLCBwcmV2aW91c1ZhbHVlcy5jb25jYXQocikpLCBpbnRvKTtcbiAgICAgICAgfVxuICAgICAgfVxuXG4gICAgICByZXR1cm4gX2ludG87XG4gICAgfVxuICB9LFxuXG4gIHJlY2VpdmU6IGZ1bmN0aW9uIChyZWNlaXZlX2Z1biwgdGltZW91dF9pbl9tcyA9IG51bGwsIHRpbWVvdXRfZm4gPSB0aW1lID0+IHRydWUpIHtcbiAgICBpZiAodGltZW91dF9pbl9tcyA9PSBudWxsIHx8IHRpbWVvdXRfaW5fbXMgPT09IFN5c3RlbS5mb3IoJ2luZmluaXR5JykpIHtcbiAgICAgIHdoaWxlICh0cnVlKSB7XG4gICAgICAgIGlmIChzZWxmLm1haWxib3gubGVuZ3RoICE9PSAwKSB7XG4gICAgICAgICAgbGV0IG1lc3NhZ2UgPSBzZWxmLm1haWxib3hbMF07XG4gICAgICAgICAgc2VsZi5tYWlsYm94ID0gc2VsZi5tYWlsYm94LnNsaWNlKDEpO1xuICAgICAgICAgIHJldHVybiByZWNlaXZlX2Z1bihtZXNzYWdlKTtcbiAgICAgICAgfVxuICAgICAgfVxuICAgIH0gZWxzZSBpZiAodGltZW91dF9pbl9tcyA9PT0gMCkge1xuICAgICAgaWYgKHNlbGYubWFpbGJveC5sZW5ndGggIT09IDApIHtcbiAgICAgICAgbGV0IG1lc3NhZ2UgPSBzZWxmLm1haWxib3hbMF07XG4gICAgICAgIHNlbGYubWFpbGJveCA9IHNlbGYubWFpbGJveC5zbGljZSgxKTtcbiAgICAgICAgcmV0dXJuIHJlY2VpdmVfZnVuKG1lc3NhZ2UpO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgcmV0dXJuIG51bGw7XG4gICAgICB9XG4gICAgfSBlbHNlIHtcbiAgICAgIGxldCBub3cgPSBEYXRlLm5vdygpO1xuICAgICAgd2hpbGUgKERhdGUubm93KCkgPCBub3cgKyB0aW1lb3V0X2luX21zKSB7XG4gICAgICAgIGlmIChzZWxmLm1haWxib3gubGVuZ3RoICE9PSAwKSB7XG4gICAgICAgICAgbGV0IG1lc3NhZ2UgPSBzZWxmLm1haWxib3hbMF07XG4gICAgICAgICAgc2VsZi5tYWlsYm94ID0gc2VsZi5tYWlsYm94LnNsaWNlKDEpO1xuICAgICAgICAgIHJldHVybiByZWNlaXZlX2Z1bihtZXNzYWdlKTtcbiAgICAgICAgfVxuICAgICAgfVxuXG4gICAgICByZXR1cm4gdGltZW91dF9mbih0aW1lb3V0X2luX21zKTtcbiAgICB9XG4gIH0sXG5cbiAgdHVwbGU6IGZ1bmN0aW9uICguLi5hcmdzKSB7XG4gICAgcmV0dXJuIG5ldyBUdXBsZSQxKC4uLmFyZ3MpO1xuICB9LFxuXG4gIF90cnk6IGZ1bmN0aW9uIChkb19mdW4sIHJlc2N1ZV9mdW5jdGlvbiwgY2F0Y2hfZnVuLCBlbHNlX2Z1bmN0aW9uLCBhZnRlcl9mdW5jdGlvbikge1xuICAgIGxldCByZXN1bHQgPSBudWxsO1xuXG4gICAgdHJ5IHtcbiAgICAgIHJlc3VsdCA9IGRvX2Z1bigpO1xuICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgIGxldCBleF9yZXN1bHQgPSBudWxsO1xuXG4gICAgICBpZiAocmVzY3VlX2Z1bmN0aW9uKSB7XG4gICAgICAgIHRyeSB7XG4gICAgICAgICAgZXhfcmVzdWx0ID0gcmVzY3VlX2Z1bmN0aW9uKGUpO1xuICAgICAgICAgIHJldHVybiBleF9yZXN1bHQ7XG4gICAgICAgIH0gY2F0Y2ggKGV4KSB7XG4gICAgICAgICAgaWYgKGV4IGluc3RhbmNlb2YgUGF0dGVybnMuTWF0Y2hFcnJvcikge1xuICAgICAgICAgICAgdGhyb3cgZXg7XG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICB9XG5cbiAgICAgIGlmIChjYXRjaF9mdW4pIHtcbiAgICAgICAgdHJ5IHtcbiAgICAgICAgICBleF9yZXN1bHQgPSBjYXRjaF9mdW4oZSk7XG4gICAgICAgICAgcmV0dXJuIGV4X3Jlc3VsdDtcbiAgICAgICAgfSBjYXRjaCAoZXgpIHtcbiAgICAgICAgICBpZiAoZXggaW5zdGFuY2VvZiBQYXR0ZXJucy5NYXRjaEVycm9yKSB7XG4gICAgICAgICAgICB0aHJvdyBleDtcbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgIH1cblxuICAgICAgdGhyb3cgZTtcbiAgICB9IGZpbmFsbHkge1xuICAgICAgaWYgKGFmdGVyX2Z1bmN0aW9uKSB7XG4gICAgICAgIGFmdGVyX2Z1bmN0aW9uKCk7XG4gICAgICB9XG4gICAgfVxuXG4gICAgaWYgKGVsc2VfZnVuY3Rpb24pIHtcbiAgICAgIHRyeSB7XG4gICAgICAgIHJldHVybiBlbHNlX2Z1bmN0aW9uKHJlc3VsdCk7XG4gICAgICB9IGNhdGNoIChleCkge1xuICAgICAgICBpZiAoZXggaW5zdGFuY2VvZiBQYXR0ZXJucy5NYXRjaEVycm9yKSB7XG4gICAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdObyBNYXRjaCBGb3VuZCBpbiBFbHNlJyk7XG4gICAgICAgIH1cblxuICAgICAgICB0aHJvdyBleDtcbiAgICAgIH1cbiAgICB9IGVsc2Uge1xuICAgICAgcmV0dXJuIHJlc3VsdDtcbiAgICB9XG4gIH1cblxufTtcblxuZnVuY3Rpb24gdG9fc3RyaW5nJDEodHVwbGUpIHtcbiAgcmV0dXJuIHR1cGxlLnRvU3RyaW5nKCk7XG59O1xuXG5mdW5jdGlvbiBkZWxldGVfYXQodHVwbGUsIGluZGV4KSB7XG4gIGxldCBuZXdfbGlzdCA9IFtdO1xuXG4gIGZvciAodmFyIGkgPSAwOyBpIDwgdHVwbGUuY291bnQoKTsgaSsrKSB7XG4gICAgaWYgKGkgIT09IGluZGV4KSB7XG4gICAgICBuZXdfbGlzdC5wdXNoKHR1cGxlLmdldChpKSk7XG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIEtlcm5lbC5TcGVjaWFsRm9ybXMudHVwbGUuYXBwbHkobnVsbCwgbmV3X2xpc3QpO1xufTtcblxuZnVuY3Rpb24gZHVwbGljYXRlKGRhdGEsIHNpemUpIHtcbiAgbGV0IGFycmF5ID0gW107XG5cbiAgZm9yICh2YXIgaSA9IHNpemUgLSAxOyBpID49IDA7IGktLSkge1xuICAgIGFycmF5LnB1c2goZGF0YSk7XG4gIH1cblxuICByZXR1cm4gS2VybmVsLlNwZWNpYWxGb3Jtcy50dXBsZS5hcHBseShudWxsLCBhcnJheSk7XG59O1xuXG5mdW5jdGlvbiBpbnNlcnRfYXQodHVwbGUsIGluZGV4LCB0ZXJtKSB7XG4gIGxldCBuZXdfdHVwbGUgPSBbXTtcblxuICBmb3IgKHZhciBpID0gMDsgaSA8PSB0dXBsZS5jb3VudCgpOyBpKyspIHtcbiAgICBpZiAoaSA9PT0gaW5kZXgpIHtcbiAgICAgIG5ld190dXBsZS5wdXNoKHRlcm0pO1xuICAgICAgaSsrO1xuICAgICAgbmV3X3R1cGxlLnB1c2godHVwbGUuZ2V0KGkpKTtcbiAgICB9IGVsc2Uge1xuICAgICAgbmV3X3R1cGxlLnB1c2godHVwbGUuZ2V0KGkpKTtcbiAgICB9XG4gIH1cblxuICByZXR1cm4gS2VybmVsLlNwZWNpYWxGb3Jtcy50dXBsZS5hcHBseShudWxsLCBuZXdfdHVwbGUpO1xufTtcblxuZnVuY3Rpb24gZnJvbV9saXN0KGxpc3QpIHtcbiAgcmV0dXJuIEtlcm5lbC5TcGVjaWFsRm9ybXMudHVwbGUuYXBwbHkobnVsbCwgbGlzdCk7XG59O1xuXG5mdW5jdGlvbiB0b19saXN0KHR1cGxlKSB7XG4gIGxldCBuZXdfbGlzdCA9IFtdO1xuXG4gIGZvciAodmFyIGkgPSAwOyBpIDwgdHVwbGUuY291bnQoKTsgaSsrKSB7XG4gICAgbmV3X2xpc3QucHVzaCh0dXBsZS5nZXQoaSkpO1xuICB9XG5cbiAgcmV0dXJuIEtlcm5lbC5TcGVjaWFsRm9ybXMubGlzdCguLi5uZXdfbGlzdCk7XG59O1xuXG52YXIgVHVwbGUgPSB7XG4gIHRvX3N0cmluZzogdG9fc3RyaW5nJDEsXG4gIGRlbGV0ZV9hdCxcbiAgZHVwbGljYXRlLFxuICBpbnNlcnRfYXQsXG4gIGZyb21fbGlzdCxcbiAgdG9fbGlzdFxufTtcblxuLy9odHRwczovL2dpdGh1Yi5jb20vYWlycG9ydHloL3Byb3RvbW9ycGhpc21cbmNsYXNzIFByb3RvY29sIHtcbiAgY29uc3RydWN0b3Ioc3BlYykge1xuICAgIHRoaXMucmVnaXN0cnkgPSBuZXcgTWFwKCk7XG4gICAgdGhpcy5mYWxsYmFjayA9IG51bGw7XG5cbiAgICBmb3IgKGxldCBmdW5OYW1lIGluIHNwZWMpIHtcbiAgICAgIHRoaXNbZnVuTmFtZV0gPSBjcmVhdGVGdW4oZnVuTmFtZSkuYmluZCh0aGlzKTtcbiAgICB9XG5cbiAgICBmdW5jdGlvbiBjcmVhdGVGdW4oZnVuTmFtZSkge1xuXG4gICAgICByZXR1cm4gZnVuY3Rpb24gKC4uLmFyZ3MpIHtcbiAgICAgICAgbGV0IHRoaW5nID0gYXJnc1swXTtcbiAgICAgICAgbGV0IGZ1biA9IG51bGw7XG5cbiAgICAgICAgaWYgKE51bWJlci5pc0ludGVnZXIodGhpbmcpICYmIHRoaXMuaGFzSW1wbGVtZW50YXRpb24oSW50ZWdlciQxKSkge1xuICAgICAgICAgIGZ1biA9IHRoaXMucmVnaXN0cnkuZ2V0KEludGVnZXIkMSlbZnVuTmFtZV07XG4gICAgICAgIH0gZWxzZSBpZiAodHlwZW9mIHRoaW5nID09PSBcIm51bWJlclwiICYmICFOdW1iZXIuaXNJbnRlZ2VyKHRoaW5nKSAmJiB0aGlzLmhhc0ltcGxlbWVudGF0aW9uKEZsb2F0KSkge1xuICAgICAgICAgIGZ1biA9IHRoaXMucmVnaXN0cnkuZ2V0KEZsb2F0KVtmdW5OYW1lXTtcbiAgICAgICAgfSBlbHNlIGlmICh0aGlzLmhhc0ltcGxlbWVudGF0aW9uKHRoaW5nKSkge1xuICAgICAgICAgIGZ1biA9IHRoaXMucmVnaXN0cnkuZ2V0KHRoaW5nLmNvbnN0cnVjdG9yKVtmdW5OYW1lXTtcbiAgICAgICAgfSBlbHNlIGlmICh0aGlzLmZhbGxiYWNrKSB7XG4gICAgICAgICAgZnVuID0gdGhpcy5mYWxsYmFja1tmdW5OYW1lXTtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmIChmdW4gIT0gbnVsbCkge1xuICAgICAgICAgIGxldCByZXR2YWwgPSBmdW4uYXBwbHkodGhpcywgYXJncyk7XG4gICAgICAgICAgcmV0dXJuIHJldHZhbDtcbiAgICAgICAgfVxuXG4gICAgICAgIHRocm93IG5ldyBFcnJvcihcIk5vIGltcGxlbWVudGF0aW9uIGZvdW5kIGZvciBcIiArIHRoaW5nKTtcbiAgICAgIH07XG4gICAgfVxuICB9XG5cbiAgaW1wbGVtZW50YXRpb24odHlwZSwgaW1wbGVtZW50YXRpb24pIHtcbiAgICBpZiAodHlwZSA9PT0gbnVsbCkge1xuICAgICAgdGhpcy5mYWxsYmFjayA9IGltcGxlbWVudGF0aW9uO1xuICAgIH0gZWxzZSB7XG4gICAgICB0aGlzLnJlZ2lzdHJ5LnNldCh0eXBlLCBpbXBsZW1lbnRhdGlvbik7XG4gICAgfVxuICB9XG5cbiAgaGFzSW1wbGVtZW50YXRpb24odGhpbmcpIHtcbiAgICByZXR1cm4gdGhpcy5yZWdpc3RyeS5oYXModGhpbmcuY29uc3RydWN0b3IpO1xuICB9XG59XG5cbmZ1bmN0aW9uIHRsKGxpc3QpIHtcbiAgcmV0dXJuIFNwZWNpYWxGb3Jtcy5saXN0KC4uLmxpc3Quc2xpY2UoMSkpO1xufVxuXG5mdW5jdGlvbiBoZChsaXN0KSB7XG4gIHJldHVybiBsaXN0WzBdO1xufVxuXG5mdW5jdGlvbiBpc19uaWwoeCkge1xuICByZXR1cm4geCA9PT0gbnVsbDtcbn1cblxuZnVuY3Rpb24gaXNfYXRvbSh4KSB7XG4gIHJldHVybiB0eXBlb2YgeCA9PT0gJ3N5bWJvbCc7XG59XG5cbmZ1bmN0aW9uIGlzX2JpbmFyeSh4KSB7XG4gIHJldHVybiB0eXBlb2YgeCA9PT0gJ3N0cmluZycgfHwgeCBpbnN0YW5jZW9mIFN0cmluZztcbn1cblxuZnVuY3Rpb24gaXNfYm9vbGVhbih4KSB7XG4gIHJldHVybiB0eXBlb2YgeCA9PT0gJ2Jvb2xlYW4nIHx8IHggaW5zdGFuY2VvZiBCb29sZWFuO1xufVxuXG5mdW5jdGlvbiBpc19mdW5jdGlvbih4LCBhcml0eSA9IC0xKSB7XG4gIHJldHVybiB0eXBlb2YgeCA9PT0gJ2Z1bmN0aW9uJyB8fCB4IGluc3RhbmNlb2YgRnVuY3Rpb247XG59XG5cbmZ1bmN0aW9uIGlzX2Zsb2F0KHgpIHtcbiAgcmV0dXJuIGlzX251bWJlcih4KSAmJiAhTnVtYmVyLmlzSW50ZWdlcih4KTtcbn1cblxuZnVuY3Rpb24gaXNfaW50ZWdlcih4KSB7XG4gIHJldHVybiBOdW1iZXIuaXNJbnRlZ2VyKHgpO1xufVxuXG5mdW5jdGlvbiBpc19saXN0KHgpIHtcbiAgcmV0dXJuIHggaW5zdGFuY2VvZiBBcnJheTtcbn1cblxuZnVuY3Rpb24gaXNfbWFwKHgpIHtcbiAgcmV0dXJuIHR5cGVvZiB4ID09PSAnb2JqZWN0JyB8fCB4IGluc3RhbmNlb2YgT2JqZWN0O1xufVxuXG5mdW5jdGlvbiBpc19udW1iZXIoeCkge1xuICByZXR1cm4gdHlwZW9mIHggPT09ICdudW1iZXInO1xufVxuXG5mdW5jdGlvbiBpc190dXBsZSh4KSB7XG4gIHJldHVybiB4IGluc3RhbmNlb2YgVHVwbGUkMTtcbn1cblxuZnVuY3Rpb24gbGVuZ3RoKHgpIHtcbiAgcmV0dXJuIHgubGVuZ3RoO1xufVxuXG5mdW5jdGlvbiBpc19waWQoeCkge1xuICByZXR1cm4geCBpbnN0YW5jZW9mIFBJRDtcbn1cblxuZnVuY3Rpb24gaXNfcG9ydCh4KSB7XG4gIHJldHVybiBmYWxzZTtcbn1cblxuZnVuY3Rpb24gaXNfcmVmZXJlbmNlKHgpIHtcbiAgcmV0dXJuIGZhbHNlO1xufVxuXG5mdW5jdGlvbiBpc19iaXRzdHJpbmcoeCkge1xuICByZXR1cm4gaXNfYmluYXJ5KHgpIHx8IHggaW5zdGFuY2VvZiBCaXRTdHJpbmc7XG59XG5cbmZ1bmN0aW9uIF9faW5fXyhsZWZ0LCByaWdodCkge1xuICBmb3IgKGxldCB4IG9mIHJpZ2h0KSB7XG4gICAgaWYgKG1hdGNoX19xbWFya19fKGxlZnQsIHgpKSB7XG4gICAgICByZXR1cm4gdHJ1ZTtcbiAgICB9XG4gIH1cblxuICByZXR1cm4gZmFsc2U7XG59XG5cbmZ1bmN0aW9uIGFicyhudW1iZXIpIHtcbiAgcmV0dXJuIE1hdGguYWJzKG51bWJlcik7XG59XG5cbmZ1bmN0aW9uIHJvdW5kKG51bWJlcikge1xuICByZXR1cm4gTWF0aC5yb3VuZChudW1iZXIpO1xufVxuXG5mdW5jdGlvbiBlbGVtKHR1cGxlLCBpbmRleCkge1xuICBpZiAoaXNfbGlzdCh0dXBsZSkpIHtcbiAgICByZXR1cm4gdHVwbGVbaW5kZXhdO1xuICB9XG5cbiAgcmV0dXJuIHR1cGxlLmdldChpbmRleCk7XG59XG5cbmZ1bmN0aW9uIHJlbShsZWZ0LCByaWdodCkge1xuICByZXR1cm4gbGVmdCAlIHJpZ2h0O1xufVxuXG5mdW5jdGlvbiBkaXYobGVmdCwgcmlnaHQpIHtcbiAgcmV0dXJuIGxlZnQgLyByaWdodDtcbn1cblxuZnVuY3Rpb24gYW5kKGxlZnQsIHJpZ2h0KSB7XG4gIHJldHVybiBsZWZ0ICYmIHJpZ2h0O1xufVxuXG5mdW5jdGlvbiBvcihsZWZ0LCByaWdodCkge1xuICByZXR1cm4gbGVmdCB8fCByaWdodDtcbn1cblxuZnVuY3Rpb24gbm90KGFyZykge1xuICByZXR1cm4gIWFyZztcbn1cblxuZnVuY3Rpb24gYXBwbHkoLi4uYXJncykge1xuICBpZiAoYXJncy5sZW5ndGggPT09IDMpIHtcbiAgICBsZXQgbW9kID0gYXJnc1swXTtcbiAgICBsZXQgZnVuYyA9IGFyZ3NbMV07XG4gICAgbGV0IGZ1bmNfYXJncyA9IGFyZ3NbMl07XG4gICAgcmV0dXJuIG1vZFtmdW5jXS5hcHBseShudWxsLCBmdW5jX2FyZ3MpO1xuICB9IGVsc2Uge1xuICAgIGxldCBmdW5jID0gYXJnc1swXTtcbiAgICBsZXQgZnVuY19hcmdzID0gYXJnc1sxXTtcblxuICAgIHJldHVybiBmdW5jLmFwcGx5KG51bGwsIGZ1bmNfYXJncyk7XG4gIH1cbn1cblxuZnVuY3Rpb24gdG9fc3RyaW5nKGFyZykge1xuICBpZiAoaXNfdHVwbGUoYXJnKSkge1xuICAgIHJldHVybiBUdXBsZS50b19zdHJpbmcoYXJnKTtcbiAgfVxuXG4gIHJldHVybiBhcmcudG9TdHJpbmcoKTtcbn1cblxuZnVuY3Rpb24gbWF0Y2hfX3FtYXJrX18ocGF0dGVybiwgZXhwciwgZ3VhcmQgPSAoKSA9PiB0cnVlKSB7XG4gIHJldHVybiBQYXR0ZXJucy5tYXRjaF9ub190aHJvdyhwYXR0ZXJuLCBleHByLCBndWFyZCkgIT0gbnVsbDtcbn1cblxuZnVuY3Rpb24gZGVmc3RydWN0KGRlZmF1bHRzKSB7XG4gIHJldHVybiBjbGFzcyB7XG4gICAgY29uc3RydWN0b3IodXBkYXRlID0ge30pIHtcbiAgICAgIGxldCB0aGVfdmFsdWVzID0gT2JqZWN0LmFzc2lnbihkZWZhdWx0cywgdXBkYXRlKTtcbiAgICAgIE9iamVjdC5hc3NpZ24odGhpcywgdGhlX3ZhbHVlcyk7XG4gICAgfVxuXG4gICAgc3RhdGljIGNyZWF0ZSh1cGRhdGVzID0ge30pIHtcbiAgICAgIGxldCB4ID0gbmV3IHRoaXModXBkYXRlcyk7XG4gICAgICByZXR1cm4gT2JqZWN0LmZyZWV6ZSh4KTtcbiAgICB9XG4gIH07XG59XG5cbmZ1bmN0aW9uIGRlZnByb3RvY29sKHNwZWMpIHtcbiAgcmV0dXJuIG5ldyBQcm90b2NvbChzcGVjKTtcbn1cblxuZnVuY3Rpb24gZGVmaW1wbChwcm90b2NvbCwgdHlwZSwgaW1wbCkge1xuICBwcm90b2NvbC5pbXBsZW1lbnRhdGlvbih0eXBlLCBpbXBsKTtcbn1cblxudmFyIEtlcm5lbCA9IHtcbiAgU3BlY2lhbEZvcm1zLFxuICB0bCxcbiAgaGQsXG4gIGlzX25pbCxcbiAgaXNfYXRvbSxcbiAgaXNfYmluYXJ5LFxuICBpc19ib29sZWFuLFxuICBpc19mdW5jdGlvbixcbiAgaXNfZmxvYXQsXG4gIGlzX2ludGVnZXIsXG4gIGlzX2xpc3QsXG4gIGlzX21hcCxcbiAgaXNfbnVtYmVyLFxuICBpc190dXBsZSxcbiAgbGVuZ3RoLFxuICBpc19waWQsXG4gIGlzX3BvcnQsXG4gIGlzX3JlZmVyZW5jZSxcbiAgaXNfYml0c3RyaW5nLFxuICBpbjogX19pbl9fLFxuICBhYnMsXG4gIHJvdW5kLFxuICBlbGVtLFxuICByZW0sXG4gIGRpdixcbiAgYW5kLFxuICBvcixcbiAgbm90LFxuICBhcHBseSxcbiAgdG9fc3RyaW5nLFxuICBtYXRjaF9fcW1hcmtfXyxcbiAgZGVmc3RydWN0LFxuICBkZWZwcm90b2NvbCxcbiAgZGVmaW1wbFxufTtcblxubGV0IEF0b20gPSB7fTtcblxuQXRvbS50b19zdHJpbmcgPSBmdW5jdGlvbiAoYXRvbSkge1xuICByZXR1cm4gU3ltYm9sLmtleUZvcihhdG9tKTtcbn07XG5cbkF0b20udG9fY2hhcl9saXN0ID0gZnVuY3Rpb24gKGF0b20pIHtcbiAgcmV0dXJuIEF0b20udG9fc3RyaW5nKGF0b20pLnNwbGl0KCcnKTtcbn07XG5cbmxldCBJbnRlZ2VyID0ge1xuXG4gIGlzX2V2ZW46IGZ1bmN0aW9uIChuKSB7XG4gICAgcmV0dXJuIG4gJSAyID09PSAwO1xuICB9LFxuXG4gIGlzX29kZDogZnVuY3Rpb24gKG4pIHtcbiAgICByZXR1cm4gbiAlIDIgIT09IDA7XG4gIH0sXG5cbiAgcGFyc2U6IGZ1bmN0aW9uIChiaW4pIHtcbiAgICBsZXQgcmVzdWx0ID0gcGFyc2VJbnQoYmluKTtcblxuICAgIGlmIChpc05hTihyZXN1bHQpKSB7XG4gICAgICByZXR1cm4gS2VybmVsLlNwZWNpYWxGb3Jtcy5hdG9tKFwiZXJyb3JcIik7XG4gICAgfVxuXG4gICAgbGV0IGluZGV4T2ZEb3QgPSBiaW4uaW5kZXhPZihcIi5cIik7XG5cbiAgICBpZiAoaW5kZXhPZkRvdCA+PSAwKSB7XG4gICAgICByZXR1cm4gS2VybmVsLlNwZWNpYWxGb3Jtcy50dXBsZShyZXN1bHQsIGJpbi5zdWJzdHJpbmcoaW5kZXhPZkRvdCkpO1xuICAgIH1cblxuICAgIHJldHVybiBLZXJuZWwuU3BlY2lhbEZvcm1zLnR1cGxlKHJlc3VsdCwgXCJcIik7XG4gIH0sXG5cbiAgdG9fY2hhcl9saXN0OiBmdW5jdGlvbiAobnVtYmVyLCBiYXNlID0gMTApIHtcbiAgICByZXR1cm4gbnVtYmVyLnRvU3RyaW5nKGJhc2UpLnNwbGl0KFwiXCIpO1xuICB9LFxuXG4gIHRvX3N0cmluZzogZnVuY3Rpb24gKG51bWJlciwgYmFzZSA9IDEwKSB7XG4gICAgcmV0dXJuIG51bWJlci50b1N0cmluZyhiYXNlKTtcbiAgfVxufTtcblxubGV0IENoYXJzJDEgPSBLZXJuZWwuZGVmcHJvdG9jb2woe1xuICB0b19zdHJpbmc6IGZ1bmN0aW9uICh0aGluZykge31cbn0pO1xuXG5LZXJuZWwuZGVmaW1wbChDaGFycyQxLCBCaXRTdHJpbmcsIHtcbiAgdG9fc3RyaW5nOiBmdW5jdGlvbiAodGhpbmcpIHtcbiAgICBpZiAoS2VybmVsLmlzX2JpbmFyeSh0aGluZykpIHtcbiAgICAgIHJldHVybiB0aGluZztcbiAgICB9XG5cbiAgICByZXR1cm4gdGhpbmcudG9TdHJpbmcoKTtcbiAgfVxufSk7XG5cbktlcm5lbC5kZWZpbXBsKENoYXJzJDEsIFN5bWJvbCwge1xuICB0b19zdHJpbmc6IGZ1bmN0aW9uICh0aGluZykge1xuICAgIGlmIChuaWwpIHtcbiAgICAgIHJldHVybiBcIlwiO1xuICAgIH1cblxuICAgIHJldHVybiBBdG9tLnRvX3N0cmluZyh0aGluZyk7XG4gIH1cbn0pO1xuXG5LZXJuZWwuZGVmaW1wbChDaGFycyQxLCBJbnRlZ2VyJDEsIHtcbiAgdG9fc3RyaW5nOiBmdW5jdGlvbiAodGhpbmcpIHtcbiAgICByZXR1cm4gSW50ZWdlci50b19zdHJpbmcodGhpbmcpO1xuICB9XG59KTtcblxuS2VybmVsLmRlZmltcGwoQ2hhcnMkMSwgRmxvYXQsIHtcbiAgdG9fc3RyaW5nOiBmdW5jdGlvbiAodGhpbmcpIHtcbiAgICByZXR1cm4gdGhpbmcudG9TdHJpbmc7XG4gIH1cbn0pO1xuXG5LZXJuZWwuZGVmaW1wbChDaGFycyQxLCBBcnJheSwge1xuICB0b19zdHJpbmc6IGZ1bmN0aW9uICh0aGluZykge1xuICAgIHJldHVybiB0aGluZy50b1N0cmluZygpO1xuICB9XG59KTtcblxuS2VybmVsLmRlZmltcGwoQ2hhcnMkMSwgVHVwbGUkMSwge1xuICB0b19zdHJpbmc6IGZ1bmN0aW9uICh0aGluZykge1xuICAgIHJldHVybiBUdXBsZS50b19zdHJpbmcodGhpbmcpO1xuICB9XG59KTtcblxuS2VybmVsLmRlZmltcGwoQ2hhcnMkMSwgbnVsbCwge1xuICB0b19zdHJpbmc6IGZ1bmN0aW9uICh0aGluZykge1xuICAgIHJldHVybiB0aGluZy50b1N0cmluZygpO1xuICB9XG59KTtcblxuZnVuY3Rpb24gdG9fYXRvbShzdHJpbmcpIHtcbiAgcmV0dXJuIFN5bWJvbC5mb3Ioc3RyaW5nKTtcbn1cblxuZnVuY3Rpb24gdG9fZXhpc3RpbmdfYXRvbShzdHJpbmcpIHtcbiAgcmV0dXJuIFN5bWJvbC5mb3Ioc3RyaW5nKTtcbn1cblxuZnVuY3Rpb24gdG9fY2hhcl9saXN0KHN0cmluZykge1xuICByZXR1cm4gc3RyaW5nLnNwbGl0KCcnKTtcbn1cblxuZnVuY3Rpb24gdG9fZmxvYXQoc3RyaW5nKSB7XG4gIHJldHVybiBwYXJzZUZsb2F0KHN0cmluZyk7XG59XG5cbmZ1bmN0aW9uIHRvX2ludGVnZXIoc3RyaW5nLCBiYXNlID0gMTApIHtcbiAgcmV0dXJuIHBhcnNlSW50KHN0cmluZywgYmFzZSk7XG59XG5cbmZ1bmN0aW9uIHVwY2FzZShiaW5hcnkpIHtcbiAgcmV0dXJuIGJpbmFyeS50b1VwcGVyQ2FzZSgpO1xufVxuXG5mdW5jdGlvbiBkb3duY2FzZShiaW5hcnkpIHtcbiAgcmV0dXJuIGJpbmFyeS50b0xvd2VyQ2FzZSgpO1xufVxuXG5mdW5jdGlvbiBhdChzdHJpbmcsIHBvc2l0aW9uKSB7XG4gIGlmIChwb3NpdGlvbiA+IHN0cmluZy5sZW5ndGggLSAxKSB7XG4gICAgcmV0dXJuIG51bGw7XG4gIH1cblxuICByZXR1cm4gc3RyaW5nW3Bvc2l0aW9uXTtcbn1cblxuZnVuY3Rpb24gY2FwaXRhbGl6ZShzdHJpbmcpIHtcbiAgbGV0IHJldHVyblN0cmluZyA9ICcnO1xuXG4gIGZvciAobGV0IGkgPSAwOyBpIDwgc3RyaW5nLmxlbmd0aDsgaSsrKSB7XG4gICAgaWYgKGkgPT09IDApIHtcbiAgICAgIHJldHVyblN0cmluZyA9IHJldHVyblN0cmluZyArIHN0cmluZ1tpXS50b1VwcGVyQ2FzZSgpO1xuICAgIH0gZWxzZSB7XG4gICAgICByZXR1cm5TdHJpbmcgPSByZXR1cm5TdHJpbmcgKyBzdHJpbmdbaV0udG9Mb3dlckNhc2UoKTtcbiAgICB9XG4gIH1cblxuICByZXR1cm4gcmV0dXJuU3RyaW5nO1xufVxuXG5mdW5jdGlvbiBjb2RlcG9pbnRzKHN0cmluZykge1xuICByZXR1cm4gdG9fY2hhcl9saXN0KHN0cmluZykubWFwKGZ1bmN0aW9uIChjKSB7XG4gICAgcmV0dXJuIGMuY29kZVBvaW50QXQoMCk7XG4gIH0pO1xufVxuXG5mdW5jdGlvbiBjb250YWluc19fcW1fXyhzdHJpbmcsIGNvbnRhaW5zKSB7XG4gIGlmIChBcnJheS5pc0FycmF5KGNvbnRhaW5zKSkge1xuICAgIHJldHVybiBjb250YWlucy5zb21lKGZ1bmN0aW9uIChzKSB7XG4gICAgICByZXR1cm4gc3RyaW5nLmluZGV4T2YocykgPiAtMTtcbiAgICB9KTtcbiAgfVxuXG4gIHJldHVybiBzdHJpbmcuaW5kZXhPZihjb250YWlucykgPiAtMTtcbn1cblxuZnVuY3Rpb24gZHVwbGljYXRlJDEoc3ViamVjdCwgbikge1xuICByZXR1cm4gc3ViamVjdC5yZXBlYXQobik7XG59XG5cbmZ1bmN0aW9uIGVuZHNfd2l0aF9fcW1fXyhzdHJpbmcsIHN1ZmZpeGVzKSB7XG4gIGlmIChBcnJheS5pc0FycmF5KHN1ZmZpeGVzKSkge1xuICAgIHJldHVybiBzdWZmaXhlcy5zb21lKGZ1bmN0aW9uIChzKSB7XG4gICAgICByZXR1cm4gc3RyaW5nLmVuZHNXaXRoKHMpO1xuICAgIH0pO1xuICB9XG5cbiAgcmV0dXJuIHN0cmluZy5lbmRzV2l0aChzdWZmaXhlcyk7XG59XG5cbmZ1bmN0aW9uIGZpcnN0KHN0cmluZykge1xuICBpZiAoIXN0cmluZykge1xuICAgIHJldHVybiBudWxsO1xuICB9XG5cbiAgcmV0dXJuIHN0cmluZ1swXTtcbn1cblxuZnVuY3Rpb24gZ3JhcGhlbWVzKHN0cmluZykge1xuICByZXR1cm4gc3RyaW5nLnNwbGl0KCcnKTtcbn1cblxuZnVuY3Rpb24gbGFzdChzdHJpbmcpIHtcbiAgaWYgKCFzdHJpbmcpIHtcbiAgICByZXR1cm4gbnVsbDtcbiAgfVxuXG4gIHJldHVybiBzdHJpbmdbc3RyaW5nLmxlbmd0aCAtIDFdO1xufVxuXG5mdW5jdGlvbiBsZW5ndGgkMShzdHJpbmcpIHtcbiAgcmV0dXJuIHN0cmluZy5sZW5ndGg7XG59XG5cbmZ1bmN0aW9uIG1hdGNoX19xbV9fKHN0cmluZywgcmVnZXgpIHtcbiAgcmV0dXJuIHN0cmluZy5tYXRjaChyZWdleCkgIT0gbnVsbDtcbn1cblxuZnVuY3Rpb24gbmV4dF9jb2RlcG9pbnQoc3RyaW5nKSB7XG4gIGlmICghc3RyaW5nIHx8IHN0cmluZyA9PT0gJycpIHtcbiAgICByZXR1cm4gbnVsbDtcbiAgfVxuXG4gIHJldHVybiBLZXJuZWwuU3BlY2lhbEZvcm1zLnR1cGxlKHN0cmluZ1swXS5jb2RlUG9pbnRBdCgwKSwgc3RyaW5nLnN1YnN0cigxKSk7XG59XG5cbmZ1bmN0aW9uIG5leHRfZ3JhcGhlbWUoc3RyaW5nKSB7XG4gIGlmICghc3RyaW5nIHx8IHN0cmluZyA9PT0gJycpIHtcbiAgICByZXR1cm4gbnVsbDtcbiAgfVxuXG4gIHJldHVybiBLZXJuZWwuU3BlY2lhbEZvcm1zLnR1cGxlKHN0cmluZ1swXSwgc3RyaW5nLnN1YnN0cigxKSk7XG59XG5cbmZ1bmN0aW9uIHJldmVyc2Uoc3RyaW5nKSB7XG4gIGxldCByZXR1cm5WYWx1ZSA9ICcnO1xuXG4gIGZvciAodmFyIGkgPSBzdHJpbmcubGVuZ3RoIC0gMTsgaSA+PSAwOyBpLS0pIHtcbiAgICByZXR1cm5WYWx1ZSA9IHJldHVyblZhbHVlICsgc3RyaW5nW2ldO1xuICB9O1xuXG4gIHJldHVybiByZXR1cm5WYWx1ZTtcbn1cblxuZnVuY3Rpb24gc3BsaXQoc3RyaW5nKSB7XG4gIHJldHVybiBzdHJpbmcuc3BsaXQoKTtcbn1cblxuZnVuY3Rpb24gc3RhcnRzX3dpdGhfX3FtX18oc3RyaW5nLCBwcmVmaXhlcykge1xuICBpZiAoQXJyYXkuaXNBcnJheShwcmVmaXhlcykpIHtcbiAgICByZXR1cm4gcHJlZml4ZXMuc29tZShmdW5jdGlvbiAocykge1xuICAgICAgcmV0dXJuIHN0cmluZy5zdGFydHNXaXRoKHMpO1xuICAgIH0pO1xuICB9XG5cbiAgcmV0dXJuIHN0cmluZy5zdGFydHNXaXRoKHByZWZpeGVzKTtcbn1cblxuZnVuY3Rpb24gdmFsaWRfY2hhcmFjdGVyX19xbV9fKGNvZGVwb2ludCkge1xuICB0cnkge1xuICAgIHJldHVybiBTdHJpbmcuZnJvbUNvZGVQb2ludChjb2RlcG9pbnQpICE9IG51bGw7XG4gIH0gY2F0Y2ggKGUpIHtcbiAgICByZXR1cm4gZmFsc2U7XG4gIH1cbn1cblxudmFyIFN0cmluZyQxID0ge1xuICBhdCxcbiAgY2FwaXRhbGl6ZSxcbiAgY29kZXBvaW50cyxcbiAgY29udGFpbnNfX3FtX18sXG4gIGRvd25jYXNlLFxuICBkdXBsaWNhdGU6IGR1cGxpY2F0ZSQxLFxuICBlbmRzX3dpdGhfX3FtX18sXG4gIGZpcnN0LFxuICBncmFwaGVtZXMsXG4gIGxhc3QsXG4gIGxlbmd0aDogbGVuZ3RoJDEsXG4gIG1hdGNoX19xbV9fLFxuICBuZXh0X2NvZGVwb2ludCxcbiAgbmV4dF9ncmFwaGVtZSxcbiAgcmV2ZXJzZSxcbiAgc3BsaXQsXG4gIHN0YXJ0c193aXRoX19xbV9fLFxuICB0b19hdG9tLFxuICB0b19jaGFyX2xpc3QsXG4gIHRvX2V4aXN0aW5nX2F0b20sXG4gIHRvX2Zsb2F0LFxuICB0b19pbnRlZ2VyLFxuICB1cGNhc2UsXG4gIHZhbGlkX2NoYXJhY3Rlcl9fcW1fXyxcbiAgQ2hhcnM6IENoYXJzJDFcbn07XG5cbmxldCBDaGFycyA9IEtlcm5lbC5kZWZwcm90b2NvbCh7XG4gIHRvX2NoYXJfbGlzdDogZnVuY3Rpb24gKHRoaW5nKSB7fVxufSk7XG5cbktlcm5lbC5kZWZpbXBsKENoYXJzLCBCaXRTdHJpbmcsIHtcbiAgdG9fY2hhcl9saXN0OiBmdW5jdGlvbiAodGhpbmcpIHtcbiAgICBpZiAoS2VybmVsLmlzX2JpbmFyeSh0aGluZykpIHtcbiAgICAgIHJldHVybiBTdHJpbmckMS50b19jaGFyX2xpc3QodGhpbmcpO1xuICAgIH1cblxuICAgIHJldHVybiB0aGluZy50b1N0cmluZygpO1xuICB9XG59KTtcblxuS2VybmVsLmRlZmltcGwoQ2hhcnMsIFN5bWJvbCwge1xuICB0b19jaGFyX2xpc3Q6IGZ1bmN0aW9uICh0aGluZykge1xuICAgIHJldHVybiBBdG9tLnRvX2NoYXJfbGlzdCh0aGluZyk7XG4gIH1cbn0pO1xuXG5LZXJuZWwuZGVmaW1wbChDaGFycywgSW50ZWdlciQxLCB7XG4gIHRvX2NoYXJfbGlzdDogZnVuY3Rpb24gKHRoaW5nKSB7XG4gICAgcmV0dXJuIEludGVnZXIudG9fY2hhcl9saXN0KHRoaW5nKTtcbiAgfVxufSk7XG5cbktlcm5lbC5kZWZpbXBsKENoYXJzLCBBcnJheSwge1xuICB0b19jaGFyX2xpc3Q6IGZ1bmN0aW9uICh0aGluZykge1xuICAgIHJldHVybiB0aGluZztcbiAgfVxufSk7XG5cbmxldCBMaXN0ID0ge307XG5cbkxpc3QuQ2hhcnMgPSBDaGFycztcblxuTGlzdC5kZWxldGUgPSBmdW5jdGlvbiAobGlzdCwgaXRlbSkge1xuICBsZXQgbmV3X3ZhbHVlID0gW107XG4gIGxldCB2YWx1ZV9mb3VuZCA9IGZhbHNlO1xuXG4gIGZvciAobGV0IHggb2YgbGlzdCkge1xuICAgIGlmICh4ID09PSBpdGVtICYmIHZhbHVlX2ZvdW5kICE9PSBmYWxzZSkge1xuICAgICAgbmV3X3ZhbHVlLnB1c2goeCk7XG4gICAgICB2YWx1ZV9mb3VuZCA9IHRydWU7XG4gICAgfSBlbHNlIGlmICh4ICE9PSBpdGVtKSB7XG4gICAgICBuZXdfdmFsdWUucHVzaCh4KTtcbiAgICB9XG4gIH1cblxuICByZXR1cm4gS2VybmVsLlNwZWNpYWxGb3Jtcy5saXN0KC4uLm5ld192YWx1ZSk7XG59O1xuXG5MaXN0LmRlbGV0ZV9hdCA9IGZ1bmN0aW9uIChsaXN0LCBpbmRleCkge1xuICBsZXQgbmV3X3ZhbHVlID0gW107XG5cbiAgZm9yIChsZXQgaSA9IDA7IGkgPCBsaXN0Lmxlbmd0aDsgaSsrKSB7XG4gICAgaWYgKGkgIT09IGluZGV4KSB7XG4gICAgICBuZXdfdmFsdWUucHVzaChsaXN0W2ldKTtcbiAgICB9XG4gIH1cblxuICByZXR1cm4gS2VybmVsLlNwZWNpYWxGb3Jtcy5saXN0KC4uLm5ld192YWx1ZSk7XG59O1xuXG5MaXN0LmR1cGxpY2F0ZSA9IGZ1bmN0aW9uIChlbGVtLCBuKSB7XG4gIGxldCBuZXdfdmFsdWUgPSBbXTtcblxuICBmb3IgKHZhciBpID0gMDsgaSA8IG47IGkrKykge1xuICAgIG5ld192YWx1ZS5wdXNoKGVsZW0pO1xuICB9XG5cbiAgcmV0dXJuIEtlcm5lbC5TcGVjaWFsRm9ybXMubGlzdCguLi5uZXdfdmFsdWUpO1xufTtcblxuTGlzdC5maXJzdCA9IGZ1bmN0aW9uIChsaXN0KSB7XG4gIHJldHVybiBsaXN0WzBdO1xufTtcblxuTGlzdC5mbGF0dGVuID0gZnVuY3Rpb24gKGxpc3QsIHRhaWwgPSBLZXJuZWwuU3BlY2lhbEZvcm1zLmxpc3QoKSkge1xuICBsZXQgbmV3X3ZhbHVlID0gW107XG5cbiAgZm9yIChsZXQgeCBvZiBsaXN0KSB7XG4gICAgaWYgKEtlcm5lbC5pc19saXN0KHgpKSB7XG4gICAgICBuZXdfdmFsdWUgPSBuZXdfdmFsdWUuY29uY2F0KExpc3QuZmxhdHRlbih4KSk7XG4gICAgfSBlbHNlIHtcbiAgICAgIG5ld192YWx1ZS5wdXNoKHgpO1xuICAgIH1cbiAgfVxuXG4gIG5ld192YWx1ZSA9IG5ld192YWx1ZS5jb25jYXQodGFpbCk7XG5cbiAgcmV0dXJuIEtlcm5lbC5TcGVjaWFsRm9ybXMubGlzdCguLi5uZXdfdmFsdWUpO1xufTtcblxuTGlzdC5mb2xkbCA9IGZ1bmN0aW9uIChsaXN0LCBhY2MsIGZ1bmMpIHtcbiAgcmV0dXJuIGxpc3QucmVkdWNlKGZ1bmMsIGFjYyk7XG59O1xuXG5MaXN0LmZvbGRyID0gZnVuY3Rpb24gKGxpc3QsIGFjYywgZnVuYykge1xuICBsZXQgbmV3X2FjYyA9IGFjYztcblxuICBmb3IgKHZhciBpID0gbGlzdC5sZW5ndGggLSAxOyBpID49IDA7IGktLSkge1xuICAgIG5ld19hY2MgPSBmdW5jKGxpc3RbaV0sIG5ld19hY2MpO1xuICB9XG5cbiAgcmV0dXJuIG5ld19hY2M7XG59O1xuXG5MaXN0Lmluc2VydF9hdCA9IGZ1bmN0aW9uIChsaXN0LCBpbmRleCwgdmFsdWUpIHtcbiAgbGV0IG5ld192YWx1ZSA9IFtdO1xuXG4gIGZvciAobGV0IGkgPSAwOyBpIDwgbGlzdC5sZW5ndGg7IGkrKykge1xuICAgIGlmIChpID09PSBpbmRleCkge1xuICAgICAgbmV3X3ZhbHVlLnB1c2godmFsdWUpO1xuICAgICAgbmV3X3ZhbHVlLnB1c2gobGlzdFtpXSk7XG4gICAgfSBlbHNlIHtcbiAgICAgIG5ld192YWx1ZS5wdXNoKGxpc3RbaV0pO1xuICAgIH1cbiAgfVxuXG4gIHJldHVybiBLZXJuZWwuU3BlY2lhbEZvcm1zLmxpc3QoLi4ubmV3X3ZhbHVlKTtcbn07XG5cbkxpc3Qua2V5ZGVsZXRlID0gZnVuY3Rpb24gKGxpc3QsIGtleSwgcG9zaXRpb24pIHtcbiAgbGV0IG5ld19saXN0ID0gW107XG5cbiAgZm9yIChsZXQgaSA9IDA7IGkgPCBsaXN0Lmxlbmd0aDsgaSsrKSB7XG4gICAgaWYgKCFLZXJuZWwubWF0Y2hfX3FtYXJrX18obGlzdFtpXVtwb3NpdGlvbl0sIGtleSkpIHtcbiAgICAgIG5ld19saXN0LnB1c2gobGlzdFtpXSk7XG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIEtlcm5lbC5TcGVjaWFsRm9ybXMubGlzdCguLi5uZXdfbGlzdCk7XG59O1xuXG5MaXN0LmtleWZpbmQgPSBmdW5jdGlvbiAobGlzdCwga2V5LCBwb3NpdGlvbiwgX2RlZmF1bHQgPSBudWxsKSB7XG5cbiAgZm9yIChsZXQgaSA9IDA7IGkgPCBsaXN0Lmxlbmd0aDsgaSsrKSB7XG4gICAgaWYgKEtlcm5lbC5tYXRjaF9fcW1hcmtfXyhsaXN0W2ldW3Bvc2l0aW9uXSwga2V5KSkge1xuICAgICAgcmV0dXJuIGxpc3RbaV07XG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIF9kZWZhdWx0O1xufTtcblxuTGlzdC5rZXltZW1iZXJfX3FtYXJrX18gPSBmdW5jdGlvbiAobGlzdCwga2V5LCBwb3NpdGlvbikge1xuXG4gIGZvciAobGV0IGkgPSAwOyBpIDwgbGlzdC5sZW5ndGg7IGkrKykge1xuICAgIGlmIChLZXJuZWwubWF0Y2hfX3FtYXJrX18obGlzdFtpXVtwb3NpdGlvbl0sIGtleSkpIHtcbiAgICAgIHJldHVybiB0cnVlO1xuICAgIH1cbiAgfVxuXG4gIHJldHVybiBmYWxzZTtcbn07XG5cbkxpc3Qua2V5cmVwbGFjZSA9IGZ1bmN0aW9uIChsaXN0LCBrZXksIHBvc2l0aW9uLCBuZXdfdHVwbGUpIHtcbiAgbGV0IG5ld19saXN0ID0gW107XG5cbiAgZm9yIChsZXQgaSA9IDA7IGkgPCBsaXN0Lmxlbmd0aDsgaSsrKSB7XG4gICAgaWYgKCFLZXJuZWwubWF0Y2hfX3FtYXJrX18obGlzdFtpXVtwb3NpdGlvbl0sIGtleSkpIHtcbiAgICAgIG5ld19saXN0LnB1c2gobGlzdFtpXSk7XG4gICAgfSBlbHNlIHtcbiAgICAgIG5ld19saXN0LnB1c2gobmV3X3R1cGxlKTtcbiAgICB9XG4gIH1cblxuICByZXR1cm4gS2VybmVsLlNwZWNpYWxGb3Jtcy5saXN0KC4uLm5ld19saXN0KTtcbn07XG5cbkxpc3Qua2V5c29ydCA9IGZ1bmN0aW9uIChsaXN0LCBwb3NpdGlvbikge1xuICBsZXQgbmV3X2xpc3QgPSBsaXN0O1xuXG4gIG5ld19saXN0LnNvcnQoZnVuY3Rpb24gKGEsIGIpIHtcbiAgICBpZiAocG9zaXRpb24gPT09IDApIHtcbiAgICAgIGlmIChhW3Bvc2l0aW9uXS52YWx1ZSA8IGJbcG9zaXRpb25dLnZhbHVlKSB7XG4gICAgICAgIHJldHVybiAtMTtcbiAgICAgIH1cblxuICAgICAgaWYgKGFbcG9zaXRpb25dLnZhbHVlID4gYltwb3NpdGlvbl0udmFsdWUpIHtcbiAgICAgICAgcmV0dXJuIDE7XG4gICAgICB9XG5cbiAgICAgIHJldHVybiAwO1xuICAgIH0gZWxzZSB7XG4gICAgICBpZiAoYVtwb3NpdGlvbl0gPCBiW3Bvc2l0aW9uXSkge1xuICAgICAgICByZXR1cm4gLTE7XG4gICAgICB9XG5cbiAgICAgIGlmIChhW3Bvc2l0aW9uXSA+IGJbcG9zaXRpb25dKSB7XG4gICAgICAgIHJldHVybiAxO1xuICAgICAgfVxuXG4gICAgICByZXR1cm4gMDtcbiAgICB9XG4gIH0pO1xuXG4gIHJldHVybiBLZXJuZWwuU3BlY2lhbEZvcm1zLmxpc3QoLi4ubmV3X2xpc3QpO1xufTtcblxuTGlzdC5rZXlzdG9yZSA9IGZ1bmN0aW9uIChsaXN0LCBrZXksIHBvc2l0aW9uLCBuZXdfdHVwbGUpIHtcbiAgbGV0IG5ld19saXN0ID0gW107XG4gIGxldCByZXBsYWNlZCA9IGZhbHNlO1xuXG4gIGZvciAobGV0IGkgPSAwOyBpIDwgbGlzdC5sZW5ndGg7IGkrKykge1xuICAgIGlmICghS2VybmVsLm1hdGNoX19xbWFya19fKGxpc3RbaV1bcG9zaXRpb25dLCBrZXkpKSB7XG4gICAgICBuZXdfbGlzdC5wdXNoKGxpc3RbaV0pO1xuICAgIH0gZWxzZSB7XG4gICAgICBuZXdfbGlzdC5wdXNoKG5ld190dXBsZSk7XG4gICAgICByZXBsYWNlZCA9IHRydWU7XG4gICAgfVxuICB9XG5cbiAgaWYgKCFyZXBsYWNlZCkge1xuICAgIG5ld19saXN0LnB1c2gobmV3X3R1cGxlKTtcbiAgfVxuXG4gIHJldHVybiBLZXJuZWwuU3BlY2lhbEZvcm1zLmxpc3QoLi4ubmV3X2xpc3QpO1xufTtcblxuTGlzdC5sYXN0ID0gZnVuY3Rpb24gKGxpc3QpIHtcbiAgcmV0dXJuIGxpc3RbbGlzdC5sZW5ndGggLSAxXTtcbn07XG5cbkxpc3QucmVwbGFjZV9hdCA9IGZ1bmN0aW9uIChsaXN0LCBpbmRleCwgdmFsdWUpIHtcbiAgbGV0IG5ld192YWx1ZSA9IFtdO1xuXG4gIGZvciAobGV0IGkgPSAwOyBpIDwgbGlzdC5sZW5ndGg7IGkrKykge1xuICAgIGlmIChpID09PSBpbmRleCkge1xuICAgICAgbmV3X3ZhbHVlLnB1c2godmFsdWUpO1xuICAgIH0gZWxzZSB7XG4gICAgICBuZXdfdmFsdWUucHVzaChsaXN0W2ldKTtcbiAgICB9XG4gIH1cblxuICByZXR1cm4gS2VybmVsLlNwZWNpYWxGb3Jtcy5saXN0KC4uLm5ld192YWx1ZSk7XG59O1xuXG5MaXN0LnVwZGF0ZV9hdCA9IGZ1bmN0aW9uIChsaXN0LCBpbmRleCwgZnVuKSB7XG4gIGxldCBuZXdfdmFsdWUgPSBbXTtcblxuICBmb3IgKGxldCBpID0gMDsgaSA8IGxpc3QuY291bnQoKTsgaSsrKSB7XG4gICAgaWYgKGkgPT09IGluZGV4KSB7XG4gICAgICBuZXdfdmFsdWUucHVzaChmdW4obGlzdC5nZXQoaSkpKTtcbiAgICB9IGVsc2Uge1xuICAgICAgbmV3X3ZhbHVlLnB1c2gobGlzdC5nZXQoaSkpO1xuICAgIH1cbiAgfVxuXG4gIHJldHVybiBuZXdfdmFsdWU7XG59O1xuXG5MaXN0LndyYXAgPSBmdW5jdGlvbiAobGlzdCkge1xuICBpZiAoS2VybmVsLmlzX2xpc3QobGlzdCkpIHtcbiAgICByZXR1cm4gbGlzdDtcbiAgfSBlbHNlIGlmIChsaXN0ID09IG51bGwpIHtcbiAgICByZXR1cm4gS2VybmVsLlNwZWNpYWxGb3Jtcy5saXN0KCk7XG4gIH0gZWxzZSB7XG4gICAgcmV0dXJuIEtlcm5lbC5TcGVjaWFsRm9ybXMubGlzdChsaXN0KTtcbiAgfVxufTtcblxuTGlzdC56aXAgPSBmdW5jdGlvbiAobGlzdF9vZl9saXN0cykge1xuICBpZiAobGlzdF9vZl9saXN0cy5sZW5ndGggPT09IDApIHtcbiAgICByZXR1cm4gS2VybmVsLlNwZWNpYWxGb3Jtcy5saXN0KCk7XG4gIH1cblxuICBsZXQgbmV3X3ZhbHVlID0gW107XG4gIGxldCBzbWFsbGVzdF9sZW5ndGggPSBsaXN0X29mX2xpc3RzWzBdO1xuXG4gIGZvciAobGV0IHggb2YgbGlzdF9vZl9saXN0cykge1xuICAgIGlmICh4Lmxlbmd0aCA8IHNtYWxsZXN0X2xlbmd0aCkge1xuICAgICAgc21hbGxlc3RfbGVuZ3RoID0geC5sZW5ndGg7XG4gICAgfVxuICB9XG5cbiAgZm9yIChsZXQgaSA9IDA7IGkgPCBzbWFsbGVzdF9sZW5ndGg7IGkrKykge1xuICAgIGxldCBjdXJyZW50X3ZhbHVlID0gW107XG4gICAgZm9yIChsZXQgaiA9IDA7IGogPCBsaXN0X29mX2xpc3RzLmxlbmd0aDsgaisrKSB7XG4gICAgICBjdXJyZW50X3ZhbHVlLnB1c2gobGlzdF9vZl9saXN0c1tqXVtpXSk7XG4gICAgfVxuXG4gICAgbmV3X3ZhbHVlLnB1c2goS2VybmVsLlNwZWNpYWxGb3Jtcy50dXBsZSguLi5jdXJyZW50X3ZhbHVlKSk7XG4gIH1cblxuICByZXR1cm4gS2VybmVsLlNwZWNpYWxGb3Jtcy5saXN0KC4uLm5ld192YWx1ZSk7XG59O1xuXG5MaXN0LnRvX3R1cGxlID0gZnVuY3Rpb24gKGxpc3QpIHtcbiAgcmV0dXJuIEtlcm5lbC5TcGVjaWFsRm9ybXMudHVwbGUuYXBwbHkobnVsbCwgbGlzdCk7XG59O1xuXG5MaXN0LmFwcGVuZCA9IGZ1bmN0aW9uIChsaXN0LCB2YWx1ZSkge1xuICByZXR1cm4gS2VybmVsLlNwZWNpYWxGb3Jtcy5saXN0KC4uLmxpc3QuY29uY2F0KFt2YWx1ZV0pKTtcbn07XG5cbkxpc3QucHJlcGVuZCA9IGZ1bmN0aW9uIChsaXN0LCB2YWx1ZSkge1xuICByZXR1cm4gS2VybmVsLlNwZWNpYWxGb3Jtcy5saXN0KC4uLlt2YWx1ZV0uY29uY2F0KGxpc3QpKTtcbn07XG5cbkxpc3QuY29uY2F0ID0gZnVuY3Rpb24gKGxlZnQsIHJpZ2h0KSB7XG4gIHJldHVybiBsZWZ0LmNvbmNhdChyaWdodCk7XG59O1xuXG5sZXQgUmFuZ2UgPSBmdW5jdGlvbiAoX2ZpcnN0LCBfbGFzdCkge1xuICBpZiAoISh0aGlzIGluc3RhbmNlb2YgUmFuZ2UpKSB7XG4gICAgcmV0dXJuIG5ldyBSYW5nZShfZmlyc3QsIF9sYXN0KTtcbiAgfVxuXG4gIHRoaXMuZmlyc3QgPSBmdW5jdGlvbiAoKSB7XG4gICAgcmV0dXJuIF9maXJzdDtcbiAgfTtcblxuICB0aGlzLmxhc3QgPSBmdW5jdGlvbiAoKSB7XG4gICAgcmV0dXJuIF9sYXN0O1xuICB9O1xuXG4gIGxldCBfcmFuZ2UgPSBbXTtcblxuICBmb3IgKGxldCBpID0gX2ZpcnN0OyBpIDw9IF9sYXN0OyBpKyspIHtcbiAgICBfcmFuZ2UucHVzaChpKTtcbiAgfVxuXG4gIF9yYW5nZSA9IE9iamVjdC5mcmVlemUoX3JhbmdlKTtcblxuICB0aGlzLnZhbHVlID0gZnVuY3Rpb24gKCkge1xuICAgIHJldHVybiBfcmFuZ2U7XG4gIH07XG5cbiAgdGhpcy5sZW5ndGggPSBmdW5jdGlvbiAoKSB7XG4gICAgcmV0dXJuIF9yYW5nZS5sZW5ndGg7XG4gIH07XG5cbiAgcmV0dXJuIHRoaXM7XG59O1xuXG5SYW5nZS5wcm90b3R5cGVbU3ltYm9sLml0ZXJhdG9yXSA9IGZ1bmN0aW9uICgpIHtcbiAgcmV0dXJuIHRoaXMudmFsdWUoKVtTeW1ib2wuaXRlcmF0b3JdKCk7XG59O1xuXG5SYW5nZS5uZXcgPSBmdW5jdGlvbiAoZmlyc3QsIGxhc3QpIHtcbiAgcmV0dXJuIFJhbmdlKGZpcnN0LCBsYXN0KTtcbn07XG5cblJhbmdlLnJhbmdlX19xbWFya19fID0gZnVuY3Rpb24gKHJhbmdlKSB7XG4gIHJldHVybiByYW5nZSBpbnN0YW5jZW9mIFJhbmdlO1xufTtcblxubGV0IEtleXdvcmQgPSB7fTtcblxuS2V5d29yZC5oYXNfa2V5X19xbV9fID0gZnVuY3Rpb24gKGtleXdvcmRzLCBrZXkpIHtcbiAgZm9yIChsZXQga2V5d29yZCBvZiBrZXl3b3Jkcykge1xuICAgIGlmIChLZXJuZWwuZWxlbShrZXl3b3JkLCAwKSA9PSBrZXkpIHtcbiAgICAgIHJldHVybiB0cnVlO1xuICAgIH1cbiAgfVxuXG4gIHJldHVybiBmYWxzZTtcbn07XG5cbktleXdvcmQuZ2V0ID0gZnVuY3Rpb24gKGtleXdvcmRzLCBrZXksIHRoZV9kZWZhdWx0ID0gbnVsbCkge1xuICBmb3IgKGxldCBrZXl3b3JkIG9mIGtleXdvcmRzKSB7XG4gICAgaWYgKEtlcm5lbC5lbGVtKGtleXdvcmQsIDApID09IGtleSkge1xuICAgICAgcmV0dXJuIEtlcm5lbC5lbGVtKGtleXdvcmQsIDEpO1xuICAgIH1cbiAgfVxuXG4gIHJldHVybiB0aGVfZGVmYXVsdDtcbn07XG5cbmxldCBBZ2VudCA9IHt9O1xuXG5BZ2VudC5zdGFydCA9IGZ1bmN0aW9uIChmdW4sIG9wdGlvbnMgPSBbXSkge1xuICBsZXQgcGlkID0gc2VsZi5wcm9jZXNzZXMuc3Bhd24oKTtcblxuICBpZiAoS2V5d29yZC5oYXNfa2V5X19xbV9fKG9wdGlvbnMsIEtlcm5lbC5TcGVjaWFsRm9ybXMuYXRvbSgnbmFtZScpKSkge1xuICAgIHBpZCA9IHNlbGYucHJvY2Vzc2VzLnJlZ2lzdGVyKEtleXdvcmQuZ2V0KG9wdGlvbnMsIEtlcm5lbC5TcGVjaWFsRm9ybXMuYXRvbSgnbmFtZScpKSwgcGlkKTtcbiAgfVxuXG4gIHNlbGYucHJvY2Vzc2VzLnB1dChwaWQsICdzdGF0ZScsIGZ1bigpKTtcbiAgcmV0dXJuIEtlcm5lbC5TcGVjaWFsRm9ybXMudHVwbGUoS2VybmVsLlNwZWNpYWxGb3Jtcy5hdG9tKCdvaycpLCBwaWQpO1xufTtcblxuQWdlbnQuc3RvcCA9IGZ1bmN0aW9uIChhZ2VudCwgdGltZW91dCA9IDUwMDApIHtcbiAgc2VsZi5wcm9jZXNzZXMuZXhpdChhZ2VudCk7XG4gIHJldHVybiBLZXJuZWwuU3BlY2lhbEZvcm1zLmF0b20oJ29rJyk7XG59O1xuXG5BZ2VudC51cGRhdGUgPSBmdW5jdGlvbiAoYWdlbnQsIGZ1biwgdGltZW91dCA9IDUwMDApIHtcblxuICBjb25zdCBjdXJyZW50X3N0YXRlID0gc2VsZi5wcm9jZXNzZXMuZ2V0KGFnZW50LCAnc3RhdGUnKTtcbiAgc2VsZi5wcm9jZXNzZXMucHV0KGFnZW50LCAnc3RhdGUnLCBmdW4oY3VycmVudF9zdGF0ZSkpO1xuXG4gIHJldHVybiBLZXJuZWwuU3BlY2lhbEZvcm1zLmF0b20oJ29rJyk7XG59O1xuXG5BZ2VudC5nZXQgPSBmdW5jdGlvbiAoYWdlbnQsIGZ1biwgdGltZW91dCA9IDUwMDApIHtcbiAgcmV0dXJuIGZ1bihzZWxmLnByb2Nlc3Nlcy5nZXQoYWdlbnQsICdzdGF0ZScpKTtcbn07XG5cbkFnZW50LmdldF9hbmRfdXBkYXRlID0gZnVuY3Rpb24gKGFnZW50LCBmdW4sIHRpbWVvdXQgPSA1MDAwKSB7XG5cbiAgY29uc3QgZ2V0X2FuZF91cGRhdGVfdHVwbGUgPSBmdW4oc2VsZi5wcm9jZXNzZXMuZ2V0KGFnZW50LCAnc3RhdGUnKSk7XG4gIHNlbGYucHJvY2Vzc2VzLnB1dChhZ2VudCwgJ3N0YXRlJywgS2VybmVsLmVsZW0oZ2V0X2FuZF91cGRhdGVfdHVwbGUsIDEpKTtcblxuICByZXR1cm4gS2VybmVsLmVsZW0oZ2V0X2FuZF91cGRhdGVfdHVwbGUsIDApO1xufTtcblxuLy9odHRwczovL2RldmVsb3Blci5tb3ppbGxhLm9yZy9lbi1VUy9kb2NzL1dlYi9BUEkvV2luZG93QmFzZTY0L0Jhc2U2NF9lbmNvZGluZ19hbmRfZGVjb2RpbmcjU29sdXRpb25fMl8lRTIlODAlOTNfcmV3cml0ZV90aGVfRE9Nc19hdG9iKClfYW5kX2J0b2EoKV91c2luZ19KYXZhU2NyaXB0J3NfVHlwZWRBcnJheXNfYW5kX1VURi04XG5mdW5jdGlvbiBiNjRFbmNvZGVVbmljb2RlKHN0cikge1xuICByZXR1cm4gYnRvYShlbmNvZGVVUklDb21wb25lbnQoc3RyKS5yZXBsYWNlKC8lKFswLTlBLUZdezJ9KS9nLCBmdW5jdGlvbiAobWF0Y2gsIHAxKSB7XG4gICAgcmV0dXJuIFN0cmluZy5mcm9tQ2hhckNvZGUoJzB4JyArIHAxKTtcbiAgfSkpO1xufVxuXG5mdW5jdGlvbiBlbmNvZGU2NChkYXRhKSB7XG4gIHJldHVybiBiNjRFbmNvZGVVbmljb2RlKGRhdGEpO1xufVxuXG5mdW5jdGlvbiBkZWNvZGU2NChkYXRhKSB7XG4gIHRyeSB7XG4gICAgcmV0dXJuIEtlcm5lbC5TcGVjaWFsRm9ybXMudHVwbGUoS2VybmVsLlNwZWNpYWxGb3Jtcy5hdG9tKCdvaycpLCBhdG9iKGRhdGEpKTtcbiAgfSBjYXRjaCAoZSkge1xuICAgIHJldHVybiBLZXJuZWwuU3BlY2lhbEZvcm1zLmF0b20oJ2Vycm9yJyk7XG4gIH1cbiAgcmV0dXJuIGJ0b2EoZGF0YSk7XG59XG5cbmZ1bmN0aW9uIGRlY29kZTY0X19lbV9fKGRhdGEpIHtcbiAgcmV0dXJuIGF0b2IoZGF0YSk7XG59XG5cbnZhciBiYXNlID0ge1xuICBlbmNvZGU2NCxcbiAgZGVjb2RlNjQsXG4gIGRlY29kZTY0X19lbV9fXG59O1xuXG5mdW5jdGlvbiBibm90KGV4cHIpIHtcbiAgcmV0dXJuIH5leHByO1xufVxuXG5mdW5jdGlvbiBiYW5kKGxlZnQsIHJpZ2h0KSB7XG4gIHJldHVybiBsZWZ0ICYgcmlnaHQ7XG59XG5cbmZ1bmN0aW9uIGJvcihsZWZ0LCByaWdodCkge1xuICByZXR1cm4gbGVmdCB8IHJpZ2h0O1xufVxuXG5mdW5jdGlvbiBic2wobGVmdCwgcmlnaHQpIHtcbiAgcmV0dXJuIGxlZnQgPDwgcmlnaHQ7XG59XG5cbmZ1bmN0aW9uIGJzcihsZWZ0LCByaWdodCkge1xuICByZXR1cm4gbGVmdCA+PiByaWdodDtcbn1cblxuZnVuY3Rpb24gYnhvcihsZWZ0LCByaWdodCkge1xuICByZXR1cm4gbGVmdCBeIHJpZ2h0O1xufVxuXG52YXIgYml0d2lzZSA9IHtcbiAgYm5vdCxcbiAgYmFuZCxcbiAgYm9yLFxuICBic2wsXG4gIGJzcixcbiAgYnhvclxufTtcblxubGV0IEVudW1lcmFibGUgPSBLZXJuZWwuZGVmcHJvdG9jb2woe1xuICBjb3VudDogZnVuY3Rpb24gKGNvbGxlY3Rpb24pIHt9LFxuICBtZW1iZXJfcW1hcmtfXzogZnVuY3Rpb24gKGNvbGxlY3Rpb24sIHZhbHVlKSB7fSxcbiAgcmVkdWNlOiBmdW5jdGlvbiAoY29sbGVjdGlvbiwgYWNjLCBmdW4pIHt9XG59KTtcblxubGV0IENvbGxlY3RhYmxlID0gS2VybmVsLmRlZnByb3RvY29sKHtcbiAgaW50bzogZnVuY3Rpb24gKGNvbGxlY3RhYmxlKSB7fVxufSk7XG5cbmxldCBJbnNwZWN0ID0gS2VybmVsLmRlZnByb3RvY29sKHtcbiAgaW5zcGVjdDogZnVuY3Rpb24gKHRoaW5nLCBvcHRzKSB7fVxufSk7XG5cbmZ1bmN0aW9uIF9fbmV3X18oKSB7XG4gIHJldHVybiBTcGVjaWFsRm9ybXMubWFwKHt9KTtcbn1cblxuZnVuY3Rpb24ga2V5cyhtYXApIHtcbiAgcmV0dXJuIE9iamVjdC5rZXlzKG1hcCk7XG59XG5cbmZ1bmN0aW9uIHNpemUobWFwKSB7XG4gIHJldHVybiBrZXlzKG1hcCkubGVuZ3RoO1xufVxuXG5mdW5jdGlvbiB0b19saXN0JDEobWFwKSB7XG4gIGxldCBtYXBfa2V5cyA9IGtleXMobWFwKTtcbiAgbGV0IGxpc3QgPSBbXTtcblxuICBmb3IgKGxldCBrZXkgb2YgbWFwX2tleXMpIHtcbiAgICBsaXN0LnB1c2goU3BlY2lhbEZvcm1zLnR1cGxlKGtleSwgbWFwW2tleV0pKTtcbiAgfVxuXG4gIHJldHVybiBTcGVjaWFsRm9ybXMubGlzdCguLi5saXN0KTtcbn1cblxuZnVuY3Rpb24gdmFsdWVzKG1hcCkge1xuICBsZXQgbWFwX2tleXMgPSBrZXlzKG1hcCk7XG4gIGxldCBsaXN0ID0gW107XG5cbiAgZm9yIChsZXQga2V5IG9mIG1hcF9rZXlzKSB7XG4gICAgbGlzdC5wdXNoKG1hcFtrZXldKTtcbiAgfVxuXG4gIHJldHVybiBTcGVjaWFsRm9ybXMubGlzdCguLi5saXN0KTtcbn1cblxuZnVuY3Rpb24gZnJvbV9zdHJ1Y3Qoc3RydWN0KSB7XG4gIGxldCBtYXAgPSBPYmplY3QuYXNzaWduKHt9LCBzdHJ1Y3QpO1xuICBkZWxldGUgbWFwW1N5bWJvbC5mb3IoXCJfX3N0cnVjdF9fXCIpXTtcblxuICByZXR1cm4gU3BlY2lhbEZvcm1zLm1hcChtYXApO1xufVxuXG5mdW5jdGlvbiBfX2RlbGV0ZV9fKG1hcCwga2V5KSB7XG4gIGxldCBuZXdfbWFwID0gT2JqZWN0LmFzc2lnbih7fSwgbWFwKTtcblxuICBkZWxldGUgbmV3X21hcFtrZXldO1xuXG4gIHJldHVybiBTcGVjaWFsRm9ybXMubWFwKG5ld19tYXApO1xufVxuXG5mdW5jdGlvbiBlcXVhbF9fcW1hcmtfXyhtYXAxLCBtYXAyKSB7XG4gIHJldHVybiBtYXAxID09PSBtYXAyO1xufVxuXG5mdW5jdGlvbiBmZXRjaF9fZW1hcmtfXyhtYXAsIGtleSkge1xuICBpZiAoa2V5IGluIG1hcCkge1xuICAgIHJldHVybiBtYXBba2V5XTtcbiAgfVxuXG4gIHRocm93IG5ldyBFcnJvcihcIktleSBub3QgZm91bmQuXCIpO1xufVxuXG5mdW5jdGlvbiBmZXRjaChtYXAsIGtleSkge1xuICBpZiAoa2V5IGluIG1hcCkge1xuICAgIHJldHVybiBTcGVjaWFsRm9ybXMudHVwbGUoU3BlY2lhbEZvcm1zLmF0b20oXCJva1wiKSwgbWFwW2tleV0pO1xuICB9XG5cbiAgcmV0dXJuIFNwZWNpYWxGb3Jtcy5hdG9tKFwiZXJyb3JcIik7XG59XG5cbmZ1bmN0aW9uIGhhc19rZXlfX3FtYXJrX18obWFwLCBrZXkpIHtcbiAgcmV0dXJuIGtleSBpbiBtYXA7XG59XG5cbmZ1bmN0aW9uIHNwbGl0JDEobWFwLCBrZXlzKSB7XG4gIGxldCBzcGxpdDEgPSB7fTtcbiAgbGV0IHNwbGl0MiA9IHt9O1xuXG4gIGZvciAobGV0IGtleSBvZiBPYmplY3Qua2V5cyhtYXApKSB7XG4gICAgaWYgKGtleXMuaW5kZXhPZihrZXkpID4gLTEpIHtcbiAgICAgIHNwbGl0MVtrZXldID0gbWFwW2tleV07XG4gICAgfSBlbHNlIHtcbiAgICAgIHNwbGl0MltrZXldID0gbWFwW2tleV07XG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIFNwZWNpYWxGb3Jtcy50dXBsZShTcGVjaWFsRm9ybXMubWFwKHNwbGl0MSksIFNwZWNpYWxGb3Jtcy5tYXAoc3BsaXQyKSk7XG59XG5cbmZ1bmN0aW9uIHRha2UobWFwLCBrZXlzKSB7XG4gIGxldCBzcGxpdDEgPSB7fTtcblxuICBmb3IgKGxldCBrZXkgb2YgT2JqZWN0LmtleXMobWFwKSkge1xuICAgIGlmIChrZXlzLmluZGV4T2Yoa2V5KSA+IC0xKSB7XG4gICAgICBzcGxpdDFba2V5XSA9IG1hcFtrZXldO1xuICAgIH1cbiAgfVxuXG4gIHJldHVybiBTcGVjaWFsRm9ybXMubWFwKHNwbGl0MSk7XG59XG5cbmZ1bmN0aW9uIGRyb3AobWFwLCBrZXlzKSB7XG4gIGxldCBzcGxpdDEgPSB7fTtcblxuICBmb3IgKGxldCBrZXkgb2YgT2JqZWN0LmtleXMobWFwKSkge1xuICAgIGlmIChrZXlzLmluZGV4T2Yoa2V5KSA9PT0gLTEpIHtcbiAgICAgIHNwbGl0MVtrZXldID0gbWFwW2tleV07XG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIFNwZWNpYWxGb3Jtcy5tYXAoc3BsaXQxKTtcbn1cblxuZnVuY3Rpb24gcHV0X25ldyhtYXAsIGtleSwgdmFsdWUpIHtcbiAgaWYgKGtleSBpbiBtYXApIHtcbiAgICByZXR1cm4gbWFwO1xuICB9XG5cbiAgbGV0IG5ld19tYXAgPSBPYmplY3QuYXNzaWduKHt9LCBtYXApO1xuICBuZXdfbWFwW2tleV0gPSB2YWx1ZTtcblxuICByZXR1cm4gU3BlY2lhbEZvcm1zLm1hcChuZXdfbWFwKTtcbn1cblxuZnVuY3Rpb24gcHV0X25ld19sYXp5KG1hcCwga2V5LCBmdW4pIHtcbiAgaWYgKGtleSBpbiBtYXApIHtcbiAgICByZXR1cm4gbWFwO1xuICB9XG5cbiAgbGV0IG5ld19tYXAgPSBPYmplY3QuYXNzaWduKHt9LCBtYXApO1xuICBuZXdfbWFwW2tleV0gPSBmdW4oKTtcblxuICByZXR1cm4gU3BlY2lhbEZvcm1zLm1hcChuZXdfbWFwKTtcbn1cblxuZnVuY3Rpb24gZ2V0X2FuZF91cGRhdGUobWFwLCBrZXksIGZ1bikge1xuICBpZiAoa2V5IGluIG1hcCkge1xuICAgIHJldHVybiBtYXA7XG4gIH1cblxuICBsZXQgbmV3X21hcCA9IE9iamVjdC5hc3NpZ24oe30sIG1hcCk7XG4gIG5ld19tYXBba2V5XSA9IGZ1bihtYXBba2V5XSk7XG5cbiAgcmV0dXJuIFNwZWNpYWxGb3Jtcy5tYXAobmV3X21hcCk7XG59XG5cbmZ1bmN0aW9uIHBvcF9sYXp5KG1hcCwga2V5LCBmdW4pIHtcbiAgaWYgKCFrZXkgaW4gbWFwKSB7XG4gICAgcmV0dXJuIFNwZWNpYWxGb3Jtcy50dXBsZShmdW4oKSwgbWFwKTtcbiAgfVxuXG4gIGxldCBuZXdfbWFwID0gT2JqZWN0LmFzc2lnbih7fSwgbWFwKTtcbiAgbGV0IHZhbHVlID0gZnVuKG5ld19tYXBba2V5XSk7XG4gIGRlbGV0ZSBuZXdfbWFwW2tleV07XG5cbiAgcmV0dXJuIFNwZWNpYWxGb3Jtcy50dXBsZSh2YWx1ZSwgbmV3X21hcCk7XG59XG5cbmZ1bmN0aW9uIHBvcChtYXAsIGtleSwgX2RlZmF1bHQgPSBudWxsKSB7XG4gIGlmICgha2V5IGluIG1hcCkge1xuICAgIHJldHVybiBTcGVjaWFsRm9ybXMudHVwbGUoX2RlZmF1bHQsIG1hcCk7XG4gIH1cblxuICBsZXQgbmV3X21hcCA9IE9iamVjdC5hc3NpZ24oe30sIG1hcCk7XG4gIGxldCB2YWx1ZSA9IG5ld19tYXBba2V5XTtcbiAgZGVsZXRlIG5ld19tYXBba2V5XTtcblxuICByZXR1cm4gU3BlY2lhbEZvcm1zLnR1cGxlKHZhbHVlLCBuZXdfbWFwKTtcbn1cblxuZnVuY3Rpb24gZ2V0X2xhenkobWFwLCBrZXksIGZ1bikge1xuICBpZiAoIWtleSBpbiBtYXApIHtcbiAgICByZXR1cm4gZnVuKCk7XG4gIH1cblxuICByZXR1cm4gZnVuKG1hcFtrZXldKTtcbn1cblxuZnVuY3Rpb24gZ2V0KG1hcCwga2V5LCBfZGVmYXVsdCA9IG51bGwpIHtcbiAgaWYgKCFrZXkgaW4gbWFwKSB7XG4gICAgcmV0dXJuIF9kZWZhdWx0O1xuICB9XG5cbiAgcmV0dXJuIG1hcFtrZXldO1xufVxuXG5mdW5jdGlvbiBwdXQobWFwLCBrZXksIHZhbCkge1xuICBsZXQgbmV3X21hcCA9IE9iamVjdCh7fSwgbWFwKTtcbiAgbmV3X21hcFtrZXldID0gdmFsO1xuXG4gIHJldHVybiBTcGVjaWFsRm9ybXMubWFwKG5ld19tYXApO1xufVxuXG5mdW5jdGlvbiB1cGRhdGVfX2VtYXJrX18obWFwLCBrZXksIGZ1bikge1xuICBpZiAoIWtleSBpbiBtYXApIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoXCJLZXkgbm90IGZvdW5kXCIpO1xuICB9XG5cbiAgbGV0IG5ld19tYXAgPSBPYmplY3Qoe30sIG1hcCk7XG4gIG5ld19tYXBba2V5XSA9IGZ1bihtYXBba2V5XSk7XG5cbiAgcmV0dXJuIFNwZWNpYWxGb3Jtcy5tYXAobmV3X21hcCk7XG59XG5cbmZ1bmN0aW9uIHVwZGF0ZShtYXAsIGtleSwgaW5pdGlhbCwgZnVuKSB7XG4gIGxldCBuZXdfbWFwID0gT2JqZWN0KHt9LCBtYXApO1xuXG4gIGlmICgha2V5IGluIG1hcCkge1xuICAgIG5ld19tYXBba2V5XSA9IGluaXRpYWw7XG4gIH0gZWxzZSB7XG4gICAgbmV3X21hcFtrZXldID0gZnVuKG1hcFtrZXldKTtcbiAgfVxuXG4gIHJldHVybiBTcGVjaWFsRm9ybXMubWFwKG5ld19tYXApO1xufVxuXG52YXIgbWFwID0ge1xuICBuZXc6IF9fbmV3X18sXG4gIGtleXMsXG4gIHNpemUsXG4gIHRvX2xpc3Q6IHRvX2xpc3QkMSxcbiAgdmFsdWVzLFxuICBmcm9tX3N0cnVjdCxcbiAgZGVsZXRlOiBfX2RlbGV0ZV9fLFxuICBkcm9wLFxuICBlcXVhbF9fcW1hcmtfXyxcbiAgZmV0Y2hfX2VtYXJrX18sXG4gIGZldGNoLFxuICBoYXNfa2V5X19xbWFya19fLFxuICBzcGxpdDogc3BsaXQkMSxcbiAgdGFrZSxcbiAgcHV0X25ldyxcbiAgcHV0X25ld19sYXp5LFxuICBnZXRfYW5kX3VwZGF0ZSxcbiAgcG9wX2xhenksXG4gIHBvcCxcbiAgZ2V0X2xhenksXG4gIGdldCxcbiAgcHV0LFxuICB1cGRhdGVfX2VtYXJrX18sXG4gIHVwZGF0ZVxufTtcblxuZnVuY3Rpb24gX19uZXdfXyQxKCkge1xuICByZXR1cm4gU3BlY2lhbEZvcm1zLm1hcCh7IFtTeW1ib2wuZm9yKCdfX3N0cnVjdF9fJyldOiBTeW1ib2wuZm9yKCdNYXBTZXQnKSwgc2V0OiBTcGVjaWFsRm9ybXMubGlzdCgpIH0pO1xufVxuXG5mdW5jdGlvbiBzaXplJDIobWFwKSB7XG4gIHJldHVybiBtYXAuc2V0Lmxlbmd0aDtcbn1cblxuZnVuY3Rpb24gdG9fbGlzdCQzKG1hcCkge1xuICByZXR1cm4gbWFwLnNldDtcbn1cblxuZnVuY3Rpb24gX19kZWxldGVfXyQyKHNldCwgdGVybSkge1xuICBsZXQgbmV3X2xpc3QgPSBMaXN0LmRlbGV0ZShzZXQuc2V0LCB0ZXJtKTtcblxuICBsZXQgbmV3X21hcCA9IE9iamVjdC5hc3NpZ24oe30sIHNldCk7XG4gIG5ld19tYXAuc2V0ID0gbmV3X2xpc3Q7XG4gIHJldHVybiBTcGVjaWFsRm9ybXMubWFwKG5ld19tYXApO1xufVxuXG5mdW5jdGlvbiBwdXQkMihzZXQsIHRlcm0pIHtcbiAgaWYgKHNldC5zZXQuaW5kZXhPZih0ZXJtKSA9PT0gLTEpIHtcbiAgICBsZXQgbmV3X2xpc3QgPSBMaXN0LmFwcGVuZChzZXQuc2V0LCB0ZXJtKTtcblxuICAgIGxldCBuZXdfbWFwID0gT2JqZWN0LmFzc2lnbih7fSwgc2V0KTtcbiAgICBuZXdfbWFwLnNldCA9IG5ld19saXN0O1xuICAgIHJldHVybiBTcGVjaWFsRm9ybXMubWFwKG5ld19tYXApO1xuICB9XG5cbiAgcmV0dXJuIHNldDtcbn1cblxuZnVuY3Rpb24gZGlmZmVyZW5jZSQxKHNldDEsIHNldDIpIHtcbiAgbGV0IG5ld19tYXAgPSBPYmplY3QuYXNzaWduKHt9LCBzZXQxKTtcblxuICBmb3IgKGxldCB2YWwgb2Ygc2V0MS5zZXQpIHtcbiAgICBpZiAobWVtYmVyX19xbWFya19fJDEoc2V0MiwgdmFsKSkge1xuICAgICAgbmV3X21hcC5zZXQgPSBMaXN0LmRlbGV0ZShuZXdfbWFwLnNldCwgdmFsKTtcbiAgICB9XG4gIH1cblxuICByZXR1cm4gU3BlY2lhbEZvcm1zLm1hcChuZXdfbWFwKTtcbn1cblxuZnVuY3Rpb24gaW50ZXJzZWN0aW9uJDEoc2V0MSwgc2V0Mikge1xuICBsZXQgbmV3X21hcCA9IE9iamVjdC5hc3NpZ24oe30sIHNldDEpO1xuXG4gIGZvciAobGV0IHZhbCBvZiBzZXQxLnNldCkge1xuICAgIGlmICghbWVtYmVyX19xbWFya19fJDEoc2V0MiwgdmFsKSkge1xuICAgICAgbmV3X21hcC5zZXQgPSBMaXN0LmRlbGV0ZShuZXdfbWFwLnNldCwgdmFsKTtcbiAgICB9XG4gIH1cblxuICByZXR1cm4gU3BlY2lhbEZvcm1zLm1hcChuZXdfbWFwKTtcbn1cblxuZnVuY3Rpb24gdW5pb24kMShzZXQxLCBzZXQyKSB7XG4gIGxldCBuZXdfbWFwID0gc2V0MTtcblxuICBmb3IgKGxldCB2YWwgb2Ygc2V0Mi5zZXQpIHtcbiAgICBuZXdfbWFwID0gcHV0JDIobmV3X21hcCwgdmFsKTtcbiAgfVxuXG4gIHJldHVybiBTcGVjaWFsRm9ybXMubWFwKG5ld19tYXApO1xufVxuXG5mdW5jdGlvbiBkaXNqb2luX19xbWFya19fJDEoc2V0MSwgc2V0Mikge1xuICBmb3IgKGxldCB2YWwgb2Ygc2V0MS5zZXQpIHtcbiAgICBpZiAobWVtYmVyX19xbWFya19fJDEoc2V0MiwgdmFsKSkge1xuICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH1cbiAgfVxuXG4gIHJldHVybiB0cnVlO1xufVxuXG5mdW5jdGlvbiBtZW1iZXJfX3FtYXJrX18kMShzZXQsIHZhbHVlKSB7XG4gIHJldHVybiBzZXQuc2V0LmluZGV4T2YodmFsdWUpID49IDA7XG59XG5cbmZ1bmN0aW9uIGVxdWFsX19xbWFya19fJDIoc2V0MSwgc2V0Mikge1xuICByZXR1cm4gc2V0MS5zZXQgPT09IHNldDIuc2V0O1xufVxuXG5mdW5jdGlvbiBzdWJzZXRfX3FtYXJrX18kMShzZXQxLCBzZXQyKSB7XG4gIGZvciAobGV0IHZhbCBvZiBzZXQxLnNldCkge1xuICAgIGlmICghbWVtYmVyX19xbWFya19fJDEoc2V0MiwgdmFsKSkge1xuICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH1cbiAgfVxuXG4gIHJldHVybiB0cnVlO1xufVxuXG52YXIgTWFwU2V0ID0ge1xuICBuZXc6IF9fbmV3X18kMSxcbiAgc2l6ZTogc2l6ZSQyLFxuICB0b19saXN0OiB0b19saXN0JDMsXG4gIGRpc2pvaW5fX3FtYXJrX186IGRpc2pvaW5fX3FtYXJrX18kMSxcbiAgZGVsZXRlOiBfX2RlbGV0ZV9fJDIsXG4gIHN1YnNldF9fcW1hcmtfXzogc3Vic2V0X19xbWFya19fJDEsXG4gIGVxdWFsX19xbWFya19fOiBlcXVhbF9fcW1hcmtfXyQyLFxuICBtZW1iZXJfX3FtYXJrX186IG1lbWJlcl9fcW1hcmtfXyQxLFxuICBwdXQ6IHB1dCQyLFxuICB1bmlvbjogdW5pb24kMSxcbiAgaW50ZXJzZWN0aW9uOiBpbnRlcnNlY3Rpb24kMSxcbiAgZGlmZmVyZW5jZTogZGlmZmVyZW5jZSQxXG59O1xuXG5mdW5jdGlvbiBzaXplJDEobWFwKSB7XG4gIHJldHVybiBNYXBTZXQuc2l6ZShtYXApO1xufVxuXG5mdW5jdGlvbiB0b19saXN0JDIobWFwKSB7XG4gIHJldHVybiBNYXBTZXQudG9fbGlzdChtYXApO1xufVxuXG5mdW5jdGlvbiBfX2RlbGV0ZV9fJDEoc2V0LCB0ZXJtKSB7XG4gIHJldHVybiBNYXBTZXQuZGVsZXRlKHNldCwgdGVybSk7XG59XG5cbmZ1bmN0aW9uIHB1dCQxKHNldCwgdGVybSkge1xuICByZXR1cm4gTWFwU2V0LnB1dChzZXQsIHRlcm0pO1xufVxuXG5mdW5jdGlvbiBkaWZmZXJlbmNlKHNldDEsIHNldDIpIHtcbiAgcmV0dXJuIE1hcFNldC5kaWZmZXJlbmNlKHNldDEsIHNldDIpO1xufVxuXG5mdW5jdGlvbiBpbnRlcnNlY3Rpb24oc2V0MSwgc2V0Mikge1xuICByZXR1cm4gTWFwU2V0LmludGVyc2VjdGlvbihzZXQxLCBzZXQyKTtcbn1cblxuZnVuY3Rpb24gdW5pb24oc2V0MSwgc2V0Mikge1xuICByZXR1cm4gTWFwU2V0LnVuaW9uKHNldDEsIHNldDIpO1xufVxuXG5mdW5jdGlvbiBkaXNqb2luX19xbWFya19fKHNldDEsIHNldDIpIHtcbiAgcmV0dXJuIE1hcFNldC5kaXNqb2luX19xbWFya19fKHNldDEsIHNldDIpO1xufVxuXG5mdW5jdGlvbiBtZW1iZXJfX3FtYXJrX18oc2V0LCB2YWx1ZSkge1xuICByZXR1cm4gTWFwU2V0Lm1lbWJlcl9fcW1hcmtfXyhzZXQxLCBzZXQyKTtcbn1cblxuZnVuY3Rpb24gZXF1YWxfX3FtYXJrX18kMShzZXQxLCBzZXQyKSB7XG4gIHJldHVybiBNYXBTZXQuZXF1YWxfX3FtYXJrX18oc2V0MSwgc2V0Mik7XG59XG5cbmZ1bmN0aW9uIHN1YnNldF9fcW1hcmtfXyhzZXQxLCBzZXQyKSB7XG4gIHJldHVybiBNYXBTZXQuc3Vic2V0X19xbWFya19fKHNldDEsIHNldDIpO1xufVxuXG52YXIgc2V0ID0ge1xuICBzaXplOiBzaXplJDEsXG4gIHRvX2xpc3Q6IHRvX2xpc3QkMixcbiAgZGlzam9pbl9fcW1hcmtfXyxcbiAgZGVsZXRlOiBfX2RlbGV0ZV9fJDEsXG4gIHN1YnNldF9fcW1hcmtfXyxcbiAgZXF1YWxfX3FtYXJrX186IGVxdWFsX19xbWFya19fJDEsXG4gIG1lbWJlcl9fcW1hcmtfXyxcbiAgcHV0OiBwdXQkMSxcbiAgdW5pb24sXG4gIGludGVyc2VjdGlvbixcbiAgZGlmZmVyZW5jZVxufTtcblxubGV0IFZpcnR1YWxET00gPSAoZnVuY3Rpb24gKGUpIHtcbiAgICByZXR1cm4gZSgpO1xufSkoZnVuY3Rpb24gKCkge1xuICAgIHZhciBkZWZpbmUsIG1vZHVsZSwgZXhwb3J0cztcbiAgICByZXR1cm4gKGZ1bmN0aW9uIGUodCwgbiwgcikge1xuICAgICAgICBmdW5jdGlvbiBzKG8sIHUpIHtcbiAgICAgICAgICAgIGlmICghbltvXSkge1xuICAgICAgICAgICAgICAgIGlmICghdFtvXSkge1xuICAgICAgICAgICAgICAgICAgICB2YXIgYSA9IHR5cGVvZiByZXF1aXJlID09IFwiZnVuY3Rpb25cIiAmJiByZXF1aXJlO1xuICAgICAgICAgICAgICAgICAgICBpZiAoIXUgJiYgYSkgcmV0dXJuIGEobywgITApO1xuICAgICAgICAgICAgICAgICAgICBpZiAoaSkgcmV0dXJuIGkobywgITApO1xuICAgICAgICAgICAgICAgICAgICB2YXIgZiA9IG5ldyBFcnJvcihcIkNhbm5vdCBmaW5kIG1vZHVsZSAnXCIgKyBvICsgXCInXCIpO1xuICAgICAgICAgICAgICAgICAgICB0aHJvdyAoZi5jb2RlID0gXCJNT0RVTEVfTk9UX0ZPVU5EXCIsIGYpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB2YXIgbCA9IG5bb10gPSB7XG4gICAgICAgICAgICAgICAgICAgIGV4cG9ydHM6IHt9XG4gICAgICAgICAgICAgICAgfTtcbiAgICAgICAgICAgICAgICB0W29dWzBdLmNhbGwobC5leHBvcnRzLCBmdW5jdGlvbiAoZSkge1xuICAgICAgICAgICAgICAgICAgICB2YXIgbiA9IHRbb11bMV1bZV07XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBzKG4gPyBuIDogZSk7XG4gICAgICAgICAgICAgICAgfSwgbCwgbC5leHBvcnRzLCBlLCB0LCBuLCByKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJldHVybiBuW29dLmV4cG9ydHM7XG4gICAgICAgIH1cbiAgICAgICAgdmFyIGkgPSB0eXBlb2YgcmVxdWlyZSA9PSBcImZ1bmN0aW9uXCIgJiYgcmVxdWlyZTtcbiAgICAgICAgZm9yICh2YXIgbyA9IDA7IG8gPCByLmxlbmd0aDsgbysrKSBzKHJbb10pO1xuICAgICAgICByZXR1cm4gcztcbiAgICB9KSh7XG4gICAgICAgIDE6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG5cbiAgICAgICAgICAgIHZhciBjcmVhdGVFbGVtZW50ID0gcmVxdWlyZShcIi4vdmRvbS9jcmVhdGUtZWxlbWVudC5qc1wiKTtcblxuICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBjcmVhdGVFbGVtZW50O1xuICAgICAgICB9LCB7IFwiLi92ZG9tL2NyZWF0ZS1lbGVtZW50LmpzXCI6IDE1IH1dLCAyOiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge1xuICAgICAgICAgICAgdmFyIGRpZmYgPSByZXF1aXJlKFwiLi92dHJlZS9kaWZmLmpzXCIpO1xuXG4gICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IGRpZmY7XG4gICAgICAgIH0sIHsgXCIuL3Z0cmVlL2RpZmYuanNcIjogMzUgfV0sIDM6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICB2YXIgaCA9IHJlcXVpcmUoXCIuL3ZpcnR1YWwtaHlwZXJzY3JpcHQvaW5kZXguanNcIik7XG5cbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gaDtcbiAgICAgICAgfSwgeyBcIi4vdmlydHVhbC1oeXBlcnNjcmlwdC9pbmRleC5qc1wiOiAyMiB9XSwgNDogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHtcbiAgICAgICAgICAgIHZhciBkaWZmID0gcmVxdWlyZShcIi4vZGlmZi5qc1wiKTtcbiAgICAgICAgICAgIHZhciBwYXRjaCA9IHJlcXVpcmUoXCIuL3BhdGNoLmpzXCIpO1xuICAgICAgICAgICAgdmFyIGggPSByZXF1aXJlKFwiLi9oLmpzXCIpO1xuICAgICAgICAgICAgdmFyIGNyZWF0ZSA9IHJlcXVpcmUoXCIuL2NyZWF0ZS1lbGVtZW50LmpzXCIpO1xuICAgICAgICAgICAgdmFyIFZOb2RlID0gcmVxdWlyZShcIi4vdm5vZGUvdm5vZGUuanNcIik7XG4gICAgICAgICAgICB2YXIgVlRleHQgPSByZXF1aXJlKFwiLi92bm9kZS92dGV4dC5qc1wiKTtcblxuICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSB7XG4gICAgICAgICAgICAgICAgZGlmZjogZGlmZixcbiAgICAgICAgICAgICAgICBwYXRjaDogcGF0Y2gsXG4gICAgICAgICAgICAgICAgaDogaCxcbiAgICAgICAgICAgICAgICBjcmVhdGU6IGNyZWF0ZSxcbiAgICAgICAgICAgICAgICBWTm9kZTogVk5vZGUsXG4gICAgICAgICAgICAgICAgVlRleHQ6IFZUZXh0XG4gICAgICAgICAgICB9O1xuICAgICAgICB9LCB7IFwiLi9jcmVhdGUtZWxlbWVudC5qc1wiOiAxLCBcIi4vZGlmZi5qc1wiOiAyLCBcIi4vaC5qc1wiOiAzLCBcIi4vcGF0Y2guanNcIjogMTMsIFwiLi92bm9kZS92bm9kZS5qc1wiOiAzMSwgXCIuL3Zub2RlL3Z0ZXh0LmpzXCI6IDMzIH1dLCA1OiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge1xuICAgICAgICAgICAgLyohXG4gICAgICAgICAgICAgKiBDcm9zcy1Ccm93c2VyIFNwbGl0IDEuMS4xXG4gICAgICAgICAgICAgKiBDb3B5cmlnaHQgMjAwNy0yMDEyIFN0ZXZlbiBMZXZpdGhhbiA8c3RldmVubGV2aXRoYW4uY29tPlxuICAgICAgICAgICAgICogQXZhaWxhYmxlIHVuZGVyIHRoZSBNSVQgTGljZW5zZVxuICAgICAgICAgICAgICogRUNNQVNjcmlwdCBjb21wbGlhbnQsIHVuaWZvcm0gY3Jvc3MtYnJvd3NlciBzcGxpdCBtZXRob2RcbiAgICAgICAgICAgICAqL1xuXG4gICAgICAgICAgICAvKipcbiAgICAgICAgICAgICAqIFNwbGl0cyBhIHN0cmluZyBpbnRvIGFuIGFycmF5IG9mIHN0cmluZ3MgdXNpbmcgYSByZWdleCBvciBzdHJpbmcgc2VwYXJhdG9yLiBNYXRjaGVzIG9mIHRoZVxuICAgICAgICAgICAgICogc2VwYXJhdG9yIGFyZSBub3QgaW5jbHVkZWQgaW4gdGhlIHJlc3VsdCBhcnJheS4gSG93ZXZlciwgaWYgYHNlcGFyYXRvcmAgaXMgYSByZWdleCB0aGF0IGNvbnRhaW5zXG4gICAgICAgICAgICAgKiBjYXB0dXJpbmcgZ3JvdXBzLCBiYWNrcmVmZXJlbmNlcyBhcmUgc3BsaWNlZCBpbnRvIHRoZSByZXN1bHQgZWFjaCB0aW1lIGBzZXBhcmF0b3JgIGlzIG1hdGNoZWQuXG4gICAgICAgICAgICAgKiBGaXhlcyBicm93c2VyIGJ1Z3MgY29tcGFyZWQgdG8gdGhlIG5hdGl2ZSBgU3RyaW5nLnByb3RvdHlwZS5zcGxpdGAgYW5kIGNhbiBiZSB1c2VkIHJlbGlhYmx5XG4gICAgICAgICAgICAgKiBjcm9zcy1icm93c2VyLlxuICAgICAgICAgICAgICogQHBhcmFtIHtTdHJpbmd9IHN0ciBTdHJpbmcgdG8gc3BsaXQuXG4gICAgICAgICAgICAgKiBAcGFyYW0ge1JlZ0V4cHxTdHJpbmd9IHNlcGFyYXRvciBSZWdleCBvciBzdHJpbmcgdG8gdXNlIGZvciBzZXBhcmF0aW5nIHRoZSBzdHJpbmcuXG4gICAgICAgICAgICAgKiBAcGFyYW0ge051bWJlcn0gW2xpbWl0XSBNYXhpbXVtIG51bWJlciBvZiBpdGVtcyB0byBpbmNsdWRlIGluIHRoZSByZXN1bHQgYXJyYXkuXG4gICAgICAgICAgICAgKiBAcmV0dXJucyB7QXJyYXl9IEFycmF5IG9mIHN1YnN0cmluZ3MuXG4gICAgICAgICAgICAgKiBAZXhhbXBsZVxuICAgICAgICAgICAgICpcbiAgICAgICAgICAgICAqIC8vIEJhc2ljIHVzZVxuICAgICAgICAgICAgICogc3BsaXQoJ2EgYiBjIGQnLCAnICcpO1xuICAgICAgICAgICAgICogLy8gLT4gWydhJywgJ2InLCAnYycsICdkJ11cbiAgICAgICAgICAgICAqXG4gICAgICAgICAgICAgKiAvLyBXaXRoIGxpbWl0XG4gICAgICAgICAgICAgKiBzcGxpdCgnYSBiIGMgZCcsICcgJywgMik7XG4gICAgICAgICAgICAgKiAvLyAtPiBbJ2EnLCAnYiddXG4gICAgICAgICAgICAgKlxuICAgICAgICAgICAgICogLy8gQmFja3JlZmVyZW5jZXMgaW4gcmVzdWx0IGFycmF5XG4gICAgICAgICAgICAgKiBzcGxpdCgnLi53b3JkMSB3b3JkMi4uJywgLyhbYS16XSspKFxcZCspL2kpO1xuICAgICAgICAgICAgICogLy8gLT4gWycuLicsICd3b3JkJywgJzEnLCAnICcsICd3b3JkJywgJzInLCAnLi4nXVxuICAgICAgICAgICAgICovXG4gICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IChmdW5jdGlvbiBzcGxpdCh1bmRlZikge1xuXG4gICAgICAgICAgICAgICAgdmFyIG5hdGl2ZVNwbGl0ID0gU3RyaW5nLnByb3RvdHlwZS5zcGxpdCxcbiAgICAgICAgICAgICAgICAgICAgY29tcGxpYW50RXhlY05wY2cgPSAvKCk/Py8uZXhlYyhcIlwiKVsxXSA9PT0gdW5kZWYsXG5cbiAgICAgICAgICAgICAgICAvLyBOUENHOiBub25wYXJ0aWNpcGF0aW5nIGNhcHR1cmluZyBncm91cFxuICAgICAgICAgICAgICAgIHNlbGY7XG5cbiAgICAgICAgICAgICAgICBzZWxmID0gZnVuY3Rpb24gKHN0ciwgc2VwYXJhdG9yLCBsaW1pdCkge1xuICAgICAgICAgICAgICAgICAgICAvLyBJZiBgc2VwYXJhdG9yYCBpcyBub3QgYSByZWdleCwgdXNlIGBuYXRpdmVTcGxpdGBcbiAgICAgICAgICAgICAgICAgICAgaWYgKE9iamVjdC5wcm90b3R5cGUudG9TdHJpbmcuY2FsbChzZXBhcmF0b3IpICE9PSBcIltvYmplY3QgUmVnRXhwXVwiKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gbmF0aXZlU3BsaXQuY2FsbChzdHIsIHNlcGFyYXRvciwgbGltaXQpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIHZhciBvdXRwdXQgPSBbXSxcbiAgICAgICAgICAgICAgICAgICAgICAgIGZsYWdzID0gKHNlcGFyYXRvci5pZ25vcmVDYXNlID8gXCJpXCIgOiBcIlwiKSArIChzZXBhcmF0b3IubXVsdGlsaW5lID8gXCJtXCIgOiBcIlwiKSArIChzZXBhcmF0b3IuZXh0ZW5kZWQgPyBcInhcIiA6IFwiXCIpICsgKHNlcGFyYXRvci5zdGlja3kgPyBcInlcIiA6IFwiXCIpLFxuXG4gICAgICAgICAgICAgICAgICAgIC8vIEZpcmVmb3ggMytcbiAgICAgICAgICAgICAgICAgICAgbGFzdExhc3RJbmRleCA9IDAsXG5cbiAgICAgICAgICAgICAgICAgICAgLy8gTWFrZSBgZ2xvYmFsYCBhbmQgYXZvaWQgYGxhc3RJbmRleGAgaXNzdWVzIGJ5IHdvcmtpbmcgd2l0aCBhIGNvcHlcbiAgICAgICAgICAgICAgICAgICAgc2VwYXJhdG9yID0gbmV3IFJlZ0V4cChzZXBhcmF0b3Iuc291cmNlLCBmbGFncyArIFwiZ1wiKSxcbiAgICAgICAgICAgICAgICAgICAgICAgIHNlcGFyYXRvcjIsXG4gICAgICAgICAgICAgICAgICAgICAgICBtYXRjaCxcbiAgICAgICAgICAgICAgICAgICAgICAgIGxhc3RJbmRleCxcbiAgICAgICAgICAgICAgICAgICAgICAgIGxhc3RMZW5ndGg7XG4gICAgICAgICAgICAgICAgICAgIHN0ciArPSBcIlwiOyAvLyBUeXBlLWNvbnZlcnRcbiAgICAgICAgICAgICAgICAgICAgaWYgKCFjb21wbGlhbnRFeGVjTnBjZykge1xuICAgICAgICAgICAgICAgICAgICAgICAgLy8gRG9lc24ndCBuZWVkIGZsYWdzIGd5LCBidXQgdGhleSBkb24ndCBodXJ0XG4gICAgICAgICAgICAgICAgICAgICAgICBzZXBhcmF0b3IyID0gbmV3IFJlZ0V4cChcIl5cIiArIHNlcGFyYXRvci5zb3VyY2UgKyBcIiQoPyFcXFxccylcIiwgZmxhZ3MpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIC8qIFZhbHVlcyBmb3IgYGxpbWl0YCwgcGVyIHRoZSBzcGVjOlxuICAgICAgICAgICAgICAgICAgICAgKiBJZiB1bmRlZmluZWQ6IDQyOTQ5NjcyOTUgLy8gTWF0aC5wb3coMiwgMzIpIC0gMVxuICAgICAgICAgICAgICAgICAgICAgKiBJZiAwLCBJbmZpbml0eSwgb3IgTmFOOiAwXG4gICAgICAgICAgICAgICAgICAgICAqIElmIHBvc2l0aXZlIG51bWJlcjogbGltaXQgPSBNYXRoLmZsb29yKGxpbWl0KTsgaWYgKGxpbWl0ID4gNDI5NDk2NzI5NSkgbGltaXQgLT0gNDI5NDk2NzI5NjtcbiAgICAgICAgICAgICAgICAgICAgICogSWYgbmVnYXRpdmUgbnVtYmVyOiA0Mjk0OTY3Mjk2IC0gTWF0aC5mbG9vcihNYXRoLmFicyhsaW1pdCkpXG4gICAgICAgICAgICAgICAgICAgICAqIElmIG90aGVyOiBUeXBlLWNvbnZlcnQsIHRoZW4gdXNlIHRoZSBhYm92ZSBydWxlc1xuICAgICAgICAgICAgICAgICAgICAgKi9cbiAgICAgICAgICAgICAgICAgICAgbGltaXQgPSBsaW1pdCA9PT0gdW5kZWYgPyAtMSA+Pj4gMCA6IC8vIE1hdGgucG93KDIsIDMyKSAtIDFcbiAgICAgICAgICAgICAgICAgICAgbGltaXQgPj4+IDA7IC8vIFRvVWludDMyKGxpbWl0KVxuICAgICAgICAgICAgICAgICAgICB3aGlsZSAobWF0Y2ggPSBzZXBhcmF0b3IuZXhlYyhzdHIpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAvLyBgc2VwYXJhdG9yLmxhc3RJbmRleGAgaXMgbm90IHJlbGlhYmxlIGNyb3NzLWJyb3dzZXJcbiAgICAgICAgICAgICAgICAgICAgICAgIGxhc3RJbmRleCA9IG1hdGNoLmluZGV4ICsgbWF0Y2hbMF0ubGVuZ3RoO1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGxhc3RJbmRleCA+IGxhc3RMYXN0SW5kZXgpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBvdXRwdXQucHVzaChzdHIuc2xpY2UobGFzdExhc3RJbmRleCwgbWF0Y2guaW5kZXgpKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBGaXggYnJvd3NlcnMgd2hvc2UgYGV4ZWNgIG1ldGhvZHMgZG9uJ3QgY29uc2lzdGVudGx5IHJldHVybiBgdW5kZWZpbmVkYCBmb3JcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBub25wYXJ0aWNpcGF0aW5nIGNhcHR1cmluZyBncm91cHNcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoIWNvbXBsaWFudEV4ZWNOcGNnICYmIG1hdGNoLmxlbmd0aCA+IDEpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbWF0Y2hbMF0ucmVwbGFjZShzZXBhcmF0b3IyLCBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBmb3IgKHZhciBpID0gMTsgaSA8IGFyZ3VtZW50cy5sZW5ndGggLSAyOyBpKyspIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoYXJndW1lbnRzW2ldID09PSB1bmRlZikge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBtYXRjaFtpXSA9IHVuZGVmO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChtYXRjaC5sZW5ndGggPiAxICYmIG1hdGNoLmluZGV4IDwgc3RyLmxlbmd0aCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBBcnJheS5wcm90b3R5cGUucHVzaC5hcHBseShvdXRwdXQsIG1hdGNoLnNsaWNlKDEpKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgbGFzdExlbmd0aCA9IG1hdGNoWzBdLmxlbmd0aDtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBsYXN0TGFzdEluZGV4ID0gbGFzdEluZGV4O1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChvdXRwdXQubGVuZ3RoID49IGxpbWl0KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChzZXBhcmF0b3IubGFzdEluZGV4ID09PSBtYXRjaC5pbmRleCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNlcGFyYXRvci5sYXN0SW5kZXgrKzsgLy8gQXZvaWQgYW4gaW5maW5pdGUgbG9vcFxuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIGlmIChsYXN0TGFzdEluZGV4ID09PSBzdHIubGVuZ3RoKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAobGFzdExlbmd0aCB8fCAhc2VwYXJhdG9yLnRlc3QoXCJcIikpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBvdXRwdXQucHVzaChcIlwiKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIG91dHB1dC5wdXNoKHN0ci5zbGljZShsYXN0TGFzdEluZGV4KSk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIG91dHB1dC5sZW5ndGggPiBsaW1pdCA/IG91dHB1dC5zbGljZSgwLCBsaW1pdCkgOiBvdXRwdXQ7XG4gICAgICAgICAgICAgICAgfTtcblxuICAgICAgICAgICAgICAgIHJldHVybiBzZWxmO1xuICAgICAgICAgICAgfSkoKTtcbiAgICAgICAgfSwge31dLCA2OiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge30sIHt9XSwgNzogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHtcbiAgICAgICAgICAgIFwidXNlIHN0cmljdFwiO1xuXG4gICAgICAgICAgICB2YXIgT25lVmVyc2lvbkNvbnN0cmFpbnQgPSByZXF1aXJlKFwiaW5kaXZpZHVhbC9vbmUtdmVyc2lvblwiKTtcblxuICAgICAgICAgICAgdmFyIE1ZX1ZFUlNJT04gPSBcIjdcIjtcbiAgICAgICAgICAgIE9uZVZlcnNpb25Db25zdHJhaW50KFwiZXYtc3RvcmVcIiwgTVlfVkVSU0lPTik7XG5cbiAgICAgICAgICAgIHZhciBoYXNoS2V5ID0gXCJfX0VWX1NUT1JFX0tFWUBcIiArIE1ZX1ZFUlNJT047XG5cbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gRXZTdG9yZTtcblxuICAgICAgICAgICAgZnVuY3Rpb24gRXZTdG9yZShlbGVtKSB7XG4gICAgICAgICAgICAgICAgdmFyIGhhc2ggPSBlbGVtW2hhc2hLZXldO1xuXG4gICAgICAgICAgICAgICAgaWYgKCFoYXNoKSB7XG4gICAgICAgICAgICAgICAgICAgIGhhc2ggPSBlbGVtW2hhc2hLZXldID0ge307XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgcmV0dXJuIGhhc2g7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0sIHsgXCJpbmRpdmlkdWFsL29uZS12ZXJzaW9uXCI6IDkgfV0sIDg6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICAoZnVuY3Rpb24gKGdsb2JhbCkge1xuICAgICAgICAgICAgICAgIFwidXNlIHN0cmljdFwiO1xuXG4gICAgICAgICAgICAgICAgLypnbG9iYWwgd2luZG93LCBnbG9iYWwqL1xuXG4gICAgICAgICAgICAgICAgdmFyIHJvb3QgPSB0eXBlb2Ygd2luZG93ICE9PSBcInVuZGVmaW5lZFwiID8gd2luZG93IDogdHlwZW9mIGdsb2JhbCAhPT0gXCJ1bmRlZmluZWRcIiA/IGdsb2JhbCA6IHt9O1xuXG4gICAgICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBJbmRpdmlkdWFsO1xuXG4gICAgICAgICAgICAgICAgZnVuY3Rpb24gSW5kaXZpZHVhbChrZXksIHZhbHVlKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmIChrZXkgaW4gcm9vdCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHJvb3Rba2V5XTtcbiAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgIHJvb3Rba2V5XSA9IHZhbHVlO1xuXG4gICAgICAgICAgICAgICAgICAgIHJldHVybiB2YWx1ZTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9KS5jYWxsKHRoaXMsIHR5cGVvZiBnbG9iYWwgIT09IFwidW5kZWZpbmVkXCIgPyBnbG9iYWwgOiB0eXBlb2Ygc2VsZiAhPT0gXCJ1bmRlZmluZWRcIiA/IHNlbGYgOiB0eXBlb2Ygd2luZG93ICE9PSBcInVuZGVmaW5lZFwiID8gd2luZG93IDoge30pO1xuICAgICAgICB9LCB7fV0sIDk6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICBcInVzZSBzdHJpY3RcIjtcblxuICAgICAgICAgICAgdmFyIEluZGl2aWR1YWwgPSByZXF1aXJlKFwiLi9pbmRleC5qc1wiKTtcblxuICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBPbmVWZXJzaW9uO1xuXG4gICAgICAgICAgICBmdW5jdGlvbiBPbmVWZXJzaW9uKG1vZHVsZU5hbWUsIHZlcnNpb24sIGRlZmF1bHRWYWx1ZSkge1xuICAgICAgICAgICAgICAgIHZhciBrZXkgPSBcIl9fSU5ESVZJRFVBTF9PTkVfVkVSU0lPTl9cIiArIG1vZHVsZU5hbWU7XG4gICAgICAgICAgICAgICAgdmFyIGVuZm9yY2VLZXkgPSBrZXkgKyBcIl9FTkZPUkNFX1NJTkdMRVRPTlwiO1xuXG4gICAgICAgICAgICAgICAgdmFyIHZlcnNpb25WYWx1ZSA9IEluZGl2aWR1YWwoZW5mb3JjZUtleSwgdmVyc2lvbik7XG5cbiAgICAgICAgICAgICAgICBpZiAodmVyc2lvblZhbHVlICE9PSB2ZXJzaW9uKSB7XG4gICAgICAgICAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcihcIkNhbiBvbmx5IGhhdmUgb25lIGNvcHkgb2YgXCIgKyBtb2R1bGVOYW1lICsgXCIuXFxuXCIgKyBcIllvdSBhbHJlYWR5IGhhdmUgdmVyc2lvbiBcIiArIHZlcnNpb25WYWx1ZSArIFwiIGluc3RhbGxlZC5cXG5cIiArIFwiVGhpcyBtZWFucyB5b3UgY2Fubm90IGluc3RhbGwgdmVyc2lvbiBcIiArIHZlcnNpb24pO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHJldHVybiBJbmRpdmlkdWFsKGtleSwgZGVmYXVsdFZhbHVlKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSwgeyBcIi4vaW5kZXguanNcIjogOCB9XSwgMTA6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICAoZnVuY3Rpb24gKGdsb2JhbCkge1xuICAgICAgICAgICAgICAgIHZhciB0b3BMZXZlbCA9IHR5cGVvZiBnbG9iYWwgIT09IFwidW5kZWZpbmVkXCIgPyBnbG9iYWwgOiB0eXBlb2Ygd2luZG93ICE9PSBcInVuZGVmaW5lZFwiID8gd2luZG93IDoge307XG4gICAgICAgICAgICAgICAgdmFyIG1pbkRvYyA9IHJlcXVpcmUoXCJtaW4tZG9jdW1lbnRcIik7XG5cbiAgICAgICAgICAgICAgICBpZiAodHlwZW9mIGRvY3VtZW50ICE9PSBcInVuZGVmaW5lZFwiKSB7XG4gICAgICAgICAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gZG9jdW1lbnQ7XG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgdmFyIGRvY2N5ID0gdG9wTGV2ZWxbXCJfX0dMT0JBTF9ET0NVTUVOVF9DQUNIRUA0XCJdO1xuXG4gICAgICAgICAgICAgICAgICAgIGlmICghZG9jY3kpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGRvY2N5ID0gdG9wTGV2ZWxbXCJfX0dMT0JBTF9ET0NVTUVOVF9DQUNIRUA0XCJdID0gbWluRG9jO1xuICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBkb2NjeTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9KS5jYWxsKHRoaXMsIHR5cGVvZiBnbG9iYWwgIT09IFwidW5kZWZpbmVkXCIgPyBnbG9iYWwgOiB0eXBlb2Ygc2VsZiAhPT0gXCJ1bmRlZmluZWRcIiA/IHNlbGYgOiB0eXBlb2Ygd2luZG93ICE9PSBcInVuZGVmaW5lZFwiID8gd2luZG93IDoge30pO1xuICAgICAgICB9LCB7IFwibWluLWRvY3VtZW50XCI6IDYgfV0sIDExOiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge1xuICAgICAgICAgICAgXCJ1c2Ugc3RyaWN0XCI7XG5cbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gaXNPYmplY3QoeCkge1xuICAgICAgICAgICAgICAgIHJldHVybiB0eXBlb2YgeCA9PT0gXCJvYmplY3RcIiAmJiB4ICE9PSBudWxsO1xuICAgICAgICAgICAgfTtcbiAgICAgICAgfSwge31dLCAxMjogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHtcbiAgICAgICAgICAgIHZhciBuYXRpdmVJc0FycmF5ID0gQXJyYXkuaXNBcnJheTtcbiAgICAgICAgICAgIHZhciB0b1N0cmluZyA9IE9iamVjdC5wcm90b3R5cGUudG9TdHJpbmc7XG5cbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gbmF0aXZlSXNBcnJheSB8fCBpc0FycmF5O1xuXG4gICAgICAgICAgICBmdW5jdGlvbiBpc0FycmF5KG9iaikge1xuICAgICAgICAgICAgICAgIHJldHVybiB0b1N0cmluZy5jYWxsKG9iaikgPT09IFwiW29iamVjdCBBcnJheV1cIjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSwge31dLCAxMzogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHtcbiAgICAgICAgICAgIHZhciBwYXRjaCA9IHJlcXVpcmUoXCIuL3Zkb20vcGF0Y2guanNcIik7XG5cbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gcGF0Y2g7XG4gICAgICAgIH0sIHsgXCIuL3Zkb20vcGF0Y2guanNcIjogMTggfV0sIDE0OiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge1xuICAgICAgICAgICAgdmFyIGlzT2JqZWN0ID0gcmVxdWlyZShcImlzLW9iamVjdFwiKTtcbiAgICAgICAgICAgIHZhciBpc0hvb2sgPSByZXF1aXJlKFwiLi4vdm5vZGUvaXMtdmhvb2suanNcIik7XG5cbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gYXBwbHlQcm9wZXJ0aWVzO1xuXG4gICAgICAgICAgICBmdW5jdGlvbiBhcHBseVByb3BlcnRpZXMobm9kZSwgcHJvcHMsIHByZXZpb3VzKSB7XG4gICAgICAgICAgICAgICAgZm9yICh2YXIgcHJvcE5hbWUgaW4gcHJvcHMpIHtcbiAgICAgICAgICAgICAgICAgICAgdmFyIHByb3BWYWx1ZSA9IHByb3BzW3Byb3BOYW1lXTtcblxuICAgICAgICAgICAgICAgICAgICBpZiAocHJvcFZhbHVlID09PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJlbW92ZVByb3BlcnR5KG5vZGUsIHByb3BOYW1lLCBwcm9wVmFsdWUsIHByZXZpb3VzKTtcbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIGlmIChpc0hvb2socHJvcFZhbHVlKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgcmVtb3ZlUHJvcGVydHkobm9kZSwgcHJvcE5hbWUsIHByb3BWYWx1ZSwgcHJldmlvdXMpO1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHByb3BWYWx1ZS5ob29rKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcHJvcFZhbHVlLmhvb2sobm9kZSwgcHJvcE5hbWUsIHByZXZpb3VzID8gcHJldmlvdXNbcHJvcE5hbWVdIDogdW5kZWZpbmVkKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChpc09iamVjdChwcm9wVmFsdWUpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcGF0Y2hPYmplY3Qobm9kZSwgcHJvcHMsIHByZXZpb3VzLCBwcm9wTmFtZSwgcHJvcFZhbHVlKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgbm9kZVtwcm9wTmFtZV0gPSBwcm9wVmFsdWU7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIHJlbW92ZVByb3BlcnR5KG5vZGUsIHByb3BOYW1lLCBwcm9wVmFsdWUsIHByZXZpb3VzKSB7XG4gICAgICAgICAgICAgICAgaWYgKHByZXZpb3VzKSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciBwcmV2aW91c1ZhbHVlID0gcHJldmlvdXNbcHJvcE5hbWVdO1xuXG4gICAgICAgICAgICAgICAgICAgIGlmICghaXNIb29rKHByZXZpb3VzVmFsdWUpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAocHJvcE5hbWUgPT09IFwiYXR0cmlidXRlc1wiKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgZm9yICh2YXIgYXR0ck5hbWUgaW4gcHJldmlvdXNWYWx1ZSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBub2RlLnJlbW92ZUF0dHJpYnV0ZShhdHRyTmFtZSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIGlmIChwcm9wTmFtZSA9PT0gXCJzdHlsZVwiKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgZm9yICh2YXIgaSBpbiBwcmV2aW91c1ZhbHVlKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG5vZGUuc3R5bGVbaV0gPSBcIlwiO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAodHlwZW9mIHByZXZpb3VzVmFsdWUgPT09IFwic3RyaW5nXCIpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBub2RlW3Byb3BOYW1lXSA9IFwiXCI7XG4gICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIG5vZGVbcHJvcE5hbWVdID0gbnVsbDtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIGlmIChwcmV2aW91c1ZhbHVlLnVuaG9vaykge1xuICAgICAgICAgICAgICAgICAgICAgICAgcHJldmlvdXNWYWx1ZS51bmhvb2sobm9kZSwgcHJvcE5hbWUsIHByb3BWYWx1ZSk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIHBhdGNoT2JqZWN0KG5vZGUsIHByb3BzLCBwcmV2aW91cywgcHJvcE5hbWUsIHByb3BWYWx1ZSkge1xuICAgICAgICAgICAgICAgIHZhciBwcmV2aW91c1ZhbHVlID0gcHJldmlvdXMgPyBwcmV2aW91c1twcm9wTmFtZV0gOiB1bmRlZmluZWQ7XG5cbiAgICAgICAgICAgICAgICAvLyBTZXQgYXR0cmlidXRlc1xuICAgICAgICAgICAgICAgIGlmIChwcm9wTmFtZSA9PT0gXCJhdHRyaWJ1dGVzXCIpIHtcbiAgICAgICAgICAgICAgICAgICAgZm9yICh2YXIgYXR0ck5hbWUgaW4gcHJvcFZhbHVlKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICB2YXIgYXR0clZhbHVlID0gcHJvcFZhbHVlW2F0dHJOYW1lXTtcblxuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGF0dHJWYWx1ZSA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgbm9kZS5yZW1vdmVBdHRyaWJ1dGUoYXR0ck5hbWUpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBub2RlLnNldEF0dHJpYnV0ZShhdHRyTmFtZSwgYXR0clZhbHVlKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICBpZiAocHJldmlvdXNWYWx1ZSAmJiBpc09iamVjdChwcmV2aW91c1ZhbHVlKSAmJiBnZXRQcm90b3R5cGUocHJldmlvdXNWYWx1ZSkgIT09IGdldFByb3RvdHlwZShwcm9wVmFsdWUpKSB7XG4gICAgICAgICAgICAgICAgICAgIG5vZGVbcHJvcE5hbWVdID0gcHJvcFZhbHVlO1xuICAgICAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgaWYgKCFpc09iamVjdChub2RlW3Byb3BOYW1lXSkpIHtcbiAgICAgICAgICAgICAgICAgICAgbm9kZVtwcm9wTmFtZV0gPSB7fTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICB2YXIgcmVwbGFjZXIgPSBwcm9wTmFtZSA9PT0gXCJzdHlsZVwiID8gXCJcIiA6IHVuZGVmaW5lZDtcblxuICAgICAgICAgICAgICAgIGZvciAodmFyIGsgaW4gcHJvcFZhbHVlKSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciB2YWx1ZSA9IHByb3BWYWx1ZVtrXTtcbiAgICAgICAgICAgICAgICAgICAgbm9kZVtwcm9wTmFtZV1ba10gPSB2YWx1ZSA9PT0gdW5kZWZpbmVkID8gcmVwbGFjZXIgOiB2YWx1ZTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIGdldFByb3RvdHlwZSh2YWx1ZSkge1xuICAgICAgICAgICAgICAgIGlmIChPYmplY3QuZ2V0UHJvdG90eXBlT2YpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIE9iamVjdC5nZXRQcm90b3R5cGVPZih2YWx1ZSk7XG4gICAgICAgICAgICAgICAgfSBlbHNlIGlmICh2YWx1ZS5fX3Byb3RvX18pIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHZhbHVlLl9fcHJvdG9fXztcbiAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKHZhbHVlLmNvbnN0cnVjdG9yKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiB2YWx1ZS5jb25zdHJ1Y3Rvci5wcm90b3R5cGU7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9LCB7IFwiLi4vdm5vZGUvaXMtdmhvb2suanNcIjogMjYsIFwiaXMtb2JqZWN0XCI6IDExIH1dLCAxNTogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHtcbiAgICAgICAgICAgIHZhciBkb2N1bWVudCA9IHJlcXVpcmUoXCJnbG9iYWwvZG9jdW1lbnRcIik7XG5cbiAgICAgICAgICAgIHZhciBhcHBseVByb3BlcnRpZXMgPSByZXF1aXJlKFwiLi9hcHBseS1wcm9wZXJ0aWVzXCIpO1xuXG4gICAgICAgICAgICB2YXIgaXNWTm9kZSA9IHJlcXVpcmUoXCIuLi92bm9kZS9pcy12bm9kZS5qc1wiKTtcbiAgICAgICAgICAgIHZhciBpc1ZUZXh0ID0gcmVxdWlyZShcIi4uL3Zub2RlL2lzLXZ0ZXh0LmpzXCIpO1xuICAgICAgICAgICAgdmFyIGlzV2lkZ2V0ID0gcmVxdWlyZShcIi4uL3Zub2RlL2lzLXdpZGdldC5qc1wiKTtcbiAgICAgICAgICAgIHZhciBoYW5kbGVUaHVuayA9IHJlcXVpcmUoXCIuLi92bm9kZS9oYW5kbGUtdGh1bmsuanNcIik7XG5cbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gY3JlYXRlRWxlbWVudDtcblxuICAgICAgICAgICAgZnVuY3Rpb24gY3JlYXRlRWxlbWVudCh2bm9kZSwgb3B0cykge1xuICAgICAgICAgICAgICAgIHZhciBkb2MgPSBvcHRzID8gb3B0cy5kb2N1bWVudCB8fCBkb2N1bWVudCA6IGRvY3VtZW50O1xuICAgICAgICAgICAgICAgIHZhciB3YXJuID0gb3B0cyA/IG9wdHMud2FybiA6IG51bGw7XG5cbiAgICAgICAgICAgICAgICB2bm9kZSA9IGhhbmRsZVRodW5rKHZub2RlKS5hO1xuXG4gICAgICAgICAgICAgICAgaWYgKGlzV2lkZ2V0KHZub2RlKSkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gdm5vZGUuaW5pdCgpO1xuICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoaXNWVGV4dCh2bm9kZSkpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGRvYy5jcmVhdGVUZXh0Tm9kZSh2bm9kZS50ZXh0KTtcbiAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKCFpc1ZOb2RlKHZub2RlKSkge1xuICAgICAgICAgICAgICAgICAgICBpZiAod2Fybikge1xuICAgICAgICAgICAgICAgICAgICAgICAgd2FybihcIkl0ZW0gaXMgbm90IGEgdmFsaWQgdmlydHVhbCBkb20gbm9kZVwiLCB2bm9kZSk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIG51bGw7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgdmFyIG5vZGUgPSB2bm9kZS5uYW1lc3BhY2UgPT09IG51bGwgPyBkb2MuY3JlYXRlRWxlbWVudCh2bm9kZS50YWdOYW1lKSA6IGRvYy5jcmVhdGVFbGVtZW50TlModm5vZGUubmFtZXNwYWNlLCB2bm9kZS50YWdOYW1lKTtcblxuICAgICAgICAgICAgICAgIHZhciBwcm9wcyA9IHZub2RlLnByb3BlcnRpZXM7XG4gICAgICAgICAgICAgICAgYXBwbHlQcm9wZXJ0aWVzKG5vZGUsIHByb3BzKTtcblxuICAgICAgICAgICAgICAgIHZhciBjaGlsZHJlbiA9IHZub2RlLmNoaWxkcmVuO1xuXG4gICAgICAgICAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCBjaGlsZHJlbi5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgICAgICAgICB2YXIgY2hpbGROb2RlID0gY3JlYXRlRWxlbWVudChjaGlsZHJlbltpXSwgb3B0cyk7XG4gICAgICAgICAgICAgICAgICAgIGlmIChjaGlsZE5vZGUpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIG5vZGUuYXBwZW5kQ2hpbGQoY2hpbGROb2RlKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHJldHVybiBub2RlO1xuICAgICAgICAgICAgfVxuICAgICAgICB9LCB7IFwiLi4vdm5vZGUvaGFuZGxlLXRodW5rLmpzXCI6IDI0LCBcIi4uL3Zub2RlL2lzLXZub2RlLmpzXCI6IDI3LCBcIi4uL3Zub2RlL2lzLXZ0ZXh0LmpzXCI6IDI4LCBcIi4uL3Zub2RlL2lzLXdpZGdldC5qc1wiOiAyOSwgXCIuL2FwcGx5LXByb3BlcnRpZXNcIjogMTQsIFwiZ2xvYmFsL2RvY3VtZW50XCI6IDEwIH1dLCAxNjogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHtcbiAgICAgICAgICAgIC8vIE1hcHMgYSB2aXJ0dWFsIERPTSB0cmVlIG9udG8gYSByZWFsIERPTSB0cmVlIGluIGFuIGVmZmljaWVudCBtYW5uZXIuXG4gICAgICAgICAgICAvLyBXZSBkb24ndCB3YW50IHRvIHJlYWQgYWxsIG9mIHRoZSBET00gbm9kZXMgaW4gdGhlIHRyZWUgc28gd2UgdXNlXG4gICAgICAgICAgICAvLyB0aGUgaW4tb3JkZXIgdHJlZSBpbmRleGluZyB0byBlbGltaW5hdGUgcmVjdXJzaW9uIGRvd24gY2VydGFpbiBicmFuY2hlcy5cbiAgICAgICAgICAgIC8vIFdlIG9ubHkgcmVjdXJzZSBpbnRvIGEgRE9NIG5vZGUgaWYgd2Uga25vdyB0aGF0IGl0IGNvbnRhaW5zIGEgY2hpbGQgb2ZcbiAgICAgICAgICAgIC8vIGludGVyZXN0LlxuXG4gICAgICAgICAgICB2YXIgbm9DaGlsZCA9IHt9O1xuXG4gICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IGRvbUluZGV4O1xuXG4gICAgICAgICAgICBmdW5jdGlvbiBkb21JbmRleChyb290Tm9kZSwgdHJlZSwgaW5kaWNlcywgbm9kZXMpIHtcbiAgICAgICAgICAgICAgICBpZiAoIWluZGljZXMgfHwgaW5kaWNlcy5sZW5ndGggPT09IDApIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHt9O1xuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIGluZGljZXMuc29ydChhc2NlbmRpbmcpO1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gcmVjdXJzZShyb290Tm9kZSwgdHJlZSwgaW5kaWNlcywgbm9kZXMsIDApO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZnVuY3Rpb24gcmVjdXJzZShyb290Tm9kZSwgdHJlZSwgaW5kaWNlcywgbm9kZXMsIHJvb3RJbmRleCkge1xuICAgICAgICAgICAgICAgIG5vZGVzID0gbm9kZXMgfHwge307XG5cbiAgICAgICAgICAgICAgICBpZiAocm9vdE5vZGUpIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKGluZGV4SW5SYW5nZShpbmRpY2VzLCByb290SW5kZXgsIHJvb3RJbmRleCkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIG5vZGVzW3Jvb3RJbmRleF0gPSByb290Tm9kZTtcbiAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgIHZhciB2Q2hpbGRyZW4gPSB0cmVlLmNoaWxkcmVuO1xuXG4gICAgICAgICAgICAgICAgICAgIGlmICh2Q2hpbGRyZW4pIHtcblxuICAgICAgICAgICAgICAgICAgICAgICAgdmFyIGNoaWxkTm9kZXMgPSByb290Tm9kZS5jaGlsZE5vZGVzO1xuXG4gICAgICAgICAgICAgICAgICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IHRyZWUuY2hpbGRyZW4ubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICByb290SW5kZXggKz0gMTtcblxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZhciB2Q2hpbGQgPSB2Q2hpbGRyZW5baV0gfHwgbm9DaGlsZDtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB2YXIgbmV4dEluZGV4ID0gcm9vdEluZGV4ICsgKHZDaGlsZC5jb3VudCB8fCAwKTtcblxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIHNraXAgcmVjdXJzaW9uIGRvd24gdGhlIHRyZWUgaWYgdGhlcmUgYXJlIG5vIG5vZGVzIGRvd24gaGVyZVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChpbmRleEluUmFuZ2UoaW5kaWNlcywgcm9vdEluZGV4LCBuZXh0SW5kZXgpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlY3Vyc2UoY2hpbGROb2Rlc1tpXSwgdkNoaWxkLCBpbmRpY2VzLCBub2Rlcywgcm9vdEluZGV4KTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICByb290SW5kZXggPSBuZXh0SW5kZXg7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICByZXR1cm4gbm9kZXM7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIC8vIEJpbmFyeSBzZWFyY2ggZm9yIGFuIGluZGV4IGluIHRoZSBpbnRlcnZhbCBbbGVmdCwgcmlnaHRdXG4gICAgICAgICAgICBmdW5jdGlvbiBpbmRleEluUmFuZ2UoaW5kaWNlcywgbGVmdCwgcmlnaHQpIHtcbiAgICAgICAgICAgICAgICBpZiAoaW5kaWNlcy5sZW5ndGggPT09IDApIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHZhciBtaW5JbmRleCA9IDA7XG4gICAgICAgICAgICAgICAgdmFyIG1heEluZGV4ID0gaW5kaWNlcy5sZW5ndGggLSAxO1xuICAgICAgICAgICAgICAgIHZhciBjdXJyZW50SW5kZXg7XG4gICAgICAgICAgICAgICAgdmFyIGN1cnJlbnRJdGVtO1xuXG4gICAgICAgICAgICAgICAgd2hpbGUgKG1pbkluZGV4IDw9IG1heEluZGV4KSB7XG4gICAgICAgICAgICAgICAgICAgIGN1cnJlbnRJbmRleCA9IChtYXhJbmRleCArIG1pbkluZGV4KSAvIDIgPj4gMDtcbiAgICAgICAgICAgICAgICAgICAgY3VycmVudEl0ZW0gPSBpbmRpY2VzW2N1cnJlbnRJbmRleF07XG5cbiAgICAgICAgICAgICAgICAgICAgaWYgKG1pbkluZGV4ID09PSBtYXhJbmRleCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGN1cnJlbnRJdGVtID49IGxlZnQgJiYgY3VycmVudEl0ZW0gPD0gcmlnaHQ7XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoY3VycmVudEl0ZW0gPCBsZWZ0KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBtaW5JbmRleCA9IGN1cnJlbnRJbmRleCArIDE7XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoY3VycmVudEl0ZW0gPiByaWdodCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgbWF4SW5kZXggPSBjdXJyZW50SW5kZXggLSAxO1xuICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIGFzY2VuZGluZyhhLCBiKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGEgPiBiID8gMSA6IC0xO1xuICAgICAgICAgICAgfVxuICAgICAgICB9LCB7fV0sIDE3OiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge1xuICAgICAgICAgICAgdmFyIGFwcGx5UHJvcGVydGllcyA9IHJlcXVpcmUoXCIuL2FwcGx5LXByb3BlcnRpZXNcIik7XG5cbiAgICAgICAgICAgIHZhciBpc1dpZGdldCA9IHJlcXVpcmUoXCIuLi92bm9kZS9pcy13aWRnZXQuanNcIik7XG4gICAgICAgICAgICB2YXIgVlBhdGNoID0gcmVxdWlyZShcIi4uL3Zub2RlL3ZwYXRjaC5qc1wiKTtcblxuICAgICAgICAgICAgdmFyIHVwZGF0ZVdpZGdldCA9IHJlcXVpcmUoXCIuL3VwZGF0ZS13aWRnZXRcIik7XG5cbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gYXBwbHlQYXRjaDtcblxuICAgICAgICAgICAgZnVuY3Rpb24gYXBwbHlQYXRjaCh2cGF0Y2gsIGRvbU5vZGUsIHJlbmRlck9wdGlvbnMpIHtcbiAgICAgICAgICAgICAgICB2YXIgdHlwZSA9IHZwYXRjaC50eXBlO1xuICAgICAgICAgICAgICAgIHZhciB2Tm9kZSA9IHZwYXRjaC52Tm9kZTtcbiAgICAgICAgICAgICAgICB2YXIgcGF0Y2ggPSB2cGF0Y2gucGF0Y2g7XG5cbiAgICAgICAgICAgICAgICBzd2l0Y2ggKHR5cGUpIHtcbiAgICAgICAgICAgICAgICAgICAgY2FzZSBWUGF0Y2guUkVNT1ZFOlxuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHJlbW92ZU5vZGUoZG9tTm9kZSwgdk5vZGUpO1xuICAgICAgICAgICAgICAgICAgICBjYXNlIFZQYXRjaC5JTlNFUlQ6XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gaW5zZXJ0Tm9kZShkb21Ob2RlLCBwYXRjaCwgcmVuZGVyT3B0aW9ucyk7XG4gICAgICAgICAgICAgICAgICAgIGNhc2UgVlBhdGNoLlZURVhUOlxuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHN0cmluZ1BhdGNoKGRvbU5vZGUsIHZOb2RlLCBwYXRjaCwgcmVuZGVyT3B0aW9ucyk7XG4gICAgICAgICAgICAgICAgICAgIGNhc2UgVlBhdGNoLldJREdFVDpcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiB3aWRnZXRQYXRjaChkb21Ob2RlLCB2Tm9kZSwgcGF0Y2gsIHJlbmRlck9wdGlvbnMpO1xuICAgICAgICAgICAgICAgICAgICBjYXNlIFZQYXRjaC5WTk9ERTpcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiB2Tm9kZVBhdGNoKGRvbU5vZGUsIHZOb2RlLCBwYXRjaCwgcmVuZGVyT3B0aW9ucyk7XG4gICAgICAgICAgICAgICAgICAgIGNhc2UgVlBhdGNoLk9SREVSOlxuICAgICAgICAgICAgICAgICAgICAgICAgcmVvcmRlckNoaWxkcmVuKGRvbU5vZGUsIHBhdGNoKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBkb21Ob2RlO1xuICAgICAgICAgICAgICAgICAgICBjYXNlIFZQYXRjaC5QUk9QUzpcbiAgICAgICAgICAgICAgICAgICAgICAgIGFwcGx5UHJvcGVydGllcyhkb21Ob2RlLCBwYXRjaCwgdk5vZGUucHJvcGVydGllcyk7XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gZG9tTm9kZTtcbiAgICAgICAgICAgICAgICAgICAgY2FzZSBWUGF0Y2guVEhVTks6XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gcmVwbGFjZVJvb3QoZG9tTm9kZSwgcmVuZGVyT3B0aW9ucy5wYXRjaChkb21Ob2RlLCBwYXRjaCwgcmVuZGVyT3B0aW9ucykpO1xuICAgICAgICAgICAgICAgICAgICBkZWZhdWx0OlxuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGRvbU5vZGU7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBmdW5jdGlvbiByZW1vdmVOb2RlKGRvbU5vZGUsIHZOb2RlKSB7XG4gICAgICAgICAgICAgICAgdmFyIHBhcmVudE5vZGUgPSBkb21Ob2RlLnBhcmVudE5vZGU7XG5cbiAgICAgICAgICAgICAgICBpZiAocGFyZW50Tm9kZSkge1xuICAgICAgICAgICAgICAgICAgICBwYXJlbnROb2RlLnJlbW92ZUNoaWxkKGRvbU5vZGUpO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIGRlc3Ryb3lXaWRnZXQoZG9tTm9kZSwgdk5vZGUpO1xuXG4gICAgICAgICAgICAgICAgcmV0dXJuIG51bGw7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIGluc2VydE5vZGUocGFyZW50Tm9kZSwgdk5vZGUsIHJlbmRlck9wdGlvbnMpIHtcbiAgICAgICAgICAgICAgICB2YXIgbmV3Tm9kZSA9IHJlbmRlck9wdGlvbnMucmVuZGVyKHZOb2RlLCByZW5kZXJPcHRpb25zKTtcblxuICAgICAgICAgICAgICAgIGlmIChwYXJlbnROb2RlKSB7XG4gICAgICAgICAgICAgICAgICAgIHBhcmVudE5vZGUuYXBwZW5kQ2hpbGQobmV3Tm9kZSk7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgcmV0dXJuIHBhcmVudE5vZGU7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIHN0cmluZ1BhdGNoKGRvbU5vZGUsIGxlZnRWTm9kZSwgdlRleHQsIHJlbmRlck9wdGlvbnMpIHtcbiAgICAgICAgICAgICAgICB2YXIgbmV3Tm9kZTtcblxuICAgICAgICAgICAgICAgIGlmIChkb21Ob2RlLm5vZGVUeXBlID09PSAzKSB7XG4gICAgICAgICAgICAgICAgICAgIGRvbU5vZGUucmVwbGFjZURhdGEoMCwgZG9tTm9kZS5sZW5ndGgsIHZUZXh0LnRleHQpO1xuICAgICAgICAgICAgICAgICAgICBuZXdOb2RlID0gZG9tTm9kZTtcbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICB2YXIgcGFyZW50Tm9kZSA9IGRvbU5vZGUucGFyZW50Tm9kZTtcbiAgICAgICAgICAgICAgICAgICAgbmV3Tm9kZSA9IHJlbmRlck9wdGlvbnMucmVuZGVyKHZUZXh0LCByZW5kZXJPcHRpb25zKTtcblxuICAgICAgICAgICAgICAgICAgICBpZiAocGFyZW50Tm9kZSAmJiBuZXdOb2RlICE9PSBkb21Ob2RlKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBwYXJlbnROb2RlLnJlcGxhY2VDaGlsZChuZXdOb2RlLCBkb21Ob2RlKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHJldHVybiBuZXdOb2RlO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBmdW5jdGlvbiB3aWRnZXRQYXRjaChkb21Ob2RlLCBsZWZ0Vk5vZGUsIHdpZGdldCwgcmVuZGVyT3B0aW9ucykge1xuICAgICAgICAgICAgICAgIHZhciB1cGRhdGluZyA9IHVwZGF0ZVdpZGdldChsZWZ0Vk5vZGUsIHdpZGdldCk7XG4gICAgICAgICAgICAgICAgdmFyIG5ld05vZGU7XG5cbiAgICAgICAgICAgICAgICBpZiAodXBkYXRpbmcpIHtcbiAgICAgICAgICAgICAgICAgICAgbmV3Tm9kZSA9IHdpZGdldC51cGRhdGUobGVmdFZOb2RlLCBkb21Ob2RlKSB8fCBkb21Ob2RlO1xuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIG5ld05vZGUgPSByZW5kZXJPcHRpb25zLnJlbmRlcih3aWRnZXQsIHJlbmRlck9wdGlvbnMpO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHZhciBwYXJlbnROb2RlID0gZG9tTm9kZS5wYXJlbnROb2RlO1xuXG4gICAgICAgICAgICAgICAgaWYgKHBhcmVudE5vZGUgJiYgbmV3Tm9kZSAhPT0gZG9tTm9kZSkge1xuICAgICAgICAgICAgICAgICAgICBwYXJlbnROb2RlLnJlcGxhY2VDaGlsZChuZXdOb2RlLCBkb21Ob2RlKTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICBpZiAoIXVwZGF0aW5nKSB7XG4gICAgICAgICAgICAgICAgICAgIGRlc3Ryb3lXaWRnZXQoZG9tTm9kZSwgbGVmdFZOb2RlKTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICByZXR1cm4gbmV3Tm9kZTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZnVuY3Rpb24gdk5vZGVQYXRjaChkb21Ob2RlLCBsZWZ0Vk5vZGUsIHZOb2RlLCByZW5kZXJPcHRpb25zKSB7XG4gICAgICAgICAgICAgICAgdmFyIHBhcmVudE5vZGUgPSBkb21Ob2RlLnBhcmVudE5vZGU7XG4gICAgICAgICAgICAgICAgdmFyIG5ld05vZGUgPSByZW5kZXJPcHRpb25zLnJlbmRlcih2Tm9kZSwgcmVuZGVyT3B0aW9ucyk7XG5cbiAgICAgICAgICAgICAgICBpZiAocGFyZW50Tm9kZSAmJiBuZXdOb2RlICE9PSBkb21Ob2RlKSB7XG4gICAgICAgICAgICAgICAgICAgIHBhcmVudE5vZGUucmVwbGFjZUNoaWxkKG5ld05vZGUsIGRvbU5vZGUpO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHJldHVybiBuZXdOb2RlO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBmdW5jdGlvbiBkZXN0cm95V2lkZ2V0KGRvbU5vZGUsIHcpIHtcbiAgICAgICAgICAgICAgICBpZiAodHlwZW9mIHcuZGVzdHJveSA9PT0gXCJmdW5jdGlvblwiICYmIGlzV2lkZ2V0KHcpKSB7XG4gICAgICAgICAgICAgICAgICAgIHcuZGVzdHJveShkb21Ob2RlKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIHJlb3JkZXJDaGlsZHJlbihkb21Ob2RlLCBtb3Zlcykge1xuICAgICAgICAgICAgICAgIHZhciBjaGlsZE5vZGVzID0gZG9tTm9kZS5jaGlsZE5vZGVzO1xuICAgICAgICAgICAgICAgIHZhciBrZXlNYXAgPSB7fTtcbiAgICAgICAgICAgICAgICB2YXIgbm9kZTtcbiAgICAgICAgICAgICAgICB2YXIgcmVtb3ZlO1xuICAgICAgICAgICAgICAgIHZhciBpbnNlcnQ7XG5cbiAgICAgICAgICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IG1vdmVzLnJlbW92ZXMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgICAgICAgICAgcmVtb3ZlID0gbW92ZXMucmVtb3Zlc1tpXTtcbiAgICAgICAgICAgICAgICAgICAgbm9kZSA9IGNoaWxkTm9kZXNbcmVtb3ZlLmZyb21dO1xuICAgICAgICAgICAgICAgICAgICBpZiAocmVtb3ZlLmtleSkge1xuICAgICAgICAgICAgICAgICAgICAgICAga2V5TWFwW3JlbW92ZS5rZXldID0gbm9kZTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICBkb21Ob2RlLnJlbW92ZUNoaWxkKG5vZGUpO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHZhciBsZW5ndGggPSBjaGlsZE5vZGVzLmxlbmd0aDtcbiAgICAgICAgICAgICAgICBmb3IgKHZhciBqID0gMDsgaiA8IG1vdmVzLmluc2VydHMubGVuZ3RoOyBqKyspIHtcbiAgICAgICAgICAgICAgICAgICAgaW5zZXJ0ID0gbW92ZXMuaW5zZXJ0c1tqXTtcbiAgICAgICAgICAgICAgICAgICAgbm9kZSA9IGtleU1hcFtpbnNlcnQua2V5XTtcbiAgICAgICAgICAgICAgICAgICAgLy8gdGhpcyBpcyB0aGUgd2VpcmRlc3QgYnVnIGkndmUgZXZlciBzZWVuIGluIHdlYmtpdFxuICAgICAgICAgICAgICAgICAgICBkb21Ob2RlLmluc2VydEJlZm9yZShub2RlLCBpbnNlcnQudG8gPj0gbGVuZ3RoKysgPyBudWxsIDogY2hpbGROb2Rlc1tpbnNlcnQudG9dKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIHJlcGxhY2VSb290KG9sZFJvb3QsIG5ld1Jvb3QpIHtcbiAgICAgICAgICAgICAgICBpZiAob2xkUm9vdCAmJiBuZXdSb290ICYmIG9sZFJvb3QgIT09IG5ld1Jvb3QgJiYgb2xkUm9vdC5wYXJlbnROb2RlKSB7XG4gICAgICAgICAgICAgICAgICAgIG9sZFJvb3QucGFyZW50Tm9kZS5yZXBsYWNlQ2hpbGQobmV3Um9vdCwgb2xkUm9vdCk7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgcmV0dXJuIG5ld1Jvb3Q7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0sIHsgXCIuLi92bm9kZS9pcy13aWRnZXQuanNcIjogMjksIFwiLi4vdm5vZGUvdnBhdGNoLmpzXCI6IDMyLCBcIi4vYXBwbHktcHJvcGVydGllc1wiOiAxNCwgXCIuL3VwZGF0ZS13aWRnZXRcIjogMTkgfV0sIDE4OiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge1xuICAgICAgICAgICAgdmFyIGRvY3VtZW50ID0gcmVxdWlyZShcImdsb2JhbC9kb2N1bWVudFwiKTtcbiAgICAgICAgICAgIHZhciBpc0FycmF5ID0gcmVxdWlyZShcIngtaXMtYXJyYXlcIik7XG5cbiAgICAgICAgICAgIHZhciByZW5kZXIgPSByZXF1aXJlKFwiLi9jcmVhdGUtZWxlbWVudFwiKTtcbiAgICAgICAgICAgIHZhciBkb21JbmRleCA9IHJlcXVpcmUoXCIuL2RvbS1pbmRleFwiKTtcbiAgICAgICAgICAgIHZhciBwYXRjaE9wID0gcmVxdWlyZShcIi4vcGF0Y2gtb3BcIik7XG4gICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IHBhdGNoO1xuXG4gICAgICAgICAgICBmdW5jdGlvbiBwYXRjaChyb290Tm9kZSwgcGF0Y2hlcywgcmVuZGVyT3B0aW9ucykge1xuICAgICAgICAgICAgICAgIHJlbmRlck9wdGlvbnMgPSByZW5kZXJPcHRpb25zIHx8IHt9O1xuICAgICAgICAgICAgICAgIHJlbmRlck9wdGlvbnMucGF0Y2ggPSByZW5kZXJPcHRpb25zLnBhdGNoICYmIHJlbmRlck9wdGlvbnMucGF0Y2ggIT09IHBhdGNoID8gcmVuZGVyT3B0aW9ucy5wYXRjaCA6IHBhdGNoUmVjdXJzaXZlO1xuICAgICAgICAgICAgICAgIHJlbmRlck9wdGlvbnMucmVuZGVyID0gcmVuZGVyT3B0aW9ucy5yZW5kZXIgfHwgcmVuZGVyO1xuXG4gICAgICAgICAgICAgICAgcmV0dXJuIHJlbmRlck9wdGlvbnMucGF0Y2gocm9vdE5vZGUsIHBhdGNoZXMsIHJlbmRlck9wdGlvbnMpO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBmdW5jdGlvbiBwYXRjaFJlY3Vyc2l2ZShyb290Tm9kZSwgcGF0Y2hlcywgcmVuZGVyT3B0aW9ucykge1xuICAgICAgICAgICAgICAgIHZhciBpbmRpY2VzID0gcGF0Y2hJbmRpY2VzKHBhdGNoZXMpO1xuXG4gICAgICAgICAgICAgICAgaWYgKGluZGljZXMubGVuZ3RoID09PSAwKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiByb290Tm9kZTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICB2YXIgaW5kZXggPSBkb21JbmRleChyb290Tm9kZSwgcGF0Y2hlcy5hLCBpbmRpY2VzKTtcbiAgICAgICAgICAgICAgICB2YXIgb3duZXJEb2N1bWVudCA9IHJvb3ROb2RlLm93bmVyRG9jdW1lbnQ7XG5cbiAgICAgICAgICAgICAgICBpZiAoIXJlbmRlck9wdGlvbnMuZG9jdW1lbnQgJiYgb3duZXJEb2N1bWVudCAhPT0gZG9jdW1lbnQpIHtcbiAgICAgICAgICAgICAgICAgICAgcmVuZGVyT3B0aW9ucy5kb2N1bWVudCA9IG93bmVyRG9jdW1lbnQ7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCBpbmRpY2VzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciBub2RlSW5kZXggPSBpbmRpY2VzW2ldO1xuICAgICAgICAgICAgICAgICAgICByb290Tm9kZSA9IGFwcGx5UGF0Y2gocm9vdE5vZGUsIGluZGV4W25vZGVJbmRleF0sIHBhdGNoZXNbbm9kZUluZGV4XSwgcmVuZGVyT3B0aW9ucyk7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgcmV0dXJuIHJvb3ROb2RlO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBmdW5jdGlvbiBhcHBseVBhdGNoKHJvb3ROb2RlLCBkb21Ob2RlLCBwYXRjaExpc3QsIHJlbmRlck9wdGlvbnMpIHtcbiAgICAgICAgICAgICAgICBpZiAoIWRvbU5vZGUpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHJvb3ROb2RlO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHZhciBuZXdOb2RlO1xuXG4gICAgICAgICAgICAgICAgaWYgKGlzQXJyYXkocGF0Y2hMaXN0KSkge1xuICAgICAgICAgICAgICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IHBhdGNoTGlzdC5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgICAgICAgICAgICAgbmV3Tm9kZSA9IHBhdGNoT3AocGF0Y2hMaXN0W2ldLCBkb21Ob2RlLCByZW5kZXJPcHRpb25zKTtcblxuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGRvbU5vZGUgPT09IHJvb3ROb2RlKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcm9vdE5vZGUgPSBuZXdOb2RlO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgbmV3Tm9kZSA9IHBhdGNoT3AocGF0Y2hMaXN0LCBkb21Ob2RlLCByZW5kZXJPcHRpb25zKTtcblxuICAgICAgICAgICAgICAgICAgICBpZiAoZG9tTm9kZSA9PT0gcm9vdE5vZGUpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJvb3ROb2RlID0gbmV3Tm9kZTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHJldHVybiByb290Tm9kZTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZnVuY3Rpb24gcGF0Y2hJbmRpY2VzKHBhdGNoZXMpIHtcbiAgICAgICAgICAgICAgICB2YXIgaW5kaWNlcyA9IFtdO1xuXG4gICAgICAgICAgICAgICAgZm9yICh2YXIga2V5IGluIHBhdGNoZXMpIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKGtleSAhPT0gXCJhXCIpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGluZGljZXMucHVzaChOdW1iZXIoa2V5KSk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICByZXR1cm4gaW5kaWNlcztcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSwgeyBcIi4vY3JlYXRlLWVsZW1lbnRcIjogMTUsIFwiLi9kb20taW5kZXhcIjogMTYsIFwiLi9wYXRjaC1vcFwiOiAxNywgXCJnbG9iYWwvZG9jdW1lbnRcIjogMTAsIFwieC1pcy1hcnJheVwiOiAxMiB9XSwgMTk6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICB2YXIgaXNXaWRnZXQgPSByZXF1aXJlKFwiLi4vdm5vZGUvaXMtd2lkZ2V0LmpzXCIpO1xuXG4gICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IHVwZGF0ZVdpZGdldDtcblxuICAgICAgICAgICAgZnVuY3Rpb24gdXBkYXRlV2lkZ2V0KGEsIGIpIHtcbiAgICAgICAgICAgICAgICBpZiAoaXNXaWRnZXQoYSkgJiYgaXNXaWRnZXQoYikpIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKFwibmFtZVwiIGluIGEgJiYgXCJuYW1lXCIgaW4gYikge1xuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGEuaWQgPT09IGIuaWQ7XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gYS5pbml0ID09PSBiLmluaXQ7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0sIHsgXCIuLi92bm9kZS9pcy13aWRnZXQuanNcIjogMjkgfV0sIDIwOiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge1xuICAgICAgICAgICAgXCJ1c2Ugc3RyaWN0XCI7XG5cbiAgICAgICAgICAgIHZhciBFdlN0b3JlID0gcmVxdWlyZShcImV2LXN0b3JlXCIpO1xuXG4gICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IEV2SG9vaztcblxuICAgICAgICAgICAgZnVuY3Rpb24gRXZIb29rKHZhbHVlKSB7XG4gICAgICAgICAgICAgICAgaWYgKCEodGhpcyBpbnN0YW5jZW9mIEV2SG9vaykpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIG5ldyBFdkhvb2sodmFsdWUpO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHRoaXMudmFsdWUgPSB2YWx1ZTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgRXZIb29rLnByb3RvdHlwZS5ob29rID0gZnVuY3Rpb24gKG5vZGUsIHByb3BlcnR5TmFtZSkge1xuICAgICAgICAgICAgICAgIHZhciBlcyA9IEV2U3RvcmUobm9kZSk7XG4gICAgICAgICAgICAgICAgdmFyIHByb3BOYW1lID0gcHJvcGVydHlOYW1lLnN1YnN0cigzKTtcblxuICAgICAgICAgICAgICAgIGVzW3Byb3BOYW1lXSA9IHRoaXMudmFsdWU7XG4gICAgICAgICAgICB9O1xuXG4gICAgICAgICAgICBFdkhvb2sucHJvdG90eXBlLnVuaG9vayA9IGZ1bmN0aW9uIChub2RlLCBwcm9wZXJ0eU5hbWUpIHtcbiAgICAgICAgICAgICAgICB2YXIgZXMgPSBFdlN0b3JlKG5vZGUpO1xuICAgICAgICAgICAgICAgIHZhciBwcm9wTmFtZSA9IHByb3BlcnR5TmFtZS5zdWJzdHIoMyk7XG5cbiAgICAgICAgICAgICAgICBlc1twcm9wTmFtZV0gPSB1bmRlZmluZWQ7XG4gICAgICAgICAgICB9O1xuICAgICAgICB9LCB7IFwiZXYtc3RvcmVcIjogNyB9XSwgMjE6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICBcInVzZSBzdHJpY3RcIjtcblxuICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBTb2Z0U2V0SG9vaztcblxuICAgICAgICAgICAgZnVuY3Rpb24gU29mdFNldEhvb2sodmFsdWUpIHtcbiAgICAgICAgICAgICAgICBpZiAoISh0aGlzIGluc3RhbmNlb2YgU29mdFNldEhvb2spKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBuZXcgU29mdFNldEhvb2sodmFsdWUpO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHRoaXMudmFsdWUgPSB2YWx1ZTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgU29mdFNldEhvb2sucHJvdG90eXBlLmhvb2sgPSBmdW5jdGlvbiAobm9kZSwgcHJvcGVydHlOYW1lKSB7XG4gICAgICAgICAgICAgICAgaWYgKG5vZGVbcHJvcGVydHlOYW1lXSAhPT0gdGhpcy52YWx1ZSkge1xuICAgICAgICAgICAgICAgICAgICBub2RlW3Byb3BlcnR5TmFtZV0gPSB0aGlzLnZhbHVlO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH07XG4gICAgICAgIH0sIHt9XSwgMjI6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICBcInVzZSBzdHJpY3RcIjtcblxuICAgICAgICAgICAgdmFyIGlzQXJyYXkgPSByZXF1aXJlKFwieC1pcy1hcnJheVwiKTtcblxuICAgICAgICAgICAgdmFyIFZOb2RlID0gcmVxdWlyZShcIi4uL3Zub2RlL3Zub2RlLmpzXCIpO1xuICAgICAgICAgICAgdmFyIFZUZXh0ID0gcmVxdWlyZShcIi4uL3Zub2RlL3Z0ZXh0LmpzXCIpO1xuICAgICAgICAgICAgdmFyIGlzVk5vZGUgPSByZXF1aXJlKFwiLi4vdm5vZGUvaXMtdm5vZGVcIik7XG4gICAgICAgICAgICB2YXIgaXNWVGV4dCA9IHJlcXVpcmUoXCIuLi92bm9kZS9pcy12dGV4dFwiKTtcbiAgICAgICAgICAgIHZhciBpc1dpZGdldCA9IHJlcXVpcmUoXCIuLi92bm9kZS9pcy13aWRnZXRcIik7XG4gICAgICAgICAgICB2YXIgaXNIb29rID0gcmVxdWlyZShcIi4uL3Zub2RlL2lzLXZob29rXCIpO1xuICAgICAgICAgICAgdmFyIGlzVlRodW5rID0gcmVxdWlyZShcIi4uL3Zub2RlL2lzLXRodW5rXCIpO1xuXG4gICAgICAgICAgICB2YXIgcGFyc2VUYWcgPSByZXF1aXJlKFwiLi9wYXJzZS10YWcuanNcIik7XG4gICAgICAgICAgICB2YXIgc29mdFNldEhvb2sgPSByZXF1aXJlKFwiLi9ob29rcy9zb2Z0LXNldC1ob29rLmpzXCIpO1xuICAgICAgICAgICAgdmFyIGV2SG9vayA9IHJlcXVpcmUoXCIuL2hvb2tzL2V2LWhvb2suanNcIik7XG5cbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gaDtcblxuICAgICAgICAgICAgZnVuY3Rpb24gaCh0YWdOYW1lLCBwcm9wZXJ0aWVzLCBjaGlsZHJlbikge1xuICAgICAgICAgICAgICAgIHZhciBjaGlsZE5vZGVzID0gW107XG4gICAgICAgICAgICAgICAgdmFyIHRhZywgcHJvcHMsIGtleSwgbmFtZXNwYWNlO1xuXG4gICAgICAgICAgICAgICAgaWYgKCFjaGlsZHJlbiAmJiBpc0NoaWxkcmVuKHByb3BlcnRpZXMpKSB7XG4gICAgICAgICAgICAgICAgICAgIGNoaWxkcmVuID0gcHJvcGVydGllcztcbiAgICAgICAgICAgICAgICAgICAgcHJvcHMgPSB7fTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICBwcm9wcyA9IHByb3BzIHx8IHByb3BlcnRpZXMgfHwge307XG4gICAgICAgICAgICAgICAgdGFnID0gcGFyc2VUYWcodGFnTmFtZSwgcHJvcHMpO1xuXG4gICAgICAgICAgICAgICAgLy8gc3VwcG9ydCBrZXlzXG4gICAgICAgICAgICAgICAgaWYgKHByb3BzLmhhc093blByb3BlcnR5KFwia2V5XCIpKSB7XG4gICAgICAgICAgICAgICAgICAgIGtleSA9IHByb3BzLmtleTtcbiAgICAgICAgICAgICAgICAgICAgcHJvcHMua2V5ID0gdW5kZWZpbmVkO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIC8vIHN1cHBvcnQgbmFtZXNwYWNlXG4gICAgICAgICAgICAgICAgaWYgKHByb3BzLmhhc093blByb3BlcnR5KFwibmFtZXNwYWNlXCIpKSB7XG4gICAgICAgICAgICAgICAgICAgIG5hbWVzcGFjZSA9IHByb3BzLm5hbWVzcGFjZTtcbiAgICAgICAgICAgICAgICAgICAgcHJvcHMubmFtZXNwYWNlID0gdW5kZWZpbmVkO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIC8vIGZpeCBjdXJzb3IgYnVnXG4gICAgICAgICAgICAgICAgaWYgKHRhZyA9PT0gXCJJTlBVVFwiICYmICFuYW1lc3BhY2UgJiYgcHJvcHMuaGFzT3duUHJvcGVydHkoXCJ2YWx1ZVwiKSAmJiBwcm9wcy52YWx1ZSAhPT0gdW5kZWZpbmVkICYmICFpc0hvb2socHJvcHMudmFsdWUpKSB7XG4gICAgICAgICAgICAgICAgICAgIHByb3BzLnZhbHVlID0gc29mdFNldEhvb2socHJvcHMudmFsdWUpO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHRyYW5zZm9ybVByb3BlcnRpZXMocHJvcHMpO1xuXG4gICAgICAgICAgICAgICAgaWYgKGNoaWxkcmVuICE9PSB1bmRlZmluZWQgJiYgY2hpbGRyZW4gIT09IG51bGwpIHtcbiAgICAgICAgICAgICAgICAgICAgYWRkQ2hpbGQoY2hpbGRyZW4sIGNoaWxkTm9kZXMsIHRhZywgcHJvcHMpO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHJldHVybiBuZXcgVk5vZGUodGFnLCBwcm9wcywgY2hpbGROb2Rlcywga2V5LCBuYW1lc3BhY2UpO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBmdW5jdGlvbiBhZGRDaGlsZChjLCBjaGlsZE5vZGVzLCB0YWcsIHByb3BzKSB7XG4gICAgICAgICAgICAgICAgaWYgKHR5cGVvZiBjID09PSBcInN0cmluZ1wiKSB7XG4gICAgICAgICAgICAgICAgICAgIGNoaWxkTm9kZXMucHVzaChuZXcgVlRleHQoYykpO1xuICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAodHlwZW9mIGMgPT09IFwibnVtYmVyXCIpIHtcbiAgICAgICAgICAgICAgICAgICAgY2hpbGROb2Rlcy5wdXNoKG5ldyBWVGV4dChTdHJpbmcoYykpKTtcbiAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKGlzQ2hpbGQoYykpIHtcbiAgICAgICAgICAgICAgICAgICAgY2hpbGROb2Rlcy5wdXNoKGMpO1xuICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoaXNBcnJheShjKSkge1xuICAgICAgICAgICAgICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IGMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGFkZENoaWxkKGNbaV0sIGNoaWxkTm9kZXMsIHRhZywgcHJvcHMpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfSBlbHNlIGlmIChjID09PSBudWxsIHx8IGMgPT09IHVuZGVmaW5lZCkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgdGhyb3cgVW5leHBlY3RlZFZpcnR1YWxFbGVtZW50KHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGZvcmVpZ25PYmplY3Q6IGMsXG4gICAgICAgICAgICAgICAgICAgICAgICBwYXJlbnRWbm9kZToge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRhZ05hbWU6IHRhZyxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBwcm9wZXJ0aWVzOiBwcm9wc1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIHRyYW5zZm9ybVByb3BlcnRpZXMocHJvcHMpIHtcbiAgICAgICAgICAgICAgICBmb3IgKHZhciBwcm9wTmFtZSBpbiBwcm9wcykge1xuICAgICAgICAgICAgICAgICAgICBpZiAocHJvcHMuaGFzT3duUHJvcGVydHkocHJvcE5hbWUpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICB2YXIgdmFsdWUgPSBwcm9wc1twcm9wTmFtZV07XG5cbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChpc0hvb2sodmFsdWUpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgY29udGludWU7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChwcm9wTmFtZS5zdWJzdHIoMCwgMykgPT09IFwiZXYtXCIpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBhZGQgZXYtZm9vIHN1cHBvcnRcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBwcm9wc1twcm9wTmFtZV0gPSBldkhvb2sodmFsdWUpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBmdW5jdGlvbiBpc0NoaWxkKHgpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gaXNWTm9kZSh4KSB8fCBpc1ZUZXh0KHgpIHx8IGlzV2lkZ2V0KHgpIHx8IGlzVlRodW5rKHgpO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBmdW5jdGlvbiBpc0NoaWxkcmVuKHgpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gdHlwZW9mIHggPT09IFwic3RyaW5nXCIgfHwgaXNBcnJheSh4KSB8fCBpc0NoaWxkKHgpO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBmdW5jdGlvbiBVbmV4cGVjdGVkVmlydHVhbEVsZW1lbnQoZGF0YSkge1xuICAgICAgICAgICAgICAgIHZhciBlcnIgPSBuZXcgRXJyb3IoKTtcblxuICAgICAgICAgICAgICAgIGVyci50eXBlID0gXCJ2aXJ0dWFsLWh5cGVyc2NyaXB0LnVuZXhwZWN0ZWQudmlydHVhbC1lbGVtZW50XCI7XG4gICAgICAgICAgICAgICAgZXJyLm1lc3NhZ2UgPSBcIlVuZXhwZWN0ZWQgdmlydHVhbCBjaGlsZCBwYXNzZWQgdG8gaCgpLlxcblwiICsgXCJFeHBlY3RlZCBhIFZOb2RlIC8gVnRodW5rIC8gVldpZGdldCAvIHN0cmluZyBidXQ6XFxuXCIgKyBcImdvdDpcXG5cIiArIGVycm9yU3RyaW5nKGRhdGEuZm9yZWlnbk9iamVjdCkgKyBcIi5cXG5cIiArIFwiVGhlIHBhcmVudCB2bm9kZSBpczpcXG5cIiArIGVycm9yU3RyaW5nKGRhdGEucGFyZW50Vm5vZGUpO1xuICAgICAgICAgICAgICAgIFwiXFxuXCIgKyBcIlN1Z2dlc3RlZCBmaXg6IGNoYW5nZSB5b3VyIGBoKC4uLiwgWyAuLi4gXSlgIGNhbGxzaXRlLlwiO1xuICAgICAgICAgICAgICAgIGVyci5mb3JlaWduT2JqZWN0ID0gZGF0YS5mb3JlaWduT2JqZWN0O1xuICAgICAgICAgICAgICAgIGVyci5wYXJlbnRWbm9kZSA9IGRhdGEucGFyZW50Vm5vZGU7XG5cbiAgICAgICAgICAgICAgICByZXR1cm4gZXJyO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBmdW5jdGlvbiBlcnJvclN0cmluZyhvYmopIHtcbiAgICAgICAgICAgICAgICB0cnkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gSlNPTi5zdHJpbmdpZnkob2JqLCBudWxsLCBcIiAgICBcIik7XG4gICAgICAgICAgICAgICAgfSBjYXRjaCAoZSkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gU3RyaW5nKG9iaik7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9LCB7IFwiLi4vdm5vZGUvaXMtdGh1bmtcIjogMjUsIFwiLi4vdm5vZGUvaXMtdmhvb2tcIjogMjYsIFwiLi4vdm5vZGUvaXMtdm5vZGVcIjogMjcsIFwiLi4vdm5vZGUvaXMtdnRleHRcIjogMjgsIFwiLi4vdm5vZGUvaXMtd2lkZ2V0XCI6IDI5LCBcIi4uL3Zub2RlL3Zub2RlLmpzXCI6IDMxLCBcIi4uL3Zub2RlL3Z0ZXh0LmpzXCI6IDMzLCBcIi4vaG9va3MvZXYtaG9vay5qc1wiOiAyMCwgXCIuL2hvb2tzL3NvZnQtc2V0LWhvb2suanNcIjogMjEsIFwiLi9wYXJzZS10YWcuanNcIjogMjMsIFwieC1pcy1hcnJheVwiOiAxMiB9XSwgMjM6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICBcInVzZSBzdHJpY3RcIjtcblxuICAgICAgICAgICAgdmFyIHNwbGl0ID0gcmVxdWlyZShcImJyb3dzZXItc3BsaXRcIik7XG5cbiAgICAgICAgICAgIHZhciBjbGFzc0lkU3BsaXQgPSAvKFtcXC4jXT9bYS16QS1aMC05XFx1MDA3Ri1cXHVGRkZGXzotXSspLztcbiAgICAgICAgICAgIHZhciBub3RDbGFzc0lkID0gL15cXC58Iy87XG5cbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gcGFyc2VUYWc7XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIHBhcnNlVGFnKHRhZywgcHJvcHMpIHtcbiAgICAgICAgICAgICAgICBpZiAoIXRhZykge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gXCJESVZcIjtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICB2YXIgbm9JZCA9ICFwcm9wcy5oYXNPd25Qcm9wZXJ0eShcImlkXCIpO1xuXG4gICAgICAgICAgICAgICAgdmFyIHRhZ1BhcnRzID0gc3BsaXQodGFnLCBjbGFzc0lkU3BsaXQpO1xuICAgICAgICAgICAgICAgIHZhciB0YWdOYW1lID0gbnVsbDtcblxuICAgICAgICAgICAgICAgIGlmIChub3RDbGFzc0lkLnRlc3QodGFnUGFydHNbMV0pKSB7XG4gICAgICAgICAgICAgICAgICAgIHRhZ05hbWUgPSBcIkRJVlwiO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHZhciBjbGFzc2VzLCBwYXJ0LCB0eXBlLCBpO1xuXG4gICAgICAgICAgICAgICAgZm9yIChpID0gMDsgaSA8IHRhZ1BhcnRzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICAgICAgICAgIHBhcnQgPSB0YWdQYXJ0c1tpXTtcblxuICAgICAgICAgICAgICAgICAgICBpZiAoIXBhcnQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnRpbnVlO1xuICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgdHlwZSA9IHBhcnQuY2hhckF0KDApO1xuXG4gICAgICAgICAgICAgICAgICAgIGlmICghdGFnTmFtZSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgdGFnTmFtZSA9IHBhcnQ7XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAodHlwZSA9PT0gXCIuXCIpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGNsYXNzZXMgPSBjbGFzc2VzIHx8IFtdO1xuICAgICAgICAgICAgICAgICAgICAgICAgY2xhc3Nlcy5wdXNoKHBhcnQuc3Vic3RyaW5nKDEsIHBhcnQubGVuZ3RoKSk7XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAodHlwZSA9PT0gXCIjXCIgJiYgbm9JZCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgcHJvcHMuaWQgPSBwYXJ0LnN1YnN0cmluZygxLCBwYXJ0Lmxlbmd0aCk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICBpZiAoY2xhc3Nlcykge1xuICAgICAgICAgICAgICAgICAgICBpZiAocHJvcHMuY2xhc3NOYW1lKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBjbGFzc2VzLnB1c2gocHJvcHMuY2xhc3NOYW1lKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgIHByb3BzLmNsYXNzTmFtZSA9IGNsYXNzZXMuam9pbihcIiBcIik7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgcmV0dXJuIHByb3BzLm5hbWVzcGFjZSA/IHRhZ05hbWUgOiB0YWdOYW1lLnRvVXBwZXJDYXNlKCk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0sIHsgXCJicm93c2VyLXNwbGl0XCI6IDUgfV0sIDI0OiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge1xuICAgICAgICAgICAgdmFyIGlzVk5vZGUgPSByZXF1aXJlKFwiLi9pcy12bm9kZVwiKTtcbiAgICAgICAgICAgIHZhciBpc1ZUZXh0ID0gcmVxdWlyZShcIi4vaXMtdnRleHRcIik7XG4gICAgICAgICAgICB2YXIgaXNXaWRnZXQgPSByZXF1aXJlKFwiLi9pcy13aWRnZXRcIik7XG4gICAgICAgICAgICB2YXIgaXNUaHVuayA9IHJlcXVpcmUoXCIuL2lzLXRodW5rXCIpO1xuXG4gICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IGhhbmRsZVRodW5rO1xuXG4gICAgICAgICAgICBmdW5jdGlvbiBoYW5kbGVUaHVuayhhLCBiKSB7XG4gICAgICAgICAgICAgICAgdmFyIHJlbmRlcmVkQSA9IGE7XG4gICAgICAgICAgICAgICAgdmFyIHJlbmRlcmVkQiA9IGI7XG5cbiAgICAgICAgICAgICAgICBpZiAoaXNUaHVuayhiKSkge1xuICAgICAgICAgICAgICAgICAgICByZW5kZXJlZEIgPSByZW5kZXJUaHVuayhiLCBhKTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICBpZiAoaXNUaHVuayhhKSkge1xuICAgICAgICAgICAgICAgICAgICByZW5kZXJlZEEgPSByZW5kZXJUaHVuayhhLCBudWxsKTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgICAgICAgICBhOiByZW5kZXJlZEEsXG4gICAgICAgICAgICAgICAgICAgIGI6IHJlbmRlcmVkQlxuICAgICAgICAgICAgICAgIH07XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIHJlbmRlclRodW5rKHRodW5rLCBwcmV2aW91cykge1xuICAgICAgICAgICAgICAgIHZhciByZW5kZXJlZFRodW5rID0gdGh1bmsudm5vZGU7XG5cbiAgICAgICAgICAgICAgICBpZiAoIXJlbmRlcmVkVGh1bmspIHtcbiAgICAgICAgICAgICAgICAgICAgcmVuZGVyZWRUaHVuayA9IHRodW5rLnZub2RlID0gdGh1bmsucmVuZGVyKHByZXZpb3VzKTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICBpZiAoIShpc1ZOb2RlKHJlbmRlcmVkVGh1bmspIHx8IGlzVlRleHQocmVuZGVyZWRUaHVuaykgfHwgaXNXaWRnZXQocmVuZGVyZWRUaHVuaykpKSB7XG4gICAgICAgICAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcihcInRodW5rIGRpZCBub3QgcmV0dXJuIGEgdmFsaWQgbm9kZVwiKTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICByZXR1cm4gcmVuZGVyZWRUaHVuaztcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSwgeyBcIi4vaXMtdGh1bmtcIjogMjUsIFwiLi9pcy12bm9kZVwiOiAyNywgXCIuL2lzLXZ0ZXh0XCI6IDI4LCBcIi4vaXMtd2lkZ2V0XCI6IDI5IH1dLCAyNTogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHtcbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gaXNUaHVuaztcblxuICAgICAgICAgICAgZnVuY3Rpb24gaXNUaHVuayh0KSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHQgJiYgdC50eXBlID09PSBcIlRodW5rXCI7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0sIHt9XSwgMjY6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IGlzSG9vaztcblxuICAgICAgICAgICAgZnVuY3Rpb24gaXNIb29rKGhvb2spIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gaG9vayAmJiAodHlwZW9mIGhvb2suaG9vayA9PT0gXCJmdW5jdGlvblwiICYmICFob29rLmhhc093blByb3BlcnR5KFwiaG9va1wiKSB8fCB0eXBlb2YgaG9vay51bmhvb2sgPT09IFwiZnVuY3Rpb25cIiAmJiAhaG9vay5oYXNPd25Qcm9wZXJ0eShcInVuaG9va1wiKSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0sIHt9XSwgMjc6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICB2YXIgdmVyc2lvbiA9IHJlcXVpcmUoXCIuL3ZlcnNpb25cIik7XG5cbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gaXNWaXJ0dWFsTm9kZTtcblxuICAgICAgICAgICAgZnVuY3Rpb24gaXNWaXJ0dWFsTm9kZSh4KSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHggJiYgeC50eXBlID09PSBcIlZpcnR1YWxOb2RlXCIgJiYgeC52ZXJzaW9uID09PSB2ZXJzaW9uO1xuICAgICAgICAgICAgfVxuICAgICAgICB9LCB7IFwiLi92ZXJzaW9uXCI6IDMwIH1dLCAyODogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHtcbiAgICAgICAgICAgIHZhciB2ZXJzaW9uID0gcmVxdWlyZShcIi4vdmVyc2lvblwiKTtcblxuICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBpc1ZpcnR1YWxUZXh0O1xuXG4gICAgICAgICAgICBmdW5jdGlvbiBpc1ZpcnR1YWxUZXh0KHgpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4geCAmJiB4LnR5cGUgPT09IFwiVmlydHVhbFRleHRcIiAmJiB4LnZlcnNpb24gPT09IHZlcnNpb247XG4gICAgICAgICAgICB9XG4gICAgICAgIH0sIHsgXCIuL3ZlcnNpb25cIjogMzAgfV0sIDI5OiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge1xuICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBpc1dpZGdldDtcblxuICAgICAgICAgICAgZnVuY3Rpb24gaXNXaWRnZXQodykge1xuICAgICAgICAgICAgICAgIHJldHVybiB3ICYmIHcudHlwZSA9PT0gXCJXaWRnZXRcIjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSwge31dLCAzMDogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHtcbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gXCIyXCI7XG4gICAgICAgIH0sIHt9XSwgMzE6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICB2YXIgdmVyc2lvbiA9IHJlcXVpcmUoXCIuL3ZlcnNpb25cIik7XG4gICAgICAgICAgICB2YXIgaXNWTm9kZSA9IHJlcXVpcmUoXCIuL2lzLXZub2RlXCIpO1xuICAgICAgICAgICAgdmFyIGlzV2lkZ2V0ID0gcmVxdWlyZShcIi4vaXMtd2lkZ2V0XCIpO1xuICAgICAgICAgICAgdmFyIGlzVGh1bmsgPSByZXF1aXJlKFwiLi9pcy10aHVua1wiKTtcbiAgICAgICAgICAgIHZhciBpc1ZIb29rID0gcmVxdWlyZShcIi4vaXMtdmhvb2tcIik7XG5cbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gVmlydHVhbE5vZGU7XG5cbiAgICAgICAgICAgIHZhciBub1Byb3BlcnRpZXMgPSB7fTtcbiAgICAgICAgICAgIHZhciBub0NoaWxkcmVuID0gW107XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIFZpcnR1YWxOb2RlKHRhZ05hbWUsIHByb3BlcnRpZXMsIGNoaWxkcmVuLCBrZXksIG5hbWVzcGFjZSkge1xuICAgICAgICAgICAgICAgIHRoaXMudGFnTmFtZSA9IHRhZ05hbWU7XG4gICAgICAgICAgICAgICAgdGhpcy5wcm9wZXJ0aWVzID0gcHJvcGVydGllcyB8fCBub1Byb3BlcnRpZXM7XG4gICAgICAgICAgICAgICAgdGhpcy5jaGlsZHJlbiA9IGNoaWxkcmVuIHx8IG5vQ2hpbGRyZW47XG4gICAgICAgICAgICAgICAgdGhpcy5rZXkgPSBrZXkgIT0gbnVsbCA/IFN0cmluZyhrZXkpIDogdW5kZWZpbmVkO1xuICAgICAgICAgICAgICAgIHRoaXMubmFtZXNwYWNlID0gdHlwZW9mIG5hbWVzcGFjZSA9PT0gXCJzdHJpbmdcIiA/IG5hbWVzcGFjZSA6IG51bGw7XG5cbiAgICAgICAgICAgICAgICB2YXIgY291bnQgPSBjaGlsZHJlbiAmJiBjaGlsZHJlbi5sZW5ndGggfHwgMDtcbiAgICAgICAgICAgICAgICB2YXIgZGVzY2VuZGFudHMgPSAwO1xuICAgICAgICAgICAgICAgIHZhciBoYXNXaWRnZXRzID0gZmFsc2U7XG4gICAgICAgICAgICAgICAgdmFyIGhhc1RodW5rcyA9IGZhbHNlO1xuICAgICAgICAgICAgICAgIHZhciBkZXNjZW5kYW50SG9va3MgPSBmYWxzZTtcbiAgICAgICAgICAgICAgICB2YXIgaG9va3M7XG5cbiAgICAgICAgICAgICAgICBmb3IgKHZhciBwcm9wTmFtZSBpbiBwcm9wZXJ0aWVzKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmIChwcm9wZXJ0aWVzLmhhc093blByb3BlcnR5KHByb3BOYW1lKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgdmFyIHByb3BlcnR5ID0gcHJvcGVydGllc1twcm9wTmFtZV07XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoaXNWSG9vayhwcm9wZXJ0eSkgJiYgcHJvcGVydHkudW5ob29rKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKCFob29rcykge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBob29rcyA9IHt9O1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGhvb2tzW3Byb3BOYW1lXSA9IHByb3BlcnR5O1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCBjb3VudDsgaSsrKSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciBjaGlsZCA9IGNoaWxkcmVuW2ldO1xuICAgICAgICAgICAgICAgICAgICBpZiAoaXNWTm9kZShjaGlsZCkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGRlc2NlbmRhbnRzICs9IGNoaWxkLmNvdW50IHx8IDA7XG5cbiAgICAgICAgICAgICAgICAgICAgICAgIGlmICghaGFzV2lkZ2V0cyAmJiBjaGlsZC5oYXNXaWRnZXRzKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaGFzV2lkZ2V0cyA9IHRydWU7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgICAgIGlmICghaGFzVGh1bmtzICYmIGNoaWxkLmhhc1RodW5rcykge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGhhc1RodW5rcyA9IHRydWU7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgICAgIGlmICghZGVzY2VuZGFudEhvb2tzICYmIChjaGlsZC5ob29rcyB8fCBjaGlsZC5kZXNjZW5kYW50SG9va3MpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgZGVzY2VuZGFudEhvb2tzID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIGlmICghaGFzV2lkZ2V0cyAmJiBpc1dpZGdldChjaGlsZCkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmICh0eXBlb2YgY2hpbGQuZGVzdHJveSA9PT0gXCJmdW5jdGlvblwiKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaGFzV2lkZ2V0cyA9IHRydWU7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoIWhhc1RodW5rcyAmJiBpc1RodW5rKGNoaWxkKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgaGFzVGh1bmtzID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHRoaXMuY291bnQgPSBjb3VudCArIGRlc2NlbmRhbnRzO1xuICAgICAgICAgICAgICAgIHRoaXMuaGFzV2lkZ2V0cyA9IGhhc1dpZGdldHM7XG4gICAgICAgICAgICAgICAgdGhpcy5oYXNUaHVua3MgPSBoYXNUaHVua3M7XG4gICAgICAgICAgICAgICAgdGhpcy5ob29rcyA9IGhvb2tzO1xuICAgICAgICAgICAgICAgIHRoaXMuZGVzY2VuZGFudEhvb2tzID0gZGVzY2VuZGFudEhvb2tzO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBWaXJ0dWFsTm9kZS5wcm90b3R5cGUudmVyc2lvbiA9IHZlcnNpb247XG4gICAgICAgICAgICBWaXJ0dWFsTm9kZS5wcm90b3R5cGUudHlwZSA9IFwiVmlydHVhbE5vZGVcIjtcbiAgICAgICAgfSwgeyBcIi4vaXMtdGh1bmtcIjogMjUsIFwiLi9pcy12aG9va1wiOiAyNiwgXCIuL2lzLXZub2RlXCI6IDI3LCBcIi4vaXMtd2lkZ2V0XCI6IDI5LCBcIi4vdmVyc2lvblwiOiAzMCB9XSwgMzI6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICB2YXIgdmVyc2lvbiA9IHJlcXVpcmUoXCIuL3ZlcnNpb25cIik7XG5cbiAgICAgICAgICAgIFZpcnR1YWxQYXRjaC5OT05FID0gMDtcbiAgICAgICAgICAgIFZpcnR1YWxQYXRjaC5WVEVYVCA9IDE7XG4gICAgICAgICAgICBWaXJ0dWFsUGF0Y2guVk5PREUgPSAyO1xuICAgICAgICAgICAgVmlydHVhbFBhdGNoLldJREdFVCA9IDM7XG4gICAgICAgICAgICBWaXJ0dWFsUGF0Y2guUFJPUFMgPSA0O1xuICAgICAgICAgICAgVmlydHVhbFBhdGNoLk9SREVSID0gNTtcbiAgICAgICAgICAgIFZpcnR1YWxQYXRjaC5JTlNFUlQgPSA2O1xuICAgICAgICAgICAgVmlydHVhbFBhdGNoLlJFTU9WRSA9IDc7XG4gICAgICAgICAgICBWaXJ0dWFsUGF0Y2guVEhVTksgPSA4O1xuXG4gICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IFZpcnR1YWxQYXRjaDtcblxuICAgICAgICAgICAgZnVuY3Rpb24gVmlydHVhbFBhdGNoKHR5cGUsIHZOb2RlLCBwYXRjaCkge1xuICAgICAgICAgICAgICAgIHRoaXMudHlwZSA9IE51bWJlcih0eXBlKTtcbiAgICAgICAgICAgICAgICB0aGlzLnZOb2RlID0gdk5vZGU7XG4gICAgICAgICAgICAgICAgdGhpcy5wYXRjaCA9IHBhdGNoO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBWaXJ0dWFsUGF0Y2gucHJvdG90eXBlLnZlcnNpb24gPSB2ZXJzaW9uO1xuICAgICAgICAgICAgVmlydHVhbFBhdGNoLnByb3RvdHlwZS50eXBlID0gXCJWaXJ0dWFsUGF0Y2hcIjtcbiAgICAgICAgfSwgeyBcIi4vdmVyc2lvblwiOiAzMCB9XSwgMzM6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICB2YXIgdmVyc2lvbiA9IHJlcXVpcmUoXCIuL3ZlcnNpb25cIik7XG5cbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gVmlydHVhbFRleHQ7XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIFZpcnR1YWxUZXh0KHRleHQpIHtcbiAgICAgICAgICAgICAgICB0aGlzLnRleHQgPSBTdHJpbmcodGV4dCk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIFZpcnR1YWxUZXh0LnByb3RvdHlwZS52ZXJzaW9uID0gdmVyc2lvbjtcbiAgICAgICAgICAgIFZpcnR1YWxUZXh0LnByb3RvdHlwZS50eXBlID0gXCJWaXJ0dWFsVGV4dFwiO1xuICAgICAgICB9LCB7IFwiLi92ZXJzaW9uXCI6IDMwIH1dLCAzNDogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHtcbiAgICAgICAgICAgIHZhciBpc09iamVjdCA9IHJlcXVpcmUoXCJpcy1vYmplY3RcIik7XG4gICAgICAgICAgICB2YXIgaXNIb29rID0gcmVxdWlyZShcIi4uL3Zub2RlL2lzLXZob29rXCIpO1xuXG4gICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IGRpZmZQcm9wcztcblxuICAgICAgICAgICAgZnVuY3Rpb24gZGlmZlByb3BzKGEsIGIpIHtcbiAgICAgICAgICAgICAgICB2YXIgZGlmZjtcblxuICAgICAgICAgICAgICAgIGZvciAodmFyIGFLZXkgaW4gYSkge1xuICAgICAgICAgICAgICAgICAgICBpZiAoIShhS2V5IGluIGIpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBkaWZmID0gZGlmZiB8fCB7fTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGRpZmZbYUtleV0gPSB1bmRlZmluZWQ7XG4gICAgICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgICAgICB2YXIgYVZhbHVlID0gYVthS2V5XTtcbiAgICAgICAgICAgICAgICAgICAgdmFyIGJWYWx1ZSA9IGJbYUtleV07XG5cbiAgICAgICAgICAgICAgICAgICAgaWYgKGFWYWx1ZSA9PT0gYlZhbHVlKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBjb250aW51ZTtcbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIGlmIChpc09iamVjdChhVmFsdWUpICYmIGlzT2JqZWN0KGJWYWx1ZSkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChnZXRQcm90b3R5cGUoYlZhbHVlKSAhPT0gZ2V0UHJvdG90eXBlKGFWYWx1ZSkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBkaWZmID0gZGlmZiB8fCB7fTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBkaWZmW2FLZXldID0gYlZhbHVlO1xuICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIGlmIChpc0hvb2soYlZhbHVlKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRpZmYgPSBkaWZmIHx8IHt9O1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRpZmZbYUtleV0gPSBiVmFsdWU7XG4gICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZhciBvYmplY3REaWZmID0gZGlmZlByb3BzKGFWYWx1ZSwgYlZhbHVlKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAob2JqZWN0RGlmZikge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBkaWZmID0gZGlmZiB8fCB7fTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZGlmZlthS2V5XSA9IG9iamVjdERpZmY7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgZGlmZiA9IGRpZmYgfHwge307XG4gICAgICAgICAgICAgICAgICAgICAgICBkaWZmW2FLZXldID0gYlZhbHVlO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgZm9yICh2YXIgYktleSBpbiBiKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmICghKGJLZXkgaW4gYSkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGRpZmYgPSBkaWZmIHx8IHt9O1xuICAgICAgICAgICAgICAgICAgICAgICAgZGlmZltiS2V5XSA9IGJbYktleV07XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICByZXR1cm4gZGlmZjtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZnVuY3Rpb24gZ2V0UHJvdG90eXBlKHZhbHVlKSB7XG4gICAgICAgICAgICAgICAgaWYgKE9iamVjdC5nZXRQcm90b3R5cGVPZikge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gT2JqZWN0LmdldFByb3RvdHlwZU9mKHZhbHVlKTtcbiAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKHZhbHVlLl9fcHJvdG9fXykge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gdmFsdWUuX19wcm90b19fO1xuICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAodmFsdWUuY29uc3RydWN0b3IpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHZhbHVlLmNvbnN0cnVjdG9yLnByb3RvdHlwZTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH0sIHsgXCIuLi92bm9kZS9pcy12aG9va1wiOiAyNiwgXCJpcy1vYmplY3RcIjogMTEgfV0sIDM1OiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge1xuICAgICAgICAgICAgdmFyIGlzQXJyYXkgPSByZXF1aXJlKFwieC1pcy1hcnJheVwiKTtcblxuICAgICAgICAgICAgdmFyIFZQYXRjaCA9IHJlcXVpcmUoXCIuLi92bm9kZS92cGF0Y2hcIik7XG4gICAgICAgICAgICB2YXIgaXNWTm9kZSA9IHJlcXVpcmUoXCIuLi92bm9kZS9pcy12bm9kZVwiKTtcbiAgICAgICAgICAgIHZhciBpc1ZUZXh0ID0gcmVxdWlyZShcIi4uL3Zub2RlL2lzLXZ0ZXh0XCIpO1xuICAgICAgICAgICAgdmFyIGlzV2lkZ2V0ID0gcmVxdWlyZShcIi4uL3Zub2RlL2lzLXdpZGdldFwiKTtcbiAgICAgICAgICAgIHZhciBpc1RodW5rID0gcmVxdWlyZShcIi4uL3Zub2RlL2lzLXRodW5rXCIpO1xuICAgICAgICAgICAgdmFyIGhhbmRsZVRodW5rID0gcmVxdWlyZShcIi4uL3Zub2RlL2hhbmRsZS10aHVua1wiKTtcblxuICAgICAgICAgICAgdmFyIGRpZmZQcm9wcyA9IHJlcXVpcmUoXCIuL2RpZmYtcHJvcHNcIik7XG5cbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gZGlmZjtcblxuICAgICAgICAgICAgZnVuY3Rpb24gZGlmZihhLCBiKSB7XG4gICAgICAgICAgICAgICAgdmFyIHBhdGNoID0geyBhOiBhIH07XG4gICAgICAgICAgICAgICAgd2FsayhhLCBiLCBwYXRjaCwgMCk7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHBhdGNoO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBmdW5jdGlvbiB3YWxrKGEsIGIsIHBhdGNoLCBpbmRleCkge1xuICAgICAgICAgICAgICAgIGlmIChhID09PSBiKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICB2YXIgYXBwbHkgPSBwYXRjaFtpbmRleF07XG4gICAgICAgICAgICAgICAgdmFyIGFwcGx5Q2xlYXIgPSBmYWxzZTtcblxuICAgICAgICAgICAgICAgIGlmIChpc1RodW5rKGEpIHx8IGlzVGh1bmsoYikpIHtcbiAgICAgICAgICAgICAgICAgICAgdGh1bmtzKGEsIGIsIHBhdGNoLCBpbmRleCk7XG4gICAgICAgICAgICAgICAgfSBlbHNlIGlmIChiID09IG51bGwpIHtcblxuICAgICAgICAgICAgICAgICAgICAvLyBJZiBhIGlzIGEgd2lkZ2V0IHdlIHdpbGwgYWRkIGEgcmVtb3ZlIHBhdGNoIGZvciBpdFxuICAgICAgICAgICAgICAgICAgICAvLyBPdGhlcndpc2UgYW55IGNoaWxkIHdpZGdldHMvaG9va3MgbXVzdCBiZSBkZXN0cm95ZWQuXG4gICAgICAgICAgICAgICAgICAgIC8vIFRoaXMgcHJldmVudHMgYWRkaW5nIHR3byByZW1vdmUgcGF0Y2hlcyBmb3IgYSB3aWRnZXQuXG4gICAgICAgICAgICAgICAgICAgIGlmICghaXNXaWRnZXQoYSkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGNsZWFyU3RhdGUoYSwgcGF0Y2gsIGluZGV4KTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGFwcGx5ID0gcGF0Y2hbaW5kZXhdO1xuICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgYXBwbHkgPSBhcHBlbmRQYXRjaChhcHBseSwgbmV3IFZQYXRjaChWUGF0Y2guUkVNT1ZFLCBhLCBiKSk7XG4gICAgICAgICAgICAgICAgfSBlbHNlIGlmIChpc1ZOb2RlKGIpKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmIChpc1ZOb2RlKGEpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoYS50YWdOYW1lID09PSBiLnRhZ05hbWUgJiYgYS5uYW1lc3BhY2UgPT09IGIubmFtZXNwYWNlICYmIGEua2V5ID09PSBiLmtleSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZhciBwcm9wc1BhdGNoID0gZGlmZlByb3BzKGEucHJvcGVydGllcywgYi5wcm9wZXJ0aWVzKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAocHJvcHNQYXRjaCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBhcHBseSA9IGFwcGVuZFBhdGNoKGFwcGx5LCBuZXcgVlBhdGNoKFZQYXRjaC5QUk9QUywgYSwgcHJvcHNQYXRjaCkpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBhcHBseSA9IGRpZmZDaGlsZHJlbihhLCBiLCBwYXRjaCwgYXBwbHksIGluZGV4KTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgYXBwbHkgPSBhcHBlbmRQYXRjaChhcHBseSwgbmV3IFZQYXRjaChWUGF0Y2guVk5PREUsIGEsIGIpKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBhcHBseUNsZWFyID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGFwcGx5ID0gYXBwZW5kUGF0Y2goYXBwbHksIG5ldyBWUGF0Y2goVlBhdGNoLlZOT0RFLCBhLCBiKSk7XG4gICAgICAgICAgICAgICAgICAgICAgICBhcHBseUNsZWFyID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoaXNWVGV4dChiKSkge1xuICAgICAgICAgICAgICAgICAgICBpZiAoIWlzVlRleHQoYSkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGFwcGx5ID0gYXBwZW5kUGF0Y2goYXBwbHksIG5ldyBWUGF0Y2goVlBhdGNoLlZURVhULCBhLCBiKSk7XG4gICAgICAgICAgICAgICAgICAgICAgICBhcHBseUNsZWFyID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIGlmIChhLnRleHQgIT09IGIudGV4dCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgYXBwbHkgPSBhcHBlbmRQYXRjaChhcHBseSwgbmV3IFZQYXRjaChWUGF0Y2guVlRFWFQsIGEsIGIpKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoaXNXaWRnZXQoYikpIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKCFpc1dpZGdldChhKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgYXBwbHlDbGVhciA9IHRydWU7XG4gICAgICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgICAgICBhcHBseSA9IGFwcGVuZFBhdGNoKGFwcGx5LCBuZXcgVlBhdGNoKFZQYXRjaC5XSURHRVQsIGEsIGIpKTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICBpZiAoYXBwbHkpIHtcbiAgICAgICAgICAgICAgICAgICAgcGF0Y2hbaW5kZXhdID0gYXBwbHk7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgaWYgKGFwcGx5Q2xlYXIpIHtcbiAgICAgICAgICAgICAgICAgICAgY2xlYXJTdGF0ZShhLCBwYXRjaCwgaW5kZXgpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZnVuY3Rpb24gZGlmZkNoaWxkcmVuKGEsIGIsIHBhdGNoLCBhcHBseSwgaW5kZXgpIHtcbiAgICAgICAgICAgICAgICB2YXIgYUNoaWxkcmVuID0gYS5jaGlsZHJlbjtcbiAgICAgICAgICAgICAgICB2YXIgb3JkZXJlZFNldCA9IHJlb3JkZXIoYUNoaWxkcmVuLCBiLmNoaWxkcmVuKTtcbiAgICAgICAgICAgICAgICB2YXIgYkNoaWxkcmVuID0gb3JkZXJlZFNldC5jaGlsZHJlbjtcblxuICAgICAgICAgICAgICAgIHZhciBhTGVuID0gYUNoaWxkcmVuLmxlbmd0aDtcbiAgICAgICAgICAgICAgICB2YXIgYkxlbiA9IGJDaGlsZHJlbi5sZW5ndGg7XG4gICAgICAgICAgICAgICAgdmFyIGxlbiA9IGFMZW4gPiBiTGVuID8gYUxlbiA6IGJMZW47XG5cbiAgICAgICAgICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IGxlbjsgaSsrKSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciBsZWZ0Tm9kZSA9IGFDaGlsZHJlbltpXTtcbiAgICAgICAgICAgICAgICAgICAgdmFyIHJpZ2h0Tm9kZSA9IGJDaGlsZHJlbltpXTtcbiAgICAgICAgICAgICAgICAgICAgaW5kZXggKz0gMTtcblxuICAgICAgICAgICAgICAgICAgICBpZiAoIWxlZnROb2RlKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAocmlnaHROb2RlKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gRXhjZXNzIG5vZGVzIGluIGIgbmVlZCB0byBiZSBhZGRlZFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGFwcGx5ID0gYXBwZW5kUGF0Y2goYXBwbHksIG5ldyBWUGF0Y2goVlBhdGNoLklOU0VSVCwgbnVsbCwgcmlnaHROb2RlKSk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICB3YWxrKGxlZnROb2RlLCByaWdodE5vZGUsIHBhdGNoLCBpbmRleCk7XG4gICAgICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgICAgICBpZiAoaXNWTm9kZShsZWZ0Tm9kZSkgJiYgbGVmdE5vZGUuY291bnQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGluZGV4ICs9IGxlZnROb2RlLmNvdW50O1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgaWYgKG9yZGVyZWRTZXQubW92ZXMpIHtcbiAgICAgICAgICAgICAgICAgICAgLy8gUmVvcmRlciBub2RlcyBsYXN0XG4gICAgICAgICAgICAgICAgICAgIGFwcGx5ID0gYXBwZW5kUGF0Y2goYXBwbHksIG5ldyBWUGF0Y2goVlBhdGNoLk9SREVSLCBhLCBvcmRlcmVkU2V0Lm1vdmVzKSk7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgcmV0dXJuIGFwcGx5O1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBmdW5jdGlvbiBjbGVhclN0YXRlKHZOb2RlLCBwYXRjaCwgaW5kZXgpIHtcbiAgICAgICAgICAgICAgICAvLyBUT0RPOiBNYWtlIHRoaXMgYSBzaW5nbGUgd2Fsaywgbm90IHR3b1xuICAgICAgICAgICAgICAgIHVuaG9vayh2Tm9kZSwgcGF0Y2gsIGluZGV4KTtcbiAgICAgICAgICAgICAgICBkZXN0cm95V2lkZ2V0cyh2Tm9kZSwgcGF0Y2gsIGluZGV4KTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgLy8gUGF0Y2ggcmVjb3JkcyBmb3IgYWxsIGRlc3Ryb3llZCB3aWRnZXRzIG11c3QgYmUgYWRkZWQgYmVjYXVzZSB3ZSBuZWVkXG4gICAgICAgICAgICAvLyBhIERPTSBub2RlIHJlZmVyZW5jZSBmb3IgdGhlIGRlc3Ryb3kgZnVuY3Rpb25cbiAgICAgICAgICAgIGZ1bmN0aW9uIGRlc3Ryb3lXaWRnZXRzKHZOb2RlLCBwYXRjaCwgaW5kZXgpIHtcbiAgICAgICAgICAgICAgICBpZiAoaXNXaWRnZXQodk5vZGUpKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmICh0eXBlb2Ygdk5vZGUuZGVzdHJveSA9PT0gXCJmdW5jdGlvblwiKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBwYXRjaFtpbmRleF0gPSBhcHBlbmRQYXRjaChwYXRjaFtpbmRleF0sIG5ldyBWUGF0Y2goVlBhdGNoLlJFTU9WRSwgdk5vZGUsIG51bGwpKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoaXNWTm9kZSh2Tm9kZSkgJiYgKHZOb2RlLmhhc1dpZGdldHMgfHwgdk5vZGUuaGFzVGh1bmtzKSkge1xuICAgICAgICAgICAgICAgICAgICB2YXIgY2hpbGRyZW4gPSB2Tm9kZS5jaGlsZHJlbjtcbiAgICAgICAgICAgICAgICAgICAgdmFyIGxlbiA9IGNoaWxkcmVuLmxlbmd0aDtcbiAgICAgICAgICAgICAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCBsZW47IGkrKykge1xuICAgICAgICAgICAgICAgICAgICAgICAgdmFyIGNoaWxkID0gY2hpbGRyZW5baV07XG4gICAgICAgICAgICAgICAgICAgICAgICBpbmRleCArPSAxO1xuXG4gICAgICAgICAgICAgICAgICAgICAgICBkZXN0cm95V2lkZ2V0cyhjaGlsZCwgcGF0Y2gsIGluZGV4KTtcblxuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGlzVk5vZGUoY2hpbGQpICYmIGNoaWxkLmNvdW50KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaW5kZXggKz0gY2hpbGQuY291bnQ7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKGlzVGh1bmsodk5vZGUpKSB7XG4gICAgICAgICAgICAgICAgICAgIHRodW5rcyh2Tm9kZSwgbnVsbCwgcGF0Y2gsIGluZGV4KTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIC8vIENyZWF0ZSBhIHN1Yi1wYXRjaCBmb3IgdGh1bmtzXG4gICAgICAgICAgICBmdW5jdGlvbiB0aHVua3MoYSwgYiwgcGF0Y2gsIGluZGV4KSB7XG4gICAgICAgICAgICAgICAgdmFyIG5vZGVzID0gaGFuZGxlVGh1bmsoYSwgYik7XG4gICAgICAgICAgICAgICAgdmFyIHRodW5rUGF0Y2ggPSBkaWZmKG5vZGVzLmEsIG5vZGVzLmIpO1xuICAgICAgICAgICAgICAgIGlmIChoYXNQYXRjaGVzKHRodW5rUGF0Y2gpKSB7XG4gICAgICAgICAgICAgICAgICAgIHBhdGNoW2luZGV4XSA9IG5ldyBWUGF0Y2goVlBhdGNoLlRIVU5LLCBudWxsLCB0aHVua1BhdGNoKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIGhhc1BhdGNoZXMocGF0Y2gpIHtcbiAgICAgICAgICAgICAgICBmb3IgKHZhciBpbmRleCBpbiBwYXRjaCkge1xuICAgICAgICAgICAgICAgICAgICBpZiAoaW5kZXggIT09IFwiYVwiKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgLy8gRXhlY3V0ZSBob29rcyB3aGVuIHR3byBub2RlcyBhcmUgaWRlbnRpY2FsXG4gICAgICAgICAgICBmdW5jdGlvbiB1bmhvb2sodk5vZGUsIHBhdGNoLCBpbmRleCkge1xuICAgICAgICAgICAgICAgIGlmIChpc1ZOb2RlKHZOb2RlKSkge1xuICAgICAgICAgICAgICAgICAgICBpZiAodk5vZGUuaG9va3MpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHBhdGNoW2luZGV4XSA9IGFwcGVuZFBhdGNoKHBhdGNoW2luZGV4XSwgbmV3IFZQYXRjaChWUGF0Y2guUFJPUFMsIHZOb2RlLCB1bmRlZmluZWRLZXlzKHZOb2RlLmhvb2tzKSkpO1xuICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgaWYgKHZOb2RlLmRlc2NlbmRhbnRIb29rcyB8fCB2Tm9kZS5oYXNUaHVua3MpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHZhciBjaGlsZHJlbiA9IHZOb2RlLmNoaWxkcmVuO1xuICAgICAgICAgICAgICAgICAgICAgICAgdmFyIGxlbiA9IGNoaWxkcmVuLmxlbmd0aDtcbiAgICAgICAgICAgICAgICAgICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgbGVuOyBpKyspIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB2YXIgY2hpbGQgPSBjaGlsZHJlbltpXTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpbmRleCArPSAxO1xuXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdW5ob29rKGNoaWxkLCBwYXRjaCwgaW5kZXgpO1xuXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGlzVk5vZGUoY2hpbGQpICYmIGNoaWxkLmNvdW50KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGluZGV4ICs9IGNoaWxkLmNvdW50O1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoaXNUaHVuayh2Tm9kZSkpIHtcbiAgICAgICAgICAgICAgICAgICAgdGh1bmtzKHZOb2RlLCBudWxsLCBwYXRjaCwgaW5kZXgpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZnVuY3Rpb24gdW5kZWZpbmVkS2V5cyhvYmopIHtcbiAgICAgICAgICAgICAgICB2YXIgcmVzdWx0ID0ge307XG5cbiAgICAgICAgICAgICAgICBmb3IgKHZhciBrZXkgaW4gb2JqKSB7XG4gICAgICAgICAgICAgICAgICAgIHJlc3VsdFtrZXldID0gdW5kZWZpbmVkO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHJldHVybiByZXN1bHQ7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIC8vIExpc3QgZGlmZiwgbmFpdmUgbGVmdCB0byByaWdodCByZW9yZGVyaW5nXG4gICAgICAgICAgICBmdW5jdGlvbiByZW9yZGVyKGFDaGlsZHJlbiwgYkNoaWxkcmVuKSB7XG4gICAgICAgICAgICAgICAgLy8gTyhNKSB0aW1lLCBPKE0pIG1lbW9yeVxuICAgICAgICAgICAgICAgIHZhciBiQ2hpbGRJbmRleCA9IGtleUluZGV4KGJDaGlsZHJlbik7XG4gICAgICAgICAgICAgICAgdmFyIGJLZXlzID0gYkNoaWxkSW5kZXgua2V5cztcbiAgICAgICAgICAgICAgICB2YXIgYkZyZWUgPSBiQ2hpbGRJbmRleC5mcmVlO1xuXG4gICAgICAgICAgICAgICAgaWYgKGJGcmVlLmxlbmd0aCA9PT0gYkNoaWxkcmVuLmxlbmd0aCkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgICAgICAgICAgICAgY2hpbGRyZW46IGJDaGlsZHJlbixcbiAgICAgICAgICAgICAgICAgICAgICAgIG1vdmVzOiBudWxsXG4gICAgICAgICAgICAgICAgICAgIH07XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgLy8gTyhOKSB0aW1lLCBPKE4pIG1lbW9yeVxuICAgICAgICAgICAgICAgIHZhciBhQ2hpbGRJbmRleCA9IGtleUluZGV4KGFDaGlsZHJlbik7XG4gICAgICAgICAgICAgICAgdmFyIGFLZXlzID0gYUNoaWxkSW5kZXgua2V5cztcbiAgICAgICAgICAgICAgICB2YXIgYUZyZWUgPSBhQ2hpbGRJbmRleC5mcmVlO1xuXG4gICAgICAgICAgICAgICAgaWYgKGFGcmVlLmxlbmd0aCA9PT0gYUNoaWxkcmVuLmxlbmd0aCkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgICAgICAgICAgICAgY2hpbGRyZW46IGJDaGlsZHJlbixcbiAgICAgICAgICAgICAgICAgICAgICAgIG1vdmVzOiBudWxsXG4gICAgICAgICAgICAgICAgICAgIH07XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgLy8gTyhNQVgoTiwgTSkpIG1lbW9yeVxuICAgICAgICAgICAgICAgIHZhciBuZXdDaGlsZHJlbiA9IFtdO1xuXG4gICAgICAgICAgICAgICAgdmFyIGZyZWVJbmRleCA9IDA7XG4gICAgICAgICAgICAgICAgdmFyIGZyZWVDb3VudCA9IGJGcmVlLmxlbmd0aDtcbiAgICAgICAgICAgICAgICB2YXIgZGVsZXRlZEl0ZW1zID0gMDtcblxuICAgICAgICAgICAgICAgIC8vIEl0ZXJhdGUgdGhyb3VnaCBhIGFuZCBtYXRjaCBhIG5vZGUgaW4gYlxuICAgICAgICAgICAgICAgIC8vIE8oTikgdGltZSxcbiAgICAgICAgICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IGFDaGlsZHJlbi5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgICAgICAgICB2YXIgYUl0ZW0gPSBhQ2hpbGRyZW5baV07XG4gICAgICAgICAgICAgICAgICAgIHZhciBpdGVtSW5kZXg7XG5cbiAgICAgICAgICAgICAgICAgICAgaWYgKGFJdGVtLmtleSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGJLZXlzLmhhc093blByb3BlcnR5KGFJdGVtLmtleSkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBNYXRjaCB1cCB0aGUgb2xkIGtleXNcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpdGVtSW5kZXggPSBiS2V5c1thSXRlbS5rZXldO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIG5ld0NoaWxkcmVuLnB1c2goYkNoaWxkcmVuW2l0ZW1JbmRleF0pO1xuICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBSZW1vdmUgb2xkIGtleWVkIGl0ZW1zXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaXRlbUluZGV4ID0gaSAtIGRlbGV0ZWRJdGVtcysrO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIG5ld0NoaWxkcmVuLnB1c2gobnVsbCk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAvLyBNYXRjaCB0aGUgaXRlbSBpbiBhIHdpdGggdGhlIG5leHQgZnJlZSBpdGVtIGluIGJcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChmcmVlSW5kZXggPCBmcmVlQ291bnQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpdGVtSW5kZXggPSBiRnJlZVtmcmVlSW5kZXgrK107XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgbmV3Q2hpbGRyZW4ucHVzaChiQ2hpbGRyZW5baXRlbUluZGV4XSk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIFRoZXJlIGFyZSBubyBmcmVlIGl0ZW1zIGluIGIgdG8gbWF0Y2ggd2l0aFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIHRoZSBmcmVlIGl0ZW1zIGluIGEsIHNvIHRoZSBleHRyYSBmcmVlIG5vZGVzXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gYXJlIGRlbGV0ZWQuXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaXRlbUluZGV4ID0gaSAtIGRlbGV0ZWRJdGVtcysrO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIG5ld0NoaWxkcmVuLnB1c2gobnVsbCk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICB2YXIgbGFzdEZyZWVJbmRleCA9IGZyZWVJbmRleCA+PSBiRnJlZS5sZW5ndGggPyBiQ2hpbGRyZW4ubGVuZ3RoIDogYkZyZWVbZnJlZUluZGV4XTtcblxuICAgICAgICAgICAgICAgIC8vIEl0ZXJhdGUgdGhyb3VnaCBiIGFuZCBhcHBlbmQgYW55IG5ldyBrZXlzXG4gICAgICAgICAgICAgICAgLy8gTyhNKSB0aW1lXG4gICAgICAgICAgICAgICAgZm9yICh2YXIgaiA9IDA7IGogPCBiQ2hpbGRyZW4ubGVuZ3RoOyBqKyspIHtcbiAgICAgICAgICAgICAgICAgICAgdmFyIG5ld0l0ZW0gPSBiQ2hpbGRyZW5bal07XG5cbiAgICAgICAgICAgICAgICAgICAgaWYgKG5ld0l0ZW0ua2V5KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoIWFLZXlzLmhhc093blByb3BlcnR5KG5ld0l0ZW0ua2V5KSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIEFkZCBhbnkgbmV3IGtleWVkIGl0ZW1zXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gV2UgYXJlIGFkZGluZyBuZXcgaXRlbXMgdG8gdGhlIGVuZCBhbmQgdGhlbiBzb3J0aW5nIHRoZW1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBpbiBwbGFjZS4gSW4gZnV0dXJlIHdlIHNob3VsZCBpbnNlcnQgbmV3IGl0ZW1zIGluIHBsYWNlLlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIG5ld0NoaWxkcmVuLnB1c2gobmV3SXRlbSk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoaiA+PSBsYXN0RnJlZUluZGV4KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAvLyBBZGQgYW55IGxlZnRvdmVyIG5vbi1rZXllZCBpdGVtc1xuICAgICAgICAgICAgICAgICAgICAgICAgbmV3Q2hpbGRyZW4ucHVzaChuZXdJdGVtKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHZhciBzaW11bGF0ZSA9IG5ld0NoaWxkcmVuLnNsaWNlKCk7XG4gICAgICAgICAgICAgICAgdmFyIHNpbXVsYXRlSW5kZXggPSAwO1xuICAgICAgICAgICAgICAgIHZhciByZW1vdmVzID0gW107XG4gICAgICAgICAgICAgICAgdmFyIGluc2VydHMgPSBbXTtcbiAgICAgICAgICAgICAgICB2YXIgc2ltdWxhdGVJdGVtO1xuXG4gICAgICAgICAgICAgICAgZm9yICh2YXIgayA9IDA7IGsgPCBiQ2hpbGRyZW4ubGVuZ3RoOykge1xuICAgICAgICAgICAgICAgICAgICB2YXIgd2FudGVkSXRlbSA9IGJDaGlsZHJlbltrXTtcbiAgICAgICAgICAgICAgICAgICAgc2ltdWxhdGVJdGVtID0gc2ltdWxhdGVbc2ltdWxhdGVJbmRleF07XG5cbiAgICAgICAgICAgICAgICAgICAgLy8gcmVtb3ZlIGl0ZW1zXG4gICAgICAgICAgICAgICAgICAgIHdoaWxlIChzaW11bGF0ZUl0ZW0gPT09IG51bGwgJiYgc2ltdWxhdGUubGVuZ3RoKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICByZW1vdmVzLnB1c2gocmVtb3ZlKHNpbXVsYXRlLCBzaW11bGF0ZUluZGV4LCBudWxsKSk7XG4gICAgICAgICAgICAgICAgICAgICAgICBzaW11bGF0ZUl0ZW0gPSBzaW11bGF0ZVtzaW11bGF0ZUluZGV4XTtcbiAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgIGlmICghc2ltdWxhdGVJdGVtIHx8IHNpbXVsYXRlSXRlbS5rZXkgIT09IHdhbnRlZEl0ZW0ua2V5KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAvLyBpZiB3ZSBuZWVkIGEga2V5IGluIHRoaXMgcG9zaXRpb24uLi5cbiAgICAgICAgICAgICAgICAgICAgICAgIGlmICh3YW50ZWRJdGVtLmtleSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChzaW11bGF0ZUl0ZW0gJiYgc2ltdWxhdGVJdGVtLmtleSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBpZiBhbiBpbnNlcnQgZG9lc24ndCBwdXQgdGhpcyBrZXkgaW4gcGxhY2UsIGl0IG5lZWRzIHRvIG1vdmVcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGJLZXlzW3NpbXVsYXRlSXRlbS5rZXldICE9PSBrICsgMSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmVtb3Zlcy5wdXNoKHJlbW92ZShzaW11bGF0ZSwgc2ltdWxhdGVJbmRleCwgc2ltdWxhdGVJdGVtLmtleSkpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc2ltdWxhdGVJdGVtID0gc2ltdWxhdGVbc2ltdWxhdGVJbmRleF07XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBpZiB0aGUgcmVtb3ZlIGRpZG4ndCBwdXQgdGhlIHdhbnRlZCBpdGVtIGluIHBsYWNlLCB3ZSBuZWVkIHRvIGluc2VydCBpdFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKCFzaW11bGF0ZUl0ZW0gfHwgc2ltdWxhdGVJdGVtLmtleSAhPT0gd2FudGVkSXRlbS5rZXkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpbnNlcnRzLnB1c2goeyBrZXk6IHdhbnRlZEl0ZW0ua2V5LCB0bzogayB9KTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIGl0ZW1zIGFyZSBtYXRjaGluZywgc28gc2tpcCBhaGVhZFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc2ltdWxhdGVJbmRleCsrO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaW5zZXJ0cy5wdXNoKHsga2V5OiB3YW50ZWRJdGVtLmtleSwgdG86IGsgfSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpbnNlcnRzLnB1c2goeyBrZXk6IHdhbnRlZEl0ZW0ua2V5LCB0bzogayB9KTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaysrO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgLy8gYSBrZXkgaW4gc2ltdWxhdGUgaGFzIG5vIG1hdGNoaW5nIHdhbnRlZCBrZXksIHJlbW92ZSBpdFxuICAgICAgICAgICAgICAgICAgICAgICAgZWxzZSBpZiAoc2ltdWxhdGVJdGVtICYmIHNpbXVsYXRlSXRlbS5rZXkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICByZW1vdmVzLnB1c2gocmVtb3ZlKHNpbXVsYXRlLCBzaW11bGF0ZUluZGV4LCBzaW11bGF0ZUl0ZW0ua2V5KSk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBzaW11bGF0ZUluZGV4Kys7XG4gICAgICAgICAgICAgICAgICAgICAgICBrKys7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAvLyByZW1vdmUgYWxsIHRoZSByZW1haW5pbmcgbm9kZXMgZnJvbSBzaW11bGF0ZVxuICAgICAgICAgICAgICAgIHdoaWxlIChzaW11bGF0ZUluZGV4IDwgc2ltdWxhdGUubGVuZ3RoKSB7XG4gICAgICAgICAgICAgICAgICAgIHNpbXVsYXRlSXRlbSA9IHNpbXVsYXRlW3NpbXVsYXRlSW5kZXhdO1xuICAgICAgICAgICAgICAgICAgICByZW1vdmVzLnB1c2gocmVtb3ZlKHNpbXVsYXRlLCBzaW11bGF0ZUluZGV4LCBzaW11bGF0ZUl0ZW0gJiYgc2ltdWxhdGVJdGVtLmtleSkpO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIC8vIElmIHRoZSBvbmx5IG1vdmVzIHdlIGhhdmUgYXJlIGRlbGV0ZXMgdGhlbiB3ZSBjYW4ganVzdFxuICAgICAgICAgICAgICAgIC8vIGxldCB0aGUgZGVsZXRlIHBhdGNoIHJlbW92ZSB0aGVzZSBpdGVtcy5cbiAgICAgICAgICAgICAgICBpZiAocmVtb3Zlcy5sZW5ndGggPT09IGRlbGV0ZWRJdGVtcyAmJiAhaW5zZXJ0cy5sZW5ndGgpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGNoaWxkcmVuOiBuZXdDaGlsZHJlbixcbiAgICAgICAgICAgICAgICAgICAgICAgIG1vdmVzOiBudWxsXG4gICAgICAgICAgICAgICAgICAgIH07XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgICAgICAgICAgY2hpbGRyZW46IG5ld0NoaWxkcmVuLFxuICAgICAgICAgICAgICAgICAgICBtb3Zlczoge1xuICAgICAgICAgICAgICAgICAgICAgICAgcmVtb3ZlczogcmVtb3ZlcyxcbiAgICAgICAgICAgICAgICAgICAgICAgIGluc2VydHM6IGluc2VydHNcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH07XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIHJlbW92ZShhcnIsIGluZGV4LCBrZXkpIHtcbiAgICAgICAgICAgICAgICBhcnIuc3BsaWNlKGluZGV4LCAxKTtcblxuICAgICAgICAgICAgICAgIHJldHVybiB7XG4gICAgICAgICAgICAgICAgICAgIGZyb206IGluZGV4LFxuICAgICAgICAgICAgICAgICAgICBrZXk6IGtleVxuICAgICAgICAgICAgICAgIH07XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIGtleUluZGV4KGNoaWxkcmVuKSB7XG4gICAgICAgICAgICAgICAgdmFyIGtleXMgPSB7fTtcbiAgICAgICAgICAgICAgICB2YXIgZnJlZSA9IFtdO1xuICAgICAgICAgICAgICAgIHZhciBsZW5ndGggPSBjaGlsZHJlbi5sZW5ndGg7XG5cbiAgICAgICAgICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IGxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciBjaGlsZCA9IGNoaWxkcmVuW2ldO1xuXG4gICAgICAgICAgICAgICAgICAgIGlmIChjaGlsZC5rZXkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGtleXNbY2hpbGQua2V5XSA9IGk7XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBmcmVlLnB1c2goaSk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgICAgICAgICBrZXlzOiBrZXlzLCAvLyBBIGhhc2ggb2Yga2V5IG5hbWUgdG8gaW5kZXhcbiAgICAgICAgICAgICAgICAgICAgZnJlZTogZnJlZSAvLyBBbiBhcnJheSBvZiB1bmtleWVkIGl0ZW0gaW5kaWNlc1xuICAgICAgICAgICAgICAgIH07XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIGFwcGVuZFBhdGNoKGFwcGx5LCBwYXRjaCkge1xuICAgICAgICAgICAgICAgIGlmIChhcHBseSkge1xuICAgICAgICAgICAgICAgICAgICBpZiAoaXNBcnJheShhcHBseSkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGFwcGx5LnB1c2gocGF0Y2gpO1xuICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgYXBwbHkgPSBbYXBwbHksIHBhdGNoXTtcbiAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBhcHBseTtcbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gcGF0Y2g7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9LCB7IFwiLi4vdm5vZGUvaGFuZGxlLXRodW5rXCI6IDI0LCBcIi4uL3Zub2RlL2lzLXRodW5rXCI6IDI1LCBcIi4uL3Zub2RlL2lzLXZub2RlXCI6IDI3LCBcIi4uL3Zub2RlL2lzLXZ0ZXh0XCI6IDI4LCBcIi4uL3Zub2RlL2lzLXdpZGdldFwiOiAyOSwgXCIuLi92bm9kZS92cGF0Y2hcIjogMzIsIFwiLi9kaWZmLXByb3BzXCI6IDM0LCBcIngtaXMtYXJyYXlcIjogMTIgfV0gfSwge30sIFs0XSkoNCk7XG59KTtcblxuY29uc3Qgc3RhcnQgPSBmdW5jdGlvbiAoZG9tUm9vdCwgcmVuZGVyRm4sIGluaXRpYWxTdGF0ZSwgb3B0aW9ucyA9IFtdKSB7XG4gIGxldCBwaWQgPSBzZWxmLnByb2Nlc3Nlcy5zcGF3bigpO1xuXG4gIGlmIChLZXl3b3JkLmhhc19rZXlfX3FtX18ob3B0aW9ucywgS2VybmVsLlNwZWNpYWxGb3Jtcy5hdG9tKCduYW1lJykpKSB7XG4gICAgcGlkID0gc2VsZi5wcm9jZXNzZXMucmVnaXN0ZXIoS2V5d29yZC5nZXQob3B0aW9ucywgS2VybmVsLlNwZWNpYWxGb3Jtcy5hdG9tKCduYW1lJykpLCBwaWQpO1xuICB9XG5cbiAgY29uc3QgdHJlZSA9IHJlbmRlckZuLmFwcGx5KHRoaXMsIGluaXRpYWxTdGF0ZSk7XG4gIGNvbnN0IHJvb3ROb2RlID0gVmlydHVhbERPTS5jcmVhdGUodHJlZSk7XG5cbiAgZG9tUm9vdC5hcHBlbmRDaGlsZChyb290Tm9kZSk7XG5cbiAgc2VsZi5wcm9jZXNzZXMucHV0KHBpZCwgJ3N0YXRlJywgS2VybmVsLlNwZWNpYWxGb3Jtcy50dXBsZShyb290Tm9kZSwgdHJlZSwgcmVuZGVyRm4pKTtcbiAgcmV0dXJuIEtlcm5lbC5TcGVjaWFsRm9ybXMudHVwbGUoS2VybmVsLlNwZWNpYWxGb3Jtcy5hdG9tKCdvaycpLCBwaWQpO1xufTtcblxuY29uc3Qgc3RvcCA9IGZ1bmN0aW9uIChhZ2VudCwgdGltZW91dCA9IDUwMDApIHtcbiAgc2VsZi5wcm9jZXNzZXMuZXhpdChhZ2VudCk7XG4gIHJldHVybiBLZXJuZWwuU3BlY2lhbEZvcm1zLmF0b20oJ29rJyk7XG59O1xuXG5jb25zdCByZW5kZXIgPSBmdW5jdGlvbiAoYWdlbnQsIHN0YXRlKSB7XG5cbiAgY29uc3QgY3VycmVudF9zdGF0ZSA9IHNlbGYucHJvY2Vzc2VzLmdldChhZ2VudCwgJ3N0YXRlJyk7XG5cbiAgbGV0IHJvb3ROb2RlID0gS2VybmVsLmVsZW0oY3VycmVudF9zdGF0ZSwgMCk7XG4gIGxldCB0cmVlID0gS2VybmVsLmVsZW0oY3VycmVudF9zdGF0ZSwgMSk7XG4gIGxldCByZW5kZXJGbiA9IEtlcm5lbC5lbGVtKGN1cnJlbnRfc3RhdGUsIDIpO1xuXG4gIGxldCBuZXdUcmVlID0gcmVuZGVyRm4uYXBwbHkodGhpcywgc3RhdGUpO1xuXG4gIGxldCBwYXRjaGVzID0gVmlydHVhbERPTS5kaWZmKHRyZWUsIG5ld1RyZWUpO1xuICByb290Tm9kZSA9IFZpcnR1YWxET00ucGF0Y2gocm9vdE5vZGUsIHBhdGNoZXMpO1xuXG4gIHNlbGYucHJvY2Vzc2VzLnB1dChhZ2VudCwgJ3N0YXRlJywgS2VybmVsLlNwZWNpYWxGb3Jtcy50dXBsZShyb290Tm9kZSwgbmV3VHJlZSwgcmVuZGVyRm4pKTtcblxuICByZXR1cm4gS2VybmVsLlNwZWNpYWxGb3Jtcy5hdG9tKCdvaycpO1xufTtcblxudmFyIHZpZXcgPSB7XG4gIHN0YXJ0LFxuICBzdG9wLFxuICByZW5kZXJcbn07XG5cbnNlbGYucHJvY2Vzc2VzID0gc2VsZi5wcm9jZXNzZXMgfHwgbmV3IFByb2Nlc3NTeXN0ZW0oKTtcblxuY29uc3QgQ29yZSA9IEM7XG5cbmV4cG9ydCB7IENvcmUsIEtlcm5lbCwgQXRvbSwgRW51bSwgSW50ZWdlciwgTGlzdCwgUmFuZ2UsIFR1cGxlLCBBZ2VudCwgS2V5d29yZCwgYmFzZSBhcyBCYXNlLCBTdHJpbmckMSBhcyBTdHJpbmcsIGJpdHdpc2UgYXMgQml0d2lzZSwgRW51bWVyYWJsZSwgQ29sbGVjdGFibGUsIEluc3BlY3QsIG1hcCBhcyBNYXAsIHNldCBhcyBTZXQsIE1hcFNldCwgVmlydHVhbERPTSwgdmlldyBhcyBWaWV3IH07Il0sImZpbGUiOiJFbGl4aXIuanMiLCJzb3VyY2VSb290IjoiL3NvdXJjZS8ifQ== \ No newline at end of file diff --git a/test/elixir_script_test.exs b/test/elixir_script_test.exs index d7dc6625..401f09be 100644 --- a/test/elixir_script_test.exs +++ b/test/elixir_script_test.exs @@ -35,7 +35,7 @@ defmodule ElixirScript.Test do assert_js_matches """ import * as Elixir from 'elixir'; - const __MODULE__ = Elixir.Kernel.SpecialForms.atom('Elephant'); + const __MODULE__ = Elixir.Kernel.SpecialForms.atom('Elixir.Elephant'); const something_else = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([],function() { return Elixir.String.Chars.to_string(10); })); @@ -69,7 +69,7 @@ defmodule ElixirScript.Test do assert_js_matches """ import * as Elixir from 'elixir'; import * as Elephant from 'animals/elephant'; - const __MODULE__ = Elixir.Kernel.SpecialForms.atom('Animals.Elephant'); + const __MODULE__ = Elixir.Kernel.SpecialForms.atom('Elixir.Animals.Elephant'); const defstruct = Elixir.Kernel.defstruct({ [Elixir.Kernel.SpecialForms.atom('__struct__')]: __MODULE__, [Elixir.Kernel.SpecialForms.atom('trunk')]: true }); @@ -80,7 +80,7 @@ defmodule ElixirScript.Test do assert_js_matches """ import * as Elixir from 'elixir'; - const __MODULE__ = Elixir.Kernel.SpecialForms.atom('Elephant'); + const __MODULE__ = Elixir.Kernel.SpecialForms.atom('Elixir.Elephant'); const defstruct = Elixir.Kernel.defstruct({ [Elixir.Kernel.SpecialForms.atom('__struct__')]: __MODULE__, [Elixir.Kernel.SpecialForms.atom('trunk')]: true }); @@ -106,7 +106,7 @@ defmodule ElixirScript.Test do assert_js_matches """ import * as Elixir from 'elixir'; - const __MODULE__ = Elixir.Kernel.SpecialForms.atom('Animals'); + const __MODULE__ = Elixir.Kernel.SpecialForms.atom('Elixir.Animals'); const something_else = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([],function() { return 1 * 1; })); @@ -157,7 +157,7 @@ defmodule ElixirScript.Test do assert_js_matches """ import * as Elixir from 'elixirscript'; - const __MODULE__ = Elixir.Kernel.SpecialForms.atom('Animals'); + const __MODULE__ = Elixir.Kernel.SpecialForms.atom('Elixir.Animals'); const something_else = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([],function() { return 1 * 1; })); diff --git a/test/translator/alias_test.exs b/test/translator/alias_test.exs deleted file mode 100644 index 613af750..00000000 --- a/test/translator/alias_test.exs +++ /dev/null @@ -1,41 +0,0 @@ -defmodule ElixirScript.Translator.Alias.Test do - use ShouldI - import ElixirScript.TestHelper - - should "translate alias without as" do - ex_ast = quote do - alias Hello.World - end - - js_code = """ - import * as World from 'hello/world'; - """ - - assert_translation(ex_ast, js_code) - end - - should "translate alias with as" do - ex_ast = quote do - alias Hello.World, as: Test - end - - js_code = """ - import * as Test from 'hello/world'; - """ - - assert_translation(ex_ast, js_code) - end - - should "translate default alias with as" do - ex_ast = quote do - alias Hello.World, [as: Test, default: true] - end - - js_code = """ - import { default as Test } from 'hello/world'; - """ - - assert_translation(ex_ast, js_code) - end - -end diff --git a/test/translator/bug_test.exs b/test/translator/bug_test.exs index 5d110643..ad50a8fa 100644 --- a/test/translator/bug_test.exs +++ b/test/translator/bug_test.exs @@ -47,7 +47,7 @@ defmodule ElixirScript.Translator.Bug.Test do js_code = """ import { default as JQuery } from 'jquery'; - const __MODULE__ = Elixir.Kernel.SpecialForms.atom('App.Todo'); + const __MODULE__ = Elixir.Kernel.SpecialForms.atom('Elixir.App.Todo'); JQuery(Elixir.Core.call_property(e, 'target')); export {}; diff --git a/test/translator/defmodule_test.exs b/test/translator/defmodule_test.exs index 05117c30..8ecc4b70 100644 --- a/test/translator/defmodule_test.exs +++ b/test/translator/defmodule_test.exs @@ -9,7 +9,7 @@ defmodule ElixirScript.Translator.Defmodule.Test do end js_code = """ - const __MODULE__ = Elixir.Kernel.SpecialForms.atom('Elephant'); + const __MODULE__ = Elixir.Kernel.SpecialForms.atom('Elixir.Elephant'); export {}; """ @@ -31,7 +31,7 @@ defmodule ElixirScript.Translator.Defmodule.Test do end js_code = """ - const __MODULE__ = Elixir.Kernel.SpecialForms.atom('Elephant'); + const __MODULE__ = Elixir.Kernel.SpecialForms.atom('Elixir.Elephant'); const something_else = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([],function() { return null; })); @@ -60,7 +60,7 @@ defmodule ElixirScript.Translator.Defmodule.Test do js_code = """ import * as Crane from 'icabod/crane'; - const __MODULE__ = Elixir.Kernel.SpecialForms.atom('Elephant'); + const __MODULE__ = Elixir.Kernel.SpecialForms.atom('Elixir.Elephant'); const something_else = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([],function() { return null; })); @@ -95,7 +95,7 @@ defmodule ElixirScript.Translator.Defmodule.Test do end js_code = """ - const __MODULE__ = Elixir.Kernel.SpecialForms.atom('Elephant'); + const __MODULE__ = Elixir.Kernel.SpecialForms.atom('Elixir.Elephant'); const defstruct = Elixir.Kernel.defstruct({ [Elixir.Kernel.SpecialForms.atom('__struct__')]: __MODULE__, [Elixir.Kernel.SpecialForms.atom('trunk')]: true }); @@ -104,7 +104,7 @@ defmodule ElixirScript.Translator.Defmodule.Test do }; import * as Elephant from 'animals/elephant'; - const __MODULE__ = Elixir.Kernel.SpecialForms.atom('Animals'); + const __MODULE__ = Elixir.Kernel.SpecialForms.atom('Elixir.Animals'); const something_else = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([], function() { return null; })); @@ -116,7 +116,7 @@ defmodule ElixirScript.Translator.Defmodule.Test do }; import * as Elephant from 'animals/elephant'; - const __MODULE__ = Elixir.Kernel.SpecialForms.atom('Animals.Elephant'); + const __MODULE__ = Elixir.Kernel.SpecialForms.atom('Elixir.Animals.Elephant'); const defstruct = Elixir.Kernel.defstruct({ [Elixir.Kernel.SpecialForms.atom('__struct__')]: __MODULE__, [Elixir.Kernel.SpecialForms.atom('trunk')]: true }); @@ -154,7 +154,7 @@ defmodule ElixirScript.Translator.Defmodule.Test do js_code = """ import * as Bear from 'elephant/bear'; - const __MODULE__ = Elixir.Kernel.SpecialForms.atom('Elephant.Bear'); + const __MODULE__ = Elixir.Kernel.SpecialForms.atom('Elixir.Elephant.Bear'); const defstruct = Elixir.Kernel.defstruct({ [Elixir.Kernel.SpecialForms.atom('__struct__')]: __MODULE__, [Elixir.Kernel.SpecialForms.atom('trunk')]: true }); @@ -164,7 +164,7 @@ defmodule ElixirScript.Translator.Defmodule.Test do import * as Bear from 'elephant/bear'; import * as Elephant from 'animals/elephant'; - const __MODULE__ = Elixir.Kernel.SpecialForms.atom('Animals.Elephant'); + const __MODULE__ = Elixir.Kernel.SpecialForms.atom('Elixir.Animals.Elephant'); const defstruct = Elixir.Kernel.defstruct({ [Elixir.Kernel.SpecialForms.atom('__struct__')]: __MODULE__, [Elixir.Kernel.SpecialForms.atom('trunk')]: true }); @@ -173,7 +173,7 @@ defmodule ElixirScript.Translator.Defmodule.Test do }; import * as Elephant from 'animals/elephant'; - const __MODULE__ = Elixir.Kernel.SpecialForms.atom('Animals'); + const __MODULE__ = Elixir.Kernel.SpecialForms.atom('Elixir.Animals'); const something_else = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([], function() { return null; })); @@ -184,7 +184,7 @@ defmodule ElixirScript.Translator.Defmodule.Test do something }; - const __MODULE__ = Elixir.Kernel.SpecialForms.atom('Bear'); + const __MODULE__ = Elixir.Kernel.SpecialForms.atom('Elixir.Bear'); const defstruct = Elixir.Kernel.defstruct({ [Elixir.Kernel.SpecialForms.atom('__struct__')]: __MODULE__, [Elixir.Kernel.SpecialForms.atom('trunk')]: true }); @@ -193,7 +193,7 @@ defmodule ElixirScript.Translator.Defmodule.Test do }; import * as Bear from 'elephant/bear'; - const __MODULE__ = Elixir.Kernel.SpecialForms.atom('Elephant'); + const __MODULE__ = Elixir.Kernel.SpecialForms.atom('Elixir.Elephant'); const defstruct = Elixir.Kernel.defstruct({ [Elixir.Kernel.SpecialForms.atom('__struct__')]: __MODULE__, [Elixir.Kernel.SpecialForms.atom('trunk')]: true }); @@ -218,11 +218,11 @@ defmodule ElixirScript.Translator.Defmodule.Test do js_code = """ import * as Tigers from 'lions/tigers'; - const __MODULE__ = Elixir.Kernel.SpecialForms.atom('Animals'); + const __MODULE__ = Elixir.Kernel.SpecialForms.atom('Elixir.Animals'); Elixir.Core.call_property(Tigers,'oh_my'); export {}; - const __MODULE__ = Elixir.Kernel.SpecialForms.atom('Lions.Tigers'); + const __MODULE__ = Elixir.Kernel.SpecialForms.atom('Elixir.Lions.Tigers'); Elixir.Core.call_property(Lions.Tigers.Bears,'oh_my'); export {}; """ @@ -247,7 +247,7 @@ defmodule ElixirScript.Translator.Defmodule.Test do end js_code = """ - const __MODULE__ = Elixir.Kernel.SpecialForms.atom('Lions.Tigers'); + const __MODULE__ = Elixir.Kernel.SpecialForms.atom('Elixir.Lions.Tigers'); const oh_my = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([],function() { return null; })); @@ -257,7 +257,7 @@ defmodule ElixirScript.Translator.Defmodule.Test do }; import * as Tigers from 'lions/tigers'; - const __MODULE__ = Elixir.Kernel.SpecialForms.atom('Animals'); + const __MODULE__ = Elixir.Kernel.SpecialForms.atom('Elixir.Animals'); Elixir.Core.call_property(Tigers,'oh_my'); export {}; """ @@ -284,13 +284,13 @@ defmodule ElixirScript.Translator.Defmodule.Test do js_code = """ import * as Tigers from 'lions/tigers'; - const __MODULE__ = Elixir.Kernel.SpecialForms.atom('Animals'); + const __MODULE__ = Elixir.Kernel.SpecialForms.atom('Elixir.Animals'); Tigers.oh_my(); export {}; - const __MODULE__ = Elixir.Kernel.SpecialForms.atom('Lions.Tigers'); + const __MODULE__ = Elixir.Kernel.SpecialForms.atom('Elixir.Lions.Tigers'); const oh_my2 = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([], function() { return null; })); @@ -325,13 +325,13 @@ defmodule ElixirScript.Translator.Defmodule.Test do js_code = """ import * as Tigers from 'lions/tigers'; - const __MODULE__ = Elixir.Kernel.SpecialForms.atom('Animals'); + const __MODULE__ = Elixir.Kernel.SpecialForms.atom('Elixir.Animals'); Tigers.oh_my2(); export {}; - const __MODULE__ = Elixir.Kernel.SpecialForms.atom('Lions.Tigers'); + const __MODULE__ = Elixir.Kernel.SpecialForms.atom('Elixir.Lions.Tigers'); const oh_my2 = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([], function() { return null; diff --git a/test/translator/function_test.exs b/test/translator/function_test.exs index 41503dff..648bcfcc 100644 --- a/test/translator/function_test.exs +++ b/test/translator/function_test.exs @@ -239,7 +239,7 @@ defmodule ElixirScript.Translator.Function.Test do end js_code = """ - const __MODULE__ = Elixir.Kernel.SpecialForms.atom('Example'); + const __MODULE__ = Elixir.Kernel.SpecialForms.atom('Elixir.Example'); const example = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([],function() { return null; }),Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable()],function(oneArg) { @@ -276,7 +276,7 @@ defmodule ElixirScript.Translator.Function.Test do end js_code = """ - const __MODULE__ = Elixir.Kernel.SpecialForms.atom('Example'); + const __MODULE__ = Elixir.Kernel.SpecialForms.atom('Elixir.Example'); const example = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([],function() { return null; }),Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable()],function(oneArg) { @@ -303,7 +303,7 @@ defmodule ElixirScript.Translator.Function.Test do end js_code = """ - const __MODULE__ = Elixir.Kernel.SpecialForms.atom('Example'); + const __MODULE__ = Elixir.Kernel.SpecialForms.atom('Elixir.Example'); const example = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable()],function(oneArg) { return null; })); @@ -421,7 +421,7 @@ defmodule ElixirScript.Translator.Function.Test do end js_code = """ - const __MODULE__ = Elixir.Kernel.SpecialForms.atom('Example'); + const __MODULE__ = Elixir.Kernel.SpecialForms.atom('Elixir.Example'); const something = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable()],function(one) { return null; },function(one) { @@ -652,7 +652,7 @@ defmodule ElixirScript.Translator.Function.Test do js_code = """ - const __MODULE__ = Elixir.Kernel.SpecialForms.atom('Example'); + const __MODULE__ = Elixir.Kernel.SpecialForms.atom('Elixir.Example'); const something = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([1],function() { return null; }),Elixir.Core.Patterns.make_case([2],function() { diff --git a/test/translator/protocol_test.exs b/test/translator/protocol_test.exs index d475b5fa..d6674b0d 100644 --- a/test/translator/protocol_test.exs +++ b/test/translator/protocol_test.exs @@ -10,7 +10,7 @@ defmodule ElixirScript.Translator.Protocol.Test do end js_code = """ - const __MODULE__ = Elixir.Kernel.SpecialForms.atom('ElixirScript.Collectable'); + const __MODULE__ = Elixir.Kernel.SpecialForms.atom('Elixir.ElixirScript.Collectable'); let Collectable = Elixir.Kernel.defprotocol({ into: Elixir.Core.Patterns.defmatch( @@ -68,7 +68,7 @@ defmodule ElixirScript.Translator.Protocol.Test do end js_code = """ - const __MODULE__ = Elixir.Kernel.SpecialForms.atom('Blank'); + const __MODULE__ = Elixir.Kernel.SpecialForms.atom('Elixir.Blank'); let Blank = Elixir.Kernel.defprotocol({ blank__qmark__: Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable()],function(data) { return null; diff --git a/test/translator/require_test.exs b/test/translator/require_test.exs deleted file mode 100644 index a3c975b9..00000000 --- a/test/translator/require_test.exs +++ /dev/null @@ -1,28 +0,0 @@ -defmodule ElixirScript.Translator.Require.Test do - use ShouldI - import ElixirScript.TestHelper - - should "translate require without as" do - ex_ast = quote do - require Hello.World - end - - js_code = """ - import * as World from 'hello/world'; - """ - - assert_translation(ex_ast, js_code) - end - - should "translate require with as" do - ex_ast = quote do - require Hello.World, as: Test - end - - js_code = """ - import * as Test from 'hello/world'; - """ - - assert_translation(ex_ast, js_code) - end -end diff --git a/test/translator/struct_test.exs b/test/translator/struct_test.exs index dc765a27..6660f9f1 100644 --- a/test/translator/struct_test.exs +++ b/test/translator/struct_test.exs @@ -10,7 +10,7 @@ defmodule ElixirScript.Translator.Struct.Test do end js_code = """ - const __MODULE__ = Elixir.Kernel.SpecialForms.atom('User'); + const __MODULE__ = Elixir.Kernel.SpecialForms.atom('Elixir.User'); const defstruct = Elixir.Kernel.defstruct({ [Elixir.Kernel.SpecialForms.atom('__struct__')]: __MODULE__, [Elixir.Kernel.SpecialForms.atom('name')]: 'john', [Elixir.Kernel.SpecialForms.atom('age')]: 27 @@ -33,7 +33,7 @@ defmodule ElixirScript.Translator.Struct.Test do end js_code = """ - const __MODULE__ = Elixir.Kernel.SpecialForms.atom('User'); + const __MODULE__ = Elixir.Kernel.SpecialForms.atom('Elixir.User'); const defstruct = Elixir.Kernel.defstruct({ [Elixir.Kernel.SpecialForms.atom('__struct__')]: __MODULE__, [Elixir.Kernel.SpecialForms.atom('name')]: null, @@ -59,7 +59,7 @@ defmodule ElixirScript.Translator.Struct.Test do end js_code = """ - const __MODULE__ = Elixir.Kernel.SpecialForms.atom('User'); + const __MODULE__ = Elixir.Kernel.SpecialForms.atom('Elixir.User'); const defstruct = Elixir.Kernel.defstruct({ [Elixir.Kernel.SpecialForms.atom('__struct__')]: __MODULE__, [Elixir.Kernel.SpecialForms.atom('name')]: null, @@ -83,7 +83,7 @@ defmodule ElixirScript.Translator.Struct.Test do end js_code = """ - const __MODULE__ = Elixir.Kernel.SpecialForms.atom('User'); + const __MODULE__ = Elixir.Kernel.SpecialForms.atom('Elixir.User'); const defstruct = Elixir.Kernel.defstruct({ [Elixir.Kernel.SpecialForms.atom('__struct__')]: __MODULE__, [Elixir.Kernel.SpecialForms.atom('name')]: null, @@ -136,7 +136,7 @@ defmodule ElixirScript.Translator.Struct.Test do end js_code = """ - const __MODULE__ = Elixir.Kernel.SpecialForms.atom('MyAppError'); + const __MODULE__ = Elixir.Kernel.SpecialForms.atom('Elixir.MyAppError'); const defexception = Elixir.Kernel.defexception({ [Elixir.Kernel.SpecialForms.atom('__struct__')]: __MODULE__, [Elixir.Kernel.SpecialForms.atom('__exception__')]: true, @@ -156,7 +156,7 @@ defmodule ElixirScript.Translator.Struct.Test do end js_code = """ - const __MODULE__ = Elixir.Kernel.SpecialForms.atom('MyAppError'); + const __MODULE__ = Elixir.Kernel.SpecialForms.atom('Elixir.MyAppError'); const defexception = Elixir.Kernel.defexception({ [Elixir.Kernel.SpecialForms.atom('__struct__')]: __MODULE__, [Elixir.Kernel.SpecialForms.atom('__exception__')]: true, From 8f3af7e7021bed05acc4e1174e9fc1396bfd53b9 Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Sun, 6 Dec 2015 19:24:30 -0600 Subject: [PATCH 082/860] Removed Elixir.js --- priv/elixir.js | 4569 ------------------------------------------------ 1 file changed, 4569 deletions(-) delete mode 100644 priv/elixir.js diff --git a/priv/elixir.js b/priv/elixir.js deleted file mode 100644 index 07d90f1b..00000000 --- a/priv/elixir.js +++ /dev/null @@ -1,4569 +0,0 @@ -function call_property(item, property) { - if (property in item) { - item[property]; - if (item[property] instanceof Function) { - return item[property](); - } else { - return item[property]; - } - } else if (Symbol.for(property) in item) { - let prop = Symbol.for(property); - if (item[prop] instanceof Function) { - return item[prop](); - } else { - return item[prop]; - } - } - - throw new Error(`Property ${ property } not found in ${ item }`); -} - -class Tuple$1 { - - constructor(...args) { - this.values = Object.freeze(args); - } - - get(index) { - return this.values[index]; - } - - count() { - return this.values.length; - } - - [Symbol.iterator]() { - return this.values[Symbol.iterator](); - } - - toString() { - var i, - s = ""; - for (i = 0; i < this.values.length; i++) { - if (s !== "") { - s += ", "; - } - s += this.values[i].toString(); - } - - return "{" + s + "}"; - } - -} - -let process_counter = -1; - -class PID { - constructor() { - process_counter = process_counter + 1; - this.id = process_counter; - } - - toString() { - return "PID#<0." + this.id + ".0>"; - } -} - -class Integer$1 {} -class Float {} - -/* @flow */ - -class Variable { - - constructor(name = null) { - this.name = name; - } -} - -class Wildcard { - constructor() {} -} - -class StartsWith { - - constructor(prefix) { - this.prefix = prefix; - } -} - -class Capture { - - constructor(value) { - this.value = value; - } -} - -class HeadTail { - constructor() {} -} - -class Type { - - constructor(type, objPattern = {}) { - this.type = type; - this.objPattern = objPattern; - } -} - -class Bound { - - constructor(value) { - this.value = value; - } -} - -function variable(name = null) { - return new Variable(name); -} - -function wildcard() { - return new Wildcard(); -} - -function startsWith(prefix) { - return new StartsWith(prefix); -} - -function capture(value) { - return new Capture(value); -} - -function headTail() { - return new HeadTail(); -} - -function type(type, objPattern = {}) { - return new Type(type, objPattern); -} - -function bound(value) { - return new Bound(value); -} - -function is_number$1(value) { - return typeof value === 'number'; -} - -function is_string(value) { - return typeof value === 'string'; -} - -function is_boolean$1(value) { - return typeof value === 'boolean'; -} - -function is_symbol(value) { - return typeof value === 'symbol'; -} - -function is_null(value) { - return value === null; -} - -function is_undefined(value) { - return typeof value === 'undefined'; -} - -function is_function$1(value) { - return Object.prototype.toString.call(value) == '[object Function]'; -} - -function is_variable(value) { - return value instanceof Variable; -} - -function is_wildcard(value) { - return value instanceof Wildcard; -} - -function is_headTail(value) { - return value instanceof HeadTail; -} - -function is_capture(value) { - return value instanceof Capture; -} - -function is_type(value) { - return value instanceof Type; -} - -function is_startsWith(value) { - return value instanceof StartsWith; -} - -function is_bound(value) { - return value instanceof Bound; -} - -function is_object(value) { - return typeof value === 'object'; -} - -function is_array(value) { - return Array.isArray(value); -} - -var Checks = { - is_number: is_number$1, - is_string, - is_boolean: is_boolean$1, - is_symbol, - is_null, - is_undefined, - is_function: is_function$1, - is_variable, - is_wildcard, - is_headTail, - is_capture, - is_type, - is_startsWith, - is_bound, - is_object, - is_array -}; - -function resolveSymbol(pattern) { - return function (value) { - return Checks.is_symbol(value) && value === pattern; - }; -} - -function resolveString(pattern) { - return function (value) { - return Checks.is_string(value) && value === pattern; - }; -} - -function resolveNumber(pattern) { - return function (value) { - return Checks.is_number(value) && value === pattern; - }; -} - -function resolveBoolean(pattern) { - return function (value) { - return Checks.is_boolean(value) && value === pattern; - }; -} - -function resolveFunction(pattern) { - return function (value) { - return Checks.is_function(value) && value === pattern; - }; -} - -function resolveNull(pattern) { - return function (value) { - return Checks.is_null(value); - }; -} - -function resolveBound(pattern) { - return function (value, args) { - if (typeof value === typeof pattern.value && value === pattern.value) { - args.push(value); - return true; - } - - return false; - }; -} - -function resolveWildcard() { - return function () { - return true; - }; -} - -function resolveVariable() { - return function (value, args) { - args.push(value); - return true; - }; -} - -function resolveHeadTail() { - return function (value, args) { - if (!Checks.is_array(value) || value.length < 2) { - return false; - } - - const head = value[0]; - const tail = value.slice(1); - - args.push(head); - args.push(tail); - - return true; - }; -} - -function resolveCapture(pattern) { - const matches = buildMatch(pattern.value); - - return function (value, args) { - if (matches(value, args)) { - args.push(value); - return true; - } - - return false; - }; -} - -function resolveStartsWith(pattern) { - const prefix = pattern.prefix; - - return function (value, args) { - if (Checks.is_string(value) && value.startsWith(prefix)) { - args.push(value.substring(prefix.length)); - return true; - } - - return false; - }; -} - -function resolveType(pattern) { - return function (value, args) { - if (value instanceof pattern.type) { - const matches = buildMatch(pattern.objPattern); - return matches(value, args) && args.push(value) > 0; - } - - return false; - }; -} - -function resolveArray(pattern) { - const matches = pattern.map(x => buildMatch(x)); - - return function (value, args) { - if (!Checks.is_array(value) || value.length != pattern.length) { - return false; - } - - return value.every(function (v, i) { - return matches[i](value[i], args); - }); - }; -} - -function resolveObject(pattern) { - let matches = {}; - - for (let key of Object.keys(pattern)) { - matches[key] = buildMatch(pattern[key]); - } - - return function (value, args) { - if (!Checks.is_object(value) || pattern.length > value.length) { - return false; - } - - for (let key of Object.keys(pattern)) { - if (!(key in value) || !matches[key](value[key], args)) { - return false; - } - } - - return true; - }; -} - -function resolveNoMatch() { - return function () { - return false; - }; -} - -var Resolvers = { - resolveBound, - resolveWildcard, - resolveVariable, - resolveHeadTail, - resolveCapture, - resolveStartsWith, - resolveType, - resolveArray, - resolveObject, - resolveNoMatch, - resolveSymbol, - resolveString, - resolveNumber, - resolveBoolean, - resolveFunction, - resolveNull -}; - -function buildMatch(pattern) { - - if (Checks.is_variable(pattern)) { - return Resolvers.resolveVariable(pattern); - } - - if (Checks.is_wildcard(pattern)) { - return Resolvers.resolveWildcard(pattern); - } - - if (Checks.is_undefined(pattern)) { - return Resolvers.resolveWildcard(pattern); - } - - if (Checks.is_headTail(pattern)) { - return Resolvers.resolveHeadTail(pattern); - } - - if (Checks.is_startsWith(pattern)) { - return Resolvers.resolveStartsWith(pattern); - } - - if (Checks.is_capture(pattern)) { - return Resolvers.resolveCapture(pattern); - } - - if (Checks.is_bound(pattern)) { - return Resolvers.resolveBound(pattern); - } - - if (Checks.is_type(pattern)) { - return Resolvers.resolveType(pattern); - } - - if (Checks.is_array(pattern)) { - return Resolvers.resolveArray(pattern); - } - - if (Checks.is_number(pattern)) { - return Resolvers.resolveNumber(pattern); - } - - if (Checks.is_string(pattern)) { - return Resolvers.resolveString(pattern); - } - - if (Checks.is_boolean(pattern)) { - return Resolvers.resolveBoolean(pattern); - } - - if (Checks.is_symbol(pattern)) { - return Resolvers.resolveSymbol(pattern); - } - - if (Checks.is_null(pattern)) { - return Resolvers.resolveNull(pattern); - } - - if (Checks.is_object(pattern)) { - return Resolvers.resolveObject(pattern); - } - - return Resolvers.resolveNoMatch(); -} - -class MatchError extends Error { - constructor(arg) { - super(); - - if (typeof arg === 'symbol') { - this.message = 'No match for: ' + arg.toString(); - } else if (Array.isArray(arg)) { - let mappedValues = arg.map(x => x.toString()); - this.message = 'No match for: ' + mappedValues; - } else { - this.message = 'No match for: ' + arg; - } - - this.stack = new Error().stack; - this.name = this.constructor.name; - } -} - -class Case { - - constructor(pattern, fn, guard = () => true) { - this.pattern = buildMatch(pattern); - this.fn = fn; - this.guard = guard; - } -} - -function make_case(pattern, fn, guard = () => true) { - return new Case(pattern, fn, guard); -} - -function defmatch(...cases) { - return function (...args) { - for (let processedCase of cases) { - let result = []; - if (processedCase.pattern(args, result) && processedCase.guard.apply(this, result)) { - return processedCase.fn.apply(this, result); - } - } - - throw new MatchError(args); - }; -} - -function match(pattern, expr, guard = () => true) { - let result = []; - let processedPattern = buildMatch(pattern); - if (processedPattern(expr, result) && guard.apply(this, result)) { - return result; - } else { - throw new MatchError(expr); - } -} - -function match_no_throw(pattern, expr, guard = () => true) { - try { - return match(pattern, expr, guard); - } catch (e) { - if (e instanceof MatchError) { - return null; - } - - throw e; - } -} - -var Patterns = { - defmatch, match, MatchError, match_no_throw, - variable, wildcard, startsWith, - capture, headTail, type, bound, Case, make_case -}; - -class BitString { - constructor(...args) { - this.raw_value = function () { - return Object.freeze(args); - }; - - this.value = Object.freeze(this.process(args)); - } - - get(index) { - return this.value[index]; - } - - count() { - return this.value.length; - } - - [Symbol.iterator]() { - return this.value[Symbol.iterator](); - } - - toString() { - var i, - s = ""; - for (i = 0; i < this.count(); i++) { - if (s !== "") { - s += ", "; - } - s += this[i].toString(); - } - - return "<<" + s + ">>"; - } - - process() { - let processed_values = []; - - var i; - for (i = 0; i < this.raw_value().length; i++) { - let processed_value = this["process_" + this.raw_value()[i].type](this.raw_value()[i]); - - for (let attr of this.raw_value()[i].attributes) { - processed_value = this["process_" + attr](processed_value); - } - - processed_values = processed_values.concat(processed_value); - } - - return processed_values; - } - - process_integer(value) { - return value.value; - } - - process_float(value) { - if (value.size === 64) { - return BitString.float64ToBytes(value.value); - } else if (value.size === 32) { - return BitString.float32ToBytes(value.value); - } - - throw new Error("Invalid size for float"); - } - - process_bitstring(value) { - return value.value.value; - } - - process_binary(value) { - return BitString.toUTF8Array(value.value); - } - - process_utf8(value) { - return BitString.toUTF8Array(value.value); - } - - process_utf16(value) { - return BitString.toUTF16Array(value.value); - } - - process_utf32(value) { - return BitString.toUTF32Array(value.value); - } - - process_signed(value) { - return new Uint8Array([value])[0]; - } - - process_unsigned(value) { - return value; - } - - process_native(value) { - return value; - } - - process_big(value) { - return value; - } - - process_little(value) { - return value.reverse(); - } - - process_size(value) { - return value; - } - - process_unit(value) { - return value; - } - - static integer(value) { - return BitString.wrap(value, { "type": "integer", "unit": 1, "size": 8 }); - } - - static float(value) { - return BitString.wrap(value, { "type": "float", "unit": 1, "size": 64 }); - } - - static bitstring(value) { - return BitString.wrap(value, { "type": "bitstring", "unit": 1, "size": value.length }); - } - - static bits(value) { - return BitString.bitstring(value); - } - - static binary(value) { - return BitString.wrap(value, { "type": "binary", "unit": 8, "size": value.length }); - } - - static bytes(value) { - return BitString.binary(value); - } - - static utf8(value) { - return BitString.wrap(value, { "type": "utf8" }); - } - - static utf16(value) { - return BitString.wrap(value, { "type": "utf16" }); - } - - static utf32(value) { - return BitString.wrap(value, { "type": "utf32" }); - } - - static signed(value) { - return BitString.wrap(value, {}, "signed"); - } - - static unsigned(value) { - return BitString.wrap(value, {}, "unsigned"); - } - - static native(value) { - return BitString.wrap(value, {}, "native"); - } - - static big(value) { - return BitString.wrap(value, {}, "big"); - } - - static little(value) { - return BitString.wrap(value, {}, "little"); - } - - static size(value, count) { - return BitString.wrap(value, { "size": count }); - } - - static unit(value, count) { - return BitString.wrap(value, { "unit": count }); - } - - static wrap(value, opt, new_attribute = null) { - let the_value = value; - - if (!(value instanceof Object)) { - the_value = { "value": value, "attributes": [] }; - } - - the_value = Object.assign(the_value, opt); - - if (new_attribute) { - the_value.attributes.push(new_attribute); - } - - return the_value; - } - - static toUTF8Array(str) { - var utf8 = []; - for (var i = 0; i < str.length; i++) { - var charcode = str.charCodeAt(i); - if (charcode < 128) { - utf8.push(charcode); - } else if (charcode < 2048) { - utf8.push(192 | charcode >> 6, 128 | charcode & 63); - } else if (charcode < 55296 || charcode >= 57344) { - utf8.push(224 | charcode >> 12, 128 | charcode >> 6 & 63, 128 | charcode & 63); - } - // surrogate pair - else { - i++; - // UTF-16 encodes 0x10000-0x10FFFF by - // subtracting 0x10000 and splitting the - // 20 bits of 0x0-0xFFFFF into two halves - charcode = 65536 + ((charcode & 1023) << 10 | str.charCodeAt(i) & 1023); - utf8.push(240 | charcode >> 18, 128 | charcode >> 12 & 63, 128 | charcode >> 6 & 63, 128 | charcode & 63); - } - } - return utf8; - } - - static toUTF16Array(str) { - var utf16 = []; - for (var i = 0; i < str.length; i++) { - var codePoint = str.codePointAt(i); - - if (codePoint <= 255) { - utf16.push(0); - utf16.push(codePoint); - } else { - utf16.push(codePoint >> 8 & 255); - utf16.push(codePoint & 255); - } - } - return utf16; - } - - static toUTF32Array(str) { - var utf32 = []; - for (var i = 0; i < str.length; i++) { - var codePoint = str.codePointAt(i); - - if (codePoint <= 255) { - utf32.push(0); - utf32.push(0); - utf32.push(0); - utf32.push(codePoint); - } else { - utf32.push(0); - utf32.push(0); - utf32.push(codePoint >> 8 & 255); - utf32.push(codePoint & 255); - } - } - return utf32; - } - - //http://stackoverflow.com/questions/2003493/javascript-float-from-to-bits - static float32ToBytes(f) { - var bytes = []; - - var buf = new ArrayBuffer(4); - new Float32Array(buf)[0] = f; - - let intVersion = new Uint32Array(buf)[0]; - - bytes.push(intVersion >> 24 & 255); - bytes.push(intVersion >> 16 & 255); - bytes.push(intVersion >> 8 & 255); - bytes.push(intVersion & 255); - - return bytes; - } - - static float64ToBytes(f) { - var bytes = []; - - var buf = new ArrayBuffer(8); - new Float64Array(buf)[0] = f; - - var intVersion1 = new Uint32Array(buf)[0]; - var intVersion2 = new Uint32Array(buf)[1]; - - bytes.push(intVersion2 >> 24 & 255); - bytes.push(intVersion2 >> 16 & 255); - bytes.push(intVersion2 >> 8 & 255); - bytes.push(intVersion2 & 255); - - bytes.push(intVersion1 >> 24 & 255); - bytes.push(intVersion1 >> 16 & 255); - bytes.push(intVersion1 >> 8 & 255); - bytes.push(intVersion1 & 255); - - return bytes; - } -} - -/* @flow */ - -class Mailbox { - - constructor() { - this.messages = []; - } - - deliver(message) { - this.messages.push(message); - return message; - } - - get() { - return this.messages; - } - - isEmpty() { - return this.messages.length === 0; - } - - removeAt(index) { - this.messages.splice(index, 1); - } -} - -var States = { - NORMAL: Symbol.for("normal"), - KILL: Symbol.for("kill"), - SUSPEND: Symbol.for("suspend"), - CONTINUE: Symbol.for("continue"), - RECEIVE: Symbol.for("receive"), - SEND: Symbol.for("send"), - SLEEPING: Symbol.for("sleeping"), - RUNNING: Symbol.for("running"), - SUSPENDED: Symbol.for("suspended"), - STOPPED: Symbol.for("stopped"), - SLEEP: Symbol.for("sleep"), - EXIT: Symbol.for("exit"), - NOMATCH: Symbol.for("no_match") -}; - -class Process { - - constructor(pid, mailbox) { - this.pid = pid; - this.mailbox = mailbox; - this.status = States.STOPPED; - this.dict = {}; - } -} - -class ProcessSystem { - - constructor() { - this.pids = new Map(); - this.mailboxes = new Map(); - this.names = new Map(); - this.links = new Map(); - - this.current_process = null; - this.suspended = new Map(); - - this.main_process_pid = this.spawn(); - this.set_current(this.main_process_pid); - } - - spawn() { - return this.add_proc(false).pid; - } - - spawn_link() { - return this.add_proc(true).pid; - } - - link(pid) { - this.links.get(this.pid()).add(pid); - this.links.get(pid).add(this.pid()); - } - - unlink(pid) { - this.links.get(this.pid()).delete(pid); - this.links.get(pid).delete(this.pid()); - } - - set_current(id) { - let pid = this.pidof(id); - if (pid !== null) { - this.current_process = this.pids.get(pid); - this.current_process.status = States.RUNNING; - } - } - - add_proc(linked) { - let newpid = new PID(); - let mailbox = new Mailbox(); - let newproc = new Process(newpid, mailbox); - - this.pids.set(newpid, newproc); - this.mailboxes.set(newpid, mailbox); - this.links.set(newpid, new Set()); - - if (linked) { - this.link(newpid); - } - - return newproc; - } - - remove_proc(pid) { - this.pids.delete(pid); - this.unregister(pid); - - if (this.links.has(pid)) { - for (let linkpid of this.links.get(pid)) { - this.links.get(linkpid).delete(pid); - } - - this.links.delete(pid); - } - } - - exit(id) { - let pid = this.pidof(id); - this.remove_proc(id); - } - - register(name, pid) { - if (!this.names.has(name)) { - this.names.set(name, pid); - return name; - } else { - throw new Error("Name is already registered to another process"); - } - } - - registered(name) { - return this.names.has(name) ? this.names.get(name) : null; - } - - unregister(pid) { - for (let name of this.names.keys()) { - if (this.names.has(name) && this.names.get(name) === pid) { - this.names.delete(name); - } - } - } - - pid() { - return this.current_process.pid; - } - - pidof(id) { - if (id instanceof PID) { - return this.pids.has(id) ? id : null; - } else if (id instanceof Process) { - return id.pid; - } else { - let pid = this.registered(id); - if (pid === null) throw "Process name not registered: " + id + " (" + typeof id + ")"; - return pid; - } - } - - put(id, key, value) { - let pid = this.pidof(id); - let process = this.pids.get(pid); - process.dict[key] = value; - } - - get(id, key) { - let pid = this.pidof(id); - let process = this.pids.get(pid); - - if (key != null) { - return process.dict[key]; - } else { - return process.dict; - } - } - - get_keys(id) { - let pid = this.pidof(id); - let process = this.pids.get(pid); - - return Object.keys(process.dict); - } - - erase(id, key) { - let pid = this.pidof(id); - let process = this.pids.get(pid); - - if (key != null) { - delete process.dict[key]; - } else { - process.dict = {}; - } - } -} - -var C = Object.freeze({ - ProcessSystem: ProcessSystem, - Tuple: Tuple$1, - PID: PID, - BitString: BitString, - Patterns: Patterns, - Integer: Integer$1, - Float: Float, - call_property: call_property -}); - -let Enum = { - - all__qmark__: function (collection, fun = x => x) { - for (let elem of collection) { - if (!fun(elem)) { - return false; - } - } - - return true; - }, - - any__qmark__: function (collection, fun = x => x) { - for (let elem of collection) { - if (fun(elem)) { - return true; - } - } - - return false; - }, - - at: function (collection, n, the_default = null) { - if (n > this.count(collection) || n < 0) { - return the_default; - } - - return collection[n]; - }, - - concat: function (...enumables) { - return enumables[0].concat(enumables[1]); - }, - - count: function (collection, fun = null) { - if (fun == null) { - return collection.length; - } else { - return collection.filter(fun).length; - } - }, - - drop: function (collection, count) { - return collection.slice(count); - }, - - drop_while: function (collection, fun) { - let count = 0; - - for (let elem of collection) { - if (fun(elem)) { - count = count + 1; - } else { - break; - } - } - - return collection.slice(count); - }, - - each: function (collection, fun) { - for (let elem of collection) { - fun(elem); - } - }, - - empty__qmark__: function (collection) { - return collection.length === 0; - }, - - fetch: function (collection, n) { - if (Kernel.is_list(collection)) { - if (n < this.count(collection) && n >= 0) { - return Kernel.SpecialForms.tuple(Kernel.SpecialForms.atom("ok"), collection[n]); - } else { - return Kernel.SpecialForms.atom("error"); - } - } - - throw new Error("collection is not an Enumerable"); - }, - - fetch__emark__: function (collection, n) { - if (Kernel.is_list(collection)) { - if (n < this.count(collection) && n >= 0) { - return collection[n]; - } else { - throw new Error("out of bounds error"); - } - } - - throw new Error("collection is not an Enumerable"); - }, - - filter: function (collection, fun) { - let result = []; - - for (let elem of collection) { - if (fun(elem)) { - result.push(elem); - } - } - - return result; - }, - - filter_map: function (collection, filter, mapper) { - return Enum.map(Enum.filter(collection, filter), mapper); - }, - - find: function (collection, if_none = null, fun) { - for (let elem of collection) { - if (fun(elem)) { - return elem; - } - } - - return if_none; - }, - - into: function (collection, list) { - return list.concat(collection); - }, - - map: function (collection, fun) { - let result = []; - - for (let elem of collection) { - result.push(fun(elem)); - } - - return result; - }, - - map_reduce: function (collection, acc, fun) { - let mapped = Kernel.SpecialForms.list(); - let the_acc = acc; - - for (var i = 0; i < this.count(collection); i++) { - let tuple = fun(collection[i], the_acc); - - the_acc = Kernel.elem(tuple, 1); - mapped = Kernel.SpecialForms.list(...mapped.concat([Kernel.elem(tuple, 0)])); - } - - return Kernel.SpecialForms.tuple(mapped, the_acc); - }, - - member: function (collection, value) { - return collection.includes(value); - }, - - reduce: function (collection, acc, fun) { - let the_acc = acc; - - for (var i = 0; i < this.count(collection); i++) { - let tuple = fun(collection[i], the_acc); - - the_acc = Kernel.elem(tuple, 1); - } - - return the_acc; - }, - - take: function (collection, count) { - return collection.slice(0, count); - }, - - take_every: function (collection, nth) { - let result = []; - let index = 0; - - for (let elem of collection) { - if (index % nth === 0) { - result.push(elem); - } - } - - return Kernel.SpecialForms.list(...result); - }, - - take_while: function (collection, fun) { - let count = 0; - - for (let elem of collection) { - if (fun(elem)) { - count = count + 1; - } else { - break; - } - } - - return collection.slice(0, count); - }, - - to_list: function (collection) { - return collection; - } -}; - -let SpecialForms = { - - __DIR__: function () { - if (__dirname) { - return __dirname; - } - - if (document.currentScript) { - return document.currentScript.src; - } - - return null; - }, - - atom: function (_value) { - return Symbol.for(_value); - }, - - list: function (...args) { - return Object.freeze(args); - }, - - bitstring: function (...args) { - return new BitString(...args); - }, - - bound: function (_var) { - return Patterns.bound(_var); - }, - - _case: function (condition, clauses) { - return Patterns.defmatch(...clauses)(condition); - }, - - cond: function (clauses) { - for (let clause of clauses) { - if (clause[0]) { - return clause[1](); - } - } - - throw new Error(); - }, - - fn: function (clauses) { - return Patterns.defmatch(clauses); - }, - - map: function (obj) { - return Object.freeze(obj); - }, - - map_update: function (map, values) { - return Object.freeze(Object.assign(Object.create(map.constructor.prototype), map, values)); - }, - - _for: function (collections, fun, filter = () => true, into = [], previousValues = []) { - let pattern = collections[0][0]; - let collection = collections[0][1]; - - if (collections.length === 1) { - - for (let elem of collection) { - let r = Patterns.match_no_throw(pattern, elem); - let args = previousValues.concat(r); - - if (r && filter.apply(this, args)) { - into = Enum.into([fun.apply(this, args)], into); - } - } - - return into; - } else { - let _into = []; - - for (let elem of collection) { - let r = Patterns.match_no_throw(pattern, elem); - if (r) { - _into = Enum.into(this._for(collections.slice(1), fun, filter, _into, previousValues.concat(r)), into); - } - } - - return _into; - } - }, - - receive: function (receive_fun, timeout_in_ms = null, timeout_fn = time => true) { - if (timeout_in_ms == null || timeout_in_ms === System.for('infinity')) { - while (true) { - if (self.mailbox.length !== 0) { - let message = self.mailbox[0]; - self.mailbox = self.mailbox.slice(1); - return receive_fun(message); - } - } - } else if (timeout_in_ms === 0) { - if (self.mailbox.length !== 0) { - let message = self.mailbox[0]; - self.mailbox = self.mailbox.slice(1); - return receive_fun(message); - } else { - return null; - } - } else { - let now = Date.now(); - while (Date.now() < now + timeout_in_ms) { - if (self.mailbox.length !== 0) { - let message = self.mailbox[0]; - self.mailbox = self.mailbox.slice(1); - return receive_fun(message); - } - } - - return timeout_fn(timeout_in_ms); - } - }, - - tuple: function (...args) { - return new Tuple$1(...args); - }, - - _try: function (do_fun, rescue_function, catch_fun, else_function, after_function) { - let result = null; - - try { - result = do_fun(); - } catch (e) { - let ex_result = null; - - if (rescue_function) { - try { - ex_result = rescue_function(e); - return ex_result; - } catch (ex) { - if (ex instanceof Patterns.MatchError) { - throw ex; - } - } - } - - if (catch_fun) { - try { - ex_result = catch_fun(e); - return ex_result; - } catch (ex) { - if (ex instanceof Patterns.MatchError) { - throw ex; - } - } - } - - throw e; - } finally { - if (after_function) { - after_function(); - } - } - - if (else_function) { - try { - return else_function(result); - } catch (ex) { - if (ex instanceof Patterns.MatchError) { - throw new Error('No Match Found in Else'); - } - - throw ex; - } - } else { - return result; - } - } - -}; - -function to_string$1(tuple) { - return tuple.toString(); -}; - -function delete_at(tuple, index) { - let new_list = []; - - for (var i = 0; i < tuple.count(); i++) { - if (i !== index) { - new_list.push(tuple.get(i)); - } - } - - return Kernel.SpecialForms.tuple.apply(null, new_list); -}; - -function duplicate(data, size) { - let array = []; - - for (var i = size - 1; i >= 0; i--) { - array.push(data); - } - - return Kernel.SpecialForms.tuple.apply(null, array); -}; - -function insert_at(tuple, index, term) { - let new_tuple = []; - - for (var i = 0; i <= tuple.count(); i++) { - if (i === index) { - new_tuple.push(term); - i++; - new_tuple.push(tuple.get(i)); - } else { - new_tuple.push(tuple.get(i)); - } - } - - return Kernel.SpecialForms.tuple.apply(null, new_tuple); -}; - -function from_list(list) { - return Kernel.SpecialForms.tuple.apply(null, list); -}; - -function to_list(tuple) { - let new_list = []; - - for (var i = 0; i < tuple.count(); i++) { - new_list.push(tuple.get(i)); - } - - return Kernel.SpecialForms.list(...new_list); -}; - -var Tuple = { - to_string: to_string$1, - delete_at, - duplicate, - insert_at, - from_list, - to_list -}; - -//https://github.com/airportyh/protomorphism -class Protocol { - constructor(spec) { - this.registry = new Map(); - this.fallback = null; - - for (let funName in spec) { - this[funName] = createFun(funName).bind(this); - } - - function createFun(funName) { - - return function (...args) { - let thing = args[0]; - let fun = null; - - if (Number.isInteger(thing) && this.hasImplementation(Integer$1)) { - fun = this.registry.get(Integer$1)[funName]; - } else if (typeof thing === "number" && !Number.isInteger(thing) && this.hasImplementation(Float)) { - fun = this.registry.get(Float)[funName]; - } else if (this.hasImplementation(thing)) { - fun = this.registry.get(thing.constructor)[funName]; - } else if (this.fallback) { - fun = this.fallback[funName]; - } - - if (fun != null) { - let retval = fun.apply(this, args); - return retval; - } - - throw new Error("No implementation found for " + thing); - }; - } - } - - implementation(type, implementation) { - if (type === null) { - this.fallback = implementation; - } else { - this.registry.set(type, implementation); - } - } - - hasImplementation(thing) { - return this.registry.has(thing.constructor); - } -} - -function tl(list) { - return SpecialForms.list(...list.slice(1)); -} - -function hd(list) { - return list[0]; -} - -function is_nil(x) { - return x === null; -} - -function is_atom(x) { - return typeof x === 'symbol'; -} - -function is_binary(x) { - return typeof x === 'string' || x instanceof String; -} - -function is_boolean(x) { - return typeof x === 'boolean' || x instanceof Boolean; -} - -function is_function(x, arity = -1) { - return typeof x === 'function' || x instanceof Function; -} - -function is_float(x) { - return is_number(x) && !Number.isInteger(x); -} - -function is_integer(x) { - return Number.isInteger(x); -} - -function is_list(x) { - return x instanceof Array; -} - -function is_map(x) { - return typeof x === 'object' || x instanceof Object; -} - -function is_number(x) { - return typeof x === 'number'; -} - -function is_tuple(x) { - return x instanceof Tuple$1; -} - -function length(x) { - return x.length; -} - -function is_pid(x) { - return x instanceof PID; -} - -function is_port(x) { - return false; -} - -function is_reference(x) { - return false; -} - -function is_bitstring(x) { - return is_binary(x) || x instanceof BitString; -} - -function __in__(left, right) { - for (let x of right) { - if (match__qmark__(left, x)) { - return true; - } - } - - return false; -} - -function abs(number) { - return Math.abs(number); -} - -function round(number) { - return Math.round(number); -} - -function elem(tuple, index) { - if (is_list(tuple)) { - return tuple[index]; - } - - return tuple.get(index); -} - -function rem(left, right) { - return left % right; -} - -function div(left, right) { - return left / right; -} - -function and(left, right) { - return left && right; -} - -function or(left, right) { - return left || right; -} - -function not(arg) { - return !arg; -} - -function apply(...args) { - if (args.length === 3) { - let mod = args[0]; - let func = args[1]; - let func_args = args[2]; - return mod[func].apply(null, func_args); - } else { - let func = args[0]; - let func_args = args[1]; - - return func.apply(null, func_args); - } -} - -function to_string(arg) { - if (is_tuple(arg)) { - return Tuple.to_string(arg); - } - - return arg.toString(); -} - -function match__qmark__(pattern, expr, guard = () => true) { - return Patterns.match_no_throw(pattern, expr, guard) != null; -} - -function defstruct(defaults) { - return class { - constructor(update = {}) { - let the_values = Object.assign(defaults, update); - Object.assign(this, the_values); - } - - static create(updates = {}) { - let x = new this(updates); - return Object.freeze(x); - } - }; -} - -function defprotocol(spec) { - return new Protocol(spec); -} - -function defimpl(protocol, type, impl) { - protocol.implementation(type, impl); -} - -var Kernel = { - SpecialForms, - tl, - hd, - is_nil, - is_atom, - is_binary, - is_boolean, - is_function, - is_float, - is_integer, - is_list, - is_map, - is_number, - is_tuple, - length, - is_pid, - is_port, - is_reference, - is_bitstring, - in: __in__, - abs, - round, - elem, - rem, - div, - and, - or, - not, - apply, - to_string, - match__qmark__, - defstruct, - defprotocol, - defimpl -}; - -let Atom = {}; - -Atom.to_string = function (atom) { - return Symbol.keyFor(atom); -}; - -Atom.to_char_list = function (atom) { - return Atom.to_string(atom).split(''); -}; - -let Integer = { - - is_even: function (n) { - return n % 2 === 0; - }, - - is_odd: function (n) { - return n % 2 !== 0; - }, - - parse: function (bin) { - let result = parseInt(bin); - - if (isNaN(result)) { - return Kernel.SpecialForms.atom("error"); - } - - let indexOfDot = bin.indexOf("."); - - if (indexOfDot >= 0) { - return Kernel.SpecialForms.tuple(result, bin.substring(indexOfDot)); - } - - return Kernel.SpecialForms.tuple(result, ""); - }, - - to_char_list: function (number, base = 10) { - return number.toString(base).split(""); - }, - - to_string: function (number, base = 10) { - return number.toString(base); - } -}; - -let Chars$1 = Kernel.defprotocol({ - to_string: function (thing) {} -}); - -Kernel.defimpl(Chars$1, BitString, { - to_string: function (thing) { - if (Kernel.is_binary(thing)) { - return thing; - } - - return thing.toString(); - } -}); - -Kernel.defimpl(Chars$1, Symbol, { - to_string: function (thing) { - if (nil) { - return ""; - } - - return Atom.to_string(thing); - } -}); - -Kernel.defimpl(Chars$1, Integer$1, { - to_string: function (thing) { - return Integer.to_string(thing); - } -}); - -Kernel.defimpl(Chars$1, Float, { - to_string: function (thing) { - return thing.toString; - } -}); - -Kernel.defimpl(Chars$1, Array, { - to_string: function (thing) { - return thing.toString(); - } -}); - -Kernel.defimpl(Chars$1, Tuple$1, { - to_string: function (thing) { - return Tuple.to_string(thing); - } -}); - -Kernel.defimpl(Chars$1, null, { - to_string: function (thing) { - return thing.toString(); - } -}); - -function to_atom(string) { - return Symbol.for(string); -} - -function to_existing_atom(string) { - return Symbol.for(string); -} - -function to_char_list(string) { - return string.split(''); -} - -function to_float(string) { - return parseFloat(string); -} - -function to_integer(string, base = 10) { - return parseInt(string, base); -} - -function upcase(binary) { - return binary.toUpperCase(); -} - -function downcase(binary) { - return binary.toLowerCase(); -} - -function at(string, position) { - if (position > string.length - 1) { - return null; - } - - return string[position]; -} - -function capitalize(string) { - let returnString = ''; - - for (let i = 0; i < string.length; i++) { - if (i === 0) { - returnString = returnString + string[i].toUpperCase(); - } else { - returnString = returnString + string[i].toLowerCase(); - } - } - - return returnString; -} - -function codepoints(string) { - return to_char_list(string).map(function (c) { - return c.codePointAt(0); - }); -} - -function contains__qm__(string, contains) { - if (Array.isArray(contains)) { - return contains.some(function (s) { - return string.indexOf(s) > -1; - }); - } - - return string.indexOf(contains) > -1; -} - -function duplicate$1(subject, n) { - return subject.repeat(n); -} - -function ends_with__qm__(string, suffixes) { - if (Array.isArray(suffixes)) { - return suffixes.some(function (s) { - return string.endsWith(s); - }); - } - - return string.endsWith(suffixes); -} - -function first(string) { - if (!string) { - return null; - } - - return string[0]; -} - -function graphemes(string) { - return string.split(''); -} - -function last(string) { - if (!string) { - return null; - } - - return string[string.length - 1]; -} - -function length$1(string) { - return string.length; -} - -function match__qm__(string, regex) { - return string.match(regex) != null; -} - -function next_codepoint(string) { - if (!string || string === '') { - return null; - } - - return Kernel.SpecialForms.tuple(string[0].codePointAt(0), string.substr(1)); -} - -function next_grapheme(string) { - if (!string || string === '') { - return null; - } - - return Kernel.SpecialForms.tuple(string[0], string.substr(1)); -} - -function reverse(string) { - let returnValue = ''; - - for (var i = string.length - 1; i >= 0; i--) { - returnValue = returnValue + string[i]; - }; - - return returnValue; -} - -function split(string) { - return string.split(); -} - -function starts_with__qm__(string, prefixes) { - if (Array.isArray(prefixes)) { - return prefixes.some(function (s) { - return string.startsWith(s); - }); - } - - return string.startsWith(prefixes); -} - -function valid_character__qm__(codepoint) { - try { - return String.fromCodePoint(codepoint) != null; - } catch (e) { - return false; - } -} - -var String$1 = { - at, - capitalize, - codepoints, - contains__qm__, - downcase, - duplicate: duplicate$1, - ends_with__qm__, - first, - graphemes, - last, - length: length$1, - match__qm__, - next_codepoint, - next_grapheme, - reverse, - split, - starts_with__qm__, - to_atom, - to_char_list, - to_existing_atom, - to_float, - to_integer, - upcase, - valid_character__qm__, - Chars: Chars$1 -}; - -let Chars = Kernel.defprotocol({ - to_char_list: function (thing) {} -}); - -Kernel.defimpl(Chars, BitString, { - to_char_list: function (thing) { - if (Kernel.is_binary(thing)) { - return String$1.to_char_list(thing); - } - - return thing.toString(); - } -}); - -Kernel.defimpl(Chars, Symbol, { - to_char_list: function (thing) { - return Atom.to_char_list(thing); - } -}); - -Kernel.defimpl(Chars, Integer$1, { - to_char_list: function (thing) { - return Integer.to_char_list(thing); - } -}); - -Kernel.defimpl(Chars, Array, { - to_char_list: function (thing) { - return thing; - } -}); - -let List = {}; - -List.Chars = Chars; - -List.delete = function (list, item) { - let new_value = []; - let value_found = false; - - for (let x of list) { - if (x === item && value_found !== false) { - new_value.push(x); - value_found = true; - } else if (x !== item) { - new_value.push(x); - } - } - - return Kernel.SpecialForms.list(...new_value); -}; - -List.delete_at = function (list, index) { - let new_value = []; - - for (let i = 0; i < list.length; i++) { - if (i !== index) { - new_value.push(list[i]); - } - } - - return Kernel.SpecialForms.list(...new_value); -}; - -List.duplicate = function (elem, n) { - let new_value = []; - - for (var i = 0; i < n; i++) { - new_value.push(elem); - } - - return Kernel.SpecialForms.list(...new_value); -}; - -List.first = function (list) { - return list[0]; -}; - -List.flatten = function (list, tail = Kernel.SpecialForms.list()) { - let new_value = []; - - for (let x of list) { - if (Kernel.is_list(x)) { - new_value = new_value.concat(List.flatten(x)); - } else { - new_value.push(x); - } - } - - new_value = new_value.concat(tail); - - return Kernel.SpecialForms.list(...new_value); -}; - -List.foldl = function (list, acc, func) { - return list.reduce(func, acc); -}; - -List.foldr = function (list, acc, func) { - let new_acc = acc; - - for (var i = list.length - 1; i >= 0; i--) { - new_acc = func(list[i], new_acc); - } - - return new_acc; -}; - -List.insert_at = function (list, index, value) { - let new_value = []; - - for (let i = 0; i < list.length; i++) { - if (i === index) { - new_value.push(value); - new_value.push(list[i]); - } else { - new_value.push(list[i]); - } - } - - return Kernel.SpecialForms.list(...new_value); -}; - -List.keydelete = function (list, key, position) { - let new_list = []; - - for (let i = 0; i < list.length; i++) { - if (!Kernel.match__qmark__(list[i][position], key)) { - new_list.push(list[i]); - } - } - - return Kernel.SpecialForms.list(...new_list); -}; - -List.keyfind = function (list, key, position, _default = null) { - - for (let i = 0; i < list.length; i++) { - if (Kernel.match__qmark__(list[i][position], key)) { - return list[i]; - } - } - - return _default; -}; - -List.keymember__qmark__ = function (list, key, position) { - - for (let i = 0; i < list.length; i++) { - if (Kernel.match__qmark__(list[i][position], key)) { - return true; - } - } - - return false; -}; - -List.keyreplace = function (list, key, position, new_tuple) { - let new_list = []; - - for (let i = 0; i < list.length; i++) { - if (!Kernel.match__qmark__(list[i][position], key)) { - new_list.push(list[i]); - } else { - new_list.push(new_tuple); - } - } - - return Kernel.SpecialForms.list(...new_list); -}; - -List.keysort = function (list, position) { - let new_list = list; - - new_list.sort(function (a, b) { - if (position === 0) { - if (a[position].value < b[position].value) { - return -1; - } - - if (a[position].value > b[position].value) { - return 1; - } - - return 0; - } else { - if (a[position] < b[position]) { - return -1; - } - - if (a[position] > b[position]) { - return 1; - } - - return 0; - } - }); - - return Kernel.SpecialForms.list(...new_list); -}; - -List.keystore = function (list, key, position, new_tuple) { - let new_list = []; - let replaced = false; - - for (let i = 0; i < list.length; i++) { - if (!Kernel.match__qmark__(list[i][position], key)) { - new_list.push(list[i]); - } else { - new_list.push(new_tuple); - replaced = true; - } - } - - if (!replaced) { - new_list.push(new_tuple); - } - - return Kernel.SpecialForms.list(...new_list); -}; - -List.last = function (list) { - return list[list.length - 1]; -}; - -List.replace_at = function (list, index, value) { - let new_value = []; - - for (let i = 0; i < list.length; i++) { - if (i === index) { - new_value.push(value); - } else { - new_value.push(list[i]); - } - } - - return Kernel.SpecialForms.list(...new_value); -}; - -List.update_at = function (list, index, fun) { - let new_value = []; - - for (let i = 0; i < list.count(); i++) { - if (i === index) { - new_value.push(fun(list.get(i))); - } else { - new_value.push(list.get(i)); - } - } - - return new_value; -}; - -List.wrap = function (list) { - if (Kernel.is_list(list)) { - return list; - } else if (list == null) { - return Kernel.SpecialForms.list(); - } else { - return Kernel.SpecialForms.list(list); - } -}; - -List.zip = function (list_of_lists) { - if (list_of_lists.length === 0) { - return Kernel.SpecialForms.list(); - } - - let new_value = []; - let smallest_length = list_of_lists[0]; - - for (let x of list_of_lists) { - if (x.length < smallest_length) { - smallest_length = x.length; - } - } - - for (let i = 0; i < smallest_length; i++) { - let current_value = []; - for (let j = 0; j < list_of_lists.length; j++) { - current_value.push(list_of_lists[j][i]); - } - - new_value.push(Kernel.SpecialForms.tuple(...current_value)); - } - - return Kernel.SpecialForms.list(...new_value); -}; - -List.to_tuple = function (list) { - return Kernel.SpecialForms.tuple.apply(null, list); -}; - -List.append = function (list, value) { - return Kernel.SpecialForms.list(...list.concat([value])); -}; - -List.prepend = function (list, value) { - return Kernel.SpecialForms.list(...[value].concat(list)); -}; - -List.concat = function (left, right) { - return left.concat(right); -}; - -let Range = function (_first, _last) { - if (!(this instanceof Range)) { - return new Range(_first, _last); - } - - this.first = function () { - return _first; - }; - - this.last = function () { - return _last; - }; - - let _range = []; - - for (let i = _first; i <= _last; i++) { - _range.push(i); - } - - _range = Object.freeze(_range); - - this.value = function () { - return _range; - }; - - this.length = function () { - return _range.length; - }; - - return this; -}; - -Range.prototype[Symbol.iterator] = function () { - return this.value()[Symbol.iterator](); -}; - -Range.new = function (first, last) { - return Range(first, last); -}; - -Range.range__qmark__ = function (range) { - return range instanceof Range; -}; - -let Keyword = {}; - -Keyword.has_key__qm__ = function (keywords, key) { - for (let keyword of keywords) { - if (Kernel.elem(keyword, 0) == key) { - return true; - } - } - - return false; -}; - -Keyword.get = function (keywords, key, the_default = null) { - for (let keyword of keywords) { - if (Kernel.elem(keyword, 0) == key) { - return Kernel.elem(keyword, 1); - } - } - - return the_default; -}; - -let Agent = {}; - -Agent.start = function (fun, options = []) { - let pid = self.processes.spawn(); - - if (Keyword.has_key__qm__(options, Kernel.SpecialForms.atom('name'))) { - pid = self.processes.register(Keyword.get(options, Kernel.SpecialForms.atom('name')), pid); - } - - self.processes.put(pid, 'state', fun()); - return Kernel.SpecialForms.tuple(Kernel.SpecialForms.atom('ok'), pid); -}; - -Agent.stop = function (agent, timeout = 5000) { - self.processes.exit(agent); - return Kernel.SpecialForms.atom('ok'); -}; - -Agent.update = function (agent, fun, timeout = 5000) { - - const current_state = self.processes.get(agent, 'state'); - self.processes.put(agent, 'state', fun(current_state)); - - return Kernel.SpecialForms.atom('ok'); -}; - -Agent.get = function (agent, fun, timeout = 5000) { - return fun(self.processes.get(agent, 'state')); -}; - -Agent.get_and_update = function (agent, fun, timeout = 5000) { - - const get_and_update_tuple = fun(self.processes.get(agent, 'state')); - self.processes.put(agent, 'state', Kernel.elem(get_and_update_tuple, 1)); - - return Kernel.elem(get_and_update_tuple, 0); -}; - -//https://developer.mozilla.org/en-US/docs/Web/API/WindowBase64/Base64_encoding_and_decoding#Solution_2_%E2%80%93_rewrite_the_DOMs_atob()_and_btoa()_using_JavaScript's_TypedArrays_and_UTF-8 -function b64EncodeUnicode(str) { - return btoa(encodeURIComponent(str).replace(/%([0-9A-F]{2})/g, function (match, p1) { - return String.fromCharCode('0x' + p1); - })); -} - -function encode64(data) { - return b64EncodeUnicode(data); -} - -function decode64(data) { - try { - return Kernel.SpecialForms.tuple(Kernel.SpecialForms.atom('ok'), atob(data)); - } catch (e) { - return Kernel.SpecialForms.atom('error'); - } - return btoa(data); -} - -function decode64__em__(data) { - return atob(data); -} - -var base = { - encode64, - decode64, - decode64__em__ -}; - -function bnot(expr) { - return ~expr; -} - -function band(left, right) { - return left & right; -} - -function bor(left, right) { - return left | right; -} - -function bsl(left, right) { - return left << right; -} - -function bsr(left, right) { - return left >> right; -} - -function bxor(left, right) { - return left ^ right; -} - -var bitwise = { - bnot, - band, - bor, - bsl, - bsr, - bxor -}; - -let Enumerable = Kernel.defprotocol({ - count: function (collection) {}, - member_qmark__: function (collection, value) {}, - reduce: function (collection, acc, fun) {} -}); - -let Collectable = Kernel.defprotocol({ - into: function (collectable) {} -}); - -let Inspect = Kernel.defprotocol({ - inspect: function (thing, opts) {} -}); - -function __new__() { - return SpecialForms.map({}); -} - -function keys(map) { - return Object.keys(map); -} - -function size(map) { - return keys(map).length; -} - -function to_list$1(map) { - let map_keys = keys(map); - let list = []; - - for (let key of map_keys) { - list.push(SpecialForms.tuple(key, map[key])); - } - - return SpecialForms.list(...list); -} - -function values(map) { - let map_keys = keys(map); - let list = []; - - for (let key of map_keys) { - list.push(map[key]); - } - - return SpecialForms.list(...list); -} - -function from_struct(struct) { - let map = Object.assign({}, struct); - delete map[Symbol.for("__struct__")]; - - return SpecialForms.map(map); -} - -function __delete__(map, key) { - let new_map = Object.assign({}, map); - - delete new_map[key]; - - return SpecialForms.map(new_map); -} - -function equal__qmark__(map1, map2) { - return map1 === map2; -} - -function fetch__emark__(map, key) { - if (key in map) { - return map[key]; - } - - throw new Error("Key not found."); -} - -function fetch(map, key) { - if (key in map) { - return SpecialForms.tuple(SpecialForms.atom("ok"), map[key]); - } - - return SpecialForms.atom("error"); -} - -function has_key__qmark__(map, key) { - return key in map; -} - -function split$1(map, keys) { - let split1 = {}; - let split2 = {}; - - for (let key of Object.keys(map)) { - if (keys.indexOf(key) > -1) { - split1[key] = map[key]; - } else { - split2[key] = map[key]; - } - } - - return SpecialForms.tuple(SpecialForms.map(split1), SpecialForms.map(split2)); -} - -function take(map, keys) { - let split1 = {}; - - for (let key of Object.keys(map)) { - if (keys.indexOf(key) > -1) { - split1[key] = map[key]; - } - } - - return SpecialForms.map(split1); -} - -function drop(map, keys) { - let split1 = {}; - - for (let key of Object.keys(map)) { - if (keys.indexOf(key) === -1) { - split1[key] = map[key]; - } - } - - return SpecialForms.map(split1); -} - -function put_new(map, key, value) { - if (key in map) { - return map; - } - - let new_map = Object.assign({}, map); - new_map[key] = value; - - return SpecialForms.map(new_map); -} - -function put_new_lazy(map, key, fun) { - if (key in map) { - return map; - } - - let new_map = Object.assign({}, map); - new_map[key] = fun(); - - return SpecialForms.map(new_map); -} - -function get_and_update(map, key, fun) { - if (key in map) { - return map; - } - - let new_map = Object.assign({}, map); - new_map[key] = fun(map[key]); - - return SpecialForms.map(new_map); -} - -function pop_lazy(map, key, fun) { - if (!key in map) { - return SpecialForms.tuple(fun(), map); - } - - let new_map = Object.assign({}, map); - let value = fun(new_map[key]); - delete new_map[key]; - - return SpecialForms.tuple(value, new_map); -} - -function pop(map, key, _default = null) { - if (!key in map) { - return SpecialForms.tuple(_default, map); - } - - let new_map = Object.assign({}, map); - let value = new_map[key]; - delete new_map[key]; - - return SpecialForms.tuple(value, new_map); -} - -function get_lazy(map, key, fun) { - if (!key in map) { - return fun(); - } - - return fun(map[key]); -} - -function get(map, key, _default = null) { - if (!key in map) { - return _default; - } - - return map[key]; -} - -function put(map, key, val) { - let new_map = Object({}, map); - new_map[key] = val; - - return SpecialForms.map(new_map); -} - -function update__emark__(map, key, fun) { - if (!key in map) { - throw new Error("Key not found"); - } - - let new_map = Object({}, map); - new_map[key] = fun(map[key]); - - return SpecialForms.map(new_map); -} - -function update(map, key, initial, fun) { - let new_map = Object({}, map); - - if (!key in map) { - new_map[key] = initial; - } else { - new_map[key] = fun(map[key]); - } - - return SpecialForms.map(new_map); -} - -var map = { - new: __new__, - keys, - size, - to_list: to_list$1, - values, - from_struct, - delete: __delete__, - drop, - equal__qmark__, - fetch__emark__, - fetch, - has_key__qmark__, - split: split$1, - take, - put_new, - put_new_lazy, - get_and_update, - pop_lazy, - pop, - get_lazy, - get, - put, - update__emark__, - update -}; - -function __new__$1() { - return SpecialForms.map({ [Symbol.for('__struct__')]: Symbol.for('MapSet'), set: SpecialForms.list() }); -} - -function size$2(map) { - return map.set.length; -} - -function to_list$3(map) { - return map.set; -} - -function __delete__$2(set, term) { - let new_list = List.delete(set.set, term); - - let new_map = Object.assign({}, set); - new_map.set = new_list; - return SpecialForms.map(new_map); -} - -function put$2(set, term) { - if (set.set.indexOf(term) === -1) { - let new_list = List.append(set.set, term); - - let new_map = Object.assign({}, set); - new_map.set = new_list; - return SpecialForms.map(new_map); - } - - return set; -} - -function difference$1(set1, set2) { - let new_map = Object.assign({}, set1); - - for (let val of set1.set) { - if (member__qmark__$1(set2, val)) { - new_map.set = List.delete(new_map.set, val); - } - } - - return SpecialForms.map(new_map); -} - -function intersection$1(set1, set2) { - let new_map = Object.assign({}, set1); - - for (let val of set1.set) { - if (!member__qmark__$1(set2, val)) { - new_map.set = List.delete(new_map.set, val); - } - } - - return SpecialForms.map(new_map); -} - -function union$1(set1, set2) { - let new_map = set1; - - for (let val of set2.set) { - new_map = put$2(new_map, val); - } - - return SpecialForms.map(new_map); -} - -function disjoin__qmark__$1(set1, set2) { - for (let val of set1.set) { - if (member__qmark__$1(set2, val)) { - return false; - } - } - - return true; -} - -function member__qmark__$1(set, value) { - return set.set.indexOf(value) >= 0; -} - -function equal__qmark__$2(set1, set2) { - return set1.set === set2.set; -} - -function subset__qmark__$1(set1, set2) { - for (let val of set1.set) { - if (!member__qmark__$1(set2, val)) { - return false; - } - } - - return true; -} - -var MapSet = { - new: __new__$1, - size: size$2, - to_list: to_list$3, - disjoin__qmark__: disjoin__qmark__$1, - delete: __delete__$2, - subset__qmark__: subset__qmark__$1, - equal__qmark__: equal__qmark__$2, - member__qmark__: member__qmark__$1, - put: put$2, - union: union$1, - intersection: intersection$1, - difference: difference$1 -}; - -function size$1(map) { - return MapSet.size(map); -} - -function to_list$2(map) { - return MapSet.to_list(map); -} - -function __delete__$1(set, term) { - return MapSet.delete(set, term); -} - -function put$1(set, term) { - return MapSet.put(set, term); -} - -function difference(set1, set2) { - return MapSet.difference(set1, set2); -} - -function intersection(set1, set2) { - return MapSet.intersection(set1, set2); -} - -function union(set1, set2) { - return MapSet.union(set1, set2); -} - -function disjoin__qmark__(set1, set2) { - return MapSet.disjoin__qmark__(set1, set2); -} - -function member__qmark__(set, value) { - return MapSet.member__qmark__(set1, set2); -} - -function equal__qmark__$1(set1, set2) { - return MapSet.equal__qmark__(set1, set2); -} - -function subset__qmark__(set1, set2) { - return MapSet.subset__qmark__(set1, set2); -} - -var set = { - size: size$1, - to_list: to_list$2, - disjoin__qmark__, - delete: __delete__$1, - subset__qmark__, - equal__qmark__: equal__qmark__$1, - member__qmark__, - put: put$1, - union, - intersection, - difference -}; - -let VirtualDOM = (function (e) { - return e(); -})(function () { - var define, module, exports; - return (function e(t, n, r) { - function s(o, u) { - if (!n[o]) { - if (!t[o]) { - var a = typeof require == "function" && require; - if (!u && a) return a(o, !0); - if (i) return i(o, !0); - var f = new Error("Cannot find module '" + o + "'"); - throw (f.code = "MODULE_NOT_FOUND", f); - } - var l = n[o] = { - exports: {} - }; - t[o][0].call(l.exports, function (e) { - var n = t[o][1][e]; - return s(n ? n : e); - }, l, l.exports, e, t, n, r); - } - return n[o].exports; - } - var i = typeof require == "function" && require; - for (var o = 0; o < r.length; o++) s(r[o]); - return s; - })({ - 1: [function (require, module, exports) { - - var createElement = require("./vdom/create-element.js"); - - module.exports = createElement; - }, { "./vdom/create-element.js": 15 }], 2: [function (require, module, exports) { - var diff = require("./vtree/diff.js"); - - module.exports = diff; - }, { "./vtree/diff.js": 35 }], 3: [function (require, module, exports) { - var h = require("./virtual-hyperscript/index.js"); - - module.exports = h; - }, { "./virtual-hyperscript/index.js": 22 }], 4: [function (require, module, exports) { - var diff = require("./diff.js"); - var patch = require("./patch.js"); - var h = require("./h.js"); - var create = require("./create-element.js"); - var VNode = require("./vnode/vnode.js"); - var VText = require("./vnode/vtext.js"); - - module.exports = { - diff: diff, - patch: patch, - h: h, - create: create, - VNode: VNode, - VText: VText - }; - }, { "./create-element.js": 1, "./diff.js": 2, "./h.js": 3, "./patch.js": 13, "./vnode/vnode.js": 31, "./vnode/vtext.js": 33 }], 5: [function (require, module, exports) { - /*! - * Cross-Browser Split 1.1.1 - * Copyright 2007-2012 Steven Levithan - * Available under the MIT License - * ECMAScript compliant, uniform cross-browser split method - */ - - /** - * Splits a string into an array of strings using a regex or string separator. Matches of the - * separator are not included in the result array. However, if `separator` is a regex that contains - * capturing groups, backreferences are spliced into the result each time `separator` is matched. - * Fixes browser bugs compared to the native `String.prototype.split` and can be used reliably - * cross-browser. - * @param {String} str String to split. - * @param {RegExp|String} separator Regex or string to use for separating the string. - * @param {Number} [limit] Maximum number of items to include in the result array. - * @returns {Array} Array of substrings. - * @example - * - * // Basic use - * split('a b c d', ' '); - * // -> ['a', 'b', 'c', 'd'] - * - * // With limit - * split('a b c d', ' ', 2); - * // -> ['a', 'b'] - * - * // Backreferences in result array - * split('..word1 word2..', /([a-z]+)(\d+)/i); - * // -> ['..', 'word', '1', ' ', 'word', '2', '..'] - */ - module.exports = (function split(undef) { - - var nativeSplit = String.prototype.split, - compliantExecNpcg = /()??/.exec("")[1] === undef, - - // NPCG: nonparticipating capturing group - self; - - self = function (str, separator, limit) { - // If `separator` is not a regex, use `nativeSplit` - if (Object.prototype.toString.call(separator) !== "[object RegExp]") { - return nativeSplit.call(str, separator, limit); - } - var output = [], - flags = (separator.ignoreCase ? "i" : "") + (separator.multiline ? "m" : "") + (separator.extended ? "x" : "") + (separator.sticky ? "y" : ""), - - // Firefox 3+ - lastLastIndex = 0, - - // Make `global` and avoid `lastIndex` issues by working with a copy - separator = new RegExp(separator.source, flags + "g"), - separator2, - match, - lastIndex, - lastLength; - str += ""; // Type-convert - if (!compliantExecNpcg) { - // Doesn't need flags gy, but they don't hurt - separator2 = new RegExp("^" + separator.source + "$(?!\\s)", flags); - } - /* Values for `limit`, per the spec: - * If undefined: 4294967295 // Math.pow(2, 32) - 1 - * If 0, Infinity, or NaN: 0 - * If positive number: limit = Math.floor(limit); if (limit > 4294967295) limit -= 4294967296; - * If negative number: 4294967296 - Math.floor(Math.abs(limit)) - * If other: Type-convert, then use the above rules - */ - limit = limit === undef ? -1 >>> 0 : // Math.pow(2, 32) - 1 - limit >>> 0; // ToUint32(limit) - while (match = separator.exec(str)) { - // `separator.lastIndex` is not reliable cross-browser - lastIndex = match.index + match[0].length; - if (lastIndex > lastLastIndex) { - output.push(str.slice(lastLastIndex, match.index)); - // Fix browsers whose `exec` methods don't consistently return `undefined` for - // nonparticipating capturing groups - if (!compliantExecNpcg && match.length > 1) { - match[0].replace(separator2, function () { - for (var i = 1; i < arguments.length - 2; i++) { - if (arguments[i] === undef) { - match[i] = undef; - } - } - }); - } - if (match.length > 1 && match.index < str.length) { - Array.prototype.push.apply(output, match.slice(1)); - } - lastLength = match[0].length; - lastLastIndex = lastIndex; - if (output.length >= limit) { - break; - } - } - if (separator.lastIndex === match.index) { - separator.lastIndex++; // Avoid an infinite loop - } - } - if (lastLastIndex === str.length) { - if (lastLength || !separator.test("")) { - output.push(""); - } - } else { - output.push(str.slice(lastLastIndex)); - } - return output.length > limit ? output.slice(0, limit) : output; - }; - - return self; - })(); - }, {}], 6: [function (require, module, exports) {}, {}], 7: [function (require, module, exports) { - "use strict"; - - var OneVersionConstraint = require("individual/one-version"); - - var MY_VERSION = "7"; - OneVersionConstraint("ev-store", MY_VERSION); - - var hashKey = "__EV_STORE_KEY@" + MY_VERSION; - - module.exports = EvStore; - - function EvStore(elem) { - var hash = elem[hashKey]; - - if (!hash) { - hash = elem[hashKey] = {}; - } - - return hash; - } - }, { "individual/one-version": 9 }], 8: [function (require, module, exports) { - (function (global) { - "use strict"; - - /*global window, global*/ - - var root = typeof window !== "undefined" ? window : typeof global !== "undefined" ? global : {}; - - module.exports = Individual; - - function Individual(key, value) { - if (key in root) { - return root[key]; - } - - root[key] = value; - - return value; - } - }).call(this, typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}); - }, {}], 9: [function (require, module, exports) { - "use strict"; - - var Individual = require("./index.js"); - - module.exports = OneVersion; - - function OneVersion(moduleName, version, defaultValue) { - var key = "__INDIVIDUAL_ONE_VERSION_" + moduleName; - var enforceKey = key + "_ENFORCE_SINGLETON"; - - var versionValue = Individual(enforceKey, version); - - if (versionValue !== version) { - throw new Error("Can only have one copy of " + moduleName + ".\n" + "You already have version " + versionValue + " installed.\n" + "This means you cannot install version " + version); - } - - return Individual(key, defaultValue); - } - }, { "./index.js": 8 }], 10: [function (require, module, exports) { - (function (global) { - var topLevel = typeof global !== "undefined" ? global : typeof window !== "undefined" ? window : {}; - var minDoc = require("min-document"); - - if (typeof document !== "undefined") { - module.exports = document; - } else { - var doccy = topLevel["__GLOBAL_DOCUMENT_CACHE@4"]; - - if (!doccy) { - doccy = topLevel["__GLOBAL_DOCUMENT_CACHE@4"] = minDoc; - } - - module.exports = doccy; - } - }).call(this, typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}); - }, { "min-document": 6 }], 11: [function (require, module, exports) { - "use strict"; - - module.exports = function isObject(x) { - return typeof x === "object" && x !== null; - }; - }, {}], 12: [function (require, module, exports) { - var nativeIsArray = Array.isArray; - var toString = Object.prototype.toString; - - module.exports = nativeIsArray || isArray; - - function isArray(obj) { - return toString.call(obj) === "[object Array]"; - } - }, {}], 13: [function (require, module, exports) { - var patch = require("./vdom/patch.js"); - - module.exports = patch; - }, { "./vdom/patch.js": 18 }], 14: [function (require, module, exports) { - var isObject = require("is-object"); - var isHook = require("../vnode/is-vhook.js"); - - module.exports = applyProperties; - - function applyProperties(node, props, previous) { - for (var propName in props) { - var propValue = props[propName]; - - if (propValue === undefined) { - removeProperty(node, propName, propValue, previous); - } else if (isHook(propValue)) { - removeProperty(node, propName, propValue, previous); - if (propValue.hook) { - propValue.hook(node, propName, previous ? previous[propName] : undefined); - } - } else { - if (isObject(propValue)) { - patchObject(node, props, previous, propName, propValue); - } else { - node[propName] = propValue; - } - } - } - } - - function removeProperty(node, propName, propValue, previous) { - if (previous) { - var previousValue = previous[propName]; - - if (!isHook(previousValue)) { - if (propName === "attributes") { - for (var attrName in previousValue) { - node.removeAttribute(attrName); - } - } else if (propName === "style") { - for (var i in previousValue) { - node.style[i] = ""; - } - } else if (typeof previousValue === "string") { - node[propName] = ""; - } else { - node[propName] = null; - } - } else if (previousValue.unhook) { - previousValue.unhook(node, propName, propValue); - } - } - } - - function patchObject(node, props, previous, propName, propValue) { - var previousValue = previous ? previous[propName] : undefined; - - // Set attributes - if (propName === "attributes") { - for (var attrName in propValue) { - var attrValue = propValue[attrName]; - - if (attrValue === undefined) { - node.removeAttribute(attrName); - } else { - node.setAttribute(attrName, attrValue); - } - } - - return; - } - - if (previousValue && isObject(previousValue) && getPrototype(previousValue) !== getPrototype(propValue)) { - node[propName] = propValue; - return; - } - - if (!isObject(node[propName])) { - node[propName] = {}; - } - - var replacer = propName === "style" ? "" : undefined; - - for (var k in propValue) { - var value = propValue[k]; - node[propName][k] = value === undefined ? replacer : value; - } - } - - function getPrototype(value) { - if (Object.getPrototypeOf) { - return Object.getPrototypeOf(value); - } else if (value.__proto__) { - return value.__proto__; - } else if (value.constructor) { - return value.constructor.prototype; - } - } - }, { "../vnode/is-vhook.js": 26, "is-object": 11 }], 15: [function (require, module, exports) { - var document = require("global/document"); - - var applyProperties = require("./apply-properties"); - - var isVNode = require("../vnode/is-vnode.js"); - var isVText = require("../vnode/is-vtext.js"); - var isWidget = require("../vnode/is-widget.js"); - var handleThunk = require("../vnode/handle-thunk.js"); - - module.exports = createElement; - - function createElement(vnode, opts) { - var doc = opts ? opts.document || document : document; - var warn = opts ? opts.warn : null; - - vnode = handleThunk(vnode).a; - - if (isWidget(vnode)) { - return vnode.init(); - } else if (isVText(vnode)) { - return doc.createTextNode(vnode.text); - } else if (!isVNode(vnode)) { - if (warn) { - warn("Item is not a valid virtual dom node", vnode); - } - return null; - } - - var node = vnode.namespace === null ? doc.createElement(vnode.tagName) : doc.createElementNS(vnode.namespace, vnode.tagName); - - var props = vnode.properties; - applyProperties(node, props); - - var children = vnode.children; - - for (var i = 0; i < children.length; i++) { - var childNode = createElement(children[i], opts); - if (childNode) { - node.appendChild(childNode); - } - } - - return node; - } - }, { "../vnode/handle-thunk.js": 24, "../vnode/is-vnode.js": 27, "../vnode/is-vtext.js": 28, "../vnode/is-widget.js": 29, "./apply-properties": 14, "global/document": 10 }], 16: [function (require, module, exports) { - // Maps a virtual DOM tree onto a real DOM tree in an efficient manner. - // We don't want to read all of the DOM nodes in the tree so we use - // the in-order tree indexing to eliminate recursion down certain branches. - // We only recurse into a DOM node if we know that it contains a child of - // interest. - - var noChild = {}; - - module.exports = domIndex; - - function domIndex(rootNode, tree, indices, nodes) { - if (!indices || indices.length === 0) { - return {}; - } else { - indices.sort(ascending); - return recurse(rootNode, tree, indices, nodes, 0); - } - } - - function recurse(rootNode, tree, indices, nodes, rootIndex) { - nodes = nodes || {}; - - if (rootNode) { - if (indexInRange(indices, rootIndex, rootIndex)) { - nodes[rootIndex] = rootNode; - } - - var vChildren = tree.children; - - if (vChildren) { - - var childNodes = rootNode.childNodes; - - for (var i = 0; i < tree.children.length; i++) { - rootIndex += 1; - - var vChild = vChildren[i] || noChild; - var nextIndex = rootIndex + (vChild.count || 0); - - // skip recursion down the tree if there are no nodes down here - if (indexInRange(indices, rootIndex, nextIndex)) { - recurse(childNodes[i], vChild, indices, nodes, rootIndex); - } - - rootIndex = nextIndex; - } - } - } - - return nodes; - } - - // Binary search for an index in the interval [left, right] - function indexInRange(indices, left, right) { - if (indices.length === 0) { - return false; - } - - var minIndex = 0; - var maxIndex = indices.length - 1; - var currentIndex; - var currentItem; - - while (minIndex <= maxIndex) { - currentIndex = (maxIndex + minIndex) / 2 >> 0; - currentItem = indices[currentIndex]; - - if (minIndex === maxIndex) { - return currentItem >= left && currentItem <= right; - } else if (currentItem < left) { - minIndex = currentIndex + 1; - } else if (currentItem > right) { - maxIndex = currentIndex - 1; - } else { - return true; - } - } - - return false; - } - - function ascending(a, b) { - return a > b ? 1 : -1; - } - }, {}], 17: [function (require, module, exports) { - var applyProperties = require("./apply-properties"); - - var isWidget = require("../vnode/is-widget.js"); - var VPatch = require("../vnode/vpatch.js"); - - var updateWidget = require("./update-widget"); - - module.exports = applyPatch; - - function applyPatch(vpatch, domNode, renderOptions) { - var type = vpatch.type; - var vNode = vpatch.vNode; - var patch = vpatch.patch; - - switch (type) { - case VPatch.REMOVE: - return removeNode(domNode, vNode); - case VPatch.INSERT: - return insertNode(domNode, patch, renderOptions); - case VPatch.VTEXT: - return stringPatch(domNode, vNode, patch, renderOptions); - case VPatch.WIDGET: - return widgetPatch(domNode, vNode, patch, renderOptions); - case VPatch.VNODE: - return vNodePatch(domNode, vNode, patch, renderOptions); - case VPatch.ORDER: - reorderChildren(domNode, patch); - return domNode; - case VPatch.PROPS: - applyProperties(domNode, patch, vNode.properties); - return domNode; - case VPatch.THUNK: - return replaceRoot(domNode, renderOptions.patch(domNode, patch, renderOptions)); - default: - return domNode; - } - } - - function removeNode(domNode, vNode) { - var parentNode = domNode.parentNode; - - if (parentNode) { - parentNode.removeChild(domNode); - } - - destroyWidget(domNode, vNode); - - return null; - } - - function insertNode(parentNode, vNode, renderOptions) { - var newNode = renderOptions.render(vNode, renderOptions); - - if (parentNode) { - parentNode.appendChild(newNode); - } - - return parentNode; - } - - function stringPatch(domNode, leftVNode, vText, renderOptions) { - var newNode; - - if (domNode.nodeType === 3) { - domNode.replaceData(0, domNode.length, vText.text); - newNode = domNode; - } else { - var parentNode = domNode.parentNode; - newNode = renderOptions.render(vText, renderOptions); - - if (parentNode && newNode !== domNode) { - parentNode.replaceChild(newNode, domNode); - } - } - - return newNode; - } - - function widgetPatch(domNode, leftVNode, widget, renderOptions) { - var updating = updateWidget(leftVNode, widget); - var newNode; - - if (updating) { - newNode = widget.update(leftVNode, domNode) || domNode; - } else { - newNode = renderOptions.render(widget, renderOptions); - } - - var parentNode = domNode.parentNode; - - if (parentNode && newNode !== domNode) { - parentNode.replaceChild(newNode, domNode); - } - - if (!updating) { - destroyWidget(domNode, leftVNode); - } - - return newNode; - } - - function vNodePatch(domNode, leftVNode, vNode, renderOptions) { - var parentNode = domNode.parentNode; - var newNode = renderOptions.render(vNode, renderOptions); - - if (parentNode && newNode !== domNode) { - parentNode.replaceChild(newNode, domNode); - } - - return newNode; - } - - function destroyWidget(domNode, w) { - if (typeof w.destroy === "function" && isWidget(w)) { - w.destroy(domNode); - } - } - - function reorderChildren(domNode, moves) { - var childNodes = domNode.childNodes; - var keyMap = {}; - var node; - var remove; - var insert; - - for (var i = 0; i < moves.removes.length; i++) { - remove = moves.removes[i]; - node = childNodes[remove.from]; - if (remove.key) { - keyMap[remove.key] = node; - } - domNode.removeChild(node); - } - - var length = childNodes.length; - for (var j = 0; j < moves.inserts.length; j++) { - insert = moves.inserts[j]; - node = keyMap[insert.key]; - // this is the weirdest bug i've ever seen in webkit - domNode.insertBefore(node, insert.to >= length++ ? null : childNodes[insert.to]); - } - } - - function replaceRoot(oldRoot, newRoot) { - if (oldRoot && newRoot && oldRoot !== newRoot && oldRoot.parentNode) { - oldRoot.parentNode.replaceChild(newRoot, oldRoot); - } - - return newRoot; - } - }, { "../vnode/is-widget.js": 29, "../vnode/vpatch.js": 32, "./apply-properties": 14, "./update-widget": 19 }], 18: [function (require, module, exports) { - var document = require("global/document"); - var isArray = require("x-is-array"); - - var render = require("./create-element"); - var domIndex = require("./dom-index"); - var patchOp = require("./patch-op"); - module.exports = patch; - - function patch(rootNode, patches, renderOptions) { - renderOptions = renderOptions || {}; - renderOptions.patch = renderOptions.patch && renderOptions.patch !== patch ? renderOptions.patch : patchRecursive; - renderOptions.render = renderOptions.render || render; - - return renderOptions.patch(rootNode, patches, renderOptions); - } - - function patchRecursive(rootNode, patches, renderOptions) { - var indices = patchIndices(patches); - - if (indices.length === 0) { - return rootNode; - } - - var index = domIndex(rootNode, patches.a, indices); - var ownerDocument = rootNode.ownerDocument; - - if (!renderOptions.document && ownerDocument !== document) { - renderOptions.document = ownerDocument; - } - - for (var i = 0; i < indices.length; i++) { - var nodeIndex = indices[i]; - rootNode = applyPatch(rootNode, index[nodeIndex], patches[nodeIndex], renderOptions); - } - - return rootNode; - } - - function applyPatch(rootNode, domNode, patchList, renderOptions) { - if (!domNode) { - return rootNode; - } - - var newNode; - - if (isArray(patchList)) { - for (var i = 0; i < patchList.length; i++) { - newNode = patchOp(patchList[i], domNode, renderOptions); - - if (domNode === rootNode) { - rootNode = newNode; - } - } - } else { - newNode = patchOp(patchList, domNode, renderOptions); - - if (domNode === rootNode) { - rootNode = newNode; - } - } - - return rootNode; - } - - function patchIndices(patches) { - var indices = []; - - for (var key in patches) { - if (key !== "a") { - indices.push(Number(key)); - } - } - - return indices; - } - }, { "./create-element": 15, "./dom-index": 16, "./patch-op": 17, "global/document": 10, "x-is-array": 12 }], 19: [function (require, module, exports) { - var isWidget = require("../vnode/is-widget.js"); - - module.exports = updateWidget; - - function updateWidget(a, b) { - if (isWidget(a) && isWidget(b)) { - if ("name" in a && "name" in b) { - return a.id === b.id; - } else { - return a.init === b.init; - } - } - - return false; - } - }, { "../vnode/is-widget.js": 29 }], 20: [function (require, module, exports) { - "use strict"; - - var EvStore = require("ev-store"); - - module.exports = EvHook; - - function EvHook(value) { - if (!(this instanceof EvHook)) { - return new EvHook(value); - } - - this.value = value; - } - - EvHook.prototype.hook = function (node, propertyName) { - var es = EvStore(node); - var propName = propertyName.substr(3); - - es[propName] = this.value; - }; - - EvHook.prototype.unhook = function (node, propertyName) { - var es = EvStore(node); - var propName = propertyName.substr(3); - - es[propName] = undefined; - }; - }, { "ev-store": 7 }], 21: [function (require, module, exports) { - "use strict"; - - module.exports = SoftSetHook; - - function SoftSetHook(value) { - if (!(this instanceof SoftSetHook)) { - return new SoftSetHook(value); - } - - this.value = value; - } - - SoftSetHook.prototype.hook = function (node, propertyName) { - if (node[propertyName] !== this.value) { - node[propertyName] = this.value; - } - }; - }, {}], 22: [function (require, module, exports) { - "use strict"; - - var isArray = require("x-is-array"); - - var VNode = require("../vnode/vnode.js"); - var VText = require("../vnode/vtext.js"); - var isVNode = require("../vnode/is-vnode"); - var isVText = require("../vnode/is-vtext"); - var isWidget = require("../vnode/is-widget"); - var isHook = require("../vnode/is-vhook"); - var isVThunk = require("../vnode/is-thunk"); - - var parseTag = require("./parse-tag.js"); - var softSetHook = require("./hooks/soft-set-hook.js"); - var evHook = require("./hooks/ev-hook.js"); - - module.exports = h; - - function h(tagName, properties, children) { - var childNodes = []; - var tag, props, key, namespace; - - if (!children && isChildren(properties)) { - children = properties; - props = {}; - } - - props = props || properties || {}; - tag = parseTag(tagName, props); - - // support keys - if (props.hasOwnProperty("key")) { - key = props.key; - props.key = undefined; - } - - // support namespace - if (props.hasOwnProperty("namespace")) { - namespace = props.namespace; - props.namespace = undefined; - } - - // fix cursor bug - if (tag === "INPUT" && !namespace && props.hasOwnProperty("value") && props.value !== undefined && !isHook(props.value)) { - props.value = softSetHook(props.value); - } - - transformProperties(props); - - if (children !== undefined && children !== null) { - addChild(children, childNodes, tag, props); - } - - return new VNode(tag, props, childNodes, key, namespace); - } - - function addChild(c, childNodes, tag, props) { - if (typeof c === "string") { - childNodes.push(new VText(c)); - } else if (typeof c === "number") { - childNodes.push(new VText(String(c))); - } else if (isChild(c)) { - childNodes.push(c); - } else if (isArray(c)) { - for (var i = 0; i < c.length; i++) { - addChild(c[i], childNodes, tag, props); - } - } else if (c === null || c === undefined) { - return; - } else { - throw UnexpectedVirtualElement({ - foreignObject: c, - parentVnode: { - tagName: tag, - properties: props - } - }); - } - } - - function transformProperties(props) { - for (var propName in props) { - if (props.hasOwnProperty(propName)) { - var value = props[propName]; - - if (isHook(value)) { - continue; - } - - if (propName.substr(0, 3) === "ev-") { - // add ev-foo support - props[propName] = evHook(value); - } - } - } - } - - function isChild(x) { - return isVNode(x) || isVText(x) || isWidget(x) || isVThunk(x); - } - - function isChildren(x) { - return typeof x === "string" || isArray(x) || isChild(x); - } - - function UnexpectedVirtualElement(data) { - var err = new Error(); - - err.type = "virtual-hyperscript.unexpected.virtual-element"; - err.message = "Unexpected virtual child passed to h().\n" + "Expected a VNode / Vthunk / VWidget / string but:\n" + "got:\n" + errorString(data.foreignObject) + ".\n" + "The parent vnode is:\n" + errorString(data.parentVnode); - "\n" + "Suggested fix: change your `h(..., [ ... ])` callsite."; - err.foreignObject = data.foreignObject; - err.parentVnode = data.parentVnode; - - return err; - } - - function errorString(obj) { - try { - return JSON.stringify(obj, null, " "); - } catch (e) { - return String(obj); - } - } - }, { "../vnode/is-thunk": 25, "../vnode/is-vhook": 26, "../vnode/is-vnode": 27, "../vnode/is-vtext": 28, "../vnode/is-widget": 29, "../vnode/vnode.js": 31, "../vnode/vtext.js": 33, "./hooks/ev-hook.js": 20, "./hooks/soft-set-hook.js": 21, "./parse-tag.js": 23, "x-is-array": 12 }], 23: [function (require, module, exports) { - "use strict"; - - var split = require("browser-split"); - - var classIdSplit = /([\.#]?[a-zA-Z0-9\u007F-\uFFFF_:-]+)/; - var notClassId = /^\.|#/; - - module.exports = parseTag; - - function parseTag(tag, props) { - if (!tag) { - return "DIV"; - } - - var noId = !props.hasOwnProperty("id"); - - var tagParts = split(tag, classIdSplit); - var tagName = null; - - if (notClassId.test(tagParts[1])) { - tagName = "DIV"; - } - - var classes, part, type, i; - - for (i = 0; i < tagParts.length; i++) { - part = tagParts[i]; - - if (!part) { - continue; - } - - type = part.charAt(0); - - if (!tagName) { - tagName = part; - } else if (type === ".") { - classes = classes || []; - classes.push(part.substring(1, part.length)); - } else if (type === "#" && noId) { - props.id = part.substring(1, part.length); - } - } - - if (classes) { - if (props.className) { - classes.push(props.className); - } - - props.className = classes.join(" "); - } - - return props.namespace ? tagName : tagName.toUpperCase(); - } - }, { "browser-split": 5 }], 24: [function (require, module, exports) { - var isVNode = require("./is-vnode"); - var isVText = require("./is-vtext"); - var isWidget = require("./is-widget"); - var isThunk = require("./is-thunk"); - - module.exports = handleThunk; - - function handleThunk(a, b) { - var renderedA = a; - var renderedB = b; - - if (isThunk(b)) { - renderedB = renderThunk(b, a); - } - - if (isThunk(a)) { - renderedA = renderThunk(a, null); - } - - return { - a: renderedA, - b: renderedB - }; - } - - function renderThunk(thunk, previous) { - var renderedThunk = thunk.vnode; - - if (!renderedThunk) { - renderedThunk = thunk.vnode = thunk.render(previous); - } - - if (!(isVNode(renderedThunk) || isVText(renderedThunk) || isWidget(renderedThunk))) { - throw new Error("thunk did not return a valid node"); - } - - return renderedThunk; - } - }, { "./is-thunk": 25, "./is-vnode": 27, "./is-vtext": 28, "./is-widget": 29 }], 25: [function (require, module, exports) { - module.exports = isThunk; - - function isThunk(t) { - return t && t.type === "Thunk"; - } - }, {}], 26: [function (require, module, exports) { - module.exports = isHook; - - function isHook(hook) { - return hook && (typeof hook.hook === "function" && !hook.hasOwnProperty("hook") || typeof hook.unhook === "function" && !hook.hasOwnProperty("unhook")); - } - }, {}], 27: [function (require, module, exports) { - var version = require("./version"); - - module.exports = isVirtualNode; - - function isVirtualNode(x) { - return x && x.type === "VirtualNode" && x.version === version; - } - }, { "./version": 30 }], 28: [function (require, module, exports) { - var version = require("./version"); - - module.exports = isVirtualText; - - function isVirtualText(x) { - return x && x.type === "VirtualText" && x.version === version; - } - }, { "./version": 30 }], 29: [function (require, module, exports) { - module.exports = isWidget; - - function isWidget(w) { - return w && w.type === "Widget"; - } - }, {}], 30: [function (require, module, exports) { - module.exports = "2"; - }, {}], 31: [function (require, module, exports) { - var version = require("./version"); - var isVNode = require("./is-vnode"); - var isWidget = require("./is-widget"); - var isThunk = require("./is-thunk"); - var isVHook = require("./is-vhook"); - - module.exports = VirtualNode; - - var noProperties = {}; - var noChildren = []; - - function VirtualNode(tagName, properties, children, key, namespace) { - this.tagName = tagName; - this.properties = properties || noProperties; - this.children = children || noChildren; - this.key = key != null ? String(key) : undefined; - this.namespace = typeof namespace === "string" ? namespace : null; - - var count = children && children.length || 0; - var descendants = 0; - var hasWidgets = false; - var hasThunks = false; - var descendantHooks = false; - var hooks; - - for (var propName in properties) { - if (properties.hasOwnProperty(propName)) { - var property = properties[propName]; - if (isVHook(property) && property.unhook) { - if (!hooks) { - hooks = {}; - } - - hooks[propName] = property; - } - } - } - - for (var i = 0; i < count; i++) { - var child = children[i]; - if (isVNode(child)) { - descendants += child.count || 0; - - if (!hasWidgets && child.hasWidgets) { - hasWidgets = true; - } - - if (!hasThunks && child.hasThunks) { - hasThunks = true; - } - - if (!descendantHooks && (child.hooks || child.descendantHooks)) { - descendantHooks = true; - } - } else if (!hasWidgets && isWidget(child)) { - if (typeof child.destroy === "function") { - hasWidgets = true; - } - } else if (!hasThunks && isThunk(child)) { - hasThunks = true; - } - } - - this.count = count + descendants; - this.hasWidgets = hasWidgets; - this.hasThunks = hasThunks; - this.hooks = hooks; - this.descendantHooks = descendantHooks; - } - - VirtualNode.prototype.version = version; - VirtualNode.prototype.type = "VirtualNode"; - }, { "./is-thunk": 25, "./is-vhook": 26, "./is-vnode": 27, "./is-widget": 29, "./version": 30 }], 32: [function (require, module, exports) { - var version = require("./version"); - - VirtualPatch.NONE = 0; - VirtualPatch.VTEXT = 1; - VirtualPatch.VNODE = 2; - VirtualPatch.WIDGET = 3; - VirtualPatch.PROPS = 4; - VirtualPatch.ORDER = 5; - VirtualPatch.INSERT = 6; - VirtualPatch.REMOVE = 7; - VirtualPatch.THUNK = 8; - - module.exports = VirtualPatch; - - function VirtualPatch(type, vNode, patch) { - this.type = Number(type); - this.vNode = vNode; - this.patch = patch; - } - - VirtualPatch.prototype.version = version; - VirtualPatch.prototype.type = "VirtualPatch"; - }, { "./version": 30 }], 33: [function (require, module, exports) { - var version = require("./version"); - - module.exports = VirtualText; - - function VirtualText(text) { - this.text = String(text); - } - - VirtualText.prototype.version = version; - VirtualText.prototype.type = "VirtualText"; - }, { "./version": 30 }], 34: [function (require, module, exports) { - var isObject = require("is-object"); - var isHook = require("../vnode/is-vhook"); - - module.exports = diffProps; - - function diffProps(a, b) { - var diff; - - for (var aKey in a) { - if (!(aKey in b)) { - diff = diff || {}; - diff[aKey] = undefined; - } - - var aValue = a[aKey]; - var bValue = b[aKey]; - - if (aValue === bValue) { - continue; - } else if (isObject(aValue) && isObject(bValue)) { - if (getPrototype(bValue) !== getPrototype(aValue)) { - diff = diff || {}; - diff[aKey] = bValue; - } else if (isHook(bValue)) { - diff = diff || {}; - diff[aKey] = bValue; - } else { - var objectDiff = diffProps(aValue, bValue); - if (objectDiff) { - diff = diff || {}; - diff[aKey] = objectDiff; - } - } - } else { - diff = diff || {}; - diff[aKey] = bValue; - } - } - - for (var bKey in b) { - if (!(bKey in a)) { - diff = diff || {}; - diff[bKey] = b[bKey]; - } - } - - return diff; - } - - function getPrototype(value) { - if (Object.getPrototypeOf) { - return Object.getPrototypeOf(value); - } else if (value.__proto__) { - return value.__proto__; - } else if (value.constructor) { - return value.constructor.prototype; - } - } - }, { "../vnode/is-vhook": 26, "is-object": 11 }], 35: [function (require, module, exports) { - var isArray = require("x-is-array"); - - var VPatch = require("../vnode/vpatch"); - var isVNode = require("../vnode/is-vnode"); - var isVText = require("../vnode/is-vtext"); - var isWidget = require("../vnode/is-widget"); - var isThunk = require("../vnode/is-thunk"); - var handleThunk = require("../vnode/handle-thunk"); - - var diffProps = require("./diff-props"); - - module.exports = diff; - - function diff(a, b) { - var patch = { a: a }; - walk(a, b, patch, 0); - return patch; - } - - function walk(a, b, patch, index) { - if (a === b) { - return; - } - - var apply = patch[index]; - var applyClear = false; - - if (isThunk(a) || isThunk(b)) { - thunks(a, b, patch, index); - } else if (b == null) { - - // If a is a widget we will add a remove patch for it - // Otherwise any child widgets/hooks must be destroyed. - // This prevents adding two remove patches for a widget. - if (!isWidget(a)) { - clearState(a, patch, index); - apply = patch[index]; - } - - apply = appendPatch(apply, new VPatch(VPatch.REMOVE, a, b)); - } else if (isVNode(b)) { - if (isVNode(a)) { - if (a.tagName === b.tagName && a.namespace === b.namespace && a.key === b.key) { - var propsPatch = diffProps(a.properties, b.properties); - if (propsPatch) { - apply = appendPatch(apply, new VPatch(VPatch.PROPS, a, propsPatch)); - } - apply = diffChildren(a, b, patch, apply, index); - } else { - apply = appendPatch(apply, new VPatch(VPatch.VNODE, a, b)); - applyClear = true; - } - } else { - apply = appendPatch(apply, new VPatch(VPatch.VNODE, a, b)); - applyClear = true; - } - } else if (isVText(b)) { - if (!isVText(a)) { - apply = appendPatch(apply, new VPatch(VPatch.VTEXT, a, b)); - applyClear = true; - } else if (a.text !== b.text) { - apply = appendPatch(apply, new VPatch(VPatch.VTEXT, a, b)); - } - } else if (isWidget(b)) { - if (!isWidget(a)) { - applyClear = true; - } - - apply = appendPatch(apply, new VPatch(VPatch.WIDGET, a, b)); - } - - if (apply) { - patch[index] = apply; - } - - if (applyClear) { - clearState(a, patch, index); - } - } - - function diffChildren(a, b, patch, apply, index) { - var aChildren = a.children; - var orderedSet = reorder(aChildren, b.children); - var bChildren = orderedSet.children; - - var aLen = aChildren.length; - var bLen = bChildren.length; - var len = aLen > bLen ? aLen : bLen; - - for (var i = 0; i < len; i++) { - var leftNode = aChildren[i]; - var rightNode = bChildren[i]; - index += 1; - - if (!leftNode) { - if (rightNode) { - // Excess nodes in b need to be added - apply = appendPatch(apply, new VPatch(VPatch.INSERT, null, rightNode)); - } - } else { - walk(leftNode, rightNode, patch, index); - } - - if (isVNode(leftNode) && leftNode.count) { - index += leftNode.count; - } - } - - if (orderedSet.moves) { - // Reorder nodes last - apply = appendPatch(apply, new VPatch(VPatch.ORDER, a, orderedSet.moves)); - } - - return apply; - } - - function clearState(vNode, patch, index) { - // TODO: Make this a single walk, not two - unhook(vNode, patch, index); - destroyWidgets(vNode, patch, index); - } - - // Patch records for all destroyed widgets must be added because we need - // a DOM node reference for the destroy function - function destroyWidgets(vNode, patch, index) { - if (isWidget(vNode)) { - if (typeof vNode.destroy === "function") { - patch[index] = appendPatch(patch[index], new VPatch(VPatch.REMOVE, vNode, null)); - } - } else if (isVNode(vNode) && (vNode.hasWidgets || vNode.hasThunks)) { - var children = vNode.children; - var len = children.length; - for (var i = 0; i < len; i++) { - var child = children[i]; - index += 1; - - destroyWidgets(child, patch, index); - - if (isVNode(child) && child.count) { - index += child.count; - } - } - } else if (isThunk(vNode)) { - thunks(vNode, null, patch, index); - } - } - - // Create a sub-patch for thunks - function thunks(a, b, patch, index) { - var nodes = handleThunk(a, b); - var thunkPatch = diff(nodes.a, nodes.b); - if (hasPatches(thunkPatch)) { - patch[index] = new VPatch(VPatch.THUNK, null, thunkPatch); - } - } - - function hasPatches(patch) { - for (var index in patch) { - if (index !== "a") { - return true; - } - } - - return false; - } - - // Execute hooks when two nodes are identical - function unhook(vNode, patch, index) { - if (isVNode(vNode)) { - if (vNode.hooks) { - patch[index] = appendPatch(patch[index], new VPatch(VPatch.PROPS, vNode, undefinedKeys(vNode.hooks))); - } - - if (vNode.descendantHooks || vNode.hasThunks) { - var children = vNode.children; - var len = children.length; - for (var i = 0; i < len; i++) { - var child = children[i]; - index += 1; - - unhook(child, patch, index); - - if (isVNode(child) && child.count) { - index += child.count; - } - } - } - } else if (isThunk(vNode)) { - thunks(vNode, null, patch, index); - } - } - - function undefinedKeys(obj) { - var result = {}; - - for (var key in obj) { - result[key] = undefined; - } - - return result; - } - - // List diff, naive left to right reordering - function reorder(aChildren, bChildren) { - // O(M) time, O(M) memory - var bChildIndex = keyIndex(bChildren); - var bKeys = bChildIndex.keys; - var bFree = bChildIndex.free; - - if (bFree.length === bChildren.length) { - return { - children: bChildren, - moves: null - }; - } - - // O(N) time, O(N) memory - var aChildIndex = keyIndex(aChildren); - var aKeys = aChildIndex.keys; - var aFree = aChildIndex.free; - - if (aFree.length === aChildren.length) { - return { - children: bChildren, - moves: null - }; - } - - // O(MAX(N, M)) memory - var newChildren = []; - - var freeIndex = 0; - var freeCount = bFree.length; - var deletedItems = 0; - - // Iterate through a and match a node in b - // O(N) time, - for (var i = 0; i < aChildren.length; i++) { - var aItem = aChildren[i]; - var itemIndex; - - if (aItem.key) { - if (bKeys.hasOwnProperty(aItem.key)) { - // Match up the old keys - itemIndex = bKeys[aItem.key]; - newChildren.push(bChildren[itemIndex]); - } else { - // Remove old keyed items - itemIndex = i - deletedItems++; - newChildren.push(null); - } - } else { - // Match the item in a with the next free item in b - if (freeIndex < freeCount) { - itemIndex = bFree[freeIndex++]; - newChildren.push(bChildren[itemIndex]); - } else { - // There are no free items in b to match with - // the free items in a, so the extra free nodes - // are deleted. - itemIndex = i - deletedItems++; - newChildren.push(null); - } - } - } - - var lastFreeIndex = freeIndex >= bFree.length ? bChildren.length : bFree[freeIndex]; - - // Iterate through b and append any new keys - // O(M) time - for (var j = 0; j < bChildren.length; j++) { - var newItem = bChildren[j]; - - if (newItem.key) { - if (!aKeys.hasOwnProperty(newItem.key)) { - // Add any new keyed items - // We are adding new items to the end and then sorting them - // in place. In future we should insert new items in place. - newChildren.push(newItem); - } - } else if (j >= lastFreeIndex) { - // Add any leftover non-keyed items - newChildren.push(newItem); - } - } - - var simulate = newChildren.slice(); - var simulateIndex = 0; - var removes = []; - var inserts = []; - var simulateItem; - - for (var k = 0; k < bChildren.length;) { - var wantedItem = bChildren[k]; - simulateItem = simulate[simulateIndex]; - - // remove items - while (simulateItem === null && simulate.length) { - removes.push(remove(simulate, simulateIndex, null)); - simulateItem = simulate[simulateIndex]; - } - - if (!simulateItem || simulateItem.key !== wantedItem.key) { - // if we need a key in this position... - if (wantedItem.key) { - if (simulateItem && simulateItem.key) { - // if an insert doesn't put this key in place, it needs to move - if (bKeys[simulateItem.key] !== k + 1) { - removes.push(remove(simulate, simulateIndex, simulateItem.key)); - simulateItem = simulate[simulateIndex]; - // if the remove didn't put the wanted item in place, we need to insert it - if (!simulateItem || simulateItem.key !== wantedItem.key) { - inserts.push({ key: wantedItem.key, to: k }); - } - // items are matching, so skip ahead - else { - simulateIndex++; - } - } else { - inserts.push({ key: wantedItem.key, to: k }); - } - } else { - inserts.push({ key: wantedItem.key, to: k }); - } - k++; - } - // a key in simulate has no matching wanted key, remove it - else if (simulateItem && simulateItem.key) { - removes.push(remove(simulate, simulateIndex, simulateItem.key)); - } - } else { - simulateIndex++; - k++; - } - } - - // remove all the remaining nodes from simulate - while (simulateIndex < simulate.length) { - simulateItem = simulate[simulateIndex]; - removes.push(remove(simulate, simulateIndex, simulateItem && simulateItem.key)); - } - - // If the only moves we have are deletes then we can just - // let the delete patch remove these items. - if (removes.length === deletedItems && !inserts.length) { - return { - children: newChildren, - moves: null - }; - } - - return { - children: newChildren, - moves: { - removes: removes, - inserts: inserts - } - }; - } - - function remove(arr, index, key) { - arr.splice(index, 1); - - return { - from: index, - key: key - }; - } - - function keyIndex(children) { - var keys = {}; - var free = []; - var length = children.length; - - for (var i = 0; i < length; i++) { - var child = children[i]; - - if (child.key) { - keys[child.key] = i; - } else { - free.push(i); - } - } - - return { - keys: keys, // A hash of key name to index - free: free // An array of unkeyed item indices - }; - } - - function appendPatch(apply, patch) { - if (apply) { - if (isArray(apply)) { - apply.push(patch); - } else { - apply = [apply, patch]; - } - - return apply; - } else { - return patch; - } - } - }, { "../vnode/handle-thunk": 24, "../vnode/is-thunk": 25, "../vnode/is-vnode": 27, "../vnode/is-vtext": 28, "../vnode/is-widget": 29, "../vnode/vpatch": 32, "./diff-props": 34, "x-is-array": 12 }] }, {}, [4])(4); -}); - -const start = function (domRoot, renderFn, initialState, options = []) { - let pid = self.processes.spawn(); - - if (Keyword.has_key__qm__(options, Kernel.SpecialForms.atom('name'))) { - pid = self.processes.register(Keyword.get(options, Kernel.SpecialForms.atom('name')), pid); - } - - const tree = renderFn.apply(this, initialState); - const rootNode = VirtualDOM.create(tree); - - domRoot.appendChild(rootNode); - - self.processes.put(pid, 'state', Kernel.SpecialForms.tuple(rootNode, tree, renderFn)); - return Kernel.SpecialForms.tuple(Kernel.SpecialForms.atom('ok'), pid); -}; - -const stop = function (agent, timeout = 5000) { - self.processes.exit(agent); - return Kernel.SpecialForms.atom('ok'); -}; - -const render = function (agent, state) { - - const current_state = self.processes.get(agent, 'state'); - - let rootNode = Kernel.elem(current_state, 0); - let tree = Kernel.elem(current_state, 1); - let renderFn = Kernel.elem(current_state, 2); - - let newTree = renderFn.apply(this, state); - - let patches = VirtualDOM.diff(tree, newTree); - rootNode = VirtualDOM.patch(rootNode, patches); - - self.processes.put(agent, 'state', Kernel.SpecialForms.tuple(rootNode, newTree, renderFn)); - - return Kernel.SpecialForms.atom('ok'); -}; - -var view = { - start, - stop, - render -}; - -self.processes = self.processes || new ProcessSystem(); - -const Core = C; - -export { Core, Kernel, Atom, Enum, Integer, List, Range, Tuple, Agent, Keyword, base as Base, String$1 as String, bitwise as Bitwise, Enumerable, Collectable, Inspect, map as Map, set as Set, MapSet, VirtualDOM, view as View }; -//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiIiwic291cmNlcyI6WyJFbGl4aXIuanMiXSwic291cmNlc0NvbnRlbnQiOlsiZnVuY3Rpb24gY2FsbF9wcm9wZXJ0eShpdGVtLCBwcm9wZXJ0eSkge1xuICBpZiAocHJvcGVydHkgaW4gaXRlbSkge1xuICAgIGl0ZW1bcHJvcGVydHldO1xuICAgIGlmIChpdGVtW3Byb3BlcnR5XSBpbnN0YW5jZW9mIEZ1bmN0aW9uKSB7XG4gICAgICByZXR1cm4gaXRlbVtwcm9wZXJ0eV0oKTtcbiAgICB9IGVsc2Uge1xuICAgICAgcmV0dXJuIGl0ZW1bcHJvcGVydHldO1xuICAgIH1cbiAgfSBlbHNlIGlmIChTeW1ib2wuZm9yKHByb3BlcnR5KSBpbiBpdGVtKSB7XG4gICAgbGV0IHByb3AgPSBTeW1ib2wuZm9yKHByb3BlcnR5KTtcbiAgICBpZiAoaXRlbVtwcm9wXSBpbnN0YW5jZW9mIEZ1bmN0aW9uKSB7XG4gICAgICByZXR1cm4gaXRlbVtwcm9wXSgpO1xuICAgIH0gZWxzZSB7XG4gICAgICByZXR1cm4gaXRlbVtwcm9wXTtcbiAgICB9XG4gIH1cblxuICB0aHJvdyBuZXcgRXJyb3IoYFByb3BlcnR5ICR7IHByb3BlcnR5IH0gbm90IGZvdW5kIGluICR7IGl0ZW0gfWApO1xufVxuXG5jbGFzcyBUdXBsZSQxIHtcblxuICBjb25zdHJ1Y3RvciguLi5hcmdzKSB7XG4gICAgdGhpcy52YWx1ZXMgPSBPYmplY3QuZnJlZXplKGFyZ3MpO1xuICB9XG5cbiAgZ2V0KGluZGV4KSB7XG4gICAgcmV0dXJuIHRoaXMudmFsdWVzW2luZGV4XTtcbiAgfVxuXG4gIGNvdW50KCkge1xuICAgIHJldHVybiB0aGlzLnZhbHVlcy5sZW5ndGg7XG4gIH1cblxuICBbU3ltYm9sLml0ZXJhdG9yXSgpIHtcbiAgICByZXR1cm4gdGhpcy52YWx1ZXNbU3ltYm9sLml0ZXJhdG9yXSgpO1xuICB9XG5cbiAgdG9TdHJpbmcoKSB7XG4gICAgdmFyIGksXG4gICAgICAgIHMgPSBcIlwiO1xuICAgIGZvciAoaSA9IDA7IGkgPCB0aGlzLnZhbHVlcy5sZW5ndGg7IGkrKykge1xuICAgICAgaWYgKHMgIT09IFwiXCIpIHtcbiAgICAgICAgcyArPSBcIiwgXCI7XG4gICAgICB9XG4gICAgICBzICs9IHRoaXMudmFsdWVzW2ldLnRvU3RyaW5nKCk7XG4gICAgfVxuXG4gICAgcmV0dXJuIFwie1wiICsgcyArIFwifVwiO1xuICB9XG5cbn1cblxubGV0IHByb2Nlc3NfY291bnRlciA9IC0xO1xuXG5jbGFzcyBQSUQge1xuICBjb25zdHJ1Y3RvcigpIHtcbiAgICBwcm9jZXNzX2NvdW50ZXIgPSBwcm9jZXNzX2NvdW50ZXIgKyAxO1xuICAgIHRoaXMuaWQgPSBwcm9jZXNzX2NvdW50ZXI7XG4gIH1cblxuICB0b1N0cmluZygpIHtcbiAgICByZXR1cm4gXCJQSUQjPDAuXCIgKyB0aGlzLmlkICsgXCIuMD5cIjtcbiAgfVxufVxuXG5jbGFzcyBJbnRlZ2VyJDEge31cbmNsYXNzIEZsb2F0IHt9XG5cbi8qIEBmbG93ICovXG5cbmNsYXNzIFZhcmlhYmxlIHtcblxuICBjb25zdHJ1Y3RvcihuYW1lID0gbnVsbCkge1xuICAgIHRoaXMubmFtZSA9IG5hbWU7XG4gIH1cbn1cblxuY2xhc3MgV2lsZGNhcmQge1xuICBjb25zdHJ1Y3RvcigpIHt9XG59XG5cbmNsYXNzIFN0YXJ0c1dpdGgge1xuXG4gIGNvbnN0cnVjdG9yKHByZWZpeCkge1xuICAgIHRoaXMucHJlZml4ID0gcHJlZml4O1xuICB9XG59XG5cbmNsYXNzIENhcHR1cmUge1xuXG4gIGNvbnN0cnVjdG9yKHZhbHVlKSB7XG4gICAgdGhpcy52YWx1ZSA9IHZhbHVlO1xuICB9XG59XG5cbmNsYXNzIEhlYWRUYWlsIHtcbiAgY29uc3RydWN0b3IoKSB7fVxufVxuXG5jbGFzcyBUeXBlIHtcblxuICBjb25zdHJ1Y3Rvcih0eXBlLCBvYmpQYXR0ZXJuID0ge30pIHtcbiAgICB0aGlzLnR5cGUgPSB0eXBlO1xuICAgIHRoaXMub2JqUGF0dGVybiA9IG9ialBhdHRlcm47XG4gIH1cbn1cblxuY2xhc3MgQm91bmQge1xuXG4gIGNvbnN0cnVjdG9yKHZhbHVlKSB7XG4gICAgdGhpcy52YWx1ZSA9IHZhbHVlO1xuICB9XG59XG5cbmZ1bmN0aW9uIHZhcmlhYmxlKG5hbWUgPSBudWxsKSB7XG4gIHJldHVybiBuZXcgVmFyaWFibGUobmFtZSk7XG59XG5cbmZ1bmN0aW9uIHdpbGRjYXJkKCkge1xuICByZXR1cm4gbmV3IFdpbGRjYXJkKCk7XG59XG5cbmZ1bmN0aW9uIHN0YXJ0c1dpdGgocHJlZml4KSB7XG4gIHJldHVybiBuZXcgU3RhcnRzV2l0aChwcmVmaXgpO1xufVxuXG5mdW5jdGlvbiBjYXB0dXJlKHZhbHVlKSB7XG4gIHJldHVybiBuZXcgQ2FwdHVyZSh2YWx1ZSk7XG59XG5cbmZ1bmN0aW9uIGhlYWRUYWlsKCkge1xuICByZXR1cm4gbmV3IEhlYWRUYWlsKCk7XG59XG5cbmZ1bmN0aW9uIHR5cGUodHlwZSwgb2JqUGF0dGVybiA9IHt9KSB7XG4gIHJldHVybiBuZXcgVHlwZSh0eXBlLCBvYmpQYXR0ZXJuKTtcbn1cblxuZnVuY3Rpb24gYm91bmQodmFsdWUpIHtcbiAgcmV0dXJuIG5ldyBCb3VuZCh2YWx1ZSk7XG59XG5cbmZ1bmN0aW9uIGlzX251bWJlciQxKHZhbHVlKSB7XG4gIHJldHVybiB0eXBlb2YgdmFsdWUgPT09ICdudW1iZXInO1xufVxuXG5mdW5jdGlvbiBpc19zdHJpbmcodmFsdWUpIHtcbiAgcmV0dXJuIHR5cGVvZiB2YWx1ZSA9PT0gJ3N0cmluZyc7XG59XG5cbmZ1bmN0aW9uIGlzX2Jvb2xlYW4kMSh2YWx1ZSkge1xuICByZXR1cm4gdHlwZW9mIHZhbHVlID09PSAnYm9vbGVhbic7XG59XG5cbmZ1bmN0aW9uIGlzX3N5bWJvbCh2YWx1ZSkge1xuICByZXR1cm4gdHlwZW9mIHZhbHVlID09PSAnc3ltYm9sJztcbn1cblxuZnVuY3Rpb24gaXNfbnVsbCh2YWx1ZSkge1xuICByZXR1cm4gdmFsdWUgPT09IG51bGw7XG59XG5cbmZ1bmN0aW9uIGlzX3VuZGVmaW5lZCh2YWx1ZSkge1xuICByZXR1cm4gdHlwZW9mIHZhbHVlID09PSAndW5kZWZpbmVkJztcbn1cblxuZnVuY3Rpb24gaXNfZnVuY3Rpb24kMSh2YWx1ZSkge1xuICByZXR1cm4gT2JqZWN0LnByb3RvdHlwZS50b1N0cmluZy5jYWxsKHZhbHVlKSA9PSAnW29iamVjdCBGdW5jdGlvbl0nO1xufVxuXG5mdW5jdGlvbiBpc192YXJpYWJsZSh2YWx1ZSkge1xuICByZXR1cm4gdmFsdWUgaW5zdGFuY2VvZiBWYXJpYWJsZTtcbn1cblxuZnVuY3Rpb24gaXNfd2lsZGNhcmQodmFsdWUpIHtcbiAgcmV0dXJuIHZhbHVlIGluc3RhbmNlb2YgV2lsZGNhcmQ7XG59XG5cbmZ1bmN0aW9uIGlzX2hlYWRUYWlsKHZhbHVlKSB7XG4gIHJldHVybiB2YWx1ZSBpbnN0YW5jZW9mIEhlYWRUYWlsO1xufVxuXG5mdW5jdGlvbiBpc19jYXB0dXJlKHZhbHVlKSB7XG4gIHJldHVybiB2YWx1ZSBpbnN0YW5jZW9mIENhcHR1cmU7XG59XG5cbmZ1bmN0aW9uIGlzX3R5cGUodmFsdWUpIHtcbiAgcmV0dXJuIHZhbHVlIGluc3RhbmNlb2YgVHlwZTtcbn1cblxuZnVuY3Rpb24gaXNfc3RhcnRzV2l0aCh2YWx1ZSkge1xuICByZXR1cm4gdmFsdWUgaW5zdGFuY2VvZiBTdGFydHNXaXRoO1xufVxuXG5mdW5jdGlvbiBpc19ib3VuZCh2YWx1ZSkge1xuICByZXR1cm4gdmFsdWUgaW5zdGFuY2VvZiBCb3VuZDtcbn1cblxuZnVuY3Rpb24gaXNfb2JqZWN0KHZhbHVlKSB7XG4gIHJldHVybiB0eXBlb2YgdmFsdWUgPT09ICdvYmplY3QnO1xufVxuXG5mdW5jdGlvbiBpc19hcnJheSh2YWx1ZSkge1xuICByZXR1cm4gQXJyYXkuaXNBcnJheSh2YWx1ZSk7XG59XG5cbnZhciBDaGVja3MgPSB7XG4gIGlzX251bWJlcjogaXNfbnVtYmVyJDEsXG4gIGlzX3N0cmluZyxcbiAgaXNfYm9vbGVhbjogaXNfYm9vbGVhbiQxLFxuICBpc19zeW1ib2wsXG4gIGlzX251bGwsXG4gIGlzX3VuZGVmaW5lZCxcbiAgaXNfZnVuY3Rpb246IGlzX2Z1bmN0aW9uJDEsXG4gIGlzX3ZhcmlhYmxlLFxuICBpc193aWxkY2FyZCxcbiAgaXNfaGVhZFRhaWwsXG4gIGlzX2NhcHR1cmUsXG4gIGlzX3R5cGUsXG4gIGlzX3N0YXJ0c1dpdGgsXG4gIGlzX2JvdW5kLFxuICBpc19vYmplY3QsXG4gIGlzX2FycmF5XG59O1xuXG5mdW5jdGlvbiByZXNvbHZlU3ltYm9sKHBhdHRlcm4pIHtcbiAgcmV0dXJuIGZ1bmN0aW9uICh2YWx1ZSkge1xuICAgIHJldHVybiBDaGVja3MuaXNfc3ltYm9sKHZhbHVlKSAmJiB2YWx1ZSA9PT0gcGF0dGVybjtcbiAgfTtcbn1cblxuZnVuY3Rpb24gcmVzb2x2ZVN0cmluZyhwYXR0ZXJuKSB7XG4gIHJldHVybiBmdW5jdGlvbiAodmFsdWUpIHtcbiAgICByZXR1cm4gQ2hlY2tzLmlzX3N0cmluZyh2YWx1ZSkgJiYgdmFsdWUgPT09IHBhdHRlcm47XG4gIH07XG59XG5cbmZ1bmN0aW9uIHJlc29sdmVOdW1iZXIocGF0dGVybikge1xuICByZXR1cm4gZnVuY3Rpb24gKHZhbHVlKSB7XG4gICAgcmV0dXJuIENoZWNrcy5pc19udW1iZXIodmFsdWUpICYmIHZhbHVlID09PSBwYXR0ZXJuO1xuICB9O1xufVxuXG5mdW5jdGlvbiByZXNvbHZlQm9vbGVhbihwYXR0ZXJuKSB7XG4gIHJldHVybiBmdW5jdGlvbiAodmFsdWUpIHtcbiAgICByZXR1cm4gQ2hlY2tzLmlzX2Jvb2xlYW4odmFsdWUpICYmIHZhbHVlID09PSBwYXR0ZXJuO1xuICB9O1xufVxuXG5mdW5jdGlvbiByZXNvbHZlRnVuY3Rpb24ocGF0dGVybikge1xuICByZXR1cm4gZnVuY3Rpb24gKHZhbHVlKSB7XG4gICAgcmV0dXJuIENoZWNrcy5pc19mdW5jdGlvbih2YWx1ZSkgJiYgdmFsdWUgPT09IHBhdHRlcm47XG4gIH07XG59XG5cbmZ1bmN0aW9uIHJlc29sdmVOdWxsKHBhdHRlcm4pIHtcbiAgcmV0dXJuIGZ1bmN0aW9uICh2YWx1ZSkge1xuICAgIHJldHVybiBDaGVja3MuaXNfbnVsbCh2YWx1ZSk7XG4gIH07XG59XG5cbmZ1bmN0aW9uIHJlc29sdmVCb3VuZChwYXR0ZXJuKSB7XG4gIHJldHVybiBmdW5jdGlvbiAodmFsdWUsIGFyZ3MpIHtcbiAgICBpZiAodHlwZW9mIHZhbHVlID09PSB0eXBlb2YgcGF0dGVybi52YWx1ZSAmJiB2YWx1ZSA9PT0gcGF0dGVybi52YWx1ZSkge1xuICAgICAgYXJncy5wdXNoKHZhbHVlKTtcbiAgICAgIHJldHVybiB0cnVlO1xuICAgIH1cblxuICAgIHJldHVybiBmYWxzZTtcbiAgfTtcbn1cblxuZnVuY3Rpb24gcmVzb2x2ZVdpbGRjYXJkKCkge1xuICByZXR1cm4gZnVuY3Rpb24gKCkge1xuICAgIHJldHVybiB0cnVlO1xuICB9O1xufVxuXG5mdW5jdGlvbiByZXNvbHZlVmFyaWFibGUoKSB7XG4gIHJldHVybiBmdW5jdGlvbiAodmFsdWUsIGFyZ3MpIHtcbiAgICBhcmdzLnB1c2godmFsdWUpO1xuICAgIHJldHVybiB0cnVlO1xuICB9O1xufVxuXG5mdW5jdGlvbiByZXNvbHZlSGVhZFRhaWwoKSB7XG4gIHJldHVybiBmdW5jdGlvbiAodmFsdWUsIGFyZ3MpIHtcbiAgICBpZiAoIUNoZWNrcy5pc19hcnJheSh2YWx1ZSkgfHwgdmFsdWUubGVuZ3RoIDwgMikge1xuICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH1cblxuICAgIGNvbnN0IGhlYWQgPSB2YWx1ZVswXTtcbiAgICBjb25zdCB0YWlsID0gdmFsdWUuc2xpY2UoMSk7XG5cbiAgICBhcmdzLnB1c2goaGVhZCk7XG4gICAgYXJncy5wdXNoKHRhaWwpO1xuXG4gICAgcmV0dXJuIHRydWU7XG4gIH07XG59XG5cbmZ1bmN0aW9uIHJlc29sdmVDYXB0dXJlKHBhdHRlcm4pIHtcbiAgY29uc3QgbWF0Y2hlcyA9IGJ1aWxkTWF0Y2gocGF0dGVybi52YWx1ZSk7XG5cbiAgcmV0dXJuIGZ1bmN0aW9uICh2YWx1ZSwgYXJncykge1xuICAgIGlmIChtYXRjaGVzKHZhbHVlLCBhcmdzKSkge1xuICAgICAgYXJncy5wdXNoKHZhbHVlKTtcbiAgICAgIHJldHVybiB0cnVlO1xuICAgIH1cblxuICAgIHJldHVybiBmYWxzZTtcbiAgfTtcbn1cblxuZnVuY3Rpb24gcmVzb2x2ZVN0YXJ0c1dpdGgocGF0dGVybikge1xuICBjb25zdCBwcmVmaXggPSBwYXR0ZXJuLnByZWZpeDtcblxuICByZXR1cm4gZnVuY3Rpb24gKHZhbHVlLCBhcmdzKSB7XG4gICAgaWYgKENoZWNrcy5pc19zdHJpbmcodmFsdWUpICYmIHZhbHVlLnN0YXJ0c1dpdGgocHJlZml4KSkge1xuICAgICAgYXJncy5wdXNoKHZhbHVlLnN1YnN0cmluZyhwcmVmaXgubGVuZ3RoKSk7XG4gICAgICByZXR1cm4gdHJ1ZTtcbiAgICB9XG5cbiAgICByZXR1cm4gZmFsc2U7XG4gIH07XG59XG5cbmZ1bmN0aW9uIHJlc29sdmVUeXBlKHBhdHRlcm4pIHtcbiAgcmV0dXJuIGZ1bmN0aW9uICh2YWx1ZSwgYXJncykge1xuICAgIGlmICh2YWx1ZSBpbnN0YW5jZW9mIHBhdHRlcm4udHlwZSkge1xuICAgICAgY29uc3QgbWF0Y2hlcyA9IGJ1aWxkTWF0Y2gocGF0dGVybi5vYmpQYXR0ZXJuKTtcbiAgICAgIHJldHVybiBtYXRjaGVzKHZhbHVlLCBhcmdzKSAmJiBhcmdzLnB1c2godmFsdWUpID4gMDtcbiAgICB9XG5cbiAgICByZXR1cm4gZmFsc2U7XG4gIH07XG59XG5cbmZ1bmN0aW9uIHJlc29sdmVBcnJheShwYXR0ZXJuKSB7XG4gIGNvbnN0IG1hdGNoZXMgPSBwYXR0ZXJuLm1hcCh4ID0+IGJ1aWxkTWF0Y2goeCkpO1xuXG4gIHJldHVybiBmdW5jdGlvbiAodmFsdWUsIGFyZ3MpIHtcbiAgICBpZiAoIUNoZWNrcy5pc19hcnJheSh2YWx1ZSkgfHwgdmFsdWUubGVuZ3RoICE9IHBhdHRlcm4ubGVuZ3RoKSB7XG4gICAgICByZXR1cm4gZmFsc2U7XG4gICAgfVxuXG4gICAgcmV0dXJuIHZhbHVlLmV2ZXJ5KGZ1bmN0aW9uICh2LCBpKSB7XG4gICAgICByZXR1cm4gbWF0Y2hlc1tpXSh2YWx1ZVtpXSwgYXJncyk7XG4gICAgfSk7XG4gIH07XG59XG5cbmZ1bmN0aW9uIHJlc29sdmVPYmplY3QocGF0dGVybikge1xuICBsZXQgbWF0Y2hlcyA9IHt9O1xuXG4gIGZvciAobGV0IGtleSBvZiBPYmplY3Qua2V5cyhwYXR0ZXJuKSkge1xuICAgIG1hdGNoZXNba2V5XSA9IGJ1aWxkTWF0Y2gocGF0dGVybltrZXldKTtcbiAgfVxuXG4gIHJldHVybiBmdW5jdGlvbiAodmFsdWUsIGFyZ3MpIHtcbiAgICBpZiAoIUNoZWNrcy5pc19vYmplY3QodmFsdWUpIHx8IHBhdHRlcm4ubGVuZ3RoID4gdmFsdWUubGVuZ3RoKSB7XG4gICAgICByZXR1cm4gZmFsc2U7XG4gICAgfVxuXG4gICAgZm9yIChsZXQga2V5IG9mIE9iamVjdC5rZXlzKHBhdHRlcm4pKSB7XG4gICAgICBpZiAoIShrZXkgaW4gdmFsdWUpIHx8ICFtYXRjaGVzW2tleV0odmFsdWVba2V5XSwgYXJncykpIHtcbiAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgfVxuICAgIH1cblxuICAgIHJldHVybiB0cnVlO1xuICB9O1xufVxuXG5mdW5jdGlvbiByZXNvbHZlTm9NYXRjaCgpIHtcbiAgcmV0dXJuIGZ1bmN0aW9uICgpIHtcbiAgICByZXR1cm4gZmFsc2U7XG4gIH07XG59XG5cbnZhciBSZXNvbHZlcnMgPSB7XG4gIHJlc29sdmVCb3VuZCxcbiAgcmVzb2x2ZVdpbGRjYXJkLFxuICByZXNvbHZlVmFyaWFibGUsXG4gIHJlc29sdmVIZWFkVGFpbCxcbiAgcmVzb2x2ZUNhcHR1cmUsXG4gIHJlc29sdmVTdGFydHNXaXRoLFxuICByZXNvbHZlVHlwZSxcbiAgcmVzb2x2ZUFycmF5LFxuICByZXNvbHZlT2JqZWN0LFxuICByZXNvbHZlTm9NYXRjaCxcbiAgcmVzb2x2ZVN5bWJvbCxcbiAgcmVzb2x2ZVN0cmluZyxcbiAgcmVzb2x2ZU51bWJlcixcbiAgcmVzb2x2ZUJvb2xlYW4sXG4gIHJlc29sdmVGdW5jdGlvbixcbiAgcmVzb2x2ZU51bGxcbn07XG5cbmZ1bmN0aW9uIGJ1aWxkTWF0Y2gocGF0dGVybikge1xuXG4gIGlmIChDaGVja3MuaXNfdmFyaWFibGUocGF0dGVybikpIHtcbiAgICByZXR1cm4gUmVzb2x2ZXJzLnJlc29sdmVWYXJpYWJsZShwYXR0ZXJuKTtcbiAgfVxuXG4gIGlmIChDaGVja3MuaXNfd2lsZGNhcmQocGF0dGVybikpIHtcbiAgICByZXR1cm4gUmVzb2x2ZXJzLnJlc29sdmVXaWxkY2FyZChwYXR0ZXJuKTtcbiAgfVxuXG4gIGlmIChDaGVja3MuaXNfdW5kZWZpbmVkKHBhdHRlcm4pKSB7XG4gICAgcmV0dXJuIFJlc29sdmVycy5yZXNvbHZlV2lsZGNhcmQocGF0dGVybik7XG4gIH1cblxuICBpZiAoQ2hlY2tzLmlzX2hlYWRUYWlsKHBhdHRlcm4pKSB7XG4gICAgcmV0dXJuIFJlc29sdmVycy5yZXNvbHZlSGVhZFRhaWwocGF0dGVybik7XG4gIH1cblxuICBpZiAoQ2hlY2tzLmlzX3N0YXJ0c1dpdGgocGF0dGVybikpIHtcbiAgICByZXR1cm4gUmVzb2x2ZXJzLnJlc29sdmVTdGFydHNXaXRoKHBhdHRlcm4pO1xuICB9XG5cbiAgaWYgKENoZWNrcy5pc19jYXB0dXJlKHBhdHRlcm4pKSB7XG4gICAgcmV0dXJuIFJlc29sdmVycy5yZXNvbHZlQ2FwdHVyZShwYXR0ZXJuKTtcbiAgfVxuXG4gIGlmIChDaGVja3MuaXNfYm91bmQocGF0dGVybikpIHtcbiAgICByZXR1cm4gUmVzb2x2ZXJzLnJlc29sdmVCb3VuZChwYXR0ZXJuKTtcbiAgfVxuXG4gIGlmIChDaGVja3MuaXNfdHlwZShwYXR0ZXJuKSkge1xuICAgIHJldHVybiBSZXNvbHZlcnMucmVzb2x2ZVR5cGUocGF0dGVybik7XG4gIH1cblxuICBpZiAoQ2hlY2tzLmlzX2FycmF5KHBhdHRlcm4pKSB7XG4gICAgcmV0dXJuIFJlc29sdmVycy5yZXNvbHZlQXJyYXkocGF0dGVybik7XG4gIH1cblxuICBpZiAoQ2hlY2tzLmlzX251bWJlcihwYXR0ZXJuKSkge1xuICAgIHJldHVybiBSZXNvbHZlcnMucmVzb2x2ZU51bWJlcihwYXR0ZXJuKTtcbiAgfVxuXG4gIGlmIChDaGVja3MuaXNfc3RyaW5nKHBhdHRlcm4pKSB7XG4gICAgcmV0dXJuIFJlc29sdmVycy5yZXNvbHZlU3RyaW5nKHBhdHRlcm4pO1xuICB9XG5cbiAgaWYgKENoZWNrcy5pc19ib29sZWFuKHBhdHRlcm4pKSB7XG4gICAgcmV0dXJuIFJlc29sdmVycy5yZXNvbHZlQm9vbGVhbihwYXR0ZXJuKTtcbiAgfVxuXG4gIGlmIChDaGVja3MuaXNfc3ltYm9sKHBhdHRlcm4pKSB7XG4gICAgcmV0dXJuIFJlc29sdmVycy5yZXNvbHZlU3ltYm9sKHBhdHRlcm4pO1xuICB9XG5cbiAgaWYgKENoZWNrcy5pc19udWxsKHBhdHRlcm4pKSB7XG4gICAgcmV0dXJuIFJlc29sdmVycy5yZXNvbHZlTnVsbChwYXR0ZXJuKTtcbiAgfVxuXG4gIGlmIChDaGVja3MuaXNfb2JqZWN0KHBhdHRlcm4pKSB7XG4gICAgcmV0dXJuIFJlc29sdmVycy5yZXNvbHZlT2JqZWN0KHBhdHRlcm4pO1xuICB9XG5cbiAgcmV0dXJuIFJlc29sdmVycy5yZXNvbHZlTm9NYXRjaCgpO1xufVxuXG5jbGFzcyBNYXRjaEVycm9yIGV4dGVuZHMgRXJyb3Ige1xuICBjb25zdHJ1Y3RvcihhcmcpIHtcbiAgICBzdXBlcigpO1xuXG4gICAgaWYgKHR5cGVvZiBhcmcgPT09ICdzeW1ib2wnKSB7XG4gICAgICB0aGlzLm1lc3NhZ2UgPSAnTm8gbWF0Y2ggZm9yOiAnICsgYXJnLnRvU3RyaW5nKCk7XG4gICAgfSBlbHNlIGlmIChBcnJheS5pc0FycmF5KGFyZykpIHtcbiAgICAgIGxldCBtYXBwZWRWYWx1ZXMgPSBhcmcubWFwKHggPT4geC50b1N0cmluZygpKTtcbiAgICAgIHRoaXMubWVzc2FnZSA9ICdObyBtYXRjaCBmb3I6ICcgKyBtYXBwZWRWYWx1ZXM7XG4gICAgfSBlbHNlIHtcbiAgICAgIHRoaXMubWVzc2FnZSA9ICdObyBtYXRjaCBmb3I6ICcgKyBhcmc7XG4gICAgfVxuXG4gICAgdGhpcy5zdGFjayA9IG5ldyBFcnJvcigpLnN0YWNrO1xuICAgIHRoaXMubmFtZSA9IHRoaXMuY29uc3RydWN0b3IubmFtZTtcbiAgfVxufVxuXG5jbGFzcyBDYXNlIHtcblxuICBjb25zdHJ1Y3RvcihwYXR0ZXJuLCBmbiwgZ3VhcmQgPSAoKSA9PiB0cnVlKSB7XG4gICAgdGhpcy5wYXR0ZXJuID0gYnVpbGRNYXRjaChwYXR0ZXJuKTtcbiAgICB0aGlzLmZuID0gZm47XG4gICAgdGhpcy5ndWFyZCA9IGd1YXJkO1xuICB9XG59XG5cbmZ1bmN0aW9uIG1ha2VfY2FzZShwYXR0ZXJuLCBmbiwgZ3VhcmQgPSAoKSA9PiB0cnVlKSB7XG4gIHJldHVybiBuZXcgQ2FzZShwYXR0ZXJuLCBmbiwgZ3VhcmQpO1xufVxuXG5mdW5jdGlvbiBkZWZtYXRjaCguLi5jYXNlcykge1xuICByZXR1cm4gZnVuY3Rpb24gKC4uLmFyZ3MpIHtcbiAgICBmb3IgKGxldCBwcm9jZXNzZWRDYXNlIG9mIGNhc2VzKSB7XG4gICAgICBsZXQgcmVzdWx0ID0gW107XG4gICAgICBpZiAocHJvY2Vzc2VkQ2FzZS5wYXR0ZXJuKGFyZ3MsIHJlc3VsdCkgJiYgcHJvY2Vzc2VkQ2FzZS5ndWFyZC5hcHBseSh0aGlzLCByZXN1bHQpKSB7XG4gICAgICAgIHJldHVybiBwcm9jZXNzZWRDYXNlLmZuLmFwcGx5KHRoaXMsIHJlc3VsdCk7XG4gICAgICB9XG4gICAgfVxuXG4gICAgdGhyb3cgbmV3IE1hdGNoRXJyb3IoYXJncyk7XG4gIH07XG59XG5cbmZ1bmN0aW9uIG1hdGNoKHBhdHRlcm4sIGV4cHIsIGd1YXJkID0gKCkgPT4gdHJ1ZSkge1xuICBsZXQgcmVzdWx0ID0gW107XG4gIGxldCBwcm9jZXNzZWRQYXR0ZXJuID0gYnVpbGRNYXRjaChwYXR0ZXJuKTtcbiAgaWYgKHByb2Nlc3NlZFBhdHRlcm4oZXhwciwgcmVzdWx0KSAmJiBndWFyZC5hcHBseSh0aGlzLCByZXN1bHQpKSB7XG4gICAgcmV0dXJuIHJlc3VsdDtcbiAgfSBlbHNlIHtcbiAgICB0aHJvdyBuZXcgTWF0Y2hFcnJvcihleHByKTtcbiAgfVxufVxuXG5mdW5jdGlvbiBtYXRjaF9ub190aHJvdyhwYXR0ZXJuLCBleHByLCBndWFyZCA9ICgpID0+IHRydWUpIHtcbiAgdHJ5IHtcbiAgICByZXR1cm4gbWF0Y2gocGF0dGVybiwgZXhwciwgZ3VhcmQpO1xuICB9IGNhdGNoIChlKSB7XG4gICAgaWYgKGUgaW5zdGFuY2VvZiBNYXRjaEVycm9yKSB7XG4gICAgICByZXR1cm4gbnVsbDtcbiAgICB9XG5cbiAgICB0aHJvdyBlO1xuICB9XG59XG5cbnZhciBQYXR0ZXJucyA9IHtcbiAgZGVmbWF0Y2gsIG1hdGNoLCBNYXRjaEVycm9yLCBtYXRjaF9ub190aHJvdyxcbiAgdmFyaWFibGUsIHdpbGRjYXJkLCBzdGFydHNXaXRoLFxuICBjYXB0dXJlLCBoZWFkVGFpbCwgdHlwZSwgYm91bmQsIENhc2UsIG1ha2VfY2FzZVxufTtcblxuY2xhc3MgQml0U3RyaW5nIHtcbiAgY29uc3RydWN0b3IoLi4uYXJncykge1xuICAgIHRoaXMucmF3X3ZhbHVlID0gZnVuY3Rpb24gKCkge1xuICAgICAgcmV0dXJuIE9iamVjdC5mcmVlemUoYXJncyk7XG4gICAgfTtcblxuICAgIHRoaXMudmFsdWUgPSBPYmplY3QuZnJlZXplKHRoaXMucHJvY2VzcyhhcmdzKSk7XG4gIH1cblxuICBnZXQoaW5kZXgpIHtcbiAgICByZXR1cm4gdGhpcy52YWx1ZVtpbmRleF07XG4gIH1cblxuICBjb3VudCgpIHtcbiAgICByZXR1cm4gdGhpcy52YWx1ZS5sZW5ndGg7XG4gIH1cblxuICBbU3ltYm9sLml0ZXJhdG9yXSgpIHtcbiAgICByZXR1cm4gdGhpcy52YWx1ZVtTeW1ib2wuaXRlcmF0b3JdKCk7XG4gIH1cblxuICB0b1N0cmluZygpIHtcbiAgICB2YXIgaSxcbiAgICAgICAgcyA9IFwiXCI7XG4gICAgZm9yIChpID0gMDsgaSA8IHRoaXMuY291bnQoKTsgaSsrKSB7XG4gICAgICBpZiAocyAhPT0gXCJcIikge1xuICAgICAgICBzICs9IFwiLCBcIjtcbiAgICAgIH1cbiAgICAgIHMgKz0gdGhpc1tpXS50b1N0cmluZygpO1xuICAgIH1cblxuICAgIHJldHVybiBcIjw8XCIgKyBzICsgXCI+PlwiO1xuICB9XG5cbiAgcHJvY2VzcygpIHtcbiAgICBsZXQgcHJvY2Vzc2VkX3ZhbHVlcyA9IFtdO1xuXG4gICAgdmFyIGk7XG4gICAgZm9yIChpID0gMDsgaSA8IHRoaXMucmF3X3ZhbHVlKCkubGVuZ3RoOyBpKyspIHtcbiAgICAgIGxldCBwcm9jZXNzZWRfdmFsdWUgPSB0aGlzW1wicHJvY2Vzc19cIiArIHRoaXMucmF3X3ZhbHVlKClbaV0udHlwZV0odGhpcy5yYXdfdmFsdWUoKVtpXSk7XG5cbiAgICAgIGZvciAobGV0IGF0dHIgb2YgdGhpcy5yYXdfdmFsdWUoKVtpXS5hdHRyaWJ1dGVzKSB7XG4gICAgICAgIHByb2Nlc3NlZF92YWx1ZSA9IHRoaXNbXCJwcm9jZXNzX1wiICsgYXR0cl0ocHJvY2Vzc2VkX3ZhbHVlKTtcbiAgICAgIH1cblxuICAgICAgcHJvY2Vzc2VkX3ZhbHVlcyA9IHByb2Nlc3NlZF92YWx1ZXMuY29uY2F0KHByb2Nlc3NlZF92YWx1ZSk7XG4gICAgfVxuXG4gICAgcmV0dXJuIHByb2Nlc3NlZF92YWx1ZXM7XG4gIH1cblxuICBwcm9jZXNzX2ludGVnZXIodmFsdWUpIHtcbiAgICByZXR1cm4gdmFsdWUudmFsdWU7XG4gIH1cblxuICBwcm9jZXNzX2Zsb2F0KHZhbHVlKSB7XG4gICAgaWYgKHZhbHVlLnNpemUgPT09IDY0KSB7XG4gICAgICByZXR1cm4gQml0U3RyaW5nLmZsb2F0NjRUb0J5dGVzKHZhbHVlLnZhbHVlKTtcbiAgICB9IGVsc2UgaWYgKHZhbHVlLnNpemUgPT09IDMyKSB7XG4gICAgICByZXR1cm4gQml0U3RyaW5nLmZsb2F0MzJUb0J5dGVzKHZhbHVlLnZhbHVlKTtcbiAgICB9XG5cbiAgICB0aHJvdyBuZXcgRXJyb3IoXCJJbnZhbGlkIHNpemUgZm9yIGZsb2F0XCIpO1xuICB9XG5cbiAgcHJvY2Vzc19iaXRzdHJpbmcodmFsdWUpIHtcbiAgICByZXR1cm4gdmFsdWUudmFsdWUudmFsdWU7XG4gIH1cblxuICBwcm9jZXNzX2JpbmFyeSh2YWx1ZSkge1xuICAgIHJldHVybiBCaXRTdHJpbmcudG9VVEY4QXJyYXkodmFsdWUudmFsdWUpO1xuICB9XG5cbiAgcHJvY2Vzc191dGY4KHZhbHVlKSB7XG4gICAgcmV0dXJuIEJpdFN0cmluZy50b1VURjhBcnJheSh2YWx1ZS52YWx1ZSk7XG4gIH1cblxuICBwcm9jZXNzX3V0ZjE2KHZhbHVlKSB7XG4gICAgcmV0dXJuIEJpdFN0cmluZy50b1VURjE2QXJyYXkodmFsdWUudmFsdWUpO1xuICB9XG5cbiAgcHJvY2Vzc191dGYzMih2YWx1ZSkge1xuICAgIHJldHVybiBCaXRTdHJpbmcudG9VVEYzMkFycmF5KHZhbHVlLnZhbHVlKTtcbiAgfVxuXG4gIHByb2Nlc3Nfc2lnbmVkKHZhbHVlKSB7XG4gICAgcmV0dXJuIG5ldyBVaW50OEFycmF5KFt2YWx1ZV0pWzBdO1xuICB9XG5cbiAgcHJvY2Vzc191bnNpZ25lZCh2YWx1ZSkge1xuICAgIHJldHVybiB2YWx1ZTtcbiAgfVxuXG4gIHByb2Nlc3NfbmF0aXZlKHZhbHVlKSB7XG4gICAgcmV0dXJuIHZhbHVlO1xuICB9XG5cbiAgcHJvY2Vzc19iaWcodmFsdWUpIHtcbiAgICByZXR1cm4gdmFsdWU7XG4gIH1cblxuICBwcm9jZXNzX2xpdHRsZSh2YWx1ZSkge1xuICAgIHJldHVybiB2YWx1ZS5yZXZlcnNlKCk7XG4gIH1cblxuICBwcm9jZXNzX3NpemUodmFsdWUpIHtcbiAgICByZXR1cm4gdmFsdWU7XG4gIH1cblxuICBwcm9jZXNzX3VuaXQodmFsdWUpIHtcbiAgICByZXR1cm4gdmFsdWU7XG4gIH1cblxuICBzdGF0aWMgaW50ZWdlcih2YWx1ZSkge1xuICAgIHJldHVybiBCaXRTdHJpbmcud3JhcCh2YWx1ZSwgeyBcInR5cGVcIjogXCJpbnRlZ2VyXCIsIFwidW5pdFwiOiAxLCBcInNpemVcIjogOCB9KTtcbiAgfVxuXG4gIHN0YXRpYyBmbG9hdCh2YWx1ZSkge1xuICAgIHJldHVybiBCaXRTdHJpbmcud3JhcCh2YWx1ZSwgeyBcInR5cGVcIjogXCJmbG9hdFwiLCBcInVuaXRcIjogMSwgXCJzaXplXCI6IDY0IH0pO1xuICB9XG5cbiAgc3RhdGljIGJpdHN0cmluZyh2YWx1ZSkge1xuICAgIHJldHVybiBCaXRTdHJpbmcud3JhcCh2YWx1ZSwgeyBcInR5cGVcIjogXCJiaXRzdHJpbmdcIiwgXCJ1bml0XCI6IDEsIFwic2l6ZVwiOiB2YWx1ZS5sZW5ndGggfSk7XG4gIH1cblxuICBzdGF0aWMgYml0cyh2YWx1ZSkge1xuICAgIHJldHVybiBCaXRTdHJpbmcuYml0c3RyaW5nKHZhbHVlKTtcbiAgfVxuXG4gIHN0YXRpYyBiaW5hcnkodmFsdWUpIHtcbiAgICByZXR1cm4gQml0U3RyaW5nLndyYXAodmFsdWUsIHsgXCJ0eXBlXCI6IFwiYmluYXJ5XCIsIFwidW5pdFwiOiA4LCBcInNpemVcIjogdmFsdWUubGVuZ3RoIH0pO1xuICB9XG5cbiAgc3RhdGljIGJ5dGVzKHZhbHVlKSB7XG4gICAgcmV0dXJuIEJpdFN0cmluZy5iaW5hcnkodmFsdWUpO1xuICB9XG5cbiAgc3RhdGljIHV0ZjgodmFsdWUpIHtcbiAgICByZXR1cm4gQml0U3RyaW5nLndyYXAodmFsdWUsIHsgXCJ0eXBlXCI6IFwidXRmOFwiIH0pO1xuICB9XG5cbiAgc3RhdGljIHV0ZjE2KHZhbHVlKSB7XG4gICAgcmV0dXJuIEJpdFN0cmluZy53cmFwKHZhbHVlLCB7IFwidHlwZVwiOiBcInV0ZjE2XCIgfSk7XG4gIH1cblxuICBzdGF0aWMgdXRmMzIodmFsdWUpIHtcbiAgICByZXR1cm4gQml0U3RyaW5nLndyYXAodmFsdWUsIHsgXCJ0eXBlXCI6IFwidXRmMzJcIiB9KTtcbiAgfVxuXG4gIHN0YXRpYyBzaWduZWQodmFsdWUpIHtcbiAgICByZXR1cm4gQml0U3RyaW5nLndyYXAodmFsdWUsIHt9LCBcInNpZ25lZFwiKTtcbiAgfVxuXG4gIHN0YXRpYyB1bnNpZ25lZCh2YWx1ZSkge1xuICAgIHJldHVybiBCaXRTdHJpbmcud3JhcCh2YWx1ZSwge30sIFwidW5zaWduZWRcIik7XG4gIH1cblxuICBzdGF0aWMgbmF0aXZlKHZhbHVlKSB7XG4gICAgcmV0dXJuIEJpdFN0cmluZy53cmFwKHZhbHVlLCB7fSwgXCJuYXRpdmVcIik7XG4gIH1cblxuICBzdGF0aWMgYmlnKHZhbHVlKSB7XG4gICAgcmV0dXJuIEJpdFN0cmluZy53cmFwKHZhbHVlLCB7fSwgXCJiaWdcIik7XG4gIH1cblxuICBzdGF0aWMgbGl0dGxlKHZhbHVlKSB7XG4gICAgcmV0dXJuIEJpdFN0cmluZy53cmFwKHZhbHVlLCB7fSwgXCJsaXR0bGVcIik7XG4gIH1cblxuICBzdGF0aWMgc2l6ZSh2YWx1ZSwgY291bnQpIHtcbiAgICByZXR1cm4gQml0U3RyaW5nLndyYXAodmFsdWUsIHsgXCJzaXplXCI6IGNvdW50IH0pO1xuICB9XG5cbiAgc3RhdGljIHVuaXQodmFsdWUsIGNvdW50KSB7XG4gICAgcmV0dXJuIEJpdFN0cmluZy53cmFwKHZhbHVlLCB7IFwidW5pdFwiOiBjb3VudCB9KTtcbiAgfVxuXG4gIHN0YXRpYyB3cmFwKHZhbHVlLCBvcHQsIG5ld19hdHRyaWJ1dGUgPSBudWxsKSB7XG4gICAgbGV0IHRoZV92YWx1ZSA9IHZhbHVlO1xuXG4gICAgaWYgKCEodmFsdWUgaW5zdGFuY2VvZiBPYmplY3QpKSB7XG4gICAgICB0aGVfdmFsdWUgPSB7IFwidmFsdWVcIjogdmFsdWUsIFwiYXR0cmlidXRlc1wiOiBbXSB9O1xuICAgIH1cblxuICAgIHRoZV92YWx1ZSA9IE9iamVjdC5hc3NpZ24odGhlX3ZhbHVlLCBvcHQpO1xuXG4gICAgaWYgKG5ld19hdHRyaWJ1dGUpIHtcbiAgICAgIHRoZV92YWx1ZS5hdHRyaWJ1dGVzLnB1c2gobmV3X2F0dHJpYnV0ZSk7XG4gICAgfVxuXG4gICAgcmV0dXJuIHRoZV92YWx1ZTtcbiAgfVxuXG4gIHN0YXRpYyB0b1VURjhBcnJheShzdHIpIHtcbiAgICB2YXIgdXRmOCA9IFtdO1xuICAgIGZvciAodmFyIGkgPSAwOyBpIDwgc3RyLmxlbmd0aDsgaSsrKSB7XG4gICAgICB2YXIgY2hhcmNvZGUgPSBzdHIuY2hhckNvZGVBdChpKTtcbiAgICAgIGlmIChjaGFyY29kZSA8IDEyOCkge1xuICAgICAgICB1dGY4LnB1c2goY2hhcmNvZGUpO1xuICAgICAgfSBlbHNlIGlmIChjaGFyY29kZSA8IDIwNDgpIHtcbiAgICAgICAgdXRmOC5wdXNoKDE5MiB8IGNoYXJjb2RlID4+IDYsIDEyOCB8IGNoYXJjb2RlICYgNjMpO1xuICAgICAgfSBlbHNlIGlmIChjaGFyY29kZSA8IDU1Mjk2IHx8IGNoYXJjb2RlID49IDU3MzQ0KSB7XG4gICAgICAgIHV0ZjgucHVzaCgyMjQgfCBjaGFyY29kZSA+PiAxMiwgMTI4IHwgY2hhcmNvZGUgPj4gNiAmIDYzLCAxMjggfCBjaGFyY29kZSAmIDYzKTtcbiAgICAgIH1cbiAgICAgIC8vIHN1cnJvZ2F0ZSBwYWlyXG4gICAgICBlbHNlIHtcbiAgICAgICAgaSsrO1xuICAgICAgICAvLyBVVEYtMTYgZW5jb2RlcyAweDEwMDAwLTB4MTBGRkZGIGJ5XG4gICAgICAgIC8vIHN1YnRyYWN0aW5nIDB4MTAwMDAgYW5kIHNwbGl0dGluZyB0aGVcbiAgICAgICAgLy8gMjAgYml0cyBvZiAweDAtMHhGRkZGRiBpbnRvIHR3byBoYWx2ZXNcbiAgICAgICAgY2hhcmNvZGUgPSA2NTUzNiArICgoY2hhcmNvZGUgJiAxMDIzKSA8PCAxMCB8IHN0ci5jaGFyQ29kZUF0KGkpICYgMTAyMyk7XG4gICAgICAgIHV0ZjgucHVzaCgyNDAgfCBjaGFyY29kZSA+PiAxOCwgMTI4IHwgY2hhcmNvZGUgPj4gMTIgJiA2MywgMTI4IHwgY2hhcmNvZGUgPj4gNiAmIDYzLCAxMjggfCBjaGFyY29kZSAmIDYzKTtcbiAgICAgIH1cbiAgICB9XG4gICAgcmV0dXJuIHV0Zjg7XG4gIH1cblxuICBzdGF0aWMgdG9VVEYxNkFycmF5KHN0cikge1xuICAgIHZhciB1dGYxNiA9IFtdO1xuICAgIGZvciAodmFyIGkgPSAwOyBpIDwgc3RyLmxlbmd0aDsgaSsrKSB7XG4gICAgICB2YXIgY29kZVBvaW50ID0gc3RyLmNvZGVQb2ludEF0KGkpO1xuXG4gICAgICBpZiAoY29kZVBvaW50IDw9IDI1NSkge1xuICAgICAgICB1dGYxNi5wdXNoKDApO1xuICAgICAgICB1dGYxNi5wdXNoKGNvZGVQb2ludCk7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICB1dGYxNi5wdXNoKGNvZGVQb2ludCA+PiA4ICYgMjU1KTtcbiAgICAgICAgdXRmMTYucHVzaChjb2RlUG9pbnQgJiAyNTUpO1xuICAgICAgfVxuICAgIH1cbiAgICByZXR1cm4gdXRmMTY7XG4gIH1cblxuICBzdGF0aWMgdG9VVEYzMkFycmF5KHN0cikge1xuICAgIHZhciB1dGYzMiA9IFtdO1xuICAgIGZvciAodmFyIGkgPSAwOyBpIDwgc3RyLmxlbmd0aDsgaSsrKSB7XG4gICAgICB2YXIgY29kZVBvaW50ID0gc3RyLmNvZGVQb2ludEF0KGkpO1xuXG4gICAgICBpZiAoY29kZVBvaW50IDw9IDI1NSkge1xuICAgICAgICB1dGYzMi5wdXNoKDApO1xuICAgICAgICB1dGYzMi5wdXNoKDApO1xuICAgICAgICB1dGYzMi5wdXNoKDApO1xuICAgICAgICB1dGYzMi5wdXNoKGNvZGVQb2ludCk7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICB1dGYzMi5wdXNoKDApO1xuICAgICAgICB1dGYzMi5wdXNoKDApO1xuICAgICAgICB1dGYzMi5wdXNoKGNvZGVQb2ludCA+PiA4ICYgMjU1KTtcbiAgICAgICAgdXRmMzIucHVzaChjb2RlUG9pbnQgJiAyNTUpO1xuICAgICAgfVxuICAgIH1cbiAgICByZXR1cm4gdXRmMzI7XG4gIH1cblxuICAvL2h0dHA6Ly9zdGFja292ZXJmbG93LmNvbS9xdWVzdGlvbnMvMjAwMzQ5My9qYXZhc2NyaXB0LWZsb2F0LWZyb20tdG8tYml0c1xuICBzdGF0aWMgZmxvYXQzMlRvQnl0ZXMoZikge1xuICAgIHZhciBieXRlcyA9IFtdO1xuXG4gICAgdmFyIGJ1ZiA9IG5ldyBBcnJheUJ1ZmZlcig0KTtcbiAgICBuZXcgRmxvYXQzMkFycmF5KGJ1ZilbMF0gPSBmO1xuXG4gICAgbGV0IGludFZlcnNpb24gPSBuZXcgVWludDMyQXJyYXkoYnVmKVswXTtcblxuICAgIGJ5dGVzLnB1c2goaW50VmVyc2lvbiA+PiAyNCAmIDI1NSk7XG4gICAgYnl0ZXMucHVzaChpbnRWZXJzaW9uID4+IDE2ICYgMjU1KTtcbiAgICBieXRlcy5wdXNoKGludFZlcnNpb24gPj4gOCAmIDI1NSk7XG4gICAgYnl0ZXMucHVzaChpbnRWZXJzaW9uICYgMjU1KTtcblxuICAgIHJldHVybiBieXRlcztcbiAgfVxuXG4gIHN0YXRpYyBmbG9hdDY0VG9CeXRlcyhmKSB7XG4gICAgdmFyIGJ5dGVzID0gW107XG5cbiAgICB2YXIgYnVmID0gbmV3IEFycmF5QnVmZmVyKDgpO1xuICAgIG5ldyBGbG9hdDY0QXJyYXkoYnVmKVswXSA9IGY7XG5cbiAgICB2YXIgaW50VmVyc2lvbjEgPSBuZXcgVWludDMyQXJyYXkoYnVmKVswXTtcbiAgICB2YXIgaW50VmVyc2lvbjIgPSBuZXcgVWludDMyQXJyYXkoYnVmKVsxXTtcblxuICAgIGJ5dGVzLnB1c2goaW50VmVyc2lvbjIgPj4gMjQgJiAyNTUpO1xuICAgIGJ5dGVzLnB1c2goaW50VmVyc2lvbjIgPj4gMTYgJiAyNTUpO1xuICAgIGJ5dGVzLnB1c2goaW50VmVyc2lvbjIgPj4gOCAmIDI1NSk7XG4gICAgYnl0ZXMucHVzaChpbnRWZXJzaW9uMiAmIDI1NSk7XG5cbiAgICBieXRlcy5wdXNoKGludFZlcnNpb24xID4+IDI0ICYgMjU1KTtcbiAgICBieXRlcy5wdXNoKGludFZlcnNpb24xID4+IDE2ICYgMjU1KTtcbiAgICBieXRlcy5wdXNoKGludFZlcnNpb24xID4+IDggJiAyNTUpO1xuICAgIGJ5dGVzLnB1c2goaW50VmVyc2lvbjEgJiAyNTUpO1xuXG4gICAgcmV0dXJuIGJ5dGVzO1xuICB9XG59XG5cbi8qIEBmbG93ICovXG5cbmNsYXNzIE1haWxib3gge1xuXG4gIGNvbnN0cnVjdG9yKCkge1xuICAgIHRoaXMubWVzc2FnZXMgPSBbXTtcbiAgfVxuXG4gIGRlbGl2ZXIobWVzc2FnZSkge1xuICAgIHRoaXMubWVzc2FnZXMucHVzaChtZXNzYWdlKTtcbiAgICByZXR1cm4gbWVzc2FnZTtcbiAgfVxuXG4gIGdldCgpIHtcbiAgICByZXR1cm4gdGhpcy5tZXNzYWdlcztcbiAgfVxuXG4gIGlzRW1wdHkoKSB7XG4gICAgcmV0dXJuIHRoaXMubWVzc2FnZXMubGVuZ3RoID09PSAwO1xuICB9XG5cbiAgcmVtb3ZlQXQoaW5kZXgpIHtcbiAgICB0aGlzLm1lc3NhZ2VzLnNwbGljZShpbmRleCwgMSk7XG4gIH1cbn1cblxudmFyIFN0YXRlcyA9IHtcbiAgTk9STUFMOiBTeW1ib2wuZm9yKFwibm9ybWFsXCIpLFxuICBLSUxMOiBTeW1ib2wuZm9yKFwia2lsbFwiKSxcbiAgU1VTUEVORDogU3ltYm9sLmZvcihcInN1c3BlbmRcIiksXG4gIENPTlRJTlVFOiBTeW1ib2wuZm9yKFwiY29udGludWVcIiksXG4gIFJFQ0VJVkU6IFN5bWJvbC5mb3IoXCJyZWNlaXZlXCIpLFxuICBTRU5EOiBTeW1ib2wuZm9yKFwic2VuZFwiKSxcbiAgU0xFRVBJTkc6IFN5bWJvbC5mb3IoXCJzbGVlcGluZ1wiKSxcbiAgUlVOTklORzogU3ltYm9sLmZvcihcInJ1bm5pbmdcIiksXG4gIFNVU1BFTkRFRDogU3ltYm9sLmZvcihcInN1c3BlbmRlZFwiKSxcbiAgU1RPUFBFRDogU3ltYm9sLmZvcihcInN0b3BwZWRcIiksXG4gIFNMRUVQOiBTeW1ib2wuZm9yKFwic2xlZXBcIiksXG4gIEVYSVQ6IFN5bWJvbC5mb3IoXCJleGl0XCIpLFxuICBOT01BVENIOiBTeW1ib2wuZm9yKFwibm9fbWF0Y2hcIilcbn07XG5cbmNsYXNzIFByb2Nlc3Mge1xuXG4gIGNvbnN0cnVjdG9yKHBpZCwgbWFpbGJveCkge1xuICAgIHRoaXMucGlkID0gcGlkO1xuICAgIHRoaXMubWFpbGJveCA9IG1haWxib3g7XG4gICAgdGhpcy5zdGF0dXMgPSBTdGF0ZXMuU1RPUFBFRDtcbiAgICB0aGlzLmRpY3QgPSB7fTtcbiAgfVxufVxuXG5jbGFzcyBQcm9jZXNzU3lzdGVtIHtcblxuICBjb25zdHJ1Y3RvcigpIHtcbiAgICB0aGlzLnBpZHMgPSBuZXcgTWFwKCk7XG4gICAgdGhpcy5tYWlsYm94ZXMgPSBuZXcgTWFwKCk7XG4gICAgdGhpcy5uYW1lcyA9IG5ldyBNYXAoKTtcbiAgICB0aGlzLmxpbmtzID0gbmV3IE1hcCgpO1xuXG4gICAgdGhpcy5jdXJyZW50X3Byb2Nlc3MgPSBudWxsO1xuICAgIHRoaXMuc3VzcGVuZGVkID0gbmV3IE1hcCgpO1xuXG4gICAgdGhpcy5tYWluX3Byb2Nlc3NfcGlkID0gdGhpcy5zcGF3bigpO1xuICAgIHRoaXMuc2V0X2N1cnJlbnQodGhpcy5tYWluX3Byb2Nlc3NfcGlkKTtcbiAgfVxuXG4gIHNwYXduKCkge1xuICAgIHJldHVybiB0aGlzLmFkZF9wcm9jKGZhbHNlKS5waWQ7XG4gIH1cblxuICBzcGF3bl9saW5rKCkge1xuICAgIHJldHVybiB0aGlzLmFkZF9wcm9jKHRydWUpLnBpZDtcbiAgfVxuXG4gIGxpbmsocGlkKSB7XG4gICAgdGhpcy5saW5rcy5nZXQodGhpcy5waWQoKSkuYWRkKHBpZCk7XG4gICAgdGhpcy5saW5rcy5nZXQocGlkKS5hZGQodGhpcy5waWQoKSk7XG4gIH1cblxuICB1bmxpbmsocGlkKSB7XG4gICAgdGhpcy5saW5rcy5nZXQodGhpcy5waWQoKSkuZGVsZXRlKHBpZCk7XG4gICAgdGhpcy5saW5rcy5nZXQocGlkKS5kZWxldGUodGhpcy5waWQoKSk7XG4gIH1cblxuICBzZXRfY3VycmVudChpZCkge1xuICAgIGxldCBwaWQgPSB0aGlzLnBpZG9mKGlkKTtcbiAgICBpZiAocGlkICE9PSBudWxsKSB7XG4gICAgICB0aGlzLmN1cnJlbnRfcHJvY2VzcyA9IHRoaXMucGlkcy5nZXQocGlkKTtcbiAgICAgIHRoaXMuY3VycmVudF9wcm9jZXNzLnN0YXR1cyA9IFN0YXRlcy5SVU5OSU5HO1xuICAgIH1cbiAgfVxuXG4gIGFkZF9wcm9jKGxpbmtlZCkge1xuICAgIGxldCBuZXdwaWQgPSBuZXcgUElEKCk7XG4gICAgbGV0IG1haWxib3ggPSBuZXcgTWFpbGJveCgpO1xuICAgIGxldCBuZXdwcm9jID0gbmV3IFByb2Nlc3MobmV3cGlkLCBtYWlsYm94KTtcblxuICAgIHRoaXMucGlkcy5zZXQobmV3cGlkLCBuZXdwcm9jKTtcbiAgICB0aGlzLm1haWxib3hlcy5zZXQobmV3cGlkLCBtYWlsYm94KTtcbiAgICB0aGlzLmxpbmtzLnNldChuZXdwaWQsIG5ldyBTZXQoKSk7XG5cbiAgICBpZiAobGlua2VkKSB7XG4gICAgICB0aGlzLmxpbmsobmV3cGlkKTtcbiAgICB9XG5cbiAgICByZXR1cm4gbmV3cHJvYztcbiAgfVxuXG4gIHJlbW92ZV9wcm9jKHBpZCkge1xuICAgIHRoaXMucGlkcy5kZWxldGUocGlkKTtcbiAgICB0aGlzLnVucmVnaXN0ZXIocGlkKTtcblxuICAgIGlmICh0aGlzLmxpbmtzLmhhcyhwaWQpKSB7XG4gICAgICBmb3IgKGxldCBsaW5rcGlkIG9mIHRoaXMubGlua3MuZ2V0KHBpZCkpIHtcbiAgICAgICAgdGhpcy5saW5rcy5nZXQobGlua3BpZCkuZGVsZXRlKHBpZCk7XG4gICAgICB9XG5cbiAgICAgIHRoaXMubGlua3MuZGVsZXRlKHBpZCk7XG4gICAgfVxuICB9XG5cbiAgZXhpdChpZCkge1xuICAgIGxldCBwaWQgPSB0aGlzLnBpZG9mKGlkKTtcbiAgICB0aGlzLnJlbW92ZV9wcm9jKGlkKTtcbiAgfVxuXG4gIHJlZ2lzdGVyKG5hbWUsIHBpZCkge1xuICAgIGlmICghdGhpcy5uYW1lcy5oYXMobmFtZSkpIHtcbiAgICAgIHRoaXMubmFtZXMuc2V0KG5hbWUsIHBpZCk7XG4gICAgICByZXR1cm4gbmFtZTtcbiAgICB9IGVsc2Uge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKFwiTmFtZSBpcyBhbHJlYWR5IHJlZ2lzdGVyZWQgdG8gYW5vdGhlciBwcm9jZXNzXCIpO1xuICAgIH1cbiAgfVxuXG4gIHJlZ2lzdGVyZWQobmFtZSkge1xuICAgIHJldHVybiB0aGlzLm5hbWVzLmhhcyhuYW1lKSA/IHRoaXMubmFtZXMuZ2V0KG5hbWUpIDogbnVsbDtcbiAgfVxuXG4gIHVucmVnaXN0ZXIocGlkKSB7XG4gICAgZm9yIChsZXQgbmFtZSBvZiB0aGlzLm5hbWVzLmtleXMoKSkge1xuICAgICAgaWYgKHRoaXMubmFtZXMuaGFzKG5hbWUpICYmIHRoaXMubmFtZXMuZ2V0KG5hbWUpID09PSBwaWQpIHtcbiAgICAgICAgdGhpcy5uYW1lcy5kZWxldGUobmFtZSk7XG4gICAgICB9XG4gICAgfVxuICB9XG5cbiAgcGlkKCkge1xuICAgIHJldHVybiB0aGlzLmN1cnJlbnRfcHJvY2Vzcy5waWQ7XG4gIH1cblxuICBwaWRvZihpZCkge1xuICAgIGlmIChpZCBpbnN0YW5jZW9mIFBJRCkge1xuICAgICAgcmV0dXJuIHRoaXMucGlkcy5oYXMoaWQpID8gaWQgOiBudWxsO1xuICAgIH0gZWxzZSBpZiAoaWQgaW5zdGFuY2VvZiBQcm9jZXNzKSB7XG4gICAgICByZXR1cm4gaWQucGlkO1xuICAgIH0gZWxzZSB7XG4gICAgICBsZXQgcGlkID0gdGhpcy5yZWdpc3RlcmVkKGlkKTtcbiAgICAgIGlmIChwaWQgPT09IG51bGwpIHRocm93IFwiUHJvY2VzcyBuYW1lIG5vdCByZWdpc3RlcmVkOiBcIiArIGlkICsgXCIgKFwiICsgdHlwZW9mIGlkICsgXCIpXCI7XG4gICAgICByZXR1cm4gcGlkO1xuICAgIH1cbiAgfVxuXG4gIHB1dChpZCwga2V5LCB2YWx1ZSkge1xuICAgIGxldCBwaWQgPSB0aGlzLnBpZG9mKGlkKTtcbiAgICBsZXQgcHJvY2VzcyA9IHRoaXMucGlkcy5nZXQocGlkKTtcbiAgICBwcm9jZXNzLmRpY3Rba2V5XSA9IHZhbHVlO1xuICB9XG5cbiAgZ2V0KGlkLCBrZXkpIHtcbiAgICBsZXQgcGlkID0gdGhpcy5waWRvZihpZCk7XG4gICAgbGV0IHByb2Nlc3MgPSB0aGlzLnBpZHMuZ2V0KHBpZCk7XG5cbiAgICBpZiAoa2V5ICE9IG51bGwpIHtcbiAgICAgIHJldHVybiBwcm9jZXNzLmRpY3Rba2V5XTtcbiAgICB9IGVsc2Uge1xuICAgICAgcmV0dXJuIHByb2Nlc3MuZGljdDtcbiAgICB9XG4gIH1cblxuICBnZXRfa2V5cyhpZCkge1xuICAgIGxldCBwaWQgPSB0aGlzLnBpZG9mKGlkKTtcbiAgICBsZXQgcHJvY2VzcyA9IHRoaXMucGlkcy5nZXQocGlkKTtcblxuICAgIHJldHVybiBPYmplY3Qua2V5cyhwcm9jZXNzLmRpY3QpO1xuICB9XG5cbiAgZXJhc2UoaWQsIGtleSkge1xuICAgIGxldCBwaWQgPSB0aGlzLnBpZG9mKGlkKTtcbiAgICBsZXQgcHJvY2VzcyA9IHRoaXMucGlkcy5nZXQocGlkKTtcblxuICAgIGlmIChrZXkgIT0gbnVsbCkge1xuICAgICAgZGVsZXRlIHByb2Nlc3MuZGljdFtrZXldO1xuICAgIH0gZWxzZSB7XG4gICAgICBwcm9jZXNzLmRpY3QgPSB7fTtcbiAgICB9XG4gIH1cbn1cblxudmFyIEMgPSBPYmplY3QuZnJlZXplKHtcblx0UHJvY2Vzc1N5c3RlbTogUHJvY2Vzc1N5c3RlbSxcblx0VHVwbGU6IFR1cGxlJDEsXG5cdFBJRDogUElELFxuXHRCaXRTdHJpbmc6IEJpdFN0cmluZyxcblx0UGF0dGVybnM6IFBhdHRlcm5zLFxuXHRJbnRlZ2VyOiBJbnRlZ2VyJDEsXG5cdEZsb2F0OiBGbG9hdCxcblx0Y2FsbF9wcm9wZXJ0eTogY2FsbF9wcm9wZXJ0eVxufSk7XG5cbmxldCBFbnVtID0ge1xuXG4gIGFsbF9fcW1hcmtfXzogZnVuY3Rpb24gKGNvbGxlY3Rpb24sIGZ1biA9IHggPT4geCkge1xuICAgIGZvciAobGV0IGVsZW0gb2YgY29sbGVjdGlvbikge1xuICAgICAgaWYgKCFmdW4oZWxlbSkpIHtcbiAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgfVxuICAgIH1cblxuICAgIHJldHVybiB0cnVlO1xuICB9LFxuXG4gIGFueV9fcW1hcmtfXzogZnVuY3Rpb24gKGNvbGxlY3Rpb24sIGZ1biA9IHggPT4geCkge1xuICAgIGZvciAobGV0IGVsZW0gb2YgY29sbGVjdGlvbikge1xuICAgICAgaWYgKGZ1bihlbGVtKSkge1xuICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICByZXR1cm4gZmFsc2U7XG4gIH0sXG5cbiAgYXQ6IGZ1bmN0aW9uIChjb2xsZWN0aW9uLCBuLCB0aGVfZGVmYXVsdCA9IG51bGwpIHtcbiAgICBpZiAobiA+IHRoaXMuY291bnQoY29sbGVjdGlvbikgfHwgbiA8IDApIHtcbiAgICAgIHJldHVybiB0aGVfZGVmYXVsdDtcbiAgICB9XG5cbiAgICByZXR1cm4gY29sbGVjdGlvbltuXTtcbiAgfSxcblxuICBjb25jYXQ6IGZ1bmN0aW9uICguLi5lbnVtYWJsZXMpIHtcbiAgICByZXR1cm4gZW51bWFibGVzWzBdLmNvbmNhdChlbnVtYWJsZXNbMV0pO1xuICB9LFxuXG4gIGNvdW50OiBmdW5jdGlvbiAoY29sbGVjdGlvbiwgZnVuID0gbnVsbCkge1xuICAgIGlmIChmdW4gPT0gbnVsbCkge1xuICAgICAgcmV0dXJuIGNvbGxlY3Rpb24ubGVuZ3RoO1xuICAgIH0gZWxzZSB7XG4gICAgICByZXR1cm4gY29sbGVjdGlvbi5maWx0ZXIoZnVuKS5sZW5ndGg7XG4gICAgfVxuICB9LFxuXG4gIGRyb3A6IGZ1bmN0aW9uIChjb2xsZWN0aW9uLCBjb3VudCkge1xuICAgIHJldHVybiBjb2xsZWN0aW9uLnNsaWNlKGNvdW50KTtcbiAgfSxcblxuICBkcm9wX3doaWxlOiBmdW5jdGlvbiAoY29sbGVjdGlvbiwgZnVuKSB7XG4gICAgbGV0IGNvdW50ID0gMDtcblxuICAgIGZvciAobGV0IGVsZW0gb2YgY29sbGVjdGlvbikge1xuICAgICAgaWYgKGZ1bihlbGVtKSkge1xuICAgICAgICBjb3VudCA9IGNvdW50ICsgMTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIGJyZWFrO1xuICAgICAgfVxuICAgIH1cblxuICAgIHJldHVybiBjb2xsZWN0aW9uLnNsaWNlKGNvdW50KTtcbiAgfSxcblxuICBlYWNoOiBmdW5jdGlvbiAoY29sbGVjdGlvbiwgZnVuKSB7XG4gICAgZm9yIChsZXQgZWxlbSBvZiBjb2xsZWN0aW9uKSB7XG4gICAgICBmdW4oZWxlbSk7XG4gICAgfVxuICB9LFxuXG4gIGVtcHR5X19xbWFya19fOiBmdW5jdGlvbiAoY29sbGVjdGlvbikge1xuICAgIHJldHVybiBjb2xsZWN0aW9uLmxlbmd0aCA9PT0gMDtcbiAgfSxcblxuICBmZXRjaDogZnVuY3Rpb24gKGNvbGxlY3Rpb24sIG4pIHtcbiAgICBpZiAoS2VybmVsLmlzX2xpc3QoY29sbGVjdGlvbikpIHtcbiAgICAgIGlmIChuIDwgdGhpcy5jb3VudChjb2xsZWN0aW9uKSAmJiBuID49IDApIHtcbiAgICAgICAgcmV0dXJuIEtlcm5lbC5TcGVjaWFsRm9ybXMudHVwbGUoS2VybmVsLlNwZWNpYWxGb3Jtcy5hdG9tKFwib2tcIiksIGNvbGxlY3Rpb25bbl0pO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgcmV0dXJuIEtlcm5lbC5TcGVjaWFsRm9ybXMuYXRvbShcImVycm9yXCIpO1xuICAgICAgfVxuICAgIH1cblxuICAgIHRocm93IG5ldyBFcnJvcihcImNvbGxlY3Rpb24gaXMgbm90IGFuIEVudW1lcmFibGVcIik7XG4gIH0sXG5cbiAgZmV0Y2hfX2VtYXJrX186IGZ1bmN0aW9uIChjb2xsZWN0aW9uLCBuKSB7XG4gICAgaWYgKEtlcm5lbC5pc19saXN0KGNvbGxlY3Rpb24pKSB7XG4gICAgICBpZiAobiA8IHRoaXMuY291bnQoY29sbGVjdGlvbikgJiYgbiA+PSAwKSB7XG4gICAgICAgIHJldHVybiBjb2xsZWN0aW9uW25dO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKFwib3V0IG9mIGJvdW5kcyBlcnJvclwiKTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICB0aHJvdyBuZXcgRXJyb3IoXCJjb2xsZWN0aW9uIGlzIG5vdCBhbiBFbnVtZXJhYmxlXCIpO1xuICB9LFxuXG4gIGZpbHRlcjogZnVuY3Rpb24gKGNvbGxlY3Rpb24sIGZ1bikge1xuICAgIGxldCByZXN1bHQgPSBbXTtcblxuICAgIGZvciAobGV0IGVsZW0gb2YgY29sbGVjdGlvbikge1xuICAgICAgaWYgKGZ1bihlbGVtKSkge1xuICAgICAgICByZXN1bHQucHVzaChlbGVtKTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICByZXR1cm4gcmVzdWx0O1xuICB9LFxuXG4gIGZpbHRlcl9tYXA6IGZ1bmN0aW9uIChjb2xsZWN0aW9uLCBmaWx0ZXIsIG1hcHBlcikge1xuICAgIHJldHVybiBFbnVtLm1hcChFbnVtLmZpbHRlcihjb2xsZWN0aW9uLCBmaWx0ZXIpLCBtYXBwZXIpO1xuICB9LFxuXG4gIGZpbmQ6IGZ1bmN0aW9uIChjb2xsZWN0aW9uLCBpZl9ub25lID0gbnVsbCwgZnVuKSB7XG4gICAgZm9yIChsZXQgZWxlbSBvZiBjb2xsZWN0aW9uKSB7XG4gICAgICBpZiAoZnVuKGVsZW0pKSB7XG4gICAgICAgIHJldHVybiBlbGVtO1xuICAgICAgfVxuICAgIH1cblxuICAgIHJldHVybiBpZl9ub25lO1xuICB9LFxuXG4gIGludG86IGZ1bmN0aW9uIChjb2xsZWN0aW9uLCBsaXN0KSB7XG4gICAgcmV0dXJuIGxpc3QuY29uY2F0KGNvbGxlY3Rpb24pO1xuICB9LFxuXG4gIG1hcDogZnVuY3Rpb24gKGNvbGxlY3Rpb24sIGZ1bikge1xuICAgIGxldCByZXN1bHQgPSBbXTtcblxuICAgIGZvciAobGV0IGVsZW0gb2YgY29sbGVjdGlvbikge1xuICAgICAgcmVzdWx0LnB1c2goZnVuKGVsZW0pKTtcbiAgICB9XG5cbiAgICByZXR1cm4gcmVzdWx0O1xuICB9LFxuXG4gIG1hcF9yZWR1Y2U6IGZ1bmN0aW9uIChjb2xsZWN0aW9uLCBhY2MsIGZ1bikge1xuICAgIGxldCBtYXBwZWQgPSBLZXJuZWwuU3BlY2lhbEZvcm1zLmxpc3QoKTtcbiAgICBsZXQgdGhlX2FjYyA9IGFjYztcblxuICAgIGZvciAodmFyIGkgPSAwOyBpIDwgdGhpcy5jb3VudChjb2xsZWN0aW9uKTsgaSsrKSB7XG4gICAgICBsZXQgdHVwbGUgPSBmdW4oY29sbGVjdGlvbltpXSwgdGhlX2FjYyk7XG5cbiAgICAgIHRoZV9hY2MgPSBLZXJuZWwuZWxlbSh0dXBsZSwgMSk7XG4gICAgICBtYXBwZWQgPSBLZXJuZWwuU3BlY2lhbEZvcm1zLmxpc3QoLi4ubWFwcGVkLmNvbmNhdChbS2VybmVsLmVsZW0odHVwbGUsIDApXSkpO1xuICAgIH1cblxuICAgIHJldHVybiBLZXJuZWwuU3BlY2lhbEZvcm1zLnR1cGxlKG1hcHBlZCwgdGhlX2FjYyk7XG4gIH0sXG5cbiAgbWVtYmVyOiBmdW5jdGlvbiAoY29sbGVjdGlvbiwgdmFsdWUpIHtcbiAgICByZXR1cm4gY29sbGVjdGlvbi5pbmNsdWRlcyh2YWx1ZSk7XG4gIH0sXG5cbiAgcmVkdWNlOiBmdW5jdGlvbiAoY29sbGVjdGlvbiwgYWNjLCBmdW4pIHtcbiAgICBsZXQgdGhlX2FjYyA9IGFjYztcblxuICAgIGZvciAodmFyIGkgPSAwOyBpIDwgdGhpcy5jb3VudChjb2xsZWN0aW9uKTsgaSsrKSB7XG4gICAgICBsZXQgdHVwbGUgPSBmdW4oY29sbGVjdGlvbltpXSwgdGhlX2FjYyk7XG5cbiAgICAgIHRoZV9hY2MgPSBLZXJuZWwuZWxlbSh0dXBsZSwgMSk7XG4gICAgfVxuXG4gICAgcmV0dXJuIHRoZV9hY2M7XG4gIH0sXG5cbiAgdGFrZTogZnVuY3Rpb24gKGNvbGxlY3Rpb24sIGNvdW50KSB7XG4gICAgcmV0dXJuIGNvbGxlY3Rpb24uc2xpY2UoMCwgY291bnQpO1xuICB9LFxuXG4gIHRha2VfZXZlcnk6IGZ1bmN0aW9uIChjb2xsZWN0aW9uLCBudGgpIHtcbiAgICBsZXQgcmVzdWx0ID0gW107XG4gICAgbGV0IGluZGV4ID0gMDtcblxuICAgIGZvciAobGV0IGVsZW0gb2YgY29sbGVjdGlvbikge1xuICAgICAgaWYgKGluZGV4ICUgbnRoID09PSAwKSB7XG4gICAgICAgIHJlc3VsdC5wdXNoKGVsZW0pO1xuICAgICAgfVxuICAgIH1cblxuICAgIHJldHVybiBLZXJuZWwuU3BlY2lhbEZvcm1zLmxpc3QoLi4ucmVzdWx0KTtcbiAgfSxcblxuICB0YWtlX3doaWxlOiBmdW5jdGlvbiAoY29sbGVjdGlvbiwgZnVuKSB7XG4gICAgbGV0IGNvdW50ID0gMDtcblxuICAgIGZvciAobGV0IGVsZW0gb2YgY29sbGVjdGlvbikge1xuICAgICAgaWYgKGZ1bihlbGVtKSkge1xuICAgICAgICBjb3VudCA9IGNvdW50ICsgMTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIGJyZWFrO1xuICAgICAgfVxuICAgIH1cblxuICAgIHJldHVybiBjb2xsZWN0aW9uLnNsaWNlKDAsIGNvdW50KTtcbiAgfSxcblxuICB0b19saXN0OiBmdW5jdGlvbiAoY29sbGVjdGlvbikge1xuICAgIHJldHVybiBjb2xsZWN0aW9uO1xuICB9XG59O1xuXG5sZXQgU3BlY2lhbEZvcm1zID0ge1xuXG4gIF9fRElSX186IGZ1bmN0aW9uICgpIHtcbiAgICBpZiAoX19kaXJuYW1lKSB7XG4gICAgICByZXR1cm4gX19kaXJuYW1lO1xuICAgIH1cblxuICAgIGlmIChkb2N1bWVudC5jdXJyZW50U2NyaXB0KSB7XG4gICAgICByZXR1cm4gZG9jdW1lbnQuY3VycmVudFNjcmlwdC5zcmM7XG4gICAgfVxuXG4gICAgcmV0dXJuIG51bGw7XG4gIH0sXG5cbiAgYXRvbTogZnVuY3Rpb24gKF92YWx1ZSkge1xuICAgIHJldHVybiBTeW1ib2wuZm9yKF92YWx1ZSk7XG4gIH0sXG5cbiAgbGlzdDogZnVuY3Rpb24gKC4uLmFyZ3MpIHtcbiAgICByZXR1cm4gT2JqZWN0LmZyZWV6ZShhcmdzKTtcbiAgfSxcblxuICBiaXRzdHJpbmc6IGZ1bmN0aW9uICguLi5hcmdzKSB7XG4gICAgcmV0dXJuIG5ldyBCaXRTdHJpbmcoLi4uYXJncyk7XG4gIH0sXG5cbiAgYm91bmQ6IGZ1bmN0aW9uIChfdmFyKSB7XG4gICAgcmV0dXJuIFBhdHRlcm5zLmJvdW5kKF92YXIpO1xuICB9LFxuXG4gIF9jYXNlOiBmdW5jdGlvbiAoY29uZGl0aW9uLCBjbGF1c2VzKSB7XG4gICAgcmV0dXJuIFBhdHRlcm5zLmRlZm1hdGNoKC4uLmNsYXVzZXMpKGNvbmRpdGlvbik7XG4gIH0sXG5cbiAgY29uZDogZnVuY3Rpb24gKGNsYXVzZXMpIHtcbiAgICBmb3IgKGxldCBjbGF1c2Ugb2YgY2xhdXNlcykge1xuICAgICAgaWYgKGNsYXVzZVswXSkge1xuICAgICAgICByZXR1cm4gY2xhdXNlWzFdKCk7XG4gICAgICB9XG4gICAgfVxuXG4gICAgdGhyb3cgbmV3IEVycm9yKCk7XG4gIH0sXG5cbiAgZm46IGZ1bmN0aW9uIChjbGF1c2VzKSB7XG4gICAgcmV0dXJuIFBhdHRlcm5zLmRlZm1hdGNoKGNsYXVzZXMpO1xuICB9LFxuXG4gIG1hcDogZnVuY3Rpb24gKG9iaikge1xuICAgIHJldHVybiBPYmplY3QuZnJlZXplKG9iaik7XG4gIH0sXG5cbiAgbWFwX3VwZGF0ZTogZnVuY3Rpb24gKG1hcCwgdmFsdWVzKSB7XG4gICAgcmV0dXJuIE9iamVjdC5mcmVlemUoT2JqZWN0LmFzc2lnbihPYmplY3QuY3JlYXRlKG1hcC5jb25zdHJ1Y3Rvci5wcm90b3R5cGUpLCBtYXAsIHZhbHVlcykpO1xuICB9LFxuXG4gIF9mb3I6IGZ1bmN0aW9uIChjb2xsZWN0aW9ucywgZnVuLCBmaWx0ZXIgPSAoKSA9PiB0cnVlLCBpbnRvID0gW10sIHByZXZpb3VzVmFsdWVzID0gW10pIHtcbiAgICBsZXQgcGF0dGVybiA9IGNvbGxlY3Rpb25zWzBdWzBdO1xuICAgIGxldCBjb2xsZWN0aW9uID0gY29sbGVjdGlvbnNbMF1bMV07XG5cbiAgICBpZiAoY29sbGVjdGlvbnMubGVuZ3RoID09PSAxKSB7XG5cbiAgICAgIGZvciAobGV0IGVsZW0gb2YgY29sbGVjdGlvbikge1xuICAgICAgICBsZXQgciA9IFBhdHRlcm5zLm1hdGNoX25vX3Rocm93KHBhdHRlcm4sIGVsZW0pO1xuICAgICAgICBsZXQgYXJncyA9IHByZXZpb3VzVmFsdWVzLmNvbmNhdChyKTtcblxuICAgICAgICBpZiAociAmJiBmaWx0ZXIuYXBwbHkodGhpcywgYXJncykpIHtcbiAgICAgICAgICBpbnRvID0gRW51bS5pbnRvKFtmdW4uYXBwbHkodGhpcywgYXJncyldLCBpbnRvKTtcbiAgICAgICAgfVxuICAgICAgfVxuXG4gICAgICByZXR1cm4gaW50bztcbiAgICB9IGVsc2Uge1xuICAgICAgbGV0IF9pbnRvID0gW107XG5cbiAgICAgIGZvciAobGV0IGVsZW0gb2YgY29sbGVjdGlvbikge1xuICAgICAgICBsZXQgciA9IFBhdHRlcm5zLm1hdGNoX25vX3Rocm93KHBhdHRlcm4sIGVsZW0pO1xuICAgICAgICBpZiAocikge1xuICAgICAgICAgIF9pbnRvID0gRW51bS5pbnRvKHRoaXMuX2Zvcihjb2xsZWN0aW9ucy5zbGljZSgxKSwgZnVuLCBmaWx0ZXIsIF9pbnRvLCBwcmV2aW91c1ZhbHVlcy5jb25jYXQocikpLCBpbnRvKTtcbiAgICAgICAgfVxuICAgICAgfVxuXG4gICAgICByZXR1cm4gX2ludG87XG4gICAgfVxuICB9LFxuXG4gIHJlY2VpdmU6IGZ1bmN0aW9uIChyZWNlaXZlX2Z1biwgdGltZW91dF9pbl9tcyA9IG51bGwsIHRpbWVvdXRfZm4gPSB0aW1lID0+IHRydWUpIHtcbiAgICBpZiAodGltZW91dF9pbl9tcyA9PSBudWxsIHx8IHRpbWVvdXRfaW5fbXMgPT09IFN5c3RlbS5mb3IoJ2luZmluaXR5JykpIHtcbiAgICAgIHdoaWxlICh0cnVlKSB7XG4gICAgICAgIGlmIChzZWxmLm1haWxib3gubGVuZ3RoICE9PSAwKSB7XG4gICAgICAgICAgbGV0IG1lc3NhZ2UgPSBzZWxmLm1haWxib3hbMF07XG4gICAgICAgICAgc2VsZi5tYWlsYm94ID0gc2VsZi5tYWlsYm94LnNsaWNlKDEpO1xuICAgICAgICAgIHJldHVybiByZWNlaXZlX2Z1bihtZXNzYWdlKTtcbiAgICAgICAgfVxuICAgICAgfVxuICAgIH0gZWxzZSBpZiAodGltZW91dF9pbl9tcyA9PT0gMCkge1xuICAgICAgaWYgKHNlbGYubWFpbGJveC5sZW5ndGggIT09IDApIHtcbiAgICAgICAgbGV0IG1lc3NhZ2UgPSBzZWxmLm1haWxib3hbMF07XG4gICAgICAgIHNlbGYubWFpbGJveCA9IHNlbGYubWFpbGJveC5zbGljZSgxKTtcbiAgICAgICAgcmV0dXJuIHJlY2VpdmVfZnVuKG1lc3NhZ2UpO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgcmV0dXJuIG51bGw7XG4gICAgICB9XG4gICAgfSBlbHNlIHtcbiAgICAgIGxldCBub3cgPSBEYXRlLm5vdygpO1xuICAgICAgd2hpbGUgKERhdGUubm93KCkgPCBub3cgKyB0aW1lb3V0X2luX21zKSB7XG4gICAgICAgIGlmIChzZWxmLm1haWxib3gubGVuZ3RoICE9PSAwKSB7XG4gICAgICAgICAgbGV0IG1lc3NhZ2UgPSBzZWxmLm1haWxib3hbMF07XG4gICAgICAgICAgc2VsZi5tYWlsYm94ID0gc2VsZi5tYWlsYm94LnNsaWNlKDEpO1xuICAgICAgICAgIHJldHVybiByZWNlaXZlX2Z1bihtZXNzYWdlKTtcbiAgICAgICAgfVxuICAgICAgfVxuXG4gICAgICByZXR1cm4gdGltZW91dF9mbih0aW1lb3V0X2luX21zKTtcbiAgICB9XG4gIH0sXG5cbiAgdHVwbGU6IGZ1bmN0aW9uICguLi5hcmdzKSB7XG4gICAgcmV0dXJuIG5ldyBUdXBsZSQxKC4uLmFyZ3MpO1xuICB9LFxuXG4gIF90cnk6IGZ1bmN0aW9uIChkb19mdW4sIHJlc2N1ZV9mdW5jdGlvbiwgY2F0Y2hfZnVuLCBlbHNlX2Z1bmN0aW9uLCBhZnRlcl9mdW5jdGlvbikge1xuICAgIGxldCByZXN1bHQgPSBudWxsO1xuXG4gICAgdHJ5IHtcbiAgICAgIHJlc3VsdCA9IGRvX2Z1bigpO1xuICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgIGxldCBleF9yZXN1bHQgPSBudWxsO1xuXG4gICAgICBpZiAocmVzY3VlX2Z1bmN0aW9uKSB7XG4gICAgICAgIHRyeSB7XG4gICAgICAgICAgZXhfcmVzdWx0ID0gcmVzY3VlX2Z1bmN0aW9uKGUpO1xuICAgICAgICAgIHJldHVybiBleF9yZXN1bHQ7XG4gICAgICAgIH0gY2F0Y2ggKGV4KSB7XG4gICAgICAgICAgaWYgKGV4IGluc3RhbmNlb2YgUGF0dGVybnMuTWF0Y2hFcnJvcikge1xuICAgICAgICAgICAgdGhyb3cgZXg7XG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICB9XG5cbiAgICAgIGlmIChjYXRjaF9mdW4pIHtcbiAgICAgICAgdHJ5IHtcbiAgICAgICAgICBleF9yZXN1bHQgPSBjYXRjaF9mdW4oZSk7XG4gICAgICAgICAgcmV0dXJuIGV4X3Jlc3VsdDtcbiAgICAgICAgfSBjYXRjaCAoZXgpIHtcbiAgICAgICAgICBpZiAoZXggaW5zdGFuY2VvZiBQYXR0ZXJucy5NYXRjaEVycm9yKSB7XG4gICAgICAgICAgICB0aHJvdyBleDtcbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgIH1cblxuICAgICAgdGhyb3cgZTtcbiAgICB9IGZpbmFsbHkge1xuICAgICAgaWYgKGFmdGVyX2Z1bmN0aW9uKSB7XG4gICAgICAgIGFmdGVyX2Z1bmN0aW9uKCk7XG4gICAgICB9XG4gICAgfVxuXG4gICAgaWYgKGVsc2VfZnVuY3Rpb24pIHtcbiAgICAgIHRyeSB7XG4gICAgICAgIHJldHVybiBlbHNlX2Z1bmN0aW9uKHJlc3VsdCk7XG4gICAgICB9IGNhdGNoIChleCkge1xuICAgICAgICBpZiAoZXggaW5zdGFuY2VvZiBQYXR0ZXJucy5NYXRjaEVycm9yKSB7XG4gICAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdObyBNYXRjaCBGb3VuZCBpbiBFbHNlJyk7XG4gICAgICAgIH1cblxuICAgICAgICB0aHJvdyBleDtcbiAgICAgIH1cbiAgICB9IGVsc2Uge1xuICAgICAgcmV0dXJuIHJlc3VsdDtcbiAgICB9XG4gIH1cblxufTtcblxuZnVuY3Rpb24gdG9fc3RyaW5nJDEodHVwbGUpIHtcbiAgcmV0dXJuIHR1cGxlLnRvU3RyaW5nKCk7XG59O1xuXG5mdW5jdGlvbiBkZWxldGVfYXQodHVwbGUsIGluZGV4KSB7XG4gIGxldCBuZXdfbGlzdCA9IFtdO1xuXG4gIGZvciAodmFyIGkgPSAwOyBpIDwgdHVwbGUuY291bnQoKTsgaSsrKSB7XG4gICAgaWYgKGkgIT09IGluZGV4KSB7XG4gICAgICBuZXdfbGlzdC5wdXNoKHR1cGxlLmdldChpKSk7XG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIEtlcm5lbC5TcGVjaWFsRm9ybXMudHVwbGUuYXBwbHkobnVsbCwgbmV3X2xpc3QpO1xufTtcblxuZnVuY3Rpb24gZHVwbGljYXRlKGRhdGEsIHNpemUpIHtcbiAgbGV0IGFycmF5ID0gW107XG5cbiAgZm9yICh2YXIgaSA9IHNpemUgLSAxOyBpID49IDA7IGktLSkge1xuICAgIGFycmF5LnB1c2goZGF0YSk7XG4gIH1cblxuICByZXR1cm4gS2VybmVsLlNwZWNpYWxGb3Jtcy50dXBsZS5hcHBseShudWxsLCBhcnJheSk7XG59O1xuXG5mdW5jdGlvbiBpbnNlcnRfYXQodHVwbGUsIGluZGV4LCB0ZXJtKSB7XG4gIGxldCBuZXdfdHVwbGUgPSBbXTtcblxuICBmb3IgKHZhciBpID0gMDsgaSA8PSB0dXBsZS5jb3VudCgpOyBpKyspIHtcbiAgICBpZiAoaSA9PT0gaW5kZXgpIHtcbiAgICAgIG5ld190dXBsZS5wdXNoKHRlcm0pO1xuICAgICAgaSsrO1xuICAgICAgbmV3X3R1cGxlLnB1c2godHVwbGUuZ2V0KGkpKTtcbiAgICB9IGVsc2Uge1xuICAgICAgbmV3X3R1cGxlLnB1c2godHVwbGUuZ2V0KGkpKTtcbiAgICB9XG4gIH1cblxuICByZXR1cm4gS2VybmVsLlNwZWNpYWxGb3Jtcy50dXBsZS5hcHBseShudWxsLCBuZXdfdHVwbGUpO1xufTtcblxuZnVuY3Rpb24gZnJvbV9saXN0KGxpc3QpIHtcbiAgcmV0dXJuIEtlcm5lbC5TcGVjaWFsRm9ybXMudHVwbGUuYXBwbHkobnVsbCwgbGlzdCk7XG59O1xuXG5mdW5jdGlvbiB0b19saXN0KHR1cGxlKSB7XG4gIGxldCBuZXdfbGlzdCA9IFtdO1xuXG4gIGZvciAodmFyIGkgPSAwOyBpIDwgdHVwbGUuY291bnQoKTsgaSsrKSB7XG4gICAgbmV3X2xpc3QucHVzaCh0dXBsZS5nZXQoaSkpO1xuICB9XG5cbiAgcmV0dXJuIEtlcm5lbC5TcGVjaWFsRm9ybXMubGlzdCguLi5uZXdfbGlzdCk7XG59O1xuXG52YXIgVHVwbGUgPSB7XG4gIHRvX3N0cmluZzogdG9fc3RyaW5nJDEsXG4gIGRlbGV0ZV9hdCxcbiAgZHVwbGljYXRlLFxuICBpbnNlcnRfYXQsXG4gIGZyb21fbGlzdCxcbiAgdG9fbGlzdFxufTtcblxuLy9odHRwczovL2dpdGh1Yi5jb20vYWlycG9ydHloL3Byb3RvbW9ycGhpc21cbmNsYXNzIFByb3RvY29sIHtcbiAgY29uc3RydWN0b3Ioc3BlYykge1xuICAgIHRoaXMucmVnaXN0cnkgPSBuZXcgTWFwKCk7XG4gICAgdGhpcy5mYWxsYmFjayA9IG51bGw7XG5cbiAgICBmb3IgKGxldCBmdW5OYW1lIGluIHNwZWMpIHtcbiAgICAgIHRoaXNbZnVuTmFtZV0gPSBjcmVhdGVGdW4oZnVuTmFtZSkuYmluZCh0aGlzKTtcbiAgICB9XG5cbiAgICBmdW5jdGlvbiBjcmVhdGVGdW4oZnVuTmFtZSkge1xuXG4gICAgICByZXR1cm4gZnVuY3Rpb24gKC4uLmFyZ3MpIHtcbiAgICAgICAgbGV0IHRoaW5nID0gYXJnc1swXTtcbiAgICAgICAgbGV0IGZ1biA9IG51bGw7XG5cbiAgICAgICAgaWYgKE51bWJlci5pc0ludGVnZXIodGhpbmcpICYmIHRoaXMuaGFzSW1wbGVtZW50YXRpb24oSW50ZWdlciQxKSkge1xuICAgICAgICAgIGZ1biA9IHRoaXMucmVnaXN0cnkuZ2V0KEludGVnZXIkMSlbZnVuTmFtZV07XG4gICAgICAgIH0gZWxzZSBpZiAodHlwZW9mIHRoaW5nID09PSBcIm51bWJlclwiICYmICFOdW1iZXIuaXNJbnRlZ2VyKHRoaW5nKSAmJiB0aGlzLmhhc0ltcGxlbWVudGF0aW9uKEZsb2F0KSkge1xuICAgICAgICAgIGZ1biA9IHRoaXMucmVnaXN0cnkuZ2V0KEZsb2F0KVtmdW5OYW1lXTtcbiAgICAgICAgfSBlbHNlIGlmICh0aGlzLmhhc0ltcGxlbWVudGF0aW9uKHRoaW5nKSkge1xuICAgICAgICAgIGZ1biA9IHRoaXMucmVnaXN0cnkuZ2V0KHRoaW5nLmNvbnN0cnVjdG9yKVtmdW5OYW1lXTtcbiAgICAgICAgfSBlbHNlIGlmICh0aGlzLmZhbGxiYWNrKSB7XG4gICAgICAgICAgZnVuID0gdGhpcy5mYWxsYmFja1tmdW5OYW1lXTtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmIChmdW4gIT0gbnVsbCkge1xuICAgICAgICAgIGxldCByZXR2YWwgPSBmdW4uYXBwbHkodGhpcywgYXJncyk7XG4gICAgICAgICAgcmV0dXJuIHJldHZhbDtcbiAgICAgICAgfVxuXG4gICAgICAgIHRocm93IG5ldyBFcnJvcihcIk5vIGltcGxlbWVudGF0aW9uIGZvdW5kIGZvciBcIiArIHRoaW5nKTtcbiAgICAgIH07XG4gICAgfVxuICB9XG5cbiAgaW1wbGVtZW50YXRpb24odHlwZSwgaW1wbGVtZW50YXRpb24pIHtcbiAgICBpZiAodHlwZSA9PT0gbnVsbCkge1xuICAgICAgdGhpcy5mYWxsYmFjayA9IGltcGxlbWVudGF0aW9uO1xuICAgIH0gZWxzZSB7XG4gICAgICB0aGlzLnJlZ2lzdHJ5LnNldCh0eXBlLCBpbXBsZW1lbnRhdGlvbik7XG4gICAgfVxuICB9XG5cbiAgaGFzSW1wbGVtZW50YXRpb24odGhpbmcpIHtcbiAgICByZXR1cm4gdGhpcy5yZWdpc3RyeS5oYXModGhpbmcuY29uc3RydWN0b3IpO1xuICB9XG59XG5cbmZ1bmN0aW9uIHRsKGxpc3QpIHtcbiAgcmV0dXJuIFNwZWNpYWxGb3Jtcy5saXN0KC4uLmxpc3Quc2xpY2UoMSkpO1xufVxuXG5mdW5jdGlvbiBoZChsaXN0KSB7XG4gIHJldHVybiBsaXN0WzBdO1xufVxuXG5mdW5jdGlvbiBpc19uaWwoeCkge1xuICByZXR1cm4geCA9PT0gbnVsbDtcbn1cblxuZnVuY3Rpb24gaXNfYXRvbSh4KSB7XG4gIHJldHVybiB0eXBlb2YgeCA9PT0gJ3N5bWJvbCc7XG59XG5cbmZ1bmN0aW9uIGlzX2JpbmFyeSh4KSB7XG4gIHJldHVybiB0eXBlb2YgeCA9PT0gJ3N0cmluZycgfHwgeCBpbnN0YW5jZW9mIFN0cmluZztcbn1cblxuZnVuY3Rpb24gaXNfYm9vbGVhbih4KSB7XG4gIHJldHVybiB0eXBlb2YgeCA9PT0gJ2Jvb2xlYW4nIHx8IHggaW5zdGFuY2VvZiBCb29sZWFuO1xufVxuXG5mdW5jdGlvbiBpc19mdW5jdGlvbih4LCBhcml0eSA9IC0xKSB7XG4gIHJldHVybiB0eXBlb2YgeCA9PT0gJ2Z1bmN0aW9uJyB8fCB4IGluc3RhbmNlb2YgRnVuY3Rpb247XG59XG5cbmZ1bmN0aW9uIGlzX2Zsb2F0KHgpIHtcbiAgcmV0dXJuIGlzX251bWJlcih4KSAmJiAhTnVtYmVyLmlzSW50ZWdlcih4KTtcbn1cblxuZnVuY3Rpb24gaXNfaW50ZWdlcih4KSB7XG4gIHJldHVybiBOdW1iZXIuaXNJbnRlZ2VyKHgpO1xufVxuXG5mdW5jdGlvbiBpc19saXN0KHgpIHtcbiAgcmV0dXJuIHggaW5zdGFuY2VvZiBBcnJheTtcbn1cblxuZnVuY3Rpb24gaXNfbWFwKHgpIHtcbiAgcmV0dXJuIHR5cGVvZiB4ID09PSAnb2JqZWN0JyB8fCB4IGluc3RhbmNlb2YgT2JqZWN0O1xufVxuXG5mdW5jdGlvbiBpc19udW1iZXIoeCkge1xuICByZXR1cm4gdHlwZW9mIHggPT09ICdudW1iZXInO1xufVxuXG5mdW5jdGlvbiBpc190dXBsZSh4KSB7XG4gIHJldHVybiB4IGluc3RhbmNlb2YgVHVwbGUkMTtcbn1cblxuZnVuY3Rpb24gbGVuZ3RoKHgpIHtcbiAgcmV0dXJuIHgubGVuZ3RoO1xufVxuXG5mdW5jdGlvbiBpc19waWQoeCkge1xuICByZXR1cm4geCBpbnN0YW5jZW9mIFBJRDtcbn1cblxuZnVuY3Rpb24gaXNfcG9ydCh4KSB7XG4gIHJldHVybiBmYWxzZTtcbn1cblxuZnVuY3Rpb24gaXNfcmVmZXJlbmNlKHgpIHtcbiAgcmV0dXJuIGZhbHNlO1xufVxuXG5mdW5jdGlvbiBpc19iaXRzdHJpbmcoeCkge1xuICByZXR1cm4gaXNfYmluYXJ5KHgpIHx8IHggaW5zdGFuY2VvZiBCaXRTdHJpbmc7XG59XG5cbmZ1bmN0aW9uIF9faW5fXyhsZWZ0LCByaWdodCkge1xuICBmb3IgKGxldCB4IG9mIHJpZ2h0KSB7XG4gICAgaWYgKG1hdGNoX19xbWFya19fKGxlZnQsIHgpKSB7XG4gICAgICByZXR1cm4gdHJ1ZTtcbiAgICB9XG4gIH1cblxuICByZXR1cm4gZmFsc2U7XG59XG5cbmZ1bmN0aW9uIGFicyhudW1iZXIpIHtcbiAgcmV0dXJuIE1hdGguYWJzKG51bWJlcik7XG59XG5cbmZ1bmN0aW9uIHJvdW5kKG51bWJlcikge1xuICByZXR1cm4gTWF0aC5yb3VuZChudW1iZXIpO1xufVxuXG5mdW5jdGlvbiBlbGVtKHR1cGxlLCBpbmRleCkge1xuICBpZiAoaXNfbGlzdCh0dXBsZSkpIHtcbiAgICByZXR1cm4gdHVwbGVbaW5kZXhdO1xuICB9XG5cbiAgcmV0dXJuIHR1cGxlLmdldChpbmRleCk7XG59XG5cbmZ1bmN0aW9uIHJlbShsZWZ0LCByaWdodCkge1xuICByZXR1cm4gbGVmdCAlIHJpZ2h0O1xufVxuXG5mdW5jdGlvbiBkaXYobGVmdCwgcmlnaHQpIHtcbiAgcmV0dXJuIGxlZnQgLyByaWdodDtcbn1cblxuZnVuY3Rpb24gYW5kKGxlZnQsIHJpZ2h0KSB7XG4gIHJldHVybiBsZWZ0ICYmIHJpZ2h0O1xufVxuXG5mdW5jdGlvbiBvcihsZWZ0LCByaWdodCkge1xuICByZXR1cm4gbGVmdCB8fCByaWdodDtcbn1cblxuZnVuY3Rpb24gbm90KGFyZykge1xuICByZXR1cm4gIWFyZztcbn1cblxuZnVuY3Rpb24gYXBwbHkoLi4uYXJncykge1xuICBpZiAoYXJncy5sZW5ndGggPT09IDMpIHtcbiAgICBsZXQgbW9kID0gYXJnc1swXTtcbiAgICBsZXQgZnVuYyA9IGFyZ3NbMV07XG4gICAgbGV0IGZ1bmNfYXJncyA9IGFyZ3NbMl07XG4gICAgcmV0dXJuIG1vZFtmdW5jXS5hcHBseShudWxsLCBmdW5jX2FyZ3MpO1xuICB9IGVsc2Uge1xuICAgIGxldCBmdW5jID0gYXJnc1swXTtcbiAgICBsZXQgZnVuY19hcmdzID0gYXJnc1sxXTtcblxuICAgIHJldHVybiBmdW5jLmFwcGx5KG51bGwsIGZ1bmNfYXJncyk7XG4gIH1cbn1cblxuZnVuY3Rpb24gdG9fc3RyaW5nKGFyZykge1xuICBpZiAoaXNfdHVwbGUoYXJnKSkge1xuICAgIHJldHVybiBUdXBsZS50b19zdHJpbmcoYXJnKTtcbiAgfVxuXG4gIHJldHVybiBhcmcudG9TdHJpbmcoKTtcbn1cblxuZnVuY3Rpb24gbWF0Y2hfX3FtYXJrX18ocGF0dGVybiwgZXhwciwgZ3VhcmQgPSAoKSA9PiB0cnVlKSB7XG4gIHJldHVybiBQYXR0ZXJucy5tYXRjaF9ub190aHJvdyhwYXR0ZXJuLCBleHByLCBndWFyZCkgIT0gbnVsbDtcbn1cblxuZnVuY3Rpb24gZGVmc3RydWN0KGRlZmF1bHRzKSB7XG4gIHJldHVybiBjbGFzcyB7XG4gICAgY29uc3RydWN0b3IodXBkYXRlID0ge30pIHtcbiAgICAgIGxldCB0aGVfdmFsdWVzID0gT2JqZWN0LmFzc2lnbihkZWZhdWx0cywgdXBkYXRlKTtcbiAgICAgIE9iamVjdC5hc3NpZ24odGhpcywgdGhlX3ZhbHVlcyk7XG4gICAgfVxuXG4gICAgc3RhdGljIGNyZWF0ZSh1cGRhdGVzID0ge30pIHtcbiAgICAgIGxldCB4ID0gbmV3IHRoaXModXBkYXRlcyk7XG4gICAgICByZXR1cm4gT2JqZWN0LmZyZWV6ZSh4KTtcbiAgICB9XG4gIH07XG59XG5cbmZ1bmN0aW9uIGRlZnByb3RvY29sKHNwZWMpIHtcbiAgcmV0dXJuIG5ldyBQcm90b2NvbChzcGVjKTtcbn1cblxuZnVuY3Rpb24gZGVmaW1wbChwcm90b2NvbCwgdHlwZSwgaW1wbCkge1xuICBwcm90b2NvbC5pbXBsZW1lbnRhdGlvbih0eXBlLCBpbXBsKTtcbn1cblxudmFyIEtlcm5lbCA9IHtcbiAgU3BlY2lhbEZvcm1zLFxuICB0bCxcbiAgaGQsXG4gIGlzX25pbCxcbiAgaXNfYXRvbSxcbiAgaXNfYmluYXJ5LFxuICBpc19ib29sZWFuLFxuICBpc19mdW5jdGlvbixcbiAgaXNfZmxvYXQsXG4gIGlzX2ludGVnZXIsXG4gIGlzX2xpc3QsXG4gIGlzX21hcCxcbiAgaXNfbnVtYmVyLFxuICBpc190dXBsZSxcbiAgbGVuZ3RoLFxuICBpc19waWQsXG4gIGlzX3BvcnQsXG4gIGlzX3JlZmVyZW5jZSxcbiAgaXNfYml0c3RyaW5nLFxuICBpbjogX19pbl9fLFxuICBhYnMsXG4gIHJvdW5kLFxuICBlbGVtLFxuICByZW0sXG4gIGRpdixcbiAgYW5kLFxuICBvcixcbiAgbm90LFxuICBhcHBseSxcbiAgdG9fc3RyaW5nLFxuICBtYXRjaF9fcW1hcmtfXyxcbiAgZGVmc3RydWN0LFxuICBkZWZwcm90b2NvbCxcbiAgZGVmaW1wbFxufTtcblxubGV0IEF0b20gPSB7fTtcblxuQXRvbS50b19zdHJpbmcgPSBmdW5jdGlvbiAoYXRvbSkge1xuICByZXR1cm4gU3ltYm9sLmtleUZvcihhdG9tKTtcbn07XG5cbkF0b20udG9fY2hhcl9saXN0ID0gZnVuY3Rpb24gKGF0b20pIHtcbiAgcmV0dXJuIEF0b20udG9fc3RyaW5nKGF0b20pLnNwbGl0KCcnKTtcbn07XG5cbmxldCBJbnRlZ2VyID0ge1xuXG4gIGlzX2V2ZW46IGZ1bmN0aW9uIChuKSB7XG4gICAgcmV0dXJuIG4gJSAyID09PSAwO1xuICB9LFxuXG4gIGlzX29kZDogZnVuY3Rpb24gKG4pIHtcbiAgICByZXR1cm4gbiAlIDIgIT09IDA7XG4gIH0sXG5cbiAgcGFyc2U6IGZ1bmN0aW9uIChiaW4pIHtcbiAgICBsZXQgcmVzdWx0ID0gcGFyc2VJbnQoYmluKTtcblxuICAgIGlmIChpc05hTihyZXN1bHQpKSB7XG4gICAgICByZXR1cm4gS2VybmVsLlNwZWNpYWxGb3Jtcy5hdG9tKFwiZXJyb3JcIik7XG4gICAgfVxuXG4gICAgbGV0IGluZGV4T2ZEb3QgPSBiaW4uaW5kZXhPZihcIi5cIik7XG5cbiAgICBpZiAoaW5kZXhPZkRvdCA+PSAwKSB7XG4gICAgICByZXR1cm4gS2VybmVsLlNwZWNpYWxGb3Jtcy50dXBsZShyZXN1bHQsIGJpbi5zdWJzdHJpbmcoaW5kZXhPZkRvdCkpO1xuICAgIH1cblxuICAgIHJldHVybiBLZXJuZWwuU3BlY2lhbEZvcm1zLnR1cGxlKHJlc3VsdCwgXCJcIik7XG4gIH0sXG5cbiAgdG9fY2hhcl9saXN0OiBmdW5jdGlvbiAobnVtYmVyLCBiYXNlID0gMTApIHtcbiAgICByZXR1cm4gbnVtYmVyLnRvU3RyaW5nKGJhc2UpLnNwbGl0KFwiXCIpO1xuICB9LFxuXG4gIHRvX3N0cmluZzogZnVuY3Rpb24gKG51bWJlciwgYmFzZSA9IDEwKSB7XG4gICAgcmV0dXJuIG51bWJlci50b1N0cmluZyhiYXNlKTtcbiAgfVxufTtcblxubGV0IENoYXJzJDEgPSBLZXJuZWwuZGVmcHJvdG9jb2woe1xuICB0b19zdHJpbmc6IGZ1bmN0aW9uICh0aGluZykge31cbn0pO1xuXG5LZXJuZWwuZGVmaW1wbChDaGFycyQxLCBCaXRTdHJpbmcsIHtcbiAgdG9fc3RyaW5nOiBmdW5jdGlvbiAodGhpbmcpIHtcbiAgICBpZiAoS2VybmVsLmlzX2JpbmFyeSh0aGluZykpIHtcbiAgICAgIHJldHVybiB0aGluZztcbiAgICB9XG5cbiAgICByZXR1cm4gdGhpbmcudG9TdHJpbmcoKTtcbiAgfVxufSk7XG5cbktlcm5lbC5kZWZpbXBsKENoYXJzJDEsIFN5bWJvbCwge1xuICB0b19zdHJpbmc6IGZ1bmN0aW9uICh0aGluZykge1xuICAgIGlmIChuaWwpIHtcbiAgICAgIHJldHVybiBcIlwiO1xuICAgIH1cblxuICAgIHJldHVybiBBdG9tLnRvX3N0cmluZyh0aGluZyk7XG4gIH1cbn0pO1xuXG5LZXJuZWwuZGVmaW1wbChDaGFycyQxLCBJbnRlZ2VyJDEsIHtcbiAgdG9fc3RyaW5nOiBmdW5jdGlvbiAodGhpbmcpIHtcbiAgICByZXR1cm4gSW50ZWdlci50b19zdHJpbmcodGhpbmcpO1xuICB9XG59KTtcblxuS2VybmVsLmRlZmltcGwoQ2hhcnMkMSwgRmxvYXQsIHtcbiAgdG9fc3RyaW5nOiBmdW5jdGlvbiAodGhpbmcpIHtcbiAgICByZXR1cm4gdGhpbmcudG9TdHJpbmc7XG4gIH1cbn0pO1xuXG5LZXJuZWwuZGVmaW1wbChDaGFycyQxLCBBcnJheSwge1xuICB0b19zdHJpbmc6IGZ1bmN0aW9uICh0aGluZykge1xuICAgIHJldHVybiB0aGluZy50b1N0cmluZygpO1xuICB9XG59KTtcblxuS2VybmVsLmRlZmltcGwoQ2hhcnMkMSwgVHVwbGUkMSwge1xuICB0b19zdHJpbmc6IGZ1bmN0aW9uICh0aGluZykge1xuICAgIHJldHVybiBUdXBsZS50b19zdHJpbmcodGhpbmcpO1xuICB9XG59KTtcblxuS2VybmVsLmRlZmltcGwoQ2hhcnMkMSwgbnVsbCwge1xuICB0b19zdHJpbmc6IGZ1bmN0aW9uICh0aGluZykge1xuICAgIHJldHVybiB0aGluZy50b1N0cmluZygpO1xuICB9XG59KTtcblxuZnVuY3Rpb24gdG9fYXRvbShzdHJpbmcpIHtcbiAgcmV0dXJuIFN5bWJvbC5mb3Ioc3RyaW5nKTtcbn1cblxuZnVuY3Rpb24gdG9fZXhpc3RpbmdfYXRvbShzdHJpbmcpIHtcbiAgcmV0dXJuIFN5bWJvbC5mb3Ioc3RyaW5nKTtcbn1cblxuZnVuY3Rpb24gdG9fY2hhcl9saXN0KHN0cmluZykge1xuICByZXR1cm4gc3RyaW5nLnNwbGl0KCcnKTtcbn1cblxuZnVuY3Rpb24gdG9fZmxvYXQoc3RyaW5nKSB7XG4gIHJldHVybiBwYXJzZUZsb2F0KHN0cmluZyk7XG59XG5cbmZ1bmN0aW9uIHRvX2ludGVnZXIoc3RyaW5nLCBiYXNlID0gMTApIHtcbiAgcmV0dXJuIHBhcnNlSW50KHN0cmluZywgYmFzZSk7XG59XG5cbmZ1bmN0aW9uIHVwY2FzZShiaW5hcnkpIHtcbiAgcmV0dXJuIGJpbmFyeS50b1VwcGVyQ2FzZSgpO1xufVxuXG5mdW5jdGlvbiBkb3duY2FzZShiaW5hcnkpIHtcbiAgcmV0dXJuIGJpbmFyeS50b0xvd2VyQ2FzZSgpO1xufVxuXG5mdW5jdGlvbiBhdChzdHJpbmcsIHBvc2l0aW9uKSB7XG4gIGlmIChwb3NpdGlvbiA+IHN0cmluZy5sZW5ndGggLSAxKSB7XG4gICAgcmV0dXJuIG51bGw7XG4gIH1cblxuICByZXR1cm4gc3RyaW5nW3Bvc2l0aW9uXTtcbn1cblxuZnVuY3Rpb24gY2FwaXRhbGl6ZShzdHJpbmcpIHtcbiAgbGV0IHJldHVyblN0cmluZyA9ICcnO1xuXG4gIGZvciAobGV0IGkgPSAwOyBpIDwgc3RyaW5nLmxlbmd0aDsgaSsrKSB7XG4gICAgaWYgKGkgPT09IDApIHtcbiAgICAgIHJldHVyblN0cmluZyA9IHJldHVyblN0cmluZyArIHN0cmluZ1tpXS50b1VwcGVyQ2FzZSgpO1xuICAgIH0gZWxzZSB7XG4gICAgICByZXR1cm5TdHJpbmcgPSByZXR1cm5TdHJpbmcgKyBzdHJpbmdbaV0udG9Mb3dlckNhc2UoKTtcbiAgICB9XG4gIH1cblxuICByZXR1cm4gcmV0dXJuU3RyaW5nO1xufVxuXG5mdW5jdGlvbiBjb2RlcG9pbnRzKHN0cmluZykge1xuICByZXR1cm4gdG9fY2hhcl9saXN0KHN0cmluZykubWFwKGZ1bmN0aW9uIChjKSB7XG4gICAgcmV0dXJuIGMuY29kZVBvaW50QXQoMCk7XG4gIH0pO1xufVxuXG5mdW5jdGlvbiBjb250YWluc19fcW1fXyhzdHJpbmcsIGNvbnRhaW5zKSB7XG4gIGlmIChBcnJheS5pc0FycmF5KGNvbnRhaW5zKSkge1xuICAgIHJldHVybiBjb250YWlucy5zb21lKGZ1bmN0aW9uIChzKSB7XG4gICAgICByZXR1cm4gc3RyaW5nLmluZGV4T2YocykgPiAtMTtcbiAgICB9KTtcbiAgfVxuXG4gIHJldHVybiBzdHJpbmcuaW5kZXhPZihjb250YWlucykgPiAtMTtcbn1cblxuZnVuY3Rpb24gZHVwbGljYXRlJDEoc3ViamVjdCwgbikge1xuICByZXR1cm4gc3ViamVjdC5yZXBlYXQobik7XG59XG5cbmZ1bmN0aW9uIGVuZHNfd2l0aF9fcW1fXyhzdHJpbmcsIHN1ZmZpeGVzKSB7XG4gIGlmIChBcnJheS5pc0FycmF5KHN1ZmZpeGVzKSkge1xuICAgIHJldHVybiBzdWZmaXhlcy5zb21lKGZ1bmN0aW9uIChzKSB7XG4gICAgICByZXR1cm4gc3RyaW5nLmVuZHNXaXRoKHMpO1xuICAgIH0pO1xuICB9XG5cbiAgcmV0dXJuIHN0cmluZy5lbmRzV2l0aChzdWZmaXhlcyk7XG59XG5cbmZ1bmN0aW9uIGZpcnN0KHN0cmluZykge1xuICBpZiAoIXN0cmluZykge1xuICAgIHJldHVybiBudWxsO1xuICB9XG5cbiAgcmV0dXJuIHN0cmluZ1swXTtcbn1cblxuZnVuY3Rpb24gZ3JhcGhlbWVzKHN0cmluZykge1xuICByZXR1cm4gc3RyaW5nLnNwbGl0KCcnKTtcbn1cblxuZnVuY3Rpb24gbGFzdChzdHJpbmcpIHtcbiAgaWYgKCFzdHJpbmcpIHtcbiAgICByZXR1cm4gbnVsbDtcbiAgfVxuXG4gIHJldHVybiBzdHJpbmdbc3RyaW5nLmxlbmd0aCAtIDFdO1xufVxuXG5mdW5jdGlvbiBsZW5ndGgkMShzdHJpbmcpIHtcbiAgcmV0dXJuIHN0cmluZy5sZW5ndGg7XG59XG5cbmZ1bmN0aW9uIG1hdGNoX19xbV9fKHN0cmluZywgcmVnZXgpIHtcbiAgcmV0dXJuIHN0cmluZy5tYXRjaChyZWdleCkgIT0gbnVsbDtcbn1cblxuZnVuY3Rpb24gbmV4dF9jb2RlcG9pbnQoc3RyaW5nKSB7XG4gIGlmICghc3RyaW5nIHx8IHN0cmluZyA9PT0gJycpIHtcbiAgICByZXR1cm4gbnVsbDtcbiAgfVxuXG4gIHJldHVybiBLZXJuZWwuU3BlY2lhbEZvcm1zLnR1cGxlKHN0cmluZ1swXS5jb2RlUG9pbnRBdCgwKSwgc3RyaW5nLnN1YnN0cigxKSk7XG59XG5cbmZ1bmN0aW9uIG5leHRfZ3JhcGhlbWUoc3RyaW5nKSB7XG4gIGlmICghc3RyaW5nIHx8IHN0cmluZyA9PT0gJycpIHtcbiAgICByZXR1cm4gbnVsbDtcbiAgfVxuXG4gIHJldHVybiBLZXJuZWwuU3BlY2lhbEZvcm1zLnR1cGxlKHN0cmluZ1swXSwgc3RyaW5nLnN1YnN0cigxKSk7XG59XG5cbmZ1bmN0aW9uIHJldmVyc2Uoc3RyaW5nKSB7XG4gIGxldCByZXR1cm5WYWx1ZSA9ICcnO1xuXG4gIGZvciAodmFyIGkgPSBzdHJpbmcubGVuZ3RoIC0gMTsgaSA+PSAwOyBpLS0pIHtcbiAgICByZXR1cm5WYWx1ZSA9IHJldHVyblZhbHVlICsgc3RyaW5nW2ldO1xuICB9O1xuXG4gIHJldHVybiByZXR1cm5WYWx1ZTtcbn1cblxuZnVuY3Rpb24gc3BsaXQoc3RyaW5nKSB7XG4gIHJldHVybiBzdHJpbmcuc3BsaXQoKTtcbn1cblxuZnVuY3Rpb24gc3RhcnRzX3dpdGhfX3FtX18oc3RyaW5nLCBwcmVmaXhlcykge1xuICBpZiAoQXJyYXkuaXNBcnJheShwcmVmaXhlcykpIHtcbiAgICByZXR1cm4gcHJlZml4ZXMuc29tZShmdW5jdGlvbiAocykge1xuICAgICAgcmV0dXJuIHN0cmluZy5zdGFydHNXaXRoKHMpO1xuICAgIH0pO1xuICB9XG5cbiAgcmV0dXJuIHN0cmluZy5zdGFydHNXaXRoKHByZWZpeGVzKTtcbn1cblxuZnVuY3Rpb24gdmFsaWRfY2hhcmFjdGVyX19xbV9fKGNvZGVwb2ludCkge1xuICB0cnkge1xuICAgIHJldHVybiBTdHJpbmcuZnJvbUNvZGVQb2ludChjb2RlcG9pbnQpICE9IG51bGw7XG4gIH0gY2F0Y2ggKGUpIHtcbiAgICByZXR1cm4gZmFsc2U7XG4gIH1cbn1cblxudmFyIFN0cmluZyQxID0ge1xuICBhdCxcbiAgY2FwaXRhbGl6ZSxcbiAgY29kZXBvaW50cyxcbiAgY29udGFpbnNfX3FtX18sXG4gIGRvd25jYXNlLFxuICBkdXBsaWNhdGU6IGR1cGxpY2F0ZSQxLFxuICBlbmRzX3dpdGhfX3FtX18sXG4gIGZpcnN0LFxuICBncmFwaGVtZXMsXG4gIGxhc3QsXG4gIGxlbmd0aDogbGVuZ3RoJDEsXG4gIG1hdGNoX19xbV9fLFxuICBuZXh0X2NvZGVwb2ludCxcbiAgbmV4dF9ncmFwaGVtZSxcbiAgcmV2ZXJzZSxcbiAgc3BsaXQsXG4gIHN0YXJ0c193aXRoX19xbV9fLFxuICB0b19hdG9tLFxuICB0b19jaGFyX2xpc3QsXG4gIHRvX2V4aXN0aW5nX2F0b20sXG4gIHRvX2Zsb2F0LFxuICB0b19pbnRlZ2VyLFxuICB1cGNhc2UsXG4gIHZhbGlkX2NoYXJhY3Rlcl9fcW1fXyxcbiAgQ2hhcnM6IENoYXJzJDFcbn07XG5cbmxldCBDaGFycyA9IEtlcm5lbC5kZWZwcm90b2NvbCh7XG4gIHRvX2NoYXJfbGlzdDogZnVuY3Rpb24gKHRoaW5nKSB7fVxufSk7XG5cbktlcm5lbC5kZWZpbXBsKENoYXJzLCBCaXRTdHJpbmcsIHtcbiAgdG9fY2hhcl9saXN0OiBmdW5jdGlvbiAodGhpbmcpIHtcbiAgICBpZiAoS2VybmVsLmlzX2JpbmFyeSh0aGluZykpIHtcbiAgICAgIHJldHVybiBTdHJpbmckMS50b19jaGFyX2xpc3QodGhpbmcpO1xuICAgIH1cblxuICAgIHJldHVybiB0aGluZy50b1N0cmluZygpO1xuICB9XG59KTtcblxuS2VybmVsLmRlZmltcGwoQ2hhcnMsIFN5bWJvbCwge1xuICB0b19jaGFyX2xpc3Q6IGZ1bmN0aW9uICh0aGluZykge1xuICAgIHJldHVybiBBdG9tLnRvX2NoYXJfbGlzdCh0aGluZyk7XG4gIH1cbn0pO1xuXG5LZXJuZWwuZGVmaW1wbChDaGFycywgSW50ZWdlciQxLCB7XG4gIHRvX2NoYXJfbGlzdDogZnVuY3Rpb24gKHRoaW5nKSB7XG4gICAgcmV0dXJuIEludGVnZXIudG9fY2hhcl9saXN0KHRoaW5nKTtcbiAgfVxufSk7XG5cbktlcm5lbC5kZWZpbXBsKENoYXJzLCBBcnJheSwge1xuICB0b19jaGFyX2xpc3Q6IGZ1bmN0aW9uICh0aGluZykge1xuICAgIHJldHVybiB0aGluZztcbiAgfVxufSk7XG5cbmxldCBMaXN0ID0ge307XG5cbkxpc3QuQ2hhcnMgPSBDaGFycztcblxuTGlzdC5kZWxldGUgPSBmdW5jdGlvbiAobGlzdCwgaXRlbSkge1xuICBsZXQgbmV3X3ZhbHVlID0gW107XG4gIGxldCB2YWx1ZV9mb3VuZCA9IGZhbHNlO1xuXG4gIGZvciAobGV0IHggb2YgbGlzdCkge1xuICAgIGlmICh4ID09PSBpdGVtICYmIHZhbHVlX2ZvdW5kICE9PSBmYWxzZSkge1xuICAgICAgbmV3X3ZhbHVlLnB1c2goeCk7XG4gICAgICB2YWx1ZV9mb3VuZCA9IHRydWU7XG4gICAgfSBlbHNlIGlmICh4ICE9PSBpdGVtKSB7XG4gICAgICBuZXdfdmFsdWUucHVzaCh4KTtcbiAgICB9XG4gIH1cblxuICByZXR1cm4gS2VybmVsLlNwZWNpYWxGb3Jtcy5saXN0KC4uLm5ld192YWx1ZSk7XG59O1xuXG5MaXN0LmRlbGV0ZV9hdCA9IGZ1bmN0aW9uIChsaXN0LCBpbmRleCkge1xuICBsZXQgbmV3X3ZhbHVlID0gW107XG5cbiAgZm9yIChsZXQgaSA9IDA7IGkgPCBsaXN0Lmxlbmd0aDsgaSsrKSB7XG4gICAgaWYgKGkgIT09IGluZGV4KSB7XG4gICAgICBuZXdfdmFsdWUucHVzaChsaXN0W2ldKTtcbiAgICB9XG4gIH1cblxuICByZXR1cm4gS2VybmVsLlNwZWNpYWxGb3Jtcy5saXN0KC4uLm5ld192YWx1ZSk7XG59O1xuXG5MaXN0LmR1cGxpY2F0ZSA9IGZ1bmN0aW9uIChlbGVtLCBuKSB7XG4gIGxldCBuZXdfdmFsdWUgPSBbXTtcblxuICBmb3IgKHZhciBpID0gMDsgaSA8IG47IGkrKykge1xuICAgIG5ld192YWx1ZS5wdXNoKGVsZW0pO1xuICB9XG5cbiAgcmV0dXJuIEtlcm5lbC5TcGVjaWFsRm9ybXMubGlzdCguLi5uZXdfdmFsdWUpO1xufTtcblxuTGlzdC5maXJzdCA9IGZ1bmN0aW9uIChsaXN0KSB7XG4gIHJldHVybiBsaXN0WzBdO1xufTtcblxuTGlzdC5mbGF0dGVuID0gZnVuY3Rpb24gKGxpc3QsIHRhaWwgPSBLZXJuZWwuU3BlY2lhbEZvcm1zLmxpc3QoKSkge1xuICBsZXQgbmV3X3ZhbHVlID0gW107XG5cbiAgZm9yIChsZXQgeCBvZiBsaXN0KSB7XG4gICAgaWYgKEtlcm5lbC5pc19saXN0KHgpKSB7XG4gICAgICBuZXdfdmFsdWUgPSBuZXdfdmFsdWUuY29uY2F0KExpc3QuZmxhdHRlbih4KSk7XG4gICAgfSBlbHNlIHtcbiAgICAgIG5ld192YWx1ZS5wdXNoKHgpO1xuICAgIH1cbiAgfVxuXG4gIG5ld192YWx1ZSA9IG5ld192YWx1ZS5jb25jYXQodGFpbCk7XG5cbiAgcmV0dXJuIEtlcm5lbC5TcGVjaWFsRm9ybXMubGlzdCguLi5uZXdfdmFsdWUpO1xufTtcblxuTGlzdC5mb2xkbCA9IGZ1bmN0aW9uIChsaXN0LCBhY2MsIGZ1bmMpIHtcbiAgcmV0dXJuIGxpc3QucmVkdWNlKGZ1bmMsIGFjYyk7XG59O1xuXG5MaXN0LmZvbGRyID0gZnVuY3Rpb24gKGxpc3QsIGFjYywgZnVuYykge1xuICBsZXQgbmV3X2FjYyA9IGFjYztcblxuICBmb3IgKHZhciBpID0gbGlzdC5sZW5ndGggLSAxOyBpID49IDA7IGktLSkge1xuICAgIG5ld19hY2MgPSBmdW5jKGxpc3RbaV0sIG5ld19hY2MpO1xuICB9XG5cbiAgcmV0dXJuIG5ld19hY2M7XG59O1xuXG5MaXN0Lmluc2VydF9hdCA9IGZ1bmN0aW9uIChsaXN0LCBpbmRleCwgdmFsdWUpIHtcbiAgbGV0IG5ld192YWx1ZSA9IFtdO1xuXG4gIGZvciAobGV0IGkgPSAwOyBpIDwgbGlzdC5sZW5ndGg7IGkrKykge1xuICAgIGlmIChpID09PSBpbmRleCkge1xuICAgICAgbmV3X3ZhbHVlLnB1c2godmFsdWUpO1xuICAgICAgbmV3X3ZhbHVlLnB1c2gobGlzdFtpXSk7XG4gICAgfSBlbHNlIHtcbiAgICAgIG5ld192YWx1ZS5wdXNoKGxpc3RbaV0pO1xuICAgIH1cbiAgfVxuXG4gIHJldHVybiBLZXJuZWwuU3BlY2lhbEZvcm1zLmxpc3QoLi4ubmV3X3ZhbHVlKTtcbn07XG5cbkxpc3Qua2V5ZGVsZXRlID0gZnVuY3Rpb24gKGxpc3QsIGtleSwgcG9zaXRpb24pIHtcbiAgbGV0IG5ld19saXN0ID0gW107XG5cbiAgZm9yIChsZXQgaSA9IDA7IGkgPCBsaXN0Lmxlbmd0aDsgaSsrKSB7XG4gICAgaWYgKCFLZXJuZWwubWF0Y2hfX3FtYXJrX18obGlzdFtpXVtwb3NpdGlvbl0sIGtleSkpIHtcbiAgICAgIG5ld19saXN0LnB1c2gobGlzdFtpXSk7XG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIEtlcm5lbC5TcGVjaWFsRm9ybXMubGlzdCguLi5uZXdfbGlzdCk7XG59O1xuXG5MaXN0LmtleWZpbmQgPSBmdW5jdGlvbiAobGlzdCwga2V5LCBwb3NpdGlvbiwgX2RlZmF1bHQgPSBudWxsKSB7XG5cbiAgZm9yIChsZXQgaSA9IDA7IGkgPCBsaXN0Lmxlbmd0aDsgaSsrKSB7XG4gICAgaWYgKEtlcm5lbC5tYXRjaF9fcW1hcmtfXyhsaXN0W2ldW3Bvc2l0aW9uXSwga2V5KSkge1xuICAgICAgcmV0dXJuIGxpc3RbaV07XG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIF9kZWZhdWx0O1xufTtcblxuTGlzdC5rZXltZW1iZXJfX3FtYXJrX18gPSBmdW5jdGlvbiAobGlzdCwga2V5LCBwb3NpdGlvbikge1xuXG4gIGZvciAobGV0IGkgPSAwOyBpIDwgbGlzdC5sZW5ndGg7IGkrKykge1xuICAgIGlmIChLZXJuZWwubWF0Y2hfX3FtYXJrX18obGlzdFtpXVtwb3NpdGlvbl0sIGtleSkpIHtcbiAgICAgIHJldHVybiB0cnVlO1xuICAgIH1cbiAgfVxuXG4gIHJldHVybiBmYWxzZTtcbn07XG5cbkxpc3Qua2V5cmVwbGFjZSA9IGZ1bmN0aW9uIChsaXN0LCBrZXksIHBvc2l0aW9uLCBuZXdfdHVwbGUpIHtcbiAgbGV0IG5ld19saXN0ID0gW107XG5cbiAgZm9yIChsZXQgaSA9IDA7IGkgPCBsaXN0Lmxlbmd0aDsgaSsrKSB7XG4gICAgaWYgKCFLZXJuZWwubWF0Y2hfX3FtYXJrX18obGlzdFtpXVtwb3NpdGlvbl0sIGtleSkpIHtcbiAgICAgIG5ld19saXN0LnB1c2gobGlzdFtpXSk7XG4gICAgfSBlbHNlIHtcbiAgICAgIG5ld19saXN0LnB1c2gobmV3X3R1cGxlKTtcbiAgICB9XG4gIH1cblxuICByZXR1cm4gS2VybmVsLlNwZWNpYWxGb3Jtcy5saXN0KC4uLm5ld19saXN0KTtcbn07XG5cbkxpc3Qua2V5c29ydCA9IGZ1bmN0aW9uIChsaXN0LCBwb3NpdGlvbikge1xuICBsZXQgbmV3X2xpc3QgPSBsaXN0O1xuXG4gIG5ld19saXN0LnNvcnQoZnVuY3Rpb24gKGEsIGIpIHtcbiAgICBpZiAocG9zaXRpb24gPT09IDApIHtcbiAgICAgIGlmIChhW3Bvc2l0aW9uXS52YWx1ZSA8IGJbcG9zaXRpb25dLnZhbHVlKSB7XG4gICAgICAgIHJldHVybiAtMTtcbiAgICAgIH1cblxuICAgICAgaWYgKGFbcG9zaXRpb25dLnZhbHVlID4gYltwb3NpdGlvbl0udmFsdWUpIHtcbiAgICAgICAgcmV0dXJuIDE7XG4gICAgICB9XG5cbiAgICAgIHJldHVybiAwO1xuICAgIH0gZWxzZSB7XG4gICAgICBpZiAoYVtwb3NpdGlvbl0gPCBiW3Bvc2l0aW9uXSkge1xuICAgICAgICByZXR1cm4gLTE7XG4gICAgICB9XG5cbiAgICAgIGlmIChhW3Bvc2l0aW9uXSA+IGJbcG9zaXRpb25dKSB7XG4gICAgICAgIHJldHVybiAxO1xuICAgICAgfVxuXG4gICAgICByZXR1cm4gMDtcbiAgICB9XG4gIH0pO1xuXG4gIHJldHVybiBLZXJuZWwuU3BlY2lhbEZvcm1zLmxpc3QoLi4ubmV3X2xpc3QpO1xufTtcblxuTGlzdC5rZXlzdG9yZSA9IGZ1bmN0aW9uIChsaXN0LCBrZXksIHBvc2l0aW9uLCBuZXdfdHVwbGUpIHtcbiAgbGV0IG5ld19saXN0ID0gW107XG4gIGxldCByZXBsYWNlZCA9IGZhbHNlO1xuXG4gIGZvciAobGV0IGkgPSAwOyBpIDwgbGlzdC5sZW5ndGg7IGkrKykge1xuICAgIGlmICghS2VybmVsLm1hdGNoX19xbWFya19fKGxpc3RbaV1bcG9zaXRpb25dLCBrZXkpKSB7XG4gICAgICBuZXdfbGlzdC5wdXNoKGxpc3RbaV0pO1xuICAgIH0gZWxzZSB7XG4gICAgICBuZXdfbGlzdC5wdXNoKG5ld190dXBsZSk7XG4gICAgICByZXBsYWNlZCA9IHRydWU7XG4gICAgfVxuICB9XG5cbiAgaWYgKCFyZXBsYWNlZCkge1xuICAgIG5ld19saXN0LnB1c2gobmV3X3R1cGxlKTtcbiAgfVxuXG4gIHJldHVybiBLZXJuZWwuU3BlY2lhbEZvcm1zLmxpc3QoLi4ubmV3X2xpc3QpO1xufTtcblxuTGlzdC5sYXN0ID0gZnVuY3Rpb24gKGxpc3QpIHtcbiAgcmV0dXJuIGxpc3RbbGlzdC5sZW5ndGggLSAxXTtcbn07XG5cbkxpc3QucmVwbGFjZV9hdCA9IGZ1bmN0aW9uIChsaXN0LCBpbmRleCwgdmFsdWUpIHtcbiAgbGV0IG5ld192YWx1ZSA9IFtdO1xuXG4gIGZvciAobGV0IGkgPSAwOyBpIDwgbGlzdC5sZW5ndGg7IGkrKykge1xuICAgIGlmIChpID09PSBpbmRleCkge1xuICAgICAgbmV3X3ZhbHVlLnB1c2godmFsdWUpO1xuICAgIH0gZWxzZSB7XG4gICAgICBuZXdfdmFsdWUucHVzaChsaXN0W2ldKTtcbiAgICB9XG4gIH1cblxuICByZXR1cm4gS2VybmVsLlNwZWNpYWxGb3Jtcy5saXN0KC4uLm5ld192YWx1ZSk7XG59O1xuXG5MaXN0LnVwZGF0ZV9hdCA9IGZ1bmN0aW9uIChsaXN0LCBpbmRleCwgZnVuKSB7XG4gIGxldCBuZXdfdmFsdWUgPSBbXTtcblxuICBmb3IgKGxldCBpID0gMDsgaSA8IGxpc3QuY291bnQoKTsgaSsrKSB7XG4gICAgaWYgKGkgPT09IGluZGV4KSB7XG4gICAgICBuZXdfdmFsdWUucHVzaChmdW4obGlzdC5nZXQoaSkpKTtcbiAgICB9IGVsc2Uge1xuICAgICAgbmV3X3ZhbHVlLnB1c2gobGlzdC5nZXQoaSkpO1xuICAgIH1cbiAgfVxuXG4gIHJldHVybiBuZXdfdmFsdWU7XG59O1xuXG5MaXN0LndyYXAgPSBmdW5jdGlvbiAobGlzdCkge1xuICBpZiAoS2VybmVsLmlzX2xpc3QobGlzdCkpIHtcbiAgICByZXR1cm4gbGlzdDtcbiAgfSBlbHNlIGlmIChsaXN0ID09IG51bGwpIHtcbiAgICByZXR1cm4gS2VybmVsLlNwZWNpYWxGb3Jtcy5saXN0KCk7XG4gIH0gZWxzZSB7XG4gICAgcmV0dXJuIEtlcm5lbC5TcGVjaWFsRm9ybXMubGlzdChsaXN0KTtcbiAgfVxufTtcblxuTGlzdC56aXAgPSBmdW5jdGlvbiAobGlzdF9vZl9saXN0cykge1xuICBpZiAobGlzdF9vZl9saXN0cy5sZW5ndGggPT09IDApIHtcbiAgICByZXR1cm4gS2VybmVsLlNwZWNpYWxGb3Jtcy5saXN0KCk7XG4gIH1cblxuICBsZXQgbmV3X3ZhbHVlID0gW107XG4gIGxldCBzbWFsbGVzdF9sZW5ndGggPSBsaXN0X29mX2xpc3RzWzBdO1xuXG4gIGZvciAobGV0IHggb2YgbGlzdF9vZl9saXN0cykge1xuICAgIGlmICh4Lmxlbmd0aCA8IHNtYWxsZXN0X2xlbmd0aCkge1xuICAgICAgc21hbGxlc3RfbGVuZ3RoID0geC5sZW5ndGg7XG4gICAgfVxuICB9XG5cbiAgZm9yIChsZXQgaSA9IDA7IGkgPCBzbWFsbGVzdF9sZW5ndGg7IGkrKykge1xuICAgIGxldCBjdXJyZW50X3ZhbHVlID0gW107XG4gICAgZm9yIChsZXQgaiA9IDA7IGogPCBsaXN0X29mX2xpc3RzLmxlbmd0aDsgaisrKSB7XG4gICAgICBjdXJyZW50X3ZhbHVlLnB1c2gobGlzdF9vZl9saXN0c1tqXVtpXSk7XG4gICAgfVxuXG4gICAgbmV3X3ZhbHVlLnB1c2goS2VybmVsLlNwZWNpYWxGb3Jtcy50dXBsZSguLi5jdXJyZW50X3ZhbHVlKSk7XG4gIH1cblxuICByZXR1cm4gS2VybmVsLlNwZWNpYWxGb3Jtcy5saXN0KC4uLm5ld192YWx1ZSk7XG59O1xuXG5MaXN0LnRvX3R1cGxlID0gZnVuY3Rpb24gKGxpc3QpIHtcbiAgcmV0dXJuIEtlcm5lbC5TcGVjaWFsRm9ybXMudHVwbGUuYXBwbHkobnVsbCwgbGlzdCk7XG59O1xuXG5MaXN0LmFwcGVuZCA9IGZ1bmN0aW9uIChsaXN0LCB2YWx1ZSkge1xuICByZXR1cm4gS2VybmVsLlNwZWNpYWxGb3Jtcy5saXN0KC4uLmxpc3QuY29uY2F0KFt2YWx1ZV0pKTtcbn07XG5cbkxpc3QucHJlcGVuZCA9IGZ1bmN0aW9uIChsaXN0LCB2YWx1ZSkge1xuICByZXR1cm4gS2VybmVsLlNwZWNpYWxGb3Jtcy5saXN0KC4uLlt2YWx1ZV0uY29uY2F0KGxpc3QpKTtcbn07XG5cbkxpc3QuY29uY2F0ID0gZnVuY3Rpb24gKGxlZnQsIHJpZ2h0KSB7XG4gIHJldHVybiBsZWZ0LmNvbmNhdChyaWdodCk7XG59O1xuXG5sZXQgUmFuZ2UgPSBmdW5jdGlvbiAoX2ZpcnN0LCBfbGFzdCkge1xuICBpZiAoISh0aGlzIGluc3RhbmNlb2YgUmFuZ2UpKSB7XG4gICAgcmV0dXJuIG5ldyBSYW5nZShfZmlyc3QsIF9sYXN0KTtcbiAgfVxuXG4gIHRoaXMuZmlyc3QgPSBmdW5jdGlvbiAoKSB7XG4gICAgcmV0dXJuIF9maXJzdDtcbiAgfTtcblxuICB0aGlzLmxhc3QgPSBmdW5jdGlvbiAoKSB7XG4gICAgcmV0dXJuIF9sYXN0O1xuICB9O1xuXG4gIGxldCBfcmFuZ2UgPSBbXTtcblxuICBmb3IgKGxldCBpID0gX2ZpcnN0OyBpIDw9IF9sYXN0OyBpKyspIHtcbiAgICBfcmFuZ2UucHVzaChpKTtcbiAgfVxuXG4gIF9yYW5nZSA9IE9iamVjdC5mcmVlemUoX3JhbmdlKTtcblxuICB0aGlzLnZhbHVlID0gZnVuY3Rpb24gKCkge1xuICAgIHJldHVybiBfcmFuZ2U7XG4gIH07XG5cbiAgdGhpcy5sZW5ndGggPSBmdW5jdGlvbiAoKSB7XG4gICAgcmV0dXJuIF9yYW5nZS5sZW5ndGg7XG4gIH07XG5cbiAgcmV0dXJuIHRoaXM7XG59O1xuXG5SYW5nZS5wcm90b3R5cGVbU3ltYm9sLml0ZXJhdG9yXSA9IGZ1bmN0aW9uICgpIHtcbiAgcmV0dXJuIHRoaXMudmFsdWUoKVtTeW1ib2wuaXRlcmF0b3JdKCk7XG59O1xuXG5SYW5nZS5uZXcgPSBmdW5jdGlvbiAoZmlyc3QsIGxhc3QpIHtcbiAgcmV0dXJuIFJhbmdlKGZpcnN0LCBsYXN0KTtcbn07XG5cblJhbmdlLnJhbmdlX19xbWFya19fID0gZnVuY3Rpb24gKHJhbmdlKSB7XG4gIHJldHVybiByYW5nZSBpbnN0YW5jZW9mIFJhbmdlO1xufTtcblxubGV0IEtleXdvcmQgPSB7fTtcblxuS2V5d29yZC5oYXNfa2V5X19xbV9fID0gZnVuY3Rpb24gKGtleXdvcmRzLCBrZXkpIHtcbiAgZm9yIChsZXQga2V5d29yZCBvZiBrZXl3b3Jkcykge1xuICAgIGlmIChLZXJuZWwuZWxlbShrZXl3b3JkLCAwKSA9PSBrZXkpIHtcbiAgICAgIHJldHVybiB0cnVlO1xuICAgIH1cbiAgfVxuXG4gIHJldHVybiBmYWxzZTtcbn07XG5cbktleXdvcmQuZ2V0ID0gZnVuY3Rpb24gKGtleXdvcmRzLCBrZXksIHRoZV9kZWZhdWx0ID0gbnVsbCkge1xuICBmb3IgKGxldCBrZXl3b3JkIG9mIGtleXdvcmRzKSB7XG4gICAgaWYgKEtlcm5lbC5lbGVtKGtleXdvcmQsIDApID09IGtleSkge1xuICAgICAgcmV0dXJuIEtlcm5lbC5lbGVtKGtleXdvcmQsIDEpO1xuICAgIH1cbiAgfVxuXG4gIHJldHVybiB0aGVfZGVmYXVsdDtcbn07XG5cbmxldCBBZ2VudCA9IHt9O1xuXG5BZ2VudC5zdGFydCA9IGZ1bmN0aW9uIChmdW4sIG9wdGlvbnMgPSBbXSkge1xuICBsZXQgcGlkID0gc2VsZi5wcm9jZXNzZXMuc3Bhd24oKTtcblxuICBpZiAoS2V5d29yZC5oYXNfa2V5X19xbV9fKG9wdGlvbnMsIEtlcm5lbC5TcGVjaWFsRm9ybXMuYXRvbSgnbmFtZScpKSkge1xuICAgIHBpZCA9IHNlbGYucHJvY2Vzc2VzLnJlZ2lzdGVyKEtleXdvcmQuZ2V0KG9wdGlvbnMsIEtlcm5lbC5TcGVjaWFsRm9ybXMuYXRvbSgnbmFtZScpKSwgcGlkKTtcbiAgfVxuXG4gIHNlbGYucHJvY2Vzc2VzLnB1dChwaWQsICdzdGF0ZScsIGZ1bigpKTtcbiAgcmV0dXJuIEtlcm5lbC5TcGVjaWFsRm9ybXMudHVwbGUoS2VybmVsLlNwZWNpYWxGb3Jtcy5hdG9tKCdvaycpLCBwaWQpO1xufTtcblxuQWdlbnQuc3RvcCA9IGZ1bmN0aW9uIChhZ2VudCwgdGltZW91dCA9IDUwMDApIHtcbiAgc2VsZi5wcm9jZXNzZXMuZXhpdChhZ2VudCk7XG4gIHJldHVybiBLZXJuZWwuU3BlY2lhbEZvcm1zLmF0b20oJ29rJyk7XG59O1xuXG5BZ2VudC51cGRhdGUgPSBmdW5jdGlvbiAoYWdlbnQsIGZ1biwgdGltZW91dCA9IDUwMDApIHtcblxuICBjb25zdCBjdXJyZW50X3N0YXRlID0gc2VsZi5wcm9jZXNzZXMuZ2V0KGFnZW50LCAnc3RhdGUnKTtcbiAgc2VsZi5wcm9jZXNzZXMucHV0KGFnZW50LCAnc3RhdGUnLCBmdW4oY3VycmVudF9zdGF0ZSkpO1xuXG4gIHJldHVybiBLZXJuZWwuU3BlY2lhbEZvcm1zLmF0b20oJ29rJyk7XG59O1xuXG5BZ2VudC5nZXQgPSBmdW5jdGlvbiAoYWdlbnQsIGZ1biwgdGltZW91dCA9IDUwMDApIHtcbiAgcmV0dXJuIGZ1bihzZWxmLnByb2Nlc3Nlcy5nZXQoYWdlbnQsICdzdGF0ZScpKTtcbn07XG5cbkFnZW50LmdldF9hbmRfdXBkYXRlID0gZnVuY3Rpb24gKGFnZW50LCBmdW4sIHRpbWVvdXQgPSA1MDAwKSB7XG5cbiAgY29uc3QgZ2V0X2FuZF91cGRhdGVfdHVwbGUgPSBmdW4oc2VsZi5wcm9jZXNzZXMuZ2V0KGFnZW50LCAnc3RhdGUnKSk7XG4gIHNlbGYucHJvY2Vzc2VzLnB1dChhZ2VudCwgJ3N0YXRlJywgS2VybmVsLmVsZW0oZ2V0X2FuZF91cGRhdGVfdHVwbGUsIDEpKTtcblxuICByZXR1cm4gS2VybmVsLmVsZW0oZ2V0X2FuZF91cGRhdGVfdHVwbGUsIDApO1xufTtcblxuLy9odHRwczovL2RldmVsb3Blci5tb3ppbGxhLm9yZy9lbi1VUy9kb2NzL1dlYi9BUEkvV2luZG93QmFzZTY0L0Jhc2U2NF9lbmNvZGluZ19hbmRfZGVjb2RpbmcjU29sdXRpb25fMl8lRTIlODAlOTNfcmV3cml0ZV90aGVfRE9Nc19hdG9iKClfYW5kX2J0b2EoKV91c2luZ19KYXZhU2NyaXB0J3NfVHlwZWRBcnJheXNfYW5kX1VURi04XG5mdW5jdGlvbiBiNjRFbmNvZGVVbmljb2RlKHN0cikge1xuICByZXR1cm4gYnRvYShlbmNvZGVVUklDb21wb25lbnQoc3RyKS5yZXBsYWNlKC8lKFswLTlBLUZdezJ9KS9nLCBmdW5jdGlvbiAobWF0Y2gsIHAxKSB7XG4gICAgcmV0dXJuIFN0cmluZy5mcm9tQ2hhckNvZGUoJzB4JyArIHAxKTtcbiAgfSkpO1xufVxuXG5mdW5jdGlvbiBlbmNvZGU2NChkYXRhKSB7XG4gIHJldHVybiBiNjRFbmNvZGVVbmljb2RlKGRhdGEpO1xufVxuXG5mdW5jdGlvbiBkZWNvZGU2NChkYXRhKSB7XG4gIHRyeSB7XG4gICAgcmV0dXJuIEtlcm5lbC5TcGVjaWFsRm9ybXMudHVwbGUoS2VybmVsLlNwZWNpYWxGb3Jtcy5hdG9tKCdvaycpLCBhdG9iKGRhdGEpKTtcbiAgfSBjYXRjaCAoZSkge1xuICAgIHJldHVybiBLZXJuZWwuU3BlY2lhbEZvcm1zLmF0b20oJ2Vycm9yJyk7XG4gIH1cbiAgcmV0dXJuIGJ0b2EoZGF0YSk7XG59XG5cbmZ1bmN0aW9uIGRlY29kZTY0X19lbV9fKGRhdGEpIHtcbiAgcmV0dXJuIGF0b2IoZGF0YSk7XG59XG5cbnZhciBiYXNlID0ge1xuICBlbmNvZGU2NCxcbiAgZGVjb2RlNjQsXG4gIGRlY29kZTY0X19lbV9fXG59O1xuXG5mdW5jdGlvbiBibm90KGV4cHIpIHtcbiAgcmV0dXJuIH5leHByO1xufVxuXG5mdW5jdGlvbiBiYW5kKGxlZnQsIHJpZ2h0KSB7XG4gIHJldHVybiBsZWZ0ICYgcmlnaHQ7XG59XG5cbmZ1bmN0aW9uIGJvcihsZWZ0LCByaWdodCkge1xuICByZXR1cm4gbGVmdCB8IHJpZ2h0O1xufVxuXG5mdW5jdGlvbiBic2wobGVmdCwgcmlnaHQpIHtcbiAgcmV0dXJuIGxlZnQgPDwgcmlnaHQ7XG59XG5cbmZ1bmN0aW9uIGJzcihsZWZ0LCByaWdodCkge1xuICByZXR1cm4gbGVmdCA+PiByaWdodDtcbn1cblxuZnVuY3Rpb24gYnhvcihsZWZ0LCByaWdodCkge1xuICByZXR1cm4gbGVmdCBeIHJpZ2h0O1xufVxuXG52YXIgYml0d2lzZSA9IHtcbiAgYm5vdCxcbiAgYmFuZCxcbiAgYm9yLFxuICBic2wsXG4gIGJzcixcbiAgYnhvclxufTtcblxubGV0IEVudW1lcmFibGUgPSBLZXJuZWwuZGVmcHJvdG9jb2woe1xuICBjb3VudDogZnVuY3Rpb24gKGNvbGxlY3Rpb24pIHt9LFxuICBtZW1iZXJfcW1hcmtfXzogZnVuY3Rpb24gKGNvbGxlY3Rpb24sIHZhbHVlKSB7fSxcbiAgcmVkdWNlOiBmdW5jdGlvbiAoY29sbGVjdGlvbiwgYWNjLCBmdW4pIHt9XG59KTtcblxubGV0IENvbGxlY3RhYmxlID0gS2VybmVsLmRlZnByb3RvY29sKHtcbiAgaW50bzogZnVuY3Rpb24gKGNvbGxlY3RhYmxlKSB7fVxufSk7XG5cbmxldCBJbnNwZWN0ID0gS2VybmVsLmRlZnByb3RvY29sKHtcbiAgaW5zcGVjdDogZnVuY3Rpb24gKHRoaW5nLCBvcHRzKSB7fVxufSk7XG5cbmZ1bmN0aW9uIF9fbmV3X18oKSB7XG4gIHJldHVybiBTcGVjaWFsRm9ybXMubWFwKHt9KTtcbn1cblxuZnVuY3Rpb24ga2V5cyhtYXApIHtcbiAgcmV0dXJuIE9iamVjdC5rZXlzKG1hcCk7XG59XG5cbmZ1bmN0aW9uIHNpemUobWFwKSB7XG4gIHJldHVybiBrZXlzKG1hcCkubGVuZ3RoO1xufVxuXG5mdW5jdGlvbiB0b19saXN0JDEobWFwKSB7XG4gIGxldCBtYXBfa2V5cyA9IGtleXMobWFwKTtcbiAgbGV0IGxpc3QgPSBbXTtcblxuICBmb3IgKGxldCBrZXkgb2YgbWFwX2tleXMpIHtcbiAgICBsaXN0LnB1c2goU3BlY2lhbEZvcm1zLnR1cGxlKGtleSwgbWFwW2tleV0pKTtcbiAgfVxuXG4gIHJldHVybiBTcGVjaWFsRm9ybXMubGlzdCguLi5saXN0KTtcbn1cblxuZnVuY3Rpb24gdmFsdWVzKG1hcCkge1xuICBsZXQgbWFwX2tleXMgPSBrZXlzKG1hcCk7XG4gIGxldCBsaXN0ID0gW107XG5cbiAgZm9yIChsZXQga2V5IG9mIG1hcF9rZXlzKSB7XG4gICAgbGlzdC5wdXNoKG1hcFtrZXldKTtcbiAgfVxuXG4gIHJldHVybiBTcGVjaWFsRm9ybXMubGlzdCguLi5saXN0KTtcbn1cblxuZnVuY3Rpb24gZnJvbV9zdHJ1Y3Qoc3RydWN0KSB7XG4gIGxldCBtYXAgPSBPYmplY3QuYXNzaWduKHt9LCBzdHJ1Y3QpO1xuICBkZWxldGUgbWFwW1N5bWJvbC5mb3IoXCJfX3N0cnVjdF9fXCIpXTtcblxuICByZXR1cm4gU3BlY2lhbEZvcm1zLm1hcChtYXApO1xufVxuXG5mdW5jdGlvbiBfX2RlbGV0ZV9fKG1hcCwga2V5KSB7XG4gIGxldCBuZXdfbWFwID0gT2JqZWN0LmFzc2lnbih7fSwgbWFwKTtcblxuICBkZWxldGUgbmV3X21hcFtrZXldO1xuXG4gIHJldHVybiBTcGVjaWFsRm9ybXMubWFwKG5ld19tYXApO1xufVxuXG5mdW5jdGlvbiBlcXVhbF9fcW1hcmtfXyhtYXAxLCBtYXAyKSB7XG4gIHJldHVybiBtYXAxID09PSBtYXAyO1xufVxuXG5mdW5jdGlvbiBmZXRjaF9fZW1hcmtfXyhtYXAsIGtleSkge1xuICBpZiAoa2V5IGluIG1hcCkge1xuICAgIHJldHVybiBtYXBba2V5XTtcbiAgfVxuXG4gIHRocm93IG5ldyBFcnJvcihcIktleSBub3QgZm91bmQuXCIpO1xufVxuXG5mdW5jdGlvbiBmZXRjaChtYXAsIGtleSkge1xuICBpZiAoa2V5IGluIG1hcCkge1xuICAgIHJldHVybiBTcGVjaWFsRm9ybXMudHVwbGUoU3BlY2lhbEZvcm1zLmF0b20oXCJva1wiKSwgbWFwW2tleV0pO1xuICB9XG5cbiAgcmV0dXJuIFNwZWNpYWxGb3Jtcy5hdG9tKFwiZXJyb3JcIik7XG59XG5cbmZ1bmN0aW9uIGhhc19rZXlfX3FtYXJrX18obWFwLCBrZXkpIHtcbiAgcmV0dXJuIGtleSBpbiBtYXA7XG59XG5cbmZ1bmN0aW9uIHNwbGl0JDEobWFwLCBrZXlzKSB7XG4gIGxldCBzcGxpdDEgPSB7fTtcbiAgbGV0IHNwbGl0MiA9IHt9O1xuXG4gIGZvciAobGV0IGtleSBvZiBPYmplY3Qua2V5cyhtYXApKSB7XG4gICAgaWYgKGtleXMuaW5kZXhPZihrZXkpID4gLTEpIHtcbiAgICAgIHNwbGl0MVtrZXldID0gbWFwW2tleV07XG4gICAgfSBlbHNlIHtcbiAgICAgIHNwbGl0MltrZXldID0gbWFwW2tleV07XG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIFNwZWNpYWxGb3Jtcy50dXBsZShTcGVjaWFsRm9ybXMubWFwKHNwbGl0MSksIFNwZWNpYWxGb3Jtcy5tYXAoc3BsaXQyKSk7XG59XG5cbmZ1bmN0aW9uIHRha2UobWFwLCBrZXlzKSB7XG4gIGxldCBzcGxpdDEgPSB7fTtcblxuICBmb3IgKGxldCBrZXkgb2YgT2JqZWN0LmtleXMobWFwKSkge1xuICAgIGlmIChrZXlzLmluZGV4T2Yoa2V5KSA+IC0xKSB7XG4gICAgICBzcGxpdDFba2V5XSA9IG1hcFtrZXldO1xuICAgIH1cbiAgfVxuXG4gIHJldHVybiBTcGVjaWFsRm9ybXMubWFwKHNwbGl0MSk7XG59XG5cbmZ1bmN0aW9uIGRyb3AobWFwLCBrZXlzKSB7XG4gIGxldCBzcGxpdDEgPSB7fTtcblxuICBmb3IgKGxldCBrZXkgb2YgT2JqZWN0LmtleXMobWFwKSkge1xuICAgIGlmIChrZXlzLmluZGV4T2Yoa2V5KSA9PT0gLTEpIHtcbiAgICAgIHNwbGl0MVtrZXldID0gbWFwW2tleV07XG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIFNwZWNpYWxGb3Jtcy5tYXAoc3BsaXQxKTtcbn1cblxuZnVuY3Rpb24gcHV0X25ldyhtYXAsIGtleSwgdmFsdWUpIHtcbiAgaWYgKGtleSBpbiBtYXApIHtcbiAgICByZXR1cm4gbWFwO1xuICB9XG5cbiAgbGV0IG5ld19tYXAgPSBPYmplY3QuYXNzaWduKHt9LCBtYXApO1xuICBuZXdfbWFwW2tleV0gPSB2YWx1ZTtcblxuICByZXR1cm4gU3BlY2lhbEZvcm1zLm1hcChuZXdfbWFwKTtcbn1cblxuZnVuY3Rpb24gcHV0X25ld19sYXp5KG1hcCwga2V5LCBmdW4pIHtcbiAgaWYgKGtleSBpbiBtYXApIHtcbiAgICByZXR1cm4gbWFwO1xuICB9XG5cbiAgbGV0IG5ld19tYXAgPSBPYmplY3QuYXNzaWduKHt9LCBtYXApO1xuICBuZXdfbWFwW2tleV0gPSBmdW4oKTtcblxuICByZXR1cm4gU3BlY2lhbEZvcm1zLm1hcChuZXdfbWFwKTtcbn1cblxuZnVuY3Rpb24gZ2V0X2FuZF91cGRhdGUobWFwLCBrZXksIGZ1bikge1xuICBpZiAoa2V5IGluIG1hcCkge1xuICAgIHJldHVybiBtYXA7XG4gIH1cblxuICBsZXQgbmV3X21hcCA9IE9iamVjdC5hc3NpZ24oe30sIG1hcCk7XG4gIG5ld19tYXBba2V5XSA9IGZ1bihtYXBba2V5XSk7XG5cbiAgcmV0dXJuIFNwZWNpYWxGb3Jtcy5tYXAobmV3X21hcCk7XG59XG5cbmZ1bmN0aW9uIHBvcF9sYXp5KG1hcCwga2V5LCBmdW4pIHtcbiAgaWYgKCFrZXkgaW4gbWFwKSB7XG4gICAgcmV0dXJuIFNwZWNpYWxGb3Jtcy50dXBsZShmdW4oKSwgbWFwKTtcbiAgfVxuXG4gIGxldCBuZXdfbWFwID0gT2JqZWN0LmFzc2lnbih7fSwgbWFwKTtcbiAgbGV0IHZhbHVlID0gZnVuKG5ld19tYXBba2V5XSk7XG4gIGRlbGV0ZSBuZXdfbWFwW2tleV07XG5cbiAgcmV0dXJuIFNwZWNpYWxGb3Jtcy50dXBsZSh2YWx1ZSwgbmV3X21hcCk7XG59XG5cbmZ1bmN0aW9uIHBvcChtYXAsIGtleSwgX2RlZmF1bHQgPSBudWxsKSB7XG4gIGlmICgha2V5IGluIG1hcCkge1xuICAgIHJldHVybiBTcGVjaWFsRm9ybXMudHVwbGUoX2RlZmF1bHQsIG1hcCk7XG4gIH1cblxuICBsZXQgbmV3X21hcCA9IE9iamVjdC5hc3NpZ24oe30sIG1hcCk7XG4gIGxldCB2YWx1ZSA9IG5ld19tYXBba2V5XTtcbiAgZGVsZXRlIG5ld19tYXBba2V5XTtcblxuICByZXR1cm4gU3BlY2lhbEZvcm1zLnR1cGxlKHZhbHVlLCBuZXdfbWFwKTtcbn1cblxuZnVuY3Rpb24gZ2V0X2xhenkobWFwLCBrZXksIGZ1bikge1xuICBpZiAoIWtleSBpbiBtYXApIHtcbiAgICByZXR1cm4gZnVuKCk7XG4gIH1cblxuICByZXR1cm4gZnVuKG1hcFtrZXldKTtcbn1cblxuZnVuY3Rpb24gZ2V0KG1hcCwga2V5LCBfZGVmYXVsdCA9IG51bGwpIHtcbiAgaWYgKCFrZXkgaW4gbWFwKSB7XG4gICAgcmV0dXJuIF9kZWZhdWx0O1xuICB9XG5cbiAgcmV0dXJuIG1hcFtrZXldO1xufVxuXG5mdW5jdGlvbiBwdXQobWFwLCBrZXksIHZhbCkge1xuICBsZXQgbmV3X21hcCA9IE9iamVjdCh7fSwgbWFwKTtcbiAgbmV3X21hcFtrZXldID0gdmFsO1xuXG4gIHJldHVybiBTcGVjaWFsRm9ybXMubWFwKG5ld19tYXApO1xufVxuXG5mdW5jdGlvbiB1cGRhdGVfX2VtYXJrX18obWFwLCBrZXksIGZ1bikge1xuICBpZiAoIWtleSBpbiBtYXApIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoXCJLZXkgbm90IGZvdW5kXCIpO1xuICB9XG5cbiAgbGV0IG5ld19tYXAgPSBPYmplY3Qoe30sIG1hcCk7XG4gIG5ld19tYXBba2V5XSA9IGZ1bihtYXBba2V5XSk7XG5cbiAgcmV0dXJuIFNwZWNpYWxGb3Jtcy5tYXAobmV3X21hcCk7XG59XG5cbmZ1bmN0aW9uIHVwZGF0ZShtYXAsIGtleSwgaW5pdGlhbCwgZnVuKSB7XG4gIGxldCBuZXdfbWFwID0gT2JqZWN0KHt9LCBtYXApO1xuXG4gIGlmICgha2V5IGluIG1hcCkge1xuICAgIG5ld19tYXBba2V5XSA9IGluaXRpYWw7XG4gIH0gZWxzZSB7XG4gICAgbmV3X21hcFtrZXldID0gZnVuKG1hcFtrZXldKTtcbiAgfVxuXG4gIHJldHVybiBTcGVjaWFsRm9ybXMubWFwKG5ld19tYXApO1xufVxuXG52YXIgbWFwID0ge1xuICBuZXc6IF9fbmV3X18sXG4gIGtleXMsXG4gIHNpemUsXG4gIHRvX2xpc3Q6IHRvX2xpc3QkMSxcbiAgdmFsdWVzLFxuICBmcm9tX3N0cnVjdCxcbiAgZGVsZXRlOiBfX2RlbGV0ZV9fLFxuICBkcm9wLFxuICBlcXVhbF9fcW1hcmtfXyxcbiAgZmV0Y2hfX2VtYXJrX18sXG4gIGZldGNoLFxuICBoYXNfa2V5X19xbWFya19fLFxuICBzcGxpdDogc3BsaXQkMSxcbiAgdGFrZSxcbiAgcHV0X25ldyxcbiAgcHV0X25ld19sYXp5LFxuICBnZXRfYW5kX3VwZGF0ZSxcbiAgcG9wX2xhenksXG4gIHBvcCxcbiAgZ2V0X2xhenksXG4gIGdldCxcbiAgcHV0LFxuICB1cGRhdGVfX2VtYXJrX18sXG4gIHVwZGF0ZVxufTtcblxuZnVuY3Rpb24gX19uZXdfXyQxKCkge1xuICByZXR1cm4gU3BlY2lhbEZvcm1zLm1hcCh7IFtTeW1ib2wuZm9yKCdfX3N0cnVjdF9fJyldOiBTeW1ib2wuZm9yKCdNYXBTZXQnKSwgc2V0OiBTcGVjaWFsRm9ybXMubGlzdCgpIH0pO1xufVxuXG5mdW5jdGlvbiBzaXplJDIobWFwKSB7XG4gIHJldHVybiBtYXAuc2V0Lmxlbmd0aDtcbn1cblxuZnVuY3Rpb24gdG9fbGlzdCQzKG1hcCkge1xuICByZXR1cm4gbWFwLnNldDtcbn1cblxuZnVuY3Rpb24gX19kZWxldGVfXyQyKHNldCwgdGVybSkge1xuICBsZXQgbmV3X2xpc3QgPSBMaXN0LmRlbGV0ZShzZXQuc2V0LCB0ZXJtKTtcblxuICBsZXQgbmV3X21hcCA9IE9iamVjdC5hc3NpZ24oe30sIHNldCk7XG4gIG5ld19tYXAuc2V0ID0gbmV3X2xpc3Q7XG4gIHJldHVybiBTcGVjaWFsRm9ybXMubWFwKG5ld19tYXApO1xufVxuXG5mdW5jdGlvbiBwdXQkMihzZXQsIHRlcm0pIHtcbiAgaWYgKHNldC5zZXQuaW5kZXhPZih0ZXJtKSA9PT0gLTEpIHtcbiAgICBsZXQgbmV3X2xpc3QgPSBMaXN0LmFwcGVuZChzZXQuc2V0LCB0ZXJtKTtcblxuICAgIGxldCBuZXdfbWFwID0gT2JqZWN0LmFzc2lnbih7fSwgc2V0KTtcbiAgICBuZXdfbWFwLnNldCA9IG5ld19saXN0O1xuICAgIHJldHVybiBTcGVjaWFsRm9ybXMubWFwKG5ld19tYXApO1xuICB9XG5cbiAgcmV0dXJuIHNldDtcbn1cblxuZnVuY3Rpb24gZGlmZmVyZW5jZSQxKHNldDEsIHNldDIpIHtcbiAgbGV0IG5ld19tYXAgPSBPYmplY3QuYXNzaWduKHt9LCBzZXQxKTtcblxuICBmb3IgKGxldCB2YWwgb2Ygc2V0MS5zZXQpIHtcbiAgICBpZiAobWVtYmVyX19xbWFya19fJDEoc2V0MiwgdmFsKSkge1xuICAgICAgbmV3X21hcC5zZXQgPSBMaXN0LmRlbGV0ZShuZXdfbWFwLnNldCwgdmFsKTtcbiAgICB9XG4gIH1cblxuICByZXR1cm4gU3BlY2lhbEZvcm1zLm1hcChuZXdfbWFwKTtcbn1cblxuZnVuY3Rpb24gaW50ZXJzZWN0aW9uJDEoc2V0MSwgc2V0Mikge1xuICBsZXQgbmV3X21hcCA9IE9iamVjdC5hc3NpZ24oe30sIHNldDEpO1xuXG4gIGZvciAobGV0IHZhbCBvZiBzZXQxLnNldCkge1xuICAgIGlmICghbWVtYmVyX19xbWFya19fJDEoc2V0MiwgdmFsKSkge1xuICAgICAgbmV3X21hcC5zZXQgPSBMaXN0LmRlbGV0ZShuZXdfbWFwLnNldCwgdmFsKTtcbiAgICB9XG4gIH1cblxuICByZXR1cm4gU3BlY2lhbEZvcm1zLm1hcChuZXdfbWFwKTtcbn1cblxuZnVuY3Rpb24gdW5pb24kMShzZXQxLCBzZXQyKSB7XG4gIGxldCBuZXdfbWFwID0gc2V0MTtcblxuICBmb3IgKGxldCB2YWwgb2Ygc2V0Mi5zZXQpIHtcbiAgICBuZXdfbWFwID0gcHV0JDIobmV3X21hcCwgdmFsKTtcbiAgfVxuXG4gIHJldHVybiBTcGVjaWFsRm9ybXMubWFwKG5ld19tYXApO1xufVxuXG5mdW5jdGlvbiBkaXNqb2luX19xbWFya19fJDEoc2V0MSwgc2V0Mikge1xuICBmb3IgKGxldCB2YWwgb2Ygc2V0MS5zZXQpIHtcbiAgICBpZiAobWVtYmVyX19xbWFya19fJDEoc2V0MiwgdmFsKSkge1xuICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH1cbiAgfVxuXG4gIHJldHVybiB0cnVlO1xufVxuXG5mdW5jdGlvbiBtZW1iZXJfX3FtYXJrX18kMShzZXQsIHZhbHVlKSB7XG4gIHJldHVybiBzZXQuc2V0LmluZGV4T2YodmFsdWUpID49IDA7XG59XG5cbmZ1bmN0aW9uIGVxdWFsX19xbWFya19fJDIoc2V0MSwgc2V0Mikge1xuICByZXR1cm4gc2V0MS5zZXQgPT09IHNldDIuc2V0O1xufVxuXG5mdW5jdGlvbiBzdWJzZXRfX3FtYXJrX18kMShzZXQxLCBzZXQyKSB7XG4gIGZvciAobGV0IHZhbCBvZiBzZXQxLnNldCkge1xuICAgIGlmICghbWVtYmVyX19xbWFya19fJDEoc2V0MiwgdmFsKSkge1xuICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH1cbiAgfVxuXG4gIHJldHVybiB0cnVlO1xufVxuXG52YXIgTWFwU2V0ID0ge1xuICBuZXc6IF9fbmV3X18kMSxcbiAgc2l6ZTogc2l6ZSQyLFxuICB0b19saXN0OiB0b19saXN0JDMsXG4gIGRpc2pvaW5fX3FtYXJrX186IGRpc2pvaW5fX3FtYXJrX18kMSxcbiAgZGVsZXRlOiBfX2RlbGV0ZV9fJDIsXG4gIHN1YnNldF9fcW1hcmtfXzogc3Vic2V0X19xbWFya19fJDEsXG4gIGVxdWFsX19xbWFya19fOiBlcXVhbF9fcW1hcmtfXyQyLFxuICBtZW1iZXJfX3FtYXJrX186IG1lbWJlcl9fcW1hcmtfXyQxLFxuICBwdXQ6IHB1dCQyLFxuICB1bmlvbjogdW5pb24kMSxcbiAgaW50ZXJzZWN0aW9uOiBpbnRlcnNlY3Rpb24kMSxcbiAgZGlmZmVyZW5jZTogZGlmZmVyZW5jZSQxXG59O1xuXG5mdW5jdGlvbiBzaXplJDEobWFwKSB7XG4gIHJldHVybiBNYXBTZXQuc2l6ZShtYXApO1xufVxuXG5mdW5jdGlvbiB0b19saXN0JDIobWFwKSB7XG4gIHJldHVybiBNYXBTZXQudG9fbGlzdChtYXApO1xufVxuXG5mdW5jdGlvbiBfX2RlbGV0ZV9fJDEoc2V0LCB0ZXJtKSB7XG4gIHJldHVybiBNYXBTZXQuZGVsZXRlKHNldCwgdGVybSk7XG59XG5cbmZ1bmN0aW9uIHB1dCQxKHNldCwgdGVybSkge1xuICByZXR1cm4gTWFwU2V0LnB1dChzZXQsIHRlcm0pO1xufVxuXG5mdW5jdGlvbiBkaWZmZXJlbmNlKHNldDEsIHNldDIpIHtcbiAgcmV0dXJuIE1hcFNldC5kaWZmZXJlbmNlKHNldDEsIHNldDIpO1xufVxuXG5mdW5jdGlvbiBpbnRlcnNlY3Rpb24oc2V0MSwgc2V0Mikge1xuICByZXR1cm4gTWFwU2V0LmludGVyc2VjdGlvbihzZXQxLCBzZXQyKTtcbn1cblxuZnVuY3Rpb24gdW5pb24oc2V0MSwgc2V0Mikge1xuICByZXR1cm4gTWFwU2V0LnVuaW9uKHNldDEsIHNldDIpO1xufVxuXG5mdW5jdGlvbiBkaXNqb2luX19xbWFya19fKHNldDEsIHNldDIpIHtcbiAgcmV0dXJuIE1hcFNldC5kaXNqb2luX19xbWFya19fKHNldDEsIHNldDIpO1xufVxuXG5mdW5jdGlvbiBtZW1iZXJfX3FtYXJrX18oc2V0LCB2YWx1ZSkge1xuICByZXR1cm4gTWFwU2V0Lm1lbWJlcl9fcW1hcmtfXyhzZXQxLCBzZXQyKTtcbn1cblxuZnVuY3Rpb24gZXF1YWxfX3FtYXJrX18kMShzZXQxLCBzZXQyKSB7XG4gIHJldHVybiBNYXBTZXQuZXF1YWxfX3FtYXJrX18oc2V0MSwgc2V0Mik7XG59XG5cbmZ1bmN0aW9uIHN1YnNldF9fcW1hcmtfXyhzZXQxLCBzZXQyKSB7XG4gIHJldHVybiBNYXBTZXQuc3Vic2V0X19xbWFya19fKHNldDEsIHNldDIpO1xufVxuXG52YXIgc2V0ID0ge1xuICBzaXplOiBzaXplJDEsXG4gIHRvX2xpc3Q6IHRvX2xpc3QkMixcbiAgZGlzam9pbl9fcW1hcmtfXyxcbiAgZGVsZXRlOiBfX2RlbGV0ZV9fJDEsXG4gIHN1YnNldF9fcW1hcmtfXyxcbiAgZXF1YWxfX3FtYXJrX186IGVxdWFsX19xbWFya19fJDEsXG4gIG1lbWJlcl9fcW1hcmtfXyxcbiAgcHV0OiBwdXQkMSxcbiAgdW5pb24sXG4gIGludGVyc2VjdGlvbixcbiAgZGlmZmVyZW5jZVxufTtcblxubGV0IFZpcnR1YWxET00gPSAoZnVuY3Rpb24gKGUpIHtcbiAgICByZXR1cm4gZSgpO1xufSkoZnVuY3Rpb24gKCkge1xuICAgIHZhciBkZWZpbmUsIG1vZHVsZSwgZXhwb3J0cztcbiAgICByZXR1cm4gKGZ1bmN0aW9uIGUodCwgbiwgcikge1xuICAgICAgICBmdW5jdGlvbiBzKG8sIHUpIHtcbiAgICAgICAgICAgIGlmICghbltvXSkge1xuICAgICAgICAgICAgICAgIGlmICghdFtvXSkge1xuICAgICAgICAgICAgICAgICAgICB2YXIgYSA9IHR5cGVvZiByZXF1aXJlID09IFwiZnVuY3Rpb25cIiAmJiByZXF1aXJlO1xuICAgICAgICAgICAgICAgICAgICBpZiAoIXUgJiYgYSkgcmV0dXJuIGEobywgITApO1xuICAgICAgICAgICAgICAgICAgICBpZiAoaSkgcmV0dXJuIGkobywgITApO1xuICAgICAgICAgICAgICAgICAgICB2YXIgZiA9IG5ldyBFcnJvcihcIkNhbm5vdCBmaW5kIG1vZHVsZSAnXCIgKyBvICsgXCInXCIpO1xuICAgICAgICAgICAgICAgICAgICB0aHJvdyAoZi5jb2RlID0gXCJNT0RVTEVfTk9UX0ZPVU5EXCIsIGYpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB2YXIgbCA9IG5bb10gPSB7XG4gICAgICAgICAgICAgICAgICAgIGV4cG9ydHM6IHt9XG4gICAgICAgICAgICAgICAgfTtcbiAgICAgICAgICAgICAgICB0W29dWzBdLmNhbGwobC5leHBvcnRzLCBmdW5jdGlvbiAoZSkge1xuICAgICAgICAgICAgICAgICAgICB2YXIgbiA9IHRbb11bMV1bZV07XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBzKG4gPyBuIDogZSk7XG4gICAgICAgICAgICAgICAgfSwgbCwgbC5leHBvcnRzLCBlLCB0LCBuLCByKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJldHVybiBuW29dLmV4cG9ydHM7XG4gICAgICAgIH1cbiAgICAgICAgdmFyIGkgPSB0eXBlb2YgcmVxdWlyZSA9PSBcImZ1bmN0aW9uXCIgJiYgcmVxdWlyZTtcbiAgICAgICAgZm9yICh2YXIgbyA9IDA7IG8gPCByLmxlbmd0aDsgbysrKSBzKHJbb10pO1xuICAgICAgICByZXR1cm4gcztcbiAgICB9KSh7XG4gICAgICAgIDE6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG5cbiAgICAgICAgICAgIHZhciBjcmVhdGVFbGVtZW50ID0gcmVxdWlyZShcIi4vdmRvbS9jcmVhdGUtZWxlbWVudC5qc1wiKTtcblxuICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBjcmVhdGVFbGVtZW50O1xuICAgICAgICB9LCB7IFwiLi92ZG9tL2NyZWF0ZS1lbGVtZW50LmpzXCI6IDE1IH1dLCAyOiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge1xuICAgICAgICAgICAgdmFyIGRpZmYgPSByZXF1aXJlKFwiLi92dHJlZS9kaWZmLmpzXCIpO1xuXG4gICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IGRpZmY7XG4gICAgICAgIH0sIHsgXCIuL3Z0cmVlL2RpZmYuanNcIjogMzUgfV0sIDM6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICB2YXIgaCA9IHJlcXVpcmUoXCIuL3ZpcnR1YWwtaHlwZXJzY3JpcHQvaW5kZXguanNcIik7XG5cbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gaDtcbiAgICAgICAgfSwgeyBcIi4vdmlydHVhbC1oeXBlcnNjcmlwdC9pbmRleC5qc1wiOiAyMiB9XSwgNDogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHtcbiAgICAgICAgICAgIHZhciBkaWZmID0gcmVxdWlyZShcIi4vZGlmZi5qc1wiKTtcbiAgICAgICAgICAgIHZhciBwYXRjaCA9IHJlcXVpcmUoXCIuL3BhdGNoLmpzXCIpO1xuICAgICAgICAgICAgdmFyIGggPSByZXF1aXJlKFwiLi9oLmpzXCIpO1xuICAgICAgICAgICAgdmFyIGNyZWF0ZSA9IHJlcXVpcmUoXCIuL2NyZWF0ZS1lbGVtZW50LmpzXCIpO1xuICAgICAgICAgICAgdmFyIFZOb2RlID0gcmVxdWlyZShcIi4vdm5vZGUvdm5vZGUuanNcIik7XG4gICAgICAgICAgICB2YXIgVlRleHQgPSByZXF1aXJlKFwiLi92bm9kZS92dGV4dC5qc1wiKTtcblxuICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSB7XG4gICAgICAgICAgICAgICAgZGlmZjogZGlmZixcbiAgICAgICAgICAgICAgICBwYXRjaDogcGF0Y2gsXG4gICAgICAgICAgICAgICAgaDogaCxcbiAgICAgICAgICAgICAgICBjcmVhdGU6IGNyZWF0ZSxcbiAgICAgICAgICAgICAgICBWTm9kZTogVk5vZGUsXG4gICAgICAgICAgICAgICAgVlRleHQ6IFZUZXh0XG4gICAgICAgICAgICB9O1xuICAgICAgICB9LCB7IFwiLi9jcmVhdGUtZWxlbWVudC5qc1wiOiAxLCBcIi4vZGlmZi5qc1wiOiAyLCBcIi4vaC5qc1wiOiAzLCBcIi4vcGF0Y2guanNcIjogMTMsIFwiLi92bm9kZS92bm9kZS5qc1wiOiAzMSwgXCIuL3Zub2RlL3Z0ZXh0LmpzXCI6IDMzIH1dLCA1OiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge1xuICAgICAgICAgICAgLyohXG4gICAgICAgICAgICAgKiBDcm9zcy1Ccm93c2VyIFNwbGl0IDEuMS4xXG4gICAgICAgICAgICAgKiBDb3B5cmlnaHQgMjAwNy0yMDEyIFN0ZXZlbiBMZXZpdGhhbiA8c3RldmVubGV2aXRoYW4uY29tPlxuICAgICAgICAgICAgICogQXZhaWxhYmxlIHVuZGVyIHRoZSBNSVQgTGljZW5zZVxuICAgICAgICAgICAgICogRUNNQVNjcmlwdCBjb21wbGlhbnQsIHVuaWZvcm0gY3Jvc3MtYnJvd3NlciBzcGxpdCBtZXRob2RcbiAgICAgICAgICAgICAqL1xuXG4gICAgICAgICAgICAvKipcbiAgICAgICAgICAgICAqIFNwbGl0cyBhIHN0cmluZyBpbnRvIGFuIGFycmF5IG9mIHN0cmluZ3MgdXNpbmcgYSByZWdleCBvciBzdHJpbmcgc2VwYXJhdG9yLiBNYXRjaGVzIG9mIHRoZVxuICAgICAgICAgICAgICogc2VwYXJhdG9yIGFyZSBub3QgaW5jbHVkZWQgaW4gdGhlIHJlc3VsdCBhcnJheS4gSG93ZXZlciwgaWYgYHNlcGFyYXRvcmAgaXMgYSByZWdleCB0aGF0IGNvbnRhaW5zXG4gICAgICAgICAgICAgKiBjYXB0dXJpbmcgZ3JvdXBzLCBiYWNrcmVmZXJlbmNlcyBhcmUgc3BsaWNlZCBpbnRvIHRoZSByZXN1bHQgZWFjaCB0aW1lIGBzZXBhcmF0b3JgIGlzIG1hdGNoZWQuXG4gICAgICAgICAgICAgKiBGaXhlcyBicm93c2VyIGJ1Z3MgY29tcGFyZWQgdG8gdGhlIG5hdGl2ZSBgU3RyaW5nLnByb3RvdHlwZS5zcGxpdGAgYW5kIGNhbiBiZSB1c2VkIHJlbGlhYmx5XG4gICAgICAgICAgICAgKiBjcm9zcy1icm93c2VyLlxuICAgICAgICAgICAgICogQHBhcmFtIHtTdHJpbmd9IHN0ciBTdHJpbmcgdG8gc3BsaXQuXG4gICAgICAgICAgICAgKiBAcGFyYW0ge1JlZ0V4cHxTdHJpbmd9IHNlcGFyYXRvciBSZWdleCBvciBzdHJpbmcgdG8gdXNlIGZvciBzZXBhcmF0aW5nIHRoZSBzdHJpbmcuXG4gICAgICAgICAgICAgKiBAcGFyYW0ge051bWJlcn0gW2xpbWl0XSBNYXhpbXVtIG51bWJlciBvZiBpdGVtcyB0byBpbmNsdWRlIGluIHRoZSByZXN1bHQgYXJyYXkuXG4gICAgICAgICAgICAgKiBAcmV0dXJucyB7QXJyYXl9IEFycmF5IG9mIHN1YnN0cmluZ3MuXG4gICAgICAgICAgICAgKiBAZXhhbXBsZVxuICAgICAgICAgICAgICpcbiAgICAgICAgICAgICAqIC8vIEJhc2ljIHVzZVxuICAgICAgICAgICAgICogc3BsaXQoJ2EgYiBjIGQnLCAnICcpO1xuICAgICAgICAgICAgICogLy8gLT4gWydhJywgJ2InLCAnYycsICdkJ11cbiAgICAgICAgICAgICAqXG4gICAgICAgICAgICAgKiAvLyBXaXRoIGxpbWl0XG4gICAgICAgICAgICAgKiBzcGxpdCgnYSBiIGMgZCcsICcgJywgMik7XG4gICAgICAgICAgICAgKiAvLyAtPiBbJ2EnLCAnYiddXG4gICAgICAgICAgICAgKlxuICAgICAgICAgICAgICogLy8gQmFja3JlZmVyZW5jZXMgaW4gcmVzdWx0IGFycmF5XG4gICAgICAgICAgICAgKiBzcGxpdCgnLi53b3JkMSB3b3JkMi4uJywgLyhbYS16XSspKFxcZCspL2kpO1xuICAgICAgICAgICAgICogLy8gLT4gWycuLicsICd3b3JkJywgJzEnLCAnICcsICd3b3JkJywgJzInLCAnLi4nXVxuICAgICAgICAgICAgICovXG4gICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IChmdW5jdGlvbiBzcGxpdCh1bmRlZikge1xuXG4gICAgICAgICAgICAgICAgdmFyIG5hdGl2ZVNwbGl0ID0gU3RyaW5nLnByb3RvdHlwZS5zcGxpdCxcbiAgICAgICAgICAgICAgICAgICAgY29tcGxpYW50RXhlY05wY2cgPSAvKCk/Py8uZXhlYyhcIlwiKVsxXSA9PT0gdW5kZWYsXG5cbiAgICAgICAgICAgICAgICAvLyBOUENHOiBub25wYXJ0aWNpcGF0aW5nIGNhcHR1cmluZyBncm91cFxuICAgICAgICAgICAgICAgIHNlbGY7XG5cbiAgICAgICAgICAgICAgICBzZWxmID0gZnVuY3Rpb24gKHN0ciwgc2VwYXJhdG9yLCBsaW1pdCkge1xuICAgICAgICAgICAgICAgICAgICAvLyBJZiBgc2VwYXJhdG9yYCBpcyBub3QgYSByZWdleCwgdXNlIGBuYXRpdmVTcGxpdGBcbiAgICAgICAgICAgICAgICAgICAgaWYgKE9iamVjdC5wcm90b3R5cGUudG9TdHJpbmcuY2FsbChzZXBhcmF0b3IpICE9PSBcIltvYmplY3QgUmVnRXhwXVwiKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gbmF0aXZlU3BsaXQuY2FsbChzdHIsIHNlcGFyYXRvciwgbGltaXQpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIHZhciBvdXRwdXQgPSBbXSxcbiAgICAgICAgICAgICAgICAgICAgICAgIGZsYWdzID0gKHNlcGFyYXRvci5pZ25vcmVDYXNlID8gXCJpXCIgOiBcIlwiKSArIChzZXBhcmF0b3IubXVsdGlsaW5lID8gXCJtXCIgOiBcIlwiKSArIChzZXBhcmF0b3IuZXh0ZW5kZWQgPyBcInhcIiA6IFwiXCIpICsgKHNlcGFyYXRvci5zdGlja3kgPyBcInlcIiA6IFwiXCIpLFxuXG4gICAgICAgICAgICAgICAgICAgIC8vIEZpcmVmb3ggMytcbiAgICAgICAgICAgICAgICAgICAgbGFzdExhc3RJbmRleCA9IDAsXG5cbiAgICAgICAgICAgICAgICAgICAgLy8gTWFrZSBgZ2xvYmFsYCBhbmQgYXZvaWQgYGxhc3RJbmRleGAgaXNzdWVzIGJ5IHdvcmtpbmcgd2l0aCBhIGNvcHlcbiAgICAgICAgICAgICAgICAgICAgc2VwYXJhdG9yID0gbmV3IFJlZ0V4cChzZXBhcmF0b3Iuc291cmNlLCBmbGFncyArIFwiZ1wiKSxcbiAgICAgICAgICAgICAgICAgICAgICAgIHNlcGFyYXRvcjIsXG4gICAgICAgICAgICAgICAgICAgICAgICBtYXRjaCxcbiAgICAgICAgICAgICAgICAgICAgICAgIGxhc3RJbmRleCxcbiAgICAgICAgICAgICAgICAgICAgICAgIGxhc3RMZW5ndGg7XG4gICAgICAgICAgICAgICAgICAgIHN0ciArPSBcIlwiOyAvLyBUeXBlLWNvbnZlcnRcbiAgICAgICAgICAgICAgICAgICAgaWYgKCFjb21wbGlhbnRFeGVjTnBjZykge1xuICAgICAgICAgICAgICAgICAgICAgICAgLy8gRG9lc24ndCBuZWVkIGZsYWdzIGd5LCBidXQgdGhleSBkb24ndCBodXJ0XG4gICAgICAgICAgICAgICAgICAgICAgICBzZXBhcmF0b3IyID0gbmV3IFJlZ0V4cChcIl5cIiArIHNlcGFyYXRvci5zb3VyY2UgKyBcIiQoPyFcXFxccylcIiwgZmxhZ3MpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIC8qIFZhbHVlcyBmb3IgYGxpbWl0YCwgcGVyIHRoZSBzcGVjOlxuICAgICAgICAgICAgICAgICAgICAgKiBJZiB1bmRlZmluZWQ6IDQyOTQ5NjcyOTUgLy8gTWF0aC5wb3coMiwgMzIpIC0gMVxuICAgICAgICAgICAgICAgICAgICAgKiBJZiAwLCBJbmZpbml0eSwgb3IgTmFOOiAwXG4gICAgICAgICAgICAgICAgICAgICAqIElmIHBvc2l0aXZlIG51bWJlcjogbGltaXQgPSBNYXRoLmZsb29yKGxpbWl0KTsgaWYgKGxpbWl0ID4gNDI5NDk2NzI5NSkgbGltaXQgLT0gNDI5NDk2NzI5NjtcbiAgICAgICAgICAgICAgICAgICAgICogSWYgbmVnYXRpdmUgbnVtYmVyOiA0Mjk0OTY3Mjk2IC0gTWF0aC5mbG9vcihNYXRoLmFicyhsaW1pdCkpXG4gICAgICAgICAgICAgICAgICAgICAqIElmIG90aGVyOiBUeXBlLWNvbnZlcnQsIHRoZW4gdXNlIHRoZSBhYm92ZSBydWxlc1xuICAgICAgICAgICAgICAgICAgICAgKi9cbiAgICAgICAgICAgICAgICAgICAgbGltaXQgPSBsaW1pdCA9PT0gdW5kZWYgPyAtMSA+Pj4gMCA6IC8vIE1hdGgucG93KDIsIDMyKSAtIDFcbiAgICAgICAgICAgICAgICAgICAgbGltaXQgPj4+IDA7IC8vIFRvVWludDMyKGxpbWl0KVxuICAgICAgICAgICAgICAgICAgICB3aGlsZSAobWF0Y2ggPSBzZXBhcmF0b3IuZXhlYyhzdHIpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAvLyBgc2VwYXJhdG9yLmxhc3RJbmRleGAgaXMgbm90IHJlbGlhYmxlIGNyb3NzLWJyb3dzZXJcbiAgICAgICAgICAgICAgICAgICAgICAgIGxhc3RJbmRleCA9IG1hdGNoLmluZGV4ICsgbWF0Y2hbMF0ubGVuZ3RoO1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGxhc3RJbmRleCA+IGxhc3RMYXN0SW5kZXgpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBvdXRwdXQucHVzaChzdHIuc2xpY2UobGFzdExhc3RJbmRleCwgbWF0Y2guaW5kZXgpKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBGaXggYnJvd3NlcnMgd2hvc2UgYGV4ZWNgIG1ldGhvZHMgZG9uJ3QgY29uc2lzdGVudGx5IHJldHVybiBgdW5kZWZpbmVkYCBmb3JcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBub25wYXJ0aWNpcGF0aW5nIGNhcHR1cmluZyBncm91cHNcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoIWNvbXBsaWFudEV4ZWNOcGNnICYmIG1hdGNoLmxlbmd0aCA+IDEpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbWF0Y2hbMF0ucmVwbGFjZShzZXBhcmF0b3IyLCBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBmb3IgKHZhciBpID0gMTsgaSA8IGFyZ3VtZW50cy5sZW5ndGggLSAyOyBpKyspIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoYXJndW1lbnRzW2ldID09PSB1bmRlZikge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBtYXRjaFtpXSA9IHVuZGVmO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChtYXRjaC5sZW5ndGggPiAxICYmIG1hdGNoLmluZGV4IDwgc3RyLmxlbmd0aCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBBcnJheS5wcm90b3R5cGUucHVzaC5hcHBseShvdXRwdXQsIG1hdGNoLnNsaWNlKDEpKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgbGFzdExlbmd0aCA9IG1hdGNoWzBdLmxlbmd0aDtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBsYXN0TGFzdEluZGV4ID0gbGFzdEluZGV4O1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChvdXRwdXQubGVuZ3RoID49IGxpbWl0KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChzZXBhcmF0b3IubGFzdEluZGV4ID09PSBtYXRjaC5pbmRleCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNlcGFyYXRvci5sYXN0SW5kZXgrKzsgLy8gQXZvaWQgYW4gaW5maW5pdGUgbG9vcFxuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIGlmIChsYXN0TGFzdEluZGV4ID09PSBzdHIubGVuZ3RoKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAobGFzdExlbmd0aCB8fCAhc2VwYXJhdG9yLnRlc3QoXCJcIikpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBvdXRwdXQucHVzaChcIlwiKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIG91dHB1dC5wdXNoKHN0ci5zbGljZShsYXN0TGFzdEluZGV4KSk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIG91dHB1dC5sZW5ndGggPiBsaW1pdCA/IG91dHB1dC5zbGljZSgwLCBsaW1pdCkgOiBvdXRwdXQ7XG4gICAgICAgICAgICAgICAgfTtcblxuICAgICAgICAgICAgICAgIHJldHVybiBzZWxmO1xuICAgICAgICAgICAgfSkoKTtcbiAgICAgICAgfSwge31dLCA2OiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge30sIHt9XSwgNzogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHtcbiAgICAgICAgICAgIFwidXNlIHN0cmljdFwiO1xuXG4gICAgICAgICAgICB2YXIgT25lVmVyc2lvbkNvbnN0cmFpbnQgPSByZXF1aXJlKFwiaW5kaXZpZHVhbC9vbmUtdmVyc2lvblwiKTtcblxuICAgICAgICAgICAgdmFyIE1ZX1ZFUlNJT04gPSBcIjdcIjtcbiAgICAgICAgICAgIE9uZVZlcnNpb25Db25zdHJhaW50KFwiZXYtc3RvcmVcIiwgTVlfVkVSU0lPTik7XG5cbiAgICAgICAgICAgIHZhciBoYXNoS2V5ID0gXCJfX0VWX1NUT1JFX0tFWUBcIiArIE1ZX1ZFUlNJT047XG5cbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gRXZTdG9yZTtcblxuICAgICAgICAgICAgZnVuY3Rpb24gRXZTdG9yZShlbGVtKSB7XG4gICAgICAgICAgICAgICAgdmFyIGhhc2ggPSBlbGVtW2hhc2hLZXldO1xuXG4gICAgICAgICAgICAgICAgaWYgKCFoYXNoKSB7XG4gICAgICAgICAgICAgICAgICAgIGhhc2ggPSBlbGVtW2hhc2hLZXldID0ge307XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgcmV0dXJuIGhhc2g7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0sIHsgXCJpbmRpdmlkdWFsL29uZS12ZXJzaW9uXCI6IDkgfV0sIDg6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICAoZnVuY3Rpb24gKGdsb2JhbCkge1xuICAgICAgICAgICAgICAgIFwidXNlIHN0cmljdFwiO1xuXG4gICAgICAgICAgICAgICAgLypnbG9iYWwgd2luZG93LCBnbG9iYWwqL1xuXG4gICAgICAgICAgICAgICAgdmFyIHJvb3QgPSB0eXBlb2Ygd2luZG93ICE9PSBcInVuZGVmaW5lZFwiID8gd2luZG93IDogdHlwZW9mIGdsb2JhbCAhPT0gXCJ1bmRlZmluZWRcIiA/IGdsb2JhbCA6IHt9O1xuXG4gICAgICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBJbmRpdmlkdWFsO1xuXG4gICAgICAgICAgICAgICAgZnVuY3Rpb24gSW5kaXZpZHVhbChrZXksIHZhbHVlKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmIChrZXkgaW4gcm9vdCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHJvb3Rba2V5XTtcbiAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgIHJvb3Rba2V5XSA9IHZhbHVlO1xuXG4gICAgICAgICAgICAgICAgICAgIHJldHVybiB2YWx1ZTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9KS5jYWxsKHRoaXMsIHR5cGVvZiBnbG9iYWwgIT09IFwidW5kZWZpbmVkXCIgPyBnbG9iYWwgOiB0eXBlb2Ygc2VsZiAhPT0gXCJ1bmRlZmluZWRcIiA/IHNlbGYgOiB0eXBlb2Ygd2luZG93ICE9PSBcInVuZGVmaW5lZFwiID8gd2luZG93IDoge30pO1xuICAgICAgICB9LCB7fV0sIDk6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICBcInVzZSBzdHJpY3RcIjtcblxuICAgICAgICAgICAgdmFyIEluZGl2aWR1YWwgPSByZXF1aXJlKFwiLi9pbmRleC5qc1wiKTtcblxuICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBPbmVWZXJzaW9uO1xuXG4gICAgICAgICAgICBmdW5jdGlvbiBPbmVWZXJzaW9uKG1vZHVsZU5hbWUsIHZlcnNpb24sIGRlZmF1bHRWYWx1ZSkge1xuICAgICAgICAgICAgICAgIHZhciBrZXkgPSBcIl9fSU5ESVZJRFVBTF9PTkVfVkVSU0lPTl9cIiArIG1vZHVsZU5hbWU7XG4gICAgICAgICAgICAgICAgdmFyIGVuZm9yY2VLZXkgPSBrZXkgKyBcIl9FTkZPUkNFX1NJTkdMRVRPTlwiO1xuXG4gICAgICAgICAgICAgICAgdmFyIHZlcnNpb25WYWx1ZSA9IEluZGl2aWR1YWwoZW5mb3JjZUtleSwgdmVyc2lvbik7XG5cbiAgICAgICAgICAgICAgICBpZiAodmVyc2lvblZhbHVlICE9PSB2ZXJzaW9uKSB7XG4gICAgICAgICAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcihcIkNhbiBvbmx5IGhhdmUgb25lIGNvcHkgb2YgXCIgKyBtb2R1bGVOYW1lICsgXCIuXFxuXCIgKyBcIllvdSBhbHJlYWR5IGhhdmUgdmVyc2lvbiBcIiArIHZlcnNpb25WYWx1ZSArIFwiIGluc3RhbGxlZC5cXG5cIiArIFwiVGhpcyBtZWFucyB5b3UgY2Fubm90IGluc3RhbGwgdmVyc2lvbiBcIiArIHZlcnNpb24pO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHJldHVybiBJbmRpdmlkdWFsKGtleSwgZGVmYXVsdFZhbHVlKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSwgeyBcIi4vaW5kZXguanNcIjogOCB9XSwgMTA6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICAoZnVuY3Rpb24gKGdsb2JhbCkge1xuICAgICAgICAgICAgICAgIHZhciB0b3BMZXZlbCA9IHR5cGVvZiBnbG9iYWwgIT09IFwidW5kZWZpbmVkXCIgPyBnbG9iYWwgOiB0eXBlb2Ygd2luZG93ICE9PSBcInVuZGVmaW5lZFwiID8gd2luZG93IDoge307XG4gICAgICAgICAgICAgICAgdmFyIG1pbkRvYyA9IHJlcXVpcmUoXCJtaW4tZG9jdW1lbnRcIik7XG5cbiAgICAgICAgICAgICAgICBpZiAodHlwZW9mIGRvY3VtZW50ICE9PSBcInVuZGVmaW5lZFwiKSB7XG4gICAgICAgICAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gZG9jdW1lbnQ7XG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgdmFyIGRvY2N5ID0gdG9wTGV2ZWxbXCJfX0dMT0JBTF9ET0NVTUVOVF9DQUNIRUA0XCJdO1xuXG4gICAgICAgICAgICAgICAgICAgIGlmICghZG9jY3kpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGRvY2N5ID0gdG9wTGV2ZWxbXCJfX0dMT0JBTF9ET0NVTUVOVF9DQUNIRUA0XCJdID0gbWluRG9jO1xuICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBkb2NjeTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9KS5jYWxsKHRoaXMsIHR5cGVvZiBnbG9iYWwgIT09IFwidW5kZWZpbmVkXCIgPyBnbG9iYWwgOiB0eXBlb2Ygc2VsZiAhPT0gXCJ1bmRlZmluZWRcIiA/IHNlbGYgOiB0eXBlb2Ygd2luZG93ICE9PSBcInVuZGVmaW5lZFwiID8gd2luZG93IDoge30pO1xuICAgICAgICB9LCB7IFwibWluLWRvY3VtZW50XCI6IDYgfV0sIDExOiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge1xuICAgICAgICAgICAgXCJ1c2Ugc3RyaWN0XCI7XG5cbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gaXNPYmplY3QoeCkge1xuICAgICAgICAgICAgICAgIHJldHVybiB0eXBlb2YgeCA9PT0gXCJvYmplY3RcIiAmJiB4ICE9PSBudWxsO1xuICAgICAgICAgICAgfTtcbiAgICAgICAgfSwge31dLCAxMjogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHtcbiAgICAgICAgICAgIHZhciBuYXRpdmVJc0FycmF5ID0gQXJyYXkuaXNBcnJheTtcbiAgICAgICAgICAgIHZhciB0b1N0cmluZyA9IE9iamVjdC5wcm90b3R5cGUudG9TdHJpbmc7XG5cbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gbmF0aXZlSXNBcnJheSB8fCBpc0FycmF5O1xuXG4gICAgICAgICAgICBmdW5jdGlvbiBpc0FycmF5KG9iaikge1xuICAgICAgICAgICAgICAgIHJldHVybiB0b1N0cmluZy5jYWxsKG9iaikgPT09IFwiW29iamVjdCBBcnJheV1cIjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSwge31dLCAxMzogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHtcbiAgICAgICAgICAgIHZhciBwYXRjaCA9IHJlcXVpcmUoXCIuL3Zkb20vcGF0Y2guanNcIik7XG5cbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gcGF0Y2g7XG4gICAgICAgIH0sIHsgXCIuL3Zkb20vcGF0Y2guanNcIjogMTggfV0sIDE0OiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge1xuICAgICAgICAgICAgdmFyIGlzT2JqZWN0ID0gcmVxdWlyZShcImlzLW9iamVjdFwiKTtcbiAgICAgICAgICAgIHZhciBpc0hvb2sgPSByZXF1aXJlKFwiLi4vdm5vZGUvaXMtdmhvb2suanNcIik7XG5cbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gYXBwbHlQcm9wZXJ0aWVzO1xuXG4gICAgICAgICAgICBmdW5jdGlvbiBhcHBseVByb3BlcnRpZXMobm9kZSwgcHJvcHMsIHByZXZpb3VzKSB7XG4gICAgICAgICAgICAgICAgZm9yICh2YXIgcHJvcE5hbWUgaW4gcHJvcHMpIHtcbiAgICAgICAgICAgICAgICAgICAgdmFyIHByb3BWYWx1ZSA9IHByb3BzW3Byb3BOYW1lXTtcblxuICAgICAgICAgICAgICAgICAgICBpZiAocHJvcFZhbHVlID09PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJlbW92ZVByb3BlcnR5KG5vZGUsIHByb3BOYW1lLCBwcm9wVmFsdWUsIHByZXZpb3VzKTtcbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIGlmIChpc0hvb2socHJvcFZhbHVlKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgcmVtb3ZlUHJvcGVydHkobm9kZSwgcHJvcE5hbWUsIHByb3BWYWx1ZSwgcHJldmlvdXMpO1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHByb3BWYWx1ZS5ob29rKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcHJvcFZhbHVlLmhvb2sobm9kZSwgcHJvcE5hbWUsIHByZXZpb3VzID8gcHJldmlvdXNbcHJvcE5hbWVdIDogdW5kZWZpbmVkKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChpc09iamVjdChwcm9wVmFsdWUpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcGF0Y2hPYmplY3Qobm9kZSwgcHJvcHMsIHByZXZpb3VzLCBwcm9wTmFtZSwgcHJvcFZhbHVlKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgbm9kZVtwcm9wTmFtZV0gPSBwcm9wVmFsdWU7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIHJlbW92ZVByb3BlcnR5KG5vZGUsIHByb3BOYW1lLCBwcm9wVmFsdWUsIHByZXZpb3VzKSB7XG4gICAgICAgICAgICAgICAgaWYgKHByZXZpb3VzKSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciBwcmV2aW91c1ZhbHVlID0gcHJldmlvdXNbcHJvcE5hbWVdO1xuXG4gICAgICAgICAgICAgICAgICAgIGlmICghaXNIb29rKHByZXZpb3VzVmFsdWUpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAocHJvcE5hbWUgPT09IFwiYXR0cmlidXRlc1wiKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgZm9yICh2YXIgYXR0ck5hbWUgaW4gcHJldmlvdXNWYWx1ZSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBub2RlLnJlbW92ZUF0dHJpYnV0ZShhdHRyTmFtZSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIGlmIChwcm9wTmFtZSA9PT0gXCJzdHlsZVwiKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgZm9yICh2YXIgaSBpbiBwcmV2aW91c1ZhbHVlKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG5vZGUuc3R5bGVbaV0gPSBcIlwiO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAodHlwZW9mIHByZXZpb3VzVmFsdWUgPT09IFwic3RyaW5nXCIpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBub2RlW3Byb3BOYW1lXSA9IFwiXCI7XG4gICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIG5vZGVbcHJvcE5hbWVdID0gbnVsbDtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIGlmIChwcmV2aW91c1ZhbHVlLnVuaG9vaykge1xuICAgICAgICAgICAgICAgICAgICAgICAgcHJldmlvdXNWYWx1ZS51bmhvb2sobm9kZSwgcHJvcE5hbWUsIHByb3BWYWx1ZSk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIHBhdGNoT2JqZWN0KG5vZGUsIHByb3BzLCBwcmV2aW91cywgcHJvcE5hbWUsIHByb3BWYWx1ZSkge1xuICAgICAgICAgICAgICAgIHZhciBwcmV2aW91c1ZhbHVlID0gcHJldmlvdXMgPyBwcmV2aW91c1twcm9wTmFtZV0gOiB1bmRlZmluZWQ7XG5cbiAgICAgICAgICAgICAgICAvLyBTZXQgYXR0cmlidXRlc1xuICAgICAgICAgICAgICAgIGlmIChwcm9wTmFtZSA9PT0gXCJhdHRyaWJ1dGVzXCIpIHtcbiAgICAgICAgICAgICAgICAgICAgZm9yICh2YXIgYXR0ck5hbWUgaW4gcHJvcFZhbHVlKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICB2YXIgYXR0clZhbHVlID0gcHJvcFZhbHVlW2F0dHJOYW1lXTtcblxuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGF0dHJWYWx1ZSA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgbm9kZS5yZW1vdmVBdHRyaWJ1dGUoYXR0ck5hbWUpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBub2RlLnNldEF0dHJpYnV0ZShhdHRyTmFtZSwgYXR0clZhbHVlKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICBpZiAocHJldmlvdXNWYWx1ZSAmJiBpc09iamVjdChwcmV2aW91c1ZhbHVlKSAmJiBnZXRQcm90b3R5cGUocHJldmlvdXNWYWx1ZSkgIT09IGdldFByb3RvdHlwZShwcm9wVmFsdWUpKSB7XG4gICAgICAgICAgICAgICAgICAgIG5vZGVbcHJvcE5hbWVdID0gcHJvcFZhbHVlO1xuICAgICAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgaWYgKCFpc09iamVjdChub2RlW3Byb3BOYW1lXSkpIHtcbiAgICAgICAgICAgICAgICAgICAgbm9kZVtwcm9wTmFtZV0gPSB7fTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICB2YXIgcmVwbGFjZXIgPSBwcm9wTmFtZSA9PT0gXCJzdHlsZVwiID8gXCJcIiA6IHVuZGVmaW5lZDtcblxuICAgICAgICAgICAgICAgIGZvciAodmFyIGsgaW4gcHJvcFZhbHVlKSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciB2YWx1ZSA9IHByb3BWYWx1ZVtrXTtcbiAgICAgICAgICAgICAgICAgICAgbm9kZVtwcm9wTmFtZV1ba10gPSB2YWx1ZSA9PT0gdW5kZWZpbmVkID8gcmVwbGFjZXIgOiB2YWx1ZTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIGdldFByb3RvdHlwZSh2YWx1ZSkge1xuICAgICAgICAgICAgICAgIGlmIChPYmplY3QuZ2V0UHJvdG90eXBlT2YpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIE9iamVjdC5nZXRQcm90b3R5cGVPZih2YWx1ZSk7XG4gICAgICAgICAgICAgICAgfSBlbHNlIGlmICh2YWx1ZS5fX3Byb3RvX18pIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHZhbHVlLl9fcHJvdG9fXztcbiAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKHZhbHVlLmNvbnN0cnVjdG9yKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiB2YWx1ZS5jb25zdHJ1Y3Rvci5wcm90b3R5cGU7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9LCB7IFwiLi4vdm5vZGUvaXMtdmhvb2suanNcIjogMjYsIFwiaXMtb2JqZWN0XCI6IDExIH1dLCAxNTogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHtcbiAgICAgICAgICAgIHZhciBkb2N1bWVudCA9IHJlcXVpcmUoXCJnbG9iYWwvZG9jdW1lbnRcIik7XG5cbiAgICAgICAgICAgIHZhciBhcHBseVByb3BlcnRpZXMgPSByZXF1aXJlKFwiLi9hcHBseS1wcm9wZXJ0aWVzXCIpO1xuXG4gICAgICAgICAgICB2YXIgaXNWTm9kZSA9IHJlcXVpcmUoXCIuLi92bm9kZS9pcy12bm9kZS5qc1wiKTtcbiAgICAgICAgICAgIHZhciBpc1ZUZXh0ID0gcmVxdWlyZShcIi4uL3Zub2RlL2lzLXZ0ZXh0LmpzXCIpO1xuICAgICAgICAgICAgdmFyIGlzV2lkZ2V0ID0gcmVxdWlyZShcIi4uL3Zub2RlL2lzLXdpZGdldC5qc1wiKTtcbiAgICAgICAgICAgIHZhciBoYW5kbGVUaHVuayA9IHJlcXVpcmUoXCIuLi92bm9kZS9oYW5kbGUtdGh1bmsuanNcIik7XG5cbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gY3JlYXRlRWxlbWVudDtcblxuICAgICAgICAgICAgZnVuY3Rpb24gY3JlYXRlRWxlbWVudCh2bm9kZSwgb3B0cykge1xuICAgICAgICAgICAgICAgIHZhciBkb2MgPSBvcHRzID8gb3B0cy5kb2N1bWVudCB8fCBkb2N1bWVudCA6IGRvY3VtZW50O1xuICAgICAgICAgICAgICAgIHZhciB3YXJuID0gb3B0cyA/IG9wdHMud2FybiA6IG51bGw7XG5cbiAgICAgICAgICAgICAgICB2bm9kZSA9IGhhbmRsZVRodW5rKHZub2RlKS5hO1xuXG4gICAgICAgICAgICAgICAgaWYgKGlzV2lkZ2V0KHZub2RlKSkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gdm5vZGUuaW5pdCgpO1xuICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoaXNWVGV4dCh2bm9kZSkpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGRvYy5jcmVhdGVUZXh0Tm9kZSh2bm9kZS50ZXh0KTtcbiAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKCFpc1ZOb2RlKHZub2RlKSkge1xuICAgICAgICAgICAgICAgICAgICBpZiAod2Fybikge1xuICAgICAgICAgICAgICAgICAgICAgICAgd2FybihcIkl0ZW0gaXMgbm90IGEgdmFsaWQgdmlydHVhbCBkb20gbm9kZVwiLCB2bm9kZSk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIG51bGw7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgdmFyIG5vZGUgPSB2bm9kZS5uYW1lc3BhY2UgPT09IG51bGwgPyBkb2MuY3JlYXRlRWxlbWVudCh2bm9kZS50YWdOYW1lKSA6IGRvYy5jcmVhdGVFbGVtZW50TlModm5vZGUubmFtZXNwYWNlLCB2bm9kZS50YWdOYW1lKTtcblxuICAgICAgICAgICAgICAgIHZhciBwcm9wcyA9IHZub2RlLnByb3BlcnRpZXM7XG4gICAgICAgICAgICAgICAgYXBwbHlQcm9wZXJ0aWVzKG5vZGUsIHByb3BzKTtcblxuICAgICAgICAgICAgICAgIHZhciBjaGlsZHJlbiA9IHZub2RlLmNoaWxkcmVuO1xuXG4gICAgICAgICAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCBjaGlsZHJlbi5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgICAgICAgICB2YXIgY2hpbGROb2RlID0gY3JlYXRlRWxlbWVudChjaGlsZHJlbltpXSwgb3B0cyk7XG4gICAgICAgICAgICAgICAgICAgIGlmIChjaGlsZE5vZGUpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIG5vZGUuYXBwZW5kQ2hpbGQoY2hpbGROb2RlKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHJldHVybiBub2RlO1xuICAgICAgICAgICAgfVxuICAgICAgICB9LCB7IFwiLi4vdm5vZGUvaGFuZGxlLXRodW5rLmpzXCI6IDI0LCBcIi4uL3Zub2RlL2lzLXZub2RlLmpzXCI6IDI3LCBcIi4uL3Zub2RlL2lzLXZ0ZXh0LmpzXCI6IDI4LCBcIi4uL3Zub2RlL2lzLXdpZGdldC5qc1wiOiAyOSwgXCIuL2FwcGx5LXByb3BlcnRpZXNcIjogMTQsIFwiZ2xvYmFsL2RvY3VtZW50XCI6IDEwIH1dLCAxNjogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHtcbiAgICAgICAgICAgIC8vIE1hcHMgYSB2aXJ0dWFsIERPTSB0cmVlIG9udG8gYSByZWFsIERPTSB0cmVlIGluIGFuIGVmZmljaWVudCBtYW5uZXIuXG4gICAgICAgICAgICAvLyBXZSBkb24ndCB3YW50IHRvIHJlYWQgYWxsIG9mIHRoZSBET00gbm9kZXMgaW4gdGhlIHRyZWUgc28gd2UgdXNlXG4gICAgICAgICAgICAvLyB0aGUgaW4tb3JkZXIgdHJlZSBpbmRleGluZyB0byBlbGltaW5hdGUgcmVjdXJzaW9uIGRvd24gY2VydGFpbiBicmFuY2hlcy5cbiAgICAgICAgICAgIC8vIFdlIG9ubHkgcmVjdXJzZSBpbnRvIGEgRE9NIG5vZGUgaWYgd2Uga25vdyB0aGF0IGl0IGNvbnRhaW5zIGEgY2hpbGQgb2ZcbiAgICAgICAgICAgIC8vIGludGVyZXN0LlxuXG4gICAgICAgICAgICB2YXIgbm9DaGlsZCA9IHt9O1xuXG4gICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IGRvbUluZGV4O1xuXG4gICAgICAgICAgICBmdW5jdGlvbiBkb21JbmRleChyb290Tm9kZSwgdHJlZSwgaW5kaWNlcywgbm9kZXMpIHtcbiAgICAgICAgICAgICAgICBpZiAoIWluZGljZXMgfHwgaW5kaWNlcy5sZW5ndGggPT09IDApIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHt9O1xuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIGluZGljZXMuc29ydChhc2NlbmRpbmcpO1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gcmVjdXJzZShyb290Tm9kZSwgdHJlZSwgaW5kaWNlcywgbm9kZXMsIDApO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZnVuY3Rpb24gcmVjdXJzZShyb290Tm9kZSwgdHJlZSwgaW5kaWNlcywgbm9kZXMsIHJvb3RJbmRleCkge1xuICAgICAgICAgICAgICAgIG5vZGVzID0gbm9kZXMgfHwge307XG5cbiAgICAgICAgICAgICAgICBpZiAocm9vdE5vZGUpIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKGluZGV4SW5SYW5nZShpbmRpY2VzLCByb290SW5kZXgsIHJvb3RJbmRleCkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIG5vZGVzW3Jvb3RJbmRleF0gPSByb290Tm9kZTtcbiAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgIHZhciB2Q2hpbGRyZW4gPSB0cmVlLmNoaWxkcmVuO1xuXG4gICAgICAgICAgICAgICAgICAgIGlmICh2Q2hpbGRyZW4pIHtcblxuICAgICAgICAgICAgICAgICAgICAgICAgdmFyIGNoaWxkTm9kZXMgPSByb290Tm9kZS5jaGlsZE5vZGVzO1xuXG4gICAgICAgICAgICAgICAgICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IHRyZWUuY2hpbGRyZW4ubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICByb290SW5kZXggKz0gMTtcblxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZhciB2Q2hpbGQgPSB2Q2hpbGRyZW5baV0gfHwgbm9DaGlsZDtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB2YXIgbmV4dEluZGV4ID0gcm9vdEluZGV4ICsgKHZDaGlsZC5jb3VudCB8fCAwKTtcblxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIHNraXAgcmVjdXJzaW9uIGRvd24gdGhlIHRyZWUgaWYgdGhlcmUgYXJlIG5vIG5vZGVzIGRvd24gaGVyZVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChpbmRleEluUmFuZ2UoaW5kaWNlcywgcm9vdEluZGV4LCBuZXh0SW5kZXgpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlY3Vyc2UoY2hpbGROb2Rlc1tpXSwgdkNoaWxkLCBpbmRpY2VzLCBub2Rlcywgcm9vdEluZGV4KTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICByb290SW5kZXggPSBuZXh0SW5kZXg7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICByZXR1cm4gbm9kZXM7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIC8vIEJpbmFyeSBzZWFyY2ggZm9yIGFuIGluZGV4IGluIHRoZSBpbnRlcnZhbCBbbGVmdCwgcmlnaHRdXG4gICAgICAgICAgICBmdW5jdGlvbiBpbmRleEluUmFuZ2UoaW5kaWNlcywgbGVmdCwgcmlnaHQpIHtcbiAgICAgICAgICAgICAgICBpZiAoaW5kaWNlcy5sZW5ndGggPT09IDApIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHZhciBtaW5JbmRleCA9IDA7XG4gICAgICAgICAgICAgICAgdmFyIG1heEluZGV4ID0gaW5kaWNlcy5sZW5ndGggLSAxO1xuICAgICAgICAgICAgICAgIHZhciBjdXJyZW50SW5kZXg7XG4gICAgICAgICAgICAgICAgdmFyIGN1cnJlbnRJdGVtO1xuXG4gICAgICAgICAgICAgICAgd2hpbGUgKG1pbkluZGV4IDw9IG1heEluZGV4KSB7XG4gICAgICAgICAgICAgICAgICAgIGN1cnJlbnRJbmRleCA9IChtYXhJbmRleCArIG1pbkluZGV4KSAvIDIgPj4gMDtcbiAgICAgICAgICAgICAgICAgICAgY3VycmVudEl0ZW0gPSBpbmRpY2VzW2N1cnJlbnRJbmRleF07XG5cbiAgICAgICAgICAgICAgICAgICAgaWYgKG1pbkluZGV4ID09PSBtYXhJbmRleCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGN1cnJlbnRJdGVtID49IGxlZnQgJiYgY3VycmVudEl0ZW0gPD0gcmlnaHQ7XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoY3VycmVudEl0ZW0gPCBsZWZ0KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBtaW5JbmRleCA9IGN1cnJlbnRJbmRleCArIDE7XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoY3VycmVudEl0ZW0gPiByaWdodCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgbWF4SW5kZXggPSBjdXJyZW50SW5kZXggLSAxO1xuICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIGFzY2VuZGluZyhhLCBiKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGEgPiBiID8gMSA6IC0xO1xuICAgICAgICAgICAgfVxuICAgICAgICB9LCB7fV0sIDE3OiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge1xuICAgICAgICAgICAgdmFyIGFwcGx5UHJvcGVydGllcyA9IHJlcXVpcmUoXCIuL2FwcGx5LXByb3BlcnRpZXNcIik7XG5cbiAgICAgICAgICAgIHZhciBpc1dpZGdldCA9IHJlcXVpcmUoXCIuLi92bm9kZS9pcy13aWRnZXQuanNcIik7XG4gICAgICAgICAgICB2YXIgVlBhdGNoID0gcmVxdWlyZShcIi4uL3Zub2RlL3ZwYXRjaC5qc1wiKTtcblxuICAgICAgICAgICAgdmFyIHVwZGF0ZVdpZGdldCA9IHJlcXVpcmUoXCIuL3VwZGF0ZS13aWRnZXRcIik7XG5cbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gYXBwbHlQYXRjaDtcblxuICAgICAgICAgICAgZnVuY3Rpb24gYXBwbHlQYXRjaCh2cGF0Y2gsIGRvbU5vZGUsIHJlbmRlck9wdGlvbnMpIHtcbiAgICAgICAgICAgICAgICB2YXIgdHlwZSA9IHZwYXRjaC50eXBlO1xuICAgICAgICAgICAgICAgIHZhciB2Tm9kZSA9IHZwYXRjaC52Tm9kZTtcbiAgICAgICAgICAgICAgICB2YXIgcGF0Y2ggPSB2cGF0Y2gucGF0Y2g7XG5cbiAgICAgICAgICAgICAgICBzd2l0Y2ggKHR5cGUpIHtcbiAgICAgICAgICAgICAgICAgICAgY2FzZSBWUGF0Y2guUkVNT1ZFOlxuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHJlbW92ZU5vZGUoZG9tTm9kZSwgdk5vZGUpO1xuICAgICAgICAgICAgICAgICAgICBjYXNlIFZQYXRjaC5JTlNFUlQ6XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gaW5zZXJ0Tm9kZShkb21Ob2RlLCBwYXRjaCwgcmVuZGVyT3B0aW9ucyk7XG4gICAgICAgICAgICAgICAgICAgIGNhc2UgVlBhdGNoLlZURVhUOlxuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHN0cmluZ1BhdGNoKGRvbU5vZGUsIHZOb2RlLCBwYXRjaCwgcmVuZGVyT3B0aW9ucyk7XG4gICAgICAgICAgICAgICAgICAgIGNhc2UgVlBhdGNoLldJREdFVDpcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiB3aWRnZXRQYXRjaChkb21Ob2RlLCB2Tm9kZSwgcGF0Y2gsIHJlbmRlck9wdGlvbnMpO1xuICAgICAgICAgICAgICAgICAgICBjYXNlIFZQYXRjaC5WTk9ERTpcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiB2Tm9kZVBhdGNoKGRvbU5vZGUsIHZOb2RlLCBwYXRjaCwgcmVuZGVyT3B0aW9ucyk7XG4gICAgICAgICAgICAgICAgICAgIGNhc2UgVlBhdGNoLk9SREVSOlxuICAgICAgICAgICAgICAgICAgICAgICAgcmVvcmRlckNoaWxkcmVuKGRvbU5vZGUsIHBhdGNoKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBkb21Ob2RlO1xuICAgICAgICAgICAgICAgICAgICBjYXNlIFZQYXRjaC5QUk9QUzpcbiAgICAgICAgICAgICAgICAgICAgICAgIGFwcGx5UHJvcGVydGllcyhkb21Ob2RlLCBwYXRjaCwgdk5vZGUucHJvcGVydGllcyk7XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gZG9tTm9kZTtcbiAgICAgICAgICAgICAgICAgICAgY2FzZSBWUGF0Y2guVEhVTks6XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gcmVwbGFjZVJvb3QoZG9tTm9kZSwgcmVuZGVyT3B0aW9ucy5wYXRjaChkb21Ob2RlLCBwYXRjaCwgcmVuZGVyT3B0aW9ucykpO1xuICAgICAgICAgICAgICAgICAgICBkZWZhdWx0OlxuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGRvbU5vZGU7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBmdW5jdGlvbiByZW1vdmVOb2RlKGRvbU5vZGUsIHZOb2RlKSB7XG4gICAgICAgICAgICAgICAgdmFyIHBhcmVudE5vZGUgPSBkb21Ob2RlLnBhcmVudE5vZGU7XG5cbiAgICAgICAgICAgICAgICBpZiAocGFyZW50Tm9kZSkge1xuICAgICAgICAgICAgICAgICAgICBwYXJlbnROb2RlLnJlbW92ZUNoaWxkKGRvbU5vZGUpO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIGRlc3Ryb3lXaWRnZXQoZG9tTm9kZSwgdk5vZGUpO1xuXG4gICAgICAgICAgICAgICAgcmV0dXJuIG51bGw7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIGluc2VydE5vZGUocGFyZW50Tm9kZSwgdk5vZGUsIHJlbmRlck9wdGlvbnMpIHtcbiAgICAgICAgICAgICAgICB2YXIgbmV3Tm9kZSA9IHJlbmRlck9wdGlvbnMucmVuZGVyKHZOb2RlLCByZW5kZXJPcHRpb25zKTtcblxuICAgICAgICAgICAgICAgIGlmIChwYXJlbnROb2RlKSB7XG4gICAgICAgICAgICAgICAgICAgIHBhcmVudE5vZGUuYXBwZW5kQ2hpbGQobmV3Tm9kZSk7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgcmV0dXJuIHBhcmVudE5vZGU7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIHN0cmluZ1BhdGNoKGRvbU5vZGUsIGxlZnRWTm9kZSwgdlRleHQsIHJlbmRlck9wdGlvbnMpIHtcbiAgICAgICAgICAgICAgICB2YXIgbmV3Tm9kZTtcblxuICAgICAgICAgICAgICAgIGlmIChkb21Ob2RlLm5vZGVUeXBlID09PSAzKSB7XG4gICAgICAgICAgICAgICAgICAgIGRvbU5vZGUucmVwbGFjZURhdGEoMCwgZG9tTm9kZS5sZW5ndGgsIHZUZXh0LnRleHQpO1xuICAgICAgICAgICAgICAgICAgICBuZXdOb2RlID0gZG9tTm9kZTtcbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICB2YXIgcGFyZW50Tm9kZSA9IGRvbU5vZGUucGFyZW50Tm9kZTtcbiAgICAgICAgICAgICAgICAgICAgbmV3Tm9kZSA9IHJlbmRlck9wdGlvbnMucmVuZGVyKHZUZXh0LCByZW5kZXJPcHRpb25zKTtcblxuICAgICAgICAgICAgICAgICAgICBpZiAocGFyZW50Tm9kZSAmJiBuZXdOb2RlICE9PSBkb21Ob2RlKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBwYXJlbnROb2RlLnJlcGxhY2VDaGlsZChuZXdOb2RlLCBkb21Ob2RlKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHJldHVybiBuZXdOb2RlO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBmdW5jdGlvbiB3aWRnZXRQYXRjaChkb21Ob2RlLCBsZWZ0Vk5vZGUsIHdpZGdldCwgcmVuZGVyT3B0aW9ucykge1xuICAgICAgICAgICAgICAgIHZhciB1cGRhdGluZyA9IHVwZGF0ZVdpZGdldChsZWZ0Vk5vZGUsIHdpZGdldCk7XG4gICAgICAgICAgICAgICAgdmFyIG5ld05vZGU7XG5cbiAgICAgICAgICAgICAgICBpZiAodXBkYXRpbmcpIHtcbiAgICAgICAgICAgICAgICAgICAgbmV3Tm9kZSA9IHdpZGdldC51cGRhdGUobGVmdFZOb2RlLCBkb21Ob2RlKSB8fCBkb21Ob2RlO1xuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIG5ld05vZGUgPSByZW5kZXJPcHRpb25zLnJlbmRlcih3aWRnZXQsIHJlbmRlck9wdGlvbnMpO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHZhciBwYXJlbnROb2RlID0gZG9tTm9kZS5wYXJlbnROb2RlO1xuXG4gICAgICAgICAgICAgICAgaWYgKHBhcmVudE5vZGUgJiYgbmV3Tm9kZSAhPT0gZG9tTm9kZSkge1xuICAgICAgICAgICAgICAgICAgICBwYXJlbnROb2RlLnJlcGxhY2VDaGlsZChuZXdOb2RlLCBkb21Ob2RlKTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICBpZiAoIXVwZGF0aW5nKSB7XG4gICAgICAgICAgICAgICAgICAgIGRlc3Ryb3lXaWRnZXQoZG9tTm9kZSwgbGVmdFZOb2RlKTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICByZXR1cm4gbmV3Tm9kZTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZnVuY3Rpb24gdk5vZGVQYXRjaChkb21Ob2RlLCBsZWZ0Vk5vZGUsIHZOb2RlLCByZW5kZXJPcHRpb25zKSB7XG4gICAgICAgICAgICAgICAgdmFyIHBhcmVudE5vZGUgPSBkb21Ob2RlLnBhcmVudE5vZGU7XG4gICAgICAgICAgICAgICAgdmFyIG5ld05vZGUgPSByZW5kZXJPcHRpb25zLnJlbmRlcih2Tm9kZSwgcmVuZGVyT3B0aW9ucyk7XG5cbiAgICAgICAgICAgICAgICBpZiAocGFyZW50Tm9kZSAmJiBuZXdOb2RlICE9PSBkb21Ob2RlKSB7XG4gICAgICAgICAgICAgICAgICAgIHBhcmVudE5vZGUucmVwbGFjZUNoaWxkKG5ld05vZGUsIGRvbU5vZGUpO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHJldHVybiBuZXdOb2RlO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBmdW5jdGlvbiBkZXN0cm95V2lkZ2V0KGRvbU5vZGUsIHcpIHtcbiAgICAgICAgICAgICAgICBpZiAodHlwZW9mIHcuZGVzdHJveSA9PT0gXCJmdW5jdGlvblwiICYmIGlzV2lkZ2V0KHcpKSB7XG4gICAgICAgICAgICAgICAgICAgIHcuZGVzdHJveShkb21Ob2RlKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIHJlb3JkZXJDaGlsZHJlbihkb21Ob2RlLCBtb3Zlcykge1xuICAgICAgICAgICAgICAgIHZhciBjaGlsZE5vZGVzID0gZG9tTm9kZS5jaGlsZE5vZGVzO1xuICAgICAgICAgICAgICAgIHZhciBrZXlNYXAgPSB7fTtcbiAgICAgICAgICAgICAgICB2YXIgbm9kZTtcbiAgICAgICAgICAgICAgICB2YXIgcmVtb3ZlO1xuICAgICAgICAgICAgICAgIHZhciBpbnNlcnQ7XG5cbiAgICAgICAgICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IG1vdmVzLnJlbW92ZXMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgICAgICAgICAgcmVtb3ZlID0gbW92ZXMucmVtb3Zlc1tpXTtcbiAgICAgICAgICAgICAgICAgICAgbm9kZSA9IGNoaWxkTm9kZXNbcmVtb3ZlLmZyb21dO1xuICAgICAgICAgICAgICAgICAgICBpZiAocmVtb3ZlLmtleSkge1xuICAgICAgICAgICAgICAgICAgICAgICAga2V5TWFwW3JlbW92ZS5rZXldID0gbm9kZTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICBkb21Ob2RlLnJlbW92ZUNoaWxkKG5vZGUpO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHZhciBsZW5ndGggPSBjaGlsZE5vZGVzLmxlbmd0aDtcbiAgICAgICAgICAgICAgICBmb3IgKHZhciBqID0gMDsgaiA8IG1vdmVzLmluc2VydHMubGVuZ3RoOyBqKyspIHtcbiAgICAgICAgICAgICAgICAgICAgaW5zZXJ0ID0gbW92ZXMuaW5zZXJ0c1tqXTtcbiAgICAgICAgICAgICAgICAgICAgbm9kZSA9IGtleU1hcFtpbnNlcnQua2V5XTtcbiAgICAgICAgICAgICAgICAgICAgLy8gdGhpcyBpcyB0aGUgd2VpcmRlc3QgYnVnIGkndmUgZXZlciBzZWVuIGluIHdlYmtpdFxuICAgICAgICAgICAgICAgICAgICBkb21Ob2RlLmluc2VydEJlZm9yZShub2RlLCBpbnNlcnQudG8gPj0gbGVuZ3RoKysgPyBudWxsIDogY2hpbGROb2Rlc1tpbnNlcnQudG9dKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIHJlcGxhY2VSb290KG9sZFJvb3QsIG5ld1Jvb3QpIHtcbiAgICAgICAgICAgICAgICBpZiAob2xkUm9vdCAmJiBuZXdSb290ICYmIG9sZFJvb3QgIT09IG5ld1Jvb3QgJiYgb2xkUm9vdC5wYXJlbnROb2RlKSB7XG4gICAgICAgICAgICAgICAgICAgIG9sZFJvb3QucGFyZW50Tm9kZS5yZXBsYWNlQ2hpbGQobmV3Um9vdCwgb2xkUm9vdCk7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgcmV0dXJuIG5ld1Jvb3Q7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0sIHsgXCIuLi92bm9kZS9pcy13aWRnZXQuanNcIjogMjksIFwiLi4vdm5vZGUvdnBhdGNoLmpzXCI6IDMyLCBcIi4vYXBwbHktcHJvcGVydGllc1wiOiAxNCwgXCIuL3VwZGF0ZS13aWRnZXRcIjogMTkgfV0sIDE4OiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge1xuICAgICAgICAgICAgdmFyIGRvY3VtZW50ID0gcmVxdWlyZShcImdsb2JhbC9kb2N1bWVudFwiKTtcbiAgICAgICAgICAgIHZhciBpc0FycmF5ID0gcmVxdWlyZShcIngtaXMtYXJyYXlcIik7XG5cbiAgICAgICAgICAgIHZhciByZW5kZXIgPSByZXF1aXJlKFwiLi9jcmVhdGUtZWxlbWVudFwiKTtcbiAgICAgICAgICAgIHZhciBkb21JbmRleCA9IHJlcXVpcmUoXCIuL2RvbS1pbmRleFwiKTtcbiAgICAgICAgICAgIHZhciBwYXRjaE9wID0gcmVxdWlyZShcIi4vcGF0Y2gtb3BcIik7XG4gICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IHBhdGNoO1xuXG4gICAgICAgICAgICBmdW5jdGlvbiBwYXRjaChyb290Tm9kZSwgcGF0Y2hlcywgcmVuZGVyT3B0aW9ucykge1xuICAgICAgICAgICAgICAgIHJlbmRlck9wdGlvbnMgPSByZW5kZXJPcHRpb25zIHx8IHt9O1xuICAgICAgICAgICAgICAgIHJlbmRlck9wdGlvbnMucGF0Y2ggPSByZW5kZXJPcHRpb25zLnBhdGNoICYmIHJlbmRlck9wdGlvbnMucGF0Y2ggIT09IHBhdGNoID8gcmVuZGVyT3B0aW9ucy5wYXRjaCA6IHBhdGNoUmVjdXJzaXZlO1xuICAgICAgICAgICAgICAgIHJlbmRlck9wdGlvbnMucmVuZGVyID0gcmVuZGVyT3B0aW9ucy5yZW5kZXIgfHwgcmVuZGVyO1xuXG4gICAgICAgICAgICAgICAgcmV0dXJuIHJlbmRlck9wdGlvbnMucGF0Y2gocm9vdE5vZGUsIHBhdGNoZXMsIHJlbmRlck9wdGlvbnMpO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBmdW5jdGlvbiBwYXRjaFJlY3Vyc2l2ZShyb290Tm9kZSwgcGF0Y2hlcywgcmVuZGVyT3B0aW9ucykge1xuICAgICAgICAgICAgICAgIHZhciBpbmRpY2VzID0gcGF0Y2hJbmRpY2VzKHBhdGNoZXMpO1xuXG4gICAgICAgICAgICAgICAgaWYgKGluZGljZXMubGVuZ3RoID09PSAwKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiByb290Tm9kZTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICB2YXIgaW5kZXggPSBkb21JbmRleChyb290Tm9kZSwgcGF0Y2hlcy5hLCBpbmRpY2VzKTtcbiAgICAgICAgICAgICAgICB2YXIgb3duZXJEb2N1bWVudCA9IHJvb3ROb2RlLm93bmVyRG9jdW1lbnQ7XG5cbiAgICAgICAgICAgICAgICBpZiAoIXJlbmRlck9wdGlvbnMuZG9jdW1lbnQgJiYgb3duZXJEb2N1bWVudCAhPT0gZG9jdW1lbnQpIHtcbiAgICAgICAgICAgICAgICAgICAgcmVuZGVyT3B0aW9ucy5kb2N1bWVudCA9IG93bmVyRG9jdW1lbnQ7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCBpbmRpY2VzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciBub2RlSW5kZXggPSBpbmRpY2VzW2ldO1xuICAgICAgICAgICAgICAgICAgICByb290Tm9kZSA9IGFwcGx5UGF0Y2gocm9vdE5vZGUsIGluZGV4W25vZGVJbmRleF0sIHBhdGNoZXNbbm9kZUluZGV4XSwgcmVuZGVyT3B0aW9ucyk7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgcmV0dXJuIHJvb3ROb2RlO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBmdW5jdGlvbiBhcHBseVBhdGNoKHJvb3ROb2RlLCBkb21Ob2RlLCBwYXRjaExpc3QsIHJlbmRlck9wdGlvbnMpIHtcbiAgICAgICAgICAgICAgICBpZiAoIWRvbU5vZGUpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHJvb3ROb2RlO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHZhciBuZXdOb2RlO1xuXG4gICAgICAgICAgICAgICAgaWYgKGlzQXJyYXkocGF0Y2hMaXN0KSkge1xuICAgICAgICAgICAgICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IHBhdGNoTGlzdC5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgICAgICAgICAgICAgbmV3Tm9kZSA9IHBhdGNoT3AocGF0Y2hMaXN0W2ldLCBkb21Ob2RlLCByZW5kZXJPcHRpb25zKTtcblxuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGRvbU5vZGUgPT09IHJvb3ROb2RlKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcm9vdE5vZGUgPSBuZXdOb2RlO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgbmV3Tm9kZSA9IHBhdGNoT3AocGF0Y2hMaXN0LCBkb21Ob2RlLCByZW5kZXJPcHRpb25zKTtcblxuICAgICAgICAgICAgICAgICAgICBpZiAoZG9tTm9kZSA9PT0gcm9vdE5vZGUpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJvb3ROb2RlID0gbmV3Tm9kZTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHJldHVybiByb290Tm9kZTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZnVuY3Rpb24gcGF0Y2hJbmRpY2VzKHBhdGNoZXMpIHtcbiAgICAgICAgICAgICAgICB2YXIgaW5kaWNlcyA9IFtdO1xuXG4gICAgICAgICAgICAgICAgZm9yICh2YXIga2V5IGluIHBhdGNoZXMpIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKGtleSAhPT0gXCJhXCIpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGluZGljZXMucHVzaChOdW1iZXIoa2V5KSk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICByZXR1cm4gaW5kaWNlcztcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSwgeyBcIi4vY3JlYXRlLWVsZW1lbnRcIjogMTUsIFwiLi9kb20taW5kZXhcIjogMTYsIFwiLi9wYXRjaC1vcFwiOiAxNywgXCJnbG9iYWwvZG9jdW1lbnRcIjogMTAsIFwieC1pcy1hcnJheVwiOiAxMiB9XSwgMTk6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICB2YXIgaXNXaWRnZXQgPSByZXF1aXJlKFwiLi4vdm5vZGUvaXMtd2lkZ2V0LmpzXCIpO1xuXG4gICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IHVwZGF0ZVdpZGdldDtcblxuICAgICAgICAgICAgZnVuY3Rpb24gdXBkYXRlV2lkZ2V0KGEsIGIpIHtcbiAgICAgICAgICAgICAgICBpZiAoaXNXaWRnZXQoYSkgJiYgaXNXaWRnZXQoYikpIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKFwibmFtZVwiIGluIGEgJiYgXCJuYW1lXCIgaW4gYikge1xuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGEuaWQgPT09IGIuaWQ7XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gYS5pbml0ID09PSBiLmluaXQ7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0sIHsgXCIuLi92bm9kZS9pcy13aWRnZXQuanNcIjogMjkgfV0sIDIwOiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge1xuICAgICAgICAgICAgXCJ1c2Ugc3RyaWN0XCI7XG5cbiAgICAgICAgICAgIHZhciBFdlN0b3JlID0gcmVxdWlyZShcImV2LXN0b3JlXCIpO1xuXG4gICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IEV2SG9vaztcblxuICAgICAgICAgICAgZnVuY3Rpb24gRXZIb29rKHZhbHVlKSB7XG4gICAgICAgICAgICAgICAgaWYgKCEodGhpcyBpbnN0YW5jZW9mIEV2SG9vaykpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIG5ldyBFdkhvb2sodmFsdWUpO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHRoaXMudmFsdWUgPSB2YWx1ZTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgRXZIb29rLnByb3RvdHlwZS5ob29rID0gZnVuY3Rpb24gKG5vZGUsIHByb3BlcnR5TmFtZSkge1xuICAgICAgICAgICAgICAgIHZhciBlcyA9IEV2U3RvcmUobm9kZSk7XG4gICAgICAgICAgICAgICAgdmFyIHByb3BOYW1lID0gcHJvcGVydHlOYW1lLnN1YnN0cigzKTtcblxuICAgICAgICAgICAgICAgIGVzW3Byb3BOYW1lXSA9IHRoaXMudmFsdWU7XG4gICAgICAgICAgICB9O1xuXG4gICAgICAgICAgICBFdkhvb2sucHJvdG90eXBlLnVuaG9vayA9IGZ1bmN0aW9uIChub2RlLCBwcm9wZXJ0eU5hbWUpIHtcbiAgICAgICAgICAgICAgICB2YXIgZXMgPSBFdlN0b3JlKG5vZGUpO1xuICAgICAgICAgICAgICAgIHZhciBwcm9wTmFtZSA9IHByb3BlcnR5TmFtZS5zdWJzdHIoMyk7XG5cbiAgICAgICAgICAgICAgICBlc1twcm9wTmFtZV0gPSB1bmRlZmluZWQ7XG4gICAgICAgICAgICB9O1xuICAgICAgICB9LCB7IFwiZXYtc3RvcmVcIjogNyB9XSwgMjE6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICBcInVzZSBzdHJpY3RcIjtcblxuICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBTb2Z0U2V0SG9vaztcblxuICAgICAgICAgICAgZnVuY3Rpb24gU29mdFNldEhvb2sodmFsdWUpIHtcbiAgICAgICAgICAgICAgICBpZiAoISh0aGlzIGluc3RhbmNlb2YgU29mdFNldEhvb2spKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBuZXcgU29mdFNldEhvb2sodmFsdWUpO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHRoaXMudmFsdWUgPSB2YWx1ZTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgU29mdFNldEhvb2sucHJvdG90eXBlLmhvb2sgPSBmdW5jdGlvbiAobm9kZSwgcHJvcGVydHlOYW1lKSB7XG4gICAgICAgICAgICAgICAgaWYgKG5vZGVbcHJvcGVydHlOYW1lXSAhPT0gdGhpcy52YWx1ZSkge1xuICAgICAgICAgICAgICAgICAgICBub2RlW3Byb3BlcnR5TmFtZV0gPSB0aGlzLnZhbHVlO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH07XG4gICAgICAgIH0sIHt9XSwgMjI6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICBcInVzZSBzdHJpY3RcIjtcblxuICAgICAgICAgICAgdmFyIGlzQXJyYXkgPSByZXF1aXJlKFwieC1pcy1hcnJheVwiKTtcblxuICAgICAgICAgICAgdmFyIFZOb2RlID0gcmVxdWlyZShcIi4uL3Zub2RlL3Zub2RlLmpzXCIpO1xuICAgICAgICAgICAgdmFyIFZUZXh0ID0gcmVxdWlyZShcIi4uL3Zub2RlL3Z0ZXh0LmpzXCIpO1xuICAgICAgICAgICAgdmFyIGlzVk5vZGUgPSByZXF1aXJlKFwiLi4vdm5vZGUvaXMtdm5vZGVcIik7XG4gICAgICAgICAgICB2YXIgaXNWVGV4dCA9IHJlcXVpcmUoXCIuLi92bm9kZS9pcy12dGV4dFwiKTtcbiAgICAgICAgICAgIHZhciBpc1dpZGdldCA9IHJlcXVpcmUoXCIuLi92bm9kZS9pcy13aWRnZXRcIik7XG4gICAgICAgICAgICB2YXIgaXNIb29rID0gcmVxdWlyZShcIi4uL3Zub2RlL2lzLXZob29rXCIpO1xuICAgICAgICAgICAgdmFyIGlzVlRodW5rID0gcmVxdWlyZShcIi4uL3Zub2RlL2lzLXRodW5rXCIpO1xuXG4gICAgICAgICAgICB2YXIgcGFyc2VUYWcgPSByZXF1aXJlKFwiLi9wYXJzZS10YWcuanNcIik7XG4gICAgICAgICAgICB2YXIgc29mdFNldEhvb2sgPSByZXF1aXJlKFwiLi9ob29rcy9zb2Z0LXNldC1ob29rLmpzXCIpO1xuICAgICAgICAgICAgdmFyIGV2SG9vayA9IHJlcXVpcmUoXCIuL2hvb2tzL2V2LWhvb2suanNcIik7XG5cbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gaDtcblxuICAgICAgICAgICAgZnVuY3Rpb24gaCh0YWdOYW1lLCBwcm9wZXJ0aWVzLCBjaGlsZHJlbikge1xuICAgICAgICAgICAgICAgIHZhciBjaGlsZE5vZGVzID0gW107XG4gICAgICAgICAgICAgICAgdmFyIHRhZywgcHJvcHMsIGtleSwgbmFtZXNwYWNlO1xuXG4gICAgICAgICAgICAgICAgaWYgKCFjaGlsZHJlbiAmJiBpc0NoaWxkcmVuKHByb3BlcnRpZXMpKSB7XG4gICAgICAgICAgICAgICAgICAgIGNoaWxkcmVuID0gcHJvcGVydGllcztcbiAgICAgICAgICAgICAgICAgICAgcHJvcHMgPSB7fTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICBwcm9wcyA9IHByb3BzIHx8IHByb3BlcnRpZXMgfHwge307XG4gICAgICAgICAgICAgICAgdGFnID0gcGFyc2VUYWcodGFnTmFtZSwgcHJvcHMpO1xuXG4gICAgICAgICAgICAgICAgLy8gc3VwcG9ydCBrZXlzXG4gICAgICAgICAgICAgICAgaWYgKHByb3BzLmhhc093blByb3BlcnR5KFwia2V5XCIpKSB7XG4gICAgICAgICAgICAgICAgICAgIGtleSA9IHByb3BzLmtleTtcbiAgICAgICAgICAgICAgICAgICAgcHJvcHMua2V5ID0gdW5kZWZpbmVkO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIC8vIHN1cHBvcnQgbmFtZXNwYWNlXG4gICAgICAgICAgICAgICAgaWYgKHByb3BzLmhhc093blByb3BlcnR5KFwibmFtZXNwYWNlXCIpKSB7XG4gICAgICAgICAgICAgICAgICAgIG5hbWVzcGFjZSA9IHByb3BzLm5hbWVzcGFjZTtcbiAgICAgICAgICAgICAgICAgICAgcHJvcHMubmFtZXNwYWNlID0gdW5kZWZpbmVkO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIC8vIGZpeCBjdXJzb3IgYnVnXG4gICAgICAgICAgICAgICAgaWYgKHRhZyA9PT0gXCJJTlBVVFwiICYmICFuYW1lc3BhY2UgJiYgcHJvcHMuaGFzT3duUHJvcGVydHkoXCJ2YWx1ZVwiKSAmJiBwcm9wcy52YWx1ZSAhPT0gdW5kZWZpbmVkICYmICFpc0hvb2socHJvcHMudmFsdWUpKSB7XG4gICAgICAgICAgICAgICAgICAgIHByb3BzLnZhbHVlID0gc29mdFNldEhvb2socHJvcHMudmFsdWUpO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHRyYW5zZm9ybVByb3BlcnRpZXMocHJvcHMpO1xuXG4gICAgICAgICAgICAgICAgaWYgKGNoaWxkcmVuICE9PSB1bmRlZmluZWQgJiYgY2hpbGRyZW4gIT09IG51bGwpIHtcbiAgICAgICAgICAgICAgICAgICAgYWRkQ2hpbGQoY2hpbGRyZW4sIGNoaWxkTm9kZXMsIHRhZywgcHJvcHMpO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHJldHVybiBuZXcgVk5vZGUodGFnLCBwcm9wcywgY2hpbGROb2Rlcywga2V5LCBuYW1lc3BhY2UpO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBmdW5jdGlvbiBhZGRDaGlsZChjLCBjaGlsZE5vZGVzLCB0YWcsIHByb3BzKSB7XG4gICAgICAgICAgICAgICAgaWYgKHR5cGVvZiBjID09PSBcInN0cmluZ1wiKSB7XG4gICAgICAgICAgICAgICAgICAgIGNoaWxkTm9kZXMucHVzaChuZXcgVlRleHQoYykpO1xuICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAodHlwZW9mIGMgPT09IFwibnVtYmVyXCIpIHtcbiAgICAgICAgICAgICAgICAgICAgY2hpbGROb2Rlcy5wdXNoKG5ldyBWVGV4dChTdHJpbmcoYykpKTtcbiAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKGlzQ2hpbGQoYykpIHtcbiAgICAgICAgICAgICAgICAgICAgY2hpbGROb2Rlcy5wdXNoKGMpO1xuICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoaXNBcnJheShjKSkge1xuICAgICAgICAgICAgICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IGMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGFkZENoaWxkKGNbaV0sIGNoaWxkTm9kZXMsIHRhZywgcHJvcHMpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfSBlbHNlIGlmIChjID09PSBudWxsIHx8IGMgPT09IHVuZGVmaW5lZCkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgdGhyb3cgVW5leHBlY3RlZFZpcnR1YWxFbGVtZW50KHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGZvcmVpZ25PYmplY3Q6IGMsXG4gICAgICAgICAgICAgICAgICAgICAgICBwYXJlbnRWbm9kZToge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRhZ05hbWU6IHRhZyxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBwcm9wZXJ0aWVzOiBwcm9wc1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIHRyYW5zZm9ybVByb3BlcnRpZXMocHJvcHMpIHtcbiAgICAgICAgICAgICAgICBmb3IgKHZhciBwcm9wTmFtZSBpbiBwcm9wcykge1xuICAgICAgICAgICAgICAgICAgICBpZiAocHJvcHMuaGFzT3duUHJvcGVydHkocHJvcE5hbWUpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICB2YXIgdmFsdWUgPSBwcm9wc1twcm9wTmFtZV07XG5cbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChpc0hvb2sodmFsdWUpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgY29udGludWU7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChwcm9wTmFtZS5zdWJzdHIoMCwgMykgPT09IFwiZXYtXCIpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBhZGQgZXYtZm9vIHN1cHBvcnRcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBwcm9wc1twcm9wTmFtZV0gPSBldkhvb2sodmFsdWUpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBmdW5jdGlvbiBpc0NoaWxkKHgpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gaXNWTm9kZSh4KSB8fCBpc1ZUZXh0KHgpIHx8IGlzV2lkZ2V0KHgpIHx8IGlzVlRodW5rKHgpO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBmdW5jdGlvbiBpc0NoaWxkcmVuKHgpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gdHlwZW9mIHggPT09IFwic3RyaW5nXCIgfHwgaXNBcnJheSh4KSB8fCBpc0NoaWxkKHgpO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBmdW5jdGlvbiBVbmV4cGVjdGVkVmlydHVhbEVsZW1lbnQoZGF0YSkge1xuICAgICAgICAgICAgICAgIHZhciBlcnIgPSBuZXcgRXJyb3IoKTtcblxuICAgICAgICAgICAgICAgIGVyci50eXBlID0gXCJ2aXJ0dWFsLWh5cGVyc2NyaXB0LnVuZXhwZWN0ZWQudmlydHVhbC1lbGVtZW50XCI7XG4gICAgICAgICAgICAgICAgZXJyLm1lc3NhZ2UgPSBcIlVuZXhwZWN0ZWQgdmlydHVhbCBjaGlsZCBwYXNzZWQgdG8gaCgpLlxcblwiICsgXCJFeHBlY3RlZCBhIFZOb2RlIC8gVnRodW5rIC8gVldpZGdldCAvIHN0cmluZyBidXQ6XFxuXCIgKyBcImdvdDpcXG5cIiArIGVycm9yU3RyaW5nKGRhdGEuZm9yZWlnbk9iamVjdCkgKyBcIi5cXG5cIiArIFwiVGhlIHBhcmVudCB2bm9kZSBpczpcXG5cIiArIGVycm9yU3RyaW5nKGRhdGEucGFyZW50Vm5vZGUpO1xuICAgICAgICAgICAgICAgIFwiXFxuXCIgKyBcIlN1Z2dlc3RlZCBmaXg6IGNoYW5nZSB5b3VyIGBoKC4uLiwgWyAuLi4gXSlgIGNhbGxzaXRlLlwiO1xuICAgICAgICAgICAgICAgIGVyci5mb3JlaWduT2JqZWN0ID0gZGF0YS5mb3JlaWduT2JqZWN0O1xuICAgICAgICAgICAgICAgIGVyci5wYXJlbnRWbm9kZSA9IGRhdGEucGFyZW50Vm5vZGU7XG5cbiAgICAgICAgICAgICAgICByZXR1cm4gZXJyO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBmdW5jdGlvbiBlcnJvclN0cmluZyhvYmopIHtcbiAgICAgICAgICAgICAgICB0cnkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gSlNPTi5zdHJpbmdpZnkob2JqLCBudWxsLCBcIiAgICBcIik7XG4gICAgICAgICAgICAgICAgfSBjYXRjaCAoZSkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gU3RyaW5nKG9iaik7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9LCB7IFwiLi4vdm5vZGUvaXMtdGh1bmtcIjogMjUsIFwiLi4vdm5vZGUvaXMtdmhvb2tcIjogMjYsIFwiLi4vdm5vZGUvaXMtdm5vZGVcIjogMjcsIFwiLi4vdm5vZGUvaXMtdnRleHRcIjogMjgsIFwiLi4vdm5vZGUvaXMtd2lkZ2V0XCI6IDI5LCBcIi4uL3Zub2RlL3Zub2RlLmpzXCI6IDMxLCBcIi4uL3Zub2RlL3Z0ZXh0LmpzXCI6IDMzLCBcIi4vaG9va3MvZXYtaG9vay5qc1wiOiAyMCwgXCIuL2hvb2tzL3NvZnQtc2V0LWhvb2suanNcIjogMjEsIFwiLi9wYXJzZS10YWcuanNcIjogMjMsIFwieC1pcy1hcnJheVwiOiAxMiB9XSwgMjM6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICBcInVzZSBzdHJpY3RcIjtcblxuICAgICAgICAgICAgdmFyIHNwbGl0ID0gcmVxdWlyZShcImJyb3dzZXItc3BsaXRcIik7XG5cbiAgICAgICAgICAgIHZhciBjbGFzc0lkU3BsaXQgPSAvKFtcXC4jXT9bYS16QS1aMC05XFx1MDA3Ri1cXHVGRkZGXzotXSspLztcbiAgICAgICAgICAgIHZhciBub3RDbGFzc0lkID0gL15cXC58Iy87XG5cbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gcGFyc2VUYWc7XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIHBhcnNlVGFnKHRhZywgcHJvcHMpIHtcbiAgICAgICAgICAgICAgICBpZiAoIXRhZykge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gXCJESVZcIjtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICB2YXIgbm9JZCA9ICFwcm9wcy5oYXNPd25Qcm9wZXJ0eShcImlkXCIpO1xuXG4gICAgICAgICAgICAgICAgdmFyIHRhZ1BhcnRzID0gc3BsaXQodGFnLCBjbGFzc0lkU3BsaXQpO1xuICAgICAgICAgICAgICAgIHZhciB0YWdOYW1lID0gbnVsbDtcblxuICAgICAgICAgICAgICAgIGlmIChub3RDbGFzc0lkLnRlc3QodGFnUGFydHNbMV0pKSB7XG4gICAgICAgICAgICAgICAgICAgIHRhZ05hbWUgPSBcIkRJVlwiO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHZhciBjbGFzc2VzLCBwYXJ0LCB0eXBlLCBpO1xuXG4gICAgICAgICAgICAgICAgZm9yIChpID0gMDsgaSA8IHRhZ1BhcnRzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICAgICAgICAgIHBhcnQgPSB0YWdQYXJ0c1tpXTtcblxuICAgICAgICAgICAgICAgICAgICBpZiAoIXBhcnQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnRpbnVlO1xuICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgdHlwZSA9IHBhcnQuY2hhckF0KDApO1xuXG4gICAgICAgICAgICAgICAgICAgIGlmICghdGFnTmFtZSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgdGFnTmFtZSA9IHBhcnQ7XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAodHlwZSA9PT0gXCIuXCIpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGNsYXNzZXMgPSBjbGFzc2VzIHx8IFtdO1xuICAgICAgICAgICAgICAgICAgICAgICAgY2xhc3Nlcy5wdXNoKHBhcnQuc3Vic3RyaW5nKDEsIHBhcnQubGVuZ3RoKSk7XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAodHlwZSA9PT0gXCIjXCIgJiYgbm9JZCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgcHJvcHMuaWQgPSBwYXJ0LnN1YnN0cmluZygxLCBwYXJ0Lmxlbmd0aCk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICBpZiAoY2xhc3Nlcykge1xuICAgICAgICAgICAgICAgICAgICBpZiAocHJvcHMuY2xhc3NOYW1lKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBjbGFzc2VzLnB1c2gocHJvcHMuY2xhc3NOYW1lKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgIHByb3BzLmNsYXNzTmFtZSA9IGNsYXNzZXMuam9pbihcIiBcIik7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgcmV0dXJuIHByb3BzLm5hbWVzcGFjZSA/IHRhZ05hbWUgOiB0YWdOYW1lLnRvVXBwZXJDYXNlKCk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0sIHsgXCJicm93c2VyLXNwbGl0XCI6IDUgfV0sIDI0OiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge1xuICAgICAgICAgICAgdmFyIGlzVk5vZGUgPSByZXF1aXJlKFwiLi9pcy12bm9kZVwiKTtcbiAgICAgICAgICAgIHZhciBpc1ZUZXh0ID0gcmVxdWlyZShcIi4vaXMtdnRleHRcIik7XG4gICAgICAgICAgICB2YXIgaXNXaWRnZXQgPSByZXF1aXJlKFwiLi9pcy13aWRnZXRcIik7XG4gICAgICAgICAgICB2YXIgaXNUaHVuayA9IHJlcXVpcmUoXCIuL2lzLXRodW5rXCIpO1xuXG4gICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IGhhbmRsZVRodW5rO1xuXG4gICAgICAgICAgICBmdW5jdGlvbiBoYW5kbGVUaHVuayhhLCBiKSB7XG4gICAgICAgICAgICAgICAgdmFyIHJlbmRlcmVkQSA9IGE7XG4gICAgICAgICAgICAgICAgdmFyIHJlbmRlcmVkQiA9IGI7XG5cbiAgICAgICAgICAgICAgICBpZiAoaXNUaHVuayhiKSkge1xuICAgICAgICAgICAgICAgICAgICByZW5kZXJlZEIgPSByZW5kZXJUaHVuayhiLCBhKTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICBpZiAoaXNUaHVuayhhKSkge1xuICAgICAgICAgICAgICAgICAgICByZW5kZXJlZEEgPSByZW5kZXJUaHVuayhhLCBudWxsKTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgICAgICAgICBhOiByZW5kZXJlZEEsXG4gICAgICAgICAgICAgICAgICAgIGI6IHJlbmRlcmVkQlxuICAgICAgICAgICAgICAgIH07XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIHJlbmRlclRodW5rKHRodW5rLCBwcmV2aW91cykge1xuICAgICAgICAgICAgICAgIHZhciByZW5kZXJlZFRodW5rID0gdGh1bmsudm5vZGU7XG5cbiAgICAgICAgICAgICAgICBpZiAoIXJlbmRlcmVkVGh1bmspIHtcbiAgICAgICAgICAgICAgICAgICAgcmVuZGVyZWRUaHVuayA9IHRodW5rLnZub2RlID0gdGh1bmsucmVuZGVyKHByZXZpb3VzKTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICBpZiAoIShpc1ZOb2RlKHJlbmRlcmVkVGh1bmspIHx8IGlzVlRleHQocmVuZGVyZWRUaHVuaykgfHwgaXNXaWRnZXQocmVuZGVyZWRUaHVuaykpKSB7XG4gICAgICAgICAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcihcInRodW5rIGRpZCBub3QgcmV0dXJuIGEgdmFsaWQgbm9kZVwiKTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICByZXR1cm4gcmVuZGVyZWRUaHVuaztcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSwgeyBcIi4vaXMtdGh1bmtcIjogMjUsIFwiLi9pcy12bm9kZVwiOiAyNywgXCIuL2lzLXZ0ZXh0XCI6IDI4LCBcIi4vaXMtd2lkZ2V0XCI6IDI5IH1dLCAyNTogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHtcbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gaXNUaHVuaztcblxuICAgICAgICAgICAgZnVuY3Rpb24gaXNUaHVuayh0KSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHQgJiYgdC50eXBlID09PSBcIlRodW5rXCI7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0sIHt9XSwgMjY6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IGlzSG9vaztcblxuICAgICAgICAgICAgZnVuY3Rpb24gaXNIb29rKGhvb2spIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gaG9vayAmJiAodHlwZW9mIGhvb2suaG9vayA9PT0gXCJmdW5jdGlvblwiICYmICFob29rLmhhc093blByb3BlcnR5KFwiaG9va1wiKSB8fCB0eXBlb2YgaG9vay51bmhvb2sgPT09IFwiZnVuY3Rpb25cIiAmJiAhaG9vay5oYXNPd25Qcm9wZXJ0eShcInVuaG9va1wiKSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0sIHt9XSwgMjc6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICB2YXIgdmVyc2lvbiA9IHJlcXVpcmUoXCIuL3ZlcnNpb25cIik7XG5cbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gaXNWaXJ0dWFsTm9kZTtcblxuICAgICAgICAgICAgZnVuY3Rpb24gaXNWaXJ0dWFsTm9kZSh4KSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHggJiYgeC50eXBlID09PSBcIlZpcnR1YWxOb2RlXCIgJiYgeC52ZXJzaW9uID09PSB2ZXJzaW9uO1xuICAgICAgICAgICAgfVxuICAgICAgICB9LCB7IFwiLi92ZXJzaW9uXCI6IDMwIH1dLCAyODogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHtcbiAgICAgICAgICAgIHZhciB2ZXJzaW9uID0gcmVxdWlyZShcIi4vdmVyc2lvblwiKTtcblxuICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBpc1ZpcnR1YWxUZXh0O1xuXG4gICAgICAgICAgICBmdW5jdGlvbiBpc1ZpcnR1YWxUZXh0KHgpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4geCAmJiB4LnR5cGUgPT09IFwiVmlydHVhbFRleHRcIiAmJiB4LnZlcnNpb24gPT09IHZlcnNpb247XG4gICAgICAgICAgICB9XG4gICAgICAgIH0sIHsgXCIuL3ZlcnNpb25cIjogMzAgfV0sIDI5OiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge1xuICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBpc1dpZGdldDtcblxuICAgICAgICAgICAgZnVuY3Rpb24gaXNXaWRnZXQodykge1xuICAgICAgICAgICAgICAgIHJldHVybiB3ICYmIHcudHlwZSA9PT0gXCJXaWRnZXRcIjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSwge31dLCAzMDogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHtcbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gXCIyXCI7XG4gICAgICAgIH0sIHt9XSwgMzE6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICB2YXIgdmVyc2lvbiA9IHJlcXVpcmUoXCIuL3ZlcnNpb25cIik7XG4gICAgICAgICAgICB2YXIgaXNWTm9kZSA9IHJlcXVpcmUoXCIuL2lzLXZub2RlXCIpO1xuICAgICAgICAgICAgdmFyIGlzV2lkZ2V0ID0gcmVxdWlyZShcIi4vaXMtd2lkZ2V0XCIpO1xuICAgICAgICAgICAgdmFyIGlzVGh1bmsgPSByZXF1aXJlKFwiLi9pcy10aHVua1wiKTtcbiAgICAgICAgICAgIHZhciBpc1ZIb29rID0gcmVxdWlyZShcIi4vaXMtdmhvb2tcIik7XG5cbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gVmlydHVhbE5vZGU7XG5cbiAgICAgICAgICAgIHZhciBub1Byb3BlcnRpZXMgPSB7fTtcbiAgICAgICAgICAgIHZhciBub0NoaWxkcmVuID0gW107XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIFZpcnR1YWxOb2RlKHRhZ05hbWUsIHByb3BlcnRpZXMsIGNoaWxkcmVuLCBrZXksIG5hbWVzcGFjZSkge1xuICAgICAgICAgICAgICAgIHRoaXMudGFnTmFtZSA9IHRhZ05hbWU7XG4gICAgICAgICAgICAgICAgdGhpcy5wcm9wZXJ0aWVzID0gcHJvcGVydGllcyB8fCBub1Byb3BlcnRpZXM7XG4gICAgICAgICAgICAgICAgdGhpcy5jaGlsZHJlbiA9IGNoaWxkcmVuIHx8IG5vQ2hpbGRyZW47XG4gICAgICAgICAgICAgICAgdGhpcy5rZXkgPSBrZXkgIT0gbnVsbCA/IFN0cmluZyhrZXkpIDogdW5kZWZpbmVkO1xuICAgICAgICAgICAgICAgIHRoaXMubmFtZXNwYWNlID0gdHlwZW9mIG5hbWVzcGFjZSA9PT0gXCJzdHJpbmdcIiA/IG5hbWVzcGFjZSA6IG51bGw7XG5cbiAgICAgICAgICAgICAgICB2YXIgY291bnQgPSBjaGlsZHJlbiAmJiBjaGlsZHJlbi5sZW5ndGggfHwgMDtcbiAgICAgICAgICAgICAgICB2YXIgZGVzY2VuZGFudHMgPSAwO1xuICAgICAgICAgICAgICAgIHZhciBoYXNXaWRnZXRzID0gZmFsc2U7XG4gICAgICAgICAgICAgICAgdmFyIGhhc1RodW5rcyA9IGZhbHNlO1xuICAgICAgICAgICAgICAgIHZhciBkZXNjZW5kYW50SG9va3MgPSBmYWxzZTtcbiAgICAgICAgICAgICAgICB2YXIgaG9va3M7XG5cbiAgICAgICAgICAgICAgICBmb3IgKHZhciBwcm9wTmFtZSBpbiBwcm9wZXJ0aWVzKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmIChwcm9wZXJ0aWVzLmhhc093blByb3BlcnR5KHByb3BOYW1lKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgdmFyIHByb3BlcnR5ID0gcHJvcGVydGllc1twcm9wTmFtZV07XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoaXNWSG9vayhwcm9wZXJ0eSkgJiYgcHJvcGVydHkudW5ob29rKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKCFob29rcykge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBob29rcyA9IHt9O1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGhvb2tzW3Byb3BOYW1lXSA9IHByb3BlcnR5O1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCBjb3VudDsgaSsrKSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciBjaGlsZCA9IGNoaWxkcmVuW2ldO1xuICAgICAgICAgICAgICAgICAgICBpZiAoaXNWTm9kZShjaGlsZCkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGRlc2NlbmRhbnRzICs9IGNoaWxkLmNvdW50IHx8IDA7XG5cbiAgICAgICAgICAgICAgICAgICAgICAgIGlmICghaGFzV2lkZ2V0cyAmJiBjaGlsZC5oYXNXaWRnZXRzKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaGFzV2lkZ2V0cyA9IHRydWU7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgICAgIGlmICghaGFzVGh1bmtzICYmIGNoaWxkLmhhc1RodW5rcykge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGhhc1RodW5rcyA9IHRydWU7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgICAgIGlmICghZGVzY2VuZGFudEhvb2tzICYmIChjaGlsZC5ob29rcyB8fCBjaGlsZC5kZXNjZW5kYW50SG9va3MpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgZGVzY2VuZGFudEhvb2tzID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIGlmICghaGFzV2lkZ2V0cyAmJiBpc1dpZGdldChjaGlsZCkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmICh0eXBlb2YgY2hpbGQuZGVzdHJveSA9PT0gXCJmdW5jdGlvblwiKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaGFzV2lkZ2V0cyA9IHRydWU7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoIWhhc1RodW5rcyAmJiBpc1RodW5rKGNoaWxkKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgaGFzVGh1bmtzID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHRoaXMuY291bnQgPSBjb3VudCArIGRlc2NlbmRhbnRzO1xuICAgICAgICAgICAgICAgIHRoaXMuaGFzV2lkZ2V0cyA9IGhhc1dpZGdldHM7XG4gICAgICAgICAgICAgICAgdGhpcy5oYXNUaHVua3MgPSBoYXNUaHVua3M7XG4gICAgICAgICAgICAgICAgdGhpcy5ob29rcyA9IGhvb2tzO1xuICAgICAgICAgICAgICAgIHRoaXMuZGVzY2VuZGFudEhvb2tzID0gZGVzY2VuZGFudEhvb2tzO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBWaXJ0dWFsTm9kZS5wcm90b3R5cGUudmVyc2lvbiA9IHZlcnNpb247XG4gICAgICAgICAgICBWaXJ0dWFsTm9kZS5wcm90b3R5cGUudHlwZSA9IFwiVmlydHVhbE5vZGVcIjtcbiAgICAgICAgfSwgeyBcIi4vaXMtdGh1bmtcIjogMjUsIFwiLi9pcy12aG9va1wiOiAyNiwgXCIuL2lzLXZub2RlXCI6IDI3LCBcIi4vaXMtd2lkZ2V0XCI6IDI5LCBcIi4vdmVyc2lvblwiOiAzMCB9XSwgMzI6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICB2YXIgdmVyc2lvbiA9IHJlcXVpcmUoXCIuL3ZlcnNpb25cIik7XG5cbiAgICAgICAgICAgIFZpcnR1YWxQYXRjaC5OT05FID0gMDtcbiAgICAgICAgICAgIFZpcnR1YWxQYXRjaC5WVEVYVCA9IDE7XG4gICAgICAgICAgICBWaXJ0dWFsUGF0Y2guVk5PREUgPSAyO1xuICAgICAgICAgICAgVmlydHVhbFBhdGNoLldJREdFVCA9IDM7XG4gICAgICAgICAgICBWaXJ0dWFsUGF0Y2guUFJPUFMgPSA0O1xuICAgICAgICAgICAgVmlydHVhbFBhdGNoLk9SREVSID0gNTtcbiAgICAgICAgICAgIFZpcnR1YWxQYXRjaC5JTlNFUlQgPSA2O1xuICAgICAgICAgICAgVmlydHVhbFBhdGNoLlJFTU9WRSA9IDc7XG4gICAgICAgICAgICBWaXJ0dWFsUGF0Y2guVEhVTksgPSA4O1xuXG4gICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IFZpcnR1YWxQYXRjaDtcblxuICAgICAgICAgICAgZnVuY3Rpb24gVmlydHVhbFBhdGNoKHR5cGUsIHZOb2RlLCBwYXRjaCkge1xuICAgICAgICAgICAgICAgIHRoaXMudHlwZSA9IE51bWJlcih0eXBlKTtcbiAgICAgICAgICAgICAgICB0aGlzLnZOb2RlID0gdk5vZGU7XG4gICAgICAgICAgICAgICAgdGhpcy5wYXRjaCA9IHBhdGNoO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBWaXJ0dWFsUGF0Y2gucHJvdG90eXBlLnZlcnNpb24gPSB2ZXJzaW9uO1xuICAgICAgICAgICAgVmlydHVhbFBhdGNoLnByb3RvdHlwZS50eXBlID0gXCJWaXJ0dWFsUGF0Y2hcIjtcbiAgICAgICAgfSwgeyBcIi4vdmVyc2lvblwiOiAzMCB9XSwgMzM6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICB2YXIgdmVyc2lvbiA9IHJlcXVpcmUoXCIuL3ZlcnNpb25cIik7XG5cbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gVmlydHVhbFRleHQ7XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIFZpcnR1YWxUZXh0KHRleHQpIHtcbiAgICAgICAgICAgICAgICB0aGlzLnRleHQgPSBTdHJpbmcodGV4dCk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIFZpcnR1YWxUZXh0LnByb3RvdHlwZS52ZXJzaW9uID0gdmVyc2lvbjtcbiAgICAgICAgICAgIFZpcnR1YWxUZXh0LnByb3RvdHlwZS50eXBlID0gXCJWaXJ0dWFsVGV4dFwiO1xuICAgICAgICB9LCB7IFwiLi92ZXJzaW9uXCI6IDMwIH1dLCAzNDogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHtcbiAgICAgICAgICAgIHZhciBpc09iamVjdCA9IHJlcXVpcmUoXCJpcy1vYmplY3RcIik7XG4gICAgICAgICAgICB2YXIgaXNIb29rID0gcmVxdWlyZShcIi4uL3Zub2RlL2lzLXZob29rXCIpO1xuXG4gICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IGRpZmZQcm9wcztcblxuICAgICAgICAgICAgZnVuY3Rpb24gZGlmZlByb3BzKGEsIGIpIHtcbiAgICAgICAgICAgICAgICB2YXIgZGlmZjtcblxuICAgICAgICAgICAgICAgIGZvciAodmFyIGFLZXkgaW4gYSkge1xuICAgICAgICAgICAgICAgICAgICBpZiAoIShhS2V5IGluIGIpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBkaWZmID0gZGlmZiB8fCB7fTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGRpZmZbYUtleV0gPSB1bmRlZmluZWQ7XG4gICAgICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgICAgICB2YXIgYVZhbHVlID0gYVthS2V5XTtcbiAgICAgICAgICAgICAgICAgICAgdmFyIGJWYWx1ZSA9IGJbYUtleV07XG5cbiAgICAgICAgICAgICAgICAgICAgaWYgKGFWYWx1ZSA9PT0gYlZhbHVlKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBjb250aW51ZTtcbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIGlmIChpc09iamVjdChhVmFsdWUpICYmIGlzT2JqZWN0KGJWYWx1ZSkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChnZXRQcm90b3R5cGUoYlZhbHVlKSAhPT0gZ2V0UHJvdG90eXBlKGFWYWx1ZSkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBkaWZmID0gZGlmZiB8fCB7fTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBkaWZmW2FLZXldID0gYlZhbHVlO1xuICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIGlmIChpc0hvb2soYlZhbHVlKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRpZmYgPSBkaWZmIHx8IHt9O1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRpZmZbYUtleV0gPSBiVmFsdWU7XG4gICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZhciBvYmplY3REaWZmID0gZGlmZlByb3BzKGFWYWx1ZSwgYlZhbHVlKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAob2JqZWN0RGlmZikge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBkaWZmID0gZGlmZiB8fCB7fTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZGlmZlthS2V5XSA9IG9iamVjdERpZmY7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgZGlmZiA9IGRpZmYgfHwge307XG4gICAgICAgICAgICAgICAgICAgICAgICBkaWZmW2FLZXldID0gYlZhbHVlO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgZm9yICh2YXIgYktleSBpbiBiKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmICghKGJLZXkgaW4gYSkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGRpZmYgPSBkaWZmIHx8IHt9O1xuICAgICAgICAgICAgICAgICAgICAgICAgZGlmZltiS2V5XSA9IGJbYktleV07XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICByZXR1cm4gZGlmZjtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZnVuY3Rpb24gZ2V0UHJvdG90eXBlKHZhbHVlKSB7XG4gICAgICAgICAgICAgICAgaWYgKE9iamVjdC5nZXRQcm90b3R5cGVPZikge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gT2JqZWN0LmdldFByb3RvdHlwZU9mKHZhbHVlKTtcbiAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKHZhbHVlLl9fcHJvdG9fXykge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gdmFsdWUuX19wcm90b19fO1xuICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAodmFsdWUuY29uc3RydWN0b3IpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHZhbHVlLmNvbnN0cnVjdG9yLnByb3RvdHlwZTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH0sIHsgXCIuLi92bm9kZS9pcy12aG9va1wiOiAyNiwgXCJpcy1vYmplY3RcIjogMTEgfV0sIDM1OiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge1xuICAgICAgICAgICAgdmFyIGlzQXJyYXkgPSByZXF1aXJlKFwieC1pcy1hcnJheVwiKTtcblxuICAgICAgICAgICAgdmFyIFZQYXRjaCA9IHJlcXVpcmUoXCIuLi92bm9kZS92cGF0Y2hcIik7XG4gICAgICAgICAgICB2YXIgaXNWTm9kZSA9IHJlcXVpcmUoXCIuLi92bm9kZS9pcy12bm9kZVwiKTtcbiAgICAgICAgICAgIHZhciBpc1ZUZXh0ID0gcmVxdWlyZShcIi4uL3Zub2RlL2lzLXZ0ZXh0XCIpO1xuICAgICAgICAgICAgdmFyIGlzV2lkZ2V0ID0gcmVxdWlyZShcIi4uL3Zub2RlL2lzLXdpZGdldFwiKTtcbiAgICAgICAgICAgIHZhciBpc1RodW5rID0gcmVxdWlyZShcIi4uL3Zub2RlL2lzLXRodW5rXCIpO1xuICAgICAgICAgICAgdmFyIGhhbmRsZVRodW5rID0gcmVxdWlyZShcIi4uL3Zub2RlL2hhbmRsZS10aHVua1wiKTtcblxuICAgICAgICAgICAgdmFyIGRpZmZQcm9wcyA9IHJlcXVpcmUoXCIuL2RpZmYtcHJvcHNcIik7XG5cbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gZGlmZjtcblxuICAgICAgICAgICAgZnVuY3Rpb24gZGlmZihhLCBiKSB7XG4gICAgICAgICAgICAgICAgdmFyIHBhdGNoID0geyBhOiBhIH07XG4gICAgICAgICAgICAgICAgd2FsayhhLCBiLCBwYXRjaCwgMCk7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHBhdGNoO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBmdW5jdGlvbiB3YWxrKGEsIGIsIHBhdGNoLCBpbmRleCkge1xuICAgICAgICAgICAgICAgIGlmIChhID09PSBiKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICB2YXIgYXBwbHkgPSBwYXRjaFtpbmRleF07XG4gICAgICAgICAgICAgICAgdmFyIGFwcGx5Q2xlYXIgPSBmYWxzZTtcblxuICAgICAgICAgICAgICAgIGlmIChpc1RodW5rKGEpIHx8IGlzVGh1bmsoYikpIHtcbiAgICAgICAgICAgICAgICAgICAgdGh1bmtzKGEsIGIsIHBhdGNoLCBpbmRleCk7XG4gICAgICAgICAgICAgICAgfSBlbHNlIGlmIChiID09IG51bGwpIHtcblxuICAgICAgICAgICAgICAgICAgICAvLyBJZiBhIGlzIGEgd2lkZ2V0IHdlIHdpbGwgYWRkIGEgcmVtb3ZlIHBhdGNoIGZvciBpdFxuICAgICAgICAgICAgICAgICAgICAvLyBPdGhlcndpc2UgYW55IGNoaWxkIHdpZGdldHMvaG9va3MgbXVzdCBiZSBkZXN0cm95ZWQuXG4gICAgICAgICAgICAgICAgICAgIC8vIFRoaXMgcHJldmVudHMgYWRkaW5nIHR3byByZW1vdmUgcGF0Y2hlcyBmb3IgYSB3aWRnZXQuXG4gICAgICAgICAgICAgICAgICAgIGlmICghaXNXaWRnZXQoYSkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGNsZWFyU3RhdGUoYSwgcGF0Y2gsIGluZGV4KTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGFwcGx5ID0gcGF0Y2hbaW5kZXhdO1xuICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgYXBwbHkgPSBhcHBlbmRQYXRjaChhcHBseSwgbmV3IFZQYXRjaChWUGF0Y2guUkVNT1ZFLCBhLCBiKSk7XG4gICAgICAgICAgICAgICAgfSBlbHNlIGlmIChpc1ZOb2RlKGIpKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmIChpc1ZOb2RlKGEpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoYS50YWdOYW1lID09PSBiLnRhZ05hbWUgJiYgYS5uYW1lc3BhY2UgPT09IGIubmFtZXNwYWNlICYmIGEua2V5ID09PSBiLmtleSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZhciBwcm9wc1BhdGNoID0gZGlmZlByb3BzKGEucHJvcGVydGllcywgYi5wcm9wZXJ0aWVzKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAocHJvcHNQYXRjaCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBhcHBseSA9IGFwcGVuZFBhdGNoKGFwcGx5LCBuZXcgVlBhdGNoKFZQYXRjaC5QUk9QUywgYSwgcHJvcHNQYXRjaCkpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBhcHBseSA9IGRpZmZDaGlsZHJlbihhLCBiLCBwYXRjaCwgYXBwbHksIGluZGV4KTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgYXBwbHkgPSBhcHBlbmRQYXRjaChhcHBseSwgbmV3IFZQYXRjaChWUGF0Y2guVk5PREUsIGEsIGIpKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBhcHBseUNsZWFyID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGFwcGx5ID0gYXBwZW5kUGF0Y2goYXBwbHksIG5ldyBWUGF0Y2goVlBhdGNoLlZOT0RFLCBhLCBiKSk7XG4gICAgICAgICAgICAgICAgICAgICAgICBhcHBseUNsZWFyID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoaXNWVGV4dChiKSkge1xuICAgICAgICAgICAgICAgICAgICBpZiAoIWlzVlRleHQoYSkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGFwcGx5ID0gYXBwZW5kUGF0Y2goYXBwbHksIG5ldyBWUGF0Y2goVlBhdGNoLlZURVhULCBhLCBiKSk7XG4gICAgICAgICAgICAgICAgICAgICAgICBhcHBseUNsZWFyID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIGlmIChhLnRleHQgIT09IGIudGV4dCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgYXBwbHkgPSBhcHBlbmRQYXRjaChhcHBseSwgbmV3IFZQYXRjaChWUGF0Y2guVlRFWFQsIGEsIGIpKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoaXNXaWRnZXQoYikpIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKCFpc1dpZGdldChhKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgYXBwbHlDbGVhciA9IHRydWU7XG4gICAgICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgICAgICBhcHBseSA9IGFwcGVuZFBhdGNoKGFwcGx5LCBuZXcgVlBhdGNoKFZQYXRjaC5XSURHRVQsIGEsIGIpKTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICBpZiAoYXBwbHkpIHtcbiAgICAgICAgICAgICAgICAgICAgcGF0Y2hbaW5kZXhdID0gYXBwbHk7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgaWYgKGFwcGx5Q2xlYXIpIHtcbiAgICAgICAgICAgICAgICAgICAgY2xlYXJTdGF0ZShhLCBwYXRjaCwgaW5kZXgpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZnVuY3Rpb24gZGlmZkNoaWxkcmVuKGEsIGIsIHBhdGNoLCBhcHBseSwgaW5kZXgpIHtcbiAgICAgICAgICAgICAgICB2YXIgYUNoaWxkcmVuID0gYS5jaGlsZHJlbjtcbiAgICAgICAgICAgICAgICB2YXIgb3JkZXJlZFNldCA9IHJlb3JkZXIoYUNoaWxkcmVuLCBiLmNoaWxkcmVuKTtcbiAgICAgICAgICAgICAgICB2YXIgYkNoaWxkcmVuID0gb3JkZXJlZFNldC5jaGlsZHJlbjtcblxuICAgICAgICAgICAgICAgIHZhciBhTGVuID0gYUNoaWxkcmVuLmxlbmd0aDtcbiAgICAgICAgICAgICAgICB2YXIgYkxlbiA9IGJDaGlsZHJlbi5sZW5ndGg7XG4gICAgICAgICAgICAgICAgdmFyIGxlbiA9IGFMZW4gPiBiTGVuID8gYUxlbiA6IGJMZW47XG5cbiAgICAgICAgICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IGxlbjsgaSsrKSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciBsZWZ0Tm9kZSA9IGFDaGlsZHJlbltpXTtcbiAgICAgICAgICAgICAgICAgICAgdmFyIHJpZ2h0Tm9kZSA9IGJDaGlsZHJlbltpXTtcbiAgICAgICAgICAgICAgICAgICAgaW5kZXggKz0gMTtcblxuICAgICAgICAgICAgICAgICAgICBpZiAoIWxlZnROb2RlKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAocmlnaHROb2RlKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gRXhjZXNzIG5vZGVzIGluIGIgbmVlZCB0byBiZSBhZGRlZFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGFwcGx5ID0gYXBwZW5kUGF0Y2goYXBwbHksIG5ldyBWUGF0Y2goVlBhdGNoLklOU0VSVCwgbnVsbCwgcmlnaHROb2RlKSk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICB3YWxrKGxlZnROb2RlLCByaWdodE5vZGUsIHBhdGNoLCBpbmRleCk7XG4gICAgICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgICAgICBpZiAoaXNWTm9kZShsZWZ0Tm9kZSkgJiYgbGVmdE5vZGUuY291bnQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGluZGV4ICs9IGxlZnROb2RlLmNvdW50O1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgaWYgKG9yZGVyZWRTZXQubW92ZXMpIHtcbiAgICAgICAgICAgICAgICAgICAgLy8gUmVvcmRlciBub2RlcyBsYXN0XG4gICAgICAgICAgICAgICAgICAgIGFwcGx5ID0gYXBwZW5kUGF0Y2goYXBwbHksIG5ldyBWUGF0Y2goVlBhdGNoLk9SREVSLCBhLCBvcmRlcmVkU2V0Lm1vdmVzKSk7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgcmV0dXJuIGFwcGx5O1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBmdW5jdGlvbiBjbGVhclN0YXRlKHZOb2RlLCBwYXRjaCwgaW5kZXgpIHtcbiAgICAgICAgICAgICAgICAvLyBUT0RPOiBNYWtlIHRoaXMgYSBzaW5nbGUgd2Fsaywgbm90IHR3b1xuICAgICAgICAgICAgICAgIHVuaG9vayh2Tm9kZSwgcGF0Y2gsIGluZGV4KTtcbiAgICAgICAgICAgICAgICBkZXN0cm95V2lkZ2V0cyh2Tm9kZSwgcGF0Y2gsIGluZGV4KTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgLy8gUGF0Y2ggcmVjb3JkcyBmb3IgYWxsIGRlc3Ryb3llZCB3aWRnZXRzIG11c3QgYmUgYWRkZWQgYmVjYXVzZSB3ZSBuZWVkXG4gICAgICAgICAgICAvLyBhIERPTSBub2RlIHJlZmVyZW5jZSBmb3IgdGhlIGRlc3Ryb3kgZnVuY3Rpb25cbiAgICAgICAgICAgIGZ1bmN0aW9uIGRlc3Ryb3lXaWRnZXRzKHZOb2RlLCBwYXRjaCwgaW5kZXgpIHtcbiAgICAgICAgICAgICAgICBpZiAoaXNXaWRnZXQodk5vZGUpKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmICh0eXBlb2Ygdk5vZGUuZGVzdHJveSA9PT0gXCJmdW5jdGlvblwiKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBwYXRjaFtpbmRleF0gPSBhcHBlbmRQYXRjaChwYXRjaFtpbmRleF0sIG5ldyBWUGF0Y2goVlBhdGNoLlJFTU9WRSwgdk5vZGUsIG51bGwpKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoaXNWTm9kZSh2Tm9kZSkgJiYgKHZOb2RlLmhhc1dpZGdldHMgfHwgdk5vZGUuaGFzVGh1bmtzKSkge1xuICAgICAgICAgICAgICAgICAgICB2YXIgY2hpbGRyZW4gPSB2Tm9kZS5jaGlsZHJlbjtcbiAgICAgICAgICAgICAgICAgICAgdmFyIGxlbiA9IGNoaWxkcmVuLmxlbmd0aDtcbiAgICAgICAgICAgICAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCBsZW47IGkrKykge1xuICAgICAgICAgICAgICAgICAgICAgICAgdmFyIGNoaWxkID0gY2hpbGRyZW5baV07XG4gICAgICAgICAgICAgICAgICAgICAgICBpbmRleCArPSAxO1xuXG4gICAgICAgICAgICAgICAgICAgICAgICBkZXN0cm95V2lkZ2V0cyhjaGlsZCwgcGF0Y2gsIGluZGV4KTtcblxuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGlzVk5vZGUoY2hpbGQpICYmIGNoaWxkLmNvdW50KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaW5kZXggKz0gY2hpbGQuY291bnQ7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKGlzVGh1bmsodk5vZGUpKSB7XG4gICAgICAgICAgICAgICAgICAgIHRodW5rcyh2Tm9kZSwgbnVsbCwgcGF0Y2gsIGluZGV4KTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIC8vIENyZWF0ZSBhIHN1Yi1wYXRjaCBmb3IgdGh1bmtzXG4gICAgICAgICAgICBmdW5jdGlvbiB0aHVua3MoYSwgYiwgcGF0Y2gsIGluZGV4KSB7XG4gICAgICAgICAgICAgICAgdmFyIG5vZGVzID0gaGFuZGxlVGh1bmsoYSwgYik7XG4gICAgICAgICAgICAgICAgdmFyIHRodW5rUGF0Y2ggPSBkaWZmKG5vZGVzLmEsIG5vZGVzLmIpO1xuICAgICAgICAgICAgICAgIGlmIChoYXNQYXRjaGVzKHRodW5rUGF0Y2gpKSB7XG4gICAgICAgICAgICAgICAgICAgIHBhdGNoW2luZGV4XSA9IG5ldyBWUGF0Y2goVlBhdGNoLlRIVU5LLCBudWxsLCB0aHVua1BhdGNoKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIGhhc1BhdGNoZXMocGF0Y2gpIHtcbiAgICAgICAgICAgICAgICBmb3IgKHZhciBpbmRleCBpbiBwYXRjaCkge1xuICAgICAgICAgICAgICAgICAgICBpZiAoaW5kZXggIT09IFwiYVwiKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgLy8gRXhlY3V0ZSBob29rcyB3aGVuIHR3byBub2RlcyBhcmUgaWRlbnRpY2FsXG4gICAgICAgICAgICBmdW5jdGlvbiB1bmhvb2sodk5vZGUsIHBhdGNoLCBpbmRleCkge1xuICAgICAgICAgICAgICAgIGlmIChpc1ZOb2RlKHZOb2RlKSkge1xuICAgICAgICAgICAgICAgICAgICBpZiAodk5vZGUuaG9va3MpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHBhdGNoW2luZGV4XSA9IGFwcGVuZFBhdGNoKHBhdGNoW2luZGV4XSwgbmV3IFZQYXRjaChWUGF0Y2guUFJPUFMsIHZOb2RlLCB1bmRlZmluZWRLZXlzKHZOb2RlLmhvb2tzKSkpO1xuICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgaWYgKHZOb2RlLmRlc2NlbmRhbnRIb29rcyB8fCB2Tm9kZS5oYXNUaHVua3MpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHZhciBjaGlsZHJlbiA9IHZOb2RlLmNoaWxkcmVuO1xuICAgICAgICAgICAgICAgICAgICAgICAgdmFyIGxlbiA9IGNoaWxkcmVuLmxlbmd0aDtcbiAgICAgICAgICAgICAgICAgICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgbGVuOyBpKyspIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB2YXIgY2hpbGQgPSBjaGlsZHJlbltpXTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpbmRleCArPSAxO1xuXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdW5ob29rKGNoaWxkLCBwYXRjaCwgaW5kZXgpO1xuXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGlzVk5vZGUoY2hpbGQpICYmIGNoaWxkLmNvdW50KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGluZGV4ICs9IGNoaWxkLmNvdW50O1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoaXNUaHVuayh2Tm9kZSkpIHtcbiAgICAgICAgICAgICAgICAgICAgdGh1bmtzKHZOb2RlLCBudWxsLCBwYXRjaCwgaW5kZXgpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZnVuY3Rpb24gdW5kZWZpbmVkS2V5cyhvYmopIHtcbiAgICAgICAgICAgICAgICB2YXIgcmVzdWx0ID0ge307XG5cbiAgICAgICAgICAgICAgICBmb3IgKHZhciBrZXkgaW4gb2JqKSB7XG4gICAgICAgICAgICAgICAgICAgIHJlc3VsdFtrZXldID0gdW5kZWZpbmVkO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHJldHVybiByZXN1bHQ7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIC8vIExpc3QgZGlmZiwgbmFpdmUgbGVmdCB0byByaWdodCByZW9yZGVyaW5nXG4gICAgICAgICAgICBmdW5jdGlvbiByZW9yZGVyKGFDaGlsZHJlbiwgYkNoaWxkcmVuKSB7XG4gICAgICAgICAgICAgICAgLy8gTyhNKSB0aW1lLCBPKE0pIG1lbW9yeVxuICAgICAgICAgICAgICAgIHZhciBiQ2hpbGRJbmRleCA9IGtleUluZGV4KGJDaGlsZHJlbik7XG4gICAgICAgICAgICAgICAgdmFyIGJLZXlzID0gYkNoaWxkSW5kZXgua2V5cztcbiAgICAgICAgICAgICAgICB2YXIgYkZyZWUgPSBiQ2hpbGRJbmRleC5mcmVlO1xuXG4gICAgICAgICAgICAgICAgaWYgKGJGcmVlLmxlbmd0aCA9PT0gYkNoaWxkcmVuLmxlbmd0aCkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgICAgICAgICAgICAgY2hpbGRyZW46IGJDaGlsZHJlbixcbiAgICAgICAgICAgICAgICAgICAgICAgIG1vdmVzOiBudWxsXG4gICAgICAgICAgICAgICAgICAgIH07XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgLy8gTyhOKSB0aW1lLCBPKE4pIG1lbW9yeVxuICAgICAgICAgICAgICAgIHZhciBhQ2hpbGRJbmRleCA9IGtleUluZGV4KGFDaGlsZHJlbik7XG4gICAgICAgICAgICAgICAgdmFyIGFLZXlzID0gYUNoaWxkSW5kZXgua2V5cztcbiAgICAgICAgICAgICAgICB2YXIgYUZyZWUgPSBhQ2hpbGRJbmRleC5mcmVlO1xuXG4gICAgICAgICAgICAgICAgaWYgKGFGcmVlLmxlbmd0aCA9PT0gYUNoaWxkcmVuLmxlbmd0aCkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgICAgICAgICAgICAgY2hpbGRyZW46IGJDaGlsZHJlbixcbiAgICAgICAgICAgICAgICAgICAgICAgIG1vdmVzOiBudWxsXG4gICAgICAgICAgICAgICAgICAgIH07XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgLy8gTyhNQVgoTiwgTSkpIG1lbW9yeVxuICAgICAgICAgICAgICAgIHZhciBuZXdDaGlsZHJlbiA9IFtdO1xuXG4gICAgICAgICAgICAgICAgdmFyIGZyZWVJbmRleCA9IDA7XG4gICAgICAgICAgICAgICAgdmFyIGZyZWVDb3VudCA9IGJGcmVlLmxlbmd0aDtcbiAgICAgICAgICAgICAgICB2YXIgZGVsZXRlZEl0ZW1zID0gMDtcblxuICAgICAgICAgICAgICAgIC8vIEl0ZXJhdGUgdGhyb3VnaCBhIGFuZCBtYXRjaCBhIG5vZGUgaW4gYlxuICAgICAgICAgICAgICAgIC8vIE8oTikgdGltZSxcbiAgICAgICAgICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IGFDaGlsZHJlbi5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgICAgICAgICB2YXIgYUl0ZW0gPSBhQ2hpbGRyZW5baV07XG4gICAgICAgICAgICAgICAgICAgIHZhciBpdGVtSW5kZXg7XG5cbiAgICAgICAgICAgICAgICAgICAgaWYgKGFJdGVtLmtleSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGJLZXlzLmhhc093blByb3BlcnR5KGFJdGVtLmtleSkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBNYXRjaCB1cCB0aGUgb2xkIGtleXNcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpdGVtSW5kZXggPSBiS2V5c1thSXRlbS5rZXldO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIG5ld0NoaWxkcmVuLnB1c2goYkNoaWxkcmVuW2l0ZW1JbmRleF0pO1xuICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBSZW1vdmUgb2xkIGtleWVkIGl0ZW1zXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaXRlbUluZGV4ID0gaSAtIGRlbGV0ZWRJdGVtcysrO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIG5ld0NoaWxkcmVuLnB1c2gobnVsbCk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAvLyBNYXRjaCB0aGUgaXRlbSBpbiBhIHdpdGggdGhlIG5leHQgZnJlZSBpdGVtIGluIGJcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChmcmVlSW5kZXggPCBmcmVlQ291bnQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpdGVtSW5kZXggPSBiRnJlZVtmcmVlSW5kZXgrK107XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgbmV3Q2hpbGRyZW4ucHVzaChiQ2hpbGRyZW5baXRlbUluZGV4XSk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIFRoZXJlIGFyZSBubyBmcmVlIGl0ZW1zIGluIGIgdG8gbWF0Y2ggd2l0aFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIHRoZSBmcmVlIGl0ZW1zIGluIGEsIHNvIHRoZSBleHRyYSBmcmVlIG5vZGVzXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gYXJlIGRlbGV0ZWQuXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaXRlbUluZGV4ID0gaSAtIGRlbGV0ZWRJdGVtcysrO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIG5ld0NoaWxkcmVuLnB1c2gobnVsbCk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICB2YXIgbGFzdEZyZWVJbmRleCA9IGZyZWVJbmRleCA+PSBiRnJlZS5sZW5ndGggPyBiQ2hpbGRyZW4ubGVuZ3RoIDogYkZyZWVbZnJlZUluZGV4XTtcblxuICAgICAgICAgICAgICAgIC8vIEl0ZXJhdGUgdGhyb3VnaCBiIGFuZCBhcHBlbmQgYW55IG5ldyBrZXlzXG4gICAgICAgICAgICAgICAgLy8gTyhNKSB0aW1lXG4gICAgICAgICAgICAgICAgZm9yICh2YXIgaiA9IDA7IGogPCBiQ2hpbGRyZW4ubGVuZ3RoOyBqKyspIHtcbiAgICAgICAgICAgICAgICAgICAgdmFyIG5ld0l0ZW0gPSBiQ2hpbGRyZW5bal07XG5cbiAgICAgICAgICAgICAgICAgICAgaWYgKG5ld0l0ZW0ua2V5KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoIWFLZXlzLmhhc093blByb3BlcnR5KG5ld0l0ZW0ua2V5KSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIEFkZCBhbnkgbmV3IGtleWVkIGl0ZW1zXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gV2UgYXJlIGFkZGluZyBuZXcgaXRlbXMgdG8gdGhlIGVuZCBhbmQgdGhlbiBzb3J0aW5nIHRoZW1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBpbiBwbGFjZS4gSW4gZnV0dXJlIHdlIHNob3VsZCBpbnNlcnQgbmV3IGl0ZW1zIGluIHBsYWNlLlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIG5ld0NoaWxkcmVuLnB1c2gobmV3SXRlbSk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoaiA+PSBsYXN0RnJlZUluZGV4KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAvLyBBZGQgYW55IGxlZnRvdmVyIG5vbi1rZXllZCBpdGVtc1xuICAgICAgICAgICAgICAgICAgICAgICAgbmV3Q2hpbGRyZW4ucHVzaChuZXdJdGVtKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHZhciBzaW11bGF0ZSA9IG5ld0NoaWxkcmVuLnNsaWNlKCk7XG4gICAgICAgICAgICAgICAgdmFyIHNpbXVsYXRlSW5kZXggPSAwO1xuICAgICAgICAgICAgICAgIHZhciByZW1vdmVzID0gW107XG4gICAgICAgICAgICAgICAgdmFyIGluc2VydHMgPSBbXTtcbiAgICAgICAgICAgICAgICB2YXIgc2ltdWxhdGVJdGVtO1xuXG4gICAgICAgICAgICAgICAgZm9yICh2YXIgayA9IDA7IGsgPCBiQ2hpbGRyZW4ubGVuZ3RoOykge1xuICAgICAgICAgICAgICAgICAgICB2YXIgd2FudGVkSXRlbSA9IGJDaGlsZHJlbltrXTtcbiAgICAgICAgICAgICAgICAgICAgc2ltdWxhdGVJdGVtID0gc2ltdWxhdGVbc2ltdWxhdGVJbmRleF07XG5cbiAgICAgICAgICAgICAgICAgICAgLy8gcmVtb3ZlIGl0ZW1zXG4gICAgICAgICAgICAgICAgICAgIHdoaWxlIChzaW11bGF0ZUl0ZW0gPT09IG51bGwgJiYgc2ltdWxhdGUubGVuZ3RoKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICByZW1vdmVzLnB1c2gocmVtb3ZlKHNpbXVsYXRlLCBzaW11bGF0ZUluZGV4LCBudWxsKSk7XG4gICAgICAgICAgICAgICAgICAgICAgICBzaW11bGF0ZUl0ZW0gPSBzaW11bGF0ZVtzaW11bGF0ZUluZGV4XTtcbiAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgIGlmICghc2ltdWxhdGVJdGVtIHx8IHNpbXVsYXRlSXRlbS5rZXkgIT09IHdhbnRlZEl0ZW0ua2V5KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAvLyBpZiB3ZSBuZWVkIGEga2V5IGluIHRoaXMgcG9zaXRpb24uLi5cbiAgICAgICAgICAgICAgICAgICAgICAgIGlmICh3YW50ZWRJdGVtLmtleSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChzaW11bGF0ZUl0ZW0gJiYgc2ltdWxhdGVJdGVtLmtleSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBpZiBhbiBpbnNlcnQgZG9lc24ndCBwdXQgdGhpcyBrZXkgaW4gcGxhY2UsIGl0IG5lZWRzIHRvIG1vdmVcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGJLZXlzW3NpbXVsYXRlSXRlbS5rZXldICE9PSBrICsgMSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmVtb3Zlcy5wdXNoKHJlbW92ZShzaW11bGF0ZSwgc2ltdWxhdGVJbmRleCwgc2ltdWxhdGVJdGVtLmtleSkpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc2ltdWxhdGVJdGVtID0gc2ltdWxhdGVbc2ltdWxhdGVJbmRleF07XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBpZiB0aGUgcmVtb3ZlIGRpZG4ndCBwdXQgdGhlIHdhbnRlZCBpdGVtIGluIHBsYWNlLCB3ZSBuZWVkIHRvIGluc2VydCBpdFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKCFzaW11bGF0ZUl0ZW0gfHwgc2ltdWxhdGVJdGVtLmtleSAhPT0gd2FudGVkSXRlbS5rZXkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpbnNlcnRzLnB1c2goeyBrZXk6IHdhbnRlZEl0ZW0ua2V5LCB0bzogayB9KTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIGl0ZW1zIGFyZSBtYXRjaGluZywgc28gc2tpcCBhaGVhZFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc2ltdWxhdGVJbmRleCsrO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaW5zZXJ0cy5wdXNoKHsga2V5OiB3YW50ZWRJdGVtLmtleSwgdG86IGsgfSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpbnNlcnRzLnB1c2goeyBrZXk6IHdhbnRlZEl0ZW0ua2V5LCB0bzogayB9KTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaysrO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgLy8gYSBrZXkgaW4gc2ltdWxhdGUgaGFzIG5vIG1hdGNoaW5nIHdhbnRlZCBrZXksIHJlbW92ZSBpdFxuICAgICAgICAgICAgICAgICAgICAgICAgZWxzZSBpZiAoc2ltdWxhdGVJdGVtICYmIHNpbXVsYXRlSXRlbS5rZXkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICByZW1vdmVzLnB1c2gocmVtb3ZlKHNpbXVsYXRlLCBzaW11bGF0ZUluZGV4LCBzaW11bGF0ZUl0ZW0ua2V5KSk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBzaW11bGF0ZUluZGV4Kys7XG4gICAgICAgICAgICAgICAgICAgICAgICBrKys7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAvLyByZW1vdmUgYWxsIHRoZSByZW1haW5pbmcgbm9kZXMgZnJvbSBzaW11bGF0ZVxuICAgICAgICAgICAgICAgIHdoaWxlIChzaW11bGF0ZUluZGV4IDwgc2ltdWxhdGUubGVuZ3RoKSB7XG4gICAgICAgICAgICAgICAgICAgIHNpbXVsYXRlSXRlbSA9IHNpbXVsYXRlW3NpbXVsYXRlSW5kZXhdO1xuICAgICAgICAgICAgICAgICAgICByZW1vdmVzLnB1c2gocmVtb3ZlKHNpbXVsYXRlLCBzaW11bGF0ZUluZGV4LCBzaW11bGF0ZUl0ZW0gJiYgc2ltdWxhdGVJdGVtLmtleSkpO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIC8vIElmIHRoZSBvbmx5IG1vdmVzIHdlIGhhdmUgYXJlIGRlbGV0ZXMgdGhlbiB3ZSBjYW4ganVzdFxuICAgICAgICAgICAgICAgIC8vIGxldCB0aGUgZGVsZXRlIHBhdGNoIHJlbW92ZSB0aGVzZSBpdGVtcy5cbiAgICAgICAgICAgICAgICBpZiAocmVtb3Zlcy5sZW5ndGggPT09IGRlbGV0ZWRJdGVtcyAmJiAhaW5zZXJ0cy5sZW5ndGgpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGNoaWxkcmVuOiBuZXdDaGlsZHJlbixcbiAgICAgICAgICAgICAgICAgICAgICAgIG1vdmVzOiBudWxsXG4gICAgICAgICAgICAgICAgICAgIH07XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgICAgICAgICAgY2hpbGRyZW46IG5ld0NoaWxkcmVuLFxuICAgICAgICAgICAgICAgICAgICBtb3Zlczoge1xuICAgICAgICAgICAgICAgICAgICAgICAgcmVtb3ZlczogcmVtb3ZlcyxcbiAgICAgICAgICAgICAgICAgICAgICAgIGluc2VydHM6IGluc2VydHNcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH07XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIHJlbW92ZShhcnIsIGluZGV4LCBrZXkpIHtcbiAgICAgICAgICAgICAgICBhcnIuc3BsaWNlKGluZGV4LCAxKTtcblxuICAgICAgICAgICAgICAgIHJldHVybiB7XG4gICAgICAgICAgICAgICAgICAgIGZyb206IGluZGV4LFxuICAgICAgICAgICAgICAgICAgICBrZXk6IGtleVxuICAgICAgICAgICAgICAgIH07XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIGtleUluZGV4KGNoaWxkcmVuKSB7XG4gICAgICAgICAgICAgICAgdmFyIGtleXMgPSB7fTtcbiAgICAgICAgICAgICAgICB2YXIgZnJlZSA9IFtdO1xuICAgICAgICAgICAgICAgIHZhciBsZW5ndGggPSBjaGlsZHJlbi5sZW5ndGg7XG5cbiAgICAgICAgICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IGxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciBjaGlsZCA9IGNoaWxkcmVuW2ldO1xuXG4gICAgICAgICAgICAgICAgICAgIGlmIChjaGlsZC5rZXkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGtleXNbY2hpbGQua2V5XSA9IGk7XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBmcmVlLnB1c2goaSk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgICAgICAgICBrZXlzOiBrZXlzLCAvLyBBIGhhc2ggb2Yga2V5IG5hbWUgdG8gaW5kZXhcbiAgICAgICAgICAgICAgICAgICAgZnJlZTogZnJlZSAvLyBBbiBhcnJheSBvZiB1bmtleWVkIGl0ZW0gaW5kaWNlc1xuICAgICAgICAgICAgICAgIH07XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIGFwcGVuZFBhdGNoKGFwcGx5LCBwYXRjaCkge1xuICAgICAgICAgICAgICAgIGlmIChhcHBseSkge1xuICAgICAgICAgICAgICAgICAgICBpZiAoaXNBcnJheShhcHBseSkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGFwcGx5LnB1c2gocGF0Y2gpO1xuICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgYXBwbHkgPSBbYXBwbHksIHBhdGNoXTtcbiAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBhcHBseTtcbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gcGF0Y2g7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9LCB7IFwiLi4vdm5vZGUvaGFuZGxlLXRodW5rXCI6IDI0LCBcIi4uL3Zub2RlL2lzLXRodW5rXCI6IDI1LCBcIi4uL3Zub2RlL2lzLXZub2RlXCI6IDI3LCBcIi4uL3Zub2RlL2lzLXZ0ZXh0XCI6IDI4LCBcIi4uL3Zub2RlL2lzLXdpZGdldFwiOiAyOSwgXCIuLi92bm9kZS92cGF0Y2hcIjogMzIsIFwiLi9kaWZmLXByb3BzXCI6IDM0LCBcIngtaXMtYXJyYXlcIjogMTIgfV0gfSwge30sIFs0XSkoNCk7XG59KTtcblxuY29uc3Qgc3RhcnQgPSBmdW5jdGlvbiAoZG9tUm9vdCwgcmVuZGVyRm4sIGluaXRpYWxTdGF0ZSwgb3B0aW9ucyA9IFtdKSB7XG4gIGxldCBwaWQgPSBzZWxmLnByb2Nlc3Nlcy5zcGF3bigpO1xuXG4gIGlmIChLZXl3b3JkLmhhc19rZXlfX3FtX18ob3B0aW9ucywgS2VybmVsLlNwZWNpYWxGb3Jtcy5hdG9tKCduYW1lJykpKSB7XG4gICAgcGlkID0gc2VsZi5wcm9jZXNzZXMucmVnaXN0ZXIoS2V5d29yZC5nZXQob3B0aW9ucywgS2VybmVsLlNwZWNpYWxGb3Jtcy5hdG9tKCduYW1lJykpLCBwaWQpO1xuICB9XG5cbiAgY29uc3QgdHJlZSA9IHJlbmRlckZuLmFwcGx5KHRoaXMsIGluaXRpYWxTdGF0ZSk7XG4gIGNvbnN0IHJvb3ROb2RlID0gVmlydHVhbERPTS5jcmVhdGUodHJlZSk7XG5cbiAgZG9tUm9vdC5hcHBlbmRDaGlsZChyb290Tm9kZSk7XG5cbiAgc2VsZi5wcm9jZXNzZXMucHV0KHBpZCwgJ3N0YXRlJywgS2VybmVsLlNwZWNpYWxGb3Jtcy50dXBsZShyb290Tm9kZSwgdHJlZSwgcmVuZGVyRm4pKTtcbiAgcmV0dXJuIEtlcm5lbC5TcGVjaWFsRm9ybXMudHVwbGUoS2VybmVsLlNwZWNpYWxGb3Jtcy5hdG9tKCdvaycpLCBwaWQpO1xufTtcblxuY29uc3Qgc3RvcCA9IGZ1bmN0aW9uIChhZ2VudCwgdGltZW91dCA9IDUwMDApIHtcbiAgc2VsZi5wcm9jZXNzZXMuZXhpdChhZ2VudCk7XG4gIHJldHVybiBLZXJuZWwuU3BlY2lhbEZvcm1zLmF0b20oJ29rJyk7XG59O1xuXG5jb25zdCByZW5kZXIgPSBmdW5jdGlvbiAoYWdlbnQsIHN0YXRlKSB7XG5cbiAgY29uc3QgY3VycmVudF9zdGF0ZSA9IHNlbGYucHJvY2Vzc2VzLmdldChhZ2VudCwgJ3N0YXRlJyk7XG5cbiAgbGV0IHJvb3ROb2RlID0gS2VybmVsLmVsZW0oY3VycmVudF9zdGF0ZSwgMCk7XG4gIGxldCB0cmVlID0gS2VybmVsLmVsZW0oY3VycmVudF9zdGF0ZSwgMSk7XG4gIGxldCByZW5kZXJGbiA9IEtlcm5lbC5lbGVtKGN1cnJlbnRfc3RhdGUsIDIpO1xuXG4gIGxldCBuZXdUcmVlID0gcmVuZGVyRm4uYXBwbHkodGhpcywgc3RhdGUpO1xuXG4gIGxldCBwYXRjaGVzID0gVmlydHVhbERPTS5kaWZmKHRyZWUsIG5ld1RyZWUpO1xuICByb290Tm9kZSA9IFZpcnR1YWxET00ucGF0Y2gocm9vdE5vZGUsIHBhdGNoZXMpO1xuXG4gIHNlbGYucHJvY2Vzc2VzLnB1dChhZ2VudCwgJ3N0YXRlJywgS2VybmVsLlNwZWNpYWxGb3Jtcy50dXBsZShyb290Tm9kZSwgbmV3VHJlZSwgcmVuZGVyRm4pKTtcblxuICByZXR1cm4gS2VybmVsLlNwZWNpYWxGb3Jtcy5hdG9tKCdvaycpO1xufTtcblxudmFyIHZpZXcgPSB7XG4gIHN0YXJ0LFxuICBzdG9wLFxuICByZW5kZXJcbn07XG5cbnNlbGYucHJvY2Vzc2VzID0gc2VsZi5wcm9jZXNzZXMgfHwgbmV3IFByb2Nlc3NTeXN0ZW0oKTtcblxuY29uc3QgQ29yZSA9IEM7XG5cbmV4cG9ydCB7IENvcmUsIEtlcm5lbCwgQXRvbSwgRW51bSwgSW50ZWdlciwgTGlzdCwgUmFuZ2UsIFR1cGxlLCBBZ2VudCwgS2V5d29yZCwgYmFzZSBhcyBCYXNlLCBTdHJpbmckMSBhcyBTdHJpbmcsIGJpdHdpc2UgYXMgQml0d2lzZSwgRW51bWVyYWJsZSwgQ29sbGVjdGFibGUsIEluc3BlY3QsIG1hcCBhcyBNYXAsIHNldCBhcyBTZXQsIE1hcFNldCwgVmlydHVhbERPTSwgdmlldyBhcyBWaWV3IH07Il0sImZpbGUiOiJFbGl4aXIuanMiLCJzb3VyY2VSb290IjoiL3NvdXJjZS8ifQ== \ No newline at end of file From 3a0b75092614b3cc613fe41ac7ab08f9636fa99a Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Sun, 6 Dec 2015 19:25:05 -0600 Subject: [PATCH 083/860] Added Elixir.js --- priv/Elixir.js | 4569 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 4569 insertions(+) create mode 100644 priv/Elixir.js diff --git a/priv/Elixir.js b/priv/Elixir.js new file mode 100644 index 00000000..07d90f1b --- /dev/null +++ b/priv/Elixir.js @@ -0,0 +1,4569 @@ +function call_property(item, property) { + if (property in item) { + item[property]; + if (item[property] instanceof Function) { + return item[property](); + } else { + return item[property]; + } + } else if (Symbol.for(property) in item) { + let prop = Symbol.for(property); + if (item[prop] instanceof Function) { + return item[prop](); + } else { + return item[prop]; + } + } + + throw new Error(`Property ${ property } not found in ${ item }`); +} + +class Tuple$1 { + + constructor(...args) { + this.values = Object.freeze(args); + } + + get(index) { + return this.values[index]; + } + + count() { + return this.values.length; + } + + [Symbol.iterator]() { + return this.values[Symbol.iterator](); + } + + toString() { + var i, + s = ""; + for (i = 0; i < this.values.length; i++) { + if (s !== "") { + s += ", "; + } + s += this.values[i].toString(); + } + + return "{" + s + "}"; + } + +} + +let process_counter = -1; + +class PID { + constructor() { + process_counter = process_counter + 1; + this.id = process_counter; + } + + toString() { + return "PID#<0." + this.id + ".0>"; + } +} + +class Integer$1 {} +class Float {} + +/* @flow */ + +class Variable { + + constructor(name = null) { + this.name = name; + } +} + +class Wildcard { + constructor() {} +} + +class StartsWith { + + constructor(prefix) { + this.prefix = prefix; + } +} + +class Capture { + + constructor(value) { + this.value = value; + } +} + +class HeadTail { + constructor() {} +} + +class Type { + + constructor(type, objPattern = {}) { + this.type = type; + this.objPattern = objPattern; + } +} + +class Bound { + + constructor(value) { + this.value = value; + } +} + +function variable(name = null) { + return new Variable(name); +} + +function wildcard() { + return new Wildcard(); +} + +function startsWith(prefix) { + return new StartsWith(prefix); +} + +function capture(value) { + return new Capture(value); +} + +function headTail() { + return new HeadTail(); +} + +function type(type, objPattern = {}) { + return new Type(type, objPattern); +} + +function bound(value) { + return new Bound(value); +} + +function is_number$1(value) { + return typeof value === 'number'; +} + +function is_string(value) { + return typeof value === 'string'; +} + +function is_boolean$1(value) { + return typeof value === 'boolean'; +} + +function is_symbol(value) { + return typeof value === 'symbol'; +} + +function is_null(value) { + return value === null; +} + +function is_undefined(value) { + return typeof value === 'undefined'; +} + +function is_function$1(value) { + return Object.prototype.toString.call(value) == '[object Function]'; +} + +function is_variable(value) { + return value instanceof Variable; +} + +function is_wildcard(value) { + return value instanceof Wildcard; +} + +function is_headTail(value) { + return value instanceof HeadTail; +} + +function is_capture(value) { + return value instanceof Capture; +} + +function is_type(value) { + return value instanceof Type; +} + +function is_startsWith(value) { + return value instanceof StartsWith; +} + +function is_bound(value) { + return value instanceof Bound; +} + +function is_object(value) { + return typeof value === 'object'; +} + +function is_array(value) { + return Array.isArray(value); +} + +var Checks = { + is_number: is_number$1, + is_string, + is_boolean: is_boolean$1, + is_symbol, + is_null, + is_undefined, + is_function: is_function$1, + is_variable, + is_wildcard, + is_headTail, + is_capture, + is_type, + is_startsWith, + is_bound, + is_object, + is_array +}; + +function resolveSymbol(pattern) { + return function (value) { + return Checks.is_symbol(value) && value === pattern; + }; +} + +function resolveString(pattern) { + return function (value) { + return Checks.is_string(value) && value === pattern; + }; +} + +function resolveNumber(pattern) { + return function (value) { + return Checks.is_number(value) && value === pattern; + }; +} + +function resolveBoolean(pattern) { + return function (value) { + return Checks.is_boolean(value) && value === pattern; + }; +} + +function resolveFunction(pattern) { + return function (value) { + return Checks.is_function(value) && value === pattern; + }; +} + +function resolveNull(pattern) { + return function (value) { + return Checks.is_null(value); + }; +} + +function resolveBound(pattern) { + return function (value, args) { + if (typeof value === typeof pattern.value && value === pattern.value) { + args.push(value); + return true; + } + + return false; + }; +} + +function resolveWildcard() { + return function () { + return true; + }; +} + +function resolveVariable() { + return function (value, args) { + args.push(value); + return true; + }; +} + +function resolveHeadTail() { + return function (value, args) { + if (!Checks.is_array(value) || value.length < 2) { + return false; + } + + const head = value[0]; + const tail = value.slice(1); + + args.push(head); + args.push(tail); + + return true; + }; +} + +function resolveCapture(pattern) { + const matches = buildMatch(pattern.value); + + return function (value, args) { + if (matches(value, args)) { + args.push(value); + return true; + } + + return false; + }; +} + +function resolveStartsWith(pattern) { + const prefix = pattern.prefix; + + return function (value, args) { + if (Checks.is_string(value) && value.startsWith(prefix)) { + args.push(value.substring(prefix.length)); + return true; + } + + return false; + }; +} + +function resolveType(pattern) { + return function (value, args) { + if (value instanceof pattern.type) { + const matches = buildMatch(pattern.objPattern); + return matches(value, args) && args.push(value) > 0; + } + + return false; + }; +} + +function resolveArray(pattern) { + const matches = pattern.map(x => buildMatch(x)); + + return function (value, args) { + if (!Checks.is_array(value) || value.length != pattern.length) { + return false; + } + + return value.every(function (v, i) { + return matches[i](value[i], args); + }); + }; +} + +function resolveObject(pattern) { + let matches = {}; + + for (let key of Object.keys(pattern)) { + matches[key] = buildMatch(pattern[key]); + } + + return function (value, args) { + if (!Checks.is_object(value) || pattern.length > value.length) { + return false; + } + + for (let key of Object.keys(pattern)) { + if (!(key in value) || !matches[key](value[key], args)) { + return false; + } + } + + return true; + }; +} + +function resolveNoMatch() { + return function () { + return false; + }; +} + +var Resolvers = { + resolveBound, + resolveWildcard, + resolveVariable, + resolveHeadTail, + resolveCapture, + resolveStartsWith, + resolveType, + resolveArray, + resolveObject, + resolveNoMatch, + resolveSymbol, + resolveString, + resolveNumber, + resolveBoolean, + resolveFunction, + resolveNull +}; + +function buildMatch(pattern) { + + if (Checks.is_variable(pattern)) { + return Resolvers.resolveVariable(pattern); + } + + if (Checks.is_wildcard(pattern)) { + return Resolvers.resolveWildcard(pattern); + } + + if (Checks.is_undefined(pattern)) { + return Resolvers.resolveWildcard(pattern); + } + + if (Checks.is_headTail(pattern)) { + return Resolvers.resolveHeadTail(pattern); + } + + if (Checks.is_startsWith(pattern)) { + return Resolvers.resolveStartsWith(pattern); + } + + if (Checks.is_capture(pattern)) { + return Resolvers.resolveCapture(pattern); + } + + if (Checks.is_bound(pattern)) { + return Resolvers.resolveBound(pattern); + } + + if (Checks.is_type(pattern)) { + return Resolvers.resolveType(pattern); + } + + if (Checks.is_array(pattern)) { + return Resolvers.resolveArray(pattern); + } + + if (Checks.is_number(pattern)) { + return Resolvers.resolveNumber(pattern); + } + + if (Checks.is_string(pattern)) { + return Resolvers.resolveString(pattern); + } + + if (Checks.is_boolean(pattern)) { + return Resolvers.resolveBoolean(pattern); + } + + if (Checks.is_symbol(pattern)) { + return Resolvers.resolveSymbol(pattern); + } + + if (Checks.is_null(pattern)) { + return Resolvers.resolveNull(pattern); + } + + if (Checks.is_object(pattern)) { + return Resolvers.resolveObject(pattern); + } + + return Resolvers.resolveNoMatch(); +} + +class MatchError extends Error { + constructor(arg) { + super(); + + if (typeof arg === 'symbol') { + this.message = 'No match for: ' + arg.toString(); + } else if (Array.isArray(arg)) { + let mappedValues = arg.map(x => x.toString()); + this.message = 'No match for: ' + mappedValues; + } else { + this.message = 'No match for: ' + arg; + } + + this.stack = new Error().stack; + this.name = this.constructor.name; + } +} + +class Case { + + constructor(pattern, fn, guard = () => true) { + this.pattern = buildMatch(pattern); + this.fn = fn; + this.guard = guard; + } +} + +function make_case(pattern, fn, guard = () => true) { + return new Case(pattern, fn, guard); +} + +function defmatch(...cases) { + return function (...args) { + for (let processedCase of cases) { + let result = []; + if (processedCase.pattern(args, result) && processedCase.guard.apply(this, result)) { + return processedCase.fn.apply(this, result); + } + } + + throw new MatchError(args); + }; +} + +function match(pattern, expr, guard = () => true) { + let result = []; + let processedPattern = buildMatch(pattern); + if (processedPattern(expr, result) && guard.apply(this, result)) { + return result; + } else { + throw new MatchError(expr); + } +} + +function match_no_throw(pattern, expr, guard = () => true) { + try { + return match(pattern, expr, guard); + } catch (e) { + if (e instanceof MatchError) { + return null; + } + + throw e; + } +} + +var Patterns = { + defmatch, match, MatchError, match_no_throw, + variable, wildcard, startsWith, + capture, headTail, type, bound, Case, make_case +}; + +class BitString { + constructor(...args) { + this.raw_value = function () { + return Object.freeze(args); + }; + + this.value = Object.freeze(this.process(args)); + } + + get(index) { + return this.value[index]; + } + + count() { + return this.value.length; + } + + [Symbol.iterator]() { + return this.value[Symbol.iterator](); + } + + toString() { + var i, + s = ""; + for (i = 0; i < this.count(); i++) { + if (s !== "") { + s += ", "; + } + s += this[i].toString(); + } + + return "<<" + s + ">>"; + } + + process() { + let processed_values = []; + + var i; + for (i = 0; i < this.raw_value().length; i++) { + let processed_value = this["process_" + this.raw_value()[i].type](this.raw_value()[i]); + + for (let attr of this.raw_value()[i].attributes) { + processed_value = this["process_" + attr](processed_value); + } + + processed_values = processed_values.concat(processed_value); + } + + return processed_values; + } + + process_integer(value) { + return value.value; + } + + process_float(value) { + if (value.size === 64) { + return BitString.float64ToBytes(value.value); + } else if (value.size === 32) { + return BitString.float32ToBytes(value.value); + } + + throw new Error("Invalid size for float"); + } + + process_bitstring(value) { + return value.value.value; + } + + process_binary(value) { + return BitString.toUTF8Array(value.value); + } + + process_utf8(value) { + return BitString.toUTF8Array(value.value); + } + + process_utf16(value) { + return BitString.toUTF16Array(value.value); + } + + process_utf32(value) { + return BitString.toUTF32Array(value.value); + } + + process_signed(value) { + return new Uint8Array([value])[0]; + } + + process_unsigned(value) { + return value; + } + + process_native(value) { + return value; + } + + process_big(value) { + return value; + } + + process_little(value) { + return value.reverse(); + } + + process_size(value) { + return value; + } + + process_unit(value) { + return value; + } + + static integer(value) { + return BitString.wrap(value, { "type": "integer", "unit": 1, "size": 8 }); + } + + static float(value) { + return BitString.wrap(value, { "type": "float", "unit": 1, "size": 64 }); + } + + static bitstring(value) { + return BitString.wrap(value, { "type": "bitstring", "unit": 1, "size": value.length }); + } + + static bits(value) { + return BitString.bitstring(value); + } + + static binary(value) { + return BitString.wrap(value, { "type": "binary", "unit": 8, "size": value.length }); + } + + static bytes(value) { + return BitString.binary(value); + } + + static utf8(value) { + return BitString.wrap(value, { "type": "utf8" }); + } + + static utf16(value) { + return BitString.wrap(value, { "type": "utf16" }); + } + + static utf32(value) { + return BitString.wrap(value, { "type": "utf32" }); + } + + static signed(value) { + return BitString.wrap(value, {}, "signed"); + } + + static unsigned(value) { + return BitString.wrap(value, {}, "unsigned"); + } + + static native(value) { + return BitString.wrap(value, {}, "native"); + } + + static big(value) { + return BitString.wrap(value, {}, "big"); + } + + static little(value) { + return BitString.wrap(value, {}, "little"); + } + + static size(value, count) { + return BitString.wrap(value, { "size": count }); + } + + static unit(value, count) { + return BitString.wrap(value, { "unit": count }); + } + + static wrap(value, opt, new_attribute = null) { + let the_value = value; + + if (!(value instanceof Object)) { + the_value = { "value": value, "attributes": [] }; + } + + the_value = Object.assign(the_value, opt); + + if (new_attribute) { + the_value.attributes.push(new_attribute); + } + + return the_value; + } + + static toUTF8Array(str) { + var utf8 = []; + for (var i = 0; i < str.length; i++) { + var charcode = str.charCodeAt(i); + if (charcode < 128) { + utf8.push(charcode); + } else if (charcode < 2048) { + utf8.push(192 | charcode >> 6, 128 | charcode & 63); + } else if (charcode < 55296 || charcode >= 57344) { + utf8.push(224 | charcode >> 12, 128 | charcode >> 6 & 63, 128 | charcode & 63); + } + // surrogate pair + else { + i++; + // UTF-16 encodes 0x10000-0x10FFFF by + // subtracting 0x10000 and splitting the + // 20 bits of 0x0-0xFFFFF into two halves + charcode = 65536 + ((charcode & 1023) << 10 | str.charCodeAt(i) & 1023); + utf8.push(240 | charcode >> 18, 128 | charcode >> 12 & 63, 128 | charcode >> 6 & 63, 128 | charcode & 63); + } + } + return utf8; + } + + static toUTF16Array(str) { + var utf16 = []; + for (var i = 0; i < str.length; i++) { + var codePoint = str.codePointAt(i); + + if (codePoint <= 255) { + utf16.push(0); + utf16.push(codePoint); + } else { + utf16.push(codePoint >> 8 & 255); + utf16.push(codePoint & 255); + } + } + return utf16; + } + + static toUTF32Array(str) { + var utf32 = []; + for (var i = 0; i < str.length; i++) { + var codePoint = str.codePointAt(i); + + if (codePoint <= 255) { + utf32.push(0); + utf32.push(0); + utf32.push(0); + utf32.push(codePoint); + } else { + utf32.push(0); + utf32.push(0); + utf32.push(codePoint >> 8 & 255); + utf32.push(codePoint & 255); + } + } + return utf32; + } + + //http://stackoverflow.com/questions/2003493/javascript-float-from-to-bits + static float32ToBytes(f) { + var bytes = []; + + var buf = new ArrayBuffer(4); + new Float32Array(buf)[0] = f; + + let intVersion = new Uint32Array(buf)[0]; + + bytes.push(intVersion >> 24 & 255); + bytes.push(intVersion >> 16 & 255); + bytes.push(intVersion >> 8 & 255); + bytes.push(intVersion & 255); + + return bytes; + } + + static float64ToBytes(f) { + var bytes = []; + + var buf = new ArrayBuffer(8); + new Float64Array(buf)[0] = f; + + var intVersion1 = new Uint32Array(buf)[0]; + var intVersion2 = new Uint32Array(buf)[1]; + + bytes.push(intVersion2 >> 24 & 255); + bytes.push(intVersion2 >> 16 & 255); + bytes.push(intVersion2 >> 8 & 255); + bytes.push(intVersion2 & 255); + + bytes.push(intVersion1 >> 24 & 255); + bytes.push(intVersion1 >> 16 & 255); + bytes.push(intVersion1 >> 8 & 255); + bytes.push(intVersion1 & 255); + + return bytes; + } +} + +/* @flow */ + +class Mailbox { + + constructor() { + this.messages = []; + } + + deliver(message) { + this.messages.push(message); + return message; + } + + get() { + return this.messages; + } + + isEmpty() { + return this.messages.length === 0; + } + + removeAt(index) { + this.messages.splice(index, 1); + } +} + +var States = { + NORMAL: Symbol.for("normal"), + KILL: Symbol.for("kill"), + SUSPEND: Symbol.for("suspend"), + CONTINUE: Symbol.for("continue"), + RECEIVE: Symbol.for("receive"), + SEND: Symbol.for("send"), + SLEEPING: Symbol.for("sleeping"), + RUNNING: Symbol.for("running"), + SUSPENDED: Symbol.for("suspended"), + STOPPED: Symbol.for("stopped"), + SLEEP: Symbol.for("sleep"), + EXIT: Symbol.for("exit"), + NOMATCH: Symbol.for("no_match") +}; + +class Process { + + constructor(pid, mailbox) { + this.pid = pid; + this.mailbox = mailbox; + this.status = States.STOPPED; + this.dict = {}; + } +} + +class ProcessSystem { + + constructor() { + this.pids = new Map(); + this.mailboxes = new Map(); + this.names = new Map(); + this.links = new Map(); + + this.current_process = null; + this.suspended = new Map(); + + this.main_process_pid = this.spawn(); + this.set_current(this.main_process_pid); + } + + spawn() { + return this.add_proc(false).pid; + } + + spawn_link() { + return this.add_proc(true).pid; + } + + link(pid) { + this.links.get(this.pid()).add(pid); + this.links.get(pid).add(this.pid()); + } + + unlink(pid) { + this.links.get(this.pid()).delete(pid); + this.links.get(pid).delete(this.pid()); + } + + set_current(id) { + let pid = this.pidof(id); + if (pid !== null) { + this.current_process = this.pids.get(pid); + this.current_process.status = States.RUNNING; + } + } + + add_proc(linked) { + let newpid = new PID(); + let mailbox = new Mailbox(); + let newproc = new Process(newpid, mailbox); + + this.pids.set(newpid, newproc); + this.mailboxes.set(newpid, mailbox); + this.links.set(newpid, new Set()); + + if (linked) { + this.link(newpid); + } + + return newproc; + } + + remove_proc(pid) { + this.pids.delete(pid); + this.unregister(pid); + + if (this.links.has(pid)) { + for (let linkpid of this.links.get(pid)) { + this.links.get(linkpid).delete(pid); + } + + this.links.delete(pid); + } + } + + exit(id) { + let pid = this.pidof(id); + this.remove_proc(id); + } + + register(name, pid) { + if (!this.names.has(name)) { + this.names.set(name, pid); + return name; + } else { + throw new Error("Name is already registered to another process"); + } + } + + registered(name) { + return this.names.has(name) ? this.names.get(name) : null; + } + + unregister(pid) { + for (let name of this.names.keys()) { + if (this.names.has(name) && this.names.get(name) === pid) { + this.names.delete(name); + } + } + } + + pid() { + return this.current_process.pid; + } + + pidof(id) { + if (id instanceof PID) { + return this.pids.has(id) ? id : null; + } else if (id instanceof Process) { + return id.pid; + } else { + let pid = this.registered(id); + if (pid === null) throw "Process name not registered: " + id + " (" + typeof id + ")"; + return pid; + } + } + + put(id, key, value) { + let pid = this.pidof(id); + let process = this.pids.get(pid); + process.dict[key] = value; + } + + get(id, key) { + let pid = this.pidof(id); + let process = this.pids.get(pid); + + if (key != null) { + return process.dict[key]; + } else { + return process.dict; + } + } + + get_keys(id) { + let pid = this.pidof(id); + let process = this.pids.get(pid); + + return Object.keys(process.dict); + } + + erase(id, key) { + let pid = this.pidof(id); + let process = this.pids.get(pid); + + if (key != null) { + delete process.dict[key]; + } else { + process.dict = {}; + } + } +} + +var C = Object.freeze({ + ProcessSystem: ProcessSystem, + Tuple: Tuple$1, + PID: PID, + BitString: BitString, + Patterns: Patterns, + Integer: Integer$1, + Float: Float, + call_property: call_property +}); + +let Enum = { + + all__qmark__: function (collection, fun = x => x) { + for (let elem of collection) { + if (!fun(elem)) { + return false; + } + } + + return true; + }, + + any__qmark__: function (collection, fun = x => x) { + for (let elem of collection) { + if (fun(elem)) { + return true; + } + } + + return false; + }, + + at: function (collection, n, the_default = null) { + if (n > this.count(collection) || n < 0) { + return the_default; + } + + return collection[n]; + }, + + concat: function (...enumables) { + return enumables[0].concat(enumables[1]); + }, + + count: function (collection, fun = null) { + if (fun == null) { + return collection.length; + } else { + return collection.filter(fun).length; + } + }, + + drop: function (collection, count) { + return collection.slice(count); + }, + + drop_while: function (collection, fun) { + let count = 0; + + for (let elem of collection) { + if (fun(elem)) { + count = count + 1; + } else { + break; + } + } + + return collection.slice(count); + }, + + each: function (collection, fun) { + for (let elem of collection) { + fun(elem); + } + }, + + empty__qmark__: function (collection) { + return collection.length === 0; + }, + + fetch: function (collection, n) { + if (Kernel.is_list(collection)) { + if (n < this.count(collection) && n >= 0) { + return Kernel.SpecialForms.tuple(Kernel.SpecialForms.atom("ok"), collection[n]); + } else { + return Kernel.SpecialForms.atom("error"); + } + } + + throw new Error("collection is not an Enumerable"); + }, + + fetch__emark__: function (collection, n) { + if (Kernel.is_list(collection)) { + if (n < this.count(collection) && n >= 0) { + return collection[n]; + } else { + throw new Error("out of bounds error"); + } + } + + throw new Error("collection is not an Enumerable"); + }, + + filter: function (collection, fun) { + let result = []; + + for (let elem of collection) { + if (fun(elem)) { + result.push(elem); + } + } + + return result; + }, + + filter_map: function (collection, filter, mapper) { + return Enum.map(Enum.filter(collection, filter), mapper); + }, + + find: function (collection, if_none = null, fun) { + for (let elem of collection) { + if (fun(elem)) { + return elem; + } + } + + return if_none; + }, + + into: function (collection, list) { + return list.concat(collection); + }, + + map: function (collection, fun) { + let result = []; + + for (let elem of collection) { + result.push(fun(elem)); + } + + return result; + }, + + map_reduce: function (collection, acc, fun) { + let mapped = Kernel.SpecialForms.list(); + let the_acc = acc; + + for (var i = 0; i < this.count(collection); i++) { + let tuple = fun(collection[i], the_acc); + + the_acc = Kernel.elem(tuple, 1); + mapped = Kernel.SpecialForms.list(...mapped.concat([Kernel.elem(tuple, 0)])); + } + + return Kernel.SpecialForms.tuple(mapped, the_acc); + }, + + member: function (collection, value) { + return collection.includes(value); + }, + + reduce: function (collection, acc, fun) { + let the_acc = acc; + + for (var i = 0; i < this.count(collection); i++) { + let tuple = fun(collection[i], the_acc); + + the_acc = Kernel.elem(tuple, 1); + } + + return the_acc; + }, + + take: function (collection, count) { + return collection.slice(0, count); + }, + + take_every: function (collection, nth) { + let result = []; + let index = 0; + + for (let elem of collection) { + if (index % nth === 0) { + result.push(elem); + } + } + + return Kernel.SpecialForms.list(...result); + }, + + take_while: function (collection, fun) { + let count = 0; + + for (let elem of collection) { + if (fun(elem)) { + count = count + 1; + } else { + break; + } + } + + return collection.slice(0, count); + }, + + to_list: function (collection) { + return collection; + } +}; + +let SpecialForms = { + + __DIR__: function () { + if (__dirname) { + return __dirname; + } + + if (document.currentScript) { + return document.currentScript.src; + } + + return null; + }, + + atom: function (_value) { + return Symbol.for(_value); + }, + + list: function (...args) { + return Object.freeze(args); + }, + + bitstring: function (...args) { + return new BitString(...args); + }, + + bound: function (_var) { + return Patterns.bound(_var); + }, + + _case: function (condition, clauses) { + return Patterns.defmatch(...clauses)(condition); + }, + + cond: function (clauses) { + for (let clause of clauses) { + if (clause[0]) { + return clause[1](); + } + } + + throw new Error(); + }, + + fn: function (clauses) { + return Patterns.defmatch(clauses); + }, + + map: function (obj) { + return Object.freeze(obj); + }, + + map_update: function (map, values) { + return Object.freeze(Object.assign(Object.create(map.constructor.prototype), map, values)); + }, + + _for: function (collections, fun, filter = () => true, into = [], previousValues = []) { + let pattern = collections[0][0]; + let collection = collections[0][1]; + + if (collections.length === 1) { + + for (let elem of collection) { + let r = Patterns.match_no_throw(pattern, elem); + let args = previousValues.concat(r); + + if (r && filter.apply(this, args)) { + into = Enum.into([fun.apply(this, args)], into); + } + } + + return into; + } else { + let _into = []; + + for (let elem of collection) { + let r = Patterns.match_no_throw(pattern, elem); + if (r) { + _into = Enum.into(this._for(collections.slice(1), fun, filter, _into, previousValues.concat(r)), into); + } + } + + return _into; + } + }, + + receive: function (receive_fun, timeout_in_ms = null, timeout_fn = time => true) { + if (timeout_in_ms == null || timeout_in_ms === System.for('infinity')) { + while (true) { + if (self.mailbox.length !== 0) { + let message = self.mailbox[0]; + self.mailbox = self.mailbox.slice(1); + return receive_fun(message); + } + } + } else if (timeout_in_ms === 0) { + if (self.mailbox.length !== 0) { + let message = self.mailbox[0]; + self.mailbox = self.mailbox.slice(1); + return receive_fun(message); + } else { + return null; + } + } else { + let now = Date.now(); + while (Date.now() < now + timeout_in_ms) { + if (self.mailbox.length !== 0) { + let message = self.mailbox[0]; + self.mailbox = self.mailbox.slice(1); + return receive_fun(message); + } + } + + return timeout_fn(timeout_in_ms); + } + }, + + tuple: function (...args) { + return new Tuple$1(...args); + }, + + _try: function (do_fun, rescue_function, catch_fun, else_function, after_function) { + let result = null; + + try { + result = do_fun(); + } catch (e) { + let ex_result = null; + + if (rescue_function) { + try { + ex_result = rescue_function(e); + return ex_result; + } catch (ex) { + if (ex instanceof Patterns.MatchError) { + throw ex; + } + } + } + + if (catch_fun) { + try { + ex_result = catch_fun(e); + return ex_result; + } catch (ex) { + if (ex instanceof Patterns.MatchError) { + throw ex; + } + } + } + + throw e; + } finally { + if (after_function) { + after_function(); + } + } + + if (else_function) { + try { + return else_function(result); + } catch (ex) { + if (ex instanceof Patterns.MatchError) { + throw new Error('No Match Found in Else'); + } + + throw ex; + } + } else { + return result; + } + } + +}; + +function to_string$1(tuple) { + return tuple.toString(); +}; + +function delete_at(tuple, index) { + let new_list = []; + + for (var i = 0; i < tuple.count(); i++) { + if (i !== index) { + new_list.push(tuple.get(i)); + } + } + + return Kernel.SpecialForms.tuple.apply(null, new_list); +}; + +function duplicate(data, size) { + let array = []; + + for (var i = size - 1; i >= 0; i--) { + array.push(data); + } + + return Kernel.SpecialForms.tuple.apply(null, array); +}; + +function insert_at(tuple, index, term) { + let new_tuple = []; + + for (var i = 0; i <= tuple.count(); i++) { + if (i === index) { + new_tuple.push(term); + i++; + new_tuple.push(tuple.get(i)); + } else { + new_tuple.push(tuple.get(i)); + } + } + + return Kernel.SpecialForms.tuple.apply(null, new_tuple); +}; + +function from_list(list) { + return Kernel.SpecialForms.tuple.apply(null, list); +}; + +function to_list(tuple) { + let new_list = []; + + for (var i = 0; i < tuple.count(); i++) { + new_list.push(tuple.get(i)); + } + + return Kernel.SpecialForms.list(...new_list); +}; + +var Tuple = { + to_string: to_string$1, + delete_at, + duplicate, + insert_at, + from_list, + to_list +}; + +//https://github.com/airportyh/protomorphism +class Protocol { + constructor(spec) { + this.registry = new Map(); + this.fallback = null; + + for (let funName in spec) { + this[funName] = createFun(funName).bind(this); + } + + function createFun(funName) { + + return function (...args) { + let thing = args[0]; + let fun = null; + + if (Number.isInteger(thing) && this.hasImplementation(Integer$1)) { + fun = this.registry.get(Integer$1)[funName]; + } else if (typeof thing === "number" && !Number.isInteger(thing) && this.hasImplementation(Float)) { + fun = this.registry.get(Float)[funName]; + } else if (this.hasImplementation(thing)) { + fun = this.registry.get(thing.constructor)[funName]; + } else if (this.fallback) { + fun = this.fallback[funName]; + } + + if (fun != null) { + let retval = fun.apply(this, args); + return retval; + } + + throw new Error("No implementation found for " + thing); + }; + } + } + + implementation(type, implementation) { + if (type === null) { + this.fallback = implementation; + } else { + this.registry.set(type, implementation); + } + } + + hasImplementation(thing) { + return this.registry.has(thing.constructor); + } +} + +function tl(list) { + return SpecialForms.list(...list.slice(1)); +} + +function hd(list) { + return list[0]; +} + +function is_nil(x) { + return x === null; +} + +function is_atom(x) { + return typeof x === 'symbol'; +} + +function is_binary(x) { + return typeof x === 'string' || x instanceof String; +} + +function is_boolean(x) { + return typeof x === 'boolean' || x instanceof Boolean; +} + +function is_function(x, arity = -1) { + return typeof x === 'function' || x instanceof Function; +} + +function is_float(x) { + return is_number(x) && !Number.isInteger(x); +} + +function is_integer(x) { + return Number.isInteger(x); +} + +function is_list(x) { + return x instanceof Array; +} + +function is_map(x) { + return typeof x === 'object' || x instanceof Object; +} + +function is_number(x) { + return typeof x === 'number'; +} + +function is_tuple(x) { + return x instanceof Tuple$1; +} + +function length(x) { + return x.length; +} + +function is_pid(x) { + return x instanceof PID; +} + +function is_port(x) { + return false; +} + +function is_reference(x) { + return false; +} + +function is_bitstring(x) { + return is_binary(x) || x instanceof BitString; +} + +function __in__(left, right) { + for (let x of right) { + if (match__qmark__(left, x)) { + return true; + } + } + + return false; +} + +function abs(number) { + return Math.abs(number); +} + +function round(number) { + return Math.round(number); +} + +function elem(tuple, index) { + if (is_list(tuple)) { + return tuple[index]; + } + + return tuple.get(index); +} + +function rem(left, right) { + return left % right; +} + +function div(left, right) { + return left / right; +} + +function and(left, right) { + return left && right; +} + +function or(left, right) { + return left || right; +} + +function not(arg) { + return !arg; +} + +function apply(...args) { + if (args.length === 3) { + let mod = args[0]; + let func = args[1]; + let func_args = args[2]; + return mod[func].apply(null, func_args); + } else { + let func = args[0]; + let func_args = args[1]; + + return func.apply(null, func_args); + } +} + +function to_string(arg) { + if (is_tuple(arg)) { + return Tuple.to_string(arg); + } + + return arg.toString(); +} + +function match__qmark__(pattern, expr, guard = () => true) { + return Patterns.match_no_throw(pattern, expr, guard) != null; +} + +function defstruct(defaults) { + return class { + constructor(update = {}) { + let the_values = Object.assign(defaults, update); + Object.assign(this, the_values); + } + + static create(updates = {}) { + let x = new this(updates); + return Object.freeze(x); + } + }; +} + +function defprotocol(spec) { + return new Protocol(spec); +} + +function defimpl(protocol, type, impl) { + protocol.implementation(type, impl); +} + +var Kernel = { + SpecialForms, + tl, + hd, + is_nil, + is_atom, + is_binary, + is_boolean, + is_function, + is_float, + is_integer, + is_list, + is_map, + is_number, + is_tuple, + length, + is_pid, + is_port, + is_reference, + is_bitstring, + in: __in__, + abs, + round, + elem, + rem, + div, + and, + or, + not, + apply, + to_string, + match__qmark__, + defstruct, + defprotocol, + defimpl +}; + +let Atom = {}; + +Atom.to_string = function (atom) { + return Symbol.keyFor(atom); +}; + +Atom.to_char_list = function (atom) { + return Atom.to_string(atom).split(''); +}; + +let Integer = { + + is_even: function (n) { + return n % 2 === 0; + }, + + is_odd: function (n) { + return n % 2 !== 0; + }, + + parse: function (bin) { + let result = parseInt(bin); + + if (isNaN(result)) { + return Kernel.SpecialForms.atom("error"); + } + + let indexOfDot = bin.indexOf("."); + + if (indexOfDot >= 0) { + return Kernel.SpecialForms.tuple(result, bin.substring(indexOfDot)); + } + + return Kernel.SpecialForms.tuple(result, ""); + }, + + to_char_list: function (number, base = 10) { + return number.toString(base).split(""); + }, + + to_string: function (number, base = 10) { + return number.toString(base); + } +}; + +let Chars$1 = Kernel.defprotocol({ + to_string: function (thing) {} +}); + +Kernel.defimpl(Chars$1, BitString, { + to_string: function (thing) { + if (Kernel.is_binary(thing)) { + return thing; + } + + return thing.toString(); + } +}); + +Kernel.defimpl(Chars$1, Symbol, { + to_string: function (thing) { + if (nil) { + return ""; + } + + return Atom.to_string(thing); + } +}); + +Kernel.defimpl(Chars$1, Integer$1, { + to_string: function (thing) { + return Integer.to_string(thing); + } +}); + +Kernel.defimpl(Chars$1, Float, { + to_string: function (thing) { + return thing.toString; + } +}); + +Kernel.defimpl(Chars$1, Array, { + to_string: function (thing) { + return thing.toString(); + } +}); + +Kernel.defimpl(Chars$1, Tuple$1, { + to_string: function (thing) { + return Tuple.to_string(thing); + } +}); + +Kernel.defimpl(Chars$1, null, { + to_string: function (thing) { + return thing.toString(); + } +}); + +function to_atom(string) { + return Symbol.for(string); +} + +function to_existing_atom(string) { + return Symbol.for(string); +} + +function to_char_list(string) { + return string.split(''); +} + +function to_float(string) { + return parseFloat(string); +} + +function to_integer(string, base = 10) { + return parseInt(string, base); +} + +function upcase(binary) { + return binary.toUpperCase(); +} + +function downcase(binary) { + return binary.toLowerCase(); +} + +function at(string, position) { + if (position > string.length - 1) { + return null; + } + + return string[position]; +} + +function capitalize(string) { + let returnString = ''; + + for (let i = 0; i < string.length; i++) { + if (i === 0) { + returnString = returnString + string[i].toUpperCase(); + } else { + returnString = returnString + string[i].toLowerCase(); + } + } + + return returnString; +} + +function codepoints(string) { + return to_char_list(string).map(function (c) { + return c.codePointAt(0); + }); +} + +function contains__qm__(string, contains) { + if (Array.isArray(contains)) { + return contains.some(function (s) { + return string.indexOf(s) > -1; + }); + } + + return string.indexOf(contains) > -1; +} + +function duplicate$1(subject, n) { + return subject.repeat(n); +} + +function ends_with__qm__(string, suffixes) { + if (Array.isArray(suffixes)) { + return suffixes.some(function (s) { + return string.endsWith(s); + }); + } + + return string.endsWith(suffixes); +} + +function first(string) { + if (!string) { + return null; + } + + return string[0]; +} + +function graphemes(string) { + return string.split(''); +} + +function last(string) { + if (!string) { + return null; + } + + return string[string.length - 1]; +} + +function length$1(string) { + return string.length; +} + +function match__qm__(string, regex) { + return string.match(regex) != null; +} + +function next_codepoint(string) { + if (!string || string === '') { + return null; + } + + return Kernel.SpecialForms.tuple(string[0].codePointAt(0), string.substr(1)); +} + +function next_grapheme(string) { + if (!string || string === '') { + return null; + } + + return Kernel.SpecialForms.tuple(string[0], string.substr(1)); +} + +function reverse(string) { + let returnValue = ''; + + for (var i = string.length - 1; i >= 0; i--) { + returnValue = returnValue + string[i]; + }; + + return returnValue; +} + +function split(string) { + return string.split(); +} + +function starts_with__qm__(string, prefixes) { + if (Array.isArray(prefixes)) { + return prefixes.some(function (s) { + return string.startsWith(s); + }); + } + + return string.startsWith(prefixes); +} + +function valid_character__qm__(codepoint) { + try { + return String.fromCodePoint(codepoint) != null; + } catch (e) { + return false; + } +} + +var String$1 = { + at, + capitalize, + codepoints, + contains__qm__, + downcase, + duplicate: duplicate$1, + ends_with__qm__, + first, + graphemes, + last, + length: length$1, + match__qm__, + next_codepoint, + next_grapheme, + reverse, + split, + starts_with__qm__, + to_atom, + to_char_list, + to_existing_atom, + to_float, + to_integer, + upcase, + valid_character__qm__, + Chars: Chars$1 +}; + +let Chars = Kernel.defprotocol({ + to_char_list: function (thing) {} +}); + +Kernel.defimpl(Chars, BitString, { + to_char_list: function (thing) { + if (Kernel.is_binary(thing)) { + return String$1.to_char_list(thing); + } + + return thing.toString(); + } +}); + +Kernel.defimpl(Chars, Symbol, { + to_char_list: function (thing) { + return Atom.to_char_list(thing); + } +}); + +Kernel.defimpl(Chars, Integer$1, { + to_char_list: function (thing) { + return Integer.to_char_list(thing); + } +}); + +Kernel.defimpl(Chars, Array, { + to_char_list: function (thing) { + return thing; + } +}); + +let List = {}; + +List.Chars = Chars; + +List.delete = function (list, item) { + let new_value = []; + let value_found = false; + + for (let x of list) { + if (x === item && value_found !== false) { + new_value.push(x); + value_found = true; + } else if (x !== item) { + new_value.push(x); + } + } + + return Kernel.SpecialForms.list(...new_value); +}; + +List.delete_at = function (list, index) { + let new_value = []; + + for (let i = 0; i < list.length; i++) { + if (i !== index) { + new_value.push(list[i]); + } + } + + return Kernel.SpecialForms.list(...new_value); +}; + +List.duplicate = function (elem, n) { + let new_value = []; + + for (var i = 0; i < n; i++) { + new_value.push(elem); + } + + return Kernel.SpecialForms.list(...new_value); +}; + +List.first = function (list) { + return list[0]; +}; + +List.flatten = function (list, tail = Kernel.SpecialForms.list()) { + let new_value = []; + + for (let x of list) { + if (Kernel.is_list(x)) { + new_value = new_value.concat(List.flatten(x)); + } else { + new_value.push(x); + } + } + + new_value = new_value.concat(tail); + + return Kernel.SpecialForms.list(...new_value); +}; + +List.foldl = function (list, acc, func) { + return list.reduce(func, acc); +}; + +List.foldr = function (list, acc, func) { + let new_acc = acc; + + for (var i = list.length - 1; i >= 0; i--) { + new_acc = func(list[i], new_acc); + } + + return new_acc; +}; + +List.insert_at = function (list, index, value) { + let new_value = []; + + for (let i = 0; i < list.length; i++) { + if (i === index) { + new_value.push(value); + new_value.push(list[i]); + } else { + new_value.push(list[i]); + } + } + + return Kernel.SpecialForms.list(...new_value); +}; + +List.keydelete = function (list, key, position) { + let new_list = []; + + for (let i = 0; i < list.length; i++) { + if (!Kernel.match__qmark__(list[i][position], key)) { + new_list.push(list[i]); + } + } + + return Kernel.SpecialForms.list(...new_list); +}; + +List.keyfind = function (list, key, position, _default = null) { + + for (let i = 0; i < list.length; i++) { + if (Kernel.match__qmark__(list[i][position], key)) { + return list[i]; + } + } + + return _default; +}; + +List.keymember__qmark__ = function (list, key, position) { + + for (let i = 0; i < list.length; i++) { + if (Kernel.match__qmark__(list[i][position], key)) { + return true; + } + } + + return false; +}; + +List.keyreplace = function (list, key, position, new_tuple) { + let new_list = []; + + for (let i = 0; i < list.length; i++) { + if (!Kernel.match__qmark__(list[i][position], key)) { + new_list.push(list[i]); + } else { + new_list.push(new_tuple); + } + } + + return Kernel.SpecialForms.list(...new_list); +}; + +List.keysort = function (list, position) { + let new_list = list; + + new_list.sort(function (a, b) { + if (position === 0) { + if (a[position].value < b[position].value) { + return -1; + } + + if (a[position].value > b[position].value) { + return 1; + } + + return 0; + } else { + if (a[position] < b[position]) { + return -1; + } + + if (a[position] > b[position]) { + return 1; + } + + return 0; + } + }); + + return Kernel.SpecialForms.list(...new_list); +}; + +List.keystore = function (list, key, position, new_tuple) { + let new_list = []; + let replaced = false; + + for (let i = 0; i < list.length; i++) { + if (!Kernel.match__qmark__(list[i][position], key)) { + new_list.push(list[i]); + } else { + new_list.push(new_tuple); + replaced = true; + } + } + + if (!replaced) { + new_list.push(new_tuple); + } + + return Kernel.SpecialForms.list(...new_list); +}; + +List.last = function (list) { + return list[list.length - 1]; +}; + +List.replace_at = function (list, index, value) { + let new_value = []; + + for (let i = 0; i < list.length; i++) { + if (i === index) { + new_value.push(value); + } else { + new_value.push(list[i]); + } + } + + return Kernel.SpecialForms.list(...new_value); +}; + +List.update_at = function (list, index, fun) { + let new_value = []; + + for (let i = 0; i < list.count(); i++) { + if (i === index) { + new_value.push(fun(list.get(i))); + } else { + new_value.push(list.get(i)); + } + } + + return new_value; +}; + +List.wrap = function (list) { + if (Kernel.is_list(list)) { + return list; + } else if (list == null) { + return Kernel.SpecialForms.list(); + } else { + return Kernel.SpecialForms.list(list); + } +}; + +List.zip = function (list_of_lists) { + if (list_of_lists.length === 0) { + return Kernel.SpecialForms.list(); + } + + let new_value = []; + let smallest_length = list_of_lists[0]; + + for (let x of list_of_lists) { + if (x.length < smallest_length) { + smallest_length = x.length; + } + } + + for (let i = 0; i < smallest_length; i++) { + let current_value = []; + for (let j = 0; j < list_of_lists.length; j++) { + current_value.push(list_of_lists[j][i]); + } + + new_value.push(Kernel.SpecialForms.tuple(...current_value)); + } + + return Kernel.SpecialForms.list(...new_value); +}; + +List.to_tuple = function (list) { + return Kernel.SpecialForms.tuple.apply(null, list); +}; + +List.append = function (list, value) { + return Kernel.SpecialForms.list(...list.concat([value])); +}; + +List.prepend = function (list, value) { + return Kernel.SpecialForms.list(...[value].concat(list)); +}; + +List.concat = function (left, right) { + return left.concat(right); +}; + +let Range = function (_first, _last) { + if (!(this instanceof Range)) { + return new Range(_first, _last); + } + + this.first = function () { + return _first; + }; + + this.last = function () { + return _last; + }; + + let _range = []; + + for (let i = _first; i <= _last; i++) { + _range.push(i); + } + + _range = Object.freeze(_range); + + this.value = function () { + return _range; + }; + + this.length = function () { + return _range.length; + }; + + return this; +}; + +Range.prototype[Symbol.iterator] = function () { + return this.value()[Symbol.iterator](); +}; + +Range.new = function (first, last) { + return Range(first, last); +}; + +Range.range__qmark__ = function (range) { + return range instanceof Range; +}; + +let Keyword = {}; + +Keyword.has_key__qm__ = function (keywords, key) { + for (let keyword of keywords) { + if (Kernel.elem(keyword, 0) == key) { + return true; + } + } + + return false; +}; + +Keyword.get = function (keywords, key, the_default = null) { + for (let keyword of keywords) { + if (Kernel.elem(keyword, 0) == key) { + return Kernel.elem(keyword, 1); + } + } + + return the_default; +}; + +let Agent = {}; + +Agent.start = function (fun, options = []) { + let pid = self.processes.spawn(); + + if (Keyword.has_key__qm__(options, Kernel.SpecialForms.atom('name'))) { + pid = self.processes.register(Keyword.get(options, Kernel.SpecialForms.atom('name')), pid); + } + + self.processes.put(pid, 'state', fun()); + return Kernel.SpecialForms.tuple(Kernel.SpecialForms.atom('ok'), pid); +}; + +Agent.stop = function (agent, timeout = 5000) { + self.processes.exit(agent); + return Kernel.SpecialForms.atom('ok'); +}; + +Agent.update = function (agent, fun, timeout = 5000) { + + const current_state = self.processes.get(agent, 'state'); + self.processes.put(agent, 'state', fun(current_state)); + + return Kernel.SpecialForms.atom('ok'); +}; + +Agent.get = function (agent, fun, timeout = 5000) { + return fun(self.processes.get(agent, 'state')); +}; + +Agent.get_and_update = function (agent, fun, timeout = 5000) { + + const get_and_update_tuple = fun(self.processes.get(agent, 'state')); + self.processes.put(agent, 'state', Kernel.elem(get_and_update_tuple, 1)); + + return Kernel.elem(get_and_update_tuple, 0); +}; + +//https://developer.mozilla.org/en-US/docs/Web/API/WindowBase64/Base64_encoding_and_decoding#Solution_2_%E2%80%93_rewrite_the_DOMs_atob()_and_btoa()_using_JavaScript's_TypedArrays_and_UTF-8 +function b64EncodeUnicode(str) { + return btoa(encodeURIComponent(str).replace(/%([0-9A-F]{2})/g, function (match, p1) { + return String.fromCharCode('0x' + p1); + })); +} + +function encode64(data) { + return b64EncodeUnicode(data); +} + +function decode64(data) { + try { + return Kernel.SpecialForms.tuple(Kernel.SpecialForms.atom('ok'), atob(data)); + } catch (e) { + return Kernel.SpecialForms.atom('error'); + } + return btoa(data); +} + +function decode64__em__(data) { + return atob(data); +} + +var base = { + encode64, + decode64, + decode64__em__ +}; + +function bnot(expr) { + return ~expr; +} + +function band(left, right) { + return left & right; +} + +function bor(left, right) { + return left | right; +} + +function bsl(left, right) { + return left << right; +} + +function bsr(left, right) { + return left >> right; +} + +function bxor(left, right) { + return left ^ right; +} + +var bitwise = { + bnot, + band, + bor, + bsl, + bsr, + bxor +}; + +let Enumerable = Kernel.defprotocol({ + count: function (collection) {}, + member_qmark__: function (collection, value) {}, + reduce: function (collection, acc, fun) {} +}); + +let Collectable = Kernel.defprotocol({ + into: function (collectable) {} +}); + +let Inspect = Kernel.defprotocol({ + inspect: function (thing, opts) {} +}); + +function __new__() { + return SpecialForms.map({}); +} + +function keys(map) { + return Object.keys(map); +} + +function size(map) { + return keys(map).length; +} + +function to_list$1(map) { + let map_keys = keys(map); + let list = []; + + for (let key of map_keys) { + list.push(SpecialForms.tuple(key, map[key])); + } + + return SpecialForms.list(...list); +} + +function values(map) { + let map_keys = keys(map); + let list = []; + + for (let key of map_keys) { + list.push(map[key]); + } + + return SpecialForms.list(...list); +} + +function from_struct(struct) { + let map = Object.assign({}, struct); + delete map[Symbol.for("__struct__")]; + + return SpecialForms.map(map); +} + +function __delete__(map, key) { + let new_map = Object.assign({}, map); + + delete new_map[key]; + + return SpecialForms.map(new_map); +} + +function equal__qmark__(map1, map2) { + return map1 === map2; +} + +function fetch__emark__(map, key) { + if (key in map) { + return map[key]; + } + + throw new Error("Key not found."); +} + +function fetch(map, key) { + if (key in map) { + return SpecialForms.tuple(SpecialForms.atom("ok"), map[key]); + } + + return SpecialForms.atom("error"); +} + +function has_key__qmark__(map, key) { + return key in map; +} + +function split$1(map, keys) { + let split1 = {}; + let split2 = {}; + + for (let key of Object.keys(map)) { + if (keys.indexOf(key) > -1) { + split1[key] = map[key]; + } else { + split2[key] = map[key]; + } + } + + return SpecialForms.tuple(SpecialForms.map(split1), SpecialForms.map(split2)); +} + +function take(map, keys) { + let split1 = {}; + + for (let key of Object.keys(map)) { + if (keys.indexOf(key) > -1) { + split1[key] = map[key]; + } + } + + return SpecialForms.map(split1); +} + +function drop(map, keys) { + let split1 = {}; + + for (let key of Object.keys(map)) { + if (keys.indexOf(key) === -1) { + split1[key] = map[key]; + } + } + + return SpecialForms.map(split1); +} + +function put_new(map, key, value) { + if (key in map) { + return map; + } + + let new_map = Object.assign({}, map); + new_map[key] = value; + + return SpecialForms.map(new_map); +} + +function put_new_lazy(map, key, fun) { + if (key in map) { + return map; + } + + let new_map = Object.assign({}, map); + new_map[key] = fun(); + + return SpecialForms.map(new_map); +} + +function get_and_update(map, key, fun) { + if (key in map) { + return map; + } + + let new_map = Object.assign({}, map); + new_map[key] = fun(map[key]); + + return SpecialForms.map(new_map); +} + +function pop_lazy(map, key, fun) { + if (!key in map) { + return SpecialForms.tuple(fun(), map); + } + + let new_map = Object.assign({}, map); + let value = fun(new_map[key]); + delete new_map[key]; + + return SpecialForms.tuple(value, new_map); +} + +function pop(map, key, _default = null) { + if (!key in map) { + return SpecialForms.tuple(_default, map); + } + + let new_map = Object.assign({}, map); + let value = new_map[key]; + delete new_map[key]; + + return SpecialForms.tuple(value, new_map); +} + +function get_lazy(map, key, fun) { + if (!key in map) { + return fun(); + } + + return fun(map[key]); +} + +function get(map, key, _default = null) { + if (!key in map) { + return _default; + } + + return map[key]; +} + +function put(map, key, val) { + let new_map = Object({}, map); + new_map[key] = val; + + return SpecialForms.map(new_map); +} + +function update__emark__(map, key, fun) { + if (!key in map) { + throw new Error("Key not found"); + } + + let new_map = Object({}, map); + new_map[key] = fun(map[key]); + + return SpecialForms.map(new_map); +} + +function update(map, key, initial, fun) { + let new_map = Object({}, map); + + if (!key in map) { + new_map[key] = initial; + } else { + new_map[key] = fun(map[key]); + } + + return SpecialForms.map(new_map); +} + +var map = { + new: __new__, + keys, + size, + to_list: to_list$1, + values, + from_struct, + delete: __delete__, + drop, + equal__qmark__, + fetch__emark__, + fetch, + has_key__qmark__, + split: split$1, + take, + put_new, + put_new_lazy, + get_and_update, + pop_lazy, + pop, + get_lazy, + get, + put, + update__emark__, + update +}; + +function __new__$1() { + return SpecialForms.map({ [Symbol.for('__struct__')]: Symbol.for('MapSet'), set: SpecialForms.list() }); +} + +function size$2(map) { + return map.set.length; +} + +function to_list$3(map) { + return map.set; +} + +function __delete__$2(set, term) { + let new_list = List.delete(set.set, term); + + let new_map = Object.assign({}, set); + new_map.set = new_list; + return SpecialForms.map(new_map); +} + +function put$2(set, term) { + if (set.set.indexOf(term) === -1) { + let new_list = List.append(set.set, term); + + let new_map = Object.assign({}, set); + new_map.set = new_list; + return SpecialForms.map(new_map); + } + + return set; +} + +function difference$1(set1, set2) { + let new_map = Object.assign({}, set1); + + for (let val of set1.set) { + if (member__qmark__$1(set2, val)) { + new_map.set = List.delete(new_map.set, val); + } + } + + return SpecialForms.map(new_map); +} + +function intersection$1(set1, set2) { + let new_map = Object.assign({}, set1); + + for (let val of set1.set) { + if (!member__qmark__$1(set2, val)) { + new_map.set = List.delete(new_map.set, val); + } + } + + return SpecialForms.map(new_map); +} + +function union$1(set1, set2) { + let new_map = set1; + + for (let val of set2.set) { + new_map = put$2(new_map, val); + } + + return SpecialForms.map(new_map); +} + +function disjoin__qmark__$1(set1, set2) { + for (let val of set1.set) { + if (member__qmark__$1(set2, val)) { + return false; + } + } + + return true; +} + +function member__qmark__$1(set, value) { + return set.set.indexOf(value) >= 0; +} + +function equal__qmark__$2(set1, set2) { + return set1.set === set2.set; +} + +function subset__qmark__$1(set1, set2) { + for (let val of set1.set) { + if (!member__qmark__$1(set2, val)) { + return false; + } + } + + return true; +} + +var MapSet = { + new: __new__$1, + size: size$2, + to_list: to_list$3, + disjoin__qmark__: disjoin__qmark__$1, + delete: __delete__$2, + subset__qmark__: subset__qmark__$1, + equal__qmark__: equal__qmark__$2, + member__qmark__: member__qmark__$1, + put: put$2, + union: union$1, + intersection: intersection$1, + difference: difference$1 +}; + +function size$1(map) { + return MapSet.size(map); +} + +function to_list$2(map) { + return MapSet.to_list(map); +} + +function __delete__$1(set, term) { + return MapSet.delete(set, term); +} + +function put$1(set, term) { + return MapSet.put(set, term); +} + +function difference(set1, set2) { + return MapSet.difference(set1, set2); +} + +function intersection(set1, set2) { + return MapSet.intersection(set1, set2); +} + +function union(set1, set2) { + return MapSet.union(set1, set2); +} + +function disjoin__qmark__(set1, set2) { + return MapSet.disjoin__qmark__(set1, set2); +} + +function member__qmark__(set, value) { + return MapSet.member__qmark__(set1, set2); +} + +function equal__qmark__$1(set1, set2) { + return MapSet.equal__qmark__(set1, set2); +} + +function subset__qmark__(set1, set2) { + return MapSet.subset__qmark__(set1, set2); +} + +var set = { + size: size$1, + to_list: to_list$2, + disjoin__qmark__, + delete: __delete__$1, + subset__qmark__, + equal__qmark__: equal__qmark__$1, + member__qmark__, + put: put$1, + union, + intersection, + difference +}; + +let VirtualDOM = (function (e) { + return e(); +})(function () { + var define, module, exports; + return (function e(t, n, r) { + function s(o, u) { + if (!n[o]) { + if (!t[o]) { + var a = typeof require == "function" && require; + if (!u && a) return a(o, !0); + if (i) return i(o, !0); + var f = new Error("Cannot find module '" + o + "'"); + throw (f.code = "MODULE_NOT_FOUND", f); + } + var l = n[o] = { + exports: {} + }; + t[o][0].call(l.exports, function (e) { + var n = t[o][1][e]; + return s(n ? n : e); + }, l, l.exports, e, t, n, r); + } + return n[o].exports; + } + var i = typeof require == "function" && require; + for (var o = 0; o < r.length; o++) s(r[o]); + return s; + })({ + 1: [function (require, module, exports) { + + var createElement = require("./vdom/create-element.js"); + + module.exports = createElement; + }, { "./vdom/create-element.js": 15 }], 2: [function (require, module, exports) { + var diff = require("./vtree/diff.js"); + + module.exports = diff; + }, { "./vtree/diff.js": 35 }], 3: [function (require, module, exports) { + var h = require("./virtual-hyperscript/index.js"); + + module.exports = h; + }, { "./virtual-hyperscript/index.js": 22 }], 4: [function (require, module, exports) { + var diff = require("./diff.js"); + var patch = require("./patch.js"); + var h = require("./h.js"); + var create = require("./create-element.js"); + var VNode = require("./vnode/vnode.js"); + var VText = require("./vnode/vtext.js"); + + module.exports = { + diff: diff, + patch: patch, + h: h, + create: create, + VNode: VNode, + VText: VText + }; + }, { "./create-element.js": 1, "./diff.js": 2, "./h.js": 3, "./patch.js": 13, "./vnode/vnode.js": 31, "./vnode/vtext.js": 33 }], 5: [function (require, module, exports) { + /*! + * Cross-Browser Split 1.1.1 + * Copyright 2007-2012 Steven Levithan + * Available under the MIT License + * ECMAScript compliant, uniform cross-browser split method + */ + + /** + * Splits a string into an array of strings using a regex or string separator. Matches of the + * separator are not included in the result array. However, if `separator` is a regex that contains + * capturing groups, backreferences are spliced into the result each time `separator` is matched. + * Fixes browser bugs compared to the native `String.prototype.split` and can be used reliably + * cross-browser. + * @param {String} str String to split. + * @param {RegExp|String} separator Regex or string to use for separating the string. + * @param {Number} [limit] Maximum number of items to include in the result array. + * @returns {Array} Array of substrings. + * @example + * + * // Basic use + * split('a b c d', ' '); + * // -> ['a', 'b', 'c', 'd'] + * + * // With limit + * split('a b c d', ' ', 2); + * // -> ['a', 'b'] + * + * // Backreferences in result array + * split('..word1 word2..', /([a-z]+)(\d+)/i); + * // -> ['..', 'word', '1', ' ', 'word', '2', '..'] + */ + module.exports = (function split(undef) { + + var nativeSplit = String.prototype.split, + compliantExecNpcg = /()??/.exec("")[1] === undef, + + // NPCG: nonparticipating capturing group + self; + + self = function (str, separator, limit) { + // If `separator` is not a regex, use `nativeSplit` + if (Object.prototype.toString.call(separator) !== "[object RegExp]") { + return nativeSplit.call(str, separator, limit); + } + var output = [], + flags = (separator.ignoreCase ? "i" : "") + (separator.multiline ? "m" : "") + (separator.extended ? "x" : "") + (separator.sticky ? "y" : ""), + + // Firefox 3+ + lastLastIndex = 0, + + // Make `global` and avoid `lastIndex` issues by working with a copy + separator = new RegExp(separator.source, flags + "g"), + separator2, + match, + lastIndex, + lastLength; + str += ""; // Type-convert + if (!compliantExecNpcg) { + // Doesn't need flags gy, but they don't hurt + separator2 = new RegExp("^" + separator.source + "$(?!\\s)", flags); + } + /* Values for `limit`, per the spec: + * If undefined: 4294967295 // Math.pow(2, 32) - 1 + * If 0, Infinity, or NaN: 0 + * If positive number: limit = Math.floor(limit); if (limit > 4294967295) limit -= 4294967296; + * If negative number: 4294967296 - Math.floor(Math.abs(limit)) + * If other: Type-convert, then use the above rules + */ + limit = limit === undef ? -1 >>> 0 : // Math.pow(2, 32) - 1 + limit >>> 0; // ToUint32(limit) + while (match = separator.exec(str)) { + // `separator.lastIndex` is not reliable cross-browser + lastIndex = match.index + match[0].length; + if (lastIndex > lastLastIndex) { + output.push(str.slice(lastLastIndex, match.index)); + // Fix browsers whose `exec` methods don't consistently return `undefined` for + // nonparticipating capturing groups + if (!compliantExecNpcg && match.length > 1) { + match[0].replace(separator2, function () { + for (var i = 1; i < arguments.length - 2; i++) { + if (arguments[i] === undef) { + match[i] = undef; + } + } + }); + } + if (match.length > 1 && match.index < str.length) { + Array.prototype.push.apply(output, match.slice(1)); + } + lastLength = match[0].length; + lastLastIndex = lastIndex; + if (output.length >= limit) { + break; + } + } + if (separator.lastIndex === match.index) { + separator.lastIndex++; // Avoid an infinite loop + } + } + if (lastLastIndex === str.length) { + if (lastLength || !separator.test("")) { + output.push(""); + } + } else { + output.push(str.slice(lastLastIndex)); + } + return output.length > limit ? output.slice(0, limit) : output; + }; + + return self; + })(); + }, {}], 6: [function (require, module, exports) {}, {}], 7: [function (require, module, exports) { + "use strict"; + + var OneVersionConstraint = require("individual/one-version"); + + var MY_VERSION = "7"; + OneVersionConstraint("ev-store", MY_VERSION); + + var hashKey = "__EV_STORE_KEY@" + MY_VERSION; + + module.exports = EvStore; + + function EvStore(elem) { + var hash = elem[hashKey]; + + if (!hash) { + hash = elem[hashKey] = {}; + } + + return hash; + } + }, { "individual/one-version": 9 }], 8: [function (require, module, exports) { + (function (global) { + "use strict"; + + /*global window, global*/ + + var root = typeof window !== "undefined" ? window : typeof global !== "undefined" ? global : {}; + + module.exports = Individual; + + function Individual(key, value) { + if (key in root) { + return root[key]; + } + + root[key] = value; + + return value; + } + }).call(this, typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}); + }, {}], 9: [function (require, module, exports) { + "use strict"; + + var Individual = require("./index.js"); + + module.exports = OneVersion; + + function OneVersion(moduleName, version, defaultValue) { + var key = "__INDIVIDUAL_ONE_VERSION_" + moduleName; + var enforceKey = key + "_ENFORCE_SINGLETON"; + + var versionValue = Individual(enforceKey, version); + + if (versionValue !== version) { + throw new Error("Can only have one copy of " + moduleName + ".\n" + "You already have version " + versionValue + " installed.\n" + "This means you cannot install version " + version); + } + + return Individual(key, defaultValue); + } + }, { "./index.js": 8 }], 10: [function (require, module, exports) { + (function (global) { + var topLevel = typeof global !== "undefined" ? global : typeof window !== "undefined" ? window : {}; + var minDoc = require("min-document"); + + if (typeof document !== "undefined") { + module.exports = document; + } else { + var doccy = topLevel["__GLOBAL_DOCUMENT_CACHE@4"]; + + if (!doccy) { + doccy = topLevel["__GLOBAL_DOCUMENT_CACHE@4"] = minDoc; + } + + module.exports = doccy; + } + }).call(this, typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}); + }, { "min-document": 6 }], 11: [function (require, module, exports) { + "use strict"; + + module.exports = function isObject(x) { + return typeof x === "object" && x !== null; + }; + }, {}], 12: [function (require, module, exports) { + var nativeIsArray = Array.isArray; + var toString = Object.prototype.toString; + + module.exports = nativeIsArray || isArray; + + function isArray(obj) { + return toString.call(obj) === "[object Array]"; + } + }, {}], 13: [function (require, module, exports) { + var patch = require("./vdom/patch.js"); + + module.exports = patch; + }, { "./vdom/patch.js": 18 }], 14: [function (require, module, exports) { + var isObject = require("is-object"); + var isHook = require("../vnode/is-vhook.js"); + + module.exports = applyProperties; + + function applyProperties(node, props, previous) { + for (var propName in props) { + var propValue = props[propName]; + + if (propValue === undefined) { + removeProperty(node, propName, propValue, previous); + } else if (isHook(propValue)) { + removeProperty(node, propName, propValue, previous); + if (propValue.hook) { + propValue.hook(node, propName, previous ? previous[propName] : undefined); + } + } else { + if (isObject(propValue)) { + patchObject(node, props, previous, propName, propValue); + } else { + node[propName] = propValue; + } + } + } + } + + function removeProperty(node, propName, propValue, previous) { + if (previous) { + var previousValue = previous[propName]; + + if (!isHook(previousValue)) { + if (propName === "attributes") { + for (var attrName in previousValue) { + node.removeAttribute(attrName); + } + } else if (propName === "style") { + for (var i in previousValue) { + node.style[i] = ""; + } + } else if (typeof previousValue === "string") { + node[propName] = ""; + } else { + node[propName] = null; + } + } else if (previousValue.unhook) { + previousValue.unhook(node, propName, propValue); + } + } + } + + function patchObject(node, props, previous, propName, propValue) { + var previousValue = previous ? previous[propName] : undefined; + + // Set attributes + if (propName === "attributes") { + for (var attrName in propValue) { + var attrValue = propValue[attrName]; + + if (attrValue === undefined) { + node.removeAttribute(attrName); + } else { + node.setAttribute(attrName, attrValue); + } + } + + return; + } + + if (previousValue && isObject(previousValue) && getPrototype(previousValue) !== getPrototype(propValue)) { + node[propName] = propValue; + return; + } + + if (!isObject(node[propName])) { + node[propName] = {}; + } + + var replacer = propName === "style" ? "" : undefined; + + for (var k in propValue) { + var value = propValue[k]; + node[propName][k] = value === undefined ? replacer : value; + } + } + + function getPrototype(value) { + if (Object.getPrototypeOf) { + return Object.getPrototypeOf(value); + } else if (value.__proto__) { + return value.__proto__; + } else if (value.constructor) { + return value.constructor.prototype; + } + } + }, { "../vnode/is-vhook.js": 26, "is-object": 11 }], 15: [function (require, module, exports) { + var document = require("global/document"); + + var applyProperties = require("./apply-properties"); + + var isVNode = require("../vnode/is-vnode.js"); + var isVText = require("../vnode/is-vtext.js"); + var isWidget = require("../vnode/is-widget.js"); + var handleThunk = require("../vnode/handle-thunk.js"); + + module.exports = createElement; + + function createElement(vnode, opts) { + var doc = opts ? opts.document || document : document; + var warn = opts ? opts.warn : null; + + vnode = handleThunk(vnode).a; + + if (isWidget(vnode)) { + return vnode.init(); + } else if (isVText(vnode)) { + return doc.createTextNode(vnode.text); + } else if (!isVNode(vnode)) { + if (warn) { + warn("Item is not a valid virtual dom node", vnode); + } + return null; + } + + var node = vnode.namespace === null ? doc.createElement(vnode.tagName) : doc.createElementNS(vnode.namespace, vnode.tagName); + + var props = vnode.properties; + applyProperties(node, props); + + var children = vnode.children; + + for (var i = 0; i < children.length; i++) { + var childNode = createElement(children[i], opts); + if (childNode) { + node.appendChild(childNode); + } + } + + return node; + } + }, { "../vnode/handle-thunk.js": 24, "../vnode/is-vnode.js": 27, "../vnode/is-vtext.js": 28, "../vnode/is-widget.js": 29, "./apply-properties": 14, "global/document": 10 }], 16: [function (require, module, exports) { + // Maps a virtual DOM tree onto a real DOM tree in an efficient manner. + // We don't want to read all of the DOM nodes in the tree so we use + // the in-order tree indexing to eliminate recursion down certain branches. + // We only recurse into a DOM node if we know that it contains a child of + // interest. + + var noChild = {}; + + module.exports = domIndex; + + function domIndex(rootNode, tree, indices, nodes) { + if (!indices || indices.length === 0) { + return {}; + } else { + indices.sort(ascending); + return recurse(rootNode, tree, indices, nodes, 0); + } + } + + function recurse(rootNode, tree, indices, nodes, rootIndex) { + nodes = nodes || {}; + + if (rootNode) { + if (indexInRange(indices, rootIndex, rootIndex)) { + nodes[rootIndex] = rootNode; + } + + var vChildren = tree.children; + + if (vChildren) { + + var childNodes = rootNode.childNodes; + + for (var i = 0; i < tree.children.length; i++) { + rootIndex += 1; + + var vChild = vChildren[i] || noChild; + var nextIndex = rootIndex + (vChild.count || 0); + + // skip recursion down the tree if there are no nodes down here + if (indexInRange(indices, rootIndex, nextIndex)) { + recurse(childNodes[i], vChild, indices, nodes, rootIndex); + } + + rootIndex = nextIndex; + } + } + } + + return nodes; + } + + // Binary search for an index in the interval [left, right] + function indexInRange(indices, left, right) { + if (indices.length === 0) { + return false; + } + + var minIndex = 0; + var maxIndex = indices.length - 1; + var currentIndex; + var currentItem; + + while (minIndex <= maxIndex) { + currentIndex = (maxIndex + minIndex) / 2 >> 0; + currentItem = indices[currentIndex]; + + if (minIndex === maxIndex) { + return currentItem >= left && currentItem <= right; + } else if (currentItem < left) { + minIndex = currentIndex + 1; + } else if (currentItem > right) { + maxIndex = currentIndex - 1; + } else { + return true; + } + } + + return false; + } + + function ascending(a, b) { + return a > b ? 1 : -1; + } + }, {}], 17: [function (require, module, exports) { + var applyProperties = require("./apply-properties"); + + var isWidget = require("../vnode/is-widget.js"); + var VPatch = require("../vnode/vpatch.js"); + + var updateWidget = require("./update-widget"); + + module.exports = applyPatch; + + function applyPatch(vpatch, domNode, renderOptions) { + var type = vpatch.type; + var vNode = vpatch.vNode; + var patch = vpatch.patch; + + switch (type) { + case VPatch.REMOVE: + return removeNode(domNode, vNode); + case VPatch.INSERT: + return insertNode(domNode, patch, renderOptions); + case VPatch.VTEXT: + return stringPatch(domNode, vNode, patch, renderOptions); + case VPatch.WIDGET: + return widgetPatch(domNode, vNode, patch, renderOptions); + case VPatch.VNODE: + return vNodePatch(domNode, vNode, patch, renderOptions); + case VPatch.ORDER: + reorderChildren(domNode, patch); + return domNode; + case VPatch.PROPS: + applyProperties(domNode, patch, vNode.properties); + return domNode; + case VPatch.THUNK: + return replaceRoot(domNode, renderOptions.patch(domNode, patch, renderOptions)); + default: + return domNode; + } + } + + function removeNode(domNode, vNode) { + var parentNode = domNode.parentNode; + + if (parentNode) { + parentNode.removeChild(domNode); + } + + destroyWidget(domNode, vNode); + + return null; + } + + function insertNode(parentNode, vNode, renderOptions) { + var newNode = renderOptions.render(vNode, renderOptions); + + if (parentNode) { + parentNode.appendChild(newNode); + } + + return parentNode; + } + + function stringPatch(domNode, leftVNode, vText, renderOptions) { + var newNode; + + if (domNode.nodeType === 3) { + domNode.replaceData(0, domNode.length, vText.text); + newNode = domNode; + } else { + var parentNode = domNode.parentNode; + newNode = renderOptions.render(vText, renderOptions); + + if (parentNode && newNode !== domNode) { + parentNode.replaceChild(newNode, domNode); + } + } + + return newNode; + } + + function widgetPatch(domNode, leftVNode, widget, renderOptions) { + var updating = updateWidget(leftVNode, widget); + var newNode; + + if (updating) { + newNode = widget.update(leftVNode, domNode) || domNode; + } else { + newNode = renderOptions.render(widget, renderOptions); + } + + var parentNode = domNode.parentNode; + + if (parentNode && newNode !== domNode) { + parentNode.replaceChild(newNode, domNode); + } + + if (!updating) { + destroyWidget(domNode, leftVNode); + } + + return newNode; + } + + function vNodePatch(domNode, leftVNode, vNode, renderOptions) { + var parentNode = domNode.parentNode; + var newNode = renderOptions.render(vNode, renderOptions); + + if (parentNode && newNode !== domNode) { + parentNode.replaceChild(newNode, domNode); + } + + return newNode; + } + + function destroyWidget(domNode, w) { + if (typeof w.destroy === "function" && isWidget(w)) { + w.destroy(domNode); + } + } + + function reorderChildren(domNode, moves) { + var childNodes = domNode.childNodes; + var keyMap = {}; + var node; + var remove; + var insert; + + for (var i = 0; i < moves.removes.length; i++) { + remove = moves.removes[i]; + node = childNodes[remove.from]; + if (remove.key) { + keyMap[remove.key] = node; + } + domNode.removeChild(node); + } + + var length = childNodes.length; + for (var j = 0; j < moves.inserts.length; j++) { + insert = moves.inserts[j]; + node = keyMap[insert.key]; + // this is the weirdest bug i've ever seen in webkit + domNode.insertBefore(node, insert.to >= length++ ? null : childNodes[insert.to]); + } + } + + function replaceRoot(oldRoot, newRoot) { + if (oldRoot && newRoot && oldRoot !== newRoot && oldRoot.parentNode) { + oldRoot.parentNode.replaceChild(newRoot, oldRoot); + } + + return newRoot; + } + }, { "../vnode/is-widget.js": 29, "../vnode/vpatch.js": 32, "./apply-properties": 14, "./update-widget": 19 }], 18: [function (require, module, exports) { + var document = require("global/document"); + var isArray = require("x-is-array"); + + var render = require("./create-element"); + var domIndex = require("./dom-index"); + var patchOp = require("./patch-op"); + module.exports = patch; + + function patch(rootNode, patches, renderOptions) { + renderOptions = renderOptions || {}; + renderOptions.patch = renderOptions.patch && renderOptions.patch !== patch ? renderOptions.patch : patchRecursive; + renderOptions.render = renderOptions.render || render; + + return renderOptions.patch(rootNode, patches, renderOptions); + } + + function patchRecursive(rootNode, patches, renderOptions) { + var indices = patchIndices(patches); + + if (indices.length === 0) { + return rootNode; + } + + var index = domIndex(rootNode, patches.a, indices); + var ownerDocument = rootNode.ownerDocument; + + if (!renderOptions.document && ownerDocument !== document) { + renderOptions.document = ownerDocument; + } + + for (var i = 0; i < indices.length; i++) { + var nodeIndex = indices[i]; + rootNode = applyPatch(rootNode, index[nodeIndex], patches[nodeIndex], renderOptions); + } + + return rootNode; + } + + function applyPatch(rootNode, domNode, patchList, renderOptions) { + if (!domNode) { + return rootNode; + } + + var newNode; + + if (isArray(patchList)) { + for (var i = 0; i < patchList.length; i++) { + newNode = patchOp(patchList[i], domNode, renderOptions); + + if (domNode === rootNode) { + rootNode = newNode; + } + } + } else { + newNode = patchOp(patchList, domNode, renderOptions); + + if (domNode === rootNode) { + rootNode = newNode; + } + } + + return rootNode; + } + + function patchIndices(patches) { + var indices = []; + + for (var key in patches) { + if (key !== "a") { + indices.push(Number(key)); + } + } + + return indices; + } + }, { "./create-element": 15, "./dom-index": 16, "./patch-op": 17, "global/document": 10, "x-is-array": 12 }], 19: [function (require, module, exports) { + var isWidget = require("../vnode/is-widget.js"); + + module.exports = updateWidget; + + function updateWidget(a, b) { + if (isWidget(a) && isWidget(b)) { + if ("name" in a && "name" in b) { + return a.id === b.id; + } else { + return a.init === b.init; + } + } + + return false; + } + }, { "../vnode/is-widget.js": 29 }], 20: [function (require, module, exports) { + "use strict"; + + var EvStore = require("ev-store"); + + module.exports = EvHook; + + function EvHook(value) { + if (!(this instanceof EvHook)) { + return new EvHook(value); + } + + this.value = value; + } + + EvHook.prototype.hook = function (node, propertyName) { + var es = EvStore(node); + var propName = propertyName.substr(3); + + es[propName] = this.value; + }; + + EvHook.prototype.unhook = function (node, propertyName) { + var es = EvStore(node); + var propName = propertyName.substr(3); + + es[propName] = undefined; + }; + }, { "ev-store": 7 }], 21: [function (require, module, exports) { + "use strict"; + + module.exports = SoftSetHook; + + function SoftSetHook(value) { + if (!(this instanceof SoftSetHook)) { + return new SoftSetHook(value); + } + + this.value = value; + } + + SoftSetHook.prototype.hook = function (node, propertyName) { + if (node[propertyName] !== this.value) { + node[propertyName] = this.value; + } + }; + }, {}], 22: [function (require, module, exports) { + "use strict"; + + var isArray = require("x-is-array"); + + var VNode = require("../vnode/vnode.js"); + var VText = require("../vnode/vtext.js"); + var isVNode = require("../vnode/is-vnode"); + var isVText = require("../vnode/is-vtext"); + var isWidget = require("../vnode/is-widget"); + var isHook = require("../vnode/is-vhook"); + var isVThunk = require("../vnode/is-thunk"); + + var parseTag = require("./parse-tag.js"); + var softSetHook = require("./hooks/soft-set-hook.js"); + var evHook = require("./hooks/ev-hook.js"); + + module.exports = h; + + function h(tagName, properties, children) { + var childNodes = []; + var tag, props, key, namespace; + + if (!children && isChildren(properties)) { + children = properties; + props = {}; + } + + props = props || properties || {}; + tag = parseTag(tagName, props); + + // support keys + if (props.hasOwnProperty("key")) { + key = props.key; + props.key = undefined; + } + + // support namespace + if (props.hasOwnProperty("namespace")) { + namespace = props.namespace; + props.namespace = undefined; + } + + // fix cursor bug + if (tag === "INPUT" && !namespace && props.hasOwnProperty("value") && props.value !== undefined && !isHook(props.value)) { + props.value = softSetHook(props.value); + } + + transformProperties(props); + + if (children !== undefined && children !== null) { + addChild(children, childNodes, tag, props); + } + + return new VNode(tag, props, childNodes, key, namespace); + } + + function addChild(c, childNodes, tag, props) { + if (typeof c === "string") { + childNodes.push(new VText(c)); + } else if (typeof c === "number") { + childNodes.push(new VText(String(c))); + } else if (isChild(c)) { + childNodes.push(c); + } else if (isArray(c)) { + for (var i = 0; i < c.length; i++) { + addChild(c[i], childNodes, tag, props); + } + } else if (c === null || c === undefined) { + return; + } else { + throw UnexpectedVirtualElement({ + foreignObject: c, + parentVnode: { + tagName: tag, + properties: props + } + }); + } + } + + function transformProperties(props) { + for (var propName in props) { + if (props.hasOwnProperty(propName)) { + var value = props[propName]; + + if (isHook(value)) { + continue; + } + + if (propName.substr(0, 3) === "ev-") { + // add ev-foo support + props[propName] = evHook(value); + } + } + } + } + + function isChild(x) { + return isVNode(x) || isVText(x) || isWidget(x) || isVThunk(x); + } + + function isChildren(x) { + return typeof x === "string" || isArray(x) || isChild(x); + } + + function UnexpectedVirtualElement(data) { + var err = new Error(); + + err.type = "virtual-hyperscript.unexpected.virtual-element"; + err.message = "Unexpected virtual child passed to h().\n" + "Expected a VNode / Vthunk / VWidget / string but:\n" + "got:\n" + errorString(data.foreignObject) + ".\n" + "The parent vnode is:\n" + errorString(data.parentVnode); + "\n" + "Suggested fix: change your `h(..., [ ... ])` callsite."; + err.foreignObject = data.foreignObject; + err.parentVnode = data.parentVnode; + + return err; + } + + function errorString(obj) { + try { + return JSON.stringify(obj, null, " "); + } catch (e) { + return String(obj); + } + } + }, { "../vnode/is-thunk": 25, "../vnode/is-vhook": 26, "../vnode/is-vnode": 27, "../vnode/is-vtext": 28, "../vnode/is-widget": 29, "../vnode/vnode.js": 31, "../vnode/vtext.js": 33, "./hooks/ev-hook.js": 20, "./hooks/soft-set-hook.js": 21, "./parse-tag.js": 23, "x-is-array": 12 }], 23: [function (require, module, exports) { + "use strict"; + + var split = require("browser-split"); + + var classIdSplit = /([\.#]?[a-zA-Z0-9\u007F-\uFFFF_:-]+)/; + var notClassId = /^\.|#/; + + module.exports = parseTag; + + function parseTag(tag, props) { + if (!tag) { + return "DIV"; + } + + var noId = !props.hasOwnProperty("id"); + + var tagParts = split(tag, classIdSplit); + var tagName = null; + + if (notClassId.test(tagParts[1])) { + tagName = "DIV"; + } + + var classes, part, type, i; + + for (i = 0; i < tagParts.length; i++) { + part = tagParts[i]; + + if (!part) { + continue; + } + + type = part.charAt(0); + + if (!tagName) { + tagName = part; + } else if (type === ".") { + classes = classes || []; + classes.push(part.substring(1, part.length)); + } else if (type === "#" && noId) { + props.id = part.substring(1, part.length); + } + } + + if (classes) { + if (props.className) { + classes.push(props.className); + } + + props.className = classes.join(" "); + } + + return props.namespace ? tagName : tagName.toUpperCase(); + } + }, { "browser-split": 5 }], 24: [function (require, module, exports) { + var isVNode = require("./is-vnode"); + var isVText = require("./is-vtext"); + var isWidget = require("./is-widget"); + var isThunk = require("./is-thunk"); + + module.exports = handleThunk; + + function handleThunk(a, b) { + var renderedA = a; + var renderedB = b; + + if (isThunk(b)) { + renderedB = renderThunk(b, a); + } + + if (isThunk(a)) { + renderedA = renderThunk(a, null); + } + + return { + a: renderedA, + b: renderedB + }; + } + + function renderThunk(thunk, previous) { + var renderedThunk = thunk.vnode; + + if (!renderedThunk) { + renderedThunk = thunk.vnode = thunk.render(previous); + } + + if (!(isVNode(renderedThunk) || isVText(renderedThunk) || isWidget(renderedThunk))) { + throw new Error("thunk did not return a valid node"); + } + + return renderedThunk; + } + }, { "./is-thunk": 25, "./is-vnode": 27, "./is-vtext": 28, "./is-widget": 29 }], 25: [function (require, module, exports) { + module.exports = isThunk; + + function isThunk(t) { + return t && t.type === "Thunk"; + } + }, {}], 26: [function (require, module, exports) { + module.exports = isHook; + + function isHook(hook) { + return hook && (typeof hook.hook === "function" && !hook.hasOwnProperty("hook") || typeof hook.unhook === "function" && !hook.hasOwnProperty("unhook")); + } + }, {}], 27: [function (require, module, exports) { + var version = require("./version"); + + module.exports = isVirtualNode; + + function isVirtualNode(x) { + return x && x.type === "VirtualNode" && x.version === version; + } + }, { "./version": 30 }], 28: [function (require, module, exports) { + var version = require("./version"); + + module.exports = isVirtualText; + + function isVirtualText(x) { + return x && x.type === "VirtualText" && x.version === version; + } + }, { "./version": 30 }], 29: [function (require, module, exports) { + module.exports = isWidget; + + function isWidget(w) { + return w && w.type === "Widget"; + } + }, {}], 30: [function (require, module, exports) { + module.exports = "2"; + }, {}], 31: [function (require, module, exports) { + var version = require("./version"); + var isVNode = require("./is-vnode"); + var isWidget = require("./is-widget"); + var isThunk = require("./is-thunk"); + var isVHook = require("./is-vhook"); + + module.exports = VirtualNode; + + var noProperties = {}; + var noChildren = []; + + function VirtualNode(tagName, properties, children, key, namespace) { + this.tagName = tagName; + this.properties = properties || noProperties; + this.children = children || noChildren; + this.key = key != null ? String(key) : undefined; + this.namespace = typeof namespace === "string" ? namespace : null; + + var count = children && children.length || 0; + var descendants = 0; + var hasWidgets = false; + var hasThunks = false; + var descendantHooks = false; + var hooks; + + for (var propName in properties) { + if (properties.hasOwnProperty(propName)) { + var property = properties[propName]; + if (isVHook(property) && property.unhook) { + if (!hooks) { + hooks = {}; + } + + hooks[propName] = property; + } + } + } + + for (var i = 0; i < count; i++) { + var child = children[i]; + if (isVNode(child)) { + descendants += child.count || 0; + + if (!hasWidgets && child.hasWidgets) { + hasWidgets = true; + } + + if (!hasThunks && child.hasThunks) { + hasThunks = true; + } + + if (!descendantHooks && (child.hooks || child.descendantHooks)) { + descendantHooks = true; + } + } else if (!hasWidgets && isWidget(child)) { + if (typeof child.destroy === "function") { + hasWidgets = true; + } + } else if (!hasThunks && isThunk(child)) { + hasThunks = true; + } + } + + this.count = count + descendants; + this.hasWidgets = hasWidgets; + this.hasThunks = hasThunks; + this.hooks = hooks; + this.descendantHooks = descendantHooks; + } + + VirtualNode.prototype.version = version; + VirtualNode.prototype.type = "VirtualNode"; + }, { "./is-thunk": 25, "./is-vhook": 26, "./is-vnode": 27, "./is-widget": 29, "./version": 30 }], 32: [function (require, module, exports) { + var version = require("./version"); + + VirtualPatch.NONE = 0; + VirtualPatch.VTEXT = 1; + VirtualPatch.VNODE = 2; + VirtualPatch.WIDGET = 3; + VirtualPatch.PROPS = 4; + VirtualPatch.ORDER = 5; + VirtualPatch.INSERT = 6; + VirtualPatch.REMOVE = 7; + VirtualPatch.THUNK = 8; + + module.exports = VirtualPatch; + + function VirtualPatch(type, vNode, patch) { + this.type = Number(type); + this.vNode = vNode; + this.patch = patch; + } + + VirtualPatch.prototype.version = version; + VirtualPatch.prototype.type = "VirtualPatch"; + }, { "./version": 30 }], 33: [function (require, module, exports) { + var version = require("./version"); + + module.exports = VirtualText; + + function VirtualText(text) { + this.text = String(text); + } + + VirtualText.prototype.version = version; + VirtualText.prototype.type = "VirtualText"; + }, { "./version": 30 }], 34: [function (require, module, exports) { + var isObject = require("is-object"); + var isHook = require("../vnode/is-vhook"); + + module.exports = diffProps; + + function diffProps(a, b) { + var diff; + + for (var aKey in a) { + if (!(aKey in b)) { + diff = diff || {}; + diff[aKey] = undefined; + } + + var aValue = a[aKey]; + var bValue = b[aKey]; + + if (aValue === bValue) { + continue; + } else if (isObject(aValue) && isObject(bValue)) { + if (getPrototype(bValue) !== getPrototype(aValue)) { + diff = diff || {}; + diff[aKey] = bValue; + } else if (isHook(bValue)) { + diff = diff || {}; + diff[aKey] = bValue; + } else { + var objectDiff = diffProps(aValue, bValue); + if (objectDiff) { + diff = diff || {}; + diff[aKey] = objectDiff; + } + } + } else { + diff = diff || {}; + diff[aKey] = bValue; + } + } + + for (var bKey in b) { + if (!(bKey in a)) { + diff = diff || {}; + diff[bKey] = b[bKey]; + } + } + + return diff; + } + + function getPrototype(value) { + if (Object.getPrototypeOf) { + return Object.getPrototypeOf(value); + } else if (value.__proto__) { + return value.__proto__; + } else if (value.constructor) { + return value.constructor.prototype; + } + } + }, { "../vnode/is-vhook": 26, "is-object": 11 }], 35: [function (require, module, exports) { + var isArray = require("x-is-array"); + + var VPatch = require("../vnode/vpatch"); + var isVNode = require("../vnode/is-vnode"); + var isVText = require("../vnode/is-vtext"); + var isWidget = require("../vnode/is-widget"); + var isThunk = require("../vnode/is-thunk"); + var handleThunk = require("../vnode/handle-thunk"); + + var diffProps = require("./diff-props"); + + module.exports = diff; + + function diff(a, b) { + var patch = { a: a }; + walk(a, b, patch, 0); + return patch; + } + + function walk(a, b, patch, index) { + if (a === b) { + return; + } + + var apply = patch[index]; + var applyClear = false; + + if (isThunk(a) || isThunk(b)) { + thunks(a, b, patch, index); + } else if (b == null) { + + // If a is a widget we will add a remove patch for it + // Otherwise any child widgets/hooks must be destroyed. + // This prevents adding two remove patches for a widget. + if (!isWidget(a)) { + clearState(a, patch, index); + apply = patch[index]; + } + + apply = appendPatch(apply, new VPatch(VPatch.REMOVE, a, b)); + } else if (isVNode(b)) { + if (isVNode(a)) { + if (a.tagName === b.tagName && a.namespace === b.namespace && a.key === b.key) { + var propsPatch = diffProps(a.properties, b.properties); + if (propsPatch) { + apply = appendPatch(apply, new VPatch(VPatch.PROPS, a, propsPatch)); + } + apply = diffChildren(a, b, patch, apply, index); + } else { + apply = appendPatch(apply, new VPatch(VPatch.VNODE, a, b)); + applyClear = true; + } + } else { + apply = appendPatch(apply, new VPatch(VPatch.VNODE, a, b)); + applyClear = true; + } + } else if (isVText(b)) { + if (!isVText(a)) { + apply = appendPatch(apply, new VPatch(VPatch.VTEXT, a, b)); + applyClear = true; + } else if (a.text !== b.text) { + apply = appendPatch(apply, new VPatch(VPatch.VTEXT, a, b)); + } + } else if (isWidget(b)) { + if (!isWidget(a)) { + applyClear = true; + } + + apply = appendPatch(apply, new VPatch(VPatch.WIDGET, a, b)); + } + + if (apply) { + patch[index] = apply; + } + + if (applyClear) { + clearState(a, patch, index); + } + } + + function diffChildren(a, b, patch, apply, index) { + var aChildren = a.children; + var orderedSet = reorder(aChildren, b.children); + var bChildren = orderedSet.children; + + var aLen = aChildren.length; + var bLen = bChildren.length; + var len = aLen > bLen ? aLen : bLen; + + for (var i = 0; i < len; i++) { + var leftNode = aChildren[i]; + var rightNode = bChildren[i]; + index += 1; + + if (!leftNode) { + if (rightNode) { + // Excess nodes in b need to be added + apply = appendPatch(apply, new VPatch(VPatch.INSERT, null, rightNode)); + } + } else { + walk(leftNode, rightNode, patch, index); + } + + if (isVNode(leftNode) && leftNode.count) { + index += leftNode.count; + } + } + + if (orderedSet.moves) { + // Reorder nodes last + apply = appendPatch(apply, new VPatch(VPatch.ORDER, a, orderedSet.moves)); + } + + return apply; + } + + function clearState(vNode, patch, index) { + // TODO: Make this a single walk, not two + unhook(vNode, patch, index); + destroyWidgets(vNode, patch, index); + } + + // Patch records for all destroyed widgets must be added because we need + // a DOM node reference for the destroy function + function destroyWidgets(vNode, patch, index) { + if (isWidget(vNode)) { + if (typeof vNode.destroy === "function") { + patch[index] = appendPatch(patch[index], new VPatch(VPatch.REMOVE, vNode, null)); + } + } else if (isVNode(vNode) && (vNode.hasWidgets || vNode.hasThunks)) { + var children = vNode.children; + var len = children.length; + for (var i = 0; i < len; i++) { + var child = children[i]; + index += 1; + + destroyWidgets(child, patch, index); + + if (isVNode(child) && child.count) { + index += child.count; + } + } + } else if (isThunk(vNode)) { + thunks(vNode, null, patch, index); + } + } + + // Create a sub-patch for thunks + function thunks(a, b, patch, index) { + var nodes = handleThunk(a, b); + var thunkPatch = diff(nodes.a, nodes.b); + if (hasPatches(thunkPatch)) { + patch[index] = new VPatch(VPatch.THUNK, null, thunkPatch); + } + } + + function hasPatches(patch) { + for (var index in patch) { + if (index !== "a") { + return true; + } + } + + return false; + } + + // Execute hooks when two nodes are identical + function unhook(vNode, patch, index) { + if (isVNode(vNode)) { + if (vNode.hooks) { + patch[index] = appendPatch(patch[index], new VPatch(VPatch.PROPS, vNode, undefinedKeys(vNode.hooks))); + } + + if (vNode.descendantHooks || vNode.hasThunks) { + var children = vNode.children; + var len = children.length; + for (var i = 0; i < len; i++) { + var child = children[i]; + index += 1; + + unhook(child, patch, index); + + if (isVNode(child) && child.count) { + index += child.count; + } + } + } + } else if (isThunk(vNode)) { + thunks(vNode, null, patch, index); + } + } + + function undefinedKeys(obj) { + var result = {}; + + for (var key in obj) { + result[key] = undefined; + } + + return result; + } + + // List diff, naive left to right reordering + function reorder(aChildren, bChildren) { + // O(M) time, O(M) memory + var bChildIndex = keyIndex(bChildren); + var bKeys = bChildIndex.keys; + var bFree = bChildIndex.free; + + if (bFree.length === bChildren.length) { + return { + children: bChildren, + moves: null + }; + } + + // O(N) time, O(N) memory + var aChildIndex = keyIndex(aChildren); + var aKeys = aChildIndex.keys; + var aFree = aChildIndex.free; + + if (aFree.length === aChildren.length) { + return { + children: bChildren, + moves: null + }; + } + + // O(MAX(N, M)) memory + var newChildren = []; + + var freeIndex = 0; + var freeCount = bFree.length; + var deletedItems = 0; + + // Iterate through a and match a node in b + // O(N) time, + for (var i = 0; i < aChildren.length; i++) { + var aItem = aChildren[i]; + var itemIndex; + + if (aItem.key) { + if (bKeys.hasOwnProperty(aItem.key)) { + // Match up the old keys + itemIndex = bKeys[aItem.key]; + newChildren.push(bChildren[itemIndex]); + } else { + // Remove old keyed items + itemIndex = i - deletedItems++; + newChildren.push(null); + } + } else { + // Match the item in a with the next free item in b + if (freeIndex < freeCount) { + itemIndex = bFree[freeIndex++]; + newChildren.push(bChildren[itemIndex]); + } else { + // There are no free items in b to match with + // the free items in a, so the extra free nodes + // are deleted. + itemIndex = i - deletedItems++; + newChildren.push(null); + } + } + } + + var lastFreeIndex = freeIndex >= bFree.length ? bChildren.length : bFree[freeIndex]; + + // Iterate through b and append any new keys + // O(M) time + for (var j = 0; j < bChildren.length; j++) { + var newItem = bChildren[j]; + + if (newItem.key) { + if (!aKeys.hasOwnProperty(newItem.key)) { + // Add any new keyed items + // We are adding new items to the end and then sorting them + // in place. In future we should insert new items in place. + newChildren.push(newItem); + } + } else if (j >= lastFreeIndex) { + // Add any leftover non-keyed items + newChildren.push(newItem); + } + } + + var simulate = newChildren.slice(); + var simulateIndex = 0; + var removes = []; + var inserts = []; + var simulateItem; + + for (var k = 0; k < bChildren.length;) { + var wantedItem = bChildren[k]; + simulateItem = simulate[simulateIndex]; + + // remove items + while (simulateItem === null && simulate.length) { + removes.push(remove(simulate, simulateIndex, null)); + simulateItem = simulate[simulateIndex]; + } + + if (!simulateItem || simulateItem.key !== wantedItem.key) { + // if we need a key in this position... + if (wantedItem.key) { + if (simulateItem && simulateItem.key) { + // if an insert doesn't put this key in place, it needs to move + if (bKeys[simulateItem.key] !== k + 1) { + removes.push(remove(simulate, simulateIndex, simulateItem.key)); + simulateItem = simulate[simulateIndex]; + // if the remove didn't put the wanted item in place, we need to insert it + if (!simulateItem || simulateItem.key !== wantedItem.key) { + inserts.push({ key: wantedItem.key, to: k }); + } + // items are matching, so skip ahead + else { + simulateIndex++; + } + } else { + inserts.push({ key: wantedItem.key, to: k }); + } + } else { + inserts.push({ key: wantedItem.key, to: k }); + } + k++; + } + // a key in simulate has no matching wanted key, remove it + else if (simulateItem && simulateItem.key) { + removes.push(remove(simulate, simulateIndex, simulateItem.key)); + } + } else { + simulateIndex++; + k++; + } + } + + // remove all the remaining nodes from simulate + while (simulateIndex < simulate.length) { + simulateItem = simulate[simulateIndex]; + removes.push(remove(simulate, simulateIndex, simulateItem && simulateItem.key)); + } + + // If the only moves we have are deletes then we can just + // let the delete patch remove these items. + if (removes.length === deletedItems && !inserts.length) { + return { + children: newChildren, + moves: null + }; + } + + return { + children: newChildren, + moves: { + removes: removes, + inserts: inserts + } + }; + } + + function remove(arr, index, key) { + arr.splice(index, 1); + + return { + from: index, + key: key + }; + } + + function keyIndex(children) { + var keys = {}; + var free = []; + var length = children.length; + + for (var i = 0; i < length; i++) { + var child = children[i]; + + if (child.key) { + keys[child.key] = i; + } else { + free.push(i); + } + } + + return { + keys: keys, // A hash of key name to index + free: free // An array of unkeyed item indices + }; + } + + function appendPatch(apply, patch) { + if (apply) { + if (isArray(apply)) { + apply.push(patch); + } else { + apply = [apply, patch]; + } + + return apply; + } else { + return patch; + } + } + }, { "../vnode/handle-thunk": 24, "../vnode/is-thunk": 25, "../vnode/is-vnode": 27, "../vnode/is-vtext": 28, "../vnode/is-widget": 29, "../vnode/vpatch": 32, "./diff-props": 34, "x-is-array": 12 }] }, {}, [4])(4); +}); + +const start = function (domRoot, renderFn, initialState, options = []) { + let pid = self.processes.spawn(); + + if (Keyword.has_key__qm__(options, Kernel.SpecialForms.atom('name'))) { + pid = self.processes.register(Keyword.get(options, Kernel.SpecialForms.atom('name')), pid); + } + + const tree = renderFn.apply(this, initialState); + const rootNode = VirtualDOM.create(tree); + + domRoot.appendChild(rootNode); + + self.processes.put(pid, 'state', Kernel.SpecialForms.tuple(rootNode, tree, renderFn)); + return Kernel.SpecialForms.tuple(Kernel.SpecialForms.atom('ok'), pid); +}; + +const stop = function (agent, timeout = 5000) { + self.processes.exit(agent); + return Kernel.SpecialForms.atom('ok'); +}; + +const render = function (agent, state) { + + const current_state = self.processes.get(agent, 'state'); + + let rootNode = Kernel.elem(current_state, 0); + let tree = Kernel.elem(current_state, 1); + let renderFn = Kernel.elem(current_state, 2); + + let newTree = renderFn.apply(this, state); + + let patches = VirtualDOM.diff(tree, newTree); + rootNode = VirtualDOM.patch(rootNode, patches); + + self.processes.put(agent, 'state', Kernel.SpecialForms.tuple(rootNode, newTree, renderFn)); + + return Kernel.SpecialForms.atom('ok'); +}; + +var view = { + start, + stop, + render +}; + +self.processes = self.processes || new ProcessSystem(); + +const Core = C; + +export { Core, Kernel, Atom, Enum, Integer, List, Range, Tuple, Agent, Keyword, base as Base, String$1 as String, bitwise as Bitwise, Enumerable, Collectable, Inspect, map as Map, set as Set, MapSet, VirtualDOM, view as View }; +//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiIiwic291cmNlcyI6WyJFbGl4aXIuanMiXSwic291cmNlc0NvbnRlbnQiOlsiZnVuY3Rpb24gY2FsbF9wcm9wZXJ0eShpdGVtLCBwcm9wZXJ0eSkge1xuICBpZiAocHJvcGVydHkgaW4gaXRlbSkge1xuICAgIGl0ZW1bcHJvcGVydHldO1xuICAgIGlmIChpdGVtW3Byb3BlcnR5XSBpbnN0YW5jZW9mIEZ1bmN0aW9uKSB7XG4gICAgICByZXR1cm4gaXRlbVtwcm9wZXJ0eV0oKTtcbiAgICB9IGVsc2Uge1xuICAgICAgcmV0dXJuIGl0ZW1bcHJvcGVydHldO1xuICAgIH1cbiAgfSBlbHNlIGlmIChTeW1ib2wuZm9yKHByb3BlcnR5KSBpbiBpdGVtKSB7XG4gICAgbGV0IHByb3AgPSBTeW1ib2wuZm9yKHByb3BlcnR5KTtcbiAgICBpZiAoaXRlbVtwcm9wXSBpbnN0YW5jZW9mIEZ1bmN0aW9uKSB7XG4gICAgICByZXR1cm4gaXRlbVtwcm9wXSgpO1xuICAgIH0gZWxzZSB7XG4gICAgICByZXR1cm4gaXRlbVtwcm9wXTtcbiAgICB9XG4gIH1cblxuICB0aHJvdyBuZXcgRXJyb3IoYFByb3BlcnR5ICR7IHByb3BlcnR5IH0gbm90IGZvdW5kIGluICR7IGl0ZW0gfWApO1xufVxuXG5jbGFzcyBUdXBsZSQxIHtcblxuICBjb25zdHJ1Y3RvciguLi5hcmdzKSB7XG4gICAgdGhpcy52YWx1ZXMgPSBPYmplY3QuZnJlZXplKGFyZ3MpO1xuICB9XG5cbiAgZ2V0KGluZGV4KSB7XG4gICAgcmV0dXJuIHRoaXMudmFsdWVzW2luZGV4XTtcbiAgfVxuXG4gIGNvdW50KCkge1xuICAgIHJldHVybiB0aGlzLnZhbHVlcy5sZW5ndGg7XG4gIH1cblxuICBbU3ltYm9sLml0ZXJhdG9yXSgpIHtcbiAgICByZXR1cm4gdGhpcy52YWx1ZXNbU3ltYm9sLml0ZXJhdG9yXSgpO1xuICB9XG5cbiAgdG9TdHJpbmcoKSB7XG4gICAgdmFyIGksXG4gICAgICAgIHMgPSBcIlwiO1xuICAgIGZvciAoaSA9IDA7IGkgPCB0aGlzLnZhbHVlcy5sZW5ndGg7IGkrKykge1xuICAgICAgaWYgKHMgIT09IFwiXCIpIHtcbiAgICAgICAgcyArPSBcIiwgXCI7XG4gICAgICB9XG4gICAgICBzICs9IHRoaXMudmFsdWVzW2ldLnRvU3RyaW5nKCk7XG4gICAgfVxuXG4gICAgcmV0dXJuIFwie1wiICsgcyArIFwifVwiO1xuICB9XG5cbn1cblxubGV0IHByb2Nlc3NfY291bnRlciA9IC0xO1xuXG5jbGFzcyBQSUQge1xuICBjb25zdHJ1Y3RvcigpIHtcbiAgICBwcm9jZXNzX2NvdW50ZXIgPSBwcm9jZXNzX2NvdW50ZXIgKyAxO1xuICAgIHRoaXMuaWQgPSBwcm9jZXNzX2NvdW50ZXI7XG4gIH1cblxuICB0b1N0cmluZygpIHtcbiAgICByZXR1cm4gXCJQSUQjPDAuXCIgKyB0aGlzLmlkICsgXCIuMD5cIjtcbiAgfVxufVxuXG5jbGFzcyBJbnRlZ2VyJDEge31cbmNsYXNzIEZsb2F0IHt9XG5cbi8qIEBmbG93ICovXG5cbmNsYXNzIFZhcmlhYmxlIHtcblxuICBjb25zdHJ1Y3RvcihuYW1lID0gbnVsbCkge1xuICAgIHRoaXMubmFtZSA9IG5hbWU7XG4gIH1cbn1cblxuY2xhc3MgV2lsZGNhcmQge1xuICBjb25zdHJ1Y3RvcigpIHt9XG59XG5cbmNsYXNzIFN0YXJ0c1dpdGgge1xuXG4gIGNvbnN0cnVjdG9yKHByZWZpeCkge1xuICAgIHRoaXMucHJlZml4ID0gcHJlZml4O1xuICB9XG59XG5cbmNsYXNzIENhcHR1cmUge1xuXG4gIGNvbnN0cnVjdG9yKHZhbHVlKSB7XG4gICAgdGhpcy52YWx1ZSA9IHZhbHVlO1xuICB9XG59XG5cbmNsYXNzIEhlYWRUYWlsIHtcbiAgY29uc3RydWN0b3IoKSB7fVxufVxuXG5jbGFzcyBUeXBlIHtcblxuICBjb25zdHJ1Y3Rvcih0eXBlLCBvYmpQYXR0ZXJuID0ge30pIHtcbiAgICB0aGlzLnR5cGUgPSB0eXBlO1xuICAgIHRoaXMub2JqUGF0dGVybiA9IG9ialBhdHRlcm47XG4gIH1cbn1cblxuY2xhc3MgQm91bmQge1xuXG4gIGNvbnN0cnVjdG9yKHZhbHVlKSB7XG4gICAgdGhpcy52YWx1ZSA9IHZhbHVlO1xuICB9XG59XG5cbmZ1bmN0aW9uIHZhcmlhYmxlKG5hbWUgPSBudWxsKSB7XG4gIHJldHVybiBuZXcgVmFyaWFibGUobmFtZSk7XG59XG5cbmZ1bmN0aW9uIHdpbGRjYXJkKCkge1xuICByZXR1cm4gbmV3IFdpbGRjYXJkKCk7XG59XG5cbmZ1bmN0aW9uIHN0YXJ0c1dpdGgocHJlZml4KSB7XG4gIHJldHVybiBuZXcgU3RhcnRzV2l0aChwcmVmaXgpO1xufVxuXG5mdW5jdGlvbiBjYXB0dXJlKHZhbHVlKSB7XG4gIHJldHVybiBuZXcgQ2FwdHVyZSh2YWx1ZSk7XG59XG5cbmZ1bmN0aW9uIGhlYWRUYWlsKCkge1xuICByZXR1cm4gbmV3IEhlYWRUYWlsKCk7XG59XG5cbmZ1bmN0aW9uIHR5cGUodHlwZSwgb2JqUGF0dGVybiA9IHt9KSB7XG4gIHJldHVybiBuZXcgVHlwZSh0eXBlLCBvYmpQYXR0ZXJuKTtcbn1cblxuZnVuY3Rpb24gYm91bmQodmFsdWUpIHtcbiAgcmV0dXJuIG5ldyBCb3VuZCh2YWx1ZSk7XG59XG5cbmZ1bmN0aW9uIGlzX251bWJlciQxKHZhbHVlKSB7XG4gIHJldHVybiB0eXBlb2YgdmFsdWUgPT09ICdudW1iZXInO1xufVxuXG5mdW5jdGlvbiBpc19zdHJpbmcodmFsdWUpIHtcbiAgcmV0dXJuIHR5cGVvZiB2YWx1ZSA9PT0gJ3N0cmluZyc7XG59XG5cbmZ1bmN0aW9uIGlzX2Jvb2xlYW4kMSh2YWx1ZSkge1xuICByZXR1cm4gdHlwZW9mIHZhbHVlID09PSAnYm9vbGVhbic7XG59XG5cbmZ1bmN0aW9uIGlzX3N5bWJvbCh2YWx1ZSkge1xuICByZXR1cm4gdHlwZW9mIHZhbHVlID09PSAnc3ltYm9sJztcbn1cblxuZnVuY3Rpb24gaXNfbnVsbCh2YWx1ZSkge1xuICByZXR1cm4gdmFsdWUgPT09IG51bGw7XG59XG5cbmZ1bmN0aW9uIGlzX3VuZGVmaW5lZCh2YWx1ZSkge1xuICByZXR1cm4gdHlwZW9mIHZhbHVlID09PSAndW5kZWZpbmVkJztcbn1cblxuZnVuY3Rpb24gaXNfZnVuY3Rpb24kMSh2YWx1ZSkge1xuICByZXR1cm4gT2JqZWN0LnByb3RvdHlwZS50b1N0cmluZy5jYWxsKHZhbHVlKSA9PSAnW29iamVjdCBGdW5jdGlvbl0nO1xufVxuXG5mdW5jdGlvbiBpc192YXJpYWJsZSh2YWx1ZSkge1xuICByZXR1cm4gdmFsdWUgaW5zdGFuY2VvZiBWYXJpYWJsZTtcbn1cblxuZnVuY3Rpb24gaXNfd2lsZGNhcmQodmFsdWUpIHtcbiAgcmV0dXJuIHZhbHVlIGluc3RhbmNlb2YgV2lsZGNhcmQ7XG59XG5cbmZ1bmN0aW9uIGlzX2hlYWRUYWlsKHZhbHVlKSB7XG4gIHJldHVybiB2YWx1ZSBpbnN0YW5jZW9mIEhlYWRUYWlsO1xufVxuXG5mdW5jdGlvbiBpc19jYXB0dXJlKHZhbHVlKSB7XG4gIHJldHVybiB2YWx1ZSBpbnN0YW5jZW9mIENhcHR1cmU7XG59XG5cbmZ1bmN0aW9uIGlzX3R5cGUodmFsdWUpIHtcbiAgcmV0dXJuIHZhbHVlIGluc3RhbmNlb2YgVHlwZTtcbn1cblxuZnVuY3Rpb24gaXNfc3RhcnRzV2l0aCh2YWx1ZSkge1xuICByZXR1cm4gdmFsdWUgaW5zdGFuY2VvZiBTdGFydHNXaXRoO1xufVxuXG5mdW5jdGlvbiBpc19ib3VuZCh2YWx1ZSkge1xuICByZXR1cm4gdmFsdWUgaW5zdGFuY2VvZiBCb3VuZDtcbn1cblxuZnVuY3Rpb24gaXNfb2JqZWN0KHZhbHVlKSB7XG4gIHJldHVybiB0eXBlb2YgdmFsdWUgPT09ICdvYmplY3QnO1xufVxuXG5mdW5jdGlvbiBpc19hcnJheSh2YWx1ZSkge1xuICByZXR1cm4gQXJyYXkuaXNBcnJheSh2YWx1ZSk7XG59XG5cbnZhciBDaGVja3MgPSB7XG4gIGlzX251bWJlcjogaXNfbnVtYmVyJDEsXG4gIGlzX3N0cmluZyxcbiAgaXNfYm9vbGVhbjogaXNfYm9vbGVhbiQxLFxuICBpc19zeW1ib2wsXG4gIGlzX251bGwsXG4gIGlzX3VuZGVmaW5lZCxcbiAgaXNfZnVuY3Rpb246IGlzX2Z1bmN0aW9uJDEsXG4gIGlzX3ZhcmlhYmxlLFxuICBpc193aWxkY2FyZCxcbiAgaXNfaGVhZFRhaWwsXG4gIGlzX2NhcHR1cmUsXG4gIGlzX3R5cGUsXG4gIGlzX3N0YXJ0c1dpdGgsXG4gIGlzX2JvdW5kLFxuICBpc19vYmplY3QsXG4gIGlzX2FycmF5XG59O1xuXG5mdW5jdGlvbiByZXNvbHZlU3ltYm9sKHBhdHRlcm4pIHtcbiAgcmV0dXJuIGZ1bmN0aW9uICh2YWx1ZSkge1xuICAgIHJldHVybiBDaGVja3MuaXNfc3ltYm9sKHZhbHVlKSAmJiB2YWx1ZSA9PT0gcGF0dGVybjtcbiAgfTtcbn1cblxuZnVuY3Rpb24gcmVzb2x2ZVN0cmluZyhwYXR0ZXJuKSB7XG4gIHJldHVybiBmdW5jdGlvbiAodmFsdWUpIHtcbiAgICByZXR1cm4gQ2hlY2tzLmlzX3N0cmluZyh2YWx1ZSkgJiYgdmFsdWUgPT09IHBhdHRlcm47XG4gIH07XG59XG5cbmZ1bmN0aW9uIHJlc29sdmVOdW1iZXIocGF0dGVybikge1xuICByZXR1cm4gZnVuY3Rpb24gKHZhbHVlKSB7XG4gICAgcmV0dXJuIENoZWNrcy5pc19udW1iZXIodmFsdWUpICYmIHZhbHVlID09PSBwYXR0ZXJuO1xuICB9O1xufVxuXG5mdW5jdGlvbiByZXNvbHZlQm9vbGVhbihwYXR0ZXJuKSB7XG4gIHJldHVybiBmdW5jdGlvbiAodmFsdWUpIHtcbiAgICByZXR1cm4gQ2hlY2tzLmlzX2Jvb2xlYW4odmFsdWUpICYmIHZhbHVlID09PSBwYXR0ZXJuO1xuICB9O1xufVxuXG5mdW5jdGlvbiByZXNvbHZlRnVuY3Rpb24ocGF0dGVybikge1xuICByZXR1cm4gZnVuY3Rpb24gKHZhbHVlKSB7XG4gICAgcmV0dXJuIENoZWNrcy5pc19mdW5jdGlvbih2YWx1ZSkgJiYgdmFsdWUgPT09IHBhdHRlcm47XG4gIH07XG59XG5cbmZ1bmN0aW9uIHJlc29sdmVOdWxsKHBhdHRlcm4pIHtcbiAgcmV0dXJuIGZ1bmN0aW9uICh2YWx1ZSkge1xuICAgIHJldHVybiBDaGVja3MuaXNfbnVsbCh2YWx1ZSk7XG4gIH07XG59XG5cbmZ1bmN0aW9uIHJlc29sdmVCb3VuZChwYXR0ZXJuKSB7XG4gIHJldHVybiBmdW5jdGlvbiAodmFsdWUsIGFyZ3MpIHtcbiAgICBpZiAodHlwZW9mIHZhbHVlID09PSB0eXBlb2YgcGF0dGVybi52YWx1ZSAmJiB2YWx1ZSA9PT0gcGF0dGVybi52YWx1ZSkge1xuICAgICAgYXJncy5wdXNoKHZhbHVlKTtcbiAgICAgIHJldHVybiB0cnVlO1xuICAgIH1cblxuICAgIHJldHVybiBmYWxzZTtcbiAgfTtcbn1cblxuZnVuY3Rpb24gcmVzb2x2ZVdpbGRjYXJkKCkge1xuICByZXR1cm4gZnVuY3Rpb24gKCkge1xuICAgIHJldHVybiB0cnVlO1xuICB9O1xufVxuXG5mdW5jdGlvbiByZXNvbHZlVmFyaWFibGUoKSB7XG4gIHJldHVybiBmdW5jdGlvbiAodmFsdWUsIGFyZ3MpIHtcbiAgICBhcmdzLnB1c2godmFsdWUpO1xuICAgIHJldHVybiB0cnVlO1xuICB9O1xufVxuXG5mdW5jdGlvbiByZXNvbHZlSGVhZFRhaWwoKSB7XG4gIHJldHVybiBmdW5jdGlvbiAodmFsdWUsIGFyZ3MpIHtcbiAgICBpZiAoIUNoZWNrcy5pc19hcnJheSh2YWx1ZSkgfHwgdmFsdWUubGVuZ3RoIDwgMikge1xuICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH1cblxuICAgIGNvbnN0IGhlYWQgPSB2YWx1ZVswXTtcbiAgICBjb25zdCB0YWlsID0gdmFsdWUuc2xpY2UoMSk7XG5cbiAgICBhcmdzLnB1c2goaGVhZCk7XG4gICAgYXJncy5wdXNoKHRhaWwpO1xuXG4gICAgcmV0dXJuIHRydWU7XG4gIH07XG59XG5cbmZ1bmN0aW9uIHJlc29sdmVDYXB0dXJlKHBhdHRlcm4pIHtcbiAgY29uc3QgbWF0Y2hlcyA9IGJ1aWxkTWF0Y2gocGF0dGVybi52YWx1ZSk7XG5cbiAgcmV0dXJuIGZ1bmN0aW9uICh2YWx1ZSwgYXJncykge1xuICAgIGlmIChtYXRjaGVzKHZhbHVlLCBhcmdzKSkge1xuICAgICAgYXJncy5wdXNoKHZhbHVlKTtcbiAgICAgIHJldHVybiB0cnVlO1xuICAgIH1cblxuICAgIHJldHVybiBmYWxzZTtcbiAgfTtcbn1cblxuZnVuY3Rpb24gcmVzb2x2ZVN0YXJ0c1dpdGgocGF0dGVybikge1xuICBjb25zdCBwcmVmaXggPSBwYXR0ZXJuLnByZWZpeDtcblxuICByZXR1cm4gZnVuY3Rpb24gKHZhbHVlLCBhcmdzKSB7XG4gICAgaWYgKENoZWNrcy5pc19zdHJpbmcodmFsdWUpICYmIHZhbHVlLnN0YXJ0c1dpdGgocHJlZml4KSkge1xuICAgICAgYXJncy5wdXNoKHZhbHVlLnN1YnN0cmluZyhwcmVmaXgubGVuZ3RoKSk7XG4gICAgICByZXR1cm4gdHJ1ZTtcbiAgICB9XG5cbiAgICByZXR1cm4gZmFsc2U7XG4gIH07XG59XG5cbmZ1bmN0aW9uIHJlc29sdmVUeXBlKHBhdHRlcm4pIHtcbiAgcmV0dXJuIGZ1bmN0aW9uICh2YWx1ZSwgYXJncykge1xuICAgIGlmICh2YWx1ZSBpbnN0YW5jZW9mIHBhdHRlcm4udHlwZSkge1xuICAgICAgY29uc3QgbWF0Y2hlcyA9IGJ1aWxkTWF0Y2gocGF0dGVybi5vYmpQYXR0ZXJuKTtcbiAgICAgIHJldHVybiBtYXRjaGVzKHZhbHVlLCBhcmdzKSAmJiBhcmdzLnB1c2godmFsdWUpID4gMDtcbiAgICB9XG5cbiAgICByZXR1cm4gZmFsc2U7XG4gIH07XG59XG5cbmZ1bmN0aW9uIHJlc29sdmVBcnJheShwYXR0ZXJuKSB7XG4gIGNvbnN0IG1hdGNoZXMgPSBwYXR0ZXJuLm1hcCh4ID0+IGJ1aWxkTWF0Y2goeCkpO1xuXG4gIHJldHVybiBmdW5jdGlvbiAodmFsdWUsIGFyZ3MpIHtcbiAgICBpZiAoIUNoZWNrcy5pc19hcnJheSh2YWx1ZSkgfHwgdmFsdWUubGVuZ3RoICE9IHBhdHRlcm4ubGVuZ3RoKSB7XG4gICAgICByZXR1cm4gZmFsc2U7XG4gICAgfVxuXG4gICAgcmV0dXJuIHZhbHVlLmV2ZXJ5KGZ1bmN0aW9uICh2LCBpKSB7XG4gICAgICByZXR1cm4gbWF0Y2hlc1tpXSh2YWx1ZVtpXSwgYXJncyk7XG4gICAgfSk7XG4gIH07XG59XG5cbmZ1bmN0aW9uIHJlc29sdmVPYmplY3QocGF0dGVybikge1xuICBsZXQgbWF0Y2hlcyA9IHt9O1xuXG4gIGZvciAobGV0IGtleSBvZiBPYmplY3Qua2V5cyhwYXR0ZXJuKSkge1xuICAgIG1hdGNoZXNba2V5XSA9IGJ1aWxkTWF0Y2gocGF0dGVybltrZXldKTtcbiAgfVxuXG4gIHJldHVybiBmdW5jdGlvbiAodmFsdWUsIGFyZ3MpIHtcbiAgICBpZiAoIUNoZWNrcy5pc19vYmplY3QodmFsdWUpIHx8IHBhdHRlcm4ubGVuZ3RoID4gdmFsdWUubGVuZ3RoKSB7XG4gICAgICByZXR1cm4gZmFsc2U7XG4gICAgfVxuXG4gICAgZm9yIChsZXQga2V5IG9mIE9iamVjdC5rZXlzKHBhdHRlcm4pKSB7XG4gICAgICBpZiAoIShrZXkgaW4gdmFsdWUpIHx8ICFtYXRjaGVzW2tleV0odmFsdWVba2V5XSwgYXJncykpIHtcbiAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgfVxuICAgIH1cblxuICAgIHJldHVybiB0cnVlO1xuICB9O1xufVxuXG5mdW5jdGlvbiByZXNvbHZlTm9NYXRjaCgpIHtcbiAgcmV0dXJuIGZ1bmN0aW9uICgpIHtcbiAgICByZXR1cm4gZmFsc2U7XG4gIH07XG59XG5cbnZhciBSZXNvbHZlcnMgPSB7XG4gIHJlc29sdmVCb3VuZCxcbiAgcmVzb2x2ZVdpbGRjYXJkLFxuICByZXNvbHZlVmFyaWFibGUsXG4gIHJlc29sdmVIZWFkVGFpbCxcbiAgcmVzb2x2ZUNhcHR1cmUsXG4gIHJlc29sdmVTdGFydHNXaXRoLFxuICByZXNvbHZlVHlwZSxcbiAgcmVzb2x2ZUFycmF5LFxuICByZXNvbHZlT2JqZWN0LFxuICByZXNvbHZlTm9NYXRjaCxcbiAgcmVzb2x2ZVN5bWJvbCxcbiAgcmVzb2x2ZVN0cmluZyxcbiAgcmVzb2x2ZU51bWJlcixcbiAgcmVzb2x2ZUJvb2xlYW4sXG4gIHJlc29sdmVGdW5jdGlvbixcbiAgcmVzb2x2ZU51bGxcbn07XG5cbmZ1bmN0aW9uIGJ1aWxkTWF0Y2gocGF0dGVybikge1xuXG4gIGlmIChDaGVja3MuaXNfdmFyaWFibGUocGF0dGVybikpIHtcbiAgICByZXR1cm4gUmVzb2x2ZXJzLnJlc29sdmVWYXJpYWJsZShwYXR0ZXJuKTtcbiAgfVxuXG4gIGlmIChDaGVja3MuaXNfd2lsZGNhcmQocGF0dGVybikpIHtcbiAgICByZXR1cm4gUmVzb2x2ZXJzLnJlc29sdmVXaWxkY2FyZChwYXR0ZXJuKTtcbiAgfVxuXG4gIGlmIChDaGVja3MuaXNfdW5kZWZpbmVkKHBhdHRlcm4pKSB7XG4gICAgcmV0dXJuIFJlc29sdmVycy5yZXNvbHZlV2lsZGNhcmQocGF0dGVybik7XG4gIH1cblxuICBpZiAoQ2hlY2tzLmlzX2hlYWRUYWlsKHBhdHRlcm4pKSB7XG4gICAgcmV0dXJuIFJlc29sdmVycy5yZXNvbHZlSGVhZFRhaWwocGF0dGVybik7XG4gIH1cblxuICBpZiAoQ2hlY2tzLmlzX3N0YXJ0c1dpdGgocGF0dGVybikpIHtcbiAgICByZXR1cm4gUmVzb2x2ZXJzLnJlc29sdmVTdGFydHNXaXRoKHBhdHRlcm4pO1xuICB9XG5cbiAgaWYgKENoZWNrcy5pc19jYXB0dXJlKHBhdHRlcm4pKSB7XG4gICAgcmV0dXJuIFJlc29sdmVycy5yZXNvbHZlQ2FwdHVyZShwYXR0ZXJuKTtcbiAgfVxuXG4gIGlmIChDaGVja3MuaXNfYm91bmQocGF0dGVybikpIHtcbiAgICByZXR1cm4gUmVzb2x2ZXJzLnJlc29sdmVCb3VuZChwYXR0ZXJuKTtcbiAgfVxuXG4gIGlmIChDaGVja3MuaXNfdHlwZShwYXR0ZXJuKSkge1xuICAgIHJldHVybiBSZXNvbHZlcnMucmVzb2x2ZVR5cGUocGF0dGVybik7XG4gIH1cblxuICBpZiAoQ2hlY2tzLmlzX2FycmF5KHBhdHRlcm4pKSB7XG4gICAgcmV0dXJuIFJlc29sdmVycy5yZXNvbHZlQXJyYXkocGF0dGVybik7XG4gIH1cblxuICBpZiAoQ2hlY2tzLmlzX251bWJlcihwYXR0ZXJuKSkge1xuICAgIHJldHVybiBSZXNvbHZlcnMucmVzb2x2ZU51bWJlcihwYXR0ZXJuKTtcbiAgfVxuXG4gIGlmIChDaGVja3MuaXNfc3RyaW5nKHBhdHRlcm4pKSB7XG4gICAgcmV0dXJuIFJlc29sdmVycy5yZXNvbHZlU3RyaW5nKHBhdHRlcm4pO1xuICB9XG5cbiAgaWYgKENoZWNrcy5pc19ib29sZWFuKHBhdHRlcm4pKSB7XG4gICAgcmV0dXJuIFJlc29sdmVycy5yZXNvbHZlQm9vbGVhbihwYXR0ZXJuKTtcbiAgfVxuXG4gIGlmIChDaGVja3MuaXNfc3ltYm9sKHBhdHRlcm4pKSB7XG4gICAgcmV0dXJuIFJlc29sdmVycy5yZXNvbHZlU3ltYm9sKHBhdHRlcm4pO1xuICB9XG5cbiAgaWYgKENoZWNrcy5pc19udWxsKHBhdHRlcm4pKSB7XG4gICAgcmV0dXJuIFJlc29sdmVycy5yZXNvbHZlTnVsbChwYXR0ZXJuKTtcbiAgfVxuXG4gIGlmIChDaGVja3MuaXNfb2JqZWN0KHBhdHRlcm4pKSB7XG4gICAgcmV0dXJuIFJlc29sdmVycy5yZXNvbHZlT2JqZWN0KHBhdHRlcm4pO1xuICB9XG5cbiAgcmV0dXJuIFJlc29sdmVycy5yZXNvbHZlTm9NYXRjaCgpO1xufVxuXG5jbGFzcyBNYXRjaEVycm9yIGV4dGVuZHMgRXJyb3Ige1xuICBjb25zdHJ1Y3RvcihhcmcpIHtcbiAgICBzdXBlcigpO1xuXG4gICAgaWYgKHR5cGVvZiBhcmcgPT09ICdzeW1ib2wnKSB7XG4gICAgICB0aGlzLm1lc3NhZ2UgPSAnTm8gbWF0Y2ggZm9yOiAnICsgYXJnLnRvU3RyaW5nKCk7XG4gICAgfSBlbHNlIGlmIChBcnJheS5pc0FycmF5KGFyZykpIHtcbiAgICAgIGxldCBtYXBwZWRWYWx1ZXMgPSBhcmcubWFwKHggPT4geC50b1N0cmluZygpKTtcbiAgICAgIHRoaXMubWVzc2FnZSA9ICdObyBtYXRjaCBmb3I6ICcgKyBtYXBwZWRWYWx1ZXM7XG4gICAgfSBlbHNlIHtcbiAgICAgIHRoaXMubWVzc2FnZSA9ICdObyBtYXRjaCBmb3I6ICcgKyBhcmc7XG4gICAgfVxuXG4gICAgdGhpcy5zdGFjayA9IG5ldyBFcnJvcigpLnN0YWNrO1xuICAgIHRoaXMubmFtZSA9IHRoaXMuY29uc3RydWN0b3IubmFtZTtcbiAgfVxufVxuXG5jbGFzcyBDYXNlIHtcblxuICBjb25zdHJ1Y3RvcihwYXR0ZXJuLCBmbiwgZ3VhcmQgPSAoKSA9PiB0cnVlKSB7XG4gICAgdGhpcy5wYXR0ZXJuID0gYnVpbGRNYXRjaChwYXR0ZXJuKTtcbiAgICB0aGlzLmZuID0gZm47XG4gICAgdGhpcy5ndWFyZCA9IGd1YXJkO1xuICB9XG59XG5cbmZ1bmN0aW9uIG1ha2VfY2FzZShwYXR0ZXJuLCBmbiwgZ3VhcmQgPSAoKSA9PiB0cnVlKSB7XG4gIHJldHVybiBuZXcgQ2FzZShwYXR0ZXJuLCBmbiwgZ3VhcmQpO1xufVxuXG5mdW5jdGlvbiBkZWZtYXRjaCguLi5jYXNlcykge1xuICByZXR1cm4gZnVuY3Rpb24gKC4uLmFyZ3MpIHtcbiAgICBmb3IgKGxldCBwcm9jZXNzZWRDYXNlIG9mIGNhc2VzKSB7XG4gICAgICBsZXQgcmVzdWx0ID0gW107XG4gICAgICBpZiAocHJvY2Vzc2VkQ2FzZS5wYXR0ZXJuKGFyZ3MsIHJlc3VsdCkgJiYgcHJvY2Vzc2VkQ2FzZS5ndWFyZC5hcHBseSh0aGlzLCByZXN1bHQpKSB7XG4gICAgICAgIHJldHVybiBwcm9jZXNzZWRDYXNlLmZuLmFwcGx5KHRoaXMsIHJlc3VsdCk7XG4gICAgICB9XG4gICAgfVxuXG4gICAgdGhyb3cgbmV3IE1hdGNoRXJyb3IoYXJncyk7XG4gIH07XG59XG5cbmZ1bmN0aW9uIG1hdGNoKHBhdHRlcm4sIGV4cHIsIGd1YXJkID0gKCkgPT4gdHJ1ZSkge1xuICBsZXQgcmVzdWx0ID0gW107XG4gIGxldCBwcm9jZXNzZWRQYXR0ZXJuID0gYnVpbGRNYXRjaChwYXR0ZXJuKTtcbiAgaWYgKHByb2Nlc3NlZFBhdHRlcm4oZXhwciwgcmVzdWx0KSAmJiBndWFyZC5hcHBseSh0aGlzLCByZXN1bHQpKSB7XG4gICAgcmV0dXJuIHJlc3VsdDtcbiAgfSBlbHNlIHtcbiAgICB0aHJvdyBuZXcgTWF0Y2hFcnJvcihleHByKTtcbiAgfVxufVxuXG5mdW5jdGlvbiBtYXRjaF9ub190aHJvdyhwYXR0ZXJuLCBleHByLCBndWFyZCA9ICgpID0+IHRydWUpIHtcbiAgdHJ5IHtcbiAgICByZXR1cm4gbWF0Y2gocGF0dGVybiwgZXhwciwgZ3VhcmQpO1xuICB9IGNhdGNoIChlKSB7XG4gICAgaWYgKGUgaW5zdGFuY2VvZiBNYXRjaEVycm9yKSB7XG4gICAgICByZXR1cm4gbnVsbDtcbiAgICB9XG5cbiAgICB0aHJvdyBlO1xuICB9XG59XG5cbnZhciBQYXR0ZXJucyA9IHtcbiAgZGVmbWF0Y2gsIG1hdGNoLCBNYXRjaEVycm9yLCBtYXRjaF9ub190aHJvdyxcbiAgdmFyaWFibGUsIHdpbGRjYXJkLCBzdGFydHNXaXRoLFxuICBjYXB0dXJlLCBoZWFkVGFpbCwgdHlwZSwgYm91bmQsIENhc2UsIG1ha2VfY2FzZVxufTtcblxuY2xhc3MgQml0U3RyaW5nIHtcbiAgY29uc3RydWN0b3IoLi4uYXJncykge1xuICAgIHRoaXMucmF3X3ZhbHVlID0gZnVuY3Rpb24gKCkge1xuICAgICAgcmV0dXJuIE9iamVjdC5mcmVlemUoYXJncyk7XG4gICAgfTtcblxuICAgIHRoaXMudmFsdWUgPSBPYmplY3QuZnJlZXplKHRoaXMucHJvY2VzcyhhcmdzKSk7XG4gIH1cblxuICBnZXQoaW5kZXgpIHtcbiAgICByZXR1cm4gdGhpcy52YWx1ZVtpbmRleF07XG4gIH1cblxuICBjb3VudCgpIHtcbiAgICByZXR1cm4gdGhpcy52YWx1ZS5sZW5ndGg7XG4gIH1cblxuICBbU3ltYm9sLml0ZXJhdG9yXSgpIHtcbiAgICByZXR1cm4gdGhpcy52YWx1ZVtTeW1ib2wuaXRlcmF0b3JdKCk7XG4gIH1cblxuICB0b1N0cmluZygpIHtcbiAgICB2YXIgaSxcbiAgICAgICAgcyA9IFwiXCI7XG4gICAgZm9yIChpID0gMDsgaSA8IHRoaXMuY291bnQoKTsgaSsrKSB7XG4gICAgICBpZiAocyAhPT0gXCJcIikge1xuICAgICAgICBzICs9IFwiLCBcIjtcbiAgICAgIH1cbiAgICAgIHMgKz0gdGhpc1tpXS50b1N0cmluZygpO1xuICAgIH1cblxuICAgIHJldHVybiBcIjw8XCIgKyBzICsgXCI+PlwiO1xuICB9XG5cbiAgcHJvY2VzcygpIHtcbiAgICBsZXQgcHJvY2Vzc2VkX3ZhbHVlcyA9IFtdO1xuXG4gICAgdmFyIGk7XG4gICAgZm9yIChpID0gMDsgaSA8IHRoaXMucmF3X3ZhbHVlKCkubGVuZ3RoOyBpKyspIHtcbiAgICAgIGxldCBwcm9jZXNzZWRfdmFsdWUgPSB0aGlzW1wicHJvY2Vzc19cIiArIHRoaXMucmF3X3ZhbHVlKClbaV0udHlwZV0odGhpcy5yYXdfdmFsdWUoKVtpXSk7XG5cbiAgICAgIGZvciAobGV0IGF0dHIgb2YgdGhpcy5yYXdfdmFsdWUoKVtpXS5hdHRyaWJ1dGVzKSB7XG4gICAgICAgIHByb2Nlc3NlZF92YWx1ZSA9IHRoaXNbXCJwcm9jZXNzX1wiICsgYXR0cl0ocHJvY2Vzc2VkX3ZhbHVlKTtcbiAgICAgIH1cblxuICAgICAgcHJvY2Vzc2VkX3ZhbHVlcyA9IHByb2Nlc3NlZF92YWx1ZXMuY29uY2F0KHByb2Nlc3NlZF92YWx1ZSk7XG4gICAgfVxuXG4gICAgcmV0dXJuIHByb2Nlc3NlZF92YWx1ZXM7XG4gIH1cblxuICBwcm9jZXNzX2ludGVnZXIodmFsdWUpIHtcbiAgICByZXR1cm4gdmFsdWUudmFsdWU7XG4gIH1cblxuICBwcm9jZXNzX2Zsb2F0KHZhbHVlKSB7XG4gICAgaWYgKHZhbHVlLnNpemUgPT09IDY0KSB7XG4gICAgICByZXR1cm4gQml0U3RyaW5nLmZsb2F0NjRUb0J5dGVzKHZhbHVlLnZhbHVlKTtcbiAgICB9IGVsc2UgaWYgKHZhbHVlLnNpemUgPT09IDMyKSB7XG4gICAgICByZXR1cm4gQml0U3RyaW5nLmZsb2F0MzJUb0J5dGVzKHZhbHVlLnZhbHVlKTtcbiAgICB9XG5cbiAgICB0aHJvdyBuZXcgRXJyb3IoXCJJbnZhbGlkIHNpemUgZm9yIGZsb2F0XCIpO1xuICB9XG5cbiAgcHJvY2Vzc19iaXRzdHJpbmcodmFsdWUpIHtcbiAgICByZXR1cm4gdmFsdWUudmFsdWUudmFsdWU7XG4gIH1cblxuICBwcm9jZXNzX2JpbmFyeSh2YWx1ZSkge1xuICAgIHJldHVybiBCaXRTdHJpbmcudG9VVEY4QXJyYXkodmFsdWUudmFsdWUpO1xuICB9XG5cbiAgcHJvY2Vzc191dGY4KHZhbHVlKSB7XG4gICAgcmV0dXJuIEJpdFN0cmluZy50b1VURjhBcnJheSh2YWx1ZS52YWx1ZSk7XG4gIH1cblxuICBwcm9jZXNzX3V0ZjE2KHZhbHVlKSB7XG4gICAgcmV0dXJuIEJpdFN0cmluZy50b1VURjE2QXJyYXkodmFsdWUudmFsdWUpO1xuICB9XG5cbiAgcHJvY2Vzc191dGYzMih2YWx1ZSkge1xuICAgIHJldHVybiBCaXRTdHJpbmcudG9VVEYzMkFycmF5KHZhbHVlLnZhbHVlKTtcbiAgfVxuXG4gIHByb2Nlc3Nfc2lnbmVkKHZhbHVlKSB7XG4gICAgcmV0dXJuIG5ldyBVaW50OEFycmF5KFt2YWx1ZV0pWzBdO1xuICB9XG5cbiAgcHJvY2Vzc191bnNpZ25lZCh2YWx1ZSkge1xuICAgIHJldHVybiB2YWx1ZTtcbiAgfVxuXG4gIHByb2Nlc3NfbmF0aXZlKHZhbHVlKSB7XG4gICAgcmV0dXJuIHZhbHVlO1xuICB9XG5cbiAgcHJvY2Vzc19iaWcodmFsdWUpIHtcbiAgICByZXR1cm4gdmFsdWU7XG4gIH1cblxuICBwcm9jZXNzX2xpdHRsZSh2YWx1ZSkge1xuICAgIHJldHVybiB2YWx1ZS5yZXZlcnNlKCk7XG4gIH1cblxuICBwcm9jZXNzX3NpemUodmFsdWUpIHtcbiAgICByZXR1cm4gdmFsdWU7XG4gIH1cblxuICBwcm9jZXNzX3VuaXQodmFsdWUpIHtcbiAgICByZXR1cm4gdmFsdWU7XG4gIH1cblxuICBzdGF0aWMgaW50ZWdlcih2YWx1ZSkge1xuICAgIHJldHVybiBCaXRTdHJpbmcud3JhcCh2YWx1ZSwgeyBcInR5cGVcIjogXCJpbnRlZ2VyXCIsIFwidW5pdFwiOiAxLCBcInNpemVcIjogOCB9KTtcbiAgfVxuXG4gIHN0YXRpYyBmbG9hdCh2YWx1ZSkge1xuICAgIHJldHVybiBCaXRTdHJpbmcud3JhcCh2YWx1ZSwgeyBcInR5cGVcIjogXCJmbG9hdFwiLCBcInVuaXRcIjogMSwgXCJzaXplXCI6IDY0IH0pO1xuICB9XG5cbiAgc3RhdGljIGJpdHN0cmluZyh2YWx1ZSkge1xuICAgIHJldHVybiBCaXRTdHJpbmcud3JhcCh2YWx1ZSwgeyBcInR5cGVcIjogXCJiaXRzdHJpbmdcIiwgXCJ1bml0XCI6IDEsIFwic2l6ZVwiOiB2YWx1ZS5sZW5ndGggfSk7XG4gIH1cblxuICBzdGF0aWMgYml0cyh2YWx1ZSkge1xuICAgIHJldHVybiBCaXRTdHJpbmcuYml0c3RyaW5nKHZhbHVlKTtcbiAgfVxuXG4gIHN0YXRpYyBiaW5hcnkodmFsdWUpIHtcbiAgICByZXR1cm4gQml0U3RyaW5nLndyYXAodmFsdWUsIHsgXCJ0eXBlXCI6IFwiYmluYXJ5XCIsIFwidW5pdFwiOiA4LCBcInNpemVcIjogdmFsdWUubGVuZ3RoIH0pO1xuICB9XG5cbiAgc3RhdGljIGJ5dGVzKHZhbHVlKSB7XG4gICAgcmV0dXJuIEJpdFN0cmluZy5iaW5hcnkodmFsdWUpO1xuICB9XG5cbiAgc3RhdGljIHV0ZjgodmFsdWUpIHtcbiAgICByZXR1cm4gQml0U3RyaW5nLndyYXAodmFsdWUsIHsgXCJ0eXBlXCI6IFwidXRmOFwiIH0pO1xuICB9XG5cbiAgc3RhdGljIHV0ZjE2KHZhbHVlKSB7XG4gICAgcmV0dXJuIEJpdFN0cmluZy53cmFwKHZhbHVlLCB7IFwidHlwZVwiOiBcInV0ZjE2XCIgfSk7XG4gIH1cblxuICBzdGF0aWMgdXRmMzIodmFsdWUpIHtcbiAgICByZXR1cm4gQml0U3RyaW5nLndyYXAodmFsdWUsIHsgXCJ0eXBlXCI6IFwidXRmMzJcIiB9KTtcbiAgfVxuXG4gIHN0YXRpYyBzaWduZWQodmFsdWUpIHtcbiAgICByZXR1cm4gQml0U3RyaW5nLndyYXAodmFsdWUsIHt9LCBcInNpZ25lZFwiKTtcbiAgfVxuXG4gIHN0YXRpYyB1bnNpZ25lZCh2YWx1ZSkge1xuICAgIHJldHVybiBCaXRTdHJpbmcud3JhcCh2YWx1ZSwge30sIFwidW5zaWduZWRcIik7XG4gIH1cblxuICBzdGF0aWMgbmF0aXZlKHZhbHVlKSB7XG4gICAgcmV0dXJuIEJpdFN0cmluZy53cmFwKHZhbHVlLCB7fSwgXCJuYXRpdmVcIik7XG4gIH1cblxuICBzdGF0aWMgYmlnKHZhbHVlKSB7XG4gICAgcmV0dXJuIEJpdFN0cmluZy53cmFwKHZhbHVlLCB7fSwgXCJiaWdcIik7XG4gIH1cblxuICBzdGF0aWMgbGl0dGxlKHZhbHVlKSB7XG4gICAgcmV0dXJuIEJpdFN0cmluZy53cmFwKHZhbHVlLCB7fSwgXCJsaXR0bGVcIik7XG4gIH1cblxuICBzdGF0aWMgc2l6ZSh2YWx1ZSwgY291bnQpIHtcbiAgICByZXR1cm4gQml0U3RyaW5nLndyYXAodmFsdWUsIHsgXCJzaXplXCI6IGNvdW50IH0pO1xuICB9XG5cbiAgc3RhdGljIHVuaXQodmFsdWUsIGNvdW50KSB7XG4gICAgcmV0dXJuIEJpdFN0cmluZy53cmFwKHZhbHVlLCB7IFwidW5pdFwiOiBjb3VudCB9KTtcbiAgfVxuXG4gIHN0YXRpYyB3cmFwKHZhbHVlLCBvcHQsIG5ld19hdHRyaWJ1dGUgPSBudWxsKSB7XG4gICAgbGV0IHRoZV92YWx1ZSA9IHZhbHVlO1xuXG4gICAgaWYgKCEodmFsdWUgaW5zdGFuY2VvZiBPYmplY3QpKSB7XG4gICAgICB0aGVfdmFsdWUgPSB7IFwidmFsdWVcIjogdmFsdWUsIFwiYXR0cmlidXRlc1wiOiBbXSB9O1xuICAgIH1cblxuICAgIHRoZV92YWx1ZSA9IE9iamVjdC5hc3NpZ24odGhlX3ZhbHVlLCBvcHQpO1xuXG4gICAgaWYgKG5ld19hdHRyaWJ1dGUpIHtcbiAgICAgIHRoZV92YWx1ZS5hdHRyaWJ1dGVzLnB1c2gobmV3X2F0dHJpYnV0ZSk7XG4gICAgfVxuXG4gICAgcmV0dXJuIHRoZV92YWx1ZTtcbiAgfVxuXG4gIHN0YXRpYyB0b1VURjhBcnJheShzdHIpIHtcbiAgICB2YXIgdXRmOCA9IFtdO1xuICAgIGZvciAodmFyIGkgPSAwOyBpIDwgc3RyLmxlbmd0aDsgaSsrKSB7XG4gICAgICB2YXIgY2hhcmNvZGUgPSBzdHIuY2hhckNvZGVBdChpKTtcbiAgICAgIGlmIChjaGFyY29kZSA8IDEyOCkge1xuICAgICAgICB1dGY4LnB1c2goY2hhcmNvZGUpO1xuICAgICAgfSBlbHNlIGlmIChjaGFyY29kZSA8IDIwNDgpIHtcbiAgICAgICAgdXRmOC5wdXNoKDE5MiB8IGNoYXJjb2RlID4+IDYsIDEyOCB8IGNoYXJjb2RlICYgNjMpO1xuICAgICAgfSBlbHNlIGlmIChjaGFyY29kZSA8IDU1Mjk2IHx8IGNoYXJjb2RlID49IDU3MzQ0KSB7XG4gICAgICAgIHV0ZjgucHVzaCgyMjQgfCBjaGFyY29kZSA+PiAxMiwgMTI4IHwgY2hhcmNvZGUgPj4gNiAmIDYzLCAxMjggfCBjaGFyY29kZSAmIDYzKTtcbiAgICAgIH1cbiAgICAgIC8vIHN1cnJvZ2F0ZSBwYWlyXG4gICAgICBlbHNlIHtcbiAgICAgICAgaSsrO1xuICAgICAgICAvLyBVVEYtMTYgZW5jb2RlcyAweDEwMDAwLTB4MTBGRkZGIGJ5XG4gICAgICAgIC8vIHN1YnRyYWN0aW5nIDB4MTAwMDAgYW5kIHNwbGl0dGluZyB0aGVcbiAgICAgICAgLy8gMjAgYml0cyBvZiAweDAtMHhGRkZGRiBpbnRvIHR3byBoYWx2ZXNcbiAgICAgICAgY2hhcmNvZGUgPSA2NTUzNiArICgoY2hhcmNvZGUgJiAxMDIzKSA8PCAxMCB8IHN0ci5jaGFyQ29kZUF0KGkpICYgMTAyMyk7XG4gICAgICAgIHV0ZjgucHVzaCgyNDAgfCBjaGFyY29kZSA+PiAxOCwgMTI4IHwgY2hhcmNvZGUgPj4gMTIgJiA2MywgMTI4IHwgY2hhcmNvZGUgPj4gNiAmIDYzLCAxMjggfCBjaGFyY29kZSAmIDYzKTtcbiAgICAgIH1cbiAgICB9XG4gICAgcmV0dXJuIHV0Zjg7XG4gIH1cblxuICBzdGF0aWMgdG9VVEYxNkFycmF5KHN0cikge1xuICAgIHZhciB1dGYxNiA9IFtdO1xuICAgIGZvciAodmFyIGkgPSAwOyBpIDwgc3RyLmxlbmd0aDsgaSsrKSB7XG4gICAgICB2YXIgY29kZVBvaW50ID0gc3RyLmNvZGVQb2ludEF0KGkpO1xuXG4gICAgICBpZiAoY29kZVBvaW50IDw9IDI1NSkge1xuICAgICAgICB1dGYxNi5wdXNoKDApO1xuICAgICAgICB1dGYxNi5wdXNoKGNvZGVQb2ludCk7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICB1dGYxNi5wdXNoKGNvZGVQb2ludCA+PiA4ICYgMjU1KTtcbiAgICAgICAgdXRmMTYucHVzaChjb2RlUG9pbnQgJiAyNTUpO1xuICAgICAgfVxuICAgIH1cbiAgICByZXR1cm4gdXRmMTY7XG4gIH1cblxuICBzdGF0aWMgdG9VVEYzMkFycmF5KHN0cikge1xuICAgIHZhciB1dGYzMiA9IFtdO1xuICAgIGZvciAodmFyIGkgPSAwOyBpIDwgc3RyLmxlbmd0aDsgaSsrKSB7XG4gICAgICB2YXIgY29kZVBvaW50ID0gc3RyLmNvZGVQb2ludEF0KGkpO1xuXG4gICAgICBpZiAoY29kZVBvaW50IDw9IDI1NSkge1xuICAgICAgICB1dGYzMi5wdXNoKDApO1xuICAgICAgICB1dGYzMi5wdXNoKDApO1xuICAgICAgICB1dGYzMi5wdXNoKDApO1xuICAgICAgICB1dGYzMi5wdXNoKGNvZGVQb2ludCk7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICB1dGYzMi5wdXNoKDApO1xuICAgICAgICB1dGYzMi5wdXNoKDApO1xuICAgICAgICB1dGYzMi5wdXNoKGNvZGVQb2ludCA+PiA4ICYgMjU1KTtcbiAgICAgICAgdXRmMzIucHVzaChjb2RlUG9pbnQgJiAyNTUpO1xuICAgICAgfVxuICAgIH1cbiAgICByZXR1cm4gdXRmMzI7XG4gIH1cblxuICAvL2h0dHA6Ly9zdGFja292ZXJmbG93LmNvbS9xdWVzdGlvbnMvMjAwMzQ5My9qYXZhc2NyaXB0LWZsb2F0LWZyb20tdG8tYml0c1xuICBzdGF0aWMgZmxvYXQzMlRvQnl0ZXMoZikge1xuICAgIHZhciBieXRlcyA9IFtdO1xuXG4gICAgdmFyIGJ1ZiA9IG5ldyBBcnJheUJ1ZmZlcig0KTtcbiAgICBuZXcgRmxvYXQzMkFycmF5KGJ1ZilbMF0gPSBmO1xuXG4gICAgbGV0IGludFZlcnNpb24gPSBuZXcgVWludDMyQXJyYXkoYnVmKVswXTtcblxuICAgIGJ5dGVzLnB1c2goaW50VmVyc2lvbiA+PiAyNCAmIDI1NSk7XG4gICAgYnl0ZXMucHVzaChpbnRWZXJzaW9uID4+IDE2ICYgMjU1KTtcbiAgICBieXRlcy5wdXNoKGludFZlcnNpb24gPj4gOCAmIDI1NSk7XG4gICAgYnl0ZXMucHVzaChpbnRWZXJzaW9uICYgMjU1KTtcblxuICAgIHJldHVybiBieXRlcztcbiAgfVxuXG4gIHN0YXRpYyBmbG9hdDY0VG9CeXRlcyhmKSB7XG4gICAgdmFyIGJ5dGVzID0gW107XG5cbiAgICB2YXIgYnVmID0gbmV3IEFycmF5QnVmZmVyKDgpO1xuICAgIG5ldyBGbG9hdDY0QXJyYXkoYnVmKVswXSA9IGY7XG5cbiAgICB2YXIgaW50VmVyc2lvbjEgPSBuZXcgVWludDMyQXJyYXkoYnVmKVswXTtcbiAgICB2YXIgaW50VmVyc2lvbjIgPSBuZXcgVWludDMyQXJyYXkoYnVmKVsxXTtcblxuICAgIGJ5dGVzLnB1c2goaW50VmVyc2lvbjIgPj4gMjQgJiAyNTUpO1xuICAgIGJ5dGVzLnB1c2goaW50VmVyc2lvbjIgPj4gMTYgJiAyNTUpO1xuICAgIGJ5dGVzLnB1c2goaW50VmVyc2lvbjIgPj4gOCAmIDI1NSk7XG4gICAgYnl0ZXMucHVzaChpbnRWZXJzaW9uMiAmIDI1NSk7XG5cbiAgICBieXRlcy5wdXNoKGludFZlcnNpb24xID4+IDI0ICYgMjU1KTtcbiAgICBieXRlcy5wdXNoKGludFZlcnNpb24xID4+IDE2ICYgMjU1KTtcbiAgICBieXRlcy5wdXNoKGludFZlcnNpb24xID4+IDggJiAyNTUpO1xuICAgIGJ5dGVzLnB1c2goaW50VmVyc2lvbjEgJiAyNTUpO1xuXG4gICAgcmV0dXJuIGJ5dGVzO1xuICB9XG59XG5cbi8qIEBmbG93ICovXG5cbmNsYXNzIE1haWxib3gge1xuXG4gIGNvbnN0cnVjdG9yKCkge1xuICAgIHRoaXMubWVzc2FnZXMgPSBbXTtcbiAgfVxuXG4gIGRlbGl2ZXIobWVzc2FnZSkge1xuICAgIHRoaXMubWVzc2FnZXMucHVzaChtZXNzYWdlKTtcbiAgICByZXR1cm4gbWVzc2FnZTtcbiAgfVxuXG4gIGdldCgpIHtcbiAgICByZXR1cm4gdGhpcy5tZXNzYWdlcztcbiAgfVxuXG4gIGlzRW1wdHkoKSB7XG4gICAgcmV0dXJuIHRoaXMubWVzc2FnZXMubGVuZ3RoID09PSAwO1xuICB9XG5cbiAgcmVtb3ZlQXQoaW5kZXgpIHtcbiAgICB0aGlzLm1lc3NhZ2VzLnNwbGljZShpbmRleCwgMSk7XG4gIH1cbn1cblxudmFyIFN0YXRlcyA9IHtcbiAgTk9STUFMOiBTeW1ib2wuZm9yKFwibm9ybWFsXCIpLFxuICBLSUxMOiBTeW1ib2wuZm9yKFwia2lsbFwiKSxcbiAgU1VTUEVORDogU3ltYm9sLmZvcihcInN1c3BlbmRcIiksXG4gIENPTlRJTlVFOiBTeW1ib2wuZm9yKFwiY29udGludWVcIiksXG4gIFJFQ0VJVkU6IFN5bWJvbC5mb3IoXCJyZWNlaXZlXCIpLFxuICBTRU5EOiBTeW1ib2wuZm9yKFwic2VuZFwiKSxcbiAgU0xFRVBJTkc6IFN5bWJvbC5mb3IoXCJzbGVlcGluZ1wiKSxcbiAgUlVOTklORzogU3ltYm9sLmZvcihcInJ1bm5pbmdcIiksXG4gIFNVU1BFTkRFRDogU3ltYm9sLmZvcihcInN1c3BlbmRlZFwiKSxcbiAgU1RPUFBFRDogU3ltYm9sLmZvcihcInN0b3BwZWRcIiksXG4gIFNMRUVQOiBTeW1ib2wuZm9yKFwic2xlZXBcIiksXG4gIEVYSVQ6IFN5bWJvbC5mb3IoXCJleGl0XCIpLFxuICBOT01BVENIOiBTeW1ib2wuZm9yKFwibm9fbWF0Y2hcIilcbn07XG5cbmNsYXNzIFByb2Nlc3Mge1xuXG4gIGNvbnN0cnVjdG9yKHBpZCwgbWFpbGJveCkge1xuICAgIHRoaXMucGlkID0gcGlkO1xuICAgIHRoaXMubWFpbGJveCA9IG1haWxib3g7XG4gICAgdGhpcy5zdGF0dXMgPSBTdGF0ZXMuU1RPUFBFRDtcbiAgICB0aGlzLmRpY3QgPSB7fTtcbiAgfVxufVxuXG5jbGFzcyBQcm9jZXNzU3lzdGVtIHtcblxuICBjb25zdHJ1Y3RvcigpIHtcbiAgICB0aGlzLnBpZHMgPSBuZXcgTWFwKCk7XG4gICAgdGhpcy5tYWlsYm94ZXMgPSBuZXcgTWFwKCk7XG4gICAgdGhpcy5uYW1lcyA9IG5ldyBNYXAoKTtcbiAgICB0aGlzLmxpbmtzID0gbmV3IE1hcCgpO1xuXG4gICAgdGhpcy5jdXJyZW50X3Byb2Nlc3MgPSBudWxsO1xuICAgIHRoaXMuc3VzcGVuZGVkID0gbmV3IE1hcCgpO1xuXG4gICAgdGhpcy5tYWluX3Byb2Nlc3NfcGlkID0gdGhpcy5zcGF3bigpO1xuICAgIHRoaXMuc2V0X2N1cnJlbnQodGhpcy5tYWluX3Byb2Nlc3NfcGlkKTtcbiAgfVxuXG4gIHNwYXduKCkge1xuICAgIHJldHVybiB0aGlzLmFkZF9wcm9jKGZhbHNlKS5waWQ7XG4gIH1cblxuICBzcGF3bl9saW5rKCkge1xuICAgIHJldHVybiB0aGlzLmFkZF9wcm9jKHRydWUpLnBpZDtcbiAgfVxuXG4gIGxpbmsocGlkKSB7XG4gICAgdGhpcy5saW5rcy5nZXQodGhpcy5waWQoKSkuYWRkKHBpZCk7XG4gICAgdGhpcy5saW5rcy5nZXQocGlkKS5hZGQodGhpcy5waWQoKSk7XG4gIH1cblxuICB1bmxpbmsocGlkKSB7XG4gICAgdGhpcy5saW5rcy5nZXQodGhpcy5waWQoKSkuZGVsZXRlKHBpZCk7XG4gICAgdGhpcy5saW5rcy5nZXQocGlkKS5kZWxldGUodGhpcy5waWQoKSk7XG4gIH1cblxuICBzZXRfY3VycmVudChpZCkge1xuICAgIGxldCBwaWQgPSB0aGlzLnBpZG9mKGlkKTtcbiAgICBpZiAocGlkICE9PSBudWxsKSB7XG4gICAgICB0aGlzLmN1cnJlbnRfcHJvY2VzcyA9IHRoaXMucGlkcy5nZXQocGlkKTtcbiAgICAgIHRoaXMuY3VycmVudF9wcm9jZXNzLnN0YXR1cyA9IFN0YXRlcy5SVU5OSU5HO1xuICAgIH1cbiAgfVxuXG4gIGFkZF9wcm9jKGxpbmtlZCkge1xuICAgIGxldCBuZXdwaWQgPSBuZXcgUElEKCk7XG4gICAgbGV0IG1haWxib3ggPSBuZXcgTWFpbGJveCgpO1xuICAgIGxldCBuZXdwcm9jID0gbmV3IFByb2Nlc3MobmV3cGlkLCBtYWlsYm94KTtcblxuICAgIHRoaXMucGlkcy5zZXQobmV3cGlkLCBuZXdwcm9jKTtcbiAgICB0aGlzLm1haWxib3hlcy5zZXQobmV3cGlkLCBtYWlsYm94KTtcbiAgICB0aGlzLmxpbmtzLnNldChuZXdwaWQsIG5ldyBTZXQoKSk7XG5cbiAgICBpZiAobGlua2VkKSB7XG4gICAgICB0aGlzLmxpbmsobmV3cGlkKTtcbiAgICB9XG5cbiAgICByZXR1cm4gbmV3cHJvYztcbiAgfVxuXG4gIHJlbW92ZV9wcm9jKHBpZCkge1xuICAgIHRoaXMucGlkcy5kZWxldGUocGlkKTtcbiAgICB0aGlzLnVucmVnaXN0ZXIocGlkKTtcblxuICAgIGlmICh0aGlzLmxpbmtzLmhhcyhwaWQpKSB7XG4gICAgICBmb3IgKGxldCBsaW5rcGlkIG9mIHRoaXMubGlua3MuZ2V0KHBpZCkpIHtcbiAgICAgICAgdGhpcy5saW5rcy5nZXQobGlua3BpZCkuZGVsZXRlKHBpZCk7XG4gICAgICB9XG5cbiAgICAgIHRoaXMubGlua3MuZGVsZXRlKHBpZCk7XG4gICAgfVxuICB9XG5cbiAgZXhpdChpZCkge1xuICAgIGxldCBwaWQgPSB0aGlzLnBpZG9mKGlkKTtcbiAgICB0aGlzLnJlbW92ZV9wcm9jKGlkKTtcbiAgfVxuXG4gIHJlZ2lzdGVyKG5hbWUsIHBpZCkge1xuICAgIGlmICghdGhpcy5uYW1lcy5oYXMobmFtZSkpIHtcbiAgICAgIHRoaXMubmFtZXMuc2V0KG5hbWUsIHBpZCk7XG4gICAgICByZXR1cm4gbmFtZTtcbiAgICB9IGVsc2Uge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKFwiTmFtZSBpcyBhbHJlYWR5IHJlZ2lzdGVyZWQgdG8gYW5vdGhlciBwcm9jZXNzXCIpO1xuICAgIH1cbiAgfVxuXG4gIHJlZ2lzdGVyZWQobmFtZSkge1xuICAgIHJldHVybiB0aGlzLm5hbWVzLmhhcyhuYW1lKSA/IHRoaXMubmFtZXMuZ2V0KG5hbWUpIDogbnVsbDtcbiAgfVxuXG4gIHVucmVnaXN0ZXIocGlkKSB7XG4gICAgZm9yIChsZXQgbmFtZSBvZiB0aGlzLm5hbWVzLmtleXMoKSkge1xuICAgICAgaWYgKHRoaXMubmFtZXMuaGFzKG5hbWUpICYmIHRoaXMubmFtZXMuZ2V0KG5hbWUpID09PSBwaWQpIHtcbiAgICAgICAgdGhpcy5uYW1lcy5kZWxldGUobmFtZSk7XG4gICAgICB9XG4gICAgfVxuICB9XG5cbiAgcGlkKCkge1xuICAgIHJldHVybiB0aGlzLmN1cnJlbnRfcHJvY2Vzcy5waWQ7XG4gIH1cblxuICBwaWRvZihpZCkge1xuICAgIGlmIChpZCBpbnN0YW5jZW9mIFBJRCkge1xuICAgICAgcmV0dXJuIHRoaXMucGlkcy5oYXMoaWQpID8gaWQgOiBudWxsO1xuICAgIH0gZWxzZSBpZiAoaWQgaW5zdGFuY2VvZiBQcm9jZXNzKSB7XG4gICAgICByZXR1cm4gaWQucGlkO1xuICAgIH0gZWxzZSB7XG4gICAgICBsZXQgcGlkID0gdGhpcy5yZWdpc3RlcmVkKGlkKTtcbiAgICAgIGlmIChwaWQgPT09IG51bGwpIHRocm93IFwiUHJvY2VzcyBuYW1lIG5vdCByZWdpc3RlcmVkOiBcIiArIGlkICsgXCIgKFwiICsgdHlwZW9mIGlkICsgXCIpXCI7XG4gICAgICByZXR1cm4gcGlkO1xuICAgIH1cbiAgfVxuXG4gIHB1dChpZCwga2V5LCB2YWx1ZSkge1xuICAgIGxldCBwaWQgPSB0aGlzLnBpZG9mKGlkKTtcbiAgICBsZXQgcHJvY2VzcyA9IHRoaXMucGlkcy5nZXQocGlkKTtcbiAgICBwcm9jZXNzLmRpY3Rba2V5XSA9IHZhbHVlO1xuICB9XG5cbiAgZ2V0KGlkLCBrZXkpIHtcbiAgICBsZXQgcGlkID0gdGhpcy5waWRvZihpZCk7XG4gICAgbGV0IHByb2Nlc3MgPSB0aGlzLnBpZHMuZ2V0KHBpZCk7XG5cbiAgICBpZiAoa2V5ICE9IG51bGwpIHtcbiAgICAgIHJldHVybiBwcm9jZXNzLmRpY3Rba2V5XTtcbiAgICB9IGVsc2Uge1xuICAgICAgcmV0dXJuIHByb2Nlc3MuZGljdDtcbiAgICB9XG4gIH1cblxuICBnZXRfa2V5cyhpZCkge1xuICAgIGxldCBwaWQgPSB0aGlzLnBpZG9mKGlkKTtcbiAgICBsZXQgcHJvY2VzcyA9IHRoaXMucGlkcy5nZXQocGlkKTtcblxuICAgIHJldHVybiBPYmplY3Qua2V5cyhwcm9jZXNzLmRpY3QpO1xuICB9XG5cbiAgZXJhc2UoaWQsIGtleSkge1xuICAgIGxldCBwaWQgPSB0aGlzLnBpZG9mKGlkKTtcbiAgICBsZXQgcHJvY2VzcyA9IHRoaXMucGlkcy5nZXQocGlkKTtcblxuICAgIGlmIChrZXkgIT0gbnVsbCkge1xuICAgICAgZGVsZXRlIHByb2Nlc3MuZGljdFtrZXldO1xuICAgIH0gZWxzZSB7XG4gICAgICBwcm9jZXNzLmRpY3QgPSB7fTtcbiAgICB9XG4gIH1cbn1cblxudmFyIEMgPSBPYmplY3QuZnJlZXplKHtcblx0UHJvY2Vzc1N5c3RlbTogUHJvY2Vzc1N5c3RlbSxcblx0VHVwbGU6IFR1cGxlJDEsXG5cdFBJRDogUElELFxuXHRCaXRTdHJpbmc6IEJpdFN0cmluZyxcblx0UGF0dGVybnM6IFBhdHRlcm5zLFxuXHRJbnRlZ2VyOiBJbnRlZ2VyJDEsXG5cdEZsb2F0OiBGbG9hdCxcblx0Y2FsbF9wcm9wZXJ0eTogY2FsbF9wcm9wZXJ0eVxufSk7XG5cbmxldCBFbnVtID0ge1xuXG4gIGFsbF9fcW1hcmtfXzogZnVuY3Rpb24gKGNvbGxlY3Rpb24sIGZ1biA9IHggPT4geCkge1xuICAgIGZvciAobGV0IGVsZW0gb2YgY29sbGVjdGlvbikge1xuICAgICAgaWYgKCFmdW4oZWxlbSkpIHtcbiAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgfVxuICAgIH1cblxuICAgIHJldHVybiB0cnVlO1xuICB9LFxuXG4gIGFueV9fcW1hcmtfXzogZnVuY3Rpb24gKGNvbGxlY3Rpb24sIGZ1biA9IHggPT4geCkge1xuICAgIGZvciAobGV0IGVsZW0gb2YgY29sbGVjdGlvbikge1xuICAgICAgaWYgKGZ1bihlbGVtKSkge1xuICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICByZXR1cm4gZmFsc2U7XG4gIH0sXG5cbiAgYXQ6IGZ1bmN0aW9uIChjb2xsZWN0aW9uLCBuLCB0aGVfZGVmYXVsdCA9IG51bGwpIHtcbiAgICBpZiAobiA+IHRoaXMuY291bnQoY29sbGVjdGlvbikgfHwgbiA8IDApIHtcbiAgICAgIHJldHVybiB0aGVfZGVmYXVsdDtcbiAgICB9XG5cbiAgICByZXR1cm4gY29sbGVjdGlvbltuXTtcbiAgfSxcblxuICBjb25jYXQ6IGZ1bmN0aW9uICguLi5lbnVtYWJsZXMpIHtcbiAgICByZXR1cm4gZW51bWFibGVzWzBdLmNvbmNhdChlbnVtYWJsZXNbMV0pO1xuICB9LFxuXG4gIGNvdW50OiBmdW5jdGlvbiAoY29sbGVjdGlvbiwgZnVuID0gbnVsbCkge1xuICAgIGlmIChmdW4gPT0gbnVsbCkge1xuICAgICAgcmV0dXJuIGNvbGxlY3Rpb24ubGVuZ3RoO1xuICAgIH0gZWxzZSB7XG4gICAgICByZXR1cm4gY29sbGVjdGlvbi5maWx0ZXIoZnVuKS5sZW5ndGg7XG4gICAgfVxuICB9LFxuXG4gIGRyb3A6IGZ1bmN0aW9uIChjb2xsZWN0aW9uLCBjb3VudCkge1xuICAgIHJldHVybiBjb2xsZWN0aW9uLnNsaWNlKGNvdW50KTtcbiAgfSxcblxuICBkcm9wX3doaWxlOiBmdW5jdGlvbiAoY29sbGVjdGlvbiwgZnVuKSB7XG4gICAgbGV0IGNvdW50ID0gMDtcblxuICAgIGZvciAobGV0IGVsZW0gb2YgY29sbGVjdGlvbikge1xuICAgICAgaWYgKGZ1bihlbGVtKSkge1xuICAgICAgICBjb3VudCA9IGNvdW50ICsgMTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIGJyZWFrO1xuICAgICAgfVxuICAgIH1cblxuICAgIHJldHVybiBjb2xsZWN0aW9uLnNsaWNlKGNvdW50KTtcbiAgfSxcblxuICBlYWNoOiBmdW5jdGlvbiAoY29sbGVjdGlvbiwgZnVuKSB7XG4gICAgZm9yIChsZXQgZWxlbSBvZiBjb2xsZWN0aW9uKSB7XG4gICAgICBmdW4oZWxlbSk7XG4gICAgfVxuICB9LFxuXG4gIGVtcHR5X19xbWFya19fOiBmdW5jdGlvbiAoY29sbGVjdGlvbikge1xuICAgIHJldHVybiBjb2xsZWN0aW9uLmxlbmd0aCA9PT0gMDtcbiAgfSxcblxuICBmZXRjaDogZnVuY3Rpb24gKGNvbGxlY3Rpb24sIG4pIHtcbiAgICBpZiAoS2VybmVsLmlzX2xpc3QoY29sbGVjdGlvbikpIHtcbiAgICAgIGlmIChuIDwgdGhpcy5jb3VudChjb2xsZWN0aW9uKSAmJiBuID49IDApIHtcbiAgICAgICAgcmV0dXJuIEtlcm5lbC5TcGVjaWFsRm9ybXMudHVwbGUoS2VybmVsLlNwZWNpYWxGb3Jtcy5hdG9tKFwib2tcIiksIGNvbGxlY3Rpb25bbl0pO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgcmV0dXJuIEtlcm5lbC5TcGVjaWFsRm9ybXMuYXRvbShcImVycm9yXCIpO1xuICAgICAgfVxuICAgIH1cblxuICAgIHRocm93IG5ldyBFcnJvcihcImNvbGxlY3Rpb24gaXMgbm90IGFuIEVudW1lcmFibGVcIik7XG4gIH0sXG5cbiAgZmV0Y2hfX2VtYXJrX186IGZ1bmN0aW9uIChjb2xsZWN0aW9uLCBuKSB7XG4gICAgaWYgKEtlcm5lbC5pc19saXN0KGNvbGxlY3Rpb24pKSB7XG4gICAgICBpZiAobiA8IHRoaXMuY291bnQoY29sbGVjdGlvbikgJiYgbiA+PSAwKSB7XG4gICAgICAgIHJldHVybiBjb2xsZWN0aW9uW25dO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKFwib3V0IG9mIGJvdW5kcyBlcnJvclwiKTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICB0aHJvdyBuZXcgRXJyb3IoXCJjb2xsZWN0aW9uIGlzIG5vdCBhbiBFbnVtZXJhYmxlXCIpO1xuICB9LFxuXG4gIGZpbHRlcjogZnVuY3Rpb24gKGNvbGxlY3Rpb24sIGZ1bikge1xuICAgIGxldCByZXN1bHQgPSBbXTtcblxuICAgIGZvciAobGV0IGVsZW0gb2YgY29sbGVjdGlvbikge1xuICAgICAgaWYgKGZ1bihlbGVtKSkge1xuICAgICAgICByZXN1bHQucHVzaChlbGVtKTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICByZXR1cm4gcmVzdWx0O1xuICB9LFxuXG4gIGZpbHRlcl9tYXA6IGZ1bmN0aW9uIChjb2xsZWN0aW9uLCBmaWx0ZXIsIG1hcHBlcikge1xuICAgIHJldHVybiBFbnVtLm1hcChFbnVtLmZpbHRlcihjb2xsZWN0aW9uLCBmaWx0ZXIpLCBtYXBwZXIpO1xuICB9LFxuXG4gIGZpbmQ6IGZ1bmN0aW9uIChjb2xsZWN0aW9uLCBpZl9ub25lID0gbnVsbCwgZnVuKSB7XG4gICAgZm9yIChsZXQgZWxlbSBvZiBjb2xsZWN0aW9uKSB7XG4gICAgICBpZiAoZnVuKGVsZW0pKSB7XG4gICAgICAgIHJldHVybiBlbGVtO1xuICAgICAgfVxuICAgIH1cblxuICAgIHJldHVybiBpZl9ub25lO1xuICB9LFxuXG4gIGludG86IGZ1bmN0aW9uIChjb2xsZWN0aW9uLCBsaXN0KSB7XG4gICAgcmV0dXJuIGxpc3QuY29uY2F0KGNvbGxlY3Rpb24pO1xuICB9LFxuXG4gIG1hcDogZnVuY3Rpb24gKGNvbGxlY3Rpb24sIGZ1bikge1xuICAgIGxldCByZXN1bHQgPSBbXTtcblxuICAgIGZvciAobGV0IGVsZW0gb2YgY29sbGVjdGlvbikge1xuICAgICAgcmVzdWx0LnB1c2goZnVuKGVsZW0pKTtcbiAgICB9XG5cbiAgICByZXR1cm4gcmVzdWx0O1xuICB9LFxuXG4gIG1hcF9yZWR1Y2U6IGZ1bmN0aW9uIChjb2xsZWN0aW9uLCBhY2MsIGZ1bikge1xuICAgIGxldCBtYXBwZWQgPSBLZXJuZWwuU3BlY2lhbEZvcm1zLmxpc3QoKTtcbiAgICBsZXQgdGhlX2FjYyA9IGFjYztcblxuICAgIGZvciAodmFyIGkgPSAwOyBpIDwgdGhpcy5jb3VudChjb2xsZWN0aW9uKTsgaSsrKSB7XG4gICAgICBsZXQgdHVwbGUgPSBmdW4oY29sbGVjdGlvbltpXSwgdGhlX2FjYyk7XG5cbiAgICAgIHRoZV9hY2MgPSBLZXJuZWwuZWxlbSh0dXBsZSwgMSk7XG4gICAgICBtYXBwZWQgPSBLZXJuZWwuU3BlY2lhbEZvcm1zLmxpc3QoLi4ubWFwcGVkLmNvbmNhdChbS2VybmVsLmVsZW0odHVwbGUsIDApXSkpO1xuICAgIH1cblxuICAgIHJldHVybiBLZXJuZWwuU3BlY2lhbEZvcm1zLnR1cGxlKG1hcHBlZCwgdGhlX2FjYyk7XG4gIH0sXG5cbiAgbWVtYmVyOiBmdW5jdGlvbiAoY29sbGVjdGlvbiwgdmFsdWUpIHtcbiAgICByZXR1cm4gY29sbGVjdGlvbi5pbmNsdWRlcyh2YWx1ZSk7XG4gIH0sXG5cbiAgcmVkdWNlOiBmdW5jdGlvbiAoY29sbGVjdGlvbiwgYWNjLCBmdW4pIHtcbiAgICBsZXQgdGhlX2FjYyA9IGFjYztcblxuICAgIGZvciAodmFyIGkgPSAwOyBpIDwgdGhpcy5jb3VudChjb2xsZWN0aW9uKTsgaSsrKSB7XG4gICAgICBsZXQgdHVwbGUgPSBmdW4oY29sbGVjdGlvbltpXSwgdGhlX2FjYyk7XG5cbiAgICAgIHRoZV9hY2MgPSBLZXJuZWwuZWxlbSh0dXBsZSwgMSk7XG4gICAgfVxuXG4gICAgcmV0dXJuIHRoZV9hY2M7XG4gIH0sXG5cbiAgdGFrZTogZnVuY3Rpb24gKGNvbGxlY3Rpb24sIGNvdW50KSB7XG4gICAgcmV0dXJuIGNvbGxlY3Rpb24uc2xpY2UoMCwgY291bnQpO1xuICB9LFxuXG4gIHRha2VfZXZlcnk6IGZ1bmN0aW9uIChjb2xsZWN0aW9uLCBudGgpIHtcbiAgICBsZXQgcmVzdWx0ID0gW107XG4gICAgbGV0IGluZGV4ID0gMDtcblxuICAgIGZvciAobGV0IGVsZW0gb2YgY29sbGVjdGlvbikge1xuICAgICAgaWYgKGluZGV4ICUgbnRoID09PSAwKSB7XG4gICAgICAgIHJlc3VsdC5wdXNoKGVsZW0pO1xuICAgICAgfVxuICAgIH1cblxuICAgIHJldHVybiBLZXJuZWwuU3BlY2lhbEZvcm1zLmxpc3QoLi4ucmVzdWx0KTtcbiAgfSxcblxuICB0YWtlX3doaWxlOiBmdW5jdGlvbiAoY29sbGVjdGlvbiwgZnVuKSB7XG4gICAgbGV0IGNvdW50ID0gMDtcblxuICAgIGZvciAobGV0IGVsZW0gb2YgY29sbGVjdGlvbikge1xuICAgICAgaWYgKGZ1bihlbGVtKSkge1xuICAgICAgICBjb3VudCA9IGNvdW50ICsgMTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIGJyZWFrO1xuICAgICAgfVxuICAgIH1cblxuICAgIHJldHVybiBjb2xsZWN0aW9uLnNsaWNlKDAsIGNvdW50KTtcbiAgfSxcblxuICB0b19saXN0OiBmdW5jdGlvbiAoY29sbGVjdGlvbikge1xuICAgIHJldHVybiBjb2xsZWN0aW9uO1xuICB9XG59O1xuXG5sZXQgU3BlY2lhbEZvcm1zID0ge1xuXG4gIF9fRElSX186IGZ1bmN0aW9uICgpIHtcbiAgICBpZiAoX19kaXJuYW1lKSB7XG4gICAgICByZXR1cm4gX19kaXJuYW1lO1xuICAgIH1cblxuICAgIGlmIChkb2N1bWVudC5jdXJyZW50U2NyaXB0KSB7XG4gICAgICByZXR1cm4gZG9jdW1lbnQuY3VycmVudFNjcmlwdC5zcmM7XG4gICAgfVxuXG4gICAgcmV0dXJuIG51bGw7XG4gIH0sXG5cbiAgYXRvbTogZnVuY3Rpb24gKF92YWx1ZSkge1xuICAgIHJldHVybiBTeW1ib2wuZm9yKF92YWx1ZSk7XG4gIH0sXG5cbiAgbGlzdDogZnVuY3Rpb24gKC4uLmFyZ3MpIHtcbiAgICByZXR1cm4gT2JqZWN0LmZyZWV6ZShhcmdzKTtcbiAgfSxcblxuICBiaXRzdHJpbmc6IGZ1bmN0aW9uICguLi5hcmdzKSB7XG4gICAgcmV0dXJuIG5ldyBCaXRTdHJpbmcoLi4uYXJncyk7XG4gIH0sXG5cbiAgYm91bmQ6IGZ1bmN0aW9uIChfdmFyKSB7XG4gICAgcmV0dXJuIFBhdHRlcm5zLmJvdW5kKF92YXIpO1xuICB9LFxuXG4gIF9jYXNlOiBmdW5jdGlvbiAoY29uZGl0aW9uLCBjbGF1c2VzKSB7XG4gICAgcmV0dXJuIFBhdHRlcm5zLmRlZm1hdGNoKC4uLmNsYXVzZXMpKGNvbmRpdGlvbik7XG4gIH0sXG5cbiAgY29uZDogZnVuY3Rpb24gKGNsYXVzZXMpIHtcbiAgICBmb3IgKGxldCBjbGF1c2Ugb2YgY2xhdXNlcykge1xuICAgICAgaWYgKGNsYXVzZVswXSkge1xuICAgICAgICByZXR1cm4gY2xhdXNlWzFdKCk7XG4gICAgICB9XG4gICAgfVxuXG4gICAgdGhyb3cgbmV3IEVycm9yKCk7XG4gIH0sXG5cbiAgZm46IGZ1bmN0aW9uIChjbGF1c2VzKSB7XG4gICAgcmV0dXJuIFBhdHRlcm5zLmRlZm1hdGNoKGNsYXVzZXMpO1xuICB9LFxuXG4gIG1hcDogZnVuY3Rpb24gKG9iaikge1xuICAgIHJldHVybiBPYmplY3QuZnJlZXplKG9iaik7XG4gIH0sXG5cbiAgbWFwX3VwZGF0ZTogZnVuY3Rpb24gKG1hcCwgdmFsdWVzKSB7XG4gICAgcmV0dXJuIE9iamVjdC5mcmVlemUoT2JqZWN0LmFzc2lnbihPYmplY3QuY3JlYXRlKG1hcC5jb25zdHJ1Y3Rvci5wcm90b3R5cGUpLCBtYXAsIHZhbHVlcykpO1xuICB9LFxuXG4gIF9mb3I6IGZ1bmN0aW9uIChjb2xsZWN0aW9ucywgZnVuLCBmaWx0ZXIgPSAoKSA9PiB0cnVlLCBpbnRvID0gW10sIHByZXZpb3VzVmFsdWVzID0gW10pIHtcbiAgICBsZXQgcGF0dGVybiA9IGNvbGxlY3Rpb25zWzBdWzBdO1xuICAgIGxldCBjb2xsZWN0aW9uID0gY29sbGVjdGlvbnNbMF1bMV07XG5cbiAgICBpZiAoY29sbGVjdGlvbnMubGVuZ3RoID09PSAxKSB7XG5cbiAgICAgIGZvciAobGV0IGVsZW0gb2YgY29sbGVjdGlvbikge1xuICAgICAgICBsZXQgciA9IFBhdHRlcm5zLm1hdGNoX25vX3Rocm93KHBhdHRlcm4sIGVsZW0pO1xuICAgICAgICBsZXQgYXJncyA9IHByZXZpb3VzVmFsdWVzLmNvbmNhdChyKTtcblxuICAgICAgICBpZiAociAmJiBmaWx0ZXIuYXBwbHkodGhpcywgYXJncykpIHtcbiAgICAgICAgICBpbnRvID0gRW51bS5pbnRvKFtmdW4uYXBwbHkodGhpcywgYXJncyldLCBpbnRvKTtcbiAgICAgICAgfVxuICAgICAgfVxuXG4gICAgICByZXR1cm4gaW50bztcbiAgICB9IGVsc2Uge1xuICAgICAgbGV0IF9pbnRvID0gW107XG5cbiAgICAgIGZvciAobGV0IGVsZW0gb2YgY29sbGVjdGlvbikge1xuICAgICAgICBsZXQgciA9IFBhdHRlcm5zLm1hdGNoX25vX3Rocm93KHBhdHRlcm4sIGVsZW0pO1xuICAgICAgICBpZiAocikge1xuICAgICAgICAgIF9pbnRvID0gRW51bS5pbnRvKHRoaXMuX2Zvcihjb2xsZWN0aW9ucy5zbGljZSgxKSwgZnVuLCBmaWx0ZXIsIF9pbnRvLCBwcmV2aW91c1ZhbHVlcy5jb25jYXQocikpLCBpbnRvKTtcbiAgICAgICAgfVxuICAgICAgfVxuXG4gICAgICByZXR1cm4gX2ludG87XG4gICAgfVxuICB9LFxuXG4gIHJlY2VpdmU6IGZ1bmN0aW9uIChyZWNlaXZlX2Z1biwgdGltZW91dF9pbl9tcyA9IG51bGwsIHRpbWVvdXRfZm4gPSB0aW1lID0+IHRydWUpIHtcbiAgICBpZiAodGltZW91dF9pbl9tcyA9PSBudWxsIHx8IHRpbWVvdXRfaW5fbXMgPT09IFN5c3RlbS5mb3IoJ2luZmluaXR5JykpIHtcbiAgICAgIHdoaWxlICh0cnVlKSB7XG4gICAgICAgIGlmIChzZWxmLm1haWxib3gubGVuZ3RoICE9PSAwKSB7XG4gICAgICAgICAgbGV0IG1lc3NhZ2UgPSBzZWxmLm1haWxib3hbMF07XG4gICAgICAgICAgc2VsZi5tYWlsYm94ID0gc2VsZi5tYWlsYm94LnNsaWNlKDEpO1xuICAgICAgICAgIHJldHVybiByZWNlaXZlX2Z1bihtZXNzYWdlKTtcbiAgICAgICAgfVxuICAgICAgfVxuICAgIH0gZWxzZSBpZiAodGltZW91dF9pbl9tcyA9PT0gMCkge1xuICAgICAgaWYgKHNlbGYubWFpbGJveC5sZW5ndGggIT09IDApIHtcbiAgICAgICAgbGV0IG1lc3NhZ2UgPSBzZWxmLm1haWxib3hbMF07XG4gICAgICAgIHNlbGYubWFpbGJveCA9IHNlbGYubWFpbGJveC5zbGljZSgxKTtcbiAgICAgICAgcmV0dXJuIHJlY2VpdmVfZnVuKG1lc3NhZ2UpO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgcmV0dXJuIG51bGw7XG4gICAgICB9XG4gICAgfSBlbHNlIHtcbiAgICAgIGxldCBub3cgPSBEYXRlLm5vdygpO1xuICAgICAgd2hpbGUgKERhdGUubm93KCkgPCBub3cgKyB0aW1lb3V0X2luX21zKSB7XG4gICAgICAgIGlmIChzZWxmLm1haWxib3gubGVuZ3RoICE9PSAwKSB7XG4gICAgICAgICAgbGV0IG1lc3NhZ2UgPSBzZWxmLm1haWxib3hbMF07XG4gICAgICAgICAgc2VsZi5tYWlsYm94ID0gc2VsZi5tYWlsYm94LnNsaWNlKDEpO1xuICAgICAgICAgIHJldHVybiByZWNlaXZlX2Z1bihtZXNzYWdlKTtcbiAgICAgICAgfVxuICAgICAgfVxuXG4gICAgICByZXR1cm4gdGltZW91dF9mbih0aW1lb3V0X2luX21zKTtcbiAgICB9XG4gIH0sXG5cbiAgdHVwbGU6IGZ1bmN0aW9uICguLi5hcmdzKSB7XG4gICAgcmV0dXJuIG5ldyBUdXBsZSQxKC4uLmFyZ3MpO1xuICB9LFxuXG4gIF90cnk6IGZ1bmN0aW9uIChkb19mdW4sIHJlc2N1ZV9mdW5jdGlvbiwgY2F0Y2hfZnVuLCBlbHNlX2Z1bmN0aW9uLCBhZnRlcl9mdW5jdGlvbikge1xuICAgIGxldCByZXN1bHQgPSBudWxsO1xuXG4gICAgdHJ5IHtcbiAgICAgIHJlc3VsdCA9IGRvX2Z1bigpO1xuICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgIGxldCBleF9yZXN1bHQgPSBudWxsO1xuXG4gICAgICBpZiAocmVzY3VlX2Z1bmN0aW9uKSB7XG4gICAgICAgIHRyeSB7XG4gICAgICAgICAgZXhfcmVzdWx0ID0gcmVzY3VlX2Z1bmN0aW9uKGUpO1xuICAgICAgICAgIHJldHVybiBleF9yZXN1bHQ7XG4gICAgICAgIH0gY2F0Y2ggKGV4KSB7XG4gICAgICAgICAgaWYgKGV4IGluc3RhbmNlb2YgUGF0dGVybnMuTWF0Y2hFcnJvcikge1xuICAgICAgICAgICAgdGhyb3cgZXg7XG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICB9XG5cbiAgICAgIGlmIChjYXRjaF9mdW4pIHtcbiAgICAgICAgdHJ5IHtcbiAgICAgICAgICBleF9yZXN1bHQgPSBjYXRjaF9mdW4oZSk7XG4gICAgICAgICAgcmV0dXJuIGV4X3Jlc3VsdDtcbiAgICAgICAgfSBjYXRjaCAoZXgpIHtcbiAgICAgICAgICBpZiAoZXggaW5zdGFuY2VvZiBQYXR0ZXJucy5NYXRjaEVycm9yKSB7XG4gICAgICAgICAgICB0aHJvdyBleDtcbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgIH1cblxuICAgICAgdGhyb3cgZTtcbiAgICB9IGZpbmFsbHkge1xuICAgICAgaWYgKGFmdGVyX2Z1bmN0aW9uKSB7XG4gICAgICAgIGFmdGVyX2Z1bmN0aW9uKCk7XG4gICAgICB9XG4gICAgfVxuXG4gICAgaWYgKGVsc2VfZnVuY3Rpb24pIHtcbiAgICAgIHRyeSB7XG4gICAgICAgIHJldHVybiBlbHNlX2Z1bmN0aW9uKHJlc3VsdCk7XG4gICAgICB9IGNhdGNoIChleCkge1xuICAgICAgICBpZiAoZXggaW5zdGFuY2VvZiBQYXR0ZXJucy5NYXRjaEVycm9yKSB7XG4gICAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdObyBNYXRjaCBGb3VuZCBpbiBFbHNlJyk7XG4gICAgICAgIH1cblxuICAgICAgICB0aHJvdyBleDtcbiAgICAgIH1cbiAgICB9IGVsc2Uge1xuICAgICAgcmV0dXJuIHJlc3VsdDtcbiAgICB9XG4gIH1cblxufTtcblxuZnVuY3Rpb24gdG9fc3RyaW5nJDEodHVwbGUpIHtcbiAgcmV0dXJuIHR1cGxlLnRvU3RyaW5nKCk7XG59O1xuXG5mdW5jdGlvbiBkZWxldGVfYXQodHVwbGUsIGluZGV4KSB7XG4gIGxldCBuZXdfbGlzdCA9IFtdO1xuXG4gIGZvciAodmFyIGkgPSAwOyBpIDwgdHVwbGUuY291bnQoKTsgaSsrKSB7XG4gICAgaWYgKGkgIT09IGluZGV4KSB7XG4gICAgICBuZXdfbGlzdC5wdXNoKHR1cGxlLmdldChpKSk7XG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIEtlcm5lbC5TcGVjaWFsRm9ybXMudHVwbGUuYXBwbHkobnVsbCwgbmV3X2xpc3QpO1xufTtcblxuZnVuY3Rpb24gZHVwbGljYXRlKGRhdGEsIHNpemUpIHtcbiAgbGV0IGFycmF5ID0gW107XG5cbiAgZm9yICh2YXIgaSA9IHNpemUgLSAxOyBpID49IDA7IGktLSkge1xuICAgIGFycmF5LnB1c2goZGF0YSk7XG4gIH1cblxuICByZXR1cm4gS2VybmVsLlNwZWNpYWxGb3Jtcy50dXBsZS5hcHBseShudWxsLCBhcnJheSk7XG59O1xuXG5mdW5jdGlvbiBpbnNlcnRfYXQodHVwbGUsIGluZGV4LCB0ZXJtKSB7XG4gIGxldCBuZXdfdHVwbGUgPSBbXTtcblxuICBmb3IgKHZhciBpID0gMDsgaSA8PSB0dXBsZS5jb3VudCgpOyBpKyspIHtcbiAgICBpZiAoaSA9PT0gaW5kZXgpIHtcbiAgICAgIG5ld190dXBsZS5wdXNoKHRlcm0pO1xuICAgICAgaSsrO1xuICAgICAgbmV3X3R1cGxlLnB1c2godHVwbGUuZ2V0KGkpKTtcbiAgICB9IGVsc2Uge1xuICAgICAgbmV3X3R1cGxlLnB1c2godHVwbGUuZ2V0KGkpKTtcbiAgICB9XG4gIH1cblxuICByZXR1cm4gS2VybmVsLlNwZWNpYWxGb3Jtcy50dXBsZS5hcHBseShudWxsLCBuZXdfdHVwbGUpO1xufTtcblxuZnVuY3Rpb24gZnJvbV9saXN0KGxpc3QpIHtcbiAgcmV0dXJuIEtlcm5lbC5TcGVjaWFsRm9ybXMudHVwbGUuYXBwbHkobnVsbCwgbGlzdCk7XG59O1xuXG5mdW5jdGlvbiB0b19saXN0KHR1cGxlKSB7XG4gIGxldCBuZXdfbGlzdCA9IFtdO1xuXG4gIGZvciAodmFyIGkgPSAwOyBpIDwgdHVwbGUuY291bnQoKTsgaSsrKSB7XG4gICAgbmV3X2xpc3QucHVzaCh0dXBsZS5nZXQoaSkpO1xuICB9XG5cbiAgcmV0dXJuIEtlcm5lbC5TcGVjaWFsRm9ybXMubGlzdCguLi5uZXdfbGlzdCk7XG59O1xuXG52YXIgVHVwbGUgPSB7XG4gIHRvX3N0cmluZzogdG9fc3RyaW5nJDEsXG4gIGRlbGV0ZV9hdCxcbiAgZHVwbGljYXRlLFxuICBpbnNlcnRfYXQsXG4gIGZyb21fbGlzdCxcbiAgdG9fbGlzdFxufTtcblxuLy9odHRwczovL2dpdGh1Yi5jb20vYWlycG9ydHloL3Byb3RvbW9ycGhpc21cbmNsYXNzIFByb3RvY29sIHtcbiAgY29uc3RydWN0b3Ioc3BlYykge1xuICAgIHRoaXMucmVnaXN0cnkgPSBuZXcgTWFwKCk7XG4gICAgdGhpcy5mYWxsYmFjayA9IG51bGw7XG5cbiAgICBmb3IgKGxldCBmdW5OYW1lIGluIHNwZWMpIHtcbiAgICAgIHRoaXNbZnVuTmFtZV0gPSBjcmVhdGVGdW4oZnVuTmFtZSkuYmluZCh0aGlzKTtcbiAgICB9XG5cbiAgICBmdW5jdGlvbiBjcmVhdGVGdW4oZnVuTmFtZSkge1xuXG4gICAgICByZXR1cm4gZnVuY3Rpb24gKC4uLmFyZ3MpIHtcbiAgICAgICAgbGV0IHRoaW5nID0gYXJnc1swXTtcbiAgICAgICAgbGV0IGZ1biA9IG51bGw7XG5cbiAgICAgICAgaWYgKE51bWJlci5pc0ludGVnZXIodGhpbmcpICYmIHRoaXMuaGFzSW1wbGVtZW50YXRpb24oSW50ZWdlciQxKSkge1xuICAgICAgICAgIGZ1biA9IHRoaXMucmVnaXN0cnkuZ2V0KEludGVnZXIkMSlbZnVuTmFtZV07XG4gICAgICAgIH0gZWxzZSBpZiAodHlwZW9mIHRoaW5nID09PSBcIm51bWJlclwiICYmICFOdW1iZXIuaXNJbnRlZ2VyKHRoaW5nKSAmJiB0aGlzLmhhc0ltcGxlbWVudGF0aW9uKEZsb2F0KSkge1xuICAgICAgICAgIGZ1biA9IHRoaXMucmVnaXN0cnkuZ2V0KEZsb2F0KVtmdW5OYW1lXTtcbiAgICAgICAgfSBlbHNlIGlmICh0aGlzLmhhc0ltcGxlbWVudGF0aW9uKHRoaW5nKSkge1xuICAgICAgICAgIGZ1biA9IHRoaXMucmVnaXN0cnkuZ2V0KHRoaW5nLmNvbnN0cnVjdG9yKVtmdW5OYW1lXTtcbiAgICAgICAgfSBlbHNlIGlmICh0aGlzLmZhbGxiYWNrKSB7XG4gICAgICAgICAgZnVuID0gdGhpcy5mYWxsYmFja1tmdW5OYW1lXTtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmIChmdW4gIT0gbnVsbCkge1xuICAgICAgICAgIGxldCByZXR2YWwgPSBmdW4uYXBwbHkodGhpcywgYXJncyk7XG4gICAgICAgICAgcmV0dXJuIHJldHZhbDtcbiAgICAgICAgfVxuXG4gICAgICAgIHRocm93IG5ldyBFcnJvcihcIk5vIGltcGxlbWVudGF0aW9uIGZvdW5kIGZvciBcIiArIHRoaW5nKTtcbiAgICAgIH07XG4gICAgfVxuICB9XG5cbiAgaW1wbGVtZW50YXRpb24odHlwZSwgaW1wbGVtZW50YXRpb24pIHtcbiAgICBpZiAodHlwZSA9PT0gbnVsbCkge1xuICAgICAgdGhpcy5mYWxsYmFjayA9IGltcGxlbWVudGF0aW9uO1xuICAgIH0gZWxzZSB7XG4gICAgICB0aGlzLnJlZ2lzdHJ5LnNldCh0eXBlLCBpbXBsZW1lbnRhdGlvbik7XG4gICAgfVxuICB9XG5cbiAgaGFzSW1wbGVtZW50YXRpb24odGhpbmcpIHtcbiAgICByZXR1cm4gdGhpcy5yZWdpc3RyeS5oYXModGhpbmcuY29uc3RydWN0b3IpO1xuICB9XG59XG5cbmZ1bmN0aW9uIHRsKGxpc3QpIHtcbiAgcmV0dXJuIFNwZWNpYWxGb3Jtcy5saXN0KC4uLmxpc3Quc2xpY2UoMSkpO1xufVxuXG5mdW5jdGlvbiBoZChsaXN0KSB7XG4gIHJldHVybiBsaXN0WzBdO1xufVxuXG5mdW5jdGlvbiBpc19uaWwoeCkge1xuICByZXR1cm4geCA9PT0gbnVsbDtcbn1cblxuZnVuY3Rpb24gaXNfYXRvbSh4KSB7XG4gIHJldHVybiB0eXBlb2YgeCA9PT0gJ3N5bWJvbCc7XG59XG5cbmZ1bmN0aW9uIGlzX2JpbmFyeSh4KSB7XG4gIHJldHVybiB0eXBlb2YgeCA9PT0gJ3N0cmluZycgfHwgeCBpbnN0YW5jZW9mIFN0cmluZztcbn1cblxuZnVuY3Rpb24gaXNfYm9vbGVhbih4KSB7XG4gIHJldHVybiB0eXBlb2YgeCA9PT0gJ2Jvb2xlYW4nIHx8IHggaW5zdGFuY2VvZiBCb29sZWFuO1xufVxuXG5mdW5jdGlvbiBpc19mdW5jdGlvbih4LCBhcml0eSA9IC0xKSB7XG4gIHJldHVybiB0eXBlb2YgeCA9PT0gJ2Z1bmN0aW9uJyB8fCB4IGluc3RhbmNlb2YgRnVuY3Rpb247XG59XG5cbmZ1bmN0aW9uIGlzX2Zsb2F0KHgpIHtcbiAgcmV0dXJuIGlzX251bWJlcih4KSAmJiAhTnVtYmVyLmlzSW50ZWdlcih4KTtcbn1cblxuZnVuY3Rpb24gaXNfaW50ZWdlcih4KSB7XG4gIHJldHVybiBOdW1iZXIuaXNJbnRlZ2VyKHgpO1xufVxuXG5mdW5jdGlvbiBpc19saXN0KHgpIHtcbiAgcmV0dXJuIHggaW5zdGFuY2VvZiBBcnJheTtcbn1cblxuZnVuY3Rpb24gaXNfbWFwKHgpIHtcbiAgcmV0dXJuIHR5cGVvZiB4ID09PSAnb2JqZWN0JyB8fCB4IGluc3RhbmNlb2YgT2JqZWN0O1xufVxuXG5mdW5jdGlvbiBpc19udW1iZXIoeCkge1xuICByZXR1cm4gdHlwZW9mIHggPT09ICdudW1iZXInO1xufVxuXG5mdW5jdGlvbiBpc190dXBsZSh4KSB7XG4gIHJldHVybiB4IGluc3RhbmNlb2YgVHVwbGUkMTtcbn1cblxuZnVuY3Rpb24gbGVuZ3RoKHgpIHtcbiAgcmV0dXJuIHgubGVuZ3RoO1xufVxuXG5mdW5jdGlvbiBpc19waWQoeCkge1xuICByZXR1cm4geCBpbnN0YW5jZW9mIFBJRDtcbn1cblxuZnVuY3Rpb24gaXNfcG9ydCh4KSB7XG4gIHJldHVybiBmYWxzZTtcbn1cblxuZnVuY3Rpb24gaXNfcmVmZXJlbmNlKHgpIHtcbiAgcmV0dXJuIGZhbHNlO1xufVxuXG5mdW5jdGlvbiBpc19iaXRzdHJpbmcoeCkge1xuICByZXR1cm4gaXNfYmluYXJ5KHgpIHx8IHggaW5zdGFuY2VvZiBCaXRTdHJpbmc7XG59XG5cbmZ1bmN0aW9uIF9faW5fXyhsZWZ0LCByaWdodCkge1xuICBmb3IgKGxldCB4IG9mIHJpZ2h0KSB7XG4gICAgaWYgKG1hdGNoX19xbWFya19fKGxlZnQsIHgpKSB7XG4gICAgICByZXR1cm4gdHJ1ZTtcbiAgICB9XG4gIH1cblxuICByZXR1cm4gZmFsc2U7XG59XG5cbmZ1bmN0aW9uIGFicyhudW1iZXIpIHtcbiAgcmV0dXJuIE1hdGguYWJzKG51bWJlcik7XG59XG5cbmZ1bmN0aW9uIHJvdW5kKG51bWJlcikge1xuICByZXR1cm4gTWF0aC5yb3VuZChudW1iZXIpO1xufVxuXG5mdW5jdGlvbiBlbGVtKHR1cGxlLCBpbmRleCkge1xuICBpZiAoaXNfbGlzdCh0dXBsZSkpIHtcbiAgICByZXR1cm4gdHVwbGVbaW5kZXhdO1xuICB9XG5cbiAgcmV0dXJuIHR1cGxlLmdldChpbmRleCk7XG59XG5cbmZ1bmN0aW9uIHJlbShsZWZ0LCByaWdodCkge1xuICByZXR1cm4gbGVmdCAlIHJpZ2h0O1xufVxuXG5mdW5jdGlvbiBkaXYobGVmdCwgcmlnaHQpIHtcbiAgcmV0dXJuIGxlZnQgLyByaWdodDtcbn1cblxuZnVuY3Rpb24gYW5kKGxlZnQsIHJpZ2h0KSB7XG4gIHJldHVybiBsZWZ0ICYmIHJpZ2h0O1xufVxuXG5mdW5jdGlvbiBvcihsZWZ0LCByaWdodCkge1xuICByZXR1cm4gbGVmdCB8fCByaWdodDtcbn1cblxuZnVuY3Rpb24gbm90KGFyZykge1xuICByZXR1cm4gIWFyZztcbn1cblxuZnVuY3Rpb24gYXBwbHkoLi4uYXJncykge1xuICBpZiAoYXJncy5sZW5ndGggPT09IDMpIHtcbiAgICBsZXQgbW9kID0gYXJnc1swXTtcbiAgICBsZXQgZnVuYyA9IGFyZ3NbMV07XG4gICAgbGV0IGZ1bmNfYXJncyA9IGFyZ3NbMl07XG4gICAgcmV0dXJuIG1vZFtmdW5jXS5hcHBseShudWxsLCBmdW5jX2FyZ3MpO1xuICB9IGVsc2Uge1xuICAgIGxldCBmdW5jID0gYXJnc1swXTtcbiAgICBsZXQgZnVuY19hcmdzID0gYXJnc1sxXTtcblxuICAgIHJldHVybiBmdW5jLmFwcGx5KG51bGwsIGZ1bmNfYXJncyk7XG4gIH1cbn1cblxuZnVuY3Rpb24gdG9fc3RyaW5nKGFyZykge1xuICBpZiAoaXNfdHVwbGUoYXJnKSkge1xuICAgIHJldHVybiBUdXBsZS50b19zdHJpbmcoYXJnKTtcbiAgfVxuXG4gIHJldHVybiBhcmcudG9TdHJpbmcoKTtcbn1cblxuZnVuY3Rpb24gbWF0Y2hfX3FtYXJrX18ocGF0dGVybiwgZXhwciwgZ3VhcmQgPSAoKSA9PiB0cnVlKSB7XG4gIHJldHVybiBQYXR0ZXJucy5tYXRjaF9ub190aHJvdyhwYXR0ZXJuLCBleHByLCBndWFyZCkgIT0gbnVsbDtcbn1cblxuZnVuY3Rpb24gZGVmc3RydWN0KGRlZmF1bHRzKSB7XG4gIHJldHVybiBjbGFzcyB7XG4gICAgY29uc3RydWN0b3IodXBkYXRlID0ge30pIHtcbiAgICAgIGxldCB0aGVfdmFsdWVzID0gT2JqZWN0LmFzc2lnbihkZWZhdWx0cywgdXBkYXRlKTtcbiAgICAgIE9iamVjdC5hc3NpZ24odGhpcywgdGhlX3ZhbHVlcyk7XG4gICAgfVxuXG4gICAgc3RhdGljIGNyZWF0ZSh1cGRhdGVzID0ge30pIHtcbiAgICAgIGxldCB4ID0gbmV3IHRoaXModXBkYXRlcyk7XG4gICAgICByZXR1cm4gT2JqZWN0LmZyZWV6ZSh4KTtcbiAgICB9XG4gIH07XG59XG5cbmZ1bmN0aW9uIGRlZnByb3RvY29sKHNwZWMpIHtcbiAgcmV0dXJuIG5ldyBQcm90b2NvbChzcGVjKTtcbn1cblxuZnVuY3Rpb24gZGVmaW1wbChwcm90b2NvbCwgdHlwZSwgaW1wbCkge1xuICBwcm90b2NvbC5pbXBsZW1lbnRhdGlvbih0eXBlLCBpbXBsKTtcbn1cblxudmFyIEtlcm5lbCA9IHtcbiAgU3BlY2lhbEZvcm1zLFxuICB0bCxcbiAgaGQsXG4gIGlzX25pbCxcbiAgaXNfYXRvbSxcbiAgaXNfYmluYXJ5LFxuICBpc19ib29sZWFuLFxuICBpc19mdW5jdGlvbixcbiAgaXNfZmxvYXQsXG4gIGlzX2ludGVnZXIsXG4gIGlzX2xpc3QsXG4gIGlzX21hcCxcbiAgaXNfbnVtYmVyLFxuICBpc190dXBsZSxcbiAgbGVuZ3RoLFxuICBpc19waWQsXG4gIGlzX3BvcnQsXG4gIGlzX3JlZmVyZW5jZSxcbiAgaXNfYml0c3RyaW5nLFxuICBpbjogX19pbl9fLFxuICBhYnMsXG4gIHJvdW5kLFxuICBlbGVtLFxuICByZW0sXG4gIGRpdixcbiAgYW5kLFxuICBvcixcbiAgbm90LFxuICBhcHBseSxcbiAgdG9fc3RyaW5nLFxuICBtYXRjaF9fcW1hcmtfXyxcbiAgZGVmc3RydWN0LFxuICBkZWZwcm90b2NvbCxcbiAgZGVmaW1wbFxufTtcblxubGV0IEF0b20gPSB7fTtcblxuQXRvbS50b19zdHJpbmcgPSBmdW5jdGlvbiAoYXRvbSkge1xuICByZXR1cm4gU3ltYm9sLmtleUZvcihhdG9tKTtcbn07XG5cbkF0b20udG9fY2hhcl9saXN0ID0gZnVuY3Rpb24gKGF0b20pIHtcbiAgcmV0dXJuIEF0b20udG9fc3RyaW5nKGF0b20pLnNwbGl0KCcnKTtcbn07XG5cbmxldCBJbnRlZ2VyID0ge1xuXG4gIGlzX2V2ZW46IGZ1bmN0aW9uIChuKSB7XG4gICAgcmV0dXJuIG4gJSAyID09PSAwO1xuICB9LFxuXG4gIGlzX29kZDogZnVuY3Rpb24gKG4pIHtcbiAgICByZXR1cm4gbiAlIDIgIT09IDA7XG4gIH0sXG5cbiAgcGFyc2U6IGZ1bmN0aW9uIChiaW4pIHtcbiAgICBsZXQgcmVzdWx0ID0gcGFyc2VJbnQoYmluKTtcblxuICAgIGlmIChpc05hTihyZXN1bHQpKSB7XG4gICAgICByZXR1cm4gS2VybmVsLlNwZWNpYWxGb3Jtcy5hdG9tKFwiZXJyb3JcIik7XG4gICAgfVxuXG4gICAgbGV0IGluZGV4T2ZEb3QgPSBiaW4uaW5kZXhPZihcIi5cIik7XG5cbiAgICBpZiAoaW5kZXhPZkRvdCA+PSAwKSB7XG4gICAgICByZXR1cm4gS2VybmVsLlNwZWNpYWxGb3Jtcy50dXBsZShyZXN1bHQsIGJpbi5zdWJzdHJpbmcoaW5kZXhPZkRvdCkpO1xuICAgIH1cblxuICAgIHJldHVybiBLZXJuZWwuU3BlY2lhbEZvcm1zLnR1cGxlKHJlc3VsdCwgXCJcIik7XG4gIH0sXG5cbiAgdG9fY2hhcl9saXN0OiBmdW5jdGlvbiAobnVtYmVyLCBiYXNlID0gMTApIHtcbiAgICByZXR1cm4gbnVtYmVyLnRvU3RyaW5nKGJhc2UpLnNwbGl0KFwiXCIpO1xuICB9LFxuXG4gIHRvX3N0cmluZzogZnVuY3Rpb24gKG51bWJlciwgYmFzZSA9IDEwKSB7XG4gICAgcmV0dXJuIG51bWJlci50b1N0cmluZyhiYXNlKTtcbiAgfVxufTtcblxubGV0IENoYXJzJDEgPSBLZXJuZWwuZGVmcHJvdG9jb2woe1xuICB0b19zdHJpbmc6IGZ1bmN0aW9uICh0aGluZykge31cbn0pO1xuXG5LZXJuZWwuZGVmaW1wbChDaGFycyQxLCBCaXRTdHJpbmcsIHtcbiAgdG9fc3RyaW5nOiBmdW5jdGlvbiAodGhpbmcpIHtcbiAgICBpZiAoS2VybmVsLmlzX2JpbmFyeSh0aGluZykpIHtcbiAgICAgIHJldHVybiB0aGluZztcbiAgICB9XG5cbiAgICByZXR1cm4gdGhpbmcudG9TdHJpbmcoKTtcbiAgfVxufSk7XG5cbktlcm5lbC5kZWZpbXBsKENoYXJzJDEsIFN5bWJvbCwge1xuICB0b19zdHJpbmc6IGZ1bmN0aW9uICh0aGluZykge1xuICAgIGlmIChuaWwpIHtcbiAgICAgIHJldHVybiBcIlwiO1xuICAgIH1cblxuICAgIHJldHVybiBBdG9tLnRvX3N0cmluZyh0aGluZyk7XG4gIH1cbn0pO1xuXG5LZXJuZWwuZGVmaW1wbChDaGFycyQxLCBJbnRlZ2VyJDEsIHtcbiAgdG9fc3RyaW5nOiBmdW5jdGlvbiAodGhpbmcpIHtcbiAgICByZXR1cm4gSW50ZWdlci50b19zdHJpbmcodGhpbmcpO1xuICB9XG59KTtcblxuS2VybmVsLmRlZmltcGwoQ2hhcnMkMSwgRmxvYXQsIHtcbiAgdG9fc3RyaW5nOiBmdW5jdGlvbiAodGhpbmcpIHtcbiAgICByZXR1cm4gdGhpbmcudG9TdHJpbmc7XG4gIH1cbn0pO1xuXG5LZXJuZWwuZGVmaW1wbChDaGFycyQxLCBBcnJheSwge1xuICB0b19zdHJpbmc6IGZ1bmN0aW9uICh0aGluZykge1xuICAgIHJldHVybiB0aGluZy50b1N0cmluZygpO1xuICB9XG59KTtcblxuS2VybmVsLmRlZmltcGwoQ2hhcnMkMSwgVHVwbGUkMSwge1xuICB0b19zdHJpbmc6IGZ1bmN0aW9uICh0aGluZykge1xuICAgIHJldHVybiBUdXBsZS50b19zdHJpbmcodGhpbmcpO1xuICB9XG59KTtcblxuS2VybmVsLmRlZmltcGwoQ2hhcnMkMSwgbnVsbCwge1xuICB0b19zdHJpbmc6IGZ1bmN0aW9uICh0aGluZykge1xuICAgIHJldHVybiB0aGluZy50b1N0cmluZygpO1xuICB9XG59KTtcblxuZnVuY3Rpb24gdG9fYXRvbShzdHJpbmcpIHtcbiAgcmV0dXJuIFN5bWJvbC5mb3Ioc3RyaW5nKTtcbn1cblxuZnVuY3Rpb24gdG9fZXhpc3RpbmdfYXRvbShzdHJpbmcpIHtcbiAgcmV0dXJuIFN5bWJvbC5mb3Ioc3RyaW5nKTtcbn1cblxuZnVuY3Rpb24gdG9fY2hhcl9saXN0KHN0cmluZykge1xuICByZXR1cm4gc3RyaW5nLnNwbGl0KCcnKTtcbn1cblxuZnVuY3Rpb24gdG9fZmxvYXQoc3RyaW5nKSB7XG4gIHJldHVybiBwYXJzZUZsb2F0KHN0cmluZyk7XG59XG5cbmZ1bmN0aW9uIHRvX2ludGVnZXIoc3RyaW5nLCBiYXNlID0gMTApIHtcbiAgcmV0dXJuIHBhcnNlSW50KHN0cmluZywgYmFzZSk7XG59XG5cbmZ1bmN0aW9uIHVwY2FzZShiaW5hcnkpIHtcbiAgcmV0dXJuIGJpbmFyeS50b1VwcGVyQ2FzZSgpO1xufVxuXG5mdW5jdGlvbiBkb3duY2FzZShiaW5hcnkpIHtcbiAgcmV0dXJuIGJpbmFyeS50b0xvd2VyQ2FzZSgpO1xufVxuXG5mdW5jdGlvbiBhdChzdHJpbmcsIHBvc2l0aW9uKSB7XG4gIGlmIChwb3NpdGlvbiA+IHN0cmluZy5sZW5ndGggLSAxKSB7XG4gICAgcmV0dXJuIG51bGw7XG4gIH1cblxuICByZXR1cm4gc3RyaW5nW3Bvc2l0aW9uXTtcbn1cblxuZnVuY3Rpb24gY2FwaXRhbGl6ZShzdHJpbmcpIHtcbiAgbGV0IHJldHVyblN0cmluZyA9ICcnO1xuXG4gIGZvciAobGV0IGkgPSAwOyBpIDwgc3RyaW5nLmxlbmd0aDsgaSsrKSB7XG4gICAgaWYgKGkgPT09IDApIHtcbiAgICAgIHJldHVyblN0cmluZyA9IHJldHVyblN0cmluZyArIHN0cmluZ1tpXS50b1VwcGVyQ2FzZSgpO1xuICAgIH0gZWxzZSB7XG4gICAgICByZXR1cm5TdHJpbmcgPSByZXR1cm5TdHJpbmcgKyBzdHJpbmdbaV0udG9Mb3dlckNhc2UoKTtcbiAgICB9XG4gIH1cblxuICByZXR1cm4gcmV0dXJuU3RyaW5nO1xufVxuXG5mdW5jdGlvbiBjb2RlcG9pbnRzKHN0cmluZykge1xuICByZXR1cm4gdG9fY2hhcl9saXN0KHN0cmluZykubWFwKGZ1bmN0aW9uIChjKSB7XG4gICAgcmV0dXJuIGMuY29kZVBvaW50QXQoMCk7XG4gIH0pO1xufVxuXG5mdW5jdGlvbiBjb250YWluc19fcW1fXyhzdHJpbmcsIGNvbnRhaW5zKSB7XG4gIGlmIChBcnJheS5pc0FycmF5KGNvbnRhaW5zKSkge1xuICAgIHJldHVybiBjb250YWlucy5zb21lKGZ1bmN0aW9uIChzKSB7XG4gICAgICByZXR1cm4gc3RyaW5nLmluZGV4T2YocykgPiAtMTtcbiAgICB9KTtcbiAgfVxuXG4gIHJldHVybiBzdHJpbmcuaW5kZXhPZihjb250YWlucykgPiAtMTtcbn1cblxuZnVuY3Rpb24gZHVwbGljYXRlJDEoc3ViamVjdCwgbikge1xuICByZXR1cm4gc3ViamVjdC5yZXBlYXQobik7XG59XG5cbmZ1bmN0aW9uIGVuZHNfd2l0aF9fcW1fXyhzdHJpbmcsIHN1ZmZpeGVzKSB7XG4gIGlmIChBcnJheS5pc0FycmF5KHN1ZmZpeGVzKSkge1xuICAgIHJldHVybiBzdWZmaXhlcy5zb21lKGZ1bmN0aW9uIChzKSB7XG4gICAgICByZXR1cm4gc3RyaW5nLmVuZHNXaXRoKHMpO1xuICAgIH0pO1xuICB9XG5cbiAgcmV0dXJuIHN0cmluZy5lbmRzV2l0aChzdWZmaXhlcyk7XG59XG5cbmZ1bmN0aW9uIGZpcnN0KHN0cmluZykge1xuICBpZiAoIXN0cmluZykge1xuICAgIHJldHVybiBudWxsO1xuICB9XG5cbiAgcmV0dXJuIHN0cmluZ1swXTtcbn1cblxuZnVuY3Rpb24gZ3JhcGhlbWVzKHN0cmluZykge1xuICByZXR1cm4gc3RyaW5nLnNwbGl0KCcnKTtcbn1cblxuZnVuY3Rpb24gbGFzdChzdHJpbmcpIHtcbiAgaWYgKCFzdHJpbmcpIHtcbiAgICByZXR1cm4gbnVsbDtcbiAgfVxuXG4gIHJldHVybiBzdHJpbmdbc3RyaW5nLmxlbmd0aCAtIDFdO1xufVxuXG5mdW5jdGlvbiBsZW5ndGgkMShzdHJpbmcpIHtcbiAgcmV0dXJuIHN0cmluZy5sZW5ndGg7XG59XG5cbmZ1bmN0aW9uIG1hdGNoX19xbV9fKHN0cmluZywgcmVnZXgpIHtcbiAgcmV0dXJuIHN0cmluZy5tYXRjaChyZWdleCkgIT0gbnVsbDtcbn1cblxuZnVuY3Rpb24gbmV4dF9jb2RlcG9pbnQoc3RyaW5nKSB7XG4gIGlmICghc3RyaW5nIHx8IHN0cmluZyA9PT0gJycpIHtcbiAgICByZXR1cm4gbnVsbDtcbiAgfVxuXG4gIHJldHVybiBLZXJuZWwuU3BlY2lhbEZvcm1zLnR1cGxlKHN0cmluZ1swXS5jb2RlUG9pbnRBdCgwKSwgc3RyaW5nLnN1YnN0cigxKSk7XG59XG5cbmZ1bmN0aW9uIG5leHRfZ3JhcGhlbWUoc3RyaW5nKSB7XG4gIGlmICghc3RyaW5nIHx8IHN0cmluZyA9PT0gJycpIHtcbiAgICByZXR1cm4gbnVsbDtcbiAgfVxuXG4gIHJldHVybiBLZXJuZWwuU3BlY2lhbEZvcm1zLnR1cGxlKHN0cmluZ1swXSwgc3RyaW5nLnN1YnN0cigxKSk7XG59XG5cbmZ1bmN0aW9uIHJldmVyc2Uoc3RyaW5nKSB7XG4gIGxldCByZXR1cm5WYWx1ZSA9ICcnO1xuXG4gIGZvciAodmFyIGkgPSBzdHJpbmcubGVuZ3RoIC0gMTsgaSA+PSAwOyBpLS0pIHtcbiAgICByZXR1cm5WYWx1ZSA9IHJldHVyblZhbHVlICsgc3RyaW5nW2ldO1xuICB9O1xuXG4gIHJldHVybiByZXR1cm5WYWx1ZTtcbn1cblxuZnVuY3Rpb24gc3BsaXQoc3RyaW5nKSB7XG4gIHJldHVybiBzdHJpbmcuc3BsaXQoKTtcbn1cblxuZnVuY3Rpb24gc3RhcnRzX3dpdGhfX3FtX18oc3RyaW5nLCBwcmVmaXhlcykge1xuICBpZiAoQXJyYXkuaXNBcnJheShwcmVmaXhlcykpIHtcbiAgICByZXR1cm4gcHJlZml4ZXMuc29tZShmdW5jdGlvbiAocykge1xuICAgICAgcmV0dXJuIHN0cmluZy5zdGFydHNXaXRoKHMpO1xuICAgIH0pO1xuICB9XG5cbiAgcmV0dXJuIHN0cmluZy5zdGFydHNXaXRoKHByZWZpeGVzKTtcbn1cblxuZnVuY3Rpb24gdmFsaWRfY2hhcmFjdGVyX19xbV9fKGNvZGVwb2ludCkge1xuICB0cnkge1xuICAgIHJldHVybiBTdHJpbmcuZnJvbUNvZGVQb2ludChjb2RlcG9pbnQpICE9IG51bGw7XG4gIH0gY2F0Y2ggKGUpIHtcbiAgICByZXR1cm4gZmFsc2U7XG4gIH1cbn1cblxudmFyIFN0cmluZyQxID0ge1xuICBhdCxcbiAgY2FwaXRhbGl6ZSxcbiAgY29kZXBvaW50cyxcbiAgY29udGFpbnNfX3FtX18sXG4gIGRvd25jYXNlLFxuICBkdXBsaWNhdGU6IGR1cGxpY2F0ZSQxLFxuICBlbmRzX3dpdGhfX3FtX18sXG4gIGZpcnN0LFxuICBncmFwaGVtZXMsXG4gIGxhc3QsXG4gIGxlbmd0aDogbGVuZ3RoJDEsXG4gIG1hdGNoX19xbV9fLFxuICBuZXh0X2NvZGVwb2ludCxcbiAgbmV4dF9ncmFwaGVtZSxcbiAgcmV2ZXJzZSxcbiAgc3BsaXQsXG4gIHN0YXJ0c193aXRoX19xbV9fLFxuICB0b19hdG9tLFxuICB0b19jaGFyX2xpc3QsXG4gIHRvX2V4aXN0aW5nX2F0b20sXG4gIHRvX2Zsb2F0LFxuICB0b19pbnRlZ2VyLFxuICB1cGNhc2UsXG4gIHZhbGlkX2NoYXJhY3Rlcl9fcW1fXyxcbiAgQ2hhcnM6IENoYXJzJDFcbn07XG5cbmxldCBDaGFycyA9IEtlcm5lbC5kZWZwcm90b2NvbCh7XG4gIHRvX2NoYXJfbGlzdDogZnVuY3Rpb24gKHRoaW5nKSB7fVxufSk7XG5cbktlcm5lbC5kZWZpbXBsKENoYXJzLCBCaXRTdHJpbmcsIHtcbiAgdG9fY2hhcl9saXN0OiBmdW5jdGlvbiAodGhpbmcpIHtcbiAgICBpZiAoS2VybmVsLmlzX2JpbmFyeSh0aGluZykpIHtcbiAgICAgIHJldHVybiBTdHJpbmckMS50b19jaGFyX2xpc3QodGhpbmcpO1xuICAgIH1cblxuICAgIHJldHVybiB0aGluZy50b1N0cmluZygpO1xuICB9XG59KTtcblxuS2VybmVsLmRlZmltcGwoQ2hhcnMsIFN5bWJvbCwge1xuICB0b19jaGFyX2xpc3Q6IGZ1bmN0aW9uICh0aGluZykge1xuICAgIHJldHVybiBBdG9tLnRvX2NoYXJfbGlzdCh0aGluZyk7XG4gIH1cbn0pO1xuXG5LZXJuZWwuZGVmaW1wbChDaGFycywgSW50ZWdlciQxLCB7XG4gIHRvX2NoYXJfbGlzdDogZnVuY3Rpb24gKHRoaW5nKSB7XG4gICAgcmV0dXJuIEludGVnZXIudG9fY2hhcl9saXN0KHRoaW5nKTtcbiAgfVxufSk7XG5cbktlcm5lbC5kZWZpbXBsKENoYXJzLCBBcnJheSwge1xuICB0b19jaGFyX2xpc3Q6IGZ1bmN0aW9uICh0aGluZykge1xuICAgIHJldHVybiB0aGluZztcbiAgfVxufSk7XG5cbmxldCBMaXN0ID0ge307XG5cbkxpc3QuQ2hhcnMgPSBDaGFycztcblxuTGlzdC5kZWxldGUgPSBmdW5jdGlvbiAobGlzdCwgaXRlbSkge1xuICBsZXQgbmV3X3ZhbHVlID0gW107XG4gIGxldCB2YWx1ZV9mb3VuZCA9IGZhbHNlO1xuXG4gIGZvciAobGV0IHggb2YgbGlzdCkge1xuICAgIGlmICh4ID09PSBpdGVtICYmIHZhbHVlX2ZvdW5kICE9PSBmYWxzZSkge1xuICAgICAgbmV3X3ZhbHVlLnB1c2goeCk7XG4gICAgICB2YWx1ZV9mb3VuZCA9IHRydWU7XG4gICAgfSBlbHNlIGlmICh4ICE9PSBpdGVtKSB7XG4gICAgICBuZXdfdmFsdWUucHVzaCh4KTtcbiAgICB9XG4gIH1cblxuICByZXR1cm4gS2VybmVsLlNwZWNpYWxGb3Jtcy5saXN0KC4uLm5ld192YWx1ZSk7XG59O1xuXG5MaXN0LmRlbGV0ZV9hdCA9IGZ1bmN0aW9uIChsaXN0LCBpbmRleCkge1xuICBsZXQgbmV3X3ZhbHVlID0gW107XG5cbiAgZm9yIChsZXQgaSA9IDA7IGkgPCBsaXN0Lmxlbmd0aDsgaSsrKSB7XG4gICAgaWYgKGkgIT09IGluZGV4KSB7XG4gICAgICBuZXdfdmFsdWUucHVzaChsaXN0W2ldKTtcbiAgICB9XG4gIH1cblxuICByZXR1cm4gS2VybmVsLlNwZWNpYWxGb3Jtcy5saXN0KC4uLm5ld192YWx1ZSk7XG59O1xuXG5MaXN0LmR1cGxpY2F0ZSA9IGZ1bmN0aW9uIChlbGVtLCBuKSB7XG4gIGxldCBuZXdfdmFsdWUgPSBbXTtcblxuICBmb3IgKHZhciBpID0gMDsgaSA8IG47IGkrKykge1xuICAgIG5ld192YWx1ZS5wdXNoKGVsZW0pO1xuICB9XG5cbiAgcmV0dXJuIEtlcm5lbC5TcGVjaWFsRm9ybXMubGlzdCguLi5uZXdfdmFsdWUpO1xufTtcblxuTGlzdC5maXJzdCA9IGZ1bmN0aW9uIChsaXN0KSB7XG4gIHJldHVybiBsaXN0WzBdO1xufTtcblxuTGlzdC5mbGF0dGVuID0gZnVuY3Rpb24gKGxpc3QsIHRhaWwgPSBLZXJuZWwuU3BlY2lhbEZvcm1zLmxpc3QoKSkge1xuICBsZXQgbmV3X3ZhbHVlID0gW107XG5cbiAgZm9yIChsZXQgeCBvZiBsaXN0KSB7XG4gICAgaWYgKEtlcm5lbC5pc19saXN0KHgpKSB7XG4gICAgICBuZXdfdmFsdWUgPSBuZXdfdmFsdWUuY29uY2F0KExpc3QuZmxhdHRlbih4KSk7XG4gICAgfSBlbHNlIHtcbiAgICAgIG5ld192YWx1ZS5wdXNoKHgpO1xuICAgIH1cbiAgfVxuXG4gIG5ld192YWx1ZSA9IG5ld192YWx1ZS5jb25jYXQodGFpbCk7XG5cbiAgcmV0dXJuIEtlcm5lbC5TcGVjaWFsRm9ybXMubGlzdCguLi5uZXdfdmFsdWUpO1xufTtcblxuTGlzdC5mb2xkbCA9IGZ1bmN0aW9uIChsaXN0LCBhY2MsIGZ1bmMpIHtcbiAgcmV0dXJuIGxpc3QucmVkdWNlKGZ1bmMsIGFjYyk7XG59O1xuXG5MaXN0LmZvbGRyID0gZnVuY3Rpb24gKGxpc3QsIGFjYywgZnVuYykge1xuICBsZXQgbmV3X2FjYyA9IGFjYztcblxuICBmb3IgKHZhciBpID0gbGlzdC5sZW5ndGggLSAxOyBpID49IDA7IGktLSkge1xuICAgIG5ld19hY2MgPSBmdW5jKGxpc3RbaV0sIG5ld19hY2MpO1xuICB9XG5cbiAgcmV0dXJuIG5ld19hY2M7XG59O1xuXG5MaXN0Lmluc2VydF9hdCA9IGZ1bmN0aW9uIChsaXN0LCBpbmRleCwgdmFsdWUpIHtcbiAgbGV0IG5ld192YWx1ZSA9IFtdO1xuXG4gIGZvciAobGV0IGkgPSAwOyBpIDwgbGlzdC5sZW5ndGg7IGkrKykge1xuICAgIGlmIChpID09PSBpbmRleCkge1xuICAgICAgbmV3X3ZhbHVlLnB1c2godmFsdWUpO1xuICAgICAgbmV3X3ZhbHVlLnB1c2gobGlzdFtpXSk7XG4gICAgfSBlbHNlIHtcbiAgICAgIG5ld192YWx1ZS5wdXNoKGxpc3RbaV0pO1xuICAgIH1cbiAgfVxuXG4gIHJldHVybiBLZXJuZWwuU3BlY2lhbEZvcm1zLmxpc3QoLi4ubmV3X3ZhbHVlKTtcbn07XG5cbkxpc3Qua2V5ZGVsZXRlID0gZnVuY3Rpb24gKGxpc3QsIGtleSwgcG9zaXRpb24pIHtcbiAgbGV0IG5ld19saXN0ID0gW107XG5cbiAgZm9yIChsZXQgaSA9IDA7IGkgPCBsaXN0Lmxlbmd0aDsgaSsrKSB7XG4gICAgaWYgKCFLZXJuZWwubWF0Y2hfX3FtYXJrX18obGlzdFtpXVtwb3NpdGlvbl0sIGtleSkpIHtcbiAgICAgIG5ld19saXN0LnB1c2gobGlzdFtpXSk7XG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIEtlcm5lbC5TcGVjaWFsRm9ybXMubGlzdCguLi5uZXdfbGlzdCk7XG59O1xuXG5MaXN0LmtleWZpbmQgPSBmdW5jdGlvbiAobGlzdCwga2V5LCBwb3NpdGlvbiwgX2RlZmF1bHQgPSBudWxsKSB7XG5cbiAgZm9yIChsZXQgaSA9IDA7IGkgPCBsaXN0Lmxlbmd0aDsgaSsrKSB7XG4gICAgaWYgKEtlcm5lbC5tYXRjaF9fcW1hcmtfXyhsaXN0W2ldW3Bvc2l0aW9uXSwga2V5KSkge1xuICAgICAgcmV0dXJuIGxpc3RbaV07XG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIF9kZWZhdWx0O1xufTtcblxuTGlzdC5rZXltZW1iZXJfX3FtYXJrX18gPSBmdW5jdGlvbiAobGlzdCwga2V5LCBwb3NpdGlvbikge1xuXG4gIGZvciAobGV0IGkgPSAwOyBpIDwgbGlzdC5sZW5ndGg7IGkrKykge1xuICAgIGlmIChLZXJuZWwubWF0Y2hfX3FtYXJrX18obGlzdFtpXVtwb3NpdGlvbl0sIGtleSkpIHtcbiAgICAgIHJldHVybiB0cnVlO1xuICAgIH1cbiAgfVxuXG4gIHJldHVybiBmYWxzZTtcbn07XG5cbkxpc3Qua2V5cmVwbGFjZSA9IGZ1bmN0aW9uIChsaXN0LCBrZXksIHBvc2l0aW9uLCBuZXdfdHVwbGUpIHtcbiAgbGV0IG5ld19saXN0ID0gW107XG5cbiAgZm9yIChsZXQgaSA9IDA7IGkgPCBsaXN0Lmxlbmd0aDsgaSsrKSB7XG4gICAgaWYgKCFLZXJuZWwubWF0Y2hfX3FtYXJrX18obGlzdFtpXVtwb3NpdGlvbl0sIGtleSkpIHtcbiAgICAgIG5ld19saXN0LnB1c2gobGlzdFtpXSk7XG4gICAgfSBlbHNlIHtcbiAgICAgIG5ld19saXN0LnB1c2gobmV3X3R1cGxlKTtcbiAgICB9XG4gIH1cblxuICByZXR1cm4gS2VybmVsLlNwZWNpYWxGb3Jtcy5saXN0KC4uLm5ld19saXN0KTtcbn07XG5cbkxpc3Qua2V5c29ydCA9IGZ1bmN0aW9uIChsaXN0LCBwb3NpdGlvbikge1xuICBsZXQgbmV3X2xpc3QgPSBsaXN0O1xuXG4gIG5ld19saXN0LnNvcnQoZnVuY3Rpb24gKGEsIGIpIHtcbiAgICBpZiAocG9zaXRpb24gPT09IDApIHtcbiAgICAgIGlmIChhW3Bvc2l0aW9uXS52YWx1ZSA8IGJbcG9zaXRpb25dLnZhbHVlKSB7XG4gICAgICAgIHJldHVybiAtMTtcbiAgICAgIH1cblxuICAgICAgaWYgKGFbcG9zaXRpb25dLnZhbHVlID4gYltwb3NpdGlvbl0udmFsdWUpIHtcbiAgICAgICAgcmV0dXJuIDE7XG4gICAgICB9XG5cbiAgICAgIHJldHVybiAwO1xuICAgIH0gZWxzZSB7XG4gICAgICBpZiAoYVtwb3NpdGlvbl0gPCBiW3Bvc2l0aW9uXSkge1xuICAgICAgICByZXR1cm4gLTE7XG4gICAgICB9XG5cbiAgICAgIGlmIChhW3Bvc2l0aW9uXSA+IGJbcG9zaXRpb25dKSB7XG4gICAgICAgIHJldHVybiAxO1xuICAgICAgfVxuXG4gICAgICByZXR1cm4gMDtcbiAgICB9XG4gIH0pO1xuXG4gIHJldHVybiBLZXJuZWwuU3BlY2lhbEZvcm1zLmxpc3QoLi4ubmV3X2xpc3QpO1xufTtcblxuTGlzdC5rZXlzdG9yZSA9IGZ1bmN0aW9uIChsaXN0LCBrZXksIHBvc2l0aW9uLCBuZXdfdHVwbGUpIHtcbiAgbGV0IG5ld19saXN0ID0gW107XG4gIGxldCByZXBsYWNlZCA9IGZhbHNlO1xuXG4gIGZvciAobGV0IGkgPSAwOyBpIDwgbGlzdC5sZW5ndGg7IGkrKykge1xuICAgIGlmICghS2VybmVsLm1hdGNoX19xbWFya19fKGxpc3RbaV1bcG9zaXRpb25dLCBrZXkpKSB7XG4gICAgICBuZXdfbGlzdC5wdXNoKGxpc3RbaV0pO1xuICAgIH0gZWxzZSB7XG4gICAgICBuZXdfbGlzdC5wdXNoKG5ld190dXBsZSk7XG4gICAgICByZXBsYWNlZCA9IHRydWU7XG4gICAgfVxuICB9XG5cbiAgaWYgKCFyZXBsYWNlZCkge1xuICAgIG5ld19saXN0LnB1c2gobmV3X3R1cGxlKTtcbiAgfVxuXG4gIHJldHVybiBLZXJuZWwuU3BlY2lhbEZvcm1zLmxpc3QoLi4ubmV3X2xpc3QpO1xufTtcblxuTGlzdC5sYXN0ID0gZnVuY3Rpb24gKGxpc3QpIHtcbiAgcmV0dXJuIGxpc3RbbGlzdC5sZW5ndGggLSAxXTtcbn07XG5cbkxpc3QucmVwbGFjZV9hdCA9IGZ1bmN0aW9uIChsaXN0LCBpbmRleCwgdmFsdWUpIHtcbiAgbGV0IG5ld192YWx1ZSA9IFtdO1xuXG4gIGZvciAobGV0IGkgPSAwOyBpIDwgbGlzdC5sZW5ndGg7IGkrKykge1xuICAgIGlmIChpID09PSBpbmRleCkge1xuICAgICAgbmV3X3ZhbHVlLnB1c2godmFsdWUpO1xuICAgIH0gZWxzZSB7XG4gICAgICBuZXdfdmFsdWUucHVzaChsaXN0W2ldKTtcbiAgICB9XG4gIH1cblxuICByZXR1cm4gS2VybmVsLlNwZWNpYWxGb3Jtcy5saXN0KC4uLm5ld192YWx1ZSk7XG59O1xuXG5MaXN0LnVwZGF0ZV9hdCA9IGZ1bmN0aW9uIChsaXN0LCBpbmRleCwgZnVuKSB7XG4gIGxldCBuZXdfdmFsdWUgPSBbXTtcblxuICBmb3IgKGxldCBpID0gMDsgaSA8IGxpc3QuY291bnQoKTsgaSsrKSB7XG4gICAgaWYgKGkgPT09IGluZGV4KSB7XG4gICAgICBuZXdfdmFsdWUucHVzaChmdW4obGlzdC5nZXQoaSkpKTtcbiAgICB9IGVsc2Uge1xuICAgICAgbmV3X3ZhbHVlLnB1c2gobGlzdC5nZXQoaSkpO1xuICAgIH1cbiAgfVxuXG4gIHJldHVybiBuZXdfdmFsdWU7XG59O1xuXG5MaXN0LndyYXAgPSBmdW5jdGlvbiAobGlzdCkge1xuICBpZiAoS2VybmVsLmlzX2xpc3QobGlzdCkpIHtcbiAgICByZXR1cm4gbGlzdDtcbiAgfSBlbHNlIGlmIChsaXN0ID09IG51bGwpIHtcbiAgICByZXR1cm4gS2VybmVsLlNwZWNpYWxGb3Jtcy5saXN0KCk7XG4gIH0gZWxzZSB7XG4gICAgcmV0dXJuIEtlcm5lbC5TcGVjaWFsRm9ybXMubGlzdChsaXN0KTtcbiAgfVxufTtcblxuTGlzdC56aXAgPSBmdW5jdGlvbiAobGlzdF9vZl9saXN0cykge1xuICBpZiAobGlzdF9vZl9saXN0cy5sZW5ndGggPT09IDApIHtcbiAgICByZXR1cm4gS2VybmVsLlNwZWNpYWxGb3Jtcy5saXN0KCk7XG4gIH1cblxuICBsZXQgbmV3X3ZhbHVlID0gW107XG4gIGxldCBzbWFsbGVzdF9sZW5ndGggPSBsaXN0X29mX2xpc3RzWzBdO1xuXG4gIGZvciAobGV0IHggb2YgbGlzdF9vZl9saXN0cykge1xuICAgIGlmICh4Lmxlbmd0aCA8IHNtYWxsZXN0X2xlbmd0aCkge1xuICAgICAgc21hbGxlc3RfbGVuZ3RoID0geC5sZW5ndGg7XG4gICAgfVxuICB9XG5cbiAgZm9yIChsZXQgaSA9IDA7IGkgPCBzbWFsbGVzdF9sZW5ndGg7IGkrKykge1xuICAgIGxldCBjdXJyZW50X3ZhbHVlID0gW107XG4gICAgZm9yIChsZXQgaiA9IDA7IGogPCBsaXN0X29mX2xpc3RzLmxlbmd0aDsgaisrKSB7XG4gICAgICBjdXJyZW50X3ZhbHVlLnB1c2gobGlzdF9vZl9saXN0c1tqXVtpXSk7XG4gICAgfVxuXG4gICAgbmV3X3ZhbHVlLnB1c2goS2VybmVsLlNwZWNpYWxGb3Jtcy50dXBsZSguLi5jdXJyZW50X3ZhbHVlKSk7XG4gIH1cblxuICByZXR1cm4gS2VybmVsLlNwZWNpYWxGb3Jtcy5saXN0KC4uLm5ld192YWx1ZSk7XG59O1xuXG5MaXN0LnRvX3R1cGxlID0gZnVuY3Rpb24gKGxpc3QpIHtcbiAgcmV0dXJuIEtlcm5lbC5TcGVjaWFsRm9ybXMudHVwbGUuYXBwbHkobnVsbCwgbGlzdCk7XG59O1xuXG5MaXN0LmFwcGVuZCA9IGZ1bmN0aW9uIChsaXN0LCB2YWx1ZSkge1xuICByZXR1cm4gS2VybmVsLlNwZWNpYWxGb3Jtcy5saXN0KC4uLmxpc3QuY29uY2F0KFt2YWx1ZV0pKTtcbn07XG5cbkxpc3QucHJlcGVuZCA9IGZ1bmN0aW9uIChsaXN0LCB2YWx1ZSkge1xuICByZXR1cm4gS2VybmVsLlNwZWNpYWxGb3Jtcy5saXN0KC4uLlt2YWx1ZV0uY29uY2F0KGxpc3QpKTtcbn07XG5cbkxpc3QuY29uY2F0ID0gZnVuY3Rpb24gKGxlZnQsIHJpZ2h0KSB7XG4gIHJldHVybiBsZWZ0LmNvbmNhdChyaWdodCk7XG59O1xuXG5sZXQgUmFuZ2UgPSBmdW5jdGlvbiAoX2ZpcnN0LCBfbGFzdCkge1xuICBpZiAoISh0aGlzIGluc3RhbmNlb2YgUmFuZ2UpKSB7XG4gICAgcmV0dXJuIG5ldyBSYW5nZShfZmlyc3QsIF9sYXN0KTtcbiAgfVxuXG4gIHRoaXMuZmlyc3QgPSBmdW5jdGlvbiAoKSB7XG4gICAgcmV0dXJuIF9maXJzdDtcbiAgfTtcblxuICB0aGlzLmxhc3QgPSBmdW5jdGlvbiAoKSB7XG4gICAgcmV0dXJuIF9sYXN0O1xuICB9O1xuXG4gIGxldCBfcmFuZ2UgPSBbXTtcblxuICBmb3IgKGxldCBpID0gX2ZpcnN0OyBpIDw9IF9sYXN0OyBpKyspIHtcbiAgICBfcmFuZ2UucHVzaChpKTtcbiAgfVxuXG4gIF9yYW5nZSA9IE9iamVjdC5mcmVlemUoX3JhbmdlKTtcblxuICB0aGlzLnZhbHVlID0gZnVuY3Rpb24gKCkge1xuICAgIHJldHVybiBfcmFuZ2U7XG4gIH07XG5cbiAgdGhpcy5sZW5ndGggPSBmdW5jdGlvbiAoKSB7XG4gICAgcmV0dXJuIF9yYW5nZS5sZW5ndGg7XG4gIH07XG5cbiAgcmV0dXJuIHRoaXM7XG59O1xuXG5SYW5nZS5wcm90b3R5cGVbU3ltYm9sLml0ZXJhdG9yXSA9IGZ1bmN0aW9uICgpIHtcbiAgcmV0dXJuIHRoaXMudmFsdWUoKVtTeW1ib2wuaXRlcmF0b3JdKCk7XG59O1xuXG5SYW5nZS5uZXcgPSBmdW5jdGlvbiAoZmlyc3QsIGxhc3QpIHtcbiAgcmV0dXJuIFJhbmdlKGZpcnN0LCBsYXN0KTtcbn07XG5cblJhbmdlLnJhbmdlX19xbWFya19fID0gZnVuY3Rpb24gKHJhbmdlKSB7XG4gIHJldHVybiByYW5nZSBpbnN0YW5jZW9mIFJhbmdlO1xufTtcblxubGV0IEtleXdvcmQgPSB7fTtcblxuS2V5d29yZC5oYXNfa2V5X19xbV9fID0gZnVuY3Rpb24gKGtleXdvcmRzLCBrZXkpIHtcbiAgZm9yIChsZXQga2V5d29yZCBvZiBrZXl3b3Jkcykge1xuICAgIGlmIChLZXJuZWwuZWxlbShrZXl3b3JkLCAwKSA9PSBrZXkpIHtcbiAgICAgIHJldHVybiB0cnVlO1xuICAgIH1cbiAgfVxuXG4gIHJldHVybiBmYWxzZTtcbn07XG5cbktleXdvcmQuZ2V0ID0gZnVuY3Rpb24gKGtleXdvcmRzLCBrZXksIHRoZV9kZWZhdWx0ID0gbnVsbCkge1xuICBmb3IgKGxldCBrZXl3b3JkIG9mIGtleXdvcmRzKSB7XG4gICAgaWYgKEtlcm5lbC5lbGVtKGtleXdvcmQsIDApID09IGtleSkge1xuICAgICAgcmV0dXJuIEtlcm5lbC5lbGVtKGtleXdvcmQsIDEpO1xuICAgIH1cbiAgfVxuXG4gIHJldHVybiB0aGVfZGVmYXVsdDtcbn07XG5cbmxldCBBZ2VudCA9IHt9O1xuXG5BZ2VudC5zdGFydCA9IGZ1bmN0aW9uIChmdW4sIG9wdGlvbnMgPSBbXSkge1xuICBsZXQgcGlkID0gc2VsZi5wcm9jZXNzZXMuc3Bhd24oKTtcblxuICBpZiAoS2V5d29yZC5oYXNfa2V5X19xbV9fKG9wdGlvbnMsIEtlcm5lbC5TcGVjaWFsRm9ybXMuYXRvbSgnbmFtZScpKSkge1xuICAgIHBpZCA9IHNlbGYucHJvY2Vzc2VzLnJlZ2lzdGVyKEtleXdvcmQuZ2V0KG9wdGlvbnMsIEtlcm5lbC5TcGVjaWFsRm9ybXMuYXRvbSgnbmFtZScpKSwgcGlkKTtcbiAgfVxuXG4gIHNlbGYucHJvY2Vzc2VzLnB1dChwaWQsICdzdGF0ZScsIGZ1bigpKTtcbiAgcmV0dXJuIEtlcm5lbC5TcGVjaWFsRm9ybXMudHVwbGUoS2VybmVsLlNwZWNpYWxGb3Jtcy5hdG9tKCdvaycpLCBwaWQpO1xufTtcblxuQWdlbnQuc3RvcCA9IGZ1bmN0aW9uIChhZ2VudCwgdGltZW91dCA9IDUwMDApIHtcbiAgc2VsZi5wcm9jZXNzZXMuZXhpdChhZ2VudCk7XG4gIHJldHVybiBLZXJuZWwuU3BlY2lhbEZvcm1zLmF0b20oJ29rJyk7XG59O1xuXG5BZ2VudC51cGRhdGUgPSBmdW5jdGlvbiAoYWdlbnQsIGZ1biwgdGltZW91dCA9IDUwMDApIHtcblxuICBjb25zdCBjdXJyZW50X3N0YXRlID0gc2VsZi5wcm9jZXNzZXMuZ2V0KGFnZW50LCAnc3RhdGUnKTtcbiAgc2VsZi5wcm9jZXNzZXMucHV0KGFnZW50LCAnc3RhdGUnLCBmdW4oY3VycmVudF9zdGF0ZSkpO1xuXG4gIHJldHVybiBLZXJuZWwuU3BlY2lhbEZvcm1zLmF0b20oJ29rJyk7XG59O1xuXG5BZ2VudC5nZXQgPSBmdW5jdGlvbiAoYWdlbnQsIGZ1biwgdGltZW91dCA9IDUwMDApIHtcbiAgcmV0dXJuIGZ1bihzZWxmLnByb2Nlc3Nlcy5nZXQoYWdlbnQsICdzdGF0ZScpKTtcbn07XG5cbkFnZW50LmdldF9hbmRfdXBkYXRlID0gZnVuY3Rpb24gKGFnZW50LCBmdW4sIHRpbWVvdXQgPSA1MDAwKSB7XG5cbiAgY29uc3QgZ2V0X2FuZF91cGRhdGVfdHVwbGUgPSBmdW4oc2VsZi5wcm9jZXNzZXMuZ2V0KGFnZW50LCAnc3RhdGUnKSk7XG4gIHNlbGYucHJvY2Vzc2VzLnB1dChhZ2VudCwgJ3N0YXRlJywgS2VybmVsLmVsZW0oZ2V0X2FuZF91cGRhdGVfdHVwbGUsIDEpKTtcblxuICByZXR1cm4gS2VybmVsLmVsZW0oZ2V0X2FuZF91cGRhdGVfdHVwbGUsIDApO1xufTtcblxuLy9odHRwczovL2RldmVsb3Blci5tb3ppbGxhLm9yZy9lbi1VUy9kb2NzL1dlYi9BUEkvV2luZG93QmFzZTY0L0Jhc2U2NF9lbmNvZGluZ19hbmRfZGVjb2RpbmcjU29sdXRpb25fMl8lRTIlODAlOTNfcmV3cml0ZV90aGVfRE9Nc19hdG9iKClfYW5kX2J0b2EoKV91c2luZ19KYXZhU2NyaXB0J3NfVHlwZWRBcnJheXNfYW5kX1VURi04XG5mdW5jdGlvbiBiNjRFbmNvZGVVbmljb2RlKHN0cikge1xuICByZXR1cm4gYnRvYShlbmNvZGVVUklDb21wb25lbnQoc3RyKS5yZXBsYWNlKC8lKFswLTlBLUZdezJ9KS9nLCBmdW5jdGlvbiAobWF0Y2gsIHAxKSB7XG4gICAgcmV0dXJuIFN0cmluZy5mcm9tQ2hhckNvZGUoJzB4JyArIHAxKTtcbiAgfSkpO1xufVxuXG5mdW5jdGlvbiBlbmNvZGU2NChkYXRhKSB7XG4gIHJldHVybiBiNjRFbmNvZGVVbmljb2RlKGRhdGEpO1xufVxuXG5mdW5jdGlvbiBkZWNvZGU2NChkYXRhKSB7XG4gIHRyeSB7XG4gICAgcmV0dXJuIEtlcm5lbC5TcGVjaWFsRm9ybXMudHVwbGUoS2VybmVsLlNwZWNpYWxGb3Jtcy5hdG9tKCdvaycpLCBhdG9iKGRhdGEpKTtcbiAgfSBjYXRjaCAoZSkge1xuICAgIHJldHVybiBLZXJuZWwuU3BlY2lhbEZvcm1zLmF0b20oJ2Vycm9yJyk7XG4gIH1cbiAgcmV0dXJuIGJ0b2EoZGF0YSk7XG59XG5cbmZ1bmN0aW9uIGRlY29kZTY0X19lbV9fKGRhdGEpIHtcbiAgcmV0dXJuIGF0b2IoZGF0YSk7XG59XG5cbnZhciBiYXNlID0ge1xuICBlbmNvZGU2NCxcbiAgZGVjb2RlNjQsXG4gIGRlY29kZTY0X19lbV9fXG59O1xuXG5mdW5jdGlvbiBibm90KGV4cHIpIHtcbiAgcmV0dXJuIH5leHByO1xufVxuXG5mdW5jdGlvbiBiYW5kKGxlZnQsIHJpZ2h0KSB7XG4gIHJldHVybiBsZWZ0ICYgcmlnaHQ7XG59XG5cbmZ1bmN0aW9uIGJvcihsZWZ0LCByaWdodCkge1xuICByZXR1cm4gbGVmdCB8IHJpZ2h0O1xufVxuXG5mdW5jdGlvbiBic2wobGVmdCwgcmlnaHQpIHtcbiAgcmV0dXJuIGxlZnQgPDwgcmlnaHQ7XG59XG5cbmZ1bmN0aW9uIGJzcihsZWZ0LCByaWdodCkge1xuICByZXR1cm4gbGVmdCA+PiByaWdodDtcbn1cblxuZnVuY3Rpb24gYnhvcihsZWZ0LCByaWdodCkge1xuICByZXR1cm4gbGVmdCBeIHJpZ2h0O1xufVxuXG52YXIgYml0d2lzZSA9IHtcbiAgYm5vdCxcbiAgYmFuZCxcbiAgYm9yLFxuICBic2wsXG4gIGJzcixcbiAgYnhvclxufTtcblxubGV0IEVudW1lcmFibGUgPSBLZXJuZWwuZGVmcHJvdG9jb2woe1xuICBjb3VudDogZnVuY3Rpb24gKGNvbGxlY3Rpb24pIHt9LFxuICBtZW1iZXJfcW1hcmtfXzogZnVuY3Rpb24gKGNvbGxlY3Rpb24sIHZhbHVlKSB7fSxcbiAgcmVkdWNlOiBmdW5jdGlvbiAoY29sbGVjdGlvbiwgYWNjLCBmdW4pIHt9XG59KTtcblxubGV0IENvbGxlY3RhYmxlID0gS2VybmVsLmRlZnByb3RvY29sKHtcbiAgaW50bzogZnVuY3Rpb24gKGNvbGxlY3RhYmxlKSB7fVxufSk7XG5cbmxldCBJbnNwZWN0ID0gS2VybmVsLmRlZnByb3RvY29sKHtcbiAgaW5zcGVjdDogZnVuY3Rpb24gKHRoaW5nLCBvcHRzKSB7fVxufSk7XG5cbmZ1bmN0aW9uIF9fbmV3X18oKSB7XG4gIHJldHVybiBTcGVjaWFsRm9ybXMubWFwKHt9KTtcbn1cblxuZnVuY3Rpb24ga2V5cyhtYXApIHtcbiAgcmV0dXJuIE9iamVjdC5rZXlzKG1hcCk7XG59XG5cbmZ1bmN0aW9uIHNpemUobWFwKSB7XG4gIHJldHVybiBrZXlzKG1hcCkubGVuZ3RoO1xufVxuXG5mdW5jdGlvbiB0b19saXN0JDEobWFwKSB7XG4gIGxldCBtYXBfa2V5cyA9IGtleXMobWFwKTtcbiAgbGV0IGxpc3QgPSBbXTtcblxuICBmb3IgKGxldCBrZXkgb2YgbWFwX2tleXMpIHtcbiAgICBsaXN0LnB1c2goU3BlY2lhbEZvcm1zLnR1cGxlKGtleSwgbWFwW2tleV0pKTtcbiAgfVxuXG4gIHJldHVybiBTcGVjaWFsRm9ybXMubGlzdCguLi5saXN0KTtcbn1cblxuZnVuY3Rpb24gdmFsdWVzKG1hcCkge1xuICBsZXQgbWFwX2tleXMgPSBrZXlzKG1hcCk7XG4gIGxldCBsaXN0ID0gW107XG5cbiAgZm9yIChsZXQga2V5IG9mIG1hcF9rZXlzKSB7XG4gICAgbGlzdC5wdXNoKG1hcFtrZXldKTtcbiAgfVxuXG4gIHJldHVybiBTcGVjaWFsRm9ybXMubGlzdCguLi5saXN0KTtcbn1cblxuZnVuY3Rpb24gZnJvbV9zdHJ1Y3Qoc3RydWN0KSB7XG4gIGxldCBtYXAgPSBPYmplY3QuYXNzaWduKHt9LCBzdHJ1Y3QpO1xuICBkZWxldGUgbWFwW1N5bWJvbC5mb3IoXCJfX3N0cnVjdF9fXCIpXTtcblxuICByZXR1cm4gU3BlY2lhbEZvcm1zLm1hcChtYXApO1xufVxuXG5mdW5jdGlvbiBfX2RlbGV0ZV9fKG1hcCwga2V5KSB7XG4gIGxldCBuZXdfbWFwID0gT2JqZWN0LmFzc2lnbih7fSwgbWFwKTtcblxuICBkZWxldGUgbmV3X21hcFtrZXldO1xuXG4gIHJldHVybiBTcGVjaWFsRm9ybXMubWFwKG5ld19tYXApO1xufVxuXG5mdW5jdGlvbiBlcXVhbF9fcW1hcmtfXyhtYXAxLCBtYXAyKSB7XG4gIHJldHVybiBtYXAxID09PSBtYXAyO1xufVxuXG5mdW5jdGlvbiBmZXRjaF9fZW1hcmtfXyhtYXAsIGtleSkge1xuICBpZiAoa2V5IGluIG1hcCkge1xuICAgIHJldHVybiBtYXBba2V5XTtcbiAgfVxuXG4gIHRocm93IG5ldyBFcnJvcihcIktleSBub3QgZm91bmQuXCIpO1xufVxuXG5mdW5jdGlvbiBmZXRjaChtYXAsIGtleSkge1xuICBpZiAoa2V5IGluIG1hcCkge1xuICAgIHJldHVybiBTcGVjaWFsRm9ybXMudHVwbGUoU3BlY2lhbEZvcm1zLmF0b20oXCJva1wiKSwgbWFwW2tleV0pO1xuICB9XG5cbiAgcmV0dXJuIFNwZWNpYWxGb3Jtcy5hdG9tKFwiZXJyb3JcIik7XG59XG5cbmZ1bmN0aW9uIGhhc19rZXlfX3FtYXJrX18obWFwLCBrZXkpIHtcbiAgcmV0dXJuIGtleSBpbiBtYXA7XG59XG5cbmZ1bmN0aW9uIHNwbGl0JDEobWFwLCBrZXlzKSB7XG4gIGxldCBzcGxpdDEgPSB7fTtcbiAgbGV0IHNwbGl0MiA9IHt9O1xuXG4gIGZvciAobGV0IGtleSBvZiBPYmplY3Qua2V5cyhtYXApKSB7XG4gICAgaWYgKGtleXMuaW5kZXhPZihrZXkpID4gLTEpIHtcbiAgICAgIHNwbGl0MVtrZXldID0gbWFwW2tleV07XG4gICAgfSBlbHNlIHtcbiAgICAgIHNwbGl0MltrZXldID0gbWFwW2tleV07XG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIFNwZWNpYWxGb3Jtcy50dXBsZShTcGVjaWFsRm9ybXMubWFwKHNwbGl0MSksIFNwZWNpYWxGb3Jtcy5tYXAoc3BsaXQyKSk7XG59XG5cbmZ1bmN0aW9uIHRha2UobWFwLCBrZXlzKSB7XG4gIGxldCBzcGxpdDEgPSB7fTtcblxuICBmb3IgKGxldCBrZXkgb2YgT2JqZWN0LmtleXMobWFwKSkge1xuICAgIGlmIChrZXlzLmluZGV4T2Yoa2V5KSA+IC0xKSB7XG4gICAgICBzcGxpdDFba2V5XSA9IG1hcFtrZXldO1xuICAgIH1cbiAgfVxuXG4gIHJldHVybiBTcGVjaWFsRm9ybXMubWFwKHNwbGl0MSk7XG59XG5cbmZ1bmN0aW9uIGRyb3AobWFwLCBrZXlzKSB7XG4gIGxldCBzcGxpdDEgPSB7fTtcblxuICBmb3IgKGxldCBrZXkgb2YgT2JqZWN0LmtleXMobWFwKSkge1xuICAgIGlmIChrZXlzLmluZGV4T2Yoa2V5KSA9PT0gLTEpIHtcbiAgICAgIHNwbGl0MVtrZXldID0gbWFwW2tleV07XG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIFNwZWNpYWxGb3Jtcy5tYXAoc3BsaXQxKTtcbn1cblxuZnVuY3Rpb24gcHV0X25ldyhtYXAsIGtleSwgdmFsdWUpIHtcbiAgaWYgKGtleSBpbiBtYXApIHtcbiAgICByZXR1cm4gbWFwO1xuICB9XG5cbiAgbGV0IG5ld19tYXAgPSBPYmplY3QuYXNzaWduKHt9LCBtYXApO1xuICBuZXdfbWFwW2tleV0gPSB2YWx1ZTtcblxuICByZXR1cm4gU3BlY2lhbEZvcm1zLm1hcChuZXdfbWFwKTtcbn1cblxuZnVuY3Rpb24gcHV0X25ld19sYXp5KG1hcCwga2V5LCBmdW4pIHtcbiAgaWYgKGtleSBpbiBtYXApIHtcbiAgICByZXR1cm4gbWFwO1xuICB9XG5cbiAgbGV0IG5ld19tYXAgPSBPYmplY3QuYXNzaWduKHt9LCBtYXApO1xuICBuZXdfbWFwW2tleV0gPSBmdW4oKTtcblxuICByZXR1cm4gU3BlY2lhbEZvcm1zLm1hcChuZXdfbWFwKTtcbn1cblxuZnVuY3Rpb24gZ2V0X2FuZF91cGRhdGUobWFwLCBrZXksIGZ1bikge1xuICBpZiAoa2V5IGluIG1hcCkge1xuICAgIHJldHVybiBtYXA7XG4gIH1cblxuICBsZXQgbmV3X21hcCA9IE9iamVjdC5hc3NpZ24oe30sIG1hcCk7XG4gIG5ld19tYXBba2V5XSA9IGZ1bihtYXBba2V5XSk7XG5cbiAgcmV0dXJuIFNwZWNpYWxGb3Jtcy5tYXAobmV3X21hcCk7XG59XG5cbmZ1bmN0aW9uIHBvcF9sYXp5KG1hcCwga2V5LCBmdW4pIHtcbiAgaWYgKCFrZXkgaW4gbWFwKSB7XG4gICAgcmV0dXJuIFNwZWNpYWxGb3Jtcy50dXBsZShmdW4oKSwgbWFwKTtcbiAgfVxuXG4gIGxldCBuZXdfbWFwID0gT2JqZWN0LmFzc2lnbih7fSwgbWFwKTtcbiAgbGV0IHZhbHVlID0gZnVuKG5ld19tYXBba2V5XSk7XG4gIGRlbGV0ZSBuZXdfbWFwW2tleV07XG5cbiAgcmV0dXJuIFNwZWNpYWxGb3Jtcy50dXBsZSh2YWx1ZSwgbmV3X21hcCk7XG59XG5cbmZ1bmN0aW9uIHBvcChtYXAsIGtleSwgX2RlZmF1bHQgPSBudWxsKSB7XG4gIGlmICgha2V5IGluIG1hcCkge1xuICAgIHJldHVybiBTcGVjaWFsRm9ybXMudHVwbGUoX2RlZmF1bHQsIG1hcCk7XG4gIH1cblxuICBsZXQgbmV3X21hcCA9IE9iamVjdC5hc3NpZ24oe30sIG1hcCk7XG4gIGxldCB2YWx1ZSA9IG5ld19tYXBba2V5XTtcbiAgZGVsZXRlIG5ld19tYXBba2V5XTtcblxuICByZXR1cm4gU3BlY2lhbEZvcm1zLnR1cGxlKHZhbHVlLCBuZXdfbWFwKTtcbn1cblxuZnVuY3Rpb24gZ2V0X2xhenkobWFwLCBrZXksIGZ1bikge1xuICBpZiAoIWtleSBpbiBtYXApIHtcbiAgICByZXR1cm4gZnVuKCk7XG4gIH1cblxuICByZXR1cm4gZnVuKG1hcFtrZXldKTtcbn1cblxuZnVuY3Rpb24gZ2V0KG1hcCwga2V5LCBfZGVmYXVsdCA9IG51bGwpIHtcbiAgaWYgKCFrZXkgaW4gbWFwKSB7XG4gICAgcmV0dXJuIF9kZWZhdWx0O1xuICB9XG5cbiAgcmV0dXJuIG1hcFtrZXldO1xufVxuXG5mdW5jdGlvbiBwdXQobWFwLCBrZXksIHZhbCkge1xuICBsZXQgbmV3X21hcCA9IE9iamVjdCh7fSwgbWFwKTtcbiAgbmV3X21hcFtrZXldID0gdmFsO1xuXG4gIHJldHVybiBTcGVjaWFsRm9ybXMubWFwKG5ld19tYXApO1xufVxuXG5mdW5jdGlvbiB1cGRhdGVfX2VtYXJrX18obWFwLCBrZXksIGZ1bikge1xuICBpZiAoIWtleSBpbiBtYXApIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoXCJLZXkgbm90IGZvdW5kXCIpO1xuICB9XG5cbiAgbGV0IG5ld19tYXAgPSBPYmplY3Qoe30sIG1hcCk7XG4gIG5ld19tYXBba2V5XSA9IGZ1bihtYXBba2V5XSk7XG5cbiAgcmV0dXJuIFNwZWNpYWxGb3Jtcy5tYXAobmV3X21hcCk7XG59XG5cbmZ1bmN0aW9uIHVwZGF0ZShtYXAsIGtleSwgaW5pdGlhbCwgZnVuKSB7XG4gIGxldCBuZXdfbWFwID0gT2JqZWN0KHt9LCBtYXApO1xuXG4gIGlmICgha2V5IGluIG1hcCkge1xuICAgIG5ld19tYXBba2V5XSA9IGluaXRpYWw7XG4gIH0gZWxzZSB7XG4gICAgbmV3X21hcFtrZXldID0gZnVuKG1hcFtrZXldKTtcbiAgfVxuXG4gIHJldHVybiBTcGVjaWFsRm9ybXMubWFwKG5ld19tYXApO1xufVxuXG52YXIgbWFwID0ge1xuICBuZXc6IF9fbmV3X18sXG4gIGtleXMsXG4gIHNpemUsXG4gIHRvX2xpc3Q6IHRvX2xpc3QkMSxcbiAgdmFsdWVzLFxuICBmcm9tX3N0cnVjdCxcbiAgZGVsZXRlOiBfX2RlbGV0ZV9fLFxuICBkcm9wLFxuICBlcXVhbF9fcW1hcmtfXyxcbiAgZmV0Y2hfX2VtYXJrX18sXG4gIGZldGNoLFxuICBoYXNfa2V5X19xbWFya19fLFxuICBzcGxpdDogc3BsaXQkMSxcbiAgdGFrZSxcbiAgcHV0X25ldyxcbiAgcHV0X25ld19sYXp5LFxuICBnZXRfYW5kX3VwZGF0ZSxcbiAgcG9wX2xhenksXG4gIHBvcCxcbiAgZ2V0X2xhenksXG4gIGdldCxcbiAgcHV0LFxuICB1cGRhdGVfX2VtYXJrX18sXG4gIHVwZGF0ZVxufTtcblxuZnVuY3Rpb24gX19uZXdfXyQxKCkge1xuICByZXR1cm4gU3BlY2lhbEZvcm1zLm1hcCh7IFtTeW1ib2wuZm9yKCdfX3N0cnVjdF9fJyldOiBTeW1ib2wuZm9yKCdNYXBTZXQnKSwgc2V0OiBTcGVjaWFsRm9ybXMubGlzdCgpIH0pO1xufVxuXG5mdW5jdGlvbiBzaXplJDIobWFwKSB7XG4gIHJldHVybiBtYXAuc2V0Lmxlbmd0aDtcbn1cblxuZnVuY3Rpb24gdG9fbGlzdCQzKG1hcCkge1xuICByZXR1cm4gbWFwLnNldDtcbn1cblxuZnVuY3Rpb24gX19kZWxldGVfXyQyKHNldCwgdGVybSkge1xuICBsZXQgbmV3X2xpc3QgPSBMaXN0LmRlbGV0ZShzZXQuc2V0LCB0ZXJtKTtcblxuICBsZXQgbmV3X21hcCA9IE9iamVjdC5hc3NpZ24oe30sIHNldCk7XG4gIG5ld19tYXAuc2V0ID0gbmV3X2xpc3Q7XG4gIHJldHVybiBTcGVjaWFsRm9ybXMubWFwKG5ld19tYXApO1xufVxuXG5mdW5jdGlvbiBwdXQkMihzZXQsIHRlcm0pIHtcbiAgaWYgKHNldC5zZXQuaW5kZXhPZih0ZXJtKSA9PT0gLTEpIHtcbiAgICBsZXQgbmV3X2xpc3QgPSBMaXN0LmFwcGVuZChzZXQuc2V0LCB0ZXJtKTtcblxuICAgIGxldCBuZXdfbWFwID0gT2JqZWN0LmFzc2lnbih7fSwgc2V0KTtcbiAgICBuZXdfbWFwLnNldCA9IG5ld19saXN0O1xuICAgIHJldHVybiBTcGVjaWFsRm9ybXMubWFwKG5ld19tYXApO1xuICB9XG5cbiAgcmV0dXJuIHNldDtcbn1cblxuZnVuY3Rpb24gZGlmZmVyZW5jZSQxKHNldDEsIHNldDIpIHtcbiAgbGV0IG5ld19tYXAgPSBPYmplY3QuYXNzaWduKHt9LCBzZXQxKTtcblxuICBmb3IgKGxldCB2YWwgb2Ygc2V0MS5zZXQpIHtcbiAgICBpZiAobWVtYmVyX19xbWFya19fJDEoc2V0MiwgdmFsKSkge1xuICAgICAgbmV3X21hcC5zZXQgPSBMaXN0LmRlbGV0ZShuZXdfbWFwLnNldCwgdmFsKTtcbiAgICB9XG4gIH1cblxuICByZXR1cm4gU3BlY2lhbEZvcm1zLm1hcChuZXdfbWFwKTtcbn1cblxuZnVuY3Rpb24gaW50ZXJzZWN0aW9uJDEoc2V0MSwgc2V0Mikge1xuICBsZXQgbmV3X21hcCA9IE9iamVjdC5hc3NpZ24oe30sIHNldDEpO1xuXG4gIGZvciAobGV0IHZhbCBvZiBzZXQxLnNldCkge1xuICAgIGlmICghbWVtYmVyX19xbWFya19fJDEoc2V0MiwgdmFsKSkge1xuICAgICAgbmV3X21hcC5zZXQgPSBMaXN0LmRlbGV0ZShuZXdfbWFwLnNldCwgdmFsKTtcbiAgICB9XG4gIH1cblxuICByZXR1cm4gU3BlY2lhbEZvcm1zLm1hcChuZXdfbWFwKTtcbn1cblxuZnVuY3Rpb24gdW5pb24kMShzZXQxLCBzZXQyKSB7XG4gIGxldCBuZXdfbWFwID0gc2V0MTtcblxuICBmb3IgKGxldCB2YWwgb2Ygc2V0Mi5zZXQpIHtcbiAgICBuZXdfbWFwID0gcHV0JDIobmV3X21hcCwgdmFsKTtcbiAgfVxuXG4gIHJldHVybiBTcGVjaWFsRm9ybXMubWFwKG5ld19tYXApO1xufVxuXG5mdW5jdGlvbiBkaXNqb2luX19xbWFya19fJDEoc2V0MSwgc2V0Mikge1xuICBmb3IgKGxldCB2YWwgb2Ygc2V0MS5zZXQpIHtcbiAgICBpZiAobWVtYmVyX19xbWFya19fJDEoc2V0MiwgdmFsKSkge1xuICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH1cbiAgfVxuXG4gIHJldHVybiB0cnVlO1xufVxuXG5mdW5jdGlvbiBtZW1iZXJfX3FtYXJrX18kMShzZXQsIHZhbHVlKSB7XG4gIHJldHVybiBzZXQuc2V0LmluZGV4T2YodmFsdWUpID49IDA7XG59XG5cbmZ1bmN0aW9uIGVxdWFsX19xbWFya19fJDIoc2V0MSwgc2V0Mikge1xuICByZXR1cm4gc2V0MS5zZXQgPT09IHNldDIuc2V0O1xufVxuXG5mdW5jdGlvbiBzdWJzZXRfX3FtYXJrX18kMShzZXQxLCBzZXQyKSB7XG4gIGZvciAobGV0IHZhbCBvZiBzZXQxLnNldCkge1xuICAgIGlmICghbWVtYmVyX19xbWFya19fJDEoc2V0MiwgdmFsKSkge1xuICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH1cbiAgfVxuXG4gIHJldHVybiB0cnVlO1xufVxuXG52YXIgTWFwU2V0ID0ge1xuICBuZXc6IF9fbmV3X18kMSxcbiAgc2l6ZTogc2l6ZSQyLFxuICB0b19saXN0OiB0b19saXN0JDMsXG4gIGRpc2pvaW5fX3FtYXJrX186IGRpc2pvaW5fX3FtYXJrX18kMSxcbiAgZGVsZXRlOiBfX2RlbGV0ZV9fJDIsXG4gIHN1YnNldF9fcW1hcmtfXzogc3Vic2V0X19xbWFya19fJDEsXG4gIGVxdWFsX19xbWFya19fOiBlcXVhbF9fcW1hcmtfXyQyLFxuICBtZW1iZXJfX3FtYXJrX186IG1lbWJlcl9fcW1hcmtfXyQxLFxuICBwdXQ6IHB1dCQyLFxuICB1bmlvbjogdW5pb24kMSxcbiAgaW50ZXJzZWN0aW9uOiBpbnRlcnNlY3Rpb24kMSxcbiAgZGlmZmVyZW5jZTogZGlmZmVyZW5jZSQxXG59O1xuXG5mdW5jdGlvbiBzaXplJDEobWFwKSB7XG4gIHJldHVybiBNYXBTZXQuc2l6ZShtYXApO1xufVxuXG5mdW5jdGlvbiB0b19saXN0JDIobWFwKSB7XG4gIHJldHVybiBNYXBTZXQudG9fbGlzdChtYXApO1xufVxuXG5mdW5jdGlvbiBfX2RlbGV0ZV9fJDEoc2V0LCB0ZXJtKSB7XG4gIHJldHVybiBNYXBTZXQuZGVsZXRlKHNldCwgdGVybSk7XG59XG5cbmZ1bmN0aW9uIHB1dCQxKHNldCwgdGVybSkge1xuICByZXR1cm4gTWFwU2V0LnB1dChzZXQsIHRlcm0pO1xufVxuXG5mdW5jdGlvbiBkaWZmZXJlbmNlKHNldDEsIHNldDIpIHtcbiAgcmV0dXJuIE1hcFNldC5kaWZmZXJlbmNlKHNldDEsIHNldDIpO1xufVxuXG5mdW5jdGlvbiBpbnRlcnNlY3Rpb24oc2V0MSwgc2V0Mikge1xuICByZXR1cm4gTWFwU2V0LmludGVyc2VjdGlvbihzZXQxLCBzZXQyKTtcbn1cblxuZnVuY3Rpb24gdW5pb24oc2V0MSwgc2V0Mikge1xuICByZXR1cm4gTWFwU2V0LnVuaW9uKHNldDEsIHNldDIpO1xufVxuXG5mdW5jdGlvbiBkaXNqb2luX19xbWFya19fKHNldDEsIHNldDIpIHtcbiAgcmV0dXJuIE1hcFNldC5kaXNqb2luX19xbWFya19fKHNldDEsIHNldDIpO1xufVxuXG5mdW5jdGlvbiBtZW1iZXJfX3FtYXJrX18oc2V0LCB2YWx1ZSkge1xuICByZXR1cm4gTWFwU2V0Lm1lbWJlcl9fcW1hcmtfXyhzZXQxLCBzZXQyKTtcbn1cblxuZnVuY3Rpb24gZXF1YWxfX3FtYXJrX18kMShzZXQxLCBzZXQyKSB7XG4gIHJldHVybiBNYXBTZXQuZXF1YWxfX3FtYXJrX18oc2V0MSwgc2V0Mik7XG59XG5cbmZ1bmN0aW9uIHN1YnNldF9fcW1hcmtfXyhzZXQxLCBzZXQyKSB7XG4gIHJldHVybiBNYXBTZXQuc3Vic2V0X19xbWFya19fKHNldDEsIHNldDIpO1xufVxuXG52YXIgc2V0ID0ge1xuICBzaXplOiBzaXplJDEsXG4gIHRvX2xpc3Q6IHRvX2xpc3QkMixcbiAgZGlzam9pbl9fcW1hcmtfXyxcbiAgZGVsZXRlOiBfX2RlbGV0ZV9fJDEsXG4gIHN1YnNldF9fcW1hcmtfXyxcbiAgZXF1YWxfX3FtYXJrX186IGVxdWFsX19xbWFya19fJDEsXG4gIG1lbWJlcl9fcW1hcmtfXyxcbiAgcHV0OiBwdXQkMSxcbiAgdW5pb24sXG4gIGludGVyc2VjdGlvbixcbiAgZGlmZmVyZW5jZVxufTtcblxubGV0IFZpcnR1YWxET00gPSAoZnVuY3Rpb24gKGUpIHtcbiAgICByZXR1cm4gZSgpO1xufSkoZnVuY3Rpb24gKCkge1xuICAgIHZhciBkZWZpbmUsIG1vZHVsZSwgZXhwb3J0cztcbiAgICByZXR1cm4gKGZ1bmN0aW9uIGUodCwgbiwgcikge1xuICAgICAgICBmdW5jdGlvbiBzKG8sIHUpIHtcbiAgICAgICAgICAgIGlmICghbltvXSkge1xuICAgICAgICAgICAgICAgIGlmICghdFtvXSkge1xuICAgICAgICAgICAgICAgICAgICB2YXIgYSA9IHR5cGVvZiByZXF1aXJlID09IFwiZnVuY3Rpb25cIiAmJiByZXF1aXJlO1xuICAgICAgICAgICAgICAgICAgICBpZiAoIXUgJiYgYSkgcmV0dXJuIGEobywgITApO1xuICAgICAgICAgICAgICAgICAgICBpZiAoaSkgcmV0dXJuIGkobywgITApO1xuICAgICAgICAgICAgICAgICAgICB2YXIgZiA9IG5ldyBFcnJvcihcIkNhbm5vdCBmaW5kIG1vZHVsZSAnXCIgKyBvICsgXCInXCIpO1xuICAgICAgICAgICAgICAgICAgICB0aHJvdyAoZi5jb2RlID0gXCJNT0RVTEVfTk9UX0ZPVU5EXCIsIGYpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB2YXIgbCA9IG5bb10gPSB7XG4gICAgICAgICAgICAgICAgICAgIGV4cG9ydHM6IHt9XG4gICAgICAgICAgICAgICAgfTtcbiAgICAgICAgICAgICAgICB0W29dWzBdLmNhbGwobC5leHBvcnRzLCBmdW5jdGlvbiAoZSkge1xuICAgICAgICAgICAgICAgICAgICB2YXIgbiA9IHRbb11bMV1bZV07XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBzKG4gPyBuIDogZSk7XG4gICAgICAgICAgICAgICAgfSwgbCwgbC5leHBvcnRzLCBlLCB0LCBuLCByKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJldHVybiBuW29dLmV4cG9ydHM7XG4gICAgICAgIH1cbiAgICAgICAgdmFyIGkgPSB0eXBlb2YgcmVxdWlyZSA9PSBcImZ1bmN0aW9uXCIgJiYgcmVxdWlyZTtcbiAgICAgICAgZm9yICh2YXIgbyA9IDA7IG8gPCByLmxlbmd0aDsgbysrKSBzKHJbb10pO1xuICAgICAgICByZXR1cm4gcztcbiAgICB9KSh7XG4gICAgICAgIDE6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG5cbiAgICAgICAgICAgIHZhciBjcmVhdGVFbGVtZW50ID0gcmVxdWlyZShcIi4vdmRvbS9jcmVhdGUtZWxlbWVudC5qc1wiKTtcblxuICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBjcmVhdGVFbGVtZW50O1xuICAgICAgICB9LCB7IFwiLi92ZG9tL2NyZWF0ZS1lbGVtZW50LmpzXCI6IDE1IH1dLCAyOiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge1xuICAgICAgICAgICAgdmFyIGRpZmYgPSByZXF1aXJlKFwiLi92dHJlZS9kaWZmLmpzXCIpO1xuXG4gICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IGRpZmY7XG4gICAgICAgIH0sIHsgXCIuL3Z0cmVlL2RpZmYuanNcIjogMzUgfV0sIDM6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICB2YXIgaCA9IHJlcXVpcmUoXCIuL3ZpcnR1YWwtaHlwZXJzY3JpcHQvaW5kZXguanNcIik7XG5cbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gaDtcbiAgICAgICAgfSwgeyBcIi4vdmlydHVhbC1oeXBlcnNjcmlwdC9pbmRleC5qc1wiOiAyMiB9XSwgNDogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHtcbiAgICAgICAgICAgIHZhciBkaWZmID0gcmVxdWlyZShcIi4vZGlmZi5qc1wiKTtcbiAgICAgICAgICAgIHZhciBwYXRjaCA9IHJlcXVpcmUoXCIuL3BhdGNoLmpzXCIpO1xuICAgICAgICAgICAgdmFyIGggPSByZXF1aXJlKFwiLi9oLmpzXCIpO1xuICAgICAgICAgICAgdmFyIGNyZWF0ZSA9IHJlcXVpcmUoXCIuL2NyZWF0ZS1lbGVtZW50LmpzXCIpO1xuICAgICAgICAgICAgdmFyIFZOb2RlID0gcmVxdWlyZShcIi4vdm5vZGUvdm5vZGUuanNcIik7XG4gICAgICAgICAgICB2YXIgVlRleHQgPSByZXF1aXJlKFwiLi92bm9kZS92dGV4dC5qc1wiKTtcblxuICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSB7XG4gICAgICAgICAgICAgICAgZGlmZjogZGlmZixcbiAgICAgICAgICAgICAgICBwYXRjaDogcGF0Y2gsXG4gICAgICAgICAgICAgICAgaDogaCxcbiAgICAgICAgICAgICAgICBjcmVhdGU6IGNyZWF0ZSxcbiAgICAgICAgICAgICAgICBWTm9kZTogVk5vZGUsXG4gICAgICAgICAgICAgICAgVlRleHQ6IFZUZXh0XG4gICAgICAgICAgICB9O1xuICAgICAgICB9LCB7IFwiLi9jcmVhdGUtZWxlbWVudC5qc1wiOiAxLCBcIi4vZGlmZi5qc1wiOiAyLCBcIi4vaC5qc1wiOiAzLCBcIi4vcGF0Y2guanNcIjogMTMsIFwiLi92bm9kZS92bm9kZS5qc1wiOiAzMSwgXCIuL3Zub2RlL3Z0ZXh0LmpzXCI6IDMzIH1dLCA1OiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge1xuICAgICAgICAgICAgLyohXG4gICAgICAgICAgICAgKiBDcm9zcy1Ccm93c2VyIFNwbGl0IDEuMS4xXG4gICAgICAgICAgICAgKiBDb3B5cmlnaHQgMjAwNy0yMDEyIFN0ZXZlbiBMZXZpdGhhbiA8c3RldmVubGV2aXRoYW4uY29tPlxuICAgICAgICAgICAgICogQXZhaWxhYmxlIHVuZGVyIHRoZSBNSVQgTGljZW5zZVxuICAgICAgICAgICAgICogRUNNQVNjcmlwdCBjb21wbGlhbnQsIHVuaWZvcm0gY3Jvc3MtYnJvd3NlciBzcGxpdCBtZXRob2RcbiAgICAgICAgICAgICAqL1xuXG4gICAgICAgICAgICAvKipcbiAgICAgICAgICAgICAqIFNwbGl0cyBhIHN0cmluZyBpbnRvIGFuIGFycmF5IG9mIHN0cmluZ3MgdXNpbmcgYSByZWdleCBvciBzdHJpbmcgc2VwYXJhdG9yLiBNYXRjaGVzIG9mIHRoZVxuICAgICAgICAgICAgICogc2VwYXJhdG9yIGFyZSBub3QgaW5jbHVkZWQgaW4gdGhlIHJlc3VsdCBhcnJheS4gSG93ZXZlciwgaWYgYHNlcGFyYXRvcmAgaXMgYSByZWdleCB0aGF0IGNvbnRhaW5zXG4gICAgICAgICAgICAgKiBjYXB0dXJpbmcgZ3JvdXBzLCBiYWNrcmVmZXJlbmNlcyBhcmUgc3BsaWNlZCBpbnRvIHRoZSByZXN1bHQgZWFjaCB0aW1lIGBzZXBhcmF0b3JgIGlzIG1hdGNoZWQuXG4gICAgICAgICAgICAgKiBGaXhlcyBicm93c2VyIGJ1Z3MgY29tcGFyZWQgdG8gdGhlIG5hdGl2ZSBgU3RyaW5nLnByb3RvdHlwZS5zcGxpdGAgYW5kIGNhbiBiZSB1c2VkIHJlbGlhYmx5XG4gICAgICAgICAgICAgKiBjcm9zcy1icm93c2VyLlxuICAgICAgICAgICAgICogQHBhcmFtIHtTdHJpbmd9IHN0ciBTdHJpbmcgdG8gc3BsaXQuXG4gICAgICAgICAgICAgKiBAcGFyYW0ge1JlZ0V4cHxTdHJpbmd9IHNlcGFyYXRvciBSZWdleCBvciBzdHJpbmcgdG8gdXNlIGZvciBzZXBhcmF0aW5nIHRoZSBzdHJpbmcuXG4gICAgICAgICAgICAgKiBAcGFyYW0ge051bWJlcn0gW2xpbWl0XSBNYXhpbXVtIG51bWJlciBvZiBpdGVtcyB0byBpbmNsdWRlIGluIHRoZSByZXN1bHQgYXJyYXkuXG4gICAgICAgICAgICAgKiBAcmV0dXJucyB7QXJyYXl9IEFycmF5IG9mIHN1YnN0cmluZ3MuXG4gICAgICAgICAgICAgKiBAZXhhbXBsZVxuICAgICAgICAgICAgICpcbiAgICAgICAgICAgICAqIC8vIEJhc2ljIHVzZVxuICAgICAgICAgICAgICogc3BsaXQoJ2EgYiBjIGQnLCAnICcpO1xuICAgICAgICAgICAgICogLy8gLT4gWydhJywgJ2InLCAnYycsICdkJ11cbiAgICAgICAgICAgICAqXG4gICAgICAgICAgICAgKiAvLyBXaXRoIGxpbWl0XG4gICAgICAgICAgICAgKiBzcGxpdCgnYSBiIGMgZCcsICcgJywgMik7XG4gICAgICAgICAgICAgKiAvLyAtPiBbJ2EnLCAnYiddXG4gICAgICAgICAgICAgKlxuICAgICAgICAgICAgICogLy8gQmFja3JlZmVyZW5jZXMgaW4gcmVzdWx0IGFycmF5XG4gICAgICAgICAgICAgKiBzcGxpdCgnLi53b3JkMSB3b3JkMi4uJywgLyhbYS16XSspKFxcZCspL2kpO1xuICAgICAgICAgICAgICogLy8gLT4gWycuLicsICd3b3JkJywgJzEnLCAnICcsICd3b3JkJywgJzInLCAnLi4nXVxuICAgICAgICAgICAgICovXG4gICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IChmdW5jdGlvbiBzcGxpdCh1bmRlZikge1xuXG4gICAgICAgICAgICAgICAgdmFyIG5hdGl2ZVNwbGl0ID0gU3RyaW5nLnByb3RvdHlwZS5zcGxpdCxcbiAgICAgICAgICAgICAgICAgICAgY29tcGxpYW50RXhlY05wY2cgPSAvKCk/Py8uZXhlYyhcIlwiKVsxXSA9PT0gdW5kZWYsXG5cbiAgICAgICAgICAgICAgICAvLyBOUENHOiBub25wYXJ0aWNpcGF0aW5nIGNhcHR1cmluZyBncm91cFxuICAgICAgICAgICAgICAgIHNlbGY7XG5cbiAgICAgICAgICAgICAgICBzZWxmID0gZnVuY3Rpb24gKHN0ciwgc2VwYXJhdG9yLCBsaW1pdCkge1xuICAgICAgICAgICAgICAgICAgICAvLyBJZiBgc2VwYXJhdG9yYCBpcyBub3QgYSByZWdleCwgdXNlIGBuYXRpdmVTcGxpdGBcbiAgICAgICAgICAgICAgICAgICAgaWYgKE9iamVjdC5wcm90b3R5cGUudG9TdHJpbmcuY2FsbChzZXBhcmF0b3IpICE9PSBcIltvYmplY3QgUmVnRXhwXVwiKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gbmF0aXZlU3BsaXQuY2FsbChzdHIsIHNlcGFyYXRvciwgbGltaXQpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIHZhciBvdXRwdXQgPSBbXSxcbiAgICAgICAgICAgICAgICAgICAgICAgIGZsYWdzID0gKHNlcGFyYXRvci5pZ25vcmVDYXNlID8gXCJpXCIgOiBcIlwiKSArIChzZXBhcmF0b3IubXVsdGlsaW5lID8gXCJtXCIgOiBcIlwiKSArIChzZXBhcmF0b3IuZXh0ZW5kZWQgPyBcInhcIiA6IFwiXCIpICsgKHNlcGFyYXRvci5zdGlja3kgPyBcInlcIiA6IFwiXCIpLFxuXG4gICAgICAgICAgICAgICAgICAgIC8vIEZpcmVmb3ggMytcbiAgICAgICAgICAgICAgICAgICAgbGFzdExhc3RJbmRleCA9IDAsXG5cbiAgICAgICAgICAgICAgICAgICAgLy8gTWFrZSBgZ2xvYmFsYCBhbmQgYXZvaWQgYGxhc3RJbmRleGAgaXNzdWVzIGJ5IHdvcmtpbmcgd2l0aCBhIGNvcHlcbiAgICAgICAgICAgICAgICAgICAgc2VwYXJhdG9yID0gbmV3IFJlZ0V4cChzZXBhcmF0b3Iuc291cmNlLCBmbGFncyArIFwiZ1wiKSxcbiAgICAgICAgICAgICAgICAgICAgICAgIHNlcGFyYXRvcjIsXG4gICAgICAgICAgICAgICAgICAgICAgICBtYXRjaCxcbiAgICAgICAgICAgICAgICAgICAgICAgIGxhc3RJbmRleCxcbiAgICAgICAgICAgICAgICAgICAgICAgIGxhc3RMZW5ndGg7XG4gICAgICAgICAgICAgICAgICAgIHN0ciArPSBcIlwiOyAvLyBUeXBlLWNvbnZlcnRcbiAgICAgICAgICAgICAgICAgICAgaWYgKCFjb21wbGlhbnRFeGVjTnBjZykge1xuICAgICAgICAgICAgICAgICAgICAgICAgLy8gRG9lc24ndCBuZWVkIGZsYWdzIGd5LCBidXQgdGhleSBkb24ndCBodXJ0XG4gICAgICAgICAgICAgICAgICAgICAgICBzZXBhcmF0b3IyID0gbmV3IFJlZ0V4cChcIl5cIiArIHNlcGFyYXRvci5zb3VyY2UgKyBcIiQoPyFcXFxccylcIiwgZmxhZ3MpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIC8qIFZhbHVlcyBmb3IgYGxpbWl0YCwgcGVyIHRoZSBzcGVjOlxuICAgICAgICAgICAgICAgICAgICAgKiBJZiB1bmRlZmluZWQ6IDQyOTQ5NjcyOTUgLy8gTWF0aC5wb3coMiwgMzIpIC0gMVxuICAgICAgICAgICAgICAgICAgICAgKiBJZiAwLCBJbmZpbml0eSwgb3IgTmFOOiAwXG4gICAgICAgICAgICAgICAgICAgICAqIElmIHBvc2l0aXZlIG51bWJlcjogbGltaXQgPSBNYXRoLmZsb29yKGxpbWl0KTsgaWYgKGxpbWl0ID4gNDI5NDk2NzI5NSkgbGltaXQgLT0gNDI5NDk2NzI5NjtcbiAgICAgICAgICAgICAgICAgICAgICogSWYgbmVnYXRpdmUgbnVtYmVyOiA0Mjk0OTY3Mjk2IC0gTWF0aC5mbG9vcihNYXRoLmFicyhsaW1pdCkpXG4gICAgICAgICAgICAgICAgICAgICAqIElmIG90aGVyOiBUeXBlLWNvbnZlcnQsIHRoZW4gdXNlIHRoZSBhYm92ZSBydWxlc1xuICAgICAgICAgICAgICAgICAgICAgKi9cbiAgICAgICAgICAgICAgICAgICAgbGltaXQgPSBsaW1pdCA9PT0gdW5kZWYgPyAtMSA+Pj4gMCA6IC8vIE1hdGgucG93KDIsIDMyKSAtIDFcbiAgICAgICAgICAgICAgICAgICAgbGltaXQgPj4+IDA7IC8vIFRvVWludDMyKGxpbWl0KVxuICAgICAgICAgICAgICAgICAgICB3aGlsZSAobWF0Y2ggPSBzZXBhcmF0b3IuZXhlYyhzdHIpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAvLyBgc2VwYXJhdG9yLmxhc3RJbmRleGAgaXMgbm90IHJlbGlhYmxlIGNyb3NzLWJyb3dzZXJcbiAgICAgICAgICAgICAgICAgICAgICAgIGxhc3RJbmRleCA9IG1hdGNoLmluZGV4ICsgbWF0Y2hbMF0ubGVuZ3RoO1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGxhc3RJbmRleCA+IGxhc3RMYXN0SW5kZXgpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBvdXRwdXQucHVzaChzdHIuc2xpY2UobGFzdExhc3RJbmRleCwgbWF0Y2guaW5kZXgpKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBGaXggYnJvd3NlcnMgd2hvc2UgYGV4ZWNgIG1ldGhvZHMgZG9uJ3QgY29uc2lzdGVudGx5IHJldHVybiBgdW5kZWZpbmVkYCBmb3JcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBub25wYXJ0aWNpcGF0aW5nIGNhcHR1cmluZyBncm91cHNcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoIWNvbXBsaWFudEV4ZWNOcGNnICYmIG1hdGNoLmxlbmd0aCA+IDEpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbWF0Y2hbMF0ucmVwbGFjZShzZXBhcmF0b3IyLCBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBmb3IgKHZhciBpID0gMTsgaSA8IGFyZ3VtZW50cy5sZW5ndGggLSAyOyBpKyspIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoYXJndW1lbnRzW2ldID09PSB1bmRlZikge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBtYXRjaFtpXSA9IHVuZGVmO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChtYXRjaC5sZW5ndGggPiAxICYmIG1hdGNoLmluZGV4IDwgc3RyLmxlbmd0aCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBBcnJheS5wcm90b3R5cGUucHVzaC5hcHBseShvdXRwdXQsIG1hdGNoLnNsaWNlKDEpKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgbGFzdExlbmd0aCA9IG1hdGNoWzBdLmxlbmd0aDtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBsYXN0TGFzdEluZGV4ID0gbGFzdEluZGV4O1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChvdXRwdXQubGVuZ3RoID49IGxpbWl0KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChzZXBhcmF0b3IubGFzdEluZGV4ID09PSBtYXRjaC5pbmRleCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNlcGFyYXRvci5sYXN0SW5kZXgrKzsgLy8gQXZvaWQgYW4gaW5maW5pdGUgbG9vcFxuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIGlmIChsYXN0TGFzdEluZGV4ID09PSBzdHIubGVuZ3RoKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAobGFzdExlbmd0aCB8fCAhc2VwYXJhdG9yLnRlc3QoXCJcIikpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBvdXRwdXQucHVzaChcIlwiKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIG91dHB1dC5wdXNoKHN0ci5zbGljZShsYXN0TGFzdEluZGV4KSk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIG91dHB1dC5sZW5ndGggPiBsaW1pdCA/IG91dHB1dC5zbGljZSgwLCBsaW1pdCkgOiBvdXRwdXQ7XG4gICAgICAgICAgICAgICAgfTtcblxuICAgICAgICAgICAgICAgIHJldHVybiBzZWxmO1xuICAgICAgICAgICAgfSkoKTtcbiAgICAgICAgfSwge31dLCA2OiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge30sIHt9XSwgNzogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHtcbiAgICAgICAgICAgIFwidXNlIHN0cmljdFwiO1xuXG4gICAgICAgICAgICB2YXIgT25lVmVyc2lvbkNvbnN0cmFpbnQgPSByZXF1aXJlKFwiaW5kaXZpZHVhbC9vbmUtdmVyc2lvblwiKTtcblxuICAgICAgICAgICAgdmFyIE1ZX1ZFUlNJT04gPSBcIjdcIjtcbiAgICAgICAgICAgIE9uZVZlcnNpb25Db25zdHJhaW50KFwiZXYtc3RvcmVcIiwgTVlfVkVSU0lPTik7XG5cbiAgICAgICAgICAgIHZhciBoYXNoS2V5ID0gXCJfX0VWX1NUT1JFX0tFWUBcIiArIE1ZX1ZFUlNJT047XG5cbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gRXZTdG9yZTtcblxuICAgICAgICAgICAgZnVuY3Rpb24gRXZTdG9yZShlbGVtKSB7XG4gICAgICAgICAgICAgICAgdmFyIGhhc2ggPSBlbGVtW2hhc2hLZXldO1xuXG4gICAgICAgICAgICAgICAgaWYgKCFoYXNoKSB7XG4gICAgICAgICAgICAgICAgICAgIGhhc2ggPSBlbGVtW2hhc2hLZXldID0ge307XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgcmV0dXJuIGhhc2g7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0sIHsgXCJpbmRpdmlkdWFsL29uZS12ZXJzaW9uXCI6IDkgfV0sIDg6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICAoZnVuY3Rpb24gKGdsb2JhbCkge1xuICAgICAgICAgICAgICAgIFwidXNlIHN0cmljdFwiO1xuXG4gICAgICAgICAgICAgICAgLypnbG9iYWwgd2luZG93LCBnbG9iYWwqL1xuXG4gICAgICAgICAgICAgICAgdmFyIHJvb3QgPSB0eXBlb2Ygd2luZG93ICE9PSBcInVuZGVmaW5lZFwiID8gd2luZG93IDogdHlwZW9mIGdsb2JhbCAhPT0gXCJ1bmRlZmluZWRcIiA/IGdsb2JhbCA6IHt9O1xuXG4gICAgICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBJbmRpdmlkdWFsO1xuXG4gICAgICAgICAgICAgICAgZnVuY3Rpb24gSW5kaXZpZHVhbChrZXksIHZhbHVlKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmIChrZXkgaW4gcm9vdCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHJvb3Rba2V5XTtcbiAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgIHJvb3Rba2V5XSA9IHZhbHVlO1xuXG4gICAgICAgICAgICAgICAgICAgIHJldHVybiB2YWx1ZTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9KS5jYWxsKHRoaXMsIHR5cGVvZiBnbG9iYWwgIT09IFwidW5kZWZpbmVkXCIgPyBnbG9iYWwgOiB0eXBlb2Ygc2VsZiAhPT0gXCJ1bmRlZmluZWRcIiA/IHNlbGYgOiB0eXBlb2Ygd2luZG93ICE9PSBcInVuZGVmaW5lZFwiID8gd2luZG93IDoge30pO1xuICAgICAgICB9LCB7fV0sIDk6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICBcInVzZSBzdHJpY3RcIjtcblxuICAgICAgICAgICAgdmFyIEluZGl2aWR1YWwgPSByZXF1aXJlKFwiLi9pbmRleC5qc1wiKTtcblxuICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBPbmVWZXJzaW9uO1xuXG4gICAgICAgICAgICBmdW5jdGlvbiBPbmVWZXJzaW9uKG1vZHVsZU5hbWUsIHZlcnNpb24sIGRlZmF1bHRWYWx1ZSkge1xuICAgICAgICAgICAgICAgIHZhciBrZXkgPSBcIl9fSU5ESVZJRFVBTF9PTkVfVkVSU0lPTl9cIiArIG1vZHVsZU5hbWU7XG4gICAgICAgICAgICAgICAgdmFyIGVuZm9yY2VLZXkgPSBrZXkgKyBcIl9FTkZPUkNFX1NJTkdMRVRPTlwiO1xuXG4gICAgICAgICAgICAgICAgdmFyIHZlcnNpb25WYWx1ZSA9IEluZGl2aWR1YWwoZW5mb3JjZUtleSwgdmVyc2lvbik7XG5cbiAgICAgICAgICAgICAgICBpZiAodmVyc2lvblZhbHVlICE9PSB2ZXJzaW9uKSB7XG4gICAgICAgICAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcihcIkNhbiBvbmx5IGhhdmUgb25lIGNvcHkgb2YgXCIgKyBtb2R1bGVOYW1lICsgXCIuXFxuXCIgKyBcIllvdSBhbHJlYWR5IGhhdmUgdmVyc2lvbiBcIiArIHZlcnNpb25WYWx1ZSArIFwiIGluc3RhbGxlZC5cXG5cIiArIFwiVGhpcyBtZWFucyB5b3UgY2Fubm90IGluc3RhbGwgdmVyc2lvbiBcIiArIHZlcnNpb24pO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHJldHVybiBJbmRpdmlkdWFsKGtleSwgZGVmYXVsdFZhbHVlKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSwgeyBcIi4vaW5kZXguanNcIjogOCB9XSwgMTA6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICAoZnVuY3Rpb24gKGdsb2JhbCkge1xuICAgICAgICAgICAgICAgIHZhciB0b3BMZXZlbCA9IHR5cGVvZiBnbG9iYWwgIT09IFwidW5kZWZpbmVkXCIgPyBnbG9iYWwgOiB0eXBlb2Ygd2luZG93ICE9PSBcInVuZGVmaW5lZFwiID8gd2luZG93IDoge307XG4gICAgICAgICAgICAgICAgdmFyIG1pbkRvYyA9IHJlcXVpcmUoXCJtaW4tZG9jdW1lbnRcIik7XG5cbiAgICAgICAgICAgICAgICBpZiAodHlwZW9mIGRvY3VtZW50ICE9PSBcInVuZGVmaW5lZFwiKSB7XG4gICAgICAgICAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gZG9jdW1lbnQ7XG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgdmFyIGRvY2N5ID0gdG9wTGV2ZWxbXCJfX0dMT0JBTF9ET0NVTUVOVF9DQUNIRUA0XCJdO1xuXG4gICAgICAgICAgICAgICAgICAgIGlmICghZG9jY3kpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGRvY2N5ID0gdG9wTGV2ZWxbXCJfX0dMT0JBTF9ET0NVTUVOVF9DQUNIRUA0XCJdID0gbWluRG9jO1xuICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBkb2NjeTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9KS5jYWxsKHRoaXMsIHR5cGVvZiBnbG9iYWwgIT09IFwidW5kZWZpbmVkXCIgPyBnbG9iYWwgOiB0eXBlb2Ygc2VsZiAhPT0gXCJ1bmRlZmluZWRcIiA/IHNlbGYgOiB0eXBlb2Ygd2luZG93ICE9PSBcInVuZGVmaW5lZFwiID8gd2luZG93IDoge30pO1xuICAgICAgICB9LCB7IFwibWluLWRvY3VtZW50XCI6IDYgfV0sIDExOiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge1xuICAgICAgICAgICAgXCJ1c2Ugc3RyaWN0XCI7XG5cbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gaXNPYmplY3QoeCkge1xuICAgICAgICAgICAgICAgIHJldHVybiB0eXBlb2YgeCA9PT0gXCJvYmplY3RcIiAmJiB4ICE9PSBudWxsO1xuICAgICAgICAgICAgfTtcbiAgICAgICAgfSwge31dLCAxMjogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHtcbiAgICAgICAgICAgIHZhciBuYXRpdmVJc0FycmF5ID0gQXJyYXkuaXNBcnJheTtcbiAgICAgICAgICAgIHZhciB0b1N0cmluZyA9IE9iamVjdC5wcm90b3R5cGUudG9TdHJpbmc7XG5cbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gbmF0aXZlSXNBcnJheSB8fCBpc0FycmF5O1xuXG4gICAgICAgICAgICBmdW5jdGlvbiBpc0FycmF5KG9iaikge1xuICAgICAgICAgICAgICAgIHJldHVybiB0b1N0cmluZy5jYWxsKG9iaikgPT09IFwiW29iamVjdCBBcnJheV1cIjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSwge31dLCAxMzogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHtcbiAgICAgICAgICAgIHZhciBwYXRjaCA9IHJlcXVpcmUoXCIuL3Zkb20vcGF0Y2guanNcIik7XG5cbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gcGF0Y2g7XG4gICAgICAgIH0sIHsgXCIuL3Zkb20vcGF0Y2guanNcIjogMTggfV0sIDE0OiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge1xuICAgICAgICAgICAgdmFyIGlzT2JqZWN0ID0gcmVxdWlyZShcImlzLW9iamVjdFwiKTtcbiAgICAgICAgICAgIHZhciBpc0hvb2sgPSByZXF1aXJlKFwiLi4vdm5vZGUvaXMtdmhvb2suanNcIik7XG5cbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gYXBwbHlQcm9wZXJ0aWVzO1xuXG4gICAgICAgICAgICBmdW5jdGlvbiBhcHBseVByb3BlcnRpZXMobm9kZSwgcHJvcHMsIHByZXZpb3VzKSB7XG4gICAgICAgICAgICAgICAgZm9yICh2YXIgcHJvcE5hbWUgaW4gcHJvcHMpIHtcbiAgICAgICAgICAgICAgICAgICAgdmFyIHByb3BWYWx1ZSA9IHByb3BzW3Byb3BOYW1lXTtcblxuICAgICAgICAgICAgICAgICAgICBpZiAocHJvcFZhbHVlID09PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJlbW92ZVByb3BlcnR5KG5vZGUsIHByb3BOYW1lLCBwcm9wVmFsdWUsIHByZXZpb3VzKTtcbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIGlmIChpc0hvb2socHJvcFZhbHVlKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgcmVtb3ZlUHJvcGVydHkobm9kZSwgcHJvcE5hbWUsIHByb3BWYWx1ZSwgcHJldmlvdXMpO1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHByb3BWYWx1ZS5ob29rKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcHJvcFZhbHVlLmhvb2sobm9kZSwgcHJvcE5hbWUsIHByZXZpb3VzID8gcHJldmlvdXNbcHJvcE5hbWVdIDogdW5kZWZpbmVkKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChpc09iamVjdChwcm9wVmFsdWUpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcGF0Y2hPYmplY3Qobm9kZSwgcHJvcHMsIHByZXZpb3VzLCBwcm9wTmFtZSwgcHJvcFZhbHVlKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgbm9kZVtwcm9wTmFtZV0gPSBwcm9wVmFsdWU7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIHJlbW92ZVByb3BlcnR5KG5vZGUsIHByb3BOYW1lLCBwcm9wVmFsdWUsIHByZXZpb3VzKSB7XG4gICAgICAgICAgICAgICAgaWYgKHByZXZpb3VzKSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciBwcmV2aW91c1ZhbHVlID0gcHJldmlvdXNbcHJvcE5hbWVdO1xuXG4gICAgICAgICAgICAgICAgICAgIGlmICghaXNIb29rKHByZXZpb3VzVmFsdWUpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAocHJvcE5hbWUgPT09IFwiYXR0cmlidXRlc1wiKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgZm9yICh2YXIgYXR0ck5hbWUgaW4gcHJldmlvdXNWYWx1ZSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBub2RlLnJlbW92ZUF0dHJpYnV0ZShhdHRyTmFtZSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIGlmIChwcm9wTmFtZSA9PT0gXCJzdHlsZVwiKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgZm9yICh2YXIgaSBpbiBwcmV2aW91c1ZhbHVlKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG5vZGUuc3R5bGVbaV0gPSBcIlwiO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAodHlwZW9mIHByZXZpb3VzVmFsdWUgPT09IFwic3RyaW5nXCIpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBub2RlW3Byb3BOYW1lXSA9IFwiXCI7XG4gICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIG5vZGVbcHJvcE5hbWVdID0gbnVsbDtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIGlmIChwcmV2aW91c1ZhbHVlLnVuaG9vaykge1xuICAgICAgICAgICAgICAgICAgICAgICAgcHJldmlvdXNWYWx1ZS51bmhvb2sobm9kZSwgcHJvcE5hbWUsIHByb3BWYWx1ZSk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIHBhdGNoT2JqZWN0KG5vZGUsIHByb3BzLCBwcmV2aW91cywgcHJvcE5hbWUsIHByb3BWYWx1ZSkge1xuICAgICAgICAgICAgICAgIHZhciBwcmV2aW91c1ZhbHVlID0gcHJldmlvdXMgPyBwcmV2aW91c1twcm9wTmFtZV0gOiB1bmRlZmluZWQ7XG5cbiAgICAgICAgICAgICAgICAvLyBTZXQgYXR0cmlidXRlc1xuICAgICAgICAgICAgICAgIGlmIChwcm9wTmFtZSA9PT0gXCJhdHRyaWJ1dGVzXCIpIHtcbiAgICAgICAgICAgICAgICAgICAgZm9yICh2YXIgYXR0ck5hbWUgaW4gcHJvcFZhbHVlKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICB2YXIgYXR0clZhbHVlID0gcHJvcFZhbHVlW2F0dHJOYW1lXTtcblxuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGF0dHJWYWx1ZSA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgbm9kZS5yZW1vdmVBdHRyaWJ1dGUoYXR0ck5hbWUpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBub2RlLnNldEF0dHJpYnV0ZShhdHRyTmFtZSwgYXR0clZhbHVlKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICBpZiAocHJldmlvdXNWYWx1ZSAmJiBpc09iamVjdChwcmV2aW91c1ZhbHVlKSAmJiBnZXRQcm90b3R5cGUocHJldmlvdXNWYWx1ZSkgIT09IGdldFByb3RvdHlwZShwcm9wVmFsdWUpKSB7XG4gICAgICAgICAgICAgICAgICAgIG5vZGVbcHJvcE5hbWVdID0gcHJvcFZhbHVlO1xuICAgICAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgaWYgKCFpc09iamVjdChub2RlW3Byb3BOYW1lXSkpIHtcbiAgICAgICAgICAgICAgICAgICAgbm9kZVtwcm9wTmFtZV0gPSB7fTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICB2YXIgcmVwbGFjZXIgPSBwcm9wTmFtZSA9PT0gXCJzdHlsZVwiID8gXCJcIiA6IHVuZGVmaW5lZDtcblxuICAgICAgICAgICAgICAgIGZvciAodmFyIGsgaW4gcHJvcFZhbHVlKSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciB2YWx1ZSA9IHByb3BWYWx1ZVtrXTtcbiAgICAgICAgICAgICAgICAgICAgbm9kZVtwcm9wTmFtZV1ba10gPSB2YWx1ZSA9PT0gdW5kZWZpbmVkID8gcmVwbGFjZXIgOiB2YWx1ZTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIGdldFByb3RvdHlwZSh2YWx1ZSkge1xuICAgICAgICAgICAgICAgIGlmIChPYmplY3QuZ2V0UHJvdG90eXBlT2YpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIE9iamVjdC5nZXRQcm90b3R5cGVPZih2YWx1ZSk7XG4gICAgICAgICAgICAgICAgfSBlbHNlIGlmICh2YWx1ZS5fX3Byb3RvX18pIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHZhbHVlLl9fcHJvdG9fXztcbiAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKHZhbHVlLmNvbnN0cnVjdG9yKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiB2YWx1ZS5jb25zdHJ1Y3Rvci5wcm90b3R5cGU7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9LCB7IFwiLi4vdm5vZGUvaXMtdmhvb2suanNcIjogMjYsIFwiaXMtb2JqZWN0XCI6IDExIH1dLCAxNTogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHtcbiAgICAgICAgICAgIHZhciBkb2N1bWVudCA9IHJlcXVpcmUoXCJnbG9iYWwvZG9jdW1lbnRcIik7XG5cbiAgICAgICAgICAgIHZhciBhcHBseVByb3BlcnRpZXMgPSByZXF1aXJlKFwiLi9hcHBseS1wcm9wZXJ0aWVzXCIpO1xuXG4gICAgICAgICAgICB2YXIgaXNWTm9kZSA9IHJlcXVpcmUoXCIuLi92bm9kZS9pcy12bm9kZS5qc1wiKTtcbiAgICAgICAgICAgIHZhciBpc1ZUZXh0ID0gcmVxdWlyZShcIi4uL3Zub2RlL2lzLXZ0ZXh0LmpzXCIpO1xuICAgICAgICAgICAgdmFyIGlzV2lkZ2V0ID0gcmVxdWlyZShcIi4uL3Zub2RlL2lzLXdpZGdldC5qc1wiKTtcbiAgICAgICAgICAgIHZhciBoYW5kbGVUaHVuayA9IHJlcXVpcmUoXCIuLi92bm9kZS9oYW5kbGUtdGh1bmsuanNcIik7XG5cbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gY3JlYXRlRWxlbWVudDtcblxuICAgICAgICAgICAgZnVuY3Rpb24gY3JlYXRlRWxlbWVudCh2bm9kZSwgb3B0cykge1xuICAgICAgICAgICAgICAgIHZhciBkb2MgPSBvcHRzID8gb3B0cy5kb2N1bWVudCB8fCBkb2N1bWVudCA6IGRvY3VtZW50O1xuICAgICAgICAgICAgICAgIHZhciB3YXJuID0gb3B0cyA/IG9wdHMud2FybiA6IG51bGw7XG5cbiAgICAgICAgICAgICAgICB2bm9kZSA9IGhhbmRsZVRodW5rKHZub2RlKS5hO1xuXG4gICAgICAgICAgICAgICAgaWYgKGlzV2lkZ2V0KHZub2RlKSkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gdm5vZGUuaW5pdCgpO1xuICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoaXNWVGV4dCh2bm9kZSkpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGRvYy5jcmVhdGVUZXh0Tm9kZSh2bm9kZS50ZXh0KTtcbiAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKCFpc1ZOb2RlKHZub2RlKSkge1xuICAgICAgICAgICAgICAgICAgICBpZiAod2Fybikge1xuICAgICAgICAgICAgICAgICAgICAgICAgd2FybihcIkl0ZW0gaXMgbm90IGEgdmFsaWQgdmlydHVhbCBkb20gbm9kZVwiLCB2bm9kZSk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIG51bGw7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgdmFyIG5vZGUgPSB2bm9kZS5uYW1lc3BhY2UgPT09IG51bGwgPyBkb2MuY3JlYXRlRWxlbWVudCh2bm9kZS50YWdOYW1lKSA6IGRvYy5jcmVhdGVFbGVtZW50TlModm5vZGUubmFtZXNwYWNlLCB2bm9kZS50YWdOYW1lKTtcblxuICAgICAgICAgICAgICAgIHZhciBwcm9wcyA9IHZub2RlLnByb3BlcnRpZXM7XG4gICAgICAgICAgICAgICAgYXBwbHlQcm9wZXJ0aWVzKG5vZGUsIHByb3BzKTtcblxuICAgICAgICAgICAgICAgIHZhciBjaGlsZHJlbiA9IHZub2RlLmNoaWxkcmVuO1xuXG4gICAgICAgICAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCBjaGlsZHJlbi5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgICAgICAgICB2YXIgY2hpbGROb2RlID0gY3JlYXRlRWxlbWVudChjaGlsZHJlbltpXSwgb3B0cyk7XG4gICAgICAgICAgICAgICAgICAgIGlmIChjaGlsZE5vZGUpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIG5vZGUuYXBwZW5kQ2hpbGQoY2hpbGROb2RlKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHJldHVybiBub2RlO1xuICAgICAgICAgICAgfVxuICAgICAgICB9LCB7IFwiLi4vdm5vZGUvaGFuZGxlLXRodW5rLmpzXCI6IDI0LCBcIi4uL3Zub2RlL2lzLXZub2RlLmpzXCI6IDI3LCBcIi4uL3Zub2RlL2lzLXZ0ZXh0LmpzXCI6IDI4LCBcIi4uL3Zub2RlL2lzLXdpZGdldC5qc1wiOiAyOSwgXCIuL2FwcGx5LXByb3BlcnRpZXNcIjogMTQsIFwiZ2xvYmFsL2RvY3VtZW50XCI6IDEwIH1dLCAxNjogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHtcbiAgICAgICAgICAgIC8vIE1hcHMgYSB2aXJ0dWFsIERPTSB0cmVlIG9udG8gYSByZWFsIERPTSB0cmVlIGluIGFuIGVmZmljaWVudCBtYW5uZXIuXG4gICAgICAgICAgICAvLyBXZSBkb24ndCB3YW50IHRvIHJlYWQgYWxsIG9mIHRoZSBET00gbm9kZXMgaW4gdGhlIHRyZWUgc28gd2UgdXNlXG4gICAgICAgICAgICAvLyB0aGUgaW4tb3JkZXIgdHJlZSBpbmRleGluZyB0byBlbGltaW5hdGUgcmVjdXJzaW9uIGRvd24gY2VydGFpbiBicmFuY2hlcy5cbiAgICAgICAgICAgIC8vIFdlIG9ubHkgcmVjdXJzZSBpbnRvIGEgRE9NIG5vZGUgaWYgd2Uga25vdyB0aGF0IGl0IGNvbnRhaW5zIGEgY2hpbGQgb2ZcbiAgICAgICAgICAgIC8vIGludGVyZXN0LlxuXG4gICAgICAgICAgICB2YXIgbm9DaGlsZCA9IHt9O1xuXG4gICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IGRvbUluZGV4O1xuXG4gICAgICAgICAgICBmdW5jdGlvbiBkb21JbmRleChyb290Tm9kZSwgdHJlZSwgaW5kaWNlcywgbm9kZXMpIHtcbiAgICAgICAgICAgICAgICBpZiAoIWluZGljZXMgfHwgaW5kaWNlcy5sZW5ndGggPT09IDApIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHt9O1xuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIGluZGljZXMuc29ydChhc2NlbmRpbmcpO1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gcmVjdXJzZShyb290Tm9kZSwgdHJlZSwgaW5kaWNlcywgbm9kZXMsIDApO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZnVuY3Rpb24gcmVjdXJzZShyb290Tm9kZSwgdHJlZSwgaW5kaWNlcywgbm9kZXMsIHJvb3RJbmRleCkge1xuICAgICAgICAgICAgICAgIG5vZGVzID0gbm9kZXMgfHwge307XG5cbiAgICAgICAgICAgICAgICBpZiAocm9vdE5vZGUpIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKGluZGV4SW5SYW5nZShpbmRpY2VzLCByb290SW5kZXgsIHJvb3RJbmRleCkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIG5vZGVzW3Jvb3RJbmRleF0gPSByb290Tm9kZTtcbiAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgIHZhciB2Q2hpbGRyZW4gPSB0cmVlLmNoaWxkcmVuO1xuXG4gICAgICAgICAgICAgICAgICAgIGlmICh2Q2hpbGRyZW4pIHtcblxuICAgICAgICAgICAgICAgICAgICAgICAgdmFyIGNoaWxkTm9kZXMgPSByb290Tm9kZS5jaGlsZE5vZGVzO1xuXG4gICAgICAgICAgICAgICAgICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IHRyZWUuY2hpbGRyZW4ubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICByb290SW5kZXggKz0gMTtcblxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZhciB2Q2hpbGQgPSB2Q2hpbGRyZW5baV0gfHwgbm9DaGlsZDtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB2YXIgbmV4dEluZGV4ID0gcm9vdEluZGV4ICsgKHZDaGlsZC5jb3VudCB8fCAwKTtcblxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIHNraXAgcmVjdXJzaW9uIGRvd24gdGhlIHRyZWUgaWYgdGhlcmUgYXJlIG5vIG5vZGVzIGRvd24gaGVyZVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChpbmRleEluUmFuZ2UoaW5kaWNlcywgcm9vdEluZGV4LCBuZXh0SW5kZXgpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlY3Vyc2UoY2hpbGROb2Rlc1tpXSwgdkNoaWxkLCBpbmRpY2VzLCBub2Rlcywgcm9vdEluZGV4KTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICByb290SW5kZXggPSBuZXh0SW5kZXg7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICByZXR1cm4gbm9kZXM7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIC8vIEJpbmFyeSBzZWFyY2ggZm9yIGFuIGluZGV4IGluIHRoZSBpbnRlcnZhbCBbbGVmdCwgcmlnaHRdXG4gICAgICAgICAgICBmdW5jdGlvbiBpbmRleEluUmFuZ2UoaW5kaWNlcywgbGVmdCwgcmlnaHQpIHtcbiAgICAgICAgICAgICAgICBpZiAoaW5kaWNlcy5sZW5ndGggPT09IDApIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHZhciBtaW5JbmRleCA9IDA7XG4gICAgICAgICAgICAgICAgdmFyIG1heEluZGV4ID0gaW5kaWNlcy5sZW5ndGggLSAxO1xuICAgICAgICAgICAgICAgIHZhciBjdXJyZW50SW5kZXg7XG4gICAgICAgICAgICAgICAgdmFyIGN1cnJlbnRJdGVtO1xuXG4gICAgICAgICAgICAgICAgd2hpbGUgKG1pbkluZGV4IDw9IG1heEluZGV4KSB7XG4gICAgICAgICAgICAgICAgICAgIGN1cnJlbnRJbmRleCA9IChtYXhJbmRleCArIG1pbkluZGV4KSAvIDIgPj4gMDtcbiAgICAgICAgICAgICAgICAgICAgY3VycmVudEl0ZW0gPSBpbmRpY2VzW2N1cnJlbnRJbmRleF07XG5cbiAgICAgICAgICAgICAgICAgICAgaWYgKG1pbkluZGV4ID09PSBtYXhJbmRleCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGN1cnJlbnRJdGVtID49IGxlZnQgJiYgY3VycmVudEl0ZW0gPD0gcmlnaHQ7XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoY3VycmVudEl0ZW0gPCBsZWZ0KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBtaW5JbmRleCA9IGN1cnJlbnRJbmRleCArIDE7XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoY3VycmVudEl0ZW0gPiByaWdodCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgbWF4SW5kZXggPSBjdXJyZW50SW5kZXggLSAxO1xuICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIGFzY2VuZGluZyhhLCBiKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGEgPiBiID8gMSA6IC0xO1xuICAgICAgICAgICAgfVxuICAgICAgICB9LCB7fV0sIDE3OiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge1xuICAgICAgICAgICAgdmFyIGFwcGx5UHJvcGVydGllcyA9IHJlcXVpcmUoXCIuL2FwcGx5LXByb3BlcnRpZXNcIik7XG5cbiAgICAgICAgICAgIHZhciBpc1dpZGdldCA9IHJlcXVpcmUoXCIuLi92bm9kZS9pcy13aWRnZXQuanNcIik7XG4gICAgICAgICAgICB2YXIgVlBhdGNoID0gcmVxdWlyZShcIi4uL3Zub2RlL3ZwYXRjaC5qc1wiKTtcblxuICAgICAgICAgICAgdmFyIHVwZGF0ZVdpZGdldCA9IHJlcXVpcmUoXCIuL3VwZGF0ZS13aWRnZXRcIik7XG5cbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gYXBwbHlQYXRjaDtcblxuICAgICAgICAgICAgZnVuY3Rpb24gYXBwbHlQYXRjaCh2cGF0Y2gsIGRvbU5vZGUsIHJlbmRlck9wdGlvbnMpIHtcbiAgICAgICAgICAgICAgICB2YXIgdHlwZSA9IHZwYXRjaC50eXBlO1xuICAgICAgICAgICAgICAgIHZhciB2Tm9kZSA9IHZwYXRjaC52Tm9kZTtcbiAgICAgICAgICAgICAgICB2YXIgcGF0Y2ggPSB2cGF0Y2gucGF0Y2g7XG5cbiAgICAgICAgICAgICAgICBzd2l0Y2ggKHR5cGUpIHtcbiAgICAgICAgICAgICAgICAgICAgY2FzZSBWUGF0Y2guUkVNT1ZFOlxuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHJlbW92ZU5vZGUoZG9tTm9kZSwgdk5vZGUpO1xuICAgICAgICAgICAgICAgICAgICBjYXNlIFZQYXRjaC5JTlNFUlQ6XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gaW5zZXJ0Tm9kZShkb21Ob2RlLCBwYXRjaCwgcmVuZGVyT3B0aW9ucyk7XG4gICAgICAgICAgICAgICAgICAgIGNhc2UgVlBhdGNoLlZURVhUOlxuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHN0cmluZ1BhdGNoKGRvbU5vZGUsIHZOb2RlLCBwYXRjaCwgcmVuZGVyT3B0aW9ucyk7XG4gICAgICAgICAgICAgICAgICAgIGNhc2UgVlBhdGNoLldJREdFVDpcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiB3aWRnZXRQYXRjaChkb21Ob2RlLCB2Tm9kZSwgcGF0Y2gsIHJlbmRlck9wdGlvbnMpO1xuICAgICAgICAgICAgICAgICAgICBjYXNlIFZQYXRjaC5WTk9ERTpcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiB2Tm9kZVBhdGNoKGRvbU5vZGUsIHZOb2RlLCBwYXRjaCwgcmVuZGVyT3B0aW9ucyk7XG4gICAgICAgICAgICAgICAgICAgIGNhc2UgVlBhdGNoLk9SREVSOlxuICAgICAgICAgICAgICAgICAgICAgICAgcmVvcmRlckNoaWxkcmVuKGRvbU5vZGUsIHBhdGNoKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBkb21Ob2RlO1xuICAgICAgICAgICAgICAgICAgICBjYXNlIFZQYXRjaC5QUk9QUzpcbiAgICAgICAgICAgICAgICAgICAgICAgIGFwcGx5UHJvcGVydGllcyhkb21Ob2RlLCBwYXRjaCwgdk5vZGUucHJvcGVydGllcyk7XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gZG9tTm9kZTtcbiAgICAgICAgICAgICAgICAgICAgY2FzZSBWUGF0Y2guVEhVTks6XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gcmVwbGFjZVJvb3QoZG9tTm9kZSwgcmVuZGVyT3B0aW9ucy5wYXRjaChkb21Ob2RlLCBwYXRjaCwgcmVuZGVyT3B0aW9ucykpO1xuICAgICAgICAgICAgICAgICAgICBkZWZhdWx0OlxuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGRvbU5vZGU7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBmdW5jdGlvbiByZW1vdmVOb2RlKGRvbU5vZGUsIHZOb2RlKSB7XG4gICAgICAgICAgICAgICAgdmFyIHBhcmVudE5vZGUgPSBkb21Ob2RlLnBhcmVudE5vZGU7XG5cbiAgICAgICAgICAgICAgICBpZiAocGFyZW50Tm9kZSkge1xuICAgICAgICAgICAgICAgICAgICBwYXJlbnROb2RlLnJlbW92ZUNoaWxkKGRvbU5vZGUpO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIGRlc3Ryb3lXaWRnZXQoZG9tTm9kZSwgdk5vZGUpO1xuXG4gICAgICAgICAgICAgICAgcmV0dXJuIG51bGw7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIGluc2VydE5vZGUocGFyZW50Tm9kZSwgdk5vZGUsIHJlbmRlck9wdGlvbnMpIHtcbiAgICAgICAgICAgICAgICB2YXIgbmV3Tm9kZSA9IHJlbmRlck9wdGlvbnMucmVuZGVyKHZOb2RlLCByZW5kZXJPcHRpb25zKTtcblxuICAgICAgICAgICAgICAgIGlmIChwYXJlbnROb2RlKSB7XG4gICAgICAgICAgICAgICAgICAgIHBhcmVudE5vZGUuYXBwZW5kQ2hpbGQobmV3Tm9kZSk7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgcmV0dXJuIHBhcmVudE5vZGU7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIHN0cmluZ1BhdGNoKGRvbU5vZGUsIGxlZnRWTm9kZSwgdlRleHQsIHJlbmRlck9wdGlvbnMpIHtcbiAgICAgICAgICAgICAgICB2YXIgbmV3Tm9kZTtcblxuICAgICAgICAgICAgICAgIGlmIChkb21Ob2RlLm5vZGVUeXBlID09PSAzKSB7XG4gICAgICAgICAgICAgICAgICAgIGRvbU5vZGUucmVwbGFjZURhdGEoMCwgZG9tTm9kZS5sZW5ndGgsIHZUZXh0LnRleHQpO1xuICAgICAgICAgICAgICAgICAgICBuZXdOb2RlID0gZG9tTm9kZTtcbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICB2YXIgcGFyZW50Tm9kZSA9IGRvbU5vZGUucGFyZW50Tm9kZTtcbiAgICAgICAgICAgICAgICAgICAgbmV3Tm9kZSA9IHJlbmRlck9wdGlvbnMucmVuZGVyKHZUZXh0LCByZW5kZXJPcHRpb25zKTtcblxuICAgICAgICAgICAgICAgICAgICBpZiAocGFyZW50Tm9kZSAmJiBuZXdOb2RlICE9PSBkb21Ob2RlKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBwYXJlbnROb2RlLnJlcGxhY2VDaGlsZChuZXdOb2RlLCBkb21Ob2RlKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHJldHVybiBuZXdOb2RlO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBmdW5jdGlvbiB3aWRnZXRQYXRjaChkb21Ob2RlLCBsZWZ0Vk5vZGUsIHdpZGdldCwgcmVuZGVyT3B0aW9ucykge1xuICAgICAgICAgICAgICAgIHZhciB1cGRhdGluZyA9IHVwZGF0ZVdpZGdldChsZWZ0Vk5vZGUsIHdpZGdldCk7XG4gICAgICAgICAgICAgICAgdmFyIG5ld05vZGU7XG5cbiAgICAgICAgICAgICAgICBpZiAodXBkYXRpbmcpIHtcbiAgICAgICAgICAgICAgICAgICAgbmV3Tm9kZSA9IHdpZGdldC51cGRhdGUobGVmdFZOb2RlLCBkb21Ob2RlKSB8fCBkb21Ob2RlO1xuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIG5ld05vZGUgPSByZW5kZXJPcHRpb25zLnJlbmRlcih3aWRnZXQsIHJlbmRlck9wdGlvbnMpO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHZhciBwYXJlbnROb2RlID0gZG9tTm9kZS5wYXJlbnROb2RlO1xuXG4gICAgICAgICAgICAgICAgaWYgKHBhcmVudE5vZGUgJiYgbmV3Tm9kZSAhPT0gZG9tTm9kZSkge1xuICAgICAgICAgICAgICAgICAgICBwYXJlbnROb2RlLnJlcGxhY2VDaGlsZChuZXdOb2RlLCBkb21Ob2RlKTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICBpZiAoIXVwZGF0aW5nKSB7XG4gICAgICAgICAgICAgICAgICAgIGRlc3Ryb3lXaWRnZXQoZG9tTm9kZSwgbGVmdFZOb2RlKTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICByZXR1cm4gbmV3Tm9kZTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZnVuY3Rpb24gdk5vZGVQYXRjaChkb21Ob2RlLCBsZWZ0Vk5vZGUsIHZOb2RlLCByZW5kZXJPcHRpb25zKSB7XG4gICAgICAgICAgICAgICAgdmFyIHBhcmVudE5vZGUgPSBkb21Ob2RlLnBhcmVudE5vZGU7XG4gICAgICAgICAgICAgICAgdmFyIG5ld05vZGUgPSByZW5kZXJPcHRpb25zLnJlbmRlcih2Tm9kZSwgcmVuZGVyT3B0aW9ucyk7XG5cbiAgICAgICAgICAgICAgICBpZiAocGFyZW50Tm9kZSAmJiBuZXdOb2RlICE9PSBkb21Ob2RlKSB7XG4gICAgICAgICAgICAgICAgICAgIHBhcmVudE5vZGUucmVwbGFjZUNoaWxkKG5ld05vZGUsIGRvbU5vZGUpO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHJldHVybiBuZXdOb2RlO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBmdW5jdGlvbiBkZXN0cm95V2lkZ2V0KGRvbU5vZGUsIHcpIHtcbiAgICAgICAgICAgICAgICBpZiAodHlwZW9mIHcuZGVzdHJveSA9PT0gXCJmdW5jdGlvblwiICYmIGlzV2lkZ2V0KHcpKSB7XG4gICAgICAgICAgICAgICAgICAgIHcuZGVzdHJveShkb21Ob2RlKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIHJlb3JkZXJDaGlsZHJlbihkb21Ob2RlLCBtb3Zlcykge1xuICAgICAgICAgICAgICAgIHZhciBjaGlsZE5vZGVzID0gZG9tTm9kZS5jaGlsZE5vZGVzO1xuICAgICAgICAgICAgICAgIHZhciBrZXlNYXAgPSB7fTtcbiAgICAgICAgICAgICAgICB2YXIgbm9kZTtcbiAgICAgICAgICAgICAgICB2YXIgcmVtb3ZlO1xuICAgICAgICAgICAgICAgIHZhciBpbnNlcnQ7XG5cbiAgICAgICAgICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IG1vdmVzLnJlbW92ZXMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgICAgICAgICAgcmVtb3ZlID0gbW92ZXMucmVtb3Zlc1tpXTtcbiAgICAgICAgICAgICAgICAgICAgbm9kZSA9IGNoaWxkTm9kZXNbcmVtb3ZlLmZyb21dO1xuICAgICAgICAgICAgICAgICAgICBpZiAocmVtb3ZlLmtleSkge1xuICAgICAgICAgICAgICAgICAgICAgICAga2V5TWFwW3JlbW92ZS5rZXldID0gbm9kZTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICBkb21Ob2RlLnJlbW92ZUNoaWxkKG5vZGUpO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHZhciBsZW5ndGggPSBjaGlsZE5vZGVzLmxlbmd0aDtcbiAgICAgICAgICAgICAgICBmb3IgKHZhciBqID0gMDsgaiA8IG1vdmVzLmluc2VydHMubGVuZ3RoOyBqKyspIHtcbiAgICAgICAgICAgICAgICAgICAgaW5zZXJ0ID0gbW92ZXMuaW5zZXJ0c1tqXTtcbiAgICAgICAgICAgICAgICAgICAgbm9kZSA9IGtleU1hcFtpbnNlcnQua2V5XTtcbiAgICAgICAgICAgICAgICAgICAgLy8gdGhpcyBpcyB0aGUgd2VpcmRlc3QgYnVnIGkndmUgZXZlciBzZWVuIGluIHdlYmtpdFxuICAgICAgICAgICAgICAgICAgICBkb21Ob2RlLmluc2VydEJlZm9yZShub2RlLCBpbnNlcnQudG8gPj0gbGVuZ3RoKysgPyBudWxsIDogY2hpbGROb2Rlc1tpbnNlcnQudG9dKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIHJlcGxhY2VSb290KG9sZFJvb3QsIG5ld1Jvb3QpIHtcbiAgICAgICAgICAgICAgICBpZiAob2xkUm9vdCAmJiBuZXdSb290ICYmIG9sZFJvb3QgIT09IG5ld1Jvb3QgJiYgb2xkUm9vdC5wYXJlbnROb2RlKSB7XG4gICAgICAgICAgICAgICAgICAgIG9sZFJvb3QucGFyZW50Tm9kZS5yZXBsYWNlQ2hpbGQobmV3Um9vdCwgb2xkUm9vdCk7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgcmV0dXJuIG5ld1Jvb3Q7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0sIHsgXCIuLi92bm9kZS9pcy13aWRnZXQuanNcIjogMjksIFwiLi4vdm5vZGUvdnBhdGNoLmpzXCI6IDMyLCBcIi4vYXBwbHktcHJvcGVydGllc1wiOiAxNCwgXCIuL3VwZGF0ZS13aWRnZXRcIjogMTkgfV0sIDE4OiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge1xuICAgICAgICAgICAgdmFyIGRvY3VtZW50ID0gcmVxdWlyZShcImdsb2JhbC9kb2N1bWVudFwiKTtcbiAgICAgICAgICAgIHZhciBpc0FycmF5ID0gcmVxdWlyZShcIngtaXMtYXJyYXlcIik7XG5cbiAgICAgICAgICAgIHZhciByZW5kZXIgPSByZXF1aXJlKFwiLi9jcmVhdGUtZWxlbWVudFwiKTtcbiAgICAgICAgICAgIHZhciBkb21JbmRleCA9IHJlcXVpcmUoXCIuL2RvbS1pbmRleFwiKTtcbiAgICAgICAgICAgIHZhciBwYXRjaE9wID0gcmVxdWlyZShcIi4vcGF0Y2gtb3BcIik7XG4gICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IHBhdGNoO1xuXG4gICAgICAgICAgICBmdW5jdGlvbiBwYXRjaChyb290Tm9kZSwgcGF0Y2hlcywgcmVuZGVyT3B0aW9ucykge1xuICAgICAgICAgICAgICAgIHJlbmRlck9wdGlvbnMgPSByZW5kZXJPcHRpb25zIHx8IHt9O1xuICAgICAgICAgICAgICAgIHJlbmRlck9wdGlvbnMucGF0Y2ggPSByZW5kZXJPcHRpb25zLnBhdGNoICYmIHJlbmRlck9wdGlvbnMucGF0Y2ggIT09IHBhdGNoID8gcmVuZGVyT3B0aW9ucy5wYXRjaCA6IHBhdGNoUmVjdXJzaXZlO1xuICAgICAgICAgICAgICAgIHJlbmRlck9wdGlvbnMucmVuZGVyID0gcmVuZGVyT3B0aW9ucy5yZW5kZXIgfHwgcmVuZGVyO1xuXG4gICAgICAgICAgICAgICAgcmV0dXJuIHJlbmRlck9wdGlvbnMucGF0Y2gocm9vdE5vZGUsIHBhdGNoZXMsIHJlbmRlck9wdGlvbnMpO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBmdW5jdGlvbiBwYXRjaFJlY3Vyc2l2ZShyb290Tm9kZSwgcGF0Y2hlcywgcmVuZGVyT3B0aW9ucykge1xuICAgICAgICAgICAgICAgIHZhciBpbmRpY2VzID0gcGF0Y2hJbmRpY2VzKHBhdGNoZXMpO1xuXG4gICAgICAgICAgICAgICAgaWYgKGluZGljZXMubGVuZ3RoID09PSAwKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiByb290Tm9kZTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICB2YXIgaW5kZXggPSBkb21JbmRleChyb290Tm9kZSwgcGF0Y2hlcy5hLCBpbmRpY2VzKTtcbiAgICAgICAgICAgICAgICB2YXIgb3duZXJEb2N1bWVudCA9IHJvb3ROb2RlLm93bmVyRG9jdW1lbnQ7XG5cbiAgICAgICAgICAgICAgICBpZiAoIXJlbmRlck9wdGlvbnMuZG9jdW1lbnQgJiYgb3duZXJEb2N1bWVudCAhPT0gZG9jdW1lbnQpIHtcbiAgICAgICAgICAgICAgICAgICAgcmVuZGVyT3B0aW9ucy5kb2N1bWVudCA9IG93bmVyRG9jdW1lbnQ7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCBpbmRpY2VzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciBub2RlSW5kZXggPSBpbmRpY2VzW2ldO1xuICAgICAgICAgICAgICAgICAgICByb290Tm9kZSA9IGFwcGx5UGF0Y2gocm9vdE5vZGUsIGluZGV4W25vZGVJbmRleF0sIHBhdGNoZXNbbm9kZUluZGV4XSwgcmVuZGVyT3B0aW9ucyk7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgcmV0dXJuIHJvb3ROb2RlO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBmdW5jdGlvbiBhcHBseVBhdGNoKHJvb3ROb2RlLCBkb21Ob2RlLCBwYXRjaExpc3QsIHJlbmRlck9wdGlvbnMpIHtcbiAgICAgICAgICAgICAgICBpZiAoIWRvbU5vZGUpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHJvb3ROb2RlO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHZhciBuZXdOb2RlO1xuXG4gICAgICAgICAgICAgICAgaWYgKGlzQXJyYXkocGF0Y2hMaXN0KSkge1xuICAgICAgICAgICAgICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IHBhdGNoTGlzdC5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgICAgICAgICAgICAgbmV3Tm9kZSA9IHBhdGNoT3AocGF0Y2hMaXN0W2ldLCBkb21Ob2RlLCByZW5kZXJPcHRpb25zKTtcblxuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGRvbU5vZGUgPT09IHJvb3ROb2RlKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcm9vdE5vZGUgPSBuZXdOb2RlO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgbmV3Tm9kZSA9IHBhdGNoT3AocGF0Y2hMaXN0LCBkb21Ob2RlLCByZW5kZXJPcHRpb25zKTtcblxuICAgICAgICAgICAgICAgICAgICBpZiAoZG9tTm9kZSA9PT0gcm9vdE5vZGUpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJvb3ROb2RlID0gbmV3Tm9kZTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHJldHVybiByb290Tm9kZTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZnVuY3Rpb24gcGF0Y2hJbmRpY2VzKHBhdGNoZXMpIHtcbiAgICAgICAgICAgICAgICB2YXIgaW5kaWNlcyA9IFtdO1xuXG4gICAgICAgICAgICAgICAgZm9yICh2YXIga2V5IGluIHBhdGNoZXMpIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKGtleSAhPT0gXCJhXCIpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGluZGljZXMucHVzaChOdW1iZXIoa2V5KSk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICByZXR1cm4gaW5kaWNlcztcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSwgeyBcIi4vY3JlYXRlLWVsZW1lbnRcIjogMTUsIFwiLi9kb20taW5kZXhcIjogMTYsIFwiLi9wYXRjaC1vcFwiOiAxNywgXCJnbG9iYWwvZG9jdW1lbnRcIjogMTAsIFwieC1pcy1hcnJheVwiOiAxMiB9XSwgMTk6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICB2YXIgaXNXaWRnZXQgPSByZXF1aXJlKFwiLi4vdm5vZGUvaXMtd2lkZ2V0LmpzXCIpO1xuXG4gICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IHVwZGF0ZVdpZGdldDtcblxuICAgICAgICAgICAgZnVuY3Rpb24gdXBkYXRlV2lkZ2V0KGEsIGIpIHtcbiAgICAgICAgICAgICAgICBpZiAoaXNXaWRnZXQoYSkgJiYgaXNXaWRnZXQoYikpIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKFwibmFtZVwiIGluIGEgJiYgXCJuYW1lXCIgaW4gYikge1xuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGEuaWQgPT09IGIuaWQ7XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gYS5pbml0ID09PSBiLmluaXQ7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0sIHsgXCIuLi92bm9kZS9pcy13aWRnZXQuanNcIjogMjkgfV0sIDIwOiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge1xuICAgICAgICAgICAgXCJ1c2Ugc3RyaWN0XCI7XG5cbiAgICAgICAgICAgIHZhciBFdlN0b3JlID0gcmVxdWlyZShcImV2LXN0b3JlXCIpO1xuXG4gICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IEV2SG9vaztcblxuICAgICAgICAgICAgZnVuY3Rpb24gRXZIb29rKHZhbHVlKSB7XG4gICAgICAgICAgICAgICAgaWYgKCEodGhpcyBpbnN0YW5jZW9mIEV2SG9vaykpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIG5ldyBFdkhvb2sodmFsdWUpO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHRoaXMudmFsdWUgPSB2YWx1ZTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgRXZIb29rLnByb3RvdHlwZS5ob29rID0gZnVuY3Rpb24gKG5vZGUsIHByb3BlcnR5TmFtZSkge1xuICAgICAgICAgICAgICAgIHZhciBlcyA9IEV2U3RvcmUobm9kZSk7XG4gICAgICAgICAgICAgICAgdmFyIHByb3BOYW1lID0gcHJvcGVydHlOYW1lLnN1YnN0cigzKTtcblxuICAgICAgICAgICAgICAgIGVzW3Byb3BOYW1lXSA9IHRoaXMudmFsdWU7XG4gICAgICAgICAgICB9O1xuXG4gICAgICAgICAgICBFdkhvb2sucHJvdG90eXBlLnVuaG9vayA9IGZ1bmN0aW9uIChub2RlLCBwcm9wZXJ0eU5hbWUpIHtcbiAgICAgICAgICAgICAgICB2YXIgZXMgPSBFdlN0b3JlKG5vZGUpO1xuICAgICAgICAgICAgICAgIHZhciBwcm9wTmFtZSA9IHByb3BlcnR5TmFtZS5zdWJzdHIoMyk7XG5cbiAgICAgICAgICAgICAgICBlc1twcm9wTmFtZV0gPSB1bmRlZmluZWQ7XG4gICAgICAgICAgICB9O1xuICAgICAgICB9LCB7IFwiZXYtc3RvcmVcIjogNyB9XSwgMjE6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICBcInVzZSBzdHJpY3RcIjtcblxuICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBTb2Z0U2V0SG9vaztcblxuICAgICAgICAgICAgZnVuY3Rpb24gU29mdFNldEhvb2sodmFsdWUpIHtcbiAgICAgICAgICAgICAgICBpZiAoISh0aGlzIGluc3RhbmNlb2YgU29mdFNldEhvb2spKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBuZXcgU29mdFNldEhvb2sodmFsdWUpO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHRoaXMudmFsdWUgPSB2YWx1ZTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgU29mdFNldEhvb2sucHJvdG90eXBlLmhvb2sgPSBmdW5jdGlvbiAobm9kZSwgcHJvcGVydHlOYW1lKSB7XG4gICAgICAgICAgICAgICAgaWYgKG5vZGVbcHJvcGVydHlOYW1lXSAhPT0gdGhpcy52YWx1ZSkge1xuICAgICAgICAgICAgICAgICAgICBub2RlW3Byb3BlcnR5TmFtZV0gPSB0aGlzLnZhbHVlO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH07XG4gICAgICAgIH0sIHt9XSwgMjI6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICBcInVzZSBzdHJpY3RcIjtcblxuICAgICAgICAgICAgdmFyIGlzQXJyYXkgPSByZXF1aXJlKFwieC1pcy1hcnJheVwiKTtcblxuICAgICAgICAgICAgdmFyIFZOb2RlID0gcmVxdWlyZShcIi4uL3Zub2RlL3Zub2RlLmpzXCIpO1xuICAgICAgICAgICAgdmFyIFZUZXh0ID0gcmVxdWlyZShcIi4uL3Zub2RlL3Z0ZXh0LmpzXCIpO1xuICAgICAgICAgICAgdmFyIGlzVk5vZGUgPSByZXF1aXJlKFwiLi4vdm5vZGUvaXMtdm5vZGVcIik7XG4gICAgICAgICAgICB2YXIgaXNWVGV4dCA9IHJlcXVpcmUoXCIuLi92bm9kZS9pcy12dGV4dFwiKTtcbiAgICAgICAgICAgIHZhciBpc1dpZGdldCA9IHJlcXVpcmUoXCIuLi92bm9kZS9pcy13aWRnZXRcIik7XG4gICAgICAgICAgICB2YXIgaXNIb29rID0gcmVxdWlyZShcIi4uL3Zub2RlL2lzLXZob29rXCIpO1xuICAgICAgICAgICAgdmFyIGlzVlRodW5rID0gcmVxdWlyZShcIi4uL3Zub2RlL2lzLXRodW5rXCIpO1xuXG4gICAgICAgICAgICB2YXIgcGFyc2VUYWcgPSByZXF1aXJlKFwiLi9wYXJzZS10YWcuanNcIik7XG4gICAgICAgICAgICB2YXIgc29mdFNldEhvb2sgPSByZXF1aXJlKFwiLi9ob29rcy9zb2Z0LXNldC1ob29rLmpzXCIpO1xuICAgICAgICAgICAgdmFyIGV2SG9vayA9IHJlcXVpcmUoXCIuL2hvb2tzL2V2LWhvb2suanNcIik7XG5cbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gaDtcblxuICAgICAgICAgICAgZnVuY3Rpb24gaCh0YWdOYW1lLCBwcm9wZXJ0aWVzLCBjaGlsZHJlbikge1xuICAgICAgICAgICAgICAgIHZhciBjaGlsZE5vZGVzID0gW107XG4gICAgICAgICAgICAgICAgdmFyIHRhZywgcHJvcHMsIGtleSwgbmFtZXNwYWNlO1xuXG4gICAgICAgICAgICAgICAgaWYgKCFjaGlsZHJlbiAmJiBpc0NoaWxkcmVuKHByb3BlcnRpZXMpKSB7XG4gICAgICAgICAgICAgICAgICAgIGNoaWxkcmVuID0gcHJvcGVydGllcztcbiAgICAgICAgICAgICAgICAgICAgcHJvcHMgPSB7fTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICBwcm9wcyA9IHByb3BzIHx8IHByb3BlcnRpZXMgfHwge307XG4gICAgICAgICAgICAgICAgdGFnID0gcGFyc2VUYWcodGFnTmFtZSwgcHJvcHMpO1xuXG4gICAgICAgICAgICAgICAgLy8gc3VwcG9ydCBrZXlzXG4gICAgICAgICAgICAgICAgaWYgKHByb3BzLmhhc093blByb3BlcnR5KFwia2V5XCIpKSB7XG4gICAgICAgICAgICAgICAgICAgIGtleSA9IHByb3BzLmtleTtcbiAgICAgICAgICAgICAgICAgICAgcHJvcHMua2V5ID0gdW5kZWZpbmVkO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIC8vIHN1cHBvcnQgbmFtZXNwYWNlXG4gICAgICAgICAgICAgICAgaWYgKHByb3BzLmhhc093blByb3BlcnR5KFwibmFtZXNwYWNlXCIpKSB7XG4gICAgICAgICAgICAgICAgICAgIG5hbWVzcGFjZSA9IHByb3BzLm5hbWVzcGFjZTtcbiAgICAgICAgICAgICAgICAgICAgcHJvcHMubmFtZXNwYWNlID0gdW5kZWZpbmVkO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIC8vIGZpeCBjdXJzb3IgYnVnXG4gICAgICAgICAgICAgICAgaWYgKHRhZyA9PT0gXCJJTlBVVFwiICYmICFuYW1lc3BhY2UgJiYgcHJvcHMuaGFzT3duUHJvcGVydHkoXCJ2YWx1ZVwiKSAmJiBwcm9wcy52YWx1ZSAhPT0gdW5kZWZpbmVkICYmICFpc0hvb2socHJvcHMudmFsdWUpKSB7XG4gICAgICAgICAgICAgICAgICAgIHByb3BzLnZhbHVlID0gc29mdFNldEhvb2socHJvcHMudmFsdWUpO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHRyYW5zZm9ybVByb3BlcnRpZXMocHJvcHMpO1xuXG4gICAgICAgICAgICAgICAgaWYgKGNoaWxkcmVuICE9PSB1bmRlZmluZWQgJiYgY2hpbGRyZW4gIT09IG51bGwpIHtcbiAgICAgICAgICAgICAgICAgICAgYWRkQ2hpbGQoY2hpbGRyZW4sIGNoaWxkTm9kZXMsIHRhZywgcHJvcHMpO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHJldHVybiBuZXcgVk5vZGUodGFnLCBwcm9wcywgY2hpbGROb2Rlcywga2V5LCBuYW1lc3BhY2UpO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBmdW5jdGlvbiBhZGRDaGlsZChjLCBjaGlsZE5vZGVzLCB0YWcsIHByb3BzKSB7XG4gICAgICAgICAgICAgICAgaWYgKHR5cGVvZiBjID09PSBcInN0cmluZ1wiKSB7XG4gICAgICAgICAgICAgICAgICAgIGNoaWxkTm9kZXMucHVzaChuZXcgVlRleHQoYykpO1xuICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAodHlwZW9mIGMgPT09IFwibnVtYmVyXCIpIHtcbiAgICAgICAgICAgICAgICAgICAgY2hpbGROb2Rlcy5wdXNoKG5ldyBWVGV4dChTdHJpbmcoYykpKTtcbiAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKGlzQ2hpbGQoYykpIHtcbiAgICAgICAgICAgICAgICAgICAgY2hpbGROb2Rlcy5wdXNoKGMpO1xuICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoaXNBcnJheShjKSkge1xuICAgICAgICAgICAgICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IGMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGFkZENoaWxkKGNbaV0sIGNoaWxkTm9kZXMsIHRhZywgcHJvcHMpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfSBlbHNlIGlmIChjID09PSBudWxsIHx8IGMgPT09IHVuZGVmaW5lZCkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgdGhyb3cgVW5leHBlY3RlZFZpcnR1YWxFbGVtZW50KHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGZvcmVpZ25PYmplY3Q6IGMsXG4gICAgICAgICAgICAgICAgICAgICAgICBwYXJlbnRWbm9kZToge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRhZ05hbWU6IHRhZyxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBwcm9wZXJ0aWVzOiBwcm9wc1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIHRyYW5zZm9ybVByb3BlcnRpZXMocHJvcHMpIHtcbiAgICAgICAgICAgICAgICBmb3IgKHZhciBwcm9wTmFtZSBpbiBwcm9wcykge1xuICAgICAgICAgICAgICAgICAgICBpZiAocHJvcHMuaGFzT3duUHJvcGVydHkocHJvcE5hbWUpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICB2YXIgdmFsdWUgPSBwcm9wc1twcm9wTmFtZV07XG5cbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChpc0hvb2sodmFsdWUpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgY29udGludWU7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChwcm9wTmFtZS5zdWJzdHIoMCwgMykgPT09IFwiZXYtXCIpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBhZGQgZXYtZm9vIHN1cHBvcnRcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBwcm9wc1twcm9wTmFtZV0gPSBldkhvb2sodmFsdWUpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBmdW5jdGlvbiBpc0NoaWxkKHgpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gaXNWTm9kZSh4KSB8fCBpc1ZUZXh0KHgpIHx8IGlzV2lkZ2V0KHgpIHx8IGlzVlRodW5rKHgpO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBmdW5jdGlvbiBpc0NoaWxkcmVuKHgpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gdHlwZW9mIHggPT09IFwic3RyaW5nXCIgfHwgaXNBcnJheSh4KSB8fCBpc0NoaWxkKHgpO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBmdW5jdGlvbiBVbmV4cGVjdGVkVmlydHVhbEVsZW1lbnQoZGF0YSkge1xuICAgICAgICAgICAgICAgIHZhciBlcnIgPSBuZXcgRXJyb3IoKTtcblxuICAgICAgICAgICAgICAgIGVyci50eXBlID0gXCJ2aXJ0dWFsLWh5cGVyc2NyaXB0LnVuZXhwZWN0ZWQudmlydHVhbC1lbGVtZW50XCI7XG4gICAgICAgICAgICAgICAgZXJyLm1lc3NhZ2UgPSBcIlVuZXhwZWN0ZWQgdmlydHVhbCBjaGlsZCBwYXNzZWQgdG8gaCgpLlxcblwiICsgXCJFeHBlY3RlZCBhIFZOb2RlIC8gVnRodW5rIC8gVldpZGdldCAvIHN0cmluZyBidXQ6XFxuXCIgKyBcImdvdDpcXG5cIiArIGVycm9yU3RyaW5nKGRhdGEuZm9yZWlnbk9iamVjdCkgKyBcIi5cXG5cIiArIFwiVGhlIHBhcmVudCB2bm9kZSBpczpcXG5cIiArIGVycm9yU3RyaW5nKGRhdGEucGFyZW50Vm5vZGUpO1xuICAgICAgICAgICAgICAgIFwiXFxuXCIgKyBcIlN1Z2dlc3RlZCBmaXg6IGNoYW5nZSB5b3VyIGBoKC4uLiwgWyAuLi4gXSlgIGNhbGxzaXRlLlwiO1xuICAgICAgICAgICAgICAgIGVyci5mb3JlaWduT2JqZWN0ID0gZGF0YS5mb3JlaWduT2JqZWN0O1xuICAgICAgICAgICAgICAgIGVyci5wYXJlbnRWbm9kZSA9IGRhdGEucGFyZW50Vm5vZGU7XG5cbiAgICAgICAgICAgICAgICByZXR1cm4gZXJyO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBmdW5jdGlvbiBlcnJvclN0cmluZyhvYmopIHtcbiAgICAgICAgICAgICAgICB0cnkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gSlNPTi5zdHJpbmdpZnkob2JqLCBudWxsLCBcIiAgICBcIik7XG4gICAgICAgICAgICAgICAgfSBjYXRjaCAoZSkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gU3RyaW5nKG9iaik7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9LCB7IFwiLi4vdm5vZGUvaXMtdGh1bmtcIjogMjUsIFwiLi4vdm5vZGUvaXMtdmhvb2tcIjogMjYsIFwiLi4vdm5vZGUvaXMtdm5vZGVcIjogMjcsIFwiLi4vdm5vZGUvaXMtdnRleHRcIjogMjgsIFwiLi4vdm5vZGUvaXMtd2lkZ2V0XCI6IDI5LCBcIi4uL3Zub2RlL3Zub2RlLmpzXCI6IDMxLCBcIi4uL3Zub2RlL3Z0ZXh0LmpzXCI6IDMzLCBcIi4vaG9va3MvZXYtaG9vay5qc1wiOiAyMCwgXCIuL2hvb2tzL3NvZnQtc2V0LWhvb2suanNcIjogMjEsIFwiLi9wYXJzZS10YWcuanNcIjogMjMsIFwieC1pcy1hcnJheVwiOiAxMiB9XSwgMjM6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICBcInVzZSBzdHJpY3RcIjtcblxuICAgICAgICAgICAgdmFyIHNwbGl0ID0gcmVxdWlyZShcImJyb3dzZXItc3BsaXRcIik7XG5cbiAgICAgICAgICAgIHZhciBjbGFzc0lkU3BsaXQgPSAvKFtcXC4jXT9bYS16QS1aMC05XFx1MDA3Ri1cXHVGRkZGXzotXSspLztcbiAgICAgICAgICAgIHZhciBub3RDbGFzc0lkID0gL15cXC58Iy87XG5cbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gcGFyc2VUYWc7XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIHBhcnNlVGFnKHRhZywgcHJvcHMpIHtcbiAgICAgICAgICAgICAgICBpZiAoIXRhZykge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gXCJESVZcIjtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICB2YXIgbm9JZCA9ICFwcm9wcy5oYXNPd25Qcm9wZXJ0eShcImlkXCIpO1xuXG4gICAgICAgICAgICAgICAgdmFyIHRhZ1BhcnRzID0gc3BsaXQodGFnLCBjbGFzc0lkU3BsaXQpO1xuICAgICAgICAgICAgICAgIHZhciB0YWdOYW1lID0gbnVsbDtcblxuICAgICAgICAgICAgICAgIGlmIChub3RDbGFzc0lkLnRlc3QodGFnUGFydHNbMV0pKSB7XG4gICAgICAgICAgICAgICAgICAgIHRhZ05hbWUgPSBcIkRJVlwiO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHZhciBjbGFzc2VzLCBwYXJ0LCB0eXBlLCBpO1xuXG4gICAgICAgICAgICAgICAgZm9yIChpID0gMDsgaSA8IHRhZ1BhcnRzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICAgICAgICAgIHBhcnQgPSB0YWdQYXJ0c1tpXTtcblxuICAgICAgICAgICAgICAgICAgICBpZiAoIXBhcnQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnRpbnVlO1xuICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgdHlwZSA9IHBhcnQuY2hhckF0KDApO1xuXG4gICAgICAgICAgICAgICAgICAgIGlmICghdGFnTmFtZSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgdGFnTmFtZSA9IHBhcnQ7XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAodHlwZSA9PT0gXCIuXCIpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGNsYXNzZXMgPSBjbGFzc2VzIHx8IFtdO1xuICAgICAgICAgICAgICAgICAgICAgICAgY2xhc3Nlcy5wdXNoKHBhcnQuc3Vic3RyaW5nKDEsIHBhcnQubGVuZ3RoKSk7XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAodHlwZSA9PT0gXCIjXCIgJiYgbm9JZCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgcHJvcHMuaWQgPSBwYXJ0LnN1YnN0cmluZygxLCBwYXJ0Lmxlbmd0aCk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICBpZiAoY2xhc3Nlcykge1xuICAgICAgICAgICAgICAgICAgICBpZiAocHJvcHMuY2xhc3NOYW1lKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBjbGFzc2VzLnB1c2gocHJvcHMuY2xhc3NOYW1lKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgIHByb3BzLmNsYXNzTmFtZSA9IGNsYXNzZXMuam9pbihcIiBcIik7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgcmV0dXJuIHByb3BzLm5hbWVzcGFjZSA/IHRhZ05hbWUgOiB0YWdOYW1lLnRvVXBwZXJDYXNlKCk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0sIHsgXCJicm93c2VyLXNwbGl0XCI6IDUgfV0sIDI0OiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge1xuICAgICAgICAgICAgdmFyIGlzVk5vZGUgPSByZXF1aXJlKFwiLi9pcy12bm9kZVwiKTtcbiAgICAgICAgICAgIHZhciBpc1ZUZXh0ID0gcmVxdWlyZShcIi4vaXMtdnRleHRcIik7XG4gICAgICAgICAgICB2YXIgaXNXaWRnZXQgPSByZXF1aXJlKFwiLi9pcy13aWRnZXRcIik7XG4gICAgICAgICAgICB2YXIgaXNUaHVuayA9IHJlcXVpcmUoXCIuL2lzLXRodW5rXCIpO1xuXG4gICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IGhhbmRsZVRodW5rO1xuXG4gICAgICAgICAgICBmdW5jdGlvbiBoYW5kbGVUaHVuayhhLCBiKSB7XG4gICAgICAgICAgICAgICAgdmFyIHJlbmRlcmVkQSA9IGE7XG4gICAgICAgICAgICAgICAgdmFyIHJlbmRlcmVkQiA9IGI7XG5cbiAgICAgICAgICAgICAgICBpZiAoaXNUaHVuayhiKSkge1xuICAgICAgICAgICAgICAgICAgICByZW5kZXJlZEIgPSByZW5kZXJUaHVuayhiLCBhKTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICBpZiAoaXNUaHVuayhhKSkge1xuICAgICAgICAgICAgICAgICAgICByZW5kZXJlZEEgPSByZW5kZXJUaHVuayhhLCBudWxsKTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgICAgICAgICBhOiByZW5kZXJlZEEsXG4gICAgICAgICAgICAgICAgICAgIGI6IHJlbmRlcmVkQlxuICAgICAgICAgICAgICAgIH07XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIHJlbmRlclRodW5rKHRodW5rLCBwcmV2aW91cykge1xuICAgICAgICAgICAgICAgIHZhciByZW5kZXJlZFRodW5rID0gdGh1bmsudm5vZGU7XG5cbiAgICAgICAgICAgICAgICBpZiAoIXJlbmRlcmVkVGh1bmspIHtcbiAgICAgICAgICAgICAgICAgICAgcmVuZGVyZWRUaHVuayA9IHRodW5rLnZub2RlID0gdGh1bmsucmVuZGVyKHByZXZpb3VzKTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICBpZiAoIShpc1ZOb2RlKHJlbmRlcmVkVGh1bmspIHx8IGlzVlRleHQocmVuZGVyZWRUaHVuaykgfHwgaXNXaWRnZXQocmVuZGVyZWRUaHVuaykpKSB7XG4gICAgICAgICAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcihcInRodW5rIGRpZCBub3QgcmV0dXJuIGEgdmFsaWQgbm9kZVwiKTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICByZXR1cm4gcmVuZGVyZWRUaHVuaztcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSwgeyBcIi4vaXMtdGh1bmtcIjogMjUsIFwiLi9pcy12bm9kZVwiOiAyNywgXCIuL2lzLXZ0ZXh0XCI6IDI4LCBcIi4vaXMtd2lkZ2V0XCI6IDI5IH1dLCAyNTogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHtcbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gaXNUaHVuaztcblxuICAgICAgICAgICAgZnVuY3Rpb24gaXNUaHVuayh0KSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHQgJiYgdC50eXBlID09PSBcIlRodW5rXCI7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0sIHt9XSwgMjY6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IGlzSG9vaztcblxuICAgICAgICAgICAgZnVuY3Rpb24gaXNIb29rKGhvb2spIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gaG9vayAmJiAodHlwZW9mIGhvb2suaG9vayA9PT0gXCJmdW5jdGlvblwiICYmICFob29rLmhhc093blByb3BlcnR5KFwiaG9va1wiKSB8fCB0eXBlb2YgaG9vay51bmhvb2sgPT09IFwiZnVuY3Rpb25cIiAmJiAhaG9vay5oYXNPd25Qcm9wZXJ0eShcInVuaG9va1wiKSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0sIHt9XSwgMjc6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICB2YXIgdmVyc2lvbiA9IHJlcXVpcmUoXCIuL3ZlcnNpb25cIik7XG5cbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gaXNWaXJ0dWFsTm9kZTtcblxuICAgICAgICAgICAgZnVuY3Rpb24gaXNWaXJ0dWFsTm9kZSh4KSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHggJiYgeC50eXBlID09PSBcIlZpcnR1YWxOb2RlXCIgJiYgeC52ZXJzaW9uID09PSB2ZXJzaW9uO1xuICAgICAgICAgICAgfVxuICAgICAgICB9LCB7IFwiLi92ZXJzaW9uXCI6IDMwIH1dLCAyODogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHtcbiAgICAgICAgICAgIHZhciB2ZXJzaW9uID0gcmVxdWlyZShcIi4vdmVyc2lvblwiKTtcblxuICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBpc1ZpcnR1YWxUZXh0O1xuXG4gICAgICAgICAgICBmdW5jdGlvbiBpc1ZpcnR1YWxUZXh0KHgpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4geCAmJiB4LnR5cGUgPT09IFwiVmlydHVhbFRleHRcIiAmJiB4LnZlcnNpb24gPT09IHZlcnNpb247XG4gICAgICAgICAgICB9XG4gICAgICAgIH0sIHsgXCIuL3ZlcnNpb25cIjogMzAgfV0sIDI5OiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge1xuICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBpc1dpZGdldDtcblxuICAgICAgICAgICAgZnVuY3Rpb24gaXNXaWRnZXQodykge1xuICAgICAgICAgICAgICAgIHJldHVybiB3ICYmIHcudHlwZSA9PT0gXCJXaWRnZXRcIjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSwge31dLCAzMDogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHtcbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gXCIyXCI7XG4gICAgICAgIH0sIHt9XSwgMzE6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICB2YXIgdmVyc2lvbiA9IHJlcXVpcmUoXCIuL3ZlcnNpb25cIik7XG4gICAgICAgICAgICB2YXIgaXNWTm9kZSA9IHJlcXVpcmUoXCIuL2lzLXZub2RlXCIpO1xuICAgICAgICAgICAgdmFyIGlzV2lkZ2V0ID0gcmVxdWlyZShcIi4vaXMtd2lkZ2V0XCIpO1xuICAgICAgICAgICAgdmFyIGlzVGh1bmsgPSByZXF1aXJlKFwiLi9pcy10aHVua1wiKTtcbiAgICAgICAgICAgIHZhciBpc1ZIb29rID0gcmVxdWlyZShcIi4vaXMtdmhvb2tcIik7XG5cbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gVmlydHVhbE5vZGU7XG5cbiAgICAgICAgICAgIHZhciBub1Byb3BlcnRpZXMgPSB7fTtcbiAgICAgICAgICAgIHZhciBub0NoaWxkcmVuID0gW107XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIFZpcnR1YWxOb2RlKHRhZ05hbWUsIHByb3BlcnRpZXMsIGNoaWxkcmVuLCBrZXksIG5hbWVzcGFjZSkge1xuICAgICAgICAgICAgICAgIHRoaXMudGFnTmFtZSA9IHRhZ05hbWU7XG4gICAgICAgICAgICAgICAgdGhpcy5wcm9wZXJ0aWVzID0gcHJvcGVydGllcyB8fCBub1Byb3BlcnRpZXM7XG4gICAgICAgICAgICAgICAgdGhpcy5jaGlsZHJlbiA9IGNoaWxkcmVuIHx8IG5vQ2hpbGRyZW47XG4gICAgICAgICAgICAgICAgdGhpcy5rZXkgPSBrZXkgIT0gbnVsbCA/IFN0cmluZyhrZXkpIDogdW5kZWZpbmVkO1xuICAgICAgICAgICAgICAgIHRoaXMubmFtZXNwYWNlID0gdHlwZW9mIG5hbWVzcGFjZSA9PT0gXCJzdHJpbmdcIiA/IG5hbWVzcGFjZSA6IG51bGw7XG5cbiAgICAgICAgICAgICAgICB2YXIgY291bnQgPSBjaGlsZHJlbiAmJiBjaGlsZHJlbi5sZW5ndGggfHwgMDtcbiAgICAgICAgICAgICAgICB2YXIgZGVzY2VuZGFudHMgPSAwO1xuICAgICAgICAgICAgICAgIHZhciBoYXNXaWRnZXRzID0gZmFsc2U7XG4gICAgICAgICAgICAgICAgdmFyIGhhc1RodW5rcyA9IGZhbHNlO1xuICAgICAgICAgICAgICAgIHZhciBkZXNjZW5kYW50SG9va3MgPSBmYWxzZTtcbiAgICAgICAgICAgICAgICB2YXIgaG9va3M7XG5cbiAgICAgICAgICAgICAgICBmb3IgKHZhciBwcm9wTmFtZSBpbiBwcm9wZXJ0aWVzKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmIChwcm9wZXJ0aWVzLmhhc093blByb3BlcnR5KHByb3BOYW1lKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgdmFyIHByb3BlcnR5ID0gcHJvcGVydGllc1twcm9wTmFtZV07XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoaXNWSG9vayhwcm9wZXJ0eSkgJiYgcHJvcGVydHkudW5ob29rKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKCFob29rcykge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBob29rcyA9IHt9O1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGhvb2tzW3Byb3BOYW1lXSA9IHByb3BlcnR5O1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCBjb3VudDsgaSsrKSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciBjaGlsZCA9IGNoaWxkcmVuW2ldO1xuICAgICAgICAgICAgICAgICAgICBpZiAoaXNWTm9kZShjaGlsZCkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGRlc2NlbmRhbnRzICs9IGNoaWxkLmNvdW50IHx8IDA7XG5cbiAgICAgICAgICAgICAgICAgICAgICAgIGlmICghaGFzV2lkZ2V0cyAmJiBjaGlsZC5oYXNXaWRnZXRzKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaGFzV2lkZ2V0cyA9IHRydWU7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgICAgIGlmICghaGFzVGh1bmtzICYmIGNoaWxkLmhhc1RodW5rcykge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGhhc1RodW5rcyA9IHRydWU7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgICAgIGlmICghZGVzY2VuZGFudEhvb2tzICYmIChjaGlsZC5ob29rcyB8fCBjaGlsZC5kZXNjZW5kYW50SG9va3MpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgZGVzY2VuZGFudEhvb2tzID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIGlmICghaGFzV2lkZ2V0cyAmJiBpc1dpZGdldChjaGlsZCkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmICh0eXBlb2YgY2hpbGQuZGVzdHJveSA9PT0gXCJmdW5jdGlvblwiKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaGFzV2lkZ2V0cyA9IHRydWU7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoIWhhc1RodW5rcyAmJiBpc1RodW5rKGNoaWxkKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgaGFzVGh1bmtzID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHRoaXMuY291bnQgPSBjb3VudCArIGRlc2NlbmRhbnRzO1xuICAgICAgICAgICAgICAgIHRoaXMuaGFzV2lkZ2V0cyA9IGhhc1dpZGdldHM7XG4gICAgICAgICAgICAgICAgdGhpcy5oYXNUaHVua3MgPSBoYXNUaHVua3M7XG4gICAgICAgICAgICAgICAgdGhpcy5ob29rcyA9IGhvb2tzO1xuICAgICAgICAgICAgICAgIHRoaXMuZGVzY2VuZGFudEhvb2tzID0gZGVzY2VuZGFudEhvb2tzO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBWaXJ0dWFsTm9kZS5wcm90b3R5cGUudmVyc2lvbiA9IHZlcnNpb247XG4gICAgICAgICAgICBWaXJ0dWFsTm9kZS5wcm90b3R5cGUudHlwZSA9IFwiVmlydHVhbE5vZGVcIjtcbiAgICAgICAgfSwgeyBcIi4vaXMtdGh1bmtcIjogMjUsIFwiLi9pcy12aG9va1wiOiAyNiwgXCIuL2lzLXZub2RlXCI6IDI3LCBcIi4vaXMtd2lkZ2V0XCI6IDI5LCBcIi4vdmVyc2lvblwiOiAzMCB9XSwgMzI6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICB2YXIgdmVyc2lvbiA9IHJlcXVpcmUoXCIuL3ZlcnNpb25cIik7XG5cbiAgICAgICAgICAgIFZpcnR1YWxQYXRjaC5OT05FID0gMDtcbiAgICAgICAgICAgIFZpcnR1YWxQYXRjaC5WVEVYVCA9IDE7XG4gICAgICAgICAgICBWaXJ0dWFsUGF0Y2guVk5PREUgPSAyO1xuICAgICAgICAgICAgVmlydHVhbFBhdGNoLldJREdFVCA9IDM7XG4gICAgICAgICAgICBWaXJ0dWFsUGF0Y2guUFJPUFMgPSA0O1xuICAgICAgICAgICAgVmlydHVhbFBhdGNoLk9SREVSID0gNTtcbiAgICAgICAgICAgIFZpcnR1YWxQYXRjaC5JTlNFUlQgPSA2O1xuICAgICAgICAgICAgVmlydHVhbFBhdGNoLlJFTU9WRSA9IDc7XG4gICAgICAgICAgICBWaXJ0dWFsUGF0Y2guVEhVTksgPSA4O1xuXG4gICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IFZpcnR1YWxQYXRjaDtcblxuICAgICAgICAgICAgZnVuY3Rpb24gVmlydHVhbFBhdGNoKHR5cGUsIHZOb2RlLCBwYXRjaCkge1xuICAgICAgICAgICAgICAgIHRoaXMudHlwZSA9IE51bWJlcih0eXBlKTtcbiAgICAgICAgICAgICAgICB0aGlzLnZOb2RlID0gdk5vZGU7XG4gICAgICAgICAgICAgICAgdGhpcy5wYXRjaCA9IHBhdGNoO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBWaXJ0dWFsUGF0Y2gucHJvdG90eXBlLnZlcnNpb24gPSB2ZXJzaW9uO1xuICAgICAgICAgICAgVmlydHVhbFBhdGNoLnByb3RvdHlwZS50eXBlID0gXCJWaXJ0dWFsUGF0Y2hcIjtcbiAgICAgICAgfSwgeyBcIi4vdmVyc2lvblwiOiAzMCB9XSwgMzM6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICB2YXIgdmVyc2lvbiA9IHJlcXVpcmUoXCIuL3ZlcnNpb25cIik7XG5cbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gVmlydHVhbFRleHQ7XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIFZpcnR1YWxUZXh0KHRleHQpIHtcbiAgICAgICAgICAgICAgICB0aGlzLnRleHQgPSBTdHJpbmcodGV4dCk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIFZpcnR1YWxUZXh0LnByb3RvdHlwZS52ZXJzaW9uID0gdmVyc2lvbjtcbiAgICAgICAgICAgIFZpcnR1YWxUZXh0LnByb3RvdHlwZS50eXBlID0gXCJWaXJ0dWFsVGV4dFwiO1xuICAgICAgICB9LCB7IFwiLi92ZXJzaW9uXCI6IDMwIH1dLCAzNDogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHtcbiAgICAgICAgICAgIHZhciBpc09iamVjdCA9IHJlcXVpcmUoXCJpcy1vYmplY3RcIik7XG4gICAgICAgICAgICB2YXIgaXNIb29rID0gcmVxdWlyZShcIi4uL3Zub2RlL2lzLXZob29rXCIpO1xuXG4gICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IGRpZmZQcm9wcztcblxuICAgICAgICAgICAgZnVuY3Rpb24gZGlmZlByb3BzKGEsIGIpIHtcbiAgICAgICAgICAgICAgICB2YXIgZGlmZjtcblxuICAgICAgICAgICAgICAgIGZvciAodmFyIGFLZXkgaW4gYSkge1xuICAgICAgICAgICAgICAgICAgICBpZiAoIShhS2V5IGluIGIpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBkaWZmID0gZGlmZiB8fCB7fTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGRpZmZbYUtleV0gPSB1bmRlZmluZWQ7XG4gICAgICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgICAgICB2YXIgYVZhbHVlID0gYVthS2V5XTtcbiAgICAgICAgICAgICAgICAgICAgdmFyIGJWYWx1ZSA9IGJbYUtleV07XG5cbiAgICAgICAgICAgICAgICAgICAgaWYgKGFWYWx1ZSA9PT0gYlZhbHVlKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBjb250aW51ZTtcbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIGlmIChpc09iamVjdChhVmFsdWUpICYmIGlzT2JqZWN0KGJWYWx1ZSkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChnZXRQcm90b3R5cGUoYlZhbHVlKSAhPT0gZ2V0UHJvdG90eXBlKGFWYWx1ZSkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBkaWZmID0gZGlmZiB8fCB7fTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBkaWZmW2FLZXldID0gYlZhbHVlO1xuICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIGlmIChpc0hvb2soYlZhbHVlKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRpZmYgPSBkaWZmIHx8IHt9O1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRpZmZbYUtleV0gPSBiVmFsdWU7XG4gICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZhciBvYmplY3REaWZmID0gZGlmZlByb3BzKGFWYWx1ZSwgYlZhbHVlKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAob2JqZWN0RGlmZikge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBkaWZmID0gZGlmZiB8fCB7fTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZGlmZlthS2V5XSA9IG9iamVjdERpZmY7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgZGlmZiA9IGRpZmYgfHwge307XG4gICAgICAgICAgICAgICAgICAgICAgICBkaWZmW2FLZXldID0gYlZhbHVlO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgZm9yICh2YXIgYktleSBpbiBiKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmICghKGJLZXkgaW4gYSkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGRpZmYgPSBkaWZmIHx8IHt9O1xuICAgICAgICAgICAgICAgICAgICAgICAgZGlmZltiS2V5XSA9IGJbYktleV07XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICByZXR1cm4gZGlmZjtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZnVuY3Rpb24gZ2V0UHJvdG90eXBlKHZhbHVlKSB7XG4gICAgICAgICAgICAgICAgaWYgKE9iamVjdC5nZXRQcm90b3R5cGVPZikge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gT2JqZWN0LmdldFByb3RvdHlwZU9mKHZhbHVlKTtcbiAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKHZhbHVlLl9fcHJvdG9fXykge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gdmFsdWUuX19wcm90b19fO1xuICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAodmFsdWUuY29uc3RydWN0b3IpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHZhbHVlLmNvbnN0cnVjdG9yLnByb3RvdHlwZTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH0sIHsgXCIuLi92bm9kZS9pcy12aG9va1wiOiAyNiwgXCJpcy1vYmplY3RcIjogMTEgfV0sIDM1OiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge1xuICAgICAgICAgICAgdmFyIGlzQXJyYXkgPSByZXF1aXJlKFwieC1pcy1hcnJheVwiKTtcblxuICAgICAgICAgICAgdmFyIFZQYXRjaCA9IHJlcXVpcmUoXCIuLi92bm9kZS92cGF0Y2hcIik7XG4gICAgICAgICAgICB2YXIgaXNWTm9kZSA9IHJlcXVpcmUoXCIuLi92bm9kZS9pcy12bm9kZVwiKTtcbiAgICAgICAgICAgIHZhciBpc1ZUZXh0ID0gcmVxdWlyZShcIi4uL3Zub2RlL2lzLXZ0ZXh0XCIpO1xuICAgICAgICAgICAgdmFyIGlzV2lkZ2V0ID0gcmVxdWlyZShcIi4uL3Zub2RlL2lzLXdpZGdldFwiKTtcbiAgICAgICAgICAgIHZhciBpc1RodW5rID0gcmVxdWlyZShcIi4uL3Zub2RlL2lzLXRodW5rXCIpO1xuICAgICAgICAgICAgdmFyIGhhbmRsZVRodW5rID0gcmVxdWlyZShcIi4uL3Zub2RlL2hhbmRsZS10aHVua1wiKTtcblxuICAgICAgICAgICAgdmFyIGRpZmZQcm9wcyA9IHJlcXVpcmUoXCIuL2RpZmYtcHJvcHNcIik7XG5cbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gZGlmZjtcblxuICAgICAgICAgICAgZnVuY3Rpb24gZGlmZihhLCBiKSB7XG4gICAgICAgICAgICAgICAgdmFyIHBhdGNoID0geyBhOiBhIH07XG4gICAgICAgICAgICAgICAgd2FsayhhLCBiLCBwYXRjaCwgMCk7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHBhdGNoO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBmdW5jdGlvbiB3YWxrKGEsIGIsIHBhdGNoLCBpbmRleCkge1xuICAgICAgICAgICAgICAgIGlmIChhID09PSBiKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICB2YXIgYXBwbHkgPSBwYXRjaFtpbmRleF07XG4gICAgICAgICAgICAgICAgdmFyIGFwcGx5Q2xlYXIgPSBmYWxzZTtcblxuICAgICAgICAgICAgICAgIGlmIChpc1RodW5rKGEpIHx8IGlzVGh1bmsoYikpIHtcbiAgICAgICAgICAgICAgICAgICAgdGh1bmtzKGEsIGIsIHBhdGNoLCBpbmRleCk7XG4gICAgICAgICAgICAgICAgfSBlbHNlIGlmIChiID09IG51bGwpIHtcblxuICAgICAgICAgICAgICAgICAgICAvLyBJZiBhIGlzIGEgd2lkZ2V0IHdlIHdpbGwgYWRkIGEgcmVtb3ZlIHBhdGNoIGZvciBpdFxuICAgICAgICAgICAgICAgICAgICAvLyBPdGhlcndpc2UgYW55IGNoaWxkIHdpZGdldHMvaG9va3MgbXVzdCBiZSBkZXN0cm95ZWQuXG4gICAgICAgICAgICAgICAgICAgIC8vIFRoaXMgcHJldmVudHMgYWRkaW5nIHR3byByZW1vdmUgcGF0Y2hlcyBmb3IgYSB3aWRnZXQuXG4gICAgICAgICAgICAgICAgICAgIGlmICghaXNXaWRnZXQoYSkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGNsZWFyU3RhdGUoYSwgcGF0Y2gsIGluZGV4KTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGFwcGx5ID0gcGF0Y2hbaW5kZXhdO1xuICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgYXBwbHkgPSBhcHBlbmRQYXRjaChhcHBseSwgbmV3IFZQYXRjaChWUGF0Y2guUkVNT1ZFLCBhLCBiKSk7XG4gICAgICAgICAgICAgICAgfSBlbHNlIGlmIChpc1ZOb2RlKGIpKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmIChpc1ZOb2RlKGEpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoYS50YWdOYW1lID09PSBiLnRhZ05hbWUgJiYgYS5uYW1lc3BhY2UgPT09IGIubmFtZXNwYWNlICYmIGEua2V5ID09PSBiLmtleSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZhciBwcm9wc1BhdGNoID0gZGlmZlByb3BzKGEucHJvcGVydGllcywgYi5wcm9wZXJ0aWVzKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAocHJvcHNQYXRjaCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBhcHBseSA9IGFwcGVuZFBhdGNoKGFwcGx5LCBuZXcgVlBhdGNoKFZQYXRjaC5QUk9QUywgYSwgcHJvcHNQYXRjaCkpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBhcHBseSA9IGRpZmZDaGlsZHJlbihhLCBiLCBwYXRjaCwgYXBwbHksIGluZGV4KTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgYXBwbHkgPSBhcHBlbmRQYXRjaChhcHBseSwgbmV3IFZQYXRjaChWUGF0Y2guVk5PREUsIGEsIGIpKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBhcHBseUNsZWFyID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGFwcGx5ID0gYXBwZW5kUGF0Y2goYXBwbHksIG5ldyBWUGF0Y2goVlBhdGNoLlZOT0RFLCBhLCBiKSk7XG4gICAgICAgICAgICAgICAgICAgICAgICBhcHBseUNsZWFyID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoaXNWVGV4dChiKSkge1xuICAgICAgICAgICAgICAgICAgICBpZiAoIWlzVlRleHQoYSkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGFwcGx5ID0gYXBwZW5kUGF0Y2goYXBwbHksIG5ldyBWUGF0Y2goVlBhdGNoLlZURVhULCBhLCBiKSk7XG4gICAgICAgICAgICAgICAgICAgICAgICBhcHBseUNsZWFyID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIGlmIChhLnRleHQgIT09IGIudGV4dCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgYXBwbHkgPSBhcHBlbmRQYXRjaChhcHBseSwgbmV3IFZQYXRjaChWUGF0Y2guVlRFWFQsIGEsIGIpKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoaXNXaWRnZXQoYikpIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKCFpc1dpZGdldChhKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgYXBwbHlDbGVhciA9IHRydWU7XG4gICAgICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgICAgICBhcHBseSA9IGFwcGVuZFBhdGNoKGFwcGx5LCBuZXcgVlBhdGNoKFZQYXRjaC5XSURHRVQsIGEsIGIpKTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICBpZiAoYXBwbHkpIHtcbiAgICAgICAgICAgICAgICAgICAgcGF0Y2hbaW5kZXhdID0gYXBwbHk7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgaWYgKGFwcGx5Q2xlYXIpIHtcbiAgICAgICAgICAgICAgICAgICAgY2xlYXJTdGF0ZShhLCBwYXRjaCwgaW5kZXgpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZnVuY3Rpb24gZGlmZkNoaWxkcmVuKGEsIGIsIHBhdGNoLCBhcHBseSwgaW5kZXgpIHtcbiAgICAgICAgICAgICAgICB2YXIgYUNoaWxkcmVuID0gYS5jaGlsZHJlbjtcbiAgICAgICAgICAgICAgICB2YXIgb3JkZXJlZFNldCA9IHJlb3JkZXIoYUNoaWxkcmVuLCBiLmNoaWxkcmVuKTtcbiAgICAgICAgICAgICAgICB2YXIgYkNoaWxkcmVuID0gb3JkZXJlZFNldC5jaGlsZHJlbjtcblxuICAgICAgICAgICAgICAgIHZhciBhTGVuID0gYUNoaWxkcmVuLmxlbmd0aDtcbiAgICAgICAgICAgICAgICB2YXIgYkxlbiA9IGJDaGlsZHJlbi5sZW5ndGg7XG4gICAgICAgICAgICAgICAgdmFyIGxlbiA9IGFMZW4gPiBiTGVuID8gYUxlbiA6IGJMZW47XG5cbiAgICAgICAgICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IGxlbjsgaSsrKSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciBsZWZ0Tm9kZSA9IGFDaGlsZHJlbltpXTtcbiAgICAgICAgICAgICAgICAgICAgdmFyIHJpZ2h0Tm9kZSA9IGJDaGlsZHJlbltpXTtcbiAgICAgICAgICAgICAgICAgICAgaW5kZXggKz0gMTtcblxuICAgICAgICAgICAgICAgICAgICBpZiAoIWxlZnROb2RlKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAocmlnaHROb2RlKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gRXhjZXNzIG5vZGVzIGluIGIgbmVlZCB0byBiZSBhZGRlZFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGFwcGx5ID0gYXBwZW5kUGF0Y2goYXBwbHksIG5ldyBWUGF0Y2goVlBhdGNoLklOU0VSVCwgbnVsbCwgcmlnaHROb2RlKSk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICB3YWxrKGxlZnROb2RlLCByaWdodE5vZGUsIHBhdGNoLCBpbmRleCk7XG4gICAgICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgICAgICBpZiAoaXNWTm9kZShsZWZ0Tm9kZSkgJiYgbGVmdE5vZGUuY291bnQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGluZGV4ICs9IGxlZnROb2RlLmNvdW50O1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgaWYgKG9yZGVyZWRTZXQubW92ZXMpIHtcbiAgICAgICAgICAgICAgICAgICAgLy8gUmVvcmRlciBub2RlcyBsYXN0XG4gICAgICAgICAgICAgICAgICAgIGFwcGx5ID0gYXBwZW5kUGF0Y2goYXBwbHksIG5ldyBWUGF0Y2goVlBhdGNoLk9SREVSLCBhLCBvcmRlcmVkU2V0Lm1vdmVzKSk7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgcmV0dXJuIGFwcGx5O1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBmdW5jdGlvbiBjbGVhclN0YXRlKHZOb2RlLCBwYXRjaCwgaW5kZXgpIHtcbiAgICAgICAgICAgICAgICAvLyBUT0RPOiBNYWtlIHRoaXMgYSBzaW5nbGUgd2Fsaywgbm90IHR3b1xuICAgICAgICAgICAgICAgIHVuaG9vayh2Tm9kZSwgcGF0Y2gsIGluZGV4KTtcbiAgICAgICAgICAgICAgICBkZXN0cm95V2lkZ2V0cyh2Tm9kZSwgcGF0Y2gsIGluZGV4KTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgLy8gUGF0Y2ggcmVjb3JkcyBmb3IgYWxsIGRlc3Ryb3llZCB3aWRnZXRzIG11c3QgYmUgYWRkZWQgYmVjYXVzZSB3ZSBuZWVkXG4gICAgICAgICAgICAvLyBhIERPTSBub2RlIHJlZmVyZW5jZSBmb3IgdGhlIGRlc3Ryb3kgZnVuY3Rpb25cbiAgICAgICAgICAgIGZ1bmN0aW9uIGRlc3Ryb3lXaWRnZXRzKHZOb2RlLCBwYXRjaCwgaW5kZXgpIHtcbiAgICAgICAgICAgICAgICBpZiAoaXNXaWRnZXQodk5vZGUpKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmICh0eXBlb2Ygdk5vZGUuZGVzdHJveSA9PT0gXCJmdW5jdGlvblwiKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBwYXRjaFtpbmRleF0gPSBhcHBlbmRQYXRjaChwYXRjaFtpbmRleF0sIG5ldyBWUGF0Y2goVlBhdGNoLlJFTU9WRSwgdk5vZGUsIG51bGwpKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoaXNWTm9kZSh2Tm9kZSkgJiYgKHZOb2RlLmhhc1dpZGdldHMgfHwgdk5vZGUuaGFzVGh1bmtzKSkge1xuICAgICAgICAgICAgICAgICAgICB2YXIgY2hpbGRyZW4gPSB2Tm9kZS5jaGlsZHJlbjtcbiAgICAgICAgICAgICAgICAgICAgdmFyIGxlbiA9IGNoaWxkcmVuLmxlbmd0aDtcbiAgICAgICAgICAgICAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCBsZW47IGkrKykge1xuICAgICAgICAgICAgICAgICAgICAgICAgdmFyIGNoaWxkID0gY2hpbGRyZW5baV07XG4gICAgICAgICAgICAgICAgICAgICAgICBpbmRleCArPSAxO1xuXG4gICAgICAgICAgICAgICAgICAgICAgICBkZXN0cm95V2lkZ2V0cyhjaGlsZCwgcGF0Y2gsIGluZGV4KTtcblxuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGlzVk5vZGUoY2hpbGQpICYmIGNoaWxkLmNvdW50KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaW5kZXggKz0gY2hpbGQuY291bnQ7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKGlzVGh1bmsodk5vZGUpKSB7XG4gICAgICAgICAgICAgICAgICAgIHRodW5rcyh2Tm9kZSwgbnVsbCwgcGF0Y2gsIGluZGV4KTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIC8vIENyZWF0ZSBhIHN1Yi1wYXRjaCBmb3IgdGh1bmtzXG4gICAgICAgICAgICBmdW5jdGlvbiB0aHVua3MoYSwgYiwgcGF0Y2gsIGluZGV4KSB7XG4gICAgICAgICAgICAgICAgdmFyIG5vZGVzID0gaGFuZGxlVGh1bmsoYSwgYik7XG4gICAgICAgICAgICAgICAgdmFyIHRodW5rUGF0Y2ggPSBkaWZmKG5vZGVzLmEsIG5vZGVzLmIpO1xuICAgICAgICAgICAgICAgIGlmIChoYXNQYXRjaGVzKHRodW5rUGF0Y2gpKSB7XG4gICAgICAgICAgICAgICAgICAgIHBhdGNoW2luZGV4XSA9IG5ldyBWUGF0Y2goVlBhdGNoLlRIVU5LLCBudWxsLCB0aHVua1BhdGNoKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIGhhc1BhdGNoZXMocGF0Y2gpIHtcbiAgICAgICAgICAgICAgICBmb3IgKHZhciBpbmRleCBpbiBwYXRjaCkge1xuICAgICAgICAgICAgICAgICAgICBpZiAoaW5kZXggIT09IFwiYVwiKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgLy8gRXhlY3V0ZSBob29rcyB3aGVuIHR3byBub2RlcyBhcmUgaWRlbnRpY2FsXG4gICAgICAgICAgICBmdW5jdGlvbiB1bmhvb2sodk5vZGUsIHBhdGNoLCBpbmRleCkge1xuICAgICAgICAgICAgICAgIGlmIChpc1ZOb2RlKHZOb2RlKSkge1xuICAgICAgICAgICAgICAgICAgICBpZiAodk5vZGUuaG9va3MpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHBhdGNoW2luZGV4XSA9IGFwcGVuZFBhdGNoKHBhdGNoW2luZGV4XSwgbmV3IFZQYXRjaChWUGF0Y2guUFJPUFMsIHZOb2RlLCB1bmRlZmluZWRLZXlzKHZOb2RlLmhvb2tzKSkpO1xuICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgaWYgKHZOb2RlLmRlc2NlbmRhbnRIb29rcyB8fCB2Tm9kZS5oYXNUaHVua3MpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHZhciBjaGlsZHJlbiA9IHZOb2RlLmNoaWxkcmVuO1xuICAgICAgICAgICAgICAgICAgICAgICAgdmFyIGxlbiA9IGNoaWxkcmVuLmxlbmd0aDtcbiAgICAgICAgICAgICAgICAgICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgbGVuOyBpKyspIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB2YXIgY2hpbGQgPSBjaGlsZHJlbltpXTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpbmRleCArPSAxO1xuXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdW5ob29rKGNoaWxkLCBwYXRjaCwgaW5kZXgpO1xuXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGlzVk5vZGUoY2hpbGQpICYmIGNoaWxkLmNvdW50KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGluZGV4ICs9IGNoaWxkLmNvdW50O1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoaXNUaHVuayh2Tm9kZSkpIHtcbiAgICAgICAgICAgICAgICAgICAgdGh1bmtzKHZOb2RlLCBudWxsLCBwYXRjaCwgaW5kZXgpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZnVuY3Rpb24gdW5kZWZpbmVkS2V5cyhvYmopIHtcbiAgICAgICAgICAgICAgICB2YXIgcmVzdWx0ID0ge307XG5cbiAgICAgICAgICAgICAgICBmb3IgKHZhciBrZXkgaW4gb2JqKSB7XG4gICAgICAgICAgICAgICAgICAgIHJlc3VsdFtrZXldID0gdW5kZWZpbmVkO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHJldHVybiByZXN1bHQ7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIC8vIExpc3QgZGlmZiwgbmFpdmUgbGVmdCB0byByaWdodCByZW9yZGVyaW5nXG4gICAgICAgICAgICBmdW5jdGlvbiByZW9yZGVyKGFDaGlsZHJlbiwgYkNoaWxkcmVuKSB7XG4gICAgICAgICAgICAgICAgLy8gTyhNKSB0aW1lLCBPKE0pIG1lbW9yeVxuICAgICAgICAgICAgICAgIHZhciBiQ2hpbGRJbmRleCA9IGtleUluZGV4KGJDaGlsZHJlbik7XG4gICAgICAgICAgICAgICAgdmFyIGJLZXlzID0gYkNoaWxkSW5kZXgua2V5cztcbiAgICAgICAgICAgICAgICB2YXIgYkZyZWUgPSBiQ2hpbGRJbmRleC5mcmVlO1xuXG4gICAgICAgICAgICAgICAgaWYgKGJGcmVlLmxlbmd0aCA9PT0gYkNoaWxkcmVuLmxlbmd0aCkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgICAgICAgICAgICAgY2hpbGRyZW46IGJDaGlsZHJlbixcbiAgICAgICAgICAgICAgICAgICAgICAgIG1vdmVzOiBudWxsXG4gICAgICAgICAgICAgICAgICAgIH07XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgLy8gTyhOKSB0aW1lLCBPKE4pIG1lbW9yeVxuICAgICAgICAgICAgICAgIHZhciBhQ2hpbGRJbmRleCA9IGtleUluZGV4KGFDaGlsZHJlbik7XG4gICAgICAgICAgICAgICAgdmFyIGFLZXlzID0gYUNoaWxkSW5kZXgua2V5cztcbiAgICAgICAgICAgICAgICB2YXIgYUZyZWUgPSBhQ2hpbGRJbmRleC5mcmVlO1xuXG4gICAgICAgICAgICAgICAgaWYgKGFGcmVlLmxlbmd0aCA9PT0gYUNoaWxkcmVuLmxlbmd0aCkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgICAgICAgICAgICAgY2hpbGRyZW46IGJDaGlsZHJlbixcbiAgICAgICAgICAgICAgICAgICAgICAgIG1vdmVzOiBudWxsXG4gICAgICAgICAgICAgICAgICAgIH07XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgLy8gTyhNQVgoTiwgTSkpIG1lbW9yeVxuICAgICAgICAgICAgICAgIHZhciBuZXdDaGlsZHJlbiA9IFtdO1xuXG4gICAgICAgICAgICAgICAgdmFyIGZyZWVJbmRleCA9IDA7XG4gICAgICAgICAgICAgICAgdmFyIGZyZWVDb3VudCA9IGJGcmVlLmxlbmd0aDtcbiAgICAgICAgICAgICAgICB2YXIgZGVsZXRlZEl0ZW1zID0gMDtcblxuICAgICAgICAgICAgICAgIC8vIEl0ZXJhdGUgdGhyb3VnaCBhIGFuZCBtYXRjaCBhIG5vZGUgaW4gYlxuICAgICAgICAgICAgICAgIC8vIE8oTikgdGltZSxcbiAgICAgICAgICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IGFDaGlsZHJlbi5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgICAgICAgICB2YXIgYUl0ZW0gPSBhQ2hpbGRyZW5baV07XG4gICAgICAgICAgICAgICAgICAgIHZhciBpdGVtSW5kZXg7XG5cbiAgICAgICAgICAgICAgICAgICAgaWYgKGFJdGVtLmtleSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGJLZXlzLmhhc093blByb3BlcnR5KGFJdGVtLmtleSkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBNYXRjaCB1cCB0aGUgb2xkIGtleXNcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpdGVtSW5kZXggPSBiS2V5c1thSXRlbS5rZXldO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIG5ld0NoaWxkcmVuLnB1c2goYkNoaWxkcmVuW2l0ZW1JbmRleF0pO1xuICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBSZW1vdmUgb2xkIGtleWVkIGl0ZW1zXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaXRlbUluZGV4ID0gaSAtIGRlbGV0ZWRJdGVtcysrO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIG5ld0NoaWxkcmVuLnB1c2gobnVsbCk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAvLyBNYXRjaCB0aGUgaXRlbSBpbiBhIHdpdGggdGhlIG5leHQgZnJlZSBpdGVtIGluIGJcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChmcmVlSW5kZXggPCBmcmVlQ291bnQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpdGVtSW5kZXggPSBiRnJlZVtmcmVlSW5kZXgrK107XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgbmV3Q2hpbGRyZW4ucHVzaChiQ2hpbGRyZW5baXRlbUluZGV4XSk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIFRoZXJlIGFyZSBubyBmcmVlIGl0ZW1zIGluIGIgdG8gbWF0Y2ggd2l0aFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIHRoZSBmcmVlIGl0ZW1zIGluIGEsIHNvIHRoZSBleHRyYSBmcmVlIG5vZGVzXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gYXJlIGRlbGV0ZWQuXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaXRlbUluZGV4ID0gaSAtIGRlbGV0ZWRJdGVtcysrO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIG5ld0NoaWxkcmVuLnB1c2gobnVsbCk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICB2YXIgbGFzdEZyZWVJbmRleCA9IGZyZWVJbmRleCA+PSBiRnJlZS5sZW5ndGggPyBiQ2hpbGRyZW4ubGVuZ3RoIDogYkZyZWVbZnJlZUluZGV4XTtcblxuICAgICAgICAgICAgICAgIC8vIEl0ZXJhdGUgdGhyb3VnaCBiIGFuZCBhcHBlbmQgYW55IG5ldyBrZXlzXG4gICAgICAgICAgICAgICAgLy8gTyhNKSB0aW1lXG4gICAgICAgICAgICAgICAgZm9yICh2YXIgaiA9IDA7IGogPCBiQ2hpbGRyZW4ubGVuZ3RoOyBqKyspIHtcbiAgICAgICAgICAgICAgICAgICAgdmFyIG5ld0l0ZW0gPSBiQ2hpbGRyZW5bal07XG5cbiAgICAgICAgICAgICAgICAgICAgaWYgKG5ld0l0ZW0ua2V5KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoIWFLZXlzLmhhc093blByb3BlcnR5KG5ld0l0ZW0ua2V5KSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIEFkZCBhbnkgbmV3IGtleWVkIGl0ZW1zXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gV2UgYXJlIGFkZGluZyBuZXcgaXRlbXMgdG8gdGhlIGVuZCBhbmQgdGhlbiBzb3J0aW5nIHRoZW1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBpbiBwbGFjZS4gSW4gZnV0dXJlIHdlIHNob3VsZCBpbnNlcnQgbmV3IGl0ZW1zIGluIHBsYWNlLlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIG5ld0NoaWxkcmVuLnB1c2gobmV3SXRlbSk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoaiA+PSBsYXN0RnJlZUluZGV4KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAvLyBBZGQgYW55IGxlZnRvdmVyIG5vbi1rZXllZCBpdGVtc1xuICAgICAgICAgICAgICAgICAgICAgICAgbmV3Q2hpbGRyZW4ucHVzaChuZXdJdGVtKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHZhciBzaW11bGF0ZSA9IG5ld0NoaWxkcmVuLnNsaWNlKCk7XG4gICAgICAgICAgICAgICAgdmFyIHNpbXVsYXRlSW5kZXggPSAwO1xuICAgICAgICAgICAgICAgIHZhciByZW1vdmVzID0gW107XG4gICAgICAgICAgICAgICAgdmFyIGluc2VydHMgPSBbXTtcbiAgICAgICAgICAgICAgICB2YXIgc2ltdWxhdGVJdGVtO1xuXG4gICAgICAgICAgICAgICAgZm9yICh2YXIgayA9IDA7IGsgPCBiQ2hpbGRyZW4ubGVuZ3RoOykge1xuICAgICAgICAgICAgICAgICAgICB2YXIgd2FudGVkSXRlbSA9IGJDaGlsZHJlbltrXTtcbiAgICAgICAgICAgICAgICAgICAgc2ltdWxhdGVJdGVtID0gc2ltdWxhdGVbc2ltdWxhdGVJbmRleF07XG5cbiAgICAgICAgICAgICAgICAgICAgLy8gcmVtb3ZlIGl0ZW1zXG4gICAgICAgICAgICAgICAgICAgIHdoaWxlIChzaW11bGF0ZUl0ZW0gPT09IG51bGwgJiYgc2ltdWxhdGUubGVuZ3RoKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICByZW1vdmVzLnB1c2gocmVtb3ZlKHNpbXVsYXRlLCBzaW11bGF0ZUluZGV4LCBudWxsKSk7XG4gICAgICAgICAgICAgICAgICAgICAgICBzaW11bGF0ZUl0ZW0gPSBzaW11bGF0ZVtzaW11bGF0ZUluZGV4XTtcbiAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgIGlmICghc2ltdWxhdGVJdGVtIHx8IHNpbXVsYXRlSXRlbS5rZXkgIT09IHdhbnRlZEl0ZW0ua2V5KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAvLyBpZiB3ZSBuZWVkIGEga2V5IGluIHRoaXMgcG9zaXRpb24uLi5cbiAgICAgICAgICAgICAgICAgICAgICAgIGlmICh3YW50ZWRJdGVtLmtleSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChzaW11bGF0ZUl0ZW0gJiYgc2ltdWxhdGVJdGVtLmtleSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBpZiBhbiBpbnNlcnQgZG9lc24ndCBwdXQgdGhpcyBrZXkgaW4gcGxhY2UsIGl0IG5lZWRzIHRvIG1vdmVcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGJLZXlzW3NpbXVsYXRlSXRlbS5rZXldICE9PSBrICsgMSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmVtb3Zlcy5wdXNoKHJlbW92ZShzaW11bGF0ZSwgc2ltdWxhdGVJbmRleCwgc2ltdWxhdGVJdGVtLmtleSkpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc2ltdWxhdGVJdGVtID0gc2ltdWxhdGVbc2ltdWxhdGVJbmRleF07XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBpZiB0aGUgcmVtb3ZlIGRpZG4ndCBwdXQgdGhlIHdhbnRlZCBpdGVtIGluIHBsYWNlLCB3ZSBuZWVkIHRvIGluc2VydCBpdFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKCFzaW11bGF0ZUl0ZW0gfHwgc2ltdWxhdGVJdGVtLmtleSAhPT0gd2FudGVkSXRlbS5rZXkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpbnNlcnRzLnB1c2goeyBrZXk6IHdhbnRlZEl0ZW0ua2V5LCB0bzogayB9KTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIGl0ZW1zIGFyZSBtYXRjaGluZywgc28gc2tpcCBhaGVhZFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc2ltdWxhdGVJbmRleCsrO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaW5zZXJ0cy5wdXNoKHsga2V5OiB3YW50ZWRJdGVtLmtleSwgdG86IGsgfSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpbnNlcnRzLnB1c2goeyBrZXk6IHdhbnRlZEl0ZW0ua2V5LCB0bzogayB9KTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaysrO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgLy8gYSBrZXkgaW4gc2ltdWxhdGUgaGFzIG5vIG1hdGNoaW5nIHdhbnRlZCBrZXksIHJlbW92ZSBpdFxuICAgICAgICAgICAgICAgICAgICAgICAgZWxzZSBpZiAoc2ltdWxhdGVJdGVtICYmIHNpbXVsYXRlSXRlbS5rZXkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICByZW1vdmVzLnB1c2gocmVtb3ZlKHNpbXVsYXRlLCBzaW11bGF0ZUluZGV4LCBzaW11bGF0ZUl0ZW0ua2V5KSk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBzaW11bGF0ZUluZGV4Kys7XG4gICAgICAgICAgICAgICAgICAgICAgICBrKys7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAvLyByZW1vdmUgYWxsIHRoZSByZW1haW5pbmcgbm9kZXMgZnJvbSBzaW11bGF0ZVxuICAgICAgICAgICAgICAgIHdoaWxlIChzaW11bGF0ZUluZGV4IDwgc2ltdWxhdGUubGVuZ3RoKSB7XG4gICAgICAgICAgICAgICAgICAgIHNpbXVsYXRlSXRlbSA9IHNpbXVsYXRlW3NpbXVsYXRlSW5kZXhdO1xuICAgICAgICAgICAgICAgICAgICByZW1vdmVzLnB1c2gocmVtb3ZlKHNpbXVsYXRlLCBzaW11bGF0ZUluZGV4LCBzaW11bGF0ZUl0ZW0gJiYgc2ltdWxhdGVJdGVtLmtleSkpO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIC8vIElmIHRoZSBvbmx5IG1vdmVzIHdlIGhhdmUgYXJlIGRlbGV0ZXMgdGhlbiB3ZSBjYW4ganVzdFxuICAgICAgICAgICAgICAgIC8vIGxldCB0aGUgZGVsZXRlIHBhdGNoIHJlbW92ZSB0aGVzZSBpdGVtcy5cbiAgICAgICAgICAgICAgICBpZiAocmVtb3Zlcy5sZW5ndGggPT09IGRlbGV0ZWRJdGVtcyAmJiAhaW5zZXJ0cy5sZW5ndGgpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGNoaWxkcmVuOiBuZXdDaGlsZHJlbixcbiAgICAgICAgICAgICAgICAgICAgICAgIG1vdmVzOiBudWxsXG4gICAgICAgICAgICAgICAgICAgIH07XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgICAgICAgICAgY2hpbGRyZW46IG5ld0NoaWxkcmVuLFxuICAgICAgICAgICAgICAgICAgICBtb3Zlczoge1xuICAgICAgICAgICAgICAgICAgICAgICAgcmVtb3ZlczogcmVtb3ZlcyxcbiAgICAgICAgICAgICAgICAgICAgICAgIGluc2VydHM6IGluc2VydHNcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH07XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIHJlbW92ZShhcnIsIGluZGV4LCBrZXkpIHtcbiAgICAgICAgICAgICAgICBhcnIuc3BsaWNlKGluZGV4LCAxKTtcblxuICAgICAgICAgICAgICAgIHJldHVybiB7XG4gICAgICAgICAgICAgICAgICAgIGZyb206IGluZGV4LFxuICAgICAgICAgICAgICAgICAgICBrZXk6IGtleVxuICAgICAgICAgICAgICAgIH07XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIGtleUluZGV4KGNoaWxkcmVuKSB7XG4gICAgICAgICAgICAgICAgdmFyIGtleXMgPSB7fTtcbiAgICAgICAgICAgICAgICB2YXIgZnJlZSA9IFtdO1xuICAgICAgICAgICAgICAgIHZhciBsZW5ndGggPSBjaGlsZHJlbi5sZW5ndGg7XG5cbiAgICAgICAgICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IGxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciBjaGlsZCA9IGNoaWxkcmVuW2ldO1xuXG4gICAgICAgICAgICAgICAgICAgIGlmIChjaGlsZC5rZXkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGtleXNbY2hpbGQua2V5XSA9IGk7XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBmcmVlLnB1c2goaSk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgICAgICAgICBrZXlzOiBrZXlzLCAvLyBBIGhhc2ggb2Yga2V5IG5hbWUgdG8gaW5kZXhcbiAgICAgICAgICAgICAgICAgICAgZnJlZTogZnJlZSAvLyBBbiBhcnJheSBvZiB1bmtleWVkIGl0ZW0gaW5kaWNlc1xuICAgICAgICAgICAgICAgIH07XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIGFwcGVuZFBhdGNoKGFwcGx5LCBwYXRjaCkge1xuICAgICAgICAgICAgICAgIGlmIChhcHBseSkge1xuICAgICAgICAgICAgICAgICAgICBpZiAoaXNBcnJheShhcHBseSkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGFwcGx5LnB1c2gocGF0Y2gpO1xuICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgYXBwbHkgPSBbYXBwbHksIHBhdGNoXTtcbiAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBhcHBseTtcbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gcGF0Y2g7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9LCB7IFwiLi4vdm5vZGUvaGFuZGxlLXRodW5rXCI6IDI0LCBcIi4uL3Zub2RlL2lzLXRodW5rXCI6IDI1LCBcIi4uL3Zub2RlL2lzLXZub2RlXCI6IDI3LCBcIi4uL3Zub2RlL2lzLXZ0ZXh0XCI6IDI4LCBcIi4uL3Zub2RlL2lzLXdpZGdldFwiOiAyOSwgXCIuLi92bm9kZS92cGF0Y2hcIjogMzIsIFwiLi9kaWZmLXByb3BzXCI6IDM0LCBcIngtaXMtYXJyYXlcIjogMTIgfV0gfSwge30sIFs0XSkoNCk7XG59KTtcblxuY29uc3Qgc3RhcnQgPSBmdW5jdGlvbiAoZG9tUm9vdCwgcmVuZGVyRm4sIGluaXRpYWxTdGF0ZSwgb3B0aW9ucyA9IFtdKSB7XG4gIGxldCBwaWQgPSBzZWxmLnByb2Nlc3Nlcy5zcGF3bigpO1xuXG4gIGlmIChLZXl3b3JkLmhhc19rZXlfX3FtX18ob3B0aW9ucywgS2VybmVsLlNwZWNpYWxGb3Jtcy5hdG9tKCduYW1lJykpKSB7XG4gICAgcGlkID0gc2VsZi5wcm9jZXNzZXMucmVnaXN0ZXIoS2V5d29yZC5nZXQob3B0aW9ucywgS2VybmVsLlNwZWNpYWxGb3Jtcy5hdG9tKCduYW1lJykpLCBwaWQpO1xuICB9XG5cbiAgY29uc3QgdHJlZSA9IHJlbmRlckZuLmFwcGx5KHRoaXMsIGluaXRpYWxTdGF0ZSk7XG4gIGNvbnN0IHJvb3ROb2RlID0gVmlydHVhbERPTS5jcmVhdGUodHJlZSk7XG5cbiAgZG9tUm9vdC5hcHBlbmRDaGlsZChyb290Tm9kZSk7XG5cbiAgc2VsZi5wcm9jZXNzZXMucHV0KHBpZCwgJ3N0YXRlJywgS2VybmVsLlNwZWNpYWxGb3Jtcy50dXBsZShyb290Tm9kZSwgdHJlZSwgcmVuZGVyRm4pKTtcbiAgcmV0dXJuIEtlcm5lbC5TcGVjaWFsRm9ybXMudHVwbGUoS2VybmVsLlNwZWNpYWxGb3Jtcy5hdG9tKCdvaycpLCBwaWQpO1xufTtcblxuY29uc3Qgc3RvcCA9IGZ1bmN0aW9uIChhZ2VudCwgdGltZW91dCA9IDUwMDApIHtcbiAgc2VsZi5wcm9jZXNzZXMuZXhpdChhZ2VudCk7XG4gIHJldHVybiBLZXJuZWwuU3BlY2lhbEZvcm1zLmF0b20oJ29rJyk7XG59O1xuXG5jb25zdCByZW5kZXIgPSBmdW5jdGlvbiAoYWdlbnQsIHN0YXRlKSB7XG5cbiAgY29uc3QgY3VycmVudF9zdGF0ZSA9IHNlbGYucHJvY2Vzc2VzLmdldChhZ2VudCwgJ3N0YXRlJyk7XG5cbiAgbGV0IHJvb3ROb2RlID0gS2VybmVsLmVsZW0oY3VycmVudF9zdGF0ZSwgMCk7XG4gIGxldCB0cmVlID0gS2VybmVsLmVsZW0oY3VycmVudF9zdGF0ZSwgMSk7XG4gIGxldCByZW5kZXJGbiA9IEtlcm5lbC5lbGVtKGN1cnJlbnRfc3RhdGUsIDIpO1xuXG4gIGxldCBuZXdUcmVlID0gcmVuZGVyRm4uYXBwbHkodGhpcywgc3RhdGUpO1xuXG4gIGxldCBwYXRjaGVzID0gVmlydHVhbERPTS5kaWZmKHRyZWUsIG5ld1RyZWUpO1xuICByb290Tm9kZSA9IFZpcnR1YWxET00ucGF0Y2gocm9vdE5vZGUsIHBhdGNoZXMpO1xuXG4gIHNlbGYucHJvY2Vzc2VzLnB1dChhZ2VudCwgJ3N0YXRlJywgS2VybmVsLlNwZWNpYWxGb3Jtcy50dXBsZShyb290Tm9kZSwgbmV3VHJlZSwgcmVuZGVyRm4pKTtcblxuICByZXR1cm4gS2VybmVsLlNwZWNpYWxGb3Jtcy5hdG9tKCdvaycpO1xufTtcblxudmFyIHZpZXcgPSB7XG4gIHN0YXJ0LFxuICBzdG9wLFxuICByZW5kZXJcbn07XG5cbnNlbGYucHJvY2Vzc2VzID0gc2VsZi5wcm9jZXNzZXMgfHwgbmV3IFByb2Nlc3NTeXN0ZW0oKTtcblxuY29uc3QgQ29yZSA9IEM7XG5cbmV4cG9ydCB7IENvcmUsIEtlcm5lbCwgQXRvbSwgRW51bSwgSW50ZWdlciwgTGlzdCwgUmFuZ2UsIFR1cGxlLCBBZ2VudCwgS2V5d29yZCwgYmFzZSBhcyBCYXNlLCBTdHJpbmckMSBhcyBTdHJpbmcsIGJpdHdpc2UgYXMgQml0d2lzZSwgRW51bWVyYWJsZSwgQ29sbGVjdGFibGUsIEluc3BlY3QsIG1hcCBhcyBNYXAsIHNldCBhcyBTZXQsIE1hcFNldCwgVmlydHVhbERPTSwgdmlldyBhcyBWaWV3IH07Il0sImZpbGUiOiJFbGl4aXIuanMiLCJzb3VyY2VSb290IjoiL3NvdXJjZS8ifQ== \ No newline at end of file From 6ba216c2ff411398d13ff5d66b3d2df6e01bcf4b Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Sun, 6 Dec 2015 20:31:03 -0600 Subject: [PATCH 084/860] Fixed most tests. Inner module test still failing --- lib/elixir_script/preprocess/modules.ex | 26 +-- lib/elixir_script/state.ex | 15 +- test/elixir_script_test.exs | 31 ++-- test/translator/defmodule_test.exs | 204 ++++++++++-------------- test/translator/protocol_test.exs | 14 +- test/translator/struct_test.exs | 51 +++--- 6 files changed, 159 insertions(+), 182 deletions(-) diff --git a/lib/elixir_script/preprocess/modules.ex b/lib/elixir_script/preprocess/modules.ex index ed512957..fa2b8a73 100644 --- a/lib/elixir_script/preprocess/modules.ex +++ b/lib/elixir_script/preprocess/modules.ex @@ -113,9 +113,10 @@ defmodule ElixirScript.Preprocess.Modules do case x do {:defmodule, _, [{:__aliases__, _, module_name_list2}, [do: body2]]} -> body2 = make_inner_module_aliases(module_name_list2, body2) - add_module_to_state(module_name_list, module_name_list2, body2) + inner_alias = add_module_to_state(module_name_list, module_name_list2, body2) - [] + + [ inner_alias ] _ -> x end @@ -125,9 +126,9 @@ defmodule ElixirScript.Preprocess.Modules do {:__block__, meta2, list2} {:defmodule, _, [{:__aliases__, meta2, module_name_list2}, [do: body2]]} -> body2 = make_inner_module_aliases(module_name_list2, body2) - add_module_to_state(module_name_list, module_name_list2, body2) + inner_alias = add_module_to_state(module_name_list, module_name_list2, body2) - {:__block__, meta2, [] } + {:__block__, meta2, [ inner_alias ] } _ -> body end @@ -141,24 +142,27 @@ defmodule ElixirScript.Preprocess.Modules do imports = get_imports_from_module(body2) js_imports = get_js_imports_from_module(body2) + inner_alias = {:alias, [], [{:__aliases__, [alias: false], module_name_list ++ module_name_list2}]} {inner_alias_atom, _ } = Code.eval_quoted({:__aliases__, [alias: false], module_name_list ++ module_name_list2}) aliases = Set.put(aliases, {inner_alias_atom, inner_alias_atom}) aliases = Set.union(aliases, requires.aliases) |> Set.union(imports.aliases) - mod = %ElixirScript.Module{ name: ElixirScript.Module.quoted_to_name({:__aliases__, [], module_name_list2}), body: body2, - functions: functions, macros: macros, aliases: aliases, - requires: requires.requires, imports: imports.imports, js_imports: js_imports } + module_name = ElixirScript.Module.quoted_to_name({:__aliases__, [], module_name_list2}) - if State.module_listed?(module_name_list2) do - State.delete_module(mod) + if State.module_listed?(module_name) do + State.delete_module_by_name(module_name) end - mod = %ElixirScript.Module{ name: ElixirScript.Module.quoted_to_name({:__aliases__, [], module_name_list ++ module_name_list2}), body: body2, + module_name = ElixirScript.Module.quoted_to_name({:__aliases__, [], module_name_list ++ module_name_list2}) + + mod = %ElixirScript.Module{ name: module_name, body: body2, functions: functions, macros: macros, aliases: aliases, - requires: requires.requires } + requires: requires.requires, js_imports: js_imports } State.add_module(mod) + + inner_alias end diff --git a/lib/elixir_script/state.ex b/lib/elixir_script/state.ex index 31bf1a76..0f97a6ac 100644 --- a/lib/elixir_script/state.ex +++ b/lib/elixir_script/state.ex @@ -25,6 +25,17 @@ defmodule ElixirScript.State do end) end + def delete_module_by_name(module_name) do + Agent.update(__MODULE__, fn state -> + set = state.modules + |> Set.to_list() + |> Enum.filter(fn(x) -> x.name != module_name end) + |> Enum.into(HashSet.new) + + %{state | modules: set } + end) + end + def module_listed?(module_name) do Agent.get(__MODULE__, fn state -> Enum.any?(state.modules, fn(x) -> x.name == module_name end) || @@ -166,9 +177,7 @@ defmodule ElixirScript.State do def list_modules() do Agent.get(__MODULE__, fn(x) -> - Enum.map(x.modules, fn(y) -> - y.name - end) + Enum.map(x.modules, fn(y) -> y.name end) ++ Enum.map(x.protocols, fn({key, _}) -> key end) end) end diff --git a/test/elixir_script_test.exs b/test/elixir_script_test.exs index 401f09be..41d28aac 100644 --- a/test/elixir_script_test.exs +++ b/test/elixir_script_test.exs @@ -34,7 +34,7 @@ defmodule ElixirScript.Test do """) assert_js_matches """ - import * as Elixir from 'elixir'; + import * as Elixir from 'Elixir'; const __MODULE__ = Elixir.Kernel.SpecialForms.atom('Elixir.Elephant'); const something_else = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([],function() { return Elixir.String.Chars.to_string(10); @@ -67,26 +67,25 @@ defmodule ElixirScript.Test do """, env: make_custom_env) assert_js_matches """ - import * as Elixir from 'elixir'; - import * as Elephant from 'animals/elephant'; - const __MODULE__ = Elixir.Kernel.SpecialForms.atom('Elixir.Animals.Elephant'); - const defstruct = Elixir.Kernel.defstruct({ - [Elixir.Kernel.SpecialForms.atom('__struct__')]: __MODULE__, [Elixir.Kernel.SpecialForms.atom('trunk')]: true - }); + import * as Elixir from 'Elixir'; + const __MODULE__ = Elixir.Kernel.SpecialForms.atom('Elixir.Animals'); + const something = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([],function() { + return Elixir$Animals$Elephant.Elixir$Animals$Elephant.create(Elixir.Kernel.SpecialForms.map({})); + })); export { - Elephant: defstruct - }; + something + }; """, hd(js_code) assert_js_matches """ - import * as Elixir from 'elixir'; - const __MODULE__ = Elixir.Kernel.SpecialForms.atom('Elixir.Elephant'); + import * as Elixir from 'Elixir'; + const __MODULE__ = Elixir.Kernel.SpecialForms.atom('Elixir.Animals.Elephant'); const defstruct = Elixir.Kernel.defstruct({ - [Elixir.Kernel.SpecialForms.atom('__struct__')]: __MODULE__, [Elixir.Kernel.SpecialForms.atom('trunk')]: true - }); + [Elixir.Kernel.SpecialForms.atom('__struct__')]: __MODULE__, [Elixir.Kernel.SpecialForms.atom('trunk')]: true + }); export { - Elephant: defstruct - }; + Elixir$Animals$Elephant: defstruct + }; """, Enum.fetch!(js_code, 1) end @@ -105,7 +104,7 @@ defmodule ElixirScript.Test do """, env: make_custom_env) assert_js_matches """ - import * as Elixir from 'elixir'; + import * as Elixir from 'Elixir'; const __MODULE__ = Elixir.Kernel.SpecialForms.atom('Elixir.Animals'); const something_else = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([],function() { return 1 * 1; diff --git a/test/translator/defmodule_test.exs b/test/translator/defmodule_test.exs index 8ecc4b70..2102a464 100644 --- a/test/translator/defmodule_test.exs +++ b/test/translator/defmodule_test.exs @@ -59,17 +59,16 @@ defmodule ElixirScript.Translator.Defmodule.Test do end js_code = """ - import * as Crane from 'icabod/crane'; - const __MODULE__ = Elixir.Kernel.SpecialForms.atom('Elixir.Elephant'); - const something_else = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([],function() { - return null; - })); - const something = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([],function() { - return null; - })); - export { - something - }; + const __MODULE__ = Elixir.Kernel.SpecialForms.atom('Elixir.Elephant'); + const something_else = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([],function() { + return null; + })); + const something = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([],function() { + return null; + })); + export { + something + }; """ assert_translation(ex_ast, js_code) @@ -83,7 +82,6 @@ defmodule ElixirScript.Translator.Defmodule.Test do defstruct trunk: true end - def something() do %Elephant{} end @@ -95,34 +93,28 @@ defmodule ElixirScript.Translator.Defmodule.Test do end js_code = """ - const __MODULE__ = Elixir.Kernel.SpecialForms.atom('Elixir.Elephant'); - const defstruct = Elixir.Kernel.defstruct({ - [Elixir.Kernel.SpecialForms.atom('__struct__')]: __MODULE__, [Elixir.Kernel.SpecialForms.atom('trunk')]: true + const __MODULE__ = Elixir.Kernel.SpecialForms.atom('Elixir.Animals.Elephant'); + const defstruct = Elixir.Kernel.defstruct({ + [Elixir.Kernel.SpecialForms.atom('__struct__')]: __MODULE__, + [Elixir.Kernel.SpecialForms.atom('trunk')]: true }); - export { - Elephant: defstruct + export { + Elixir$Animals$Elephant: defstruct }; - import * as Elephant from 'animals/elephant'; - const __MODULE__ = Elixir.Kernel.SpecialForms.atom('Elixir.Animals'); - const something_else = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([], function() { - return null; - })); - const something = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([], function() { - return Elephant.Elephant.create(Elixir.Kernel.SpecialForms.map({})); - })); - export { - something - }; + const __MODULE__ = Elixir.Kernel.SpecialForms.atom('Elixir.Animals'); - import * as Elephant from 'animals/elephant'; - const __MODULE__ = Elixir.Kernel.SpecialForms.atom('Elixir.Animals.Elephant'); - const defstruct = Elixir.Kernel.defstruct({ - [Elixir.Kernel.SpecialForms.atom('__struct__')]: __MODULE__, [Elixir.Kernel.SpecialForms.atom('trunk')]: true - }); - export { - Elephant: defstruct - }; + const something_else = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([],function() { + return null; + })); + + const something = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([],function() { + return Elixir$Animals$Elephant.Elixir$Animals$Elephant.create(Elixir.Kernel.SpecialForms.map({})); + })); + + export { + something + }; """ assert_translation(ex_ast, js_code) @@ -153,53 +145,32 @@ defmodule ElixirScript.Translator.Defmodule.Test do end js_code = """ - import * as Bear from 'elephant/bear'; - const __MODULE__ = Elixir.Kernel.SpecialForms.atom('Elixir.Elephant.Bear'); - const defstruct = Elixir.Kernel.defstruct({ - [Elixir.Kernel.SpecialForms.atom('__struct__')]: __MODULE__, [Elixir.Kernel.SpecialForms.atom('trunk')]: true - }); - export { - Bear: defstruct - }; - - import * as Bear from 'elephant/bear'; - import * as Elephant from 'animals/elephant'; const __MODULE__ = Elixir.Kernel.SpecialForms.atom('Elixir.Animals.Elephant'); const defstruct = Elixir.Kernel.defstruct({ - [Elixir.Kernel.SpecialForms.atom('__struct__')]: __MODULE__, [Elixir.Kernel.SpecialForms.atom('trunk')]: true - }); + [Elixir.Kernel.SpecialForms.atom('__struct__')]: __MODULE__, [Elixir.Kernel.SpecialForms.atom('trunk')]: true + }); export { - Elephant: defstruct - }; + Elixir$Animals$Elephant: defstruct + }; - import * as Elephant from 'animals/elephant'; const __MODULE__ = Elixir.Kernel.SpecialForms.atom('Elixir.Animals'); - const something_else = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([], function() { - return null; - })); - const something = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([], function() { - return Elephant.Elephant.create(Elixir.Kernel.SpecialForms.map({})); - })); + const something_else = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([],function() { + return null; + })); + const something = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([],function() { + return Elixir$Animals$Elephant.Elixir$Animals$Elephant.create(Elixir.Kernel.SpecialForms.map({})); + })); export { something - }; - - const __MODULE__ = Elixir.Kernel.SpecialForms.atom('Elixir.Bear'); - const defstruct = Elixir.Kernel.defstruct({ - [Elixir.Kernel.SpecialForms.atom('__struct__')]: __MODULE__, [Elixir.Kernel.SpecialForms.atom('trunk')]: true - }); - export { - Bear: defstruct - }; + }; - import * as Bear from 'elephant/bear'; - const __MODULE__ = Elixir.Kernel.SpecialForms.atom('Elixir.Elephant'); + const __MODULE__ = Elixir.Kernel.SpecialForms.atom('Elixir.Animals.Elephant.Bear'); const defstruct = Elixir.Kernel.defstruct({ - [Elixir.Kernel.SpecialForms.atom('__struct__')]: __MODULE__, [Elixir.Kernel.SpecialForms.atom('trunk')]: true - }); + [Elixir.Kernel.SpecialForms.atom('__struct__')]: __MODULE__, [Elixir.Kernel.SpecialForms.atom('trunk')]: true + }); export { - Elephant: defstruct - }; + Elixir$Animals$Elephant$Bear: defstruct + }; """ assert_translation(ex_ast, js_code) @@ -217,14 +188,14 @@ defmodule ElixirScript.Translator.Defmodule.Test do end js_code = """ - import * as Tigers from 'lions/tigers'; - const __MODULE__ = Elixir.Kernel.SpecialForms.atom('Elixir.Animals'); - Elixir.Core.call_property(Tigers,'oh_my'); - export {}; - - const __MODULE__ = Elixir.Kernel.SpecialForms.atom('Elixir.Lions.Tigers'); - Elixir.Core.call_property(Lions.Tigers.Bears,'oh_my'); - export {}; + const __MODULE__ = Elixir.Kernel.SpecialForms.atom('Elixir.Lions.Tigers'); + Elixir.Core.call_property(Lions.Tigers.Bears,'oh_my'); + export {}; + + import * as Elixir$Lions$Tigers from 'Elixir.Lions.Tigers'; + const __MODULE__ = Elixir.Kernel.SpecialForms.atom('Elixir.Animals'); + Elixir.Core.call_property(Elixir$Lions$Tigers,'oh_my'); + export {}; """ assert_translation(ex_ast, js_code) @@ -247,19 +218,19 @@ defmodule ElixirScript.Translator.Defmodule.Test do end js_code = """ - const __MODULE__ = Elixir.Kernel.SpecialForms.atom('Elixir.Lions.Tigers'); - const oh_my = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([],function() { - return null; - })); - Elixir.Core.call_property(Lions.Tigers.Bears,'oh_my'); - export { - oh_my - }; + import * as Elixir$Lions$Tigers from 'Elixir.Lions.Tigers'; + const __MODULE__ = Elixir.Kernel.SpecialForms.atom('Elixir.Animals'); + Elixir.Core.call_property(Elixir$Lions$Tigers,'oh_my'); + export {}; - import * as Tigers from 'lions/tigers'; - const __MODULE__ = Elixir.Kernel.SpecialForms.atom('Elixir.Animals'); - Elixir.Core.call_property(Tigers,'oh_my'); - export {}; + const __MODULE__ = Elixir.Kernel.SpecialForms.atom('Elixir.Lions.Tigers'); + const oh_my = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([],function() { + return null; + })); + Elixir.Core.call_property(Lions.Tigers.Bears,'oh_my'); + export { + oh_my + }; """ assert_translation(ex_ast, js_code) @@ -283,24 +254,22 @@ defmodule ElixirScript.Translator.Defmodule.Test do end js_code = """ - import * as Tigers from 'lions/tigers'; - const __MODULE__ = Elixir.Kernel.SpecialForms.atom('Elixir.Animals'); - Tigers.oh_my(); - export {}; - - - const __MODULE__ = Elixir.Kernel.SpecialForms.atom('Elixir.Lions.Tigers'); - const oh_my2 = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([], function() { - return null; - })); - const oh_my = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([], function() { - return null; - })); + const oh_my2 = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([],function() { + return null; + })); + const oh_my = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([],function() { + return null; + })); export { - oh_my2, - oh_my + oh_my2, + oh_my }; + + import * as Elixir$Lions$Tigers from 'Elixir.Lions.Tigers'; + const __MODULE__ = Elixir.Kernel.SpecialForms.atom('Elixir.Animals'); + Elixir$Lions$Tigers.oh_my(); + export {}; """ assert_translation(ex_ast, js_code) @@ -324,26 +293,23 @@ defmodule ElixirScript.Translator.Defmodule.Test do end js_code = """ - import * as Tigers from 'lions/tigers'; + import * as Elixir$Lions$Tigers from 'Elixir.Lions.Tigers'; const __MODULE__ = Elixir.Kernel.SpecialForms.atom('Elixir.Animals'); - Tigers.oh_my2(); + Elixir$Lions$Tigers.oh_my2(); export {}; - - const __MODULE__ = Elixir.Kernel.SpecialForms.atom('Elixir.Lions.Tigers'); - - const oh_my2 = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([], function() { - return null; + const oh_my2 = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([],function() { + return null; })); - const oh_my = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([], function() { - return null; + const oh_my = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([],function() { + return null; })); export { - oh_my2, - oh_my + oh_my2, + oh_my }; """ diff --git a/test/translator/protocol_test.exs b/test/translator/protocol_test.exs index d6674b0d..8159b778 100644 --- a/test/translator/protocol_test.exs +++ b/test/translator/protocol_test.exs @@ -12,7 +12,7 @@ defmodule ElixirScript.Translator.Protocol.Test do js_code = """ const __MODULE__ = Elixir.Kernel.SpecialForms.atom('Elixir.ElixirScript.Collectable'); - let Collectable = Elixir.Kernel.defprotocol({ + let Elixir$ElixirScript$Collectable = Elixir.Kernel.defprotocol({ into: Elixir.Core.Patterns.defmatch( Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable()], function(collectable){ return null; @@ -20,7 +20,7 @@ defmodule ElixirScript.Translator.Protocol.Test do ) }); - export default Collectable; + export default Elixir$ElixirScript$Collectable; """ assert_translation(ex_ast, js_code) @@ -69,19 +69,19 @@ defmodule ElixirScript.Translator.Protocol.Test do js_code = """ const __MODULE__ = Elixir.Kernel.SpecialForms.atom('Elixir.Blank'); - let Blank = Elixir.Kernel.defprotocol({ + let Elixir$Blank = Elixir.Kernel.defprotocol({ blank__qmark__: Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable()],function(data) { return null; })) }); - Elixir.Kernel.defimpl(Blank, Array,{ + Elixir.Kernel.defimpl(Elixir$Blank, Array,{ blank__qmark__: Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Kernel.SpecialForms.list()],function() { return true; }),Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.wildcard()],function() { return false; })) }) - Elixir.Kernel.defimpl(Blank,Symbol,{ + Elixir.Kernel.defimpl(Elixir$Blank,Symbol,{ blank__qmark__: Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([false],function() { return true; }),Elixir.Core.Patterns.make_case([null],function() { @@ -90,12 +90,12 @@ defmodule ElixirScript.Translator.Protocol.Test do return false; })) }) - Elixir.Kernel.defimpl(Blank, Elixir.Core.Integer, { + Elixir.Kernel.defimpl(Elixir$Blank, Elixir.Core.Integer, { blank__qmark__: Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable()],function(number) { return false; })) }) - export default Blank; + export default Elixir$Blank; """ assert_translation(ex_ast, js_code) diff --git a/test/translator/struct_test.exs b/test/translator/struct_test.exs index 6660f9f1..2a2c4d4b 100644 --- a/test/translator/struct_test.exs +++ b/test/translator/struct_test.exs @@ -13,11 +13,13 @@ defmodule ElixirScript.Translator.Struct.Test do const __MODULE__ = Elixir.Kernel.SpecialForms.atom('Elixir.User'); const defstruct = Elixir.Kernel.defstruct({ - [Elixir.Kernel.SpecialForms.atom('__struct__')]: __MODULE__, [Elixir.Kernel.SpecialForms.atom('name')]: 'john', [Elixir.Kernel.SpecialForms.atom('age')]: 27 + [Elixir.Kernel.SpecialForms.atom('__struct__')]: __MODULE__, + [Elixir.Kernel.SpecialForms.atom('name')]: 'john', + [Elixir.Kernel.SpecialForms.atom('age')]: 27 }); export { - User: defstruct + Elixir$User: defstruct }; """ @@ -33,16 +35,15 @@ defmodule ElixirScript.Translator.Struct.Test do end js_code = """ - const __MODULE__ = Elixir.Kernel.SpecialForms.atom('Elixir.User'); - const defstruct = Elixir.Kernel.defstruct({ - [Elixir.Kernel.SpecialForms.atom('__struct__')]: __MODULE__, - [Elixir.Kernel.SpecialForms.atom('name')]: null, - [Elixir.Kernel.SpecialForms.atom('age')]: null - }); - - export { - User: defstruct - }; + const __MODULE__ = Elixir.Kernel.SpecialForms.atom('Elixir.User'); + const defstruct = Elixir.Kernel.defstruct({ + [Elixir.Kernel.SpecialForms.atom('__struct__')]: __MODULE__, + [Elixir.Kernel.SpecialForms.atom('name')]: null, + [Elixir.Kernel.SpecialForms.atom('age')]: null + }); + export { + Elixir$User: defstruct + }; """ assert_translation(ex_ast, js_code) @@ -66,10 +67,10 @@ defmodule ElixirScript.Translator.Struct.Test do [Elixir.Kernel.SpecialForms.atom('age')]: null }); export { - User: defstruct + Elixir$User: defstruct }; - let [user] = Elixir.Core.Patterns.match(Elixir.Core.Patterns.variable(), User.User.create(Elixir.Kernel.SpecialForms.map({}))); + let [user] = Elixir.Core.Patterns.match(Elixir.Core.Patterns.variable(), Elixir$User.Elixir$User.create(Elixir.Kernel.SpecialForms.map({}))); """ assert_translation(ex_ast, js_code) @@ -83,19 +84,17 @@ defmodule ElixirScript.Translator.Struct.Test do end js_code = """ + let [user] = Elixir.Core.Patterns.match(Elixir.Core.Patterns.variable(),Elixir$User.Elixir$User.create(Elixir.Kernel.SpecialForms.map({ + [Elixir.Kernel.SpecialForms.atom('name')]: 'John' + }))); + const __MODULE__ = Elixir.Kernel.SpecialForms.atom('Elixir.User'); const defstruct = Elixir.Kernel.defstruct({ - [Elixir.Kernel.SpecialForms.atom('__struct__')]: __MODULE__, - [Elixir.Kernel.SpecialForms.atom('name')]: null, - [Elixir.Kernel.SpecialForms.atom('age')]: null - }); + [Elixir.Kernel.SpecialForms.atom('__struct__')]: __MODULE__, [Elixir.Kernel.SpecialForms.atom('name')]: null, [Elixir.Kernel.SpecialForms.atom('age')]: null + }); export { - User: defstruct - }; - - let [user] = Elixir.Core.Patterns.match(Elixir.Core.Patterns.variable(), User.User.create(Elixir.Kernel.SpecialForms.map({ - [Elixir.Kernel.SpecialForms.atom('name')]: 'John' - }))); + Elixir$User: defstruct + }; """ assert_translation(ex_ast, js_code) @@ -143,7 +142,7 @@ defmodule ElixirScript.Translator.Struct.Test do [Elixir.Kernel.SpecialForms.atom('message')]: 'This is a message' }); export { - MyAppError: defexception + Elixir$MyAppError: defexception }; """ @@ -164,7 +163,7 @@ defmodule ElixirScript.Translator.Struct.Test do }); export { - MyAppError: defexception + Elixir$MyAppError: defexception }; """ From 853de24f357b8c354771aed177f933659d3d49b1 Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Sun, 6 Dec 2015 20:44:51 -0600 Subject: [PATCH 085/860] Fixed inner module capture adding an extra module --- lib/elixir_script/preprocess/modules.ex | 11 ++++------- test/translator/defmodule_test.exs | 16 ++++++++-------- 2 files changed, 12 insertions(+), 15 deletions(-) diff --git a/lib/elixir_script/preprocess/modules.ex b/lib/elixir_script/preprocess/modules.ex index fa2b8a73..7e4271fe 100644 --- a/lib/elixir_script/preprocess/modules.ex +++ b/lib/elixir_script/preprocess/modules.ex @@ -112,7 +112,7 @@ defmodule ElixirScript.Preprocess.Modules do list2 = Enum.map(list2, fn(x) -> case x do {:defmodule, _, [{:__aliases__, _, module_name_list2}, [do: body2]]} -> - body2 = make_inner_module_aliases(module_name_list2, body2) + body2 = make_inner_module_aliases( module_name_list ++ module_name_list2, body2) inner_alias = add_module_to_state(module_name_list, module_name_list2, body2) @@ -125,7 +125,7 @@ defmodule ElixirScript.Preprocess.Modules do {:__block__, meta2, list2} {:defmodule, _, [{:__aliases__, meta2, module_name_list2}, [do: body2]]} -> - body2 = make_inner_module_aliases(module_name_list2, body2) + body2 = make_inner_module_aliases(module_name_list ++ module_name_list2, body2) inner_alias = add_module_to_state(module_name_list, module_name_list2, body2) {:__block__, meta2, [ inner_alias ] } @@ -148,11 +148,8 @@ defmodule ElixirScript.Preprocess.Modules do aliases = Set.put(aliases, {inner_alias_atom, inner_alias_atom}) aliases = Set.union(aliases, requires.aliases) |> Set.union(imports.aliases) - module_name = ElixirScript.Module.quoted_to_name({:__aliases__, [], module_name_list2}) - - if State.module_listed?(module_name) do - State.delete_module_by_name(module_name) - end + module_name = ElixirScript.Module.quoted_to_name({:__aliases__, [], tl(module_name_list) ++ module_name_list2}) + State.delete_module_by_name(module_name) module_name = ElixirScript.Module.quoted_to_name({:__aliases__, [], module_name_list ++ module_name_list2}) diff --git a/test/translator/defmodule_test.exs b/test/translator/defmodule_test.exs index 2102a464..6f7de66e 100644 --- a/test/translator/defmodule_test.exs +++ b/test/translator/defmodule_test.exs @@ -145,14 +145,6 @@ defmodule ElixirScript.Translator.Defmodule.Test do end js_code = """ - const __MODULE__ = Elixir.Kernel.SpecialForms.atom('Elixir.Animals.Elephant'); - const defstruct = Elixir.Kernel.defstruct({ - [Elixir.Kernel.SpecialForms.atom('__struct__')]: __MODULE__, [Elixir.Kernel.SpecialForms.atom('trunk')]: true - }); - export { - Elixir$Animals$Elephant: defstruct - }; - const __MODULE__ = Elixir.Kernel.SpecialForms.atom('Elixir.Animals'); const something_else = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([],function() { return null; @@ -171,6 +163,14 @@ defmodule ElixirScript.Translator.Defmodule.Test do export { Elixir$Animals$Elephant$Bear: defstruct }; + + const __MODULE__ = Elixir.Kernel.SpecialForms.atom('Elixir.Animals.Elephant'); + const defstruct = Elixir.Kernel.defstruct({ + [Elixir.Kernel.SpecialForms.atom('__struct__')]: __MODULE__, [Elixir.Kernel.SpecialForms.atom('trunk')]: true + }); + export { + Elixir$Animals$Elephant: defstruct + }; """ assert_translation(ex_ast, js_code) From 867eaf318158202ba7ee30bb2e60ec81036631a3 Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Mon, 7 Dec 2015 16:16:51 -0600 Subject: [PATCH 086/860] Fixed output of .DS_Store and LICENSE. Updated to 0.14.1 --- CHANGELOG.md | 4 ++++ lib/elixir_script.ex | 2 +- mix.exs | 6 +++--- 3 files changed, 8 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 50284109..c5ea5071 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,7 @@ +# v0.14.1 +* Enhancements + * Removed .DS_Store and LICENSE from output + # v0.14.0 * Breaking * Renamed `ex2js` to `elixirscript`. This effects the escript as well as the diff --git a/lib/elixir_script.ex b/lib/elixir_script.ex index 50b1291f..c557f71e 100644 --- a/lib/elixir_script.ex +++ b/lib/elixir_script.ex @@ -133,7 +133,7 @@ defmodule ElixirScript do to the specified location """ def copy_standard_libs_to_destination(destination) do - File.cp_r!(operating_path, destination) + File.cp!(operating_path <> "/elixir.js", destination <> "/elixir.js") end @doc """ diff --git a/mix.exs b/mix.exs index ee583be5..d598bbd3 100644 --- a/mix.exs +++ b/mix.exs @@ -4,7 +4,7 @@ defmodule ElixirScript.Mixfile do def project do [ app: :elixir_script, - version: "0.14.0", + version: "0.14.1", elixir: "~> 1.0", escript: escript_config, deps: deps, @@ -86,8 +86,8 @@ defmodule ElixirScript.Mixfile do File.mkdir_p(folder_name <> "/bin") File.cp!("elixirscript", "#{folder_name}/bin/elixirscript") - File.cp_r!("priv", "#{folder_name}") - File.cp_r!("LICENSE", "#{folder_name}/LICENSE") + File.cp!("priv/elixir.js", "#{folder_name}/elixir.js") + File.cp!("LICENSE", "#{folder_name}/LICENSE") System.cmd("tar", ["czf", archive_file_name, folder_name]) From 9174b80d45fcfc1a0594c36ed1d43d90006ef155 Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Mon, 7 Dec 2015 20:16:46 -0600 Subject: [PATCH 087/860] Fixed remnants of merge conflict --- mix.exs | 4 ---- 1 file changed, 4 deletions(-) diff --git a/mix.exs b/mix.exs index 6ed5f5c2..b4d9447d 100644 --- a/mix.exs +++ b/mix.exs @@ -86,11 +86,7 @@ defmodule ElixirScript.Mixfile do File.mkdir_p(folder_name <> "/bin") File.cp!("elixirscript", "#{folder_name}/bin/elixirscript") -<<<<<<< HEAD File.cp!("priv/Elixir.js", "#{folder_name}/Elixir.js") -======= - File.cp!("priv/elixir.js", "#{folder_name}/elixir.js") ->>>>>>> master File.cp!("LICENSE", "#{folder_name}/LICENSE") System.cmd("tar", ["czf", archive_file_name, folder_name]) From 4630fa644770aeacff17d9efa1609379d8ca20be Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Mon, 7 Dec 2015 20:18:52 -0600 Subject: [PATCH 088/860] Updated version to 0.15.0-dev --- CHANGELOG.md | 2 ++ mix.exs | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index c5ea5071..d6c76296 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,5 @@ +# v0.15.0 + # v0.14.1 * Enhancements * Removed .DS_Store and LICENSE from output diff --git a/mix.exs b/mix.exs index b4d9447d..bbed44af 100644 --- a/mix.exs +++ b/mix.exs @@ -4,7 +4,7 @@ defmodule ElixirScript.Mixfile do def project do [ app: :elixir_script, - version: "0.14.1", + version: "0.15.0-dev", elixir: "~> 1.0", escript: escript_config, deps: deps, From 30a6c35dcda8cb46036807e95f052dd0b25999c6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Kalbarczyk?= Date: Mon, 14 Dec 2015 20:42:26 +0100 Subject: [PATCH 089/860] add gulp npm build task --- gulpfile.js | 8 ++++++++ package.json | 10 +++++----- 2 files changed, 13 insertions(+), 5 deletions(-) diff --git a/gulpfile.js b/gulpfile.js index 90c08076..b202f56d 100644 --- a/gulpfile.js +++ b/gulpfile.js @@ -50,5 +50,13 @@ gulp.task('dist_add_source_map', function() { .pipe(gulp.dest('./priv')); }); +gulp.task('npm_build', function() { + npmDistPath = 'dist/npm' + gulp.src('./package.json').pipe(gulp.dest(npmDistPath)); + gulp.src('./elixirscript').pipe(gulp.dest(npmDistPath)); + return gulp.src([path + '/**/*.js', '!' + path + '/build/**/*.js', '!' + path + '/dist/**/*.js', '!' + path + '/dist_build/**/*.js', '!' + path + '/tests/**/*.js']) + .pipe(babel({sourceMap: false, modules:'common'})) + .pipe(gulp.dest(npmDistPath)); +}); gulp.task('default', ['lint', 'test']); diff --git a/package.json b/package.json index 9116a303..14a90415 100644 --- a/package.json +++ b/package.json @@ -1,10 +1,10 @@ { - "name": "elixir_script", - "version": "1.0.0", + "name": "elixirscript", + "version": "0.14.1", "description": "Convert Elixir to JavaScript", - "main": "index.js", - "directories": { - "test": "test" + "main": "elixir.js", + "bin": { + "elixirscript": "./elixirscript" }, "scripts": { "test": "echo \"Error: no test specified\" && exit 1" From 88deb87c9b72230fd3761d67b359e915b65c24fb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Kalbarczyk?= Date: Sun, 20 Dec 2015 15:58:36 +0100 Subject: [PATCH 090/860] add default function parameter value support --- lib/elixir_script/pattern_matching/match.ex | 6 +++++ lib/elixir_script/translator/function.ex | 16 +++++------ test/translator/function_test.exs | 30 ++++++++++++++++++++- 3 files changed, 41 insertions(+), 11 deletions(-) diff --git a/lib/elixir_script/pattern_matching/match.ex b/lib/elixir_script/pattern_matching/match.ex index e2c05403..f9442943 100644 --- a/lib/elixir_script/pattern_matching/match.ex +++ b/lib/elixir_script/pattern_matching/match.ex @@ -180,6 +180,12 @@ defmodule ElixirScript.PatternMatching.Match do { [type(Primitive.tuple_class, pattern)], params } end + defp do_build_match({:\\, _, [{name, _, _}, default]}, env) do + name = Utils.filter_name(name) + { [parameter()], [ JS.assignment_expression(:=, JS.identifier(name), Translator.translate(default, env))] } + end + + defp do_build_match({name, _, _}, _) do name = Utils.filter_name(name) { [parameter()], [JS.identifier(name)] } diff --git a/lib/elixir_script/translator/function.ex b/lib/elixir_script/translator/function.ex index a974acfd..8baf5863 100644 --- a/lib/elixir_script/translator/function.ex +++ b/lib/elixir_script/translator/function.ex @@ -8,8 +8,8 @@ defmodule ElixirScript.Translator.Function do @patterns JS.member_expression( JS.member_expression( - JS.identifier("Elixir"), - JS.identifier("Core") + JS.identifier("Elixir"), + JS.identifier("Core") ), JS.identifier("Patterns") ) @@ -68,7 +68,7 @@ defmodule ElixirScript.Translator.Function do |> Stream.map(fn {:->, _, [ [{:when, _, [params | guards]}], body ]} -> params = wrap_params(params) - { patterns, params } = Match.build_match(List.wrap(params), env) + { patterns, params } = Match.build_match(params, env) params = make_params(params) body = make_function_body(body, env) guard_body = make_guards(guards, env) @@ -118,13 +118,9 @@ defmodule ElixirScript.Translator.Function do ) end - def wrap_params(params) when is_atom(params) do - [] - end - - def wrap_params(params) do - params - end + def wrap_params(params) when is_atom(params), do: [] + def wrap_params(params) when is_list(params), do: params + def wrap_params(params), do: List.wrap(params) def make_function_body(body, env) do body diff --git a/test/translator/function_test.exs b/test/translator/function_test.exs index 648bcfcc..b1116b3b 100644 --- a/test/translator/function_test.exs +++ b/test/translator/function_test.exs @@ -729,7 +729,6 @@ defmodule ElixirScript.Translator.Function.Test do assert_translation(ex_ast, js_code) end - should "translate function variables with ? or !" do ex_ast = quote do def test1(alpha?, beta!) do @@ -749,4 +748,33 @@ defmodule ElixirScript.Translator.Function.Test do assert_translation(ex_ast, js_code) end + should "translate function params with defaults" do + ex_ast = quote do + def test1(alpha, beta \\ 0) do + end + end + + js_code = """ + const test1 = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable(), Elixir.Core.Patterns.variable()],function(alpha,beta = 0) { + return null; + })); + """ + + assert_translation(ex_ast, js_code) + + ex_ast = quote do + def test1(alpha \\ fn x -> x end) do + end + end + + js_code = """ + const test1 = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable()],function(alpha = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable()],function(x) { + return x; + }))) { + return null; + })); + """ + + assert_translation(ex_ast, js_code) + end end From fdb6a02fc5f562797d984df33ffa771fe4941edc Mon Sep 17 00:00:00 2001 From: halohalospecial Date: Thu, 24 Dec 2015 10:44:49 +0800 Subject: [PATCH 091/860] Fixed pattern matching for maps having atom keys --- priv/Elixir.js | 14 +++++++------- src/javascript/lib/core/patterns/resolvers.js | 4 ++-- src/javascript/lib/map.js | 8 ++++---- 3 files changed, 13 insertions(+), 13 deletions(-) diff --git a/priv/Elixir.js b/priv/Elixir.js index 07d90f1b..12b52805 100644 --- a/priv/Elixir.js +++ b/priv/Elixir.js @@ -354,7 +354,7 @@ function resolveArray(pattern) { function resolveObject(pattern) { let matches = {}; - for (let key of Object.keys(pattern)) { + for (let key of Object.keys(pattern).concat(Object.getOwnPropertySymbols(pattern))) { matches[key] = buildMatch(pattern[key]); } @@ -363,7 +363,7 @@ function resolveObject(pattern) { return false; } - for (let key of Object.keys(pattern)) { + for (let key of Object.keys(pattern).concat(Object.getOwnPropertySymbols(pattern))) { if (!(key in value) || !matches[key](value[key], args)) { return false; } @@ -1013,7 +1013,7 @@ class ProcessSystem { let pid = this.pidof(id); let process = this.pids.get(pid); - return Object.keys(process.dict); + return Object.keys(process.dict).concat(Object.getOwnPropertySymbols(process.dict)); } erase(id, key) { @@ -2505,7 +2505,7 @@ function __new__() { } function keys(map) { - return Object.keys(map); + return Object.keys(map).concat(Object.getOwnPropertySymbols(map)); } function size(map) { @@ -2577,7 +2577,7 @@ function split$1(map, keys) { let split1 = {}; let split2 = {}; - for (let key of Object.keys(map)) { + for (let key of Object.keys(map).concat(Object.getOwnPropertySymbols(map))) { if (keys.indexOf(key) > -1) { split1[key] = map[key]; } else { @@ -2591,7 +2591,7 @@ function split$1(map, keys) { function take(map, keys) { let split1 = {}; - for (let key of Object.keys(map)) { + for (let key of Object.keys(map).concat(Object.getOwnPropertySymbols(map))) { if (keys.indexOf(key) > -1) { split1[key] = map[key]; } @@ -2603,7 +2603,7 @@ function take(map, keys) { function drop(map, keys) { let split1 = {}; - for (let key of Object.keys(map)) { + for (let key of Object.keys(map).concat(Object.getOwnPropertySymbols(map))) { if (keys.indexOf(key) === -1) { split1[key] = map[key]; } diff --git a/src/javascript/lib/core/patterns/resolvers.js b/src/javascript/lib/core/patterns/resolvers.js index 9b0fcbd1..ea21d51d 100644 --- a/src/javascript/lib/core/patterns/resolvers.js +++ b/src/javascript/lib/core/patterns/resolvers.js @@ -134,7 +134,7 @@ function resolveArray(pattern: Array): Function { function resolveObject(pattern: Object): Function { let matches = {}; - for(let key of Object.keys(pattern)){ + for(let key of Object.keys(pattern).concat(Object.getOwnPropertySymbols(pattern))){ matches[key] = buildMatch(pattern[key]); } @@ -143,7 +143,7 @@ function resolveObject(pattern: Object): Function { return false; } - for(let key of Object.keys(pattern)){ + for(let key of Object.keys(pattern).concat(Object.getOwnPropertySymbols(pattern))){ if(!(key in value) || !matches[key](value[key], args) ){ return false; } diff --git a/src/javascript/lib/map.js b/src/javascript/lib/map.js index 00a5ba39..8775d4ea 100644 --- a/src/javascript/lib/map.js +++ b/src/javascript/lib/map.js @@ -5,7 +5,7 @@ function __new__(){ } function keys(map){ - return Object.keys(map); + return Object.keys(map).concat(Object.getOwnPropertySymbols(map)); } function size(map){ @@ -92,7 +92,7 @@ function split(map, keys){ let split1 = {}; let split2 = {}; - for(let key of Object.keys(map)){ + for(let key of Object.keys(map).concat(Object.getOwnPropertySymbols(map))){ if(keys.indexOf(key) > -1){ split1[key] = map[key]; }else{ @@ -109,7 +109,7 @@ function split(map, keys){ function take(map, keys){ let split1 = {}; - for(let key of Object.keys(map)){ + for(let key of Object.keys(map).concat(Object.getOwnPropertySymbols(map))){ if(keys.indexOf(key) > -1){ split1[key] = map[key]; } @@ -121,7 +121,7 @@ function take(map, keys){ function drop(map, keys){ let split1 = {}; - for(let key of Object.keys(map)){ + for(let key of Object.keys(map).concat(Object.getOwnPropertySymbols(map))){ if(keys.indexOf(key) === -1){ split1[key] = map[key]; } From 2dff85f563e7f28d17676df947e6efa769e10c7c Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Wed, 23 Dec 2015 21:26:50 -0600 Subject: [PATCH 092/860] Added ENV tracking. * Can now define alias, import, and require at lexical scopes * __ENV__ and __CALLER__ are now supported * Some refactoring to remove duplicate code * Removed unused modules * Started writing stadard libs in Elixir instead of JavaScript Squashed commit of the following: commit 95a0ae958ff616c7d33c987854bd9137ea31470e Author: Bryan Joseph Date: Wed Dec 23 21:24:56 2015 -0600 Updated FAQ commit e075bec545bcc15ca25595680dd35b9051dca705 Author: Bryan Joseph Date: Wed Dec 23 21:21:17 2015 -0600 Removed implementations for enumerable and collectable commit 59b4e0812d1fd55c380917d4d009bac9615c51e6 Merge: 3d8dac3 f28013e Author: Bryan Joseph Date: Wed Dec 23 21:14:52 2015 -0600 Merged from master commit 3d8dac3a1b04f9c07fc48a8860db00e0ec0ab92d Author: Bryan Joseph Date: Wed Dec 23 21:08:33 2015 -0600 Updated CHANGELOG commit 43286e0a793f1612f436c8605f017d626d445eb8 Author: Bryan Joseph Date: Wed Dec 23 20:28:27 2015 -0600 More refactoring. Added ElixirScript.Macro.Env module commit df93c15a02e40aac82da92976d3db3174e64d38b Author: Bryan Joseph Date: Wed Dec 23 20:09:20 2015 -0600 More refactoring of duplicated code commit f2aca9f455b65321dbe2ddc1e4518659f2337252 Merge: 1e1af1d 3963476 Author: Bryan Joseph Date: Wed Dec 23 14:21:38 2015 -0600 Merged from master commit 1e1af1d758c63e685cbaef1bb07c893a34d73aee Author: Bryan Joseph Date: Tue Dec 22 17:05:08 2015 -0600 Fixed most unit tests. Commented out pattern matching tests until its figured out how to handle them with the compiler state commit 91a2969554571d1da1645acc3cd365735457f929 Author: Bryan Joseph Date: Mon Dec 21 12:36:35 2015 -0600 Fixed more bugs that cropped up from using the env for imports instead of the current module commit 2d7f36b1fe2f616c7951a93758c8c3cc78702da9 Author: Bryan Joseph Date: Mon Dec 21 09:29:33 2015 -0600 imports, requires, and aliases should now work in scope (WIP) commit caf64a8c2c31a3679d7e85e2b7c9ac15a14dd6c1 Author: Bryan Joseph Date: Sun Dec 20 16:49:21 2015 -0600 Finished adding tracking of environment commit dc26960e1dd47377c78ab429bcb5a7258ef44e59 Author: Bryan Joseph Date: Sun Dec 20 11:10:05 2015 -0600 Getting closer passing and returning an environment commit c10962d10dd7128aeb031af72fdc1ffbd1a771a5 Author: Bryan Joseph Date: Wed Dec 16 21:12:18 2015 -0600 Refactored ElixirScript.Env commit 02ac54384cb7cdf5ce4f1258f356c4ae69132a02 Author: Bryan Joseph Date: Wed Dec 16 20:30:25 2015 -0600 Updated ElixirScript.env to track environment. Passing it around instead of elixir's env commit 727be4185eca5721972234a59d35e6b3d3f6f7d9 Author: Bryan Joseph Date: Tue Dec 15 21:23:54 2015 -0600 Refactoring make _module and protocol code commit 42f2942631fd1a8e3b3ea7574e97925902440133 Author: Bryan Joseph Date: Tue Dec 15 16:20:03 2015 -0600 Exposing list of module aliases publicly commit a60cd30d3a47eaf2b8aa8123b735594586298f8a Author: Bryan Joseph Date: Mon Dec 14 20:28:41 2015 -0600 Fixed member? definition commit 3b5689c5d41b2166d145d81034f4c3bf44679b72 Author: Bryan Joseph Date: Mon Dec 14 20:17:37 2015 -0600 Added view module in elixir commit e0a4905949935f817b7577152d59b38eadbe9b92 Author: Bryan Joseph Date: Sun Dec 13 17:06:08 2015 -0600 Added more types of modules from the standard library to see how they fit commit 7c20bf1bd53f28ee3fa37219130a2735aa328bfe Author: Bryan Joseph Date: Fri Dec 11 23:19:44 2015 -0600 Working through writing elixirscript Kernel module in Elixir commit be61c44a81cd0e23ef360091c4cb35b27bb6d20d Author: Bryan Joseph Date: Tue Dec 8 09:31:44 2015 -0600 Started writing kernel module --- CHANGELOG.md | 7 +- FAQ.md | 18 +- lib/elixir_script.ex | 119 +- lib/elixir_script/env.ex | 173 +- lib/elixir_script/lib/js.ex | 14 - lib/elixir_script/lib/view.ex | 41 - lib/elixir_script/module.ex | 92 +- lib/elixir_script/pattern_matching/match.ex | 40 +- lib/elixir_script/preprocess/aliases.ex | 56 - lib/elixir_script/preprocess/modules.ex | 221 +-- lib/elixir_script/preprocess/using.ex | 18 +- lib/elixir_script/preprocess/variables.ex | 152 -- lib/elixir_script/state.ex | 94 +- lib/elixir_script/translator.ex | 356 ++-- lib/elixir_script/translator/assignment.ex | 10 +- lib/elixir_script/translator/bitstring.ex | 39 +- lib/elixir_script/translator/block.ex | 8 +- lib/elixir_script/translator/capture.ex | 57 +- lib/elixir_script/translator/case.ex | 17 +- lib/elixir_script/translator/cond.ex | 10 +- lib/elixir_script/translator/expression.ex | 10 +- lib/elixir_script/translator/for.ex | 41 +- lib/elixir_script/translator/function.ex | 240 ++- lib/elixir_script/translator/import.ex | 70 - lib/elixir_script/translator/js.ex | 40 +- lib/elixir_script/translator/kernel.ex | 298 ---- lib/elixir_script/translator/logger.ex | 24 - lib/elixir_script/translator/map.ex | 12 +- lib/elixir_script/translator/module.ex | 85 +- lib/elixir_script/translator/primitive.ex | 23 +- lib/elixir_script/translator/protocol.ex | 80 +- lib/elixir_script/translator/quote.ex | 8 +- lib/elixir_script/translator/receive.ex | 52 - lib/elixir_script/translator/struct.ex | 47 +- lib/elixir_script/translator/try.ex | 29 +- lib/elixir_script/translator/utils.ex | 94 +- lib/elixir_script/universal/atom.ex | 12 + lib/elixir_script/universal/collectable.ex | 3 + lib/elixir_script/universal/enumerable.ex | 5 + lib/elixir_script/universal/integer.ex | 19 + lib/elixir_script/universal/kernel.ex | 181 ++ lib/elixir_script/universal/macro/env.ex | 19 + lib/elixir_script/universal/string/chars.ex | 47 + lib/elixir_script/universal/tuple.ex | 23 + lib/elixir_script/universal/view.ex | 78 + mix.exs | 5 +- mix.lock | 2 +- priv/Elixir.js | 1664 ++++++++++--------- src/javascript/elixir.js | 4 - src/javascript/lib/base.js | 3 +- src/javascript/lib/core.js | 63 +- src/javascript/lib/core/functions.js | 216 ++- src/javascript/lib/core/primitives.js | 1 + src/javascript/lib/enum.js | 2 +- test/elixir_script_test.exs | 35 +- test/pattern_matching/match_test.exs | 464 +++--- test/test_helper.exs | 3 +- test/translator/atom_test.exs | 7 +- test/translator/bug_test.exs | 9 +- test/translator/capture_test.exs | 12 +- test/translator/case_test.exs | 26 +- test/translator/defmodule_test.exs | 137 +- test/translator/for_test.exs | 6 +- test/translator/function_test.exs | 96 +- test/translator/kernel_test.exs | 22 +- test/translator/list_test.exs | 20 +- test/translator/protocol_test.exs | 47 +- test/translator/quote_test.exs | 12 +- test/translator/receive_test.exs | 63 - test/translator/string_test.exs | 8 +- test/translator/struct_test.exs | 81 +- test/translator/try_test.exs | 2 +- 72 files changed, 3092 insertions(+), 3000 deletions(-) delete mode 100644 lib/elixir_script/lib/view.ex delete mode 100644 lib/elixir_script/preprocess/aliases.ex delete mode 100644 lib/elixir_script/preprocess/variables.ex delete mode 100644 lib/elixir_script/translator/kernel.ex delete mode 100644 lib/elixir_script/translator/logger.ex delete mode 100644 lib/elixir_script/translator/receive.ex create mode 100644 lib/elixir_script/universal/atom.ex create mode 100644 lib/elixir_script/universal/collectable.ex create mode 100644 lib/elixir_script/universal/enumerable.ex create mode 100644 lib/elixir_script/universal/integer.ex create mode 100644 lib/elixir_script/universal/kernel.ex create mode 100644 lib/elixir_script/universal/macro/env.ex create mode 100644 lib/elixir_script/universal/string/chars.ex create mode 100644 lib/elixir_script/universal/tuple.ex create mode 100644 lib/elixir_script/universal/view.ex delete mode 100644 test/translator/receive_test.exs diff --git a/CHANGELOG.md b/CHANGELOG.md index d6c76296..af24a172 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,4 +1,9 @@ -# v0.15.0 +# v0.15.0-dev +* Enhancements + * Now tracking environment scopes + * `alias`, `require`, and `import` now work inside lexical scopes + * `__ENV__` and `__CALLER__` are now supported + * Began writing some of the standard libraries in Elixir instead of JavaScript # v0.14.1 * Enhancements diff --git a/FAQ.md b/FAQ.md index 7a0c79d7..dc1c7056 100644 --- a/FAQ.md +++ b/FAQ.md @@ -4,7 +4,7 @@ ### A. Because you may reference JavaScript code in your ElixirScript modules that the Elixir compiler may not know about. -For instance, if you are writing an ElixirScript module that references JQuery or React. Since the Elixir compiler won't know about the existence of these, you may end up with some compiler errors. The main purpose is to sort of hide it from the Elixir compiler. You can feed normal `.ex` files to the ElixirScript compiler and it can turn them into JavaScript however. +For instance, if you are writing an ElixirScript module that references JQuery or React. Since the Elixir compiler won't know about the existence of these, you may end up with some compiler errors. The main purpose is to sort of hide it from the Elixir compiler. You can feed normal `.ex` files to the ElixirScript compiler and it can turn them into JavaScript however. In the future, the added file extension may not be needed as much as ElixirScript continues to support more of the Elixir standard library. An eventual goal would be to use standard `.ex` files in both Elixir and ElixirScript, while leaving `exjs` files strictly for JavaScript related code. @@ -40,11 +40,13 @@ The compiler to this point has been focused on translating Kernel.SpecialForms a * `require` * `left :: right` * `alias` - -* Missing * `__CALLER__` * `__ENV__` + +* Missing * `super(args)` + * `receive` + * `with` * Caveats * `<>` - not supported in pattern matching yet @@ -52,10 +54,10 @@ The compiler to this point has been focused on translating Kernel.SpecialForms a * `left = right` does not support full unification yet. ```elixir a = 1 # works as expected - + 1 = a # may not work currently, but in some cases it will ``` - + #### Completed Modules @@ -66,7 +68,7 @@ The compiler to this point has been focused on translating Kernel.SpecialForms a * Logger * Map * MapSet - + #### Incomplete Modules * Kernel @@ -78,7 +80,7 @@ The compiler to this point has been focused on translating Kernel.SpecialForms a * String * Bitwise * Set - + #### Missing Modules * Everything else @@ -110,4 +112,4 @@ One of my demos is an example of using a design similar to redux to accomplish t ### A. Maybe. -Once processes are added, then we can see about adding OTP similar or specific things to ElixirScript. \ No newline at end of file +Once processes are added, then we can see about adding OTP similar or specific things to ElixirScript. diff --git a/lib/elixir_script.ex b/lib/elixir_script.ex index de50b300..05b1b028 100644 --- a/lib/elixir_script.ex +++ b/lib/elixir_script.ex @@ -2,7 +2,6 @@ defmodule ElixirScript do alias ElixirScript.Translator.JSModule alias ESTree.Tools.Builder alias ESTree.Tools.Generator - require Logger @moduledoc """ Translates Elixir into JavaScript. @@ -23,6 +22,23 @@ defmodule ElixirScript do When using this option, the Elixir.js file is not exported """ + defmacro __using__(_) do + quote do + import Kernel, only: [&&: 2, use: 2, use: 1] + import ElixirScript.Kernel + require ElixirScript.JS, as: JS + require ElixirScript.Html, as: Html + require ElixirScript.VDom, as: VDom + end + end + + @external_resource libs_path = Path.join([__DIR__, "elixir_script", "universal", "**", "*.ex"]) + @libs (for path <- Path.wildcard(libs_path) do + path + |> File.read! + |> Code.string_to_quoted! + end) + @doc """ Compiles the given Elixir code string """ @@ -46,7 +62,10 @@ defmodule ElixirScript do ElixirScript.State.start_link(root, env) - build_environment([quoted]) + libs = @libs + |> updated_quoted + + build_environment(libs ++ [updated_quoted(quoted)]) create_code(include_path, import_standard_libs?, stdlib_path) end @@ -62,10 +81,14 @@ defmodule ElixirScript do ElixirScript.State.start_link(root, env) - path + libs = @libs + |> updated_quoted + + code = path |> Path.wildcard |> Enum.map(&file_to_quoted/1) - |> build_environment + + build_environment(libs ++ code) create_code(include_path, true, stdlib_path) end @@ -74,6 +97,7 @@ defmodule ElixirScript do file |> File.read! |> Code.string_to_quoted! + |> updated_quoted end defp build_environment(code_list) do @@ -81,51 +105,58 @@ defmodule ElixirScript do |> ElixirScript.Preprocess.Modules.get_info end - defp custom_env() do - require Logger - require ElixirScript.JS, as: JS - require ElixirScript.Html, as: Html - require ElixirScript.VDom, as: VDom + defp updated_quoted(quoted) do + Macro.prewalk(quoted, fn + ({name, context, parms}) -> + if context[:import] == Kernel do + context = Keyword.update!(context, :import, fn(_) -> ElixirScript.Kernel end) + end + + {name, context, parms} + (x) -> + x + end) + end + + def custom_env() do + __using__([]) __ENV__ end defp create_code(include_path, import_standard_libs?, stdlib_path) do - ElixirScript.State.process_imports + standard_lib_modules = ElixirScript.Module.build_standard_lib_map() + |> Map.values state = ElixirScript.State.get - parent = self - result = - state.modules - |> Enum.map(fn ast -> - spawn_link fn -> - Process.put(:current_module, ast.name) - - result = - ElixirScript.Translator.Module.make_module(ast.name, ast.body, state.env) - |> Enum.map(&(convert_to_code(&1, state.root, include_path, state.env, import_standard_libs?, stdlib_path))) - send parent, {self, result} - end + Map.values(state.modules) + |> Enum.reject(fn(ast) -> + import_standard_libs? == false && ast.name in standard_lib_modules end) - |> Enum.map(fn pid -> - receive do - {^pid, x} -> x - end + |> Enum.map(fn ast -> + env = ElixirScript.Env.module_env(ast.name, "#{create_file_name(ast.name)}") + + case ast.type do + :module -> + ElixirScript.Translator.Module.make_module(ast.name, ast.body, env) + :protocol -> + ElixirScript.Translator.Protocol.consolidate(ast, env) + end + |> convert_to_code(state.root, state.elixir_env, import_standard_libs?, stdlib_path) end) - |> List.flatten - - protocol_result = - state.protocols - |> Dict.to_list - |> ElixirScript.Translator.Protocol.consolidate(state.env) - |> Enum.map(&(convert_to_code(&1, state.root, include_path, state.env, import_standard_libs?, stdlib_path))) - |> List.flatten ElixirScript.State.stop - result ++ protocol_result + result + |> Enum.map(fn({path, code}) -> + if(include_path) do + { path, code } + else + code + end + end) end @doc """ @@ -143,11 +174,10 @@ defmodule ElixirScript do File.read!(operating_path <> "/Elixir.js") end - defp convert_to_code(js_ast, root, include_path, env, import_standard_libs, stdlib_path) do + defp convert_to_code(js_ast, root, env, import_standard_libs, stdlib_path) do js_ast |> process_module(root, env, import_standard_libs, stdlib_path) |> javascript_ast_to_code - |> process_include_path(include_path) end defp process_module(%JSModule{} = module, root, _, import_standard_libs, stdlib_path) do @@ -172,11 +202,10 @@ defmodule ElixirScript do "#{name}.js" end - defp process_include_path({_, _} = pair, true), - do: pair - - defp process_include_path({_, code}, false), - do: code + defp create_file_name(name) do + name = ElixirScript.Module.name_to_js_file_name(name) + "#{name}.js" + end @doc false def javascript_ast_to_code({path, js_ast}) do @@ -192,16 +221,18 @@ defmodule ElixirScript do end defp prepare_js_ast(js_ast) do - case js_ast do + js_ast = case js_ast do modules when is_list(modules) -> modules |> Enum.reduce([], &(&2 ++ &1.body)) |> Builder.program - %ElixirScript.Translator.Group{body: body} -> + %ElixirScript.Translator.Group{ body: body } -> Builder.program(body) _ -> js_ast end + + js_ast end defp operating_path do diff --git a/lib/elixir_script/env.ex b/lib/elixir_script/env.ex index 5fe1f014..49ee8262 100644 --- a/lib/elixir_script/env.ex +++ b/lib/elixir_script/env.ex @@ -1,6 +1,177 @@ defmodule ElixirScript.Env do @moduledoc false - defstruct env: __ENV__, modules: HashSet.new, root: "", protocols: HashDict.new + def module_env(ElixirScript.Temp, filename) do + + env = %ElixirScript.Macro.Env { + module: ElixirScript.Temp, file: filename, requires: [], + functions: [], + macros: [] + } + + add_import(env, ElixirScript.Kernel) + end + + def module_env(module_name, filename) do + module = ElixirScript.State.get_module(module_name) + + env = %ElixirScript.Macro.Env { + module: module_name, file: filename, requires: [], + functions: [{ module.name, module.functions}], + macros: [{ module.name, module.macros}] + } + + add_import(env, ElixirScript.Kernel) + end + + def function_env(env, { _, _ } = func) do + %{ env | function: func, caller: env } + end + + def function_env(env, nil) do + %{ env | function: nil, caller: env, vars: [] } + end + + def find_module(env, name_arity) do + result = Enum.find(env.functions ++ env.macros, fn({_, functions}) -> + name_arity in functions + end) + + if result == nil do + nil + else + elem(result, 0) + end + + end + + def add_var(env, variable_name) when is_binary(variable_name) do + add_var(env, String.to_atom(variable_name)) + end + + def add_var(env, variable_name) do + %{ env | vars: Keyword.update(env.vars, variable_name, 0, &(&1 + 1)) } + end + + def get_var(env, variable_name) when is_binary(variable_name) do + get_var(env, String.to_atom(variable_name)) + end + + def get_var(env, variable_name) do + count = Keyword.get(env.vars, variable_name, nil) + + case count do + nil -> + nil + 0 -> + String.to_atom(Atom.to_string(variable_name)) + _ -> + String.to_atom(Atom.to_string(variable_name) <> to_string(count)) + end + end + + def has_var?(env, variable_name) when is_binary(variable_name) do + has_var?(env, String.to_atom(variable_name)) + end + + def has_var?(env, variable_name) do + Keyword.get(env.vars, variable_name, nil) != nil + end + + defp get_module(env, Kernel) do + get_module(env, ElixirScript.Kernel) + end + + defp get_module(env, module_name) do + module = ElixirScript.State.get_module(module_name) + + unless module do + raise "Module #{module_name} not found" + end + + ElixirScript.State.add_module_reference(env.module, module.name) + module + end + + def add_import(env, module_name) do + module = get_module(env, module_name) + + + %{ env | requires: Enum.uniq(env.requires ++ [module.name]), + functions: env.functions ++ [{ module.name, module.functions }], + macros: env.macros ++ [{ module.name, module.macros }] } + end + + def add_import(env, module_name, [only: :functions]) do + module = get_module(env, module_name) + + + %{ env | requires: Enum.uniq(env.requires ++ [module.name]), + functions: env.functions ++ [{ module.name, module.functions }] } + end + + def add_import(env, module_name, [only: :macros]) do + module = get_module(env, module_name) + + + %{ env | requires: Enum.uniq(env.requires ++ [module.name]), + macros: env.macros ++ [{ module.name, module.macros }] } + end + + def add_import(env, module_name, [only: only]) do + module = get_module(env, module_name) + + macros = Enum.filter(module.macros, fn(mac) -> + mac in only + end) + functions = Enum.filter(module.functions, fn(func) -> + func in only + end) + + %{ env | requires: Enum.uniq(env.requires ++ [module.name]), + functions: env.functions ++ [{ module.name, functions }], + macros: env.macros ++ [{ module.name, macros }] } + end + + def add_import(env, module_name, [except: except]) do + module = get_module(env, module_name) + + macros = Enum.filter(module.macros, fn(mac) -> not(mac in except) end) + functions = Enum.filter(module.functions, fn(func) -> not(func in except) end) + + %{ env | requires: env.requires ++ [module.name], + functions: env.functions ++ [{ module.name, functions }], + macros: env.macros ++ [{ module.name, macros }] } + end + + def add_alias(env, module_name, alias_name) do + module = get_module(env, module_name) + + %{ env | aliases: Enum.uniq(env.aliases ++ [{alias_name, module.name}]) } + end + + def add_require(env, module_name) do + module = get_module(env, module_name) + + %{ env | requires: Enum.uniq(env.requires ++ [module.name]) } + end + + def add_require(env, module_name, alias_name) do + module = get_module(env, module_name) + + %{ env | aliases: Enum.uniq(env.aliases ++ [{alias_name, module.name}]), + requires: Enum.uniq(env.requires ++ [module.name]) } + end + + def get_module_name(env, module_name) do + module_name = ElixirScript.Module.get_module_name(module_name) + + if Keyword.has_key?(env.aliases, module_name) do + Keyword.fetch!(env.aliases, module_name) + else + module_name + end + + end end diff --git a/lib/elixir_script/lib/js.ex b/lib/elixir_script/lib/js.ex index 4ba5d7c3..ae58012b 100644 --- a/lib/elixir_script/lib/js.ex +++ b/lib/elixir_script/lib/js.ex @@ -38,18 +38,4 @@ defmodule ElixirScript.JS do defmacro import(module, from) do end - - @doc """ - Turns an ElixirScript data structure into a JavaScript one. - """ - defmacro to_js(value) do - end - - - @doc """ - Turns an ElixirScript data structure into JSON. - """ - defmacro to_json(value) do - end - end diff --git a/lib/elixir_script/lib/view.ex b/lib/elixir_script/lib/view.ex deleted file mode 100644 index 5c484430..00000000 --- a/lib/elixir_script/lib/view.ex +++ /dev/null @@ -1,41 +0,0 @@ -defmodule ElixirScript.View do - @moduledoc """ - Defines a module to handle view state. Handles the diffing and patching - normally done manually using the `VDom` module. - - def render(id) do - Html.div [id: "hello"] do - Html.span do - "Hello" - end - end - end - - #Starts View state and renders initial view - {:ok, view} = View.start(:document.body, &render/1, ["hello"]) - - #Updates the view with the new args - View.render(view, ["world"]) - """ - - - @doc """ - Starts the View state. This will render the initial view using the - render_func and the args - """ - def start(dom_root, render_func, args, options \\ []) do - end - - @doc """ - Stops the View state - """ - def stop(view) do - end - - @doc """ - Updates the view by passing the args to the render_func - """ - def render(view, args) do - end - -end diff --git a/lib/elixir_script/module.ex b/lib/elixir_script/module.ex index 9f3ca8a9..781631a6 100644 --- a/lib/elixir_script/module.ex +++ b/lib/elixir_script/module.ex @@ -1,67 +1,12 @@ defmodule ElixirScript.Module do @moduledoc false - defstruct name: nil, functions: Keyword.new, macros: Keyword.new, body: nil, - aliases: [], requires: [], imports: [], js_imports: [], module_refs: [] + defstruct name: nil, + functions: Keyword.new, private_functions: Keyword.new, + macros: Keyword.new, private_macros: Keyword.new, + body: nil, js_imports: [], module_refs: [], type: :module, + spec: nil, impls: HashDict.new - def functions(module) do - Keyword.keys(module.functions) |> Enum.uniq - end - - def macros(module) do - Keyword.keys(module.macros) |> Enum.uniq - end - - def aliases(module) do - module.aliases - end - - def requires(module) do - module.requires - end - - def imports(module) do - module.imports - end - - def has_alias?(module, name) do - case module.aliases do - aliases when is_list(aliases) -> - List.keymember?(module.aliases, name, 0) - _ -> - List.keymember?(Set.to_list(module.aliases), name, 0) - end - end - - def get_alias(nil, _) do - nil - end - - def get_alias(module, name) when is_list(name) do - name = {:__aliases__, [], name } |> quoted_to_name - get_alias(module, name) - end - - def get_alias(module, name) when is_atom(name) do - Enum.find(module.aliases, fn({the_alias, _}) -> - name == the_alias - end) - end - - def get_alias(module, {:__aliases__, _, _} = ast) do - name = quoted_to_name(ast) - get_alias(module, name) - end - - def imported?(module, function_name) do - imported_modules = Enum.find(module.imports, fn({_, funcs}) -> - Enum.member?(funcs, function_name) - end) - - if imported_modules do - elem(imported_modules, 0) - end - end def quoted_to_name(the_alias) do {name, _} = Code.eval_quoted(the_alias) @@ -88,4 +33,31 @@ defmodule ElixirScript.Module do Enum.join([:Elixir] ++ name, ".") end + def has_function?(module_name, name_arity) do + module = ElixirScript.State.get_module(module_name) + name_arity in module.functions or name_arity in module.private_functions + end + + def build_standard_lib_map() do + Map.new + |> Map.put(Kernel, ElixirScript.Kernel) + |> Map.put(Tuple, ElixirScript.Tuple) + |> Map.put(Atom, ElixirScript.Atom) + |> Map.put(Collectable, ElixirScript.Collectable) + |> Map.put(String.Chars, ElixirScript.String.Chars) + |> Map.put(Enumerable, ElixirScript.Enumerable) + |> Map.put(Integer, ElixirScript.Integer) + |> Map.put(Macro.Env, ElixirScript.Macro.Env) + |> Map.put(View, ElixirScript.View) + end + + def get_module_name(module_name) do + case Map.get(build_standard_lib_map, module_name) do + nil -> + module_name + actual_module_name -> + actual_module_name + end + end + end diff --git a/lib/elixir_script/pattern_matching/match.ex b/lib/elixir_script/pattern_matching/match.ex index f9442943..af0f7e3a 100644 --- a/lib/elixir_script/pattern_matching/match.ex +++ b/lib/elixir_script/pattern_matching/match.ex @@ -100,13 +100,37 @@ defmodule ElixirScript.PatternMatching.Match do ) end + def process_match(params, env) do + build_match(params, env) + |> update_env(env) + end + + defp update_env({ patterns, params }, env) do + + { params, env } = Enum.map_reduce(params, env, fn + (%ESTree.Identifier{name: :undefined} = param, env) -> + { param, env } + + (%ESTree.Identifier{} = param, env) -> + env = ElixirScript.Env.add_var(env, param.name) + new_name = ElixirScript.Env.get_var(env, param.name) + + { %{ param | name: new_name }, env } + + (param, env) -> + { param, env } + end) + + { patterns, params, env } + end + def build_match(params, env) do Enum.map(params, &do_build_match(&1, env)) |> reduce_patterns end defp do_build_match({:^, _, [value]}, env) do - { [bound(Translator.translate(value, env))], [nil] } + { [bound(Translator.translate!(value, env))], [nil] } end defp do_build_match({:_, _, _}, _) do @@ -114,17 +138,17 @@ defmodule ElixirScript.PatternMatching.Match do end defp do_build_match([{:|, _, [head, tail]}], env) do - { [head_tail()], [Translator.translate(head, env), Translator.translate(tail, env)] } + { [head_tail()], [Translator.translate!(head, env), Translator.translate!(tail, env)] } end defp do_build_match({:<>, _, [prefix, value]}, env) do - { [starts_with(prefix)], [Translator.translate(value, env)] } + { [starts_with(prefix)], [Translator.translate!(value, env)] } end defp do_build_match({:%{}, _, props}, env) do properties = Enum.map(props, fn({key, value}) -> {pattern, params} = do_build_match(value, env) - { Map.make_property(Translator.translate(key, env), hd(List.wrap(pattern))), params } + { Map.make_property(Translator.translate!(key, env), hd(List.wrap(pattern))), params } end) {props, params} = Enum.reduce(properties, {[], []}, fn({prop, param}, {props, params}) -> @@ -134,7 +158,7 @@ defmodule ElixirScript.PatternMatching.Match do { JS.object_expression(List.wrap(props)), params } end - defp do_build_match({:%, _, [{:__aliases__, _, name}, {:%{}, meta, props}]}, env) do + defp do_build_match({:%, _, [{:__aliases__, _, _} = name, {:%{}, meta, props}]}, env) do struct_name = Struct.get_struct_class(name, env) {pattern, params} = do_build_match({:%{}, meta, props}, env) @@ -158,7 +182,7 @@ defmodule ElixirScript.PatternMatching.Match do end defp do_build_match(term, env) when is_number(term) or is_binary(term) or is_boolean(term) or is_atom(term) or is_nil(term) do - { [Translator.translate(term, env)], [] } + { [Translator.translate!(term, env)], [] } end defp do_build_match({ one, two }, env) do @@ -182,7 +206,7 @@ defmodule ElixirScript.PatternMatching.Match do defp do_build_match({:\\, _, [{name, _, _}, default]}, env) do name = Utils.filter_name(name) - { [parameter()], [ JS.assignment_expression(:=, JS.identifier(name), Translator.translate(default, env))] } + { [parameter()], [ JS.assignment_expression(:=, JS.identifier(name), Translator.translate!(default, env))] } end @@ -199,7 +223,7 @@ defmodule ElixirScript.PatternMatching.Match do end defp unify(target, source, env) do - {patterns, params} = build_match([source], env) + { patterns, params } = build_match([source], env) { [capture(hd(patterns))], params ++ [JS.identifier(Utils.filter_name(target))] } end diff --git a/lib/elixir_script/preprocess/aliases.ex b/lib/elixir_script/preprocess/aliases.ex deleted file mode 100644 index 14da4ae2..00000000 --- a/lib/elixir_script/preprocess/aliases.ex +++ /dev/null @@ -1,56 +0,0 @@ -defmodule ElixirScript.Preprocess.Aliases do - @moduledoc false - - @doc """ - Takes the ast, records any uses of outer modules, and updates the calls - to make them look like as if using an alias - - ex. - Hello.World.hi() - - #would turn into - World.hi() - - #the "Hello.World" would be placed in a set and later used for building an alias - """ - def process(module_name_list, ast, env) do - new_ast = Macro.prewalk(ast, fn(x) -> - process_aliases(x, env, module_name_list) - end) - - module = ElixirScript.State.get_module(module_name_list) - - if module do - { new_ast, ElixirScript.Module.aliases(module) } - else - { new_ast, [] } - end - end - - def process_aliases({{:., meta1, [{:__aliases__, meta2, aliases}, function]}, meta3, params}, _, module_name_list) when aliases in [[:Collectable], [:Enumerable], [:Inspect], [:List, :Chars], [:String, :Chars]] do - new_ast = {{:., meta1, [{:__aliases__, meta2, List.last(aliases) |> List.wrap }, function]}, meta3, params} - ElixirScript.State.add_alias(ElixirScript.Module.quoted_to_name({:__aliases__, [], module_name_list}), {:__aliases__, meta2, [:Elixir] ++ aliases}) - new_ast - end - - - def process_aliases({{:., meta1, [{:__aliases__, meta2, aliases}, function]}, meta3, params} = ast, _, module_name_list) do - if ElixirScript.State.module_listed?(aliases) do - new_ast = {{:., meta1, [{:__aliases__, meta2, List.last(aliases) |> List.wrap }, function]}, meta3, params} - - module = ElixirScript.State.get_module(module_name_list) - - if !ElixirScript.Module.has_alias?(module, {:__aliases__, meta2, List.last(aliases) |> List.wrap }) do - ElixirScript.State.add_alias(ElixirScript.Module.quoted_to_name({:__aliases__, [], module_name_list}), {:__aliases__, meta2, aliases}) - end - - new_ast - else - ast - end - end - - def process_aliases(ast, _, _) do - ast - end -end diff --git a/lib/elixir_script/preprocess/modules.ex b/lib/elixir_script/preprocess/modules.ex index 7e4271fe..32e0f522 100644 --- a/lib/elixir_script/preprocess/modules.ex +++ b/lib/elixir_script/preprocess/modules.ex @@ -3,21 +3,13 @@ defmodule ElixirScript.Preprocess.Modules do alias ElixirScript.State - @standard_lib_protocols [ - [:Enumerable], - [:Inspect], - [:String, :Chars], - [:List, :Chars], - [:Collectable] - ] - def get_info(modules) do Enum.map(modules, fn { :__block__, _, list } -> {mods, no_mods} = Enum.partition(list, fn - ({:defprotocol, _, [{:__aliases__, _, protocol}| _ ] }) when not protocol in @standard_lib_protocols -> + ({:defprotocol, _, _ }) -> true - ({:defimpl, _, [ {:__aliases__, _, protocol} | _] }) when not protocol in @standard_lib_protocols -> + ({:defimpl, _, _ }) -> true ({:defmodule, _, _}) -> true @@ -26,9 +18,9 @@ defmodule ElixirScript.Preprocess.Modules do end) mods ++ [{:defmodule, [], [{:__aliases__, [], [:ElixirScript, :Temp]}, [do: { :__block__, [], no_mods }]]}] - ({:defprotocol, _, [{:__aliases__, _, protocol}| _ ] }) = x when not protocol in @standard_lib_protocols -> + ({:defprotocol, _, _ }) = x -> x - ({:defimpl, _, [ {:__aliases__, _, protocol} | _] }) = x when not protocol in @standard_lib_protocols -> + ({:defimpl, _, _}) = x -> x ({:defmodule, _, _}) = x -> x @@ -49,24 +41,18 @@ defmodule ElixirScript.Preprocess.Modules do ElixirScript.State.add_protocol(ElixirScript.Module.quoted_to_name(the_alias), {:__block__, [], [spec]}) end - def do_get_info({:defimpl, _, [ {:__aliases__, _, protocol} = the_alias, [for: type], [do: {:__block__, context, spec}] ]}) when not protocol in @standard_lib_protocols do + def do_get_info({:defimpl, _, [ {:__aliases__, _, _} = the_alias, [for: type], [do: {:__block__, context, spec}] ]}) do ElixirScript.State.add_protocol_impl(ElixirScript.Module.quoted_to_name(the_alias), type, {:__block__, context, spec}) end - def do_get_info({:defimpl, _, [ {:__aliases__, _, protocol} = the_alias, [for: type], [do: spec] ]}) when not protocol in @standard_lib_protocols do + def do_get_info({:defimpl, _, [ {:__aliases__, _, _} = the_alias, [for: type], [do: spec] ]}) do ElixirScript.State.add_protocol_impl(ElixirScript.Module.quoted_to_name(the_alias), type, {:__block__, [], [spec]}) end def do_get_info({:defmodule, _, [{:__aliases__, _, [:ElixirScript, :Temp]}, [do: body]]} = ast) do - body = case body do - {:__block__, _, _ } -> - Macro.expand(body, State.get().env) - _ -> - body - end - - mod = %ElixirScript.Module{ name: ElixirScript.Temp , body: body } - State.add_module(mod) + body + |> make_module([:ElixirScript, :Temp]) + |> State.add_module ast end @@ -74,33 +60,31 @@ defmodule ElixirScript.Preprocess.Modules do def do_get_info({:defmodule, _, [{:__aliases__, _, module_name_list}, [do: body]]} = ast) do body = make_inner_module_aliases(module_name_list, body) - functions = get_functions_from_module(body) - macros = get_macros_from_module(body) - aliases = get_aliases_from_module(body) - requires = get_requires_from_module(body) - imports = get_imports_from_module(body) - js_imports = get_js_imports_from_module(body) + make_module(body, module_name_list) + |> State.add_module + ast + end + + def do_get_info(ast) do + ast + end + + defp make_module(body, module_name_list) do body = case body do {:__block__, _, _ } -> - Macro.expand(body, State.get().env) + Macro.expand(body, State.get().elixir_env) _ -> body end - aliases = Set.union(aliases, requires.aliases) |> Set.union(imports.aliases) - mod = %ElixirScript.Module{ name: ElixirScript.Module.quoted_to_name({:__aliases__, [], module_name_list}) , body: body, - functions: functions, macros: macros, - aliases: aliases, requires: requires.requires, - imports: imports.imports, js_imports: js_imports } - - State.add_module(mod) + %{def: functions, defp: private_functions, defmacro: macros, defmacrop: private_macros } = get_functions_from_module(body) + js_imports = get_js_imports_from_module(body) - ast - end - - def do_get_info(ast) do - ast + %ElixirScript.Module{ name: ElixirScript.Module.quoted_to_name({:__aliases__, [], module_name_list}) , body: body, + functions: functions, private_functions: private_functions, + macros: macros, private_macros: private_macros, + js_imports: js_imports } end defp make_inner_module_aliases(module_name_list, body) do @@ -135,18 +119,10 @@ defmodule ElixirScript.Preprocess.Modules do end defp add_module_to_state(module_name_list, module_name_list2, body2) do - functions = get_functions_from_module(body2) - macros = get_macros_from_module(body2) - aliases = get_aliases_from_module(body2) - requires = get_requires_from_module(body2) - imports = get_imports_from_module(body2) + %{def: functions, defp: private_functions, defmacro: macros, defmacrop: private_macros } = get_functions_from_module(body2) js_imports = get_js_imports_from_module(body2) inner_alias = {:alias, [], [{:__aliases__, [alias: false], module_name_list ++ module_name_list2}]} - {inner_alias_atom, _ } = Code.eval_quoted({:__aliases__, [alias: false], module_name_list ++ module_name_list2}) - - aliases = Set.put(aliases, {inner_alias_atom, inner_alias_atom}) - aliases = Set.union(aliases, requires.aliases) |> Set.union(imports.aliases) module_name = ElixirScript.Module.quoted_to_name({:__aliases__, [], tl(module_name_list) ++ module_name_list2}) State.delete_module_by_name(module_name) @@ -154,8 +130,9 @@ defmodule ElixirScript.Preprocess.Modules do module_name = ElixirScript.Module.quoted_to_name({:__aliases__, [], module_name_list ++ module_name_list2}) mod = %ElixirScript.Module{ name: module_name, body: body2, - functions: functions, macros: macros, aliases: aliases, - requires: requires.requires, js_imports: js_imports } + functions: functions, private_functions: private_functions, + macros: macros, private_macros: private_macros, + js_imports: js_imports } State.add_module(mod) @@ -164,139 +141,63 @@ defmodule ElixirScript.Preprocess.Modules do defp get_functions_from_module({:__block__, _, list}) do - Enum.reduce(list, Keyword.new, fn - ({:def, _, [{:when, _, [{name, _, params} | _guards] }, [do: _body]] }, state) -> - arity = if is_nil(params), do: 0, else: length(params) + Enum.reduce(list, %{ def: Keyword.new, defp: Keyword.new, defmacro: Keyword.new, defmacrop: Keyword.new }, fn + ({type, _, [{:when, _, [{name, _, params} | _guards] }, [do: _body]] }, state) when type in [:def, :defp] and is_atom(params) -> + arity = 0 - unless Enum.member?(Keyword.get_values([], name), arity) do - Keyword.put(state, name, arity); - end + add_function_to_map(state, type, name, arity) - ({:def, _, [{name, _, params}, [do: _body]]}, state) -> - arity = if is_nil(params), do: 0, else: length(params) + ({type, _, [{:when, _, [{name, _, params} | _guards] }, [do: _body]] }, state) when type in [:def, :defp] -> + arity = if is_nil(params), do: 0, else: length(params) - unless Enum.member?(Keyword.get_values([], name), arity) do - Keyword.put(state, name, arity); - end + add_function_to_map(state, type, name, arity) - _, state -> - state + ({type, _, [{name, _, params}, [do: _body]]}, state) when type in [:def, :defp] and is_atom(params) -> + arity = 0 - end) - end + add_function_to_map(state, type, name, arity) - defp get_functions_from_module(_) do - Keyword.new - end - defp get_macros_from_module({:__block__, _, list}) do - Enum.reduce(list, Keyword.new, fn - ({:defmacro, _, [{:when, _, [{name, _, params} | _guards] }, [do: _body]] }, state) -> - arity = length(params) + ({type, _, [{name, _, params}, [do: _body]]}, state) when type in [:def, :defp] -> + arity = if is_nil(params), do: 0, else: length(params) - unless Enum.member?(Keyword.get_values([], name), arity) do - Keyword.put(state, name, arity); - end + add_function_to_map(state, type, name, arity) - ({:defmacro, _, [{name, _, params}, [do: _body]]}, state) -> - arity = length(params) + ({type, _, [{:when, _, [{name, _, params} | _guards] }, [do: _body]] }, state) when type in [:defmacro, :defmacrop] -> + arity = length(params) - unless Enum.member?(Keyword.get_values([], name), arity) do - Keyword.put(state, name, arity); - end + add_function_to_map(state, type, name, arity) - _, state -> - state - end) - end - - defp get_macros_from_module(_) do - Keyword.new - end + ({type, _, [{name, _, params}, [do: _body]]}, state) when type in [:defmacro, :defmacrop] -> + arity = length(params) - - defp get_aliases_from_module({:__block__, _, list}) do - Enum.reduce(list, HashSet.new, fn - ({:alias, _, [name]}, state) -> - {main, _} = Code.eval_quoted(name) - {:__aliases__, _, aliases } = name - {the_alias, _} = Code.eval_quoted({:__aliases__, [alias: false], List.last(aliases) |> List.wrap }) - Set.put(state, {the_alias, main}) - ({:alias, _, [name, [as: the_alias]]}, state) -> - {name, _} = Code.eval_quoted(name) - {the_alias, _} = Code.eval_quoted(the_alias) - - Set.put(state, {the_alias, name}) + add_function_to_map(state, type, name, arity) _, state -> state - end) - end - - defp get_aliases_from_module(_) do - HashSet.new - end - - - defp get_requires_from_module({:__block__, _, list}) do - Enum.reduce(list, %{ requires: HashSet.new, aliases: HashSet.new }, fn - ({:require, _, [name]}, state) -> - {main, _} = Code.eval_quoted(name) - {:__aliases__, _, aliases } = name - {the_alias, _} = Code.eval_quoted({:__aliases__, [alias: false], List.last(aliases) |> List.wrap }) - - %{ state | requires: Set.put(state.requires, main), aliases: Set.put(state.aliases, {the_alias, main}) } - ({:require, _, [name, [as: the_alias]]}, state) -> - {name, _} = Code.eval_quoted(name) - {the_alias, _} = Code.eval_quoted(the_alias) - - %{ state | requires: Set.put(state.requires, name), aliases: Set.put(state.aliases, {the_alias, name}) } - - _, state -> - state end) end - - defp get_requires_from_module(_) do - %{ requires: HashSet.new, aliases: HashSet.new } - end - - - defp get_imports_from_module({:__block__, _, list}) do - Enum.reduce(list, %{ imports: HashSet.new, aliases: HashSet.new }, fn - ({:import, _, [name]}, state) -> - {main, _} = Code.eval_quoted(name) - {:__aliases__, _, aliases } = name - {the_alias, _} = Code.eval_quoted({:__aliases__, [alias: false], List.last(aliases) |> List.wrap }) - - %{ state | imports: Set.put(state.imports, {main, []}), aliases: Set.put(state.aliases, {the_alias, main}) } - - ({:import, _, [name, options]}, state) -> - {main, _} = Code.eval_quoted(name) - {:__aliases__, _, aliases } = name - {the_alias, _} = Code.eval_quoted({:__aliases__, [alias: false], List.last(aliases) |> List.wrap }) - - %{ state | imports: Set.put(state.imports, {main, options}), aliases: Set.put(state.aliases, {the_alias, main}) } - - - _, state -> - state - end) + defp get_functions_from_module(_) do + %{ def: Keyword.new, defp: Keyword.new, defmacro: Keyword.new, defmacrop: Keyword.new } end + defp add_function_to_map(map, type, name, arity) do + list = Map.get(map, type) - defp get_imports_from_module(_) do - %{ imports: HashSet.new, aliases: HashSet.new } + if {name, arity} in list do + map + else + Map.put(map, type, list ++ [{ name, arity }]) + end end - defp get_js_imports_from_module({:__block__, _, list}) do - Enum.reduce(list, HashSet.new, fn + Enum.reduce(list, MapSet.new, fn ({{:., _, [{:__aliases__, _, [:JS]}, :import]}, _, [name, path]}, state) -> {name, _} = Code.eval_quoted(name) - Set.put(state, {name, path}) + MapSet.put(state, {name, path}) _, state -> state @@ -305,6 +206,6 @@ defmodule ElixirScript.Preprocess.Modules do defp get_js_imports_from_module(_) do - HashSet.new + MapSet.new end end diff --git a/lib/elixir_script/preprocess/using.ex b/lib/elixir_script/preprocess/using.ex index 1b1a8317..7d32a8f3 100644 --- a/lib/elixir_script/preprocess/using.ex +++ b/lib/elixir_script/preprocess/using.ex @@ -1,24 +1,24 @@ defmodule ElixirScript.Preprocess.Using do @moduledoc false - def process(ast, env) do + def process(ast) do Macro.prewalk(ast, fn(x) -> - process_using(x, env) + process_using(x) end) end - def process_using({:use, _, _} = ast, env) do + def process_using({:use, _, _} = ast) do ast - |> Macro.expand(env) - |> expand__using__(env) + |> Macro.expand(ElixirScript.State.get().elixir_env) + |> expand__using__ end - def process_using(ast, _) do + def process_using(ast) do ast end - defp expand__using__({:__block__, _, [{:require, _, _}, {{:., _, [_, :__using__]}, _, _} = using_ast]}, env) do - Macro.expand_once(using_ast, env) + defp expand__using__({:__block__, _, [{:require, _, _}, {{:., _, [_, :__using__]}, _, _} = using_ast]}) do + Macro.expand_once(using_ast, ElixirScript.State.get().elixir_env) end -end \ No newline at end of file +end diff --git a/lib/elixir_script/preprocess/variables.ex b/lib/elixir_script/preprocess/variables.ex deleted file mode 100644 index 55c45180..00000000 --- a/lib/elixir_script/preprocess/variables.ex +++ /dev/null @@ -1,152 +0,0 @@ -defmodule ElixirScript.Preprocess.Variables do - @moduledoc false - - @doc """ - Creates a new variable binding whenever an - identifier is reused. - - ex. - a = 1 - a = 2 - - #becomes - - a0 = 1 - a1 = 2 - """ - def process(ast) do - {new_ast, _ } = Macro.prewalk(ast, %{}, fn(x, acc) -> - process_variables(x, acc) - end) - - new_ast - end - - def process_variables({:::, meta, [{{:., meta1, [Kernel, :to_string]}, meta2, params}, {:binary, meta3, context}]}, state) do - params = Enum.map(params, fn(x) -> - {value, _} = process_variables(x, state) - value - end) - - { {:::, meta, [{{:., meta1, [Kernel, :to_string]}, meta2, params}, {:binary, meta3, context}]}, state } - end - - def process_variables({:=, meta, [{var1, var2}, value]}, state) do - - { value, _ } = process_variables(value, state) - - { [var1, var2], state } = Enum.map_reduce([var1, var2], state, fn(x, current_state) -> - case x do - {variable_name, meta2, context} when not(variable_name in [:%, :{}, :^, :&, :%{}]) -> - {new_variable_name, new_state} = get_new_variable_name(variable_name, current_state) - { {new_variable_name, meta2, context} , new_state } - _ -> - {x, current_state} - end - end) - - { {:=, meta, [{var1, var2}, value]}, state } - end - - def process_variables({:=, meta, [{:{}, meta2, variables}, value]}, state) do - - { value, _ } = process_variables(value, state) - - { variables, state } = Enum.map_reduce(variables, state, fn(x, current_state) -> - case x do - {variable_name, meta3, context} when not(variable_name in [:%, :{}, :^, :&, :_, :%{}]) -> - {new_variable_name, new_state} = get_new_variable_name(variable_name, current_state) - { {new_variable_name, meta3, context} , new_state } - _ -> - {x, current_state} - end - end) - - { {:=, meta, [{:{}, meta2, variables}, value]}, state } - end - - def process_variables({:=, meta, [variables, value]}, state) when is_list(variables) do - - { value, _ } = process_variables(value, state) - - { variables, state } = Enum.map_reduce(variables, state, fn(x, current_state) -> - case x do - {variable_name, meta3, context} when not(variable_name in [:%, :{}, :^, :&, :_, :%{}]) -> - {new_variable_name, new_state} = get_new_variable_name(variable_name, current_state) - { {new_variable_name, meta3, context} , new_state } - _ -> - {x, current_state} - end - end) - - { {:=, meta, [variables, value]}, state } - end - - def process_variables({:=, meta, [{variable_name, meta2, context}, value]}, state) when not(variable_name in [:%, :{}, :^, :&, :., :%{}]) do - { value, _ } = process_variables(value, state) - - {new_variable_name, new_state} = get_new_variable_name(variable_name, state) - { {:=, meta, [{new_variable_name, meta2, context}, value]}, new_state } - end - - def process_variables({:<<>>, meta, params}, state) do - params = Enum.map(params, fn(x) -> - {value, _} = process_variables(x, state) - value - end) - - { {:<<>>, meta, params}, state } - end - - def process_variables({{:., meta, [{:__aliases__, context, module}, function]}, meta2, params}, state) do - params = Enum.map(params, fn(x) -> - {value, _} = process_variables(x, state) - value - end) - - { {{:., meta, [{:__aliases__, context, module}, function]}, meta2, params}, state } - end - - def process_variables({{:., meta, [variable, function]}, meta2, params}, state) do - {variable, _} = process_variables(variable, state) - - params = Enum.map(params, fn(x) -> - {value, _} = process_variables(x, state) - value - end) - - { {{:., meta, [variable, function]}, meta2, params}, state } - end - - def process_variables(variables, state) when is_list(variables) do - variables = Enum.map(variables, fn(x) -> - {value, _} = process_variables(x, state) - value - end) - - { variables, state } - end - - def process_variables({variable_name, meta, context}, state) do - cond do - Map.has_key?(state, variable_name) -> - new_variable_name = String.to_atom("#{variable_name}#{Map.get(state, variable_name)}") - { {new_variable_name, meta, context}, state } - true -> - { {variable_name, meta, context}, state } - end - end - - def process_variables(ast, state) do - { ast, state } - end - - defp get_new_variable_name(variable_name, state) do - current = Map.get(state, variable_name, -1) + 1 - new_variable_name = String.to_atom("#{variable_name}#{current}") - new_state = Map.put(state, variable_name, current) - - { new_variable_name, new_state } - end - -end \ No newline at end of file diff --git a/lib/elixir_script/state.ex b/lib/elixir_script/state.ex index 0f97a6ac..895fc47d 100644 --- a/lib/elixir_script/state.ex +++ b/lib/elixir_script/state.ex @@ -1,9 +1,9 @@ defmodule ElixirScript.State do @moduledoc false - def start_link(root, env \\ __ENV__) do + def start_link(root, elixir_env \\ __ENV__) do Agent.start_link(fn -> - %ElixirScript.Env{root: root, env: env} + %{ root: root, elixir_env: elixir_env, modules: Map.new } end, name: __MODULE__) end @@ -15,51 +15,45 @@ defmodule ElixirScript.State do def add_module(module) do Agent.update(__MODULE__, fn state -> - %{state | modules: Set.put(state.modules, module)} + %{ state | modules: Map.put(state.modules, module.name, module) } end) end def delete_module(module) do Agent.update(__MODULE__, fn state -> - %{state | modules: Set.delete(state.modules, module)} + %{ state | modules: Map.delete(state.modules, module.name ) } end) end def delete_module_by_name(module_name) do Agent.update(__MODULE__, fn state -> - set = state.modules - |> Set.to_list() - |> Enum.filter(fn(x) -> x.name != module_name end) - |> Enum.into(HashSet.new) - - %{state | modules: set } + %{ state | modules: Map.delete(state.modules, module_name ) } end) end def module_listed?(module_name) do Agent.get(__MODULE__, fn state -> - Enum.any?(state.modules, fn(x) -> x.name == module_name end) || - Enum.any?(state.protocols, fn({key, _}) -> key == module_name end) + Map.has_key?(state.modules, module_name) end) end def protocol_listed?(module_name) do Agent.get(__MODULE__, fn state -> - Enum.any?(state.protocols, fn({key, _}) -> key == module_name end) + Map.has_key?(state.modules, module_name) && Map.get(state.modules, module_name).type == :protocol end) end def add_protocol(name, spec) do Agent.update(__MODULE__, fn state -> - proto = Dict.get(state.protocols, name) + proto = do_get_module(state, name) if proto == nil do - proto = %{name: name, spec: spec, impls: HashDict.new} + proto = %ElixirScript.Module{ name: name, spec: spec, impls: HashDict.new, type: :protocol } else - proto = %{proto | spec: spec} + proto = %{proto | spec: spec, type: :protocol } end - %{state | protocols: Dict.put(state.protocols, name, proto)} + %{ state | modules: Map.put(state.modules, name, proto) } end) end @@ -71,15 +65,15 @@ defmodule ElixirScript.State do def add_protocol_impl(protocol, type, impl) do Agent.update(__MODULE__, fn state -> - proto = Dict.get(state.protocols, protocol) + proto = do_get_module(state, protocol) if proto == nil do - proto = %{name: protocol, spec: nil, impls: HashDict.new} + proto = %ElixirScript.Module{ name: protocol, spec: nil, impls: HashDict.new, type: :protocol } end - proto = %{proto | impls: Dict.put(proto.impls, type, impl)} + proto = %{ proto | impls: Dict.put(proto.impls, type, impl), type: :protocol } - %{state | protocols: Dict.put(state.protocols, protocol, proto)} + %{ state | modules: Map.put(state.modules, protocol, proto) } end) end @@ -92,6 +86,10 @@ defmodule ElixirScript.State do do_get_module(state, module) end + def get_module({:__aliases__, _, _} = name) do + state = Agent.get(__MODULE__, &(&1)) + do_get_module(state, ElixirScript.Module.quoted_to_name(name)) + end def get_module(module_name_list) when is_list(module_name_list) do state = Agent.get(__MODULE__, &(&1)) @@ -99,9 +97,8 @@ defmodule ElixirScript.State do end defp do_get_module(state, name) do - Enum.find(Set.to_list(state.modules), fn x -> - x.name == name - end) + name = ElixirScript.Module.get_module_name(name) + Map.get(state.modules, name) end def add_alias(module_name, module_alias) do @@ -109,7 +106,7 @@ defmodule ElixirScript.State do if module do delete_module(module) - module = %{module | aliases: Set.put(module.aliases, {module_alias, module_name}) } + module = %{ module | aliases: MapSet.put(module.aliases, {module_alias, module_name}) } add_module(module) end end @@ -119,7 +116,7 @@ defmodule ElixirScript.State do if module do delete_module(module) - module = %{ module | module_refs: module.module_refs ++ [module_ref] } + module = %{ module | module_refs: Enum.uniq(module.module_refs ++ [module_ref]) } add_module(module) end end @@ -135,49 +132,16 @@ defmodule ElixirScript.State do end end - def process_imports do - Agent.update(__MODULE__, fn state -> - modules = - state.modules - |> Enum.map(fn x -> - imports = - Enum.map(x.imports, fn {y, options} -> - {y, get_imported_functions(state, y, options)} - end) - %{x | imports: imports} - end) - - %{state | modules: Enum.into(modules, HashSet.new)} + def list_modules() do + Agent.get(__MODULE__, fn(x) -> + Map.values(x.modules) end) end - defp get_imported_functions(state, module_name, []) do - module = do_get_module(state, module_name) - ElixirScript.Module.functions(module) ++ ElixirScript.Module.macros(module) - end - - defp get_imported_functions(_, _, [only: list]) do - Keyword.keys(list) - end - - defp get_imported_functions(state, module_name, [only: :functions]) do - module = do_get_module(state, module_name) - ElixirScript.Module.functions(module) - end - - defp get_imported_functions(state, module_name, [only: :macros]) do - module = do_get_module(state, module_name) - ElixirScript.Module.macros(module) - end - - defp get_imported_functions(state, module_name, [except: list]) do - module = do_get_module(state, module_name) - ElixirScript.Module.functions(module) ++ ElixirScript.Module.macros(module) -- Keyword.keys(list) - end - - def list_modules() do + def list_module_names() do Agent.get(__MODULE__, fn(x) -> - Enum.map(x.modules, fn(y) -> y.name end) ++ Enum.map(x.protocols, fn({key, _}) -> key end) + Map.values(x.modules) + |> Enum.map(fn(x) -> x.name end) end) end diff --git a/lib/elixir_script/translator.ex b/lib/elixir_script/translator.ex index f235da69..a8f83ab1 100644 --- a/lib/elixir_script/translator.ex +++ b/lib/elixir_script/translator.ex @@ -3,11 +3,11 @@ defmodule ElixirScript.Translator do Translates the given Elixir AST into JavaScript AST """ alias ElixirScript.Translator.Primitive + alias ElixirScript.Translator.Expression alias ElixirScript.Translator.Assignment alias ElixirScript.Translator.Map alias ElixirScript.Translator.Function alias ElixirScript.Translator.Capture - alias ElixirScript.Translator.Import alias ElixirScript.Translator.Cond alias ElixirScript.Translator.Case alias ElixirScript.Translator.For @@ -17,22 +17,11 @@ defmodule ElixirScript.Translator do alias ElixirScript.Translator.Module alias ElixirScript.Translator.Utils alias ElixirScript.Translator.Bitstring - alias ElixirScript.Translator.Receive alias ElixirScript.Translator.Quote alias ElixirScript.Translator.Utils - alias ElixirScript.Translator.Protocol - alias ElixirScript.Translator.Kernel, as: KernelLib - alias ElixirScript.Translator.Logger alias ElixirScript.Translator.JS, as: JSLib alias ESTree.Tools.Builder, as: JS - @standard_lib_protocols [ - [:Enumerable], - [:Inspect], - [:String, :Chars], - [:List, :Chars], - [:Collectable] - ] @doc """ @@ -42,12 +31,17 @@ defmodule ElixirScript.Translator do do_translate(ast, env) end - defp do_translate(ast, _) when is_number(ast) or is_binary(ast) or is_boolean(ast) or is_nil(ast) do - Primitive.make_literal(ast) + def translate!(ast, env) do + { js_ast, _ } = translate(ast, env) + js_ast end - defp do_translate(ast, _) when is_atom(ast) do - Primitive.make_atom(ast) + defp do_translate(ast, env) when is_number(ast) or is_binary(ast) or is_boolean(ast) or is_nil(ast) do + { Primitive.make_literal(ast), env } + end + + defp do_translate(ast, env) when is_atom(ast) do + { Primitive.make_atom(ast), env } end defp do_translate(ast, env) when is_list(ast) do @@ -58,18 +52,69 @@ defmodule ElixirScript.Translator do Primitive.make_tuple({one, two}, env) end - defp do_translate({:&, [], [number]}, _) when is_number(number) do - Primitive.make_identifier(String.to_atom("__#{number}")) + defp do_translate({operator, _, [value]}, env) when operator in [:-, :!, :+] do + Expression.make_unary_expression(operator, value, env) + end + + defp do_translate({:not, _, [value]}, env) do + Expression.make_unary_expression(:!, value, env) + end + + defp do_translate({operator, _, [left, right]}, env) when operator in [:+, :-, :/, :*, :==, :!=, :&&, :||, :>, :<, :>=, :<=, :===, :!==] do + Expression.make_binary_expression(operator, left, right, env) + end + + defp do_translate({:and, _, [left, right]}, env) do + Expression.make_binary_expression(:&&, left, right, env) + end + + defp do_translate({:or, _, [left, right]}, env) do + Expression.make_binary_expression(:||, left, right, env) + end + + defp do_translate({:div, _, [left, right]}, env) do + Expression.make_binary_expression(:/, left, right, env) + end + + defp do_translate({:rem, _, [left, right]}, env) do + Expression.make_binary_expression(:%, left, right, env) + end + + defp do_translate({:throw, _, [params]}, env) do + { result, env } = translate(params, env) + { JS.throw_statement(result), env } + end + + defp do_translate({:<>, context, [left, right]}, env) do + translate({:+, context, [left, right]}, env) + end + + defp do_translate({:++, _, [left, right]}, env) do + quoted = quote do + Elixir.Core.concat_lists(unquote(left),unquote(right)) + end + + translate(quoted, env) + end + + defp do_translate({:.., _, [first, last]}, env) do + quoted_range = quote do: Range.(unquote(first), unquote(last)) + + translate(quoted_range, env) + end + + defp do_translate({:&, _, [number]}, env) when is_number(number) do + { Primitive.make_identifier(String.to_atom("__#{number}")), env } end - defp do_translate({:&, _, [{:/, _, [{{:., _, [{:__aliases__, _, module_name}, function_name]}, _, []}, arity]}]}, env) do + defp do_translate({:&, _, [{:/, _, [{{:., _, [module_name, function_name]}, _, []}, arity]}]}, env) do function_name = Utils.filter_name(function_name) - Capture.make_capture(List.last(module_name), function_name, arity, env) + { Capture.make_capture(module_name, function_name, arity, env), env } end defp do_translate({:&, _, [{:/, _, [{function_name, _, _}, arity]}]}, env) do function_name = Utils.filter_name(function_name) - Capture.make_capture(function_name, arity, env) + { Capture.make_capture(function_name, arity, env), env } end defp do_translate({:&, _, body}, env) do @@ -77,31 +122,31 @@ defmodule ElixirScript.Translator do Function.make_anonymous_function([{:->, [], [params, body]}], env) end - defp do_translate({:@, _, [{name, _, _}]}, _) + defp do_translate({:@, _, [{name, _, _}]}, env) when name in [:doc, :moduledoc, :type, :typep, :spec, :opaque, :callback, :macrocallback] do - %ElixirScript.Translator.Group{} + { %ElixirScript.Translator.Group{}, env } end defp do_translate({:@, _, [{name, _, [value]}]}, env) do name = Utils.filter_name(name) - Module.make_attribute(name, value, env) + { Module.make_attribute(name, value, env), env } end - defp do_translate({:@, _, [{name, _, _}]}, _) do + defp do_translate({:@, _, [{name, _, _}]}, env) do name = Utils.filter_name(name) - Primitive.make_identifier(name) + { Primitive.make_identifier(name), env } end defp do_translate({:%, _, [alias_info, data]}, env) do - Struct.new_struct(alias_info, data, env) + { Struct.new_struct(alias_info, data, env), env } end defp do_translate({:%{}, _, [{:|, _, [map, data]}]}, env) do - Map.make_map_update(map, data, env); + { Map.make_map_update(map, data, env), env } end defp do_translate({:%{}, _, properties}, env) do - Map.make_object(properties, env) + { Map.make_object(properties, env), env } end defp do_translate({:<<>>, _, elements}, env) do @@ -124,12 +169,8 @@ defmodule ElixirScript.Translator do end end - defp do_translate({{:., _, [{:__aliases__, _, [:Logger]}, function_name]}, _, params }, env) do - Logger.make_logger(function_name, params, env) - end - defp do_translate({{:., _, [Access, :get]}, _, [target, property]}, env) do - Map.make_get_property(target, property, env) + { Map.make_get_property(target, property, env), env } end defp do_translate({{:., _, [function_name]}, _, params}, env) do @@ -137,9 +178,10 @@ defmodule ElixirScript.Translator do end defp do_translate({:., _, [module_name, function_name]} = ast, env) do - expanded_ast = Macro.expand(ast, env) + expanded_ast = Macro.expand(ast, ElixirScript.State.get().elixir_env) if expanded_ast == ast do + module_name = create_module_name(module_name, env) Function.make_function_or_property_call(module_name, function_name, env) else translate(expanded_ast, env) @@ -147,100 +189,146 @@ defmodule ElixirScript.Translator do end defp do_translate({{:., _, [module_name, function_name]}, _, [] } = ast, env) do - expanded_ast = Macro.expand(ast, env) + expanded_ast = Macro.expand(ast, ElixirScript.State.get().elixir_env) if expanded_ast == ast do + module_name = create_module_name(module_name, env) Function.make_function_or_property_call(module_name, function_name, env) else translate(expanded_ast, env) end end - defp do_translate({{:., _, [{:__aliases__, _, module_name}]}, _, params} = ast, env) do - expanded_ast = Macro.expand(ast, env) + defp do_translate({{:., _, [{:__aliases__, _, _} = module_name]}, _, params} = ast, env) do + expanded_ast = Macro.expand(ast, ElixirScript.State.get().elixir_env) + if expanded_ast == ast do - Function.make_function_call(hd(module_name), params, env) + module_name = create_module_name(module_name, env) + Function.make_function_call(module_name, params, env) else translate(expanded_ast, env) end end + defp do_translate({{:., _, [{:__aliases__, _, [:JS]}, function_name]}, _, params }, env) do + JSLib.translate_js_function(function_name, params, env) + end + + defp do_translate({{:., _, [module_name, function_name]}, _, params } = ast, env) do - case module_name do - Kernel -> - KernelLib.translate_kernel_function(function_name, params, env) - {:__aliases__, _, [:JS]} -> - JSLib.translate_js_function(function_name, params, env) - _ -> - expanded_ast = Macro.expand(ast, env) - if expanded_ast == ast do - Function.make_function_call(module_name, function_name, params, env) - else - translate(expanded_ast, env) - end + expanded_ast = Macro.expand(ast, ElixirScript.State.get().elixir_env) + + if expanded_ast == ast do + module_name = create_module_name(module_name, env) + Function.make_function_call(module_name, function_name, params, env) + else + translate(expanded_ast, env) end end - defp do_translate({:_, _, _}, _env) do - Primitive.make_identifier(:undefined) + defp do_translate({:_, _, _}, env) do + { Primitive.make_identifier(:undefined), env } end - defp do_translate({:__aliases__, _, aliases}, _) do - Primitive.make_identifier({:__aliases__, [], aliases}) + defp do_translate({:__aliases__, _, aliases}, env) do + { Primitive.make_identifier({:__aliases__, [], aliases}), env } + end + + defp do_translate({:__MODULE__, _, _ }, env) do + translate(env.module, env) end defp do_translate({:__block__, _, expressions }, env) do Block.make_block(expressions, env) end - defp do_translate({:__DIR__, _, _}, _) do - JS.call_expression( - JS.member_expression( - Primitive.special_forms(), - JS.identifier(:__DIR__) - ), - [] - ) + defp do_translate({:__DIR__, _, _}, env) do + case env.file do + nil -> + { JS.identifier(:null), env } + filepath -> + { JS.literal(Path.dirname(filepath)), env } + end end defp do_translate({:try, _, [ blocks ]}, env) do Try.make_try(blocks, env) end - defp do_translate({:receive, _, [expressions] }, env) do - Receive.make_receive(expressions, env); + defp do_translate({:receive, _, _ }, _ ) do + raise ElixirScript.UnsupportedError, "receive" end - defp do_translate({:super, _, _expressions }, _) do + defp do_translate({:super, _, _expressions }, _ ) do raise ElixirScript.UnsupportedError, "super" end - defp do_translate({:__CALLER__, _, _expressions }, _) do - raise ElixirScript.UnsupportedError, "__CALLER__" + defp do_translate({:__CALLER__, _, _expressions }, env) do + env_to_translate = %{ env.caller | vars: Enum.map(env.caller.vars, fn({key, _}) -> {key, nil} end), caller: nil } + + quoted = Macro.escape(env_to_translate) + translate(quoted, env) end - defp do_translate({:__ENV__, _, _expressions }, _) do - raise ElixirScript.UnsupportedError, "__ENV__" + defp do_translate({:__ENV__, _, _expressions }, env) do + env_to_translate = %{ env | vars: Enum.map(env.vars, fn({key, _}) -> {key, nil} end), caller: nil } + + quoted = Macro.escape(env_to_translate) + translate(quoted, env) end defp do_translate({:quote, _, [[do: expr]]}, env) do - Quote.make_quote([], expr, env) + { Quote.make_quote([], expr, env), env } end defp do_translate({:quote, _, [opts, [do: expr]]}, env) do - Quote.make_quote(opts, expr, env) + { Quote.make_quote(opts, expr, env), env } + end + + defp do_translate({:import, _, [{:__aliases__, _, _} = module_name]}, env) do + env = ElixirScript.Env.add_import(env, module_name) + { %ElixirScript.Translator.Group{}, env } end - defp do_translate({:import, _, _}, _) do - %ElixirScript.Translator.Group{} + defp do_translate({:import, _, [{:__aliases__, _, _} = module_name, options]}, env) do + module_name = ElixirScript.Module.quoted_to_name(module_name) + + env = ElixirScript.Env.add_import(env, module_name, options) + + { %ElixirScript.Translator.Group{}, env } end - defp do_translate({:alias, _, _}, _) do - %ElixirScript.Translator.Group{} + defp do_translate({:alias, _, [{:__aliases__, _, _} = module_name] }, env) do + {_, _, name} = module_name + name = [List.last(name)] + + module_name = ElixirScript.Module.quoted_to_name(module_name) + alias_name = ElixirScript.Module.quoted_to_name({:__aliases__, [], name }) + + env = ElixirScript.Env.add_alias(env, module_name, alias_name) + { %ElixirScript.Translator.Group{}, env } end - defp do_translate({:require, _, _}, _) do - %ElixirScript.Translator.Group{} + defp do_translate({:alias, _, [{:__aliases__, _, _} = module_name, [as: {:__aliases__, _, _} = alias_name]]}, env) do + module_name = ElixirScript.Module.quoted_to_name(module_name) + alias_name = ElixirScript.Module.quoted_to_name(alias_name) + + env = ElixirScript.Env.add_alias(env, module_name, alias_name) + { %ElixirScript.Translator.Group{}, env } + end + + defp do_translate({:require, _, [{:__aliases__, _, _} = module_name] }, env) do + module_name = ElixirScript.Module.quoted_to_name(module_name) + env = ElixirScript.Env.add_require(env, module_name) + { %ElixirScript.Translator.Group{}, env } + end + + defp do_translate({:require, _, [{:__aliases__, _, _} = module_name, [as: {:__aliases__, _, _} = alias_name]]}, env) do + module_name = ElixirScript.Module.quoted_to_name(module_name) + alias_name = ElixirScript.Module.quoted_to_name(alias_name) + + env = ElixirScript.Env.add_require(env, module_name, alias_name) + { %ElixirScript.Translator.Group{}, env } end defp do_translate({:case, _, [condition, [do: clauses]]}, env) do @@ -256,6 +344,7 @@ defmodule ElixirScript.Translator do end defp do_translate({:fn, _, clauses}, env) do + env = ElixirScript.Env.function_env(env, nil) Function.make_anonymous_function(clauses, env) end @@ -271,70 +360,127 @@ defmodule ElixirScript.Translator do Function.process_function(Utils.filter_name(name), [ast], env) end + defp do_translate({function, _, [{name, _, params}, [do: _body]]} = ast, env) when function in [:def, :defp] and is_atom(params) do + Function.process_function(Utils.filter_name(name), [ast], env) + end + defp do_translate({function, _, [{name, _, _params}, [do: _body]]} = ast, env) when function in [:def, :defp] do Function.process_function(Utils.filter_name(name), [ast], env) end defp do_translate({:defstruct, _, attributes}, env) do - Struct.make_defstruct(attributes, env) + { Struct.make_defstruct(attributes, env), env } end defp do_translate({:defexception, _, attributes}, env) do - Struct.make_defexception(attributes, env) + { Struct.make_defexception(attributes, env), env } end defp do_translate({:defmodule, _, [{:__aliases__, _, module_name_list}, [do: body]]}, env) do - Module.make_module(module_name_list, body, env) + { Module.make_module(module_name_list, body, env), env } end - defp do_translate({:defprotocol, _, _}, _) do - %ElixirScript.Translator.Group{} + defp do_translate({:defprotocol, _, _}, env) do + { %ElixirScript.Translator.Group{}, env } end - defp do_translate({:defimpl, _, [ {:__aliases__, _, protocol}, [for: type], [do: {:__block__, context, spec}] ]}, env) when protocol in @standard_lib_protocols do - Protocol.make_standard_lib_impl({:__aliases__, [], [:Elixir] ++ protocol}, type, {:__block__, context, spec}, env) + defp do_translate({:defmacro, _, _}, env) do + { %ElixirScript.Translator.Group{}, env } end - defp do_translate({:defimpl, _, [ {:__aliases__, _, protocol}, [for: type], [do: spec] ]}, env) when protocol in @standard_lib_protocols do - Protocol.make_standard_lib_impl({:__aliases__, [], [:Elixir] ++ protocol}, type, {:__block__, [], [spec]}, env) + defp do_translate({:defmacrop, _, _}, env) do + { %ElixirScript.Translator.Group{}, env } end - defp do_translate({:defimpl, _, _}, _) do - %ElixirScript.Translator.Group{} + defp do_translate({:defimpl, _, _}, env) do + { %ElixirScript.Translator.Group{}, env } end defp do_translate({:|, _, [item, list]}, env) do quoted = quote do - List.prepend(unquote(list), unquote(item)) + Elixir.Core.prepend_to_list(unquote(list), unquote(item)) end translate(quoted, env) end + defp do_translate({:raise, _, [alias_info, attributes]}, env) do + js_ast = JS.throw_statement( + Struct.new_struct(alias_info, {:%{}, [], attributes }, env) + ) + + { js_ast, env } + end + + defp do_translate({:raise, _, [message]}, env) do + js_ast = JS.throw_statement( + JS.object_expression( + [ + Map.make_property(translate!(:__struct__, env), translate!(:RuntimeError, env)), + Map.make_property(translate!(:__exception__, env), translate!(true, env)), + Map.make_property(translate!(:message, env), JS.literal(message)) + ] + ) + ) + + { js_ast, env } + end + defp do_translate({name, _, params} = ast, env) when is_list(params) do - if KernelLib.is_defined_in_kernel(name, length(params)) do - KernelLib.translate_kernel_function(name, params, env) - else - expanded_ast = Macro.expand(ast, env) - if expanded_ast == ast do - module = ElixirScript.State.get_module(Process.get(:current_module)) - imported_module = ElixirScript.Module.imported?(module, name) - if imported_module do - imported_module = ElixirScript.State.get_module(imported_module) - Function.make_function_call(ElixirScript.Module.name_to_quoted(imported_module.name) , name, params, env) - else - Function.make_function_call(name, params, env) + + expanded_ast = Macro.expand(ast, ElixirScript.State.get().elixir_env) + + if expanded_ast == ast do + name_arity = {name, length(params)} + module = ElixirScript.State.get_module(env.module) + + cond do + name_arity in module.functions or name_arity in module.private_functions -> + Function.make_function_call(name, params, env) + ElixirScript.Env.find_module(env, name_arity) -> + imported_module_name = ElixirScript.Env.find_module(env, name_arity) + Function.make_function_call(imported_module_name, name, params, env) + true -> + Function.make_function_call(name, params, env) end + else translate(expanded_ast, env) end + end + + defp do_translate({ name, _, params }, env) when is_atom(params) do + cond do + ElixirScript.Env.has_var?(env, name) -> + name = Utils.filter_name(name) + { Primitive.make_identifier(name), env } + ElixirScript.Module.has_function?(env.module, {name, 0}) -> + Function.make_function_call(name, [], env) + ElixirScript.Env.find_module(env, {name, 0}) -> + imported_module_name = ElixirScript.Env.find_module(env, {name, 0}) + Function.make_function_call(imported_module_name, name, params, env) + true -> + name = Utils.filter_name(name) + { Primitive.make_identifier(name), env } end end - defp do_translate({ name, _, _ }, _) do - name = Utils.filter_name(name) - Primitive.make_identifier(name) + + defp create_module_name(module_name, env) do + case module_name do + {:__aliases__, _, _} -> + candiate_module_name = ElixirScript.Module.quoted_to_name(module_name) + |> ElixirScript.Module.get_module_name + + if ElixirScript.Env.get_module_name(env, candiate_module_name) in ElixirScript.State.list_module_names() do + ElixirScript.Env.get_module_name(env, candiate_module_name) + else + module_name + end + _ -> + module_name + end end end diff --git a/lib/elixir_script/translator/assignment.ex b/lib/elixir_script/translator/assignment.ex index 455a9a21..d5f671aa 100644 --- a/lib/elixir_script/translator/assignment.ex +++ b/lib/elixir_script/translator/assignment.ex @@ -6,7 +6,9 @@ defmodule ElixirScript.Translator.Assignment do alias ElixirScript.PatternMatching.Match def make_assignment(left, right, env) do - { patterns, params } = Match.build_match([left], env) + { right_ast, env } = Translator.translate(right, env) + + { patterns, params, env } = Match.process_match([left], env) declarator = JS.variable_declarator( JS.array_pattern(params), @@ -21,13 +23,13 @@ defmodule ElixirScript.Translator.Assignment do ), JS.identifier("match") ), - [hd(patterns), Translator.translate(right, env)] + [hd(patterns), right_ast] ) ) array_pattern = JS.variable_declaration([declarator], :let) - case left do + js_ast = case left do list when is_list(list) -> make_ref(array_pattern, params, "list") {_left1, _left2} -> @@ -37,6 +39,8 @@ defmodule ElixirScript.Translator.Assignment do _ -> array_pattern end + + { js_ast, env } end defp make_ref(array_pattern, params, type) do diff --git a/lib/elixir_script/translator/bitstring.ex b/lib/elixir_script/translator/bitstring.ex index 1b42cc7a..eb32ffdd 100644 --- a/lib/elixir_script/translator/bitstring.ex +++ b/lib/elixir_script/translator/bitstring.ex @@ -6,46 +6,49 @@ defmodule ElixirScript.Translator.Bitstring do def make_bitstring(elements, env) do - JS.call_expression( + js_ast = JS.call_expression( JS.member_expression( Primitive.special_forms(), JS.identifier("bitstring") ), Enum.map(elements, &make_bitstring_element(&1, env)) ) + + { js_ast, env } end defp make_bitstring_element(element, env) when is_number(element) do - do_make_bitstring_element({:integer, Translator.translate(element, env)}) + do_make_bitstring_element({:integer, Translator.translate!(element, env)}) end defp make_bitstring_element(element, env) when is_binary(element) do - do_make_bitstring_element({:binary, Translator.translate(element, env)}) + do_make_bitstring_element({:binary, Translator.translate!(element, env)}) end defp make_bitstring_element({:<<>>, [], elements}, env) do - make_bitstring(elements, env) + {ast, _} = make_bitstring(elements, env) + ast end defp make_bitstring_element({:::, _, [element, {type, _, _}]}, env) when type in [:integer, :float, :bitstring, :bits, :binary, :bytes, :utf8, :utf16, :utf32] do - do_make_bitstring_element({type, Translator.translate(element, env)}) + do_make_bitstring_element({type, Translator.translate!(element, env)}) end defp make_bitstring_element({:::, _, [element, {type, _, params}]}, env) when type in [:size, :unit] do - do_make_bitstring_element({type, Translator.translate(element, env), Enum.map(params, &Translator.translate(&1, env))}) + do_make_bitstring_element({type, Translator.translate!(element, env), Enum.map(params, &Translator.translate!(&1, env))}) end defp make_bitstring_element({:::, _, [element, {:*, _, [size, unit]}]}, env) do - size_ast = do_make_bitstring_element({:size, Translator.translate(element, env), [Translator.translate(size, env)]}) - do_make_bitstring_element({:unit, size_ast, [Translator.translate(unit, env)]}) + size_ast = do_make_bitstring_element({:size, Translator.translate!(element, env), [Translator.translate!(size, env)]}) + do_make_bitstring_element({:unit, size_ast, [Translator.translate!(unit, env)]}) end defp make_bitstring_element({:::, _, [element, {:-, _, types}]}, env) do - handle_type_adjectives({:-, [], types}, Translator.translate(element, env), env) + handle_type_adjectives({:-, [], types}, Translator.translate!(element, env), env) end defp make_bitstring_element({:::, _, [element, size]}, env) do - do_make_bitstring_element({:size, Translator.translate(element, env), [Translator.translate(size, env)]}) + do_make_bitstring_element({:size, Translator.translate!(element, env), [Translator.translate!(size, env)]}) end defp handle_type_adjectives({:-, _, types}, ast, env) do @@ -54,10 +57,10 @@ defmodule ElixirScript.Translator.Bitstring do {:-, _, sub_types} -> handle_type_adjectives({:-, [], sub_types}, current_ast, env) {:*, _, [size, unit]} -> - size_ast = do_make_bitstring_element({:size, current_ast, [Translator.translate(size, env)]}) - do_make_bitstring_element({:unit, size_ast, [Translator.translate(unit, env)]}) + size_ast = do_make_bitstring_element({:size, current_ast, [Translator.translate!(size, env)]}) + do_make_bitstring_element({:unit, size_ast, [Translator.translate!(unit, env)]}) {the_type, _, params} when is_list(params) -> - do_make_bitstring_element({the_type, current_ast, Enum.map(params, &Translator.translate(&1, env))}) + do_make_bitstring_element({the_type, current_ast, Enum.map(params, &Translator.translate!(&1, env))}) {the_type, _, _} -> do_make_bitstring_element({the_type, current_ast}) end @@ -102,20 +105,20 @@ defmodule ElixirScript.Translator.Bitstring do translated_elements = Enum.map(elements, fn(x)-> case x do elem when is_binary(elem) -> - Translator.translate(elem, env) + Translator.translate!(elem, env) {:::, _, data} -> - Translator.translate(hd(data), env) + Translator.translate!(hd(data), env) end end) - do_make_interpolated_string(tl(translated_elements), hd(translated_elements), env) + { do_make_interpolated_string(tl(translated_elements), hd(translated_elements), env), env } end - def do_make_interpolated_string([], ast, _) do + defp do_make_interpolated_string([], ast, _) do ast end - def do_make_interpolated_string(elements, ast, env) do + defp do_make_interpolated_string(elements, ast, env) do JS.binary_expression( :+, ast, diff --git a/lib/elixir_script/translator/block.ex b/lib/elixir_script/translator/block.ex index 5bd958f9..2173e1ae 100644 --- a/lib/elixir_script/translator/block.ex +++ b/lib/elixir_script/translator/block.ex @@ -4,7 +4,11 @@ defmodule ElixirScript.Translator.Block do alias ElixirScript.Translator def make_block(expressions, env) do - Builder.block_statement(Enum.map(expressions, &Translator.translate(&1, env))) + { list, env } = Enum.map_reduce(expressions, env, fn(x, updated_env) -> + Translator.translate(x, updated_env) + end) + + { Builder.block_statement(list), env } end -end \ No newline at end of file +end diff --git a/lib/elixir_script/translator/capture.ex b/lib/elixir_script/translator/capture.ex index 68cfc72c..07d631c1 100644 --- a/lib/elixir_script/translator/capture.ex +++ b/lib/elixir_script/translator/capture.ex @@ -3,53 +3,54 @@ defmodule ElixirScript.Translator.Capture do alias ESTree.Tools.Builder, as: JS alias ElixirScript.PatternMatching.Match - alias ElixirScript.Translator.Utils alias ElixirScript.Translator.Function def make_capture(function_name, arity, env) do - params = Enum.map(1..arity, fn(x) -> {String.to_atom("__#{x}"), [], ElixirScript.Translator.Capture} end) - - { patterns, params } = Match.build_match(params, env) + { patterns, params, _ } = process_params(arity, env) body = JS.block_statement([ - JS.return_statement( - JS.call_expression( - JS.identifier(function_name), - params - ) - ) - ]) - - - Function.make_defmatch([ - Function.do_make_function_clause(patterns, params, body) + JS.return_statement( + JS.call_expression( + JS.identifier(function_name), + params + ) + ) ]) - end + + make_capture_function(patterns, params, body) + end def make_capture(module_name, function_name, arity, env) do - params = Enum.map(1..arity, fn(x) -> {String.to_atom("__#{x}"), [], ElixirScript.Translator.Capture} end) + arity_params = Enum.map(1..arity, fn(x) -> {String.to_atom("__#{x}"), [], ElixirScript.Translator.Capture} end) + + { patterns, params, env } = process_params(arity, env) + + { _, _, name } = module_name - if Function.module_in_standard_libs?(module_name) do - module_name = [:Elixir, module_name] + if name == [:Kernel] or name == [Elixir, :Kernel] do + name = [:ElixirScript, :Kernel] end - { patterns, params } = Match.build_match(params, env) + { func, _ } = Function.make_function_call({:__aliases__, [], name }, function_name, arity_params, env) body = JS.block_statement([ JS.return_statement( - JS.call_expression( - Utils.make_member_expression(module_name, function_name, env), - params - ) + func ) ]) + make_capture_function(patterns, params, body) + end + + defp process_params(arity, env) do + params = Enum.map(1..arity, fn(x) -> {String.to_atom("__#{x}"), [], ElixirScript.Translator.Capture} end) + Match.process_match(params, env) + end + defp make_capture_function(patterns, params, body) do Function.make_defmatch([ - Function.do_make_function_clause(patterns, params, body) + Function.make_function_clause(patterns, params, body, nil) ]) - - end def find_value_placeholders(ast) do @@ -64,4 +65,4 @@ defmodule ElixirScript.Translator.Capture do [] end end -end \ No newline at end of file +end diff --git a/lib/elixir_script/translator/case.ex b/lib/elixir_script/translator/case.ex index befef37d..5d1215e3 100644 --- a/lib/elixir_script/translator/case.ex +++ b/lib/elixir_script/translator/case.ex @@ -3,14 +3,15 @@ defmodule ElixirScript.Translator.Case do alias ESTree.Tools.Builder, as: JS alias ElixirScript.Translator alias ElixirScript.Translator.Function - + def make_case(condition, clauses, env) do - JS.call_expression( - JS.member_expression( - Function.make_anonymous_function(clauses, env), - JS.identifier("call") - ), - [JS.identifier(:this), Translator.translate(condition, env)] + { func, env } = Function.make_anonymous_function(clauses, env) + + js_ast = JS.call_expression( + JS.member_expression( func, JS.identifier("call")), + [JS.identifier(:this), Translator.translate!(condition, env)] ) + + { js_ast, env } end -end \ No newline at end of file +end diff --git a/lib/elixir_script/translator/cond.ex b/lib/elixir_script/translator/cond.ex index 0a3c2f79..a9959972 100644 --- a/lib/elixir_script/translator/cond.ex +++ b/lib/elixir_script/translator/cond.ex @@ -7,20 +7,24 @@ defmodule ElixirScript.Translator.Cond do alias ElixirScript.Translator.Function def make_cond(clauses, env) do - JS.call_expression( + js_ast = JS.call_expression( JS.member_expression( Primitive.special_forms(), JS.identifier("cond") ), process_cond(clauses, env) ) + + { js_ast, env } end defp process_cond(clauses, env) do Enum.map(clauses, fn({:->, _, [clause, clause_body]}) -> - translated_body = Function.prepare_function_body(clause_body, env) |> JS.block_statement + { translated_body, env } = Function.prepare_function_body(clause_body, env) + + translated_body = JS.block_statement(translated_body) function = JS.function_expression([], [], translated_body) - translated_clause = Translator.translate(hd(clause), env) + translated_clause = Translator.translate!(hd(clause), env) Primitive.make_list_no_translate([translated_clause, function]) diff --git a/lib/elixir_script/translator/expression.ex b/lib/elixir_script/translator/expression.ex index e3341266..583e52a4 100644 --- a/lib/elixir_script/translator/expression.ex +++ b/lib/elixir_script/translator/expression.ex @@ -4,11 +4,15 @@ defmodule ElixirScript.Translator.Expression do alias ElixirScript.Translator def make_unary_expression(operator, expr, env) do - Builder.unary_expression(operator, true, Translator.translate(expr, env)) + { js_ast, env } = Translator.translate(expr, env) + { Builder.unary_expression(operator, true, js_ast), env } end def make_binary_expression(operator, left, right, env) do - Builder.binary_expression(operator, Translator.translate(left, env), Translator.translate(right, env)) + { left, _ } = Translator.translate(left, env) + { right, _ } = Translator.translate(right, env) + + { Builder.binary_expression(operator, left, right), env } end -end \ No newline at end of file +end diff --git a/lib/elixir_script/translator/for.ex b/lib/elixir_script/translator/for.ex index 65874561..02b50a29 100644 --- a/lib/elixir_script/translator/for.ex +++ b/lib/elixir_script/translator/for.ex @@ -15,51 +15,52 @@ defmodule ElixirScript.Translator.For do filter = args.filter || JS.function_expression([], [], JS.block_statement([JS.return_statement(JS.identifier("true"))])) fun = args.fun - JS.call_expression( + js_ast = JS.call_expression( JS.member_expression( Primitive.special_forms(), JS.identifier("_for") ), [collections, fun, filter, into] ) + + { js_ast, env } end defp handle_args(generators, env) do Enum.reduce(generators, %{collections: [], args: [], filter: nil, fun: nil, into: nil}, fn ({:<-, [], [identifier, enum]}, state) -> - { patterns, params } = Match.build_match([identifier], env) + { patterns, params, env } = Match.process_match([identifier], env) - list = Primitive.make_list_no_translate([hd(patterns), Translator.translate(enum, env)]) + list = Primitive.make_list_no_translate([hd(patterns), Translator.translate!(enum, env)]) %{state | collections: state.collections ++ [list], args: state.args ++ params } ([into: expression], state) -> %{ state | into: Translator.translate(expression, env) } + ([into: expression, do: expression2], state) -> - fun = JS.function_expression( - state.args, - [], - Function.make_function_body(expression2, env) - ) + fun = create_function_expression(expression2, env, state) - %{ state | into: Translator.translate(expression, env), fun: fun } + %{ state | into: Translator.translate!(expression, env), fun: fun } ([do: expression], state) -> - - fun = JS.function_expression( - state.args, - [], - Function.make_function_body(expression, env) - ) + fun = create_function_expression(expression, env, state) %{ state | fun: fun } (filter, state) -> - fun = JS.function_expression( - state.args, - [], - Function.make_function_body(filter, env) - ) + fun = create_function_expression(filter, env, state) %{ state | filter: fun } end) end + + + defp create_function_expression(ast, env, state) do + { ast, _ } = Function.make_function_body(ast, env) + + JS.function_expression( + state.args, + [], + ast + ) + end end diff --git a/lib/elixir_script/translator/function.ex b/lib/elixir_script/translator/function.ex index 8baf5863..92d1babe 100644 --- a/lib/elixir_script/translator/function.ex +++ b/lib/elixir_script/translator/function.ex @@ -4,7 +4,6 @@ defmodule ElixirScript.Translator.Function do alias ElixirScript.Translator alias ElixirScript.Translator.Utils alias ElixirScript.PatternMatching.Match - alias ElixirScript.Preprocess.Variables @patterns JS.member_expression( JS.member_expression( @@ -14,98 +13,36 @@ defmodule ElixirScript.Translator.Function do JS.identifier("Patterns") ) - @standard_libs [ - :Patterns, :Kernel, :Atom, :Enum, :Integer, :JS, - :List, :Range, :Tuple, :Agent, :Keyword, - :Base, :String, :Bitwise, :Collectable, :Enumerable, - :Inspect, :Map, :MapSet, :Set, :VirtualDom, :View - ] - - def update_alias({:__aliases__, context, [:List, :Chars]}) do - {:__aliases__, context, [:Elixir] ++ [:List, :Chars] } - end - - def update_alias({:__aliases__, context, [:String, :Chars]}) do - {:__aliases__, context, [:Elixir] ++ [:String, :Chars] } - end - - def update_alias({:__aliases__, context, [name | rest]}) when name in @standard_libs do - {:__aliases__, context, [:Elixir, name] ++ rest } - end - - def update_alias({:__aliases__, context, [name]}) when name in @standard_libs do - {:__aliases__, context, [:Elixir, name] } - end - - def update_alias({{:., context, [module_name, function_name]}, context2, params }) do - {{:., context, [update_alias(module_name), function_name]}, context2, params } - end - - def update_alias(ast) do - ast - end - - def module_in_standard_libs?(name) do - name in @standard_libs - end - - def process_function(name, functions, env) do - result = make_anonymous_function(functions, env) + { result, _ } = make_anonymous_function(functions, env, name) declarator = JS.variable_declarator( JS.identifier(name), result ) - JS.variable_declaration([declarator], :const) + { JS.variable_declaration([declarator], :const), env } end - def make_anonymous_function(functions, env) do - + def make_anonymous_function(functions, env, name \\ nil) do clauses = functions - |> Stream.map(fn(x) -> Variables.process(x) end) - |> Stream.map(fn + |> Enum.map(fn {:->, _, [ [{:when, _, [params | guards]}], body ]} -> - params = wrap_params(params) - { patterns, params } = Match.build_match(params, env) - params = make_params(params) - body = make_function_body(body, env) - guard_body = make_guards(guards, env) - do_make_function_clause(patterns, params, body, guard_body) - + process_function_body(params, body, env, name, guards) ({:->, _, [params, body]}) -> - params = wrap_params(params) - { patterns, params } = Match.build_match(params, env) - params = make_params(params) - body = make_function_body(body, env) - do_make_function_clause(patterns, params, body) + process_function_body(params, body, env, name) ({_, _, [{:when, _, [{_, _, params} | guards] }, [do: body]]}) -> - params = wrap_params(params) - { patterns, params } = Match.build_match(params, env) - params = make_params(params) - body = make_function_body(body, env) - guard_body = make_guards(guards, env) - do_make_function_clause(patterns, params, body, guard_body) + process_function_body(params, body, env, name, guards) ({_, _, [{_, _, params}, [do: body]]}) -> - params = wrap_params(params) - { patterns, params } = Match.build_match(params, env) - params = make_params(params) - body = make_function_body(body, env) - do_make_function_clause(patterns, params, body) + process_function_body(params, body, env, name) ({_, _, [{_, _, params}]}) -> - params = wrap_params(params) - { patterns, params } = Match.build_match(params, env) - params = make_params(params) - body = make_function_body([], env) - do_make_function_clause(patterns, params, body) + process_function_body(params, [], env, name) end) - |> Enum.to_list - make_defmatch(clauses) + { make_defmatch(clauses), env } end def make_defmatch(clauses) do @@ -118,22 +55,38 @@ defmodule ElixirScript.Translator.Function do ) end + defp process_function_body(params, body, env, name, guards \\ nil) do + env = ElixirScript.Env.function_env(env, {name, get_arity(params)}) + + { patterns, params, env } = process_params(params, env) + { body, _ } = make_function_body(body, env) + + if guards do + { guard_body, _ } = hd(List.wrap(guards)) + |> prepare_function_body(env) + + guard_body = JS.block_statement(guard_body) + make_function_clause(patterns, params, body, guard_body) + else + make_function_clause(patterns, params, body, nil) + end + end + def wrap_params(params) when is_atom(params), do: [] - def wrap_params(params) when is_list(params), do: params def wrap_params(params), do: List.wrap(params) def make_function_body(body, env) do - body + { body, _ } = body |> prepare_function_body(env) - |> JS.block_statement - end - defp make_guards(guards, env) do - hd(List.wrap(guards)) - |> prepare_function_body(env) - |> JS.block_statement + + { JS.block_statement(body), env } end + defp get_arity(params) when is_atom(params), do: 0 + defp get_arity(params) when is_tuple(params), do: 1 + defp get_arity(params), do: length(params) + defp make_params(params) do Enum.filter(params, fn (%ESTree.Identifier{name: :undefined}) -> false @@ -141,103 +94,102 @@ defmodule ElixirScript.Translator.Function do end) end - def do_make_function_clause(patterns, params, body, guard_body) do - JS.call_expression( - JS.member_expression( - @patterns, - JS.identifier("make_case") - ), - [ - JS.array_expression(patterns), - JS.function_expression(params, [], body), - JS.function_expression(params, [], guard_body) - ] - ) + defp process_params(params, env) do + params = wrap_params(params) + { patterns, params, env } = Match.process_match(params, env) + { patterns, make_params(params), env } end - def do_make_function_clause(patterns, params, body) do + def make_function_clause(patterns, params, body, guard_body) do + arguments = [ + JS.array_expression(patterns), + JS.function_expression(params, [], body), + ] + + if guard_body do + arguments = arguments ++ [JS.function_expression(params, [], guard_body)] + end + JS.call_expression( JS.member_expression( @patterns, JS.identifier("make_case") ), - [ - JS.array_expression(patterns), - JS.function_expression(params, [], body) - ] + arguments ) end def make_function_or_property_call(module_name, function_name, env) do - the_name = case update_alias(module_name) do - {:__aliases__, _, _} = name -> - module_name = ElixirScript.Module.quoted_to_name(name) - get_name_js_ast(module_name) + the_name = get_module_name_for_function(module_name, env) - {name, _, _} when is_atom(name) -> - get_name_js_ast(name) - - {{:., _, [_module_name, _function_name]}, _, _params } = ast -> - ast - - name -> - name - end - - JS.call_expression( + js_ast = JS.call_expression( JS.member_expression( JS.member_expression( - JS.identifier("Elixir"), - JS.identifier("Core") + JS.identifier("Elixir"), + JS.identifier("Core") ), JS.identifier("call_property") ), [ Utils.make_module_expression_tree(the_name, false, env), - Translator.translate(to_string(function_name), env) + Translator.translate!(to_string(function_name), env) ] ) - end - def make_function_call(function_name, params, env) when is_tuple(function_name) do - Utils.make_call_expression(function_name, params, env) - end - - def make_function_call(function_name, params, env) do - Utils.make_call_expression(Utils.filter_name(function_name), params, env) + { js_ast, env } end - def make_function_call(module_name, function_name, params, env) do - the_name = case update_alias(module_name) do + defp get_module_name_for_function(module_name, env) do + case module_name do {:__aliases__, _, name} -> module_name = ElixirScript.Module.quoted_to_name(name) - get_name_js_ast(module_name) + get_js_name(module_name, env) {name, _, _} when is_atom(name) -> - get_name_js_ast(name) + get_js_name(name, env) {{:., _, [_, _]}, _, _ } = ast -> ast {{:., _, [{:__aliases__, _, _}]}, _, _} = ast -> ast name -> - name + get_js_name(name, env) end + end - Utils.make_call_expression(the_name, Utils.filter_name(function_name), params, env) + def make_function_call(function_name, params, env) when is_tuple(function_name) do + { Utils.make_call_expression(function_name, params, env), env } + end + + def make_function_call(function_name, params, env) do + { Utils.make_call_expression(Utils.filter_name(function_name), params, env), env } + end + + def make_function_call(module_name, function_name, params, env) do + the_name = get_module_name_for_function(module_name, env) + { Utils.make_call_expression(the_name, Utils.filter_name(function_name), params, env), env } end def prepare_function_body(body, env) do - case body do + { list, env } = case body do nil -> - [] + { [], env } list when is_list(list) -> - Enum.map(list, &Translator.translate(&1, env)) + Enum.map_reduce(list, env, fn(x, env) -> + Translator.translate(x, env) + end) {:__block__, _, list} -> - Enum.map(list, &Translator.translate(&1, env)) + Enum.map_reduce(list, env, fn(x, env) -> + Translator.translate(x, env) + end) _ -> - [Translator.translate(body, env)] + Enum.map_reduce(List.wrap(body), env, fn(x, env) -> + Translator.translate(x, env) + end) end - |> Utils.inflate_groups + + list = Utils.inflate_groups(list) |> return_last_expression + + { list, env } end def return_last_expression(nil) do @@ -305,25 +257,23 @@ defmodule ElixirScript.Translator.Function do end end - defp get_name_js_ast([Elixir | _] = list) do + defp get_js_name([Elixir | _] = list, _) do list end - defp get_name_js_ast(module_name) when is_list(module_name) do + defp get_js_name(module_name, env) when is_list(module_name) do ElixirScript.Module.quoted_to_name({:__aliases__, [], module_name}) - |> get_name_js_ast + |> get_js_name(env) end - defp get_name_js_ast(module_name) do + defp get_js_name(module_name, env) do + cond do - ElixirScript.State.get_module(module_name) -> - ElixirScript.State.add_module_reference(Process.get(:current_module), module_name) + module_name in env.requires -> ElixirScript.Module.name_to_js_name(module_name) - ElixirScript.Module.has_alias?(ElixirScript.State.get_module(Process.get(:current_module)), module_name) -> - module = ElixirScript.State.get_module(Process.get(:current_module)) - {_, module_name } = ElixirScript.Module.get_alias(module, module_name) - ElixirScript.State.add_module_reference(Process.get(:current_module), module_name) + module_name in ElixirScript.State.list_module_names -> + ElixirScript.State.add_module_reference(env.module, module_name) ElixirScript.Module.name_to_js_name(module_name) true -> diff --git a/lib/elixir_script/translator/import.ex b/lib/elixir_script/translator/import.ex index 36187203..4973f086 100644 --- a/lib/elixir_script/translator/import.ex +++ b/lib/elixir_script/translator/import.ex @@ -1,7 +1,6 @@ defmodule ElixirScript.Translator.Import do @moduledoc false alias ESTree.Tools.Builder, as: JS - alias ElixirScript.State def make_import(module_name) do import_specifier = JS.import_namespace_specifier( @@ -14,75 +13,6 @@ defmodule ElixirScript.Translator.Import do ) end - def make_alias_import(alias_info, options) do - - {_, _, name} = alias_info - - default = Dict.get(options, :default, false) - - if State.protocol_listed?(name) do - default = true - end - - import_specifier = if default == false do - if options[:as] do - {_, _, alt} = options[:as] - - JS.import_namespace_specifier( - JS.identifier(List.last(alt)) - ) - else - JS.import_namespace_specifier( - JS.identifier(List.last(name)) - ) - end - else - if options[:as] do - {_, _, alt} = options[:as] - - JS.import_specifier( - JS.identifier("default"), - JS.identifier(List.last(alt)) - ) - else - JS.import_default_specifier( - JS.identifier(List.last(name)), - JS.identifier(List.last(name)) - ) - end - end - - import_path = make_source(name) - - JS.import_declaration( - [import_specifier], - JS.identifier(import_path) - ) - end - - defp make_source(name) do - root = ElixirScript.State.get().root - "'#{make_root(root)}#{make_file_path(name)}'" - end - - def make_file_path(name) do - Enum.map(name, fn(x) -> - x - |> Atom.to_string - |> Inflex.underscore - |> String.downcase - end) - |> Enum.join("/") - end - - def get_functions_from_module(functions, [only: only]) do - Set.intersection(Enum.into(only, HashSet.new), Enum.into(functions, HashSet.new)) - end - - def get_functions_from_module(functions, [except: except]) do - Set.difference(Enum.into(functions, HashSet.new), Enum.into(except, HashSet.new)) - end - def create_standard_lib_imports(root, name) do import_specifier = JS.import_namespace_specifier( diff --git a/lib/elixir_script/translator/js.ex b/lib/elixir_script/translator/js.ex index 606af69c..4917ba19 100644 --- a/lib/elixir_script/translator/js.ex +++ b/lib/elixir_script/translator/js.ex @@ -7,20 +7,20 @@ defmodule ElixirScript.Translator.JS do @doc false def translate_js_function(name, params, env) do - do_translate({name, [], params}, env) + { do_translate({name, [], params}, env), env } end defp do_translate({:new, _, [{:__aliases__, _, module_name}, params]}, env) do Builder.new_expression( Utils.make_module_expression_tree(module_name, false, env), - Enum.map(params, &Translator.translate(&1, env)) + Enum.map(params, &Translator.translate!(&1, env)) ) end defp do_translate({:new, _, [module_name, params]}, env) do Builder.new_expression( Translator.translate(module_name, env), - Enum.map(params, &Translator.translate(&1, env)) + Enum.map(params, &Translator.translate!(&1, env)) ) end @@ -28,19 +28,19 @@ defmodule ElixirScript.Translator.JS do Builder.assignment_expression( :=, Builder.member_expression( - Translator.translate(object, env), - Translator.translate(property, env), + Translator.translate!(object, env), + Translator.translate!(property, env), true ), - Translator.translate(value, env) + Translator.translate!(value, env) ) end defp do_translate({:import, _, [module_names, from]}, env) when is_list(module_names) do import_specifiers = Enum.map(module_names, fn(x) -> Builder.import_specifier( - Translator.translate(x, env), - Translator.translate(x, env) + Translator.translate!(x, env), + Translator.translate!(x, env) ) end) @@ -51,34 +51,12 @@ defmodule ElixirScript.Translator.JS do import_specifier = Builder.import_specifier( Builder.identifier("default"), - Translator.translate(module_name, env) + Translator.translate!(module_name, env) ) build_import_declaration([import_specifier], from) end - defp do_translate({:to_js, _, [value]}, env) do - quoted = quote do - if is_list(unquote(value)) || is_map(unquote(value)) || is_tuple(unquote(value)) do - value.toJS() - else - value - end - end - - Translator.translate(quoted, env) - end - - - defp do_translate({:to_json, _, [value]}, env) do - quoted = quote do - JSON.stringify(JS.to_js(unquote(value))) - end - - Translator.translate(quoted, env) - end - - defp build_import_declaration(import_specifiers, from) do Builder.import_declaration( import_specifiers, diff --git a/lib/elixir_script/translator/kernel.ex b/lib/elixir_script/translator/kernel.ex deleted file mode 100644 index 92fae8e7..00000000 --- a/lib/elixir_script/translator/kernel.ex +++ /dev/null @@ -1,298 +0,0 @@ -defmodule ElixirScript.Translator.Kernel do - @moduledoc false - alias ESTree.Tools.Builder, as: JS - alias ElixirScript.Translator - alias ElixirScript.Translator.Map - alias ElixirScript.Translator.Function - alias ElixirScript.Translator.Expression - - @kernel_definitions Kernel.__info__(:functions) ++ Kernel.__info__(:macros) - - def is_defined_in_kernel(name, arity) do - { name, arity } in @kernel_definitions - end - - def translate_kernel_function(name, params, env) do - do_translate({name, [], params}, env) - end - - defp do_translate({operator, _, [value]}, env) when operator in [:-, :!, :+] do - Expression.make_unary_expression(operator, value, env) - end - - defp do_translate({operator, _, [left, right]}, env) when operator in [:+, :-, :/, :*, :==, :!=, :&&, :||, :>, :<, :>=, :<=, :===, :!==] do - Expression.make_binary_expression(operator, left, right, env) - end - - defp do_translate({:<>, _, [left, right]}, env) do - Expression.make_binary_expression(:+, left, right, env) - end - - defp do_translate({:++, _, [left, right]}, env) do - JS.call_expression( - JS.member_expression( - Translator.translate(left, env), - JS.identifier(:concat) - ), - [Translator.translate(right, env)] - ) - end - - defp do_translate({:.., _, [first, last]}, env) do - quoted_range = quote do: Range.(unquote(first), unquote(last)) - - Translator.translate(quoted_range, env) - end - - defp do_translate({:abs, _, [number]}, env) do - quoted = quote do - Math.abs(unquote(number)) - end - - Translator.translate(quoted, env) - end - - defp do_translate({:apply, _, [fun, args]}, env) do - quoted = quote do - unquote(fun)(unquote_splicing(args)) - end - - Translator.translate(quoted, env) - end - - defp do_translate({:apply, _, [module, fun, args]}, env) do - quoted = quote do - unquote(module).unquote(fun)(unquote_splicing(args)) - end - - Translator.translate(quoted, env) - end - - defp do_translate({:and, _, [left, right]}, env) do - Expression.make_binary_expression(:&&, left, right, env) - end - - defp do_translate({:div, _, [left, right]}, env) do - Expression.make_binary_expression(:/, left, right, env) - end - - defp do_translate({:or, _, [left, right]}, env) do - Expression.make_binary_expression(:||, left, right, env) - end - - defp do_translate({:not, _, [value]}, env) do - Expression.make_unary_expression(:!, value, env) - end - - defp do_translate({:rem, _, [left, right]}, env) do - Expression.make_binary_expression(:%, left, right, env) - end - - defp do_translate({:round, _, [value]}, env) do - quoted = quote do - Math.round(unquote(value)) - end - - Translator.translate(quoted, env) - end - - defp do_translate({:self, _, []}, _) do - JS.call_expression( - JS.member_expression( - JS.identifier(:self), - JS.member_expression( - JS.identifier(:scheduler), - JS.identifier(:pid) - ) - ), - [] - ) - end - - defp do_translate({:spawn, _, [fun]}, env) do - JS.call_expression( - JS.member_expression( - JS.identifier(:self), - JS.member_expression( - JS.identifier(:scheduler), - JS.identifier(:spawn) - ) - ), - [Translator.translate(fun, env)] - ) - end - - defp do_translate({:spawn, _, [module, fun, args]}, env) do - JS.call_expression( - JS.member_expression( - JS.identifier(:self), - JS.member_expression( - JS.identifier(:scheduler), - JS.identifier(:spawn_from_module) - ) - ), - [Translator.translate(module, env), Translator.translate(fun, env), Translator.translate(args, env)] - ) - end - - defp do_translate({:spawn_link, _, [fun]}, env) do - JS.call_expression( - JS.member_expression( - JS.identifier(:self), - JS.member_expression( - JS.identifier(:scheduler), - JS.identifier(:spawn_link) - ) - ), - [Translator.translate(fun, env)] - ) - end - - defp do_translate({:spawn_link, _, [module, fun, args]}, env) do - JS.call_expression( - JS.member_expression( - JS.identifier(:self), - JS.member_expression( - JS.identifier(:scheduler), - JS.identifier(:spawn_link_from_module) - ) - ), - [Translator.translate(module, env), Translator.translate(fun, env), Translator.translate(args, env)] - ) - end - - defp do_translate({:exit, _, [reason]}, env) do - JS.call_expression( - JS.member_expression( - JS.identifier(:self), - JS.member_expression( - JS.identifier(:scheduler), - JS.identifier(:exit) - ) - ), - [Translator.translate(reason, env)] - ) - end - - defp do_translate({:tuple_size, _, [tuple]}, env) do - quoted = quote do - unquote(tuple).count() - end - - Translator.translate(quoted, env) - end - - defp do_translate({:map_size, _, [map]}, env) do - quoted = quote do - Object.keys(unquote(map)).length - end - - Translator.translate(quoted, env) - end - - defp do_translate({:max, _, [first, second]}, env) do - quoted = quote do - Math.max(unquote(first), unquote(second)) - end - - Translator.translate(quoted, env) - end - - defp do_translate({:min, _, [first, second]}, env) do - quoted = quote do - Math.min(unquote(first), unquote(second)) - end - - Translator.translate(quoted, env) - end - - defp do_translate({:if, _, _} = ast, env) do - Macro.expand(ast, env) - |> Translator.translate(env) - end - - defp do_translate({:unless, _, _} = ast, env) do - Macro.expand(ast, env) - |> Translator.translate(env) - end - - defp do_translate({:throw, _, [params]}, env) do - JS.throw_statement(Translator.translate(params, env)) - end - - defp do_translate({:|>, _, [left, right]}, env) do - case right do - {{:., meta, [module, fun]}, meta2, params} -> - Translator.translate({{:., meta, [module, fun]}, meta2, [left] ++ params}, env) - {fun, meta, params} -> - Translator.translate({fun, meta, [left] ++ params}, env) - end - end - - defp do_translate({:hd, _, [list]}, env) do - quoted = quote do - unquote(list)[0] - end - - Translator.translate(quoted, env) - end - - defp do_translate({:tl, _, [list]}, env) do - JS.call_expression( - JS.member_expression( - Translator.translate(list, env), - JS.identifier(:slice) - ), - [JS.literal(1)] - ) - end - - defp do_translate({:length, _, [list]}, env) when is_list(list) do - JS.member_expression( - Translator.translate(list, env), - JS.identifier(:length) - ) - end - - defp do_translate({:raise, _, [alias_info, attributes]}, env) do - {_, _, name} = alias_info - - JS.throw_statement( - JS.call_expression( - JS.member_expression( - JS.identifier(List.last(name)), - JS.identifier(:defexception) - ), - Enum.map(attributes, fn({k, v})-> - JS.assignment_expression( - :=, - JS.identifier(k), - Translator.translate(v, env) - ) - end) - ) - ) - end - - defp do_translate({:raise, _, [message]}, env) do - JS.throw_statement( - JS.object_expression( - [ - Map.make_property(Translator.translate(:__struct__, env), Translator.translate(:RuntimeError, env)), - Map.make_property(Translator.translate(:__exception__, env), Translator.translate(true, env)), - Map.make_property(Translator.translate(:message, env), JS.literal(message)) - ] - ) - ) - end - - defp do_translate({:to_string, _, _} = ast, env) do - Macro.expand(ast, env) - |> Translator.translate(env) - end - - defp do_translate({name, _, params}, env) do - Function.make_function_call({:__aliases__, [], [:Elixir, :Kernel]}, name, params, env) - end - -end diff --git a/lib/elixir_script/translator/logger.ex b/lib/elixir_script/translator/logger.ex deleted file mode 100644 index 2537c1c5..00000000 --- a/lib/elixir_script/translator/logger.ex +++ /dev/null @@ -1,24 +0,0 @@ -defmodule ElixirScript.Translator.Logger do - @moduledoc false - alias ESTree.Tools.Builder, as: JS - alias ElixirScript.Translator - - - def make_logger(:log, params, env) do - do_make_logger(hd(params), tl(params), env) - end - - def make_logger(level, params, env) do - do_make_logger(level, params, env) - end - - defp do_make_logger(level, params, env) do - JS.call_expression( - JS.member_expression( - JS.identifier("console"), - JS.identifier(level) - ), - [Translator.translate(hd(params), env)] - ) - end -end \ No newline at end of file diff --git a/lib/elixir_script/translator/map.ex b/lib/elixir_script/translator/map.ex index a309591f..3abb5c10 100644 --- a/lib/elixir_script/translator/map.ex +++ b/lib/elixir_script/translator/map.ex @@ -16,8 +16,8 @@ defmodule ElixirScript.Translator.Map do def make_get_property(target, property, env) do JS.member_expression( - Translator.translate(target, env), - Translator.translate(property, env), + Translator.translate!(target, env), + Translator.translate!(property, env), true ) end @@ -25,8 +25,8 @@ defmodule ElixirScript.Translator.Map do def make_object(properties, env) do properties |> Enum.map(fn - ({x, {:__aliases__, _, [value]}}) -> make_property(Translator.translate(x, env), JS.identifier(value)) - ({x, y}) -> make_property(Translator.translate(x, env), Translator.translate(y, env)) + ({x, {:__aliases__, _, [value]}}) -> make_property(Translator.translate!(x, env), JS.identifier(value)) + ({x, y}) -> make_property(Translator.translate!(x, env), Translator.translate!(y, env)) end) |> JS.object_expression |> make_map @@ -49,12 +49,12 @@ defmodule ElixirScript.Translator.Map do end def make_map_update(map, data, env) do - map = Translator.translate(map, env) + map = Translator.translate!(map, env) map_update = JS.object_expression( Enum.map(data, fn({key, value}) -> - make_property(Translator.translate(key, env), Translator.translate(value, env)) + make_property(Translator.translate!(key, env), Translator.translate!(value, env)) end ) ) diff --git a/lib/elixir_script/translator/module.ex b/lib/elixir_script/translator/module.ex index bc222541..71c11c9e 100644 --- a/lib/elixir_script/translator/module.ex +++ b/lib/elixir_script/translator/module.ex @@ -4,30 +4,29 @@ defmodule ElixirScript.Translator.Module do alias ElixirScript.Translator alias ElixirScript.Translator.Utils alias ElixirScript.Translator.JSModule - alias ElixirScript.Preprocess.Aliases alias ElixirScript.Preprocess.Using alias ElixirScript.Translator.Function - alias ElixirScript.Translator.Primitive def make_module(ElixirScript.Temp, body, env) do - [%JSModule{ name: ElixirScript.Temp, body: translate_body(body, env) |> Utils.inflate_groups }] + { body, _ } = translate_body(body, env) + %JSModule{ name: ElixirScript.Temp, body: body |> Utils.inflate_groups } end - def make_module(module, nil, env) do - [%JSModule{ name: module, body: List.wrap(create__module__(module, env)) }] + def make_module(module, nil, _) do + %JSModule{ name: module, body: [] } end def make_module(module, body, env) do - body = Using.process(body, env) + body = Using.process(body) { body, functions } = extract_functions_from_module(body) - { exported_functions, private_functions } = process_functions(functions, env) + { body, env } = translate_body(body, env) - body = translate_body(body, env) + { exported_functions, private_functions } = process_functions(functions, env) modules_refs = ElixirScript.State.get_module_references(module) {imports, body} = extract_imports_from_body(body) - {structs, body} = extract_structs_from_body(body) + {structs, body} = extract_structs_from_body(body, env) #Add imports found from walking the ast #and make sure to only put one declaration per alias @@ -57,29 +56,19 @@ defmodule ElixirScript.Translator.Module do private_functions = Enum.map(private_functions, fn({_key, value}) -> value end) default = JS.export_named_declaration(exported_object) - {modules, body} = Enum.partition(body, fn(x) -> - case x do - %JSModule{} -> - true - _ -> - false - end - end) - result = [ - %JSModule{ + result = %JSModule{ name: ElixirScript.Module.quoted_to_name({:__aliases__, [], module }), - body: imports ++ List.wrap(create__module__(module, env)) ++ structs ++ private_functions ++ exported_functions ++ body ++ [default] + body: imports ++ structs ++ private_functions ++ exported_functions ++ body ++ [default] } - ] ++ List.flatten(modules) result end def translate_body(body, env) do - body = Translator.translate(body, env) + { body, env } = Translator.translate(body, env) - case body do + body = case body do [%ESTree.BlockStatement{ body: body }] -> body %ESTree.BlockStatement{ body: body } -> @@ -87,6 +76,8 @@ defmodule ElixirScript.Translator.Module do _ -> List.wrap(body) end + + { body, env } end def extract_functions_from_module({:__block__, meta, body_list}) do @@ -137,10 +128,12 @@ defmodule ElixirScript.Translator.Module do end) end - def extract_structs_from_body(body) do + def extract_structs_from_body(body, env) do + module_js_name = ElixirScript.Module.name_to_js_name(env.module) + Enum.partition(body, fn(x) -> case x do - %ESTree.VariableDeclaration{declarations: [%ESTree.VariableDeclarator{id: %ESTree.Identifier{name: name} } ] } when name in [:defstruct, :defexception] -> + %ESTree.VariableDeclaration{declarations: [%ESTree.VariableDeclarator{id: %ESTree.Identifier{name: ^module_js_name} } ] } -> true _ -> false @@ -153,32 +146,34 @@ defmodule ElixirScript.Translator.Module do end defp make_defstruct_property(module_name, [the_struct]) do + module_js_name = ElixirScript.Module.name_to_js_name(module_name) + case the_struct do - %ESTree.VariableDeclaration{declarations: [%ESTree.VariableDeclarator{id: %ESTree.Identifier{name: name} } ] } when name in [:defstruct, :defexception] -> - [JS.property(JS.identifier(ElixirScript.Module.name_to_js_name(module_name)), JS.identifier(name), :init)] + %ESTree.VariableDeclaration{declarations: [%ESTree.VariableDeclarator{id: %ESTree.Identifier{name: ^module_js_name} } ] } -> + [JS.property(JS.identifier(module_js_name), JS.identifier(module_js_name), :init, true)] end end def process_imports(imports, module_refs) do imports ++ make_imports(module_refs) - |> Enum.into(HashSet.new) - |> Enum.reduce(HashSet.new, fn(x, acc)-> - HashSet.put(acc, x) + |> Enum.into(MapSet.new) + |> Enum.reduce(MapSet.new, fn(x, acc)-> + MapSet.put(acc, x) end) - |> HashSet.to_list - |> Enum.reduce(%{ identifiers: HashSet.new, imports: [] }, fn(x, state) -> + |> MapSet.to_list + |> Enum.reduce(%{ identifiers: MapSet.new, imports: [] }, fn(x, state) -> case x do %ESTree.ImportDeclaration{ specifiers: [%ESTree.ImportSpecifier{ local: id }] } -> - if HashSet.member?(state.identifiers, id.name) do + if MapSet.member?(state.identifiers, id.name) do state else - %{ state | identifiers: HashSet.put(state.identifiers, id.name), imports: state.imports ++ [x] } + %{ state | identifiers: MapSet.put(state.identifiers, id.name), imports: state.imports ++ [x] } end %ESTree.ImportDeclaration{ specifiers: [%ESTree.ImportDefaultSpecifier{ local: id }] } -> - if HashSet.member?(state.identifiers, id.name) do + if MapSet.member?(state.identifiers, id.name) do state else - %{ state | identifiers: HashSet.put(state.identifiers, id.name), imports: state.imports ++ [x] } + %{ state | identifiers: MapSet.put(state.identifiers, id.name), imports: state.imports ++ [x] } end _ -> %{ state | imports: state.imports ++ [x] } @@ -189,12 +184,15 @@ defmodule ElixirScript.Translator.Module do def process_functions(%{ exported: exported, private: private }, env) do exported_functions = Enum.map(Dict.keys(exported), fn(key) -> functions = Dict.get(exported, key) - { key, Function.process_function(key, functions, env) } + + { functions, _ } = Function.process_function(key, functions, env) + { key, functions } end) private_functions = Enum.map(Dict.keys(private), fn(key) -> functions = Dict.get(private, key) - { key, Function.process_function(key, functions, env) } + { functions, _ } = Function.process_function(key, functions, env) + { key, functions } end) { exported_functions, private_functions } @@ -203,16 +201,7 @@ defmodule ElixirScript.Translator.Module do def make_attribute(name, value, env) do declarator = JS.variable_declarator( JS.identifier(name), - ElixirScript.Translator.translate(value, env) - ) - - JS.variable_declaration([declarator], :const) - end - - def create__module__(module, _) do - declarator = JS.variable_declarator( - JS.identifier(:__MODULE__), - Primitive.make_atom(module) + ElixirScript.Translator.translate!(value, env) ) JS.variable_declaration([declarator], :const) diff --git a/lib/elixir_script/translator/primitive.ex b/lib/elixir_script/translator/primitive.ex index d4b3f8e3..658667d2 100644 --- a/lib/elixir_script/translator/primitive.ex +++ b/lib/elixir_script/translator/primitive.ex @@ -25,13 +25,6 @@ defmodule ElixirScript.Translator.Primitive do ) end - def scheduler() do - JS.member_expression( - JS.identifier("self"), - JS.identifier("system") - ) - end - def make_identifier({:__aliases__, _, aliases}) do Utils.make_module_expression_tree(aliases, false, __ENV__) end @@ -63,13 +56,17 @@ defmodule ElixirScript.Translator.Primitive do end def make_list(ast, env) when is_list(ast) do - JS.call_expression( + list = Enum.map(ast, &Translator.translate!(&1, env)) + + js_ast = JS.call_expression( JS.member_expression( special_forms(), JS.identifier("list") ), - Enum.map(ast, fn(x) -> Translator.translate(x, env) end) + list ) + + { js_ast, env } end def make_list_quoted(opts, ast, env) when is_list(ast) do @@ -97,13 +94,17 @@ defmodule ElixirScript.Translator.Primitive do end def make_tuple(elements, env) do - JS.call_expression( + list = Enum.map(elements, &Translator.translate!(&1, env)) + + js_ast = JS.call_expression( JS.member_expression( special_forms(), JS.identifier("tuple") ), - Enum.map(elements, fn(x) -> Translator.translate(x, env) end) + list ) + + { js_ast, env } end def make_tuple_no_translate(elements) do diff --git a/lib/elixir_script/translator/protocol.ex b/lib/elixir_script/translator/protocol.ex index 472b3055..2c67c319 100644 --- a/lib/elixir_script/translator/protocol.ex +++ b/lib/elixir_script/translator/protocol.ex @@ -2,24 +2,16 @@ defmodule ElixirScript.Translator.Protocol do @moduledoc false alias ESTree.Tools.Builder, as: JS - alias ElixirScript.Translator alias ElixirScript.Translator.Module - alias ElixirScript.Preprocess.Aliases alias ElixirScript.Translator.JSModule alias ElixirScript.Translator.Map alias ElixirScript.Translator.Function alias ElixirScript.Translator.Utils @doc """ - Takes a list of protocols and turns them into modules + Takes a protocol and turns them into modules """ - def consolidate(protocols, env) when is_list(protocols) do - Enum.map(protocols, fn({_, protocol}) -> - do_consolidate(protocol, env) - end) - end - - defp do_consolidate(protocol, env) do + def consolidate(protocol, env) do name = protocol.name spec = protocol.spec impls = protocol.impls |> Dict.to_list @@ -28,23 +20,21 @@ defmodule ElixirScript.Translator.Protocol do {impl_imports, impl_body, impls} = define_impls(name, impls, env) body = spec_body ++ impl_body - imports = spec_imports ++ impl_imports + imports = Enum.uniq(spec_imports ++ impl_imports) create_module(name, spec, impls, imports, body, env) end defp define_spec(name, spec, env) do - { body, aliases } = Aliases.process(name, spec, env) - - { body, functions } = extract_function_from_spec(body) - + { body, functions } = extract_function_from_spec(spec) + { body, env } = Module.translate_body(body, env) { exported_functions, _ } = process_functions(functions, env) - body = Module.translate_body(body, env) + modules_refs = ElixirScript.State.get_module_references(name) {imports, body} = Module.extract_imports_from_body(body) - imports = Module.process_imports(imports, aliases) + imports = Module.process_imports(imports, modules_refs) imports = imports.imports object = Enum.map(exported_functions, fn({key, value}) -> @@ -66,7 +56,7 @@ defmodule ElixirScript.Translator.Protocol do ) ) - {imports, body, [JS.variable_declaration([declarator], :let)]} + {imports, body, [JS.variable_declaration([declarator], :const)]} end defp define_impls(_, [], _) do @@ -76,15 +66,16 @@ defmodule ElixirScript.Translator.Protocol do defp define_impls(name, impls, env) do Enum.map(impls, fn({type, impl}) -> type = map_to_js(type) - { body, aliases } = Aliases.process(name, impl, env) - { body, functions } = Module.extract_functions_from_module(body) + { body, functions } = Module.extract_functions_from_module(impl) + { body, env } = Module.translate_body(body, env) + { exported_functions, _ } = process_functions(functions, env) - body = Module.translate_body(body, env) + modules_refs = ElixirScript.State.get_module_references(name) {imports, body} = Module.extract_imports_from_body(body) - imports = Module.process_imports(imports, aliases) + imports = Module.process_imports(imports, modules_refs) imports = imports.imports object = Enum.map(exported_functions, fn({key, value}) -> @@ -115,36 +106,12 @@ defmodule ElixirScript.Translator.Protocol do end) end - def make_standard_lib_impl(protocol, type, impl, env) do - type = map_to_js(type) - protocol = Translator.translate(protocol, env) - - { _, functions } = Module.extract_functions_from_module(impl) - { exported_functions, _ } = process_functions(functions, env) - - object = Enum.map(exported_functions, fn({key, value}) -> - Map.make_property(JS.identifier(Utils.filter_name(key)), value) - end) - |> JS.object_expression - - JS.call_expression( - JS.member_expression( - JS.identifier(:Elixir), - JS.member_expression( - JS.identifier(:Kernel), - JS.identifier(:defimpl) - ) - ), - [protocol, type, object] - ) - end - - defp create_module(name, spec, impls, imports, body, env) do + defp create_module(name, spec, impls, imports, body, _) do default = JS.export_default_declaration(JS.identifier(ElixirScript.Module.name_to_js_name(name))) %JSModule{ name: name, - body: imports ++ List.wrap(Module.create__module__(name, env)) ++ body ++ spec ++ impls ++ [default] + body: imports ++ body ++ spec ++ impls ++ [default] } end @@ -169,12 +136,17 @@ defmodule ElixirScript.Translator.Protocol do defp process_functions(%{ exported: exported, private: private }, env) do exported_functions = Enum.map(Dict.keys(exported), fn(key) -> functions = Dict.get(exported, key) - { key, Function.make_anonymous_function(functions, env) } + + { functions, _ } = Function.make_anonymous_function(functions, env) + + { key, functions } end) private_functions = Enum.map(Dict.keys(private), fn(key) -> functions = Dict.get(private, key) - { key, Function.make_anonymous_function(functions, env) } + { functions, _ } = Function.make_anonymous_function(functions, env) + + { key, functions } end) { exported_functions, private_functions } @@ -261,15 +233,11 @@ defmodule ElixirScript.Translator.Protocol do end defp map_to_js({:__aliases__, _, [:Any]}) do - quoted = quote do - nil - end - - Translator.translate(quoted, ElixirScript.State.get().env) + JS.identifier(:null) end - defp map_to_js({:__aliases__, _, module}) do + defp map_to_js({:__aliases__, _, _} = module) do ElixirScript.Translator.Struct.get_struct_class( module, ElixirScript.State.get().env diff --git a/lib/elixir_script/translator/quote.ex b/lib/elixir_script/translator/quote.ex index e3932d61..80b6b3fd 100644 --- a/lib/elixir_script/translator/quote.ex +++ b/lib/elixir_script/translator/quote.ex @@ -6,7 +6,7 @@ defmodule ElixirScript.Translator.Quote do alias ElixirScript.Translator.Primitive def make_quote(_opts, expr, env) when is_number(expr) or is_binary(expr) or is_boolean(expr) or is_nil(expr) or is_atom(expr) do - Translator.translate(expr, env) + Translator.translate!(expr, env) end def make_quote(opts, expr, env) when is_list(expr) do @@ -57,18 +57,18 @@ defmodule ElixirScript.Translator.Quote do def make_quote(opts, {name, context, elements }, env) do if is_in_bind_quoted(opts[:bind_quoted], name) do - Translator.translate({name, context, elements }, env) + Translator.translate!({name, context, elements }, env) else Primitive.make_tuple_quoted(opts, [name, context, elements], env) end end def make_unquote(expr, env) do - Translator.translate(expr, env) + Translator.translate!(expr, env) end def make_unquote_slicing(expr, env) do - Translator.translate(expr, env) + Translator.translate!(expr, env) end defp is_in_bind_quoted(nil, _) do diff --git a/lib/elixir_script/translator/receive.ex b/lib/elixir_script/translator/receive.ex deleted file mode 100644 index e363d3ed..00000000 --- a/lib/elixir_script/translator/receive.ex +++ /dev/null @@ -1,52 +0,0 @@ -defmodule ElixirScript.Translator.Receive do - @moduledoc false - alias ESTree.Tools.Builder, as: JS - alias ElixirScript.Translator - alias ElixirScript.Translator.Primitive - - def make_receive([do: clauses], env) do - JS.yield_expression( - JS.call_expression( - JS.member_expression( - Primitive.scheduler(), - JS.identifier("receive") - ), - [ - JS.function_expression( - [JS.identifier(:message)], - [], - JS.block_statement([ - JS.return_statement( - ElixirScript.Translator.Case.make_case({:__aliases__, [], [:message]}, clauses, env) - ) - ]) - ) - ] - ) - ) - end - - def make_receive([do: clauses, after: [{:->, _, [[time], _body]}] = after_clause], env) do - JS.yield_expression( - JS.call_expression( - JS.member_expression( - Primitive.scheduler(), - JS.identifier("receive") - ), - [ - JS.function_expression( - [JS.identifier(:message)], - [], - JS.block_statement([ - JS.return_statement( - ElixirScript.Translator.Case.make_case({:__aliases__, [], [:message]}, clauses, env) - ) - ]) - ), - Translator.translate(time, env), - ElixirScript.Translator.Function.make_anonymous_function(after_clause, env) - ] - ) - ) - end -end \ No newline at end of file diff --git a/lib/elixir_script/translator/struct.ex b/lib/elixir_script/translator/struct.ex index 5519d52f..ed4d7818 100644 --- a/lib/elixir_script/translator/struct.ex +++ b/lib/elixir_script/translator/struct.ex @@ -6,22 +6,19 @@ defmodule ElixirScript.Translator.Struct do alias ElixirScript.Translator.Map def get_struct_class(module_name, env) do - current_module = ElixirScript.State.get_module(Process.get(:current_module)) + candiate_module_name = ElixirScript.Module.quoted_to_name(module_name) + |> ElixirScript.Module.get_module_name - name = ElixirScript.Module.quoted_to_name(module_name) - the_alias = ElixirScript.Module.get_alias(current_module, name) + if ElixirScript.Env.get_module_name(env, candiate_module_name) in ElixirScript.State.list_module_names() do + name = ElixirScript.Env.get_module_name(env, candiate_module_name) - if the_alias do - { _, name } = the_alias - end - - if the_alias == nil && ElixirScript.State.get_module(ElixirScript.Module.quoted_to_name(module_name)) == nil do - Utils.make_module_expression_tree(module_name, false, env) - else JS.member_expression( JS.identifier(ElixirScript.Module.name_to_js_name(name)), JS.identifier(ElixirScript.Module.name_to_js_name(name)) ) + + else + Utils.make_module_expression_tree(module_name, false, env) end end @@ -32,7 +29,7 @@ defmodule ElixirScript.Translator.Struct do get_struct_class(module_name, env), JS.identifier(:create) ), - [Translator.translate(data, env)] + [Translator.translate!(data, env)] ) end @@ -41,8 +38,8 @@ defmodule ElixirScript.Translator.Struct do defaults = Enum.map(attributes, fn({x, y}) -> Map.make_property( - Translator.translate(x, env), - Translator.translate(y, env) + Translator.translate!(x, env), + Translator.translate!(y, env) ) end) |> JS.object_expression @@ -53,8 +50,8 @@ defmodule ElixirScript.Translator.Struct do def make_defstruct(attributes, env) do defaults = Enum.map(attributes, fn(x) -> Map.make_property( - Translator.translate(x, env), - Translator.translate(nil, env) + Translator.translate!(x, env), + Translator.translate!(nil, env) ) end) |> JS.object_expression @@ -63,20 +60,20 @@ defmodule ElixirScript.Translator.Struct do end def make_defexception(attributes, env) when length(attributes) == 1 do - exception_key_value = Map.make_property(Translator.translate(:__exception__, env), Translator.translate(true, env)) + exception_key_value = Map.make_property(Translator.translate!(:__exception__, env), Translator.translate!(true, env)) attributes = Enum.flat_map(attributes, fn(x) -> x end) defaults = [exception_key_value] ++ Enum.map(attributes, fn ({x, y}) -> Map.make_property( - Translator.translate(x, env), - Translator.translate(y, env) + Translator.translate!(x, env), + Translator.translate!(y, env) ) (x) -> Map.make_property( - Translator.translate(x, env), - Translator.translate(nil, env) + Translator.translate!(x, env), + Translator.translate!(nil, env) ) end) |> JS.object_expression @@ -85,13 +82,13 @@ defmodule ElixirScript.Translator.Struct do end def make_defexceptions(attributes, env) do - exception_key_value = Map.make_property(Translator.translate(:__exception__, env), Translator.translate(true, env)) + exception_key_value = Map.make_property(Translator.translate!(:__exception__, env), Translator.translate!(true, env)) defaults = [exception_key_value] ++ Enum.map(attributes, fn (x) -> Map.make_property( - Translator.translate(x, env), - Translator.translate(nil, env) + Translator.translate!(x, env), + Translator.translate!(nil, env) ) end) |> JS.object_expression @@ -100,11 +97,11 @@ defmodule ElixirScript.Translator.Struct do end defp do_make_defstruct(name, defaults, env) do - struct_name = Map.make_property(Translator.translate(:__struct__, env), JS.identifier(:__MODULE__)) + struct_name = Map.make_property(Translator.translate!(:__struct__, env), Translator.translate!({:__MODULE__, [], []}, env)) defaults = %{ defaults | properties: [struct_name] ++ defaults.properties } - ref = JS.identifier(name) + ref = JS.identifier(ElixirScript.Module.name_to_js_name(env.module)) ref_declarator = JS.variable_declarator( ref, diff --git a/lib/elixir_script/translator/try.ex b/lib/elixir_script/translator/try.ex index 16fb2740..ee9bf1e9 100644 --- a/lib/elixir_script/translator/try.ex +++ b/lib/elixir_script/translator/try.ex @@ -11,7 +11,9 @@ defmodule ElixirScript.Translator.Try do after_block = Dict.get(blocks, :after, nil) else_block = Dict.get(blocks, :else, nil) - translated_body = Function.prepare_function_body(try_block, env) |> JS.block_statement + { translated_body, _ } = Function.prepare_function_body(try_block, env) + + translated_body = JS.block_statement(translated_body) try_block = JS.function_expression([], [], translated_body) if rescue_block do @@ -33,12 +35,12 @@ defmodule ElixirScript.Translator.Try do end if else_block do - else_block = Function.make_anonymous_function(else_block, env) + { else_block, _ } = Function.make_anonymous_function(else_block, env) else else_block = JS.identifier(:null) end - JS.call_expression( + js_ast = JS.call_expression( JS.member_expression( Primitive.special_forms(), JS.identifier("_try") @@ -52,18 +54,19 @@ defmodule ElixirScript.Translator.Try do ] ) + { js_ast, env } end defp process_rescue_block(rescue_block, env) do - Enum.map(rescue_block, fn(x) -> + { func, _ } = Enum.map(rescue_block, fn(x) -> case x do {:->, _, [[{value, _, module}], block]} when not is_list(module) -> {:->, [], [[{value, [], convert_to_struct(module)}], block]} {:->, _, [[{:in, meta, [value, error_names]}], block]} -> error_names = Enum.map(error_names, fn(x) -> - convert_to_struct(x) + convert_to_struct(x) end) - + guards = {:in, meta, [value, error_names]} {:->, [], [ [{:when, [], [value | [guards]]}], block ]} @@ -75,16 +78,22 @@ defmodule ElixirScript.Translator.Try do end) |> List.flatten |> Function.make_anonymous_function(env) + + func end defp process_catch_block(catch_block, env) do - catch_block + {func, _} = catch_block |> Function.make_anonymous_function(env) + + func end defp process_after_block(after_block, env) do - translated_body = Function.prepare_function_body(after_block, env) |> JS.block_statement - JS.function_expression([], [], translated_body) + { translated_body, _ } = Function.prepare_function_body(after_block, env) + translated_body = JS.block_statement(translated_body) + + JS.function_expression([], [], translated_body) end defp convert_to_struct([module]) do @@ -99,4 +108,4 @@ defmodule ElixirScript.Translator.Try do ast end end -end \ No newline at end of file +end diff --git a/lib/elixir_script/translator/utils.ex b/lib/elixir_script/translator/utils.ex index 94c16b60..19a29ede 100644 --- a/lib/elixir_script/translator/utils.ex +++ b/lib/elixir_script/translator/utils.ex @@ -19,17 +19,6 @@ defmodule ElixirScript.Translator.Utils do |> List.flatten end - def make_throw_statement(error_name, message) do - JS.throw_statement( - JS.new_expression( - JS.identifier(error_name), - [ - JS.literal(message) - ] - ) - ) - end - def make_module_expression_tree([module], computed, env) do make_module_expression_tree(module, computed, env) end @@ -52,34 +41,27 @@ defmodule ElixirScript.Translator.Utils do end def make_module_expression_tree(module, _computed, env) do - Translator.translate(module, env) - end - - def make_call_expression_with_ast_params(module_name, function_name, params, env) do - JS.call_expression( - make_member_expression(module_name, function_name, env), - params - ) + Translator.translate!(module, env) end def make_call_expression(module_name, function_name, params, env) do JS.call_expression( make_member_expression(module_name, function_name, env), - Enum.map(params, &Translator.translate(&1, env)) + Enum.map(params, &Translator.translate!(&1, env)) ) end def make_call_expression(function_name, params, env) when is_tuple(function_name) do JS.call_expression( - Translator.translate(function_name, env), - Enum.map(params, &Translator.translate(&1, env)) + Translator.translate!(function_name, env), + Enum.map(params, &Translator.translate!(&1, env)) ) end def make_call_expression(function_name, params, env) do JS.call_expression( JS.identifier(function_name), - Enum.map(params, &Translator.translate(&1, env)) + Enum.map(params, &Translator.translate!(&1, env)) ) end @@ -89,90 +71,42 @@ defmodule ElixirScript.Translator.Utils do ast = make_module_expression_tree(modules, computed, env) JS.member_expression( ast, - build_function_name_ast(function_name), + JS.identifier(function_name), computed ) modules when is_list(modules) and length(modules) == 1 -> JS.member_expression( JS.identifier(hd(modules)), - build_function_name_ast(function_name), + JS.identifier(function_name), computed ) {{:., _, [_module_name, _function_name]}, _, _params } = ast -> JS.member_expression( - Translator.translate(ast, env), - build_function_name_ast(function_name), + Translator.translate!(ast, env), + JS.identifier(function_name), computed ) {{:., _, [{:__aliases__, _, _}]}, _, _} = ast -> JS.member_expression( - Translator.translate(ast, env), - build_function_name_ast(function_name), + Translator.translate!(ast, env), + JS.identifier(function_name), computed ) {:., _, _} = ast -> JS.member_expression( - Translator.translate(ast, env), - build_function_name_ast(function_name), + Translator.translate!(ast, env), + JS.identifier(function_name), computed ) _ -> JS.member_expression( JS.identifier(module_name), - build_function_name_ast(function_name), + JS.identifier(function_name), computed ) end end - def build_function_name_ast(function_name) do - JS.identifier(function_name) - end - - def make_array_accessor_call(name, index) do - make_member_expression(name, index, true) - end - - def wrap_in_function_closure(body) do - the_body = case body do - b when is_list(b) -> - b - _ -> - [body] - end - - JS.call_expression( - JS.member_expression( - JS.function_expression([],[], - JS.block_statement(the_body) - ), - JS.identifier("call") - ), - [JS.identifier("this")] - ) - end - - def make_match(pattern, expr, env) do - JS.call_expression( - make_member_expression("Kernel", "match__qmark__", env), - [ - pattern, - expr - ] - ) - end - - def make_match(pattern, expr, guard, env) do - JS.call_expression( - make_member_expression("Kernel", "match__qmark__", env), - [ - pattern, - expr, - guard - ] - ) - end - def filter_name(name) do to_string(name) |> String.replace("?", "__qmark__") diff --git a/lib/elixir_script/universal/atom.ex b/lib/elixir_script/universal/atom.ex new file mode 100644 index 00000000..13929c47 --- /dev/null +++ b/lib/elixir_script/universal/atom.ex @@ -0,0 +1,12 @@ +defmodule ElixirScript.Atom do + import Kernel, except: [to_string: 1] + + def to_char_list(atom) do + to_string(atom).split("") + end + + def to_string(atom) do + Symbol.keyFor(atom) + end + +end diff --git a/lib/elixir_script/universal/collectable.ex b/lib/elixir_script/universal/collectable.ex new file mode 100644 index 00000000..66990821 --- /dev/null +++ b/lib/elixir_script/universal/collectable.ex @@ -0,0 +1,3 @@ +defprotocol ElixirScript.Collectable do + def into(collectable) +end diff --git a/lib/elixir_script/universal/enumerable.ex b/lib/elixir_script/universal/enumerable.ex new file mode 100644 index 00000000..ffbad71f --- /dev/null +++ b/lib/elixir_script/universal/enumerable.ex @@ -0,0 +1,5 @@ +defprotocol ElixirScript.Enumerable do + def reduce(collection, acc, fun) + def member?(collection, value) + def count(collection) +end diff --git a/lib/elixir_script/universal/integer.ex b/lib/elixir_script/universal/integer.ex new file mode 100644 index 00000000..9ced7e8f --- /dev/null +++ b/lib/elixir_script/universal/integer.ex @@ -0,0 +1,19 @@ +defmodule ElixirScript.Integer do + + def is_even(number) do + rem(number, 2) == 0 + end + + def is_odd(number) do + rem(number, 2) != 0 + end + + def to_char_list(number) do + to_char_list(number, 10) + end + + def to_char_list(number, base) do + number.toString(base).split('') + end + +end diff --git a/lib/elixir_script/universal/kernel.ex b/lib/elixir_script/universal/kernel.ex new file mode 100644 index 00000000..67cc02cd --- /dev/null +++ b/lib/elixir_script/universal/kernel.ex @@ -0,0 +1,181 @@ +defmodule ElixirScript.Kernel do + import Kernel, only: [defmodule: 2, def: 1, def: 2, defp: 2, + defmacro: 1, defmacro: 2, defmacrop: 2, ||: 2, !: 1, ++: 2, in: 2, &&: 2] + + defmacro if(condition, clauses) do + build_if(condition, clauses) + end + + defp build_if(condition, do: do_clause) do + build_if(condition, do: do_clause, else: nil) + end + + defp build_if(condition, do: do_clause, else: else_clause) do + quote do + case unquote(condition) do + x when x in [false, nil] -> + unquote(else_clause) + _ -> + unquote(do_clause) + end + end + end + + defmacro unless(condition, clauses) do + build_unless(condition, clauses) + end + + defp build_unless(condition, do: do_clause) do + build_unless(condition, do: do_clause, else: nil) + end + + defp build_unless(condition, do: do_clause, else: else_clause) do + quote do + if(unquote(condition), do: unquote(else_clause), else: unquote(do_clause)) + end + end + + def abs(number) do + Math.abs(number) + end + + def apply(fun, args) do + Elixir.Core.apply(fun, args) + end + + def apply(module, fun, args) do + fun = if Elixir.Core.is_atom(fun), do: Atom.to_string(fun), else: fun + Elixir.Core.apply(module, fun, args) + end + + def binary_part(binary, start, len) do + binary.substring(start, len) + end + + def hd(list) do + list[0] + end + + def tl(list) do + list.slice(1) + end + + def is_atom(term) do + Elixir.Core.is_atom(term) + end + + def is_binary(term) do + Elixir.Core.is_binary(term) + end + + def is_bitstring(term) do + Elixir.Core.is_bitstring(term) + end + + def is_boolean(term) do + Elixir.Core.is_boolean(term) + end + + def is_float(term) do + Elixir.Core.is_float(term) + end + + def is_function(term) do + Elixir.Core.is_function(term) + end + + def is_function(term, arity) do + Elixir.Core.is_function(term, arity) + end + + def is_integer(term) do + Elixir.Core.is_integer(term) + end + + def is_list(term) do + Elixir.Core.is_list(term) + end + + def is_number(term) do + Elixir.Core.is_integer(term) || Elixir.Core.is_float(term) + end + + def is_pid(term) do + Elixir.Core.is_pid(term) + end + + def is_tuple(term) do + Elixir.Core.is_tuple(term) + end + + def is_map(term) do + Elixir.Core.is_map(term) + end + + def length(term) do + Elixir.Core.size(term) + end + + def map_size(term) do + Elixir.Core.size(Object.keys(term)) + end + + def max(first, second) do + Math.max(first, second) + end + + def min(first, second) do + Math.min(first, second) + end + + def round(number) do + Math.round(number) + end + + def trunc(number) do + Math.floor(number) + end + + def tuple_size(tuple) do + Elixir.Core.size(tuple) + end + + def elem(tuple, index) do + Elixir.Core.apply(tuple, "get", [index]) + end + + def is_nil(term) do + Elixir.Core.is_nil(term) + end + + defmacro match?(left, right) do + quote do + case unquote(right) do + unquote(left) -> + true + _ -> + false + end + end + end + + defmacro to_string(arg) when Kernel.is_binary(arg) do + arg + end + + defmacro to_string(arg) do + quote do + String.Chars.to_string(unquote(arg)) + end + end + + defmacro left |> {fun, context, params} do + {fun, context, [left] ++ params } + end + + defmacro left in right do + quote do + Elixir.Core.contains(unquote(left), unquote(right)) + end + end +end diff --git a/lib/elixir_script/universal/macro/env.ex b/lib/elixir_script/universal/macro/env.ex new file mode 100644 index 00000000..d415657f --- /dev/null +++ b/lib/elixir_script/universal/macro/env.ex @@ -0,0 +1,19 @@ +defmodule ElixirScript.Macro.Env do + defstruct [ + module: nil, + file: nil, + line: 0, + function: nil, + context: nil, + aliases: [], + requires: [], + functions: [], + macros: [], + macro_aliases: [], + context_modules: [], + vars: [], + export_vars: nil, + lexical_tracker: nil, + caller: nil + ] +end diff --git a/lib/elixir_script/universal/string/chars.ex b/lib/elixir_script/universal/string/chars.ex new file mode 100644 index 00000000..50e12fcd --- /dev/null +++ b/lib/elixir_script/universal/string/chars.ex @@ -0,0 +1,47 @@ +defprotocol ElixirScript.String.Chars do + def to_string(item) +end + +defimpl ElixirScript.String.Chars, for: Atom do + def to_string(nil) do + "" + end + + def to_string(atom) do + Atom.to_string(atom) + end +end + +defimpl ElixirScript.String.Chars, for: BitString do + def to_string(thing) when is_binary(thing) do + thing + end + + def to_string(thing) do + thing.toString() + end +end + +defimpl ElixirScript.String.Chars, for: List do + def to_string(list) do + list.toString() + end +end + +defimpl ElixirScript.String.Chars, for: Tuple do + def to_string(tuple) do + tuple.toString() + end +end + +defimpl ElixirScript.String.Chars, for: Integer do + def to_string(integer) do + integer.toString() + end +end + +defimpl ElixirScript.String.Chars, for: Float do + def to_string(float) do + float.toString() + end +end diff --git a/lib/elixir_script/universal/tuple.ex b/lib/elixir_script/universal/tuple.ex new file mode 100644 index 00000000..98737499 --- /dev/null +++ b/lib/elixir_script/universal/tuple.ex @@ -0,0 +1,23 @@ +defmodule ElixirScript.Tuple do + + def duplicate(data, size) do + Elixir.Core.make_tuple(size, data) + end + + def to_list(tuple) do + tuple["value"] + end + + def insert_at(tuple, index, value) do + Elixir.Core.insert_at(tuple, index, value) + end + + def delete_at(tuple, index) do + Elixir.Core.delete_at(tuple, index) + end + + def append(tuple, value) do + Elixir.Core.new_tuple(to_list(tuple) ++ value) + end + +end diff --git a/lib/elixir_script/universal/view.ex b/lib/elixir_script/universal/view.ex new file mode 100644 index 00000000..e0d6b781 --- /dev/null +++ b/lib/elixir_script/universal/view.ex @@ -0,0 +1,78 @@ +defmodule ElixirScript.View do + @moduledoc """ + Defines a module to handle view state. Handles the diffing and patching + normally done manually using the `VDom` module. + + def render(id) do + Html.div [id: "hello"] do + Html.span do + "Hello" + end + end + end + + #Starts View state and renders initial view + {:ok, view} = View.start(:document.body, &render/1, ["hello"]) + + #Updates the view with the new args + View.render(view, ["world"]) + """ + + + @doc """ + Starts the View state. This will render the initial view using the + render_func and the args + """ + def start(dom_root, render_func, args) do + pid = Elixir.Core.global().processes.spawn() + + tree = render_func.apply(nil, args); + root_node = Elixir.VirtualDOM.create(tree); + + dom_root.appendChild(root_node); + + Elixir.Core.global().processes.put(pid, "state", { root_node, tree, render_func }); + { :ok, pid } + end + + def start(dom_root, render_func, args, options) do + pid = Elixir.Core.global().processes.spawn() + + if Elixir.Keyword.has_key?(options, :name) do + pid = Elixir.Core.global().processes.register(Elixir.Keyword.get(options, :name), pid) + end + + tree = render_func.apply(nil, args); + root_node = Elixir.VirtualDOM.create(tree); + + dom_root.appendChild(root_node); + + Elixir.Core.global().processes.put(pid, "state", { root_node, tree, render_func }) + { :ok, pid } + end + + @doc """ + Stops the View state + """ + def stop(view) do + Elixir.Core.global().processes.exit(view) + :ok + end + + @doc """ + Updates the view by passing the args to the render_func + """ + def render(view, args) do + { root_node, tree, render_func } = Elixir.Core.global().processes.get(view, "state") + + new_tree = render_func.apply(nil, args); + + patches = Elixir.VirtualDOM.diff(tree, new_tree) + root_node = Elixir.VirtualDOM.patch(root_node, patches) + + Elixir.Core.global().processes.put(view, "state", { root_node, new_tree, render_func }); + + :ok + end + +end diff --git a/mix.exs b/mix.exs index bbed44af..22f3ecd1 100644 --- a/mix.exs +++ b/mix.exs @@ -22,20 +22,19 @@ defmodule ElixirScript.Mixfile do def application do [ - applications: [:logger, :inflex, :estree] + applications: [:logger, :estree] ] end defp deps do [ - {:inflex, "~> 1.5" }, {:estree, "~> 2.0"}, {:shouldi, only: :test }, {:earmark, "~> 0.1", only: :dev }, {:ex_doc, "~> 0.10", only: :dev }, {:benchfella, "~> 0.2", only: :test}, {:excoveralls, "~> 0.4", only: :test}, - {:credo, "~> 0.1.0", only: [:dev, :test]} + {:credo, "~> 0.2.0", only: [:dev, :test]} ] end diff --git a/mix.lock b/mix.lock index 19126311..a001ef8b 100644 --- a/mix.lock +++ b/mix.lock @@ -1,7 +1,7 @@ %{"benchfella": {:hex, :benchfella, "0.3.0"}, "bunt": {:hex, :bunt, "0.1.4"}, "certifi": {:hex, :certifi, "0.3.0"}, - "credo": {:hex, :credo, "0.1.10"}, + "credo": {:hex, :credo, "0.2.2"}, "dogma": {:hex, :dogma, "0.0.7"}, "earmark": {:hex, :earmark, "0.1.19"}, "estree": {:hex, :estree, "2.1.1"}, diff --git a/priv/Elixir.js b/priv/Elixir.js index 12b52805..d697e731 100644 --- a/priv/Elixir.js +++ b/priv/Elixir.js @@ -1,27 +1,60 @@ -function call_property(item, property) { - if (property in item) { - item[property]; - if (item[property] instanceof Function) { - return item[property](); - } else { - return item[property]; - } - } else if (Symbol.for(property) in item) { - let prop = Symbol.for(property); - if (item[prop] instanceof Function) { - return item[prop](); - } else { - return item[prop]; - } +/* @flow */ + +class Mailbox { + + constructor() { + this.messages = []; } - throw new Error(`Property ${ property } not found in ${ item }`); + deliver(message) { + this.messages.push(message); + return message; + } + + get() { + return this.messages; + } + + isEmpty() { + return this.messages.length === 0; + } + + removeAt(index) { + this.messages.splice(index, 1); + } +} + +var States = { + NORMAL: Symbol.for("normal"), + KILL: Symbol.for("kill"), + SUSPEND: Symbol.for("suspend"), + CONTINUE: Symbol.for("continue"), + RECEIVE: Symbol.for("receive"), + SEND: Symbol.for("send"), + SLEEPING: Symbol.for("sleeping"), + RUNNING: Symbol.for("running"), + SUSPENDED: Symbol.for("suspended"), + STOPPED: Symbol.for("stopped"), + SLEEP: Symbol.for("sleep"), + EXIT: Symbol.for("exit"), + NOMATCH: Symbol.for("no_match") +}; + +class Process { + + constructor(pid, mailbox) { + this.pid = pid; + this.mailbox = mailbox; + this.status = States.STOPPED; + this.dict = {}; + } } class Tuple$1 { constructor(...args) { this.values = Object.freeze(args); + this.length = this.values.length; } get(index) { @@ -67,967 +100,1081 @@ class PID { class Integer$1 {} class Float {} -/* @flow */ +class ProcessSystem { -class Variable { + constructor() { + this.pids = new Map(); + this.mailboxes = new Map(); + this.names = new Map(); + this.links = new Map(); - constructor(name = null) { - this.name = name; + this.current_process = null; + this.suspended = new Map(); + + this.main_process_pid = this.spawn(); + this.set_current(this.main_process_pid); } -} -class Wildcard { - constructor() {} -} + spawn() { + return this.add_proc(false).pid; + } -class StartsWith { + spawn_link() { + return this.add_proc(true).pid; + } - constructor(prefix) { - this.prefix = prefix; + link(pid) { + this.links.get(this.pid()).add(pid); + this.links.get(pid).add(this.pid()); } -} -class Capture { + unlink(pid) { + this.links.get(this.pid()).delete(pid); + this.links.get(pid).delete(this.pid()); + } - constructor(value) { - this.value = value; + set_current(id) { + let pid = this.pidof(id); + if (pid !== null) { + this.current_process = this.pids.get(pid); + this.current_process.status = States.RUNNING; + } } -} -class HeadTail { - constructor() {} -} + add_proc(linked) { + let newpid = new PID(); + let mailbox = new Mailbox(); + let newproc = new Process(newpid, mailbox); -class Type { + this.pids.set(newpid, newproc); + this.mailboxes.set(newpid, mailbox); + this.links.set(newpid, new Set()); - constructor(type, objPattern = {}) { - this.type = type; - this.objPattern = objPattern; + if (linked) { + this.link(newpid); + } + + return newproc; } -} -class Bound { + remove_proc(pid) { + this.pids.delete(pid); + this.unregister(pid); - constructor(value) { - this.value = value; + if (this.links.has(pid)) { + for (let linkpid of this.links.get(pid)) { + this.links.get(linkpid).delete(pid); + } + + this.links.delete(pid); + } } -} -function variable(name = null) { - return new Variable(name); -} + exit(id) { + let pid = this.pidof(id); + this.remove_proc(id); + } -function wildcard() { - return new Wildcard(); -} + register(name, pid) { + if (!this.names.has(name)) { + this.names.set(name, pid); + return name; + } else { + throw new Error("Name is already registered to another process"); + } + } -function startsWith(prefix) { - return new StartsWith(prefix); -} + registered(name) { + return this.names.has(name) ? this.names.get(name) : null; + } -function capture(value) { - return new Capture(value); -} + unregister(pid) { + for (let name of this.names.keys()) { + if (this.names.has(name) && this.names.get(name) === pid) { + this.names.delete(name); + } + } + } -function headTail() { - return new HeadTail(); -} + pid() { + return this.current_process.pid; + } -function type(type, objPattern = {}) { - return new Type(type, objPattern); -} + pidof(id) { + if (id instanceof PID) { + return this.pids.has(id) ? id : null; + } else if (id instanceof Process) { + return id.pid; + } else { + let pid = this.registered(id); + if (pid === null) throw "Process name not registered: " + id + " (" + typeof id + ")"; + return pid; + } + } -function bound(value) { - return new Bound(value); -} + put(id, key, value) { + let pid = this.pidof(id); + let process = this.pids.get(pid); + process.dict[key] = value; + } -function is_number$1(value) { - return typeof value === 'number'; -} + get(id, key) { + let pid = this.pidof(id); + let process = this.pids.get(pid); -function is_string(value) { - return typeof value === 'string'; -} + if (key != null) { + return process.dict[key]; + } else { + return process.dict; + } + } -function is_boolean$1(value) { - return typeof value === 'boolean'; -} + get_keys(id) { + let pid = this.pidof(id); + let process = this.pids.get(pid); -function is_symbol(value) { - return typeof value === 'symbol'; -} + return Object.keys(process.dict); + } -function is_null(value) { - return value === null; -} + erase(id, key) { + let pid = this.pidof(id); + let process = this.pids.get(pid); -function is_undefined(value) { - return typeof value === 'undefined'; + if (key != null) { + delete process.dict[key]; + } else { + process.dict = {}; + } + } } -function is_function$1(value) { - return Object.prototype.toString.call(value) == '[object Function]'; -} +class BitString { + constructor(...args) { + this.raw_value = function () { + return Object.freeze(args); + }; -function is_variable(value) { - return value instanceof Variable; -} + this.value = Object.freeze(this.process(args)); + } -function is_wildcard(value) { - return value instanceof Wildcard; -} + get(index) { + return this.value[index]; + } -function is_headTail(value) { - return value instanceof HeadTail; -} + count() { + return this.value.length; + } -function is_capture(value) { - return value instanceof Capture; -} + [Symbol.iterator]() { + return this.value[Symbol.iterator](); + } -function is_type(value) { - return value instanceof Type; -} + toString() { + var i, + s = ""; + for (i = 0; i < this.count(); i++) { + if (s !== "") { + s += ", "; + } + s += this[i].toString(); + } -function is_startsWith(value) { - return value instanceof StartsWith; -} + return "<<" + s + ">>"; + } -function is_bound(value) { - return value instanceof Bound; -} + process() { + let processed_values = []; -function is_object(value) { - return typeof value === 'object'; -} + var i; + for (i = 0; i < this.raw_value().length; i++) { + let processed_value = this["process_" + this.raw_value()[i].type](this.raw_value()[i]); -function is_array(value) { - return Array.isArray(value); -} + for (let attr of this.raw_value()[i].attributes) { + processed_value = this["process_" + attr](processed_value); + } -var Checks = { - is_number: is_number$1, - is_string, - is_boolean: is_boolean$1, - is_symbol, - is_null, - is_undefined, - is_function: is_function$1, - is_variable, - is_wildcard, - is_headTail, - is_capture, - is_type, - is_startsWith, - is_bound, - is_object, - is_array -}; + processed_values = processed_values.concat(processed_value); + } -function resolveSymbol(pattern) { - return function (value) { - return Checks.is_symbol(value) && value === pattern; - }; -} + return processed_values; + } -function resolveString(pattern) { - return function (value) { - return Checks.is_string(value) && value === pattern; - }; -} + process_integer(value) { + return value.value; + } -function resolveNumber(pattern) { - return function (value) { - return Checks.is_number(value) && value === pattern; - }; -} + process_float(value) { + if (value.size === 64) { + return BitString.float64ToBytes(value.value); + } else if (value.size === 32) { + return BitString.float32ToBytes(value.value); + } + + throw new Error("Invalid size for float"); + } + + process_bitstring(value) { + return value.value.value; + } + + process_binary(value) { + return BitString.toUTF8Array(value.value); + } + + process_utf8(value) { + return BitString.toUTF8Array(value.value); + } + + process_utf16(value) { + return BitString.toUTF16Array(value.value); + } + + process_utf32(value) { + return BitString.toUTF32Array(value.value); + } + + process_signed(value) { + return new Uint8Array([value])[0]; + } + + process_unsigned(value) { + return value; + } + + process_native(value) { + return value; + } + + process_big(value) { + return value; + } + + process_little(value) { + return value.reverse(); + } + + process_size(value) { + return value; + } + + process_unit(value) { + return value; + } + + static integer(value) { + return BitString.wrap(value, { "type": "integer", "unit": 1, "size": 8 }); + } + + static float(value) { + return BitString.wrap(value, { "type": "float", "unit": 1, "size": 64 }); + } + + static bitstring(value) { + return BitString.wrap(value, { "type": "bitstring", "unit": 1, "size": value.length }); + } + + static bits(value) { + return BitString.bitstring(value); + } + + static binary(value) { + return BitString.wrap(value, { "type": "binary", "unit": 8, "size": value.length }); + } + + static bytes(value) { + return BitString.binary(value); + } + + static utf8(value) { + return BitString.wrap(value, { "type": "utf8" }); + } + + static utf16(value) { + return BitString.wrap(value, { "type": "utf16" }); + } + + static utf32(value) { + return BitString.wrap(value, { "type": "utf32" }); + } + + static signed(value) { + return BitString.wrap(value, {}, "signed"); + } + + static unsigned(value) { + return BitString.wrap(value, {}, "unsigned"); + } + + static native(value) { + return BitString.wrap(value, {}, "native"); + } + + static big(value) { + return BitString.wrap(value, {}, "big"); + } + + static little(value) { + return BitString.wrap(value, {}, "little"); + } + + static size(value, count) { + return BitString.wrap(value, { "size": count }); + } + + static unit(value, count) { + return BitString.wrap(value, { "unit": count }); + } + + static wrap(value, opt, new_attribute = null) { + let the_value = value; + + if (!(value instanceof Object)) { + the_value = { "value": value, "attributes": [] }; + } + + the_value = Object.assign(the_value, opt); + + if (new_attribute) { + the_value.attributes.push(new_attribute); + } + + return the_value; + } + + static toUTF8Array(str) { + var utf8 = []; + for (var i = 0; i < str.length; i++) { + var charcode = str.charCodeAt(i); + if (charcode < 128) { + utf8.push(charcode); + } else if (charcode < 2048) { + utf8.push(192 | charcode >> 6, 128 | charcode & 63); + } else if (charcode < 55296 || charcode >= 57344) { + utf8.push(224 | charcode >> 12, 128 | charcode >> 6 & 63, 128 | charcode & 63); + } + // surrogate pair + else { + i++; + // UTF-16 encodes 0x10000-0x10FFFF by + // subtracting 0x10000 and splitting the + // 20 bits of 0x0-0xFFFFF into two halves + charcode = 65536 + ((charcode & 1023) << 10 | str.charCodeAt(i) & 1023); + utf8.push(240 | charcode >> 18, 128 | charcode >> 12 & 63, 128 | charcode >> 6 & 63, 128 | charcode & 63); + } + } + return utf8; + } + + static toUTF16Array(str) { + var utf16 = []; + for (var i = 0; i < str.length; i++) { + var codePoint = str.codePointAt(i); + + if (codePoint <= 255) { + utf16.push(0); + utf16.push(codePoint); + } else { + utf16.push(codePoint >> 8 & 255); + utf16.push(codePoint & 255); + } + } + return utf16; + } + + static toUTF32Array(str) { + var utf32 = []; + for (var i = 0; i < str.length; i++) { + var codePoint = str.codePointAt(i); + + if (codePoint <= 255) { + utf32.push(0); + utf32.push(0); + utf32.push(0); + utf32.push(codePoint); + } else { + utf32.push(0); + utf32.push(0); + utf32.push(codePoint >> 8 & 255); + utf32.push(codePoint & 255); + } + } + return utf32; + } -function resolveBoolean(pattern) { - return function (value) { - return Checks.is_boolean(value) && value === pattern; - }; -} + //http://stackoverflow.com/questions/2003493/javascript-float-from-to-bits + static float32ToBytes(f) { + var bytes = []; -function resolveFunction(pattern) { - return function (value) { - return Checks.is_function(value) && value === pattern; - }; -} + var buf = new ArrayBuffer(4); + new Float32Array(buf)[0] = f; -function resolveNull(pattern) { - return function (value) { - return Checks.is_null(value); - }; -} + let intVersion = new Uint32Array(buf)[0]; -function resolveBound(pattern) { - return function (value, args) { - if (typeof value === typeof pattern.value && value === pattern.value) { - args.push(value); - return true; - } + bytes.push(intVersion >> 24 & 255); + bytes.push(intVersion >> 16 & 255); + bytes.push(intVersion >> 8 & 255); + bytes.push(intVersion & 255); - return false; - }; -} + return bytes; + } -function resolveWildcard() { - return function () { - return true; - }; -} + static float64ToBytes(f) { + var bytes = []; -function resolveVariable() { - return function (value, args) { - args.push(value); - return true; - }; -} + var buf = new ArrayBuffer(8); + new Float64Array(buf)[0] = f; -function resolveHeadTail() { - return function (value, args) { - if (!Checks.is_array(value) || value.length < 2) { - return false; - } + var intVersion1 = new Uint32Array(buf)[0]; + var intVersion2 = new Uint32Array(buf)[1]; - const head = value[0]; - const tail = value.slice(1); + bytes.push(intVersion2 >> 24 & 255); + bytes.push(intVersion2 >> 16 & 255); + bytes.push(intVersion2 >> 8 & 255); + bytes.push(intVersion2 & 255); - args.push(head); - args.push(tail); + bytes.push(intVersion1 >> 24 & 255); + bytes.push(intVersion1 >> 16 & 255); + bytes.push(intVersion1 >> 8 & 255); + bytes.push(intVersion1 & 255); - return true; - }; + return bytes; + } } -function resolveCapture(pattern) { - const matches = buildMatch(pattern.value); +/* @flow */ - return function (value, args) { - if (matches(value, args)) { - args.push(value); - return true; - } +class Variable { - return false; - }; + constructor(name = null) { + this.name = name; + } } -function resolveStartsWith(pattern) { - const prefix = pattern.prefix; - - return function (value, args) { - if (Checks.is_string(value) && value.startsWith(prefix)) { - args.push(value.substring(prefix.length)); - return true; - } - - return false; - }; +class Wildcard { + constructor() {} } -function resolveType(pattern) { - return function (value, args) { - if (value instanceof pattern.type) { - const matches = buildMatch(pattern.objPattern); - return matches(value, args) && args.push(value) > 0; - } +class StartsWith { - return false; - }; + constructor(prefix) { + this.prefix = prefix; + } } -function resolveArray(pattern) { - const matches = pattern.map(x => buildMatch(x)); +class Capture { - return function (value, args) { - if (!Checks.is_array(value) || value.length != pattern.length) { - return false; - } + constructor(value) { + this.value = value; + } +} - return value.every(function (v, i) { - return matches[i](value[i], args); - }); - }; +class HeadTail { + constructor() {} } -function resolveObject(pattern) { - let matches = {}; +class Type { - for (let key of Object.keys(pattern).concat(Object.getOwnPropertySymbols(pattern))) { - matches[key] = buildMatch(pattern[key]); + constructor(type, objPattern = {}) { + this.type = type; + this.objPattern = objPattern; } +} - return function (value, args) { - if (!Checks.is_object(value) || pattern.length > value.length) { - return false; - } - - for (let key of Object.keys(pattern).concat(Object.getOwnPropertySymbols(pattern))) { - if (!(key in value) || !matches[key](value[key], args)) { - return false; - } - } +class Bound { - return true; - }; + constructor(value) { + this.value = value; + } } -function resolveNoMatch() { - return function () { - return false; - }; +function variable(name = null) { + return new Variable(name); } -var Resolvers = { - resolveBound, - resolveWildcard, - resolveVariable, - resolveHeadTail, - resolveCapture, - resolveStartsWith, - resolveType, - resolveArray, - resolveObject, - resolveNoMatch, - resolveSymbol, - resolveString, - resolveNumber, - resolveBoolean, - resolveFunction, - resolveNull -}; - -function buildMatch(pattern) { - - if (Checks.is_variable(pattern)) { - return Resolvers.resolveVariable(pattern); - } +function wildcard() { + return new Wildcard(); +} - if (Checks.is_wildcard(pattern)) { - return Resolvers.resolveWildcard(pattern); - } +function startsWith(prefix) { + return new StartsWith(prefix); +} - if (Checks.is_undefined(pattern)) { - return Resolvers.resolveWildcard(pattern); - } +function capture(value) { + return new Capture(value); +} - if (Checks.is_headTail(pattern)) { - return Resolvers.resolveHeadTail(pattern); - } +function headTail() { + return new HeadTail(); +} - if (Checks.is_startsWith(pattern)) { - return Resolvers.resolveStartsWith(pattern); - } +function type(type, objPattern = {}) { + return new Type(type, objPattern); +} - if (Checks.is_capture(pattern)) { - return Resolvers.resolveCapture(pattern); - } +function bound(value) { + return new Bound(value); +} - if (Checks.is_bound(pattern)) { - return Resolvers.resolveBound(pattern); - } +function is_number$2(value) { + return typeof value === 'number'; +} - if (Checks.is_type(pattern)) { - return Resolvers.resolveType(pattern); - } +function is_string(value) { + return typeof value === 'string'; +} - if (Checks.is_array(pattern)) { - return Resolvers.resolveArray(pattern); - } +function is_boolean$2(value) { + return typeof value === 'boolean'; +} - if (Checks.is_number(pattern)) { - return Resolvers.resolveNumber(pattern); - } +function is_symbol(value) { + return typeof value === 'symbol'; +} - if (Checks.is_string(pattern)) { - return Resolvers.resolveString(pattern); - } +function is_null(value) { + return value === null; +} - if (Checks.is_boolean(pattern)) { - return Resolvers.resolveBoolean(pattern); - } +function is_undefined(value) { + return typeof value === 'undefined'; +} - if (Checks.is_symbol(pattern)) { - return Resolvers.resolveSymbol(pattern); - } +function is_function$2(value) { + return Object.prototype.toString.call(value) == '[object Function]'; +} - if (Checks.is_null(pattern)) { - return Resolvers.resolveNull(pattern); - } +function is_variable(value) { + return value instanceof Variable; +} - if (Checks.is_object(pattern)) { - return Resolvers.resolveObject(pattern); - } +function is_wildcard(value) { + return value instanceof Wildcard; +} - return Resolvers.resolveNoMatch(); +function is_headTail(value) { + return value instanceof HeadTail; } -class MatchError extends Error { - constructor(arg) { - super(); +function is_capture(value) { + return value instanceof Capture; +} - if (typeof arg === 'symbol') { - this.message = 'No match for: ' + arg.toString(); - } else if (Array.isArray(arg)) { - let mappedValues = arg.map(x => x.toString()); - this.message = 'No match for: ' + mappedValues; - } else { - this.message = 'No match for: ' + arg; - } +function is_type(value) { + return value instanceof Type; +} - this.stack = new Error().stack; - this.name = this.constructor.name; - } +function is_startsWith(value) { + return value instanceof StartsWith; } -class Case { +function is_bound(value) { + return value instanceof Bound; +} - constructor(pattern, fn, guard = () => true) { - this.pattern = buildMatch(pattern); - this.fn = fn; - this.guard = guard; - } +function is_object(value) { + return typeof value === 'object'; } -function make_case(pattern, fn, guard = () => true) { - return new Case(pattern, fn, guard); +function is_array(value) { + return Array.isArray(value); } -function defmatch(...cases) { - return function (...args) { - for (let processedCase of cases) { - let result = []; - if (processedCase.pattern(args, result) && processedCase.guard.apply(this, result)) { - return processedCase.fn.apply(this, result); - } - } +var Checks = { + is_number: is_number$2, + is_string, + is_boolean: is_boolean$2, + is_symbol, + is_null, + is_undefined, + is_function: is_function$2, + is_variable, + is_wildcard, + is_headTail, + is_capture, + is_type, + is_startsWith, + is_bound, + is_object, + is_array +}; - throw new MatchError(args); +function resolveSymbol(pattern) { + return function (value) { + return Checks.is_symbol(value) && value === pattern; }; } -function match(pattern, expr, guard = () => true) { - let result = []; - let processedPattern = buildMatch(pattern); - if (processedPattern(expr, result) && guard.apply(this, result)) { - return result; - } else { - throw new MatchError(expr); - } +function resolveString(pattern) { + return function (value) { + return Checks.is_string(value) && value === pattern; + }; } -function match_no_throw(pattern, expr, guard = () => true) { - try { - return match(pattern, expr, guard); - } catch (e) { - if (e instanceof MatchError) { - return null; - } +function resolveNumber(pattern) { + return function (value) { + return Checks.is_number(value) && value === pattern; + }; +} - throw e; - } +function resolveBoolean(pattern) { + return function (value) { + return Checks.is_boolean(value) && value === pattern; + }; } -var Patterns = { - defmatch, match, MatchError, match_no_throw, - variable, wildcard, startsWith, - capture, headTail, type, bound, Case, make_case -}; +function resolveFunction(pattern) { + return function (value) { + return Checks.is_function(value) && value === pattern; + }; +} -class BitString { - constructor(...args) { - this.raw_value = function () { - return Object.freeze(args); - }; +function resolveNull(pattern) { + return function (value) { + return Checks.is_null(value); + }; +} - this.value = Object.freeze(this.process(args)); - } +function resolveBound(pattern) { + return function (value, args) { + if (typeof value === typeof pattern.value && value === pattern.value) { + args.push(value); + return true; + } - get(index) { - return this.value[index]; - } + return false; + }; +} - count() { - return this.value.length; - } +function resolveWildcard() { + return function () { + return true; + }; +} - [Symbol.iterator]() { - return this.value[Symbol.iterator](); - } +function resolveVariable() { + return function (value, args) { + args.push(value); + return true; + }; +} - toString() { - var i, - s = ""; - for (i = 0; i < this.count(); i++) { - if (s !== "") { - s += ", "; - } - s += this[i].toString(); +function resolveHeadTail() { + return function (value, args) { + if (!Checks.is_array(value) || value.length < 2) { + return false; } - return "<<" + s + ">>"; - } + const head = value[0]; + const tail = value.slice(1); - process() { - let processed_values = []; + args.push(head); + args.push(tail); - var i; - for (i = 0; i < this.raw_value().length; i++) { - let processed_value = this["process_" + this.raw_value()[i].type](this.raw_value()[i]); + return true; + }; +} - for (let attr of this.raw_value()[i].attributes) { - processed_value = this["process_" + attr](processed_value); - } +function resolveCapture(pattern) { + const matches = buildMatch(pattern.value); - processed_values = processed_values.concat(processed_value); + return function (value, args) { + if (matches(value, args)) { + args.push(value); + return true; } - return processed_values; - } + return false; + }; +} - process_integer(value) { - return value.value; - } +function resolveStartsWith(pattern) { + const prefix = pattern.prefix; - process_float(value) { - if (value.size === 64) { - return BitString.float64ToBytes(value.value); - } else if (value.size === 32) { - return BitString.float32ToBytes(value.value); + return function (value, args) { + if (Checks.is_string(value) && value.startsWith(prefix)) { + args.push(value.substring(prefix.length)); + return true; } - throw new Error("Invalid size for float"); - } - - process_bitstring(value) { - return value.value.value; - } + return false; + }; +} - process_binary(value) { - return BitString.toUTF8Array(value.value); - } +function resolveType(pattern) { + return function (value, args) { + if (value instanceof pattern.type) { + const matches = buildMatch(pattern.objPattern); + return matches(value, args) && args.push(value) > 0; + } - process_utf8(value) { - return BitString.toUTF8Array(value.value); - } + return false; + }; +} - process_utf16(value) { - return BitString.toUTF16Array(value.value); - } +function resolveArray(pattern) { + const matches = pattern.map(x => buildMatch(x)); - process_utf32(value) { - return BitString.toUTF32Array(value.value); - } + return function (value, args) { + if (!Checks.is_array(value) || value.length != pattern.length) { + return false; + } - process_signed(value) { - return new Uint8Array([value])[0]; - } + return value.every(function (v, i) { + return matches[i](value[i], args); + }); + }; +} - process_unsigned(value) { - return value; - } +function resolveObject(pattern) { + let matches = {}; - process_native(value) { - return value; + for (let key of Object.keys(pattern).concat(Object.getOwnPropertySymbols(pattern))) { + matches[key] = buildMatch(pattern[key]); } - process_big(value) { - return value; - } + return function (value, args) { + if (!Checks.is_object(value) || pattern.length > value.length) { + return false; + } - process_little(value) { - return value.reverse(); - } + for (let key of Object.keys(pattern).concat(Object.getOwnPropertySymbols(pattern))) { + if (!(key in value) || !matches[key](value[key], args)) { + return false; + } + } - process_size(value) { - return value; - } + return true; + }; +} - process_unit(value) { - return value; - } +function resolveNoMatch() { + return function () { + return false; + }; +} - static integer(value) { - return BitString.wrap(value, { "type": "integer", "unit": 1, "size": 8 }); - } +var Resolvers = { + resolveBound, + resolveWildcard, + resolveVariable, + resolveHeadTail, + resolveCapture, + resolveStartsWith, + resolveType, + resolveArray, + resolveObject, + resolveNoMatch, + resolveSymbol, + resolveString, + resolveNumber, + resolveBoolean, + resolveFunction, + resolveNull +}; - static float(value) { - return BitString.wrap(value, { "type": "float", "unit": 1, "size": 64 }); - } +function buildMatch(pattern) { - static bitstring(value) { - return BitString.wrap(value, { "type": "bitstring", "unit": 1, "size": value.length }); + if (Checks.is_variable(pattern)) { + return Resolvers.resolveVariable(pattern); } - static bits(value) { - return BitString.bitstring(value); + if (Checks.is_wildcard(pattern)) { + return Resolvers.resolveWildcard(pattern); } - static binary(value) { - return BitString.wrap(value, { "type": "binary", "unit": 8, "size": value.length }); + if (Checks.is_undefined(pattern)) { + return Resolvers.resolveWildcard(pattern); } - static bytes(value) { - return BitString.binary(value); + if (Checks.is_headTail(pattern)) { + return Resolvers.resolveHeadTail(pattern); } - static utf8(value) { - return BitString.wrap(value, { "type": "utf8" }); + if (Checks.is_startsWith(pattern)) { + return Resolvers.resolveStartsWith(pattern); } - static utf16(value) { - return BitString.wrap(value, { "type": "utf16" }); + if (Checks.is_capture(pattern)) { + return Resolvers.resolveCapture(pattern); } - static utf32(value) { - return BitString.wrap(value, { "type": "utf32" }); + if (Checks.is_bound(pattern)) { + return Resolvers.resolveBound(pattern); } - static signed(value) { - return BitString.wrap(value, {}, "signed"); + if (Checks.is_type(pattern)) { + return Resolvers.resolveType(pattern); } - static unsigned(value) { - return BitString.wrap(value, {}, "unsigned"); + if (Checks.is_array(pattern)) { + return Resolvers.resolveArray(pattern); } - static native(value) { - return BitString.wrap(value, {}, "native"); + if (Checks.is_number(pattern)) { + return Resolvers.resolveNumber(pattern); } - static big(value) { - return BitString.wrap(value, {}, "big"); + if (Checks.is_string(pattern)) { + return Resolvers.resolveString(pattern); } - static little(value) { - return BitString.wrap(value, {}, "little"); + if (Checks.is_boolean(pattern)) { + return Resolvers.resolveBoolean(pattern); } - static size(value, count) { - return BitString.wrap(value, { "size": count }); + if (Checks.is_symbol(pattern)) { + return Resolvers.resolveSymbol(pattern); } - static unit(value, count) { - return BitString.wrap(value, { "unit": count }); + if (Checks.is_null(pattern)) { + return Resolvers.resolveNull(pattern); } - static wrap(value, opt, new_attribute = null) { - let the_value = value; - - if (!(value instanceof Object)) { - the_value = { "value": value, "attributes": [] }; - } - - the_value = Object.assign(the_value, opt); - - if (new_attribute) { - the_value.attributes.push(new_attribute); - } - - return the_value; + if (Checks.is_object(pattern)) { + return Resolvers.resolveObject(pattern); } - static toUTF8Array(str) { - var utf8 = []; - for (var i = 0; i < str.length; i++) { - var charcode = str.charCodeAt(i); - if (charcode < 128) { - utf8.push(charcode); - } else if (charcode < 2048) { - utf8.push(192 | charcode >> 6, 128 | charcode & 63); - } else if (charcode < 55296 || charcode >= 57344) { - utf8.push(224 | charcode >> 12, 128 | charcode >> 6 & 63, 128 | charcode & 63); - } - // surrogate pair - else { - i++; - // UTF-16 encodes 0x10000-0x10FFFF by - // subtracting 0x10000 and splitting the - // 20 bits of 0x0-0xFFFFF into two halves - charcode = 65536 + ((charcode & 1023) << 10 | str.charCodeAt(i) & 1023); - utf8.push(240 | charcode >> 18, 128 | charcode >> 12 & 63, 128 | charcode >> 6 & 63, 128 | charcode & 63); - } - } - return utf8; - } + return Resolvers.resolveNoMatch(); +} - static toUTF16Array(str) { - var utf16 = []; - for (var i = 0; i < str.length; i++) { - var codePoint = str.codePointAt(i); +class MatchError extends Error { + constructor(arg) { + super(); - if (codePoint <= 255) { - utf16.push(0); - utf16.push(codePoint); - } else { - utf16.push(codePoint >> 8 & 255); - utf16.push(codePoint & 255); - } + if (typeof arg === 'symbol') { + this.message = 'No match for: ' + arg.toString(); + } else if (Array.isArray(arg)) { + let mappedValues = arg.map(x => x.toString()); + this.message = 'No match for: ' + mappedValues; + } else { + this.message = 'No match for: ' + arg; } - return utf16; - } - - static toUTF32Array(str) { - var utf32 = []; - for (var i = 0; i < str.length; i++) { - var codePoint = str.codePointAt(i); - if (codePoint <= 255) { - utf32.push(0); - utf32.push(0); - utf32.push(0); - utf32.push(codePoint); - } else { - utf32.push(0); - utf32.push(0); - utf32.push(codePoint >> 8 & 255); - utf32.push(codePoint & 255); - } - } - return utf32; + this.stack = new Error().stack; + this.name = this.constructor.name; } +} - //http://stackoverflow.com/questions/2003493/javascript-float-from-to-bits - static float32ToBytes(f) { - var bytes = []; - - var buf = new ArrayBuffer(4); - new Float32Array(buf)[0] = f; - - let intVersion = new Uint32Array(buf)[0]; - - bytes.push(intVersion >> 24 & 255); - bytes.push(intVersion >> 16 & 255); - bytes.push(intVersion >> 8 & 255); - bytes.push(intVersion & 255); +class Case { - return bytes; + constructor(pattern, fn, guard = () => true) { + this.pattern = buildMatch(pattern); + this.fn = fn; + this.guard = guard; } +} - static float64ToBytes(f) { - var bytes = []; - - var buf = new ArrayBuffer(8); - new Float64Array(buf)[0] = f; - - var intVersion1 = new Uint32Array(buf)[0]; - var intVersion2 = new Uint32Array(buf)[1]; - - bytes.push(intVersion2 >> 24 & 255); - bytes.push(intVersion2 >> 16 & 255); - bytes.push(intVersion2 >> 8 & 255); - bytes.push(intVersion2 & 255); - - bytes.push(intVersion1 >> 24 & 255); - bytes.push(intVersion1 >> 16 & 255); - bytes.push(intVersion1 >> 8 & 255); - bytes.push(intVersion1 & 255); - - return bytes; - } +function make_case(pattern, fn, guard = () => true) { + return new Case(pattern, fn, guard); } -/* @flow */ +function defmatch(...cases) { + return function (...args) { + for (let processedCase of cases) { + let result = []; + if (processedCase.pattern(args, result) && processedCase.guard.apply(this, result)) { + return processedCase.fn.apply(this, result); + } + } -class Mailbox { + throw new MatchError(args); + }; +} - constructor() { - this.messages = []; +function match(pattern, expr, guard = () => true) { + let result = []; + let processedPattern = buildMatch(pattern); + if (processedPattern(expr, result) && guard.apply(this, result)) { + return result; + } else { + throw new MatchError(expr); } +} - deliver(message) { - this.messages.push(message); - return message; - } +function match_no_throw(pattern, expr, guard = () => true) { + try { + return match(pattern, expr, guard); + } catch (e) { + if (e instanceof MatchError) { + return null; + } - get() { - return this.messages; + throw e; } +} - isEmpty() { - return this.messages.length === 0; - } +var Patterns = { + defmatch, match, MatchError, match_no_throw, + variable, wildcard, startsWith, + capture, headTail, type, bound, Case, make_case +}; - removeAt(index) { - this.messages.splice(index, 1); +function call_property(item, property) { + if (property in item) { + item[property]; + if (item[property] instanceof Function) { + return item[property](); + } else { + return item[property]; + } + } else if (Symbol.for(property) in item) { + let prop = Symbol.for(property); + if (item[prop] instanceof Function) { + return item[prop](); + } else { + return item[prop]; + } } + + throw new Error(`Property ${ property } not found in ${ item }`); } -var States = { - NORMAL: Symbol.for("normal"), - KILL: Symbol.for("kill"), - SUSPEND: Symbol.for("suspend"), - CONTINUE: Symbol.for("continue"), - RECEIVE: Symbol.for("receive"), - SEND: Symbol.for("send"), - SLEEPING: Symbol.for("sleeping"), - RUNNING: Symbol.for("running"), - SUSPENDED: Symbol.for("suspended"), - STOPPED: Symbol.for("stopped"), - SLEEP: Symbol.for("sleep"), - EXIT: Symbol.for("exit"), - NOMATCH: Symbol.for("no_match") -}; +function is_instance_of(value, type) { + return value instanceof type; +} -class Process { +function size$3(term) { + return term.length; +} - constructor(pid, mailbox) { - this.pid = pid; - this.mailbox = mailbox; - this.status = States.STOPPED; - this.dict = {}; - } +function is_nil$1(x) { + return x === null; } -class ProcessSystem { +function is_atom$1(x) { + return typeof x === 'symbol'; +} - constructor() { - this.pids = new Map(); - this.mailboxes = new Map(); - this.names = new Map(); - this.links = new Map(); +function is_binary$1(x) { + return typeof x === 'string' || x instanceof String; +} - this.current_process = null; - this.suspended = new Map(); +function is_boolean$1(x) { + return typeof x === 'boolean' || x instanceof Boolean; +} - this.main_process_pid = this.spawn(); - this.set_current(this.main_process_pid); - } +function is_function$1(x, arity = -1) { + return typeof x === 'function' || x instanceof Function; +} - spawn() { - return this.add_proc(false).pid; - } +function is_float$1(x) { + return is_number$1(x) && !Number.isInteger(x); +} - spawn_link() { - return this.add_proc(true).pid; - } +function is_integer$1(x) { + return Number.isInteger(x); +} - link(pid) { - this.links.get(this.pid()).add(pid); - this.links.get(pid).add(this.pid()); - } +function is_list$1(x) { + return x instanceof Array; +} - unlink(pid) { - this.links.get(this.pid()).delete(pid); - this.links.get(pid).delete(this.pid()); - } +function is_map$1(x) { + return typeof x === 'object' || x instanceof Object; +} - set_current(id) { - let pid = this.pidof(id); - if (pid !== null) { - this.current_process = this.pids.get(pid); - this.current_process.status = States.RUNNING; - } - } +function is_number$1(x) { + return typeof x === 'number'; +} - add_proc(linked) { - let newpid = new PID(); - let mailbox = new Mailbox(); - let newproc = new Process(newpid, mailbox); +function is_tuple$1(x) { + return x instanceof Tuple$1; +} - this.pids.set(newpid, newproc); - this.mailboxes.set(newpid, mailbox); - this.links.set(newpid, new Set()); +function is_pid$1(x) { + return x instanceof PID; +} - if (linked) { - this.link(newpid); - } +function is_port$1(x) { + return false; +} - return newproc; - } +function is_reference$1(x) { + return false; +} - remove_proc(pid) { - this.pids.delete(pid); - this.unregister(pid); +function is_bitstring$1(x) { + return is_binary$1(x) || x instanceof BitString; +} - if (this.links.has(pid)) { - for (let linkpid of this.links.get(pid)) { - this.links.get(linkpid).delete(pid); - } +function add(one, two) { + return one + two; +} - this.links.delete(pid); - } - } +function subtract(one, two) { + return one + two; +} - exit(id) { - let pid = this.pidof(id); - this.remove_proc(id); - } +function multiply(one, two) { + return one + two; +} - register(name, pid) { - if (!this.names.has(name)) { - this.names.set(name, pid); - return name; - } else { - throw new Error("Name is already registered to another process"); - } - } +function divide(one, two) { + return one + two; +} - registered(name) { - return this.names.has(name) ? this.names.get(name) : null; - } +function remainder(one, two) { + return one + two; +} - unregister(pid) { - for (let name of this.names.keys()) { - if (this.names.has(name) && this.names.get(name) === pid) { - this.names.delete(name); - } - } +function apply$1(...args) { + if (args.length === 2) { + args[0].apply(null, args.slice(1)); + } else { + args[0][args[1]].apply(null, args.slice(2)); } +} - pid() { - return this.current_process.pid; - } +function new_tuple(args) { + return new Tuple$1(...args); +} - pidof(id) { - if (id instanceof PID) { - return this.pids.has(id) ? id : null; - } else if (id instanceof Process) { - return id.pid; - } else { - let pid = this.registered(id); - if (pid === null) throw "Process name not registered: " + id + " (" + typeof id + ")"; - return pid; - } - } +function duplicate$2(data, size) { + let array = []; - put(id, key, value) { - let pid = this.pidof(id); - let process = this.pids.get(pid); - process.dict[key] = value; + for (var i = size - 1; i >= 0; i--) { + array.push(data); } - get(id, key) { - let pid = this.pidof(id); - let process = this.pids.get(pid); + return array; +} - if (key != null) { - return process.dict[key]; - } else { - return process.dict; +function contains(left, right) { + for (let x of right) { + if (Patterns.match_no_throw(left, x) != null) { + return true; } } - get_keys(id) { - let pid = this.pidof(id); - let process = this.pids.get(pid); + return false; +} - return Object.keys(process.dict).concat(Object.getOwnPropertySymbols(process.dict)); +function reverse$1(list) { + return list.concat([]).reverse(); +} + +function get_global() { + if (typeof self !== 'undefined') { + return self; + } else if (typeof global !== 'undefined') { + return global; } - erase(id, key) { - let pid = this.pidof(id); - let process = this.pids.get(pid); + throw 'No global state found'; +} - if (key != null) { - delete process.dict[key]; - } else { - process.dict = {}; - } - } +function concat_lists(left, right) { + return left.concat(right); +} + +function prepend_to_list(list, item) { + return [item].concat(list); } +get_global().processes = get_global().processes || new ProcessSystem(); + + + var C = Object.freeze({ ProcessSystem: ProcessSystem, Tuple: Tuple$1, @@ -1036,7 +1183,37 @@ var C = Object.freeze({ Patterns: Patterns, Integer: Integer$1, Float: Float, - call_property: call_property + call_property: call_property, + is_instance_of: is_instance_of, + size: size$3, + is_nil: is_nil$1, + is_atom: is_atom$1, + is_binary: is_binary$1, + is_boolean: is_boolean$1, + is_function: is_function$1, + is_float: is_float$1, + is_integer: is_integer$1, + is_list: is_list$1, + is_map: is_map$1, + is_number: is_number$1, + is_tuple: is_tuple$1, + is_pid: is_pid$1, + is_port: is_port$1, + is_reference: is_reference$1, + is_bitstring: is_bitstring$1, + add: add, + subtract: subtract, + multiply: multiply, + divide: divide, + remainder: remainder, + apply: apply$1, + new_tuple: new_tuple, + duplicate: duplicate$2, + contains: contains, + reverse: reverse$1, + get_global: get_global, + concat_lists: concat_lists, + prepend_to_list: prepend_to_list }); let Enum = { @@ -1187,7 +1364,7 @@ let Enum = { return Kernel.SpecialForms.tuple(mapped, the_acc); }, - member: function (collection, value) { + member__qmark__: function (collection, value) { return collection.includes(value); }, @@ -2440,6 +2617,7 @@ function decode64(data) { } catch (e) { return Kernel.SpecialForms.atom('error'); } + return btoa(data); } @@ -4561,9 +4739,7 @@ var view = { render }; -self.processes = self.processes || new ProcessSystem(); - const Core = C; export { Core, Kernel, Atom, Enum, Integer, List, Range, Tuple, Agent, Keyword, base as Base, String$1 as String, bitwise as Bitwise, Enumerable, Collectable, Inspect, map as Map, set as Set, MapSet, VirtualDOM, view as View }; -//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiIiwic291cmNlcyI6WyJFbGl4aXIuanMiXSwic291cmNlc0NvbnRlbnQiOlsiZnVuY3Rpb24gY2FsbF9wcm9wZXJ0eShpdGVtLCBwcm9wZXJ0eSkge1xuICBpZiAocHJvcGVydHkgaW4gaXRlbSkge1xuICAgIGl0ZW1bcHJvcGVydHldO1xuICAgIGlmIChpdGVtW3Byb3BlcnR5XSBpbnN0YW5jZW9mIEZ1bmN0aW9uKSB7XG4gICAgICByZXR1cm4gaXRlbVtwcm9wZXJ0eV0oKTtcbiAgICB9IGVsc2Uge1xuICAgICAgcmV0dXJuIGl0ZW1bcHJvcGVydHldO1xuICAgIH1cbiAgfSBlbHNlIGlmIChTeW1ib2wuZm9yKHByb3BlcnR5KSBpbiBpdGVtKSB7XG4gICAgbGV0IHByb3AgPSBTeW1ib2wuZm9yKHByb3BlcnR5KTtcbiAgICBpZiAoaXRlbVtwcm9wXSBpbnN0YW5jZW9mIEZ1bmN0aW9uKSB7XG4gICAgICByZXR1cm4gaXRlbVtwcm9wXSgpO1xuICAgIH0gZWxzZSB7XG4gICAgICByZXR1cm4gaXRlbVtwcm9wXTtcbiAgICB9XG4gIH1cblxuICB0aHJvdyBuZXcgRXJyb3IoYFByb3BlcnR5ICR7IHByb3BlcnR5IH0gbm90IGZvdW5kIGluICR7IGl0ZW0gfWApO1xufVxuXG5jbGFzcyBUdXBsZSQxIHtcblxuICBjb25zdHJ1Y3RvciguLi5hcmdzKSB7XG4gICAgdGhpcy52YWx1ZXMgPSBPYmplY3QuZnJlZXplKGFyZ3MpO1xuICB9XG5cbiAgZ2V0KGluZGV4KSB7XG4gICAgcmV0dXJuIHRoaXMudmFsdWVzW2luZGV4XTtcbiAgfVxuXG4gIGNvdW50KCkge1xuICAgIHJldHVybiB0aGlzLnZhbHVlcy5sZW5ndGg7XG4gIH1cblxuICBbU3ltYm9sLml0ZXJhdG9yXSgpIHtcbiAgICByZXR1cm4gdGhpcy52YWx1ZXNbU3ltYm9sLml0ZXJhdG9yXSgpO1xuICB9XG5cbiAgdG9TdHJpbmcoKSB7XG4gICAgdmFyIGksXG4gICAgICAgIHMgPSBcIlwiO1xuICAgIGZvciAoaSA9IDA7IGkgPCB0aGlzLnZhbHVlcy5sZW5ndGg7IGkrKykge1xuICAgICAgaWYgKHMgIT09IFwiXCIpIHtcbiAgICAgICAgcyArPSBcIiwgXCI7XG4gICAgICB9XG4gICAgICBzICs9IHRoaXMudmFsdWVzW2ldLnRvU3RyaW5nKCk7XG4gICAgfVxuXG4gICAgcmV0dXJuIFwie1wiICsgcyArIFwifVwiO1xuICB9XG5cbn1cblxubGV0IHByb2Nlc3NfY291bnRlciA9IC0xO1xuXG5jbGFzcyBQSUQge1xuICBjb25zdHJ1Y3RvcigpIHtcbiAgICBwcm9jZXNzX2NvdW50ZXIgPSBwcm9jZXNzX2NvdW50ZXIgKyAxO1xuICAgIHRoaXMuaWQgPSBwcm9jZXNzX2NvdW50ZXI7XG4gIH1cblxuICB0b1N0cmluZygpIHtcbiAgICByZXR1cm4gXCJQSUQjPDAuXCIgKyB0aGlzLmlkICsgXCIuMD5cIjtcbiAgfVxufVxuXG5jbGFzcyBJbnRlZ2VyJDEge31cbmNsYXNzIEZsb2F0IHt9XG5cbi8qIEBmbG93ICovXG5cbmNsYXNzIFZhcmlhYmxlIHtcblxuICBjb25zdHJ1Y3RvcihuYW1lID0gbnVsbCkge1xuICAgIHRoaXMubmFtZSA9IG5hbWU7XG4gIH1cbn1cblxuY2xhc3MgV2lsZGNhcmQge1xuICBjb25zdHJ1Y3RvcigpIHt9XG59XG5cbmNsYXNzIFN0YXJ0c1dpdGgge1xuXG4gIGNvbnN0cnVjdG9yKHByZWZpeCkge1xuICAgIHRoaXMucHJlZml4ID0gcHJlZml4O1xuICB9XG59XG5cbmNsYXNzIENhcHR1cmUge1xuXG4gIGNvbnN0cnVjdG9yKHZhbHVlKSB7XG4gICAgdGhpcy52YWx1ZSA9IHZhbHVlO1xuICB9XG59XG5cbmNsYXNzIEhlYWRUYWlsIHtcbiAgY29uc3RydWN0b3IoKSB7fVxufVxuXG5jbGFzcyBUeXBlIHtcblxuICBjb25zdHJ1Y3Rvcih0eXBlLCBvYmpQYXR0ZXJuID0ge30pIHtcbiAgICB0aGlzLnR5cGUgPSB0eXBlO1xuICAgIHRoaXMub2JqUGF0dGVybiA9IG9ialBhdHRlcm47XG4gIH1cbn1cblxuY2xhc3MgQm91bmQge1xuXG4gIGNvbnN0cnVjdG9yKHZhbHVlKSB7XG4gICAgdGhpcy52YWx1ZSA9IHZhbHVlO1xuICB9XG59XG5cbmZ1bmN0aW9uIHZhcmlhYmxlKG5hbWUgPSBudWxsKSB7XG4gIHJldHVybiBuZXcgVmFyaWFibGUobmFtZSk7XG59XG5cbmZ1bmN0aW9uIHdpbGRjYXJkKCkge1xuICByZXR1cm4gbmV3IFdpbGRjYXJkKCk7XG59XG5cbmZ1bmN0aW9uIHN0YXJ0c1dpdGgocHJlZml4KSB7XG4gIHJldHVybiBuZXcgU3RhcnRzV2l0aChwcmVmaXgpO1xufVxuXG5mdW5jdGlvbiBjYXB0dXJlKHZhbHVlKSB7XG4gIHJldHVybiBuZXcgQ2FwdHVyZSh2YWx1ZSk7XG59XG5cbmZ1bmN0aW9uIGhlYWRUYWlsKCkge1xuICByZXR1cm4gbmV3IEhlYWRUYWlsKCk7XG59XG5cbmZ1bmN0aW9uIHR5cGUodHlwZSwgb2JqUGF0dGVybiA9IHt9KSB7XG4gIHJldHVybiBuZXcgVHlwZSh0eXBlLCBvYmpQYXR0ZXJuKTtcbn1cblxuZnVuY3Rpb24gYm91bmQodmFsdWUpIHtcbiAgcmV0dXJuIG5ldyBCb3VuZCh2YWx1ZSk7XG59XG5cbmZ1bmN0aW9uIGlzX251bWJlciQxKHZhbHVlKSB7XG4gIHJldHVybiB0eXBlb2YgdmFsdWUgPT09ICdudW1iZXInO1xufVxuXG5mdW5jdGlvbiBpc19zdHJpbmcodmFsdWUpIHtcbiAgcmV0dXJuIHR5cGVvZiB2YWx1ZSA9PT0gJ3N0cmluZyc7XG59XG5cbmZ1bmN0aW9uIGlzX2Jvb2xlYW4kMSh2YWx1ZSkge1xuICByZXR1cm4gdHlwZW9mIHZhbHVlID09PSAnYm9vbGVhbic7XG59XG5cbmZ1bmN0aW9uIGlzX3N5bWJvbCh2YWx1ZSkge1xuICByZXR1cm4gdHlwZW9mIHZhbHVlID09PSAnc3ltYm9sJztcbn1cblxuZnVuY3Rpb24gaXNfbnVsbCh2YWx1ZSkge1xuICByZXR1cm4gdmFsdWUgPT09IG51bGw7XG59XG5cbmZ1bmN0aW9uIGlzX3VuZGVmaW5lZCh2YWx1ZSkge1xuICByZXR1cm4gdHlwZW9mIHZhbHVlID09PSAndW5kZWZpbmVkJztcbn1cblxuZnVuY3Rpb24gaXNfZnVuY3Rpb24kMSh2YWx1ZSkge1xuICByZXR1cm4gT2JqZWN0LnByb3RvdHlwZS50b1N0cmluZy5jYWxsKHZhbHVlKSA9PSAnW29iamVjdCBGdW5jdGlvbl0nO1xufVxuXG5mdW5jdGlvbiBpc192YXJpYWJsZSh2YWx1ZSkge1xuICByZXR1cm4gdmFsdWUgaW5zdGFuY2VvZiBWYXJpYWJsZTtcbn1cblxuZnVuY3Rpb24gaXNfd2lsZGNhcmQodmFsdWUpIHtcbiAgcmV0dXJuIHZhbHVlIGluc3RhbmNlb2YgV2lsZGNhcmQ7XG59XG5cbmZ1bmN0aW9uIGlzX2hlYWRUYWlsKHZhbHVlKSB7XG4gIHJldHVybiB2YWx1ZSBpbnN0YW5jZW9mIEhlYWRUYWlsO1xufVxuXG5mdW5jdGlvbiBpc19jYXB0dXJlKHZhbHVlKSB7XG4gIHJldHVybiB2YWx1ZSBpbnN0YW5jZW9mIENhcHR1cmU7XG59XG5cbmZ1bmN0aW9uIGlzX3R5cGUodmFsdWUpIHtcbiAgcmV0dXJuIHZhbHVlIGluc3RhbmNlb2YgVHlwZTtcbn1cblxuZnVuY3Rpb24gaXNfc3RhcnRzV2l0aCh2YWx1ZSkge1xuICByZXR1cm4gdmFsdWUgaW5zdGFuY2VvZiBTdGFydHNXaXRoO1xufVxuXG5mdW5jdGlvbiBpc19ib3VuZCh2YWx1ZSkge1xuICByZXR1cm4gdmFsdWUgaW5zdGFuY2VvZiBCb3VuZDtcbn1cblxuZnVuY3Rpb24gaXNfb2JqZWN0KHZhbHVlKSB7XG4gIHJldHVybiB0eXBlb2YgdmFsdWUgPT09ICdvYmplY3QnO1xufVxuXG5mdW5jdGlvbiBpc19hcnJheSh2YWx1ZSkge1xuICByZXR1cm4gQXJyYXkuaXNBcnJheSh2YWx1ZSk7XG59XG5cbnZhciBDaGVja3MgPSB7XG4gIGlzX251bWJlcjogaXNfbnVtYmVyJDEsXG4gIGlzX3N0cmluZyxcbiAgaXNfYm9vbGVhbjogaXNfYm9vbGVhbiQxLFxuICBpc19zeW1ib2wsXG4gIGlzX251bGwsXG4gIGlzX3VuZGVmaW5lZCxcbiAgaXNfZnVuY3Rpb246IGlzX2Z1bmN0aW9uJDEsXG4gIGlzX3ZhcmlhYmxlLFxuICBpc193aWxkY2FyZCxcbiAgaXNfaGVhZFRhaWwsXG4gIGlzX2NhcHR1cmUsXG4gIGlzX3R5cGUsXG4gIGlzX3N0YXJ0c1dpdGgsXG4gIGlzX2JvdW5kLFxuICBpc19vYmplY3QsXG4gIGlzX2FycmF5XG59O1xuXG5mdW5jdGlvbiByZXNvbHZlU3ltYm9sKHBhdHRlcm4pIHtcbiAgcmV0dXJuIGZ1bmN0aW9uICh2YWx1ZSkge1xuICAgIHJldHVybiBDaGVja3MuaXNfc3ltYm9sKHZhbHVlKSAmJiB2YWx1ZSA9PT0gcGF0dGVybjtcbiAgfTtcbn1cblxuZnVuY3Rpb24gcmVzb2x2ZVN0cmluZyhwYXR0ZXJuKSB7XG4gIHJldHVybiBmdW5jdGlvbiAodmFsdWUpIHtcbiAgICByZXR1cm4gQ2hlY2tzLmlzX3N0cmluZyh2YWx1ZSkgJiYgdmFsdWUgPT09IHBhdHRlcm47XG4gIH07XG59XG5cbmZ1bmN0aW9uIHJlc29sdmVOdW1iZXIocGF0dGVybikge1xuICByZXR1cm4gZnVuY3Rpb24gKHZhbHVlKSB7XG4gICAgcmV0dXJuIENoZWNrcy5pc19udW1iZXIodmFsdWUpICYmIHZhbHVlID09PSBwYXR0ZXJuO1xuICB9O1xufVxuXG5mdW5jdGlvbiByZXNvbHZlQm9vbGVhbihwYXR0ZXJuKSB7XG4gIHJldHVybiBmdW5jdGlvbiAodmFsdWUpIHtcbiAgICByZXR1cm4gQ2hlY2tzLmlzX2Jvb2xlYW4odmFsdWUpICYmIHZhbHVlID09PSBwYXR0ZXJuO1xuICB9O1xufVxuXG5mdW5jdGlvbiByZXNvbHZlRnVuY3Rpb24ocGF0dGVybikge1xuICByZXR1cm4gZnVuY3Rpb24gKHZhbHVlKSB7XG4gICAgcmV0dXJuIENoZWNrcy5pc19mdW5jdGlvbih2YWx1ZSkgJiYgdmFsdWUgPT09IHBhdHRlcm47XG4gIH07XG59XG5cbmZ1bmN0aW9uIHJlc29sdmVOdWxsKHBhdHRlcm4pIHtcbiAgcmV0dXJuIGZ1bmN0aW9uICh2YWx1ZSkge1xuICAgIHJldHVybiBDaGVja3MuaXNfbnVsbCh2YWx1ZSk7XG4gIH07XG59XG5cbmZ1bmN0aW9uIHJlc29sdmVCb3VuZChwYXR0ZXJuKSB7XG4gIHJldHVybiBmdW5jdGlvbiAodmFsdWUsIGFyZ3MpIHtcbiAgICBpZiAodHlwZW9mIHZhbHVlID09PSB0eXBlb2YgcGF0dGVybi52YWx1ZSAmJiB2YWx1ZSA9PT0gcGF0dGVybi52YWx1ZSkge1xuICAgICAgYXJncy5wdXNoKHZhbHVlKTtcbiAgICAgIHJldHVybiB0cnVlO1xuICAgIH1cblxuICAgIHJldHVybiBmYWxzZTtcbiAgfTtcbn1cblxuZnVuY3Rpb24gcmVzb2x2ZVdpbGRjYXJkKCkge1xuICByZXR1cm4gZnVuY3Rpb24gKCkge1xuICAgIHJldHVybiB0cnVlO1xuICB9O1xufVxuXG5mdW5jdGlvbiByZXNvbHZlVmFyaWFibGUoKSB7XG4gIHJldHVybiBmdW5jdGlvbiAodmFsdWUsIGFyZ3MpIHtcbiAgICBhcmdzLnB1c2godmFsdWUpO1xuICAgIHJldHVybiB0cnVlO1xuICB9O1xufVxuXG5mdW5jdGlvbiByZXNvbHZlSGVhZFRhaWwoKSB7XG4gIHJldHVybiBmdW5jdGlvbiAodmFsdWUsIGFyZ3MpIHtcbiAgICBpZiAoIUNoZWNrcy5pc19hcnJheSh2YWx1ZSkgfHwgdmFsdWUubGVuZ3RoIDwgMikge1xuICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH1cblxuICAgIGNvbnN0IGhlYWQgPSB2YWx1ZVswXTtcbiAgICBjb25zdCB0YWlsID0gdmFsdWUuc2xpY2UoMSk7XG5cbiAgICBhcmdzLnB1c2goaGVhZCk7XG4gICAgYXJncy5wdXNoKHRhaWwpO1xuXG4gICAgcmV0dXJuIHRydWU7XG4gIH07XG59XG5cbmZ1bmN0aW9uIHJlc29sdmVDYXB0dXJlKHBhdHRlcm4pIHtcbiAgY29uc3QgbWF0Y2hlcyA9IGJ1aWxkTWF0Y2gocGF0dGVybi52YWx1ZSk7XG5cbiAgcmV0dXJuIGZ1bmN0aW9uICh2YWx1ZSwgYXJncykge1xuICAgIGlmIChtYXRjaGVzKHZhbHVlLCBhcmdzKSkge1xuICAgICAgYXJncy5wdXNoKHZhbHVlKTtcbiAgICAgIHJldHVybiB0cnVlO1xuICAgIH1cblxuICAgIHJldHVybiBmYWxzZTtcbiAgfTtcbn1cblxuZnVuY3Rpb24gcmVzb2x2ZVN0YXJ0c1dpdGgocGF0dGVybikge1xuICBjb25zdCBwcmVmaXggPSBwYXR0ZXJuLnByZWZpeDtcblxuICByZXR1cm4gZnVuY3Rpb24gKHZhbHVlLCBhcmdzKSB7XG4gICAgaWYgKENoZWNrcy5pc19zdHJpbmcodmFsdWUpICYmIHZhbHVlLnN0YXJ0c1dpdGgocHJlZml4KSkge1xuICAgICAgYXJncy5wdXNoKHZhbHVlLnN1YnN0cmluZyhwcmVmaXgubGVuZ3RoKSk7XG4gICAgICByZXR1cm4gdHJ1ZTtcbiAgICB9XG5cbiAgICByZXR1cm4gZmFsc2U7XG4gIH07XG59XG5cbmZ1bmN0aW9uIHJlc29sdmVUeXBlKHBhdHRlcm4pIHtcbiAgcmV0dXJuIGZ1bmN0aW9uICh2YWx1ZSwgYXJncykge1xuICAgIGlmICh2YWx1ZSBpbnN0YW5jZW9mIHBhdHRlcm4udHlwZSkge1xuICAgICAgY29uc3QgbWF0Y2hlcyA9IGJ1aWxkTWF0Y2gocGF0dGVybi5vYmpQYXR0ZXJuKTtcbiAgICAgIHJldHVybiBtYXRjaGVzKHZhbHVlLCBhcmdzKSAmJiBhcmdzLnB1c2godmFsdWUpID4gMDtcbiAgICB9XG5cbiAgICByZXR1cm4gZmFsc2U7XG4gIH07XG59XG5cbmZ1bmN0aW9uIHJlc29sdmVBcnJheShwYXR0ZXJuKSB7XG4gIGNvbnN0IG1hdGNoZXMgPSBwYXR0ZXJuLm1hcCh4ID0+IGJ1aWxkTWF0Y2goeCkpO1xuXG4gIHJldHVybiBmdW5jdGlvbiAodmFsdWUsIGFyZ3MpIHtcbiAgICBpZiAoIUNoZWNrcy5pc19hcnJheSh2YWx1ZSkgfHwgdmFsdWUubGVuZ3RoICE9IHBhdHRlcm4ubGVuZ3RoKSB7XG4gICAgICByZXR1cm4gZmFsc2U7XG4gICAgfVxuXG4gICAgcmV0dXJuIHZhbHVlLmV2ZXJ5KGZ1bmN0aW9uICh2LCBpKSB7XG4gICAgICByZXR1cm4gbWF0Y2hlc1tpXSh2YWx1ZVtpXSwgYXJncyk7XG4gICAgfSk7XG4gIH07XG59XG5cbmZ1bmN0aW9uIHJlc29sdmVPYmplY3QocGF0dGVybikge1xuICBsZXQgbWF0Y2hlcyA9IHt9O1xuXG4gIGZvciAobGV0IGtleSBvZiBPYmplY3Qua2V5cyhwYXR0ZXJuKSkge1xuICAgIG1hdGNoZXNba2V5XSA9IGJ1aWxkTWF0Y2gocGF0dGVybltrZXldKTtcbiAgfVxuXG4gIHJldHVybiBmdW5jdGlvbiAodmFsdWUsIGFyZ3MpIHtcbiAgICBpZiAoIUNoZWNrcy5pc19vYmplY3QodmFsdWUpIHx8IHBhdHRlcm4ubGVuZ3RoID4gdmFsdWUubGVuZ3RoKSB7XG4gICAgICByZXR1cm4gZmFsc2U7XG4gICAgfVxuXG4gICAgZm9yIChsZXQga2V5IG9mIE9iamVjdC5rZXlzKHBhdHRlcm4pKSB7XG4gICAgICBpZiAoIShrZXkgaW4gdmFsdWUpIHx8ICFtYXRjaGVzW2tleV0odmFsdWVba2V5XSwgYXJncykpIHtcbiAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgfVxuICAgIH1cblxuICAgIHJldHVybiB0cnVlO1xuICB9O1xufVxuXG5mdW5jdGlvbiByZXNvbHZlTm9NYXRjaCgpIHtcbiAgcmV0dXJuIGZ1bmN0aW9uICgpIHtcbiAgICByZXR1cm4gZmFsc2U7XG4gIH07XG59XG5cbnZhciBSZXNvbHZlcnMgPSB7XG4gIHJlc29sdmVCb3VuZCxcbiAgcmVzb2x2ZVdpbGRjYXJkLFxuICByZXNvbHZlVmFyaWFibGUsXG4gIHJlc29sdmVIZWFkVGFpbCxcbiAgcmVzb2x2ZUNhcHR1cmUsXG4gIHJlc29sdmVTdGFydHNXaXRoLFxuICByZXNvbHZlVHlwZSxcbiAgcmVzb2x2ZUFycmF5LFxuICByZXNvbHZlT2JqZWN0LFxuICByZXNvbHZlTm9NYXRjaCxcbiAgcmVzb2x2ZVN5bWJvbCxcbiAgcmVzb2x2ZVN0cmluZyxcbiAgcmVzb2x2ZU51bWJlcixcbiAgcmVzb2x2ZUJvb2xlYW4sXG4gIHJlc29sdmVGdW5jdGlvbixcbiAgcmVzb2x2ZU51bGxcbn07XG5cbmZ1bmN0aW9uIGJ1aWxkTWF0Y2gocGF0dGVybikge1xuXG4gIGlmIChDaGVja3MuaXNfdmFyaWFibGUocGF0dGVybikpIHtcbiAgICByZXR1cm4gUmVzb2x2ZXJzLnJlc29sdmVWYXJpYWJsZShwYXR0ZXJuKTtcbiAgfVxuXG4gIGlmIChDaGVja3MuaXNfd2lsZGNhcmQocGF0dGVybikpIHtcbiAgICByZXR1cm4gUmVzb2x2ZXJzLnJlc29sdmVXaWxkY2FyZChwYXR0ZXJuKTtcbiAgfVxuXG4gIGlmIChDaGVja3MuaXNfdW5kZWZpbmVkKHBhdHRlcm4pKSB7XG4gICAgcmV0dXJuIFJlc29sdmVycy5yZXNvbHZlV2lsZGNhcmQocGF0dGVybik7XG4gIH1cblxuICBpZiAoQ2hlY2tzLmlzX2hlYWRUYWlsKHBhdHRlcm4pKSB7XG4gICAgcmV0dXJuIFJlc29sdmVycy5yZXNvbHZlSGVhZFRhaWwocGF0dGVybik7XG4gIH1cblxuICBpZiAoQ2hlY2tzLmlzX3N0YXJ0c1dpdGgocGF0dGVybikpIHtcbiAgICByZXR1cm4gUmVzb2x2ZXJzLnJlc29sdmVTdGFydHNXaXRoKHBhdHRlcm4pO1xuICB9XG5cbiAgaWYgKENoZWNrcy5pc19jYXB0dXJlKHBhdHRlcm4pKSB7XG4gICAgcmV0dXJuIFJlc29sdmVycy5yZXNvbHZlQ2FwdHVyZShwYXR0ZXJuKTtcbiAgfVxuXG4gIGlmIChDaGVja3MuaXNfYm91bmQocGF0dGVybikpIHtcbiAgICByZXR1cm4gUmVzb2x2ZXJzLnJlc29sdmVCb3VuZChwYXR0ZXJuKTtcbiAgfVxuXG4gIGlmIChDaGVja3MuaXNfdHlwZShwYXR0ZXJuKSkge1xuICAgIHJldHVybiBSZXNvbHZlcnMucmVzb2x2ZVR5cGUocGF0dGVybik7XG4gIH1cblxuICBpZiAoQ2hlY2tzLmlzX2FycmF5KHBhdHRlcm4pKSB7XG4gICAgcmV0dXJuIFJlc29sdmVycy5yZXNvbHZlQXJyYXkocGF0dGVybik7XG4gIH1cblxuICBpZiAoQ2hlY2tzLmlzX251bWJlcihwYXR0ZXJuKSkge1xuICAgIHJldHVybiBSZXNvbHZlcnMucmVzb2x2ZU51bWJlcihwYXR0ZXJuKTtcbiAgfVxuXG4gIGlmIChDaGVja3MuaXNfc3RyaW5nKHBhdHRlcm4pKSB7XG4gICAgcmV0dXJuIFJlc29sdmVycy5yZXNvbHZlU3RyaW5nKHBhdHRlcm4pO1xuICB9XG5cbiAgaWYgKENoZWNrcy5pc19ib29sZWFuKHBhdHRlcm4pKSB7XG4gICAgcmV0dXJuIFJlc29sdmVycy5yZXNvbHZlQm9vbGVhbihwYXR0ZXJuKTtcbiAgfVxuXG4gIGlmIChDaGVja3MuaXNfc3ltYm9sKHBhdHRlcm4pKSB7XG4gICAgcmV0dXJuIFJlc29sdmVycy5yZXNvbHZlU3ltYm9sKHBhdHRlcm4pO1xuICB9XG5cbiAgaWYgKENoZWNrcy5pc19udWxsKHBhdHRlcm4pKSB7XG4gICAgcmV0dXJuIFJlc29sdmVycy5yZXNvbHZlTnVsbChwYXR0ZXJuKTtcbiAgfVxuXG4gIGlmIChDaGVja3MuaXNfb2JqZWN0KHBhdHRlcm4pKSB7XG4gICAgcmV0dXJuIFJlc29sdmVycy5yZXNvbHZlT2JqZWN0KHBhdHRlcm4pO1xuICB9XG5cbiAgcmV0dXJuIFJlc29sdmVycy5yZXNvbHZlTm9NYXRjaCgpO1xufVxuXG5jbGFzcyBNYXRjaEVycm9yIGV4dGVuZHMgRXJyb3Ige1xuICBjb25zdHJ1Y3RvcihhcmcpIHtcbiAgICBzdXBlcigpO1xuXG4gICAgaWYgKHR5cGVvZiBhcmcgPT09ICdzeW1ib2wnKSB7XG4gICAgICB0aGlzLm1lc3NhZ2UgPSAnTm8gbWF0Y2ggZm9yOiAnICsgYXJnLnRvU3RyaW5nKCk7XG4gICAgfSBlbHNlIGlmIChBcnJheS5pc0FycmF5KGFyZykpIHtcbiAgICAgIGxldCBtYXBwZWRWYWx1ZXMgPSBhcmcubWFwKHggPT4geC50b1N0cmluZygpKTtcbiAgICAgIHRoaXMubWVzc2FnZSA9ICdObyBtYXRjaCBmb3I6ICcgKyBtYXBwZWRWYWx1ZXM7XG4gICAgfSBlbHNlIHtcbiAgICAgIHRoaXMubWVzc2FnZSA9ICdObyBtYXRjaCBmb3I6ICcgKyBhcmc7XG4gICAgfVxuXG4gICAgdGhpcy5zdGFjayA9IG5ldyBFcnJvcigpLnN0YWNrO1xuICAgIHRoaXMubmFtZSA9IHRoaXMuY29uc3RydWN0b3IubmFtZTtcbiAgfVxufVxuXG5jbGFzcyBDYXNlIHtcblxuICBjb25zdHJ1Y3RvcihwYXR0ZXJuLCBmbiwgZ3VhcmQgPSAoKSA9PiB0cnVlKSB7XG4gICAgdGhpcy5wYXR0ZXJuID0gYnVpbGRNYXRjaChwYXR0ZXJuKTtcbiAgICB0aGlzLmZuID0gZm47XG4gICAgdGhpcy5ndWFyZCA9IGd1YXJkO1xuICB9XG59XG5cbmZ1bmN0aW9uIG1ha2VfY2FzZShwYXR0ZXJuLCBmbiwgZ3VhcmQgPSAoKSA9PiB0cnVlKSB7XG4gIHJldHVybiBuZXcgQ2FzZShwYXR0ZXJuLCBmbiwgZ3VhcmQpO1xufVxuXG5mdW5jdGlvbiBkZWZtYXRjaCguLi5jYXNlcykge1xuICByZXR1cm4gZnVuY3Rpb24gKC4uLmFyZ3MpIHtcbiAgICBmb3IgKGxldCBwcm9jZXNzZWRDYXNlIG9mIGNhc2VzKSB7XG4gICAgICBsZXQgcmVzdWx0ID0gW107XG4gICAgICBpZiAocHJvY2Vzc2VkQ2FzZS5wYXR0ZXJuKGFyZ3MsIHJlc3VsdCkgJiYgcHJvY2Vzc2VkQ2FzZS5ndWFyZC5hcHBseSh0aGlzLCByZXN1bHQpKSB7XG4gICAgICAgIHJldHVybiBwcm9jZXNzZWRDYXNlLmZuLmFwcGx5KHRoaXMsIHJlc3VsdCk7XG4gICAgICB9XG4gICAgfVxuXG4gICAgdGhyb3cgbmV3IE1hdGNoRXJyb3IoYXJncyk7XG4gIH07XG59XG5cbmZ1bmN0aW9uIG1hdGNoKHBhdHRlcm4sIGV4cHIsIGd1YXJkID0gKCkgPT4gdHJ1ZSkge1xuICBsZXQgcmVzdWx0ID0gW107XG4gIGxldCBwcm9jZXNzZWRQYXR0ZXJuID0gYnVpbGRNYXRjaChwYXR0ZXJuKTtcbiAgaWYgKHByb2Nlc3NlZFBhdHRlcm4oZXhwciwgcmVzdWx0KSAmJiBndWFyZC5hcHBseSh0aGlzLCByZXN1bHQpKSB7XG4gICAgcmV0dXJuIHJlc3VsdDtcbiAgfSBlbHNlIHtcbiAgICB0aHJvdyBuZXcgTWF0Y2hFcnJvcihleHByKTtcbiAgfVxufVxuXG5mdW5jdGlvbiBtYXRjaF9ub190aHJvdyhwYXR0ZXJuLCBleHByLCBndWFyZCA9ICgpID0+IHRydWUpIHtcbiAgdHJ5IHtcbiAgICByZXR1cm4gbWF0Y2gocGF0dGVybiwgZXhwciwgZ3VhcmQpO1xuICB9IGNhdGNoIChlKSB7XG4gICAgaWYgKGUgaW5zdGFuY2VvZiBNYXRjaEVycm9yKSB7XG4gICAgICByZXR1cm4gbnVsbDtcbiAgICB9XG5cbiAgICB0aHJvdyBlO1xuICB9XG59XG5cbnZhciBQYXR0ZXJucyA9IHtcbiAgZGVmbWF0Y2gsIG1hdGNoLCBNYXRjaEVycm9yLCBtYXRjaF9ub190aHJvdyxcbiAgdmFyaWFibGUsIHdpbGRjYXJkLCBzdGFydHNXaXRoLFxuICBjYXB0dXJlLCBoZWFkVGFpbCwgdHlwZSwgYm91bmQsIENhc2UsIG1ha2VfY2FzZVxufTtcblxuY2xhc3MgQml0U3RyaW5nIHtcbiAgY29uc3RydWN0b3IoLi4uYXJncykge1xuICAgIHRoaXMucmF3X3ZhbHVlID0gZnVuY3Rpb24gKCkge1xuICAgICAgcmV0dXJuIE9iamVjdC5mcmVlemUoYXJncyk7XG4gICAgfTtcblxuICAgIHRoaXMudmFsdWUgPSBPYmplY3QuZnJlZXplKHRoaXMucHJvY2VzcyhhcmdzKSk7XG4gIH1cblxuICBnZXQoaW5kZXgpIHtcbiAgICByZXR1cm4gdGhpcy52YWx1ZVtpbmRleF07XG4gIH1cblxuICBjb3VudCgpIHtcbiAgICByZXR1cm4gdGhpcy52YWx1ZS5sZW5ndGg7XG4gIH1cblxuICBbU3ltYm9sLml0ZXJhdG9yXSgpIHtcbiAgICByZXR1cm4gdGhpcy52YWx1ZVtTeW1ib2wuaXRlcmF0b3JdKCk7XG4gIH1cblxuICB0b1N0cmluZygpIHtcbiAgICB2YXIgaSxcbiAgICAgICAgcyA9IFwiXCI7XG4gICAgZm9yIChpID0gMDsgaSA8IHRoaXMuY291bnQoKTsgaSsrKSB7XG4gICAgICBpZiAocyAhPT0gXCJcIikge1xuICAgICAgICBzICs9IFwiLCBcIjtcbiAgICAgIH1cbiAgICAgIHMgKz0gdGhpc1tpXS50b1N0cmluZygpO1xuICAgIH1cblxuICAgIHJldHVybiBcIjw8XCIgKyBzICsgXCI+PlwiO1xuICB9XG5cbiAgcHJvY2VzcygpIHtcbiAgICBsZXQgcHJvY2Vzc2VkX3ZhbHVlcyA9IFtdO1xuXG4gICAgdmFyIGk7XG4gICAgZm9yIChpID0gMDsgaSA8IHRoaXMucmF3X3ZhbHVlKCkubGVuZ3RoOyBpKyspIHtcbiAgICAgIGxldCBwcm9jZXNzZWRfdmFsdWUgPSB0aGlzW1wicHJvY2Vzc19cIiArIHRoaXMucmF3X3ZhbHVlKClbaV0udHlwZV0odGhpcy5yYXdfdmFsdWUoKVtpXSk7XG5cbiAgICAgIGZvciAobGV0IGF0dHIgb2YgdGhpcy5yYXdfdmFsdWUoKVtpXS5hdHRyaWJ1dGVzKSB7XG4gICAgICAgIHByb2Nlc3NlZF92YWx1ZSA9IHRoaXNbXCJwcm9jZXNzX1wiICsgYXR0cl0ocHJvY2Vzc2VkX3ZhbHVlKTtcbiAgICAgIH1cblxuICAgICAgcHJvY2Vzc2VkX3ZhbHVlcyA9IHByb2Nlc3NlZF92YWx1ZXMuY29uY2F0KHByb2Nlc3NlZF92YWx1ZSk7XG4gICAgfVxuXG4gICAgcmV0dXJuIHByb2Nlc3NlZF92YWx1ZXM7XG4gIH1cblxuICBwcm9jZXNzX2ludGVnZXIodmFsdWUpIHtcbiAgICByZXR1cm4gdmFsdWUudmFsdWU7XG4gIH1cblxuICBwcm9jZXNzX2Zsb2F0KHZhbHVlKSB7XG4gICAgaWYgKHZhbHVlLnNpemUgPT09IDY0KSB7XG4gICAgICByZXR1cm4gQml0U3RyaW5nLmZsb2F0NjRUb0J5dGVzKHZhbHVlLnZhbHVlKTtcbiAgICB9IGVsc2UgaWYgKHZhbHVlLnNpemUgPT09IDMyKSB7XG4gICAgICByZXR1cm4gQml0U3RyaW5nLmZsb2F0MzJUb0J5dGVzKHZhbHVlLnZhbHVlKTtcbiAgICB9XG5cbiAgICB0aHJvdyBuZXcgRXJyb3IoXCJJbnZhbGlkIHNpemUgZm9yIGZsb2F0XCIpO1xuICB9XG5cbiAgcHJvY2Vzc19iaXRzdHJpbmcodmFsdWUpIHtcbiAgICByZXR1cm4gdmFsdWUudmFsdWUudmFsdWU7XG4gIH1cblxuICBwcm9jZXNzX2JpbmFyeSh2YWx1ZSkge1xuICAgIHJldHVybiBCaXRTdHJpbmcudG9VVEY4QXJyYXkodmFsdWUudmFsdWUpO1xuICB9XG5cbiAgcHJvY2Vzc191dGY4KHZhbHVlKSB7XG4gICAgcmV0dXJuIEJpdFN0cmluZy50b1VURjhBcnJheSh2YWx1ZS52YWx1ZSk7XG4gIH1cblxuICBwcm9jZXNzX3V0ZjE2KHZhbHVlKSB7XG4gICAgcmV0dXJuIEJpdFN0cmluZy50b1VURjE2QXJyYXkodmFsdWUudmFsdWUpO1xuICB9XG5cbiAgcHJvY2Vzc191dGYzMih2YWx1ZSkge1xuICAgIHJldHVybiBCaXRTdHJpbmcudG9VVEYzMkFycmF5KHZhbHVlLnZhbHVlKTtcbiAgfVxuXG4gIHByb2Nlc3Nfc2lnbmVkKHZhbHVlKSB7XG4gICAgcmV0dXJuIG5ldyBVaW50OEFycmF5KFt2YWx1ZV0pWzBdO1xuICB9XG5cbiAgcHJvY2Vzc191bnNpZ25lZCh2YWx1ZSkge1xuICAgIHJldHVybiB2YWx1ZTtcbiAgfVxuXG4gIHByb2Nlc3NfbmF0aXZlKHZhbHVlKSB7XG4gICAgcmV0dXJuIHZhbHVlO1xuICB9XG5cbiAgcHJvY2Vzc19iaWcodmFsdWUpIHtcbiAgICByZXR1cm4gdmFsdWU7XG4gIH1cblxuICBwcm9jZXNzX2xpdHRsZSh2YWx1ZSkge1xuICAgIHJldHVybiB2YWx1ZS5yZXZlcnNlKCk7XG4gIH1cblxuICBwcm9jZXNzX3NpemUodmFsdWUpIHtcbiAgICByZXR1cm4gdmFsdWU7XG4gIH1cblxuICBwcm9jZXNzX3VuaXQodmFsdWUpIHtcbiAgICByZXR1cm4gdmFsdWU7XG4gIH1cblxuICBzdGF0aWMgaW50ZWdlcih2YWx1ZSkge1xuICAgIHJldHVybiBCaXRTdHJpbmcud3JhcCh2YWx1ZSwgeyBcInR5cGVcIjogXCJpbnRlZ2VyXCIsIFwidW5pdFwiOiAxLCBcInNpemVcIjogOCB9KTtcbiAgfVxuXG4gIHN0YXRpYyBmbG9hdCh2YWx1ZSkge1xuICAgIHJldHVybiBCaXRTdHJpbmcud3JhcCh2YWx1ZSwgeyBcInR5cGVcIjogXCJmbG9hdFwiLCBcInVuaXRcIjogMSwgXCJzaXplXCI6IDY0IH0pO1xuICB9XG5cbiAgc3RhdGljIGJpdHN0cmluZyh2YWx1ZSkge1xuICAgIHJldHVybiBCaXRTdHJpbmcud3JhcCh2YWx1ZSwgeyBcInR5cGVcIjogXCJiaXRzdHJpbmdcIiwgXCJ1bml0XCI6IDEsIFwic2l6ZVwiOiB2YWx1ZS5sZW5ndGggfSk7XG4gIH1cblxuICBzdGF0aWMgYml0cyh2YWx1ZSkge1xuICAgIHJldHVybiBCaXRTdHJpbmcuYml0c3RyaW5nKHZhbHVlKTtcbiAgfVxuXG4gIHN0YXRpYyBiaW5hcnkodmFsdWUpIHtcbiAgICByZXR1cm4gQml0U3RyaW5nLndyYXAodmFsdWUsIHsgXCJ0eXBlXCI6IFwiYmluYXJ5XCIsIFwidW5pdFwiOiA4LCBcInNpemVcIjogdmFsdWUubGVuZ3RoIH0pO1xuICB9XG5cbiAgc3RhdGljIGJ5dGVzKHZhbHVlKSB7XG4gICAgcmV0dXJuIEJpdFN0cmluZy5iaW5hcnkodmFsdWUpO1xuICB9XG5cbiAgc3RhdGljIHV0ZjgodmFsdWUpIHtcbiAgICByZXR1cm4gQml0U3RyaW5nLndyYXAodmFsdWUsIHsgXCJ0eXBlXCI6IFwidXRmOFwiIH0pO1xuICB9XG5cbiAgc3RhdGljIHV0ZjE2KHZhbHVlKSB7XG4gICAgcmV0dXJuIEJpdFN0cmluZy53cmFwKHZhbHVlLCB7IFwidHlwZVwiOiBcInV0ZjE2XCIgfSk7XG4gIH1cblxuICBzdGF0aWMgdXRmMzIodmFsdWUpIHtcbiAgICByZXR1cm4gQml0U3RyaW5nLndyYXAodmFsdWUsIHsgXCJ0eXBlXCI6IFwidXRmMzJcIiB9KTtcbiAgfVxuXG4gIHN0YXRpYyBzaWduZWQodmFsdWUpIHtcbiAgICByZXR1cm4gQml0U3RyaW5nLndyYXAodmFsdWUsIHt9LCBcInNpZ25lZFwiKTtcbiAgfVxuXG4gIHN0YXRpYyB1bnNpZ25lZCh2YWx1ZSkge1xuICAgIHJldHVybiBCaXRTdHJpbmcud3JhcCh2YWx1ZSwge30sIFwidW5zaWduZWRcIik7XG4gIH1cblxuICBzdGF0aWMgbmF0aXZlKHZhbHVlKSB7XG4gICAgcmV0dXJuIEJpdFN0cmluZy53cmFwKHZhbHVlLCB7fSwgXCJuYXRpdmVcIik7XG4gIH1cblxuICBzdGF0aWMgYmlnKHZhbHVlKSB7XG4gICAgcmV0dXJuIEJpdFN0cmluZy53cmFwKHZhbHVlLCB7fSwgXCJiaWdcIik7XG4gIH1cblxuICBzdGF0aWMgbGl0dGxlKHZhbHVlKSB7XG4gICAgcmV0dXJuIEJpdFN0cmluZy53cmFwKHZhbHVlLCB7fSwgXCJsaXR0bGVcIik7XG4gIH1cblxuICBzdGF0aWMgc2l6ZSh2YWx1ZSwgY291bnQpIHtcbiAgICByZXR1cm4gQml0U3RyaW5nLndyYXAodmFsdWUsIHsgXCJzaXplXCI6IGNvdW50IH0pO1xuICB9XG5cbiAgc3RhdGljIHVuaXQodmFsdWUsIGNvdW50KSB7XG4gICAgcmV0dXJuIEJpdFN0cmluZy53cmFwKHZhbHVlLCB7IFwidW5pdFwiOiBjb3VudCB9KTtcbiAgfVxuXG4gIHN0YXRpYyB3cmFwKHZhbHVlLCBvcHQsIG5ld19hdHRyaWJ1dGUgPSBudWxsKSB7XG4gICAgbGV0IHRoZV92YWx1ZSA9IHZhbHVlO1xuXG4gICAgaWYgKCEodmFsdWUgaW5zdGFuY2VvZiBPYmplY3QpKSB7XG4gICAgICB0aGVfdmFsdWUgPSB7IFwidmFsdWVcIjogdmFsdWUsIFwiYXR0cmlidXRlc1wiOiBbXSB9O1xuICAgIH1cblxuICAgIHRoZV92YWx1ZSA9IE9iamVjdC5hc3NpZ24odGhlX3ZhbHVlLCBvcHQpO1xuXG4gICAgaWYgKG5ld19hdHRyaWJ1dGUpIHtcbiAgICAgIHRoZV92YWx1ZS5hdHRyaWJ1dGVzLnB1c2gobmV3X2F0dHJpYnV0ZSk7XG4gICAgfVxuXG4gICAgcmV0dXJuIHRoZV92YWx1ZTtcbiAgfVxuXG4gIHN0YXRpYyB0b1VURjhBcnJheShzdHIpIHtcbiAgICB2YXIgdXRmOCA9IFtdO1xuICAgIGZvciAodmFyIGkgPSAwOyBpIDwgc3RyLmxlbmd0aDsgaSsrKSB7XG4gICAgICB2YXIgY2hhcmNvZGUgPSBzdHIuY2hhckNvZGVBdChpKTtcbiAgICAgIGlmIChjaGFyY29kZSA8IDEyOCkge1xuICAgICAgICB1dGY4LnB1c2goY2hhcmNvZGUpO1xuICAgICAgfSBlbHNlIGlmIChjaGFyY29kZSA8IDIwNDgpIHtcbiAgICAgICAgdXRmOC5wdXNoKDE5MiB8IGNoYXJjb2RlID4+IDYsIDEyOCB8IGNoYXJjb2RlICYgNjMpO1xuICAgICAgfSBlbHNlIGlmIChjaGFyY29kZSA8IDU1Mjk2IHx8IGNoYXJjb2RlID49IDU3MzQ0KSB7XG4gICAgICAgIHV0ZjgucHVzaCgyMjQgfCBjaGFyY29kZSA+PiAxMiwgMTI4IHwgY2hhcmNvZGUgPj4gNiAmIDYzLCAxMjggfCBjaGFyY29kZSAmIDYzKTtcbiAgICAgIH1cbiAgICAgIC8vIHN1cnJvZ2F0ZSBwYWlyXG4gICAgICBlbHNlIHtcbiAgICAgICAgaSsrO1xuICAgICAgICAvLyBVVEYtMTYgZW5jb2RlcyAweDEwMDAwLTB4MTBGRkZGIGJ5XG4gICAgICAgIC8vIHN1YnRyYWN0aW5nIDB4MTAwMDAgYW5kIHNwbGl0dGluZyB0aGVcbiAgICAgICAgLy8gMjAgYml0cyBvZiAweDAtMHhGRkZGRiBpbnRvIHR3byBoYWx2ZXNcbiAgICAgICAgY2hhcmNvZGUgPSA2NTUzNiArICgoY2hhcmNvZGUgJiAxMDIzKSA8PCAxMCB8IHN0ci5jaGFyQ29kZUF0KGkpICYgMTAyMyk7XG4gICAgICAgIHV0ZjgucHVzaCgyNDAgfCBjaGFyY29kZSA+PiAxOCwgMTI4IHwgY2hhcmNvZGUgPj4gMTIgJiA2MywgMTI4IHwgY2hhcmNvZGUgPj4gNiAmIDYzLCAxMjggfCBjaGFyY29kZSAmIDYzKTtcbiAgICAgIH1cbiAgICB9XG4gICAgcmV0dXJuIHV0Zjg7XG4gIH1cblxuICBzdGF0aWMgdG9VVEYxNkFycmF5KHN0cikge1xuICAgIHZhciB1dGYxNiA9IFtdO1xuICAgIGZvciAodmFyIGkgPSAwOyBpIDwgc3RyLmxlbmd0aDsgaSsrKSB7XG4gICAgICB2YXIgY29kZVBvaW50ID0gc3RyLmNvZGVQb2ludEF0KGkpO1xuXG4gICAgICBpZiAoY29kZVBvaW50IDw9IDI1NSkge1xuICAgICAgICB1dGYxNi5wdXNoKDApO1xuICAgICAgICB1dGYxNi5wdXNoKGNvZGVQb2ludCk7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICB1dGYxNi5wdXNoKGNvZGVQb2ludCA+PiA4ICYgMjU1KTtcbiAgICAgICAgdXRmMTYucHVzaChjb2RlUG9pbnQgJiAyNTUpO1xuICAgICAgfVxuICAgIH1cbiAgICByZXR1cm4gdXRmMTY7XG4gIH1cblxuICBzdGF0aWMgdG9VVEYzMkFycmF5KHN0cikge1xuICAgIHZhciB1dGYzMiA9IFtdO1xuICAgIGZvciAodmFyIGkgPSAwOyBpIDwgc3RyLmxlbmd0aDsgaSsrKSB7XG4gICAgICB2YXIgY29kZVBvaW50ID0gc3RyLmNvZGVQb2ludEF0KGkpO1xuXG4gICAgICBpZiAoY29kZVBvaW50IDw9IDI1NSkge1xuICAgICAgICB1dGYzMi5wdXNoKDApO1xuICAgICAgICB1dGYzMi5wdXNoKDApO1xuICAgICAgICB1dGYzMi5wdXNoKDApO1xuICAgICAgICB1dGYzMi5wdXNoKGNvZGVQb2ludCk7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICB1dGYzMi5wdXNoKDApO1xuICAgICAgICB1dGYzMi5wdXNoKDApO1xuICAgICAgICB1dGYzMi5wdXNoKGNvZGVQb2ludCA+PiA4ICYgMjU1KTtcbiAgICAgICAgdXRmMzIucHVzaChjb2RlUG9pbnQgJiAyNTUpO1xuICAgICAgfVxuICAgIH1cbiAgICByZXR1cm4gdXRmMzI7XG4gIH1cblxuICAvL2h0dHA6Ly9zdGFja292ZXJmbG93LmNvbS9xdWVzdGlvbnMvMjAwMzQ5My9qYXZhc2NyaXB0LWZsb2F0LWZyb20tdG8tYml0c1xuICBzdGF0aWMgZmxvYXQzMlRvQnl0ZXMoZikge1xuICAgIHZhciBieXRlcyA9IFtdO1xuXG4gICAgdmFyIGJ1ZiA9IG5ldyBBcnJheUJ1ZmZlcig0KTtcbiAgICBuZXcgRmxvYXQzMkFycmF5KGJ1ZilbMF0gPSBmO1xuXG4gICAgbGV0IGludFZlcnNpb24gPSBuZXcgVWludDMyQXJyYXkoYnVmKVswXTtcblxuICAgIGJ5dGVzLnB1c2goaW50VmVyc2lvbiA+PiAyNCAmIDI1NSk7XG4gICAgYnl0ZXMucHVzaChpbnRWZXJzaW9uID4+IDE2ICYgMjU1KTtcbiAgICBieXRlcy5wdXNoKGludFZlcnNpb24gPj4gOCAmIDI1NSk7XG4gICAgYnl0ZXMucHVzaChpbnRWZXJzaW9uICYgMjU1KTtcblxuICAgIHJldHVybiBieXRlcztcbiAgfVxuXG4gIHN0YXRpYyBmbG9hdDY0VG9CeXRlcyhmKSB7XG4gICAgdmFyIGJ5dGVzID0gW107XG5cbiAgICB2YXIgYnVmID0gbmV3IEFycmF5QnVmZmVyKDgpO1xuICAgIG5ldyBGbG9hdDY0QXJyYXkoYnVmKVswXSA9IGY7XG5cbiAgICB2YXIgaW50VmVyc2lvbjEgPSBuZXcgVWludDMyQXJyYXkoYnVmKVswXTtcbiAgICB2YXIgaW50VmVyc2lvbjIgPSBuZXcgVWludDMyQXJyYXkoYnVmKVsxXTtcblxuICAgIGJ5dGVzLnB1c2goaW50VmVyc2lvbjIgPj4gMjQgJiAyNTUpO1xuICAgIGJ5dGVzLnB1c2goaW50VmVyc2lvbjIgPj4gMTYgJiAyNTUpO1xuICAgIGJ5dGVzLnB1c2goaW50VmVyc2lvbjIgPj4gOCAmIDI1NSk7XG4gICAgYnl0ZXMucHVzaChpbnRWZXJzaW9uMiAmIDI1NSk7XG5cbiAgICBieXRlcy5wdXNoKGludFZlcnNpb24xID4+IDI0ICYgMjU1KTtcbiAgICBieXRlcy5wdXNoKGludFZlcnNpb24xID4+IDE2ICYgMjU1KTtcbiAgICBieXRlcy5wdXNoKGludFZlcnNpb24xID4+IDggJiAyNTUpO1xuICAgIGJ5dGVzLnB1c2goaW50VmVyc2lvbjEgJiAyNTUpO1xuXG4gICAgcmV0dXJuIGJ5dGVzO1xuICB9XG59XG5cbi8qIEBmbG93ICovXG5cbmNsYXNzIE1haWxib3gge1xuXG4gIGNvbnN0cnVjdG9yKCkge1xuICAgIHRoaXMubWVzc2FnZXMgPSBbXTtcbiAgfVxuXG4gIGRlbGl2ZXIobWVzc2FnZSkge1xuICAgIHRoaXMubWVzc2FnZXMucHVzaChtZXNzYWdlKTtcbiAgICByZXR1cm4gbWVzc2FnZTtcbiAgfVxuXG4gIGdldCgpIHtcbiAgICByZXR1cm4gdGhpcy5tZXNzYWdlcztcbiAgfVxuXG4gIGlzRW1wdHkoKSB7XG4gICAgcmV0dXJuIHRoaXMubWVzc2FnZXMubGVuZ3RoID09PSAwO1xuICB9XG5cbiAgcmVtb3ZlQXQoaW5kZXgpIHtcbiAgICB0aGlzLm1lc3NhZ2VzLnNwbGljZShpbmRleCwgMSk7XG4gIH1cbn1cblxudmFyIFN0YXRlcyA9IHtcbiAgTk9STUFMOiBTeW1ib2wuZm9yKFwibm9ybWFsXCIpLFxuICBLSUxMOiBTeW1ib2wuZm9yKFwia2lsbFwiKSxcbiAgU1VTUEVORDogU3ltYm9sLmZvcihcInN1c3BlbmRcIiksXG4gIENPTlRJTlVFOiBTeW1ib2wuZm9yKFwiY29udGludWVcIiksXG4gIFJFQ0VJVkU6IFN5bWJvbC5mb3IoXCJyZWNlaXZlXCIpLFxuICBTRU5EOiBTeW1ib2wuZm9yKFwic2VuZFwiKSxcbiAgU0xFRVBJTkc6IFN5bWJvbC5mb3IoXCJzbGVlcGluZ1wiKSxcbiAgUlVOTklORzogU3ltYm9sLmZvcihcInJ1bm5pbmdcIiksXG4gIFNVU1BFTkRFRDogU3ltYm9sLmZvcihcInN1c3BlbmRlZFwiKSxcbiAgU1RPUFBFRDogU3ltYm9sLmZvcihcInN0b3BwZWRcIiksXG4gIFNMRUVQOiBTeW1ib2wuZm9yKFwic2xlZXBcIiksXG4gIEVYSVQ6IFN5bWJvbC5mb3IoXCJleGl0XCIpLFxuICBOT01BVENIOiBTeW1ib2wuZm9yKFwibm9fbWF0Y2hcIilcbn07XG5cbmNsYXNzIFByb2Nlc3Mge1xuXG4gIGNvbnN0cnVjdG9yKHBpZCwgbWFpbGJveCkge1xuICAgIHRoaXMucGlkID0gcGlkO1xuICAgIHRoaXMubWFpbGJveCA9IG1haWxib3g7XG4gICAgdGhpcy5zdGF0dXMgPSBTdGF0ZXMuU1RPUFBFRDtcbiAgICB0aGlzLmRpY3QgPSB7fTtcbiAgfVxufVxuXG5jbGFzcyBQcm9jZXNzU3lzdGVtIHtcblxuICBjb25zdHJ1Y3RvcigpIHtcbiAgICB0aGlzLnBpZHMgPSBuZXcgTWFwKCk7XG4gICAgdGhpcy5tYWlsYm94ZXMgPSBuZXcgTWFwKCk7XG4gICAgdGhpcy5uYW1lcyA9IG5ldyBNYXAoKTtcbiAgICB0aGlzLmxpbmtzID0gbmV3IE1hcCgpO1xuXG4gICAgdGhpcy5jdXJyZW50X3Byb2Nlc3MgPSBudWxsO1xuICAgIHRoaXMuc3VzcGVuZGVkID0gbmV3IE1hcCgpO1xuXG4gICAgdGhpcy5tYWluX3Byb2Nlc3NfcGlkID0gdGhpcy5zcGF3bigpO1xuICAgIHRoaXMuc2V0X2N1cnJlbnQodGhpcy5tYWluX3Byb2Nlc3NfcGlkKTtcbiAgfVxuXG4gIHNwYXduKCkge1xuICAgIHJldHVybiB0aGlzLmFkZF9wcm9jKGZhbHNlKS5waWQ7XG4gIH1cblxuICBzcGF3bl9saW5rKCkge1xuICAgIHJldHVybiB0aGlzLmFkZF9wcm9jKHRydWUpLnBpZDtcbiAgfVxuXG4gIGxpbmsocGlkKSB7XG4gICAgdGhpcy5saW5rcy5nZXQodGhpcy5waWQoKSkuYWRkKHBpZCk7XG4gICAgdGhpcy5saW5rcy5nZXQocGlkKS5hZGQodGhpcy5waWQoKSk7XG4gIH1cblxuICB1bmxpbmsocGlkKSB7XG4gICAgdGhpcy5saW5rcy5nZXQodGhpcy5waWQoKSkuZGVsZXRlKHBpZCk7XG4gICAgdGhpcy5saW5rcy5nZXQocGlkKS5kZWxldGUodGhpcy5waWQoKSk7XG4gIH1cblxuICBzZXRfY3VycmVudChpZCkge1xuICAgIGxldCBwaWQgPSB0aGlzLnBpZG9mKGlkKTtcbiAgICBpZiAocGlkICE9PSBudWxsKSB7XG4gICAgICB0aGlzLmN1cnJlbnRfcHJvY2VzcyA9IHRoaXMucGlkcy5nZXQocGlkKTtcbiAgICAgIHRoaXMuY3VycmVudF9wcm9jZXNzLnN0YXR1cyA9IFN0YXRlcy5SVU5OSU5HO1xuICAgIH1cbiAgfVxuXG4gIGFkZF9wcm9jKGxpbmtlZCkge1xuICAgIGxldCBuZXdwaWQgPSBuZXcgUElEKCk7XG4gICAgbGV0IG1haWxib3ggPSBuZXcgTWFpbGJveCgpO1xuICAgIGxldCBuZXdwcm9jID0gbmV3IFByb2Nlc3MobmV3cGlkLCBtYWlsYm94KTtcblxuICAgIHRoaXMucGlkcy5zZXQobmV3cGlkLCBuZXdwcm9jKTtcbiAgICB0aGlzLm1haWxib3hlcy5zZXQobmV3cGlkLCBtYWlsYm94KTtcbiAgICB0aGlzLmxpbmtzLnNldChuZXdwaWQsIG5ldyBTZXQoKSk7XG5cbiAgICBpZiAobGlua2VkKSB7XG4gICAgICB0aGlzLmxpbmsobmV3cGlkKTtcbiAgICB9XG5cbiAgICByZXR1cm4gbmV3cHJvYztcbiAgfVxuXG4gIHJlbW92ZV9wcm9jKHBpZCkge1xuICAgIHRoaXMucGlkcy5kZWxldGUocGlkKTtcbiAgICB0aGlzLnVucmVnaXN0ZXIocGlkKTtcblxuICAgIGlmICh0aGlzLmxpbmtzLmhhcyhwaWQpKSB7XG4gICAgICBmb3IgKGxldCBsaW5rcGlkIG9mIHRoaXMubGlua3MuZ2V0KHBpZCkpIHtcbiAgICAgICAgdGhpcy5saW5rcy5nZXQobGlua3BpZCkuZGVsZXRlKHBpZCk7XG4gICAgICB9XG5cbiAgICAgIHRoaXMubGlua3MuZGVsZXRlKHBpZCk7XG4gICAgfVxuICB9XG5cbiAgZXhpdChpZCkge1xuICAgIGxldCBwaWQgPSB0aGlzLnBpZG9mKGlkKTtcbiAgICB0aGlzLnJlbW92ZV9wcm9jKGlkKTtcbiAgfVxuXG4gIHJlZ2lzdGVyKG5hbWUsIHBpZCkge1xuICAgIGlmICghdGhpcy5uYW1lcy5oYXMobmFtZSkpIHtcbiAgICAgIHRoaXMubmFtZXMuc2V0KG5hbWUsIHBpZCk7XG4gICAgICByZXR1cm4gbmFtZTtcbiAgICB9IGVsc2Uge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKFwiTmFtZSBpcyBhbHJlYWR5IHJlZ2lzdGVyZWQgdG8gYW5vdGhlciBwcm9jZXNzXCIpO1xuICAgIH1cbiAgfVxuXG4gIHJlZ2lzdGVyZWQobmFtZSkge1xuICAgIHJldHVybiB0aGlzLm5hbWVzLmhhcyhuYW1lKSA/IHRoaXMubmFtZXMuZ2V0KG5hbWUpIDogbnVsbDtcbiAgfVxuXG4gIHVucmVnaXN0ZXIocGlkKSB7XG4gICAgZm9yIChsZXQgbmFtZSBvZiB0aGlzLm5hbWVzLmtleXMoKSkge1xuICAgICAgaWYgKHRoaXMubmFtZXMuaGFzKG5hbWUpICYmIHRoaXMubmFtZXMuZ2V0KG5hbWUpID09PSBwaWQpIHtcbiAgICAgICAgdGhpcy5uYW1lcy5kZWxldGUobmFtZSk7XG4gICAgICB9XG4gICAgfVxuICB9XG5cbiAgcGlkKCkge1xuICAgIHJldHVybiB0aGlzLmN1cnJlbnRfcHJvY2Vzcy5waWQ7XG4gIH1cblxuICBwaWRvZihpZCkge1xuICAgIGlmIChpZCBpbnN0YW5jZW9mIFBJRCkge1xuICAgICAgcmV0dXJuIHRoaXMucGlkcy5oYXMoaWQpID8gaWQgOiBudWxsO1xuICAgIH0gZWxzZSBpZiAoaWQgaW5zdGFuY2VvZiBQcm9jZXNzKSB7XG4gICAgICByZXR1cm4gaWQucGlkO1xuICAgIH0gZWxzZSB7XG4gICAgICBsZXQgcGlkID0gdGhpcy5yZWdpc3RlcmVkKGlkKTtcbiAgICAgIGlmIChwaWQgPT09IG51bGwpIHRocm93IFwiUHJvY2VzcyBuYW1lIG5vdCByZWdpc3RlcmVkOiBcIiArIGlkICsgXCIgKFwiICsgdHlwZW9mIGlkICsgXCIpXCI7XG4gICAgICByZXR1cm4gcGlkO1xuICAgIH1cbiAgfVxuXG4gIHB1dChpZCwga2V5LCB2YWx1ZSkge1xuICAgIGxldCBwaWQgPSB0aGlzLnBpZG9mKGlkKTtcbiAgICBsZXQgcHJvY2VzcyA9IHRoaXMucGlkcy5nZXQocGlkKTtcbiAgICBwcm9jZXNzLmRpY3Rba2V5XSA9IHZhbHVlO1xuICB9XG5cbiAgZ2V0KGlkLCBrZXkpIHtcbiAgICBsZXQgcGlkID0gdGhpcy5waWRvZihpZCk7XG4gICAgbGV0IHByb2Nlc3MgPSB0aGlzLnBpZHMuZ2V0KHBpZCk7XG5cbiAgICBpZiAoa2V5ICE9IG51bGwpIHtcbiAgICAgIHJldHVybiBwcm9jZXNzLmRpY3Rba2V5XTtcbiAgICB9IGVsc2Uge1xuICAgICAgcmV0dXJuIHByb2Nlc3MuZGljdDtcbiAgICB9XG4gIH1cblxuICBnZXRfa2V5cyhpZCkge1xuICAgIGxldCBwaWQgPSB0aGlzLnBpZG9mKGlkKTtcbiAgICBsZXQgcHJvY2VzcyA9IHRoaXMucGlkcy5nZXQocGlkKTtcblxuICAgIHJldHVybiBPYmplY3Qua2V5cyhwcm9jZXNzLmRpY3QpO1xuICB9XG5cbiAgZXJhc2UoaWQsIGtleSkge1xuICAgIGxldCBwaWQgPSB0aGlzLnBpZG9mKGlkKTtcbiAgICBsZXQgcHJvY2VzcyA9IHRoaXMucGlkcy5nZXQocGlkKTtcblxuICAgIGlmIChrZXkgIT0gbnVsbCkge1xuICAgICAgZGVsZXRlIHByb2Nlc3MuZGljdFtrZXldO1xuICAgIH0gZWxzZSB7XG4gICAgICBwcm9jZXNzLmRpY3QgPSB7fTtcbiAgICB9XG4gIH1cbn1cblxudmFyIEMgPSBPYmplY3QuZnJlZXplKHtcblx0UHJvY2Vzc1N5c3RlbTogUHJvY2Vzc1N5c3RlbSxcblx0VHVwbGU6IFR1cGxlJDEsXG5cdFBJRDogUElELFxuXHRCaXRTdHJpbmc6IEJpdFN0cmluZyxcblx0UGF0dGVybnM6IFBhdHRlcm5zLFxuXHRJbnRlZ2VyOiBJbnRlZ2VyJDEsXG5cdEZsb2F0OiBGbG9hdCxcblx0Y2FsbF9wcm9wZXJ0eTogY2FsbF9wcm9wZXJ0eVxufSk7XG5cbmxldCBFbnVtID0ge1xuXG4gIGFsbF9fcW1hcmtfXzogZnVuY3Rpb24gKGNvbGxlY3Rpb24sIGZ1biA9IHggPT4geCkge1xuICAgIGZvciAobGV0IGVsZW0gb2YgY29sbGVjdGlvbikge1xuICAgICAgaWYgKCFmdW4oZWxlbSkpIHtcbiAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgfVxuICAgIH1cblxuICAgIHJldHVybiB0cnVlO1xuICB9LFxuXG4gIGFueV9fcW1hcmtfXzogZnVuY3Rpb24gKGNvbGxlY3Rpb24sIGZ1biA9IHggPT4geCkge1xuICAgIGZvciAobGV0IGVsZW0gb2YgY29sbGVjdGlvbikge1xuICAgICAgaWYgKGZ1bihlbGVtKSkge1xuICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICByZXR1cm4gZmFsc2U7XG4gIH0sXG5cbiAgYXQ6IGZ1bmN0aW9uIChjb2xsZWN0aW9uLCBuLCB0aGVfZGVmYXVsdCA9IG51bGwpIHtcbiAgICBpZiAobiA+IHRoaXMuY291bnQoY29sbGVjdGlvbikgfHwgbiA8IDApIHtcbiAgICAgIHJldHVybiB0aGVfZGVmYXVsdDtcbiAgICB9XG5cbiAgICByZXR1cm4gY29sbGVjdGlvbltuXTtcbiAgfSxcblxuICBjb25jYXQ6IGZ1bmN0aW9uICguLi5lbnVtYWJsZXMpIHtcbiAgICByZXR1cm4gZW51bWFibGVzWzBdLmNvbmNhdChlbnVtYWJsZXNbMV0pO1xuICB9LFxuXG4gIGNvdW50OiBmdW5jdGlvbiAoY29sbGVjdGlvbiwgZnVuID0gbnVsbCkge1xuICAgIGlmIChmdW4gPT0gbnVsbCkge1xuICAgICAgcmV0dXJuIGNvbGxlY3Rpb24ubGVuZ3RoO1xuICAgIH0gZWxzZSB7XG4gICAgICByZXR1cm4gY29sbGVjdGlvbi5maWx0ZXIoZnVuKS5sZW5ndGg7XG4gICAgfVxuICB9LFxuXG4gIGRyb3A6IGZ1bmN0aW9uIChjb2xsZWN0aW9uLCBjb3VudCkge1xuICAgIHJldHVybiBjb2xsZWN0aW9uLnNsaWNlKGNvdW50KTtcbiAgfSxcblxuICBkcm9wX3doaWxlOiBmdW5jdGlvbiAoY29sbGVjdGlvbiwgZnVuKSB7XG4gICAgbGV0IGNvdW50ID0gMDtcblxuICAgIGZvciAobGV0IGVsZW0gb2YgY29sbGVjdGlvbikge1xuICAgICAgaWYgKGZ1bihlbGVtKSkge1xuICAgICAgICBjb3VudCA9IGNvdW50ICsgMTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIGJyZWFrO1xuICAgICAgfVxuICAgIH1cblxuICAgIHJldHVybiBjb2xsZWN0aW9uLnNsaWNlKGNvdW50KTtcbiAgfSxcblxuICBlYWNoOiBmdW5jdGlvbiAoY29sbGVjdGlvbiwgZnVuKSB7XG4gICAgZm9yIChsZXQgZWxlbSBvZiBjb2xsZWN0aW9uKSB7XG4gICAgICBmdW4oZWxlbSk7XG4gICAgfVxuICB9LFxuXG4gIGVtcHR5X19xbWFya19fOiBmdW5jdGlvbiAoY29sbGVjdGlvbikge1xuICAgIHJldHVybiBjb2xsZWN0aW9uLmxlbmd0aCA9PT0gMDtcbiAgfSxcblxuICBmZXRjaDogZnVuY3Rpb24gKGNvbGxlY3Rpb24sIG4pIHtcbiAgICBpZiAoS2VybmVsLmlzX2xpc3QoY29sbGVjdGlvbikpIHtcbiAgICAgIGlmIChuIDwgdGhpcy5jb3VudChjb2xsZWN0aW9uKSAmJiBuID49IDApIHtcbiAgICAgICAgcmV0dXJuIEtlcm5lbC5TcGVjaWFsRm9ybXMudHVwbGUoS2VybmVsLlNwZWNpYWxGb3Jtcy5hdG9tKFwib2tcIiksIGNvbGxlY3Rpb25bbl0pO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgcmV0dXJuIEtlcm5lbC5TcGVjaWFsRm9ybXMuYXRvbShcImVycm9yXCIpO1xuICAgICAgfVxuICAgIH1cblxuICAgIHRocm93IG5ldyBFcnJvcihcImNvbGxlY3Rpb24gaXMgbm90IGFuIEVudW1lcmFibGVcIik7XG4gIH0sXG5cbiAgZmV0Y2hfX2VtYXJrX186IGZ1bmN0aW9uIChjb2xsZWN0aW9uLCBuKSB7XG4gICAgaWYgKEtlcm5lbC5pc19saXN0KGNvbGxlY3Rpb24pKSB7XG4gICAgICBpZiAobiA8IHRoaXMuY291bnQoY29sbGVjdGlvbikgJiYgbiA+PSAwKSB7XG4gICAgICAgIHJldHVybiBjb2xsZWN0aW9uW25dO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKFwib3V0IG9mIGJvdW5kcyBlcnJvclwiKTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICB0aHJvdyBuZXcgRXJyb3IoXCJjb2xsZWN0aW9uIGlzIG5vdCBhbiBFbnVtZXJhYmxlXCIpO1xuICB9LFxuXG4gIGZpbHRlcjogZnVuY3Rpb24gKGNvbGxlY3Rpb24sIGZ1bikge1xuICAgIGxldCByZXN1bHQgPSBbXTtcblxuICAgIGZvciAobGV0IGVsZW0gb2YgY29sbGVjdGlvbikge1xuICAgICAgaWYgKGZ1bihlbGVtKSkge1xuICAgICAgICByZXN1bHQucHVzaChlbGVtKTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICByZXR1cm4gcmVzdWx0O1xuICB9LFxuXG4gIGZpbHRlcl9tYXA6IGZ1bmN0aW9uIChjb2xsZWN0aW9uLCBmaWx0ZXIsIG1hcHBlcikge1xuICAgIHJldHVybiBFbnVtLm1hcChFbnVtLmZpbHRlcihjb2xsZWN0aW9uLCBmaWx0ZXIpLCBtYXBwZXIpO1xuICB9LFxuXG4gIGZpbmQ6IGZ1bmN0aW9uIChjb2xsZWN0aW9uLCBpZl9ub25lID0gbnVsbCwgZnVuKSB7XG4gICAgZm9yIChsZXQgZWxlbSBvZiBjb2xsZWN0aW9uKSB7XG4gICAgICBpZiAoZnVuKGVsZW0pKSB7XG4gICAgICAgIHJldHVybiBlbGVtO1xuICAgICAgfVxuICAgIH1cblxuICAgIHJldHVybiBpZl9ub25lO1xuICB9LFxuXG4gIGludG86IGZ1bmN0aW9uIChjb2xsZWN0aW9uLCBsaXN0KSB7XG4gICAgcmV0dXJuIGxpc3QuY29uY2F0KGNvbGxlY3Rpb24pO1xuICB9LFxuXG4gIG1hcDogZnVuY3Rpb24gKGNvbGxlY3Rpb24sIGZ1bikge1xuICAgIGxldCByZXN1bHQgPSBbXTtcblxuICAgIGZvciAobGV0IGVsZW0gb2YgY29sbGVjdGlvbikge1xuICAgICAgcmVzdWx0LnB1c2goZnVuKGVsZW0pKTtcbiAgICB9XG5cbiAgICByZXR1cm4gcmVzdWx0O1xuICB9LFxuXG4gIG1hcF9yZWR1Y2U6IGZ1bmN0aW9uIChjb2xsZWN0aW9uLCBhY2MsIGZ1bikge1xuICAgIGxldCBtYXBwZWQgPSBLZXJuZWwuU3BlY2lhbEZvcm1zLmxpc3QoKTtcbiAgICBsZXQgdGhlX2FjYyA9IGFjYztcblxuICAgIGZvciAodmFyIGkgPSAwOyBpIDwgdGhpcy5jb3VudChjb2xsZWN0aW9uKTsgaSsrKSB7XG4gICAgICBsZXQgdHVwbGUgPSBmdW4oY29sbGVjdGlvbltpXSwgdGhlX2FjYyk7XG5cbiAgICAgIHRoZV9hY2MgPSBLZXJuZWwuZWxlbSh0dXBsZSwgMSk7XG4gICAgICBtYXBwZWQgPSBLZXJuZWwuU3BlY2lhbEZvcm1zLmxpc3QoLi4ubWFwcGVkLmNvbmNhdChbS2VybmVsLmVsZW0odHVwbGUsIDApXSkpO1xuICAgIH1cblxuICAgIHJldHVybiBLZXJuZWwuU3BlY2lhbEZvcm1zLnR1cGxlKG1hcHBlZCwgdGhlX2FjYyk7XG4gIH0sXG5cbiAgbWVtYmVyOiBmdW5jdGlvbiAoY29sbGVjdGlvbiwgdmFsdWUpIHtcbiAgICByZXR1cm4gY29sbGVjdGlvbi5pbmNsdWRlcyh2YWx1ZSk7XG4gIH0sXG5cbiAgcmVkdWNlOiBmdW5jdGlvbiAoY29sbGVjdGlvbiwgYWNjLCBmdW4pIHtcbiAgICBsZXQgdGhlX2FjYyA9IGFjYztcblxuICAgIGZvciAodmFyIGkgPSAwOyBpIDwgdGhpcy5jb3VudChjb2xsZWN0aW9uKTsgaSsrKSB7XG4gICAgICBsZXQgdHVwbGUgPSBmdW4oY29sbGVjdGlvbltpXSwgdGhlX2FjYyk7XG5cbiAgICAgIHRoZV9hY2MgPSBLZXJuZWwuZWxlbSh0dXBsZSwgMSk7XG4gICAgfVxuXG4gICAgcmV0dXJuIHRoZV9hY2M7XG4gIH0sXG5cbiAgdGFrZTogZnVuY3Rpb24gKGNvbGxlY3Rpb24sIGNvdW50KSB7XG4gICAgcmV0dXJuIGNvbGxlY3Rpb24uc2xpY2UoMCwgY291bnQpO1xuICB9LFxuXG4gIHRha2VfZXZlcnk6IGZ1bmN0aW9uIChjb2xsZWN0aW9uLCBudGgpIHtcbiAgICBsZXQgcmVzdWx0ID0gW107XG4gICAgbGV0IGluZGV4ID0gMDtcblxuICAgIGZvciAobGV0IGVsZW0gb2YgY29sbGVjdGlvbikge1xuICAgICAgaWYgKGluZGV4ICUgbnRoID09PSAwKSB7XG4gICAgICAgIHJlc3VsdC5wdXNoKGVsZW0pO1xuICAgICAgfVxuICAgIH1cblxuICAgIHJldHVybiBLZXJuZWwuU3BlY2lhbEZvcm1zLmxpc3QoLi4ucmVzdWx0KTtcbiAgfSxcblxuICB0YWtlX3doaWxlOiBmdW5jdGlvbiAoY29sbGVjdGlvbiwgZnVuKSB7XG4gICAgbGV0IGNvdW50ID0gMDtcblxuICAgIGZvciAobGV0IGVsZW0gb2YgY29sbGVjdGlvbikge1xuICAgICAgaWYgKGZ1bihlbGVtKSkge1xuICAgICAgICBjb3VudCA9IGNvdW50ICsgMTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIGJyZWFrO1xuICAgICAgfVxuICAgIH1cblxuICAgIHJldHVybiBjb2xsZWN0aW9uLnNsaWNlKDAsIGNvdW50KTtcbiAgfSxcblxuICB0b19saXN0OiBmdW5jdGlvbiAoY29sbGVjdGlvbikge1xuICAgIHJldHVybiBjb2xsZWN0aW9uO1xuICB9XG59O1xuXG5sZXQgU3BlY2lhbEZvcm1zID0ge1xuXG4gIF9fRElSX186IGZ1bmN0aW9uICgpIHtcbiAgICBpZiAoX19kaXJuYW1lKSB7XG4gICAgICByZXR1cm4gX19kaXJuYW1lO1xuICAgIH1cblxuICAgIGlmIChkb2N1bWVudC5jdXJyZW50U2NyaXB0KSB7XG4gICAgICByZXR1cm4gZG9jdW1lbnQuY3VycmVudFNjcmlwdC5zcmM7XG4gICAgfVxuXG4gICAgcmV0dXJuIG51bGw7XG4gIH0sXG5cbiAgYXRvbTogZnVuY3Rpb24gKF92YWx1ZSkge1xuICAgIHJldHVybiBTeW1ib2wuZm9yKF92YWx1ZSk7XG4gIH0sXG5cbiAgbGlzdDogZnVuY3Rpb24gKC4uLmFyZ3MpIHtcbiAgICByZXR1cm4gT2JqZWN0LmZyZWV6ZShhcmdzKTtcbiAgfSxcblxuICBiaXRzdHJpbmc6IGZ1bmN0aW9uICguLi5hcmdzKSB7XG4gICAgcmV0dXJuIG5ldyBCaXRTdHJpbmcoLi4uYXJncyk7XG4gIH0sXG5cbiAgYm91bmQ6IGZ1bmN0aW9uIChfdmFyKSB7XG4gICAgcmV0dXJuIFBhdHRlcm5zLmJvdW5kKF92YXIpO1xuICB9LFxuXG4gIF9jYXNlOiBmdW5jdGlvbiAoY29uZGl0aW9uLCBjbGF1c2VzKSB7XG4gICAgcmV0dXJuIFBhdHRlcm5zLmRlZm1hdGNoKC4uLmNsYXVzZXMpKGNvbmRpdGlvbik7XG4gIH0sXG5cbiAgY29uZDogZnVuY3Rpb24gKGNsYXVzZXMpIHtcbiAgICBmb3IgKGxldCBjbGF1c2Ugb2YgY2xhdXNlcykge1xuICAgICAgaWYgKGNsYXVzZVswXSkge1xuICAgICAgICByZXR1cm4gY2xhdXNlWzFdKCk7XG4gICAgICB9XG4gICAgfVxuXG4gICAgdGhyb3cgbmV3IEVycm9yKCk7XG4gIH0sXG5cbiAgZm46IGZ1bmN0aW9uIChjbGF1c2VzKSB7XG4gICAgcmV0dXJuIFBhdHRlcm5zLmRlZm1hdGNoKGNsYXVzZXMpO1xuICB9LFxuXG4gIG1hcDogZnVuY3Rpb24gKG9iaikge1xuICAgIHJldHVybiBPYmplY3QuZnJlZXplKG9iaik7XG4gIH0sXG5cbiAgbWFwX3VwZGF0ZTogZnVuY3Rpb24gKG1hcCwgdmFsdWVzKSB7XG4gICAgcmV0dXJuIE9iamVjdC5mcmVlemUoT2JqZWN0LmFzc2lnbihPYmplY3QuY3JlYXRlKG1hcC5jb25zdHJ1Y3Rvci5wcm90b3R5cGUpLCBtYXAsIHZhbHVlcykpO1xuICB9LFxuXG4gIF9mb3I6IGZ1bmN0aW9uIChjb2xsZWN0aW9ucywgZnVuLCBmaWx0ZXIgPSAoKSA9PiB0cnVlLCBpbnRvID0gW10sIHByZXZpb3VzVmFsdWVzID0gW10pIHtcbiAgICBsZXQgcGF0dGVybiA9IGNvbGxlY3Rpb25zWzBdWzBdO1xuICAgIGxldCBjb2xsZWN0aW9uID0gY29sbGVjdGlvbnNbMF1bMV07XG5cbiAgICBpZiAoY29sbGVjdGlvbnMubGVuZ3RoID09PSAxKSB7XG5cbiAgICAgIGZvciAobGV0IGVsZW0gb2YgY29sbGVjdGlvbikge1xuICAgICAgICBsZXQgciA9IFBhdHRlcm5zLm1hdGNoX25vX3Rocm93KHBhdHRlcm4sIGVsZW0pO1xuICAgICAgICBsZXQgYXJncyA9IHByZXZpb3VzVmFsdWVzLmNvbmNhdChyKTtcblxuICAgICAgICBpZiAociAmJiBmaWx0ZXIuYXBwbHkodGhpcywgYXJncykpIHtcbiAgICAgICAgICBpbnRvID0gRW51bS5pbnRvKFtmdW4uYXBwbHkodGhpcywgYXJncyldLCBpbnRvKTtcbiAgICAgICAgfVxuICAgICAgfVxuXG4gICAgICByZXR1cm4gaW50bztcbiAgICB9IGVsc2Uge1xuICAgICAgbGV0IF9pbnRvID0gW107XG5cbiAgICAgIGZvciAobGV0IGVsZW0gb2YgY29sbGVjdGlvbikge1xuICAgICAgICBsZXQgciA9IFBhdHRlcm5zLm1hdGNoX25vX3Rocm93KHBhdHRlcm4sIGVsZW0pO1xuICAgICAgICBpZiAocikge1xuICAgICAgICAgIF9pbnRvID0gRW51bS5pbnRvKHRoaXMuX2Zvcihjb2xsZWN0aW9ucy5zbGljZSgxKSwgZnVuLCBmaWx0ZXIsIF9pbnRvLCBwcmV2aW91c1ZhbHVlcy5jb25jYXQocikpLCBpbnRvKTtcbiAgICAgICAgfVxuICAgICAgfVxuXG4gICAgICByZXR1cm4gX2ludG87XG4gICAgfVxuICB9LFxuXG4gIHJlY2VpdmU6IGZ1bmN0aW9uIChyZWNlaXZlX2Z1biwgdGltZW91dF9pbl9tcyA9IG51bGwsIHRpbWVvdXRfZm4gPSB0aW1lID0+IHRydWUpIHtcbiAgICBpZiAodGltZW91dF9pbl9tcyA9PSBudWxsIHx8IHRpbWVvdXRfaW5fbXMgPT09IFN5c3RlbS5mb3IoJ2luZmluaXR5JykpIHtcbiAgICAgIHdoaWxlICh0cnVlKSB7XG4gICAgICAgIGlmIChzZWxmLm1haWxib3gubGVuZ3RoICE9PSAwKSB7XG4gICAgICAgICAgbGV0IG1lc3NhZ2UgPSBzZWxmLm1haWxib3hbMF07XG4gICAgICAgICAgc2VsZi5tYWlsYm94ID0gc2VsZi5tYWlsYm94LnNsaWNlKDEpO1xuICAgICAgICAgIHJldHVybiByZWNlaXZlX2Z1bihtZXNzYWdlKTtcbiAgICAgICAgfVxuICAgICAgfVxuICAgIH0gZWxzZSBpZiAodGltZW91dF9pbl9tcyA9PT0gMCkge1xuICAgICAgaWYgKHNlbGYubWFpbGJveC5sZW5ndGggIT09IDApIHtcbiAgICAgICAgbGV0IG1lc3NhZ2UgPSBzZWxmLm1haWxib3hbMF07XG4gICAgICAgIHNlbGYubWFpbGJveCA9IHNlbGYubWFpbGJveC5zbGljZSgxKTtcbiAgICAgICAgcmV0dXJuIHJlY2VpdmVfZnVuKG1lc3NhZ2UpO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgcmV0dXJuIG51bGw7XG4gICAgICB9XG4gICAgfSBlbHNlIHtcbiAgICAgIGxldCBub3cgPSBEYXRlLm5vdygpO1xuICAgICAgd2hpbGUgKERhdGUubm93KCkgPCBub3cgKyB0aW1lb3V0X2luX21zKSB7XG4gICAgICAgIGlmIChzZWxmLm1haWxib3gubGVuZ3RoICE9PSAwKSB7XG4gICAgICAgICAgbGV0IG1lc3NhZ2UgPSBzZWxmLm1haWxib3hbMF07XG4gICAgICAgICAgc2VsZi5tYWlsYm94ID0gc2VsZi5tYWlsYm94LnNsaWNlKDEpO1xuICAgICAgICAgIHJldHVybiByZWNlaXZlX2Z1bihtZXNzYWdlKTtcbiAgICAgICAgfVxuICAgICAgfVxuXG4gICAgICByZXR1cm4gdGltZW91dF9mbih0aW1lb3V0X2luX21zKTtcbiAgICB9XG4gIH0sXG5cbiAgdHVwbGU6IGZ1bmN0aW9uICguLi5hcmdzKSB7XG4gICAgcmV0dXJuIG5ldyBUdXBsZSQxKC4uLmFyZ3MpO1xuICB9LFxuXG4gIF90cnk6IGZ1bmN0aW9uIChkb19mdW4sIHJlc2N1ZV9mdW5jdGlvbiwgY2F0Y2hfZnVuLCBlbHNlX2Z1bmN0aW9uLCBhZnRlcl9mdW5jdGlvbikge1xuICAgIGxldCByZXN1bHQgPSBudWxsO1xuXG4gICAgdHJ5IHtcbiAgICAgIHJlc3VsdCA9IGRvX2Z1bigpO1xuICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgIGxldCBleF9yZXN1bHQgPSBudWxsO1xuXG4gICAgICBpZiAocmVzY3VlX2Z1bmN0aW9uKSB7XG4gICAgICAgIHRyeSB7XG4gICAgICAgICAgZXhfcmVzdWx0ID0gcmVzY3VlX2Z1bmN0aW9uKGUpO1xuICAgICAgICAgIHJldHVybiBleF9yZXN1bHQ7XG4gICAgICAgIH0gY2F0Y2ggKGV4KSB7XG4gICAgICAgICAgaWYgKGV4IGluc3RhbmNlb2YgUGF0dGVybnMuTWF0Y2hFcnJvcikge1xuICAgICAgICAgICAgdGhyb3cgZXg7XG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICB9XG5cbiAgICAgIGlmIChjYXRjaF9mdW4pIHtcbiAgICAgICAgdHJ5IHtcbiAgICAgICAgICBleF9yZXN1bHQgPSBjYXRjaF9mdW4oZSk7XG4gICAgICAgICAgcmV0dXJuIGV4X3Jlc3VsdDtcbiAgICAgICAgfSBjYXRjaCAoZXgpIHtcbiAgICAgICAgICBpZiAoZXggaW5zdGFuY2VvZiBQYXR0ZXJucy5NYXRjaEVycm9yKSB7XG4gICAgICAgICAgICB0aHJvdyBleDtcbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgIH1cblxuICAgICAgdGhyb3cgZTtcbiAgICB9IGZpbmFsbHkge1xuICAgICAgaWYgKGFmdGVyX2Z1bmN0aW9uKSB7XG4gICAgICAgIGFmdGVyX2Z1bmN0aW9uKCk7XG4gICAgICB9XG4gICAgfVxuXG4gICAgaWYgKGVsc2VfZnVuY3Rpb24pIHtcbiAgICAgIHRyeSB7XG4gICAgICAgIHJldHVybiBlbHNlX2Z1bmN0aW9uKHJlc3VsdCk7XG4gICAgICB9IGNhdGNoIChleCkge1xuICAgICAgICBpZiAoZXggaW5zdGFuY2VvZiBQYXR0ZXJucy5NYXRjaEVycm9yKSB7XG4gICAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdObyBNYXRjaCBGb3VuZCBpbiBFbHNlJyk7XG4gICAgICAgIH1cblxuICAgICAgICB0aHJvdyBleDtcbiAgICAgIH1cbiAgICB9IGVsc2Uge1xuICAgICAgcmV0dXJuIHJlc3VsdDtcbiAgICB9XG4gIH1cblxufTtcblxuZnVuY3Rpb24gdG9fc3RyaW5nJDEodHVwbGUpIHtcbiAgcmV0dXJuIHR1cGxlLnRvU3RyaW5nKCk7XG59O1xuXG5mdW5jdGlvbiBkZWxldGVfYXQodHVwbGUsIGluZGV4KSB7XG4gIGxldCBuZXdfbGlzdCA9IFtdO1xuXG4gIGZvciAodmFyIGkgPSAwOyBpIDwgdHVwbGUuY291bnQoKTsgaSsrKSB7XG4gICAgaWYgKGkgIT09IGluZGV4KSB7XG4gICAgICBuZXdfbGlzdC5wdXNoKHR1cGxlLmdldChpKSk7XG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIEtlcm5lbC5TcGVjaWFsRm9ybXMudHVwbGUuYXBwbHkobnVsbCwgbmV3X2xpc3QpO1xufTtcblxuZnVuY3Rpb24gZHVwbGljYXRlKGRhdGEsIHNpemUpIHtcbiAgbGV0IGFycmF5ID0gW107XG5cbiAgZm9yICh2YXIgaSA9IHNpemUgLSAxOyBpID49IDA7IGktLSkge1xuICAgIGFycmF5LnB1c2goZGF0YSk7XG4gIH1cblxuICByZXR1cm4gS2VybmVsLlNwZWNpYWxGb3Jtcy50dXBsZS5hcHBseShudWxsLCBhcnJheSk7XG59O1xuXG5mdW5jdGlvbiBpbnNlcnRfYXQodHVwbGUsIGluZGV4LCB0ZXJtKSB7XG4gIGxldCBuZXdfdHVwbGUgPSBbXTtcblxuICBmb3IgKHZhciBpID0gMDsgaSA8PSB0dXBsZS5jb3VudCgpOyBpKyspIHtcbiAgICBpZiAoaSA9PT0gaW5kZXgpIHtcbiAgICAgIG5ld190dXBsZS5wdXNoKHRlcm0pO1xuICAgICAgaSsrO1xuICAgICAgbmV3X3R1cGxlLnB1c2godHVwbGUuZ2V0KGkpKTtcbiAgICB9IGVsc2Uge1xuICAgICAgbmV3X3R1cGxlLnB1c2godHVwbGUuZ2V0KGkpKTtcbiAgICB9XG4gIH1cblxuICByZXR1cm4gS2VybmVsLlNwZWNpYWxGb3Jtcy50dXBsZS5hcHBseShudWxsLCBuZXdfdHVwbGUpO1xufTtcblxuZnVuY3Rpb24gZnJvbV9saXN0KGxpc3QpIHtcbiAgcmV0dXJuIEtlcm5lbC5TcGVjaWFsRm9ybXMudHVwbGUuYXBwbHkobnVsbCwgbGlzdCk7XG59O1xuXG5mdW5jdGlvbiB0b19saXN0KHR1cGxlKSB7XG4gIGxldCBuZXdfbGlzdCA9IFtdO1xuXG4gIGZvciAodmFyIGkgPSAwOyBpIDwgdHVwbGUuY291bnQoKTsgaSsrKSB7XG4gICAgbmV3X2xpc3QucHVzaCh0dXBsZS5nZXQoaSkpO1xuICB9XG5cbiAgcmV0dXJuIEtlcm5lbC5TcGVjaWFsRm9ybXMubGlzdCguLi5uZXdfbGlzdCk7XG59O1xuXG52YXIgVHVwbGUgPSB7XG4gIHRvX3N0cmluZzogdG9fc3RyaW5nJDEsXG4gIGRlbGV0ZV9hdCxcbiAgZHVwbGljYXRlLFxuICBpbnNlcnRfYXQsXG4gIGZyb21fbGlzdCxcbiAgdG9fbGlzdFxufTtcblxuLy9odHRwczovL2dpdGh1Yi5jb20vYWlycG9ydHloL3Byb3RvbW9ycGhpc21cbmNsYXNzIFByb3RvY29sIHtcbiAgY29uc3RydWN0b3Ioc3BlYykge1xuICAgIHRoaXMucmVnaXN0cnkgPSBuZXcgTWFwKCk7XG4gICAgdGhpcy5mYWxsYmFjayA9IG51bGw7XG5cbiAgICBmb3IgKGxldCBmdW5OYW1lIGluIHNwZWMpIHtcbiAgICAgIHRoaXNbZnVuTmFtZV0gPSBjcmVhdGVGdW4oZnVuTmFtZSkuYmluZCh0aGlzKTtcbiAgICB9XG5cbiAgICBmdW5jdGlvbiBjcmVhdGVGdW4oZnVuTmFtZSkge1xuXG4gICAgICByZXR1cm4gZnVuY3Rpb24gKC4uLmFyZ3MpIHtcbiAgICAgICAgbGV0IHRoaW5nID0gYXJnc1swXTtcbiAgICAgICAgbGV0IGZ1biA9IG51bGw7XG5cbiAgICAgICAgaWYgKE51bWJlci5pc0ludGVnZXIodGhpbmcpICYmIHRoaXMuaGFzSW1wbGVtZW50YXRpb24oSW50ZWdlciQxKSkge1xuICAgICAgICAgIGZ1biA9IHRoaXMucmVnaXN0cnkuZ2V0KEludGVnZXIkMSlbZnVuTmFtZV07XG4gICAgICAgIH0gZWxzZSBpZiAodHlwZW9mIHRoaW5nID09PSBcIm51bWJlclwiICYmICFOdW1iZXIuaXNJbnRlZ2VyKHRoaW5nKSAmJiB0aGlzLmhhc0ltcGxlbWVudGF0aW9uKEZsb2F0KSkge1xuICAgICAgICAgIGZ1biA9IHRoaXMucmVnaXN0cnkuZ2V0KEZsb2F0KVtmdW5OYW1lXTtcbiAgICAgICAgfSBlbHNlIGlmICh0aGlzLmhhc0ltcGxlbWVudGF0aW9uKHRoaW5nKSkge1xuICAgICAgICAgIGZ1biA9IHRoaXMucmVnaXN0cnkuZ2V0KHRoaW5nLmNvbnN0cnVjdG9yKVtmdW5OYW1lXTtcbiAgICAgICAgfSBlbHNlIGlmICh0aGlzLmZhbGxiYWNrKSB7XG4gICAgICAgICAgZnVuID0gdGhpcy5mYWxsYmFja1tmdW5OYW1lXTtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmIChmdW4gIT0gbnVsbCkge1xuICAgICAgICAgIGxldCByZXR2YWwgPSBmdW4uYXBwbHkodGhpcywgYXJncyk7XG4gICAgICAgICAgcmV0dXJuIHJldHZhbDtcbiAgICAgICAgfVxuXG4gICAgICAgIHRocm93IG5ldyBFcnJvcihcIk5vIGltcGxlbWVudGF0aW9uIGZvdW5kIGZvciBcIiArIHRoaW5nKTtcbiAgICAgIH07XG4gICAgfVxuICB9XG5cbiAgaW1wbGVtZW50YXRpb24odHlwZSwgaW1wbGVtZW50YXRpb24pIHtcbiAgICBpZiAodHlwZSA9PT0gbnVsbCkge1xuICAgICAgdGhpcy5mYWxsYmFjayA9IGltcGxlbWVudGF0aW9uO1xuICAgIH0gZWxzZSB7XG4gICAgICB0aGlzLnJlZ2lzdHJ5LnNldCh0eXBlLCBpbXBsZW1lbnRhdGlvbik7XG4gICAgfVxuICB9XG5cbiAgaGFzSW1wbGVtZW50YXRpb24odGhpbmcpIHtcbiAgICByZXR1cm4gdGhpcy5yZWdpc3RyeS5oYXModGhpbmcuY29uc3RydWN0b3IpO1xuICB9XG59XG5cbmZ1bmN0aW9uIHRsKGxpc3QpIHtcbiAgcmV0dXJuIFNwZWNpYWxGb3Jtcy5saXN0KC4uLmxpc3Quc2xpY2UoMSkpO1xufVxuXG5mdW5jdGlvbiBoZChsaXN0KSB7XG4gIHJldHVybiBsaXN0WzBdO1xufVxuXG5mdW5jdGlvbiBpc19uaWwoeCkge1xuICByZXR1cm4geCA9PT0gbnVsbDtcbn1cblxuZnVuY3Rpb24gaXNfYXRvbSh4KSB7XG4gIHJldHVybiB0eXBlb2YgeCA9PT0gJ3N5bWJvbCc7XG59XG5cbmZ1bmN0aW9uIGlzX2JpbmFyeSh4KSB7XG4gIHJldHVybiB0eXBlb2YgeCA9PT0gJ3N0cmluZycgfHwgeCBpbnN0YW5jZW9mIFN0cmluZztcbn1cblxuZnVuY3Rpb24gaXNfYm9vbGVhbih4KSB7XG4gIHJldHVybiB0eXBlb2YgeCA9PT0gJ2Jvb2xlYW4nIHx8IHggaW5zdGFuY2VvZiBCb29sZWFuO1xufVxuXG5mdW5jdGlvbiBpc19mdW5jdGlvbih4LCBhcml0eSA9IC0xKSB7XG4gIHJldHVybiB0eXBlb2YgeCA9PT0gJ2Z1bmN0aW9uJyB8fCB4IGluc3RhbmNlb2YgRnVuY3Rpb247XG59XG5cbmZ1bmN0aW9uIGlzX2Zsb2F0KHgpIHtcbiAgcmV0dXJuIGlzX251bWJlcih4KSAmJiAhTnVtYmVyLmlzSW50ZWdlcih4KTtcbn1cblxuZnVuY3Rpb24gaXNfaW50ZWdlcih4KSB7XG4gIHJldHVybiBOdW1iZXIuaXNJbnRlZ2VyKHgpO1xufVxuXG5mdW5jdGlvbiBpc19saXN0KHgpIHtcbiAgcmV0dXJuIHggaW5zdGFuY2VvZiBBcnJheTtcbn1cblxuZnVuY3Rpb24gaXNfbWFwKHgpIHtcbiAgcmV0dXJuIHR5cGVvZiB4ID09PSAnb2JqZWN0JyB8fCB4IGluc3RhbmNlb2YgT2JqZWN0O1xufVxuXG5mdW5jdGlvbiBpc19udW1iZXIoeCkge1xuICByZXR1cm4gdHlwZW9mIHggPT09ICdudW1iZXInO1xufVxuXG5mdW5jdGlvbiBpc190dXBsZSh4KSB7XG4gIHJldHVybiB4IGluc3RhbmNlb2YgVHVwbGUkMTtcbn1cblxuZnVuY3Rpb24gbGVuZ3RoKHgpIHtcbiAgcmV0dXJuIHgubGVuZ3RoO1xufVxuXG5mdW5jdGlvbiBpc19waWQoeCkge1xuICByZXR1cm4geCBpbnN0YW5jZW9mIFBJRDtcbn1cblxuZnVuY3Rpb24gaXNfcG9ydCh4KSB7XG4gIHJldHVybiBmYWxzZTtcbn1cblxuZnVuY3Rpb24gaXNfcmVmZXJlbmNlKHgpIHtcbiAgcmV0dXJuIGZhbHNlO1xufVxuXG5mdW5jdGlvbiBpc19iaXRzdHJpbmcoeCkge1xuICByZXR1cm4gaXNfYmluYXJ5KHgpIHx8IHggaW5zdGFuY2VvZiBCaXRTdHJpbmc7XG59XG5cbmZ1bmN0aW9uIF9faW5fXyhsZWZ0LCByaWdodCkge1xuICBmb3IgKGxldCB4IG9mIHJpZ2h0KSB7XG4gICAgaWYgKG1hdGNoX19xbWFya19fKGxlZnQsIHgpKSB7XG4gICAgICByZXR1cm4gdHJ1ZTtcbiAgICB9XG4gIH1cblxuICByZXR1cm4gZmFsc2U7XG59XG5cbmZ1bmN0aW9uIGFicyhudW1iZXIpIHtcbiAgcmV0dXJuIE1hdGguYWJzKG51bWJlcik7XG59XG5cbmZ1bmN0aW9uIHJvdW5kKG51bWJlcikge1xuICByZXR1cm4gTWF0aC5yb3VuZChudW1iZXIpO1xufVxuXG5mdW5jdGlvbiBlbGVtKHR1cGxlLCBpbmRleCkge1xuICBpZiAoaXNfbGlzdCh0dXBsZSkpIHtcbiAgICByZXR1cm4gdHVwbGVbaW5kZXhdO1xuICB9XG5cbiAgcmV0dXJuIHR1cGxlLmdldChpbmRleCk7XG59XG5cbmZ1bmN0aW9uIHJlbShsZWZ0LCByaWdodCkge1xuICByZXR1cm4gbGVmdCAlIHJpZ2h0O1xufVxuXG5mdW5jdGlvbiBkaXYobGVmdCwgcmlnaHQpIHtcbiAgcmV0dXJuIGxlZnQgLyByaWdodDtcbn1cblxuZnVuY3Rpb24gYW5kKGxlZnQsIHJpZ2h0KSB7XG4gIHJldHVybiBsZWZ0ICYmIHJpZ2h0O1xufVxuXG5mdW5jdGlvbiBvcihsZWZ0LCByaWdodCkge1xuICByZXR1cm4gbGVmdCB8fCByaWdodDtcbn1cblxuZnVuY3Rpb24gbm90KGFyZykge1xuICByZXR1cm4gIWFyZztcbn1cblxuZnVuY3Rpb24gYXBwbHkoLi4uYXJncykge1xuICBpZiAoYXJncy5sZW5ndGggPT09IDMpIHtcbiAgICBsZXQgbW9kID0gYXJnc1swXTtcbiAgICBsZXQgZnVuYyA9IGFyZ3NbMV07XG4gICAgbGV0IGZ1bmNfYXJncyA9IGFyZ3NbMl07XG4gICAgcmV0dXJuIG1vZFtmdW5jXS5hcHBseShudWxsLCBmdW5jX2FyZ3MpO1xuICB9IGVsc2Uge1xuICAgIGxldCBmdW5jID0gYXJnc1swXTtcbiAgICBsZXQgZnVuY19hcmdzID0gYXJnc1sxXTtcblxuICAgIHJldHVybiBmdW5jLmFwcGx5KG51bGwsIGZ1bmNfYXJncyk7XG4gIH1cbn1cblxuZnVuY3Rpb24gdG9fc3RyaW5nKGFyZykge1xuICBpZiAoaXNfdHVwbGUoYXJnKSkge1xuICAgIHJldHVybiBUdXBsZS50b19zdHJpbmcoYXJnKTtcbiAgfVxuXG4gIHJldHVybiBhcmcudG9TdHJpbmcoKTtcbn1cblxuZnVuY3Rpb24gbWF0Y2hfX3FtYXJrX18ocGF0dGVybiwgZXhwciwgZ3VhcmQgPSAoKSA9PiB0cnVlKSB7XG4gIHJldHVybiBQYXR0ZXJucy5tYXRjaF9ub190aHJvdyhwYXR0ZXJuLCBleHByLCBndWFyZCkgIT0gbnVsbDtcbn1cblxuZnVuY3Rpb24gZGVmc3RydWN0KGRlZmF1bHRzKSB7XG4gIHJldHVybiBjbGFzcyB7XG4gICAgY29uc3RydWN0b3IodXBkYXRlID0ge30pIHtcbiAgICAgIGxldCB0aGVfdmFsdWVzID0gT2JqZWN0LmFzc2lnbihkZWZhdWx0cywgdXBkYXRlKTtcbiAgICAgIE9iamVjdC5hc3NpZ24odGhpcywgdGhlX3ZhbHVlcyk7XG4gICAgfVxuXG4gICAgc3RhdGljIGNyZWF0ZSh1cGRhdGVzID0ge30pIHtcbiAgICAgIGxldCB4ID0gbmV3IHRoaXModXBkYXRlcyk7XG4gICAgICByZXR1cm4gT2JqZWN0LmZyZWV6ZSh4KTtcbiAgICB9XG4gIH07XG59XG5cbmZ1bmN0aW9uIGRlZnByb3RvY29sKHNwZWMpIHtcbiAgcmV0dXJuIG5ldyBQcm90b2NvbChzcGVjKTtcbn1cblxuZnVuY3Rpb24gZGVmaW1wbChwcm90b2NvbCwgdHlwZSwgaW1wbCkge1xuICBwcm90b2NvbC5pbXBsZW1lbnRhdGlvbih0eXBlLCBpbXBsKTtcbn1cblxudmFyIEtlcm5lbCA9IHtcbiAgU3BlY2lhbEZvcm1zLFxuICB0bCxcbiAgaGQsXG4gIGlzX25pbCxcbiAgaXNfYXRvbSxcbiAgaXNfYmluYXJ5LFxuICBpc19ib29sZWFuLFxuICBpc19mdW5jdGlvbixcbiAgaXNfZmxvYXQsXG4gIGlzX2ludGVnZXIsXG4gIGlzX2xpc3QsXG4gIGlzX21hcCxcbiAgaXNfbnVtYmVyLFxuICBpc190dXBsZSxcbiAgbGVuZ3RoLFxuICBpc19waWQsXG4gIGlzX3BvcnQsXG4gIGlzX3JlZmVyZW5jZSxcbiAgaXNfYml0c3RyaW5nLFxuICBpbjogX19pbl9fLFxuICBhYnMsXG4gIHJvdW5kLFxuICBlbGVtLFxuICByZW0sXG4gIGRpdixcbiAgYW5kLFxuICBvcixcbiAgbm90LFxuICBhcHBseSxcbiAgdG9fc3RyaW5nLFxuICBtYXRjaF9fcW1hcmtfXyxcbiAgZGVmc3RydWN0LFxuICBkZWZwcm90b2NvbCxcbiAgZGVmaW1wbFxufTtcblxubGV0IEF0b20gPSB7fTtcblxuQXRvbS50b19zdHJpbmcgPSBmdW5jdGlvbiAoYXRvbSkge1xuICByZXR1cm4gU3ltYm9sLmtleUZvcihhdG9tKTtcbn07XG5cbkF0b20udG9fY2hhcl9saXN0ID0gZnVuY3Rpb24gKGF0b20pIHtcbiAgcmV0dXJuIEF0b20udG9fc3RyaW5nKGF0b20pLnNwbGl0KCcnKTtcbn07XG5cbmxldCBJbnRlZ2VyID0ge1xuXG4gIGlzX2V2ZW46IGZ1bmN0aW9uIChuKSB7XG4gICAgcmV0dXJuIG4gJSAyID09PSAwO1xuICB9LFxuXG4gIGlzX29kZDogZnVuY3Rpb24gKG4pIHtcbiAgICByZXR1cm4gbiAlIDIgIT09IDA7XG4gIH0sXG5cbiAgcGFyc2U6IGZ1bmN0aW9uIChiaW4pIHtcbiAgICBsZXQgcmVzdWx0ID0gcGFyc2VJbnQoYmluKTtcblxuICAgIGlmIChpc05hTihyZXN1bHQpKSB7XG4gICAgICByZXR1cm4gS2VybmVsLlNwZWNpYWxGb3Jtcy5hdG9tKFwiZXJyb3JcIik7XG4gICAgfVxuXG4gICAgbGV0IGluZGV4T2ZEb3QgPSBiaW4uaW5kZXhPZihcIi5cIik7XG5cbiAgICBpZiAoaW5kZXhPZkRvdCA+PSAwKSB7XG4gICAgICByZXR1cm4gS2VybmVsLlNwZWNpYWxGb3Jtcy50dXBsZShyZXN1bHQsIGJpbi5zdWJzdHJpbmcoaW5kZXhPZkRvdCkpO1xuICAgIH1cblxuICAgIHJldHVybiBLZXJuZWwuU3BlY2lhbEZvcm1zLnR1cGxlKHJlc3VsdCwgXCJcIik7XG4gIH0sXG5cbiAgdG9fY2hhcl9saXN0OiBmdW5jdGlvbiAobnVtYmVyLCBiYXNlID0gMTApIHtcbiAgICByZXR1cm4gbnVtYmVyLnRvU3RyaW5nKGJhc2UpLnNwbGl0KFwiXCIpO1xuICB9LFxuXG4gIHRvX3N0cmluZzogZnVuY3Rpb24gKG51bWJlciwgYmFzZSA9IDEwKSB7XG4gICAgcmV0dXJuIG51bWJlci50b1N0cmluZyhiYXNlKTtcbiAgfVxufTtcblxubGV0IENoYXJzJDEgPSBLZXJuZWwuZGVmcHJvdG9jb2woe1xuICB0b19zdHJpbmc6IGZ1bmN0aW9uICh0aGluZykge31cbn0pO1xuXG5LZXJuZWwuZGVmaW1wbChDaGFycyQxLCBCaXRTdHJpbmcsIHtcbiAgdG9fc3RyaW5nOiBmdW5jdGlvbiAodGhpbmcpIHtcbiAgICBpZiAoS2VybmVsLmlzX2JpbmFyeSh0aGluZykpIHtcbiAgICAgIHJldHVybiB0aGluZztcbiAgICB9XG5cbiAgICByZXR1cm4gdGhpbmcudG9TdHJpbmcoKTtcbiAgfVxufSk7XG5cbktlcm5lbC5kZWZpbXBsKENoYXJzJDEsIFN5bWJvbCwge1xuICB0b19zdHJpbmc6IGZ1bmN0aW9uICh0aGluZykge1xuICAgIGlmIChuaWwpIHtcbiAgICAgIHJldHVybiBcIlwiO1xuICAgIH1cblxuICAgIHJldHVybiBBdG9tLnRvX3N0cmluZyh0aGluZyk7XG4gIH1cbn0pO1xuXG5LZXJuZWwuZGVmaW1wbChDaGFycyQxLCBJbnRlZ2VyJDEsIHtcbiAgdG9fc3RyaW5nOiBmdW5jdGlvbiAodGhpbmcpIHtcbiAgICByZXR1cm4gSW50ZWdlci50b19zdHJpbmcodGhpbmcpO1xuICB9XG59KTtcblxuS2VybmVsLmRlZmltcGwoQ2hhcnMkMSwgRmxvYXQsIHtcbiAgdG9fc3RyaW5nOiBmdW5jdGlvbiAodGhpbmcpIHtcbiAgICByZXR1cm4gdGhpbmcudG9TdHJpbmc7XG4gIH1cbn0pO1xuXG5LZXJuZWwuZGVmaW1wbChDaGFycyQxLCBBcnJheSwge1xuICB0b19zdHJpbmc6IGZ1bmN0aW9uICh0aGluZykge1xuICAgIHJldHVybiB0aGluZy50b1N0cmluZygpO1xuICB9XG59KTtcblxuS2VybmVsLmRlZmltcGwoQ2hhcnMkMSwgVHVwbGUkMSwge1xuICB0b19zdHJpbmc6IGZ1bmN0aW9uICh0aGluZykge1xuICAgIHJldHVybiBUdXBsZS50b19zdHJpbmcodGhpbmcpO1xuICB9XG59KTtcblxuS2VybmVsLmRlZmltcGwoQ2hhcnMkMSwgbnVsbCwge1xuICB0b19zdHJpbmc6IGZ1bmN0aW9uICh0aGluZykge1xuICAgIHJldHVybiB0aGluZy50b1N0cmluZygpO1xuICB9XG59KTtcblxuZnVuY3Rpb24gdG9fYXRvbShzdHJpbmcpIHtcbiAgcmV0dXJuIFN5bWJvbC5mb3Ioc3RyaW5nKTtcbn1cblxuZnVuY3Rpb24gdG9fZXhpc3RpbmdfYXRvbShzdHJpbmcpIHtcbiAgcmV0dXJuIFN5bWJvbC5mb3Ioc3RyaW5nKTtcbn1cblxuZnVuY3Rpb24gdG9fY2hhcl9saXN0KHN0cmluZykge1xuICByZXR1cm4gc3RyaW5nLnNwbGl0KCcnKTtcbn1cblxuZnVuY3Rpb24gdG9fZmxvYXQoc3RyaW5nKSB7XG4gIHJldHVybiBwYXJzZUZsb2F0KHN0cmluZyk7XG59XG5cbmZ1bmN0aW9uIHRvX2ludGVnZXIoc3RyaW5nLCBiYXNlID0gMTApIHtcbiAgcmV0dXJuIHBhcnNlSW50KHN0cmluZywgYmFzZSk7XG59XG5cbmZ1bmN0aW9uIHVwY2FzZShiaW5hcnkpIHtcbiAgcmV0dXJuIGJpbmFyeS50b1VwcGVyQ2FzZSgpO1xufVxuXG5mdW5jdGlvbiBkb3duY2FzZShiaW5hcnkpIHtcbiAgcmV0dXJuIGJpbmFyeS50b0xvd2VyQ2FzZSgpO1xufVxuXG5mdW5jdGlvbiBhdChzdHJpbmcsIHBvc2l0aW9uKSB7XG4gIGlmIChwb3NpdGlvbiA+IHN0cmluZy5sZW5ndGggLSAxKSB7XG4gICAgcmV0dXJuIG51bGw7XG4gIH1cblxuICByZXR1cm4gc3RyaW5nW3Bvc2l0aW9uXTtcbn1cblxuZnVuY3Rpb24gY2FwaXRhbGl6ZShzdHJpbmcpIHtcbiAgbGV0IHJldHVyblN0cmluZyA9ICcnO1xuXG4gIGZvciAobGV0IGkgPSAwOyBpIDwgc3RyaW5nLmxlbmd0aDsgaSsrKSB7XG4gICAgaWYgKGkgPT09IDApIHtcbiAgICAgIHJldHVyblN0cmluZyA9IHJldHVyblN0cmluZyArIHN0cmluZ1tpXS50b1VwcGVyQ2FzZSgpO1xuICAgIH0gZWxzZSB7XG4gICAgICByZXR1cm5TdHJpbmcgPSByZXR1cm5TdHJpbmcgKyBzdHJpbmdbaV0udG9Mb3dlckNhc2UoKTtcbiAgICB9XG4gIH1cblxuICByZXR1cm4gcmV0dXJuU3RyaW5nO1xufVxuXG5mdW5jdGlvbiBjb2RlcG9pbnRzKHN0cmluZykge1xuICByZXR1cm4gdG9fY2hhcl9saXN0KHN0cmluZykubWFwKGZ1bmN0aW9uIChjKSB7XG4gICAgcmV0dXJuIGMuY29kZVBvaW50QXQoMCk7XG4gIH0pO1xufVxuXG5mdW5jdGlvbiBjb250YWluc19fcW1fXyhzdHJpbmcsIGNvbnRhaW5zKSB7XG4gIGlmIChBcnJheS5pc0FycmF5KGNvbnRhaW5zKSkge1xuICAgIHJldHVybiBjb250YWlucy5zb21lKGZ1bmN0aW9uIChzKSB7XG4gICAgICByZXR1cm4gc3RyaW5nLmluZGV4T2YocykgPiAtMTtcbiAgICB9KTtcbiAgfVxuXG4gIHJldHVybiBzdHJpbmcuaW5kZXhPZihjb250YWlucykgPiAtMTtcbn1cblxuZnVuY3Rpb24gZHVwbGljYXRlJDEoc3ViamVjdCwgbikge1xuICByZXR1cm4gc3ViamVjdC5yZXBlYXQobik7XG59XG5cbmZ1bmN0aW9uIGVuZHNfd2l0aF9fcW1fXyhzdHJpbmcsIHN1ZmZpeGVzKSB7XG4gIGlmIChBcnJheS5pc0FycmF5KHN1ZmZpeGVzKSkge1xuICAgIHJldHVybiBzdWZmaXhlcy5zb21lKGZ1bmN0aW9uIChzKSB7XG4gICAgICByZXR1cm4gc3RyaW5nLmVuZHNXaXRoKHMpO1xuICAgIH0pO1xuICB9XG5cbiAgcmV0dXJuIHN0cmluZy5lbmRzV2l0aChzdWZmaXhlcyk7XG59XG5cbmZ1bmN0aW9uIGZpcnN0KHN0cmluZykge1xuICBpZiAoIXN0cmluZykge1xuICAgIHJldHVybiBudWxsO1xuICB9XG5cbiAgcmV0dXJuIHN0cmluZ1swXTtcbn1cblxuZnVuY3Rpb24gZ3JhcGhlbWVzKHN0cmluZykge1xuICByZXR1cm4gc3RyaW5nLnNwbGl0KCcnKTtcbn1cblxuZnVuY3Rpb24gbGFzdChzdHJpbmcpIHtcbiAgaWYgKCFzdHJpbmcpIHtcbiAgICByZXR1cm4gbnVsbDtcbiAgfVxuXG4gIHJldHVybiBzdHJpbmdbc3RyaW5nLmxlbmd0aCAtIDFdO1xufVxuXG5mdW5jdGlvbiBsZW5ndGgkMShzdHJpbmcpIHtcbiAgcmV0dXJuIHN0cmluZy5sZW5ndGg7XG59XG5cbmZ1bmN0aW9uIG1hdGNoX19xbV9fKHN0cmluZywgcmVnZXgpIHtcbiAgcmV0dXJuIHN0cmluZy5tYXRjaChyZWdleCkgIT0gbnVsbDtcbn1cblxuZnVuY3Rpb24gbmV4dF9jb2RlcG9pbnQoc3RyaW5nKSB7XG4gIGlmICghc3RyaW5nIHx8IHN0cmluZyA9PT0gJycpIHtcbiAgICByZXR1cm4gbnVsbDtcbiAgfVxuXG4gIHJldHVybiBLZXJuZWwuU3BlY2lhbEZvcm1zLnR1cGxlKHN0cmluZ1swXS5jb2RlUG9pbnRBdCgwKSwgc3RyaW5nLnN1YnN0cigxKSk7XG59XG5cbmZ1bmN0aW9uIG5leHRfZ3JhcGhlbWUoc3RyaW5nKSB7XG4gIGlmICghc3RyaW5nIHx8IHN0cmluZyA9PT0gJycpIHtcbiAgICByZXR1cm4gbnVsbDtcbiAgfVxuXG4gIHJldHVybiBLZXJuZWwuU3BlY2lhbEZvcm1zLnR1cGxlKHN0cmluZ1swXSwgc3RyaW5nLnN1YnN0cigxKSk7XG59XG5cbmZ1bmN0aW9uIHJldmVyc2Uoc3RyaW5nKSB7XG4gIGxldCByZXR1cm5WYWx1ZSA9ICcnO1xuXG4gIGZvciAodmFyIGkgPSBzdHJpbmcubGVuZ3RoIC0gMTsgaSA+PSAwOyBpLS0pIHtcbiAgICByZXR1cm5WYWx1ZSA9IHJldHVyblZhbHVlICsgc3RyaW5nW2ldO1xuICB9O1xuXG4gIHJldHVybiByZXR1cm5WYWx1ZTtcbn1cblxuZnVuY3Rpb24gc3BsaXQoc3RyaW5nKSB7XG4gIHJldHVybiBzdHJpbmcuc3BsaXQoKTtcbn1cblxuZnVuY3Rpb24gc3RhcnRzX3dpdGhfX3FtX18oc3RyaW5nLCBwcmVmaXhlcykge1xuICBpZiAoQXJyYXkuaXNBcnJheShwcmVmaXhlcykpIHtcbiAgICByZXR1cm4gcHJlZml4ZXMuc29tZShmdW5jdGlvbiAocykge1xuICAgICAgcmV0dXJuIHN0cmluZy5zdGFydHNXaXRoKHMpO1xuICAgIH0pO1xuICB9XG5cbiAgcmV0dXJuIHN0cmluZy5zdGFydHNXaXRoKHByZWZpeGVzKTtcbn1cblxuZnVuY3Rpb24gdmFsaWRfY2hhcmFjdGVyX19xbV9fKGNvZGVwb2ludCkge1xuICB0cnkge1xuICAgIHJldHVybiBTdHJpbmcuZnJvbUNvZGVQb2ludChjb2RlcG9pbnQpICE9IG51bGw7XG4gIH0gY2F0Y2ggKGUpIHtcbiAgICByZXR1cm4gZmFsc2U7XG4gIH1cbn1cblxudmFyIFN0cmluZyQxID0ge1xuICBhdCxcbiAgY2FwaXRhbGl6ZSxcbiAgY29kZXBvaW50cyxcbiAgY29udGFpbnNfX3FtX18sXG4gIGRvd25jYXNlLFxuICBkdXBsaWNhdGU6IGR1cGxpY2F0ZSQxLFxuICBlbmRzX3dpdGhfX3FtX18sXG4gIGZpcnN0LFxuICBncmFwaGVtZXMsXG4gIGxhc3QsXG4gIGxlbmd0aDogbGVuZ3RoJDEsXG4gIG1hdGNoX19xbV9fLFxuICBuZXh0X2NvZGVwb2ludCxcbiAgbmV4dF9ncmFwaGVtZSxcbiAgcmV2ZXJzZSxcbiAgc3BsaXQsXG4gIHN0YXJ0c193aXRoX19xbV9fLFxuICB0b19hdG9tLFxuICB0b19jaGFyX2xpc3QsXG4gIHRvX2V4aXN0aW5nX2F0b20sXG4gIHRvX2Zsb2F0LFxuICB0b19pbnRlZ2VyLFxuICB1cGNhc2UsXG4gIHZhbGlkX2NoYXJhY3Rlcl9fcW1fXyxcbiAgQ2hhcnM6IENoYXJzJDFcbn07XG5cbmxldCBDaGFycyA9IEtlcm5lbC5kZWZwcm90b2NvbCh7XG4gIHRvX2NoYXJfbGlzdDogZnVuY3Rpb24gKHRoaW5nKSB7fVxufSk7XG5cbktlcm5lbC5kZWZpbXBsKENoYXJzLCBCaXRTdHJpbmcsIHtcbiAgdG9fY2hhcl9saXN0OiBmdW5jdGlvbiAodGhpbmcpIHtcbiAgICBpZiAoS2VybmVsLmlzX2JpbmFyeSh0aGluZykpIHtcbiAgICAgIHJldHVybiBTdHJpbmckMS50b19jaGFyX2xpc3QodGhpbmcpO1xuICAgIH1cblxuICAgIHJldHVybiB0aGluZy50b1N0cmluZygpO1xuICB9XG59KTtcblxuS2VybmVsLmRlZmltcGwoQ2hhcnMsIFN5bWJvbCwge1xuICB0b19jaGFyX2xpc3Q6IGZ1bmN0aW9uICh0aGluZykge1xuICAgIHJldHVybiBBdG9tLnRvX2NoYXJfbGlzdCh0aGluZyk7XG4gIH1cbn0pO1xuXG5LZXJuZWwuZGVmaW1wbChDaGFycywgSW50ZWdlciQxLCB7XG4gIHRvX2NoYXJfbGlzdDogZnVuY3Rpb24gKHRoaW5nKSB7XG4gICAgcmV0dXJuIEludGVnZXIudG9fY2hhcl9saXN0KHRoaW5nKTtcbiAgfVxufSk7XG5cbktlcm5lbC5kZWZpbXBsKENoYXJzLCBBcnJheSwge1xuICB0b19jaGFyX2xpc3Q6IGZ1bmN0aW9uICh0aGluZykge1xuICAgIHJldHVybiB0aGluZztcbiAgfVxufSk7XG5cbmxldCBMaXN0ID0ge307XG5cbkxpc3QuQ2hhcnMgPSBDaGFycztcblxuTGlzdC5kZWxldGUgPSBmdW5jdGlvbiAobGlzdCwgaXRlbSkge1xuICBsZXQgbmV3X3ZhbHVlID0gW107XG4gIGxldCB2YWx1ZV9mb3VuZCA9IGZhbHNlO1xuXG4gIGZvciAobGV0IHggb2YgbGlzdCkge1xuICAgIGlmICh4ID09PSBpdGVtICYmIHZhbHVlX2ZvdW5kICE9PSBmYWxzZSkge1xuICAgICAgbmV3X3ZhbHVlLnB1c2goeCk7XG4gICAgICB2YWx1ZV9mb3VuZCA9IHRydWU7XG4gICAgfSBlbHNlIGlmICh4ICE9PSBpdGVtKSB7XG4gICAgICBuZXdfdmFsdWUucHVzaCh4KTtcbiAgICB9XG4gIH1cblxuICByZXR1cm4gS2VybmVsLlNwZWNpYWxGb3Jtcy5saXN0KC4uLm5ld192YWx1ZSk7XG59O1xuXG5MaXN0LmRlbGV0ZV9hdCA9IGZ1bmN0aW9uIChsaXN0LCBpbmRleCkge1xuICBsZXQgbmV3X3ZhbHVlID0gW107XG5cbiAgZm9yIChsZXQgaSA9IDA7IGkgPCBsaXN0Lmxlbmd0aDsgaSsrKSB7XG4gICAgaWYgKGkgIT09IGluZGV4KSB7XG4gICAgICBuZXdfdmFsdWUucHVzaChsaXN0W2ldKTtcbiAgICB9XG4gIH1cblxuICByZXR1cm4gS2VybmVsLlNwZWNpYWxGb3Jtcy5saXN0KC4uLm5ld192YWx1ZSk7XG59O1xuXG5MaXN0LmR1cGxpY2F0ZSA9IGZ1bmN0aW9uIChlbGVtLCBuKSB7XG4gIGxldCBuZXdfdmFsdWUgPSBbXTtcblxuICBmb3IgKHZhciBpID0gMDsgaSA8IG47IGkrKykge1xuICAgIG5ld192YWx1ZS5wdXNoKGVsZW0pO1xuICB9XG5cbiAgcmV0dXJuIEtlcm5lbC5TcGVjaWFsRm9ybXMubGlzdCguLi5uZXdfdmFsdWUpO1xufTtcblxuTGlzdC5maXJzdCA9IGZ1bmN0aW9uIChsaXN0KSB7XG4gIHJldHVybiBsaXN0WzBdO1xufTtcblxuTGlzdC5mbGF0dGVuID0gZnVuY3Rpb24gKGxpc3QsIHRhaWwgPSBLZXJuZWwuU3BlY2lhbEZvcm1zLmxpc3QoKSkge1xuICBsZXQgbmV3X3ZhbHVlID0gW107XG5cbiAgZm9yIChsZXQgeCBvZiBsaXN0KSB7XG4gICAgaWYgKEtlcm5lbC5pc19saXN0KHgpKSB7XG4gICAgICBuZXdfdmFsdWUgPSBuZXdfdmFsdWUuY29uY2F0KExpc3QuZmxhdHRlbih4KSk7XG4gICAgfSBlbHNlIHtcbiAgICAgIG5ld192YWx1ZS5wdXNoKHgpO1xuICAgIH1cbiAgfVxuXG4gIG5ld192YWx1ZSA9IG5ld192YWx1ZS5jb25jYXQodGFpbCk7XG5cbiAgcmV0dXJuIEtlcm5lbC5TcGVjaWFsRm9ybXMubGlzdCguLi5uZXdfdmFsdWUpO1xufTtcblxuTGlzdC5mb2xkbCA9IGZ1bmN0aW9uIChsaXN0LCBhY2MsIGZ1bmMpIHtcbiAgcmV0dXJuIGxpc3QucmVkdWNlKGZ1bmMsIGFjYyk7XG59O1xuXG5MaXN0LmZvbGRyID0gZnVuY3Rpb24gKGxpc3QsIGFjYywgZnVuYykge1xuICBsZXQgbmV3X2FjYyA9IGFjYztcblxuICBmb3IgKHZhciBpID0gbGlzdC5sZW5ndGggLSAxOyBpID49IDA7IGktLSkge1xuICAgIG5ld19hY2MgPSBmdW5jKGxpc3RbaV0sIG5ld19hY2MpO1xuICB9XG5cbiAgcmV0dXJuIG5ld19hY2M7XG59O1xuXG5MaXN0Lmluc2VydF9hdCA9IGZ1bmN0aW9uIChsaXN0LCBpbmRleCwgdmFsdWUpIHtcbiAgbGV0IG5ld192YWx1ZSA9IFtdO1xuXG4gIGZvciAobGV0IGkgPSAwOyBpIDwgbGlzdC5sZW5ndGg7IGkrKykge1xuICAgIGlmIChpID09PSBpbmRleCkge1xuICAgICAgbmV3X3ZhbHVlLnB1c2godmFsdWUpO1xuICAgICAgbmV3X3ZhbHVlLnB1c2gobGlzdFtpXSk7XG4gICAgfSBlbHNlIHtcbiAgICAgIG5ld192YWx1ZS5wdXNoKGxpc3RbaV0pO1xuICAgIH1cbiAgfVxuXG4gIHJldHVybiBLZXJuZWwuU3BlY2lhbEZvcm1zLmxpc3QoLi4ubmV3X3ZhbHVlKTtcbn07XG5cbkxpc3Qua2V5ZGVsZXRlID0gZnVuY3Rpb24gKGxpc3QsIGtleSwgcG9zaXRpb24pIHtcbiAgbGV0IG5ld19saXN0ID0gW107XG5cbiAgZm9yIChsZXQgaSA9IDA7IGkgPCBsaXN0Lmxlbmd0aDsgaSsrKSB7XG4gICAgaWYgKCFLZXJuZWwubWF0Y2hfX3FtYXJrX18obGlzdFtpXVtwb3NpdGlvbl0sIGtleSkpIHtcbiAgICAgIG5ld19saXN0LnB1c2gobGlzdFtpXSk7XG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIEtlcm5lbC5TcGVjaWFsRm9ybXMubGlzdCguLi5uZXdfbGlzdCk7XG59O1xuXG5MaXN0LmtleWZpbmQgPSBmdW5jdGlvbiAobGlzdCwga2V5LCBwb3NpdGlvbiwgX2RlZmF1bHQgPSBudWxsKSB7XG5cbiAgZm9yIChsZXQgaSA9IDA7IGkgPCBsaXN0Lmxlbmd0aDsgaSsrKSB7XG4gICAgaWYgKEtlcm5lbC5tYXRjaF9fcW1hcmtfXyhsaXN0W2ldW3Bvc2l0aW9uXSwga2V5KSkge1xuICAgICAgcmV0dXJuIGxpc3RbaV07XG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIF9kZWZhdWx0O1xufTtcblxuTGlzdC5rZXltZW1iZXJfX3FtYXJrX18gPSBmdW5jdGlvbiAobGlzdCwga2V5LCBwb3NpdGlvbikge1xuXG4gIGZvciAobGV0IGkgPSAwOyBpIDwgbGlzdC5sZW5ndGg7IGkrKykge1xuICAgIGlmIChLZXJuZWwubWF0Y2hfX3FtYXJrX18obGlzdFtpXVtwb3NpdGlvbl0sIGtleSkpIHtcbiAgICAgIHJldHVybiB0cnVlO1xuICAgIH1cbiAgfVxuXG4gIHJldHVybiBmYWxzZTtcbn07XG5cbkxpc3Qua2V5cmVwbGFjZSA9IGZ1bmN0aW9uIChsaXN0LCBrZXksIHBvc2l0aW9uLCBuZXdfdHVwbGUpIHtcbiAgbGV0IG5ld19saXN0ID0gW107XG5cbiAgZm9yIChsZXQgaSA9IDA7IGkgPCBsaXN0Lmxlbmd0aDsgaSsrKSB7XG4gICAgaWYgKCFLZXJuZWwubWF0Y2hfX3FtYXJrX18obGlzdFtpXVtwb3NpdGlvbl0sIGtleSkpIHtcbiAgICAgIG5ld19saXN0LnB1c2gobGlzdFtpXSk7XG4gICAgfSBlbHNlIHtcbiAgICAgIG5ld19saXN0LnB1c2gobmV3X3R1cGxlKTtcbiAgICB9XG4gIH1cblxuICByZXR1cm4gS2VybmVsLlNwZWNpYWxGb3Jtcy5saXN0KC4uLm5ld19saXN0KTtcbn07XG5cbkxpc3Qua2V5c29ydCA9IGZ1bmN0aW9uIChsaXN0LCBwb3NpdGlvbikge1xuICBsZXQgbmV3X2xpc3QgPSBsaXN0O1xuXG4gIG5ld19saXN0LnNvcnQoZnVuY3Rpb24gKGEsIGIpIHtcbiAgICBpZiAocG9zaXRpb24gPT09IDApIHtcbiAgICAgIGlmIChhW3Bvc2l0aW9uXS52YWx1ZSA8IGJbcG9zaXRpb25dLnZhbHVlKSB7XG4gICAgICAgIHJldHVybiAtMTtcbiAgICAgIH1cblxuICAgICAgaWYgKGFbcG9zaXRpb25dLnZhbHVlID4gYltwb3NpdGlvbl0udmFsdWUpIHtcbiAgICAgICAgcmV0dXJuIDE7XG4gICAgICB9XG5cbiAgICAgIHJldHVybiAwO1xuICAgIH0gZWxzZSB7XG4gICAgICBpZiAoYVtwb3NpdGlvbl0gPCBiW3Bvc2l0aW9uXSkge1xuICAgICAgICByZXR1cm4gLTE7XG4gICAgICB9XG5cbiAgICAgIGlmIChhW3Bvc2l0aW9uXSA+IGJbcG9zaXRpb25dKSB7XG4gICAgICAgIHJldHVybiAxO1xuICAgICAgfVxuXG4gICAgICByZXR1cm4gMDtcbiAgICB9XG4gIH0pO1xuXG4gIHJldHVybiBLZXJuZWwuU3BlY2lhbEZvcm1zLmxpc3QoLi4ubmV3X2xpc3QpO1xufTtcblxuTGlzdC5rZXlzdG9yZSA9IGZ1bmN0aW9uIChsaXN0LCBrZXksIHBvc2l0aW9uLCBuZXdfdHVwbGUpIHtcbiAgbGV0IG5ld19saXN0ID0gW107XG4gIGxldCByZXBsYWNlZCA9IGZhbHNlO1xuXG4gIGZvciAobGV0IGkgPSAwOyBpIDwgbGlzdC5sZW5ndGg7IGkrKykge1xuICAgIGlmICghS2VybmVsLm1hdGNoX19xbWFya19fKGxpc3RbaV1bcG9zaXRpb25dLCBrZXkpKSB7XG4gICAgICBuZXdfbGlzdC5wdXNoKGxpc3RbaV0pO1xuICAgIH0gZWxzZSB7XG4gICAgICBuZXdfbGlzdC5wdXNoKG5ld190dXBsZSk7XG4gICAgICByZXBsYWNlZCA9IHRydWU7XG4gICAgfVxuICB9XG5cbiAgaWYgKCFyZXBsYWNlZCkge1xuICAgIG5ld19saXN0LnB1c2gobmV3X3R1cGxlKTtcbiAgfVxuXG4gIHJldHVybiBLZXJuZWwuU3BlY2lhbEZvcm1zLmxpc3QoLi4ubmV3X2xpc3QpO1xufTtcblxuTGlzdC5sYXN0ID0gZnVuY3Rpb24gKGxpc3QpIHtcbiAgcmV0dXJuIGxpc3RbbGlzdC5sZW5ndGggLSAxXTtcbn07XG5cbkxpc3QucmVwbGFjZV9hdCA9IGZ1bmN0aW9uIChsaXN0LCBpbmRleCwgdmFsdWUpIHtcbiAgbGV0IG5ld192YWx1ZSA9IFtdO1xuXG4gIGZvciAobGV0IGkgPSAwOyBpIDwgbGlzdC5sZW5ndGg7IGkrKykge1xuICAgIGlmIChpID09PSBpbmRleCkge1xuICAgICAgbmV3X3ZhbHVlLnB1c2godmFsdWUpO1xuICAgIH0gZWxzZSB7XG4gICAgICBuZXdfdmFsdWUucHVzaChsaXN0W2ldKTtcbiAgICB9XG4gIH1cblxuICByZXR1cm4gS2VybmVsLlNwZWNpYWxGb3Jtcy5saXN0KC4uLm5ld192YWx1ZSk7XG59O1xuXG5MaXN0LnVwZGF0ZV9hdCA9IGZ1bmN0aW9uIChsaXN0LCBpbmRleCwgZnVuKSB7XG4gIGxldCBuZXdfdmFsdWUgPSBbXTtcblxuICBmb3IgKGxldCBpID0gMDsgaSA8IGxpc3QuY291bnQoKTsgaSsrKSB7XG4gICAgaWYgKGkgPT09IGluZGV4KSB7XG4gICAgICBuZXdfdmFsdWUucHVzaChmdW4obGlzdC5nZXQoaSkpKTtcbiAgICB9IGVsc2Uge1xuICAgICAgbmV3X3ZhbHVlLnB1c2gobGlzdC5nZXQoaSkpO1xuICAgIH1cbiAgfVxuXG4gIHJldHVybiBuZXdfdmFsdWU7XG59O1xuXG5MaXN0LndyYXAgPSBmdW5jdGlvbiAobGlzdCkge1xuICBpZiAoS2VybmVsLmlzX2xpc3QobGlzdCkpIHtcbiAgICByZXR1cm4gbGlzdDtcbiAgfSBlbHNlIGlmIChsaXN0ID09IG51bGwpIHtcbiAgICByZXR1cm4gS2VybmVsLlNwZWNpYWxGb3Jtcy5saXN0KCk7XG4gIH0gZWxzZSB7XG4gICAgcmV0dXJuIEtlcm5lbC5TcGVjaWFsRm9ybXMubGlzdChsaXN0KTtcbiAgfVxufTtcblxuTGlzdC56aXAgPSBmdW5jdGlvbiAobGlzdF9vZl9saXN0cykge1xuICBpZiAobGlzdF9vZl9saXN0cy5sZW5ndGggPT09IDApIHtcbiAgICByZXR1cm4gS2VybmVsLlNwZWNpYWxGb3Jtcy5saXN0KCk7XG4gIH1cblxuICBsZXQgbmV3X3ZhbHVlID0gW107XG4gIGxldCBzbWFsbGVzdF9sZW5ndGggPSBsaXN0X29mX2xpc3RzWzBdO1xuXG4gIGZvciAobGV0IHggb2YgbGlzdF9vZl9saXN0cykge1xuICAgIGlmICh4Lmxlbmd0aCA8IHNtYWxsZXN0X2xlbmd0aCkge1xuICAgICAgc21hbGxlc3RfbGVuZ3RoID0geC5sZW5ndGg7XG4gICAgfVxuICB9XG5cbiAgZm9yIChsZXQgaSA9IDA7IGkgPCBzbWFsbGVzdF9sZW5ndGg7IGkrKykge1xuICAgIGxldCBjdXJyZW50X3ZhbHVlID0gW107XG4gICAgZm9yIChsZXQgaiA9IDA7IGogPCBsaXN0X29mX2xpc3RzLmxlbmd0aDsgaisrKSB7XG4gICAgICBjdXJyZW50X3ZhbHVlLnB1c2gobGlzdF9vZl9saXN0c1tqXVtpXSk7XG4gICAgfVxuXG4gICAgbmV3X3ZhbHVlLnB1c2goS2VybmVsLlNwZWNpYWxGb3Jtcy50dXBsZSguLi5jdXJyZW50X3ZhbHVlKSk7XG4gIH1cblxuICByZXR1cm4gS2VybmVsLlNwZWNpYWxGb3Jtcy5saXN0KC4uLm5ld192YWx1ZSk7XG59O1xuXG5MaXN0LnRvX3R1cGxlID0gZnVuY3Rpb24gKGxpc3QpIHtcbiAgcmV0dXJuIEtlcm5lbC5TcGVjaWFsRm9ybXMudHVwbGUuYXBwbHkobnVsbCwgbGlzdCk7XG59O1xuXG5MaXN0LmFwcGVuZCA9IGZ1bmN0aW9uIChsaXN0LCB2YWx1ZSkge1xuICByZXR1cm4gS2VybmVsLlNwZWNpYWxGb3Jtcy5saXN0KC4uLmxpc3QuY29uY2F0KFt2YWx1ZV0pKTtcbn07XG5cbkxpc3QucHJlcGVuZCA9IGZ1bmN0aW9uIChsaXN0LCB2YWx1ZSkge1xuICByZXR1cm4gS2VybmVsLlNwZWNpYWxGb3Jtcy5saXN0KC4uLlt2YWx1ZV0uY29uY2F0KGxpc3QpKTtcbn07XG5cbkxpc3QuY29uY2F0ID0gZnVuY3Rpb24gKGxlZnQsIHJpZ2h0KSB7XG4gIHJldHVybiBsZWZ0LmNvbmNhdChyaWdodCk7XG59O1xuXG5sZXQgUmFuZ2UgPSBmdW5jdGlvbiAoX2ZpcnN0LCBfbGFzdCkge1xuICBpZiAoISh0aGlzIGluc3RhbmNlb2YgUmFuZ2UpKSB7XG4gICAgcmV0dXJuIG5ldyBSYW5nZShfZmlyc3QsIF9sYXN0KTtcbiAgfVxuXG4gIHRoaXMuZmlyc3QgPSBmdW5jdGlvbiAoKSB7XG4gICAgcmV0dXJuIF9maXJzdDtcbiAgfTtcblxuICB0aGlzLmxhc3QgPSBmdW5jdGlvbiAoKSB7XG4gICAgcmV0dXJuIF9sYXN0O1xuICB9O1xuXG4gIGxldCBfcmFuZ2UgPSBbXTtcblxuICBmb3IgKGxldCBpID0gX2ZpcnN0OyBpIDw9IF9sYXN0OyBpKyspIHtcbiAgICBfcmFuZ2UucHVzaChpKTtcbiAgfVxuXG4gIF9yYW5nZSA9IE9iamVjdC5mcmVlemUoX3JhbmdlKTtcblxuICB0aGlzLnZhbHVlID0gZnVuY3Rpb24gKCkge1xuICAgIHJldHVybiBfcmFuZ2U7XG4gIH07XG5cbiAgdGhpcy5sZW5ndGggPSBmdW5jdGlvbiAoKSB7XG4gICAgcmV0dXJuIF9yYW5nZS5sZW5ndGg7XG4gIH07XG5cbiAgcmV0dXJuIHRoaXM7XG59O1xuXG5SYW5nZS5wcm90b3R5cGVbU3ltYm9sLml0ZXJhdG9yXSA9IGZ1bmN0aW9uICgpIHtcbiAgcmV0dXJuIHRoaXMudmFsdWUoKVtTeW1ib2wuaXRlcmF0b3JdKCk7XG59O1xuXG5SYW5nZS5uZXcgPSBmdW5jdGlvbiAoZmlyc3QsIGxhc3QpIHtcbiAgcmV0dXJuIFJhbmdlKGZpcnN0LCBsYXN0KTtcbn07XG5cblJhbmdlLnJhbmdlX19xbWFya19fID0gZnVuY3Rpb24gKHJhbmdlKSB7XG4gIHJldHVybiByYW5nZSBpbnN0YW5jZW9mIFJhbmdlO1xufTtcblxubGV0IEtleXdvcmQgPSB7fTtcblxuS2V5d29yZC5oYXNfa2V5X19xbV9fID0gZnVuY3Rpb24gKGtleXdvcmRzLCBrZXkpIHtcbiAgZm9yIChsZXQga2V5d29yZCBvZiBrZXl3b3Jkcykge1xuICAgIGlmIChLZXJuZWwuZWxlbShrZXl3b3JkLCAwKSA9PSBrZXkpIHtcbiAgICAgIHJldHVybiB0cnVlO1xuICAgIH1cbiAgfVxuXG4gIHJldHVybiBmYWxzZTtcbn07XG5cbktleXdvcmQuZ2V0ID0gZnVuY3Rpb24gKGtleXdvcmRzLCBrZXksIHRoZV9kZWZhdWx0ID0gbnVsbCkge1xuICBmb3IgKGxldCBrZXl3b3JkIG9mIGtleXdvcmRzKSB7XG4gICAgaWYgKEtlcm5lbC5lbGVtKGtleXdvcmQsIDApID09IGtleSkge1xuICAgICAgcmV0dXJuIEtlcm5lbC5lbGVtKGtleXdvcmQsIDEpO1xuICAgIH1cbiAgfVxuXG4gIHJldHVybiB0aGVfZGVmYXVsdDtcbn07XG5cbmxldCBBZ2VudCA9IHt9O1xuXG5BZ2VudC5zdGFydCA9IGZ1bmN0aW9uIChmdW4sIG9wdGlvbnMgPSBbXSkge1xuICBsZXQgcGlkID0gc2VsZi5wcm9jZXNzZXMuc3Bhd24oKTtcblxuICBpZiAoS2V5d29yZC5oYXNfa2V5X19xbV9fKG9wdGlvbnMsIEtlcm5lbC5TcGVjaWFsRm9ybXMuYXRvbSgnbmFtZScpKSkge1xuICAgIHBpZCA9IHNlbGYucHJvY2Vzc2VzLnJlZ2lzdGVyKEtleXdvcmQuZ2V0KG9wdGlvbnMsIEtlcm5lbC5TcGVjaWFsRm9ybXMuYXRvbSgnbmFtZScpKSwgcGlkKTtcbiAgfVxuXG4gIHNlbGYucHJvY2Vzc2VzLnB1dChwaWQsICdzdGF0ZScsIGZ1bigpKTtcbiAgcmV0dXJuIEtlcm5lbC5TcGVjaWFsRm9ybXMudHVwbGUoS2VybmVsLlNwZWNpYWxGb3Jtcy5hdG9tKCdvaycpLCBwaWQpO1xufTtcblxuQWdlbnQuc3RvcCA9IGZ1bmN0aW9uIChhZ2VudCwgdGltZW91dCA9IDUwMDApIHtcbiAgc2VsZi5wcm9jZXNzZXMuZXhpdChhZ2VudCk7XG4gIHJldHVybiBLZXJuZWwuU3BlY2lhbEZvcm1zLmF0b20oJ29rJyk7XG59O1xuXG5BZ2VudC51cGRhdGUgPSBmdW5jdGlvbiAoYWdlbnQsIGZ1biwgdGltZW91dCA9IDUwMDApIHtcblxuICBjb25zdCBjdXJyZW50X3N0YXRlID0gc2VsZi5wcm9jZXNzZXMuZ2V0KGFnZW50LCAnc3RhdGUnKTtcbiAgc2VsZi5wcm9jZXNzZXMucHV0KGFnZW50LCAnc3RhdGUnLCBmdW4oY3VycmVudF9zdGF0ZSkpO1xuXG4gIHJldHVybiBLZXJuZWwuU3BlY2lhbEZvcm1zLmF0b20oJ29rJyk7XG59O1xuXG5BZ2VudC5nZXQgPSBmdW5jdGlvbiAoYWdlbnQsIGZ1biwgdGltZW91dCA9IDUwMDApIHtcbiAgcmV0dXJuIGZ1bihzZWxmLnByb2Nlc3Nlcy5nZXQoYWdlbnQsICdzdGF0ZScpKTtcbn07XG5cbkFnZW50LmdldF9hbmRfdXBkYXRlID0gZnVuY3Rpb24gKGFnZW50LCBmdW4sIHRpbWVvdXQgPSA1MDAwKSB7XG5cbiAgY29uc3QgZ2V0X2FuZF91cGRhdGVfdHVwbGUgPSBmdW4oc2VsZi5wcm9jZXNzZXMuZ2V0KGFnZW50LCAnc3RhdGUnKSk7XG4gIHNlbGYucHJvY2Vzc2VzLnB1dChhZ2VudCwgJ3N0YXRlJywgS2VybmVsLmVsZW0oZ2V0X2FuZF91cGRhdGVfdHVwbGUsIDEpKTtcblxuICByZXR1cm4gS2VybmVsLmVsZW0oZ2V0X2FuZF91cGRhdGVfdHVwbGUsIDApO1xufTtcblxuLy9odHRwczovL2RldmVsb3Blci5tb3ppbGxhLm9yZy9lbi1VUy9kb2NzL1dlYi9BUEkvV2luZG93QmFzZTY0L0Jhc2U2NF9lbmNvZGluZ19hbmRfZGVjb2RpbmcjU29sdXRpb25fMl8lRTIlODAlOTNfcmV3cml0ZV90aGVfRE9Nc19hdG9iKClfYW5kX2J0b2EoKV91c2luZ19KYXZhU2NyaXB0J3NfVHlwZWRBcnJheXNfYW5kX1VURi04XG5mdW5jdGlvbiBiNjRFbmNvZGVVbmljb2RlKHN0cikge1xuICByZXR1cm4gYnRvYShlbmNvZGVVUklDb21wb25lbnQoc3RyKS5yZXBsYWNlKC8lKFswLTlBLUZdezJ9KS9nLCBmdW5jdGlvbiAobWF0Y2gsIHAxKSB7XG4gICAgcmV0dXJuIFN0cmluZy5mcm9tQ2hhckNvZGUoJzB4JyArIHAxKTtcbiAgfSkpO1xufVxuXG5mdW5jdGlvbiBlbmNvZGU2NChkYXRhKSB7XG4gIHJldHVybiBiNjRFbmNvZGVVbmljb2RlKGRhdGEpO1xufVxuXG5mdW5jdGlvbiBkZWNvZGU2NChkYXRhKSB7XG4gIHRyeSB7XG4gICAgcmV0dXJuIEtlcm5lbC5TcGVjaWFsRm9ybXMudHVwbGUoS2VybmVsLlNwZWNpYWxGb3Jtcy5hdG9tKCdvaycpLCBhdG9iKGRhdGEpKTtcbiAgfSBjYXRjaCAoZSkge1xuICAgIHJldHVybiBLZXJuZWwuU3BlY2lhbEZvcm1zLmF0b20oJ2Vycm9yJyk7XG4gIH1cbiAgcmV0dXJuIGJ0b2EoZGF0YSk7XG59XG5cbmZ1bmN0aW9uIGRlY29kZTY0X19lbV9fKGRhdGEpIHtcbiAgcmV0dXJuIGF0b2IoZGF0YSk7XG59XG5cbnZhciBiYXNlID0ge1xuICBlbmNvZGU2NCxcbiAgZGVjb2RlNjQsXG4gIGRlY29kZTY0X19lbV9fXG59O1xuXG5mdW5jdGlvbiBibm90KGV4cHIpIHtcbiAgcmV0dXJuIH5leHByO1xufVxuXG5mdW5jdGlvbiBiYW5kKGxlZnQsIHJpZ2h0KSB7XG4gIHJldHVybiBsZWZ0ICYgcmlnaHQ7XG59XG5cbmZ1bmN0aW9uIGJvcihsZWZ0LCByaWdodCkge1xuICByZXR1cm4gbGVmdCB8IHJpZ2h0O1xufVxuXG5mdW5jdGlvbiBic2wobGVmdCwgcmlnaHQpIHtcbiAgcmV0dXJuIGxlZnQgPDwgcmlnaHQ7XG59XG5cbmZ1bmN0aW9uIGJzcihsZWZ0LCByaWdodCkge1xuICByZXR1cm4gbGVmdCA+PiByaWdodDtcbn1cblxuZnVuY3Rpb24gYnhvcihsZWZ0LCByaWdodCkge1xuICByZXR1cm4gbGVmdCBeIHJpZ2h0O1xufVxuXG52YXIgYml0d2lzZSA9IHtcbiAgYm5vdCxcbiAgYmFuZCxcbiAgYm9yLFxuICBic2wsXG4gIGJzcixcbiAgYnhvclxufTtcblxubGV0IEVudW1lcmFibGUgPSBLZXJuZWwuZGVmcHJvdG9jb2woe1xuICBjb3VudDogZnVuY3Rpb24gKGNvbGxlY3Rpb24pIHt9LFxuICBtZW1iZXJfcW1hcmtfXzogZnVuY3Rpb24gKGNvbGxlY3Rpb24sIHZhbHVlKSB7fSxcbiAgcmVkdWNlOiBmdW5jdGlvbiAoY29sbGVjdGlvbiwgYWNjLCBmdW4pIHt9XG59KTtcblxubGV0IENvbGxlY3RhYmxlID0gS2VybmVsLmRlZnByb3RvY29sKHtcbiAgaW50bzogZnVuY3Rpb24gKGNvbGxlY3RhYmxlKSB7fVxufSk7XG5cbmxldCBJbnNwZWN0ID0gS2VybmVsLmRlZnByb3RvY29sKHtcbiAgaW5zcGVjdDogZnVuY3Rpb24gKHRoaW5nLCBvcHRzKSB7fVxufSk7XG5cbmZ1bmN0aW9uIF9fbmV3X18oKSB7XG4gIHJldHVybiBTcGVjaWFsRm9ybXMubWFwKHt9KTtcbn1cblxuZnVuY3Rpb24ga2V5cyhtYXApIHtcbiAgcmV0dXJuIE9iamVjdC5rZXlzKG1hcCk7XG59XG5cbmZ1bmN0aW9uIHNpemUobWFwKSB7XG4gIHJldHVybiBrZXlzKG1hcCkubGVuZ3RoO1xufVxuXG5mdW5jdGlvbiB0b19saXN0JDEobWFwKSB7XG4gIGxldCBtYXBfa2V5cyA9IGtleXMobWFwKTtcbiAgbGV0IGxpc3QgPSBbXTtcblxuICBmb3IgKGxldCBrZXkgb2YgbWFwX2tleXMpIHtcbiAgICBsaXN0LnB1c2goU3BlY2lhbEZvcm1zLnR1cGxlKGtleSwgbWFwW2tleV0pKTtcbiAgfVxuXG4gIHJldHVybiBTcGVjaWFsRm9ybXMubGlzdCguLi5saXN0KTtcbn1cblxuZnVuY3Rpb24gdmFsdWVzKG1hcCkge1xuICBsZXQgbWFwX2tleXMgPSBrZXlzKG1hcCk7XG4gIGxldCBsaXN0ID0gW107XG5cbiAgZm9yIChsZXQga2V5IG9mIG1hcF9rZXlzKSB7XG4gICAgbGlzdC5wdXNoKG1hcFtrZXldKTtcbiAgfVxuXG4gIHJldHVybiBTcGVjaWFsRm9ybXMubGlzdCguLi5saXN0KTtcbn1cblxuZnVuY3Rpb24gZnJvbV9zdHJ1Y3Qoc3RydWN0KSB7XG4gIGxldCBtYXAgPSBPYmplY3QuYXNzaWduKHt9LCBzdHJ1Y3QpO1xuICBkZWxldGUgbWFwW1N5bWJvbC5mb3IoXCJfX3N0cnVjdF9fXCIpXTtcblxuICByZXR1cm4gU3BlY2lhbEZvcm1zLm1hcChtYXApO1xufVxuXG5mdW5jdGlvbiBfX2RlbGV0ZV9fKG1hcCwga2V5KSB7XG4gIGxldCBuZXdfbWFwID0gT2JqZWN0LmFzc2lnbih7fSwgbWFwKTtcblxuICBkZWxldGUgbmV3X21hcFtrZXldO1xuXG4gIHJldHVybiBTcGVjaWFsRm9ybXMubWFwKG5ld19tYXApO1xufVxuXG5mdW5jdGlvbiBlcXVhbF9fcW1hcmtfXyhtYXAxLCBtYXAyKSB7XG4gIHJldHVybiBtYXAxID09PSBtYXAyO1xufVxuXG5mdW5jdGlvbiBmZXRjaF9fZW1hcmtfXyhtYXAsIGtleSkge1xuICBpZiAoa2V5IGluIG1hcCkge1xuICAgIHJldHVybiBtYXBba2V5XTtcbiAgfVxuXG4gIHRocm93IG5ldyBFcnJvcihcIktleSBub3QgZm91bmQuXCIpO1xufVxuXG5mdW5jdGlvbiBmZXRjaChtYXAsIGtleSkge1xuICBpZiAoa2V5IGluIG1hcCkge1xuICAgIHJldHVybiBTcGVjaWFsRm9ybXMudHVwbGUoU3BlY2lhbEZvcm1zLmF0b20oXCJva1wiKSwgbWFwW2tleV0pO1xuICB9XG5cbiAgcmV0dXJuIFNwZWNpYWxGb3Jtcy5hdG9tKFwiZXJyb3JcIik7XG59XG5cbmZ1bmN0aW9uIGhhc19rZXlfX3FtYXJrX18obWFwLCBrZXkpIHtcbiAgcmV0dXJuIGtleSBpbiBtYXA7XG59XG5cbmZ1bmN0aW9uIHNwbGl0JDEobWFwLCBrZXlzKSB7XG4gIGxldCBzcGxpdDEgPSB7fTtcbiAgbGV0IHNwbGl0MiA9IHt9O1xuXG4gIGZvciAobGV0IGtleSBvZiBPYmplY3Qua2V5cyhtYXApKSB7XG4gICAgaWYgKGtleXMuaW5kZXhPZihrZXkpID4gLTEpIHtcbiAgICAgIHNwbGl0MVtrZXldID0gbWFwW2tleV07XG4gICAgfSBlbHNlIHtcbiAgICAgIHNwbGl0MltrZXldID0gbWFwW2tleV07XG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIFNwZWNpYWxGb3Jtcy50dXBsZShTcGVjaWFsRm9ybXMubWFwKHNwbGl0MSksIFNwZWNpYWxGb3Jtcy5tYXAoc3BsaXQyKSk7XG59XG5cbmZ1bmN0aW9uIHRha2UobWFwLCBrZXlzKSB7XG4gIGxldCBzcGxpdDEgPSB7fTtcblxuICBmb3IgKGxldCBrZXkgb2YgT2JqZWN0LmtleXMobWFwKSkge1xuICAgIGlmIChrZXlzLmluZGV4T2Yoa2V5KSA+IC0xKSB7XG4gICAgICBzcGxpdDFba2V5XSA9IG1hcFtrZXldO1xuICAgIH1cbiAgfVxuXG4gIHJldHVybiBTcGVjaWFsRm9ybXMubWFwKHNwbGl0MSk7XG59XG5cbmZ1bmN0aW9uIGRyb3AobWFwLCBrZXlzKSB7XG4gIGxldCBzcGxpdDEgPSB7fTtcblxuICBmb3IgKGxldCBrZXkgb2YgT2JqZWN0LmtleXMobWFwKSkge1xuICAgIGlmIChrZXlzLmluZGV4T2Yoa2V5KSA9PT0gLTEpIHtcbiAgICAgIHNwbGl0MVtrZXldID0gbWFwW2tleV07XG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIFNwZWNpYWxGb3Jtcy5tYXAoc3BsaXQxKTtcbn1cblxuZnVuY3Rpb24gcHV0X25ldyhtYXAsIGtleSwgdmFsdWUpIHtcbiAgaWYgKGtleSBpbiBtYXApIHtcbiAgICByZXR1cm4gbWFwO1xuICB9XG5cbiAgbGV0IG5ld19tYXAgPSBPYmplY3QuYXNzaWduKHt9LCBtYXApO1xuICBuZXdfbWFwW2tleV0gPSB2YWx1ZTtcblxuICByZXR1cm4gU3BlY2lhbEZvcm1zLm1hcChuZXdfbWFwKTtcbn1cblxuZnVuY3Rpb24gcHV0X25ld19sYXp5KG1hcCwga2V5LCBmdW4pIHtcbiAgaWYgKGtleSBpbiBtYXApIHtcbiAgICByZXR1cm4gbWFwO1xuICB9XG5cbiAgbGV0IG5ld19tYXAgPSBPYmplY3QuYXNzaWduKHt9LCBtYXApO1xuICBuZXdfbWFwW2tleV0gPSBmdW4oKTtcblxuICByZXR1cm4gU3BlY2lhbEZvcm1zLm1hcChuZXdfbWFwKTtcbn1cblxuZnVuY3Rpb24gZ2V0X2FuZF91cGRhdGUobWFwLCBrZXksIGZ1bikge1xuICBpZiAoa2V5IGluIG1hcCkge1xuICAgIHJldHVybiBtYXA7XG4gIH1cblxuICBsZXQgbmV3X21hcCA9IE9iamVjdC5hc3NpZ24oe30sIG1hcCk7XG4gIG5ld19tYXBba2V5XSA9IGZ1bihtYXBba2V5XSk7XG5cbiAgcmV0dXJuIFNwZWNpYWxGb3Jtcy5tYXAobmV3X21hcCk7XG59XG5cbmZ1bmN0aW9uIHBvcF9sYXp5KG1hcCwga2V5LCBmdW4pIHtcbiAgaWYgKCFrZXkgaW4gbWFwKSB7XG4gICAgcmV0dXJuIFNwZWNpYWxGb3Jtcy50dXBsZShmdW4oKSwgbWFwKTtcbiAgfVxuXG4gIGxldCBuZXdfbWFwID0gT2JqZWN0LmFzc2lnbih7fSwgbWFwKTtcbiAgbGV0IHZhbHVlID0gZnVuKG5ld19tYXBba2V5XSk7XG4gIGRlbGV0ZSBuZXdfbWFwW2tleV07XG5cbiAgcmV0dXJuIFNwZWNpYWxGb3Jtcy50dXBsZSh2YWx1ZSwgbmV3X21hcCk7XG59XG5cbmZ1bmN0aW9uIHBvcChtYXAsIGtleSwgX2RlZmF1bHQgPSBudWxsKSB7XG4gIGlmICgha2V5IGluIG1hcCkge1xuICAgIHJldHVybiBTcGVjaWFsRm9ybXMudHVwbGUoX2RlZmF1bHQsIG1hcCk7XG4gIH1cblxuICBsZXQgbmV3X21hcCA9IE9iamVjdC5hc3NpZ24oe30sIG1hcCk7XG4gIGxldCB2YWx1ZSA9IG5ld19tYXBba2V5XTtcbiAgZGVsZXRlIG5ld19tYXBba2V5XTtcblxuICByZXR1cm4gU3BlY2lhbEZvcm1zLnR1cGxlKHZhbHVlLCBuZXdfbWFwKTtcbn1cblxuZnVuY3Rpb24gZ2V0X2xhenkobWFwLCBrZXksIGZ1bikge1xuICBpZiAoIWtleSBpbiBtYXApIHtcbiAgICByZXR1cm4gZnVuKCk7XG4gIH1cblxuICByZXR1cm4gZnVuKG1hcFtrZXldKTtcbn1cblxuZnVuY3Rpb24gZ2V0KG1hcCwga2V5LCBfZGVmYXVsdCA9IG51bGwpIHtcbiAgaWYgKCFrZXkgaW4gbWFwKSB7XG4gICAgcmV0dXJuIF9kZWZhdWx0O1xuICB9XG5cbiAgcmV0dXJuIG1hcFtrZXldO1xufVxuXG5mdW5jdGlvbiBwdXQobWFwLCBrZXksIHZhbCkge1xuICBsZXQgbmV3X21hcCA9IE9iamVjdCh7fSwgbWFwKTtcbiAgbmV3X21hcFtrZXldID0gdmFsO1xuXG4gIHJldHVybiBTcGVjaWFsRm9ybXMubWFwKG5ld19tYXApO1xufVxuXG5mdW5jdGlvbiB1cGRhdGVfX2VtYXJrX18obWFwLCBrZXksIGZ1bikge1xuICBpZiAoIWtleSBpbiBtYXApIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoXCJLZXkgbm90IGZvdW5kXCIpO1xuICB9XG5cbiAgbGV0IG5ld19tYXAgPSBPYmplY3Qoe30sIG1hcCk7XG4gIG5ld19tYXBba2V5XSA9IGZ1bihtYXBba2V5XSk7XG5cbiAgcmV0dXJuIFNwZWNpYWxGb3Jtcy5tYXAobmV3X21hcCk7XG59XG5cbmZ1bmN0aW9uIHVwZGF0ZShtYXAsIGtleSwgaW5pdGlhbCwgZnVuKSB7XG4gIGxldCBuZXdfbWFwID0gT2JqZWN0KHt9LCBtYXApO1xuXG4gIGlmICgha2V5IGluIG1hcCkge1xuICAgIG5ld19tYXBba2V5XSA9IGluaXRpYWw7XG4gIH0gZWxzZSB7XG4gICAgbmV3X21hcFtrZXldID0gZnVuKG1hcFtrZXldKTtcbiAgfVxuXG4gIHJldHVybiBTcGVjaWFsRm9ybXMubWFwKG5ld19tYXApO1xufVxuXG52YXIgbWFwID0ge1xuICBuZXc6IF9fbmV3X18sXG4gIGtleXMsXG4gIHNpemUsXG4gIHRvX2xpc3Q6IHRvX2xpc3QkMSxcbiAgdmFsdWVzLFxuICBmcm9tX3N0cnVjdCxcbiAgZGVsZXRlOiBfX2RlbGV0ZV9fLFxuICBkcm9wLFxuICBlcXVhbF9fcW1hcmtfXyxcbiAgZmV0Y2hfX2VtYXJrX18sXG4gIGZldGNoLFxuICBoYXNfa2V5X19xbWFya19fLFxuICBzcGxpdDogc3BsaXQkMSxcbiAgdGFrZSxcbiAgcHV0X25ldyxcbiAgcHV0X25ld19sYXp5LFxuICBnZXRfYW5kX3VwZGF0ZSxcbiAgcG9wX2xhenksXG4gIHBvcCxcbiAgZ2V0X2xhenksXG4gIGdldCxcbiAgcHV0LFxuICB1cGRhdGVfX2VtYXJrX18sXG4gIHVwZGF0ZVxufTtcblxuZnVuY3Rpb24gX19uZXdfXyQxKCkge1xuICByZXR1cm4gU3BlY2lhbEZvcm1zLm1hcCh7IFtTeW1ib2wuZm9yKCdfX3N0cnVjdF9fJyldOiBTeW1ib2wuZm9yKCdNYXBTZXQnKSwgc2V0OiBTcGVjaWFsRm9ybXMubGlzdCgpIH0pO1xufVxuXG5mdW5jdGlvbiBzaXplJDIobWFwKSB7XG4gIHJldHVybiBtYXAuc2V0Lmxlbmd0aDtcbn1cblxuZnVuY3Rpb24gdG9fbGlzdCQzKG1hcCkge1xuICByZXR1cm4gbWFwLnNldDtcbn1cblxuZnVuY3Rpb24gX19kZWxldGVfXyQyKHNldCwgdGVybSkge1xuICBsZXQgbmV3X2xpc3QgPSBMaXN0LmRlbGV0ZShzZXQuc2V0LCB0ZXJtKTtcblxuICBsZXQgbmV3X21hcCA9IE9iamVjdC5hc3NpZ24oe30sIHNldCk7XG4gIG5ld19tYXAuc2V0ID0gbmV3X2xpc3Q7XG4gIHJldHVybiBTcGVjaWFsRm9ybXMubWFwKG5ld19tYXApO1xufVxuXG5mdW5jdGlvbiBwdXQkMihzZXQsIHRlcm0pIHtcbiAgaWYgKHNldC5zZXQuaW5kZXhPZih0ZXJtKSA9PT0gLTEpIHtcbiAgICBsZXQgbmV3X2xpc3QgPSBMaXN0LmFwcGVuZChzZXQuc2V0LCB0ZXJtKTtcblxuICAgIGxldCBuZXdfbWFwID0gT2JqZWN0LmFzc2lnbih7fSwgc2V0KTtcbiAgICBuZXdfbWFwLnNldCA9IG5ld19saXN0O1xuICAgIHJldHVybiBTcGVjaWFsRm9ybXMubWFwKG5ld19tYXApO1xuICB9XG5cbiAgcmV0dXJuIHNldDtcbn1cblxuZnVuY3Rpb24gZGlmZmVyZW5jZSQxKHNldDEsIHNldDIpIHtcbiAgbGV0IG5ld19tYXAgPSBPYmplY3QuYXNzaWduKHt9LCBzZXQxKTtcblxuICBmb3IgKGxldCB2YWwgb2Ygc2V0MS5zZXQpIHtcbiAgICBpZiAobWVtYmVyX19xbWFya19fJDEoc2V0MiwgdmFsKSkge1xuICAgICAgbmV3X21hcC5zZXQgPSBMaXN0LmRlbGV0ZShuZXdfbWFwLnNldCwgdmFsKTtcbiAgICB9XG4gIH1cblxuICByZXR1cm4gU3BlY2lhbEZvcm1zLm1hcChuZXdfbWFwKTtcbn1cblxuZnVuY3Rpb24gaW50ZXJzZWN0aW9uJDEoc2V0MSwgc2V0Mikge1xuICBsZXQgbmV3X21hcCA9IE9iamVjdC5hc3NpZ24oe30sIHNldDEpO1xuXG4gIGZvciAobGV0IHZhbCBvZiBzZXQxLnNldCkge1xuICAgIGlmICghbWVtYmVyX19xbWFya19fJDEoc2V0MiwgdmFsKSkge1xuICAgICAgbmV3X21hcC5zZXQgPSBMaXN0LmRlbGV0ZShuZXdfbWFwLnNldCwgdmFsKTtcbiAgICB9XG4gIH1cblxuICByZXR1cm4gU3BlY2lhbEZvcm1zLm1hcChuZXdfbWFwKTtcbn1cblxuZnVuY3Rpb24gdW5pb24kMShzZXQxLCBzZXQyKSB7XG4gIGxldCBuZXdfbWFwID0gc2V0MTtcblxuICBmb3IgKGxldCB2YWwgb2Ygc2V0Mi5zZXQpIHtcbiAgICBuZXdfbWFwID0gcHV0JDIobmV3X21hcCwgdmFsKTtcbiAgfVxuXG4gIHJldHVybiBTcGVjaWFsRm9ybXMubWFwKG5ld19tYXApO1xufVxuXG5mdW5jdGlvbiBkaXNqb2luX19xbWFya19fJDEoc2V0MSwgc2V0Mikge1xuICBmb3IgKGxldCB2YWwgb2Ygc2V0MS5zZXQpIHtcbiAgICBpZiAobWVtYmVyX19xbWFya19fJDEoc2V0MiwgdmFsKSkge1xuICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH1cbiAgfVxuXG4gIHJldHVybiB0cnVlO1xufVxuXG5mdW5jdGlvbiBtZW1iZXJfX3FtYXJrX18kMShzZXQsIHZhbHVlKSB7XG4gIHJldHVybiBzZXQuc2V0LmluZGV4T2YodmFsdWUpID49IDA7XG59XG5cbmZ1bmN0aW9uIGVxdWFsX19xbWFya19fJDIoc2V0MSwgc2V0Mikge1xuICByZXR1cm4gc2V0MS5zZXQgPT09IHNldDIuc2V0O1xufVxuXG5mdW5jdGlvbiBzdWJzZXRfX3FtYXJrX18kMShzZXQxLCBzZXQyKSB7XG4gIGZvciAobGV0IHZhbCBvZiBzZXQxLnNldCkge1xuICAgIGlmICghbWVtYmVyX19xbWFya19fJDEoc2V0MiwgdmFsKSkge1xuICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH1cbiAgfVxuXG4gIHJldHVybiB0cnVlO1xufVxuXG52YXIgTWFwU2V0ID0ge1xuICBuZXc6IF9fbmV3X18kMSxcbiAgc2l6ZTogc2l6ZSQyLFxuICB0b19saXN0OiB0b19saXN0JDMsXG4gIGRpc2pvaW5fX3FtYXJrX186IGRpc2pvaW5fX3FtYXJrX18kMSxcbiAgZGVsZXRlOiBfX2RlbGV0ZV9fJDIsXG4gIHN1YnNldF9fcW1hcmtfXzogc3Vic2V0X19xbWFya19fJDEsXG4gIGVxdWFsX19xbWFya19fOiBlcXVhbF9fcW1hcmtfXyQyLFxuICBtZW1iZXJfX3FtYXJrX186IG1lbWJlcl9fcW1hcmtfXyQxLFxuICBwdXQ6IHB1dCQyLFxuICB1bmlvbjogdW5pb24kMSxcbiAgaW50ZXJzZWN0aW9uOiBpbnRlcnNlY3Rpb24kMSxcbiAgZGlmZmVyZW5jZTogZGlmZmVyZW5jZSQxXG59O1xuXG5mdW5jdGlvbiBzaXplJDEobWFwKSB7XG4gIHJldHVybiBNYXBTZXQuc2l6ZShtYXApO1xufVxuXG5mdW5jdGlvbiB0b19saXN0JDIobWFwKSB7XG4gIHJldHVybiBNYXBTZXQudG9fbGlzdChtYXApO1xufVxuXG5mdW5jdGlvbiBfX2RlbGV0ZV9fJDEoc2V0LCB0ZXJtKSB7XG4gIHJldHVybiBNYXBTZXQuZGVsZXRlKHNldCwgdGVybSk7XG59XG5cbmZ1bmN0aW9uIHB1dCQxKHNldCwgdGVybSkge1xuICByZXR1cm4gTWFwU2V0LnB1dChzZXQsIHRlcm0pO1xufVxuXG5mdW5jdGlvbiBkaWZmZXJlbmNlKHNldDEsIHNldDIpIHtcbiAgcmV0dXJuIE1hcFNldC5kaWZmZXJlbmNlKHNldDEsIHNldDIpO1xufVxuXG5mdW5jdGlvbiBpbnRlcnNlY3Rpb24oc2V0MSwgc2V0Mikge1xuICByZXR1cm4gTWFwU2V0LmludGVyc2VjdGlvbihzZXQxLCBzZXQyKTtcbn1cblxuZnVuY3Rpb24gdW5pb24oc2V0MSwgc2V0Mikge1xuICByZXR1cm4gTWFwU2V0LnVuaW9uKHNldDEsIHNldDIpO1xufVxuXG5mdW5jdGlvbiBkaXNqb2luX19xbWFya19fKHNldDEsIHNldDIpIHtcbiAgcmV0dXJuIE1hcFNldC5kaXNqb2luX19xbWFya19fKHNldDEsIHNldDIpO1xufVxuXG5mdW5jdGlvbiBtZW1iZXJfX3FtYXJrX18oc2V0LCB2YWx1ZSkge1xuICByZXR1cm4gTWFwU2V0Lm1lbWJlcl9fcW1hcmtfXyhzZXQxLCBzZXQyKTtcbn1cblxuZnVuY3Rpb24gZXF1YWxfX3FtYXJrX18kMShzZXQxLCBzZXQyKSB7XG4gIHJldHVybiBNYXBTZXQuZXF1YWxfX3FtYXJrX18oc2V0MSwgc2V0Mik7XG59XG5cbmZ1bmN0aW9uIHN1YnNldF9fcW1hcmtfXyhzZXQxLCBzZXQyKSB7XG4gIHJldHVybiBNYXBTZXQuc3Vic2V0X19xbWFya19fKHNldDEsIHNldDIpO1xufVxuXG52YXIgc2V0ID0ge1xuICBzaXplOiBzaXplJDEsXG4gIHRvX2xpc3Q6IHRvX2xpc3QkMixcbiAgZGlzam9pbl9fcW1hcmtfXyxcbiAgZGVsZXRlOiBfX2RlbGV0ZV9fJDEsXG4gIHN1YnNldF9fcW1hcmtfXyxcbiAgZXF1YWxfX3FtYXJrX186IGVxdWFsX19xbWFya19fJDEsXG4gIG1lbWJlcl9fcW1hcmtfXyxcbiAgcHV0OiBwdXQkMSxcbiAgdW5pb24sXG4gIGludGVyc2VjdGlvbixcbiAgZGlmZmVyZW5jZVxufTtcblxubGV0IFZpcnR1YWxET00gPSAoZnVuY3Rpb24gKGUpIHtcbiAgICByZXR1cm4gZSgpO1xufSkoZnVuY3Rpb24gKCkge1xuICAgIHZhciBkZWZpbmUsIG1vZHVsZSwgZXhwb3J0cztcbiAgICByZXR1cm4gKGZ1bmN0aW9uIGUodCwgbiwgcikge1xuICAgICAgICBmdW5jdGlvbiBzKG8sIHUpIHtcbiAgICAgICAgICAgIGlmICghbltvXSkge1xuICAgICAgICAgICAgICAgIGlmICghdFtvXSkge1xuICAgICAgICAgICAgICAgICAgICB2YXIgYSA9IHR5cGVvZiByZXF1aXJlID09IFwiZnVuY3Rpb25cIiAmJiByZXF1aXJlO1xuICAgICAgICAgICAgICAgICAgICBpZiAoIXUgJiYgYSkgcmV0dXJuIGEobywgITApO1xuICAgICAgICAgICAgICAgICAgICBpZiAoaSkgcmV0dXJuIGkobywgITApO1xuICAgICAgICAgICAgICAgICAgICB2YXIgZiA9IG5ldyBFcnJvcihcIkNhbm5vdCBmaW5kIG1vZHVsZSAnXCIgKyBvICsgXCInXCIpO1xuICAgICAgICAgICAgICAgICAgICB0aHJvdyAoZi5jb2RlID0gXCJNT0RVTEVfTk9UX0ZPVU5EXCIsIGYpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB2YXIgbCA9IG5bb10gPSB7XG4gICAgICAgICAgICAgICAgICAgIGV4cG9ydHM6IHt9XG4gICAgICAgICAgICAgICAgfTtcbiAgICAgICAgICAgICAgICB0W29dWzBdLmNhbGwobC5leHBvcnRzLCBmdW5jdGlvbiAoZSkge1xuICAgICAgICAgICAgICAgICAgICB2YXIgbiA9IHRbb11bMV1bZV07XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBzKG4gPyBuIDogZSk7XG4gICAgICAgICAgICAgICAgfSwgbCwgbC5leHBvcnRzLCBlLCB0LCBuLCByKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJldHVybiBuW29dLmV4cG9ydHM7XG4gICAgICAgIH1cbiAgICAgICAgdmFyIGkgPSB0eXBlb2YgcmVxdWlyZSA9PSBcImZ1bmN0aW9uXCIgJiYgcmVxdWlyZTtcbiAgICAgICAgZm9yICh2YXIgbyA9IDA7IG8gPCByLmxlbmd0aDsgbysrKSBzKHJbb10pO1xuICAgICAgICByZXR1cm4gcztcbiAgICB9KSh7XG4gICAgICAgIDE6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG5cbiAgICAgICAgICAgIHZhciBjcmVhdGVFbGVtZW50ID0gcmVxdWlyZShcIi4vdmRvbS9jcmVhdGUtZWxlbWVudC5qc1wiKTtcblxuICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBjcmVhdGVFbGVtZW50O1xuICAgICAgICB9LCB7IFwiLi92ZG9tL2NyZWF0ZS1lbGVtZW50LmpzXCI6IDE1IH1dLCAyOiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge1xuICAgICAgICAgICAgdmFyIGRpZmYgPSByZXF1aXJlKFwiLi92dHJlZS9kaWZmLmpzXCIpO1xuXG4gICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IGRpZmY7XG4gICAgICAgIH0sIHsgXCIuL3Z0cmVlL2RpZmYuanNcIjogMzUgfV0sIDM6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICB2YXIgaCA9IHJlcXVpcmUoXCIuL3ZpcnR1YWwtaHlwZXJzY3JpcHQvaW5kZXguanNcIik7XG5cbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gaDtcbiAgICAgICAgfSwgeyBcIi4vdmlydHVhbC1oeXBlcnNjcmlwdC9pbmRleC5qc1wiOiAyMiB9XSwgNDogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHtcbiAgICAgICAgICAgIHZhciBkaWZmID0gcmVxdWlyZShcIi4vZGlmZi5qc1wiKTtcbiAgICAgICAgICAgIHZhciBwYXRjaCA9IHJlcXVpcmUoXCIuL3BhdGNoLmpzXCIpO1xuICAgICAgICAgICAgdmFyIGggPSByZXF1aXJlKFwiLi9oLmpzXCIpO1xuICAgICAgICAgICAgdmFyIGNyZWF0ZSA9IHJlcXVpcmUoXCIuL2NyZWF0ZS1lbGVtZW50LmpzXCIpO1xuICAgICAgICAgICAgdmFyIFZOb2RlID0gcmVxdWlyZShcIi4vdm5vZGUvdm5vZGUuanNcIik7XG4gICAgICAgICAgICB2YXIgVlRleHQgPSByZXF1aXJlKFwiLi92bm9kZS92dGV4dC5qc1wiKTtcblxuICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSB7XG4gICAgICAgICAgICAgICAgZGlmZjogZGlmZixcbiAgICAgICAgICAgICAgICBwYXRjaDogcGF0Y2gsXG4gICAgICAgICAgICAgICAgaDogaCxcbiAgICAgICAgICAgICAgICBjcmVhdGU6IGNyZWF0ZSxcbiAgICAgICAgICAgICAgICBWTm9kZTogVk5vZGUsXG4gICAgICAgICAgICAgICAgVlRleHQ6IFZUZXh0XG4gICAgICAgICAgICB9O1xuICAgICAgICB9LCB7IFwiLi9jcmVhdGUtZWxlbWVudC5qc1wiOiAxLCBcIi4vZGlmZi5qc1wiOiAyLCBcIi4vaC5qc1wiOiAzLCBcIi4vcGF0Y2guanNcIjogMTMsIFwiLi92bm9kZS92bm9kZS5qc1wiOiAzMSwgXCIuL3Zub2RlL3Z0ZXh0LmpzXCI6IDMzIH1dLCA1OiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge1xuICAgICAgICAgICAgLyohXG4gICAgICAgICAgICAgKiBDcm9zcy1Ccm93c2VyIFNwbGl0IDEuMS4xXG4gICAgICAgICAgICAgKiBDb3B5cmlnaHQgMjAwNy0yMDEyIFN0ZXZlbiBMZXZpdGhhbiA8c3RldmVubGV2aXRoYW4uY29tPlxuICAgICAgICAgICAgICogQXZhaWxhYmxlIHVuZGVyIHRoZSBNSVQgTGljZW5zZVxuICAgICAgICAgICAgICogRUNNQVNjcmlwdCBjb21wbGlhbnQsIHVuaWZvcm0gY3Jvc3MtYnJvd3NlciBzcGxpdCBtZXRob2RcbiAgICAgICAgICAgICAqL1xuXG4gICAgICAgICAgICAvKipcbiAgICAgICAgICAgICAqIFNwbGl0cyBhIHN0cmluZyBpbnRvIGFuIGFycmF5IG9mIHN0cmluZ3MgdXNpbmcgYSByZWdleCBvciBzdHJpbmcgc2VwYXJhdG9yLiBNYXRjaGVzIG9mIHRoZVxuICAgICAgICAgICAgICogc2VwYXJhdG9yIGFyZSBub3QgaW5jbHVkZWQgaW4gdGhlIHJlc3VsdCBhcnJheS4gSG93ZXZlciwgaWYgYHNlcGFyYXRvcmAgaXMgYSByZWdleCB0aGF0IGNvbnRhaW5zXG4gICAgICAgICAgICAgKiBjYXB0dXJpbmcgZ3JvdXBzLCBiYWNrcmVmZXJlbmNlcyBhcmUgc3BsaWNlZCBpbnRvIHRoZSByZXN1bHQgZWFjaCB0aW1lIGBzZXBhcmF0b3JgIGlzIG1hdGNoZWQuXG4gICAgICAgICAgICAgKiBGaXhlcyBicm93c2VyIGJ1Z3MgY29tcGFyZWQgdG8gdGhlIG5hdGl2ZSBgU3RyaW5nLnByb3RvdHlwZS5zcGxpdGAgYW5kIGNhbiBiZSB1c2VkIHJlbGlhYmx5XG4gICAgICAgICAgICAgKiBjcm9zcy1icm93c2VyLlxuICAgICAgICAgICAgICogQHBhcmFtIHtTdHJpbmd9IHN0ciBTdHJpbmcgdG8gc3BsaXQuXG4gICAgICAgICAgICAgKiBAcGFyYW0ge1JlZ0V4cHxTdHJpbmd9IHNlcGFyYXRvciBSZWdleCBvciBzdHJpbmcgdG8gdXNlIGZvciBzZXBhcmF0aW5nIHRoZSBzdHJpbmcuXG4gICAgICAgICAgICAgKiBAcGFyYW0ge051bWJlcn0gW2xpbWl0XSBNYXhpbXVtIG51bWJlciBvZiBpdGVtcyB0byBpbmNsdWRlIGluIHRoZSByZXN1bHQgYXJyYXkuXG4gICAgICAgICAgICAgKiBAcmV0dXJucyB7QXJyYXl9IEFycmF5IG9mIHN1YnN0cmluZ3MuXG4gICAgICAgICAgICAgKiBAZXhhbXBsZVxuICAgICAgICAgICAgICpcbiAgICAgICAgICAgICAqIC8vIEJhc2ljIHVzZVxuICAgICAgICAgICAgICogc3BsaXQoJ2EgYiBjIGQnLCAnICcpO1xuICAgICAgICAgICAgICogLy8gLT4gWydhJywgJ2InLCAnYycsICdkJ11cbiAgICAgICAgICAgICAqXG4gICAgICAgICAgICAgKiAvLyBXaXRoIGxpbWl0XG4gICAgICAgICAgICAgKiBzcGxpdCgnYSBiIGMgZCcsICcgJywgMik7XG4gICAgICAgICAgICAgKiAvLyAtPiBbJ2EnLCAnYiddXG4gICAgICAgICAgICAgKlxuICAgICAgICAgICAgICogLy8gQmFja3JlZmVyZW5jZXMgaW4gcmVzdWx0IGFycmF5XG4gICAgICAgICAgICAgKiBzcGxpdCgnLi53b3JkMSB3b3JkMi4uJywgLyhbYS16XSspKFxcZCspL2kpO1xuICAgICAgICAgICAgICogLy8gLT4gWycuLicsICd3b3JkJywgJzEnLCAnICcsICd3b3JkJywgJzInLCAnLi4nXVxuICAgICAgICAgICAgICovXG4gICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IChmdW5jdGlvbiBzcGxpdCh1bmRlZikge1xuXG4gICAgICAgICAgICAgICAgdmFyIG5hdGl2ZVNwbGl0ID0gU3RyaW5nLnByb3RvdHlwZS5zcGxpdCxcbiAgICAgICAgICAgICAgICAgICAgY29tcGxpYW50RXhlY05wY2cgPSAvKCk/Py8uZXhlYyhcIlwiKVsxXSA9PT0gdW5kZWYsXG5cbiAgICAgICAgICAgICAgICAvLyBOUENHOiBub25wYXJ0aWNpcGF0aW5nIGNhcHR1cmluZyBncm91cFxuICAgICAgICAgICAgICAgIHNlbGY7XG5cbiAgICAgICAgICAgICAgICBzZWxmID0gZnVuY3Rpb24gKHN0ciwgc2VwYXJhdG9yLCBsaW1pdCkge1xuICAgICAgICAgICAgICAgICAgICAvLyBJZiBgc2VwYXJhdG9yYCBpcyBub3QgYSByZWdleCwgdXNlIGBuYXRpdmVTcGxpdGBcbiAgICAgICAgICAgICAgICAgICAgaWYgKE9iamVjdC5wcm90b3R5cGUudG9TdHJpbmcuY2FsbChzZXBhcmF0b3IpICE9PSBcIltvYmplY3QgUmVnRXhwXVwiKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gbmF0aXZlU3BsaXQuY2FsbChzdHIsIHNlcGFyYXRvciwgbGltaXQpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIHZhciBvdXRwdXQgPSBbXSxcbiAgICAgICAgICAgICAgICAgICAgICAgIGZsYWdzID0gKHNlcGFyYXRvci5pZ25vcmVDYXNlID8gXCJpXCIgOiBcIlwiKSArIChzZXBhcmF0b3IubXVsdGlsaW5lID8gXCJtXCIgOiBcIlwiKSArIChzZXBhcmF0b3IuZXh0ZW5kZWQgPyBcInhcIiA6IFwiXCIpICsgKHNlcGFyYXRvci5zdGlja3kgPyBcInlcIiA6IFwiXCIpLFxuXG4gICAgICAgICAgICAgICAgICAgIC8vIEZpcmVmb3ggMytcbiAgICAgICAgICAgICAgICAgICAgbGFzdExhc3RJbmRleCA9IDAsXG5cbiAgICAgICAgICAgICAgICAgICAgLy8gTWFrZSBgZ2xvYmFsYCBhbmQgYXZvaWQgYGxhc3RJbmRleGAgaXNzdWVzIGJ5IHdvcmtpbmcgd2l0aCBhIGNvcHlcbiAgICAgICAgICAgICAgICAgICAgc2VwYXJhdG9yID0gbmV3IFJlZ0V4cChzZXBhcmF0b3Iuc291cmNlLCBmbGFncyArIFwiZ1wiKSxcbiAgICAgICAgICAgICAgICAgICAgICAgIHNlcGFyYXRvcjIsXG4gICAgICAgICAgICAgICAgICAgICAgICBtYXRjaCxcbiAgICAgICAgICAgICAgICAgICAgICAgIGxhc3RJbmRleCxcbiAgICAgICAgICAgICAgICAgICAgICAgIGxhc3RMZW5ndGg7XG4gICAgICAgICAgICAgICAgICAgIHN0ciArPSBcIlwiOyAvLyBUeXBlLWNvbnZlcnRcbiAgICAgICAgICAgICAgICAgICAgaWYgKCFjb21wbGlhbnRFeGVjTnBjZykge1xuICAgICAgICAgICAgICAgICAgICAgICAgLy8gRG9lc24ndCBuZWVkIGZsYWdzIGd5LCBidXQgdGhleSBkb24ndCBodXJ0XG4gICAgICAgICAgICAgICAgICAgICAgICBzZXBhcmF0b3IyID0gbmV3IFJlZ0V4cChcIl5cIiArIHNlcGFyYXRvci5zb3VyY2UgKyBcIiQoPyFcXFxccylcIiwgZmxhZ3MpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIC8qIFZhbHVlcyBmb3IgYGxpbWl0YCwgcGVyIHRoZSBzcGVjOlxuICAgICAgICAgICAgICAgICAgICAgKiBJZiB1bmRlZmluZWQ6IDQyOTQ5NjcyOTUgLy8gTWF0aC5wb3coMiwgMzIpIC0gMVxuICAgICAgICAgICAgICAgICAgICAgKiBJZiAwLCBJbmZpbml0eSwgb3IgTmFOOiAwXG4gICAgICAgICAgICAgICAgICAgICAqIElmIHBvc2l0aXZlIG51bWJlcjogbGltaXQgPSBNYXRoLmZsb29yKGxpbWl0KTsgaWYgKGxpbWl0ID4gNDI5NDk2NzI5NSkgbGltaXQgLT0gNDI5NDk2NzI5NjtcbiAgICAgICAgICAgICAgICAgICAgICogSWYgbmVnYXRpdmUgbnVtYmVyOiA0Mjk0OTY3Mjk2IC0gTWF0aC5mbG9vcihNYXRoLmFicyhsaW1pdCkpXG4gICAgICAgICAgICAgICAgICAgICAqIElmIG90aGVyOiBUeXBlLWNvbnZlcnQsIHRoZW4gdXNlIHRoZSBhYm92ZSBydWxlc1xuICAgICAgICAgICAgICAgICAgICAgKi9cbiAgICAgICAgICAgICAgICAgICAgbGltaXQgPSBsaW1pdCA9PT0gdW5kZWYgPyAtMSA+Pj4gMCA6IC8vIE1hdGgucG93KDIsIDMyKSAtIDFcbiAgICAgICAgICAgICAgICAgICAgbGltaXQgPj4+IDA7IC8vIFRvVWludDMyKGxpbWl0KVxuICAgICAgICAgICAgICAgICAgICB3aGlsZSAobWF0Y2ggPSBzZXBhcmF0b3IuZXhlYyhzdHIpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAvLyBgc2VwYXJhdG9yLmxhc3RJbmRleGAgaXMgbm90IHJlbGlhYmxlIGNyb3NzLWJyb3dzZXJcbiAgICAgICAgICAgICAgICAgICAgICAgIGxhc3RJbmRleCA9IG1hdGNoLmluZGV4ICsgbWF0Y2hbMF0ubGVuZ3RoO1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGxhc3RJbmRleCA+IGxhc3RMYXN0SW5kZXgpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBvdXRwdXQucHVzaChzdHIuc2xpY2UobGFzdExhc3RJbmRleCwgbWF0Y2guaW5kZXgpKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBGaXggYnJvd3NlcnMgd2hvc2UgYGV4ZWNgIG1ldGhvZHMgZG9uJ3QgY29uc2lzdGVudGx5IHJldHVybiBgdW5kZWZpbmVkYCBmb3JcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBub25wYXJ0aWNpcGF0aW5nIGNhcHR1cmluZyBncm91cHNcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoIWNvbXBsaWFudEV4ZWNOcGNnICYmIG1hdGNoLmxlbmd0aCA+IDEpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbWF0Y2hbMF0ucmVwbGFjZShzZXBhcmF0b3IyLCBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBmb3IgKHZhciBpID0gMTsgaSA8IGFyZ3VtZW50cy5sZW5ndGggLSAyOyBpKyspIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoYXJndW1lbnRzW2ldID09PSB1bmRlZikge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBtYXRjaFtpXSA9IHVuZGVmO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChtYXRjaC5sZW5ndGggPiAxICYmIG1hdGNoLmluZGV4IDwgc3RyLmxlbmd0aCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBBcnJheS5wcm90b3R5cGUucHVzaC5hcHBseShvdXRwdXQsIG1hdGNoLnNsaWNlKDEpKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgbGFzdExlbmd0aCA9IG1hdGNoWzBdLmxlbmd0aDtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBsYXN0TGFzdEluZGV4ID0gbGFzdEluZGV4O1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChvdXRwdXQubGVuZ3RoID49IGxpbWl0KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChzZXBhcmF0b3IubGFzdEluZGV4ID09PSBtYXRjaC5pbmRleCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNlcGFyYXRvci5sYXN0SW5kZXgrKzsgLy8gQXZvaWQgYW4gaW5maW5pdGUgbG9vcFxuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIGlmIChsYXN0TGFzdEluZGV4ID09PSBzdHIubGVuZ3RoKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAobGFzdExlbmd0aCB8fCAhc2VwYXJhdG9yLnRlc3QoXCJcIikpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBvdXRwdXQucHVzaChcIlwiKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIG91dHB1dC5wdXNoKHN0ci5zbGljZShsYXN0TGFzdEluZGV4KSk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIG91dHB1dC5sZW5ndGggPiBsaW1pdCA/IG91dHB1dC5zbGljZSgwLCBsaW1pdCkgOiBvdXRwdXQ7XG4gICAgICAgICAgICAgICAgfTtcblxuICAgICAgICAgICAgICAgIHJldHVybiBzZWxmO1xuICAgICAgICAgICAgfSkoKTtcbiAgICAgICAgfSwge31dLCA2OiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge30sIHt9XSwgNzogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHtcbiAgICAgICAgICAgIFwidXNlIHN0cmljdFwiO1xuXG4gICAgICAgICAgICB2YXIgT25lVmVyc2lvbkNvbnN0cmFpbnQgPSByZXF1aXJlKFwiaW5kaXZpZHVhbC9vbmUtdmVyc2lvblwiKTtcblxuICAgICAgICAgICAgdmFyIE1ZX1ZFUlNJT04gPSBcIjdcIjtcbiAgICAgICAgICAgIE9uZVZlcnNpb25Db25zdHJhaW50KFwiZXYtc3RvcmVcIiwgTVlfVkVSU0lPTik7XG5cbiAgICAgICAgICAgIHZhciBoYXNoS2V5ID0gXCJfX0VWX1NUT1JFX0tFWUBcIiArIE1ZX1ZFUlNJT047XG5cbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gRXZTdG9yZTtcblxuICAgICAgICAgICAgZnVuY3Rpb24gRXZTdG9yZShlbGVtKSB7XG4gICAgICAgICAgICAgICAgdmFyIGhhc2ggPSBlbGVtW2hhc2hLZXldO1xuXG4gICAgICAgICAgICAgICAgaWYgKCFoYXNoKSB7XG4gICAgICAgICAgICAgICAgICAgIGhhc2ggPSBlbGVtW2hhc2hLZXldID0ge307XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgcmV0dXJuIGhhc2g7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0sIHsgXCJpbmRpdmlkdWFsL29uZS12ZXJzaW9uXCI6IDkgfV0sIDg6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICAoZnVuY3Rpb24gKGdsb2JhbCkge1xuICAgICAgICAgICAgICAgIFwidXNlIHN0cmljdFwiO1xuXG4gICAgICAgICAgICAgICAgLypnbG9iYWwgd2luZG93LCBnbG9iYWwqL1xuXG4gICAgICAgICAgICAgICAgdmFyIHJvb3QgPSB0eXBlb2Ygd2luZG93ICE9PSBcInVuZGVmaW5lZFwiID8gd2luZG93IDogdHlwZW9mIGdsb2JhbCAhPT0gXCJ1bmRlZmluZWRcIiA/IGdsb2JhbCA6IHt9O1xuXG4gICAgICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBJbmRpdmlkdWFsO1xuXG4gICAgICAgICAgICAgICAgZnVuY3Rpb24gSW5kaXZpZHVhbChrZXksIHZhbHVlKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmIChrZXkgaW4gcm9vdCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHJvb3Rba2V5XTtcbiAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgIHJvb3Rba2V5XSA9IHZhbHVlO1xuXG4gICAgICAgICAgICAgICAgICAgIHJldHVybiB2YWx1ZTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9KS5jYWxsKHRoaXMsIHR5cGVvZiBnbG9iYWwgIT09IFwidW5kZWZpbmVkXCIgPyBnbG9iYWwgOiB0eXBlb2Ygc2VsZiAhPT0gXCJ1bmRlZmluZWRcIiA/IHNlbGYgOiB0eXBlb2Ygd2luZG93ICE9PSBcInVuZGVmaW5lZFwiID8gd2luZG93IDoge30pO1xuICAgICAgICB9LCB7fV0sIDk6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICBcInVzZSBzdHJpY3RcIjtcblxuICAgICAgICAgICAgdmFyIEluZGl2aWR1YWwgPSByZXF1aXJlKFwiLi9pbmRleC5qc1wiKTtcblxuICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBPbmVWZXJzaW9uO1xuXG4gICAgICAgICAgICBmdW5jdGlvbiBPbmVWZXJzaW9uKG1vZHVsZU5hbWUsIHZlcnNpb24sIGRlZmF1bHRWYWx1ZSkge1xuICAgICAgICAgICAgICAgIHZhciBrZXkgPSBcIl9fSU5ESVZJRFVBTF9PTkVfVkVSU0lPTl9cIiArIG1vZHVsZU5hbWU7XG4gICAgICAgICAgICAgICAgdmFyIGVuZm9yY2VLZXkgPSBrZXkgKyBcIl9FTkZPUkNFX1NJTkdMRVRPTlwiO1xuXG4gICAgICAgICAgICAgICAgdmFyIHZlcnNpb25WYWx1ZSA9IEluZGl2aWR1YWwoZW5mb3JjZUtleSwgdmVyc2lvbik7XG5cbiAgICAgICAgICAgICAgICBpZiAodmVyc2lvblZhbHVlICE9PSB2ZXJzaW9uKSB7XG4gICAgICAgICAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcihcIkNhbiBvbmx5IGhhdmUgb25lIGNvcHkgb2YgXCIgKyBtb2R1bGVOYW1lICsgXCIuXFxuXCIgKyBcIllvdSBhbHJlYWR5IGhhdmUgdmVyc2lvbiBcIiArIHZlcnNpb25WYWx1ZSArIFwiIGluc3RhbGxlZC5cXG5cIiArIFwiVGhpcyBtZWFucyB5b3UgY2Fubm90IGluc3RhbGwgdmVyc2lvbiBcIiArIHZlcnNpb24pO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHJldHVybiBJbmRpdmlkdWFsKGtleSwgZGVmYXVsdFZhbHVlKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSwgeyBcIi4vaW5kZXguanNcIjogOCB9XSwgMTA6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICAoZnVuY3Rpb24gKGdsb2JhbCkge1xuICAgICAgICAgICAgICAgIHZhciB0b3BMZXZlbCA9IHR5cGVvZiBnbG9iYWwgIT09IFwidW5kZWZpbmVkXCIgPyBnbG9iYWwgOiB0eXBlb2Ygd2luZG93ICE9PSBcInVuZGVmaW5lZFwiID8gd2luZG93IDoge307XG4gICAgICAgICAgICAgICAgdmFyIG1pbkRvYyA9IHJlcXVpcmUoXCJtaW4tZG9jdW1lbnRcIik7XG5cbiAgICAgICAgICAgICAgICBpZiAodHlwZW9mIGRvY3VtZW50ICE9PSBcInVuZGVmaW5lZFwiKSB7XG4gICAgICAgICAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gZG9jdW1lbnQ7XG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgdmFyIGRvY2N5ID0gdG9wTGV2ZWxbXCJfX0dMT0JBTF9ET0NVTUVOVF9DQUNIRUA0XCJdO1xuXG4gICAgICAgICAgICAgICAgICAgIGlmICghZG9jY3kpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGRvY2N5ID0gdG9wTGV2ZWxbXCJfX0dMT0JBTF9ET0NVTUVOVF9DQUNIRUA0XCJdID0gbWluRG9jO1xuICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBkb2NjeTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9KS5jYWxsKHRoaXMsIHR5cGVvZiBnbG9iYWwgIT09IFwidW5kZWZpbmVkXCIgPyBnbG9iYWwgOiB0eXBlb2Ygc2VsZiAhPT0gXCJ1bmRlZmluZWRcIiA/IHNlbGYgOiB0eXBlb2Ygd2luZG93ICE9PSBcInVuZGVmaW5lZFwiID8gd2luZG93IDoge30pO1xuICAgICAgICB9LCB7IFwibWluLWRvY3VtZW50XCI6IDYgfV0sIDExOiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge1xuICAgICAgICAgICAgXCJ1c2Ugc3RyaWN0XCI7XG5cbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gaXNPYmplY3QoeCkge1xuICAgICAgICAgICAgICAgIHJldHVybiB0eXBlb2YgeCA9PT0gXCJvYmplY3RcIiAmJiB4ICE9PSBudWxsO1xuICAgICAgICAgICAgfTtcbiAgICAgICAgfSwge31dLCAxMjogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHtcbiAgICAgICAgICAgIHZhciBuYXRpdmVJc0FycmF5ID0gQXJyYXkuaXNBcnJheTtcbiAgICAgICAgICAgIHZhciB0b1N0cmluZyA9IE9iamVjdC5wcm90b3R5cGUudG9TdHJpbmc7XG5cbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gbmF0aXZlSXNBcnJheSB8fCBpc0FycmF5O1xuXG4gICAgICAgICAgICBmdW5jdGlvbiBpc0FycmF5KG9iaikge1xuICAgICAgICAgICAgICAgIHJldHVybiB0b1N0cmluZy5jYWxsKG9iaikgPT09IFwiW29iamVjdCBBcnJheV1cIjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSwge31dLCAxMzogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHtcbiAgICAgICAgICAgIHZhciBwYXRjaCA9IHJlcXVpcmUoXCIuL3Zkb20vcGF0Y2guanNcIik7XG5cbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gcGF0Y2g7XG4gICAgICAgIH0sIHsgXCIuL3Zkb20vcGF0Y2guanNcIjogMTggfV0sIDE0OiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge1xuICAgICAgICAgICAgdmFyIGlzT2JqZWN0ID0gcmVxdWlyZShcImlzLW9iamVjdFwiKTtcbiAgICAgICAgICAgIHZhciBpc0hvb2sgPSByZXF1aXJlKFwiLi4vdm5vZGUvaXMtdmhvb2suanNcIik7XG5cbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gYXBwbHlQcm9wZXJ0aWVzO1xuXG4gICAgICAgICAgICBmdW5jdGlvbiBhcHBseVByb3BlcnRpZXMobm9kZSwgcHJvcHMsIHByZXZpb3VzKSB7XG4gICAgICAgICAgICAgICAgZm9yICh2YXIgcHJvcE5hbWUgaW4gcHJvcHMpIHtcbiAgICAgICAgICAgICAgICAgICAgdmFyIHByb3BWYWx1ZSA9IHByb3BzW3Byb3BOYW1lXTtcblxuICAgICAgICAgICAgICAgICAgICBpZiAocHJvcFZhbHVlID09PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJlbW92ZVByb3BlcnR5KG5vZGUsIHByb3BOYW1lLCBwcm9wVmFsdWUsIHByZXZpb3VzKTtcbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIGlmIChpc0hvb2socHJvcFZhbHVlKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgcmVtb3ZlUHJvcGVydHkobm9kZSwgcHJvcE5hbWUsIHByb3BWYWx1ZSwgcHJldmlvdXMpO1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHByb3BWYWx1ZS5ob29rKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcHJvcFZhbHVlLmhvb2sobm9kZSwgcHJvcE5hbWUsIHByZXZpb3VzID8gcHJldmlvdXNbcHJvcE5hbWVdIDogdW5kZWZpbmVkKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChpc09iamVjdChwcm9wVmFsdWUpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcGF0Y2hPYmplY3Qobm9kZSwgcHJvcHMsIHByZXZpb3VzLCBwcm9wTmFtZSwgcHJvcFZhbHVlKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgbm9kZVtwcm9wTmFtZV0gPSBwcm9wVmFsdWU7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIHJlbW92ZVByb3BlcnR5KG5vZGUsIHByb3BOYW1lLCBwcm9wVmFsdWUsIHByZXZpb3VzKSB7XG4gICAgICAgICAgICAgICAgaWYgKHByZXZpb3VzKSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciBwcmV2aW91c1ZhbHVlID0gcHJldmlvdXNbcHJvcE5hbWVdO1xuXG4gICAgICAgICAgICAgICAgICAgIGlmICghaXNIb29rKHByZXZpb3VzVmFsdWUpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAocHJvcE5hbWUgPT09IFwiYXR0cmlidXRlc1wiKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgZm9yICh2YXIgYXR0ck5hbWUgaW4gcHJldmlvdXNWYWx1ZSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBub2RlLnJlbW92ZUF0dHJpYnV0ZShhdHRyTmFtZSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIGlmIChwcm9wTmFtZSA9PT0gXCJzdHlsZVwiKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgZm9yICh2YXIgaSBpbiBwcmV2aW91c1ZhbHVlKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG5vZGUuc3R5bGVbaV0gPSBcIlwiO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAodHlwZW9mIHByZXZpb3VzVmFsdWUgPT09IFwic3RyaW5nXCIpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBub2RlW3Byb3BOYW1lXSA9IFwiXCI7XG4gICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIG5vZGVbcHJvcE5hbWVdID0gbnVsbDtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIGlmIChwcmV2aW91c1ZhbHVlLnVuaG9vaykge1xuICAgICAgICAgICAgICAgICAgICAgICAgcHJldmlvdXNWYWx1ZS51bmhvb2sobm9kZSwgcHJvcE5hbWUsIHByb3BWYWx1ZSk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIHBhdGNoT2JqZWN0KG5vZGUsIHByb3BzLCBwcmV2aW91cywgcHJvcE5hbWUsIHByb3BWYWx1ZSkge1xuICAgICAgICAgICAgICAgIHZhciBwcmV2aW91c1ZhbHVlID0gcHJldmlvdXMgPyBwcmV2aW91c1twcm9wTmFtZV0gOiB1bmRlZmluZWQ7XG5cbiAgICAgICAgICAgICAgICAvLyBTZXQgYXR0cmlidXRlc1xuICAgICAgICAgICAgICAgIGlmIChwcm9wTmFtZSA9PT0gXCJhdHRyaWJ1dGVzXCIpIHtcbiAgICAgICAgICAgICAgICAgICAgZm9yICh2YXIgYXR0ck5hbWUgaW4gcHJvcFZhbHVlKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICB2YXIgYXR0clZhbHVlID0gcHJvcFZhbHVlW2F0dHJOYW1lXTtcblxuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGF0dHJWYWx1ZSA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgbm9kZS5yZW1vdmVBdHRyaWJ1dGUoYXR0ck5hbWUpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBub2RlLnNldEF0dHJpYnV0ZShhdHRyTmFtZSwgYXR0clZhbHVlKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICBpZiAocHJldmlvdXNWYWx1ZSAmJiBpc09iamVjdChwcmV2aW91c1ZhbHVlKSAmJiBnZXRQcm90b3R5cGUocHJldmlvdXNWYWx1ZSkgIT09IGdldFByb3RvdHlwZShwcm9wVmFsdWUpKSB7XG4gICAgICAgICAgICAgICAgICAgIG5vZGVbcHJvcE5hbWVdID0gcHJvcFZhbHVlO1xuICAgICAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgaWYgKCFpc09iamVjdChub2RlW3Byb3BOYW1lXSkpIHtcbiAgICAgICAgICAgICAgICAgICAgbm9kZVtwcm9wTmFtZV0gPSB7fTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICB2YXIgcmVwbGFjZXIgPSBwcm9wTmFtZSA9PT0gXCJzdHlsZVwiID8gXCJcIiA6IHVuZGVmaW5lZDtcblxuICAgICAgICAgICAgICAgIGZvciAodmFyIGsgaW4gcHJvcFZhbHVlKSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciB2YWx1ZSA9IHByb3BWYWx1ZVtrXTtcbiAgICAgICAgICAgICAgICAgICAgbm9kZVtwcm9wTmFtZV1ba10gPSB2YWx1ZSA9PT0gdW5kZWZpbmVkID8gcmVwbGFjZXIgOiB2YWx1ZTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIGdldFByb3RvdHlwZSh2YWx1ZSkge1xuICAgICAgICAgICAgICAgIGlmIChPYmplY3QuZ2V0UHJvdG90eXBlT2YpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIE9iamVjdC5nZXRQcm90b3R5cGVPZih2YWx1ZSk7XG4gICAgICAgICAgICAgICAgfSBlbHNlIGlmICh2YWx1ZS5fX3Byb3RvX18pIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHZhbHVlLl9fcHJvdG9fXztcbiAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKHZhbHVlLmNvbnN0cnVjdG9yKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiB2YWx1ZS5jb25zdHJ1Y3Rvci5wcm90b3R5cGU7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9LCB7IFwiLi4vdm5vZGUvaXMtdmhvb2suanNcIjogMjYsIFwiaXMtb2JqZWN0XCI6IDExIH1dLCAxNTogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHtcbiAgICAgICAgICAgIHZhciBkb2N1bWVudCA9IHJlcXVpcmUoXCJnbG9iYWwvZG9jdW1lbnRcIik7XG5cbiAgICAgICAgICAgIHZhciBhcHBseVByb3BlcnRpZXMgPSByZXF1aXJlKFwiLi9hcHBseS1wcm9wZXJ0aWVzXCIpO1xuXG4gICAgICAgICAgICB2YXIgaXNWTm9kZSA9IHJlcXVpcmUoXCIuLi92bm9kZS9pcy12bm9kZS5qc1wiKTtcbiAgICAgICAgICAgIHZhciBpc1ZUZXh0ID0gcmVxdWlyZShcIi4uL3Zub2RlL2lzLXZ0ZXh0LmpzXCIpO1xuICAgICAgICAgICAgdmFyIGlzV2lkZ2V0ID0gcmVxdWlyZShcIi4uL3Zub2RlL2lzLXdpZGdldC5qc1wiKTtcbiAgICAgICAgICAgIHZhciBoYW5kbGVUaHVuayA9IHJlcXVpcmUoXCIuLi92bm9kZS9oYW5kbGUtdGh1bmsuanNcIik7XG5cbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gY3JlYXRlRWxlbWVudDtcblxuICAgICAgICAgICAgZnVuY3Rpb24gY3JlYXRlRWxlbWVudCh2bm9kZSwgb3B0cykge1xuICAgICAgICAgICAgICAgIHZhciBkb2MgPSBvcHRzID8gb3B0cy5kb2N1bWVudCB8fCBkb2N1bWVudCA6IGRvY3VtZW50O1xuICAgICAgICAgICAgICAgIHZhciB3YXJuID0gb3B0cyA/IG9wdHMud2FybiA6IG51bGw7XG5cbiAgICAgICAgICAgICAgICB2bm9kZSA9IGhhbmRsZVRodW5rKHZub2RlKS5hO1xuXG4gICAgICAgICAgICAgICAgaWYgKGlzV2lkZ2V0KHZub2RlKSkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gdm5vZGUuaW5pdCgpO1xuICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoaXNWVGV4dCh2bm9kZSkpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGRvYy5jcmVhdGVUZXh0Tm9kZSh2bm9kZS50ZXh0KTtcbiAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKCFpc1ZOb2RlKHZub2RlKSkge1xuICAgICAgICAgICAgICAgICAgICBpZiAod2Fybikge1xuICAgICAgICAgICAgICAgICAgICAgICAgd2FybihcIkl0ZW0gaXMgbm90IGEgdmFsaWQgdmlydHVhbCBkb20gbm9kZVwiLCB2bm9kZSk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIG51bGw7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgdmFyIG5vZGUgPSB2bm9kZS5uYW1lc3BhY2UgPT09IG51bGwgPyBkb2MuY3JlYXRlRWxlbWVudCh2bm9kZS50YWdOYW1lKSA6IGRvYy5jcmVhdGVFbGVtZW50TlModm5vZGUubmFtZXNwYWNlLCB2bm9kZS50YWdOYW1lKTtcblxuICAgICAgICAgICAgICAgIHZhciBwcm9wcyA9IHZub2RlLnByb3BlcnRpZXM7XG4gICAgICAgICAgICAgICAgYXBwbHlQcm9wZXJ0aWVzKG5vZGUsIHByb3BzKTtcblxuICAgICAgICAgICAgICAgIHZhciBjaGlsZHJlbiA9IHZub2RlLmNoaWxkcmVuO1xuXG4gICAgICAgICAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCBjaGlsZHJlbi5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgICAgICAgICB2YXIgY2hpbGROb2RlID0gY3JlYXRlRWxlbWVudChjaGlsZHJlbltpXSwgb3B0cyk7XG4gICAgICAgICAgICAgICAgICAgIGlmIChjaGlsZE5vZGUpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIG5vZGUuYXBwZW5kQ2hpbGQoY2hpbGROb2RlKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHJldHVybiBub2RlO1xuICAgICAgICAgICAgfVxuICAgICAgICB9LCB7IFwiLi4vdm5vZGUvaGFuZGxlLXRodW5rLmpzXCI6IDI0LCBcIi4uL3Zub2RlL2lzLXZub2RlLmpzXCI6IDI3LCBcIi4uL3Zub2RlL2lzLXZ0ZXh0LmpzXCI6IDI4LCBcIi4uL3Zub2RlL2lzLXdpZGdldC5qc1wiOiAyOSwgXCIuL2FwcGx5LXByb3BlcnRpZXNcIjogMTQsIFwiZ2xvYmFsL2RvY3VtZW50XCI6IDEwIH1dLCAxNjogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHtcbiAgICAgICAgICAgIC8vIE1hcHMgYSB2aXJ0dWFsIERPTSB0cmVlIG9udG8gYSByZWFsIERPTSB0cmVlIGluIGFuIGVmZmljaWVudCBtYW5uZXIuXG4gICAgICAgICAgICAvLyBXZSBkb24ndCB3YW50IHRvIHJlYWQgYWxsIG9mIHRoZSBET00gbm9kZXMgaW4gdGhlIHRyZWUgc28gd2UgdXNlXG4gICAgICAgICAgICAvLyB0aGUgaW4tb3JkZXIgdHJlZSBpbmRleGluZyB0byBlbGltaW5hdGUgcmVjdXJzaW9uIGRvd24gY2VydGFpbiBicmFuY2hlcy5cbiAgICAgICAgICAgIC8vIFdlIG9ubHkgcmVjdXJzZSBpbnRvIGEgRE9NIG5vZGUgaWYgd2Uga25vdyB0aGF0IGl0IGNvbnRhaW5zIGEgY2hpbGQgb2ZcbiAgICAgICAgICAgIC8vIGludGVyZXN0LlxuXG4gICAgICAgICAgICB2YXIgbm9DaGlsZCA9IHt9O1xuXG4gICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IGRvbUluZGV4O1xuXG4gICAgICAgICAgICBmdW5jdGlvbiBkb21JbmRleChyb290Tm9kZSwgdHJlZSwgaW5kaWNlcywgbm9kZXMpIHtcbiAgICAgICAgICAgICAgICBpZiAoIWluZGljZXMgfHwgaW5kaWNlcy5sZW5ndGggPT09IDApIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHt9O1xuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIGluZGljZXMuc29ydChhc2NlbmRpbmcpO1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gcmVjdXJzZShyb290Tm9kZSwgdHJlZSwgaW5kaWNlcywgbm9kZXMsIDApO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZnVuY3Rpb24gcmVjdXJzZShyb290Tm9kZSwgdHJlZSwgaW5kaWNlcywgbm9kZXMsIHJvb3RJbmRleCkge1xuICAgICAgICAgICAgICAgIG5vZGVzID0gbm9kZXMgfHwge307XG5cbiAgICAgICAgICAgICAgICBpZiAocm9vdE5vZGUpIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKGluZGV4SW5SYW5nZShpbmRpY2VzLCByb290SW5kZXgsIHJvb3RJbmRleCkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIG5vZGVzW3Jvb3RJbmRleF0gPSByb290Tm9kZTtcbiAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgIHZhciB2Q2hpbGRyZW4gPSB0cmVlLmNoaWxkcmVuO1xuXG4gICAgICAgICAgICAgICAgICAgIGlmICh2Q2hpbGRyZW4pIHtcblxuICAgICAgICAgICAgICAgICAgICAgICAgdmFyIGNoaWxkTm9kZXMgPSByb290Tm9kZS5jaGlsZE5vZGVzO1xuXG4gICAgICAgICAgICAgICAgICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IHRyZWUuY2hpbGRyZW4ubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICByb290SW5kZXggKz0gMTtcblxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZhciB2Q2hpbGQgPSB2Q2hpbGRyZW5baV0gfHwgbm9DaGlsZDtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB2YXIgbmV4dEluZGV4ID0gcm9vdEluZGV4ICsgKHZDaGlsZC5jb3VudCB8fCAwKTtcblxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIHNraXAgcmVjdXJzaW9uIGRvd24gdGhlIHRyZWUgaWYgdGhlcmUgYXJlIG5vIG5vZGVzIGRvd24gaGVyZVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChpbmRleEluUmFuZ2UoaW5kaWNlcywgcm9vdEluZGV4LCBuZXh0SW5kZXgpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlY3Vyc2UoY2hpbGROb2Rlc1tpXSwgdkNoaWxkLCBpbmRpY2VzLCBub2Rlcywgcm9vdEluZGV4KTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICByb290SW5kZXggPSBuZXh0SW5kZXg7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICByZXR1cm4gbm9kZXM7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIC8vIEJpbmFyeSBzZWFyY2ggZm9yIGFuIGluZGV4IGluIHRoZSBpbnRlcnZhbCBbbGVmdCwgcmlnaHRdXG4gICAgICAgICAgICBmdW5jdGlvbiBpbmRleEluUmFuZ2UoaW5kaWNlcywgbGVmdCwgcmlnaHQpIHtcbiAgICAgICAgICAgICAgICBpZiAoaW5kaWNlcy5sZW5ndGggPT09IDApIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHZhciBtaW5JbmRleCA9IDA7XG4gICAgICAgICAgICAgICAgdmFyIG1heEluZGV4ID0gaW5kaWNlcy5sZW5ndGggLSAxO1xuICAgICAgICAgICAgICAgIHZhciBjdXJyZW50SW5kZXg7XG4gICAgICAgICAgICAgICAgdmFyIGN1cnJlbnRJdGVtO1xuXG4gICAgICAgICAgICAgICAgd2hpbGUgKG1pbkluZGV4IDw9IG1heEluZGV4KSB7XG4gICAgICAgICAgICAgICAgICAgIGN1cnJlbnRJbmRleCA9IChtYXhJbmRleCArIG1pbkluZGV4KSAvIDIgPj4gMDtcbiAgICAgICAgICAgICAgICAgICAgY3VycmVudEl0ZW0gPSBpbmRpY2VzW2N1cnJlbnRJbmRleF07XG5cbiAgICAgICAgICAgICAgICAgICAgaWYgKG1pbkluZGV4ID09PSBtYXhJbmRleCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGN1cnJlbnRJdGVtID49IGxlZnQgJiYgY3VycmVudEl0ZW0gPD0gcmlnaHQ7XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoY3VycmVudEl0ZW0gPCBsZWZ0KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBtaW5JbmRleCA9IGN1cnJlbnRJbmRleCArIDE7XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoY3VycmVudEl0ZW0gPiByaWdodCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgbWF4SW5kZXggPSBjdXJyZW50SW5kZXggLSAxO1xuICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIGFzY2VuZGluZyhhLCBiKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGEgPiBiID8gMSA6IC0xO1xuICAgICAgICAgICAgfVxuICAgICAgICB9LCB7fV0sIDE3OiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge1xuICAgICAgICAgICAgdmFyIGFwcGx5UHJvcGVydGllcyA9IHJlcXVpcmUoXCIuL2FwcGx5LXByb3BlcnRpZXNcIik7XG5cbiAgICAgICAgICAgIHZhciBpc1dpZGdldCA9IHJlcXVpcmUoXCIuLi92bm9kZS9pcy13aWRnZXQuanNcIik7XG4gICAgICAgICAgICB2YXIgVlBhdGNoID0gcmVxdWlyZShcIi4uL3Zub2RlL3ZwYXRjaC5qc1wiKTtcblxuICAgICAgICAgICAgdmFyIHVwZGF0ZVdpZGdldCA9IHJlcXVpcmUoXCIuL3VwZGF0ZS13aWRnZXRcIik7XG5cbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gYXBwbHlQYXRjaDtcblxuICAgICAgICAgICAgZnVuY3Rpb24gYXBwbHlQYXRjaCh2cGF0Y2gsIGRvbU5vZGUsIHJlbmRlck9wdGlvbnMpIHtcbiAgICAgICAgICAgICAgICB2YXIgdHlwZSA9IHZwYXRjaC50eXBlO1xuICAgICAgICAgICAgICAgIHZhciB2Tm9kZSA9IHZwYXRjaC52Tm9kZTtcbiAgICAgICAgICAgICAgICB2YXIgcGF0Y2ggPSB2cGF0Y2gucGF0Y2g7XG5cbiAgICAgICAgICAgICAgICBzd2l0Y2ggKHR5cGUpIHtcbiAgICAgICAgICAgICAgICAgICAgY2FzZSBWUGF0Y2guUkVNT1ZFOlxuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHJlbW92ZU5vZGUoZG9tTm9kZSwgdk5vZGUpO1xuICAgICAgICAgICAgICAgICAgICBjYXNlIFZQYXRjaC5JTlNFUlQ6XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gaW5zZXJ0Tm9kZShkb21Ob2RlLCBwYXRjaCwgcmVuZGVyT3B0aW9ucyk7XG4gICAgICAgICAgICAgICAgICAgIGNhc2UgVlBhdGNoLlZURVhUOlxuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHN0cmluZ1BhdGNoKGRvbU5vZGUsIHZOb2RlLCBwYXRjaCwgcmVuZGVyT3B0aW9ucyk7XG4gICAgICAgICAgICAgICAgICAgIGNhc2UgVlBhdGNoLldJREdFVDpcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiB3aWRnZXRQYXRjaChkb21Ob2RlLCB2Tm9kZSwgcGF0Y2gsIHJlbmRlck9wdGlvbnMpO1xuICAgICAgICAgICAgICAgICAgICBjYXNlIFZQYXRjaC5WTk9ERTpcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiB2Tm9kZVBhdGNoKGRvbU5vZGUsIHZOb2RlLCBwYXRjaCwgcmVuZGVyT3B0aW9ucyk7XG4gICAgICAgICAgICAgICAgICAgIGNhc2UgVlBhdGNoLk9SREVSOlxuICAgICAgICAgICAgICAgICAgICAgICAgcmVvcmRlckNoaWxkcmVuKGRvbU5vZGUsIHBhdGNoKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBkb21Ob2RlO1xuICAgICAgICAgICAgICAgICAgICBjYXNlIFZQYXRjaC5QUk9QUzpcbiAgICAgICAgICAgICAgICAgICAgICAgIGFwcGx5UHJvcGVydGllcyhkb21Ob2RlLCBwYXRjaCwgdk5vZGUucHJvcGVydGllcyk7XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gZG9tTm9kZTtcbiAgICAgICAgICAgICAgICAgICAgY2FzZSBWUGF0Y2guVEhVTks6XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gcmVwbGFjZVJvb3QoZG9tTm9kZSwgcmVuZGVyT3B0aW9ucy5wYXRjaChkb21Ob2RlLCBwYXRjaCwgcmVuZGVyT3B0aW9ucykpO1xuICAgICAgICAgICAgICAgICAgICBkZWZhdWx0OlxuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGRvbU5vZGU7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBmdW5jdGlvbiByZW1vdmVOb2RlKGRvbU5vZGUsIHZOb2RlKSB7XG4gICAgICAgICAgICAgICAgdmFyIHBhcmVudE5vZGUgPSBkb21Ob2RlLnBhcmVudE5vZGU7XG5cbiAgICAgICAgICAgICAgICBpZiAocGFyZW50Tm9kZSkge1xuICAgICAgICAgICAgICAgICAgICBwYXJlbnROb2RlLnJlbW92ZUNoaWxkKGRvbU5vZGUpO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIGRlc3Ryb3lXaWRnZXQoZG9tTm9kZSwgdk5vZGUpO1xuXG4gICAgICAgICAgICAgICAgcmV0dXJuIG51bGw7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIGluc2VydE5vZGUocGFyZW50Tm9kZSwgdk5vZGUsIHJlbmRlck9wdGlvbnMpIHtcbiAgICAgICAgICAgICAgICB2YXIgbmV3Tm9kZSA9IHJlbmRlck9wdGlvbnMucmVuZGVyKHZOb2RlLCByZW5kZXJPcHRpb25zKTtcblxuICAgICAgICAgICAgICAgIGlmIChwYXJlbnROb2RlKSB7XG4gICAgICAgICAgICAgICAgICAgIHBhcmVudE5vZGUuYXBwZW5kQ2hpbGQobmV3Tm9kZSk7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgcmV0dXJuIHBhcmVudE5vZGU7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIHN0cmluZ1BhdGNoKGRvbU5vZGUsIGxlZnRWTm9kZSwgdlRleHQsIHJlbmRlck9wdGlvbnMpIHtcbiAgICAgICAgICAgICAgICB2YXIgbmV3Tm9kZTtcblxuICAgICAgICAgICAgICAgIGlmIChkb21Ob2RlLm5vZGVUeXBlID09PSAzKSB7XG4gICAgICAgICAgICAgICAgICAgIGRvbU5vZGUucmVwbGFjZURhdGEoMCwgZG9tTm9kZS5sZW5ndGgsIHZUZXh0LnRleHQpO1xuICAgICAgICAgICAgICAgICAgICBuZXdOb2RlID0gZG9tTm9kZTtcbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICB2YXIgcGFyZW50Tm9kZSA9IGRvbU5vZGUucGFyZW50Tm9kZTtcbiAgICAgICAgICAgICAgICAgICAgbmV3Tm9kZSA9IHJlbmRlck9wdGlvbnMucmVuZGVyKHZUZXh0LCByZW5kZXJPcHRpb25zKTtcblxuICAgICAgICAgICAgICAgICAgICBpZiAocGFyZW50Tm9kZSAmJiBuZXdOb2RlICE9PSBkb21Ob2RlKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBwYXJlbnROb2RlLnJlcGxhY2VDaGlsZChuZXdOb2RlLCBkb21Ob2RlKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHJldHVybiBuZXdOb2RlO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBmdW5jdGlvbiB3aWRnZXRQYXRjaChkb21Ob2RlLCBsZWZ0Vk5vZGUsIHdpZGdldCwgcmVuZGVyT3B0aW9ucykge1xuICAgICAgICAgICAgICAgIHZhciB1cGRhdGluZyA9IHVwZGF0ZVdpZGdldChsZWZ0Vk5vZGUsIHdpZGdldCk7XG4gICAgICAgICAgICAgICAgdmFyIG5ld05vZGU7XG5cbiAgICAgICAgICAgICAgICBpZiAodXBkYXRpbmcpIHtcbiAgICAgICAgICAgICAgICAgICAgbmV3Tm9kZSA9IHdpZGdldC51cGRhdGUobGVmdFZOb2RlLCBkb21Ob2RlKSB8fCBkb21Ob2RlO1xuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIG5ld05vZGUgPSByZW5kZXJPcHRpb25zLnJlbmRlcih3aWRnZXQsIHJlbmRlck9wdGlvbnMpO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHZhciBwYXJlbnROb2RlID0gZG9tTm9kZS5wYXJlbnROb2RlO1xuXG4gICAgICAgICAgICAgICAgaWYgKHBhcmVudE5vZGUgJiYgbmV3Tm9kZSAhPT0gZG9tTm9kZSkge1xuICAgICAgICAgICAgICAgICAgICBwYXJlbnROb2RlLnJlcGxhY2VDaGlsZChuZXdOb2RlLCBkb21Ob2RlKTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICBpZiAoIXVwZGF0aW5nKSB7XG4gICAgICAgICAgICAgICAgICAgIGRlc3Ryb3lXaWRnZXQoZG9tTm9kZSwgbGVmdFZOb2RlKTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICByZXR1cm4gbmV3Tm9kZTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZnVuY3Rpb24gdk5vZGVQYXRjaChkb21Ob2RlLCBsZWZ0Vk5vZGUsIHZOb2RlLCByZW5kZXJPcHRpb25zKSB7XG4gICAgICAgICAgICAgICAgdmFyIHBhcmVudE5vZGUgPSBkb21Ob2RlLnBhcmVudE5vZGU7XG4gICAgICAgICAgICAgICAgdmFyIG5ld05vZGUgPSByZW5kZXJPcHRpb25zLnJlbmRlcih2Tm9kZSwgcmVuZGVyT3B0aW9ucyk7XG5cbiAgICAgICAgICAgICAgICBpZiAocGFyZW50Tm9kZSAmJiBuZXdOb2RlICE9PSBkb21Ob2RlKSB7XG4gICAgICAgICAgICAgICAgICAgIHBhcmVudE5vZGUucmVwbGFjZUNoaWxkKG5ld05vZGUsIGRvbU5vZGUpO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHJldHVybiBuZXdOb2RlO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBmdW5jdGlvbiBkZXN0cm95V2lkZ2V0KGRvbU5vZGUsIHcpIHtcbiAgICAgICAgICAgICAgICBpZiAodHlwZW9mIHcuZGVzdHJveSA9PT0gXCJmdW5jdGlvblwiICYmIGlzV2lkZ2V0KHcpKSB7XG4gICAgICAgICAgICAgICAgICAgIHcuZGVzdHJveShkb21Ob2RlKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIHJlb3JkZXJDaGlsZHJlbihkb21Ob2RlLCBtb3Zlcykge1xuICAgICAgICAgICAgICAgIHZhciBjaGlsZE5vZGVzID0gZG9tTm9kZS5jaGlsZE5vZGVzO1xuICAgICAgICAgICAgICAgIHZhciBrZXlNYXAgPSB7fTtcbiAgICAgICAgICAgICAgICB2YXIgbm9kZTtcbiAgICAgICAgICAgICAgICB2YXIgcmVtb3ZlO1xuICAgICAgICAgICAgICAgIHZhciBpbnNlcnQ7XG5cbiAgICAgICAgICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IG1vdmVzLnJlbW92ZXMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgICAgICAgICAgcmVtb3ZlID0gbW92ZXMucmVtb3Zlc1tpXTtcbiAgICAgICAgICAgICAgICAgICAgbm9kZSA9IGNoaWxkTm9kZXNbcmVtb3ZlLmZyb21dO1xuICAgICAgICAgICAgICAgICAgICBpZiAocmVtb3ZlLmtleSkge1xuICAgICAgICAgICAgICAgICAgICAgICAga2V5TWFwW3JlbW92ZS5rZXldID0gbm9kZTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICBkb21Ob2RlLnJlbW92ZUNoaWxkKG5vZGUpO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHZhciBsZW5ndGggPSBjaGlsZE5vZGVzLmxlbmd0aDtcbiAgICAgICAgICAgICAgICBmb3IgKHZhciBqID0gMDsgaiA8IG1vdmVzLmluc2VydHMubGVuZ3RoOyBqKyspIHtcbiAgICAgICAgICAgICAgICAgICAgaW5zZXJ0ID0gbW92ZXMuaW5zZXJ0c1tqXTtcbiAgICAgICAgICAgICAgICAgICAgbm9kZSA9IGtleU1hcFtpbnNlcnQua2V5XTtcbiAgICAgICAgICAgICAgICAgICAgLy8gdGhpcyBpcyB0aGUgd2VpcmRlc3QgYnVnIGkndmUgZXZlciBzZWVuIGluIHdlYmtpdFxuICAgICAgICAgICAgICAgICAgICBkb21Ob2RlLmluc2VydEJlZm9yZShub2RlLCBpbnNlcnQudG8gPj0gbGVuZ3RoKysgPyBudWxsIDogY2hpbGROb2Rlc1tpbnNlcnQudG9dKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIHJlcGxhY2VSb290KG9sZFJvb3QsIG5ld1Jvb3QpIHtcbiAgICAgICAgICAgICAgICBpZiAob2xkUm9vdCAmJiBuZXdSb290ICYmIG9sZFJvb3QgIT09IG5ld1Jvb3QgJiYgb2xkUm9vdC5wYXJlbnROb2RlKSB7XG4gICAgICAgICAgICAgICAgICAgIG9sZFJvb3QucGFyZW50Tm9kZS5yZXBsYWNlQ2hpbGQobmV3Um9vdCwgb2xkUm9vdCk7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgcmV0dXJuIG5ld1Jvb3Q7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0sIHsgXCIuLi92bm9kZS9pcy13aWRnZXQuanNcIjogMjksIFwiLi4vdm5vZGUvdnBhdGNoLmpzXCI6IDMyLCBcIi4vYXBwbHktcHJvcGVydGllc1wiOiAxNCwgXCIuL3VwZGF0ZS13aWRnZXRcIjogMTkgfV0sIDE4OiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge1xuICAgICAgICAgICAgdmFyIGRvY3VtZW50ID0gcmVxdWlyZShcImdsb2JhbC9kb2N1bWVudFwiKTtcbiAgICAgICAgICAgIHZhciBpc0FycmF5ID0gcmVxdWlyZShcIngtaXMtYXJyYXlcIik7XG5cbiAgICAgICAgICAgIHZhciByZW5kZXIgPSByZXF1aXJlKFwiLi9jcmVhdGUtZWxlbWVudFwiKTtcbiAgICAgICAgICAgIHZhciBkb21JbmRleCA9IHJlcXVpcmUoXCIuL2RvbS1pbmRleFwiKTtcbiAgICAgICAgICAgIHZhciBwYXRjaE9wID0gcmVxdWlyZShcIi4vcGF0Y2gtb3BcIik7XG4gICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IHBhdGNoO1xuXG4gICAgICAgICAgICBmdW5jdGlvbiBwYXRjaChyb290Tm9kZSwgcGF0Y2hlcywgcmVuZGVyT3B0aW9ucykge1xuICAgICAgICAgICAgICAgIHJlbmRlck9wdGlvbnMgPSByZW5kZXJPcHRpb25zIHx8IHt9O1xuICAgICAgICAgICAgICAgIHJlbmRlck9wdGlvbnMucGF0Y2ggPSByZW5kZXJPcHRpb25zLnBhdGNoICYmIHJlbmRlck9wdGlvbnMucGF0Y2ggIT09IHBhdGNoID8gcmVuZGVyT3B0aW9ucy5wYXRjaCA6IHBhdGNoUmVjdXJzaXZlO1xuICAgICAgICAgICAgICAgIHJlbmRlck9wdGlvbnMucmVuZGVyID0gcmVuZGVyT3B0aW9ucy5yZW5kZXIgfHwgcmVuZGVyO1xuXG4gICAgICAgICAgICAgICAgcmV0dXJuIHJlbmRlck9wdGlvbnMucGF0Y2gocm9vdE5vZGUsIHBhdGNoZXMsIHJlbmRlck9wdGlvbnMpO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBmdW5jdGlvbiBwYXRjaFJlY3Vyc2l2ZShyb290Tm9kZSwgcGF0Y2hlcywgcmVuZGVyT3B0aW9ucykge1xuICAgICAgICAgICAgICAgIHZhciBpbmRpY2VzID0gcGF0Y2hJbmRpY2VzKHBhdGNoZXMpO1xuXG4gICAgICAgICAgICAgICAgaWYgKGluZGljZXMubGVuZ3RoID09PSAwKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiByb290Tm9kZTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICB2YXIgaW5kZXggPSBkb21JbmRleChyb290Tm9kZSwgcGF0Y2hlcy5hLCBpbmRpY2VzKTtcbiAgICAgICAgICAgICAgICB2YXIgb3duZXJEb2N1bWVudCA9IHJvb3ROb2RlLm93bmVyRG9jdW1lbnQ7XG5cbiAgICAgICAgICAgICAgICBpZiAoIXJlbmRlck9wdGlvbnMuZG9jdW1lbnQgJiYgb3duZXJEb2N1bWVudCAhPT0gZG9jdW1lbnQpIHtcbiAgICAgICAgICAgICAgICAgICAgcmVuZGVyT3B0aW9ucy5kb2N1bWVudCA9IG93bmVyRG9jdW1lbnQ7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCBpbmRpY2VzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciBub2RlSW5kZXggPSBpbmRpY2VzW2ldO1xuICAgICAgICAgICAgICAgICAgICByb290Tm9kZSA9IGFwcGx5UGF0Y2gocm9vdE5vZGUsIGluZGV4W25vZGVJbmRleF0sIHBhdGNoZXNbbm9kZUluZGV4XSwgcmVuZGVyT3B0aW9ucyk7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgcmV0dXJuIHJvb3ROb2RlO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBmdW5jdGlvbiBhcHBseVBhdGNoKHJvb3ROb2RlLCBkb21Ob2RlLCBwYXRjaExpc3QsIHJlbmRlck9wdGlvbnMpIHtcbiAgICAgICAgICAgICAgICBpZiAoIWRvbU5vZGUpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHJvb3ROb2RlO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHZhciBuZXdOb2RlO1xuXG4gICAgICAgICAgICAgICAgaWYgKGlzQXJyYXkocGF0Y2hMaXN0KSkge1xuICAgICAgICAgICAgICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IHBhdGNoTGlzdC5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgICAgICAgICAgICAgbmV3Tm9kZSA9IHBhdGNoT3AocGF0Y2hMaXN0W2ldLCBkb21Ob2RlLCByZW5kZXJPcHRpb25zKTtcblxuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGRvbU5vZGUgPT09IHJvb3ROb2RlKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcm9vdE5vZGUgPSBuZXdOb2RlO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgbmV3Tm9kZSA9IHBhdGNoT3AocGF0Y2hMaXN0LCBkb21Ob2RlLCByZW5kZXJPcHRpb25zKTtcblxuICAgICAgICAgICAgICAgICAgICBpZiAoZG9tTm9kZSA9PT0gcm9vdE5vZGUpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJvb3ROb2RlID0gbmV3Tm9kZTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHJldHVybiByb290Tm9kZTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZnVuY3Rpb24gcGF0Y2hJbmRpY2VzKHBhdGNoZXMpIHtcbiAgICAgICAgICAgICAgICB2YXIgaW5kaWNlcyA9IFtdO1xuXG4gICAgICAgICAgICAgICAgZm9yICh2YXIga2V5IGluIHBhdGNoZXMpIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKGtleSAhPT0gXCJhXCIpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGluZGljZXMucHVzaChOdW1iZXIoa2V5KSk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICByZXR1cm4gaW5kaWNlcztcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSwgeyBcIi4vY3JlYXRlLWVsZW1lbnRcIjogMTUsIFwiLi9kb20taW5kZXhcIjogMTYsIFwiLi9wYXRjaC1vcFwiOiAxNywgXCJnbG9iYWwvZG9jdW1lbnRcIjogMTAsIFwieC1pcy1hcnJheVwiOiAxMiB9XSwgMTk6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICB2YXIgaXNXaWRnZXQgPSByZXF1aXJlKFwiLi4vdm5vZGUvaXMtd2lkZ2V0LmpzXCIpO1xuXG4gICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IHVwZGF0ZVdpZGdldDtcblxuICAgICAgICAgICAgZnVuY3Rpb24gdXBkYXRlV2lkZ2V0KGEsIGIpIHtcbiAgICAgICAgICAgICAgICBpZiAoaXNXaWRnZXQoYSkgJiYgaXNXaWRnZXQoYikpIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKFwibmFtZVwiIGluIGEgJiYgXCJuYW1lXCIgaW4gYikge1xuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGEuaWQgPT09IGIuaWQ7XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gYS5pbml0ID09PSBiLmluaXQ7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0sIHsgXCIuLi92bm9kZS9pcy13aWRnZXQuanNcIjogMjkgfV0sIDIwOiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge1xuICAgICAgICAgICAgXCJ1c2Ugc3RyaWN0XCI7XG5cbiAgICAgICAgICAgIHZhciBFdlN0b3JlID0gcmVxdWlyZShcImV2LXN0b3JlXCIpO1xuXG4gICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IEV2SG9vaztcblxuICAgICAgICAgICAgZnVuY3Rpb24gRXZIb29rKHZhbHVlKSB7XG4gICAgICAgICAgICAgICAgaWYgKCEodGhpcyBpbnN0YW5jZW9mIEV2SG9vaykpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIG5ldyBFdkhvb2sodmFsdWUpO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHRoaXMudmFsdWUgPSB2YWx1ZTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgRXZIb29rLnByb3RvdHlwZS5ob29rID0gZnVuY3Rpb24gKG5vZGUsIHByb3BlcnR5TmFtZSkge1xuICAgICAgICAgICAgICAgIHZhciBlcyA9IEV2U3RvcmUobm9kZSk7XG4gICAgICAgICAgICAgICAgdmFyIHByb3BOYW1lID0gcHJvcGVydHlOYW1lLnN1YnN0cigzKTtcblxuICAgICAgICAgICAgICAgIGVzW3Byb3BOYW1lXSA9IHRoaXMudmFsdWU7XG4gICAgICAgICAgICB9O1xuXG4gICAgICAgICAgICBFdkhvb2sucHJvdG90eXBlLnVuaG9vayA9IGZ1bmN0aW9uIChub2RlLCBwcm9wZXJ0eU5hbWUpIHtcbiAgICAgICAgICAgICAgICB2YXIgZXMgPSBFdlN0b3JlKG5vZGUpO1xuICAgICAgICAgICAgICAgIHZhciBwcm9wTmFtZSA9IHByb3BlcnR5TmFtZS5zdWJzdHIoMyk7XG5cbiAgICAgICAgICAgICAgICBlc1twcm9wTmFtZV0gPSB1bmRlZmluZWQ7XG4gICAgICAgICAgICB9O1xuICAgICAgICB9LCB7IFwiZXYtc3RvcmVcIjogNyB9XSwgMjE6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICBcInVzZSBzdHJpY3RcIjtcblxuICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBTb2Z0U2V0SG9vaztcblxuICAgICAgICAgICAgZnVuY3Rpb24gU29mdFNldEhvb2sodmFsdWUpIHtcbiAgICAgICAgICAgICAgICBpZiAoISh0aGlzIGluc3RhbmNlb2YgU29mdFNldEhvb2spKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBuZXcgU29mdFNldEhvb2sodmFsdWUpO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHRoaXMudmFsdWUgPSB2YWx1ZTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgU29mdFNldEhvb2sucHJvdG90eXBlLmhvb2sgPSBmdW5jdGlvbiAobm9kZSwgcHJvcGVydHlOYW1lKSB7XG4gICAgICAgICAgICAgICAgaWYgKG5vZGVbcHJvcGVydHlOYW1lXSAhPT0gdGhpcy52YWx1ZSkge1xuICAgICAgICAgICAgICAgICAgICBub2RlW3Byb3BlcnR5TmFtZV0gPSB0aGlzLnZhbHVlO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH07XG4gICAgICAgIH0sIHt9XSwgMjI6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICBcInVzZSBzdHJpY3RcIjtcblxuICAgICAgICAgICAgdmFyIGlzQXJyYXkgPSByZXF1aXJlKFwieC1pcy1hcnJheVwiKTtcblxuICAgICAgICAgICAgdmFyIFZOb2RlID0gcmVxdWlyZShcIi4uL3Zub2RlL3Zub2RlLmpzXCIpO1xuICAgICAgICAgICAgdmFyIFZUZXh0ID0gcmVxdWlyZShcIi4uL3Zub2RlL3Z0ZXh0LmpzXCIpO1xuICAgICAgICAgICAgdmFyIGlzVk5vZGUgPSByZXF1aXJlKFwiLi4vdm5vZGUvaXMtdm5vZGVcIik7XG4gICAgICAgICAgICB2YXIgaXNWVGV4dCA9IHJlcXVpcmUoXCIuLi92bm9kZS9pcy12dGV4dFwiKTtcbiAgICAgICAgICAgIHZhciBpc1dpZGdldCA9IHJlcXVpcmUoXCIuLi92bm9kZS9pcy13aWRnZXRcIik7XG4gICAgICAgICAgICB2YXIgaXNIb29rID0gcmVxdWlyZShcIi4uL3Zub2RlL2lzLXZob29rXCIpO1xuICAgICAgICAgICAgdmFyIGlzVlRodW5rID0gcmVxdWlyZShcIi4uL3Zub2RlL2lzLXRodW5rXCIpO1xuXG4gICAgICAgICAgICB2YXIgcGFyc2VUYWcgPSByZXF1aXJlKFwiLi9wYXJzZS10YWcuanNcIik7XG4gICAgICAgICAgICB2YXIgc29mdFNldEhvb2sgPSByZXF1aXJlKFwiLi9ob29rcy9zb2Z0LXNldC1ob29rLmpzXCIpO1xuICAgICAgICAgICAgdmFyIGV2SG9vayA9IHJlcXVpcmUoXCIuL2hvb2tzL2V2LWhvb2suanNcIik7XG5cbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gaDtcblxuICAgICAgICAgICAgZnVuY3Rpb24gaCh0YWdOYW1lLCBwcm9wZXJ0aWVzLCBjaGlsZHJlbikge1xuICAgICAgICAgICAgICAgIHZhciBjaGlsZE5vZGVzID0gW107XG4gICAgICAgICAgICAgICAgdmFyIHRhZywgcHJvcHMsIGtleSwgbmFtZXNwYWNlO1xuXG4gICAgICAgICAgICAgICAgaWYgKCFjaGlsZHJlbiAmJiBpc0NoaWxkcmVuKHByb3BlcnRpZXMpKSB7XG4gICAgICAgICAgICAgICAgICAgIGNoaWxkcmVuID0gcHJvcGVydGllcztcbiAgICAgICAgICAgICAgICAgICAgcHJvcHMgPSB7fTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICBwcm9wcyA9IHByb3BzIHx8IHByb3BlcnRpZXMgfHwge307XG4gICAgICAgICAgICAgICAgdGFnID0gcGFyc2VUYWcodGFnTmFtZSwgcHJvcHMpO1xuXG4gICAgICAgICAgICAgICAgLy8gc3VwcG9ydCBrZXlzXG4gICAgICAgICAgICAgICAgaWYgKHByb3BzLmhhc093blByb3BlcnR5KFwia2V5XCIpKSB7XG4gICAgICAgICAgICAgICAgICAgIGtleSA9IHByb3BzLmtleTtcbiAgICAgICAgICAgICAgICAgICAgcHJvcHMua2V5ID0gdW5kZWZpbmVkO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIC8vIHN1cHBvcnQgbmFtZXNwYWNlXG4gICAgICAgICAgICAgICAgaWYgKHByb3BzLmhhc093blByb3BlcnR5KFwibmFtZXNwYWNlXCIpKSB7XG4gICAgICAgICAgICAgICAgICAgIG5hbWVzcGFjZSA9IHByb3BzLm5hbWVzcGFjZTtcbiAgICAgICAgICAgICAgICAgICAgcHJvcHMubmFtZXNwYWNlID0gdW5kZWZpbmVkO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIC8vIGZpeCBjdXJzb3IgYnVnXG4gICAgICAgICAgICAgICAgaWYgKHRhZyA9PT0gXCJJTlBVVFwiICYmICFuYW1lc3BhY2UgJiYgcHJvcHMuaGFzT3duUHJvcGVydHkoXCJ2YWx1ZVwiKSAmJiBwcm9wcy52YWx1ZSAhPT0gdW5kZWZpbmVkICYmICFpc0hvb2socHJvcHMudmFsdWUpKSB7XG4gICAgICAgICAgICAgICAgICAgIHByb3BzLnZhbHVlID0gc29mdFNldEhvb2socHJvcHMudmFsdWUpO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHRyYW5zZm9ybVByb3BlcnRpZXMocHJvcHMpO1xuXG4gICAgICAgICAgICAgICAgaWYgKGNoaWxkcmVuICE9PSB1bmRlZmluZWQgJiYgY2hpbGRyZW4gIT09IG51bGwpIHtcbiAgICAgICAgICAgICAgICAgICAgYWRkQ2hpbGQoY2hpbGRyZW4sIGNoaWxkTm9kZXMsIHRhZywgcHJvcHMpO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHJldHVybiBuZXcgVk5vZGUodGFnLCBwcm9wcywgY2hpbGROb2Rlcywga2V5LCBuYW1lc3BhY2UpO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBmdW5jdGlvbiBhZGRDaGlsZChjLCBjaGlsZE5vZGVzLCB0YWcsIHByb3BzKSB7XG4gICAgICAgICAgICAgICAgaWYgKHR5cGVvZiBjID09PSBcInN0cmluZ1wiKSB7XG4gICAgICAgICAgICAgICAgICAgIGNoaWxkTm9kZXMucHVzaChuZXcgVlRleHQoYykpO1xuICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAodHlwZW9mIGMgPT09IFwibnVtYmVyXCIpIHtcbiAgICAgICAgICAgICAgICAgICAgY2hpbGROb2Rlcy5wdXNoKG5ldyBWVGV4dChTdHJpbmcoYykpKTtcbiAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKGlzQ2hpbGQoYykpIHtcbiAgICAgICAgICAgICAgICAgICAgY2hpbGROb2Rlcy5wdXNoKGMpO1xuICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoaXNBcnJheShjKSkge1xuICAgICAgICAgICAgICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IGMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGFkZENoaWxkKGNbaV0sIGNoaWxkTm9kZXMsIHRhZywgcHJvcHMpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfSBlbHNlIGlmIChjID09PSBudWxsIHx8IGMgPT09IHVuZGVmaW5lZCkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgdGhyb3cgVW5leHBlY3RlZFZpcnR1YWxFbGVtZW50KHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGZvcmVpZ25PYmplY3Q6IGMsXG4gICAgICAgICAgICAgICAgICAgICAgICBwYXJlbnRWbm9kZToge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRhZ05hbWU6IHRhZyxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBwcm9wZXJ0aWVzOiBwcm9wc1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIHRyYW5zZm9ybVByb3BlcnRpZXMocHJvcHMpIHtcbiAgICAgICAgICAgICAgICBmb3IgKHZhciBwcm9wTmFtZSBpbiBwcm9wcykge1xuICAgICAgICAgICAgICAgICAgICBpZiAocHJvcHMuaGFzT3duUHJvcGVydHkocHJvcE5hbWUpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICB2YXIgdmFsdWUgPSBwcm9wc1twcm9wTmFtZV07XG5cbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChpc0hvb2sodmFsdWUpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgY29udGludWU7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChwcm9wTmFtZS5zdWJzdHIoMCwgMykgPT09IFwiZXYtXCIpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBhZGQgZXYtZm9vIHN1cHBvcnRcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBwcm9wc1twcm9wTmFtZV0gPSBldkhvb2sodmFsdWUpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBmdW5jdGlvbiBpc0NoaWxkKHgpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gaXNWTm9kZSh4KSB8fCBpc1ZUZXh0KHgpIHx8IGlzV2lkZ2V0KHgpIHx8IGlzVlRodW5rKHgpO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBmdW5jdGlvbiBpc0NoaWxkcmVuKHgpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gdHlwZW9mIHggPT09IFwic3RyaW5nXCIgfHwgaXNBcnJheSh4KSB8fCBpc0NoaWxkKHgpO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBmdW5jdGlvbiBVbmV4cGVjdGVkVmlydHVhbEVsZW1lbnQoZGF0YSkge1xuICAgICAgICAgICAgICAgIHZhciBlcnIgPSBuZXcgRXJyb3IoKTtcblxuICAgICAgICAgICAgICAgIGVyci50eXBlID0gXCJ2aXJ0dWFsLWh5cGVyc2NyaXB0LnVuZXhwZWN0ZWQudmlydHVhbC1lbGVtZW50XCI7XG4gICAgICAgICAgICAgICAgZXJyLm1lc3NhZ2UgPSBcIlVuZXhwZWN0ZWQgdmlydHVhbCBjaGlsZCBwYXNzZWQgdG8gaCgpLlxcblwiICsgXCJFeHBlY3RlZCBhIFZOb2RlIC8gVnRodW5rIC8gVldpZGdldCAvIHN0cmluZyBidXQ6XFxuXCIgKyBcImdvdDpcXG5cIiArIGVycm9yU3RyaW5nKGRhdGEuZm9yZWlnbk9iamVjdCkgKyBcIi5cXG5cIiArIFwiVGhlIHBhcmVudCB2bm9kZSBpczpcXG5cIiArIGVycm9yU3RyaW5nKGRhdGEucGFyZW50Vm5vZGUpO1xuICAgICAgICAgICAgICAgIFwiXFxuXCIgKyBcIlN1Z2dlc3RlZCBmaXg6IGNoYW5nZSB5b3VyIGBoKC4uLiwgWyAuLi4gXSlgIGNhbGxzaXRlLlwiO1xuICAgICAgICAgICAgICAgIGVyci5mb3JlaWduT2JqZWN0ID0gZGF0YS5mb3JlaWduT2JqZWN0O1xuICAgICAgICAgICAgICAgIGVyci5wYXJlbnRWbm9kZSA9IGRhdGEucGFyZW50Vm5vZGU7XG5cbiAgICAgICAgICAgICAgICByZXR1cm4gZXJyO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBmdW5jdGlvbiBlcnJvclN0cmluZyhvYmopIHtcbiAgICAgICAgICAgICAgICB0cnkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gSlNPTi5zdHJpbmdpZnkob2JqLCBudWxsLCBcIiAgICBcIik7XG4gICAgICAgICAgICAgICAgfSBjYXRjaCAoZSkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gU3RyaW5nKG9iaik7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9LCB7IFwiLi4vdm5vZGUvaXMtdGh1bmtcIjogMjUsIFwiLi4vdm5vZGUvaXMtdmhvb2tcIjogMjYsIFwiLi4vdm5vZGUvaXMtdm5vZGVcIjogMjcsIFwiLi4vdm5vZGUvaXMtdnRleHRcIjogMjgsIFwiLi4vdm5vZGUvaXMtd2lkZ2V0XCI6IDI5LCBcIi4uL3Zub2RlL3Zub2RlLmpzXCI6IDMxLCBcIi4uL3Zub2RlL3Z0ZXh0LmpzXCI6IDMzLCBcIi4vaG9va3MvZXYtaG9vay5qc1wiOiAyMCwgXCIuL2hvb2tzL3NvZnQtc2V0LWhvb2suanNcIjogMjEsIFwiLi9wYXJzZS10YWcuanNcIjogMjMsIFwieC1pcy1hcnJheVwiOiAxMiB9XSwgMjM6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICBcInVzZSBzdHJpY3RcIjtcblxuICAgICAgICAgICAgdmFyIHNwbGl0ID0gcmVxdWlyZShcImJyb3dzZXItc3BsaXRcIik7XG5cbiAgICAgICAgICAgIHZhciBjbGFzc0lkU3BsaXQgPSAvKFtcXC4jXT9bYS16QS1aMC05XFx1MDA3Ri1cXHVGRkZGXzotXSspLztcbiAgICAgICAgICAgIHZhciBub3RDbGFzc0lkID0gL15cXC58Iy87XG5cbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gcGFyc2VUYWc7XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIHBhcnNlVGFnKHRhZywgcHJvcHMpIHtcbiAgICAgICAgICAgICAgICBpZiAoIXRhZykge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gXCJESVZcIjtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICB2YXIgbm9JZCA9ICFwcm9wcy5oYXNPd25Qcm9wZXJ0eShcImlkXCIpO1xuXG4gICAgICAgICAgICAgICAgdmFyIHRhZ1BhcnRzID0gc3BsaXQodGFnLCBjbGFzc0lkU3BsaXQpO1xuICAgICAgICAgICAgICAgIHZhciB0YWdOYW1lID0gbnVsbDtcblxuICAgICAgICAgICAgICAgIGlmIChub3RDbGFzc0lkLnRlc3QodGFnUGFydHNbMV0pKSB7XG4gICAgICAgICAgICAgICAgICAgIHRhZ05hbWUgPSBcIkRJVlwiO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHZhciBjbGFzc2VzLCBwYXJ0LCB0eXBlLCBpO1xuXG4gICAgICAgICAgICAgICAgZm9yIChpID0gMDsgaSA8IHRhZ1BhcnRzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICAgICAgICAgIHBhcnQgPSB0YWdQYXJ0c1tpXTtcblxuICAgICAgICAgICAgICAgICAgICBpZiAoIXBhcnQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnRpbnVlO1xuICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgdHlwZSA9IHBhcnQuY2hhckF0KDApO1xuXG4gICAgICAgICAgICAgICAgICAgIGlmICghdGFnTmFtZSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgdGFnTmFtZSA9IHBhcnQ7XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAodHlwZSA9PT0gXCIuXCIpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGNsYXNzZXMgPSBjbGFzc2VzIHx8IFtdO1xuICAgICAgICAgICAgICAgICAgICAgICAgY2xhc3Nlcy5wdXNoKHBhcnQuc3Vic3RyaW5nKDEsIHBhcnQubGVuZ3RoKSk7XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAodHlwZSA9PT0gXCIjXCIgJiYgbm9JZCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgcHJvcHMuaWQgPSBwYXJ0LnN1YnN0cmluZygxLCBwYXJ0Lmxlbmd0aCk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICBpZiAoY2xhc3Nlcykge1xuICAgICAgICAgICAgICAgICAgICBpZiAocHJvcHMuY2xhc3NOYW1lKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBjbGFzc2VzLnB1c2gocHJvcHMuY2xhc3NOYW1lKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgIHByb3BzLmNsYXNzTmFtZSA9IGNsYXNzZXMuam9pbihcIiBcIik7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgcmV0dXJuIHByb3BzLm5hbWVzcGFjZSA/IHRhZ05hbWUgOiB0YWdOYW1lLnRvVXBwZXJDYXNlKCk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0sIHsgXCJicm93c2VyLXNwbGl0XCI6IDUgfV0sIDI0OiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge1xuICAgICAgICAgICAgdmFyIGlzVk5vZGUgPSByZXF1aXJlKFwiLi9pcy12bm9kZVwiKTtcbiAgICAgICAgICAgIHZhciBpc1ZUZXh0ID0gcmVxdWlyZShcIi4vaXMtdnRleHRcIik7XG4gICAgICAgICAgICB2YXIgaXNXaWRnZXQgPSByZXF1aXJlKFwiLi9pcy13aWRnZXRcIik7XG4gICAgICAgICAgICB2YXIgaXNUaHVuayA9IHJlcXVpcmUoXCIuL2lzLXRodW5rXCIpO1xuXG4gICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IGhhbmRsZVRodW5rO1xuXG4gICAgICAgICAgICBmdW5jdGlvbiBoYW5kbGVUaHVuayhhLCBiKSB7XG4gICAgICAgICAgICAgICAgdmFyIHJlbmRlcmVkQSA9IGE7XG4gICAgICAgICAgICAgICAgdmFyIHJlbmRlcmVkQiA9IGI7XG5cbiAgICAgICAgICAgICAgICBpZiAoaXNUaHVuayhiKSkge1xuICAgICAgICAgICAgICAgICAgICByZW5kZXJlZEIgPSByZW5kZXJUaHVuayhiLCBhKTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICBpZiAoaXNUaHVuayhhKSkge1xuICAgICAgICAgICAgICAgICAgICByZW5kZXJlZEEgPSByZW5kZXJUaHVuayhhLCBudWxsKTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgICAgICAgICBhOiByZW5kZXJlZEEsXG4gICAgICAgICAgICAgICAgICAgIGI6IHJlbmRlcmVkQlxuICAgICAgICAgICAgICAgIH07XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIHJlbmRlclRodW5rKHRodW5rLCBwcmV2aW91cykge1xuICAgICAgICAgICAgICAgIHZhciByZW5kZXJlZFRodW5rID0gdGh1bmsudm5vZGU7XG5cbiAgICAgICAgICAgICAgICBpZiAoIXJlbmRlcmVkVGh1bmspIHtcbiAgICAgICAgICAgICAgICAgICAgcmVuZGVyZWRUaHVuayA9IHRodW5rLnZub2RlID0gdGh1bmsucmVuZGVyKHByZXZpb3VzKTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICBpZiAoIShpc1ZOb2RlKHJlbmRlcmVkVGh1bmspIHx8IGlzVlRleHQocmVuZGVyZWRUaHVuaykgfHwgaXNXaWRnZXQocmVuZGVyZWRUaHVuaykpKSB7XG4gICAgICAgICAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcihcInRodW5rIGRpZCBub3QgcmV0dXJuIGEgdmFsaWQgbm9kZVwiKTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICByZXR1cm4gcmVuZGVyZWRUaHVuaztcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSwgeyBcIi4vaXMtdGh1bmtcIjogMjUsIFwiLi9pcy12bm9kZVwiOiAyNywgXCIuL2lzLXZ0ZXh0XCI6IDI4LCBcIi4vaXMtd2lkZ2V0XCI6IDI5IH1dLCAyNTogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHtcbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gaXNUaHVuaztcblxuICAgICAgICAgICAgZnVuY3Rpb24gaXNUaHVuayh0KSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHQgJiYgdC50eXBlID09PSBcIlRodW5rXCI7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0sIHt9XSwgMjY6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IGlzSG9vaztcblxuICAgICAgICAgICAgZnVuY3Rpb24gaXNIb29rKGhvb2spIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gaG9vayAmJiAodHlwZW9mIGhvb2suaG9vayA9PT0gXCJmdW5jdGlvblwiICYmICFob29rLmhhc093blByb3BlcnR5KFwiaG9va1wiKSB8fCB0eXBlb2YgaG9vay51bmhvb2sgPT09IFwiZnVuY3Rpb25cIiAmJiAhaG9vay5oYXNPd25Qcm9wZXJ0eShcInVuaG9va1wiKSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0sIHt9XSwgMjc6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICB2YXIgdmVyc2lvbiA9IHJlcXVpcmUoXCIuL3ZlcnNpb25cIik7XG5cbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gaXNWaXJ0dWFsTm9kZTtcblxuICAgICAgICAgICAgZnVuY3Rpb24gaXNWaXJ0dWFsTm9kZSh4KSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHggJiYgeC50eXBlID09PSBcIlZpcnR1YWxOb2RlXCIgJiYgeC52ZXJzaW9uID09PSB2ZXJzaW9uO1xuICAgICAgICAgICAgfVxuICAgICAgICB9LCB7IFwiLi92ZXJzaW9uXCI6IDMwIH1dLCAyODogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHtcbiAgICAgICAgICAgIHZhciB2ZXJzaW9uID0gcmVxdWlyZShcIi4vdmVyc2lvblwiKTtcblxuICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBpc1ZpcnR1YWxUZXh0O1xuXG4gICAgICAgICAgICBmdW5jdGlvbiBpc1ZpcnR1YWxUZXh0KHgpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4geCAmJiB4LnR5cGUgPT09IFwiVmlydHVhbFRleHRcIiAmJiB4LnZlcnNpb24gPT09IHZlcnNpb247XG4gICAgICAgICAgICB9XG4gICAgICAgIH0sIHsgXCIuL3ZlcnNpb25cIjogMzAgfV0sIDI5OiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge1xuICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBpc1dpZGdldDtcblxuICAgICAgICAgICAgZnVuY3Rpb24gaXNXaWRnZXQodykge1xuICAgICAgICAgICAgICAgIHJldHVybiB3ICYmIHcudHlwZSA9PT0gXCJXaWRnZXRcIjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSwge31dLCAzMDogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHtcbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gXCIyXCI7XG4gICAgICAgIH0sIHt9XSwgMzE6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICB2YXIgdmVyc2lvbiA9IHJlcXVpcmUoXCIuL3ZlcnNpb25cIik7XG4gICAgICAgICAgICB2YXIgaXNWTm9kZSA9IHJlcXVpcmUoXCIuL2lzLXZub2RlXCIpO1xuICAgICAgICAgICAgdmFyIGlzV2lkZ2V0ID0gcmVxdWlyZShcIi4vaXMtd2lkZ2V0XCIpO1xuICAgICAgICAgICAgdmFyIGlzVGh1bmsgPSByZXF1aXJlKFwiLi9pcy10aHVua1wiKTtcbiAgICAgICAgICAgIHZhciBpc1ZIb29rID0gcmVxdWlyZShcIi4vaXMtdmhvb2tcIik7XG5cbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gVmlydHVhbE5vZGU7XG5cbiAgICAgICAgICAgIHZhciBub1Byb3BlcnRpZXMgPSB7fTtcbiAgICAgICAgICAgIHZhciBub0NoaWxkcmVuID0gW107XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIFZpcnR1YWxOb2RlKHRhZ05hbWUsIHByb3BlcnRpZXMsIGNoaWxkcmVuLCBrZXksIG5hbWVzcGFjZSkge1xuICAgICAgICAgICAgICAgIHRoaXMudGFnTmFtZSA9IHRhZ05hbWU7XG4gICAgICAgICAgICAgICAgdGhpcy5wcm9wZXJ0aWVzID0gcHJvcGVydGllcyB8fCBub1Byb3BlcnRpZXM7XG4gICAgICAgICAgICAgICAgdGhpcy5jaGlsZHJlbiA9IGNoaWxkcmVuIHx8IG5vQ2hpbGRyZW47XG4gICAgICAgICAgICAgICAgdGhpcy5rZXkgPSBrZXkgIT0gbnVsbCA/IFN0cmluZyhrZXkpIDogdW5kZWZpbmVkO1xuICAgICAgICAgICAgICAgIHRoaXMubmFtZXNwYWNlID0gdHlwZW9mIG5hbWVzcGFjZSA9PT0gXCJzdHJpbmdcIiA/IG5hbWVzcGFjZSA6IG51bGw7XG5cbiAgICAgICAgICAgICAgICB2YXIgY291bnQgPSBjaGlsZHJlbiAmJiBjaGlsZHJlbi5sZW5ndGggfHwgMDtcbiAgICAgICAgICAgICAgICB2YXIgZGVzY2VuZGFudHMgPSAwO1xuICAgICAgICAgICAgICAgIHZhciBoYXNXaWRnZXRzID0gZmFsc2U7XG4gICAgICAgICAgICAgICAgdmFyIGhhc1RodW5rcyA9IGZhbHNlO1xuICAgICAgICAgICAgICAgIHZhciBkZXNjZW5kYW50SG9va3MgPSBmYWxzZTtcbiAgICAgICAgICAgICAgICB2YXIgaG9va3M7XG5cbiAgICAgICAgICAgICAgICBmb3IgKHZhciBwcm9wTmFtZSBpbiBwcm9wZXJ0aWVzKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmIChwcm9wZXJ0aWVzLmhhc093blByb3BlcnR5KHByb3BOYW1lKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgdmFyIHByb3BlcnR5ID0gcHJvcGVydGllc1twcm9wTmFtZV07XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoaXNWSG9vayhwcm9wZXJ0eSkgJiYgcHJvcGVydHkudW5ob29rKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKCFob29rcykge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBob29rcyA9IHt9O1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGhvb2tzW3Byb3BOYW1lXSA9IHByb3BlcnR5O1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCBjb3VudDsgaSsrKSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciBjaGlsZCA9IGNoaWxkcmVuW2ldO1xuICAgICAgICAgICAgICAgICAgICBpZiAoaXNWTm9kZShjaGlsZCkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGRlc2NlbmRhbnRzICs9IGNoaWxkLmNvdW50IHx8IDA7XG5cbiAgICAgICAgICAgICAgICAgICAgICAgIGlmICghaGFzV2lkZ2V0cyAmJiBjaGlsZC5oYXNXaWRnZXRzKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaGFzV2lkZ2V0cyA9IHRydWU7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgICAgIGlmICghaGFzVGh1bmtzICYmIGNoaWxkLmhhc1RodW5rcykge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGhhc1RodW5rcyA9IHRydWU7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgICAgIGlmICghZGVzY2VuZGFudEhvb2tzICYmIChjaGlsZC5ob29rcyB8fCBjaGlsZC5kZXNjZW5kYW50SG9va3MpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgZGVzY2VuZGFudEhvb2tzID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIGlmICghaGFzV2lkZ2V0cyAmJiBpc1dpZGdldChjaGlsZCkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmICh0eXBlb2YgY2hpbGQuZGVzdHJveSA9PT0gXCJmdW5jdGlvblwiKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaGFzV2lkZ2V0cyA9IHRydWU7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoIWhhc1RodW5rcyAmJiBpc1RodW5rKGNoaWxkKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgaGFzVGh1bmtzID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHRoaXMuY291bnQgPSBjb3VudCArIGRlc2NlbmRhbnRzO1xuICAgICAgICAgICAgICAgIHRoaXMuaGFzV2lkZ2V0cyA9IGhhc1dpZGdldHM7XG4gICAgICAgICAgICAgICAgdGhpcy5oYXNUaHVua3MgPSBoYXNUaHVua3M7XG4gICAgICAgICAgICAgICAgdGhpcy5ob29rcyA9IGhvb2tzO1xuICAgICAgICAgICAgICAgIHRoaXMuZGVzY2VuZGFudEhvb2tzID0gZGVzY2VuZGFudEhvb2tzO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBWaXJ0dWFsTm9kZS5wcm90b3R5cGUudmVyc2lvbiA9IHZlcnNpb247XG4gICAgICAgICAgICBWaXJ0dWFsTm9kZS5wcm90b3R5cGUudHlwZSA9IFwiVmlydHVhbE5vZGVcIjtcbiAgICAgICAgfSwgeyBcIi4vaXMtdGh1bmtcIjogMjUsIFwiLi9pcy12aG9va1wiOiAyNiwgXCIuL2lzLXZub2RlXCI6IDI3LCBcIi4vaXMtd2lkZ2V0XCI6IDI5LCBcIi4vdmVyc2lvblwiOiAzMCB9XSwgMzI6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICB2YXIgdmVyc2lvbiA9IHJlcXVpcmUoXCIuL3ZlcnNpb25cIik7XG5cbiAgICAgICAgICAgIFZpcnR1YWxQYXRjaC5OT05FID0gMDtcbiAgICAgICAgICAgIFZpcnR1YWxQYXRjaC5WVEVYVCA9IDE7XG4gICAgICAgICAgICBWaXJ0dWFsUGF0Y2guVk5PREUgPSAyO1xuICAgICAgICAgICAgVmlydHVhbFBhdGNoLldJREdFVCA9IDM7XG4gICAgICAgICAgICBWaXJ0dWFsUGF0Y2guUFJPUFMgPSA0O1xuICAgICAgICAgICAgVmlydHVhbFBhdGNoLk9SREVSID0gNTtcbiAgICAgICAgICAgIFZpcnR1YWxQYXRjaC5JTlNFUlQgPSA2O1xuICAgICAgICAgICAgVmlydHVhbFBhdGNoLlJFTU9WRSA9IDc7XG4gICAgICAgICAgICBWaXJ0dWFsUGF0Y2guVEhVTksgPSA4O1xuXG4gICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IFZpcnR1YWxQYXRjaDtcblxuICAgICAgICAgICAgZnVuY3Rpb24gVmlydHVhbFBhdGNoKHR5cGUsIHZOb2RlLCBwYXRjaCkge1xuICAgICAgICAgICAgICAgIHRoaXMudHlwZSA9IE51bWJlcih0eXBlKTtcbiAgICAgICAgICAgICAgICB0aGlzLnZOb2RlID0gdk5vZGU7XG4gICAgICAgICAgICAgICAgdGhpcy5wYXRjaCA9IHBhdGNoO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBWaXJ0dWFsUGF0Y2gucHJvdG90eXBlLnZlcnNpb24gPSB2ZXJzaW9uO1xuICAgICAgICAgICAgVmlydHVhbFBhdGNoLnByb3RvdHlwZS50eXBlID0gXCJWaXJ0dWFsUGF0Y2hcIjtcbiAgICAgICAgfSwgeyBcIi4vdmVyc2lvblwiOiAzMCB9XSwgMzM6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICB2YXIgdmVyc2lvbiA9IHJlcXVpcmUoXCIuL3ZlcnNpb25cIik7XG5cbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gVmlydHVhbFRleHQ7XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIFZpcnR1YWxUZXh0KHRleHQpIHtcbiAgICAgICAgICAgICAgICB0aGlzLnRleHQgPSBTdHJpbmcodGV4dCk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIFZpcnR1YWxUZXh0LnByb3RvdHlwZS52ZXJzaW9uID0gdmVyc2lvbjtcbiAgICAgICAgICAgIFZpcnR1YWxUZXh0LnByb3RvdHlwZS50eXBlID0gXCJWaXJ0dWFsVGV4dFwiO1xuICAgICAgICB9LCB7IFwiLi92ZXJzaW9uXCI6IDMwIH1dLCAzNDogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHtcbiAgICAgICAgICAgIHZhciBpc09iamVjdCA9IHJlcXVpcmUoXCJpcy1vYmplY3RcIik7XG4gICAgICAgICAgICB2YXIgaXNIb29rID0gcmVxdWlyZShcIi4uL3Zub2RlL2lzLXZob29rXCIpO1xuXG4gICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IGRpZmZQcm9wcztcblxuICAgICAgICAgICAgZnVuY3Rpb24gZGlmZlByb3BzKGEsIGIpIHtcbiAgICAgICAgICAgICAgICB2YXIgZGlmZjtcblxuICAgICAgICAgICAgICAgIGZvciAodmFyIGFLZXkgaW4gYSkge1xuICAgICAgICAgICAgICAgICAgICBpZiAoIShhS2V5IGluIGIpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBkaWZmID0gZGlmZiB8fCB7fTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGRpZmZbYUtleV0gPSB1bmRlZmluZWQ7XG4gICAgICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgICAgICB2YXIgYVZhbHVlID0gYVthS2V5XTtcbiAgICAgICAgICAgICAgICAgICAgdmFyIGJWYWx1ZSA9IGJbYUtleV07XG5cbiAgICAgICAgICAgICAgICAgICAgaWYgKGFWYWx1ZSA9PT0gYlZhbHVlKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBjb250aW51ZTtcbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIGlmIChpc09iamVjdChhVmFsdWUpICYmIGlzT2JqZWN0KGJWYWx1ZSkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChnZXRQcm90b3R5cGUoYlZhbHVlKSAhPT0gZ2V0UHJvdG90eXBlKGFWYWx1ZSkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBkaWZmID0gZGlmZiB8fCB7fTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBkaWZmW2FLZXldID0gYlZhbHVlO1xuICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIGlmIChpc0hvb2soYlZhbHVlKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRpZmYgPSBkaWZmIHx8IHt9O1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRpZmZbYUtleV0gPSBiVmFsdWU7XG4gICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZhciBvYmplY3REaWZmID0gZGlmZlByb3BzKGFWYWx1ZSwgYlZhbHVlKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAob2JqZWN0RGlmZikge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBkaWZmID0gZGlmZiB8fCB7fTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZGlmZlthS2V5XSA9IG9iamVjdERpZmY7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgZGlmZiA9IGRpZmYgfHwge307XG4gICAgICAgICAgICAgICAgICAgICAgICBkaWZmW2FLZXldID0gYlZhbHVlO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgZm9yICh2YXIgYktleSBpbiBiKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmICghKGJLZXkgaW4gYSkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGRpZmYgPSBkaWZmIHx8IHt9O1xuICAgICAgICAgICAgICAgICAgICAgICAgZGlmZltiS2V5XSA9IGJbYktleV07XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICByZXR1cm4gZGlmZjtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZnVuY3Rpb24gZ2V0UHJvdG90eXBlKHZhbHVlKSB7XG4gICAgICAgICAgICAgICAgaWYgKE9iamVjdC5nZXRQcm90b3R5cGVPZikge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gT2JqZWN0LmdldFByb3RvdHlwZU9mKHZhbHVlKTtcbiAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKHZhbHVlLl9fcHJvdG9fXykge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gdmFsdWUuX19wcm90b19fO1xuICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAodmFsdWUuY29uc3RydWN0b3IpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHZhbHVlLmNvbnN0cnVjdG9yLnByb3RvdHlwZTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH0sIHsgXCIuLi92bm9kZS9pcy12aG9va1wiOiAyNiwgXCJpcy1vYmplY3RcIjogMTEgfV0sIDM1OiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge1xuICAgICAgICAgICAgdmFyIGlzQXJyYXkgPSByZXF1aXJlKFwieC1pcy1hcnJheVwiKTtcblxuICAgICAgICAgICAgdmFyIFZQYXRjaCA9IHJlcXVpcmUoXCIuLi92bm9kZS92cGF0Y2hcIik7XG4gICAgICAgICAgICB2YXIgaXNWTm9kZSA9IHJlcXVpcmUoXCIuLi92bm9kZS9pcy12bm9kZVwiKTtcbiAgICAgICAgICAgIHZhciBpc1ZUZXh0ID0gcmVxdWlyZShcIi4uL3Zub2RlL2lzLXZ0ZXh0XCIpO1xuICAgICAgICAgICAgdmFyIGlzV2lkZ2V0ID0gcmVxdWlyZShcIi4uL3Zub2RlL2lzLXdpZGdldFwiKTtcbiAgICAgICAgICAgIHZhciBpc1RodW5rID0gcmVxdWlyZShcIi4uL3Zub2RlL2lzLXRodW5rXCIpO1xuICAgICAgICAgICAgdmFyIGhhbmRsZVRodW5rID0gcmVxdWlyZShcIi4uL3Zub2RlL2hhbmRsZS10aHVua1wiKTtcblxuICAgICAgICAgICAgdmFyIGRpZmZQcm9wcyA9IHJlcXVpcmUoXCIuL2RpZmYtcHJvcHNcIik7XG5cbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gZGlmZjtcblxuICAgICAgICAgICAgZnVuY3Rpb24gZGlmZihhLCBiKSB7XG4gICAgICAgICAgICAgICAgdmFyIHBhdGNoID0geyBhOiBhIH07XG4gICAgICAgICAgICAgICAgd2FsayhhLCBiLCBwYXRjaCwgMCk7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHBhdGNoO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBmdW5jdGlvbiB3YWxrKGEsIGIsIHBhdGNoLCBpbmRleCkge1xuICAgICAgICAgICAgICAgIGlmIChhID09PSBiKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICB2YXIgYXBwbHkgPSBwYXRjaFtpbmRleF07XG4gICAgICAgICAgICAgICAgdmFyIGFwcGx5Q2xlYXIgPSBmYWxzZTtcblxuICAgICAgICAgICAgICAgIGlmIChpc1RodW5rKGEpIHx8IGlzVGh1bmsoYikpIHtcbiAgICAgICAgICAgICAgICAgICAgdGh1bmtzKGEsIGIsIHBhdGNoLCBpbmRleCk7XG4gICAgICAgICAgICAgICAgfSBlbHNlIGlmIChiID09IG51bGwpIHtcblxuICAgICAgICAgICAgICAgICAgICAvLyBJZiBhIGlzIGEgd2lkZ2V0IHdlIHdpbGwgYWRkIGEgcmVtb3ZlIHBhdGNoIGZvciBpdFxuICAgICAgICAgICAgICAgICAgICAvLyBPdGhlcndpc2UgYW55IGNoaWxkIHdpZGdldHMvaG9va3MgbXVzdCBiZSBkZXN0cm95ZWQuXG4gICAgICAgICAgICAgICAgICAgIC8vIFRoaXMgcHJldmVudHMgYWRkaW5nIHR3byByZW1vdmUgcGF0Y2hlcyBmb3IgYSB3aWRnZXQuXG4gICAgICAgICAgICAgICAgICAgIGlmICghaXNXaWRnZXQoYSkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGNsZWFyU3RhdGUoYSwgcGF0Y2gsIGluZGV4KTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGFwcGx5ID0gcGF0Y2hbaW5kZXhdO1xuICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgYXBwbHkgPSBhcHBlbmRQYXRjaChhcHBseSwgbmV3IFZQYXRjaChWUGF0Y2guUkVNT1ZFLCBhLCBiKSk7XG4gICAgICAgICAgICAgICAgfSBlbHNlIGlmIChpc1ZOb2RlKGIpKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmIChpc1ZOb2RlKGEpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoYS50YWdOYW1lID09PSBiLnRhZ05hbWUgJiYgYS5uYW1lc3BhY2UgPT09IGIubmFtZXNwYWNlICYmIGEua2V5ID09PSBiLmtleSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZhciBwcm9wc1BhdGNoID0gZGlmZlByb3BzKGEucHJvcGVydGllcywgYi5wcm9wZXJ0aWVzKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAocHJvcHNQYXRjaCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBhcHBseSA9IGFwcGVuZFBhdGNoKGFwcGx5LCBuZXcgVlBhdGNoKFZQYXRjaC5QUk9QUywgYSwgcHJvcHNQYXRjaCkpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBhcHBseSA9IGRpZmZDaGlsZHJlbihhLCBiLCBwYXRjaCwgYXBwbHksIGluZGV4KTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgYXBwbHkgPSBhcHBlbmRQYXRjaChhcHBseSwgbmV3IFZQYXRjaChWUGF0Y2guVk5PREUsIGEsIGIpKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBhcHBseUNsZWFyID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGFwcGx5ID0gYXBwZW5kUGF0Y2goYXBwbHksIG5ldyBWUGF0Y2goVlBhdGNoLlZOT0RFLCBhLCBiKSk7XG4gICAgICAgICAgICAgICAgICAgICAgICBhcHBseUNsZWFyID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoaXNWVGV4dChiKSkge1xuICAgICAgICAgICAgICAgICAgICBpZiAoIWlzVlRleHQoYSkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGFwcGx5ID0gYXBwZW5kUGF0Y2goYXBwbHksIG5ldyBWUGF0Y2goVlBhdGNoLlZURVhULCBhLCBiKSk7XG4gICAgICAgICAgICAgICAgICAgICAgICBhcHBseUNsZWFyID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIGlmIChhLnRleHQgIT09IGIudGV4dCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgYXBwbHkgPSBhcHBlbmRQYXRjaChhcHBseSwgbmV3IFZQYXRjaChWUGF0Y2guVlRFWFQsIGEsIGIpKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoaXNXaWRnZXQoYikpIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKCFpc1dpZGdldChhKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgYXBwbHlDbGVhciA9IHRydWU7XG4gICAgICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgICAgICBhcHBseSA9IGFwcGVuZFBhdGNoKGFwcGx5LCBuZXcgVlBhdGNoKFZQYXRjaC5XSURHRVQsIGEsIGIpKTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICBpZiAoYXBwbHkpIHtcbiAgICAgICAgICAgICAgICAgICAgcGF0Y2hbaW5kZXhdID0gYXBwbHk7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgaWYgKGFwcGx5Q2xlYXIpIHtcbiAgICAgICAgICAgICAgICAgICAgY2xlYXJTdGF0ZShhLCBwYXRjaCwgaW5kZXgpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZnVuY3Rpb24gZGlmZkNoaWxkcmVuKGEsIGIsIHBhdGNoLCBhcHBseSwgaW5kZXgpIHtcbiAgICAgICAgICAgICAgICB2YXIgYUNoaWxkcmVuID0gYS5jaGlsZHJlbjtcbiAgICAgICAgICAgICAgICB2YXIgb3JkZXJlZFNldCA9IHJlb3JkZXIoYUNoaWxkcmVuLCBiLmNoaWxkcmVuKTtcbiAgICAgICAgICAgICAgICB2YXIgYkNoaWxkcmVuID0gb3JkZXJlZFNldC5jaGlsZHJlbjtcblxuICAgICAgICAgICAgICAgIHZhciBhTGVuID0gYUNoaWxkcmVuLmxlbmd0aDtcbiAgICAgICAgICAgICAgICB2YXIgYkxlbiA9IGJDaGlsZHJlbi5sZW5ndGg7XG4gICAgICAgICAgICAgICAgdmFyIGxlbiA9IGFMZW4gPiBiTGVuID8gYUxlbiA6IGJMZW47XG5cbiAgICAgICAgICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IGxlbjsgaSsrKSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciBsZWZ0Tm9kZSA9IGFDaGlsZHJlbltpXTtcbiAgICAgICAgICAgICAgICAgICAgdmFyIHJpZ2h0Tm9kZSA9IGJDaGlsZHJlbltpXTtcbiAgICAgICAgICAgICAgICAgICAgaW5kZXggKz0gMTtcblxuICAgICAgICAgICAgICAgICAgICBpZiAoIWxlZnROb2RlKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAocmlnaHROb2RlKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gRXhjZXNzIG5vZGVzIGluIGIgbmVlZCB0byBiZSBhZGRlZFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGFwcGx5ID0gYXBwZW5kUGF0Y2goYXBwbHksIG5ldyBWUGF0Y2goVlBhdGNoLklOU0VSVCwgbnVsbCwgcmlnaHROb2RlKSk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICB3YWxrKGxlZnROb2RlLCByaWdodE5vZGUsIHBhdGNoLCBpbmRleCk7XG4gICAgICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgICAgICBpZiAoaXNWTm9kZShsZWZ0Tm9kZSkgJiYgbGVmdE5vZGUuY291bnQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGluZGV4ICs9IGxlZnROb2RlLmNvdW50O1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgaWYgKG9yZGVyZWRTZXQubW92ZXMpIHtcbiAgICAgICAgICAgICAgICAgICAgLy8gUmVvcmRlciBub2RlcyBsYXN0XG4gICAgICAgICAgICAgICAgICAgIGFwcGx5ID0gYXBwZW5kUGF0Y2goYXBwbHksIG5ldyBWUGF0Y2goVlBhdGNoLk9SREVSLCBhLCBvcmRlcmVkU2V0Lm1vdmVzKSk7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgcmV0dXJuIGFwcGx5O1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBmdW5jdGlvbiBjbGVhclN0YXRlKHZOb2RlLCBwYXRjaCwgaW5kZXgpIHtcbiAgICAgICAgICAgICAgICAvLyBUT0RPOiBNYWtlIHRoaXMgYSBzaW5nbGUgd2Fsaywgbm90IHR3b1xuICAgICAgICAgICAgICAgIHVuaG9vayh2Tm9kZSwgcGF0Y2gsIGluZGV4KTtcbiAgICAgICAgICAgICAgICBkZXN0cm95V2lkZ2V0cyh2Tm9kZSwgcGF0Y2gsIGluZGV4KTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgLy8gUGF0Y2ggcmVjb3JkcyBmb3IgYWxsIGRlc3Ryb3llZCB3aWRnZXRzIG11c3QgYmUgYWRkZWQgYmVjYXVzZSB3ZSBuZWVkXG4gICAgICAgICAgICAvLyBhIERPTSBub2RlIHJlZmVyZW5jZSBmb3IgdGhlIGRlc3Ryb3kgZnVuY3Rpb25cbiAgICAgICAgICAgIGZ1bmN0aW9uIGRlc3Ryb3lXaWRnZXRzKHZOb2RlLCBwYXRjaCwgaW5kZXgpIHtcbiAgICAgICAgICAgICAgICBpZiAoaXNXaWRnZXQodk5vZGUpKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmICh0eXBlb2Ygdk5vZGUuZGVzdHJveSA9PT0gXCJmdW5jdGlvblwiKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBwYXRjaFtpbmRleF0gPSBhcHBlbmRQYXRjaChwYXRjaFtpbmRleF0sIG5ldyBWUGF0Y2goVlBhdGNoLlJFTU9WRSwgdk5vZGUsIG51bGwpKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoaXNWTm9kZSh2Tm9kZSkgJiYgKHZOb2RlLmhhc1dpZGdldHMgfHwgdk5vZGUuaGFzVGh1bmtzKSkge1xuICAgICAgICAgICAgICAgICAgICB2YXIgY2hpbGRyZW4gPSB2Tm9kZS5jaGlsZHJlbjtcbiAgICAgICAgICAgICAgICAgICAgdmFyIGxlbiA9IGNoaWxkcmVuLmxlbmd0aDtcbiAgICAgICAgICAgICAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCBsZW47IGkrKykge1xuICAgICAgICAgICAgICAgICAgICAgICAgdmFyIGNoaWxkID0gY2hpbGRyZW5baV07XG4gICAgICAgICAgICAgICAgICAgICAgICBpbmRleCArPSAxO1xuXG4gICAgICAgICAgICAgICAgICAgICAgICBkZXN0cm95V2lkZ2V0cyhjaGlsZCwgcGF0Y2gsIGluZGV4KTtcblxuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGlzVk5vZGUoY2hpbGQpICYmIGNoaWxkLmNvdW50KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaW5kZXggKz0gY2hpbGQuY291bnQ7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKGlzVGh1bmsodk5vZGUpKSB7XG4gICAgICAgICAgICAgICAgICAgIHRodW5rcyh2Tm9kZSwgbnVsbCwgcGF0Y2gsIGluZGV4KTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIC8vIENyZWF0ZSBhIHN1Yi1wYXRjaCBmb3IgdGh1bmtzXG4gICAgICAgICAgICBmdW5jdGlvbiB0aHVua3MoYSwgYiwgcGF0Y2gsIGluZGV4KSB7XG4gICAgICAgICAgICAgICAgdmFyIG5vZGVzID0gaGFuZGxlVGh1bmsoYSwgYik7XG4gICAgICAgICAgICAgICAgdmFyIHRodW5rUGF0Y2ggPSBkaWZmKG5vZGVzLmEsIG5vZGVzLmIpO1xuICAgICAgICAgICAgICAgIGlmIChoYXNQYXRjaGVzKHRodW5rUGF0Y2gpKSB7XG4gICAgICAgICAgICAgICAgICAgIHBhdGNoW2luZGV4XSA9IG5ldyBWUGF0Y2goVlBhdGNoLlRIVU5LLCBudWxsLCB0aHVua1BhdGNoKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIGhhc1BhdGNoZXMocGF0Y2gpIHtcbiAgICAgICAgICAgICAgICBmb3IgKHZhciBpbmRleCBpbiBwYXRjaCkge1xuICAgICAgICAgICAgICAgICAgICBpZiAoaW5kZXggIT09IFwiYVwiKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgLy8gRXhlY3V0ZSBob29rcyB3aGVuIHR3byBub2RlcyBhcmUgaWRlbnRpY2FsXG4gICAgICAgICAgICBmdW5jdGlvbiB1bmhvb2sodk5vZGUsIHBhdGNoLCBpbmRleCkge1xuICAgICAgICAgICAgICAgIGlmIChpc1ZOb2RlKHZOb2RlKSkge1xuICAgICAgICAgICAgICAgICAgICBpZiAodk5vZGUuaG9va3MpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHBhdGNoW2luZGV4XSA9IGFwcGVuZFBhdGNoKHBhdGNoW2luZGV4XSwgbmV3IFZQYXRjaChWUGF0Y2guUFJPUFMsIHZOb2RlLCB1bmRlZmluZWRLZXlzKHZOb2RlLmhvb2tzKSkpO1xuICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgaWYgKHZOb2RlLmRlc2NlbmRhbnRIb29rcyB8fCB2Tm9kZS5oYXNUaHVua3MpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHZhciBjaGlsZHJlbiA9IHZOb2RlLmNoaWxkcmVuO1xuICAgICAgICAgICAgICAgICAgICAgICAgdmFyIGxlbiA9IGNoaWxkcmVuLmxlbmd0aDtcbiAgICAgICAgICAgICAgICAgICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgbGVuOyBpKyspIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB2YXIgY2hpbGQgPSBjaGlsZHJlbltpXTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpbmRleCArPSAxO1xuXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdW5ob29rKGNoaWxkLCBwYXRjaCwgaW5kZXgpO1xuXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGlzVk5vZGUoY2hpbGQpICYmIGNoaWxkLmNvdW50KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGluZGV4ICs9IGNoaWxkLmNvdW50O1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoaXNUaHVuayh2Tm9kZSkpIHtcbiAgICAgICAgICAgICAgICAgICAgdGh1bmtzKHZOb2RlLCBudWxsLCBwYXRjaCwgaW5kZXgpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZnVuY3Rpb24gdW5kZWZpbmVkS2V5cyhvYmopIHtcbiAgICAgICAgICAgICAgICB2YXIgcmVzdWx0ID0ge307XG5cbiAgICAgICAgICAgICAgICBmb3IgKHZhciBrZXkgaW4gb2JqKSB7XG4gICAgICAgICAgICAgICAgICAgIHJlc3VsdFtrZXldID0gdW5kZWZpbmVkO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHJldHVybiByZXN1bHQ7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIC8vIExpc3QgZGlmZiwgbmFpdmUgbGVmdCB0byByaWdodCByZW9yZGVyaW5nXG4gICAgICAgICAgICBmdW5jdGlvbiByZW9yZGVyKGFDaGlsZHJlbiwgYkNoaWxkcmVuKSB7XG4gICAgICAgICAgICAgICAgLy8gTyhNKSB0aW1lLCBPKE0pIG1lbW9yeVxuICAgICAgICAgICAgICAgIHZhciBiQ2hpbGRJbmRleCA9IGtleUluZGV4KGJDaGlsZHJlbik7XG4gICAgICAgICAgICAgICAgdmFyIGJLZXlzID0gYkNoaWxkSW5kZXgua2V5cztcbiAgICAgICAgICAgICAgICB2YXIgYkZyZWUgPSBiQ2hpbGRJbmRleC5mcmVlO1xuXG4gICAgICAgICAgICAgICAgaWYgKGJGcmVlLmxlbmd0aCA9PT0gYkNoaWxkcmVuLmxlbmd0aCkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgICAgICAgICAgICAgY2hpbGRyZW46IGJDaGlsZHJlbixcbiAgICAgICAgICAgICAgICAgICAgICAgIG1vdmVzOiBudWxsXG4gICAgICAgICAgICAgICAgICAgIH07XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgLy8gTyhOKSB0aW1lLCBPKE4pIG1lbW9yeVxuICAgICAgICAgICAgICAgIHZhciBhQ2hpbGRJbmRleCA9IGtleUluZGV4KGFDaGlsZHJlbik7XG4gICAgICAgICAgICAgICAgdmFyIGFLZXlzID0gYUNoaWxkSW5kZXgua2V5cztcbiAgICAgICAgICAgICAgICB2YXIgYUZyZWUgPSBhQ2hpbGRJbmRleC5mcmVlO1xuXG4gICAgICAgICAgICAgICAgaWYgKGFGcmVlLmxlbmd0aCA9PT0gYUNoaWxkcmVuLmxlbmd0aCkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgICAgICAgICAgICAgY2hpbGRyZW46IGJDaGlsZHJlbixcbiAgICAgICAgICAgICAgICAgICAgICAgIG1vdmVzOiBudWxsXG4gICAgICAgICAgICAgICAgICAgIH07XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgLy8gTyhNQVgoTiwgTSkpIG1lbW9yeVxuICAgICAgICAgICAgICAgIHZhciBuZXdDaGlsZHJlbiA9IFtdO1xuXG4gICAgICAgICAgICAgICAgdmFyIGZyZWVJbmRleCA9IDA7XG4gICAgICAgICAgICAgICAgdmFyIGZyZWVDb3VudCA9IGJGcmVlLmxlbmd0aDtcbiAgICAgICAgICAgICAgICB2YXIgZGVsZXRlZEl0ZW1zID0gMDtcblxuICAgICAgICAgICAgICAgIC8vIEl0ZXJhdGUgdGhyb3VnaCBhIGFuZCBtYXRjaCBhIG5vZGUgaW4gYlxuICAgICAgICAgICAgICAgIC8vIE8oTikgdGltZSxcbiAgICAgICAgICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IGFDaGlsZHJlbi5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgICAgICAgICB2YXIgYUl0ZW0gPSBhQ2hpbGRyZW5baV07XG4gICAgICAgICAgICAgICAgICAgIHZhciBpdGVtSW5kZXg7XG5cbiAgICAgICAgICAgICAgICAgICAgaWYgKGFJdGVtLmtleSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGJLZXlzLmhhc093blByb3BlcnR5KGFJdGVtLmtleSkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBNYXRjaCB1cCB0aGUgb2xkIGtleXNcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpdGVtSW5kZXggPSBiS2V5c1thSXRlbS5rZXldO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIG5ld0NoaWxkcmVuLnB1c2goYkNoaWxkcmVuW2l0ZW1JbmRleF0pO1xuICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBSZW1vdmUgb2xkIGtleWVkIGl0ZW1zXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaXRlbUluZGV4ID0gaSAtIGRlbGV0ZWRJdGVtcysrO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIG5ld0NoaWxkcmVuLnB1c2gobnVsbCk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAvLyBNYXRjaCB0aGUgaXRlbSBpbiBhIHdpdGggdGhlIG5leHQgZnJlZSBpdGVtIGluIGJcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChmcmVlSW5kZXggPCBmcmVlQ291bnQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpdGVtSW5kZXggPSBiRnJlZVtmcmVlSW5kZXgrK107XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgbmV3Q2hpbGRyZW4ucHVzaChiQ2hpbGRyZW5baXRlbUluZGV4XSk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIFRoZXJlIGFyZSBubyBmcmVlIGl0ZW1zIGluIGIgdG8gbWF0Y2ggd2l0aFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIHRoZSBmcmVlIGl0ZW1zIGluIGEsIHNvIHRoZSBleHRyYSBmcmVlIG5vZGVzXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gYXJlIGRlbGV0ZWQuXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaXRlbUluZGV4ID0gaSAtIGRlbGV0ZWRJdGVtcysrO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIG5ld0NoaWxkcmVuLnB1c2gobnVsbCk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICB2YXIgbGFzdEZyZWVJbmRleCA9IGZyZWVJbmRleCA+PSBiRnJlZS5sZW5ndGggPyBiQ2hpbGRyZW4ubGVuZ3RoIDogYkZyZWVbZnJlZUluZGV4XTtcblxuICAgICAgICAgICAgICAgIC8vIEl0ZXJhdGUgdGhyb3VnaCBiIGFuZCBhcHBlbmQgYW55IG5ldyBrZXlzXG4gICAgICAgICAgICAgICAgLy8gTyhNKSB0aW1lXG4gICAgICAgICAgICAgICAgZm9yICh2YXIgaiA9IDA7IGogPCBiQ2hpbGRyZW4ubGVuZ3RoOyBqKyspIHtcbiAgICAgICAgICAgICAgICAgICAgdmFyIG5ld0l0ZW0gPSBiQ2hpbGRyZW5bal07XG5cbiAgICAgICAgICAgICAgICAgICAgaWYgKG5ld0l0ZW0ua2V5KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoIWFLZXlzLmhhc093blByb3BlcnR5KG5ld0l0ZW0ua2V5KSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIEFkZCBhbnkgbmV3IGtleWVkIGl0ZW1zXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gV2UgYXJlIGFkZGluZyBuZXcgaXRlbXMgdG8gdGhlIGVuZCBhbmQgdGhlbiBzb3J0aW5nIHRoZW1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBpbiBwbGFjZS4gSW4gZnV0dXJlIHdlIHNob3VsZCBpbnNlcnQgbmV3IGl0ZW1zIGluIHBsYWNlLlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIG5ld0NoaWxkcmVuLnB1c2gobmV3SXRlbSk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoaiA+PSBsYXN0RnJlZUluZGV4KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAvLyBBZGQgYW55IGxlZnRvdmVyIG5vbi1rZXllZCBpdGVtc1xuICAgICAgICAgICAgICAgICAgICAgICAgbmV3Q2hpbGRyZW4ucHVzaChuZXdJdGVtKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHZhciBzaW11bGF0ZSA9IG5ld0NoaWxkcmVuLnNsaWNlKCk7XG4gICAgICAgICAgICAgICAgdmFyIHNpbXVsYXRlSW5kZXggPSAwO1xuICAgICAgICAgICAgICAgIHZhciByZW1vdmVzID0gW107XG4gICAgICAgICAgICAgICAgdmFyIGluc2VydHMgPSBbXTtcbiAgICAgICAgICAgICAgICB2YXIgc2ltdWxhdGVJdGVtO1xuXG4gICAgICAgICAgICAgICAgZm9yICh2YXIgayA9IDA7IGsgPCBiQ2hpbGRyZW4ubGVuZ3RoOykge1xuICAgICAgICAgICAgICAgICAgICB2YXIgd2FudGVkSXRlbSA9IGJDaGlsZHJlbltrXTtcbiAgICAgICAgICAgICAgICAgICAgc2ltdWxhdGVJdGVtID0gc2ltdWxhdGVbc2ltdWxhdGVJbmRleF07XG5cbiAgICAgICAgICAgICAgICAgICAgLy8gcmVtb3ZlIGl0ZW1zXG4gICAgICAgICAgICAgICAgICAgIHdoaWxlIChzaW11bGF0ZUl0ZW0gPT09IG51bGwgJiYgc2ltdWxhdGUubGVuZ3RoKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICByZW1vdmVzLnB1c2gocmVtb3ZlKHNpbXVsYXRlLCBzaW11bGF0ZUluZGV4LCBudWxsKSk7XG4gICAgICAgICAgICAgICAgICAgICAgICBzaW11bGF0ZUl0ZW0gPSBzaW11bGF0ZVtzaW11bGF0ZUluZGV4XTtcbiAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgIGlmICghc2ltdWxhdGVJdGVtIHx8IHNpbXVsYXRlSXRlbS5rZXkgIT09IHdhbnRlZEl0ZW0ua2V5KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAvLyBpZiB3ZSBuZWVkIGEga2V5IGluIHRoaXMgcG9zaXRpb24uLi5cbiAgICAgICAgICAgICAgICAgICAgICAgIGlmICh3YW50ZWRJdGVtLmtleSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChzaW11bGF0ZUl0ZW0gJiYgc2ltdWxhdGVJdGVtLmtleSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBpZiBhbiBpbnNlcnQgZG9lc24ndCBwdXQgdGhpcyBrZXkgaW4gcGxhY2UsIGl0IG5lZWRzIHRvIG1vdmVcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGJLZXlzW3NpbXVsYXRlSXRlbS5rZXldICE9PSBrICsgMSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmVtb3Zlcy5wdXNoKHJlbW92ZShzaW11bGF0ZSwgc2ltdWxhdGVJbmRleCwgc2ltdWxhdGVJdGVtLmtleSkpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc2ltdWxhdGVJdGVtID0gc2ltdWxhdGVbc2ltdWxhdGVJbmRleF07XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBpZiB0aGUgcmVtb3ZlIGRpZG4ndCBwdXQgdGhlIHdhbnRlZCBpdGVtIGluIHBsYWNlLCB3ZSBuZWVkIHRvIGluc2VydCBpdFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKCFzaW11bGF0ZUl0ZW0gfHwgc2ltdWxhdGVJdGVtLmtleSAhPT0gd2FudGVkSXRlbS5rZXkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpbnNlcnRzLnB1c2goeyBrZXk6IHdhbnRlZEl0ZW0ua2V5LCB0bzogayB9KTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIGl0ZW1zIGFyZSBtYXRjaGluZywgc28gc2tpcCBhaGVhZFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc2ltdWxhdGVJbmRleCsrO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaW5zZXJ0cy5wdXNoKHsga2V5OiB3YW50ZWRJdGVtLmtleSwgdG86IGsgfSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpbnNlcnRzLnB1c2goeyBrZXk6IHdhbnRlZEl0ZW0ua2V5LCB0bzogayB9KTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaysrO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgLy8gYSBrZXkgaW4gc2ltdWxhdGUgaGFzIG5vIG1hdGNoaW5nIHdhbnRlZCBrZXksIHJlbW92ZSBpdFxuICAgICAgICAgICAgICAgICAgICAgICAgZWxzZSBpZiAoc2ltdWxhdGVJdGVtICYmIHNpbXVsYXRlSXRlbS5rZXkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICByZW1vdmVzLnB1c2gocmVtb3ZlKHNpbXVsYXRlLCBzaW11bGF0ZUluZGV4LCBzaW11bGF0ZUl0ZW0ua2V5KSk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBzaW11bGF0ZUluZGV4Kys7XG4gICAgICAgICAgICAgICAgICAgICAgICBrKys7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAvLyByZW1vdmUgYWxsIHRoZSByZW1haW5pbmcgbm9kZXMgZnJvbSBzaW11bGF0ZVxuICAgICAgICAgICAgICAgIHdoaWxlIChzaW11bGF0ZUluZGV4IDwgc2ltdWxhdGUubGVuZ3RoKSB7XG4gICAgICAgICAgICAgICAgICAgIHNpbXVsYXRlSXRlbSA9IHNpbXVsYXRlW3NpbXVsYXRlSW5kZXhdO1xuICAgICAgICAgICAgICAgICAgICByZW1vdmVzLnB1c2gocmVtb3ZlKHNpbXVsYXRlLCBzaW11bGF0ZUluZGV4LCBzaW11bGF0ZUl0ZW0gJiYgc2ltdWxhdGVJdGVtLmtleSkpO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIC8vIElmIHRoZSBvbmx5IG1vdmVzIHdlIGhhdmUgYXJlIGRlbGV0ZXMgdGhlbiB3ZSBjYW4ganVzdFxuICAgICAgICAgICAgICAgIC8vIGxldCB0aGUgZGVsZXRlIHBhdGNoIHJlbW92ZSB0aGVzZSBpdGVtcy5cbiAgICAgICAgICAgICAgICBpZiAocmVtb3Zlcy5sZW5ndGggPT09IGRlbGV0ZWRJdGVtcyAmJiAhaW5zZXJ0cy5sZW5ndGgpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGNoaWxkcmVuOiBuZXdDaGlsZHJlbixcbiAgICAgICAgICAgICAgICAgICAgICAgIG1vdmVzOiBudWxsXG4gICAgICAgICAgICAgICAgICAgIH07XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgICAgICAgICAgY2hpbGRyZW46IG5ld0NoaWxkcmVuLFxuICAgICAgICAgICAgICAgICAgICBtb3Zlczoge1xuICAgICAgICAgICAgICAgICAgICAgICAgcmVtb3ZlczogcmVtb3ZlcyxcbiAgICAgICAgICAgICAgICAgICAgICAgIGluc2VydHM6IGluc2VydHNcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH07XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIHJlbW92ZShhcnIsIGluZGV4LCBrZXkpIHtcbiAgICAgICAgICAgICAgICBhcnIuc3BsaWNlKGluZGV4LCAxKTtcblxuICAgICAgICAgICAgICAgIHJldHVybiB7XG4gICAgICAgICAgICAgICAgICAgIGZyb206IGluZGV4LFxuICAgICAgICAgICAgICAgICAgICBrZXk6IGtleVxuICAgICAgICAgICAgICAgIH07XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIGtleUluZGV4KGNoaWxkcmVuKSB7XG4gICAgICAgICAgICAgICAgdmFyIGtleXMgPSB7fTtcbiAgICAgICAgICAgICAgICB2YXIgZnJlZSA9IFtdO1xuICAgICAgICAgICAgICAgIHZhciBsZW5ndGggPSBjaGlsZHJlbi5sZW5ndGg7XG5cbiAgICAgICAgICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IGxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciBjaGlsZCA9IGNoaWxkcmVuW2ldO1xuXG4gICAgICAgICAgICAgICAgICAgIGlmIChjaGlsZC5rZXkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGtleXNbY2hpbGQua2V5XSA9IGk7XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBmcmVlLnB1c2goaSk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgICAgICAgICBrZXlzOiBrZXlzLCAvLyBBIGhhc2ggb2Yga2V5IG5hbWUgdG8gaW5kZXhcbiAgICAgICAgICAgICAgICAgICAgZnJlZTogZnJlZSAvLyBBbiBhcnJheSBvZiB1bmtleWVkIGl0ZW0gaW5kaWNlc1xuICAgICAgICAgICAgICAgIH07XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIGFwcGVuZFBhdGNoKGFwcGx5LCBwYXRjaCkge1xuICAgICAgICAgICAgICAgIGlmIChhcHBseSkge1xuICAgICAgICAgICAgICAgICAgICBpZiAoaXNBcnJheShhcHBseSkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGFwcGx5LnB1c2gocGF0Y2gpO1xuICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgYXBwbHkgPSBbYXBwbHksIHBhdGNoXTtcbiAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBhcHBseTtcbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gcGF0Y2g7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9LCB7IFwiLi4vdm5vZGUvaGFuZGxlLXRodW5rXCI6IDI0LCBcIi4uL3Zub2RlL2lzLXRodW5rXCI6IDI1LCBcIi4uL3Zub2RlL2lzLXZub2RlXCI6IDI3LCBcIi4uL3Zub2RlL2lzLXZ0ZXh0XCI6IDI4LCBcIi4uL3Zub2RlL2lzLXdpZGdldFwiOiAyOSwgXCIuLi92bm9kZS92cGF0Y2hcIjogMzIsIFwiLi9kaWZmLXByb3BzXCI6IDM0LCBcIngtaXMtYXJyYXlcIjogMTIgfV0gfSwge30sIFs0XSkoNCk7XG59KTtcblxuY29uc3Qgc3RhcnQgPSBmdW5jdGlvbiAoZG9tUm9vdCwgcmVuZGVyRm4sIGluaXRpYWxTdGF0ZSwgb3B0aW9ucyA9IFtdKSB7XG4gIGxldCBwaWQgPSBzZWxmLnByb2Nlc3Nlcy5zcGF3bigpO1xuXG4gIGlmIChLZXl3b3JkLmhhc19rZXlfX3FtX18ob3B0aW9ucywgS2VybmVsLlNwZWNpYWxGb3Jtcy5hdG9tKCduYW1lJykpKSB7XG4gICAgcGlkID0gc2VsZi5wcm9jZXNzZXMucmVnaXN0ZXIoS2V5d29yZC5nZXQob3B0aW9ucywgS2VybmVsLlNwZWNpYWxGb3Jtcy5hdG9tKCduYW1lJykpLCBwaWQpO1xuICB9XG5cbiAgY29uc3QgdHJlZSA9IHJlbmRlckZuLmFwcGx5KHRoaXMsIGluaXRpYWxTdGF0ZSk7XG4gIGNvbnN0IHJvb3ROb2RlID0gVmlydHVhbERPTS5jcmVhdGUodHJlZSk7XG5cbiAgZG9tUm9vdC5hcHBlbmRDaGlsZChyb290Tm9kZSk7XG5cbiAgc2VsZi5wcm9jZXNzZXMucHV0KHBpZCwgJ3N0YXRlJywgS2VybmVsLlNwZWNpYWxGb3Jtcy50dXBsZShyb290Tm9kZSwgdHJlZSwgcmVuZGVyRm4pKTtcbiAgcmV0dXJuIEtlcm5lbC5TcGVjaWFsRm9ybXMudHVwbGUoS2VybmVsLlNwZWNpYWxGb3Jtcy5hdG9tKCdvaycpLCBwaWQpO1xufTtcblxuY29uc3Qgc3RvcCA9IGZ1bmN0aW9uIChhZ2VudCwgdGltZW91dCA9IDUwMDApIHtcbiAgc2VsZi5wcm9jZXNzZXMuZXhpdChhZ2VudCk7XG4gIHJldHVybiBLZXJuZWwuU3BlY2lhbEZvcm1zLmF0b20oJ29rJyk7XG59O1xuXG5jb25zdCByZW5kZXIgPSBmdW5jdGlvbiAoYWdlbnQsIHN0YXRlKSB7XG5cbiAgY29uc3QgY3VycmVudF9zdGF0ZSA9IHNlbGYucHJvY2Vzc2VzLmdldChhZ2VudCwgJ3N0YXRlJyk7XG5cbiAgbGV0IHJvb3ROb2RlID0gS2VybmVsLmVsZW0oY3VycmVudF9zdGF0ZSwgMCk7XG4gIGxldCB0cmVlID0gS2VybmVsLmVsZW0oY3VycmVudF9zdGF0ZSwgMSk7XG4gIGxldCByZW5kZXJGbiA9IEtlcm5lbC5lbGVtKGN1cnJlbnRfc3RhdGUsIDIpO1xuXG4gIGxldCBuZXdUcmVlID0gcmVuZGVyRm4uYXBwbHkodGhpcywgc3RhdGUpO1xuXG4gIGxldCBwYXRjaGVzID0gVmlydHVhbERPTS5kaWZmKHRyZWUsIG5ld1RyZWUpO1xuICByb290Tm9kZSA9IFZpcnR1YWxET00ucGF0Y2gocm9vdE5vZGUsIHBhdGNoZXMpO1xuXG4gIHNlbGYucHJvY2Vzc2VzLnB1dChhZ2VudCwgJ3N0YXRlJywgS2VybmVsLlNwZWNpYWxGb3Jtcy50dXBsZShyb290Tm9kZSwgbmV3VHJlZSwgcmVuZGVyRm4pKTtcblxuICByZXR1cm4gS2VybmVsLlNwZWNpYWxGb3Jtcy5hdG9tKCdvaycpO1xufTtcblxudmFyIHZpZXcgPSB7XG4gIHN0YXJ0LFxuICBzdG9wLFxuICByZW5kZXJcbn07XG5cbnNlbGYucHJvY2Vzc2VzID0gc2VsZi5wcm9jZXNzZXMgfHwgbmV3IFByb2Nlc3NTeXN0ZW0oKTtcblxuY29uc3QgQ29yZSA9IEM7XG5cbmV4cG9ydCB7IENvcmUsIEtlcm5lbCwgQXRvbSwgRW51bSwgSW50ZWdlciwgTGlzdCwgUmFuZ2UsIFR1cGxlLCBBZ2VudCwgS2V5d29yZCwgYmFzZSBhcyBCYXNlLCBTdHJpbmckMSBhcyBTdHJpbmcsIGJpdHdpc2UgYXMgQml0d2lzZSwgRW51bWVyYWJsZSwgQ29sbGVjdGFibGUsIEluc3BlY3QsIG1hcCBhcyBNYXAsIHNldCBhcyBTZXQsIE1hcFNldCwgVmlydHVhbERPTSwgdmlldyBhcyBWaWV3IH07Il0sImZpbGUiOiJFbGl4aXIuanMiLCJzb3VyY2VSb290IjoiL3NvdXJjZS8ifQ== \ No newline at end of file +//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiIiwic291cmNlcyI6WyJFbGl4aXIuanMiXSwic291cmNlc0NvbnRlbnQiOlsiLyogQGZsb3cgKi9cblxuY2xhc3MgTWFpbGJveCB7XG5cbiAgY29uc3RydWN0b3IoKSB7XG4gICAgdGhpcy5tZXNzYWdlcyA9IFtdO1xuICB9XG5cbiAgZGVsaXZlcihtZXNzYWdlKSB7XG4gICAgdGhpcy5tZXNzYWdlcy5wdXNoKG1lc3NhZ2UpO1xuICAgIHJldHVybiBtZXNzYWdlO1xuICB9XG5cbiAgZ2V0KCkge1xuICAgIHJldHVybiB0aGlzLm1lc3NhZ2VzO1xuICB9XG5cbiAgaXNFbXB0eSgpIHtcbiAgICByZXR1cm4gdGhpcy5tZXNzYWdlcy5sZW5ndGggPT09IDA7XG4gIH1cblxuICByZW1vdmVBdChpbmRleCkge1xuICAgIHRoaXMubWVzc2FnZXMuc3BsaWNlKGluZGV4LCAxKTtcbiAgfVxufVxuXG52YXIgU3RhdGVzID0ge1xuICBOT1JNQUw6IFN5bWJvbC5mb3IoXCJub3JtYWxcIiksXG4gIEtJTEw6IFN5bWJvbC5mb3IoXCJraWxsXCIpLFxuICBTVVNQRU5EOiBTeW1ib2wuZm9yKFwic3VzcGVuZFwiKSxcbiAgQ09OVElOVUU6IFN5bWJvbC5mb3IoXCJjb250aW51ZVwiKSxcbiAgUkVDRUlWRTogU3ltYm9sLmZvcihcInJlY2VpdmVcIiksXG4gIFNFTkQ6IFN5bWJvbC5mb3IoXCJzZW5kXCIpLFxuICBTTEVFUElORzogU3ltYm9sLmZvcihcInNsZWVwaW5nXCIpLFxuICBSVU5OSU5HOiBTeW1ib2wuZm9yKFwicnVubmluZ1wiKSxcbiAgU1VTUEVOREVEOiBTeW1ib2wuZm9yKFwic3VzcGVuZGVkXCIpLFxuICBTVE9QUEVEOiBTeW1ib2wuZm9yKFwic3RvcHBlZFwiKSxcbiAgU0xFRVA6IFN5bWJvbC5mb3IoXCJzbGVlcFwiKSxcbiAgRVhJVDogU3ltYm9sLmZvcihcImV4aXRcIiksXG4gIE5PTUFUQ0g6IFN5bWJvbC5mb3IoXCJub19tYXRjaFwiKVxufTtcblxuY2xhc3MgUHJvY2VzcyB7XG5cbiAgY29uc3RydWN0b3IocGlkLCBtYWlsYm94KSB7XG4gICAgdGhpcy5waWQgPSBwaWQ7XG4gICAgdGhpcy5tYWlsYm94ID0gbWFpbGJveDtcbiAgICB0aGlzLnN0YXR1cyA9IFN0YXRlcy5TVE9QUEVEO1xuICAgIHRoaXMuZGljdCA9IHt9O1xuICB9XG59XG5cbmNsYXNzIFR1cGxlJDEge1xuXG4gIGNvbnN0cnVjdG9yKC4uLmFyZ3MpIHtcbiAgICB0aGlzLnZhbHVlcyA9IE9iamVjdC5mcmVlemUoYXJncyk7XG4gICAgdGhpcy5sZW5ndGggPSB0aGlzLnZhbHVlcy5sZW5ndGg7XG4gIH1cblxuICBnZXQoaW5kZXgpIHtcbiAgICByZXR1cm4gdGhpcy52YWx1ZXNbaW5kZXhdO1xuICB9XG5cbiAgY291bnQoKSB7XG4gICAgcmV0dXJuIHRoaXMudmFsdWVzLmxlbmd0aDtcbiAgfVxuXG4gIFtTeW1ib2wuaXRlcmF0b3JdKCkge1xuICAgIHJldHVybiB0aGlzLnZhbHVlc1tTeW1ib2wuaXRlcmF0b3JdKCk7XG4gIH1cblxuICB0b1N0cmluZygpIHtcbiAgICB2YXIgaSxcbiAgICAgICAgcyA9IFwiXCI7XG4gICAgZm9yIChpID0gMDsgaSA8IHRoaXMudmFsdWVzLmxlbmd0aDsgaSsrKSB7XG4gICAgICBpZiAocyAhPT0gXCJcIikge1xuICAgICAgICBzICs9IFwiLCBcIjtcbiAgICAgIH1cbiAgICAgIHMgKz0gdGhpcy52YWx1ZXNbaV0udG9TdHJpbmcoKTtcbiAgICB9XG5cbiAgICByZXR1cm4gXCJ7XCIgKyBzICsgXCJ9XCI7XG4gIH1cblxufVxuXG5sZXQgcHJvY2Vzc19jb3VudGVyID0gLTE7XG5cbmNsYXNzIFBJRCB7XG4gIGNvbnN0cnVjdG9yKCkge1xuICAgIHByb2Nlc3NfY291bnRlciA9IHByb2Nlc3NfY291bnRlciArIDE7XG4gICAgdGhpcy5pZCA9IHByb2Nlc3NfY291bnRlcjtcbiAgfVxuXG4gIHRvU3RyaW5nKCkge1xuICAgIHJldHVybiBcIlBJRCM8MC5cIiArIHRoaXMuaWQgKyBcIi4wPlwiO1xuICB9XG59XG5cbmNsYXNzIEludGVnZXIkMSB7fVxuY2xhc3MgRmxvYXQge31cblxuY2xhc3MgUHJvY2Vzc1N5c3RlbSB7XG5cbiAgY29uc3RydWN0b3IoKSB7XG4gICAgdGhpcy5waWRzID0gbmV3IE1hcCgpO1xuICAgIHRoaXMubWFpbGJveGVzID0gbmV3IE1hcCgpO1xuICAgIHRoaXMubmFtZXMgPSBuZXcgTWFwKCk7XG4gICAgdGhpcy5saW5rcyA9IG5ldyBNYXAoKTtcblxuICAgIHRoaXMuY3VycmVudF9wcm9jZXNzID0gbnVsbDtcbiAgICB0aGlzLnN1c3BlbmRlZCA9IG5ldyBNYXAoKTtcblxuICAgIHRoaXMubWFpbl9wcm9jZXNzX3BpZCA9IHRoaXMuc3Bhd24oKTtcbiAgICB0aGlzLnNldF9jdXJyZW50KHRoaXMubWFpbl9wcm9jZXNzX3BpZCk7XG4gIH1cblxuICBzcGF3bigpIHtcbiAgICByZXR1cm4gdGhpcy5hZGRfcHJvYyhmYWxzZSkucGlkO1xuICB9XG5cbiAgc3Bhd25fbGluaygpIHtcbiAgICByZXR1cm4gdGhpcy5hZGRfcHJvYyh0cnVlKS5waWQ7XG4gIH1cblxuICBsaW5rKHBpZCkge1xuICAgIHRoaXMubGlua3MuZ2V0KHRoaXMucGlkKCkpLmFkZChwaWQpO1xuICAgIHRoaXMubGlua3MuZ2V0KHBpZCkuYWRkKHRoaXMucGlkKCkpO1xuICB9XG5cbiAgdW5saW5rKHBpZCkge1xuICAgIHRoaXMubGlua3MuZ2V0KHRoaXMucGlkKCkpLmRlbGV0ZShwaWQpO1xuICAgIHRoaXMubGlua3MuZ2V0KHBpZCkuZGVsZXRlKHRoaXMucGlkKCkpO1xuICB9XG5cbiAgc2V0X2N1cnJlbnQoaWQpIHtcbiAgICBsZXQgcGlkID0gdGhpcy5waWRvZihpZCk7XG4gICAgaWYgKHBpZCAhPT0gbnVsbCkge1xuICAgICAgdGhpcy5jdXJyZW50X3Byb2Nlc3MgPSB0aGlzLnBpZHMuZ2V0KHBpZCk7XG4gICAgICB0aGlzLmN1cnJlbnRfcHJvY2Vzcy5zdGF0dXMgPSBTdGF0ZXMuUlVOTklORztcbiAgICB9XG4gIH1cblxuICBhZGRfcHJvYyhsaW5rZWQpIHtcbiAgICBsZXQgbmV3cGlkID0gbmV3IFBJRCgpO1xuICAgIGxldCBtYWlsYm94ID0gbmV3IE1haWxib3goKTtcbiAgICBsZXQgbmV3cHJvYyA9IG5ldyBQcm9jZXNzKG5ld3BpZCwgbWFpbGJveCk7XG5cbiAgICB0aGlzLnBpZHMuc2V0KG5ld3BpZCwgbmV3cHJvYyk7XG4gICAgdGhpcy5tYWlsYm94ZXMuc2V0KG5ld3BpZCwgbWFpbGJveCk7XG4gICAgdGhpcy5saW5rcy5zZXQobmV3cGlkLCBuZXcgU2V0KCkpO1xuXG4gICAgaWYgKGxpbmtlZCkge1xuICAgICAgdGhpcy5saW5rKG5ld3BpZCk7XG4gICAgfVxuXG4gICAgcmV0dXJuIG5ld3Byb2M7XG4gIH1cblxuICByZW1vdmVfcHJvYyhwaWQpIHtcbiAgICB0aGlzLnBpZHMuZGVsZXRlKHBpZCk7XG4gICAgdGhpcy51bnJlZ2lzdGVyKHBpZCk7XG5cbiAgICBpZiAodGhpcy5saW5rcy5oYXMocGlkKSkge1xuICAgICAgZm9yIChsZXQgbGlua3BpZCBvZiB0aGlzLmxpbmtzLmdldChwaWQpKSB7XG4gICAgICAgIHRoaXMubGlua3MuZ2V0KGxpbmtwaWQpLmRlbGV0ZShwaWQpO1xuICAgICAgfVxuXG4gICAgICB0aGlzLmxpbmtzLmRlbGV0ZShwaWQpO1xuICAgIH1cbiAgfVxuXG4gIGV4aXQoaWQpIHtcbiAgICBsZXQgcGlkID0gdGhpcy5waWRvZihpZCk7XG4gICAgdGhpcy5yZW1vdmVfcHJvYyhpZCk7XG4gIH1cblxuICByZWdpc3RlcihuYW1lLCBwaWQpIHtcbiAgICBpZiAoIXRoaXMubmFtZXMuaGFzKG5hbWUpKSB7XG4gICAgICB0aGlzLm5hbWVzLnNldChuYW1lLCBwaWQpO1xuICAgICAgcmV0dXJuIG5hbWU7XG4gICAgfSBlbHNlIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcihcIk5hbWUgaXMgYWxyZWFkeSByZWdpc3RlcmVkIHRvIGFub3RoZXIgcHJvY2Vzc1wiKTtcbiAgICB9XG4gIH1cblxuICByZWdpc3RlcmVkKG5hbWUpIHtcbiAgICByZXR1cm4gdGhpcy5uYW1lcy5oYXMobmFtZSkgPyB0aGlzLm5hbWVzLmdldChuYW1lKSA6IG51bGw7XG4gIH1cblxuICB1bnJlZ2lzdGVyKHBpZCkge1xuICAgIGZvciAobGV0IG5hbWUgb2YgdGhpcy5uYW1lcy5rZXlzKCkpIHtcbiAgICAgIGlmICh0aGlzLm5hbWVzLmhhcyhuYW1lKSAmJiB0aGlzLm5hbWVzLmdldChuYW1lKSA9PT0gcGlkKSB7XG4gICAgICAgIHRoaXMubmFtZXMuZGVsZXRlKG5hbWUpO1xuICAgICAgfVxuICAgIH1cbiAgfVxuXG4gIHBpZCgpIHtcbiAgICByZXR1cm4gdGhpcy5jdXJyZW50X3Byb2Nlc3MucGlkO1xuICB9XG5cbiAgcGlkb2YoaWQpIHtcbiAgICBpZiAoaWQgaW5zdGFuY2VvZiBQSUQpIHtcbiAgICAgIHJldHVybiB0aGlzLnBpZHMuaGFzKGlkKSA/IGlkIDogbnVsbDtcbiAgICB9IGVsc2UgaWYgKGlkIGluc3RhbmNlb2YgUHJvY2Vzcykge1xuICAgICAgcmV0dXJuIGlkLnBpZDtcbiAgICB9IGVsc2Uge1xuICAgICAgbGV0IHBpZCA9IHRoaXMucmVnaXN0ZXJlZChpZCk7XG4gICAgICBpZiAocGlkID09PSBudWxsKSB0aHJvdyBcIlByb2Nlc3MgbmFtZSBub3QgcmVnaXN0ZXJlZDogXCIgKyBpZCArIFwiIChcIiArIHR5cGVvZiBpZCArIFwiKVwiO1xuICAgICAgcmV0dXJuIHBpZDtcbiAgICB9XG4gIH1cblxuICBwdXQoaWQsIGtleSwgdmFsdWUpIHtcbiAgICBsZXQgcGlkID0gdGhpcy5waWRvZihpZCk7XG4gICAgbGV0IHByb2Nlc3MgPSB0aGlzLnBpZHMuZ2V0KHBpZCk7XG4gICAgcHJvY2Vzcy5kaWN0W2tleV0gPSB2YWx1ZTtcbiAgfVxuXG4gIGdldChpZCwga2V5KSB7XG4gICAgbGV0IHBpZCA9IHRoaXMucGlkb2YoaWQpO1xuICAgIGxldCBwcm9jZXNzID0gdGhpcy5waWRzLmdldChwaWQpO1xuXG4gICAgaWYgKGtleSAhPSBudWxsKSB7XG4gICAgICByZXR1cm4gcHJvY2Vzcy5kaWN0W2tleV07XG4gICAgfSBlbHNlIHtcbiAgICAgIHJldHVybiBwcm9jZXNzLmRpY3Q7XG4gICAgfVxuICB9XG5cbiAgZ2V0X2tleXMoaWQpIHtcbiAgICBsZXQgcGlkID0gdGhpcy5waWRvZihpZCk7XG4gICAgbGV0IHByb2Nlc3MgPSB0aGlzLnBpZHMuZ2V0KHBpZCk7XG5cbiAgICByZXR1cm4gT2JqZWN0LmtleXMocHJvY2Vzcy5kaWN0KTtcbiAgfVxuXG4gIGVyYXNlKGlkLCBrZXkpIHtcbiAgICBsZXQgcGlkID0gdGhpcy5waWRvZihpZCk7XG4gICAgbGV0IHByb2Nlc3MgPSB0aGlzLnBpZHMuZ2V0KHBpZCk7XG5cbiAgICBpZiAoa2V5ICE9IG51bGwpIHtcbiAgICAgIGRlbGV0ZSBwcm9jZXNzLmRpY3Rba2V5XTtcbiAgICB9IGVsc2Uge1xuICAgICAgcHJvY2Vzcy5kaWN0ID0ge307XG4gICAgfVxuICB9XG59XG5cbmNsYXNzIEJpdFN0cmluZyB7XG4gIGNvbnN0cnVjdG9yKC4uLmFyZ3MpIHtcbiAgICB0aGlzLnJhd192YWx1ZSA9IGZ1bmN0aW9uICgpIHtcbiAgICAgIHJldHVybiBPYmplY3QuZnJlZXplKGFyZ3MpO1xuICAgIH07XG5cbiAgICB0aGlzLnZhbHVlID0gT2JqZWN0LmZyZWV6ZSh0aGlzLnByb2Nlc3MoYXJncykpO1xuICB9XG5cbiAgZ2V0KGluZGV4KSB7XG4gICAgcmV0dXJuIHRoaXMudmFsdWVbaW5kZXhdO1xuICB9XG5cbiAgY291bnQoKSB7XG4gICAgcmV0dXJuIHRoaXMudmFsdWUubGVuZ3RoO1xuICB9XG5cbiAgW1N5bWJvbC5pdGVyYXRvcl0oKSB7XG4gICAgcmV0dXJuIHRoaXMudmFsdWVbU3ltYm9sLml0ZXJhdG9yXSgpO1xuICB9XG5cbiAgdG9TdHJpbmcoKSB7XG4gICAgdmFyIGksXG4gICAgICAgIHMgPSBcIlwiO1xuICAgIGZvciAoaSA9IDA7IGkgPCB0aGlzLmNvdW50KCk7IGkrKykge1xuICAgICAgaWYgKHMgIT09IFwiXCIpIHtcbiAgICAgICAgcyArPSBcIiwgXCI7XG4gICAgICB9XG4gICAgICBzICs9IHRoaXNbaV0udG9TdHJpbmcoKTtcbiAgICB9XG5cbiAgICByZXR1cm4gXCI8PFwiICsgcyArIFwiPj5cIjtcbiAgfVxuXG4gIHByb2Nlc3MoKSB7XG4gICAgbGV0IHByb2Nlc3NlZF92YWx1ZXMgPSBbXTtcblxuICAgIHZhciBpO1xuICAgIGZvciAoaSA9IDA7IGkgPCB0aGlzLnJhd192YWx1ZSgpLmxlbmd0aDsgaSsrKSB7XG4gICAgICBsZXQgcHJvY2Vzc2VkX3ZhbHVlID0gdGhpc1tcInByb2Nlc3NfXCIgKyB0aGlzLnJhd192YWx1ZSgpW2ldLnR5cGVdKHRoaXMucmF3X3ZhbHVlKClbaV0pO1xuXG4gICAgICBmb3IgKGxldCBhdHRyIG9mIHRoaXMucmF3X3ZhbHVlKClbaV0uYXR0cmlidXRlcykge1xuICAgICAgICBwcm9jZXNzZWRfdmFsdWUgPSB0aGlzW1wicHJvY2Vzc19cIiArIGF0dHJdKHByb2Nlc3NlZF92YWx1ZSk7XG4gICAgICB9XG5cbiAgICAgIHByb2Nlc3NlZF92YWx1ZXMgPSBwcm9jZXNzZWRfdmFsdWVzLmNvbmNhdChwcm9jZXNzZWRfdmFsdWUpO1xuICAgIH1cblxuICAgIHJldHVybiBwcm9jZXNzZWRfdmFsdWVzO1xuICB9XG5cbiAgcHJvY2Vzc19pbnRlZ2VyKHZhbHVlKSB7XG4gICAgcmV0dXJuIHZhbHVlLnZhbHVlO1xuICB9XG5cbiAgcHJvY2Vzc19mbG9hdCh2YWx1ZSkge1xuICAgIGlmICh2YWx1ZS5zaXplID09PSA2NCkge1xuICAgICAgcmV0dXJuIEJpdFN0cmluZy5mbG9hdDY0VG9CeXRlcyh2YWx1ZS52YWx1ZSk7XG4gICAgfSBlbHNlIGlmICh2YWx1ZS5zaXplID09PSAzMikge1xuICAgICAgcmV0dXJuIEJpdFN0cmluZy5mbG9hdDMyVG9CeXRlcyh2YWx1ZS52YWx1ZSk7XG4gICAgfVxuXG4gICAgdGhyb3cgbmV3IEVycm9yKFwiSW52YWxpZCBzaXplIGZvciBmbG9hdFwiKTtcbiAgfVxuXG4gIHByb2Nlc3NfYml0c3RyaW5nKHZhbHVlKSB7XG4gICAgcmV0dXJuIHZhbHVlLnZhbHVlLnZhbHVlO1xuICB9XG5cbiAgcHJvY2Vzc19iaW5hcnkodmFsdWUpIHtcbiAgICByZXR1cm4gQml0U3RyaW5nLnRvVVRGOEFycmF5KHZhbHVlLnZhbHVlKTtcbiAgfVxuXG4gIHByb2Nlc3NfdXRmOCh2YWx1ZSkge1xuICAgIHJldHVybiBCaXRTdHJpbmcudG9VVEY4QXJyYXkodmFsdWUudmFsdWUpO1xuICB9XG5cbiAgcHJvY2Vzc191dGYxNih2YWx1ZSkge1xuICAgIHJldHVybiBCaXRTdHJpbmcudG9VVEYxNkFycmF5KHZhbHVlLnZhbHVlKTtcbiAgfVxuXG4gIHByb2Nlc3NfdXRmMzIodmFsdWUpIHtcbiAgICByZXR1cm4gQml0U3RyaW5nLnRvVVRGMzJBcnJheSh2YWx1ZS52YWx1ZSk7XG4gIH1cblxuICBwcm9jZXNzX3NpZ25lZCh2YWx1ZSkge1xuICAgIHJldHVybiBuZXcgVWludDhBcnJheShbdmFsdWVdKVswXTtcbiAgfVxuXG4gIHByb2Nlc3NfdW5zaWduZWQodmFsdWUpIHtcbiAgICByZXR1cm4gdmFsdWU7XG4gIH1cblxuICBwcm9jZXNzX25hdGl2ZSh2YWx1ZSkge1xuICAgIHJldHVybiB2YWx1ZTtcbiAgfVxuXG4gIHByb2Nlc3NfYmlnKHZhbHVlKSB7XG4gICAgcmV0dXJuIHZhbHVlO1xuICB9XG5cbiAgcHJvY2Vzc19saXR0bGUodmFsdWUpIHtcbiAgICByZXR1cm4gdmFsdWUucmV2ZXJzZSgpO1xuICB9XG5cbiAgcHJvY2Vzc19zaXplKHZhbHVlKSB7XG4gICAgcmV0dXJuIHZhbHVlO1xuICB9XG5cbiAgcHJvY2Vzc191bml0KHZhbHVlKSB7XG4gICAgcmV0dXJuIHZhbHVlO1xuICB9XG5cbiAgc3RhdGljIGludGVnZXIodmFsdWUpIHtcbiAgICByZXR1cm4gQml0U3RyaW5nLndyYXAodmFsdWUsIHsgXCJ0eXBlXCI6IFwiaW50ZWdlclwiLCBcInVuaXRcIjogMSwgXCJzaXplXCI6IDggfSk7XG4gIH1cblxuICBzdGF0aWMgZmxvYXQodmFsdWUpIHtcbiAgICByZXR1cm4gQml0U3RyaW5nLndyYXAodmFsdWUsIHsgXCJ0eXBlXCI6IFwiZmxvYXRcIiwgXCJ1bml0XCI6IDEsIFwic2l6ZVwiOiA2NCB9KTtcbiAgfVxuXG4gIHN0YXRpYyBiaXRzdHJpbmcodmFsdWUpIHtcbiAgICByZXR1cm4gQml0U3RyaW5nLndyYXAodmFsdWUsIHsgXCJ0eXBlXCI6IFwiYml0c3RyaW5nXCIsIFwidW5pdFwiOiAxLCBcInNpemVcIjogdmFsdWUubGVuZ3RoIH0pO1xuICB9XG5cbiAgc3RhdGljIGJpdHModmFsdWUpIHtcbiAgICByZXR1cm4gQml0U3RyaW5nLmJpdHN0cmluZyh2YWx1ZSk7XG4gIH1cblxuICBzdGF0aWMgYmluYXJ5KHZhbHVlKSB7XG4gICAgcmV0dXJuIEJpdFN0cmluZy53cmFwKHZhbHVlLCB7IFwidHlwZVwiOiBcImJpbmFyeVwiLCBcInVuaXRcIjogOCwgXCJzaXplXCI6IHZhbHVlLmxlbmd0aCB9KTtcbiAgfVxuXG4gIHN0YXRpYyBieXRlcyh2YWx1ZSkge1xuICAgIHJldHVybiBCaXRTdHJpbmcuYmluYXJ5KHZhbHVlKTtcbiAgfVxuXG4gIHN0YXRpYyB1dGY4KHZhbHVlKSB7XG4gICAgcmV0dXJuIEJpdFN0cmluZy53cmFwKHZhbHVlLCB7IFwidHlwZVwiOiBcInV0ZjhcIiB9KTtcbiAgfVxuXG4gIHN0YXRpYyB1dGYxNih2YWx1ZSkge1xuICAgIHJldHVybiBCaXRTdHJpbmcud3JhcCh2YWx1ZSwgeyBcInR5cGVcIjogXCJ1dGYxNlwiIH0pO1xuICB9XG5cbiAgc3RhdGljIHV0ZjMyKHZhbHVlKSB7XG4gICAgcmV0dXJuIEJpdFN0cmluZy53cmFwKHZhbHVlLCB7IFwidHlwZVwiOiBcInV0ZjMyXCIgfSk7XG4gIH1cblxuICBzdGF0aWMgc2lnbmVkKHZhbHVlKSB7XG4gICAgcmV0dXJuIEJpdFN0cmluZy53cmFwKHZhbHVlLCB7fSwgXCJzaWduZWRcIik7XG4gIH1cblxuICBzdGF0aWMgdW5zaWduZWQodmFsdWUpIHtcbiAgICByZXR1cm4gQml0U3RyaW5nLndyYXAodmFsdWUsIHt9LCBcInVuc2lnbmVkXCIpO1xuICB9XG5cbiAgc3RhdGljIG5hdGl2ZSh2YWx1ZSkge1xuICAgIHJldHVybiBCaXRTdHJpbmcud3JhcCh2YWx1ZSwge30sIFwibmF0aXZlXCIpO1xuICB9XG5cbiAgc3RhdGljIGJpZyh2YWx1ZSkge1xuICAgIHJldHVybiBCaXRTdHJpbmcud3JhcCh2YWx1ZSwge30sIFwiYmlnXCIpO1xuICB9XG5cbiAgc3RhdGljIGxpdHRsZSh2YWx1ZSkge1xuICAgIHJldHVybiBCaXRTdHJpbmcud3JhcCh2YWx1ZSwge30sIFwibGl0dGxlXCIpO1xuICB9XG5cbiAgc3RhdGljIHNpemUodmFsdWUsIGNvdW50KSB7XG4gICAgcmV0dXJuIEJpdFN0cmluZy53cmFwKHZhbHVlLCB7IFwic2l6ZVwiOiBjb3VudCB9KTtcbiAgfVxuXG4gIHN0YXRpYyB1bml0KHZhbHVlLCBjb3VudCkge1xuICAgIHJldHVybiBCaXRTdHJpbmcud3JhcCh2YWx1ZSwgeyBcInVuaXRcIjogY291bnQgfSk7XG4gIH1cblxuICBzdGF0aWMgd3JhcCh2YWx1ZSwgb3B0LCBuZXdfYXR0cmlidXRlID0gbnVsbCkge1xuICAgIGxldCB0aGVfdmFsdWUgPSB2YWx1ZTtcblxuICAgIGlmICghKHZhbHVlIGluc3RhbmNlb2YgT2JqZWN0KSkge1xuICAgICAgdGhlX3ZhbHVlID0geyBcInZhbHVlXCI6IHZhbHVlLCBcImF0dHJpYnV0ZXNcIjogW10gfTtcbiAgICB9XG5cbiAgICB0aGVfdmFsdWUgPSBPYmplY3QuYXNzaWduKHRoZV92YWx1ZSwgb3B0KTtcblxuICAgIGlmIChuZXdfYXR0cmlidXRlKSB7XG4gICAgICB0aGVfdmFsdWUuYXR0cmlidXRlcy5wdXNoKG5ld19hdHRyaWJ1dGUpO1xuICAgIH1cblxuICAgIHJldHVybiB0aGVfdmFsdWU7XG4gIH1cblxuICBzdGF0aWMgdG9VVEY4QXJyYXkoc3RyKSB7XG4gICAgdmFyIHV0ZjggPSBbXTtcbiAgICBmb3IgKHZhciBpID0gMDsgaSA8IHN0ci5sZW5ndGg7IGkrKykge1xuICAgICAgdmFyIGNoYXJjb2RlID0gc3RyLmNoYXJDb2RlQXQoaSk7XG4gICAgICBpZiAoY2hhcmNvZGUgPCAxMjgpIHtcbiAgICAgICAgdXRmOC5wdXNoKGNoYXJjb2RlKTtcbiAgICAgIH0gZWxzZSBpZiAoY2hhcmNvZGUgPCAyMDQ4KSB7XG4gICAgICAgIHV0ZjgucHVzaCgxOTIgfCBjaGFyY29kZSA+PiA2LCAxMjggfCBjaGFyY29kZSAmIDYzKTtcbiAgICAgIH0gZWxzZSBpZiAoY2hhcmNvZGUgPCA1NTI5NiB8fCBjaGFyY29kZSA+PSA1NzM0NCkge1xuICAgICAgICB1dGY4LnB1c2goMjI0IHwgY2hhcmNvZGUgPj4gMTIsIDEyOCB8IGNoYXJjb2RlID4+IDYgJiA2MywgMTI4IHwgY2hhcmNvZGUgJiA2Myk7XG4gICAgICB9XG4gICAgICAvLyBzdXJyb2dhdGUgcGFpclxuICAgICAgZWxzZSB7XG4gICAgICAgIGkrKztcbiAgICAgICAgLy8gVVRGLTE2IGVuY29kZXMgMHgxMDAwMC0weDEwRkZGRiBieVxuICAgICAgICAvLyBzdWJ0cmFjdGluZyAweDEwMDAwIGFuZCBzcGxpdHRpbmcgdGhlXG4gICAgICAgIC8vIDIwIGJpdHMgb2YgMHgwLTB4RkZGRkYgaW50byB0d28gaGFsdmVzXG4gICAgICAgIGNoYXJjb2RlID0gNjU1MzYgKyAoKGNoYXJjb2RlICYgMTAyMykgPDwgMTAgfCBzdHIuY2hhckNvZGVBdChpKSAmIDEwMjMpO1xuICAgICAgICB1dGY4LnB1c2goMjQwIHwgY2hhcmNvZGUgPj4gMTgsIDEyOCB8IGNoYXJjb2RlID4+IDEyICYgNjMsIDEyOCB8IGNoYXJjb2RlID4+IDYgJiA2MywgMTI4IHwgY2hhcmNvZGUgJiA2Myk7XG4gICAgICB9XG4gICAgfVxuICAgIHJldHVybiB1dGY4O1xuICB9XG5cbiAgc3RhdGljIHRvVVRGMTZBcnJheShzdHIpIHtcbiAgICB2YXIgdXRmMTYgPSBbXTtcbiAgICBmb3IgKHZhciBpID0gMDsgaSA8IHN0ci5sZW5ndGg7IGkrKykge1xuICAgICAgdmFyIGNvZGVQb2ludCA9IHN0ci5jb2RlUG9pbnRBdChpKTtcblxuICAgICAgaWYgKGNvZGVQb2ludCA8PSAyNTUpIHtcbiAgICAgICAgdXRmMTYucHVzaCgwKTtcbiAgICAgICAgdXRmMTYucHVzaChjb2RlUG9pbnQpO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgdXRmMTYucHVzaChjb2RlUG9pbnQgPj4gOCAmIDI1NSk7XG4gICAgICAgIHV0ZjE2LnB1c2goY29kZVBvaW50ICYgMjU1KTtcbiAgICAgIH1cbiAgICB9XG4gICAgcmV0dXJuIHV0ZjE2O1xuICB9XG5cbiAgc3RhdGljIHRvVVRGMzJBcnJheShzdHIpIHtcbiAgICB2YXIgdXRmMzIgPSBbXTtcbiAgICBmb3IgKHZhciBpID0gMDsgaSA8IHN0ci5sZW5ndGg7IGkrKykge1xuICAgICAgdmFyIGNvZGVQb2ludCA9IHN0ci5jb2RlUG9pbnRBdChpKTtcblxuICAgICAgaWYgKGNvZGVQb2ludCA8PSAyNTUpIHtcbiAgICAgICAgdXRmMzIucHVzaCgwKTtcbiAgICAgICAgdXRmMzIucHVzaCgwKTtcbiAgICAgICAgdXRmMzIucHVzaCgwKTtcbiAgICAgICAgdXRmMzIucHVzaChjb2RlUG9pbnQpO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgdXRmMzIucHVzaCgwKTtcbiAgICAgICAgdXRmMzIucHVzaCgwKTtcbiAgICAgICAgdXRmMzIucHVzaChjb2RlUG9pbnQgPj4gOCAmIDI1NSk7XG4gICAgICAgIHV0ZjMyLnB1c2goY29kZVBvaW50ICYgMjU1KTtcbiAgICAgIH1cbiAgICB9XG4gICAgcmV0dXJuIHV0ZjMyO1xuICB9XG5cbiAgLy9odHRwOi8vc3RhY2tvdmVyZmxvdy5jb20vcXVlc3Rpb25zLzIwMDM0OTMvamF2YXNjcmlwdC1mbG9hdC1mcm9tLXRvLWJpdHNcbiAgc3RhdGljIGZsb2F0MzJUb0J5dGVzKGYpIHtcbiAgICB2YXIgYnl0ZXMgPSBbXTtcblxuICAgIHZhciBidWYgPSBuZXcgQXJyYXlCdWZmZXIoNCk7XG4gICAgbmV3IEZsb2F0MzJBcnJheShidWYpWzBdID0gZjtcblxuICAgIGxldCBpbnRWZXJzaW9uID0gbmV3IFVpbnQzMkFycmF5KGJ1ZilbMF07XG5cbiAgICBieXRlcy5wdXNoKGludFZlcnNpb24gPj4gMjQgJiAyNTUpO1xuICAgIGJ5dGVzLnB1c2goaW50VmVyc2lvbiA+PiAxNiAmIDI1NSk7XG4gICAgYnl0ZXMucHVzaChpbnRWZXJzaW9uID4+IDggJiAyNTUpO1xuICAgIGJ5dGVzLnB1c2goaW50VmVyc2lvbiAmIDI1NSk7XG5cbiAgICByZXR1cm4gYnl0ZXM7XG4gIH1cblxuICBzdGF0aWMgZmxvYXQ2NFRvQnl0ZXMoZikge1xuICAgIHZhciBieXRlcyA9IFtdO1xuXG4gICAgdmFyIGJ1ZiA9IG5ldyBBcnJheUJ1ZmZlcig4KTtcbiAgICBuZXcgRmxvYXQ2NEFycmF5KGJ1ZilbMF0gPSBmO1xuXG4gICAgdmFyIGludFZlcnNpb24xID0gbmV3IFVpbnQzMkFycmF5KGJ1ZilbMF07XG4gICAgdmFyIGludFZlcnNpb24yID0gbmV3IFVpbnQzMkFycmF5KGJ1ZilbMV07XG5cbiAgICBieXRlcy5wdXNoKGludFZlcnNpb24yID4+IDI0ICYgMjU1KTtcbiAgICBieXRlcy5wdXNoKGludFZlcnNpb24yID4+IDE2ICYgMjU1KTtcbiAgICBieXRlcy5wdXNoKGludFZlcnNpb24yID4+IDggJiAyNTUpO1xuICAgIGJ5dGVzLnB1c2goaW50VmVyc2lvbjIgJiAyNTUpO1xuXG4gICAgYnl0ZXMucHVzaChpbnRWZXJzaW9uMSA+PiAyNCAmIDI1NSk7XG4gICAgYnl0ZXMucHVzaChpbnRWZXJzaW9uMSA+PiAxNiAmIDI1NSk7XG4gICAgYnl0ZXMucHVzaChpbnRWZXJzaW9uMSA+PiA4ICYgMjU1KTtcbiAgICBieXRlcy5wdXNoKGludFZlcnNpb24xICYgMjU1KTtcblxuICAgIHJldHVybiBieXRlcztcbiAgfVxufVxuXG4vKiBAZmxvdyAqL1xuXG5jbGFzcyBWYXJpYWJsZSB7XG5cbiAgY29uc3RydWN0b3IobmFtZSA9IG51bGwpIHtcbiAgICB0aGlzLm5hbWUgPSBuYW1lO1xuICB9XG59XG5cbmNsYXNzIFdpbGRjYXJkIHtcbiAgY29uc3RydWN0b3IoKSB7fVxufVxuXG5jbGFzcyBTdGFydHNXaXRoIHtcblxuICBjb25zdHJ1Y3RvcihwcmVmaXgpIHtcbiAgICB0aGlzLnByZWZpeCA9IHByZWZpeDtcbiAgfVxufVxuXG5jbGFzcyBDYXB0dXJlIHtcblxuICBjb25zdHJ1Y3Rvcih2YWx1ZSkge1xuICAgIHRoaXMudmFsdWUgPSB2YWx1ZTtcbiAgfVxufVxuXG5jbGFzcyBIZWFkVGFpbCB7XG4gIGNvbnN0cnVjdG9yKCkge31cbn1cblxuY2xhc3MgVHlwZSB7XG5cbiAgY29uc3RydWN0b3IodHlwZSwgb2JqUGF0dGVybiA9IHt9KSB7XG4gICAgdGhpcy50eXBlID0gdHlwZTtcbiAgICB0aGlzLm9ialBhdHRlcm4gPSBvYmpQYXR0ZXJuO1xuICB9XG59XG5cbmNsYXNzIEJvdW5kIHtcblxuICBjb25zdHJ1Y3Rvcih2YWx1ZSkge1xuICAgIHRoaXMudmFsdWUgPSB2YWx1ZTtcbiAgfVxufVxuXG5mdW5jdGlvbiB2YXJpYWJsZShuYW1lID0gbnVsbCkge1xuICByZXR1cm4gbmV3IFZhcmlhYmxlKG5hbWUpO1xufVxuXG5mdW5jdGlvbiB3aWxkY2FyZCgpIHtcbiAgcmV0dXJuIG5ldyBXaWxkY2FyZCgpO1xufVxuXG5mdW5jdGlvbiBzdGFydHNXaXRoKHByZWZpeCkge1xuICByZXR1cm4gbmV3IFN0YXJ0c1dpdGgocHJlZml4KTtcbn1cblxuZnVuY3Rpb24gY2FwdHVyZSh2YWx1ZSkge1xuICByZXR1cm4gbmV3IENhcHR1cmUodmFsdWUpO1xufVxuXG5mdW5jdGlvbiBoZWFkVGFpbCgpIHtcbiAgcmV0dXJuIG5ldyBIZWFkVGFpbCgpO1xufVxuXG5mdW5jdGlvbiB0eXBlKHR5cGUsIG9ialBhdHRlcm4gPSB7fSkge1xuICByZXR1cm4gbmV3IFR5cGUodHlwZSwgb2JqUGF0dGVybik7XG59XG5cbmZ1bmN0aW9uIGJvdW5kKHZhbHVlKSB7XG4gIHJldHVybiBuZXcgQm91bmQodmFsdWUpO1xufVxuXG5mdW5jdGlvbiBpc19udW1iZXIkMih2YWx1ZSkge1xuICByZXR1cm4gdHlwZW9mIHZhbHVlID09PSAnbnVtYmVyJztcbn1cblxuZnVuY3Rpb24gaXNfc3RyaW5nKHZhbHVlKSB7XG4gIHJldHVybiB0eXBlb2YgdmFsdWUgPT09ICdzdHJpbmcnO1xufVxuXG5mdW5jdGlvbiBpc19ib29sZWFuJDIodmFsdWUpIHtcbiAgcmV0dXJuIHR5cGVvZiB2YWx1ZSA9PT0gJ2Jvb2xlYW4nO1xufVxuXG5mdW5jdGlvbiBpc19zeW1ib2wodmFsdWUpIHtcbiAgcmV0dXJuIHR5cGVvZiB2YWx1ZSA9PT0gJ3N5bWJvbCc7XG59XG5cbmZ1bmN0aW9uIGlzX251bGwodmFsdWUpIHtcbiAgcmV0dXJuIHZhbHVlID09PSBudWxsO1xufVxuXG5mdW5jdGlvbiBpc191bmRlZmluZWQodmFsdWUpIHtcbiAgcmV0dXJuIHR5cGVvZiB2YWx1ZSA9PT0gJ3VuZGVmaW5lZCc7XG59XG5cbmZ1bmN0aW9uIGlzX2Z1bmN0aW9uJDIodmFsdWUpIHtcbiAgcmV0dXJuIE9iamVjdC5wcm90b3R5cGUudG9TdHJpbmcuY2FsbCh2YWx1ZSkgPT0gJ1tvYmplY3QgRnVuY3Rpb25dJztcbn1cblxuZnVuY3Rpb24gaXNfdmFyaWFibGUodmFsdWUpIHtcbiAgcmV0dXJuIHZhbHVlIGluc3RhbmNlb2YgVmFyaWFibGU7XG59XG5cbmZ1bmN0aW9uIGlzX3dpbGRjYXJkKHZhbHVlKSB7XG4gIHJldHVybiB2YWx1ZSBpbnN0YW5jZW9mIFdpbGRjYXJkO1xufVxuXG5mdW5jdGlvbiBpc19oZWFkVGFpbCh2YWx1ZSkge1xuICByZXR1cm4gdmFsdWUgaW5zdGFuY2VvZiBIZWFkVGFpbDtcbn1cblxuZnVuY3Rpb24gaXNfY2FwdHVyZSh2YWx1ZSkge1xuICByZXR1cm4gdmFsdWUgaW5zdGFuY2VvZiBDYXB0dXJlO1xufVxuXG5mdW5jdGlvbiBpc190eXBlKHZhbHVlKSB7XG4gIHJldHVybiB2YWx1ZSBpbnN0YW5jZW9mIFR5cGU7XG59XG5cbmZ1bmN0aW9uIGlzX3N0YXJ0c1dpdGgodmFsdWUpIHtcbiAgcmV0dXJuIHZhbHVlIGluc3RhbmNlb2YgU3RhcnRzV2l0aDtcbn1cblxuZnVuY3Rpb24gaXNfYm91bmQodmFsdWUpIHtcbiAgcmV0dXJuIHZhbHVlIGluc3RhbmNlb2YgQm91bmQ7XG59XG5cbmZ1bmN0aW9uIGlzX29iamVjdCh2YWx1ZSkge1xuICByZXR1cm4gdHlwZW9mIHZhbHVlID09PSAnb2JqZWN0Jztcbn1cblxuZnVuY3Rpb24gaXNfYXJyYXkodmFsdWUpIHtcbiAgcmV0dXJuIEFycmF5LmlzQXJyYXkodmFsdWUpO1xufVxuXG52YXIgQ2hlY2tzID0ge1xuICBpc19udW1iZXI6IGlzX251bWJlciQyLFxuICBpc19zdHJpbmcsXG4gIGlzX2Jvb2xlYW46IGlzX2Jvb2xlYW4kMixcbiAgaXNfc3ltYm9sLFxuICBpc19udWxsLFxuICBpc191bmRlZmluZWQsXG4gIGlzX2Z1bmN0aW9uOiBpc19mdW5jdGlvbiQyLFxuICBpc192YXJpYWJsZSxcbiAgaXNfd2lsZGNhcmQsXG4gIGlzX2hlYWRUYWlsLFxuICBpc19jYXB0dXJlLFxuICBpc190eXBlLFxuICBpc19zdGFydHNXaXRoLFxuICBpc19ib3VuZCxcbiAgaXNfb2JqZWN0LFxuICBpc19hcnJheVxufTtcblxuZnVuY3Rpb24gcmVzb2x2ZVN5bWJvbChwYXR0ZXJuKSB7XG4gIHJldHVybiBmdW5jdGlvbiAodmFsdWUpIHtcbiAgICByZXR1cm4gQ2hlY2tzLmlzX3N5bWJvbCh2YWx1ZSkgJiYgdmFsdWUgPT09IHBhdHRlcm47XG4gIH07XG59XG5cbmZ1bmN0aW9uIHJlc29sdmVTdHJpbmcocGF0dGVybikge1xuICByZXR1cm4gZnVuY3Rpb24gKHZhbHVlKSB7XG4gICAgcmV0dXJuIENoZWNrcy5pc19zdHJpbmcodmFsdWUpICYmIHZhbHVlID09PSBwYXR0ZXJuO1xuICB9O1xufVxuXG5mdW5jdGlvbiByZXNvbHZlTnVtYmVyKHBhdHRlcm4pIHtcbiAgcmV0dXJuIGZ1bmN0aW9uICh2YWx1ZSkge1xuICAgIHJldHVybiBDaGVja3MuaXNfbnVtYmVyKHZhbHVlKSAmJiB2YWx1ZSA9PT0gcGF0dGVybjtcbiAgfTtcbn1cblxuZnVuY3Rpb24gcmVzb2x2ZUJvb2xlYW4ocGF0dGVybikge1xuICByZXR1cm4gZnVuY3Rpb24gKHZhbHVlKSB7XG4gICAgcmV0dXJuIENoZWNrcy5pc19ib29sZWFuKHZhbHVlKSAmJiB2YWx1ZSA9PT0gcGF0dGVybjtcbiAgfTtcbn1cblxuZnVuY3Rpb24gcmVzb2x2ZUZ1bmN0aW9uKHBhdHRlcm4pIHtcbiAgcmV0dXJuIGZ1bmN0aW9uICh2YWx1ZSkge1xuICAgIHJldHVybiBDaGVja3MuaXNfZnVuY3Rpb24odmFsdWUpICYmIHZhbHVlID09PSBwYXR0ZXJuO1xuICB9O1xufVxuXG5mdW5jdGlvbiByZXNvbHZlTnVsbChwYXR0ZXJuKSB7XG4gIHJldHVybiBmdW5jdGlvbiAodmFsdWUpIHtcbiAgICByZXR1cm4gQ2hlY2tzLmlzX251bGwodmFsdWUpO1xuICB9O1xufVxuXG5mdW5jdGlvbiByZXNvbHZlQm91bmQocGF0dGVybikge1xuICByZXR1cm4gZnVuY3Rpb24gKHZhbHVlLCBhcmdzKSB7XG4gICAgaWYgKHR5cGVvZiB2YWx1ZSA9PT0gdHlwZW9mIHBhdHRlcm4udmFsdWUgJiYgdmFsdWUgPT09IHBhdHRlcm4udmFsdWUpIHtcbiAgICAgIGFyZ3MucHVzaCh2YWx1ZSk7XG4gICAgICByZXR1cm4gdHJ1ZTtcbiAgICB9XG5cbiAgICByZXR1cm4gZmFsc2U7XG4gIH07XG59XG5cbmZ1bmN0aW9uIHJlc29sdmVXaWxkY2FyZCgpIHtcbiAgcmV0dXJuIGZ1bmN0aW9uICgpIHtcbiAgICByZXR1cm4gdHJ1ZTtcbiAgfTtcbn1cblxuZnVuY3Rpb24gcmVzb2x2ZVZhcmlhYmxlKCkge1xuICByZXR1cm4gZnVuY3Rpb24gKHZhbHVlLCBhcmdzKSB7XG4gICAgYXJncy5wdXNoKHZhbHVlKTtcbiAgICByZXR1cm4gdHJ1ZTtcbiAgfTtcbn1cblxuZnVuY3Rpb24gcmVzb2x2ZUhlYWRUYWlsKCkge1xuICByZXR1cm4gZnVuY3Rpb24gKHZhbHVlLCBhcmdzKSB7XG4gICAgaWYgKCFDaGVja3MuaXNfYXJyYXkodmFsdWUpIHx8IHZhbHVlLmxlbmd0aCA8IDIpIHtcbiAgICAgIHJldHVybiBmYWxzZTtcbiAgICB9XG5cbiAgICBjb25zdCBoZWFkID0gdmFsdWVbMF07XG4gICAgY29uc3QgdGFpbCA9IHZhbHVlLnNsaWNlKDEpO1xuXG4gICAgYXJncy5wdXNoKGhlYWQpO1xuICAgIGFyZ3MucHVzaCh0YWlsKTtcblxuICAgIHJldHVybiB0cnVlO1xuICB9O1xufVxuXG5mdW5jdGlvbiByZXNvbHZlQ2FwdHVyZShwYXR0ZXJuKSB7XG4gIGNvbnN0IG1hdGNoZXMgPSBidWlsZE1hdGNoKHBhdHRlcm4udmFsdWUpO1xuXG4gIHJldHVybiBmdW5jdGlvbiAodmFsdWUsIGFyZ3MpIHtcbiAgICBpZiAobWF0Y2hlcyh2YWx1ZSwgYXJncykpIHtcbiAgICAgIGFyZ3MucHVzaCh2YWx1ZSk7XG4gICAgICByZXR1cm4gdHJ1ZTtcbiAgICB9XG5cbiAgICByZXR1cm4gZmFsc2U7XG4gIH07XG59XG5cbmZ1bmN0aW9uIHJlc29sdmVTdGFydHNXaXRoKHBhdHRlcm4pIHtcbiAgY29uc3QgcHJlZml4ID0gcGF0dGVybi5wcmVmaXg7XG5cbiAgcmV0dXJuIGZ1bmN0aW9uICh2YWx1ZSwgYXJncykge1xuICAgIGlmIChDaGVja3MuaXNfc3RyaW5nKHZhbHVlKSAmJiB2YWx1ZS5zdGFydHNXaXRoKHByZWZpeCkpIHtcbiAgICAgIGFyZ3MucHVzaCh2YWx1ZS5zdWJzdHJpbmcocHJlZml4Lmxlbmd0aCkpO1xuICAgICAgcmV0dXJuIHRydWU7XG4gICAgfVxuXG4gICAgcmV0dXJuIGZhbHNlO1xuICB9O1xufVxuXG5mdW5jdGlvbiByZXNvbHZlVHlwZShwYXR0ZXJuKSB7XG4gIHJldHVybiBmdW5jdGlvbiAodmFsdWUsIGFyZ3MpIHtcbiAgICBpZiAodmFsdWUgaW5zdGFuY2VvZiBwYXR0ZXJuLnR5cGUpIHtcbiAgICAgIGNvbnN0IG1hdGNoZXMgPSBidWlsZE1hdGNoKHBhdHRlcm4ub2JqUGF0dGVybik7XG4gICAgICByZXR1cm4gbWF0Y2hlcyh2YWx1ZSwgYXJncykgJiYgYXJncy5wdXNoKHZhbHVlKSA+IDA7XG4gICAgfVxuXG4gICAgcmV0dXJuIGZhbHNlO1xuICB9O1xufVxuXG5mdW5jdGlvbiByZXNvbHZlQXJyYXkocGF0dGVybikge1xuICBjb25zdCBtYXRjaGVzID0gcGF0dGVybi5tYXAoeCA9PiBidWlsZE1hdGNoKHgpKTtcblxuICByZXR1cm4gZnVuY3Rpb24gKHZhbHVlLCBhcmdzKSB7XG4gICAgaWYgKCFDaGVja3MuaXNfYXJyYXkodmFsdWUpIHx8IHZhbHVlLmxlbmd0aCAhPSBwYXR0ZXJuLmxlbmd0aCkge1xuICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH1cblxuICAgIHJldHVybiB2YWx1ZS5ldmVyeShmdW5jdGlvbiAodiwgaSkge1xuICAgICAgcmV0dXJuIG1hdGNoZXNbaV0odmFsdWVbaV0sIGFyZ3MpO1xuICAgIH0pO1xuICB9O1xufVxuXG5mdW5jdGlvbiByZXNvbHZlT2JqZWN0KHBhdHRlcm4pIHtcbiAgbGV0IG1hdGNoZXMgPSB7fTtcblxuICBmb3IgKGxldCBrZXkgb2YgT2JqZWN0LmtleXMocGF0dGVybikuY29uY2F0KE9iamVjdC5nZXRPd25Qcm9wZXJ0eVN5bWJvbHMocGF0dGVybikpKSB7XG4gICAgbWF0Y2hlc1trZXldID0gYnVpbGRNYXRjaChwYXR0ZXJuW2tleV0pO1xuICB9XG5cbiAgcmV0dXJuIGZ1bmN0aW9uICh2YWx1ZSwgYXJncykge1xuICAgIGlmICghQ2hlY2tzLmlzX29iamVjdCh2YWx1ZSkgfHwgcGF0dGVybi5sZW5ndGggPiB2YWx1ZS5sZW5ndGgpIHtcbiAgICAgIHJldHVybiBmYWxzZTtcbiAgICB9XG5cbiAgICBmb3IgKGxldCBrZXkgb2YgT2JqZWN0LmtleXMocGF0dGVybikuY29uY2F0KE9iamVjdC5nZXRPd25Qcm9wZXJ0eVN5bWJvbHMocGF0dGVybikpKSB7XG4gICAgICBpZiAoIShrZXkgaW4gdmFsdWUpIHx8ICFtYXRjaGVzW2tleV0odmFsdWVba2V5XSwgYXJncykpIHtcbiAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgfVxuICAgIH1cblxuICAgIHJldHVybiB0cnVlO1xuICB9O1xufVxuXG5mdW5jdGlvbiByZXNvbHZlTm9NYXRjaCgpIHtcbiAgcmV0dXJuIGZ1bmN0aW9uICgpIHtcbiAgICByZXR1cm4gZmFsc2U7XG4gIH07XG59XG5cbnZhciBSZXNvbHZlcnMgPSB7XG4gIHJlc29sdmVCb3VuZCxcbiAgcmVzb2x2ZVdpbGRjYXJkLFxuICByZXNvbHZlVmFyaWFibGUsXG4gIHJlc29sdmVIZWFkVGFpbCxcbiAgcmVzb2x2ZUNhcHR1cmUsXG4gIHJlc29sdmVTdGFydHNXaXRoLFxuICByZXNvbHZlVHlwZSxcbiAgcmVzb2x2ZUFycmF5LFxuICByZXNvbHZlT2JqZWN0LFxuICByZXNvbHZlTm9NYXRjaCxcbiAgcmVzb2x2ZVN5bWJvbCxcbiAgcmVzb2x2ZVN0cmluZyxcbiAgcmVzb2x2ZU51bWJlcixcbiAgcmVzb2x2ZUJvb2xlYW4sXG4gIHJlc29sdmVGdW5jdGlvbixcbiAgcmVzb2x2ZU51bGxcbn07XG5cbmZ1bmN0aW9uIGJ1aWxkTWF0Y2gocGF0dGVybikge1xuXG4gIGlmIChDaGVja3MuaXNfdmFyaWFibGUocGF0dGVybikpIHtcbiAgICByZXR1cm4gUmVzb2x2ZXJzLnJlc29sdmVWYXJpYWJsZShwYXR0ZXJuKTtcbiAgfVxuXG4gIGlmIChDaGVja3MuaXNfd2lsZGNhcmQocGF0dGVybikpIHtcbiAgICByZXR1cm4gUmVzb2x2ZXJzLnJlc29sdmVXaWxkY2FyZChwYXR0ZXJuKTtcbiAgfVxuXG4gIGlmIChDaGVja3MuaXNfdW5kZWZpbmVkKHBhdHRlcm4pKSB7XG4gICAgcmV0dXJuIFJlc29sdmVycy5yZXNvbHZlV2lsZGNhcmQocGF0dGVybik7XG4gIH1cblxuICBpZiAoQ2hlY2tzLmlzX2hlYWRUYWlsKHBhdHRlcm4pKSB7XG4gICAgcmV0dXJuIFJlc29sdmVycy5yZXNvbHZlSGVhZFRhaWwocGF0dGVybik7XG4gIH1cblxuICBpZiAoQ2hlY2tzLmlzX3N0YXJ0c1dpdGgocGF0dGVybikpIHtcbiAgICByZXR1cm4gUmVzb2x2ZXJzLnJlc29sdmVTdGFydHNXaXRoKHBhdHRlcm4pO1xuICB9XG5cbiAgaWYgKENoZWNrcy5pc19jYXB0dXJlKHBhdHRlcm4pKSB7XG4gICAgcmV0dXJuIFJlc29sdmVycy5yZXNvbHZlQ2FwdHVyZShwYXR0ZXJuKTtcbiAgfVxuXG4gIGlmIChDaGVja3MuaXNfYm91bmQocGF0dGVybikpIHtcbiAgICByZXR1cm4gUmVzb2x2ZXJzLnJlc29sdmVCb3VuZChwYXR0ZXJuKTtcbiAgfVxuXG4gIGlmIChDaGVja3MuaXNfdHlwZShwYXR0ZXJuKSkge1xuICAgIHJldHVybiBSZXNvbHZlcnMucmVzb2x2ZVR5cGUocGF0dGVybik7XG4gIH1cblxuICBpZiAoQ2hlY2tzLmlzX2FycmF5KHBhdHRlcm4pKSB7XG4gICAgcmV0dXJuIFJlc29sdmVycy5yZXNvbHZlQXJyYXkocGF0dGVybik7XG4gIH1cblxuICBpZiAoQ2hlY2tzLmlzX251bWJlcihwYXR0ZXJuKSkge1xuICAgIHJldHVybiBSZXNvbHZlcnMucmVzb2x2ZU51bWJlcihwYXR0ZXJuKTtcbiAgfVxuXG4gIGlmIChDaGVja3MuaXNfc3RyaW5nKHBhdHRlcm4pKSB7XG4gICAgcmV0dXJuIFJlc29sdmVycy5yZXNvbHZlU3RyaW5nKHBhdHRlcm4pO1xuICB9XG5cbiAgaWYgKENoZWNrcy5pc19ib29sZWFuKHBhdHRlcm4pKSB7XG4gICAgcmV0dXJuIFJlc29sdmVycy5yZXNvbHZlQm9vbGVhbihwYXR0ZXJuKTtcbiAgfVxuXG4gIGlmIChDaGVja3MuaXNfc3ltYm9sKHBhdHRlcm4pKSB7XG4gICAgcmV0dXJuIFJlc29sdmVycy5yZXNvbHZlU3ltYm9sKHBhdHRlcm4pO1xuICB9XG5cbiAgaWYgKENoZWNrcy5pc19udWxsKHBhdHRlcm4pKSB7XG4gICAgcmV0dXJuIFJlc29sdmVycy5yZXNvbHZlTnVsbChwYXR0ZXJuKTtcbiAgfVxuXG4gIGlmIChDaGVja3MuaXNfb2JqZWN0KHBhdHRlcm4pKSB7XG4gICAgcmV0dXJuIFJlc29sdmVycy5yZXNvbHZlT2JqZWN0KHBhdHRlcm4pO1xuICB9XG5cbiAgcmV0dXJuIFJlc29sdmVycy5yZXNvbHZlTm9NYXRjaCgpO1xufVxuXG5jbGFzcyBNYXRjaEVycm9yIGV4dGVuZHMgRXJyb3Ige1xuICBjb25zdHJ1Y3RvcihhcmcpIHtcbiAgICBzdXBlcigpO1xuXG4gICAgaWYgKHR5cGVvZiBhcmcgPT09ICdzeW1ib2wnKSB7XG4gICAgICB0aGlzLm1lc3NhZ2UgPSAnTm8gbWF0Y2ggZm9yOiAnICsgYXJnLnRvU3RyaW5nKCk7XG4gICAgfSBlbHNlIGlmIChBcnJheS5pc0FycmF5KGFyZykpIHtcbiAgICAgIGxldCBtYXBwZWRWYWx1ZXMgPSBhcmcubWFwKHggPT4geC50b1N0cmluZygpKTtcbiAgICAgIHRoaXMubWVzc2FnZSA9ICdObyBtYXRjaCBmb3I6ICcgKyBtYXBwZWRWYWx1ZXM7XG4gICAgfSBlbHNlIHtcbiAgICAgIHRoaXMubWVzc2FnZSA9ICdObyBtYXRjaCBmb3I6ICcgKyBhcmc7XG4gICAgfVxuXG4gICAgdGhpcy5zdGFjayA9IG5ldyBFcnJvcigpLnN0YWNrO1xuICAgIHRoaXMubmFtZSA9IHRoaXMuY29uc3RydWN0b3IubmFtZTtcbiAgfVxufVxuXG5jbGFzcyBDYXNlIHtcblxuICBjb25zdHJ1Y3RvcihwYXR0ZXJuLCBmbiwgZ3VhcmQgPSAoKSA9PiB0cnVlKSB7XG4gICAgdGhpcy5wYXR0ZXJuID0gYnVpbGRNYXRjaChwYXR0ZXJuKTtcbiAgICB0aGlzLmZuID0gZm47XG4gICAgdGhpcy5ndWFyZCA9IGd1YXJkO1xuICB9XG59XG5cbmZ1bmN0aW9uIG1ha2VfY2FzZShwYXR0ZXJuLCBmbiwgZ3VhcmQgPSAoKSA9PiB0cnVlKSB7XG4gIHJldHVybiBuZXcgQ2FzZShwYXR0ZXJuLCBmbiwgZ3VhcmQpO1xufVxuXG5mdW5jdGlvbiBkZWZtYXRjaCguLi5jYXNlcykge1xuICByZXR1cm4gZnVuY3Rpb24gKC4uLmFyZ3MpIHtcbiAgICBmb3IgKGxldCBwcm9jZXNzZWRDYXNlIG9mIGNhc2VzKSB7XG4gICAgICBsZXQgcmVzdWx0ID0gW107XG4gICAgICBpZiAocHJvY2Vzc2VkQ2FzZS5wYXR0ZXJuKGFyZ3MsIHJlc3VsdCkgJiYgcHJvY2Vzc2VkQ2FzZS5ndWFyZC5hcHBseSh0aGlzLCByZXN1bHQpKSB7XG4gICAgICAgIHJldHVybiBwcm9jZXNzZWRDYXNlLmZuLmFwcGx5KHRoaXMsIHJlc3VsdCk7XG4gICAgICB9XG4gICAgfVxuXG4gICAgdGhyb3cgbmV3IE1hdGNoRXJyb3IoYXJncyk7XG4gIH07XG59XG5cbmZ1bmN0aW9uIG1hdGNoKHBhdHRlcm4sIGV4cHIsIGd1YXJkID0gKCkgPT4gdHJ1ZSkge1xuICBsZXQgcmVzdWx0ID0gW107XG4gIGxldCBwcm9jZXNzZWRQYXR0ZXJuID0gYnVpbGRNYXRjaChwYXR0ZXJuKTtcbiAgaWYgKHByb2Nlc3NlZFBhdHRlcm4oZXhwciwgcmVzdWx0KSAmJiBndWFyZC5hcHBseSh0aGlzLCByZXN1bHQpKSB7XG4gICAgcmV0dXJuIHJlc3VsdDtcbiAgfSBlbHNlIHtcbiAgICB0aHJvdyBuZXcgTWF0Y2hFcnJvcihleHByKTtcbiAgfVxufVxuXG5mdW5jdGlvbiBtYXRjaF9ub190aHJvdyhwYXR0ZXJuLCBleHByLCBndWFyZCA9ICgpID0+IHRydWUpIHtcbiAgdHJ5IHtcbiAgICByZXR1cm4gbWF0Y2gocGF0dGVybiwgZXhwciwgZ3VhcmQpO1xuICB9IGNhdGNoIChlKSB7XG4gICAgaWYgKGUgaW5zdGFuY2VvZiBNYXRjaEVycm9yKSB7XG4gICAgICByZXR1cm4gbnVsbDtcbiAgICB9XG5cbiAgICB0aHJvdyBlO1xuICB9XG59XG5cbnZhciBQYXR0ZXJucyA9IHtcbiAgZGVmbWF0Y2gsIG1hdGNoLCBNYXRjaEVycm9yLCBtYXRjaF9ub190aHJvdyxcbiAgdmFyaWFibGUsIHdpbGRjYXJkLCBzdGFydHNXaXRoLFxuICBjYXB0dXJlLCBoZWFkVGFpbCwgdHlwZSwgYm91bmQsIENhc2UsIG1ha2VfY2FzZVxufTtcblxuZnVuY3Rpb24gY2FsbF9wcm9wZXJ0eShpdGVtLCBwcm9wZXJ0eSkge1xuICBpZiAocHJvcGVydHkgaW4gaXRlbSkge1xuICAgIGl0ZW1bcHJvcGVydHldO1xuICAgIGlmIChpdGVtW3Byb3BlcnR5XSBpbnN0YW5jZW9mIEZ1bmN0aW9uKSB7XG4gICAgICByZXR1cm4gaXRlbVtwcm9wZXJ0eV0oKTtcbiAgICB9IGVsc2Uge1xuICAgICAgcmV0dXJuIGl0ZW1bcHJvcGVydHldO1xuICAgIH1cbiAgfSBlbHNlIGlmIChTeW1ib2wuZm9yKHByb3BlcnR5KSBpbiBpdGVtKSB7XG4gICAgbGV0IHByb3AgPSBTeW1ib2wuZm9yKHByb3BlcnR5KTtcbiAgICBpZiAoaXRlbVtwcm9wXSBpbnN0YW5jZW9mIEZ1bmN0aW9uKSB7XG4gICAgICByZXR1cm4gaXRlbVtwcm9wXSgpO1xuICAgIH0gZWxzZSB7XG4gICAgICByZXR1cm4gaXRlbVtwcm9wXTtcbiAgICB9XG4gIH1cblxuICB0aHJvdyBuZXcgRXJyb3IoYFByb3BlcnR5ICR7IHByb3BlcnR5IH0gbm90IGZvdW5kIGluICR7IGl0ZW0gfWApO1xufVxuXG5mdW5jdGlvbiBpc19pbnN0YW5jZV9vZih2YWx1ZSwgdHlwZSkge1xuICByZXR1cm4gdmFsdWUgaW5zdGFuY2VvZiB0eXBlO1xufVxuXG5mdW5jdGlvbiBzaXplJDModGVybSkge1xuICByZXR1cm4gdGVybS5sZW5ndGg7XG59XG5cbmZ1bmN0aW9uIGlzX25pbCQxKHgpIHtcbiAgcmV0dXJuIHggPT09IG51bGw7XG59XG5cbmZ1bmN0aW9uIGlzX2F0b20kMSh4KSB7XG4gIHJldHVybiB0eXBlb2YgeCA9PT0gJ3N5bWJvbCc7XG59XG5cbmZ1bmN0aW9uIGlzX2JpbmFyeSQxKHgpIHtcbiAgcmV0dXJuIHR5cGVvZiB4ID09PSAnc3RyaW5nJyB8fCB4IGluc3RhbmNlb2YgU3RyaW5nO1xufVxuXG5mdW5jdGlvbiBpc19ib29sZWFuJDEoeCkge1xuICByZXR1cm4gdHlwZW9mIHggPT09ICdib29sZWFuJyB8fCB4IGluc3RhbmNlb2YgQm9vbGVhbjtcbn1cblxuZnVuY3Rpb24gaXNfZnVuY3Rpb24kMSh4LCBhcml0eSA9IC0xKSB7XG4gIHJldHVybiB0eXBlb2YgeCA9PT0gJ2Z1bmN0aW9uJyB8fCB4IGluc3RhbmNlb2YgRnVuY3Rpb247XG59XG5cbmZ1bmN0aW9uIGlzX2Zsb2F0JDEoeCkge1xuICByZXR1cm4gaXNfbnVtYmVyJDEoeCkgJiYgIU51bWJlci5pc0ludGVnZXIoeCk7XG59XG5cbmZ1bmN0aW9uIGlzX2ludGVnZXIkMSh4KSB7XG4gIHJldHVybiBOdW1iZXIuaXNJbnRlZ2VyKHgpO1xufVxuXG5mdW5jdGlvbiBpc19saXN0JDEoeCkge1xuICByZXR1cm4geCBpbnN0YW5jZW9mIEFycmF5O1xufVxuXG5mdW5jdGlvbiBpc19tYXAkMSh4KSB7XG4gIHJldHVybiB0eXBlb2YgeCA9PT0gJ29iamVjdCcgfHwgeCBpbnN0YW5jZW9mIE9iamVjdDtcbn1cblxuZnVuY3Rpb24gaXNfbnVtYmVyJDEoeCkge1xuICByZXR1cm4gdHlwZW9mIHggPT09ICdudW1iZXInO1xufVxuXG5mdW5jdGlvbiBpc190dXBsZSQxKHgpIHtcbiAgcmV0dXJuIHggaW5zdGFuY2VvZiBUdXBsZSQxO1xufVxuXG5mdW5jdGlvbiBpc19waWQkMSh4KSB7XG4gIHJldHVybiB4IGluc3RhbmNlb2YgUElEO1xufVxuXG5mdW5jdGlvbiBpc19wb3J0JDEoeCkge1xuICByZXR1cm4gZmFsc2U7XG59XG5cbmZ1bmN0aW9uIGlzX3JlZmVyZW5jZSQxKHgpIHtcbiAgcmV0dXJuIGZhbHNlO1xufVxuXG5mdW5jdGlvbiBpc19iaXRzdHJpbmckMSh4KSB7XG4gIHJldHVybiBpc19iaW5hcnkkMSh4KSB8fCB4IGluc3RhbmNlb2YgQml0U3RyaW5nO1xufVxuXG5mdW5jdGlvbiBhZGQob25lLCB0d28pIHtcbiAgcmV0dXJuIG9uZSArIHR3bztcbn1cblxuZnVuY3Rpb24gc3VidHJhY3Qob25lLCB0d28pIHtcbiAgcmV0dXJuIG9uZSArIHR3bztcbn1cblxuZnVuY3Rpb24gbXVsdGlwbHkob25lLCB0d28pIHtcbiAgcmV0dXJuIG9uZSArIHR3bztcbn1cblxuZnVuY3Rpb24gZGl2aWRlKG9uZSwgdHdvKSB7XG4gIHJldHVybiBvbmUgKyB0d287XG59XG5cbmZ1bmN0aW9uIHJlbWFpbmRlcihvbmUsIHR3bykge1xuICByZXR1cm4gb25lICsgdHdvO1xufVxuXG5mdW5jdGlvbiBhcHBseSQxKC4uLmFyZ3MpIHtcbiAgaWYgKGFyZ3MubGVuZ3RoID09PSAyKSB7XG4gICAgYXJnc1swXS5hcHBseShudWxsLCBhcmdzLnNsaWNlKDEpKTtcbiAgfSBlbHNlIHtcbiAgICBhcmdzWzBdW2FyZ3NbMV1dLmFwcGx5KG51bGwsIGFyZ3Muc2xpY2UoMikpO1xuICB9XG59XG5cbmZ1bmN0aW9uIG5ld190dXBsZShhcmdzKSB7XG4gIHJldHVybiBuZXcgVHVwbGUkMSguLi5hcmdzKTtcbn1cblxuZnVuY3Rpb24gZHVwbGljYXRlJDIoZGF0YSwgc2l6ZSkge1xuICBsZXQgYXJyYXkgPSBbXTtcblxuICBmb3IgKHZhciBpID0gc2l6ZSAtIDE7IGkgPj0gMDsgaS0tKSB7XG4gICAgYXJyYXkucHVzaChkYXRhKTtcbiAgfVxuXG4gIHJldHVybiBhcnJheTtcbn1cblxuZnVuY3Rpb24gY29udGFpbnMobGVmdCwgcmlnaHQpIHtcbiAgZm9yIChsZXQgeCBvZiByaWdodCkge1xuICAgIGlmIChQYXR0ZXJucy5tYXRjaF9ub190aHJvdyhsZWZ0LCB4KSAhPSBudWxsKSB7XG4gICAgICByZXR1cm4gdHJ1ZTtcbiAgICB9XG4gIH1cblxuICByZXR1cm4gZmFsc2U7XG59XG5cbmZ1bmN0aW9uIHJldmVyc2UkMShsaXN0KSB7XG4gIHJldHVybiBsaXN0LmNvbmNhdChbXSkucmV2ZXJzZSgpO1xufVxuXG5mdW5jdGlvbiBnZXRfZ2xvYmFsKCkge1xuICBpZiAodHlwZW9mIHNlbGYgIT09ICd1bmRlZmluZWQnKSB7XG4gICAgcmV0dXJuIHNlbGY7XG4gIH0gZWxzZSBpZiAodHlwZW9mIGdsb2JhbCAhPT0gJ3VuZGVmaW5lZCcpIHtcbiAgICByZXR1cm4gZ2xvYmFsO1xuICB9XG5cbiAgdGhyb3cgJ05vIGdsb2JhbCBzdGF0ZSBmb3VuZCc7XG59XG5cbmZ1bmN0aW9uIGNvbmNhdF9saXN0cyhsZWZ0LCByaWdodCkge1xuICByZXR1cm4gbGVmdC5jb25jYXQocmlnaHQpO1xufVxuXG5mdW5jdGlvbiBwcmVwZW5kX3RvX2xpc3QobGlzdCwgaXRlbSkge1xuICByZXR1cm4gW2l0ZW1dLmNvbmNhdChsaXN0KTtcbn1cblxuZ2V0X2dsb2JhbCgpLnByb2Nlc3NlcyA9IGdldF9nbG9iYWwoKS5wcm9jZXNzZXMgfHwgbmV3IFByb2Nlc3NTeXN0ZW0oKTtcblxuXG5cbnZhciBDID0gT2JqZWN0LmZyZWV6ZSh7XG5cdFByb2Nlc3NTeXN0ZW06IFByb2Nlc3NTeXN0ZW0sXG5cdFR1cGxlOiBUdXBsZSQxLFxuXHRQSUQ6IFBJRCxcblx0Qml0U3RyaW5nOiBCaXRTdHJpbmcsXG5cdFBhdHRlcm5zOiBQYXR0ZXJucyxcblx0SW50ZWdlcjogSW50ZWdlciQxLFxuXHRGbG9hdDogRmxvYXQsXG5cdGNhbGxfcHJvcGVydHk6IGNhbGxfcHJvcGVydHksXG5cdGlzX2luc3RhbmNlX29mOiBpc19pbnN0YW5jZV9vZixcblx0c2l6ZTogc2l6ZSQzLFxuXHRpc19uaWw6IGlzX25pbCQxLFxuXHRpc19hdG9tOiBpc19hdG9tJDEsXG5cdGlzX2JpbmFyeTogaXNfYmluYXJ5JDEsXG5cdGlzX2Jvb2xlYW46IGlzX2Jvb2xlYW4kMSxcblx0aXNfZnVuY3Rpb246IGlzX2Z1bmN0aW9uJDEsXG5cdGlzX2Zsb2F0OiBpc19mbG9hdCQxLFxuXHRpc19pbnRlZ2VyOiBpc19pbnRlZ2VyJDEsXG5cdGlzX2xpc3Q6IGlzX2xpc3QkMSxcblx0aXNfbWFwOiBpc19tYXAkMSxcblx0aXNfbnVtYmVyOiBpc19udW1iZXIkMSxcblx0aXNfdHVwbGU6IGlzX3R1cGxlJDEsXG5cdGlzX3BpZDogaXNfcGlkJDEsXG5cdGlzX3BvcnQ6IGlzX3BvcnQkMSxcblx0aXNfcmVmZXJlbmNlOiBpc19yZWZlcmVuY2UkMSxcblx0aXNfYml0c3RyaW5nOiBpc19iaXRzdHJpbmckMSxcblx0YWRkOiBhZGQsXG5cdHN1YnRyYWN0OiBzdWJ0cmFjdCxcblx0bXVsdGlwbHk6IG11bHRpcGx5LFxuXHRkaXZpZGU6IGRpdmlkZSxcblx0cmVtYWluZGVyOiByZW1haW5kZXIsXG5cdGFwcGx5OiBhcHBseSQxLFxuXHRuZXdfdHVwbGU6IG5ld190dXBsZSxcblx0ZHVwbGljYXRlOiBkdXBsaWNhdGUkMixcblx0Y29udGFpbnM6IGNvbnRhaW5zLFxuXHRyZXZlcnNlOiByZXZlcnNlJDEsXG5cdGdldF9nbG9iYWw6IGdldF9nbG9iYWwsXG5cdGNvbmNhdF9saXN0czogY29uY2F0X2xpc3RzLFxuXHRwcmVwZW5kX3RvX2xpc3Q6IHByZXBlbmRfdG9fbGlzdFxufSk7XG5cbmxldCBFbnVtID0ge1xuXG4gIGFsbF9fcW1hcmtfXzogZnVuY3Rpb24gKGNvbGxlY3Rpb24sIGZ1biA9IHggPT4geCkge1xuICAgIGZvciAobGV0IGVsZW0gb2YgY29sbGVjdGlvbikge1xuICAgICAgaWYgKCFmdW4oZWxlbSkpIHtcbiAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgfVxuICAgIH1cblxuICAgIHJldHVybiB0cnVlO1xuICB9LFxuXG4gIGFueV9fcW1hcmtfXzogZnVuY3Rpb24gKGNvbGxlY3Rpb24sIGZ1biA9IHggPT4geCkge1xuICAgIGZvciAobGV0IGVsZW0gb2YgY29sbGVjdGlvbikge1xuICAgICAgaWYgKGZ1bihlbGVtKSkge1xuICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICByZXR1cm4gZmFsc2U7XG4gIH0sXG5cbiAgYXQ6IGZ1bmN0aW9uIChjb2xsZWN0aW9uLCBuLCB0aGVfZGVmYXVsdCA9IG51bGwpIHtcbiAgICBpZiAobiA+IHRoaXMuY291bnQoY29sbGVjdGlvbikgfHwgbiA8IDApIHtcbiAgICAgIHJldHVybiB0aGVfZGVmYXVsdDtcbiAgICB9XG5cbiAgICByZXR1cm4gY29sbGVjdGlvbltuXTtcbiAgfSxcblxuICBjb25jYXQ6IGZ1bmN0aW9uICguLi5lbnVtYWJsZXMpIHtcbiAgICByZXR1cm4gZW51bWFibGVzWzBdLmNvbmNhdChlbnVtYWJsZXNbMV0pO1xuICB9LFxuXG4gIGNvdW50OiBmdW5jdGlvbiAoY29sbGVjdGlvbiwgZnVuID0gbnVsbCkge1xuICAgIGlmIChmdW4gPT0gbnVsbCkge1xuICAgICAgcmV0dXJuIGNvbGxlY3Rpb24ubGVuZ3RoO1xuICAgIH0gZWxzZSB7XG4gICAgICByZXR1cm4gY29sbGVjdGlvbi5maWx0ZXIoZnVuKS5sZW5ndGg7XG4gICAgfVxuICB9LFxuXG4gIGRyb3A6IGZ1bmN0aW9uIChjb2xsZWN0aW9uLCBjb3VudCkge1xuICAgIHJldHVybiBjb2xsZWN0aW9uLnNsaWNlKGNvdW50KTtcbiAgfSxcblxuICBkcm9wX3doaWxlOiBmdW5jdGlvbiAoY29sbGVjdGlvbiwgZnVuKSB7XG4gICAgbGV0IGNvdW50ID0gMDtcblxuICAgIGZvciAobGV0IGVsZW0gb2YgY29sbGVjdGlvbikge1xuICAgICAgaWYgKGZ1bihlbGVtKSkge1xuICAgICAgICBjb3VudCA9IGNvdW50ICsgMTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIGJyZWFrO1xuICAgICAgfVxuICAgIH1cblxuICAgIHJldHVybiBjb2xsZWN0aW9uLnNsaWNlKGNvdW50KTtcbiAgfSxcblxuICBlYWNoOiBmdW5jdGlvbiAoY29sbGVjdGlvbiwgZnVuKSB7XG4gICAgZm9yIChsZXQgZWxlbSBvZiBjb2xsZWN0aW9uKSB7XG4gICAgICBmdW4oZWxlbSk7XG4gICAgfVxuICB9LFxuXG4gIGVtcHR5X19xbWFya19fOiBmdW5jdGlvbiAoY29sbGVjdGlvbikge1xuICAgIHJldHVybiBjb2xsZWN0aW9uLmxlbmd0aCA9PT0gMDtcbiAgfSxcblxuICBmZXRjaDogZnVuY3Rpb24gKGNvbGxlY3Rpb24sIG4pIHtcbiAgICBpZiAoS2VybmVsLmlzX2xpc3QoY29sbGVjdGlvbikpIHtcbiAgICAgIGlmIChuIDwgdGhpcy5jb3VudChjb2xsZWN0aW9uKSAmJiBuID49IDApIHtcbiAgICAgICAgcmV0dXJuIEtlcm5lbC5TcGVjaWFsRm9ybXMudHVwbGUoS2VybmVsLlNwZWNpYWxGb3Jtcy5hdG9tKFwib2tcIiksIGNvbGxlY3Rpb25bbl0pO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgcmV0dXJuIEtlcm5lbC5TcGVjaWFsRm9ybXMuYXRvbShcImVycm9yXCIpO1xuICAgICAgfVxuICAgIH1cblxuICAgIHRocm93IG5ldyBFcnJvcihcImNvbGxlY3Rpb24gaXMgbm90IGFuIEVudW1lcmFibGVcIik7XG4gIH0sXG5cbiAgZmV0Y2hfX2VtYXJrX186IGZ1bmN0aW9uIChjb2xsZWN0aW9uLCBuKSB7XG4gICAgaWYgKEtlcm5lbC5pc19saXN0KGNvbGxlY3Rpb24pKSB7XG4gICAgICBpZiAobiA8IHRoaXMuY291bnQoY29sbGVjdGlvbikgJiYgbiA+PSAwKSB7XG4gICAgICAgIHJldHVybiBjb2xsZWN0aW9uW25dO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKFwib3V0IG9mIGJvdW5kcyBlcnJvclwiKTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICB0aHJvdyBuZXcgRXJyb3IoXCJjb2xsZWN0aW9uIGlzIG5vdCBhbiBFbnVtZXJhYmxlXCIpO1xuICB9LFxuXG4gIGZpbHRlcjogZnVuY3Rpb24gKGNvbGxlY3Rpb24sIGZ1bikge1xuICAgIGxldCByZXN1bHQgPSBbXTtcblxuICAgIGZvciAobGV0IGVsZW0gb2YgY29sbGVjdGlvbikge1xuICAgICAgaWYgKGZ1bihlbGVtKSkge1xuICAgICAgICByZXN1bHQucHVzaChlbGVtKTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICByZXR1cm4gcmVzdWx0O1xuICB9LFxuXG4gIGZpbHRlcl9tYXA6IGZ1bmN0aW9uIChjb2xsZWN0aW9uLCBmaWx0ZXIsIG1hcHBlcikge1xuICAgIHJldHVybiBFbnVtLm1hcChFbnVtLmZpbHRlcihjb2xsZWN0aW9uLCBmaWx0ZXIpLCBtYXBwZXIpO1xuICB9LFxuXG4gIGZpbmQ6IGZ1bmN0aW9uIChjb2xsZWN0aW9uLCBpZl9ub25lID0gbnVsbCwgZnVuKSB7XG4gICAgZm9yIChsZXQgZWxlbSBvZiBjb2xsZWN0aW9uKSB7XG4gICAgICBpZiAoZnVuKGVsZW0pKSB7XG4gICAgICAgIHJldHVybiBlbGVtO1xuICAgICAgfVxuICAgIH1cblxuICAgIHJldHVybiBpZl9ub25lO1xuICB9LFxuXG4gIGludG86IGZ1bmN0aW9uIChjb2xsZWN0aW9uLCBsaXN0KSB7XG4gICAgcmV0dXJuIGxpc3QuY29uY2F0KGNvbGxlY3Rpb24pO1xuICB9LFxuXG4gIG1hcDogZnVuY3Rpb24gKGNvbGxlY3Rpb24sIGZ1bikge1xuICAgIGxldCByZXN1bHQgPSBbXTtcblxuICAgIGZvciAobGV0IGVsZW0gb2YgY29sbGVjdGlvbikge1xuICAgICAgcmVzdWx0LnB1c2goZnVuKGVsZW0pKTtcbiAgICB9XG5cbiAgICByZXR1cm4gcmVzdWx0O1xuICB9LFxuXG4gIG1hcF9yZWR1Y2U6IGZ1bmN0aW9uIChjb2xsZWN0aW9uLCBhY2MsIGZ1bikge1xuICAgIGxldCBtYXBwZWQgPSBLZXJuZWwuU3BlY2lhbEZvcm1zLmxpc3QoKTtcbiAgICBsZXQgdGhlX2FjYyA9IGFjYztcblxuICAgIGZvciAodmFyIGkgPSAwOyBpIDwgdGhpcy5jb3VudChjb2xsZWN0aW9uKTsgaSsrKSB7XG4gICAgICBsZXQgdHVwbGUgPSBmdW4oY29sbGVjdGlvbltpXSwgdGhlX2FjYyk7XG5cbiAgICAgIHRoZV9hY2MgPSBLZXJuZWwuZWxlbSh0dXBsZSwgMSk7XG4gICAgICBtYXBwZWQgPSBLZXJuZWwuU3BlY2lhbEZvcm1zLmxpc3QoLi4ubWFwcGVkLmNvbmNhdChbS2VybmVsLmVsZW0odHVwbGUsIDApXSkpO1xuICAgIH1cblxuICAgIHJldHVybiBLZXJuZWwuU3BlY2lhbEZvcm1zLnR1cGxlKG1hcHBlZCwgdGhlX2FjYyk7XG4gIH0sXG5cbiAgbWVtYmVyX19xbWFya19fOiBmdW5jdGlvbiAoY29sbGVjdGlvbiwgdmFsdWUpIHtcbiAgICByZXR1cm4gY29sbGVjdGlvbi5pbmNsdWRlcyh2YWx1ZSk7XG4gIH0sXG5cbiAgcmVkdWNlOiBmdW5jdGlvbiAoY29sbGVjdGlvbiwgYWNjLCBmdW4pIHtcbiAgICBsZXQgdGhlX2FjYyA9IGFjYztcblxuICAgIGZvciAodmFyIGkgPSAwOyBpIDwgdGhpcy5jb3VudChjb2xsZWN0aW9uKTsgaSsrKSB7XG4gICAgICBsZXQgdHVwbGUgPSBmdW4oY29sbGVjdGlvbltpXSwgdGhlX2FjYyk7XG5cbiAgICAgIHRoZV9hY2MgPSBLZXJuZWwuZWxlbSh0dXBsZSwgMSk7XG4gICAgfVxuXG4gICAgcmV0dXJuIHRoZV9hY2M7XG4gIH0sXG5cbiAgdGFrZTogZnVuY3Rpb24gKGNvbGxlY3Rpb24sIGNvdW50KSB7XG4gICAgcmV0dXJuIGNvbGxlY3Rpb24uc2xpY2UoMCwgY291bnQpO1xuICB9LFxuXG4gIHRha2VfZXZlcnk6IGZ1bmN0aW9uIChjb2xsZWN0aW9uLCBudGgpIHtcbiAgICBsZXQgcmVzdWx0ID0gW107XG4gICAgbGV0IGluZGV4ID0gMDtcblxuICAgIGZvciAobGV0IGVsZW0gb2YgY29sbGVjdGlvbikge1xuICAgICAgaWYgKGluZGV4ICUgbnRoID09PSAwKSB7XG4gICAgICAgIHJlc3VsdC5wdXNoKGVsZW0pO1xuICAgICAgfVxuICAgIH1cblxuICAgIHJldHVybiBLZXJuZWwuU3BlY2lhbEZvcm1zLmxpc3QoLi4ucmVzdWx0KTtcbiAgfSxcblxuICB0YWtlX3doaWxlOiBmdW5jdGlvbiAoY29sbGVjdGlvbiwgZnVuKSB7XG4gICAgbGV0IGNvdW50ID0gMDtcblxuICAgIGZvciAobGV0IGVsZW0gb2YgY29sbGVjdGlvbikge1xuICAgICAgaWYgKGZ1bihlbGVtKSkge1xuICAgICAgICBjb3VudCA9IGNvdW50ICsgMTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIGJyZWFrO1xuICAgICAgfVxuICAgIH1cblxuICAgIHJldHVybiBjb2xsZWN0aW9uLnNsaWNlKDAsIGNvdW50KTtcbiAgfSxcblxuICB0b19saXN0OiBmdW5jdGlvbiAoY29sbGVjdGlvbikge1xuICAgIHJldHVybiBjb2xsZWN0aW9uO1xuICB9XG59O1xuXG5sZXQgU3BlY2lhbEZvcm1zID0ge1xuXG4gIF9fRElSX186IGZ1bmN0aW9uICgpIHtcbiAgICBpZiAoX19kaXJuYW1lKSB7XG4gICAgICByZXR1cm4gX19kaXJuYW1lO1xuICAgIH1cblxuICAgIGlmIChkb2N1bWVudC5jdXJyZW50U2NyaXB0KSB7XG4gICAgICByZXR1cm4gZG9jdW1lbnQuY3VycmVudFNjcmlwdC5zcmM7XG4gICAgfVxuXG4gICAgcmV0dXJuIG51bGw7XG4gIH0sXG5cbiAgYXRvbTogZnVuY3Rpb24gKF92YWx1ZSkge1xuICAgIHJldHVybiBTeW1ib2wuZm9yKF92YWx1ZSk7XG4gIH0sXG5cbiAgbGlzdDogZnVuY3Rpb24gKC4uLmFyZ3MpIHtcbiAgICByZXR1cm4gT2JqZWN0LmZyZWV6ZShhcmdzKTtcbiAgfSxcblxuICBiaXRzdHJpbmc6IGZ1bmN0aW9uICguLi5hcmdzKSB7XG4gICAgcmV0dXJuIG5ldyBCaXRTdHJpbmcoLi4uYXJncyk7XG4gIH0sXG5cbiAgYm91bmQ6IGZ1bmN0aW9uIChfdmFyKSB7XG4gICAgcmV0dXJuIFBhdHRlcm5zLmJvdW5kKF92YXIpO1xuICB9LFxuXG4gIF9jYXNlOiBmdW5jdGlvbiAoY29uZGl0aW9uLCBjbGF1c2VzKSB7XG4gICAgcmV0dXJuIFBhdHRlcm5zLmRlZm1hdGNoKC4uLmNsYXVzZXMpKGNvbmRpdGlvbik7XG4gIH0sXG5cbiAgY29uZDogZnVuY3Rpb24gKGNsYXVzZXMpIHtcbiAgICBmb3IgKGxldCBjbGF1c2Ugb2YgY2xhdXNlcykge1xuICAgICAgaWYgKGNsYXVzZVswXSkge1xuICAgICAgICByZXR1cm4gY2xhdXNlWzFdKCk7XG4gICAgICB9XG4gICAgfVxuXG4gICAgdGhyb3cgbmV3IEVycm9yKCk7XG4gIH0sXG5cbiAgZm46IGZ1bmN0aW9uIChjbGF1c2VzKSB7XG4gICAgcmV0dXJuIFBhdHRlcm5zLmRlZm1hdGNoKGNsYXVzZXMpO1xuICB9LFxuXG4gIG1hcDogZnVuY3Rpb24gKG9iaikge1xuICAgIHJldHVybiBPYmplY3QuZnJlZXplKG9iaik7XG4gIH0sXG5cbiAgbWFwX3VwZGF0ZTogZnVuY3Rpb24gKG1hcCwgdmFsdWVzKSB7XG4gICAgcmV0dXJuIE9iamVjdC5mcmVlemUoT2JqZWN0LmFzc2lnbihPYmplY3QuY3JlYXRlKG1hcC5jb25zdHJ1Y3Rvci5wcm90b3R5cGUpLCBtYXAsIHZhbHVlcykpO1xuICB9LFxuXG4gIF9mb3I6IGZ1bmN0aW9uIChjb2xsZWN0aW9ucywgZnVuLCBmaWx0ZXIgPSAoKSA9PiB0cnVlLCBpbnRvID0gW10sIHByZXZpb3VzVmFsdWVzID0gW10pIHtcbiAgICBsZXQgcGF0dGVybiA9IGNvbGxlY3Rpb25zWzBdWzBdO1xuICAgIGxldCBjb2xsZWN0aW9uID0gY29sbGVjdGlvbnNbMF1bMV07XG5cbiAgICBpZiAoY29sbGVjdGlvbnMubGVuZ3RoID09PSAxKSB7XG5cbiAgICAgIGZvciAobGV0IGVsZW0gb2YgY29sbGVjdGlvbikge1xuICAgICAgICBsZXQgciA9IFBhdHRlcm5zLm1hdGNoX25vX3Rocm93KHBhdHRlcm4sIGVsZW0pO1xuICAgICAgICBsZXQgYXJncyA9IHByZXZpb3VzVmFsdWVzLmNvbmNhdChyKTtcblxuICAgICAgICBpZiAociAmJiBmaWx0ZXIuYXBwbHkodGhpcywgYXJncykpIHtcbiAgICAgICAgICBpbnRvID0gRW51bS5pbnRvKFtmdW4uYXBwbHkodGhpcywgYXJncyldLCBpbnRvKTtcbiAgICAgICAgfVxuICAgICAgfVxuXG4gICAgICByZXR1cm4gaW50bztcbiAgICB9IGVsc2Uge1xuICAgICAgbGV0IF9pbnRvID0gW107XG5cbiAgICAgIGZvciAobGV0IGVsZW0gb2YgY29sbGVjdGlvbikge1xuICAgICAgICBsZXQgciA9IFBhdHRlcm5zLm1hdGNoX25vX3Rocm93KHBhdHRlcm4sIGVsZW0pO1xuICAgICAgICBpZiAocikge1xuICAgICAgICAgIF9pbnRvID0gRW51bS5pbnRvKHRoaXMuX2Zvcihjb2xsZWN0aW9ucy5zbGljZSgxKSwgZnVuLCBmaWx0ZXIsIF9pbnRvLCBwcmV2aW91c1ZhbHVlcy5jb25jYXQocikpLCBpbnRvKTtcbiAgICAgICAgfVxuICAgICAgfVxuXG4gICAgICByZXR1cm4gX2ludG87XG4gICAgfVxuICB9LFxuXG4gIHJlY2VpdmU6IGZ1bmN0aW9uIChyZWNlaXZlX2Z1biwgdGltZW91dF9pbl9tcyA9IG51bGwsIHRpbWVvdXRfZm4gPSB0aW1lID0+IHRydWUpIHtcbiAgICBpZiAodGltZW91dF9pbl9tcyA9PSBudWxsIHx8IHRpbWVvdXRfaW5fbXMgPT09IFN5c3RlbS5mb3IoJ2luZmluaXR5JykpIHtcbiAgICAgIHdoaWxlICh0cnVlKSB7XG4gICAgICAgIGlmIChzZWxmLm1haWxib3gubGVuZ3RoICE9PSAwKSB7XG4gICAgICAgICAgbGV0IG1lc3NhZ2UgPSBzZWxmLm1haWxib3hbMF07XG4gICAgICAgICAgc2VsZi5tYWlsYm94ID0gc2VsZi5tYWlsYm94LnNsaWNlKDEpO1xuICAgICAgICAgIHJldHVybiByZWNlaXZlX2Z1bihtZXNzYWdlKTtcbiAgICAgICAgfVxuICAgICAgfVxuICAgIH0gZWxzZSBpZiAodGltZW91dF9pbl9tcyA9PT0gMCkge1xuICAgICAgaWYgKHNlbGYubWFpbGJveC5sZW5ndGggIT09IDApIHtcbiAgICAgICAgbGV0IG1lc3NhZ2UgPSBzZWxmLm1haWxib3hbMF07XG4gICAgICAgIHNlbGYubWFpbGJveCA9IHNlbGYubWFpbGJveC5zbGljZSgxKTtcbiAgICAgICAgcmV0dXJuIHJlY2VpdmVfZnVuKG1lc3NhZ2UpO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgcmV0dXJuIG51bGw7XG4gICAgICB9XG4gICAgfSBlbHNlIHtcbiAgICAgIGxldCBub3cgPSBEYXRlLm5vdygpO1xuICAgICAgd2hpbGUgKERhdGUubm93KCkgPCBub3cgKyB0aW1lb3V0X2luX21zKSB7XG4gICAgICAgIGlmIChzZWxmLm1haWxib3gubGVuZ3RoICE9PSAwKSB7XG4gICAgICAgICAgbGV0IG1lc3NhZ2UgPSBzZWxmLm1haWxib3hbMF07XG4gICAgICAgICAgc2VsZi5tYWlsYm94ID0gc2VsZi5tYWlsYm94LnNsaWNlKDEpO1xuICAgICAgICAgIHJldHVybiByZWNlaXZlX2Z1bihtZXNzYWdlKTtcbiAgICAgICAgfVxuICAgICAgfVxuXG4gICAgICByZXR1cm4gdGltZW91dF9mbih0aW1lb3V0X2luX21zKTtcbiAgICB9XG4gIH0sXG5cbiAgdHVwbGU6IGZ1bmN0aW9uICguLi5hcmdzKSB7XG4gICAgcmV0dXJuIG5ldyBUdXBsZSQxKC4uLmFyZ3MpO1xuICB9LFxuXG4gIF90cnk6IGZ1bmN0aW9uIChkb19mdW4sIHJlc2N1ZV9mdW5jdGlvbiwgY2F0Y2hfZnVuLCBlbHNlX2Z1bmN0aW9uLCBhZnRlcl9mdW5jdGlvbikge1xuICAgIGxldCByZXN1bHQgPSBudWxsO1xuXG4gICAgdHJ5IHtcbiAgICAgIHJlc3VsdCA9IGRvX2Z1bigpO1xuICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgIGxldCBleF9yZXN1bHQgPSBudWxsO1xuXG4gICAgICBpZiAocmVzY3VlX2Z1bmN0aW9uKSB7XG4gICAgICAgIHRyeSB7XG4gICAgICAgICAgZXhfcmVzdWx0ID0gcmVzY3VlX2Z1bmN0aW9uKGUpO1xuICAgICAgICAgIHJldHVybiBleF9yZXN1bHQ7XG4gICAgICAgIH0gY2F0Y2ggKGV4KSB7XG4gICAgICAgICAgaWYgKGV4IGluc3RhbmNlb2YgUGF0dGVybnMuTWF0Y2hFcnJvcikge1xuICAgICAgICAgICAgdGhyb3cgZXg7XG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICB9XG5cbiAgICAgIGlmIChjYXRjaF9mdW4pIHtcbiAgICAgICAgdHJ5IHtcbiAgICAgICAgICBleF9yZXN1bHQgPSBjYXRjaF9mdW4oZSk7XG4gICAgICAgICAgcmV0dXJuIGV4X3Jlc3VsdDtcbiAgICAgICAgfSBjYXRjaCAoZXgpIHtcbiAgICAgICAgICBpZiAoZXggaW5zdGFuY2VvZiBQYXR0ZXJucy5NYXRjaEVycm9yKSB7XG4gICAgICAgICAgICB0aHJvdyBleDtcbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgIH1cblxuICAgICAgdGhyb3cgZTtcbiAgICB9IGZpbmFsbHkge1xuICAgICAgaWYgKGFmdGVyX2Z1bmN0aW9uKSB7XG4gICAgICAgIGFmdGVyX2Z1bmN0aW9uKCk7XG4gICAgICB9XG4gICAgfVxuXG4gICAgaWYgKGVsc2VfZnVuY3Rpb24pIHtcbiAgICAgIHRyeSB7XG4gICAgICAgIHJldHVybiBlbHNlX2Z1bmN0aW9uKHJlc3VsdCk7XG4gICAgICB9IGNhdGNoIChleCkge1xuICAgICAgICBpZiAoZXggaW5zdGFuY2VvZiBQYXR0ZXJucy5NYXRjaEVycm9yKSB7XG4gICAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdObyBNYXRjaCBGb3VuZCBpbiBFbHNlJyk7XG4gICAgICAgIH1cblxuICAgICAgICB0aHJvdyBleDtcbiAgICAgIH1cbiAgICB9IGVsc2Uge1xuICAgICAgcmV0dXJuIHJlc3VsdDtcbiAgICB9XG4gIH1cblxufTtcblxuZnVuY3Rpb24gdG9fc3RyaW5nJDEodHVwbGUpIHtcbiAgcmV0dXJuIHR1cGxlLnRvU3RyaW5nKCk7XG59O1xuXG5mdW5jdGlvbiBkZWxldGVfYXQodHVwbGUsIGluZGV4KSB7XG4gIGxldCBuZXdfbGlzdCA9IFtdO1xuXG4gIGZvciAodmFyIGkgPSAwOyBpIDwgdHVwbGUuY291bnQoKTsgaSsrKSB7XG4gICAgaWYgKGkgIT09IGluZGV4KSB7XG4gICAgICBuZXdfbGlzdC5wdXNoKHR1cGxlLmdldChpKSk7XG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIEtlcm5lbC5TcGVjaWFsRm9ybXMudHVwbGUuYXBwbHkobnVsbCwgbmV3X2xpc3QpO1xufTtcblxuZnVuY3Rpb24gZHVwbGljYXRlKGRhdGEsIHNpemUpIHtcbiAgbGV0IGFycmF5ID0gW107XG5cbiAgZm9yICh2YXIgaSA9IHNpemUgLSAxOyBpID49IDA7IGktLSkge1xuICAgIGFycmF5LnB1c2goZGF0YSk7XG4gIH1cblxuICByZXR1cm4gS2VybmVsLlNwZWNpYWxGb3Jtcy50dXBsZS5hcHBseShudWxsLCBhcnJheSk7XG59O1xuXG5mdW5jdGlvbiBpbnNlcnRfYXQodHVwbGUsIGluZGV4LCB0ZXJtKSB7XG4gIGxldCBuZXdfdHVwbGUgPSBbXTtcblxuICBmb3IgKHZhciBpID0gMDsgaSA8PSB0dXBsZS5jb3VudCgpOyBpKyspIHtcbiAgICBpZiAoaSA9PT0gaW5kZXgpIHtcbiAgICAgIG5ld190dXBsZS5wdXNoKHRlcm0pO1xuICAgICAgaSsrO1xuICAgICAgbmV3X3R1cGxlLnB1c2godHVwbGUuZ2V0KGkpKTtcbiAgICB9IGVsc2Uge1xuICAgICAgbmV3X3R1cGxlLnB1c2godHVwbGUuZ2V0KGkpKTtcbiAgICB9XG4gIH1cblxuICByZXR1cm4gS2VybmVsLlNwZWNpYWxGb3Jtcy50dXBsZS5hcHBseShudWxsLCBuZXdfdHVwbGUpO1xufTtcblxuZnVuY3Rpb24gZnJvbV9saXN0KGxpc3QpIHtcbiAgcmV0dXJuIEtlcm5lbC5TcGVjaWFsRm9ybXMudHVwbGUuYXBwbHkobnVsbCwgbGlzdCk7XG59O1xuXG5mdW5jdGlvbiB0b19saXN0KHR1cGxlKSB7XG4gIGxldCBuZXdfbGlzdCA9IFtdO1xuXG4gIGZvciAodmFyIGkgPSAwOyBpIDwgdHVwbGUuY291bnQoKTsgaSsrKSB7XG4gICAgbmV3X2xpc3QucHVzaCh0dXBsZS5nZXQoaSkpO1xuICB9XG5cbiAgcmV0dXJuIEtlcm5lbC5TcGVjaWFsRm9ybXMubGlzdCguLi5uZXdfbGlzdCk7XG59O1xuXG52YXIgVHVwbGUgPSB7XG4gIHRvX3N0cmluZzogdG9fc3RyaW5nJDEsXG4gIGRlbGV0ZV9hdCxcbiAgZHVwbGljYXRlLFxuICBpbnNlcnRfYXQsXG4gIGZyb21fbGlzdCxcbiAgdG9fbGlzdFxufTtcblxuLy9odHRwczovL2dpdGh1Yi5jb20vYWlycG9ydHloL3Byb3RvbW9ycGhpc21cbmNsYXNzIFByb3RvY29sIHtcbiAgY29uc3RydWN0b3Ioc3BlYykge1xuICAgIHRoaXMucmVnaXN0cnkgPSBuZXcgTWFwKCk7XG4gICAgdGhpcy5mYWxsYmFjayA9IG51bGw7XG5cbiAgICBmb3IgKGxldCBmdW5OYW1lIGluIHNwZWMpIHtcbiAgICAgIHRoaXNbZnVuTmFtZV0gPSBjcmVhdGVGdW4oZnVuTmFtZSkuYmluZCh0aGlzKTtcbiAgICB9XG5cbiAgICBmdW5jdGlvbiBjcmVhdGVGdW4oZnVuTmFtZSkge1xuXG4gICAgICByZXR1cm4gZnVuY3Rpb24gKC4uLmFyZ3MpIHtcbiAgICAgICAgbGV0IHRoaW5nID0gYXJnc1swXTtcbiAgICAgICAgbGV0IGZ1biA9IG51bGw7XG5cbiAgICAgICAgaWYgKE51bWJlci5pc0ludGVnZXIodGhpbmcpICYmIHRoaXMuaGFzSW1wbGVtZW50YXRpb24oSW50ZWdlciQxKSkge1xuICAgICAgICAgIGZ1biA9IHRoaXMucmVnaXN0cnkuZ2V0KEludGVnZXIkMSlbZnVuTmFtZV07XG4gICAgICAgIH0gZWxzZSBpZiAodHlwZW9mIHRoaW5nID09PSBcIm51bWJlclwiICYmICFOdW1iZXIuaXNJbnRlZ2VyKHRoaW5nKSAmJiB0aGlzLmhhc0ltcGxlbWVudGF0aW9uKEZsb2F0KSkge1xuICAgICAgICAgIGZ1biA9IHRoaXMucmVnaXN0cnkuZ2V0KEZsb2F0KVtmdW5OYW1lXTtcbiAgICAgICAgfSBlbHNlIGlmICh0aGlzLmhhc0ltcGxlbWVudGF0aW9uKHRoaW5nKSkge1xuICAgICAgICAgIGZ1biA9IHRoaXMucmVnaXN0cnkuZ2V0KHRoaW5nLmNvbnN0cnVjdG9yKVtmdW5OYW1lXTtcbiAgICAgICAgfSBlbHNlIGlmICh0aGlzLmZhbGxiYWNrKSB7XG4gICAgICAgICAgZnVuID0gdGhpcy5mYWxsYmFja1tmdW5OYW1lXTtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmIChmdW4gIT0gbnVsbCkge1xuICAgICAgICAgIGxldCByZXR2YWwgPSBmdW4uYXBwbHkodGhpcywgYXJncyk7XG4gICAgICAgICAgcmV0dXJuIHJldHZhbDtcbiAgICAgICAgfVxuXG4gICAgICAgIHRocm93IG5ldyBFcnJvcihcIk5vIGltcGxlbWVudGF0aW9uIGZvdW5kIGZvciBcIiArIHRoaW5nKTtcbiAgICAgIH07XG4gICAgfVxuICB9XG5cbiAgaW1wbGVtZW50YXRpb24odHlwZSwgaW1wbGVtZW50YXRpb24pIHtcbiAgICBpZiAodHlwZSA9PT0gbnVsbCkge1xuICAgICAgdGhpcy5mYWxsYmFjayA9IGltcGxlbWVudGF0aW9uO1xuICAgIH0gZWxzZSB7XG4gICAgICB0aGlzLnJlZ2lzdHJ5LnNldCh0eXBlLCBpbXBsZW1lbnRhdGlvbik7XG4gICAgfVxuICB9XG5cbiAgaGFzSW1wbGVtZW50YXRpb24odGhpbmcpIHtcbiAgICByZXR1cm4gdGhpcy5yZWdpc3RyeS5oYXModGhpbmcuY29uc3RydWN0b3IpO1xuICB9XG59XG5cbmZ1bmN0aW9uIHRsKGxpc3QpIHtcbiAgcmV0dXJuIFNwZWNpYWxGb3Jtcy5saXN0KC4uLmxpc3Quc2xpY2UoMSkpO1xufVxuXG5mdW5jdGlvbiBoZChsaXN0KSB7XG4gIHJldHVybiBsaXN0WzBdO1xufVxuXG5mdW5jdGlvbiBpc19uaWwoeCkge1xuICByZXR1cm4geCA9PT0gbnVsbDtcbn1cblxuZnVuY3Rpb24gaXNfYXRvbSh4KSB7XG4gIHJldHVybiB0eXBlb2YgeCA9PT0gJ3N5bWJvbCc7XG59XG5cbmZ1bmN0aW9uIGlzX2JpbmFyeSh4KSB7XG4gIHJldHVybiB0eXBlb2YgeCA9PT0gJ3N0cmluZycgfHwgeCBpbnN0YW5jZW9mIFN0cmluZztcbn1cblxuZnVuY3Rpb24gaXNfYm9vbGVhbih4KSB7XG4gIHJldHVybiB0eXBlb2YgeCA9PT0gJ2Jvb2xlYW4nIHx8IHggaW5zdGFuY2VvZiBCb29sZWFuO1xufVxuXG5mdW5jdGlvbiBpc19mdW5jdGlvbih4LCBhcml0eSA9IC0xKSB7XG4gIHJldHVybiB0eXBlb2YgeCA9PT0gJ2Z1bmN0aW9uJyB8fCB4IGluc3RhbmNlb2YgRnVuY3Rpb247XG59XG5cbmZ1bmN0aW9uIGlzX2Zsb2F0KHgpIHtcbiAgcmV0dXJuIGlzX251bWJlcih4KSAmJiAhTnVtYmVyLmlzSW50ZWdlcih4KTtcbn1cblxuZnVuY3Rpb24gaXNfaW50ZWdlcih4KSB7XG4gIHJldHVybiBOdW1iZXIuaXNJbnRlZ2VyKHgpO1xufVxuXG5mdW5jdGlvbiBpc19saXN0KHgpIHtcbiAgcmV0dXJuIHggaW5zdGFuY2VvZiBBcnJheTtcbn1cblxuZnVuY3Rpb24gaXNfbWFwKHgpIHtcbiAgcmV0dXJuIHR5cGVvZiB4ID09PSAnb2JqZWN0JyB8fCB4IGluc3RhbmNlb2YgT2JqZWN0O1xufVxuXG5mdW5jdGlvbiBpc19udW1iZXIoeCkge1xuICByZXR1cm4gdHlwZW9mIHggPT09ICdudW1iZXInO1xufVxuXG5mdW5jdGlvbiBpc190dXBsZSh4KSB7XG4gIHJldHVybiB4IGluc3RhbmNlb2YgVHVwbGUkMTtcbn1cblxuZnVuY3Rpb24gbGVuZ3RoKHgpIHtcbiAgcmV0dXJuIHgubGVuZ3RoO1xufVxuXG5mdW5jdGlvbiBpc19waWQoeCkge1xuICByZXR1cm4geCBpbnN0YW5jZW9mIFBJRDtcbn1cblxuZnVuY3Rpb24gaXNfcG9ydCh4KSB7XG4gIHJldHVybiBmYWxzZTtcbn1cblxuZnVuY3Rpb24gaXNfcmVmZXJlbmNlKHgpIHtcbiAgcmV0dXJuIGZhbHNlO1xufVxuXG5mdW5jdGlvbiBpc19iaXRzdHJpbmcoeCkge1xuICByZXR1cm4gaXNfYmluYXJ5KHgpIHx8IHggaW5zdGFuY2VvZiBCaXRTdHJpbmc7XG59XG5cbmZ1bmN0aW9uIF9faW5fXyhsZWZ0LCByaWdodCkge1xuICBmb3IgKGxldCB4IG9mIHJpZ2h0KSB7XG4gICAgaWYgKG1hdGNoX19xbWFya19fKGxlZnQsIHgpKSB7XG4gICAgICByZXR1cm4gdHJ1ZTtcbiAgICB9XG4gIH1cblxuICByZXR1cm4gZmFsc2U7XG59XG5cbmZ1bmN0aW9uIGFicyhudW1iZXIpIHtcbiAgcmV0dXJuIE1hdGguYWJzKG51bWJlcik7XG59XG5cbmZ1bmN0aW9uIHJvdW5kKG51bWJlcikge1xuICByZXR1cm4gTWF0aC5yb3VuZChudW1iZXIpO1xufVxuXG5mdW5jdGlvbiBlbGVtKHR1cGxlLCBpbmRleCkge1xuICBpZiAoaXNfbGlzdCh0dXBsZSkpIHtcbiAgICByZXR1cm4gdHVwbGVbaW5kZXhdO1xuICB9XG5cbiAgcmV0dXJuIHR1cGxlLmdldChpbmRleCk7XG59XG5cbmZ1bmN0aW9uIHJlbShsZWZ0LCByaWdodCkge1xuICByZXR1cm4gbGVmdCAlIHJpZ2h0O1xufVxuXG5mdW5jdGlvbiBkaXYobGVmdCwgcmlnaHQpIHtcbiAgcmV0dXJuIGxlZnQgLyByaWdodDtcbn1cblxuZnVuY3Rpb24gYW5kKGxlZnQsIHJpZ2h0KSB7XG4gIHJldHVybiBsZWZ0ICYmIHJpZ2h0O1xufVxuXG5mdW5jdGlvbiBvcihsZWZ0LCByaWdodCkge1xuICByZXR1cm4gbGVmdCB8fCByaWdodDtcbn1cblxuZnVuY3Rpb24gbm90KGFyZykge1xuICByZXR1cm4gIWFyZztcbn1cblxuZnVuY3Rpb24gYXBwbHkoLi4uYXJncykge1xuICBpZiAoYXJncy5sZW5ndGggPT09IDMpIHtcbiAgICBsZXQgbW9kID0gYXJnc1swXTtcbiAgICBsZXQgZnVuYyA9IGFyZ3NbMV07XG4gICAgbGV0IGZ1bmNfYXJncyA9IGFyZ3NbMl07XG4gICAgcmV0dXJuIG1vZFtmdW5jXS5hcHBseShudWxsLCBmdW5jX2FyZ3MpO1xuICB9IGVsc2Uge1xuICAgIGxldCBmdW5jID0gYXJnc1swXTtcbiAgICBsZXQgZnVuY19hcmdzID0gYXJnc1sxXTtcblxuICAgIHJldHVybiBmdW5jLmFwcGx5KG51bGwsIGZ1bmNfYXJncyk7XG4gIH1cbn1cblxuZnVuY3Rpb24gdG9fc3RyaW5nKGFyZykge1xuICBpZiAoaXNfdHVwbGUoYXJnKSkge1xuICAgIHJldHVybiBUdXBsZS50b19zdHJpbmcoYXJnKTtcbiAgfVxuXG4gIHJldHVybiBhcmcudG9TdHJpbmcoKTtcbn1cblxuZnVuY3Rpb24gbWF0Y2hfX3FtYXJrX18ocGF0dGVybiwgZXhwciwgZ3VhcmQgPSAoKSA9PiB0cnVlKSB7XG4gIHJldHVybiBQYXR0ZXJucy5tYXRjaF9ub190aHJvdyhwYXR0ZXJuLCBleHByLCBndWFyZCkgIT0gbnVsbDtcbn1cblxuZnVuY3Rpb24gZGVmc3RydWN0KGRlZmF1bHRzKSB7XG4gIHJldHVybiBjbGFzcyB7XG4gICAgY29uc3RydWN0b3IodXBkYXRlID0ge30pIHtcbiAgICAgIGxldCB0aGVfdmFsdWVzID0gT2JqZWN0LmFzc2lnbihkZWZhdWx0cywgdXBkYXRlKTtcbiAgICAgIE9iamVjdC5hc3NpZ24odGhpcywgdGhlX3ZhbHVlcyk7XG4gICAgfVxuXG4gICAgc3RhdGljIGNyZWF0ZSh1cGRhdGVzID0ge30pIHtcbiAgICAgIGxldCB4ID0gbmV3IHRoaXModXBkYXRlcyk7XG4gICAgICByZXR1cm4gT2JqZWN0LmZyZWV6ZSh4KTtcbiAgICB9XG4gIH07XG59XG5cbmZ1bmN0aW9uIGRlZnByb3RvY29sKHNwZWMpIHtcbiAgcmV0dXJuIG5ldyBQcm90b2NvbChzcGVjKTtcbn1cblxuZnVuY3Rpb24gZGVmaW1wbChwcm90b2NvbCwgdHlwZSwgaW1wbCkge1xuICBwcm90b2NvbC5pbXBsZW1lbnRhdGlvbih0eXBlLCBpbXBsKTtcbn1cblxudmFyIEtlcm5lbCA9IHtcbiAgU3BlY2lhbEZvcm1zLFxuICB0bCxcbiAgaGQsXG4gIGlzX25pbCxcbiAgaXNfYXRvbSxcbiAgaXNfYmluYXJ5LFxuICBpc19ib29sZWFuLFxuICBpc19mdW5jdGlvbixcbiAgaXNfZmxvYXQsXG4gIGlzX2ludGVnZXIsXG4gIGlzX2xpc3QsXG4gIGlzX21hcCxcbiAgaXNfbnVtYmVyLFxuICBpc190dXBsZSxcbiAgbGVuZ3RoLFxuICBpc19waWQsXG4gIGlzX3BvcnQsXG4gIGlzX3JlZmVyZW5jZSxcbiAgaXNfYml0c3RyaW5nLFxuICBpbjogX19pbl9fLFxuICBhYnMsXG4gIHJvdW5kLFxuICBlbGVtLFxuICByZW0sXG4gIGRpdixcbiAgYW5kLFxuICBvcixcbiAgbm90LFxuICBhcHBseSxcbiAgdG9fc3RyaW5nLFxuICBtYXRjaF9fcW1hcmtfXyxcbiAgZGVmc3RydWN0LFxuICBkZWZwcm90b2NvbCxcbiAgZGVmaW1wbFxufTtcblxubGV0IEF0b20gPSB7fTtcblxuQXRvbS50b19zdHJpbmcgPSBmdW5jdGlvbiAoYXRvbSkge1xuICByZXR1cm4gU3ltYm9sLmtleUZvcihhdG9tKTtcbn07XG5cbkF0b20udG9fY2hhcl9saXN0ID0gZnVuY3Rpb24gKGF0b20pIHtcbiAgcmV0dXJuIEF0b20udG9fc3RyaW5nKGF0b20pLnNwbGl0KCcnKTtcbn07XG5cbmxldCBJbnRlZ2VyID0ge1xuXG4gIGlzX2V2ZW46IGZ1bmN0aW9uIChuKSB7XG4gICAgcmV0dXJuIG4gJSAyID09PSAwO1xuICB9LFxuXG4gIGlzX29kZDogZnVuY3Rpb24gKG4pIHtcbiAgICByZXR1cm4gbiAlIDIgIT09IDA7XG4gIH0sXG5cbiAgcGFyc2U6IGZ1bmN0aW9uIChiaW4pIHtcbiAgICBsZXQgcmVzdWx0ID0gcGFyc2VJbnQoYmluKTtcblxuICAgIGlmIChpc05hTihyZXN1bHQpKSB7XG4gICAgICByZXR1cm4gS2VybmVsLlNwZWNpYWxGb3Jtcy5hdG9tKFwiZXJyb3JcIik7XG4gICAgfVxuXG4gICAgbGV0IGluZGV4T2ZEb3QgPSBiaW4uaW5kZXhPZihcIi5cIik7XG5cbiAgICBpZiAoaW5kZXhPZkRvdCA+PSAwKSB7XG4gICAgICByZXR1cm4gS2VybmVsLlNwZWNpYWxGb3Jtcy50dXBsZShyZXN1bHQsIGJpbi5zdWJzdHJpbmcoaW5kZXhPZkRvdCkpO1xuICAgIH1cblxuICAgIHJldHVybiBLZXJuZWwuU3BlY2lhbEZvcm1zLnR1cGxlKHJlc3VsdCwgXCJcIik7XG4gIH0sXG5cbiAgdG9fY2hhcl9saXN0OiBmdW5jdGlvbiAobnVtYmVyLCBiYXNlID0gMTApIHtcbiAgICByZXR1cm4gbnVtYmVyLnRvU3RyaW5nKGJhc2UpLnNwbGl0KFwiXCIpO1xuICB9LFxuXG4gIHRvX3N0cmluZzogZnVuY3Rpb24gKG51bWJlciwgYmFzZSA9IDEwKSB7XG4gICAgcmV0dXJuIG51bWJlci50b1N0cmluZyhiYXNlKTtcbiAgfVxufTtcblxubGV0IENoYXJzJDEgPSBLZXJuZWwuZGVmcHJvdG9jb2woe1xuICB0b19zdHJpbmc6IGZ1bmN0aW9uICh0aGluZykge31cbn0pO1xuXG5LZXJuZWwuZGVmaW1wbChDaGFycyQxLCBCaXRTdHJpbmcsIHtcbiAgdG9fc3RyaW5nOiBmdW5jdGlvbiAodGhpbmcpIHtcbiAgICBpZiAoS2VybmVsLmlzX2JpbmFyeSh0aGluZykpIHtcbiAgICAgIHJldHVybiB0aGluZztcbiAgICB9XG5cbiAgICByZXR1cm4gdGhpbmcudG9TdHJpbmcoKTtcbiAgfVxufSk7XG5cbktlcm5lbC5kZWZpbXBsKENoYXJzJDEsIFN5bWJvbCwge1xuICB0b19zdHJpbmc6IGZ1bmN0aW9uICh0aGluZykge1xuICAgIGlmIChuaWwpIHtcbiAgICAgIHJldHVybiBcIlwiO1xuICAgIH1cblxuICAgIHJldHVybiBBdG9tLnRvX3N0cmluZyh0aGluZyk7XG4gIH1cbn0pO1xuXG5LZXJuZWwuZGVmaW1wbChDaGFycyQxLCBJbnRlZ2VyJDEsIHtcbiAgdG9fc3RyaW5nOiBmdW5jdGlvbiAodGhpbmcpIHtcbiAgICByZXR1cm4gSW50ZWdlci50b19zdHJpbmcodGhpbmcpO1xuICB9XG59KTtcblxuS2VybmVsLmRlZmltcGwoQ2hhcnMkMSwgRmxvYXQsIHtcbiAgdG9fc3RyaW5nOiBmdW5jdGlvbiAodGhpbmcpIHtcbiAgICByZXR1cm4gdGhpbmcudG9TdHJpbmc7XG4gIH1cbn0pO1xuXG5LZXJuZWwuZGVmaW1wbChDaGFycyQxLCBBcnJheSwge1xuICB0b19zdHJpbmc6IGZ1bmN0aW9uICh0aGluZykge1xuICAgIHJldHVybiB0aGluZy50b1N0cmluZygpO1xuICB9XG59KTtcblxuS2VybmVsLmRlZmltcGwoQ2hhcnMkMSwgVHVwbGUkMSwge1xuICB0b19zdHJpbmc6IGZ1bmN0aW9uICh0aGluZykge1xuICAgIHJldHVybiBUdXBsZS50b19zdHJpbmcodGhpbmcpO1xuICB9XG59KTtcblxuS2VybmVsLmRlZmltcGwoQ2hhcnMkMSwgbnVsbCwge1xuICB0b19zdHJpbmc6IGZ1bmN0aW9uICh0aGluZykge1xuICAgIHJldHVybiB0aGluZy50b1N0cmluZygpO1xuICB9XG59KTtcblxuZnVuY3Rpb24gdG9fYXRvbShzdHJpbmcpIHtcbiAgcmV0dXJuIFN5bWJvbC5mb3Ioc3RyaW5nKTtcbn1cblxuZnVuY3Rpb24gdG9fZXhpc3RpbmdfYXRvbShzdHJpbmcpIHtcbiAgcmV0dXJuIFN5bWJvbC5mb3Ioc3RyaW5nKTtcbn1cblxuZnVuY3Rpb24gdG9fY2hhcl9saXN0KHN0cmluZykge1xuICByZXR1cm4gc3RyaW5nLnNwbGl0KCcnKTtcbn1cblxuZnVuY3Rpb24gdG9fZmxvYXQoc3RyaW5nKSB7XG4gIHJldHVybiBwYXJzZUZsb2F0KHN0cmluZyk7XG59XG5cbmZ1bmN0aW9uIHRvX2ludGVnZXIoc3RyaW5nLCBiYXNlID0gMTApIHtcbiAgcmV0dXJuIHBhcnNlSW50KHN0cmluZywgYmFzZSk7XG59XG5cbmZ1bmN0aW9uIHVwY2FzZShiaW5hcnkpIHtcbiAgcmV0dXJuIGJpbmFyeS50b1VwcGVyQ2FzZSgpO1xufVxuXG5mdW5jdGlvbiBkb3duY2FzZShiaW5hcnkpIHtcbiAgcmV0dXJuIGJpbmFyeS50b0xvd2VyQ2FzZSgpO1xufVxuXG5mdW5jdGlvbiBhdChzdHJpbmcsIHBvc2l0aW9uKSB7XG4gIGlmIChwb3NpdGlvbiA+IHN0cmluZy5sZW5ndGggLSAxKSB7XG4gICAgcmV0dXJuIG51bGw7XG4gIH1cblxuICByZXR1cm4gc3RyaW5nW3Bvc2l0aW9uXTtcbn1cblxuZnVuY3Rpb24gY2FwaXRhbGl6ZShzdHJpbmcpIHtcbiAgbGV0IHJldHVyblN0cmluZyA9ICcnO1xuXG4gIGZvciAobGV0IGkgPSAwOyBpIDwgc3RyaW5nLmxlbmd0aDsgaSsrKSB7XG4gICAgaWYgKGkgPT09IDApIHtcbiAgICAgIHJldHVyblN0cmluZyA9IHJldHVyblN0cmluZyArIHN0cmluZ1tpXS50b1VwcGVyQ2FzZSgpO1xuICAgIH0gZWxzZSB7XG4gICAgICByZXR1cm5TdHJpbmcgPSByZXR1cm5TdHJpbmcgKyBzdHJpbmdbaV0udG9Mb3dlckNhc2UoKTtcbiAgICB9XG4gIH1cblxuICByZXR1cm4gcmV0dXJuU3RyaW5nO1xufVxuXG5mdW5jdGlvbiBjb2RlcG9pbnRzKHN0cmluZykge1xuICByZXR1cm4gdG9fY2hhcl9saXN0KHN0cmluZykubWFwKGZ1bmN0aW9uIChjKSB7XG4gICAgcmV0dXJuIGMuY29kZVBvaW50QXQoMCk7XG4gIH0pO1xufVxuXG5mdW5jdGlvbiBjb250YWluc19fcW1fXyhzdHJpbmcsIGNvbnRhaW5zKSB7XG4gIGlmIChBcnJheS5pc0FycmF5KGNvbnRhaW5zKSkge1xuICAgIHJldHVybiBjb250YWlucy5zb21lKGZ1bmN0aW9uIChzKSB7XG4gICAgICByZXR1cm4gc3RyaW5nLmluZGV4T2YocykgPiAtMTtcbiAgICB9KTtcbiAgfVxuXG4gIHJldHVybiBzdHJpbmcuaW5kZXhPZihjb250YWlucykgPiAtMTtcbn1cblxuZnVuY3Rpb24gZHVwbGljYXRlJDEoc3ViamVjdCwgbikge1xuICByZXR1cm4gc3ViamVjdC5yZXBlYXQobik7XG59XG5cbmZ1bmN0aW9uIGVuZHNfd2l0aF9fcW1fXyhzdHJpbmcsIHN1ZmZpeGVzKSB7XG4gIGlmIChBcnJheS5pc0FycmF5KHN1ZmZpeGVzKSkge1xuICAgIHJldHVybiBzdWZmaXhlcy5zb21lKGZ1bmN0aW9uIChzKSB7XG4gICAgICByZXR1cm4gc3RyaW5nLmVuZHNXaXRoKHMpO1xuICAgIH0pO1xuICB9XG5cbiAgcmV0dXJuIHN0cmluZy5lbmRzV2l0aChzdWZmaXhlcyk7XG59XG5cbmZ1bmN0aW9uIGZpcnN0KHN0cmluZykge1xuICBpZiAoIXN0cmluZykge1xuICAgIHJldHVybiBudWxsO1xuICB9XG5cbiAgcmV0dXJuIHN0cmluZ1swXTtcbn1cblxuZnVuY3Rpb24gZ3JhcGhlbWVzKHN0cmluZykge1xuICByZXR1cm4gc3RyaW5nLnNwbGl0KCcnKTtcbn1cblxuZnVuY3Rpb24gbGFzdChzdHJpbmcpIHtcbiAgaWYgKCFzdHJpbmcpIHtcbiAgICByZXR1cm4gbnVsbDtcbiAgfVxuXG4gIHJldHVybiBzdHJpbmdbc3RyaW5nLmxlbmd0aCAtIDFdO1xufVxuXG5mdW5jdGlvbiBsZW5ndGgkMShzdHJpbmcpIHtcbiAgcmV0dXJuIHN0cmluZy5sZW5ndGg7XG59XG5cbmZ1bmN0aW9uIG1hdGNoX19xbV9fKHN0cmluZywgcmVnZXgpIHtcbiAgcmV0dXJuIHN0cmluZy5tYXRjaChyZWdleCkgIT0gbnVsbDtcbn1cblxuZnVuY3Rpb24gbmV4dF9jb2RlcG9pbnQoc3RyaW5nKSB7XG4gIGlmICghc3RyaW5nIHx8IHN0cmluZyA9PT0gJycpIHtcbiAgICByZXR1cm4gbnVsbDtcbiAgfVxuXG4gIHJldHVybiBLZXJuZWwuU3BlY2lhbEZvcm1zLnR1cGxlKHN0cmluZ1swXS5jb2RlUG9pbnRBdCgwKSwgc3RyaW5nLnN1YnN0cigxKSk7XG59XG5cbmZ1bmN0aW9uIG5leHRfZ3JhcGhlbWUoc3RyaW5nKSB7XG4gIGlmICghc3RyaW5nIHx8IHN0cmluZyA9PT0gJycpIHtcbiAgICByZXR1cm4gbnVsbDtcbiAgfVxuXG4gIHJldHVybiBLZXJuZWwuU3BlY2lhbEZvcm1zLnR1cGxlKHN0cmluZ1swXSwgc3RyaW5nLnN1YnN0cigxKSk7XG59XG5cbmZ1bmN0aW9uIHJldmVyc2Uoc3RyaW5nKSB7XG4gIGxldCByZXR1cm5WYWx1ZSA9ICcnO1xuXG4gIGZvciAodmFyIGkgPSBzdHJpbmcubGVuZ3RoIC0gMTsgaSA+PSAwOyBpLS0pIHtcbiAgICByZXR1cm5WYWx1ZSA9IHJldHVyblZhbHVlICsgc3RyaW5nW2ldO1xuICB9O1xuXG4gIHJldHVybiByZXR1cm5WYWx1ZTtcbn1cblxuZnVuY3Rpb24gc3BsaXQoc3RyaW5nKSB7XG4gIHJldHVybiBzdHJpbmcuc3BsaXQoKTtcbn1cblxuZnVuY3Rpb24gc3RhcnRzX3dpdGhfX3FtX18oc3RyaW5nLCBwcmVmaXhlcykge1xuICBpZiAoQXJyYXkuaXNBcnJheShwcmVmaXhlcykpIHtcbiAgICByZXR1cm4gcHJlZml4ZXMuc29tZShmdW5jdGlvbiAocykge1xuICAgICAgcmV0dXJuIHN0cmluZy5zdGFydHNXaXRoKHMpO1xuICAgIH0pO1xuICB9XG5cbiAgcmV0dXJuIHN0cmluZy5zdGFydHNXaXRoKHByZWZpeGVzKTtcbn1cblxuZnVuY3Rpb24gdmFsaWRfY2hhcmFjdGVyX19xbV9fKGNvZGVwb2ludCkge1xuICB0cnkge1xuICAgIHJldHVybiBTdHJpbmcuZnJvbUNvZGVQb2ludChjb2RlcG9pbnQpICE9IG51bGw7XG4gIH0gY2F0Y2ggKGUpIHtcbiAgICByZXR1cm4gZmFsc2U7XG4gIH1cbn1cblxudmFyIFN0cmluZyQxID0ge1xuICBhdCxcbiAgY2FwaXRhbGl6ZSxcbiAgY29kZXBvaW50cyxcbiAgY29udGFpbnNfX3FtX18sXG4gIGRvd25jYXNlLFxuICBkdXBsaWNhdGU6IGR1cGxpY2F0ZSQxLFxuICBlbmRzX3dpdGhfX3FtX18sXG4gIGZpcnN0LFxuICBncmFwaGVtZXMsXG4gIGxhc3QsXG4gIGxlbmd0aDogbGVuZ3RoJDEsXG4gIG1hdGNoX19xbV9fLFxuICBuZXh0X2NvZGVwb2ludCxcbiAgbmV4dF9ncmFwaGVtZSxcbiAgcmV2ZXJzZSxcbiAgc3BsaXQsXG4gIHN0YXJ0c193aXRoX19xbV9fLFxuICB0b19hdG9tLFxuICB0b19jaGFyX2xpc3QsXG4gIHRvX2V4aXN0aW5nX2F0b20sXG4gIHRvX2Zsb2F0LFxuICB0b19pbnRlZ2VyLFxuICB1cGNhc2UsXG4gIHZhbGlkX2NoYXJhY3Rlcl9fcW1fXyxcbiAgQ2hhcnM6IENoYXJzJDFcbn07XG5cbmxldCBDaGFycyA9IEtlcm5lbC5kZWZwcm90b2NvbCh7XG4gIHRvX2NoYXJfbGlzdDogZnVuY3Rpb24gKHRoaW5nKSB7fVxufSk7XG5cbktlcm5lbC5kZWZpbXBsKENoYXJzLCBCaXRTdHJpbmcsIHtcbiAgdG9fY2hhcl9saXN0OiBmdW5jdGlvbiAodGhpbmcpIHtcbiAgICBpZiAoS2VybmVsLmlzX2JpbmFyeSh0aGluZykpIHtcbiAgICAgIHJldHVybiBTdHJpbmckMS50b19jaGFyX2xpc3QodGhpbmcpO1xuICAgIH1cblxuICAgIHJldHVybiB0aGluZy50b1N0cmluZygpO1xuICB9XG59KTtcblxuS2VybmVsLmRlZmltcGwoQ2hhcnMsIFN5bWJvbCwge1xuICB0b19jaGFyX2xpc3Q6IGZ1bmN0aW9uICh0aGluZykge1xuICAgIHJldHVybiBBdG9tLnRvX2NoYXJfbGlzdCh0aGluZyk7XG4gIH1cbn0pO1xuXG5LZXJuZWwuZGVmaW1wbChDaGFycywgSW50ZWdlciQxLCB7XG4gIHRvX2NoYXJfbGlzdDogZnVuY3Rpb24gKHRoaW5nKSB7XG4gICAgcmV0dXJuIEludGVnZXIudG9fY2hhcl9saXN0KHRoaW5nKTtcbiAgfVxufSk7XG5cbktlcm5lbC5kZWZpbXBsKENoYXJzLCBBcnJheSwge1xuICB0b19jaGFyX2xpc3Q6IGZ1bmN0aW9uICh0aGluZykge1xuICAgIHJldHVybiB0aGluZztcbiAgfVxufSk7XG5cbmxldCBMaXN0ID0ge307XG5cbkxpc3QuQ2hhcnMgPSBDaGFycztcblxuTGlzdC5kZWxldGUgPSBmdW5jdGlvbiAobGlzdCwgaXRlbSkge1xuICBsZXQgbmV3X3ZhbHVlID0gW107XG4gIGxldCB2YWx1ZV9mb3VuZCA9IGZhbHNlO1xuXG4gIGZvciAobGV0IHggb2YgbGlzdCkge1xuICAgIGlmICh4ID09PSBpdGVtICYmIHZhbHVlX2ZvdW5kICE9PSBmYWxzZSkge1xuICAgICAgbmV3X3ZhbHVlLnB1c2goeCk7XG4gICAgICB2YWx1ZV9mb3VuZCA9IHRydWU7XG4gICAgfSBlbHNlIGlmICh4ICE9PSBpdGVtKSB7XG4gICAgICBuZXdfdmFsdWUucHVzaCh4KTtcbiAgICB9XG4gIH1cblxuICByZXR1cm4gS2VybmVsLlNwZWNpYWxGb3Jtcy5saXN0KC4uLm5ld192YWx1ZSk7XG59O1xuXG5MaXN0LmRlbGV0ZV9hdCA9IGZ1bmN0aW9uIChsaXN0LCBpbmRleCkge1xuICBsZXQgbmV3X3ZhbHVlID0gW107XG5cbiAgZm9yIChsZXQgaSA9IDA7IGkgPCBsaXN0Lmxlbmd0aDsgaSsrKSB7XG4gICAgaWYgKGkgIT09IGluZGV4KSB7XG4gICAgICBuZXdfdmFsdWUucHVzaChsaXN0W2ldKTtcbiAgICB9XG4gIH1cblxuICByZXR1cm4gS2VybmVsLlNwZWNpYWxGb3Jtcy5saXN0KC4uLm5ld192YWx1ZSk7XG59O1xuXG5MaXN0LmR1cGxpY2F0ZSA9IGZ1bmN0aW9uIChlbGVtLCBuKSB7XG4gIGxldCBuZXdfdmFsdWUgPSBbXTtcblxuICBmb3IgKHZhciBpID0gMDsgaSA8IG47IGkrKykge1xuICAgIG5ld192YWx1ZS5wdXNoKGVsZW0pO1xuICB9XG5cbiAgcmV0dXJuIEtlcm5lbC5TcGVjaWFsRm9ybXMubGlzdCguLi5uZXdfdmFsdWUpO1xufTtcblxuTGlzdC5maXJzdCA9IGZ1bmN0aW9uIChsaXN0KSB7XG4gIHJldHVybiBsaXN0WzBdO1xufTtcblxuTGlzdC5mbGF0dGVuID0gZnVuY3Rpb24gKGxpc3QsIHRhaWwgPSBLZXJuZWwuU3BlY2lhbEZvcm1zLmxpc3QoKSkge1xuICBsZXQgbmV3X3ZhbHVlID0gW107XG5cbiAgZm9yIChsZXQgeCBvZiBsaXN0KSB7XG4gICAgaWYgKEtlcm5lbC5pc19saXN0KHgpKSB7XG4gICAgICBuZXdfdmFsdWUgPSBuZXdfdmFsdWUuY29uY2F0KExpc3QuZmxhdHRlbih4KSk7XG4gICAgfSBlbHNlIHtcbiAgICAgIG5ld192YWx1ZS5wdXNoKHgpO1xuICAgIH1cbiAgfVxuXG4gIG5ld192YWx1ZSA9IG5ld192YWx1ZS5jb25jYXQodGFpbCk7XG5cbiAgcmV0dXJuIEtlcm5lbC5TcGVjaWFsRm9ybXMubGlzdCguLi5uZXdfdmFsdWUpO1xufTtcblxuTGlzdC5mb2xkbCA9IGZ1bmN0aW9uIChsaXN0LCBhY2MsIGZ1bmMpIHtcbiAgcmV0dXJuIGxpc3QucmVkdWNlKGZ1bmMsIGFjYyk7XG59O1xuXG5MaXN0LmZvbGRyID0gZnVuY3Rpb24gKGxpc3QsIGFjYywgZnVuYykge1xuICBsZXQgbmV3X2FjYyA9IGFjYztcblxuICBmb3IgKHZhciBpID0gbGlzdC5sZW5ndGggLSAxOyBpID49IDA7IGktLSkge1xuICAgIG5ld19hY2MgPSBmdW5jKGxpc3RbaV0sIG5ld19hY2MpO1xuICB9XG5cbiAgcmV0dXJuIG5ld19hY2M7XG59O1xuXG5MaXN0Lmluc2VydF9hdCA9IGZ1bmN0aW9uIChsaXN0LCBpbmRleCwgdmFsdWUpIHtcbiAgbGV0IG5ld192YWx1ZSA9IFtdO1xuXG4gIGZvciAobGV0IGkgPSAwOyBpIDwgbGlzdC5sZW5ndGg7IGkrKykge1xuICAgIGlmIChpID09PSBpbmRleCkge1xuICAgICAgbmV3X3ZhbHVlLnB1c2godmFsdWUpO1xuICAgICAgbmV3X3ZhbHVlLnB1c2gobGlzdFtpXSk7XG4gICAgfSBlbHNlIHtcbiAgICAgIG5ld192YWx1ZS5wdXNoKGxpc3RbaV0pO1xuICAgIH1cbiAgfVxuXG4gIHJldHVybiBLZXJuZWwuU3BlY2lhbEZvcm1zLmxpc3QoLi4ubmV3X3ZhbHVlKTtcbn07XG5cbkxpc3Qua2V5ZGVsZXRlID0gZnVuY3Rpb24gKGxpc3QsIGtleSwgcG9zaXRpb24pIHtcbiAgbGV0IG5ld19saXN0ID0gW107XG5cbiAgZm9yIChsZXQgaSA9IDA7IGkgPCBsaXN0Lmxlbmd0aDsgaSsrKSB7XG4gICAgaWYgKCFLZXJuZWwubWF0Y2hfX3FtYXJrX18obGlzdFtpXVtwb3NpdGlvbl0sIGtleSkpIHtcbiAgICAgIG5ld19saXN0LnB1c2gobGlzdFtpXSk7XG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIEtlcm5lbC5TcGVjaWFsRm9ybXMubGlzdCguLi5uZXdfbGlzdCk7XG59O1xuXG5MaXN0LmtleWZpbmQgPSBmdW5jdGlvbiAobGlzdCwga2V5LCBwb3NpdGlvbiwgX2RlZmF1bHQgPSBudWxsKSB7XG5cbiAgZm9yIChsZXQgaSA9IDA7IGkgPCBsaXN0Lmxlbmd0aDsgaSsrKSB7XG4gICAgaWYgKEtlcm5lbC5tYXRjaF9fcW1hcmtfXyhsaXN0W2ldW3Bvc2l0aW9uXSwga2V5KSkge1xuICAgICAgcmV0dXJuIGxpc3RbaV07XG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIF9kZWZhdWx0O1xufTtcblxuTGlzdC5rZXltZW1iZXJfX3FtYXJrX18gPSBmdW5jdGlvbiAobGlzdCwga2V5LCBwb3NpdGlvbikge1xuXG4gIGZvciAobGV0IGkgPSAwOyBpIDwgbGlzdC5sZW5ndGg7IGkrKykge1xuICAgIGlmIChLZXJuZWwubWF0Y2hfX3FtYXJrX18obGlzdFtpXVtwb3NpdGlvbl0sIGtleSkpIHtcbiAgICAgIHJldHVybiB0cnVlO1xuICAgIH1cbiAgfVxuXG4gIHJldHVybiBmYWxzZTtcbn07XG5cbkxpc3Qua2V5cmVwbGFjZSA9IGZ1bmN0aW9uIChsaXN0LCBrZXksIHBvc2l0aW9uLCBuZXdfdHVwbGUpIHtcbiAgbGV0IG5ld19saXN0ID0gW107XG5cbiAgZm9yIChsZXQgaSA9IDA7IGkgPCBsaXN0Lmxlbmd0aDsgaSsrKSB7XG4gICAgaWYgKCFLZXJuZWwubWF0Y2hfX3FtYXJrX18obGlzdFtpXVtwb3NpdGlvbl0sIGtleSkpIHtcbiAgICAgIG5ld19saXN0LnB1c2gobGlzdFtpXSk7XG4gICAgfSBlbHNlIHtcbiAgICAgIG5ld19saXN0LnB1c2gobmV3X3R1cGxlKTtcbiAgICB9XG4gIH1cblxuICByZXR1cm4gS2VybmVsLlNwZWNpYWxGb3Jtcy5saXN0KC4uLm5ld19saXN0KTtcbn07XG5cbkxpc3Qua2V5c29ydCA9IGZ1bmN0aW9uIChsaXN0LCBwb3NpdGlvbikge1xuICBsZXQgbmV3X2xpc3QgPSBsaXN0O1xuXG4gIG5ld19saXN0LnNvcnQoZnVuY3Rpb24gKGEsIGIpIHtcbiAgICBpZiAocG9zaXRpb24gPT09IDApIHtcbiAgICAgIGlmIChhW3Bvc2l0aW9uXS52YWx1ZSA8IGJbcG9zaXRpb25dLnZhbHVlKSB7XG4gICAgICAgIHJldHVybiAtMTtcbiAgICAgIH1cblxuICAgICAgaWYgKGFbcG9zaXRpb25dLnZhbHVlID4gYltwb3NpdGlvbl0udmFsdWUpIHtcbiAgICAgICAgcmV0dXJuIDE7XG4gICAgICB9XG5cbiAgICAgIHJldHVybiAwO1xuICAgIH0gZWxzZSB7XG4gICAgICBpZiAoYVtwb3NpdGlvbl0gPCBiW3Bvc2l0aW9uXSkge1xuICAgICAgICByZXR1cm4gLTE7XG4gICAgICB9XG5cbiAgICAgIGlmIChhW3Bvc2l0aW9uXSA+IGJbcG9zaXRpb25dKSB7XG4gICAgICAgIHJldHVybiAxO1xuICAgICAgfVxuXG4gICAgICByZXR1cm4gMDtcbiAgICB9XG4gIH0pO1xuXG4gIHJldHVybiBLZXJuZWwuU3BlY2lhbEZvcm1zLmxpc3QoLi4ubmV3X2xpc3QpO1xufTtcblxuTGlzdC5rZXlzdG9yZSA9IGZ1bmN0aW9uIChsaXN0LCBrZXksIHBvc2l0aW9uLCBuZXdfdHVwbGUpIHtcbiAgbGV0IG5ld19saXN0ID0gW107XG4gIGxldCByZXBsYWNlZCA9IGZhbHNlO1xuXG4gIGZvciAobGV0IGkgPSAwOyBpIDwgbGlzdC5sZW5ndGg7IGkrKykge1xuICAgIGlmICghS2VybmVsLm1hdGNoX19xbWFya19fKGxpc3RbaV1bcG9zaXRpb25dLCBrZXkpKSB7XG4gICAgICBuZXdfbGlzdC5wdXNoKGxpc3RbaV0pO1xuICAgIH0gZWxzZSB7XG4gICAgICBuZXdfbGlzdC5wdXNoKG5ld190dXBsZSk7XG4gICAgICByZXBsYWNlZCA9IHRydWU7XG4gICAgfVxuICB9XG5cbiAgaWYgKCFyZXBsYWNlZCkge1xuICAgIG5ld19saXN0LnB1c2gobmV3X3R1cGxlKTtcbiAgfVxuXG4gIHJldHVybiBLZXJuZWwuU3BlY2lhbEZvcm1zLmxpc3QoLi4ubmV3X2xpc3QpO1xufTtcblxuTGlzdC5sYXN0ID0gZnVuY3Rpb24gKGxpc3QpIHtcbiAgcmV0dXJuIGxpc3RbbGlzdC5sZW5ndGggLSAxXTtcbn07XG5cbkxpc3QucmVwbGFjZV9hdCA9IGZ1bmN0aW9uIChsaXN0LCBpbmRleCwgdmFsdWUpIHtcbiAgbGV0IG5ld192YWx1ZSA9IFtdO1xuXG4gIGZvciAobGV0IGkgPSAwOyBpIDwgbGlzdC5sZW5ndGg7IGkrKykge1xuICAgIGlmIChpID09PSBpbmRleCkge1xuICAgICAgbmV3X3ZhbHVlLnB1c2godmFsdWUpO1xuICAgIH0gZWxzZSB7XG4gICAgICBuZXdfdmFsdWUucHVzaChsaXN0W2ldKTtcbiAgICB9XG4gIH1cblxuICByZXR1cm4gS2VybmVsLlNwZWNpYWxGb3Jtcy5saXN0KC4uLm5ld192YWx1ZSk7XG59O1xuXG5MaXN0LnVwZGF0ZV9hdCA9IGZ1bmN0aW9uIChsaXN0LCBpbmRleCwgZnVuKSB7XG4gIGxldCBuZXdfdmFsdWUgPSBbXTtcblxuICBmb3IgKGxldCBpID0gMDsgaSA8IGxpc3QuY291bnQoKTsgaSsrKSB7XG4gICAgaWYgKGkgPT09IGluZGV4KSB7XG4gICAgICBuZXdfdmFsdWUucHVzaChmdW4obGlzdC5nZXQoaSkpKTtcbiAgICB9IGVsc2Uge1xuICAgICAgbmV3X3ZhbHVlLnB1c2gobGlzdC5nZXQoaSkpO1xuICAgIH1cbiAgfVxuXG4gIHJldHVybiBuZXdfdmFsdWU7XG59O1xuXG5MaXN0LndyYXAgPSBmdW5jdGlvbiAobGlzdCkge1xuICBpZiAoS2VybmVsLmlzX2xpc3QobGlzdCkpIHtcbiAgICByZXR1cm4gbGlzdDtcbiAgfSBlbHNlIGlmIChsaXN0ID09IG51bGwpIHtcbiAgICByZXR1cm4gS2VybmVsLlNwZWNpYWxGb3Jtcy5saXN0KCk7XG4gIH0gZWxzZSB7XG4gICAgcmV0dXJuIEtlcm5lbC5TcGVjaWFsRm9ybXMubGlzdChsaXN0KTtcbiAgfVxufTtcblxuTGlzdC56aXAgPSBmdW5jdGlvbiAobGlzdF9vZl9saXN0cykge1xuICBpZiAobGlzdF9vZl9saXN0cy5sZW5ndGggPT09IDApIHtcbiAgICByZXR1cm4gS2VybmVsLlNwZWNpYWxGb3Jtcy5saXN0KCk7XG4gIH1cblxuICBsZXQgbmV3X3ZhbHVlID0gW107XG4gIGxldCBzbWFsbGVzdF9sZW5ndGggPSBsaXN0X29mX2xpc3RzWzBdO1xuXG4gIGZvciAobGV0IHggb2YgbGlzdF9vZl9saXN0cykge1xuICAgIGlmICh4Lmxlbmd0aCA8IHNtYWxsZXN0X2xlbmd0aCkge1xuICAgICAgc21hbGxlc3RfbGVuZ3RoID0geC5sZW5ndGg7XG4gICAgfVxuICB9XG5cbiAgZm9yIChsZXQgaSA9IDA7IGkgPCBzbWFsbGVzdF9sZW5ndGg7IGkrKykge1xuICAgIGxldCBjdXJyZW50X3ZhbHVlID0gW107XG4gICAgZm9yIChsZXQgaiA9IDA7IGogPCBsaXN0X29mX2xpc3RzLmxlbmd0aDsgaisrKSB7XG4gICAgICBjdXJyZW50X3ZhbHVlLnB1c2gobGlzdF9vZl9saXN0c1tqXVtpXSk7XG4gICAgfVxuXG4gICAgbmV3X3ZhbHVlLnB1c2goS2VybmVsLlNwZWNpYWxGb3Jtcy50dXBsZSguLi5jdXJyZW50X3ZhbHVlKSk7XG4gIH1cblxuICByZXR1cm4gS2VybmVsLlNwZWNpYWxGb3Jtcy5saXN0KC4uLm5ld192YWx1ZSk7XG59O1xuXG5MaXN0LnRvX3R1cGxlID0gZnVuY3Rpb24gKGxpc3QpIHtcbiAgcmV0dXJuIEtlcm5lbC5TcGVjaWFsRm9ybXMudHVwbGUuYXBwbHkobnVsbCwgbGlzdCk7XG59O1xuXG5MaXN0LmFwcGVuZCA9IGZ1bmN0aW9uIChsaXN0LCB2YWx1ZSkge1xuICByZXR1cm4gS2VybmVsLlNwZWNpYWxGb3Jtcy5saXN0KC4uLmxpc3QuY29uY2F0KFt2YWx1ZV0pKTtcbn07XG5cbkxpc3QucHJlcGVuZCA9IGZ1bmN0aW9uIChsaXN0LCB2YWx1ZSkge1xuICByZXR1cm4gS2VybmVsLlNwZWNpYWxGb3Jtcy5saXN0KC4uLlt2YWx1ZV0uY29uY2F0KGxpc3QpKTtcbn07XG5cbkxpc3QuY29uY2F0ID0gZnVuY3Rpb24gKGxlZnQsIHJpZ2h0KSB7XG4gIHJldHVybiBsZWZ0LmNvbmNhdChyaWdodCk7XG59O1xuXG5sZXQgUmFuZ2UgPSBmdW5jdGlvbiAoX2ZpcnN0LCBfbGFzdCkge1xuICBpZiAoISh0aGlzIGluc3RhbmNlb2YgUmFuZ2UpKSB7XG4gICAgcmV0dXJuIG5ldyBSYW5nZShfZmlyc3QsIF9sYXN0KTtcbiAgfVxuXG4gIHRoaXMuZmlyc3QgPSBmdW5jdGlvbiAoKSB7XG4gICAgcmV0dXJuIF9maXJzdDtcbiAgfTtcblxuICB0aGlzLmxhc3QgPSBmdW5jdGlvbiAoKSB7XG4gICAgcmV0dXJuIF9sYXN0O1xuICB9O1xuXG4gIGxldCBfcmFuZ2UgPSBbXTtcblxuICBmb3IgKGxldCBpID0gX2ZpcnN0OyBpIDw9IF9sYXN0OyBpKyspIHtcbiAgICBfcmFuZ2UucHVzaChpKTtcbiAgfVxuXG4gIF9yYW5nZSA9IE9iamVjdC5mcmVlemUoX3JhbmdlKTtcblxuICB0aGlzLnZhbHVlID0gZnVuY3Rpb24gKCkge1xuICAgIHJldHVybiBfcmFuZ2U7XG4gIH07XG5cbiAgdGhpcy5sZW5ndGggPSBmdW5jdGlvbiAoKSB7XG4gICAgcmV0dXJuIF9yYW5nZS5sZW5ndGg7XG4gIH07XG5cbiAgcmV0dXJuIHRoaXM7XG59O1xuXG5SYW5nZS5wcm90b3R5cGVbU3ltYm9sLml0ZXJhdG9yXSA9IGZ1bmN0aW9uICgpIHtcbiAgcmV0dXJuIHRoaXMudmFsdWUoKVtTeW1ib2wuaXRlcmF0b3JdKCk7XG59O1xuXG5SYW5nZS5uZXcgPSBmdW5jdGlvbiAoZmlyc3QsIGxhc3QpIHtcbiAgcmV0dXJuIFJhbmdlKGZpcnN0LCBsYXN0KTtcbn07XG5cblJhbmdlLnJhbmdlX19xbWFya19fID0gZnVuY3Rpb24gKHJhbmdlKSB7XG4gIHJldHVybiByYW5nZSBpbnN0YW5jZW9mIFJhbmdlO1xufTtcblxubGV0IEtleXdvcmQgPSB7fTtcblxuS2V5d29yZC5oYXNfa2V5X19xbV9fID0gZnVuY3Rpb24gKGtleXdvcmRzLCBrZXkpIHtcbiAgZm9yIChsZXQga2V5d29yZCBvZiBrZXl3b3Jkcykge1xuICAgIGlmIChLZXJuZWwuZWxlbShrZXl3b3JkLCAwKSA9PSBrZXkpIHtcbiAgICAgIHJldHVybiB0cnVlO1xuICAgIH1cbiAgfVxuXG4gIHJldHVybiBmYWxzZTtcbn07XG5cbktleXdvcmQuZ2V0ID0gZnVuY3Rpb24gKGtleXdvcmRzLCBrZXksIHRoZV9kZWZhdWx0ID0gbnVsbCkge1xuICBmb3IgKGxldCBrZXl3b3JkIG9mIGtleXdvcmRzKSB7XG4gICAgaWYgKEtlcm5lbC5lbGVtKGtleXdvcmQsIDApID09IGtleSkge1xuICAgICAgcmV0dXJuIEtlcm5lbC5lbGVtKGtleXdvcmQsIDEpO1xuICAgIH1cbiAgfVxuXG4gIHJldHVybiB0aGVfZGVmYXVsdDtcbn07XG5cbmxldCBBZ2VudCA9IHt9O1xuXG5BZ2VudC5zdGFydCA9IGZ1bmN0aW9uIChmdW4sIG9wdGlvbnMgPSBbXSkge1xuICBsZXQgcGlkID0gc2VsZi5wcm9jZXNzZXMuc3Bhd24oKTtcblxuICBpZiAoS2V5d29yZC5oYXNfa2V5X19xbV9fKG9wdGlvbnMsIEtlcm5lbC5TcGVjaWFsRm9ybXMuYXRvbSgnbmFtZScpKSkge1xuICAgIHBpZCA9IHNlbGYucHJvY2Vzc2VzLnJlZ2lzdGVyKEtleXdvcmQuZ2V0KG9wdGlvbnMsIEtlcm5lbC5TcGVjaWFsRm9ybXMuYXRvbSgnbmFtZScpKSwgcGlkKTtcbiAgfVxuXG4gIHNlbGYucHJvY2Vzc2VzLnB1dChwaWQsICdzdGF0ZScsIGZ1bigpKTtcbiAgcmV0dXJuIEtlcm5lbC5TcGVjaWFsRm9ybXMudHVwbGUoS2VybmVsLlNwZWNpYWxGb3Jtcy5hdG9tKCdvaycpLCBwaWQpO1xufTtcblxuQWdlbnQuc3RvcCA9IGZ1bmN0aW9uIChhZ2VudCwgdGltZW91dCA9IDUwMDApIHtcbiAgc2VsZi5wcm9jZXNzZXMuZXhpdChhZ2VudCk7XG4gIHJldHVybiBLZXJuZWwuU3BlY2lhbEZvcm1zLmF0b20oJ29rJyk7XG59O1xuXG5BZ2VudC51cGRhdGUgPSBmdW5jdGlvbiAoYWdlbnQsIGZ1biwgdGltZW91dCA9IDUwMDApIHtcblxuICBjb25zdCBjdXJyZW50X3N0YXRlID0gc2VsZi5wcm9jZXNzZXMuZ2V0KGFnZW50LCAnc3RhdGUnKTtcbiAgc2VsZi5wcm9jZXNzZXMucHV0KGFnZW50LCAnc3RhdGUnLCBmdW4oY3VycmVudF9zdGF0ZSkpO1xuXG4gIHJldHVybiBLZXJuZWwuU3BlY2lhbEZvcm1zLmF0b20oJ29rJyk7XG59O1xuXG5BZ2VudC5nZXQgPSBmdW5jdGlvbiAoYWdlbnQsIGZ1biwgdGltZW91dCA9IDUwMDApIHtcbiAgcmV0dXJuIGZ1bihzZWxmLnByb2Nlc3Nlcy5nZXQoYWdlbnQsICdzdGF0ZScpKTtcbn07XG5cbkFnZW50LmdldF9hbmRfdXBkYXRlID0gZnVuY3Rpb24gKGFnZW50LCBmdW4sIHRpbWVvdXQgPSA1MDAwKSB7XG5cbiAgY29uc3QgZ2V0X2FuZF91cGRhdGVfdHVwbGUgPSBmdW4oc2VsZi5wcm9jZXNzZXMuZ2V0KGFnZW50LCAnc3RhdGUnKSk7XG4gIHNlbGYucHJvY2Vzc2VzLnB1dChhZ2VudCwgJ3N0YXRlJywgS2VybmVsLmVsZW0oZ2V0X2FuZF91cGRhdGVfdHVwbGUsIDEpKTtcblxuICByZXR1cm4gS2VybmVsLmVsZW0oZ2V0X2FuZF91cGRhdGVfdHVwbGUsIDApO1xufTtcblxuLy9odHRwczovL2RldmVsb3Blci5tb3ppbGxhLm9yZy9lbi1VUy9kb2NzL1dlYi9BUEkvV2luZG93QmFzZTY0L0Jhc2U2NF9lbmNvZGluZ19hbmRfZGVjb2RpbmcjU29sdXRpb25fMl8lRTIlODAlOTNfcmV3cml0ZV90aGVfRE9Nc19hdG9iKClfYW5kX2J0b2EoKV91c2luZ19KYXZhU2NyaXB0J3NfVHlwZWRBcnJheXNfYW5kX1VURi04XG5mdW5jdGlvbiBiNjRFbmNvZGVVbmljb2RlKHN0cikge1xuICByZXR1cm4gYnRvYShlbmNvZGVVUklDb21wb25lbnQoc3RyKS5yZXBsYWNlKC8lKFswLTlBLUZdezJ9KS9nLCBmdW5jdGlvbiAobWF0Y2gsIHAxKSB7XG4gICAgcmV0dXJuIFN0cmluZy5mcm9tQ2hhckNvZGUoJzB4JyArIHAxKTtcbiAgfSkpO1xufVxuXG5mdW5jdGlvbiBlbmNvZGU2NChkYXRhKSB7XG4gIHJldHVybiBiNjRFbmNvZGVVbmljb2RlKGRhdGEpO1xufVxuXG5mdW5jdGlvbiBkZWNvZGU2NChkYXRhKSB7XG4gIHRyeSB7XG4gICAgcmV0dXJuIEtlcm5lbC5TcGVjaWFsRm9ybXMudHVwbGUoS2VybmVsLlNwZWNpYWxGb3Jtcy5hdG9tKCdvaycpLCBhdG9iKGRhdGEpKTtcbiAgfSBjYXRjaCAoZSkge1xuICAgIHJldHVybiBLZXJuZWwuU3BlY2lhbEZvcm1zLmF0b20oJ2Vycm9yJyk7XG4gIH1cblxuICByZXR1cm4gYnRvYShkYXRhKTtcbn1cblxuZnVuY3Rpb24gZGVjb2RlNjRfX2VtX18oZGF0YSkge1xuICByZXR1cm4gYXRvYihkYXRhKTtcbn1cblxudmFyIGJhc2UgPSB7XG4gIGVuY29kZTY0LFxuICBkZWNvZGU2NCxcbiAgZGVjb2RlNjRfX2VtX19cbn07XG5cbmZ1bmN0aW9uIGJub3QoZXhwcikge1xuICByZXR1cm4gfmV4cHI7XG59XG5cbmZ1bmN0aW9uIGJhbmQobGVmdCwgcmlnaHQpIHtcbiAgcmV0dXJuIGxlZnQgJiByaWdodDtcbn1cblxuZnVuY3Rpb24gYm9yKGxlZnQsIHJpZ2h0KSB7XG4gIHJldHVybiBsZWZ0IHwgcmlnaHQ7XG59XG5cbmZ1bmN0aW9uIGJzbChsZWZ0LCByaWdodCkge1xuICByZXR1cm4gbGVmdCA8PCByaWdodDtcbn1cblxuZnVuY3Rpb24gYnNyKGxlZnQsIHJpZ2h0KSB7XG4gIHJldHVybiBsZWZ0ID4+IHJpZ2h0O1xufVxuXG5mdW5jdGlvbiBieG9yKGxlZnQsIHJpZ2h0KSB7XG4gIHJldHVybiBsZWZ0IF4gcmlnaHQ7XG59XG5cbnZhciBiaXR3aXNlID0ge1xuICBibm90LFxuICBiYW5kLFxuICBib3IsXG4gIGJzbCxcbiAgYnNyLFxuICBieG9yXG59O1xuXG5sZXQgRW51bWVyYWJsZSA9IEtlcm5lbC5kZWZwcm90b2NvbCh7XG4gIGNvdW50OiBmdW5jdGlvbiAoY29sbGVjdGlvbikge30sXG4gIG1lbWJlcl9xbWFya19fOiBmdW5jdGlvbiAoY29sbGVjdGlvbiwgdmFsdWUpIHt9LFxuICByZWR1Y2U6IGZ1bmN0aW9uIChjb2xsZWN0aW9uLCBhY2MsIGZ1bikge31cbn0pO1xuXG5sZXQgQ29sbGVjdGFibGUgPSBLZXJuZWwuZGVmcHJvdG9jb2woe1xuICBpbnRvOiBmdW5jdGlvbiAoY29sbGVjdGFibGUpIHt9XG59KTtcblxubGV0IEluc3BlY3QgPSBLZXJuZWwuZGVmcHJvdG9jb2woe1xuICBpbnNwZWN0OiBmdW5jdGlvbiAodGhpbmcsIG9wdHMpIHt9XG59KTtcblxuZnVuY3Rpb24gX19uZXdfXygpIHtcbiAgcmV0dXJuIFNwZWNpYWxGb3Jtcy5tYXAoe30pO1xufVxuXG5mdW5jdGlvbiBrZXlzKG1hcCkge1xuICByZXR1cm4gT2JqZWN0LmtleXMobWFwKS5jb25jYXQoT2JqZWN0LmdldE93blByb3BlcnR5U3ltYm9scyhtYXApKTtcbn1cblxuZnVuY3Rpb24gc2l6ZShtYXApIHtcbiAgcmV0dXJuIGtleXMobWFwKS5sZW5ndGg7XG59XG5cbmZ1bmN0aW9uIHRvX2xpc3QkMShtYXApIHtcbiAgbGV0IG1hcF9rZXlzID0ga2V5cyhtYXApO1xuICBsZXQgbGlzdCA9IFtdO1xuXG4gIGZvciAobGV0IGtleSBvZiBtYXBfa2V5cykge1xuICAgIGxpc3QucHVzaChTcGVjaWFsRm9ybXMudHVwbGUoa2V5LCBtYXBba2V5XSkpO1xuICB9XG5cbiAgcmV0dXJuIFNwZWNpYWxGb3Jtcy5saXN0KC4uLmxpc3QpO1xufVxuXG5mdW5jdGlvbiB2YWx1ZXMobWFwKSB7XG4gIGxldCBtYXBfa2V5cyA9IGtleXMobWFwKTtcbiAgbGV0IGxpc3QgPSBbXTtcblxuICBmb3IgKGxldCBrZXkgb2YgbWFwX2tleXMpIHtcbiAgICBsaXN0LnB1c2gobWFwW2tleV0pO1xuICB9XG5cbiAgcmV0dXJuIFNwZWNpYWxGb3Jtcy5saXN0KC4uLmxpc3QpO1xufVxuXG5mdW5jdGlvbiBmcm9tX3N0cnVjdChzdHJ1Y3QpIHtcbiAgbGV0IG1hcCA9IE9iamVjdC5hc3NpZ24oe30sIHN0cnVjdCk7XG4gIGRlbGV0ZSBtYXBbU3ltYm9sLmZvcihcIl9fc3RydWN0X19cIildO1xuXG4gIHJldHVybiBTcGVjaWFsRm9ybXMubWFwKG1hcCk7XG59XG5cbmZ1bmN0aW9uIF9fZGVsZXRlX18obWFwLCBrZXkpIHtcbiAgbGV0IG5ld19tYXAgPSBPYmplY3QuYXNzaWduKHt9LCBtYXApO1xuXG4gIGRlbGV0ZSBuZXdfbWFwW2tleV07XG5cbiAgcmV0dXJuIFNwZWNpYWxGb3Jtcy5tYXAobmV3X21hcCk7XG59XG5cbmZ1bmN0aW9uIGVxdWFsX19xbWFya19fKG1hcDEsIG1hcDIpIHtcbiAgcmV0dXJuIG1hcDEgPT09IG1hcDI7XG59XG5cbmZ1bmN0aW9uIGZldGNoX19lbWFya19fKG1hcCwga2V5KSB7XG4gIGlmIChrZXkgaW4gbWFwKSB7XG4gICAgcmV0dXJuIG1hcFtrZXldO1xuICB9XG5cbiAgdGhyb3cgbmV3IEVycm9yKFwiS2V5IG5vdCBmb3VuZC5cIik7XG59XG5cbmZ1bmN0aW9uIGZldGNoKG1hcCwga2V5KSB7XG4gIGlmIChrZXkgaW4gbWFwKSB7XG4gICAgcmV0dXJuIFNwZWNpYWxGb3Jtcy50dXBsZShTcGVjaWFsRm9ybXMuYXRvbShcIm9rXCIpLCBtYXBba2V5XSk7XG4gIH1cblxuICByZXR1cm4gU3BlY2lhbEZvcm1zLmF0b20oXCJlcnJvclwiKTtcbn1cblxuZnVuY3Rpb24gaGFzX2tleV9fcW1hcmtfXyhtYXAsIGtleSkge1xuICByZXR1cm4ga2V5IGluIG1hcDtcbn1cblxuZnVuY3Rpb24gc3BsaXQkMShtYXAsIGtleXMpIHtcbiAgbGV0IHNwbGl0MSA9IHt9O1xuICBsZXQgc3BsaXQyID0ge307XG5cbiAgZm9yIChsZXQga2V5IG9mIE9iamVjdC5rZXlzKG1hcCkuY29uY2F0KE9iamVjdC5nZXRPd25Qcm9wZXJ0eVN5bWJvbHMobWFwKSkpIHtcbiAgICBpZiAoa2V5cy5pbmRleE9mKGtleSkgPiAtMSkge1xuICAgICAgc3BsaXQxW2tleV0gPSBtYXBba2V5XTtcbiAgICB9IGVsc2Uge1xuICAgICAgc3BsaXQyW2tleV0gPSBtYXBba2V5XTtcbiAgICB9XG4gIH1cblxuICByZXR1cm4gU3BlY2lhbEZvcm1zLnR1cGxlKFNwZWNpYWxGb3Jtcy5tYXAoc3BsaXQxKSwgU3BlY2lhbEZvcm1zLm1hcChzcGxpdDIpKTtcbn1cblxuZnVuY3Rpb24gdGFrZShtYXAsIGtleXMpIHtcbiAgbGV0IHNwbGl0MSA9IHt9O1xuXG4gIGZvciAobGV0IGtleSBvZiBPYmplY3Qua2V5cyhtYXApLmNvbmNhdChPYmplY3QuZ2V0T3duUHJvcGVydHlTeW1ib2xzKG1hcCkpKSB7XG4gICAgaWYgKGtleXMuaW5kZXhPZihrZXkpID4gLTEpIHtcbiAgICAgIHNwbGl0MVtrZXldID0gbWFwW2tleV07XG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIFNwZWNpYWxGb3Jtcy5tYXAoc3BsaXQxKTtcbn1cblxuZnVuY3Rpb24gZHJvcChtYXAsIGtleXMpIHtcbiAgbGV0IHNwbGl0MSA9IHt9O1xuXG4gIGZvciAobGV0IGtleSBvZiBPYmplY3Qua2V5cyhtYXApLmNvbmNhdChPYmplY3QuZ2V0T3duUHJvcGVydHlTeW1ib2xzKG1hcCkpKSB7XG4gICAgaWYgKGtleXMuaW5kZXhPZihrZXkpID09PSAtMSkge1xuICAgICAgc3BsaXQxW2tleV0gPSBtYXBba2V5XTtcbiAgICB9XG4gIH1cblxuICByZXR1cm4gU3BlY2lhbEZvcm1zLm1hcChzcGxpdDEpO1xufVxuXG5mdW5jdGlvbiBwdXRfbmV3KG1hcCwga2V5LCB2YWx1ZSkge1xuICBpZiAoa2V5IGluIG1hcCkge1xuICAgIHJldHVybiBtYXA7XG4gIH1cblxuICBsZXQgbmV3X21hcCA9IE9iamVjdC5hc3NpZ24oe30sIG1hcCk7XG4gIG5ld19tYXBba2V5XSA9IHZhbHVlO1xuXG4gIHJldHVybiBTcGVjaWFsRm9ybXMubWFwKG5ld19tYXApO1xufVxuXG5mdW5jdGlvbiBwdXRfbmV3X2xhenkobWFwLCBrZXksIGZ1bikge1xuICBpZiAoa2V5IGluIG1hcCkge1xuICAgIHJldHVybiBtYXA7XG4gIH1cblxuICBsZXQgbmV3X21hcCA9IE9iamVjdC5hc3NpZ24oe30sIG1hcCk7XG4gIG5ld19tYXBba2V5XSA9IGZ1bigpO1xuXG4gIHJldHVybiBTcGVjaWFsRm9ybXMubWFwKG5ld19tYXApO1xufVxuXG5mdW5jdGlvbiBnZXRfYW5kX3VwZGF0ZShtYXAsIGtleSwgZnVuKSB7XG4gIGlmIChrZXkgaW4gbWFwKSB7XG4gICAgcmV0dXJuIG1hcDtcbiAgfVxuXG4gIGxldCBuZXdfbWFwID0gT2JqZWN0LmFzc2lnbih7fSwgbWFwKTtcbiAgbmV3X21hcFtrZXldID0gZnVuKG1hcFtrZXldKTtcblxuICByZXR1cm4gU3BlY2lhbEZvcm1zLm1hcChuZXdfbWFwKTtcbn1cblxuZnVuY3Rpb24gcG9wX2xhenkobWFwLCBrZXksIGZ1bikge1xuICBpZiAoIWtleSBpbiBtYXApIHtcbiAgICByZXR1cm4gU3BlY2lhbEZvcm1zLnR1cGxlKGZ1bigpLCBtYXApO1xuICB9XG5cbiAgbGV0IG5ld19tYXAgPSBPYmplY3QuYXNzaWduKHt9LCBtYXApO1xuICBsZXQgdmFsdWUgPSBmdW4obmV3X21hcFtrZXldKTtcbiAgZGVsZXRlIG5ld19tYXBba2V5XTtcblxuICByZXR1cm4gU3BlY2lhbEZvcm1zLnR1cGxlKHZhbHVlLCBuZXdfbWFwKTtcbn1cblxuZnVuY3Rpb24gcG9wKG1hcCwga2V5LCBfZGVmYXVsdCA9IG51bGwpIHtcbiAgaWYgKCFrZXkgaW4gbWFwKSB7XG4gICAgcmV0dXJuIFNwZWNpYWxGb3Jtcy50dXBsZShfZGVmYXVsdCwgbWFwKTtcbiAgfVxuXG4gIGxldCBuZXdfbWFwID0gT2JqZWN0LmFzc2lnbih7fSwgbWFwKTtcbiAgbGV0IHZhbHVlID0gbmV3X21hcFtrZXldO1xuICBkZWxldGUgbmV3X21hcFtrZXldO1xuXG4gIHJldHVybiBTcGVjaWFsRm9ybXMudHVwbGUodmFsdWUsIG5ld19tYXApO1xufVxuXG5mdW5jdGlvbiBnZXRfbGF6eShtYXAsIGtleSwgZnVuKSB7XG4gIGlmICgha2V5IGluIG1hcCkge1xuICAgIHJldHVybiBmdW4oKTtcbiAgfVxuXG4gIHJldHVybiBmdW4obWFwW2tleV0pO1xufVxuXG5mdW5jdGlvbiBnZXQobWFwLCBrZXksIF9kZWZhdWx0ID0gbnVsbCkge1xuICBpZiAoIWtleSBpbiBtYXApIHtcbiAgICByZXR1cm4gX2RlZmF1bHQ7XG4gIH1cblxuICByZXR1cm4gbWFwW2tleV07XG59XG5cbmZ1bmN0aW9uIHB1dChtYXAsIGtleSwgdmFsKSB7XG4gIGxldCBuZXdfbWFwID0gT2JqZWN0KHt9LCBtYXApO1xuICBuZXdfbWFwW2tleV0gPSB2YWw7XG5cbiAgcmV0dXJuIFNwZWNpYWxGb3Jtcy5tYXAobmV3X21hcCk7XG59XG5cbmZ1bmN0aW9uIHVwZGF0ZV9fZW1hcmtfXyhtYXAsIGtleSwgZnVuKSB7XG4gIGlmICgha2V5IGluIG1hcCkge1xuICAgIHRocm93IG5ldyBFcnJvcihcIktleSBub3QgZm91bmRcIik7XG4gIH1cblxuICBsZXQgbmV3X21hcCA9IE9iamVjdCh7fSwgbWFwKTtcbiAgbmV3X21hcFtrZXldID0gZnVuKG1hcFtrZXldKTtcblxuICByZXR1cm4gU3BlY2lhbEZvcm1zLm1hcChuZXdfbWFwKTtcbn1cblxuZnVuY3Rpb24gdXBkYXRlKG1hcCwga2V5LCBpbml0aWFsLCBmdW4pIHtcbiAgbGV0IG5ld19tYXAgPSBPYmplY3Qoe30sIG1hcCk7XG5cbiAgaWYgKCFrZXkgaW4gbWFwKSB7XG4gICAgbmV3X21hcFtrZXldID0gaW5pdGlhbDtcbiAgfSBlbHNlIHtcbiAgICBuZXdfbWFwW2tleV0gPSBmdW4obWFwW2tleV0pO1xuICB9XG5cbiAgcmV0dXJuIFNwZWNpYWxGb3Jtcy5tYXAobmV3X21hcCk7XG59XG5cbnZhciBtYXAgPSB7XG4gIG5ldzogX19uZXdfXyxcbiAga2V5cyxcbiAgc2l6ZSxcbiAgdG9fbGlzdDogdG9fbGlzdCQxLFxuICB2YWx1ZXMsXG4gIGZyb21fc3RydWN0LFxuICBkZWxldGU6IF9fZGVsZXRlX18sXG4gIGRyb3AsXG4gIGVxdWFsX19xbWFya19fLFxuICBmZXRjaF9fZW1hcmtfXyxcbiAgZmV0Y2gsXG4gIGhhc19rZXlfX3FtYXJrX18sXG4gIHNwbGl0OiBzcGxpdCQxLFxuICB0YWtlLFxuICBwdXRfbmV3LFxuICBwdXRfbmV3X2xhenksXG4gIGdldF9hbmRfdXBkYXRlLFxuICBwb3BfbGF6eSxcbiAgcG9wLFxuICBnZXRfbGF6eSxcbiAgZ2V0LFxuICBwdXQsXG4gIHVwZGF0ZV9fZW1hcmtfXyxcbiAgdXBkYXRlXG59O1xuXG5mdW5jdGlvbiBfX25ld19fJDEoKSB7XG4gIHJldHVybiBTcGVjaWFsRm9ybXMubWFwKHsgW1N5bWJvbC5mb3IoJ19fc3RydWN0X18nKV06IFN5bWJvbC5mb3IoJ01hcFNldCcpLCBzZXQ6IFNwZWNpYWxGb3Jtcy5saXN0KCkgfSk7XG59XG5cbmZ1bmN0aW9uIHNpemUkMihtYXApIHtcbiAgcmV0dXJuIG1hcC5zZXQubGVuZ3RoO1xufVxuXG5mdW5jdGlvbiB0b19saXN0JDMobWFwKSB7XG4gIHJldHVybiBtYXAuc2V0O1xufVxuXG5mdW5jdGlvbiBfX2RlbGV0ZV9fJDIoc2V0LCB0ZXJtKSB7XG4gIGxldCBuZXdfbGlzdCA9IExpc3QuZGVsZXRlKHNldC5zZXQsIHRlcm0pO1xuXG4gIGxldCBuZXdfbWFwID0gT2JqZWN0LmFzc2lnbih7fSwgc2V0KTtcbiAgbmV3X21hcC5zZXQgPSBuZXdfbGlzdDtcbiAgcmV0dXJuIFNwZWNpYWxGb3Jtcy5tYXAobmV3X21hcCk7XG59XG5cbmZ1bmN0aW9uIHB1dCQyKHNldCwgdGVybSkge1xuICBpZiAoc2V0LnNldC5pbmRleE9mKHRlcm0pID09PSAtMSkge1xuICAgIGxldCBuZXdfbGlzdCA9IExpc3QuYXBwZW5kKHNldC5zZXQsIHRlcm0pO1xuXG4gICAgbGV0IG5ld19tYXAgPSBPYmplY3QuYXNzaWduKHt9LCBzZXQpO1xuICAgIG5ld19tYXAuc2V0ID0gbmV3X2xpc3Q7XG4gICAgcmV0dXJuIFNwZWNpYWxGb3Jtcy5tYXAobmV3X21hcCk7XG4gIH1cblxuICByZXR1cm4gc2V0O1xufVxuXG5mdW5jdGlvbiBkaWZmZXJlbmNlJDEoc2V0MSwgc2V0Mikge1xuICBsZXQgbmV3X21hcCA9IE9iamVjdC5hc3NpZ24oe30sIHNldDEpO1xuXG4gIGZvciAobGV0IHZhbCBvZiBzZXQxLnNldCkge1xuICAgIGlmIChtZW1iZXJfX3FtYXJrX18kMShzZXQyLCB2YWwpKSB7XG4gICAgICBuZXdfbWFwLnNldCA9IExpc3QuZGVsZXRlKG5ld19tYXAuc2V0LCB2YWwpO1xuICAgIH1cbiAgfVxuXG4gIHJldHVybiBTcGVjaWFsRm9ybXMubWFwKG5ld19tYXApO1xufVxuXG5mdW5jdGlvbiBpbnRlcnNlY3Rpb24kMShzZXQxLCBzZXQyKSB7XG4gIGxldCBuZXdfbWFwID0gT2JqZWN0LmFzc2lnbih7fSwgc2V0MSk7XG5cbiAgZm9yIChsZXQgdmFsIG9mIHNldDEuc2V0KSB7XG4gICAgaWYgKCFtZW1iZXJfX3FtYXJrX18kMShzZXQyLCB2YWwpKSB7XG4gICAgICBuZXdfbWFwLnNldCA9IExpc3QuZGVsZXRlKG5ld19tYXAuc2V0LCB2YWwpO1xuICAgIH1cbiAgfVxuXG4gIHJldHVybiBTcGVjaWFsRm9ybXMubWFwKG5ld19tYXApO1xufVxuXG5mdW5jdGlvbiB1bmlvbiQxKHNldDEsIHNldDIpIHtcbiAgbGV0IG5ld19tYXAgPSBzZXQxO1xuXG4gIGZvciAobGV0IHZhbCBvZiBzZXQyLnNldCkge1xuICAgIG5ld19tYXAgPSBwdXQkMihuZXdfbWFwLCB2YWwpO1xuICB9XG5cbiAgcmV0dXJuIFNwZWNpYWxGb3Jtcy5tYXAobmV3X21hcCk7XG59XG5cbmZ1bmN0aW9uIGRpc2pvaW5fX3FtYXJrX18kMShzZXQxLCBzZXQyKSB7XG4gIGZvciAobGV0IHZhbCBvZiBzZXQxLnNldCkge1xuICAgIGlmIChtZW1iZXJfX3FtYXJrX18kMShzZXQyLCB2YWwpKSB7XG4gICAgICByZXR1cm4gZmFsc2U7XG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIHRydWU7XG59XG5cbmZ1bmN0aW9uIG1lbWJlcl9fcW1hcmtfXyQxKHNldCwgdmFsdWUpIHtcbiAgcmV0dXJuIHNldC5zZXQuaW5kZXhPZih2YWx1ZSkgPj0gMDtcbn1cblxuZnVuY3Rpb24gZXF1YWxfX3FtYXJrX18kMihzZXQxLCBzZXQyKSB7XG4gIHJldHVybiBzZXQxLnNldCA9PT0gc2V0Mi5zZXQ7XG59XG5cbmZ1bmN0aW9uIHN1YnNldF9fcW1hcmtfXyQxKHNldDEsIHNldDIpIHtcbiAgZm9yIChsZXQgdmFsIG9mIHNldDEuc2V0KSB7XG4gICAgaWYgKCFtZW1iZXJfX3FtYXJrX18kMShzZXQyLCB2YWwpKSB7XG4gICAgICByZXR1cm4gZmFsc2U7XG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIHRydWU7XG59XG5cbnZhciBNYXBTZXQgPSB7XG4gIG5ldzogX19uZXdfXyQxLFxuICBzaXplOiBzaXplJDIsXG4gIHRvX2xpc3Q6IHRvX2xpc3QkMyxcbiAgZGlzam9pbl9fcW1hcmtfXzogZGlzam9pbl9fcW1hcmtfXyQxLFxuICBkZWxldGU6IF9fZGVsZXRlX18kMixcbiAgc3Vic2V0X19xbWFya19fOiBzdWJzZXRfX3FtYXJrX18kMSxcbiAgZXF1YWxfX3FtYXJrX186IGVxdWFsX19xbWFya19fJDIsXG4gIG1lbWJlcl9fcW1hcmtfXzogbWVtYmVyX19xbWFya19fJDEsXG4gIHB1dDogcHV0JDIsXG4gIHVuaW9uOiB1bmlvbiQxLFxuICBpbnRlcnNlY3Rpb246IGludGVyc2VjdGlvbiQxLFxuICBkaWZmZXJlbmNlOiBkaWZmZXJlbmNlJDFcbn07XG5cbmZ1bmN0aW9uIHNpemUkMShtYXApIHtcbiAgcmV0dXJuIE1hcFNldC5zaXplKG1hcCk7XG59XG5cbmZ1bmN0aW9uIHRvX2xpc3QkMihtYXApIHtcbiAgcmV0dXJuIE1hcFNldC50b19saXN0KG1hcCk7XG59XG5cbmZ1bmN0aW9uIF9fZGVsZXRlX18kMShzZXQsIHRlcm0pIHtcbiAgcmV0dXJuIE1hcFNldC5kZWxldGUoc2V0LCB0ZXJtKTtcbn1cblxuZnVuY3Rpb24gcHV0JDEoc2V0LCB0ZXJtKSB7XG4gIHJldHVybiBNYXBTZXQucHV0KHNldCwgdGVybSk7XG59XG5cbmZ1bmN0aW9uIGRpZmZlcmVuY2Uoc2V0MSwgc2V0Mikge1xuICByZXR1cm4gTWFwU2V0LmRpZmZlcmVuY2Uoc2V0MSwgc2V0Mik7XG59XG5cbmZ1bmN0aW9uIGludGVyc2VjdGlvbihzZXQxLCBzZXQyKSB7XG4gIHJldHVybiBNYXBTZXQuaW50ZXJzZWN0aW9uKHNldDEsIHNldDIpO1xufVxuXG5mdW5jdGlvbiB1bmlvbihzZXQxLCBzZXQyKSB7XG4gIHJldHVybiBNYXBTZXQudW5pb24oc2V0MSwgc2V0Mik7XG59XG5cbmZ1bmN0aW9uIGRpc2pvaW5fX3FtYXJrX18oc2V0MSwgc2V0Mikge1xuICByZXR1cm4gTWFwU2V0LmRpc2pvaW5fX3FtYXJrX18oc2V0MSwgc2V0Mik7XG59XG5cbmZ1bmN0aW9uIG1lbWJlcl9fcW1hcmtfXyhzZXQsIHZhbHVlKSB7XG4gIHJldHVybiBNYXBTZXQubWVtYmVyX19xbWFya19fKHNldDEsIHNldDIpO1xufVxuXG5mdW5jdGlvbiBlcXVhbF9fcW1hcmtfXyQxKHNldDEsIHNldDIpIHtcbiAgcmV0dXJuIE1hcFNldC5lcXVhbF9fcW1hcmtfXyhzZXQxLCBzZXQyKTtcbn1cblxuZnVuY3Rpb24gc3Vic2V0X19xbWFya19fKHNldDEsIHNldDIpIHtcbiAgcmV0dXJuIE1hcFNldC5zdWJzZXRfX3FtYXJrX18oc2V0MSwgc2V0Mik7XG59XG5cbnZhciBzZXQgPSB7XG4gIHNpemU6IHNpemUkMSxcbiAgdG9fbGlzdDogdG9fbGlzdCQyLFxuICBkaXNqb2luX19xbWFya19fLFxuICBkZWxldGU6IF9fZGVsZXRlX18kMSxcbiAgc3Vic2V0X19xbWFya19fLFxuICBlcXVhbF9fcW1hcmtfXzogZXF1YWxfX3FtYXJrX18kMSxcbiAgbWVtYmVyX19xbWFya19fLFxuICBwdXQ6IHB1dCQxLFxuICB1bmlvbixcbiAgaW50ZXJzZWN0aW9uLFxuICBkaWZmZXJlbmNlXG59O1xuXG5sZXQgVmlydHVhbERPTSA9IChmdW5jdGlvbiAoZSkge1xuICAgIHJldHVybiBlKCk7XG59KShmdW5jdGlvbiAoKSB7XG4gICAgdmFyIGRlZmluZSwgbW9kdWxlLCBleHBvcnRzO1xuICAgIHJldHVybiAoZnVuY3Rpb24gZSh0LCBuLCByKSB7XG4gICAgICAgIGZ1bmN0aW9uIHMobywgdSkge1xuICAgICAgICAgICAgaWYgKCFuW29dKSB7XG4gICAgICAgICAgICAgICAgaWYgKCF0W29dKSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciBhID0gdHlwZW9mIHJlcXVpcmUgPT0gXCJmdW5jdGlvblwiICYmIHJlcXVpcmU7XG4gICAgICAgICAgICAgICAgICAgIGlmICghdSAmJiBhKSByZXR1cm4gYShvLCAhMCk7XG4gICAgICAgICAgICAgICAgICAgIGlmIChpKSByZXR1cm4gaShvLCAhMCk7XG4gICAgICAgICAgICAgICAgICAgIHZhciBmID0gbmV3IEVycm9yKFwiQ2Fubm90IGZpbmQgbW9kdWxlICdcIiArIG8gKyBcIidcIik7XG4gICAgICAgICAgICAgICAgICAgIHRocm93IChmLmNvZGUgPSBcIk1PRFVMRV9OT1RfRk9VTkRcIiwgZik7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHZhciBsID0gbltvXSA9IHtcbiAgICAgICAgICAgICAgICAgICAgZXhwb3J0czoge31cbiAgICAgICAgICAgICAgICB9O1xuICAgICAgICAgICAgICAgIHRbb11bMF0uY2FsbChsLmV4cG9ydHMsIGZ1bmN0aW9uIChlKSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciBuID0gdFtvXVsxXVtlXTtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHMobiA/IG4gOiBlKTtcbiAgICAgICAgICAgICAgICB9LCBsLCBsLmV4cG9ydHMsIGUsIHQsIG4sIHIpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmV0dXJuIG5bb10uZXhwb3J0cztcbiAgICAgICAgfVxuICAgICAgICB2YXIgaSA9IHR5cGVvZiByZXF1aXJlID09IFwiZnVuY3Rpb25cIiAmJiByZXF1aXJlO1xuICAgICAgICBmb3IgKHZhciBvID0gMDsgbyA8IHIubGVuZ3RoOyBvKyspIHMocltvXSk7XG4gICAgICAgIHJldHVybiBzO1xuICAgIH0pKHtcbiAgICAgICAgMTogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHtcblxuICAgICAgICAgICAgdmFyIGNyZWF0ZUVsZW1lbnQgPSByZXF1aXJlKFwiLi92ZG9tL2NyZWF0ZS1lbGVtZW50LmpzXCIpO1xuXG4gICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IGNyZWF0ZUVsZW1lbnQ7XG4gICAgICAgIH0sIHsgXCIuL3Zkb20vY3JlYXRlLWVsZW1lbnQuanNcIjogMTUgfV0sIDI6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICB2YXIgZGlmZiA9IHJlcXVpcmUoXCIuL3Z0cmVlL2RpZmYuanNcIik7XG5cbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gZGlmZjtcbiAgICAgICAgfSwgeyBcIi4vdnRyZWUvZGlmZi5qc1wiOiAzNSB9XSwgMzogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHtcbiAgICAgICAgICAgIHZhciBoID0gcmVxdWlyZShcIi4vdmlydHVhbC1oeXBlcnNjcmlwdC9pbmRleC5qc1wiKTtcblxuICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBoO1xuICAgICAgICB9LCB7IFwiLi92aXJ0dWFsLWh5cGVyc2NyaXB0L2luZGV4LmpzXCI6IDIyIH1dLCA0OiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge1xuICAgICAgICAgICAgdmFyIGRpZmYgPSByZXF1aXJlKFwiLi9kaWZmLmpzXCIpO1xuICAgICAgICAgICAgdmFyIHBhdGNoID0gcmVxdWlyZShcIi4vcGF0Y2guanNcIik7XG4gICAgICAgICAgICB2YXIgaCA9IHJlcXVpcmUoXCIuL2guanNcIik7XG4gICAgICAgICAgICB2YXIgY3JlYXRlID0gcmVxdWlyZShcIi4vY3JlYXRlLWVsZW1lbnQuanNcIik7XG4gICAgICAgICAgICB2YXIgVk5vZGUgPSByZXF1aXJlKFwiLi92bm9kZS92bm9kZS5qc1wiKTtcbiAgICAgICAgICAgIHZhciBWVGV4dCA9IHJlcXVpcmUoXCIuL3Zub2RlL3Z0ZXh0LmpzXCIpO1xuXG4gICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IHtcbiAgICAgICAgICAgICAgICBkaWZmOiBkaWZmLFxuICAgICAgICAgICAgICAgIHBhdGNoOiBwYXRjaCxcbiAgICAgICAgICAgICAgICBoOiBoLFxuICAgICAgICAgICAgICAgIGNyZWF0ZTogY3JlYXRlLFxuICAgICAgICAgICAgICAgIFZOb2RlOiBWTm9kZSxcbiAgICAgICAgICAgICAgICBWVGV4dDogVlRleHRcbiAgICAgICAgICAgIH07XG4gICAgICAgIH0sIHsgXCIuL2NyZWF0ZS1lbGVtZW50LmpzXCI6IDEsIFwiLi9kaWZmLmpzXCI6IDIsIFwiLi9oLmpzXCI6IDMsIFwiLi9wYXRjaC5qc1wiOiAxMywgXCIuL3Zub2RlL3Zub2RlLmpzXCI6IDMxLCBcIi4vdm5vZGUvdnRleHQuanNcIjogMzMgfV0sIDU6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICAvKiFcbiAgICAgICAgICAgICAqIENyb3NzLUJyb3dzZXIgU3BsaXQgMS4xLjFcbiAgICAgICAgICAgICAqIENvcHlyaWdodCAyMDA3LTIwMTIgU3RldmVuIExldml0aGFuIDxzdGV2ZW5sZXZpdGhhbi5jb20+XG4gICAgICAgICAgICAgKiBBdmFpbGFibGUgdW5kZXIgdGhlIE1JVCBMaWNlbnNlXG4gICAgICAgICAgICAgKiBFQ01BU2NyaXB0IGNvbXBsaWFudCwgdW5pZm9ybSBjcm9zcy1icm93c2VyIHNwbGl0IG1ldGhvZFxuICAgICAgICAgICAgICovXG5cbiAgICAgICAgICAgIC8qKlxuICAgICAgICAgICAgICogU3BsaXRzIGEgc3RyaW5nIGludG8gYW4gYXJyYXkgb2Ygc3RyaW5ncyB1c2luZyBhIHJlZ2V4IG9yIHN0cmluZyBzZXBhcmF0b3IuIE1hdGNoZXMgb2YgdGhlXG4gICAgICAgICAgICAgKiBzZXBhcmF0b3IgYXJlIG5vdCBpbmNsdWRlZCBpbiB0aGUgcmVzdWx0IGFycmF5LiBIb3dldmVyLCBpZiBgc2VwYXJhdG9yYCBpcyBhIHJlZ2V4IHRoYXQgY29udGFpbnNcbiAgICAgICAgICAgICAqIGNhcHR1cmluZyBncm91cHMsIGJhY2tyZWZlcmVuY2VzIGFyZSBzcGxpY2VkIGludG8gdGhlIHJlc3VsdCBlYWNoIHRpbWUgYHNlcGFyYXRvcmAgaXMgbWF0Y2hlZC5cbiAgICAgICAgICAgICAqIEZpeGVzIGJyb3dzZXIgYnVncyBjb21wYXJlZCB0byB0aGUgbmF0aXZlIGBTdHJpbmcucHJvdG90eXBlLnNwbGl0YCBhbmQgY2FuIGJlIHVzZWQgcmVsaWFibHlcbiAgICAgICAgICAgICAqIGNyb3NzLWJyb3dzZXIuXG4gICAgICAgICAgICAgKiBAcGFyYW0ge1N0cmluZ30gc3RyIFN0cmluZyB0byBzcGxpdC5cbiAgICAgICAgICAgICAqIEBwYXJhbSB7UmVnRXhwfFN0cmluZ30gc2VwYXJhdG9yIFJlZ2V4IG9yIHN0cmluZyB0byB1c2UgZm9yIHNlcGFyYXRpbmcgdGhlIHN0cmluZy5cbiAgICAgICAgICAgICAqIEBwYXJhbSB7TnVtYmVyfSBbbGltaXRdIE1heGltdW0gbnVtYmVyIG9mIGl0ZW1zIHRvIGluY2x1ZGUgaW4gdGhlIHJlc3VsdCBhcnJheS5cbiAgICAgICAgICAgICAqIEByZXR1cm5zIHtBcnJheX0gQXJyYXkgb2Ygc3Vic3RyaW5ncy5cbiAgICAgICAgICAgICAqIEBleGFtcGxlXG4gICAgICAgICAgICAgKlxuICAgICAgICAgICAgICogLy8gQmFzaWMgdXNlXG4gICAgICAgICAgICAgKiBzcGxpdCgnYSBiIGMgZCcsICcgJyk7XG4gICAgICAgICAgICAgKiAvLyAtPiBbJ2EnLCAnYicsICdjJywgJ2QnXVxuICAgICAgICAgICAgICpcbiAgICAgICAgICAgICAqIC8vIFdpdGggbGltaXRcbiAgICAgICAgICAgICAqIHNwbGl0KCdhIGIgYyBkJywgJyAnLCAyKTtcbiAgICAgICAgICAgICAqIC8vIC0+IFsnYScsICdiJ11cbiAgICAgICAgICAgICAqXG4gICAgICAgICAgICAgKiAvLyBCYWNrcmVmZXJlbmNlcyBpbiByZXN1bHQgYXJyYXlcbiAgICAgICAgICAgICAqIHNwbGl0KCcuLndvcmQxIHdvcmQyLi4nLCAvKFthLXpdKykoXFxkKykvaSk7XG4gICAgICAgICAgICAgKiAvLyAtPiBbJy4uJywgJ3dvcmQnLCAnMScsICcgJywgJ3dvcmQnLCAnMicsICcuLiddXG4gICAgICAgICAgICAgKi9cbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gKGZ1bmN0aW9uIHNwbGl0KHVuZGVmKSB7XG5cbiAgICAgICAgICAgICAgICB2YXIgbmF0aXZlU3BsaXQgPSBTdHJpbmcucHJvdG90eXBlLnNwbGl0LFxuICAgICAgICAgICAgICAgICAgICBjb21wbGlhbnRFeGVjTnBjZyA9IC8oKT8/Ly5leGVjKFwiXCIpWzFdID09PSB1bmRlZixcblxuICAgICAgICAgICAgICAgIC8vIE5QQ0c6IG5vbnBhcnRpY2lwYXRpbmcgY2FwdHVyaW5nIGdyb3VwXG4gICAgICAgICAgICAgICAgc2VsZjtcblxuICAgICAgICAgICAgICAgIHNlbGYgPSBmdW5jdGlvbiAoc3RyLCBzZXBhcmF0b3IsIGxpbWl0KSB7XG4gICAgICAgICAgICAgICAgICAgIC8vIElmIGBzZXBhcmF0b3JgIGlzIG5vdCBhIHJlZ2V4LCB1c2UgYG5hdGl2ZVNwbGl0YFxuICAgICAgICAgICAgICAgICAgICBpZiAoT2JqZWN0LnByb3RvdHlwZS50b1N0cmluZy5jYWxsKHNlcGFyYXRvcikgIT09IFwiW29iamVjdCBSZWdFeHBdXCIpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBuYXRpdmVTcGxpdC5jYWxsKHN0ciwgc2VwYXJhdG9yLCBsaW1pdCk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgdmFyIG91dHB1dCA9IFtdLFxuICAgICAgICAgICAgICAgICAgICAgICAgZmxhZ3MgPSAoc2VwYXJhdG9yLmlnbm9yZUNhc2UgPyBcImlcIiA6IFwiXCIpICsgKHNlcGFyYXRvci5tdWx0aWxpbmUgPyBcIm1cIiA6IFwiXCIpICsgKHNlcGFyYXRvci5leHRlbmRlZCA/IFwieFwiIDogXCJcIikgKyAoc2VwYXJhdG9yLnN0aWNreSA/IFwieVwiIDogXCJcIiksXG5cbiAgICAgICAgICAgICAgICAgICAgLy8gRmlyZWZveCAzK1xuICAgICAgICAgICAgICAgICAgICBsYXN0TGFzdEluZGV4ID0gMCxcblxuICAgICAgICAgICAgICAgICAgICAvLyBNYWtlIGBnbG9iYWxgIGFuZCBhdm9pZCBgbGFzdEluZGV4YCBpc3N1ZXMgYnkgd29ya2luZyB3aXRoIGEgY29weVxuICAgICAgICAgICAgICAgICAgICBzZXBhcmF0b3IgPSBuZXcgUmVnRXhwKHNlcGFyYXRvci5zb3VyY2UsIGZsYWdzICsgXCJnXCIpLFxuICAgICAgICAgICAgICAgICAgICAgICAgc2VwYXJhdG9yMixcbiAgICAgICAgICAgICAgICAgICAgICAgIG1hdGNoLFxuICAgICAgICAgICAgICAgICAgICAgICAgbGFzdEluZGV4LFxuICAgICAgICAgICAgICAgICAgICAgICAgbGFzdExlbmd0aDtcbiAgICAgICAgICAgICAgICAgICAgc3RyICs9IFwiXCI7IC8vIFR5cGUtY29udmVydFxuICAgICAgICAgICAgICAgICAgICBpZiAoIWNvbXBsaWFudEV4ZWNOcGNnKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAvLyBEb2Vzbid0IG5lZWQgZmxhZ3MgZ3ksIGJ1dCB0aGV5IGRvbid0IGh1cnRcbiAgICAgICAgICAgICAgICAgICAgICAgIHNlcGFyYXRvcjIgPSBuZXcgUmVnRXhwKFwiXlwiICsgc2VwYXJhdG9yLnNvdXJjZSArIFwiJCg/IVxcXFxzKVwiLCBmbGFncyk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgLyogVmFsdWVzIGZvciBgbGltaXRgLCBwZXIgdGhlIHNwZWM6XG4gICAgICAgICAgICAgICAgICAgICAqIElmIHVuZGVmaW5lZDogNDI5NDk2NzI5NSAvLyBNYXRoLnBvdygyLCAzMikgLSAxXG4gICAgICAgICAgICAgICAgICAgICAqIElmIDAsIEluZmluaXR5LCBvciBOYU46IDBcbiAgICAgICAgICAgICAgICAgICAgICogSWYgcG9zaXRpdmUgbnVtYmVyOiBsaW1pdCA9IE1hdGguZmxvb3IobGltaXQpOyBpZiAobGltaXQgPiA0Mjk0OTY3Mjk1KSBsaW1pdCAtPSA0Mjk0OTY3Mjk2O1xuICAgICAgICAgICAgICAgICAgICAgKiBJZiBuZWdhdGl2ZSBudW1iZXI6IDQyOTQ5NjcyOTYgLSBNYXRoLmZsb29yKE1hdGguYWJzKGxpbWl0KSlcbiAgICAgICAgICAgICAgICAgICAgICogSWYgb3RoZXI6IFR5cGUtY29udmVydCwgdGhlbiB1c2UgdGhlIGFib3ZlIHJ1bGVzXG4gICAgICAgICAgICAgICAgICAgICAqL1xuICAgICAgICAgICAgICAgICAgICBsaW1pdCA9IGxpbWl0ID09PSB1bmRlZiA/IC0xID4+PiAwIDogLy8gTWF0aC5wb3coMiwgMzIpIC0gMVxuICAgICAgICAgICAgICAgICAgICBsaW1pdCA+Pj4gMDsgLy8gVG9VaW50MzIobGltaXQpXG4gICAgICAgICAgICAgICAgICAgIHdoaWxlIChtYXRjaCA9IHNlcGFyYXRvci5leGVjKHN0cikpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIGBzZXBhcmF0b3IubGFzdEluZGV4YCBpcyBub3QgcmVsaWFibGUgY3Jvc3MtYnJvd3NlclxuICAgICAgICAgICAgICAgICAgICAgICAgbGFzdEluZGV4ID0gbWF0Y2guaW5kZXggKyBtYXRjaFswXS5sZW5ndGg7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAobGFzdEluZGV4ID4gbGFzdExhc3RJbmRleCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIG91dHB1dC5wdXNoKHN0ci5zbGljZShsYXN0TGFzdEluZGV4LCBtYXRjaC5pbmRleCkpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIEZpeCBicm93c2VycyB3aG9zZSBgZXhlY2AgbWV0aG9kcyBkb24ndCBjb25zaXN0ZW50bHkgcmV0dXJuIGB1bmRlZmluZWRgIGZvclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIG5vbnBhcnRpY2lwYXRpbmcgY2FwdHVyaW5nIGdyb3Vwc1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmICghY29tcGxpYW50RXhlY05wY2cgJiYgbWF0Y2gubGVuZ3RoID4gMSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBtYXRjaFswXS5yZXBsYWNlKHNlcGFyYXRvcjIsIGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZvciAodmFyIGkgPSAxOyBpIDwgYXJndW1lbnRzLmxlbmd0aCAtIDI7IGkrKykge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChhcmd1bWVudHNbaV0gPT09IHVuZGVmKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1hdGNoW2ldID0gdW5kZWY7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKG1hdGNoLmxlbmd0aCA+IDEgJiYgbWF0Y2guaW5kZXggPCBzdHIubGVuZ3RoKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIEFycmF5LnByb3RvdHlwZS5wdXNoLmFwcGx5KG91dHB1dCwgbWF0Y2guc2xpY2UoMSkpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBsYXN0TGVuZ3RoID0gbWF0Y2hbMF0ubGVuZ3RoO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxhc3RMYXN0SW5kZXggPSBsYXN0SW5kZXg7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKG91dHB1dC5sZW5ndGggPj0gbGltaXQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHNlcGFyYXRvci5sYXN0SW5kZXggPT09IG1hdGNoLmluZGV4KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgc2VwYXJhdG9yLmxhc3RJbmRleCsrOyAvLyBBdm9pZCBhbiBpbmZpbml0ZSBsb29wXG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgaWYgKGxhc3RMYXN0SW5kZXggPT09IHN0ci5sZW5ndGgpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChsYXN0TGVuZ3RoIHx8ICFzZXBhcmF0b3IudGVzdChcIlwiKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIG91dHB1dC5wdXNoKFwiXCIpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgb3V0cHV0LnB1c2goc3RyLnNsaWNlKGxhc3RMYXN0SW5kZXgpKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICByZXR1cm4gb3V0cHV0Lmxlbmd0aCA+IGxpbWl0ID8gb3V0cHV0LnNsaWNlKDAsIGxpbWl0KSA6IG91dHB1dDtcbiAgICAgICAgICAgICAgICB9O1xuXG4gICAgICAgICAgICAgICAgcmV0dXJuIHNlbGY7XG4gICAgICAgICAgICB9KSgpO1xuICAgICAgICB9LCB7fV0sIDY6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7fSwge31dLCA3OiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge1xuICAgICAgICAgICAgXCJ1c2Ugc3RyaWN0XCI7XG5cbiAgICAgICAgICAgIHZhciBPbmVWZXJzaW9uQ29uc3RyYWludCA9IHJlcXVpcmUoXCJpbmRpdmlkdWFsL29uZS12ZXJzaW9uXCIpO1xuXG4gICAgICAgICAgICB2YXIgTVlfVkVSU0lPTiA9IFwiN1wiO1xuICAgICAgICAgICAgT25lVmVyc2lvbkNvbnN0cmFpbnQoXCJldi1zdG9yZVwiLCBNWV9WRVJTSU9OKTtcblxuICAgICAgICAgICAgdmFyIGhhc2hLZXkgPSBcIl9fRVZfU1RPUkVfS0VZQFwiICsgTVlfVkVSU0lPTjtcblxuICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBFdlN0b3JlO1xuXG4gICAgICAgICAgICBmdW5jdGlvbiBFdlN0b3JlKGVsZW0pIHtcbiAgICAgICAgICAgICAgICB2YXIgaGFzaCA9IGVsZW1baGFzaEtleV07XG5cbiAgICAgICAgICAgICAgICBpZiAoIWhhc2gpIHtcbiAgICAgICAgICAgICAgICAgICAgaGFzaCA9IGVsZW1baGFzaEtleV0gPSB7fTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICByZXR1cm4gaGFzaDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSwgeyBcImluZGl2aWR1YWwvb25lLXZlcnNpb25cIjogOSB9XSwgODogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHtcbiAgICAgICAgICAgIChmdW5jdGlvbiAoZ2xvYmFsKSB7XG4gICAgICAgICAgICAgICAgXCJ1c2Ugc3RyaWN0XCI7XG5cbiAgICAgICAgICAgICAgICAvKmdsb2JhbCB3aW5kb3csIGdsb2JhbCovXG5cbiAgICAgICAgICAgICAgICB2YXIgcm9vdCA9IHR5cGVvZiB3aW5kb3cgIT09IFwidW5kZWZpbmVkXCIgPyB3aW5kb3cgOiB0eXBlb2YgZ2xvYmFsICE9PSBcInVuZGVmaW5lZFwiID8gZ2xvYmFsIDoge307XG5cbiAgICAgICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IEluZGl2aWR1YWw7XG5cbiAgICAgICAgICAgICAgICBmdW5jdGlvbiBJbmRpdmlkdWFsKGtleSwgdmFsdWUpIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKGtleSBpbiByb290KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gcm9vdFtrZXldO1xuICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgcm9vdFtrZXldID0gdmFsdWU7XG5cbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHZhbHVlO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0pLmNhbGwodGhpcywgdHlwZW9mIGdsb2JhbCAhPT0gXCJ1bmRlZmluZWRcIiA/IGdsb2JhbCA6IHR5cGVvZiBzZWxmICE9PSBcInVuZGVmaW5lZFwiID8gc2VsZiA6IHR5cGVvZiB3aW5kb3cgIT09IFwidW5kZWZpbmVkXCIgPyB3aW5kb3cgOiB7fSk7XG4gICAgICAgIH0sIHt9XSwgOTogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHtcbiAgICAgICAgICAgIFwidXNlIHN0cmljdFwiO1xuXG4gICAgICAgICAgICB2YXIgSW5kaXZpZHVhbCA9IHJlcXVpcmUoXCIuL2luZGV4LmpzXCIpO1xuXG4gICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IE9uZVZlcnNpb247XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIE9uZVZlcnNpb24obW9kdWxlTmFtZSwgdmVyc2lvbiwgZGVmYXVsdFZhbHVlKSB7XG4gICAgICAgICAgICAgICAgdmFyIGtleSA9IFwiX19JTkRJVklEVUFMX09ORV9WRVJTSU9OX1wiICsgbW9kdWxlTmFtZTtcbiAgICAgICAgICAgICAgICB2YXIgZW5mb3JjZUtleSA9IGtleSArIFwiX0VORk9SQ0VfU0lOR0xFVE9OXCI7XG5cbiAgICAgICAgICAgICAgICB2YXIgdmVyc2lvblZhbHVlID0gSW5kaXZpZHVhbChlbmZvcmNlS2V5LCB2ZXJzaW9uKTtcblxuICAgICAgICAgICAgICAgIGlmICh2ZXJzaW9uVmFsdWUgIT09IHZlcnNpb24pIHtcbiAgICAgICAgICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKFwiQ2FuIG9ubHkgaGF2ZSBvbmUgY29weSBvZiBcIiArIG1vZHVsZU5hbWUgKyBcIi5cXG5cIiArIFwiWW91IGFscmVhZHkgaGF2ZSB2ZXJzaW9uIFwiICsgdmVyc2lvblZhbHVlICsgXCIgaW5zdGFsbGVkLlxcblwiICsgXCJUaGlzIG1lYW5zIHlvdSBjYW5ub3QgaW5zdGFsbCB2ZXJzaW9uIFwiICsgdmVyc2lvbik7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgcmV0dXJuIEluZGl2aWR1YWwoa2V5LCBkZWZhdWx0VmFsdWUpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9LCB7IFwiLi9pbmRleC5qc1wiOiA4IH1dLCAxMDogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHtcbiAgICAgICAgICAgIChmdW5jdGlvbiAoZ2xvYmFsKSB7XG4gICAgICAgICAgICAgICAgdmFyIHRvcExldmVsID0gdHlwZW9mIGdsb2JhbCAhPT0gXCJ1bmRlZmluZWRcIiA/IGdsb2JhbCA6IHR5cGVvZiB3aW5kb3cgIT09IFwidW5kZWZpbmVkXCIgPyB3aW5kb3cgOiB7fTtcbiAgICAgICAgICAgICAgICB2YXIgbWluRG9jID0gcmVxdWlyZShcIm1pbi1kb2N1bWVudFwiKTtcblxuICAgICAgICAgICAgICAgIGlmICh0eXBlb2YgZG9jdW1lbnQgIT09IFwidW5kZWZpbmVkXCIpIHtcbiAgICAgICAgICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBkb2N1bWVudDtcbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICB2YXIgZG9jY3kgPSB0b3BMZXZlbFtcIl9fR0xPQkFMX0RPQ1VNRU5UX0NBQ0hFQDRcIl07XG5cbiAgICAgICAgICAgICAgICAgICAgaWYgKCFkb2NjeSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgZG9jY3kgPSB0b3BMZXZlbFtcIl9fR0xPQkFMX0RPQ1VNRU5UX0NBQ0hFQDRcIl0gPSBtaW5Eb2M7XG4gICAgICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IGRvY2N5O1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0pLmNhbGwodGhpcywgdHlwZW9mIGdsb2JhbCAhPT0gXCJ1bmRlZmluZWRcIiA/IGdsb2JhbCA6IHR5cGVvZiBzZWxmICE9PSBcInVuZGVmaW5lZFwiID8gc2VsZiA6IHR5cGVvZiB3aW5kb3cgIT09IFwidW5kZWZpbmVkXCIgPyB3aW5kb3cgOiB7fSk7XG4gICAgICAgIH0sIHsgXCJtaW4tZG9jdW1lbnRcIjogNiB9XSwgMTE6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICBcInVzZSBzdHJpY3RcIjtcblxuICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiBpc09iamVjdCh4KSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHR5cGVvZiB4ID09PSBcIm9iamVjdFwiICYmIHggIT09IG51bGw7XG4gICAgICAgICAgICB9O1xuICAgICAgICB9LCB7fV0sIDEyOiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge1xuICAgICAgICAgICAgdmFyIG5hdGl2ZUlzQXJyYXkgPSBBcnJheS5pc0FycmF5O1xuICAgICAgICAgICAgdmFyIHRvU3RyaW5nID0gT2JqZWN0LnByb3RvdHlwZS50b1N0cmluZztcblxuICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBuYXRpdmVJc0FycmF5IHx8IGlzQXJyYXk7XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIGlzQXJyYXkob2JqKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHRvU3RyaW5nLmNhbGwob2JqKSA9PT0gXCJbb2JqZWN0IEFycmF5XVwiO1xuICAgICAgICAgICAgfVxuICAgICAgICB9LCB7fV0sIDEzOiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge1xuICAgICAgICAgICAgdmFyIHBhdGNoID0gcmVxdWlyZShcIi4vdmRvbS9wYXRjaC5qc1wiKTtcblxuICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBwYXRjaDtcbiAgICAgICAgfSwgeyBcIi4vdmRvbS9wYXRjaC5qc1wiOiAxOCB9XSwgMTQ6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICB2YXIgaXNPYmplY3QgPSByZXF1aXJlKFwiaXMtb2JqZWN0XCIpO1xuICAgICAgICAgICAgdmFyIGlzSG9vayA9IHJlcXVpcmUoXCIuLi92bm9kZS9pcy12aG9vay5qc1wiKTtcblxuICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBhcHBseVByb3BlcnRpZXM7XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIGFwcGx5UHJvcGVydGllcyhub2RlLCBwcm9wcywgcHJldmlvdXMpIHtcbiAgICAgICAgICAgICAgICBmb3IgKHZhciBwcm9wTmFtZSBpbiBwcm9wcykge1xuICAgICAgICAgICAgICAgICAgICB2YXIgcHJvcFZhbHVlID0gcHJvcHNbcHJvcE5hbWVdO1xuXG4gICAgICAgICAgICAgICAgICAgIGlmIChwcm9wVmFsdWUgPT09IHVuZGVmaW5lZCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgcmVtb3ZlUHJvcGVydHkobm9kZSwgcHJvcE5hbWUsIHByb3BWYWx1ZSwgcHJldmlvdXMpO1xuICAgICAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKGlzSG9vayhwcm9wVmFsdWUpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICByZW1vdmVQcm9wZXJ0eShub2RlLCBwcm9wTmFtZSwgcHJvcFZhbHVlLCBwcmV2aW91cyk7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAocHJvcFZhbHVlLmhvb2spIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBwcm9wVmFsdWUuaG9vayhub2RlLCBwcm9wTmFtZSwgcHJldmlvdXMgPyBwcmV2aW91c1twcm9wTmFtZV0gOiB1bmRlZmluZWQpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGlzT2JqZWN0KHByb3BWYWx1ZSkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBwYXRjaE9iamVjdChub2RlLCBwcm9wcywgcHJldmlvdXMsIHByb3BOYW1lLCBwcm9wVmFsdWUpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBub2RlW3Byb3BOYW1lXSA9IHByb3BWYWx1ZTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZnVuY3Rpb24gcmVtb3ZlUHJvcGVydHkobm9kZSwgcHJvcE5hbWUsIHByb3BWYWx1ZSwgcHJldmlvdXMpIHtcbiAgICAgICAgICAgICAgICBpZiAocHJldmlvdXMpIHtcbiAgICAgICAgICAgICAgICAgICAgdmFyIHByZXZpb3VzVmFsdWUgPSBwcmV2aW91c1twcm9wTmFtZV07XG5cbiAgICAgICAgICAgICAgICAgICAgaWYgKCFpc0hvb2socHJldmlvdXNWYWx1ZSkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChwcm9wTmFtZSA9PT0gXCJhdHRyaWJ1dGVzXCIpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBmb3IgKHZhciBhdHRyTmFtZSBpbiBwcmV2aW91c1ZhbHVlKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG5vZGUucmVtb3ZlQXR0cmlidXRlKGF0dHJOYW1lKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKHByb3BOYW1lID09PSBcInN0eWxlXCIpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBmb3IgKHZhciBpIGluIHByZXZpb3VzVmFsdWUpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbm9kZS5zdHlsZVtpXSA9IFwiXCI7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIGlmICh0eXBlb2YgcHJldmlvdXNWYWx1ZSA9PT0gXCJzdHJpbmdcIikge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIG5vZGVbcHJvcE5hbWVdID0gXCJcIjtcbiAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgbm9kZVtwcm9wTmFtZV0gPSBudWxsO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKHByZXZpb3VzVmFsdWUudW5ob29rKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBwcmV2aW91c1ZhbHVlLnVuaG9vayhub2RlLCBwcm9wTmFtZSwgcHJvcFZhbHVlKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZnVuY3Rpb24gcGF0Y2hPYmplY3Qobm9kZSwgcHJvcHMsIHByZXZpb3VzLCBwcm9wTmFtZSwgcHJvcFZhbHVlKSB7XG4gICAgICAgICAgICAgICAgdmFyIHByZXZpb3VzVmFsdWUgPSBwcmV2aW91cyA/IHByZXZpb3VzW3Byb3BOYW1lXSA6IHVuZGVmaW5lZDtcblxuICAgICAgICAgICAgICAgIC8vIFNldCBhdHRyaWJ1dGVzXG4gICAgICAgICAgICAgICAgaWYgKHByb3BOYW1lID09PSBcImF0dHJpYnV0ZXNcIikge1xuICAgICAgICAgICAgICAgICAgICBmb3IgKHZhciBhdHRyTmFtZSBpbiBwcm9wVmFsdWUpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHZhciBhdHRyVmFsdWUgPSBwcm9wVmFsdWVbYXR0ck5hbWVdO1xuXG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoYXR0clZhbHVlID09PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBub2RlLnJlbW92ZUF0dHJpYnV0ZShhdHRyTmFtZSk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIG5vZGUuc2V0QXR0cmlidXRlKGF0dHJOYW1lLCBhdHRyVmFsdWUpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIGlmIChwcmV2aW91c1ZhbHVlICYmIGlzT2JqZWN0KHByZXZpb3VzVmFsdWUpICYmIGdldFByb3RvdHlwZShwcmV2aW91c1ZhbHVlKSAhPT0gZ2V0UHJvdG90eXBlKHByb3BWYWx1ZSkpIHtcbiAgICAgICAgICAgICAgICAgICAgbm9kZVtwcm9wTmFtZV0gPSBwcm9wVmFsdWU7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICBpZiAoIWlzT2JqZWN0KG5vZGVbcHJvcE5hbWVdKSkge1xuICAgICAgICAgICAgICAgICAgICBub2RlW3Byb3BOYW1lXSA9IHt9O1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHZhciByZXBsYWNlciA9IHByb3BOYW1lID09PSBcInN0eWxlXCIgPyBcIlwiIDogdW5kZWZpbmVkO1xuXG4gICAgICAgICAgICAgICAgZm9yICh2YXIgayBpbiBwcm9wVmFsdWUpIHtcbiAgICAgICAgICAgICAgICAgICAgdmFyIHZhbHVlID0gcHJvcFZhbHVlW2tdO1xuICAgICAgICAgICAgICAgICAgICBub2RlW3Byb3BOYW1lXVtrXSA9IHZhbHVlID09PSB1bmRlZmluZWQgPyByZXBsYWNlciA6IHZhbHVlO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZnVuY3Rpb24gZ2V0UHJvdG90eXBlKHZhbHVlKSB7XG4gICAgICAgICAgICAgICAgaWYgKE9iamVjdC5nZXRQcm90b3R5cGVPZikge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gT2JqZWN0LmdldFByb3RvdHlwZU9mKHZhbHVlKTtcbiAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKHZhbHVlLl9fcHJvdG9fXykge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gdmFsdWUuX19wcm90b19fO1xuICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAodmFsdWUuY29uc3RydWN0b3IpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHZhbHVlLmNvbnN0cnVjdG9yLnByb3RvdHlwZTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH0sIHsgXCIuLi92bm9kZS9pcy12aG9vay5qc1wiOiAyNiwgXCJpcy1vYmplY3RcIjogMTEgfV0sIDE1OiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge1xuICAgICAgICAgICAgdmFyIGRvY3VtZW50ID0gcmVxdWlyZShcImdsb2JhbC9kb2N1bWVudFwiKTtcblxuICAgICAgICAgICAgdmFyIGFwcGx5UHJvcGVydGllcyA9IHJlcXVpcmUoXCIuL2FwcGx5LXByb3BlcnRpZXNcIik7XG5cbiAgICAgICAgICAgIHZhciBpc1ZOb2RlID0gcmVxdWlyZShcIi4uL3Zub2RlL2lzLXZub2RlLmpzXCIpO1xuICAgICAgICAgICAgdmFyIGlzVlRleHQgPSByZXF1aXJlKFwiLi4vdm5vZGUvaXMtdnRleHQuanNcIik7XG4gICAgICAgICAgICB2YXIgaXNXaWRnZXQgPSByZXF1aXJlKFwiLi4vdm5vZGUvaXMtd2lkZ2V0LmpzXCIpO1xuICAgICAgICAgICAgdmFyIGhhbmRsZVRodW5rID0gcmVxdWlyZShcIi4uL3Zub2RlL2hhbmRsZS10aHVuay5qc1wiKTtcblxuICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBjcmVhdGVFbGVtZW50O1xuXG4gICAgICAgICAgICBmdW5jdGlvbiBjcmVhdGVFbGVtZW50KHZub2RlLCBvcHRzKSB7XG4gICAgICAgICAgICAgICAgdmFyIGRvYyA9IG9wdHMgPyBvcHRzLmRvY3VtZW50IHx8IGRvY3VtZW50IDogZG9jdW1lbnQ7XG4gICAgICAgICAgICAgICAgdmFyIHdhcm4gPSBvcHRzID8gb3B0cy53YXJuIDogbnVsbDtcblxuICAgICAgICAgICAgICAgIHZub2RlID0gaGFuZGxlVGh1bmsodm5vZGUpLmE7XG5cbiAgICAgICAgICAgICAgICBpZiAoaXNXaWRnZXQodm5vZGUpKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiB2bm9kZS5pbml0KCk7XG4gICAgICAgICAgICAgICAgfSBlbHNlIGlmIChpc1ZUZXh0KHZub2RlKSkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gZG9jLmNyZWF0ZVRleHROb2RlKHZub2RlLnRleHQpO1xuICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoIWlzVk5vZGUodm5vZGUpKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmICh3YXJuKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICB3YXJuKFwiSXRlbSBpcyBub3QgYSB2YWxpZCB2aXJ0dWFsIGRvbSBub2RlXCIsIHZub2RlKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICByZXR1cm4gbnVsbDtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICB2YXIgbm9kZSA9IHZub2RlLm5hbWVzcGFjZSA9PT0gbnVsbCA/IGRvYy5jcmVhdGVFbGVtZW50KHZub2RlLnRhZ05hbWUpIDogZG9jLmNyZWF0ZUVsZW1lbnROUyh2bm9kZS5uYW1lc3BhY2UsIHZub2RlLnRhZ05hbWUpO1xuXG4gICAgICAgICAgICAgICAgdmFyIHByb3BzID0gdm5vZGUucHJvcGVydGllcztcbiAgICAgICAgICAgICAgICBhcHBseVByb3BlcnRpZXMobm9kZSwgcHJvcHMpO1xuXG4gICAgICAgICAgICAgICAgdmFyIGNoaWxkcmVuID0gdm5vZGUuY2hpbGRyZW47XG5cbiAgICAgICAgICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IGNoaWxkcmVuLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciBjaGlsZE5vZGUgPSBjcmVhdGVFbGVtZW50KGNoaWxkcmVuW2ldLCBvcHRzKTtcbiAgICAgICAgICAgICAgICAgICAgaWYgKGNoaWxkTm9kZSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgbm9kZS5hcHBlbmRDaGlsZChjaGlsZE5vZGUpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgcmV0dXJuIG5vZGU7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0sIHsgXCIuLi92bm9kZS9oYW5kbGUtdGh1bmsuanNcIjogMjQsIFwiLi4vdm5vZGUvaXMtdm5vZGUuanNcIjogMjcsIFwiLi4vdm5vZGUvaXMtdnRleHQuanNcIjogMjgsIFwiLi4vdm5vZGUvaXMtd2lkZ2V0LmpzXCI6IDI5LCBcIi4vYXBwbHktcHJvcGVydGllc1wiOiAxNCwgXCJnbG9iYWwvZG9jdW1lbnRcIjogMTAgfV0sIDE2OiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge1xuICAgICAgICAgICAgLy8gTWFwcyBhIHZpcnR1YWwgRE9NIHRyZWUgb250byBhIHJlYWwgRE9NIHRyZWUgaW4gYW4gZWZmaWNpZW50IG1hbm5lci5cbiAgICAgICAgICAgIC8vIFdlIGRvbid0IHdhbnQgdG8gcmVhZCBhbGwgb2YgdGhlIERPTSBub2RlcyBpbiB0aGUgdHJlZSBzbyB3ZSB1c2VcbiAgICAgICAgICAgIC8vIHRoZSBpbi1vcmRlciB0cmVlIGluZGV4aW5nIHRvIGVsaW1pbmF0ZSByZWN1cnNpb24gZG93biBjZXJ0YWluIGJyYW5jaGVzLlxuICAgICAgICAgICAgLy8gV2Ugb25seSByZWN1cnNlIGludG8gYSBET00gbm9kZSBpZiB3ZSBrbm93IHRoYXQgaXQgY29udGFpbnMgYSBjaGlsZCBvZlxuICAgICAgICAgICAgLy8gaW50ZXJlc3QuXG5cbiAgICAgICAgICAgIHZhciBub0NoaWxkID0ge307XG5cbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gZG9tSW5kZXg7XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIGRvbUluZGV4KHJvb3ROb2RlLCB0cmVlLCBpbmRpY2VzLCBub2Rlcykge1xuICAgICAgICAgICAgICAgIGlmICghaW5kaWNlcyB8fCBpbmRpY2VzLmxlbmd0aCA9PT0gMCkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4ge307XG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgaW5kaWNlcy5zb3J0KGFzY2VuZGluZyk7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiByZWN1cnNlKHJvb3ROb2RlLCB0cmVlLCBpbmRpY2VzLCBub2RlcywgMCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBmdW5jdGlvbiByZWN1cnNlKHJvb3ROb2RlLCB0cmVlLCBpbmRpY2VzLCBub2Rlcywgcm9vdEluZGV4KSB7XG4gICAgICAgICAgICAgICAgbm9kZXMgPSBub2RlcyB8fCB7fTtcblxuICAgICAgICAgICAgICAgIGlmIChyb290Tm9kZSkge1xuICAgICAgICAgICAgICAgICAgICBpZiAoaW5kZXhJblJhbmdlKGluZGljZXMsIHJvb3RJbmRleCwgcm9vdEluZGV4KSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgbm9kZXNbcm9vdEluZGV4XSA9IHJvb3ROb2RlO1xuICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgdmFyIHZDaGlsZHJlbiA9IHRyZWUuY2hpbGRyZW47XG5cbiAgICAgICAgICAgICAgICAgICAgaWYgKHZDaGlsZHJlbikge1xuXG4gICAgICAgICAgICAgICAgICAgICAgICB2YXIgY2hpbGROb2RlcyA9IHJvb3ROb2RlLmNoaWxkTm9kZXM7XG5cbiAgICAgICAgICAgICAgICAgICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgdHJlZS5jaGlsZHJlbi5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJvb3RJbmRleCArPSAxO1xuXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdmFyIHZDaGlsZCA9IHZDaGlsZHJlbltpXSB8fCBub0NoaWxkO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZhciBuZXh0SW5kZXggPSByb290SW5kZXggKyAodkNoaWxkLmNvdW50IHx8IDApO1xuXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gc2tpcCByZWN1cnNpb24gZG93biB0aGUgdHJlZSBpZiB0aGVyZSBhcmUgbm8gbm9kZXMgZG93biBoZXJlXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGluZGV4SW5SYW5nZShpbmRpY2VzLCByb290SW5kZXgsIG5leHRJbmRleCkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmVjdXJzZShjaGlsZE5vZGVzW2ldLCB2Q2hpbGQsIGluZGljZXMsIG5vZGVzLCByb290SW5kZXgpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJvb3RJbmRleCA9IG5leHRJbmRleDtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHJldHVybiBub2RlcztcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgLy8gQmluYXJ5IHNlYXJjaCBmb3IgYW4gaW5kZXggaW4gdGhlIGludGVydmFsIFtsZWZ0LCByaWdodF1cbiAgICAgICAgICAgIGZ1bmN0aW9uIGluZGV4SW5SYW5nZShpbmRpY2VzLCBsZWZ0LCByaWdodCkge1xuICAgICAgICAgICAgICAgIGlmIChpbmRpY2VzLmxlbmd0aCA9PT0gMCkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgdmFyIG1pbkluZGV4ID0gMDtcbiAgICAgICAgICAgICAgICB2YXIgbWF4SW5kZXggPSBpbmRpY2VzLmxlbmd0aCAtIDE7XG4gICAgICAgICAgICAgICAgdmFyIGN1cnJlbnRJbmRleDtcbiAgICAgICAgICAgICAgICB2YXIgY3VycmVudEl0ZW07XG5cbiAgICAgICAgICAgICAgICB3aGlsZSAobWluSW5kZXggPD0gbWF4SW5kZXgpIHtcbiAgICAgICAgICAgICAgICAgICAgY3VycmVudEluZGV4ID0gKG1heEluZGV4ICsgbWluSW5kZXgpIC8gMiA+PiAwO1xuICAgICAgICAgICAgICAgICAgICBjdXJyZW50SXRlbSA9IGluZGljZXNbY3VycmVudEluZGV4XTtcblxuICAgICAgICAgICAgICAgICAgICBpZiAobWluSW5kZXggPT09IG1heEluZGV4KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gY3VycmVudEl0ZW0gPj0gbGVmdCAmJiBjdXJyZW50SXRlbSA8PSByaWdodDtcbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIGlmIChjdXJyZW50SXRlbSA8IGxlZnQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIG1pbkluZGV4ID0gY3VycmVudEluZGV4ICsgMTtcbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIGlmIChjdXJyZW50SXRlbSA+IHJpZ2h0KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBtYXhJbmRleCA9IGN1cnJlbnRJbmRleCAtIDE7XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZnVuY3Rpb24gYXNjZW5kaW5nKGEsIGIpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gYSA+IGIgPyAxIDogLTE7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0sIHt9XSwgMTc6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICB2YXIgYXBwbHlQcm9wZXJ0aWVzID0gcmVxdWlyZShcIi4vYXBwbHktcHJvcGVydGllc1wiKTtcblxuICAgICAgICAgICAgdmFyIGlzV2lkZ2V0ID0gcmVxdWlyZShcIi4uL3Zub2RlL2lzLXdpZGdldC5qc1wiKTtcbiAgICAgICAgICAgIHZhciBWUGF0Y2ggPSByZXF1aXJlKFwiLi4vdm5vZGUvdnBhdGNoLmpzXCIpO1xuXG4gICAgICAgICAgICB2YXIgdXBkYXRlV2lkZ2V0ID0gcmVxdWlyZShcIi4vdXBkYXRlLXdpZGdldFwiKTtcblxuICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBhcHBseVBhdGNoO1xuXG4gICAgICAgICAgICBmdW5jdGlvbiBhcHBseVBhdGNoKHZwYXRjaCwgZG9tTm9kZSwgcmVuZGVyT3B0aW9ucykge1xuICAgICAgICAgICAgICAgIHZhciB0eXBlID0gdnBhdGNoLnR5cGU7XG4gICAgICAgICAgICAgICAgdmFyIHZOb2RlID0gdnBhdGNoLnZOb2RlO1xuICAgICAgICAgICAgICAgIHZhciBwYXRjaCA9IHZwYXRjaC5wYXRjaDtcblxuICAgICAgICAgICAgICAgIHN3aXRjaCAodHlwZSkge1xuICAgICAgICAgICAgICAgICAgICBjYXNlIFZQYXRjaC5SRU1PVkU6XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gcmVtb3ZlTm9kZShkb21Ob2RlLCB2Tm9kZSk7XG4gICAgICAgICAgICAgICAgICAgIGNhc2UgVlBhdGNoLklOU0VSVDpcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBpbnNlcnROb2RlKGRvbU5vZGUsIHBhdGNoLCByZW5kZXJPcHRpb25zKTtcbiAgICAgICAgICAgICAgICAgICAgY2FzZSBWUGF0Y2guVlRFWFQ6XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gc3RyaW5nUGF0Y2goZG9tTm9kZSwgdk5vZGUsIHBhdGNoLCByZW5kZXJPcHRpb25zKTtcbiAgICAgICAgICAgICAgICAgICAgY2FzZSBWUGF0Y2guV0lER0VUOlxuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHdpZGdldFBhdGNoKGRvbU5vZGUsIHZOb2RlLCBwYXRjaCwgcmVuZGVyT3B0aW9ucyk7XG4gICAgICAgICAgICAgICAgICAgIGNhc2UgVlBhdGNoLlZOT0RFOlxuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHZOb2RlUGF0Y2goZG9tTm9kZSwgdk5vZGUsIHBhdGNoLCByZW5kZXJPcHRpb25zKTtcbiAgICAgICAgICAgICAgICAgICAgY2FzZSBWUGF0Y2guT1JERVI6XG4gICAgICAgICAgICAgICAgICAgICAgICByZW9yZGVyQ2hpbGRyZW4oZG9tTm9kZSwgcGF0Y2gpO1xuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGRvbU5vZGU7XG4gICAgICAgICAgICAgICAgICAgIGNhc2UgVlBhdGNoLlBST1BTOlxuICAgICAgICAgICAgICAgICAgICAgICAgYXBwbHlQcm9wZXJ0aWVzKGRvbU5vZGUsIHBhdGNoLCB2Tm9kZS5wcm9wZXJ0aWVzKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBkb21Ob2RlO1xuICAgICAgICAgICAgICAgICAgICBjYXNlIFZQYXRjaC5USFVOSzpcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiByZXBsYWNlUm9vdChkb21Ob2RlLCByZW5kZXJPcHRpb25zLnBhdGNoKGRvbU5vZGUsIHBhdGNoLCByZW5kZXJPcHRpb25zKSk7XG4gICAgICAgICAgICAgICAgICAgIGRlZmF1bHQ6XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gZG9tTm9kZTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIHJlbW92ZU5vZGUoZG9tTm9kZSwgdk5vZGUpIHtcbiAgICAgICAgICAgICAgICB2YXIgcGFyZW50Tm9kZSA9IGRvbU5vZGUucGFyZW50Tm9kZTtcblxuICAgICAgICAgICAgICAgIGlmIChwYXJlbnROb2RlKSB7XG4gICAgICAgICAgICAgICAgICAgIHBhcmVudE5vZGUucmVtb3ZlQ2hpbGQoZG9tTm9kZSk7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgZGVzdHJveVdpZGdldChkb21Ob2RlLCB2Tm9kZSk7XG5cbiAgICAgICAgICAgICAgICByZXR1cm4gbnVsbDtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZnVuY3Rpb24gaW5zZXJ0Tm9kZShwYXJlbnROb2RlLCB2Tm9kZSwgcmVuZGVyT3B0aW9ucykge1xuICAgICAgICAgICAgICAgIHZhciBuZXdOb2RlID0gcmVuZGVyT3B0aW9ucy5yZW5kZXIodk5vZGUsIHJlbmRlck9wdGlvbnMpO1xuXG4gICAgICAgICAgICAgICAgaWYgKHBhcmVudE5vZGUpIHtcbiAgICAgICAgICAgICAgICAgICAgcGFyZW50Tm9kZS5hcHBlbmRDaGlsZChuZXdOb2RlKTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICByZXR1cm4gcGFyZW50Tm9kZTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZnVuY3Rpb24gc3RyaW5nUGF0Y2goZG9tTm9kZSwgbGVmdFZOb2RlLCB2VGV4dCwgcmVuZGVyT3B0aW9ucykge1xuICAgICAgICAgICAgICAgIHZhciBuZXdOb2RlO1xuXG4gICAgICAgICAgICAgICAgaWYgKGRvbU5vZGUubm9kZVR5cGUgPT09IDMpIHtcbiAgICAgICAgICAgICAgICAgICAgZG9tTm9kZS5yZXBsYWNlRGF0YSgwLCBkb21Ob2RlLmxlbmd0aCwgdlRleHQudGV4dCk7XG4gICAgICAgICAgICAgICAgICAgIG5ld05vZGUgPSBkb21Ob2RlO1xuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciBwYXJlbnROb2RlID0gZG9tTm9kZS5wYXJlbnROb2RlO1xuICAgICAgICAgICAgICAgICAgICBuZXdOb2RlID0gcmVuZGVyT3B0aW9ucy5yZW5kZXIodlRleHQsIHJlbmRlck9wdGlvbnMpO1xuXG4gICAgICAgICAgICAgICAgICAgIGlmIChwYXJlbnROb2RlICYmIG5ld05vZGUgIT09IGRvbU5vZGUpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHBhcmVudE5vZGUucmVwbGFjZUNoaWxkKG5ld05vZGUsIGRvbU5vZGUpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgcmV0dXJuIG5ld05vZGU7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIHdpZGdldFBhdGNoKGRvbU5vZGUsIGxlZnRWTm9kZSwgd2lkZ2V0LCByZW5kZXJPcHRpb25zKSB7XG4gICAgICAgICAgICAgICAgdmFyIHVwZGF0aW5nID0gdXBkYXRlV2lkZ2V0KGxlZnRWTm9kZSwgd2lkZ2V0KTtcbiAgICAgICAgICAgICAgICB2YXIgbmV3Tm9kZTtcblxuICAgICAgICAgICAgICAgIGlmICh1cGRhdGluZykge1xuICAgICAgICAgICAgICAgICAgICBuZXdOb2RlID0gd2lkZ2V0LnVwZGF0ZShsZWZ0Vk5vZGUsIGRvbU5vZGUpIHx8IGRvbU5vZGU7XG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgbmV3Tm9kZSA9IHJlbmRlck9wdGlvbnMucmVuZGVyKHdpZGdldCwgcmVuZGVyT3B0aW9ucyk7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgdmFyIHBhcmVudE5vZGUgPSBkb21Ob2RlLnBhcmVudE5vZGU7XG5cbiAgICAgICAgICAgICAgICBpZiAocGFyZW50Tm9kZSAmJiBuZXdOb2RlICE9PSBkb21Ob2RlKSB7XG4gICAgICAgICAgICAgICAgICAgIHBhcmVudE5vZGUucmVwbGFjZUNoaWxkKG5ld05vZGUsIGRvbU5vZGUpO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIGlmICghdXBkYXRpbmcpIHtcbiAgICAgICAgICAgICAgICAgICAgZGVzdHJveVdpZGdldChkb21Ob2RlLCBsZWZ0Vk5vZGUpO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHJldHVybiBuZXdOb2RlO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBmdW5jdGlvbiB2Tm9kZVBhdGNoKGRvbU5vZGUsIGxlZnRWTm9kZSwgdk5vZGUsIHJlbmRlck9wdGlvbnMpIHtcbiAgICAgICAgICAgICAgICB2YXIgcGFyZW50Tm9kZSA9IGRvbU5vZGUucGFyZW50Tm9kZTtcbiAgICAgICAgICAgICAgICB2YXIgbmV3Tm9kZSA9IHJlbmRlck9wdGlvbnMucmVuZGVyKHZOb2RlLCByZW5kZXJPcHRpb25zKTtcblxuICAgICAgICAgICAgICAgIGlmIChwYXJlbnROb2RlICYmIG5ld05vZGUgIT09IGRvbU5vZGUpIHtcbiAgICAgICAgICAgICAgICAgICAgcGFyZW50Tm9kZS5yZXBsYWNlQ2hpbGQobmV3Tm9kZSwgZG9tTm9kZSk7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgcmV0dXJuIG5ld05vZGU7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIGRlc3Ryb3lXaWRnZXQoZG9tTm9kZSwgdykge1xuICAgICAgICAgICAgICAgIGlmICh0eXBlb2Ygdy5kZXN0cm95ID09PSBcImZ1bmN0aW9uXCIgJiYgaXNXaWRnZXQodykpIHtcbiAgICAgICAgICAgICAgICAgICAgdy5kZXN0cm95KGRvbU5vZGUpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZnVuY3Rpb24gcmVvcmRlckNoaWxkcmVuKGRvbU5vZGUsIG1vdmVzKSB7XG4gICAgICAgICAgICAgICAgdmFyIGNoaWxkTm9kZXMgPSBkb21Ob2RlLmNoaWxkTm9kZXM7XG4gICAgICAgICAgICAgICAgdmFyIGtleU1hcCA9IHt9O1xuICAgICAgICAgICAgICAgIHZhciBub2RlO1xuICAgICAgICAgICAgICAgIHZhciByZW1vdmU7XG4gICAgICAgICAgICAgICAgdmFyIGluc2VydDtcblxuICAgICAgICAgICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgbW92ZXMucmVtb3Zlcy5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgICAgICAgICByZW1vdmUgPSBtb3Zlcy5yZW1vdmVzW2ldO1xuICAgICAgICAgICAgICAgICAgICBub2RlID0gY2hpbGROb2Rlc1tyZW1vdmUuZnJvbV07XG4gICAgICAgICAgICAgICAgICAgIGlmIChyZW1vdmUua2V5KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBrZXlNYXBbcmVtb3ZlLmtleV0gPSBub2RlO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIGRvbU5vZGUucmVtb3ZlQ2hpbGQobm9kZSk7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgdmFyIGxlbmd0aCA9IGNoaWxkTm9kZXMubGVuZ3RoO1xuICAgICAgICAgICAgICAgIGZvciAodmFyIGogPSAwOyBqIDwgbW92ZXMuaW5zZXJ0cy5sZW5ndGg7IGorKykge1xuICAgICAgICAgICAgICAgICAgICBpbnNlcnQgPSBtb3Zlcy5pbnNlcnRzW2pdO1xuICAgICAgICAgICAgICAgICAgICBub2RlID0ga2V5TWFwW2luc2VydC5rZXldO1xuICAgICAgICAgICAgICAgICAgICAvLyB0aGlzIGlzIHRoZSB3ZWlyZGVzdCBidWcgaSd2ZSBldmVyIHNlZW4gaW4gd2Via2l0XG4gICAgICAgICAgICAgICAgICAgIGRvbU5vZGUuaW5zZXJ0QmVmb3JlKG5vZGUsIGluc2VydC50byA+PSBsZW5ndGgrKyA/IG51bGwgOiBjaGlsZE5vZGVzW2luc2VydC50b10pO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZnVuY3Rpb24gcmVwbGFjZVJvb3Qob2xkUm9vdCwgbmV3Um9vdCkge1xuICAgICAgICAgICAgICAgIGlmIChvbGRSb290ICYmIG5ld1Jvb3QgJiYgb2xkUm9vdCAhPT0gbmV3Um9vdCAmJiBvbGRSb290LnBhcmVudE5vZGUpIHtcbiAgICAgICAgICAgICAgICAgICAgb2xkUm9vdC5wYXJlbnROb2RlLnJlcGxhY2VDaGlsZChuZXdSb290LCBvbGRSb290KTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICByZXR1cm4gbmV3Um9vdDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSwgeyBcIi4uL3Zub2RlL2lzLXdpZGdldC5qc1wiOiAyOSwgXCIuLi92bm9kZS92cGF0Y2guanNcIjogMzIsIFwiLi9hcHBseS1wcm9wZXJ0aWVzXCI6IDE0LCBcIi4vdXBkYXRlLXdpZGdldFwiOiAxOSB9XSwgMTg6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICB2YXIgZG9jdW1lbnQgPSByZXF1aXJlKFwiZ2xvYmFsL2RvY3VtZW50XCIpO1xuICAgICAgICAgICAgdmFyIGlzQXJyYXkgPSByZXF1aXJlKFwieC1pcy1hcnJheVwiKTtcblxuICAgICAgICAgICAgdmFyIHJlbmRlciA9IHJlcXVpcmUoXCIuL2NyZWF0ZS1lbGVtZW50XCIpO1xuICAgICAgICAgICAgdmFyIGRvbUluZGV4ID0gcmVxdWlyZShcIi4vZG9tLWluZGV4XCIpO1xuICAgICAgICAgICAgdmFyIHBhdGNoT3AgPSByZXF1aXJlKFwiLi9wYXRjaC1vcFwiKTtcbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gcGF0Y2g7XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIHBhdGNoKHJvb3ROb2RlLCBwYXRjaGVzLCByZW5kZXJPcHRpb25zKSB7XG4gICAgICAgICAgICAgICAgcmVuZGVyT3B0aW9ucyA9IHJlbmRlck9wdGlvbnMgfHwge307XG4gICAgICAgICAgICAgICAgcmVuZGVyT3B0aW9ucy5wYXRjaCA9IHJlbmRlck9wdGlvbnMucGF0Y2ggJiYgcmVuZGVyT3B0aW9ucy5wYXRjaCAhPT0gcGF0Y2ggPyByZW5kZXJPcHRpb25zLnBhdGNoIDogcGF0Y2hSZWN1cnNpdmU7XG4gICAgICAgICAgICAgICAgcmVuZGVyT3B0aW9ucy5yZW5kZXIgPSByZW5kZXJPcHRpb25zLnJlbmRlciB8fCByZW5kZXI7XG5cbiAgICAgICAgICAgICAgICByZXR1cm4gcmVuZGVyT3B0aW9ucy5wYXRjaChyb290Tm9kZSwgcGF0Y2hlcywgcmVuZGVyT3B0aW9ucyk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIHBhdGNoUmVjdXJzaXZlKHJvb3ROb2RlLCBwYXRjaGVzLCByZW5kZXJPcHRpb25zKSB7XG4gICAgICAgICAgICAgICAgdmFyIGluZGljZXMgPSBwYXRjaEluZGljZXMocGF0Y2hlcyk7XG5cbiAgICAgICAgICAgICAgICBpZiAoaW5kaWNlcy5sZW5ndGggPT09IDApIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHJvb3ROb2RlO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHZhciBpbmRleCA9IGRvbUluZGV4KHJvb3ROb2RlLCBwYXRjaGVzLmEsIGluZGljZXMpO1xuICAgICAgICAgICAgICAgIHZhciBvd25lckRvY3VtZW50ID0gcm9vdE5vZGUub3duZXJEb2N1bWVudDtcblxuICAgICAgICAgICAgICAgIGlmICghcmVuZGVyT3B0aW9ucy5kb2N1bWVudCAmJiBvd25lckRvY3VtZW50ICE9PSBkb2N1bWVudCkge1xuICAgICAgICAgICAgICAgICAgICByZW5kZXJPcHRpb25zLmRvY3VtZW50ID0gb3duZXJEb2N1bWVudDtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IGluZGljZXMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgICAgICAgICAgdmFyIG5vZGVJbmRleCA9IGluZGljZXNbaV07XG4gICAgICAgICAgICAgICAgICAgIHJvb3ROb2RlID0gYXBwbHlQYXRjaChyb290Tm9kZSwgaW5kZXhbbm9kZUluZGV4XSwgcGF0Y2hlc1tub2RlSW5kZXhdLCByZW5kZXJPcHRpb25zKTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICByZXR1cm4gcm9vdE5vZGU7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIGFwcGx5UGF0Y2gocm9vdE5vZGUsIGRvbU5vZGUsIHBhdGNoTGlzdCwgcmVuZGVyT3B0aW9ucykge1xuICAgICAgICAgICAgICAgIGlmICghZG9tTm9kZSkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gcm9vdE5vZGU7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgdmFyIG5ld05vZGU7XG5cbiAgICAgICAgICAgICAgICBpZiAoaXNBcnJheShwYXRjaExpc3QpKSB7XG4gICAgICAgICAgICAgICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgcGF0Y2hMaXN0Lmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBuZXdOb2RlID0gcGF0Y2hPcChwYXRjaExpc3RbaV0sIGRvbU5vZGUsIHJlbmRlck9wdGlvbnMpO1xuXG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoZG9tTm9kZSA9PT0gcm9vdE5vZGUpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICByb290Tm9kZSA9IG5ld05vZGU7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICBuZXdOb2RlID0gcGF0Y2hPcChwYXRjaExpc3QsIGRvbU5vZGUsIHJlbmRlck9wdGlvbnMpO1xuXG4gICAgICAgICAgICAgICAgICAgIGlmIChkb21Ob2RlID09PSByb290Tm9kZSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgcm9vdE5vZGUgPSBuZXdOb2RlO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgcmV0dXJuIHJvb3ROb2RlO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBmdW5jdGlvbiBwYXRjaEluZGljZXMocGF0Y2hlcykge1xuICAgICAgICAgICAgICAgIHZhciBpbmRpY2VzID0gW107XG5cbiAgICAgICAgICAgICAgICBmb3IgKHZhciBrZXkgaW4gcGF0Y2hlcykge1xuICAgICAgICAgICAgICAgICAgICBpZiAoa2V5ICE9PSBcImFcIikge1xuICAgICAgICAgICAgICAgICAgICAgICAgaW5kaWNlcy5wdXNoKE51bWJlcihrZXkpKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHJldHVybiBpbmRpY2VzO1xuICAgICAgICAgICAgfVxuICAgICAgICB9LCB7IFwiLi9jcmVhdGUtZWxlbWVudFwiOiAxNSwgXCIuL2RvbS1pbmRleFwiOiAxNiwgXCIuL3BhdGNoLW9wXCI6IDE3LCBcImdsb2JhbC9kb2N1bWVudFwiOiAxMCwgXCJ4LWlzLWFycmF5XCI6IDEyIH1dLCAxOTogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHtcbiAgICAgICAgICAgIHZhciBpc1dpZGdldCA9IHJlcXVpcmUoXCIuLi92bm9kZS9pcy13aWRnZXQuanNcIik7XG5cbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gdXBkYXRlV2lkZ2V0O1xuXG4gICAgICAgICAgICBmdW5jdGlvbiB1cGRhdGVXaWRnZXQoYSwgYikge1xuICAgICAgICAgICAgICAgIGlmIChpc1dpZGdldChhKSAmJiBpc1dpZGdldChiKSkge1xuICAgICAgICAgICAgICAgICAgICBpZiAoXCJuYW1lXCIgaW4gYSAmJiBcIm5hbWVcIiBpbiBiKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gYS5pZCA9PT0gYi5pZDtcbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBhLmluaXQgPT09IGIuaW5pdDtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSwgeyBcIi4uL3Zub2RlL2lzLXdpZGdldC5qc1wiOiAyOSB9XSwgMjA6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICBcInVzZSBzdHJpY3RcIjtcblxuICAgICAgICAgICAgdmFyIEV2U3RvcmUgPSByZXF1aXJlKFwiZXYtc3RvcmVcIik7XG5cbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gRXZIb29rO1xuXG4gICAgICAgICAgICBmdW5jdGlvbiBFdkhvb2sodmFsdWUpIHtcbiAgICAgICAgICAgICAgICBpZiAoISh0aGlzIGluc3RhbmNlb2YgRXZIb29rKSkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gbmV3IEV2SG9vayh2YWx1ZSk7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgdGhpcy52YWx1ZSA9IHZhbHVlO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBFdkhvb2sucHJvdG90eXBlLmhvb2sgPSBmdW5jdGlvbiAobm9kZSwgcHJvcGVydHlOYW1lKSB7XG4gICAgICAgICAgICAgICAgdmFyIGVzID0gRXZTdG9yZShub2RlKTtcbiAgICAgICAgICAgICAgICB2YXIgcHJvcE5hbWUgPSBwcm9wZXJ0eU5hbWUuc3Vic3RyKDMpO1xuXG4gICAgICAgICAgICAgICAgZXNbcHJvcE5hbWVdID0gdGhpcy52YWx1ZTtcbiAgICAgICAgICAgIH07XG5cbiAgICAgICAgICAgIEV2SG9vay5wcm90b3R5cGUudW5ob29rID0gZnVuY3Rpb24gKG5vZGUsIHByb3BlcnR5TmFtZSkge1xuICAgICAgICAgICAgICAgIHZhciBlcyA9IEV2U3RvcmUobm9kZSk7XG4gICAgICAgICAgICAgICAgdmFyIHByb3BOYW1lID0gcHJvcGVydHlOYW1lLnN1YnN0cigzKTtcblxuICAgICAgICAgICAgICAgIGVzW3Byb3BOYW1lXSA9IHVuZGVmaW5lZDtcbiAgICAgICAgICAgIH07XG4gICAgICAgIH0sIHsgXCJldi1zdG9yZVwiOiA3IH1dLCAyMTogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHtcbiAgICAgICAgICAgIFwidXNlIHN0cmljdFwiO1xuXG4gICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IFNvZnRTZXRIb29rO1xuXG4gICAgICAgICAgICBmdW5jdGlvbiBTb2Z0U2V0SG9vayh2YWx1ZSkge1xuICAgICAgICAgICAgICAgIGlmICghKHRoaXMgaW5zdGFuY2VvZiBTb2Z0U2V0SG9vaykpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIG5ldyBTb2Z0U2V0SG9vayh2YWx1ZSk7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgdGhpcy52YWx1ZSA9IHZhbHVlO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBTb2Z0U2V0SG9vay5wcm90b3R5cGUuaG9vayA9IGZ1bmN0aW9uIChub2RlLCBwcm9wZXJ0eU5hbWUpIHtcbiAgICAgICAgICAgICAgICBpZiAobm9kZVtwcm9wZXJ0eU5hbWVdICE9PSB0aGlzLnZhbHVlKSB7XG4gICAgICAgICAgICAgICAgICAgIG5vZGVbcHJvcGVydHlOYW1lXSA9IHRoaXMudmFsdWU7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfTtcbiAgICAgICAgfSwge31dLCAyMjogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHtcbiAgICAgICAgICAgIFwidXNlIHN0cmljdFwiO1xuXG4gICAgICAgICAgICB2YXIgaXNBcnJheSA9IHJlcXVpcmUoXCJ4LWlzLWFycmF5XCIpO1xuXG4gICAgICAgICAgICB2YXIgVk5vZGUgPSByZXF1aXJlKFwiLi4vdm5vZGUvdm5vZGUuanNcIik7XG4gICAgICAgICAgICB2YXIgVlRleHQgPSByZXF1aXJlKFwiLi4vdm5vZGUvdnRleHQuanNcIik7XG4gICAgICAgICAgICB2YXIgaXNWTm9kZSA9IHJlcXVpcmUoXCIuLi92bm9kZS9pcy12bm9kZVwiKTtcbiAgICAgICAgICAgIHZhciBpc1ZUZXh0ID0gcmVxdWlyZShcIi4uL3Zub2RlL2lzLXZ0ZXh0XCIpO1xuICAgICAgICAgICAgdmFyIGlzV2lkZ2V0ID0gcmVxdWlyZShcIi4uL3Zub2RlL2lzLXdpZGdldFwiKTtcbiAgICAgICAgICAgIHZhciBpc0hvb2sgPSByZXF1aXJlKFwiLi4vdm5vZGUvaXMtdmhvb2tcIik7XG4gICAgICAgICAgICB2YXIgaXNWVGh1bmsgPSByZXF1aXJlKFwiLi4vdm5vZGUvaXMtdGh1bmtcIik7XG5cbiAgICAgICAgICAgIHZhciBwYXJzZVRhZyA9IHJlcXVpcmUoXCIuL3BhcnNlLXRhZy5qc1wiKTtcbiAgICAgICAgICAgIHZhciBzb2Z0U2V0SG9vayA9IHJlcXVpcmUoXCIuL2hvb2tzL3NvZnQtc2V0LWhvb2suanNcIik7XG4gICAgICAgICAgICB2YXIgZXZIb29rID0gcmVxdWlyZShcIi4vaG9va3MvZXYtaG9vay5qc1wiKTtcblxuICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBoO1xuXG4gICAgICAgICAgICBmdW5jdGlvbiBoKHRhZ05hbWUsIHByb3BlcnRpZXMsIGNoaWxkcmVuKSB7XG4gICAgICAgICAgICAgICAgdmFyIGNoaWxkTm9kZXMgPSBbXTtcbiAgICAgICAgICAgICAgICB2YXIgdGFnLCBwcm9wcywga2V5LCBuYW1lc3BhY2U7XG5cbiAgICAgICAgICAgICAgICBpZiAoIWNoaWxkcmVuICYmIGlzQ2hpbGRyZW4ocHJvcGVydGllcykpIHtcbiAgICAgICAgICAgICAgICAgICAgY2hpbGRyZW4gPSBwcm9wZXJ0aWVzO1xuICAgICAgICAgICAgICAgICAgICBwcm9wcyA9IHt9O1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHByb3BzID0gcHJvcHMgfHwgcHJvcGVydGllcyB8fCB7fTtcbiAgICAgICAgICAgICAgICB0YWcgPSBwYXJzZVRhZyh0YWdOYW1lLCBwcm9wcyk7XG5cbiAgICAgICAgICAgICAgICAvLyBzdXBwb3J0IGtleXNcbiAgICAgICAgICAgICAgICBpZiAocHJvcHMuaGFzT3duUHJvcGVydHkoXCJrZXlcIikpIHtcbiAgICAgICAgICAgICAgICAgICAga2V5ID0gcHJvcHMua2V5O1xuICAgICAgICAgICAgICAgICAgICBwcm9wcy5rZXkgPSB1bmRlZmluZWQ7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgLy8gc3VwcG9ydCBuYW1lc3BhY2VcbiAgICAgICAgICAgICAgICBpZiAocHJvcHMuaGFzT3duUHJvcGVydHkoXCJuYW1lc3BhY2VcIikpIHtcbiAgICAgICAgICAgICAgICAgICAgbmFtZXNwYWNlID0gcHJvcHMubmFtZXNwYWNlO1xuICAgICAgICAgICAgICAgICAgICBwcm9wcy5uYW1lc3BhY2UgPSB1bmRlZmluZWQ7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgLy8gZml4IGN1cnNvciBidWdcbiAgICAgICAgICAgICAgICBpZiAodGFnID09PSBcIklOUFVUXCIgJiYgIW5hbWVzcGFjZSAmJiBwcm9wcy5oYXNPd25Qcm9wZXJ0eShcInZhbHVlXCIpICYmIHByb3BzLnZhbHVlICE9PSB1bmRlZmluZWQgJiYgIWlzSG9vayhwcm9wcy52YWx1ZSkpIHtcbiAgICAgICAgICAgICAgICAgICAgcHJvcHMudmFsdWUgPSBzb2Z0U2V0SG9vayhwcm9wcy52YWx1ZSk7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgdHJhbnNmb3JtUHJvcGVydGllcyhwcm9wcyk7XG5cbiAgICAgICAgICAgICAgICBpZiAoY2hpbGRyZW4gIT09IHVuZGVmaW5lZCAmJiBjaGlsZHJlbiAhPT0gbnVsbCkge1xuICAgICAgICAgICAgICAgICAgICBhZGRDaGlsZChjaGlsZHJlbiwgY2hpbGROb2RlcywgdGFnLCBwcm9wcyk7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgcmV0dXJuIG5ldyBWTm9kZSh0YWcsIHByb3BzLCBjaGlsZE5vZGVzLCBrZXksIG5hbWVzcGFjZSk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIGFkZENoaWxkKGMsIGNoaWxkTm9kZXMsIHRhZywgcHJvcHMpIHtcbiAgICAgICAgICAgICAgICBpZiAodHlwZW9mIGMgPT09IFwic3RyaW5nXCIpIHtcbiAgICAgICAgICAgICAgICAgICAgY2hpbGROb2Rlcy5wdXNoKG5ldyBWVGV4dChjKSk7XG4gICAgICAgICAgICAgICAgfSBlbHNlIGlmICh0eXBlb2YgYyA9PT0gXCJudW1iZXJcIikge1xuICAgICAgICAgICAgICAgICAgICBjaGlsZE5vZGVzLnB1c2gobmV3IFZUZXh0KFN0cmluZyhjKSkpO1xuICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoaXNDaGlsZChjKSkge1xuICAgICAgICAgICAgICAgICAgICBjaGlsZE5vZGVzLnB1c2goYyk7XG4gICAgICAgICAgICAgICAgfSBlbHNlIGlmIChpc0FycmF5KGMpKSB7XG4gICAgICAgICAgICAgICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgYy5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgICAgICAgICAgICAgYWRkQ2hpbGQoY1tpXSwgY2hpbGROb2RlcywgdGFnLCBwcm9wcyk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKGMgPT09IG51bGwgfHwgYyA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICB0aHJvdyBVbmV4cGVjdGVkVmlydHVhbEVsZW1lbnQoe1xuICAgICAgICAgICAgICAgICAgICAgICAgZm9yZWlnbk9iamVjdDogYyxcbiAgICAgICAgICAgICAgICAgICAgICAgIHBhcmVudFZub2RlOiB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdGFnTmFtZTogdGFnLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHByb3BlcnRpZXM6IHByb3BzXG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZnVuY3Rpb24gdHJhbnNmb3JtUHJvcGVydGllcyhwcm9wcykge1xuICAgICAgICAgICAgICAgIGZvciAodmFyIHByb3BOYW1lIGluIHByb3BzKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmIChwcm9wcy5oYXNPd25Qcm9wZXJ0eShwcm9wTmFtZSkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHZhciB2YWx1ZSA9IHByb3BzW3Byb3BOYW1lXTtcblxuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGlzSG9vayh2YWx1ZSkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb250aW51ZTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHByb3BOYW1lLnN1YnN0cigwLCAzKSA9PT0gXCJldi1cIikge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIGFkZCBldi1mb28gc3VwcG9ydFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHByb3BzW3Byb3BOYW1lXSA9IGV2SG9vayh2YWx1ZSk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIGlzQ2hpbGQoeCkge1xuICAgICAgICAgICAgICAgIHJldHVybiBpc1ZOb2RlKHgpIHx8IGlzVlRleHQoeCkgfHwgaXNXaWRnZXQoeCkgfHwgaXNWVGh1bmsoeCk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIGlzQ2hpbGRyZW4oeCkge1xuICAgICAgICAgICAgICAgIHJldHVybiB0eXBlb2YgeCA9PT0gXCJzdHJpbmdcIiB8fCBpc0FycmF5KHgpIHx8IGlzQ2hpbGQoeCk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIFVuZXhwZWN0ZWRWaXJ0dWFsRWxlbWVudChkYXRhKSB7XG4gICAgICAgICAgICAgICAgdmFyIGVyciA9IG5ldyBFcnJvcigpO1xuXG4gICAgICAgICAgICAgICAgZXJyLnR5cGUgPSBcInZpcnR1YWwtaHlwZXJzY3JpcHQudW5leHBlY3RlZC52aXJ0dWFsLWVsZW1lbnRcIjtcbiAgICAgICAgICAgICAgICBlcnIubWVzc2FnZSA9IFwiVW5leHBlY3RlZCB2aXJ0dWFsIGNoaWxkIHBhc3NlZCB0byBoKCkuXFxuXCIgKyBcIkV4cGVjdGVkIGEgVk5vZGUgLyBWdGh1bmsgLyBWV2lkZ2V0IC8gc3RyaW5nIGJ1dDpcXG5cIiArIFwiZ290OlxcblwiICsgZXJyb3JTdHJpbmcoZGF0YS5mb3JlaWduT2JqZWN0KSArIFwiLlxcblwiICsgXCJUaGUgcGFyZW50IHZub2RlIGlzOlxcblwiICsgZXJyb3JTdHJpbmcoZGF0YS5wYXJlbnRWbm9kZSk7XG4gICAgICAgICAgICAgICAgXCJcXG5cIiArIFwiU3VnZ2VzdGVkIGZpeDogY2hhbmdlIHlvdXIgYGgoLi4uLCBbIC4uLiBdKWAgY2FsbHNpdGUuXCI7XG4gICAgICAgICAgICAgICAgZXJyLmZvcmVpZ25PYmplY3QgPSBkYXRhLmZvcmVpZ25PYmplY3Q7XG4gICAgICAgICAgICAgICAgZXJyLnBhcmVudFZub2RlID0gZGF0YS5wYXJlbnRWbm9kZTtcblxuICAgICAgICAgICAgICAgIHJldHVybiBlcnI7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIGVycm9yU3RyaW5nKG9iaikge1xuICAgICAgICAgICAgICAgIHRyeSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBKU09OLnN0cmluZ2lmeShvYmosIG51bGwsIFwiICAgIFwiKTtcbiAgICAgICAgICAgICAgICB9IGNhdGNoIChlKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBTdHJpbmcob2JqKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH0sIHsgXCIuLi92bm9kZS9pcy10aHVua1wiOiAyNSwgXCIuLi92bm9kZS9pcy12aG9va1wiOiAyNiwgXCIuLi92bm9kZS9pcy12bm9kZVwiOiAyNywgXCIuLi92bm9kZS9pcy12dGV4dFwiOiAyOCwgXCIuLi92bm9kZS9pcy13aWRnZXRcIjogMjksIFwiLi4vdm5vZGUvdm5vZGUuanNcIjogMzEsIFwiLi4vdm5vZGUvdnRleHQuanNcIjogMzMsIFwiLi9ob29rcy9ldi1ob29rLmpzXCI6IDIwLCBcIi4vaG9va3Mvc29mdC1zZXQtaG9vay5qc1wiOiAyMSwgXCIuL3BhcnNlLXRhZy5qc1wiOiAyMywgXCJ4LWlzLWFycmF5XCI6IDEyIH1dLCAyMzogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHtcbiAgICAgICAgICAgIFwidXNlIHN0cmljdFwiO1xuXG4gICAgICAgICAgICB2YXIgc3BsaXQgPSByZXF1aXJlKFwiYnJvd3Nlci1zcGxpdFwiKTtcblxuICAgICAgICAgICAgdmFyIGNsYXNzSWRTcGxpdCA9IC8oW1xcLiNdP1thLXpBLVowLTlcXHUwMDdGLVxcdUZGRkZfOi1dKykvO1xuICAgICAgICAgICAgdmFyIG5vdENsYXNzSWQgPSAvXlxcLnwjLztcblxuICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBwYXJzZVRhZztcblxuICAgICAgICAgICAgZnVuY3Rpb24gcGFyc2VUYWcodGFnLCBwcm9wcykge1xuICAgICAgICAgICAgICAgIGlmICghdGFnKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBcIkRJVlwiO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHZhciBub0lkID0gIXByb3BzLmhhc093blByb3BlcnR5KFwiaWRcIik7XG5cbiAgICAgICAgICAgICAgICB2YXIgdGFnUGFydHMgPSBzcGxpdCh0YWcsIGNsYXNzSWRTcGxpdCk7XG4gICAgICAgICAgICAgICAgdmFyIHRhZ05hbWUgPSBudWxsO1xuXG4gICAgICAgICAgICAgICAgaWYgKG5vdENsYXNzSWQudGVzdCh0YWdQYXJ0c1sxXSkpIHtcbiAgICAgICAgICAgICAgICAgICAgdGFnTmFtZSA9IFwiRElWXCI7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgdmFyIGNsYXNzZXMsIHBhcnQsIHR5cGUsIGk7XG5cbiAgICAgICAgICAgICAgICBmb3IgKGkgPSAwOyBpIDwgdGFnUGFydHMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgICAgICAgICAgcGFydCA9IHRhZ1BhcnRzW2ldO1xuXG4gICAgICAgICAgICAgICAgICAgIGlmICghcGFydCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgY29udGludWU7XG4gICAgICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgICAgICB0eXBlID0gcGFydC5jaGFyQXQoMCk7XG5cbiAgICAgICAgICAgICAgICAgICAgaWYgKCF0YWdOYW1lKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICB0YWdOYW1lID0gcGFydDtcbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIGlmICh0eXBlID09PSBcIi5cIikge1xuICAgICAgICAgICAgICAgICAgICAgICAgY2xhc3NlcyA9IGNsYXNzZXMgfHwgW107XG4gICAgICAgICAgICAgICAgICAgICAgICBjbGFzc2VzLnB1c2gocGFydC5zdWJzdHJpbmcoMSwgcGFydC5sZW5ndGgpKTtcbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIGlmICh0eXBlID09PSBcIiNcIiAmJiBub0lkKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBwcm9wcy5pZCA9IHBhcnQuc3Vic3RyaW5nKDEsIHBhcnQubGVuZ3RoKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIGlmIChjbGFzc2VzKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmIChwcm9wcy5jbGFzc05hbWUpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGNsYXNzZXMucHVzaChwcm9wcy5jbGFzc05hbWUpO1xuICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgcHJvcHMuY2xhc3NOYW1lID0gY2xhc3Nlcy5qb2luKFwiIFwiKTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICByZXR1cm4gcHJvcHMubmFtZXNwYWNlID8gdGFnTmFtZSA6IHRhZ05hbWUudG9VcHBlckNhc2UoKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSwgeyBcImJyb3dzZXItc3BsaXRcIjogNSB9XSwgMjQ6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICB2YXIgaXNWTm9kZSA9IHJlcXVpcmUoXCIuL2lzLXZub2RlXCIpO1xuICAgICAgICAgICAgdmFyIGlzVlRleHQgPSByZXF1aXJlKFwiLi9pcy12dGV4dFwiKTtcbiAgICAgICAgICAgIHZhciBpc1dpZGdldCA9IHJlcXVpcmUoXCIuL2lzLXdpZGdldFwiKTtcbiAgICAgICAgICAgIHZhciBpc1RodW5rID0gcmVxdWlyZShcIi4vaXMtdGh1bmtcIik7XG5cbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gaGFuZGxlVGh1bms7XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIGhhbmRsZVRodW5rKGEsIGIpIHtcbiAgICAgICAgICAgICAgICB2YXIgcmVuZGVyZWRBID0gYTtcbiAgICAgICAgICAgICAgICB2YXIgcmVuZGVyZWRCID0gYjtcblxuICAgICAgICAgICAgICAgIGlmIChpc1RodW5rKGIpKSB7XG4gICAgICAgICAgICAgICAgICAgIHJlbmRlcmVkQiA9IHJlbmRlclRodW5rKGIsIGEpO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIGlmIChpc1RodW5rKGEpKSB7XG4gICAgICAgICAgICAgICAgICAgIHJlbmRlcmVkQSA9IHJlbmRlclRodW5rKGEsIG51bGwpO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHJldHVybiB7XG4gICAgICAgICAgICAgICAgICAgIGE6IHJlbmRlcmVkQSxcbiAgICAgICAgICAgICAgICAgICAgYjogcmVuZGVyZWRCXG4gICAgICAgICAgICAgICAgfTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZnVuY3Rpb24gcmVuZGVyVGh1bmsodGh1bmssIHByZXZpb3VzKSB7XG4gICAgICAgICAgICAgICAgdmFyIHJlbmRlcmVkVGh1bmsgPSB0aHVuay52bm9kZTtcblxuICAgICAgICAgICAgICAgIGlmICghcmVuZGVyZWRUaHVuaykge1xuICAgICAgICAgICAgICAgICAgICByZW5kZXJlZFRodW5rID0gdGh1bmsudm5vZGUgPSB0aHVuay5yZW5kZXIocHJldmlvdXMpO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIGlmICghKGlzVk5vZGUocmVuZGVyZWRUaHVuaykgfHwgaXNWVGV4dChyZW5kZXJlZFRodW5rKSB8fCBpc1dpZGdldChyZW5kZXJlZFRodW5rKSkpIHtcbiAgICAgICAgICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKFwidGh1bmsgZGlkIG5vdCByZXR1cm4gYSB2YWxpZCBub2RlXCIpO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHJldHVybiByZW5kZXJlZFRodW5rO1xuICAgICAgICAgICAgfVxuICAgICAgICB9LCB7IFwiLi9pcy10aHVua1wiOiAyNSwgXCIuL2lzLXZub2RlXCI6IDI3LCBcIi4vaXMtdnRleHRcIjogMjgsIFwiLi9pcy13aWRnZXRcIjogMjkgfV0sIDI1OiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge1xuICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBpc1RodW5rO1xuXG4gICAgICAgICAgICBmdW5jdGlvbiBpc1RodW5rKHQpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gdCAmJiB0LnR5cGUgPT09IFwiVGh1bmtcIjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSwge31dLCAyNjogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHtcbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gaXNIb29rO1xuXG4gICAgICAgICAgICBmdW5jdGlvbiBpc0hvb2soaG9vaykge1xuICAgICAgICAgICAgICAgIHJldHVybiBob29rICYmICh0eXBlb2YgaG9vay5ob29rID09PSBcImZ1bmN0aW9uXCIgJiYgIWhvb2suaGFzT3duUHJvcGVydHkoXCJob29rXCIpIHx8IHR5cGVvZiBob29rLnVuaG9vayA9PT0gXCJmdW5jdGlvblwiICYmICFob29rLmhhc093blByb3BlcnR5KFwidW5ob29rXCIpKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSwge31dLCAyNzogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHtcbiAgICAgICAgICAgIHZhciB2ZXJzaW9uID0gcmVxdWlyZShcIi4vdmVyc2lvblwiKTtcblxuICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBpc1ZpcnR1YWxOb2RlO1xuXG4gICAgICAgICAgICBmdW5jdGlvbiBpc1ZpcnR1YWxOb2RlKHgpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4geCAmJiB4LnR5cGUgPT09IFwiVmlydHVhbE5vZGVcIiAmJiB4LnZlcnNpb24gPT09IHZlcnNpb247XG4gICAgICAgICAgICB9XG4gICAgICAgIH0sIHsgXCIuL3ZlcnNpb25cIjogMzAgfV0sIDI4OiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge1xuICAgICAgICAgICAgdmFyIHZlcnNpb24gPSByZXF1aXJlKFwiLi92ZXJzaW9uXCIpO1xuXG4gICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IGlzVmlydHVhbFRleHQ7XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIGlzVmlydHVhbFRleHQoeCkge1xuICAgICAgICAgICAgICAgIHJldHVybiB4ICYmIHgudHlwZSA9PT0gXCJWaXJ0dWFsVGV4dFwiICYmIHgudmVyc2lvbiA9PT0gdmVyc2lvbjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSwgeyBcIi4vdmVyc2lvblwiOiAzMCB9XSwgMjk6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IGlzV2lkZ2V0O1xuXG4gICAgICAgICAgICBmdW5jdGlvbiBpc1dpZGdldCh3KSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHcgJiYgdy50eXBlID09PSBcIldpZGdldFwiO1xuICAgICAgICAgICAgfVxuICAgICAgICB9LCB7fV0sIDMwOiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge1xuICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBcIjJcIjtcbiAgICAgICAgfSwge31dLCAzMTogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHtcbiAgICAgICAgICAgIHZhciB2ZXJzaW9uID0gcmVxdWlyZShcIi4vdmVyc2lvblwiKTtcbiAgICAgICAgICAgIHZhciBpc1ZOb2RlID0gcmVxdWlyZShcIi4vaXMtdm5vZGVcIik7XG4gICAgICAgICAgICB2YXIgaXNXaWRnZXQgPSByZXF1aXJlKFwiLi9pcy13aWRnZXRcIik7XG4gICAgICAgICAgICB2YXIgaXNUaHVuayA9IHJlcXVpcmUoXCIuL2lzLXRodW5rXCIpO1xuICAgICAgICAgICAgdmFyIGlzVkhvb2sgPSByZXF1aXJlKFwiLi9pcy12aG9va1wiKTtcblxuICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBWaXJ0dWFsTm9kZTtcblxuICAgICAgICAgICAgdmFyIG5vUHJvcGVydGllcyA9IHt9O1xuICAgICAgICAgICAgdmFyIG5vQ2hpbGRyZW4gPSBbXTtcblxuICAgICAgICAgICAgZnVuY3Rpb24gVmlydHVhbE5vZGUodGFnTmFtZSwgcHJvcGVydGllcywgY2hpbGRyZW4sIGtleSwgbmFtZXNwYWNlKSB7XG4gICAgICAgICAgICAgICAgdGhpcy50YWdOYW1lID0gdGFnTmFtZTtcbiAgICAgICAgICAgICAgICB0aGlzLnByb3BlcnRpZXMgPSBwcm9wZXJ0aWVzIHx8IG5vUHJvcGVydGllcztcbiAgICAgICAgICAgICAgICB0aGlzLmNoaWxkcmVuID0gY2hpbGRyZW4gfHwgbm9DaGlsZHJlbjtcbiAgICAgICAgICAgICAgICB0aGlzLmtleSA9IGtleSAhPSBudWxsID8gU3RyaW5nKGtleSkgOiB1bmRlZmluZWQ7XG4gICAgICAgICAgICAgICAgdGhpcy5uYW1lc3BhY2UgPSB0eXBlb2YgbmFtZXNwYWNlID09PSBcInN0cmluZ1wiID8gbmFtZXNwYWNlIDogbnVsbDtcblxuICAgICAgICAgICAgICAgIHZhciBjb3VudCA9IGNoaWxkcmVuICYmIGNoaWxkcmVuLmxlbmd0aCB8fCAwO1xuICAgICAgICAgICAgICAgIHZhciBkZXNjZW5kYW50cyA9IDA7XG4gICAgICAgICAgICAgICAgdmFyIGhhc1dpZGdldHMgPSBmYWxzZTtcbiAgICAgICAgICAgICAgICB2YXIgaGFzVGh1bmtzID0gZmFsc2U7XG4gICAgICAgICAgICAgICAgdmFyIGRlc2NlbmRhbnRIb29rcyA9IGZhbHNlO1xuICAgICAgICAgICAgICAgIHZhciBob29rcztcblxuICAgICAgICAgICAgICAgIGZvciAodmFyIHByb3BOYW1lIGluIHByb3BlcnRpZXMpIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKHByb3BlcnRpZXMuaGFzT3duUHJvcGVydHkocHJvcE5hbWUpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICB2YXIgcHJvcGVydHkgPSBwcm9wZXJ0aWVzW3Byb3BOYW1lXTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChpc1ZIb29rKHByb3BlcnR5KSAmJiBwcm9wZXJ0eS51bmhvb2spIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoIWhvb2tzKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGhvb2tzID0ge307XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaG9va3NbcHJvcE5hbWVdID0gcHJvcGVydHk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IGNvdW50OyBpKyspIHtcbiAgICAgICAgICAgICAgICAgICAgdmFyIGNoaWxkID0gY2hpbGRyZW5baV07XG4gICAgICAgICAgICAgICAgICAgIGlmIChpc1ZOb2RlKGNoaWxkKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgZGVzY2VuZGFudHMgKz0gY2hpbGQuY291bnQgfHwgMDtcblxuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKCFoYXNXaWRnZXRzICYmIGNoaWxkLmhhc1dpZGdldHMpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBoYXNXaWRnZXRzID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKCFoYXNUaHVua3MgJiYgY2hpbGQuaGFzVGh1bmtzKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaGFzVGh1bmtzID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKCFkZXNjZW5kYW50SG9va3MgJiYgKGNoaWxkLmhvb2tzIHx8IGNoaWxkLmRlc2NlbmRhbnRIb29rcykpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBkZXNjZW5kYW50SG9va3MgPSB0cnVlO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKCFoYXNXaWRnZXRzICYmIGlzV2lkZ2V0KGNoaWxkKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHR5cGVvZiBjaGlsZC5kZXN0cm95ID09PSBcImZ1bmN0aW9uXCIpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBoYXNXaWRnZXRzID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIGlmICghaGFzVGh1bmtzICYmIGlzVGh1bmsoY2hpbGQpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBoYXNUaHVua3MgPSB0cnVlO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgdGhpcy5jb3VudCA9IGNvdW50ICsgZGVzY2VuZGFudHM7XG4gICAgICAgICAgICAgICAgdGhpcy5oYXNXaWRnZXRzID0gaGFzV2lkZ2V0cztcbiAgICAgICAgICAgICAgICB0aGlzLmhhc1RodW5rcyA9IGhhc1RodW5rcztcbiAgICAgICAgICAgICAgICB0aGlzLmhvb2tzID0gaG9va3M7XG4gICAgICAgICAgICAgICAgdGhpcy5kZXNjZW5kYW50SG9va3MgPSBkZXNjZW5kYW50SG9va3M7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIFZpcnR1YWxOb2RlLnByb3RvdHlwZS52ZXJzaW9uID0gdmVyc2lvbjtcbiAgICAgICAgICAgIFZpcnR1YWxOb2RlLnByb3RvdHlwZS50eXBlID0gXCJWaXJ0dWFsTm9kZVwiO1xuICAgICAgICB9LCB7IFwiLi9pcy10aHVua1wiOiAyNSwgXCIuL2lzLXZob29rXCI6IDI2LCBcIi4vaXMtdm5vZGVcIjogMjcsIFwiLi9pcy13aWRnZXRcIjogMjksIFwiLi92ZXJzaW9uXCI6IDMwIH1dLCAzMjogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHtcbiAgICAgICAgICAgIHZhciB2ZXJzaW9uID0gcmVxdWlyZShcIi4vdmVyc2lvblwiKTtcblxuICAgICAgICAgICAgVmlydHVhbFBhdGNoLk5PTkUgPSAwO1xuICAgICAgICAgICAgVmlydHVhbFBhdGNoLlZURVhUID0gMTtcbiAgICAgICAgICAgIFZpcnR1YWxQYXRjaC5WTk9ERSA9IDI7XG4gICAgICAgICAgICBWaXJ0dWFsUGF0Y2guV0lER0VUID0gMztcbiAgICAgICAgICAgIFZpcnR1YWxQYXRjaC5QUk9QUyA9IDQ7XG4gICAgICAgICAgICBWaXJ0dWFsUGF0Y2guT1JERVIgPSA1O1xuICAgICAgICAgICAgVmlydHVhbFBhdGNoLklOU0VSVCA9IDY7XG4gICAgICAgICAgICBWaXJ0dWFsUGF0Y2guUkVNT1ZFID0gNztcbiAgICAgICAgICAgIFZpcnR1YWxQYXRjaC5USFVOSyA9IDg7XG5cbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gVmlydHVhbFBhdGNoO1xuXG4gICAgICAgICAgICBmdW5jdGlvbiBWaXJ0dWFsUGF0Y2godHlwZSwgdk5vZGUsIHBhdGNoKSB7XG4gICAgICAgICAgICAgICAgdGhpcy50eXBlID0gTnVtYmVyKHR5cGUpO1xuICAgICAgICAgICAgICAgIHRoaXMudk5vZGUgPSB2Tm9kZTtcbiAgICAgICAgICAgICAgICB0aGlzLnBhdGNoID0gcGF0Y2g7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIFZpcnR1YWxQYXRjaC5wcm90b3R5cGUudmVyc2lvbiA9IHZlcnNpb247XG4gICAgICAgICAgICBWaXJ0dWFsUGF0Y2gucHJvdG90eXBlLnR5cGUgPSBcIlZpcnR1YWxQYXRjaFwiO1xuICAgICAgICB9LCB7IFwiLi92ZXJzaW9uXCI6IDMwIH1dLCAzMzogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHtcbiAgICAgICAgICAgIHZhciB2ZXJzaW9uID0gcmVxdWlyZShcIi4vdmVyc2lvblwiKTtcblxuICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBWaXJ0dWFsVGV4dDtcblxuICAgICAgICAgICAgZnVuY3Rpb24gVmlydHVhbFRleHQodGV4dCkge1xuICAgICAgICAgICAgICAgIHRoaXMudGV4dCA9IFN0cmluZyh0ZXh0KTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgVmlydHVhbFRleHQucHJvdG90eXBlLnZlcnNpb24gPSB2ZXJzaW9uO1xuICAgICAgICAgICAgVmlydHVhbFRleHQucHJvdG90eXBlLnR5cGUgPSBcIlZpcnR1YWxUZXh0XCI7XG4gICAgICAgIH0sIHsgXCIuL3ZlcnNpb25cIjogMzAgfV0sIDM0OiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge1xuICAgICAgICAgICAgdmFyIGlzT2JqZWN0ID0gcmVxdWlyZShcImlzLW9iamVjdFwiKTtcbiAgICAgICAgICAgIHZhciBpc0hvb2sgPSByZXF1aXJlKFwiLi4vdm5vZGUvaXMtdmhvb2tcIik7XG5cbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gZGlmZlByb3BzO1xuXG4gICAgICAgICAgICBmdW5jdGlvbiBkaWZmUHJvcHMoYSwgYikge1xuICAgICAgICAgICAgICAgIHZhciBkaWZmO1xuXG4gICAgICAgICAgICAgICAgZm9yICh2YXIgYUtleSBpbiBhKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmICghKGFLZXkgaW4gYikpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGRpZmYgPSBkaWZmIHx8IHt9O1xuICAgICAgICAgICAgICAgICAgICAgICAgZGlmZlthS2V5XSA9IHVuZGVmaW5lZDtcbiAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgIHZhciBhVmFsdWUgPSBhW2FLZXldO1xuICAgICAgICAgICAgICAgICAgICB2YXIgYlZhbHVlID0gYlthS2V5XTtcblxuICAgICAgICAgICAgICAgICAgICBpZiAoYVZhbHVlID09PSBiVmFsdWUpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnRpbnVlO1xuICAgICAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKGlzT2JqZWN0KGFWYWx1ZSkgJiYgaXNPYmplY3QoYlZhbHVlKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGdldFByb3RvdHlwZShiVmFsdWUpICE9PSBnZXRQcm90b3R5cGUoYVZhbHVlKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRpZmYgPSBkaWZmIHx8IHt9O1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRpZmZbYUtleV0gPSBiVmFsdWU7XG4gICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKGlzSG9vayhiVmFsdWUpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgZGlmZiA9IGRpZmYgfHwge307XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgZGlmZlthS2V5XSA9IGJWYWx1ZTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdmFyIG9iamVjdERpZmYgPSBkaWZmUHJvcHMoYVZhbHVlLCBiVmFsdWUpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChvYmplY3REaWZmKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRpZmYgPSBkaWZmIHx8IHt9O1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBkaWZmW2FLZXldID0gb2JqZWN0RGlmZjtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBkaWZmID0gZGlmZiB8fCB7fTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGRpZmZbYUtleV0gPSBiVmFsdWU7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICBmb3IgKHZhciBiS2V5IGluIGIpIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKCEoYktleSBpbiBhKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgZGlmZiA9IGRpZmYgfHwge307XG4gICAgICAgICAgICAgICAgICAgICAgICBkaWZmW2JLZXldID0gYltiS2V5XTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHJldHVybiBkaWZmO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBmdW5jdGlvbiBnZXRQcm90b3R5cGUodmFsdWUpIHtcbiAgICAgICAgICAgICAgICBpZiAoT2JqZWN0LmdldFByb3RvdHlwZU9mKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBPYmplY3QuZ2V0UHJvdG90eXBlT2YodmFsdWUpO1xuICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAodmFsdWUuX19wcm90b19fKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiB2YWx1ZS5fX3Byb3RvX187XG4gICAgICAgICAgICAgICAgfSBlbHNlIGlmICh2YWx1ZS5jb25zdHJ1Y3Rvcikge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gdmFsdWUuY29uc3RydWN0b3IucHJvdG90eXBlO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgfSwgeyBcIi4uL3Zub2RlL2lzLXZob29rXCI6IDI2LCBcImlzLW9iamVjdFwiOiAxMSB9XSwgMzU6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICB2YXIgaXNBcnJheSA9IHJlcXVpcmUoXCJ4LWlzLWFycmF5XCIpO1xuXG4gICAgICAgICAgICB2YXIgVlBhdGNoID0gcmVxdWlyZShcIi4uL3Zub2RlL3ZwYXRjaFwiKTtcbiAgICAgICAgICAgIHZhciBpc1ZOb2RlID0gcmVxdWlyZShcIi4uL3Zub2RlL2lzLXZub2RlXCIpO1xuICAgICAgICAgICAgdmFyIGlzVlRleHQgPSByZXF1aXJlKFwiLi4vdm5vZGUvaXMtdnRleHRcIik7XG4gICAgICAgICAgICB2YXIgaXNXaWRnZXQgPSByZXF1aXJlKFwiLi4vdm5vZGUvaXMtd2lkZ2V0XCIpO1xuICAgICAgICAgICAgdmFyIGlzVGh1bmsgPSByZXF1aXJlKFwiLi4vdm5vZGUvaXMtdGh1bmtcIik7XG4gICAgICAgICAgICB2YXIgaGFuZGxlVGh1bmsgPSByZXF1aXJlKFwiLi4vdm5vZGUvaGFuZGxlLXRodW5rXCIpO1xuXG4gICAgICAgICAgICB2YXIgZGlmZlByb3BzID0gcmVxdWlyZShcIi4vZGlmZi1wcm9wc1wiKTtcblxuICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBkaWZmO1xuXG4gICAgICAgICAgICBmdW5jdGlvbiBkaWZmKGEsIGIpIHtcbiAgICAgICAgICAgICAgICB2YXIgcGF0Y2ggPSB7IGE6IGEgfTtcbiAgICAgICAgICAgICAgICB3YWxrKGEsIGIsIHBhdGNoLCAwKTtcbiAgICAgICAgICAgICAgICByZXR1cm4gcGF0Y2g7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIHdhbGsoYSwgYiwgcGF0Y2gsIGluZGV4KSB7XG4gICAgICAgICAgICAgICAgaWYgKGEgPT09IGIpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHZhciBhcHBseSA9IHBhdGNoW2luZGV4XTtcbiAgICAgICAgICAgICAgICB2YXIgYXBwbHlDbGVhciA9IGZhbHNlO1xuXG4gICAgICAgICAgICAgICAgaWYgKGlzVGh1bmsoYSkgfHwgaXNUaHVuayhiKSkge1xuICAgICAgICAgICAgICAgICAgICB0aHVua3MoYSwgYiwgcGF0Y2gsIGluZGV4KTtcbiAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKGIgPT0gbnVsbCkge1xuXG4gICAgICAgICAgICAgICAgICAgIC8vIElmIGEgaXMgYSB3aWRnZXQgd2Ugd2lsbCBhZGQgYSByZW1vdmUgcGF0Y2ggZm9yIGl0XG4gICAgICAgICAgICAgICAgICAgIC8vIE90aGVyd2lzZSBhbnkgY2hpbGQgd2lkZ2V0cy9ob29rcyBtdXN0IGJlIGRlc3Ryb3llZC5cbiAgICAgICAgICAgICAgICAgICAgLy8gVGhpcyBwcmV2ZW50cyBhZGRpbmcgdHdvIHJlbW92ZSBwYXRjaGVzIGZvciBhIHdpZGdldC5cbiAgICAgICAgICAgICAgICAgICAgaWYgKCFpc1dpZGdldChhKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgY2xlYXJTdGF0ZShhLCBwYXRjaCwgaW5kZXgpO1xuICAgICAgICAgICAgICAgICAgICAgICAgYXBwbHkgPSBwYXRjaFtpbmRleF07XG4gICAgICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgICAgICBhcHBseSA9IGFwcGVuZFBhdGNoKGFwcGx5LCBuZXcgVlBhdGNoKFZQYXRjaC5SRU1PVkUsIGEsIGIpKTtcbiAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKGlzVk5vZGUoYikpIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKGlzVk5vZGUoYSkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChhLnRhZ05hbWUgPT09IGIudGFnTmFtZSAmJiBhLm5hbWVzcGFjZSA9PT0gYi5uYW1lc3BhY2UgJiYgYS5rZXkgPT09IGIua2V5KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdmFyIHByb3BzUGF0Y2ggPSBkaWZmUHJvcHMoYS5wcm9wZXJ0aWVzLCBiLnByb3BlcnRpZXMpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChwcm9wc1BhdGNoKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGFwcGx5ID0gYXBwZW5kUGF0Y2goYXBwbHksIG5ldyBWUGF0Y2goVlBhdGNoLlBST1BTLCBhLCBwcm9wc1BhdGNoKSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGFwcGx5ID0gZGlmZkNoaWxkcmVuKGEsIGIsIHBhdGNoLCBhcHBseSwgaW5kZXgpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBhcHBseSA9IGFwcGVuZFBhdGNoKGFwcGx5LCBuZXcgVlBhdGNoKFZQYXRjaC5WTk9ERSwgYSwgYikpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGFwcGx5Q2xlYXIgPSB0cnVlO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgYXBwbHkgPSBhcHBlbmRQYXRjaChhcHBseSwgbmV3IFZQYXRjaChWUGF0Y2guVk5PREUsIGEsIGIpKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGFwcGx5Q2xlYXIgPSB0cnVlO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfSBlbHNlIGlmIChpc1ZUZXh0KGIpKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmICghaXNWVGV4dChhKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgYXBwbHkgPSBhcHBlbmRQYXRjaChhcHBseSwgbmV3IFZQYXRjaChWUGF0Y2guVlRFWFQsIGEsIGIpKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGFwcGx5Q2xlYXIgPSB0cnVlO1xuICAgICAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKGEudGV4dCAhPT0gYi50ZXh0KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBhcHBseSA9IGFwcGVuZFBhdGNoKGFwcGx5LCBuZXcgVlBhdGNoKFZQYXRjaC5WVEVYVCwgYSwgYikpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfSBlbHNlIGlmIChpc1dpZGdldChiKSkge1xuICAgICAgICAgICAgICAgICAgICBpZiAoIWlzV2lkZ2V0KGEpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBhcHBseUNsZWFyID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgIGFwcGx5ID0gYXBwZW5kUGF0Y2goYXBwbHksIG5ldyBWUGF0Y2goVlBhdGNoLldJREdFVCwgYSwgYikpO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIGlmIChhcHBseSkge1xuICAgICAgICAgICAgICAgICAgICBwYXRjaFtpbmRleF0gPSBhcHBseTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICBpZiAoYXBwbHlDbGVhcikge1xuICAgICAgICAgICAgICAgICAgICBjbGVhclN0YXRlKGEsIHBhdGNoLCBpbmRleCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBmdW5jdGlvbiBkaWZmQ2hpbGRyZW4oYSwgYiwgcGF0Y2gsIGFwcGx5LCBpbmRleCkge1xuICAgICAgICAgICAgICAgIHZhciBhQ2hpbGRyZW4gPSBhLmNoaWxkcmVuO1xuICAgICAgICAgICAgICAgIHZhciBvcmRlcmVkU2V0ID0gcmVvcmRlcihhQ2hpbGRyZW4sIGIuY2hpbGRyZW4pO1xuICAgICAgICAgICAgICAgIHZhciBiQ2hpbGRyZW4gPSBvcmRlcmVkU2V0LmNoaWxkcmVuO1xuXG4gICAgICAgICAgICAgICAgdmFyIGFMZW4gPSBhQ2hpbGRyZW4ubGVuZ3RoO1xuICAgICAgICAgICAgICAgIHZhciBiTGVuID0gYkNoaWxkcmVuLmxlbmd0aDtcbiAgICAgICAgICAgICAgICB2YXIgbGVuID0gYUxlbiA+IGJMZW4gPyBhTGVuIDogYkxlbjtcblxuICAgICAgICAgICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgbGVuOyBpKyspIHtcbiAgICAgICAgICAgICAgICAgICAgdmFyIGxlZnROb2RlID0gYUNoaWxkcmVuW2ldO1xuICAgICAgICAgICAgICAgICAgICB2YXIgcmlnaHROb2RlID0gYkNoaWxkcmVuW2ldO1xuICAgICAgICAgICAgICAgICAgICBpbmRleCArPSAxO1xuXG4gICAgICAgICAgICAgICAgICAgIGlmICghbGVmdE5vZGUpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChyaWdodE5vZGUpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBFeGNlc3Mgbm9kZXMgaW4gYiBuZWVkIHRvIGJlIGFkZGVkXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgYXBwbHkgPSBhcHBlbmRQYXRjaChhcHBseSwgbmV3IFZQYXRjaChWUGF0Y2guSU5TRVJULCBudWxsLCByaWdodE5vZGUpKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHdhbGsobGVmdE5vZGUsIHJpZ2h0Tm9kZSwgcGF0Y2gsIGluZGV4KTtcbiAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgIGlmIChpc1ZOb2RlKGxlZnROb2RlKSAmJiBsZWZ0Tm9kZS5jb3VudCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgaW5kZXggKz0gbGVmdE5vZGUuY291bnQ7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICBpZiAob3JkZXJlZFNldC5tb3Zlcykge1xuICAgICAgICAgICAgICAgICAgICAvLyBSZW9yZGVyIG5vZGVzIGxhc3RcbiAgICAgICAgICAgICAgICAgICAgYXBwbHkgPSBhcHBlbmRQYXRjaChhcHBseSwgbmV3IFZQYXRjaChWUGF0Y2guT1JERVIsIGEsIG9yZGVyZWRTZXQubW92ZXMpKTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICByZXR1cm4gYXBwbHk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIGNsZWFyU3RhdGUodk5vZGUsIHBhdGNoLCBpbmRleCkge1xuICAgICAgICAgICAgICAgIC8vIFRPRE86IE1ha2UgdGhpcyBhIHNpbmdsZSB3YWxrLCBub3QgdHdvXG4gICAgICAgICAgICAgICAgdW5ob29rKHZOb2RlLCBwYXRjaCwgaW5kZXgpO1xuICAgICAgICAgICAgICAgIGRlc3Ryb3lXaWRnZXRzKHZOb2RlLCBwYXRjaCwgaW5kZXgpO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAvLyBQYXRjaCByZWNvcmRzIGZvciBhbGwgZGVzdHJveWVkIHdpZGdldHMgbXVzdCBiZSBhZGRlZCBiZWNhdXNlIHdlIG5lZWRcbiAgICAgICAgICAgIC8vIGEgRE9NIG5vZGUgcmVmZXJlbmNlIGZvciB0aGUgZGVzdHJveSBmdW5jdGlvblxuICAgICAgICAgICAgZnVuY3Rpb24gZGVzdHJveVdpZGdldHModk5vZGUsIHBhdGNoLCBpbmRleCkge1xuICAgICAgICAgICAgICAgIGlmIChpc1dpZGdldCh2Tm9kZSkpIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKHR5cGVvZiB2Tm9kZS5kZXN0cm95ID09PSBcImZ1bmN0aW9uXCIpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHBhdGNoW2luZGV4XSA9IGFwcGVuZFBhdGNoKHBhdGNoW2luZGV4XSwgbmV3IFZQYXRjaChWUGF0Y2guUkVNT1ZFLCB2Tm9kZSwgbnVsbCkpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfSBlbHNlIGlmIChpc1ZOb2RlKHZOb2RlKSAmJiAodk5vZGUuaGFzV2lkZ2V0cyB8fCB2Tm9kZS5oYXNUaHVua3MpKSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciBjaGlsZHJlbiA9IHZOb2RlLmNoaWxkcmVuO1xuICAgICAgICAgICAgICAgICAgICB2YXIgbGVuID0gY2hpbGRyZW4ubGVuZ3RoO1xuICAgICAgICAgICAgICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IGxlbjsgaSsrKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICB2YXIgY2hpbGQgPSBjaGlsZHJlbltpXTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGluZGV4ICs9IDE7XG5cbiAgICAgICAgICAgICAgICAgICAgICAgIGRlc3Ryb3lXaWRnZXRzKGNoaWxkLCBwYXRjaCwgaW5kZXgpO1xuXG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoaXNWTm9kZShjaGlsZCkgJiYgY2hpbGQuY291bnQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpbmRleCArPSBjaGlsZC5jb3VudDtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoaXNUaHVuayh2Tm9kZSkpIHtcbiAgICAgICAgICAgICAgICAgICAgdGh1bmtzKHZOb2RlLCBudWxsLCBwYXRjaCwgaW5kZXgpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgLy8gQ3JlYXRlIGEgc3ViLXBhdGNoIGZvciB0aHVua3NcbiAgICAgICAgICAgIGZ1bmN0aW9uIHRodW5rcyhhLCBiLCBwYXRjaCwgaW5kZXgpIHtcbiAgICAgICAgICAgICAgICB2YXIgbm9kZXMgPSBoYW5kbGVUaHVuayhhLCBiKTtcbiAgICAgICAgICAgICAgICB2YXIgdGh1bmtQYXRjaCA9IGRpZmYobm9kZXMuYSwgbm9kZXMuYik7XG4gICAgICAgICAgICAgICAgaWYgKGhhc1BhdGNoZXModGh1bmtQYXRjaCkpIHtcbiAgICAgICAgICAgICAgICAgICAgcGF0Y2hbaW5kZXhdID0gbmV3IFZQYXRjaChWUGF0Y2guVEhVTkssIG51bGwsIHRodW5rUGF0Y2gpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZnVuY3Rpb24gaGFzUGF0Y2hlcyhwYXRjaCkge1xuICAgICAgICAgICAgICAgIGZvciAodmFyIGluZGV4IGluIHBhdGNoKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmIChpbmRleCAhPT0gXCJhXCIpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAvLyBFeGVjdXRlIGhvb2tzIHdoZW4gdHdvIG5vZGVzIGFyZSBpZGVudGljYWxcbiAgICAgICAgICAgIGZ1bmN0aW9uIHVuaG9vayh2Tm9kZSwgcGF0Y2gsIGluZGV4KSB7XG4gICAgICAgICAgICAgICAgaWYgKGlzVk5vZGUodk5vZGUpKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmICh2Tm9kZS5ob29rcykge1xuICAgICAgICAgICAgICAgICAgICAgICAgcGF0Y2hbaW5kZXhdID0gYXBwZW5kUGF0Y2gocGF0Y2hbaW5kZXhdLCBuZXcgVlBhdGNoKFZQYXRjaC5QUk9QUywgdk5vZGUsIHVuZGVmaW5lZEtleXModk5vZGUuaG9va3MpKSk7XG4gICAgICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgICAgICBpZiAodk5vZGUuZGVzY2VuZGFudEhvb2tzIHx8IHZOb2RlLmhhc1RodW5rcykge1xuICAgICAgICAgICAgICAgICAgICAgICAgdmFyIGNoaWxkcmVuID0gdk5vZGUuY2hpbGRyZW47XG4gICAgICAgICAgICAgICAgICAgICAgICB2YXIgbGVuID0gY2hpbGRyZW4ubGVuZ3RoO1xuICAgICAgICAgICAgICAgICAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCBsZW47IGkrKykge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZhciBjaGlsZCA9IGNoaWxkcmVuW2ldO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGluZGV4ICs9IDE7XG5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB1bmhvb2soY2hpbGQsIHBhdGNoLCBpbmRleCk7XG5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoaXNWTm9kZShjaGlsZCkgJiYgY2hpbGQuY291bnQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaW5kZXggKz0gY2hpbGQuY291bnQ7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfSBlbHNlIGlmIChpc1RodW5rKHZOb2RlKSkge1xuICAgICAgICAgICAgICAgICAgICB0aHVua3Modk5vZGUsIG51bGwsIHBhdGNoLCBpbmRleCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBmdW5jdGlvbiB1bmRlZmluZWRLZXlzKG9iaikge1xuICAgICAgICAgICAgICAgIHZhciByZXN1bHQgPSB7fTtcblxuICAgICAgICAgICAgICAgIGZvciAodmFyIGtleSBpbiBvYmopIHtcbiAgICAgICAgICAgICAgICAgICAgcmVzdWx0W2tleV0gPSB1bmRlZmluZWQ7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgcmV0dXJuIHJlc3VsdDtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgLy8gTGlzdCBkaWZmLCBuYWl2ZSBsZWZ0IHRvIHJpZ2h0IHJlb3JkZXJpbmdcbiAgICAgICAgICAgIGZ1bmN0aW9uIHJlb3JkZXIoYUNoaWxkcmVuLCBiQ2hpbGRyZW4pIHtcbiAgICAgICAgICAgICAgICAvLyBPKE0pIHRpbWUsIE8oTSkgbWVtb3J5XG4gICAgICAgICAgICAgICAgdmFyIGJDaGlsZEluZGV4ID0ga2V5SW5kZXgoYkNoaWxkcmVuKTtcbiAgICAgICAgICAgICAgICB2YXIgYktleXMgPSBiQ2hpbGRJbmRleC5rZXlzO1xuICAgICAgICAgICAgICAgIHZhciBiRnJlZSA9IGJDaGlsZEluZGV4LmZyZWU7XG5cbiAgICAgICAgICAgICAgICBpZiAoYkZyZWUubGVuZ3RoID09PSBiQ2hpbGRyZW4ubGVuZ3RoKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiB7XG4gICAgICAgICAgICAgICAgICAgICAgICBjaGlsZHJlbjogYkNoaWxkcmVuLFxuICAgICAgICAgICAgICAgICAgICAgICAgbW92ZXM6IG51bGxcbiAgICAgICAgICAgICAgICAgICAgfTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAvLyBPKE4pIHRpbWUsIE8oTikgbWVtb3J5XG4gICAgICAgICAgICAgICAgdmFyIGFDaGlsZEluZGV4ID0ga2V5SW5kZXgoYUNoaWxkcmVuKTtcbiAgICAgICAgICAgICAgICB2YXIgYUtleXMgPSBhQ2hpbGRJbmRleC5rZXlzO1xuICAgICAgICAgICAgICAgIHZhciBhRnJlZSA9IGFDaGlsZEluZGV4LmZyZWU7XG5cbiAgICAgICAgICAgICAgICBpZiAoYUZyZWUubGVuZ3RoID09PSBhQ2hpbGRyZW4ubGVuZ3RoKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiB7XG4gICAgICAgICAgICAgICAgICAgICAgICBjaGlsZHJlbjogYkNoaWxkcmVuLFxuICAgICAgICAgICAgICAgICAgICAgICAgbW92ZXM6IG51bGxcbiAgICAgICAgICAgICAgICAgICAgfTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAvLyBPKE1BWChOLCBNKSkgbWVtb3J5XG4gICAgICAgICAgICAgICAgdmFyIG5ld0NoaWxkcmVuID0gW107XG5cbiAgICAgICAgICAgICAgICB2YXIgZnJlZUluZGV4ID0gMDtcbiAgICAgICAgICAgICAgICB2YXIgZnJlZUNvdW50ID0gYkZyZWUubGVuZ3RoO1xuICAgICAgICAgICAgICAgIHZhciBkZWxldGVkSXRlbXMgPSAwO1xuXG4gICAgICAgICAgICAgICAgLy8gSXRlcmF0ZSB0aHJvdWdoIGEgYW5kIG1hdGNoIGEgbm9kZSBpbiBiXG4gICAgICAgICAgICAgICAgLy8gTyhOKSB0aW1lLFxuICAgICAgICAgICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgYUNoaWxkcmVuLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciBhSXRlbSA9IGFDaGlsZHJlbltpXTtcbiAgICAgICAgICAgICAgICAgICAgdmFyIGl0ZW1JbmRleDtcblxuICAgICAgICAgICAgICAgICAgICBpZiAoYUl0ZW0ua2V5KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoYktleXMuaGFzT3duUHJvcGVydHkoYUl0ZW0ua2V5KSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIE1hdGNoIHVwIHRoZSBvbGQga2V5c1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGl0ZW1JbmRleCA9IGJLZXlzW2FJdGVtLmtleV07XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgbmV3Q2hpbGRyZW4ucHVzaChiQ2hpbGRyZW5baXRlbUluZGV4XSk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIFJlbW92ZSBvbGQga2V5ZWQgaXRlbXNcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpdGVtSW5kZXggPSBpIC0gZGVsZXRlZEl0ZW1zKys7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgbmV3Q2hpbGRyZW4ucHVzaChudWxsKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIE1hdGNoIHRoZSBpdGVtIGluIGEgd2l0aCB0aGUgbmV4dCBmcmVlIGl0ZW0gaW4gYlxuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGZyZWVJbmRleCA8IGZyZWVDb3VudCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGl0ZW1JbmRleCA9IGJGcmVlW2ZyZWVJbmRleCsrXTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBuZXdDaGlsZHJlbi5wdXNoKGJDaGlsZHJlbltpdGVtSW5kZXhdKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gVGhlcmUgYXJlIG5vIGZyZWUgaXRlbXMgaW4gYiB0byBtYXRjaCB3aXRoXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gdGhlIGZyZWUgaXRlbXMgaW4gYSwgc28gdGhlIGV4dHJhIGZyZWUgbm9kZXNcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBhcmUgZGVsZXRlZC5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpdGVtSW5kZXggPSBpIC0gZGVsZXRlZEl0ZW1zKys7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgbmV3Q2hpbGRyZW4ucHVzaChudWxsKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHZhciBsYXN0RnJlZUluZGV4ID0gZnJlZUluZGV4ID49IGJGcmVlLmxlbmd0aCA/IGJDaGlsZHJlbi5sZW5ndGggOiBiRnJlZVtmcmVlSW5kZXhdO1xuXG4gICAgICAgICAgICAgICAgLy8gSXRlcmF0ZSB0aHJvdWdoIGIgYW5kIGFwcGVuZCBhbnkgbmV3IGtleXNcbiAgICAgICAgICAgICAgICAvLyBPKE0pIHRpbWVcbiAgICAgICAgICAgICAgICBmb3IgKHZhciBqID0gMDsgaiA8IGJDaGlsZHJlbi5sZW5ndGg7IGorKykge1xuICAgICAgICAgICAgICAgICAgICB2YXIgbmV3SXRlbSA9IGJDaGlsZHJlbltqXTtcblxuICAgICAgICAgICAgICAgICAgICBpZiAobmV3SXRlbS5rZXkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmICghYUtleXMuaGFzT3duUHJvcGVydHkobmV3SXRlbS5rZXkpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gQWRkIGFueSBuZXcga2V5ZWQgaXRlbXNcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBXZSBhcmUgYWRkaW5nIG5ldyBpdGVtcyB0byB0aGUgZW5kIGFuZCB0aGVuIHNvcnRpbmcgdGhlbVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIGluIHBsYWNlLiBJbiBmdXR1cmUgd2Ugc2hvdWxkIGluc2VydCBuZXcgaXRlbXMgaW4gcGxhY2UuXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgbmV3Q2hpbGRyZW4ucHVzaChuZXdJdGVtKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIGlmIChqID49IGxhc3RGcmVlSW5kZXgpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIEFkZCBhbnkgbGVmdG92ZXIgbm9uLWtleWVkIGl0ZW1zXG4gICAgICAgICAgICAgICAgICAgICAgICBuZXdDaGlsZHJlbi5wdXNoKG5ld0l0ZW0pO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgdmFyIHNpbXVsYXRlID0gbmV3Q2hpbGRyZW4uc2xpY2UoKTtcbiAgICAgICAgICAgICAgICB2YXIgc2ltdWxhdGVJbmRleCA9IDA7XG4gICAgICAgICAgICAgICAgdmFyIHJlbW92ZXMgPSBbXTtcbiAgICAgICAgICAgICAgICB2YXIgaW5zZXJ0cyA9IFtdO1xuICAgICAgICAgICAgICAgIHZhciBzaW11bGF0ZUl0ZW07XG5cbiAgICAgICAgICAgICAgICBmb3IgKHZhciBrID0gMDsgayA8IGJDaGlsZHJlbi5sZW5ndGg7KSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciB3YW50ZWRJdGVtID0gYkNoaWxkcmVuW2tdO1xuICAgICAgICAgICAgICAgICAgICBzaW11bGF0ZUl0ZW0gPSBzaW11bGF0ZVtzaW11bGF0ZUluZGV4XTtcblxuICAgICAgICAgICAgICAgICAgICAvLyByZW1vdmUgaXRlbXNcbiAgICAgICAgICAgICAgICAgICAgd2hpbGUgKHNpbXVsYXRlSXRlbSA9PT0gbnVsbCAmJiBzaW11bGF0ZS5sZW5ndGgpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJlbW92ZXMucHVzaChyZW1vdmUoc2ltdWxhdGUsIHNpbXVsYXRlSW5kZXgsIG51bGwpKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIHNpbXVsYXRlSXRlbSA9IHNpbXVsYXRlW3NpbXVsYXRlSW5kZXhdO1xuICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgaWYgKCFzaW11bGF0ZUl0ZW0gfHwgc2ltdWxhdGVJdGVtLmtleSAhPT0gd2FudGVkSXRlbS5rZXkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIGlmIHdlIG5lZWQgYSBrZXkgaW4gdGhpcyBwb3NpdGlvbi4uLlxuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHdhbnRlZEl0ZW0ua2V5KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHNpbXVsYXRlSXRlbSAmJiBzaW11bGF0ZUl0ZW0ua2V5KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIGlmIGFuIGluc2VydCBkb2Vzbid0IHB1dCB0aGlzIGtleSBpbiBwbGFjZSwgaXQgbmVlZHMgdG8gbW92ZVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoYktleXNbc2ltdWxhdGVJdGVtLmtleV0gIT09IGsgKyAxKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICByZW1vdmVzLnB1c2gocmVtb3ZlKHNpbXVsYXRlLCBzaW11bGF0ZUluZGV4LCBzaW11bGF0ZUl0ZW0ua2V5KSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzaW11bGF0ZUl0ZW0gPSBzaW11bGF0ZVtzaW11bGF0ZUluZGV4XTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIGlmIHRoZSByZW1vdmUgZGlkbid0IHB1dCB0aGUgd2FudGVkIGl0ZW0gaW4gcGxhY2UsIHdlIG5lZWQgdG8gaW5zZXJ0IGl0XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoIXNpbXVsYXRlSXRlbSB8fCBzaW11bGF0ZUl0ZW0ua2V5ICE9PSB3YW50ZWRJdGVtLmtleSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGluc2VydHMucHVzaCh7IGtleTogd2FudGVkSXRlbS5rZXksIHRvOiBrIH0pO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gaXRlbXMgYXJlIG1hdGNoaW5nLCBzbyBza2lwIGFoZWFkXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzaW11bGF0ZUluZGV4Kys7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpbnNlcnRzLnB1c2goeyBrZXk6IHdhbnRlZEl0ZW0ua2V5LCB0bzogayB9KTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGluc2VydHMucHVzaCh7IGtleTogd2FudGVkSXRlbS5rZXksIHRvOiBrIH0pO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBrKys7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAvLyBhIGtleSBpbiBzaW11bGF0ZSBoYXMgbm8gbWF0Y2hpbmcgd2FudGVkIGtleSwgcmVtb3ZlIGl0XG4gICAgICAgICAgICAgICAgICAgICAgICBlbHNlIGlmIChzaW11bGF0ZUl0ZW0gJiYgc2ltdWxhdGVJdGVtLmtleSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlbW92ZXMucHVzaChyZW1vdmUoc2ltdWxhdGUsIHNpbXVsYXRlSW5kZXgsIHNpbXVsYXRlSXRlbS5rZXkpKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHNpbXVsYXRlSW5kZXgrKztcbiAgICAgICAgICAgICAgICAgICAgICAgIGsrKztcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIC8vIHJlbW92ZSBhbGwgdGhlIHJlbWFpbmluZyBub2RlcyBmcm9tIHNpbXVsYXRlXG4gICAgICAgICAgICAgICAgd2hpbGUgKHNpbXVsYXRlSW5kZXggPCBzaW11bGF0ZS5sZW5ndGgpIHtcbiAgICAgICAgICAgICAgICAgICAgc2ltdWxhdGVJdGVtID0gc2ltdWxhdGVbc2ltdWxhdGVJbmRleF07XG4gICAgICAgICAgICAgICAgICAgIHJlbW92ZXMucHVzaChyZW1vdmUoc2ltdWxhdGUsIHNpbXVsYXRlSW5kZXgsIHNpbXVsYXRlSXRlbSAmJiBzaW11bGF0ZUl0ZW0ua2V5KSk7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgLy8gSWYgdGhlIG9ubHkgbW92ZXMgd2UgaGF2ZSBhcmUgZGVsZXRlcyB0aGVuIHdlIGNhbiBqdXN0XG4gICAgICAgICAgICAgICAgLy8gbGV0IHRoZSBkZWxldGUgcGF0Y2ggcmVtb3ZlIHRoZXNlIGl0ZW1zLlxuICAgICAgICAgICAgICAgIGlmIChyZW1vdmVzLmxlbmd0aCA9PT0gZGVsZXRlZEl0ZW1zICYmICFpbnNlcnRzLmxlbmd0aCkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgICAgICAgICAgICAgY2hpbGRyZW46IG5ld0NoaWxkcmVuLFxuICAgICAgICAgICAgICAgICAgICAgICAgbW92ZXM6IG51bGxcbiAgICAgICAgICAgICAgICAgICAgfTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgICAgICAgICBjaGlsZHJlbjogbmV3Q2hpbGRyZW4sXG4gICAgICAgICAgICAgICAgICAgIG1vdmVzOiB7XG4gICAgICAgICAgICAgICAgICAgICAgICByZW1vdmVzOiByZW1vdmVzLFxuICAgICAgICAgICAgICAgICAgICAgICAgaW5zZXJ0czogaW5zZXJ0c1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZnVuY3Rpb24gcmVtb3ZlKGFyciwgaW5kZXgsIGtleSkge1xuICAgICAgICAgICAgICAgIGFyci5zcGxpY2UoaW5kZXgsIDEpO1xuXG4gICAgICAgICAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgICAgICAgICAgZnJvbTogaW5kZXgsXG4gICAgICAgICAgICAgICAgICAgIGtleToga2V5XG4gICAgICAgICAgICAgICAgfTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZnVuY3Rpb24ga2V5SW5kZXgoY2hpbGRyZW4pIHtcbiAgICAgICAgICAgICAgICB2YXIga2V5cyA9IHt9O1xuICAgICAgICAgICAgICAgIHZhciBmcmVlID0gW107XG4gICAgICAgICAgICAgICAgdmFyIGxlbmd0aCA9IGNoaWxkcmVuLmxlbmd0aDtcblxuICAgICAgICAgICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgbGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgICAgICAgICAgdmFyIGNoaWxkID0gY2hpbGRyZW5baV07XG5cbiAgICAgICAgICAgICAgICAgICAgaWYgKGNoaWxkLmtleSkge1xuICAgICAgICAgICAgICAgICAgICAgICAga2V5c1tjaGlsZC5rZXldID0gaTtcbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGZyZWUucHVzaChpKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHJldHVybiB7XG4gICAgICAgICAgICAgICAgICAgIGtleXM6IGtleXMsIC8vIEEgaGFzaCBvZiBrZXkgbmFtZSB0byBpbmRleFxuICAgICAgICAgICAgICAgICAgICBmcmVlOiBmcmVlIC8vIEFuIGFycmF5IG9mIHVua2V5ZWQgaXRlbSBpbmRpY2VzXG4gICAgICAgICAgICAgICAgfTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZnVuY3Rpb24gYXBwZW5kUGF0Y2goYXBwbHksIHBhdGNoKSB7XG4gICAgICAgICAgICAgICAgaWYgKGFwcGx5KSB7XG4gICAgICAgICAgICAgICAgICAgIGlmIChpc0FycmF5KGFwcGx5KSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgYXBwbHkucHVzaChwYXRjaCk7XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBhcHBseSA9IFthcHBseSwgcGF0Y2hdO1xuICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGFwcGx5O1xuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBwYXRjaDtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH0sIHsgXCIuLi92bm9kZS9oYW5kbGUtdGh1bmtcIjogMjQsIFwiLi4vdm5vZGUvaXMtdGh1bmtcIjogMjUsIFwiLi4vdm5vZGUvaXMtdm5vZGVcIjogMjcsIFwiLi4vdm5vZGUvaXMtdnRleHRcIjogMjgsIFwiLi4vdm5vZGUvaXMtd2lkZ2V0XCI6IDI5LCBcIi4uL3Zub2RlL3ZwYXRjaFwiOiAzMiwgXCIuL2RpZmYtcHJvcHNcIjogMzQsIFwieC1pcy1hcnJheVwiOiAxMiB9XSB9LCB7fSwgWzRdKSg0KTtcbn0pO1xuXG5jb25zdCBzdGFydCA9IGZ1bmN0aW9uIChkb21Sb290LCByZW5kZXJGbiwgaW5pdGlhbFN0YXRlLCBvcHRpb25zID0gW10pIHtcbiAgbGV0IHBpZCA9IHNlbGYucHJvY2Vzc2VzLnNwYXduKCk7XG5cbiAgaWYgKEtleXdvcmQuaGFzX2tleV9fcW1fXyhvcHRpb25zLCBLZXJuZWwuU3BlY2lhbEZvcm1zLmF0b20oJ25hbWUnKSkpIHtcbiAgICBwaWQgPSBzZWxmLnByb2Nlc3Nlcy5yZWdpc3RlcihLZXl3b3JkLmdldChvcHRpb25zLCBLZXJuZWwuU3BlY2lhbEZvcm1zLmF0b20oJ25hbWUnKSksIHBpZCk7XG4gIH1cblxuICBjb25zdCB0cmVlID0gcmVuZGVyRm4uYXBwbHkodGhpcywgaW5pdGlhbFN0YXRlKTtcbiAgY29uc3Qgcm9vdE5vZGUgPSBWaXJ0dWFsRE9NLmNyZWF0ZSh0cmVlKTtcblxuICBkb21Sb290LmFwcGVuZENoaWxkKHJvb3ROb2RlKTtcblxuICBzZWxmLnByb2Nlc3Nlcy5wdXQocGlkLCAnc3RhdGUnLCBLZXJuZWwuU3BlY2lhbEZvcm1zLnR1cGxlKHJvb3ROb2RlLCB0cmVlLCByZW5kZXJGbikpO1xuICByZXR1cm4gS2VybmVsLlNwZWNpYWxGb3Jtcy50dXBsZShLZXJuZWwuU3BlY2lhbEZvcm1zLmF0b20oJ29rJyksIHBpZCk7XG59O1xuXG5jb25zdCBzdG9wID0gZnVuY3Rpb24gKGFnZW50LCB0aW1lb3V0ID0gNTAwMCkge1xuICBzZWxmLnByb2Nlc3Nlcy5leGl0KGFnZW50KTtcbiAgcmV0dXJuIEtlcm5lbC5TcGVjaWFsRm9ybXMuYXRvbSgnb2snKTtcbn07XG5cbmNvbnN0IHJlbmRlciA9IGZ1bmN0aW9uIChhZ2VudCwgc3RhdGUpIHtcblxuICBjb25zdCBjdXJyZW50X3N0YXRlID0gc2VsZi5wcm9jZXNzZXMuZ2V0KGFnZW50LCAnc3RhdGUnKTtcblxuICBsZXQgcm9vdE5vZGUgPSBLZXJuZWwuZWxlbShjdXJyZW50X3N0YXRlLCAwKTtcbiAgbGV0IHRyZWUgPSBLZXJuZWwuZWxlbShjdXJyZW50X3N0YXRlLCAxKTtcbiAgbGV0IHJlbmRlckZuID0gS2VybmVsLmVsZW0oY3VycmVudF9zdGF0ZSwgMik7XG5cbiAgbGV0IG5ld1RyZWUgPSByZW5kZXJGbi5hcHBseSh0aGlzLCBzdGF0ZSk7XG5cbiAgbGV0IHBhdGNoZXMgPSBWaXJ0dWFsRE9NLmRpZmYodHJlZSwgbmV3VHJlZSk7XG4gIHJvb3ROb2RlID0gVmlydHVhbERPTS5wYXRjaChyb290Tm9kZSwgcGF0Y2hlcyk7XG5cbiAgc2VsZi5wcm9jZXNzZXMucHV0KGFnZW50LCAnc3RhdGUnLCBLZXJuZWwuU3BlY2lhbEZvcm1zLnR1cGxlKHJvb3ROb2RlLCBuZXdUcmVlLCByZW5kZXJGbikpO1xuXG4gIHJldHVybiBLZXJuZWwuU3BlY2lhbEZvcm1zLmF0b20oJ29rJyk7XG59O1xuXG52YXIgdmlldyA9IHtcbiAgc3RhcnQsXG4gIHN0b3AsXG4gIHJlbmRlclxufTtcblxuY29uc3QgQ29yZSA9IEM7XG5cbmV4cG9ydCB7IENvcmUsIEtlcm5lbCwgQXRvbSwgRW51bSwgSW50ZWdlciwgTGlzdCwgUmFuZ2UsIFR1cGxlLCBBZ2VudCwgS2V5d29yZCwgYmFzZSBhcyBCYXNlLCBTdHJpbmckMSBhcyBTdHJpbmcsIGJpdHdpc2UgYXMgQml0d2lzZSwgRW51bWVyYWJsZSwgQ29sbGVjdGFibGUsIEluc3BlY3QsIG1hcCBhcyBNYXAsIHNldCBhcyBTZXQsIE1hcFNldCwgVmlydHVhbERPTSwgdmlldyBhcyBWaWV3IH07Il0sImZpbGUiOiJFbGl4aXIuanMiLCJzb3VyY2VSb290IjoiL3NvdXJjZS8ifQ== \ No newline at end of file diff --git a/src/javascript/elixir.js b/src/javascript/elixir.js index 7c06cdff..a36ea382 100644 --- a/src/javascript/elixir.js +++ b/src/javascript/elixir.js @@ -1,9 +1,5 @@ import * as C from './lib/core'; -self.processes = self.processes || new C.ProcessSystem(); - - - export const Core = C; export { default as Kernel } from './lib/kernel'; export { default as Atom } from './lib/atom'; diff --git a/src/javascript/lib/base.js b/src/javascript/lib/base.js index efd92d88..e625b78b 100644 --- a/src/javascript/lib/base.js +++ b/src/javascript/lib/base.js @@ -17,6 +17,7 @@ function decode64(data){ }catch(e){ return Kernel.SpecialForms.atom("error"); } + return btoa(data); } @@ -29,4 +30,4 @@ export default { encode64, decode64, decode64__em__ -} \ No newline at end of file +} diff --git a/src/javascript/lib/core.js b/src/javascript/lib/core.js index 1f0edbe2..b56184b1 100644 --- a/src/javascript/lib/core.js +++ b/src/javascript/lib/core.js @@ -2,7 +2,36 @@ import ProcessSystem from './core/process_system'; import { Tuple, PID, Integer, Float } from './core/primitives'; import BitString from './core/bit_string'; import Patterns from './core/patterns'; -import { call_property } from './core/functions'; +import { call_property, is_instance_of, size, is_nil, + is_atom, + is_binary, + is_boolean, + is_function, + is_float, + is_integer, + is_list, + is_map, + is_number, + is_tuple, + is_pid, + is_port, + is_reference, + is_bitstring, + add, + subtract, + multiply, + divide, + remainder, + apply, + new_tuple, + duplicate, + contains, + reverse, + get_global, + concat_lists, + prepend_to_list } from './core/functions'; + +get_global().processes = get_global().processes || new ProcessSystem(); export { ProcessSystem, @@ -12,5 +41,35 @@ export { Patterns, Integer, Float, - call_property + call_property, + is_instance_of, + size, + is_nil, + is_atom, + is_binary, + is_boolean, + is_function, + is_float, + is_integer, + is_list, + is_map, + is_number, + is_tuple, + is_pid, + is_port, + is_reference, + is_bitstring, + add, + subtract, + multiply, + divide, + remainder, + apply, + new_tuple, + duplicate, + contains, + reverse, + get_global, + concat_lists, + prepend_to_list } diff --git a/src/javascript/lib/core/functions.js b/src/javascript/lib/core/functions.js index ca31c75b..78ac4b89 100644 --- a/src/javascript/lib/core/functions.js +++ b/src/javascript/lib/core/functions.js @@ -1,3 +1,7 @@ +import { PID, Tuple, Integer, Float } from './primitives'; +import BitString from './bit_string'; +import Patterns from './patterns'; + function call_property(item, property){ if(property in item){ item[property]; @@ -19,6 +23,216 @@ function call_property(item, property){ throw new Error(`Property ${property} not found in ${item}`); } +function is_instance_of(value, type){ + return value instanceof type; +} + +function size(term){ + return term.length; +} + +function is_nil(x){ + return x === null; +} + +function is_atom(x){ + return typeof x === 'symbol'; +} + +function is_binary(x){ + return typeof x === 'string' || x instanceof String; +} + +function is_boolean(x){ + return typeof x === 'boolean' || x instanceof Boolean; +} + +function is_function(x, arity = -1){ + return typeof x === 'function' || x instanceof Function; +} + +function is_float(x){ + return is_number(x) && !Number.isInteger(x); +} + +function is_integer(x){ + return Number.isInteger(x); +} + +function is_list(x){ + return x instanceof Array; +} + +function is_map(x){ + return typeof x === 'object' || x instanceof Object; +} + +function is_number(x){ + return typeof x === "number"; +} + +function is_tuple(x){ + return x instanceof Tuple; +} + +function is_pid(x){ + return x instanceof PID; +} + +function is_port(x){ + return false; +} + +function is_reference(x){ + return false; +} + +function is_bitstring(x){ + return is_binary(x) || x instanceof BitString; +} + +function add(one, two){ + return one + two; +} + +function subtract(one, two){ + return one + two; +} + +function multiply(one, two){ + return one + two; +} + +function divide(one, two){ + return one + two; +} + +function remainder(one, two){ + return one + two; +} + +function apply(...args){ + if(args.length === 2){ + args[0].apply(null, args.slice(1)); + }else{ + args[0][args[1]].apply(null, args.slice(2)); + } +} + +function new_tuple(args){ + return new Tuple(...args); +} + +function make_tuple(data, size){ + let array = []; + + for (var i = size - 1; i >= 0; i--) { + array.push(data); + } + + return new Tuple(...array); +} + +function insert_at(tuple, index, term){ + let new_tuple = []; + + for (var i = 0; i <= tuple.count(); i++) { + if(i === index){ + new_tuple.push(term); + i++; + new_tuple.push(tuple.get(i)); + }else{ + new_tuple.push(tuple.get(i)); + } + } + + return new Tuple(...new_tuple); +} + +function duplicate(data, size){ + let array = []; + + for (var i = size - 1; i >= 0; i--) { + array.push(data); + } + + return array; +} + +function delete_at(tuple, index){ + let new_list = []; + + for (var i = 0; i < tuple.count(); i++) { + if(i !== index){ + new_list.push(tuple.get(i)); + } + } + + return new Tuple(...new_list); +}; + +function contains(left, right){ + for(let x of right){ + if(Patterns.match_no_throw(left, x) != null){ + return true; + } + } + + return false; +} + +function reverse(list){ + return list.concat([]).reverse(); +} + +function get_global(){ + if(typeof(self) !== "undefined"){ + return self; + }else if(typeof(global) !== "undefined"){ + return global; + } + + throw "No global state found"; +} + +function concat_lists(left, right){ + return left.concat(right); +} + +function prepend_to_list(list, item){ + return [item].concat(list); +} + export { - call_property + call_property, + is_instance_of, + size, + is_nil, + is_atom, + is_binary, + is_boolean, + is_function, + is_float, + is_integer, + is_list, + is_map, + is_number, + is_tuple, + is_pid, + is_port, + is_reference, + is_bitstring, + add, + subtract, + multiply, + divide, + remainder, + apply, + new_tuple, + duplicate, + contains, + reverse, + get_global, + concat_lists, + prepend_to_list }; diff --git a/src/javascript/lib/core/primitives.js b/src/javascript/lib/core/primitives.js index d222905d..2521eb63 100644 --- a/src/javascript/lib/core/primitives.js +++ b/src/javascript/lib/core/primitives.js @@ -2,6 +2,7 @@ class Tuple { constructor(...args){ this.values = Object.freeze(args); + this.length = this.values.length; } get(index) { diff --git a/src/javascript/lib/enum.js b/src/javascript/lib/enum.js index c176025a..2c6781d4 100644 --- a/src/javascript/lib/enum.js +++ b/src/javascript/lib/enum.js @@ -148,7 +148,7 @@ let Enum = { return Kernel.SpecialForms.tuple(mapped, the_acc); }, - member: function(collection, value){ + member__qmark__: function(collection, value){ return collection.includes(value); }, diff --git a/test/elixir_script_test.exs b/test/elixir_script_test.exs index 41d28aac..c9aa57b5 100644 --- a/test/elixir_script_test.exs +++ b/test/elixir_script_test.exs @@ -7,12 +7,12 @@ defmodule ElixirScript.Test do JQuery.("
").text(html) """) - assert hd(js_code) =~ "JQuery('
').text(html)" + assert Enum.join(js_code, "\n") =~ "JQuery('
').text(html)" end should "turn javascript ast into javascript code strings" do js_code = ElixirScript.compile(":atom") - assert hd(js_code) =~ "Elixir.Kernel.SpecialForms.atom('atom')" + assert Enum.join(js_code, "\n") =~ "Elixir.Kernel.SpecialForms.atom('atom')" end should "parse one module correctly" do @@ -34,10 +34,11 @@ defmodule ElixirScript.Test do """) assert_js_matches """ - import * as Elixir from 'Elixir'; - const __MODULE__ = Elixir.Kernel.SpecialForms.atom('Elixir.Elephant'); + import * as Elixir from 'Elixir'; + import * as Elixir$ElixirScript$Kernel from 'Elixir.ElixirScript.Kernel'; + import * as Elixir$ElixirScript$String$Chars from 'Elixir.ElixirScript.String.Chars'; const something_else = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([],function() { - return Elixir.String.Chars.to_string(10); + return Elixir$ElixirScript$String$Chars.to_string(10); })); const something = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([],function() { return ul; @@ -68,7 +69,8 @@ defmodule ElixirScript.Test do assert_js_matches """ import * as Elixir from 'Elixir'; - const __MODULE__ = Elixir.Kernel.SpecialForms.atom('Elixir.Animals'); + import * as Elixir$Animals$Elephant from 'Elixir.Animals.Elephant'; + import * as Elixir$ElixirScript$Kernel from 'Elixir.ElixirScript.Kernel'; const something = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([],function() { return Elixir$Animals$Elephant.Elixir$Animals$Elephant.create(Elixir.Kernel.SpecialForms.map({})); })); @@ -79,12 +81,13 @@ defmodule ElixirScript.Test do assert_js_matches """ import * as Elixir from 'Elixir'; - const __MODULE__ = Elixir.Kernel.SpecialForms.atom('Elixir.Animals.Elephant'); - const defstruct = Elixir.Kernel.defstruct({ - [Elixir.Kernel.SpecialForms.atom('__struct__')]: __MODULE__, [Elixir.Kernel.SpecialForms.atom('trunk')]: true + import * as Elixir$ElixirScript$Kernel from 'Elixir.ElixirScript.Kernel'; + const Elixir$Animals$Elephant = Elixir.Kernel.defstruct({ + [Elixir.Kernel.SpecialForms.atom('__struct__')]: Elixir.Kernel.SpecialForms.atom('Elixir.Animals.Elephant'), + [Elixir.Kernel.SpecialForms.atom('trunk')]: true }); export { - Elixir$Animals$Elephant: defstruct + Elixir$Animals$Elephant }; """, Enum.fetch!(js_code, 1) end @@ -105,7 +108,7 @@ defmodule ElixirScript.Test do assert_js_matches """ import * as Elixir from 'Elixir'; - const __MODULE__ = Elixir.Kernel.SpecialForms.atom('Elixir.Animals'); + import * as Elixir$ElixirScript$Kernel from 'Elixir.ElixirScript.Kernel'; const something_else = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([],function() { return 1 * 1; })); @@ -135,9 +138,11 @@ defmodule ElixirScript.Test do :document.getElementById("main").appendChild(rootNode) """) - assert hd(js_code) =~ "Elixir.VirtualDOM.h('div'" - assert hd(js_code) =~ "Elixir.VirtualDOM.h('span'" - assert hd(js_code) =~ "Elixir.VirtualDOM.create" + js_code = Enum.join(js_code, "\n") + + assert js_code =~ "Elixir.VirtualDOM.h('div'" + assert js_code =~ "Elixir.VirtualDOM.h('span'" + assert js_code =~ "Elixir.VirtualDOM.create" end @@ -156,7 +161,7 @@ defmodule ElixirScript.Test do assert_js_matches """ import * as Elixir from 'elixirscript'; - const __MODULE__ = Elixir.Kernel.SpecialForms.atom('Elixir.Animals'); + import * as Elixir$ElixirScript$Kernel from 'Elixir.ElixirScript.Kernel'; const something_else = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([],function() { return 1 * 1; })); diff --git a/test/pattern_matching/match_test.exs b/test/pattern_matching/match_test.exs index 3ae2cbdb..9930ea23 100644 --- a/test/pattern_matching/match_test.exs +++ b/test/pattern_matching/match_test.exs @@ -6,237 +6,237 @@ defmodule ElixirScript.PatternMatching.Match.Test do alias ElixirScript.Translator.Map alias ESTree.Tools.Builder, as: JS - should "match wildcard" do - params = [{:_, [], Test}] - result = Match.build_match(params, __ENV__) - expected_result = { [Match.wildcard], [JS.identifier(:undefined)] } - - assert result == expected_result - end - - should "match one identifier param" do - params = [{:a, [], Test}] - result = Match.build_match(params, __ENV__) - expected_result = {[Match.parameter], [JS.identifier("a")]} - - assert result == expected_result - end - - should "match multiple identifier params" do - params = [{:a, [], Test}, {:b, [], Test}, {:c, [], Test}] - result = Match.build_match(params, __ENV__) - expected_result = { - List.duplicate(Match.parameter, 3), - [JS.identifier("a"), JS.identifier("b"), JS.identifier("c")] - } - - assert result == expected_result - end - - should "match head and tail param" do - params = [[{:|, [], [{:head, [], Elixir}, {:tail, [], Elixir}]}]] - result = Match.build_match(params, __ENV__) - expected_result = { - [Match.head_tail], - [JS.identifier("head"), JS.identifier("tail")] - } - - assert result == expected_result - end - - should "match prefix param" do - params = [{:<>, [context: Elixir, import: Elixir.Kernel], ["Bearer ", {:token, [], Elixir}]}] - result = Match.build_match(params, __ENV__) - expected_result = { - [Match.starts_with("Bearer ")], - [JS.identifier("token")] - } - - assert result == expected_result - end - - should "match list" do - params = [[{:a, [], Elixir}, {:b, [], Elixir}, {:c, [], Elixir}]] - result = Match.build_match(params, __ENV__) - expected_result = { - [Primitive.make_list_no_translate(List.duplicate(Match.parameter, 3))], - [JS.identifier("a"), JS.identifier("b"), JS.identifier("c")] - } - - assert result == expected_result - end - - should "match list with a literal" do - params = [[1, {:b, [], Elixir}, {:c, [], Elixir}]] - result = Match.build_match(params, __ENV__) - expected_result = { - [Primitive.make_list_no_translate([JS.literal(1), Match.parameter, Match.parameter])], - [JS.identifier("b"), JS.identifier("c")] - } - - assert result == expected_result - end - - should "match number" do - params = [1] - result = Match.build_match(params, __ENV__) - expected_result = { - [JS.literal(1)], - [] - } - - assert result == expected_result - end - - should "match struct pattern" do - ElixirScript.State.start_link(nil, nil) - - params = [{:%, [], [{:__aliases__, [alias: false], [:Hello]}, {:%{}, [], []}]}] - result = Match.build_match(params, __ENV__) - expected_result = { - [Match.type(JS.identifier(:Hello), JS.object_expression([]))], - [] - } - - assert result == expected_result - - ElixirScript.State.stop() - end - - should "match struct pattern with property" do - ElixirScript.State.start_link(nil, nil) - - params = [{:%, [], [{:__aliases__, [alias: false], [:Hello]}, {:%{}, [], [key: 1]}]}] - result = Match.build_match(params, __ENV__) - expected_result = { - [Match.type(JS.identifier(:Hello), JS.object_expression([ - Map.make_property(Translator.translate(:key, __ENV__), Translator.translate(1, __ENV__)) - ])) - ], - [] - } - - assert result == expected_result - - ElixirScript.State.stop() - end - - should "match struct pattern with property param" do - ElixirScript.State.start_link(nil, nil) - - params = [{:%, [], [{:__aliases__, [alias: false], [:Hello]}, {:%{}, [], [key: {:key, [], Elixir }]}]}] - result = Match.build_match(params, __ENV__) - expected_result = { - [Match.type(JS.identifier(:Hello), JS.object_expression([ - Map.make_property(Translator.translate(:key, __ENV__), Match.parameter) - ])) - ], - [JS.identifier("key")] - } - - assert result == expected_result - - ElixirScript.State.stop() - - end - - should "capture parameter when assigning it" do - ElixirScript.State.start_link(nil, nil) - - params = [{:=, [], [1, {:a, [], Elixir}]}] - result = Match.build_match(params, __ENV__) - expected_result = { - [Match.capture(JS.literal(1))], - [JS.identifier("a")] - } - - assert result == expected_result - - - params = [{:=, [], [{:a, [], Elixir}, 1]}] - result = Match.build_match(params, __ENV__) - expected_result = { - [Match.capture(JS.literal(1))], - [JS.identifier("a")] - } - - assert result == expected_result - - - params = [{:=, [], [{:%, [], [{:__aliases__, [alias: false], [:AStruct]}, {:%{}, [], []}]}, {:a, [], ElixirScript.Translator.Function.Test}]}] - result = Match.build_match(params, __ENV__) - expected_result = { - [Match.capture(Match.type(JS.identifier(:AStruct), JS.object_expression([])))], - [JS.identifier("a")] - } - - assert result == expected_result - - ElixirScript.State.stop() - end - - should "match and assign list" do - params = [{:=, [], [[{:a, [], Elixir}, {:b, [], Elixir}, {:c, [], Elixir}], {:d, [], Elixir}]}] - result = Match.build_match(params, __ENV__) - expected_result = { - [Match.capture(Primitive.make_list_no_translate([Match.parameter, Match.parameter, Match.parameter]))], - [JS.identifier("a"), JS.identifier("b"), JS.identifier("c"), JS.identifier("d")] - } - - assert result == expected_result - end - - should "match on tuple" do - params = [{:{}, [], [1, {:b, [], Elixir}, 3]}] - result = Match.build_match(params, __ENV__) - expected_result = { - [Match.type(Primitive.tuple_class, JS.object_expression([JS.property( - JS.identifier("values"), - JS.array_expression([JS.literal(1), Match.parameter, JS.literal(3)]) - ) ] )) ], - [JS.identifier("b")] - } - - assert result == expected_result - - params = [{1, {:b, [], Elixir}}] - result = Match.build_match(params, __ENV__) - expected_result = { - [Match.type(Primitive.tuple_class, JS.object_expression([JS.property( - JS.identifier("values"), - JS.array_expression([JS.literal(1), Match.parameter]) - ) ] )) ], - [JS.identifier("b")] - } - - assert result == expected_result - end - - should "match on map" do - params = [{:%{}, [], [which: 13]}] - result = Match.build_match(params, __ENV__) - - expected_result = { - [JS.object_expression([ - Map.make_property(Translator.translate(:which, __ENV__), JS.literal(13)) - ])], - [] - } - - assert result == expected_result - end - - - should "match on bound value" do - params = [{:^, [], [{:a, [], Elixir}]}] - result = Match.build_match(params, __ENV__) - - expected_result = { - [Match.bound(JS.identifier("a"))], - [nil] - } - - assert result == expected_result - end +# should "match wildcard" do +# params = [{:_, [], Test}] +# result = Match.build_match(params, ElixirScript.Env.module_env(ElixirScript.Temp, "temp.ex") ) +# expected_result = { [Match.wildcard], [JS.identifier(:undefined)] } +# +# assert result == expected_result +# end +# +# should "match one identifier param" do +# params = [{:a, [], Test}] +# result = Match.build_match(params, ElixirScript.Env.module_env(ElixirScript.Temp, "temp.ex") ) +# expected_result = {[Match.parameter], [JS.identifier("a")]} +# +# assert result == expected_result +# end +# +# should "match multiple identifier params" do +# params = [{:a, [], Test}, {:b, [], Test}, {:c, [], Test}] +# result = Match.build_match(params, ElixirScript.Env.module_env(ElixirScript.Temp, "temp.ex") ) +# expected_result = { +# List.duplicate(Match.parameter, 3), +# [JS.identifier("a"), JS.identifier("b"), JS.identifier("c")] +# } +# +# assert result == expected_result +# end +# +# should "match head and tail param" do +# params = [[{:|, [], [{:head, [], Elixir}, {:tail, [], Elixir}]}]] +# result = Match.build_match(params, ElixirScript.Env.module_env(ElixirScript.Temp, "temp.ex") ) +# expected_result = { +# [Match.head_tail], +# [JS.identifier("head"), JS.identifier("tail")] +# } +# +# assert result == expected_result +# end +# +# should "match prefix param" do +# params = [{:<>, [context: Elixir, import: Elixir.Kernel], ["Bearer ", {:token, [], Elixir}]}] +# result = Match.build_match(params, ElixirScript.Env.module_env(ElixirScript.Temp, "temp.ex") ) +# expected_result = { +# [Match.starts_with("Bearer ")], +# [JS.identifier("token")] +# } +# +# assert result == expected_result +# end +# +# should "match list" do +# params = [[{:a, [], Elixir}, {:b, [], Elixir}, {:c, [], Elixir}]] +# result = Match.build_match(params, ElixirScript.Env.module_env(ElixirScript.Temp, "temp.ex") ) +# expected_result = { +# [Primitive.make_list_no_translate(List.duplicate(Match.parameter, 3))], +# [JS.identifier("a"), JS.identifier("b"), JS.identifier("c")] +# } +# +# assert result == expected_result +# end +# +# should "match list with a literal" do +# params = [[1, {:b, [], Elixir}, {:c, [], Elixir}]] +# result = Match.build_match(params, ElixirScript.Env.module_env(ElixirScript.Temp, "temp.ex") ) +# expected_result = { +# [Primitive.make_list_no_translate([JS.literal(1), Match.parameter, Match.parameter])], +# [JS.identifier("b"), JS.identifier("c")] +# } +# +# assert result == expected_result +# end +# +# should "match number" do +# params = [1] +# result = Match.build_match(params, ElixirScript.Env.module_env(ElixirScript.Temp, "temp.ex") ) +# expected_result = { +# [JS.literal(1)], +# [] +# } +# +# assert result == expected_result +# end +# +# should "match struct pattern" do +# ElixirScript.State.start_link(nil, nil) +# +# params = [{:%, [], [{:__aliases__, [alias: false], [:Hello]}, {:%{}, [], []}]}] +# result = Match.build_match(params, ElixirScript.Env.module_env(ElixirScript.Temp, "temp.ex") ) +# expected_result = { +# [Match.type(JS.identifier(:Hello), JS.object_expression([]))], +# [] +# } +# +# assert result == expected_result +# +# ElixirScript.State.stop() +# end +# +# should "match struct pattern with property" do +# ElixirScript.State.start_link(nil, nil) +# +# params = [{:%, [], [{:__aliases__, [alias: false], [:Hello]}, {:%{}, [], [key: 1]}]}] +# result = Match.build_match(params, ElixirScript.Env.module_env(ElixirScript.Temp, "temp.ex") ) +# expected_result = { +# [Match.type(JS.identifier(:Hello), JS.object_expression([ +# Map.make_property(Translator.translate!(:key, ElixirScript.Env.module_env(ElixirScript.Temp, "temp.ex") ), Translator.translate!(1, ElixirScript.Env.module_env(ElixirScript.Temp, "temp.ex") )) +# ])) +# ], +# [] +# } +# +# assert result == expected_result +# +# ElixirScript.State.stop() +# end +# +# should "match struct pattern with property param" do +# ElixirScript.State.start_link(nil, nil) +# +# params = [{:%, [], [{:__aliases__, [alias: false], [:Hello]}, {:%{}, [], [key: {:key, [], Elixir }]}]}] +# result = Match.build_match(params, ElixirScript.Env.module_env(ElixirScript.Temp, "temp.ex") ) +# expected_result = { +# [Match.type(JS.identifier(:Hello), JS.object_expression([ +# Map.make_property(Translator.translate!(:key, ElixirScript.Env.module_env(ElixirScript.Temp, "temp.ex") ), Match.parameter) +# ])) +# ], +# [JS.identifier("key")] +# } +# +# assert result == expected_result +# +# ElixirScript.State.stop() +# +# end +# +# should "capture parameter when assigning it" do +# ElixirScript.State.start_link(nil, nil) +# +# params = [{:=, [], [1, {:a, [], Elixir}]}] +# result = Match.build_match(params, ElixirScript.Env.module_env(ElixirScript.Temp, "temp.ex") ) +# expected_result = { +# [Match.capture(JS.literal(1))], +# [JS.identifier("a")] +# } +# +# assert result == expected_result +# +# +# params = [{:=, [], [{:a, [], Elixir}, 1]}] +# result = Match.build_match(params, ElixirScript.Env.module_env(ElixirScript.Temp, "temp.ex") ) +# expected_result = { +# [Match.capture(JS.literal(1))], +# [JS.identifier("a")] +# } +# +# assert result == expected_result +# +# +# params = [{:=, [], [{:%, [], [{:__aliases__, [alias: false], [:AStruct]}, {:%{}, [], []}]}, {:a, [], ElixirScript.Translator.Function.Test}]}] +# result = Match.build_match(params, ElixirScript.Env.module_env(ElixirScript.Temp, "temp.ex") ) +# expected_result = { +# [Match.capture(Match.type(JS.identifier(:AStruct), JS.object_expression([])))], +# [JS.identifier("a")] +# } +# +# assert result == expected_result +# +# ElixirScript.State.stop() +# end +# +# should "match and assign list" do +# params = [{:=, [], [[{:a, [], Elixir}, {:b, [], Elixir}, {:c, [], Elixir}], {:d, [], Elixir}]}] +# result = Match.build_match(params, ElixirScript.Env.module_env(ElixirScript.Temp, "temp.ex") ) +# expected_result = { +# [Match.capture(Primitive.make_list_no_translate([Match.parameter, Match.parameter, Match.parameter]))], +# [JS.identifier("a"), JS.identifier("b"), JS.identifier("c"), JS.identifier("d")] +# } +# +# assert result == expected_result +# end +# +# should "match on tuple" do +# params = [{:{}, [], [1, {:b, [], Elixir}, 3]}] +# result = Match.build_match(params, ElixirScript.Env.module_env(ElixirScript.Temp, "temp.ex") ) +# expected_result = { +# [Match.type(Primitive.tuple_class, JS.object_expression([JS.property( +# JS.identifier("values"), +# JS.array_expression([JS.literal(1), Match.parameter, JS.literal(3)]) +# ) ] )) ], +# [JS.identifier("b")] +# } +# +# assert result == expected_result +# +# params = [{1, {:b, [], Elixir}}] +# result = Match.build_match(params, ElixirScript.Env.module_env(ElixirScript.Temp, "temp.ex") ) +# expected_result = { +# [Match.type(Primitive.tuple_class, JS.object_expression([JS.property( +# JS.identifier("values"), +# JS.array_expression([JS.literal(1), Match.parameter]) +# ) ] )) ], +# [JS.identifier("b")] +# } +# +# assert result == expected_result +# end +# +# should "match on map" do +# params = [{:%{}, [], [which: 13]}] +# result = Match.build_match(params, ElixirScript.Env.module_env(ElixirScript.Temp, "temp.ex") ) +# +# expected_result = { +# [JS.object_expression([ +# Map.make_property(Translator.translate!(:which, ElixirScript.Env.module_env(ElixirScript.Temp, "temp.ex") ), JS.literal(13)) +# ])], +# [] +# } +# +# assert result == expected_result +# end +# +# +# should "match on bound value" do +# params = [{:^, [], [{:a, [], Elixir}]}] +# result = Match.build_match(params, ElixirScript.Env.module_env(ElixirScript.Temp, "temp.ex") ) +# +# expected_result = { +# [Match.bound(JS.identifier("a"))], +# [nil] +# } +# +# assert result == expected_result +# end end diff --git a/test/test_helper.exs b/test/test_helper.exs index 0cc4b2ca..f541a448 100644 --- a/test/test_helper.exs +++ b/test/test_helper.exs @@ -21,10 +21,9 @@ end defmodule ElixirScript.TestHelper do use ShouldI - require Logger def make_custom_env do - require Logger + use ElixirScript require ElixirScript.Math require ElixirScript.Using __ENV__ diff --git a/test/translator/atom_test.exs b/test/translator/atom_test.exs index 3c323f2d..6e51bd97 100644 --- a/test/translator/atom_test.exs +++ b/test/translator/atom_test.exs @@ -6,4 +6,9 @@ defmodule ElixirScript.Translator.Atom.Test do ex_ast = quote do: :atom assert_translation(ex_ast, "Elixir.Kernel.SpecialForms.atom('atom')") end -end \ No newline at end of file + + should "Call Atom module" do + ex_ast = quote do: Atom.to_string(:atom) + assert_translation(ex_ast, "Elixir$ElixirScript$Atom.to_string(Elixir.Kernel.SpecialForms.atom('atom'))") + end +end diff --git a/test/translator/bug_test.exs b/test/translator/bug_test.exs index ad50a8fa..eefc9208 100644 --- a/test/translator/bug_test.exs +++ b/test/translator/bug_test.exs @@ -46,11 +46,10 @@ defmodule ElixirScript.Translator.Bug.Test do end js_code = """ - import { default as JQuery } from 'jquery'; - const __MODULE__ = Elixir.Kernel.SpecialForms.atom('Elixir.App.Todo'); - - JQuery(Elixir.Core.call_property(e, 'target')); - export {}; + import { default as JQuery } from 'jquery'; + import * as Elixir$ElixirScript$Kernel from 'Elixir.ElixirScript.Kernel'; + JQuery(Elixir.Core.call_property(e,'target')); + export {}; """ assert_translation(ex_ast, js_code) diff --git a/test/translator/capture_test.exs b/test/translator/capture_test.exs index c291b304..bcfcc7d4 100644 --- a/test/translator/capture_test.exs +++ b/test/translator/capture_test.exs @@ -9,7 +9,7 @@ defmodule ElixirScript.Translator.Capture.Test do js_code = """ let [fun] = Elixir.Core.Patterns.match(Elixir.Core.Patterns.variable(),Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable()],function(__1) { - return Elixir.Kernel.is_atom(__1); + return Elixir$ElixirScript$Kernel.is_atom(__1); }))); """ @@ -25,7 +25,7 @@ defmodule ElixirScript.Translator.Capture.Test do js_code = """ let [fun] = Elixir.Core.Patterns.match(Elixir.Core.Patterns.variable(),Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable()],function(__1) { - return Elixir.Kernel.is_atom(__1); + return Elixir$ElixirScript$Kernel.is_atom(__1); }))); """ @@ -50,7 +50,7 @@ defmodule ElixirScript.Translator.Capture.Test do end - should "translate capture operator with anonymous function" do + should "translate capture operator with anonymous function" do ex_ast = quote do fun = &(&1 * 2) @@ -66,7 +66,7 @@ defmodule ElixirScript.Translator.Capture.Test do end - should "translate capture operator with anonymous function tuple" do + should "translate capture operator with anonymous function tuple" do ex_ast = quote do fun = &{&1, &2} @@ -95,7 +95,7 @@ defmodule ElixirScript.Translator.Capture.Test do end - should "translate capture operator with anonymous functions as parameters" do + should "translate capture operator with anonymous functions as parameters" do ex_ast = quote do Elixir.Enum.map(items, &process(&1)) @@ -122,4 +122,4 @@ defmodule ElixirScript.Translator.Capture.Test do assert_translation(ex_ast, js_code) end -end \ No newline at end of file +end diff --git a/test/translator/case_test.exs b/test/translator/case_test.exs index 0192a804..bbc3a57d 100644 --- a/test/translator/case_test.exs +++ b/test/translator/case_test.exs @@ -30,8 +30,8 @@ defmodule ElixirScript.Translator.Case.Test do js_code = """ Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([false],function() { - let [value0] = Elixir.Core.Patterns.match(Elixir.Core.Patterns.variable(),13); - return value0; + let [value] = Elixir.Core.Patterns.match(Elixir.Core.Patterns.variable(),13); + return value; }),Elixir.Core.Patterns.make_case([true],function() { return true; })).call(this,data) @@ -50,8 +50,8 @@ defmodule ElixirScript.Translator.Case.Test do js_code = """ Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([false],function() { - let [value0] = Elixir.Core.Patterns.match(Elixir.Core.Patterns.variable(),13); - return value0; + let [value] = Elixir.Core.Patterns.match(Elixir.Core.Patterns.variable(),13); + return value; }),Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.wildcard()],function() { return true; })).call(this,data) @@ -72,10 +72,10 @@ defmodule ElixirScript.Translator.Case.Test do js_code = """ Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable()],function(number) { - let [value0] = Elixir.Core.Patterns.match(Elixir.Core.Patterns.variable(),13); - return value0; + let [value] = Elixir.Core.Patterns.match(Elixir.Core.Patterns.variable(),13); + return value; },function(number) { - return Elixir.Kernel.in(number,Elixir.Kernel.SpecialForms.list(1,2,3,4)); + return Elixir.Core.contains(number,Elixir.Kernel.SpecialForms.list(1,2,3,4)); }),Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.wildcard()],function() { return true; })).call(this,data) @@ -88,7 +88,7 @@ defmodule ElixirScript.Translator.Case.Test do ex_ast = quote do case data do :ok -> - Logger.info("info") + :console.info("info") Todo.add(data) :error -> nil @@ -111,7 +111,7 @@ defmodule ElixirScript.Translator.Case.Test do ex_ast = quote do case data do { one, two } -> - Logger.info(one) + :console.info(one) :error -> nil end @@ -134,7 +134,7 @@ defmodule ElixirScript.Translator.Case.Test do ex_ast = quote do case data do { {one, two} , three } -> - Logger.info(one) + :console.info(one) :error -> nil end @@ -157,7 +157,7 @@ defmodule ElixirScript.Translator.Case.Test do ex_ast = quote do case data do { one, {two, three} } -> - Logger.info(one) + :console.info(one) :error -> nil end @@ -181,7 +181,7 @@ defmodule ElixirScript.Translator.Case.Test do ex_ast = quote do case data do %AStruct{key: %BStruct{ key2: value }} -> - Logger.info(value) + :console.info(value) :error -> nil end @@ -205,7 +205,7 @@ defmodule ElixirScript.Translator.Case.Test do ex_ast = quote do case data do %AStruct{key: %BStruct{ key2: value, key3: %CStruct{ key4: value2 } }} -> - Logger.info(value) + :console.info(value) :error -> nil end diff --git a/test/translator/defmodule_test.exs b/test/translator/defmodule_test.exs index 6f7de66e..d586a0f3 100644 --- a/test/translator/defmodule_test.exs +++ b/test/translator/defmodule_test.exs @@ -9,7 +9,7 @@ defmodule ElixirScript.Translator.Defmodule.Test do end js_code = """ - const __MODULE__ = Elixir.Kernel.SpecialForms.atom('Elixir.Elephant'); + import * as Elixir$ElixirScript$Kernel from 'Elixir.ElixirScript.Kernel'; export {}; """ @@ -31,7 +31,8 @@ defmodule ElixirScript.Translator.Defmodule.Test do end js_code = """ - const __MODULE__ = Elixir.Kernel.SpecialForms.atom('Elixir.Elephant'); + + import * as Elixir$ElixirScript$Kernel from 'Elixir.ElixirScript.Kernel'; const something_else = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([],function() { return null; })); @@ -45,33 +46,6 @@ defmodule ElixirScript.Translator.Defmodule.Test do """ assert_translation(ex_ast, js_code) - - ex_ast = quote do - defmodule Elephant do - alias Icabod.Crane - - def something() do - end - - defp something_else() do - end - end - end - - js_code = """ - const __MODULE__ = Elixir.Kernel.SpecialForms.atom('Elixir.Elephant'); - const something_else = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([],function() { - return null; - })); - const something = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([],function() { - return null; - })); - export { - something - }; - """ - - assert_translation(ex_ast, js_code) end should "translate modules with inner modules" do @@ -93,28 +67,28 @@ defmodule ElixirScript.Translator.Defmodule.Test do end js_code = """ - const __MODULE__ = Elixir.Kernel.SpecialForms.atom('Elixir.Animals.Elephant'); - const defstruct = Elixir.Kernel.defstruct({ - [Elixir.Kernel.SpecialForms.atom('__struct__')]: __MODULE__, - [Elixir.Kernel.SpecialForms.atom('trunk')]: true - }); - export { - Elixir$Animals$Elephant: defstruct - }; + import * as Elixir$Animals$Elephant from 'Elixir.Animals.Elephant'; + import * as Elixir$ElixirScript$Kernel from 'Elixir.ElixirScript.Kernel'; + const something_else = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([],function() { + return null; + })); - const __MODULE__ = Elixir.Kernel.SpecialForms.atom('Elixir.Animals'); + const something = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([],function() { + return Elixir$Animals$Elephant.Elixir$Animals$Elephant.create(Elixir.Kernel.SpecialForms.map({})); + })); - const something_else = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([],function() { - return null; - })); + export { + something + }; - const something = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([],function() { - return Elixir$Animals$Elephant.Elixir$Animals$Elephant.create(Elixir.Kernel.SpecialForms.map({})); - })); + import * as Elixir$ElixirScript$Kernel from 'Elixir.ElixirScript.Kernel'; + const Elixir$Animals$Elephant = Elixir.Kernel.defstruct({ + [Elixir.Kernel.SpecialForms.atom('__struct__')]: Elixir.Kernel.SpecialForms.atom('Elixir.Animals.Elephant'), [Elixir.Kernel.SpecialForms.atom('trunk')]: true + }); - export { - something - }; + export { + Elixir$Animals$Elephant + }; """ assert_translation(ex_ast, js_code) @@ -145,31 +119,37 @@ defmodule ElixirScript.Translator.Defmodule.Test do end js_code = """ - const __MODULE__ = Elixir.Kernel.SpecialForms.atom('Elixir.Animals'); + import * as Elixir$Animals$Elephant from 'Elixir.Animals.Elephant'; + import * as Elixir$ElixirScript$Kernel from 'Elixir.ElixirScript.Kernel'; const something_else = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([],function() { return null; })); const something = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([],function() { return Elixir$Animals$Elephant.Elixir$Animals$Elephant.create(Elixir.Kernel.SpecialForms.map({})); })); + export { something }; - const __MODULE__ = Elixir.Kernel.SpecialForms.atom('Elixir.Animals.Elephant.Bear'); - const defstruct = Elixir.Kernel.defstruct({ - [Elixir.Kernel.SpecialForms.atom('__struct__')]: __MODULE__, [Elixir.Kernel.SpecialForms.atom('trunk')]: true + import * as Elixir$Animals$Elephant$Bear from 'Elixir.Animals.Elephant.Bear'; + import * as Elixir$ElixirScript$Kernel from 'Elixir.ElixirScript.Kernel'; + const Elixir$Animals$Elephant = Elixir.Kernel.defstruct({ + [Elixir.Kernel.SpecialForms.atom('__struct__')]: Elixir.Kernel.SpecialForms.atom('Elixir.Animals.Elephant'), + [Elixir.Kernel.SpecialForms.atom('trunk')]: true }); export { - Elixir$Animals$Elephant$Bear: defstruct + Elixir$Animals$Elephant }; - const __MODULE__ = Elixir.Kernel.SpecialForms.atom('Elixir.Animals.Elephant'); - const defstruct = Elixir.Kernel.defstruct({ - [Elixir.Kernel.SpecialForms.atom('__struct__')]: __MODULE__, [Elixir.Kernel.SpecialForms.atom('trunk')]: true + import * as Elixir$ElixirScript$Kernel from 'Elixir.ElixirScript.Kernel'; + const Elixir$Animals$Elephant$Bear = Elixir.Kernel.defstruct({ + [Elixir.Kernel.SpecialForms.atom('__struct__')]: Elixir.Kernel.SpecialForms.atom('Elixir.Animals.Elephant.Bear'), + [Elixir.Kernel.SpecialForms.atom('trunk')]: true }); + export { - Elixir$Animals$Elephant: defstruct + Elixir$Animals$Elephant$Bear }; """ @@ -188,14 +168,14 @@ defmodule ElixirScript.Translator.Defmodule.Test do end js_code = """ - const __MODULE__ = Elixir.Kernel.SpecialForms.atom('Elixir.Lions.Tigers'); - Elixir.Core.call_property(Lions.Tigers.Bears,'oh_my'); - export {}; - + import * as Elixir$ElixirScript$Kernel from 'Elixir.ElixirScript.Kernel'; import * as Elixir$Lions$Tigers from 'Elixir.Lions.Tigers'; - const __MODULE__ = Elixir.Kernel.SpecialForms.atom('Elixir.Animals'); Elixir.Core.call_property(Elixir$Lions$Tigers,'oh_my'); export {}; + + import * as Elixir$ElixirScript$Kernel from 'Elixir.ElixirScript.Kernel'; + Elixir.Core.call_property(Lions.Tigers.Bears,'oh_my'); + export {}; """ assert_translation(ex_ast, js_code) @@ -218,12 +198,12 @@ defmodule ElixirScript.Translator.Defmodule.Test do end js_code = """ + import * as Elixir$ElixirScript$Kernel from 'Elixir.ElixirScript.Kernel'; import * as Elixir$Lions$Tigers from 'Elixir.Lions.Tigers'; - const __MODULE__ = Elixir.Kernel.SpecialForms.atom('Elixir.Animals'); Elixir.Core.call_property(Elixir$Lions$Tigers,'oh_my'); export {}; - const __MODULE__ = Elixir.Kernel.SpecialForms.atom('Elixir.Lions.Tigers'); + import * as Elixir$ElixirScript$Kernel from 'Elixir.ElixirScript.Kernel'; const oh_my = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([],function() { return null; })); @@ -247,29 +227,30 @@ defmodule ElixirScript.Translator.Defmodule.Test do end defmodule Animals do - import Lions.Tigers, only: [oh_my: 1] + import Lions.Tigers, only: [oh_my: 0] oh_my() end end js_code = """ - const __MODULE__ = Elixir.Kernel.SpecialForms.atom('Elixir.Lions.Tigers'); + import * as Elixir$ElixirScript$Kernel from 'Elixir.ElixirScript.Kernel'; + import * as Elixir$Lions$Tigers from 'Elixir.Lions.Tigers'; + Elixir$Lions$Tigers.oh_my(); + export {}; + + import * as Elixir$ElixirScript$Kernel from 'Elixir.ElixirScript.Kernel'; const oh_my2 = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([],function() { - return null; - })); + return null; + })); + const oh_my = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([],function() { - return null; - })); + return null; + })); + export { - oh_my2, - oh_my + oh_my2, oh_my }; - - import * as Elixir$Lions$Tigers from 'Elixir.Lions.Tigers'; - const __MODULE__ = Elixir.Kernel.SpecialForms.atom('Elixir.Animals'); - Elixir$Lions$Tigers.oh_my(); - export {}; """ assert_translation(ex_ast, js_code) @@ -293,12 +274,12 @@ defmodule ElixirScript.Translator.Defmodule.Test do end js_code = """ + import * as Elixir$ElixirScript$Kernel from 'Elixir.ElixirScript.Kernel'; import * as Elixir$Lions$Tigers from 'Elixir.Lions.Tigers'; - const __MODULE__ = Elixir.Kernel.SpecialForms.atom('Elixir.Animals'); Elixir$Lions$Tigers.oh_my2(); export {}; - const __MODULE__ = Elixir.Kernel.SpecialForms.atom('Elixir.Lions.Tigers'); + import * as Elixir$ElixirScript$Kernel from 'Elixir.ElixirScript.Kernel'; const oh_my2 = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([],function() { return null; })); diff --git a/test/translator/for_test.exs b/test/translator/for_test.exs index 40c4da9b..8123bb8c 100644 --- a/test/translator/for_test.exs +++ b/test/translator/for_test.exs @@ -93,9 +93,9 @@ defmodule ElixirScript.Translator.For.Test do js_code = """ Elixir.Kernel.SpecialForms._for(Elixir.Kernel.SpecialForms.list(Elixir.Kernel.SpecialForms.list(Elixir.Core.Patterns.variable(),Elixir.Kernel.SpecialForms.list(1,2,3,4,5,6))),function(n) { - return n; + return n; },function(n) { - return n % 2 == 0; + return n % 2 == 0; },Elixir.Kernel.SpecialForms.list()) """ @@ -105,7 +105,7 @@ defmodule ElixirScript.Translator.For.Test do should "translate for with pattern matched input" do ex_ast = quote do for {:user, name} <- [user: "john", admin: "john", user: "meg"] do - String.upcase(name) + Elixir.String.upcase(name) end end diff --git a/test/translator/function_test.exs b/test/translator/function_test.exs index b1116b3b..c1e7b713 100644 --- a/test/translator/function_test.exs +++ b/test/translator/function_test.exs @@ -67,8 +67,8 @@ defmodule ElixirScript.Translator.Function.Test do js_code = """ const test1 = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable(), Elixir.Core.Patterns.variable()],function(alpha,beta) { - let [a0] = Elixir.Core.Patterns.match(Elixir.Core.Patterns.variable(),alpha); - return a0; + let [a] = Elixir.Core.Patterns.match(Elixir.Core.Patterns.variable(),alpha); + return a; })); """ @@ -89,7 +89,7 @@ defmodule ElixirScript.Translator.Function.Test do return Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable()],function(x) { return 2; },function(x) { - return Elixir.Kernel.in(x,Elixir.Kernel.SpecialForms.list(false,null)); + return Elixir.Enum.member__qmark__(Elixir.Kernel.SpecialForms.list(false,null), x); }),Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.wildcard()],function() { return 1; })).call(this,1 == 1); @@ -113,22 +113,22 @@ defmodule ElixirScript.Translator.Function.Test do end js_code = """ - const test1 = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable(), Elixir.Core.Patterns.variable()],function(alpha,beta) { - return Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable()],function(x) { - return 2; - },function(x) { - return Elixir.Kernel.in(x,Elixir.Kernel.SpecialForms.list(false,null)); - }),Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.wildcard()],function() { - return Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable()],function(x) { - let [a000] = Elixir.Core.Patterns.match(Elixir.Core.Patterns.variable(),1); - return a000; - },function(x) { - return Elixir.Kernel.in(x,Elixir.Kernel.SpecialForms.list(false,null)); - }),Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.wildcard()],function() { - return 4; - })).call(this,2 == 2); - })).call(this,1 == 1); - })); + const test1 = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable(), Elixir.Core.Patterns.variable()],function(alpha,beta) { + return Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable()],function(x) { + return 2; + },function(x) { + return Elixir.Enum.member__qmark__(Elixir.Kernel.SpecialForms.list(false,null),x); + }),Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.wildcard()],function() { + return Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable()],function(x) { + let [a] = Elixir.Core.Patterns.match(Elixir.Core.Patterns.variable(), 1); + return a; + },function(x) { + return Elixir.Enum.member__qmark__(Elixir.Kernel.SpecialForms.list(false,null),x); + }),Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.wildcard()],function() { + return 4; + })).call(this,2 == 2); + })).call(this,1 == 1); + })); """ assert_translation(ex_ast, js_code) @@ -141,10 +141,10 @@ defmodule ElixirScript.Translator.Function.Test do js_code = """ const test1 = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable(), Elixir.Core.Patterns.variable()], function(alpha, beta) { - let [a0, b0] = Elixir.Core.Patterns.match(Elixir.Core.Patterns.type(Elixir.Core.Tuple, { + let [a, b] = Elixir.Core.Patterns.match(Elixir.Core.Patterns.type(Elixir.Core.Tuple, { values: [Elixir.Core.Patterns.variable(), Elixir.Core.Patterns.variable()] }), Elixir.Kernel.SpecialForms.tuple(1, 2)); - let _ref = Elixir.Kernel.SpecialForms.tuple(a0, b0); + let _ref = Elixir.Kernel.SpecialForms.tuple(a, b); return _ref; })); """ @@ -239,7 +239,7 @@ defmodule ElixirScript.Translator.Function.Test do end js_code = """ - const __MODULE__ = Elixir.Kernel.SpecialForms.atom('Elixir.Example'); + import * as Elixir$ElixirScript$Kernel from 'Elixir.ElixirScript.Kernel'; const example = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([],function() { return null; }),Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable()],function(oneArg) { @@ -276,7 +276,7 @@ defmodule ElixirScript.Translator.Function.Test do end js_code = """ - const __MODULE__ = Elixir.Kernel.SpecialForms.atom('Elixir.Example'); + import * as Elixir$ElixirScript$Kernel from 'Elixir.ElixirScript.Kernel'; const example = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([],function() { return null; }),Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable()],function(oneArg) { @@ -303,7 +303,7 @@ defmodule ElixirScript.Translator.Function.Test do end js_code = """ - const __MODULE__ = Elixir.Kernel.SpecialForms.atom('Elixir.Example'); + import * as Elixir$ElixirScript$Kernel from 'Elixir.ElixirScript.Kernel'; const example = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable()],function(oneArg) { return null; })); @@ -339,7 +339,7 @@ defmodule ElixirScript.Translator.Function.Test do is_atom(:atom) end - js_code = "Elixir.Kernel.is_atom(Elixir.Kernel.SpecialForms.atom('atom'))" + js_code = "Elixir$ElixirScript$Kernel.is_atom(Elixir.Kernel.SpecialForms.atom('atom'))" assert_translation(ex_ast, js_code) end @@ -355,7 +355,7 @@ defmodule ElixirScript.Translator.Function.Test do const something = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable()],function(one) { return null; },function(one) { - return Elixir.Kernel.is_number(one); + return Elixir$ElixirScript$Kernel.is_number(one); })); """ @@ -372,7 +372,7 @@ defmodule ElixirScript.Translator.Function.Test do const something = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable()],function(one) { return null; },function(one) { - return Elixir.Kernel.is_number(one) || Elixir.Kernel.is_atom(one); + return Elixir$ElixirScript$Kernel.is_number(one) || Elixir$ElixirScript$Kernel.is_atom(one); })); """ @@ -388,7 +388,7 @@ defmodule ElixirScript.Translator.Function.Test do const something = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable()],function(one) { return null; },function(one) { - return Elixir.Kernel.is_number(one) || Elixir.Kernel.is_atom(one); + return Elixir$ElixirScript$Kernel.is_number(one) || Elixir$ElixirScript$Kernel.is_atom(one); })); """ @@ -401,11 +401,11 @@ defmodule ElixirScript.Translator.Function.Test do js_code = """ - const something = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable(), Elixir.Core.Patterns.variable()],function(one,two) { - return null; - },function(one,two) { - return Elixir.Kernel.in(one,Elixir.Kernel.SpecialForms.list(1,2,3)); - })); + const something = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable(), Elixir.Core.Patterns.variable()],function(one,two) { + return null; + },function(one,two) { + return Elixir.Core.contains(one,Elixir.Kernel.SpecialForms.list(1,2,3)); + })); """ assert_translation(ex_ast, js_code) @@ -421,15 +421,15 @@ defmodule ElixirScript.Translator.Function.Test do end js_code = """ - const __MODULE__ = Elixir.Kernel.SpecialForms.atom('Elixir.Example'); + import * as Elixir$ElixirScript$Kernel from 'Elixir.ElixirScript.Kernel'; const something = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable()],function(one) { return null; },function(one) { - return Elixir.Kernel.in(one,Elixir.Kernel.SpecialForms.list(1,2,3)); + return Elixir.Core.contains(one,Elixir.Kernel.SpecialForms.list(1,2,3)); }),Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable()],function(one) { return null; },function(one) { - return Elixir.Kernel.is_number(one) || Elixir.Kernel.is_atom(one); + return Elixir$ElixirScript$Kernel.is_number(one) || Elixir$ElixirScript$Kernel.is_atom(one); })); export { something @@ -581,7 +581,7 @@ defmodule ElixirScript.Translator.Function.Test do })], function(value) { return null; }, function(value) { - return Elixir.Kernel.is_number(value); + return Elixir$ElixirScript$Kernel.is_number(value); })); """ @@ -652,7 +652,7 @@ defmodule ElixirScript.Translator.Function.Test do js_code = """ - const __MODULE__ = Elixir.Kernel.SpecialForms.atom('Elixir.Example'); + import * as Elixir$ElixirScript$Kernel from 'Elixir.ElixirScript.Kernel'; const something = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([1],function() { return null; }),Elixir.Core.Patterns.make_case([2],function() { @@ -660,7 +660,7 @@ defmodule ElixirScript.Translator.Function.Test do }),Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable()],function(one) { return null; },function(one) { - return Elixir.Kernel.is_binary(one); + return Elixir$ElixirScript$Kernel.is_binary(one); }),Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable()],function(one) { return null; })); @@ -683,7 +683,7 @@ defmodule ElixirScript.Translator.Function.Test do js_code = """ const test1 = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable(), Elixir.Core.Patterns.variable()],function(alpha,beta) { - let [a0] = Elixir.Core.Patterns.match(Elixir.Core.Patterns.variable(),1); + let [a] = Elixir.Core.Patterns.match(Elixir.Core.Patterns.variable(),1); let [a1] = Elixir.Core.Patterns.match(Elixir.Core.Patterns.variable(),2); return a1; })); @@ -701,8 +701,8 @@ defmodule ElixirScript.Translator.Function.Test do js_code = """ const test1 = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable(), Elixir.Core.Patterns.variable()],function(alpha,beta) { - let [a0] = Elixir.Core.Patterns.match(Elixir.Core.Patterns.variable(),1); - let [a1] = Elixir.Core.Patterns.match(Elixir.Core.Patterns.variable(),a0); + let [a] = Elixir.Core.Patterns.match(Elixir.Core.Patterns.variable(),1); + let [a1] = Elixir.Core.Patterns.match(Elixir.Core.Patterns.variable(),a); let [a2] = Elixir.Core.Patterns.match(Elixir.Core.Patterns.variable(),2); return a2; })); @@ -719,9 +719,9 @@ defmodule ElixirScript.Translator.Function.Test do js_code = """ const test1 = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable(), Elixir.Core.Patterns.variable()],function(alpha,beta) { - let [a0] = Elixir.Core.Patterns.match(Elixir.Core.Patterns.variable(),1); - let [a1,b0,c0] = Elixir.Core.Patterns.match(Elixir.Kernel.SpecialForms.list(Elixir.Core.Patterns.variable(),Elixir.Core.Patterns.variable(),Elixir.Core.Patterns.variable()),Elixir.Kernel.SpecialForms.list(a0,2,3)); - let _ref = Elixir.Kernel.SpecialForms.list(a1,b0,c0); + let [a] = Elixir.Core.Patterns.match(Elixir.Core.Patterns.variable(),1); + let [a1,b,c] = Elixir.Core.Patterns.match(Elixir.Kernel.SpecialForms.list(Elixir.Core.Patterns.variable(),Elixir.Core.Patterns.variable(),Elixir.Core.Patterns.variable()),Elixir.Kernel.SpecialForms.list(a,2,3)); + let _ref = Elixir.Kernel.SpecialForms.list(a1,b,c); return _ref; })); """ @@ -739,9 +739,9 @@ defmodule ElixirScript.Translator.Function.Test do js_code = """ const test1 = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable(), Elixir.Core.Patterns.variable()],function(alpha__qmark__,beta__emark__) { - let [a__qmark__0] = Elixir.Core.Patterns.match(Elixir.Core.Patterns.variable(),1); - let [b__emark__0] = Elixir.Core.Patterns.match(Elixir.Core.Patterns.variable(),2); - return b__emark__0; + let [a__qmark__] = Elixir.Core.Patterns.match(Elixir.Core.Patterns.variable(),1); + let [b__emark__] = Elixir.Core.Patterns.match(Elixir.Core.Patterns.variable(),2); + return b__emark__; })); """ diff --git a/test/translator/kernel_test.exs b/test/translator/kernel_test.exs index 7cc82bf7..1113504f 100644 --- a/test/translator/kernel_test.exs +++ b/test/translator/kernel_test.exs @@ -8,10 +8,10 @@ defmodule ElixirScript.Translator.Kernel.Test do end js_code = """ - Math.max(1, 2) + Elixir$ElixirScript$Kernel.max(1, 2) """ - assert_translation(ex_ast, js_code) + assert_translation(ex_ast, js_code) end @@ -21,10 +21,10 @@ defmodule ElixirScript.Translator.Kernel.Test do end js_code = """ - fun(1,2,3) + Elixir$ElixirScript$Kernel.apply(fun, Elixir.Kernel.SpecialForms.list(1,2,3)) """ - assert_translation(ex_ast, js_code) + assert_translation(ex_ast, js_code) end @@ -34,10 +34,10 @@ defmodule ElixirScript.Translator.Kernel.Test do end js_code = """ - Elixir.Enum.reverse(1,2,3) + Elixir$ElixirScript$Kernel.apply(Enum,Elixir.Kernel.SpecialForms.atom('reverse'),Elixir.Kernel.SpecialForms.list(1,2,3)) """ - assert_translation(ex_ast, js_code) + assert_translation(ex_ast, js_code) end @@ -47,10 +47,10 @@ defmodule ElixirScript.Translator.Kernel.Test do end js_code = """ - Elixir.Kernel.SpecialForms.list(1,2,3)[0] + Elixir$ElixirScript$Kernel.hd(Elixir.Kernel.SpecialForms.list(1,2,3)) """ - assert_translation(ex_ast, js_code) + assert_translation(ex_ast, js_code) end @@ -60,10 +60,10 @@ defmodule ElixirScript.Translator.Kernel.Test do end js_code = """ - Elixir.Kernel.SpecialForms.list(1,2,3).slice(1) + Elixir$ElixirScript$Kernel.tl(Elixir.Kernel.SpecialForms.list(1,2,3)) """ - assert_translation(ex_ast, js_code) + assert_translation(ex_ast, js_code) end -end \ No newline at end of file +end diff --git a/test/translator/list_test.exs b/test/translator/list_test.exs index 14b84d56..3bf0c7a3 100644 --- a/test/translator/list_test.exs +++ b/test/translator/list_test.exs @@ -14,8 +14,8 @@ defmodule ElixirScript.Translator.List.Test do assert_translation(ex_ast, js_code) ex_ast = quote do: [:a, :b, :c] - js_code = "Elixir.Kernel.SpecialForms.list(Elixir.Kernel.SpecialForms.atom('a'), Elixir.Kernel.SpecialForms.atom('b'), Elixir.Kernel.SpecialForms.atom('c'))" - + js_code = "Elixir.Kernel.SpecialForms.list(Elixir.Kernel.SpecialForms.atom('a'), Elixir.Kernel.SpecialForms.atom('b'), Elixir.Kernel.SpecialForms.atom('c'))" + assert_translation(ex_ast, js_code) ex_ast = quote do: [:a, 2, "c"] @@ -26,22 +26,22 @@ defmodule ElixirScript.Translator.List.Test do should "concatenate lists" do ex_ast = quote do: [1, 2, 3] ++ [4, 5, 6] - js_code = "Elixir.Kernel.SpecialForms.list(1,2,3).concat(Elixir.Kernel.SpecialForms.list(4,5,6))" + js_code = "Elixir.Core.concat_lists(Elixir.Kernel.SpecialForms.list(1,2,3),Elixir.Kernel.SpecialForms.list(4,5,6))" assert_translation(ex_ast, js_code) ex_ast = quote do: this.list ++ [4, 5, 6] - js_code = "Elixir.Core.call_property(this,'list').concat(Elixir.Kernel.SpecialForms.list(4,5,6))" + js_code = "Elixir.Core.concat_lists(Elixir.Core.call_property(this,'list'),Elixir.Kernel.SpecialForms.list(4,5,6))" - assert_translation(ex_ast, js_code) + assert_translation(ex_ast, js_code) end should "prepend element" do ex_ast = quote do: [x|list] - js_code = "Elixir.List.prepend(list, x)" + js_code = "Elixir.Core.prepend_to_list(list,x)" - assert_translation(ex_ast, js_code) + assert_translation(ex_ast, js_code) end should "prepend element in function" do @@ -51,10 +51,10 @@ defmodule ElixirScript.Translator.List.Test do js_code = """ Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.wildcard()],function(){ - return Elixir.List.prepend(list, x); + return Elixir.Core.prepend_to_list(list,x); })) """ - assert_translation(ex_ast, js_code) + assert_translation(ex_ast, js_code) end -end \ No newline at end of file +end diff --git a/test/translator/protocol_test.exs b/test/translator/protocol_test.exs index 8159b778..52bf875f 100644 --- a/test/translator/protocol_test.exs +++ b/test/translator/protocol_test.exs @@ -2,49 +2,6 @@ defmodule ElixirScript.Translator.Protocol.Test do use ShouldI import ElixirScript.TestHelper - test "parse protocol spec" do - ex_ast = quote do - defprotocol ElixirScript.Collectable do - def into(collectable) - end - end - - js_code = """ - const __MODULE__ = Elixir.Kernel.SpecialForms.atom('Elixir.ElixirScript.Collectable'); - - let Elixir$ElixirScript$Collectable = Elixir.Kernel.defprotocol({ - into: Elixir.Core.Patterns.defmatch( - Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable()], function(collectable){ - return null; - }) - ) - }); - - export default Elixir$ElixirScript$Collectable; - """ - - assert_translation(ex_ast, js_code) - end - - test "translate standard lib protocol defimpl" do - ex_ast = quote do - defimpl String.Chars, for: Duck do - def to_string(duck), do: "quack" - end - end - - js_code = """ - Elixir.Kernel.defimpl(Elixir.String.Chars, Duck, { - to_string: Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable()],function(duck) { - return 'quack'; - })) - }) - """ - - assert_translation(ex_ast, js_code) - end - - test "parse protocol spec with implementations" do ex_ast = quote do defprotocol Blank do @@ -68,8 +25,8 @@ defmodule ElixirScript.Translator.Protocol.Test do end js_code = """ - const __MODULE__ = Elixir.Kernel.SpecialForms.atom('Elixir.Blank'); - let Elixir$Blank = Elixir.Kernel.defprotocol({ + import * as Elixir$ElixirScript$Kernel from 'Elixir.ElixirScript.Kernel'; + const Elixir$Blank = Elixir.Kernel.defprotocol({ blank__qmark__: Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable()],function(data) { return null; })) diff --git a/test/translator/quote_test.exs b/test/translator/quote_test.exs index cc5f67b9..916af085 100644 --- a/test/translator/quote_test.exs +++ b/test/translator/quote_test.exs @@ -50,8 +50,8 @@ defmodule ElixirScript.Translator.Quote.Test do quote do: test(1) end - js_code = "Elixir.Kernel.SpecialForms.tuple(Elixir.Kernel.SpecialForms.atom('test'), - Elixir.Kernel.SpecialForms.list(Elixir.Kernel.SpecialForms.tuple(Elixir.Kernel.SpecialForms.atom('context'),Elixir.Kernel.SpecialForms.atom('Elixir.ElixirScript.Translator.Quote.Test')),Elixir.Kernel.SpecialForms.tuple(Elixir.Kernel.SpecialForms.atom('import'),Elixir.Kernel.SpecialForms.atom('Elixir.ExUnit.Case'))), + js_code = "Elixir.Kernel.SpecialForms.tuple(Elixir.Kernel.SpecialForms.atom('test'), + Elixir.Kernel.SpecialForms.list(Elixir.Kernel.SpecialForms.tuple(Elixir.Kernel.SpecialForms.atom('context'),Elixir.Kernel.SpecialForms.atom('Elixir.ElixirScript.Translator.Quote.Test')),Elixir.Kernel.SpecialForms.tuple(Elixir.Kernel.SpecialForms.atom('import'),Elixir.Kernel.SpecialForms.atom('Elixir.ExUnit.Case'))), Elixir.Kernel.SpecialForms.list(1))" assert_translation(ex_ast, js_code) @@ -79,7 +79,7 @@ defmodule ElixirScript.Translator.Quote.Test do end js_code = "Elixir.Kernel.SpecialForms.tuple( - Elixir.Kernel.SpecialForms.atom('test'), + Elixir.Kernel.SpecialForms.atom('test'), Elixir.Kernel.SpecialForms.list(Elixir.Kernel.SpecialForms.tuple(Elixir.Kernel.SpecialForms.atom('context'),Elixir.Kernel.SpecialForms.atom('Elixir.ElixirScript.Translator.Quote.Test')),Elixir.Kernel.SpecialForms.tuple(Elixir.Kernel.SpecialForms.atom('import'),Elixir.Kernel.SpecialForms.atom('Elixir.ExUnit.Case'))), Elixir.Kernel.SpecialForms.list(x) )" @@ -107,10 +107,10 @@ defmodule ElixirScript.Translator.Quote.Test do js_code = "Elixir.Kernel.SpecialForms.tuple( Elixir.Kernel.SpecialForms.atom('*'), - Elixir.Kernel.SpecialForms.list(Elixir.Kernel.SpecialForms.tuple(Elixir.Kernel.SpecialForms.atom('context'),Elixir.Kernel.SpecialForms.atom('Elixir.ElixirScript.Translator.Quote.Test')),Elixir.Kernel.SpecialForms.tuple(Elixir.Kernel.SpecialForms.atom('import'),Elixir.Kernel.SpecialForms.atom('Elixir.Kernel'))), + Elixir.Kernel.SpecialForms.list(Elixir.Kernel.SpecialForms.tuple(Elixir.Kernel.SpecialForms.atom('context'),Elixir.Kernel.SpecialForms.atom('Elixir.ElixirScript.Translator.Quote.Test')),Elixir.Kernel.SpecialForms.tuple(Elixir.Kernel.SpecialForms.atom('import'),Elixir.Kernel.SpecialForms.atom('Elixir.ElixirScript.Kernel'))), Elixir.Kernel.SpecialForms.list(x, x) )" - assert_translation(ex_ast, js_code) + assert_translation(ex_ast, js_code) end -end \ No newline at end of file +end diff --git a/test/translator/receive_test.exs b/test/translator/receive_test.exs deleted file mode 100644 index 868eed33..00000000 --- a/test/translator/receive_test.exs +++ /dev/null @@ -1,63 +0,0 @@ -defmodule ElixirScript.Translator.Receive.Test do - use ShouldI - import ElixirScript.TestHelper - - should "translate receive without after" do - ex_ast = quote do - receive do - :ok -> - value - :error -> - value - _ -> - IO.puts "Unexpected message received" - end - end - - js_code = """ - yield self.system.receive(function(message) { - return Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Kernel.SpecialForms.atom('ok')],function() { - return value; - }),Elixir.Core.Patterns.make_case([Elixir.Kernel.SpecialForms.atom('error')],function() { - return value; - }),Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.wildcard()],function() { - return IO.puts('Unexpected message received'); - })).call(this,message); - }) - """ - - assert_translation(ex_ast, js_code) - end - - should "translate receive with after" do - ex_ast = quote do - receive do - :ok -> - value - :error -> - value - _ -> - IO.puts "Unexpected message received" - after - 5000 -> - IO.puts "No message in 5 seconds" - end - end - - js_code = """ - yield self.system.receive(function(message) { - return Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Kernel.SpecialForms.atom('ok')],function() { - return value; - }),Elixir.Core.Patterns.make_case([Elixir.Kernel.SpecialForms.atom('error')],function() { - return value; - }),Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.wildcard()],function() { - return IO.puts('Unexpected message received'); - })).call(this,message); - },5000,Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([5000],function() { - return IO.puts('No message in 5 seconds'); - }))) - """ - - assert_translation(ex_ast, js_code) - end -end \ No newline at end of file diff --git a/test/translator/string_test.exs b/test/translator/string_test.exs index d48ef6cd..491b1d8a 100644 --- a/test/translator/string_test.exs +++ b/test/translator/string_test.exs @@ -25,19 +25,19 @@ defmodule ElixirScript.Translator.String.Test do assert_translation(ex_ast, "'Hello ' + 'world'") ex_ast = quote do: "Hello #{length([])}" - assert_translation(ex_ast, "'Hello ' + Elixir.String.Chars.to_string(Elixir.Kernel.SpecialForms.list().length)") + assert_translation(ex_ast, "'Hello ' + Elixir$ElixirScript$String$Chars.to_string(Elixir$ElixirScript$Kernel.length(Elixir.Kernel.SpecialForms.list()))") end should "translate multiline string interpolation" do ex_ast = quote do: """ Hello #{length([])} """ - assert_translation(ex_ast, "'Hello ' + (Elixir.String.Chars.to_string(Elixir.Kernel.SpecialForms.list().length) + '\\n')") + assert_translation(ex_ast, "'Hello ' + (Elixir$ElixirScript$String$Chars.to_string(Elixir$ElixirScript$Kernel.length(Elixir.Kernel.SpecialForms.list())) + '\\n')") ex_ast = quote do: """ Hello #{length([])} How are you, #{length([])}? """ - assert_translation(ex_ast, "'Hello ' + (Elixir.String.Chars.to_string(Elixir.Kernel.SpecialForms.list().length) + ('\\nHow are you, ' + (Elixir.String.Chars.to_string(Elixir.Kernel.SpecialForms.list().length) + '?\\n')))") + assert_translation(ex_ast, "'Hello ' + (Elixir$ElixirScript$String$Chars.to_string(Elixir$ElixirScript$Kernel.length(Elixir.Kernel.SpecialForms.list())) + ('\\nHow are you, ' + (Elixir$ElixirScript$String$Chars.to_string(Elixir$ElixirScript$Kernel.length(Elixir.Kernel.SpecialForms.list())) + '?\\n')))") end -end \ No newline at end of file +end diff --git a/test/translator/struct_test.exs b/test/translator/struct_test.exs index 2a2c4d4b..e22ce6e9 100644 --- a/test/translator/struct_test.exs +++ b/test/translator/struct_test.exs @@ -10,16 +10,15 @@ defmodule ElixirScript.Translator.Struct.Test do end js_code = """ - const __MODULE__ = Elixir.Kernel.SpecialForms.atom('Elixir.User'); - - const defstruct = Elixir.Kernel.defstruct({ - [Elixir.Kernel.SpecialForms.atom('__struct__')]: __MODULE__, + import * as Elixir$ElixirScript$Kernel from 'Elixir.ElixirScript.Kernel'; + const Elixir$User = Elixir.Kernel.defstruct({ + [Elixir.Kernel.SpecialForms.atom('__struct__')]: Elixir.Kernel.SpecialForms.atom('Elixir.User'), [Elixir.Kernel.SpecialForms.atom('name')]: 'john', [Elixir.Kernel.SpecialForms.atom('age')]: 27 }); export { - Elixir$User: defstruct + Elixir$User }; """ @@ -35,14 +34,14 @@ defmodule ElixirScript.Translator.Struct.Test do end js_code = """ - const __MODULE__ = Elixir.Kernel.SpecialForms.atom('Elixir.User'); - const defstruct = Elixir.Kernel.defstruct({ - [Elixir.Kernel.SpecialForms.atom('__struct__')]: __MODULE__, + import * as Elixir$ElixirScript$Kernel from 'Elixir.ElixirScript.Kernel'; + const Elixir$User = Elixir.Kernel.defstruct({ + [Elixir.Kernel.SpecialForms.atom('__struct__')]: Elixir.Kernel.SpecialForms.atom('Elixir.User'), [Elixir.Kernel.SpecialForms.atom('name')]: null, [Elixir.Kernel.SpecialForms.atom('age')]: null }); export { - Elixir$User: defstruct + Elixir$User }; """ @@ -60,17 +59,18 @@ defmodule ElixirScript.Translator.Struct.Test do end js_code = """ - const __MODULE__ = Elixir.Kernel.SpecialForms.atom('Elixir.User'); - const defstruct = Elixir.Kernel.defstruct({ - [Elixir.Kernel.SpecialForms.atom('__struct__')]: __MODULE__, + let [user] = Elixir.Core.Patterns.match(Elixir.Core.Patterns.variable(), Elixir$User.Elixir$User.create(Elixir.Kernel.SpecialForms.map({}))); + + import * as Elixir$ElixirScript$Kernel from 'Elixir.ElixirScript.Kernel'; + const Elixir$User = Elixir.Kernel.defstruct({ + [Elixir.Kernel.SpecialForms.atom('__struct__')]: Elixir.Kernel.SpecialForms.atom('Elixir.User'), [Elixir.Kernel.SpecialForms.atom('name')]: null, [Elixir.Kernel.SpecialForms.atom('age')]: null }); + export { - Elixir$User: defstruct + Elixir$User }; - - let [user] = Elixir.Core.Patterns.match(Elixir.Core.Patterns.variable(), Elixir$User.Elixir$User.create(Elixir.Kernel.SpecialForms.map({}))); """ assert_translation(ex_ast, js_code) @@ -88,12 +88,14 @@ defmodule ElixirScript.Translator.Struct.Test do [Elixir.Kernel.SpecialForms.atom('name')]: 'John' }))); - const __MODULE__ = Elixir.Kernel.SpecialForms.atom('Elixir.User'); - const defstruct = Elixir.Kernel.defstruct({ - [Elixir.Kernel.SpecialForms.atom('__struct__')]: __MODULE__, [Elixir.Kernel.SpecialForms.atom('name')]: null, [Elixir.Kernel.SpecialForms.atom('age')]: null - }); + import * as Elixir$ElixirScript$Kernel from 'Elixir.ElixirScript.Kernel'; + const Elixir$User = Elixir.Kernel.defstruct({ + [Elixir.Kernel.SpecialForms.atom('__struct__')]: Elixir.Kernel.SpecialForms.atom('Elixir.User'), + [Elixir.Kernel.SpecialForms.atom('name')]: null, + [Elixir.Kernel.SpecialForms.atom('age')]: null + }); export { - Elixir$User: defstruct + Elixir$User }; """ @@ -135,14 +137,14 @@ defmodule ElixirScript.Translator.Struct.Test do end js_code = """ - const __MODULE__ = Elixir.Kernel.SpecialForms.atom('Elixir.MyAppError'); - const defexception = Elixir.Kernel.defexception({ - [Elixir.Kernel.SpecialForms.atom('__struct__')]: __MODULE__, + import * as Elixir$ElixirScript$Kernel from 'Elixir.ElixirScript.Kernel'; + const Elixir$MyAppError = Elixir.Kernel.defexception({ + [Elixir.Kernel.SpecialForms.atom('__struct__')]: Elixir.Kernel.SpecialForms.atom('Elixir.MyAppError'), [Elixir.Kernel.SpecialForms.atom('__exception__')]: true, [Elixir.Kernel.SpecialForms.atom('message')]: 'This is a message' }); export { - Elixir$MyAppError: defexception + Elixir$MyAppError }; """ @@ -155,15 +157,15 @@ defmodule ElixirScript.Translator.Struct.Test do end js_code = """ - const __MODULE__ = Elixir.Kernel.SpecialForms.atom('Elixir.MyAppError'); - const defexception = Elixir.Kernel.defexception({ - [Elixir.Kernel.SpecialForms.atom('__struct__')]: __MODULE__, + import * as Elixir$ElixirScript$Kernel from 'Elixir.ElixirScript.Kernel'; + const Elixir$MyAppError = Elixir.Kernel.defexception({ + [Elixir.Kernel.SpecialForms.atom('__struct__')]: Elixir.Kernel.SpecialForms.atom('Elixir.MyAppError'), [Elixir.Kernel.SpecialForms.atom('__exception__')]: true, [Elixir.Kernel.SpecialForms.atom('message')]: null }); export { - Elixir$MyAppError: defexception + Elixir$MyAppError }; """ @@ -173,11 +175,28 @@ defmodule ElixirScript.Translator.Struct.Test do should "translate raise exception" do ex_ast = quote do + defmodule MyAppError do + defexception [:message] + end + raise MyAppError, message: "did not get what was expected" end js_code = """ - throw MyAppError.defexception(message = 'did not get what was expected'); + throw Elixir$MyAppError.Elixir$MyAppError.create(Elixir.Kernel.SpecialForms.map({ + [Elixir.Kernel.SpecialForms.atom('message')]: 'did not get what was expected' + })); + +import * as Elixir$ElixirScript$Kernel from 'Elixir.ElixirScript.Kernel'; + const Elixir$MyAppError = Elixir.Kernel.defexception({ + [Elixir.Kernel.SpecialForms.atom('__struct__')]: Elixir.Kernel.SpecialForms.atom('Elixir.MyAppError'), + [Elixir.Kernel.SpecialForms.atom('__exception__')]: true, + [Elixir.Kernel.SpecialForms.atom('message')]: null + }); + + export { + Elixir$MyAppError + }; """ assert_translation(ex_ast, js_code) @@ -188,11 +207,11 @@ defmodule ElixirScript.Translator.Struct.Test do end js_code = """ - throw { + throw { [Elixir.Kernel.SpecialForms.atom('__struct__')]: Elixir.Kernel.SpecialForms.atom('RuntimeError'), [Elixir.Kernel.SpecialForms.atom('__exception__')]: true, [Elixir.Kernel.SpecialForms.atom('message')]: 'did not get what was expected' - }; + }; """ assert_translation(ex_ast, js_code) diff --git a/test/translator/try_test.exs b/test/translator/try_test.exs index 5c506248..edbe2733 100644 --- a/test/translator/try_test.exs +++ b/test/translator/try_test.exs @@ -60,7 +60,7 @@ defmodule ElixirScript.Translator.Try.Test do }, Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable()], function(x) { return IO.puts('Invalid argument given'); }, function(x) { - return Elixir.Kernel.in(x, Elixir.Kernel.SpecialForms.list(ArgumentError.create(Elixir.Kernel.SpecialForms.map({})))); + return Elixir.Core.contains(x,Elixir.Kernel.SpecialForms.list(ArgumentError.create(Elixir.Kernel.SpecialForms.map({})))); })), null, null, null) """ From 381bdebd95d90e0aa70a532a824be0ce144ab3ca Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Sun, 27 Dec 2015 20:29:10 -0600 Subject: [PATCH 093/860] Lots of refactoring to make the code simpler and cleaner --- CHANGELOG.md | 3 + GettingStarted.md | 6 +- lib/elixir_script.ex | 98 +- lib/elixir_script/cli.ex | 8 +- lib/elixir_script/module.ex | 63 - lib/elixir_script/pattern_matching/match.ex | 4 +- lib/elixir_script/prelude/agent.ex | 43 + .../{universal => prelude}/atom.ex | 0 lib/elixir_script/prelude/base.ex | 19 + .../{universal => prelude}/collectable.ex | 0 .../{universal => prelude}/enumerable.ex | 0 lib/elixir_script/prelude/integer.ex | 33 + .../{universal => prelude}/kernel.ex | 48 +- .../{universal => prelude}/macro/env.ex | 0 lib/elixir_script/prelude/module.ex | 10 + lib/elixir_script/prelude/range.ex | 11 + lib/elixir_script/prelude/string.ex | 189 +++ .../{universal => prelude}/string/chars.ex | 0 .../{universal => prelude}/tuple.ex | 8 +- .../{universal => prelude}/view.ex | 16 +- lib/elixir_script/preprocess/modules.ex | 78 +- lib/elixir_script/preprocess/using.ex | 24 - lib/elixir_script/translator.ex | 79 +- lib/elixir_script/translator/assignment.ex | 15 +- lib/elixir_script/{ => translator}/env.ex | 37 +- lib/elixir_script/translator/function.ex | 23 +- lib/elixir_script/translator/import.ex | 38 +- lib/elixir_script/translator/js_module.ex | 4 - lib/elixir_script/translator/module.ex | 76 +- lib/elixir_script/translator/primitive.ex | 64 +- lib/elixir_script/translator/protocol.ex | 63 +- lib/elixir_script/{ => translator}/state.ex | 84 +- lib/elixir_script/translator/struct.ex | 19 +- .../translator/unsupported_error.ex | 8 + lib/elixir_script/translator/utils.ex | 29 + lib/elixir_script/universal/integer.ex | 19 - lib/elixir_script/unsupported_error.ex | 8 - priv/Elixir.js | 1053 ++++------------- src/javascript/elixir.js | 12 - src/javascript/lib/agent.js | 42 - src/javascript/lib/atom.js | 11 - src/javascript/lib/base.js | 33 - src/javascript/lib/collectable.js | 8 - src/javascript/lib/core.js | 68 +- src/javascript/lib/core/functions.js | 86 +- src/javascript/lib/core/primitives.js | 6 +- .../lib/core/{ => processes}/mailbox.js | 0 .../lib/core/{ => processes}/process.js | 0 .../core/{ => processes}/process_system.js | 2 +- .../lib/core/{ => processes}/states.js | 0 src/javascript/lib/{ => core}/protocol.js | 6 +- src/javascript/lib/enum.js | 17 +- src/javascript/lib/enumerable.js | 9 - src/javascript/lib/inspect.js | 7 - src/javascript/lib/integer.js | 38 - src/javascript/lib/kernel.js | 54 +- src/javascript/lib/kernel/special_forms.js | 12 - src/javascript/lib/keyword.js | 4 +- src/javascript/lib/list.js | 42 +- src/javascript/lib/list/chars.js | 40 - src/javascript/lib/map.js | 43 +- src/javascript/lib/map_set.js | 15 +- src/javascript/lib/range.js | 44 - src/javascript/lib/set.js | 60 - src/javascript/lib/string.js | 195 --- src/javascript/lib/string/chars.js | 63 - src/javascript/lib/tuple.js | 66 -- src/javascript/lib/view.js | 51 - src/javascript/tests/atom.spec.js | 26 - src/javascript/tests/case.spec.js | 2 +- src/javascript/tests/integer.spec.js | 34 - src/javascript/tests/kernel.spec.js | 4 +- src/javascript/tests/list.spec.js | 6 +- src/javascript/tests/range.spec.js | 16 - src/javascript/tests/string.chars.spec.js | 14 - src/javascript/tests/try.spec.js | 6 +- src/javascript/tests/tuple.spec.js | 54 - test/elixir_script_test.exs | 38 +- test/lib/js_test.exs | 2 +- test/lib/kernel_test.exs | 7 +- test/pattern_matching/match_test.exs | 60 +- test/test_helper.exs | 2 +- test/translator/access_test.exs | 2 +- test/translator/assignment_test.exs | 22 +- test/translator/atom_test.exs | 4 +- test/translator/bug_test.exs | 22 +- test/translator/capture_test.exs | 4 +- test/translator/case_test.exs | 30 +- test/translator/cond_test.exs | 12 +- test/translator/defmodule_test.exs | 68 +- test/translator/for_test.exs | 38 +- test/translator/function_test.exs | 42 +- test/translator/kernel_test.exs | 8 +- test/translator/list_test.exs | 12 +- test/translator/map_test.exs | 10 +- test/translator/protocol_test.exs | 12 +- test/translator/quote_test.exs | 38 +- test/translator/string_test.exs | 6 +- test/translator/struct_test.exs | 84 +- test/translator/try_test.exs | 8 +- test/translator/tuple_test.exs | 10 +- 101 files changed, 1376 insertions(+), 2641 deletions(-) delete mode 100644 lib/elixir_script/module.ex create mode 100644 lib/elixir_script/prelude/agent.ex rename lib/elixir_script/{universal => prelude}/atom.ex (100%) create mode 100644 lib/elixir_script/prelude/base.ex rename lib/elixir_script/{universal => prelude}/collectable.ex (100%) rename lib/elixir_script/{universal => prelude}/enumerable.ex (100%) create mode 100644 lib/elixir_script/prelude/integer.ex rename lib/elixir_script/{universal => prelude}/kernel.ex (70%) rename lib/elixir_script/{universal => prelude}/macro/env.ex (100%) create mode 100644 lib/elixir_script/prelude/module.ex create mode 100644 lib/elixir_script/prelude/range.ex create mode 100644 lib/elixir_script/prelude/string.ex rename lib/elixir_script/{universal => prelude}/string/chars.ex (100%) rename lib/elixir_script/{universal => prelude}/tuple.ex (52%) rename lib/elixir_script/{universal => prelude}/view.ex (67%) delete mode 100644 lib/elixir_script/preprocess/using.ex rename lib/elixir_script/{ => translator}/env.ex (71%) delete mode 100644 lib/elixir_script/translator/js_module.ex rename lib/elixir_script/{ => translator}/state.ex (64%) create mode 100644 lib/elixir_script/translator/unsupported_error.ex delete mode 100644 lib/elixir_script/universal/integer.ex delete mode 100644 lib/elixir_script/unsupported_error.ex delete mode 100644 src/javascript/lib/agent.js delete mode 100644 src/javascript/lib/atom.js delete mode 100644 src/javascript/lib/base.js delete mode 100644 src/javascript/lib/collectable.js rename src/javascript/lib/core/{ => processes}/mailbox.js (100%) rename src/javascript/lib/core/{ => processes}/process.js (100%) rename src/javascript/lib/core/{ => processes}/process_system.js (98%) rename src/javascript/lib/core/{ => processes}/states.js (100%) rename src/javascript/lib/{ => core}/protocol.js (88%) delete mode 100644 src/javascript/lib/enumerable.js delete mode 100644 src/javascript/lib/inspect.js delete mode 100644 src/javascript/lib/integer.js delete mode 100644 src/javascript/lib/list/chars.js delete mode 100644 src/javascript/lib/range.js delete mode 100644 src/javascript/lib/set.js delete mode 100644 src/javascript/lib/string.js delete mode 100644 src/javascript/lib/string/chars.js delete mode 100644 src/javascript/lib/tuple.js delete mode 100644 src/javascript/lib/view.js delete mode 100644 src/javascript/tests/atom.spec.js delete mode 100644 src/javascript/tests/integer.spec.js delete mode 100644 src/javascript/tests/range.spec.js delete mode 100644 src/javascript/tests/string.chars.spec.js delete mode 100644 src/javascript/tests/tuple.spec.js diff --git a/CHANGELOG.md b/CHANGELOG.md index af24a172..6ec0de54 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,9 @@ * `__ENV__` and `__CALLER__` are now supported * Began writing some of the standard libraries in Elixir instead of JavaScript +* Breaking + * `compile`, `compile_path`, and `compile_quoted` opts parameter now expects a map + # v0.14.1 * Enhancements * Removed .DS_Store and LICENSE from output diff --git a/GettingStarted.md b/GettingStarted.md index 263d3058..066e3934 100644 --- a/GettingStarted.md +++ b/GettingStarted.md @@ -44,16 +44,16 @@ The intent of this guide is to get you started with ElixirScript. It will give y ```bash $ elixirscript ":atom" -ex - Kernel.SpecialForms.atom('atom') + Symbol.for('atom') ``` - The elixirscript escript changed the elixir code, `:atom` into the JavaScript code `Kernel.SpecialForms.atom('atom')`. The `-ex` parameter lets the script know that the input is an Elixir code string instead of a file. + The elixirscript escript changed the elixir code, `:atom` into the JavaScript code `Symbol.for('atom')`. The `-ex` parameter lets the script know that the input is an Elixir code string instead of a file. What if we wanted to give it a file? You would simply do the following: ```bash $ elixirscript "example.exjs" - Kernel.SpecialForms.atom('atom') + Symbol.for('atom') ``` What you will have noticed by now is that it has output everything we've done so far to the terminal. What about if we want to place the output to a path? The next example takes a file as input and outputs the result in another directory. diff --git a/lib/elixir_script.ex b/lib/elixir_script.ex index 05b1b028..bf080df5 100644 --- a/lib/elixir_script.ex +++ b/lib/elixir_script.ex @@ -1,7 +1,7 @@ defmodule ElixirScript do - alias ElixirScript.Translator.JSModule alias ESTree.Tools.Builder alias ESTree.Tools.Generator + alias ElixirScript.Translator.Utils @moduledoc """ Translates Elixir into JavaScript. @@ -32,7 +32,7 @@ defmodule ElixirScript do end end - @external_resource libs_path = Path.join([__DIR__, "elixir_script", "universal", "**", "*.ex"]) + @external_resource libs_path = Path.join([__DIR__, "elixir_script", "prelude", "**", "*.ex"]) @libs (for path <- Path.wildcard(libs_path) do path |> File.read! @@ -42,8 +42,8 @@ defmodule ElixirScript do @doc """ Compiles the given Elixir code string """ - @spec compile(binary, Dict.t) :: [binary | {binary, binary}] - def compile(elixir_code, opts \\ []) do + @spec compile(binary, Map.t) :: [binary | {binary, binary}] + def compile(elixir_code, opts \\ %{}) do elixir_code |> Code.string_to_quoted! |> compile_quoted(opts) @@ -52,34 +52,27 @@ defmodule ElixirScript do @doc """ Compiles the given Elixir code in quoted form """ - @spec compile_quoted(Macro.t, Dict.t) :: [binary | {binary, binary}] - def compile_quoted(quoted, opts \\ []) do - include_path = Dict.get(opts, :include_path, false) - root = Dict.get(opts, :root) - env = Dict.get(opts, :env, custom_env) - import_standard_libs? = Dict.get(opts, :import_standard_libs, true) - stdlib_path = Dict.get(opts, :stdlib_path, "Elixir") + @spec compile_quoted(Macro.t, Map.t) :: [binary | {binary, binary}] + def compile_quoted(quoted, opts \\ %{}) do - ElixirScript.State.start_link(root, env) + compiler_opts = build_compiler_options(opts) + ElixirScript.Translator.State.start_link(compiler_opts) libs = @libs |> updated_quoted build_environment(libs ++ [updated_quoted(quoted)]) - create_code(include_path, import_standard_libs?, stdlib_path) + create_code(compiler_opts) end @doc """ Compiles the elixir files found at the given path """ - @spec compile_path(binary, Dict.t) :: [binary | {binary, binary}] - def compile_path(path, opts \\ []) do - include_path = Dict.get(opts, :include_path, false) - root = Dict.get(opts, :root) - env = Dict.get(opts, :env, custom_env) - stdlib_path = Dict.get(opts, :stdlib_path, "Elixir") + @spec compile_path(binary, Map.t) :: [binary | {binary, binary}] + def compile_path(path, opts \\ %{}) do - ElixirScript.State.start_link(root, env) + compiler_opts = build_compiler_options(opts) + ElixirScript.Translator.State.start_link(compiler_opts) libs = @libs |> updated_quoted @@ -90,7 +83,18 @@ defmodule ElixirScript do build_environment(libs ++ code) - create_code(include_path, true, stdlib_path) + create_code(compiler_opts) + end + + defp build_compiler_options(opts) do + default_options = Map.new + |> Map.put(:include_path, false) + |> Map.put(:root, nil) + |> Map.put(:env, custom_env) + |> Map.put(:import_standard_libs, true) + |> Map.put(:stdlib_path, "Elixir") + + Map.merge(default_options, opts) end defp file_to_quoted(file) do @@ -102,7 +106,7 @@ defmodule ElixirScript do defp build_environment(code_list) do code_list - |> ElixirScript.Preprocess.Modules.get_info + |> ElixirScript.Preprocess.Modules.process_modules end defp updated_quoted(quoted) do @@ -123,20 +127,20 @@ defmodule ElixirScript do __ENV__ end - defp create_code(include_path, import_standard_libs?, stdlib_path) do + defp create_code(compiler_opts) do - standard_lib_modules = ElixirScript.Module.build_standard_lib_map() - |> Map.values + state = ElixirScript.Translator.State.get - state = ElixirScript.State.get + standard_lib_modules = state.std_lib_map + |> Map.values result = Map.values(state.modules) |> Enum.reject(fn(ast) -> - import_standard_libs? == false && ast.name in standard_lib_modules + compiler_opts.import_standard_libs == false && ast.name in standard_lib_modules end) |> Enum.map(fn ast -> - env = ElixirScript.Env.module_env(ast.name, "#{create_file_name(ast.name)}") + env = ElixirScript.Translator.Env.module_env(ast.name, Utils.name_to_js_file_name(ast.name) <> ".js") case ast.type do :module -> @@ -144,14 +148,14 @@ defmodule ElixirScript do :protocol -> ElixirScript.Translator.Protocol.consolidate(ast, env) end - |> convert_to_code(state.root, state.elixir_env, import_standard_libs?, stdlib_path) + |> convert_to_code() end) - ElixirScript.State.stop + ElixirScript.Translator.State.stop result |> Enum.map(fn({path, code}) -> - if(include_path) do + if(compiler_opts.include_path) do { path, code } else code @@ -174,37 +178,15 @@ defmodule ElixirScript do File.read!(operating_path <> "/Elixir.js") end - defp convert_to_code(js_ast, root, env, import_standard_libs, stdlib_path) do - js_ast - |> process_module(root, env, import_standard_libs, stdlib_path) + defp convert_to_code(js_ast) do + process_module(js_ast) |> javascript_ast_to_code end - defp process_module(%JSModule{} = module, root, _, import_standard_libs, stdlib_path) do - file_path = create_file_name(module) - - standard_libs_import = - if import_standard_libs do - ElixirScript.Translator.Import.create_standard_lib_imports(root, stdlib_path) - else - [] - end - - program = - standard_libs_import ++ module.body - |> ESTree.Tools.Builder.program - - {file_path, program} - end - - defp create_file_name(%JSModule{name: module}) do - name = ElixirScript.Module.name_to_js_file_name(module) - "#{name}.js" - end + defp process_module(module) do + file_path = Utils.name_to_js_file_name(module.name) <> ".js" - defp create_file_name(name) do - name = ElixirScript.Module.name_to_js_file_name(name) - "#{name}.js" + { file_path, ESTree.Tools.Builder.program(module.body) } end @doc false diff --git a/lib/elixir_script/cli.ex b/lib/elixir_script/cli.ex index 3323cbfa..400469aa 100644 --- a/lib/elixir_script/cli.ex +++ b/lib/elixir_script/cli.ex @@ -57,11 +57,11 @@ defmodule ElixirScript.CLI do end def do_process(input, options) do - compile_opts = [ + compile_opts = %{ root: options[:root], include_path: options[:output] != nil, - stdlib_path: Dict.get(options, :stdlib_path, "Elixir") - ] + stdlib_path: Keyword.get(options, :stdlib_path, "Elixir") + } compile_output = case options[:elixir] do true -> @@ -82,7 +82,7 @@ defmodule ElixirScript.CLI do write_to_file(x, output_path) end) - if Dict.get(options, :stdlib_path) == nil do + if options[:stdlib_path] == nil do ElixirScript.copy_standard_libs_to_destination(output_path) end end diff --git a/lib/elixir_script/module.ex b/lib/elixir_script/module.ex deleted file mode 100644 index 781631a6..00000000 --- a/lib/elixir_script/module.ex +++ /dev/null @@ -1,63 +0,0 @@ -defmodule ElixirScript.Module do - @moduledoc false - - defstruct name: nil, - functions: Keyword.new, private_functions: Keyword.new, - macros: Keyword.new, private_macros: Keyword.new, - body: nil, js_imports: [], module_refs: [], type: :module, - spec: nil, impls: HashDict.new - - - def quoted_to_name(the_alias) do - {name, _} = Code.eval_quoted(the_alias) - name - end - - def name_to_quoted(name) do - name = name - |> Atom.to_string - |> String.split(".") - |> tl - |> Enum.map(fn x -> String.to_atom(x) end) - - { :__aliases__, [], name } - end - - def name_to_js_name(name) do - { :__aliases__, _, name } = name_to_quoted(name) - Enum.join([:Elixir] ++ name, "$") - end - - def name_to_js_file_name(name) do - { :__aliases__, _, name } = name_to_quoted(name) - Enum.join([:Elixir] ++ name, ".") - end - - def has_function?(module_name, name_arity) do - module = ElixirScript.State.get_module(module_name) - name_arity in module.functions or name_arity in module.private_functions - end - - def build_standard_lib_map() do - Map.new - |> Map.put(Kernel, ElixirScript.Kernel) - |> Map.put(Tuple, ElixirScript.Tuple) - |> Map.put(Atom, ElixirScript.Atom) - |> Map.put(Collectable, ElixirScript.Collectable) - |> Map.put(String.Chars, ElixirScript.String.Chars) - |> Map.put(Enumerable, ElixirScript.Enumerable) - |> Map.put(Integer, ElixirScript.Integer) - |> Map.put(Macro.Env, ElixirScript.Macro.Env) - |> Map.put(View, ElixirScript.View) - end - - def get_module_name(module_name) do - case Map.get(build_standard_lib_map, module_name) do - nil -> - module_name - actual_module_name -> - actual_module_name - end - end - -end diff --git a/lib/elixir_script/pattern_matching/match.ex b/lib/elixir_script/pattern_matching/match.ex index af0f7e3a..bdddc737 100644 --- a/lib/elixir_script/pattern_matching/match.ex +++ b/lib/elixir_script/pattern_matching/match.ex @@ -112,8 +112,8 @@ defmodule ElixirScript.PatternMatching.Match do { param, env } (%ESTree.Identifier{} = param, env) -> - env = ElixirScript.Env.add_var(env, param.name) - new_name = ElixirScript.Env.get_var(env, param.name) + env = ElixirScript.Translator.Env.add_var(env, param.name) + new_name = ElixirScript.Translator.Env.get_var(env, param.name) { %{ param | name: new_name }, env } diff --git a/lib/elixir_script/prelude/agent.ex b/lib/elixir_script/prelude/agent.ex new file mode 100644 index 00000000..096eb678 --- /dev/null +++ b/lib/elixir_script/prelude/agent.ex @@ -0,0 +1,43 @@ +defmodule ElixirScript.Agent do + + def start(fun) do + pid = Elixir.Core.Functions.get_global().processes.spawn() + Elixir.Core.Functions.get_global().processes.put(pid, "state", fun.()); + { :ok, pid } + end + + def start(fun, options) do + pid = Elixir.Core.Functions.get_global().processes.spawn() + + if Elixir.Keyword.has_key?(options, :name) do + pid = Elixir.Core.Functions.get_global().processes.register(Elixir.Keyword.get(options, :name), pid) + end + + Elixir.Core.Functions.get_global().processes.put(pid, "state", fun.()) + { :ok, pid } + end + + def stop(view) do + Elixir.Core.Functions.get_global().processes.exit(view) + :ok + end + + def update(agent, fun) do + current_state = Elixir.Core.Functions.get_global().processes.get(agent, "state") + Elixir.Core.Functions.get_global().processes.put(agent, "state", fun.(current_state)); + :ok + end + + def get(agent, fun) do + current_state = Elixir.Core.Functions.get_global().processes.get(agent, "state") + fun.(current_state) + end + + def get_and_update(agent, fun) do + current_state = Elixir.Core.Functions.get_global().processes.get(agent, "state") + {val, new_state} = fun.(current_state) + Elixir.Core.Functions.get_global().processes.put(agent, "state", new_state); + val + end + +end diff --git a/lib/elixir_script/universal/atom.ex b/lib/elixir_script/prelude/atom.ex similarity index 100% rename from lib/elixir_script/universal/atom.ex rename to lib/elixir_script/prelude/atom.ex diff --git a/lib/elixir_script/prelude/base.ex b/lib/elixir_script/prelude/base.ex new file mode 100644 index 00000000..0ec26036 --- /dev/null +++ b/lib/elixir_script/prelude/base.ex @@ -0,0 +1,19 @@ +defmodule ElixirScript.Base do + + def encode64(data) do + Elixir.Core.b64EncodeUnicode(data) + end + + def decode64(data) do + if Elixir.Core.can_decode64(data) do + {:ok, decode64!(data) } + else + :error + end + end + + def decode64!(data) do + Elixir.Core.get_global().atob(data) + end + +end diff --git a/lib/elixir_script/universal/collectable.ex b/lib/elixir_script/prelude/collectable.ex similarity index 100% rename from lib/elixir_script/universal/collectable.ex rename to lib/elixir_script/prelude/collectable.ex diff --git a/lib/elixir_script/universal/enumerable.ex b/lib/elixir_script/prelude/enumerable.ex similarity index 100% rename from lib/elixir_script/universal/enumerable.ex rename to lib/elixir_script/prelude/enumerable.ex diff --git a/lib/elixir_script/prelude/integer.ex b/lib/elixir_script/prelude/integer.ex new file mode 100644 index 00000000..97c7a7ed --- /dev/null +++ b/lib/elixir_script/prelude/integer.ex @@ -0,0 +1,33 @@ +defmodule ElixirScript.Integer do + + def is_even(number) do + rem(number, 2) == 0 + end + + def is_odd(number) do + rem(number, 2) != 0 + end + + def to_char_list(number) do + to_char_list(number, 10) + end + + def to_char_list(number, base) do + number.toString(base).split('') + end + + def parse(bin) do + result = Elixir.Core.Functions.get_global().parseInt(bin) + + if Elixir.Core.Functions.get_global().isNaN(result) do + :error + else + case bin.indexOf(".") do + index_of_dot when index_of_dot < 0 -> + {result, ""} + index_of_dot -> + {result, bin.substring(index_of_dot)} + end + end + end +end diff --git a/lib/elixir_script/universal/kernel.ex b/lib/elixir_script/prelude/kernel.ex similarity index 70% rename from lib/elixir_script/universal/kernel.ex rename to lib/elixir_script/prelude/kernel.ex index 67cc02cd..0940b3a2 100644 --- a/lib/elixir_script/universal/kernel.ex +++ b/lib/elixir_script/prelude/kernel.ex @@ -40,12 +40,12 @@ defmodule ElixirScript.Kernel do end def apply(fun, args) do - Elixir.Core.apply(fun, args) + Elixir.Core.Functions.apply(fun, args) end def apply(module, fun, args) do fun = if Elixir.Core.is_atom(fun), do: Atom.to_string(fun), else: fun - Elixir.Core.apply(module, fun, args) + Elixir.Core.Functions.apply(module, fun, args) end def binary_part(binary, start, len) do @@ -61,63 +61,63 @@ defmodule ElixirScript.Kernel do end def is_atom(term) do - Elixir.Core.is_atom(term) + Elixir.Core.Functions.is_atom(term) end def is_binary(term) do - Elixir.Core.is_binary(term) + Elixir.Core.Functions.is_binary(term) end def is_bitstring(term) do - Elixir.Core.is_bitstring(term) + Elixir.Core.Functions.is_bitstring(term) end def is_boolean(term) do - Elixir.Core.is_boolean(term) + Elixir.Core.Functions.is_boolean(term) end def is_float(term) do - Elixir.Core.is_float(term) + Elixir.Core.Functions.is_float(term) end def is_function(term) do - Elixir.Core.is_function(term) + Elixir.Core.Functions.is_function(term) end def is_function(term, arity) do - Elixir.Core.is_function(term, arity) + Elixir.Core.Functions.is_function(term, arity) end def is_integer(term) do - Elixir.Core.is_integer(term) + Elixir.Core.Functions.is_integer(term) end def is_list(term) do - Elixir.Core.is_list(term) + Elixir.Core.Functions.is_list(term) end def is_number(term) do - Elixir.Core.is_integer(term) || Elixir.Core.is_float(term) + Elixir.Core.Functions.is_integer(term) || Elixir.Core.Functions.is_float(term) end def is_pid(term) do - Elixir.Core.is_pid(term) + Elixir.Core.Functions.is_pid(term) end def is_tuple(term) do - Elixir.Core.is_tuple(term) + Elixir.Core.Functions.is_tuple(term) end def is_map(term) do - Elixir.Core.is_map(term) + Elixir.Core.Functions.is_map(term) end def length(term) do - Elixir.Core.size(term) + Elixir.Core.Functions.size(term) end def map_size(term) do - Elixir.Core.size(Object.keys(term)) + Elixir.Core.Functions.size(Object.keys(term)) end def max(first, second) do @@ -137,15 +137,15 @@ defmodule ElixirScript.Kernel do end def tuple_size(tuple) do - Elixir.Core.size(tuple) + Elixir.Core.Functions.size(tuple) end def elem(tuple, index) do - Elixir.Core.apply(tuple, "get", [index]) + Elixir.Core.Functions.apply(tuple, "get", [index]) end def is_nil(term) do - Elixir.Core.is_nil(term) + Elixir.Core.Functions.is_nil(term) end defmacro match?(left, right) do @@ -175,7 +175,13 @@ defmodule ElixirScript.Kernel do defmacro left in right do quote do - Elixir.Core.contains(unquote(left), unquote(right)) + Elixir.Core.Functions.contains(unquote(left), unquote(right)) + end + end + + defmacro first .. last do + quote do + %ElixirScript.Range{ first: unquote(first), last: unquote(last) } end end end diff --git a/lib/elixir_script/universal/macro/env.ex b/lib/elixir_script/prelude/macro/env.ex similarity index 100% rename from lib/elixir_script/universal/macro/env.ex rename to lib/elixir_script/prelude/macro/env.ex diff --git a/lib/elixir_script/prelude/module.ex b/lib/elixir_script/prelude/module.ex new file mode 100644 index 00000000..dc32959a --- /dev/null +++ b/lib/elixir_script/prelude/module.ex @@ -0,0 +1,10 @@ +defmodule ElixirScript.Module do + @moduledoc false + + defstruct name: nil, + functions: Keyword.new, private_functions: Keyword.new, + macros: Keyword.new, private_macros: Keyword.new, + body: nil, js_imports: [], module_refs: [], type: :module, + spec: nil, impls: HashDict.new + +end diff --git a/lib/elixir_script/prelude/range.ex b/lib/elixir_script/prelude/range.ex new file mode 100644 index 00000000..5e64017a --- /dev/null +++ b/lib/elixir_script/prelude/range.ex @@ -0,0 +1,11 @@ +defmodule ElixirScript.Range do + defstruct first: nil, last: nil + + def new(first, last) do + %ElixirScript.Range{first: first, last: last} + end + + def range?(%ElixirScript.Range{}), do: true + def range?(_), do: false + +end diff --git a/lib/elixir_script/prelude/string.ex b/lib/elixir_script/prelude/string.ex new file mode 100644 index 00000000..8ce8ebe2 --- /dev/null +++ b/lib/elixir_script/prelude/string.ex @@ -0,0 +1,189 @@ +defmodule ElixirScript.String do + import Kernel, except: [length: 1] + + def to_atom(str) do + Symbol.for(str) + end + + def to_existing_atom(str) do + Symbol.for(str) + end + + def to_char_list(str) do + str.split("") + end + + def to_float(str) do + Elixir.Core.get_global().parseFloat(str) + end + + def to_integer(str) do + Elixir.Core.get_global().parseInt(str, 10) + end + + def to_integer(str, base) do + Elixir.Core.get_global().parseInt(str, base) + end + + def upcase(str) do + str.toUpperCase() + end + + def downcase(str) do + str.toLowerCase() + end + + def at(str, pos) do + case pos > length(str) do + true -> + nil + _ -> + str[pos] + end + end + + def capitalize(str) do + first = str[0].toUpperCase() + rest = str.substr(1).toLowerCase() + + first <> rest + end + + def split(str) do + str.split() + end + + + def next_grapheme(nil), do: nil + def next_grapheme(""), do: nil + + def next_grapheme(str) do + { str[0], str.substr(1) } + end + + def first(nil), do: nil + def first(str) do + str[0] + end + + def last(nil), do: nil + def last(str) do + str[length(str) - 1] + end + + def graphemes(str) do + str.split('') + end + + def length(str) do + str.length() + end + + def match?(str, regex) do + str.match(regex) != nil + end + + def next_codepoint(nil), do: nil + def next_codepoint(""), do: nil + def next_codepoint(str) do + { str[0].codePointAt(0), str.substr(1) } + end + + def reverse(str) do + do_reverse(str, "") + end + + defp do_reverse("", str) do + str + end + + defp do_reverse(str, reverse_str) do + do_reverse(str.substr(1), reverse_str <> last(str)) + end + + def starts_with?(str, prefix) when is_binary(prefix) do + str.startsWith(prefix) + end + + def starts_with?(str, prefixes) when is_list(prefixes) do + do_starts_with?(str, prefixes) + end + + def do_starts_with?(_, []) do + false + end + + def do_starts_with?(str, prefixes) do + case starts_with?(str, hd(prefixes)) do + true -> + true + _ -> + do_starts_with?(str, tl(prefixes)) + end + end + + + def ends_with?(str, suffix) when is_binary(suffix) do + str.endsWith(suffix) + end + + def ends_with?(str, suffixes) when is_list(suffixes) do + do_ends_with?(str, suffixes) + end + + def do_ends_with?(_, []) do + false + end + + def do_ends_with?(str, suffixes) do + case ends_with?(str, hd(suffixes)) do + true -> + true + _ -> + do_ends_with?(str, tl(suffixes)) + end + end + + def duplicate(str, n) do + str.repeat(n) + end + + + def contains?(str, s) when is_binary(s) do + str.indexOf(s) > -1 + end + + def contains?(str, s) when is_list(s) do + do_contains?(str, s) + end + + def do_contains?(_, []) do + false + end + + def do_contains?(str, prefixes) do + case contains?(str, hd(prefixes)) do + true -> + true + _ -> + do_contains?(str, tl(prefixes)) + end + end + + + def codepoints(str) do + do_codepoints(str, []) + end + + def do_codepoints("", codepoint_list) do + codepoint_list + end + + def do_codepoints(str, codepoint_list) do + do_codepoints(str.substr(1), codepoint_list ++ [first(str).codePointAt(0)]) + end + + def valid_character?(codepoint) do + Elixir.Core.Functions.is_valid_character(codepoint) + end +end diff --git a/lib/elixir_script/universal/string/chars.ex b/lib/elixir_script/prelude/string/chars.ex similarity index 100% rename from lib/elixir_script/universal/string/chars.ex rename to lib/elixir_script/prelude/string/chars.ex diff --git a/lib/elixir_script/universal/tuple.ex b/lib/elixir_script/prelude/tuple.ex similarity index 52% rename from lib/elixir_script/universal/tuple.ex rename to lib/elixir_script/prelude/tuple.ex index 98737499..2f91079d 100644 --- a/lib/elixir_script/universal/tuple.ex +++ b/lib/elixir_script/prelude/tuple.ex @@ -1,7 +1,7 @@ defmodule ElixirScript.Tuple do def duplicate(data, size) do - Elixir.Core.make_tuple(size, data) + Elixir.Core.Functions.make_tuple(size, data) end def to_list(tuple) do @@ -9,15 +9,15 @@ defmodule ElixirScript.Tuple do end def insert_at(tuple, index, value) do - Elixir.Core.insert_at(tuple, index, value) + Elixir.Core.Functions.insert_at(tuple, index, value) end def delete_at(tuple, index) do - Elixir.Core.delete_at(tuple, index) + Elixir.Core.Functions.delete_at(tuple, index) end def append(tuple, value) do - Elixir.Core.new_tuple(to_list(tuple) ++ value) + Elixir.Core.Functions.new_tuple.apply(nil, to_list(tuple) ++ value) end end diff --git a/lib/elixir_script/universal/view.ex b/lib/elixir_script/prelude/view.ex similarity index 67% rename from lib/elixir_script/universal/view.ex rename to lib/elixir_script/prelude/view.ex index e0d6b781..df05796c 100644 --- a/lib/elixir_script/universal/view.ex +++ b/lib/elixir_script/prelude/view.ex @@ -24,22 +24,22 @@ defmodule ElixirScript.View do render_func and the args """ def start(dom_root, render_func, args) do - pid = Elixir.Core.global().processes.spawn() + pid = Elixir.Core.Functions.get_global().processes.spawn() tree = render_func.apply(nil, args); root_node = Elixir.VirtualDOM.create(tree); dom_root.appendChild(root_node); - Elixir.Core.global().processes.put(pid, "state", { root_node, tree, render_func }); + Elixir.Core.Functions.get_global().processes.put(pid, "state", { root_node, tree, render_func }); { :ok, pid } end def start(dom_root, render_func, args, options) do - pid = Elixir.Core.global().processes.spawn() + pid = Elixir.Core.Functions.get_global().processes.spawn() if Elixir.Keyword.has_key?(options, :name) do - pid = Elixir.Core.global().processes.register(Elixir.Keyword.get(options, :name), pid) + pid = Elixir.Core.Functions.get_global().processes.register(Elixir.Keyword.get(options, :name), pid) end tree = render_func.apply(nil, args); @@ -47,7 +47,7 @@ defmodule ElixirScript.View do dom_root.appendChild(root_node); - Elixir.Core.global().processes.put(pid, "state", { root_node, tree, render_func }) + Elixir.Core.Functions.get_global().processes.put(pid, "state", { root_node, tree, render_func }) { :ok, pid } end @@ -55,7 +55,7 @@ defmodule ElixirScript.View do Stops the View state """ def stop(view) do - Elixir.Core.global().processes.exit(view) + Elixir.Core.Functions.get_global().processes.exit(view) :ok end @@ -63,14 +63,14 @@ defmodule ElixirScript.View do Updates the view by passing the args to the render_func """ def render(view, args) do - { root_node, tree, render_func } = Elixir.Core.global().processes.get(view, "state") + { root_node, tree, render_func } = Elixir.Core.Functions.get_global().processes.get(view, "state") new_tree = render_func.apply(nil, args); patches = Elixir.VirtualDOM.diff(tree, new_tree) root_node = Elixir.VirtualDOM.patch(root_node, patches) - Elixir.Core.global().processes.put(view, "state", { root_node, new_tree, render_func }); + Elixir.Core.Functions.get_global().processes.put(view, "state", { root_node, new_tree, render_func }); :ok end diff --git a/lib/elixir_script/preprocess/modules.ex b/lib/elixir_script/preprocess/modules.ex index 32e0f522..1f035118 100644 --- a/lib/elixir_script/preprocess/modules.ex +++ b/lib/elixir_script/preprocess/modules.ex @@ -1,12 +1,13 @@ defmodule ElixirScript.Preprocess.Modules do @moduledoc false - alias ElixirScript.State + alias ElixirScript.Translator.State + alias ElixirScript.Translator.Utils - def get_info(modules) do + def process_modules(modules) do Enum.map(modules, fn { :__block__, _, list } -> - {mods, no_mods} = Enum.partition(list, fn + {modules, not_modules} = Enum.partition(list, fn ({:defprotocol, _, _ }) -> true ({:defimpl, _, _ }) -> @@ -17,7 +18,8 @@ defmodule ElixirScript.Preprocess.Modules do false end) - mods ++ [{:defmodule, [], [{:__aliases__, [], [:ElixirScript, :Temp]}, [do: { :__block__, [], no_mods }]]}] + temp_module = [{:defmodule, [], [{:__aliases__, [], [:ElixirScript, :Temp]}, [do: { :__block__, [], not_modules }]]}] + modules ++ temp_module ({:defprotocol, _, _ }) = x -> x ({:defimpl, _, _}) = x -> @@ -29,27 +31,27 @@ defmodule ElixirScript.Preprocess.Modules do end) |> List.flatten |> Enum.each(fn(m) -> - Macro.postwalk(m, &do_get_info(&1)) + Macro.postwalk(m, &do_process_modules(&1)) end) end - def do_get_info({:defprotocol, _, [{:__aliases__, _, _} = the_alias, [do: {:__block__, context, spec}]]}) do - ElixirScript.State.add_protocol(ElixirScript.Module.quoted_to_name(the_alias), {:__block__, context, spec}) + def do_process_modules({:defprotocol, _, [{:__aliases__, _, _} = the_alias, [do: {:__block__, context, spec}]]}) do + ElixirScript.Translator.State.add_protocol(Utils.quoted_to_name(the_alias), {:__block__, context, spec}) end - def do_get_info({:defprotocol, _, [{:__aliases__, _, _} = the_alias, [do: spec]]}) do - ElixirScript.State.add_protocol(ElixirScript.Module.quoted_to_name(the_alias), {:__block__, [], [spec]}) + def do_process_modules({:defprotocol, _, [{:__aliases__, _, _} = the_alias, [do: spec]]}) do + ElixirScript.Translator.State.add_protocol(Utils.quoted_to_name(the_alias), {:__block__, [], [spec]}) end - def do_get_info({:defimpl, _, [ {:__aliases__, _, _} = the_alias, [for: type], [do: {:__block__, context, spec}] ]}) do - ElixirScript.State.add_protocol_impl(ElixirScript.Module.quoted_to_name(the_alias), type, {:__block__, context, spec}) + def do_process_modules({:defimpl, _, [ {:__aliases__, _, _} = the_alias, [for: type], [do: {:__block__, context, spec}] ]}) do + ElixirScript.Translator.State.add_protocol_impl(Utils.quoted_to_name(the_alias), type, {:__block__, context, spec}) end - def do_get_info({:defimpl, _, [ {:__aliases__, _, _} = the_alias, [for: type], [do: spec] ]}) do - ElixirScript.State.add_protocol_impl(ElixirScript.Module.quoted_to_name(the_alias), type, {:__block__, [], [spec]}) + def do_process_modules({:defimpl, _, [ {:__aliases__, _, _} = the_alias, [for: type], [do: spec] ]}) do + ElixirScript.Translator.State.add_protocol_impl(Utils.quoted_to_name(the_alias), type, {:__block__, [], [spec]}) end - def do_get_info({:defmodule, _, [{:__aliases__, _, [:ElixirScript, :Temp]}, [do: body]]} = ast) do + def do_process_modules({:defmodule, _, [{:__aliases__, _, [:ElixirScript, :Temp]}, [do: body]]} = ast) do body |> make_module([:ElixirScript, :Temp]) |> State.add_module @@ -57,23 +59,23 @@ defmodule ElixirScript.Preprocess.Modules do ast end - def do_get_info({:defmodule, _, [{:__aliases__, _, module_name_list}, [do: body]]} = ast) do - body = make_inner_module_aliases(module_name_list, body) + def do_process_modules({:defmodule, _, [{:__aliases__, _, name}, [do: body]]} = ast) do + body = make_inner_module_aliases(name, body) - make_module(body, module_name_list) + make_module(body, name) |> State.add_module ast end - def do_get_info(ast) do + def do_process_modules(ast) do ast end - defp make_module(body, module_name_list) do + defp make_module(body, name) do body = case body do {:__block__, _, _ } -> - Macro.expand(body, State.get().elixir_env) + Macro.expand(body, State.get().compiler_opts.env) _ -> body end @@ -81,23 +83,23 @@ defmodule ElixirScript.Preprocess.Modules do %{def: functions, defp: private_functions, defmacro: macros, defmacrop: private_macros } = get_functions_from_module(body) js_imports = get_js_imports_from_module(body) - %ElixirScript.Module{ name: ElixirScript.Module.quoted_to_name({:__aliases__, [], module_name_list}) , body: body, + %ElixirScript.Module{ name: Utils.quoted_to_name({:__aliases__, [], name}) , body: body, functions: functions, private_functions: private_functions, macros: macros, private_macros: private_macros, js_imports: js_imports } end - defp make_inner_module_aliases(module_name_list, body) do + defp make_inner_module_aliases(name, body) do case body do nil -> { :__block__, [], [] } - {:__block__, meta2, list2 } -> + {:__block__, context, list2 } -> list2 = Enum.map(list2, fn(x) -> case x do - {:defmodule, _, [{:__aliases__, _, module_name_list2}, [do: body2]]} -> - body2 = make_inner_module_aliases( module_name_list ++ module_name_list2, body2) - inner_alias = add_module_to_state(module_name_list, module_name_list2, body2) + {:defmodule, _, [{:__aliases__, _, inner_module_name}, [do: inner_module_body]]} -> + inner_module_body = make_inner_module_aliases( name ++ inner_module_name, inner_module_body) + inner_alias = add_module_to_state(name, inner_module_name, inner_module_body) [ inner_alias ] @@ -107,29 +109,29 @@ defmodule ElixirScript.Preprocess.Modules do end) |> List.flatten - {:__block__, meta2, list2} - {:defmodule, _, [{:__aliases__, meta2, module_name_list2}, [do: body2]]} -> - body2 = make_inner_module_aliases(module_name_list ++ module_name_list2, body2) - inner_alias = add_module_to_state(module_name_list, module_name_list2, body2) + {:__block__, context, list2} + {:defmodule, _, [{:__aliases__, context, inner_module_name}, [do: inner_module_body]]} -> + inner_module_body = make_inner_module_aliases(name ++ inner_module_name, inner_module_body) + inner_alias = add_module_to_state(name, inner_module_name, inner_module_body) - {:__block__, meta2, [ inner_alias ] } + {:__block__, context, [ inner_alias ] } _ -> body end end - defp add_module_to_state(module_name_list, module_name_list2, body2) do - %{def: functions, defp: private_functions, defmacro: macros, defmacrop: private_macros } = get_functions_from_module(body2) - js_imports = get_js_imports_from_module(body2) + defp add_module_to_state(name, inner_module_name, inner_module_body) do + %{def: functions, defp: private_functions, defmacro: macros, defmacrop: private_macros } = get_functions_from_module(inner_module_body) + js_imports = get_js_imports_from_module(inner_module_body) - inner_alias = {:alias, [], [{:__aliases__, [alias: false], module_name_list ++ module_name_list2}]} + inner_alias = {:alias, [], [{:__aliases__, [alias: false], name ++ inner_module_name}]} - module_name = ElixirScript.Module.quoted_to_name({:__aliases__, [], tl(module_name_list) ++ module_name_list2}) + module_name = Utils.quoted_to_name({:__aliases__, [], tl(name) ++ inner_module_name}) State.delete_module_by_name(module_name) - module_name = ElixirScript.Module.quoted_to_name({:__aliases__, [], module_name_list ++ module_name_list2}) + module_name = Utils.quoted_to_name({:__aliases__, [], name ++ inner_module_name}) - mod = %ElixirScript.Module{ name: module_name, body: body2, + mod = %ElixirScript.Module{ name: module_name, body: inner_module_body, functions: functions, private_functions: private_functions, macros: macros, private_macros: private_macros, js_imports: js_imports } diff --git a/lib/elixir_script/preprocess/using.ex b/lib/elixir_script/preprocess/using.ex deleted file mode 100644 index 7d32a8f3..00000000 --- a/lib/elixir_script/preprocess/using.ex +++ /dev/null @@ -1,24 +0,0 @@ -defmodule ElixirScript.Preprocess.Using do - @moduledoc false - - def process(ast) do - Macro.prewalk(ast, fn(x) -> - process_using(x) - end) - end - - def process_using({:use, _, _} = ast) do - ast - |> Macro.expand(ElixirScript.State.get().elixir_env) - |> expand__using__ - end - - def process_using(ast) do - ast - end - - defp expand__using__({:__block__, _, [{:require, _, _}, {{:., _, [_, :__using__]}, _, _} = using_ast]}) do - Macro.expand_once(using_ast, ElixirScript.State.get().elixir_env) - end - -end diff --git a/lib/elixir_script/translator.ex b/lib/elixir_script/translator.ex index a8f83ab1..e17dd659 100644 --- a/lib/elixir_script/translator.ex +++ b/lib/elixir_script/translator.ex @@ -91,18 +91,12 @@ defmodule ElixirScript.Translator do defp do_translate({:++, _, [left, right]}, env) do quoted = quote do - Elixir.Core.concat_lists(unquote(left),unquote(right)) + Elixir.Core.Functions.concat_lists(unquote(left),unquote(right)) end translate(quoted, env) end - defp do_translate({:.., _, [first, last]}, env) do - quoted_range = quote do: Range.(unquote(first), unquote(last)) - - translate(quoted_range, env) - end - defp do_translate({:&, _, [number]}, env) when is_number(number) do { Primitive.make_identifier(String.to_atom("__#{number}")), env } end @@ -178,7 +172,7 @@ defmodule ElixirScript.Translator do end defp do_translate({:., _, [module_name, function_name]} = ast, env) do - expanded_ast = Macro.expand(ast, ElixirScript.State.get().elixir_env) + expanded_ast = Macro.expand(ast, ElixirScript.Translator.State.get().compiler_opts.env) if expanded_ast == ast do module_name = create_module_name(module_name, env) @@ -189,7 +183,7 @@ defmodule ElixirScript.Translator do end defp do_translate({{:., _, [module_name, function_name]}, _, [] } = ast, env) do - expanded_ast = Macro.expand(ast, ElixirScript.State.get().elixir_env) + expanded_ast = Macro.expand(ast, ElixirScript.Translator.State.get().compiler_opts.env) if expanded_ast == ast do module_name = create_module_name(module_name, env) @@ -200,7 +194,7 @@ defmodule ElixirScript.Translator do end defp do_translate({{:., _, [{:__aliases__, _, _} = module_name]}, _, params} = ast, env) do - expanded_ast = Macro.expand(ast, ElixirScript.State.get().elixir_env) + expanded_ast = Macro.expand(ast, ElixirScript.Translator.State.get().compiler_opts.env) if expanded_ast == ast do module_name = create_module_name(module_name, env) @@ -216,7 +210,7 @@ defmodule ElixirScript.Translator do defp do_translate({{:., _, [module_name, function_name]}, _, params } = ast, env) do - expanded_ast = Macro.expand(ast, ElixirScript.State.get().elixir_env) + expanded_ast = Macro.expand(ast, ElixirScript.Translator.State.get().compiler_opts.env) if expanded_ast == ast do module_name = create_module_name(module_name, env) @@ -256,11 +250,11 @@ defmodule ElixirScript.Translator do end defp do_translate({:receive, _, _ }, _ ) do - raise ElixirScript.UnsupportedError, "receive" + raise ElixirScript.Translator.UnsupportedError, "receive" end defp do_translate({:super, _, _expressions }, _ ) do - raise ElixirScript.UnsupportedError, "super" + raise ElixirScript.Translator.UnsupportedError, "super" end defp do_translate({:__CALLER__, _, _expressions }, env) do @@ -286,14 +280,14 @@ defmodule ElixirScript.Translator do end defp do_translate({:import, _, [{:__aliases__, _, _} = module_name]}, env) do - env = ElixirScript.Env.add_import(env, module_name) + env = ElixirScript.Translator.Env.add_import(env, module_name) { %ElixirScript.Translator.Group{}, env } end defp do_translate({:import, _, [{:__aliases__, _, _} = module_name, options]}, env) do - module_name = ElixirScript.Module.quoted_to_name(module_name) + module_name = Utils.quoted_to_name(module_name) - env = ElixirScript.Env.add_import(env, module_name, options) + env = ElixirScript.Translator.Env.add_import(env, module_name, options) { %ElixirScript.Translator.Group{}, env } end @@ -302,32 +296,32 @@ defmodule ElixirScript.Translator do {_, _, name} = module_name name = [List.last(name)] - module_name = ElixirScript.Module.quoted_to_name(module_name) - alias_name = ElixirScript.Module.quoted_to_name({:__aliases__, [], name }) + module_name = Utils.quoted_to_name(module_name) + alias_name = Utils.quoted_to_name({:__aliases__, [], name }) - env = ElixirScript.Env.add_alias(env, module_name, alias_name) + env = ElixirScript.Translator.Env.add_alias(env, module_name, alias_name) { %ElixirScript.Translator.Group{}, env } end defp do_translate({:alias, _, [{:__aliases__, _, _} = module_name, [as: {:__aliases__, _, _} = alias_name]]}, env) do - module_name = ElixirScript.Module.quoted_to_name(module_name) - alias_name = ElixirScript.Module.quoted_to_name(alias_name) + module_name = Utils.quoted_to_name(module_name) + alias_name = Utils.quoted_to_name(alias_name) - env = ElixirScript.Env.add_alias(env, module_name, alias_name) + env = ElixirScript.Translator.Env.add_alias(env, module_name, alias_name) { %ElixirScript.Translator.Group{}, env } end defp do_translate({:require, _, [{:__aliases__, _, _} = module_name] }, env) do - module_name = ElixirScript.Module.quoted_to_name(module_name) - env = ElixirScript.Env.add_require(env, module_name) + module_name = Utils.quoted_to_name(module_name) + env = ElixirScript.Translator.Env.add_require(env, module_name) { %ElixirScript.Translator.Group{}, env } end defp do_translate({:require, _, [{:__aliases__, _, _} = module_name, [as: {:__aliases__, _, _} = alias_name]]}, env) do - module_name = ElixirScript.Module.quoted_to_name(module_name) - alias_name = ElixirScript.Module.quoted_to_name(alias_name) + module_name = Utils.quoted_to_name(module_name) + alias_name = Utils.quoted_to_name(alias_name) - env = ElixirScript.Env.add_require(env, module_name, alias_name) + env = ElixirScript.Translator.Env.add_require(env, module_name, alias_name) { %ElixirScript.Translator.Group{}, env } end @@ -344,7 +338,7 @@ defmodule ElixirScript.Translator do end defp do_translate({:fn, _, clauses}, env) do - env = ElixirScript.Env.function_env(env, nil) + env = ElixirScript.Translator.Env.function_env(env, nil) Function.make_anonymous_function(clauses, env) end @@ -429,17 +423,17 @@ defmodule ElixirScript.Translator do defp do_translate({name, _, params} = ast, env) when is_list(params) do - expanded_ast = Macro.expand(ast, ElixirScript.State.get().elixir_env) + expanded_ast = Macro.expand(ast, ElixirScript.Translator.State.get().compiler_opts.env) if expanded_ast == ast do name_arity = {name, length(params)} - module = ElixirScript.State.get_module(env.module) + module = ElixirScript.Translator.State.get_module(env.module) cond do name_arity in module.functions or name_arity in module.private_functions -> Function.make_function_call(name, params, env) - ElixirScript.Env.find_module(env, name_arity) -> - imported_module_name = ElixirScript.Env.find_module(env, name_arity) + ElixirScript.Translator.Env.find_module(env, name_arity) -> + imported_module_name = ElixirScript.Translator.Env.find_module(env, name_arity) Function.make_function_call(imported_module_name, name, params, env) true -> Function.make_function_call(name, params, env) @@ -452,13 +446,13 @@ defmodule ElixirScript.Translator do defp do_translate({ name, _, params }, env) when is_atom(params) do cond do - ElixirScript.Env.has_var?(env, name) -> + ElixirScript.Translator.Env.has_var?(env, name) -> name = Utils.filter_name(name) { Primitive.make_identifier(name), env } - ElixirScript.Module.has_function?(env.module, {name, 0}) -> + has_function?(env.module, {name, 0}) -> Function.make_function_call(name, [], env) - ElixirScript.Env.find_module(env, {name, 0}) -> - imported_module_name = ElixirScript.Env.find_module(env, {name, 0}) + ElixirScript.Translator.Env.find_module(env, {name, 0}) -> + imported_module_name = ElixirScript.Translator.Env.find_module(env, {name, 0}) Function.make_function_call(imported_module_name, name, params, env) true -> name = Utils.filter_name(name) @@ -470,11 +464,11 @@ defmodule ElixirScript.Translator do defp create_module_name(module_name, env) do case module_name do {:__aliases__, _, _} -> - candiate_module_name = ElixirScript.Module.quoted_to_name(module_name) - |> ElixirScript.Module.get_module_name + candiate_module_name = Utils.quoted_to_name(module_name) + |> ElixirScript.Translator.State.get_module_name - if ElixirScript.Env.get_module_name(env, candiate_module_name) in ElixirScript.State.list_module_names() do - ElixirScript.Env.get_module_name(env, candiate_module_name) + if ElixirScript.Translator.Env.get_module_name(env, candiate_module_name) in ElixirScript.Translator.State.list_module_names() do + ElixirScript.Translator.Env.get_module_name(env, candiate_module_name) else module_name end @@ -483,4 +477,9 @@ defmodule ElixirScript.Translator do end end + def has_function?(module_name, name_arity) do + module = ElixirScript.Translator.State.get_module(module_name) + name_arity in module.functions or name_arity in module.private_functions + end + end diff --git a/lib/elixir_script/translator/assignment.ex b/lib/elixir_script/translator/assignment.ex index d5f671aa..12299176 100644 --- a/lib/elixir_script/translator/assignment.ex +++ b/lib/elixir_script/translator/assignment.ex @@ -2,8 +2,8 @@ defmodule ElixirScript.Translator.Assignment do @moduledoc false alias ESTree.Tools.Builder, as: JS alias ElixirScript.Translator - alias ElixirScript.Translator.Primitive alias ElixirScript.PatternMatching.Match + alias ElixirScript.Translator.Primitive def make_assignment(left, right, env) do { right_ast, env } = Translator.translate(right, env) @@ -31,11 +31,11 @@ defmodule ElixirScript.Translator.Assignment do js_ast = case left do list when is_list(list) -> - make_ref(array_pattern, params, "list") + make_ref(array_pattern, params, Primitive.list_ast()) {_left1, _left2} -> - make_ref(array_pattern, params, "tuple") + make_ref(array_pattern, params, Primitive.new_tuple_function()) {:{}, _, _} -> - make_ref(array_pattern, params, "tuple") + make_ref(array_pattern, params, Primitive.new_tuple_function()) _ -> array_pattern end @@ -43,7 +43,7 @@ defmodule ElixirScript.Translator.Assignment do { js_ast, env } end - defp make_ref(array_pattern, params, type) do + defp make_ref(array_pattern, params, ast) do ref = JS.identifier("_ref") params = Enum.map(params, fn @@ -54,10 +54,7 @@ defmodule ElixirScript.Translator.Assignment do ref_declarator = JS.variable_declarator( ref, JS.call_expression( - JS.member_expression( - Primitive.special_forms(), - JS.identifier(type) - ), + ast, params ) ) diff --git a/lib/elixir_script/env.ex b/lib/elixir_script/translator/env.ex similarity index 71% rename from lib/elixir_script/env.ex rename to lib/elixir_script/translator/env.ex index 49ee8262..dce9b7af 100644 --- a/lib/elixir_script/env.ex +++ b/lib/elixir_script/translator/env.ex @@ -1,4 +1,4 @@ -defmodule ElixirScript.Env do +defmodule ElixirScript.Translator.Env do @moduledoc false def module_env(ElixirScript.Temp, filename) do @@ -13,7 +13,7 @@ defmodule ElixirScript.Env do end def module_env(module_name, filename) do - module = ElixirScript.State.get_module(module_name) + module = ElixirScript.Translator.State.get_module(module_name) env = %ElixirScript.Macro.Env { module: module_name, file: filename, requires: [], @@ -83,13 +83,13 @@ defmodule ElixirScript.Env do end defp get_module(env, module_name) do - module = ElixirScript.State.get_module(module_name) + module = ElixirScript.Translator.State.get_module(module_name) unless module do raise "Module #{module_name} not found" end - ElixirScript.State.add_module_reference(env.module, module.name) + ElixirScript.Translator.State.add_module_reference(env.module, module.name) module end @@ -105,17 +105,17 @@ defmodule ElixirScript.Env do def add_import(env, module_name, [only: :functions]) do module = get_module(env, module_name) - - %{ env | requires: Enum.uniq(env.requires ++ [module.name]), - functions: env.functions ++ [{ module.name, module.functions }] } + %{ env | functions: List.keydelete(env.functions, module_name, 0) ++ [{ module.name, module.functions }], + macros: List.keydelete(env.macros, module_name, 0), + requires: Enum.uniq(env.requires ++ [module.name]) } end def add_import(env, module_name, [only: :macros]) do module = get_module(env, module_name) - - %{ env | requires: Enum.uniq(env.requires ++ [module.name]), - macros: env.macros ++ [{ module.name, module.macros }] } + %{ env | macros: List.keydelete(env.macros, module_name, 0) ++ [{ module.name, module.macros }], + functions: List.keydelete(env.functions, module_name, 0), + requires: Enum.uniq(env.requires ++ [module.name]) } end def add_import(env, module_name, [only: only]) do @@ -129,19 +129,22 @@ defmodule ElixirScript.Env do end) %{ env | requires: Enum.uniq(env.requires ++ [module.name]), - functions: env.functions ++ [{ module.name, functions }], - macros: env.macros ++ [{ module.name, macros }] } + functions: List.keydelete(env.functions, module_name, 0) ++ [{ module.name, functions }], + macros: List.keydelete(env.macros, module_name, 0) ++ [{ module.name, macros }] } end def add_import(env, module_name, [except: except]) do module = get_module(env, module_name) - macros = Enum.filter(module.macros, fn(mac) -> not(mac in except) end) - functions = Enum.filter(module.functions, fn(func) -> not(func in except) end) + {_, current_functions } = List.keyfind(env.functions, module_name, 0, { module_name, module.functions }) + {_, current_macros } = List.keyfind(env.macros, module_name, 0, { module_name, module.macros }) + + macros = Enum.filter(current_macros, fn(mac) -> not(mac in except) end) + functions = Enum.filter(current_functions, fn(func) -> not(func in except) end) %{ env | requires: env.requires ++ [module.name], - functions: env.functions ++ [{ module.name, functions }], - macros: env.macros ++ [{ module.name, macros }] } + functions: List.keydelete(env.functions, module_name, 0) ++ [{ module.name, functions }], + macros: List.keydelete(env.macros, module_name, 0) ++ [{ module.name, macros }] } end def add_alias(env, module_name, alias_name) do @@ -164,7 +167,7 @@ defmodule ElixirScript.Env do end def get_module_name(env, module_name) do - module_name = ElixirScript.Module.get_module_name(module_name) + module_name = ElixirScript.Translator.State.get_module_name(module_name) if Keyword.has_key?(env.aliases, module_name) do Keyword.fetch!(env.aliases, module_name) diff --git a/lib/elixir_script/translator/function.ex b/lib/elixir_script/translator/function.ex index 92d1babe..ca55447f 100644 --- a/lib/elixir_script/translator/function.ex +++ b/lib/elixir_script/translator/function.ex @@ -17,7 +17,7 @@ defmodule ElixirScript.Translator.Function do { result, _ } = make_anonymous_function(functions, env, name) declarator = JS.variable_declarator( - JS.identifier(name), + JS.identifier(Utils.filter_name(name)), result ) @@ -56,7 +56,7 @@ defmodule ElixirScript.Translator.Function do end defp process_function_body(params, body, env, name, guards \\ nil) do - env = ElixirScript.Env.function_env(env, {name, get_arity(params)}) + env = ElixirScript.Translator.Env.function_env(env, {name, get_arity(params)}) { patterns, params, env } = process_params(params, env) { body, _ } = make_function_body(body, env) @@ -126,7 +126,10 @@ defmodule ElixirScript.Translator.Function do JS.member_expression( JS.member_expression( JS.identifier("Elixir"), - JS.identifier("Core") + JS.member_expression( + JS.identifier("Core"), + JS.identifier("Functions") + ) ), JS.identifier("call_property") ), @@ -142,7 +145,7 @@ defmodule ElixirScript.Translator.Function do defp get_module_name_for_function(module_name, env) do case module_name do {:__aliases__, _, name} -> - module_name = ElixirScript.Module.quoted_to_name(name) + module_name = Utils.quoted_to_name(name) get_js_name(module_name, env) {name, _, _} when is_atom(name) -> get_js_name(name, env) @@ -262,7 +265,7 @@ defmodule ElixirScript.Translator.Function do end defp get_js_name(module_name, env) when is_list(module_name) do - ElixirScript.Module.quoted_to_name({:__aliases__, [], module_name}) + Utils.quoted_to_name({:__aliases__, [], module_name}) |> get_js_name(env) end @@ -270,16 +273,16 @@ defmodule ElixirScript.Translator.Function do cond do module_name in env.requires -> - ElixirScript.Module.name_to_js_name(module_name) + Utils.name_to_js_name(module_name) - module_name in ElixirScript.State.list_module_names -> - ElixirScript.State.add_module_reference(env.module, module_name) - ElixirScript.Module.name_to_js_name(module_name) + module_name in ElixirScript.Translator.State.list_module_names -> + ElixirScript.Translator.State.add_module_reference(env.module, module_name) + Utils.name_to_js_name(module_name) true -> case Atom.to_string(module_name) do "Elixir." <> _ -> - {:__aliases__, _, name } = ElixirScript.Module.name_to_quoted(module_name) + {:__aliases__, _, name } = Utils.name_to_quoted(module_name) name _ -> module_name diff --git a/lib/elixir_script/translator/import.ex b/lib/elixir_script/translator/import.ex index 4973f086..f0e24bcc 100644 --- a/lib/elixir_script/translator/import.ex +++ b/lib/elixir_script/translator/import.ex @@ -1,38 +1,34 @@ defmodule ElixirScript.Translator.Import do @moduledoc false alias ESTree.Tools.Builder, as: JS + alias ElixirScript.Translator.Utils def make_import(module_name) do - import_specifier = JS.import_namespace_specifier( - JS.identifier(ElixirScript.Module.name_to_js_name(module_name)) - ) + do_make_import(Utils.name_to_js_name(module_name), Utils.name_to_js_file_name(module_name)) + end - JS.import_declaration( - [import_specifier], - JS.literal("#{ElixirScript.Module.name_to_js_file_name(module_name)}") - ) + def create_standard_lib_imports(std_lib_path) do + do_make_import(:Elixir, std_lib_path) end - def create_standard_lib_imports(root, name) do + defp do_make_import(import_name, file_name) do + root = ElixirScript.Translator.State.get().compiler_opts.root import_specifier = JS.import_namespace_specifier( - JS.identifier(:Elixir) + JS.identifier(import_name) ) - import_declaration = JS.import_declaration( + root = case root do + nil -> + "./" + root -> + root <> "/" + end + + JS.import_declaration( [import_specifier], - JS.identifier("'#{make_root(root) <> name}'") + JS.literal("#{root <> file_name}") ) - - [import_declaration] - end - - defp make_root(nil) do - "" - end - - defp make_root(root) do - root <> "/" end end diff --git a/lib/elixir_script/translator/js_module.ex b/lib/elixir_script/translator/js_module.ex deleted file mode 100644 index f1fb023d..00000000 --- a/lib/elixir_script/translator/js_module.ex +++ /dev/null @@ -1,4 +0,0 @@ -defmodule ElixirScript.Translator.JSModule do - @moduledoc false - defstruct name: [], body: [] -end diff --git a/lib/elixir_script/translator/module.ex b/lib/elixir_script/translator/module.ex index 71c11c9e..34bf11b2 100644 --- a/lib/elixir_script/translator/module.ex +++ b/lib/elixir_script/translator/module.ex @@ -3,35 +3,30 @@ defmodule ElixirScript.Translator.Module do alias ESTree.Tools.Builder, as: JS alias ElixirScript.Translator alias ElixirScript.Translator.Utils - alias ElixirScript.Translator.JSModule - alias ElixirScript.Preprocess.Using alias ElixirScript.Translator.Function def make_module(ElixirScript.Temp, body, env) do { body, _ } = translate_body(body, env) - %JSModule{ name: ElixirScript.Temp, body: body |> Utils.inflate_groups } + %{ name: ElixirScript.Temp, body: body |> Utils.inflate_groups } end def make_module(module, nil, _) do - %JSModule{ name: module, body: [] } + %{ name: module, body: [] } end def make_module(module, body, env) do - body = Using.process(body) + body = process_use(body) { body, functions } = extract_functions_from_module(body) { body, env } = translate_body(body, env) { exported_functions, private_functions } = process_functions(functions, env) - modules_refs = ElixirScript.State.get_module_references(module) + module_refs = ElixirScript.Translator.State.get_module_references(module) -- [env.module] {imports, body} = extract_imports_from_body(body) {structs, body} = extract_structs_from_body(body, env) - #Add imports found from walking the ast - #and make sure to only put one declaration per alias - imports = process_imports(imports, modules_refs) - imports = imports.imports + imports = imports ++ make_std_lib_import() ++ make_imports(module_refs) #Collect all the functions so that we can process their arity body = Enum.map(body, fn(x) -> @@ -48,7 +43,7 @@ defmodule ElixirScript.Translator.Module do exported_object = JS.object_expression( make_defstruct_property(module, structs) ++ Enum.map(exported_functions, fn({key, _value}) -> - JS.property(JS.identifier(key), JS.identifier(key), :init, true) + JS.property(JS.identifier(Utils.filter_name(key)), JS.identifier(Utils.filter_name(key)), :init, true) end) ) @@ -57,14 +52,32 @@ defmodule ElixirScript.Translator.Module do default = JS.export_named_declaration(exported_object) - result = %JSModule{ - name: ElixirScript.Module.quoted_to_name({:__aliases__, [], module }), + result = %{ + name: Utils.quoted_to_name({:__aliases__, [], module }), body: imports ++ structs ++ private_functions ++ exported_functions ++ body ++ [default] } result end + defp process_use(ast) do + Macro.prewalk(ast, &do_process_use(&1)) + end + + defp do_process_use({:use, _, _} = ast) do + ast + |> Macro.expand(ElixirScript.Translator.State.get().compiler_opts.env) + |> expand__using__ + end + + defp do_process_use(ast) do + ast + end + + defp expand__using__({:__block__, _, [{:require, _, _}, {{:., _, [_, :__using__]}, _, _} = using_ast]}) do + Macro.expand_once(using_ast, ElixirScript.Translator.State.get().compiler_opts.env) + end + def translate_body(body, env) do { body, env } = Translator.translate(body, env) @@ -129,7 +142,7 @@ defmodule ElixirScript.Translator.Module do end def extract_structs_from_body(body, env) do - module_js_name = ElixirScript.Module.name_to_js_name(env.module) + module_js_name = Utils.name_to_js_name(env.module) Enum.partition(body, fn(x) -> case x do @@ -146,7 +159,7 @@ defmodule ElixirScript.Translator.Module do end defp make_defstruct_property(module_name, [the_struct]) do - module_js_name = ElixirScript.Module.name_to_js_name(module_name) + module_js_name = Utils.name_to_js_name(module_name) case the_struct do %ESTree.VariableDeclaration{declarations: [%ESTree.VariableDeclarator{id: %ESTree.Identifier{name: ^module_js_name} } ] } -> @@ -154,31 +167,14 @@ defmodule ElixirScript.Translator.Module do end end - def process_imports(imports, module_refs) do - imports ++ make_imports(module_refs) - |> Enum.into(MapSet.new) - |> Enum.reduce(MapSet.new, fn(x, acc)-> - MapSet.put(acc, x) - end) - |> MapSet.to_list - |> Enum.reduce(%{ identifiers: MapSet.new, imports: [] }, fn(x, state) -> - case x do - %ESTree.ImportDeclaration{ specifiers: [%ESTree.ImportSpecifier{ local: id }] } -> - if MapSet.member?(state.identifiers, id.name) do - state - else - %{ state | identifiers: MapSet.put(state.identifiers, id.name), imports: state.imports ++ [x] } - end - %ESTree.ImportDeclaration{ specifiers: [%ESTree.ImportDefaultSpecifier{ local: id }] } -> - if MapSet.member?(state.identifiers, id.name) do - state - else - %{ state | identifiers: MapSet.put(state.identifiers, id.name), imports: state.imports ++ [x] } - end - _ -> - %{ state | imports: state.imports ++ [x] } - end - end) + def make_std_lib_import() do + compiler_opts = ElixirScript.Translator.State.get().compiler_opts + case compiler_opts.import_standard_libs do + true -> + [ElixirScript.Translator.Import.create_standard_lib_imports(compiler_opts.stdlib_path)] + false -> + [] + end end def process_functions(%{ exported: exported, private: private }, env) do diff --git a/lib/elixir_script/translator/primitive.ex b/lib/elixir_script/translator/primitive.ex index 658667d2..8736dd6f 100644 --- a/lib/elixir_script/translator/primitive.ex +++ b/lib/elixir_script/translator/primitive.ex @@ -15,6 +15,19 @@ defmodule ElixirScript.Translator.Primitive do ) end + def new_tuple_function() do + JS.member_expression( + JS.member_expression( + JS.identifier("Elixir"), + JS.member_expression( + JS.identifier("Core"), + JS.identifier("Functions") + ) + ), + JS.identifier("new_tuple") + ) + end + def tuple_class() do JS.member_expression( JS.member_expression( @@ -25,6 +38,17 @@ defmodule ElixirScript.Translator.Primitive do ) end + def list_ast() do + JS.member_expression( + JS.member_expression( + JS.identifier("Elixir"), + JS.identifier("Core") + ), + JS.identifier("List") + ) + end + + def make_identifier({:__aliases__, _, aliases}) do Utils.make_module_expression_tree(aliases, false, __ENV__) end @@ -44,8 +68,8 @@ defmodule ElixirScript.Translator.Primitive do def make_atom(ast) when is_atom(ast) do JS.call_expression( JS.member_expression( - special_forms(), - JS.identifier("atom") + JS.identifier("Symbol"), + JS.identifier("for") ), [JS.literal(ast)] ) @@ -59,10 +83,7 @@ defmodule ElixirScript.Translator.Primitive do list = Enum.map(ast, &Translator.translate!(&1, env)) js_ast = JS.call_expression( - JS.member_expression( - special_forms(), - JS.identifier("list") - ), + list_ast(), list ) @@ -71,20 +92,14 @@ defmodule ElixirScript.Translator.Primitive do def make_list_quoted(opts, ast, env) when is_list(ast) do JS.call_expression( - JS.member_expression( - special_forms(), - JS.identifier("list") - ), + list_ast(), Enum.map(ast, fn(x) -> Quote.make_quote(opts, x, env) end) ) end def make_list_no_translate(ast) when is_list(ast) do JS.call_expression( - JS.member_expression( - special_forms(), - JS.identifier("list") - ), + list_ast(), ast ) end @@ -96,33 +111,18 @@ defmodule ElixirScript.Translator.Primitive do def make_tuple(elements, env) do list = Enum.map(elements, &Translator.translate!(&1, env)) - js_ast = JS.call_expression( - JS.member_expression( - special_forms(), - JS.identifier("tuple") - ), - list - ) + js_ast = JS.call_expression(new_tuple_function, list) { js_ast, env } end def make_tuple_no_translate(elements) do - JS.call_expression( - JS.member_expression( - special_forms(), - JS.identifier("tuple") - ), - elements - ) + JS.call_expression(new_tuple_function, elements) end def make_tuple_quoted(opts, elements, env) do JS.call_expression( - JS.member_expression( - special_forms(), - JS.identifier("tuple") - ), + new_tuple_function, Enum.map(elements, fn(x) -> Quote.make_quote(opts, x, env) end) ) end diff --git a/lib/elixir_script/translator/protocol.ex b/lib/elixir_script/translator/protocol.ex index 2c67c319..4262f63e 100644 --- a/lib/elixir_script/translator/protocol.ex +++ b/lib/elixir_script/translator/protocol.ex @@ -3,7 +3,6 @@ defmodule ElixirScript.Translator.Protocol do alias ESTree.Tools.Builder, as: JS alias ElixirScript.Translator.Module - alias ElixirScript.Translator.JSModule alias ElixirScript.Translator.Map alias ElixirScript.Translator.Function alias ElixirScript.Translator.Utils @@ -30,12 +29,11 @@ defmodule ElixirScript.Translator.Protocol do { body, env } = Module.translate_body(body, env) { exported_functions, _ } = process_functions(functions, env) - modules_refs = ElixirScript.State.get_module_references(name) + module_refs = ElixirScript.Translator.State.get_module_references(name) {imports, body} = Module.extract_imports_from_body(body) - imports = Module.process_imports(imports, modules_refs) - imports = imports.imports + imports = imports ++ Module.make_std_lib_import() ++ Module.make_imports(module_refs) object = Enum.map(exported_functions, fn({key, value}) -> Map.make_property(JS.identifier(Utils.filter_name(key)), value) @@ -43,13 +41,16 @@ defmodule ElixirScript.Translator.Protocol do |> JS.object_expression declarator = JS.variable_declarator( - JS.identifier(ElixirScript.Module.name_to_js_name(name)), + JS.identifier(Utils.name_to_js_name(name)), JS.call_expression( JS.member_expression( JS.identifier(:Elixir), JS.member_expression( - JS.identifier(:Kernel), - JS.identifier(:defprotocol) + JS.identifier(:Core), + JS.member_expression( + JS.identifier(:Functions), + JS.identifier(:defprotocol) + ) ) ), [object] @@ -65,18 +66,17 @@ defmodule ElixirScript.Translator.Protocol do defp define_impls(name, impls, env) do Enum.map(impls, fn({type, impl}) -> - type = map_to_js(type) + type = map_to_js(type, env) { body, functions } = Module.extract_functions_from_module(impl) { body, env } = Module.translate_body(body, env) { exported_functions, _ } = process_functions(functions, env) - modules_refs = ElixirScript.State.get_module_references(name) + module_refs = ElixirScript.Translator.State.get_module_references(name) {imports, body} = Module.extract_imports_from_body(body) - imports = Module.process_imports(imports, modules_refs) - imports = imports.imports + imports = imports ++ Module.make_std_lib_import() ++ Module.make_imports(module_refs) object = Enum.map(exported_functions, fn({key, value}) -> Map.make_property(JS.identifier(Utils.filter_name(key)), value) @@ -87,11 +87,14 @@ defmodule ElixirScript.Translator.Protocol do JS.member_expression( JS.identifier(:Elixir), JS.member_expression( - JS.identifier(:Kernel), - JS.identifier(:defimpl) + JS.identifier(:Core), + JS.member_expression( + JS.identifier(:Functions), + JS.identifier(:defimpl) + ) ) ), - [JS.identifier(ElixirScript.Module.name_to_js_name(name)), type, object] + [JS.identifier(Utils.name_to_js_name(name)), type, object] ) {imports, body, [impl]} @@ -107,9 +110,9 @@ defmodule ElixirScript.Translator.Protocol do end defp create_module(name, spec, impls, imports, body, _) do - default = JS.export_default_declaration(JS.identifier(ElixirScript.Module.name_to_js_name(name))) + default = JS.export_default_declaration(JS.identifier(Utils.name_to_js_name(name))) - %JSModule{ + %{ name: name, body: imports ++ body ++ spec ++ impls ++ [default] } @@ -152,7 +155,7 @@ defmodule ElixirScript.Translator.Protocol do { exported_functions, private_functions } end - defp map_to_js({:__aliases__, _, [:Integer]}) do + defp map_to_js({:__aliases__, _, [:Integer]}, _) do JS.member_expression( JS.member_expression( JS.identifier(:Elixir), @@ -162,7 +165,7 @@ defmodule ElixirScript.Translator.Protocol do ) end - defp map_to_js({:__aliases__, _, [:Tuple]}) do + defp map_to_js({:__aliases__, _, [:Tuple]}, _) do JS.member_expression( JS.member_expression( JS.identifier(:Elixir), @@ -172,15 +175,15 @@ defmodule ElixirScript.Translator.Protocol do ) end - defp map_to_js({:__aliases__, _, [:Atom]}) do + defp map_to_js({:__aliases__, _, [:Atom]}, _) do JS.identifier(:Symbol) end - defp map_to_js({:__aliases__, _, [:List]}) do + defp map_to_js({:__aliases__, _, [:List]}, _) do JS.identifier(:Array) end - defp map_to_js({:__aliases__, _, [:BitString]}) do + defp map_to_js({:__aliases__, _, [:BitString]}, _) do JS.member_expression( JS.member_expression( JS.identifier(:Elixir), @@ -190,7 +193,7 @@ defmodule ElixirScript.Translator.Protocol do ) end - defp map_to_js({:__aliases__, _, [:Float]}) do + defp map_to_js({:__aliases__, _, [:Float]}, _) do JS.member_expression( JS.member_expression( JS.identifier(:Elixir), @@ -200,11 +203,11 @@ defmodule ElixirScript.Translator.Protocol do ) end - defp map_to_js({:__aliases__, _, [:Function]}) do + defp map_to_js({:__aliases__, _, [:Function]}, _) do JS.identifier(:Function) end - defp map_to_js({:__aliases__, _, [:PID]}) do + defp map_to_js({:__aliases__, _, [:PID]}, _) do JS.member_expression( JS.member_expression( JS.identifier(:Elixir), @@ -214,33 +217,33 @@ defmodule ElixirScript.Translator.Protocol do ) end - defp map_to_js({:__aliases__, _, [:Port]}) do + defp map_to_js({:__aliases__, _, [:Port]}, _) do JS.member_expression( JS.identifier(:Elixir), JS.identifier(:Port) ) end - defp map_to_js({:__aliases__, _, [:Reference]}) do + defp map_to_js({:__aliases__, _, [:Reference]}, _) do JS.member_expression( JS.identifier(:Elixir), JS.identifier(:Reference) ) end - defp map_to_js({:__aliases__, _, [:Map]}) do + defp map_to_js({:__aliases__, _, [:Map]}, _) do JS.identifier(:Object) end - defp map_to_js({:__aliases__, _, [:Any]}) do + defp map_to_js({:__aliases__, _, [:Any]}, _) do JS.identifier(:null) end - defp map_to_js({:__aliases__, _, _} = module) do + defp map_to_js({:__aliases__, _, _} = module, env) do ElixirScript.Translator.Struct.get_struct_class( module, - ElixirScript.State.get().env + env ) end diff --git a/lib/elixir_script/state.ex b/lib/elixir_script/translator/state.ex similarity index 64% rename from lib/elixir_script/state.ex rename to lib/elixir_script/translator/state.ex index 895fc47d..88ebebe4 100644 --- a/lib/elixir_script/state.ex +++ b/lib/elixir_script/translator/state.ex @@ -1,16 +1,29 @@ -defmodule ElixirScript.State do +defmodule ElixirScript.Translator.State do @moduledoc false + alias ElixirScript.Translator.Utils - def start_link(root, elixir_env \\ __ENV__) do + def start_link(compiler_opts \\ []) do Agent.start_link(fn -> - %{ root: root, elixir_env: elixir_env, modules: Map.new } + %{ compiler_opts: compiler_opts, modules: Map.new, std_lib_map: build_standard_lib_map() } end, name: __MODULE__) end - def update_env(env) do - Agent.update(__MODULE__, fn state -> - %{state | env: env} - end) + defp build_standard_lib_map() do + Map.new + |> Map.put(Kernel, ElixirScript.Kernel) + |> Map.put(Tuple, ElixirScript.Tuple) + |> Map.put(Atom, ElixirScript.Atom) + |> Map.put(Collectable, ElixirScript.Collectable) + |> Map.put(String.Chars, ElixirScript.String.Chars) + |> Map.put(Enumerable, ElixirScript.Enumerable) + |> Map.put(Integer, ElixirScript.Integer) + |> Map.put(Macro.Env, ElixirScript.Macro.Env) + |> Map.put(View, ElixirScript.View) + |> Map.put(Agent, ElixirScript.Agent) + |> Map.put(Range, ElixirScript.Range) + |> Map.put(String, ElixirScript.String) + |> Map.put(Base, ElixirScript.Base) + |> Map.put(Module, ElixirScript.Module) end def add_module(module) do @@ -19,30 +32,12 @@ defmodule ElixirScript.State do end) end - def delete_module(module) do - Agent.update(__MODULE__, fn state -> - %{ state | modules: Map.delete(state.modules, module.name ) } - end) - end - def delete_module_by_name(module_name) do Agent.update(__MODULE__, fn state -> %{ state | modules: Map.delete(state.modules, module_name ) } end) end - def module_listed?(module_name) do - Agent.get(__MODULE__, fn state -> - Map.has_key?(state.modules, module_name) - end) - end - - def protocol_listed?(module_name) do - Agent.get(__MODULE__, fn state -> - Map.has_key?(state.modules, module_name) && Map.get(state.modules, module_name).type == :protocol - end) - end - def add_protocol(name, spec) do Agent.update(__MODULE__, fn state -> proto = do_get_module(state, name) @@ -81,6 +76,15 @@ defmodule ElixirScript.State do Agent.get(__MODULE__, &(&1)) end + def get_module_name(module_name) do + case Map.get(build_standard_lib_map, module_name) do + nil -> + module_name + actual_module_name -> + actual_module_name + end + end + def get_module(module) when is_atom(module) do state = Agent.get(__MODULE__, &(&1)) do_get_module(state, module) @@ -88,47 +92,33 @@ defmodule ElixirScript.State do def get_module({:__aliases__, _, _} = name) do state = Agent.get(__MODULE__, &(&1)) - do_get_module(state, ElixirScript.Module.quoted_to_name(name)) + do_get_module(state, Utils.quoted_to_name(name)) end def get_module(module_name_list) when is_list(module_name_list) do state = Agent.get(__MODULE__, &(&1)) - do_get_module(state, ElixirScript.Module.quoted_to_name({:__aliases__, [], module_name_list})) + do_get_module(state, Utils.quoted_to_name({:__aliases__, [], module_name_list})) end defp do_get_module(state, name) do - name = ElixirScript.Module.get_module_name(name) - Map.get(state.modules, name) - end - - def add_alias(module_name, module_alias) do - module = get_module(module_name) - - if module do - delete_module(module) - module = %{ module | aliases: MapSet.put(module.aliases, {module_alias, module_name}) } - add_module(module) - end + Map.get(state.modules, get_module_name(name)) end def add_module_reference(module_name, module_ref) do module = get_module(module_name) if module do - delete_module(module) module = %{ module | module_refs: Enum.uniq(module.module_refs ++ [module_ref]) } add_module(module) end end def get_module_references(module_name) do - module = get_module(module_name) - - if module do - module.module_refs - |> Enum.uniq - else - [] + case get_module(module_name) do + nil -> + [] + module -> + module.module_refs end end diff --git a/lib/elixir_script/translator/struct.ex b/lib/elixir_script/translator/struct.ex index ed4d7818..b41b6783 100644 --- a/lib/elixir_script/translator/struct.ex +++ b/lib/elixir_script/translator/struct.ex @@ -6,15 +6,15 @@ defmodule ElixirScript.Translator.Struct do alias ElixirScript.Translator.Map def get_struct_class(module_name, env) do - candiate_module_name = ElixirScript.Module.quoted_to_name(module_name) - |> ElixirScript.Module.get_module_name + candiate_module_name = Utils.quoted_to_name(module_name) + |> ElixirScript.Translator.State.get_module_name - if ElixirScript.Env.get_module_name(env, candiate_module_name) in ElixirScript.State.list_module_names() do - name = ElixirScript.Env.get_module_name(env, candiate_module_name) + if ElixirScript.Translator.Env.get_module_name(env, candiate_module_name) in ElixirScript.Translator.State.list_module_names() do + name = ElixirScript.Translator.Env.get_module_name(env, candiate_module_name) JS.member_expression( - JS.identifier(ElixirScript.Module.name_to_js_name(name)), - JS.identifier(ElixirScript.Module.name_to_js_name(name)) + JS.identifier(Utils.name_to_js_name(name)), + JS.identifier(Utils.name_to_js_name(name)) ) else @@ -101,7 +101,7 @@ defmodule ElixirScript.Translator.Struct do defaults = %{ defaults | properties: [struct_name] ++ defaults.properties } - ref = JS.identifier(ElixirScript.Module.name_to_js_name(env.module)) + ref = JS.identifier(Utils.name_to_js_name(env.module)) ref_declarator = JS.variable_declarator( ref, @@ -109,7 +109,10 @@ defmodule ElixirScript.Translator.Struct do JS.member_expression( JS.member_expression( JS.identifier("Elixir"), - JS.identifier("Kernel") + JS.member_expression( + JS.identifier("Core"), + JS.identifier("Functions") + ) ), JS.identifier(name) ), diff --git a/lib/elixir_script/translator/unsupported_error.ex b/lib/elixir_script/translator/unsupported_error.ex new file mode 100644 index 00000000..34bb1b6d --- /dev/null +++ b/lib/elixir_script/translator/unsupported_error.ex @@ -0,0 +1,8 @@ +defmodule ElixirScript.Translator.UnsupportedError do + defexception [:message] + + def exception(value) do + msg = "Currently unsupported #{inspect value}" + %ElixirScript.Translator.UnsupportedError{message: msg} + end +end diff --git a/lib/elixir_script/translator/utils.ex b/lib/elixir_script/translator/utils.ex index 19a29ede..683b2267 100644 --- a/lib/elixir_script/translator/utils.ex +++ b/lib/elixir_script/translator/utils.ex @@ -107,10 +107,39 @@ defmodule ElixirScript.Translator.Utils do end end + def filter_name(:new) do + "__new__" + end + def filter_name(name) do to_string(name) |> String.replace("?", "__qmark__") |> String.replace("!", "__emark__") end + def quoted_to_name(the_alias) do + {name, _} = Code.eval_quoted(the_alias) + name + end + + def name_to_quoted(name) do + name = name + |> Atom.to_string + |> String.split(".") + |> tl + |> Enum.map(fn x -> String.to_atom(x) end) + + { :__aliases__, [], name } + end + + def name_to_js_name(name) do + { :__aliases__, _, name } = name_to_quoted(name) + Enum.join([:Elixir] ++ name, "$") + end + + def name_to_js_file_name(name) do + { :__aliases__, _, name } = name_to_quoted(name) + Enum.join([:Elixir] ++ name, ".") + end + end diff --git a/lib/elixir_script/universal/integer.ex b/lib/elixir_script/universal/integer.ex deleted file mode 100644 index 9ced7e8f..00000000 --- a/lib/elixir_script/universal/integer.ex +++ /dev/null @@ -1,19 +0,0 @@ -defmodule ElixirScript.Integer do - - def is_even(number) do - rem(number, 2) == 0 - end - - def is_odd(number) do - rem(number, 2) != 0 - end - - def to_char_list(number) do - to_char_list(number, 10) - end - - def to_char_list(number, base) do - number.toString(base).split('') - end - -end diff --git a/lib/elixir_script/unsupported_error.ex b/lib/elixir_script/unsupported_error.ex deleted file mode 100644 index cead0820..00000000 --- a/lib/elixir_script/unsupported_error.ex +++ /dev/null @@ -1,8 +0,0 @@ -defmodule ElixirScript.UnsupportedError do - defexception [:message] - - def exception(value) do - msg = "Currently unsupported #{inspect value}" - %ElixirScript.UnsupportedError{message: msg} - end -end \ No newline at end of file diff --git a/priv/Elixir.js b/priv/Elixir.js index d697e731..77b15e0a 100644 --- a/priv/Elixir.js +++ b/priv/Elixir.js @@ -50,7 +50,7 @@ class Process { } } -class Tuple$1 { +class Tuple { constructor(...args) { this.values = Object.freeze(args); @@ -97,9 +97,13 @@ class PID { } } -class Integer$1 {} +class Integer {} class Float {} +function List$1(...args) { + return Object.freeze(args); +} + class ProcessSystem { constructor() { @@ -1033,7 +1037,7 @@ function is_instance_of(value, type) { return value instanceof type; } -function size$3(term) { +function size$2(term) { return term.length; } @@ -1078,7 +1082,7 @@ function is_number$1(x) { } function is_tuple$1(x) { - return x instanceof Tuple$1; + return x instanceof Tuple; } function is_pid$1(x) { @@ -1125,11 +1129,11 @@ function apply$1(...args) { } } -function new_tuple(args) { - return new Tuple$1(...args); +function new_tuple(...args) { + return new Tuple(...args); } -function duplicate$2(data, size) { +function duplicate(data, size) { let array = []; for (var i = size - 1; i >= 0; i--) { @@ -1149,7 +1153,7 @@ function contains(left, right) { return false; } -function reverse$1(list) { +function reverse(list) { return list.concat([]).reverse(); } @@ -1171,49 +1175,124 @@ function prepend_to_list(list, item) { return [item].concat(list); } -get_global().processes = get_global().processes || new ProcessSystem(); +function defstruct(defaults) { + return class { + constructor(update = {}) { + let the_values = Object.assign(defaults, update); + Object.assign(this, the_values); + } + + static create(updates = {}) { + let x = new this(updates); + return Object.freeze(x); + } + }; +} + +function defexception(defaults) { + return class extends Error { + constructor(update = {}) { + let message = update.message || ''; + super(message); + + let the_values = Object.assign(defaults, update); + Object.assign(this, the_values); + + this.name = this.constructor.name; + this.message = message; + this[SpecialForms.atom('__exception__')] = true; + Error.captureStackTrace(this, this.constructor.name); + } + + static create(updates = {}) { + let x = new this(updates); + return Object.freeze(x); + } + }; +} + +function defprotocol(spec) { + return new Protocol(spec); +} + +function defimpl(protocol, type, impl) { + protocol.implementation(type, impl); +} + +function get_object_keys(obj) { + return Object.keys(obj).concat(Object.getOwnPropertySymbols(obj)); +} + +function is_valid_character(codepoint) { + try { + return String.fromCodePoint(codepoint) != null; + } catch (e) { + return false; + } +} + +//https://developer.mozilla.org/en-US/docs/Web/API/WindowBase64/Base64_encoding_and_decoding#Solution_2_%E2%80%93_rewrite_the_DOMs_atob()_and_btoa()_using_JavaScript's_TypedArrays_and_UTF-8 +function b64EncodeUnicode(str) { + return btoa(encodeURIComponent(str).replace(/%([0-9A-F]{2})/g, function (match, p1) { + return String.fromCharCode('0x' + p1); + })); +} + +var Functions = { + call_property, + is_instance_of, + size: size$2, + is_nil: is_nil$1, + is_atom: is_atom$1, + is_binary: is_binary$1, + is_boolean: is_boolean$1, + is_function: is_function$1, + is_float: is_float$1, + is_integer: is_integer$1, + is_list: is_list$1, + is_map: is_map$1, + is_number: is_number$1, + is_tuple: is_tuple$1, + is_pid: is_pid$1, + is_port: is_port$1, + is_reference: is_reference$1, + is_bitstring: is_bitstring$1, + add, + subtract, + multiply, + divide, + remainder, + apply: apply$1, + new_tuple, + duplicate, + contains, + reverse, + get_global, + concat_lists, + prepend_to_list, + defstruct, + defexception, + defprotocol, + defimpl, + get_object_keys, + is_valid_character, + b64EncodeUnicode +}; + +Functions.get_global().processes = Functions.get_global().processes || new ProcessSystem(); var C = Object.freeze({ ProcessSystem: ProcessSystem, - Tuple: Tuple$1, + Tuple: Tuple, PID: PID, BitString: BitString, Patterns: Patterns, - Integer: Integer$1, + Integer: Integer, Float: Float, - call_property: call_property, - is_instance_of: is_instance_of, - size: size$3, - is_nil: is_nil$1, - is_atom: is_atom$1, - is_binary: is_binary$1, - is_boolean: is_boolean$1, - is_function: is_function$1, - is_float: is_float$1, - is_integer: is_integer$1, - is_list: is_list$1, - is_map: is_map$1, - is_number: is_number$1, - is_tuple: is_tuple$1, - is_pid: is_pid$1, - is_port: is_port$1, - is_reference: is_reference$1, - is_bitstring: is_bitstring$1, - add: add, - subtract: subtract, - multiply: multiply, - divide: divide, - remainder: remainder, - apply: apply$1, - new_tuple: new_tuple, - duplicate: duplicate$2, - contains: contains, - reverse: reverse$1, - get_global: get_global, - concat_lists: concat_lists, - prepend_to_list: prepend_to_list + Functions: Functions, + List: List$1 }); let Enum = { @@ -1289,13 +1368,13 @@ let Enum = { fetch: function (collection, n) { if (Kernel.is_list(collection)) { if (n < this.count(collection) && n >= 0) { - return Kernel.SpecialForms.tuple(Kernel.SpecialForms.atom("ok"), collection[n]); + return new Tuple(Symbol.for('ok'), collection[n]); } else { - return Kernel.SpecialForms.atom("error"); + return Symbol.for('error'); } } - throw new Error("collection is not an Enumerable"); + throw new Error('collection is not an Enumerable'); }, fetch__emark__: function (collection, n) { @@ -1303,11 +1382,11 @@ let Enum = { if (n < this.count(collection) && n >= 0) { return collection[n]; } else { - throw new Error("out of bounds error"); + throw new Error('out of bounds error'); } } - throw new Error("collection is not an Enumerable"); + throw new Error('collection is not an Enumerable'); }, filter: function (collection, fun) { @@ -1351,17 +1430,17 @@ let Enum = { }, map_reduce: function (collection, acc, fun) { - let mapped = Kernel.SpecialForms.list(); + let mapped = List$1(); let the_acc = acc; for (var i = 0; i < this.count(collection); i++) { let tuple = fun(collection[i], the_acc); - the_acc = Kernel.elem(tuple, 1); - mapped = Kernel.SpecialForms.list(...mapped.concat([Kernel.elem(tuple, 0)])); + the_acc = tuple.get(1); + mapped = List$1(...mapped.concat([tuple.get(0)])); } - return Kernel.SpecialForms.tuple(mapped, the_acc); + return new Tuple(mapped, the_acc); }, member__qmark__: function (collection, value) { @@ -1374,7 +1453,7 @@ let Enum = { for (var i = 0; i < this.count(collection); i++) { let tuple = fun(collection[i], the_acc); - the_acc = Kernel.elem(tuple, 1); + the_acc = tuple.get(1); } return the_acc; @@ -1394,7 +1473,7 @@ let Enum = { } } - return Kernel.SpecialForms.list(...result); + return List$1(...result); }, take_while: function (collection, fun) { @@ -1416,19 +1495,7 @@ let Enum = { } }; -let SpecialForms = { - - __DIR__: function () { - if (__dirname) { - return __dirname; - } - - if (document.currentScript) { - return document.currentScript.src; - } - - return null; - }, +let SpecialForms$1 = { atom: function (_value) { return Symbol.for(_value); @@ -1534,7 +1601,7 @@ let SpecialForms = { }, tuple: function (...args) { - return new Tuple$1(...args); + return new Tuple(...args); }, _try: function (do_fun, rescue_function, catch_fun, else_function, after_function) { @@ -1591,122 +1658,8 @@ let SpecialForms = { }; -function to_string$1(tuple) { - return tuple.toString(); -}; - -function delete_at(tuple, index) { - let new_list = []; - - for (var i = 0; i < tuple.count(); i++) { - if (i !== index) { - new_list.push(tuple.get(i)); - } - } - - return Kernel.SpecialForms.tuple.apply(null, new_list); -}; - -function duplicate(data, size) { - let array = []; - - for (var i = size - 1; i >= 0; i--) { - array.push(data); - } - - return Kernel.SpecialForms.tuple.apply(null, array); -}; - -function insert_at(tuple, index, term) { - let new_tuple = []; - - for (var i = 0; i <= tuple.count(); i++) { - if (i === index) { - new_tuple.push(term); - i++; - new_tuple.push(tuple.get(i)); - } else { - new_tuple.push(tuple.get(i)); - } - } - - return Kernel.SpecialForms.tuple.apply(null, new_tuple); -}; - -function from_list(list) { - return Kernel.SpecialForms.tuple.apply(null, list); -}; - -function to_list(tuple) { - let new_list = []; - - for (var i = 0; i < tuple.count(); i++) { - new_list.push(tuple.get(i)); - } - - return Kernel.SpecialForms.list(...new_list); -}; - -var Tuple = { - to_string: to_string$1, - delete_at, - duplicate, - insert_at, - from_list, - to_list -}; - -//https://github.com/airportyh/protomorphism -class Protocol { - constructor(spec) { - this.registry = new Map(); - this.fallback = null; - - for (let funName in spec) { - this[funName] = createFun(funName).bind(this); - } - - function createFun(funName) { - - return function (...args) { - let thing = args[0]; - let fun = null; - - if (Number.isInteger(thing) && this.hasImplementation(Integer$1)) { - fun = this.registry.get(Integer$1)[funName]; - } else if (typeof thing === "number" && !Number.isInteger(thing) && this.hasImplementation(Float)) { - fun = this.registry.get(Float)[funName]; - } else if (this.hasImplementation(thing)) { - fun = this.registry.get(thing.constructor)[funName]; - } else if (this.fallback) { - fun = this.fallback[funName]; - } - - if (fun != null) { - let retval = fun.apply(this, args); - return retval; - } - - throw new Error("No implementation found for " + thing); - }; - } - } - - implementation(type, implementation) { - if (type === null) { - this.fallback = implementation; - } else { - this.registry.set(type, implementation); - } - } - - hasImplementation(thing) { - return this.registry.has(thing.constructor); - } -} - function tl(list) { - return SpecialForms.list(...list.slice(1)); + return SpecialForms$1.list(...list.slice(1)); } function hd(list) { @@ -1754,7 +1707,7 @@ function is_number(x) { } function is_tuple(x) { - return x instanceof Tuple$1; + return x instanceof Tuple; } function length(x) { @@ -1839,7 +1792,7 @@ function apply(...args) { function to_string(arg) { if (is_tuple(arg)) { - return Tuple.to_string(arg); + return arg.toString(); } return arg.toString(); @@ -1849,30 +1802,8 @@ function match__qmark__(pattern, expr, guard = () => true) { return Patterns.match_no_throw(pattern, expr, guard) != null; } -function defstruct(defaults) { - return class { - constructor(update = {}) { - let the_values = Object.assign(defaults, update); - Object.assign(this, the_values); - } - - static create(updates = {}) { - let x = new this(updates); - return Object.freeze(x); - } - }; -} - -function defprotocol(spec) { - return new Protocol(spec); -} - -function defimpl(protocol, type, impl) { - protocol.implementation(type, impl); -} - var Kernel = { - SpecialForms, + SpecialForms: SpecialForms$1, tl, hd, is_nil, @@ -1902,331 +1833,11 @@ var Kernel = { not, apply, to_string, - match__qmark__, - defstruct, - defprotocol, - defimpl + match__qmark__ }; -let Atom = {}; - -Atom.to_string = function (atom) { - return Symbol.keyFor(atom); -}; - -Atom.to_char_list = function (atom) { - return Atom.to_string(atom).split(''); -}; - -let Integer = { - - is_even: function (n) { - return n % 2 === 0; - }, - - is_odd: function (n) { - return n % 2 !== 0; - }, - - parse: function (bin) { - let result = parseInt(bin); - - if (isNaN(result)) { - return Kernel.SpecialForms.atom("error"); - } - - let indexOfDot = bin.indexOf("."); - - if (indexOfDot >= 0) { - return Kernel.SpecialForms.tuple(result, bin.substring(indexOfDot)); - } - - return Kernel.SpecialForms.tuple(result, ""); - }, - - to_char_list: function (number, base = 10) { - return number.toString(base).split(""); - }, - - to_string: function (number, base = 10) { - return number.toString(base); - } -}; - -let Chars$1 = Kernel.defprotocol({ - to_string: function (thing) {} -}); - -Kernel.defimpl(Chars$1, BitString, { - to_string: function (thing) { - if (Kernel.is_binary(thing)) { - return thing; - } - - return thing.toString(); - } -}); - -Kernel.defimpl(Chars$1, Symbol, { - to_string: function (thing) { - if (nil) { - return ""; - } - - return Atom.to_string(thing); - } -}); - -Kernel.defimpl(Chars$1, Integer$1, { - to_string: function (thing) { - return Integer.to_string(thing); - } -}); - -Kernel.defimpl(Chars$1, Float, { - to_string: function (thing) { - return thing.toString; - } -}); - -Kernel.defimpl(Chars$1, Array, { - to_string: function (thing) { - return thing.toString(); - } -}); - -Kernel.defimpl(Chars$1, Tuple$1, { - to_string: function (thing) { - return Tuple.to_string(thing); - } -}); - -Kernel.defimpl(Chars$1, null, { - to_string: function (thing) { - return thing.toString(); - } -}); - -function to_atom(string) { - return Symbol.for(string); -} - -function to_existing_atom(string) { - return Symbol.for(string); -} - -function to_char_list(string) { - return string.split(''); -} - -function to_float(string) { - return parseFloat(string); -} - -function to_integer(string, base = 10) { - return parseInt(string, base); -} - -function upcase(binary) { - return binary.toUpperCase(); -} - -function downcase(binary) { - return binary.toLowerCase(); -} - -function at(string, position) { - if (position > string.length - 1) { - return null; - } - - return string[position]; -} - -function capitalize(string) { - let returnString = ''; - - for (let i = 0; i < string.length; i++) { - if (i === 0) { - returnString = returnString + string[i].toUpperCase(); - } else { - returnString = returnString + string[i].toLowerCase(); - } - } - - return returnString; -} - -function codepoints(string) { - return to_char_list(string).map(function (c) { - return c.codePointAt(0); - }); -} - -function contains__qm__(string, contains) { - if (Array.isArray(contains)) { - return contains.some(function (s) { - return string.indexOf(s) > -1; - }); - } - - return string.indexOf(contains) > -1; -} - -function duplicate$1(subject, n) { - return subject.repeat(n); -} - -function ends_with__qm__(string, suffixes) { - if (Array.isArray(suffixes)) { - return suffixes.some(function (s) { - return string.endsWith(s); - }); - } - - return string.endsWith(suffixes); -} - -function first(string) { - if (!string) { - return null; - } - - return string[0]; -} - -function graphemes(string) { - return string.split(''); -} - -function last(string) { - if (!string) { - return null; - } - - return string[string.length - 1]; -} - -function length$1(string) { - return string.length; -} - -function match__qm__(string, regex) { - return string.match(regex) != null; -} - -function next_codepoint(string) { - if (!string || string === '') { - return null; - } - - return Kernel.SpecialForms.tuple(string[0].codePointAt(0), string.substr(1)); -} - -function next_grapheme(string) { - if (!string || string === '') { - return null; - } - - return Kernel.SpecialForms.tuple(string[0], string.substr(1)); -} - -function reverse(string) { - let returnValue = ''; - - for (var i = string.length - 1; i >= 0; i--) { - returnValue = returnValue + string[i]; - }; - - return returnValue; -} - -function split(string) { - return string.split(); -} - -function starts_with__qm__(string, prefixes) { - if (Array.isArray(prefixes)) { - return prefixes.some(function (s) { - return string.startsWith(s); - }); - } - - return string.startsWith(prefixes); -} - -function valid_character__qm__(codepoint) { - try { - return String.fromCodePoint(codepoint) != null; - } catch (e) { - return false; - } -} - -var String$1 = { - at, - capitalize, - codepoints, - contains__qm__, - downcase, - duplicate: duplicate$1, - ends_with__qm__, - first, - graphemes, - last, - length: length$1, - match__qm__, - next_codepoint, - next_grapheme, - reverse, - split, - starts_with__qm__, - to_atom, - to_char_list, - to_existing_atom, - to_float, - to_integer, - upcase, - valid_character__qm__, - Chars: Chars$1 -}; - -let Chars = Kernel.defprotocol({ - to_char_list: function (thing) {} -}); - -Kernel.defimpl(Chars, BitString, { - to_char_list: function (thing) { - if (Kernel.is_binary(thing)) { - return String$1.to_char_list(thing); - } - - return thing.toString(); - } -}); - -Kernel.defimpl(Chars, Symbol, { - to_char_list: function (thing) { - return Atom.to_char_list(thing); - } -}); - -Kernel.defimpl(Chars, Integer$1, { - to_char_list: function (thing) { - return Integer.to_char_list(thing); - } -}); - -Kernel.defimpl(Chars, Array, { - to_char_list: function (thing) { - return thing; - } -}); - let List = {}; -List.Chars = Chars; - List.delete = function (list, item) { let new_value = []; let value_found = false; @@ -2240,7 +1851,7 @@ List.delete = function (list, item) { } } - return Kernel.SpecialForms.list(...new_value); + return List$1(...new_value); }; List.delete_at = function (list, index) { @@ -2252,7 +1863,7 @@ List.delete_at = function (list, index) { } } - return Kernel.SpecialForms.list(...new_value); + return List$1(...new_value); }; List.duplicate = function (elem, n) { @@ -2262,14 +1873,14 @@ List.duplicate = function (elem, n) { new_value.push(elem); } - return Kernel.SpecialForms.list(...new_value); + return List$1(...new_value); }; List.first = function (list) { return list[0]; }; -List.flatten = function (list, tail = Kernel.SpecialForms.list()) { +List.flatten = function (list, tail = List$1()) { let new_value = []; for (let x of list) { @@ -2282,7 +1893,7 @@ List.flatten = function (list, tail = Kernel.SpecialForms.list()) { new_value = new_value.concat(tail); - return Kernel.SpecialForms.list(...new_value); + return List$1(...new_value); }; List.foldl = function (list, acc, func) { @@ -2311,7 +1922,7 @@ List.insert_at = function (list, index, value) { } } - return Kernel.SpecialForms.list(...new_value); + return List$1(...new_value); }; List.keydelete = function (list, key, position) { @@ -2323,7 +1934,7 @@ List.keydelete = function (list, key, position) { } } - return Kernel.SpecialForms.list(...new_list); + return List$1(...new_list); }; List.keyfind = function (list, key, position, _default = null) { @@ -2359,7 +1970,7 @@ List.keyreplace = function (list, key, position, new_tuple) { } } - return Kernel.SpecialForms.list(...new_list); + return List$1(...new_list); }; List.keysort = function (list, position) { @@ -2389,7 +2000,7 @@ List.keysort = function (list, position) { } }); - return Kernel.SpecialForms.list(...new_list); + return List$1(...new_list); }; List.keystore = function (list, key, position, new_tuple) { @@ -2409,7 +2020,7 @@ List.keystore = function (list, key, position, new_tuple) { new_list.push(new_tuple); } - return Kernel.SpecialForms.list(...new_list); + return List$1(...new_list); }; List.last = function (list) { @@ -2427,7 +2038,7 @@ List.replace_at = function (list, index, value) { } } - return Kernel.SpecialForms.list(...new_value); + return List$1(...new_value); }; List.update_at = function (list, index, fun) { @@ -2448,15 +2059,15 @@ List.wrap = function (list) { if (Kernel.is_list(list)) { return list; } else if (list == null) { - return Kernel.SpecialForms.list(); + return List$1(); } else { - return Kernel.SpecialForms.list(list); + return List$1(list); } }; List.zip = function (list_of_lists) { if (list_of_lists.length === 0) { - return Kernel.SpecialForms.list(); + return List$1(); } let new_value = []; @@ -2474,75 +2085,31 @@ List.zip = function (list_of_lists) { current_value.push(list_of_lists[j][i]); } - new_value.push(Kernel.SpecialForms.tuple(...current_value)); + new_value.push(new Tuple(...current_value)); } - return Kernel.SpecialForms.list(...new_value); + return List$1(...new_value); }; List.to_tuple = function (list) { - return Kernel.SpecialForms.tuple.apply(null, list); + return new Tuple(...list); }; List.append = function (list, value) { - return Kernel.SpecialForms.list(...list.concat([value])); + return List$1(...list.concat([value])); }; List.prepend = function (list, value) { - return Kernel.SpecialForms.list(...[value].concat(list)); + return List$1(...[value].concat(list)); }; List.concat = function (left, right) { return left.concat(right); }; -let Range = function (_first, _last) { - if (!(this instanceof Range)) { - return new Range(_first, _last); - } - - this.first = function () { - return _first; - }; - - this.last = function () { - return _last; - }; - - let _range = []; - - for (let i = _first; i <= _last; i++) { - _range.push(i); - } - - _range = Object.freeze(_range); - - this.value = function () { - return _range; - }; - - this.length = function () { - return _range.length; - }; - - return this; -}; - -Range.prototype[Symbol.iterator] = function () { - return this.value()[Symbol.iterator](); -}; - -Range.new = function (first, last) { - return Range(first, last); -}; - -Range.range__qmark__ = function (range) { - return range instanceof Range; -}; - let Keyword = {}; -Keyword.has_key__qm__ = function (keywords, key) { +Keyword.has_key__qmark__ = function (keywords, key) { for (let keyword of keywords) { if (Kernel.elem(keyword, 0) == key) { return true; @@ -2562,75 +2129,6 @@ Keyword.get = function (keywords, key, the_default = null) { return the_default; }; -let Agent = {}; - -Agent.start = function (fun, options = []) { - let pid = self.processes.spawn(); - - if (Keyword.has_key__qm__(options, Kernel.SpecialForms.atom('name'))) { - pid = self.processes.register(Keyword.get(options, Kernel.SpecialForms.atom('name')), pid); - } - - self.processes.put(pid, 'state', fun()); - return Kernel.SpecialForms.tuple(Kernel.SpecialForms.atom('ok'), pid); -}; - -Agent.stop = function (agent, timeout = 5000) { - self.processes.exit(agent); - return Kernel.SpecialForms.atom('ok'); -}; - -Agent.update = function (agent, fun, timeout = 5000) { - - const current_state = self.processes.get(agent, 'state'); - self.processes.put(agent, 'state', fun(current_state)); - - return Kernel.SpecialForms.atom('ok'); -}; - -Agent.get = function (agent, fun, timeout = 5000) { - return fun(self.processes.get(agent, 'state')); -}; - -Agent.get_and_update = function (agent, fun, timeout = 5000) { - - const get_and_update_tuple = fun(self.processes.get(agent, 'state')); - self.processes.put(agent, 'state', Kernel.elem(get_and_update_tuple, 1)); - - return Kernel.elem(get_and_update_tuple, 0); -}; - -//https://developer.mozilla.org/en-US/docs/Web/API/WindowBase64/Base64_encoding_and_decoding#Solution_2_%E2%80%93_rewrite_the_DOMs_atob()_and_btoa()_using_JavaScript's_TypedArrays_and_UTF-8 -function b64EncodeUnicode(str) { - return btoa(encodeURIComponent(str).replace(/%([0-9A-F]{2})/g, function (match, p1) { - return String.fromCharCode('0x' + p1); - })); -} - -function encode64(data) { - return b64EncodeUnicode(data); -} - -function decode64(data) { - try { - return Kernel.SpecialForms.tuple(Kernel.SpecialForms.atom('ok'), atob(data)); - } catch (e) { - return Kernel.SpecialForms.atom('error'); - } - - return btoa(data); -} - -function decode64__em__(data) { - return atob(data); -} - -var base = { - encode64, - decode64, - decode64__em__ -}; - function bnot(expr) { return ~expr; } @@ -2664,41 +2162,27 @@ var bitwise = { bxor }; -let Enumerable = Kernel.defprotocol({ - count: function (collection) {}, - member_qmark__: function (collection, value) {}, - reduce: function (collection, acc, fun) {} -}); - -let Collectable = Kernel.defprotocol({ - into: function (collectable) {} -}); - -let Inspect = Kernel.defprotocol({ - inspect: function (thing, opts) {} -}); - function __new__() { - return SpecialForms.map({}); + return SpecialForms$1.map({}); } function keys(map) { - return Object.keys(map).concat(Object.getOwnPropertySymbols(map)); + return Functions.get_object_keys(map); } function size(map) { return keys(map).length; } -function to_list$1(map) { +function to_list(map) { let map_keys = keys(map); let list = []; for (let key of map_keys) { - list.push(SpecialForms.tuple(key, map[key])); + list.push(new Tuple(key, map[key])); } - return SpecialForms.list(...list); + return List$1(...list); } function values(map) { @@ -2709,14 +2193,14 @@ function values(map) { list.push(map[key]); } - return SpecialForms.list(...list); + return List$1(...list); } function from_struct(struct) { let map = Object.assign({}, struct); - delete map[Symbol.for("__struct__")]; + delete map[Symbol.for('__struct__')]; - return SpecialForms.map(map); + return SpecialForms$1.map(map); } function __delete__(map, key) { @@ -2724,7 +2208,7 @@ function __delete__(map, key) { delete new_map[key]; - return SpecialForms.map(new_map); + return SpecialForms$1.map(new_map); } function equal__qmark__(map1, map2) { @@ -2736,26 +2220,26 @@ function fetch__emark__(map, key) { return map[key]; } - throw new Error("Key not found."); + throw new Error('Key not found.'); } function fetch(map, key) { if (key in map) { - return SpecialForms.tuple(SpecialForms.atom("ok"), map[key]); + return new Tuple(Symbol.for('ok'), map[key]); } - return SpecialForms.atom("error"); + return Symbol.for('error'); } function has_key__qmark__(map, key) { return key in map; } -function split$1(map, keys) { +function split(map, keys) { let split1 = {}; let split2 = {}; - for (let key of Object.keys(map).concat(Object.getOwnPropertySymbols(map))) { + for (let key of Functions.get_object_keys(map)) { if (keys.indexOf(key) > -1) { split1[key] = map[key]; } else { @@ -2763,31 +2247,31 @@ function split$1(map, keys) { } } - return SpecialForms.tuple(SpecialForms.map(split1), SpecialForms.map(split2)); + return new Tuple(SpecialForms$1.map(split1), SpecialForms$1.map(split2)); } function take(map, keys) { let split1 = {}; - for (let key of Object.keys(map).concat(Object.getOwnPropertySymbols(map))) { + for (let key of Functions.get_object_keys(map)) { if (keys.indexOf(key) > -1) { split1[key] = map[key]; } } - return SpecialForms.map(split1); + return SpecialForms$1.map(split1); } function drop(map, keys) { let split1 = {}; - for (let key of Object.keys(map).concat(Object.getOwnPropertySymbols(map))) { + for (let key of Functions.get_object_keys(map)) { if (keys.indexOf(key) === -1) { split1[key] = map[key]; } } - return SpecialForms.map(split1); + return SpecialForms$1.map(split1); } function put_new(map, key, value) { @@ -2798,7 +2282,7 @@ function put_new(map, key, value) { let new_map = Object.assign({}, map); new_map[key] = value; - return SpecialForms.map(new_map); + return SpecialForms$1.map(new_map); } function put_new_lazy(map, key, fun) { @@ -2809,7 +2293,7 @@ function put_new_lazy(map, key, fun) { let new_map = Object.assign({}, map); new_map[key] = fun(); - return SpecialForms.map(new_map); + return SpecialForms$1.map(new_map); } function get_and_update(map, key, fun) { @@ -2820,31 +2304,31 @@ function get_and_update(map, key, fun) { let new_map = Object.assign({}, map); new_map[key] = fun(map[key]); - return SpecialForms.map(new_map); + return SpecialForms$1.map(new_map); } function pop_lazy(map, key, fun) { if (!key in map) { - return SpecialForms.tuple(fun(), map); + return new Tuple(fun(), map); } let new_map = Object.assign({}, map); let value = fun(new_map[key]); delete new_map[key]; - return SpecialForms.tuple(value, new_map); + return new Tuple(value, new_map); } function pop(map, key, _default = null) { if (!key in map) { - return SpecialForms.tuple(_default, map); + return new Tuple(_default, map); } let new_map = Object.assign({}, map); let value = new_map[key]; delete new_map[key]; - return SpecialForms.tuple(value, new_map); + return new Tuple(value, new_map); } function get_lazy(map, key, fun) { @@ -2867,18 +2351,18 @@ function put(map, key, val) { let new_map = Object({}, map); new_map[key] = val; - return SpecialForms.map(new_map); + return SpecialForms$1.map(new_map); } function update__emark__(map, key, fun) { if (!key in map) { - throw new Error("Key not found"); + throw new Error('Key not found'); } let new_map = Object({}, map); new_map[key] = fun(map[key]); - return SpecialForms.map(new_map); + return SpecialForms$1.map(new_map); } function update(map, key, initial, fun) { @@ -2890,14 +2374,14 @@ function update(map, key, initial, fun) { new_map[key] = fun(map[key]); } - return SpecialForms.map(new_map); + return SpecialForms$1.map(new_map); } var map = { new: __new__, keys, size, - to_list: to_list$1, + to_list, values, from_struct, delete: __delete__, @@ -2906,7 +2390,7 @@ var map = { fetch__emark__, fetch, has_key__qmark__, - split: split$1, + split, take, put_new, put_new_lazy, @@ -2921,74 +2405,74 @@ var map = { }; function __new__$1() { - return SpecialForms.map({ [Symbol.for('__struct__')]: Symbol.for('MapSet'), set: SpecialForms.list() }); + return SpecialForms$1.map({ [Symbol.for('__struct__')]: Symbol.for('MapSet'), set: List$1() }); } -function size$2(map) { +function size$1(map) { return map.set.length; } -function to_list$3(map) { +function to_list$1(map) { return map.set; } -function __delete__$2(set, term) { +function __delete__$1(set, term) { let new_list = List.delete(set.set, term); let new_map = Object.assign({}, set); new_map.set = new_list; - return SpecialForms.map(new_map); + return SpecialForms$1.map(new_map); } -function put$2(set, term) { +function put$1(set, term) { if (set.set.indexOf(term) === -1) { let new_list = List.append(set.set, term); let new_map = Object.assign({}, set); new_map.set = new_list; - return SpecialForms.map(new_map); + return SpecialForms$1.map(new_map); } return set; } -function difference$1(set1, set2) { +function difference(set1, set2) { let new_map = Object.assign({}, set1); for (let val of set1.set) { - if (member__qmark__$1(set2, val)) { + if (member__qmark__(set2, val)) { new_map.set = List.delete(new_map.set, val); } } - return SpecialForms.map(new_map); + return SpecialForms$1.map(new_map); } -function intersection$1(set1, set2) { +function intersection(set1, set2) { let new_map = Object.assign({}, set1); for (let val of set1.set) { - if (!member__qmark__$1(set2, val)) { + if (!member__qmark__(set2, val)) { new_map.set = List.delete(new_map.set, val); } } - return SpecialForms.map(new_map); + return SpecialForms$1.map(new_map); } -function union$1(set1, set2) { +function union(set1, set2) { let new_map = set1; for (let val of set2.set) { - new_map = put$2(new_map, val); + new_map = put$1(new_map, val); } - return SpecialForms.map(new_map); + return SpecialForms$1.map(new_map); } -function disjoin__qmark__$1(set1, set2) { +function disjoin__qmark__(set1, set2) { for (let val of set1.set) { - if (member__qmark__$1(set2, val)) { + if (member__qmark__(set2, val)) { return false; } } @@ -2996,17 +2480,17 @@ function disjoin__qmark__$1(set1, set2) { return true; } -function member__qmark__$1(set, value) { +function member__qmark__(set, value) { return set.set.indexOf(value) >= 0; } -function equal__qmark__$2(set1, set2) { +function equal__qmark__$1(set1, set2) { return set1.set === set2.set; } -function subset__qmark__$1(set1, set2) { +function subset__qmark__(set1, set2) { for (let val of set1.set) { - if (!member__qmark__$1(set2, val)) { + if (!member__qmark__(set2, val)) { return false; } } @@ -3014,68 +2498,10 @@ function subset__qmark__$1(set1, set2) { return true; } -var MapSet = { +var map_set = { new: __new__$1, - size: size$2, - to_list: to_list$3, - disjoin__qmark__: disjoin__qmark__$1, - delete: __delete__$2, - subset__qmark__: subset__qmark__$1, - equal__qmark__: equal__qmark__$2, - member__qmark__: member__qmark__$1, - put: put$2, - union: union$1, - intersection: intersection$1, - difference: difference$1 -}; - -function size$1(map) { - return MapSet.size(map); -} - -function to_list$2(map) { - return MapSet.to_list(map); -} - -function __delete__$1(set, term) { - return MapSet.delete(set, term); -} - -function put$1(set, term) { - return MapSet.put(set, term); -} - -function difference(set1, set2) { - return MapSet.difference(set1, set2); -} - -function intersection(set1, set2) { - return MapSet.intersection(set1, set2); -} - -function union(set1, set2) { - return MapSet.union(set1, set2); -} - -function disjoin__qmark__(set1, set2) { - return MapSet.disjoin__qmark__(set1, set2); -} - -function member__qmark__(set, value) { - return MapSet.member__qmark__(set1, set2); -} - -function equal__qmark__$1(set1, set2) { - return MapSet.equal__qmark__(set1, set2); -} - -function subset__qmark__(set1, set2) { - return MapSet.subset__qmark__(set1, set2); -} - -var set = { size: size$1, - to_list: to_list$2, + to_list: to_list$1, disjoin__qmark__, delete: __delete__$1, subset__qmark__, @@ -4694,52 +4120,7 @@ let VirtualDOM = (function (e) { }, { "../vnode/handle-thunk": 24, "../vnode/is-thunk": 25, "../vnode/is-vnode": 27, "../vnode/is-vtext": 28, "../vnode/is-widget": 29, "../vnode/vpatch": 32, "./diff-props": 34, "x-is-array": 12 }] }, {}, [4])(4); }); -const start = function (domRoot, renderFn, initialState, options = []) { - let pid = self.processes.spawn(); - - if (Keyword.has_key__qm__(options, Kernel.SpecialForms.atom('name'))) { - pid = self.processes.register(Keyword.get(options, Kernel.SpecialForms.atom('name')), pid); - } - - const tree = renderFn.apply(this, initialState); - const rootNode = VirtualDOM.create(tree); - - domRoot.appendChild(rootNode); - - self.processes.put(pid, 'state', Kernel.SpecialForms.tuple(rootNode, tree, renderFn)); - return Kernel.SpecialForms.tuple(Kernel.SpecialForms.atom('ok'), pid); -}; - -const stop = function (agent, timeout = 5000) { - self.processes.exit(agent); - return Kernel.SpecialForms.atom('ok'); -}; - -const render = function (agent, state) { - - const current_state = self.processes.get(agent, 'state'); - - let rootNode = Kernel.elem(current_state, 0); - let tree = Kernel.elem(current_state, 1); - let renderFn = Kernel.elem(current_state, 2); - - let newTree = renderFn.apply(this, state); - - let patches = VirtualDOM.diff(tree, newTree); - rootNode = VirtualDOM.patch(rootNode, patches); - - self.processes.put(agent, 'state', Kernel.SpecialForms.tuple(rootNode, newTree, renderFn)); - - return Kernel.SpecialForms.atom('ok'); -}; - -var view = { - start, - stop, - render -}; - const Core = C; -export { Core, Kernel, Atom, Enum, Integer, List, Range, Tuple, Agent, Keyword, base as Base, String$1 as String, bitwise as Bitwise, Enumerable, Collectable, Inspect, map as Map, set as Set, MapSet, VirtualDOM, view as View }; -//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiIiwic291cmNlcyI6WyJFbGl4aXIuanMiXSwic291cmNlc0NvbnRlbnQiOlsiLyogQGZsb3cgKi9cblxuY2xhc3MgTWFpbGJveCB7XG5cbiAgY29uc3RydWN0b3IoKSB7XG4gICAgdGhpcy5tZXNzYWdlcyA9IFtdO1xuICB9XG5cbiAgZGVsaXZlcihtZXNzYWdlKSB7XG4gICAgdGhpcy5tZXNzYWdlcy5wdXNoKG1lc3NhZ2UpO1xuICAgIHJldHVybiBtZXNzYWdlO1xuICB9XG5cbiAgZ2V0KCkge1xuICAgIHJldHVybiB0aGlzLm1lc3NhZ2VzO1xuICB9XG5cbiAgaXNFbXB0eSgpIHtcbiAgICByZXR1cm4gdGhpcy5tZXNzYWdlcy5sZW5ndGggPT09IDA7XG4gIH1cblxuICByZW1vdmVBdChpbmRleCkge1xuICAgIHRoaXMubWVzc2FnZXMuc3BsaWNlKGluZGV4LCAxKTtcbiAgfVxufVxuXG52YXIgU3RhdGVzID0ge1xuICBOT1JNQUw6IFN5bWJvbC5mb3IoXCJub3JtYWxcIiksXG4gIEtJTEw6IFN5bWJvbC5mb3IoXCJraWxsXCIpLFxuICBTVVNQRU5EOiBTeW1ib2wuZm9yKFwic3VzcGVuZFwiKSxcbiAgQ09OVElOVUU6IFN5bWJvbC5mb3IoXCJjb250aW51ZVwiKSxcbiAgUkVDRUlWRTogU3ltYm9sLmZvcihcInJlY2VpdmVcIiksXG4gIFNFTkQ6IFN5bWJvbC5mb3IoXCJzZW5kXCIpLFxuICBTTEVFUElORzogU3ltYm9sLmZvcihcInNsZWVwaW5nXCIpLFxuICBSVU5OSU5HOiBTeW1ib2wuZm9yKFwicnVubmluZ1wiKSxcbiAgU1VTUEVOREVEOiBTeW1ib2wuZm9yKFwic3VzcGVuZGVkXCIpLFxuICBTVE9QUEVEOiBTeW1ib2wuZm9yKFwic3RvcHBlZFwiKSxcbiAgU0xFRVA6IFN5bWJvbC5mb3IoXCJzbGVlcFwiKSxcbiAgRVhJVDogU3ltYm9sLmZvcihcImV4aXRcIiksXG4gIE5PTUFUQ0g6IFN5bWJvbC5mb3IoXCJub19tYXRjaFwiKVxufTtcblxuY2xhc3MgUHJvY2VzcyB7XG5cbiAgY29uc3RydWN0b3IocGlkLCBtYWlsYm94KSB7XG4gICAgdGhpcy5waWQgPSBwaWQ7XG4gICAgdGhpcy5tYWlsYm94ID0gbWFpbGJveDtcbiAgICB0aGlzLnN0YXR1cyA9IFN0YXRlcy5TVE9QUEVEO1xuICAgIHRoaXMuZGljdCA9IHt9O1xuICB9XG59XG5cbmNsYXNzIFR1cGxlJDEge1xuXG4gIGNvbnN0cnVjdG9yKC4uLmFyZ3MpIHtcbiAgICB0aGlzLnZhbHVlcyA9IE9iamVjdC5mcmVlemUoYXJncyk7XG4gICAgdGhpcy5sZW5ndGggPSB0aGlzLnZhbHVlcy5sZW5ndGg7XG4gIH1cblxuICBnZXQoaW5kZXgpIHtcbiAgICByZXR1cm4gdGhpcy52YWx1ZXNbaW5kZXhdO1xuICB9XG5cbiAgY291bnQoKSB7XG4gICAgcmV0dXJuIHRoaXMudmFsdWVzLmxlbmd0aDtcbiAgfVxuXG4gIFtTeW1ib2wuaXRlcmF0b3JdKCkge1xuICAgIHJldHVybiB0aGlzLnZhbHVlc1tTeW1ib2wuaXRlcmF0b3JdKCk7XG4gIH1cblxuICB0b1N0cmluZygpIHtcbiAgICB2YXIgaSxcbiAgICAgICAgcyA9IFwiXCI7XG4gICAgZm9yIChpID0gMDsgaSA8IHRoaXMudmFsdWVzLmxlbmd0aDsgaSsrKSB7XG4gICAgICBpZiAocyAhPT0gXCJcIikge1xuICAgICAgICBzICs9IFwiLCBcIjtcbiAgICAgIH1cbiAgICAgIHMgKz0gdGhpcy52YWx1ZXNbaV0udG9TdHJpbmcoKTtcbiAgICB9XG5cbiAgICByZXR1cm4gXCJ7XCIgKyBzICsgXCJ9XCI7XG4gIH1cblxufVxuXG5sZXQgcHJvY2Vzc19jb3VudGVyID0gLTE7XG5cbmNsYXNzIFBJRCB7XG4gIGNvbnN0cnVjdG9yKCkge1xuICAgIHByb2Nlc3NfY291bnRlciA9IHByb2Nlc3NfY291bnRlciArIDE7XG4gICAgdGhpcy5pZCA9IHByb2Nlc3NfY291bnRlcjtcbiAgfVxuXG4gIHRvU3RyaW5nKCkge1xuICAgIHJldHVybiBcIlBJRCM8MC5cIiArIHRoaXMuaWQgKyBcIi4wPlwiO1xuICB9XG59XG5cbmNsYXNzIEludGVnZXIkMSB7fVxuY2xhc3MgRmxvYXQge31cblxuY2xhc3MgUHJvY2Vzc1N5c3RlbSB7XG5cbiAgY29uc3RydWN0b3IoKSB7XG4gICAgdGhpcy5waWRzID0gbmV3IE1hcCgpO1xuICAgIHRoaXMubWFpbGJveGVzID0gbmV3IE1hcCgpO1xuICAgIHRoaXMubmFtZXMgPSBuZXcgTWFwKCk7XG4gICAgdGhpcy5saW5rcyA9IG5ldyBNYXAoKTtcblxuICAgIHRoaXMuY3VycmVudF9wcm9jZXNzID0gbnVsbDtcbiAgICB0aGlzLnN1c3BlbmRlZCA9IG5ldyBNYXAoKTtcblxuICAgIHRoaXMubWFpbl9wcm9jZXNzX3BpZCA9IHRoaXMuc3Bhd24oKTtcbiAgICB0aGlzLnNldF9jdXJyZW50KHRoaXMubWFpbl9wcm9jZXNzX3BpZCk7XG4gIH1cblxuICBzcGF3bigpIHtcbiAgICByZXR1cm4gdGhpcy5hZGRfcHJvYyhmYWxzZSkucGlkO1xuICB9XG5cbiAgc3Bhd25fbGluaygpIHtcbiAgICByZXR1cm4gdGhpcy5hZGRfcHJvYyh0cnVlKS5waWQ7XG4gIH1cblxuICBsaW5rKHBpZCkge1xuICAgIHRoaXMubGlua3MuZ2V0KHRoaXMucGlkKCkpLmFkZChwaWQpO1xuICAgIHRoaXMubGlua3MuZ2V0KHBpZCkuYWRkKHRoaXMucGlkKCkpO1xuICB9XG5cbiAgdW5saW5rKHBpZCkge1xuICAgIHRoaXMubGlua3MuZ2V0KHRoaXMucGlkKCkpLmRlbGV0ZShwaWQpO1xuICAgIHRoaXMubGlua3MuZ2V0KHBpZCkuZGVsZXRlKHRoaXMucGlkKCkpO1xuICB9XG5cbiAgc2V0X2N1cnJlbnQoaWQpIHtcbiAgICBsZXQgcGlkID0gdGhpcy5waWRvZihpZCk7XG4gICAgaWYgKHBpZCAhPT0gbnVsbCkge1xuICAgICAgdGhpcy5jdXJyZW50X3Byb2Nlc3MgPSB0aGlzLnBpZHMuZ2V0KHBpZCk7XG4gICAgICB0aGlzLmN1cnJlbnRfcHJvY2Vzcy5zdGF0dXMgPSBTdGF0ZXMuUlVOTklORztcbiAgICB9XG4gIH1cblxuICBhZGRfcHJvYyhsaW5rZWQpIHtcbiAgICBsZXQgbmV3cGlkID0gbmV3IFBJRCgpO1xuICAgIGxldCBtYWlsYm94ID0gbmV3IE1haWxib3goKTtcbiAgICBsZXQgbmV3cHJvYyA9IG5ldyBQcm9jZXNzKG5ld3BpZCwgbWFpbGJveCk7XG5cbiAgICB0aGlzLnBpZHMuc2V0KG5ld3BpZCwgbmV3cHJvYyk7XG4gICAgdGhpcy5tYWlsYm94ZXMuc2V0KG5ld3BpZCwgbWFpbGJveCk7XG4gICAgdGhpcy5saW5rcy5zZXQobmV3cGlkLCBuZXcgU2V0KCkpO1xuXG4gICAgaWYgKGxpbmtlZCkge1xuICAgICAgdGhpcy5saW5rKG5ld3BpZCk7XG4gICAgfVxuXG4gICAgcmV0dXJuIG5ld3Byb2M7XG4gIH1cblxuICByZW1vdmVfcHJvYyhwaWQpIHtcbiAgICB0aGlzLnBpZHMuZGVsZXRlKHBpZCk7XG4gICAgdGhpcy51bnJlZ2lzdGVyKHBpZCk7XG5cbiAgICBpZiAodGhpcy5saW5rcy5oYXMocGlkKSkge1xuICAgICAgZm9yIChsZXQgbGlua3BpZCBvZiB0aGlzLmxpbmtzLmdldChwaWQpKSB7XG4gICAgICAgIHRoaXMubGlua3MuZ2V0KGxpbmtwaWQpLmRlbGV0ZShwaWQpO1xuICAgICAgfVxuXG4gICAgICB0aGlzLmxpbmtzLmRlbGV0ZShwaWQpO1xuICAgIH1cbiAgfVxuXG4gIGV4aXQoaWQpIHtcbiAgICBsZXQgcGlkID0gdGhpcy5waWRvZihpZCk7XG4gICAgdGhpcy5yZW1vdmVfcHJvYyhpZCk7XG4gIH1cblxuICByZWdpc3RlcihuYW1lLCBwaWQpIHtcbiAgICBpZiAoIXRoaXMubmFtZXMuaGFzKG5hbWUpKSB7XG4gICAgICB0aGlzLm5hbWVzLnNldChuYW1lLCBwaWQpO1xuICAgICAgcmV0dXJuIG5hbWU7XG4gICAgfSBlbHNlIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcihcIk5hbWUgaXMgYWxyZWFkeSByZWdpc3RlcmVkIHRvIGFub3RoZXIgcHJvY2Vzc1wiKTtcbiAgICB9XG4gIH1cblxuICByZWdpc3RlcmVkKG5hbWUpIHtcbiAgICByZXR1cm4gdGhpcy5uYW1lcy5oYXMobmFtZSkgPyB0aGlzLm5hbWVzLmdldChuYW1lKSA6IG51bGw7XG4gIH1cblxuICB1bnJlZ2lzdGVyKHBpZCkge1xuICAgIGZvciAobGV0IG5hbWUgb2YgdGhpcy5uYW1lcy5rZXlzKCkpIHtcbiAgICAgIGlmICh0aGlzLm5hbWVzLmhhcyhuYW1lKSAmJiB0aGlzLm5hbWVzLmdldChuYW1lKSA9PT0gcGlkKSB7XG4gICAgICAgIHRoaXMubmFtZXMuZGVsZXRlKG5hbWUpO1xuICAgICAgfVxuICAgIH1cbiAgfVxuXG4gIHBpZCgpIHtcbiAgICByZXR1cm4gdGhpcy5jdXJyZW50X3Byb2Nlc3MucGlkO1xuICB9XG5cbiAgcGlkb2YoaWQpIHtcbiAgICBpZiAoaWQgaW5zdGFuY2VvZiBQSUQpIHtcbiAgICAgIHJldHVybiB0aGlzLnBpZHMuaGFzKGlkKSA/IGlkIDogbnVsbDtcbiAgICB9IGVsc2UgaWYgKGlkIGluc3RhbmNlb2YgUHJvY2Vzcykge1xuICAgICAgcmV0dXJuIGlkLnBpZDtcbiAgICB9IGVsc2Uge1xuICAgICAgbGV0IHBpZCA9IHRoaXMucmVnaXN0ZXJlZChpZCk7XG4gICAgICBpZiAocGlkID09PSBudWxsKSB0aHJvdyBcIlByb2Nlc3MgbmFtZSBub3QgcmVnaXN0ZXJlZDogXCIgKyBpZCArIFwiIChcIiArIHR5cGVvZiBpZCArIFwiKVwiO1xuICAgICAgcmV0dXJuIHBpZDtcbiAgICB9XG4gIH1cblxuICBwdXQoaWQsIGtleSwgdmFsdWUpIHtcbiAgICBsZXQgcGlkID0gdGhpcy5waWRvZihpZCk7XG4gICAgbGV0IHByb2Nlc3MgPSB0aGlzLnBpZHMuZ2V0KHBpZCk7XG4gICAgcHJvY2Vzcy5kaWN0W2tleV0gPSB2YWx1ZTtcbiAgfVxuXG4gIGdldChpZCwga2V5KSB7XG4gICAgbGV0IHBpZCA9IHRoaXMucGlkb2YoaWQpO1xuICAgIGxldCBwcm9jZXNzID0gdGhpcy5waWRzLmdldChwaWQpO1xuXG4gICAgaWYgKGtleSAhPSBudWxsKSB7XG4gICAgICByZXR1cm4gcHJvY2Vzcy5kaWN0W2tleV07XG4gICAgfSBlbHNlIHtcbiAgICAgIHJldHVybiBwcm9jZXNzLmRpY3Q7XG4gICAgfVxuICB9XG5cbiAgZ2V0X2tleXMoaWQpIHtcbiAgICBsZXQgcGlkID0gdGhpcy5waWRvZihpZCk7XG4gICAgbGV0IHByb2Nlc3MgPSB0aGlzLnBpZHMuZ2V0KHBpZCk7XG5cbiAgICByZXR1cm4gT2JqZWN0LmtleXMocHJvY2Vzcy5kaWN0KTtcbiAgfVxuXG4gIGVyYXNlKGlkLCBrZXkpIHtcbiAgICBsZXQgcGlkID0gdGhpcy5waWRvZihpZCk7XG4gICAgbGV0IHByb2Nlc3MgPSB0aGlzLnBpZHMuZ2V0KHBpZCk7XG5cbiAgICBpZiAoa2V5ICE9IG51bGwpIHtcbiAgICAgIGRlbGV0ZSBwcm9jZXNzLmRpY3Rba2V5XTtcbiAgICB9IGVsc2Uge1xuICAgICAgcHJvY2Vzcy5kaWN0ID0ge307XG4gICAgfVxuICB9XG59XG5cbmNsYXNzIEJpdFN0cmluZyB7XG4gIGNvbnN0cnVjdG9yKC4uLmFyZ3MpIHtcbiAgICB0aGlzLnJhd192YWx1ZSA9IGZ1bmN0aW9uICgpIHtcbiAgICAgIHJldHVybiBPYmplY3QuZnJlZXplKGFyZ3MpO1xuICAgIH07XG5cbiAgICB0aGlzLnZhbHVlID0gT2JqZWN0LmZyZWV6ZSh0aGlzLnByb2Nlc3MoYXJncykpO1xuICB9XG5cbiAgZ2V0KGluZGV4KSB7XG4gICAgcmV0dXJuIHRoaXMudmFsdWVbaW5kZXhdO1xuICB9XG5cbiAgY291bnQoKSB7XG4gICAgcmV0dXJuIHRoaXMudmFsdWUubGVuZ3RoO1xuICB9XG5cbiAgW1N5bWJvbC5pdGVyYXRvcl0oKSB7XG4gICAgcmV0dXJuIHRoaXMudmFsdWVbU3ltYm9sLml0ZXJhdG9yXSgpO1xuICB9XG5cbiAgdG9TdHJpbmcoKSB7XG4gICAgdmFyIGksXG4gICAgICAgIHMgPSBcIlwiO1xuICAgIGZvciAoaSA9IDA7IGkgPCB0aGlzLmNvdW50KCk7IGkrKykge1xuICAgICAgaWYgKHMgIT09IFwiXCIpIHtcbiAgICAgICAgcyArPSBcIiwgXCI7XG4gICAgICB9XG4gICAgICBzICs9IHRoaXNbaV0udG9TdHJpbmcoKTtcbiAgICB9XG5cbiAgICByZXR1cm4gXCI8PFwiICsgcyArIFwiPj5cIjtcbiAgfVxuXG4gIHByb2Nlc3MoKSB7XG4gICAgbGV0IHByb2Nlc3NlZF92YWx1ZXMgPSBbXTtcblxuICAgIHZhciBpO1xuICAgIGZvciAoaSA9IDA7IGkgPCB0aGlzLnJhd192YWx1ZSgpLmxlbmd0aDsgaSsrKSB7XG4gICAgICBsZXQgcHJvY2Vzc2VkX3ZhbHVlID0gdGhpc1tcInByb2Nlc3NfXCIgKyB0aGlzLnJhd192YWx1ZSgpW2ldLnR5cGVdKHRoaXMucmF3X3ZhbHVlKClbaV0pO1xuXG4gICAgICBmb3IgKGxldCBhdHRyIG9mIHRoaXMucmF3X3ZhbHVlKClbaV0uYXR0cmlidXRlcykge1xuICAgICAgICBwcm9jZXNzZWRfdmFsdWUgPSB0aGlzW1wicHJvY2Vzc19cIiArIGF0dHJdKHByb2Nlc3NlZF92YWx1ZSk7XG4gICAgICB9XG5cbiAgICAgIHByb2Nlc3NlZF92YWx1ZXMgPSBwcm9jZXNzZWRfdmFsdWVzLmNvbmNhdChwcm9jZXNzZWRfdmFsdWUpO1xuICAgIH1cblxuICAgIHJldHVybiBwcm9jZXNzZWRfdmFsdWVzO1xuICB9XG5cbiAgcHJvY2Vzc19pbnRlZ2VyKHZhbHVlKSB7XG4gICAgcmV0dXJuIHZhbHVlLnZhbHVlO1xuICB9XG5cbiAgcHJvY2Vzc19mbG9hdCh2YWx1ZSkge1xuICAgIGlmICh2YWx1ZS5zaXplID09PSA2NCkge1xuICAgICAgcmV0dXJuIEJpdFN0cmluZy5mbG9hdDY0VG9CeXRlcyh2YWx1ZS52YWx1ZSk7XG4gICAgfSBlbHNlIGlmICh2YWx1ZS5zaXplID09PSAzMikge1xuICAgICAgcmV0dXJuIEJpdFN0cmluZy5mbG9hdDMyVG9CeXRlcyh2YWx1ZS52YWx1ZSk7XG4gICAgfVxuXG4gICAgdGhyb3cgbmV3IEVycm9yKFwiSW52YWxpZCBzaXplIGZvciBmbG9hdFwiKTtcbiAgfVxuXG4gIHByb2Nlc3NfYml0c3RyaW5nKHZhbHVlKSB7XG4gICAgcmV0dXJuIHZhbHVlLnZhbHVlLnZhbHVlO1xuICB9XG5cbiAgcHJvY2Vzc19iaW5hcnkodmFsdWUpIHtcbiAgICByZXR1cm4gQml0U3RyaW5nLnRvVVRGOEFycmF5KHZhbHVlLnZhbHVlKTtcbiAgfVxuXG4gIHByb2Nlc3NfdXRmOCh2YWx1ZSkge1xuICAgIHJldHVybiBCaXRTdHJpbmcudG9VVEY4QXJyYXkodmFsdWUudmFsdWUpO1xuICB9XG5cbiAgcHJvY2Vzc191dGYxNih2YWx1ZSkge1xuICAgIHJldHVybiBCaXRTdHJpbmcudG9VVEYxNkFycmF5KHZhbHVlLnZhbHVlKTtcbiAgfVxuXG4gIHByb2Nlc3NfdXRmMzIodmFsdWUpIHtcbiAgICByZXR1cm4gQml0U3RyaW5nLnRvVVRGMzJBcnJheSh2YWx1ZS52YWx1ZSk7XG4gIH1cblxuICBwcm9jZXNzX3NpZ25lZCh2YWx1ZSkge1xuICAgIHJldHVybiBuZXcgVWludDhBcnJheShbdmFsdWVdKVswXTtcbiAgfVxuXG4gIHByb2Nlc3NfdW5zaWduZWQodmFsdWUpIHtcbiAgICByZXR1cm4gdmFsdWU7XG4gIH1cblxuICBwcm9jZXNzX25hdGl2ZSh2YWx1ZSkge1xuICAgIHJldHVybiB2YWx1ZTtcbiAgfVxuXG4gIHByb2Nlc3NfYmlnKHZhbHVlKSB7XG4gICAgcmV0dXJuIHZhbHVlO1xuICB9XG5cbiAgcHJvY2Vzc19saXR0bGUodmFsdWUpIHtcbiAgICByZXR1cm4gdmFsdWUucmV2ZXJzZSgpO1xuICB9XG5cbiAgcHJvY2Vzc19zaXplKHZhbHVlKSB7XG4gICAgcmV0dXJuIHZhbHVlO1xuICB9XG5cbiAgcHJvY2Vzc191bml0KHZhbHVlKSB7XG4gICAgcmV0dXJuIHZhbHVlO1xuICB9XG5cbiAgc3RhdGljIGludGVnZXIodmFsdWUpIHtcbiAgICByZXR1cm4gQml0U3RyaW5nLndyYXAodmFsdWUsIHsgXCJ0eXBlXCI6IFwiaW50ZWdlclwiLCBcInVuaXRcIjogMSwgXCJzaXplXCI6IDggfSk7XG4gIH1cblxuICBzdGF0aWMgZmxvYXQodmFsdWUpIHtcbiAgICByZXR1cm4gQml0U3RyaW5nLndyYXAodmFsdWUsIHsgXCJ0eXBlXCI6IFwiZmxvYXRcIiwgXCJ1bml0XCI6IDEsIFwic2l6ZVwiOiA2NCB9KTtcbiAgfVxuXG4gIHN0YXRpYyBiaXRzdHJpbmcodmFsdWUpIHtcbiAgICByZXR1cm4gQml0U3RyaW5nLndyYXAodmFsdWUsIHsgXCJ0eXBlXCI6IFwiYml0c3RyaW5nXCIsIFwidW5pdFwiOiAxLCBcInNpemVcIjogdmFsdWUubGVuZ3RoIH0pO1xuICB9XG5cbiAgc3RhdGljIGJpdHModmFsdWUpIHtcbiAgICByZXR1cm4gQml0U3RyaW5nLmJpdHN0cmluZyh2YWx1ZSk7XG4gIH1cblxuICBzdGF0aWMgYmluYXJ5KHZhbHVlKSB7XG4gICAgcmV0dXJuIEJpdFN0cmluZy53cmFwKHZhbHVlLCB7IFwidHlwZVwiOiBcImJpbmFyeVwiLCBcInVuaXRcIjogOCwgXCJzaXplXCI6IHZhbHVlLmxlbmd0aCB9KTtcbiAgfVxuXG4gIHN0YXRpYyBieXRlcyh2YWx1ZSkge1xuICAgIHJldHVybiBCaXRTdHJpbmcuYmluYXJ5KHZhbHVlKTtcbiAgfVxuXG4gIHN0YXRpYyB1dGY4KHZhbHVlKSB7XG4gICAgcmV0dXJuIEJpdFN0cmluZy53cmFwKHZhbHVlLCB7IFwidHlwZVwiOiBcInV0ZjhcIiB9KTtcbiAgfVxuXG4gIHN0YXRpYyB1dGYxNih2YWx1ZSkge1xuICAgIHJldHVybiBCaXRTdHJpbmcud3JhcCh2YWx1ZSwgeyBcInR5cGVcIjogXCJ1dGYxNlwiIH0pO1xuICB9XG5cbiAgc3RhdGljIHV0ZjMyKHZhbHVlKSB7XG4gICAgcmV0dXJuIEJpdFN0cmluZy53cmFwKHZhbHVlLCB7IFwidHlwZVwiOiBcInV0ZjMyXCIgfSk7XG4gIH1cblxuICBzdGF0aWMgc2lnbmVkKHZhbHVlKSB7XG4gICAgcmV0dXJuIEJpdFN0cmluZy53cmFwKHZhbHVlLCB7fSwgXCJzaWduZWRcIik7XG4gIH1cblxuICBzdGF0aWMgdW5zaWduZWQodmFsdWUpIHtcbiAgICByZXR1cm4gQml0U3RyaW5nLndyYXAodmFsdWUsIHt9LCBcInVuc2lnbmVkXCIpO1xuICB9XG5cbiAgc3RhdGljIG5hdGl2ZSh2YWx1ZSkge1xuICAgIHJldHVybiBCaXRTdHJpbmcud3JhcCh2YWx1ZSwge30sIFwibmF0aXZlXCIpO1xuICB9XG5cbiAgc3RhdGljIGJpZyh2YWx1ZSkge1xuICAgIHJldHVybiBCaXRTdHJpbmcud3JhcCh2YWx1ZSwge30sIFwiYmlnXCIpO1xuICB9XG5cbiAgc3RhdGljIGxpdHRsZSh2YWx1ZSkge1xuICAgIHJldHVybiBCaXRTdHJpbmcud3JhcCh2YWx1ZSwge30sIFwibGl0dGxlXCIpO1xuICB9XG5cbiAgc3RhdGljIHNpemUodmFsdWUsIGNvdW50KSB7XG4gICAgcmV0dXJuIEJpdFN0cmluZy53cmFwKHZhbHVlLCB7IFwic2l6ZVwiOiBjb3VudCB9KTtcbiAgfVxuXG4gIHN0YXRpYyB1bml0KHZhbHVlLCBjb3VudCkge1xuICAgIHJldHVybiBCaXRTdHJpbmcud3JhcCh2YWx1ZSwgeyBcInVuaXRcIjogY291bnQgfSk7XG4gIH1cblxuICBzdGF0aWMgd3JhcCh2YWx1ZSwgb3B0LCBuZXdfYXR0cmlidXRlID0gbnVsbCkge1xuICAgIGxldCB0aGVfdmFsdWUgPSB2YWx1ZTtcblxuICAgIGlmICghKHZhbHVlIGluc3RhbmNlb2YgT2JqZWN0KSkge1xuICAgICAgdGhlX3ZhbHVlID0geyBcInZhbHVlXCI6IHZhbHVlLCBcImF0dHJpYnV0ZXNcIjogW10gfTtcbiAgICB9XG5cbiAgICB0aGVfdmFsdWUgPSBPYmplY3QuYXNzaWduKHRoZV92YWx1ZSwgb3B0KTtcblxuICAgIGlmIChuZXdfYXR0cmlidXRlKSB7XG4gICAgICB0aGVfdmFsdWUuYXR0cmlidXRlcy5wdXNoKG5ld19hdHRyaWJ1dGUpO1xuICAgIH1cblxuICAgIHJldHVybiB0aGVfdmFsdWU7XG4gIH1cblxuICBzdGF0aWMgdG9VVEY4QXJyYXkoc3RyKSB7XG4gICAgdmFyIHV0ZjggPSBbXTtcbiAgICBmb3IgKHZhciBpID0gMDsgaSA8IHN0ci5sZW5ndGg7IGkrKykge1xuICAgICAgdmFyIGNoYXJjb2RlID0gc3RyLmNoYXJDb2RlQXQoaSk7XG4gICAgICBpZiAoY2hhcmNvZGUgPCAxMjgpIHtcbiAgICAgICAgdXRmOC5wdXNoKGNoYXJjb2RlKTtcbiAgICAgIH0gZWxzZSBpZiAoY2hhcmNvZGUgPCAyMDQ4KSB7XG4gICAgICAgIHV0ZjgucHVzaCgxOTIgfCBjaGFyY29kZSA+PiA2LCAxMjggfCBjaGFyY29kZSAmIDYzKTtcbiAgICAgIH0gZWxzZSBpZiAoY2hhcmNvZGUgPCA1NTI5NiB8fCBjaGFyY29kZSA+PSA1NzM0NCkge1xuICAgICAgICB1dGY4LnB1c2goMjI0IHwgY2hhcmNvZGUgPj4gMTIsIDEyOCB8IGNoYXJjb2RlID4+IDYgJiA2MywgMTI4IHwgY2hhcmNvZGUgJiA2Myk7XG4gICAgICB9XG4gICAgICAvLyBzdXJyb2dhdGUgcGFpclxuICAgICAgZWxzZSB7XG4gICAgICAgIGkrKztcbiAgICAgICAgLy8gVVRGLTE2IGVuY29kZXMgMHgxMDAwMC0weDEwRkZGRiBieVxuICAgICAgICAvLyBzdWJ0cmFjdGluZyAweDEwMDAwIGFuZCBzcGxpdHRpbmcgdGhlXG4gICAgICAgIC8vIDIwIGJpdHMgb2YgMHgwLTB4RkZGRkYgaW50byB0d28gaGFsdmVzXG4gICAgICAgIGNoYXJjb2RlID0gNjU1MzYgKyAoKGNoYXJjb2RlICYgMTAyMykgPDwgMTAgfCBzdHIuY2hhckNvZGVBdChpKSAmIDEwMjMpO1xuICAgICAgICB1dGY4LnB1c2goMjQwIHwgY2hhcmNvZGUgPj4gMTgsIDEyOCB8IGNoYXJjb2RlID4+IDEyICYgNjMsIDEyOCB8IGNoYXJjb2RlID4+IDYgJiA2MywgMTI4IHwgY2hhcmNvZGUgJiA2Myk7XG4gICAgICB9XG4gICAgfVxuICAgIHJldHVybiB1dGY4O1xuICB9XG5cbiAgc3RhdGljIHRvVVRGMTZBcnJheShzdHIpIHtcbiAgICB2YXIgdXRmMTYgPSBbXTtcbiAgICBmb3IgKHZhciBpID0gMDsgaSA8IHN0ci5sZW5ndGg7IGkrKykge1xuICAgICAgdmFyIGNvZGVQb2ludCA9IHN0ci5jb2RlUG9pbnRBdChpKTtcblxuICAgICAgaWYgKGNvZGVQb2ludCA8PSAyNTUpIHtcbiAgICAgICAgdXRmMTYucHVzaCgwKTtcbiAgICAgICAgdXRmMTYucHVzaChjb2RlUG9pbnQpO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgdXRmMTYucHVzaChjb2RlUG9pbnQgPj4gOCAmIDI1NSk7XG4gICAgICAgIHV0ZjE2LnB1c2goY29kZVBvaW50ICYgMjU1KTtcbiAgICAgIH1cbiAgICB9XG4gICAgcmV0dXJuIHV0ZjE2O1xuICB9XG5cbiAgc3RhdGljIHRvVVRGMzJBcnJheShzdHIpIHtcbiAgICB2YXIgdXRmMzIgPSBbXTtcbiAgICBmb3IgKHZhciBpID0gMDsgaSA8IHN0ci5sZW5ndGg7IGkrKykge1xuICAgICAgdmFyIGNvZGVQb2ludCA9IHN0ci5jb2RlUG9pbnRBdChpKTtcblxuICAgICAgaWYgKGNvZGVQb2ludCA8PSAyNTUpIHtcbiAgICAgICAgdXRmMzIucHVzaCgwKTtcbiAgICAgICAgdXRmMzIucHVzaCgwKTtcbiAgICAgICAgdXRmMzIucHVzaCgwKTtcbiAgICAgICAgdXRmMzIucHVzaChjb2RlUG9pbnQpO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgdXRmMzIucHVzaCgwKTtcbiAgICAgICAgdXRmMzIucHVzaCgwKTtcbiAgICAgICAgdXRmMzIucHVzaChjb2RlUG9pbnQgPj4gOCAmIDI1NSk7XG4gICAgICAgIHV0ZjMyLnB1c2goY29kZVBvaW50ICYgMjU1KTtcbiAgICAgIH1cbiAgICB9XG4gICAgcmV0dXJuIHV0ZjMyO1xuICB9XG5cbiAgLy9odHRwOi8vc3RhY2tvdmVyZmxvdy5jb20vcXVlc3Rpb25zLzIwMDM0OTMvamF2YXNjcmlwdC1mbG9hdC1mcm9tLXRvLWJpdHNcbiAgc3RhdGljIGZsb2F0MzJUb0J5dGVzKGYpIHtcbiAgICB2YXIgYnl0ZXMgPSBbXTtcblxuICAgIHZhciBidWYgPSBuZXcgQXJyYXlCdWZmZXIoNCk7XG4gICAgbmV3IEZsb2F0MzJBcnJheShidWYpWzBdID0gZjtcblxuICAgIGxldCBpbnRWZXJzaW9uID0gbmV3IFVpbnQzMkFycmF5KGJ1ZilbMF07XG5cbiAgICBieXRlcy5wdXNoKGludFZlcnNpb24gPj4gMjQgJiAyNTUpO1xuICAgIGJ5dGVzLnB1c2goaW50VmVyc2lvbiA+PiAxNiAmIDI1NSk7XG4gICAgYnl0ZXMucHVzaChpbnRWZXJzaW9uID4+IDggJiAyNTUpO1xuICAgIGJ5dGVzLnB1c2goaW50VmVyc2lvbiAmIDI1NSk7XG5cbiAgICByZXR1cm4gYnl0ZXM7XG4gIH1cblxuICBzdGF0aWMgZmxvYXQ2NFRvQnl0ZXMoZikge1xuICAgIHZhciBieXRlcyA9IFtdO1xuXG4gICAgdmFyIGJ1ZiA9IG5ldyBBcnJheUJ1ZmZlcig4KTtcbiAgICBuZXcgRmxvYXQ2NEFycmF5KGJ1ZilbMF0gPSBmO1xuXG4gICAgdmFyIGludFZlcnNpb24xID0gbmV3IFVpbnQzMkFycmF5KGJ1ZilbMF07XG4gICAgdmFyIGludFZlcnNpb24yID0gbmV3IFVpbnQzMkFycmF5KGJ1ZilbMV07XG5cbiAgICBieXRlcy5wdXNoKGludFZlcnNpb24yID4+IDI0ICYgMjU1KTtcbiAgICBieXRlcy5wdXNoKGludFZlcnNpb24yID4+IDE2ICYgMjU1KTtcbiAgICBieXRlcy5wdXNoKGludFZlcnNpb24yID4+IDggJiAyNTUpO1xuICAgIGJ5dGVzLnB1c2goaW50VmVyc2lvbjIgJiAyNTUpO1xuXG4gICAgYnl0ZXMucHVzaChpbnRWZXJzaW9uMSA+PiAyNCAmIDI1NSk7XG4gICAgYnl0ZXMucHVzaChpbnRWZXJzaW9uMSA+PiAxNiAmIDI1NSk7XG4gICAgYnl0ZXMucHVzaChpbnRWZXJzaW9uMSA+PiA4ICYgMjU1KTtcbiAgICBieXRlcy5wdXNoKGludFZlcnNpb24xICYgMjU1KTtcblxuICAgIHJldHVybiBieXRlcztcbiAgfVxufVxuXG4vKiBAZmxvdyAqL1xuXG5jbGFzcyBWYXJpYWJsZSB7XG5cbiAgY29uc3RydWN0b3IobmFtZSA9IG51bGwpIHtcbiAgICB0aGlzLm5hbWUgPSBuYW1lO1xuICB9XG59XG5cbmNsYXNzIFdpbGRjYXJkIHtcbiAgY29uc3RydWN0b3IoKSB7fVxufVxuXG5jbGFzcyBTdGFydHNXaXRoIHtcblxuICBjb25zdHJ1Y3RvcihwcmVmaXgpIHtcbiAgICB0aGlzLnByZWZpeCA9IHByZWZpeDtcbiAgfVxufVxuXG5jbGFzcyBDYXB0dXJlIHtcblxuICBjb25zdHJ1Y3Rvcih2YWx1ZSkge1xuICAgIHRoaXMudmFsdWUgPSB2YWx1ZTtcbiAgfVxufVxuXG5jbGFzcyBIZWFkVGFpbCB7XG4gIGNvbnN0cnVjdG9yKCkge31cbn1cblxuY2xhc3MgVHlwZSB7XG5cbiAgY29uc3RydWN0b3IodHlwZSwgb2JqUGF0dGVybiA9IHt9KSB7XG4gICAgdGhpcy50eXBlID0gdHlwZTtcbiAgICB0aGlzLm9ialBhdHRlcm4gPSBvYmpQYXR0ZXJuO1xuICB9XG59XG5cbmNsYXNzIEJvdW5kIHtcblxuICBjb25zdHJ1Y3Rvcih2YWx1ZSkge1xuICAgIHRoaXMudmFsdWUgPSB2YWx1ZTtcbiAgfVxufVxuXG5mdW5jdGlvbiB2YXJpYWJsZShuYW1lID0gbnVsbCkge1xuICByZXR1cm4gbmV3IFZhcmlhYmxlKG5hbWUpO1xufVxuXG5mdW5jdGlvbiB3aWxkY2FyZCgpIHtcbiAgcmV0dXJuIG5ldyBXaWxkY2FyZCgpO1xufVxuXG5mdW5jdGlvbiBzdGFydHNXaXRoKHByZWZpeCkge1xuICByZXR1cm4gbmV3IFN0YXJ0c1dpdGgocHJlZml4KTtcbn1cblxuZnVuY3Rpb24gY2FwdHVyZSh2YWx1ZSkge1xuICByZXR1cm4gbmV3IENhcHR1cmUodmFsdWUpO1xufVxuXG5mdW5jdGlvbiBoZWFkVGFpbCgpIHtcbiAgcmV0dXJuIG5ldyBIZWFkVGFpbCgpO1xufVxuXG5mdW5jdGlvbiB0eXBlKHR5cGUsIG9ialBhdHRlcm4gPSB7fSkge1xuICByZXR1cm4gbmV3IFR5cGUodHlwZSwgb2JqUGF0dGVybik7XG59XG5cbmZ1bmN0aW9uIGJvdW5kKHZhbHVlKSB7XG4gIHJldHVybiBuZXcgQm91bmQodmFsdWUpO1xufVxuXG5mdW5jdGlvbiBpc19udW1iZXIkMih2YWx1ZSkge1xuICByZXR1cm4gdHlwZW9mIHZhbHVlID09PSAnbnVtYmVyJztcbn1cblxuZnVuY3Rpb24gaXNfc3RyaW5nKHZhbHVlKSB7XG4gIHJldHVybiB0eXBlb2YgdmFsdWUgPT09ICdzdHJpbmcnO1xufVxuXG5mdW5jdGlvbiBpc19ib29sZWFuJDIodmFsdWUpIHtcbiAgcmV0dXJuIHR5cGVvZiB2YWx1ZSA9PT0gJ2Jvb2xlYW4nO1xufVxuXG5mdW5jdGlvbiBpc19zeW1ib2wodmFsdWUpIHtcbiAgcmV0dXJuIHR5cGVvZiB2YWx1ZSA9PT0gJ3N5bWJvbCc7XG59XG5cbmZ1bmN0aW9uIGlzX251bGwodmFsdWUpIHtcbiAgcmV0dXJuIHZhbHVlID09PSBudWxsO1xufVxuXG5mdW5jdGlvbiBpc191bmRlZmluZWQodmFsdWUpIHtcbiAgcmV0dXJuIHR5cGVvZiB2YWx1ZSA9PT0gJ3VuZGVmaW5lZCc7XG59XG5cbmZ1bmN0aW9uIGlzX2Z1bmN0aW9uJDIodmFsdWUpIHtcbiAgcmV0dXJuIE9iamVjdC5wcm90b3R5cGUudG9TdHJpbmcuY2FsbCh2YWx1ZSkgPT0gJ1tvYmplY3QgRnVuY3Rpb25dJztcbn1cblxuZnVuY3Rpb24gaXNfdmFyaWFibGUodmFsdWUpIHtcbiAgcmV0dXJuIHZhbHVlIGluc3RhbmNlb2YgVmFyaWFibGU7XG59XG5cbmZ1bmN0aW9uIGlzX3dpbGRjYXJkKHZhbHVlKSB7XG4gIHJldHVybiB2YWx1ZSBpbnN0YW5jZW9mIFdpbGRjYXJkO1xufVxuXG5mdW5jdGlvbiBpc19oZWFkVGFpbCh2YWx1ZSkge1xuICByZXR1cm4gdmFsdWUgaW5zdGFuY2VvZiBIZWFkVGFpbDtcbn1cblxuZnVuY3Rpb24gaXNfY2FwdHVyZSh2YWx1ZSkge1xuICByZXR1cm4gdmFsdWUgaW5zdGFuY2VvZiBDYXB0dXJlO1xufVxuXG5mdW5jdGlvbiBpc190eXBlKHZhbHVlKSB7XG4gIHJldHVybiB2YWx1ZSBpbnN0YW5jZW9mIFR5cGU7XG59XG5cbmZ1bmN0aW9uIGlzX3N0YXJ0c1dpdGgodmFsdWUpIHtcbiAgcmV0dXJuIHZhbHVlIGluc3RhbmNlb2YgU3RhcnRzV2l0aDtcbn1cblxuZnVuY3Rpb24gaXNfYm91bmQodmFsdWUpIHtcbiAgcmV0dXJuIHZhbHVlIGluc3RhbmNlb2YgQm91bmQ7XG59XG5cbmZ1bmN0aW9uIGlzX29iamVjdCh2YWx1ZSkge1xuICByZXR1cm4gdHlwZW9mIHZhbHVlID09PSAnb2JqZWN0Jztcbn1cblxuZnVuY3Rpb24gaXNfYXJyYXkodmFsdWUpIHtcbiAgcmV0dXJuIEFycmF5LmlzQXJyYXkodmFsdWUpO1xufVxuXG52YXIgQ2hlY2tzID0ge1xuICBpc19udW1iZXI6IGlzX251bWJlciQyLFxuICBpc19zdHJpbmcsXG4gIGlzX2Jvb2xlYW46IGlzX2Jvb2xlYW4kMixcbiAgaXNfc3ltYm9sLFxuICBpc19udWxsLFxuICBpc191bmRlZmluZWQsXG4gIGlzX2Z1bmN0aW9uOiBpc19mdW5jdGlvbiQyLFxuICBpc192YXJpYWJsZSxcbiAgaXNfd2lsZGNhcmQsXG4gIGlzX2hlYWRUYWlsLFxuICBpc19jYXB0dXJlLFxuICBpc190eXBlLFxuICBpc19zdGFydHNXaXRoLFxuICBpc19ib3VuZCxcbiAgaXNfb2JqZWN0LFxuICBpc19hcnJheVxufTtcblxuZnVuY3Rpb24gcmVzb2x2ZVN5bWJvbChwYXR0ZXJuKSB7XG4gIHJldHVybiBmdW5jdGlvbiAodmFsdWUpIHtcbiAgICByZXR1cm4gQ2hlY2tzLmlzX3N5bWJvbCh2YWx1ZSkgJiYgdmFsdWUgPT09IHBhdHRlcm47XG4gIH07XG59XG5cbmZ1bmN0aW9uIHJlc29sdmVTdHJpbmcocGF0dGVybikge1xuICByZXR1cm4gZnVuY3Rpb24gKHZhbHVlKSB7XG4gICAgcmV0dXJuIENoZWNrcy5pc19zdHJpbmcodmFsdWUpICYmIHZhbHVlID09PSBwYXR0ZXJuO1xuICB9O1xufVxuXG5mdW5jdGlvbiByZXNvbHZlTnVtYmVyKHBhdHRlcm4pIHtcbiAgcmV0dXJuIGZ1bmN0aW9uICh2YWx1ZSkge1xuICAgIHJldHVybiBDaGVja3MuaXNfbnVtYmVyKHZhbHVlKSAmJiB2YWx1ZSA9PT0gcGF0dGVybjtcbiAgfTtcbn1cblxuZnVuY3Rpb24gcmVzb2x2ZUJvb2xlYW4ocGF0dGVybikge1xuICByZXR1cm4gZnVuY3Rpb24gKHZhbHVlKSB7XG4gICAgcmV0dXJuIENoZWNrcy5pc19ib29sZWFuKHZhbHVlKSAmJiB2YWx1ZSA9PT0gcGF0dGVybjtcbiAgfTtcbn1cblxuZnVuY3Rpb24gcmVzb2x2ZUZ1bmN0aW9uKHBhdHRlcm4pIHtcbiAgcmV0dXJuIGZ1bmN0aW9uICh2YWx1ZSkge1xuICAgIHJldHVybiBDaGVja3MuaXNfZnVuY3Rpb24odmFsdWUpICYmIHZhbHVlID09PSBwYXR0ZXJuO1xuICB9O1xufVxuXG5mdW5jdGlvbiByZXNvbHZlTnVsbChwYXR0ZXJuKSB7XG4gIHJldHVybiBmdW5jdGlvbiAodmFsdWUpIHtcbiAgICByZXR1cm4gQ2hlY2tzLmlzX251bGwodmFsdWUpO1xuICB9O1xufVxuXG5mdW5jdGlvbiByZXNvbHZlQm91bmQocGF0dGVybikge1xuICByZXR1cm4gZnVuY3Rpb24gKHZhbHVlLCBhcmdzKSB7XG4gICAgaWYgKHR5cGVvZiB2YWx1ZSA9PT0gdHlwZW9mIHBhdHRlcm4udmFsdWUgJiYgdmFsdWUgPT09IHBhdHRlcm4udmFsdWUpIHtcbiAgICAgIGFyZ3MucHVzaCh2YWx1ZSk7XG4gICAgICByZXR1cm4gdHJ1ZTtcbiAgICB9XG5cbiAgICByZXR1cm4gZmFsc2U7XG4gIH07XG59XG5cbmZ1bmN0aW9uIHJlc29sdmVXaWxkY2FyZCgpIHtcbiAgcmV0dXJuIGZ1bmN0aW9uICgpIHtcbiAgICByZXR1cm4gdHJ1ZTtcbiAgfTtcbn1cblxuZnVuY3Rpb24gcmVzb2x2ZVZhcmlhYmxlKCkge1xuICByZXR1cm4gZnVuY3Rpb24gKHZhbHVlLCBhcmdzKSB7XG4gICAgYXJncy5wdXNoKHZhbHVlKTtcbiAgICByZXR1cm4gdHJ1ZTtcbiAgfTtcbn1cblxuZnVuY3Rpb24gcmVzb2x2ZUhlYWRUYWlsKCkge1xuICByZXR1cm4gZnVuY3Rpb24gKHZhbHVlLCBhcmdzKSB7XG4gICAgaWYgKCFDaGVja3MuaXNfYXJyYXkodmFsdWUpIHx8IHZhbHVlLmxlbmd0aCA8IDIpIHtcbiAgICAgIHJldHVybiBmYWxzZTtcbiAgICB9XG5cbiAgICBjb25zdCBoZWFkID0gdmFsdWVbMF07XG4gICAgY29uc3QgdGFpbCA9IHZhbHVlLnNsaWNlKDEpO1xuXG4gICAgYXJncy5wdXNoKGhlYWQpO1xuICAgIGFyZ3MucHVzaCh0YWlsKTtcblxuICAgIHJldHVybiB0cnVlO1xuICB9O1xufVxuXG5mdW5jdGlvbiByZXNvbHZlQ2FwdHVyZShwYXR0ZXJuKSB7XG4gIGNvbnN0IG1hdGNoZXMgPSBidWlsZE1hdGNoKHBhdHRlcm4udmFsdWUpO1xuXG4gIHJldHVybiBmdW5jdGlvbiAodmFsdWUsIGFyZ3MpIHtcbiAgICBpZiAobWF0Y2hlcyh2YWx1ZSwgYXJncykpIHtcbiAgICAgIGFyZ3MucHVzaCh2YWx1ZSk7XG4gICAgICByZXR1cm4gdHJ1ZTtcbiAgICB9XG5cbiAgICByZXR1cm4gZmFsc2U7XG4gIH07XG59XG5cbmZ1bmN0aW9uIHJlc29sdmVTdGFydHNXaXRoKHBhdHRlcm4pIHtcbiAgY29uc3QgcHJlZml4ID0gcGF0dGVybi5wcmVmaXg7XG5cbiAgcmV0dXJuIGZ1bmN0aW9uICh2YWx1ZSwgYXJncykge1xuICAgIGlmIChDaGVja3MuaXNfc3RyaW5nKHZhbHVlKSAmJiB2YWx1ZS5zdGFydHNXaXRoKHByZWZpeCkpIHtcbiAgICAgIGFyZ3MucHVzaCh2YWx1ZS5zdWJzdHJpbmcocHJlZml4Lmxlbmd0aCkpO1xuICAgICAgcmV0dXJuIHRydWU7XG4gICAgfVxuXG4gICAgcmV0dXJuIGZhbHNlO1xuICB9O1xufVxuXG5mdW5jdGlvbiByZXNvbHZlVHlwZShwYXR0ZXJuKSB7XG4gIHJldHVybiBmdW5jdGlvbiAodmFsdWUsIGFyZ3MpIHtcbiAgICBpZiAodmFsdWUgaW5zdGFuY2VvZiBwYXR0ZXJuLnR5cGUpIHtcbiAgICAgIGNvbnN0IG1hdGNoZXMgPSBidWlsZE1hdGNoKHBhdHRlcm4ub2JqUGF0dGVybik7XG4gICAgICByZXR1cm4gbWF0Y2hlcyh2YWx1ZSwgYXJncykgJiYgYXJncy5wdXNoKHZhbHVlKSA+IDA7XG4gICAgfVxuXG4gICAgcmV0dXJuIGZhbHNlO1xuICB9O1xufVxuXG5mdW5jdGlvbiByZXNvbHZlQXJyYXkocGF0dGVybikge1xuICBjb25zdCBtYXRjaGVzID0gcGF0dGVybi5tYXAoeCA9PiBidWlsZE1hdGNoKHgpKTtcblxuICByZXR1cm4gZnVuY3Rpb24gKHZhbHVlLCBhcmdzKSB7XG4gICAgaWYgKCFDaGVja3MuaXNfYXJyYXkodmFsdWUpIHx8IHZhbHVlLmxlbmd0aCAhPSBwYXR0ZXJuLmxlbmd0aCkge1xuICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH1cblxuICAgIHJldHVybiB2YWx1ZS5ldmVyeShmdW5jdGlvbiAodiwgaSkge1xuICAgICAgcmV0dXJuIG1hdGNoZXNbaV0odmFsdWVbaV0sIGFyZ3MpO1xuICAgIH0pO1xuICB9O1xufVxuXG5mdW5jdGlvbiByZXNvbHZlT2JqZWN0KHBhdHRlcm4pIHtcbiAgbGV0IG1hdGNoZXMgPSB7fTtcblxuICBmb3IgKGxldCBrZXkgb2YgT2JqZWN0LmtleXMocGF0dGVybikuY29uY2F0KE9iamVjdC5nZXRPd25Qcm9wZXJ0eVN5bWJvbHMocGF0dGVybikpKSB7XG4gICAgbWF0Y2hlc1trZXldID0gYnVpbGRNYXRjaChwYXR0ZXJuW2tleV0pO1xuICB9XG5cbiAgcmV0dXJuIGZ1bmN0aW9uICh2YWx1ZSwgYXJncykge1xuICAgIGlmICghQ2hlY2tzLmlzX29iamVjdCh2YWx1ZSkgfHwgcGF0dGVybi5sZW5ndGggPiB2YWx1ZS5sZW5ndGgpIHtcbiAgICAgIHJldHVybiBmYWxzZTtcbiAgICB9XG5cbiAgICBmb3IgKGxldCBrZXkgb2YgT2JqZWN0LmtleXMocGF0dGVybikuY29uY2F0KE9iamVjdC5nZXRPd25Qcm9wZXJ0eVN5bWJvbHMocGF0dGVybikpKSB7XG4gICAgICBpZiAoIShrZXkgaW4gdmFsdWUpIHx8ICFtYXRjaGVzW2tleV0odmFsdWVba2V5XSwgYXJncykpIHtcbiAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgfVxuICAgIH1cblxuICAgIHJldHVybiB0cnVlO1xuICB9O1xufVxuXG5mdW5jdGlvbiByZXNvbHZlTm9NYXRjaCgpIHtcbiAgcmV0dXJuIGZ1bmN0aW9uICgpIHtcbiAgICByZXR1cm4gZmFsc2U7XG4gIH07XG59XG5cbnZhciBSZXNvbHZlcnMgPSB7XG4gIHJlc29sdmVCb3VuZCxcbiAgcmVzb2x2ZVdpbGRjYXJkLFxuICByZXNvbHZlVmFyaWFibGUsXG4gIHJlc29sdmVIZWFkVGFpbCxcbiAgcmVzb2x2ZUNhcHR1cmUsXG4gIHJlc29sdmVTdGFydHNXaXRoLFxuICByZXNvbHZlVHlwZSxcbiAgcmVzb2x2ZUFycmF5LFxuICByZXNvbHZlT2JqZWN0LFxuICByZXNvbHZlTm9NYXRjaCxcbiAgcmVzb2x2ZVN5bWJvbCxcbiAgcmVzb2x2ZVN0cmluZyxcbiAgcmVzb2x2ZU51bWJlcixcbiAgcmVzb2x2ZUJvb2xlYW4sXG4gIHJlc29sdmVGdW5jdGlvbixcbiAgcmVzb2x2ZU51bGxcbn07XG5cbmZ1bmN0aW9uIGJ1aWxkTWF0Y2gocGF0dGVybikge1xuXG4gIGlmIChDaGVja3MuaXNfdmFyaWFibGUocGF0dGVybikpIHtcbiAgICByZXR1cm4gUmVzb2x2ZXJzLnJlc29sdmVWYXJpYWJsZShwYXR0ZXJuKTtcbiAgfVxuXG4gIGlmIChDaGVja3MuaXNfd2lsZGNhcmQocGF0dGVybikpIHtcbiAgICByZXR1cm4gUmVzb2x2ZXJzLnJlc29sdmVXaWxkY2FyZChwYXR0ZXJuKTtcbiAgfVxuXG4gIGlmIChDaGVja3MuaXNfdW5kZWZpbmVkKHBhdHRlcm4pKSB7XG4gICAgcmV0dXJuIFJlc29sdmVycy5yZXNvbHZlV2lsZGNhcmQocGF0dGVybik7XG4gIH1cblxuICBpZiAoQ2hlY2tzLmlzX2hlYWRUYWlsKHBhdHRlcm4pKSB7XG4gICAgcmV0dXJuIFJlc29sdmVycy5yZXNvbHZlSGVhZFRhaWwocGF0dGVybik7XG4gIH1cblxuICBpZiAoQ2hlY2tzLmlzX3N0YXJ0c1dpdGgocGF0dGVybikpIHtcbiAgICByZXR1cm4gUmVzb2x2ZXJzLnJlc29sdmVTdGFydHNXaXRoKHBhdHRlcm4pO1xuICB9XG5cbiAgaWYgKENoZWNrcy5pc19jYXB0dXJlKHBhdHRlcm4pKSB7XG4gICAgcmV0dXJuIFJlc29sdmVycy5yZXNvbHZlQ2FwdHVyZShwYXR0ZXJuKTtcbiAgfVxuXG4gIGlmIChDaGVja3MuaXNfYm91bmQocGF0dGVybikpIHtcbiAgICByZXR1cm4gUmVzb2x2ZXJzLnJlc29sdmVCb3VuZChwYXR0ZXJuKTtcbiAgfVxuXG4gIGlmIChDaGVja3MuaXNfdHlwZShwYXR0ZXJuKSkge1xuICAgIHJldHVybiBSZXNvbHZlcnMucmVzb2x2ZVR5cGUocGF0dGVybik7XG4gIH1cblxuICBpZiAoQ2hlY2tzLmlzX2FycmF5KHBhdHRlcm4pKSB7XG4gICAgcmV0dXJuIFJlc29sdmVycy5yZXNvbHZlQXJyYXkocGF0dGVybik7XG4gIH1cblxuICBpZiAoQ2hlY2tzLmlzX251bWJlcihwYXR0ZXJuKSkge1xuICAgIHJldHVybiBSZXNvbHZlcnMucmVzb2x2ZU51bWJlcihwYXR0ZXJuKTtcbiAgfVxuXG4gIGlmIChDaGVja3MuaXNfc3RyaW5nKHBhdHRlcm4pKSB7XG4gICAgcmV0dXJuIFJlc29sdmVycy5yZXNvbHZlU3RyaW5nKHBhdHRlcm4pO1xuICB9XG5cbiAgaWYgKENoZWNrcy5pc19ib29sZWFuKHBhdHRlcm4pKSB7XG4gICAgcmV0dXJuIFJlc29sdmVycy5yZXNvbHZlQm9vbGVhbihwYXR0ZXJuKTtcbiAgfVxuXG4gIGlmIChDaGVja3MuaXNfc3ltYm9sKHBhdHRlcm4pKSB7XG4gICAgcmV0dXJuIFJlc29sdmVycy5yZXNvbHZlU3ltYm9sKHBhdHRlcm4pO1xuICB9XG5cbiAgaWYgKENoZWNrcy5pc19udWxsKHBhdHRlcm4pKSB7XG4gICAgcmV0dXJuIFJlc29sdmVycy5yZXNvbHZlTnVsbChwYXR0ZXJuKTtcbiAgfVxuXG4gIGlmIChDaGVja3MuaXNfb2JqZWN0KHBhdHRlcm4pKSB7XG4gICAgcmV0dXJuIFJlc29sdmVycy5yZXNvbHZlT2JqZWN0KHBhdHRlcm4pO1xuICB9XG5cbiAgcmV0dXJuIFJlc29sdmVycy5yZXNvbHZlTm9NYXRjaCgpO1xufVxuXG5jbGFzcyBNYXRjaEVycm9yIGV4dGVuZHMgRXJyb3Ige1xuICBjb25zdHJ1Y3RvcihhcmcpIHtcbiAgICBzdXBlcigpO1xuXG4gICAgaWYgKHR5cGVvZiBhcmcgPT09ICdzeW1ib2wnKSB7XG4gICAgICB0aGlzLm1lc3NhZ2UgPSAnTm8gbWF0Y2ggZm9yOiAnICsgYXJnLnRvU3RyaW5nKCk7XG4gICAgfSBlbHNlIGlmIChBcnJheS5pc0FycmF5KGFyZykpIHtcbiAgICAgIGxldCBtYXBwZWRWYWx1ZXMgPSBhcmcubWFwKHggPT4geC50b1N0cmluZygpKTtcbiAgICAgIHRoaXMubWVzc2FnZSA9ICdObyBtYXRjaCBmb3I6ICcgKyBtYXBwZWRWYWx1ZXM7XG4gICAgfSBlbHNlIHtcbiAgICAgIHRoaXMubWVzc2FnZSA9ICdObyBtYXRjaCBmb3I6ICcgKyBhcmc7XG4gICAgfVxuXG4gICAgdGhpcy5zdGFjayA9IG5ldyBFcnJvcigpLnN0YWNrO1xuICAgIHRoaXMubmFtZSA9IHRoaXMuY29uc3RydWN0b3IubmFtZTtcbiAgfVxufVxuXG5jbGFzcyBDYXNlIHtcblxuICBjb25zdHJ1Y3RvcihwYXR0ZXJuLCBmbiwgZ3VhcmQgPSAoKSA9PiB0cnVlKSB7XG4gICAgdGhpcy5wYXR0ZXJuID0gYnVpbGRNYXRjaChwYXR0ZXJuKTtcbiAgICB0aGlzLmZuID0gZm47XG4gICAgdGhpcy5ndWFyZCA9IGd1YXJkO1xuICB9XG59XG5cbmZ1bmN0aW9uIG1ha2VfY2FzZShwYXR0ZXJuLCBmbiwgZ3VhcmQgPSAoKSA9PiB0cnVlKSB7XG4gIHJldHVybiBuZXcgQ2FzZShwYXR0ZXJuLCBmbiwgZ3VhcmQpO1xufVxuXG5mdW5jdGlvbiBkZWZtYXRjaCguLi5jYXNlcykge1xuICByZXR1cm4gZnVuY3Rpb24gKC4uLmFyZ3MpIHtcbiAgICBmb3IgKGxldCBwcm9jZXNzZWRDYXNlIG9mIGNhc2VzKSB7XG4gICAgICBsZXQgcmVzdWx0ID0gW107XG4gICAgICBpZiAocHJvY2Vzc2VkQ2FzZS5wYXR0ZXJuKGFyZ3MsIHJlc3VsdCkgJiYgcHJvY2Vzc2VkQ2FzZS5ndWFyZC5hcHBseSh0aGlzLCByZXN1bHQpKSB7XG4gICAgICAgIHJldHVybiBwcm9jZXNzZWRDYXNlLmZuLmFwcGx5KHRoaXMsIHJlc3VsdCk7XG4gICAgICB9XG4gICAgfVxuXG4gICAgdGhyb3cgbmV3IE1hdGNoRXJyb3IoYXJncyk7XG4gIH07XG59XG5cbmZ1bmN0aW9uIG1hdGNoKHBhdHRlcm4sIGV4cHIsIGd1YXJkID0gKCkgPT4gdHJ1ZSkge1xuICBsZXQgcmVzdWx0ID0gW107XG4gIGxldCBwcm9jZXNzZWRQYXR0ZXJuID0gYnVpbGRNYXRjaChwYXR0ZXJuKTtcbiAgaWYgKHByb2Nlc3NlZFBhdHRlcm4oZXhwciwgcmVzdWx0KSAmJiBndWFyZC5hcHBseSh0aGlzLCByZXN1bHQpKSB7XG4gICAgcmV0dXJuIHJlc3VsdDtcbiAgfSBlbHNlIHtcbiAgICB0aHJvdyBuZXcgTWF0Y2hFcnJvcihleHByKTtcbiAgfVxufVxuXG5mdW5jdGlvbiBtYXRjaF9ub190aHJvdyhwYXR0ZXJuLCBleHByLCBndWFyZCA9ICgpID0+IHRydWUpIHtcbiAgdHJ5IHtcbiAgICByZXR1cm4gbWF0Y2gocGF0dGVybiwgZXhwciwgZ3VhcmQpO1xuICB9IGNhdGNoIChlKSB7XG4gICAgaWYgKGUgaW5zdGFuY2VvZiBNYXRjaEVycm9yKSB7XG4gICAgICByZXR1cm4gbnVsbDtcbiAgICB9XG5cbiAgICB0aHJvdyBlO1xuICB9XG59XG5cbnZhciBQYXR0ZXJucyA9IHtcbiAgZGVmbWF0Y2gsIG1hdGNoLCBNYXRjaEVycm9yLCBtYXRjaF9ub190aHJvdyxcbiAgdmFyaWFibGUsIHdpbGRjYXJkLCBzdGFydHNXaXRoLFxuICBjYXB0dXJlLCBoZWFkVGFpbCwgdHlwZSwgYm91bmQsIENhc2UsIG1ha2VfY2FzZVxufTtcblxuZnVuY3Rpb24gY2FsbF9wcm9wZXJ0eShpdGVtLCBwcm9wZXJ0eSkge1xuICBpZiAocHJvcGVydHkgaW4gaXRlbSkge1xuICAgIGl0ZW1bcHJvcGVydHldO1xuICAgIGlmIChpdGVtW3Byb3BlcnR5XSBpbnN0YW5jZW9mIEZ1bmN0aW9uKSB7XG4gICAgICByZXR1cm4gaXRlbVtwcm9wZXJ0eV0oKTtcbiAgICB9IGVsc2Uge1xuICAgICAgcmV0dXJuIGl0ZW1bcHJvcGVydHldO1xuICAgIH1cbiAgfSBlbHNlIGlmIChTeW1ib2wuZm9yKHByb3BlcnR5KSBpbiBpdGVtKSB7XG4gICAgbGV0IHByb3AgPSBTeW1ib2wuZm9yKHByb3BlcnR5KTtcbiAgICBpZiAoaXRlbVtwcm9wXSBpbnN0YW5jZW9mIEZ1bmN0aW9uKSB7XG4gICAgICByZXR1cm4gaXRlbVtwcm9wXSgpO1xuICAgIH0gZWxzZSB7XG4gICAgICByZXR1cm4gaXRlbVtwcm9wXTtcbiAgICB9XG4gIH1cblxuICB0aHJvdyBuZXcgRXJyb3IoYFByb3BlcnR5ICR7IHByb3BlcnR5IH0gbm90IGZvdW5kIGluICR7IGl0ZW0gfWApO1xufVxuXG5mdW5jdGlvbiBpc19pbnN0YW5jZV9vZih2YWx1ZSwgdHlwZSkge1xuICByZXR1cm4gdmFsdWUgaW5zdGFuY2VvZiB0eXBlO1xufVxuXG5mdW5jdGlvbiBzaXplJDModGVybSkge1xuICByZXR1cm4gdGVybS5sZW5ndGg7XG59XG5cbmZ1bmN0aW9uIGlzX25pbCQxKHgpIHtcbiAgcmV0dXJuIHggPT09IG51bGw7XG59XG5cbmZ1bmN0aW9uIGlzX2F0b20kMSh4KSB7XG4gIHJldHVybiB0eXBlb2YgeCA9PT0gJ3N5bWJvbCc7XG59XG5cbmZ1bmN0aW9uIGlzX2JpbmFyeSQxKHgpIHtcbiAgcmV0dXJuIHR5cGVvZiB4ID09PSAnc3RyaW5nJyB8fCB4IGluc3RhbmNlb2YgU3RyaW5nO1xufVxuXG5mdW5jdGlvbiBpc19ib29sZWFuJDEoeCkge1xuICByZXR1cm4gdHlwZW9mIHggPT09ICdib29sZWFuJyB8fCB4IGluc3RhbmNlb2YgQm9vbGVhbjtcbn1cblxuZnVuY3Rpb24gaXNfZnVuY3Rpb24kMSh4LCBhcml0eSA9IC0xKSB7XG4gIHJldHVybiB0eXBlb2YgeCA9PT0gJ2Z1bmN0aW9uJyB8fCB4IGluc3RhbmNlb2YgRnVuY3Rpb247XG59XG5cbmZ1bmN0aW9uIGlzX2Zsb2F0JDEoeCkge1xuICByZXR1cm4gaXNfbnVtYmVyJDEoeCkgJiYgIU51bWJlci5pc0ludGVnZXIoeCk7XG59XG5cbmZ1bmN0aW9uIGlzX2ludGVnZXIkMSh4KSB7XG4gIHJldHVybiBOdW1iZXIuaXNJbnRlZ2VyKHgpO1xufVxuXG5mdW5jdGlvbiBpc19saXN0JDEoeCkge1xuICByZXR1cm4geCBpbnN0YW5jZW9mIEFycmF5O1xufVxuXG5mdW5jdGlvbiBpc19tYXAkMSh4KSB7XG4gIHJldHVybiB0eXBlb2YgeCA9PT0gJ29iamVjdCcgfHwgeCBpbnN0YW5jZW9mIE9iamVjdDtcbn1cblxuZnVuY3Rpb24gaXNfbnVtYmVyJDEoeCkge1xuICByZXR1cm4gdHlwZW9mIHggPT09ICdudW1iZXInO1xufVxuXG5mdW5jdGlvbiBpc190dXBsZSQxKHgpIHtcbiAgcmV0dXJuIHggaW5zdGFuY2VvZiBUdXBsZSQxO1xufVxuXG5mdW5jdGlvbiBpc19waWQkMSh4KSB7XG4gIHJldHVybiB4IGluc3RhbmNlb2YgUElEO1xufVxuXG5mdW5jdGlvbiBpc19wb3J0JDEoeCkge1xuICByZXR1cm4gZmFsc2U7XG59XG5cbmZ1bmN0aW9uIGlzX3JlZmVyZW5jZSQxKHgpIHtcbiAgcmV0dXJuIGZhbHNlO1xufVxuXG5mdW5jdGlvbiBpc19iaXRzdHJpbmckMSh4KSB7XG4gIHJldHVybiBpc19iaW5hcnkkMSh4KSB8fCB4IGluc3RhbmNlb2YgQml0U3RyaW5nO1xufVxuXG5mdW5jdGlvbiBhZGQob25lLCB0d28pIHtcbiAgcmV0dXJuIG9uZSArIHR3bztcbn1cblxuZnVuY3Rpb24gc3VidHJhY3Qob25lLCB0d28pIHtcbiAgcmV0dXJuIG9uZSArIHR3bztcbn1cblxuZnVuY3Rpb24gbXVsdGlwbHkob25lLCB0d28pIHtcbiAgcmV0dXJuIG9uZSArIHR3bztcbn1cblxuZnVuY3Rpb24gZGl2aWRlKG9uZSwgdHdvKSB7XG4gIHJldHVybiBvbmUgKyB0d287XG59XG5cbmZ1bmN0aW9uIHJlbWFpbmRlcihvbmUsIHR3bykge1xuICByZXR1cm4gb25lICsgdHdvO1xufVxuXG5mdW5jdGlvbiBhcHBseSQxKC4uLmFyZ3MpIHtcbiAgaWYgKGFyZ3MubGVuZ3RoID09PSAyKSB7XG4gICAgYXJnc1swXS5hcHBseShudWxsLCBhcmdzLnNsaWNlKDEpKTtcbiAgfSBlbHNlIHtcbiAgICBhcmdzWzBdW2FyZ3NbMV1dLmFwcGx5KG51bGwsIGFyZ3Muc2xpY2UoMikpO1xuICB9XG59XG5cbmZ1bmN0aW9uIG5ld190dXBsZShhcmdzKSB7XG4gIHJldHVybiBuZXcgVHVwbGUkMSguLi5hcmdzKTtcbn1cblxuZnVuY3Rpb24gZHVwbGljYXRlJDIoZGF0YSwgc2l6ZSkge1xuICBsZXQgYXJyYXkgPSBbXTtcblxuICBmb3IgKHZhciBpID0gc2l6ZSAtIDE7IGkgPj0gMDsgaS0tKSB7XG4gICAgYXJyYXkucHVzaChkYXRhKTtcbiAgfVxuXG4gIHJldHVybiBhcnJheTtcbn1cblxuZnVuY3Rpb24gY29udGFpbnMobGVmdCwgcmlnaHQpIHtcbiAgZm9yIChsZXQgeCBvZiByaWdodCkge1xuICAgIGlmIChQYXR0ZXJucy5tYXRjaF9ub190aHJvdyhsZWZ0LCB4KSAhPSBudWxsKSB7XG4gICAgICByZXR1cm4gdHJ1ZTtcbiAgICB9XG4gIH1cblxuICByZXR1cm4gZmFsc2U7XG59XG5cbmZ1bmN0aW9uIHJldmVyc2UkMShsaXN0KSB7XG4gIHJldHVybiBsaXN0LmNvbmNhdChbXSkucmV2ZXJzZSgpO1xufVxuXG5mdW5jdGlvbiBnZXRfZ2xvYmFsKCkge1xuICBpZiAodHlwZW9mIHNlbGYgIT09ICd1bmRlZmluZWQnKSB7XG4gICAgcmV0dXJuIHNlbGY7XG4gIH0gZWxzZSBpZiAodHlwZW9mIGdsb2JhbCAhPT0gJ3VuZGVmaW5lZCcpIHtcbiAgICByZXR1cm4gZ2xvYmFsO1xuICB9XG5cbiAgdGhyb3cgJ05vIGdsb2JhbCBzdGF0ZSBmb3VuZCc7XG59XG5cbmZ1bmN0aW9uIGNvbmNhdF9saXN0cyhsZWZ0LCByaWdodCkge1xuICByZXR1cm4gbGVmdC5jb25jYXQocmlnaHQpO1xufVxuXG5mdW5jdGlvbiBwcmVwZW5kX3RvX2xpc3QobGlzdCwgaXRlbSkge1xuICByZXR1cm4gW2l0ZW1dLmNvbmNhdChsaXN0KTtcbn1cblxuZ2V0X2dsb2JhbCgpLnByb2Nlc3NlcyA9IGdldF9nbG9iYWwoKS5wcm9jZXNzZXMgfHwgbmV3IFByb2Nlc3NTeXN0ZW0oKTtcblxuXG5cbnZhciBDID0gT2JqZWN0LmZyZWV6ZSh7XG5cdFByb2Nlc3NTeXN0ZW06IFByb2Nlc3NTeXN0ZW0sXG5cdFR1cGxlOiBUdXBsZSQxLFxuXHRQSUQ6IFBJRCxcblx0Qml0U3RyaW5nOiBCaXRTdHJpbmcsXG5cdFBhdHRlcm5zOiBQYXR0ZXJucyxcblx0SW50ZWdlcjogSW50ZWdlciQxLFxuXHRGbG9hdDogRmxvYXQsXG5cdGNhbGxfcHJvcGVydHk6IGNhbGxfcHJvcGVydHksXG5cdGlzX2luc3RhbmNlX29mOiBpc19pbnN0YW5jZV9vZixcblx0c2l6ZTogc2l6ZSQzLFxuXHRpc19uaWw6IGlzX25pbCQxLFxuXHRpc19hdG9tOiBpc19hdG9tJDEsXG5cdGlzX2JpbmFyeTogaXNfYmluYXJ5JDEsXG5cdGlzX2Jvb2xlYW46IGlzX2Jvb2xlYW4kMSxcblx0aXNfZnVuY3Rpb246IGlzX2Z1bmN0aW9uJDEsXG5cdGlzX2Zsb2F0OiBpc19mbG9hdCQxLFxuXHRpc19pbnRlZ2VyOiBpc19pbnRlZ2VyJDEsXG5cdGlzX2xpc3Q6IGlzX2xpc3QkMSxcblx0aXNfbWFwOiBpc19tYXAkMSxcblx0aXNfbnVtYmVyOiBpc19udW1iZXIkMSxcblx0aXNfdHVwbGU6IGlzX3R1cGxlJDEsXG5cdGlzX3BpZDogaXNfcGlkJDEsXG5cdGlzX3BvcnQ6IGlzX3BvcnQkMSxcblx0aXNfcmVmZXJlbmNlOiBpc19yZWZlcmVuY2UkMSxcblx0aXNfYml0c3RyaW5nOiBpc19iaXRzdHJpbmckMSxcblx0YWRkOiBhZGQsXG5cdHN1YnRyYWN0OiBzdWJ0cmFjdCxcblx0bXVsdGlwbHk6IG11bHRpcGx5LFxuXHRkaXZpZGU6IGRpdmlkZSxcblx0cmVtYWluZGVyOiByZW1haW5kZXIsXG5cdGFwcGx5OiBhcHBseSQxLFxuXHRuZXdfdHVwbGU6IG5ld190dXBsZSxcblx0ZHVwbGljYXRlOiBkdXBsaWNhdGUkMixcblx0Y29udGFpbnM6IGNvbnRhaW5zLFxuXHRyZXZlcnNlOiByZXZlcnNlJDEsXG5cdGdldF9nbG9iYWw6IGdldF9nbG9iYWwsXG5cdGNvbmNhdF9saXN0czogY29uY2F0X2xpc3RzLFxuXHRwcmVwZW5kX3RvX2xpc3Q6IHByZXBlbmRfdG9fbGlzdFxufSk7XG5cbmxldCBFbnVtID0ge1xuXG4gIGFsbF9fcW1hcmtfXzogZnVuY3Rpb24gKGNvbGxlY3Rpb24sIGZ1biA9IHggPT4geCkge1xuICAgIGZvciAobGV0IGVsZW0gb2YgY29sbGVjdGlvbikge1xuICAgICAgaWYgKCFmdW4oZWxlbSkpIHtcbiAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgfVxuICAgIH1cblxuICAgIHJldHVybiB0cnVlO1xuICB9LFxuXG4gIGFueV9fcW1hcmtfXzogZnVuY3Rpb24gKGNvbGxlY3Rpb24sIGZ1biA9IHggPT4geCkge1xuICAgIGZvciAobGV0IGVsZW0gb2YgY29sbGVjdGlvbikge1xuICAgICAgaWYgKGZ1bihlbGVtKSkge1xuICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICByZXR1cm4gZmFsc2U7XG4gIH0sXG5cbiAgYXQ6IGZ1bmN0aW9uIChjb2xsZWN0aW9uLCBuLCB0aGVfZGVmYXVsdCA9IG51bGwpIHtcbiAgICBpZiAobiA+IHRoaXMuY291bnQoY29sbGVjdGlvbikgfHwgbiA8IDApIHtcbiAgICAgIHJldHVybiB0aGVfZGVmYXVsdDtcbiAgICB9XG5cbiAgICByZXR1cm4gY29sbGVjdGlvbltuXTtcbiAgfSxcblxuICBjb25jYXQ6IGZ1bmN0aW9uICguLi5lbnVtYWJsZXMpIHtcbiAgICByZXR1cm4gZW51bWFibGVzWzBdLmNvbmNhdChlbnVtYWJsZXNbMV0pO1xuICB9LFxuXG4gIGNvdW50OiBmdW5jdGlvbiAoY29sbGVjdGlvbiwgZnVuID0gbnVsbCkge1xuICAgIGlmIChmdW4gPT0gbnVsbCkge1xuICAgICAgcmV0dXJuIGNvbGxlY3Rpb24ubGVuZ3RoO1xuICAgIH0gZWxzZSB7XG4gICAgICByZXR1cm4gY29sbGVjdGlvbi5maWx0ZXIoZnVuKS5sZW5ndGg7XG4gICAgfVxuICB9LFxuXG4gIGRyb3A6IGZ1bmN0aW9uIChjb2xsZWN0aW9uLCBjb3VudCkge1xuICAgIHJldHVybiBjb2xsZWN0aW9uLnNsaWNlKGNvdW50KTtcbiAgfSxcblxuICBkcm9wX3doaWxlOiBmdW5jdGlvbiAoY29sbGVjdGlvbiwgZnVuKSB7XG4gICAgbGV0IGNvdW50ID0gMDtcblxuICAgIGZvciAobGV0IGVsZW0gb2YgY29sbGVjdGlvbikge1xuICAgICAgaWYgKGZ1bihlbGVtKSkge1xuICAgICAgICBjb3VudCA9IGNvdW50ICsgMTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIGJyZWFrO1xuICAgICAgfVxuICAgIH1cblxuICAgIHJldHVybiBjb2xsZWN0aW9uLnNsaWNlKGNvdW50KTtcbiAgfSxcblxuICBlYWNoOiBmdW5jdGlvbiAoY29sbGVjdGlvbiwgZnVuKSB7XG4gICAgZm9yIChsZXQgZWxlbSBvZiBjb2xsZWN0aW9uKSB7XG4gICAgICBmdW4oZWxlbSk7XG4gICAgfVxuICB9LFxuXG4gIGVtcHR5X19xbWFya19fOiBmdW5jdGlvbiAoY29sbGVjdGlvbikge1xuICAgIHJldHVybiBjb2xsZWN0aW9uLmxlbmd0aCA9PT0gMDtcbiAgfSxcblxuICBmZXRjaDogZnVuY3Rpb24gKGNvbGxlY3Rpb24sIG4pIHtcbiAgICBpZiAoS2VybmVsLmlzX2xpc3QoY29sbGVjdGlvbikpIHtcbiAgICAgIGlmIChuIDwgdGhpcy5jb3VudChjb2xsZWN0aW9uKSAmJiBuID49IDApIHtcbiAgICAgICAgcmV0dXJuIEtlcm5lbC5TcGVjaWFsRm9ybXMudHVwbGUoS2VybmVsLlNwZWNpYWxGb3Jtcy5hdG9tKFwib2tcIiksIGNvbGxlY3Rpb25bbl0pO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgcmV0dXJuIEtlcm5lbC5TcGVjaWFsRm9ybXMuYXRvbShcImVycm9yXCIpO1xuICAgICAgfVxuICAgIH1cblxuICAgIHRocm93IG5ldyBFcnJvcihcImNvbGxlY3Rpb24gaXMgbm90IGFuIEVudW1lcmFibGVcIik7XG4gIH0sXG5cbiAgZmV0Y2hfX2VtYXJrX186IGZ1bmN0aW9uIChjb2xsZWN0aW9uLCBuKSB7XG4gICAgaWYgKEtlcm5lbC5pc19saXN0KGNvbGxlY3Rpb24pKSB7XG4gICAgICBpZiAobiA8IHRoaXMuY291bnQoY29sbGVjdGlvbikgJiYgbiA+PSAwKSB7XG4gICAgICAgIHJldHVybiBjb2xsZWN0aW9uW25dO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKFwib3V0IG9mIGJvdW5kcyBlcnJvclwiKTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICB0aHJvdyBuZXcgRXJyb3IoXCJjb2xsZWN0aW9uIGlzIG5vdCBhbiBFbnVtZXJhYmxlXCIpO1xuICB9LFxuXG4gIGZpbHRlcjogZnVuY3Rpb24gKGNvbGxlY3Rpb24sIGZ1bikge1xuICAgIGxldCByZXN1bHQgPSBbXTtcblxuICAgIGZvciAobGV0IGVsZW0gb2YgY29sbGVjdGlvbikge1xuICAgICAgaWYgKGZ1bihlbGVtKSkge1xuICAgICAgICByZXN1bHQucHVzaChlbGVtKTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICByZXR1cm4gcmVzdWx0O1xuICB9LFxuXG4gIGZpbHRlcl9tYXA6IGZ1bmN0aW9uIChjb2xsZWN0aW9uLCBmaWx0ZXIsIG1hcHBlcikge1xuICAgIHJldHVybiBFbnVtLm1hcChFbnVtLmZpbHRlcihjb2xsZWN0aW9uLCBmaWx0ZXIpLCBtYXBwZXIpO1xuICB9LFxuXG4gIGZpbmQ6IGZ1bmN0aW9uIChjb2xsZWN0aW9uLCBpZl9ub25lID0gbnVsbCwgZnVuKSB7XG4gICAgZm9yIChsZXQgZWxlbSBvZiBjb2xsZWN0aW9uKSB7XG4gICAgICBpZiAoZnVuKGVsZW0pKSB7XG4gICAgICAgIHJldHVybiBlbGVtO1xuICAgICAgfVxuICAgIH1cblxuICAgIHJldHVybiBpZl9ub25lO1xuICB9LFxuXG4gIGludG86IGZ1bmN0aW9uIChjb2xsZWN0aW9uLCBsaXN0KSB7XG4gICAgcmV0dXJuIGxpc3QuY29uY2F0KGNvbGxlY3Rpb24pO1xuICB9LFxuXG4gIG1hcDogZnVuY3Rpb24gKGNvbGxlY3Rpb24sIGZ1bikge1xuICAgIGxldCByZXN1bHQgPSBbXTtcblxuICAgIGZvciAobGV0IGVsZW0gb2YgY29sbGVjdGlvbikge1xuICAgICAgcmVzdWx0LnB1c2goZnVuKGVsZW0pKTtcbiAgICB9XG5cbiAgICByZXR1cm4gcmVzdWx0O1xuICB9LFxuXG4gIG1hcF9yZWR1Y2U6IGZ1bmN0aW9uIChjb2xsZWN0aW9uLCBhY2MsIGZ1bikge1xuICAgIGxldCBtYXBwZWQgPSBLZXJuZWwuU3BlY2lhbEZvcm1zLmxpc3QoKTtcbiAgICBsZXQgdGhlX2FjYyA9IGFjYztcblxuICAgIGZvciAodmFyIGkgPSAwOyBpIDwgdGhpcy5jb3VudChjb2xsZWN0aW9uKTsgaSsrKSB7XG4gICAgICBsZXQgdHVwbGUgPSBmdW4oY29sbGVjdGlvbltpXSwgdGhlX2FjYyk7XG5cbiAgICAgIHRoZV9hY2MgPSBLZXJuZWwuZWxlbSh0dXBsZSwgMSk7XG4gICAgICBtYXBwZWQgPSBLZXJuZWwuU3BlY2lhbEZvcm1zLmxpc3QoLi4ubWFwcGVkLmNvbmNhdChbS2VybmVsLmVsZW0odHVwbGUsIDApXSkpO1xuICAgIH1cblxuICAgIHJldHVybiBLZXJuZWwuU3BlY2lhbEZvcm1zLnR1cGxlKG1hcHBlZCwgdGhlX2FjYyk7XG4gIH0sXG5cbiAgbWVtYmVyX19xbWFya19fOiBmdW5jdGlvbiAoY29sbGVjdGlvbiwgdmFsdWUpIHtcbiAgICByZXR1cm4gY29sbGVjdGlvbi5pbmNsdWRlcyh2YWx1ZSk7XG4gIH0sXG5cbiAgcmVkdWNlOiBmdW5jdGlvbiAoY29sbGVjdGlvbiwgYWNjLCBmdW4pIHtcbiAgICBsZXQgdGhlX2FjYyA9IGFjYztcblxuICAgIGZvciAodmFyIGkgPSAwOyBpIDwgdGhpcy5jb3VudChjb2xsZWN0aW9uKTsgaSsrKSB7XG4gICAgICBsZXQgdHVwbGUgPSBmdW4oY29sbGVjdGlvbltpXSwgdGhlX2FjYyk7XG5cbiAgICAgIHRoZV9hY2MgPSBLZXJuZWwuZWxlbSh0dXBsZSwgMSk7XG4gICAgfVxuXG4gICAgcmV0dXJuIHRoZV9hY2M7XG4gIH0sXG5cbiAgdGFrZTogZnVuY3Rpb24gKGNvbGxlY3Rpb24sIGNvdW50KSB7XG4gICAgcmV0dXJuIGNvbGxlY3Rpb24uc2xpY2UoMCwgY291bnQpO1xuICB9LFxuXG4gIHRha2VfZXZlcnk6IGZ1bmN0aW9uIChjb2xsZWN0aW9uLCBudGgpIHtcbiAgICBsZXQgcmVzdWx0ID0gW107XG4gICAgbGV0IGluZGV4ID0gMDtcblxuICAgIGZvciAobGV0IGVsZW0gb2YgY29sbGVjdGlvbikge1xuICAgICAgaWYgKGluZGV4ICUgbnRoID09PSAwKSB7XG4gICAgICAgIHJlc3VsdC5wdXNoKGVsZW0pO1xuICAgICAgfVxuICAgIH1cblxuICAgIHJldHVybiBLZXJuZWwuU3BlY2lhbEZvcm1zLmxpc3QoLi4ucmVzdWx0KTtcbiAgfSxcblxuICB0YWtlX3doaWxlOiBmdW5jdGlvbiAoY29sbGVjdGlvbiwgZnVuKSB7XG4gICAgbGV0IGNvdW50ID0gMDtcblxuICAgIGZvciAobGV0IGVsZW0gb2YgY29sbGVjdGlvbikge1xuICAgICAgaWYgKGZ1bihlbGVtKSkge1xuICAgICAgICBjb3VudCA9IGNvdW50ICsgMTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIGJyZWFrO1xuICAgICAgfVxuICAgIH1cblxuICAgIHJldHVybiBjb2xsZWN0aW9uLnNsaWNlKDAsIGNvdW50KTtcbiAgfSxcblxuICB0b19saXN0OiBmdW5jdGlvbiAoY29sbGVjdGlvbikge1xuICAgIHJldHVybiBjb2xsZWN0aW9uO1xuICB9XG59O1xuXG5sZXQgU3BlY2lhbEZvcm1zID0ge1xuXG4gIF9fRElSX186IGZ1bmN0aW9uICgpIHtcbiAgICBpZiAoX19kaXJuYW1lKSB7XG4gICAgICByZXR1cm4gX19kaXJuYW1lO1xuICAgIH1cblxuICAgIGlmIChkb2N1bWVudC5jdXJyZW50U2NyaXB0KSB7XG4gICAgICByZXR1cm4gZG9jdW1lbnQuY3VycmVudFNjcmlwdC5zcmM7XG4gICAgfVxuXG4gICAgcmV0dXJuIG51bGw7XG4gIH0sXG5cbiAgYXRvbTogZnVuY3Rpb24gKF92YWx1ZSkge1xuICAgIHJldHVybiBTeW1ib2wuZm9yKF92YWx1ZSk7XG4gIH0sXG5cbiAgbGlzdDogZnVuY3Rpb24gKC4uLmFyZ3MpIHtcbiAgICByZXR1cm4gT2JqZWN0LmZyZWV6ZShhcmdzKTtcbiAgfSxcblxuICBiaXRzdHJpbmc6IGZ1bmN0aW9uICguLi5hcmdzKSB7XG4gICAgcmV0dXJuIG5ldyBCaXRTdHJpbmcoLi4uYXJncyk7XG4gIH0sXG5cbiAgYm91bmQ6IGZ1bmN0aW9uIChfdmFyKSB7XG4gICAgcmV0dXJuIFBhdHRlcm5zLmJvdW5kKF92YXIpO1xuICB9LFxuXG4gIF9jYXNlOiBmdW5jdGlvbiAoY29uZGl0aW9uLCBjbGF1c2VzKSB7XG4gICAgcmV0dXJuIFBhdHRlcm5zLmRlZm1hdGNoKC4uLmNsYXVzZXMpKGNvbmRpdGlvbik7XG4gIH0sXG5cbiAgY29uZDogZnVuY3Rpb24gKGNsYXVzZXMpIHtcbiAgICBmb3IgKGxldCBjbGF1c2Ugb2YgY2xhdXNlcykge1xuICAgICAgaWYgKGNsYXVzZVswXSkge1xuICAgICAgICByZXR1cm4gY2xhdXNlWzFdKCk7XG4gICAgICB9XG4gICAgfVxuXG4gICAgdGhyb3cgbmV3IEVycm9yKCk7XG4gIH0sXG5cbiAgZm46IGZ1bmN0aW9uIChjbGF1c2VzKSB7XG4gICAgcmV0dXJuIFBhdHRlcm5zLmRlZm1hdGNoKGNsYXVzZXMpO1xuICB9LFxuXG4gIG1hcDogZnVuY3Rpb24gKG9iaikge1xuICAgIHJldHVybiBPYmplY3QuZnJlZXplKG9iaik7XG4gIH0sXG5cbiAgbWFwX3VwZGF0ZTogZnVuY3Rpb24gKG1hcCwgdmFsdWVzKSB7XG4gICAgcmV0dXJuIE9iamVjdC5mcmVlemUoT2JqZWN0LmFzc2lnbihPYmplY3QuY3JlYXRlKG1hcC5jb25zdHJ1Y3Rvci5wcm90b3R5cGUpLCBtYXAsIHZhbHVlcykpO1xuICB9LFxuXG4gIF9mb3I6IGZ1bmN0aW9uIChjb2xsZWN0aW9ucywgZnVuLCBmaWx0ZXIgPSAoKSA9PiB0cnVlLCBpbnRvID0gW10sIHByZXZpb3VzVmFsdWVzID0gW10pIHtcbiAgICBsZXQgcGF0dGVybiA9IGNvbGxlY3Rpb25zWzBdWzBdO1xuICAgIGxldCBjb2xsZWN0aW9uID0gY29sbGVjdGlvbnNbMF1bMV07XG5cbiAgICBpZiAoY29sbGVjdGlvbnMubGVuZ3RoID09PSAxKSB7XG5cbiAgICAgIGZvciAobGV0IGVsZW0gb2YgY29sbGVjdGlvbikge1xuICAgICAgICBsZXQgciA9IFBhdHRlcm5zLm1hdGNoX25vX3Rocm93KHBhdHRlcm4sIGVsZW0pO1xuICAgICAgICBsZXQgYXJncyA9IHByZXZpb3VzVmFsdWVzLmNvbmNhdChyKTtcblxuICAgICAgICBpZiAociAmJiBmaWx0ZXIuYXBwbHkodGhpcywgYXJncykpIHtcbiAgICAgICAgICBpbnRvID0gRW51bS5pbnRvKFtmdW4uYXBwbHkodGhpcywgYXJncyldLCBpbnRvKTtcbiAgICAgICAgfVxuICAgICAgfVxuXG4gICAgICByZXR1cm4gaW50bztcbiAgICB9IGVsc2Uge1xuICAgICAgbGV0IF9pbnRvID0gW107XG5cbiAgICAgIGZvciAobGV0IGVsZW0gb2YgY29sbGVjdGlvbikge1xuICAgICAgICBsZXQgciA9IFBhdHRlcm5zLm1hdGNoX25vX3Rocm93KHBhdHRlcm4sIGVsZW0pO1xuICAgICAgICBpZiAocikge1xuICAgICAgICAgIF9pbnRvID0gRW51bS5pbnRvKHRoaXMuX2Zvcihjb2xsZWN0aW9ucy5zbGljZSgxKSwgZnVuLCBmaWx0ZXIsIF9pbnRvLCBwcmV2aW91c1ZhbHVlcy5jb25jYXQocikpLCBpbnRvKTtcbiAgICAgICAgfVxuICAgICAgfVxuXG4gICAgICByZXR1cm4gX2ludG87XG4gICAgfVxuICB9LFxuXG4gIHJlY2VpdmU6IGZ1bmN0aW9uIChyZWNlaXZlX2Z1biwgdGltZW91dF9pbl9tcyA9IG51bGwsIHRpbWVvdXRfZm4gPSB0aW1lID0+IHRydWUpIHtcbiAgICBpZiAodGltZW91dF9pbl9tcyA9PSBudWxsIHx8IHRpbWVvdXRfaW5fbXMgPT09IFN5c3RlbS5mb3IoJ2luZmluaXR5JykpIHtcbiAgICAgIHdoaWxlICh0cnVlKSB7XG4gICAgICAgIGlmIChzZWxmLm1haWxib3gubGVuZ3RoICE9PSAwKSB7XG4gICAgICAgICAgbGV0IG1lc3NhZ2UgPSBzZWxmLm1haWxib3hbMF07XG4gICAgICAgICAgc2VsZi5tYWlsYm94ID0gc2VsZi5tYWlsYm94LnNsaWNlKDEpO1xuICAgICAgICAgIHJldHVybiByZWNlaXZlX2Z1bihtZXNzYWdlKTtcbiAgICAgICAgfVxuICAgICAgfVxuICAgIH0gZWxzZSBpZiAodGltZW91dF9pbl9tcyA9PT0gMCkge1xuICAgICAgaWYgKHNlbGYubWFpbGJveC5sZW5ndGggIT09IDApIHtcbiAgICAgICAgbGV0IG1lc3NhZ2UgPSBzZWxmLm1haWxib3hbMF07XG4gICAgICAgIHNlbGYubWFpbGJveCA9IHNlbGYubWFpbGJveC5zbGljZSgxKTtcbiAgICAgICAgcmV0dXJuIHJlY2VpdmVfZnVuKG1lc3NhZ2UpO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgcmV0dXJuIG51bGw7XG4gICAgICB9XG4gICAgfSBlbHNlIHtcbiAgICAgIGxldCBub3cgPSBEYXRlLm5vdygpO1xuICAgICAgd2hpbGUgKERhdGUubm93KCkgPCBub3cgKyB0aW1lb3V0X2luX21zKSB7XG4gICAgICAgIGlmIChzZWxmLm1haWxib3gubGVuZ3RoICE9PSAwKSB7XG4gICAgICAgICAgbGV0IG1lc3NhZ2UgPSBzZWxmLm1haWxib3hbMF07XG4gICAgICAgICAgc2VsZi5tYWlsYm94ID0gc2VsZi5tYWlsYm94LnNsaWNlKDEpO1xuICAgICAgICAgIHJldHVybiByZWNlaXZlX2Z1bihtZXNzYWdlKTtcbiAgICAgICAgfVxuICAgICAgfVxuXG4gICAgICByZXR1cm4gdGltZW91dF9mbih0aW1lb3V0X2luX21zKTtcbiAgICB9XG4gIH0sXG5cbiAgdHVwbGU6IGZ1bmN0aW9uICguLi5hcmdzKSB7XG4gICAgcmV0dXJuIG5ldyBUdXBsZSQxKC4uLmFyZ3MpO1xuICB9LFxuXG4gIF90cnk6IGZ1bmN0aW9uIChkb19mdW4sIHJlc2N1ZV9mdW5jdGlvbiwgY2F0Y2hfZnVuLCBlbHNlX2Z1bmN0aW9uLCBhZnRlcl9mdW5jdGlvbikge1xuICAgIGxldCByZXN1bHQgPSBudWxsO1xuXG4gICAgdHJ5IHtcbiAgICAgIHJlc3VsdCA9IGRvX2Z1bigpO1xuICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgIGxldCBleF9yZXN1bHQgPSBudWxsO1xuXG4gICAgICBpZiAocmVzY3VlX2Z1bmN0aW9uKSB7XG4gICAgICAgIHRyeSB7XG4gICAgICAgICAgZXhfcmVzdWx0ID0gcmVzY3VlX2Z1bmN0aW9uKGUpO1xuICAgICAgICAgIHJldHVybiBleF9yZXN1bHQ7XG4gICAgICAgIH0gY2F0Y2ggKGV4KSB7XG4gICAgICAgICAgaWYgKGV4IGluc3RhbmNlb2YgUGF0dGVybnMuTWF0Y2hFcnJvcikge1xuICAgICAgICAgICAgdGhyb3cgZXg7XG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICB9XG5cbiAgICAgIGlmIChjYXRjaF9mdW4pIHtcbiAgICAgICAgdHJ5IHtcbiAgICAgICAgICBleF9yZXN1bHQgPSBjYXRjaF9mdW4oZSk7XG4gICAgICAgICAgcmV0dXJuIGV4X3Jlc3VsdDtcbiAgICAgICAgfSBjYXRjaCAoZXgpIHtcbiAgICAgICAgICBpZiAoZXggaW5zdGFuY2VvZiBQYXR0ZXJucy5NYXRjaEVycm9yKSB7XG4gICAgICAgICAgICB0aHJvdyBleDtcbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgIH1cblxuICAgICAgdGhyb3cgZTtcbiAgICB9IGZpbmFsbHkge1xuICAgICAgaWYgKGFmdGVyX2Z1bmN0aW9uKSB7XG4gICAgICAgIGFmdGVyX2Z1bmN0aW9uKCk7XG4gICAgICB9XG4gICAgfVxuXG4gICAgaWYgKGVsc2VfZnVuY3Rpb24pIHtcbiAgICAgIHRyeSB7XG4gICAgICAgIHJldHVybiBlbHNlX2Z1bmN0aW9uKHJlc3VsdCk7XG4gICAgICB9IGNhdGNoIChleCkge1xuICAgICAgICBpZiAoZXggaW5zdGFuY2VvZiBQYXR0ZXJucy5NYXRjaEVycm9yKSB7XG4gICAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdObyBNYXRjaCBGb3VuZCBpbiBFbHNlJyk7XG4gICAgICAgIH1cblxuICAgICAgICB0aHJvdyBleDtcbiAgICAgIH1cbiAgICB9IGVsc2Uge1xuICAgICAgcmV0dXJuIHJlc3VsdDtcbiAgICB9XG4gIH1cblxufTtcblxuZnVuY3Rpb24gdG9fc3RyaW5nJDEodHVwbGUpIHtcbiAgcmV0dXJuIHR1cGxlLnRvU3RyaW5nKCk7XG59O1xuXG5mdW5jdGlvbiBkZWxldGVfYXQodHVwbGUsIGluZGV4KSB7XG4gIGxldCBuZXdfbGlzdCA9IFtdO1xuXG4gIGZvciAodmFyIGkgPSAwOyBpIDwgdHVwbGUuY291bnQoKTsgaSsrKSB7XG4gICAgaWYgKGkgIT09IGluZGV4KSB7XG4gICAgICBuZXdfbGlzdC5wdXNoKHR1cGxlLmdldChpKSk7XG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIEtlcm5lbC5TcGVjaWFsRm9ybXMudHVwbGUuYXBwbHkobnVsbCwgbmV3X2xpc3QpO1xufTtcblxuZnVuY3Rpb24gZHVwbGljYXRlKGRhdGEsIHNpemUpIHtcbiAgbGV0IGFycmF5ID0gW107XG5cbiAgZm9yICh2YXIgaSA9IHNpemUgLSAxOyBpID49IDA7IGktLSkge1xuICAgIGFycmF5LnB1c2goZGF0YSk7XG4gIH1cblxuICByZXR1cm4gS2VybmVsLlNwZWNpYWxGb3Jtcy50dXBsZS5hcHBseShudWxsLCBhcnJheSk7XG59O1xuXG5mdW5jdGlvbiBpbnNlcnRfYXQodHVwbGUsIGluZGV4LCB0ZXJtKSB7XG4gIGxldCBuZXdfdHVwbGUgPSBbXTtcblxuICBmb3IgKHZhciBpID0gMDsgaSA8PSB0dXBsZS5jb3VudCgpOyBpKyspIHtcbiAgICBpZiAoaSA9PT0gaW5kZXgpIHtcbiAgICAgIG5ld190dXBsZS5wdXNoKHRlcm0pO1xuICAgICAgaSsrO1xuICAgICAgbmV3X3R1cGxlLnB1c2godHVwbGUuZ2V0KGkpKTtcbiAgICB9IGVsc2Uge1xuICAgICAgbmV3X3R1cGxlLnB1c2godHVwbGUuZ2V0KGkpKTtcbiAgICB9XG4gIH1cblxuICByZXR1cm4gS2VybmVsLlNwZWNpYWxGb3Jtcy50dXBsZS5hcHBseShudWxsLCBuZXdfdHVwbGUpO1xufTtcblxuZnVuY3Rpb24gZnJvbV9saXN0KGxpc3QpIHtcbiAgcmV0dXJuIEtlcm5lbC5TcGVjaWFsRm9ybXMudHVwbGUuYXBwbHkobnVsbCwgbGlzdCk7XG59O1xuXG5mdW5jdGlvbiB0b19saXN0KHR1cGxlKSB7XG4gIGxldCBuZXdfbGlzdCA9IFtdO1xuXG4gIGZvciAodmFyIGkgPSAwOyBpIDwgdHVwbGUuY291bnQoKTsgaSsrKSB7XG4gICAgbmV3X2xpc3QucHVzaCh0dXBsZS5nZXQoaSkpO1xuICB9XG5cbiAgcmV0dXJuIEtlcm5lbC5TcGVjaWFsRm9ybXMubGlzdCguLi5uZXdfbGlzdCk7XG59O1xuXG52YXIgVHVwbGUgPSB7XG4gIHRvX3N0cmluZzogdG9fc3RyaW5nJDEsXG4gIGRlbGV0ZV9hdCxcbiAgZHVwbGljYXRlLFxuICBpbnNlcnRfYXQsXG4gIGZyb21fbGlzdCxcbiAgdG9fbGlzdFxufTtcblxuLy9odHRwczovL2dpdGh1Yi5jb20vYWlycG9ydHloL3Byb3RvbW9ycGhpc21cbmNsYXNzIFByb3RvY29sIHtcbiAgY29uc3RydWN0b3Ioc3BlYykge1xuICAgIHRoaXMucmVnaXN0cnkgPSBuZXcgTWFwKCk7XG4gICAgdGhpcy5mYWxsYmFjayA9IG51bGw7XG5cbiAgICBmb3IgKGxldCBmdW5OYW1lIGluIHNwZWMpIHtcbiAgICAgIHRoaXNbZnVuTmFtZV0gPSBjcmVhdGVGdW4oZnVuTmFtZSkuYmluZCh0aGlzKTtcbiAgICB9XG5cbiAgICBmdW5jdGlvbiBjcmVhdGVGdW4oZnVuTmFtZSkge1xuXG4gICAgICByZXR1cm4gZnVuY3Rpb24gKC4uLmFyZ3MpIHtcbiAgICAgICAgbGV0IHRoaW5nID0gYXJnc1swXTtcbiAgICAgICAgbGV0IGZ1biA9IG51bGw7XG5cbiAgICAgICAgaWYgKE51bWJlci5pc0ludGVnZXIodGhpbmcpICYmIHRoaXMuaGFzSW1wbGVtZW50YXRpb24oSW50ZWdlciQxKSkge1xuICAgICAgICAgIGZ1biA9IHRoaXMucmVnaXN0cnkuZ2V0KEludGVnZXIkMSlbZnVuTmFtZV07XG4gICAgICAgIH0gZWxzZSBpZiAodHlwZW9mIHRoaW5nID09PSBcIm51bWJlclwiICYmICFOdW1iZXIuaXNJbnRlZ2VyKHRoaW5nKSAmJiB0aGlzLmhhc0ltcGxlbWVudGF0aW9uKEZsb2F0KSkge1xuICAgICAgICAgIGZ1biA9IHRoaXMucmVnaXN0cnkuZ2V0KEZsb2F0KVtmdW5OYW1lXTtcbiAgICAgICAgfSBlbHNlIGlmICh0aGlzLmhhc0ltcGxlbWVudGF0aW9uKHRoaW5nKSkge1xuICAgICAgICAgIGZ1biA9IHRoaXMucmVnaXN0cnkuZ2V0KHRoaW5nLmNvbnN0cnVjdG9yKVtmdW5OYW1lXTtcbiAgICAgICAgfSBlbHNlIGlmICh0aGlzLmZhbGxiYWNrKSB7XG4gICAgICAgICAgZnVuID0gdGhpcy5mYWxsYmFja1tmdW5OYW1lXTtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmIChmdW4gIT0gbnVsbCkge1xuICAgICAgICAgIGxldCByZXR2YWwgPSBmdW4uYXBwbHkodGhpcywgYXJncyk7XG4gICAgICAgICAgcmV0dXJuIHJldHZhbDtcbiAgICAgICAgfVxuXG4gICAgICAgIHRocm93IG5ldyBFcnJvcihcIk5vIGltcGxlbWVudGF0aW9uIGZvdW5kIGZvciBcIiArIHRoaW5nKTtcbiAgICAgIH07XG4gICAgfVxuICB9XG5cbiAgaW1wbGVtZW50YXRpb24odHlwZSwgaW1wbGVtZW50YXRpb24pIHtcbiAgICBpZiAodHlwZSA9PT0gbnVsbCkge1xuICAgICAgdGhpcy5mYWxsYmFjayA9IGltcGxlbWVudGF0aW9uO1xuICAgIH0gZWxzZSB7XG4gICAgICB0aGlzLnJlZ2lzdHJ5LnNldCh0eXBlLCBpbXBsZW1lbnRhdGlvbik7XG4gICAgfVxuICB9XG5cbiAgaGFzSW1wbGVtZW50YXRpb24odGhpbmcpIHtcbiAgICByZXR1cm4gdGhpcy5yZWdpc3RyeS5oYXModGhpbmcuY29uc3RydWN0b3IpO1xuICB9XG59XG5cbmZ1bmN0aW9uIHRsKGxpc3QpIHtcbiAgcmV0dXJuIFNwZWNpYWxGb3Jtcy5saXN0KC4uLmxpc3Quc2xpY2UoMSkpO1xufVxuXG5mdW5jdGlvbiBoZChsaXN0KSB7XG4gIHJldHVybiBsaXN0WzBdO1xufVxuXG5mdW5jdGlvbiBpc19uaWwoeCkge1xuICByZXR1cm4geCA9PT0gbnVsbDtcbn1cblxuZnVuY3Rpb24gaXNfYXRvbSh4KSB7XG4gIHJldHVybiB0eXBlb2YgeCA9PT0gJ3N5bWJvbCc7XG59XG5cbmZ1bmN0aW9uIGlzX2JpbmFyeSh4KSB7XG4gIHJldHVybiB0eXBlb2YgeCA9PT0gJ3N0cmluZycgfHwgeCBpbnN0YW5jZW9mIFN0cmluZztcbn1cblxuZnVuY3Rpb24gaXNfYm9vbGVhbih4KSB7XG4gIHJldHVybiB0eXBlb2YgeCA9PT0gJ2Jvb2xlYW4nIHx8IHggaW5zdGFuY2VvZiBCb29sZWFuO1xufVxuXG5mdW5jdGlvbiBpc19mdW5jdGlvbih4LCBhcml0eSA9IC0xKSB7XG4gIHJldHVybiB0eXBlb2YgeCA9PT0gJ2Z1bmN0aW9uJyB8fCB4IGluc3RhbmNlb2YgRnVuY3Rpb247XG59XG5cbmZ1bmN0aW9uIGlzX2Zsb2F0KHgpIHtcbiAgcmV0dXJuIGlzX251bWJlcih4KSAmJiAhTnVtYmVyLmlzSW50ZWdlcih4KTtcbn1cblxuZnVuY3Rpb24gaXNfaW50ZWdlcih4KSB7XG4gIHJldHVybiBOdW1iZXIuaXNJbnRlZ2VyKHgpO1xufVxuXG5mdW5jdGlvbiBpc19saXN0KHgpIHtcbiAgcmV0dXJuIHggaW5zdGFuY2VvZiBBcnJheTtcbn1cblxuZnVuY3Rpb24gaXNfbWFwKHgpIHtcbiAgcmV0dXJuIHR5cGVvZiB4ID09PSAnb2JqZWN0JyB8fCB4IGluc3RhbmNlb2YgT2JqZWN0O1xufVxuXG5mdW5jdGlvbiBpc19udW1iZXIoeCkge1xuICByZXR1cm4gdHlwZW9mIHggPT09ICdudW1iZXInO1xufVxuXG5mdW5jdGlvbiBpc190dXBsZSh4KSB7XG4gIHJldHVybiB4IGluc3RhbmNlb2YgVHVwbGUkMTtcbn1cblxuZnVuY3Rpb24gbGVuZ3RoKHgpIHtcbiAgcmV0dXJuIHgubGVuZ3RoO1xufVxuXG5mdW5jdGlvbiBpc19waWQoeCkge1xuICByZXR1cm4geCBpbnN0YW5jZW9mIFBJRDtcbn1cblxuZnVuY3Rpb24gaXNfcG9ydCh4KSB7XG4gIHJldHVybiBmYWxzZTtcbn1cblxuZnVuY3Rpb24gaXNfcmVmZXJlbmNlKHgpIHtcbiAgcmV0dXJuIGZhbHNlO1xufVxuXG5mdW5jdGlvbiBpc19iaXRzdHJpbmcoeCkge1xuICByZXR1cm4gaXNfYmluYXJ5KHgpIHx8IHggaW5zdGFuY2VvZiBCaXRTdHJpbmc7XG59XG5cbmZ1bmN0aW9uIF9faW5fXyhsZWZ0LCByaWdodCkge1xuICBmb3IgKGxldCB4IG9mIHJpZ2h0KSB7XG4gICAgaWYgKG1hdGNoX19xbWFya19fKGxlZnQsIHgpKSB7XG4gICAgICByZXR1cm4gdHJ1ZTtcbiAgICB9XG4gIH1cblxuICByZXR1cm4gZmFsc2U7XG59XG5cbmZ1bmN0aW9uIGFicyhudW1iZXIpIHtcbiAgcmV0dXJuIE1hdGguYWJzKG51bWJlcik7XG59XG5cbmZ1bmN0aW9uIHJvdW5kKG51bWJlcikge1xuICByZXR1cm4gTWF0aC5yb3VuZChudW1iZXIpO1xufVxuXG5mdW5jdGlvbiBlbGVtKHR1cGxlLCBpbmRleCkge1xuICBpZiAoaXNfbGlzdCh0dXBsZSkpIHtcbiAgICByZXR1cm4gdHVwbGVbaW5kZXhdO1xuICB9XG5cbiAgcmV0dXJuIHR1cGxlLmdldChpbmRleCk7XG59XG5cbmZ1bmN0aW9uIHJlbShsZWZ0LCByaWdodCkge1xuICByZXR1cm4gbGVmdCAlIHJpZ2h0O1xufVxuXG5mdW5jdGlvbiBkaXYobGVmdCwgcmlnaHQpIHtcbiAgcmV0dXJuIGxlZnQgLyByaWdodDtcbn1cblxuZnVuY3Rpb24gYW5kKGxlZnQsIHJpZ2h0KSB7XG4gIHJldHVybiBsZWZ0ICYmIHJpZ2h0O1xufVxuXG5mdW5jdGlvbiBvcihsZWZ0LCByaWdodCkge1xuICByZXR1cm4gbGVmdCB8fCByaWdodDtcbn1cblxuZnVuY3Rpb24gbm90KGFyZykge1xuICByZXR1cm4gIWFyZztcbn1cblxuZnVuY3Rpb24gYXBwbHkoLi4uYXJncykge1xuICBpZiAoYXJncy5sZW5ndGggPT09IDMpIHtcbiAgICBsZXQgbW9kID0gYXJnc1swXTtcbiAgICBsZXQgZnVuYyA9IGFyZ3NbMV07XG4gICAgbGV0IGZ1bmNfYXJncyA9IGFyZ3NbMl07XG4gICAgcmV0dXJuIG1vZFtmdW5jXS5hcHBseShudWxsLCBmdW5jX2FyZ3MpO1xuICB9IGVsc2Uge1xuICAgIGxldCBmdW5jID0gYXJnc1swXTtcbiAgICBsZXQgZnVuY19hcmdzID0gYXJnc1sxXTtcblxuICAgIHJldHVybiBmdW5jLmFwcGx5KG51bGwsIGZ1bmNfYXJncyk7XG4gIH1cbn1cblxuZnVuY3Rpb24gdG9fc3RyaW5nKGFyZykge1xuICBpZiAoaXNfdHVwbGUoYXJnKSkge1xuICAgIHJldHVybiBUdXBsZS50b19zdHJpbmcoYXJnKTtcbiAgfVxuXG4gIHJldHVybiBhcmcudG9TdHJpbmcoKTtcbn1cblxuZnVuY3Rpb24gbWF0Y2hfX3FtYXJrX18ocGF0dGVybiwgZXhwciwgZ3VhcmQgPSAoKSA9PiB0cnVlKSB7XG4gIHJldHVybiBQYXR0ZXJucy5tYXRjaF9ub190aHJvdyhwYXR0ZXJuLCBleHByLCBndWFyZCkgIT0gbnVsbDtcbn1cblxuZnVuY3Rpb24gZGVmc3RydWN0KGRlZmF1bHRzKSB7XG4gIHJldHVybiBjbGFzcyB7XG4gICAgY29uc3RydWN0b3IodXBkYXRlID0ge30pIHtcbiAgICAgIGxldCB0aGVfdmFsdWVzID0gT2JqZWN0LmFzc2lnbihkZWZhdWx0cywgdXBkYXRlKTtcbiAgICAgIE9iamVjdC5hc3NpZ24odGhpcywgdGhlX3ZhbHVlcyk7XG4gICAgfVxuXG4gICAgc3RhdGljIGNyZWF0ZSh1cGRhdGVzID0ge30pIHtcbiAgICAgIGxldCB4ID0gbmV3IHRoaXModXBkYXRlcyk7XG4gICAgICByZXR1cm4gT2JqZWN0LmZyZWV6ZSh4KTtcbiAgICB9XG4gIH07XG59XG5cbmZ1bmN0aW9uIGRlZnByb3RvY29sKHNwZWMpIHtcbiAgcmV0dXJuIG5ldyBQcm90b2NvbChzcGVjKTtcbn1cblxuZnVuY3Rpb24gZGVmaW1wbChwcm90b2NvbCwgdHlwZSwgaW1wbCkge1xuICBwcm90b2NvbC5pbXBsZW1lbnRhdGlvbih0eXBlLCBpbXBsKTtcbn1cblxudmFyIEtlcm5lbCA9IHtcbiAgU3BlY2lhbEZvcm1zLFxuICB0bCxcbiAgaGQsXG4gIGlzX25pbCxcbiAgaXNfYXRvbSxcbiAgaXNfYmluYXJ5LFxuICBpc19ib29sZWFuLFxuICBpc19mdW5jdGlvbixcbiAgaXNfZmxvYXQsXG4gIGlzX2ludGVnZXIsXG4gIGlzX2xpc3QsXG4gIGlzX21hcCxcbiAgaXNfbnVtYmVyLFxuICBpc190dXBsZSxcbiAgbGVuZ3RoLFxuICBpc19waWQsXG4gIGlzX3BvcnQsXG4gIGlzX3JlZmVyZW5jZSxcbiAgaXNfYml0c3RyaW5nLFxuICBpbjogX19pbl9fLFxuICBhYnMsXG4gIHJvdW5kLFxuICBlbGVtLFxuICByZW0sXG4gIGRpdixcbiAgYW5kLFxuICBvcixcbiAgbm90LFxuICBhcHBseSxcbiAgdG9fc3RyaW5nLFxuICBtYXRjaF9fcW1hcmtfXyxcbiAgZGVmc3RydWN0LFxuICBkZWZwcm90b2NvbCxcbiAgZGVmaW1wbFxufTtcblxubGV0IEF0b20gPSB7fTtcblxuQXRvbS50b19zdHJpbmcgPSBmdW5jdGlvbiAoYXRvbSkge1xuICByZXR1cm4gU3ltYm9sLmtleUZvcihhdG9tKTtcbn07XG5cbkF0b20udG9fY2hhcl9saXN0ID0gZnVuY3Rpb24gKGF0b20pIHtcbiAgcmV0dXJuIEF0b20udG9fc3RyaW5nKGF0b20pLnNwbGl0KCcnKTtcbn07XG5cbmxldCBJbnRlZ2VyID0ge1xuXG4gIGlzX2V2ZW46IGZ1bmN0aW9uIChuKSB7XG4gICAgcmV0dXJuIG4gJSAyID09PSAwO1xuICB9LFxuXG4gIGlzX29kZDogZnVuY3Rpb24gKG4pIHtcbiAgICByZXR1cm4gbiAlIDIgIT09IDA7XG4gIH0sXG5cbiAgcGFyc2U6IGZ1bmN0aW9uIChiaW4pIHtcbiAgICBsZXQgcmVzdWx0ID0gcGFyc2VJbnQoYmluKTtcblxuICAgIGlmIChpc05hTihyZXN1bHQpKSB7XG4gICAgICByZXR1cm4gS2VybmVsLlNwZWNpYWxGb3Jtcy5hdG9tKFwiZXJyb3JcIik7XG4gICAgfVxuXG4gICAgbGV0IGluZGV4T2ZEb3QgPSBiaW4uaW5kZXhPZihcIi5cIik7XG5cbiAgICBpZiAoaW5kZXhPZkRvdCA+PSAwKSB7XG4gICAgICByZXR1cm4gS2VybmVsLlNwZWNpYWxGb3Jtcy50dXBsZShyZXN1bHQsIGJpbi5zdWJzdHJpbmcoaW5kZXhPZkRvdCkpO1xuICAgIH1cblxuICAgIHJldHVybiBLZXJuZWwuU3BlY2lhbEZvcm1zLnR1cGxlKHJlc3VsdCwgXCJcIik7XG4gIH0sXG5cbiAgdG9fY2hhcl9saXN0OiBmdW5jdGlvbiAobnVtYmVyLCBiYXNlID0gMTApIHtcbiAgICByZXR1cm4gbnVtYmVyLnRvU3RyaW5nKGJhc2UpLnNwbGl0KFwiXCIpO1xuICB9LFxuXG4gIHRvX3N0cmluZzogZnVuY3Rpb24gKG51bWJlciwgYmFzZSA9IDEwKSB7XG4gICAgcmV0dXJuIG51bWJlci50b1N0cmluZyhiYXNlKTtcbiAgfVxufTtcblxubGV0IENoYXJzJDEgPSBLZXJuZWwuZGVmcHJvdG9jb2woe1xuICB0b19zdHJpbmc6IGZ1bmN0aW9uICh0aGluZykge31cbn0pO1xuXG5LZXJuZWwuZGVmaW1wbChDaGFycyQxLCBCaXRTdHJpbmcsIHtcbiAgdG9fc3RyaW5nOiBmdW5jdGlvbiAodGhpbmcpIHtcbiAgICBpZiAoS2VybmVsLmlzX2JpbmFyeSh0aGluZykpIHtcbiAgICAgIHJldHVybiB0aGluZztcbiAgICB9XG5cbiAgICByZXR1cm4gdGhpbmcudG9TdHJpbmcoKTtcbiAgfVxufSk7XG5cbktlcm5lbC5kZWZpbXBsKENoYXJzJDEsIFN5bWJvbCwge1xuICB0b19zdHJpbmc6IGZ1bmN0aW9uICh0aGluZykge1xuICAgIGlmIChuaWwpIHtcbiAgICAgIHJldHVybiBcIlwiO1xuICAgIH1cblxuICAgIHJldHVybiBBdG9tLnRvX3N0cmluZyh0aGluZyk7XG4gIH1cbn0pO1xuXG5LZXJuZWwuZGVmaW1wbChDaGFycyQxLCBJbnRlZ2VyJDEsIHtcbiAgdG9fc3RyaW5nOiBmdW5jdGlvbiAodGhpbmcpIHtcbiAgICByZXR1cm4gSW50ZWdlci50b19zdHJpbmcodGhpbmcpO1xuICB9XG59KTtcblxuS2VybmVsLmRlZmltcGwoQ2hhcnMkMSwgRmxvYXQsIHtcbiAgdG9fc3RyaW5nOiBmdW5jdGlvbiAodGhpbmcpIHtcbiAgICByZXR1cm4gdGhpbmcudG9TdHJpbmc7XG4gIH1cbn0pO1xuXG5LZXJuZWwuZGVmaW1wbChDaGFycyQxLCBBcnJheSwge1xuICB0b19zdHJpbmc6IGZ1bmN0aW9uICh0aGluZykge1xuICAgIHJldHVybiB0aGluZy50b1N0cmluZygpO1xuICB9XG59KTtcblxuS2VybmVsLmRlZmltcGwoQ2hhcnMkMSwgVHVwbGUkMSwge1xuICB0b19zdHJpbmc6IGZ1bmN0aW9uICh0aGluZykge1xuICAgIHJldHVybiBUdXBsZS50b19zdHJpbmcodGhpbmcpO1xuICB9XG59KTtcblxuS2VybmVsLmRlZmltcGwoQ2hhcnMkMSwgbnVsbCwge1xuICB0b19zdHJpbmc6IGZ1bmN0aW9uICh0aGluZykge1xuICAgIHJldHVybiB0aGluZy50b1N0cmluZygpO1xuICB9XG59KTtcblxuZnVuY3Rpb24gdG9fYXRvbShzdHJpbmcpIHtcbiAgcmV0dXJuIFN5bWJvbC5mb3Ioc3RyaW5nKTtcbn1cblxuZnVuY3Rpb24gdG9fZXhpc3RpbmdfYXRvbShzdHJpbmcpIHtcbiAgcmV0dXJuIFN5bWJvbC5mb3Ioc3RyaW5nKTtcbn1cblxuZnVuY3Rpb24gdG9fY2hhcl9saXN0KHN0cmluZykge1xuICByZXR1cm4gc3RyaW5nLnNwbGl0KCcnKTtcbn1cblxuZnVuY3Rpb24gdG9fZmxvYXQoc3RyaW5nKSB7XG4gIHJldHVybiBwYXJzZUZsb2F0KHN0cmluZyk7XG59XG5cbmZ1bmN0aW9uIHRvX2ludGVnZXIoc3RyaW5nLCBiYXNlID0gMTApIHtcbiAgcmV0dXJuIHBhcnNlSW50KHN0cmluZywgYmFzZSk7XG59XG5cbmZ1bmN0aW9uIHVwY2FzZShiaW5hcnkpIHtcbiAgcmV0dXJuIGJpbmFyeS50b1VwcGVyQ2FzZSgpO1xufVxuXG5mdW5jdGlvbiBkb3duY2FzZShiaW5hcnkpIHtcbiAgcmV0dXJuIGJpbmFyeS50b0xvd2VyQ2FzZSgpO1xufVxuXG5mdW5jdGlvbiBhdChzdHJpbmcsIHBvc2l0aW9uKSB7XG4gIGlmIChwb3NpdGlvbiA+IHN0cmluZy5sZW5ndGggLSAxKSB7XG4gICAgcmV0dXJuIG51bGw7XG4gIH1cblxuICByZXR1cm4gc3RyaW5nW3Bvc2l0aW9uXTtcbn1cblxuZnVuY3Rpb24gY2FwaXRhbGl6ZShzdHJpbmcpIHtcbiAgbGV0IHJldHVyblN0cmluZyA9ICcnO1xuXG4gIGZvciAobGV0IGkgPSAwOyBpIDwgc3RyaW5nLmxlbmd0aDsgaSsrKSB7XG4gICAgaWYgKGkgPT09IDApIHtcbiAgICAgIHJldHVyblN0cmluZyA9IHJldHVyblN0cmluZyArIHN0cmluZ1tpXS50b1VwcGVyQ2FzZSgpO1xuICAgIH0gZWxzZSB7XG4gICAgICByZXR1cm5TdHJpbmcgPSByZXR1cm5TdHJpbmcgKyBzdHJpbmdbaV0udG9Mb3dlckNhc2UoKTtcbiAgICB9XG4gIH1cblxuICByZXR1cm4gcmV0dXJuU3RyaW5nO1xufVxuXG5mdW5jdGlvbiBjb2RlcG9pbnRzKHN0cmluZykge1xuICByZXR1cm4gdG9fY2hhcl9saXN0KHN0cmluZykubWFwKGZ1bmN0aW9uIChjKSB7XG4gICAgcmV0dXJuIGMuY29kZVBvaW50QXQoMCk7XG4gIH0pO1xufVxuXG5mdW5jdGlvbiBjb250YWluc19fcW1fXyhzdHJpbmcsIGNvbnRhaW5zKSB7XG4gIGlmIChBcnJheS5pc0FycmF5KGNvbnRhaW5zKSkge1xuICAgIHJldHVybiBjb250YWlucy5zb21lKGZ1bmN0aW9uIChzKSB7XG4gICAgICByZXR1cm4gc3RyaW5nLmluZGV4T2YocykgPiAtMTtcbiAgICB9KTtcbiAgfVxuXG4gIHJldHVybiBzdHJpbmcuaW5kZXhPZihjb250YWlucykgPiAtMTtcbn1cblxuZnVuY3Rpb24gZHVwbGljYXRlJDEoc3ViamVjdCwgbikge1xuICByZXR1cm4gc3ViamVjdC5yZXBlYXQobik7XG59XG5cbmZ1bmN0aW9uIGVuZHNfd2l0aF9fcW1fXyhzdHJpbmcsIHN1ZmZpeGVzKSB7XG4gIGlmIChBcnJheS5pc0FycmF5KHN1ZmZpeGVzKSkge1xuICAgIHJldHVybiBzdWZmaXhlcy5zb21lKGZ1bmN0aW9uIChzKSB7XG4gICAgICByZXR1cm4gc3RyaW5nLmVuZHNXaXRoKHMpO1xuICAgIH0pO1xuICB9XG5cbiAgcmV0dXJuIHN0cmluZy5lbmRzV2l0aChzdWZmaXhlcyk7XG59XG5cbmZ1bmN0aW9uIGZpcnN0KHN0cmluZykge1xuICBpZiAoIXN0cmluZykge1xuICAgIHJldHVybiBudWxsO1xuICB9XG5cbiAgcmV0dXJuIHN0cmluZ1swXTtcbn1cblxuZnVuY3Rpb24gZ3JhcGhlbWVzKHN0cmluZykge1xuICByZXR1cm4gc3RyaW5nLnNwbGl0KCcnKTtcbn1cblxuZnVuY3Rpb24gbGFzdChzdHJpbmcpIHtcbiAgaWYgKCFzdHJpbmcpIHtcbiAgICByZXR1cm4gbnVsbDtcbiAgfVxuXG4gIHJldHVybiBzdHJpbmdbc3RyaW5nLmxlbmd0aCAtIDFdO1xufVxuXG5mdW5jdGlvbiBsZW5ndGgkMShzdHJpbmcpIHtcbiAgcmV0dXJuIHN0cmluZy5sZW5ndGg7XG59XG5cbmZ1bmN0aW9uIG1hdGNoX19xbV9fKHN0cmluZywgcmVnZXgpIHtcbiAgcmV0dXJuIHN0cmluZy5tYXRjaChyZWdleCkgIT0gbnVsbDtcbn1cblxuZnVuY3Rpb24gbmV4dF9jb2RlcG9pbnQoc3RyaW5nKSB7XG4gIGlmICghc3RyaW5nIHx8IHN0cmluZyA9PT0gJycpIHtcbiAgICByZXR1cm4gbnVsbDtcbiAgfVxuXG4gIHJldHVybiBLZXJuZWwuU3BlY2lhbEZvcm1zLnR1cGxlKHN0cmluZ1swXS5jb2RlUG9pbnRBdCgwKSwgc3RyaW5nLnN1YnN0cigxKSk7XG59XG5cbmZ1bmN0aW9uIG5leHRfZ3JhcGhlbWUoc3RyaW5nKSB7XG4gIGlmICghc3RyaW5nIHx8IHN0cmluZyA9PT0gJycpIHtcbiAgICByZXR1cm4gbnVsbDtcbiAgfVxuXG4gIHJldHVybiBLZXJuZWwuU3BlY2lhbEZvcm1zLnR1cGxlKHN0cmluZ1swXSwgc3RyaW5nLnN1YnN0cigxKSk7XG59XG5cbmZ1bmN0aW9uIHJldmVyc2Uoc3RyaW5nKSB7XG4gIGxldCByZXR1cm5WYWx1ZSA9ICcnO1xuXG4gIGZvciAodmFyIGkgPSBzdHJpbmcubGVuZ3RoIC0gMTsgaSA+PSAwOyBpLS0pIHtcbiAgICByZXR1cm5WYWx1ZSA9IHJldHVyblZhbHVlICsgc3RyaW5nW2ldO1xuICB9O1xuXG4gIHJldHVybiByZXR1cm5WYWx1ZTtcbn1cblxuZnVuY3Rpb24gc3BsaXQoc3RyaW5nKSB7XG4gIHJldHVybiBzdHJpbmcuc3BsaXQoKTtcbn1cblxuZnVuY3Rpb24gc3RhcnRzX3dpdGhfX3FtX18oc3RyaW5nLCBwcmVmaXhlcykge1xuICBpZiAoQXJyYXkuaXNBcnJheShwcmVmaXhlcykpIHtcbiAgICByZXR1cm4gcHJlZml4ZXMuc29tZShmdW5jdGlvbiAocykge1xuICAgICAgcmV0dXJuIHN0cmluZy5zdGFydHNXaXRoKHMpO1xuICAgIH0pO1xuICB9XG5cbiAgcmV0dXJuIHN0cmluZy5zdGFydHNXaXRoKHByZWZpeGVzKTtcbn1cblxuZnVuY3Rpb24gdmFsaWRfY2hhcmFjdGVyX19xbV9fKGNvZGVwb2ludCkge1xuICB0cnkge1xuICAgIHJldHVybiBTdHJpbmcuZnJvbUNvZGVQb2ludChjb2RlcG9pbnQpICE9IG51bGw7XG4gIH0gY2F0Y2ggKGUpIHtcbiAgICByZXR1cm4gZmFsc2U7XG4gIH1cbn1cblxudmFyIFN0cmluZyQxID0ge1xuICBhdCxcbiAgY2FwaXRhbGl6ZSxcbiAgY29kZXBvaW50cyxcbiAgY29udGFpbnNfX3FtX18sXG4gIGRvd25jYXNlLFxuICBkdXBsaWNhdGU6IGR1cGxpY2F0ZSQxLFxuICBlbmRzX3dpdGhfX3FtX18sXG4gIGZpcnN0LFxuICBncmFwaGVtZXMsXG4gIGxhc3QsXG4gIGxlbmd0aDogbGVuZ3RoJDEsXG4gIG1hdGNoX19xbV9fLFxuICBuZXh0X2NvZGVwb2ludCxcbiAgbmV4dF9ncmFwaGVtZSxcbiAgcmV2ZXJzZSxcbiAgc3BsaXQsXG4gIHN0YXJ0c193aXRoX19xbV9fLFxuICB0b19hdG9tLFxuICB0b19jaGFyX2xpc3QsXG4gIHRvX2V4aXN0aW5nX2F0b20sXG4gIHRvX2Zsb2F0LFxuICB0b19pbnRlZ2VyLFxuICB1cGNhc2UsXG4gIHZhbGlkX2NoYXJhY3Rlcl9fcW1fXyxcbiAgQ2hhcnM6IENoYXJzJDFcbn07XG5cbmxldCBDaGFycyA9IEtlcm5lbC5kZWZwcm90b2NvbCh7XG4gIHRvX2NoYXJfbGlzdDogZnVuY3Rpb24gKHRoaW5nKSB7fVxufSk7XG5cbktlcm5lbC5kZWZpbXBsKENoYXJzLCBCaXRTdHJpbmcsIHtcbiAgdG9fY2hhcl9saXN0OiBmdW5jdGlvbiAodGhpbmcpIHtcbiAgICBpZiAoS2VybmVsLmlzX2JpbmFyeSh0aGluZykpIHtcbiAgICAgIHJldHVybiBTdHJpbmckMS50b19jaGFyX2xpc3QodGhpbmcpO1xuICAgIH1cblxuICAgIHJldHVybiB0aGluZy50b1N0cmluZygpO1xuICB9XG59KTtcblxuS2VybmVsLmRlZmltcGwoQ2hhcnMsIFN5bWJvbCwge1xuICB0b19jaGFyX2xpc3Q6IGZ1bmN0aW9uICh0aGluZykge1xuICAgIHJldHVybiBBdG9tLnRvX2NoYXJfbGlzdCh0aGluZyk7XG4gIH1cbn0pO1xuXG5LZXJuZWwuZGVmaW1wbChDaGFycywgSW50ZWdlciQxLCB7XG4gIHRvX2NoYXJfbGlzdDogZnVuY3Rpb24gKHRoaW5nKSB7XG4gICAgcmV0dXJuIEludGVnZXIudG9fY2hhcl9saXN0KHRoaW5nKTtcbiAgfVxufSk7XG5cbktlcm5lbC5kZWZpbXBsKENoYXJzLCBBcnJheSwge1xuICB0b19jaGFyX2xpc3Q6IGZ1bmN0aW9uICh0aGluZykge1xuICAgIHJldHVybiB0aGluZztcbiAgfVxufSk7XG5cbmxldCBMaXN0ID0ge307XG5cbkxpc3QuQ2hhcnMgPSBDaGFycztcblxuTGlzdC5kZWxldGUgPSBmdW5jdGlvbiAobGlzdCwgaXRlbSkge1xuICBsZXQgbmV3X3ZhbHVlID0gW107XG4gIGxldCB2YWx1ZV9mb3VuZCA9IGZhbHNlO1xuXG4gIGZvciAobGV0IHggb2YgbGlzdCkge1xuICAgIGlmICh4ID09PSBpdGVtICYmIHZhbHVlX2ZvdW5kICE9PSBmYWxzZSkge1xuICAgICAgbmV3X3ZhbHVlLnB1c2goeCk7XG4gICAgICB2YWx1ZV9mb3VuZCA9IHRydWU7XG4gICAgfSBlbHNlIGlmICh4ICE9PSBpdGVtKSB7XG4gICAgICBuZXdfdmFsdWUucHVzaCh4KTtcbiAgICB9XG4gIH1cblxuICByZXR1cm4gS2VybmVsLlNwZWNpYWxGb3Jtcy5saXN0KC4uLm5ld192YWx1ZSk7XG59O1xuXG5MaXN0LmRlbGV0ZV9hdCA9IGZ1bmN0aW9uIChsaXN0LCBpbmRleCkge1xuICBsZXQgbmV3X3ZhbHVlID0gW107XG5cbiAgZm9yIChsZXQgaSA9IDA7IGkgPCBsaXN0Lmxlbmd0aDsgaSsrKSB7XG4gICAgaWYgKGkgIT09IGluZGV4KSB7XG4gICAgICBuZXdfdmFsdWUucHVzaChsaXN0W2ldKTtcbiAgICB9XG4gIH1cblxuICByZXR1cm4gS2VybmVsLlNwZWNpYWxGb3Jtcy5saXN0KC4uLm5ld192YWx1ZSk7XG59O1xuXG5MaXN0LmR1cGxpY2F0ZSA9IGZ1bmN0aW9uIChlbGVtLCBuKSB7XG4gIGxldCBuZXdfdmFsdWUgPSBbXTtcblxuICBmb3IgKHZhciBpID0gMDsgaSA8IG47IGkrKykge1xuICAgIG5ld192YWx1ZS5wdXNoKGVsZW0pO1xuICB9XG5cbiAgcmV0dXJuIEtlcm5lbC5TcGVjaWFsRm9ybXMubGlzdCguLi5uZXdfdmFsdWUpO1xufTtcblxuTGlzdC5maXJzdCA9IGZ1bmN0aW9uIChsaXN0KSB7XG4gIHJldHVybiBsaXN0WzBdO1xufTtcblxuTGlzdC5mbGF0dGVuID0gZnVuY3Rpb24gKGxpc3QsIHRhaWwgPSBLZXJuZWwuU3BlY2lhbEZvcm1zLmxpc3QoKSkge1xuICBsZXQgbmV3X3ZhbHVlID0gW107XG5cbiAgZm9yIChsZXQgeCBvZiBsaXN0KSB7XG4gICAgaWYgKEtlcm5lbC5pc19saXN0KHgpKSB7XG4gICAgICBuZXdfdmFsdWUgPSBuZXdfdmFsdWUuY29uY2F0KExpc3QuZmxhdHRlbih4KSk7XG4gICAgfSBlbHNlIHtcbiAgICAgIG5ld192YWx1ZS5wdXNoKHgpO1xuICAgIH1cbiAgfVxuXG4gIG5ld192YWx1ZSA9IG5ld192YWx1ZS5jb25jYXQodGFpbCk7XG5cbiAgcmV0dXJuIEtlcm5lbC5TcGVjaWFsRm9ybXMubGlzdCguLi5uZXdfdmFsdWUpO1xufTtcblxuTGlzdC5mb2xkbCA9IGZ1bmN0aW9uIChsaXN0LCBhY2MsIGZ1bmMpIHtcbiAgcmV0dXJuIGxpc3QucmVkdWNlKGZ1bmMsIGFjYyk7XG59O1xuXG5MaXN0LmZvbGRyID0gZnVuY3Rpb24gKGxpc3QsIGFjYywgZnVuYykge1xuICBsZXQgbmV3X2FjYyA9IGFjYztcblxuICBmb3IgKHZhciBpID0gbGlzdC5sZW5ndGggLSAxOyBpID49IDA7IGktLSkge1xuICAgIG5ld19hY2MgPSBmdW5jKGxpc3RbaV0sIG5ld19hY2MpO1xuICB9XG5cbiAgcmV0dXJuIG5ld19hY2M7XG59O1xuXG5MaXN0Lmluc2VydF9hdCA9IGZ1bmN0aW9uIChsaXN0LCBpbmRleCwgdmFsdWUpIHtcbiAgbGV0IG5ld192YWx1ZSA9IFtdO1xuXG4gIGZvciAobGV0IGkgPSAwOyBpIDwgbGlzdC5sZW5ndGg7IGkrKykge1xuICAgIGlmIChpID09PSBpbmRleCkge1xuICAgICAgbmV3X3ZhbHVlLnB1c2godmFsdWUpO1xuICAgICAgbmV3X3ZhbHVlLnB1c2gobGlzdFtpXSk7XG4gICAgfSBlbHNlIHtcbiAgICAgIG5ld192YWx1ZS5wdXNoKGxpc3RbaV0pO1xuICAgIH1cbiAgfVxuXG4gIHJldHVybiBLZXJuZWwuU3BlY2lhbEZvcm1zLmxpc3QoLi4ubmV3X3ZhbHVlKTtcbn07XG5cbkxpc3Qua2V5ZGVsZXRlID0gZnVuY3Rpb24gKGxpc3QsIGtleSwgcG9zaXRpb24pIHtcbiAgbGV0IG5ld19saXN0ID0gW107XG5cbiAgZm9yIChsZXQgaSA9IDA7IGkgPCBsaXN0Lmxlbmd0aDsgaSsrKSB7XG4gICAgaWYgKCFLZXJuZWwubWF0Y2hfX3FtYXJrX18obGlzdFtpXVtwb3NpdGlvbl0sIGtleSkpIHtcbiAgICAgIG5ld19saXN0LnB1c2gobGlzdFtpXSk7XG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIEtlcm5lbC5TcGVjaWFsRm9ybXMubGlzdCguLi5uZXdfbGlzdCk7XG59O1xuXG5MaXN0LmtleWZpbmQgPSBmdW5jdGlvbiAobGlzdCwga2V5LCBwb3NpdGlvbiwgX2RlZmF1bHQgPSBudWxsKSB7XG5cbiAgZm9yIChsZXQgaSA9IDA7IGkgPCBsaXN0Lmxlbmd0aDsgaSsrKSB7XG4gICAgaWYgKEtlcm5lbC5tYXRjaF9fcW1hcmtfXyhsaXN0W2ldW3Bvc2l0aW9uXSwga2V5KSkge1xuICAgICAgcmV0dXJuIGxpc3RbaV07XG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIF9kZWZhdWx0O1xufTtcblxuTGlzdC5rZXltZW1iZXJfX3FtYXJrX18gPSBmdW5jdGlvbiAobGlzdCwga2V5LCBwb3NpdGlvbikge1xuXG4gIGZvciAobGV0IGkgPSAwOyBpIDwgbGlzdC5sZW5ndGg7IGkrKykge1xuICAgIGlmIChLZXJuZWwubWF0Y2hfX3FtYXJrX18obGlzdFtpXVtwb3NpdGlvbl0sIGtleSkpIHtcbiAgICAgIHJldHVybiB0cnVlO1xuICAgIH1cbiAgfVxuXG4gIHJldHVybiBmYWxzZTtcbn07XG5cbkxpc3Qua2V5cmVwbGFjZSA9IGZ1bmN0aW9uIChsaXN0LCBrZXksIHBvc2l0aW9uLCBuZXdfdHVwbGUpIHtcbiAgbGV0IG5ld19saXN0ID0gW107XG5cbiAgZm9yIChsZXQgaSA9IDA7IGkgPCBsaXN0Lmxlbmd0aDsgaSsrKSB7XG4gICAgaWYgKCFLZXJuZWwubWF0Y2hfX3FtYXJrX18obGlzdFtpXVtwb3NpdGlvbl0sIGtleSkpIHtcbiAgICAgIG5ld19saXN0LnB1c2gobGlzdFtpXSk7XG4gICAgfSBlbHNlIHtcbiAgICAgIG5ld19saXN0LnB1c2gobmV3X3R1cGxlKTtcbiAgICB9XG4gIH1cblxuICByZXR1cm4gS2VybmVsLlNwZWNpYWxGb3Jtcy5saXN0KC4uLm5ld19saXN0KTtcbn07XG5cbkxpc3Qua2V5c29ydCA9IGZ1bmN0aW9uIChsaXN0LCBwb3NpdGlvbikge1xuICBsZXQgbmV3X2xpc3QgPSBsaXN0O1xuXG4gIG5ld19saXN0LnNvcnQoZnVuY3Rpb24gKGEsIGIpIHtcbiAgICBpZiAocG9zaXRpb24gPT09IDApIHtcbiAgICAgIGlmIChhW3Bvc2l0aW9uXS52YWx1ZSA8IGJbcG9zaXRpb25dLnZhbHVlKSB7XG4gICAgICAgIHJldHVybiAtMTtcbiAgICAgIH1cblxuICAgICAgaWYgKGFbcG9zaXRpb25dLnZhbHVlID4gYltwb3NpdGlvbl0udmFsdWUpIHtcbiAgICAgICAgcmV0dXJuIDE7XG4gICAgICB9XG5cbiAgICAgIHJldHVybiAwO1xuICAgIH0gZWxzZSB7XG4gICAgICBpZiAoYVtwb3NpdGlvbl0gPCBiW3Bvc2l0aW9uXSkge1xuICAgICAgICByZXR1cm4gLTE7XG4gICAgICB9XG5cbiAgICAgIGlmIChhW3Bvc2l0aW9uXSA+IGJbcG9zaXRpb25dKSB7XG4gICAgICAgIHJldHVybiAxO1xuICAgICAgfVxuXG4gICAgICByZXR1cm4gMDtcbiAgICB9XG4gIH0pO1xuXG4gIHJldHVybiBLZXJuZWwuU3BlY2lhbEZvcm1zLmxpc3QoLi4ubmV3X2xpc3QpO1xufTtcblxuTGlzdC5rZXlzdG9yZSA9IGZ1bmN0aW9uIChsaXN0LCBrZXksIHBvc2l0aW9uLCBuZXdfdHVwbGUpIHtcbiAgbGV0IG5ld19saXN0ID0gW107XG4gIGxldCByZXBsYWNlZCA9IGZhbHNlO1xuXG4gIGZvciAobGV0IGkgPSAwOyBpIDwgbGlzdC5sZW5ndGg7IGkrKykge1xuICAgIGlmICghS2VybmVsLm1hdGNoX19xbWFya19fKGxpc3RbaV1bcG9zaXRpb25dLCBrZXkpKSB7XG4gICAgICBuZXdfbGlzdC5wdXNoKGxpc3RbaV0pO1xuICAgIH0gZWxzZSB7XG4gICAgICBuZXdfbGlzdC5wdXNoKG5ld190dXBsZSk7XG4gICAgICByZXBsYWNlZCA9IHRydWU7XG4gICAgfVxuICB9XG5cbiAgaWYgKCFyZXBsYWNlZCkge1xuICAgIG5ld19saXN0LnB1c2gobmV3X3R1cGxlKTtcbiAgfVxuXG4gIHJldHVybiBLZXJuZWwuU3BlY2lhbEZvcm1zLmxpc3QoLi4ubmV3X2xpc3QpO1xufTtcblxuTGlzdC5sYXN0ID0gZnVuY3Rpb24gKGxpc3QpIHtcbiAgcmV0dXJuIGxpc3RbbGlzdC5sZW5ndGggLSAxXTtcbn07XG5cbkxpc3QucmVwbGFjZV9hdCA9IGZ1bmN0aW9uIChsaXN0LCBpbmRleCwgdmFsdWUpIHtcbiAgbGV0IG5ld192YWx1ZSA9IFtdO1xuXG4gIGZvciAobGV0IGkgPSAwOyBpIDwgbGlzdC5sZW5ndGg7IGkrKykge1xuICAgIGlmIChpID09PSBpbmRleCkge1xuICAgICAgbmV3X3ZhbHVlLnB1c2godmFsdWUpO1xuICAgIH0gZWxzZSB7XG4gICAgICBuZXdfdmFsdWUucHVzaChsaXN0W2ldKTtcbiAgICB9XG4gIH1cblxuICByZXR1cm4gS2VybmVsLlNwZWNpYWxGb3Jtcy5saXN0KC4uLm5ld192YWx1ZSk7XG59O1xuXG5MaXN0LnVwZGF0ZV9hdCA9IGZ1bmN0aW9uIChsaXN0LCBpbmRleCwgZnVuKSB7XG4gIGxldCBuZXdfdmFsdWUgPSBbXTtcblxuICBmb3IgKGxldCBpID0gMDsgaSA8IGxpc3QuY291bnQoKTsgaSsrKSB7XG4gICAgaWYgKGkgPT09IGluZGV4KSB7XG4gICAgICBuZXdfdmFsdWUucHVzaChmdW4obGlzdC5nZXQoaSkpKTtcbiAgICB9IGVsc2Uge1xuICAgICAgbmV3X3ZhbHVlLnB1c2gobGlzdC5nZXQoaSkpO1xuICAgIH1cbiAgfVxuXG4gIHJldHVybiBuZXdfdmFsdWU7XG59O1xuXG5MaXN0LndyYXAgPSBmdW5jdGlvbiAobGlzdCkge1xuICBpZiAoS2VybmVsLmlzX2xpc3QobGlzdCkpIHtcbiAgICByZXR1cm4gbGlzdDtcbiAgfSBlbHNlIGlmIChsaXN0ID09IG51bGwpIHtcbiAgICByZXR1cm4gS2VybmVsLlNwZWNpYWxGb3Jtcy5saXN0KCk7XG4gIH0gZWxzZSB7XG4gICAgcmV0dXJuIEtlcm5lbC5TcGVjaWFsRm9ybXMubGlzdChsaXN0KTtcbiAgfVxufTtcblxuTGlzdC56aXAgPSBmdW5jdGlvbiAobGlzdF9vZl9saXN0cykge1xuICBpZiAobGlzdF9vZl9saXN0cy5sZW5ndGggPT09IDApIHtcbiAgICByZXR1cm4gS2VybmVsLlNwZWNpYWxGb3Jtcy5saXN0KCk7XG4gIH1cblxuICBsZXQgbmV3X3ZhbHVlID0gW107XG4gIGxldCBzbWFsbGVzdF9sZW5ndGggPSBsaXN0X29mX2xpc3RzWzBdO1xuXG4gIGZvciAobGV0IHggb2YgbGlzdF9vZl9saXN0cykge1xuICAgIGlmICh4Lmxlbmd0aCA8IHNtYWxsZXN0X2xlbmd0aCkge1xuICAgICAgc21hbGxlc3RfbGVuZ3RoID0geC5sZW5ndGg7XG4gICAgfVxuICB9XG5cbiAgZm9yIChsZXQgaSA9IDA7IGkgPCBzbWFsbGVzdF9sZW5ndGg7IGkrKykge1xuICAgIGxldCBjdXJyZW50X3ZhbHVlID0gW107XG4gICAgZm9yIChsZXQgaiA9IDA7IGogPCBsaXN0X29mX2xpc3RzLmxlbmd0aDsgaisrKSB7XG4gICAgICBjdXJyZW50X3ZhbHVlLnB1c2gobGlzdF9vZl9saXN0c1tqXVtpXSk7XG4gICAgfVxuXG4gICAgbmV3X3ZhbHVlLnB1c2goS2VybmVsLlNwZWNpYWxGb3Jtcy50dXBsZSguLi5jdXJyZW50X3ZhbHVlKSk7XG4gIH1cblxuICByZXR1cm4gS2VybmVsLlNwZWNpYWxGb3Jtcy5saXN0KC4uLm5ld192YWx1ZSk7XG59O1xuXG5MaXN0LnRvX3R1cGxlID0gZnVuY3Rpb24gKGxpc3QpIHtcbiAgcmV0dXJuIEtlcm5lbC5TcGVjaWFsRm9ybXMudHVwbGUuYXBwbHkobnVsbCwgbGlzdCk7XG59O1xuXG5MaXN0LmFwcGVuZCA9IGZ1bmN0aW9uIChsaXN0LCB2YWx1ZSkge1xuICByZXR1cm4gS2VybmVsLlNwZWNpYWxGb3Jtcy5saXN0KC4uLmxpc3QuY29uY2F0KFt2YWx1ZV0pKTtcbn07XG5cbkxpc3QucHJlcGVuZCA9IGZ1bmN0aW9uIChsaXN0LCB2YWx1ZSkge1xuICByZXR1cm4gS2VybmVsLlNwZWNpYWxGb3Jtcy5saXN0KC4uLlt2YWx1ZV0uY29uY2F0KGxpc3QpKTtcbn07XG5cbkxpc3QuY29uY2F0ID0gZnVuY3Rpb24gKGxlZnQsIHJpZ2h0KSB7XG4gIHJldHVybiBsZWZ0LmNvbmNhdChyaWdodCk7XG59O1xuXG5sZXQgUmFuZ2UgPSBmdW5jdGlvbiAoX2ZpcnN0LCBfbGFzdCkge1xuICBpZiAoISh0aGlzIGluc3RhbmNlb2YgUmFuZ2UpKSB7XG4gICAgcmV0dXJuIG5ldyBSYW5nZShfZmlyc3QsIF9sYXN0KTtcbiAgfVxuXG4gIHRoaXMuZmlyc3QgPSBmdW5jdGlvbiAoKSB7XG4gICAgcmV0dXJuIF9maXJzdDtcbiAgfTtcblxuICB0aGlzLmxhc3QgPSBmdW5jdGlvbiAoKSB7XG4gICAgcmV0dXJuIF9sYXN0O1xuICB9O1xuXG4gIGxldCBfcmFuZ2UgPSBbXTtcblxuICBmb3IgKGxldCBpID0gX2ZpcnN0OyBpIDw9IF9sYXN0OyBpKyspIHtcbiAgICBfcmFuZ2UucHVzaChpKTtcbiAgfVxuXG4gIF9yYW5nZSA9IE9iamVjdC5mcmVlemUoX3JhbmdlKTtcblxuICB0aGlzLnZhbHVlID0gZnVuY3Rpb24gKCkge1xuICAgIHJldHVybiBfcmFuZ2U7XG4gIH07XG5cbiAgdGhpcy5sZW5ndGggPSBmdW5jdGlvbiAoKSB7XG4gICAgcmV0dXJuIF9yYW5nZS5sZW5ndGg7XG4gIH07XG5cbiAgcmV0dXJuIHRoaXM7XG59O1xuXG5SYW5nZS5wcm90b3R5cGVbU3ltYm9sLml0ZXJhdG9yXSA9IGZ1bmN0aW9uICgpIHtcbiAgcmV0dXJuIHRoaXMudmFsdWUoKVtTeW1ib2wuaXRlcmF0b3JdKCk7XG59O1xuXG5SYW5nZS5uZXcgPSBmdW5jdGlvbiAoZmlyc3QsIGxhc3QpIHtcbiAgcmV0dXJuIFJhbmdlKGZpcnN0LCBsYXN0KTtcbn07XG5cblJhbmdlLnJhbmdlX19xbWFya19fID0gZnVuY3Rpb24gKHJhbmdlKSB7XG4gIHJldHVybiByYW5nZSBpbnN0YW5jZW9mIFJhbmdlO1xufTtcblxubGV0IEtleXdvcmQgPSB7fTtcblxuS2V5d29yZC5oYXNfa2V5X19xbV9fID0gZnVuY3Rpb24gKGtleXdvcmRzLCBrZXkpIHtcbiAgZm9yIChsZXQga2V5d29yZCBvZiBrZXl3b3Jkcykge1xuICAgIGlmIChLZXJuZWwuZWxlbShrZXl3b3JkLCAwKSA9PSBrZXkpIHtcbiAgICAgIHJldHVybiB0cnVlO1xuICAgIH1cbiAgfVxuXG4gIHJldHVybiBmYWxzZTtcbn07XG5cbktleXdvcmQuZ2V0ID0gZnVuY3Rpb24gKGtleXdvcmRzLCBrZXksIHRoZV9kZWZhdWx0ID0gbnVsbCkge1xuICBmb3IgKGxldCBrZXl3b3JkIG9mIGtleXdvcmRzKSB7XG4gICAgaWYgKEtlcm5lbC5lbGVtKGtleXdvcmQsIDApID09IGtleSkge1xuICAgICAgcmV0dXJuIEtlcm5lbC5lbGVtKGtleXdvcmQsIDEpO1xuICAgIH1cbiAgfVxuXG4gIHJldHVybiB0aGVfZGVmYXVsdDtcbn07XG5cbmxldCBBZ2VudCA9IHt9O1xuXG5BZ2VudC5zdGFydCA9IGZ1bmN0aW9uIChmdW4sIG9wdGlvbnMgPSBbXSkge1xuICBsZXQgcGlkID0gc2VsZi5wcm9jZXNzZXMuc3Bhd24oKTtcblxuICBpZiAoS2V5d29yZC5oYXNfa2V5X19xbV9fKG9wdGlvbnMsIEtlcm5lbC5TcGVjaWFsRm9ybXMuYXRvbSgnbmFtZScpKSkge1xuICAgIHBpZCA9IHNlbGYucHJvY2Vzc2VzLnJlZ2lzdGVyKEtleXdvcmQuZ2V0KG9wdGlvbnMsIEtlcm5lbC5TcGVjaWFsRm9ybXMuYXRvbSgnbmFtZScpKSwgcGlkKTtcbiAgfVxuXG4gIHNlbGYucHJvY2Vzc2VzLnB1dChwaWQsICdzdGF0ZScsIGZ1bigpKTtcbiAgcmV0dXJuIEtlcm5lbC5TcGVjaWFsRm9ybXMudHVwbGUoS2VybmVsLlNwZWNpYWxGb3Jtcy5hdG9tKCdvaycpLCBwaWQpO1xufTtcblxuQWdlbnQuc3RvcCA9IGZ1bmN0aW9uIChhZ2VudCwgdGltZW91dCA9IDUwMDApIHtcbiAgc2VsZi5wcm9jZXNzZXMuZXhpdChhZ2VudCk7XG4gIHJldHVybiBLZXJuZWwuU3BlY2lhbEZvcm1zLmF0b20oJ29rJyk7XG59O1xuXG5BZ2VudC51cGRhdGUgPSBmdW5jdGlvbiAoYWdlbnQsIGZ1biwgdGltZW91dCA9IDUwMDApIHtcblxuICBjb25zdCBjdXJyZW50X3N0YXRlID0gc2VsZi5wcm9jZXNzZXMuZ2V0KGFnZW50LCAnc3RhdGUnKTtcbiAgc2VsZi5wcm9jZXNzZXMucHV0KGFnZW50LCAnc3RhdGUnLCBmdW4oY3VycmVudF9zdGF0ZSkpO1xuXG4gIHJldHVybiBLZXJuZWwuU3BlY2lhbEZvcm1zLmF0b20oJ29rJyk7XG59O1xuXG5BZ2VudC5nZXQgPSBmdW5jdGlvbiAoYWdlbnQsIGZ1biwgdGltZW91dCA9IDUwMDApIHtcbiAgcmV0dXJuIGZ1bihzZWxmLnByb2Nlc3Nlcy5nZXQoYWdlbnQsICdzdGF0ZScpKTtcbn07XG5cbkFnZW50LmdldF9hbmRfdXBkYXRlID0gZnVuY3Rpb24gKGFnZW50LCBmdW4sIHRpbWVvdXQgPSA1MDAwKSB7XG5cbiAgY29uc3QgZ2V0X2FuZF91cGRhdGVfdHVwbGUgPSBmdW4oc2VsZi5wcm9jZXNzZXMuZ2V0KGFnZW50LCAnc3RhdGUnKSk7XG4gIHNlbGYucHJvY2Vzc2VzLnB1dChhZ2VudCwgJ3N0YXRlJywgS2VybmVsLmVsZW0oZ2V0X2FuZF91cGRhdGVfdHVwbGUsIDEpKTtcblxuICByZXR1cm4gS2VybmVsLmVsZW0oZ2V0X2FuZF91cGRhdGVfdHVwbGUsIDApO1xufTtcblxuLy9odHRwczovL2RldmVsb3Blci5tb3ppbGxhLm9yZy9lbi1VUy9kb2NzL1dlYi9BUEkvV2luZG93QmFzZTY0L0Jhc2U2NF9lbmNvZGluZ19hbmRfZGVjb2RpbmcjU29sdXRpb25fMl8lRTIlODAlOTNfcmV3cml0ZV90aGVfRE9Nc19hdG9iKClfYW5kX2J0b2EoKV91c2luZ19KYXZhU2NyaXB0J3NfVHlwZWRBcnJheXNfYW5kX1VURi04XG5mdW5jdGlvbiBiNjRFbmNvZGVVbmljb2RlKHN0cikge1xuICByZXR1cm4gYnRvYShlbmNvZGVVUklDb21wb25lbnQoc3RyKS5yZXBsYWNlKC8lKFswLTlBLUZdezJ9KS9nLCBmdW5jdGlvbiAobWF0Y2gsIHAxKSB7XG4gICAgcmV0dXJuIFN0cmluZy5mcm9tQ2hhckNvZGUoJzB4JyArIHAxKTtcbiAgfSkpO1xufVxuXG5mdW5jdGlvbiBlbmNvZGU2NChkYXRhKSB7XG4gIHJldHVybiBiNjRFbmNvZGVVbmljb2RlKGRhdGEpO1xufVxuXG5mdW5jdGlvbiBkZWNvZGU2NChkYXRhKSB7XG4gIHRyeSB7XG4gICAgcmV0dXJuIEtlcm5lbC5TcGVjaWFsRm9ybXMudHVwbGUoS2VybmVsLlNwZWNpYWxGb3Jtcy5hdG9tKCdvaycpLCBhdG9iKGRhdGEpKTtcbiAgfSBjYXRjaCAoZSkge1xuICAgIHJldHVybiBLZXJuZWwuU3BlY2lhbEZvcm1zLmF0b20oJ2Vycm9yJyk7XG4gIH1cblxuICByZXR1cm4gYnRvYShkYXRhKTtcbn1cblxuZnVuY3Rpb24gZGVjb2RlNjRfX2VtX18oZGF0YSkge1xuICByZXR1cm4gYXRvYihkYXRhKTtcbn1cblxudmFyIGJhc2UgPSB7XG4gIGVuY29kZTY0LFxuICBkZWNvZGU2NCxcbiAgZGVjb2RlNjRfX2VtX19cbn07XG5cbmZ1bmN0aW9uIGJub3QoZXhwcikge1xuICByZXR1cm4gfmV4cHI7XG59XG5cbmZ1bmN0aW9uIGJhbmQobGVmdCwgcmlnaHQpIHtcbiAgcmV0dXJuIGxlZnQgJiByaWdodDtcbn1cblxuZnVuY3Rpb24gYm9yKGxlZnQsIHJpZ2h0KSB7XG4gIHJldHVybiBsZWZ0IHwgcmlnaHQ7XG59XG5cbmZ1bmN0aW9uIGJzbChsZWZ0LCByaWdodCkge1xuICByZXR1cm4gbGVmdCA8PCByaWdodDtcbn1cblxuZnVuY3Rpb24gYnNyKGxlZnQsIHJpZ2h0KSB7XG4gIHJldHVybiBsZWZ0ID4+IHJpZ2h0O1xufVxuXG5mdW5jdGlvbiBieG9yKGxlZnQsIHJpZ2h0KSB7XG4gIHJldHVybiBsZWZ0IF4gcmlnaHQ7XG59XG5cbnZhciBiaXR3aXNlID0ge1xuICBibm90LFxuICBiYW5kLFxuICBib3IsXG4gIGJzbCxcbiAgYnNyLFxuICBieG9yXG59O1xuXG5sZXQgRW51bWVyYWJsZSA9IEtlcm5lbC5kZWZwcm90b2NvbCh7XG4gIGNvdW50OiBmdW5jdGlvbiAoY29sbGVjdGlvbikge30sXG4gIG1lbWJlcl9xbWFya19fOiBmdW5jdGlvbiAoY29sbGVjdGlvbiwgdmFsdWUpIHt9LFxuICByZWR1Y2U6IGZ1bmN0aW9uIChjb2xsZWN0aW9uLCBhY2MsIGZ1bikge31cbn0pO1xuXG5sZXQgQ29sbGVjdGFibGUgPSBLZXJuZWwuZGVmcHJvdG9jb2woe1xuICBpbnRvOiBmdW5jdGlvbiAoY29sbGVjdGFibGUpIHt9XG59KTtcblxubGV0IEluc3BlY3QgPSBLZXJuZWwuZGVmcHJvdG9jb2woe1xuICBpbnNwZWN0OiBmdW5jdGlvbiAodGhpbmcsIG9wdHMpIHt9XG59KTtcblxuZnVuY3Rpb24gX19uZXdfXygpIHtcbiAgcmV0dXJuIFNwZWNpYWxGb3Jtcy5tYXAoe30pO1xufVxuXG5mdW5jdGlvbiBrZXlzKG1hcCkge1xuICByZXR1cm4gT2JqZWN0LmtleXMobWFwKS5jb25jYXQoT2JqZWN0LmdldE93blByb3BlcnR5U3ltYm9scyhtYXApKTtcbn1cblxuZnVuY3Rpb24gc2l6ZShtYXApIHtcbiAgcmV0dXJuIGtleXMobWFwKS5sZW5ndGg7XG59XG5cbmZ1bmN0aW9uIHRvX2xpc3QkMShtYXApIHtcbiAgbGV0IG1hcF9rZXlzID0ga2V5cyhtYXApO1xuICBsZXQgbGlzdCA9IFtdO1xuXG4gIGZvciAobGV0IGtleSBvZiBtYXBfa2V5cykge1xuICAgIGxpc3QucHVzaChTcGVjaWFsRm9ybXMudHVwbGUoa2V5LCBtYXBba2V5XSkpO1xuICB9XG5cbiAgcmV0dXJuIFNwZWNpYWxGb3Jtcy5saXN0KC4uLmxpc3QpO1xufVxuXG5mdW5jdGlvbiB2YWx1ZXMobWFwKSB7XG4gIGxldCBtYXBfa2V5cyA9IGtleXMobWFwKTtcbiAgbGV0IGxpc3QgPSBbXTtcblxuICBmb3IgKGxldCBrZXkgb2YgbWFwX2tleXMpIHtcbiAgICBsaXN0LnB1c2gobWFwW2tleV0pO1xuICB9XG5cbiAgcmV0dXJuIFNwZWNpYWxGb3Jtcy5saXN0KC4uLmxpc3QpO1xufVxuXG5mdW5jdGlvbiBmcm9tX3N0cnVjdChzdHJ1Y3QpIHtcbiAgbGV0IG1hcCA9IE9iamVjdC5hc3NpZ24oe30sIHN0cnVjdCk7XG4gIGRlbGV0ZSBtYXBbU3ltYm9sLmZvcihcIl9fc3RydWN0X19cIildO1xuXG4gIHJldHVybiBTcGVjaWFsRm9ybXMubWFwKG1hcCk7XG59XG5cbmZ1bmN0aW9uIF9fZGVsZXRlX18obWFwLCBrZXkpIHtcbiAgbGV0IG5ld19tYXAgPSBPYmplY3QuYXNzaWduKHt9LCBtYXApO1xuXG4gIGRlbGV0ZSBuZXdfbWFwW2tleV07XG5cbiAgcmV0dXJuIFNwZWNpYWxGb3Jtcy5tYXAobmV3X21hcCk7XG59XG5cbmZ1bmN0aW9uIGVxdWFsX19xbWFya19fKG1hcDEsIG1hcDIpIHtcbiAgcmV0dXJuIG1hcDEgPT09IG1hcDI7XG59XG5cbmZ1bmN0aW9uIGZldGNoX19lbWFya19fKG1hcCwga2V5KSB7XG4gIGlmIChrZXkgaW4gbWFwKSB7XG4gICAgcmV0dXJuIG1hcFtrZXldO1xuICB9XG5cbiAgdGhyb3cgbmV3IEVycm9yKFwiS2V5IG5vdCBmb3VuZC5cIik7XG59XG5cbmZ1bmN0aW9uIGZldGNoKG1hcCwga2V5KSB7XG4gIGlmIChrZXkgaW4gbWFwKSB7XG4gICAgcmV0dXJuIFNwZWNpYWxGb3Jtcy50dXBsZShTcGVjaWFsRm9ybXMuYXRvbShcIm9rXCIpLCBtYXBba2V5XSk7XG4gIH1cblxuICByZXR1cm4gU3BlY2lhbEZvcm1zLmF0b20oXCJlcnJvclwiKTtcbn1cblxuZnVuY3Rpb24gaGFzX2tleV9fcW1hcmtfXyhtYXAsIGtleSkge1xuICByZXR1cm4ga2V5IGluIG1hcDtcbn1cblxuZnVuY3Rpb24gc3BsaXQkMShtYXAsIGtleXMpIHtcbiAgbGV0IHNwbGl0MSA9IHt9O1xuICBsZXQgc3BsaXQyID0ge307XG5cbiAgZm9yIChsZXQga2V5IG9mIE9iamVjdC5rZXlzKG1hcCkuY29uY2F0KE9iamVjdC5nZXRPd25Qcm9wZXJ0eVN5bWJvbHMobWFwKSkpIHtcbiAgICBpZiAoa2V5cy5pbmRleE9mKGtleSkgPiAtMSkge1xuICAgICAgc3BsaXQxW2tleV0gPSBtYXBba2V5XTtcbiAgICB9IGVsc2Uge1xuICAgICAgc3BsaXQyW2tleV0gPSBtYXBba2V5XTtcbiAgICB9XG4gIH1cblxuICByZXR1cm4gU3BlY2lhbEZvcm1zLnR1cGxlKFNwZWNpYWxGb3Jtcy5tYXAoc3BsaXQxKSwgU3BlY2lhbEZvcm1zLm1hcChzcGxpdDIpKTtcbn1cblxuZnVuY3Rpb24gdGFrZShtYXAsIGtleXMpIHtcbiAgbGV0IHNwbGl0MSA9IHt9O1xuXG4gIGZvciAobGV0IGtleSBvZiBPYmplY3Qua2V5cyhtYXApLmNvbmNhdChPYmplY3QuZ2V0T3duUHJvcGVydHlTeW1ib2xzKG1hcCkpKSB7XG4gICAgaWYgKGtleXMuaW5kZXhPZihrZXkpID4gLTEpIHtcbiAgICAgIHNwbGl0MVtrZXldID0gbWFwW2tleV07XG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIFNwZWNpYWxGb3Jtcy5tYXAoc3BsaXQxKTtcbn1cblxuZnVuY3Rpb24gZHJvcChtYXAsIGtleXMpIHtcbiAgbGV0IHNwbGl0MSA9IHt9O1xuXG4gIGZvciAobGV0IGtleSBvZiBPYmplY3Qua2V5cyhtYXApLmNvbmNhdChPYmplY3QuZ2V0T3duUHJvcGVydHlTeW1ib2xzKG1hcCkpKSB7XG4gICAgaWYgKGtleXMuaW5kZXhPZihrZXkpID09PSAtMSkge1xuICAgICAgc3BsaXQxW2tleV0gPSBtYXBba2V5XTtcbiAgICB9XG4gIH1cblxuICByZXR1cm4gU3BlY2lhbEZvcm1zLm1hcChzcGxpdDEpO1xufVxuXG5mdW5jdGlvbiBwdXRfbmV3KG1hcCwga2V5LCB2YWx1ZSkge1xuICBpZiAoa2V5IGluIG1hcCkge1xuICAgIHJldHVybiBtYXA7XG4gIH1cblxuICBsZXQgbmV3X21hcCA9IE9iamVjdC5hc3NpZ24oe30sIG1hcCk7XG4gIG5ld19tYXBba2V5XSA9IHZhbHVlO1xuXG4gIHJldHVybiBTcGVjaWFsRm9ybXMubWFwKG5ld19tYXApO1xufVxuXG5mdW5jdGlvbiBwdXRfbmV3X2xhenkobWFwLCBrZXksIGZ1bikge1xuICBpZiAoa2V5IGluIG1hcCkge1xuICAgIHJldHVybiBtYXA7XG4gIH1cblxuICBsZXQgbmV3X21hcCA9IE9iamVjdC5hc3NpZ24oe30sIG1hcCk7XG4gIG5ld19tYXBba2V5XSA9IGZ1bigpO1xuXG4gIHJldHVybiBTcGVjaWFsRm9ybXMubWFwKG5ld19tYXApO1xufVxuXG5mdW5jdGlvbiBnZXRfYW5kX3VwZGF0ZShtYXAsIGtleSwgZnVuKSB7XG4gIGlmIChrZXkgaW4gbWFwKSB7XG4gICAgcmV0dXJuIG1hcDtcbiAgfVxuXG4gIGxldCBuZXdfbWFwID0gT2JqZWN0LmFzc2lnbih7fSwgbWFwKTtcbiAgbmV3X21hcFtrZXldID0gZnVuKG1hcFtrZXldKTtcblxuICByZXR1cm4gU3BlY2lhbEZvcm1zLm1hcChuZXdfbWFwKTtcbn1cblxuZnVuY3Rpb24gcG9wX2xhenkobWFwLCBrZXksIGZ1bikge1xuICBpZiAoIWtleSBpbiBtYXApIHtcbiAgICByZXR1cm4gU3BlY2lhbEZvcm1zLnR1cGxlKGZ1bigpLCBtYXApO1xuICB9XG5cbiAgbGV0IG5ld19tYXAgPSBPYmplY3QuYXNzaWduKHt9LCBtYXApO1xuICBsZXQgdmFsdWUgPSBmdW4obmV3X21hcFtrZXldKTtcbiAgZGVsZXRlIG5ld19tYXBba2V5XTtcblxuICByZXR1cm4gU3BlY2lhbEZvcm1zLnR1cGxlKHZhbHVlLCBuZXdfbWFwKTtcbn1cblxuZnVuY3Rpb24gcG9wKG1hcCwga2V5LCBfZGVmYXVsdCA9IG51bGwpIHtcbiAgaWYgKCFrZXkgaW4gbWFwKSB7XG4gICAgcmV0dXJuIFNwZWNpYWxGb3Jtcy50dXBsZShfZGVmYXVsdCwgbWFwKTtcbiAgfVxuXG4gIGxldCBuZXdfbWFwID0gT2JqZWN0LmFzc2lnbih7fSwgbWFwKTtcbiAgbGV0IHZhbHVlID0gbmV3X21hcFtrZXldO1xuICBkZWxldGUgbmV3X21hcFtrZXldO1xuXG4gIHJldHVybiBTcGVjaWFsRm9ybXMudHVwbGUodmFsdWUsIG5ld19tYXApO1xufVxuXG5mdW5jdGlvbiBnZXRfbGF6eShtYXAsIGtleSwgZnVuKSB7XG4gIGlmICgha2V5IGluIG1hcCkge1xuICAgIHJldHVybiBmdW4oKTtcbiAgfVxuXG4gIHJldHVybiBmdW4obWFwW2tleV0pO1xufVxuXG5mdW5jdGlvbiBnZXQobWFwLCBrZXksIF9kZWZhdWx0ID0gbnVsbCkge1xuICBpZiAoIWtleSBpbiBtYXApIHtcbiAgICByZXR1cm4gX2RlZmF1bHQ7XG4gIH1cblxuICByZXR1cm4gbWFwW2tleV07XG59XG5cbmZ1bmN0aW9uIHB1dChtYXAsIGtleSwgdmFsKSB7XG4gIGxldCBuZXdfbWFwID0gT2JqZWN0KHt9LCBtYXApO1xuICBuZXdfbWFwW2tleV0gPSB2YWw7XG5cbiAgcmV0dXJuIFNwZWNpYWxGb3Jtcy5tYXAobmV3X21hcCk7XG59XG5cbmZ1bmN0aW9uIHVwZGF0ZV9fZW1hcmtfXyhtYXAsIGtleSwgZnVuKSB7XG4gIGlmICgha2V5IGluIG1hcCkge1xuICAgIHRocm93IG5ldyBFcnJvcihcIktleSBub3QgZm91bmRcIik7XG4gIH1cblxuICBsZXQgbmV3X21hcCA9IE9iamVjdCh7fSwgbWFwKTtcbiAgbmV3X21hcFtrZXldID0gZnVuKG1hcFtrZXldKTtcblxuICByZXR1cm4gU3BlY2lhbEZvcm1zLm1hcChuZXdfbWFwKTtcbn1cblxuZnVuY3Rpb24gdXBkYXRlKG1hcCwga2V5LCBpbml0aWFsLCBmdW4pIHtcbiAgbGV0IG5ld19tYXAgPSBPYmplY3Qoe30sIG1hcCk7XG5cbiAgaWYgKCFrZXkgaW4gbWFwKSB7XG4gICAgbmV3X21hcFtrZXldID0gaW5pdGlhbDtcbiAgfSBlbHNlIHtcbiAgICBuZXdfbWFwW2tleV0gPSBmdW4obWFwW2tleV0pO1xuICB9XG5cbiAgcmV0dXJuIFNwZWNpYWxGb3Jtcy5tYXAobmV3X21hcCk7XG59XG5cbnZhciBtYXAgPSB7XG4gIG5ldzogX19uZXdfXyxcbiAga2V5cyxcbiAgc2l6ZSxcbiAgdG9fbGlzdDogdG9fbGlzdCQxLFxuICB2YWx1ZXMsXG4gIGZyb21fc3RydWN0LFxuICBkZWxldGU6IF9fZGVsZXRlX18sXG4gIGRyb3AsXG4gIGVxdWFsX19xbWFya19fLFxuICBmZXRjaF9fZW1hcmtfXyxcbiAgZmV0Y2gsXG4gIGhhc19rZXlfX3FtYXJrX18sXG4gIHNwbGl0OiBzcGxpdCQxLFxuICB0YWtlLFxuICBwdXRfbmV3LFxuICBwdXRfbmV3X2xhenksXG4gIGdldF9hbmRfdXBkYXRlLFxuICBwb3BfbGF6eSxcbiAgcG9wLFxuICBnZXRfbGF6eSxcbiAgZ2V0LFxuICBwdXQsXG4gIHVwZGF0ZV9fZW1hcmtfXyxcbiAgdXBkYXRlXG59O1xuXG5mdW5jdGlvbiBfX25ld19fJDEoKSB7XG4gIHJldHVybiBTcGVjaWFsRm9ybXMubWFwKHsgW1N5bWJvbC5mb3IoJ19fc3RydWN0X18nKV06IFN5bWJvbC5mb3IoJ01hcFNldCcpLCBzZXQ6IFNwZWNpYWxGb3Jtcy5saXN0KCkgfSk7XG59XG5cbmZ1bmN0aW9uIHNpemUkMihtYXApIHtcbiAgcmV0dXJuIG1hcC5zZXQubGVuZ3RoO1xufVxuXG5mdW5jdGlvbiB0b19saXN0JDMobWFwKSB7XG4gIHJldHVybiBtYXAuc2V0O1xufVxuXG5mdW5jdGlvbiBfX2RlbGV0ZV9fJDIoc2V0LCB0ZXJtKSB7XG4gIGxldCBuZXdfbGlzdCA9IExpc3QuZGVsZXRlKHNldC5zZXQsIHRlcm0pO1xuXG4gIGxldCBuZXdfbWFwID0gT2JqZWN0LmFzc2lnbih7fSwgc2V0KTtcbiAgbmV3X21hcC5zZXQgPSBuZXdfbGlzdDtcbiAgcmV0dXJuIFNwZWNpYWxGb3Jtcy5tYXAobmV3X21hcCk7XG59XG5cbmZ1bmN0aW9uIHB1dCQyKHNldCwgdGVybSkge1xuICBpZiAoc2V0LnNldC5pbmRleE9mKHRlcm0pID09PSAtMSkge1xuICAgIGxldCBuZXdfbGlzdCA9IExpc3QuYXBwZW5kKHNldC5zZXQsIHRlcm0pO1xuXG4gICAgbGV0IG5ld19tYXAgPSBPYmplY3QuYXNzaWduKHt9LCBzZXQpO1xuICAgIG5ld19tYXAuc2V0ID0gbmV3X2xpc3Q7XG4gICAgcmV0dXJuIFNwZWNpYWxGb3Jtcy5tYXAobmV3X21hcCk7XG4gIH1cblxuICByZXR1cm4gc2V0O1xufVxuXG5mdW5jdGlvbiBkaWZmZXJlbmNlJDEoc2V0MSwgc2V0Mikge1xuICBsZXQgbmV3X21hcCA9IE9iamVjdC5hc3NpZ24oe30sIHNldDEpO1xuXG4gIGZvciAobGV0IHZhbCBvZiBzZXQxLnNldCkge1xuICAgIGlmIChtZW1iZXJfX3FtYXJrX18kMShzZXQyLCB2YWwpKSB7XG4gICAgICBuZXdfbWFwLnNldCA9IExpc3QuZGVsZXRlKG5ld19tYXAuc2V0LCB2YWwpO1xuICAgIH1cbiAgfVxuXG4gIHJldHVybiBTcGVjaWFsRm9ybXMubWFwKG5ld19tYXApO1xufVxuXG5mdW5jdGlvbiBpbnRlcnNlY3Rpb24kMShzZXQxLCBzZXQyKSB7XG4gIGxldCBuZXdfbWFwID0gT2JqZWN0LmFzc2lnbih7fSwgc2V0MSk7XG5cbiAgZm9yIChsZXQgdmFsIG9mIHNldDEuc2V0KSB7XG4gICAgaWYgKCFtZW1iZXJfX3FtYXJrX18kMShzZXQyLCB2YWwpKSB7XG4gICAgICBuZXdfbWFwLnNldCA9IExpc3QuZGVsZXRlKG5ld19tYXAuc2V0LCB2YWwpO1xuICAgIH1cbiAgfVxuXG4gIHJldHVybiBTcGVjaWFsRm9ybXMubWFwKG5ld19tYXApO1xufVxuXG5mdW5jdGlvbiB1bmlvbiQxKHNldDEsIHNldDIpIHtcbiAgbGV0IG5ld19tYXAgPSBzZXQxO1xuXG4gIGZvciAobGV0IHZhbCBvZiBzZXQyLnNldCkge1xuICAgIG5ld19tYXAgPSBwdXQkMihuZXdfbWFwLCB2YWwpO1xuICB9XG5cbiAgcmV0dXJuIFNwZWNpYWxGb3Jtcy5tYXAobmV3X21hcCk7XG59XG5cbmZ1bmN0aW9uIGRpc2pvaW5fX3FtYXJrX18kMShzZXQxLCBzZXQyKSB7XG4gIGZvciAobGV0IHZhbCBvZiBzZXQxLnNldCkge1xuICAgIGlmIChtZW1iZXJfX3FtYXJrX18kMShzZXQyLCB2YWwpKSB7XG4gICAgICByZXR1cm4gZmFsc2U7XG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIHRydWU7XG59XG5cbmZ1bmN0aW9uIG1lbWJlcl9fcW1hcmtfXyQxKHNldCwgdmFsdWUpIHtcbiAgcmV0dXJuIHNldC5zZXQuaW5kZXhPZih2YWx1ZSkgPj0gMDtcbn1cblxuZnVuY3Rpb24gZXF1YWxfX3FtYXJrX18kMihzZXQxLCBzZXQyKSB7XG4gIHJldHVybiBzZXQxLnNldCA9PT0gc2V0Mi5zZXQ7XG59XG5cbmZ1bmN0aW9uIHN1YnNldF9fcW1hcmtfXyQxKHNldDEsIHNldDIpIHtcbiAgZm9yIChsZXQgdmFsIG9mIHNldDEuc2V0KSB7XG4gICAgaWYgKCFtZW1iZXJfX3FtYXJrX18kMShzZXQyLCB2YWwpKSB7XG4gICAgICByZXR1cm4gZmFsc2U7XG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIHRydWU7XG59XG5cbnZhciBNYXBTZXQgPSB7XG4gIG5ldzogX19uZXdfXyQxLFxuICBzaXplOiBzaXplJDIsXG4gIHRvX2xpc3Q6IHRvX2xpc3QkMyxcbiAgZGlzam9pbl9fcW1hcmtfXzogZGlzam9pbl9fcW1hcmtfXyQxLFxuICBkZWxldGU6IF9fZGVsZXRlX18kMixcbiAgc3Vic2V0X19xbWFya19fOiBzdWJzZXRfX3FtYXJrX18kMSxcbiAgZXF1YWxfX3FtYXJrX186IGVxdWFsX19xbWFya19fJDIsXG4gIG1lbWJlcl9fcW1hcmtfXzogbWVtYmVyX19xbWFya19fJDEsXG4gIHB1dDogcHV0JDIsXG4gIHVuaW9uOiB1bmlvbiQxLFxuICBpbnRlcnNlY3Rpb246IGludGVyc2VjdGlvbiQxLFxuICBkaWZmZXJlbmNlOiBkaWZmZXJlbmNlJDFcbn07XG5cbmZ1bmN0aW9uIHNpemUkMShtYXApIHtcbiAgcmV0dXJuIE1hcFNldC5zaXplKG1hcCk7XG59XG5cbmZ1bmN0aW9uIHRvX2xpc3QkMihtYXApIHtcbiAgcmV0dXJuIE1hcFNldC50b19saXN0KG1hcCk7XG59XG5cbmZ1bmN0aW9uIF9fZGVsZXRlX18kMShzZXQsIHRlcm0pIHtcbiAgcmV0dXJuIE1hcFNldC5kZWxldGUoc2V0LCB0ZXJtKTtcbn1cblxuZnVuY3Rpb24gcHV0JDEoc2V0LCB0ZXJtKSB7XG4gIHJldHVybiBNYXBTZXQucHV0KHNldCwgdGVybSk7XG59XG5cbmZ1bmN0aW9uIGRpZmZlcmVuY2Uoc2V0MSwgc2V0Mikge1xuICByZXR1cm4gTWFwU2V0LmRpZmZlcmVuY2Uoc2V0MSwgc2V0Mik7XG59XG5cbmZ1bmN0aW9uIGludGVyc2VjdGlvbihzZXQxLCBzZXQyKSB7XG4gIHJldHVybiBNYXBTZXQuaW50ZXJzZWN0aW9uKHNldDEsIHNldDIpO1xufVxuXG5mdW5jdGlvbiB1bmlvbihzZXQxLCBzZXQyKSB7XG4gIHJldHVybiBNYXBTZXQudW5pb24oc2V0MSwgc2V0Mik7XG59XG5cbmZ1bmN0aW9uIGRpc2pvaW5fX3FtYXJrX18oc2V0MSwgc2V0Mikge1xuICByZXR1cm4gTWFwU2V0LmRpc2pvaW5fX3FtYXJrX18oc2V0MSwgc2V0Mik7XG59XG5cbmZ1bmN0aW9uIG1lbWJlcl9fcW1hcmtfXyhzZXQsIHZhbHVlKSB7XG4gIHJldHVybiBNYXBTZXQubWVtYmVyX19xbWFya19fKHNldDEsIHNldDIpO1xufVxuXG5mdW5jdGlvbiBlcXVhbF9fcW1hcmtfXyQxKHNldDEsIHNldDIpIHtcbiAgcmV0dXJuIE1hcFNldC5lcXVhbF9fcW1hcmtfXyhzZXQxLCBzZXQyKTtcbn1cblxuZnVuY3Rpb24gc3Vic2V0X19xbWFya19fKHNldDEsIHNldDIpIHtcbiAgcmV0dXJuIE1hcFNldC5zdWJzZXRfX3FtYXJrX18oc2V0MSwgc2V0Mik7XG59XG5cbnZhciBzZXQgPSB7XG4gIHNpemU6IHNpemUkMSxcbiAgdG9fbGlzdDogdG9fbGlzdCQyLFxuICBkaXNqb2luX19xbWFya19fLFxuICBkZWxldGU6IF9fZGVsZXRlX18kMSxcbiAgc3Vic2V0X19xbWFya19fLFxuICBlcXVhbF9fcW1hcmtfXzogZXF1YWxfX3FtYXJrX18kMSxcbiAgbWVtYmVyX19xbWFya19fLFxuICBwdXQ6IHB1dCQxLFxuICB1bmlvbixcbiAgaW50ZXJzZWN0aW9uLFxuICBkaWZmZXJlbmNlXG59O1xuXG5sZXQgVmlydHVhbERPTSA9IChmdW5jdGlvbiAoZSkge1xuICAgIHJldHVybiBlKCk7XG59KShmdW5jdGlvbiAoKSB7XG4gICAgdmFyIGRlZmluZSwgbW9kdWxlLCBleHBvcnRzO1xuICAgIHJldHVybiAoZnVuY3Rpb24gZSh0LCBuLCByKSB7XG4gICAgICAgIGZ1bmN0aW9uIHMobywgdSkge1xuICAgICAgICAgICAgaWYgKCFuW29dKSB7XG4gICAgICAgICAgICAgICAgaWYgKCF0W29dKSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciBhID0gdHlwZW9mIHJlcXVpcmUgPT0gXCJmdW5jdGlvblwiICYmIHJlcXVpcmU7XG4gICAgICAgICAgICAgICAgICAgIGlmICghdSAmJiBhKSByZXR1cm4gYShvLCAhMCk7XG4gICAgICAgICAgICAgICAgICAgIGlmIChpKSByZXR1cm4gaShvLCAhMCk7XG4gICAgICAgICAgICAgICAgICAgIHZhciBmID0gbmV3IEVycm9yKFwiQ2Fubm90IGZpbmQgbW9kdWxlICdcIiArIG8gKyBcIidcIik7XG4gICAgICAgICAgICAgICAgICAgIHRocm93IChmLmNvZGUgPSBcIk1PRFVMRV9OT1RfRk9VTkRcIiwgZik7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHZhciBsID0gbltvXSA9IHtcbiAgICAgICAgICAgICAgICAgICAgZXhwb3J0czoge31cbiAgICAgICAgICAgICAgICB9O1xuICAgICAgICAgICAgICAgIHRbb11bMF0uY2FsbChsLmV4cG9ydHMsIGZ1bmN0aW9uIChlKSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciBuID0gdFtvXVsxXVtlXTtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHMobiA/IG4gOiBlKTtcbiAgICAgICAgICAgICAgICB9LCBsLCBsLmV4cG9ydHMsIGUsIHQsIG4sIHIpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmV0dXJuIG5bb10uZXhwb3J0cztcbiAgICAgICAgfVxuICAgICAgICB2YXIgaSA9IHR5cGVvZiByZXF1aXJlID09IFwiZnVuY3Rpb25cIiAmJiByZXF1aXJlO1xuICAgICAgICBmb3IgKHZhciBvID0gMDsgbyA8IHIubGVuZ3RoOyBvKyspIHMocltvXSk7XG4gICAgICAgIHJldHVybiBzO1xuICAgIH0pKHtcbiAgICAgICAgMTogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHtcblxuICAgICAgICAgICAgdmFyIGNyZWF0ZUVsZW1lbnQgPSByZXF1aXJlKFwiLi92ZG9tL2NyZWF0ZS1lbGVtZW50LmpzXCIpO1xuXG4gICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IGNyZWF0ZUVsZW1lbnQ7XG4gICAgICAgIH0sIHsgXCIuL3Zkb20vY3JlYXRlLWVsZW1lbnQuanNcIjogMTUgfV0sIDI6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICB2YXIgZGlmZiA9IHJlcXVpcmUoXCIuL3Z0cmVlL2RpZmYuanNcIik7XG5cbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gZGlmZjtcbiAgICAgICAgfSwgeyBcIi4vdnRyZWUvZGlmZi5qc1wiOiAzNSB9XSwgMzogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHtcbiAgICAgICAgICAgIHZhciBoID0gcmVxdWlyZShcIi4vdmlydHVhbC1oeXBlcnNjcmlwdC9pbmRleC5qc1wiKTtcblxuICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBoO1xuICAgICAgICB9LCB7IFwiLi92aXJ0dWFsLWh5cGVyc2NyaXB0L2luZGV4LmpzXCI6IDIyIH1dLCA0OiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge1xuICAgICAgICAgICAgdmFyIGRpZmYgPSByZXF1aXJlKFwiLi9kaWZmLmpzXCIpO1xuICAgICAgICAgICAgdmFyIHBhdGNoID0gcmVxdWlyZShcIi4vcGF0Y2guanNcIik7XG4gICAgICAgICAgICB2YXIgaCA9IHJlcXVpcmUoXCIuL2guanNcIik7XG4gICAgICAgICAgICB2YXIgY3JlYXRlID0gcmVxdWlyZShcIi4vY3JlYXRlLWVsZW1lbnQuanNcIik7XG4gICAgICAgICAgICB2YXIgVk5vZGUgPSByZXF1aXJlKFwiLi92bm9kZS92bm9kZS5qc1wiKTtcbiAgICAgICAgICAgIHZhciBWVGV4dCA9IHJlcXVpcmUoXCIuL3Zub2RlL3Z0ZXh0LmpzXCIpO1xuXG4gICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IHtcbiAgICAgICAgICAgICAgICBkaWZmOiBkaWZmLFxuICAgICAgICAgICAgICAgIHBhdGNoOiBwYXRjaCxcbiAgICAgICAgICAgICAgICBoOiBoLFxuICAgICAgICAgICAgICAgIGNyZWF0ZTogY3JlYXRlLFxuICAgICAgICAgICAgICAgIFZOb2RlOiBWTm9kZSxcbiAgICAgICAgICAgICAgICBWVGV4dDogVlRleHRcbiAgICAgICAgICAgIH07XG4gICAgICAgIH0sIHsgXCIuL2NyZWF0ZS1lbGVtZW50LmpzXCI6IDEsIFwiLi9kaWZmLmpzXCI6IDIsIFwiLi9oLmpzXCI6IDMsIFwiLi9wYXRjaC5qc1wiOiAxMywgXCIuL3Zub2RlL3Zub2RlLmpzXCI6IDMxLCBcIi4vdm5vZGUvdnRleHQuanNcIjogMzMgfV0sIDU6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICAvKiFcbiAgICAgICAgICAgICAqIENyb3NzLUJyb3dzZXIgU3BsaXQgMS4xLjFcbiAgICAgICAgICAgICAqIENvcHlyaWdodCAyMDA3LTIwMTIgU3RldmVuIExldml0aGFuIDxzdGV2ZW5sZXZpdGhhbi5jb20+XG4gICAgICAgICAgICAgKiBBdmFpbGFibGUgdW5kZXIgdGhlIE1JVCBMaWNlbnNlXG4gICAgICAgICAgICAgKiBFQ01BU2NyaXB0IGNvbXBsaWFudCwgdW5pZm9ybSBjcm9zcy1icm93c2VyIHNwbGl0IG1ldGhvZFxuICAgICAgICAgICAgICovXG5cbiAgICAgICAgICAgIC8qKlxuICAgICAgICAgICAgICogU3BsaXRzIGEgc3RyaW5nIGludG8gYW4gYXJyYXkgb2Ygc3RyaW5ncyB1c2luZyBhIHJlZ2V4IG9yIHN0cmluZyBzZXBhcmF0b3IuIE1hdGNoZXMgb2YgdGhlXG4gICAgICAgICAgICAgKiBzZXBhcmF0b3IgYXJlIG5vdCBpbmNsdWRlZCBpbiB0aGUgcmVzdWx0IGFycmF5LiBIb3dldmVyLCBpZiBgc2VwYXJhdG9yYCBpcyBhIHJlZ2V4IHRoYXQgY29udGFpbnNcbiAgICAgICAgICAgICAqIGNhcHR1cmluZyBncm91cHMsIGJhY2tyZWZlcmVuY2VzIGFyZSBzcGxpY2VkIGludG8gdGhlIHJlc3VsdCBlYWNoIHRpbWUgYHNlcGFyYXRvcmAgaXMgbWF0Y2hlZC5cbiAgICAgICAgICAgICAqIEZpeGVzIGJyb3dzZXIgYnVncyBjb21wYXJlZCB0byB0aGUgbmF0aXZlIGBTdHJpbmcucHJvdG90eXBlLnNwbGl0YCBhbmQgY2FuIGJlIHVzZWQgcmVsaWFibHlcbiAgICAgICAgICAgICAqIGNyb3NzLWJyb3dzZXIuXG4gICAgICAgICAgICAgKiBAcGFyYW0ge1N0cmluZ30gc3RyIFN0cmluZyB0byBzcGxpdC5cbiAgICAgICAgICAgICAqIEBwYXJhbSB7UmVnRXhwfFN0cmluZ30gc2VwYXJhdG9yIFJlZ2V4IG9yIHN0cmluZyB0byB1c2UgZm9yIHNlcGFyYXRpbmcgdGhlIHN0cmluZy5cbiAgICAgICAgICAgICAqIEBwYXJhbSB7TnVtYmVyfSBbbGltaXRdIE1heGltdW0gbnVtYmVyIG9mIGl0ZW1zIHRvIGluY2x1ZGUgaW4gdGhlIHJlc3VsdCBhcnJheS5cbiAgICAgICAgICAgICAqIEByZXR1cm5zIHtBcnJheX0gQXJyYXkgb2Ygc3Vic3RyaW5ncy5cbiAgICAgICAgICAgICAqIEBleGFtcGxlXG4gICAgICAgICAgICAgKlxuICAgICAgICAgICAgICogLy8gQmFzaWMgdXNlXG4gICAgICAgICAgICAgKiBzcGxpdCgnYSBiIGMgZCcsICcgJyk7XG4gICAgICAgICAgICAgKiAvLyAtPiBbJ2EnLCAnYicsICdjJywgJ2QnXVxuICAgICAgICAgICAgICpcbiAgICAgICAgICAgICAqIC8vIFdpdGggbGltaXRcbiAgICAgICAgICAgICAqIHNwbGl0KCdhIGIgYyBkJywgJyAnLCAyKTtcbiAgICAgICAgICAgICAqIC8vIC0+IFsnYScsICdiJ11cbiAgICAgICAgICAgICAqXG4gICAgICAgICAgICAgKiAvLyBCYWNrcmVmZXJlbmNlcyBpbiByZXN1bHQgYXJyYXlcbiAgICAgICAgICAgICAqIHNwbGl0KCcuLndvcmQxIHdvcmQyLi4nLCAvKFthLXpdKykoXFxkKykvaSk7XG4gICAgICAgICAgICAgKiAvLyAtPiBbJy4uJywgJ3dvcmQnLCAnMScsICcgJywgJ3dvcmQnLCAnMicsICcuLiddXG4gICAgICAgICAgICAgKi9cbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gKGZ1bmN0aW9uIHNwbGl0KHVuZGVmKSB7XG5cbiAgICAgICAgICAgICAgICB2YXIgbmF0aXZlU3BsaXQgPSBTdHJpbmcucHJvdG90eXBlLnNwbGl0LFxuICAgICAgICAgICAgICAgICAgICBjb21wbGlhbnRFeGVjTnBjZyA9IC8oKT8/Ly5leGVjKFwiXCIpWzFdID09PSB1bmRlZixcblxuICAgICAgICAgICAgICAgIC8vIE5QQ0c6IG5vbnBhcnRpY2lwYXRpbmcgY2FwdHVyaW5nIGdyb3VwXG4gICAgICAgICAgICAgICAgc2VsZjtcblxuICAgICAgICAgICAgICAgIHNlbGYgPSBmdW5jdGlvbiAoc3RyLCBzZXBhcmF0b3IsIGxpbWl0KSB7XG4gICAgICAgICAgICAgICAgICAgIC8vIElmIGBzZXBhcmF0b3JgIGlzIG5vdCBhIHJlZ2V4LCB1c2UgYG5hdGl2ZVNwbGl0YFxuICAgICAgICAgICAgICAgICAgICBpZiAoT2JqZWN0LnByb3RvdHlwZS50b1N0cmluZy5jYWxsKHNlcGFyYXRvcikgIT09IFwiW29iamVjdCBSZWdFeHBdXCIpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBuYXRpdmVTcGxpdC5jYWxsKHN0ciwgc2VwYXJhdG9yLCBsaW1pdCk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgdmFyIG91dHB1dCA9IFtdLFxuICAgICAgICAgICAgICAgICAgICAgICAgZmxhZ3MgPSAoc2VwYXJhdG9yLmlnbm9yZUNhc2UgPyBcImlcIiA6IFwiXCIpICsgKHNlcGFyYXRvci5tdWx0aWxpbmUgPyBcIm1cIiA6IFwiXCIpICsgKHNlcGFyYXRvci5leHRlbmRlZCA/IFwieFwiIDogXCJcIikgKyAoc2VwYXJhdG9yLnN0aWNreSA/IFwieVwiIDogXCJcIiksXG5cbiAgICAgICAgICAgICAgICAgICAgLy8gRmlyZWZveCAzK1xuICAgICAgICAgICAgICAgICAgICBsYXN0TGFzdEluZGV4ID0gMCxcblxuICAgICAgICAgICAgICAgICAgICAvLyBNYWtlIGBnbG9iYWxgIGFuZCBhdm9pZCBgbGFzdEluZGV4YCBpc3N1ZXMgYnkgd29ya2luZyB3aXRoIGEgY29weVxuICAgICAgICAgICAgICAgICAgICBzZXBhcmF0b3IgPSBuZXcgUmVnRXhwKHNlcGFyYXRvci5zb3VyY2UsIGZsYWdzICsgXCJnXCIpLFxuICAgICAgICAgICAgICAgICAgICAgICAgc2VwYXJhdG9yMixcbiAgICAgICAgICAgICAgICAgICAgICAgIG1hdGNoLFxuICAgICAgICAgICAgICAgICAgICAgICAgbGFzdEluZGV4LFxuICAgICAgICAgICAgICAgICAgICAgICAgbGFzdExlbmd0aDtcbiAgICAgICAgICAgICAgICAgICAgc3RyICs9IFwiXCI7IC8vIFR5cGUtY29udmVydFxuICAgICAgICAgICAgICAgICAgICBpZiAoIWNvbXBsaWFudEV4ZWNOcGNnKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAvLyBEb2Vzbid0IG5lZWQgZmxhZ3MgZ3ksIGJ1dCB0aGV5IGRvbid0IGh1cnRcbiAgICAgICAgICAgICAgICAgICAgICAgIHNlcGFyYXRvcjIgPSBuZXcgUmVnRXhwKFwiXlwiICsgc2VwYXJhdG9yLnNvdXJjZSArIFwiJCg/IVxcXFxzKVwiLCBmbGFncyk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgLyogVmFsdWVzIGZvciBgbGltaXRgLCBwZXIgdGhlIHNwZWM6XG4gICAgICAgICAgICAgICAgICAgICAqIElmIHVuZGVmaW5lZDogNDI5NDk2NzI5NSAvLyBNYXRoLnBvdygyLCAzMikgLSAxXG4gICAgICAgICAgICAgICAgICAgICAqIElmIDAsIEluZmluaXR5LCBvciBOYU46IDBcbiAgICAgICAgICAgICAgICAgICAgICogSWYgcG9zaXRpdmUgbnVtYmVyOiBsaW1pdCA9IE1hdGguZmxvb3IobGltaXQpOyBpZiAobGltaXQgPiA0Mjk0OTY3Mjk1KSBsaW1pdCAtPSA0Mjk0OTY3Mjk2O1xuICAgICAgICAgICAgICAgICAgICAgKiBJZiBuZWdhdGl2ZSBudW1iZXI6IDQyOTQ5NjcyOTYgLSBNYXRoLmZsb29yKE1hdGguYWJzKGxpbWl0KSlcbiAgICAgICAgICAgICAgICAgICAgICogSWYgb3RoZXI6IFR5cGUtY29udmVydCwgdGhlbiB1c2UgdGhlIGFib3ZlIHJ1bGVzXG4gICAgICAgICAgICAgICAgICAgICAqL1xuICAgICAgICAgICAgICAgICAgICBsaW1pdCA9IGxpbWl0ID09PSB1bmRlZiA/IC0xID4+PiAwIDogLy8gTWF0aC5wb3coMiwgMzIpIC0gMVxuICAgICAgICAgICAgICAgICAgICBsaW1pdCA+Pj4gMDsgLy8gVG9VaW50MzIobGltaXQpXG4gICAgICAgICAgICAgICAgICAgIHdoaWxlIChtYXRjaCA9IHNlcGFyYXRvci5leGVjKHN0cikpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIGBzZXBhcmF0b3IubGFzdEluZGV4YCBpcyBub3QgcmVsaWFibGUgY3Jvc3MtYnJvd3NlclxuICAgICAgICAgICAgICAgICAgICAgICAgbGFzdEluZGV4ID0gbWF0Y2guaW5kZXggKyBtYXRjaFswXS5sZW5ndGg7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAobGFzdEluZGV4ID4gbGFzdExhc3RJbmRleCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIG91dHB1dC5wdXNoKHN0ci5zbGljZShsYXN0TGFzdEluZGV4LCBtYXRjaC5pbmRleCkpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIEZpeCBicm93c2VycyB3aG9zZSBgZXhlY2AgbWV0aG9kcyBkb24ndCBjb25zaXN0ZW50bHkgcmV0dXJuIGB1bmRlZmluZWRgIGZvclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIG5vbnBhcnRpY2lwYXRpbmcgY2FwdHVyaW5nIGdyb3Vwc1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmICghY29tcGxpYW50RXhlY05wY2cgJiYgbWF0Y2gubGVuZ3RoID4gMSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBtYXRjaFswXS5yZXBsYWNlKHNlcGFyYXRvcjIsIGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZvciAodmFyIGkgPSAxOyBpIDwgYXJndW1lbnRzLmxlbmd0aCAtIDI7IGkrKykge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChhcmd1bWVudHNbaV0gPT09IHVuZGVmKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1hdGNoW2ldID0gdW5kZWY7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKG1hdGNoLmxlbmd0aCA+IDEgJiYgbWF0Y2guaW5kZXggPCBzdHIubGVuZ3RoKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIEFycmF5LnByb3RvdHlwZS5wdXNoLmFwcGx5KG91dHB1dCwgbWF0Y2guc2xpY2UoMSkpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBsYXN0TGVuZ3RoID0gbWF0Y2hbMF0ubGVuZ3RoO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxhc3RMYXN0SW5kZXggPSBsYXN0SW5kZXg7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKG91dHB1dC5sZW5ndGggPj0gbGltaXQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHNlcGFyYXRvci5sYXN0SW5kZXggPT09IG1hdGNoLmluZGV4KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgc2VwYXJhdG9yLmxhc3RJbmRleCsrOyAvLyBBdm9pZCBhbiBpbmZpbml0ZSBsb29wXG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgaWYgKGxhc3RMYXN0SW5kZXggPT09IHN0ci5sZW5ndGgpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChsYXN0TGVuZ3RoIHx8ICFzZXBhcmF0b3IudGVzdChcIlwiKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIG91dHB1dC5wdXNoKFwiXCIpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgb3V0cHV0LnB1c2goc3RyLnNsaWNlKGxhc3RMYXN0SW5kZXgpKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICByZXR1cm4gb3V0cHV0Lmxlbmd0aCA+IGxpbWl0ID8gb3V0cHV0LnNsaWNlKDAsIGxpbWl0KSA6IG91dHB1dDtcbiAgICAgICAgICAgICAgICB9O1xuXG4gICAgICAgICAgICAgICAgcmV0dXJuIHNlbGY7XG4gICAgICAgICAgICB9KSgpO1xuICAgICAgICB9LCB7fV0sIDY6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7fSwge31dLCA3OiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge1xuICAgICAgICAgICAgXCJ1c2Ugc3RyaWN0XCI7XG5cbiAgICAgICAgICAgIHZhciBPbmVWZXJzaW9uQ29uc3RyYWludCA9IHJlcXVpcmUoXCJpbmRpdmlkdWFsL29uZS12ZXJzaW9uXCIpO1xuXG4gICAgICAgICAgICB2YXIgTVlfVkVSU0lPTiA9IFwiN1wiO1xuICAgICAgICAgICAgT25lVmVyc2lvbkNvbnN0cmFpbnQoXCJldi1zdG9yZVwiLCBNWV9WRVJTSU9OKTtcblxuICAgICAgICAgICAgdmFyIGhhc2hLZXkgPSBcIl9fRVZfU1RPUkVfS0VZQFwiICsgTVlfVkVSU0lPTjtcblxuICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBFdlN0b3JlO1xuXG4gICAgICAgICAgICBmdW5jdGlvbiBFdlN0b3JlKGVsZW0pIHtcbiAgICAgICAgICAgICAgICB2YXIgaGFzaCA9IGVsZW1baGFzaEtleV07XG5cbiAgICAgICAgICAgICAgICBpZiAoIWhhc2gpIHtcbiAgICAgICAgICAgICAgICAgICAgaGFzaCA9IGVsZW1baGFzaEtleV0gPSB7fTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICByZXR1cm4gaGFzaDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSwgeyBcImluZGl2aWR1YWwvb25lLXZlcnNpb25cIjogOSB9XSwgODogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHtcbiAgICAgICAgICAgIChmdW5jdGlvbiAoZ2xvYmFsKSB7XG4gICAgICAgICAgICAgICAgXCJ1c2Ugc3RyaWN0XCI7XG5cbiAgICAgICAgICAgICAgICAvKmdsb2JhbCB3aW5kb3csIGdsb2JhbCovXG5cbiAgICAgICAgICAgICAgICB2YXIgcm9vdCA9IHR5cGVvZiB3aW5kb3cgIT09IFwidW5kZWZpbmVkXCIgPyB3aW5kb3cgOiB0eXBlb2YgZ2xvYmFsICE9PSBcInVuZGVmaW5lZFwiID8gZ2xvYmFsIDoge307XG5cbiAgICAgICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IEluZGl2aWR1YWw7XG5cbiAgICAgICAgICAgICAgICBmdW5jdGlvbiBJbmRpdmlkdWFsKGtleSwgdmFsdWUpIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKGtleSBpbiByb290KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gcm9vdFtrZXldO1xuICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgcm9vdFtrZXldID0gdmFsdWU7XG5cbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHZhbHVlO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0pLmNhbGwodGhpcywgdHlwZW9mIGdsb2JhbCAhPT0gXCJ1bmRlZmluZWRcIiA/IGdsb2JhbCA6IHR5cGVvZiBzZWxmICE9PSBcInVuZGVmaW5lZFwiID8gc2VsZiA6IHR5cGVvZiB3aW5kb3cgIT09IFwidW5kZWZpbmVkXCIgPyB3aW5kb3cgOiB7fSk7XG4gICAgICAgIH0sIHt9XSwgOTogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHtcbiAgICAgICAgICAgIFwidXNlIHN0cmljdFwiO1xuXG4gICAgICAgICAgICB2YXIgSW5kaXZpZHVhbCA9IHJlcXVpcmUoXCIuL2luZGV4LmpzXCIpO1xuXG4gICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IE9uZVZlcnNpb247XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIE9uZVZlcnNpb24obW9kdWxlTmFtZSwgdmVyc2lvbiwgZGVmYXVsdFZhbHVlKSB7XG4gICAgICAgICAgICAgICAgdmFyIGtleSA9IFwiX19JTkRJVklEVUFMX09ORV9WRVJTSU9OX1wiICsgbW9kdWxlTmFtZTtcbiAgICAgICAgICAgICAgICB2YXIgZW5mb3JjZUtleSA9IGtleSArIFwiX0VORk9SQ0VfU0lOR0xFVE9OXCI7XG5cbiAgICAgICAgICAgICAgICB2YXIgdmVyc2lvblZhbHVlID0gSW5kaXZpZHVhbChlbmZvcmNlS2V5LCB2ZXJzaW9uKTtcblxuICAgICAgICAgICAgICAgIGlmICh2ZXJzaW9uVmFsdWUgIT09IHZlcnNpb24pIHtcbiAgICAgICAgICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKFwiQ2FuIG9ubHkgaGF2ZSBvbmUgY29weSBvZiBcIiArIG1vZHVsZU5hbWUgKyBcIi5cXG5cIiArIFwiWW91IGFscmVhZHkgaGF2ZSB2ZXJzaW9uIFwiICsgdmVyc2lvblZhbHVlICsgXCIgaW5zdGFsbGVkLlxcblwiICsgXCJUaGlzIG1lYW5zIHlvdSBjYW5ub3QgaW5zdGFsbCB2ZXJzaW9uIFwiICsgdmVyc2lvbik7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgcmV0dXJuIEluZGl2aWR1YWwoa2V5LCBkZWZhdWx0VmFsdWUpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9LCB7IFwiLi9pbmRleC5qc1wiOiA4IH1dLCAxMDogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHtcbiAgICAgICAgICAgIChmdW5jdGlvbiAoZ2xvYmFsKSB7XG4gICAgICAgICAgICAgICAgdmFyIHRvcExldmVsID0gdHlwZW9mIGdsb2JhbCAhPT0gXCJ1bmRlZmluZWRcIiA/IGdsb2JhbCA6IHR5cGVvZiB3aW5kb3cgIT09IFwidW5kZWZpbmVkXCIgPyB3aW5kb3cgOiB7fTtcbiAgICAgICAgICAgICAgICB2YXIgbWluRG9jID0gcmVxdWlyZShcIm1pbi1kb2N1bWVudFwiKTtcblxuICAgICAgICAgICAgICAgIGlmICh0eXBlb2YgZG9jdW1lbnQgIT09IFwidW5kZWZpbmVkXCIpIHtcbiAgICAgICAgICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBkb2N1bWVudDtcbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICB2YXIgZG9jY3kgPSB0b3BMZXZlbFtcIl9fR0xPQkFMX0RPQ1VNRU5UX0NBQ0hFQDRcIl07XG5cbiAgICAgICAgICAgICAgICAgICAgaWYgKCFkb2NjeSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgZG9jY3kgPSB0b3BMZXZlbFtcIl9fR0xPQkFMX0RPQ1VNRU5UX0NBQ0hFQDRcIl0gPSBtaW5Eb2M7XG4gICAgICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IGRvY2N5O1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0pLmNhbGwodGhpcywgdHlwZW9mIGdsb2JhbCAhPT0gXCJ1bmRlZmluZWRcIiA/IGdsb2JhbCA6IHR5cGVvZiBzZWxmICE9PSBcInVuZGVmaW5lZFwiID8gc2VsZiA6IHR5cGVvZiB3aW5kb3cgIT09IFwidW5kZWZpbmVkXCIgPyB3aW5kb3cgOiB7fSk7XG4gICAgICAgIH0sIHsgXCJtaW4tZG9jdW1lbnRcIjogNiB9XSwgMTE6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICBcInVzZSBzdHJpY3RcIjtcblxuICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiBpc09iamVjdCh4KSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHR5cGVvZiB4ID09PSBcIm9iamVjdFwiICYmIHggIT09IG51bGw7XG4gICAgICAgICAgICB9O1xuICAgICAgICB9LCB7fV0sIDEyOiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge1xuICAgICAgICAgICAgdmFyIG5hdGl2ZUlzQXJyYXkgPSBBcnJheS5pc0FycmF5O1xuICAgICAgICAgICAgdmFyIHRvU3RyaW5nID0gT2JqZWN0LnByb3RvdHlwZS50b1N0cmluZztcblxuICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBuYXRpdmVJc0FycmF5IHx8IGlzQXJyYXk7XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIGlzQXJyYXkob2JqKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHRvU3RyaW5nLmNhbGwob2JqKSA9PT0gXCJbb2JqZWN0IEFycmF5XVwiO1xuICAgICAgICAgICAgfVxuICAgICAgICB9LCB7fV0sIDEzOiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge1xuICAgICAgICAgICAgdmFyIHBhdGNoID0gcmVxdWlyZShcIi4vdmRvbS9wYXRjaC5qc1wiKTtcblxuICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBwYXRjaDtcbiAgICAgICAgfSwgeyBcIi4vdmRvbS9wYXRjaC5qc1wiOiAxOCB9XSwgMTQ6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICB2YXIgaXNPYmplY3QgPSByZXF1aXJlKFwiaXMtb2JqZWN0XCIpO1xuICAgICAgICAgICAgdmFyIGlzSG9vayA9IHJlcXVpcmUoXCIuLi92bm9kZS9pcy12aG9vay5qc1wiKTtcblxuICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBhcHBseVByb3BlcnRpZXM7XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIGFwcGx5UHJvcGVydGllcyhub2RlLCBwcm9wcywgcHJldmlvdXMpIHtcbiAgICAgICAgICAgICAgICBmb3IgKHZhciBwcm9wTmFtZSBpbiBwcm9wcykge1xuICAgICAgICAgICAgICAgICAgICB2YXIgcHJvcFZhbHVlID0gcHJvcHNbcHJvcE5hbWVdO1xuXG4gICAgICAgICAgICAgICAgICAgIGlmIChwcm9wVmFsdWUgPT09IHVuZGVmaW5lZCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgcmVtb3ZlUHJvcGVydHkobm9kZSwgcHJvcE5hbWUsIHByb3BWYWx1ZSwgcHJldmlvdXMpO1xuICAgICAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKGlzSG9vayhwcm9wVmFsdWUpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICByZW1vdmVQcm9wZXJ0eShub2RlLCBwcm9wTmFtZSwgcHJvcFZhbHVlLCBwcmV2aW91cyk7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAocHJvcFZhbHVlLmhvb2spIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBwcm9wVmFsdWUuaG9vayhub2RlLCBwcm9wTmFtZSwgcHJldmlvdXMgPyBwcmV2aW91c1twcm9wTmFtZV0gOiB1bmRlZmluZWQpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGlzT2JqZWN0KHByb3BWYWx1ZSkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBwYXRjaE9iamVjdChub2RlLCBwcm9wcywgcHJldmlvdXMsIHByb3BOYW1lLCBwcm9wVmFsdWUpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBub2RlW3Byb3BOYW1lXSA9IHByb3BWYWx1ZTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZnVuY3Rpb24gcmVtb3ZlUHJvcGVydHkobm9kZSwgcHJvcE5hbWUsIHByb3BWYWx1ZSwgcHJldmlvdXMpIHtcbiAgICAgICAgICAgICAgICBpZiAocHJldmlvdXMpIHtcbiAgICAgICAgICAgICAgICAgICAgdmFyIHByZXZpb3VzVmFsdWUgPSBwcmV2aW91c1twcm9wTmFtZV07XG5cbiAgICAgICAgICAgICAgICAgICAgaWYgKCFpc0hvb2socHJldmlvdXNWYWx1ZSkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChwcm9wTmFtZSA9PT0gXCJhdHRyaWJ1dGVzXCIpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBmb3IgKHZhciBhdHRyTmFtZSBpbiBwcmV2aW91c1ZhbHVlKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG5vZGUucmVtb3ZlQXR0cmlidXRlKGF0dHJOYW1lKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKHByb3BOYW1lID09PSBcInN0eWxlXCIpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBmb3IgKHZhciBpIGluIHByZXZpb3VzVmFsdWUpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbm9kZS5zdHlsZVtpXSA9IFwiXCI7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIGlmICh0eXBlb2YgcHJldmlvdXNWYWx1ZSA9PT0gXCJzdHJpbmdcIikge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIG5vZGVbcHJvcE5hbWVdID0gXCJcIjtcbiAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgbm9kZVtwcm9wTmFtZV0gPSBudWxsO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKHByZXZpb3VzVmFsdWUudW5ob29rKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBwcmV2aW91c1ZhbHVlLnVuaG9vayhub2RlLCBwcm9wTmFtZSwgcHJvcFZhbHVlKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZnVuY3Rpb24gcGF0Y2hPYmplY3Qobm9kZSwgcHJvcHMsIHByZXZpb3VzLCBwcm9wTmFtZSwgcHJvcFZhbHVlKSB7XG4gICAgICAgICAgICAgICAgdmFyIHByZXZpb3VzVmFsdWUgPSBwcmV2aW91cyA/IHByZXZpb3VzW3Byb3BOYW1lXSA6IHVuZGVmaW5lZDtcblxuICAgICAgICAgICAgICAgIC8vIFNldCBhdHRyaWJ1dGVzXG4gICAgICAgICAgICAgICAgaWYgKHByb3BOYW1lID09PSBcImF0dHJpYnV0ZXNcIikge1xuICAgICAgICAgICAgICAgICAgICBmb3IgKHZhciBhdHRyTmFtZSBpbiBwcm9wVmFsdWUpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHZhciBhdHRyVmFsdWUgPSBwcm9wVmFsdWVbYXR0ck5hbWVdO1xuXG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoYXR0clZhbHVlID09PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBub2RlLnJlbW92ZUF0dHJpYnV0ZShhdHRyTmFtZSk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIG5vZGUuc2V0QXR0cmlidXRlKGF0dHJOYW1lLCBhdHRyVmFsdWUpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIGlmIChwcmV2aW91c1ZhbHVlICYmIGlzT2JqZWN0KHByZXZpb3VzVmFsdWUpICYmIGdldFByb3RvdHlwZShwcmV2aW91c1ZhbHVlKSAhPT0gZ2V0UHJvdG90eXBlKHByb3BWYWx1ZSkpIHtcbiAgICAgICAgICAgICAgICAgICAgbm9kZVtwcm9wTmFtZV0gPSBwcm9wVmFsdWU7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICBpZiAoIWlzT2JqZWN0KG5vZGVbcHJvcE5hbWVdKSkge1xuICAgICAgICAgICAgICAgICAgICBub2RlW3Byb3BOYW1lXSA9IHt9O1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHZhciByZXBsYWNlciA9IHByb3BOYW1lID09PSBcInN0eWxlXCIgPyBcIlwiIDogdW5kZWZpbmVkO1xuXG4gICAgICAgICAgICAgICAgZm9yICh2YXIgayBpbiBwcm9wVmFsdWUpIHtcbiAgICAgICAgICAgICAgICAgICAgdmFyIHZhbHVlID0gcHJvcFZhbHVlW2tdO1xuICAgICAgICAgICAgICAgICAgICBub2RlW3Byb3BOYW1lXVtrXSA9IHZhbHVlID09PSB1bmRlZmluZWQgPyByZXBsYWNlciA6IHZhbHVlO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZnVuY3Rpb24gZ2V0UHJvdG90eXBlKHZhbHVlKSB7XG4gICAgICAgICAgICAgICAgaWYgKE9iamVjdC5nZXRQcm90b3R5cGVPZikge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gT2JqZWN0LmdldFByb3RvdHlwZU9mKHZhbHVlKTtcbiAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKHZhbHVlLl9fcHJvdG9fXykge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gdmFsdWUuX19wcm90b19fO1xuICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAodmFsdWUuY29uc3RydWN0b3IpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHZhbHVlLmNvbnN0cnVjdG9yLnByb3RvdHlwZTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH0sIHsgXCIuLi92bm9kZS9pcy12aG9vay5qc1wiOiAyNiwgXCJpcy1vYmplY3RcIjogMTEgfV0sIDE1OiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge1xuICAgICAgICAgICAgdmFyIGRvY3VtZW50ID0gcmVxdWlyZShcImdsb2JhbC9kb2N1bWVudFwiKTtcblxuICAgICAgICAgICAgdmFyIGFwcGx5UHJvcGVydGllcyA9IHJlcXVpcmUoXCIuL2FwcGx5LXByb3BlcnRpZXNcIik7XG5cbiAgICAgICAgICAgIHZhciBpc1ZOb2RlID0gcmVxdWlyZShcIi4uL3Zub2RlL2lzLXZub2RlLmpzXCIpO1xuICAgICAgICAgICAgdmFyIGlzVlRleHQgPSByZXF1aXJlKFwiLi4vdm5vZGUvaXMtdnRleHQuanNcIik7XG4gICAgICAgICAgICB2YXIgaXNXaWRnZXQgPSByZXF1aXJlKFwiLi4vdm5vZGUvaXMtd2lkZ2V0LmpzXCIpO1xuICAgICAgICAgICAgdmFyIGhhbmRsZVRodW5rID0gcmVxdWlyZShcIi4uL3Zub2RlL2hhbmRsZS10aHVuay5qc1wiKTtcblxuICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBjcmVhdGVFbGVtZW50O1xuXG4gICAgICAgICAgICBmdW5jdGlvbiBjcmVhdGVFbGVtZW50KHZub2RlLCBvcHRzKSB7XG4gICAgICAgICAgICAgICAgdmFyIGRvYyA9IG9wdHMgPyBvcHRzLmRvY3VtZW50IHx8IGRvY3VtZW50IDogZG9jdW1lbnQ7XG4gICAgICAgICAgICAgICAgdmFyIHdhcm4gPSBvcHRzID8gb3B0cy53YXJuIDogbnVsbDtcblxuICAgICAgICAgICAgICAgIHZub2RlID0gaGFuZGxlVGh1bmsodm5vZGUpLmE7XG5cbiAgICAgICAgICAgICAgICBpZiAoaXNXaWRnZXQodm5vZGUpKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiB2bm9kZS5pbml0KCk7XG4gICAgICAgICAgICAgICAgfSBlbHNlIGlmIChpc1ZUZXh0KHZub2RlKSkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gZG9jLmNyZWF0ZVRleHROb2RlKHZub2RlLnRleHQpO1xuICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoIWlzVk5vZGUodm5vZGUpKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmICh3YXJuKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICB3YXJuKFwiSXRlbSBpcyBub3QgYSB2YWxpZCB2aXJ0dWFsIGRvbSBub2RlXCIsIHZub2RlKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICByZXR1cm4gbnVsbDtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICB2YXIgbm9kZSA9IHZub2RlLm5hbWVzcGFjZSA9PT0gbnVsbCA/IGRvYy5jcmVhdGVFbGVtZW50KHZub2RlLnRhZ05hbWUpIDogZG9jLmNyZWF0ZUVsZW1lbnROUyh2bm9kZS5uYW1lc3BhY2UsIHZub2RlLnRhZ05hbWUpO1xuXG4gICAgICAgICAgICAgICAgdmFyIHByb3BzID0gdm5vZGUucHJvcGVydGllcztcbiAgICAgICAgICAgICAgICBhcHBseVByb3BlcnRpZXMobm9kZSwgcHJvcHMpO1xuXG4gICAgICAgICAgICAgICAgdmFyIGNoaWxkcmVuID0gdm5vZGUuY2hpbGRyZW47XG5cbiAgICAgICAgICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IGNoaWxkcmVuLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciBjaGlsZE5vZGUgPSBjcmVhdGVFbGVtZW50KGNoaWxkcmVuW2ldLCBvcHRzKTtcbiAgICAgICAgICAgICAgICAgICAgaWYgKGNoaWxkTm9kZSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgbm9kZS5hcHBlbmRDaGlsZChjaGlsZE5vZGUpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgcmV0dXJuIG5vZGU7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0sIHsgXCIuLi92bm9kZS9oYW5kbGUtdGh1bmsuanNcIjogMjQsIFwiLi4vdm5vZGUvaXMtdm5vZGUuanNcIjogMjcsIFwiLi4vdm5vZGUvaXMtdnRleHQuanNcIjogMjgsIFwiLi4vdm5vZGUvaXMtd2lkZ2V0LmpzXCI6IDI5LCBcIi4vYXBwbHktcHJvcGVydGllc1wiOiAxNCwgXCJnbG9iYWwvZG9jdW1lbnRcIjogMTAgfV0sIDE2OiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge1xuICAgICAgICAgICAgLy8gTWFwcyBhIHZpcnR1YWwgRE9NIHRyZWUgb250byBhIHJlYWwgRE9NIHRyZWUgaW4gYW4gZWZmaWNpZW50IG1hbm5lci5cbiAgICAgICAgICAgIC8vIFdlIGRvbid0IHdhbnQgdG8gcmVhZCBhbGwgb2YgdGhlIERPTSBub2RlcyBpbiB0aGUgdHJlZSBzbyB3ZSB1c2VcbiAgICAgICAgICAgIC8vIHRoZSBpbi1vcmRlciB0cmVlIGluZGV4aW5nIHRvIGVsaW1pbmF0ZSByZWN1cnNpb24gZG93biBjZXJ0YWluIGJyYW5jaGVzLlxuICAgICAgICAgICAgLy8gV2Ugb25seSByZWN1cnNlIGludG8gYSBET00gbm9kZSBpZiB3ZSBrbm93IHRoYXQgaXQgY29udGFpbnMgYSBjaGlsZCBvZlxuICAgICAgICAgICAgLy8gaW50ZXJlc3QuXG5cbiAgICAgICAgICAgIHZhciBub0NoaWxkID0ge307XG5cbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gZG9tSW5kZXg7XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIGRvbUluZGV4KHJvb3ROb2RlLCB0cmVlLCBpbmRpY2VzLCBub2Rlcykge1xuICAgICAgICAgICAgICAgIGlmICghaW5kaWNlcyB8fCBpbmRpY2VzLmxlbmd0aCA9PT0gMCkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4ge307XG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgaW5kaWNlcy5zb3J0KGFzY2VuZGluZyk7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiByZWN1cnNlKHJvb3ROb2RlLCB0cmVlLCBpbmRpY2VzLCBub2RlcywgMCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBmdW5jdGlvbiByZWN1cnNlKHJvb3ROb2RlLCB0cmVlLCBpbmRpY2VzLCBub2Rlcywgcm9vdEluZGV4KSB7XG4gICAgICAgICAgICAgICAgbm9kZXMgPSBub2RlcyB8fCB7fTtcblxuICAgICAgICAgICAgICAgIGlmIChyb290Tm9kZSkge1xuICAgICAgICAgICAgICAgICAgICBpZiAoaW5kZXhJblJhbmdlKGluZGljZXMsIHJvb3RJbmRleCwgcm9vdEluZGV4KSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgbm9kZXNbcm9vdEluZGV4XSA9IHJvb3ROb2RlO1xuICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgdmFyIHZDaGlsZHJlbiA9IHRyZWUuY2hpbGRyZW47XG5cbiAgICAgICAgICAgICAgICAgICAgaWYgKHZDaGlsZHJlbikge1xuXG4gICAgICAgICAgICAgICAgICAgICAgICB2YXIgY2hpbGROb2RlcyA9IHJvb3ROb2RlLmNoaWxkTm9kZXM7XG5cbiAgICAgICAgICAgICAgICAgICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgdHJlZS5jaGlsZHJlbi5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJvb3RJbmRleCArPSAxO1xuXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdmFyIHZDaGlsZCA9IHZDaGlsZHJlbltpXSB8fCBub0NoaWxkO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZhciBuZXh0SW5kZXggPSByb290SW5kZXggKyAodkNoaWxkLmNvdW50IHx8IDApO1xuXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gc2tpcCByZWN1cnNpb24gZG93biB0aGUgdHJlZSBpZiB0aGVyZSBhcmUgbm8gbm9kZXMgZG93biBoZXJlXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGluZGV4SW5SYW5nZShpbmRpY2VzLCByb290SW5kZXgsIG5leHRJbmRleCkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmVjdXJzZShjaGlsZE5vZGVzW2ldLCB2Q2hpbGQsIGluZGljZXMsIG5vZGVzLCByb290SW5kZXgpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJvb3RJbmRleCA9IG5leHRJbmRleDtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHJldHVybiBub2RlcztcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgLy8gQmluYXJ5IHNlYXJjaCBmb3IgYW4gaW5kZXggaW4gdGhlIGludGVydmFsIFtsZWZ0LCByaWdodF1cbiAgICAgICAgICAgIGZ1bmN0aW9uIGluZGV4SW5SYW5nZShpbmRpY2VzLCBsZWZ0LCByaWdodCkge1xuICAgICAgICAgICAgICAgIGlmIChpbmRpY2VzLmxlbmd0aCA9PT0gMCkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgdmFyIG1pbkluZGV4ID0gMDtcbiAgICAgICAgICAgICAgICB2YXIgbWF4SW5kZXggPSBpbmRpY2VzLmxlbmd0aCAtIDE7XG4gICAgICAgICAgICAgICAgdmFyIGN1cnJlbnRJbmRleDtcbiAgICAgICAgICAgICAgICB2YXIgY3VycmVudEl0ZW07XG5cbiAgICAgICAgICAgICAgICB3aGlsZSAobWluSW5kZXggPD0gbWF4SW5kZXgpIHtcbiAgICAgICAgICAgICAgICAgICAgY3VycmVudEluZGV4ID0gKG1heEluZGV4ICsgbWluSW5kZXgpIC8gMiA+PiAwO1xuICAgICAgICAgICAgICAgICAgICBjdXJyZW50SXRlbSA9IGluZGljZXNbY3VycmVudEluZGV4XTtcblxuICAgICAgICAgICAgICAgICAgICBpZiAobWluSW5kZXggPT09IG1heEluZGV4KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gY3VycmVudEl0ZW0gPj0gbGVmdCAmJiBjdXJyZW50SXRlbSA8PSByaWdodDtcbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIGlmIChjdXJyZW50SXRlbSA8IGxlZnQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIG1pbkluZGV4ID0gY3VycmVudEluZGV4ICsgMTtcbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIGlmIChjdXJyZW50SXRlbSA+IHJpZ2h0KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBtYXhJbmRleCA9IGN1cnJlbnRJbmRleCAtIDE7XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZnVuY3Rpb24gYXNjZW5kaW5nKGEsIGIpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gYSA+IGIgPyAxIDogLTE7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0sIHt9XSwgMTc6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICB2YXIgYXBwbHlQcm9wZXJ0aWVzID0gcmVxdWlyZShcIi4vYXBwbHktcHJvcGVydGllc1wiKTtcblxuICAgICAgICAgICAgdmFyIGlzV2lkZ2V0ID0gcmVxdWlyZShcIi4uL3Zub2RlL2lzLXdpZGdldC5qc1wiKTtcbiAgICAgICAgICAgIHZhciBWUGF0Y2ggPSByZXF1aXJlKFwiLi4vdm5vZGUvdnBhdGNoLmpzXCIpO1xuXG4gICAgICAgICAgICB2YXIgdXBkYXRlV2lkZ2V0ID0gcmVxdWlyZShcIi4vdXBkYXRlLXdpZGdldFwiKTtcblxuICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBhcHBseVBhdGNoO1xuXG4gICAgICAgICAgICBmdW5jdGlvbiBhcHBseVBhdGNoKHZwYXRjaCwgZG9tTm9kZSwgcmVuZGVyT3B0aW9ucykge1xuICAgICAgICAgICAgICAgIHZhciB0eXBlID0gdnBhdGNoLnR5cGU7XG4gICAgICAgICAgICAgICAgdmFyIHZOb2RlID0gdnBhdGNoLnZOb2RlO1xuICAgICAgICAgICAgICAgIHZhciBwYXRjaCA9IHZwYXRjaC5wYXRjaDtcblxuICAgICAgICAgICAgICAgIHN3aXRjaCAodHlwZSkge1xuICAgICAgICAgICAgICAgICAgICBjYXNlIFZQYXRjaC5SRU1PVkU6XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gcmVtb3ZlTm9kZShkb21Ob2RlLCB2Tm9kZSk7XG4gICAgICAgICAgICAgICAgICAgIGNhc2UgVlBhdGNoLklOU0VSVDpcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBpbnNlcnROb2RlKGRvbU5vZGUsIHBhdGNoLCByZW5kZXJPcHRpb25zKTtcbiAgICAgICAgICAgICAgICAgICAgY2FzZSBWUGF0Y2guVlRFWFQ6XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gc3RyaW5nUGF0Y2goZG9tTm9kZSwgdk5vZGUsIHBhdGNoLCByZW5kZXJPcHRpb25zKTtcbiAgICAgICAgICAgICAgICAgICAgY2FzZSBWUGF0Y2guV0lER0VUOlxuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHdpZGdldFBhdGNoKGRvbU5vZGUsIHZOb2RlLCBwYXRjaCwgcmVuZGVyT3B0aW9ucyk7XG4gICAgICAgICAgICAgICAgICAgIGNhc2UgVlBhdGNoLlZOT0RFOlxuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHZOb2RlUGF0Y2goZG9tTm9kZSwgdk5vZGUsIHBhdGNoLCByZW5kZXJPcHRpb25zKTtcbiAgICAgICAgICAgICAgICAgICAgY2FzZSBWUGF0Y2guT1JERVI6XG4gICAgICAgICAgICAgICAgICAgICAgICByZW9yZGVyQ2hpbGRyZW4oZG9tTm9kZSwgcGF0Y2gpO1xuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGRvbU5vZGU7XG4gICAgICAgICAgICAgICAgICAgIGNhc2UgVlBhdGNoLlBST1BTOlxuICAgICAgICAgICAgICAgICAgICAgICAgYXBwbHlQcm9wZXJ0aWVzKGRvbU5vZGUsIHBhdGNoLCB2Tm9kZS5wcm9wZXJ0aWVzKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBkb21Ob2RlO1xuICAgICAgICAgICAgICAgICAgICBjYXNlIFZQYXRjaC5USFVOSzpcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiByZXBsYWNlUm9vdChkb21Ob2RlLCByZW5kZXJPcHRpb25zLnBhdGNoKGRvbU5vZGUsIHBhdGNoLCByZW5kZXJPcHRpb25zKSk7XG4gICAgICAgICAgICAgICAgICAgIGRlZmF1bHQ6XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gZG9tTm9kZTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIHJlbW92ZU5vZGUoZG9tTm9kZSwgdk5vZGUpIHtcbiAgICAgICAgICAgICAgICB2YXIgcGFyZW50Tm9kZSA9IGRvbU5vZGUucGFyZW50Tm9kZTtcblxuICAgICAgICAgICAgICAgIGlmIChwYXJlbnROb2RlKSB7XG4gICAgICAgICAgICAgICAgICAgIHBhcmVudE5vZGUucmVtb3ZlQ2hpbGQoZG9tTm9kZSk7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgZGVzdHJveVdpZGdldChkb21Ob2RlLCB2Tm9kZSk7XG5cbiAgICAgICAgICAgICAgICByZXR1cm4gbnVsbDtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZnVuY3Rpb24gaW5zZXJ0Tm9kZShwYXJlbnROb2RlLCB2Tm9kZSwgcmVuZGVyT3B0aW9ucykge1xuICAgICAgICAgICAgICAgIHZhciBuZXdOb2RlID0gcmVuZGVyT3B0aW9ucy5yZW5kZXIodk5vZGUsIHJlbmRlck9wdGlvbnMpO1xuXG4gICAgICAgICAgICAgICAgaWYgKHBhcmVudE5vZGUpIHtcbiAgICAgICAgICAgICAgICAgICAgcGFyZW50Tm9kZS5hcHBlbmRDaGlsZChuZXdOb2RlKTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICByZXR1cm4gcGFyZW50Tm9kZTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZnVuY3Rpb24gc3RyaW5nUGF0Y2goZG9tTm9kZSwgbGVmdFZOb2RlLCB2VGV4dCwgcmVuZGVyT3B0aW9ucykge1xuICAgICAgICAgICAgICAgIHZhciBuZXdOb2RlO1xuXG4gICAgICAgICAgICAgICAgaWYgKGRvbU5vZGUubm9kZVR5cGUgPT09IDMpIHtcbiAgICAgICAgICAgICAgICAgICAgZG9tTm9kZS5yZXBsYWNlRGF0YSgwLCBkb21Ob2RlLmxlbmd0aCwgdlRleHQudGV4dCk7XG4gICAgICAgICAgICAgICAgICAgIG5ld05vZGUgPSBkb21Ob2RlO1xuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciBwYXJlbnROb2RlID0gZG9tTm9kZS5wYXJlbnROb2RlO1xuICAgICAgICAgICAgICAgICAgICBuZXdOb2RlID0gcmVuZGVyT3B0aW9ucy5yZW5kZXIodlRleHQsIHJlbmRlck9wdGlvbnMpO1xuXG4gICAgICAgICAgICAgICAgICAgIGlmIChwYXJlbnROb2RlICYmIG5ld05vZGUgIT09IGRvbU5vZGUpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHBhcmVudE5vZGUucmVwbGFjZUNoaWxkKG5ld05vZGUsIGRvbU5vZGUpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgcmV0dXJuIG5ld05vZGU7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIHdpZGdldFBhdGNoKGRvbU5vZGUsIGxlZnRWTm9kZSwgd2lkZ2V0LCByZW5kZXJPcHRpb25zKSB7XG4gICAgICAgICAgICAgICAgdmFyIHVwZGF0aW5nID0gdXBkYXRlV2lkZ2V0KGxlZnRWTm9kZSwgd2lkZ2V0KTtcbiAgICAgICAgICAgICAgICB2YXIgbmV3Tm9kZTtcblxuICAgICAgICAgICAgICAgIGlmICh1cGRhdGluZykge1xuICAgICAgICAgICAgICAgICAgICBuZXdOb2RlID0gd2lkZ2V0LnVwZGF0ZShsZWZ0Vk5vZGUsIGRvbU5vZGUpIHx8IGRvbU5vZGU7XG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgbmV3Tm9kZSA9IHJlbmRlck9wdGlvbnMucmVuZGVyKHdpZGdldCwgcmVuZGVyT3B0aW9ucyk7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgdmFyIHBhcmVudE5vZGUgPSBkb21Ob2RlLnBhcmVudE5vZGU7XG5cbiAgICAgICAgICAgICAgICBpZiAocGFyZW50Tm9kZSAmJiBuZXdOb2RlICE9PSBkb21Ob2RlKSB7XG4gICAgICAgICAgICAgICAgICAgIHBhcmVudE5vZGUucmVwbGFjZUNoaWxkKG5ld05vZGUsIGRvbU5vZGUpO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIGlmICghdXBkYXRpbmcpIHtcbiAgICAgICAgICAgICAgICAgICAgZGVzdHJveVdpZGdldChkb21Ob2RlLCBsZWZ0Vk5vZGUpO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHJldHVybiBuZXdOb2RlO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBmdW5jdGlvbiB2Tm9kZVBhdGNoKGRvbU5vZGUsIGxlZnRWTm9kZSwgdk5vZGUsIHJlbmRlck9wdGlvbnMpIHtcbiAgICAgICAgICAgICAgICB2YXIgcGFyZW50Tm9kZSA9IGRvbU5vZGUucGFyZW50Tm9kZTtcbiAgICAgICAgICAgICAgICB2YXIgbmV3Tm9kZSA9IHJlbmRlck9wdGlvbnMucmVuZGVyKHZOb2RlLCByZW5kZXJPcHRpb25zKTtcblxuICAgICAgICAgICAgICAgIGlmIChwYXJlbnROb2RlICYmIG5ld05vZGUgIT09IGRvbU5vZGUpIHtcbiAgICAgICAgICAgICAgICAgICAgcGFyZW50Tm9kZS5yZXBsYWNlQ2hpbGQobmV3Tm9kZSwgZG9tTm9kZSk7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgcmV0dXJuIG5ld05vZGU7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIGRlc3Ryb3lXaWRnZXQoZG9tTm9kZSwgdykge1xuICAgICAgICAgICAgICAgIGlmICh0eXBlb2Ygdy5kZXN0cm95ID09PSBcImZ1bmN0aW9uXCIgJiYgaXNXaWRnZXQodykpIHtcbiAgICAgICAgICAgICAgICAgICAgdy5kZXN0cm95KGRvbU5vZGUpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZnVuY3Rpb24gcmVvcmRlckNoaWxkcmVuKGRvbU5vZGUsIG1vdmVzKSB7XG4gICAgICAgICAgICAgICAgdmFyIGNoaWxkTm9kZXMgPSBkb21Ob2RlLmNoaWxkTm9kZXM7XG4gICAgICAgICAgICAgICAgdmFyIGtleU1hcCA9IHt9O1xuICAgICAgICAgICAgICAgIHZhciBub2RlO1xuICAgICAgICAgICAgICAgIHZhciByZW1vdmU7XG4gICAgICAgICAgICAgICAgdmFyIGluc2VydDtcblxuICAgICAgICAgICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgbW92ZXMucmVtb3Zlcy5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgICAgICAgICByZW1vdmUgPSBtb3Zlcy5yZW1vdmVzW2ldO1xuICAgICAgICAgICAgICAgICAgICBub2RlID0gY2hpbGROb2Rlc1tyZW1vdmUuZnJvbV07XG4gICAgICAgICAgICAgICAgICAgIGlmIChyZW1vdmUua2V5KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBrZXlNYXBbcmVtb3ZlLmtleV0gPSBub2RlO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIGRvbU5vZGUucmVtb3ZlQ2hpbGQobm9kZSk7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgdmFyIGxlbmd0aCA9IGNoaWxkTm9kZXMubGVuZ3RoO1xuICAgICAgICAgICAgICAgIGZvciAodmFyIGogPSAwOyBqIDwgbW92ZXMuaW5zZXJ0cy5sZW5ndGg7IGorKykge1xuICAgICAgICAgICAgICAgICAgICBpbnNlcnQgPSBtb3Zlcy5pbnNlcnRzW2pdO1xuICAgICAgICAgICAgICAgICAgICBub2RlID0ga2V5TWFwW2luc2VydC5rZXldO1xuICAgICAgICAgICAgICAgICAgICAvLyB0aGlzIGlzIHRoZSB3ZWlyZGVzdCBidWcgaSd2ZSBldmVyIHNlZW4gaW4gd2Via2l0XG4gICAgICAgICAgICAgICAgICAgIGRvbU5vZGUuaW5zZXJ0QmVmb3JlKG5vZGUsIGluc2VydC50byA+PSBsZW5ndGgrKyA/IG51bGwgOiBjaGlsZE5vZGVzW2luc2VydC50b10pO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZnVuY3Rpb24gcmVwbGFjZVJvb3Qob2xkUm9vdCwgbmV3Um9vdCkge1xuICAgICAgICAgICAgICAgIGlmIChvbGRSb290ICYmIG5ld1Jvb3QgJiYgb2xkUm9vdCAhPT0gbmV3Um9vdCAmJiBvbGRSb290LnBhcmVudE5vZGUpIHtcbiAgICAgICAgICAgICAgICAgICAgb2xkUm9vdC5wYXJlbnROb2RlLnJlcGxhY2VDaGlsZChuZXdSb290LCBvbGRSb290KTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICByZXR1cm4gbmV3Um9vdDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSwgeyBcIi4uL3Zub2RlL2lzLXdpZGdldC5qc1wiOiAyOSwgXCIuLi92bm9kZS92cGF0Y2guanNcIjogMzIsIFwiLi9hcHBseS1wcm9wZXJ0aWVzXCI6IDE0LCBcIi4vdXBkYXRlLXdpZGdldFwiOiAxOSB9XSwgMTg6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICB2YXIgZG9jdW1lbnQgPSByZXF1aXJlKFwiZ2xvYmFsL2RvY3VtZW50XCIpO1xuICAgICAgICAgICAgdmFyIGlzQXJyYXkgPSByZXF1aXJlKFwieC1pcy1hcnJheVwiKTtcblxuICAgICAgICAgICAgdmFyIHJlbmRlciA9IHJlcXVpcmUoXCIuL2NyZWF0ZS1lbGVtZW50XCIpO1xuICAgICAgICAgICAgdmFyIGRvbUluZGV4ID0gcmVxdWlyZShcIi4vZG9tLWluZGV4XCIpO1xuICAgICAgICAgICAgdmFyIHBhdGNoT3AgPSByZXF1aXJlKFwiLi9wYXRjaC1vcFwiKTtcbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gcGF0Y2g7XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIHBhdGNoKHJvb3ROb2RlLCBwYXRjaGVzLCByZW5kZXJPcHRpb25zKSB7XG4gICAgICAgICAgICAgICAgcmVuZGVyT3B0aW9ucyA9IHJlbmRlck9wdGlvbnMgfHwge307XG4gICAgICAgICAgICAgICAgcmVuZGVyT3B0aW9ucy5wYXRjaCA9IHJlbmRlck9wdGlvbnMucGF0Y2ggJiYgcmVuZGVyT3B0aW9ucy5wYXRjaCAhPT0gcGF0Y2ggPyByZW5kZXJPcHRpb25zLnBhdGNoIDogcGF0Y2hSZWN1cnNpdmU7XG4gICAgICAgICAgICAgICAgcmVuZGVyT3B0aW9ucy5yZW5kZXIgPSByZW5kZXJPcHRpb25zLnJlbmRlciB8fCByZW5kZXI7XG5cbiAgICAgICAgICAgICAgICByZXR1cm4gcmVuZGVyT3B0aW9ucy5wYXRjaChyb290Tm9kZSwgcGF0Y2hlcywgcmVuZGVyT3B0aW9ucyk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIHBhdGNoUmVjdXJzaXZlKHJvb3ROb2RlLCBwYXRjaGVzLCByZW5kZXJPcHRpb25zKSB7XG4gICAgICAgICAgICAgICAgdmFyIGluZGljZXMgPSBwYXRjaEluZGljZXMocGF0Y2hlcyk7XG5cbiAgICAgICAgICAgICAgICBpZiAoaW5kaWNlcy5sZW5ndGggPT09IDApIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHJvb3ROb2RlO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHZhciBpbmRleCA9IGRvbUluZGV4KHJvb3ROb2RlLCBwYXRjaGVzLmEsIGluZGljZXMpO1xuICAgICAgICAgICAgICAgIHZhciBvd25lckRvY3VtZW50ID0gcm9vdE5vZGUub3duZXJEb2N1bWVudDtcblxuICAgICAgICAgICAgICAgIGlmICghcmVuZGVyT3B0aW9ucy5kb2N1bWVudCAmJiBvd25lckRvY3VtZW50ICE9PSBkb2N1bWVudCkge1xuICAgICAgICAgICAgICAgICAgICByZW5kZXJPcHRpb25zLmRvY3VtZW50ID0gb3duZXJEb2N1bWVudDtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IGluZGljZXMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgICAgICAgICAgdmFyIG5vZGVJbmRleCA9IGluZGljZXNbaV07XG4gICAgICAgICAgICAgICAgICAgIHJvb3ROb2RlID0gYXBwbHlQYXRjaChyb290Tm9kZSwgaW5kZXhbbm9kZUluZGV4XSwgcGF0Y2hlc1tub2RlSW5kZXhdLCByZW5kZXJPcHRpb25zKTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICByZXR1cm4gcm9vdE5vZGU7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIGFwcGx5UGF0Y2gocm9vdE5vZGUsIGRvbU5vZGUsIHBhdGNoTGlzdCwgcmVuZGVyT3B0aW9ucykge1xuICAgICAgICAgICAgICAgIGlmICghZG9tTm9kZSkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gcm9vdE5vZGU7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgdmFyIG5ld05vZGU7XG5cbiAgICAgICAgICAgICAgICBpZiAoaXNBcnJheShwYXRjaExpc3QpKSB7XG4gICAgICAgICAgICAgICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgcGF0Y2hMaXN0Lmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBuZXdOb2RlID0gcGF0Y2hPcChwYXRjaExpc3RbaV0sIGRvbU5vZGUsIHJlbmRlck9wdGlvbnMpO1xuXG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoZG9tTm9kZSA9PT0gcm9vdE5vZGUpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICByb290Tm9kZSA9IG5ld05vZGU7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICBuZXdOb2RlID0gcGF0Y2hPcChwYXRjaExpc3QsIGRvbU5vZGUsIHJlbmRlck9wdGlvbnMpO1xuXG4gICAgICAgICAgICAgICAgICAgIGlmIChkb21Ob2RlID09PSByb290Tm9kZSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgcm9vdE5vZGUgPSBuZXdOb2RlO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgcmV0dXJuIHJvb3ROb2RlO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBmdW5jdGlvbiBwYXRjaEluZGljZXMocGF0Y2hlcykge1xuICAgICAgICAgICAgICAgIHZhciBpbmRpY2VzID0gW107XG5cbiAgICAgICAgICAgICAgICBmb3IgKHZhciBrZXkgaW4gcGF0Y2hlcykge1xuICAgICAgICAgICAgICAgICAgICBpZiAoa2V5ICE9PSBcImFcIikge1xuICAgICAgICAgICAgICAgICAgICAgICAgaW5kaWNlcy5wdXNoKE51bWJlcihrZXkpKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHJldHVybiBpbmRpY2VzO1xuICAgICAgICAgICAgfVxuICAgICAgICB9LCB7IFwiLi9jcmVhdGUtZWxlbWVudFwiOiAxNSwgXCIuL2RvbS1pbmRleFwiOiAxNiwgXCIuL3BhdGNoLW9wXCI6IDE3LCBcImdsb2JhbC9kb2N1bWVudFwiOiAxMCwgXCJ4LWlzLWFycmF5XCI6IDEyIH1dLCAxOTogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHtcbiAgICAgICAgICAgIHZhciBpc1dpZGdldCA9IHJlcXVpcmUoXCIuLi92bm9kZS9pcy13aWRnZXQuanNcIik7XG5cbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gdXBkYXRlV2lkZ2V0O1xuXG4gICAgICAgICAgICBmdW5jdGlvbiB1cGRhdGVXaWRnZXQoYSwgYikge1xuICAgICAgICAgICAgICAgIGlmIChpc1dpZGdldChhKSAmJiBpc1dpZGdldChiKSkge1xuICAgICAgICAgICAgICAgICAgICBpZiAoXCJuYW1lXCIgaW4gYSAmJiBcIm5hbWVcIiBpbiBiKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gYS5pZCA9PT0gYi5pZDtcbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBhLmluaXQgPT09IGIuaW5pdDtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSwgeyBcIi4uL3Zub2RlL2lzLXdpZGdldC5qc1wiOiAyOSB9XSwgMjA6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICBcInVzZSBzdHJpY3RcIjtcblxuICAgICAgICAgICAgdmFyIEV2U3RvcmUgPSByZXF1aXJlKFwiZXYtc3RvcmVcIik7XG5cbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gRXZIb29rO1xuXG4gICAgICAgICAgICBmdW5jdGlvbiBFdkhvb2sodmFsdWUpIHtcbiAgICAgICAgICAgICAgICBpZiAoISh0aGlzIGluc3RhbmNlb2YgRXZIb29rKSkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gbmV3IEV2SG9vayh2YWx1ZSk7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgdGhpcy52YWx1ZSA9IHZhbHVlO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBFdkhvb2sucHJvdG90eXBlLmhvb2sgPSBmdW5jdGlvbiAobm9kZSwgcHJvcGVydHlOYW1lKSB7XG4gICAgICAgICAgICAgICAgdmFyIGVzID0gRXZTdG9yZShub2RlKTtcbiAgICAgICAgICAgICAgICB2YXIgcHJvcE5hbWUgPSBwcm9wZXJ0eU5hbWUuc3Vic3RyKDMpO1xuXG4gICAgICAgICAgICAgICAgZXNbcHJvcE5hbWVdID0gdGhpcy52YWx1ZTtcbiAgICAgICAgICAgIH07XG5cbiAgICAgICAgICAgIEV2SG9vay5wcm90b3R5cGUudW5ob29rID0gZnVuY3Rpb24gKG5vZGUsIHByb3BlcnR5TmFtZSkge1xuICAgICAgICAgICAgICAgIHZhciBlcyA9IEV2U3RvcmUobm9kZSk7XG4gICAgICAgICAgICAgICAgdmFyIHByb3BOYW1lID0gcHJvcGVydHlOYW1lLnN1YnN0cigzKTtcblxuICAgICAgICAgICAgICAgIGVzW3Byb3BOYW1lXSA9IHVuZGVmaW5lZDtcbiAgICAgICAgICAgIH07XG4gICAgICAgIH0sIHsgXCJldi1zdG9yZVwiOiA3IH1dLCAyMTogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHtcbiAgICAgICAgICAgIFwidXNlIHN0cmljdFwiO1xuXG4gICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IFNvZnRTZXRIb29rO1xuXG4gICAgICAgICAgICBmdW5jdGlvbiBTb2Z0U2V0SG9vayh2YWx1ZSkge1xuICAgICAgICAgICAgICAgIGlmICghKHRoaXMgaW5zdGFuY2VvZiBTb2Z0U2V0SG9vaykpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIG5ldyBTb2Z0U2V0SG9vayh2YWx1ZSk7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgdGhpcy52YWx1ZSA9IHZhbHVlO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBTb2Z0U2V0SG9vay5wcm90b3R5cGUuaG9vayA9IGZ1bmN0aW9uIChub2RlLCBwcm9wZXJ0eU5hbWUpIHtcbiAgICAgICAgICAgICAgICBpZiAobm9kZVtwcm9wZXJ0eU5hbWVdICE9PSB0aGlzLnZhbHVlKSB7XG4gICAgICAgICAgICAgICAgICAgIG5vZGVbcHJvcGVydHlOYW1lXSA9IHRoaXMudmFsdWU7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfTtcbiAgICAgICAgfSwge31dLCAyMjogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHtcbiAgICAgICAgICAgIFwidXNlIHN0cmljdFwiO1xuXG4gICAgICAgICAgICB2YXIgaXNBcnJheSA9IHJlcXVpcmUoXCJ4LWlzLWFycmF5XCIpO1xuXG4gICAgICAgICAgICB2YXIgVk5vZGUgPSByZXF1aXJlKFwiLi4vdm5vZGUvdm5vZGUuanNcIik7XG4gICAgICAgICAgICB2YXIgVlRleHQgPSByZXF1aXJlKFwiLi4vdm5vZGUvdnRleHQuanNcIik7XG4gICAgICAgICAgICB2YXIgaXNWTm9kZSA9IHJlcXVpcmUoXCIuLi92bm9kZS9pcy12bm9kZVwiKTtcbiAgICAgICAgICAgIHZhciBpc1ZUZXh0ID0gcmVxdWlyZShcIi4uL3Zub2RlL2lzLXZ0ZXh0XCIpO1xuICAgICAgICAgICAgdmFyIGlzV2lkZ2V0ID0gcmVxdWlyZShcIi4uL3Zub2RlL2lzLXdpZGdldFwiKTtcbiAgICAgICAgICAgIHZhciBpc0hvb2sgPSByZXF1aXJlKFwiLi4vdm5vZGUvaXMtdmhvb2tcIik7XG4gICAgICAgICAgICB2YXIgaXNWVGh1bmsgPSByZXF1aXJlKFwiLi4vdm5vZGUvaXMtdGh1bmtcIik7XG5cbiAgICAgICAgICAgIHZhciBwYXJzZVRhZyA9IHJlcXVpcmUoXCIuL3BhcnNlLXRhZy5qc1wiKTtcbiAgICAgICAgICAgIHZhciBzb2Z0U2V0SG9vayA9IHJlcXVpcmUoXCIuL2hvb2tzL3NvZnQtc2V0LWhvb2suanNcIik7XG4gICAgICAgICAgICB2YXIgZXZIb29rID0gcmVxdWlyZShcIi4vaG9va3MvZXYtaG9vay5qc1wiKTtcblxuICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBoO1xuXG4gICAgICAgICAgICBmdW5jdGlvbiBoKHRhZ05hbWUsIHByb3BlcnRpZXMsIGNoaWxkcmVuKSB7XG4gICAgICAgICAgICAgICAgdmFyIGNoaWxkTm9kZXMgPSBbXTtcbiAgICAgICAgICAgICAgICB2YXIgdGFnLCBwcm9wcywga2V5LCBuYW1lc3BhY2U7XG5cbiAgICAgICAgICAgICAgICBpZiAoIWNoaWxkcmVuICYmIGlzQ2hpbGRyZW4ocHJvcGVydGllcykpIHtcbiAgICAgICAgICAgICAgICAgICAgY2hpbGRyZW4gPSBwcm9wZXJ0aWVzO1xuICAgICAgICAgICAgICAgICAgICBwcm9wcyA9IHt9O1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHByb3BzID0gcHJvcHMgfHwgcHJvcGVydGllcyB8fCB7fTtcbiAgICAgICAgICAgICAgICB0YWcgPSBwYXJzZVRhZyh0YWdOYW1lLCBwcm9wcyk7XG5cbiAgICAgICAgICAgICAgICAvLyBzdXBwb3J0IGtleXNcbiAgICAgICAgICAgICAgICBpZiAocHJvcHMuaGFzT3duUHJvcGVydHkoXCJrZXlcIikpIHtcbiAgICAgICAgICAgICAgICAgICAga2V5ID0gcHJvcHMua2V5O1xuICAgICAgICAgICAgICAgICAgICBwcm9wcy5rZXkgPSB1bmRlZmluZWQ7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgLy8gc3VwcG9ydCBuYW1lc3BhY2VcbiAgICAgICAgICAgICAgICBpZiAocHJvcHMuaGFzT3duUHJvcGVydHkoXCJuYW1lc3BhY2VcIikpIHtcbiAgICAgICAgICAgICAgICAgICAgbmFtZXNwYWNlID0gcHJvcHMubmFtZXNwYWNlO1xuICAgICAgICAgICAgICAgICAgICBwcm9wcy5uYW1lc3BhY2UgPSB1bmRlZmluZWQ7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgLy8gZml4IGN1cnNvciBidWdcbiAgICAgICAgICAgICAgICBpZiAodGFnID09PSBcIklOUFVUXCIgJiYgIW5hbWVzcGFjZSAmJiBwcm9wcy5oYXNPd25Qcm9wZXJ0eShcInZhbHVlXCIpICYmIHByb3BzLnZhbHVlICE9PSB1bmRlZmluZWQgJiYgIWlzSG9vayhwcm9wcy52YWx1ZSkpIHtcbiAgICAgICAgICAgICAgICAgICAgcHJvcHMudmFsdWUgPSBzb2Z0U2V0SG9vayhwcm9wcy52YWx1ZSk7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgdHJhbnNmb3JtUHJvcGVydGllcyhwcm9wcyk7XG5cbiAgICAgICAgICAgICAgICBpZiAoY2hpbGRyZW4gIT09IHVuZGVmaW5lZCAmJiBjaGlsZHJlbiAhPT0gbnVsbCkge1xuICAgICAgICAgICAgICAgICAgICBhZGRDaGlsZChjaGlsZHJlbiwgY2hpbGROb2RlcywgdGFnLCBwcm9wcyk7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgcmV0dXJuIG5ldyBWTm9kZSh0YWcsIHByb3BzLCBjaGlsZE5vZGVzLCBrZXksIG5hbWVzcGFjZSk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIGFkZENoaWxkKGMsIGNoaWxkTm9kZXMsIHRhZywgcHJvcHMpIHtcbiAgICAgICAgICAgICAgICBpZiAodHlwZW9mIGMgPT09IFwic3RyaW5nXCIpIHtcbiAgICAgICAgICAgICAgICAgICAgY2hpbGROb2Rlcy5wdXNoKG5ldyBWVGV4dChjKSk7XG4gICAgICAgICAgICAgICAgfSBlbHNlIGlmICh0eXBlb2YgYyA9PT0gXCJudW1iZXJcIikge1xuICAgICAgICAgICAgICAgICAgICBjaGlsZE5vZGVzLnB1c2gobmV3IFZUZXh0KFN0cmluZyhjKSkpO1xuICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoaXNDaGlsZChjKSkge1xuICAgICAgICAgICAgICAgICAgICBjaGlsZE5vZGVzLnB1c2goYyk7XG4gICAgICAgICAgICAgICAgfSBlbHNlIGlmIChpc0FycmF5KGMpKSB7XG4gICAgICAgICAgICAgICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgYy5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgICAgICAgICAgICAgYWRkQ2hpbGQoY1tpXSwgY2hpbGROb2RlcywgdGFnLCBwcm9wcyk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKGMgPT09IG51bGwgfHwgYyA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICB0aHJvdyBVbmV4cGVjdGVkVmlydHVhbEVsZW1lbnQoe1xuICAgICAgICAgICAgICAgICAgICAgICAgZm9yZWlnbk9iamVjdDogYyxcbiAgICAgICAgICAgICAgICAgICAgICAgIHBhcmVudFZub2RlOiB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdGFnTmFtZTogdGFnLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHByb3BlcnRpZXM6IHByb3BzXG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZnVuY3Rpb24gdHJhbnNmb3JtUHJvcGVydGllcyhwcm9wcykge1xuICAgICAgICAgICAgICAgIGZvciAodmFyIHByb3BOYW1lIGluIHByb3BzKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmIChwcm9wcy5oYXNPd25Qcm9wZXJ0eShwcm9wTmFtZSkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHZhciB2YWx1ZSA9IHByb3BzW3Byb3BOYW1lXTtcblxuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGlzSG9vayh2YWx1ZSkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb250aW51ZTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHByb3BOYW1lLnN1YnN0cigwLCAzKSA9PT0gXCJldi1cIikge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIGFkZCBldi1mb28gc3VwcG9ydFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHByb3BzW3Byb3BOYW1lXSA9IGV2SG9vayh2YWx1ZSk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIGlzQ2hpbGQoeCkge1xuICAgICAgICAgICAgICAgIHJldHVybiBpc1ZOb2RlKHgpIHx8IGlzVlRleHQoeCkgfHwgaXNXaWRnZXQoeCkgfHwgaXNWVGh1bmsoeCk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIGlzQ2hpbGRyZW4oeCkge1xuICAgICAgICAgICAgICAgIHJldHVybiB0eXBlb2YgeCA9PT0gXCJzdHJpbmdcIiB8fCBpc0FycmF5KHgpIHx8IGlzQ2hpbGQoeCk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIFVuZXhwZWN0ZWRWaXJ0dWFsRWxlbWVudChkYXRhKSB7XG4gICAgICAgICAgICAgICAgdmFyIGVyciA9IG5ldyBFcnJvcigpO1xuXG4gICAgICAgICAgICAgICAgZXJyLnR5cGUgPSBcInZpcnR1YWwtaHlwZXJzY3JpcHQudW5leHBlY3RlZC52aXJ0dWFsLWVsZW1lbnRcIjtcbiAgICAgICAgICAgICAgICBlcnIubWVzc2FnZSA9IFwiVW5leHBlY3RlZCB2aXJ0dWFsIGNoaWxkIHBhc3NlZCB0byBoKCkuXFxuXCIgKyBcIkV4cGVjdGVkIGEgVk5vZGUgLyBWdGh1bmsgLyBWV2lkZ2V0IC8gc3RyaW5nIGJ1dDpcXG5cIiArIFwiZ290OlxcblwiICsgZXJyb3JTdHJpbmcoZGF0YS5mb3JlaWduT2JqZWN0KSArIFwiLlxcblwiICsgXCJUaGUgcGFyZW50IHZub2RlIGlzOlxcblwiICsgZXJyb3JTdHJpbmcoZGF0YS5wYXJlbnRWbm9kZSk7XG4gICAgICAgICAgICAgICAgXCJcXG5cIiArIFwiU3VnZ2VzdGVkIGZpeDogY2hhbmdlIHlvdXIgYGgoLi4uLCBbIC4uLiBdKWAgY2FsbHNpdGUuXCI7XG4gICAgICAgICAgICAgICAgZXJyLmZvcmVpZ25PYmplY3QgPSBkYXRhLmZvcmVpZ25PYmplY3Q7XG4gICAgICAgICAgICAgICAgZXJyLnBhcmVudFZub2RlID0gZGF0YS5wYXJlbnRWbm9kZTtcblxuICAgICAgICAgICAgICAgIHJldHVybiBlcnI7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIGVycm9yU3RyaW5nKG9iaikge1xuICAgICAgICAgICAgICAgIHRyeSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBKU09OLnN0cmluZ2lmeShvYmosIG51bGwsIFwiICAgIFwiKTtcbiAgICAgICAgICAgICAgICB9IGNhdGNoIChlKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBTdHJpbmcob2JqKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH0sIHsgXCIuLi92bm9kZS9pcy10aHVua1wiOiAyNSwgXCIuLi92bm9kZS9pcy12aG9va1wiOiAyNiwgXCIuLi92bm9kZS9pcy12bm9kZVwiOiAyNywgXCIuLi92bm9kZS9pcy12dGV4dFwiOiAyOCwgXCIuLi92bm9kZS9pcy13aWRnZXRcIjogMjksIFwiLi4vdm5vZGUvdm5vZGUuanNcIjogMzEsIFwiLi4vdm5vZGUvdnRleHQuanNcIjogMzMsIFwiLi9ob29rcy9ldi1ob29rLmpzXCI6IDIwLCBcIi4vaG9va3Mvc29mdC1zZXQtaG9vay5qc1wiOiAyMSwgXCIuL3BhcnNlLXRhZy5qc1wiOiAyMywgXCJ4LWlzLWFycmF5XCI6IDEyIH1dLCAyMzogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHtcbiAgICAgICAgICAgIFwidXNlIHN0cmljdFwiO1xuXG4gICAgICAgICAgICB2YXIgc3BsaXQgPSByZXF1aXJlKFwiYnJvd3Nlci1zcGxpdFwiKTtcblxuICAgICAgICAgICAgdmFyIGNsYXNzSWRTcGxpdCA9IC8oW1xcLiNdP1thLXpBLVowLTlcXHUwMDdGLVxcdUZGRkZfOi1dKykvO1xuICAgICAgICAgICAgdmFyIG5vdENsYXNzSWQgPSAvXlxcLnwjLztcblxuICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBwYXJzZVRhZztcblxuICAgICAgICAgICAgZnVuY3Rpb24gcGFyc2VUYWcodGFnLCBwcm9wcykge1xuICAgICAgICAgICAgICAgIGlmICghdGFnKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBcIkRJVlwiO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHZhciBub0lkID0gIXByb3BzLmhhc093blByb3BlcnR5KFwiaWRcIik7XG5cbiAgICAgICAgICAgICAgICB2YXIgdGFnUGFydHMgPSBzcGxpdCh0YWcsIGNsYXNzSWRTcGxpdCk7XG4gICAgICAgICAgICAgICAgdmFyIHRhZ05hbWUgPSBudWxsO1xuXG4gICAgICAgICAgICAgICAgaWYgKG5vdENsYXNzSWQudGVzdCh0YWdQYXJ0c1sxXSkpIHtcbiAgICAgICAgICAgICAgICAgICAgdGFnTmFtZSA9IFwiRElWXCI7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgdmFyIGNsYXNzZXMsIHBhcnQsIHR5cGUsIGk7XG5cbiAgICAgICAgICAgICAgICBmb3IgKGkgPSAwOyBpIDwgdGFnUGFydHMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgICAgICAgICAgcGFydCA9IHRhZ1BhcnRzW2ldO1xuXG4gICAgICAgICAgICAgICAgICAgIGlmICghcGFydCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgY29udGludWU7XG4gICAgICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgICAgICB0eXBlID0gcGFydC5jaGFyQXQoMCk7XG5cbiAgICAgICAgICAgICAgICAgICAgaWYgKCF0YWdOYW1lKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICB0YWdOYW1lID0gcGFydDtcbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIGlmICh0eXBlID09PSBcIi5cIikge1xuICAgICAgICAgICAgICAgICAgICAgICAgY2xhc3NlcyA9IGNsYXNzZXMgfHwgW107XG4gICAgICAgICAgICAgICAgICAgICAgICBjbGFzc2VzLnB1c2gocGFydC5zdWJzdHJpbmcoMSwgcGFydC5sZW5ndGgpKTtcbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIGlmICh0eXBlID09PSBcIiNcIiAmJiBub0lkKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBwcm9wcy5pZCA9IHBhcnQuc3Vic3RyaW5nKDEsIHBhcnQubGVuZ3RoKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIGlmIChjbGFzc2VzKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmIChwcm9wcy5jbGFzc05hbWUpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGNsYXNzZXMucHVzaChwcm9wcy5jbGFzc05hbWUpO1xuICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgcHJvcHMuY2xhc3NOYW1lID0gY2xhc3Nlcy5qb2luKFwiIFwiKTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICByZXR1cm4gcHJvcHMubmFtZXNwYWNlID8gdGFnTmFtZSA6IHRhZ05hbWUudG9VcHBlckNhc2UoKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSwgeyBcImJyb3dzZXItc3BsaXRcIjogNSB9XSwgMjQ6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICB2YXIgaXNWTm9kZSA9IHJlcXVpcmUoXCIuL2lzLXZub2RlXCIpO1xuICAgICAgICAgICAgdmFyIGlzVlRleHQgPSByZXF1aXJlKFwiLi9pcy12dGV4dFwiKTtcbiAgICAgICAgICAgIHZhciBpc1dpZGdldCA9IHJlcXVpcmUoXCIuL2lzLXdpZGdldFwiKTtcbiAgICAgICAgICAgIHZhciBpc1RodW5rID0gcmVxdWlyZShcIi4vaXMtdGh1bmtcIik7XG5cbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gaGFuZGxlVGh1bms7XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIGhhbmRsZVRodW5rKGEsIGIpIHtcbiAgICAgICAgICAgICAgICB2YXIgcmVuZGVyZWRBID0gYTtcbiAgICAgICAgICAgICAgICB2YXIgcmVuZGVyZWRCID0gYjtcblxuICAgICAgICAgICAgICAgIGlmIChpc1RodW5rKGIpKSB7XG4gICAgICAgICAgICAgICAgICAgIHJlbmRlcmVkQiA9IHJlbmRlclRodW5rKGIsIGEpO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIGlmIChpc1RodW5rKGEpKSB7XG4gICAgICAgICAgICAgICAgICAgIHJlbmRlcmVkQSA9IHJlbmRlclRodW5rKGEsIG51bGwpO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHJldHVybiB7XG4gICAgICAgICAgICAgICAgICAgIGE6IHJlbmRlcmVkQSxcbiAgICAgICAgICAgICAgICAgICAgYjogcmVuZGVyZWRCXG4gICAgICAgICAgICAgICAgfTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZnVuY3Rpb24gcmVuZGVyVGh1bmsodGh1bmssIHByZXZpb3VzKSB7XG4gICAgICAgICAgICAgICAgdmFyIHJlbmRlcmVkVGh1bmsgPSB0aHVuay52bm9kZTtcblxuICAgICAgICAgICAgICAgIGlmICghcmVuZGVyZWRUaHVuaykge1xuICAgICAgICAgICAgICAgICAgICByZW5kZXJlZFRodW5rID0gdGh1bmsudm5vZGUgPSB0aHVuay5yZW5kZXIocHJldmlvdXMpO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIGlmICghKGlzVk5vZGUocmVuZGVyZWRUaHVuaykgfHwgaXNWVGV4dChyZW5kZXJlZFRodW5rKSB8fCBpc1dpZGdldChyZW5kZXJlZFRodW5rKSkpIHtcbiAgICAgICAgICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKFwidGh1bmsgZGlkIG5vdCByZXR1cm4gYSB2YWxpZCBub2RlXCIpO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHJldHVybiByZW5kZXJlZFRodW5rO1xuICAgICAgICAgICAgfVxuICAgICAgICB9LCB7IFwiLi9pcy10aHVua1wiOiAyNSwgXCIuL2lzLXZub2RlXCI6IDI3LCBcIi4vaXMtdnRleHRcIjogMjgsIFwiLi9pcy13aWRnZXRcIjogMjkgfV0sIDI1OiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge1xuICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBpc1RodW5rO1xuXG4gICAgICAgICAgICBmdW5jdGlvbiBpc1RodW5rKHQpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gdCAmJiB0LnR5cGUgPT09IFwiVGh1bmtcIjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSwge31dLCAyNjogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHtcbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gaXNIb29rO1xuXG4gICAgICAgICAgICBmdW5jdGlvbiBpc0hvb2soaG9vaykge1xuICAgICAgICAgICAgICAgIHJldHVybiBob29rICYmICh0eXBlb2YgaG9vay5ob29rID09PSBcImZ1bmN0aW9uXCIgJiYgIWhvb2suaGFzT3duUHJvcGVydHkoXCJob29rXCIpIHx8IHR5cGVvZiBob29rLnVuaG9vayA9PT0gXCJmdW5jdGlvblwiICYmICFob29rLmhhc093blByb3BlcnR5KFwidW5ob29rXCIpKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSwge31dLCAyNzogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHtcbiAgICAgICAgICAgIHZhciB2ZXJzaW9uID0gcmVxdWlyZShcIi4vdmVyc2lvblwiKTtcblxuICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBpc1ZpcnR1YWxOb2RlO1xuXG4gICAgICAgICAgICBmdW5jdGlvbiBpc1ZpcnR1YWxOb2RlKHgpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4geCAmJiB4LnR5cGUgPT09IFwiVmlydHVhbE5vZGVcIiAmJiB4LnZlcnNpb24gPT09IHZlcnNpb247XG4gICAgICAgICAgICB9XG4gICAgICAgIH0sIHsgXCIuL3ZlcnNpb25cIjogMzAgfV0sIDI4OiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge1xuICAgICAgICAgICAgdmFyIHZlcnNpb24gPSByZXF1aXJlKFwiLi92ZXJzaW9uXCIpO1xuXG4gICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IGlzVmlydHVhbFRleHQ7XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIGlzVmlydHVhbFRleHQoeCkge1xuICAgICAgICAgICAgICAgIHJldHVybiB4ICYmIHgudHlwZSA9PT0gXCJWaXJ0dWFsVGV4dFwiICYmIHgudmVyc2lvbiA9PT0gdmVyc2lvbjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSwgeyBcIi4vdmVyc2lvblwiOiAzMCB9XSwgMjk6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IGlzV2lkZ2V0O1xuXG4gICAgICAgICAgICBmdW5jdGlvbiBpc1dpZGdldCh3KSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHcgJiYgdy50eXBlID09PSBcIldpZGdldFwiO1xuICAgICAgICAgICAgfVxuICAgICAgICB9LCB7fV0sIDMwOiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge1xuICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBcIjJcIjtcbiAgICAgICAgfSwge31dLCAzMTogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHtcbiAgICAgICAgICAgIHZhciB2ZXJzaW9uID0gcmVxdWlyZShcIi4vdmVyc2lvblwiKTtcbiAgICAgICAgICAgIHZhciBpc1ZOb2RlID0gcmVxdWlyZShcIi4vaXMtdm5vZGVcIik7XG4gICAgICAgICAgICB2YXIgaXNXaWRnZXQgPSByZXF1aXJlKFwiLi9pcy13aWRnZXRcIik7XG4gICAgICAgICAgICB2YXIgaXNUaHVuayA9IHJlcXVpcmUoXCIuL2lzLXRodW5rXCIpO1xuICAgICAgICAgICAgdmFyIGlzVkhvb2sgPSByZXF1aXJlKFwiLi9pcy12aG9va1wiKTtcblxuICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBWaXJ0dWFsTm9kZTtcblxuICAgICAgICAgICAgdmFyIG5vUHJvcGVydGllcyA9IHt9O1xuICAgICAgICAgICAgdmFyIG5vQ2hpbGRyZW4gPSBbXTtcblxuICAgICAgICAgICAgZnVuY3Rpb24gVmlydHVhbE5vZGUodGFnTmFtZSwgcHJvcGVydGllcywgY2hpbGRyZW4sIGtleSwgbmFtZXNwYWNlKSB7XG4gICAgICAgICAgICAgICAgdGhpcy50YWdOYW1lID0gdGFnTmFtZTtcbiAgICAgICAgICAgICAgICB0aGlzLnByb3BlcnRpZXMgPSBwcm9wZXJ0aWVzIHx8IG5vUHJvcGVydGllcztcbiAgICAgICAgICAgICAgICB0aGlzLmNoaWxkcmVuID0gY2hpbGRyZW4gfHwgbm9DaGlsZHJlbjtcbiAgICAgICAgICAgICAgICB0aGlzLmtleSA9IGtleSAhPSBudWxsID8gU3RyaW5nKGtleSkgOiB1bmRlZmluZWQ7XG4gICAgICAgICAgICAgICAgdGhpcy5uYW1lc3BhY2UgPSB0eXBlb2YgbmFtZXNwYWNlID09PSBcInN0cmluZ1wiID8gbmFtZXNwYWNlIDogbnVsbDtcblxuICAgICAgICAgICAgICAgIHZhciBjb3VudCA9IGNoaWxkcmVuICYmIGNoaWxkcmVuLmxlbmd0aCB8fCAwO1xuICAgICAgICAgICAgICAgIHZhciBkZXNjZW5kYW50cyA9IDA7XG4gICAgICAgICAgICAgICAgdmFyIGhhc1dpZGdldHMgPSBmYWxzZTtcbiAgICAgICAgICAgICAgICB2YXIgaGFzVGh1bmtzID0gZmFsc2U7XG4gICAgICAgICAgICAgICAgdmFyIGRlc2NlbmRhbnRIb29rcyA9IGZhbHNlO1xuICAgICAgICAgICAgICAgIHZhciBob29rcztcblxuICAgICAgICAgICAgICAgIGZvciAodmFyIHByb3BOYW1lIGluIHByb3BlcnRpZXMpIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKHByb3BlcnRpZXMuaGFzT3duUHJvcGVydHkocHJvcE5hbWUpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICB2YXIgcHJvcGVydHkgPSBwcm9wZXJ0aWVzW3Byb3BOYW1lXTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChpc1ZIb29rKHByb3BlcnR5KSAmJiBwcm9wZXJ0eS51bmhvb2spIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoIWhvb2tzKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGhvb2tzID0ge307XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaG9va3NbcHJvcE5hbWVdID0gcHJvcGVydHk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IGNvdW50OyBpKyspIHtcbiAgICAgICAgICAgICAgICAgICAgdmFyIGNoaWxkID0gY2hpbGRyZW5baV07XG4gICAgICAgICAgICAgICAgICAgIGlmIChpc1ZOb2RlKGNoaWxkKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgZGVzY2VuZGFudHMgKz0gY2hpbGQuY291bnQgfHwgMDtcblxuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKCFoYXNXaWRnZXRzICYmIGNoaWxkLmhhc1dpZGdldHMpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBoYXNXaWRnZXRzID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKCFoYXNUaHVua3MgJiYgY2hpbGQuaGFzVGh1bmtzKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaGFzVGh1bmtzID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKCFkZXNjZW5kYW50SG9va3MgJiYgKGNoaWxkLmhvb2tzIHx8IGNoaWxkLmRlc2NlbmRhbnRIb29rcykpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBkZXNjZW5kYW50SG9va3MgPSB0cnVlO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKCFoYXNXaWRnZXRzICYmIGlzV2lkZ2V0KGNoaWxkKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHR5cGVvZiBjaGlsZC5kZXN0cm95ID09PSBcImZ1bmN0aW9uXCIpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBoYXNXaWRnZXRzID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIGlmICghaGFzVGh1bmtzICYmIGlzVGh1bmsoY2hpbGQpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBoYXNUaHVua3MgPSB0cnVlO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgdGhpcy5jb3VudCA9IGNvdW50ICsgZGVzY2VuZGFudHM7XG4gICAgICAgICAgICAgICAgdGhpcy5oYXNXaWRnZXRzID0gaGFzV2lkZ2V0cztcbiAgICAgICAgICAgICAgICB0aGlzLmhhc1RodW5rcyA9IGhhc1RodW5rcztcbiAgICAgICAgICAgICAgICB0aGlzLmhvb2tzID0gaG9va3M7XG4gICAgICAgICAgICAgICAgdGhpcy5kZXNjZW5kYW50SG9va3MgPSBkZXNjZW5kYW50SG9va3M7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIFZpcnR1YWxOb2RlLnByb3RvdHlwZS52ZXJzaW9uID0gdmVyc2lvbjtcbiAgICAgICAgICAgIFZpcnR1YWxOb2RlLnByb3RvdHlwZS50eXBlID0gXCJWaXJ0dWFsTm9kZVwiO1xuICAgICAgICB9LCB7IFwiLi9pcy10aHVua1wiOiAyNSwgXCIuL2lzLXZob29rXCI6IDI2LCBcIi4vaXMtdm5vZGVcIjogMjcsIFwiLi9pcy13aWRnZXRcIjogMjksIFwiLi92ZXJzaW9uXCI6IDMwIH1dLCAzMjogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHtcbiAgICAgICAgICAgIHZhciB2ZXJzaW9uID0gcmVxdWlyZShcIi4vdmVyc2lvblwiKTtcblxuICAgICAgICAgICAgVmlydHVhbFBhdGNoLk5PTkUgPSAwO1xuICAgICAgICAgICAgVmlydHVhbFBhdGNoLlZURVhUID0gMTtcbiAgICAgICAgICAgIFZpcnR1YWxQYXRjaC5WTk9ERSA9IDI7XG4gICAgICAgICAgICBWaXJ0dWFsUGF0Y2guV0lER0VUID0gMztcbiAgICAgICAgICAgIFZpcnR1YWxQYXRjaC5QUk9QUyA9IDQ7XG4gICAgICAgICAgICBWaXJ0dWFsUGF0Y2guT1JERVIgPSA1O1xuICAgICAgICAgICAgVmlydHVhbFBhdGNoLklOU0VSVCA9IDY7XG4gICAgICAgICAgICBWaXJ0dWFsUGF0Y2guUkVNT1ZFID0gNztcbiAgICAgICAgICAgIFZpcnR1YWxQYXRjaC5USFVOSyA9IDg7XG5cbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gVmlydHVhbFBhdGNoO1xuXG4gICAgICAgICAgICBmdW5jdGlvbiBWaXJ0dWFsUGF0Y2godHlwZSwgdk5vZGUsIHBhdGNoKSB7XG4gICAgICAgICAgICAgICAgdGhpcy50eXBlID0gTnVtYmVyKHR5cGUpO1xuICAgICAgICAgICAgICAgIHRoaXMudk5vZGUgPSB2Tm9kZTtcbiAgICAgICAgICAgICAgICB0aGlzLnBhdGNoID0gcGF0Y2g7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIFZpcnR1YWxQYXRjaC5wcm90b3R5cGUudmVyc2lvbiA9IHZlcnNpb247XG4gICAgICAgICAgICBWaXJ0dWFsUGF0Y2gucHJvdG90eXBlLnR5cGUgPSBcIlZpcnR1YWxQYXRjaFwiO1xuICAgICAgICB9LCB7IFwiLi92ZXJzaW9uXCI6IDMwIH1dLCAzMzogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHtcbiAgICAgICAgICAgIHZhciB2ZXJzaW9uID0gcmVxdWlyZShcIi4vdmVyc2lvblwiKTtcblxuICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBWaXJ0dWFsVGV4dDtcblxuICAgICAgICAgICAgZnVuY3Rpb24gVmlydHVhbFRleHQodGV4dCkge1xuICAgICAgICAgICAgICAgIHRoaXMudGV4dCA9IFN0cmluZyh0ZXh0KTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgVmlydHVhbFRleHQucHJvdG90eXBlLnZlcnNpb24gPSB2ZXJzaW9uO1xuICAgICAgICAgICAgVmlydHVhbFRleHQucHJvdG90eXBlLnR5cGUgPSBcIlZpcnR1YWxUZXh0XCI7XG4gICAgICAgIH0sIHsgXCIuL3ZlcnNpb25cIjogMzAgfV0sIDM0OiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge1xuICAgICAgICAgICAgdmFyIGlzT2JqZWN0ID0gcmVxdWlyZShcImlzLW9iamVjdFwiKTtcbiAgICAgICAgICAgIHZhciBpc0hvb2sgPSByZXF1aXJlKFwiLi4vdm5vZGUvaXMtdmhvb2tcIik7XG5cbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gZGlmZlByb3BzO1xuXG4gICAgICAgICAgICBmdW5jdGlvbiBkaWZmUHJvcHMoYSwgYikge1xuICAgICAgICAgICAgICAgIHZhciBkaWZmO1xuXG4gICAgICAgICAgICAgICAgZm9yICh2YXIgYUtleSBpbiBhKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmICghKGFLZXkgaW4gYikpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGRpZmYgPSBkaWZmIHx8IHt9O1xuICAgICAgICAgICAgICAgICAgICAgICAgZGlmZlthS2V5XSA9IHVuZGVmaW5lZDtcbiAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgIHZhciBhVmFsdWUgPSBhW2FLZXldO1xuICAgICAgICAgICAgICAgICAgICB2YXIgYlZhbHVlID0gYlthS2V5XTtcblxuICAgICAgICAgICAgICAgICAgICBpZiAoYVZhbHVlID09PSBiVmFsdWUpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnRpbnVlO1xuICAgICAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKGlzT2JqZWN0KGFWYWx1ZSkgJiYgaXNPYmplY3QoYlZhbHVlKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGdldFByb3RvdHlwZShiVmFsdWUpICE9PSBnZXRQcm90b3R5cGUoYVZhbHVlKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRpZmYgPSBkaWZmIHx8IHt9O1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRpZmZbYUtleV0gPSBiVmFsdWU7XG4gICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKGlzSG9vayhiVmFsdWUpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgZGlmZiA9IGRpZmYgfHwge307XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgZGlmZlthS2V5XSA9IGJWYWx1ZTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdmFyIG9iamVjdERpZmYgPSBkaWZmUHJvcHMoYVZhbHVlLCBiVmFsdWUpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChvYmplY3REaWZmKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRpZmYgPSBkaWZmIHx8IHt9O1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBkaWZmW2FLZXldID0gb2JqZWN0RGlmZjtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBkaWZmID0gZGlmZiB8fCB7fTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGRpZmZbYUtleV0gPSBiVmFsdWU7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICBmb3IgKHZhciBiS2V5IGluIGIpIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKCEoYktleSBpbiBhKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgZGlmZiA9IGRpZmYgfHwge307XG4gICAgICAgICAgICAgICAgICAgICAgICBkaWZmW2JLZXldID0gYltiS2V5XTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHJldHVybiBkaWZmO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBmdW5jdGlvbiBnZXRQcm90b3R5cGUodmFsdWUpIHtcbiAgICAgICAgICAgICAgICBpZiAoT2JqZWN0LmdldFByb3RvdHlwZU9mKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBPYmplY3QuZ2V0UHJvdG90eXBlT2YodmFsdWUpO1xuICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAodmFsdWUuX19wcm90b19fKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiB2YWx1ZS5fX3Byb3RvX187XG4gICAgICAgICAgICAgICAgfSBlbHNlIGlmICh2YWx1ZS5jb25zdHJ1Y3Rvcikge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gdmFsdWUuY29uc3RydWN0b3IucHJvdG90eXBlO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgfSwgeyBcIi4uL3Zub2RlL2lzLXZob29rXCI6IDI2LCBcImlzLW9iamVjdFwiOiAxMSB9XSwgMzU6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICB2YXIgaXNBcnJheSA9IHJlcXVpcmUoXCJ4LWlzLWFycmF5XCIpO1xuXG4gICAgICAgICAgICB2YXIgVlBhdGNoID0gcmVxdWlyZShcIi4uL3Zub2RlL3ZwYXRjaFwiKTtcbiAgICAgICAgICAgIHZhciBpc1ZOb2RlID0gcmVxdWlyZShcIi4uL3Zub2RlL2lzLXZub2RlXCIpO1xuICAgICAgICAgICAgdmFyIGlzVlRleHQgPSByZXF1aXJlKFwiLi4vdm5vZGUvaXMtdnRleHRcIik7XG4gICAgICAgICAgICB2YXIgaXNXaWRnZXQgPSByZXF1aXJlKFwiLi4vdm5vZGUvaXMtd2lkZ2V0XCIpO1xuICAgICAgICAgICAgdmFyIGlzVGh1bmsgPSByZXF1aXJlKFwiLi4vdm5vZGUvaXMtdGh1bmtcIik7XG4gICAgICAgICAgICB2YXIgaGFuZGxlVGh1bmsgPSByZXF1aXJlKFwiLi4vdm5vZGUvaGFuZGxlLXRodW5rXCIpO1xuXG4gICAgICAgICAgICB2YXIgZGlmZlByb3BzID0gcmVxdWlyZShcIi4vZGlmZi1wcm9wc1wiKTtcblxuICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBkaWZmO1xuXG4gICAgICAgICAgICBmdW5jdGlvbiBkaWZmKGEsIGIpIHtcbiAgICAgICAgICAgICAgICB2YXIgcGF0Y2ggPSB7IGE6IGEgfTtcbiAgICAgICAgICAgICAgICB3YWxrKGEsIGIsIHBhdGNoLCAwKTtcbiAgICAgICAgICAgICAgICByZXR1cm4gcGF0Y2g7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIHdhbGsoYSwgYiwgcGF0Y2gsIGluZGV4KSB7XG4gICAgICAgICAgICAgICAgaWYgKGEgPT09IGIpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHZhciBhcHBseSA9IHBhdGNoW2luZGV4XTtcbiAgICAgICAgICAgICAgICB2YXIgYXBwbHlDbGVhciA9IGZhbHNlO1xuXG4gICAgICAgICAgICAgICAgaWYgKGlzVGh1bmsoYSkgfHwgaXNUaHVuayhiKSkge1xuICAgICAgICAgICAgICAgICAgICB0aHVua3MoYSwgYiwgcGF0Y2gsIGluZGV4KTtcbiAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKGIgPT0gbnVsbCkge1xuXG4gICAgICAgICAgICAgICAgICAgIC8vIElmIGEgaXMgYSB3aWRnZXQgd2Ugd2lsbCBhZGQgYSByZW1vdmUgcGF0Y2ggZm9yIGl0XG4gICAgICAgICAgICAgICAgICAgIC8vIE90aGVyd2lzZSBhbnkgY2hpbGQgd2lkZ2V0cy9ob29rcyBtdXN0IGJlIGRlc3Ryb3llZC5cbiAgICAgICAgICAgICAgICAgICAgLy8gVGhpcyBwcmV2ZW50cyBhZGRpbmcgdHdvIHJlbW92ZSBwYXRjaGVzIGZvciBhIHdpZGdldC5cbiAgICAgICAgICAgICAgICAgICAgaWYgKCFpc1dpZGdldChhKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgY2xlYXJTdGF0ZShhLCBwYXRjaCwgaW5kZXgpO1xuICAgICAgICAgICAgICAgICAgICAgICAgYXBwbHkgPSBwYXRjaFtpbmRleF07XG4gICAgICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgICAgICBhcHBseSA9IGFwcGVuZFBhdGNoKGFwcGx5LCBuZXcgVlBhdGNoKFZQYXRjaC5SRU1PVkUsIGEsIGIpKTtcbiAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKGlzVk5vZGUoYikpIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKGlzVk5vZGUoYSkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChhLnRhZ05hbWUgPT09IGIudGFnTmFtZSAmJiBhLm5hbWVzcGFjZSA9PT0gYi5uYW1lc3BhY2UgJiYgYS5rZXkgPT09IGIua2V5KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdmFyIHByb3BzUGF0Y2ggPSBkaWZmUHJvcHMoYS5wcm9wZXJ0aWVzLCBiLnByb3BlcnRpZXMpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChwcm9wc1BhdGNoKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGFwcGx5ID0gYXBwZW5kUGF0Y2goYXBwbHksIG5ldyBWUGF0Y2goVlBhdGNoLlBST1BTLCBhLCBwcm9wc1BhdGNoKSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGFwcGx5ID0gZGlmZkNoaWxkcmVuKGEsIGIsIHBhdGNoLCBhcHBseSwgaW5kZXgpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBhcHBseSA9IGFwcGVuZFBhdGNoKGFwcGx5LCBuZXcgVlBhdGNoKFZQYXRjaC5WTk9ERSwgYSwgYikpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGFwcGx5Q2xlYXIgPSB0cnVlO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgYXBwbHkgPSBhcHBlbmRQYXRjaChhcHBseSwgbmV3IFZQYXRjaChWUGF0Y2guVk5PREUsIGEsIGIpKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGFwcGx5Q2xlYXIgPSB0cnVlO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfSBlbHNlIGlmIChpc1ZUZXh0KGIpKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmICghaXNWVGV4dChhKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgYXBwbHkgPSBhcHBlbmRQYXRjaChhcHBseSwgbmV3IFZQYXRjaChWUGF0Y2guVlRFWFQsIGEsIGIpKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGFwcGx5Q2xlYXIgPSB0cnVlO1xuICAgICAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKGEudGV4dCAhPT0gYi50ZXh0KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBhcHBseSA9IGFwcGVuZFBhdGNoKGFwcGx5LCBuZXcgVlBhdGNoKFZQYXRjaC5WVEVYVCwgYSwgYikpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfSBlbHNlIGlmIChpc1dpZGdldChiKSkge1xuICAgICAgICAgICAgICAgICAgICBpZiAoIWlzV2lkZ2V0KGEpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBhcHBseUNsZWFyID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgIGFwcGx5ID0gYXBwZW5kUGF0Y2goYXBwbHksIG5ldyBWUGF0Y2goVlBhdGNoLldJREdFVCwgYSwgYikpO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIGlmIChhcHBseSkge1xuICAgICAgICAgICAgICAgICAgICBwYXRjaFtpbmRleF0gPSBhcHBseTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICBpZiAoYXBwbHlDbGVhcikge1xuICAgICAgICAgICAgICAgICAgICBjbGVhclN0YXRlKGEsIHBhdGNoLCBpbmRleCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBmdW5jdGlvbiBkaWZmQ2hpbGRyZW4oYSwgYiwgcGF0Y2gsIGFwcGx5LCBpbmRleCkge1xuICAgICAgICAgICAgICAgIHZhciBhQ2hpbGRyZW4gPSBhLmNoaWxkcmVuO1xuICAgICAgICAgICAgICAgIHZhciBvcmRlcmVkU2V0ID0gcmVvcmRlcihhQ2hpbGRyZW4sIGIuY2hpbGRyZW4pO1xuICAgICAgICAgICAgICAgIHZhciBiQ2hpbGRyZW4gPSBvcmRlcmVkU2V0LmNoaWxkcmVuO1xuXG4gICAgICAgICAgICAgICAgdmFyIGFMZW4gPSBhQ2hpbGRyZW4ubGVuZ3RoO1xuICAgICAgICAgICAgICAgIHZhciBiTGVuID0gYkNoaWxkcmVuLmxlbmd0aDtcbiAgICAgICAgICAgICAgICB2YXIgbGVuID0gYUxlbiA+IGJMZW4gPyBhTGVuIDogYkxlbjtcblxuICAgICAgICAgICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgbGVuOyBpKyspIHtcbiAgICAgICAgICAgICAgICAgICAgdmFyIGxlZnROb2RlID0gYUNoaWxkcmVuW2ldO1xuICAgICAgICAgICAgICAgICAgICB2YXIgcmlnaHROb2RlID0gYkNoaWxkcmVuW2ldO1xuICAgICAgICAgICAgICAgICAgICBpbmRleCArPSAxO1xuXG4gICAgICAgICAgICAgICAgICAgIGlmICghbGVmdE5vZGUpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChyaWdodE5vZGUpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBFeGNlc3Mgbm9kZXMgaW4gYiBuZWVkIHRvIGJlIGFkZGVkXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgYXBwbHkgPSBhcHBlbmRQYXRjaChhcHBseSwgbmV3IFZQYXRjaChWUGF0Y2guSU5TRVJULCBudWxsLCByaWdodE5vZGUpKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHdhbGsobGVmdE5vZGUsIHJpZ2h0Tm9kZSwgcGF0Y2gsIGluZGV4KTtcbiAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgIGlmIChpc1ZOb2RlKGxlZnROb2RlKSAmJiBsZWZ0Tm9kZS5jb3VudCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgaW5kZXggKz0gbGVmdE5vZGUuY291bnQ7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICBpZiAob3JkZXJlZFNldC5tb3Zlcykge1xuICAgICAgICAgICAgICAgICAgICAvLyBSZW9yZGVyIG5vZGVzIGxhc3RcbiAgICAgICAgICAgICAgICAgICAgYXBwbHkgPSBhcHBlbmRQYXRjaChhcHBseSwgbmV3IFZQYXRjaChWUGF0Y2guT1JERVIsIGEsIG9yZGVyZWRTZXQubW92ZXMpKTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICByZXR1cm4gYXBwbHk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIGNsZWFyU3RhdGUodk5vZGUsIHBhdGNoLCBpbmRleCkge1xuICAgICAgICAgICAgICAgIC8vIFRPRE86IE1ha2UgdGhpcyBhIHNpbmdsZSB3YWxrLCBub3QgdHdvXG4gICAgICAgICAgICAgICAgdW5ob29rKHZOb2RlLCBwYXRjaCwgaW5kZXgpO1xuICAgICAgICAgICAgICAgIGRlc3Ryb3lXaWRnZXRzKHZOb2RlLCBwYXRjaCwgaW5kZXgpO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAvLyBQYXRjaCByZWNvcmRzIGZvciBhbGwgZGVzdHJveWVkIHdpZGdldHMgbXVzdCBiZSBhZGRlZCBiZWNhdXNlIHdlIG5lZWRcbiAgICAgICAgICAgIC8vIGEgRE9NIG5vZGUgcmVmZXJlbmNlIGZvciB0aGUgZGVzdHJveSBmdW5jdGlvblxuICAgICAgICAgICAgZnVuY3Rpb24gZGVzdHJveVdpZGdldHModk5vZGUsIHBhdGNoLCBpbmRleCkge1xuICAgICAgICAgICAgICAgIGlmIChpc1dpZGdldCh2Tm9kZSkpIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKHR5cGVvZiB2Tm9kZS5kZXN0cm95ID09PSBcImZ1bmN0aW9uXCIpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHBhdGNoW2luZGV4XSA9IGFwcGVuZFBhdGNoKHBhdGNoW2luZGV4XSwgbmV3IFZQYXRjaChWUGF0Y2guUkVNT1ZFLCB2Tm9kZSwgbnVsbCkpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfSBlbHNlIGlmIChpc1ZOb2RlKHZOb2RlKSAmJiAodk5vZGUuaGFzV2lkZ2V0cyB8fCB2Tm9kZS5oYXNUaHVua3MpKSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciBjaGlsZHJlbiA9IHZOb2RlLmNoaWxkcmVuO1xuICAgICAgICAgICAgICAgICAgICB2YXIgbGVuID0gY2hpbGRyZW4ubGVuZ3RoO1xuICAgICAgICAgICAgICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IGxlbjsgaSsrKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICB2YXIgY2hpbGQgPSBjaGlsZHJlbltpXTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGluZGV4ICs9IDE7XG5cbiAgICAgICAgICAgICAgICAgICAgICAgIGRlc3Ryb3lXaWRnZXRzKGNoaWxkLCBwYXRjaCwgaW5kZXgpO1xuXG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoaXNWTm9kZShjaGlsZCkgJiYgY2hpbGQuY291bnQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpbmRleCArPSBjaGlsZC5jb3VudDtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoaXNUaHVuayh2Tm9kZSkpIHtcbiAgICAgICAgICAgICAgICAgICAgdGh1bmtzKHZOb2RlLCBudWxsLCBwYXRjaCwgaW5kZXgpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgLy8gQ3JlYXRlIGEgc3ViLXBhdGNoIGZvciB0aHVua3NcbiAgICAgICAgICAgIGZ1bmN0aW9uIHRodW5rcyhhLCBiLCBwYXRjaCwgaW5kZXgpIHtcbiAgICAgICAgICAgICAgICB2YXIgbm9kZXMgPSBoYW5kbGVUaHVuayhhLCBiKTtcbiAgICAgICAgICAgICAgICB2YXIgdGh1bmtQYXRjaCA9IGRpZmYobm9kZXMuYSwgbm9kZXMuYik7XG4gICAgICAgICAgICAgICAgaWYgKGhhc1BhdGNoZXModGh1bmtQYXRjaCkpIHtcbiAgICAgICAgICAgICAgICAgICAgcGF0Y2hbaW5kZXhdID0gbmV3IFZQYXRjaChWUGF0Y2guVEhVTkssIG51bGwsIHRodW5rUGF0Y2gpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZnVuY3Rpb24gaGFzUGF0Y2hlcyhwYXRjaCkge1xuICAgICAgICAgICAgICAgIGZvciAodmFyIGluZGV4IGluIHBhdGNoKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmIChpbmRleCAhPT0gXCJhXCIpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAvLyBFeGVjdXRlIGhvb2tzIHdoZW4gdHdvIG5vZGVzIGFyZSBpZGVudGljYWxcbiAgICAgICAgICAgIGZ1bmN0aW9uIHVuaG9vayh2Tm9kZSwgcGF0Y2gsIGluZGV4KSB7XG4gICAgICAgICAgICAgICAgaWYgKGlzVk5vZGUodk5vZGUpKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmICh2Tm9kZS5ob29rcykge1xuICAgICAgICAgICAgICAgICAgICAgICAgcGF0Y2hbaW5kZXhdID0gYXBwZW5kUGF0Y2gocGF0Y2hbaW5kZXhdLCBuZXcgVlBhdGNoKFZQYXRjaC5QUk9QUywgdk5vZGUsIHVuZGVmaW5lZEtleXModk5vZGUuaG9va3MpKSk7XG4gICAgICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgICAgICBpZiAodk5vZGUuZGVzY2VuZGFudEhvb2tzIHx8IHZOb2RlLmhhc1RodW5rcykge1xuICAgICAgICAgICAgICAgICAgICAgICAgdmFyIGNoaWxkcmVuID0gdk5vZGUuY2hpbGRyZW47XG4gICAgICAgICAgICAgICAgICAgICAgICB2YXIgbGVuID0gY2hpbGRyZW4ubGVuZ3RoO1xuICAgICAgICAgICAgICAgICAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCBsZW47IGkrKykge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZhciBjaGlsZCA9IGNoaWxkcmVuW2ldO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGluZGV4ICs9IDE7XG5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB1bmhvb2soY2hpbGQsIHBhdGNoLCBpbmRleCk7XG5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoaXNWTm9kZShjaGlsZCkgJiYgY2hpbGQuY291bnQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaW5kZXggKz0gY2hpbGQuY291bnQ7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfSBlbHNlIGlmIChpc1RodW5rKHZOb2RlKSkge1xuICAgICAgICAgICAgICAgICAgICB0aHVua3Modk5vZGUsIG51bGwsIHBhdGNoLCBpbmRleCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBmdW5jdGlvbiB1bmRlZmluZWRLZXlzKG9iaikge1xuICAgICAgICAgICAgICAgIHZhciByZXN1bHQgPSB7fTtcblxuICAgICAgICAgICAgICAgIGZvciAodmFyIGtleSBpbiBvYmopIHtcbiAgICAgICAgICAgICAgICAgICAgcmVzdWx0W2tleV0gPSB1bmRlZmluZWQ7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgcmV0dXJuIHJlc3VsdDtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgLy8gTGlzdCBkaWZmLCBuYWl2ZSBsZWZ0IHRvIHJpZ2h0IHJlb3JkZXJpbmdcbiAgICAgICAgICAgIGZ1bmN0aW9uIHJlb3JkZXIoYUNoaWxkcmVuLCBiQ2hpbGRyZW4pIHtcbiAgICAgICAgICAgICAgICAvLyBPKE0pIHRpbWUsIE8oTSkgbWVtb3J5XG4gICAgICAgICAgICAgICAgdmFyIGJDaGlsZEluZGV4ID0ga2V5SW5kZXgoYkNoaWxkcmVuKTtcbiAgICAgICAgICAgICAgICB2YXIgYktleXMgPSBiQ2hpbGRJbmRleC5rZXlzO1xuICAgICAgICAgICAgICAgIHZhciBiRnJlZSA9IGJDaGlsZEluZGV4LmZyZWU7XG5cbiAgICAgICAgICAgICAgICBpZiAoYkZyZWUubGVuZ3RoID09PSBiQ2hpbGRyZW4ubGVuZ3RoKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiB7XG4gICAgICAgICAgICAgICAgICAgICAgICBjaGlsZHJlbjogYkNoaWxkcmVuLFxuICAgICAgICAgICAgICAgICAgICAgICAgbW92ZXM6IG51bGxcbiAgICAgICAgICAgICAgICAgICAgfTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAvLyBPKE4pIHRpbWUsIE8oTikgbWVtb3J5XG4gICAgICAgICAgICAgICAgdmFyIGFDaGlsZEluZGV4ID0ga2V5SW5kZXgoYUNoaWxkcmVuKTtcbiAgICAgICAgICAgICAgICB2YXIgYUtleXMgPSBhQ2hpbGRJbmRleC5rZXlzO1xuICAgICAgICAgICAgICAgIHZhciBhRnJlZSA9IGFDaGlsZEluZGV4LmZyZWU7XG5cbiAgICAgICAgICAgICAgICBpZiAoYUZyZWUubGVuZ3RoID09PSBhQ2hpbGRyZW4ubGVuZ3RoKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiB7XG4gICAgICAgICAgICAgICAgICAgICAgICBjaGlsZHJlbjogYkNoaWxkcmVuLFxuICAgICAgICAgICAgICAgICAgICAgICAgbW92ZXM6IG51bGxcbiAgICAgICAgICAgICAgICAgICAgfTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAvLyBPKE1BWChOLCBNKSkgbWVtb3J5XG4gICAgICAgICAgICAgICAgdmFyIG5ld0NoaWxkcmVuID0gW107XG5cbiAgICAgICAgICAgICAgICB2YXIgZnJlZUluZGV4ID0gMDtcbiAgICAgICAgICAgICAgICB2YXIgZnJlZUNvdW50ID0gYkZyZWUubGVuZ3RoO1xuICAgICAgICAgICAgICAgIHZhciBkZWxldGVkSXRlbXMgPSAwO1xuXG4gICAgICAgICAgICAgICAgLy8gSXRlcmF0ZSB0aHJvdWdoIGEgYW5kIG1hdGNoIGEgbm9kZSBpbiBiXG4gICAgICAgICAgICAgICAgLy8gTyhOKSB0aW1lLFxuICAgICAgICAgICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgYUNoaWxkcmVuLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciBhSXRlbSA9IGFDaGlsZHJlbltpXTtcbiAgICAgICAgICAgICAgICAgICAgdmFyIGl0ZW1JbmRleDtcblxuICAgICAgICAgICAgICAgICAgICBpZiAoYUl0ZW0ua2V5KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoYktleXMuaGFzT3duUHJvcGVydHkoYUl0ZW0ua2V5KSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIE1hdGNoIHVwIHRoZSBvbGQga2V5c1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGl0ZW1JbmRleCA9IGJLZXlzW2FJdGVtLmtleV07XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgbmV3Q2hpbGRyZW4ucHVzaChiQ2hpbGRyZW5baXRlbUluZGV4XSk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIFJlbW92ZSBvbGQga2V5ZWQgaXRlbXNcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpdGVtSW5kZXggPSBpIC0gZGVsZXRlZEl0ZW1zKys7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgbmV3Q2hpbGRyZW4ucHVzaChudWxsKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIE1hdGNoIHRoZSBpdGVtIGluIGEgd2l0aCB0aGUgbmV4dCBmcmVlIGl0ZW0gaW4gYlxuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGZyZWVJbmRleCA8IGZyZWVDb3VudCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGl0ZW1JbmRleCA9IGJGcmVlW2ZyZWVJbmRleCsrXTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBuZXdDaGlsZHJlbi5wdXNoKGJDaGlsZHJlbltpdGVtSW5kZXhdKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gVGhlcmUgYXJlIG5vIGZyZWUgaXRlbXMgaW4gYiB0byBtYXRjaCB3aXRoXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gdGhlIGZyZWUgaXRlbXMgaW4gYSwgc28gdGhlIGV4dHJhIGZyZWUgbm9kZXNcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBhcmUgZGVsZXRlZC5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpdGVtSW5kZXggPSBpIC0gZGVsZXRlZEl0ZW1zKys7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgbmV3Q2hpbGRyZW4ucHVzaChudWxsKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHZhciBsYXN0RnJlZUluZGV4ID0gZnJlZUluZGV4ID49IGJGcmVlLmxlbmd0aCA/IGJDaGlsZHJlbi5sZW5ndGggOiBiRnJlZVtmcmVlSW5kZXhdO1xuXG4gICAgICAgICAgICAgICAgLy8gSXRlcmF0ZSB0aHJvdWdoIGIgYW5kIGFwcGVuZCBhbnkgbmV3IGtleXNcbiAgICAgICAgICAgICAgICAvLyBPKE0pIHRpbWVcbiAgICAgICAgICAgICAgICBmb3IgKHZhciBqID0gMDsgaiA8IGJDaGlsZHJlbi5sZW5ndGg7IGorKykge1xuICAgICAgICAgICAgICAgICAgICB2YXIgbmV3SXRlbSA9IGJDaGlsZHJlbltqXTtcblxuICAgICAgICAgICAgICAgICAgICBpZiAobmV3SXRlbS5rZXkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmICghYUtleXMuaGFzT3duUHJvcGVydHkobmV3SXRlbS5rZXkpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gQWRkIGFueSBuZXcga2V5ZWQgaXRlbXNcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBXZSBhcmUgYWRkaW5nIG5ldyBpdGVtcyB0byB0aGUgZW5kIGFuZCB0aGVuIHNvcnRpbmcgdGhlbVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIGluIHBsYWNlLiBJbiBmdXR1cmUgd2Ugc2hvdWxkIGluc2VydCBuZXcgaXRlbXMgaW4gcGxhY2UuXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgbmV3Q2hpbGRyZW4ucHVzaChuZXdJdGVtKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIGlmIChqID49IGxhc3RGcmVlSW5kZXgpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIEFkZCBhbnkgbGVmdG92ZXIgbm9uLWtleWVkIGl0ZW1zXG4gICAgICAgICAgICAgICAgICAgICAgICBuZXdDaGlsZHJlbi5wdXNoKG5ld0l0ZW0pO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgdmFyIHNpbXVsYXRlID0gbmV3Q2hpbGRyZW4uc2xpY2UoKTtcbiAgICAgICAgICAgICAgICB2YXIgc2ltdWxhdGVJbmRleCA9IDA7XG4gICAgICAgICAgICAgICAgdmFyIHJlbW92ZXMgPSBbXTtcbiAgICAgICAgICAgICAgICB2YXIgaW5zZXJ0cyA9IFtdO1xuICAgICAgICAgICAgICAgIHZhciBzaW11bGF0ZUl0ZW07XG5cbiAgICAgICAgICAgICAgICBmb3IgKHZhciBrID0gMDsgayA8IGJDaGlsZHJlbi5sZW5ndGg7KSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciB3YW50ZWRJdGVtID0gYkNoaWxkcmVuW2tdO1xuICAgICAgICAgICAgICAgICAgICBzaW11bGF0ZUl0ZW0gPSBzaW11bGF0ZVtzaW11bGF0ZUluZGV4XTtcblxuICAgICAgICAgICAgICAgICAgICAvLyByZW1vdmUgaXRlbXNcbiAgICAgICAgICAgICAgICAgICAgd2hpbGUgKHNpbXVsYXRlSXRlbSA9PT0gbnVsbCAmJiBzaW11bGF0ZS5sZW5ndGgpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJlbW92ZXMucHVzaChyZW1vdmUoc2ltdWxhdGUsIHNpbXVsYXRlSW5kZXgsIG51bGwpKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIHNpbXVsYXRlSXRlbSA9IHNpbXVsYXRlW3NpbXVsYXRlSW5kZXhdO1xuICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgaWYgKCFzaW11bGF0ZUl0ZW0gfHwgc2ltdWxhdGVJdGVtLmtleSAhPT0gd2FudGVkSXRlbS5rZXkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIGlmIHdlIG5lZWQgYSBrZXkgaW4gdGhpcyBwb3NpdGlvbi4uLlxuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHdhbnRlZEl0ZW0ua2V5KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHNpbXVsYXRlSXRlbSAmJiBzaW11bGF0ZUl0ZW0ua2V5KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIGlmIGFuIGluc2VydCBkb2Vzbid0IHB1dCB0aGlzIGtleSBpbiBwbGFjZSwgaXQgbmVlZHMgdG8gbW92ZVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoYktleXNbc2ltdWxhdGVJdGVtLmtleV0gIT09IGsgKyAxKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICByZW1vdmVzLnB1c2gocmVtb3ZlKHNpbXVsYXRlLCBzaW11bGF0ZUluZGV4LCBzaW11bGF0ZUl0ZW0ua2V5KSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzaW11bGF0ZUl0ZW0gPSBzaW11bGF0ZVtzaW11bGF0ZUluZGV4XTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIGlmIHRoZSByZW1vdmUgZGlkbid0IHB1dCB0aGUgd2FudGVkIGl0ZW0gaW4gcGxhY2UsIHdlIG5lZWQgdG8gaW5zZXJ0IGl0XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoIXNpbXVsYXRlSXRlbSB8fCBzaW11bGF0ZUl0ZW0ua2V5ICE9PSB3YW50ZWRJdGVtLmtleSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGluc2VydHMucHVzaCh7IGtleTogd2FudGVkSXRlbS5rZXksIHRvOiBrIH0pO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gaXRlbXMgYXJlIG1hdGNoaW5nLCBzbyBza2lwIGFoZWFkXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzaW11bGF0ZUluZGV4Kys7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpbnNlcnRzLnB1c2goeyBrZXk6IHdhbnRlZEl0ZW0ua2V5LCB0bzogayB9KTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGluc2VydHMucHVzaCh7IGtleTogd2FudGVkSXRlbS5rZXksIHRvOiBrIH0pO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBrKys7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAvLyBhIGtleSBpbiBzaW11bGF0ZSBoYXMgbm8gbWF0Y2hpbmcgd2FudGVkIGtleSwgcmVtb3ZlIGl0XG4gICAgICAgICAgICAgICAgICAgICAgICBlbHNlIGlmIChzaW11bGF0ZUl0ZW0gJiYgc2ltdWxhdGVJdGVtLmtleSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlbW92ZXMucHVzaChyZW1vdmUoc2ltdWxhdGUsIHNpbXVsYXRlSW5kZXgsIHNpbXVsYXRlSXRlbS5rZXkpKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHNpbXVsYXRlSW5kZXgrKztcbiAgICAgICAgICAgICAgICAgICAgICAgIGsrKztcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIC8vIHJlbW92ZSBhbGwgdGhlIHJlbWFpbmluZyBub2RlcyBmcm9tIHNpbXVsYXRlXG4gICAgICAgICAgICAgICAgd2hpbGUgKHNpbXVsYXRlSW5kZXggPCBzaW11bGF0ZS5sZW5ndGgpIHtcbiAgICAgICAgICAgICAgICAgICAgc2ltdWxhdGVJdGVtID0gc2ltdWxhdGVbc2ltdWxhdGVJbmRleF07XG4gICAgICAgICAgICAgICAgICAgIHJlbW92ZXMucHVzaChyZW1vdmUoc2ltdWxhdGUsIHNpbXVsYXRlSW5kZXgsIHNpbXVsYXRlSXRlbSAmJiBzaW11bGF0ZUl0ZW0ua2V5KSk7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgLy8gSWYgdGhlIG9ubHkgbW92ZXMgd2UgaGF2ZSBhcmUgZGVsZXRlcyB0aGVuIHdlIGNhbiBqdXN0XG4gICAgICAgICAgICAgICAgLy8gbGV0IHRoZSBkZWxldGUgcGF0Y2ggcmVtb3ZlIHRoZXNlIGl0ZW1zLlxuICAgICAgICAgICAgICAgIGlmIChyZW1vdmVzLmxlbmd0aCA9PT0gZGVsZXRlZEl0ZW1zICYmICFpbnNlcnRzLmxlbmd0aCkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgICAgICAgICAgICAgY2hpbGRyZW46IG5ld0NoaWxkcmVuLFxuICAgICAgICAgICAgICAgICAgICAgICAgbW92ZXM6IG51bGxcbiAgICAgICAgICAgICAgICAgICAgfTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgICAgICAgICBjaGlsZHJlbjogbmV3Q2hpbGRyZW4sXG4gICAgICAgICAgICAgICAgICAgIG1vdmVzOiB7XG4gICAgICAgICAgICAgICAgICAgICAgICByZW1vdmVzOiByZW1vdmVzLFxuICAgICAgICAgICAgICAgICAgICAgICAgaW5zZXJ0czogaW5zZXJ0c1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZnVuY3Rpb24gcmVtb3ZlKGFyciwgaW5kZXgsIGtleSkge1xuICAgICAgICAgICAgICAgIGFyci5zcGxpY2UoaW5kZXgsIDEpO1xuXG4gICAgICAgICAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgICAgICAgICAgZnJvbTogaW5kZXgsXG4gICAgICAgICAgICAgICAgICAgIGtleToga2V5XG4gICAgICAgICAgICAgICAgfTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZnVuY3Rpb24ga2V5SW5kZXgoY2hpbGRyZW4pIHtcbiAgICAgICAgICAgICAgICB2YXIga2V5cyA9IHt9O1xuICAgICAgICAgICAgICAgIHZhciBmcmVlID0gW107XG4gICAgICAgICAgICAgICAgdmFyIGxlbmd0aCA9IGNoaWxkcmVuLmxlbmd0aDtcblxuICAgICAgICAgICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgbGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgICAgICAgICAgdmFyIGNoaWxkID0gY2hpbGRyZW5baV07XG5cbiAgICAgICAgICAgICAgICAgICAgaWYgKGNoaWxkLmtleSkge1xuICAgICAgICAgICAgICAgICAgICAgICAga2V5c1tjaGlsZC5rZXldID0gaTtcbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGZyZWUucHVzaChpKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHJldHVybiB7XG4gICAgICAgICAgICAgICAgICAgIGtleXM6IGtleXMsIC8vIEEgaGFzaCBvZiBrZXkgbmFtZSB0byBpbmRleFxuICAgICAgICAgICAgICAgICAgICBmcmVlOiBmcmVlIC8vIEFuIGFycmF5IG9mIHVua2V5ZWQgaXRlbSBpbmRpY2VzXG4gICAgICAgICAgICAgICAgfTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZnVuY3Rpb24gYXBwZW5kUGF0Y2goYXBwbHksIHBhdGNoKSB7XG4gICAgICAgICAgICAgICAgaWYgKGFwcGx5KSB7XG4gICAgICAgICAgICAgICAgICAgIGlmIChpc0FycmF5KGFwcGx5KSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgYXBwbHkucHVzaChwYXRjaCk7XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBhcHBseSA9IFthcHBseSwgcGF0Y2hdO1xuICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGFwcGx5O1xuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBwYXRjaDtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH0sIHsgXCIuLi92bm9kZS9oYW5kbGUtdGh1bmtcIjogMjQsIFwiLi4vdm5vZGUvaXMtdGh1bmtcIjogMjUsIFwiLi4vdm5vZGUvaXMtdm5vZGVcIjogMjcsIFwiLi4vdm5vZGUvaXMtdnRleHRcIjogMjgsIFwiLi4vdm5vZGUvaXMtd2lkZ2V0XCI6IDI5LCBcIi4uL3Zub2RlL3ZwYXRjaFwiOiAzMiwgXCIuL2RpZmYtcHJvcHNcIjogMzQsIFwieC1pcy1hcnJheVwiOiAxMiB9XSB9LCB7fSwgWzRdKSg0KTtcbn0pO1xuXG5jb25zdCBzdGFydCA9IGZ1bmN0aW9uIChkb21Sb290LCByZW5kZXJGbiwgaW5pdGlhbFN0YXRlLCBvcHRpb25zID0gW10pIHtcbiAgbGV0IHBpZCA9IHNlbGYucHJvY2Vzc2VzLnNwYXduKCk7XG5cbiAgaWYgKEtleXdvcmQuaGFzX2tleV9fcW1fXyhvcHRpb25zLCBLZXJuZWwuU3BlY2lhbEZvcm1zLmF0b20oJ25hbWUnKSkpIHtcbiAgICBwaWQgPSBzZWxmLnByb2Nlc3Nlcy5yZWdpc3RlcihLZXl3b3JkLmdldChvcHRpb25zLCBLZXJuZWwuU3BlY2lhbEZvcm1zLmF0b20oJ25hbWUnKSksIHBpZCk7XG4gIH1cblxuICBjb25zdCB0cmVlID0gcmVuZGVyRm4uYXBwbHkodGhpcywgaW5pdGlhbFN0YXRlKTtcbiAgY29uc3Qgcm9vdE5vZGUgPSBWaXJ0dWFsRE9NLmNyZWF0ZSh0cmVlKTtcblxuICBkb21Sb290LmFwcGVuZENoaWxkKHJvb3ROb2RlKTtcblxuICBzZWxmLnByb2Nlc3Nlcy5wdXQocGlkLCAnc3RhdGUnLCBLZXJuZWwuU3BlY2lhbEZvcm1zLnR1cGxlKHJvb3ROb2RlLCB0cmVlLCByZW5kZXJGbikpO1xuICByZXR1cm4gS2VybmVsLlNwZWNpYWxGb3Jtcy50dXBsZShLZXJuZWwuU3BlY2lhbEZvcm1zLmF0b20oJ29rJyksIHBpZCk7XG59O1xuXG5jb25zdCBzdG9wID0gZnVuY3Rpb24gKGFnZW50LCB0aW1lb3V0ID0gNTAwMCkge1xuICBzZWxmLnByb2Nlc3Nlcy5leGl0KGFnZW50KTtcbiAgcmV0dXJuIEtlcm5lbC5TcGVjaWFsRm9ybXMuYXRvbSgnb2snKTtcbn07XG5cbmNvbnN0IHJlbmRlciA9IGZ1bmN0aW9uIChhZ2VudCwgc3RhdGUpIHtcblxuICBjb25zdCBjdXJyZW50X3N0YXRlID0gc2VsZi5wcm9jZXNzZXMuZ2V0KGFnZW50LCAnc3RhdGUnKTtcblxuICBsZXQgcm9vdE5vZGUgPSBLZXJuZWwuZWxlbShjdXJyZW50X3N0YXRlLCAwKTtcbiAgbGV0IHRyZWUgPSBLZXJuZWwuZWxlbShjdXJyZW50X3N0YXRlLCAxKTtcbiAgbGV0IHJlbmRlckZuID0gS2VybmVsLmVsZW0oY3VycmVudF9zdGF0ZSwgMik7XG5cbiAgbGV0IG5ld1RyZWUgPSByZW5kZXJGbi5hcHBseSh0aGlzLCBzdGF0ZSk7XG5cbiAgbGV0IHBhdGNoZXMgPSBWaXJ0dWFsRE9NLmRpZmYodHJlZSwgbmV3VHJlZSk7XG4gIHJvb3ROb2RlID0gVmlydHVhbERPTS5wYXRjaChyb290Tm9kZSwgcGF0Y2hlcyk7XG5cbiAgc2VsZi5wcm9jZXNzZXMucHV0KGFnZW50LCAnc3RhdGUnLCBLZXJuZWwuU3BlY2lhbEZvcm1zLnR1cGxlKHJvb3ROb2RlLCBuZXdUcmVlLCByZW5kZXJGbikpO1xuXG4gIHJldHVybiBLZXJuZWwuU3BlY2lhbEZvcm1zLmF0b20oJ29rJyk7XG59O1xuXG52YXIgdmlldyA9IHtcbiAgc3RhcnQsXG4gIHN0b3AsXG4gIHJlbmRlclxufTtcblxuY29uc3QgQ29yZSA9IEM7XG5cbmV4cG9ydCB7IENvcmUsIEtlcm5lbCwgQXRvbSwgRW51bSwgSW50ZWdlciwgTGlzdCwgUmFuZ2UsIFR1cGxlLCBBZ2VudCwgS2V5d29yZCwgYmFzZSBhcyBCYXNlLCBTdHJpbmckMSBhcyBTdHJpbmcsIGJpdHdpc2UgYXMgQml0d2lzZSwgRW51bWVyYWJsZSwgQ29sbGVjdGFibGUsIEluc3BlY3QsIG1hcCBhcyBNYXAsIHNldCBhcyBTZXQsIE1hcFNldCwgVmlydHVhbERPTSwgdmlldyBhcyBWaWV3IH07Il0sImZpbGUiOiJFbGl4aXIuanMiLCJzb3VyY2VSb290IjoiL3NvdXJjZS8ifQ== \ No newline at end of file +export { Core, Kernel, Enum, List, Keyword, bitwise as Bitwise, map as Map, map_set as MapSet, VirtualDOM }; +//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiIiwic291cmNlcyI6WyJFbGl4aXIuanMiXSwic291cmNlc0NvbnRlbnQiOlsiLyogQGZsb3cgKi9cblxuY2xhc3MgTWFpbGJveCB7XG5cbiAgY29uc3RydWN0b3IoKSB7XG4gICAgdGhpcy5tZXNzYWdlcyA9IFtdO1xuICB9XG5cbiAgZGVsaXZlcihtZXNzYWdlKSB7XG4gICAgdGhpcy5tZXNzYWdlcy5wdXNoKG1lc3NhZ2UpO1xuICAgIHJldHVybiBtZXNzYWdlO1xuICB9XG5cbiAgZ2V0KCkge1xuICAgIHJldHVybiB0aGlzLm1lc3NhZ2VzO1xuICB9XG5cbiAgaXNFbXB0eSgpIHtcbiAgICByZXR1cm4gdGhpcy5tZXNzYWdlcy5sZW5ndGggPT09IDA7XG4gIH1cblxuICByZW1vdmVBdChpbmRleCkge1xuICAgIHRoaXMubWVzc2FnZXMuc3BsaWNlKGluZGV4LCAxKTtcbiAgfVxufVxuXG52YXIgU3RhdGVzID0ge1xuICBOT1JNQUw6IFN5bWJvbC5mb3IoXCJub3JtYWxcIiksXG4gIEtJTEw6IFN5bWJvbC5mb3IoXCJraWxsXCIpLFxuICBTVVNQRU5EOiBTeW1ib2wuZm9yKFwic3VzcGVuZFwiKSxcbiAgQ09OVElOVUU6IFN5bWJvbC5mb3IoXCJjb250aW51ZVwiKSxcbiAgUkVDRUlWRTogU3ltYm9sLmZvcihcInJlY2VpdmVcIiksXG4gIFNFTkQ6IFN5bWJvbC5mb3IoXCJzZW5kXCIpLFxuICBTTEVFUElORzogU3ltYm9sLmZvcihcInNsZWVwaW5nXCIpLFxuICBSVU5OSU5HOiBTeW1ib2wuZm9yKFwicnVubmluZ1wiKSxcbiAgU1VTUEVOREVEOiBTeW1ib2wuZm9yKFwic3VzcGVuZGVkXCIpLFxuICBTVE9QUEVEOiBTeW1ib2wuZm9yKFwic3RvcHBlZFwiKSxcbiAgU0xFRVA6IFN5bWJvbC5mb3IoXCJzbGVlcFwiKSxcbiAgRVhJVDogU3ltYm9sLmZvcihcImV4aXRcIiksXG4gIE5PTUFUQ0g6IFN5bWJvbC5mb3IoXCJub19tYXRjaFwiKVxufTtcblxuY2xhc3MgUHJvY2VzcyB7XG5cbiAgY29uc3RydWN0b3IocGlkLCBtYWlsYm94KSB7XG4gICAgdGhpcy5waWQgPSBwaWQ7XG4gICAgdGhpcy5tYWlsYm94ID0gbWFpbGJveDtcbiAgICB0aGlzLnN0YXR1cyA9IFN0YXRlcy5TVE9QUEVEO1xuICAgIHRoaXMuZGljdCA9IHt9O1xuICB9XG59XG5cbmNsYXNzIFR1cGxlIHtcblxuICBjb25zdHJ1Y3RvciguLi5hcmdzKSB7XG4gICAgdGhpcy52YWx1ZXMgPSBPYmplY3QuZnJlZXplKGFyZ3MpO1xuICAgIHRoaXMubGVuZ3RoID0gdGhpcy52YWx1ZXMubGVuZ3RoO1xuICB9XG5cbiAgZ2V0KGluZGV4KSB7XG4gICAgcmV0dXJuIHRoaXMudmFsdWVzW2luZGV4XTtcbiAgfVxuXG4gIGNvdW50KCkge1xuICAgIHJldHVybiB0aGlzLnZhbHVlcy5sZW5ndGg7XG4gIH1cblxuICBbU3ltYm9sLml0ZXJhdG9yXSgpIHtcbiAgICByZXR1cm4gdGhpcy52YWx1ZXNbU3ltYm9sLml0ZXJhdG9yXSgpO1xuICB9XG5cbiAgdG9TdHJpbmcoKSB7XG4gICAgdmFyIGksXG4gICAgICAgIHMgPSBcIlwiO1xuICAgIGZvciAoaSA9IDA7IGkgPCB0aGlzLnZhbHVlcy5sZW5ndGg7IGkrKykge1xuICAgICAgaWYgKHMgIT09IFwiXCIpIHtcbiAgICAgICAgcyArPSBcIiwgXCI7XG4gICAgICB9XG4gICAgICBzICs9IHRoaXMudmFsdWVzW2ldLnRvU3RyaW5nKCk7XG4gICAgfVxuXG4gICAgcmV0dXJuIFwie1wiICsgcyArIFwifVwiO1xuICB9XG5cbn1cblxubGV0IHByb2Nlc3NfY291bnRlciA9IC0xO1xuXG5jbGFzcyBQSUQge1xuICBjb25zdHJ1Y3RvcigpIHtcbiAgICBwcm9jZXNzX2NvdW50ZXIgPSBwcm9jZXNzX2NvdW50ZXIgKyAxO1xuICAgIHRoaXMuaWQgPSBwcm9jZXNzX2NvdW50ZXI7XG4gIH1cblxuICB0b1N0cmluZygpIHtcbiAgICByZXR1cm4gXCJQSUQjPDAuXCIgKyB0aGlzLmlkICsgXCIuMD5cIjtcbiAgfVxufVxuXG5jbGFzcyBJbnRlZ2VyIHt9XG5jbGFzcyBGbG9hdCB7fVxuXG5mdW5jdGlvbiBMaXN0JDEoLi4uYXJncykge1xuICByZXR1cm4gT2JqZWN0LmZyZWV6ZShhcmdzKTtcbn1cblxuY2xhc3MgUHJvY2Vzc1N5c3RlbSB7XG5cbiAgY29uc3RydWN0b3IoKSB7XG4gICAgdGhpcy5waWRzID0gbmV3IE1hcCgpO1xuICAgIHRoaXMubWFpbGJveGVzID0gbmV3IE1hcCgpO1xuICAgIHRoaXMubmFtZXMgPSBuZXcgTWFwKCk7XG4gICAgdGhpcy5saW5rcyA9IG5ldyBNYXAoKTtcblxuICAgIHRoaXMuY3VycmVudF9wcm9jZXNzID0gbnVsbDtcbiAgICB0aGlzLnN1c3BlbmRlZCA9IG5ldyBNYXAoKTtcblxuICAgIHRoaXMubWFpbl9wcm9jZXNzX3BpZCA9IHRoaXMuc3Bhd24oKTtcbiAgICB0aGlzLnNldF9jdXJyZW50KHRoaXMubWFpbl9wcm9jZXNzX3BpZCk7XG4gIH1cblxuICBzcGF3bigpIHtcbiAgICByZXR1cm4gdGhpcy5hZGRfcHJvYyhmYWxzZSkucGlkO1xuICB9XG5cbiAgc3Bhd25fbGluaygpIHtcbiAgICByZXR1cm4gdGhpcy5hZGRfcHJvYyh0cnVlKS5waWQ7XG4gIH1cblxuICBsaW5rKHBpZCkge1xuICAgIHRoaXMubGlua3MuZ2V0KHRoaXMucGlkKCkpLmFkZChwaWQpO1xuICAgIHRoaXMubGlua3MuZ2V0KHBpZCkuYWRkKHRoaXMucGlkKCkpO1xuICB9XG5cbiAgdW5saW5rKHBpZCkge1xuICAgIHRoaXMubGlua3MuZ2V0KHRoaXMucGlkKCkpLmRlbGV0ZShwaWQpO1xuICAgIHRoaXMubGlua3MuZ2V0KHBpZCkuZGVsZXRlKHRoaXMucGlkKCkpO1xuICB9XG5cbiAgc2V0X2N1cnJlbnQoaWQpIHtcbiAgICBsZXQgcGlkID0gdGhpcy5waWRvZihpZCk7XG4gICAgaWYgKHBpZCAhPT0gbnVsbCkge1xuICAgICAgdGhpcy5jdXJyZW50X3Byb2Nlc3MgPSB0aGlzLnBpZHMuZ2V0KHBpZCk7XG4gICAgICB0aGlzLmN1cnJlbnRfcHJvY2Vzcy5zdGF0dXMgPSBTdGF0ZXMuUlVOTklORztcbiAgICB9XG4gIH1cblxuICBhZGRfcHJvYyhsaW5rZWQpIHtcbiAgICBsZXQgbmV3cGlkID0gbmV3IFBJRCgpO1xuICAgIGxldCBtYWlsYm94ID0gbmV3IE1haWxib3goKTtcbiAgICBsZXQgbmV3cHJvYyA9IG5ldyBQcm9jZXNzKG5ld3BpZCwgbWFpbGJveCk7XG5cbiAgICB0aGlzLnBpZHMuc2V0KG5ld3BpZCwgbmV3cHJvYyk7XG4gICAgdGhpcy5tYWlsYm94ZXMuc2V0KG5ld3BpZCwgbWFpbGJveCk7XG4gICAgdGhpcy5saW5rcy5zZXQobmV3cGlkLCBuZXcgU2V0KCkpO1xuXG4gICAgaWYgKGxpbmtlZCkge1xuICAgICAgdGhpcy5saW5rKG5ld3BpZCk7XG4gICAgfVxuXG4gICAgcmV0dXJuIG5ld3Byb2M7XG4gIH1cblxuICByZW1vdmVfcHJvYyhwaWQpIHtcbiAgICB0aGlzLnBpZHMuZGVsZXRlKHBpZCk7XG4gICAgdGhpcy51bnJlZ2lzdGVyKHBpZCk7XG5cbiAgICBpZiAodGhpcy5saW5rcy5oYXMocGlkKSkge1xuICAgICAgZm9yIChsZXQgbGlua3BpZCBvZiB0aGlzLmxpbmtzLmdldChwaWQpKSB7XG4gICAgICAgIHRoaXMubGlua3MuZ2V0KGxpbmtwaWQpLmRlbGV0ZShwaWQpO1xuICAgICAgfVxuXG4gICAgICB0aGlzLmxpbmtzLmRlbGV0ZShwaWQpO1xuICAgIH1cbiAgfVxuXG4gIGV4aXQoaWQpIHtcbiAgICBsZXQgcGlkID0gdGhpcy5waWRvZihpZCk7XG4gICAgdGhpcy5yZW1vdmVfcHJvYyhpZCk7XG4gIH1cblxuICByZWdpc3RlcihuYW1lLCBwaWQpIHtcbiAgICBpZiAoIXRoaXMubmFtZXMuaGFzKG5hbWUpKSB7XG4gICAgICB0aGlzLm5hbWVzLnNldChuYW1lLCBwaWQpO1xuICAgICAgcmV0dXJuIG5hbWU7XG4gICAgfSBlbHNlIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcihcIk5hbWUgaXMgYWxyZWFkeSByZWdpc3RlcmVkIHRvIGFub3RoZXIgcHJvY2Vzc1wiKTtcbiAgICB9XG4gIH1cblxuICByZWdpc3RlcmVkKG5hbWUpIHtcbiAgICByZXR1cm4gdGhpcy5uYW1lcy5oYXMobmFtZSkgPyB0aGlzLm5hbWVzLmdldChuYW1lKSA6IG51bGw7XG4gIH1cblxuICB1bnJlZ2lzdGVyKHBpZCkge1xuICAgIGZvciAobGV0IG5hbWUgb2YgdGhpcy5uYW1lcy5rZXlzKCkpIHtcbiAgICAgIGlmICh0aGlzLm5hbWVzLmhhcyhuYW1lKSAmJiB0aGlzLm5hbWVzLmdldChuYW1lKSA9PT0gcGlkKSB7XG4gICAgICAgIHRoaXMubmFtZXMuZGVsZXRlKG5hbWUpO1xuICAgICAgfVxuICAgIH1cbiAgfVxuXG4gIHBpZCgpIHtcbiAgICByZXR1cm4gdGhpcy5jdXJyZW50X3Byb2Nlc3MucGlkO1xuICB9XG5cbiAgcGlkb2YoaWQpIHtcbiAgICBpZiAoaWQgaW5zdGFuY2VvZiBQSUQpIHtcbiAgICAgIHJldHVybiB0aGlzLnBpZHMuaGFzKGlkKSA/IGlkIDogbnVsbDtcbiAgICB9IGVsc2UgaWYgKGlkIGluc3RhbmNlb2YgUHJvY2Vzcykge1xuICAgICAgcmV0dXJuIGlkLnBpZDtcbiAgICB9IGVsc2Uge1xuICAgICAgbGV0IHBpZCA9IHRoaXMucmVnaXN0ZXJlZChpZCk7XG4gICAgICBpZiAocGlkID09PSBudWxsKSB0aHJvdyBcIlByb2Nlc3MgbmFtZSBub3QgcmVnaXN0ZXJlZDogXCIgKyBpZCArIFwiIChcIiArIHR5cGVvZiBpZCArIFwiKVwiO1xuICAgICAgcmV0dXJuIHBpZDtcbiAgICB9XG4gIH1cblxuICBwdXQoaWQsIGtleSwgdmFsdWUpIHtcbiAgICBsZXQgcGlkID0gdGhpcy5waWRvZihpZCk7XG4gICAgbGV0IHByb2Nlc3MgPSB0aGlzLnBpZHMuZ2V0KHBpZCk7XG4gICAgcHJvY2Vzcy5kaWN0W2tleV0gPSB2YWx1ZTtcbiAgfVxuXG4gIGdldChpZCwga2V5KSB7XG4gICAgbGV0IHBpZCA9IHRoaXMucGlkb2YoaWQpO1xuICAgIGxldCBwcm9jZXNzID0gdGhpcy5waWRzLmdldChwaWQpO1xuXG4gICAgaWYgKGtleSAhPSBudWxsKSB7XG4gICAgICByZXR1cm4gcHJvY2Vzcy5kaWN0W2tleV07XG4gICAgfSBlbHNlIHtcbiAgICAgIHJldHVybiBwcm9jZXNzLmRpY3Q7XG4gICAgfVxuICB9XG5cbiAgZ2V0X2tleXMoaWQpIHtcbiAgICBsZXQgcGlkID0gdGhpcy5waWRvZihpZCk7XG4gICAgbGV0IHByb2Nlc3MgPSB0aGlzLnBpZHMuZ2V0KHBpZCk7XG5cbiAgICByZXR1cm4gT2JqZWN0LmtleXMocHJvY2Vzcy5kaWN0KTtcbiAgfVxuXG4gIGVyYXNlKGlkLCBrZXkpIHtcbiAgICBsZXQgcGlkID0gdGhpcy5waWRvZihpZCk7XG4gICAgbGV0IHByb2Nlc3MgPSB0aGlzLnBpZHMuZ2V0KHBpZCk7XG5cbiAgICBpZiAoa2V5ICE9IG51bGwpIHtcbiAgICAgIGRlbGV0ZSBwcm9jZXNzLmRpY3Rba2V5XTtcbiAgICB9IGVsc2Uge1xuICAgICAgcHJvY2Vzcy5kaWN0ID0ge307XG4gICAgfVxuICB9XG59XG5cbmNsYXNzIEJpdFN0cmluZyB7XG4gIGNvbnN0cnVjdG9yKC4uLmFyZ3MpIHtcbiAgICB0aGlzLnJhd192YWx1ZSA9IGZ1bmN0aW9uICgpIHtcbiAgICAgIHJldHVybiBPYmplY3QuZnJlZXplKGFyZ3MpO1xuICAgIH07XG5cbiAgICB0aGlzLnZhbHVlID0gT2JqZWN0LmZyZWV6ZSh0aGlzLnByb2Nlc3MoYXJncykpO1xuICB9XG5cbiAgZ2V0KGluZGV4KSB7XG4gICAgcmV0dXJuIHRoaXMudmFsdWVbaW5kZXhdO1xuICB9XG5cbiAgY291bnQoKSB7XG4gICAgcmV0dXJuIHRoaXMudmFsdWUubGVuZ3RoO1xuICB9XG5cbiAgW1N5bWJvbC5pdGVyYXRvcl0oKSB7XG4gICAgcmV0dXJuIHRoaXMudmFsdWVbU3ltYm9sLml0ZXJhdG9yXSgpO1xuICB9XG5cbiAgdG9TdHJpbmcoKSB7XG4gICAgdmFyIGksXG4gICAgICAgIHMgPSBcIlwiO1xuICAgIGZvciAoaSA9IDA7IGkgPCB0aGlzLmNvdW50KCk7IGkrKykge1xuICAgICAgaWYgKHMgIT09IFwiXCIpIHtcbiAgICAgICAgcyArPSBcIiwgXCI7XG4gICAgICB9XG4gICAgICBzICs9IHRoaXNbaV0udG9TdHJpbmcoKTtcbiAgICB9XG5cbiAgICByZXR1cm4gXCI8PFwiICsgcyArIFwiPj5cIjtcbiAgfVxuXG4gIHByb2Nlc3MoKSB7XG4gICAgbGV0IHByb2Nlc3NlZF92YWx1ZXMgPSBbXTtcblxuICAgIHZhciBpO1xuICAgIGZvciAoaSA9IDA7IGkgPCB0aGlzLnJhd192YWx1ZSgpLmxlbmd0aDsgaSsrKSB7XG4gICAgICBsZXQgcHJvY2Vzc2VkX3ZhbHVlID0gdGhpc1tcInByb2Nlc3NfXCIgKyB0aGlzLnJhd192YWx1ZSgpW2ldLnR5cGVdKHRoaXMucmF3X3ZhbHVlKClbaV0pO1xuXG4gICAgICBmb3IgKGxldCBhdHRyIG9mIHRoaXMucmF3X3ZhbHVlKClbaV0uYXR0cmlidXRlcykge1xuICAgICAgICBwcm9jZXNzZWRfdmFsdWUgPSB0aGlzW1wicHJvY2Vzc19cIiArIGF0dHJdKHByb2Nlc3NlZF92YWx1ZSk7XG4gICAgICB9XG5cbiAgICAgIHByb2Nlc3NlZF92YWx1ZXMgPSBwcm9jZXNzZWRfdmFsdWVzLmNvbmNhdChwcm9jZXNzZWRfdmFsdWUpO1xuICAgIH1cblxuICAgIHJldHVybiBwcm9jZXNzZWRfdmFsdWVzO1xuICB9XG5cbiAgcHJvY2Vzc19pbnRlZ2VyKHZhbHVlKSB7XG4gICAgcmV0dXJuIHZhbHVlLnZhbHVlO1xuICB9XG5cbiAgcHJvY2Vzc19mbG9hdCh2YWx1ZSkge1xuICAgIGlmICh2YWx1ZS5zaXplID09PSA2NCkge1xuICAgICAgcmV0dXJuIEJpdFN0cmluZy5mbG9hdDY0VG9CeXRlcyh2YWx1ZS52YWx1ZSk7XG4gICAgfSBlbHNlIGlmICh2YWx1ZS5zaXplID09PSAzMikge1xuICAgICAgcmV0dXJuIEJpdFN0cmluZy5mbG9hdDMyVG9CeXRlcyh2YWx1ZS52YWx1ZSk7XG4gICAgfVxuXG4gICAgdGhyb3cgbmV3IEVycm9yKFwiSW52YWxpZCBzaXplIGZvciBmbG9hdFwiKTtcbiAgfVxuXG4gIHByb2Nlc3NfYml0c3RyaW5nKHZhbHVlKSB7XG4gICAgcmV0dXJuIHZhbHVlLnZhbHVlLnZhbHVlO1xuICB9XG5cbiAgcHJvY2Vzc19iaW5hcnkodmFsdWUpIHtcbiAgICByZXR1cm4gQml0U3RyaW5nLnRvVVRGOEFycmF5KHZhbHVlLnZhbHVlKTtcbiAgfVxuXG4gIHByb2Nlc3NfdXRmOCh2YWx1ZSkge1xuICAgIHJldHVybiBCaXRTdHJpbmcudG9VVEY4QXJyYXkodmFsdWUudmFsdWUpO1xuICB9XG5cbiAgcHJvY2Vzc191dGYxNih2YWx1ZSkge1xuICAgIHJldHVybiBCaXRTdHJpbmcudG9VVEYxNkFycmF5KHZhbHVlLnZhbHVlKTtcbiAgfVxuXG4gIHByb2Nlc3NfdXRmMzIodmFsdWUpIHtcbiAgICByZXR1cm4gQml0U3RyaW5nLnRvVVRGMzJBcnJheSh2YWx1ZS52YWx1ZSk7XG4gIH1cblxuICBwcm9jZXNzX3NpZ25lZCh2YWx1ZSkge1xuICAgIHJldHVybiBuZXcgVWludDhBcnJheShbdmFsdWVdKVswXTtcbiAgfVxuXG4gIHByb2Nlc3NfdW5zaWduZWQodmFsdWUpIHtcbiAgICByZXR1cm4gdmFsdWU7XG4gIH1cblxuICBwcm9jZXNzX25hdGl2ZSh2YWx1ZSkge1xuICAgIHJldHVybiB2YWx1ZTtcbiAgfVxuXG4gIHByb2Nlc3NfYmlnKHZhbHVlKSB7XG4gICAgcmV0dXJuIHZhbHVlO1xuICB9XG5cbiAgcHJvY2Vzc19saXR0bGUodmFsdWUpIHtcbiAgICByZXR1cm4gdmFsdWUucmV2ZXJzZSgpO1xuICB9XG5cbiAgcHJvY2Vzc19zaXplKHZhbHVlKSB7XG4gICAgcmV0dXJuIHZhbHVlO1xuICB9XG5cbiAgcHJvY2Vzc191bml0KHZhbHVlKSB7XG4gICAgcmV0dXJuIHZhbHVlO1xuICB9XG5cbiAgc3RhdGljIGludGVnZXIodmFsdWUpIHtcbiAgICByZXR1cm4gQml0U3RyaW5nLndyYXAodmFsdWUsIHsgXCJ0eXBlXCI6IFwiaW50ZWdlclwiLCBcInVuaXRcIjogMSwgXCJzaXplXCI6IDggfSk7XG4gIH1cblxuICBzdGF0aWMgZmxvYXQodmFsdWUpIHtcbiAgICByZXR1cm4gQml0U3RyaW5nLndyYXAodmFsdWUsIHsgXCJ0eXBlXCI6IFwiZmxvYXRcIiwgXCJ1bml0XCI6IDEsIFwic2l6ZVwiOiA2NCB9KTtcbiAgfVxuXG4gIHN0YXRpYyBiaXRzdHJpbmcodmFsdWUpIHtcbiAgICByZXR1cm4gQml0U3RyaW5nLndyYXAodmFsdWUsIHsgXCJ0eXBlXCI6IFwiYml0c3RyaW5nXCIsIFwidW5pdFwiOiAxLCBcInNpemVcIjogdmFsdWUubGVuZ3RoIH0pO1xuICB9XG5cbiAgc3RhdGljIGJpdHModmFsdWUpIHtcbiAgICByZXR1cm4gQml0U3RyaW5nLmJpdHN0cmluZyh2YWx1ZSk7XG4gIH1cblxuICBzdGF0aWMgYmluYXJ5KHZhbHVlKSB7XG4gICAgcmV0dXJuIEJpdFN0cmluZy53cmFwKHZhbHVlLCB7IFwidHlwZVwiOiBcImJpbmFyeVwiLCBcInVuaXRcIjogOCwgXCJzaXplXCI6IHZhbHVlLmxlbmd0aCB9KTtcbiAgfVxuXG4gIHN0YXRpYyBieXRlcyh2YWx1ZSkge1xuICAgIHJldHVybiBCaXRTdHJpbmcuYmluYXJ5KHZhbHVlKTtcbiAgfVxuXG4gIHN0YXRpYyB1dGY4KHZhbHVlKSB7XG4gICAgcmV0dXJuIEJpdFN0cmluZy53cmFwKHZhbHVlLCB7IFwidHlwZVwiOiBcInV0ZjhcIiB9KTtcbiAgfVxuXG4gIHN0YXRpYyB1dGYxNih2YWx1ZSkge1xuICAgIHJldHVybiBCaXRTdHJpbmcud3JhcCh2YWx1ZSwgeyBcInR5cGVcIjogXCJ1dGYxNlwiIH0pO1xuICB9XG5cbiAgc3RhdGljIHV0ZjMyKHZhbHVlKSB7XG4gICAgcmV0dXJuIEJpdFN0cmluZy53cmFwKHZhbHVlLCB7IFwidHlwZVwiOiBcInV0ZjMyXCIgfSk7XG4gIH1cblxuICBzdGF0aWMgc2lnbmVkKHZhbHVlKSB7XG4gICAgcmV0dXJuIEJpdFN0cmluZy53cmFwKHZhbHVlLCB7fSwgXCJzaWduZWRcIik7XG4gIH1cblxuICBzdGF0aWMgdW5zaWduZWQodmFsdWUpIHtcbiAgICByZXR1cm4gQml0U3RyaW5nLndyYXAodmFsdWUsIHt9LCBcInVuc2lnbmVkXCIpO1xuICB9XG5cbiAgc3RhdGljIG5hdGl2ZSh2YWx1ZSkge1xuICAgIHJldHVybiBCaXRTdHJpbmcud3JhcCh2YWx1ZSwge30sIFwibmF0aXZlXCIpO1xuICB9XG5cbiAgc3RhdGljIGJpZyh2YWx1ZSkge1xuICAgIHJldHVybiBCaXRTdHJpbmcud3JhcCh2YWx1ZSwge30sIFwiYmlnXCIpO1xuICB9XG5cbiAgc3RhdGljIGxpdHRsZSh2YWx1ZSkge1xuICAgIHJldHVybiBCaXRTdHJpbmcud3JhcCh2YWx1ZSwge30sIFwibGl0dGxlXCIpO1xuICB9XG5cbiAgc3RhdGljIHNpemUodmFsdWUsIGNvdW50KSB7XG4gICAgcmV0dXJuIEJpdFN0cmluZy53cmFwKHZhbHVlLCB7IFwic2l6ZVwiOiBjb3VudCB9KTtcbiAgfVxuXG4gIHN0YXRpYyB1bml0KHZhbHVlLCBjb3VudCkge1xuICAgIHJldHVybiBCaXRTdHJpbmcud3JhcCh2YWx1ZSwgeyBcInVuaXRcIjogY291bnQgfSk7XG4gIH1cblxuICBzdGF0aWMgd3JhcCh2YWx1ZSwgb3B0LCBuZXdfYXR0cmlidXRlID0gbnVsbCkge1xuICAgIGxldCB0aGVfdmFsdWUgPSB2YWx1ZTtcblxuICAgIGlmICghKHZhbHVlIGluc3RhbmNlb2YgT2JqZWN0KSkge1xuICAgICAgdGhlX3ZhbHVlID0geyBcInZhbHVlXCI6IHZhbHVlLCBcImF0dHJpYnV0ZXNcIjogW10gfTtcbiAgICB9XG5cbiAgICB0aGVfdmFsdWUgPSBPYmplY3QuYXNzaWduKHRoZV92YWx1ZSwgb3B0KTtcblxuICAgIGlmIChuZXdfYXR0cmlidXRlKSB7XG4gICAgICB0aGVfdmFsdWUuYXR0cmlidXRlcy5wdXNoKG5ld19hdHRyaWJ1dGUpO1xuICAgIH1cblxuICAgIHJldHVybiB0aGVfdmFsdWU7XG4gIH1cblxuICBzdGF0aWMgdG9VVEY4QXJyYXkoc3RyKSB7XG4gICAgdmFyIHV0ZjggPSBbXTtcbiAgICBmb3IgKHZhciBpID0gMDsgaSA8IHN0ci5sZW5ndGg7IGkrKykge1xuICAgICAgdmFyIGNoYXJjb2RlID0gc3RyLmNoYXJDb2RlQXQoaSk7XG4gICAgICBpZiAoY2hhcmNvZGUgPCAxMjgpIHtcbiAgICAgICAgdXRmOC5wdXNoKGNoYXJjb2RlKTtcbiAgICAgIH0gZWxzZSBpZiAoY2hhcmNvZGUgPCAyMDQ4KSB7XG4gICAgICAgIHV0ZjgucHVzaCgxOTIgfCBjaGFyY29kZSA+PiA2LCAxMjggfCBjaGFyY29kZSAmIDYzKTtcbiAgICAgIH0gZWxzZSBpZiAoY2hhcmNvZGUgPCA1NTI5NiB8fCBjaGFyY29kZSA+PSA1NzM0NCkge1xuICAgICAgICB1dGY4LnB1c2goMjI0IHwgY2hhcmNvZGUgPj4gMTIsIDEyOCB8IGNoYXJjb2RlID4+IDYgJiA2MywgMTI4IHwgY2hhcmNvZGUgJiA2Myk7XG4gICAgICB9XG4gICAgICAvLyBzdXJyb2dhdGUgcGFpclxuICAgICAgZWxzZSB7XG4gICAgICAgIGkrKztcbiAgICAgICAgLy8gVVRGLTE2IGVuY29kZXMgMHgxMDAwMC0weDEwRkZGRiBieVxuICAgICAgICAvLyBzdWJ0cmFjdGluZyAweDEwMDAwIGFuZCBzcGxpdHRpbmcgdGhlXG4gICAgICAgIC8vIDIwIGJpdHMgb2YgMHgwLTB4RkZGRkYgaW50byB0d28gaGFsdmVzXG4gICAgICAgIGNoYXJjb2RlID0gNjU1MzYgKyAoKGNoYXJjb2RlICYgMTAyMykgPDwgMTAgfCBzdHIuY2hhckNvZGVBdChpKSAmIDEwMjMpO1xuICAgICAgICB1dGY4LnB1c2goMjQwIHwgY2hhcmNvZGUgPj4gMTgsIDEyOCB8IGNoYXJjb2RlID4+IDEyICYgNjMsIDEyOCB8IGNoYXJjb2RlID4+IDYgJiA2MywgMTI4IHwgY2hhcmNvZGUgJiA2Myk7XG4gICAgICB9XG4gICAgfVxuICAgIHJldHVybiB1dGY4O1xuICB9XG5cbiAgc3RhdGljIHRvVVRGMTZBcnJheShzdHIpIHtcbiAgICB2YXIgdXRmMTYgPSBbXTtcbiAgICBmb3IgKHZhciBpID0gMDsgaSA8IHN0ci5sZW5ndGg7IGkrKykge1xuICAgICAgdmFyIGNvZGVQb2ludCA9IHN0ci5jb2RlUG9pbnRBdChpKTtcblxuICAgICAgaWYgKGNvZGVQb2ludCA8PSAyNTUpIHtcbiAgICAgICAgdXRmMTYucHVzaCgwKTtcbiAgICAgICAgdXRmMTYucHVzaChjb2RlUG9pbnQpO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgdXRmMTYucHVzaChjb2RlUG9pbnQgPj4gOCAmIDI1NSk7XG4gICAgICAgIHV0ZjE2LnB1c2goY29kZVBvaW50ICYgMjU1KTtcbiAgICAgIH1cbiAgICB9XG4gICAgcmV0dXJuIHV0ZjE2O1xuICB9XG5cbiAgc3RhdGljIHRvVVRGMzJBcnJheShzdHIpIHtcbiAgICB2YXIgdXRmMzIgPSBbXTtcbiAgICBmb3IgKHZhciBpID0gMDsgaSA8IHN0ci5sZW5ndGg7IGkrKykge1xuICAgICAgdmFyIGNvZGVQb2ludCA9IHN0ci5jb2RlUG9pbnRBdChpKTtcblxuICAgICAgaWYgKGNvZGVQb2ludCA8PSAyNTUpIHtcbiAgICAgICAgdXRmMzIucHVzaCgwKTtcbiAgICAgICAgdXRmMzIucHVzaCgwKTtcbiAgICAgICAgdXRmMzIucHVzaCgwKTtcbiAgICAgICAgdXRmMzIucHVzaChjb2RlUG9pbnQpO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgdXRmMzIucHVzaCgwKTtcbiAgICAgICAgdXRmMzIucHVzaCgwKTtcbiAgICAgICAgdXRmMzIucHVzaChjb2RlUG9pbnQgPj4gOCAmIDI1NSk7XG4gICAgICAgIHV0ZjMyLnB1c2goY29kZVBvaW50ICYgMjU1KTtcbiAgICAgIH1cbiAgICB9XG4gICAgcmV0dXJuIHV0ZjMyO1xuICB9XG5cbiAgLy9odHRwOi8vc3RhY2tvdmVyZmxvdy5jb20vcXVlc3Rpb25zLzIwMDM0OTMvamF2YXNjcmlwdC1mbG9hdC1mcm9tLXRvLWJpdHNcbiAgc3RhdGljIGZsb2F0MzJUb0J5dGVzKGYpIHtcbiAgICB2YXIgYnl0ZXMgPSBbXTtcblxuICAgIHZhciBidWYgPSBuZXcgQXJyYXlCdWZmZXIoNCk7XG4gICAgbmV3IEZsb2F0MzJBcnJheShidWYpWzBdID0gZjtcblxuICAgIGxldCBpbnRWZXJzaW9uID0gbmV3IFVpbnQzMkFycmF5KGJ1ZilbMF07XG5cbiAgICBieXRlcy5wdXNoKGludFZlcnNpb24gPj4gMjQgJiAyNTUpO1xuICAgIGJ5dGVzLnB1c2goaW50VmVyc2lvbiA+PiAxNiAmIDI1NSk7XG4gICAgYnl0ZXMucHVzaChpbnRWZXJzaW9uID4+IDggJiAyNTUpO1xuICAgIGJ5dGVzLnB1c2goaW50VmVyc2lvbiAmIDI1NSk7XG5cbiAgICByZXR1cm4gYnl0ZXM7XG4gIH1cblxuICBzdGF0aWMgZmxvYXQ2NFRvQnl0ZXMoZikge1xuICAgIHZhciBieXRlcyA9IFtdO1xuXG4gICAgdmFyIGJ1ZiA9IG5ldyBBcnJheUJ1ZmZlcig4KTtcbiAgICBuZXcgRmxvYXQ2NEFycmF5KGJ1ZilbMF0gPSBmO1xuXG4gICAgdmFyIGludFZlcnNpb24xID0gbmV3IFVpbnQzMkFycmF5KGJ1ZilbMF07XG4gICAgdmFyIGludFZlcnNpb24yID0gbmV3IFVpbnQzMkFycmF5KGJ1ZilbMV07XG5cbiAgICBieXRlcy5wdXNoKGludFZlcnNpb24yID4+IDI0ICYgMjU1KTtcbiAgICBieXRlcy5wdXNoKGludFZlcnNpb24yID4+IDE2ICYgMjU1KTtcbiAgICBieXRlcy5wdXNoKGludFZlcnNpb24yID4+IDggJiAyNTUpO1xuICAgIGJ5dGVzLnB1c2goaW50VmVyc2lvbjIgJiAyNTUpO1xuXG4gICAgYnl0ZXMucHVzaChpbnRWZXJzaW9uMSA+PiAyNCAmIDI1NSk7XG4gICAgYnl0ZXMucHVzaChpbnRWZXJzaW9uMSA+PiAxNiAmIDI1NSk7XG4gICAgYnl0ZXMucHVzaChpbnRWZXJzaW9uMSA+PiA4ICYgMjU1KTtcbiAgICBieXRlcy5wdXNoKGludFZlcnNpb24xICYgMjU1KTtcblxuICAgIHJldHVybiBieXRlcztcbiAgfVxufVxuXG4vKiBAZmxvdyAqL1xuXG5jbGFzcyBWYXJpYWJsZSB7XG5cbiAgY29uc3RydWN0b3IobmFtZSA9IG51bGwpIHtcbiAgICB0aGlzLm5hbWUgPSBuYW1lO1xuICB9XG59XG5cbmNsYXNzIFdpbGRjYXJkIHtcbiAgY29uc3RydWN0b3IoKSB7fVxufVxuXG5jbGFzcyBTdGFydHNXaXRoIHtcblxuICBjb25zdHJ1Y3RvcihwcmVmaXgpIHtcbiAgICB0aGlzLnByZWZpeCA9IHByZWZpeDtcbiAgfVxufVxuXG5jbGFzcyBDYXB0dXJlIHtcblxuICBjb25zdHJ1Y3Rvcih2YWx1ZSkge1xuICAgIHRoaXMudmFsdWUgPSB2YWx1ZTtcbiAgfVxufVxuXG5jbGFzcyBIZWFkVGFpbCB7XG4gIGNvbnN0cnVjdG9yKCkge31cbn1cblxuY2xhc3MgVHlwZSB7XG5cbiAgY29uc3RydWN0b3IodHlwZSwgb2JqUGF0dGVybiA9IHt9KSB7XG4gICAgdGhpcy50eXBlID0gdHlwZTtcbiAgICB0aGlzLm9ialBhdHRlcm4gPSBvYmpQYXR0ZXJuO1xuICB9XG59XG5cbmNsYXNzIEJvdW5kIHtcblxuICBjb25zdHJ1Y3Rvcih2YWx1ZSkge1xuICAgIHRoaXMudmFsdWUgPSB2YWx1ZTtcbiAgfVxufVxuXG5mdW5jdGlvbiB2YXJpYWJsZShuYW1lID0gbnVsbCkge1xuICByZXR1cm4gbmV3IFZhcmlhYmxlKG5hbWUpO1xufVxuXG5mdW5jdGlvbiB3aWxkY2FyZCgpIHtcbiAgcmV0dXJuIG5ldyBXaWxkY2FyZCgpO1xufVxuXG5mdW5jdGlvbiBzdGFydHNXaXRoKHByZWZpeCkge1xuICByZXR1cm4gbmV3IFN0YXJ0c1dpdGgocHJlZml4KTtcbn1cblxuZnVuY3Rpb24gY2FwdHVyZSh2YWx1ZSkge1xuICByZXR1cm4gbmV3IENhcHR1cmUodmFsdWUpO1xufVxuXG5mdW5jdGlvbiBoZWFkVGFpbCgpIHtcbiAgcmV0dXJuIG5ldyBIZWFkVGFpbCgpO1xufVxuXG5mdW5jdGlvbiB0eXBlKHR5cGUsIG9ialBhdHRlcm4gPSB7fSkge1xuICByZXR1cm4gbmV3IFR5cGUodHlwZSwgb2JqUGF0dGVybik7XG59XG5cbmZ1bmN0aW9uIGJvdW5kKHZhbHVlKSB7XG4gIHJldHVybiBuZXcgQm91bmQodmFsdWUpO1xufVxuXG5mdW5jdGlvbiBpc19udW1iZXIkMih2YWx1ZSkge1xuICByZXR1cm4gdHlwZW9mIHZhbHVlID09PSAnbnVtYmVyJztcbn1cblxuZnVuY3Rpb24gaXNfc3RyaW5nKHZhbHVlKSB7XG4gIHJldHVybiB0eXBlb2YgdmFsdWUgPT09ICdzdHJpbmcnO1xufVxuXG5mdW5jdGlvbiBpc19ib29sZWFuJDIodmFsdWUpIHtcbiAgcmV0dXJuIHR5cGVvZiB2YWx1ZSA9PT0gJ2Jvb2xlYW4nO1xufVxuXG5mdW5jdGlvbiBpc19zeW1ib2wodmFsdWUpIHtcbiAgcmV0dXJuIHR5cGVvZiB2YWx1ZSA9PT0gJ3N5bWJvbCc7XG59XG5cbmZ1bmN0aW9uIGlzX251bGwodmFsdWUpIHtcbiAgcmV0dXJuIHZhbHVlID09PSBudWxsO1xufVxuXG5mdW5jdGlvbiBpc191bmRlZmluZWQodmFsdWUpIHtcbiAgcmV0dXJuIHR5cGVvZiB2YWx1ZSA9PT0gJ3VuZGVmaW5lZCc7XG59XG5cbmZ1bmN0aW9uIGlzX2Z1bmN0aW9uJDIodmFsdWUpIHtcbiAgcmV0dXJuIE9iamVjdC5wcm90b3R5cGUudG9TdHJpbmcuY2FsbCh2YWx1ZSkgPT0gJ1tvYmplY3QgRnVuY3Rpb25dJztcbn1cblxuZnVuY3Rpb24gaXNfdmFyaWFibGUodmFsdWUpIHtcbiAgcmV0dXJuIHZhbHVlIGluc3RhbmNlb2YgVmFyaWFibGU7XG59XG5cbmZ1bmN0aW9uIGlzX3dpbGRjYXJkKHZhbHVlKSB7XG4gIHJldHVybiB2YWx1ZSBpbnN0YW5jZW9mIFdpbGRjYXJkO1xufVxuXG5mdW5jdGlvbiBpc19oZWFkVGFpbCh2YWx1ZSkge1xuICByZXR1cm4gdmFsdWUgaW5zdGFuY2VvZiBIZWFkVGFpbDtcbn1cblxuZnVuY3Rpb24gaXNfY2FwdHVyZSh2YWx1ZSkge1xuICByZXR1cm4gdmFsdWUgaW5zdGFuY2VvZiBDYXB0dXJlO1xufVxuXG5mdW5jdGlvbiBpc190eXBlKHZhbHVlKSB7XG4gIHJldHVybiB2YWx1ZSBpbnN0YW5jZW9mIFR5cGU7XG59XG5cbmZ1bmN0aW9uIGlzX3N0YXJ0c1dpdGgodmFsdWUpIHtcbiAgcmV0dXJuIHZhbHVlIGluc3RhbmNlb2YgU3RhcnRzV2l0aDtcbn1cblxuZnVuY3Rpb24gaXNfYm91bmQodmFsdWUpIHtcbiAgcmV0dXJuIHZhbHVlIGluc3RhbmNlb2YgQm91bmQ7XG59XG5cbmZ1bmN0aW9uIGlzX29iamVjdCh2YWx1ZSkge1xuICByZXR1cm4gdHlwZW9mIHZhbHVlID09PSAnb2JqZWN0Jztcbn1cblxuZnVuY3Rpb24gaXNfYXJyYXkodmFsdWUpIHtcbiAgcmV0dXJuIEFycmF5LmlzQXJyYXkodmFsdWUpO1xufVxuXG52YXIgQ2hlY2tzID0ge1xuICBpc19udW1iZXI6IGlzX251bWJlciQyLFxuICBpc19zdHJpbmcsXG4gIGlzX2Jvb2xlYW46IGlzX2Jvb2xlYW4kMixcbiAgaXNfc3ltYm9sLFxuICBpc19udWxsLFxuICBpc191bmRlZmluZWQsXG4gIGlzX2Z1bmN0aW9uOiBpc19mdW5jdGlvbiQyLFxuICBpc192YXJpYWJsZSxcbiAgaXNfd2lsZGNhcmQsXG4gIGlzX2hlYWRUYWlsLFxuICBpc19jYXB0dXJlLFxuICBpc190eXBlLFxuICBpc19zdGFydHNXaXRoLFxuICBpc19ib3VuZCxcbiAgaXNfb2JqZWN0LFxuICBpc19hcnJheVxufTtcblxuZnVuY3Rpb24gcmVzb2x2ZVN5bWJvbChwYXR0ZXJuKSB7XG4gIHJldHVybiBmdW5jdGlvbiAodmFsdWUpIHtcbiAgICByZXR1cm4gQ2hlY2tzLmlzX3N5bWJvbCh2YWx1ZSkgJiYgdmFsdWUgPT09IHBhdHRlcm47XG4gIH07XG59XG5cbmZ1bmN0aW9uIHJlc29sdmVTdHJpbmcocGF0dGVybikge1xuICByZXR1cm4gZnVuY3Rpb24gKHZhbHVlKSB7XG4gICAgcmV0dXJuIENoZWNrcy5pc19zdHJpbmcodmFsdWUpICYmIHZhbHVlID09PSBwYXR0ZXJuO1xuICB9O1xufVxuXG5mdW5jdGlvbiByZXNvbHZlTnVtYmVyKHBhdHRlcm4pIHtcbiAgcmV0dXJuIGZ1bmN0aW9uICh2YWx1ZSkge1xuICAgIHJldHVybiBDaGVja3MuaXNfbnVtYmVyKHZhbHVlKSAmJiB2YWx1ZSA9PT0gcGF0dGVybjtcbiAgfTtcbn1cblxuZnVuY3Rpb24gcmVzb2x2ZUJvb2xlYW4ocGF0dGVybikge1xuICByZXR1cm4gZnVuY3Rpb24gKHZhbHVlKSB7XG4gICAgcmV0dXJuIENoZWNrcy5pc19ib29sZWFuKHZhbHVlKSAmJiB2YWx1ZSA9PT0gcGF0dGVybjtcbiAgfTtcbn1cblxuZnVuY3Rpb24gcmVzb2x2ZUZ1bmN0aW9uKHBhdHRlcm4pIHtcbiAgcmV0dXJuIGZ1bmN0aW9uICh2YWx1ZSkge1xuICAgIHJldHVybiBDaGVja3MuaXNfZnVuY3Rpb24odmFsdWUpICYmIHZhbHVlID09PSBwYXR0ZXJuO1xuICB9O1xufVxuXG5mdW5jdGlvbiByZXNvbHZlTnVsbChwYXR0ZXJuKSB7XG4gIHJldHVybiBmdW5jdGlvbiAodmFsdWUpIHtcbiAgICByZXR1cm4gQ2hlY2tzLmlzX251bGwodmFsdWUpO1xuICB9O1xufVxuXG5mdW5jdGlvbiByZXNvbHZlQm91bmQocGF0dGVybikge1xuICByZXR1cm4gZnVuY3Rpb24gKHZhbHVlLCBhcmdzKSB7XG4gICAgaWYgKHR5cGVvZiB2YWx1ZSA9PT0gdHlwZW9mIHBhdHRlcm4udmFsdWUgJiYgdmFsdWUgPT09IHBhdHRlcm4udmFsdWUpIHtcbiAgICAgIGFyZ3MucHVzaCh2YWx1ZSk7XG4gICAgICByZXR1cm4gdHJ1ZTtcbiAgICB9XG5cbiAgICByZXR1cm4gZmFsc2U7XG4gIH07XG59XG5cbmZ1bmN0aW9uIHJlc29sdmVXaWxkY2FyZCgpIHtcbiAgcmV0dXJuIGZ1bmN0aW9uICgpIHtcbiAgICByZXR1cm4gdHJ1ZTtcbiAgfTtcbn1cblxuZnVuY3Rpb24gcmVzb2x2ZVZhcmlhYmxlKCkge1xuICByZXR1cm4gZnVuY3Rpb24gKHZhbHVlLCBhcmdzKSB7XG4gICAgYXJncy5wdXNoKHZhbHVlKTtcbiAgICByZXR1cm4gdHJ1ZTtcbiAgfTtcbn1cblxuZnVuY3Rpb24gcmVzb2x2ZUhlYWRUYWlsKCkge1xuICByZXR1cm4gZnVuY3Rpb24gKHZhbHVlLCBhcmdzKSB7XG4gICAgaWYgKCFDaGVja3MuaXNfYXJyYXkodmFsdWUpIHx8IHZhbHVlLmxlbmd0aCA8IDIpIHtcbiAgICAgIHJldHVybiBmYWxzZTtcbiAgICB9XG5cbiAgICBjb25zdCBoZWFkID0gdmFsdWVbMF07XG4gICAgY29uc3QgdGFpbCA9IHZhbHVlLnNsaWNlKDEpO1xuXG4gICAgYXJncy5wdXNoKGhlYWQpO1xuICAgIGFyZ3MucHVzaCh0YWlsKTtcblxuICAgIHJldHVybiB0cnVlO1xuICB9O1xufVxuXG5mdW5jdGlvbiByZXNvbHZlQ2FwdHVyZShwYXR0ZXJuKSB7XG4gIGNvbnN0IG1hdGNoZXMgPSBidWlsZE1hdGNoKHBhdHRlcm4udmFsdWUpO1xuXG4gIHJldHVybiBmdW5jdGlvbiAodmFsdWUsIGFyZ3MpIHtcbiAgICBpZiAobWF0Y2hlcyh2YWx1ZSwgYXJncykpIHtcbiAgICAgIGFyZ3MucHVzaCh2YWx1ZSk7XG4gICAgICByZXR1cm4gdHJ1ZTtcbiAgICB9XG5cbiAgICByZXR1cm4gZmFsc2U7XG4gIH07XG59XG5cbmZ1bmN0aW9uIHJlc29sdmVTdGFydHNXaXRoKHBhdHRlcm4pIHtcbiAgY29uc3QgcHJlZml4ID0gcGF0dGVybi5wcmVmaXg7XG5cbiAgcmV0dXJuIGZ1bmN0aW9uICh2YWx1ZSwgYXJncykge1xuICAgIGlmIChDaGVja3MuaXNfc3RyaW5nKHZhbHVlKSAmJiB2YWx1ZS5zdGFydHNXaXRoKHByZWZpeCkpIHtcbiAgICAgIGFyZ3MucHVzaCh2YWx1ZS5zdWJzdHJpbmcocHJlZml4Lmxlbmd0aCkpO1xuICAgICAgcmV0dXJuIHRydWU7XG4gICAgfVxuXG4gICAgcmV0dXJuIGZhbHNlO1xuICB9O1xufVxuXG5mdW5jdGlvbiByZXNvbHZlVHlwZShwYXR0ZXJuKSB7XG4gIHJldHVybiBmdW5jdGlvbiAodmFsdWUsIGFyZ3MpIHtcbiAgICBpZiAodmFsdWUgaW5zdGFuY2VvZiBwYXR0ZXJuLnR5cGUpIHtcbiAgICAgIGNvbnN0IG1hdGNoZXMgPSBidWlsZE1hdGNoKHBhdHRlcm4ub2JqUGF0dGVybik7XG4gICAgICByZXR1cm4gbWF0Y2hlcyh2YWx1ZSwgYXJncykgJiYgYXJncy5wdXNoKHZhbHVlKSA+IDA7XG4gICAgfVxuXG4gICAgcmV0dXJuIGZhbHNlO1xuICB9O1xufVxuXG5mdW5jdGlvbiByZXNvbHZlQXJyYXkocGF0dGVybikge1xuICBjb25zdCBtYXRjaGVzID0gcGF0dGVybi5tYXAoeCA9PiBidWlsZE1hdGNoKHgpKTtcblxuICByZXR1cm4gZnVuY3Rpb24gKHZhbHVlLCBhcmdzKSB7XG4gICAgaWYgKCFDaGVja3MuaXNfYXJyYXkodmFsdWUpIHx8IHZhbHVlLmxlbmd0aCAhPSBwYXR0ZXJuLmxlbmd0aCkge1xuICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH1cblxuICAgIHJldHVybiB2YWx1ZS5ldmVyeShmdW5jdGlvbiAodiwgaSkge1xuICAgICAgcmV0dXJuIG1hdGNoZXNbaV0odmFsdWVbaV0sIGFyZ3MpO1xuICAgIH0pO1xuICB9O1xufVxuXG5mdW5jdGlvbiByZXNvbHZlT2JqZWN0KHBhdHRlcm4pIHtcbiAgbGV0IG1hdGNoZXMgPSB7fTtcblxuICBmb3IgKGxldCBrZXkgb2YgT2JqZWN0LmtleXMocGF0dGVybikuY29uY2F0KE9iamVjdC5nZXRPd25Qcm9wZXJ0eVN5bWJvbHMocGF0dGVybikpKSB7XG4gICAgbWF0Y2hlc1trZXldID0gYnVpbGRNYXRjaChwYXR0ZXJuW2tleV0pO1xuICB9XG5cbiAgcmV0dXJuIGZ1bmN0aW9uICh2YWx1ZSwgYXJncykge1xuICAgIGlmICghQ2hlY2tzLmlzX29iamVjdCh2YWx1ZSkgfHwgcGF0dGVybi5sZW5ndGggPiB2YWx1ZS5sZW5ndGgpIHtcbiAgICAgIHJldHVybiBmYWxzZTtcbiAgICB9XG5cbiAgICBmb3IgKGxldCBrZXkgb2YgT2JqZWN0LmtleXMocGF0dGVybikuY29uY2F0KE9iamVjdC5nZXRPd25Qcm9wZXJ0eVN5bWJvbHMocGF0dGVybikpKSB7XG4gICAgICBpZiAoIShrZXkgaW4gdmFsdWUpIHx8ICFtYXRjaGVzW2tleV0odmFsdWVba2V5XSwgYXJncykpIHtcbiAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgfVxuICAgIH1cblxuICAgIHJldHVybiB0cnVlO1xuICB9O1xufVxuXG5mdW5jdGlvbiByZXNvbHZlTm9NYXRjaCgpIHtcbiAgcmV0dXJuIGZ1bmN0aW9uICgpIHtcbiAgICByZXR1cm4gZmFsc2U7XG4gIH07XG59XG5cbnZhciBSZXNvbHZlcnMgPSB7XG4gIHJlc29sdmVCb3VuZCxcbiAgcmVzb2x2ZVdpbGRjYXJkLFxuICByZXNvbHZlVmFyaWFibGUsXG4gIHJlc29sdmVIZWFkVGFpbCxcbiAgcmVzb2x2ZUNhcHR1cmUsXG4gIHJlc29sdmVTdGFydHNXaXRoLFxuICByZXNvbHZlVHlwZSxcbiAgcmVzb2x2ZUFycmF5LFxuICByZXNvbHZlT2JqZWN0LFxuICByZXNvbHZlTm9NYXRjaCxcbiAgcmVzb2x2ZVN5bWJvbCxcbiAgcmVzb2x2ZVN0cmluZyxcbiAgcmVzb2x2ZU51bWJlcixcbiAgcmVzb2x2ZUJvb2xlYW4sXG4gIHJlc29sdmVGdW5jdGlvbixcbiAgcmVzb2x2ZU51bGxcbn07XG5cbmZ1bmN0aW9uIGJ1aWxkTWF0Y2gocGF0dGVybikge1xuXG4gIGlmIChDaGVja3MuaXNfdmFyaWFibGUocGF0dGVybikpIHtcbiAgICByZXR1cm4gUmVzb2x2ZXJzLnJlc29sdmVWYXJpYWJsZShwYXR0ZXJuKTtcbiAgfVxuXG4gIGlmIChDaGVja3MuaXNfd2lsZGNhcmQocGF0dGVybikpIHtcbiAgICByZXR1cm4gUmVzb2x2ZXJzLnJlc29sdmVXaWxkY2FyZChwYXR0ZXJuKTtcbiAgfVxuXG4gIGlmIChDaGVja3MuaXNfdW5kZWZpbmVkKHBhdHRlcm4pKSB7XG4gICAgcmV0dXJuIFJlc29sdmVycy5yZXNvbHZlV2lsZGNhcmQocGF0dGVybik7XG4gIH1cblxuICBpZiAoQ2hlY2tzLmlzX2hlYWRUYWlsKHBhdHRlcm4pKSB7XG4gICAgcmV0dXJuIFJlc29sdmVycy5yZXNvbHZlSGVhZFRhaWwocGF0dGVybik7XG4gIH1cblxuICBpZiAoQ2hlY2tzLmlzX3N0YXJ0c1dpdGgocGF0dGVybikpIHtcbiAgICByZXR1cm4gUmVzb2x2ZXJzLnJlc29sdmVTdGFydHNXaXRoKHBhdHRlcm4pO1xuICB9XG5cbiAgaWYgKENoZWNrcy5pc19jYXB0dXJlKHBhdHRlcm4pKSB7XG4gICAgcmV0dXJuIFJlc29sdmVycy5yZXNvbHZlQ2FwdHVyZShwYXR0ZXJuKTtcbiAgfVxuXG4gIGlmIChDaGVja3MuaXNfYm91bmQocGF0dGVybikpIHtcbiAgICByZXR1cm4gUmVzb2x2ZXJzLnJlc29sdmVCb3VuZChwYXR0ZXJuKTtcbiAgfVxuXG4gIGlmIChDaGVja3MuaXNfdHlwZShwYXR0ZXJuKSkge1xuICAgIHJldHVybiBSZXNvbHZlcnMucmVzb2x2ZVR5cGUocGF0dGVybik7XG4gIH1cblxuICBpZiAoQ2hlY2tzLmlzX2FycmF5KHBhdHRlcm4pKSB7XG4gICAgcmV0dXJuIFJlc29sdmVycy5yZXNvbHZlQXJyYXkocGF0dGVybik7XG4gIH1cblxuICBpZiAoQ2hlY2tzLmlzX251bWJlcihwYXR0ZXJuKSkge1xuICAgIHJldHVybiBSZXNvbHZlcnMucmVzb2x2ZU51bWJlcihwYXR0ZXJuKTtcbiAgfVxuXG4gIGlmIChDaGVja3MuaXNfc3RyaW5nKHBhdHRlcm4pKSB7XG4gICAgcmV0dXJuIFJlc29sdmVycy5yZXNvbHZlU3RyaW5nKHBhdHRlcm4pO1xuICB9XG5cbiAgaWYgKENoZWNrcy5pc19ib29sZWFuKHBhdHRlcm4pKSB7XG4gICAgcmV0dXJuIFJlc29sdmVycy5yZXNvbHZlQm9vbGVhbihwYXR0ZXJuKTtcbiAgfVxuXG4gIGlmIChDaGVja3MuaXNfc3ltYm9sKHBhdHRlcm4pKSB7XG4gICAgcmV0dXJuIFJlc29sdmVycy5yZXNvbHZlU3ltYm9sKHBhdHRlcm4pO1xuICB9XG5cbiAgaWYgKENoZWNrcy5pc19udWxsKHBhdHRlcm4pKSB7XG4gICAgcmV0dXJuIFJlc29sdmVycy5yZXNvbHZlTnVsbChwYXR0ZXJuKTtcbiAgfVxuXG4gIGlmIChDaGVja3MuaXNfb2JqZWN0KHBhdHRlcm4pKSB7XG4gICAgcmV0dXJuIFJlc29sdmVycy5yZXNvbHZlT2JqZWN0KHBhdHRlcm4pO1xuICB9XG5cbiAgcmV0dXJuIFJlc29sdmVycy5yZXNvbHZlTm9NYXRjaCgpO1xufVxuXG5jbGFzcyBNYXRjaEVycm9yIGV4dGVuZHMgRXJyb3Ige1xuICBjb25zdHJ1Y3RvcihhcmcpIHtcbiAgICBzdXBlcigpO1xuXG4gICAgaWYgKHR5cGVvZiBhcmcgPT09ICdzeW1ib2wnKSB7XG4gICAgICB0aGlzLm1lc3NhZ2UgPSAnTm8gbWF0Y2ggZm9yOiAnICsgYXJnLnRvU3RyaW5nKCk7XG4gICAgfSBlbHNlIGlmIChBcnJheS5pc0FycmF5KGFyZykpIHtcbiAgICAgIGxldCBtYXBwZWRWYWx1ZXMgPSBhcmcubWFwKHggPT4geC50b1N0cmluZygpKTtcbiAgICAgIHRoaXMubWVzc2FnZSA9ICdObyBtYXRjaCBmb3I6ICcgKyBtYXBwZWRWYWx1ZXM7XG4gICAgfSBlbHNlIHtcbiAgICAgIHRoaXMubWVzc2FnZSA9ICdObyBtYXRjaCBmb3I6ICcgKyBhcmc7XG4gICAgfVxuXG4gICAgdGhpcy5zdGFjayA9IG5ldyBFcnJvcigpLnN0YWNrO1xuICAgIHRoaXMubmFtZSA9IHRoaXMuY29uc3RydWN0b3IubmFtZTtcbiAgfVxufVxuXG5jbGFzcyBDYXNlIHtcblxuICBjb25zdHJ1Y3RvcihwYXR0ZXJuLCBmbiwgZ3VhcmQgPSAoKSA9PiB0cnVlKSB7XG4gICAgdGhpcy5wYXR0ZXJuID0gYnVpbGRNYXRjaChwYXR0ZXJuKTtcbiAgICB0aGlzLmZuID0gZm47XG4gICAgdGhpcy5ndWFyZCA9IGd1YXJkO1xuICB9XG59XG5cbmZ1bmN0aW9uIG1ha2VfY2FzZShwYXR0ZXJuLCBmbiwgZ3VhcmQgPSAoKSA9PiB0cnVlKSB7XG4gIHJldHVybiBuZXcgQ2FzZShwYXR0ZXJuLCBmbiwgZ3VhcmQpO1xufVxuXG5mdW5jdGlvbiBkZWZtYXRjaCguLi5jYXNlcykge1xuICByZXR1cm4gZnVuY3Rpb24gKC4uLmFyZ3MpIHtcbiAgICBmb3IgKGxldCBwcm9jZXNzZWRDYXNlIG9mIGNhc2VzKSB7XG4gICAgICBsZXQgcmVzdWx0ID0gW107XG4gICAgICBpZiAocHJvY2Vzc2VkQ2FzZS5wYXR0ZXJuKGFyZ3MsIHJlc3VsdCkgJiYgcHJvY2Vzc2VkQ2FzZS5ndWFyZC5hcHBseSh0aGlzLCByZXN1bHQpKSB7XG4gICAgICAgIHJldHVybiBwcm9jZXNzZWRDYXNlLmZuLmFwcGx5KHRoaXMsIHJlc3VsdCk7XG4gICAgICB9XG4gICAgfVxuXG4gICAgdGhyb3cgbmV3IE1hdGNoRXJyb3IoYXJncyk7XG4gIH07XG59XG5cbmZ1bmN0aW9uIG1hdGNoKHBhdHRlcm4sIGV4cHIsIGd1YXJkID0gKCkgPT4gdHJ1ZSkge1xuICBsZXQgcmVzdWx0ID0gW107XG4gIGxldCBwcm9jZXNzZWRQYXR0ZXJuID0gYnVpbGRNYXRjaChwYXR0ZXJuKTtcbiAgaWYgKHByb2Nlc3NlZFBhdHRlcm4oZXhwciwgcmVzdWx0KSAmJiBndWFyZC5hcHBseSh0aGlzLCByZXN1bHQpKSB7XG4gICAgcmV0dXJuIHJlc3VsdDtcbiAgfSBlbHNlIHtcbiAgICB0aHJvdyBuZXcgTWF0Y2hFcnJvcihleHByKTtcbiAgfVxufVxuXG5mdW5jdGlvbiBtYXRjaF9ub190aHJvdyhwYXR0ZXJuLCBleHByLCBndWFyZCA9ICgpID0+IHRydWUpIHtcbiAgdHJ5IHtcbiAgICByZXR1cm4gbWF0Y2gocGF0dGVybiwgZXhwciwgZ3VhcmQpO1xuICB9IGNhdGNoIChlKSB7XG4gICAgaWYgKGUgaW5zdGFuY2VvZiBNYXRjaEVycm9yKSB7XG4gICAgICByZXR1cm4gbnVsbDtcbiAgICB9XG5cbiAgICB0aHJvdyBlO1xuICB9XG59XG5cbnZhciBQYXR0ZXJucyA9IHtcbiAgZGVmbWF0Y2gsIG1hdGNoLCBNYXRjaEVycm9yLCBtYXRjaF9ub190aHJvdyxcbiAgdmFyaWFibGUsIHdpbGRjYXJkLCBzdGFydHNXaXRoLFxuICBjYXB0dXJlLCBoZWFkVGFpbCwgdHlwZSwgYm91bmQsIENhc2UsIG1ha2VfY2FzZVxufTtcblxuZnVuY3Rpb24gY2FsbF9wcm9wZXJ0eShpdGVtLCBwcm9wZXJ0eSkge1xuICBpZiAocHJvcGVydHkgaW4gaXRlbSkge1xuICAgIGl0ZW1bcHJvcGVydHldO1xuICAgIGlmIChpdGVtW3Byb3BlcnR5XSBpbnN0YW5jZW9mIEZ1bmN0aW9uKSB7XG4gICAgICByZXR1cm4gaXRlbVtwcm9wZXJ0eV0oKTtcbiAgICB9IGVsc2Uge1xuICAgICAgcmV0dXJuIGl0ZW1bcHJvcGVydHldO1xuICAgIH1cbiAgfSBlbHNlIGlmIChTeW1ib2wuZm9yKHByb3BlcnR5KSBpbiBpdGVtKSB7XG4gICAgbGV0IHByb3AgPSBTeW1ib2wuZm9yKHByb3BlcnR5KTtcbiAgICBpZiAoaXRlbVtwcm9wXSBpbnN0YW5jZW9mIEZ1bmN0aW9uKSB7XG4gICAgICByZXR1cm4gaXRlbVtwcm9wXSgpO1xuICAgIH0gZWxzZSB7XG4gICAgICByZXR1cm4gaXRlbVtwcm9wXTtcbiAgICB9XG4gIH1cblxuICB0aHJvdyBuZXcgRXJyb3IoYFByb3BlcnR5ICR7IHByb3BlcnR5IH0gbm90IGZvdW5kIGluICR7IGl0ZW0gfWApO1xufVxuXG5mdW5jdGlvbiBpc19pbnN0YW5jZV9vZih2YWx1ZSwgdHlwZSkge1xuICByZXR1cm4gdmFsdWUgaW5zdGFuY2VvZiB0eXBlO1xufVxuXG5mdW5jdGlvbiBzaXplJDIodGVybSkge1xuICByZXR1cm4gdGVybS5sZW5ndGg7XG59XG5cbmZ1bmN0aW9uIGlzX25pbCQxKHgpIHtcbiAgcmV0dXJuIHggPT09IG51bGw7XG59XG5cbmZ1bmN0aW9uIGlzX2F0b20kMSh4KSB7XG4gIHJldHVybiB0eXBlb2YgeCA9PT0gJ3N5bWJvbCc7XG59XG5cbmZ1bmN0aW9uIGlzX2JpbmFyeSQxKHgpIHtcbiAgcmV0dXJuIHR5cGVvZiB4ID09PSAnc3RyaW5nJyB8fCB4IGluc3RhbmNlb2YgU3RyaW5nO1xufVxuXG5mdW5jdGlvbiBpc19ib29sZWFuJDEoeCkge1xuICByZXR1cm4gdHlwZW9mIHggPT09ICdib29sZWFuJyB8fCB4IGluc3RhbmNlb2YgQm9vbGVhbjtcbn1cblxuZnVuY3Rpb24gaXNfZnVuY3Rpb24kMSh4LCBhcml0eSA9IC0xKSB7XG4gIHJldHVybiB0eXBlb2YgeCA9PT0gJ2Z1bmN0aW9uJyB8fCB4IGluc3RhbmNlb2YgRnVuY3Rpb247XG59XG5cbmZ1bmN0aW9uIGlzX2Zsb2F0JDEoeCkge1xuICByZXR1cm4gaXNfbnVtYmVyJDEoeCkgJiYgIU51bWJlci5pc0ludGVnZXIoeCk7XG59XG5cbmZ1bmN0aW9uIGlzX2ludGVnZXIkMSh4KSB7XG4gIHJldHVybiBOdW1iZXIuaXNJbnRlZ2VyKHgpO1xufVxuXG5mdW5jdGlvbiBpc19saXN0JDEoeCkge1xuICByZXR1cm4geCBpbnN0YW5jZW9mIEFycmF5O1xufVxuXG5mdW5jdGlvbiBpc19tYXAkMSh4KSB7XG4gIHJldHVybiB0eXBlb2YgeCA9PT0gJ29iamVjdCcgfHwgeCBpbnN0YW5jZW9mIE9iamVjdDtcbn1cblxuZnVuY3Rpb24gaXNfbnVtYmVyJDEoeCkge1xuICByZXR1cm4gdHlwZW9mIHggPT09ICdudW1iZXInO1xufVxuXG5mdW5jdGlvbiBpc190dXBsZSQxKHgpIHtcbiAgcmV0dXJuIHggaW5zdGFuY2VvZiBUdXBsZTtcbn1cblxuZnVuY3Rpb24gaXNfcGlkJDEoeCkge1xuICByZXR1cm4geCBpbnN0YW5jZW9mIFBJRDtcbn1cblxuZnVuY3Rpb24gaXNfcG9ydCQxKHgpIHtcbiAgcmV0dXJuIGZhbHNlO1xufVxuXG5mdW5jdGlvbiBpc19yZWZlcmVuY2UkMSh4KSB7XG4gIHJldHVybiBmYWxzZTtcbn1cblxuZnVuY3Rpb24gaXNfYml0c3RyaW5nJDEoeCkge1xuICByZXR1cm4gaXNfYmluYXJ5JDEoeCkgfHwgeCBpbnN0YW5jZW9mIEJpdFN0cmluZztcbn1cblxuZnVuY3Rpb24gYWRkKG9uZSwgdHdvKSB7XG4gIHJldHVybiBvbmUgKyB0d287XG59XG5cbmZ1bmN0aW9uIHN1YnRyYWN0KG9uZSwgdHdvKSB7XG4gIHJldHVybiBvbmUgKyB0d287XG59XG5cbmZ1bmN0aW9uIG11bHRpcGx5KG9uZSwgdHdvKSB7XG4gIHJldHVybiBvbmUgKyB0d287XG59XG5cbmZ1bmN0aW9uIGRpdmlkZShvbmUsIHR3bykge1xuICByZXR1cm4gb25lICsgdHdvO1xufVxuXG5mdW5jdGlvbiByZW1haW5kZXIob25lLCB0d28pIHtcbiAgcmV0dXJuIG9uZSArIHR3bztcbn1cblxuZnVuY3Rpb24gYXBwbHkkMSguLi5hcmdzKSB7XG4gIGlmIChhcmdzLmxlbmd0aCA9PT0gMikge1xuICAgIGFyZ3NbMF0uYXBwbHkobnVsbCwgYXJncy5zbGljZSgxKSk7XG4gIH0gZWxzZSB7XG4gICAgYXJnc1swXVthcmdzWzFdXS5hcHBseShudWxsLCBhcmdzLnNsaWNlKDIpKTtcbiAgfVxufVxuXG5mdW5jdGlvbiBuZXdfdHVwbGUoLi4uYXJncykge1xuICByZXR1cm4gbmV3IFR1cGxlKC4uLmFyZ3MpO1xufVxuXG5mdW5jdGlvbiBkdXBsaWNhdGUoZGF0YSwgc2l6ZSkge1xuICBsZXQgYXJyYXkgPSBbXTtcblxuICBmb3IgKHZhciBpID0gc2l6ZSAtIDE7IGkgPj0gMDsgaS0tKSB7XG4gICAgYXJyYXkucHVzaChkYXRhKTtcbiAgfVxuXG4gIHJldHVybiBhcnJheTtcbn1cblxuZnVuY3Rpb24gY29udGFpbnMobGVmdCwgcmlnaHQpIHtcbiAgZm9yIChsZXQgeCBvZiByaWdodCkge1xuICAgIGlmIChQYXR0ZXJucy5tYXRjaF9ub190aHJvdyhsZWZ0LCB4KSAhPSBudWxsKSB7XG4gICAgICByZXR1cm4gdHJ1ZTtcbiAgICB9XG4gIH1cblxuICByZXR1cm4gZmFsc2U7XG59XG5cbmZ1bmN0aW9uIHJldmVyc2UobGlzdCkge1xuICByZXR1cm4gbGlzdC5jb25jYXQoW10pLnJldmVyc2UoKTtcbn1cblxuZnVuY3Rpb24gZ2V0X2dsb2JhbCgpIHtcbiAgaWYgKHR5cGVvZiBzZWxmICE9PSAndW5kZWZpbmVkJykge1xuICAgIHJldHVybiBzZWxmO1xuICB9IGVsc2UgaWYgKHR5cGVvZiBnbG9iYWwgIT09ICd1bmRlZmluZWQnKSB7XG4gICAgcmV0dXJuIGdsb2JhbDtcbiAgfVxuXG4gIHRocm93ICdObyBnbG9iYWwgc3RhdGUgZm91bmQnO1xufVxuXG5mdW5jdGlvbiBjb25jYXRfbGlzdHMobGVmdCwgcmlnaHQpIHtcbiAgcmV0dXJuIGxlZnQuY29uY2F0KHJpZ2h0KTtcbn1cblxuZnVuY3Rpb24gcHJlcGVuZF90b19saXN0KGxpc3QsIGl0ZW0pIHtcbiAgcmV0dXJuIFtpdGVtXS5jb25jYXQobGlzdCk7XG59XG5cbmZ1bmN0aW9uIGRlZnN0cnVjdChkZWZhdWx0cykge1xuICByZXR1cm4gY2xhc3Mge1xuICAgIGNvbnN0cnVjdG9yKHVwZGF0ZSA9IHt9KSB7XG4gICAgICBsZXQgdGhlX3ZhbHVlcyA9IE9iamVjdC5hc3NpZ24oZGVmYXVsdHMsIHVwZGF0ZSk7XG4gICAgICBPYmplY3QuYXNzaWduKHRoaXMsIHRoZV92YWx1ZXMpO1xuICAgIH1cblxuICAgIHN0YXRpYyBjcmVhdGUodXBkYXRlcyA9IHt9KSB7XG4gICAgICBsZXQgeCA9IG5ldyB0aGlzKHVwZGF0ZXMpO1xuICAgICAgcmV0dXJuIE9iamVjdC5mcmVlemUoeCk7XG4gICAgfVxuICB9O1xufVxuXG5mdW5jdGlvbiBkZWZleGNlcHRpb24oZGVmYXVsdHMpIHtcbiAgcmV0dXJuIGNsYXNzIGV4dGVuZHMgRXJyb3Ige1xuICAgIGNvbnN0cnVjdG9yKHVwZGF0ZSA9IHt9KSB7XG4gICAgICBsZXQgbWVzc2FnZSA9IHVwZGF0ZS5tZXNzYWdlIHx8ICcnO1xuICAgICAgc3VwZXIobWVzc2FnZSk7XG5cbiAgICAgIGxldCB0aGVfdmFsdWVzID0gT2JqZWN0LmFzc2lnbihkZWZhdWx0cywgdXBkYXRlKTtcbiAgICAgIE9iamVjdC5hc3NpZ24odGhpcywgdGhlX3ZhbHVlcyk7XG5cbiAgICAgIHRoaXMubmFtZSA9IHRoaXMuY29uc3RydWN0b3IubmFtZTtcbiAgICAgIHRoaXMubWVzc2FnZSA9IG1lc3NhZ2U7XG4gICAgICB0aGlzW1NwZWNpYWxGb3Jtcy5hdG9tKCdfX2V4Y2VwdGlvbl9fJyldID0gdHJ1ZTtcbiAgICAgIEVycm9yLmNhcHR1cmVTdGFja1RyYWNlKHRoaXMsIHRoaXMuY29uc3RydWN0b3IubmFtZSk7XG4gICAgfVxuXG4gICAgc3RhdGljIGNyZWF0ZSh1cGRhdGVzID0ge30pIHtcbiAgICAgIGxldCB4ID0gbmV3IHRoaXModXBkYXRlcyk7XG4gICAgICByZXR1cm4gT2JqZWN0LmZyZWV6ZSh4KTtcbiAgICB9XG4gIH07XG59XG5cbmZ1bmN0aW9uIGRlZnByb3RvY29sKHNwZWMpIHtcbiAgcmV0dXJuIG5ldyBQcm90b2NvbChzcGVjKTtcbn1cblxuZnVuY3Rpb24gZGVmaW1wbChwcm90b2NvbCwgdHlwZSwgaW1wbCkge1xuICBwcm90b2NvbC5pbXBsZW1lbnRhdGlvbih0eXBlLCBpbXBsKTtcbn1cblxuZnVuY3Rpb24gZ2V0X29iamVjdF9rZXlzKG9iaikge1xuICByZXR1cm4gT2JqZWN0LmtleXMob2JqKS5jb25jYXQoT2JqZWN0LmdldE93blByb3BlcnR5U3ltYm9scyhvYmopKTtcbn1cblxuZnVuY3Rpb24gaXNfdmFsaWRfY2hhcmFjdGVyKGNvZGVwb2ludCkge1xuICB0cnkge1xuICAgIHJldHVybiBTdHJpbmcuZnJvbUNvZGVQb2ludChjb2RlcG9pbnQpICE9IG51bGw7XG4gIH0gY2F0Y2ggKGUpIHtcbiAgICByZXR1cm4gZmFsc2U7XG4gIH1cbn1cblxuLy9odHRwczovL2RldmVsb3Blci5tb3ppbGxhLm9yZy9lbi1VUy9kb2NzL1dlYi9BUEkvV2luZG93QmFzZTY0L0Jhc2U2NF9lbmNvZGluZ19hbmRfZGVjb2RpbmcjU29sdXRpb25fMl8lRTIlODAlOTNfcmV3cml0ZV90aGVfRE9Nc19hdG9iKClfYW5kX2J0b2EoKV91c2luZ19KYXZhU2NyaXB0J3NfVHlwZWRBcnJheXNfYW5kX1VURi04XG5mdW5jdGlvbiBiNjRFbmNvZGVVbmljb2RlKHN0cikge1xuICByZXR1cm4gYnRvYShlbmNvZGVVUklDb21wb25lbnQoc3RyKS5yZXBsYWNlKC8lKFswLTlBLUZdezJ9KS9nLCBmdW5jdGlvbiAobWF0Y2gsIHAxKSB7XG4gICAgcmV0dXJuIFN0cmluZy5mcm9tQ2hhckNvZGUoJzB4JyArIHAxKTtcbiAgfSkpO1xufVxuXG52YXIgRnVuY3Rpb25zID0ge1xuICBjYWxsX3Byb3BlcnR5LFxuICBpc19pbnN0YW5jZV9vZixcbiAgc2l6ZTogc2l6ZSQyLFxuICBpc19uaWw6IGlzX25pbCQxLFxuICBpc19hdG9tOiBpc19hdG9tJDEsXG4gIGlzX2JpbmFyeTogaXNfYmluYXJ5JDEsXG4gIGlzX2Jvb2xlYW46IGlzX2Jvb2xlYW4kMSxcbiAgaXNfZnVuY3Rpb246IGlzX2Z1bmN0aW9uJDEsXG4gIGlzX2Zsb2F0OiBpc19mbG9hdCQxLFxuICBpc19pbnRlZ2VyOiBpc19pbnRlZ2VyJDEsXG4gIGlzX2xpc3Q6IGlzX2xpc3QkMSxcbiAgaXNfbWFwOiBpc19tYXAkMSxcbiAgaXNfbnVtYmVyOiBpc19udW1iZXIkMSxcbiAgaXNfdHVwbGU6IGlzX3R1cGxlJDEsXG4gIGlzX3BpZDogaXNfcGlkJDEsXG4gIGlzX3BvcnQ6IGlzX3BvcnQkMSxcbiAgaXNfcmVmZXJlbmNlOiBpc19yZWZlcmVuY2UkMSxcbiAgaXNfYml0c3RyaW5nOiBpc19iaXRzdHJpbmckMSxcbiAgYWRkLFxuICBzdWJ0cmFjdCxcbiAgbXVsdGlwbHksXG4gIGRpdmlkZSxcbiAgcmVtYWluZGVyLFxuICBhcHBseTogYXBwbHkkMSxcbiAgbmV3X3R1cGxlLFxuICBkdXBsaWNhdGUsXG4gIGNvbnRhaW5zLFxuICByZXZlcnNlLFxuICBnZXRfZ2xvYmFsLFxuICBjb25jYXRfbGlzdHMsXG4gIHByZXBlbmRfdG9fbGlzdCxcbiAgZGVmc3RydWN0LFxuICBkZWZleGNlcHRpb24sXG4gIGRlZnByb3RvY29sLFxuICBkZWZpbXBsLFxuICBnZXRfb2JqZWN0X2tleXMsXG4gIGlzX3ZhbGlkX2NoYXJhY3RlcixcbiAgYjY0RW5jb2RlVW5pY29kZVxufTtcblxuRnVuY3Rpb25zLmdldF9nbG9iYWwoKS5wcm9jZXNzZXMgPSBGdW5jdGlvbnMuZ2V0X2dsb2JhbCgpLnByb2Nlc3NlcyB8fCBuZXcgUHJvY2Vzc1N5c3RlbSgpO1xuXG5cblxudmFyIEMgPSBPYmplY3QuZnJlZXplKHtcblx0UHJvY2Vzc1N5c3RlbTogUHJvY2Vzc1N5c3RlbSxcblx0VHVwbGU6IFR1cGxlLFxuXHRQSUQ6IFBJRCxcblx0Qml0U3RyaW5nOiBCaXRTdHJpbmcsXG5cdFBhdHRlcm5zOiBQYXR0ZXJucyxcblx0SW50ZWdlcjogSW50ZWdlcixcblx0RmxvYXQ6IEZsb2F0LFxuXHRGdW5jdGlvbnM6IEZ1bmN0aW9ucyxcblx0TGlzdDogTGlzdCQxXG59KTtcblxubGV0IEVudW0gPSB7XG5cbiAgYWxsX19xbWFya19fOiBmdW5jdGlvbiAoY29sbGVjdGlvbiwgZnVuID0geCA9PiB4KSB7XG4gICAgZm9yIChsZXQgZWxlbSBvZiBjb2xsZWN0aW9uKSB7XG4gICAgICBpZiAoIWZ1bihlbGVtKSkge1xuICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICB9XG4gICAgfVxuXG4gICAgcmV0dXJuIHRydWU7XG4gIH0sXG5cbiAgYW55X19xbWFya19fOiBmdW5jdGlvbiAoY29sbGVjdGlvbiwgZnVuID0geCA9PiB4KSB7XG4gICAgZm9yIChsZXQgZWxlbSBvZiBjb2xsZWN0aW9uKSB7XG4gICAgICBpZiAoZnVuKGVsZW0pKSB7XG4gICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgfVxuICAgIH1cblxuICAgIHJldHVybiBmYWxzZTtcbiAgfSxcblxuICBhdDogZnVuY3Rpb24gKGNvbGxlY3Rpb24sIG4sIHRoZV9kZWZhdWx0ID0gbnVsbCkge1xuICAgIGlmIChuID4gdGhpcy5jb3VudChjb2xsZWN0aW9uKSB8fCBuIDwgMCkge1xuICAgICAgcmV0dXJuIHRoZV9kZWZhdWx0O1xuICAgIH1cblxuICAgIHJldHVybiBjb2xsZWN0aW9uW25dO1xuICB9LFxuXG4gIGNvbmNhdDogZnVuY3Rpb24gKC4uLmVudW1hYmxlcykge1xuICAgIHJldHVybiBlbnVtYWJsZXNbMF0uY29uY2F0KGVudW1hYmxlc1sxXSk7XG4gIH0sXG5cbiAgY291bnQ6IGZ1bmN0aW9uIChjb2xsZWN0aW9uLCBmdW4gPSBudWxsKSB7XG4gICAgaWYgKGZ1biA9PSBudWxsKSB7XG4gICAgICByZXR1cm4gY29sbGVjdGlvbi5sZW5ndGg7XG4gICAgfSBlbHNlIHtcbiAgICAgIHJldHVybiBjb2xsZWN0aW9uLmZpbHRlcihmdW4pLmxlbmd0aDtcbiAgICB9XG4gIH0sXG5cbiAgZHJvcDogZnVuY3Rpb24gKGNvbGxlY3Rpb24sIGNvdW50KSB7XG4gICAgcmV0dXJuIGNvbGxlY3Rpb24uc2xpY2UoY291bnQpO1xuICB9LFxuXG4gIGRyb3Bfd2hpbGU6IGZ1bmN0aW9uIChjb2xsZWN0aW9uLCBmdW4pIHtcbiAgICBsZXQgY291bnQgPSAwO1xuXG4gICAgZm9yIChsZXQgZWxlbSBvZiBjb2xsZWN0aW9uKSB7XG4gICAgICBpZiAoZnVuKGVsZW0pKSB7XG4gICAgICAgIGNvdW50ID0gY291bnQgKyAxO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgYnJlYWs7XG4gICAgICB9XG4gICAgfVxuXG4gICAgcmV0dXJuIGNvbGxlY3Rpb24uc2xpY2UoY291bnQpO1xuICB9LFxuXG4gIGVhY2g6IGZ1bmN0aW9uIChjb2xsZWN0aW9uLCBmdW4pIHtcbiAgICBmb3IgKGxldCBlbGVtIG9mIGNvbGxlY3Rpb24pIHtcbiAgICAgIGZ1bihlbGVtKTtcbiAgICB9XG4gIH0sXG5cbiAgZW1wdHlfX3FtYXJrX186IGZ1bmN0aW9uIChjb2xsZWN0aW9uKSB7XG4gICAgcmV0dXJuIGNvbGxlY3Rpb24ubGVuZ3RoID09PSAwO1xuICB9LFxuXG4gIGZldGNoOiBmdW5jdGlvbiAoY29sbGVjdGlvbiwgbikge1xuICAgIGlmIChLZXJuZWwuaXNfbGlzdChjb2xsZWN0aW9uKSkge1xuICAgICAgaWYgKG4gPCB0aGlzLmNvdW50KGNvbGxlY3Rpb24pICYmIG4gPj0gMCkge1xuICAgICAgICByZXR1cm4gbmV3IFR1cGxlKFN5bWJvbC5mb3IoJ29rJyksIGNvbGxlY3Rpb25bbl0pO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgcmV0dXJuIFN5bWJvbC5mb3IoJ2Vycm9yJyk7XG4gICAgICB9XG4gICAgfVxuXG4gICAgdGhyb3cgbmV3IEVycm9yKCdjb2xsZWN0aW9uIGlzIG5vdCBhbiBFbnVtZXJhYmxlJyk7XG4gIH0sXG5cbiAgZmV0Y2hfX2VtYXJrX186IGZ1bmN0aW9uIChjb2xsZWN0aW9uLCBuKSB7XG4gICAgaWYgKEtlcm5lbC5pc19saXN0KGNvbGxlY3Rpb24pKSB7XG4gICAgICBpZiAobiA8IHRoaXMuY291bnQoY29sbGVjdGlvbikgJiYgbiA+PSAwKSB7XG4gICAgICAgIHJldHVybiBjb2xsZWN0aW9uW25dO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdvdXQgb2YgYm91bmRzIGVycm9yJyk7XG4gICAgICB9XG4gICAgfVxuXG4gICAgdGhyb3cgbmV3IEVycm9yKCdjb2xsZWN0aW9uIGlzIG5vdCBhbiBFbnVtZXJhYmxlJyk7XG4gIH0sXG5cbiAgZmlsdGVyOiBmdW5jdGlvbiAoY29sbGVjdGlvbiwgZnVuKSB7XG4gICAgbGV0IHJlc3VsdCA9IFtdO1xuXG4gICAgZm9yIChsZXQgZWxlbSBvZiBjb2xsZWN0aW9uKSB7XG4gICAgICBpZiAoZnVuKGVsZW0pKSB7XG4gICAgICAgIHJlc3VsdC5wdXNoKGVsZW0pO1xuICAgICAgfVxuICAgIH1cblxuICAgIHJldHVybiByZXN1bHQ7XG4gIH0sXG5cbiAgZmlsdGVyX21hcDogZnVuY3Rpb24gKGNvbGxlY3Rpb24sIGZpbHRlciwgbWFwcGVyKSB7XG4gICAgcmV0dXJuIEVudW0ubWFwKEVudW0uZmlsdGVyKGNvbGxlY3Rpb24sIGZpbHRlciksIG1hcHBlcik7XG4gIH0sXG5cbiAgZmluZDogZnVuY3Rpb24gKGNvbGxlY3Rpb24sIGlmX25vbmUgPSBudWxsLCBmdW4pIHtcbiAgICBmb3IgKGxldCBlbGVtIG9mIGNvbGxlY3Rpb24pIHtcbiAgICAgIGlmIChmdW4oZWxlbSkpIHtcbiAgICAgICAgcmV0dXJuIGVsZW07XG4gICAgICB9XG4gICAgfVxuXG4gICAgcmV0dXJuIGlmX25vbmU7XG4gIH0sXG5cbiAgaW50bzogZnVuY3Rpb24gKGNvbGxlY3Rpb24sIGxpc3QpIHtcbiAgICByZXR1cm4gbGlzdC5jb25jYXQoY29sbGVjdGlvbik7XG4gIH0sXG5cbiAgbWFwOiBmdW5jdGlvbiAoY29sbGVjdGlvbiwgZnVuKSB7XG4gICAgbGV0IHJlc3VsdCA9IFtdO1xuXG4gICAgZm9yIChsZXQgZWxlbSBvZiBjb2xsZWN0aW9uKSB7XG4gICAgICByZXN1bHQucHVzaChmdW4oZWxlbSkpO1xuICAgIH1cblxuICAgIHJldHVybiByZXN1bHQ7XG4gIH0sXG5cbiAgbWFwX3JlZHVjZTogZnVuY3Rpb24gKGNvbGxlY3Rpb24sIGFjYywgZnVuKSB7XG4gICAgbGV0IG1hcHBlZCA9IExpc3QkMSgpO1xuICAgIGxldCB0aGVfYWNjID0gYWNjO1xuXG4gICAgZm9yICh2YXIgaSA9IDA7IGkgPCB0aGlzLmNvdW50KGNvbGxlY3Rpb24pOyBpKyspIHtcbiAgICAgIGxldCB0dXBsZSA9IGZ1bihjb2xsZWN0aW9uW2ldLCB0aGVfYWNjKTtcblxuICAgICAgdGhlX2FjYyA9IHR1cGxlLmdldCgxKTtcbiAgICAgIG1hcHBlZCA9IExpc3QkMSguLi5tYXBwZWQuY29uY2F0KFt0dXBsZS5nZXQoMCldKSk7XG4gICAgfVxuXG4gICAgcmV0dXJuIG5ldyBUdXBsZShtYXBwZWQsIHRoZV9hY2MpO1xuICB9LFxuXG4gIG1lbWJlcl9fcW1hcmtfXzogZnVuY3Rpb24gKGNvbGxlY3Rpb24sIHZhbHVlKSB7XG4gICAgcmV0dXJuIGNvbGxlY3Rpb24uaW5jbHVkZXModmFsdWUpO1xuICB9LFxuXG4gIHJlZHVjZTogZnVuY3Rpb24gKGNvbGxlY3Rpb24sIGFjYywgZnVuKSB7XG4gICAgbGV0IHRoZV9hY2MgPSBhY2M7XG5cbiAgICBmb3IgKHZhciBpID0gMDsgaSA8IHRoaXMuY291bnQoY29sbGVjdGlvbik7IGkrKykge1xuICAgICAgbGV0IHR1cGxlID0gZnVuKGNvbGxlY3Rpb25baV0sIHRoZV9hY2MpO1xuXG4gICAgICB0aGVfYWNjID0gdHVwbGUuZ2V0KDEpO1xuICAgIH1cblxuICAgIHJldHVybiB0aGVfYWNjO1xuICB9LFxuXG4gIHRha2U6IGZ1bmN0aW9uIChjb2xsZWN0aW9uLCBjb3VudCkge1xuICAgIHJldHVybiBjb2xsZWN0aW9uLnNsaWNlKDAsIGNvdW50KTtcbiAgfSxcblxuICB0YWtlX2V2ZXJ5OiBmdW5jdGlvbiAoY29sbGVjdGlvbiwgbnRoKSB7XG4gICAgbGV0IHJlc3VsdCA9IFtdO1xuICAgIGxldCBpbmRleCA9IDA7XG5cbiAgICBmb3IgKGxldCBlbGVtIG9mIGNvbGxlY3Rpb24pIHtcbiAgICAgIGlmIChpbmRleCAlIG50aCA9PT0gMCkge1xuICAgICAgICByZXN1bHQucHVzaChlbGVtKTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICByZXR1cm4gTGlzdCQxKC4uLnJlc3VsdCk7XG4gIH0sXG5cbiAgdGFrZV93aGlsZTogZnVuY3Rpb24gKGNvbGxlY3Rpb24sIGZ1bikge1xuICAgIGxldCBjb3VudCA9IDA7XG5cbiAgICBmb3IgKGxldCBlbGVtIG9mIGNvbGxlY3Rpb24pIHtcbiAgICAgIGlmIChmdW4oZWxlbSkpIHtcbiAgICAgICAgY291bnQgPSBjb3VudCArIDE7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBicmVhaztcbiAgICAgIH1cbiAgICB9XG5cbiAgICByZXR1cm4gY29sbGVjdGlvbi5zbGljZSgwLCBjb3VudCk7XG4gIH0sXG5cbiAgdG9fbGlzdDogZnVuY3Rpb24gKGNvbGxlY3Rpb24pIHtcbiAgICByZXR1cm4gY29sbGVjdGlvbjtcbiAgfVxufTtcblxubGV0IFNwZWNpYWxGb3JtcyQxID0ge1xuXG4gIGF0b206IGZ1bmN0aW9uIChfdmFsdWUpIHtcbiAgICByZXR1cm4gU3ltYm9sLmZvcihfdmFsdWUpO1xuICB9LFxuXG4gIGxpc3Q6IGZ1bmN0aW9uICguLi5hcmdzKSB7XG4gICAgcmV0dXJuIE9iamVjdC5mcmVlemUoYXJncyk7XG4gIH0sXG5cbiAgYml0c3RyaW5nOiBmdW5jdGlvbiAoLi4uYXJncykge1xuICAgIHJldHVybiBuZXcgQml0U3RyaW5nKC4uLmFyZ3MpO1xuICB9LFxuXG4gIGJvdW5kOiBmdW5jdGlvbiAoX3Zhcikge1xuICAgIHJldHVybiBQYXR0ZXJucy5ib3VuZChfdmFyKTtcbiAgfSxcblxuICBfY2FzZTogZnVuY3Rpb24gKGNvbmRpdGlvbiwgY2xhdXNlcykge1xuICAgIHJldHVybiBQYXR0ZXJucy5kZWZtYXRjaCguLi5jbGF1c2VzKShjb25kaXRpb24pO1xuICB9LFxuXG4gIGNvbmQ6IGZ1bmN0aW9uIChjbGF1c2VzKSB7XG4gICAgZm9yIChsZXQgY2xhdXNlIG9mIGNsYXVzZXMpIHtcbiAgICAgIGlmIChjbGF1c2VbMF0pIHtcbiAgICAgICAgcmV0dXJuIGNsYXVzZVsxXSgpO1xuICAgICAgfVxuICAgIH1cblxuICAgIHRocm93IG5ldyBFcnJvcigpO1xuICB9LFxuXG4gIGZuOiBmdW5jdGlvbiAoY2xhdXNlcykge1xuICAgIHJldHVybiBQYXR0ZXJucy5kZWZtYXRjaChjbGF1c2VzKTtcbiAgfSxcblxuICBtYXA6IGZ1bmN0aW9uIChvYmopIHtcbiAgICByZXR1cm4gT2JqZWN0LmZyZWV6ZShvYmopO1xuICB9LFxuXG4gIG1hcF91cGRhdGU6IGZ1bmN0aW9uIChtYXAsIHZhbHVlcykge1xuICAgIHJldHVybiBPYmplY3QuZnJlZXplKE9iamVjdC5hc3NpZ24oT2JqZWN0LmNyZWF0ZShtYXAuY29uc3RydWN0b3IucHJvdG90eXBlKSwgbWFwLCB2YWx1ZXMpKTtcbiAgfSxcblxuICBfZm9yOiBmdW5jdGlvbiAoY29sbGVjdGlvbnMsIGZ1biwgZmlsdGVyID0gKCkgPT4gdHJ1ZSwgaW50byA9IFtdLCBwcmV2aW91c1ZhbHVlcyA9IFtdKSB7XG4gICAgbGV0IHBhdHRlcm4gPSBjb2xsZWN0aW9uc1swXVswXTtcbiAgICBsZXQgY29sbGVjdGlvbiA9IGNvbGxlY3Rpb25zWzBdWzFdO1xuXG4gICAgaWYgKGNvbGxlY3Rpb25zLmxlbmd0aCA9PT0gMSkge1xuXG4gICAgICBmb3IgKGxldCBlbGVtIG9mIGNvbGxlY3Rpb24pIHtcbiAgICAgICAgbGV0IHIgPSBQYXR0ZXJucy5tYXRjaF9ub190aHJvdyhwYXR0ZXJuLCBlbGVtKTtcbiAgICAgICAgbGV0IGFyZ3MgPSBwcmV2aW91c1ZhbHVlcy5jb25jYXQocik7XG5cbiAgICAgICAgaWYgKHIgJiYgZmlsdGVyLmFwcGx5KHRoaXMsIGFyZ3MpKSB7XG4gICAgICAgICAgaW50byA9IEVudW0uaW50byhbZnVuLmFwcGx5KHRoaXMsIGFyZ3MpXSwgaW50byk7XG4gICAgICAgIH1cbiAgICAgIH1cblxuICAgICAgcmV0dXJuIGludG87XG4gICAgfSBlbHNlIHtcbiAgICAgIGxldCBfaW50byA9IFtdO1xuXG4gICAgICBmb3IgKGxldCBlbGVtIG9mIGNvbGxlY3Rpb24pIHtcbiAgICAgICAgbGV0IHIgPSBQYXR0ZXJucy5tYXRjaF9ub190aHJvdyhwYXR0ZXJuLCBlbGVtKTtcbiAgICAgICAgaWYgKHIpIHtcbiAgICAgICAgICBfaW50byA9IEVudW0uaW50byh0aGlzLl9mb3IoY29sbGVjdGlvbnMuc2xpY2UoMSksIGZ1biwgZmlsdGVyLCBfaW50bywgcHJldmlvdXNWYWx1ZXMuY29uY2F0KHIpKSwgaW50byk7XG4gICAgICAgIH1cbiAgICAgIH1cblxuICAgICAgcmV0dXJuIF9pbnRvO1xuICAgIH1cbiAgfSxcblxuICByZWNlaXZlOiBmdW5jdGlvbiAocmVjZWl2ZV9mdW4sIHRpbWVvdXRfaW5fbXMgPSBudWxsLCB0aW1lb3V0X2ZuID0gdGltZSA9PiB0cnVlKSB7XG4gICAgaWYgKHRpbWVvdXRfaW5fbXMgPT0gbnVsbCB8fCB0aW1lb3V0X2luX21zID09PSBTeXN0ZW0uZm9yKCdpbmZpbml0eScpKSB7XG4gICAgICB3aGlsZSAodHJ1ZSkge1xuICAgICAgICBpZiAoc2VsZi5tYWlsYm94Lmxlbmd0aCAhPT0gMCkge1xuICAgICAgICAgIGxldCBtZXNzYWdlID0gc2VsZi5tYWlsYm94WzBdO1xuICAgICAgICAgIHNlbGYubWFpbGJveCA9IHNlbGYubWFpbGJveC5zbGljZSgxKTtcbiAgICAgICAgICByZXR1cm4gcmVjZWl2ZV9mdW4obWVzc2FnZSk7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9IGVsc2UgaWYgKHRpbWVvdXRfaW5fbXMgPT09IDApIHtcbiAgICAgIGlmIChzZWxmLm1haWxib3gubGVuZ3RoICE9PSAwKSB7XG4gICAgICAgIGxldCBtZXNzYWdlID0gc2VsZi5tYWlsYm94WzBdO1xuICAgICAgICBzZWxmLm1haWxib3ggPSBzZWxmLm1haWxib3guc2xpY2UoMSk7XG4gICAgICAgIHJldHVybiByZWNlaXZlX2Z1bihtZXNzYWdlKTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHJldHVybiBudWxsO1xuICAgICAgfVxuICAgIH0gZWxzZSB7XG4gICAgICBsZXQgbm93ID0gRGF0ZS5ub3coKTtcbiAgICAgIHdoaWxlIChEYXRlLm5vdygpIDwgbm93ICsgdGltZW91dF9pbl9tcykge1xuICAgICAgICBpZiAoc2VsZi5tYWlsYm94Lmxlbmd0aCAhPT0gMCkge1xuICAgICAgICAgIGxldCBtZXNzYWdlID0gc2VsZi5tYWlsYm94WzBdO1xuICAgICAgICAgIHNlbGYubWFpbGJveCA9IHNlbGYubWFpbGJveC5zbGljZSgxKTtcbiAgICAgICAgICByZXR1cm4gcmVjZWl2ZV9mdW4obWVzc2FnZSk7XG4gICAgICAgIH1cbiAgICAgIH1cblxuICAgICAgcmV0dXJuIHRpbWVvdXRfZm4odGltZW91dF9pbl9tcyk7XG4gICAgfVxuICB9LFxuXG4gIHR1cGxlOiBmdW5jdGlvbiAoLi4uYXJncykge1xuICAgIHJldHVybiBuZXcgVHVwbGUoLi4uYXJncyk7XG4gIH0sXG5cbiAgX3RyeTogZnVuY3Rpb24gKGRvX2Z1biwgcmVzY3VlX2Z1bmN0aW9uLCBjYXRjaF9mdW4sIGVsc2VfZnVuY3Rpb24sIGFmdGVyX2Z1bmN0aW9uKSB7XG4gICAgbGV0IHJlc3VsdCA9IG51bGw7XG5cbiAgICB0cnkge1xuICAgICAgcmVzdWx0ID0gZG9fZnVuKCk7XG4gICAgfSBjYXRjaCAoZSkge1xuICAgICAgbGV0IGV4X3Jlc3VsdCA9IG51bGw7XG5cbiAgICAgIGlmIChyZXNjdWVfZnVuY3Rpb24pIHtcbiAgICAgICAgdHJ5IHtcbiAgICAgICAgICBleF9yZXN1bHQgPSByZXNjdWVfZnVuY3Rpb24oZSk7XG4gICAgICAgICAgcmV0dXJuIGV4X3Jlc3VsdDtcbiAgICAgICAgfSBjYXRjaCAoZXgpIHtcbiAgICAgICAgICBpZiAoZXggaW5zdGFuY2VvZiBQYXR0ZXJucy5NYXRjaEVycm9yKSB7XG4gICAgICAgICAgICB0aHJvdyBleDtcbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgIH1cblxuICAgICAgaWYgKGNhdGNoX2Z1bikge1xuICAgICAgICB0cnkge1xuICAgICAgICAgIGV4X3Jlc3VsdCA9IGNhdGNoX2Z1bihlKTtcbiAgICAgICAgICByZXR1cm4gZXhfcmVzdWx0O1xuICAgICAgICB9IGNhdGNoIChleCkge1xuICAgICAgICAgIGlmIChleCBpbnN0YW5jZW9mIFBhdHRlcm5zLk1hdGNoRXJyb3IpIHtcbiAgICAgICAgICAgIHRocm93IGV4O1xuICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgfVxuXG4gICAgICB0aHJvdyBlO1xuICAgIH0gZmluYWxseSB7XG4gICAgICBpZiAoYWZ0ZXJfZnVuY3Rpb24pIHtcbiAgICAgICAgYWZ0ZXJfZnVuY3Rpb24oKTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICBpZiAoZWxzZV9mdW5jdGlvbikge1xuICAgICAgdHJ5IHtcbiAgICAgICAgcmV0dXJuIGVsc2VfZnVuY3Rpb24ocmVzdWx0KTtcbiAgICAgIH0gY2F0Y2ggKGV4KSB7XG4gICAgICAgIGlmIChleCBpbnN0YW5jZW9mIFBhdHRlcm5zLk1hdGNoRXJyb3IpIHtcbiAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ05vIE1hdGNoIEZvdW5kIGluIEVsc2UnKTtcbiAgICAgICAgfVxuXG4gICAgICAgIHRocm93IGV4O1xuICAgICAgfVxuICAgIH0gZWxzZSB7XG4gICAgICByZXR1cm4gcmVzdWx0O1xuICAgIH1cbiAgfVxuXG59O1xuXG5mdW5jdGlvbiB0bChsaXN0KSB7XG4gIHJldHVybiBTcGVjaWFsRm9ybXMkMS5saXN0KC4uLmxpc3Quc2xpY2UoMSkpO1xufVxuXG5mdW5jdGlvbiBoZChsaXN0KSB7XG4gIHJldHVybiBsaXN0WzBdO1xufVxuXG5mdW5jdGlvbiBpc19uaWwoeCkge1xuICByZXR1cm4geCA9PT0gbnVsbDtcbn1cblxuZnVuY3Rpb24gaXNfYXRvbSh4KSB7XG4gIHJldHVybiB0eXBlb2YgeCA9PT0gJ3N5bWJvbCc7XG59XG5cbmZ1bmN0aW9uIGlzX2JpbmFyeSh4KSB7XG4gIHJldHVybiB0eXBlb2YgeCA9PT0gJ3N0cmluZycgfHwgeCBpbnN0YW5jZW9mIFN0cmluZztcbn1cblxuZnVuY3Rpb24gaXNfYm9vbGVhbih4KSB7XG4gIHJldHVybiB0eXBlb2YgeCA9PT0gJ2Jvb2xlYW4nIHx8IHggaW5zdGFuY2VvZiBCb29sZWFuO1xufVxuXG5mdW5jdGlvbiBpc19mdW5jdGlvbih4LCBhcml0eSA9IC0xKSB7XG4gIHJldHVybiB0eXBlb2YgeCA9PT0gJ2Z1bmN0aW9uJyB8fCB4IGluc3RhbmNlb2YgRnVuY3Rpb247XG59XG5cbmZ1bmN0aW9uIGlzX2Zsb2F0KHgpIHtcbiAgcmV0dXJuIGlzX251bWJlcih4KSAmJiAhTnVtYmVyLmlzSW50ZWdlcih4KTtcbn1cblxuZnVuY3Rpb24gaXNfaW50ZWdlcih4KSB7XG4gIHJldHVybiBOdW1iZXIuaXNJbnRlZ2VyKHgpO1xufVxuXG5mdW5jdGlvbiBpc19saXN0KHgpIHtcbiAgcmV0dXJuIHggaW5zdGFuY2VvZiBBcnJheTtcbn1cblxuZnVuY3Rpb24gaXNfbWFwKHgpIHtcbiAgcmV0dXJuIHR5cGVvZiB4ID09PSAnb2JqZWN0JyB8fCB4IGluc3RhbmNlb2YgT2JqZWN0O1xufVxuXG5mdW5jdGlvbiBpc19udW1iZXIoeCkge1xuICByZXR1cm4gdHlwZW9mIHggPT09ICdudW1iZXInO1xufVxuXG5mdW5jdGlvbiBpc190dXBsZSh4KSB7XG4gIHJldHVybiB4IGluc3RhbmNlb2YgVHVwbGU7XG59XG5cbmZ1bmN0aW9uIGxlbmd0aCh4KSB7XG4gIHJldHVybiB4Lmxlbmd0aDtcbn1cblxuZnVuY3Rpb24gaXNfcGlkKHgpIHtcbiAgcmV0dXJuIHggaW5zdGFuY2VvZiBQSUQ7XG59XG5cbmZ1bmN0aW9uIGlzX3BvcnQoeCkge1xuICByZXR1cm4gZmFsc2U7XG59XG5cbmZ1bmN0aW9uIGlzX3JlZmVyZW5jZSh4KSB7XG4gIHJldHVybiBmYWxzZTtcbn1cblxuZnVuY3Rpb24gaXNfYml0c3RyaW5nKHgpIHtcbiAgcmV0dXJuIGlzX2JpbmFyeSh4KSB8fCB4IGluc3RhbmNlb2YgQml0U3RyaW5nO1xufVxuXG5mdW5jdGlvbiBfX2luX18obGVmdCwgcmlnaHQpIHtcbiAgZm9yIChsZXQgeCBvZiByaWdodCkge1xuICAgIGlmIChtYXRjaF9fcW1hcmtfXyhsZWZ0LCB4KSkge1xuICAgICAgcmV0dXJuIHRydWU7XG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIGZhbHNlO1xufVxuXG5mdW5jdGlvbiBhYnMobnVtYmVyKSB7XG4gIHJldHVybiBNYXRoLmFicyhudW1iZXIpO1xufVxuXG5mdW5jdGlvbiByb3VuZChudW1iZXIpIHtcbiAgcmV0dXJuIE1hdGgucm91bmQobnVtYmVyKTtcbn1cblxuZnVuY3Rpb24gZWxlbSh0dXBsZSwgaW5kZXgpIHtcbiAgaWYgKGlzX2xpc3QodHVwbGUpKSB7XG4gICAgcmV0dXJuIHR1cGxlW2luZGV4XTtcbiAgfVxuXG4gIHJldHVybiB0dXBsZS5nZXQoaW5kZXgpO1xufVxuXG5mdW5jdGlvbiByZW0obGVmdCwgcmlnaHQpIHtcbiAgcmV0dXJuIGxlZnQgJSByaWdodDtcbn1cblxuZnVuY3Rpb24gZGl2KGxlZnQsIHJpZ2h0KSB7XG4gIHJldHVybiBsZWZ0IC8gcmlnaHQ7XG59XG5cbmZ1bmN0aW9uIGFuZChsZWZ0LCByaWdodCkge1xuICByZXR1cm4gbGVmdCAmJiByaWdodDtcbn1cblxuZnVuY3Rpb24gb3IobGVmdCwgcmlnaHQpIHtcbiAgcmV0dXJuIGxlZnQgfHwgcmlnaHQ7XG59XG5cbmZ1bmN0aW9uIG5vdChhcmcpIHtcbiAgcmV0dXJuICFhcmc7XG59XG5cbmZ1bmN0aW9uIGFwcGx5KC4uLmFyZ3MpIHtcbiAgaWYgKGFyZ3MubGVuZ3RoID09PSAzKSB7XG4gICAgbGV0IG1vZCA9IGFyZ3NbMF07XG4gICAgbGV0IGZ1bmMgPSBhcmdzWzFdO1xuICAgIGxldCBmdW5jX2FyZ3MgPSBhcmdzWzJdO1xuICAgIHJldHVybiBtb2RbZnVuY10uYXBwbHkobnVsbCwgZnVuY19hcmdzKTtcbiAgfSBlbHNlIHtcbiAgICBsZXQgZnVuYyA9IGFyZ3NbMF07XG4gICAgbGV0IGZ1bmNfYXJncyA9IGFyZ3NbMV07XG5cbiAgICByZXR1cm4gZnVuYy5hcHBseShudWxsLCBmdW5jX2FyZ3MpO1xuICB9XG59XG5cbmZ1bmN0aW9uIHRvX3N0cmluZyhhcmcpIHtcbiAgaWYgKGlzX3R1cGxlKGFyZykpIHtcbiAgICByZXR1cm4gYXJnLnRvU3RyaW5nKCk7XG4gIH1cblxuICByZXR1cm4gYXJnLnRvU3RyaW5nKCk7XG59XG5cbmZ1bmN0aW9uIG1hdGNoX19xbWFya19fKHBhdHRlcm4sIGV4cHIsIGd1YXJkID0gKCkgPT4gdHJ1ZSkge1xuICByZXR1cm4gUGF0dGVybnMubWF0Y2hfbm9fdGhyb3cocGF0dGVybiwgZXhwciwgZ3VhcmQpICE9IG51bGw7XG59XG5cbnZhciBLZXJuZWwgPSB7XG4gIFNwZWNpYWxGb3JtczogU3BlY2lhbEZvcm1zJDEsXG4gIHRsLFxuICBoZCxcbiAgaXNfbmlsLFxuICBpc19hdG9tLFxuICBpc19iaW5hcnksXG4gIGlzX2Jvb2xlYW4sXG4gIGlzX2Z1bmN0aW9uLFxuICBpc19mbG9hdCxcbiAgaXNfaW50ZWdlcixcbiAgaXNfbGlzdCxcbiAgaXNfbWFwLFxuICBpc19udW1iZXIsXG4gIGlzX3R1cGxlLFxuICBsZW5ndGgsXG4gIGlzX3BpZCxcbiAgaXNfcG9ydCxcbiAgaXNfcmVmZXJlbmNlLFxuICBpc19iaXRzdHJpbmcsXG4gIGluOiBfX2luX18sXG4gIGFicyxcbiAgcm91bmQsXG4gIGVsZW0sXG4gIHJlbSxcbiAgZGl2LFxuICBhbmQsXG4gIG9yLFxuICBub3QsXG4gIGFwcGx5LFxuICB0b19zdHJpbmcsXG4gIG1hdGNoX19xbWFya19fXG59O1xuXG5sZXQgTGlzdCA9IHt9O1xuXG5MaXN0LmRlbGV0ZSA9IGZ1bmN0aW9uIChsaXN0LCBpdGVtKSB7XG4gIGxldCBuZXdfdmFsdWUgPSBbXTtcbiAgbGV0IHZhbHVlX2ZvdW5kID0gZmFsc2U7XG5cbiAgZm9yIChsZXQgeCBvZiBsaXN0KSB7XG4gICAgaWYgKHggPT09IGl0ZW0gJiYgdmFsdWVfZm91bmQgIT09IGZhbHNlKSB7XG4gICAgICBuZXdfdmFsdWUucHVzaCh4KTtcbiAgICAgIHZhbHVlX2ZvdW5kID0gdHJ1ZTtcbiAgICB9IGVsc2UgaWYgKHggIT09IGl0ZW0pIHtcbiAgICAgIG5ld192YWx1ZS5wdXNoKHgpO1xuICAgIH1cbiAgfVxuXG4gIHJldHVybiBMaXN0JDEoLi4ubmV3X3ZhbHVlKTtcbn07XG5cbkxpc3QuZGVsZXRlX2F0ID0gZnVuY3Rpb24gKGxpc3QsIGluZGV4KSB7XG4gIGxldCBuZXdfdmFsdWUgPSBbXTtcblxuICBmb3IgKGxldCBpID0gMDsgaSA8IGxpc3QubGVuZ3RoOyBpKyspIHtcbiAgICBpZiAoaSAhPT0gaW5kZXgpIHtcbiAgICAgIG5ld192YWx1ZS5wdXNoKGxpc3RbaV0pO1xuICAgIH1cbiAgfVxuXG4gIHJldHVybiBMaXN0JDEoLi4ubmV3X3ZhbHVlKTtcbn07XG5cbkxpc3QuZHVwbGljYXRlID0gZnVuY3Rpb24gKGVsZW0sIG4pIHtcbiAgbGV0IG5ld192YWx1ZSA9IFtdO1xuXG4gIGZvciAodmFyIGkgPSAwOyBpIDwgbjsgaSsrKSB7XG4gICAgbmV3X3ZhbHVlLnB1c2goZWxlbSk7XG4gIH1cblxuICByZXR1cm4gTGlzdCQxKC4uLm5ld192YWx1ZSk7XG59O1xuXG5MaXN0LmZpcnN0ID0gZnVuY3Rpb24gKGxpc3QpIHtcbiAgcmV0dXJuIGxpc3RbMF07XG59O1xuXG5MaXN0LmZsYXR0ZW4gPSBmdW5jdGlvbiAobGlzdCwgdGFpbCA9IExpc3QkMSgpKSB7XG4gIGxldCBuZXdfdmFsdWUgPSBbXTtcblxuICBmb3IgKGxldCB4IG9mIGxpc3QpIHtcbiAgICBpZiAoS2VybmVsLmlzX2xpc3QoeCkpIHtcbiAgICAgIG5ld192YWx1ZSA9IG5ld192YWx1ZS5jb25jYXQoTGlzdC5mbGF0dGVuKHgpKTtcbiAgICB9IGVsc2Uge1xuICAgICAgbmV3X3ZhbHVlLnB1c2goeCk7XG4gICAgfVxuICB9XG5cbiAgbmV3X3ZhbHVlID0gbmV3X3ZhbHVlLmNvbmNhdCh0YWlsKTtcblxuICByZXR1cm4gTGlzdCQxKC4uLm5ld192YWx1ZSk7XG59O1xuXG5MaXN0LmZvbGRsID0gZnVuY3Rpb24gKGxpc3QsIGFjYywgZnVuYykge1xuICByZXR1cm4gbGlzdC5yZWR1Y2UoZnVuYywgYWNjKTtcbn07XG5cbkxpc3QuZm9sZHIgPSBmdW5jdGlvbiAobGlzdCwgYWNjLCBmdW5jKSB7XG4gIGxldCBuZXdfYWNjID0gYWNjO1xuXG4gIGZvciAodmFyIGkgPSBsaXN0Lmxlbmd0aCAtIDE7IGkgPj0gMDsgaS0tKSB7XG4gICAgbmV3X2FjYyA9IGZ1bmMobGlzdFtpXSwgbmV3X2FjYyk7XG4gIH1cblxuICByZXR1cm4gbmV3X2FjYztcbn07XG5cbkxpc3QuaW5zZXJ0X2F0ID0gZnVuY3Rpb24gKGxpc3QsIGluZGV4LCB2YWx1ZSkge1xuICBsZXQgbmV3X3ZhbHVlID0gW107XG5cbiAgZm9yIChsZXQgaSA9IDA7IGkgPCBsaXN0Lmxlbmd0aDsgaSsrKSB7XG4gICAgaWYgKGkgPT09IGluZGV4KSB7XG4gICAgICBuZXdfdmFsdWUucHVzaCh2YWx1ZSk7XG4gICAgICBuZXdfdmFsdWUucHVzaChsaXN0W2ldKTtcbiAgICB9IGVsc2Uge1xuICAgICAgbmV3X3ZhbHVlLnB1c2gobGlzdFtpXSk7XG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIExpc3QkMSguLi5uZXdfdmFsdWUpO1xufTtcblxuTGlzdC5rZXlkZWxldGUgPSBmdW5jdGlvbiAobGlzdCwga2V5LCBwb3NpdGlvbikge1xuICBsZXQgbmV3X2xpc3QgPSBbXTtcblxuICBmb3IgKGxldCBpID0gMDsgaSA8IGxpc3QubGVuZ3RoOyBpKyspIHtcbiAgICBpZiAoIUtlcm5lbC5tYXRjaF9fcW1hcmtfXyhsaXN0W2ldW3Bvc2l0aW9uXSwga2V5KSkge1xuICAgICAgbmV3X2xpc3QucHVzaChsaXN0W2ldKTtcbiAgICB9XG4gIH1cblxuICByZXR1cm4gTGlzdCQxKC4uLm5ld19saXN0KTtcbn07XG5cbkxpc3Qua2V5ZmluZCA9IGZ1bmN0aW9uIChsaXN0LCBrZXksIHBvc2l0aW9uLCBfZGVmYXVsdCA9IG51bGwpIHtcblxuICBmb3IgKGxldCBpID0gMDsgaSA8IGxpc3QubGVuZ3RoOyBpKyspIHtcbiAgICBpZiAoS2VybmVsLm1hdGNoX19xbWFya19fKGxpc3RbaV1bcG9zaXRpb25dLCBrZXkpKSB7XG4gICAgICByZXR1cm4gbGlzdFtpXTtcbiAgICB9XG4gIH1cblxuICByZXR1cm4gX2RlZmF1bHQ7XG59O1xuXG5MaXN0LmtleW1lbWJlcl9fcW1hcmtfXyA9IGZ1bmN0aW9uIChsaXN0LCBrZXksIHBvc2l0aW9uKSB7XG5cbiAgZm9yIChsZXQgaSA9IDA7IGkgPCBsaXN0Lmxlbmd0aDsgaSsrKSB7XG4gICAgaWYgKEtlcm5lbC5tYXRjaF9fcW1hcmtfXyhsaXN0W2ldW3Bvc2l0aW9uXSwga2V5KSkge1xuICAgICAgcmV0dXJuIHRydWU7XG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIGZhbHNlO1xufTtcblxuTGlzdC5rZXlyZXBsYWNlID0gZnVuY3Rpb24gKGxpc3QsIGtleSwgcG9zaXRpb24sIG5ld190dXBsZSkge1xuICBsZXQgbmV3X2xpc3QgPSBbXTtcblxuICBmb3IgKGxldCBpID0gMDsgaSA8IGxpc3QubGVuZ3RoOyBpKyspIHtcbiAgICBpZiAoIUtlcm5lbC5tYXRjaF9fcW1hcmtfXyhsaXN0W2ldW3Bvc2l0aW9uXSwga2V5KSkge1xuICAgICAgbmV3X2xpc3QucHVzaChsaXN0W2ldKTtcbiAgICB9IGVsc2Uge1xuICAgICAgbmV3X2xpc3QucHVzaChuZXdfdHVwbGUpO1xuICAgIH1cbiAgfVxuXG4gIHJldHVybiBMaXN0JDEoLi4ubmV3X2xpc3QpO1xufTtcblxuTGlzdC5rZXlzb3J0ID0gZnVuY3Rpb24gKGxpc3QsIHBvc2l0aW9uKSB7XG4gIGxldCBuZXdfbGlzdCA9IGxpc3Q7XG5cbiAgbmV3X2xpc3Quc29ydChmdW5jdGlvbiAoYSwgYikge1xuICAgIGlmIChwb3NpdGlvbiA9PT0gMCkge1xuICAgICAgaWYgKGFbcG9zaXRpb25dLnZhbHVlIDwgYltwb3NpdGlvbl0udmFsdWUpIHtcbiAgICAgICAgcmV0dXJuIC0xO1xuICAgICAgfVxuXG4gICAgICBpZiAoYVtwb3NpdGlvbl0udmFsdWUgPiBiW3Bvc2l0aW9uXS52YWx1ZSkge1xuICAgICAgICByZXR1cm4gMTtcbiAgICAgIH1cblxuICAgICAgcmV0dXJuIDA7XG4gICAgfSBlbHNlIHtcbiAgICAgIGlmIChhW3Bvc2l0aW9uXSA8IGJbcG9zaXRpb25dKSB7XG4gICAgICAgIHJldHVybiAtMTtcbiAgICAgIH1cblxuICAgICAgaWYgKGFbcG9zaXRpb25dID4gYltwb3NpdGlvbl0pIHtcbiAgICAgICAgcmV0dXJuIDE7XG4gICAgICB9XG5cbiAgICAgIHJldHVybiAwO1xuICAgIH1cbiAgfSk7XG5cbiAgcmV0dXJuIExpc3QkMSguLi5uZXdfbGlzdCk7XG59O1xuXG5MaXN0LmtleXN0b3JlID0gZnVuY3Rpb24gKGxpc3QsIGtleSwgcG9zaXRpb24sIG5ld190dXBsZSkge1xuICBsZXQgbmV3X2xpc3QgPSBbXTtcbiAgbGV0IHJlcGxhY2VkID0gZmFsc2U7XG5cbiAgZm9yIChsZXQgaSA9IDA7IGkgPCBsaXN0Lmxlbmd0aDsgaSsrKSB7XG4gICAgaWYgKCFLZXJuZWwubWF0Y2hfX3FtYXJrX18obGlzdFtpXVtwb3NpdGlvbl0sIGtleSkpIHtcbiAgICAgIG5ld19saXN0LnB1c2gobGlzdFtpXSk7XG4gICAgfSBlbHNlIHtcbiAgICAgIG5ld19saXN0LnB1c2gobmV3X3R1cGxlKTtcbiAgICAgIHJlcGxhY2VkID0gdHJ1ZTtcbiAgICB9XG4gIH1cblxuICBpZiAoIXJlcGxhY2VkKSB7XG4gICAgbmV3X2xpc3QucHVzaChuZXdfdHVwbGUpO1xuICB9XG5cbiAgcmV0dXJuIExpc3QkMSguLi5uZXdfbGlzdCk7XG59O1xuXG5MaXN0Lmxhc3QgPSBmdW5jdGlvbiAobGlzdCkge1xuICByZXR1cm4gbGlzdFtsaXN0Lmxlbmd0aCAtIDFdO1xufTtcblxuTGlzdC5yZXBsYWNlX2F0ID0gZnVuY3Rpb24gKGxpc3QsIGluZGV4LCB2YWx1ZSkge1xuICBsZXQgbmV3X3ZhbHVlID0gW107XG5cbiAgZm9yIChsZXQgaSA9IDA7IGkgPCBsaXN0Lmxlbmd0aDsgaSsrKSB7XG4gICAgaWYgKGkgPT09IGluZGV4KSB7XG4gICAgICBuZXdfdmFsdWUucHVzaCh2YWx1ZSk7XG4gICAgfSBlbHNlIHtcbiAgICAgIG5ld192YWx1ZS5wdXNoKGxpc3RbaV0pO1xuICAgIH1cbiAgfVxuXG4gIHJldHVybiBMaXN0JDEoLi4ubmV3X3ZhbHVlKTtcbn07XG5cbkxpc3QudXBkYXRlX2F0ID0gZnVuY3Rpb24gKGxpc3QsIGluZGV4LCBmdW4pIHtcbiAgbGV0IG5ld192YWx1ZSA9IFtdO1xuXG4gIGZvciAobGV0IGkgPSAwOyBpIDwgbGlzdC5jb3VudCgpOyBpKyspIHtcbiAgICBpZiAoaSA9PT0gaW5kZXgpIHtcbiAgICAgIG5ld192YWx1ZS5wdXNoKGZ1bihsaXN0LmdldChpKSkpO1xuICAgIH0gZWxzZSB7XG4gICAgICBuZXdfdmFsdWUucHVzaChsaXN0LmdldChpKSk7XG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIG5ld192YWx1ZTtcbn07XG5cbkxpc3Qud3JhcCA9IGZ1bmN0aW9uIChsaXN0KSB7XG4gIGlmIChLZXJuZWwuaXNfbGlzdChsaXN0KSkge1xuICAgIHJldHVybiBsaXN0O1xuICB9IGVsc2UgaWYgKGxpc3QgPT0gbnVsbCkge1xuICAgIHJldHVybiBMaXN0JDEoKTtcbiAgfSBlbHNlIHtcbiAgICByZXR1cm4gTGlzdCQxKGxpc3QpO1xuICB9XG59O1xuXG5MaXN0LnppcCA9IGZ1bmN0aW9uIChsaXN0X29mX2xpc3RzKSB7XG4gIGlmIChsaXN0X29mX2xpc3RzLmxlbmd0aCA9PT0gMCkge1xuICAgIHJldHVybiBMaXN0JDEoKTtcbiAgfVxuXG4gIGxldCBuZXdfdmFsdWUgPSBbXTtcbiAgbGV0IHNtYWxsZXN0X2xlbmd0aCA9IGxpc3Rfb2ZfbGlzdHNbMF07XG5cbiAgZm9yIChsZXQgeCBvZiBsaXN0X29mX2xpc3RzKSB7XG4gICAgaWYgKHgubGVuZ3RoIDwgc21hbGxlc3RfbGVuZ3RoKSB7XG4gICAgICBzbWFsbGVzdF9sZW5ndGggPSB4Lmxlbmd0aDtcbiAgICB9XG4gIH1cblxuICBmb3IgKGxldCBpID0gMDsgaSA8IHNtYWxsZXN0X2xlbmd0aDsgaSsrKSB7XG4gICAgbGV0IGN1cnJlbnRfdmFsdWUgPSBbXTtcbiAgICBmb3IgKGxldCBqID0gMDsgaiA8IGxpc3Rfb2ZfbGlzdHMubGVuZ3RoOyBqKyspIHtcbiAgICAgIGN1cnJlbnRfdmFsdWUucHVzaChsaXN0X29mX2xpc3RzW2pdW2ldKTtcbiAgICB9XG5cbiAgICBuZXdfdmFsdWUucHVzaChuZXcgVHVwbGUoLi4uY3VycmVudF92YWx1ZSkpO1xuICB9XG5cbiAgcmV0dXJuIExpc3QkMSguLi5uZXdfdmFsdWUpO1xufTtcblxuTGlzdC50b190dXBsZSA9IGZ1bmN0aW9uIChsaXN0KSB7XG4gIHJldHVybiBuZXcgVHVwbGUoLi4ubGlzdCk7XG59O1xuXG5MaXN0LmFwcGVuZCA9IGZ1bmN0aW9uIChsaXN0LCB2YWx1ZSkge1xuICByZXR1cm4gTGlzdCQxKC4uLmxpc3QuY29uY2F0KFt2YWx1ZV0pKTtcbn07XG5cbkxpc3QucHJlcGVuZCA9IGZ1bmN0aW9uIChsaXN0LCB2YWx1ZSkge1xuICByZXR1cm4gTGlzdCQxKC4uLlt2YWx1ZV0uY29uY2F0KGxpc3QpKTtcbn07XG5cbkxpc3QuY29uY2F0ID0gZnVuY3Rpb24gKGxlZnQsIHJpZ2h0KSB7XG4gIHJldHVybiBsZWZ0LmNvbmNhdChyaWdodCk7XG59O1xuXG5sZXQgS2V5d29yZCA9IHt9O1xuXG5LZXl3b3JkLmhhc19rZXlfX3FtYXJrX18gPSBmdW5jdGlvbiAoa2V5d29yZHMsIGtleSkge1xuICBmb3IgKGxldCBrZXl3b3JkIG9mIGtleXdvcmRzKSB7XG4gICAgaWYgKEtlcm5lbC5lbGVtKGtleXdvcmQsIDApID09IGtleSkge1xuICAgICAgcmV0dXJuIHRydWU7XG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIGZhbHNlO1xufTtcblxuS2V5d29yZC5nZXQgPSBmdW5jdGlvbiAoa2V5d29yZHMsIGtleSwgdGhlX2RlZmF1bHQgPSBudWxsKSB7XG4gIGZvciAobGV0IGtleXdvcmQgb2Yga2V5d29yZHMpIHtcbiAgICBpZiAoS2VybmVsLmVsZW0oa2V5d29yZCwgMCkgPT0ga2V5KSB7XG4gICAgICByZXR1cm4gS2VybmVsLmVsZW0oa2V5d29yZCwgMSk7XG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIHRoZV9kZWZhdWx0O1xufTtcblxuZnVuY3Rpb24gYm5vdChleHByKSB7XG4gIHJldHVybiB+ZXhwcjtcbn1cblxuZnVuY3Rpb24gYmFuZChsZWZ0LCByaWdodCkge1xuICByZXR1cm4gbGVmdCAmIHJpZ2h0O1xufVxuXG5mdW5jdGlvbiBib3IobGVmdCwgcmlnaHQpIHtcbiAgcmV0dXJuIGxlZnQgfCByaWdodDtcbn1cblxuZnVuY3Rpb24gYnNsKGxlZnQsIHJpZ2h0KSB7XG4gIHJldHVybiBsZWZ0IDw8IHJpZ2h0O1xufVxuXG5mdW5jdGlvbiBic3IobGVmdCwgcmlnaHQpIHtcbiAgcmV0dXJuIGxlZnQgPj4gcmlnaHQ7XG59XG5cbmZ1bmN0aW9uIGJ4b3IobGVmdCwgcmlnaHQpIHtcbiAgcmV0dXJuIGxlZnQgXiByaWdodDtcbn1cblxudmFyIGJpdHdpc2UgPSB7XG4gIGJub3QsXG4gIGJhbmQsXG4gIGJvcixcbiAgYnNsLFxuICBic3IsXG4gIGJ4b3Jcbn07XG5cbmZ1bmN0aW9uIF9fbmV3X18oKSB7XG4gIHJldHVybiBTcGVjaWFsRm9ybXMkMS5tYXAoe30pO1xufVxuXG5mdW5jdGlvbiBrZXlzKG1hcCkge1xuICByZXR1cm4gRnVuY3Rpb25zLmdldF9vYmplY3Rfa2V5cyhtYXApO1xufVxuXG5mdW5jdGlvbiBzaXplKG1hcCkge1xuICByZXR1cm4ga2V5cyhtYXApLmxlbmd0aDtcbn1cblxuZnVuY3Rpb24gdG9fbGlzdChtYXApIHtcbiAgbGV0IG1hcF9rZXlzID0ga2V5cyhtYXApO1xuICBsZXQgbGlzdCA9IFtdO1xuXG4gIGZvciAobGV0IGtleSBvZiBtYXBfa2V5cykge1xuICAgIGxpc3QucHVzaChuZXcgVHVwbGUoa2V5LCBtYXBba2V5XSkpO1xuICB9XG5cbiAgcmV0dXJuIExpc3QkMSguLi5saXN0KTtcbn1cblxuZnVuY3Rpb24gdmFsdWVzKG1hcCkge1xuICBsZXQgbWFwX2tleXMgPSBrZXlzKG1hcCk7XG4gIGxldCBsaXN0ID0gW107XG5cbiAgZm9yIChsZXQga2V5IG9mIG1hcF9rZXlzKSB7XG4gICAgbGlzdC5wdXNoKG1hcFtrZXldKTtcbiAgfVxuXG4gIHJldHVybiBMaXN0JDEoLi4ubGlzdCk7XG59XG5cbmZ1bmN0aW9uIGZyb21fc3RydWN0KHN0cnVjdCkge1xuICBsZXQgbWFwID0gT2JqZWN0LmFzc2lnbih7fSwgc3RydWN0KTtcbiAgZGVsZXRlIG1hcFtTeW1ib2wuZm9yKCdfX3N0cnVjdF9fJyldO1xuXG4gIHJldHVybiBTcGVjaWFsRm9ybXMkMS5tYXAobWFwKTtcbn1cblxuZnVuY3Rpb24gX19kZWxldGVfXyhtYXAsIGtleSkge1xuICBsZXQgbmV3X21hcCA9IE9iamVjdC5hc3NpZ24oe30sIG1hcCk7XG5cbiAgZGVsZXRlIG5ld19tYXBba2V5XTtcblxuICByZXR1cm4gU3BlY2lhbEZvcm1zJDEubWFwKG5ld19tYXApO1xufVxuXG5mdW5jdGlvbiBlcXVhbF9fcW1hcmtfXyhtYXAxLCBtYXAyKSB7XG4gIHJldHVybiBtYXAxID09PSBtYXAyO1xufVxuXG5mdW5jdGlvbiBmZXRjaF9fZW1hcmtfXyhtYXAsIGtleSkge1xuICBpZiAoa2V5IGluIG1hcCkge1xuICAgIHJldHVybiBtYXBba2V5XTtcbiAgfVxuXG4gIHRocm93IG5ldyBFcnJvcignS2V5IG5vdCBmb3VuZC4nKTtcbn1cblxuZnVuY3Rpb24gZmV0Y2gobWFwLCBrZXkpIHtcbiAgaWYgKGtleSBpbiBtYXApIHtcbiAgICByZXR1cm4gbmV3IFR1cGxlKFN5bWJvbC5mb3IoJ29rJyksIG1hcFtrZXldKTtcbiAgfVxuXG4gIHJldHVybiBTeW1ib2wuZm9yKCdlcnJvcicpO1xufVxuXG5mdW5jdGlvbiBoYXNfa2V5X19xbWFya19fKG1hcCwga2V5KSB7XG4gIHJldHVybiBrZXkgaW4gbWFwO1xufVxuXG5mdW5jdGlvbiBzcGxpdChtYXAsIGtleXMpIHtcbiAgbGV0IHNwbGl0MSA9IHt9O1xuICBsZXQgc3BsaXQyID0ge307XG5cbiAgZm9yIChsZXQga2V5IG9mIEZ1bmN0aW9ucy5nZXRfb2JqZWN0X2tleXMobWFwKSkge1xuICAgIGlmIChrZXlzLmluZGV4T2Yoa2V5KSA+IC0xKSB7XG4gICAgICBzcGxpdDFba2V5XSA9IG1hcFtrZXldO1xuICAgIH0gZWxzZSB7XG4gICAgICBzcGxpdDJba2V5XSA9IG1hcFtrZXldO1xuICAgIH1cbiAgfVxuXG4gIHJldHVybiBuZXcgVHVwbGUoU3BlY2lhbEZvcm1zJDEubWFwKHNwbGl0MSksIFNwZWNpYWxGb3JtcyQxLm1hcChzcGxpdDIpKTtcbn1cblxuZnVuY3Rpb24gdGFrZShtYXAsIGtleXMpIHtcbiAgbGV0IHNwbGl0MSA9IHt9O1xuXG4gIGZvciAobGV0IGtleSBvZiBGdW5jdGlvbnMuZ2V0X29iamVjdF9rZXlzKG1hcCkpIHtcbiAgICBpZiAoa2V5cy5pbmRleE9mKGtleSkgPiAtMSkge1xuICAgICAgc3BsaXQxW2tleV0gPSBtYXBba2V5XTtcbiAgICB9XG4gIH1cblxuICByZXR1cm4gU3BlY2lhbEZvcm1zJDEubWFwKHNwbGl0MSk7XG59XG5cbmZ1bmN0aW9uIGRyb3AobWFwLCBrZXlzKSB7XG4gIGxldCBzcGxpdDEgPSB7fTtcblxuICBmb3IgKGxldCBrZXkgb2YgRnVuY3Rpb25zLmdldF9vYmplY3Rfa2V5cyhtYXApKSB7XG4gICAgaWYgKGtleXMuaW5kZXhPZihrZXkpID09PSAtMSkge1xuICAgICAgc3BsaXQxW2tleV0gPSBtYXBba2V5XTtcbiAgICB9XG4gIH1cblxuICByZXR1cm4gU3BlY2lhbEZvcm1zJDEubWFwKHNwbGl0MSk7XG59XG5cbmZ1bmN0aW9uIHB1dF9uZXcobWFwLCBrZXksIHZhbHVlKSB7XG4gIGlmIChrZXkgaW4gbWFwKSB7XG4gICAgcmV0dXJuIG1hcDtcbiAgfVxuXG4gIGxldCBuZXdfbWFwID0gT2JqZWN0LmFzc2lnbih7fSwgbWFwKTtcbiAgbmV3X21hcFtrZXldID0gdmFsdWU7XG5cbiAgcmV0dXJuIFNwZWNpYWxGb3JtcyQxLm1hcChuZXdfbWFwKTtcbn1cblxuZnVuY3Rpb24gcHV0X25ld19sYXp5KG1hcCwga2V5LCBmdW4pIHtcbiAgaWYgKGtleSBpbiBtYXApIHtcbiAgICByZXR1cm4gbWFwO1xuICB9XG5cbiAgbGV0IG5ld19tYXAgPSBPYmplY3QuYXNzaWduKHt9LCBtYXApO1xuICBuZXdfbWFwW2tleV0gPSBmdW4oKTtcblxuICByZXR1cm4gU3BlY2lhbEZvcm1zJDEubWFwKG5ld19tYXApO1xufVxuXG5mdW5jdGlvbiBnZXRfYW5kX3VwZGF0ZShtYXAsIGtleSwgZnVuKSB7XG4gIGlmIChrZXkgaW4gbWFwKSB7XG4gICAgcmV0dXJuIG1hcDtcbiAgfVxuXG4gIGxldCBuZXdfbWFwID0gT2JqZWN0LmFzc2lnbih7fSwgbWFwKTtcbiAgbmV3X21hcFtrZXldID0gZnVuKG1hcFtrZXldKTtcblxuICByZXR1cm4gU3BlY2lhbEZvcm1zJDEubWFwKG5ld19tYXApO1xufVxuXG5mdW5jdGlvbiBwb3BfbGF6eShtYXAsIGtleSwgZnVuKSB7XG4gIGlmICgha2V5IGluIG1hcCkge1xuICAgIHJldHVybiBuZXcgVHVwbGUoZnVuKCksIG1hcCk7XG4gIH1cblxuICBsZXQgbmV3X21hcCA9IE9iamVjdC5hc3NpZ24oe30sIG1hcCk7XG4gIGxldCB2YWx1ZSA9IGZ1bihuZXdfbWFwW2tleV0pO1xuICBkZWxldGUgbmV3X21hcFtrZXldO1xuXG4gIHJldHVybiBuZXcgVHVwbGUodmFsdWUsIG5ld19tYXApO1xufVxuXG5mdW5jdGlvbiBwb3AobWFwLCBrZXksIF9kZWZhdWx0ID0gbnVsbCkge1xuICBpZiAoIWtleSBpbiBtYXApIHtcbiAgICByZXR1cm4gbmV3IFR1cGxlKF9kZWZhdWx0LCBtYXApO1xuICB9XG5cbiAgbGV0IG5ld19tYXAgPSBPYmplY3QuYXNzaWduKHt9LCBtYXApO1xuICBsZXQgdmFsdWUgPSBuZXdfbWFwW2tleV07XG4gIGRlbGV0ZSBuZXdfbWFwW2tleV07XG5cbiAgcmV0dXJuIG5ldyBUdXBsZSh2YWx1ZSwgbmV3X21hcCk7XG59XG5cbmZ1bmN0aW9uIGdldF9sYXp5KG1hcCwga2V5LCBmdW4pIHtcbiAgaWYgKCFrZXkgaW4gbWFwKSB7XG4gICAgcmV0dXJuIGZ1bigpO1xuICB9XG5cbiAgcmV0dXJuIGZ1bihtYXBba2V5XSk7XG59XG5cbmZ1bmN0aW9uIGdldChtYXAsIGtleSwgX2RlZmF1bHQgPSBudWxsKSB7XG4gIGlmICgha2V5IGluIG1hcCkge1xuICAgIHJldHVybiBfZGVmYXVsdDtcbiAgfVxuXG4gIHJldHVybiBtYXBba2V5XTtcbn1cblxuZnVuY3Rpb24gcHV0KG1hcCwga2V5LCB2YWwpIHtcbiAgbGV0IG5ld19tYXAgPSBPYmplY3Qoe30sIG1hcCk7XG4gIG5ld19tYXBba2V5XSA9IHZhbDtcblxuICByZXR1cm4gU3BlY2lhbEZvcm1zJDEubWFwKG5ld19tYXApO1xufVxuXG5mdW5jdGlvbiB1cGRhdGVfX2VtYXJrX18obWFwLCBrZXksIGZ1bikge1xuICBpZiAoIWtleSBpbiBtYXApIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoJ0tleSBub3QgZm91bmQnKTtcbiAgfVxuXG4gIGxldCBuZXdfbWFwID0gT2JqZWN0KHt9LCBtYXApO1xuICBuZXdfbWFwW2tleV0gPSBmdW4obWFwW2tleV0pO1xuXG4gIHJldHVybiBTcGVjaWFsRm9ybXMkMS5tYXAobmV3X21hcCk7XG59XG5cbmZ1bmN0aW9uIHVwZGF0ZShtYXAsIGtleSwgaW5pdGlhbCwgZnVuKSB7XG4gIGxldCBuZXdfbWFwID0gT2JqZWN0KHt9LCBtYXApO1xuXG4gIGlmICgha2V5IGluIG1hcCkge1xuICAgIG5ld19tYXBba2V5XSA9IGluaXRpYWw7XG4gIH0gZWxzZSB7XG4gICAgbmV3X21hcFtrZXldID0gZnVuKG1hcFtrZXldKTtcbiAgfVxuXG4gIHJldHVybiBTcGVjaWFsRm9ybXMkMS5tYXAobmV3X21hcCk7XG59XG5cbnZhciBtYXAgPSB7XG4gIG5ldzogX19uZXdfXyxcbiAga2V5cyxcbiAgc2l6ZSxcbiAgdG9fbGlzdCxcbiAgdmFsdWVzLFxuICBmcm9tX3N0cnVjdCxcbiAgZGVsZXRlOiBfX2RlbGV0ZV9fLFxuICBkcm9wLFxuICBlcXVhbF9fcW1hcmtfXyxcbiAgZmV0Y2hfX2VtYXJrX18sXG4gIGZldGNoLFxuICBoYXNfa2V5X19xbWFya19fLFxuICBzcGxpdCxcbiAgdGFrZSxcbiAgcHV0X25ldyxcbiAgcHV0X25ld19sYXp5LFxuICBnZXRfYW5kX3VwZGF0ZSxcbiAgcG9wX2xhenksXG4gIHBvcCxcbiAgZ2V0X2xhenksXG4gIGdldCxcbiAgcHV0LFxuICB1cGRhdGVfX2VtYXJrX18sXG4gIHVwZGF0ZVxufTtcblxuZnVuY3Rpb24gX19uZXdfXyQxKCkge1xuICByZXR1cm4gU3BlY2lhbEZvcm1zJDEubWFwKHsgW1N5bWJvbC5mb3IoJ19fc3RydWN0X18nKV06IFN5bWJvbC5mb3IoJ01hcFNldCcpLCBzZXQ6IExpc3QkMSgpIH0pO1xufVxuXG5mdW5jdGlvbiBzaXplJDEobWFwKSB7XG4gIHJldHVybiBtYXAuc2V0Lmxlbmd0aDtcbn1cblxuZnVuY3Rpb24gdG9fbGlzdCQxKG1hcCkge1xuICByZXR1cm4gbWFwLnNldDtcbn1cblxuZnVuY3Rpb24gX19kZWxldGVfXyQxKHNldCwgdGVybSkge1xuICBsZXQgbmV3X2xpc3QgPSBMaXN0LmRlbGV0ZShzZXQuc2V0LCB0ZXJtKTtcblxuICBsZXQgbmV3X21hcCA9IE9iamVjdC5hc3NpZ24oe30sIHNldCk7XG4gIG5ld19tYXAuc2V0ID0gbmV3X2xpc3Q7XG4gIHJldHVybiBTcGVjaWFsRm9ybXMkMS5tYXAobmV3X21hcCk7XG59XG5cbmZ1bmN0aW9uIHB1dCQxKHNldCwgdGVybSkge1xuICBpZiAoc2V0LnNldC5pbmRleE9mKHRlcm0pID09PSAtMSkge1xuICAgIGxldCBuZXdfbGlzdCA9IExpc3QuYXBwZW5kKHNldC5zZXQsIHRlcm0pO1xuXG4gICAgbGV0IG5ld19tYXAgPSBPYmplY3QuYXNzaWduKHt9LCBzZXQpO1xuICAgIG5ld19tYXAuc2V0ID0gbmV3X2xpc3Q7XG4gICAgcmV0dXJuIFNwZWNpYWxGb3JtcyQxLm1hcChuZXdfbWFwKTtcbiAgfVxuXG4gIHJldHVybiBzZXQ7XG59XG5cbmZ1bmN0aW9uIGRpZmZlcmVuY2Uoc2V0MSwgc2V0Mikge1xuICBsZXQgbmV3X21hcCA9IE9iamVjdC5hc3NpZ24oe30sIHNldDEpO1xuXG4gIGZvciAobGV0IHZhbCBvZiBzZXQxLnNldCkge1xuICAgIGlmIChtZW1iZXJfX3FtYXJrX18oc2V0MiwgdmFsKSkge1xuICAgICAgbmV3X21hcC5zZXQgPSBMaXN0LmRlbGV0ZShuZXdfbWFwLnNldCwgdmFsKTtcbiAgICB9XG4gIH1cblxuICByZXR1cm4gU3BlY2lhbEZvcm1zJDEubWFwKG5ld19tYXApO1xufVxuXG5mdW5jdGlvbiBpbnRlcnNlY3Rpb24oc2V0MSwgc2V0Mikge1xuICBsZXQgbmV3X21hcCA9IE9iamVjdC5hc3NpZ24oe30sIHNldDEpO1xuXG4gIGZvciAobGV0IHZhbCBvZiBzZXQxLnNldCkge1xuICAgIGlmICghbWVtYmVyX19xbWFya19fKHNldDIsIHZhbCkpIHtcbiAgICAgIG5ld19tYXAuc2V0ID0gTGlzdC5kZWxldGUobmV3X21hcC5zZXQsIHZhbCk7XG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIFNwZWNpYWxGb3JtcyQxLm1hcChuZXdfbWFwKTtcbn1cblxuZnVuY3Rpb24gdW5pb24oc2V0MSwgc2V0Mikge1xuICBsZXQgbmV3X21hcCA9IHNldDE7XG5cbiAgZm9yIChsZXQgdmFsIG9mIHNldDIuc2V0KSB7XG4gICAgbmV3X21hcCA9IHB1dCQxKG5ld19tYXAsIHZhbCk7XG4gIH1cblxuICByZXR1cm4gU3BlY2lhbEZvcm1zJDEubWFwKG5ld19tYXApO1xufVxuXG5mdW5jdGlvbiBkaXNqb2luX19xbWFya19fKHNldDEsIHNldDIpIHtcbiAgZm9yIChsZXQgdmFsIG9mIHNldDEuc2V0KSB7XG4gICAgaWYgKG1lbWJlcl9fcW1hcmtfXyhzZXQyLCB2YWwpKSB7XG4gICAgICByZXR1cm4gZmFsc2U7XG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIHRydWU7XG59XG5cbmZ1bmN0aW9uIG1lbWJlcl9fcW1hcmtfXyhzZXQsIHZhbHVlKSB7XG4gIHJldHVybiBzZXQuc2V0LmluZGV4T2YodmFsdWUpID49IDA7XG59XG5cbmZ1bmN0aW9uIGVxdWFsX19xbWFya19fJDEoc2V0MSwgc2V0Mikge1xuICByZXR1cm4gc2V0MS5zZXQgPT09IHNldDIuc2V0O1xufVxuXG5mdW5jdGlvbiBzdWJzZXRfX3FtYXJrX18oc2V0MSwgc2V0Mikge1xuICBmb3IgKGxldCB2YWwgb2Ygc2V0MS5zZXQpIHtcbiAgICBpZiAoIW1lbWJlcl9fcW1hcmtfXyhzZXQyLCB2YWwpKSB7XG4gICAgICByZXR1cm4gZmFsc2U7XG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIHRydWU7XG59XG5cbnZhciBtYXBfc2V0ID0ge1xuICBuZXc6IF9fbmV3X18kMSxcbiAgc2l6ZTogc2l6ZSQxLFxuICB0b19saXN0OiB0b19saXN0JDEsXG4gIGRpc2pvaW5fX3FtYXJrX18sXG4gIGRlbGV0ZTogX19kZWxldGVfXyQxLFxuICBzdWJzZXRfX3FtYXJrX18sXG4gIGVxdWFsX19xbWFya19fOiBlcXVhbF9fcW1hcmtfXyQxLFxuICBtZW1iZXJfX3FtYXJrX18sXG4gIHB1dDogcHV0JDEsXG4gIHVuaW9uLFxuICBpbnRlcnNlY3Rpb24sXG4gIGRpZmZlcmVuY2Vcbn07XG5cbmxldCBWaXJ0dWFsRE9NID0gKGZ1bmN0aW9uIChlKSB7XG4gICAgcmV0dXJuIGUoKTtcbn0pKGZ1bmN0aW9uICgpIHtcbiAgICB2YXIgZGVmaW5lLCBtb2R1bGUsIGV4cG9ydHM7XG4gICAgcmV0dXJuIChmdW5jdGlvbiBlKHQsIG4sIHIpIHtcbiAgICAgICAgZnVuY3Rpb24gcyhvLCB1KSB7XG4gICAgICAgICAgICBpZiAoIW5bb10pIHtcbiAgICAgICAgICAgICAgICBpZiAoIXRbb10pIHtcbiAgICAgICAgICAgICAgICAgICAgdmFyIGEgPSB0eXBlb2YgcmVxdWlyZSA9PSBcImZ1bmN0aW9uXCIgJiYgcmVxdWlyZTtcbiAgICAgICAgICAgICAgICAgICAgaWYgKCF1ICYmIGEpIHJldHVybiBhKG8sICEwKTtcbiAgICAgICAgICAgICAgICAgICAgaWYgKGkpIHJldHVybiBpKG8sICEwKTtcbiAgICAgICAgICAgICAgICAgICAgdmFyIGYgPSBuZXcgRXJyb3IoXCJDYW5ub3QgZmluZCBtb2R1bGUgJ1wiICsgbyArIFwiJ1wiKTtcbiAgICAgICAgICAgICAgICAgICAgdGhyb3cgKGYuY29kZSA9IFwiTU9EVUxFX05PVF9GT1VORFwiLCBmKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgdmFyIGwgPSBuW29dID0ge1xuICAgICAgICAgICAgICAgICAgICBleHBvcnRzOiB7fVxuICAgICAgICAgICAgICAgIH07XG4gICAgICAgICAgICAgICAgdFtvXVswXS5jYWxsKGwuZXhwb3J0cywgZnVuY3Rpb24gKGUpIHtcbiAgICAgICAgICAgICAgICAgICAgdmFyIG4gPSB0W29dWzFdW2VdO1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gcyhuID8gbiA6IGUpO1xuICAgICAgICAgICAgICAgIH0sIGwsIGwuZXhwb3J0cywgZSwgdCwgbiwgcik7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXR1cm4gbltvXS5leHBvcnRzO1xuICAgICAgICB9XG4gICAgICAgIHZhciBpID0gdHlwZW9mIHJlcXVpcmUgPT0gXCJmdW5jdGlvblwiICYmIHJlcXVpcmU7XG4gICAgICAgIGZvciAodmFyIG8gPSAwOyBvIDwgci5sZW5ndGg7IG8rKykgcyhyW29dKTtcbiAgICAgICAgcmV0dXJuIHM7XG4gICAgfSkoe1xuICAgICAgICAxOiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge1xuXG4gICAgICAgICAgICB2YXIgY3JlYXRlRWxlbWVudCA9IHJlcXVpcmUoXCIuL3Zkb20vY3JlYXRlLWVsZW1lbnQuanNcIik7XG5cbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gY3JlYXRlRWxlbWVudDtcbiAgICAgICAgfSwgeyBcIi4vdmRvbS9jcmVhdGUtZWxlbWVudC5qc1wiOiAxNSB9XSwgMjogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHtcbiAgICAgICAgICAgIHZhciBkaWZmID0gcmVxdWlyZShcIi4vdnRyZWUvZGlmZi5qc1wiKTtcblxuICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBkaWZmO1xuICAgICAgICB9LCB7IFwiLi92dHJlZS9kaWZmLmpzXCI6IDM1IH1dLCAzOiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge1xuICAgICAgICAgICAgdmFyIGggPSByZXF1aXJlKFwiLi92aXJ0dWFsLWh5cGVyc2NyaXB0L2luZGV4LmpzXCIpO1xuXG4gICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IGg7XG4gICAgICAgIH0sIHsgXCIuL3ZpcnR1YWwtaHlwZXJzY3JpcHQvaW5kZXguanNcIjogMjIgfV0sIDQ6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICB2YXIgZGlmZiA9IHJlcXVpcmUoXCIuL2RpZmYuanNcIik7XG4gICAgICAgICAgICB2YXIgcGF0Y2ggPSByZXF1aXJlKFwiLi9wYXRjaC5qc1wiKTtcbiAgICAgICAgICAgIHZhciBoID0gcmVxdWlyZShcIi4vaC5qc1wiKTtcbiAgICAgICAgICAgIHZhciBjcmVhdGUgPSByZXF1aXJlKFwiLi9jcmVhdGUtZWxlbWVudC5qc1wiKTtcbiAgICAgICAgICAgIHZhciBWTm9kZSA9IHJlcXVpcmUoXCIuL3Zub2RlL3Zub2RlLmpzXCIpO1xuICAgICAgICAgICAgdmFyIFZUZXh0ID0gcmVxdWlyZShcIi4vdm5vZGUvdnRleHQuanNcIik7XG5cbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0ge1xuICAgICAgICAgICAgICAgIGRpZmY6IGRpZmYsXG4gICAgICAgICAgICAgICAgcGF0Y2g6IHBhdGNoLFxuICAgICAgICAgICAgICAgIGg6IGgsXG4gICAgICAgICAgICAgICAgY3JlYXRlOiBjcmVhdGUsXG4gICAgICAgICAgICAgICAgVk5vZGU6IFZOb2RlLFxuICAgICAgICAgICAgICAgIFZUZXh0OiBWVGV4dFxuICAgICAgICAgICAgfTtcbiAgICAgICAgfSwgeyBcIi4vY3JlYXRlLWVsZW1lbnQuanNcIjogMSwgXCIuL2RpZmYuanNcIjogMiwgXCIuL2guanNcIjogMywgXCIuL3BhdGNoLmpzXCI6IDEzLCBcIi4vdm5vZGUvdm5vZGUuanNcIjogMzEsIFwiLi92bm9kZS92dGV4dC5qc1wiOiAzMyB9XSwgNTogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHtcbiAgICAgICAgICAgIC8qIVxuICAgICAgICAgICAgICogQ3Jvc3MtQnJvd3NlciBTcGxpdCAxLjEuMVxuICAgICAgICAgICAgICogQ29weXJpZ2h0IDIwMDctMjAxMiBTdGV2ZW4gTGV2aXRoYW4gPHN0ZXZlbmxldml0aGFuLmNvbT5cbiAgICAgICAgICAgICAqIEF2YWlsYWJsZSB1bmRlciB0aGUgTUlUIExpY2Vuc2VcbiAgICAgICAgICAgICAqIEVDTUFTY3JpcHQgY29tcGxpYW50LCB1bmlmb3JtIGNyb3NzLWJyb3dzZXIgc3BsaXQgbWV0aG9kXG4gICAgICAgICAgICAgKi9cblxuICAgICAgICAgICAgLyoqXG4gICAgICAgICAgICAgKiBTcGxpdHMgYSBzdHJpbmcgaW50byBhbiBhcnJheSBvZiBzdHJpbmdzIHVzaW5nIGEgcmVnZXggb3Igc3RyaW5nIHNlcGFyYXRvci4gTWF0Y2hlcyBvZiB0aGVcbiAgICAgICAgICAgICAqIHNlcGFyYXRvciBhcmUgbm90IGluY2x1ZGVkIGluIHRoZSByZXN1bHQgYXJyYXkuIEhvd2V2ZXIsIGlmIGBzZXBhcmF0b3JgIGlzIGEgcmVnZXggdGhhdCBjb250YWluc1xuICAgICAgICAgICAgICogY2FwdHVyaW5nIGdyb3VwcywgYmFja3JlZmVyZW5jZXMgYXJlIHNwbGljZWQgaW50byB0aGUgcmVzdWx0IGVhY2ggdGltZSBgc2VwYXJhdG9yYCBpcyBtYXRjaGVkLlxuICAgICAgICAgICAgICogRml4ZXMgYnJvd3NlciBidWdzIGNvbXBhcmVkIHRvIHRoZSBuYXRpdmUgYFN0cmluZy5wcm90b3R5cGUuc3BsaXRgIGFuZCBjYW4gYmUgdXNlZCByZWxpYWJseVxuICAgICAgICAgICAgICogY3Jvc3MtYnJvd3Nlci5cbiAgICAgICAgICAgICAqIEBwYXJhbSB7U3RyaW5nfSBzdHIgU3RyaW5nIHRvIHNwbGl0LlxuICAgICAgICAgICAgICogQHBhcmFtIHtSZWdFeHB8U3RyaW5nfSBzZXBhcmF0b3IgUmVnZXggb3Igc3RyaW5nIHRvIHVzZSBmb3Igc2VwYXJhdGluZyB0aGUgc3RyaW5nLlxuICAgICAgICAgICAgICogQHBhcmFtIHtOdW1iZXJ9IFtsaW1pdF0gTWF4aW11bSBudW1iZXIgb2YgaXRlbXMgdG8gaW5jbHVkZSBpbiB0aGUgcmVzdWx0IGFycmF5LlxuICAgICAgICAgICAgICogQHJldHVybnMge0FycmF5fSBBcnJheSBvZiBzdWJzdHJpbmdzLlxuICAgICAgICAgICAgICogQGV4YW1wbGVcbiAgICAgICAgICAgICAqXG4gICAgICAgICAgICAgKiAvLyBCYXNpYyB1c2VcbiAgICAgICAgICAgICAqIHNwbGl0KCdhIGIgYyBkJywgJyAnKTtcbiAgICAgICAgICAgICAqIC8vIC0+IFsnYScsICdiJywgJ2MnLCAnZCddXG4gICAgICAgICAgICAgKlxuICAgICAgICAgICAgICogLy8gV2l0aCBsaW1pdFxuICAgICAgICAgICAgICogc3BsaXQoJ2EgYiBjIGQnLCAnICcsIDIpO1xuICAgICAgICAgICAgICogLy8gLT4gWydhJywgJ2InXVxuICAgICAgICAgICAgICpcbiAgICAgICAgICAgICAqIC8vIEJhY2tyZWZlcmVuY2VzIGluIHJlc3VsdCBhcnJheVxuICAgICAgICAgICAgICogc3BsaXQoJy4ud29yZDEgd29yZDIuLicsIC8oW2Etel0rKShcXGQrKS9pKTtcbiAgICAgICAgICAgICAqIC8vIC0+IFsnLi4nLCAnd29yZCcsICcxJywgJyAnLCAnd29yZCcsICcyJywgJy4uJ11cbiAgICAgICAgICAgICAqL1xuICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSAoZnVuY3Rpb24gc3BsaXQodW5kZWYpIHtcblxuICAgICAgICAgICAgICAgIHZhciBuYXRpdmVTcGxpdCA9IFN0cmluZy5wcm90b3R5cGUuc3BsaXQsXG4gICAgICAgICAgICAgICAgICAgIGNvbXBsaWFudEV4ZWNOcGNnID0gLygpPz8vLmV4ZWMoXCJcIilbMV0gPT09IHVuZGVmLFxuXG4gICAgICAgICAgICAgICAgLy8gTlBDRzogbm9ucGFydGljaXBhdGluZyBjYXB0dXJpbmcgZ3JvdXBcbiAgICAgICAgICAgICAgICBzZWxmO1xuXG4gICAgICAgICAgICAgICAgc2VsZiA9IGZ1bmN0aW9uIChzdHIsIHNlcGFyYXRvciwgbGltaXQpIHtcbiAgICAgICAgICAgICAgICAgICAgLy8gSWYgYHNlcGFyYXRvcmAgaXMgbm90IGEgcmVnZXgsIHVzZSBgbmF0aXZlU3BsaXRgXG4gICAgICAgICAgICAgICAgICAgIGlmIChPYmplY3QucHJvdG90eXBlLnRvU3RyaW5nLmNhbGwoc2VwYXJhdG9yKSAhPT0gXCJbb2JqZWN0IFJlZ0V4cF1cIikge1xuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIG5hdGl2ZVNwbGl0LmNhbGwoc3RyLCBzZXBhcmF0b3IsIGxpbWl0KTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB2YXIgb3V0cHV0ID0gW10sXG4gICAgICAgICAgICAgICAgICAgICAgICBmbGFncyA9IChzZXBhcmF0b3IuaWdub3JlQ2FzZSA/IFwiaVwiIDogXCJcIikgKyAoc2VwYXJhdG9yLm11bHRpbGluZSA/IFwibVwiIDogXCJcIikgKyAoc2VwYXJhdG9yLmV4dGVuZGVkID8gXCJ4XCIgOiBcIlwiKSArIChzZXBhcmF0b3Iuc3RpY2t5ID8gXCJ5XCIgOiBcIlwiKSxcblxuICAgICAgICAgICAgICAgICAgICAvLyBGaXJlZm94IDMrXG4gICAgICAgICAgICAgICAgICAgIGxhc3RMYXN0SW5kZXggPSAwLFxuXG4gICAgICAgICAgICAgICAgICAgIC8vIE1ha2UgYGdsb2JhbGAgYW5kIGF2b2lkIGBsYXN0SW5kZXhgIGlzc3VlcyBieSB3b3JraW5nIHdpdGggYSBjb3B5XG4gICAgICAgICAgICAgICAgICAgIHNlcGFyYXRvciA9IG5ldyBSZWdFeHAoc2VwYXJhdG9yLnNvdXJjZSwgZmxhZ3MgKyBcImdcIiksXG4gICAgICAgICAgICAgICAgICAgICAgICBzZXBhcmF0b3IyLFxuICAgICAgICAgICAgICAgICAgICAgICAgbWF0Y2gsXG4gICAgICAgICAgICAgICAgICAgICAgICBsYXN0SW5kZXgsXG4gICAgICAgICAgICAgICAgICAgICAgICBsYXN0TGVuZ3RoO1xuICAgICAgICAgICAgICAgICAgICBzdHIgKz0gXCJcIjsgLy8gVHlwZS1jb252ZXJ0XG4gICAgICAgICAgICAgICAgICAgIGlmICghY29tcGxpYW50RXhlY05wY2cpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIERvZXNuJ3QgbmVlZCBmbGFncyBneSwgYnV0IHRoZXkgZG9uJ3QgaHVydFxuICAgICAgICAgICAgICAgICAgICAgICAgc2VwYXJhdG9yMiA9IG5ldyBSZWdFeHAoXCJeXCIgKyBzZXBhcmF0b3Iuc291cmNlICsgXCIkKD8hXFxcXHMpXCIsIGZsYWdzKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAvKiBWYWx1ZXMgZm9yIGBsaW1pdGAsIHBlciB0aGUgc3BlYzpcbiAgICAgICAgICAgICAgICAgICAgICogSWYgdW5kZWZpbmVkOiA0Mjk0OTY3Mjk1IC8vIE1hdGgucG93KDIsIDMyKSAtIDFcbiAgICAgICAgICAgICAgICAgICAgICogSWYgMCwgSW5maW5pdHksIG9yIE5hTjogMFxuICAgICAgICAgICAgICAgICAgICAgKiBJZiBwb3NpdGl2ZSBudW1iZXI6IGxpbWl0ID0gTWF0aC5mbG9vcihsaW1pdCk7IGlmIChsaW1pdCA+IDQyOTQ5NjcyOTUpIGxpbWl0IC09IDQyOTQ5NjcyOTY7XG4gICAgICAgICAgICAgICAgICAgICAqIElmIG5lZ2F0aXZlIG51bWJlcjogNDI5NDk2NzI5NiAtIE1hdGguZmxvb3IoTWF0aC5hYnMobGltaXQpKVxuICAgICAgICAgICAgICAgICAgICAgKiBJZiBvdGhlcjogVHlwZS1jb252ZXJ0LCB0aGVuIHVzZSB0aGUgYWJvdmUgcnVsZXNcbiAgICAgICAgICAgICAgICAgICAgICovXG4gICAgICAgICAgICAgICAgICAgIGxpbWl0ID0gbGltaXQgPT09IHVuZGVmID8gLTEgPj4+IDAgOiAvLyBNYXRoLnBvdygyLCAzMikgLSAxXG4gICAgICAgICAgICAgICAgICAgIGxpbWl0ID4+PiAwOyAvLyBUb1VpbnQzMihsaW1pdClcbiAgICAgICAgICAgICAgICAgICAgd2hpbGUgKG1hdGNoID0gc2VwYXJhdG9yLmV4ZWMoc3RyKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgLy8gYHNlcGFyYXRvci5sYXN0SW5kZXhgIGlzIG5vdCByZWxpYWJsZSBjcm9zcy1icm93c2VyXG4gICAgICAgICAgICAgICAgICAgICAgICBsYXN0SW5kZXggPSBtYXRjaC5pbmRleCArIG1hdGNoWzBdLmxlbmd0aDtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChsYXN0SW5kZXggPiBsYXN0TGFzdEluZGV4KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgb3V0cHV0LnB1c2goc3RyLnNsaWNlKGxhc3RMYXN0SW5kZXgsIG1hdGNoLmluZGV4KSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gRml4IGJyb3dzZXJzIHdob3NlIGBleGVjYCBtZXRob2RzIGRvbid0IGNvbnNpc3RlbnRseSByZXR1cm4gYHVuZGVmaW5lZGAgZm9yXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gbm9ucGFydGljaXBhdGluZyBjYXB0dXJpbmcgZ3JvdXBzXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKCFjb21wbGlhbnRFeGVjTnBjZyAmJiBtYXRjaC5sZW5ndGggPiAxKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1hdGNoWzBdLnJlcGxhY2Uoc2VwYXJhdG9yMiwgZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZm9yICh2YXIgaSA9IDE7IGkgPCBhcmd1bWVudHMubGVuZ3RoIC0gMjsgaSsrKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGFyZ3VtZW50c1tpXSA9PT0gdW5kZWYpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbWF0Y2hbaV0gPSB1bmRlZjtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAobWF0Y2gubGVuZ3RoID4gMSAmJiBtYXRjaC5pbmRleCA8IHN0ci5sZW5ndGgpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgQXJyYXkucHJvdG90eXBlLnB1c2guYXBwbHkob3V0cHV0LCBtYXRjaC5zbGljZSgxKSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxhc3RMZW5ndGggPSBtYXRjaFswXS5sZW5ndGg7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgbGFzdExhc3RJbmRleCA9IGxhc3RJbmRleDtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAob3V0cHV0Lmxlbmd0aCA+PSBsaW1pdCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoc2VwYXJhdG9yLmxhc3RJbmRleCA9PT0gbWF0Y2guaW5kZXgpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBzZXBhcmF0b3IubGFzdEluZGV4Kys7IC8vIEF2b2lkIGFuIGluZmluaXRlIGxvb3BcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICBpZiAobGFzdExhc3RJbmRleCA9PT0gc3RyLmxlbmd0aCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGxhc3RMZW5ndGggfHwgIXNlcGFyYXRvci50ZXN0KFwiXCIpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgb3V0cHV0LnB1c2goXCJcIik7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBvdXRwdXQucHVzaChzdHIuc2xpY2UobGFzdExhc3RJbmRleCkpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBvdXRwdXQubGVuZ3RoID4gbGltaXQgPyBvdXRwdXQuc2xpY2UoMCwgbGltaXQpIDogb3V0cHV0O1xuICAgICAgICAgICAgICAgIH07XG5cbiAgICAgICAgICAgICAgICByZXR1cm4gc2VsZjtcbiAgICAgICAgICAgIH0pKCk7XG4gICAgICAgIH0sIHt9XSwgNjogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHt9LCB7fV0sIDc6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICBcInVzZSBzdHJpY3RcIjtcblxuICAgICAgICAgICAgdmFyIE9uZVZlcnNpb25Db25zdHJhaW50ID0gcmVxdWlyZShcImluZGl2aWR1YWwvb25lLXZlcnNpb25cIik7XG5cbiAgICAgICAgICAgIHZhciBNWV9WRVJTSU9OID0gXCI3XCI7XG4gICAgICAgICAgICBPbmVWZXJzaW9uQ29uc3RyYWludChcImV2LXN0b3JlXCIsIE1ZX1ZFUlNJT04pO1xuXG4gICAgICAgICAgICB2YXIgaGFzaEtleSA9IFwiX19FVl9TVE9SRV9LRVlAXCIgKyBNWV9WRVJTSU9OO1xuXG4gICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IEV2U3RvcmU7XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIEV2U3RvcmUoZWxlbSkge1xuICAgICAgICAgICAgICAgIHZhciBoYXNoID0gZWxlbVtoYXNoS2V5XTtcblxuICAgICAgICAgICAgICAgIGlmICghaGFzaCkge1xuICAgICAgICAgICAgICAgICAgICBoYXNoID0gZWxlbVtoYXNoS2V5XSA9IHt9O1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHJldHVybiBoYXNoO1xuICAgICAgICAgICAgfVxuICAgICAgICB9LCB7IFwiaW5kaXZpZHVhbC9vbmUtdmVyc2lvblwiOiA5IH1dLCA4OiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge1xuICAgICAgICAgICAgKGZ1bmN0aW9uIChnbG9iYWwpIHtcbiAgICAgICAgICAgICAgICBcInVzZSBzdHJpY3RcIjtcblxuICAgICAgICAgICAgICAgIC8qZ2xvYmFsIHdpbmRvdywgZ2xvYmFsKi9cblxuICAgICAgICAgICAgICAgIHZhciByb290ID0gdHlwZW9mIHdpbmRvdyAhPT0gXCJ1bmRlZmluZWRcIiA/IHdpbmRvdyA6IHR5cGVvZiBnbG9iYWwgIT09IFwidW5kZWZpbmVkXCIgPyBnbG9iYWwgOiB7fTtcblxuICAgICAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gSW5kaXZpZHVhbDtcblxuICAgICAgICAgICAgICAgIGZ1bmN0aW9uIEluZGl2aWR1YWwoa2V5LCB2YWx1ZSkge1xuICAgICAgICAgICAgICAgICAgICBpZiAoa2V5IGluIHJvb3QpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiByb290W2tleV07XG4gICAgICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgICAgICByb290W2tleV0gPSB2YWx1ZTtcblxuICAgICAgICAgICAgICAgICAgICByZXR1cm4gdmFsdWU7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSkuY2FsbCh0aGlzLCB0eXBlb2YgZ2xvYmFsICE9PSBcInVuZGVmaW5lZFwiID8gZ2xvYmFsIDogdHlwZW9mIHNlbGYgIT09IFwidW5kZWZpbmVkXCIgPyBzZWxmIDogdHlwZW9mIHdpbmRvdyAhPT0gXCJ1bmRlZmluZWRcIiA/IHdpbmRvdyA6IHt9KTtcbiAgICAgICAgfSwge31dLCA5OiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge1xuICAgICAgICAgICAgXCJ1c2Ugc3RyaWN0XCI7XG5cbiAgICAgICAgICAgIHZhciBJbmRpdmlkdWFsID0gcmVxdWlyZShcIi4vaW5kZXguanNcIik7XG5cbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gT25lVmVyc2lvbjtcblxuICAgICAgICAgICAgZnVuY3Rpb24gT25lVmVyc2lvbihtb2R1bGVOYW1lLCB2ZXJzaW9uLCBkZWZhdWx0VmFsdWUpIHtcbiAgICAgICAgICAgICAgICB2YXIga2V5ID0gXCJfX0lORElWSURVQUxfT05FX1ZFUlNJT05fXCIgKyBtb2R1bGVOYW1lO1xuICAgICAgICAgICAgICAgIHZhciBlbmZvcmNlS2V5ID0ga2V5ICsgXCJfRU5GT1JDRV9TSU5HTEVUT05cIjtcblxuICAgICAgICAgICAgICAgIHZhciB2ZXJzaW9uVmFsdWUgPSBJbmRpdmlkdWFsKGVuZm9yY2VLZXksIHZlcnNpb24pO1xuXG4gICAgICAgICAgICAgICAgaWYgKHZlcnNpb25WYWx1ZSAhPT0gdmVyc2lvbikge1xuICAgICAgICAgICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoXCJDYW4gb25seSBoYXZlIG9uZSBjb3B5IG9mIFwiICsgbW9kdWxlTmFtZSArIFwiLlxcblwiICsgXCJZb3UgYWxyZWFkeSBoYXZlIHZlcnNpb24gXCIgKyB2ZXJzaW9uVmFsdWUgKyBcIiBpbnN0YWxsZWQuXFxuXCIgKyBcIlRoaXMgbWVhbnMgeW91IGNhbm5vdCBpbnN0YWxsIHZlcnNpb24gXCIgKyB2ZXJzaW9uKTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICByZXR1cm4gSW5kaXZpZHVhbChrZXksIGRlZmF1bHRWYWx1ZSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0sIHsgXCIuL2luZGV4LmpzXCI6IDggfV0sIDEwOiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge1xuICAgICAgICAgICAgKGZ1bmN0aW9uIChnbG9iYWwpIHtcbiAgICAgICAgICAgICAgICB2YXIgdG9wTGV2ZWwgPSB0eXBlb2YgZ2xvYmFsICE9PSBcInVuZGVmaW5lZFwiID8gZ2xvYmFsIDogdHlwZW9mIHdpbmRvdyAhPT0gXCJ1bmRlZmluZWRcIiA/IHdpbmRvdyA6IHt9O1xuICAgICAgICAgICAgICAgIHZhciBtaW5Eb2MgPSByZXF1aXJlKFwibWluLWRvY3VtZW50XCIpO1xuXG4gICAgICAgICAgICAgICAgaWYgKHR5cGVvZiBkb2N1bWVudCAhPT0gXCJ1bmRlZmluZWRcIikge1xuICAgICAgICAgICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IGRvY3VtZW50O1xuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciBkb2NjeSA9IHRvcExldmVsW1wiX19HTE9CQUxfRE9DVU1FTlRfQ0FDSEVANFwiXTtcblxuICAgICAgICAgICAgICAgICAgICBpZiAoIWRvY2N5KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBkb2NjeSA9IHRvcExldmVsW1wiX19HTE9CQUxfRE9DVU1FTlRfQ0FDSEVANFwiXSA9IG1pbkRvYztcbiAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gZG9jY3k7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSkuY2FsbCh0aGlzLCB0eXBlb2YgZ2xvYmFsICE9PSBcInVuZGVmaW5lZFwiID8gZ2xvYmFsIDogdHlwZW9mIHNlbGYgIT09IFwidW5kZWZpbmVkXCIgPyBzZWxmIDogdHlwZW9mIHdpbmRvdyAhPT0gXCJ1bmRlZmluZWRcIiA/IHdpbmRvdyA6IHt9KTtcbiAgICAgICAgfSwgeyBcIm1pbi1kb2N1bWVudFwiOiA2IH1dLCAxMTogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHtcbiAgICAgICAgICAgIFwidXNlIHN0cmljdFwiO1xuXG4gICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uIGlzT2JqZWN0KHgpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gdHlwZW9mIHggPT09IFwib2JqZWN0XCIgJiYgeCAhPT0gbnVsbDtcbiAgICAgICAgICAgIH07XG4gICAgICAgIH0sIHt9XSwgMTI6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICB2YXIgbmF0aXZlSXNBcnJheSA9IEFycmF5LmlzQXJyYXk7XG4gICAgICAgICAgICB2YXIgdG9TdHJpbmcgPSBPYmplY3QucHJvdG90eXBlLnRvU3RyaW5nO1xuXG4gICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IG5hdGl2ZUlzQXJyYXkgfHwgaXNBcnJheTtcblxuICAgICAgICAgICAgZnVuY3Rpb24gaXNBcnJheShvYmopIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gdG9TdHJpbmcuY2FsbChvYmopID09PSBcIltvYmplY3QgQXJyYXldXCI7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0sIHt9XSwgMTM6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICB2YXIgcGF0Y2ggPSByZXF1aXJlKFwiLi92ZG9tL3BhdGNoLmpzXCIpO1xuXG4gICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IHBhdGNoO1xuICAgICAgICB9LCB7IFwiLi92ZG9tL3BhdGNoLmpzXCI6IDE4IH1dLCAxNDogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHtcbiAgICAgICAgICAgIHZhciBpc09iamVjdCA9IHJlcXVpcmUoXCJpcy1vYmplY3RcIik7XG4gICAgICAgICAgICB2YXIgaXNIb29rID0gcmVxdWlyZShcIi4uL3Zub2RlL2lzLXZob29rLmpzXCIpO1xuXG4gICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IGFwcGx5UHJvcGVydGllcztcblxuICAgICAgICAgICAgZnVuY3Rpb24gYXBwbHlQcm9wZXJ0aWVzKG5vZGUsIHByb3BzLCBwcmV2aW91cykge1xuICAgICAgICAgICAgICAgIGZvciAodmFyIHByb3BOYW1lIGluIHByb3BzKSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciBwcm9wVmFsdWUgPSBwcm9wc1twcm9wTmFtZV07XG5cbiAgICAgICAgICAgICAgICAgICAgaWYgKHByb3BWYWx1ZSA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICByZW1vdmVQcm9wZXJ0eShub2RlLCBwcm9wTmFtZSwgcHJvcFZhbHVlLCBwcmV2aW91cyk7XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoaXNIb29rKHByb3BWYWx1ZSkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJlbW92ZVByb3BlcnR5KG5vZGUsIHByb3BOYW1lLCBwcm9wVmFsdWUsIHByZXZpb3VzKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChwcm9wVmFsdWUuaG9vaykge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHByb3BWYWx1ZS5ob29rKG5vZGUsIHByb3BOYW1lLCBwcmV2aW91cyA/IHByZXZpb3VzW3Byb3BOYW1lXSA6IHVuZGVmaW5lZCk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoaXNPYmplY3QocHJvcFZhbHVlKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHBhdGNoT2JqZWN0KG5vZGUsIHByb3BzLCBwcmV2aW91cywgcHJvcE5hbWUsIHByb3BWYWx1ZSk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIG5vZGVbcHJvcE5hbWVdID0gcHJvcFZhbHVlO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBmdW5jdGlvbiByZW1vdmVQcm9wZXJ0eShub2RlLCBwcm9wTmFtZSwgcHJvcFZhbHVlLCBwcmV2aW91cykge1xuICAgICAgICAgICAgICAgIGlmIChwcmV2aW91cykge1xuICAgICAgICAgICAgICAgICAgICB2YXIgcHJldmlvdXNWYWx1ZSA9IHByZXZpb3VzW3Byb3BOYW1lXTtcblxuICAgICAgICAgICAgICAgICAgICBpZiAoIWlzSG9vayhwcmV2aW91c1ZhbHVlKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHByb3BOYW1lID09PSBcImF0dHJpYnV0ZXNcIikge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZvciAodmFyIGF0dHJOYW1lIGluIHByZXZpb3VzVmFsdWUpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbm9kZS5yZW1vdmVBdHRyaWJ1dGUoYXR0ck5hbWUpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAocHJvcE5hbWUgPT09IFwic3R5bGVcIikge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZvciAodmFyIGkgaW4gcHJldmlvdXNWYWx1ZSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBub2RlLnN0eWxlW2ldID0gXCJcIjtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKHR5cGVvZiBwcmV2aW91c1ZhbHVlID09PSBcInN0cmluZ1wiKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgbm9kZVtwcm9wTmFtZV0gPSBcIlwiO1xuICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBub2RlW3Byb3BOYW1lXSA9IG51bGw7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAocHJldmlvdXNWYWx1ZS51bmhvb2spIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHByZXZpb3VzVmFsdWUudW5ob29rKG5vZGUsIHByb3BOYW1lLCBwcm9wVmFsdWUpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBmdW5jdGlvbiBwYXRjaE9iamVjdChub2RlLCBwcm9wcywgcHJldmlvdXMsIHByb3BOYW1lLCBwcm9wVmFsdWUpIHtcbiAgICAgICAgICAgICAgICB2YXIgcHJldmlvdXNWYWx1ZSA9IHByZXZpb3VzID8gcHJldmlvdXNbcHJvcE5hbWVdIDogdW5kZWZpbmVkO1xuXG4gICAgICAgICAgICAgICAgLy8gU2V0IGF0dHJpYnV0ZXNcbiAgICAgICAgICAgICAgICBpZiAocHJvcE5hbWUgPT09IFwiYXR0cmlidXRlc1wiKSB7XG4gICAgICAgICAgICAgICAgICAgIGZvciAodmFyIGF0dHJOYW1lIGluIHByb3BWYWx1ZSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgdmFyIGF0dHJWYWx1ZSA9IHByb3BWYWx1ZVthdHRyTmFtZV07XG5cbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChhdHRyVmFsdWUgPT09IHVuZGVmaW5lZCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIG5vZGUucmVtb3ZlQXR0cmlidXRlKGF0dHJOYW1lKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgbm9kZS5zZXRBdHRyaWJ1dGUoYXR0ck5hbWUsIGF0dHJWYWx1ZSk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgaWYgKHByZXZpb3VzVmFsdWUgJiYgaXNPYmplY3QocHJldmlvdXNWYWx1ZSkgJiYgZ2V0UHJvdG90eXBlKHByZXZpb3VzVmFsdWUpICE9PSBnZXRQcm90b3R5cGUocHJvcFZhbHVlKSkge1xuICAgICAgICAgICAgICAgICAgICBub2RlW3Byb3BOYW1lXSA9IHByb3BWYWx1ZTtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIGlmICghaXNPYmplY3Qobm9kZVtwcm9wTmFtZV0pKSB7XG4gICAgICAgICAgICAgICAgICAgIG5vZGVbcHJvcE5hbWVdID0ge307XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgdmFyIHJlcGxhY2VyID0gcHJvcE5hbWUgPT09IFwic3R5bGVcIiA/IFwiXCIgOiB1bmRlZmluZWQ7XG5cbiAgICAgICAgICAgICAgICBmb3IgKHZhciBrIGluIHByb3BWYWx1ZSkge1xuICAgICAgICAgICAgICAgICAgICB2YXIgdmFsdWUgPSBwcm9wVmFsdWVba107XG4gICAgICAgICAgICAgICAgICAgIG5vZGVbcHJvcE5hbWVdW2tdID0gdmFsdWUgPT09IHVuZGVmaW5lZCA/IHJlcGxhY2VyIDogdmFsdWU7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBmdW5jdGlvbiBnZXRQcm90b3R5cGUodmFsdWUpIHtcbiAgICAgICAgICAgICAgICBpZiAoT2JqZWN0LmdldFByb3RvdHlwZU9mKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBPYmplY3QuZ2V0UHJvdG90eXBlT2YodmFsdWUpO1xuICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAodmFsdWUuX19wcm90b19fKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiB2YWx1ZS5fX3Byb3RvX187XG4gICAgICAgICAgICAgICAgfSBlbHNlIGlmICh2YWx1ZS5jb25zdHJ1Y3Rvcikge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gdmFsdWUuY29uc3RydWN0b3IucHJvdG90eXBlO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgfSwgeyBcIi4uL3Zub2RlL2lzLXZob29rLmpzXCI6IDI2LCBcImlzLW9iamVjdFwiOiAxMSB9XSwgMTU6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICB2YXIgZG9jdW1lbnQgPSByZXF1aXJlKFwiZ2xvYmFsL2RvY3VtZW50XCIpO1xuXG4gICAgICAgICAgICB2YXIgYXBwbHlQcm9wZXJ0aWVzID0gcmVxdWlyZShcIi4vYXBwbHktcHJvcGVydGllc1wiKTtcblxuICAgICAgICAgICAgdmFyIGlzVk5vZGUgPSByZXF1aXJlKFwiLi4vdm5vZGUvaXMtdm5vZGUuanNcIik7XG4gICAgICAgICAgICB2YXIgaXNWVGV4dCA9IHJlcXVpcmUoXCIuLi92bm9kZS9pcy12dGV4dC5qc1wiKTtcbiAgICAgICAgICAgIHZhciBpc1dpZGdldCA9IHJlcXVpcmUoXCIuLi92bm9kZS9pcy13aWRnZXQuanNcIik7XG4gICAgICAgICAgICB2YXIgaGFuZGxlVGh1bmsgPSByZXF1aXJlKFwiLi4vdm5vZGUvaGFuZGxlLXRodW5rLmpzXCIpO1xuXG4gICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IGNyZWF0ZUVsZW1lbnQ7XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIGNyZWF0ZUVsZW1lbnQodm5vZGUsIG9wdHMpIHtcbiAgICAgICAgICAgICAgICB2YXIgZG9jID0gb3B0cyA/IG9wdHMuZG9jdW1lbnQgfHwgZG9jdW1lbnQgOiBkb2N1bWVudDtcbiAgICAgICAgICAgICAgICB2YXIgd2FybiA9IG9wdHMgPyBvcHRzLndhcm4gOiBudWxsO1xuXG4gICAgICAgICAgICAgICAgdm5vZGUgPSBoYW5kbGVUaHVuayh2bm9kZSkuYTtcblxuICAgICAgICAgICAgICAgIGlmIChpc1dpZGdldCh2bm9kZSkpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHZub2RlLmluaXQoKTtcbiAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKGlzVlRleHQodm5vZGUpKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBkb2MuY3JlYXRlVGV4dE5vZGUodm5vZGUudGV4dCk7XG4gICAgICAgICAgICAgICAgfSBlbHNlIGlmICghaXNWTm9kZSh2bm9kZSkpIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKHdhcm4pIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHdhcm4oXCJJdGVtIGlzIG5vdCBhIHZhbGlkIHZpcnR1YWwgZG9tIG5vZGVcIiwgdm5vZGUpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBudWxsO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHZhciBub2RlID0gdm5vZGUubmFtZXNwYWNlID09PSBudWxsID8gZG9jLmNyZWF0ZUVsZW1lbnQodm5vZGUudGFnTmFtZSkgOiBkb2MuY3JlYXRlRWxlbWVudE5TKHZub2RlLm5hbWVzcGFjZSwgdm5vZGUudGFnTmFtZSk7XG5cbiAgICAgICAgICAgICAgICB2YXIgcHJvcHMgPSB2bm9kZS5wcm9wZXJ0aWVzO1xuICAgICAgICAgICAgICAgIGFwcGx5UHJvcGVydGllcyhub2RlLCBwcm9wcyk7XG5cbiAgICAgICAgICAgICAgICB2YXIgY2hpbGRyZW4gPSB2bm9kZS5jaGlsZHJlbjtcblxuICAgICAgICAgICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgY2hpbGRyZW4ubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgICAgICAgICAgdmFyIGNoaWxkTm9kZSA9IGNyZWF0ZUVsZW1lbnQoY2hpbGRyZW5baV0sIG9wdHMpO1xuICAgICAgICAgICAgICAgICAgICBpZiAoY2hpbGROb2RlKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBub2RlLmFwcGVuZENoaWxkKGNoaWxkTm9kZSk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICByZXR1cm4gbm9kZTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSwgeyBcIi4uL3Zub2RlL2hhbmRsZS10aHVuay5qc1wiOiAyNCwgXCIuLi92bm9kZS9pcy12bm9kZS5qc1wiOiAyNywgXCIuLi92bm9kZS9pcy12dGV4dC5qc1wiOiAyOCwgXCIuLi92bm9kZS9pcy13aWRnZXQuanNcIjogMjksIFwiLi9hcHBseS1wcm9wZXJ0aWVzXCI6IDE0LCBcImdsb2JhbC9kb2N1bWVudFwiOiAxMCB9XSwgMTY6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICAvLyBNYXBzIGEgdmlydHVhbCBET00gdHJlZSBvbnRvIGEgcmVhbCBET00gdHJlZSBpbiBhbiBlZmZpY2llbnQgbWFubmVyLlxuICAgICAgICAgICAgLy8gV2UgZG9uJ3Qgd2FudCB0byByZWFkIGFsbCBvZiB0aGUgRE9NIG5vZGVzIGluIHRoZSB0cmVlIHNvIHdlIHVzZVxuICAgICAgICAgICAgLy8gdGhlIGluLW9yZGVyIHRyZWUgaW5kZXhpbmcgdG8gZWxpbWluYXRlIHJlY3Vyc2lvbiBkb3duIGNlcnRhaW4gYnJhbmNoZXMuXG4gICAgICAgICAgICAvLyBXZSBvbmx5IHJlY3Vyc2UgaW50byBhIERPTSBub2RlIGlmIHdlIGtub3cgdGhhdCBpdCBjb250YWlucyBhIGNoaWxkIG9mXG4gICAgICAgICAgICAvLyBpbnRlcmVzdC5cblxuICAgICAgICAgICAgdmFyIG5vQ2hpbGQgPSB7fTtcblxuICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBkb21JbmRleDtcblxuICAgICAgICAgICAgZnVuY3Rpb24gZG9tSW5kZXgocm9vdE5vZGUsIHRyZWUsIGluZGljZXMsIG5vZGVzKSB7XG4gICAgICAgICAgICAgICAgaWYgKCFpbmRpY2VzIHx8IGluZGljZXMubGVuZ3RoID09PSAwKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiB7fTtcbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICBpbmRpY2VzLnNvcnQoYXNjZW5kaW5nKTtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHJlY3Vyc2Uocm9vdE5vZGUsIHRyZWUsIGluZGljZXMsIG5vZGVzLCAwKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIHJlY3Vyc2Uocm9vdE5vZGUsIHRyZWUsIGluZGljZXMsIG5vZGVzLCByb290SW5kZXgpIHtcbiAgICAgICAgICAgICAgICBub2RlcyA9IG5vZGVzIHx8IHt9O1xuXG4gICAgICAgICAgICAgICAgaWYgKHJvb3ROb2RlKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmIChpbmRleEluUmFuZ2UoaW5kaWNlcywgcm9vdEluZGV4LCByb290SW5kZXgpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBub2Rlc1tyb290SW5kZXhdID0gcm9vdE5vZGU7XG4gICAgICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgICAgICB2YXIgdkNoaWxkcmVuID0gdHJlZS5jaGlsZHJlbjtcblxuICAgICAgICAgICAgICAgICAgICBpZiAodkNoaWxkcmVuKSB7XG5cbiAgICAgICAgICAgICAgICAgICAgICAgIHZhciBjaGlsZE5vZGVzID0gcm9vdE5vZGUuY2hpbGROb2RlcztcblxuICAgICAgICAgICAgICAgICAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCB0cmVlLmNoaWxkcmVuLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcm9vdEluZGV4ICs9IDE7XG5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB2YXIgdkNoaWxkID0gdkNoaWxkcmVuW2ldIHx8IG5vQ2hpbGQ7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdmFyIG5leHRJbmRleCA9IHJvb3RJbmRleCArICh2Q2hpbGQuY291bnQgfHwgMCk7XG5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBza2lwIHJlY3Vyc2lvbiBkb3duIHRoZSB0cmVlIGlmIHRoZXJlIGFyZSBubyBub2RlcyBkb3duIGhlcmVcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoaW5kZXhJblJhbmdlKGluZGljZXMsIHJvb3RJbmRleCwgbmV4dEluZGV4KSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICByZWN1cnNlKGNoaWxkTm9kZXNbaV0sIHZDaGlsZCwgaW5kaWNlcywgbm9kZXMsIHJvb3RJbmRleCk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcm9vdEluZGV4ID0gbmV4dEluZGV4O1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgcmV0dXJuIG5vZGVzO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAvLyBCaW5hcnkgc2VhcmNoIGZvciBhbiBpbmRleCBpbiB0aGUgaW50ZXJ2YWwgW2xlZnQsIHJpZ2h0XVxuICAgICAgICAgICAgZnVuY3Rpb24gaW5kZXhJblJhbmdlKGluZGljZXMsIGxlZnQsIHJpZ2h0KSB7XG4gICAgICAgICAgICAgICAgaWYgKGluZGljZXMubGVuZ3RoID09PSAwKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICB2YXIgbWluSW5kZXggPSAwO1xuICAgICAgICAgICAgICAgIHZhciBtYXhJbmRleCA9IGluZGljZXMubGVuZ3RoIC0gMTtcbiAgICAgICAgICAgICAgICB2YXIgY3VycmVudEluZGV4O1xuICAgICAgICAgICAgICAgIHZhciBjdXJyZW50SXRlbTtcblxuICAgICAgICAgICAgICAgIHdoaWxlIChtaW5JbmRleCA8PSBtYXhJbmRleCkge1xuICAgICAgICAgICAgICAgICAgICBjdXJyZW50SW5kZXggPSAobWF4SW5kZXggKyBtaW5JbmRleCkgLyAyID4+IDA7XG4gICAgICAgICAgICAgICAgICAgIGN1cnJlbnRJdGVtID0gaW5kaWNlc1tjdXJyZW50SW5kZXhdO1xuXG4gICAgICAgICAgICAgICAgICAgIGlmIChtaW5JbmRleCA9PT0gbWF4SW5kZXgpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBjdXJyZW50SXRlbSA+PSBsZWZ0ICYmIGN1cnJlbnRJdGVtIDw9IHJpZ2h0O1xuICAgICAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKGN1cnJlbnRJdGVtIDwgbGVmdCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgbWluSW5kZXggPSBjdXJyZW50SW5kZXggKyAxO1xuICAgICAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKGN1cnJlbnRJdGVtID4gcmlnaHQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIG1heEluZGV4ID0gY3VycmVudEluZGV4IC0gMTtcbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBmdW5jdGlvbiBhc2NlbmRpbmcoYSwgYikge1xuICAgICAgICAgICAgICAgIHJldHVybiBhID4gYiA/IDEgOiAtMTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSwge31dLCAxNzogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHtcbiAgICAgICAgICAgIHZhciBhcHBseVByb3BlcnRpZXMgPSByZXF1aXJlKFwiLi9hcHBseS1wcm9wZXJ0aWVzXCIpO1xuXG4gICAgICAgICAgICB2YXIgaXNXaWRnZXQgPSByZXF1aXJlKFwiLi4vdm5vZGUvaXMtd2lkZ2V0LmpzXCIpO1xuICAgICAgICAgICAgdmFyIFZQYXRjaCA9IHJlcXVpcmUoXCIuLi92bm9kZS92cGF0Y2guanNcIik7XG5cbiAgICAgICAgICAgIHZhciB1cGRhdGVXaWRnZXQgPSByZXF1aXJlKFwiLi91cGRhdGUtd2lkZ2V0XCIpO1xuXG4gICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IGFwcGx5UGF0Y2g7XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIGFwcGx5UGF0Y2godnBhdGNoLCBkb21Ob2RlLCByZW5kZXJPcHRpb25zKSB7XG4gICAgICAgICAgICAgICAgdmFyIHR5cGUgPSB2cGF0Y2gudHlwZTtcbiAgICAgICAgICAgICAgICB2YXIgdk5vZGUgPSB2cGF0Y2gudk5vZGU7XG4gICAgICAgICAgICAgICAgdmFyIHBhdGNoID0gdnBhdGNoLnBhdGNoO1xuXG4gICAgICAgICAgICAgICAgc3dpdGNoICh0eXBlKSB7XG4gICAgICAgICAgICAgICAgICAgIGNhc2UgVlBhdGNoLlJFTU9WRTpcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiByZW1vdmVOb2RlKGRvbU5vZGUsIHZOb2RlKTtcbiAgICAgICAgICAgICAgICAgICAgY2FzZSBWUGF0Y2guSU5TRVJUOlxuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGluc2VydE5vZGUoZG9tTm9kZSwgcGF0Y2gsIHJlbmRlck9wdGlvbnMpO1xuICAgICAgICAgICAgICAgICAgICBjYXNlIFZQYXRjaC5WVEVYVDpcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBzdHJpbmdQYXRjaChkb21Ob2RlLCB2Tm9kZSwgcGF0Y2gsIHJlbmRlck9wdGlvbnMpO1xuICAgICAgICAgICAgICAgICAgICBjYXNlIFZQYXRjaC5XSURHRVQ6XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gd2lkZ2V0UGF0Y2goZG9tTm9kZSwgdk5vZGUsIHBhdGNoLCByZW5kZXJPcHRpb25zKTtcbiAgICAgICAgICAgICAgICAgICAgY2FzZSBWUGF0Y2guVk5PREU6XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gdk5vZGVQYXRjaChkb21Ob2RlLCB2Tm9kZSwgcGF0Y2gsIHJlbmRlck9wdGlvbnMpO1xuICAgICAgICAgICAgICAgICAgICBjYXNlIFZQYXRjaC5PUkRFUjpcbiAgICAgICAgICAgICAgICAgICAgICAgIHJlb3JkZXJDaGlsZHJlbihkb21Ob2RlLCBwYXRjaCk7XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gZG9tTm9kZTtcbiAgICAgICAgICAgICAgICAgICAgY2FzZSBWUGF0Y2guUFJPUFM6XG4gICAgICAgICAgICAgICAgICAgICAgICBhcHBseVByb3BlcnRpZXMoZG9tTm9kZSwgcGF0Y2gsIHZOb2RlLnByb3BlcnRpZXMpO1xuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGRvbU5vZGU7XG4gICAgICAgICAgICAgICAgICAgIGNhc2UgVlBhdGNoLlRIVU5LOlxuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHJlcGxhY2VSb290KGRvbU5vZGUsIHJlbmRlck9wdGlvbnMucGF0Y2goZG9tTm9kZSwgcGF0Y2gsIHJlbmRlck9wdGlvbnMpKTtcbiAgICAgICAgICAgICAgICAgICAgZGVmYXVsdDpcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBkb21Ob2RlO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZnVuY3Rpb24gcmVtb3ZlTm9kZShkb21Ob2RlLCB2Tm9kZSkge1xuICAgICAgICAgICAgICAgIHZhciBwYXJlbnROb2RlID0gZG9tTm9kZS5wYXJlbnROb2RlO1xuXG4gICAgICAgICAgICAgICAgaWYgKHBhcmVudE5vZGUpIHtcbiAgICAgICAgICAgICAgICAgICAgcGFyZW50Tm9kZS5yZW1vdmVDaGlsZChkb21Ob2RlKTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICBkZXN0cm95V2lkZ2V0KGRvbU5vZGUsIHZOb2RlKTtcblxuICAgICAgICAgICAgICAgIHJldHVybiBudWxsO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBmdW5jdGlvbiBpbnNlcnROb2RlKHBhcmVudE5vZGUsIHZOb2RlLCByZW5kZXJPcHRpb25zKSB7XG4gICAgICAgICAgICAgICAgdmFyIG5ld05vZGUgPSByZW5kZXJPcHRpb25zLnJlbmRlcih2Tm9kZSwgcmVuZGVyT3B0aW9ucyk7XG5cbiAgICAgICAgICAgICAgICBpZiAocGFyZW50Tm9kZSkge1xuICAgICAgICAgICAgICAgICAgICBwYXJlbnROb2RlLmFwcGVuZENoaWxkKG5ld05vZGUpO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHJldHVybiBwYXJlbnROb2RlO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBmdW5jdGlvbiBzdHJpbmdQYXRjaChkb21Ob2RlLCBsZWZ0Vk5vZGUsIHZUZXh0LCByZW5kZXJPcHRpb25zKSB7XG4gICAgICAgICAgICAgICAgdmFyIG5ld05vZGU7XG5cbiAgICAgICAgICAgICAgICBpZiAoZG9tTm9kZS5ub2RlVHlwZSA9PT0gMykge1xuICAgICAgICAgICAgICAgICAgICBkb21Ob2RlLnJlcGxhY2VEYXRhKDAsIGRvbU5vZGUubGVuZ3RoLCB2VGV4dC50ZXh0KTtcbiAgICAgICAgICAgICAgICAgICAgbmV3Tm9kZSA9IGRvbU5vZGU7XG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgdmFyIHBhcmVudE5vZGUgPSBkb21Ob2RlLnBhcmVudE5vZGU7XG4gICAgICAgICAgICAgICAgICAgIG5ld05vZGUgPSByZW5kZXJPcHRpb25zLnJlbmRlcih2VGV4dCwgcmVuZGVyT3B0aW9ucyk7XG5cbiAgICAgICAgICAgICAgICAgICAgaWYgKHBhcmVudE5vZGUgJiYgbmV3Tm9kZSAhPT0gZG9tTm9kZSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgcGFyZW50Tm9kZS5yZXBsYWNlQ2hpbGQobmV3Tm9kZSwgZG9tTm9kZSk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICByZXR1cm4gbmV3Tm9kZTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZnVuY3Rpb24gd2lkZ2V0UGF0Y2goZG9tTm9kZSwgbGVmdFZOb2RlLCB3aWRnZXQsIHJlbmRlck9wdGlvbnMpIHtcbiAgICAgICAgICAgICAgICB2YXIgdXBkYXRpbmcgPSB1cGRhdGVXaWRnZXQobGVmdFZOb2RlLCB3aWRnZXQpO1xuICAgICAgICAgICAgICAgIHZhciBuZXdOb2RlO1xuXG4gICAgICAgICAgICAgICAgaWYgKHVwZGF0aW5nKSB7XG4gICAgICAgICAgICAgICAgICAgIG5ld05vZGUgPSB3aWRnZXQudXBkYXRlKGxlZnRWTm9kZSwgZG9tTm9kZSkgfHwgZG9tTm9kZTtcbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICBuZXdOb2RlID0gcmVuZGVyT3B0aW9ucy5yZW5kZXIod2lkZ2V0LCByZW5kZXJPcHRpb25zKTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICB2YXIgcGFyZW50Tm9kZSA9IGRvbU5vZGUucGFyZW50Tm9kZTtcblxuICAgICAgICAgICAgICAgIGlmIChwYXJlbnROb2RlICYmIG5ld05vZGUgIT09IGRvbU5vZGUpIHtcbiAgICAgICAgICAgICAgICAgICAgcGFyZW50Tm9kZS5yZXBsYWNlQ2hpbGQobmV3Tm9kZSwgZG9tTm9kZSk7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgaWYgKCF1cGRhdGluZykge1xuICAgICAgICAgICAgICAgICAgICBkZXN0cm95V2lkZ2V0KGRvbU5vZGUsIGxlZnRWTm9kZSk7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgcmV0dXJuIG5ld05vZGU7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIHZOb2RlUGF0Y2goZG9tTm9kZSwgbGVmdFZOb2RlLCB2Tm9kZSwgcmVuZGVyT3B0aW9ucykge1xuICAgICAgICAgICAgICAgIHZhciBwYXJlbnROb2RlID0gZG9tTm9kZS5wYXJlbnROb2RlO1xuICAgICAgICAgICAgICAgIHZhciBuZXdOb2RlID0gcmVuZGVyT3B0aW9ucy5yZW5kZXIodk5vZGUsIHJlbmRlck9wdGlvbnMpO1xuXG4gICAgICAgICAgICAgICAgaWYgKHBhcmVudE5vZGUgJiYgbmV3Tm9kZSAhPT0gZG9tTm9kZSkge1xuICAgICAgICAgICAgICAgICAgICBwYXJlbnROb2RlLnJlcGxhY2VDaGlsZChuZXdOb2RlLCBkb21Ob2RlKTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICByZXR1cm4gbmV3Tm9kZTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZnVuY3Rpb24gZGVzdHJveVdpZGdldChkb21Ob2RlLCB3KSB7XG4gICAgICAgICAgICAgICAgaWYgKHR5cGVvZiB3LmRlc3Ryb3kgPT09IFwiZnVuY3Rpb25cIiAmJiBpc1dpZGdldCh3KSkge1xuICAgICAgICAgICAgICAgICAgICB3LmRlc3Ryb3koZG9tTm9kZSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBmdW5jdGlvbiByZW9yZGVyQ2hpbGRyZW4oZG9tTm9kZSwgbW92ZXMpIHtcbiAgICAgICAgICAgICAgICB2YXIgY2hpbGROb2RlcyA9IGRvbU5vZGUuY2hpbGROb2RlcztcbiAgICAgICAgICAgICAgICB2YXIga2V5TWFwID0ge307XG4gICAgICAgICAgICAgICAgdmFyIG5vZGU7XG4gICAgICAgICAgICAgICAgdmFyIHJlbW92ZTtcbiAgICAgICAgICAgICAgICB2YXIgaW5zZXJ0O1xuXG4gICAgICAgICAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCBtb3Zlcy5yZW1vdmVzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICAgICAgICAgIHJlbW92ZSA9IG1vdmVzLnJlbW92ZXNbaV07XG4gICAgICAgICAgICAgICAgICAgIG5vZGUgPSBjaGlsZE5vZGVzW3JlbW92ZS5mcm9tXTtcbiAgICAgICAgICAgICAgICAgICAgaWYgKHJlbW92ZS5rZXkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGtleU1hcFtyZW1vdmUua2V5XSA9IG5vZGU7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgZG9tTm9kZS5yZW1vdmVDaGlsZChub2RlKTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICB2YXIgbGVuZ3RoID0gY2hpbGROb2Rlcy5sZW5ndGg7XG4gICAgICAgICAgICAgICAgZm9yICh2YXIgaiA9IDA7IGogPCBtb3Zlcy5pbnNlcnRzLmxlbmd0aDsgaisrKSB7XG4gICAgICAgICAgICAgICAgICAgIGluc2VydCA9IG1vdmVzLmluc2VydHNbal07XG4gICAgICAgICAgICAgICAgICAgIG5vZGUgPSBrZXlNYXBbaW5zZXJ0LmtleV07XG4gICAgICAgICAgICAgICAgICAgIC8vIHRoaXMgaXMgdGhlIHdlaXJkZXN0IGJ1ZyBpJ3ZlIGV2ZXIgc2VlbiBpbiB3ZWJraXRcbiAgICAgICAgICAgICAgICAgICAgZG9tTm9kZS5pbnNlcnRCZWZvcmUobm9kZSwgaW5zZXJ0LnRvID49IGxlbmd0aCsrID8gbnVsbCA6IGNoaWxkTm9kZXNbaW5zZXJ0LnRvXSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBmdW5jdGlvbiByZXBsYWNlUm9vdChvbGRSb290LCBuZXdSb290KSB7XG4gICAgICAgICAgICAgICAgaWYgKG9sZFJvb3QgJiYgbmV3Um9vdCAmJiBvbGRSb290ICE9PSBuZXdSb290ICYmIG9sZFJvb3QucGFyZW50Tm9kZSkge1xuICAgICAgICAgICAgICAgICAgICBvbGRSb290LnBhcmVudE5vZGUucmVwbGFjZUNoaWxkKG5ld1Jvb3QsIG9sZFJvb3QpO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHJldHVybiBuZXdSb290O1xuICAgICAgICAgICAgfVxuICAgICAgICB9LCB7IFwiLi4vdm5vZGUvaXMtd2lkZ2V0LmpzXCI6IDI5LCBcIi4uL3Zub2RlL3ZwYXRjaC5qc1wiOiAzMiwgXCIuL2FwcGx5LXByb3BlcnRpZXNcIjogMTQsIFwiLi91cGRhdGUtd2lkZ2V0XCI6IDE5IH1dLCAxODogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHtcbiAgICAgICAgICAgIHZhciBkb2N1bWVudCA9IHJlcXVpcmUoXCJnbG9iYWwvZG9jdW1lbnRcIik7XG4gICAgICAgICAgICB2YXIgaXNBcnJheSA9IHJlcXVpcmUoXCJ4LWlzLWFycmF5XCIpO1xuXG4gICAgICAgICAgICB2YXIgcmVuZGVyID0gcmVxdWlyZShcIi4vY3JlYXRlLWVsZW1lbnRcIik7XG4gICAgICAgICAgICB2YXIgZG9tSW5kZXggPSByZXF1aXJlKFwiLi9kb20taW5kZXhcIik7XG4gICAgICAgICAgICB2YXIgcGF0Y2hPcCA9IHJlcXVpcmUoXCIuL3BhdGNoLW9wXCIpO1xuICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBwYXRjaDtcblxuICAgICAgICAgICAgZnVuY3Rpb24gcGF0Y2gocm9vdE5vZGUsIHBhdGNoZXMsIHJlbmRlck9wdGlvbnMpIHtcbiAgICAgICAgICAgICAgICByZW5kZXJPcHRpb25zID0gcmVuZGVyT3B0aW9ucyB8fCB7fTtcbiAgICAgICAgICAgICAgICByZW5kZXJPcHRpb25zLnBhdGNoID0gcmVuZGVyT3B0aW9ucy5wYXRjaCAmJiByZW5kZXJPcHRpb25zLnBhdGNoICE9PSBwYXRjaCA/IHJlbmRlck9wdGlvbnMucGF0Y2ggOiBwYXRjaFJlY3Vyc2l2ZTtcbiAgICAgICAgICAgICAgICByZW5kZXJPcHRpb25zLnJlbmRlciA9IHJlbmRlck9wdGlvbnMucmVuZGVyIHx8IHJlbmRlcjtcblxuICAgICAgICAgICAgICAgIHJldHVybiByZW5kZXJPcHRpb25zLnBhdGNoKHJvb3ROb2RlLCBwYXRjaGVzLCByZW5kZXJPcHRpb25zKTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZnVuY3Rpb24gcGF0Y2hSZWN1cnNpdmUocm9vdE5vZGUsIHBhdGNoZXMsIHJlbmRlck9wdGlvbnMpIHtcbiAgICAgICAgICAgICAgICB2YXIgaW5kaWNlcyA9IHBhdGNoSW5kaWNlcyhwYXRjaGVzKTtcblxuICAgICAgICAgICAgICAgIGlmIChpbmRpY2VzLmxlbmd0aCA9PT0gMCkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gcm9vdE5vZGU7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgdmFyIGluZGV4ID0gZG9tSW5kZXgocm9vdE5vZGUsIHBhdGNoZXMuYSwgaW5kaWNlcyk7XG4gICAgICAgICAgICAgICAgdmFyIG93bmVyRG9jdW1lbnQgPSByb290Tm9kZS5vd25lckRvY3VtZW50O1xuXG4gICAgICAgICAgICAgICAgaWYgKCFyZW5kZXJPcHRpb25zLmRvY3VtZW50ICYmIG93bmVyRG9jdW1lbnQgIT09IGRvY3VtZW50KSB7XG4gICAgICAgICAgICAgICAgICAgIHJlbmRlck9wdGlvbnMuZG9jdW1lbnQgPSBvd25lckRvY3VtZW50O1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgaW5kaWNlcy5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgICAgICAgICB2YXIgbm9kZUluZGV4ID0gaW5kaWNlc1tpXTtcbiAgICAgICAgICAgICAgICAgICAgcm9vdE5vZGUgPSBhcHBseVBhdGNoKHJvb3ROb2RlLCBpbmRleFtub2RlSW5kZXhdLCBwYXRjaGVzW25vZGVJbmRleF0sIHJlbmRlck9wdGlvbnMpO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHJldHVybiByb290Tm9kZTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZnVuY3Rpb24gYXBwbHlQYXRjaChyb290Tm9kZSwgZG9tTm9kZSwgcGF0Y2hMaXN0LCByZW5kZXJPcHRpb25zKSB7XG4gICAgICAgICAgICAgICAgaWYgKCFkb21Ob2RlKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiByb290Tm9kZTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICB2YXIgbmV3Tm9kZTtcblxuICAgICAgICAgICAgICAgIGlmIChpc0FycmF5KHBhdGNoTGlzdCkpIHtcbiAgICAgICAgICAgICAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCBwYXRjaExpc3QubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIG5ld05vZGUgPSBwYXRjaE9wKHBhdGNoTGlzdFtpXSwgZG9tTm9kZSwgcmVuZGVyT3B0aW9ucyk7XG5cbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChkb21Ob2RlID09PSByb290Tm9kZSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJvb3ROb2RlID0gbmV3Tm9kZTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIG5ld05vZGUgPSBwYXRjaE9wKHBhdGNoTGlzdCwgZG9tTm9kZSwgcmVuZGVyT3B0aW9ucyk7XG5cbiAgICAgICAgICAgICAgICAgICAgaWYgKGRvbU5vZGUgPT09IHJvb3ROb2RlKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICByb290Tm9kZSA9IG5ld05vZGU7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICByZXR1cm4gcm9vdE5vZGU7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIHBhdGNoSW5kaWNlcyhwYXRjaGVzKSB7XG4gICAgICAgICAgICAgICAgdmFyIGluZGljZXMgPSBbXTtcblxuICAgICAgICAgICAgICAgIGZvciAodmFyIGtleSBpbiBwYXRjaGVzKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmIChrZXkgIT09IFwiYVwiKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBpbmRpY2VzLnB1c2goTnVtYmVyKGtleSkpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgcmV0dXJuIGluZGljZXM7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0sIHsgXCIuL2NyZWF0ZS1lbGVtZW50XCI6IDE1LCBcIi4vZG9tLWluZGV4XCI6IDE2LCBcIi4vcGF0Y2gtb3BcIjogMTcsIFwiZ2xvYmFsL2RvY3VtZW50XCI6IDEwLCBcIngtaXMtYXJyYXlcIjogMTIgfV0sIDE5OiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge1xuICAgICAgICAgICAgdmFyIGlzV2lkZ2V0ID0gcmVxdWlyZShcIi4uL3Zub2RlL2lzLXdpZGdldC5qc1wiKTtcblxuICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSB1cGRhdGVXaWRnZXQ7XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIHVwZGF0ZVdpZGdldChhLCBiKSB7XG4gICAgICAgICAgICAgICAgaWYgKGlzV2lkZ2V0KGEpICYmIGlzV2lkZ2V0KGIpKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmIChcIm5hbWVcIiBpbiBhICYmIFwibmFtZVwiIGluIGIpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBhLmlkID09PSBiLmlkO1xuICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGEuaW5pdCA9PT0gYi5pbml0O1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICAgICAgfVxuICAgICAgICB9LCB7IFwiLi4vdm5vZGUvaXMtd2lkZ2V0LmpzXCI6IDI5IH1dLCAyMDogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHtcbiAgICAgICAgICAgIFwidXNlIHN0cmljdFwiO1xuXG4gICAgICAgICAgICB2YXIgRXZTdG9yZSA9IHJlcXVpcmUoXCJldi1zdG9yZVwiKTtcblxuICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBFdkhvb2s7XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIEV2SG9vayh2YWx1ZSkge1xuICAgICAgICAgICAgICAgIGlmICghKHRoaXMgaW5zdGFuY2VvZiBFdkhvb2spKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBuZXcgRXZIb29rKHZhbHVlKTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICB0aGlzLnZhbHVlID0gdmFsdWU7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIEV2SG9vay5wcm90b3R5cGUuaG9vayA9IGZ1bmN0aW9uIChub2RlLCBwcm9wZXJ0eU5hbWUpIHtcbiAgICAgICAgICAgICAgICB2YXIgZXMgPSBFdlN0b3JlKG5vZGUpO1xuICAgICAgICAgICAgICAgIHZhciBwcm9wTmFtZSA9IHByb3BlcnR5TmFtZS5zdWJzdHIoMyk7XG5cbiAgICAgICAgICAgICAgICBlc1twcm9wTmFtZV0gPSB0aGlzLnZhbHVlO1xuICAgICAgICAgICAgfTtcblxuICAgICAgICAgICAgRXZIb29rLnByb3RvdHlwZS51bmhvb2sgPSBmdW5jdGlvbiAobm9kZSwgcHJvcGVydHlOYW1lKSB7XG4gICAgICAgICAgICAgICAgdmFyIGVzID0gRXZTdG9yZShub2RlKTtcbiAgICAgICAgICAgICAgICB2YXIgcHJvcE5hbWUgPSBwcm9wZXJ0eU5hbWUuc3Vic3RyKDMpO1xuXG4gICAgICAgICAgICAgICAgZXNbcHJvcE5hbWVdID0gdW5kZWZpbmVkO1xuICAgICAgICAgICAgfTtcbiAgICAgICAgfSwgeyBcImV2LXN0b3JlXCI6IDcgfV0sIDIxOiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge1xuICAgICAgICAgICAgXCJ1c2Ugc3RyaWN0XCI7XG5cbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gU29mdFNldEhvb2s7XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIFNvZnRTZXRIb29rKHZhbHVlKSB7XG4gICAgICAgICAgICAgICAgaWYgKCEodGhpcyBpbnN0YW5jZW9mIFNvZnRTZXRIb29rKSkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gbmV3IFNvZnRTZXRIb29rKHZhbHVlKTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICB0aGlzLnZhbHVlID0gdmFsdWU7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIFNvZnRTZXRIb29rLnByb3RvdHlwZS5ob29rID0gZnVuY3Rpb24gKG5vZGUsIHByb3BlcnR5TmFtZSkge1xuICAgICAgICAgICAgICAgIGlmIChub2RlW3Byb3BlcnR5TmFtZV0gIT09IHRoaXMudmFsdWUpIHtcbiAgICAgICAgICAgICAgICAgICAgbm9kZVtwcm9wZXJ0eU5hbWVdID0gdGhpcy52YWx1ZTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9O1xuICAgICAgICB9LCB7fV0sIDIyOiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge1xuICAgICAgICAgICAgXCJ1c2Ugc3RyaWN0XCI7XG5cbiAgICAgICAgICAgIHZhciBpc0FycmF5ID0gcmVxdWlyZShcIngtaXMtYXJyYXlcIik7XG5cbiAgICAgICAgICAgIHZhciBWTm9kZSA9IHJlcXVpcmUoXCIuLi92bm9kZS92bm9kZS5qc1wiKTtcbiAgICAgICAgICAgIHZhciBWVGV4dCA9IHJlcXVpcmUoXCIuLi92bm9kZS92dGV4dC5qc1wiKTtcbiAgICAgICAgICAgIHZhciBpc1ZOb2RlID0gcmVxdWlyZShcIi4uL3Zub2RlL2lzLXZub2RlXCIpO1xuICAgICAgICAgICAgdmFyIGlzVlRleHQgPSByZXF1aXJlKFwiLi4vdm5vZGUvaXMtdnRleHRcIik7XG4gICAgICAgICAgICB2YXIgaXNXaWRnZXQgPSByZXF1aXJlKFwiLi4vdm5vZGUvaXMtd2lkZ2V0XCIpO1xuICAgICAgICAgICAgdmFyIGlzSG9vayA9IHJlcXVpcmUoXCIuLi92bm9kZS9pcy12aG9va1wiKTtcbiAgICAgICAgICAgIHZhciBpc1ZUaHVuayA9IHJlcXVpcmUoXCIuLi92bm9kZS9pcy10aHVua1wiKTtcblxuICAgICAgICAgICAgdmFyIHBhcnNlVGFnID0gcmVxdWlyZShcIi4vcGFyc2UtdGFnLmpzXCIpO1xuICAgICAgICAgICAgdmFyIHNvZnRTZXRIb29rID0gcmVxdWlyZShcIi4vaG9va3Mvc29mdC1zZXQtaG9vay5qc1wiKTtcbiAgICAgICAgICAgIHZhciBldkhvb2sgPSByZXF1aXJlKFwiLi9ob29rcy9ldi1ob29rLmpzXCIpO1xuXG4gICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IGg7XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIGgodGFnTmFtZSwgcHJvcGVydGllcywgY2hpbGRyZW4pIHtcbiAgICAgICAgICAgICAgICB2YXIgY2hpbGROb2RlcyA9IFtdO1xuICAgICAgICAgICAgICAgIHZhciB0YWcsIHByb3BzLCBrZXksIG5hbWVzcGFjZTtcblxuICAgICAgICAgICAgICAgIGlmICghY2hpbGRyZW4gJiYgaXNDaGlsZHJlbihwcm9wZXJ0aWVzKSkge1xuICAgICAgICAgICAgICAgICAgICBjaGlsZHJlbiA9IHByb3BlcnRpZXM7XG4gICAgICAgICAgICAgICAgICAgIHByb3BzID0ge307XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgcHJvcHMgPSBwcm9wcyB8fCBwcm9wZXJ0aWVzIHx8IHt9O1xuICAgICAgICAgICAgICAgIHRhZyA9IHBhcnNlVGFnKHRhZ05hbWUsIHByb3BzKTtcblxuICAgICAgICAgICAgICAgIC8vIHN1cHBvcnQga2V5c1xuICAgICAgICAgICAgICAgIGlmIChwcm9wcy5oYXNPd25Qcm9wZXJ0eShcImtleVwiKSkge1xuICAgICAgICAgICAgICAgICAgICBrZXkgPSBwcm9wcy5rZXk7XG4gICAgICAgICAgICAgICAgICAgIHByb3BzLmtleSA9IHVuZGVmaW5lZDtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAvLyBzdXBwb3J0IG5hbWVzcGFjZVxuICAgICAgICAgICAgICAgIGlmIChwcm9wcy5oYXNPd25Qcm9wZXJ0eShcIm5hbWVzcGFjZVwiKSkge1xuICAgICAgICAgICAgICAgICAgICBuYW1lc3BhY2UgPSBwcm9wcy5uYW1lc3BhY2U7XG4gICAgICAgICAgICAgICAgICAgIHByb3BzLm5hbWVzcGFjZSA9IHVuZGVmaW5lZDtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAvLyBmaXggY3Vyc29yIGJ1Z1xuICAgICAgICAgICAgICAgIGlmICh0YWcgPT09IFwiSU5QVVRcIiAmJiAhbmFtZXNwYWNlICYmIHByb3BzLmhhc093blByb3BlcnR5KFwidmFsdWVcIikgJiYgcHJvcHMudmFsdWUgIT09IHVuZGVmaW5lZCAmJiAhaXNIb29rKHByb3BzLnZhbHVlKSkge1xuICAgICAgICAgICAgICAgICAgICBwcm9wcy52YWx1ZSA9IHNvZnRTZXRIb29rKHByb3BzLnZhbHVlKTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICB0cmFuc2Zvcm1Qcm9wZXJ0aWVzKHByb3BzKTtcblxuICAgICAgICAgICAgICAgIGlmIChjaGlsZHJlbiAhPT0gdW5kZWZpbmVkICYmIGNoaWxkcmVuICE9PSBudWxsKSB7XG4gICAgICAgICAgICAgICAgICAgIGFkZENoaWxkKGNoaWxkcmVuLCBjaGlsZE5vZGVzLCB0YWcsIHByb3BzKTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICByZXR1cm4gbmV3IFZOb2RlKHRhZywgcHJvcHMsIGNoaWxkTm9kZXMsIGtleSwgbmFtZXNwYWNlKTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZnVuY3Rpb24gYWRkQ2hpbGQoYywgY2hpbGROb2RlcywgdGFnLCBwcm9wcykge1xuICAgICAgICAgICAgICAgIGlmICh0eXBlb2YgYyA9PT0gXCJzdHJpbmdcIikge1xuICAgICAgICAgICAgICAgICAgICBjaGlsZE5vZGVzLnB1c2gobmV3IFZUZXh0KGMpKTtcbiAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKHR5cGVvZiBjID09PSBcIm51bWJlclwiKSB7XG4gICAgICAgICAgICAgICAgICAgIGNoaWxkTm9kZXMucHVzaChuZXcgVlRleHQoU3RyaW5nKGMpKSk7XG4gICAgICAgICAgICAgICAgfSBlbHNlIGlmIChpc0NoaWxkKGMpKSB7XG4gICAgICAgICAgICAgICAgICAgIGNoaWxkTm9kZXMucHVzaChjKTtcbiAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKGlzQXJyYXkoYykpIHtcbiAgICAgICAgICAgICAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCBjLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBhZGRDaGlsZChjW2ldLCBjaGlsZE5vZGVzLCB0YWcsIHByb3BzKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoYyA9PT0gbnVsbCB8fCBjID09PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIHRocm93IFVuZXhwZWN0ZWRWaXJ0dWFsRWxlbWVudCh7XG4gICAgICAgICAgICAgICAgICAgICAgICBmb3JlaWduT2JqZWN0OiBjLFxuICAgICAgICAgICAgICAgICAgICAgICAgcGFyZW50Vm5vZGU6IHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0YWdOYW1lOiB0YWcsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcHJvcGVydGllczogcHJvcHNcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBmdW5jdGlvbiB0cmFuc2Zvcm1Qcm9wZXJ0aWVzKHByb3BzKSB7XG4gICAgICAgICAgICAgICAgZm9yICh2YXIgcHJvcE5hbWUgaW4gcHJvcHMpIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKHByb3BzLmhhc093blByb3BlcnR5KHByb3BOYW1lKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgdmFyIHZhbHVlID0gcHJvcHNbcHJvcE5hbWVdO1xuXG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoaXNIb29rKHZhbHVlKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnRpbnVlO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAocHJvcE5hbWUuc3Vic3RyKDAsIDMpID09PSBcImV2LVwiKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gYWRkIGV2LWZvbyBzdXBwb3J0XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcHJvcHNbcHJvcE5hbWVdID0gZXZIb29rKHZhbHVlKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZnVuY3Rpb24gaXNDaGlsZCh4KSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGlzVk5vZGUoeCkgfHwgaXNWVGV4dCh4KSB8fCBpc1dpZGdldCh4KSB8fCBpc1ZUaHVuayh4KTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZnVuY3Rpb24gaXNDaGlsZHJlbih4KSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHR5cGVvZiB4ID09PSBcInN0cmluZ1wiIHx8IGlzQXJyYXkoeCkgfHwgaXNDaGlsZCh4KTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZnVuY3Rpb24gVW5leHBlY3RlZFZpcnR1YWxFbGVtZW50KGRhdGEpIHtcbiAgICAgICAgICAgICAgICB2YXIgZXJyID0gbmV3IEVycm9yKCk7XG5cbiAgICAgICAgICAgICAgICBlcnIudHlwZSA9IFwidmlydHVhbC1oeXBlcnNjcmlwdC51bmV4cGVjdGVkLnZpcnR1YWwtZWxlbWVudFwiO1xuICAgICAgICAgICAgICAgIGVyci5tZXNzYWdlID0gXCJVbmV4cGVjdGVkIHZpcnR1YWwgY2hpbGQgcGFzc2VkIHRvIGgoKS5cXG5cIiArIFwiRXhwZWN0ZWQgYSBWTm9kZSAvIFZ0aHVuayAvIFZXaWRnZXQgLyBzdHJpbmcgYnV0OlxcblwiICsgXCJnb3Q6XFxuXCIgKyBlcnJvclN0cmluZyhkYXRhLmZvcmVpZ25PYmplY3QpICsgXCIuXFxuXCIgKyBcIlRoZSBwYXJlbnQgdm5vZGUgaXM6XFxuXCIgKyBlcnJvclN0cmluZyhkYXRhLnBhcmVudFZub2RlKTtcbiAgICAgICAgICAgICAgICBcIlxcblwiICsgXCJTdWdnZXN0ZWQgZml4OiBjaGFuZ2UgeW91ciBgaCguLi4sIFsgLi4uIF0pYCBjYWxsc2l0ZS5cIjtcbiAgICAgICAgICAgICAgICBlcnIuZm9yZWlnbk9iamVjdCA9IGRhdGEuZm9yZWlnbk9iamVjdDtcbiAgICAgICAgICAgICAgICBlcnIucGFyZW50Vm5vZGUgPSBkYXRhLnBhcmVudFZub2RlO1xuXG4gICAgICAgICAgICAgICAgcmV0dXJuIGVycjtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZnVuY3Rpb24gZXJyb3JTdHJpbmcob2JqKSB7XG4gICAgICAgICAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIEpTT04uc3RyaW5naWZ5KG9iaiwgbnVsbCwgXCIgICAgXCIpO1xuICAgICAgICAgICAgICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIFN0cmluZyhvYmopO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgfSwgeyBcIi4uL3Zub2RlL2lzLXRodW5rXCI6IDI1LCBcIi4uL3Zub2RlL2lzLXZob29rXCI6IDI2LCBcIi4uL3Zub2RlL2lzLXZub2RlXCI6IDI3LCBcIi4uL3Zub2RlL2lzLXZ0ZXh0XCI6IDI4LCBcIi4uL3Zub2RlL2lzLXdpZGdldFwiOiAyOSwgXCIuLi92bm9kZS92bm9kZS5qc1wiOiAzMSwgXCIuLi92bm9kZS92dGV4dC5qc1wiOiAzMywgXCIuL2hvb2tzL2V2LWhvb2suanNcIjogMjAsIFwiLi9ob29rcy9zb2Z0LXNldC1ob29rLmpzXCI6IDIxLCBcIi4vcGFyc2UtdGFnLmpzXCI6IDIzLCBcIngtaXMtYXJyYXlcIjogMTIgfV0sIDIzOiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge1xuICAgICAgICAgICAgXCJ1c2Ugc3RyaWN0XCI7XG5cbiAgICAgICAgICAgIHZhciBzcGxpdCA9IHJlcXVpcmUoXCJicm93c2VyLXNwbGl0XCIpO1xuXG4gICAgICAgICAgICB2YXIgY2xhc3NJZFNwbGl0ID0gLyhbXFwuI10/W2EtekEtWjAtOVxcdTAwN0YtXFx1RkZGRl86LV0rKS87XG4gICAgICAgICAgICB2YXIgbm90Q2xhc3NJZCA9IC9eXFwufCMvO1xuXG4gICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IHBhcnNlVGFnO1xuXG4gICAgICAgICAgICBmdW5jdGlvbiBwYXJzZVRhZyh0YWcsIHByb3BzKSB7XG4gICAgICAgICAgICAgICAgaWYgKCF0YWcpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIFwiRElWXCI7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgdmFyIG5vSWQgPSAhcHJvcHMuaGFzT3duUHJvcGVydHkoXCJpZFwiKTtcblxuICAgICAgICAgICAgICAgIHZhciB0YWdQYXJ0cyA9IHNwbGl0KHRhZywgY2xhc3NJZFNwbGl0KTtcbiAgICAgICAgICAgICAgICB2YXIgdGFnTmFtZSA9IG51bGw7XG5cbiAgICAgICAgICAgICAgICBpZiAobm90Q2xhc3NJZC50ZXN0KHRhZ1BhcnRzWzFdKSkge1xuICAgICAgICAgICAgICAgICAgICB0YWdOYW1lID0gXCJESVZcIjtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICB2YXIgY2xhc3NlcywgcGFydCwgdHlwZSwgaTtcblxuICAgICAgICAgICAgICAgIGZvciAoaSA9IDA7IGkgPCB0YWdQYXJ0cy5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgICAgICAgICBwYXJ0ID0gdGFnUGFydHNbaV07XG5cbiAgICAgICAgICAgICAgICAgICAgaWYgKCFwYXJ0KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBjb250aW51ZTtcbiAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgIHR5cGUgPSBwYXJ0LmNoYXJBdCgwKTtcblxuICAgICAgICAgICAgICAgICAgICBpZiAoIXRhZ05hbWUpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHRhZ05hbWUgPSBwYXJ0O1xuICAgICAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKHR5cGUgPT09IFwiLlwiKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBjbGFzc2VzID0gY2xhc3NlcyB8fCBbXTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGNsYXNzZXMucHVzaChwYXJ0LnN1YnN0cmluZygxLCBwYXJ0Lmxlbmd0aCkpO1xuICAgICAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKHR5cGUgPT09IFwiI1wiICYmIG5vSWQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHByb3BzLmlkID0gcGFydC5zdWJzdHJpbmcoMSwgcGFydC5sZW5ndGgpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgaWYgKGNsYXNzZXMpIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKHByb3BzLmNsYXNzTmFtZSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgY2xhc3Nlcy5wdXNoKHByb3BzLmNsYXNzTmFtZSk7XG4gICAgICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgICAgICBwcm9wcy5jbGFzc05hbWUgPSBjbGFzc2VzLmpvaW4oXCIgXCIpO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHJldHVybiBwcm9wcy5uYW1lc3BhY2UgPyB0YWdOYW1lIDogdGFnTmFtZS50b1VwcGVyQ2FzZSgpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9LCB7IFwiYnJvd3Nlci1zcGxpdFwiOiA1IH1dLCAyNDogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHtcbiAgICAgICAgICAgIHZhciBpc1ZOb2RlID0gcmVxdWlyZShcIi4vaXMtdm5vZGVcIik7XG4gICAgICAgICAgICB2YXIgaXNWVGV4dCA9IHJlcXVpcmUoXCIuL2lzLXZ0ZXh0XCIpO1xuICAgICAgICAgICAgdmFyIGlzV2lkZ2V0ID0gcmVxdWlyZShcIi4vaXMtd2lkZ2V0XCIpO1xuICAgICAgICAgICAgdmFyIGlzVGh1bmsgPSByZXF1aXJlKFwiLi9pcy10aHVua1wiKTtcblxuICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBoYW5kbGVUaHVuaztcblxuICAgICAgICAgICAgZnVuY3Rpb24gaGFuZGxlVGh1bmsoYSwgYikge1xuICAgICAgICAgICAgICAgIHZhciByZW5kZXJlZEEgPSBhO1xuICAgICAgICAgICAgICAgIHZhciByZW5kZXJlZEIgPSBiO1xuXG4gICAgICAgICAgICAgICAgaWYgKGlzVGh1bmsoYikpIHtcbiAgICAgICAgICAgICAgICAgICAgcmVuZGVyZWRCID0gcmVuZGVyVGh1bmsoYiwgYSk7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgaWYgKGlzVGh1bmsoYSkpIHtcbiAgICAgICAgICAgICAgICAgICAgcmVuZGVyZWRBID0gcmVuZGVyVGh1bmsoYSwgbnVsbCk7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgICAgICAgICAgYTogcmVuZGVyZWRBLFxuICAgICAgICAgICAgICAgICAgICBiOiByZW5kZXJlZEJcbiAgICAgICAgICAgICAgICB9O1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBmdW5jdGlvbiByZW5kZXJUaHVuayh0aHVuaywgcHJldmlvdXMpIHtcbiAgICAgICAgICAgICAgICB2YXIgcmVuZGVyZWRUaHVuayA9IHRodW5rLnZub2RlO1xuXG4gICAgICAgICAgICAgICAgaWYgKCFyZW5kZXJlZFRodW5rKSB7XG4gICAgICAgICAgICAgICAgICAgIHJlbmRlcmVkVGh1bmsgPSB0aHVuay52bm9kZSA9IHRodW5rLnJlbmRlcihwcmV2aW91cyk7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgaWYgKCEoaXNWTm9kZShyZW5kZXJlZFRodW5rKSB8fCBpc1ZUZXh0KHJlbmRlcmVkVGh1bmspIHx8IGlzV2lkZ2V0KHJlbmRlcmVkVGh1bmspKSkge1xuICAgICAgICAgICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoXCJ0aHVuayBkaWQgbm90IHJldHVybiBhIHZhbGlkIG5vZGVcIik7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgcmV0dXJuIHJlbmRlcmVkVGh1bms7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0sIHsgXCIuL2lzLXRodW5rXCI6IDI1LCBcIi4vaXMtdm5vZGVcIjogMjcsIFwiLi9pcy12dGV4dFwiOiAyOCwgXCIuL2lzLXdpZGdldFwiOiAyOSB9XSwgMjU6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IGlzVGh1bms7XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIGlzVGh1bmsodCkge1xuICAgICAgICAgICAgICAgIHJldHVybiB0ICYmIHQudHlwZSA9PT0gXCJUaHVua1wiO1xuICAgICAgICAgICAgfVxuICAgICAgICB9LCB7fV0sIDI2OiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge1xuICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBpc0hvb2s7XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIGlzSG9vayhob29rKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGhvb2sgJiYgKHR5cGVvZiBob29rLmhvb2sgPT09IFwiZnVuY3Rpb25cIiAmJiAhaG9vay5oYXNPd25Qcm9wZXJ0eShcImhvb2tcIikgfHwgdHlwZW9mIGhvb2sudW5ob29rID09PSBcImZ1bmN0aW9uXCIgJiYgIWhvb2suaGFzT3duUHJvcGVydHkoXCJ1bmhvb2tcIikpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9LCB7fV0sIDI3OiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge1xuICAgICAgICAgICAgdmFyIHZlcnNpb24gPSByZXF1aXJlKFwiLi92ZXJzaW9uXCIpO1xuXG4gICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IGlzVmlydHVhbE5vZGU7XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIGlzVmlydHVhbE5vZGUoeCkge1xuICAgICAgICAgICAgICAgIHJldHVybiB4ICYmIHgudHlwZSA9PT0gXCJWaXJ0dWFsTm9kZVwiICYmIHgudmVyc2lvbiA9PT0gdmVyc2lvbjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSwgeyBcIi4vdmVyc2lvblwiOiAzMCB9XSwgMjg6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICB2YXIgdmVyc2lvbiA9IHJlcXVpcmUoXCIuL3ZlcnNpb25cIik7XG5cbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gaXNWaXJ0dWFsVGV4dDtcblxuICAgICAgICAgICAgZnVuY3Rpb24gaXNWaXJ0dWFsVGV4dCh4KSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHggJiYgeC50eXBlID09PSBcIlZpcnR1YWxUZXh0XCIgJiYgeC52ZXJzaW9uID09PSB2ZXJzaW9uO1xuICAgICAgICAgICAgfVxuICAgICAgICB9LCB7IFwiLi92ZXJzaW9uXCI6IDMwIH1dLCAyOTogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHtcbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gaXNXaWRnZXQ7XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIGlzV2lkZ2V0KHcpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gdyAmJiB3LnR5cGUgPT09IFwiV2lkZ2V0XCI7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0sIHt9XSwgMzA6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IFwiMlwiO1xuICAgICAgICB9LCB7fV0sIDMxOiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge1xuICAgICAgICAgICAgdmFyIHZlcnNpb24gPSByZXF1aXJlKFwiLi92ZXJzaW9uXCIpO1xuICAgICAgICAgICAgdmFyIGlzVk5vZGUgPSByZXF1aXJlKFwiLi9pcy12bm9kZVwiKTtcbiAgICAgICAgICAgIHZhciBpc1dpZGdldCA9IHJlcXVpcmUoXCIuL2lzLXdpZGdldFwiKTtcbiAgICAgICAgICAgIHZhciBpc1RodW5rID0gcmVxdWlyZShcIi4vaXMtdGh1bmtcIik7XG4gICAgICAgICAgICB2YXIgaXNWSG9vayA9IHJlcXVpcmUoXCIuL2lzLXZob29rXCIpO1xuXG4gICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IFZpcnR1YWxOb2RlO1xuXG4gICAgICAgICAgICB2YXIgbm9Qcm9wZXJ0aWVzID0ge307XG4gICAgICAgICAgICB2YXIgbm9DaGlsZHJlbiA9IFtdO1xuXG4gICAgICAgICAgICBmdW5jdGlvbiBWaXJ0dWFsTm9kZSh0YWdOYW1lLCBwcm9wZXJ0aWVzLCBjaGlsZHJlbiwga2V5LCBuYW1lc3BhY2UpIHtcbiAgICAgICAgICAgICAgICB0aGlzLnRhZ05hbWUgPSB0YWdOYW1lO1xuICAgICAgICAgICAgICAgIHRoaXMucHJvcGVydGllcyA9IHByb3BlcnRpZXMgfHwgbm9Qcm9wZXJ0aWVzO1xuICAgICAgICAgICAgICAgIHRoaXMuY2hpbGRyZW4gPSBjaGlsZHJlbiB8fCBub0NoaWxkcmVuO1xuICAgICAgICAgICAgICAgIHRoaXMua2V5ID0ga2V5ICE9IG51bGwgPyBTdHJpbmcoa2V5KSA6IHVuZGVmaW5lZDtcbiAgICAgICAgICAgICAgICB0aGlzLm5hbWVzcGFjZSA9IHR5cGVvZiBuYW1lc3BhY2UgPT09IFwic3RyaW5nXCIgPyBuYW1lc3BhY2UgOiBudWxsO1xuXG4gICAgICAgICAgICAgICAgdmFyIGNvdW50ID0gY2hpbGRyZW4gJiYgY2hpbGRyZW4ubGVuZ3RoIHx8IDA7XG4gICAgICAgICAgICAgICAgdmFyIGRlc2NlbmRhbnRzID0gMDtcbiAgICAgICAgICAgICAgICB2YXIgaGFzV2lkZ2V0cyA9IGZhbHNlO1xuICAgICAgICAgICAgICAgIHZhciBoYXNUaHVua3MgPSBmYWxzZTtcbiAgICAgICAgICAgICAgICB2YXIgZGVzY2VuZGFudEhvb2tzID0gZmFsc2U7XG4gICAgICAgICAgICAgICAgdmFyIGhvb2tzO1xuXG4gICAgICAgICAgICAgICAgZm9yICh2YXIgcHJvcE5hbWUgaW4gcHJvcGVydGllcykge1xuICAgICAgICAgICAgICAgICAgICBpZiAocHJvcGVydGllcy5oYXNPd25Qcm9wZXJ0eShwcm9wTmFtZSkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHZhciBwcm9wZXJ0eSA9IHByb3BlcnRpZXNbcHJvcE5hbWVdO1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGlzVkhvb2socHJvcGVydHkpICYmIHByb3BlcnR5LnVuaG9vaykge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmICghaG9va3MpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaG9va3MgPSB7fTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBob29rc1twcm9wTmFtZV0gPSBwcm9wZXJ0eTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgY291bnQ7IGkrKykge1xuICAgICAgICAgICAgICAgICAgICB2YXIgY2hpbGQgPSBjaGlsZHJlbltpXTtcbiAgICAgICAgICAgICAgICAgICAgaWYgKGlzVk5vZGUoY2hpbGQpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBkZXNjZW5kYW50cyArPSBjaGlsZC5jb3VudCB8fCAwO1xuXG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoIWhhc1dpZGdldHMgJiYgY2hpbGQuaGFzV2lkZ2V0cykge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGhhc1dpZGdldHMgPSB0cnVlO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoIWhhc1RodW5rcyAmJiBjaGlsZC5oYXNUaHVua3MpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBoYXNUaHVua3MgPSB0cnVlO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoIWRlc2NlbmRhbnRIb29rcyAmJiAoY2hpbGQuaG9va3MgfHwgY2hpbGQuZGVzY2VuZGFudEhvb2tzKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRlc2NlbmRhbnRIb29rcyA9IHRydWU7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoIWhhc1dpZGdldHMgJiYgaXNXaWRnZXQoY2hpbGQpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAodHlwZW9mIGNoaWxkLmRlc3Ryb3kgPT09IFwiZnVuY3Rpb25cIikge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGhhc1dpZGdldHMgPSB0cnVlO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKCFoYXNUaHVua3MgJiYgaXNUaHVuayhjaGlsZCkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGhhc1RodW5rcyA9IHRydWU7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICB0aGlzLmNvdW50ID0gY291bnQgKyBkZXNjZW5kYW50cztcbiAgICAgICAgICAgICAgICB0aGlzLmhhc1dpZGdldHMgPSBoYXNXaWRnZXRzO1xuICAgICAgICAgICAgICAgIHRoaXMuaGFzVGh1bmtzID0gaGFzVGh1bmtzO1xuICAgICAgICAgICAgICAgIHRoaXMuaG9va3MgPSBob29rcztcbiAgICAgICAgICAgICAgICB0aGlzLmRlc2NlbmRhbnRIb29rcyA9IGRlc2NlbmRhbnRIb29rcztcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgVmlydHVhbE5vZGUucHJvdG90eXBlLnZlcnNpb24gPSB2ZXJzaW9uO1xuICAgICAgICAgICAgVmlydHVhbE5vZGUucHJvdG90eXBlLnR5cGUgPSBcIlZpcnR1YWxOb2RlXCI7XG4gICAgICAgIH0sIHsgXCIuL2lzLXRodW5rXCI6IDI1LCBcIi4vaXMtdmhvb2tcIjogMjYsIFwiLi9pcy12bm9kZVwiOiAyNywgXCIuL2lzLXdpZGdldFwiOiAyOSwgXCIuL3ZlcnNpb25cIjogMzAgfV0sIDMyOiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge1xuICAgICAgICAgICAgdmFyIHZlcnNpb24gPSByZXF1aXJlKFwiLi92ZXJzaW9uXCIpO1xuXG4gICAgICAgICAgICBWaXJ0dWFsUGF0Y2guTk9ORSA9IDA7XG4gICAgICAgICAgICBWaXJ0dWFsUGF0Y2guVlRFWFQgPSAxO1xuICAgICAgICAgICAgVmlydHVhbFBhdGNoLlZOT0RFID0gMjtcbiAgICAgICAgICAgIFZpcnR1YWxQYXRjaC5XSURHRVQgPSAzO1xuICAgICAgICAgICAgVmlydHVhbFBhdGNoLlBST1BTID0gNDtcbiAgICAgICAgICAgIFZpcnR1YWxQYXRjaC5PUkRFUiA9IDU7XG4gICAgICAgICAgICBWaXJ0dWFsUGF0Y2guSU5TRVJUID0gNjtcbiAgICAgICAgICAgIFZpcnR1YWxQYXRjaC5SRU1PVkUgPSA3O1xuICAgICAgICAgICAgVmlydHVhbFBhdGNoLlRIVU5LID0gODtcblxuICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBWaXJ0dWFsUGF0Y2g7XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIFZpcnR1YWxQYXRjaCh0eXBlLCB2Tm9kZSwgcGF0Y2gpIHtcbiAgICAgICAgICAgICAgICB0aGlzLnR5cGUgPSBOdW1iZXIodHlwZSk7XG4gICAgICAgICAgICAgICAgdGhpcy52Tm9kZSA9IHZOb2RlO1xuICAgICAgICAgICAgICAgIHRoaXMucGF0Y2ggPSBwYXRjaDtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgVmlydHVhbFBhdGNoLnByb3RvdHlwZS52ZXJzaW9uID0gdmVyc2lvbjtcbiAgICAgICAgICAgIFZpcnR1YWxQYXRjaC5wcm90b3R5cGUudHlwZSA9IFwiVmlydHVhbFBhdGNoXCI7XG4gICAgICAgIH0sIHsgXCIuL3ZlcnNpb25cIjogMzAgfV0sIDMzOiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge1xuICAgICAgICAgICAgdmFyIHZlcnNpb24gPSByZXF1aXJlKFwiLi92ZXJzaW9uXCIpO1xuXG4gICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IFZpcnR1YWxUZXh0O1xuXG4gICAgICAgICAgICBmdW5jdGlvbiBWaXJ0dWFsVGV4dCh0ZXh0KSB7XG4gICAgICAgICAgICAgICAgdGhpcy50ZXh0ID0gU3RyaW5nKHRleHQpO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBWaXJ0dWFsVGV4dC5wcm90b3R5cGUudmVyc2lvbiA9IHZlcnNpb247XG4gICAgICAgICAgICBWaXJ0dWFsVGV4dC5wcm90b3R5cGUudHlwZSA9IFwiVmlydHVhbFRleHRcIjtcbiAgICAgICAgfSwgeyBcIi4vdmVyc2lvblwiOiAzMCB9XSwgMzQ6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICB2YXIgaXNPYmplY3QgPSByZXF1aXJlKFwiaXMtb2JqZWN0XCIpO1xuICAgICAgICAgICAgdmFyIGlzSG9vayA9IHJlcXVpcmUoXCIuLi92bm9kZS9pcy12aG9va1wiKTtcblxuICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBkaWZmUHJvcHM7XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIGRpZmZQcm9wcyhhLCBiKSB7XG4gICAgICAgICAgICAgICAgdmFyIGRpZmY7XG5cbiAgICAgICAgICAgICAgICBmb3IgKHZhciBhS2V5IGluIGEpIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKCEoYUtleSBpbiBiKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgZGlmZiA9IGRpZmYgfHwge307XG4gICAgICAgICAgICAgICAgICAgICAgICBkaWZmW2FLZXldID0gdW5kZWZpbmVkO1xuICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgdmFyIGFWYWx1ZSA9IGFbYUtleV07XG4gICAgICAgICAgICAgICAgICAgIHZhciBiVmFsdWUgPSBiW2FLZXldO1xuXG4gICAgICAgICAgICAgICAgICAgIGlmIChhVmFsdWUgPT09IGJWYWx1ZSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgY29udGludWU7XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoaXNPYmplY3QoYVZhbHVlKSAmJiBpc09iamVjdChiVmFsdWUpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoZ2V0UHJvdG90eXBlKGJWYWx1ZSkgIT09IGdldFByb3RvdHlwZShhVmFsdWUpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgZGlmZiA9IGRpZmYgfHwge307XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgZGlmZlthS2V5XSA9IGJWYWx1ZTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoaXNIb29rKGJWYWx1ZSkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBkaWZmID0gZGlmZiB8fCB7fTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBkaWZmW2FLZXldID0gYlZhbHVlO1xuICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB2YXIgb2JqZWN0RGlmZiA9IGRpZmZQcm9wcyhhVmFsdWUsIGJWYWx1ZSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKG9iamVjdERpZmYpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZGlmZiA9IGRpZmYgfHwge307XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRpZmZbYUtleV0gPSBvYmplY3REaWZmO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGRpZmYgPSBkaWZmIHx8IHt9O1xuICAgICAgICAgICAgICAgICAgICAgICAgZGlmZlthS2V5XSA9IGJWYWx1ZTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIGZvciAodmFyIGJLZXkgaW4gYikge1xuICAgICAgICAgICAgICAgICAgICBpZiAoIShiS2V5IGluIGEpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBkaWZmID0gZGlmZiB8fCB7fTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGRpZmZbYktleV0gPSBiW2JLZXldO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgcmV0dXJuIGRpZmY7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIGdldFByb3RvdHlwZSh2YWx1ZSkge1xuICAgICAgICAgICAgICAgIGlmIChPYmplY3QuZ2V0UHJvdG90eXBlT2YpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIE9iamVjdC5nZXRQcm90b3R5cGVPZih2YWx1ZSk7XG4gICAgICAgICAgICAgICAgfSBlbHNlIGlmICh2YWx1ZS5fX3Byb3RvX18pIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHZhbHVlLl9fcHJvdG9fXztcbiAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKHZhbHVlLmNvbnN0cnVjdG9yKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiB2YWx1ZS5jb25zdHJ1Y3Rvci5wcm90b3R5cGU7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9LCB7IFwiLi4vdm5vZGUvaXMtdmhvb2tcIjogMjYsIFwiaXMtb2JqZWN0XCI6IDExIH1dLCAzNTogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHtcbiAgICAgICAgICAgIHZhciBpc0FycmF5ID0gcmVxdWlyZShcIngtaXMtYXJyYXlcIik7XG5cbiAgICAgICAgICAgIHZhciBWUGF0Y2ggPSByZXF1aXJlKFwiLi4vdm5vZGUvdnBhdGNoXCIpO1xuICAgICAgICAgICAgdmFyIGlzVk5vZGUgPSByZXF1aXJlKFwiLi4vdm5vZGUvaXMtdm5vZGVcIik7XG4gICAgICAgICAgICB2YXIgaXNWVGV4dCA9IHJlcXVpcmUoXCIuLi92bm9kZS9pcy12dGV4dFwiKTtcbiAgICAgICAgICAgIHZhciBpc1dpZGdldCA9IHJlcXVpcmUoXCIuLi92bm9kZS9pcy13aWRnZXRcIik7XG4gICAgICAgICAgICB2YXIgaXNUaHVuayA9IHJlcXVpcmUoXCIuLi92bm9kZS9pcy10aHVua1wiKTtcbiAgICAgICAgICAgIHZhciBoYW5kbGVUaHVuayA9IHJlcXVpcmUoXCIuLi92bm9kZS9oYW5kbGUtdGh1bmtcIik7XG5cbiAgICAgICAgICAgIHZhciBkaWZmUHJvcHMgPSByZXF1aXJlKFwiLi9kaWZmLXByb3BzXCIpO1xuXG4gICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IGRpZmY7XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIGRpZmYoYSwgYikge1xuICAgICAgICAgICAgICAgIHZhciBwYXRjaCA9IHsgYTogYSB9O1xuICAgICAgICAgICAgICAgIHdhbGsoYSwgYiwgcGF0Y2gsIDApO1xuICAgICAgICAgICAgICAgIHJldHVybiBwYXRjaDtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZnVuY3Rpb24gd2FsayhhLCBiLCBwYXRjaCwgaW5kZXgpIHtcbiAgICAgICAgICAgICAgICBpZiAoYSA9PT0gYikge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgdmFyIGFwcGx5ID0gcGF0Y2hbaW5kZXhdO1xuICAgICAgICAgICAgICAgIHZhciBhcHBseUNsZWFyID0gZmFsc2U7XG5cbiAgICAgICAgICAgICAgICBpZiAoaXNUaHVuayhhKSB8fCBpc1RodW5rKGIpKSB7XG4gICAgICAgICAgICAgICAgICAgIHRodW5rcyhhLCBiLCBwYXRjaCwgaW5kZXgpO1xuICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoYiA9PSBudWxsKSB7XG5cbiAgICAgICAgICAgICAgICAgICAgLy8gSWYgYSBpcyBhIHdpZGdldCB3ZSB3aWxsIGFkZCBhIHJlbW92ZSBwYXRjaCBmb3IgaXRcbiAgICAgICAgICAgICAgICAgICAgLy8gT3RoZXJ3aXNlIGFueSBjaGlsZCB3aWRnZXRzL2hvb2tzIG11c3QgYmUgZGVzdHJveWVkLlxuICAgICAgICAgICAgICAgICAgICAvLyBUaGlzIHByZXZlbnRzIGFkZGluZyB0d28gcmVtb3ZlIHBhdGNoZXMgZm9yIGEgd2lkZ2V0LlxuICAgICAgICAgICAgICAgICAgICBpZiAoIWlzV2lkZ2V0KGEpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBjbGVhclN0YXRlKGEsIHBhdGNoLCBpbmRleCk7XG4gICAgICAgICAgICAgICAgICAgICAgICBhcHBseSA9IHBhdGNoW2luZGV4XTtcbiAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgIGFwcGx5ID0gYXBwZW5kUGF0Y2goYXBwbHksIG5ldyBWUGF0Y2goVlBhdGNoLlJFTU9WRSwgYSwgYikpO1xuICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoaXNWTm9kZShiKSkge1xuICAgICAgICAgICAgICAgICAgICBpZiAoaXNWTm9kZShhKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGEudGFnTmFtZSA9PT0gYi50YWdOYW1lICYmIGEubmFtZXNwYWNlID09PSBiLm5hbWVzcGFjZSAmJiBhLmtleSA9PT0gYi5rZXkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB2YXIgcHJvcHNQYXRjaCA9IGRpZmZQcm9wcyhhLnByb3BlcnRpZXMsIGIucHJvcGVydGllcyk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHByb3BzUGF0Y2gpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYXBwbHkgPSBhcHBlbmRQYXRjaChhcHBseSwgbmV3IFZQYXRjaChWUGF0Y2guUFJPUFMsIGEsIHByb3BzUGF0Y2gpKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgYXBwbHkgPSBkaWZmQ2hpbGRyZW4oYSwgYiwgcGF0Y2gsIGFwcGx5LCBpbmRleCk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGFwcGx5ID0gYXBwZW5kUGF0Y2goYXBwbHksIG5ldyBWUGF0Y2goVlBhdGNoLlZOT0RFLCBhLCBiKSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgYXBwbHlDbGVhciA9IHRydWU7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBhcHBseSA9IGFwcGVuZFBhdGNoKGFwcGx5LCBuZXcgVlBhdGNoKFZQYXRjaC5WTk9ERSwgYSwgYikpO1xuICAgICAgICAgICAgICAgICAgICAgICAgYXBwbHlDbGVhciA9IHRydWU7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKGlzVlRleHQoYikpIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKCFpc1ZUZXh0KGEpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBhcHBseSA9IGFwcGVuZFBhdGNoKGFwcGx5LCBuZXcgVlBhdGNoKFZQYXRjaC5WVEVYVCwgYSwgYikpO1xuICAgICAgICAgICAgICAgICAgICAgICAgYXBwbHlDbGVhciA9IHRydWU7XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoYS50ZXh0ICE9PSBiLnRleHQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGFwcGx5ID0gYXBwZW5kUGF0Y2goYXBwbHksIG5ldyBWUGF0Y2goVlBhdGNoLlZURVhULCBhLCBiKSk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKGlzV2lkZ2V0KGIpKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmICghaXNXaWRnZXQoYSkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGFwcGx5Q2xlYXIgPSB0cnVlO1xuICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgYXBwbHkgPSBhcHBlbmRQYXRjaChhcHBseSwgbmV3IFZQYXRjaChWUGF0Y2guV0lER0VULCBhLCBiKSk7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgaWYgKGFwcGx5KSB7XG4gICAgICAgICAgICAgICAgICAgIHBhdGNoW2luZGV4XSA9IGFwcGx5O1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIGlmIChhcHBseUNsZWFyKSB7XG4gICAgICAgICAgICAgICAgICAgIGNsZWFyU3RhdGUoYSwgcGF0Y2gsIGluZGV4KTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIGRpZmZDaGlsZHJlbihhLCBiLCBwYXRjaCwgYXBwbHksIGluZGV4KSB7XG4gICAgICAgICAgICAgICAgdmFyIGFDaGlsZHJlbiA9IGEuY2hpbGRyZW47XG4gICAgICAgICAgICAgICAgdmFyIG9yZGVyZWRTZXQgPSByZW9yZGVyKGFDaGlsZHJlbiwgYi5jaGlsZHJlbik7XG4gICAgICAgICAgICAgICAgdmFyIGJDaGlsZHJlbiA9IG9yZGVyZWRTZXQuY2hpbGRyZW47XG5cbiAgICAgICAgICAgICAgICB2YXIgYUxlbiA9IGFDaGlsZHJlbi5sZW5ndGg7XG4gICAgICAgICAgICAgICAgdmFyIGJMZW4gPSBiQ2hpbGRyZW4ubGVuZ3RoO1xuICAgICAgICAgICAgICAgIHZhciBsZW4gPSBhTGVuID4gYkxlbiA/IGFMZW4gOiBiTGVuO1xuXG4gICAgICAgICAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCBsZW47IGkrKykge1xuICAgICAgICAgICAgICAgICAgICB2YXIgbGVmdE5vZGUgPSBhQ2hpbGRyZW5baV07XG4gICAgICAgICAgICAgICAgICAgIHZhciByaWdodE5vZGUgPSBiQ2hpbGRyZW5baV07XG4gICAgICAgICAgICAgICAgICAgIGluZGV4ICs9IDE7XG5cbiAgICAgICAgICAgICAgICAgICAgaWYgKCFsZWZ0Tm9kZSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHJpZ2h0Tm9kZSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIEV4Y2VzcyBub2RlcyBpbiBiIG5lZWQgdG8gYmUgYWRkZWRcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBhcHBseSA9IGFwcGVuZFBhdGNoKGFwcGx5LCBuZXcgVlBhdGNoKFZQYXRjaC5JTlNFUlQsIG51bGwsIHJpZ2h0Tm9kZSkpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgd2FsayhsZWZ0Tm9kZSwgcmlnaHROb2RlLCBwYXRjaCwgaW5kZXgpO1xuICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgaWYgKGlzVk5vZGUobGVmdE5vZGUpICYmIGxlZnROb2RlLmNvdW50KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBpbmRleCArPSBsZWZ0Tm9kZS5jb3VudDtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIGlmIChvcmRlcmVkU2V0Lm1vdmVzKSB7XG4gICAgICAgICAgICAgICAgICAgIC8vIFJlb3JkZXIgbm9kZXMgbGFzdFxuICAgICAgICAgICAgICAgICAgICBhcHBseSA9IGFwcGVuZFBhdGNoKGFwcGx5LCBuZXcgVlBhdGNoKFZQYXRjaC5PUkRFUiwgYSwgb3JkZXJlZFNldC5tb3ZlcykpO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHJldHVybiBhcHBseTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZnVuY3Rpb24gY2xlYXJTdGF0ZSh2Tm9kZSwgcGF0Y2gsIGluZGV4KSB7XG4gICAgICAgICAgICAgICAgLy8gVE9ETzogTWFrZSB0aGlzIGEgc2luZ2xlIHdhbGssIG5vdCB0d29cbiAgICAgICAgICAgICAgICB1bmhvb2sodk5vZGUsIHBhdGNoLCBpbmRleCk7XG4gICAgICAgICAgICAgICAgZGVzdHJveVdpZGdldHModk5vZGUsIHBhdGNoLCBpbmRleCk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIC8vIFBhdGNoIHJlY29yZHMgZm9yIGFsbCBkZXN0cm95ZWQgd2lkZ2V0cyBtdXN0IGJlIGFkZGVkIGJlY2F1c2Ugd2UgbmVlZFxuICAgICAgICAgICAgLy8gYSBET00gbm9kZSByZWZlcmVuY2UgZm9yIHRoZSBkZXN0cm95IGZ1bmN0aW9uXG4gICAgICAgICAgICBmdW5jdGlvbiBkZXN0cm95V2lkZ2V0cyh2Tm9kZSwgcGF0Y2gsIGluZGV4KSB7XG4gICAgICAgICAgICAgICAgaWYgKGlzV2lkZ2V0KHZOb2RlKSkge1xuICAgICAgICAgICAgICAgICAgICBpZiAodHlwZW9mIHZOb2RlLmRlc3Ryb3kgPT09IFwiZnVuY3Rpb25cIikge1xuICAgICAgICAgICAgICAgICAgICAgICAgcGF0Y2hbaW5kZXhdID0gYXBwZW5kUGF0Y2gocGF0Y2hbaW5kZXhdLCBuZXcgVlBhdGNoKFZQYXRjaC5SRU1PVkUsIHZOb2RlLCBudWxsKSk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKGlzVk5vZGUodk5vZGUpICYmICh2Tm9kZS5oYXNXaWRnZXRzIHx8IHZOb2RlLmhhc1RodW5rcykpIHtcbiAgICAgICAgICAgICAgICAgICAgdmFyIGNoaWxkcmVuID0gdk5vZGUuY2hpbGRyZW47XG4gICAgICAgICAgICAgICAgICAgIHZhciBsZW4gPSBjaGlsZHJlbi5sZW5ndGg7XG4gICAgICAgICAgICAgICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgbGVuOyBpKyspIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHZhciBjaGlsZCA9IGNoaWxkcmVuW2ldO1xuICAgICAgICAgICAgICAgICAgICAgICAgaW5kZXggKz0gMTtcblxuICAgICAgICAgICAgICAgICAgICAgICAgZGVzdHJveVdpZGdldHMoY2hpbGQsIHBhdGNoLCBpbmRleCk7XG5cbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChpc1ZOb2RlKGNoaWxkKSAmJiBjaGlsZC5jb3VudCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGluZGV4ICs9IGNoaWxkLmNvdW50O1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfSBlbHNlIGlmIChpc1RodW5rKHZOb2RlKSkge1xuICAgICAgICAgICAgICAgICAgICB0aHVua3Modk5vZGUsIG51bGwsIHBhdGNoLCBpbmRleCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAvLyBDcmVhdGUgYSBzdWItcGF0Y2ggZm9yIHRodW5rc1xuICAgICAgICAgICAgZnVuY3Rpb24gdGh1bmtzKGEsIGIsIHBhdGNoLCBpbmRleCkge1xuICAgICAgICAgICAgICAgIHZhciBub2RlcyA9IGhhbmRsZVRodW5rKGEsIGIpO1xuICAgICAgICAgICAgICAgIHZhciB0aHVua1BhdGNoID0gZGlmZihub2Rlcy5hLCBub2Rlcy5iKTtcbiAgICAgICAgICAgICAgICBpZiAoaGFzUGF0Y2hlcyh0aHVua1BhdGNoKSkge1xuICAgICAgICAgICAgICAgICAgICBwYXRjaFtpbmRleF0gPSBuZXcgVlBhdGNoKFZQYXRjaC5USFVOSywgbnVsbCwgdGh1bmtQYXRjaCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBmdW5jdGlvbiBoYXNQYXRjaGVzKHBhdGNoKSB7XG4gICAgICAgICAgICAgICAgZm9yICh2YXIgaW5kZXggaW4gcGF0Y2gpIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKGluZGV4ICE9PSBcImFcIikge1xuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIC8vIEV4ZWN1dGUgaG9va3Mgd2hlbiB0d28gbm9kZXMgYXJlIGlkZW50aWNhbFxuICAgICAgICAgICAgZnVuY3Rpb24gdW5ob29rKHZOb2RlLCBwYXRjaCwgaW5kZXgpIHtcbiAgICAgICAgICAgICAgICBpZiAoaXNWTm9kZSh2Tm9kZSkpIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKHZOb2RlLmhvb2tzKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBwYXRjaFtpbmRleF0gPSBhcHBlbmRQYXRjaChwYXRjaFtpbmRleF0sIG5ldyBWUGF0Y2goVlBhdGNoLlBST1BTLCB2Tm9kZSwgdW5kZWZpbmVkS2V5cyh2Tm9kZS5ob29rcykpKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgIGlmICh2Tm9kZS5kZXNjZW5kYW50SG9va3MgfHwgdk5vZGUuaGFzVGh1bmtzKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICB2YXIgY2hpbGRyZW4gPSB2Tm9kZS5jaGlsZHJlbjtcbiAgICAgICAgICAgICAgICAgICAgICAgIHZhciBsZW4gPSBjaGlsZHJlbi5sZW5ndGg7XG4gICAgICAgICAgICAgICAgICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IGxlbjsgaSsrKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdmFyIGNoaWxkID0gY2hpbGRyZW5baV07XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaW5kZXggKz0gMTtcblxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHVuaG9vayhjaGlsZCwgcGF0Y2gsIGluZGV4KTtcblxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChpc1ZOb2RlKGNoaWxkKSAmJiBjaGlsZC5jb3VudCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpbmRleCArPSBjaGlsZC5jb3VudDtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKGlzVGh1bmsodk5vZGUpKSB7XG4gICAgICAgICAgICAgICAgICAgIHRodW5rcyh2Tm9kZSwgbnVsbCwgcGF0Y2gsIGluZGV4KTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIHVuZGVmaW5lZEtleXMob2JqKSB7XG4gICAgICAgICAgICAgICAgdmFyIHJlc3VsdCA9IHt9O1xuXG4gICAgICAgICAgICAgICAgZm9yICh2YXIga2V5IGluIG9iaikge1xuICAgICAgICAgICAgICAgICAgICByZXN1bHRba2V5XSA9IHVuZGVmaW5lZDtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICByZXR1cm4gcmVzdWx0O1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAvLyBMaXN0IGRpZmYsIG5haXZlIGxlZnQgdG8gcmlnaHQgcmVvcmRlcmluZ1xuICAgICAgICAgICAgZnVuY3Rpb24gcmVvcmRlcihhQ2hpbGRyZW4sIGJDaGlsZHJlbikge1xuICAgICAgICAgICAgICAgIC8vIE8oTSkgdGltZSwgTyhNKSBtZW1vcnlcbiAgICAgICAgICAgICAgICB2YXIgYkNoaWxkSW5kZXggPSBrZXlJbmRleChiQ2hpbGRyZW4pO1xuICAgICAgICAgICAgICAgIHZhciBiS2V5cyA9IGJDaGlsZEluZGV4LmtleXM7XG4gICAgICAgICAgICAgICAgdmFyIGJGcmVlID0gYkNoaWxkSW5kZXguZnJlZTtcblxuICAgICAgICAgICAgICAgIGlmIChiRnJlZS5sZW5ndGggPT09IGJDaGlsZHJlbi5sZW5ndGgpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGNoaWxkcmVuOiBiQ2hpbGRyZW4sXG4gICAgICAgICAgICAgICAgICAgICAgICBtb3ZlczogbnVsbFxuICAgICAgICAgICAgICAgICAgICB9O1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIC8vIE8oTikgdGltZSwgTyhOKSBtZW1vcnlcbiAgICAgICAgICAgICAgICB2YXIgYUNoaWxkSW5kZXggPSBrZXlJbmRleChhQ2hpbGRyZW4pO1xuICAgICAgICAgICAgICAgIHZhciBhS2V5cyA9IGFDaGlsZEluZGV4LmtleXM7XG4gICAgICAgICAgICAgICAgdmFyIGFGcmVlID0gYUNoaWxkSW5kZXguZnJlZTtcblxuICAgICAgICAgICAgICAgIGlmIChhRnJlZS5sZW5ndGggPT09IGFDaGlsZHJlbi5sZW5ndGgpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGNoaWxkcmVuOiBiQ2hpbGRyZW4sXG4gICAgICAgICAgICAgICAgICAgICAgICBtb3ZlczogbnVsbFxuICAgICAgICAgICAgICAgICAgICB9O1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIC8vIE8oTUFYKE4sIE0pKSBtZW1vcnlcbiAgICAgICAgICAgICAgICB2YXIgbmV3Q2hpbGRyZW4gPSBbXTtcblxuICAgICAgICAgICAgICAgIHZhciBmcmVlSW5kZXggPSAwO1xuICAgICAgICAgICAgICAgIHZhciBmcmVlQ291bnQgPSBiRnJlZS5sZW5ndGg7XG4gICAgICAgICAgICAgICAgdmFyIGRlbGV0ZWRJdGVtcyA9IDA7XG5cbiAgICAgICAgICAgICAgICAvLyBJdGVyYXRlIHRocm91Z2ggYSBhbmQgbWF0Y2ggYSBub2RlIGluIGJcbiAgICAgICAgICAgICAgICAvLyBPKE4pIHRpbWUsXG4gICAgICAgICAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCBhQ2hpbGRyZW4ubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgICAgICAgICAgdmFyIGFJdGVtID0gYUNoaWxkcmVuW2ldO1xuICAgICAgICAgICAgICAgICAgICB2YXIgaXRlbUluZGV4O1xuXG4gICAgICAgICAgICAgICAgICAgIGlmIChhSXRlbS5rZXkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChiS2V5cy5oYXNPd25Qcm9wZXJ0eShhSXRlbS5rZXkpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gTWF0Y2ggdXAgdGhlIG9sZCBrZXlzXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaXRlbUluZGV4ID0gYktleXNbYUl0ZW0ua2V5XTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBuZXdDaGlsZHJlbi5wdXNoKGJDaGlsZHJlbltpdGVtSW5kZXhdKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gUmVtb3ZlIG9sZCBrZXllZCBpdGVtc1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGl0ZW1JbmRleCA9IGkgLSBkZWxldGVkSXRlbXMrKztcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBuZXdDaGlsZHJlbi5wdXNoKG51bGwpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgLy8gTWF0Y2ggdGhlIGl0ZW0gaW4gYSB3aXRoIHRoZSBuZXh0IGZyZWUgaXRlbSBpbiBiXG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoZnJlZUluZGV4IDwgZnJlZUNvdW50KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaXRlbUluZGV4ID0gYkZyZWVbZnJlZUluZGV4KytdO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIG5ld0NoaWxkcmVuLnB1c2goYkNoaWxkcmVuW2l0ZW1JbmRleF0pO1xuICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBUaGVyZSBhcmUgbm8gZnJlZSBpdGVtcyBpbiBiIHRvIG1hdGNoIHdpdGhcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyB0aGUgZnJlZSBpdGVtcyBpbiBhLCBzbyB0aGUgZXh0cmEgZnJlZSBub2Rlc1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIGFyZSBkZWxldGVkLlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGl0ZW1JbmRleCA9IGkgLSBkZWxldGVkSXRlbXMrKztcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBuZXdDaGlsZHJlbi5wdXNoKG51bGwpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgdmFyIGxhc3RGcmVlSW5kZXggPSBmcmVlSW5kZXggPj0gYkZyZWUubGVuZ3RoID8gYkNoaWxkcmVuLmxlbmd0aCA6IGJGcmVlW2ZyZWVJbmRleF07XG5cbiAgICAgICAgICAgICAgICAvLyBJdGVyYXRlIHRocm91Z2ggYiBhbmQgYXBwZW5kIGFueSBuZXcga2V5c1xuICAgICAgICAgICAgICAgIC8vIE8oTSkgdGltZVxuICAgICAgICAgICAgICAgIGZvciAodmFyIGogPSAwOyBqIDwgYkNoaWxkcmVuLmxlbmd0aDsgaisrKSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciBuZXdJdGVtID0gYkNoaWxkcmVuW2pdO1xuXG4gICAgICAgICAgICAgICAgICAgIGlmIChuZXdJdGVtLmtleSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKCFhS2V5cy5oYXNPd25Qcm9wZXJ0eShuZXdJdGVtLmtleSkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBBZGQgYW55IG5ldyBrZXllZCBpdGVtc1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIFdlIGFyZSBhZGRpbmcgbmV3IGl0ZW1zIHRvIHRoZSBlbmQgYW5kIHRoZW4gc29ydGluZyB0aGVtXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gaW4gcGxhY2UuIEluIGZ1dHVyZSB3ZSBzaG91bGQgaW5zZXJ0IG5ldyBpdGVtcyBpbiBwbGFjZS5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBuZXdDaGlsZHJlbi5wdXNoKG5ld0l0ZW0pO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKGogPj0gbGFzdEZyZWVJbmRleCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgLy8gQWRkIGFueSBsZWZ0b3ZlciBub24ta2V5ZWQgaXRlbXNcbiAgICAgICAgICAgICAgICAgICAgICAgIG5ld0NoaWxkcmVuLnB1c2gobmV3SXRlbSk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICB2YXIgc2ltdWxhdGUgPSBuZXdDaGlsZHJlbi5zbGljZSgpO1xuICAgICAgICAgICAgICAgIHZhciBzaW11bGF0ZUluZGV4ID0gMDtcbiAgICAgICAgICAgICAgICB2YXIgcmVtb3ZlcyA9IFtdO1xuICAgICAgICAgICAgICAgIHZhciBpbnNlcnRzID0gW107XG4gICAgICAgICAgICAgICAgdmFyIHNpbXVsYXRlSXRlbTtcblxuICAgICAgICAgICAgICAgIGZvciAodmFyIGsgPSAwOyBrIDwgYkNoaWxkcmVuLmxlbmd0aDspIHtcbiAgICAgICAgICAgICAgICAgICAgdmFyIHdhbnRlZEl0ZW0gPSBiQ2hpbGRyZW5ba107XG4gICAgICAgICAgICAgICAgICAgIHNpbXVsYXRlSXRlbSA9IHNpbXVsYXRlW3NpbXVsYXRlSW5kZXhdO1xuXG4gICAgICAgICAgICAgICAgICAgIC8vIHJlbW92ZSBpdGVtc1xuICAgICAgICAgICAgICAgICAgICB3aGlsZSAoc2ltdWxhdGVJdGVtID09PSBudWxsICYmIHNpbXVsYXRlLmxlbmd0aCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgcmVtb3Zlcy5wdXNoKHJlbW92ZShzaW11bGF0ZSwgc2ltdWxhdGVJbmRleCwgbnVsbCkpO1xuICAgICAgICAgICAgICAgICAgICAgICAgc2ltdWxhdGVJdGVtID0gc2ltdWxhdGVbc2ltdWxhdGVJbmRleF07XG4gICAgICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgICAgICBpZiAoIXNpbXVsYXRlSXRlbSB8fCBzaW11bGF0ZUl0ZW0ua2V5ICE9PSB3YW50ZWRJdGVtLmtleSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgLy8gaWYgd2UgbmVlZCBhIGtleSBpbiB0aGlzIHBvc2l0aW9uLi4uXG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAod2FudGVkSXRlbS5rZXkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoc2ltdWxhdGVJdGVtICYmIHNpbXVsYXRlSXRlbS5rZXkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gaWYgYW4gaW5zZXJ0IGRvZXNuJ3QgcHV0IHRoaXMga2V5IGluIHBsYWNlLCBpdCBuZWVkcyB0byBtb3ZlXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChiS2V5c1tzaW11bGF0ZUl0ZW0ua2V5XSAhPT0gayArIDEpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlbW92ZXMucHVzaChyZW1vdmUoc2ltdWxhdGUsIHNpbXVsYXRlSW5kZXgsIHNpbXVsYXRlSXRlbS5rZXkpKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNpbXVsYXRlSXRlbSA9IHNpbXVsYXRlW3NpbXVsYXRlSW5kZXhdO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gaWYgdGhlIHJlbW92ZSBkaWRuJ3QgcHV0IHRoZSB3YW50ZWQgaXRlbSBpbiBwbGFjZSwgd2UgbmVlZCB0byBpbnNlcnQgaXRcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmICghc2ltdWxhdGVJdGVtIHx8IHNpbXVsYXRlSXRlbS5rZXkgIT09IHdhbnRlZEl0ZW0ua2V5KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaW5zZXJ0cy5wdXNoKHsga2V5OiB3YW50ZWRJdGVtLmtleSwgdG86IGsgfSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBpdGVtcyBhcmUgbWF0Y2hpbmcsIHNvIHNraXAgYWhlYWRcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNpbXVsYXRlSW5kZXgrKztcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGluc2VydHMucHVzaCh7IGtleTogd2FudGVkSXRlbS5rZXksIHRvOiBrIH0pO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaW5zZXJ0cy5wdXNoKHsga2V5OiB3YW50ZWRJdGVtLmtleSwgdG86IGsgfSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGsrKztcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIGEga2V5IGluIHNpbXVsYXRlIGhhcyBubyBtYXRjaGluZyB3YW50ZWQga2V5LCByZW1vdmUgaXRcbiAgICAgICAgICAgICAgICAgICAgICAgIGVsc2UgaWYgKHNpbXVsYXRlSXRlbSAmJiBzaW11bGF0ZUl0ZW0ua2V5KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcmVtb3Zlcy5wdXNoKHJlbW92ZShzaW11bGF0ZSwgc2ltdWxhdGVJbmRleCwgc2ltdWxhdGVJdGVtLmtleSkpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgc2ltdWxhdGVJbmRleCsrO1xuICAgICAgICAgICAgICAgICAgICAgICAgaysrO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgLy8gcmVtb3ZlIGFsbCB0aGUgcmVtYWluaW5nIG5vZGVzIGZyb20gc2ltdWxhdGVcbiAgICAgICAgICAgICAgICB3aGlsZSAoc2ltdWxhdGVJbmRleCA8IHNpbXVsYXRlLmxlbmd0aCkge1xuICAgICAgICAgICAgICAgICAgICBzaW11bGF0ZUl0ZW0gPSBzaW11bGF0ZVtzaW11bGF0ZUluZGV4XTtcbiAgICAgICAgICAgICAgICAgICAgcmVtb3Zlcy5wdXNoKHJlbW92ZShzaW11bGF0ZSwgc2ltdWxhdGVJbmRleCwgc2ltdWxhdGVJdGVtICYmIHNpbXVsYXRlSXRlbS5rZXkpKTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAvLyBJZiB0aGUgb25seSBtb3ZlcyB3ZSBoYXZlIGFyZSBkZWxldGVzIHRoZW4gd2UgY2FuIGp1c3RcbiAgICAgICAgICAgICAgICAvLyBsZXQgdGhlIGRlbGV0ZSBwYXRjaCByZW1vdmUgdGhlc2UgaXRlbXMuXG4gICAgICAgICAgICAgICAgaWYgKHJlbW92ZXMubGVuZ3RoID09PSBkZWxldGVkSXRlbXMgJiYgIWluc2VydHMubGVuZ3RoKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiB7XG4gICAgICAgICAgICAgICAgICAgICAgICBjaGlsZHJlbjogbmV3Q2hpbGRyZW4sXG4gICAgICAgICAgICAgICAgICAgICAgICBtb3ZlczogbnVsbFxuICAgICAgICAgICAgICAgICAgICB9O1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHJldHVybiB7XG4gICAgICAgICAgICAgICAgICAgIGNoaWxkcmVuOiBuZXdDaGlsZHJlbixcbiAgICAgICAgICAgICAgICAgICAgbW92ZXM6IHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJlbW92ZXM6IHJlbW92ZXMsXG4gICAgICAgICAgICAgICAgICAgICAgICBpbnNlcnRzOiBpbnNlcnRzXG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9O1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBmdW5jdGlvbiByZW1vdmUoYXJyLCBpbmRleCwga2V5KSB7XG4gICAgICAgICAgICAgICAgYXJyLnNwbGljZShpbmRleCwgMSk7XG5cbiAgICAgICAgICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgICAgICAgICBmcm9tOiBpbmRleCxcbiAgICAgICAgICAgICAgICAgICAga2V5OiBrZXlcbiAgICAgICAgICAgICAgICB9O1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBmdW5jdGlvbiBrZXlJbmRleChjaGlsZHJlbikge1xuICAgICAgICAgICAgICAgIHZhciBrZXlzID0ge307XG4gICAgICAgICAgICAgICAgdmFyIGZyZWUgPSBbXTtcbiAgICAgICAgICAgICAgICB2YXIgbGVuZ3RoID0gY2hpbGRyZW4ubGVuZ3RoO1xuXG4gICAgICAgICAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCBsZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgICAgICAgICB2YXIgY2hpbGQgPSBjaGlsZHJlbltpXTtcblxuICAgICAgICAgICAgICAgICAgICBpZiAoY2hpbGQua2V5KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBrZXlzW2NoaWxkLmtleV0gPSBpO1xuICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgZnJlZS5wdXNoKGkpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgICAgICAgICAga2V5czoga2V5cywgLy8gQSBoYXNoIG9mIGtleSBuYW1lIHRvIGluZGV4XG4gICAgICAgICAgICAgICAgICAgIGZyZWU6IGZyZWUgLy8gQW4gYXJyYXkgb2YgdW5rZXllZCBpdGVtIGluZGljZXNcbiAgICAgICAgICAgICAgICB9O1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBmdW5jdGlvbiBhcHBlbmRQYXRjaChhcHBseSwgcGF0Y2gpIHtcbiAgICAgICAgICAgICAgICBpZiAoYXBwbHkpIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKGlzQXJyYXkoYXBwbHkpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBhcHBseS5wdXNoKHBhdGNoKTtcbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGFwcGx5ID0gW2FwcGx5LCBwYXRjaF07XG4gICAgICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgICAgICByZXR1cm4gYXBwbHk7XG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHBhdGNoO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgfSwgeyBcIi4uL3Zub2RlL2hhbmRsZS10aHVua1wiOiAyNCwgXCIuLi92bm9kZS9pcy10aHVua1wiOiAyNSwgXCIuLi92bm9kZS9pcy12bm9kZVwiOiAyNywgXCIuLi92bm9kZS9pcy12dGV4dFwiOiAyOCwgXCIuLi92bm9kZS9pcy13aWRnZXRcIjogMjksIFwiLi4vdm5vZGUvdnBhdGNoXCI6IDMyLCBcIi4vZGlmZi1wcm9wc1wiOiAzNCwgXCJ4LWlzLWFycmF5XCI6IDEyIH1dIH0sIHt9LCBbNF0pKDQpO1xufSk7XG5cbmNvbnN0IENvcmUgPSBDO1xuXG5leHBvcnQgeyBDb3JlLCBLZXJuZWwsIEVudW0sIExpc3QsIEtleXdvcmQsIGJpdHdpc2UgYXMgQml0d2lzZSwgbWFwIGFzIE1hcCwgbWFwX3NldCBhcyBNYXBTZXQsIFZpcnR1YWxET00gfTsiXSwiZmlsZSI6IkVsaXhpci5qcyIsInNvdXJjZVJvb3QiOiIvc291cmNlLyJ9 \ No newline at end of file diff --git a/src/javascript/elixir.js b/src/javascript/elixir.js index a36ea382..745d15be 100644 --- a/src/javascript/elixir.js +++ b/src/javascript/elixir.js @@ -2,22 +2,10 @@ import * as C from './lib/core'; export const Core = C; export { default as Kernel } from './lib/kernel'; -export { default as Atom } from './lib/atom'; export { default as Enum } from './lib/enum'; -export { default as Integer } from './lib/integer'; export { default as List } from './lib/list'; -export { default as Range } from './lib/range'; -export { default as Tuple } from './lib/tuple'; -export { default as Agent } from './lib/agent'; export { default as Keyword } from './lib/keyword'; -export { default as Base } from './lib/base'; -export { default as String } from './lib/string'; export { default as Bitwise } from './lib/bitwise'; -export { default as Enumerable } from './lib/enumerable'; -export { default as Collectable } from './lib/collectable'; -export { default as Inspect } from './lib/inspect'; export { default as Map } from './lib/map'; -export { default as Set } from './lib/set'; export { default as MapSet } from './lib/map_set'; export { default as VirtualDOM } from './lib/virtual-dom'; -export { default as View } from './lib/view'; diff --git a/src/javascript/lib/agent.js b/src/javascript/lib/agent.js deleted file mode 100644 index 7d79dd77..00000000 --- a/src/javascript/lib/agent.js +++ /dev/null @@ -1,42 +0,0 @@ -import Kernel from './kernel'; -import Keyword from './keyword'; - -let Agent = {}; - -Agent.start = function(fun, options = []){ - let pid = self.processes.spawn(); - - if(Keyword.has_key__qm__(options, Kernel.SpecialForms.atom("name"))){ - pid = self.processes.register(Keyword.get(options, Kernel.SpecialForms.atom("name")), pid) - } - - self.processes.put(pid, "state", fun()); - return Kernel.SpecialForms.tuple(Kernel.SpecialForms.atom("ok"), pid); -} - -Agent.stop = function(agent, timeout = 5000){ - self.processes.exit(agent); - return Kernel.SpecialForms.atom("ok"); -} - -Agent.update = function(agent, fun, timeout = 5000){ - - const current_state = self.processes.get(agent, "state"); - self.processes.put(agent, "state", fun(current_state)); - - return Kernel.SpecialForms.atom("ok"); -} - -Agent.get = function(agent, fun, timeout = 5000){ - return fun(self.processes.get(agent, "state")); -} - -Agent.get_and_update = function(agent, fun, timeout = 5000){ - - const get_and_update_tuple = fun(self.processes.get(agent, "state")); - self.processes.put(agent, "state", Kernel.elem(get_and_update_tuple, 1)); - - return Kernel.elem(get_and_update_tuple, 0); -} - -export default Agent; diff --git a/src/javascript/lib/atom.js b/src/javascript/lib/atom.js deleted file mode 100644 index 354283b8..00000000 --- a/src/javascript/lib/atom.js +++ /dev/null @@ -1,11 +0,0 @@ -let Atom = {}; - -Atom.to_string = function (atom) { - return Symbol.keyFor(atom); -}; - -Atom.to_char_list = function (atom) { - return Atom.to_string(atom).split(''); -}; - -export default Atom; diff --git a/src/javascript/lib/base.js b/src/javascript/lib/base.js deleted file mode 100644 index e625b78b..00000000 --- a/src/javascript/lib/base.js +++ /dev/null @@ -1,33 +0,0 @@ -import Kernel from './kernel'; - -//https://developer.mozilla.org/en-US/docs/Web/API/WindowBase64/Base64_encoding_and_decoding#Solution_2_%E2%80%93_rewrite_the_DOMs_atob()_and_btoa()_using_JavaScript's_TypedArrays_and_UTF-8 -function b64EncodeUnicode(str) { - return btoa(encodeURIComponent(str).replace(/%([0-9A-F]{2})/g, function(match, p1) { - return String.fromCharCode('0x' + p1); - })); -} - -function encode64(data){ - return b64EncodeUnicode(data); -} - -function decode64(data){ - try{ - return Kernel.SpecialForms.tuple(Kernel.SpecialForms.atom("ok"), atob(data)); - }catch(e){ - return Kernel.SpecialForms.atom("error"); - } - - return btoa(data); -} - -function decode64__em__(data){ - return atob(data); -} - - -export default { - encode64, - decode64, - decode64__em__ -} diff --git a/src/javascript/lib/collectable.js b/src/javascript/lib/collectable.js deleted file mode 100644 index 20c97abf..00000000 --- a/src/javascript/lib/collectable.js +++ /dev/null @@ -1,8 +0,0 @@ -import Kernel from "./kernel"; -import List from "./list"; - -let Collectable = Kernel.defprotocol({ - into: function(collectable){} -}); - -export default Collectable; diff --git a/src/javascript/lib/core.js b/src/javascript/lib/core.js index b56184b1..4414bb3e 100644 --- a/src/javascript/lib/core.js +++ b/src/javascript/lib/core.js @@ -1,37 +1,10 @@ -import ProcessSystem from './core/process_system'; -import { Tuple, PID, Integer, Float } from './core/primitives'; +import ProcessSystem from './core/processes/process_system'; +import { Tuple, PID, Integer, Float, List } from './core/primitives'; import BitString from './core/bit_string'; import Patterns from './core/patterns'; -import { call_property, is_instance_of, size, is_nil, - is_atom, - is_binary, - is_boolean, - is_function, - is_float, - is_integer, - is_list, - is_map, - is_number, - is_tuple, - is_pid, - is_port, - is_reference, - is_bitstring, - add, - subtract, - multiply, - divide, - remainder, - apply, - new_tuple, - duplicate, - contains, - reverse, - get_global, - concat_lists, - prepend_to_list } from './core/functions'; +import Functions from './core/functions'; -get_global().processes = get_global().processes || new ProcessSystem(); +Functions.get_global().processes = Functions.get_global().processes || new ProcessSystem(); export { ProcessSystem, @@ -41,35 +14,6 @@ export { Patterns, Integer, Float, - call_property, - is_instance_of, - size, - is_nil, - is_atom, - is_binary, - is_boolean, - is_function, - is_float, - is_integer, - is_list, - is_map, - is_number, - is_tuple, - is_pid, - is_port, - is_reference, - is_bitstring, - add, - subtract, - multiply, - divide, - remainder, - apply, - new_tuple, - duplicate, - contains, - reverse, - get_global, - concat_lists, - prepend_to_list + Functions, + List } diff --git a/src/javascript/lib/core/functions.js b/src/javascript/lib/core/functions.js index 78ac4b89..8289a3a7 100644 --- a/src/javascript/lib/core/functions.js +++ b/src/javascript/lib/core/functions.js @@ -119,7 +119,7 @@ function apply(...args){ } } -function new_tuple(args){ +function new_tuple(...args){ return new Tuple(...args); } @@ -203,7 +203,80 @@ function prepend_to_list(list, item){ return [item].concat(list); } -export { +function defstruct(defaults){ + return class { + constructor(update = {}){ + let the_values = Object.assign(defaults, update); + Object.assign(this, the_values); + } + + static create(updates = {}){ + let x = new this(updates); + return Object.freeze(x); + } + } +} + + +function defexception(defaults){ + return class extends Error { + constructor(update = {}){ + let message = update.message || ""; + super(message); + + let the_values = Object.assign(defaults, update); + Object.assign(this, the_values); + + this.name = this.constructor.name; + this.message = message; + this[SpecialForms.atom("__exception__")] = true; + Error.captureStackTrace(this, this.constructor.name); + } + + static create(updates = {}){ + let x = new this(updates); + return Object.freeze(x); + } + } +} + +function defprotocol(spec){ + return new Protocol(spec); +} + +function defimpl(protocol, type, impl){ + protocol.implementation(type, impl); +} + +function get_object_keys(obj){ + return Object.keys(obj).concat(Object.getOwnPropertySymbols(obj)) +} + +function is_valid_character(codepoint){ + try{ + return String.fromCodePoint(codepoint) != null; + }catch(e){ + return false; + } +} + +//https://developer.mozilla.org/en-US/docs/Web/API/WindowBase64/Base64_encoding_and_decoding#Solution_2_%E2%80%93_rewrite_the_DOMs_atob()_and_btoa()_using_JavaScript's_TypedArrays_and_UTF-8 +function b64EncodeUnicode(str) { + return btoa(encodeURIComponent(str).replace(/%([0-9A-F]{2})/g, function(match, p1) { + return String.fromCharCode('0x' + p1); + })); +} + +function can_decode64(data) { + try{ + atob(data); + return true; + }catch(e){ + return false; + } +} + +export default { call_property, is_instance_of, size, @@ -234,5 +307,12 @@ export { reverse, get_global, concat_lists, - prepend_to_list + prepend_to_list, + defstruct, + defexception, + defprotocol, + defimpl, + get_object_keys, + is_valid_character, + b64EncodeUnicode }; diff --git a/src/javascript/lib/core/primitives.js b/src/javascript/lib/core/primitives.js index 2521eb63..4ac7c456 100644 --- a/src/javascript/lib/core/primitives.js +++ b/src/javascript/lib/core/primitives.js @@ -48,4 +48,8 @@ class PID { class Integer {} class Float {} -export { PID, Tuple, Integer, Float }; +function List(...args){ + return Object.freeze(args); +} + +export { PID, Tuple, Integer, Float, List }; diff --git a/src/javascript/lib/core/mailbox.js b/src/javascript/lib/core/processes/mailbox.js similarity index 100% rename from src/javascript/lib/core/mailbox.js rename to src/javascript/lib/core/processes/mailbox.js diff --git a/src/javascript/lib/core/process.js b/src/javascript/lib/core/processes/process.js similarity index 100% rename from src/javascript/lib/core/process.js rename to src/javascript/lib/core/processes/process.js diff --git a/src/javascript/lib/core/process_system.js b/src/javascript/lib/core/processes/process_system.js similarity index 98% rename from src/javascript/lib/core/process_system.js rename to src/javascript/lib/core/processes/process_system.js index 582e0289..a28e2243 100644 --- a/src/javascript/lib/core/process_system.js +++ b/src/javascript/lib/core/processes/process_system.js @@ -4,7 +4,7 @@ import Mailbox from "./mailbox"; import Process from "./process"; import States from "./states"; -import * as Primitives from "./primitives"; +import * as Primitives from "../primitives"; class ProcessSystem { diff --git a/src/javascript/lib/core/states.js b/src/javascript/lib/core/processes/states.js similarity index 100% rename from src/javascript/lib/core/states.js rename to src/javascript/lib/core/processes/states.js diff --git a/src/javascript/lib/protocol.js b/src/javascript/lib/core/protocol.js similarity index 88% rename from src/javascript/lib/protocol.js rename to src/javascript/lib/core/protocol.js index 81876675..06912855 100644 --- a/src/javascript/lib/protocol.js +++ b/src/javascript/lib/core/protocol.js @@ -1,4 +1,4 @@ -import * as Core from './core'; +import { Integer, Float } from './primitives'; //https://github.com/airportyh/protomorphism class Protocol{ @@ -16,9 +16,9 @@ class Protocol{ let thing = args[0]; let fun = null; - if(Number.isInteger(thing) && this.hasImplementation(Core.Integer)){ + if(Number.isInteger(thing) && this.hasImplementation(Integer)){ fun = this.registry.get(Core.Integer)[funName]; - }else if(typeof thing === "number" && !Number.isInteger(thing) && this.hasImplementation(Core.Float)){ + }else if(typeof thing === "number" && !Number.isInteger(thing) && this.hasImplementation(Float)){ fun = this.registry.get(Core.Float)[funName]; }else if(this.hasImplementation(thing)){ fun = this.registry.get(thing.constructor)[funName]; diff --git a/src/javascript/lib/enum.js b/src/javascript/lib/enum.js index 2c6781d4..bb8f10d5 100644 --- a/src/javascript/lib/enum.js +++ b/src/javascript/lib/enum.js @@ -1,4 +1,5 @@ import Kernel from './kernel'; +import * as Core from './core'; let Enum = { @@ -73,9 +74,9 @@ let Enum = { fetch: function(collection, n){ if(Kernel.is_list(collection)){ if(n < this.count(collection) && n >= 0){ - return Kernel.SpecialForms.tuple(Kernel.SpecialForms.atom("ok"), collection[n]); + return new Core.Tuple(Symbol.for("ok"), collection[n]); }else{ - return Kernel.SpecialForms.atom("error"); + return Symbol.for("error"); } } @@ -135,17 +136,17 @@ let Enum = { }, map_reduce: function(collection, acc, fun){ - let mapped = Kernel.SpecialForms.list(); + let mapped = Core.List(); let the_acc = acc; for (var i = 0; i < this.count(collection); i++) { let tuple = fun(collection[i], the_acc); - the_acc = Kernel.elem(tuple, 1); - mapped = Kernel.SpecialForms.list(...mapped.concat([Kernel.elem(tuple, 0)])); + the_acc = tuple.get(1); + mapped = Core.List(...mapped.concat([tuple.get(0)])); } - return Kernel.SpecialForms.tuple(mapped, the_acc); + return new Core.Tuple(mapped, the_acc); }, member__qmark__: function(collection, value){ @@ -158,7 +159,7 @@ let Enum = { for (var i = 0; i < this.count(collection); i++) { let tuple = fun(collection[i], the_acc); - the_acc = Kernel.elem(tuple, 1); + the_acc = tuple.get(1); } return the_acc; @@ -178,7 +179,7 @@ let Enum = { } } - return Kernel.SpecialForms.list(...result); + return Core.List(...result); }, take_while: function(collection, fun){ diff --git a/src/javascript/lib/enumerable.js b/src/javascript/lib/enumerable.js deleted file mode 100644 index cec6bfe6..00000000 --- a/src/javascript/lib/enumerable.js +++ /dev/null @@ -1,9 +0,0 @@ -import Kernel from "./kernel"; - -let Enumerable = Kernel.defprotocol({ - count: function(collection){}, - member_qmark__: function(collection, value){}, - reduce: function(collection, acc, fun){} -}); - -export default Enumerable; \ No newline at end of file diff --git a/src/javascript/lib/inspect.js b/src/javascript/lib/inspect.js deleted file mode 100644 index e9a7f140..00000000 --- a/src/javascript/lib/inspect.js +++ /dev/null @@ -1,7 +0,0 @@ -import Kernel from "./kernel"; - -let Inspect = Kernel.defprotocol({ - inspect: function(thing, opts){} -}); - -export default Inspect; \ No newline at end of file diff --git a/src/javascript/lib/integer.js b/src/javascript/lib/integer.js deleted file mode 100644 index d169226f..00000000 --- a/src/javascript/lib/integer.js +++ /dev/null @@ -1,38 +0,0 @@ -import Kernel from './kernel'; - -let Integer = { - - is_even: function(n){ - return n % 2 === 0; - }, - - is_odd: function(n){ - return n % 2 !== 0; - }, - - parse: function(bin){ - let result = parseInt(bin); - - if(isNaN(result)){ - return Kernel.SpecialForms.atom("error"); - } - - let indexOfDot = bin.indexOf("."); - - if(indexOfDot >= 0){ - return Kernel.SpecialForms.tuple(result, bin.substring(indexOfDot)); - } - - return Kernel.SpecialForms.tuple(result, ""); - }, - - to_char_list: function(number, base = 10){ - return number.toString(base).split(''); - }, - - to_string: function(number, base = 10){ - return number.toString(base); - } -}; - -export default Integer; diff --git a/src/javascript/lib/kernel.js b/src/javascript/lib/kernel.js index c634f7b6..a80eeac0 100644 --- a/src/javascript/lib/kernel.js +++ b/src/javascript/lib/kernel.js @@ -1,7 +1,5 @@ import SpecialForms from './kernel/special_forms'; import * as Core from './core'; -import Tuple from "./tuple"; -import Protocol from './protocol'; function tl(list){ return SpecialForms.list(...list.slice(1)); @@ -137,7 +135,7 @@ function apply(...args){ function to_string(arg){ if(is_tuple(arg)){ - return Tuple.to_string(arg); + return arg.toString(); } return arg.toString(); @@ -147,51 +145,6 @@ function match__qmark__(pattern, expr, guard = () => true){ return Core.Patterns.match_no_throw(pattern, expr, guard) != null; } -function defstruct(defaults){ - return class { - constructor(update = {}){ - let the_values = Object.assign(defaults, update); - Object.assign(this, the_values); - } - - static create(updates = {}){ - let x = new this(updates); - return Object.freeze(x); - } - } -} - - -function defexception(defaults){ - return class extends Error { - constructor(update = {}){ - let message = update.message || ""; - super(message); - - let the_values = Object.assign(defaults, update); - Object.assign(this, the_values); - - this.name = this.constructor.name; - this.message = message; - this[SpecialForms.atom("__exception__")] = true; - Error.captureStackTrace(this, this.constructor.name); - } - - static create(updates = {}){ - let x = new this(updates); - return Object.freeze(x); - } - } -} - -function defprotocol(spec){ - return new Protocol(spec); -} - -function defimpl(protocol, type, impl){ - protocol.implementation(type, impl); -} - export default { SpecialForms, tl, @@ -223,8 +176,5 @@ export default { not, apply, to_string, - match__qmark__, - defstruct, - defprotocol, - defimpl + match__qmark__ }; diff --git a/src/javascript/lib/kernel/special_forms.js b/src/javascript/lib/kernel/special_forms.js index ad4e7bef..7a5301b5 100644 --- a/src/javascript/lib/kernel/special_forms.js +++ b/src/javascript/lib/kernel/special_forms.js @@ -3,18 +3,6 @@ import Enum from '../enum'; let SpecialForms = { - __DIR__: function(){ - if(__dirname){ - return __dirname; - } - - if(document.currentScript){ - return document.currentScript.src; - } - - return null; - }, - atom: function(_value) { return Symbol.for(_value); }, diff --git a/src/javascript/lib/keyword.js b/src/javascript/lib/keyword.js index 88532fa4..2fc61b78 100644 --- a/src/javascript/lib/keyword.js +++ b/src/javascript/lib/keyword.js @@ -2,7 +2,7 @@ import Kernel from './kernel'; let Keyword = {}; -Keyword.has_key__qm__ = function(keywords, key){ +Keyword.has_key__qmark__ = function(keywords, key){ for(let keyword of keywords){ if(Kernel.elem(keyword, 0) == key){ return true; @@ -22,4 +22,4 @@ Keyword.get = function(keywords, key, the_default = null){ return the_default; } -export default Keyword; \ No newline at end of file +export default Keyword; diff --git a/src/javascript/lib/list.js b/src/javascript/lib/list.js index 38493dac..06b98c74 100644 --- a/src/javascript/lib/list.js +++ b/src/javascript/lib/list.js @@ -1,10 +1,8 @@ import Kernel from './kernel'; -import Chars from './list/chars'; +import * as Core from './core'; let List = {}; -List.Chars = Chars; - List.delete = function(list, item){ let new_value = []; let value_found = false; @@ -18,7 +16,7 @@ List.delete = function(list, item){ } } - return Kernel.SpecialForms.list(...new_value); + return Core.List(...new_value); }; List.delete_at = function(list, index){ @@ -30,7 +28,7 @@ List.delete_at = function(list, index){ } } - return Kernel.SpecialForms.list(...new_value); + return Core.List(...new_value); }; List.duplicate = function(elem, n){ @@ -40,14 +38,14 @@ List.duplicate = function(elem, n){ new_value.push(elem); } - return Kernel.SpecialForms.list(...new_value); + return Core.List(...new_value); }; List.first = function(list){ return list[0]; }; -List.flatten = function(list, tail = Kernel.SpecialForms.list()){ +List.flatten = function(list, tail = Core.List()){ let new_value = []; for(let x of list){ @@ -60,7 +58,7 @@ List.flatten = function(list, tail = Kernel.SpecialForms.list()){ new_value = new_value.concat(tail); - return Kernel.SpecialForms.list(...new_value); + return Core.List(...new_value); }; List.foldl = function(list, acc, func){ @@ -89,7 +87,7 @@ List.insert_at = function(list, index, value){ } } - return Kernel.SpecialForms.list(...new_value); + return Core.List(...new_value); }; List.keydelete = function(list, key, position){ @@ -101,7 +99,7 @@ List.keydelete = function(list, key, position){ } } - return Kernel.SpecialForms.list(...new_list); + return Core.List(...new_list); }; List.keyfind = function(list, key, position, _default = null){ @@ -137,7 +135,7 @@ List.keyreplace = function(list, key, position, new_tuple){ } } - return Kernel.SpecialForms.list(...new_list); + return Core.List(...new_list); }; @@ -169,7 +167,7 @@ List.keysort = function(list, position){ }); - return Kernel.SpecialForms.list(...new_list); + return Core.List(...new_list); }; List.keystore = function(list, key, position, new_tuple){ @@ -189,7 +187,7 @@ List.keystore = function(list, key, position, new_tuple){ new_list.push(new_tuple); } - return Kernel.SpecialForms.list(...new_list); + return Core.List(...new_list); }; List.last = function(list){ @@ -207,7 +205,7 @@ List.replace_at = function(list, index, value){ } } - return Kernel.SpecialForms.list(...new_value); + return Core.List(...new_value); }; List.update_at = function(list, index, fun){ @@ -228,15 +226,15 @@ List.wrap = function(list){ if(Kernel.is_list(list)){ return list; }else if(list == null){ - return Kernel.SpecialForms.list(); + return Core.List(); }else{ - return Kernel.SpecialForms.list(list); + return Core.List(list); } }; List.zip = function(list_of_lists){ if(list_of_lists.length === 0){ - return Kernel.SpecialForms.list(); + return Core.List(); } let new_value = []; @@ -254,22 +252,22 @@ List.zip = function(list_of_lists){ current_value.push(list_of_lists[j][i]); } - new_value.push(Kernel.SpecialForms.tuple(...current_value)); + new_value.push(new Core.Tuple(...current_value)); } - return Kernel.SpecialForms.list(...new_value); + return Core.List(...new_value); }; List.to_tuple = function(list){ - return Kernel.SpecialForms.tuple.apply(null, list); + return new Core.Tuple(...list); }; List.append = function(list, value){ - return Kernel.SpecialForms.list(...list.concat([value])); + return Core.List(...list.concat([value])); }; List.prepend = function(list, value){ - return Kernel.SpecialForms.list(...[value].concat(list)); + return Core.List(...[value].concat(list)); }; List.concat = function(left, right){ diff --git a/src/javascript/lib/list/chars.js b/src/javascript/lib/list/chars.js deleted file mode 100644 index 44a8059a..00000000 --- a/src/javascript/lib/list/chars.js +++ /dev/null @@ -1,40 +0,0 @@ -import Kernel from "../kernel"; -import Atom from "../atom"; -import Integer from "../integer"; -import String from "../string"; -import * as Core from '../core'; - -let Chars = Kernel.defprotocol({ - to_char_list: function(thing){} -}); - -Kernel.defimpl(Chars, Core.BitString, { - to_char_list: function(thing){ - if(Kernel.is_binary(thing)){ - return String.to_char_list(thing); - } - - return thing.toString(); - } -}); - -Kernel.defimpl(Chars, Symbol, { - to_char_list: function(thing){ - return Atom.to_char_list(thing); - } -}); - -Kernel.defimpl(Chars, Core.Integer, { - to_char_list: function(thing){ - return Integer.to_char_list(thing); - } -}); - - -Kernel.defimpl(Chars, Array, { - to_char_list: function(thing){ - return thing; - } -}); - -export default Chars; diff --git a/src/javascript/lib/map.js b/src/javascript/lib/map.js index 8775d4ea..9939af0b 100644 --- a/src/javascript/lib/map.js +++ b/src/javascript/lib/map.js @@ -1,11 +1,12 @@ import SpecialForms from './kernel/special_forms'; +import * as Core from './core'; function __new__(){ return SpecialForms.map({}); } function keys(map){ - return Object.keys(map).concat(Object.getOwnPropertySymbols(map)); + return Core.Functions.get_object_keys(map); } function size(map){ @@ -17,10 +18,10 @@ function to_list(map){ let list = []; for(let key of map_keys){ - list.push(SpecialForms.tuple(key, map[key])); + list.push(new Core.Tuple(key, map[key])); } - return SpecialForms.list(...list); + return Core.List(...list); } function values(map){ @@ -31,14 +32,14 @@ function values(map){ list.push(map[key]); } - return SpecialForms.list(...list); + return Core.List(...list); } function from_struct(struct){ let map = Object.assign({}, struct); delete map[Symbol.for("__struct__")]; - return SpecialForms.map(map); + return SpecialForms.map(map); } function __delete__(map, key){ @@ -46,7 +47,7 @@ function __delete__(map, key){ delete new_map[key]; - return SpecialForms.map(new_map); + return SpecialForms.map(new_map); } function drop(map, keys){ @@ -56,7 +57,7 @@ function drop(map, keys){ delete new_map[key]; } - return SpecialForms.map(new_map); + return SpecialForms.map(new_map); } @@ -74,10 +75,10 @@ function fetch__emark__(map, key){ function fetch(map, key){ if(key in map){ - return SpecialForms.tuple(SpecialForms.atom("ok"), map[key]); + return new Core.Tuple(Symbol.for("ok"), map[key]); } - return SpecialForms.atom("error"); + return Symbol.for("error"); } function has_key__qmark__(map, key){ @@ -92,7 +93,7 @@ function split(map, keys){ let split1 = {}; let split2 = {}; - for(let key of Object.keys(map).concat(Object.getOwnPropertySymbols(map))){ + for(let key of Core.Functions.get_object_keys(map) ){ if(keys.indexOf(key) > -1){ split1[key] = map[key]; }else{ @@ -100,8 +101,8 @@ function split(map, keys){ } } - return SpecialForms.tuple( - SpecialForms.map(split1), + return new Core.Tuple( + SpecialForms.map(split1), SpecialForms.map(split2) ); } @@ -109,7 +110,7 @@ function split(map, keys){ function take(map, keys){ let split1 = {}; - for(let key of Object.keys(map).concat(Object.getOwnPropertySymbols(map))){ + for(let key of Core.Functions.get_object_keys(map) ){ if(keys.indexOf(key) > -1){ split1[key] = map[key]; } @@ -121,7 +122,7 @@ function take(map, keys){ function drop(map, keys){ let split1 = {}; - for(let key of Object.keys(map).concat(Object.getOwnPropertySymbols(map))){ + for(let key of Core.Functions.get_object_keys(map) ){ if(keys.indexOf(key) === -1){ split1[key] = map[key]; } @@ -165,27 +166,27 @@ function get_and_update(map, key, fun){ function pop_lazy(map, key, fun){ if(!key in map){ - return SpecialForms.tuple(fun(), map); + return new Core.Tuple(fun(), map); } let new_map = Object.assign({}, map); let value = fun(new_map[key]); delete new_map[key]; - return SpecialForms.tuple(value, new_map); + return new Core.Tuple(value, new_map); } function pop(map, key, _default = null){ if(!key in map){ - return SpecialForms.tuple(_default, map); + return new Core.Tuple(_default, map); } let new_map = Object.assign({}, map); let value = new_map[key]; delete new_map[key]; - return SpecialForms.tuple(value, new_map); + return new Core.Tuple(value, new_map); } function get_lazy(map, key, fun){ @@ -220,7 +221,7 @@ function update__emark__(map, key, fun){ let new_map = Object({}, map); new_map[key] = fun(map[key]); - return SpecialForms.map(new_map); + return SpecialForms.map(new_map); } function update(map, key, initial, fun){ @@ -232,7 +233,7 @@ function update(map, key, initial, fun){ new_map[key] = fun(map[key]); } - return SpecialForms.map(new_map); + return SpecialForms.map(new_map); } @@ -261,4 +262,4 @@ export default { put, update__emark__, update -} \ No newline at end of file +} diff --git a/src/javascript/lib/map_set.js b/src/javascript/lib/map_set.js index 9b2b811a..0e8e3cc2 100644 --- a/src/javascript/lib/map_set.js +++ b/src/javascript/lib/map_set.js @@ -1,8 +1,9 @@ import SpecialForms from './kernel/special_forms'; import List from './list'; +import * as Core from './core'; function __new__(){ - return SpecialForms.map({ [Symbol.for("__struct__")]: Symbol.for("MapSet"), set: SpecialForms.list() }); + return SpecialForms.map({ [Symbol.for("__struct__")]: Symbol.for("MapSet"), set: Core.List() }); } function size(map){ @@ -18,7 +19,7 @@ function __delete__(set, term){ let new_map = Object.assign({}, set); new_map.set = new_list; - return SpecialForms.map(new_map); + return SpecialForms.map(new_map); } function put(set, term){ @@ -27,7 +28,7 @@ function put(set, term){ let new_map = Object.assign({}, set); new_map.set = new_list; - return SpecialForms.map(new_map); + return SpecialForms.map(new_map); } return set; @@ -42,7 +43,7 @@ function difference(set1, set2){ } } - return SpecialForms.map(new_map); + return SpecialForms.map(new_map); } @@ -55,7 +56,7 @@ function intersection(set1, set2){ } } - return SpecialForms.map(new_map); + return SpecialForms.map(new_map); } @@ -66,7 +67,7 @@ function union(set1, set2){ new_map = put(new_map, val); } - return SpecialForms.map(new_map); + return SpecialForms.map(new_map); } @@ -112,4 +113,4 @@ export default { union, intersection, difference -} \ No newline at end of file +} diff --git a/src/javascript/lib/range.js b/src/javascript/lib/range.js deleted file mode 100644 index 274eb95b..00000000 --- a/src/javascript/lib/range.js +++ /dev/null @@ -1,44 +0,0 @@ -let Range = function(_first, _last){ - if (!(this instanceof Range)){ - return new Range(_first, _last); - } - - this.first = function(){ - return _first; - }; - - this.last = function(){ - return _last; - }; - - let _range = []; - - for(let i = _first; i <= _last; i++){ - _range.push(i); - } - - _range = Object.freeze(_range); - - this.value = function(){ - return _range; - }; - - this.length = function(){ - return _range.length; - }; - - return this; -}; - -Range.prototype[Symbol.iterator] = function(){ - return this.value()[Symbol.iterator](); -}; - -Range.new = function (first, last) { - return Range(first, last); -}; - -Range.range__qmark__ = function (range) { - return range instanceof Range; -}; -export default Range; diff --git a/src/javascript/lib/set.js b/src/javascript/lib/set.js deleted file mode 100644 index 70fe61cf..00000000 --- a/src/javascript/lib/set.js +++ /dev/null @@ -1,60 +0,0 @@ -import MapSet from './map_set'; - -function size(map){ - return MapSet.size(map); -} - -function to_list(map){ - return MapSet.to_list(map); -} - -function __delete__(set, term){ - return MapSet.delete(set, term); -} - -function put(set, term){ - return MapSet.put(set, term); -} - -function difference(set1, set2){ - return MapSet.difference(set1, set2); -} - -function intersection(set1, set2){ - return MapSet.intersection(set1, set2); -} - -function union(set1, set2){ - return MapSet.union(set1, set2); -} - -function disjoin__qmark__(set1, set2){ - return MapSet.disjoin__qmark__(set1, set2); -} - -function member__qmark__(set, value){ - return MapSet.member__qmark__(set1, set2); -} - -function equal__qmark__(set1, set2){ - return MapSet.equal__qmark__(set1, set2); -} - -function subset__qmark__(set1, set2){ - return MapSet.subset__qmark__(set1, set2); -} - - -export default { - size, - to_list, - disjoin__qmark__, - delete: __delete__, - subset__qmark__, - equal__qmark__, - member__qmark__, - put, - union, - intersection, - difference -} \ No newline at end of file diff --git a/src/javascript/lib/string.js b/src/javascript/lib/string.js deleted file mode 100644 index 37fb7cae..00000000 --- a/src/javascript/lib/string.js +++ /dev/null @@ -1,195 +0,0 @@ -import Kernel from './kernel'; -import Chars from './string/chars'; - -function to_atom(string){ - return Symbol.for(string); -} - -function to_existing_atom(string){ - return Symbol.for(string); -} - -function to_char_list(string){ - return string.split(''); -} - -function to_float(string){ - return parseFloat(string); -} - -function to_integer(string, base = 10){ - return parseInt(string, base); -} - -function upcase(binary){ - return binary.toUpperCase(); -} - -function downcase(binary){ - return binary.toLowerCase(); -} - -function at(string, position){ - if(position > (string.length - 1)){ - return null; - } - - return string[position]; -} - -function capitalize(string){ - let returnString = ""; - - for(let i = 0; i < string.length; i++){ - if(i === 0){ - returnString = returnString + string[i].toUpperCase(); - }else{ - returnString = returnString + string[i].toLowerCase(); - } - } - - return returnString; -} - - -function codepoints(string){ - return to_char_list(string).map(function(c){ - return c.codePointAt(0); - }); -} - - -function contains__qm__(string, contains){ - if(Array.isArray(contains)){ - return contains.some(function(s){ - return string.indexOf(s) > -1; - }); - } - - return string.indexOf(contains) > -1; -} - -function duplicate(subject, n){ - return subject.repeat(n); -} - -function ends_with__qm__(string, suffixes){ - if(Array.isArray(suffixes)){ - return suffixes.some(function(s){ - return string.endsWith(s); - }); - } - - return string.endsWith(suffixes); -} - -function first(string){ - if(!string){ - return null; - } - - return string[0]; -} - -function graphemes(string){ - return string.split(''); -} - -function last(string){ - if(!string){ - return null; - } - - return string[string.length - 1]; -} - -function length(string){ - return string.length; -} - - -function match__qm__(string, regex){ - return string.match(regex) != null; -} - - -function next_codepoint(string){ - if(!string || string === ""){ - return null; - } - - return Kernel.SpecialForms.tuple(string[0].codePointAt(0), string.substr(1)); -} - - -function next_grapheme(string){ - if(!string || string === ""){ - return null; - } - - return Kernel.SpecialForms.tuple(string[0], string.substr(1)); -} - - -function reverse(string){ - let returnValue = ""; - - for (var i = string.length - 1; i >= 0; i--) { - returnValue = returnValue + string[i]; - }; - - return returnValue; -} - - -function split(string){ - return string.split(); -} - - -function starts_with__qm__(string, prefixes){ - if(Array.isArray(prefixes)){ - return prefixes.some(function(s){ - return string.startsWith(s); - }); - } - - return string.startsWith(prefixes); -} - -function valid_character__qm__(codepoint){ - try{ - return String.fromCodePoint(codepoint) != null; - }catch(e){ - return false; - } -} - - -export default { - at, - capitalize, - codepoints, - contains__qm__, - downcase, - duplicate, - ends_with__qm__, - first, - graphemes, - last, - length, - match__qm__, - next_codepoint, - next_grapheme, - reverse, - split, - starts_with__qm__, - to_atom, - to_char_list, - to_existing_atom, - to_float, - to_integer, - upcase, - valid_character__qm__, - Chars -} \ No newline at end of file diff --git a/src/javascript/lib/string/chars.js b/src/javascript/lib/string/chars.js deleted file mode 100644 index 26f14ce4..00000000 --- a/src/javascript/lib/string/chars.js +++ /dev/null @@ -1,63 +0,0 @@ -import Kernel from "../kernel"; -import Atom from "../atom"; -import Integer from "../integer"; -import List from "../list"; -import * as Core from '../core'; -import Tuple from "../tuple"; - -let Chars = Kernel.defprotocol({ - to_string: function(thing){} -}); - -Kernel.defimpl(Chars, Core.BitString, { - to_string: function(thing){ - if(Kernel.is_binary(thing)){ - return thing; - } - - return thing.toString(); - } -}); - -Kernel.defimpl(Chars, Symbol, { - to_string: function(thing){ - if(nil){ - return ""; - } - - return Atom.to_string(thing); - } -}); - -Kernel.defimpl(Chars, Core.Integer, { - to_string: function(thing){ - return Integer.to_string(thing); - } -}); - -Kernel.defimpl(Chars, Core.Float, { - to_string: function(thing){ - return thing.toString; - } -}); - -Kernel.defimpl(Chars, Array, { - to_string: function(thing){ - return thing.toString(); - } -}); - -Kernel.defimpl(Chars, Core.Tuple, { - to_string: function(thing){ - return Tuple.to_string(thing); - } -}); - - -Kernel.defimpl(Chars, null, { - to_string: function(thing){ - return thing.toString(); - } -}); - -export default Chars; diff --git a/src/javascript/lib/tuple.js b/src/javascript/lib/tuple.js deleted file mode 100644 index a334beca..00000000 --- a/src/javascript/lib/tuple.js +++ /dev/null @@ -1,66 +0,0 @@ -import Kernel from './kernel'; - -function to_string(tuple){ - return tuple.toString(); -}; - -function delete_at(tuple, index){ - let new_list = []; - - for (var i = 0; i < tuple.count(); i++) { - if(i !== index){ - new_list.push(tuple.get(i)); - } - } - - return Kernel.SpecialForms.tuple.apply(null, new_list); -}; - -function duplicate(data, size){ - let array = []; - - for (var i = size - 1; i >= 0; i--) { - array.push(data); - } - - return Kernel.SpecialForms.tuple.apply(null, array); -}; - -function insert_at(tuple, index, term){ - let new_tuple = []; - - for (var i = 0; i <= tuple.count(); i++) { - if(i === index){ - new_tuple.push(term); - i++; - new_tuple.push(tuple.get(i)); - }else{ - new_tuple.push(tuple.get(i)); - } - } - - return Kernel.SpecialForms.tuple.apply(null, new_tuple); -}; - -function from_list(list){ - return Kernel.SpecialForms.tuple.apply(null, list); -}; - -function to_list(tuple){ - let new_list = []; - - for (var i = 0; i < tuple.count(); i++) { - new_list.push(tuple.get(i)); - } - - return Kernel.SpecialForms.list(...new_list); -}; - -export default { - to_string, - delete_at, - duplicate, - insert_at, - from_list, - to_list -}; diff --git a/src/javascript/lib/view.js b/src/javascript/lib/view.js deleted file mode 100644 index 64095f58..00000000 --- a/src/javascript/lib/view.js +++ /dev/null @@ -1,51 +0,0 @@ -import Kernel from './kernel'; -import Keyword from './keyword'; -import VirtualDOM from './virtual-dom'; - - -const start = function(domRoot, renderFn, initialState, options = []){ - let pid = self.processes.spawn(); - - if(Keyword.has_key__qm__(options, Kernel.SpecialForms.atom("name"))){ - pid = self.processes.register(Keyword.get(options, Kernel.SpecialForms.atom("name")), pid) - } - - const tree = renderFn.apply(this, initialState); - const rootNode = VirtualDOM.create(tree); - - domRoot.appendChild(rootNode); - - self.processes.put(pid, "state", Kernel.SpecialForms.tuple(rootNode, tree, renderFn)); - return Kernel.SpecialForms.tuple(Kernel.SpecialForms.atom("ok"), pid); -} - -const stop = function(agent, timeout = 5000){ - self.processes.exit(agent); - return Kernel.SpecialForms.atom("ok"); -} - -const render = function(agent, state){ - - const current_state = self.processes.get(agent, "state"); - - let rootNode = Kernel.elem(current_state, 0); - let tree = Kernel.elem(current_state, 1); - let renderFn = Kernel.elem(current_state, 2); - - let newTree = renderFn.apply(this, state); - - let patches = VirtualDOM.diff(tree, newTree) - rootNode = VirtualDOM.patch(rootNode, patches) - - - self.processes.put(agent, "state", Kernel.SpecialForms.tuple(rootNode, newTree, renderFn)); - - return Kernel.SpecialForms.atom("ok"); -} - - -export default { - start, - stop, - render -} diff --git a/src/javascript/tests/atom.spec.js b/src/javascript/tests/atom.spec.js deleted file mode 100644 index c3c390cc..00000000 --- a/src/javascript/tests/atom.spec.js +++ /dev/null @@ -1,26 +0,0 @@ -var Kernel = require('../lib/kernel'); -var Atom = require('../lib/atom'); -var expect = require('chai').expect; - -describe('Atom', function(){ - - describe('to_string', function(){ - it('must display correctly', function(){ - let atom = Kernel.SpecialForms.atom("test"); - expect(Atom.to_string(atom)).to.equal("test"); - }) - }) - - describe('to_char_list', function(){ - it('must return a list of characters', function(){ - let atom = Kernel.SpecialForms.atom("test"); - let char_list = Atom.to_char_list(atom); - expect(char_list.length).to.equal(4); - expect(char_list[0]).to.equal('t'); - expect(char_list[1]).to.equal('e'); - expect(char_list[2]).to.equal('s'); - expect(char_list[3]).to.equal('t'); - }) - }) -}) - diff --git a/src/javascript/tests/case.spec.js b/src/javascript/tests/case.spec.js index 921f4a40..1bc6d231 100644 --- a/src/javascript/tests/case.spec.js +++ b/src/javascript/tests/case.spec.js @@ -9,7 +9,7 @@ describe('case', () => { it('case', () => { let clauses = [ Patterns.make_case( - [Kernel.SpecialForms.tuple(Kernel.SpecialForms.atom("selector"), Patterns.variable(), Patterns.variable())], + [Kernel.SpecialForms.tuple(Symbol.for("selector"), Patterns.variable(), Patterns.variable())], function(i, value){ return value; }, function(i){ return Kernel.is_integer(i); } ), diff --git a/src/javascript/tests/integer.spec.js b/src/javascript/tests/integer.spec.js deleted file mode 100644 index ef78eb8f..00000000 --- a/src/javascript/tests/integer.spec.js +++ /dev/null @@ -1,34 +0,0 @@ -var Integer = require('../lib/integer'); -var Kernel = require('../lib/kernel'); -var expect = require('chai').expect; - -describe('Integer', function(){ - it('parses integer string to integer', function(){ - let result = Integer.parse("34"); - expect(Kernel.elem(result, 0)).to.equal(34); - expect(Kernel.elem(result, 1)).to.equal(""); - }); - - it('parses float string to integer', function(){ - let result = Integer.parse("34.5"); - expect(Kernel.elem(result, 0)).to.equal(34); - expect(Kernel.elem(result, 1)).to.equal(".5"); - }); - - it('returns error when invalid', function(){ - let result = Integer.parse("three"); - expect(Kernel.match__qmark__(result, Kernel.SpecialForms.atom('error'))).to.equal(true); - }); - - it('converts base 10 integer to char_list', function(){ - let result = Integer.to_char_list(7); - expect(Kernel.match__qmark__(result, ["7"])).to.equal(true); - }); - - it('converts base 16 integer to char_list', function(){ - let result = Integer.to_char_list(1023, 16); - expect(Kernel.match__qmark__(result, ["3", "f", "f"])).to.equal(true); - }); - -}); - diff --git a/src/javascript/tests/kernel.spec.js b/src/javascript/tests/kernel.spec.js index 078caf0a..e86df3ef 100644 --- a/src/javascript/tests/kernel.spec.js +++ b/src/javascript/tests/kernel.spec.js @@ -21,8 +21,8 @@ describe('Kernel', function(){ }); it('match atoms', function(){ - expect(Kernel.match__qmark__(Kernel.SpecialForms.atom("test"), Kernel.SpecialForms.atom("test"))).to.equal(true); - expect(Kernel.match__qmark__(Kernel.SpecialForms.atom("test"), Kernel.SpecialForms.atom("notest"))).to.equal(false); + expect(Kernel.match__qmark__(Symbol.for("test"), Symbol.for("test"))).to.equal(true); + expect(Kernel.match__qmark__(Symbol.for("test"), Symbol.for("notest"))).to.equal(false); }); it('match tuples', function(){ diff --git a/src/javascript/tests/list.spec.js b/src/javascript/tests/list.spec.js index 8f49edc5..3e42a162 100644 --- a/src/javascript/tests/list.spec.js +++ b/src/javascript/tests/list.spec.js @@ -28,9 +28,9 @@ describe('List', function(){ describe('delete', function(){ it('delete item in list', function(){ - let t = Kernel.SpecialForms.list(Kernel.SpecialForms.atom("a"), Kernel.SpecialForms.atom("b"), Kernel.SpecialForms.atom("c")); - t = List.delete(t, Kernel.SpecialForms.atom("b")); - expect(t[1]).to.equal(Kernel.SpecialForms.atom("c")); + let t = Kernel.SpecialForms.list(Symbol.for("a"), Symbol.for("b"), Symbol.for("c")); + t = List.delete(t, Symbol.for("b")); + expect(t[1]).to.equal(Symbol.for("c")); }) }) diff --git a/src/javascript/tests/range.spec.js b/src/javascript/tests/range.spec.js deleted file mode 100644 index 72201a4e..00000000 --- a/src/javascript/tests/range.spec.js +++ /dev/null @@ -1,16 +0,0 @@ -var Range = require('../lib/range'); -var expect = require('chai').expect; - -describe('Range', function(){ - - describe('new', function(){ - it('must create a new Range', function(){ - let range = Range.new(0, 2); - - expect(range.first()).to.equal(0); - expect(range.last()).to.equal(2); - expect(range.length()).to.equal(3); - }) - }) -}) - diff --git a/src/javascript/tests/string.chars.spec.js b/src/javascript/tests/string.chars.spec.js deleted file mode 100644 index 3932aa96..00000000 --- a/src/javascript/tests/string.chars.spec.js +++ /dev/null @@ -1,14 +0,0 @@ -var String = require('../lib/string'); -var Tuple = require('../lib/core').Tuple; -var expect = require('chai').expect; - -describe('String.Chars', function(){ - - it('to_string', function(){ - expect(String.Chars.to_string(1)).to.equal("1"); - expect(String.Chars.to_string("a string")).to.equal("a string"); - expect(String.Chars.to_string(new Tuple(1, 2, 3))).to.equal("{1, 2, 3}"); - expect(String.Chars.to_string([1, 2, 3])).to.equal("1,2,3"); - }); - -}); diff --git a/src/javascript/tests/try.spec.js b/src/javascript/tests/try.spec.js index 88e1dd5e..4bb50436 100644 --- a/src/javascript/tests/try.spec.js +++ b/src/javascript/tests/try.spec.js @@ -24,14 +24,14 @@ describe('try', () => { let value = Kernel.SpecialForms._try(function() { return 1 / x; }, null, null, Patterns.defmatch(Patterns.make_case([Patterns.variable()], function(y) { - return Kernel.SpecialForms.atom('small'); + return Symbol.for('small'); }, function(y) { return (y < 1) && (y > -1); }), Patterns.make_case([Patterns.wildcard()], function() { - return Kernel.SpecialForms.atom('large'); + return Symbol.for('large'); })), null) - expect(value).to.equal(Kernel.SpecialForms.atom('large')); + expect(value).to.equal(Symbol.for('large')); }); }); diff --git a/src/javascript/tests/tuple.spec.js b/src/javascript/tests/tuple.spec.js deleted file mode 100644 index ade50062..00000000 --- a/src/javascript/tests/tuple.spec.js +++ /dev/null @@ -1,54 +0,0 @@ -"use strict"; - -var Kernel = require('../lib/kernel'); -var Tuple = require('../lib/tuple'); -var expect = require('chai').expect; - -describe('Tuple', function(){ - - describe('duplicate', function(){ - it('must make a tuple with the value duplicated the specified amount of times', function(){ - let t = Tuple.duplicate("value", 3); - expect(t.count()).to.equal(3); - expect(Kernel.elem(t, 0)).to.equal("value"); - expect(Kernel.elem(t, 1)).to.equal("value"); - expect(Kernel.elem(t, 2)).to.equal("value"); - - t = Tuple.duplicate("value", 0); - expect(t.count()).to.equal(0); - }); - }); - - describe('delete_at', function(){ - it('must delete first item', function(){ - let t = Kernel.SpecialForms.tuple(1, 2, 3); - - t = Tuple.delete_at(t, 0); - - expect(t.get(0)).to.equal(2); - }); - }); - - describe('toString', function(){ - it('must display correctly', function(){ - let t = Kernel.SpecialForms.tuple(1, 2, 3); - expect(Kernel.to_string(t)).to.equal("{1, 2, 3}"); - }); - }); - - describe('from_list', function(){ - it('must create a tuple from a list', function(){ - let list = Kernel.SpecialForms.list(1, 2, 3); - let tuple = Tuple.from_list(list); - expect(Kernel.to_string(tuple)).to.equal("{1, 2, 3}"); - }); - }); - - describe('to_list', function(){ - it('must create a list from a tuple', function(){ - let t = Kernel.SpecialForms.tuple(1, 2, 3); - expect(Tuple.to_list(t).length).to.equal(3); - }); - }); -}); - diff --git a/test/elixir_script_test.exs b/test/elixir_script_test.exs index c9aa57b5..7735f87c 100644 --- a/test/elixir_script_test.exs +++ b/test/elixir_script_test.exs @@ -12,7 +12,7 @@ defmodule ElixirScript.Test do should "turn javascript ast into javascript code strings" do js_code = ElixirScript.compile(":atom") - assert Enum.join(js_code, "\n") =~ "Elixir.Kernel.SpecialForms.atom('atom')" + assert Enum.join(js_code, "\n") =~ "Symbol.for('atom')" end should "parse one module correctly" do @@ -34,9 +34,9 @@ defmodule ElixirScript.Test do """) assert_js_matches """ - import * as Elixir from 'Elixir'; - import * as Elixir$ElixirScript$Kernel from 'Elixir.ElixirScript.Kernel'; - import * as Elixir$ElixirScript$String$Chars from 'Elixir.ElixirScript.String.Chars'; + import * as Elixir from './Elixir'; + import * as Elixir$ElixirScript$Kernel from './Elixir.ElixirScript.Kernel'; + import * as Elixir$ElixirScript$String$Chars from './Elixir.ElixirScript.String.Chars'; const something_else = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([],function() { return Elixir$ElixirScript$String$Chars.to_string(10); })); @@ -65,12 +65,12 @@ defmodule ElixirScript.Test do end end - """, env: make_custom_env) + """, %{ env: make_custom_env }) assert_js_matches """ - import * as Elixir from 'Elixir'; - import * as Elixir$Animals$Elephant from 'Elixir.Animals.Elephant'; - import * as Elixir$ElixirScript$Kernel from 'Elixir.ElixirScript.Kernel'; + import * as Elixir from './Elixir'; + import * as Elixir$ElixirScript$Kernel from './Elixir.ElixirScript.Kernel'; + import * as Elixir$Animals$Elephant from './Elixir.Animals.Elephant'; const something = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([],function() { return Elixir$Animals$Elephant.Elixir$Animals$Elephant.create(Elixir.Kernel.SpecialForms.map({})); })); @@ -80,11 +80,11 @@ defmodule ElixirScript.Test do """, hd(js_code) assert_js_matches """ - import * as Elixir from 'Elixir'; - import * as Elixir$ElixirScript$Kernel from 'Elixir.ElixirScript.Kernel'; - const Elixir$Animals$Elephant = Elixir.Kernel.defstruct({ - [Elixir.Kernel.SpecialForms.atom('__struct__')]: Elixir.Kernel.SpecialForms.atom('Elixir.Animals.Elephant'), - [Elixir.Kernel.SpecialForms.atom('trunk')]: true + import * as Elixir from './Elixir'; + import * as Elixir$ElixirScript$Kernel from './Elixir.ElixirScript.Kernel'; + const Elixir$Animals$Elephant = Elixir.Core.Functions.defstruct({ + [Symbol.for('__struct__')]: Symbol.for('Elixir.Animals.Elephant'), + [Symbol.for('trunk')]: true }); export { Elixir$Animals$Elephant @@ -104,11 +104,11 @@ defmodule ElixirScript.Test do end end - """, env: make_custom_env) + """, %{ env: make_custom_env }) assert_js_matches """ - import * as Elixir from 'Elixir'; - import * as Elixir$ElixirScript$Kernel from 'Elixir.ElixirScript.Kernel'; + import * as Elixir from './Elixir'; + import * as Elixir$ElixirScript$Kernel from './Elixir.ElixirScript.Kernel'; const something_else = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([],function() { return 1 * 1; })); @@ -157,11 +157,11 @@ defmodule ElixirScript.Test do end end - """, env: make_custom_env, stdlib_path: "elixirscript") + """, %{ env: make_custom_env, stdlib_path: "elixirscript"} ) assert_js_matches """ - import * as Elixir from 'elixirscript'; - import * as Elixir$ElixirScript$Kernel from 'Elixir.ElixirScript.Kernel'; + import * as Elixir from './elixirscript'; + import * as Elixir$ElixirScript$Kernel from './Elixir.ElixirScript.Kernel'; const something_else = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([],function() { return 1 * 1; })); diff --git a/test/lib/js_test.exs b/test/lib/js_test.exs index 3b1d3427..9433a4ef 100644 --- a/test/lib/js_test.exs +++ b/test/lib/js_test.exs @@ -30,7 +30,7 @@ defmodule ElixirScript.Lib.JS.Test do end js_code = """ - A['b'] = Elixir.Kernel.SpecialForms.list(1, 2, 3) + A['b'] = Elixir.Core.List(1, 2, 3) """ assert_translation(ex_ast, js_code) diff --git a/test/lib/kernel_test.exs b/test/lib/kernel_test.exs index 73153b70..e27dfa70 100644 --- a/test/lib/kernel_test.exs +++ b/test/lib/kernel_test.exs @@ -8,9 +8,12 @@ defmodule ElixirScript.Lib.Elixir.Kernel.Test do end js_code = """ - Range(1,4) + Elixir$ElixirScript$Range.Elixir$ElixirScript$Range.create(Elixir.Kernel.SpecialForms.map({ + [Symbol.for('first')]: 1, + [Symbol.for('last')]: 4 + })) """ assert_translation(ex_ast, js_code) end -end \ No newline at end of file +end diff --git a/test/pattern_matching/match_test.exs b/test/pattern_matching/match_test.exs index 9930ea23..fe168c53 100644 --- a/test/pattern_matching/match_test.exs +++ b/test/pattern_matching/match_test.exs @@ -8,7 +8,7 @@ defmodule ElixirScript.PatternMatching.Match.Test do # should "match wildcard" do # params = [{:_, [], Test}] -# result = Match.build_match(params, ElixirScript.Env.module_env(ElixirScript.Temp, "temp.ex") ) +# result = Match.build_match(params, ElixirScript.Translator.Env.module_env(ElixirScript.Temp, "temp.ex") ) # expected_result = { [Match.wildcard], [JS.identifier(:undefined)] } # # assert result == expected_result @@ -16,7 +16,7 @@ defmodule ElixirScript.PatternMatching.Match.Test do # # should "match one identifier param" do # params = [{:a, [], Test}] -# result = Match.build_match(params, ElixirScript.Env.module_env(ElixirScript.Temp, "temp.ex") ) +# result = Match.build_match(params, ElixirScript.Translator.Env.module_env(ElixirScript.Temp, "temp.ex") ) # expected_result = {[Match.parameter], [JS.identifier("a")]} # # assert result == expected_result @@ -24,7 +24,7 @@ defmodule ElixirScript.PatternMatching.Match.Test do # # should "match multiple identifier params" do # params = [{:a, [], Test}, {:b, [], Test}, {:c, [], Test}] -# result = Match.build_match(params, ElixirScript.Env.module_env(ElixirScript.Temp, "temp.ex") ) +# result = Match.build_match(params, ElixirScript.Translator.Env.module_env(ElixirScript.Temp, "temp.ex") ) # expected_result = { # List.duplicate(Match.parameter, 3), # [JS.identifier("a"), JS.identifier("b"), JS.identifier("c")] @@ -35,7 +35,7 @@ defmodule ElixirScript.PatternMatching.Match.Test do # # should "match head and tail param" do # params = [[{:|, [], [{:head, [], Elixir}, {:tail, [], Elixir}]}]] -# result = Match.build_match(params, ElixirScript.Env.module_env(ElixirScript.Temp, "temp.ex") ) +# result = Match.build_match(params, ElixirScript.Translator.Env.module_env(ElixirScript.Temp, "temp.ex") ) # expected_result = { # [Match.head_tail], # [JS.identifier("head"), JS.identifier("tail")] @@ -46,7 +46,7 @@ defmodule ElixirScript.PatternMatching.Match.Test do # # should "match prefix param" do # params = [{:<>, [context: Elixir, import: Elixir.Kernel], ["Bearer ", {:token, [], Elixir}]}] -# result = Match.build_match(params, ElixirScript.Env.module_env(ElixirScript.Temp, "temp.ex") ) +# result = Match.build_match(params, ElixirScript.Translator.Env.module_env(ElixirScript.Temp, "temp.ex") ) # expected_result = { # [Match.starts_with("Bearer ")], # [JS.identifier("token")] @@ -57,7 +57,7 @@ defmodule ElixirScript.PatternMatching.Match.Test do # # should "match list" do # params = [[{:a, [], Elixir}, {:b, [], Elixir}, {:c, [], Elixir}]] -# result = Match.build_match(params, ElixirScript.Env.module_env(ElixirScript.Temp, "temp.ex") ) +# result = Match.build_match(params, ElixirScript.Translator.Env.module_env(ElixirScript.Temp, "temp.ex") ) # expected_result = { # [Primitive.make_list_no_translate(List.duplicate(Match.parameter, 3))], # [JS.identifier("a"), JS.identifier("b"), JS.identifier("c")] @@ -68,7 +68,7 @@ defmodule ElixirScript.PatternMatching.Match.Test do # # should "match list with a literal" do # params = [[1, {:b, [], Elixir}, {:c, [], Elixir}]] -# result = Match.build_match(params, ElixirScript.Env.module_env(ElixirScript.Temp, "temp.ex") ) +# result = Match.build_match(params, ElixirScript.Translator.Env.module_env(ElixirScript.Temp, "temp.ex") ) # expected_result = { # [Primitive.make_list_no_translate([JS.literal(1), Match.parameter, Match.parameter])], # [JS.identifier("b"), JS.identifier("c")] @@ -79,7 +79,7 @@ defmodule ElixirScript.PatternMatching.Match.Test do # # should "match number" do # params = [1] -# result = Match.build_match(params, ElixirScript.Env.module_env(ElixirScript.Temp, "temp.ex") ) +# result = Match.build_match(params, ElixirScript.Translator.Env.module_env(ElixirScript.Temp, "temp.ex") ) # expected_result = { # [JS.literal(1)], # [] @@ -89,10 +89,10 @@ defmodule ElixirScript.PatternMatching.Match.Test do # end # # should "match struct pattern" do -# ElixirScript.State.start_link(nil, nil) +# ElixirScript.Translator.State.start_link(nil, nil) # # params = [{:%, [], [{:__aliases__, [alias: false], [:Hello]}, {:%{}, [], []}]}] -# result = Match.build_match(params, ElixirScript.Env.module_env(ElixirScript.Temp, "temp.ex") ) +# result = Match.build_match(params, ElixirScript.Translator.Env.module_env(ElixirScript.Temp, "temp.ex") ) # expected_result = { # [Match.type(JS.identifier(:Hello), JS.object_expression([]))], # [] @@ -100,17 +100,17 @@ defmodule ElixirScript.PatternMatching.Match.Test do # # assert result == expected_result # -# ElixirScript.State.stop() +# ElixirScript.Translator.State.stop() # end # # should "match struct pattern with property" do -# ElixirScript.State.start_link(nil, nil) +# ElixirScript.Translator.State.start_link(nil, nil) # # params = [{:%, [], [{:__aliases__, [alias: false], [:Hello]}, {:%{}, [], [key: 1]}]}] -# result = Match.build_match(params, ElixirScript.Env.module_env(ElixirScript.Temp, "temp.ex") ) +# result = Match.build_match(params, ElixirScript.Translator.Env.module_env(ElixirScript.Temp, "temp.ex") ) # expected_result = { # [Match.type(JS.identifier(:Hello), JS.object_expression([ -# Map.make_property(Translator.translate!(:key, ElixirScript.Env.module_env(ElixirScript.Temp, "temp.ex") ), Translator.translate!(1, ElixirScript.Env.module_env(ElixirScript.Temp, "temp.ex") )) +# Map.make_property(Translator.translate!(:key, ElixirScript.Translator.Env.module_env(ElixirScript.Temp, "temp.ex") ), Translator.translate!(1, ElixirScript.Translator.Env.module_env(ElixirScript.Temp, "temp.ex") )) # ])) # ], # [] @@ -118,17 +118,17 @@ defmodule ElixirScript.PatternMatching.Match.Test do # # assert result == expected_result # -# ElixirScript.State.stop() +# ElixirScript.Translator.State.stop() # end # # should "match struct pattern with property param" do -# ElixirScript.State.start_link(nil, nil) +# ElixirScript.Translator.State.start_link(nil, nil) # # params = [{:%, [], [{:__aliases__, [alias: false], [:Hello]}, {:%{}, [], [key: {:key, [], Elixir }]}]}] -# result = Match.build_match(params, ElixirScript.Env.module_env(ElixirScript.Temp, "temp.ex") ) +# result = Match.build_match(params, ElixirScript.Translator.Env.module_env(ElixirScript.Temp, "temp.ex") ) # expected_result = { # [Match.type(JS.identifier(:Hello), JS.object_expression([ -# Map.make_property(Translator.translate!(:key, ElixirScript.Env.module_env(ElixirScript.Temp, "temp.ex") ), Match.parameter) +# Map.make_property(Translator.translate!(:key, ElixirScript.Translator.Env.module_env(ElixirScript.Temp, "temp.ex") ), Match.parameter) # ])) # ], # [JS.identifier("key")] @@ -136,15 +136,15 @@ defmodule ElixirScript.PatternMatching.Match.Test do # # assert result == expected_result # -# ElixirScript.State.stop() +# ElixirScript.Translator.State.stop() # # end # # should "capture parameter when assigning it" do -# ElixirScript.State.start_link(nil, nil) +# ElixirScript.Translator.State.start_link(nil, nil) # # params = [{:=, [], [1, {:a, [], Elixir}]}] -# result = Match.build_match(params, ElixirScript.Env.module_env(ElixirScript.Temp, "temp.ex") ) +# result = Match.build_match(params, ElixirScript.Translator.Env.module_env(ElixirScript.Temp, "temp.ex") ) # expected_result = { # [Match.capture(JS.literal(1))], # [JS.identifier("a")] @@ -154,7 +154,7 @@ defmodule ElixirScript.PatternMatching.Match.Test do # # # params = [{:=, [], [{:a, [], Elixir}, 1]}] -# result = Match.build_match(params, ElixirScript.Env.module_env(ElixirScript.Temp, "temp.ex") ) +# result = Match.build_match(params, ElixirScript.Translator.Env.module_env(ElixirScript.Temp, "temp.ex") ) # expected_result = { # [Match.capture(JS.literal(1))], # [JS.identifier("a")] @@ -164,7 +164,7 @@ defmodule ElixirScript.PatternMatching.Match.Test do # # # params = [{:=, [], [{:%, [], [{:__aliases__, [alias: false], [:AStruct]}, {:%{}, [], []}]}, {:a, [], ElixirScript.Translator.Function.Test}]}] -# result = Match.build_match(params, ElixirScript.Env.module_env(ElixirScript.Temp, "temp.ex") ) +# result = Match.build_match(params, ElixirScript.Translator.Env.module_env(ElixirScript.Temp, "temp.ex") ) # expected_result = { # [Match.capture(Match.type(JS.identifier(:AStruct), JS.object_expression([])))], # [JS.identifier("a")] @@ -172,12 +172,12 @@ defmodule ElixirScript.PatternMatching.Match.Test do # # assert result == expected_result # -# ElixirScript.State.stop() +# ElixirScript.Translator.State.stop() # end # # should "match and assign list" do # params = [{:=, [], [[{:a, [], Elixir}, {:b, [], Elixir}, {:c, [], Elixir}], {:d, [], Elixir}]}] -# result = Match.build_match(params, ElixirScript.Env.module_env(ElixirScript.Temp, "temp.ex") ) +# result = Match.build_match(params, ElixirScript.Translator.Env.module_env(ElixirScript.Temp, "temp.ex") ) # expected_result = { # [Match.capture(Primitive.make_list_no_translate([Match.parameter, Match.parameter, Match.parameter]))], # [JS.identifier("a"), JS.identifier("b"), JS.identifier("c"), JS.identifier("d")] @@ -188,7 +188,7 @@ defmodule ElixirScript.PatternMatching.Match.Test do # # should "match on tuple" do # params = [{:{}, [], [1, {:b, [], Elixir}, 3]}] -# result = Match.build_match(params, ElixirScript.Env.module_env(ElixirScript.Temp, "temp.ex") ) +# result = Match.build_match(params, ElixirScript.Translator.Env.module_env(ElixirScript.Temp, "temp.ex") ) # expected_result = { # [Match.type(Primitive.tuple_class, JS.object_expression([JS.property( # JS.identifier("values"), @@ -200,7 +200,7 @@ defmodule ElixirScript.PatternMatching.Match.Test do # assert result == expected_result # # params = [{1, {:b, [], Elixir}}] -# result = Match.build_match(params, ElixirScript.Env.module_env(ElixirScript.Temp, "temp.ex") ) +# result = Match.build_match(params, ElixirScript.Translator.Env.module_env(ElixirScript.Temp, "temp.ex") ) # expected_result = { # [Match.type(Primitive.tuple_class, JS.object_expression([JS.property( # JS.identifier("values"), @@ -214,11 +214,11 @@ defmodule ElixirScript.PatternMatching.Match.Test do # # should "match on map" do # params = [{:%{}, [], [which: 13]}] -# result = Match.build_match(params, ElixirScript.Env.module_env(ElixirScript.Temp, "temp.ex") ) +# result = Match.build_match(params, ElixirScript.Translator.Env.module_env(ElixirScript.Temp, "temp.ex") ) # # expected_result = { # [JS.object_expression([ -# Map.make_property(Translator.translate!(:which, ElixirScript.Env.module_env(ElixirScript.Temp, "temp.ex") ), JS.literal(13)) +# Map.make_property(Translator.translate!(:which, ElixirScript.Translator.Env.module_env(ElixirScript.Temp, "temp.ex") ), JS.literal(13)) # ])], # [] # } @@ -229,7 +229,7 @@ defmodule ElixirScript.PatternMatching.Match.Test do # # should "match on bound value" do # params = [{:^, [], [{:a, [], Elixir}]}] -# result = Match.build_match(params, ElixirScript.Env.module_env(ElixirScript.Temp, "temp.ex") ) +# result = Match.build_match(params, ElixirScript.Translator.Env.module_env(ElixirScript.Temp, "temp.ex") ) # # expected_result = { # [Match.bound(JS.identifier("a"))], diff --git a/test/test_helper.exs b/test/test_helper.exs index f541a448..0040f746 100644 --- a/test/test_helper.exs +++ b/test/test_helper.exs @@ -30,7 +30,7 @@ defmodule ElixirScript.TestHelper do end def ex_ast_to_js(ex_ast) do - ElixirScript.compile_quoted(ex_ast, [env: make_custom_env, import_standard_libs: false]) + ElixirScript.compile_quoted(ex_ast, %{ env: make_custom_env, import_standard_libs: false }) end def strip_spaces(js) do diff --git a/test/translator/access_test.exs b/test/translator/access_test.exs index ced404ec..db076418 100644 --- a/test/translator/access_test.exs +++ b/test/translator/access_test.exs @@ -4,7 +4,7 @@ defmodule ElixirScript.Translator.Access.Test do should "translate access" do ex_ast = quote do: a[:b] - js_code = "a[Elixir.Kernel.SpecialForms.atom('b')]" + js_code = "a[Symbol.for('b')]" assert_translation(ex_ast, js_code) diff --git a/test/translator/assignment_test.exs b/test/translator/assignment_test.exs index 1c588a4e..363e1e7e 100644 --- a/test/translator/assignment_test.exs +++ b/test/translator/assignment_test.exs @@ -9,7 +9,7 @@ defmodule ElixirScript.Translator.Assignment.Test do assert_translation(ex_ast, js_code) ex_ast = quote do: a = :atom - js_code = "let [a] = Elixir.Core.Patterns.match(Elixir.Core.Patterns.variable(), Elixir.Kernel.SpecialForms.atom('atom'));" + js_code = "let [a] = Elixir.Core.Patterns.match(Elixir.Core.Patterns.variable(), Symbol.for('atom'));" assert_translation(ex_ast, js_code) end @@ -21,8 +21,8 @@ defmodule ElixirScript.Translator.Assignment.Test do js_code = """ let [a, b] = Elixir.Core.Patterns.match(Elixir.Core.Patterns.type(Elixir.Core.Tuple, { values: [Elixir.Core.Patterns.variable(), Elixir.Core.Patterns.variable()] - }), Elixir.Kernel.SpecialForms.tuple(1, 2)); - let _ref = Elixir.Kernel.SpecialForms.tuple(a, b); + }), Elixir.Core.Functions.new_tuple(1, 2)); + let _ref = Elixir.Core.Functions.new_tuple(a, b); """ assert_translation(ex_ast, js_code) @@ -31,8 +31,8 @@ defmodule ElixirScript.Translator.Assignment.Test do js_code = """ let [a, undefined, c] = Elixir.Core.Patterns.match(Elixir.Core.Patterns.type(Elixir.Core.Tuple, { values: [Elixir.Core.Patterns.variable(), Elixir.Core.Patterns.wildcard(), Elixir.Core.Patterns.variable()] - }), Elixir.Kernel.SpecialForms.tuple(1, 2, 3)); - let _ref = Elixir.Kernel.SpecialForms.tuple(a, undefined, c); + }), Elixir.Core.Functions.new_tuple(1, 2, 3)); + let _ref = Elixir.Core.Functions.new_tuple(a, undefined, c); """ assert_translation(ex_ast, js_code) @@ -42,8 +42,8 @@ defmodule ElixirScript.Translator.Assignment.Test do js_code = """ let [, undefined, c] = Elixir.Core.Patterns.match(Elixir.Core.Patterns.type(Elixir.Core.Tuple, { values: [Elixir.Core.Patterns.bound(a), Elixir.Core.Patterns.wildcard(), Elixir.Core.Patterns.variable()] - }), Elixir.Kernel.SpecialForms.tuple(1, 2, 3)); - let _ref = Elixir.Kernel.SpecialForms.tuple(undefined, undefined, c); + }), Elixir.Core.Functions.new_tuple(1, 2, 3)); + let _ref = Elixir.Core.Functions.new_tuple(undefined, undefined, c); """ assert_translation(ex_ast, js_code) @@ -61,8 +61,8 @@ defmodule ElixirScript.Translator.Assignment.Test do should "translate list assignment" do ex_ast = quote do: [a, b] = [1, 2] js_code = """ - let [a, b] = Elixir.Core.Patterns.match(Elixir.Kernel.SpecialForms.list(Elixir.Core.Patterns.variable(), Elixir.Core.Patterns.variable()), Elixir.Kernel.SpecialForms.list(1, 2)); - let _ref = Elixir.Kernel.SpecialForms.list(a, b); + let [a, b] = Elixir.Core.Patterns.match(Elixir.Core.List(Elixir.Core.Patterns.variable(), Elixir.Core.Patterns.variable()), Elixir.Core.List(1, 2)); + let _ref = Elixir.Core.List(a, b); """ assert_translation(ex_ast, js_code) @@ -71,8 +71,8 @@ defmodule ElixirScript.Translator.Assignment.Test do should "translate head/tail assignment" do ex_ast = quote do: [a | b] = [1, 2, 3, 4] js_code = """ - let [a,b] = Elixir.Core.Patterns.match(Elixir.Core.Patterns.headTail(),Elixir.Kernel.SpecialForms.list(1,2,3,4)); - let _ref = Elixir.Kernel.SpecialForms.list(a,b); + let [a,b] = Elixir.Core.Patterns.match(Elixir.Core.Patterns.headTail(),Elixir.Core.List(1,2,3,4)); + let _ref = Elixir.Core.List(a,b); """ assert_translation(ex_ast, js_code) diff --git a/test/translator/atom_test.exs b/test/translator/atom_test.exs index 6e51bd97..f4f37367 100644 --- a/test/translator/atom_test.exs +++ b/test/translator/atom_test.exs @@ -4,11 +4,11 @@ defmodule ElixirScript.Translator.Atom.Test do should "translate atom" do ex_ast = quote do: :atom - assert_translation(ex_ast, "Elixir.Kernel.SpecialForms.atom('atom')") + assert_translation(ex_ast, "Symbol.for('atom')") end should "Call Atom module" do ex_ast = quote do: Atom.to_string(:atom) - assert_translation(ex_ast, "Elixir$ElixirScript$Atom.to_string(Elixir.Kernel.SpecialForms.atom('atom'))") + assert_translation(ex_ast, "Elixir$ElixirScript$Atom.to_string(Symbol.for('atom'))") end end diff --git a/test/translator/bug_test.exs b/test/translator/bug_test.exs index eefc9208..19858c9e 100644 --- a/test/translator/bug_test.exs +++ b/test/translator/bug_test.exs @@ -11,7 +11,7 @@ defmodule ElixirScript.Translator.Bug.Test do js_code = """ const test = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([],function(){ - return Elixir.Kernel.SpecialForms.atom('atom'); + return Symbol.for('atom'); })); """ @@ -29,7 +29,7 @@ defmodule ElixirScript.Translator.Bug.Test do js_code = """ React.createElement(React.Text,Elixir.Kernel.SpecialForms.map({ - style: Elixir.Core.call_property(styles,'welcome') + style: Elixir.Core.Functions.call_property(styles,'welcome') }),'Welcome to React Native!') """ @@ -47,8 +47,8 @@ defmodule ElixirScript.Translator.Bug.Test do js_code = """ import { default as JQuery } from 'jquery'; - import * as Elixir$ElixirScript$Kernel from 'Elixir.ElixirScript.Kernel'; - JQuery(Elixir.Core.call_property(e,'target')); + import * as Elixir$ElixirScript$Kernel from './Elixir.ElixirScript.Kernel'; + JQuery(Elixir.Core.Functions.call_property(e,'target')); export {}; """ @@ -61,7 +61,7 @@ defmodule ElixirScript.Translator.Bug.Test do end js_code = """ - const graphic_store = Elixir.Core.call_property(App.Stores.GraphicStore, 'create_store'); + const graphic_store = Elixir.Core.Functions.call_property(App.Stores.GraphicStore, 'create_store'); """ @@ -86,7 +86,7 @@ defmodule ElixirScript.Translator.Bug.Test do end js_code = """ - Elixir.Core.call_property(this, 'getRawCanvas').getContext('2d') + Elixir.Core.Functions.call_property(this, 'getRawCanvas').getContext('2d') """ assert_translation(ex_ast, js_code) @@ -119,15 +119,15 @@ defmodule ElixirScript.Translator.Bug.Test do js_code = """ const getDispatcher = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([],function() { return DeLorean.Flux.createDispatcher(Elixir.Kernel.SpecialForms.map({ - [Elixir.Kernel.SpecialForms.atom('startPainting')]: Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([],function() { + [Symbol.for('startPainting')]: Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([],function() { return this.dispatch('startPainting'); - })), [Elixir.Kernel.SpecialForms.atom('stopPainting')]: Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([],function() { + })), [Symbol.for('stopPainting')]: Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([],function() { return this.dispatch('stopPainting'); - })), [Elixir.Kernel.SpecialForms.atom('addPoint')]: Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable()],function(data) { + })), [Symbol.for('addPoint')]: Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable()],function(data) { return this.dispatch('addPoint',data); - })), [Elixir.Kernel.SpecialForms.atom('getStores')]: Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([],function() { + })), [Symbol.for('getStores')]: Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([],function() { return Elixir.Kernel.SpecialForms.map({ - [Elixir.Kernel.SpecialForms.atom('graphic')]: GraphicStore + [Symbol.for('graphic')]: GraphicStore }); })) })); diff --git a/test/translator/capture_test.exs b/test/translator/capture_test.exs index bcfcc7d4..1039a855 100644 --- a/test/translator/capture_test.exs +++ b/test/translator/capture_test.exs @@ -74,7 +74,7 @@ defmodule ElixirScript.Translator.Capture.Test do js_code = """ let [fun] = Elixir.Core.Patterns.match(Elixir.Core.Patterns.variable(),Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable(), Elixir.Core.Patterns.variable()],function(__1,__2) { - return Elixir.Kernel.SpecialForms.tuple(__1,__2); + return Elixir.Core.Functions.new_tuple(__1,__2); }))); """ @@ -86,7 +86,7 @@ defmodule ElixirScript.Translator.Capture.Test do js_code = """ let [fun] = Elixir.Core.Patterns.match(Elixir.Core.Patterns.variable(),Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable(), Elixir.Core.Patterns.variable(), Elixir.Core.Patterns.variable()],function(__1,__2,__3) { - return Elixir.Kernel.SpecialForms.tuple(__1,__2,__3); + return Elixir.Core.Functions.new_tuple(__1,__2,__3); }))); """ diff --git a/test/translator/case_test.exs b/test/translator/case_test.exs index bbc3a57d..297ca27b 100644 --- a/test/translator/case_test.exs +++ b/test/translator/case_test.exs @@ -12,9 +12,9 @@ defmodule ElixirScript.Translator.Case.Test do end js_code = """ - Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Kernel.SpecialForms.atom('ok')],function() { + Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Symbol.for('ok')],function() { return value; - }),Elixir.Core.Patterns.make_case([Elixir.Kernel.SpecialForms.atom('error')],function() { + }),Elixir.Core.Patterns.make_case([Symbol.for('error')],function() { return null; })).call(this,data) """ @@ -75,7 +75,7 @@ defmodule ElixirScript.Translator.Case.Test do let [value] = Elixir.Core.Patterns.match(Elixir.Core.Patterns.variable(),13); return value; },function(number) { - return Elixir.Core.contains(number,Elixir.Kernel.SpecialForms.list(1,2,3,4)); + return Elixir.Core.Functions.contains(number,Elixir.Core.List(1,2,3,4)); }),Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.wildcard()],function() { return true; })).call(this,data) @@ -96,10 +96,10 @@ defmodule ElixirScript.Translator.Case.Test do end js_code = """ - Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Kernel.SpecialForms.atom('ok')],function() { + Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Symbol.for('ok')],function() { console.info('info'); return Todo.add(data); - }),Elixir.Core.Patterns.make_case([Elixir.Kernel.SpecialForms.atom('error')],function() { + }),Elixir.Core.Patterns.make_case([Symbol.for('error')],function() { return null; })).call(this,data) """ @@ -122,7 +122,7 @@ defmodule ElixirScript.Translator.Case.Test do values: [Elixir.Core.Patterns.variable(), Elixir.Core.Patterns.variable()] })], function(one, two) { return console.info(one); - }), Elixir.Core.Patterns.make_case([Elixir.Kernel.SpecialForms.atom('error')], function() { + }), Elixir.Core.Patterns.make_case([Symbol.for('error')], function() { return null; })).call(this, data) """ @@ -147,7 +147,7 @@ defmodule ElixirScript.Translator.Case.Test do }), Elixir.Core.Patterns.variable()] })], function(one, two, three) { return console.info(one); - }), Elixir.Core.Patterns.make_case([Elixir.Kernel.SpecialForms.atom('error')], function() { + }), Elixir.Core.Patterns.make_case([Symbol.for('error')], function() { return null; })).call(this, data) """ @@ -170,7 +170,7 @@ defmodule ElixirScript.Translator.Case.Test do })] })], function(one, two, three) { return console.info(one); - }), Elixir.Core.Patterns.make_case([Elixir.Kernel.SpecialForms.atom('error')], function() { + }), Elixir.Core.Patterns.make_case([Symbol.for('error')], function() { return null; })).call(this, data) """ @@ -189,12 +189,12 @@ defmodule ElixirScript.Translator.Case.Test do js_code = """ Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.type(AStruct, { - [Elixir.Kernel.SpecialForms.atom('key')]: Elixir.Core.Patterns.type(BStruct, { - [Elixir.Kernel.SpecialForms.atom('key2')]: Elixir.Core.Patterns.variable() + [Symbol.for('key')]: Elixir.Core.Patterns.type(BStruct, { + [Symbol.for('key2')]: Elixir.Core.Patterns.variable() }) })], function(value) { return console.info(value); - }), Elixir.Core.Patterns.make_case([Elixir.Kernel.SpecialForms.atom('error')], function() { + }), Elixir.Core.Patterns.make_case([Symbol.for('error')], function() { return null; })).call(this, data) """ @@ -213,14 +213,14 @@ defmodule ElixirScript.Translator.Case.Test do js_code = """ Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.type(AStruct, { - [Elixir.Kernel.SpecialForms.atom('key')]: Elixir.Core.Patterns.type(BStruct, { - [Elixir.Kernel.SpecialForms.atom('key2')]: Elixir.Core.Patterns.variable(), [Elixir.Kernel.SpecialForms.atom('key3')]: Elixir.Core.Patterns.type(CStruct, { - [Elixir.Kernel.SpecialForms.atom('key4')]: Elixir.Core.Patterns.variable() + [Symbol.for('key')]: Elixir.Core.Patterns.type(BStruct, { + [Symbol.for('key2')]: Elixir.Core.Patterns.variable(), [Symbol.for('key3')]: Elixir.Core.Patterns.type(CStruct, { + [Symbol.for('key4')]: Elixir.Core.Patterns.variable() }) }) })], function(value, value2) { return console.info(value); - }), Elixir.Core.Patterns.make_case([Elixir.Kernel.SpecialForms.atom('error')], function() { + }), Elixir.Core.Patterns.make_case([Symbol.for('error')], function() { return null; })).call(this, data) """ diff --git a/test/translator/cond_test.exs b/test/translator/cond_test.exs index a6e3d364..3e066f58 100644 --- a/test/translator/cond_test.exs +++ b/test/translator/cond_test.exs @@ -15,11 +15,11 @@ defmodule ElixirScript.Translator.Cond.Test do end js_code = """ - Elixir.Kernel.SpecialForms.cond(Elixir.Kernel.SpecialForms.list(1 + 1 == 1,function() { + Elixir.Kernel.SpecialForms.cond(Elixir.Core.List(1 + 1 == 1,function() { return 'This will never match'; - }),Elixir.Kernel.SpecialForms.list(2 * 2 != 4,function() { + }),Elixir.Core.List(2 * 2 != 4,function() { return 'Nor this'; - }),Elixir.Kernel.SpecialForms.list(true,function() { + }),Elixir.Core.List(true,function() { return 'This will'; })) """ @@ -41,13 +41,13 @@ defmodule ElixirScript.Translator.Cond.Test do end js_code = """ - Elixir.Kernel.SpecialForms.cond(Elixir.Kernel.SpecialForms.list(1 + 1 == 1,function() { + Elixir.Kernel.SpecialForms.cond(Elixir.Core.List(1 + 1 == 1,function() { let [a] = Elixir.Core.Patterns.match(Elixir.Core.Patterns.variable(),1); return 'This will never match'; - }),Elixir.Kernel.SpecialForms.list(2 * 2 != 4,function() { + }),Elixir.Core.List(2 * 2 != 4,function() { let [a] = Elixir.Core.Patterns.match(Elixir.Core.Patterns.variable(),2); return 'Nor this'; - }),Elixir.Kernel.SpecialForms.list(true,function() { + }),Elixir.Core.List(true,function() { let [a] = Elixir.Core.Patterns.match(Elixir.Core.Patterns.variable(),3); return 'This will'; })) diff --git a/test/translator/defmodule_test.exs b/test/translator/defmodule_test.exs index d586a0f3..640ba3d1 100644 --- a/test/translator/defmodule_test.exs +++ b/test/translator/defmodule_test.exs @@ -9,7 +9,7 @@ defmodule ElixirScript.Translator.Defmodule.Test do end js_code = """ - import * as Elixir$ElixirScript$Kernel from 'Elixir.ElixirScript.Kernel'; + import * as Elixir$ElixirScript$Kernel from './Elixir.ElixirScript.Kernel'; export {}; """ @@ -32,7 +32,7 @@ defmodule ElixirScript.Translator.Defmodule.Test do js_code = """ - import * as Elixir$ElixirScript$Kernel from 'Elixir.ElixirScript.Kernel'; + import * as Elixir$ElixirScript$Kernel from './Elixir.ElixirScript.Kernel'; const something_else = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([],function() { return null; })); @@ -67,8 +67,8 @@ defmodule ElixirScript.Translator.Defmodule.Test do end js_code = """ - import * as Elixir$Animals$Elephant from 'Elixir.Animals.Elephant'; - import * as Elixir$ElixirScript$Kernel from 'Elixir.ElixirScript.Kernel'; + import * as Elixir$ElixirScript$Kernel from './Elixir.ElixirScript.Kernel'; + import * as Elixir$Animals$Elephant from './Elixir.Animals.Elephant'; const something_else = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([],function() { return null; })); @@ -81,9 +81,9 @@ defmodule ElixirScript.Translator.Defmodule.Test do something }; - import * as Elixir$ElixirScript$Kernel from 'Elixir.ElixirScript.Kernel'; - const Elixir$Animals$Elephant = Elixir.Kernel.defstruct({ - [Elixir.Kernel.SpecialForms.atom('__struct__')]: Elixir.Kernel.SpecialForms.atom('Elixir.Animals.Elephant'), [Elixir.Kernel.SpecialForms.atom('trunk')]: true + import * as Elixir$ElixirScript$Kernel from './Elixir.ElixirScript.Kernel'; + const Elixir$Animals$Elephant = Elixir.Core.Functions.defstruct({ + [Symbol.for('__struct__')]: Symbol.for('Elixir.Animals.Elephant'), [Symbol.for('trunk')]: true }); export { @@ -119,8 +119,8 @@ defmodule ElixirScript.Translator.Defmodule.Test do end js_code = """ - import * as Elixir$Animals$Elephant from 'Elixir.Animals.Elephant'; - import * as Elixir$ElixirScript$Kernel from 'Elixir.ElixirScript.Kernel'; + import * as Elixir$ElixirScript$Kernel from './Elixir.ElixirScript.Kernel'; + import * as Elixir$Animals$Elephant from './Elixir.Animals.Elephant'; const something_else = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([],function() { return null; })); @@ -132,20 +132,20 @@ defmodule ElixirScript.Translator.Defmodule.Test do something }; - import * as Elixir$Animals$Elephant$Bear from 'Elixir.Animals.Elephant.Bear'; - import * as Elixir$ElixirScript$Kernel from 'Elixir.ElixirScript.Kernel'; - const Elixir$Animals$Elephant = Elixir.Kernel.defstruct({ - [Elixir.Kernel.SpecialForms.atom('__struct__')]: Elixir.Kernel.SpecialForms.atom('Elixir.Animals.Elephant'), - [Elixir.Kernel.SpecialForms.atom('trunk')]: true + import * as Elixir$ElixirScript$Kernel from './Elixir.ElixirScript.Kernel'; + import * as Elixir$Animals$Elephant$Bear from './Elixir.Animals.Elephant.Bear'; + const Elixir$Animals$Elephant = Elixir.Core.Functions.defstruct({ + [Symbol.for('__struct__')]: Symbol.for('Elixir.Animals.Elephant'), + [Symbol.for('trunk')]: true }); export { Elixir$Animals$Elephant }; - import * as Elixir$ElixirScript$Kernel from 'Elixir.ElixirScript.Kernel'; - const Elixir$Animals$Elephant$Bear = Elixir.Kernel.defstruct({ - [Elixir.Kernel.SpecialForms.atom('__struct__')]: Elixir.Kernel.SpecialForms.atom('Elixir.Animals.Elephant.Bear'), - [Elixir.Kernel.SpecialForms.atom('trunk')]: true + import * as Elixir$ElixirScript$Kernel from './Elixir.ElixirScript.Kernel'; + const Elixir$Animals$Elephant$Bear = Elixir.Core.Functions.defstruct({ + [Symbol.for('__struct__')]: Symbol.for('Elixir.Animals.Elephant.Bear'), + [Symbol.for('trunk')]: true }); export { @@ -168,13 +168,13 @@ defmodule ElixirScript.Translator.Defmodule.Test do end js_code = """ - import * as Elixir$ElixirScript$Kernel from 'Elixir.ElixirScript.Kernel'; - import * as Elixir$Lions$Tigers from 'Elixir.Lions.Tigers'; - Elixir.Core.call_property(Elixir$Lions$Tigers,'oh_my'); + import * as Elixir$ElixirScript$Kernel from './Elixir.ElixirScript.Kernel'; + import * as Elixir$Lions$Tigers from './Elixir.Lions.Tigers'; + Elixir.Core.Functions.call_property(Elixir$Lions$Tigers,'oh_my'); export {}; - import * as Elixir$ElixirScript$Kernel from 'Elixir.ElixirScript.Kernel'; - Elixir.Core.call_property(Lions.Tigers.Bears,'oh_my'); + import * as Elixir$ElixirScript$Kernel from './Elixir.ElixirScript.Kernel'; + Elixir.Core.Functions.call_property(Lions.Tigers.Bears,'oh_my'); export {}; """ @@ -198,16 +198,16 @@ defmodule ElixirScript.Translator.Defmodule.Test do end js_code = """ - import * as Elixir$ElixirScript$Kernel from 'Elixir.ElixirScript.Kernel'; - import * as Elixir$Lions$Tigers from 'Elixir.Lions.Tigers'; - Elixir.Core.call_property(Elixir$Lions$Tigers,'oh_my'); + import * as Elixir$ElixirScript$Kernel from './Elixir.ElixirScript.Kernel'; + import * as Elixir$Lions$Tigers from './Elixir.Lions.Tigers'; + Elixir.Core.Functions.call_property(Elixir$Lions$Tigers,'oh_my'); export {}; - import * as Elixir$ElixirScript$Kernel from 'Elixir.ElixirScript.Kernel'; + import * as Elixir$ElixirScript$Kernel from './Elixir.ElixirScript.Kernel'; const oh_my = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([],function() { return null; })); - Elixir.Core.call_property(Lions.Tigers.Bears,'oh_my'); + Elixir.Core.Functions.call_property(Lions.Tigers.Bears,'oh_my'); export { oh_my }; @@ -234,12 +234,12 @@ defmodule ElixirScript.Translator.Defmodule.Test do end js_code = """ - import * as Elixir$ElixirScript$Kernel from 'Elixir.ElixirScript.Kernel'; - import * as Elixir$Lions$Tigers from 'Elixir.Lions.Tigers'; + import * as Elixir$ElixirScript$Kernel from './Elixir.ElixirScript.Kernel'; + import * as Elixir$Lions$Tigers from './Elixir.Lions.Tigers'; Elixir$Lions$Tigers.oh_my(); export {}; - import * as Elixir$ElixirScript$Kernel from 'Elixir.ElixirScript.Kernel'; + import * as Elixir$ElixirScript$Kernel from './Elixir.ElixirScript.Kernel'; const oh_my2 = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([],function() { return null; })); @@ -274,12 +274,12 @@ defmodule ElixirScript.Translator.Defmodule.Test do end js_code = """ - import * as Elixir$ElixirScript$Kernel from 'Elixir.ElixirScript.Kernel'; - import * as Elixir$Lions$Tigers from 'Elixir.Lions.Tigers'; + import * as Elixir$ElixirScript$Kernel from './Elixir.ElixirScript.Kernel'; + import * as Elixir$Lions$Tigers from './Elixir.Lions.Tigers'; Elixir$Lions$Tigers.oh_my2(); export {}; - import * as Elixir$ElixirScript$Kernel from 'Elixir.ElixirScript.Kernel'; + import * as Elixir$ElixirScript$Kernel from './Elixir.ElixirScript.Kernel'; const oh_my2 = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([],function() { return null; })); diff --git a/test/translator/for_test.exs b/test/translator/for_test.exs index 8123bb8c..4b2b94f7 100644 --- a/test/translator/for_test.exs +++ b/test/translator/for_test.exs @@ -8,11 +8,11 @@ defmodule ElixirScript.Translator.For.Test do end js_code = """ - Elixir.Kernel.SpecialForms._for(Elixir.Kernel.SpecialForms.list(Elixir.Kernel.SpecialForms.list(Elixir.Core.Patterns.variable(),Elixir.Kernel.SpecialForms.list(1,2,3,4))),function(n) { + Elixir.Kernel.SpecialForms._for(Elixir.Core.List(Elixir.Core.List(Elixir.Core.Patterns.variable(),Elixir.Core.List(1,2,3,4))),function(n) { return n * 2; },function() { return true; - },Elixir.Kernel.SpecialForms.list()) + },Elixir.Core.List()) """ assert_translation(ex_ast, js_code) @@ -24,11 +24,11 @@ defmodule ElixirScript.Translator.For.Test do end js_code = """ - Elixir.Kernel.SpecialForms._for(Elixir.Kernel.SpecialForms.list(Elixir.Kernel.SpecialForms.list(Elixir.Core.Patterns.variable(),Elixir.Kernel.SpecialForms.list(1,2,3,4))),function(n) { + Elixir.Kernel.SpecialForms._for(Elixir.Core.List(Elixir.Core.List(Elixir.Core.Patterns.variable(),Elixir.Core.List(1,2,3,4))),function(n) { return n * 2; },function() { return true; - },Elixir.Kernel.SpecialForms.list()) + },Elixir.Core.List()) """ assert_translation(ex_ast, js_code) @@ -40,11 +40,11 @@ defmodule ElixirScript.Translator.For.Test do end js_code = """ - Elixir.Kernel.SpecialForms._for(Elixir.Kernel.SpecialForms.list(Elixir.Kernel.SpecialForms.list(Elixir.Core.Patterns.variable(),'Opera')),function(n) { + Elixir.Kernel.SpecialForms._for(Elixir.Core.List(Elixir.Core.List(Elixir.Core.Patterns.variable(),'Opera')),function(n) { return n; },function() { return true; - },Elixir.Kernel.SpecialForms.list()) + },Elixir.Core.List()) """ assert_translation(ex_ast, js_code) @@ -56,13 +56,13 @@ defmodule ElixirScript.Translator.For.Test do end js_code = """ - Elixir.Kernel.SpecialForms._for(Elixir.Kernel.SpecialForms.list( - Elixir.Kernel.SpecialForms.list(Elixir.Core.Patterns.variable(), Elixir.Kernel.SpecialForms.list(1,2)), - Elixir.Kernel.SpecialForms.list(Elixir.Core.Patterns.variable(), Elixir.Kernel.SpecialForms.list(2,3))), function(x,y) { + Elixir.Kernel.SpecialForms._for(Elixir.Core.List( + Elixir.Core.List(Elixir.Core.Patterns.variable(), Elixir.Core.List(1,2)), + Elixir.Core.List(Elixir.Core.Patterns.variable(), Elixir.Core.List(2,3))), function(x,y) { return x * y; },function() { return true; - },Elixir.Kernel.SpecialForms.list()) + },Elixir.Core.List()) """ assert_translation(ex_ast, js_code) @@ -76,11 +76,11 @@ defmodule ElixirScript.Translator.For.Test do end js_code = """ - let [r] = Elixir.Core.Patterns.match(Elixir.Core.Patterns.variable(),Elixir.Kernel.SpecialForms._for(Elixir.Kernel.SpecialForms.list(Elixir.Kernel.SpecialForms.list(Elixir.Core.Patterns.variable(),Elixir.Kernel.SpecialForms.list(1,2)),Elixir.Kernel.SpecialForms.list(Elixir.Core.Patterns.variable(),Elixir.Kernel.SpecialForms.list(2,3))),function(x,y) { + let [r] = Elixir.Core.Patterns.match(Elixir.Core.Patterns.variable(),Elixir.Kernel.SpecialForms._for(Elixir.Core.List(Elixir.Core.List(Elixir.Core.Patterns.variable(),Elixir.Core.List(1,2)),Elixir.Core.List(Elixir.Core.Patterns.variable(),Elixir.Core.List(2,3))),function(x,y) { return x * y; },function() { return true; - },Elixir.Kernel.SpecialForms.list())); + },Elixir.Core.List())); """ assert_translation(ex_ast, js_code) @@ -92,11 +92,11 @@ defmodule ElixirScript.Translator.For.Test do end js_code = """ - Elixir.Kernel.SpecialForms._for(Elixir.Kernel.SpecialForms.list(Elixir.Kernel.SpecialForms.list(Elixir.Core.Patterns.variable(),Elixir.Kernel.SpecialForms.list(1,2,3,4,5,6))),function(n) { + Elixir.Kernel.SpecialForms._for(Elixir.Core.List(Elixir.Core.List(Elixir.Core.Patterns.variable(),Elixir.Core.List(1,2,3,4,5,6))),function(n) { return n; },function(n) { return n % 2 == 0; - },Elixir.Kernel.SpecialForms.list()) + },Elixir.Core.List()) """ assert_translation(ex_ast, js_code) @@ -110,13 +110,13 @@ defmodule ElixirScript.Translator.For.Test do end js_code = """ - Elixir.Kernel.SpecialForms._for(Elixir.Kernel.SpecialForms.list(Elixir.Kernel.SpecialForms.list(Elixir.Core.Patterns.type(Elixir.Core.Tuple,{ - values: [Elixir.Kernel.SpecialForms.atom('user'), Elixir.Core.Patterns.variable()] - }),Elixir.Kernel.SpecialForms.list(Elixir.Kernel.SpecialForms.tuple(Elixir.Kernel.SpecialForms.atom('user'),'john'),Elixir.Kernel.SpecialForms.tuple(Elixir.Kernel.SpecialForms.atom('admin'),'john'),Elixir.Kernel.SpecialForms.tuple(Elixir.Kernel.SpecialForms.atom('user'),'meg')))),function(name) { - return Elixir.String.upcase(name); + Elixir.Kernel.SpecialForms._for(Elixir.Core.List(Elixir.Core.List(Elixir.Core.Patterns.type(Elixir.Core.Tuple,{ + values: [Symbol.for('user'), Elixir.Core.Patterns.variable()] + }),Elixir.Core.List(Elixir.Core.Functions.new_tuple(Symbol.for('user'),'john'),Elixir.Core.Functions.new_tuple(Symbol.for('admin'),'john'),Elixir.Core.Functions.new_tuple(Symbol.for('user'),'meg')))),function(name) { + return Elixir$ElixirScript$String.upcase(name); },function() { return true; - },Elixir.Kernel.SpecialForms.list()) + },Elixir.Core.List()) """ assert_translation(ex_ast, js_code) diff --git a/test/translator/function_test.exs b/test/translator/function_test.exs index c1e7b713..8b167ade 100644 --- a/test/translator/function_test.exs +++ b/test/translator/function_test.exs @@ -8,7 +8,7 @@ defmodule ElixirScript.Translator.Function.Test do end js_code = """ - fun(Elixir.Kernel.SpecialForms.atom('atom')) + fun(Symbol.for('atom')) """ assert_translation(ex_ast, js_code) @@ -89,7 +89,7 @@ defmodule ElixirScript.Translator.Function.Test do return Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable()],function(x) { return 2; },function(x) { - return Elixir.Enum.member__qmark__(Elixir.Kernel.SpecialForms.list(false,null), x); + return Elixir.Enum.member__qmark__(Elixir.Core.List(false,null), x); }),Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.wildcard()],function() { return 1; })).call(this,1 == 1); @@ -117,13 +117,13 @@ defmodule ElixirScript.Translator.Function.Test do return Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable()],function(x) { return 2; },function(x) { - return Elixir.Enum.member__qmark__(Elixir.Kernel.SpecialForms.list(false,null),x); + return Elixir.Enum.member__qmark__(Elixir.Core.List(false,null),x); }),Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.wildcard()],function() { return Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable()],function(x) { let [a] = Elixir.Core.Patterns.match(Elixir.Core.Patterns.variable(), 1); return a; },function(x) { - return Elixir.Enum.member__qmark__(Elixir.Kernel.SpecialForms.list(false,null),x); + return Elixir.Enum.member__qmark__(Elixir.Core.List(false,null),x); }),Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.wildcard()],function() { return 4; })).call(this,2 == 2); @@ -143,8 +143,8 @@ defmodule ElixirScript.Translator.Function.Test do const test1 = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable(), Elixir.Core.Patterns.variable()], function(alpha, beta) { let [a, b] = Elixir.Core.Patterns.match(Elixir.Core.Patterns.type(Elixir.Core.Tuple, { values: [Elixir.Core.Patterns.variable(), Elixir.Core.Patterns.variable()] - }), Elixir.Kernel.SpecialForms.tuple(1, 2)); - let _ref = Elixir.Kernel.SpecialForms.tuple(a, b); + }), Elixir.Core.Functions.new_tuple(1, 2)); + let _ref = Elixir.Core.Functions.new_tuple(a, b); return _ref; })); """ @@ -181,7 +181,7 @@ defmodule ElixirScript.Translator.Function.Test do Taco.test1() end - js_code = "Elixir.Core.call_property(Taco, 'test1')" + js_code = "Elixir.Core.Functions.call_property(Taco, 'test1')" assert_translation(ex_ast, js_code) @@ -239,7 +239,7 @@ defmodule ElixirScript.Translator.Function.Test do end js_code = """ - import * as Elixir$ElixirScript$Kernel from 'Elixir.ElixirScript.Kernel'; + import * as Elixir$ElixirScript$Kernel from './Elixir.ElixirScript.Kernel'; const example = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([],function() { return null; }),Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable()],function(oneArg) { @@ -276,7 +276,7 @@ defmodule ElixirScript.Translator.Function.Test do end js_code = """ - import * as Elixir$ElixirScript$Kernel from 'Elixir.ElixirScript.Kernel'; + import * as Elixir$ElixirScript$Kernel from './Elixir.ElixirScript.Kernel'; const example = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([],function() { return null; }),Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable()],function(oneArg) { @@ -303,7 +303,7 @@ defmodule ElixirScript.Translator.Function.Test do end js_code = """ - import * as Elixir$ElixirScript$Kernel from 'Elixir.ElixirScript.Kernel'; + import * as Elixir$ElixirScript$Kernel from './Elixir.ElixirScript.Kernel'; const example = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable()],function(oneArg) { return null; })); @@ -339,7 +339,7 @@ defmodule ElixirScript.Translator.Function.Test do is_atom(:atom) end - js_code = "Elixir$ElixirScript$Kernel.is_atom(Elixir.Kernel.SpecialForms.atom('atom'))" + js_code = "Elixir$ElixirScript$Kernel.is_atom(Symbol.for('atom'))" assert_translation(ex_ast, js_code) end @@ -404,7 +404,7 @@ defmodule ElixirScript.Translator.Function.Test do const something = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable(), Elixir.Core.Patterns.variable()],function(one,two) { return null; },function(one,two) { - return Elixir.Core.contains(one,Elixir.Kernel.SpecialForms.list(1,2,3)); + return Elixir.Core.Functions.contains(one,Elixir.Core.List(1,2,3)); })); """ @@ -421,11 +421,11 @@ defmodule ElixirScript.Translator.Function.Test do end js_code = """ - import * as Elixir$ElixirScript$Kernel from 'Elixir.ElixirScript.Kernel'; + import * as Elixir$ElixirScript$Kernel from './Elixir.ElixirScript.Kernel'; const something = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable()],function(one) { return null; },function(one) { - return Elixir.Core.contains(one,Elixir.Kernel.SpecialForms.list(1,2,3)); + return Elixir.Core.Functions.contains(one,Elixir.Core.List(1,2,3)); }),Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable()],function(one) { return null; },function(one) { @@ -479,7 +479,7 @@ defmodule ElixirScript.Translator.Function.Test do js_code = """ - const something = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Kernel.SpecialForms.list(Elixir.Core.Patterns.variable(),Elixir.Core.Patterns.variable(),Elixir.Core.Patterns.variable())],function(apple,pear,banana) { + const something = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Core.List(Elixir.Core.Patterns.variable(),Elixir.Core.Patterns.variable(),Elixir.Core.Patterns.variable())],function(apple,pear,banana) { return null; })); """ @@ -543,7 +543,7 @@ defmodule ElixirScript.Translator.Function.Test do js_code = """ const something = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.capture({ - [Elixir.Kernel.SpecialForms.atom('which')]: 13 + [Symbol.for('which')]: 13 })],function(a) { return null; })); @@ -561,7 +561,7 @@ defmodule ElixirScript.Translator.Function.Test do js_code = """ const something = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.type(AStruct, { - [Elixir.Kernel.SpecialForms.atom('key')]: Elixir.Core.Patterns.variable(), [Elixir.Kernel.SpecialForms.atom('key1')]: 2 + [Symbol.for('key')]: Elixir.Core.Patterns.variable(), [Symbol.for('key1')]: 2 })], function(value) { return null; })); @@ -577,7 +577,7 @@ defmodule ElixirScript.Translator.Function.Test do js_code = """ const something = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.type(AStruct, { - [Elixir.Kernel.SpecialForms.atom('key')]: Elixir.Core.Patterns.variable(), [Elixir.Kernel.SpecialForms.atom('key1')]: 2 + [Symbol.for('key')]: Elixir.Core.Patterns.variable(), [Symbol.for('key1')]: 2 })], function(value) { return null; }, function(value) { @@ -652,7 +652,7 @@ defmodule ElixirScript.Translator.Function.Test do js_code = """ - import * as Elixir$ElixirScript$Kernel from 'Elixir.ElixirScript.Kernel'; + import * as Elixir$ElixirScript$Kernel from './Elixir.ElixirScript.Kernel'; const something = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([1],function() { return null; }),Elixir.Core.Patterns.make_case([2],function() { @@ -720,8 +720,8 @@ defmodule ElixirScript.Translator.Function.Test do js_code = """ const test1 = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable(), Elixir.Core.Patterns.variable()],function(alpha,beta) { let [a] = Elixir.Core.Patterns.match(Elixir.Core.Patterns.variable(),1); - let [a1,b,c] = Elixir.Core.Patterns.match(Elixir.Kernel.SpecialForms.list(Elixir.Core.Patterns.variable(),Elixir.Core.Patterns.variable(),Elixir.Core.Patterns.variable()),Elixir.Kernel.SpecialForms.list(a,2,3)); - let _ref = Elixir.Kernel.SpecialForms.list(a1,b,c); + let [a1,b,c] = Elixir.Core.Patterns.match(Elixir.Core.List(Elixir.Core.Patterns.variable(),Elixir.Core.Patterns.variable(),Elixir.Core.Patterns.variable()),Elixir.Core.List(a,2,3)); + let _ref = Elixir.Core.List(a1,b,c); return _ref; })); """ diff --git a/test/translator/kernel_test.exs b/test/translator/kernel_test.exs index 1113504f..b647d0d4 100644 --- a/test/translator/kernel_test.exs +++ b/test/translator/kernel_test.exs @@ -21,7 +21,7 @@ defmodule ElixirScript.Translator.Kernel.Test do end js_code = """ - Elixir$ElixirScript$Kernel.apply(fun, Elixir.Kernel.SpecialForms.list(1,2,3)) + Elixir$ElixirScript$Kernel.apply(fun, Elixir.Core.List(1,2,3)) """ assert_translation(ex_ast, js_code) @@ -34,7 +34,7 @@ defmodule ElixirScript.Translator.Kernel.Test do end js_code = """ - Elixir$ElixirScript$Kernel.apply(Enum,Elixir.Kernel.SpecialForms.atom('reverse'),Elixir.Kernel.SpecialForms.list(1,2,3)) + Elixir$ElixirScript$Kernel.apply(Enum,Symbol.for('reverse'),Elixir.Core.List(1,2,3)) """ assert_translation(ex_ast, js_code) @@ -47,7 +47,7 @@ defmodule ElixirScript.Translator.Kernel.Test do end js_code = """ - Elixir$ElixirScript$Kernel.hd(Elixir.Kernel.SpecialForms.list(1,2,3)) + Elixir$ElixirScript$Kernel.hd(Elixir.Core.List(1,2,3)) """ assert_translation(ex_ast, js_code) @@ -60,7 +60,7 @@ defmodule ElixirScript.Translator.Kernel.Test do end js_code = """ - Elixir$ElixirScript$Kernel.tl(Elixir.Kernel.SpecialForms.list(1,2,3)) + Elixir$ElixirScript$Kernel.tl(Elixir.Core.List(1,2,3)) """ assert_translation(ex_ast, js_code) diff --git a/test/translator/list_test.exs b/test/translator/list_test.exs index 3bf0c7a3..24fc6e85 100644 --- a/test/translator/list_test.exs +++ b/test/translator/list_test.exs @@ -4,34 +4,34 @@ defmodule ElixirScript.Translator.List.Test do should "translate list" do ex_ast = quote do: [1, 2, 3] - js_code = "Elixir.Kernel.SpecialForms.list(1, 2, 3)" + js_code = "Elixir.Core.List(1, 2, 3)" assert_translation(ex_ast, js_code) ex_ast = quote do: ["a", "b", "c"] - js_code = "Elixir.Kernel.SpecialForms.list('a', 'b', 'c')" + js_code = "Elixir.Core.List('a', 'b', 'c')" assert_translation(ex_ast, js_code) ex_ast = quote do: [:a, :b, :c] - js_code = "Elixir.Kernel.SpecialForms.list(Elixir.Kernel.SpecialForms.atom('a'), Elixir.Kernel.SpecialForms.atom('b'), Elixir.Kernel.SpecialForms.atom('c'))" + js_code = "Elixir.Core.List(Symbol.for('a'), Symbol.for('b'), Symbol.for('c'))" assert_translation(ex_ast, js_code) ex_ast = quote do: [:a, 2, "c"] - js_code = "Elixir.Kernel.SpecialForms.list(Elixir.Kernel.SpecialForms.atom('a'), 2, 'c')" + js_code = "Elixir.Core.List(Symbol.for('a'), 2, 'c')" assert_translation(ex_ast, js_code) end should "concatenate lists" do ex_ast = quote do: [1, 2, 3] ++ [4, 5, 6] - js_code = "Elixir.Core.concat_lists(Elixir.Kernel.SpecialForms.list(1,2,3),Elixir.Kernel.SpecialForms.list(4,5,6))" + js_code = "Elixir.Core.Functions.concat_lists(Elixir.Core.List(1,2,3),Elixir.Core.List(4,5,6))" assert_translation(ex_ast, js_code) ex_ast = quote do: this.list ++ [4, 5, 6] - js_code = "Elixir.Core.concat_lists(Elixir.Core.call_property(this,'list'),Elixir.Kernel.SpecialForms.list(4,5,6))" + js_code = "Elixir.Core.Functions.concat_lists(Elixir.Core.Functions.call_property(this,'list'),Elixir.Core.List(4,5,6))" assert_translation(ex_ast, js_code) end diff --git a/test/translator/map_test.exs b/test/translator/map_test.exs index 00af9105..04291cf1 100644 --- a/test/translator/map_test.exs +++ b/test/translator/map_test.exs @@ -11,7 +11,7 @@ defmodule ElixirScript.Translator.Map.Test do should "translate map with elements" do ex_ast = quote do: %{one: "one", two: "two"} - js_code = "Elixir.Kernel.SpecialForms.map({[Elixir.Kernel.SpecialForms.atom('one')]: 'one', [Elixir.Kernel.SpecialForms.atom('two')]: 'two'})" + js_code = "Elixir.Kernel.SpecialForms.map({[Symbol.for('one')]: 'one', [Symbol.for('two')]: 'two'})" assert_translation(ex_ast, js_code) end @@ -20,9 +20,9 @@ defmodule ElixirScript.Translator.Map.Test do ex_ast = quote do: %{one: "one", two: %{three: "three"}} js_code = """ Elixir.Kernel.SpecialForms.map({ - [Elixir.Kernel.SpecialForms.atom('one')]: 'one', - [Elixir.Kernel.SpecialForms.atom('two')]: Elixir.Kernel.SpecialForms.map({ - [Elixir.Kernel.SpecialForms.atom('three')]: 'three' + [Symbol.for('one')]: 'one', + [Symbol.for('two')]: Elixir.Kernel.SpecialForms.map({ + [Symbol.for('three')]: 'three' }) }) """ @@ -46,7 +46,7 @@ defmodule ElixirScript.Translator.Map.Test do ex_ast = quote do: %{ map | value: 1 } js_code = """ Elixir.Kernel.SpecialForms.map_update(map,{ - [Elixir.Kernel.SpecialForms.atom('value')]: 1 + [Symbol.for('value')]: 1 }) """ diff --git a/test/translator/protocol_test.exs b/test/translator/protocol_test.exs index 52bf875f..70d51940 100644 --- a/test/translator/protocol_test.exs +++ b/test/translator/protocol_test.exs @@ -25,20 +25,20 @@ defmodule ElixirScript.Translator.Protocol.Test do end js_code = """ - import * as Elixir$ElixirScript$Kernel from 'Elixir.ElixirScript.Kernel'; - const Elixir$Blank = Elixir.Kernel.defprotocol({ + import * as Elixir$ElixirScript$Kernel from './Elixir.ElixirScript.Kernel'; + const Elixir$Blank = Elixir.Core.Functions.defprotocol({ blank__qmark__: Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable()],function(data) { return null; })) }); - Elixir.Kernel.defimpl(Elixir$Blank, Array,{ - blank__qmark__: Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Kernel.SpecialForms.list()],function() { + Elixir.Core.Functions.defimpl(Elixir$Blank, Array,{ + blank__qmark__: Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Core.List()],function() { return true; }),Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.wildcard()],function() { return false; })) }) - Elixir.Kernel.defimpl(Elixir$Blank,Symbol,{ + Elixir.Core.Functions.defimpl(Elixir$Blank,Symbol,{ blank__qmark__: Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([false],function() { return true; }),Elixir.Core.Patterns.make_case([null],function() { @@ -47,7 +47,7 @@ defmodule ElixirScript.Translator.Protocol.Test do return false; })) }) - Elixir.Kernel.defimpl(Elixir$Blank, Elixir.Core.Integer, { + Elixir.Core.Functions.defimpl(Elixir$Blank, Elixir.Core.Integer, { blank__qmark__: Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable()],function(number) { return false; })) diff --git a/test/translator/quote_test.exs b/test/translator/quote_test.exs index 916af085..4d150a63 100644 --- a/test/translator/quote_test.exs +++ b/test/translator/quote_test.exs @@ -17,7 +17,7 @@ defmodule ElixirScript.Translator.Quote.Test do quote do: :time end - js_code = "Elixir.Kernel.SpecialForms.atom('time')" + js_code = "Symbol.for('time')" assert_translation(ex_ast, js_code) end @@ -28,7 +28,7 @@ defmodule ElixirScript.Translator.Quote.Test do quote do: {1, 2} end - js_code = "Elixir.Kernel.SpecialForms.tuple(1, 2)" + js_code = "Elixir.Core.Functions.new_tuple(1, 2)" assert_translation(ex_ast, js_code) end @@ -39,7 +39,7 @@ defmodule ElixirScript.Translator.Quote.Test do quote do: {1, 2, 3} end - js_code = "Elixir.Kernel.SpecialForms.tuple(Elixir.Kernel.SpecialForms.atom('{}'), Elixir.Kernel.SpecialForms.list(), Elixir.Kernel.SpecialForms.list(1, 2, 3))" + js_code = "Elixir.Core.Functions.new_tuple(Symbol.for('{}'), Elixir.Core.List(), Elixir.Core.List(1, 2, 3))" assert_translation(ex_ast, js_code) end @@ -50,9 +50,9 @@ defmodule ElixirScript.Translator.Quote.Test do quote do: test(1) end - js_code = "Elixir.Kernel.SpecialForms.tuple(Elixir.Kernel.SpecialForms.atom('test'), - Elixir.Kernel.SpecialForms.list(Elixir.Kernel.SpecialForms.tuple(Elixir.Kernel.SpecialForms.atom('context'),Elixir.Kernel.SpecialForms.atom('Elixir.ElixirScript.Translator.Quote.Test')),Elixir.Kernel.SpecialForms.tuple(Elixir.Kernel.SpecialForms.atom('import'),Elixir.Kernel.SpecialForms.atom('Elixir.ExUnit.Case'))), - Elixir.Kernel.SpecialForms.list(1))" + js_code = "Elixir.Core.Functions.new_tuple(Symbol.for('test'), + Elixir.Core.List(Elixir.Core.Functions.new_tuple(Symbol.for('context'),Symbol.for('Elixir.ElixirScript.Translator.Quote.Test')),Elixir.Core.Functions.new_tuple(Symbol.for('import'),Symbol.for('Elixir.ExUnit.Case'))), + Elixir.Core.List(1))" assert_translation(ex_ast, js_code) end @@ -63,10 +63,10 @@ defmodule ElixirScript.Translator.Quote.Test do quote do: test(x) end - js_code = "Elixir.Kernel.SpecialForms.tuple( - Elixir.Kernel.SpecialForms.atom('test'), - Elixir.Kernel.SpecialForms.list(Elixir.Kernel.SpecialForms.tuple(Elixir.Kernel.SpecialForms.atom('context'),Elixir.Kernel.SpecialForms.atom('Elixir.ElixirScript.Translator.Quote.Test')),Elixir.Kernel.SpecialForms.tuple(Elixir.Kernel.SpecialForms.atom('import'),Elixir.Kernel.SpecialForms.atom('Elixir.ExUnit.Case'))), - Elixir.Kernel.SpecialForms.list(Elixir.Kernel.SpecialForms.tuple(Elixir.Kernel.SpecialForms.atom('x'),Elixir.Kernel.SpecialForms.list(),Elixir.Kernel.SpecialForms.atom('Elixir.ElixirScript.Translator.Quote.Test'))) + js_code = "Elixir.Core.Functions.new_tuple( + Symbol.for('test'), + Elixir.Core.List(Elixir.Core.Functions.new_tuple(Symbol.for('context'),Symbol.for('Elixir.ElixirScript.Translator.Quote.Test')),Elixir.Core.Functions.new_tuple(Symbol.for('import'),Symbol.for('Elixir.ExUnit.Case'))), + Elixir.Core.List(Elixir.Core.Functions.new_tuple(Symbol.for('x'),Elixir.Core.List(),Symbol.for('Elixir.ElixirScript.Translator.Quote.Test'))) )" assert_translation(ex_ast, js_code) @@ -78,10 +78,10 @@ defmodule ElixirScript.Translator.Quote.Test do quote do: test(unquote(x)) end - js_code = "Elixir.Kernel.SpecialForms.tuple( - Elixir.Kernel.SpecialForms.atom('test'), - Elixir.Kernel.SpecialForms.list(Elixir.Kernel.SpecialForms.tuple(Elixir.Kernel.SpecialForms.atom('context'),Elixir.Kernel.SpecialForms.atom('Elixir.ElixirScript.Translator.Quote.Test')),Elixir.Kernel.SpecialForms.tuple(Elixir.Kernel.SpecialForms.atom('import'),Elixir.Kernel.SpecialForms.atom('Elixir.ExUnit.Case'))), - Elixir.Kernel.SpecialForms.list(x) + js_code = "Elixir.Core.Functions.new_tuple( + Symbol.for('test'), + Elixir.Core.List(Elixir.Core.Functions.new_tuple(Symbol.for('context'),Symbol.for('Elixir.ElixirScript.Translator.Quote.Test')),Elixir.Core.Functions.new_tuple(Symbol.for('import'),Symbol.for('Elixir.ExUnit.Case'))), + Elixir.Core.List(x) )" assert_translation(ex_ast, js_code) @@ -93,7 +93,7 @@ defmodule ElixirScript.Translator.Quote.Test do quote do: sum(1, unquote_splicing(values), 5) end - js_code = "Elixir.Kernel.SpecialForms.tuple(Elixir.Kernel.SpecialForms.atom('sum'), Elixir.Kernel.SpecialForms.list(), Elixir.Enum.concat(Elixir.Kernel.SpecialForms.list(1), values, Elixir.Kernel.SpecialForms.list(5)))" + js_code = "Elixir.Core.Functions.new_tuple(Symbol.for('sum'), Elixir.Core.List(), Elixir.Enum.concat(Elixir.Core.List(1), values, Elixir.Core.List(5)))" assert_translation(ex_ast, js_code) end @@ -105,10 +105,10 @@ defmodule ElixirScript.Translator.Quote.Test do end end - js_code = "Elixir.Kernel.SpecialForms.tuple( - Elixir.Kernel.SpecialForms.atom('*'), - Elixir.Kernel.SpecialForms.list(Elixir.Kernel.SpecialForms.tuple(Elixir.Kernel.SpecialForms.atom('context'),Elixir.Kernel.SpecialForms.atom('Elixir.ElixirScript.Translator.Quote.Test')),Elixir.Kernel.SpecialForms.tuple(Elixir.Kernel.SpecialForms.atom('import'),Elixir.Kernel.SpecialForms.atom('Elixir.ElixirScript.Kernel'))), - Elixir.Kernel.SpecialForms.list(x, x) + js_code = "Elixir.Core.Functions.new_tuple( + Symbol.for('*'), + Elixir.Core.List(Elixir.Core.Functions.new_tuple(Symbol.for('context'),Symbol.for('Elixir.ElixirScript.Translator.Quote.Test')),Elixir.Core.Functions.new_tuple(Symbol.for('import'),Symbol.for('Elixir.ElixirScript.Kernel'))), + Elixir.Core.List(x, x) )" assert_translation(ex_ast, js_code) diff --git a/test/translator/string_test.exs b/test/translator/string_test.exs index 491b1d8a..a8ff8524 100644 --- a/test/translator/string_test.exs +++ b/test/translator/string_test.exs @@ -25,19 +25,19 @@ defmodule ElixirScript.Translator.String.Test do assert_translation(ex_ast, "'Hello ' + 'world'") ex_ast = quote do: "Hello #{length([])}" - assert_translation(ex_ast, "'Hello ' + Elixir$ElixirScript$String$Chars.to_string(Elixir$ElixirScript$Kernel.length(Elixir.Kernel.SpecialForms.list()))") + assert_translation(ex_ast, "'Hello ' + Elixir$ElixirScript$String$Chars.to_string(Elixir$ElixirScript$Kernel.length(Elixir.Core.List()))") end should "translate multiline string interpolation" do ex_ast = quote do: """ Hello #{length([])} """ - assert_translation(ex_ast, "'Hello ' + (Elixir$ElixirScript$String$Chars.to_string(Elixir$ElixirScript$Kernel.length(Elixir.Kernel.SpecialForms.list())) + '\\n')") + assert_translation(ex_ast, "'Hello ' + (Elixir$ElixirScript$String$Chars.to_string(Elixir$ElixirScript$Kernel.length(Elixir.Core.List())) + '\\n')") ex_ast = quote do: """ Hello #{length([])} How are you, #{length([])}? """ - assert_translation(ex_ast, "'Hello ' + (Elixir$ElixirScript$String$Chars.to_string(Elixir$ElixirScript$Kernel.length(Elixir.Kernel.SpecialForms.list())) + ('\\nHow are you, ' + (Elixir$ElixirScript$String$Chars.to_string(Elixir$ElixirScript$Kernel.length(Elixir.Kernel.SpecialForms.list())) + '?\\n')))") + assert_translation(ex_ast, "'Hello ' + (Elixir$ElixirScript$String$Chars.to_string(Elixir$ElixirScript$Kernel.length(Elixir.Core.List())) + ('\\nHow are you, ' + (Elixir$ElixirScript$String$Chars.to_string(Elixir$ElixirScript$Kernel.length(Elixir.Core.List())) + '?\\n')))") end end diff --git a/test/translator/struct_test.exs b/test/translator/struct_test.exs index e22ce6e9..c50025b0 100644 --- a/test/translator/struct_test.exs +++ b/test/translator/struct_test.exs @@ -10,11 +10,11 @@ defmodule ElixirScript.Translator.Struct.Test do end js_code = """ - import * as Elixir$ElixirScript$Kernel from 'Elixir.ElixirScript.Kernel'; - const Elixir$User = Elixir.Kernel.defstruct({ - [Elixir.Kernel.SpecialForms.atom('__struct__')]: Elixir.Kernel.SpecialForms.atom('Elixir.User'), - [Elixir.Kernel.SpecialForms.atom('name')]: 'john', - [Elixir.Kernel.SpecialForms.atom('age')]: 27 + import * as Elixir$ElixirScript$Kernel from './Elixir.ElixirScript.Kernel'; + const Elixir$User = Elixir.Core.Functions.defstruct({ + [Symbol.for('__struct__')]: Symbol.for('Elixir.User'), + [Symbol.for('name')]: 'john', + [Symbol.for('age')]: 27 }); export { @@ -34,11 +34,11 @@ defmodule ElixirScript.Translator.Struct.Test do end js_code = """ - import * as Elixir$ElixirScript$Kernel from 'Elixir.ElixirScript.Kernel'; - const Elixir$User = Elixir.Kernel.defstruct({ - [Elixir.Kernel.SpecialForms.atom('__struct__')]: Elixir.Kernel.SpecialForms.atom('Elixir.User'), - [Elixir.Kernel.SpecialForms.atom('name')]: null, - [Elixir.Kernel.SpecialForms.atom('age')]: null + import * as Elixir$ElixirScript$Kernel from './Elixir.ElixirScript.Kernel'; + const Elixir$User = Elixir.Core.Functions.defstruct({ + [Symbol.for('__struct__')]: Symbol.for('Elixir.User'), + [Symbol.for('name')]: null, + [Symbol.for('age')]: null }); export { Elixir$User @@ -61,11 +61,11 @@ defmodule ElixirScript.Translator.Struct.Test do js_code = """ let [user] = Elixir.Core.Patterns.match(Elixir.Core.Patterns.variable(), Elixir$User.Elixir$User.create(Elixir.Kernel.SpecialForms.map({}))); - import * as Elixir$ElixirScript$Kernel from 'Elixir.ElixirScript.Kernel'; - const Elixir$User = Elixir.Kernel.defstruct({ - [Elixir.Kernel.SpecialForms.atom('__struct__')]: Elixir.Kernel.SpecialForms.atom('Elixir.User'), - [Elixir.Kernel.SpecialForms.atom('name')]: null, - [Elixir.Kernel.SpecialForms.atom('age')]: null + import * as Elixir$ElixirScript$Kernel from './Elixir.ElixirScript.Kernel'; + const Elixir$User = Elixir.Core.Functions.defstruct({ + [Symbol.for('__struct__')]: Symbol.for('Elixir.User'), + [Symbol.for('name')]: null, + [Symbol.for('age')]: null }); export { @@ -85,14 +85,14 @@ defmodule ElixirScript.Translator.Struct.Test do js_code = """ let [user] = Elixir.Core.Patterns.match(Elixir.Core.Patterns.variable(),Elixir$User.Elixir$User.create(Elixir.Kernel.SpecialForms.map({ - [Elixir.Kernel.SpecialForms.atom('name')]: 'John' + [Symbol.for('name')]: 'John' }))); - import * as Elixir$ElixirScript$Kernel from 'Elixir.ElixirScript.Kernel'; - const Elixir$User = Elixir.Kernel.defstruct({ - [Elixir.Kernel.SpecialForms.atom('__struct__')]: Elixir.Kernel.SpecialForms.atom('Elixir.User'), - [Elixir.Kernel.SpecialForms.atom('name')]: null, - [Elixir.Kernel.SpecialForms.atom('age')]: null + import * as Elixir$ElixirScript$Kernel from './Elixir.ElixirScript.Kernel'; + const Elixir$User = Elixir.Core.Functions.defstruct({ + [Symbol.for('__struct__')]: Symbol.for('Elixir.User'), + [Symbol.for('name')]: null, + [Symbol.for('age')]: null }); export { Elixir$User @@ -109,7 +109,7 @@ defmodule ElixirScript.Translator.Struct.Test do js_code = """ let [user] = Elixir.Core.Patterns.match(Elixir.Core.Patterns.variable(),Elixir.Kernel.SpecialForms.map_update(map,{ - [Elixir.Kernel.SpecialForms.atom('key')]: value + [Symbol.for('key')]: value })); """ @@ -122,7 +122,7 @@ defmodule ElixirScript.Translator.Struct.Test do js_code = """ let [user] = Elixir.Core.Patterns.match(Elixir.Core.Patterns.variable(),Elixir.Kernel.SpecialForms.map_update(map,{ - [Elixir.Kernel.SpecialForms.atom('key')]: value, [Elixir.Kernel.SpecialForms.atom('key1')]: value1 + [Symbol.for('key')]: value, [Symbol.for('key1')]: value1 })); """ @@ -137,11 +137,11 @@ defmodule ElixirScript.Translator.Struct.Test do end js_code = """ - import * as Elixir$ElixirScript$Kernel from 'Elixir.ElixirScript.Kernel'; - const Elixir$MyAppError = Elixir.Kernel.defexception({ - [Elixir.Kernel.SpecialForms.atom('__struct__')]: Elixir.Kernel.SpecialForms.atom('Elixir.MyAppError'), - [Elixir.Kernel.SpecialForms.atom('__exception__')]: true, - [Elixir.Kernel.SpecialForms.atom('message')]: 'This is a message' + import * as Elixir$ElixirScript$Kernel from './Elixir.ElixirScript.Kernel'; + const Elixir$MyAppError = Elixir.Core.Functions.defexception({ + [Symbol.for('__struct__')]: Symbol.for('Elixir.MyAppError'), + [Symbol.for('__exception__')]: true, + [Symbol.for('message')]: 'This is a message' }); export { Elixir$MyAppError @@ -157,11 +157,11 @@ defmodule ElixirScript.Translator.Struct.Test do end js_code = """ - import * as Elixir$ElixirScript$Kernel from 'Elixir.ElixirScript.Kernel'; - const Elixir$MyAppError = Elixir.Kernel.defexception({ - [Elixir.Kernel.SpecialForms.atom('__struct__')]: Elixir.Kernel.SpecialForms.atom('Elixir.MyAppError'), - [Elixir.Kernel.SpecialForms.atom('__exception__')]: true, - [Elixir.Kernel.SpecialForms.atom('message')]: null + import * as Elixir$ElixirScript$Kernel from './Elixir.ElixirScript.Kernel'; + const Elixir$MyAppError = Elixir.Core.Functions.defexception({ + [Symbol.for('__struct__')]: Symbol.for('Elixir.MyAppError'), + [Symbol.for('__exception__')]: true, + [Symbol.for('message')]: null }); export { @@ -184,14 +184,14 @@ defmodule ElixirScript.Translator.Struct.Test do js_code = """ throw Elixir$MyAppError.Elixir$MyAppError.create(Elixir.Kernel.SpecialForms.map({ - [Elixir.Kernel.SpecialForms.atom('message')]: 'did not get what was expected' + [Symbol.for('message')]: 'did not get what was expected' })); -import * as Elixir$ElixirScript$Kernel from 'Elixir.ElixirScript.Kernel'; - const Elixir$MyAppError = Elixir.Kernel.defexception({ - [Elixir.Kernel.SpecialForms.atom('__struct__')]: Elixir.Kernel.SpecialForms.atom('Elixir.MyAppError'), - [Elixir.Kernel.SpecialForms.atom('__exception__')]: true, - [Elixir.Kernel.SpecialForms.atom('message')]: null +import * as Elixir$ElixirScript$Kernel from './Elixir.ElixirScript.Kernel'; + const Elixir$MyAppError = Elixir.Core.Functions.defexception({ + [Symbol.for('__struct__')]: Symbol.for('Elixir.MyAppError'), + [Symbol.for('__exception__')]: true, + [Symbol.for('message')]: null }); export { @@ -208,9 +208,9 @@ import * as Elixir$ElixirScript$Kernel from 'Elixir.ElixirScript.Kernel'; js_code = """ throw { - [Elixir.Kernel.SpecialForms.atom('__struct__')]: Elixir.Kernel.SpecialForms.atom('RuntimeError'), - [Elixir.Kernel.SpecialForms.atom('__exception__')]: true, - [Elixir.Kernel.SpecialForms.atom('message')]: 'did not get what was expected' + [Symbol.for('__struct__')]: Symbol.for('RuntimeError'), + [Symbol.for('__exception__')]: true, + [Symbol.for('message')]: 'did not get what was expected' }; """ diff --git a/test/translator/try_test.exs b/test/translator/try_test.exs index edbe2733..75963481 100644 --- a/test/translator/try_test.exs +++ b/test/translator/try_test.exs @@ -60,7 +60,7 @@ defmodule ElixirScript.Translator.Try.Test do }, Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable()], function(x) { return IO.puts('Invalid argument given'); }, function(x) { - return Elixir.Core.contains(x,Elixir.Kernel.SpecialForms.list(ArgumentError.create(Elixir.Kernel.SpecialForms.map({})))); + return Elixir.Core.Functions.contains(x,Elixir.Core.List(ArgumentError.create(Elixir.Kernel.SpecialForms.map({})))); })), null, null, null) """ @@ -175,11 +175,11 @@ defmodule ElixirScript.Translator.Try.Test do Elixir.Kernel.SpecialForms._try(function() { return 1 / x; },null,null,Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable()],function(y) { - return Elixir.Kernel.SpecialForms.atom('small'); + return Symbol.for('small'); },function(y) { return (y < 1) && (y > -1); }),Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.wildcard()],function() { - return Elixir.Kernel.SpecialForms.atom('large'); + return Symbol.for('large'); })),null) """ @@ -204,7 +204,7 @@ defmodule ElixirScript.Translator.Try.Test do return do_something_that_may_fail(some_arg); }, Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.type(ArgumentError, {})], function() { return IO.puts('Invalid argument given'); - })), Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Kernel.SpecialForms.atom('throw'), Elixir.Kernel.SpecialForms.atom('Error')], function() { + })), Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Symbol.for('throw'), Symbol.for('Error')], function() { return IO.puts('caught error'); })), null, null) """ diff --git a/test/translator/tuple_test.exs b/test/translator/tuple_test.exs index cff51110..3738a81e 100644 --- a/test/translator/tuple_test.exs +++ b/test/translator/tuple_test.exs @@ -4,31 +4,31 @@ defmodule ElixirScript.Translator.Tuple.Test do should "translate 2 item tuple" do ex_ast = quote do: {1, 2} - js_code = "Elixir.Kernel.SpecialForms.tuple(1, 2)" + js_code = "Elixir.Core.Functions.new_tuple(1, 2)" assert_translation(ex_ast, js_code) end should "translate multiple item tuple" do ex_ast = quote do: {1, 2, 3, 4, 5} - js_code = "Elixir.Kernel.SpecialForms.tuple(1, 2, 3, 4, 5)" + js_code = "Elixir.Core.Functions.new_tuple(1, 2, 3, 4, 5)" assert_translation(ex_ast, js_code) end should "translate tuples of different typed items" do ex_ast = quote do: {"a", "b", "c"} - js_code = "Elixir.Kernel.SpecialForms.tuple('a', 'b', 'c')" + js_code = "Elixir.Core.Functions.new_tuple('a', 'b', 'c')" assert_translation(ex_ast, js_code) ex_ast = quote do: {:a, :b, :c} - js_code = "Elixir.Kernel.SpecialForms.tuple(Elixir.Kernel.SpecialForms.atom('a'), Elixir.Kernel.SpecialForms.atom('b'), Elixir.Kernel.SpecialForms.atom('c'))" + js_code = "Elixir.Core.Functions.new_tuple(Symbol.for('a'), Symbol.for('b'), Symbol.for('c'))" assert_translation(ex_ast, js_code) ex_ast = quote do: {:a, 2, "c"} - js_code = "Elixir.Kernel.SpecialForms.tuple(Elixir.Kernel.SpecialForms.atom('a'), 2, 'c')" + js_code = "Elixir.Core.Functions.new_tuple(Symbol.for('a'), 2, 'c')" assert_translation(ex_ast, js_code) end From 209ff888197eff8207fd027e46326218d48fb65e Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Mon, 28 Dec 2015 08:58:13 -0600 Subject: [PATCH 094/860] Updated get_global implementation. removed Set javascript test --- src/javascript/lib/core/functions.js | 4 +- src/javascript/tests/set.spec.js | 106 --------------------------- 2 files changed, 3 insertions(+), 107 deletions(-) delete mode 100644 src/javascript/tests/set.spec.js diff --git a/src/javascript/lib/core/functions.js b/src/javascript/lib/core/functions.js index 8289a3a7..0ba2725d 100644 --- a/src/javascript/lib/core/functions.js +++ b/src/javascript/lib/core/functions.js @@ -188,11 +188,13 @@ function reverse(list){ function get_global(){ if(typeof(self) !== "undefined"){ return self; + }else if(typeof(window) !== "undefined"){ + return window; }else if(typeof(global) !== "undefined"){ return global; } - throw "No global state found"; + throw new Error("No global state found"); } function concat_lists(left, right){ diff --git a/src/javascript/tests/set.spec.js b/src/javascript/tests/set.spec.js deleted file mode 100644 index b1964b75..00000000 --- a/src/javascript/tests/set.spec.js +++ /dev/null @@ -1,106 +0,0 @@ -var Set = require('../lib/set'); -var MapSet = require('../lib/map_set'); -var Kernel = require('../lib/kernel'); -var expect = require('chai').expect; - -describe('Set', function(){ - - it('new', function(){ - let set = MapSet.new(); - - expect(Set.size(set)).to.equal(0); - }); - - it('put', function(){ - let set = MapSet.new(); - - expect(Set.size(set)).to.equal(0); - - set = Set.put(set, "hello"); - expect(Set.size(set)).to.equal(1); - - set = Set.put(set, "hello"); - expect(Set.size(set)).to.equal(1); - }); - - it('to_list', function(){ - let set = MapSet.new(); - - set = Set.put(set, "hello"); - expect(Set.to_list(set)).to.deep.equal(["hello"]); - }); - - it('delete', function(){ - let set = MapSet.new(); - - set = Set.put(set, "hello"); - expect(Set.size(set)).to.equal(1); - - set = Set.delete(set, "hello") - expect(Set.size(set)).to.equal(0); - }); - - - it('difference', function(){ - let set1 = MapSet.new(); - let set2 = MapSet.new(); - - set1 = Set.put(set1, "hello"); - set1 = Set.put(set1, "world"); - - set2 = Set.put(set2, "goodbye"); - set2 = Set.put(set2, "world"); - - let set3 = Set.difference(set1, set2); - - expect(Set.to_list(set3)).to.deep.equal(["hello"]); - }); - - - it('intersection', function(){ - let set1 = MapSet.new(); - let set2 = MapSet.new(); - - set1 = Set.put(set1, "hello"); - set1 = Set.put(set1, "world"); - - set2 = Set.put(set2, "goodbye"); - set2 = Set.put(set2, "world"); - - let set3 = Set.intersection(set1, set2); - - expect(Set.to_list(set3)).to.deep.equal(["world"]); - }); - - - it('union', function(){ - let set1 = MapSet.new(); - let set2 = MapSet.new(); - - set1 = Set.put(set1, "hello"); - set1 = Set.put(set1, "world"); - - set2 = Set.put(set2, "goodbye"); - set2 = Set.put(set2, "world"); - - let set3 = Set.union(set1, set2); - - expect(Set.to_list(set3)).to.deep.equal(["hello", "world", "goodbye"]); - }); - - - it('subset?', function(){ - let set1 = MapSet.new(); - let set2 = MapSet.new(); - - set1 = Set.put(set1, "world"); - - set2 = Set.put(set2, "goodbye"); - set2 = Set.put(set2, "world"); - - expect(Set.subset__qmark__(set1, set2)).to.equal(true); - expect(Set.subset__qmark__(set2, set1)).to.equal(false); - }); - -}) - From 4b377e51e02447c9bc40e7248efc5e0e2581148b Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Mon, 28 Dec 2015 10:01:27 -0600 Subject: [PATCH 095/860] Update CONTRIBUTING.md --- CONTRIBUTING.md | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 1b3e61ce..d0f742d4 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -61,17 +61,22 @@ Contributions to ElixirScript are welcomed! These contributions can be in the form or code changes, documentation, or ideas of how to implement features found in Elixir in ElixirScript. -ElixirScript is broken up into 2 parts: +ElixirScript is broken up into the following parts: * The compiler, written in Elixir -* The runtime, written in JavaScript +* The standard library modules, mostly written in Elixir +* The javascript core The ElixirScript compiler is in the `lib` folder of the project. Here is where Elixir code is converted into JavaScript. -The JavaScript code is in the `priv/javascript`. +The standard library modules are in the `lib/elixir_script/prelude` folder. + +The JavaScript code is in the `src/javascript`. This is where features such as pattern matching and the standard library are implemented. +Please look at [this issue](https://github.com/bryanjos/elixirscript/issues/143) for information on how to add modules to the standard library. + The ElixirScript tests can be run using `mix test` The JavaScript tests can be run using `gulp test` @@ -176,4 +181,4 @@ in order to craft an excellent pull request: git rebase master ``` -Thank you for your contributions! \ No newline at end of file +Thank you for your contributions! From d53a4b54d263d986c65d442e9f82bf946b5f4d4d Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Mon, 28 Dec 2015 16:06:51 -0600 Subject: [PATCH 096/860] Updated map ast to take into considerations hyphens in property keys --- lib/elixir_script/translator/map.ex | 9 ++++++++- priv/Elixir.js | 6 ++++-- 2 files changed, 12 insertions(+), 3 deletions(-) diff --git a/lib/elixir_script/translator/map.ex b/lib/elixir_script/translator/map.ex index 3abb5c10..1ec8d4e9 100644 --- a/lib/elixir_script/translator/map.ex +++ b/lib/elixir_script/translator/map.ex @@ -37,7 +37,14 @@ defmodule ElixirScript.Translator.Map do end def make_property(%ESTree.Literal{value: k}, value) when is_binary(k) do - JS.property(JS.identifier(k), value) + key = case String.contains?(k, "-") do + true -> + JS.literal(k) + false -> + JS.identifier(k) + end + + JS.property(key, value) end def make_property(key, value) do diff --git a/priv/Elixir.js b/priv/Elixir.js index 77b15e0a..82c2961a 100644 --- a/priv/Elixir.js +++ b/priv/Elixir.js @@ -1160,11 +1160,13 @@ function reverse(list) { function get_global() { if (typeof self !== 'undefined') { return self; + } else if (typeof window !== 'undefined') { + return window; } else if (typeof global !== 'undefined') { return global; } - throw 'No global state found'; + throw new Error('No global state found'); } function concat_lists(left, right) { @@ -4123,4 +4125,4 @@ let VirtualDOM = (function (e) { const Core = C; export { Core, Kernel, Enum, List, Keyword, bitwise as Bitwise, map as Map, map_set as MapSet, VirtualDOM }; -//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiIiwic291cmNlcyI6WyJFbGl4aXIuanMiXSwic291cmNlc0NvbnRlbnQiOlsiLyogQGZsb3cgKi9cblxuY2xhc3MgTWFpbGJveCB7XG5cbiAgY29uc3RydWN0b3IoKSB7XG4gICAgdGhpcy5tZXNzYWdlcyA9IFtdO1xuICB9XG5cbiAgZGVsaXZlcihtZXNzYWdlKSB7XG4gICAgdGhpcy5tZXNzYWdlcy5wdXNoKG1lc3NhZ2UpO1xuICAgIHJldHVybiBtZXNzYWdlO1xuICB9XG5cbiAgZ2V0KCkge1xuICAgIHJldHVybiB0aGlzLm1lc3NhZ2VzO1xuICB9XG5cbiAgaXNFbXB0eSgpIHtcbiAgICByZXR1cm4gdGhpcy5tZXNzYWdlcy5sZW5ndGggPT09IDA7XG4gIH1cblxuICByZW1vdmVBdChpbmRleCkge1xuICAgIHRoaXMubWVzc2FnZXMuc3BsaWNlKGluZGV4LCAxKTtcbiAgfVxufVxuXG52YXIgU3RhdGVzID0ge1xuICBOT1JNQUw6IFN5bWJvbC5mb3IoXCJub3JtYWxcIiksXG4gIEtJTEw6IFN5bWJvbC5mb3IoXCJraWxsXCIpLFxuICBTVVNQRU5EOiBTeW1ib2wuZm9yKFwic3VzcGVuZFwiKSxcbiAgQ09OVElOVUU6IFN5bWJvbC5mb3IoXCJjb250aW51ZVwiKSxcbiAgUkVDRUlWRTogU3ltYm9sLmZvcihcInJlY2VpdmVcIiksXG4gIFNFTkQ6IFN5bWJvbC5mb3IoXCJzZW5kXCIpLFxuICBTTEVFUElORzogU3ltYm9sLmZvcihcInNsZWVwaW5nXCIpLFxuICBSVU5OSU5HOiBTeW1ib2wuZm9yKFwicnVubmluZ1wiKSxcbiAgU1VTUEVOREVEOiBTeW1ib2wuZm9yKFwic3VzcGVuZGVkXCIpLFxuICBTVE9QUEVEOiBTeW1ib2wuZm9yKFwic3RvcHBlZFwiKSxcbiAgU0xFRVA6IFN5bWJvbC5mb3IoXCJzbGVlcFwiKSxcbiAgRVhJVDogU3ltYm9sLmZvcihcImV4aXRcIiksXG4gIE5PTUFUQ0g6IFN5bWJvbC5mb3IoXCJub19tYXRjaFwiKVxufTtcblxuY2xhc3MgUHJvY2VzcyB7XG5cbiAgY29uc3RydWN0b3IocGlkLCBtYWlsYm94KSB7XG4gICAgdGhpcy5waWQgPSBwaWQ7XG4gICAgdGhpcy5tYWlsYm94ID0gbWFpbGJveDtcbiAgICB0aGlzLnN0YXR1cyA9IFN0YXRlcy5TVE9QUEVEO1xuICAgIHRoaXMuZGljdCA9IHt9O1xuICB9XG59XG5cbmNsYXNzIFR1cGxlIHtcblxuICBjb25zdHJ1Y3RvciguLi5hcmdzKSB7XG4gICAgdGhpcy52YWx1ZXMgPSBPYmplY3QuZnJlZXplKGFyZ3MpO1xuICAgIHRoaXMubGVuZ3RoID0gdGhpcy52YWx1ZXMubGVuZ3RoO1xuICB9XG5cbiAgZ2V0KGluZGV4KSB7XG4gICAgcmV0dXJuIHRoaXMudmFsdWVzW2luZGV4XTtcbiAgfVxuXG4gIGNvdW50KCkge1xuICAgIHJldHVybiB0aGlzLnZhbHVlcy5sZW5ndGg7XG4gIH1cblxuICBbU3ltYm9sLml0ZXJhdG9yXSgpIHtcbiAgICByZXR1cm4gdGhpcy52YWx1ZXNbU3ltYm9sLml0ZXJhdG9yXSgpO1xuICB9XG5cbiAgdG9TdHJpbmcoKSB7XG4gICAgdmFyIGksXG4gICAgICAgIHMgPSBcIlwiO1xuICAgIGZvciAoaSA9IDA7IGkgPCB0aGlzLnZhbHVlcy5sZW5ndGg7IGkrKykge1xuICAgICAgaWYgKHMgIT09IFwiXCIpIHtcbiAgICAgICAgcyArPSBcIiwgXCI7XG4gICAgICB9XG4gICAgICBzICs9IHRoaXMudmFsdWVzW2ldLnRvU3RyaW5nKCk7XG4gICAgfVxuXG4gICAgcmV0dXJuIFwie1wiICsgcyArIFwifVwiO1xuICB9XG5cbn1cblxubGV0IHByb2Nlc3NfY291bnRlciA9IC0xO1xuXG5jbGFzcyBQSUQge1xuICBjb25zdHJ1Y3RvcigpIHtcbiAgICBwcm9jZXNzX2NvdW50ZXIgPSBwcm9jZXNzX2NvdW50ZXIgKyAxO1xuICAgIHRoaXMuaWQgPSBwcm9jZXNzX2NvdW50ZXI7XG4gIH1cblxuICB0b1N0cmluZygpIHtcbiAgICByZXR1cm4gXCJQSUQjPDAuXCIgKyB0aGlzLmlkICsgXCIuMD5cIjtcbiAgfVxufVxuXG5jbGFzcyBJbnRlZ2VyIHt9XG5jbGFzcyBGbG9hdCB7fVxuXG5mdW5jdGlvbiBMaXN0JDEoLi4uYXJncykge1xuICByZXR1cm4gT2JqZWN0LmZyZWV6ZShhcmdzKTtcbn1cblxuY2xhc3MgUHJvY2Vzc1N5c3RlbSB7XG5cbiAgY29uc3RydWN0b3IoKSB7XG4gICAgdGhpcy5waWRzID0gbmV3IE1hcCgpO1xuICAgIHRoaXMubWFpbGJveGVzID0gbmV3IE1hcCgpO1xuICAgIHRoaXMubmFtZXMgPSBuZXcgTWFwKCk7XG4gICAgdGhpcy5saW5rcyA9IG5ldyBNYXAoKTtcblxuICAgIHRoaXMuY3VycmVudF9wcm9jZXNzID0gbnVsbDtcbiAgICB0aGlzLnN1c3BlbmRlZCA9IG5ldyBNYXAoKTtcblxuICAgIHRoaXMubWFpbl9wcm9jZXNzX3BpZCA9IHRoaXMuc3Bhd24oKTtcbiAgICB0aGlzLnNldF9jdXJyZW50KHRoaXMubWFpbl9wcm9jZXNzX3BpZCk7XG4gIH1cblxuICBzcGF3bigpIHtcbiAgICByZXR1cm4gdGhpcy5hZGRfcHJvYyhmYWxzZSkucGlkO1xuICB9XG5cbiAgc3Bhd25fbGluaygpIHtcbiAgICByZXR1cm4gdGhpcy5hZGRfcHJvYyh0cnVlKS5waWQ7XG4gIH1cblxuICBsaW5rKHBpZCkge1xuICAgIHRoaXMubGlua3MuZ2V0KHRoaXMucGlkKCkpLmFkZChwaWQpO1xuICAgIHRoaXMubGlua3MuZ2V0KHBpZCkuYWRkKHRoaXMucGlkKCkpO1xuICB9XG5cbiAgdW5saW5rKHBpZCkge1xuICAgIHRoaXMubGlua3MuZ2V0KHRoaXMucGlkKCkpLmRlbGV0ZShwaWQpO1xuICAgIHRoaXMubGlua3MuZ2V0KHBpZCkuZGVsZXRlKHRoaXMucGlkKCkpO1xuICB9XG5cbiAgc2V0X2N1cnJlbnQoaWQpIHtcbiAgICBsZXQgcGlkID0gdGhpcy5waWRvZihpZCk7XG4gICAgaWYgKHBpZCAhPT0gbnVsbCkge1xuICAgICAgdGhpcy5jdXJyZW50X3Byb2Nlc3MgPSB0aGlzLnBpZHMuZ2V0KHBpZCk7XG4gICAgICB0aGlzLmN1cnJlbnRfcHJvY2Vzcy5zdGF0dXMgPSBTdGF0ZXMuUlVOTklORztcbiAgICB9XG4gIH1cblxuICBhZGRfcHJvYyhsaW5rZWQpIHtcbiAgICBsZXQgbmV3cGlkID0gbmV3IFBJRCgpO1xuICAgIGxldCBtYWlsYm94ID0gbmV3IE1haWxib3goKTtcbiAgICBsZXQgbmV3cHJvYyA9IG5ldyBQcm9jZXNzKG5ld3BpZCwgbWFpbGJveCk7XG5cbiAgICB0aGlzLnBpZHMuc2V0KG5ld3BpZCwgbmV3cHJvYyk7XG4gICAgdGhpcy5tYWlsYm94ZXMuc2V0KG5ld3BpZCwgbWFpbGJveCk7XG4gICAgdGhpcy5saW5rcy5zZXQobmV3cGlkLCBuZXcgU2V0KCkpO1xuXG4gICAgaWYgKGxpbmtlZCkge1xuICAgICAgdGhpcy5saW5rKG5ld3BpZCk7XG4gICAgfVxuXG4gICAgcmV0dXJuIG5ld3Byb2M7XG4gIH1cblxuICByZW1vdmVfcHJvYyhwaWQpIHtcbiAgICB0aGlzLnBpZHMuZGVsZXRlKHBpZCk7XG4gICAgdGhpcy51bnJlZ2lzdGVyKHBpZCk7XG5cbiAgICBpZiAodGhpcy5saW5rcy5oYXMocGlkKSkge1xuICAgICAgZm9yIChsZXQgbGlua3BpZCBvZiB0aGlzLmxpbmtzLmdldChwaWQpKSB7XG4gICAgICAgIHRoaXMubGlua3MuZ2V0KGxpbmtwaWQpLmRlbGV0ZShwaWQpO1xuICAgICAgfVxuXG4gICAgICB0aGlzLmxpbmtzLmRlbGV0ZShwaWQpO1xuICAgIH1cbiAgfVxuXG4gIGV4aXQoaWQpIHtcbiAgICBsZXQgcGlkID0gdGhpcy5waWRvZihpZCk7XG4gICAgdGhpcy5yZW1vdmVfcHJvYyhpZCk7XG4gIH1cblxuICByZWdpc3RlcihuYW1lLCBwaWQpIHtcbiAgICBpZiAoIXRoaXMubmFtZXMuaGFzKG5hbWUpKSB7XG4gICAgICB0aGlzLm5hbWVzLnNldChuYW1lLCBwaWQpO1xuICAgICAgcmV0dXJuIG5hbWU7XG4gICAgfSBlbHNlIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcihcIk5hbWUgaXMgYWxyZWFkeSByZWdpc3RlcmVkIHRvIGFub3RoZXIgcHJvY2Vzc1wiKTtcbiAgICB9XG4gIH1cblxuICByZWdpc3RlcmVkKG5hbWUpIHtcbiAgICByZXR1cm4gdGhpcy5uYW1lcy5oYXMobmFtZSkgPyB0aGlzLm5hbWVzLmdldChuYW1lKSA6IG51bGw7XG4gIH1cblxuICB1bnJlZ2lzdGVyKHBpZCkge1xuICAgIGZvciAobGV0IG5hbWUgb2YgdGhpcy5uYW1lcy5rZXlzKCkpIHtcbiAgICAgIGlmICh0aGlzLm5hbWVzLmhhcyhuYW1lKSAmJiB0aGlzLm5hbWVzLmdldChuYW1lKSA9PT0gcGlkKSB7XG4gICAgICAgIHRoaXMubmFtZXMuZGVsZXRlKG5hbWUpO1xuICAgICAgfVxuICAgIH1cbiAgfVxuXG4gIHBpZCgpIHtcbiAgICByZXR1cm4gdGhpcy5jdXJyZW50X3Byb2Nlc3MucGlkO1xuICB9XG5cbiAgcGlkb2YoaWQpIHtcbiAgICBpZiAoaWQgaW5zdGFuY2VvZiBQSUQpIHtcbiAgICAgIHJldHVybiB0aGlzLnBpZHMuaGFzKGlkKSA/IGlkIDogbnVsbDtcbiAgICB9IGVsc2UgaWYgKGlkIGluc3RhbmNlb2YgUHJvY2Vzcykge1xuICAgICAgcmV0dXJuIGlkLnBpZDtcbiAgICB9IGVsc2Uge1xuICAgICAgbGV0IHBpZCA9IHRoaXMucmVnaXN0ZXJlZChpZCk7XG4gICAgICBpZiAocGlkID09PSBudWxsKSB0aHJvdyBcIlByb2Nlc3MgbmFtZSBub3QgcmVnaXN0ZXJlZDogXCIgKyBpZCArIFwiIChcIiArIHR5cGVvZiBpZCArIFwiKVwiO1xuICAgICAgcmV0dXJuIHBpZDtcbiAgICB9XG4gIH1cblxuICBwdXQoaWQsIGtleSwgdmFsdWUpIHtcbiAgICBsZXQgcGlkID0gdGhpcy5waWRvZihpZCk7XG4gICAgbGV0IHByb2Nlc3MgPSB0aGlzLnBpZHMuZ2V0KHBpZCk7XG4gICAgcHJvY2Vzcy5kaWN0W2tleV0gPSB2YWx1ZTtcbiAgfVxuXG4gIGdldChpZCwga2V5KSB7XG4gICAgbGV0IHBpZCA9IHRoaXMucGlkb2YoaWQpO1xuICAgIGxldCBwcm9jZXNzID0gdGhpcy5waWRzLmdldChwaWQpO1xuXG4gICAgaWYgKGtleSAhPSBudWxsKSB7XG4gICAgICByZXR1cm4gcHJvY2Vzcy5kaWN0W2tleV07XG4gICAgfSBlbHNlIHtcbiAgICAgIHJldHVybiBwcm9jZXNzLmRpY3Q7XG4gICAgfVxuICB9XG5cbiAgZ2V0X2tleXMoaWQpIHtcbiAgICBsZXQgcGlkID0gdGhpcy5waWRvZihpZCk7XG4gICAgbGV0IHByb2Nlc3MgPSB0aGlzLnBpZHMuZ2V0KHBpZCk7XG5cbiAgICByZXR1cm4gT2JqZWN0LmtleXMocHJvY2Vzcy5kaWN0KTtcbiAgfVxuXG4gIGVyYXNlKGlkLCBrZXkpIHtcbiAgICBsZXQgcGlkID0gdGhpcy5waWRvZihpZCk7XG4gICAgbGV0IHByb2Nlc3MgPSB0aGlzLnBpZHMuZ2V0KHBpZCk7XG5cbiAgICBpZiAoa2V5ICE9IG51bGwpIHtcbiAgICAgIGRlbGV0ZSBwcm9jZXNzLmRpY3Rba2V5XTtcbiAgICB9IGVsc2Uge1xuICAgICAgcHJvY2Vzcy5kaWN0ID0ge307XG4gICAgfVxuICB9XG59XG5cbmNsYXNzIEJpdFN0cmluZyB7XG4gIGNvbnN0cnVjdG9yKC4uLmFyZ3MpIHtcbiAgICB0aGlzLnJhd192YWx1ZSA9IGZ1bmN0aW9uICgpIHtcbiAgICAgIHJldHVybiBPYmplY3QuZnJlZXplKGFyZ3MpO1xuICAgIH07XG5cbiAgICB0aGlzLnZhbHVlID0gT2JqZWN0LmZyZWV6ZSh0aGlzLnByb2Nlc3MoYXJncykpO1xuICB9XG5cbiAgZ2V0KGluZGV4KSB7XG4gICAgcmV0dXJuIHRoaXMudmFsdWVbaW5kZXhdO1xuICB9XG5cbiAgY291bnQoKSB7XG4gICAgcmV0dXJuIHRoaXMudmFsdWUubGVuZ3RoO1xuICB9XG5cbiAgW1N5bWJvbC5pdGVyYXRvcl0oKSB7XG4gICAgcmV0dXJuIHRoaXMudmFsdWVbU3ltYm9sLml0ZXJhdG9yXSgpO1xuICB9XG5cbiAgdG9TdHJpbmcoKSB7XG4gICAgdmFyIGksXG4gICAgICAgIHMgPSBcIlwiO1xuICAgIGZvciAoaSA9IDA7IGkgPCB0aGlzLmNvdW50KCk7IGkrKykge1xuICAgICAgaWYgKHMgIT09IFwiXCIpIHtcbiAgICAgICAgcyArPSBcIiwgXCI7XG4gICAgICB9XG4gICAgICBzICs9IHRoaXNbaV0udG9TdHJpbmcoKTtcbiAgICB9XG5cbiAgICByZXR1cm4gXCI8PFwiICsgcyArIFwiPj5cIjtcbiAgfVxuXG4gIHByb2Nlc3MoKSB7XG4gICAgbGV0IHByb2Nlc3NlZF92YWx1ZXMgPSBbXTtcblxuICAgIHZhciBpO1xuICAgIGZvciAoaSA9IDA7IGkgPCB0aGlzLnJhd192YWx1ZSgpLmxlbmd0aDsgaSsrKSB7XG4gICAgICBsZXQgcHJvY2Vzc2VkX3ZhbHVlID0gdGhpc1tcInByb2Nlc3NfXCIgKyB0aGlzLnJhd192YWx1ZSgpW2ldLnR5cGVdKHRoaXMucmF3X3ZhbHVlKClbaV0pO1xuXG4gICAgICBmb3IgKGxldCBhdHRyIG9mIHRoaXMucmF3X3ZhbHVlKClbaV0uYXR0cmlidXRlcykge1xuICAgICAgICBwcm9jZXNzZWRfdmFsdWUgPSB0aGlzW1wicHJvY2Vzc19cIiArIGF0dHJdKHByb2Nlc3NlZF92YWx1ZSk7XG4gICAgICB9XG5cbiAgICAgIHByb2Nlc3NlZF92YWx1ZXMgPSBwcm9jZXNzZWRfdmFsdWVzLmNvbmNhdChwcm9jZXNzZWRfdmFsdWUpO1xuICAgIH1cblxuICAgIHJldHVybiBwcm9jZXNzZWRfdmFsdWVzO1xuICB9XG5cbiAgcHJvY2Vzc19pbnRlZ2VyKHZhbHVlKSB7XG4gICAgcmV0dXJuIHZhbHVlLnZhbHVlO1xuICB9XG5cbiAgcHJvY2Vzc19mbG9hdCh2YWx1ZSkge1xuICAgIGlmICh2YWx1ZS5zaXplID09PSA2NCkge1xuICAgICAgcmV0dXJuIEJpdFN0cmluZy5mbG9hdDY0VG9CeXRlcyh2YWx1ZS52YWx1ZSk7XG4gICAgfSBlbHNlIGlmICh2YWx1ZS5zaXplID09PSAzMikge1xuICAgICAgcmV0dXJuIEJpdFN0cmluZy5mbG9hdDMyVG9CeXRlcyh2YWx1ZS52YWx1ZSk7XG4gICAgfVxuXG4gICAgdGhyb3cgbmV3IEVycm9yKFwiSW52YWxpZCBzaXplIGZvciBmbG9hdFwiKTtcbiAgfVxuXG4gIHByb2Nlc3NfYml0c3RyaW5nKHZhbHVlKSB7XG4gICAgcmV0dXJuIHZhbHVlLnZhbHVlLnZhbHVlO1xuICB9XG5cbiAgcHJvY2Vzc19iaW5hcnkodmFsdWUpIHtcbiAgICByZXR1cm4gQml0U3RyaW5nLnRvVVRGOEFycmF5KHZhbHVlLnZhbHVlKTtcbiAgfVxuXG4gIHByb2Nlc3NfdXRmOCh2YWx1ZSkge1xuICAgIHJldHVybiBCaXRTdHJpbmcudG9VVEY4QXJyYXkodmFsdWUudmFsdWUpO1xuICB9XG5cbiAgcHJvY2Vzc191dGYxNih2YWx1ZSkge1xuICAgIHJldHVybiBCaXRTdHJpbmcudG9VVEYxNkFycmF5KHZhbHVlLnZhbHVlKTtcbiAgfVxuXG4gIHByb2Nlc3NfdXRmMzIodmFsdWUpIHtcbiAgICByZXR1cm4gQml0U3RyaW5nLnRvVVRGMzJBcnJheSh2YWx1ZS52YWx1ZSk7XG4gIH1cblxuICBwcm9jZXNzX3NpZ25lZCh2YWx1ZSkge1xuICAgIHJldHVybiBuZXcgVWludDhBcnJheShbdmFsdWVdKVswXTtcbiAgfVxuXG4gIHByb2Nlc3NfdW5zaWduZWQodmFsdWUpIHtcbiAgICByZXR1cm4gdmFsdWU7XG4gIH1cblxuICBwcm9jZXNzX25hdGl2ZSh2YWx1ZSkge1xuICAgIHJldHVybiB2YWx1ZTtcbiAgfVxuXG4gIHByb2Nlc3NfYmlnKHZhbHVlKSB7XG4gICAgcmV0dXJuIHZhbHVlO1xuICB9XG5cbiAgcHJvY2Vzc19saXR0bGUodmFsdWUpIHtcbiAgICByZXR1cm4gdmFsdWUucmV2ZXJzZSgpO1xuICB9XG5cbiAgcHJvY2Vzc19zaXplKHZhbHVlKSB7XG4gICAgcmV0dXJuIHZhbHVlO1xuICB9XG5cbiAgcHJvY2Vzc191bml0KHZhbHVlKSB7XG4gICAgcmV0dXJuIHZhbHVlO1xuICB9XG5cbiAgc3RhdGljIGludGVnZXIodmFsdWUpIHtcbiAgICByZXR1cm4gQml0U3RyaW5nLndyYXAodmFsdWUsIHsgXCJ0eXBlXCI6IFwiaW50ZWdlclwiLCBcInVuaXRcIjogMSwgXCJzaXplXCI6IDggfSk7XG4gIH1cblxuICBzdGF0aWMgZmxvYXQodmFsdWUpIHtcbiAgICByZXR1cm4gQml0U3RyaW5nLndyYXAodmFsdWUsIHsgXCJ0eXBlXCI6IFwiZmxvYXRcIiwgXCJ1bml0XCI6IDEsIFwic2l6ZVwiOiA2NCB9KTtcbiAgfVxuXG4gIHN0YXRpYyBiaXRzdHJpbmcodmFsdWUpIHtcbiAgICByZXR1cm4gQml0U3RyaW5nLndyYXAodmFsdWUsIHsgXCJ0eXBlXCI6IFwiYml0c3RyaW5nXCIsIFwidW5pdFwiOiAxLCBcInNpemVcIjogdmFsdWUubGVuZ3RoIH0pO1xuICB9XG5cbiAgc3RhdGljIGJpdHModmFsdWUpIHtcbiAgICByZXR1cm4gQml0U3RyaW5nLmJpdHN0cmluZyh2YWx1ZSk7XG4gIH1cblxuICBzdGF0aWMgYmluYXJ5KHZhbHVlKSB7XG4gICAgcmV0dXJuIEJpdFN0cmluZy53cmFwKHZhbHVlLCB7IFwidHlwZVwiOiBcImJpbmFyeVwiLCBcInVuaXRcIjogOCwgXCJzaXplXCI6IHZhbHVlLmxlbmd0aCB9KTtcbiAgfVxuXG4gIHN0YXRpYyBieXRlcyh2YWx1ZSkge1xuICAgIHJldHVybiBCaXRTdHJpbmcuYmluYXJ5KHZhbHVlKTtcbiAgfVxuXG4gIHN0YXRpYyB1dGY4KHZhbHVlKSB7XG4gICAgcmV0dXJuIEJpdFN0cmluZy53cmFwKHZhbHVlLCB7IFwidHlwZVwiOiBcInV0ZjhcIiB9KTtcbiAgfVxuXG4gIHN0YXRpYyB1dGYxNih2YWx1ZSkge1xuICAgIHJldHVybiBCaXRTdHJpbmcud3JhcCh2YWx1ZSwgeyBcInR5cGVcIjogXCJ1dGYxNlwiIH0pO1xuICB9XG5cbiAgc3RhdGljIHV0ZjMyKHZhbHVlKSB7XG4gICAgcmV0dXJuIEJpdFN0cmluZy53cmFwKHZhbHVlLCB7IFwidHlwZVwiOiBcInV0ZjMyXCIgfSk7XG4gIH1cblxuICBzdGF0aWMgc2lnbmVkKHZhbHVlKSB7XG4gICAgcmV0dXJuIEJpdFN0cmluZy53cmFwKHZhbHVlLCB7fSwgXCJzaWduZWRcIik7XG4gIH1cblxuICBzdGF0aWMgdW5zaWduZWQodmFsdWUpIHtcbiAgICByZXR1cm4gQml0U3RyaW5nLndyYXAodmFsdWUsIHt9LCBcInVuc2lnbmVkXCIpO1xuICB9XG5cbiAgc3RhdGljIG5hdGl2ZSh2YWx1ZSkge1xuICAgIHJldHVybiBCaXRTdHJpbmcud3JhcCh2YWx1ZSwge30sIFwibmF0aXZlXCIpO1xuICB9XG5cbiAgc3RhdGljIGJpZyh2YWx1ZSkge1xuICAgIHJldHVybiBCaXRTdHJpbmcud3JhcCh2YWx1ZSwge30sIFwiYmlnXCIpO1xuICB9XG5cbiAgc3RhdGljIGxpdHRsZSh2YWx1ZSkge1xuICAgIHJldHVybiBCaXRTdHJpbmcud3JhcCh2YWx1ZSwge30sIFwibGl0dGxlXCIpO1xuICB9XG5cbiAgc3RhdGljIHNpemUodmFsdWUsIGNvdW50KSB7XG4gICAgcmV0dXJuIEJpdFN0cmluZy53cmFwKHZhbHVlLCB7IFwic2l6ZVwiOiBjb3VudCB9KTtcbiAgfVxuXG4gIHN0YXRpYyB1bml0KHZhbHVlLCBjb3VudCkge1xuICAgIHJldHVybiBCaXRTdHJpbmcud3JhcCh2YWx1ZSwgeyBcInVuaXRcIjogY291bnQgfSk7XG4gIH1cblxuICBzdGF0aWMgd3JhcCh2YWx1ZSwgb3B0LCBuZXdfYXR0cmlidXRlID0gbnVsbCkge1xuICAgIGxldCB0aGVfdmFsdWUgPSB2YWx1ZTtcblxuICAgIGlmICghKHZhbHVlIGluc3RhbmNlb2YgT2JqZWN0KSkge1xuICAgICAgdGhlX3ZhbHVlID0geyBcInZhbHVlXCI6IHZhbHVlLCBcImF0dHJpYnV0ZXNcIjogW10gfTtcbiAgICB9XG5cbiAgICB0aGVfdmFsdWUgPSBPYmplY3QuYXNzaWduKHRoZV92YWx1ZSwgb3B0KTtcblxuICAgIGlmIChuZXdfYXR0cmlidXRlKSB7XG4gICAgICB0aGVfdmFsdWUuYXR0cmlidXRlcy5wdXNoKG5ld19hdHRyaWJ1dGUpO1xuICAgIH1cblxuICAgIHJldHVybiB0aGVfdmFsdWU7XG4gIH1cblxuICBzdGF0aWMgdG9VVEY4QXJyYXkoc3RyKSB7XG4gICAgdmFyIHV0ZjggPSBbXTtcbiAgICBmb3IgKHZhciBpID0gMDsgaSA8IHN0ci5sZW5ndGg7IGkrKykge1xuICAgICAgdmFyIGNoYXJjb2RlID0gc3RyLmNoYXJDb2RlQXQoaSk7XG4gICAgICBpZiAoY2hhcmNvZGUgPCAxMjgpIHtcbiAgICAgICAgdXRmOC5wdXNoKGNoYXJjb2RlKTtcbiAgICAgIH0gZWxzZSBpZiAoY2hhcmNvZGUgPCAyMDQ4KSB7XG4gICAgICAgIHV0ZjgucHVzaCgxOTIgfCBjaGFyY29kZSA+PiA2LCAxMjggfCBjaGFyY29kZSAmIDYzKTtcbiAgICAgIH0gZWxzZSBpZiAoY2hhcmNvZGUgPCA1NTI5NiB8fCBjaGFyY29kZSA+PSA1NzM0NCkge1xuICAgICAgICB1dGY4LnB1c2goMjI0IHwgY2hhcmNvZGUgPj4gMTIsIDEyOCB8IGNoYXJjb2RlID4+IDYgJiA2MywgMTI4IHwgY2hhcmNvZGUgJiA2Myk7XG4gICAgICB9XG4gICAgICAvLyBzdXJyb2dhdGUgcGFpclxuICAgICAgZWxzZSB7XG4gICAgICAgIGkrKztcbiAgICAgICAgLy8gVVRGLTE2IGVuY29kZXMgMHgxMDAwMC0weDEwRkZGRiBieVxuICAgICAgICAvLyBzdWJ0cmFjdGluZyAweDEwMDAwIGFuZCBzcGxpdHRpbmcgdGhlXG4gICAgICAgIC8vIDIwIGJpdHMgb2YgMHgwLTB4RkZGRkYgaW50byB0d28gaGFsdmVzXG4gICAgICAgIGNoYXJjb2RlID0gNjU1MzYgKyAoKGNoYXJjb2RlICYgMTAyMykgPDwgMTAgfCBzdHIuY2hhckNvZGVBdChpKSAmIDEwMjMpO1xuICAgICAgICB1dGY4LnB1c2goMjQwIHwgY2hhcmNvZGUgPj4gMTgsIDEyOCB8IGNoYXJjb2RlID4+IDEyICYgNjMsIDEyOCB8IGNoYXJjb2RlID4+IDYgJiA2MywgMTI4IHwgY2hhcmNvZGUgJiA2Myk7XG4gICAgICB9XG4gICAgfVxuICAgIHJldHVybiB1dGY4O1xuICB9XG5cbiAgc3RhdGljIHRvVVRGMTZBcnJheShzdHIpIHtcbiAgICB2YXIgdXRmMTYgPSBbXTtcbiAgICBmb3IgKHZhciBpID0gMDsgaSA8IHN0ci5sZW5ndGg7IGkrKykge1xuICAgICAgdmFyIGNvZGVQb2ludCA9IHN0ci5jb2RlUG9pbnRBdChpKTtcblxuICAgICAgaWYgKGNvZGVQb2ludCA8PSAyNTUpIHtcbiAgICAgICAgdXRmMTYucHVzaCgwKTtcbiAgICAgICAgdXRmMTYucHVzaChjb2RlUG9pbnQpO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgdXRmMTYucHVzaChjb2RlUG9pbnQgPj4gOCAmIDI1NSk7XG4gICAgICAgIHV0ZjE2LnB1c2goY29kZVBvaW50ICYgMjU1KTtcbiAgICAgIH1cbiAgICB9XG4gICAgcmV0dXJuIHV0ZjE2O1xuICB9XG5cbiAgc3RhdGljIHRvVVRGMzJBcnJheShzdHIpIHtcbiAgICB2YXIgdXRmMzIgPSBbXTtcbiAgICBmb3IgKHZhciBpID0gMDsgaSA8IHN0ci5sZW5ndGg7IGkrKykge1xuICAgICAgdmFyIGNvZGVQb2ludCA9IHN0ci5jb2RlUG9pbnRBdChpKTtcblxuICAgICAgaWYgKGNvZGVQb2ludCA8PSAyNTUpIHtcbiAgICAgICAgdXRmMzIucHVzaCgwKTtcbiAgICAgICAgdXRmMzIucHVzaCgwKTtcbiAgICAgICAgdXRmMzIucHVzaCgwKTtcbiAgICAgICAgdXRmMzIucHVzaChjb2RlUG9pbnQpO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgdXRmMzIucHVzaCgwKTtcbiAgICAgICAgdXRmMzIucHVzaCgwKTtcbiAgICAgICAgdXRmMzIucHVzaChjb2RlUG9pbnQgPj4gOCAmIDI1NSk7XG4gICAgICAgIHV0ZjMyLnB1c2goY29kZVBvaW50ICYgMjU1KTtcbiAgICAgIH1cbiAgICB9XG4gICAgcmV0dXJuIHV0ZjMyO1xuICB9XG5cbiAgLy9odHRwOi8vc3RhY2tvdmVyZmxvdy5jb20vcXVlc3Rpb25zLzIwMDM0OTMvamF2YXNjcmlwdC1mbG9hdC1mcm9tLXRvLWJpdHNcbiAgc3RhdGljIGZsb2F0MzJUb0J5dGVzKGYpIHtcbiAgICB2YXIgYnl0ZXMgPSBbXTtcblxuICAgIHZhciBidWYgPSBuZXcgQXJyYXlCdWZmZXIoNCk7XG4gICAgbmV3IEZsb2F0MzJBcnJheShidWYpWzBdID0gZjtcblxuICAgIGxldCBpbnRWZXJzaW9uID0gbmV3IFVpbnQzMkFycmF5KGJ1ZilbMF07XG5cbiAgICBieXRlcy5wdXNoKGludFZlcnNpb24gPj4gMjQgJiAyNTUpO1xuICAgIGJ5dGVzLnB1c2goaW50VmVyc2lvbiA+PiAxNiAmIDI1NSk7XG4gICAgYnl0ZXMucHVzaChpbnRWZXJzaW9uID4+IDggJiAyNTUpO1xuICAgIGJ5dGVzLnB1c2goaW50VmVyc2lvbiAmIDI1NSk7XG5cbiAgICByZXR1cm4gYnl0ZXM7XG4gIH1cblxuICBzdGF0aWMgZmxvYXQ2NFRvQnl0ZXMoZikge1xuICAgIHZhciBieXRlcyA9IFtdO1xuXG4gICAgdmFyIGJ1ZiA9IG5ldyBBcnJheUJ1ZmZlcig4KTtcbiAgICBuZXcgRmxvYXQ2NEFycmF5KGJ1ZilbMF0gPSBmO1xuXG4gICAgdmFyIGludFZlcnNpb24xID0gbmV3IFVpbnQzMkFycmF5KGJ1ZilbMF07XG4gICAgdmFyIGludFZlcnNpb24yID0gbmV3IFVpbnQzMkFycmF5KGJ1ZilbMV07XG5cbiAgICBieXRlcy5wdXNoKGludFZlcnNpb24yID4+IDI0ICYgMjU1KTtcbiAgICBieXRlcy5wdXNoKGludFZlcnNpb24yID4+IDE2ICYgMjU1KTtcbiAgICBieXRlcy5wdXNoKGludFZlcnNpb24yID4+IDggJiAyNTUpO1xuICAgIGJ5dGVzLnB1c2goaW50VmVyc2lvbjIgJiAyNTUpO1xuXG4gICAgYnl0ZXMucHVzaChpbnRWZXJzaW9uMSA+PiAyNCAmIDI1NSk7XG4gICAgYnl0ZXMucHVzaChpbnRWZXJzaW9uMSA+PiAxNiAmIDI1NSk7XG4gICAgYnl0ZXMucHVzaChpbnRWZXJzaW9uMSA+PiA4ICYgMjU1KTtcbiAgICBieXRlcy5wdXNoKGludFZlcnNpb24xICYgMjU1KTtcblxuICAgIHJldHVybiBieXRlcztcbiAgfVxufVxuXG4vKiBAZmxvdyAqL1xuXG5jbGFzcyBWYXJpYWJsZSB7XG5cbiAgY29uc3RydWN0b3IobmFtZSA9IG51bGwpIHtcbiAgICB0aGlzLm5hbWUgPSBuYW1lO1xuICB9XG59XG5cbmNsYXNzIFdpbGRjYXJkIHtcbiAgY29uc3RydWN0b3IoKSB7fVxufVxuXG5jbGFzcyBTdGFydHNXaXRoIHtcblxuICBjb25zdHJ1Y3RvcihwcmVmaXgpIHtcbiAgICB0aGlzLnByZWZpeCA9IHByZWZpeDtcbiAgfVxufVxuXG5jbGFzcyBDYXB0dXJlIHtcblxuICBjb25zdHJ1Y3Rvcih2YWx1ZSkge1xuICAgIHRoaXMudmFsdWUgPSB2YWx1ZTtcbiAgfVxufVxuXG5jbGFzcyBIZWFkVGFpbCB7XG4gIGNvbnN0cnVjdG9yKCkge31cbn1cblxuY2xhc3MgVHlwZSB7XG5cbiAgY29uc3RydWN0b3IodHlwZSwgb2JqUGF0dGVybiA9IHt9KSB7XG4gICAgdGhpcy50eXBlID0gdHlwZTtcbiAgICB0aGlzLm9ialBhdHRlcm4gPSBvYmpQYXR0ZXJuO1xuICB9XG59XG5cbmNsYXNzIEJvdW5kIHtcblxuICBjb25zdHJ1Y3Rvcih2YWx1ZSkge1xuICAgIHRoaXMudmFsdWUgPSB2YWx1ZTtcbiAgfVxufVxuXG5mdW5jdGlvbiB2YXJpYWJsZShuYW1lID0gbnVsbCkge1xuICByZXR1cm4gbmV3IFZhcmlhYmxlKG5hbWUpO1xufVxuXG5mdW5jdGlvbiB3aWxkY2FyZCgpIHtcbiAgcmV0dXJuIG5ldyBXaWxkY2FyZCgpO1xufVxuXG5mdW5jdGlvbiBzdGFydHNXaXRoKHByZWZpeCkge1xuICByZXR1cm4gbmV3IFN0YXJ0c1dpdGgocHJlZml4KTtcbn1cblxuZnVuY3Rpb24gY2FwdHVyZSh2YWx1ZSkge1xuICByZXR1cm4gbmV3IENhcHR1cmUodmFsdWUpO1xufVxuXG5mdW5jdGlvbiBoZWFkVGFpbCgpIHtcbiAgcmV0dXJuIG5ldyBIZWFkVGFpbCgpO1xufVxuXG5mdW5jdGlvbiB0eXBlKHR5cGUsIG9ialBhdHRlcm4gPSB7fSkge1xuICByZXR1cm4gbmV3IFR5cGUodHlwZSwgb2JqUGF0dGVybik7XG59XG5cbmZ1bmN0aW9uIGJvdW5kKHZhbHVlKSB7XG4gIHJldHVybiBuZXcgQm91bmQodmFsdWUpO1xufVxuXG5mdW5jdGlvbiBpc19udW1iZXIkMih2YWx1ZSkge1xuICByZXR1cm4gdHlwZW9mIHZhbHVlID09PSAnbnVtYmVyJztcbn1cblxuZnVuY3Rpb24gaXNfc3RyaW5nKHZhbHVlKSB7XG4gIHJldHVybiB0eXBlb2YgdmFsdWUgPT09ICdzdHJpbmcnO1xufVxuXG5mdW5jdGlvbiBpc19ib29sZWFuJDIodmFsdWUpIHtcbiAgcmV0dXJuIHR5cGVvZiB2YWx1ZSA9PT0gJ2Jvb2xlYW4nO1xufVxuXG5mdW5jdGlvbiBpc19zeW1ib2wodmFsdWUpIHtcbiAgcmV0dXJuIHR5cGVvZiB2YWx1ZSA9PT0gJ3N5bWJvbCc7XG59XG5cbmZ1bmN0aW9uIGlzX251bGwodmFsdWUpIHtcbiAgcmV0dXJuIHZhbHVlID09PSBudWxsO1xufVxuXG5mdW5jdGlvbiBpc191bmRlZmluZWQodmFsdWUpIHtcbiAgcmV0dXJuIHR5cGVvZiB2YWx1ZSA9PT0gJ3VuZGVmaW5lZCc7XG59XG5cbmZ1bmN0aW9uIGlzX2Z1bmN0aW9uJDIodmFsdWUpIHtcbiAgcmV0dXJuIE9iamVjdC5wcm90b3R5cGUudG9TdHJpbmcuY2FsbCh2YWx1ZSkgPT0gJ1tvYmplY3QgRnVuY3Rpb25dJztcbn1cblxuZnVuY3Rpb24gaXNfdmFyaWFibGUodmFsdWUpIHtcbiAgcmV0dXJuIHZhbHVlIGluc3RhbmNlb2YgVmFyaWFibGU7XG59XG5cbmZ1bmN0aW9uIGlzX3dpbGRjYXJkKHZhbHVlKSB7XG4gIHJldHVybiB2YWx1ZSBpbnN0YW5jZW9mIFdpbGRjYXJkO1xufVxuXG5mdW5jdGlvbiBpc19oZWFkVGFpbCh2YWx1ZSkge1xuICByZXR1cm4gdmFsdWUgaW5zdGFuY2VvZiBIZWFkVGFpbDtcbn1cblxuZnVuY3Rpb24gaXNfY2FwdHVyZSh2YWx1ZSkge1xuICByZXR1cm4gdmFsdWUgaW5zdGFuY2VvZiBDYXB0dXJlO1xufVxuXG5mdW5jdGlvbiBpc190eXBlKHZhbHVlKSB7XG4gIHJldHVybiB2YWx1ZSBpbnN0YW5jZW9mIFR5cGU7XG59XG5cbmZ1bmN0aW9uIGlzX3N0YXJ0c1dpdGgodmFsdWUpIHtcbiAgcmV0dXJuIHZhbHVlIGluc3RhbmNlb2YgU3RhcnRzV2l0aDtcbn1cblxuZnVuY3Rpb24gaXNfYm91bmQodmFsdWUpIHtcbiAgcmV0dXJuIHZhbHVlIGluc3RhbmNlb2YgQm91bmQ7XG59XG5cbmZ1bmN0aW9uIGlzX29iamVjdCh2YWx1ZSkge1xuICByZXR1cm4gdHlwZW9mIHZhbHVlID09PSAnb2JqZWN0Jztcbn1cblxuZnVuY3Rpb24gaXNfYXJyYXkodmFsdWUpIHtcbiAgcmV0dXJuIEFycmF5LmlzQXJyYXkodmFsdWUpO1xufVxuXG52YXIgQ2hlY2tzID0ge1xuICBpc19udW1iZXI6IGlzX251bWJlciQyLFxuICBpc19zdHJpbmcsXG4gIGlzX2Jvb2xlYW46IGlzX2Jvb2xlYW4kMixcbiAgaXNfc3ltYm9sLFxuICBpc19udWxsLFxuICBpc191bmRlZmluZWQsXG4gIGlzX2Z1bmN0aW9uOiBpc19mdW5jdGlvbiQyLFxuICBpc192YXJpYWJsZSxcbiAgaXNfd2lsZGNhcmQsXG4gIGlzX2hlYWRUYWlsLFxuICBpc19jYXB0dXJlLFxuICBpc190eXBlLFxuICBpc19zdGFydHNXaXRoLFxuICBpc19ib3VuZCxcbiAgaXNfb2JqZWN0LFxuICBpc19hcnJheVxufTtcblxuZnVuY3Rpb24gcmVzb2x2ZVN5bWJvbChwYXR0ZXJuKSB7XG4gIHJldHVybiBmdW5jdGlvbiAodmFsdWUpIHtcbiAgICByZXR1cm4gQ2hlY2tzLmlzX3N5bWJvbCh2YWx1ZSkgJiYgdmFsdWUgPT09IHBhdHRlcm47XG4gIH07XG59XG5cbmZ1bmN0aW9uIHJlc29sdmVTdHJpbmcocGF0dGVybikge1xuICByZXR1cm4gZnVuY3Rpb24gKHZhbHVlKSB7XG4gICAgcmV0dXJuIENoZWNrcy5pc19zdHJpbmcodmFsdWUpICYmIHZhbHVlID09PSBwYXR0ZXJuO1xuICB9O1xufVxuXG5mdW5jdGlvbiByZXNvbHZlTnVtYmVyKHBhdHRlcm4pIHtcbiAgcmV0dXJuIGZ1bmN0aW9uICh2YWx1ZSkge1xuICAgIHJldHVybiBDaGVja3MuaXNfbnVtYmVyKHZhbHVlKSAmJiB2YWx1ZSA9PT0gcGF0dGVybjtcbiAgfTtcbn1cblxuZnVuY3Rpb24gcmVzb2x2ZUJvb2xlYW4ocGF0dGVybikge1xuICByZXR1cm4gZnVuY3Rpb24gKHZhbHVlKSB7XG4gICAgcmV0dXJuIENoZWNrcy5pc19ib29sZWFuKHZhbHVlKSAmJiB2YWx1ZSA9PT0gcGF0dGVybjtcbiAgfTtcbn1cblxuZnVuY3Rpb24gcmVzb2x2ZUZ1bmN0aW9uKHBhdHRlcm4pIHtcbiAgcmV0dXJuIGZ1bmN0aW9uICh2YWx1ZSkge1xuICAgIHJldHVybiBDaGVja3MuaXNfZnVuY3Rpb24odmFsdWUpICYmIHZhbHVlID09PSBwYXR0ZXJuO1xuICB9O1xufVxuXG5mdW5jdGlvbiByZXNvbHZlTnVsbChwYXR0ZXJuKSB7XG4gIHJldHVybiBmdW5jdGlvbiAodmFsdWUpIHtcbiAgICByZXR1cm4gQ2hlY2tzLmlzX251bGwodmFsdWUpO1xuICB9O1xufVxuXG5mdW5jdGlvbiByZXNvbHZlQm91bmQocGF0dGVybikge1xuICByZXR1cm4gZnVuY3Rpb24gKHZhbHVlLCBhcmdzKSB7XG4gICAgaWYgKHR5cGVvZiB2YWx1ZSA9PT0gdHlwZW9mIHBhdHRlcm4udmFsdWUgJiYgdmFsdWUgPT09IHBhdHRlcm4udmFsdWUpIHtcbiAgICAgIGFyZ3MucHVzaCh2YWx1ZSk7XG4gICAgICByZXR1cm4gdHJ1ZTtcbiAgICB9XG5cbiAgICByZXR1cm4gZmFsc2U7XG4gIH07XG59XG5cbmZ1bmN0aW9uIHJlc29sdmVXaWxkY2FyZCgpIHtcbiAgcmV0dXJuIGZ1bmN0aW9uICgpIHtcbiAgICByZXR1cm4gdHJ1ZTtcbiAgfTtcbn1cblxuZnVuY3Rpb24gcmVzb2x2ZVZhcmlhYmxlKCkge1xuICByZXR1cm4gZnVuY3Rpb24gKHZhbHVlLCBhcmdzKSB7XG4gICAgYXJncy5wdXNoKHZhbHVlKTtcbiAgICByZXR1cm4gdHJ1ZTtcbiAgfTtcbn1cblxuZnVuY3Rpb24gcmVzb2x2ZUhlYWRUYWlsKCkge1xuICByZXR1cm4gZnVuY3Rpb24gKHZhbHVlLCBhcmdzKSB7XG4gICAgaWYgKCFDaGVja3MuaXNfYXJyYXkodmFsdWUpIHx8IHZhbHVlLmxlbmd0aCA8IDIpIHtcbiAgICAgIHJldHVybiBmYWxzZTtcbiAgICB9XG5cbiAgICBjb25zdCBoZWFkID0gdmFsdWVbMF07XG4gICAgY29uc3QgdGFpbCA9IHZhbHVlLnNsaWNlKDEpO1xuXG4gICAgYXJncy5wdXNoKGhlYWQpO1xuICAgIGFyZ3MucHVzaCh0YWlsKTtcblxuICAgIHJldHVybiB0cnVlO1xuICB9O1xufVxuXG5mdW5jdGlvbiByZXNvbHZlQ2FwdHVyZShwYXR0ZXJuKSB7XG4gIGNvbnN0IG1hdGNoZXMgPSBidWlsZE1hdGNoKHBhdHRlcm4udmFsdWUpO1xuXG4gIHJldHVybiBmdW5jdGlvbiAodmFsdWUsIGFyZ3MpIHtcbiAgICBpZiAobWF0Y2hlcyh2YWx1ZSwgYXJncykpIHtcbiAgICAgIGFyZ3MucHVzaCh2YWx1ZSk7XG4gICAgICByZXR1cm4gdHJ1ZTtcbiAgICB9XG5cbiAgICByZXR1cm4gZmFsc2U7XG4gIH07XG59XG5cbmZ1bmN0aW9uIHJlc29sdmVTdGFydHNXaXRoKHBhdHRlcm4pIHtcbiAgY29uc3QgcHJlZml4ID0gcGF0dGVybi5wcmVmaXg7XG5cbiAgcmV0dXJuIGZ1bmN0aW9uICh2YWx1ZSwgYXJncykge1xuICAgIGlmIChDaGVja3MuaXNfc3RyaW5nKHZhbHVlKSAmJiB2YWx1ZS5zdGFydHNXaXRoKHByZWZpeCkpIHtcbiAgICAgIGFyZ3MucHVzaCh2YWx1ZS5zdWJzdHJpbmcocHJlZml4Lmxlbmd0aCkpO1xuICAgICAgcmV0dXJuIHRydWU7XG4gICAgfVxuXG4gICAgcmV0dXJuIGZhbHNlO1xuICB9O1xufVxuXG5mdW5jdGlvbiByZXNvbHZlVHlwZShwYXR0ZXJuKSB7XG4gIHJldHVybiBmdW5jdGlvbiAodmFsdWUsIGFyZ3MpIHtcbiAgICBpZiAodmFsdWUgaW5zdGFuY2VvZiBwYXR0ZXJuLnR5cGUpIHtcbiAgICAgIGNvbnN0IG1hdGNoZXMgPSBidWlsZE1hdGNoKHBhdHRlcm4ub2JqUGF0dGVybik7XG4gICAgICByZXR1cm4gbWF0Y2hlcyh2YWx1ZSwgYXJncykgJiYgYXJncy5wdXNoKHZhbHVlKSA+IDA7XG4gICAgfVxuXG4gICAgcmV0dXJuIGZhbHNlO1xuICB9O1xufVxuXG5mdW5jdGlvbiByZXNvbHZlQXJyYXkocGF0dGVybikge1xuICBjb25zdCBtYXRjaGVzID0gcGF0dGVybi5tYXAoeCA9PiBidWlsZE1hdGNoKHgpKTtcblxuICByZXR1cm4gZnVuY3Rpb24gKHZhbHVlLCBhcmdzKSB7XG4gICAgaWYgKCFDaGVja3MuaXNfYXJyYXkodmFsdWUpIHx8IHZhbHVlLmxlbmd0aCAhPSBwYXR0ZXJuLmxlbmd0aCkge1xuICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH1cblxuICAgIHJldHVybiB2YWx1ZS5ldmVyeShmdW5jdGlvbiAodiwgaSkge1xuICAgICAgcmV0dXJuIG1hdGNoZXNbaV0odmFsdWVbaV0sIGFyZ3MpO1xuICAgIH0pO1xuICB9O1xufVxuXG5mdW5jdGlvbiByZXNvbHZlT2JqZWN0KHBhdHRlcm4pIHtcbiAgbGV0IG1hdGNoZXMgPSB7fTtcblxuICBmb3IgKGxldCBrZXkgb2YgT2JqZWN0LmtleXMocGF0dGVybikuY29uY2F0KE9iamVjdC5nZXRPd25Qcm9wZXJ0eVN5bWJvbHMocGF0dGVybikpKSB7XG4gICAgbWF0Y2hlc1trZXldID0gYnVpbGRNYXRjaChwYXR0ZXJuW2tleV0pO1xuICB9XG5cbiAgcmV0dXJuIGZ1bmN0aW9uICh2YWx1ZSwgYXJncykge1xuICAgIGlmICghQ2hlY2tzLmlzX29iamVjdCh2YWx1ZSkgfHwgcGF0dGVybi5sZW5ndGggPiB2YWx1ZS5sZW5ndGgpIHtcbiAgICAgIHJldHVybiBmYWxzZTtcbiAgICB9XG5cbiAgICBmb3IgKGxldCBrZXkgb2YgT2JqZWN0LmtleXMocGF0dGVybikuY29uY2F0KE9iamVjdC5nZXRPd25Qcm9wZXJ0eVN5bWJvbHMocGF0dGVybikpKSB7XG4gICAgICBpZiAoIShrZXkgaW4gdmFsdWUpIHx8ICFtYXRjaGVzW2tleV0odmFsdWVba2V5XSwgYXJncykpIHtcbiAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgfVxuICAgIH1cblxuICAgIHJldHVybiB0cnVlO1xuICB9O1xufVxuXG5mdW5jdGlvbiByZXNvbHZlTm9NYXRjaCgpIHtcbiAgcmV0dXJuIGZ1bmN0aW9uICgpIHtcbiAgICByZXR1cm4gZmFsc2U7XG4gIH07XG59XG5cbnZhciBSZXNvbHZlcnMgPSB7XG4gIHJlc29sdmVCb3VuZCxcbiAgcmVzb2x2ZVdpbGRjYXJkLFxuICByZXNvbHZlVmFyaWFibGUsXG4gIHJlc29sdmVIZWFkVGFpbCxcbiAgcmVzb2x2ZUNhcHR1cmUsXG4gIHJlc29sdmVTdGFydHNXaXRoLFxuICByZXNvbHZlVHlwZSxcbiAgcmVzb2x2ZUFycmF5LFxuICByZXNvbHZlT2JqZWN0LFxuICByZXNvbHZlTm9NYXRjaCxcbiAgcmVzb2x2ZVN5bWJvbCxcbiAgcmVzb2x2ZVN0cmluZyxcbiAgcmVzb2x2ZU51bWJlcixcbiAgcmVzb2x2ZUJvb2xlYW4sXG4gIHJlc29sdmVGdW5jdGlvbixcbiAgcmVzb2x2ZU51bGxcbn07XG5cbmZ1bmN0aW9uIGJ1aWxkTWF0Y2gocGF0dGVybikge1xuXG4gIGlmIChDaGVja3MuaXNfdmFyaWFibGUocGF0dGVybikpIHtcbiAgICByZXR1cm4gUmVzb2x2ZXJzLnJlc29sdmVWYXJpYWJsZShwYXR0ZXJuKTtcbiAgfVxuXG4gIGlmIChDaGVja3MuaXNfd2lsZGNhcmQocGF0dGVybikpIHtcbiAgICByZXR1cm4gUmVzb2x2ZXJzLnJlc29sdmVXaWxkY2FyZChwYXR0ZXJuKTtcbiAgfVxuXG4gIGlmIChDaGVja3MuaXNfdW5kZWZpbmVkKHBhdHRlcm4pKSB7XG4gICAgcmV0dXJuIFJlc29sdmVycy5yZXNvbHZlV2lsZGNhcmQocGF0dGVybik7XG4gIH1cblxuICBpZiAoQ2hlY2tzLmlzX2hlYWRUYWlsKHBhdHRlcm4pKSB7XG4gICAgcmV0dXJuIFJlc29sdmVycy5yZXNvbHZlSGVhZFRhaWwocGF0dGVybik7XG4gIH1cblxuICBpZiAoQ2hlY2tzLmlzX3N0YXJ0c1dpdGgocGF0dGVybikpIHtcbiAgICByZXR1cm4gUmVzb2x2ZXJzLnJlc29sdmVTdGFydHNXaXRoKHBhdHRlcm4pO1xuICB9XG5cbiAgaWYgKENoZWNrcy5pc19jYXB0dXJlKHBhdHRlcm4pKSB7XG4gICAgcmV0dXJuIFJlc29sdmVycy5yZXNvbHZlQ2FwdHVyZShwYXR0ZXJuKTtcbiAgfVxuXG4gIGlmIChDaGVja3MuaXNfYm91bmQocGF0dGVybikpIHtcbiAgICByZXR1cm4gUmVzb2x2ZXJzLnJlc29sdmVCb3VuZChwYXR0ZXJuKTtcbiAgfVxuXG4gIGlmIChDaGVja3MuaXNfdHlwZShwYXR0ZXJuKSkge1xuICAgIHJldHVybiBSZXNvbHZlcnMucmVzb2x2ZVR5cGUocGF0dGVybik7XG4gIH1cblxuICBpZiAoQ2hlY2tzLmlzX2FycmF5KHBhdHRlcm4pKSB7XG4gICAgcmV0dXJuIFJlc29sdmVycy5yZXNvbHZlQXJyYXkocGF0dGVybik7XG4gIH1cblxuICBpZiAoQ2hlY2tzLmlzX251bWJlcihwYXR0ZXJuKSkge1xuICAgIHJldHVybiBSZXNvbHZlcnMucmVzb2x2ZU51bWJlcihwYXR0ZXJuKTtcbiAgfVxuXG4gIGlmIChDaGVja3MuaXNfc3RyaW5nKHBhdHRlcm4pKSB7XG4gICAgcmV0dXJuIFJlc29sdmVycy5yZXNvbHZlU3RyaW5nKHBhdHRlcm4pO1xuICB9XG5cbiAgaWYgKENoZWNrcy5pc19ib29sZWFuKHBhdHRlcm4pKSB7XG4gICAgcmV0dXJuIFJlc29sdmVycy5yZXNvbHZlQm9vbGVhbihwYXR0ZXJuKTtcbiAgfVxuXG4gIGlmIChDaGVja3MuaXNfc3ltYm9sKHBhdHRlcm4pKSB7XG4gICAgcmV0dXJuIFJlc29sdmVycy5yZXNvbHZlU3ltYm9sKHBhdHRlcm4pO1xuICB9XG5cbiAgaWYgKENoZWNrcy5pc19udWxsKHBhdHRlcm4pKSB7XG4gICAgcmV0dXJuIFJlc29sdmVycy5yZXNvbHZlTnVsbChwYXR0ZXJuKTtcbiAgfVxuXG4gIGlmIChDaGVja3MuaXNfb2JqZWN0KHBhdHRlcm4pKSB7XG4gICAgcmV0dXJuIFJlc29sdmVycy5yZXNvbHZlT2JqZWN0KHBhdHRlcm4pO1xuICB9XG5cbiAgcmV0dXJuIFJlc29sdmVycy5yZXNvbHZlTm9NYXRjaCgpO1xufVxuXG5jbGFzcyBNYXRjaEVycm9yIGV4dGVuZHMgRXJyb3Ige1xuICBjb25zdHJ1Y3RvcihhcmcpIHtcbiAgICBzdXBlcigpO1xuXG4gICAgaWYgKHR5cGVvZiBhcmcgPT09ICdzeW1ib2wnKSB7XG4gICAgICB0aGlzLm1lc3NhZ2UgPSAnTm8gbWF0Y2ggZm9yOiAnICsgYXJnLnRvU3RyaW5nKCk7XG4gICAgfSBlbHNlIGlmIChBcnJheS5pc0FycmF5KGFyZykpIHtcbiAgICAgIGxldCBtYXBwZWRWYWx1ZXMgPSBhcmcubWFwKHggPT4geC50b1N0cmluZygpKTtcbiAgICAgIHRoaXMubWVzc2FnZSA9ICdObyBtYXRjaCBmb3I6ICcgKyBtYXBwZWRWYWx1ZXM7XG4gICAgfSBlbHNlIHtcbiAgICAgIHRoaXMubWVzc2FnZSA9ICdObyBtYXRjaCBmb3I6ICcgKyBhcmc7XG4gICAgfVxuXG4gICAgdGhpcy5zdGFjayA9IG5ldyBFcnJvcigpLnN0YWNrO1xuICAgIHRoaXMubmFtZSA9IHRoaXMuY29uc3RydWN0b3IubmFtZTtcbiAgfVxufVxuXG5jbGFzcyBDYXNlIHtcblxuICBjb25zdHJ1Y3RvcihwYXR0ZXJuLCBmbiwgZ3VhcmQgPSAoKSA9PiB0cnVlKSB7XG4gICAgdGhpcy5wYXR0ZXJuID0gYnVpbGRNYXRjaChwYXR0ZXJuKTtcbiAgICB0aGlzLmZuID0gZm47XG4gICAgdGhpcy5ndWFyZCA9IGd1YXJkO1xuICB9XG59XG5cbmZ1bmN0aW9uIG1ha2VfY2FzZShwYXR0ZXJuLCBmbiwgZ3VhcmQgPSAoKSA9PiB0cnVlKSB7XG4gIHJldHVybiBuZXcgQ2FzZShwYXR0ZXJuLCBmbiwgZ3VhcmQpO1xufVxuXG5mdW5jdGlvbiBkZWZtYXRjaCguLi5jYXNlcykge1xuICByZXR1cm4gZnVuY3Rpb24gKC4uLmFyZ3MpIHtcbiAgICBmb3IgKGxldCBwcm9jZXNzZWRDYXNlIG9mIGNhc2VzKSB7XG4gICAgICBsZXQgcmVzdWx0ID0gW107XG4gICAgICBpZiAocHJvY2Vzc2VkQ2FzZS5wYXR0ZXJuKGFyZ3MsIHJlc3VsdCkgJiYgcHJvY2Vzc2VkQ2FzZS5ndWFyZC5hcHBseSh0aGlzLCByZXN1bHQpKSB7XG4gICAgICAgIHJldHVybiBwcm9jZXNzZWRDYXNlLmZuLmFwcGx5KHRoaXMsIHJlc3VsdCk7XG4gICAgICB9XG4gICAgfVxuXG4gICAgdGhyb3cgbmV3IE1hdGNoRXJyb3IoYXJncyk7XG4gIH07XG59XG5cbmZ1bmN0aW9uIG1hdGNoKHBhdHRlcm4sIGV4cHIsIGd1YXJkID0gKCkgPT4gdHJ1ZSkge1xuICBsZXQgcmVzdWx0ID0gW107XG4gIGxldCBwcm9jZXNzZWRQYXR0ZXJuID0gYnVpbGRNYXRjaChwYXR0ZXJuKTtcbiAgaWYgKHByb2Nlc3NlZFBhdHRlcm4oZXhwciwgcmVzdWx0KSAmJiBndWFyZC5hcHBseSh0aGlzLCByZXN1bHQpKSB7XG4gICAgcmV0dXJuIHJlc3VsdDtcbiAgfSBlbHNlIHtcbiAgICB0aHJvdyBuZXcgTWF0Y2hFcnJvcihleHByKTtcbiAgfVxufVxuXG5mdW5jdGlvbiBtYXRjaF9ub190aHJvdyhwYXR0ZXJuLCBleHByLCBndWFyZCA9ICgpID0+IHRydWUpIHtcbiAgdHJ5IHtcbiAgICByZXR1cm4gbWF0Y2gocGF0dGVybiwgZXhwciwgZ3VhcmQpO1xuICB9IGNhdGNoIChlKSB7XG4gICAgaWYgKGUgaW5zdGFuY2VvZiBNYXRjaEVycm9yKSB7XG4gICAgICByZXR1cm4gbnVsbDtcbiAgICB9XG5cbiAgICB0aHJvdyBlO1xuICB9XG59XG5cbnZhciBQYXR0ZXJucyA9IHtcbiAgZGVmbWF0Y2gsIG1hdGNoLCBNYXRjaEVycm9yLCBtYXRjaF9ub190aHJvdyxcbiAgdmFyaWFibGUsIHdpbGRjYXJkLCBzdGFydHNXaXRoLFxuICBjYXB0dXJlLCBoZWFkVGFpbCwgdHlwZSwgYm91bmQsIENhc2UsIG1ha2VfY2FzZVxufTtcblxuZnVuY3Rpb24gY2FsbF9wcm9wZXJ0eShpdGVtLCBwcm9wZXJ0eSkge1xuICBpZiAocHJvcGVydHkgaW4gaXRlbSkge1xuICAgIGl0ZW1bcHJvcGVydHldO1xuICAgIGlmIChpdGVtW3Byb3BlcnR5XSBpbnN0YW5jZW9mIEZ1bmN0aW9uKSB7XG4gICAgICByZXR1cm4gaXRlbVtwcm9wZXJ0eV0oKTtcbiAgICB9IGVsc2Uge1xuICAgICAgcmV0dXJuIGl0ZW1bcHJvcGVydHldO1xuICAgIH1cbiAgfSBlbHNlIGlmIChTeW1ib2wuZm9yKHByb3BlcnR5KSBpbiBpdGVtKSB7XG4gICAgbGV0IHByb3AgPSBTeW1ib2wuZm9yKHByb3BlcnR5KTtcbiAgICBpZiAoaXRlbVtwcm9wXSBpbnN0YW5jZW9mIEZ1bmN0aW9uKSB7XG4gICAgICByZXR1cm4gaXRlbVtwcm9wXSgpO1xuICAgIH0gZWxzZSB7XG4gICAgICByZXR1cm4gaXRlbVtwcm9wXTtcbiAgICB9XG4gIH1cblxuICB0aHJvdyBuZXcgRXJyb3IoYFByb3BlcnR5ICR7IHByb3BlcnR5IH0gbm90IGZvdW5kIGluICR7IGl0ZW0gfWApO1xufVxuXG5mdW5jdGlvbiBpc19pbnN0YW5jZV9vZih2YWx1ZSwgdHlwZSkge1xuICByZXR1cm4gdmFsdWUgaW5zdGFuY2VvZiB0eXBlO1xufVxuXG5mdW5jdGlvbiBzaXplJDIodGVybSkge1xuICByZXR1cm4gdGVybS5sZW5ndGg7XG59XG5cbmZ1bmN0aW9uIGlzX25pbCQxKHgpIHtcbiAgcmV0dXJuIHggPT09IG51bGw7XG59XG5cbmZ1bmN0aW9uIGlzX2F0b20kMSh4KSB7XG4gIHJldHVybiB0eXBlb2YgeCA9PT0gJ3N5bWJvbCc7XG59XG5cbmZ1bmN0aW9uIGlzX2JpbmFyeSQxKHgpIHtcbiAgcmV0dXJuIHR5cGVvZiB4ID09PSAnc3RyaW5nJyB8fCB4IGluc3RhbmNlb2YgU3RyaW5nO1xufVxuXG5mdW5jdGlvbiBpc19ib29sZWFuJDEoeCkge1xuICByZXR1cm4gdHlwZW9mIHggPT09ICdib29sZWFuJyB8fCB4IGluc3RhbmNlb2YgQm9vbGVhbjtcbn1cblxuZnVuY3Rpb24gaXNfZnVuY3Rpb24kMSh4LCBhcml0eSA9IC0xKSB7XG4gIHJldHVybiB0eXBlb2YgeCA9PT0gJ2Z1bmN0aW9uJyB8fCB4IGluc3RhbmNlb2YgRnVuY3Rpb247XG59XG5cbmZ1bmN0aW9uIGlzX2Zsb2F0JDEoeCkge1xuICByZXR1cm4gaXNfbnVtYmVyJDEoeCkgJiYgIU51bWJlci5pc0ludGVnZXIoeCk7XG59XG5cbmZ1bmN0aW9uIGlzX2ludGVnZXIkMSh4KSB7XG4gIHJldHVybiBOdW1iZXIuaXNJbnRlZ2VyKHgpO1xufVxuXG5mdW5jdGlvbiBpc19saXN0JDEoeCkge1xuICByZXR1cm4geCBpbnN0YW5jZW9mIEFycmF5O1xufVxuXG5mdW5jdGlvbiBpc19tYXAkMSh4KSB7XG4gIHJldHVybiB0eXBlb2YgeCA9PT0gJ29iamVjdCcgfHwgeCBpbnN0YW5jZW9mIE9iamVjdDtcbn1cblxuZnVuY3Rpb24gaXNfbnVtYmVyJDEoeCkge1xuICByZXR1cm4gdHlwZW9mIHggPT09ICdudW1iZXInO1xufVxuXG5mdW5jdGlvbiBpc190dXBsZSQxKHgpIHtcbiAgcmV0dXJuIHggaW5zdGFuY2VvZiBUdXBsZTtcbn1cblxuZnVuY3Rpb24gaXNfcGlkJDEoeCkge1xuICByZXR1cm4geCBpbnN0YW5jZW9mIFBJRDtcbn1cblxuZnVuY3Rpb24gaXNfcG9ydCQxKHgpIHtcbiAgcmV0dXJuIGZhbHNlO1xufVxuXG5mdW5jdGlvbiBpc19yZWZlcmVuY2UkMSh4KSB7XG4gIHJldHVybiBmYWxzZTtcbn1cblxuZnVuY3Rpb24gaXNfYml0c3RyaW5nJDEoeCkge1xuICByZXR1cm4gaXNfYmluYXJ5JDEoeCkgfHwgeCBpbnN0YW5jZW9mIEJpdFN0cmluZztcbn1cblxuZnVuY3Rpb24gYWRkKG9uZSwgdHdvKSB7XG4gIHJldHVybiBvbmUgKyB0d287XG59XG5cbmZ1bmN0aW9uIHN1YnRyYWN0KG9uZSwgdHdvKSB7XG4gIHJldHVybiBvbmUgKyB0d287XG59XG5cbmZ1bmN0aW9uIG11bHRpcGx5KG9uZSwgdHdvKSB7XG4gIHJldHVybiBvbmUgKyB0d287XG59XG5cbmZ1bmN0aW9uIGRpdmlkZShvbmUsIHR3bykge1xuICByZXR1cm4gb25lICsgdHdvO1xufVxuXG5mdW5jdGlvbiByZW1haW5kZXIob25lLCB0d28pIHtcbiAgcmV0dXJuIG9uZSArIHR3bztcbn1cblxuZnVuY3Rpb24gYXBwbHkkMSguLi5hcmdzKSB7XG4gIGlmIChhcmdzLmxlbmd0aCA9PT0gMikge1xuICAgIGFyZ3NbMF0uYXBwbHkobnVsbCwgYXJncy5zbGljZSgxKSk7XG4gIH0gZWxzZSB7XG4gICAgYXJnc1swXVthcmdzWzFdXS5hcHBseShudWxsLCBhcmdzLnNsaWNlKDIpKTtcbiAgfVxufVxuXG5mdW5jdGlvbiBuZXdfdHVwbGUoLi4uYXJncykge1xuICByZXR1cm4gbmV3IFR1cGxlKC4uLmFyZ3MpO1xufVxuXG5mdW5jdGlvbiBkdXBsaWNhdGUoZGF0YSwgc2l6ZSkge1xuICBsZXQgYXJyYXkgPSBbXTtcblxuICBmb3IgKHZhciBpID0gc2l6ZSAtIDE7IGkgPj0gMDsgaS0tKSB7XG4gICAgYXJyYXkucHVzaChkYXRhKTtcbiAgfVxuXG4gIHJldHVybiBhcnJheTtcbn1cblxuZnVuY3Rpb24gY29udGFpbnMobGVmdCwgcmlnaHQpIHtcbiAgZm9yIChsZXQgeCBvZiByaWdodCkge1xuICAgIGlmIChQYXR0ZXJucy5tYXRjaF9ub190aHJvdyhsZWZ0LCB4KSAhPSBudWxsKSB7XG4gICAgICByZXR1cm4gdHJ1ZTtcbiAgICB9XG4gIH1cblxuICByZXR1cm4gZmFsc2U7XG59XG5cbmZ1bmN0aW9uIHJldmVyc2UobGlzdCkge1xuICByZXR1cm4gbGlzdC5jb25jYXQoW10pLnJldmVyc2UoKTtcbn1cblxuZnVuY3Rpb24gZ2V0X2dsb2JhbCgpIHtcbiAgaWYgKHR5cGVvZiBzZWxmICE9PSAndW5kZWZpbmVkJykge1xuICAgIHJldHVybiBzZWxmO1xuICB9IGVsc2UgaWYgKHR5cGVvZiBnbG9iYWwgIT09ICd1bmRlZmluZWQnKSB7XG4gICAgcmV0dXJuIGdsb2JhbDtcbiAgfVxuXG4gIHRocm93ICdObyBnbG9iYWwgc3RhdGUgZm91bmQnO1xufVxuXG5mdW5jdGlvbiBjb25jYXRfbGlzdHMobGVmdCwgcmlnaHQpIHtcbiAgcmV0dXJuIGxlZnQuY29uY2F0KHJpZ2h0KTtcbn1cblxuZnVuY3Rpb24gcHJlcGVuZF90b19saXN0KGxpc3QsIGl0ZW0pIHtcbiAgcmV0dXJuIFtpdGVtXS5jb25jYXQobGlzdCk7XG59XG5cbmZ1bmN0aW9uIGRlZnN0cnVjdChkZWZhdWx0cykge1xuICByZXR1cm4gY2xhc3Mge1xuICAgIGNvbnN0cnVjdG9yKHVwZGF0ZSA9IHt9KSB7XG4gICAgICBsZXQgdGhlX3ZhbHVlcyA9IE9iamVjdC5hc3NpZ24oZGVmYXVsdHMsIHVwZGF0ZSk7XG4gICAgICBPYmplY3QuYXNzaWduKHRoaXMsIHRoZV92YWx1ZXMpO1xuICAgIH1cblxuICAgIHN0YXRpYyBjcmVhdGUodXBkYXRlcyA9IHt9KSB7XG4gICAgICBsZXQgeCA9IG5ldyB0aGlzKHVwZGF0ZXMpO1xuICAgICAgcmV0dXJuIE9iamVjdC5mcmVlemUoeCk7XG4gICAgfVxuICB9O1xufVxuXG5mdW5jdGlvbiBkZWZleGNlcHRpb24oZGVmYXVsdHMpIHtcbiAgcmV0dXJuIGNsYXNzIGV4dGVuZHMgRXJyb3Ige1xuICAgIGNvbnN0cnVjdG9yKHVwZGF0ZSA9IHt9KSB7XG4gICAgICBsZXQgbWVzc2FnZSA9IHVwZGF0ZS5tZXNzYWdlIHx8ICcnO1xuICAgICAgc3VwZXIobWVzc2FnZSk7XG5cbiAgICAgIGxldCB0aGVfdmFsdWVzID0gT2JqZWN0LmFzc2lnbihkZWZhdWx0cywgdXBkYXRlKTtcbiAgICAgIE9iamVjdC5hc3NpZ24odGhpcywgdGhlX3ZhbHVlcyk7XG5cbiAgICAgIHRoaXMubmFtZSA9IHRoaXMuY29uc3RydWN0b3IubmFtZTtcbiAgICAgIHRoaXMubWVzc2FnZSA9IG1lc3NhZ2U7XG4gICAgICB0aGlzW1NwZWNpYWxGb3Jtcy5hdG9tKCdfX2V4Y2VwdGlvbl9fJyldID0gdHJ1ZTtcbiAgICAgIEVycm9yLmNhcHR1cmVTdGFja1RyYWNlKHRoaXMsIHRoaXMuY29uc3RydWN0b3IubmFtZSk7XG4gICAgfVxuXG4gICAgc3RhdGljIGNyZWF0ZSh1cGRhdGVzID0ge30pIHtcbiAgICAgIGxldCB4ID0gbmV3IHRoaXModXBkYXRlcyk7XG4gICAgICByZXR1cm4gT2JqZWN0LmZyZWV6ZSh4KTtcbiAgICB9XG4gIH07XG59XG5cbmZ1bmN0aW9uIGRlZnByb3RvY29sKHNwZWMpIHtcbiAgcmV0dXJuIG5ldyBQcm90b2NvbChzcGVjKTtcbn1cblxuZnVuY3Rpb24gZGVmaW1wbChwcm90b2NvbCwgdHlwZSwgaW1wbCkge1xuICBwcm90b2NvbC5pbXBsZW1lbnRhdGlvbih0eXBlLCBpbXBsKTtcbn1cblxuZnVuY3Rpb24gZ2V0X29iamVjdF9rZXlzKG9iaikge1xuICByZXR1cm4gT2JqZWN0LmtleXMob2JqKS5jb25jYXQoT2JqZWN0LmdldE93blByb3BlcnR5U3ltYm9scyhvYmopKTtcbn1cblxuZnVuY3Rpb24gaXNfdmFsaWRfY2hhcmFjdGVyKGNvZGVwb2ludCkge1xuICB0cnkge1xuICAgIHJldHVybiBTdHJpbmcuZnJvbUNvZGVQb2ludChjb2RlcG9pbnQpICE9IG51bGw7XG4gIH0gY2F0Y2ggKGUpIHtcbiAgICByZXR1cm4gZmFsc2U7XG4gIH1cbn1cblxuLy9odHRwczovL2RldmVsb3Blci5tb3ppbGxhLm9yZy9lbi1VUy9kb2NzL1dlYi9BUEkvV2luZG93QmFzZTY0L0Jhc2U2NF9lbmNvZGluZ19hbmRfZGVjb2RpbmcjU29sdXRpb25fMl8lRTIlODAlOTNfcmV3cml0ZV90aGVfRE9Nc19hdG9iKClfYW5kX2J0b2EoKV91c2luZ19KYXZhU2NyaXB0J3NfVHlwZWRBcnJheXNfYW5kX1VURi04XG5mdW5jdGlvbiBiNjRFbmNvZGVVbmljb2RlKHN0cikge1xuICByZXR1cm4gYnRvYShlbmNvZGVVUklDb21wb25lbnQoc3RyKS5yZXBsYWNlKC8lKFswLTlBLUZdezJ9KS9nLCBmdW5jdGlvbiAobWF0Y2gsIHAxKSB7XG4gICAgcmV0dXJuIFN0cmluZy5mcm9tQ2hhckNvZGUoJzB4JyArIHAxKTtcbiAgfSkpO1xufVxuXG52YXIgRnVuY3Rpb25zID0ge1xuICBjYWxsX3Byb3BlcnR5LFxuICBpc19pbnN0YW5jZV9vZixcbiAgc2l6ZTogc2l6ZSQyLFxuICBpc19uaWw6IGlzX25pbCQxLFxuICBpc19hdG9tOiBpc19hdG9tJDEsXG4gIGlzX2JpbmFyeTogaXNfYmluYXJ5JDEsXG4gIGlzX2Jvb2xlYW46IGlzX2Jvb2xlYW4kMSxcbiAgaXNfZnVuY3Rpb246IGlzX2Z1bmN0aW9uJDEsXG4gIGlzX2Zsb2F0OiBpc19mbG9hdCQxLFxuICBpc19pbnRlZ2VyOiBpc19pbnRlZ2VyJDEsXG4gIGlzX2xpc3Q6IGlzX2xpc3QkMSxcbiAgaXNfbWFwOiBpc19tYXAkMSxcbiAgaXNfbnVtYmVyOiBpc19udW1iZXIkMSxcbiAgaXNfdHVwbGU6IGlzX3R1cGxlJDEsXG4gIGlzX3BpZDogaXNfcGlkJDEsXG4gIGlzX3BvcnQ6IGlzX3BvcnQkMSxcbiAgaXNfcmVmZXJlbmNlOiBpc19yZWZlcmVuY2UkMSxcbiAgaXNfYml0c3RyaW5nOiBpc19iaXRzdHJpbmckMSxcbiAgYWRkLFxuICBzdWJ0cmFjdCxcbiAgbXVsdGlwbHksXG4gIGRpdmlkZSxcbiAgcmVtYWluZGVyLFxuICBhcHBseTogYXBwbHkkMSxcbiAgbmV3X3R1cGxlLFxuICBkdXBsaWNhdGUsXG4gIGNvbnRhaW5zLFxuICByZXZlcnNlLFxuICBnZXRfZ2xvYmFsLFxuICBjb25jYXRfbGlzdHMsXG4gIHByZXBlbmRfdG9fbGlzdCxcbiAgZGVmc3RydWN0LFxuICBkZWZleGNlcHRpb24sXG4gIGRlZnByb3RvY29sLFxuICBkZWZpbXBsLFxuICBnZXRfb2JqZWN0X2tleXMsXG4gIGlzX3ZhbGlkX2NoYXJhY3RlcixcbiAgYjY0RW5jb2RlVW5pY29kZVxufTtcblxuRnVuY3Rpb25zLmdldF9nbG9iYWwoKS5wcm9jZXNzZXMgPSBGdW5jdGlvbnMuZ2V0X2dsb2JhbCgpLnByb2Nlc3NlcyB8fCBuZXcgUHJvY2Vzc1N5c3RlbSgpO1xuXG5cblxudmFyIEMgPSBPYmplY3QuZnJlZXplKHtcblx0UHJvY2Vzc1N5c3RlbTogUHJvY2Vzc1N5c3RlbSxcblx0VHVwbGU6IFR1cGxlLFxuXHRQSUQ6IFBJRCxcblx0Qml0U3RyaW5nOiBCaXRTdHJpbmcsXG5cdFBhdHRlcm5zOiBQYXR0ZXJucyxcblx0SW50ZWdlcjogSW50ZWdlcixcblx0RmxvYXQ6IEZsb2F0LFxuXHRGdW5jdGlvbnM6IEZ1bmN0aW9ucyxcblx0TGlzdDogTGlzdCQxXG59KTtcblxubGV0IEVudW0gPSB7XG5cbiAgYWxsX19xbWFya19fOiBmdW5jdGlvbiAoY29sbGVjdGlvbiwgZnVuID0geCA9PiB4KSB7XG4gICAgZm9yIChsZXQgZWxlbSBvZiBjb2xsZWN0aW9uKSB7XG4gICAgICBpZiAoIWZ1bihlbGVtKSkge1xuICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICB9XG4gICAgfVxuXG4gICAgcmV0dXJuIHRydWU7XG4gIH0sXG5cbiAgYW55X19xbWFya19fOiBmdW5jdGlvbiAoY29sbGVjdGlvbiwgZnVuID0geCA9PiB4KSB7XG4gICAgZm9yIChsZXQgZWxlbSBvZiBjb2xsZWN0aW9uKSB7XG4gICAgICBpZiAoZnVuKGVsZW0pKSB7XG4gICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgfVxuICAgIH1cblxuICAgIHJldHVybiBmYWxzZTtcbiAgfSxcblxuICBhdDogZnVuY3Rpb24gKGNvbGxlY3Rpb24sIG4sIHRoZV9kZWZhdWx0ID0gbnVsbCkge1xuICAgIGlmIChuID4gdGhpcy5jb3VudChjb2xsZWN0aW9uKSB8fCBuIDwgMCkge1xuICAgICAgcmV0dXJuIHRoZV9kZWZhdWx0O1xuICAgIH1cblxuICAgIHJldHVybiBjb2xsZWN0aW9uW25dO1xuICB9LFxuXG4gIGNvbmNhdDogZnVuY3Rpb24gKC4uLmVudW1hYmxlcykge1xuICAgIHJldHVybiBlbnVtYWJsZXNbMF0uY29uY2F0KGVudW1hYmxlc1sxXSk7XG4gIH0sXG5cbiAgY291bnQ6IGZ1bmN0aW9uIChjb2xsZWN0aW9uLCBmdW4gPSBudWxsKSB7XG4gICAgaWYgKGZ1biA9PSBudWxsKSB7XG4gICAgICByZXR1cm4gY29sbGVjdGlvbi5sZW5ndGg7XG4gICAgfSBlbHNlIHtcbiAgICAgIHJldHVybiBjb2xsZWN0aW9uLmZpbHRlcihmdW4pLmxlbmd0aDtcbiAgICB9XG4gIH0sXG5cbiAgZHJvcDogZnVuY3Rpb24gKGNvbGxlY3Rpb24sIGNvdW50KSB7XG4gICAgcmV0dXJuIGNvbGxlY3Rpb24uc2xpY2UoY291bnQpO1xuICB9LFxuXG4gIGRyb3Bfd2hpbGU6IGZ1bmN0aW9uIChjb2xsZWN0aW9uLCBmdW4pIHtcbiAgICBsZXQgY291bnQgPSAwO1xuXG4gICAgZm9yIChsZXQgZWxlbSBvZiBjb2xsZWN0aW9uKSB7XG4gICAgICBpZiAoZnVuKGVsZW0pKSB7XG4gICAgICAgIGNvdW50ID0gY291bnQgKyAxO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgYnJlYWs7XG4gICAgICB9XG4gICAgfVxuXG4gICAgcmV0dXJuIGNvbGxlY3Rpb24uc2xpY2UoY291bnQpO1xuICB9LFxuXG4gIGVhY2g6IGZ1bmN0aW9uIChjb2xsZWN0aW9uLCBmdW4pIHtcbiAgICBmb3IgKGxldCBlbGVtIG9mIGNvbGxlY3Rpb24pIHtcbiAgICAgIGZ1bihlbGVtKTtcbiAgICB9XG4gIH0sXG5cbiAgZW1wdHlfX3FtYXJrX186IGZ1bmN0aW9uIChjb2xsZWN0aW9uKSB7XG4gICAgcmV0dXJuIGNvbGxlY3Rpb24ubGVuZ3RoID09PSAwO1xuICB9LFxuXG4gIGZldGNoOiBmdW5jdGlvbiAoY29sbGVjdGlvbiwgbikge1xuICAgIGlmIChLZXJuZWwuaXNfbGlzdChjb2xsZWN0aW9uKSkge1xuICAgICAgaWYgKG4gPCB0aGlzLmNvdW50KGNvbGxlY3Rpb24pICYmIG4gPj0gMCkge1xuICAgICAgICByZXR1cm4gbmV3IFR1cGxlKFN5bWJvbC5mb3IoJ29rJyksIGNvbGxlY3Rpb25bbl0pO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgcmV0dXJuIFN5bWJvbC5mb3IoJ2Vycm9yJyk7XG4gICAgICB9XG4gICAgfVxuXG4gICAgdGhyb3cgbmV3IEVycm9yKCdjb2xsZWN0aW9uIGlzIG5vdCBhbiBFbnVtZXJhYmxlJyk7XG4gIH0sXG5cbiAgZmV0Y2hfX2VtYXJrX186IGZ1bmN0aW9uIChjb2xsZWN0aW9uLCBuKSB7XG4gICAgaWYgKEtlcm5lbC5pc19saXN0KGNvbGxlY3Rpb24pKSB7XG4gICAgICBpZiAobiA8IHRoaXMuY291bnQoY29sbGVjdGlvbikgJiYgbiA+PSAwKSB7XG4gICAgICAgIHJldHVybiBjb2xsZWN0aW9uW25dO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdvdXQgb2YgYm91bmRzIGVycm9yJyk7XG4gICAgICB9XG4gICAgfVxuXG4gICAgdGhyb3cgbmV3IEVycm9yKCdjb2xsZWN0aW9uIGlzIG5vdCBhbiBFbnVtZXJhYmxlJyk7XG4gIH0sXG5cbiAgZmlsdGVyOiBmdW5jdGlvbiAoY29sbGVjdGlvbiwgZnVuKSB7XG4gICAgbGV0IHJlc3VsdCA9IFtdO1xuXG4gICAgZm9yIChsZXQgZWxlbSBvZiBjb2xsZWN0aW9uKSB7XG4gICAgICBpZiAoZnVuKGVsZW0pKSB7XG4gICAgICAgIHJlc3VsdC5wdXNoKGVsZW0pO1xuICAgICAgfVxuICAgIH1cblxuICAgIHJldHVybiByZXN1bHQ7XG4gIH0sXG5cbiAgZmlsdGVyX21hcDogZnVuY3Rpb24gKGNvbGxlY3Rpb24sIGZpbHRlciwgbWFwcGVyKSB7XG4gICAgcmV0dXJuIEVudW0ubWFwKEVudW0uZmlsdGVyKGNvbGxlY3Rpb24sIGZpbHRlciksIG1hcHBlcik7XG4gIH0sXG5cbiAgZmluZDogZnVuY3Rpb24gKGNvbGxlY3Rpb24sIGlmX25vbmUgPSBudWxsLCBmdW4pIHtcbiAgICBmb3IgKGxldCBlbGVtIG9mIGNvbGxlY3Rpb24pIHtcbiAgICAgIGlmIChmdW4oZWxlbSkpIHtcbiAgICAgICAgcmV0dXJuIGVsZW07XG4gICAgICB9XG4gICAgfVxuXG4gICAgcmV0dXJuIGlmX25vbmU7XG4gIH0sXG5cbiAgaW50bzogZnVuY3Rpb24gKGNvbGxlY3Rpb24sIGxpc3QpIHtcbiAgICByZXR1cm4gbGlzdC5jb25jYXQoY29sbGVjdGlvbik7XG4gIH0sXG5cbiAgbWFwOiBmdW5jdGlvbiAoY29sbGVjdGlvbiwgZnVuKSB7XG4gICAgbGV0IHJlc3VsdCA9IFtdO1xuXG4gICAgZm9yIChsZXQgZWxlbSBvZiBjb2xsZWN0aW9uKSB7XG4gICAgICByZXN1bHQucHVzaChmdW4oZWxlbSkpO1xuICAgIH1cblxuICAgIHJldHVybiByZXN1bHQ7XG4gIH0sXG5cbiAgbWFwX3JlZHVjZTogZnVuY3Rpb24gKGNvbGxlY3Rpb24sIGFjYywgZnVuKSB7XG4gICAgbGV0IG1hcHBlZCA9IExpc3QkMSgpO1xuICAgIGxldCB0aGVfYWNjID0gYWNjO1xuXG4gICAgZm9yICh2YXIgaSA9IDA7IGkgPCB0aGlzLmNvdW50KGNvbGxlY3Rpb24pOyBpKyspIHtcbiAgICAgIGxldCB0dXBsZSA9IGZ1bihjb2xsZWN0aW9uW2ldLCB0aGVfYWNjKTtcblxuICAgICAgdGhlX2FjYyA9IHR1cGxlLmdldCgxKTtcbiAgICAgIG1hcHBlZCA9IExpc3QkMSguLi5tYXBwZWQuY29uY2F0KFt0dXBsZS5nZXQoMCldKSk7XG4gICAgfVxuXG4gICAgcmV0dXJuIG5ldyBUdXBsZShtYXBwZWQsIHRoZV9hY2MpO1xuICB9LFxuXG4gIG1lbWJlcl9fcW1hcmtfXzogZnVuY3Rpb24gKGNvbGxlY3Rpb24sIHZhbHVlKSB7XG4gICAgcmV0dXJuIGNvbGxlY3Rpb24uaW5jbHVkZXModmFsdWUpO1xuICB9LFxuXG4gIHJlZHVjZTogZnVuY3Rpb24gKGNvbGxlY3Rpb24sIGFjYywgZnVuKSB7XG4gICAgbGV0IHRoZV9hY2MgPSBhY2M7XG5cbiAgICBmb3IgKHZhciBpID0gMDsgaSA8IHRoaXMuY291bnQoY29sbGVjdGlvbik7IGkrKykge1xuICAgICAgbGV0IHR1cGxlID0gZnVuKGNvbGxlY3Rpb25baV0sIHRoZV9hY2MpO1xuXG4gICAgICB0aGVfYWNjID0gdHVwbGUuZ2V0KDEpO1xuICAgIH1cblxuICAgIHJldHVybiB0aGVfYWNjO1xuICB9LFxuXG4gIHRha2U6IGZ1bmN0aW9uIChjb2xsZWN0aW9uLCBjb3VudCkge1xuICAgIHJldHVybiBjb2xsZWN0aW9uLnNsaWNlKDAsIGNvdW50KTtcbiAgfSxcblxuICB0YWtlX2V2ZXJ5OiBmdW5jdGlvbiAoY29sbGVjdGlvbiwgbnRoKSB7XG4gICAgbGV0IHJlc3VsdCA9IFtdO1xuICAgIGxldCBpbmRleCA9IDA7XG5cbiAgICBmb3IgKGxldCBlbGVtIG9mIGNvbGxlY3Rpb24pIHtcbiAgICAgIGlmIChpbmRleCAlIG50aCA9PT0gMCkge1xuICAgICAgICByZXN1bHQucHVzaChlbGVtKTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICByZXR1cm4gTGlzdCQxKC4uLnJlc3VsdCk7XG4gIH0sXG5cbiAgdGFrZV93aGlsZTogZnVuY3Rpb24gKGNvbGxlY3Rpb24sIGZ1bikge1xuICAgIGxldCBjb3VudCA9IDA7XG5cbiAgICBmb3IgKGxldCBlbGVtIG9mIGNvbGxlY3Rpb24pIHtcbiAgICAgIGlmIChmdW4oZWxlbSkpIHtcbiAgICAgICAgY291bnQgPSBjb3VudCArIDE7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBicmVhaztcbiAgICAgIH1cbiAgICB9XG5cbiAgICByZXR1cm4gY29sbGVjdGlvbi5zbGljZSgwLCBjb3VudCk7XG4gIH0sXG5cbiAgdG9fbGlzdDogZnVuY3Rpb24gKGNvbGxlY3Rpb24pIHtcbiAgICByZXR1cm4gY29sbGVjdGlvbjtcbiAgfVxufTtcblxubGV0IFNwZWNpYWxGb3JtcyQxID0ge1xuXG4gIGF0b206IGZ1bmN0aW9uIChfdmFsdWUpIHtcbiAgICByZXR1cm4gU3ltYm9sLmZvcihfdmFsdWUpO1xuICB9LFxuXG4gIGxpc3Q6IGZ1bmN0aW9uICguLi5hcmdzKSB7XG4gICAgcmV0dXJuIE9iamVjdC5mcmVlemUoYXJncyk7XG4gIH0sXG5cbiAgYml0c3RyaW5nOiBmdW5jdGlvbiAoLi4uYXJncykge1xuICAgIHJldHVybiBuZXcgQml0U3RyaW5nKC4uLmFyZ3MpO1xuICB9LFxuXG4gIGJvdW5kOiBmdW5jdGlvbiAoX3Zhcikge1xuICAgIHJldHVybiBQYXR0ZXJucy5ib3VuZChfdmFyKTtcbiAgfSxcblxuICBfY2FzZTogZnVuY3Rpb24gKGNvbmRpdGlvbiwgY2xhdXNlcykge1xuICAgIHJldHVybiBQYXR0ZXJucy5kZWZtYXRjaCguLi5jbGF1c2VzKShjb25kaXRpb24pO1xuICB9LFxuXG4gIGNvbmQ6IGZ1bmN0aW9uIChjbGF1c2VzKSB7XG4gICAgZm9yIChsZXQgY2xhdXNlIG9mIGNsYXVzZXMpIHtcbiAgICAgIGlmIChjbGF1c2VbMF0pIHtcbiAgICAgICAgcmV0dXJuIGNsYXVzZVsxXSgpO1xuICAgICAgfVxuICAgIH1cblxuICAgIHRocm93IG5ldyBFcnJvcigpO1xuICB9LFxuXG4gIGZuOiBmdW5jdGlvbiAoY2xhdXNlcykge1xuICAgIHJldHVybiBQYXR0ZXJucy5kZWZtYXRjaChjbGF1c2VzKTtcbiAgfSxcblxuICBtYXA6IGZ1bmN0aW9uIChvYmopIHtcbiAgICByZXR1cm4gT2JqZWN0LmZyZWV6ZShvYmopO1xuICB9LFxuXG4gIG1hcF91cGRhdGU6IGZ1bmN0aW9uIChtYXAsIHZhbHVlcykge1xuICAgIHJldHVybiBPYmplY3QuZnJlZXplKE9iamVjdC5hc3NpZ24oT2JqZWN0LmNyZWF0ZShtYXAuY29uc3RydWN0b3IucHJvdG90eXBlKSwgbWFwLCB2YWx1ZXMpKTtcbiAgfSxcblxuICBfZm9yOiBmdW5jdGlvbiAoY29sbGVjdGlvbnMsIGZ1biwgZmlsdGVyID0gKCkgPT4gdHJ1ZSwgaW50byA9IFtdLCBwcmV2aW91c1ZhbHVlcyA9IFtdKSB7XG4gICAgbGV0IHBhdHRlcm4gPSBjb2xsZWN0aW9uc1swXVswXTtcbiAgICBsZXQgY29sbGVjdGlvbiA9IGNvbGxlY3Rpb25zWzBdWzFdO1xuXG4gICAgaWYgKGNvbGxlY3Rpb25zLmxlbmd0aCA9PT0gMSkge1xuXG4gICAgICBmb3IgKGxldCBlbGVtIG9mIGNvbGxlY3Rpb24pIHtcbiAgICAgICAgbGV0IHIgPSBQYXR0ZXJucy5tYXRjaF9ub190aHJvdyhwYXR0ZXJuLCBlbGVtKTtcbiAgICAgICAgbGV0IGFyZ3MgPSBwcmV2aW91c1ZhbHVlcy5jb25jYXQocik7XG5cbiAgICAgICAgaWYgKHIgJiYgZmlsdGVyLmFwcGx5KHRoaXMsIGFyZ3MpKSB7XG4gICAgICAgICAgaW50byA9IEVudW0uaW50byhbZnVuLmFwcGx5KHRoaXMsIGFyZ3MpXSwgaW50byk7XG4gICAgICAgIH1cbiAgICAgIH1cblxuICAgICAgcmV0dXJuIGludG87XG4gICAgfSBlbHNlIHtcbiAgICAgIGxldCBfaW50byA9IFtdO1xuXG4gICAgICBmb3IgKGxldCBlbGVtIG9mIGNvbGxlY3Rpb24pIHtcbiAgICAgICAgbGV0IHIgPSBQYXR0ZXJucy5tYXRjaF9ub190aHJvdyhwYXR0ZXJuLCBlbGVtKTtcbiAgICAgICAgaWYgKHIpIHtcbiAgICAgICAgICBfaW50byA9IEVudW0uaW50byh0aGlzLl9mb3IoY29sbGVjdGlvbnMuc2xpY2UoMSksIGZ1biwgZmlsdGVyLCBfaW50bywgcHJldmlvdXNWYWx1ZXMuY29uY2F0KHIpKSwgaW50byk7XG4gICAgICAgIH1cbiAgICAgIH1cblxuICAgICAgcmV0dXJuIF9pbnRvO1xuICAgIH1cbiAgfSxcblxuICByZWNlaXZlOiBmdW5jdGlvbiAocmVjZWl2ZV9mdW4sIHRpbWVvdXRfaW5fbXMgPSBudWxsLCB0aW1lb3V0X2ZuID0gdGltZSA9PiB0cnVlKSB7XG4gICAgaWYgKHRpbWVvdXRfaW5fbXMgPT0gbnVsbCB8fCB0aW1lb3V0X2luX21zID09PSBTeXN0ZW0uZm9yKCdpbmZpbml0eScpKSB7XG4gICAgICB3aGlsZSAodHJ1ZSkge1xuICAgICAgICBpZiAoc2VsZi5tYWlsYm94Lmxlbmd0aCAhPT0gMCkge1xuICAgICAgICAgIGxldCBtZXNzYWdlID0gc2VsZi5tYWlsYm94WzBdO1xuICAgICAgICAgIHNlbGYubWFpbGJveCA9IHNlbGYubWFpbGJveC5zbGljZSgxKTtcbiAgICAgICAgICByZXR1cm4gcmVjZWl2ZV9mdW4obWVzc2FnZSk7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9IGVsc2UgaWYgKHRpbWVvdXRfaW5fbXMgPT09IDApIHtcbiAgICAgIGlmIChzZWxmLm1haWxib3gubGVuZ3RoICE9PSAwKSB7XG4gICAgICAgIGxldCBtZXNzYWdlID0gc2VsZi5tYWlsYm94WzBdO1xuICAgICAgICBzZWxmLm1haWxib3ggPSBzZWxmLm1haWxib3guc2xpY2UoMSk7XG4gICAgICAgIHJldHVybiByZWNlaXZlX2Z1bihtZXNzYWdlKTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHJldHVybiBudWxsO1xuICAgICAgfVxuICAgIH0gZWxzZSB7XG4gICAgICBsZXQgbm93ID0gRGF0ZS5ub3coKTtcbiAgICAgIHdoaWxlIChEYXRlLm5vdygpIDwgbm93ICsgdGltZW91dF9pbl9tcykge1xuICAgICAgICBpZiAoc2VsZi5tYWlsYm94Lmxlbmd0aCAhPT0gMCkge1xuICAgICAgICAgIGxldCBtZXNzYWdlID0gc2VsZi5tYWlsYm94WzBdO1xuICAgICAgICAgIHNlbGYubWFpbGJveCA9IHNlbGYubWFpbGJveC5zbGljZSgxKTtcbiAgICAgICAgICByZXR1cm4gcmVjZWl2ZV9mdW4obWVzc2FnZSk7XG4gICAgICAgIH1cbiAgICAgIH1cblxuICAgICAgcmV0dXJuIHRpbWVvdXRfZm4odGltZW91dF9pbl9tcyk7XG4gICAgfVxuICB9LFxuXG4gIHR1cGxlOiBmdW5jdGlvbiAoLi4uYXJncykge1xuICAgIHJldHVybiBuZXcgVHVwbGUoLi4uYXJncyk7XG4gIH0sXG5cbiAgX3RyeTogZnVuY3Rpb24gKGRvX2Z1biwgcmVzY3VlX2Z1bmN0aW9uLCBjYXRjaF9mdW4sIGVsc2VfZnVuY3Rpb24sIGFmdGVyX2Z1bmN0aW9uKSB7XG4gICAgbGV0IHJlc3VsdCA9IG51bGw7XG5cbiAgICB0cnkge1xuICAgICAgcmVzdWx0ID0gZG9fZnVuKCk7XG4gICAgfSBjYXRjaCAoZSkge1xuICAgICAgbGV0IGV4X3Jlc3VsdCA9IG51bGw7XG5cbiAgICAgIGlmIChyZXNjdWVfZnVuY3Rpb24pIHtcbiAgICAgICAgdHJ5IHtcbiAgICAgICAgICBleF9yZXN1bHQgPSByZXNjdWVfZnVuY3Rpb24oZSk7XG4gICAgICAgICAgcmV0dXJuIGV4X3Jlc3VsdDtcbiAgICAgICAgfSBjYXRjaCAoZXgpIHtcbiAgICAgICAgICBpZiAoZXggaW5zdGFuY2VvZiBQYXR0ZXJucy5NYXRjaEVycm9yKSB7XG4gICAgICAgICAgICB0aHJvdyBleDtcbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgIH1cblxuICAgICAgaWYgKGNhdGNoX2Z1bikge1xuICAgICAgICB0cnkge1xuICAgICAgICAgIGV4X3Jlc3VsdCA9IGNhdGNoX2Z1bihlKTtcbiAgICAgICAgICByZXR1cm4gZXhfcmVzdWx0O1xuICAgICAgICB9IGNhdGNoIChleCkge1xuICAgICAgICAgIGlmIChleCBpbnN0YW5jZW9mIFBhdHRlcm5zLk1hdGNoRXJyb3IpIHtcbiAgICAgICAgICAgIHRocm93IGV4O1xuICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgfVxuXG4gICAgICB0aHJvdyBlO1xuICAgIH0gZmluYWxseSB7XG4gICAgICBpZiAoYWZ0ZXJfZnVuY3Rpb24pIHtcbiAgICAgICAgYWZ0ZXJfZnVuY3Rpb24oKTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICBpZiAoZWxzZV9mdW5jdGlvbikge1xuICAgICAgdHJ5IHtcbiAgICAgICAgcmV0dXJuIGVsc2VfZnVuY3Rpb24ocmVzdWx0KTtcbiAgICAgIH0gY2F0Y2ggKGV4KSB7XG4gICAgICAgIGlmIChleCBpbnN0YW5jZW9mIFBhdHRlcm5zLk1hdGNoRXJyb3IpIHtcbiAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ05vIE1hdGNoIEZvdW5kIGluIEVsc2UnKTtcbiAgICAgICAgfVxuXG4gICAgICAgIHRocm93IGV4O1xuICAgICAgfVxuICAgIH0gZWxzZSB7XG4gICAgICByZXR1cm4gcmVzdWx0O1xuICAgIH1cbiAgfVxuXG59O1xuXG5mdW5jdGlvbiB0bChsaXN0KSB7XG4gIHJldHVybiBTcGVjaWFsRm9ybXMkMS5saXN0KC4uLmxpc3Quc2xpY2UoMSkpO1xufVxuXG5mdW5jdGlvbiBoZChsaXN0KSB7XG4gIHJldHVybiBsaXN0WzBdO1xufVxuXG5mdW5jdGlvbiBpc19uaWwoeCkge1xuICByZXR1cm4geCA9PT0gbnVsbDtcbn1cblxuZnVuY3Rpb24gaXNfYXRvbSh4KSB7XG4gIHJldHVybiB0eXBlb2YgeCA9PT0gJ3N5bWJvbCc7XG59XG5cbmZ1bmN0aW9uIGlzX2JpbmFyeSh4KSB7XG4gIHJldHVybiB0eXBlb2YgeCA9PT0gJ3N0cmluZycgfHwgeCBpbnN0YW5jZW9mIFN0cmluZztcbn1cblxuZnVuY3Rpb24gaXNfYm9vbGVhbih4KSB7XG4gIHJldHVybiB0eXBlb2YgeCA9PT0gJ2Jvb2xlYW4nIHx8IHggaW5zdGFuY2VvZiBCb29sZWFuO1xufVxuXG5mdW5jdGlvbiBpc19mdW5jdGlvbih4LCBhcml0eSA9IC0xKSB7XG4gIHJldHVybiB0eXBlb2YgeCA9PT0gJ2Z1bmN0aW9uJyB8fCB4IGluc3RhbmNlb2YgRnVuY3Rpb247XG59XG5cbmZ1bmN0aW9uIGlzX2Zsb2F0KHgpIHtcbiAgcmV0dXJuIGlzX251bWJlcih4KSAmJiAhTnVtYmVyLmlzSW50ZWdlcih4KTtcbn1cblxuZnVuY3Rpb24gaXNfaW50ZWdlcih4KSB7XG4gIHJldHVybiBOdW1iZXIuaXNJbnRlZ2VyKHgpO1xufVxuXG5mdW5jdGlvbiBpc19saXN0KHgpIHtcbiAgcmV0dXJuIHggaW5zdGFuY2VvZiBBcnJheTtcbn1cblxuZnVuY3Rpb24gaXNfbWFwKHgpIHtcbiAgcmV0dXJuIHR5cGVvZiB4ID09PSAnb2JqZWN0JyB8fCB4IGluc3RhbmNlb2YgT2JqZWN0O1xufVxuXG5mdW5jdGlvbiBpc19udW1iZXIoeCkge1xuICByZXR1cm4gdHlwZW9mIHggPT09ICdudW1iZXInO1xufVxuXG5mdW5jdGlvbiBpc190dXBsZSh4KSB7XG4gIHJldHVybiB4IGluc3RhbmNlb2YgVHVwbGU7XG59XG5cbmZ1bmN0aW9uIGxlbmd0aCh4KSB7XG4gIHJldHVybiB4Lmxlbmd0aDtcbn1cblxuZnVuY3Rpb24gaXNfcGlkKHgpIHtcbiAgcmV0dXJuIHggaW5zdGFuY2VvZiBQSUQ7XG59XG5cbmZ1bmN0aW9uIGlzX3BvcnQoeCkge1xuICByZXR1cm4gZmFsc2U7XG59XG5cbmZ1bmN0aW9uIGlzX3JlZmVyZW5jZSh4KSB7XG4gIHJldHVybiBmYWxzZTtcbn1cblxuZnVuY3Rpb24gaXNfYml0c3RyaW5nKHgpIHtcbiAgcmV0dXJuIGlzX2JpbmFyeSh4KSB8fCB4IGluc3RhbmNlb2YgQml0U3RyaW5nO1xufVxuXG5mdW5jdGlvbiBfX2luX18obGVmdCwgcmlnaHQpIHtcbiAgZm9yIChsZXQgeCBvZiByaWdodCkge1xuICAgIGlmIChtYXRjaF9fcW1hcmtfXyhsZWZ0LCB4KSkge1xuICAgICAgcmV0dXJuIHRydWU7XG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIGZhbHNlO1xufVxuXG5mdW5jdGlvbiBhYnMobnVtYmVyKSB7XG4gIHJldHVybiBNYXRoLmFicyhudW1iZXIpO1xufVxuXG5mdW5jdGlvbiByb3VuZChudW1iZXIpIHtcbiAgcmV0dXJuIE1hdGgucm91bmQobnVtYmVyKTtcbn1cblxuZnVuY3Rpb24gZWxlbSh0dXBsZSwgaW5kZXgpIHtcbiAgaWYgKGlzX2xpc3QodHVwbGUpKSB7XG4gICAgcmV0dXJuIHR1cGxlW2luZGV4XTtcbiAgfVxuXG4gIHJldHVybiB0dXBsZS5nZXQoaW5kZXgpO1xufVxuXG5mdW5jdGlvbiByZW0obGVmdCwgcmlnaHQpIHtcbiAgcmV0dXJuIGxlZnQgJSByaWdodDtcbn1cblxuZnVuY3Rpb24gZGl2KGxlZnQsIHJpZ2h0KSB7XG4gIHJldHVybiBsZWZ0IC8gcmlnaHQ7XG59XG5cbmZ1bmN0aW9uIGFuZChsZWZ0LCByaWdodCkge1xuICByZXR1cm4gbGVmdCAmJiByaWdodDtcbn1cblxuZnVuY3Rpb24gb3IobGVmdCwgcmlnaHQpIHtcbiAgcmV0dXJuIGxlZnQgfHwgcmlnaHQ7XG59XG5cbmZ1bmN0aW9uIG5vdChhcmcpIHtcbiAgcmV0dXJuICFhcmc7XG59XG5cbmZ1bmN0aW9uIGFwcGx5KC4uLmFyZ3MpIHtcbiAgaWYgKGFyZ3MubGVuZ3RoID09PSAzKSB7XG4gICAgbGV0IG1vZCA9IGFyZ3NbMF07XG4gICAgbGV0IGZ1bmMgPSBhcmdzWzFdO1xuICAgIGxldCBmdW5jX2FyZ3MgPSBhcmdzWzJdO1xuICAgIHJldHVybiBtb2RbZnVuY10uYXBwbHkobnVsbCwgZnVuY19hcmdzKTtcbiAgfSBlbHNlIHtcbiAgICBsZXQgZnVuYyA9IGFyZ3NbMF07XG4gICAgbGV0IGZ1bmNfYXJncyA9IGFyZ3NbMV07XG5cbiAgICByZXR1cm4gZnVuYy5hcHBseShudWxsLCBmdW5jX2FyZ3MpO1xuICB9XG59XG5cbmZ1bmN0aW9uIHRvX3N0cmluZyhhcmcpIHtcbiAgaWYgKGlzX3R1cGxlKGFyZykpIHtcbiAgICByZXR1cm4gYXJnLnRvU3RyaW5nKCk7XG4gIH1cblxuICByZXR1cm4gYXJnLnRvU3RyaW5nKCk7XG59XG5cbmZ1bmN0aW9uIG1hdGNoX19xbWFya19fKHBhdHRlcm4sIGV4cHIsIGd1YXJkID0gKCkgPT4gdHJ1ZSkge1xuICByZXR1cm4gUGF0dGVybnMubWF0Y2hfbm9fdGhyb3cocGF0dGVybiwgZXhwciwgZ3VhcmQpICE9IG51bGw7XG59XG5cbnZhciBLZXJuZWwgPSB7XG4gIFNwZWNpYWxGb3JtczogU3BlY2lhbEZvcm1zJDEsXG4gIHRsLFxuICBoZCxcbiAgaXNfbmlsLFxuICBpc19hdG9tLFxuICBpc19iaW5hcnksXG4gIGlzX2Jvb2xlYW4sXG4gIGlzX2Z1bmN0aW9uLFxuICBpc19mbG9hdCxcbiAgaXNfaW50ZWdlcixcbiAgaXNfbGlzdCxcbiAgaXNfbWFwLFxuICBpc19udW1iZXIsXG4gIGlzX3R1cGxlLFxuICBsZW5ndGgsXG4gIGlzX3BpZCxcbiAgaXNfcG9ydCxcbiAgaXNfcmVmZXJlbmNlLFxuICBpc19iaXRzdHJpbmcsXG4gIGluOiBfX2luX18sXG4gIGFicyxcbiAgcm91bmQsXG4gIGVsZW0sXG4gIHJlbSxcbiAgZGl2LFxuICBhbmQsXG4gIG9yLFxuICBub3QsXG4gIGFwcGx5LFxuICB0b19zdHJpbmcsXG4gIG1hdGNoX19xbWFya19fXG59O1xuXG5sZXQgTGlzdCA9IHt9O1xuXG5MaXN0LmRlbGV0ZSA9IGZ1bmN0aW9uIChsaXN0LCBpdGVtKSB7XG4gIGxldCBuZXdfdmFsdWUgPSBbXTtcbiAgbGV0IHZhbHVlX2ZvdW5kID0gZmFsc2U7XG5cbiAgZm9yIChsZXQgeCBvZiBsaXN0KSB7XG4gICAgaWYgKHggPT09IGl0ZW0gJiYgdmFsdWVfZm91bmQgIT09IGZhbHNlKSB7XG4gICAgICBuZXdfdmFsdWUucHVzaCh4KTtcbiAgICAgIHZhbHVlX2ZvdW5kID0gdHJ1ZTtcbiAgICB9IGVsc2UgaWYgKHggIT09IGl0ZW0pIHtcbiAgICAgIG5ld192YWx1ZS5wdXNoKHgpO1xuICAgIH1cbiAgfVxuXG4gIHJldHVybiBMaXN0JDEoLi4ubmV3X3ZhbHVlKTtcbn07XG5cbkxpc3QuZGVsZXRlX2F0ID0gZnVuY3Rpb24gKGxpc3QsIGluZGV4KSB7XG4gIGxldCBuZXdfdmFsdWUgPSBbXTtcblxuICBmb3IgKGxldCBpID0gMDsgaSA8IGxpc3QubGVuZ3RoOyBpKyspIHtcbiAgICBpZiAoaSAhPT0gaW5kZXgpIHtcbiAgICAgIG5ld192YWx1ZS5wdXNoKGxpc3RbaV0pO1xuICAgIH1cbiAgfVxuXG4gIHJldHVybiBMaXN0JDEoLi4ubmV3X3ZhbHVlKTtcbn07XG5cbkxpc3QuZHVwbGljYXRlID0gZnVuY3Rpb24gKGVsZW0sIG4pIHtcbiAgbGV0IG5ld192YWx1ZSA9IFtdO1xuXG4gIGZvciAodmFyIGkgPSAwOyBpIDwgbjsgaSsrKSB7XG4gICAgbmV3X3ZhbHVlLnB1c2goZWxlbSk7XG4gIH1cblxuICByZXR1cm4gTGlzdCQxKC4uLm5ld192YWx1ZSk7XG59O1xuXG5MaXN0LmZpcnN0ID0gZnVuY3Rpb24gKGxpc3QpIHtcbiAgcmV0dXJuIGxpc3RbMF07XG59O1xuXG5MaXN0LmZsYXR0ZW4gPSBmdW5jdGlvbiAobGlzdCwgdGFpbCA9IExpc3QkMSgpKSB7XG4gIGxldCBuZXdfdmFsdWUgPSBbXTtcblxuICBmb3IgKGxldCB4IG9mIGxpc3QpIHtcbiAgICBpZiAoS2VybmVsLmlzX2xpc3QoeCkpIHtcbiAgICAgIG5ld192YWx1ZSA9IG5ld192YWx1ZS5jb25jYXQoTGlzdC5mbGF0dGVuKHgpKTtcbiAgICB9IGVsc2Uge1xuICAgICAgbmV3X3ZhbHVlLnB1c2goeCk7XG4gICAgfVxuICB9XG5cbiAgbmV3X3ZhbHVlID0gbmV3X3ZhbHVlLmNvbmNhdCh0YWlsKTtcblxuICByZXR1cm4gTGlzdCQxKC4uLm5ld192YWx1ZSk7XG59O1xuXG5MaXN0LmZvbGRsID0gZnVuY3Rpb24gKGxpc3QsIGFjYywgZnVuYykge1xuICByZXR1cm4gbGlzdC5yZWR1Y2UoZnVuYywgYWNjKTtcbn07XG5cbkxpc3QuZm9sZHIgPSBmdW5jdGlvbiAobGlzdCwgYWNjLCBmdW5jKSB7XG4gIGxldCBuZXdfYWNjID0gYWNjO1xuXG4gIGZvciAodmFyIGkgPSBsaXN0Lmxlbmd0aCAtIDE7IGkgPj0gMDsgaS0tKSB7XG4gICAgbmV3X2FjYyA9IGZ1bmMobGlzdFtpXSwgbmV3X2FjYyk7XG4gIH1cblxuICByZXR1cm4gbmV3X2FjYztcbn07XG5cbkxpc3QuaW5zZXJ0X2F0ID0gZnVuY3Rpb24gKGxpc3QsIGluZGV4LCB2YWx1ZSkge1xuICBsZXQgbmV3X3ZhbHVlID0gW107XG5cbiAgZm9yIChsZXQgaSA9IDA7IGkgPCBsaXN0Lmxlbmd0aDsgaSsrKSB7XG4gICAgaWYgKGkgPT09IGluZGV4KSB7XG4gICAgICBuZXdfdmFsdWUucHVzaCh2YWx1ZSk7XG4gICAgICBuZXdfdmFsdWUucHVzaChsaXN0W2ldKTtcbiAgICB9IGVsc2Uge1xuICAgICAgbmV3X3ZhbHVlLnB1c2gobGlzdFtpXSk7XG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIExpc3QkMSguLi5uZXdfdmFsdWUpO1xufTtcblxuTGlzdC5rZXlkZWxldGUgPSBmdW5jdGlvbiAobGlzdCwga2V5LCBwb3NpdGlvbikge1xuICBsZXQgbmV3X2xpc3QgPSBbXTtcblxuICBmb3IgKGxldCBpID0gMDsgaSA8IGxpc3QubGVuZ3RoOyBpKyspIHtcbiAgICBpZiAoIUtlcm5lbC5tYXRjaF9fcW1hcmtfXyhsaXN0W2ldW3Bvc2l0aW9uXSwga2V5KSkge1xuICAgICAgbmV3X2xpc3QucHVzaChsaXN0W2ldKTtcbiAgICB9XG4gIH1cblxuICByZXR1cm4gTGlzdCQxKC4uLm5ld19saXN0KTtcbn07XG5cbkxpc3Qua2V5ZmluZCA9IGZ1bmN0aW9uIChsaXN0LCBrZXksIHBvc2l0aW9uLCBfZGVmYXVsdCA9IG51bGwpIHtcblxuICBmb3IgKGxldCBpID0gMDsgaSA8IGxpc3QubGVuZ3RoOyBpKyspIHtcbiAgICBpZiAoS2VybmVsLm1hdGNoX19xbWFya19fKGxpc3RbaV1bcG9zaXRpb25dLCBrZXkpKSB7XG4gICAgICByZXR1cm4gbGlzdFtpXTtcbiAgICB9XG4gIH1cblxuICByZXR1cm4gX2RlZmF1bHQ7XG59O1xuXG5MaXN0LmtleW1lbWJlcl9fcW1hcmtfXyA9IGZ1bmN0aW9uIChsaXN0LCBrZXksIHBvc2l0aW9uKSB7XG5cbiAgZm9yIChsZXQgaSA9IDA7IGkgPCBsaXN0Lmxlbmd0aDsgaSsrKSB7XG4gICAgaWYgKEtlcm5lbC5tYXRjaF9fcW1hcmtfXyhsaXN0W2ldW3Bvc2l0aW9uXSwga2V5KSkge1xuICAgICAgcmV0dXJuIHRydWU7XG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIGZhbHNlO1xufTtcblxuTGlzdC5rZXlyZXBsYWNlID0gZnVuY3Rpb24gKGxpc3QsIGtleSwgcG9zaXRpb24sIG5ld190dXBsZSkge1xuICBsZXQgbmV3X2xpc3QgPSBbXTtcblxuICBmb3IgKGxldCBpID0gMDsgaSA8IGxpc3QubGVuZ3RoOyBpKyspIHtcbiAgICBpZiAoIUtlcm5lbC5tYXRjaF9fcW1hcmtfXyhsaXN0W2ldW3Bvc2l0aW9uXSwga2V5KSkge1xuICAgICAgbmV3X2xpc3QucHVzaChsaXN0W2ldKTtcbiAgICB9IGVsc2Uge1xuICAgICAgbmV3X2xpc3QucHVzaChuZXdfdHVwbGUpO1xuICAgIH1cbiAgfVxuXG4gIHJldHVybiBMaXN0JDEoLi4ubmV3X2xpc3QpO1xufTtcblxuTGlzdC5rZXlzb3J0ID0gZnVuY3Rpb24gKGxpc3QsIHBvc2l0aW9uKSB7XG4gIGxldCBuZXdfbGlzdCA9IGxpc3Q7XG5cbiAgbmV3X2xpc3Quc29ydChmdW5jdGlvbiAoYSwgYikge1xuICAgIGlmIChwb3NpdGlvbiA9PT0gMCkge1xuICAgICAgaWYgKGFbcG9zaXRpb25dLnZhbHVlIDwgYltwb3NpdGlvbl0udmFsdWUpIHtcbiAgICAgICAgcmV0dXJuIC0xO1xuICAgICAgfVxuXG4gICAgICBpZiAoYVtwb3NpdGlvbl0udmFsdWUgPiBiW3Bvc2l0aW9uXS52YWx1ZSkge1xuICAgICAgICByZXR1cm4gMTtcbiAgICAgIH1cblxuICAgICAgcmV0dXJuIDA7XG4gICAgfSBlbHNlIHtcbiAgICAgIGlmIChhW3Bvc2l0aW9uXSA8IGJbcG9zaXRpb25dKSB7XG4gICAgICAgIHJldHVybiAtMTtcbiAgICAgIH1cblxuICAgICAgaWYgKGFbcG9zaXRpb25dID4gYltwb3NpdGlvbl0pIHtcbiAgICAgICAgcmV0dXJuIDE7XG4gICAgICB9XG5cbiAgICAgIHJldHVybiAwO1xuICAgIH1cbiAgfSk7XG5cbiAgcmV0dXJuIExpc3QkMSguLi5uZXdfbGlzdCk7XG59O1xuXG5MaXN0LmtleXN0b3JlID0gZnVuY3Rpb24gKGxpc3QsIGtleSwgcG9zaXRpb24sIG5ld190dXBsZSkge1xuICBsZXQgbmV3X2xpc3QgPSBbXTtcbiAgbGV0IHJlcGxhY2VkID0gZmFsc2U7XG5cbiAgZm9yIChsZXQgaSA9IDA7IGkgPCBsaXN0Lmxlbmd0aDsgaSsrKSB7XG4gICAgaWYgKCFLZXJuZWwubWF0Y2hfX3FtYXJrX18obGlzdFtpXVtwb3NpdGlvbl0sIGtleSkpIHtcbiAgICAgIG5ld19saXN0LnB1c2gobGlzdFtpXSk7XG4gICAgfSBlbHNlIHtcbiAgICAgIG5ld19saXN0LnB1c2gobmV3X3R1cGxlKTtcbiAgICAgIHJlcGxhY2VkID0gdHJ1ZTtcbiAgICB9XG4gIH1cblxuICBpZiAoIXJlcGxhY2VkKSB7XG4gICAgbmV3X2xpc3QucHVzaChuZXdfdHVwbGUpO1xuICB9XG5cbiAgcmV0dXJuIExpc3QkMSguLi5uZXdfbGlzdCk7XG59O1xuXG5MaXN0Lmxhc3QgPSBmdW5jdGlvbiAobGlzdCkge1xuICByZXR1cm4gbGlzdFtsaXN0Lmxlbmd0aCAtIDFdO1xufTtcblxuTGlzdC5yZXBsYWNlX2F0ID0gZnVuY3Rpb24gKGxpc3QsIGluZGV4LCB2YWx1ZSkge1xuICBsZXQgbmV3X3ZhbHVlID0gW107XG5cbiAgZm9yIChsZXQgaSA9IDA7IGkgPCBsaXN0Lmxlbmd0aDsgaSsrKSB7XG4gICAgaWYgKGkgPT09IGluZGV4KSB7XG4gICAgICBuZXdfdmFsdWUucHVzaCh2YWx1ZSk7XG4gICAgfSBlbHNlIHtcbiAgICAgIG5ld192YWx1ZS5wdXNoKGxpc3RbaV0pO1xuICAgIH1cbiAgfVxuXG4gIHJldHVybiBMaXN0JDEoLi4ubmV3X3ZhbHVlKTtcbn07XG5cbkxpc3QudXBkYXRlX2F0ID0gZnVuY3Rpb24gKGxpc3QsIGluZGV4LCBmdW4pIHtcbiAgbGV0IG5ld192YWx1ZSA9IFtdO1xuXG4gIGZvciAobGV0IGkgPSAwOyBpIDwgbGlzdC5jb3VudCgpOyBpKyspIHtcbiAgICBpZiAoaSA9PT0gaW5kZXgpIHtcbiAgICAgIG5ld192YWx1ZS5wdXNoKGZ1bihsaXN0LmdldChpKSkpO1xuICAgIH0gZWxzZSB7XG4gICAgICBuZXdfdmFsdWUucHVzaChsaXN0LmdldChpKSk7XG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIG5ld192YWx1ZTtcbn07XG5cbkxpc3Qud3JhcCA9IGZ1bmN0aW9uIChsaXN0KSB7XG4gIGlmIChLZXJuZWwuaXNfbGlzdChsaXN0KSkge1xuICAgIHJldHVybiBsaXN0O1xuICB9IGVsc2UgaWYgKGxpc3QgPT0gbnVsbCkge1xuICAgIHJldHVybiBMaXN0JDEoKTtcbiAgfSBlbHNlIHtcbiAgICByZXR1cm4gTGlzdCQxKGxpc3QpO1xuICB9XG59O1xuXG5MaXN0LnppcCA9IGZ1bmN0aW9uIChsaXN0X29mX2xpc3RzKSB7XG4gIGlmIChsaXN0X29mX2xpc3RzLmxlbmd0aCA9PT0gMCkge1xuICAgIHJldHVybiBMaXN0JDEoKTtcbiAgfVxuXG4gIGxldCBuZXdfdmFsdWUgPSBbXTtcbiAgbGV0IHNtYWxsZXN0X2xlbmd0aCA9IGxpc3Rfb2ZfbGlzdHNbMF07XG5cbiAgZm9yIChsZXQgeCBvZiBsaXN0X29mX2xpc3RzKSB7XG4gICAgaWYgKHgubGVuZ3RoIDwgc21hbGxlc3RfbGVuZ3RoKSB7XG4gICAgICBzbWFsbGVzdF9sZW5ndGggPSB4Lmxlbmd0aDtcbiAgICB9XG4gIH1cblxuICBmb3IgKGxldCBpID0gMDsgaSA8IHNtYWxsZXN0X2xlbmd0aDsgaSsrKSB7XG4gICAgbGV0IGN1cnJlbnRfdmFsdWUgPSBbXTtcbiAgICBmb3IgKGxldCBqID0gMDsgaiA8IGxpc3Rfb2ZfbGlzdHMubGVuZ3RoOyBqKyspIHtcbiAgICAgIGN1cnJlbnRfdmFsdWUucHVzaChsaXN0X29mX2xpc3RzW2pdW2ldKTtcbiAgICB9XG5cbiAgICBuZXdfdmFsdWUucHVzaChuZXcgVHVwbGUoLi4uY3VycmVudF92YWx1ZSkpO1xuICB9XG5cbiAgcmV0dXJuIExpc3QkMSguLi5uZXdfdmFsdWUpO1xufTtcblxuTGlzdC50b190dXBsZSA9IGZ1bmN0aW9uIChsaXN0KSB7XG4gIHJldHVybiBuZXcgVHVwbGUoLi4ubGlzdCk7XG59O1xuXG5MaXN0LmFwcGVuZCA9IGZ1bmN0aW9uIChsaXN0LCB2YWx1ZSkge1xuICByZXR1cm4gTGlzdCQxKC4uLmxpc3QuY29uY2F0KFt2YWx1ZV0pKTtcbn07XG5cbkxpc3QucHJlcGVuZCA9IGZ1bmN0aW9uIChsaXN0LCB2YWx1ZSkge1xuICByZXR1cm4gTGlzdCQxKC4uLlt2YWx1ZV0uY29uY2F0KGxpc3QpKTtcbn07XG5cbkxpc3QuY29uY2F0ID0gZnVuY3Rpb24gKGxlZnQsIHJpZ2h0KSB7XG4gIHJldHVybiBsZWZ0LmNvbmNhdChyaWdodCk7XG59O1xuXG5sZXQgS2V5d29yZCA9IHt9O1xuXG5LZXl3b3JkLmhhc19rZXlfX3FtYXJrX18gPSBmdW5jdGlvbiAoa2V5d29yZHMsIGtleSkge1xuICBmb3IgKGxldCBrZXl3b3JkIG9mIGtleXdvcmRzKSB7XG4gICAgaWYgKEtlcm5lbC5lbGVtKGtleXdvcmQsIDApID09IGtleSkge1xuICAgICAgcmV0dXJuIHRydWU7XG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIGZhbHNlO1xufTtcblxuS2V5d29yZC5nZXQgPSBmdW5jdGlvbiAoa2V5d29yZHMsIGtleSwgdGhlX2RlZmF1bHQgPSBudWxsKSB7XG4gIGZvciAobGV0IGtleXdvcmQgb2Yga2V5d29yZHMpIHtcbiAgICBpZiAoS2VybmVsLmVsZW0oa2V5d29yZCwgMCkgPT0ga2V5KSB7XG4gICAgICByZXR1cm4gS2VybmVsLmVsZW0oa2V5d29yZCwgMSk7XG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIHRoZV9kZWZhdWx0O1xufTtcblxuZnVuY3Rpb24gYm5vdChleHByKSB7XG4gIHJldHVybiB+ZXhwcjtcbn1cblxuZnVuY3Rpb24gYmFuZChsZWZ0LCByaWdodCkge1xuICByZXR1cm4gbGVmdCAmIHJpZ2h0O1xufVxuXG5mdW5jdGlvbiBib3IobGVmdCwgcmlnaHQpIHtcbiAgcmV0dXJuIGxlZnQgfCByaWdodDtcbn1cblxuZnVuY3Rpb24gYnNsKGxlZnQsIHJpZ2h0KSB7XG4gIHJldHVybiBsZWZ0IDw8IHJpZ2h0O1xufVxuXG5mdW5jdGlvbiBic3IobGVmdCwgcmlnaHQpIHtcbiAgcmV0dXJuIGxlZnQgPj4gcmlnaHQ7XG59XG5cbmZ1bmN0aW9uIGJ4b3IobGVmdCwgcmlnaHQpIHtcbiAgcmV0dXJuIGxlZnQgXiByaWdodDtcbn1cblxudmFyIGJpdHdpc2UgPSB7XG4gIGJub3QsXG4gIGJhbmQsXG4gIGJvcixcbiAgYnNsLFxuICBic3IsXG4gIGJ4b3Jcbn07XG5cbmZ1bmN0aW9uIF9fbmV3X18oKSB7XG4gIHJldHVybiBTcGVjaWFsRm9ybXMkMS5tYXAoe30pO1xufVxuXG5mdW5jdGlvbiBrZXlzKG1hcCkge1xuICByZXR1cm4gRnVuY3Rpb25zLmdldF9vYmplY3Rfa2V5cyhtYXApO1xufVxuXG5mdW5jdGlvbiBzaXplKG1hcCkge1xuICByZXR1cm4ga2V5cyhtYXApLmxlbmd0aDtcbn1cblxuZnVuY3Rpb24gdG9fbGlzdChtYXApIHtcbiAgbGV0IG1hcF9rZXlzID0ga2V5cyhtYXApO1xuICBsZXQgbGlzdCA9IFtdO1xuXG4gIGZvciAobGV0IGtleSBvZiBtYXBfa2V5cykge1xuICAgIGxpc3QucHVzaChuZXcgVHVwbGUoa2V5LCBtYXBba2V5XSkpO1xuICB9XG5cbiAgcmV0dXJuIExpc3QkMSguLi5saXN0KTtcbn1cblxuZnVuY3Rpb24gdmFsdWVzKG1hcCkge1xuICBsZXQgbWFwX2tleXMgPSBrZXlzKG1hcCk7XG4gIGxldCBsaXN0ID0gW107XG5cbiAgZm9yIChsZXQga2V5IG9mIG1hcF9rZXlzKSB7XG4gICAgbGlzdC5wdXNoKG1hcFtrZXldKTtcbiAgfVxuXG4gIHJldHVybiBMaXN0JDEoLi4ubGlzdCk7XG59XG5cbmZ1bmN0aW9uIGZyb21fc3RydWN0KHN0cnVjdCkge1xuICBsZXQgbWFwID0gT2JqZWN0LmFzc2lnbih7fSwgc3RydWN0KTtcbiAgZGVsZXRlIG1hcFtTeW1ib2wuZm9yKCdfX3N0cnVjdF9fJyldO1xuXG4gIHJldHVybiBTcGVjaWFsRm9ybXMkMS5tYXAobWFwKTtcbn1cblxuZnVuY3Rpb24gX19kZWxldGVfXyhtYXAsIGtleSkge1xuICBsZXQgbmV3X21hcCA9IE9iamVjdC5hc3NpZ24oe30sIG1hcCk7XG5cbiAgZGVsZXRlIG5ld19tYXBba2V5XTtcblxuICByZXR1cm4gU3BlY2lhbEZvcm1zJDEubWFwKG5ld19tYXApO1xufVxuXG5mdW5jdGlvbiBlcXVhbF9fcW1hcmtfXyhtYXAxLCBtYXAyKSB7XG4gIHJldHVybiBtYXAxID09PSBtYXAyO1xufVxuXG5mdW5jdGlvbiBmZXRjaF9fZW1hcmtfXyhtYXAsIGtleSkge1xuICBpZiAoa2V5IGluIG1hcCkge1xuICAgIHJldHVybiBtYXBba2V5XTtcbiAgfVxuXG4gIHRocm93IG5ldyBFcnJvcignS2V5IG5vdCBmb3VuZC4nKTtcbn1cblxuZnVuY3Rpb24gZmV0Y2gobWFwLCBrZXkpIHtcbiAgaWYgKGtleSBpbiBtYXApIHtcbiAgICByZXR1cm4gbmV3IFR1cGxlKFN5bWJvbC5mb3IoJ29rJyksIG1hcFtrZXldKTtcbiAgfVxuXG4gIHJldHVybiBTeW1ib2wuZm9yKCdlcnJvcicpO1xufVxuXG5mdW5jdGlvbiBoYXNfa2V5X19xbWFya19fKG1hcCwga2V5KSB7XG4gIHJldHVybiBrZXkgaW4gbWFwO1xufVxuXG5mdW5jdGlvbiBzcGxpdChtYXAsIGtleXMpIHtcbiAgbGV0IHNwbGl0MSA9IHt9O1xuICBsZXQgc3BsaXQyID0ge307XG5cbiAgZm9yIChsZXQga2V5IG9mIEZ1bmN0aW9ucy5nZXRfb2JqZWN0X2tleXMobWFwKSkge1xuICAgIGlmIChrZXlzLmluZGV4T2Yoa2V5KSA+IC0xKSB7XG4gICAgICBzcGxpdDFba2V5XSA9IG1hcFtrZXldO1xuICAgIH0gZWxzZSB7XG4gICAgICBzcGxpdDJba2V5XSA9IG1hcFtrZXldO1xuICAgIH1cbiAgfVxuXG4gIHJldHVybiBuZXcgVHVwbGUoU3BlY2lhbEZvcm1zJDEubWFwKHNwbGl0MSksIFNwZWNpYWxGb3JtcyQxLm1hcChzcGxpdDIpKTtcbn1cblxuZnVuY3Rpb24gdGFrZShtYXAsIGtleXMpIHtcbiAgbGV0IHNwbGl0MSA9IHt9O1xuXG4gIGZvciAobGV0IGtleSBvZiBGdW5jdGlvbnMuZ2V0X29iamVjdF9rZXlzKG1hcCkpIHtcbiAgICBpZiAoa2V5cy5pbmRleE9mKGtleSkgPiAtMSkge1xuICAgICAgc3BsaXQxW2tleV0gPSBtYXBba2V5XTtcbiAgICB9XG4gIH1cblxuICByZXR1cm4gU3BlY2lhbEZvcm1zJDEubWFwKHNwbGl0MSk7XG59XG5cbmZ1bmN0aW9uIGRyb3AobWFwLCBrZXlzKSB7XG4gIGxldCBzcGxpdDEgPSB7fTtcblxuICBmb3IgKGxldCBrZXkgb2YgRnVuY3Rpb25zLmdldF9vYmplY3Rfa2V5cyhtYXApKSB7XG4gICAgaWYgKGtleXMuaW5kZXhPZihrZXkpID09PSAtMSkge1xuICAgICAgc3BsaXQxW2tleV0gPSBtYXBba2V5XTtcbiAgICB9XG4gIH1cblxuICByZXR1cm4gU3BlY2lhbEZvcm1zJDEubWFwKHNwbGl0MSk7XG59XG5cbmZ1bmN0aW9uIHB1dF9uZXcobWFwLCBrZXksIHZhbHVlKSB7XG4gIGlmIChrZXkgaW4gbWFwKSB7XG4gICAgcmV0dXJuIG1hcDtcbiAgfVxuXG4gIGxldCBuZXdfbWFwID0gT2JqZWN0LmFzc2lnbih7fSwgbWFwKTtcbiAgbmV3X21hcFtrZXldID0gdmFsdWU7XG5cbiAgcmV0dXJuIFNwZWNpYWxGb3JtcyQxLm1hcChuZXdfbWFwKTtcbn1cblxuZnVuY3Rpb24gcHV0X25ld19sYXp5KG1hcCwga2V5LCBmdW4pIHtcbiAgaWYgKGtleSBpbiBtYXApIHtcbiAgICByZXR1cm4gbWFwO1xuICB9XG5cbiAgbGV0IG5ld19tYXAgPSBPYmplY3QuYXNzaWduKHt9LCBtYXApO1xuICBuZXdfbWFwW2tleV0gPSBmdW4oKTtcblxuICByZXR1cm4gU3BlY2lhbEZvcm1zJDEubWFwKG5ld19tYXApO1xufVxuXG5mdW5jdGlvbiBnZXRfYW5kX3VwZGF0ZShtYXAsIGtleSwgZnVuKSB7XG4gIGlmIChrZXkgaW4gbWFwKSB7XG4gICAgcmV0dXJuIG1hcDtcbiAgfVxuXG4gIGxldCBuZXdfbWFwID0gT2JqZWN0LmFzc2lnbih7fSwgbWFwKTtcbiAgbmV3X21hcFtrZXldID0gZnVuKG1hcFtrZXldKTtcblxuICByZXR1cm4gU3BlY2lhbEZvcm1zJDEubWFwKG5ld19tYXApO1xufVxuXG5mdW5jdGlvbiBwb3BfbGF6eShtYXAsIGtleSwgZnVuKSB7XG4gIGlmICgha2V5IGluIG1hcCkge1xuICAgIHJldHVybiBuZXcgVHVwbGUoZnVuKCksIG1hcCk7XG4gIH1cblxuICBsZXQgbmV3X21hcCA9IE9iamVjdC5hc3NpZ24oe30sIG1hcCk7XG4gIGxldCB2YWx1ZSA9IGZ1bihuZXdfbWFwW2tleV0pO1xuICBkZWxldGUgbmV3X21hcFtrZXldO1xuXG4gIHJldHVybiBuZXcgVHVwbGUodmFsdWUsIG5ld19tYXApO1xufVxuXG5mdW5jdGlvbiBwb3AobWFwLCBrZXksIF9kZWZhdWx0ID0gbnVsbCkge1xuICBpZiAoIWtleSBpbiBtYXApIHtcbiAgICByZXR1cm4gbmV3IFR1cGxlKF9kZWZhdWx0LCBtYXApO1xuICB9XG5cbiAgbGV0IG5ld19tYXAgPSBPYmplY3QuYXNzaWduKHt9LCBtYXApO1xuICBsZXQgdmFsdWUgPSBuZXdfbWFwW2tleV07XG4gIGRlbGV0ZSBuZXdfbWFwW2tleV07XG5cbiAgcmV0dXJuIG5ldyBUdXBsZSh2YWx1ZSwgbmV3X21hcCk7XG59XG5cbmZ1bmN0aW9uIGdldF9sYXp5KG1hcCwga2V5LCBmdW4pIHtcbiAgaWYgKCFrZXkgaW4gbWFwKSB7XG4gICAgcmV0dXJuIGZ1bigpO1xuICB9XG5cbiAgcmV0dXJuIGZ1bihtYXBba2V5XSk7XG59XG5cbmZ1bmN0aW9uIGdldChtYXAsIGtleSwgX2RlZmF1bHQgPSBudWxsKSB7XG4gIGlmICgha2V5IGluIG1hcCkge1xuICAgIHJldHVybiBfZGVmYXVsdDtcbiAgfVxuXG4gIHJldHVybiBtYXBba2V5XTtcbn1cblxuZnVuY3Rpb24gcHV0KG1hcCwga2V5LCB2YWwpIHtcbiAgbGV0IG5ld19tYXAgPSBPYmplY3Qoe30sIG1hcCk7XG4gIG5ld19tYXBba2V5XSA9IHZhbDtcblxuICByZXR1cm4gU3BlY2lhbEZvcm1zJDEubWFwKG5ld19tYXApO1xufVxuXG5mdW5jdGlvbiB1cGRhdGVfX2VtYXJrX18obWFwLCBrZXksIGZ1bikge1xuICBpZiAoIWtleSBpbiBtYXApIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoJ0tleSBub3QgZm91bmQnKTtcbiAgfVxuXG4gIGxldCBuZXdfbWFwID0gT2JqZWN0KHt9LCBtYXApO1xuICBuZXdfbWFwW2tleV0gPSBmdW4obWFwW2tleV0pO1xuXG4gIHJldHVybiBTcGVjaWFsRm9ybXMkMS5tYXAobmV3X21hcCk7XG59XG5cbmZ1bmN0aW9uIHVwZGF0ZShtYXAsIGtleSwgaW5pdGlhbCwgZnVuKSB7XG4gIGxldCBuZXdfbWFwID0gT2JqZWN0KHt9LCBtYXApO1xuXG4gIGlmICgha2V5IGluIG1hcCkge1xuICAgIG5ld19tYXBba2V5XSA9IGluaXRpYWw7XG4gIH0gZWxzZSB7XG4gICAgbmV3X21hcFtrZXldID0gZnVuKG1hcFtrZXldKTtcbiAgfVxuXG4gIHJldHVybiBTcGVjaWFsRm9ybXMkMS5tYXAobmV3X21hcCk7XG59XG5cbnZhciBtYXAgPSB7XG4gIG5ldzogX19uZXdfXyxcbiAga2V5cyxcbiAgc2l6ZSxcbiAgdG9fbGlzdCxcbiAgdmFsdWVzLFxuICBmcm9tX3N0cnVjdCxcbiAgZGVsZXRlOiBfX2RlbGV0ZV9fLFxuICBkcm9wLFxuICBlcXVhbF9fcW1hcmtfXyxcbiAgZmV0Y2hfX2VtYXJrX18sXG4gIGZldGNoLFxuICBoYXNfa2V5X19xbWFya19fLFxuICBzcGxpdCxcbiAgdGFrZSxcbiAgcHV0X25ldyxcbiAgcHV0X25ld19sYXp5LFxuICBnZXRfYW5kX3VwZGF0ZSxcbiAgcG9wX2xhenksXG4gIHBvcCxcbiAgZ2V0X2xhenksXG4gIGdldCxcbiAgcHV0LFxuICB1cGRhdGVfX2VtYXJrX18sXG4gIHVwZGF0ZVxufTtcblxuZnVuY3Rpb24gX19uZXdfXyQxKCkge1xuICByZXR1cm4gU3BlY2lhbEZvcm1zJDEubWFwKHsgW1N5bWJvbC5mb3IoJ19fc3RydWN0X18nKV06IFN5bWJvbC5mb3IoJ01hcFNldCcpLCBzZXQ6IExpc3QkMSgpIH0pO1xufVxuXG5mdW5jdGlvbiBzaXplJDEobWFwKSB7XG4gIHJldHVybiBtYXAuc2V0Lmxlbmd0aDtcbn1cblxuZnVuY3Rpb24gdG9fbGlzdCQxKG1hcCkge1xuICByZXR1cm4gbWFwLnNldDtcbn1cblxuZnVuY3Rpb24gX19kZWxldGVfXyQxKHNldCwgdGVybSkge1xuICBsZXQgbmV3X2xpc3QgPSBMaXN0LmRlbGV0ZShzZXQuc2V0LCB0ZXJtKTtcblxuICBsZXQgbmV3X21hcCA9IE9iamVjdC5hc3NpZ24oe30sIHNldCk7XG4gIG5ld19tYXAuc2V0ID0gbmV3X2xpc3Q7XG4gIHJldHVybiBTcGVjaWFsRm9ybXMkMS5tYXAobmV3X21hcCk7XG59XG5cbmZ1bmN0aW9uIHB1dCQxKHNldCwgdGVybSkge1xuICBpZiAoc2V0LnNldC5pbmRleE9mKHRlcm0pID09PSAtMSkge1xuICAgIGxldCBuZXdfbGlzdCA9IExpc3QuYXBwZW5kKHNldC5zZXQsIHRlcm0pO1xuXG4gICAgbGV0IG5ld19tYXAgPSBPYmplY3QuYXNzaWduKHt9LCBzZXQpO1xuICAgIG5ld19tYXAuc2V0ID0gbmV3X2xpc3Q7XG4gICAgcmV0dXJuIFNwZWNpYWxGb3JtcyQxLm1hcChuZXdfbWFwKTtcbiAgfVxuXG4gIHJldHVybiBzZXQ7XG59XG5cbmZ1bmN0aW9uIGRpZmZlcmVuY2Uoc2V0MSwgc2V0Mikge1xuICBsZXQgbmV3X21hcCA9IE9iamVjdC5hc3NpZ24oe30sIHNldDEpO1xuXG4gIGZvciAobGV0IHZhbCBvZiBzZXQxLnNldCkge1xuICAgIGlmIChtZW1iZXJfX3FtYXJrX18oc2V0MiwgdmFsKSkge1xuICAgICAgbmV3X21hcC5zZXQgPSBMaXN0LmRlbGV0ZShuZXdfbWFwLnNldCwgdmFsKTtcbiAgICB9XG4gIH1cblxuICByZXR1cm4gU3BlY2lhbEZvcm1zJDEubWFwKG5ld19tYXApO1xufVxuXG5mdW5jdGlvbiBpbnRlcnNlY3Rpb24oc2V0MSwgc2V0Mikge1xuICBsZXQgbmV3X21hcCA9IE9iamVjdC5hc3NpZ24oe30sIHNldDEpO1xuXG4gIGZvciAobGV0IHZhbCBvZiBzZXQxLnNldCkge1xuICAgIGlmICghbWVtYmVyX19xbWFya19fKHNldDIsIHZhbCkpIHtcbiAgICAgIG5ld19tYXAuc2V0ID0gTGlzdC5kZWxldGUobmV3X21hcC5zZXQsIHZhbCk7XG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIFNwZWNpYWxGb3JtcyQxLm1hcChuZXdfbWFwKTtcbn1cblxuZnVuY3Rpb24gdW5pb24oc2V0MSwgc2V0Mikge1xuICBsZXQgbmV3X21hcCA9IHNldDE7XG5cbiAgZm9yIChsZXQgdmFsIG9mIHNldDIuc2V0KSB7XG4gICAgbmV3X21hcCA9IHB1dCQxKG5ld19tYXAsIHZhbCk7XG4gIH1cblxuICByZXR1cm4gU3BlY2lhbEZvcm1zJDEubWFwKG5ld19tYXApO1xufVxuXG5mdW5jdGlvbiBkaXNqb2luX19xbWFya19fKHNldDEsIHNldDIpIHtcbiAgZm9yIChsZXQgdmFsIG9mIHNldDEuc2V0KSB7XG4gICAgaWYgKG1lbWJlcl9fcW1hcmtfXyhzZXQyLCB2YWwpKSB7XG4gICAgICByZXR1cm4gZmFsc2U7XG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIHRydWU7XG59XG5cbmZ1bmN0aW9uIG1lbWJlcl9fcW1hcmtfXyhzZXQsIHZhbHVlKSB7XG4gIHJldHVybiBzZXQuc2V0LmluZGV4T2YodmFsdWUpID49IDA7XG59XG5cbmZ1bmN0aW9uIGVxdWFsX19xbWFya19fJDEoc2V0MSwgc2V0Mikge1xuICByZXR1cm4gc2V0MS5zZXQgPT09IHNldDIuc2V0O1xufVxuXG5mdW5jdGlvbiBzdWJzZXRfX3FtYXJrX18oc2V0MSwgc2V0Mikge1xuICBmb3IgKGxldCB2YWwgb2Ygc2V0MS5zZXQpIHtcbiAgICBpZiAoIW1lbWJlcl9fcW1hcmtfXyhzZXQyLCB2YWwpKSB7XG4gICAgICByZXR1cm4gZmFsc2U7XG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIHRydWU7XG59XG5cbnZhciBtYXBfc2V0ID0ge1xuICBuZXc6IF9fbmV3X18kMSxcbiAgc2l6ZTogc2l6ZSQxLFxuICB0b19saXN0OiB0b19saXN0JDEsXG4gIGRpc2pvaW5fX3FtYXJrX18sXG4gIGRlbGV0ZTogX19kZWxldGVfXyQxLFxuICBzdWJzZXRfX3FtYXJrX18sXG4gIGVxdWFsX19xbWFya19fOiBlcXVhbF9fcW1hcmtfXyQxLFxuICBtZW1iZXJfX3FtYXJrX18sXG4gIHB1dDogcHV0JDEsXG4gIHVuaW9uLFxuICBpbnRlcnNlY3Rpb24sXG4gIGRpZmZlcmVuY2Vcbn07XG5cbmxldCBWaXJ0dWFsRE9NID0gKGZ1bmN0aW9uIChlKSB7XG4gICAgcmV0dXJuIGUoKTtcbn0pKGZ1bmN0aW9uICgpIHtcbiAgICB2YXIgZGVmaW5lLCBtb2R1bGUsIGV4cG9ydHM7XG4gICAgcmV0dXJuIChmdW5jdGlvbiBlKHQsIG4sIHIpIHtcbiAgICAgICAgZnVuY3Rpb24gcyhvLCB1KSB7XG4gICAgICAgICAgICBpZiAoIW5bb10pIHtcbiAgICAgICAgICAgICAgICBpZiAoIXRbb10pIHtcbiAgICAgICAgICAgICAgICAgICAgdmFyIGEgPSB0eXBlb2YgcmVxdWlyZSA9PSBcImZ1bmN0aW9uXCIgJiYgcmVxdWlyZTtcbiAgICAgICAgICAgICAgICAgICAgaWYgKCF1ICYmIGEpIHJldHVybiBhKG8sICEwKTtcbiAgICAgICAgICAgICAgICAgICAgaWYgKGkpIHJldHVybiBpKG8sICEwKTtcbiAgICAgICAgICAgICAgICAgICAgdmFyIGYgPSBuZXcgRXJyb3IoXCJDYW5ub3QgZmluZCBtb2R1bGUgJ1wiICsgbyArIFwiJ1wiKTtcbiAgICAgICAgICAgICAgICAgICAgdGhyb3cgKGYuY29kZSA9IFwiTU9EVUxFX05PVF9GT1VORFwiLCBmKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgdmFyIGwgPSBuW29dID0ge1xuICAgICAgICAgICAgICAgICAgICBleHBvcnRzOiB7fVxuICAgICAgICAgICAgICAgIH07XG4gICAgICAgICAgICAgICAgdFtvXVswXS5jYWxsKGwuZXhwb3J0cywgZnVuY3Rpb24gKGUpIHtcbiAgICAgICAgICAgICAgICAgICAgdmFyIG4gPSB0W29dWzFdW2VdO1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gcyhuID8gbiA6IGUpO1xuICAgICAgICAgICAgICAgIH0sIGwsIGwuZXhwb3J0cywgZSwgdCwgbiwgcik7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXR1cm4gbltvXS5leHBvcnRzO1xuICAgICAgICB9XG4gICAgICAgIHZhciBpID0gdHlwZW9mIHJlcXVpcmUgPT0gXCJmdW5jdGlvblwiICYmIHJlcXVpcmU7XG4gICAgICAgIGZvciAodmFyIG8gPSAwOyBvIDwgci5sZW5ndGg7IG8rKykgcyhyW29dKTtcbiAgICAgICAgcmV0dXJuIHM7XG4gICAgfSkoe1xuICAgICAgICAxOiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge1xuXG4gICAgICAgICAgICB2YXIgY3JlYXRlRWxlbWVudCA9IHJlcXVpcmUoXCIuL3Zkb20vY3JlYXRlLWVsZW1lbnQuanNcIik7XG5cbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gY3JlYXRlRWxlbWVudDtcbiAgICAgICAgfSwgeyBcIi4vdmRvbS9jcmVhdGUtZWxlbWVudC5qc1wiOiAxNSB9XSwgMjogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHtcbiAgICAgICAgICAgIHZhciBkaWZmID0gcmVxdWlyZShcIi4vdnRyZWUvZGlmZi5qc1wiKTtcblxuICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBkaWZmO1xuICAgICAgICB9LCB7IFwiLi92dHJlZS9kaWZmLmpzXCI6IDM1IH1dLCAzOiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge1xuICAgICAgICAgICAgdmFyIGggPSByZXF1aXJlKFwiLi92aXJ0dWFsLWh5cGVyc2NyaXB0L2luZGV4LmpzXCIpO1xuXG4gICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IGg7XG4gICAgICAgIH0sIHsgXCIuL3ZpcnR1YWwtaHlwZXJzY3JpcHQvaW5kZXguanNcIjogMjIgfV0sIDQ6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICB2YXIgZGlmZiA9IHJlcXVpcmUoXCIuL2RpZmYuanNcIik7XG4gICAgICAgICAgICB2YXIgcGF0Y2ggPSByZXF1aXJlKFwiLi9wYXRjaC5qc1wiKTtcbiAgICAgICAgICAgIHZhciBoID0gcmVxdWlyZShcIi4vaC5qc1wiKTtcbiAgICAgICAgICAgIHZhciBjcmVhdGUgPSByZXF1aXJlKFwiLi9jcmVhdGUtZWxlbWVudC5qc1wiKTtcbiAgICAgICAgICAgIHZhciBWTm9kZSA9IHJlcXVpcmUoXCIuL3Zub2RlL3Zub2RlLmpzXCIpO1xuICAgICAgICAgICAgdmFyIFZUZXh0ID0gcmVxdWlyZShcIi4vdm5vZGUvdnRleHQuanNcIik7XG5cbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0ge1xuICAgICAgICAgICAgICAgIGRpZmY6IGRpZmYsXG4gICAgICAgICAgICAgICAgcGF0Y2g6IHBhdGNoLFxuICAgICAgICAgICAgICAgIGg6IGgsXG4gICAgICAgICAgICAgICAgY3JlYXRlOiBjcmVhdGUsXG4gICAgICAgICAgICAgICAgVk5vZGU6IFZOb2RlLFxuICAgICAgICAgICAgICAgIFZUZXh0OiBWVGV4dFxuICAgICAgICAgICAgfTtcbiAgICAgICAgfSwgeyBcIi4vY3JlYXRlLWVsZW1lbnQuanNcIjogMSwgXCIuL2RpZmYuanNcIjogMiwgXCIuL2guanNcIjogMywgXCIuL3BhdGNoLmpzXCI6IDEzLCBcIi4vdm5vZGUvdm5vZGUuanNcIjogMzEsIFwiLi92bm9kZS92dGV4dC5qc1wiOiAzMyB9XSwgNTogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHtcbiAgICAgICAgICAgIC8qIVxuICAgICAgICAgICAgICogQ3Jvc3MtQnJvd3NlciBTcGxpdCAxLjEuMVxuICAgICAgICAgICAgICogQ29weXJpZ2h0IDIwMDctMjAxMiBTdGV2ZW4gTGV2aXRoYW4gPHN0ZXZlbmxldml0aGFuLmNvbT5cbiAgICAgICAgICAgICAqIEF2YWlsYWJsZSB1bmRlciB0aGUgTUlUIExpY2Vuc2VcbiAgICAgICAgICAgICAqIEVDTUFTY3JpcHQgY29tcGxpYW50LCB1bmlmb3JtIGNyb3NzLWJyb3dzZXIgc3BsaXQgbWV0aG9kXG4gICAgICAgICAgICAgKi9cblxuICAgICAgICAgICAgLyoqXG4gICAgICAgICAgICAgKiBTcGxpdHMgYSBzdHJpbmcgaW50byBhbiBhcnJheSBvZiBzdHJpbmdzIHVzaW5nIGEgcmVnZXggb3Igc3RyaW5nIHNlcGFyYXRvci4gTWF0Y2hlcyBvZiB0aGVcbiAgICAgICAgICAgICAqIHNlcGFyYXRvciBhcmUgbm90IGluY2x1ZGVkIGluIHRoZSByZXN1bHQgYXJyYXkuIEhvd2V2ZXIsIGlmIGBzZXBhcmF0b3JgIGlzIGEgcmVnZXggdGhhdCBjb250YWluc1xuICAgICAgICAgICAgICogY2FwdHVyaW5nIGdyb3VwcywgYmFja3JlZmVyZW5jZXMgYXJlIHNwbGljZWQgaW50byB0aGUgcmVzdWx0IGVhY2ggdGltZSBgc2VwYXJhdG9yYCBpcyBtYXRjaGVkLlxuICAgICAgICAgICAgICogRml4ZXMgYnJvd3NlciBidWdzIGNvbXBhcmVkIHRvIHRoZSBuYXRpdmUgYFN0cmluZy5wcm90b3R5cGUuc3BsaXRgIGFuZCBjYW4gYmUgdXNlZCByZWxpYWJseVxuICAgICAgICAgICAgICogY3Jvc3MtYnJvd3Nlci5cbiAgICAgICAgICAgICAqIEBwYXJhbSB7U3RyaW5nfSBzdHIgU3RyaW5nIHRvIHNwbGl0LlxuICAgICAgICAgICAgICogQHBhcmFtIHtSZWdFeHB8U3RyaW5nfSBzZXBhcmF0b3IgUmVnZXggb3Igc3RyaW5nIHRvIHVzZSBmb3Igc2VwYXJhdGluZyB0aGUgc3RyaW5nLlxuICAgICAgICAgICAgICogQHBhcmFtIHtOdW1iZXJ9IFtsaW1pdF0gTWF4aW11bSBudW1iZXIgb2YgaXRlbXMgdG8gaW5jbHVkZSBpbiB0aGUgcmVzdWx0IGFycmF5LlxuICAgICAgICAgICAgICogQHJldHVybnMge0FycmF5fSBBcnJheSBvZiBzdWJzdHJpbmdzLlxuICAgICAgICAgICAgICogQGV4YW1wbGVcbiAgICAgICAgICAgICAqXG4gICAgICAgICAgICAgKiAvLyBCYXNpYyB1c2VcbiAgICAgICAgICAgICAqIHNwbGl0KCdhIGIgYyBkJywgJyAnKTtcbiAgICAgICAgICAgICAqIC8vIC0+IFsnYScsICdiJywgJ2MnLCAnZCddXG4gICAgICAgICAgICAgKlxuICAgICAgICAgICAgICogLy8gV2l0aCBsaW1pdFxuICAgICAgICAgICAgICogc3BsaXQoJ2EgYiBjIGQnLCAnICcsIDIpO1xuICAgICAgICAgICAgICogLy8gLT4gWydhJywgJ2InXVxuICAgICAgICAgICAgICpcbiAgICAgICAgICAgICAqIC8vIEJhY2tyZWZlcmVuY2VzIGluIHJlc3VsdCBhcnJheVxuICAgICAgICAgICAgICogc3BsaXQoJy4ud29yZDEgd29yZDIuLicsIC8oW2Etel0rKShcXGQrKS9pKTtcbiAgICAgICAgICAgICAqIC8vIC0+IFsnLi4nLCAnd29yZCcsICcxJywgJyAnLCAnd29yZCcsICcyJywgJy4uJ11cbiAgICAgICAgICAgICAqL1xuICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSAoZnVuY3Rpb24gc3BsaXQodW5kZWYpIHtcblxuICAgICAgICAgICAgICAgIHZhciBuYXRpdmVTcGxpdCA9IFN0cmluZy5wcm90b3R5cGUuc3BsaXQsXG4gICAgICAgICAgICAgICAgICAgIGNvbXBsaWFudEV4ZWNOcGNnID0gLygpPz8vLmV4ZWMoXCJcIilbMV0gPT09IHVuZGVmLFxuXG4gICAgICAgICAgICAgICAgLy8gTlBDRzogbm9ucGFydGljaXBhdGluZyBjYXB0dXJpbmcgZ3JvdXBcbiAgICAgICAgICAgICAgICBzZWxmO1xuXG4gICAgICAgICAgICAgICAgc2VsZiA9IGZ1bmN0aW9uIChzdHIsIHNlcGFyYXRvciwgbGltaXQpIHtcbiAgICAgICAgICAgICAgICAgICAgLy8gSWYgYHNlcGFyYXRvcmAgaXMgbm90IGEgcmVnZXgsIHVzZSBgbmF0aXZlU3BsaXRgXG4gICAgICAgICAgICAgICAgICAgIGlmIChPYmplY3QucHJvdG90eXBlLnRvU3RyaW5nLmNhbGwoc2VwYXJhdG9yKSAhPT0gXCJbb2JqZWN0IFJlZ0V4cF1cIikge1xuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIG5hdGl2ZVNwbGl0LmNhbGwoc3RyLCBzZXBhcmF0b3IsIGxpbWl0KTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB2YXIgb3V0cHV0ID0gW10sXG4gICAgICAgICAgICAgICAgICAgICAgICBmbGFncyA9IChzZXBhcmF0b3IuaWdub3JlQ2FzZSA/IFwiaVwiIDogXCJcIikgKyAoc2VwYXJhdG9yLm11bHRpbGluZSA/IFwibVwiIDogXCJcIikgKyAoc2VwYXJhdG9yLmV4dGVuZGVkID8gXCJ4XCIgOiBcIlwiKSArIChzZXBhcmF0b3Iuc3RpY2t5ID8gXCJ5XCIgOiBcIlwiKSxcblxuICAgICAgICAgICAgICAgICAgICAvLyBGaXJlZm94IDMrXG4gICAgICAgICAgICAgICAgICAgIGxhc3RMYXN0SW5kZXggPSAwLFxuXG4gICAgICAgICAgICAgICAgICAgIC8vIE1ha2UgYGdsb2JhbGAgYW5kIGF2b2lkIGBsYXN0SW5kZXhgIGlzc3VlcyBieSB3b3JraW5nIHdpdGggYSBjb3B5XG4gICAgICAgICAgICAgICAgICAgIHNlcGFyYXRvciA9IG5ldyBSZWdFeHAoc2VwYXJhdG9yLnNvdXJjZSwgZmxhZ3MgKyBcImdcIiksXG4gICAgICAgICAgICAgICAgICAgICAgICBzZXBhcmF0b3IyLFxuICAgICAgICAgICAgICAgICAgICAgICAgbWF0Y2gsXG4gICAgICAgICAgICAgICAgICAgICAgICBsYXN0SW5kZXgsXG4gICAgICAgICAgICAgICAgICAgICAgICBsYXN0TGVuZ3RoO1xuICAgICAgICAgICAgICAgICAgICBzdHIgKz0gXCJcIjsgLy8gVHlwZS1jb252ZXJ0XG4gICAgICAgICAgICAgICAgICAgIGlmICghY29tcGxpYW50RXhlY05wY2cpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIERvZXNuJ3QgbmVlZCBmbGFncyBneSwgYnV0IHRoZXkgZG9uJ3QgaHVydFxuICAgICAgICAgICAgICAgICAgICAgICAgc2VwYXJhdG9yMiA9IG5ldyBSZWdFeHAoXCJeXCIgKyBzZXBhcmF0b3Iuc291cmNlICsgXCIkKD8hXFxcXHMpXCIsIGZsYWdzKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAvKiBWYWx1ZXMgZm9yIGBsaW1pdGAsIHBlciB0aGUgc3BlYzpcbiAgICAgICAgICAgICAgICAgICAgICogSWYgdW5kZWZpbmVkOiA0Mjk0OTY3Mjk1IC8vIE1hdGgucG93KDIsIDMyKSAtIDFcbiAgICAgICAgICAgICAgICAgICAgICogSWYgMCwgSW5maW5pdHksIG9yIE5hTjogMFxuICAgICAgICAgICAgICAgICAgICAgKiBJZiBwb3NpdGl2ZSBudW1iZXI6IGxpbWl0ID0gTWF0aC5mbG9vcihsaW1pdCk7IGlmIChsaW1pdCA+IDQyOTQ5NjcyOTUpIGxpbWl0IC09IDQyOTQ5NjcyOTY7XG4gICAgICAgICAgICAgICAgICAgICAqIElmIG5lZ2F0aXZlIG51bWJlcjogNDI5NDk2NzI5NiAtIE1hdGguZmxvb3IoTWF0aC5hYnMobGltaXQpKVxuICAgICAgICAgICAgICAgICAgICAgKiBJZiBvdGhlcjogVHlwZS1jb252ZXJ0LCB0aGVuIHVzZSB0aGUgYWJvdmUgcnVsZXNcbiAgICAgICAgICAgICAgICAgICAgICovXG4gICAgICAgICAgICAgICAgICAgIGxpbWl0ID0gbGltaXQgPT09IHVuZGVmID8gLTEgPj4+IDAgOiAvLyBNYXRoLnBvdygyLCAzMikgLSAxXG4gICAgICAgICAgICAgICAgICAgIGxpbWl0ID4+PiAwOyAvLyBUb1VpbnQzMihsaW1pdClcbiAgICAgICAgICAgICAgICAgICAgd2hpbGUgKG1hdGNoID0gc2VwYXJhdG9yLmV4ZWMoc3RyKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgLy8gYHNlcGFyYXRvci5sYXN0SW5kZXhgIGlzIG5vdCByZWxpYWJsZSBjcm9zcy1icm93c2VyXG4gICAgICAgICAgICAgICAgICAgICAgICBsYXN0SW5kZXggPSBtYXRjaC5pbmRleCArIG1hdGNoWzBdLmxlbmd0aDtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChsYXN0SW5kZXggPiBsYXN0TGFzdEluZGV4KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgb3V0cHV0LnB1c2goc3RyLnNsaWNlKGxhc3RMYXN0SW5kZXgsIG1hdGNoLmluZGV4KSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gRml4IGJyb3dzZXJzIHdob3NlIGBleGVjYCBtZXRob2RzIGRvbid0IGNvbnNpc3RlbnRseSByZXR1cm4gYHVuZGVmaW5lZGAgZm9yXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gbm9ucGFydGljaXBhdGluZyBjYXB0dXJpbmcgZ3JvdXBzXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKCFjb21wbGlhbnRFeGVjTnBjZyAmJiBtYXRjaC5sZW5ndGggPiAxKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1hdGNoWzBdLnJlcGxhY2Uoc2VwYXJhdG9yMiwgZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZm9yICh2YXIgaSA9IDE7IGkgPCBhcmd1bWVudHMubGVuZ3RoIC0gMjsgaSsrKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGFyZ3VtZW50c1tpXSA9PT0gdW5kZWYpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbWF0Y2hbaV0gPSB1bmRlZjtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAobWF0Y2gubGVuZ3RoID4gMSAmJiBtYXRjaC5pbmRleCA8IHN0ci5sZW5ndGgpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgQXJyYXkucHJvdG90eXBlLnB1c2guYXBwbHkob3V0cHV0LCBtYXRjaC5zbGljZSgxKSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxhc3RMZW5ndGggPSBtYXRjaFswXS5sZW5ndGg7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgbGFzdExhc3RJbmRleCA9IGxhc3RJbmRleDtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAob3V0cHV0Lmxlbmd0aCA+PSBsaW1pdCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoc2VwYXJhdG9yLmxhc3RJbmRleCA9PT0gbWF0Y2guaW5kZXgpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBzZXBhcmF0b3IubGFzdEluZGV4Kys7IC8vIEF2b2lkIGFuIGluZmluaXRlIGxvb3BcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICBpZiAobGFzdExhc3RJbmRleCA9PT0gc3RyLmxlbmd0aCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGxhc3RMZW5ndGggfHwgIXNlcGFyYXRvci50ZXN0KFwiXCIpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgb3V0cHV0LnB1c2goXCJcIik7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBvdXRwdXQucHVzaChzdHIuc2xpY2UobGFzdExhc3RJbmRleCkpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBvdXRwdXQubGVuZ3RoID4gbGltaXQgPyBvdXRwdXQuc2xpY2UoMCwgbGltaXQpIDogb3V0cHV0O1xuICAgICAgICAgICAgICAgIH07XG5cbiAgICAgICAgICAgICAgICByZXR1cm4gc2VsZjtcbiAgICAgICAgICAgIH0pKCk7XG4gICAgICAgIH0sIHt9XSwgNjogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHt9LCB7fV0sIDc6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICBcInVzZSBzdHJpY3RcIjtcblxuICAgICAgICAgICAgdmFyIE9uZVZlcnNpb25Db25zdHJhaW50ID0gcmVxdWlyZShcImluZGl2aWR1YWwvb25lLXZlcnNpb25cIik7XG5cbiAgICAgICAgICAgIHZhciBNWV9WRVJTSU9OID0gXCI3XCI7XG4gICAgICAgICAgICBPbmVWZXJzaW9uQ29uc3RyYWludChcImV2LXN0b3JlXCIsIE1ZX1ZFUlNJT04pO1xuXG4gICAgICAgICAgICB2YXIgaGFzaEtleSA9IFwiX19FVl9TVE9SRV9LRVlAXCIgKyBNWV9WRVJTSU9OO1xuXG4gICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IEV2U3RvcmU7XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIEV2U3RvcmUoZWxlbSkge1xuICAgICAgICAgICAgICAgIHZhciBoYXNoID0gZWxlbVtoYXNoS2V5XTtcblxuICAgICAgICAgICAgICAgIGlmICghaGFzaCkge1xuICAgICAgICAgICAgICAgICAgICBoYXNoID0gZWxlbVtoYXNoS2V5XSA9IHt9O1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHJldHVybiBoYXNoO1xuICAgICAgICAgICAgfVxuICAgICAgICB9LCB7IFwiaW5kaXZpZHVhbC9vbmUtdmVyc2lvblwiOiA5IH1dLCA4OiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge1xuICAgICAgICAgICAgKGZ1bmN0aW9uIChnbG9iYWwpIHtcbiAgICAgICAgICAgICAgICBcInVzZSBzdHJpY3RcIjtcblxuICAgICAgICAgICAgICAgIC8qZ2xvYmFsIHdpbmRvdywgZ2xvYmFsKi9cblxuICAgICAgICAgICAgICAgIHZhciByb290ID0gdHlwZW9mIHdpbmRvdyAhPT0gXCJ1bmRlZmluZWRcIiA/IHdpbmRvdyA6IHR5cGVvZiBnbG9iYWwgIT09IFwidW5kZWZpbmVkXCIgPyBnbG9iYWwgOiB7fTtcblxuICAgICAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gSW5kaXZpZHVhbDtcblxuICAgICAgICAgICAgICAgIGZ1bmN0aW9uIEluZGl2aWR1YWwoa2V5LCB2YWx1ZSkge1xuICAgICAgICAgICAgICAgICAgICBpZiAoa2V5IGluIHJvb3QpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiByb290W2tleV07XG4gICAgICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgICAgICByb290W2tleV0gPSB2YWx1ZTtcblxuICAgICAgICAgICAgICAgICAgICByZXR1cm4gdmFsdWU7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSkuY2FsbCh0aGlzLCB0eXBlb2YgZ2xvYmFsICE9PSBcInVuZGVmaW5lZFwiID8gZ2xvYmFsIDogdHlwZW9mIHNlbGYgIT09IFwidW5kZWZpbmVkXCIgPyBzZWxmIDogdHlwZW9mIHdpbmRvdyAhPT0gXCJ1bmRlZmluZWRcIiA/IHdpbmRvdyA6IHt9KTtcbiAgICAgICAgfSwge31dLCA5OiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge1xuICAgICAgICAgICAgXCJ1c2Ugc3RyaWN0XCI7XG5cbiAgICAgICAgICAgIHZhciBJbmRpdmlkdWFsID0gcmVxdWlyZShcIi4vaW5kZXguanNcIik7XG5cbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gT25lVmVyc2lvbjtcblxuICAgICAgICAgICAgZnVuY3Rpb24gT25lVmVyc2lvbihtb2R1bGVOYW1lLCB2ZXJzaW9uLCBkZWZhdWx0VmFsdWUpIHtcbiAgICAgICAgICAgICAgICB2YXIga2V5ID0gXCJfX0lORElWSURVQUxfT05FX1ZFUlNJT05fXCIgKyBtb2R1bGVOYW1lO1xuICAgICAgICAgICAgICAgIHZhciBlbmZvcmNlS2V5ID0ga2V5ICsgXCJfRU5GT1JDRV9TSU5HTEVUT05cIjtcblxuICAgICAgICAgICAgICAgIHZhciB2ZXJzaW9uVmFsdWUgPSBJbmRpdmlkdWFsKGVuZm9yY2VLZXksIHZlcnNpb24pO1xuXG4gICAgICAgICAgICAgICAgaWYgKHZlcnNpb25WYWx1ZSAhPT0gdmVyc2lvbikge1xuICAgICAgICAgICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoXCJDYW4gb25seSBoYXZlIG9uZSBjb3B5IG9mIFwiICsgbW9kdWxlTmFtZSArIFwiLlxcblwiICsgXCJZb3UgYWxyZWFkeSBoYXZlIHZlcnNpb24gXCIgKyB2ZXJzaW9uVmFsdWUgKyBcIiBpbnN0YWxsZWQuXFxuXCIgKyBcIlRoaXMgbWVhbnMgeW91IGNhbm5vdCBpbnN0YWxsIHZlcnNpb24gXCIgKyB2ZXJzaW9uKTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICByZXR1cm4gSW5kaXZpZHVhbChrZXksIGRlZmF1bHRWYWx1ZSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0sIHsgXCIuL2luZGV4LmpzXCI6IDggfV0sIDEwOiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge1xuICAgICAgICAgICAgKGZ1bmN0aW9uIChnbG9iYWwpIHtcbiAgICAgICAgICAgICAgICB2YXIgdG9wTGV2ZWwgPSB0eXBlb2YgZ2xvYmFsICE9PSBcInVuZGVmaW5lZFwiID8gZ2xvYmFsIDogdHlwZW9mIHdpbmRvdyAhPT0gXCJ1bmRlZmluZWRcIiA/IHdpbmRvdyA6IHt9O1xuICAgICAgICAgICAgICAgIHZhciBtaW5Eb2MgPSByZXF1aXJlKFwibWluLWRvY3VtZW50XCIpO1xuXG4gICAgICAgICAgICAgICAgaWYgKHR5cGVvZiBkb2N1bWVudCAhPT0gXCJ1bmRlZmluZWRcIikge1xuICAgICAgICAgICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IGRvY3VtZW50O1xuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciBkb2NjeSA9IHRvcExldmVsW1wiX19HTE9CQUxfRE9DVU1FTlRfQ0FDSEVANFwiXTtcblxuICAgICAgICAgICAgICAgICAgICBpZiAoIWRvY2N5KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBkb2NjeSA9IHRvcExldmVsW1wiX19HTE9CQUxfRE9DVU1FTlRfQ0FDSEVANFwiXSA9IG1pbkRvYztcbiAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gZG9jY3k7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSkuY2FsbCh0aGlzLCB0eXBlb2YgZ2xvYmFsICE9PSBcInVuZGVmaW5lZFwiID8gZ2xvYmFsIDogdHlwZW9mIHNlbGYgIT09IFwidW5kZWZpbmVkXCIgPyBzZWxmIDogdHlwZW9mIHdpbmRvdyAhPT0gXCJ1bmRlZmluZWRcIiA/IHdpbmRvdyA6IHt9KTtcbiAgICAgICAgfSwgeyBcIm1pbi1kb2N1bWVudFwiOiA2IH1dLCAxMTogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHtcbiAgICAgICAgICAgIFwidXNlIHN0cmljdFwiO1xuXG4gICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uIGlzT2JqZWN0KHgpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gdHlwZW9mIHggPT09IFwib2JqZWN0XCIgJiYgeCAhPT0gbnVsbDtcbiAgICAgICAgICAgIH07XG4gICAgICAgIH0sIHt9XSwgMTI6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICB2YXIgbmF0aXZlSXNBcnJheSA9IEFycmF5LmlzQXJyYXk7XG4gICAgICAgICAgICB2YXIgdG9TdHJpbmcgPSBPYmplY3QucHJvdG90eXBlLnRvU3RyaW5nO1xuXG4gICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IG5hdGl2ZUlzQXJyYXkgfHwgaXNBcnJheTtcblxuICAgICAgICAgICAgZnVuY3Rpb24gaXNBcnJheShvYmopIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gdG9TdHJpbmcuY2FsbChvYmopID09PSBcIltvYmplY3QgQXJyYXldXCI7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0sIHt9XSwgMTM6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICB2YXIgcGF0Y2ggPSByZXF1aXJlKFwiLi92ZG9tL3BhdGNoLmpzXCIpO1xuXG4gICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IHBhdGNoO1xuICAgICAgICB9LCB7IFwiLi92ZG9tL3BhdGNoLmpzXCI6IDE4IH1dLCAxNDogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHtcbiAgICAgICAgICAgIHZhciBpc09iamVjdCA9IHJlcXVpcmUoXCJpcy1vYmplY3RcIik7XG4gICAgICAgICAgICB2YXIgaXNIb29rID0gcmVxdWlyZShcIi4uL3Zub2RlL2lzLXZob29rLmpzXCIpO1xuXG4gICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IGFwcGx5UHJvcGVydGllcztcblxuICAgICAgICAgICAgZnVuY3Rpb24gYXBwbHlQcm9wZXJ0aWVzKG5vZGUsIHByb3BzLCBwcmV2aW91cykge1xuICAgICAgICAgICAgICAgIGZvciAodmFyIHByb3BOYW1lIGluIHByb3BzKSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciBwcm9wVmFsdWUgPSBwcm9wc1twcm9wTmFtZV07XG5cbiAgICAgICAgICAgICAgICAgICAgaWYgKHByb3BWYWx1ZSA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICByZW1vdmVQcm9wZXJ0eShub2RlLCBwcm9wTmFtZSwgcHJvcFZhbHVlLCBwcmV2aW91cyk7XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoaXNIb29rKHByb3BWYWx1ZSkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJlbW92ZVByb3BlcnR5KG5vZGUsIHByb3BOYW1lLCBwcm9wVmFsdWUsIHByZXZpb3VzKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChwcm9wVmFsdWUuaG9vaykge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHByb3BWYWx1ZS5ob29rKG5vZGUsIHByb3BOYW1lLCBwcmV2aW91cyA/IHByZXZpb3VzW3Byb3BOYW1lXSA6IHVuZGVmaW5lZCk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoaXNPYmplY3QocHJvcFZhbHVlKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHBhdGNoT2JqZWN0KG5vZGUsIHByb3BzLCBwcmV2aW91cywgcHJvcE5hbWUsIHByb3BWYWx1ZSk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIG5vZGVbcHJvcE5hbWVdID0gcHJvcFZhbHVlO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBmdW5jdGlvbiByZW1vdmVQcm9wZXJ0eShub2RlLCBwcm9wTmFtZSwgcHJvcFZhbHVlLCBwcmV2aW91cykge1xuICAgICAgICAgICAgICAgIGlmIChwcmV2aW91cykge1xuICAgICAgICAgICAgICAgICAgICB2YXIgcHJldmlvdXNWYWx1ZSA9IHByZXZpb3VzW3Byb3BOYW1lXTtcblxuICAgICAgICAgICAgICAgICAgICBpZiAoIWlzSG9vayhwcmV2aW91c1ZhbHVlKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHByb3BOYW1lID09PSBcImF0dHJpYnV0ZXNcIikge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZvciAodmFyIGF0dHJOYW1lIGluIHByZXZpb3VzVmFsdWUpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbm9kZS5yZW1vdmVBdHRyaWJ1dGUoYXR0ck5hbWUpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAocHJvcE5hbWUgPT09IFwic3R5bGVcIikge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZvciAodmFyIGkgaW4gcHJldmlvdXNWYWx1ZSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBub2RlLnN0eWxlW2ldID0gXCJcIjtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKHR5cGVvZiBwcmV2aW91c1ZhbHVlID09PSBcInN0cmluZ1wiKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgbm9kZVtwcm9wTmFtZV0gPSBcIlwiO1xuICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBub2RlW3Byb3BOYW1lXSA9IG51bGw7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAocHJldmlvdXNWYWx1ZS51bmhvb2spIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHByZXZpb3VzVmFsdWUudW5ob29rKG5vZGUsIHByb3BOYW1lLCBwcm9wVmFsdWUpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBmdW5jdGlvbiBwYXRjaE9iamVjdChub2RlLCBwcm9wcywgcHJldmlvdXMsIHByb3BOYW1lLCBwcm9wVmFsdWUpIHtcbiAgICAgICAgICAgICAgICB2YXIgcHJldmlvdXNWYWx1ZSA9IHByZXZpb3VzID8gcHJldmlvdXNbcHJvcE5hbWVdIDogdW5kZWZpbmVkO1xuXG4gICAgICAgICAgICAgICAgLy8gU2V0IGF0dHJpYnV0ZXNcbiAgICAgICAgICAgICAgICBpZiAocHJvcE5hbWUgPT09IFwiYXR0cmlidXRlc1wiKSB7XG4gICAgICAgICAgICAgICAgICAgIGZvciAodmFyIGF0dHJOYW1lIGluIHByb3BWYWx1ZSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgdmFyIGF0dHJWYWx1ZSA9IHByb3BWYWx1ZVthdHRyTmFtZV07XG5cbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChhdHRyVmFsdWUgPT09IHVuZGVmaW5lZCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIG5vZGUucmVtb3ZlQXR0cmlidXRlKGF0dHJOYW1lKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgbm9kZS5zZXRBdHRyaWJ1dGUoYXR0ck5hbWUsIGF0dHJWYWx1ZSk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgaWYgKHByZXZpb3VzVmFsdWUgJiYgaXNPYmplY3QocHJldmlvdXNWYWx1ZSkgJiYgZ2V0UHJvdG90eXBlKHByZXZpb3VzVmFsdWUpICE9PSBnZXRQcm90b3R5cGUocHJvcFZhbHVlKSkge1xuICAgICAgICAgICAgICAgICAgICBub2RlW3Byb3BOYW1lXSA9IHByb3BWYWx1ZTtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIGlmICghaXNPYmplY3Qobm9kZVtwcm9wTmFtZV0pKSB7XG4gICAgICAgICAgICAgICAgICAgIG5vZGVbcHJvcE5hbWVdID0ge307XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgdmFyIHJlcGxhY2VyID0gcHJvcE5hbWUgPT09IFwic3R5bGVcIiA/IFwiXCIgOiB1bmRlZmluZWQ7XG5cbiAgICAgICAgICAgICAgICBmb3IgKHZhciBrIGluIHByb3BWYWx1ZSkge1xuICAgICAgICAgICAgICAgICAgICB2YXIgdmFsdWUgPSBwcm9wVmFsdWVba107XG4gICAgICAgICAgICAgICAgICAgIG5vZGVbcHJvcE5hbWVdW2tdID0gdmFsdWUgPT09IHVuZGVmaW5lZCA/IHJlcGxhY2VyIDogdmFsdWU7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBmdW5jdGlvbiBnZXRQcm90b3R5cGUodmFsdWUpIHtcbiAgICAgICAgICAgICAgICBpZiAoT2JqZWN0LmdldFByb3RvdHlwZU9mKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBPYmplY3QuZ2V0UHJvdG90eXBlT2YodmFsdWUpO1xuICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAodmFsdWUuX19wcm90b19fKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiB2YWx1ZS5fX3Byb3RvX187XG4gICAgICAgICAgICAgICAgfSBlbHNlIGlmICh2YWx1ZS5jb25zdHJ1Y3Rvcikge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gdmFsdWUuY29uc3RydWN0b3IucHJvdG90eXBlO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgfSwgeyBcIi4uL3Zub2RlL2lzLXZob29rLmpzXCI6IDI2LCBcImlzLW9iamVjdFwiOiAxMSB9XSwgMTU6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICB2YXIgZG9jdW1lbnQgPSByZXF1aXJlKFwiZ2xvYmFsL2RvY3VtZW50XCIpO1xuXG4gICAgICAgICAgICB2YXIgYXBwbHlQcm9wZXJ0aWVzID0gcmVxdWlyZShcIi4vYXBwbHktcHJvcGVydGllc1wiKTtcblxuICAgICAgICAgICAgdmFyIGlzVk5vZGUgPSByZXF1aXJlKFwiLi4vdm5vZGUvaXMtdm5vZGUuanNcIik7XG4gICAgICAgICAgICB2YXIgaXNWVGV4dCA9IHJlcXVpcmUoXCIuLi92bm9kZS9pcy12dGV4dC5qc1wiKTtcbiAgICAgICAgICAgIHZhciBpc1dpZGdldCA9IHJlcXVpcmUoXCIuLi92bm9kZS9pcy13aWRnZXQuanNcIik7XG4gICAgICAgICAgICB2YXIgaGFuZGxlVGh1bmsgPSByZXF1aXJlKFwiLi4vdm5vZGUvaGFuZGxlLXRodW5rLmpzXCIpO1xuXG4gICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IGNyZWF0ZUVsZW1lbnQ7XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIGNyZWF0ZUVsZW1lbnQodm5vZGUsIG9wdHMpIHtcbiAgICAgICAgICAgICAgICB2YXIgZG9jID0gb3B0cyA/IG9wdHMuZG9jdW1lbnQgfHwgZG9jdW1lbnQgOiBkb2N1bWVudDtcbiAgICAgICAgICAgICAgICB2YXIgd2FybiA9IG9wdHMgPyBvcHRzLndhcm4gOiBudWxsO1xuXG4gICAgICAgICAgICAgICAgdm5vZGUgPSBoYW5kbGVUaHVuayh2bm9kZSkuYTtcblxuICAgICAgICAgICAgICAgIGlmIChpc1dpZGdldCh2bm9kZSkpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHZub2RlLmluaXQoKTtcbiAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKGlzVlRleHQodm5vZGUpKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBkb2MuY3JlYXRlVGV4dE5vZGUodm5vZGUudGV4dCk7XG4gICAgICAgICAgICAgICAgfSBlbHNlIGlmICghaXNWTm9kZSh2bm9kZSkpIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKHdhcm4pIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHdhcm4oXCJJdGVtIGlzIG5vdCBhIHZhbGlkIHZpcnR1YWwgZG9tIG5vZGVcIiwgdm5vZGUpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBudWxsO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHZhciBub2RlID0gdm5vZGUubmFtZXNwYWNlID09PSBudWxsID8gZG9jLmNyZWF0ZUVsZW1lbnQodm5vZGUudGFnTmFtZSkgOiBkb2MuY3JlYXRlRWxlbWVudE5TKHZub2RlLm5hbWVzcGFjZSwgdm5vZGUudGFnTmFtZSk7XG5cbiAgICAgICAgICAgICAgICB2YXIgcHJvcHMgPSB2bm9kZS5wcm9wZXJ0aWVzO1xuICAgICAgICAgICAgICAgIGFwcGx5UHJvcGVydGllcyhub2RlLCBwcm9wcyk7XG5cbiAgICAgICAgICAgICAgICB2YXIgY2hpbGRyZW4gPSB2bm9kZS5jaGlsZHJlbjtcblxuICAgICAgICAgICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgY2hpbGRyZW4ubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgICAgICAgICAgdmFyIGNoaWxkTm9kZSA9IGNyZWF0ZUVsZW1lbnQoY2hpbGRyZW5baV0sIG9wdHMpO1xuICAgICAgICAgICAgICAgICAgICBpZiAoY2hpbGROb2RlKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBub2RlLmFwcGVuZENoaWxkKGNoaWxkTm9kZSk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICByZXR1cm4gbm9kZTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSwgeyBcIi4uL3Zub2RlL2hhbmRsZS10aHVuay5qc1wiOiAyNCwgXCIuLi92bm9kZS9pcy12bm9kZS5qc1wiOiAyNywgXCIuLi92bm9kZS9pcy12dGV4dC5qc1wiOiAyOCwgXCIuLi92bm9kZS9pcy13aWRnZXQuanNcIjogMjksIFwiLi9hcHBseS1wcm9wZXJ0aWVzXCI6IDE0LCBcImdsb2JhbC9kb2N1bWVudFwiOiAxMCB9XSwgMTY6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICAvLyBNYXBzIGEgdmlydHVhbCBET00gdHJlZSBvbnRvIGEgcmVhbCBET00gdHJlZSBpbiBhbiBlZmZpY2llbnQgbWFubmVyLlxuICAgICAgICAgICAgLy8gV2UgZG9uJ3Qgd2FudCB0byByZWFkIGFsbCBvZiB0aGUgRE9NIG5vZGVzIGluIHRoZSB0cmVlIHNvIHdlIHVzZVxuICAgICAgICAgICAgLy8gdGhlIGluLW9yZGVyIHRyZWUgaW5kZXhpbmcgdG8gZWxpbWluYXRlIHJlY3Vyc2lvbiBkb3duIGNlcnRhaW4gYnJhbmNoZXMuXG4gICAgICAgICAgICAvLyBXZSBvbmx5IHJlY3Vyc2UgaW50byBhIERPTSBub2RlIGlmIHdlIGtub3cgdGhhdCBpdCBjb250YWlucyBhIGNoaWxkIG9mXG4gICAgICAgICAgICAvLyBpbnRlcmVzdC5cblxuICAgICAgICAgICAgdmFyIG5vQ2hpbGQgPSB7fTtcblxuICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBkb21JbmRleDtcblxuICAgICAgICAgICAgZnVuY3Rpb24gZG9tSW5kZXgocm9vdE5vZGUsIHRyZWUsIGluZGljZXMsIG5vZGVzKSB7XG4gICAgICAgICAgICAgICAgaWYgKCFpbmRpY2VzIHx8IGluZGljZXMubGVuZ3RoID09PSAwKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiB7fTtcbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICBpbmRpY2VzLnNvcnQoYXNjZW5kaW5nKTtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHJlY3Vyc2Uocm9vdE5vZGUsIHRyZWUsIGluZGljZXMsIG5vZGVzLCAwKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIHJlY3Vyc2Uocm9vdE5vZGUsIHRyZWUsIGluZGljZXMsIG5vZGVzLCByb290SW5kZXgpIHtcbiAgICAgICAgICAgICAgICBub2RlcyA9IG5vZGVzIHx8IHt9O1xuXG4gICAgICAgICAgICAgICAgaWYgKHJvb3ROb2RlKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmIChpbmRleEluUmFuZ2UoaW5kaWNlcywgcm9vdEluZGV4LCByb290SW5kZXgpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBub2Rlc1tyb290SW5kZXhdID0gcm9vdE5vZGU7XG4gICAgICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgICAgICB2YXIgdkNoaWxkcmVuID0gdHJlZS5jaGlsZHJlbjtcblxuICAgICAgICAgICAgICAgICAgICBpZiAodkNoaWxkcmVuKSB7XG5cbiAgICAgICAgICAgICAgICAgICAgICAgIHZhciBjaGlsZE5vZGVzID0gcm9vdE5vZGUuY2hpbGROb2RlcztcblxuICAgICAgICAgICAgICAgICAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCB0cmVlLmNoaWxkcmVuLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcm9vdEluZGV4ICs9IDE7XG5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB2YXIgdkNoaWxkID0gdkNoaWxkcmVuW2ldIHx8IG5vQ2hpbGQ7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdmFyIG5leHRJbmRleCA9IHJvb3RJbmRleCArICh2Q2hpbGQuY291bnQgfHwgMCk7XG5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBza2lwIHJlY3Vyc2lvbiBkb3duIHRoZSB0cmVlIGlmIHRoZXJlIGFyZSBubyBub2RlcyBkb3duIGhlcmVcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoaW5kZXhJblJhbmdlKGluZGljZXMsIHJvb3RJbmRleCwgbmV4dEluZGV4KSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICByZWN1cnNlKGNoaWxkTm9kZXNbaV0sIHZDaGlsZCwgaW5kaWNlcywgbm9kZXMsIHJvb3RJbmRleCk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcm9vdEluZGV4ID0gbmV4dEluZGV4O1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgcmV0dXJuIG5vZGVzO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAvLyBCaW5hcnkgc2VhcmNoIGZvciBhbiBpbmRleCBpbiB0aGUgaW50ZXJ2YWwgW2xlZnQsIHJpZ2h0XVxuICAgICAgICAgICAgZnVuY3Rpb24gaW5kZXhJblJhbmdlKGluZGljZXMsIGxlZnQsIHJpZ2h0KSB7XG4gICAgICAgICAgICAgICAgaWYgKGluZGljZXMubGVuZ3RoID09PSAwKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICB2YXIgbWluSW5kZXggPSAwO1xuICAgICAgICAgICAgICAgIHZhciBtYXhJbmRleCA9IGluZGljZXMubGVuZ3RoIC0gMTtcbiAgICAgICAgICAgICAgICB2YXIgY3VycmVudEluZGV4O1xuICAgICAgICAgICAgICAgIHZhciBjdXJyZW50SXRlbTtcblxuICAgICAgICAgICAgICAgIHdoaWxlIChtaW5JbmRleCA8PSBtYXhJbmRleCkge1xuICAgICAgICAgICAgICAgICAgICBjdXJyZW50SW5kZXggPSAobWF4SW5kZXggKyBtaW5JbmRleCkgLyAyID4+IDA7XG4gICAgICAgICAgICAgICAgICAgIGN1cnJlbnRJdGVtID0gaW5kaWNlc1tjdXJyZW50SW5kZXhdO1xuXG4gICAgICAgICAgICAgICAgICAgIGlmIChtaW5JbmRleCA9PT0gbWF4SW5kZXgpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBjdXJyZW50SXRlbSA+PSBsZWZ0ICYmIGN1cnJlbnRJdGVtIDw9IHJpZ2h0O1xuICAgICAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKGN1cnJlbnRJdGVtIDwgbGVmdCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgbWluSW5kZXggPSBjdXJyZW50SW5kZXggKyAxO1xuICAgICAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKGN1cnJlbnRJdGVtID4gcmlnaHQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIG1heEluZGV4ID0gY3VycmVudEluZGV4IC0gMTtcbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBmdW5jdGlvbiBhc2NlbmRpbmcoYSwgYikge1xuICAgICAgICAgICAgICAgIHJldHVybiBhID4gYiA/IDEgOiAtMTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSwge31dLCAxNzogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHtcbiAgICAgICAgICAgIHZhciBhcHBseVByb3BlcnRpZXMgPSByZXF1aXJlKFwiLi9hcHBseS1wcm9wZXJ0aWVzXCIpO1xuXG4gICAgICAgICAgICB2YXIgaXNXaWRnZXQgPSByZXF1aXJlKFwiLi4vdm5vZGUvaXMtd2lkZ2V0LmpzXCIpO1xuICAgICAgICAgICAgdmFyIFZQYXRjaCA9IHJlcXVpcmUoXCIuLi92bm9kZS92cGF0Y2guanNcIik7XG5cbiAgICAgICAgICAgIHZhciB1cGRhdGVXaWRnZXQgPSByZXF1aXJlKFwiLi91cGRhdGUtd2lkZ2V0XCIpO1xuXG4gICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IGFwcGx5UGF0Y2g7XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIGFwcGx5UGF0Y2godnBhdGNoLCBkb21Ob2RlLCByZW5kZXJPcHRpb25zKSB7XG4gICAgICAgICAgICAgICAgdmFyIHR5cGUgPSB2cGF0Y2gudHlwZTtcbiAgICAgICAgICAgICAgICB2YXIgdk5vZGUgPSB2cGF0Y2gudk5vZGU7XG4gICAgICAgICAgICAgICAgdmFyIHBhdGNoID0gdnBhdGNoLnBhdGNoO1xuXG4gICAgICAgICAgICAgICAgc3dpdGNoICh0eXBlKSB7XG4gICAgICAgICAgICAgICAgICAgIGNhc2UgVlBhdGNoLlJFTU9WRTpcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiByZW1vdmVOb2RlKGRvbU5vZGUsIHZOb2RlKTtcbiAgICAgICAgICAgICAgICAgICAgY2FzZSBWUGF0Y2guSU5TRVJUOlxuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGluc2VydE5vZGUoZG9tTm9kZSwgcGF0Y2gsIHJlbmRlck9wdGlvbnMpO1xuICAgICAgICAgICAgICAgICAgICBjYXNlIFZQYXRjaC5WVEVYVDpcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBzdHJpbmdQYXRjaChkb21Ob2RlLCB2Tm9kZSwgcGF0Y2gsIHJlbmRlck9wdGlvbnMpO1xuICAgICAgICAgICAgICAgICAgICBjYXNlIFZQYXRjaC5XSURHRVQ6XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gd2lkZ2V0UGF0Y2goZG9tTm9kZSwgdk5vZGUsIHBhdGNoLCByZW5kZXJPcHRpb25zKTtcbiAgICAgICAgICAgICAgICAgICAgY2FzZSBWUGF0Y2guVk5PREU6XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gdk5vZGVQYXRjaChkb21Ob2RlLCB2Tm9kZSwgcGF0Y2gsIHJlbmRlck9wdGlvbnMpO1xuICAgICAgICAgICAgICAgICAgICBjYXNlIFZQYXRjaC5PUkRFUjpcbiAgICAgICAgICAgICAgICAgICAgICAgIHJlb3JkZXJDaGlsZHJlbihkb21Ob2RlLCBwYXRjaCk7XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gZG9tTm9kZTtcbiAgICAgICAgICAgICAgICAgICAgY2FzZSBWUGF0Y2guUFJPUFM6XG4gICAgICAgICAgICAgICAgICAgICAgICBhcHBseVByb3BlcnRpZXMoZG9tTm9kZSwgcGF0Y2gsIHZOb2RlLnByb3BlcnRpZXMpO1xuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGRvbU5vZGU7XG4gICAgICAgICAgICAgICAgICAgIGNhc2UgVlBhdGNoLlRIVU5LOlxuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHJlcGxhY2VSb290KGRvbU5vZGUsIHJlbmRlck9wdGlvbnMucGF0Y2goZG9tTm9kZSwgcGF0Y2gsIHJlbmRlck9wdGlvbnMpKTtcbiAgICAgICAgICAgICAgICAgICAgZGVmYXVsdDpcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBkb21Ob2RlO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZnVuY3Rpb24gcmVtb3ZlTm9kZShkb21Ob2RlLCB2Tm9kZSkge1xuICAgICAgICAgICAgICAgIHZhciBwYXJlbnROb2RlID0gZG9tTm9kZS5wYXJlbnROb2RlO1xuXG4gICAgICAgICAgICAgICAgaWYgKHBhcmVudE5vZGUpIHtcbiAgICAgICAgICAgICAgICAgICAgcGFyZW50Tm9kZS5yZW1vdmVDaGlsZChkb21Ob2RlKTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICBkZXN0cm95V2lkZ2V0KGRvbU5vZGUsIHZOb2RlKTtcblxuICAgICAgICAgICAgICAgIHJldHVybiBudWxsO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBmdW5jdGlvbiBpbnNlcnROb2RlKHBhcmVudE5vZGUsIHZOb2RlLCByZW5kZXJPcHRpb25zKSB7XG4gICAgICAgICAgICAgICAgdmFyIG5ld05vZGUgPSByZW5kZXJPcHRpb25zLnJlbmRlcih2Tm9kZSwgcmVuZGVyT3B0aW9ucyk7XG5cbiAgICAgICAgICAgICAgICBpZiAocGFyZW50Tm9kZSkge1xuICAgICAgICAgICAgICAgICAgICBwYXJlbnROb2RlLmFwcGVuZENoaWxkKG5ld05vZGUpO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHJldHVybiBwYXJlbnROb2RlO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBmdW5jdGlvbiBzdHJpbmdQYXRjaChkb21Ob2RlLCBsZWZ0Vk5vZGUsIHZUZXh0LCByZW5kZXJPcHRpb25zKSB7XG4gICAgICAgICAgICAgICAgdmFyIG5ld05vZGU7XG5cbiAgICAgICAgICAgICAgICBpZiAoZG9tTm9kZS5ub2RlVHlwZSA9PT0gMykge1xuICAgICAgICAgICAgICAgICAgICBkb21Ob2RlLnJlcGxhY2VEYXRhKDAsIGRvbU5vZGUubGVuZ3RoLCB2VGV4dC50ZXh0KTtcbiAgICAgICAgICAgICAgICAgICAgbmV3Tm9kZSA9IGRvbU5vZGU7XG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgdmFyIHBhcmVudE5vZGUgPSBkb21Ob2RlLnBhcmVudE5vZGU7XG4gICAgICAgICAgICAgICAgICAgIG5ld05vZGUgPSByZW5kZXJPcHRpb25zLnJlbmRlcih2VGV4dCwgcmVuZGVyT3B0aW9ucyk7XG5cbiAgICAgICAgICAgICAgICAgICAgaWYgKHBhcmVudE5vZGUgJiYgbmV3Tm9kZSAhPT0gZG9tTm9kZSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgcGFyZW50Tm9kZS5yZXBsYWNlQ2hpbGQobmV3Tm9kZSwgZG9tTm9kZSk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICByZXR1cm4gbmV3Tm9kZTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZnVuY3Rpb24gd2lkZ2V0UGF0Y2goZG9tTm9kZSwgbGVmdFZOb2RlLCB3aWRnZXQsIHJlbmRlck9wdGlvbnMpIHtcbiAgICAgICAgICAgICAgICB2YXIgdXBkYXRpbmcgPSB1cGRhdGVXaWRnZXQobGVmdFZOb2RlLCB3aWRnZXQpO1xuICAgICAgICAgICAgICAgIHZhciBuZXdOb2RlO1xuXG4gICAgICAgICAgICAgICAgaWYgKHVwZGF0aW5nKSB7XG4gICAgICAgICAgICAgICAgICAgIG5ld05vZGUgPSB3aWRnZXQudXBkYXRlKGxlZnRWTm9kZSwgZG9tTm9kZSkgfHwgZG9tTm9kZTtcbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICBuZXdOb2RlID0gcmVuZGVyT3B0aW9ucy5yZW5kZXIod2lkZ2V0LCByZW5kZXJPcHRpb25zKTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICB2YXIgcGFyZW50Tm9kZSA9IGRvbU5vZGUucGFyZW50Tm9kZTtcblxuICAgICAgICAgICAgICAgIGlmIChwYXJlbnROb2RlICYmIG5ld05vZGUgIT09IGRvbU5vZGUpIHtcbiAgICAgICAgICAgICAgICAgICAgcGFyZW50Tm9kZS5yZXBsYWNlQ2hpbGQobmV3Tm9kZSwgZG9tTm9kZSk7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgaWYgKCF1cGRhdGluZykge1xuICAgICAgICAgICAgICAgICAgICBkZXN0cm95V2lkZ2V0KGRvbU5vZGUsIGxlZnRWTm9kZSk7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgcmV0dXJuIG5ld05vZGU7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIHZOb2RlUGF0Y2goZG9tTm9kZSwgbGVmdFZOb2RlLCB2Tm9kZSwgcmVuZGVyT3B0aW9ucykge1xuICAgICAgICAgICAgICAgIHZhciBwYXJlbnROb2RlID0gZG9tTm9kZS5wYXJlbnROb2RlO1xuICAgICAgICAgICAgICAgIHZhciBuZXdOb2RlID0gcmVuZGVyT3B0aW9ucy5yZW5kZXIodk5vZGUsIHJlbmRlck9wdGlvbnMpO1xuXG4gICAgICAgICAgICAgICAgaWYgKHBhcmVudE5vZGUgJiYgbmV3Tm9kZSAhPT0gZG9tTm9kZSkge1xuICAgICAgICAgICAgICAgICAgICBwYXJlbnROb2RlLnJlcGxhY2VDaGlsZChuZXdOb2RlLCBkb21Ob2RlKTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICByZXR1cm4gbmV3Tm9kZTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZnVuY3Rpb24gZGVzdHJveVdpZGdldChkb21Ob2RlLCB3KSB7XG4gICAgICAgICAgICAgICAgaWYgKHR5cGVvZiB3LmRlc3Ryb3kgPT09IFwiZnVuY3Rpb25cIiAmJiBpc1dpZGdldCh3KSkge1xuICAgICAgICAgICAgICAgICAgICB3LmRlc3Ryb3koZG9tTm9kZSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBmdW5jdGlvbiByZW9yZGVyQ2hpbGRyZW4oZG9tTm9kZSwgbW92ZXMpIHtcbiAgICAgICAgICAgICAgICB2YXIgY2hpbGROb2RlcyA9IGRvbU5vZGUuY2hpbGROb2RlcztcbiAgICAgICAgICAgICAgICB2YXIga2V5TWFwID0ge307XG4gICAgICAgICAgICAgICAgdmFyIG5vZGU7XG4gICAgICAgICAgICAgICAgdmFyIHJlbW92ZTtcbiAgICAgICAgICAgICAgICB2YXIgaW5zZXJ0O1xuXG4gICAgICAgICAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCBtb3Zlcy5yZW1vdmVzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICAgICAgICAgIHJlbW92ZSA9IG1vdmVzLnJlbW92ZXNbaV07XG4gICAgICAgICAgICAgICAgICAgIG5vZGUgPSBjaGlsZE5vZGVzW3JlbW92ZS5mcm9tXTtcbiAgICAgICAgICAgICAgICAgICAgaWYgKHJlbW92ZS5rZXkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGtleU1hcFtyZW1vdmUua2V5XSA9IG5vZGU7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgZG9tTm9kZS5yZW1vdmVDaGlsZChub2RlKTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICB2YXIgbGVuZ3RoID0gY2hpbGROb2Rlcy5sZW5ndGg7XG4gICAgICAgICAgICAgICAgZm9yICh2YXIgaiA9IDA7IGogPCBtb3Zlcy5pbnNlcnRzLmxlbmd0aDsgaisrKSB7XG4gICAgICAgICAgICAgICAgICAgIGluc2VydCA9IG1vdmVzLmluc2VydHNbal07XG4gICAgICAgICAgICAgICAgICAgIG5vZGUgPSBrZXlNYXBbaW5zZXJ0LmtleV07XG4gICAgICAgICAgICAgICAgICAgIC8vIHRoaXMgaXMgdGhlIHdlaXJkZXN0IGJ1ZyBpJ3ZlIGV2ZXIgc2VlbiBpbiB3ZWJraXRcbiAgICAgICAgICAgICAgICAgICAgZG9tTm9kZS5pbnNlcnRCZWZvcmUobm9kZSwgaW5zZXJ0LnRvID49IGxlbmd0aCsrID8gbnVsbCA6IGNoaWxkTm9kZXNbaW5zZXJ0LnRvXSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBmdW5jdGlvbiByZXBsYWNlUm9vdChvbGRSb290LCBuZXdSb290KSB7XG4gICAgICAgICAgICAgICAgaWYgKG9sZFJvb3QgJiYgbmV3Um9vdCAmJiBvbGRSb290ICE9PSBuZXdSb290ICYmIG9sZFJvb3QucGFyZW50Tm9kZSkge1xuICAgICAgICAgICAgICAgICAgICBvbGRSb290LnBhcmVudE5vZGUucmVwbGFjZUNoaWxkKG5ld1Jvb3QsIG9sZFJvb3QpO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHJldHVybiBuZXdSb290O1xuICAgICAgICAgICAgfVxuICAgICAgICB9LCB7IFwiLi4vdm5vZGUvaXMtd2lkZ2V0LmpzXCI6IDI5LCBcIi4uL3Zub2RlL3ZwYXRjaC5qc1wiOiAzMiwgXCIuL2FwcGx5LXByb3BlcnRpZXNcIjogMTQsIFwiLi91cGRhdGUtd2lkZ2V0XCI6IDE5IH1dLCAxODogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHtcbiAgICAgICAgICAgIHZhciBkb2N1bWVudCA9IHJlcXVpcmUoXCJnbG9iYWwvZG9jdW1lbnRcIik7XG4gICAgICAgICAgICB2YXIgaXNBcnJheSA9IHJlcXVpcmUoXCJ4LWlzLWFycmF5XCIpO1xuXG4gICAgICAgICAgICB2YXIgcmVuZGVyID0gcmVxdWlyZShcIi4vY3JlYXRlLWVsZW1lbnRcIik7XG4gICAgICAgICAgICB2YXIgZG9tSW5kZXggPSByZXF1aXJlKFwiLi9kb20taW5kZXhcIik7XG4gICAgICAgICAgICB2YXIgcGF0Y2hPcCA9IHJlcXVpcmUoXCIuL3BhdGNoLW9wXCIpO1xuICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBwYXRjaDtcblxuICAgICAgICAgICAgZnVuY3Rpb24gcGF0Y2gocm9vdE5vZGUsIHBhdGNoZXMsIHJlbmRlck9wdGlvbnMpIHtcbiAgICAgICAgICAgICAgICByZW5kZXJPcHRpb25zID0gcmVuZGVyT3B0aW9ucyB8fCB7fTtcbiAgICAgICAgICAgICAgICByZW5kZXJPcHRpb25zLnBhdGNoID0gcmVuZGVyT3B0aW9ucy5wYXRjaCAmJiByZW5kZXJPcHRpb25zLnBhdGNoICE9PSBwYXRjaCA/IHJlbmRlck9wdGlvbnMucGF0Y2ggOiBwYXRjaFJlY3Vyc2l2ZTtcbiAgICAgICAgICAgICAgICByZW5kZXJPcHRpb25zLnJlbmRlciA9IHJlbmRlck9wdGlvbnMucmVuZGVyIHx8IHJlbmRlcjtcblxuICAgICAgICAgICAgICAgIHJldHVybiByZW5kZXJPcHRpb25zLnBhdGNoKHJvb3ROb2RlLCBwYXRjaGVzLCByZW5kZXJPcHRpb25zKTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZnVuY3Rpb24gcGF0Y2hSZWN1cnNpdmUocm9vdE5vZGUsIHBhdGNoZXMsIHJlbmRlck9wdGlvbnMpIHtcbiAgICAgICAgICAgICAgICB2YXIgaW5kaWNlcyA9IHBhdGNoSW5kaWNlcyhwYXRjaGVzKTtcblxuICAgICAgICAgICAgICAgIGlmIChpbmRpY2VzLmxlbmd0aCA9PT0gMCkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gcm9vdE5vZGU7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgdmFyIGluZGV4ID0gZG9tSW5kZXgocm9vdE5vZGUsIHBhdGNoZXMuYSwgaW5kaWNlcyk7XG4gICAgICAgICAgICAgICAgdmFyIG93bmVyRG9jdW1lbnQgPSByb290Tm9kZS5vd25lckRvY3VtZW50O1xuXG4gICAgICAgICAgICAgICAgaWYgKCFyZW5kZXJPcHRpb25zLmRvY3VtZW50ICYmIG93bmVyRG9jdW1lbnQgIT09IGRvY3VtZW50KSB7XG4gICAgICAgICAgICAgICAgICAgIHJlbmRlck9wdGlvbnMuZG9jdW1lbnQgPSBvd25lckRvY3VtZW50O1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgaW5kaWNlcy5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgICAgICAgICB2YXIgbm9kZUluZGV4ID0gaW5kaWNlc1tpXTtcbiAgICAgICAgICAgICAgICAgICAgcm9vdE5vZGUgPSBhcHBseVBhdGNoKHJvb3ROb2RlLCBpbmRleFtub2RlSW5kZXhdLCBwYXRjaGVzW25vZGVJbmRleF0sIHJlbmRlck9wdGlvbnMpO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHJldHVybiByb290Tm9kZTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZnVuY3Rpb24gYXBwbHlQYXRjaChyb290Tm9kZSwgZG9tTm9kZSwgcGF0Y2hMaXN0LCByZW5kZXJPcHRpb25zKSB7XG4gICAgICAgICAgICAgICAgaWYgKCFkb21Ob2RlKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiByb290Tm9kZTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICB2YXIgbmV3Tm9kZTtcblxuICAgICAgICAgICAgICAgIGlmIChpc0FycmF5KHBhdGNoTGlzdCkpIHtcbiAgICAgICAgICAgICAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCBwYXRjaExpc3QubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIG5ld05vZGUgPSBwYXRjaE9wKHBhdGNoTGlzdFtpXSwgZG9tTm9kZSwgcmVuZGVyT3B0aW9ucyk7XG5cbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChkb21Ob2RlID09PSByb290Tm9kZSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJvb3ROb2RlID0gbmV3Tm9kZTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIG5ld05vZGUgPSBwYXRjaE9wKHBhdGNoTGlzdCwgZG9tTm9kZSwgcmVuZGVyT3B0aW9ucyk7XG5cbiAgICAgICAgICAgICAgICAgICAgaWYgKGRvbU5vZGUgPT09IHJvb3ROb2RlKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICByb290Tm9kZSA9IG5ld05vZGU7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICByZXR1cm4gcm9vdE5vZGU7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIHBhdGNoSW5kaWNlcyhwYXRjaGVzKSB7XG4gICAgICAgICAgICAgICAgdmFyIGluZGljZXMgPSBbXTtcblxuICAgICAgICAgICAgICAgIGZvciAodmFyIGtleSBpbiBwYXRjaGVzKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmIChrZXkgIT09IFwiYVwiKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBpbmRpY2VzLnB1c2goTnVtYmVyKGtleSkpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgcmV0dXJuIGluZGljZXM7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0sIHsgXCIuL2NyZWF0ZS1lbGVtZW50XCI6IDE1LCBcIi4vZG9tLWluZGV4XCI6IDE2LCBcIi4vcGF0Y2gtb3BcIjogMTcsIFwiZ2xvYmFsL2RvY3VtZW50XCI6IDEwLCBcIngtaXMtYXJyYXlcIjogMTIgfV0sIDE5OiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge1xuICAgICAgICAgICAgdmFyIGlzV2lkZ2V0ID0gcmVxdWlyZShcIi4uL3Zub2RlL2lzLXdpZGdldC5qc1wiKTtcblxuICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSB1cGRhdGVXaWRnZXQ7XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIHVwZGF0ZVdpZGdldChhLCBiKSB7XG4gICAgICAgICAgICAgICAgaWYgKGlzV2lkZ2V0KGEpICYmIGlzV2lkZ2V0KGIpKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmIChcIm5hbWVcIiBpbiBhICYmIFwibmFtZVwiIGluIGIpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBhLmlkID09PSBiLmlkO1xuICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGEuaW5pdCA9PT0gYi5pbml0O1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICAgICAgfVxuICAgICAgICB9LCB7IFwiLi4vdm5vZGUvaXMtd2lkZ2V0LmpzXCI6IDI5IH1dLCAyMDogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHtcbiAgICAgICAgICAgIFwidXNlIHN0cmljdFwiO1xuXG4gICAgICAgICAgICB2YXIgRXZTdG9yZSA9IHJlcXVpcmUoXCJldi1zdG9yZVwiKTtcblxuICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBFdkhvb2s7XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIEV2SG9vayh2YWx1ZSkge1xuICAgICAgICAgICAgICAgIGlmICghKHRoaXMgaW5zdGFuY2VvZiBFdkhvb2spKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBuZXcgRXZIb29rKHZhbHVlKTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICB0aGlzLnZhbHVlID0gdmFsdWU7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIEV2SG9vay5wcm90b3R5cGUuaG9vayA9IGZ1bmN0aW9uIChub2RlLCBwcm9wZXJ0eU5hbWUpIHtcbiAgICAgICAgICAgICAgICB2YXIgZXMgPSBFdlN0b3JlKG5vZGUpO1xuICAgICAgICAgICAgICAgIHZhciBwcm9wTmFtZSA9IHByb3BlcnR5TmFtZS5zdWJzdHIoMyk7XG5cbiAgICAgICAgICAgICAgICBlc1twcm9wTmFtZV0gPSB0aGlzLnZhbHVlO1xuICAgICAgICAgICAgfTtcblxuICAgICAgICAgICAgRXZIb29rLnByb3RvdHlwZS51bmhvb2sgPSBmdW5jdGlvbiAobm9kZSwgcHJvcGVydHlOYW1lKSB7XG4gICAgICAgICAgICAgICAgdmFyIGVzID0gRXZTdG9yZShub2RlKTtcbiAgICAgICAgICAgICAgICB2YXIgcHJvcE5hbWUgPSBwcm9wZXJ0eU5hbWUuc3Vic3RyKDMpO1xuXG4gICAgICAgICAgICAgICAgZXNbcHJvcE5hbWVdID0gdW5kZWZpbmVkO1xuICAgICAgICAgICAgfTtcbiAgICAgICAgfSwgeyBcImV2LXN0b3JlXCI6IDcgfV0sIDIxOiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge1xuICAgICAgICAgICAgXCJ1c2Ugc3RyaWN0XCI7XG5cbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gU29mdFNldEhvb2s7XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIFNvZnRTZXRIb29rKHZhbHVlKSB7XG4gICAgICAgICAgICAgICAgaWYgKCEodGhpcyBpbnN0YW5jZW9mIFNvZnRTZXRIb29rKSkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gbmV3IFNvZnRTZXRIb29rKHZhbHVlKTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICB0aGlzLnZhbHVlID0gdmFsdWU7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIFNvZnRTZXRIb29rLnByb3RvdHlwZS5ob29rID0gZnVuY3Rpb24gKG5vZGUsIHByb3BlcnR5TmFtZSkge1xuICAgICAgICAgICAgICAgIGlmIChub2RlW3Byb3BlcnR5TmFtZV0gIT09IHRoaXMudmFsdWUpIHtcbiAgICAgICAgICAgICAgICAgICAgbm9kZVtwcm9wZXJ0eU5hbWVdID0gdGhpcy52YWx1ZTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9O1xuICAgICAgICB9LCB7fV0sIDIyOiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge1xuICAgICAgICAgICAgXCJ1c2Ugc3RyaWN0XCI7XG5cbiAgICAgICAgICAgIHZhciBpc0FycmF5ID0gcmVxdWlyZShcIngtaXMtYXJyYXlcIik7XG5cbiAgICAgICAgICAgIHZhciBWTm9kZSA9IHJlcXVpcmUoXCIuLi92bm9kZS92bm9kZS5qc1wiKTtcbiAgICAgICAgICAgIHZhciBWVGV4dCA9IHJlcXVpcmUoXCIuLi92bm9kZS92dGV4dC5qc1wiKTtcbiAgICAgICAgICAgIHZhciBpc1ZOb2RlID0gcmVxdWlyZShcIi4uL3Zub2RlL2lzLXZub2RlXCIpO1xuICAgICAgICAgICAgdmFyIGlzVlRleHQgPSByZXF1aXJlKFwiLi4vdm5vZGUvaXMtdnRleHRcIik7XG4gICAgICAgICAgICB2YXIgaXNXaWRnZXQgPSByZXF1aXJlKFwiLi4vdm5vZGUvaXMtd2lkZ2V0XCIpO1xuICAgICAgICAgICAgdmFyIGlzSG9vayA9IHJlcXVpcmUoXCIuLi92bm9kZS9pcy12aG9va1wiKTtcbiAgICAgICAgICAgIHZhciBpc1ZUaHVuayA9IHJlcXVpcmUoXCIuLi92bm9kZS9pcy10aHVua1wiKTtcblxuICAgICAgICAgICAgdmFyIHBhcnNlVGFnID0gcmVxdWlyZShcIi4vcGFyc2UtdGFnLmpzXCIpO1xuICAgICAgICAgICAgdmFyIHNvZnRTZXRIb29rID0gcmVxdWlyZShcIi4vaG9va3Mvc29mdC1zZXQtaG9vay5qc1wiKTtcbiAgICAgICAgICAgIHZhciBldkhvb2sgPSByZXF1aXJlKFwiLi9ob29rcy9ldi1ob29rLmpzXCIpO1xuXG4gICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IGg7XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIGgodGFnTmFtZSwgcHJvcGVydGllcywgY2hpbGRyZW4pIHtcbiAgICAgICAgICAgICAgICB2YXIgY2hpbGROb2RlcyA9IFtdO1xuICAgICAgICAgICAgICAgIHZhciB0YWcsIHByb3BzLCBrZXksIG5hbWVzcGFjZTtcblxuICAgICAgICAgICAgICAgIGlmICghY2hpbGRyZW4gJiYgaXNDaGlsZHJlbihwcm9wZXJ0aWVzKSkge1xuICAgICAgICAgICAgICAgICAgICBjaGlsZHJlbiA9IHByb3BlcnRpZXM7XG4gICAgICAgICAgICAgICAgICAgIHByb3BzID0ge307XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgcHJvcHMgPSBwcm9wcyB8fCBwcm9wZXJ0aWVzIHx8IHt9O1xuICAgICAgICAgICAgICAgIHRhZyA9IHBhcnNlVGFnKHRhZ05hbWUsIHByb3BzKTtcblxuICAgICAgICAgICAgICAgIC8vIHN1cHBvcnQga2V5c1xuICAgICAgICAgICAgICAgIGlmIChwcm9wcy5oYXNPd25Qcm9wZXJ0eShcImtleVwiKSkge1xuICAgICAgICAgICAgICAgICAgICBrZXkgPSBwcm9wcy5rZXk7XG4gICAgICAgICAgICAgICAgICAgIHByb3BzLmtleSA9IHVuZGVmaW5lZDtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAvLyBzdXBwb3J0IG5hbWVzcGFjZVxuICAgICAgICAgICAgICAgIGlmIChwcm9wcy5oYXNPd25Qcm9wZXJ0eShcIm5hbWVzcGFjZVwiKSkge1xuICAgICAgICAgICAgICAgICAgICBuYW1lc3BhY2UgPSBwcm9wcy5uYW1lc3BhY2U7XG4gICAgICAgICAgICAgICAgICAgIHByb3BzLm5hbWVzcGFjZSA9IHVuZGVmaW5lZDtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAvLyBmaXggY3Vyc29yIGJ1Z1xuICAgICAgICAgICAgICAgIGlmICh0YWcgPT09IFwiSU5QVVRcIiAmJiAhbmFtZXNwYWNlICYmIHByb3BzLmhhc093blByb3BlcnR5KFwidmFsdWVcIikgJiYgcHJvcHMudmFsdWUgIT09IHVuZGVmaW5lZCAmJiAhaXNIb29rKHByb3BzLnZhbHVlKSkge1xuICAgICAgICAgICAgICAgICAgICBwcm9wcy52YWx1ZSA9IHNvZnRTZXRIb29rKHByb3BzLnZhbHVlKTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICB0cmFuc2Zvcm1Qcm9wZXJ0aWVzKHByb3BzKTtcblxuICAgICAgICAgICAgICAgIGlmIChjaGlsZHJlbiAhPT0gdW5kZWZpbmVkICYmIGNoaWxkcmVuICE9PSBudWxsKSB7XG4gICAgICAgICAgICAgICAgICAgIGFkZENoaWxkKGNoaWxkcmVuLCBjaGlsZE5vZGVzLCB0YWcsIHByb3BzKTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICByZXR1cm4gbmV3IFZOb2RlKHRhZywgcHJvcHMsIGNoaWxkTm9kZXMsIGtleSwgbmFtZXNwYWNlKTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZnVuY3Rpb24gYWRkQ2hpbGQoYywgY2hpbGROb2RlcywgdGFnLCBwcm9wcykge1xuICAgICAgICAgICAgICAgIGlmICh0eXBlb2YgYyA9PT0gXCJzdHJpbmdcIikge1xuICAgICAgICAgICAgICAgICAgICBjaGlsZE5vZGVzLnB1c2gobmV3IFZUZXh0KGMpKTtcbiAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKHR5cGVvZiBjID09PSBcIm51bWJlclwiKSB7XG4gICAgICAgICAgICAgICAgICAgIGNoaWxkTm9kZXMucHVzaChuZXcgVlRleHQoU3RyaW5nKGMpKSk7XG4gICAgICAgICAgICAgICAgfSBlbHNlIGlmIChpc0NoaWxkKGMpKSB7XG4gICAgICAgICAgICAgICAgICAgIGNoaWxkTm9kZXMucHVzaChjKTtcbiAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKGlzQXJyYXkoYykpIHtcbiAgICAgICAgICAgICAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCBjLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBhZGRDaGlsZChjW2ldLCBjaGlsZE5vZGVzLCB0YWcsIHByb3BzKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoYyA9PT0gbnVsbCB8fCBjID09PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIHRocm93IFVuZXhwZWN0ZWRWaXJ0dWFsRWxlbWVudCh7XG4gICAgICAgICAgICAgICAgICAgICAgICBmb3JlaWduT2JqZWN0OiBjLFxuICAgICAgICAgICAgICAgICAgICAgICAgcGFyZW50Vm5vZGU6IHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0YWdOYW1lOiB0YWcsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcHJvcGVydGllczogcHJvcHNcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBmdW5jdGlvbiB0cmFuc2Zvcm1Qcm9wZXJ0aWVzKHByb3BzKSB7XG4gICAgICAgICAgICAgICAgZm9yICh2YXIgcHJvcE5hbWUgaW4gcHJvcHMpIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKHByb3BzLmhhc093blByb3BlcnR5KHByb3BOYW1lKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgdmFyIHZhbHVlID0gcHJvcHNbcHJvcE5hbWVdO1xuXG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoaXNIb29rKHZhbHVlKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnRpbnVlO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAocHJvcE5hbWUuc3Vic3RyKDAsIDMpID09PSBcImV2LVwiKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gYWRkIGV2LWZvbyBzdXBwb3J0XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcHJvcHNbcHJvcE5hbWVdID0gZXZIb29rKHZhbHVlKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZnVuY3Rpb24gaXNDaGlsZCh4KSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGlzVk5vZGUoeCkgfHwgaXNWVGV4dCh4KSB8fCBpc1dpZGdldCh4KSB8fCBpc1ZUaHVuayh4KTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZnVuY3Rpb24gaXNDaGlsZHJlbih4KSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHR5cGVvZiB4ID09PSBcInN0cmluZ1wiIHx8IGlzQXJyYXkoeCkgfHwgaXNDaGlsZCh4KTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZnVuY3Rpb24gVW5leHBlY3RlZFZpcnR1YWxFbGVtZW50KGRhdGEpIHtcbiAgICAgICAgICAgICAgICB2YXIgZXJyID0gbmV3IEVycm9yKCk7XG5cbiAgICAgICAgICAgICAgICBlcnIudHlwZSA9IFwidmlydHVhbC1oeXBlcnNjcmlwdC51bmV4cGVjdGVkLnZpcnR1YWwtZWxlbWVudFwiO1xuICAgICAgICAgICAgICAgIGVyci5tZXNzYWdlID0gXCJVbmV4cGVjdGVkIHZpcnR1YWwgY2hpbGQgcGFzc2VkIHRvIGgoKS5cXG5cIiArIFwiRXhwZWN0ZWQgYSBWTm9kZSAvIFZ0aHVuayAvIFZXaWRnZXQgLyBzdHJpbmcgYnV0OlxcblwiICsgXCJnb3Q6XFxuXCIgKyBlcnJvclN0cmluZyhkYXRhLmZvcmVpZ25PYmplY3QpICsgXCIuXFxuXCIgKyBcIlRoZSBwYXJlbnQgdm5vZGUgaXM6XFxuXCIgKyBlcnJvclN0cmluZyhkYXRhLnBhcmVudFZub2RlKTtcbiAgICAgICAgICAgICAgICBcIlxcblwiICsgXCJTdWdnZXN0ZWQgZml4OiBjaGFuZ2UgeW91ciBgaCguLi4sIFsgLi4uIF0pYCBjYWxsc2l0ZS5cIjtcbiAgICAgICAgICAgICAgICBlcnIuZm9yZWlnbk9iamVjdCA9IGRhdGEuZm9yZWlnbk9iamVjdDtcbiAgICAgICAgICAgICAgICBlcnIucGFyZW50Vm5vZGUgPSBkYXRhLnBhcmVudFZub2RlO1xuXG4gICAgICAgICAgICAgICAgcmV0dXJuIGVycjtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZnVuY3Rpb24gZXJyb3JTdHJpbmcob2JqKSB7XG4gICAgICAgICAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIEpTT04uc3RyaW5naWZ5KG9iaiwgbnVsbCwgXCIgICAgXCIpO1xuICAgICAgICAgICAgICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIFN0cmluZyhvYmopO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgfSwgeyBcIi4uL3Zub2RlL2lzLXRodW5rXCI6IDI1LCBcIi4uL3Zub2RlL2lzLXZob29rXCI6IDI2LCBcIi4uL3Zub2RlL2lzLXZub2RlXCI6IDI3LCBcIi4uL3Zub2RlL2lzLXZ0ZXh0XCI6IDI4LCBcIi4uL3Zub2RlL2lzLXdpZGdldFwiOiAyOSwgXCIuLi92bm9kZS92bm9kZS5qc1wiOiAzMSwgXCIuLi92bm9kZS92dGV4dC5qc1wiOiAzMywgXCIuL2hvb2tzL2V2LWhvb2suanNcIjogMjAsIFwiLi9ob29rcy9zb2Z0LXNldC1ob29rLmpzXCI6IDIxLCBcIi4vcGFyc2UtdGFnLmpzXCI6IDIzLCBcIngtaXMtYXJyYXlcIjogMTIgfV0sIDIzOiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge1xuICAgICAgICAgICAgXCJ1c2Ugc3RyaWN0XCI7XG5cbiAgICAgICAgICAgIHZhciBzcGxpdCA9IHJlcXVpcmUoXCJicm93c2VyLXNwbGl0XCIpO1xuXG4gICAgICAgICAgICB2YXIgY2xhc3NJZFNwbGl0ID0gLyhbXFwuI10/W2EtekEtWjAtOVxcdTAwN0YtXFx1RkZGRl86LV0rKS87XG4gICAgICAgICAgICB2YXIgbm90Q2xhc3NJZCA9IC9eXFwufCMvO1xuXG4gICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IHBhcnNlVGFnO1xuXG4gICAgICAgICAgICBmdW5jdGlvbiBwYXJzZVRhZyh0YWcsIHByb3BzKSB7XG4gICAgICAgICAgICAgICAgaWYgKCF0YWcpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIFwiRElWXCI7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgdmFyIG5vSWQgPSAhcHJvcHMuaGFzT3duUHJvcGVydHkoXCJpZFwiKTtcblxuICAgICAgICAgICAgICAgIHZhciB0YWdQYXJ0cyA9IHNwbGl0KHRhZywgY2xhc3NJZFNwbGl0KTtcbiAgICAgICAgICAgICAgICB2YXIgdGFnTmFtZSA9IG51bGw7XG5cbiAgICAgICAgICAgICAgICBpZiAobm90Q2xhc3NJZC50ZXN0KHRhZ1BhcnRzWzFdKSkge1xuICAgICAgICAgICAgICAgICAgICB0YWdOYW1lID0gXCJESVZcIjtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICB2YXIgY2xhc3NlcywgcGFydCwgdHlwZSwgaTtcblxuICAgICAgICAgICAgICAgIGZvciAoaSA9IDA7IGkgPCB0YWdQYXJ0cy5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgICAgICAgICBwYXJ0ID0gdGFnUGFydHNbaV07XG5cbiAgICAgICAgICAgICAgICAgICAgaWYgKCFwYXJ0KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBjb250aW51ZTtcbiAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgIHR5cGUgPSBwYXJ0LmNoYXJBdCgwKTtcblxuICAgICAgICAgICAgICAgICAgICBpZiAoIXRhZ05hbWUpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHRhZ05hbWUgPSBwYXJ0O1xuICAgICAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKHR5cGUgPT09IFwiLlwiKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBjbGFzc2VzID0gY2xhc3NlcyB8fCBbXTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGNsYXNzZXMucHVzaChwYXJ0LnN1YnN0cmluZygxLCBwYXJ0Lmxlbmd0aCkpO1xuICAgICAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKHR5cGUgPT09IFwiI1wiICYmIG5vSWQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHByb3BzLmlkID0gcGFydC5zdWJzdHJpbmcoMSwgcGFydC5sZW5ndGgpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgaWYgKGNsYXNzZXMpIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKHByb3BzLmNsYXNzTmFtZSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgY2xhc3Nlcy5wdXNoKHByb3BzLmNsYXNzTmFtZSk7XG4gICAgICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgICAgICBwcm9wcy5jbGFzc05hbWUgPSBjbGFzc2VzLmpvaW4oXCIgXCIpO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHJldHVybiBwcm9wcy5uYW1lc3BhY2UgPyB0YWdOYW1lIDogdGFnTmFtZS50b1VwcGVyQ2FzZSgpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9LCB7IFwiYnJvd3Nlci1zcGxpdFwiOiA1IH1dLCAyNDogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHtcbiAgICAgICAgICAgIHZhciBpc1ZOb2RlID0gcmVxdWlyZShcIi4vaXMtdm5vZGVcIik7XG4gICAgICAgICAgICB2YXIgaXNWVGV4dCA9IHJlcXVpcmUoXCIuL2lzLXZ0ZXh0XCIpO1xuICAgICAgICAgICAgdmFyIGlzV2lkZ2V0ID0gcmVxdWlyZShcIi4vaXMtd2lkZ2V0XCIpO1xuICAgICAgICAgICAgdmFyIGlzVGh1bmsgPSByZXF1aXJlKFwiLi9pcy10aHVua1wiKTtcblxuICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBoYW5kbGVUaHVuaztcblxuICAgICAgICAgICAgZnVuY3Rpb24gaGFuZGxlVGh1bmsoYSwgYikge1xuICAgICAgICAgICAgICAgIHZhciByZW5kZXJlZEEgPSBhO1xuICAgICAgICAgICAgICAgIHZhciByZW5kZXJlZEIgPSBiO1xuXG4gICAgICAgICAgICAgICAgaWYgKGlzVGh1bmsoYikpIHtcbiAgICAgICAgICAgICAgICAgICAgcmVuZGVyZWRCID0gcmVuZGVyVGh1bmsoYiwgYSk7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgaWYgKGlzVGh1bmsoYSkpIHtcbiAgICAgICAgICAgICAgICAgICAgcmVuZGVyZWRBID0gcmVuZGVyVGh1bmsoYSwgbnVsbCk7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgICAgICAgICAgYTogcmVuZGVyZWRBLFxuICAgICAgICAgICAgICAgICAgICBiOiByZW5kZXJlZEJcbiAgICAgICAgICAgICAgICB9O1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBmdW5jdGlvbiByZW5kZXJUaHVuayh0aHVuaywgcHJldmlvdXMpIHtcbiAgICAgICAgICAgICAgICB2YXIgcmVuZGVyZWRUaHVuayA9IHRodW5rLnZub2RlO1xuXG4gICAgICAgICAgICAgICAgaWYgKCFyZW5kZXJlZFRodW5rKSB7XG4gICAgICAgICAgICAgICAgICAgIHJlbmRlcmVkVGh1bmsgPSB0aHVuay52bm9kZSA9IHRodW5rLnJlbmRlcihwcmV2aW91cyk7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgaWYgKCEoaXNWTm9kZShyZW5kZXJlZFRodW5rKSB8fCBpc1ZUZXh0KHJlbmRlcmVkVGh1bmspIHx8IGlzV2lkZ2V0KHJlbmRlcmVkVGh1bmspKSkge1xuICAgICAgICAgICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoXCJ0aHVuayBkaWQgbm90IHJldHVybiBhIHZhbGlkIG5vZGVcIik7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgcmV0dXJuIHJlbmRlcmVkVGh1bms7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0sIHsgXCIuL2lzLXRodW5rXCI6IDI1LCBcIi4vaXMtdm5vZGVcIjogMjcsIFwiLi9pcy12dGV4dFwiOiAyOCwgXCIuL2lzLXdpZGdldFwiOiAyOSB9XSwgMjU6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IGlzVGh1bms7XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIGlzVGh1bmsodCkge1xuICAgICAgICAgICAgICAgIHJldHVybiB0ICYmIHQudHlwZSA9PT0gXCJUaHVua1wiO1xuICAgICAgICAgICAgfVxuICAgICAgICB9LCB7fV0sIDI2OiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge1xuICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBpc0hvb2s7XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIGlzSG9vayhob29rKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGhvb2sgJiYgKHR5cGVvZiBob29rLmhvb2sgPT09IFwiZnVuY3Rpb25cIiAmJiAhaG9vay5oYXNPd25Qcm9wZXJ0eShcImhvb2tcIikgfHwgdHlwZW9mIGhvb2sudW5ob29rID09PSBcImZ1bmN0aW9uXCIgJiYgIWhvb2suaGFzT3duUHJvcGVydHkoXCJ1bmhvb2tcIikpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9LCB7fV0sIDI3OiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge1xuICAgICAgICAgICAgdmFyIHZlcnNpb24gPSByZXF1aXJlKFwiLi92ZXJzaW9uXCIpO1xuXG4gICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IGlzVmlydHVhbE5vZGU7XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIGlzVmlydHVhbE5vZGUoeCkge1xuICAgICAgICAgICAgICAgIHJldHVybiB4ICYmIHgudHlwZSA9PT0gXCJWaXJ0dWFsTm9kZVwiICYmIHgudmVyc2lvbiA9PT0gdmVyc2lvbjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSwgeyBcIi4vdmVyc2lvblwiOiAzMCB9XSwgMjg6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICB2YXIgdmVyc2lvbiA9IHJlcXVpcmUoXCIuL3ZlcnNpb25cIik7XG5cbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gaXNWaXJ0dWFsVGV4dDtcblxuICAgICAgICAgICAgZnVuY3Rpb24gaXNWaXJ0dWFsVGV4dCh4KSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHggJiYgeC50eXBlID09PSBcIlZpcnR1YWxUZXh0XCIgJiYgeC52ZXJzaW9uID09PSB2ZXJzaW9uO1xuICAgICAgICAgICAgfVxuICAgICAgICB9LCB7IFwiLi92ZXJzaW9uXCI6IDMwIH1dLCAyOTogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHtcbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gaXNXaWRnZXQ7XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIGlzV2lkZ2V0KHcpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gdyAmJiB3LnR5cGUgPT09IFwiV2lkZ2V0XCI7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0sIHt9XSwgMzA6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IFwiMlwiO1xuICAgICAgICB9LCB7fV0sIDMxOiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge1xuICAgICAgICAgICAgdmFyIHZlcnNpb24gPSByZXF1aXJlKFwiLi92ZXJzaW9uXCIpO1xuICAgICAgICAgICAgdmFyIGlzVk5vZGUgPSByZXF1aXJlKFwiLi9pcy12bm9kZVwiKTtcbiAgICAgICAgICAgIHZhciBpc1dpZGdldCA9IHJlcXVpcmUoXCIuL2lzLXdpZGdldFwiKTtcbiAgICAgICAgICAgIHZhciBpc1RodW5rID0gcmVxdWlyZShcIi4vaXMtdGh1bmtcIik7XG4gICAgICAgICAgICB2YXIgaXNWSG9vayA9IHJlcXVpcmUoXCIuL2lzLXZob29rXCIpO1xuXG4gICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IFZpcnR1YWxOb2RlO1xuXG4gICAgICAgICAgICB2YXIgbm9Qcm9wZXJ0aWVzID0ge307XG4gICAgICAgICAgICB2YXIgbm9DaGlsZHJlbiA9IFtdO1xuXG4gICAgICAgICAgICBmdW5jdGlvbiBWaXJ0dWFsTm9kZSh0YWdOYW1lLCBwcm9wZXJ0aWVzLCBjaGlsZHJlbiwga2V5LCBuYW1lc3BhY2UpIHtcbiAgICAgICAgICAgICAgICB0aGlzLnRhZ05hbWUgPSB0YWdOYW1lO1xuICAgICAgICAgICAgICAgIHRoaXMucHJvcGVydGllcyA9IHByb3BlcnRpZXMgfHwgbm9Qcm9wZXJ0aWVzO1xuICAgICAgICAgICAgICAgIHRoaXMuY2hpbGRyZW4gPSBjaGlsZHJlbiB8fCBub0NoaWxkcmVuO1xuICAgICAgICAgICAgICAgIHRoaXMua2V5ID0ga2V5ICE9IG51bGwgPyBTdHJpbmcoa2V5KSA6IHVuZGVmaW5lZDtcbiAgICAgICAgICAgICAgICB0aGlzLm5hbWVzcGFjZSA9IHR5cGVvZiBuYW1lc3BhY2UgPT09IFwic3RyaW5nXCIgPyBuYW1lc3BhY2UgOiBudWxsO1xuXG4gICAgICAgICAgICAgICAgdmFyIGNvdW50ID0gY2hpbGRyZW4gJiYgY2hpbGRyZW4ubGVuZ3RoIHx8IDA7XG4gICAgICAgICAgICAgICAgdmFyIGRlc2NlbmRhbnRzID0gMDtcbiAgICAgICAgICAgICAgICB2YXIgaGFzV2lkZ2V0cyA9IGZhbHNlO1xuICAgICAgICAgICAgICAgIHZhciBoYXNUaHVua3MgPSBmYWxzZTtcbiAgICAgICAgICAgICAgICB2YXIgZGVzY2VuZGFudEhvb2tzID0gZmFsc2U7XG4gICAgICAgICAgICAgICAgdmFyIGhvb2tzO1xuXG4gICAgICAgICAgICAgICAgZm9yICh2YXIgcHJvcE5hbWUgaW4gcHJvcGVydGllcykge1xuICAgICAgICAgICAgICAgICAgICBpZiAocHJvcGVydGllcy5oYXNPd25Qcm9wZXJ0eShwcm9wTmFtZSkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHZhciBwcm9wZXJ0eSA9IHByb3BlcnRpZXNbcHJvcE5hbWVdO1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGlzVkhvb2socHJvcGVydHkpICYmIHByb3BlcnR5LnVuaG9vaykge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmICghaG9va3MpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaG9va3MgPSB7fTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBob29rc1twcm9wTmFtZV0gPSBwcm9wZXJ0eTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgY291bnQ7IGkrKykge1xuICAgICAgICAgICAgICAgICAgICB2YXIgY2hpbGQgPSBjaGlsZHJlbltpXTtcbiAgICAgICAgICAgICAgICAgICAgaWYgKGlzVk5vZGUoY2hpbGQpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBkZXNjZW5kYW50cyArPSBjaGlsZC5jb3VudCB8fCAwO1xuXG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoIWhhc1dpZGdldHMgJiYgY2hpbGQuaGFzV2lkZ2V0cykge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGhhc1dpZGdldHMgPSB0cnVlO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoIWhhc1RodW5rcyAmJiBjaGlsZC5oYXNUaHVua3MpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBoYXNUaHVua3MgPSB0cnVlO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoIWRlc2NlbmRhbnRIb29rcyAmJiAoY2hpbGQuaG9va3MgfHwgY2hpbGQuZGVzY2VuZGFudEhvb2tzKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRlc2NlbmRhbnRIb29rcyA9IHRydWU7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoIWhhc1dpZGdldHMgJiYgaXNXaWRnZXQoY2hpbGQpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAodHlwZW9mIGNoaWxkLmRlc3Ryb3kgPT09IFwiZnVuY3Rpb25cIikge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGhhc1dpZGdldHMgPSB0cnVlO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKCFoYXNUaHVua3MgJiYgaXNUaHVuayhjaGlsZCkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGhhc1RodW5rcyA9IHRydWU7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICB0aGlzLmNvdW50ID0gY291bnQgKyBkZXNjZW5kYW50cztcbiAgICAgICAgICAgICAgICB0aGlzLmhhc1dpZGdldHMgPSBoYXNXaWRnZXRzO1xuICAgICAgICAgICAgICAgIHRoaXMuaGFzVGh1bmtzID0gaGFzVGh1bmtzO1xuICAgICAgICAgICAgICAgIHRoaXMuaG9va3MgPSBob29rcztcbiAgICAgICAgICAgICAgICB0aGlzLmRlc2NlbmRhbnRIb29rcyA9IGRlc2NlbmRhbnRIb29rcztcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgVmlydHVhbE5vZGUucHJvdG90eXBlLnZlcnNpb24gPSB2ZXJzaW9uO1xuICAgICAgICAgICAgVmlydHVhbE5vZGUucHJvdG90eXBlLnR5cGUgPSBcIlZpcnR1YWxOb2RlXCI7XG4gICAgICAgIH0sIHsgXCIuL2lzLXRodW5rXCI6IDI1LCBcIi4vaXMtdmhvb2tcIjogMjYsIFwiLi9pcy12bm9kZVwiOiAyNywgXCIuL2lzLXdpZGdldFwiOiAyOSwgXCIuL3ZlcnNpb25cIjogMzAgfV0sIDMyOiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge1xuICAgICAgICAgICAgdmFyIHZlcnNpb24gPSByZXF1aXJlKFwiLi92ZXJzaW9uXCIpO1xuXG4gICAgICAgICAgICBWaXJ0dWFsUGF0Y2guTk9ORSA9IDA7XG4gICAgICAgICAgICBWaXJ0dWFsUGF0Y2guVlRFWFQgPSAxO1xuICAgICAgICAgICAgVmlydHVhbFBhdGNoLlZOT0RFID0gMjtcbiAgICAgICAgICAgIFZpcnR1YWxQYXRjaC5XSURHRVQgPSAzO1xuICAgICAgICAgICAgVmlydHVhbFBhdGNoLlBST1BTID0gNDtcbiAgICAgICAgICAgIFZpcnR1YWxQYXRjaC5PUkRFUiA9IDU7XG4gICAgICAgICAgICBWaXJ0dWFsUGF0Y2guSU5TRVJUID0gNjtcbiAgICAgICAgICAgIFZpcnR1YWxQYXRjaC5SRU1PVkUgPSA3O1xuICAgICAgICAgICAgVmlydHVhbFBhdGNoLlRIVU5LID0gODtcblxuICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBWaXJ0dWFsUGF0Y2g7XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIFZpcnR1YWxQYXRjaCh0eXBlLCB2Tm9kZSwgcGF0Y2gpIHtcbiAgICAgICAgICAgICAgICB0aGlzLnR5cGUgPSBOdW1iZXIodHlwZSk7XG4gICAgICAgICAgICAgICAgdGhpcy52Tm9kZSA9IHZOb2RlO1xuICAgICAgICAgICAgICAgIHRoaXMucGF0Y2ggPSBwYXRjaDtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgVmlydHVhbFBhdGNoLnByb3RvdHlwZS52ZXJzaW9uID0gdmVyc2lvbjtcbiAgICAgICAgICAgIFZpcnR1YWxQYXRjaC5wcm90b3R5cGUudHlwZSA9IFwiVmlydHVhbFBhdGNoXCI7XG4gICAgICAgIH0sIHsgXCIuL3ZlcnNpb25cIjogMzAgfV0sIDMzOiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge1xuICAgICAgICAgICAgdmFyIHZlcnNpb24gPSByZXF1aXJlKFwiLi92ZXJzaW9uXCIpO1xuXG4gICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IFZpcnR1YWxUZXh0O1xuXG4gICAgICAgICAgICBmdW5jdGlvbiBWaXJ0dWFsVGV4dCh0ZXh0KSB7XG4gICAgICAgICAgICAgICAgdGhpcy50ZXh0ID0gU3RyaW5nKHRleHQpO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBWaXJ0dWFsVGV4dC5wcm90b3R5cGUudmVyc2lvbiA9IHZlcnNpb247XG4gICAgICAgICAgICBWaXJ0dWFsVGV4dC5wcm90b3R5cGUudHlwZSA9IFwiVmlydHVhbFRleHRcIjtcbiAgICAgICAgfSwgeyBcIi4vdmVyc2lvblwiOiAzMCB9XSwgMzQ6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICB2YXIgaXNPYmplY3QgPSByZXF1aXJlKFwiaXMtb2JqZWN0XCIpO1xuICAgICAgICAgICAgdmFyIGlzSG9vayA9IHJlcXVpcmUoXCIuLi92bm9kZS9pcy12aG9va1wiKTtcblxuICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBkaWZmUHJvcHM7XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIGRpZmZQcm9wcyhhLCBiKSB7XG4gICAgICAgICAgICAgICAgdmFyIGRpZmY7XG5cbiAgICAgICAgICAgICAgICBmb3IgKHZhciBhS2V5IGluIGEpIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKCEoYUtleSBpbiBiKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgZGlmZiA9IGRpZmYgfHwge307XG4gICAgICAgICAgICAgICAgICAgICAgICBkaWZmW2FLZXldID0gdW5kZWZpbmVkO1xuICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgdmFyIGFWYWx1ZSA9IGFbYUtleV07XG4gICAgICAgICAgICAgICAgICAgIHZhciBiVmFsdWUgPSBiW2FLZXldO1xuXG4gICAgICAgICAgICAgICAgICAgIGlmIChhVmFsdWUgPT09IGJWYWx1ZSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgY29udGludWU7XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoaXNPYmplY3QoYVZhbHVlKSAmJiBpc09iamVjdChiVmFsdWUpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoZ2V0UHJvdG90eXBlKGJWYWx1ZSkgIT09IGdldFByb3RvdHlwZShhVmFsdWUpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgZGlmZiA9IGRpZmYgfHwge307XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgZGlmZlthS2V5XSA9IGJWYWx1ZTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoaXNIb29rKGJWYWx1ZSkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBkaWZmID0gZGlmZiB8fCB7fTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBkaWZmW2FLZXldID0gYlZhbHVlO1xuICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB2YXIgb2JqZWN0RGlmZiA9IGRpZmZQcm9wcyhhVmFsdWUsIGJWYWx1ZSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKG9iamVjdERpZmYpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZGlmZiA9IGRpZmYgfHwge307XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRpZmZbYUtleV0gPSBvYmplY3REaWZmO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGRpZmYgPSBkaWZmIHx8IHt9O1xuICAgICAgICAgICAgICAgICAgICAgICAgZGlmZlthS2V5XSA9IGJWYWx1ZTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIGZvciAodmFyIGJLZXkgaW4gYikge1xuICAgICAgICAgICAgICAgICAgICBpZiAoIShiS2V5IGluIGEpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBkaWZmID0gZGlmZiB8fCB7fTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGRpZmZbYktleV0gPSBiW2JLZXldO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgcmV0dXJuIGRpZmY7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIGdldFByb3RvdHlwZSh2YWx1ZSkge1xuICAgICAgICAgICAgICAgIGlmIChPYmplY3QuZ2V0UHJvdG90eXBlT2YpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIE9iamVjdC5nZXRQcm90b3R5cGVPZih2YWx1ZSk7XG4gICAgICAgICAgICAgICAgfSBlbHNlIGlmICh2YWx1ZS5fX3Byb3RvX18pIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHZhbHVlLl9fcHJvdG9fXztcbiAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKHZhbHVlLmNvbnN0cnVjdG9yKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiB2YWx1ZS5jb25zdHJ1Y3Rvci5wcm90b3R5cGU7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9LCB7IFwiLi4vdm5vZGUvaXMtdmhvb2tcIjogMjYsIFwiaXMtb2JqZWN0XCI6IDExIH1dLCAzNTogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHtcbiAgICAgICAgICAgIHZhciBpc0FycmF5ID0gcmVxdWlyZShcIngtaXMtYXJyYXlcIik7XG5cbiAgICAgICAgICAgIHZhciBWUGF0Y2ggPSByZXF1aXJlKFwiLi4vdm5vZGUvdnBhdGNoXCIpO1xuICAgICAgICAgICAgdmFyIGlzVk5vZGUgPSByZXF1aXJlKFwiLi4vdm5vZGUvaXMtdm5vZGVcIik7XG4gICAgICAgICAgICB2YXIgaXNWVGV4dCA9IHJlcXVpcmUoXCIuLi92bm9kZS9pcy12dGV4dFwiKTtcbiAgICAgICAgICAgIHZhciBpc1dpZGdldCA9IHJlcXVpcmUoXCIuLi92bm9kZS9pcy13aWRnZXRcIik7XG4gICAgICAgICAgICB2YXIgaXNUaHVuayA9IHJlcXVpcmUoXCIuLi92bm9kZS9pcy10aHVua1wiKTtcbiAgICAgICAgICAgIHZhciBoYW5kbGVUaHVuayA9IHJlcXVpcmUoXCIuLi92bm9kZS9oYW5kbGUtdGh1bmtcIik7XG5cbiAgICAgICAgICAgIHZhciBkaWZmUHJvcHMgPSByZXF1aXJlKFwiLi9kaWZmLXByb3BzXCIpO1xuXG4gICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IGRpZmY7XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIGRpZmYoYSwgYikge1xuICAgICAgICAgICAgICAgIHZhciBwYXRjaCA9IHsgYTogYSB9O1xuICAgICAgICAgICAgICAgIHdhbGsoYSwgYiwgcGF0Y2gsIDApO1xuICAgICAgICAgICAgICAgIHJldHVybiBwYXRjaDtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZnVuY3Rpb24gd2FsayhhLCBiLCBwYXRjaCwgaW5kZXgpIHtcbiAgICAgICAgICAgICAgICBpZiAoYSA9PT0gYikge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgdmFyIGFwcGx5ID0gcGF0Y2hbaW5kZXhdO1xuICAgICAgICAgICAgICAgIHZhciBhcHBseUNsZWFyID0gZmFsc2U7XG5cbiAgICAgICAgICAgICAgICBpZiAoaXNUaHVuayhhKSB8fCBpc1RodW5rKGIpKSB7XG4gICAgICAgICAgICAgICAgICAgIHRodW5rcyhhLCBiLCBwYXRjaCwgaW5kZXgpO1xuICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoYiA9PSBudWxsKSB7XG5cbiAgICAgICAgICAgICAgICAgICAgLy8gSWYgYSBpcyBhIHdpZGdldCB3ZSB3aWxsIGFkZCBhIHJlbW92ZSBwYXRjaCBmb3IgaXRcbiAgICAgICAgICAgICAgICAgICAgLy8gT3RoZXJ3aXNlIGFueSBjaGlsZCB3aWRnZXRzL2hvb2tzIG11c3QgYmUgZGVzdHJveWVkLlxuICAgICAgICAgICAgICAgICAgICAvLyBUaGlzIHByZXZlbnRzIGFkZGluZyB0d28gcmVtb3ZlIHBhdGNoZXMgZm9yIGEgd2lkZ2V0LlxuICAgICAgICAgICAgICAgICAgICBpZiAoIWlzV2lkZ2V0KGEpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBjbGVhclN0YXRlKGEsIHBhdGNoLCBpbmRleCk7XG4gICAgICAgICAgICAgICAgICAgICAgICBhcHBseSA9IHBhdGNoW2luZGV4XTtcbiAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgIGFwcGx5ID0gYXBwZW5kUGF0Y2goYXBwbHksIG5ldyBWUGF0Y2goVlBhdGNoLlJFTU9WRSwgYSwgYikpO1xuICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoaXNWTm9kZShiKSkge1xuICAgICAgICAgICAgICAgICAgICBpZiAoaXNWTm9kZShhKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGEudGFnTmFtZSA9PT0gYi50YWdOYW1lICYmIGEubmFtZXNwYWNlID09PSBiLm5hbWVzcGFjZSAmJiBhLmtleSA9PT0gYi5rZXkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB2YXIgcHJvcHNQYXRjaCA9IGRpZmZQcm9wcyhhLnByb3BlcnRpZXMsIGIucHJvcGVydGllcyk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHByb3BzUGF0Y2gpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYXBwbHkgPSBhcHBlbmRQYXRjaChhcHBseSwgbmV3IFZQYXRjaChWUGF0Y2guUFJPUFMsIGEsIHByb3BzUGF0Y2gpKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgYXBwbHkgPSBkaWZmQ2hpbGRyZW4oYSwgYiwgcGF0Y2gsIGFwcGx5LCBpbmRleCk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGFwcGx5ID0gYXBwZW5kUGF0Y2goYXBwbHksIG5ldyBWUGF0Y2goVlBhdGNoLlZOT0RFLCBhLCBiKSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgYXBwbHlDbGVhciA9IHRydWU7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBhcHBseSA9IGFwcGVuZFBhdGNoKGFwcGx5LCBuZXcgVlBhdGNoKFZQYXRjaC5WTk9ERSwgYSwgYikpO1xuICAgICAgICAgICAgICAgICAgICAgICAgYXBwbHlDbGVhciA9IHRydWU7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKGlzVlRleHQoYikpIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKCFpc1ZUZXh0KGEpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBhcHBseSA9IGFwcGVuZFBhdGNoKGFwcGx5LCBuZXcgVlBhdGNoKFZQYXRjaC5WVEVYVCwgYSwgYikpO1xuICAgICAgICAgICAgICAgICAgICAgICAgYXBwbHlDbGVhciA9IHRydWU7XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoYS50ZXh0ICE9PSBiLnRleHQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGFwcGx5ID0gYXBwZW5kUGF0Y2goYXBwbHksIG5ldyBWUGF0Y2goVlBhdGNoLlZURVhULCBhLCBiKSk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKGlzV2lkZ2V0KGIpKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmICghaXNXaWRnZXQoYSkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGFwcGx5Q2xlYXIgPSB0cnVlO1xuICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgYXBwbHkgPSBhcHBlbmRQYXRjaChhcHBseSwgbmV3IFZQYXRjaChWUGF0Y2guV0lER0VULCBhLCBiKSk7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgaWYgKGFwcGx5KSB7XG4gICAgICAgICAgICAgICAgICAgIHBhdGNoW2luZGV4XSA9IGFwcGx5O1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIGlmIChhcHBseUNsZWFyKSB7XG4gICAgICAgICAgICAgICAgICAgIGNsZWFyU3RhdGUoYSwgcGF0Y2gsIGluZGV4KTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIGRpZmZDaGlsZHJlbihhLCBiLCBwYXRjaCwgYXBwbHksIGluZGV4KSB7XG4gICAgICAgICAgICAgICAgdmFyIGFDaGlsZHJlbiA9IGEuY2hpbGRyZW47XG4gICAgICAgICAgICAgICAgdmFyIG9yZGVyZWRTZXQgPSByZW9yZGVyKGFDaGlsZHJlbiwgYi5jaGlsZHJlbik7XG4gICAgICAgICAgICAgICAgdmFyIGJDaGlsZHJlbiA9IG9yZGVyZWRTZXQuY2hpbGRyZW47XG5cbiAgICAgICAgICAgICAgICB2YXIgYUxlbiA9IGFDaGlsZHJlbi5sZW5ndGg7XG4gICAgICAgICAgICAgICAgdmFyIGJMZW4gPSBiQ2hpbGRyZW4ubGVuZ3RoO1xuICAgICAgICAgICAgICAgIHZhciBsZW4gPSBhTGVuID4gYkxlbiA/IGFMZW4gOiBiTGVuO1xuXG4gICAgICAgICAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCBsZW47IGkrKykge1xuICAgICAgICAgICAgICAgICAgICB2YXIgbGVmdE5vZGUgPSBhQ2hpbGRyZW5baV07XG4gICAgICAgICAgICAgICAgICAgIHZhciByaWdodE5vZGUgPSBiQ2hpbGRyZW5baV07XG4gICAgICAgICAgICAgICAgICAgIGluZGV4ICs9IDE7XG5cbiAgICAgICAgICAgICAgICAgICAgaWYgKCFsZWZ0Tm9kZSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHJpZ2h0Tm9kZSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIEV4Y2VzcyBub2RlcyBpbiBiIG5lZWQgdG8gYmUgYWRkZWRcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBhcHBseSA9IGFwcGVuZFBhdGNoKGFwcGx5LCBuZXcgVlBhdGNoKFZQYXRjaC5JTlNFUlQsIG51bGwsIHJpZ2h0Tm9kZSkpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgd2FsayhsZWZ0Tm9kZSwgcmlnaHROb2RlLCBwYXRjaCwgaW5kZXgpO1xuICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgaWYgKGlzVk5vZGUobGVmdE5vZGUpICYmIGxlZnROb2RlLmNvdW50KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBpbmRleCArPSBsZWZ0Tm9kZS5jb3VudDtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIGlmIChvcmRlcmVkU2V0Lm1vdmVzKSB7XG4gICAgICAgICAgICAgICAgICAgIC8vIFJlb3JkZXIgbm9kZXMgbGFzdFxuICAgICAgICAgICAgICAgICAgICBhcHBseSA9IGFwcGVuZFBhdGNoKGFwcGx5LCBuZXcgVlBhdGNoKFZQYXRjaC5PUkRFUiwgYSwgb3JkZXJlZFNldC5tb3ZlcykpO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHJldHVybiBhcHBseTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZnVuY3Rpb24gY2xlYXJTdGF0ZSh2Tm9kZSwgcGF0Y2gsIGluZGV4KSB7XG4gICAgICAgICAgICAgICAgLy8gVE9ETzogTWFrZSB0aGlzIGEgc2luZ2xlIHdhbGssIG5vdCB0d29cbiAgICAgICAgICAgICAgICB1bmhvb2sodk5vZGUsIHBhdGNoLCBpbmRleCk7XG4gICAgICAgICAgICAgICAgZGVzdHJveVdpZGdldHModk5vZGUsIHBhdGNoLCBpbmRleCk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIC8vIFBhdGNoIHJlY29yZHMgZm9yIGFsbCBkZXN0cm95ZWQgd2lkZ2V0cyBtdXN0IGJlIGFkZGVkIGJlY2F1c2Ugd2UgbmVlZFxuICAgICAgICAgICAgLy8gYSBET00gbm9kZSByZWZlcmVuY2UgZm9yIHRoZSBkZXN0cm95IGZ1bmN0aW9uXG4gICAgICAgICAgICBmdW5jdGlvbiBkZXN0cm95V2lkZ2V0cyh2Tm9kZSwgcGF0Y2gsIGluZGV4KSB7XG4gICAgICAgICAgICAgICAgaWYgKGlzV2lkZ2V0KHZOb2RlKSkge1xuICAgICAgICAgICAgICAgICAgICBpZiAodHlwZW9mIHZOb2RlLmRlc3Ryb3kgPT09IFwiZnVuY3Rpb25cIikge1xuICAgICAgICAgICAgICAgICAgICAgICAgcGF0Y2hbaW5kZXhdID0gYXBwZW5kUGF0Y2gocGF0Y2hbaW5kZXhdLCBuZXcgVlBhdGNoKFZQYXRjaC5SRU1PVkUsIHZOb2RlLCBudWxsKSk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKGlzVk5vZGUodk5vZGUpICYmICh2Tm9kZS5oYXNXaWRnZXRzIHx8IHZOb2RlLmhhc1RodW5rcykpIHtcbiAgICAgICAgICAgICAgICAgICAgdmFyIGNoaWxkcmVuID0gdk5vZGUuY2hpbGRyZW47XG4gICAgICAgICAgICAgICAgICAgIHZhciBsZW4gPSBjaGlsZHJlbi5sZW5ndGg7XG4gICAgICAgICAgICAgICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgbGVuOyBpKyspIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHZhciBjaGlsZCA9IGNoaWxkcmVuW2ldO1xuICAgICAgICAgICAgICAgICAgICAgICAgaW5kZXggKz0gMTtcblxuICAgICAgICAgICAgICAgICAgICAgICAgZGVzdHJveVdpZGdldHMoY2hpbGQsIHBhdGNoLCBpbmRleCk7XG5cbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChpc1ZOb2RlKGNoaWxkKSAmJiBjaGlsZC5jb3VudCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGluZGV4ICs9IGNoaWxkLmNvdW50O1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfSBlbHNlIGlmIChpc1RodW5rKHZOb2RlKSkge1xuICAgICAgICAgICAgICAgICAgICB0aHVua3Modk5vZGUsIG51bGwsIHBhdGNoLCBpbmRleCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAvLyBDcmVhdGUgYSBzdWItcGF0Y2ggZm9yIHRodW5rc1xuICAgICAgICAgICAgZnVuY3Rpb24gdGh1bmtzKGEsIGIsIHBhdGNoLCBpbmRleCkge1xuICAgICAgICAgICAgICAgIHZhciBub2RlcyA9IGhhbmRsZVRodW5rKGEsIGIpO1xuICAgICAgICAgICAgICAgIHZhciB0aHVua1BhdGNoID0gZGlmZihub2Rlcy5hLCBub2Rlcy5iKTtcbiAgICAgICAgICAgICAgICBpZiAoaGFzUGF0Y2hlcyh0aHVua1BhdGNoKSkge1xuICAgICAgICAgICAgICAgICAgICBwYXRjaFtpbmRleF0gPSBuZXcgVlBhdGNoKFZQYXRjaC5USFVOSywgbnVsbCwgdGh1bmtQYXRjaCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBmdW5jdGlvbiBoYXNQYXRjaGVzKHBhdGNoKSB7XG4gICAgICAgICAgICAgICAgZm9yICh2YXIgaW5kZXggaW4gcGF0Y2gpIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKGluZGV4ICE9PSBcImFcIikge1xuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIC8vIEV4ZWN1dGUgaG9va3Mgd2hlbiB0d28gbm9kZXMgYXJlIGlkZW50aWNhbFxuICAgICAgICAgICAgZnVuY3Rpb24gdW5ob29rKHZOb2RlLCBwYXRjaCwgaW5kZXgpIHtcbiAgICAgICAgICAgICAgICBpZiAoaXNWTm9kZSh2Tm9kZSkpIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKHZOb2RlLmhvb2tzKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBwYXRjaFtpbmRleF0gPSBhcHBlbmRQYXRjaChwYXRjaFtpbmRleF0sIG5ldyBWUGF0Y2goVlBhdGNoLlBST1BTLCB2Tm9kZSwgdW5kZWZpbmVkS2V5cyh2Tm9kZS5ob29rcykpKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgIGlmICh2Tm9kZS5kZXNjZW5kYW50SG9va3MgfHwgdk5vZGUuaGFzVGh1bmtzKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICB2YXIgY2hpbGRyZW4gPSB2Tm9kZS5jaGlsZHJlbjtcbiAgICAgICAgICAgICAgICAgICAgICAgIHZhciBsZW4gPSBjaGlsZHJlbi5sZW5ndGg7XG4gICAgICAgICAgICAgICAgICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IGxlbjsgaSsrKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdmFyIGNoaWxkID0gY2hpbGRyZW5baV07XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaW5kZXggKz0gMTtcblxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHVuaG9vayhjaGlsZCwgcGF0Y2gsIGluZGV4KTtcblxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChpc1ZOb2RlKGNoaWxkKSAmJiBjaGlsZC5jb3VudCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpbmRleCArPSBjaGlsZC5jb3VudDtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKGlzVGh1bmsodk5vZGUpKSB7XG4gICAgICAgICAgICAgICAgICAgIHRodW5rcyh2Tm9kZSwgbnVsbCwgcGF0Y2gsIGluZGV4KTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIHVuZGVmaW5lZEtleXMob2JqKSB7XG4gICAgICAgICAgICAgICAgdmFyIHJlc3VsdCA9IHt9O1xuXG4gICAgICAgICAgICAgICAgZm9yICh2YXIga2V5IGluIG9iaikge1xuICAgICAgICAgICAgICAgICAgICByZXN1bHRba2V5XSA9IHVuZGVmaW5lZDtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICByZXR1cm4gcmVzdWx0O1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAvLyBMaXN0IGRpZmYsIG5haXZlIGxlZnQgdG8gcmlnaHQgcmVvcmRlcmluZ1xuICAgICAgICAgICAgZnVuY3Rpb24gcmVvcmRlcihhQ2hpbGRyZW4sIGJDaGlsZHJlbikge1xuICAgICAgICAgICAgICAgIC8vIE8oTSkgdGltZSwgTyhNKSBtZW1vcnlcbiAgICAgICAgICAgICAgICB2YXIgYkNoaWxkSW5kZXggPSBrZXlJbmRleChiQ2hpbGRyZW4pO1xuICAgICAgICAgICAgICAgIHZhciBiS2V5cyA9IGJDaGlsZEluZGV4LmtleXM7XG4gICAgICAgICAgICAgICAgdmFyIGJGcmVlID0gYkNoaWxkSW5kZXguZnJlZTtcblxuICAgICAgICAgICAgICAgIGlmIChiRnJlZS5sZW5ndGggPT09IGJDaGlsZHJlbi5sZW5ndGgpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGNoaWxkcmVuOiBiQ2hpbGRyZW4sXG4gICAgICAgICAgICAgICAgICAgICAgICBtb3ZlczogbnVsbFxuICAgICAgICAgICAgICAgICAgICB9O1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIC8vIE8oTikgdGltZSwgTyhOKSBtZW1vcnlcbiAgICAgICAgICAgICAgICB2YXIgYUNoaWxkSW5kZXggPSBrZXlJbmRleChhQ2hpbGRyZW4pO1xuICAgICAgICAgICAgICAgIHZhciBhS2V5cyA9IGFDaGlsZEluZGV4LmtleXM7XG4gICAgICAgICAgICAgICAgdmFyIGFGcmVlID0gYUNoaWxkSW5kZXguZnJlZTtcblxuICAgICAgICAgICAgICAgIGlmIChhRnJlZS5sZW5ndGggPT09IGFDaGlsZHJlbi5sZW5ndGgpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGNoaWxkcmVuOiBiQ2hpbGRyZW4sXG4gICAgICAgICAgICAgICAgICAgICAgICBtb3ZlczogbnVsbFxuICAgICAgICAgICAgICAgICAgICB9O1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIC8vIE8oTUFYKE4sIE0pKSBtZW1vcnlcbiAgICAgICAgICAgICAgICB2YXIgbmV3Q2hpbGRyZW4gPSBbXTtcblxuICAgICAgICAgICAgICAgIHZhciBmcmVlSW5kZXggPSAwO1xuICAgICAgICAgICAgICAgIHZhciBmcmVlQ291bnQgPSBiRnJlZS5sZW5ndGg7XG4gICAgICAgICAgICAgICAgdmFyIGRlbGV0ZWRJdGVtcyA9IDA7XG5cbiAgICAgICAgICAgICAgICAvLyBJdGVyYXRlIHRocm91Z2ggYSBhbmQgbWF0Y2ggYSBub2RlIGluIGJcbiAgICAgICAgICAgICAgICAvLyBPKE4pIHRpbWUsXG4gICAgICAgICAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCBhQ2hpbGRyZW4ubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgICAgICAgICAgdmFyIGFJdGVtID0gYUNoaWxkcmVuW2ldO1xuICAgICAgICAgICAgICAgICAgICB2YXIgaXRlbUluZGV4O1xuXG4gICAgICAgICAgICAgICAgICAgIGlmIChhSXRlbS5rZXkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChiS2V5cy5oYXNPd25Qcm9wZXJ0eShhSXRlbS5rZXkpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gTWF0Y2ggdXAgdGhlIG9sZCBrZXlzXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaXRlbUluZGV4ID0gYktleXNbYUl0ZW0ua2V5XTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBuZXdDaGlsZHJlbi5wdXNoKGJDaGlsZHJlbltpdGVtSW5kZXhdKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gUmVtb3ZlIG9sZCBrZXllZCBpdGVtc1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGl0ZW1JbmRleCA9IGkgLSBkZWxldGVkSXRlbXMrKztcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBuZXdDaGlsZHJlbi5wdXNoKG51bGwpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgLy8gTWF0Y2ggdGhlIGl0ZW0gaW4gYSB3aXRoIHRoZSBuZXh0IGZyZWUgaXRlbSBpbiBiXG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoZnJlZUluZGV4IDwgZnJlZUNvdW50KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaXRlbUluZGV4ID0gYkZyZWVbZnJlZUluZGV4KytdO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIG5ld0NoaWxkcmVuLnB1c2goYkNoaWxkcmVuW2l0ZW1JbmRleF0pO1xuICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBUaGVyZSBhcmUgbm8gZnJlZSBpdGVtcyBpbiBiIHRvIG1hdGNoIHdpdGhcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyB0aGUgZnJlZSBpdGVtcyBpbiBhLCBzbyB0aGUgZXh0cmEgZnJlZSBub2Rlc1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIGFyZSBkZWxldGVkLlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGl0ZW1JbmRleCA9IGkgLSBkZWxldGVkSXRlbXMrKztcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBuZXdDaGlsZHJlbi5wdXNoKG51bGwpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgdmFyIGxhc3RGcmVlSW5kZXggPSBmcmVlSW5kZXggPj0gYkZyZWUubGVuZ3RoID8gYkNoaWxkcmVuLmxlbmd0aCA6IGJGcmVlW2ZyZWVJbmRleF07XG5cbiAgICAgICAgICAgICAgICAvLyBJdGVyYXRlIHRocm91Z2ggYiBhbmQgYXBwZW5kIGFueSBuZXcga2V5c1xuICAgICAgICAgICAgICAgIC8vIE8oTSkgdGltZVxuICAgICAgICAgICAgICAgIGZvciAodmFyIGogPSAwOyBqIDwgYkNoaWxkcmVuLmxlbmd0aDsgaisrKSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciBuZXdJdGVtID0gYkNoaWxkcmVuW2pdO1xuXG4gICAgICAgICAgICAgICAgICAgIGlmIChuZXdJdGVtLmtleSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKCFhS2V5cy5oYXNPd25Qcm9wZXJ0eShuZXdJdGVtLmtleSkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBBZGQgYW55IG5ldyBrZXllZCBpdGVtc1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIFdlIGFyZSBhZGRpbmcgbmV3IGl0ZW1zIHRvIHRoZSBlbmQgYW5kIHRoZW4gc29ydGluZyB0aGVtXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gaW4gcGxhY2UuIEluIGZ1dHVyZSB3ZSBzaG91bGQgaW5zZXJ0IG5ldyBpdGVtcyBpbiBwbGFjZS5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBuZXdDaGlsZHJlbi5wdXNoKG5ld0l0ZW0pO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKGogPj0gbGFzdEZyZWVJbmRleCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgLy8gQWRkIGFueSBsZWZ0b3ZlciBub24ta2V5ZWQgaXRlbXNcbiAgICAgICAgICAgICAgICAgICAgICAgIG5ld0NoaWxkcmVuLnB1c2gobmV3SXRlbSk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICB2YXIgc2ltdWxhdGUgPSBuZXdDaGlsZHJlbi5zbGljZSgpO1xuICAgICAgICAgICAgICAgIHZhciBzaW11bGF0ZUluZGV4ID0gMDtcbiAgICAgICAgICAgICAgICB2YXIgcmVtb3ZlcyA9IFtdO1xuICAgICAgICAgICAgICAgIHZhciBpbnNlcnRzID0gW107XG4gICAgICAgICAgICAgICAgdmFyIHNpbXVsYXRlSXRlbTtcblxuICAgICAgICAgICAgICAgIGZvciAodmFyIGsgPSAwOyBrIDwgYkNoaWxkcmVuLmxlbmd0aDspIHtcbiAgICAgICAgICAgICAgICAgICAgdmFyIHdhbnRlZEl0ZW0gPSBiQ2hpbGRyZW5ba107XG4gICAgICAgICAgICAgICAgICAgIHNpbXVsYXRlSXRlbSA9IHNpbXVsYXRlW3NpbXVsYXRlSW5kZXhdO1xuXG4gICAgICAgICAgICAgICAgICAgIC8vIHJlbW92ZSBpdGVtc1xuICAgICAgICAgICAgICAgICAgICB3aGlsZSAoc2ltdWxhdGVJdGVtID09PSBudWxsICYmIHNpbXVsYXRlLmxlbmd0aCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgcmVtb3Zlcy5wdXNoKHJlbW92ZShzaW11bGF0ZSwgc2ltdWxhdGVJbmRleCwgbnVsbCkpO1xuICAgICAgICAgICAgICAgICAgICAgICAgc2ltdWxhdGVJdGVtID0gc2ltdWxhdGVbc2ltdWxhdGVJbmRleF07XG4gICAgICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgICAgICBpZiAoIXNpbXVsYXRlSXRlbSB8fCBzaW11bGF0ZUl0ZW0ua2V5ICE9PSB3YW50ZWRJdGVtLmtleSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgLy8gaWYgd2UgbmVlZCBhIGtleSBpbiB0aGlzIHBvc2l0aW9uLi4uXG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAod2FudGVkSXRlbS5rZXkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoc2ltdWxhdGVJdGVtICYmIHNpbXVsYXRlSXRlbS5rZXkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gaWYgYW4gaW5zZXJ0IGRvZXNuJ3QgcHV0IHRoaXMga2V5IGluIHBsYWNlLCBpdCBuZWVkcyB0byBtb3ZlXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChiS2V5c1tzaW11bGF0ZUl0ZW0ua2V5XSAhPT0gayArIDEpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlbW92ZXMucHVzaChyZW1vdmUoc2ltdWxhdGUsIHNpbXVsYXRlSW5kZXgsIHNpbXVsYXRlSXRlbS5rZXkpKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNpbXVsYXRlSXRlbSA9IHNpbXVsYXRlW3NpbXVsYXRlSW5kZXhdO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gaWYgdGhlIHJlbW92ZSBkaWRuJ3QgcHV0IHRoZSB3YW50ZWQgaXRlbSBpbiBwbGFjZSwgd2UgbmVlZCB0byBpbnNlcnQgaXRcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmICghc2ltdWxhdGVJdGVtIHx8IHNpbXVsYXRlSXRlbS5rZXkgIT09IHdhbnRlZEl0ZW0ua2V5KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaW5zZXJ0cy5wdXNoKHsga2V5OiB3YW50ZWRJdGVtLmtleSwgdG86IGsgfSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBpdGVtcyBhcmUgbWF0Y2hpbmcsIHNvIHNraXAgYWhlYWRcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNpbXVsYXRlSW5kZXgrKztcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGluc2VydHMucHVzaCh7IGtleTogd2FudGVkSXRlbS5rZXksIHRvOiBrIH0pO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaW5zZXJ0cy5wdXNoKHsga2V5OiB3YW50ZWRJdGVtLmtleSwgdG86IGsgfSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGsrKztcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIGEga2V5IGluIHNpbXVsYXRlIGhhcyBubyBtYXRjaGluZyB3YW50ZWQga2V5LCByZW1vdmUgaXRcbiAgICAgICAgICAgICAgICAgICAgICAgIGVsc2UgaWYgKHNpbXVsYXRlSXRlbSAmJiBzaW11bGF0ZUl0ZW0ua2V5KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcmVtb3Zlcy5wdXNoKHJlbW92ZShzaW11bGF0ZSwgc2ltdWxhdGVJbmRleCwgc2ltdWxhdGVJdGVtLmtleSkpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgc2ltdWxhdGVJbmRleCsrO1xuICAgICAgICAgICAgICAgICAgICAgICAgaysrO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgLy8gcmVtb3ZlIGFsbCB0aGUgcmVtYWluaW5nIG5vZGVzIGZyb20gc2ltdWxhdGVcbiAgICAgICAgICAgICAgICB3aGlsZSAoc2ltdWxhdGVJbmRleCA8IHNpbXVsYXRlLmxlbmd0aCkge1xuICAgICAgICAgICAgICAgICAgICBzaW11bGF0ZUl0ZW0gPSBzaW11bGF0ZVtzaW11bGF0ZUluZGV4XTtcbiAgICAgICAgICAgICAgICAgICAgcmVtb3Zlcy5wdXNoKHJlbW92ZShzaW11bGF0ZSwgc2ltdWxhdGVJbmRleCwgc2ltdWxhdGVJdGVtICYmIHNpbXVsYXRlSXRlbS5rZXkpKTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAvLyBJZiB0aGUgb25seSBtb3ZlcyB3ZSBoYXZlIGFyZSBkZWxldGVzIHRoZW4gd2UgY2FuIGp1c3RcbiAgICAgICAgICAgICAgICAvLyBsZXQgdGhlIGRlbGV0ZSBwYXRjaCByZW1vdmUgdGhlc2UgaXRlbXMuXG4gICAgICAgICAgICAgICAgaWYgKHJlbW92ZXMubGVuZ3RoID09PSBkZWxldGVkSXRlbXMgJiYgIWluc2VydHMubGVuZ3RoKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiB7XG4gICAgICAgICAgICAgICAgICAgICAgICBjaGlsZHJlbjogbmV3Q2hpbGRyZW4sXG4gICAgICAgICAgICAgICAgICAgICAgICBtb3ZlczogbnVsbFxuICAgICAgICAgICAgICAgICAgICB9O1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHJldHVybiB7XG4gICAgICAgICAgICAgICAgICAgIGNoaWxkcmVuOiBuZXdDaGlsZHJlbixcbiAgICAgICAgICAgICAgICAgICAgbW92ZXM6IHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJlbW92ZXM6IHJlbW92ZXMsXG4gICAgICAgICAgICAgICAgICAgICAgICBpbnNlcnRzOiBpbnNlcnRzXG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9O1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBmdW5jdGlvbiByZW1vdmUoYXJyLCBpbmRleCwga2V5KSB7XG4gICAgICAgICAgICAgICAgYXJyLnNwbGljZShpbmRleCwgMSk7XG5cbiAgICAgICAgICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgICAgICAgICBmcm9tOiBpbmRleCxcbiAgICAgICAgICAgICAgICAgICAga2V5OiBrZXlcbiAgICAgICAgICAgICAgICB9O1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBmdW5jdGlvbiBrZXlJbmRleChjaGlsZHJlbikge1xuICAgICAgICAgICAgICAgIHZhciBrZXlzID0ge307XG4gICAgICAgICAgICAgICAgdmFyIGZyZWUgPSBbXTtcbiAgICAgICAgICAgICAgICB2YXIgbGVuZ3RoID0gY2hpbGRyZW4ubGVuZ3RoO1xuXG4gICAgICAgICAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCBsZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgICAgICAgICB2YXIgY2hpbGQgPSBjaGlsZHJlbltpXTtcblxuICAgICAgICAgICAgICAgICAgICBpZiAoY2hpbGQua2V5KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBrZXlzW2NoaWxkLmtleV0gPSBpO1xuICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgZnJlZS5wdXNoKGkpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgICAgICAgICAga2V5czoga2V5cywgLy8gQSBoYXNoIG9mIGtleSBuYW1lIHRvIGluZGV4XG4gICAgICAgICAgICAgICAgICAgIGZyZWU6IGZyZWUgLy8gQW4gYXJyYXkgb2YgdW5rZXllZCBpdGVtIGluZGljZXNcbiAgICAgICAgICAgICAgICB9O1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBmdW5jdGlvbiBhcHBlbmRQYXRjaChhcHBseSwgcGF0Y2gpIHtcbiAgICAgICAgICAgICAgICBpZiAoYXBwbHkpIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKGlzQXJyYXkoYXBwbHkpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBhcHBseS5wdXNoKHBhdGNoKTtcbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGFwcGx5ID0gW2FwcGx5LCBwYXRjaF07XG4gICAgICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgICAgICByZXR1cm4gYXBwbHk7XG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHBhdGNoO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgfSwgeyBcIi4uL3Zub2RlL2hhbmRsZS10aHVua1wiOiAyNCwgXCIuLi92bm9kZS9pcy10aHVua1wiOiAyNSwgXCIuLi92bm9kZS9pcy12bm9kZVwiOiAyNywgXCIuLi92bm9kZS9pcy12dGV4dFwiOiAyOCwgXCIuLi92bm9kZS9pcy13aWRnZXRcIjogMjksIFwiLi4vdm5vZGUvdnBhdGNoXCI6IDMyLCBcIi4vZGlmZi1wcm9wc1wiOiAzNCwgXCJ4LWlzLWFycmF5XCI6IDEyIH1dIH0sIHt9LCBbNF0pKDQpO1xufSk7XG5cbmNvbnN0IENvcmUgPSBDO1xuXG5leHBvcnQgeyBDb3JlLCBLZXJuZWwsIEVudW0sIExpc3QsIEtleXdvcmQsIGJpdHdpc2UgYXMgQml0d2lzZSwgbWFwIGFzIE1hcCwgbWFwX3NldCBhcyBNYXBTZXQsIFZpcnR1YWxET00gfTsiXSwiZmlsZSI6IkVsaXhpci5qcyIsInNvdXJjZVJvb3QiOiIvc291cmNlLyJ9 \ No newline at end of file +//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiIiwic291cmNlcyI6WyJFbGl4aXIuanMiXSwic291cmNlc0NvbnRlbnQiOlsiLyogQGZsb3cgKi9cblxuY2xhc3MgTWFpbGJveCB7XG5cbiAgY29uc3RydWN0b3IoKSB7XG4gICAgdGhpcy5tZXNzYWdlcyA9IFtdO1xuICB9XG5cbiAgZGVsaXZlcihtZXNzYWdlKSB7XG4gICAgdGhpcy5tZXNzYWdlcy5wdXNoKG1lc3NhZ2UpO1xuICAgIHJldHVybiBtZXNzYWdlO1xuICB9XG5cbiAgZ2V0KCkge1xuICAgIHJldHVybiB0aGlzLm1lc3NhZ2VzO1xuICB9XG5cbiAgaXNFbXB0eSgpIHtcbiAgICByZXR1cm4gdGhpcy5tZXNzYWdlcy5sZW5ndGggPT09IDA7XG4gIH1cblxuICByZW1vdmVBdChpbmRleCkge1xuICAgIHRoaXMubWVzc2FnZXMuc3BsaWNlKGluZGV4LCAxKTtcbiAgfVxufVxuXG52YXIgU3RhdGVzID0ge1xuICBOT1JNQUw6IFN5bWJvbC5mb3IoXCJub3JtYWxcIiksXG4gIEtJTEw6IFN5bWJvbC5mb3IoXCJraWxsXCIpLFxuICBTVVNQRU5EOiBTeW1ib2wuZm9yKFwic3VzcGVuZFwiKSxcbiAgQ09OVElOVUU6IFN5bWJvbC5mb3IoXCJjb250aW51ZVwiKSxcbiAgUkVDRUlWRTogU3ltYm9sLmZvcihcInJlY2VpdmVcIiksXG4gIFNFTkQ6IFN5bWJvbC5mb3IoXCJzZW5kXCIpLFxuICBTTEVFUElORzogU3ltYm9sLmZvcihcInNsZWVwaW5nXCIpLFxuICBSVU5OSU5HOiBTeW1ib2wuZm9yKFwicnVubmluZ1wiKSxcbiAgU1VTUEVOREVEOiBTeW1ib2wuZm9yKFwic3VzcGVuZGVkXCIpLFxuICBTVE9QUEVEOiBTeW1ib2wuZm9yKFwic3RvcHBlZFwiKSxcbiAgU0xFRVA6IFN5bWJvbC5mb3IoXCJzbGVlcFwiKSxcbiAgRVhJVDogU3ltYm9sLmZvcihcImV4aXRcIiksXG4gIE5PTUFUQ0g6IFN5bWJvbC5mb3IoXCJub19tYXRjaFwiKVxufTtcblxuY2xhc3MgUHJvY2VzcyB7XG5cbiAgY29uc3RydWN0b3IocGlkLCBtYWlsYm94KSB7XG4gICAgdGhpcy5waWQgPSBwaWQ7XG4gICAgdGhpcy5tYWlsYm94ID0gbWFpbGJveDtcbiAgICB0aGlzLnN0YXR1cyA9IFN0YXRlcy5TVE9QUEVEO1xuICAgIHRoaXMuZGljdCA9IHt9O1xuICB9XG59XG5cbmNsYXNzIFR1cGxlIHtcblxuICBjb25zdHJ1Y3RvciguLi5hcmdzKSB7XG4gICAgdGhpcy52YWx1ZXMgPSBPYmplY3QuZnJlZXplKGFyZ3MpO1xuICAgIHRoaXMubGVuZ3RoID0gdGhpcy52YWx1ZXMubGVuZ3RoO1xuICB9XG5cbiAgZ2V0KGluZGV4KSB7XG4gICAgcmV0dXJuIHRoaXMudmFsdWVzW2luZGV4XTtcbiAgfVxuXG4gIGNvdW50KCkge1xuICAgIHJldHVybiB0aGlzLnZhbHVlcy5sZW5ndGg7XG4gIH1cblxuICBbU3ltYm9sLml0ZXJhdG9yXSgpIHtcbiAgICByZXR1cm4gdGhpcy52YWx1ZXNbU3ltYm9sLml0ZXJhdG9yXSgpO1xuICB9XG5cbiAgdG9TdHJpbmcoKSB7XG4gICAgdmFyIGksXG4gICAgICAgIHMgPSBcIlwiO1xuICAgIGZvciAoaSA9IDA7IGkgPCB0aGlzLnZhbHVlcy5sZW5ndGg7IGkrKykge1xuICAgICAgaWYgKHMgIT09IFwiXCIpIHtcbiAgICAgICAgcyArPSBcIiwgXCI7XG4gICAgICB9XG4gICAgICBzICs9IHRoaXMudmFsdWVzW2ldLnRvU3RyaW5nKCk7XG4gICAgfVxuXG4gICAgcmV0dXJuIFwie1wiICsgcyArIFwifVwiO1xuICB9XG5cbn1cblxubGV0IHByb2Nlc3NfY291bnRlciA9IC0xO1xuXG5jbGFzcyBQSUQge1xuICBjb25zdHJ1Y3RvcigpIHtcbiAgICBwcm9jZXNzX2NvdW50ZXIgPSBwcm9jZXNzX2NvdW50ZXIgKyAxO1xuICAgIHRoaXMuaWQgPSBwcm9jZXNzX2NvdW50ZXI7XG4gIH1cblxuICB0b1N0cmluZygpIHtcbiAgICByZXR1cm4gXCJQSUQjPDAuXCIgKyB0aGlzLmlkICsgXCIuMD5cIjtcbiAgfVxufVxuXG5jbGFzcyBJbnRlZ2VyIHt9XG5jbGFzcyBGbG9hdCB7fVxuXG5mdW5jdGlvbiBMaXN0JDEoLi4uYXJncykge1xuICByZXR1cm4gT2JqZWN0LmZyZWV6ZShhcmdzKTtcbn1cblxuY2xhc3MgUHJvY2Vzc1N5c3RlbSB7XG5cbiAgY29uc3RydWN0b3IoKSB7XG4gICAgdGhpcy5waWRzID0gbmV3IE1hcCgpO1xuICAgIHRoaXMubWFpbGJveGVzID0gbmV3IE1hcCgpO1xuICAgIHRoaXMubmFtZXMgPSBuZXcgTWFwKCk7XG4gICAgdGhpcy5saW5rcyA9IG5ldyBNYXAoKTtcblxuICAgIHRoaXMuY3VycmVudF9wcm9jZXNzID0gbnVsbDtcbiAgICB0aGlzLnN1c3BlbmRlZCA9IG5ldyBNYXAoKTtcblxuICAgIHRoaXMubWFpbl9wcm9jZXNzX3BpZCA9IHRoaXMuc3Bhd24oKTtcbiAgICB0aGlzLnNldF9jdXJyZW50KHRoaXMubWFpbl9wcm9jZXNzX3BpZCk7XG4gIH1cblxuICBzcGF3bigpIHtcbiAgICByZXR1cm4gdGhpcy5hZGRfcHJvYyhmYWxzZSkucGlkO1xuICB9XG5cbiAgc3Bhd25fbGluaygpIHtcbiAgICByZXR1cm4gdGhpcy5hZGRfcHJvYyh0cnVlKS5waWQ7XG4gIH1cblxuICBsaW5rKHBpZCkge1xuICAgIHRoaXMubGlua3MuZ2V0KHRoaXMucGlkKCkpLmFkZChwaWQpO1xuICAgIHRoaXMubGlua3MuZ2V0KHBpZCkuYWRkKHRoaXMucGlkKCkpO1xuICB9XG5cbiAgdW5saW5rKHBpZCkge1xuICAgIHRoaXMubGlua3MuZ2V0KHRoaXMucGlkKCkpLmRlbGV0ZShwaWQpO1xuICAgIHRoaXMubGlua3MuZ2V0KHBpZCkuZGVsZXRlKHRoaXMucGlkKCkpO1xuICB9XG5cbiAgc2V0X2N1cnJlbnQoaWQpIHtcbiAgICBsZXQgcGlkID0gdGhpcy5waWRvZihpZCk7XG4gICAgaWYgKHBpZCAhPT0gbnVsbCkge1xuICAgICAgdGhpcy5jdXJyZW50X3Byb2Nlc3MgPSB0aGlzLnBpZHMuZ2V0KHBpZCk7XG4gICAgICB0aGlzLmN1cnJlbnRfcHJvY2Vzcy5zdGF0dXMgPSBTdGF0ZXMuUlVOTklORztcbiAgICB9XG4gIH1cblxuICBhZGRfcHJvYyhsaW5rZWQpIHtcbiAgICBsZXQgbmV3cGlkID0gbmV3IFBJRCgpO1xuICAgIGxldCBtYWlsYm94ID0gbmV3IE1haWxib3goKTtcbiAgICBsZXQgbmV3cHJvYyA9IG5ldyBQcm9jZXNzKG5ld3BpZCwgbWFpbGJveCk7XG5cbiAgICB0aGlzLnBpZHMuc2V0KG5ld3BpZCwgbmV3cHJvYyk7XG4gICAgdGhpcy5tYWlsYm94ZXMuc2V0KG5ld3BpZCwgbWFpbGJveCk7XG4gICAgdGhpcy5saW5rcy5zZXQobmV3cGlkLCBuZXcgU2V0KCkpO1xuXG4gICAgaWYgKGxpbmtlZCkge1xuICAgICAgdGhpcy5saW5rKG5ld3BpZCk7XG4gICAgfVxuXG4gICAgcmV0dXJuIG5ld3Byb2M7XG4gIH1cblxuICByZW1vdmVfcHJvYyhwaWQpIHtcbiAgICB0aGlzLnBpZHMuZGVsZXRlKHBpZCk7XG4gICAgdGhpcy51bnJlZ2lzdGVyKHBpZCk7XG5cbiAgICBpZiAodGhpcy5saW5rcy5oYXMocGlkKSkge1xuICAgICAgZm9yIChsZXQgbGlua3BpZCBvZiB0aGlzLmxpbmtzLmdldChwaWQpKSB7XG4gICAgICAgIHRoaXMubGlua3MuZ2V0KGxpbmtwaWQpLmRlbGV0ZShwaWQpO1xuICAgICAgfVxuXG4gICAgICB0aGlzLmxpbmtzLmRlbGV0ZShwaWQpO1xuICAgIH1cbiAgfVxuXG4gIGV4aXQoaWQpIHtcbiAgICBsZXQgcGlkID0gdGhpcy5waWRvZihpZCk7XG4gICAgdGhpcy5yZW1vdmVfcHJvYyhpZCk7XG4gIH1cblxuICByZWdpc3RlcihuYW1lLCBwaWQpIHtcbiAgICBpZiAoIXRoaXMubmFtZXMuaGFzKG5hbWUpKSB7XG4gICAgICB0aGlzLm5hbWVzLnNldChuYW1lLCBwaWQpO1xuICAgICAgcmV0dXJuIG5hbWU7XG4gICAgfSBlbHNlIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcihcIk5hbWUgaXMgYWxyZWFkeSByZWdpc3RlcmVkIHRvIGFub3RoZXIgcHJvY2Vzc1wiKTtcbiAgICB9XG4gIH1cblxuICByZWdpc3RlcmVkKG5hbWUpIHtcbiAgICByZXR1cm4gdGhpcy5uYW1lcy5oYXMobmFtZSkgPyB0aGlzLm5hbWVzLmdldChuYW1lKSA6IG51bGw7XG4gIH1cblxuICB1bnJlZ2lzdGVyKHBpZCkge1xuICAgIGZvciAobGV0IG5hbWUgb2YgdGhpcy5uYW1lcy5rZXlzKCkpIHtcbiAgICAgIGlmICh0aGlzLm5hbWVzLmhhcyhuYW1lKSAmJiB0aGlzLm5hbWVzLmdldChuYW1lKSA9PT0gcGlkKSB7XG4gICAgICAgIHRoaXMubmFtZXMuZGVsZXRlKG5hbWUpO1xuICAgICAgfVxuICAgIH1cbiAgfVxuXG4gIHBpZCgpIHtcbiAgICByZXR1cm4gdGhpcy5jdXJyZW50X3Byb2Nlc3MucGlkO1xuICB9XG5cbiAgcGlkb2YoaWQpIHtcbiAgICBpZiAoaWQgaW5zdGFuY2VvZiBQSUQpIHtcbiAgICAgIHJldHVybiB0aGlzLnBpZHMuaGFzKGlkKSA/IGlkIDogbnVsbDtcbiAgICB9IGVsc2UgaWYgKGlkIGluc3RhbmNlb2YgUHJvY2Vzcykge1xuICAgICAgcmV0dXJuIGlkLnBpZDtcbiAgICB9IGVsc2Uge1xuICAgICAgbGV0IHBpZCA9IHRoaXMucmVnaXN0ZXJlZChpZCk7XG4gICAgICBpZiAocGlkID09PSBudWxsKSB0aHJvdyBcIlByb2Nlc3MgbmFtZSBub3QgcmVnaXN0ZXJlZDogXCIgKyBpZCArIFwiIChcIiArIHR5cGVvZiBpZCArIFwiKVwiO1xuICAgICAgcmV0dXJuIHBpZDtcbiAgICB9XG4gIH1cblxuICBwdXQoaWQsIGtleSwgdmFsdWUpIHtcbiAgICBsZXQgcGlkID0gdGhpcy5waWRvZihpZCk7XG4gICAgbGV0IHByb2Nlc3MgPSB0aGlzLnBpZHMuZ2V0KHBpZCk7XG4gICAgcHJvY2Vzcy5kaWN0W2tleV0gPSB2YWx1ZTtcbiAgfVxuXG4gIGdldChpZCwga2V5KSB7XG4gICAgbGV0IHBpZCA9IHRoaXMucGlkb2YoaWQpO1xuICAgIGxldCBwcm9jZXNzID0gdGhpcy5waWRzLmdldChwaWQpO1xuXG4gICAgaWYgKGtleSAhPSBudWxsKSB7XG4gICAgICByZXR1cm4gcHJvY2Vzcy5kaWN0W2tleV07XG4gICAgfSBlbHNlIHtcbiAgICAgIHJldHVybiBwcm9jZXNzLmRpY3Q7XG4gICAgfVxuICB9XG5cbiAgZ2V0X2tleXMoaWQpIHtcbiAgICBsZXQgcGlkID0gdGhpcy5waWRvZihpZCk7XG4gICAgbGV0IHByb2Nlc3MgPSB0aGlzLnBpZHMuZ2V0KHBpZCk7XG5cbiAgICByZXR1cm4gT2JqZWN0LmtleXMocHJvY2Vzcy5kaWN0KTtcbiAgfVxuXG4gIGVyYXNlKGlkLCBrZXkpIHtcbiAgICBsZXQgcGlkID0gdGhpcy5waWRvZihpZCk7XG4gICAgbGV0IHByb2Nlc3MgPSB0aGlzLnBpZHMuZ2V0KHBpZCk7XG5cbiAgICBpZiAoa2V5ICE9IG51bGwpIHtcbiAgICAgIGRlbGV0ZSBwcm9jZXNzLmRpY3Rba2V5XTtcbiAgICB9IGVsc2Uge1xuICAgICAgcHJvY2Vzcy5kaWN0ID0ge307XG4gICAgfVxuICB9XG59XG5cbmNsYXNzIEJpdFN0cmluZyB7XG4gIGNvbnN0cnVjdG9yKC4uLmFyZ3MpIHtcbiAgICB0aGlzLnJhd192YWx1ZSA9IGZ1bmN0aW9uICgpIHtcbiAgICAgIHJldHVybiBPYmplY3QuZnJlZXplKGFyZ3MpO1xuICAgIH07XG5cbiAgICB0aGlzLnZhbHVlID0gT2JqZWN0LmZyZWV6ZSh0aGlzLnByb2Nlc3MoYXJncykpO1xuICB9XG5cbiAgZ2V0KGluZGV4KSB7XG4gICAgcmV0dXJuIHRoaXMudmFsdWVbaW5kZXhdO1xuICB9XG5cbiAgY291bnQoKSB7XG4gICAgcmV0dXJuIHRoaXMudmFsdWUubGVuZ3RoO1xuICB9XG5cbiAgW1N5bWJvbC5pdGVyYXRvcl0oKSB7XG4gICAgcmV0dXJuIHRoaXMudmFsdWVbU3ltYm9sLml0ZXJhdG9yXSgpO1xuICB9XG5cbiAgdG9TdHJpbmcoKSB7XG4gICAgdmFyIGksXG4gICAgICAgIHMgPSBcIlwiO1xuICAgIGZvciAoaSA9IDA7IGkgPCB0aGlzLmNvdW50KCk7IGkrKykge1xuICAgICAgaWYgKHMgIT09IFwiXCIpIHtcbiAgICAgICAgcyArPSBcIiwgXCI7XG4gICAgICB9XG4gICAgICBzICs9IHRoaXNbaV0udG9TdHJpbmcoKTtcbiAgICB9XG5cbiAgICByZXR1cm4gXCI8PFwiICsgcyArIFwiPj5cIjtcbiAgfVxuXG4gIHByb2Nlc3MoKSB7XG4gICAgbGV0IHByb2Nlc3NlZF92YWx1ZXMgPSBbXTtcblxuICAgIHZhciBpO1xuICAgIGZvciAoaSA9IDA7IGkgPCB0aGlzLnJhd192YWx1ZSgpLmxlbmd0aDsgaSsrKSB7XG4gICAgICBsZXQgcHJvY2Vzc2VkX3ZhbHVlID0gdGhpc1tcInByb2Nlc3NfXCIgKyB0aGlzLnJhd192YWx1ZSgpW2ldLnR5cGVdKHRoaXMucmF3X3ZhbHVlKClbaV0pO1xuXG4gICAgICBmb3IgKGxldCBhdHRyIG9mIHRoaXMucmF3X3ZhbHVlKClbaV0uYXR0cmlidXRlcykge1xuICAgICAgICBwcm9jZXNzZWRfdmFsdWUgPSB0aGlzW1wicHJvY2Vzc19cIiArIGF0dHJdKHByb2Nlc3NlZF92YWx1ZSk7XG4gICAgICB9XG5cbiAgICAgIHByb2Nlc3NlZF92YWx1ZXMgPSBwcm9jZXNzZWRfdmFsdWVzLmNvbmNhdChwcm9jZXNzZWRfdmFsdWUpO1xuICAgIH1cblxuICAgIHJldHVybiBwcm9jZXNzZWRfdmFsdWVzO1xuICB9XG5cbiAgcHJvY2Vzc19pbnRlZ2VyKHZhbHVlKSB7XG4gICAgcmV0dXJuIHZhbHVlLnZhbHVlO1xuICB9XG5cbiAgcHJvY2Vzc19mbG9hdCh2YWx1ZSkge1xuICAgIGlmICh2YWx1ZS5zaXplID09PSA2NCkge1xuICAgICAgcmV0dXJuIEJpdFN0cmluZy5mbG9hdDY0VG9CeXRlcyh2YWx1ZS52YWx1ZSk7XG4gICAgfSBlbHNlIGlmICh2YWx1ZS5zaXplID09PSAzMikge1xuICAgICAgcmV0dXJuIEJpdFN0cmluZy5mbG9hdDMyVG9CeXRlcyh2YWx1ZS52YWx1ZSk7XG4gICAgfVxuXG4gICAgdGhyb3cgbmV3IEVycm9yKFwiSW52YWxpZCBzaXplIGZvciBmbG9hdFwiKTtcbiAgfVxuXG4gIHByb2Nlc3NfYml0c3RyaW5nKHZhbHVlKSB7XG4gICAgcmV0dXJuIHZhbHVlLnZhbHVlLnZhbHVlO1xuICB9XG5cbiAgcHJvY2Vzc19iaW5hcnkodmFsdWUpIHtcbiAgICByZXR1cm4gQml0U3RyaW5nLnRvVVRGOEFycmF5KHZhbHVlLnZhbHVlKTtcbiAgfVxuXG4gIHByb2Nlc3NfdXRmOCh2YWx1ZSkge1xuICAgIHJldHVybiBCaXRTdHJpbmcudG9VVEY4QXJyYXkodmFsdWUudmFsdWUpO1xuICB9XG5cbiAgcHJvY2Vzc191dGYxNih2YWx1ZSkge1xuICAgIHJldHVybiBCaXRTdHJpbmcudG9VVEYxNkFycmF5KHZhbHVlLnZhbHVlKTtcbiAgfVxuXG4gIHByb2Nlc3NfdXRmMzIodmFsdWUpIHtcbiAgICByZXR1cm4gQml0U3RyaW5nLnRvVVRGMzJBcnJheSh2YWx1ZS52YWx1ZSk7XG4gIH1cblxuICBwcm9jZXNzX3NpZ25lZCh2YWx1ZSkge1xuICAgIHJldHVybiBuZXcgVWludDhBcnJheShbdmFsdWVdKVswXTtcbiAgfVxuXG4gIHByb2Nlc3NfdW5zaWduZWQodmFsdWUpIHtcbiAgICByZXR1cm4gdmFsdWU7XG4gIH1cblxuICBwcm9jZXNzX25hdGl2ZSh2YWx1ZSkge1xuICAgIHJldHVybiB2YWx1ZTtcbiAgfVxuXG4gIHByb2Nlc3NfYmlnKHZhbHVlKSB7XG4gICAgcmV0dXJuIHZhbHVlO1xuICB9XG5cbiAgcHJvY2Vzc19saXR0bGUodmFsdWUpIHtcbiAgICByZXR1cm4gdmFsdWUucmV2ZXJzZSgpO1xuICB9XG5cbiAgcHJvY2Vzc19zaXplKHZhbHVlKSB7XG4gICAgcmV0dXJuIHZhbHVlO1xuICB9XG5cbiAgcHJvY2Vzc191bml0KHZhbHVlKSB7XG4gICAgcmV0dXJuIHZhbHVlO1xuICB9XG5cbiAgc3RhdGljIGludGVnZXIodmFsdWUpIHtcbiAgICByZXR1cm4gQml0U3RyaW5nLndyYXAodmFsdWUsIHsgXCJ0eXBlXCI6IFwiaW50ZWdlclwiLCBcInVuaXRcIjogMSwgXCJzaXplXCI6IDggfSk7XG4gIH1cblxuICBzdGF0aWMgZmxvYXQodmFsdWUpIHtcbiAgICByZXR1cm4gQml0U3RyaW5nLndyYXAodmFsdWUsIHsgXCJ0eXBlXCI6IFwiZmxvYXRcIiwgXCJ1bml0XCI6IDEsIFwic2l6ZVwiOiA2NCB9KTtcbiAgfVxuXG4gIHN0YXRpYyBiaXRzdHJpbmcodmFsdWUpIHtcbiAgICByZXR1cm4gQml0U3RyaW5nLndyYXAodmFsdWUsIHsgXCJ0eXBlXCI6IFwiYml0c3RyaW5nXCIsIFwidW5pdFwiOiAxLCBcInNpemVcIjogdmFsdWUubGVuZ3RoIH0pO1xuICB9XG5cbiAgc3RhdGljIGJpdHModmFsdWUpIHtcbiAgICByZXR1cm4gQml0U3RyaW5nLmJpdHN0cmluZyh2YWx1ZSk7XG4gIH1cblxuICBzdGF0aWMgYmluYXJ5KHZhbHVlKSB7XG4gICAgcmV0dXJuIEJpdFN0cmluZy53cmFwKHZhbHVlLCB7IFwidHlwZVwiOiBcImJpbmFyeVwiLCBcInVuaXRcIjogOCwgXCJzaXplXCI6IHZhbHVlLmxlbmd0aCB9KTtcbiAgfVxuXG4gIHN0YXRpYyBieXRlcyh2YWx1ZSkge1xuICAgIHJldHVybiBCaXRTdHJpbmcuYmluYXJ5KHZhbHVlKTtcbiAgfVxuXG4gIHN0YXRpYyB1dGY4KHZhbHVlKSB7XG4gICAgcmV0dXJuIEJpdFN0cmluZy53cmFwKHZhbHVlLCB7IFwidHlwZVwiOiBcInV0ZjhcIiB9KTtcbiAgfVxuXG4gIHN0YXRpYyB1dGYxNih2YWx1ZSkge1xuICAgIHJldHVybiBCaXRTdHJpbmcud3JhcCh2YWx1ZSwgeyBcInR5cGVcIjogXCJ1dGYxNlwiIH0pO1xuICB9XG5cbiAgc3RhdGljIHV0ZjMyKHZhbHVlKSB7XG4gICAgcmV0dXJuIEJpdFN0cmluZy53cmFwKHZhbHVlLCB7IFwidHlwZVwiOiBcInV0ZjMyXCIgfSk7XG4gIH1cblxuICBzdGF0aWMgc2lnbmVkKHZhbHVlKSB7XG4gICAgcmV0dXJuIEJpdFN0cmluZy53cmFwKHZhbHVlLCB7fSwgXCJzaWduZWRcIik7XG4gIH1cblxuICBzdGF0aWMgdW5zaWduZWQodmFsdWUpIHtcbiAgICByZXR1cm4gQml0U3RyaW5nLndyYXAodmFsdWUsIHt9LCBcInVuc2lnbmVkXCIpO1xuICB9XG5cbiAgc3RhdGljIG5hdGl2ZSh2YWx1ZSkge1xuICAgIHJldHVybiBCaXRTdHJpbmcud3JhcCh2YWx1ZSwge30sIFwibmF0aXZlXCIpO1xuICB9XG5cbiAgc3RhdGljIGJpZyh2YWx1ZSkge1xuICAgIHJldHVybiBCaXRTdHJpbmcud3JhcCh2YWx1ZSwge30sIFwiYmlnXCIpO1xuICB9XG5cbiAgc3RhdGljIGxpdHRsZSh2YWx1ZSkge1xuICAgIHJldHVybiBCaXRTdHJpbmcud3JhcCh2YWx1ZSwge30sIFwibGl0dGxlXCIpO1xuICB9XG5cbiAgc3RhdGljIHNpemUodmFsdWUsIGNvdW50KSB7XG4gICAgcmV0dXJuIEJpdFN0cmluZy53cmFwKHZhbHVlLCB7IFwic2l6ZVwiOiBjb3VudCB9KTtcbiAgfVxuXG4gIHN0YXRpYyB1bml0KHZhbHVlLCBjb3VudCkge1xuICAgIHJldHVybiBCaXRTdHJpbmcud3JhcCh2YWx1ZSwgeyBcInVuaXRcIjogY291bnQgfSk7XG4gIH1cblxuICBzdGF0aWMgd3JhcCh2YWx1ZSwgb3B0LCBuZXdfYXR0cmlidXRlID0gbnVsbCkge1xuICAgIGxldCB0aGVfdmFsdWUgPSB2YWx1ZTtcblxuICAgIGlmICghKHZhbHVlIGluc3RhbmNlb2YgT2JqZWN0KSkge1xuICAgICAgdGhlX3ZhbHVlID0geyBcInZhbHVlXCI6IHZhbHVlLCBcImF0dHJpYnV0ZXNcIjogW10gfTtcbiAgICB9XG5cbiAgICB0aGVfdmFsdWUgPSBPYmplY3QuYXNzaWduKHRoZV92YWx1ZSwgb3B0KTtcblxuICAgIGlmIChuZXdfYXR0cmlidXRlKSB7XG4gICAgICB0aGVfdmFsdWUuYXR0cmlidXRlcy5wdXNoKG5ld19hdHRyaWJ1dGUpO1xuICAgIH1cblxuICAgIHJldHVybiB0aGVfdmFsdWU7XG4gIH1cblxuICBzdGF0aWMgdG9VVEY4QXJyYXkoc3RyKSB7XG4gICAgdmFyIHV0ZjggPSBbXTtcbiAgICBmb3IgKHZhciBpID0gMDsgaSA8IHN0ci5sZW5ndGg7IGkrKykge1xuICAgICAgdmFyIGNoYXJjb2RlID0gc3RyLmNoYXJDb2RlQXQoaSk7XG4gICAgICBpZiAoY2hhcmNvZGUgPCAxMjgpIHtcbiAgICAgICAgdXRmOC5wdXNoKGNoYXJjb2RlKTtcbiAgICAgIH0gZWxzZSBpZiAoY2hhcmNvZGUgPCAyMDQ4KSB7XG4gICAgICAgIHV0ZjgucHVzaCgxOTIgfCBjaGFyY29kZSA+PiA2LCAxMjggfCBjaGFyY29kZSAmIDYzKTtcbiAgICAgIH0gZWxzZSBpZiAoY2hhcmNvZGUgPCA1NTI5NiB8fCBjaGFyY29kZSA+PSA1NzM0NCkge1xuICAgICAgICB1dGY4LnB1c2goMjI0IHwgY2hhcmNvZGUgPj4gMTIsIDEyOCB8IGNoYXJjb2RlID4+IDYgJiA2MywgMTI4IHwgY2hhcmNvZGUgJiA2Myk7XG4gICAgICB9XG4gICAgICAvLyBzdXJyb2dhdGUgcGFpclxuICAgICAgZWxzZSB7XG4gICAgICAgIGkrKztcbiAgICAgICAgLy8gVVRGLTE2IGVuY29kZXMgMHgxMDAwMC0weDEwRkZGRiBieVxuICAgICAgICAvLyBzdWJ0cmFjdGluZyAweDEwMDAwIGFuZCBzcGxpdHRpbmcgdGhlXG4gICAgICAgIC8vIDIwIGJpdHMgb2YgMHgwLTB4RkZGRkYgaW50byB0d28gaGFsdmVzXG4gICAgICAgIGNoYXJjb2RlID0gNjU1MzYgKyAoKGNoYXJjb2RlICYgMTAyMykgPDwgMTAgfCBzdHIuY2hhckNvZGVBdChpKSAmIDEwMjMpO1xuICAgICAgICB1dGY4LnB1c2goMjQwIHwgY2hhcmNvZGUgPj4gMTgsIDEyOCB8IGNoYXJjb2RlID4+IDEyICYgNjMsIDEyOCB8IGNoYXJjb2RlID4+IDYgJiA2MywgMTI4IHwgY2hhcmNvZGUgJiA2Myk7XG4gICAgICB9XG4gICAgfVxuICAgIHJldHVybiB1dGY4O1xuICB9XG5cbiAgc3RhdGljIHRvVVRGMTZBcnJheShzdHIpIHtcbiAgICB2YXIgdXRmMTYgPSBbXTtcbiAgICBmb3IgKHZhciBpID0gMDsgaSA8IHN0ci5sZW5ndGg7IGkrKykge1xuICAgICAgdmFyIGNvZGVQb2ludCA9IHN0ci5jb2RlUG9pbnRBdChpKTtcblxuICAgICAgaWYgKGNvZGVQb2ludCA8PSAyNTUpIHtcbiAgICAgICAgdXRmMTYucHVzaCgwKTtcbiAgICAgICAgdXRmMTYucHVzaChjb2RlUG9pbnQpO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgdXRmMTYucHVzaChjb2RlUG9pbnQgPj4gOCAmIDI1NSk7XG4gICAgICAgIHV0ZjE2LnB1c2goY29kZVBvaW50ICYgMjU1KTtcbiAgICAgIH1cbiAgICB9XG4gICAgcmV0dXJuIHV0ZjE2O1xuICB9XG5cbiAgc3RhdGljIHRvVVRGMzJBcnJheShzdHIpIHtcbiAgICB2YXIgdXRmMzIgPSBbXTtcbiAgICBmb3IgKHZhciBpID0gMDsgaSA8IHN0ci5sZW5ndGg7IGkrKykge1xuICAgICAgdmFyIGNvZGVQb2ludCA9IHN0ci5jb2RlUG9pbnRBdChpKTtcblxuICAgICAgaWYgKGNvZGVQb2ludCA8PSAyNTUpIHtcbiAgICAgICAgdXRmMzIucHVzaCgwKTtcbiAgICAgICAgdXRmMzIucHVzaCgwKTtcbiAgICAgICAgdXRmMzIucHVzaCgwKTtcbiAgICAgICAgdXRmMzIucHVzaChjb2RlUG9pbnQpO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgdXRmMzIucHVzaCgwKTtcbiAgICAgICAgdXRmMzIucHVzaCgwKTtcbiAgICAgICAgdXRmMzIucHVzaChjb2RlUG9pbnQgPj4gOCAmIDI1NSk7XG4gICAgICAgIHV0ZjMyLnB1c2goY29kZVBvaW50ICYgMjU1KTtcbiAgICAgIH1cbiAgICB9XG4gICAgcmV0dXJuIHV0ZjMyO1xuICB9XG5cbiAgLy9odHRwOi8vc3RhY2tvdmVyZmxvdy5jb20vcXVlc3Rpb25zLzIwMDM0OTMvamF2YXNjcmlwdC1mbG9hdC1mcm9tLXRvLWJpdHNcbiAgc3RhdGljIGZsb2F0MzJUb0J5dGVzKGYpIHtcbiAgICB2YXIgYnl0ZXMgPSBbXTtcblxuICAgIHZhciBidWYgPSBuZXcgQXJyYXlCdWZmZXIoNCk7XG4gICAgbmV3IEZsb2F0MzJBcnJheShidWYpWzBdID0gZjtcblxuICAgIGxldCBpbnRWZXJzaW9uID0gbmV3IFVpbnQzMkFycmF5KGJ1ZilbMF07XG5cbiAgICBieXRlcy5wdXNoKGludFZlcnNpb24gPj4gMjQgJiAyNTUpO1xuICAgIGJ5dGVzLnB1c2goaW50VmVyc2lvbiA+PiAxNiAmIDI1NSk7XG4gICAgYnl0ZXMucHVzaChpbnRWZXJzaW9uID4+IDggJiAyNTUpO1xuICAgIGJ5dGVzLnB1c2goaW50VmVyc2lvbiAmIDI1NSk7XG5cbiAgICByZXR1cm4gYnl0ZXM7XG4gIH1cblxuICBzdGF0aWMgZmxvYXQ2NFRvQnl0ZXMoZikge1xuICAgIHZhciBieXRlcyA9IFtdO1xuXG4gICAgdmFyIGJ1ZiA9IG5ldyBBcnJheUJ1ZmZlcig4KTtcbiAgICBuZXcgRmxvYXQ2NEFycmF5KGJ1ZilbMF0gPSBmO1xuXG4gICAgdmFyIGludFZlcnNpb24xID0gbmV3IFVpbnQzMkFycmF5KGJ1ZilbMF07XG4gICAgdmFyIGludFZlcnNpb24yID0gbmV3IFVpbnQzMkFycmF5KGJ1ZilbMV07XG5cbiAgICBieXRlcy5wdXNoKGludFZlcnNpb24yID4+IDI0ICYgMjU1KTtcbiAgICBieXRlcy5wdXNoKGludFZlcnNpb24yID4+IDE2ICYgMjU1KTtcbiAgICBieXRlcy5wdXNoKGludFZlcnNpb24yID4+IDggJiAyNTUpO1xuICAgIGJ5dGVzLnB1c2goaW50VmVyc2lvbjIgJiAyNTUpO1xuXG4gICAgYnl0ZXMucHVzaChpbnRWZXJzaW9uMSA+PiAyNCAmIDI1NSk7XG4gICAgYnl0ZXMucHVzaChpbnRWZXJzaW9uMSA+PiAxNiAmIDI1NSk7XG4gICAgYnl0ZXMucHVzaChpbnRWZXJzaW9uMSA+PiA4ICYgMjU1KTtcbiAgICBieXRlcy5wdXNoKGludFZlcnNpb24xICYgMjU1KTtcblxuICAgIHJldHVybiBieXRlcztcbiAgfVxufVxuXG4vKiBAZmxvdyAqL1xuXG5jbGFzcyBWYXJpYWJsZSB7XG5cbiAgY29uc3RydWN0b3IobmFtZSA9IG51bGwpIHtcbiAgICB0aGlzLm5hbWUgPSBuYW1lO1xuICB9XG59XG5cbmNsYXNzIFdpbGRjYXJkIHtcbiAgY29uc3RydWN0b3IoKSB7fVxufVxuXG5jbGFzcyBTdGFydHNXaXRoIHtcblxuICBjb25zdHJ1Y3RvcihwcmVmaXgpIHtcbiAgICB0aGlzLnByZWZpeCA9IHByZWZpeDtcbiAgfVxufVxuXG5jbGFzcyBDYXB0dXJlIHtcblxuICBjb25zdHJ1Y3Rvcih2YWx1ZSkge1xuICAgIHRoaXMudmFsdWUgPSB2YWx1ZTtcbiAgfVxufVxuXG5jbGFzcyBIZWFkVGFpbCB7XG4gIGNvbnN0cnVjdG9yKCkge31cbn1cblxuY2xhc3MgVHlwZSB7XG5cbiAgY29uc3RydWN0b3IodHlwZSwgb2JqUGF0dGVybiA9IHt9KSB7XG4gICAgdGhpcy50eXBlID0gdHlwZTtcbiAgICB0aGlzLm9ialBhdHRlcm4gPSBvYmpQYXR0ZXJuO1xuICB9XG59XG5cbmNsYXNzIEJvdW5kIHtcblxuICBjb25zdHJ1Y3Rvcih2YWx1ZSkge1xuICAgIHRoaXMudmFsdWUgPSB2YWx1ZTtcbiAgfVxufVxuXG5mdW5jdGlvbiB2YXJpYWJsZShuYW1lID0gbnVsbCkge1xuICByZXR1cm4gbmV3IFZhcmlhYmxlKG5hbWUpO1xufVxuXG5mdW5jdGlvbiB3aWxkY2FyZCgpIHtcbiAgcmV0dXJuIG5ldyBXaWxkY2FyZCgpO1xufVxuXG5mdW5jdGlvbiBzdGFydHNXaXRoKHByZWZpeCkge1xuICByZXR1cm4gbmV3IFN0YXJ0c1dpdGgocHJlZml4KTtcbn1cblxuZnVuY3Rpb24gY2FwdHVyZSh2YWx1ZSkge1xuICByZXR1cm4gbmV3IENhcHR1cmUodmFsdWUpO1xufVxuXG5mdW5jdGlvbiBoZWFkVGFpbCgpIHtcbiAgcmV0dXJuIG5ldyBIZWFkVGFpbCgpO1xufVxuXG5mdW5jdGlvbiB0eXBlKHR5cGUsIG9ialBhdHRlcm4gPSB7fSkge1xuICByZXR1cm4gbmV3IFR5cGUodHlwZSwgb2JqUGF0dGVybik7XG59XG5cbmZ1bmN0aW9uIGJvdW5kKHZhbHVlKSB7XG4gIHJldHVybiBuZXcgQm91bmQodmFsdWUpO1xufVxuXG5mdW5jdGlvbiBpc19udW1iZXIkMih2YWx1ZSkge1xuICByZXR1cm4gdHlwZW9mIHZhbHVlID09PSAnbnVtYmVyJztcbn1cblxuZnVuY3Rpb24gaXNfc3RyaW5nKHZhbHVlKSB7XG4gIHJldHVybiB0eXBlb2YgdmFsdWUgPT09ICdzdHJpbmcnO1xufVxuXG5mdW5jdGlvbiBpc19ib29sZWFuJDIodmFsdWUpIHtcbiAgcmV0dXJuIHR5cGVvZiB2YWx1ZSA9PT0gJ2Jvb2xlYW4nO1xufVxuXG5mdW5jdGlvbiBpc19zeW1ib2wodmFsdWUpIHtcbiAgcmV0dXJuIHR5cGVvZiB2YWx1ZSA9PT0gJ3N5bWJvbCc7XG59XG5cbmZ1bmN0aW9uIGlzX251bGwodmFsdWUpIHtcbiAgcmV0dXJuIHZhbHVlID09PSBudWxsO1xufVxuXG5mdW5jdGlvbiBpc191bmRlZmluZWQodmFsdWUpIHtcbiAgcmV0dXJuIHR5cGVvZiB2YWx1ZSA9PT0gJ3VuZGVmaW5lZCc7XG59XG5cbmZ1bmN0aW9uIGlzX2Z1bmN0aW9uJDIodmFsdWUpIHtcbiAgcmV0dXJuIE9iamVjdC5wcm90b3R5cGUudG9TdHJpbmcuY2FsbCh2YWx1ZSkgPT0gJ1tvYmplY3QgRnVuY3Rpb25dJztcbn1cblxuZnVuY3Rpb24gaXNfdmFyaWFibGUodmFsdWUpIHtcbiAgcmV0dXJuIHZhbHVlIGluc3RhbmNlb2YgVmFyaWFibGU7XG59XG5cbmZ1bmN0aW9uIGlzX3dpbGRjYXJkKHZhbHVlKSB7XG4gIHJldHVybiB2YWx1ZSBpbnN0YW5jZW9mIFdpbGRjYXJkO1xufVxuXG5mdW5jdGlvbiBpc19oZWFkVGFpbCh2YWx1ZSkge1xuICByZXR1cm4gdmFsdWUgaW5zdGFuY2VvZiBIZWFkVGFpbDtcbn1cblxuZnVuY3Rpb24gaXNfY2FwdHVyZSh2YWx1ZSkge1xuICByZXR1cm4gdmFsdWUgaW5zdGFuY2VvZiBDYXB0dXJlO1xufVxuXG5mdW5jdGlvbiBpc190eXBlKHZhbHVlKSB7XG4gIHJldHVybiB2YWx1ZSBpbnN0YW5jZW9mIFR5cGU7XG59XG5cbmZ1bmN0aW9uIGlzX3N0YXJ0c1dpdGgodmFsdWUpIHtcbiAgcmV0dXJuIHZhbHVlIGluc3RhbmNlb2YgU3RhcnRzV2l0aDtcbn1cblxuZnVuY3Rpb24gaXNfYm91bmQodmFsdWUpIHtcbiAgcmV0dXJuIHZhbHVlIGluc3RhbmNlb2YgQm91bmQ7XG59XG5cbmZ1bmN0aW9uIGlzX29iamVjdCh2YWx1ZSkge1xuICByZXR1cm4gdHlwZW9mIHZhbHVlID09PSAnb2JqZWN0Jztcbn1cblxuZnVuY3Rpb24gaXNfYXJyYXkodmFsdWUpIHtcbiAgcmV0dXJuIEFycmF5LmlzQXJyYXkodmFsdWUpO1xufVxuXG52YXIgQ2hlY2tzID0ge1xuICBpc19udW1iZXI6IGlzX251bWJlciQyLFxuICBpc19zdHJpbmcsXG4gIGlzX2Jvb2xlYW46IGlzX2Jvb2xlYW4kMixcbiAgaXNfc3ltYm9sLFxuICBpc19udWxsLFxuICBpc191bmRlZmluZWQsXG4gIGlzX2Z1bmN0aW9uOiBpc19mdW5jdGlvbiQyLFxuICBpc192YXJpYWJsZSxcbiAgaXNfd2lsZGNhcmQsXG4gIGlzX2hlYWRUYWlsLFxuICBpc19jYXB0dXJlLFxuICBpc190eXBlLFxuICBpc19zdGFydHNXaXRoLFxuICBpc19ib3VuZCxcbiAgaXNfb2JqZWN0LFxuICBpc19hcnJheVxufTtcblxuZnVuY3Rpb24gcmVzb2x2ZVN5bWJvbChwYXR0ZXJuKSB7XG4gIHJldHVybiBmdW5jdGlvbiAodmFsdWUpIHtcbiAgICByZXR1cm4gQ2hlY2tzLmlzX3N5bWJvbCh2YWx1ZSkgJiYgdmFsdWUgPT09IHBhdHRlcm47XG4gIH07XG59XG5cbmZ1bmN0aW9uIHJlc29sdmVTdHJpbmcocGF0dGVybikge1xuICByZXR1cm4gZnVuY3Rpb24gKHZhbHVlKSB7XG4gICAgcmV0dXJuIENoZWNrcy5pc19zdHJpbmcodmFsdWUpICYmIHZhbHVlID09PSBwYXR0ZXJuO1xuICB9O1xufVxuXG5mdW5jdGlvbiByZXNvbHZlTnVtYmVyKHBhdHRlcm4pIHtcbiAgcmV0dXJuIGZ1bmN0aW9uICh2YWx1ZSkge1xuICAgIHJldHVybiBDaGVja3MuaXNfbnVtYmVyKHZhbHVlKSAmJiB2YWx1ZSA9PT0gcGF0dGVybjtcbiAgfTtcbn1cblxuZnVuY3Rpb24gcmVzb2x2ZUJvb2xlYW4ocGF0dGVybikge1xuICByZXR1cm4gZnVuY3Rpb24gKHZhbHVlKSB7XG4gICAgcmV0dXJuIENoZWNrcy5pc19ib29sZWFuKHZhbHVlKSAmJiB2YWx1ZSA9PT0gcGF0dGVybjtcbiAgfTtcbn1cblxuZnVuY3Rpb24gcmVzb2x2ZUZ1bmN0aW9uKHBhdHRlcm4pIHtcbiAgcmV0dXJuIGZ1bmN0aW9uICh2YWx1ZSkge1xuICAgIHJldHVybiBDaGVja3MuaXNfZnVuY3Rpb24odmFsdWUpICYmIHZhbHVlID09PSBwYXR0ZXJuO1xuICB9O1xufVxuXG5mdW5jdGlvbiByZXNvbHZlTnVsbChwYXR0ZXJuKSB7XG4gIHJldHVybiBmdW5jdGlvbiAodmFsdWUpIHtcbiAgICByZXR1cm4gQ2hlY2tzLmlzX251bGwodmFsdWUpO1xuICB9O1xufVxuXG5mdW5jdGlvbiByZXNvbHZlQm91bmQocGF0dGVybikge1xuICByZXR1cm4gZnVuY3Rpb24gKHZhbHVlLCBhcmdzKSB7XG4gICAgaWYgKHR5cGVvZiB2YWx1ZSA9PT0gdHlwZW9mIHBhdHRlcm4udmFsdWUgJiYgdmFsdWUgPT09IHBhdHRlcm4udmFsdWUpIHtcbiAgICAgIGFyZ3MucHVzaCh2YWx1ZSk7XG4gICAgICByZXR1cm4gdHJ1ZTtcbiAgICB9XG5cbiAgICByZXR1cm4gZmFsc2U7XG4gIH07XG59XG5cbmZ1bmN0aW9uIHJlc29sdmVXaWxkY2FyZCgpIHtcbiAgcmV0dXJuIGZ1bmN0aW9uICgpIHtcbiAgICByZXR1cm4gdHJ1ZTtcbiAgfTtcbn1cblxuZnVuY3Rpb24gcmVzb2x2ZVZhcmlhYmxlKCkge1xuICByZXR1cm4gZnVuY3Rpb24gKHZhbHVlLCBhcmdzKSB7XG4gICAgYXJncy5wdXNoKHZhbHVlKTtcbiAgICByZXR1cm4gdHJ1ZTtcbiAgfTtcbn1cblxuZnVuY3Rpb24gcmVzb2x2ZUhlYWRUYWlsKCkge1xuICByZXR1cm4gZnVuY3Rpb24gKHZhbHVlLCBhcmdzKSB7XG4gICAgaWYgKCFDaGVja3MuaXNfYXJyYXkodmFsdWUpIHx8IHZhbHVlLmxlbmd0aCA8IDIpIHtcbiAgICAgIHJldHVybiBmYWxzZTtcbiAgICB9XG5cbiAgICBjb25zdCBoZWFkID0gdmFsdWVbMF07XG4gICAgY29uc3QgdGFpbCA9IHZhbHVlLnNsaWNlKDEpO1xuXG4gICAgYXJncy5wdXNoKGhlYWQpO1xuICAgIGFyZ3MucHVzaCh0YWlsKTtcblxuICAgIHJldHVybiB0cnVlO1xuICB9O1xufVxuXG5mdW5jdGlvbiByZXNvbHZlQ2FwdHVyZShwYXR0ZXJuKSB7XG4gIGNvbnN0IG1hdGNoZXMgPSBidWlsZE1hdGNoKHBhdHRlcm4udmFsdWUpO1xuXG4gIHJldHVybiBmdW5jdGlvbiAodmFsdWUsIGFyZ3MpIHtcbiAgICBpZiAobWF0Y2hlcyh2YWx1ZSwgYXJncykpIHtcbiAgICAgIGFyZ3MucHVzaCh2YWx1ZSk7XG4gICAgICByZXR1cm4gdHJ1ZTtcbiAgICB9XG5cbiAgICByZXR1cm4gZmFsc2U7XG4gIH07XG59XG5cbmZ1bmN0aW9uIHJlc29sdmVTdGFydHNXaXRoKHBhdHRlcm4pIHtcbiAgY29uc3QgcHJlZml4ID0gcGF0dGVybi5wcmVmaXg7XG5cbiAgcmV0dXJuIGZ1bmN0aW9uICh2YWx1ZSwgYXJncykge1xuICAgIGlmIChDaGVja3MuaXNfc3RyaW5nKHZhbHVlKSAmJiB2YWx1ZS5zdGFydHNXaXRoKHByZWZpeCkpIHtcbiAgICAgIGFyZ3MucHVzaCh2YWx1ZS5zdWJzdHJpbmcocHJlZml4Lmxlbmd0aCkpO1xuICAgICAgcmV0dXJuIHRydWU7XG4gICAgfVxuXG4gICAgcmV0dXJuIGZhbHNlO1xuICB9O1xufVxuXG5mdW5jdGlvbiByZXNvbHZlVHlwZShwYXR0ZXJuKSB7XG4gIHJldHVybiBmdW5jdGlvbiAodmFsdWUsIGFyZ3MpIHtcbiAgICBpZiAodmFsdWUgaW5zdGFuY2VvZiBwYXR0ZXJuLnR5cGUpIHtcbiAgICAgIGNvbnN0IG1hdGNoZXMgPSBidWlsZE1hdGNoKHBhdHRlcm4ub2JqUGF0dGVybik7XG4gICAgICByZXR1cm4gbWF0Y2hlcyh2YWx1ZSwgYXJncykgJiYgYXJncy5wdXNoKHZhbHVlKSA+IDA7XG4gICAgfVxuXG4gICAgcmV0dXJuIGZhbHNlO1xuICB9O1xufVxuXG5mdW5jdGlvbiByZXNvbHZlQXJyYXkocGF0dGVybikge1xuICBjb25zdCBtYXRjaGVzID0gcGF0dGVybi5tYXAoeCA9PiBidWlsZE1hdGNoKHgpKTtcblxuICByZXR1cm4gZnVuY3Rpb24gKHZhbHVlLCBhcmdzKSB7XG4gICAgaWYgKCFDaGVja3MuaXNfYXJyYXkodmFsdWUpIHx8IHZhbHVlLmxlbmd0aCAhPSBwYXR0ZXJuLmxlbmd0aCkge1xuICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH1cblxuICAgIHJldHVybiB2YWx1ZS5ldmVyeShmdW5jdGlvbiAodiwgaSkge1xuICAgICAgcmV0dXJuIG1hdGNoZXNbaV0odmFsdWVbaV0sIGFyZ3MpO1xuICAgIH0pO1xuICB9O1xufVxuXG5mdW5jdGlvbiByZXNvbHZlT2JqZWN0KHBhdHRlcm4pIHtcbiAgbGV0IG1hdGNoZXMgPSB7fTtcblxuICBmb3IgKGxldCBrZXkgb2YgT2JqZWN0LmtleXMocGF0dGVybikuY29uY2F0KE9iamVjdC5nZXRPd25Qcm9wZXJ0eVN5bWJvbHMocGF0dGVybikpKSB7XG4gICAgbWF0Y2hlc1trZXldID0gYnVpbGRNYXRjaChwYXR0ZXJuW2tleV0pO1xuICB9XG5cbiAgcmV0dXJuIGZ1bmN0aW9uICh2YWx1ZSwgYXJncykge1xuICAgIGlmICghQ2hlY2tzLmlzX29iamVjdCh2YWx1ZSkgfHwgcGF0dGVybi5sZW5ndGggPiB2YWx1ZS5sZW5ndGgpIHtcbiAgICAgIHJldHVybiBmYWxzZTtcbiAgICB9XG5cbiAgICBmb3IgKGxldCBrZXkgb2YgT2JqZWN0LmtleXMocGF0dGVybikuY29uY2F0KE9iamVjdC5nZXRPd25Qcm9wZXJ0eVN5bWJvbHMocGF0dGVybikpKSB7XG4gICAgICBpZiAoIShrZXkgaW4gdmFsdWUpIHx8ICFtYXRjaGVzW2tleV0odmFsdWVba2V5XSwgYXJncykpIHtcbiAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgfVxuICAgIH1cblxuICAgIHJldHVybiB0cnVlO1xuICB9O1xufVxuXG5mdW5jdGlvbiByZXNvbHZlTm9NYXRjaCgpIHtcbiAgcmV0dXJuIGZ1bmN0aW9uICgpIHtcbiAgICByZXR1cm4gZmFsc2U7XG4gIH07XG59XG5cbnZhciBSZXNvbHZlcnMgPSB7XG4gIHJlc29sdmVCb3VuZCxcbiAgcmVzb2x2ZVdpbGRjYXJkLFxuICByZXNvbHZlVmFyaWFibGUsXG4gIHJlc29sdmVIZWFkVGFpbCxcbiAgcmVzb2x2ZUNhcHR1cmUsXG4gIHJlc29sdmVTdGFydHNXaXRoLFxuICByZXNvbHZlVHlwZSxcbiAgcmVzb2x2ZUFycmF5LFxuICByZXNvbHZlT2JqZWN0LFxuICByZXNvbHZlTm9NYXRjaCxcbiAgcmVzb2x2ZVN5bWJvbCxcbiAgcmVzb2x2ZVN0cmluZyxcbiAgcmVzb2x2ZU51bWJlcixcbiAgcmVzb2x2ZUJvb2xlYW4sXG4gIHJlc29sdmVGdW5jdGlvbixcbiAgcmVzb2x2ZU51bGxcbn07XG5cbmZ1bmN0aW9uIGJ1aWxkTWF0Y2gocGF0dGVybikge1xuXG4gIGlmIChDaGVja3MuaXNfdmFyaWFibGUocGF0dGVybikpIHtcbiAgICByZXR1cm4gUmVzb2x2ZXJzLnJlc29sdmVWYXJpYWJsZShwYXR0ZXJuKTtcbiAgfVxuXG4gIGlmIChDaGVja3MuaXNfd2lsZGNhcmQocGF0dGVybikpIHtcbiAgICByZXR1cm4gUmVzb2x2ZXJzLnJlc29sdmVXaWxkY2FyZChwYXR0ZXJuKTtcbiAgfVxuXG4gIGlmIChDaGVja3MuaXNfdW5kZWZpbmVkKHBhdHRlcm4pKSB7XG4gICAgcmV0dXJuIFJlc29sdmVycy5yZXNvbHZlV2lsZGNhcmQocGF0dGVybik7XG4gIH1cblxuICBpZiAoQ2hlY2tzLmlzX2hlYWRUYWlsKHBhdHRlcm4pKSB7XG4gICAgcmV0dXJuIFJlc29sdmVycy5yZXNvbHZlSGVhZFRhaWwocGF0dGVybik7XG4gIH1cblxuICBpZiAoQ2hlY2tzLmlzX3N0YXJ0c1dpdGgocGF0dGVybikpIHtcbiAgICByZXR1cm4gUmVzb2x2ZXJzLnJlc29sdmVTdGFydHNXaXRoKHBhdHRlcm4pO1xuICB9XG5cbiAgaWYgKENoZWNrcy5pc19jYXB0dXJlKHBhdHRlcm4pKSB7XG4gICAgcmV0dXJuIFJlc29sdmVycy5yZXNvbHZlQ2FwdHVyZShwYXR0ZXJuKTtcbiAgfVxuXG4gIGlmIChDaGVja3MuaXNfYm91bmQocGF0dGVybikpIHtcbiAgICByZXR1cm4gUmVzb2x2ZXJzLnJlc29sdmVCb3VuZChwYXR0ZXJuKTtcbiAgfVxuXG4gIGlmIChDaGVja3MuaXNfdHlwZShwYXR0ZXJuKSkge1xuICAgIHJldHVybiBSZXNvbHZlcnMucmVzb2x2ZVR5cGUocGF0dGVybik7XG4gIH1cblxuICBpZiAoQ2hlY2tzLmlzX2FycmF5KHBhdHRlcm4pKSB7XG4gICAgcmV0dXJuIFJlc29sdmVycy5yZXNvbHZlQXJyYXkocGF0dGVybik7XG4gIH1cblxuICBpZiAoQ2hlY2tzLmlzX251bWJlcihwYXR0ZXJuKSkge1xuICAgIHJldHVybiBSZXNvbHZlcnMucmVzb2x2ZU51bWJlcihwYXR0ZXJuKTtcbiAgfVxuXG4gIGlmIChDaGVja3MuaXNfc3RyaW5nKHBhdHRlcm4pKSB7XG4gICAgcmV0dXJuIFJlc29sdmVycy5yZXNvbHZlU3RyaW5nKHBhdHRlcm4pO1xuICB9XG5cbiAgaWYgKENoZWNrcy5pc19ib29sZWFuKHBhdHRlcm4pKSB7XG4gICAgcmV0dXJuIFJlc29sdmVycy5yZXNvbHZlQm9vbGVhbihwYXR0ZXJuKTtcbiAgfVxuXG4gIGlmIChDaGVja3MuaXNfc3ltYm9sKHBhdHRlcm4pKSB7XG4gICAgcmV0dXJuIFJlc29sdmVycy5yZXNvbHZlU3ltYm9sKHBhdHRlcm4pO1xuICB9XG5cbiAgaWYgKENoZWNrcy5pc19udWxsKHBhdHRlcm4pKSB7XG4gICAgcmV0dXJuIFJlc29sdmVycy5yZXNvbHZlTnVsbChwYXR0ZXJuKTtcbiAgfVxuXG4gIGlmIChDaGVja3MuaXNfb2JqZWN0KHBhdHRlcm4pKSB7XG4gICAgcmV0dXJuIFJlc29sdmVycy5yZXNvbHZlT2JqZWN0KHBhdHRlcm4pO1xuICB9XG5cbiAgcmV0dXJuIFJlc29sdmVycy5yZXNvbHZlTm9NYXRjaCgpO1xufVxuXG5jbGFzcyBNYXRjaEVycm9yIGV4dGVuZHMgRXJyb3Ige1xuICBjb25zdHJ1Y3RvcihhcmcpIHtcbiAgICBzdXBlcigpO1xuXG4gICAgaWYgKHR5cGVvZiBhcmcgPT09ICdzeW1ib2wnKSB7XG4gICAgICB0aGlzLm1lc3NhZ2UgPSAnTm8gbWF0Y2ggZm9yOiAnICsgYXJnLnRvU3RyaW5nKCk7XG4gICAgfSBlbHNlIGlmIChBcnJheS5pc0FycmF5KGFyZykpIHtcbiAgICAgIGxldCBtYXBwZWRWYWx1ZXMgPSBhcmcubWFwKHggPT4geC50b1N0cmluZygpKTtcbiAgICAgIHRoaXMubWVzc2FnZSA9ICdObyBtYXRjaCBmb3I6ICcgKyBtYXBwZWRWYWx1ZXM7XG4gICAgfSBlbHNlIHtcbiAgICAgIHRoaXMubWVzc2FnZSA9ICdObyBtYXRjaCBmb3I6ICcgKyBhcmc7XG4gICAgfVxuXG4gICAgdGhpcy5zdGFjayA9IG5ldyBFcnJvcigpLnN0YWNrO1xuICAgIHRoaXMubmFtZSA9IHRoaXMuY29uc3RydWN0b3IubmFtZTtcbiAgfVxufVxuXG5jbGFzcyBDYXNlIHtcblxuICBjb25zdHJ1Y3RvcihwYXR0ZXJuLCBmbiwgZ3VhcmQgPSAoKSA9PiB0cnVlKSB7XG4gICAgdGhpcy5wYXR0ZXJuID0gYnVpbGRNYXRjaChwYXR0ZXJuKTtcbiAgICB0aGlzLmZuID0gZm47XG4gICAgdGhpcy5ndWFyZCA9IGd1YXJkO1xuICB9XG59XG5cbmZ1bmN0aW9uIG1ha2VfY2FzZShwYXR0ZXJuLCBmbiwgZ3VhcmQgPSAoKSA9PiB0cnVlKSB7XG4gIHJldHVybiBuZXcgQ2FzZShwYXR0ZXJuLCBmbiwgZ3VhcmQpO1xufVxuXG5mdW5jdGlvbiBkZWZtYXRjaCguLi5jYXNlcykge1xuICByZXR1cm4gZnVuY3Rpb24gKC4uLmFyZ3MpIHtcbiAgICBmb3IgKGxldCBwcm9jZXNzZWRDYXNlIG9mIGNhc2VzKSB7XG4gICAgICBsZXQgcmVzdWx0ID0gW107XG4gICAgICBpZiAocHJvY2Vzc2VkQ2FzZS5wYXR0ZXJuKGFyZ3MsIHJlc3VsdCkgJiYgcHJvY2Vzc2VkQ2FzZS5ndWFyZC5hcHBseSh0aGlzLCByZXN1bHQpKSB7XG4gICAgICAgIHJldHVybiBwcm9jZXNzZWRDYXNlLmZuLmFwcGx5KHRoaXMsIHJlc3VsdCk7XG4gICAgICB9XG4gICAgfVxuXG4gICAgdGhyb3cgbmV3IE1hdGNoRXJyb3IoYXJncyk7XG4gIH07XG59XG5cbmZ1bmN0aW9uIG1hdGNoKHBhdHRlcm4sIGV4cHIsIGd1YXJkID0gKCkgPT4gdHJ1ZSkge1xuICBsZXQgcmVzdWx0ID0gW107XG4gIGxldCBwcm9jZXNzZWRQYXR0ZXJuID0gYnVpbGRNYXRjaChwYXR0ZXJuKTtcbiAgaWYgKHByb2Nlc3NlZFBhdHRlcm4oZXhwciwgcmVzdWx0KSAmJiBndWFyZC5hcHBseSh0aGlzLCByZXN1bHQpKSB7XG4gICAgcmV0dXJuIHJlc3VsdDtcbiAgfSBlbHNlIHtcbiAgICB0aHJvdyBuZXcgTWF0Y2hFcnJvcihleHByKTtcbiAgfVxufVxuXG5mdW5jdGlvbiBtYXRjaF9ub190aHJvdyhwYXR0ZXJuLCBleHByLCBndWFyZCA9ICgpID0+IHRydWUpIHtcbiAgdHJ5IHtcbiAgICByZXR1cm4gbWF0Y2gocGF0dGVybiwgZXhwciwgZ3VhcmQpO1xuICB9IGNhdGNoIChlKSB7XG4gICAgaWYgKGUgaW5zdGFuY2VvZiBNYXRjaEVycm9yKSB7XG4gICAgICByZXR1cm4gbnVsbDtcbiAgICB9XG5cbiAgICB0aHJvdyBlO1xuICB9XG59XG5cbnZhciBQYXR0ZXJucyA9IHtcbiAgZGVmbWF0Y2gsIG1hdGNoLCBNYXRjaEVycm9yLCBtYXRjaF9ub190aHJvdyxcbiAgdmFyaWFibGUsIHdpbGRjYXJkLCBzdGFydHNXaXRoLFxuICBjYXB0dXJlLCBoZWFkVGFpbCwgdHlwZSwgYm91bmQsIENhc2UsIG1ha2VfY2FzZVxufTtcblxuZnVuY3Rpb24gY2FsbF9wcm9wZXJ0eShpdGVtLCBwcm9wZXJ0eSkge1xuICBpZiAocHJvcGVydHkgaW4gaXRlbSkge1xuICAgIGl0ZW1bcHJvcGVydHldO1xuICAgIGlmIChpdGVtW3Byb3BlcnR5XSBpbnN0YW5jZW9mIEZ1bmN0aW9uKSB7XG4gICAgICByZXR1cm4gaXRlbVtwcm9wZXJ0eV0oKTtcbiAgICB9IGVsc2Uge1xuICAgICAgcmV0dXJuIGl0ZW1bcHJvcGVydHldO1xuICAgIH1cbiAgfSBlbHNlIGlmIChTeW1ib2wuZm9yKHByb3BlcnR5KSBpbiBpdGVtKSB7XG4gICAgbGV0IHByb3AgPSBTeW1ib2wuZm9yKHByb3BlcnR5KTtcbiAgICBpZiAoaXRlbVtwcm9wXSBpbnN0YW5jZW9mIEZ1bmN0aW9uKSB7XG4gICAgICByZXR1cm4gaXRlbVtwcm9wXSgpO1xuICAgIH0gZWxzZSB7XG4gICAgICByZXR1cm4gaXRlbVtwcm9wXTtcbiAgICB9XG4gIH1cblxuICB0aHJvdyBuZXcgRXJyb3IoYFByb3BlcnR5ICR7IHByb3BlcnR5IH0gbm90IGZvdW5kIGluICR7IGl0ZW0gfWApO1xufVxuXG5mdW5jdGlvbiBpc19pbnN0YW5jZV9vZih2YWx1ZSwgdHlwZSkge1xuICByZXR1cm4gdmFsdWUgaW5zdGFuY2VvZiB0eXBlO1xufVxuXG5mdW5jdGlvbiBzaXplJDIodGVybSkge1xuICByZXR1cm4gdGVybS5sZW5ndGg7XG59XG5cbmZ1bmN0aW9uIGlzX25pbCQxKHgpIHtcbiAgcmV0dXJuIHggPT09IG51bGw7XG59XG5cbmZ1bmN0aW9uIGlzX2F0b20kMSh4KSB7XG4gIHJldHVybiB0eXBlb2YgeCA9PT0gJ3N5bWJvbCc7XG59XG5cbmZ1bmN0aW9uIGlzX2JpbmFyeSQxKHgpIHtcbiAgcmV0dXJuIHR5cGVvZiB4ID09PSAnc3RyaW5nJyB8fCB4IGluc3RhbmNlb2YgU3RyaW5nO1xufVxuXG5mdW5jdGlvbiBpc19ib29sZWFuJDEoeCkge1xuICByZXR1cm4gdHlwZW9mIHggPT09ICdib29sZWFuJyB8fCB4IGluc3RhbmNlb2YgQm9vbGVhbjtcbn1cblxuZnVuY3Rpb24gaXNfZnVuY3Rpb24kMSh4LCBhcml0eSA9IC0xKSB7XG4gIHJldHVybiB0eXBlb2YgeCA9PT0gJ2Z1bmN0aW9uJyB8fCB4IGluc3RhbmNlb2YgRnVuY3Rpb247XG59XG5cbmZ1bmN0aW9uIGlzX2Zsb2F0JDEoeCkge1xuICByZXR1cm4gaXNfbnVtYmVyJDEoeCkgJiYgIU51bWJlci5pc0ludGVnZXIoeCk7XG59XG5cbmZ1bmN0aW9uIGlzX2ludGVnZXIkMSh4KSB7XG4gIHJldHVybiBOdW1iZXIuaXNJbnRlZ2VyKHgpO1xufVxuXG5mdW5jdGlvbiBpc19saXN0JDEoeCkge1xuICByZXR1cm4geCBpbnN0YW5jZW9mIEFycmF5O1xufVxuXG5mdW5jdGlvbiBpc19tYXAkMSh4KSB7XG4gIHJldHVybiB0eXBlb2YgeCA9PT0gJ29iamVjdCcgfHwgeCBpbnN0YW5jZW9mIE9iamVjdDtcbn1cblxuZnVuY3Rpb24gaXNfbnVtYmVyJDEoeCkge1xuICByZXR1cm4gdHlwZW9mIHggPT09ICdudW1iZXInO1xufVxuXG5mdW5jdGlvbiBpc190dXBsZSQxKHgpIHtcbiAgcmV0dXJuIHggaW5zdGFuY2VvZiBUdXBsZTtcbn1cblxuZnVuY3Rpb24gaXNfcGlkJDEoeCkge1xuICByZXR1cm4geCBpbnN0YW5jZW9mIFBJRDtcbn1cblxuZnVuY3Rpb24gaXNfcG9ydCQxKHgpIHtcbiAgcmV0dXJuIGZhbHNlO1xufVxuXG5mdW5jdGlvbiBpc19yZWZlcmVuY2UkMSh4KSB7XG4gIHJldHVybiBmYWxzZTtcbn1cblxuZnVuY3Rpb24gaXNfYml0c3RyaW5nJDEoeCkge1xuICByZXR1cm4gaXNfYmluYXJ5JDEoeCkgfHwgeCBpbnN0YW5jZW9mIEJpdFN0cmluZztcbn1cblxuZnVuY3Rpb24gYWRkKG9uZSwgdHdvKSB7XG4gIHJldHVybiBvbmUgKyB0d287XG59XG5cbmZ1bmN0aW9uIHN1YnRyYWN0KG9uZSwgdHdvKSB7XG4gIHJldHVybiBvbmUgKyB0d287XG59XG5cbmZ1bmN0aW9uIG11bHRpcGx5KG9uZSwgdHdvKSB7XG4gIHJldHVybiBvbmUgKyB0d287XG59XG5cbmZ1bmN0aW9uIGRpdmlkZShvbmUsIHR3bykge1xuICByZXR1cm4gb25lICsgdHdvO1xufVxuXG5mdW5jdGlvbiByZW1haW5kZXIob25lLCB0d28pIHtcbiAgcmV0dXJuIG9uZSArIHR3bztcbn1cblxuZnVuY3Rpb24gYXBwbHkkMSguLi5hcmdzKSB7XG4gIGlmIChhcmdzLmxlbmd0aCA9PT0gMikge1xuICAgIGFyZ3NbMF0uYXBwbHkobnVsbCwgYXJncy5zbGljZSgxKSk7XG4gIH0gZWxzZSB7XG4gICAgYXJnc1swXVthcmdzWzFdXS5hcHBseShudWxsLCBhcmdzLnNsaWNlKDIpKTtcbiAgfVxufVxuXG5mdW5jdGlvbiBuZXdfdHVwbGUoLi4uYXJncykge1xuICByZXR1cm4gbmV3IFR1cGxlKC4uLmFyZ3MpO1xufVxuXG5mdW5jdGlvbiBkdXBsaWNhdGUoZGF0YSwgc2l6ZSkge1xuICBsZXQgYXJyYXkgPSBbXTtcblxuICBmb3IgKHZhciBpID0gc2l6ZSAtIDE7IGkgPj0gMDsgaS0tKSB7XG4gICAgYXJyYXkucHVzaChkYXRhKTtcbiAgfVxuXG4gIHJldHVybiBhcnJheTtcbn1cblxuZnVuY3Rpb24gY29udGFpbnMobGVmdCwgcmlnaHQpIHtcbiAgZm9yIChsZXQgeCBvZiByaWdodCkge1xuICAgIGlmIChQYXR0ZXJucy5tYXRjaF9ub190aHJvdyhsZWZ0LCB4KSAhPSBudWxsKSB7XG4gICAgICByZXR1cm4gdHJ1ZTtcbiAgICB9XG4gIH1cblxuICByZXR1cm4gZmFsc2U7XG59XG5cbmZ1bmN0aW9uIHJldmVyc2UobGlzdCkge1xuICByZXR1cm4gbGlzdC5jb25jYXQoW10pLnJldmVyc2UoKTtcbn1cblxuZnVuY3Rpb24gZ2V0X2dsb2JhbCgpIHtcbiAgaWYgKHR5cGVvZiBzZWxmICE9PSAndW5kZWZpbmVkJykge1xuICAgIHJldHVybiBzZWxmO1xuICB9IGVsc2UgaWYgKHR5cGVvZiB3aW5kb3cgIT09ICd1bmRlZmluZWQnKSB7XG4gICAgcmV0dXJuIHdpbmRvdztcbiAgfSBlbHNlIGlmICh0eXBlb2YgZ2xvYmFsICE9PSAndW5kZWZpbmVkJykge1xuICAgIHJldHVybiBnbG9iYWw7XG4gIH1cblxuICB0aHJvdyBuZXcgRXJyb3IoJ05vIGdsb2JhbCBzdGF0ZSBmb3VuZCcpO1xufVxuXG5mdW5jdGlvbiBjb25jYXRfbGlzdHMobGVmdCwgcmlnaHQpIHtcbiAgcmV0dXJuIGxlZnQuY29uY2F0KHJpZ2h0KTtcbn1cblxuZnVuY3Rpb24gcHJlcGVuZF90b19saXN0KGxpc3QsIGl0ZW0pIHtcbiAgcmV0dXJuIFtpdGVtXS5jb25jYXQobGlzdCk7XG59XG5cbmZ1bmN0aW9uIGRlZnN0cnVjdChkZWZhdWx0cykge1xuICByZXR1cm4gY2xhc3Mge1xuICAgIGNvbnN0cnVjdG9yKHVwZGF0ZSA9IHt9KSB7XG4gICAgICBsZXQgdGhlX3ZhbHVlcyA9IE9iamVjdC5hc3NpZ24oZGVmYXVsdHMsIHVwZGF0ZSk7XG4gICAgICBPYmplY3QuYXNzaWduKHRoaXMsIHRoZV92YWx1ZXMpO1xuICAgIH1cblxuICAgIHN0YXRpYyBjcmVhdGUodXBkYXRlcyA9IHt9KSB7XG4gICAgICBsZXQgeCA9IG5ldyB0aGlzKHVwZGF0ZXMpO1xuICAgICAgcmV0dXJuIE9iamVjdC5mcmVlemUoeCk7XG4gICAgfVxuICB9O1xufVxuXG5mdW5jdGlvbiBkZWZleGNlcHRpb24oZGVmYXVsdHMpIHtcbiAgcmV0dXJuIGNsYXNzIGV4dGVuZHMgRXJyb3Ige1xuICAgIGNvbnN0cnVjdG9yKHVwZGF0ZSA9IHt9KSB7XG4gICAgICBsZXQgbWVzc2FnZSA9IHVwZGF0ZS5tZXNzYWdlIHx8ICcnO1xuICAgICAgc3VwZXIobWVzc2FnZSk7XG5cbiAgICAgIGxldCB0aGVfdmFsdWVzID0gT2JqZWN0LmFzc2lnbihkZWZhdWx0cywgdXBkYXRlKTtcbiAgICAgIE9iamVjdC5hc3NpZ24odGhpcywgdGhlX3ZhbHVlcyk7XG5cbiAgICAgIHRoaXMubmFtZSA9IHRoaXMuY29uc3RydWN0b3IubmFtZTtcbiAgICAgIHRoaXMubWVzc2FnZSA9IG1lc3NhZ2U7XG4gICAgICB0aGlzW1NwZWNpYWxGb3Jtcy5hdG9tKCdfX2V4Y2VwdGlvbl9fJyldID0gdHJ1ZTtcbiAgICAgIEVycm9yLmNhcHR1cmVTdGFja1RyYWNlKHRoaXMsIHRoaXMuY29uc3RydWN0b3IubmFtZSk7XG4gICAgfVxuXG4gICAgc3RhdGljIGNyZWF0ZSh1cGRhdGVzID0ge30pIHtcbiAgICAgIGxldCB4ID0gbmV3IHRoaXModXBkYXRlcyk7XG4gICAgICByZXR1cm4gT2JqZWN0LmZyZWV6ZSh4KTtcbiAgICB9XG4gIH07XG59XG5cbmZ1bmN0aW9uIGRlZnByb3RvY29sKHNwZWMpIHtcbiAgcmV0dXJuIG5ldyBQcm90b2NvbChzcGVjKTtcbn1cblxuZnVuY3Rpb24gZGVmaW1wbChwcm90b2NvbCwgdHlwZSwgaW1wbCkge1xuICBwcm90b2NvbC5pbXBsZW1lbnRhdGlvbih0eXBlLCBpbXBsKTtcbn1cblxuZnVuY3Rpb24gZ2V0X29iamVjdF9rZXlzKG9iaikge1xuICByZXR1cm4gT2JqZWN0LmtleXMob2JqKS5jb25jYXQoT2JqZWN0LmdldE93blByb3BlcnR5U3ltYm9scyhvYmopKTtcbn1cblxuZnVuY3Rpb24gaXNfdmFsaWRfY2hhcmFjdGVyKGNvZGVwb2ludCkge1xuICB0cnkge1xuICAgIHJldHVybiBTdHJpbmcuZnJvbUNvZGVQb2ludChjb2RlcG9pbnQpICE9IG51bGw7XG4gIH0gY2F0Y2ggKGUpIHtcbiAgICByZXR1cm4gZmFsc2U7XG4gIH1cbn1cblxuLy9odHRwczovL2RldmVsb3Blci5tb3ppbGxhLm9yZy9lbi1VUy9kb2NzL1dlYi9BUEkvV2luZG93QmFzZTY0L0Jhc2U2NF9lbmNvZGluZ19hbmRfZGVjb2RpbmcjU29sdXRpb25fMl8lRTIlODAlOTNfcmV3cml0ZV90aGVfRE9Nc19hdG9iKClfYW5kX2J0b2EoKV91c2luZ19KYXZhU2NyaXB0J3NfVHlwZWRBcnJheXNfYW5kX1VURi04XG5mdW5jdGlvbiBiNjRFbmNvZGVVbmljb2RlKHN0cikge1xuICByZXR1cm4gYnRvYShlbmNvZGVVUklDb21wb25lbnQoc3RyKS5yZXBsYWNlKC8lKFswLTlBLUZdezJ9KS9nLCBmdW5jdGlvbiAobWF0Y2gsIHAxKSB7XG4gICAgcmV0dXJuIFN0cmluZy5mcm9tQ2hhckNvZGUoJzB4JyArIHAxKTtcbiAgfSkpO1xufVxuXG52YXIgRnVuY3Rpb25zID0ge1xuICBjYWxsX3Byb3BlcnR5LFxuICBpc19pbnN0YW5jZV9vZixcbiAgc2l6ZTogc2l6ZSQyLFxuICBpc19uaWw6IGlzX25pbCQxLFxuICBpc19hdG9tOiBpc19hdG9tJDEsXG4gIGlzX2JpbmFyeTogaXNfYmluYXJ5JDEsXG4gIGlzX2Jvb2xlYW46IGlzX2Jvb2xlYW4kMSxcbiAgaXNfZnVuY3Rpb246IGlzX2Z1bmN0aW9uJDEsXG4gIGlzX2Zsb2F0OiBpc19mbG9hdCQxLFxuICBpc19pbnRlZ2VyOiBpc19pbnRlZ2VyJDEsXG4gIGlzX2xpc3Q6IGlzX2xpc3QkMSxcbiAgaXNfbWFwOiBpc19tYXAkMSxcbiAgaXNfbnVtYmVyOiBpc19udW1iZXIkMSxcbiAgaXNfdHVwbGU6IGlzX3R1cGxlJDEsXG4gIGlzX3BpZDogaXNfcGlkJDEsXG4gIGlzX3BvcnQ6IGlzX3BvcnQkMSxcbiAgaXNfcmVmZXJlbmNlOiBpc19yZWZlcmVuY2UkMSxcbiAgaXNfYml0c3RyaW5nOiBpc19iaXRzdHJpbmckMSxcbiAgYWRkLFxuICBzdWJ0cmFjdCxcbiAgbXVsdGlwbHksXG4gIGRpdmlkZSxcbiAgcmVtYWluZGVyLFxuICBhcHBseTogYXBwbHkkMSxcbiAgbmV3X3R1cGxlLFxuICBkdXBsaWNhdGUsXG4gIGNvbnRhaW5zLFxuICByZXZlcnNlLFxuICBnZXRfZ2xvYmFsLFxuICBjb25jYXRfbGlzdHMsXG4gIHByZXBlbmRfdG9fbGlzdCxcbiAgZGVmc3RydWN0LFxuICBkZWZleGNlcHRpb24sXG4gIGRlZnByb3RvY29sLFxuICBkZWZpbXBsLFxuICBnZXRfb2JqZWN0X2tleXMsXG4gIGlzX3ZhbGlkX2NoYXJhY3RlcixcbiAgYjY0RW5jb2RlVW5pY29kZVxufTtcblxuRnVuY3Rpb25zLmdldF9nbG9iYWwoKS5wcm9jZXNzZXMgPSBGdW5jdGlvbnMuZ2V0X2dsb2JhbCgpLnByb2Nlc3NlcyB8fCBuZXcgUHJvY2Vzc1N5c3RlbSgpO1xuXG5cblxudmFyIEMgPSBPYmplY3QuZnJlZXplKHtcblx0UHJvY2Vzc1N5c3RlbTogUHJvY2Vzc1N5c3RlbSxcblx0VHVwbGU6IFR1cGxlLFxuXHRQSUQ6IFBJRCxcblx0Qml0U3RyaW5nOiBCaXRTdHJpbmcsXG5cdFBhdHRlcm5zOiBQYXR0ZXJucyxcblx0SW50ZWdlcjogSW50ZWdlcixcblx0RmxvYXQ6IEZsb2F0LFxuXHRGdW5jdGlvbnM6IEZ1bmN0aW9ucyxcblx0TGlzdDogTGlzdCQxXG59KTtcblxubGV0IEVudW0gPSB7XG5cbiAgYWxsX19xbWFya19fOiBmdW5jdGlvbiAoY29sbGVjdGlvbiwgZnVuID0geCA9PiB4KSB7XG4gICAgZm9yIChsZXQgZWxlbSBvZiBjb2xsZWN0aW9uKSB7XG4gICAgICBpZiAoIWZ1bihlbGVtKSkge1xuICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICB9XG4gICAgfVxuXG4gICAgcmV0dXJuIHRydWU7XG4gIH0sXG5cbiAgYW55X19xbWFya19fOiBmdW5jdGlvbiAoY29sbGVjdGlvbiwgZnVuID0geCA9PiB4KSB7XG4gICAgZm9yIChsZXQgZWxlbSBvZiBjb2xsZWN0aW9uKSB7XG4gICAgICBpZiAoZnVuKGVsZW0pKSB7XG4gICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgfVxuICAgIH1cblxuICAgIHJldHVybiBmYWxzZTtcbiAgfSxcblxuICBhdDogZnVuY3Rpb24gKGNvbGxlY3Rpb24sIG4sIHRoZV9kZWZhdWx0ID0gbnVsbCkge1xuICAgIGlmIChuID4gdGhpcy5jb3VudChjb2xsZWN0aW9uKSB8fCBuIDwgMCkge1xuICAgICAgcmV0dXJuIHRoZV9kZWZhdWx0O1xuICAgIH1cblxuICAgIHJldHVybiBjb2xsZWN0aW9uW25dO1xuICB9LFxuXG4gIGNvbmNhdDogZnVuY3Rpb24gKC4uLmVudW1hYmxlcykge1xuICAgIHJldHVybiBlbnVtYWJsZXNbMF0uY29uY2F0KGVudW1hYmxlc1sxXSk7XG4gIH0sXG5cbiAgY291bnQ6IGZ1bmN0aW9uIChjb2xsZWN0aW9uLCBmdW4gPSBudWxsKSB7XG4gICAgaWYgKGZ1biA9PSBudWxsKSB7XG4gICAgICByZXR1cm4gY29sbGVjdGlvbi5sZW5ndGg7XG4gICAgfSBlbHNlIHtcbiAgICAgIHJldHVybiBjb2xsZWN0aW9uLmZpbHRlcihmdW4pLmxlbmd0aDtcbiAgICB9XG4gIH0sXG5cbiAgZHJvcDogZnVuY3Rpb24gKGNvbGxlY3Rpb24sIGNvdW50KSB7XG4gICAgcmV0dXJuIGNvbGxlY3Rpb24uc2xpY2UoY291bnQpO1xuICB9LFxuXG4gIGRyb3Bfd2hpbGU6IGZ1bmN0aW9uIChjb2xsZWN0aW9uLCBmdW4pIHtcbiAgICBsZXQgY291bnQgPSAwO1xuXG4gICAgZm9yIChsZXQgZWxlbSBvZiBjb2xsZWN0aW9uKSB7XG4gICAgICBpZiAoZnVuKGVsZW0pKSB7XG4gICAgICAgIGNvdW50ID0gY291bnQgKyAxO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgYnJlYWs7XG4gICAgICB9XG4gICAgfVxuXG4gICAgcmV0dXJuIGNvbGxlY3Rpb24uc2xpY2UoY291bnQpO1xuICB9LFxuXG4gIGVhY2g6IGZ1bmN0aW9uIChjb2xsZWN0aW9uLCBmdW4pIHtcbiAgICBmb3IgKGxldCBlbGVtIG9mIGNvbGxlY3Rpb24pIHtcbiAgICAgIGZ1bihlbGVtKTtcbiAgICB9XG4gIH0sXG5cbiAgZW1wdHlfX3FtYXJrX186IGZ1bmN0aW9uIChjb2xsZWN0aW9uKSB7XG4gICAgcmV0dXJuIGNvbGxlY3Rpb24ubGVuZ3RoID09PSAwO1xuICB9LFxuXG4gIGZldGNoOiBmdW5jdGlvbiAoY29sbGVjdGlvbiwgbikge1xuICAgIGlmIChLZXJuZWwuaXNfbGlzdChjb2xsZWN0aW9uKSkge1xuICAgICAgaWYgKG4gPCB0aGlzLmNvdW50KGNvbGxlY3Rpb24pICYmIG4gPj0gMCkge1xuICAgICAgICByZXR1cm4gbmV3IFR1cGxlKFN5bWJvbC5mb3IoJ29rJyksIGNvbGxlY3Rpb25bbl0pO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgcmV0dXJuIFN5bWJvbC5mb3IoJ2Vycm9yJyk7XG4gICAgICB9XG4gICAgfVxuXG4gICAgdGhyb3cgbmV3IEVycm9yKCdjb2xsZWN0aW9uIGlzIG5vdCBhbiBFbnVtZXJhYmxlJyk7XG4gIH0sXG5cbiAgZmV0Y2hfX2VtYXJrX186IGZ1bmN0aW9uIChjb2xsZWN0aW9uLCBuKSB7XG4gICAgaWYgKEtlcm5lbC5pc19saXN0KGNvbGxlY3Rpb24pKSB7XG4gICAgICBpZiAobiA8IHRoaXMuY291bnQoY29sbGVjdGlvbikgJiYgbiA+PSAwKSB7XG4gICAgICAgIHJldHVybiBjb2xsZWN0aW9uW25dO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdvdXQgb2YgYm91bmRzIGVycm9yJyk7XG4gICAgICB9XG4gICAgfVxuXG4gICAgdGhyb3cgbmV3IEVycm9yKCdjb2xsZWN0aW9uIGlzIG5vdCBhbiBFbnVtZXJhYmxlJyk7XG4gIH0sXG5cbiAgZmlsdGVyOiBmdW5jdGlvbiAoY29sbGVjdGlvbiwgZnVuKSB7XG4gICAgbGV0IHJlc3VsdCA9IFtdO1xuXG4gICAgZm9yIChsZXQgZWxlbSBvZiBjb2xsZWN0aW9uKSB7XG4gICAgICBpZiAoZnVuKGVsZW0pKSB7XG4gICAgICAgIHJlc3VsdC5wdXNoKGVsZW0pO1xuICAgICAgfVxuICAgIH1cblxuICAgIHJldHVybiByZXN1bHQ7XG4gIH0sXG5cbiAgZmlsdGVyX21hcDogZnVuY3Rpb24gKGNvbGxlY3Rpb24sIGZpbHRlciwgbWFwcGVyKSB7XG4gICAgcmV0dXJuIEVudW0ubWFwKEVudW0uZmlsdGVyKGNvbGxlY3Rpb24sIGZpbHRlciksIG1hcHBlcik7XG4gIH0sXG5cbiAgZmluZDogZnVuY3Rpb24gKGNvbGxlY3Rpb24sIGlmX25vbmUgPSBudWxsLCBmdW4pIHtcbiAgICBmb3IgKGxldCBlbGVtIG9mIGNvbGxlY3Rpb24pIHtcbiAgICAgIGlmIChmdW4oZWxlbSkpIHtcbiAgICAgICAgcmV0dXJuIGVsZW07XG4gICAgICB9XG4gICAgfVxuXG4gICAgcmV0dXJuIGlmX25vbmU7XG4gIH0sXG5cbiAgaW50bzogZnVuY3Rpb24gKGNvbGxlY3Rpb24sIGxpc3QpIHtcbiAgICByZXR1cm4gbGlzdC5jb25jYXQoY29sbGVjdGlvbik7XG4gIH0sXG5cbiAgbWFwOiBmdW5jdGlvbiAoY29sbGVjdGlvbiwgZnVuKSB7XG4gICAgbGV0IHJlc3VsdCA9IFtdO1xuXG4gICAgZm9yIChsZXQgZWxlbSBvZiBjb2xsZWN0aW9uKSB7XG4gICAgICByZXN1bHQucHVzaChmdW4oZWxlbSkpO1xuICAgIH1cblxuICAgIHJldHVybiByZXN1bHQ7XG4gIH0sXG5cbiAgbWFwX3JlZHVjZTogZnVuY3Rpb24gKGNvbGxlY3Rpb24sIGFjYywgZnVuKSB7XG4gICAgbGV0IG1hcHBlZCA9IExpc3QkMSgpO1xuICAgIGxldCB0aGVfYWNjID0gYWNjO1xuXG4gICAgZm9yICh2YXIgaSA9IDA7IGkgPCB0aGlzLmNvdW50KGNvbGxlY3Rpb24pOyBpKyspIHtcbiAgICAgIGxldCB0dXBsZSA9IGZ1bihjb2xsZWN0aW9uW2ldLCB0aGVfYWNjKTtcblxuICAgICAgdGhlX2FjYyA9IHR1cGxlLmdldCgxKTtcbiAgICAgIG1hcHBlZCA9IExpc3QkMSguLi5tYXBwZWQuY29uY2F0KFt0dXBsZS5nZXQoMCldKSk7XG4gICAgfVxuXG4gICAgcmV0dXJuIG5ldyBUdXBsZShtYXBwZWQsIHRoZV9hY2MpO1xuICB9LFxuXG4gIG1lbWJlcl9fcW1hcmtfXzogZnVuY3Rpb24gKGNvbGxlY3Rpb24sIHZhbHVlKSB7XG4gICAgcmV0dXJuIGNvbGxlY3Rpb24uaW5jbHVkZXModmFsdWUpO1xuICB9LFxuXG4gIHJlZHVjZTogZnVuY3Rpb24gKGNvbGxlY3Rpb24sIGFjYywgZnVuKSB7XG4gICAgbGV0IHRoZV9hY2MgPSBhY2M7XG5cbiAgICBmb3IgKHZhciBpID0gMDsgaSA8IHRoaXMuY291bnQoY29sbGVjdGlvbik7IGkrKykge1xuICAgICAgbGV0IHR1cGxlID0gZnVuKGNvbGxlY3Rpb25baV0sIHRoZV9hY2MpO1xuXG4gICAgICB0aGVfYWNjID0gdHVwbGUuZ2V0KDEpO1xuICAgIH1cblxuICAgIHJldHVybiB0aGVfYWNjO1xuICB9LFxuXG4gIHRha2U6IGZ1bmN0aW9uIChjb2xsZWN0aW9uLCBjb3VudCkge1xuICAgIHJldHVybiBjb2xsZWN0aW9uLnNsaWNlKDAsIGNvdW50KTtcbiAgfSxcblxuICB0YWtlX2V2ZXJ5OiBmdW5jdGlvbiAoY29sbGVjdGlvbiwgbnRoKSB7XG4gICAgbGV0IHJlc3VsdCA9IFtdO1xuICAgIGxldCBpbmRleCA9IDA7XG5cbiAgICBmb3IgKGxldCBlbGVtIG9mIGNvbGxlY3Rpb24pIHtcbiAgICAgIGlmIChpbmRleCAlIG50aCA9PT0gMCkge1xuICAgICAgICByZXN1bHQucHVzaChlbGVtKTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICByZXR1cm4gTGlzdCQxKC4uLnJlc3VsdCk7XG4gIH0sXG5cbiAgdGFrZV93aGlsZTogZnVuY3Rpb24gKGNvbGxlY3Rpb24sIGZ1bikge1xuICAgIGxldCBjb3VudCA9IDA7XG5cbiAgICBmb3IgKGxldCBlbGVtIG9mIGNvbGxlY3Rpb24pIHtcbiAgICAgIGlmIChmdW4oZWxlbSkpIHtcbiAgICAgICAgY291bnQgPSBjb3VudCArIDE7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBicmVhaztcbiAgICAgIH1cbiAgICB9XG5cbiAgICByZXR1cm4gY29sbGVjdGlvbi5zbGljZSgwLCBjb3VudCk7XG4gIH0sXG5cbiAgdG9fbGlzdDogZnVuY3Rpb24gKGNvbGxlY3Rpb24pIHtcbiAgICByZXR1cm4gY29sbGVjdGlvbjtcbiAgfVxufTtcblxubGV0IFNwZWNpYWxGb3JtcyQxID0ge1xuXG4gIGF0b206IGZ1bmN0aW9uIChfdmFsdWUpIHtcbiAgICByZXR1cm4gU3ltYm9sLmZvcihfdmFsdWUpO1xuICB9LFxuXG4gIGxpc3Q6IGZ1bmN0aW9uICguLi5hcmdzKSB7XG4gICAgcmV0dXJuIE9iamVjdC5mcmVlemUoYXJncyk7XG4gIH0sXG5cbiAgYml0c3RyaW5nOiBmdW5jdGlvbiAoLi4uYXJncykge1xuICAgIHJldHVybiBuZXcgQml0U3RyaW5nKC4uLmFyZ3MpO1xuICB9LFxuXG4gIGJvdW5kOiBmdW5jdGlvbiAoX3Zhcikge1xuICAgIHJldHVybiBQYXR0ZXJucy5ib3VuZChfdmFyKTtcbiAgfSxcblxuICBfY2FzZTogZnVuY3Rpb24gKGNvbmRpdGlvbiwgY2xhdXNlcykge1xuICAgIHJldHVybiBQYXR0ZXJucy5kZWZtYXRjaCguLi5jbGF1c2VzKShjb25kaXRpb24pO1xuICB9LFxuXG4gIGNvbmQ6IGZ1bmN0aW9uIChjbGF1c2VzKSB7XG4gICAgZm9yIChsZXQgY2xhdXNlIG9mIGNsYXVzZXMpIHtcbiAgICAgIGlmIChjbGF1c2VbMF0pIHtcbiAgICAgICAgcmV0dXJuIGNsYXVzZVsxXSgpO1xuICAgICAgfVxuICAgIH1cblxuICAgIHRocm93IG5ldyBFcnJvcigpO1xuICB9LFxuXG4gIGZuOiBmdW5jdGlvbiAoY2xhdXNlcykge1xuICAgIHJldHVybiBQYXR0ZXJucy5kZWZtYXRjaChjbGF1c2VzKTtcbiAgfSxcblxuICBtYXA6IGZ1bmN0aW9uIChvYmopIHtcbiAgICByZXR1cm4gT2JqZWN0LmZyZWV6ZShvYmopO1xuICB9LFxuXG4gIG1hcF91cGRhdGU6IGZ1bmN0aW9uIChtYXAsIHZhbHVlcykge1xuICAgIHJldHVybiBPYmplY3QuZnJlZXplKE9iamVjdC5hc3NpZ24oT2JqZWN0LmNyZWF0ZShtYXAuY29uc3RydWN0b3IucHJvdG90eXBlKSwgbWFwLCB2YWx1ZXMpKTtcbiAgfSxcblxuICBfZm9yOiBmdW5jdGlvbiAoY29sbGVjdGlvbnMsIGZ1biwgZmlsdGVyID0gKCkgPT4gdHJ1ZSwgaW50byA9IFtdLCBwcmV2aW91c1ZhbHVlcyA9IFtdKSB7XG4gICAgbGV0IHBhdHRlcm4gPSBjb2xsZWN0aW9uc1swXVswXTtcbiAgICBsZXQgY29sbGVjdGlvbiA9IGNvbGxlY3Rpb25zWzBdWzFdO1xuXG4gICAgaWYgKGNvbGxlY3Rpb25zLmxlbmd0aCA9PT0gMSkge1xuXG4gICAgICBmb3IgKGxldCBlbGVtIG9mIGNvbGxlY3Rpb24pIHtcbiAgICAgICAgbGV0IHIgPSBQYXR0ZXJucy5tYXRjaF9ub190aHJvdyhwYXR0ZXJuLCBlbGVtKTtcbiAgICAgICAgbGV0IGFyZ3MgPSBwcmV2aW91c1ZhbHVlcy5jb25jYXQocik7XG5cbiAgICAgICAgaWYgKHIgJiYgZmlsdGVyLmFwcGx5KHRoaXMsIGFyZ3MpKSB7XG4gICAgICAgICAgaW50byA9IEVudW0uaW50byhbZnVuLmFwcGx5KHRoaXMsIGFyZ3MpXSwgaW50byk7XG4gICAgICAgIH1cbiAgICAgIH1cblxuICAgICAgcmV0dXJuIGludG87XG4gICAgfSBlbHNlIHtcbiAgICAgIGxldCBfaW50byA9IFtdO1xuXG4gICAgICBmb3IgKGxldCBlbGVtIG9mIGNvbGxlY3Rpb24pIHtcbiAgICAgICAgbGV0IHIgPSBQYXR0ZXJucy5tYXRjaF9ub190aHJvdyhwYXR0ZXJuLCBlbGVtKTtcbiAgICAgICAgaWYgKHIpIHtcbiAgICAgICAgICBfaW50byA9IEVudW0uaW50byh0aGlzLl9mb3IoY29sbGVjdGlvbnMuc2xpY2UoMSksIGZ1biwgZmlsdGVyLCBfaW50bywgcHJldmlvdXNWYWx1ZXMuY29uY2F0KHIpKSwgaW50byk7XG4gICAgICAgIH1cbiAgICAgIH1cblxuICAgICAgcmV0dXJuIF9pbnRvO1xuICAgIH1cbiAgfSxcblxuICByZWNlaXZlOiBmdW5jdGlvbiAocmVjZWl2ZV9mdW4sIHRpbWVvdXRfaW5fbXMgPSBudWxsLCB0aW1lb3V0X2ZuID0gdGltZSA9PiB0cnVlKSB7XG4gICAgaWYgKHRpbWVvdXRfaW5fbXMgPT0gbnVsbCB8fCB0aW1lb3V0X2luX21zID09PSBTeXN0ZW0uZm9yKCdpbmZpbml0eScpKSB7XG4gICAgICB3aGlsZSAodHJ1ZSkge1xuICAgICAgICBpZiAoc2VsZi5tYWlsYm94Lmxlbmd0aCAhPT0gMCkge1xuICAgICAgICAgIGxldCBtZXNzYWdlID0gc2VsZi5tYWlsYm94WzBdO1xuICAgICAgICAgIHNlbGYubWFpbGJveCA9IHNlbGYubWFpbGJveC5zbGljZSgxKTtcbiAgICAgICAgICByZXR1cm4gcmVjZWl2ZV9mdW4obWVzc2FnZSk7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9IGVsc2UgaWYgKHRpbWVvdXRfaW5fbXMgPT09IDApIHtcbiAgICAgIGlmIChzZWxmLm1haWxib3gubGVuZ3RoICE9PSAwKSB7XG4gICAgICAgIGxldCBtZXNzYWdlID0gc2VsZi5tYWlsYm94WzBdO1xuICAgICAgICBzZWxmLm1haWxib3ggPSBzZWxmLm1haWxib3guc2xpY2UoMSk7XG4gICAgICAgIHJldHVybiByZWNlaXZlX2Z1bihtZXNzYWdlKTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHJldHVybiBudWxsO1xuICAgICAgfVxuICAgIH0gZWxzZSB7XG4gICAgICBsZXQgbm93ID0gRGF0ZS5ub3coKTtcbiAgICAgIHdoaWxlIChEYXRlLm5vdygpIDwgbm93ICsgdGltZW91dF9pbl9tcykge1xuICAgICAgICBpZiAoc2VsZi5tYWlsYm94Lmxlbmd0aCAhPT0gMCkge1xuICAgICAgICAgIGxldCBtZXNzYWdlID0gc2VsZi5tYWlsYm94WzBdO1xuICAgICAgICAgIHNlbGYubWFpbGJveCA9IHNlbGYubWFpbGJveC5zbGljZSgxKTtcbiAgICAgICAgICByZXR1cm4gcmVjZWl2ZV9mdW4obWVzc2FnZSk7XG4gICAgICAgIH1cbiAgICAgIH1cblxuICAgICAgcmV0dXJuIHRpbWVvdXRfZm4odGltZW91dF9pbl9tcyk7XG4gICAgfVxuICB9LFxuXG4gIHR1cGxlOiBmdW5jdGlvbiAoLi4uYXJncykge1xuICAgIHJldHVybiBuZXcgVHVwbGUoLi4uYXJncyk7XG4gIH0sXG5cbiAgX3RyeTogZnVuY3Rpb24gKGRvX2Z1biwgcmVzY3VlX2Z1bmN0aW9uLCBjYXRjaF9mdW4sIGVsc2VfZnVuY3Rpb24sIGFmdGVyX2Z1bmN0aW9uKSB7XG4gICAgbGV0IHJlc3VsdCA9IG51bGw7XG5cbiAgICB0cnkge1xuICAgICAgcmVzdWx0ID0gZG9fZnVuKCk7XG4gICAgfSBjYXRjaCAoZSkge1xuICAgICAgbGV0IGV4X3Jlc3VsdCA9IG51bGw7XG5cbiAgICAgIGlmIChyZXNjdWVfZnVuY3Rpb24pIHtcbiAgICAgICAgdHJ5IHtcbiAgICAgICAgICBleF9yZXN1bHQgPSByZXNjdWVfZnVuY3Rpb24oZSk7XG4gICAgICAgICAgcmV0dXJuIGV4X3Jlc3VsdDtcbiAgICAgICAgfSBjYXRjaCAoZXgpIHtcbiAgICAgICAgICBpZiAoZXggaW5zdGFuY2VvZiBQYXR0ZXJucy5NYXRjaEVycm9yKSB7XG4gICAgICAgICAgICB0aHJvdyBleDtcbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgIH1cblxuICAgICAgaWYgKGNhdGNoX2Z1bikge1xuICAgICAgICB0cnkge1xuICAgICAgICAgIGV4X3Jlc3VsdCA9IGNhdGNoX2Z1bihlKTtcbiAgICAgICAgICByZXR1cm4gZXhfcmVzdWx0O1xuICAgICAgICB9IGNhdGNoIChleCkge1xuICAgICAgICAgIGlmIChleCBpbnN0YW5jZW9mIFBhdHRlcm5zLk1hdGNoRXJyb3IpIHtcbiAgICAgICAgICAgIHRocm93IGV4O1xuICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgfVxuXG4gICAgICB0aHJvdyBlO1xuICAgIH0gZmluYWxseSB7XG4gICAgICBpZiAoYWZ0ZXJfZnVuY3Rpb24pIHtcbiAgICAgICAgYWZ0ZXJfZnVuY3Rpb24oKTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICBpZiAoZWxzZV9mdW5jdGlvbikge1xuICAgICAgdHJ5IHtcbiAgICAgICAgcmV0dXJuIGVsc2VfZnVuY3Rpb24ocmVzdWx0KTtcbiAgICAgIH0gY2F0Y2ggKGV4KSB7XG4gICAgICAgIGlmIChleCBpbnN0YW5jZW9mIFBhdHRlcm5zLk1hdGNoRXJyb3IpIHtcbiAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ05vIE1hdGNoIEZvdW5kIGluIEVsc2UnKTtcbiAgICAgICAgfVxuXG4gICAgICAgIHRocm93IGV4O1xuICAgICAgfVxuICAgIH0gZWxzZSB7XG4gICAgICByZXR1cm4gcmVzdWx0O1xuICAgIH1cbiAgfVxuXG59O1xuXG5mdW5jdGlvbiB0bChsaXN0KSB7XG4gIHJldHVybiBTcGVjaWFsRm9ybXMkMS5saXN0KC4uLmxpc3Quc2xpY2UoMSkpO1xufVxuXG5mdW5jdGlvbiBoZChsaXN0KSB7XG4gIHJldHVybiBsaXN0WzBdO1xufVxuXG5mdW5jdGlvbiBpc19uaWwoeCkge1xuICByZXR1cm4geCA9PT0gbnVsbDtcbn1cblxuZnVuY3Rpb24gaXNfYXRvbSh4KSB7XG4gIHJldHVybiB0eXBlb2YgeCA9PT0gJ3N5bWJvbCc7XG59XG5cbmZ1bmN0aW9uIGlzX2JpbmFyeSh4KSB7XG4gIHJldHVybiB0eXBlb2YgeCA9PT0gJ3N0cmluZycgfHwgeCBpbnN0YW5jZW9mIFN0cmluZztcbn1cblxuZnVuY3Rpb24gaXNfYm9vbGVhbih4KSB7XG4gIHJldHVybiB0eXBlb2YgeCA9PT0gJ2Jvb2xlYW4nIHx8IHggaW5zdGFuY2VvZiBCb29sZWFuO1xufVxuXG5mdW5jdGlvbiBpc19mdW5jdGlvbih4LCBhcml0eSA9IC0xKSB7XG4gIHJldHVybiB0eXBlb2YgeCA9PT0gJ2Z1bmN0aW9uJyB8fCB4IGluc3RhbmNlb2YgRnVuY3Rpb247XG59XG5cbmZ1bmN0aW9uIGlzX2Zsb2F0KHgpIHtcbiAgcmV0dXJuIGlzX251bWJlcih4KSAmJiAhTnVtYmVyLmlzSW50ZWdlcih4KTtcbn1cblxuZnVuY3Rpb24gaXNfaW50ZWdlcih4KSB7XG4gIHJldHVybiBOdW1iZXIuaXNJbnRlZ2VyKHgpO1xufVxuXG5mdW5jdGlvbiBpc19saXN0KHgpIHtcbiAgcmV0dXJuIHggaW5zdGFuY2VvZiBBcnJheTtcbn1cblxuZnVuY3Rpb24gaXNfbWFwKHgpIHtcbiAgcmV0dXJuIHR5cGVvZiB4ID09PSAnb2JqZWN0JyB8fCB4IGluc3RhbmNlb2YgT2JqZWN0O1xufVxuXG5mdW5jdGlvbiBpc19udW1iZXIoeCkge1xuICByZXR1cm4gdHlwZW9mIHggPT09ICdudW1iZXInO1xufVxuXG5mdW5jdGlvbiBpc190dXBsZSh4KSB7XG4gIHJldHVybiB4IGluc3RhbmNlb2YgVHVwbGU7XG59XG5cbmZ1bmN0aW9uIGxlbmd0aCh4KSB7XG4gIHJldHVybiB4Lmxlbmd0aDtcbn1cblxuZnVuY3Rpb24gaXNfcGlkKHgpIHtcbiAgcmV0dXJuIHggaW5zdGFuY2VvZiBQSUQ7XG59XG5cbmZ1bmN0aW9uIGlzX3BvcnQoeCkge1xuICByZXR1cm4gZmFsc2U7XG59XG5cbmZ1bmN0aW9uIGlzX3JlZmVyZW5jZSh4KSB7XG4gIHJldHVybiBmYWxzZTtcbn1cblxuZnVuY3Rpb24gaXNfYml0c3RyaW5nKHgpIHtcbiAgcmV0dXJuIGlzX2JpbmFyeSh4KSB8fCB4IGluc3RhbmNlb2YgQml0U3RyaW5nO1xufVxuXG5mdW5jdGlvbiBfX2luX18obGVmdCwgcmlnaHQpIHtcbiAgZm9yIChsZXQgeCBvZiByaWdodCkge1xuICAgIGlmIChtYXRjaF9fcW1hcmtfXyhsZWZ0LCB4KSkge1xuICAgICAgcmV0dXJuIHRydWU7XG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIGZhbHNlO1xufVxuXG5mdW5jdGlvbiBhYnMobnVtYmVyKSB7XG4gIHJldHVybiBNYXRoLmFicyhudW1iZXIpO1xufVxuXG5mdW5jdGlvbiByb3VuZChudW1iZXIpIHtcbiAgcmV0dXJuIE1hdGgucm91bmQobnVtYmVyKTtcbn1cblxuZnVuY3Rpb24gZWxlbSh0dXBsZSwgaW5kZXgpIHtcbiAgaWYgKGlzX2xpc3QodHVwbGUpKSB7XG4gICAgcmV0dXJuIHR1cGxlW2luZGV4XTtcbiAgfVxuXG4gIHJldHVybiB0dXBsZS5nZXQoaW5kZXgpO1xufVxuXG5mdW5jdGlvbiByZW0obGVmdCwgcmlnaHQpIHtcbiAgcmV0dXJuIGxlZnQgJSByaWdodDtcbn1cblxuZnVuY3Rpb24gZGl2KGxlZnQsIHJpZ2h0KSB7XG4gIHJldHVybiBsZWZ0IC8gcmlnaHQ7XG59XG5cbmZ1bmN0aW9uIGFuZChsZWZ0LCByaWdodCkge1xuICByZXR1cm4gbGVmdCAmJiByaWdodDtcbn1cblxuZnVuY3Rpb24gb3IobGVmdCwgcmlnaHQpIHtcbiAgcmV0dXJuIGxlZnQgfHwgcmlnaHQ7XG59XG5cbmZ1bmN0aW9uIG5vdChhcmcpIHtcbiAgcmV0dXJuICFhcmc7XG59XG5cbmZ1bmN0aW9uIGFwcGx5KC4uLmFyZ3MpIHtcbiAgaWYgKGFyZ3MubGVuZ3RoID09PSAzKSB7XG4gICAgbGV0IG1vZCA9IGFyZ3NbMF07XG4gICAgbGV0IGZ1bmMgPSBhcmdzWzFdO1xuICAgIGxldCBmdW5jX2FyZ3MgPSBhcmdzWzJdO1xuICAgIHJldHVybiBtb2RbZnVuY10uYXBwbHkobnVsbCwgZnVuY19hcmdzKTtcbiAgfSBlbHNlIHtcbiAgICBsZXQgZnVuYyA9IGFyZ3NbMF07XG4gICAgbGV0IGZ1bmNfYXJncyA9IGFyZ3NbMV07XG5cbiAgICByZXR1cm4gZnVuYy5hcHBseShudWxsLCBmdW5jX2FyZ3MpO1xuICB9XG59XG5cbmZ1bmN0aW9uIHRvX3N0cmluZyhhcmcpIHtcbiAgaWYgKGlzX3R1cGxlKGFyZykpIHtcbiAgICByZXR1cm4gYXJnLnRvU3RyaW5nKCk7XG4gIH1cblxuICByZXR1cm4gYXJnLnRvU3RyaW5nKCk7XG59XG5cbmZ1bmN0aW9uIG1hdGNoX19xbWFya19fKHBhdHRlcm4sIGV4cHIsIGd1YXJkID0gKCkgPT4gdHJ1ZSkge1xuICByZXR1cm4gUGF0dGVybnMubWF0Y2hfbm9fdGhyb3cocGF0dGVybiwgZXhwciwgZ3VhcmQpICE9IG51bGw7XG59XG5cbnZhciBLZXJuZWwgPSB7XG4gIFNwZWNpYWxGb3JtczogU3BlY2lhbEZvcm1zJDEsXG4gIHRsLFxuICBoZCxcbiAgaXNfbmlsLFxuICBpc19hdG9tLFxuICBpc19iaW5hcnksXG4gIGlzX2Jvb2xlYW4sXG4gIGlzX2Z1bmN0aW9uLFxuICBpc19mbG9hdCxcbiAgaXNfaW50ZWdlcixcbiAgaXNfbGlzdCxcbiAgaXNfbWFwLFxuICBpc19udW1iZXIsXG4gIGlzX3R1cGxlLFxuICBsZW5ndGgsXG4gIGlzX3BpZCxcbiAgaXNfcG9ydCxcbiAgaXNfcmVmZXJlbmNlLFxuICBpc19iaXRzdHJpbmcsXG4gIGluOiBfX2luX18sXG4gIGFicyxcbiAgcm91bmQsXG4gIGVsZW0sXG4gIHJlbSxcbiAgZGl2LFxuICBhbmQsXG4gIG9yLFxuICBub3QsXG4gIGFwcGx5LFxuICB0b19zdHJpbmcsXG4gIG1hdGNoX19xbWFya19fXG59O1xuXG5sZXQgTGlzdCA9IHt9O1xuXG5MaXN0LmRlbGV0ZSA9IGZ1bmN0aW9uIChsaXN0LCBpdGVtKSB7XG4gIGxldCBuZXdfdmFsdWUgPSBbXTtcbiAgbGV0IHZhbHVlX2ZvdW5kID0gZmFsc2U7XG5cbiAgZm9yIChsZXQgeCBvZiBsaXN0KSB7XG4gICAgaWYgKHggPT09IGl0ZW0gJiYgdmFsdWVfZm91bmQgIT09IGZhbHNlKSB7XG4gICAgICBuZXdfdmFsdWUucHVzaCh4KTtcbiAgICAgIHZhbHVlX2ZvdW5kID0gdHJ1ZTtcbiAgICB9IGVsc2UgaWYgKHggIT09IGl0ZW0pIHtcbiAgICAgIG5ld192YWx1ZS5wdXNoKHgpO1xuICAgIH1cbiAgfVxuXG4gIHJldHVybiBMaXN0JDEoLi4ubmV3X3ZhbHVlKTtcbn07XG5cbkxpc3QuZGVsZXRlX2F0ID0gZnVuY3Rpb24gKGxpc3QsIGluZGV4KSB7XG4gIGxldCBuZXdfdmFsdWUgPSBbXTtcblxuICBmb3IgKGxldCBpID0gMDsgaSA8IGxpc3QubGVuZ3RoOyBpKyspIHtcbiAgICBpZiAoaSAhPT0gaW5kZXgpIHtcbiAgICAgIG5ld192YWx1ZS5wdXNoKGxpc3RbaV0pO1xuICAgIH1cbiAgfVxuXG4gIHJldHVybiBMaXN0JDEoLi4ubmV3X3ZhbHVlKTtcbn07XG5cbkxpc3QuZHVwbGljYXRlID0gZnVuY3Rpb24gKGVsZW0sIG4pIHtcbiAgbGV0IG5ld192YWx1ZSA9IFtdO1xuXG4gIGZvciAodmFyIGkgPSAwOyBpIDwgbjsgaSsrKSB7XG4gICAgbmV3X3ZhbHVlLnB1c2goZWxlbSk7XG4gIH1cblxuICByZXR1cm4gTGlzdCQxKC4uLm5ld192YWx1ZSk7XG59O1xuXG5MaXN0LmZpcnN0ID0gZnVuY3Rpb24gKGxpc3QpIHtcbiAgcmV0dXJuIGxpc3RbMF07XG59O1xuXG5MaXN0LmZsYXR0ZW4gPSBmdW5jdGlvbiAobGlzdCwgdGFpbCA9IExpc3QkMSgpKSB7XG4gIGxldCBuZXdfdmFsdWUgPSBbXTtcblxuICBmb3IgKGxldCB4IG9mIGxpc3QpIHtcbiAgICBpZiAoS2VybmVsLmlzX2xpc3QoeCkpIHtcbiAgICAgIG5ld192YWx1ZSA9IG5ld192YWx1ZS5jb25jYXQoTGlzdC5mbGF0dGVuKHgpKTtcbiAgICB9IGVsc2Uge1xuICAgICAgbmV3X3ZhbHVlLnB1c2goeCk7XG4gICAgfVxuICB9XG5cbiAgbmV3X3ZhbHVlID0gbmV3X3ZhbHVlLmNvbmNhdCh0YWlsKTtcblxuICByZXR1cm4gTGlzdCQxKC4uLm5ld192YWx1ZSk7XG59O1xuXG5MaXN0LmZvbGRsID0gZnVuY3Rpb24gKGxpc3QsIGFjYywgZnVuYykge1xuICByZXR1cm4gbGlzdC5yZWR1Y2UoZnVuYywgYWNjKTtcbn07XG5cbkxpc3QuZm9sZHIgPSBmdW5jdGlvbiAobGlzdCwgYWNjLCBmdW5jKSB7XG4gIGxldCBuZXdfYWNjID0gYWNjO1xuXG4gIGZvciAodmFyIGkgPSBsaXN0Lmxlbmd0aCAtIDE7IGkgPj0gMDsgaS0tKSB7XG4gICAgbmV3X2FjYyA9IGZ1bmMobGlzdFtpXSwgbmV3X2FjYyk7XG4gIH1cblxuICByZXR1cm4gbmV3X2FjYztcbn07XG5cbkxpc3QuaW5zZXJ0X2F0ID0gZnVuY3Rpb24gKGxpc3QsIGluZGV4LCB2YWx1ZSkge1xuICBsZXQgbmV3X3ZhbHVlID0gW107XG5cbiAgZm9yIChsZXQgaSA9IDA7IGkgPCBsaXN0Lmxlbmd0aDsgaSsrKSB7XG4gICAgaWYgKGkgPT09IGluZGV4KSB7XG4gICAgICBuZXdfdmFsdWUucHVzaCh2YWx1ZSk7XG4gICAgICBuZXdfdmFsdWUucHVzaChsaXN0W2ldKTtcbiAgICB9IGVsc2Uge1xuICAgICAgbmV3X3ZhbHVlLnB1c2gobGlzdFtpXSk7XG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIExpc3QkMSguLi5uZXdfdmFsdWUpO1xufTtcblxuTGlzdC5rZXlkZWxldGUgPSBmdW5jdGlvbiAobGlzdCwga2V5LCBwb3NpdGlvbikge1xuICBsZXQgbmV3X2xpc3QgPSBbXTtcblxuICBmb3IgKGxldCBpID0gMDsgaSA8IGxpc3QubGVuZ3RoOyBpKyspIHtcbiAgICBpZiAoIUtlcm5lbC5tYXRjaF9fcW1hcmtfXyhsaXN0W2ldW3Bvc2l0aW9uXSwga2V5KSkge1xuICAgICAgbmV3X2xpc3QucHVzaChsaXN0W2ldKTtcbiAgICB9XG4gIH1cblxuICByZXR1cm4gTGlzdCQxKC4uLm5ld19saXN0KTtcbn07XG5cbkxpc3Qua2V5ZmluZCA9IGZ1bmN0aW9uIChsaXN0LCBrZXksIHBvc2l0aW9uLCBfZGVmYXVsdCA9IG51bGwpIHtcblxuICBmb3IgKGxldCBpID0gMDsgaSA8IGxpc3QubGVuZ3RoOyBpKyspIHtcbiAgICBpZiAoS2VybmVsLm1hdGNoX19xbWFya19fKGxpc3RbaV1bcG9zaXRpb25dLCBrZXkpKSB7XG4gICAgICByZXR1cm4gbGlzdFtpXTtcbiAgICB9XG4gIH1cblxuICByZXR1cm4gX2RlZmF1bHQ7XG59O1xuXG5MaXN0LmtleW1lbWJlcl9fcW1hcmtfXyA9IGZ1bmN0aW9uIChsaXN0LCBrZXksIHBvc2l0aW9uKSB7XG5cbiAgZm9yIChsZXQgaSA9IDA7IGkgPCBsaXN0Lmxlbmd0aDsgaSsrKSB7XG4gICAgaWYgKEtlcm5lbC5tYXRjaF9fcW1hcmtfXyhsaXN0W2ldW3Bvc2l0aW9uXSwga2V5KSkge1xuICAgICAgcmV0dXJuIHRydWU7XG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIGZhbHNlO1xufTtcblxuTGlzdC5rZXlyZXBsYWNlID0gZnVuY3Rpb24gKGxpc3QsIGtleSwgcG9zaXRpb24sIG5ld190dXBsZSkge1xuICBsZXQgbmV3X2xpc3QgPSBbXTtcblxuICBmb3IgKGxldCBpID0gMDsgaSA8IGxpc3QubGVuZ3RoOyBpKyspIHtcbiAgICBpZiAoIUtlcm5lbC5tYXRjaF9fcW1hcmtfXyhsaXN0W2ldW3Bvc2l0aW9uXSwga2V5KSkge1xuICAgICAgbmV3X2xpc3QucHVzaChsaXN0W2ldKTtcbiAgICB9IGVsc2Uge1xuICAgICAgbmV3X2xpc3QucHVzaChuZXdfdHVwbGUpO1xuICAgIH1cbiAgfVxuXG4gIHJldHVybiBMaXN0JDEoLi4ubmV3X2xpc3QpO1xufTtcblxuTGlzdC5rZXlzb3J0ID0gZnVuY3Rpb24gKGxpc3QsIHBvc2l0aW9uKSB7XG4gIGxldCBuZXdfbGlzdCA9IGxpc3Q7XG5cbiAgbmV3X2xpc3Quc29ydChmdW5jdGlvbiAoYSwgYikge1xuICAgIGlmIChwb3NpdGlvbiA9PT0gMCkge1xuICAgICAgaWYgKGFbcG9zaXRpb25dLnZhbHVlIDwgYltwb3NpdGlvbl0udmFsdWUpIHtcbiAgICAgICAgcmV0dXJuIC0xO1xuICAgICAgfVxuXG4gICAgICBpZiAoYVtwb3NpdGlvbl0udmFsdWUgPiBiW3Bvc2l0aW9uXS52YWx1ZSkge1xuICAgICAgICByZXR1cm4gMTtcbiAgICAgIH1cblxuICAgICAgcmV0dXJuIDA7XG4gICAgfSBlbHNlIHtcbiAgICAgIGlmIChhW3Bvc2l0aW9uXSA8IGJbcG9zaXRpb25dKSB7XG4gICAgICAgIHJldHVybiAtMTtcbiAgICAgIH1cblxuICAgICAgaWYgKGFbcG9zaXRpb25dID4gYltwb3NpdGlvbl0pIHtcbiAgICAgICAgcmV0dXJuIDE7XG4gICAgICB9XG5cbiAgICAgIHJldHVybiAwO1xuICAgIH1cbiAgfSk7XG5cbiAgcmV0dXJuIExpc3QkMSguLi5uZXdfbGlzdCk7XG59O1xuXG5MaXN0LmtleXN0b3JlID0gZnVuY3Rpb24gKGxpc3QsIGtleSwgcG9zaXRpb24sIG5ld190dXBsZSkge1xuICBsZXQgbmV3X2xpc3QgPSBbXTtcbiAgbGV0IHJlcGxhY2VkID0gZmFsc2U7XG5cbiAgZm9yIChsZXQgaSA9IDA7IGkgPCBsaXN0Lmxlbmd0aDsgaSsrKSB7XG4gICAgaWYgKCFLZXJuZWwubWF0Y2hfX3FtYXJrX18obGlzdFtpXVtwb3NpdGlvbl0sIGtleSkpIHtcbiAgICAgIG5ld19saXN0LnB1c2gobGlzdFtpXSk7XG4gICAgfSBlbHNlIHtcbiAgICAgIG5ld19saXN0LnB1c2gobmV3X3R1cGxlKTtcbiAgICAgIHJlcGxhY2VkID0gdHJ1ZTtcbiAgICB9XG4gIH1cblxuICBpZiAoIXJlcGxhY2VkKSB7XG4gICAgbmV3X2xpc3QucHVzaChuZXdfdHVwbGUpO1xuICB9XG5cbiAgcmV0dXJuIExpc3QkMSguLi5uZXdfbGlzdCk7XG59O1xuXG5MaXN0Lmxhc3QgPSBmdW5jdGlvbiAobGlzdCkge1xuICByZXR1cm4gbGlzdFtsaXN0Lmxlbmd0aCAtIDFdO1xufTtcblxuTGlzdC5yZXBsYWNlX2F0ID0gZnVuY3Rpb24gKGxpc3QsIGluZGV4LCB2YWx1ZSkge1xuICBsZXQgbmV3X3ZhbHVlID0gW107XG5cbiAgZm9yIChsZXQgaSA9IDA7IGkgPCBsaXN0Lmxlbmd0aDsgaSsrKSB7XG4gICAgaWYgKGkgPT09IGluZGV4KSB7XG4gICAgICBuZXdfdmFsdWUucHVzaCh2YWx1ZSk7XG4gICAgfSBlbHNlIHtcbiAgICAgIG5ld192YWx1ZS5wdXNoKGxpc3RbaV0pO1xuICAgIH1cbiAgfVxuXG4gIHJldHVybiBMaXN0JDEoLi4ubmV3X3ZhbHVlKTtcbn07XG5cbkxpc3QudXBkYXRlX2F0ID0gZnVuY3Rpb24gKGxpc3QsIGluZGV4LCBmdW4pIHtcbiAgbGV0IG5ld192YWx1ZSA9IFtdO1xuXG4gIGZvciAobGV0IGkgPSAwOyBpIDwgbGlzdC5jb3VudCgpOyBpKyspIHtcbiAgICBpZiAoaSA9PT0gaW5kZXgpIHtcbiAgICAgIG5ld192YWx1ZS5wdXNoKGZ1bihsaXN0LmdldChpKSkpO1xuICAgIH0gZWxzZSB7XG4gICAgICBuZXdfdmFsdWUucHVzaChsaXN0LmdldChpKSk7XG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIG5ld192YWx1ZTtcbn07XG5cbkxpc3Qud3JhcCA9IGZ1bmN0aW9uIChsaXN0KSB7XG4gIGlmIChLZXJuZWwuaXNfbGlzdChsaXN0KSkge1xuICAgIHJldHVybiBsaXN0O1xuICB9IGVsc2UgaWYgKGxpc3QgPT0gbnVsbCkge1xuICAgIHJldHVybiBMaXN0JDEoKTtcbiAgfSBlbHNlIHtcbiAgICByZXR1cm4gTGlzdCQxKGxpc3QpO1xuICB9XG59O1xuXG5MaXN0LnppcCA9IGZ1bmN0aW9uIChsaXN0X29mX2xpc3RzKSB7XG4gIGlmIChsaXN0X29mX2xpc3RzLmxlbmd0aCA9PT0gMCkge1xuICAgIHJldHVybiBMaXN0JDEoKTtcbiAgfVxuXG4gIGxldCBuZXdfdmFsdWUgPSBbXTtcbiAgbGV0IHNtYWxsZXN0X2xlbmd0aCA9IGxpc3Rfb2ZfbGlzdHNbMF07XG5cbiAgZm9yIChsZXQgeCBvZiBsaXN0X29mX2xpc3RzKSB7XG4gICAgaWYgKHgubGVuZ3RoIDwgc21hbGxlc3RfbGVuZ3RoKSB7XG4gICAgICBzbWFsbGVzdF9sZW5ndGggPSB4Lmxlbmd0aDtcbiAgICB9XG4gIH1cblxuICBmb3IgKGxldCBpID0gMDsgaSA8IHNtYWxsZXN0X2xlbmd0aDsgaSsrKSB7XG4gICAgbGV0IGN1cnJlbnRfdmFsdWUgPSBbXTtcbiAgICBmb3IgKGxldCBqID0gMDsgaiA8IGxpc3Rfb2ZfbGlzdHMubGVuZ3RoOyBqKyspIHtcbiAgICAgIGN1cnJlbnRfdmFsdWUucHVzaChsaXN0X29mX2xpc3RzW2pdW2ldKTtcbiAgICB9XG5cbiAgICBuZXdfdmFsdWUucHVzaChuZXcgVHVwbGUoLi4uY3VycmVudF92YWx1ZSkpO1xuICB9XG5cbiAgcmV0dXJuIExpc3QkMSguLi5uZXdfdmFsdWUpO1xufTtcblxuTGlzdC50b190dXBsZSA9IGZ1bmN0aW9uIChsaXN0KSB7XG4gIHJldHVybiBuZXcgVHVwbGUoLi4ubGlzdCk7XG59O1xuXG5MaXN0LmFwcGVuZCA9IGZ1bmN0aW9uIChsaXN0LCB2YWx1ZSkge1xuICByZXR1cm4gTGlzdCQxKC4uLmxpc3QuY29uY2F0KFt2YWx1ZV0pKTtcbn07XG5cbkxpc3QucHJlcGVuZCA9IGZ1bmN0aW9uIChsaXN0LCB2YWx1ZSkge1xuICByZXR1cm4gTGlzdCQxKC4uLlt2YWx1ZV0uY29uY2F0KGxpc3QpKTtcbn07XG5cbkxpc3QuY29uY2F0ID0gZnVuY3Rpb24gKGxlZnQsIHJpZ2h0KSB7XG4gIHJldHVybiBsZWZ0LmNvbmNhdChyaWdodCk7XG59O1xuXG5sZXQgS2V5d29yZCA9IHt9O1xuXG5LZXl3b3JkLmhhc19rZXlfX3FtYXJrX18gPSBmdW5jdGlvbiAoa2V5d29yZHMsIGtleSkge1xuICBmb3IgKGxldCBrZXl3b3JkIG9mIGtleXdvcmRzKSB7XG4gICAgaWYgKEtlcm5lbC5lbGVtKGtleXdvcmQsIDApID09IGtleSkge1xuICAgICAgcmV0dXJuIHRydWU7XG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIGZhbHNlO1xufTtcblxuS2V5d29yZC5nZXQgPSBmdW5jdGlvbiAoa2V5d29yZHMsIGtleSwgdGhlX2RlZmF1bHQgPSBudWxsKSB7XG4gIGZvciAobGV0IGtleXdvcmQgb2Yga2V5d29yZHMpIHtcbiAgICBpZiAoS2VybmVsLmVsZW0oa2V5d29yZCwgMCkgPT0ga2V5KSB7XG4gICAgICByZXR1cm4gS2VybmVsLmVsZW0oa2V5d29yZCwgMSk7XG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIHRoZV9kZWZhdWx0O1xufTtcblxuZnVuY3Rpb24gYm5vdChleHByKSB7XG4gIHJldHVybiB+ZXhwcjtcbn1cblxuZnVuY3Rpb24gYmFuZChsZWZ0LCByaWdodCkge1xuICByZXR1cm4gbGVmdCAmIHJpZ2h0O1xufVxuXG5mdW5jdGlvbiBib3IobGVmdCwgcmlnaHQpIHtcbiAgcmV0dXJuIGxlZnQgfCByaWdodDtcbn1cblxuZnVuY3Rpb24gYnNsKGxlZnQsIHJpZ2h0KSB7XG4gIHJldHVybiBsZWZ0IDw8IHJpZ2h0O1xufVxuXG5mdW5jdGlvbiBic3IobGVmdCwgcmlnaHQpIHtcbiAgcmV0dXJuIGxlZnQgPj4gcmlnaHQ7XG59XG5cbmZ1bmN0aW9uIGJ4b3IobGVmdCwgcmlnaHQpIHtcbiAgcmV0dXJuIGxlZnQgXiByaWdodDtcbn1cblxudmFyIGJpdHdpc2UgPSB7XG4gIGJub3QsXG4gIGJhbmQsXG4gIGJvcixcbiAgYnNsLFxuICBic3IsXG4gIGJ4b3Jcbn07XG5cbmZ1bmN0aW9uIF9fbmV3X18oKSB7XG4gIHJldHVybiBTcGVjaWFsRm9ybXMkMS5tYXAoe30pO1xufVxuXG5mdW5jdGlvbiBrZXlzKG1hcCkge1xuICByZXR1cm4gRnVuY3Rpb25zLmdldF9vYmplY3Rfa2V5cyhtYXApO1xufVxuXG5mdW5jdGlvbiBzaXplKG1hcCkge1xuICByZXR1cm4ga2V5cyhtYXApLmxlbmd0aDtcbn1cblxuZnVuY3Rpb24gdG9fbGlzdChtYXApIHtcbiAgbGV0IG1hcF9rZXlzID0ga2V5cyhtYXApO1xuICBsZXQgbGlzdCA9IFtdO1xuXG4gIGZvciAobGV0IGtleSBvZiBtYXBfa2V5cykge1xuICAgIGxpc3QucHVzaChuZXcgVHVwbGUoa2V5LCBtYXBba2V5XSkpO1xuICB9XG5cbiAgcmV0dXJuIExpc3QkMSguLi5saXN0KTtcbn1cblxuZnVuY3Rpb24gdmFsdWVzKG1hcCkge1xuICBsZXQgbWFwX2tleXMgPSBrZXlzKG1hcCk7XG4gIGxldCBsaXN0ID0gW107XG5cbiAgZm9yIChsZXQga2V5IG9mIG1hcF9rZXlzKSB7XG4gICAgbGlzdC5wdXNoKG1hcFtrZXldKTtcbiAgfVxuXG4gIHJldHVybiBMaXN0JDEoLi4ubGlzdCk7XG59XG5cbmZ1bmN0aW9uIGZyb21fc3RydWN0KHN0cnVjdCkge1xuICBsZXQgbWFwID0gT2JqZWN0LmFzc2lnbih7fSwgc3RydWN0KTtcbiAgZGVsZXRlIG1hcFtTeW1ib2wuZm9yKCdfX3N0cnVjdF9fJyldO1xuXG4gIHJldHVybiBTcGVjaWFsRm9ybXMkMS5tYXAobWFwKTtcbn1cblxuZnVuY3Rpb24gX19kZWxldGVfXyhtYXAsIGtleSkge1xuICBsZXQgbmV3X21hcCA9IE9iamVjdC5hc3NpZ24oe30sIG1hcCk7XG5cbiAgZGVsZXRlIG5ld19tYXBba2V5XTtcblxuICByZXR1cm4gU3BlY2lhbEZvcm1zJDEubWFwKG5ld19tYXApO1xufVxuXG5mdW5jdGlvbiBlcXVhbF9fcW1hcmtfXyhtYXAxLCBtYXAyKSB7XG4gIHJldHVybiBtYXAxID09PSBtYXAyO1xufVxuXG5mdW5jdGlvbiBmZXRjaF9fZW1hcmtfXyhtYXAsIGtleSkge1xuICBpZiAoa2V5IGluIG1hcCkge1xuICAgIHJldHVybiBtYXBba2V5XTtcbiAgfVxuXG4gIHRocm93IG5ldyBFcnJvcignS2V5IG5vdCBmb3VuZC4nKTtcbn1cblxuZnVuY3Rpb24gZmV0Y2gobWFwLCBrZXkpIHtcbiAgaWYgKGtleSBpbiBtYXApIHtcbiAgICByZXR1cm4gbmV3IFR1cGxlKFN5bWJvbC5mb3IoJ29rJyksIG1hcFtrZXldKTtcbiAgfVxuXG4gIHJldHVybiBTeW1ib2wuZm9yKCdlcnJvcicpO1xufVxuXG5mdW5jdGlvbiBoYXNfa2V5X19xbWFya19fKG1hcCwga2V5KSB7XG4gIHJldHVybiBrZXkgaW4gbWFwO1xufVxuXG5mdW5jdGlvbiBzcGxpdChtYXAsIGtleXMpIHtcbiAgbGV0IHNwbGl0MSA9IHt9O1xuICBsZXQgc3BsaXQyID0ge307XG5cbiAgZm9yIChsZXQga2V5IG9mIEZ1bmN0aW9ucy5nZXRfb2JqZWN0X2tleXMobWFwKSkge1xuICAgIGlmIChrZXlzLmluZGV4T2Yoa2V5KSA+IC0xKSB7XG4gICAgICBzcGxpdDFba2V5XSA9IG1hcFtrZXldO1xuICAgIH0gZWxzZSB7XG4gICAgICBzcGxpdDJba2V5XSA9IG1hcFtrZXldO1xuICAgIH1cbiAgfVxuXG4gIHJldHVybiBuZXcgVHVwbGUoU3BlY2lhbEZvcm1zJDEubWFwKHNwbGl0MSksIFNwZWNpYWxGb3JtcyQxLm1hcChzcGxpdDIpKTtcbn1cblxuZnVuY3Rpb24gdGFrZShtYXAsIGtleXMpIHtcbiAgbGV0IHNwbGl0MSA9IHt9O1xuXG4gIGZvciAobGV0IGtleSBvZiBGdW5jdGlvbnMuZ2V0X29iamVjdF9rZXlzKG1hcCkpIHtcbiAgICBpZiAoa2V5cy5pbmRleE9mKGtleSkgPiAtMSkge1xuICAgICAgc3BsaXQxW2tleV0gPSBtYXBba2V5XTtcbiAgICB9XG4gIH1cblxuICByZXR1cm4gU3BlY2lhbEZvcm1zJDEubWFwKHNwbGl0MSk7XG59XG5cbmZ1bmN0aW9uIGRyb3AobWFwLCBrZXlzKSB7XG4gIGxldCBzcGxpdDEgPSB7fTtcblxuICBmb3IgKGxldCBrZXkgb2YgRnVuY3Rpb25zLmdldF9vYmplY3Rfa2V5cyhtYXApKSB7XG4gICAgaWYgKGtleXMuaW5kZXhPZihrZXkpID09PSAtMSkge1xuICAgICAgc3BsaXQxW2tleV0gPSBtYXBba2V5XTtcbiAgICB9XG4gIH1cblxuICByZXR1cm4gU3BlY2lhbEZvcm1zJDEubWFwKHNwbGl0MSk7XG59XG5cbmZ1bmN0aW9uIHB1dF9uZXcobWFwLCBrZXksIHZhbHVlKSB7XG4gIGlmIChrZXkgaW4gbWFwKSB7XG4gICAgcmV0dXJuIG1hcDtcbiAgfVxuXG4gIGxldCBuZXdfbWFwID0gT2JqZWN0LmFzc2lnbih7fSwgbWFwKTtcbiAgbmV3X21hcFtrZXldID0gdmFsdWU7XG5cbiAgcmV0dXJuIFNwZWNpYWxGb3JtcyQxLm1hcChuZXdfbWFwKTtcbn1cblxuZnVuY3Rpb24gcHV0X25ld19sYXp5KG1hcCwga2V5LCBmdW4pIHtcbiAgaWYgKGtleSBpbiBtYXApIHtcbiAgICByZXR1cm4gbWFwO1xuICB9XG5cbiAgbGV0IG5ld19tYXAgPSBPYmplY3QuYXNzaWduKHt9LCBtYXApO1xuICBuZXdfbWFwW2tleV0gPSBmdW4oKTtcblxuICByZXR1cm4gU3BlY2lhbEZvcm1zJDEubWFwKG5ld19tYXApO1xufVxuXG5mdW5jdGlvbiBnZXRfYW5kX3VwZGF0ZShtYXAsIGtleSwgZnVuKSB7XG4gIGlmIChrZXkgaW4gbWFwKSB7XG4gICAgcmV0dXJuIG1hcDtcbiAgfVxuXG4gIGxldCBuZXdfbWFwID0gT2JqZWN0LmFzc2lnbih7fSwgbWFwKTtcbiAgbmV3X21hcFtrZXldID0gZnVuKG1hcFtrZXldKTtcblxuICByZXR1cm4gU3BlY2lhbEZvcm1zJDEubWFwKG5ld19tYXApO1xufVxuXG5mdW5jdGlvbiBwb3BfbGF6eShtYXAsIGtleSwgZnVuKSB7XG4gIGlmICgha2V5IGluIG1hcCkge1xuICAgIHJldHVybiBuZXcgVHVwbGUoZnVuKCksIG1hcCk7XG4gIH1cblxuICBsZXQgbmV3X21hcCA9IE9iamVjdC5hc3NpZ24oe30sIG1hcCk7XG4gIGxldCB2YWx1ZSA9IGZ1bihuZXdfbWFwW2tleV0pO1xuICBkZWxldGUgbmV3X21hcFtrZXldO1xuXG4gIHJldHVybiBuZXcgVHVwbGUodmFsdWUsIG5ld19tYXApO1xufVxuXG5mdW5jdGlvbiBwb3AobWFwLCBrZXksIF9kZWZhdWx0ID0gbnVsbCkge1xuICBpZiAoIWtleSBpbiBtYXApIHtcbiAgICByZXR1cm4gbmV3IFR1cGxlKF9kZWZhdWx0LCBtYXApO1xuICB9XG5cbiAgbGV0IG5ld19tYXAgPSBPYmplY3QuYXNzaWduKHt9LCBtYXApO1xuICBsZXQgdmFsdWUgPSBuZXdfbWFwW2tleV07XG4gIGRlbGV0ZSBuZXdfbWFwW2tleV07XG5cbiAgcmV0dXJuIG5ldyBUdXBsZSh2YWx1ZSwgbmV3X21hcCk7XG59XG5cbmZ1bmN0aW9uIGdldF9sYXp5KG1hcCwga2V5LCBmdW4pIHtcbiAgaWYgKCFrZXkgaW4gbWFwKSB7XG4gICAgcmV0dXJuIGZ1bigpO1xuICB9XG5cbiAgcmV0dXJuIGZ1bihtYXBba2V5XSk7XG59XG5cbmZ1bmN0aW9uIGdldChtYXAsIGtleSwgX2RlZmF1bHQgPSBudWxsKSB7XG4gIGlmICgha2V5IGluIG1hcCkge1xuICAgIHJldHVybiBfZGVmYXVsdDtcbiAgfVxuXG4gIHJldHVybiBtYXBba2V5XTtcbn1cblxuZnVuY3Rpb24gcHV0KG1hcCwga2V5LCB2YWwpIHtcbiAgbGV0IG5ld19tYXAgPSBPYmplY3Qoe30sIG1hcCk7XG4gIG5ld19tYXBba2V5XSA9IHZhbDtcblxuICByZXR1cm4gU3BlY2lhbEZvcm1zJDEubWFwKG5ld19tYXApO1xufVxuXG5mdW5jdGlvbiB1cGRhdGVfX2VtYXJrX18obWFwLCBrZXksIGZ1bikge1xuICBpZiAoIWtleSBpbiBtYXApIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoJ0tleSBub3QgZm91bmQnKTtcbiAgfVxuXG4gIGxldCBuZXdfbWFwID0gT2JqZWN0KHt9LCBtYXApO1xuICBuZXdfbWFwW2tleV0gPSBmdW4obWFwW2tleV0pO1xuXG4gIHJldHVybiBTcGVjaWFsRm9ybXMkMS5tYXAobmV3X21hcCk7XG59XG5cbmZ1bmN0aW9uIHVwZGF0ZShtYXAsIGtleSwgaW5pdGlhbCwgZnVuKSB7XG4gIGxldCBuZXdfbWFwID0gT2JqZWN0KHt9LCBtYXApO1xuXG4gIGlmICgha2V5IGluIG1hcCkge1xuICAgIG5ld19tYXBba2V5XSA9IGluaXRpYWw7XG4gIH0gZWxzZSB7XG4gICAgbmV3X21hcFtrZXldID0gZnVuKG1hcFtrZXldKTtcbiAgfVxuXG4gIHJldHVybiBTcGVjaWFsRm9ybXMkMS5tYXAobmV3X21hcCk7XG59XG5cbnZhciBtYXAgPSB7XG4gIG5ldzogX19uZXdfXyxcbiAga2V5cyxcbiAgc2l6ZSxcbiAgdG9fbGlzdCxcbiAgdmFsdWVzLFxuICBmcm9tX3N0cnVjdCxcbiAgZGVsZXRlOiBfX2RlbGV0ZV9fLFxuICBkcm9wLFxuICBlcXVhbF9fcW1hcmtfXyxcbiAgZmV0Y2hfX2VtYXJrX18sXG4gIGZldGNoLFxuICBoYXNfa2V5X19xbWFya19fLFxuICBzcGxpdCxcbiAgdGFrZSxcbiAgcHV0X25ldyxcbiAgcHV0X25ld19sYXp5LFxuICBnZXRfYW5kX3VwZGF0ZSxcbiAgcG9wX2xhenksXG4gIHBvcCxcbiAgZ2V0X2xhenksXG4gIGdldCxcbiAgcHV0LFxuICB1cGRhdGVfX2VtYXJrX18sXG4gIHVwZGF0ZVxufTtcblxuZnVuY3Rpb24gX19uZXdfXyQxKCkge1xuICByZXR1cm4gU3BlY2lhbEZvcm1zJDEubWFwKHsgW1N5bWJvbC5mb3IoJ19fc3RydWN0X18nKV06IFN5bWJvbC5mb3IoJ01hcFNldCcpLCBzZXQ6IExpc3QkMSgpIH0pO1xufVxuXG5mdW5jdGlvbiBzaXplJDEobWFwKSB7XG4gIHJldHVybiBtYXAuc2V0Lmxlbmd0aDtcbn1cblxuZnVuY3Rpb24gdG9fbGlzdCQxKG1hcCkge1xuICByZXR1cm4gbWFwLnNldDtcbn1cblxuZnVuY3Rpb24gX19kZWxldGVfXyQxKHNldCwgdGVybSkge1xuICBsZXQgbmV3X2xpc3QgPSBMaXN0LmRlbGV0ZShzZXQuc2V0LCB0ZXJtKTtcblxuICBsZXQgbmV3X21hcCA9IE9iamVjdC5hc3NpZ24oe30sIHNldCk7XG4gIG5ld19tYXAuc2V0ID0gbmV3X2xpc3Q7XG4gIHJldHVybiBTcGVjaWFsRm9ybXMkMS5tYXAobmV3X21hcCk7XG59XG5cbmZ1bmN0aW9uIHB1dCQxKHNldCwgdGVybSkge1xuICBpZiAoc2V0LnNldC5pbmRleE9mKHRlcm0pID09PSAtMSkge1xuICAgIGxldCBuZXdfbGlzdCA9IExpc3QuYXBwZW5kKHNldC5zZXQsIHRlcm0pO1xuXG4gICAgbGV0IG5ld19tYXAgPSBPYmplY3QuYXNzaWduKHt9LCBzZXQpO1xuICAgIG5ld19tYXAuc2V0ID0gbmV3X2xpc3Q7XG4gICAgcmV0dXJuIFNwZWNpYWxGb3JtcyQxLm1hcChuZXdfbWFwKTtcbiAgfVxuXG4gIHJldHVybiBzZXQ7XG59XG5cbmZ1bmN0aW9uIGRpZmZlcmVuY2Uoc2V0MSwgc2V0Mikge1xuICBsZXQgbmV3X21hcCA9IE9iamVjdC5hc3NpZ24oe30sIHNldDEpO1xuXG4gIGZvciAobGV0IHZhbCBvZiBzZXQxLnNldCkge1xuICAgIGlmIChtZW1iZXJfX3FtYXJrX18oc2V0MiwgdmFsKSkge1xuICAgICAgbmV3X21hcC5zZXQgPSBMaXN0LmRlbGV0ZShuZXdfbWFwLnNldCwgdmFsKTtcbiAgICB9XG4gIH1cblxuICByZXR1cm4gU3BlY2lhbEZvcm1zJDEubWFwKG5ld19tYXApO1xufVxuXG5mdW5jdGlvbiBpbnRlcnNlY3Rpb24oc2V0MSwgc2V0Mikge1xuICBsZXQgbmV3X21hcCA9IE9iamVjdC5hc3NpZ24oe30sIHNldDEpO1xuXG4gIGZvciAobGV0IHZhbCBvZiBzZXQxLnNldCkge1xuICAgIGlmICghbWVtYmVyX19xbWFya19fKHNldDIsIHZhbCkpIHtcbiAgICAgIG5ld19tYXAuc2V0ID0gTGlzdC5kZWxldGUobmV3X21hcC5zZXQsIHZhbCk7XG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIFNwZWNpYWxGb3JtcyQxLm1hcChuZXdfbWFwKTtcbn1cblxuZnVuY3Rpb24gdW5pb24oc2V0MSwgc2V0Mikge1xuICBsZXQgbmV3X21hcCA9IHNldDE7XG5cbiAgZm9yIChsZXQgdmFsIG9mIHNldDIuc2V0KSB7XG4gICAgbmV3X21hcCA9IHB1dCQxKG5ld19tYXAsIHZhbCk7XG4gIH1cblxuICByZXR1cm4gU3BlY2lhbEZvcm1zJDEubWFwKG5ld19tYXApO1xufVxuXG5mdW5jdGlvbiBkaXNqb2luX19xbWFya19fKHNldDEsIHNldDIpIHtcbiAgZm9yIChsZXQgdmFsIG9mIHNldDEuc2V0KSB7XG4gICAgaWYgKG1lbWJlcl9fcW1hcmtfXyhzZXQyLCB2YWwpKSB7XG4gICAgICByZXR1cm4gZmFsc2U7XG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIHRydWU7XG59XG5cbmZ1bmN0aW9uIG1lbWJlcl9fcW1hcmtfXyhzZXQsIHZhbHVlKSB7XG4gIHJldHVybiBzZXQuc2V0LmluZGV4T2YodmFsdWUpID49IDA7XG59XG5cbmZ1bmN0aW9uIGVxdWFsX19xbWFya19fJDEoc2V0MSwgc2V0Mikge1xuICByZXR1cm4gc2V0MS5zZXQgPT09IHNldDIuc2V0O1xufVxuXG5mdW5jdGlvbiBzdWJzZXRfX3FtYXJrX18oc2V0MSwgc2V0Mikge1xuICBmb3IgKGxldCB2YWwgb2Ygc2V0MS5zZXQpIHtcbiAgICBpZiAoIW1lbWJlcl9fcW1hcmtfXyhzZXQyLCB2YWwpKSB7XG4gICAgICByZXR1cm4gZmFsc2U7XG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIHRydWU7XG59XG5cbnZhciBtYXBfc2V0ID0ge1xuICBuZXc6IF9fbmV3X18kMSxcbiAgc2l6ZTogc2l6ZSQxLFxuICB0b19saXN0OiB0b19saXN0JDEsXG4gIGRpc2pvaW5fX3FtYXJrX18sXG4gIGRlbGV0ZTogX19kZWxldGVfXyQxLFxuICBzdWJzZXRfX3FtYXJrX18sXG4gIGVxdWFsX19xbWFya19fOiBlcXVhbF9fcW1hcmtfXyQxLFxuICBtZW1iZXJfX3FtYXJrX18sXG4gIHB1dDogcHV0JDEsXG4gIHVuaW9uLFxuICBpbnRlcnNlY3Rpb24sXG4gIGRpZmZlcmVuY2Vcbn07XG5cbmxldCBWaXJ0dWFsRE9NID0gKGZ1bmN0aW9uIChlKSB7XG4gICAgcmV0dXJuIGUoKTtcbn0pKGZ1bmN0aW9uICgpIHtcbiAgICB2YXIgZGVmaW5lLCBtb2R1bGUsIGV4cG9ydHM7XG4gICAgcmV0dXJuIChmdW5jdGlvbiBlKHQsIG4sIHIpIHtcbiAgICAgICAgZnVuY3Rpb24gcyhvLCB1KSB7XG4gICAgICAgICAgICBpZiAoIW5bb10pIHtcbiAgICAgICAgICAgICAgICBpZiAoIXRbb10pIHtcbiAgICAgICAgICAgICAgICAgICAgdmFyIGEgPSB0eXBlb2YgcmVxdWlyZSA9PSBcImZ1bmN0aW9uXCIgJiYgcmVxdWlyZTtcbiAgICAgICAgICAgICAgICAgICAgaWYgKCF1ICYmIGEpIHJldHVybiBhKG8sICEwKTtcbiAgICAgICAgICAgICAgICAgICAgaWYgKGkpIHJldHVybiBpKG8sICEwKTtcbiAgICAgICAgICAgICAgICAgICAgdmFyIGYgPSBuZXcgRXJyb3IoXCJDYW5ub3QgZmluZCBtb2R1bGUgJ1wiICsgbyArIFwiJ1wiKTtcbiAgICAgICAgICAgICAgICAgICAgdGhyb3cgKGYuY29kZSA9IFwiTU9EVUxFX05PVF9GT1VORFwiLCBmKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgdmFyIGwgPSBuW29dID0ge1xuICAgICAgICAgICAgICAgICAgICBleHBvcnRzOiB7fVxuICAgICAgICAgICAgICAgIH07XG4gICAgICAgICAgICAgICAgdFtvXVswXS5jYWxsKGwuZXhwb3J0cywgZnVuY3Rpb24gKGUpIHtcbiAgICAgICAgICAgICAgICAgICAgdmFyIG4gPSB0W29dWzFdW2VdO1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gcyhuID8gbiA6IGUpO1xuICAgICAgICAgICAgICAgIH0sIGwsIGwuZXhwb3J0cywgZSwgdCwgbiwgcik7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXR1cm4gbltvXS5leHBvcnRzO1xuICAgICAgICB9XG4gICAgICAgIHZhciBpID0gdHlwZW9mIHJlcXVpcmUgPT0gXCJmdW5jdGlvblwiICYmIHJlcXVpcmU7XG4gICAgICAgIGZvciAodmFyIG8gPSAwOyBvIDwgci5sZW5ndGg7IG8rKykgcyhyW29dKTtcbiAgICAgICAgcmV0dXJuIHM7XG4gICAgfSkoe1xuICAgICAgICAxOiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge1xuXG4gICAgICAgICAgICB2YXIgY3JlYXRlRWxlbWVudCA9IHJlcXVpcmUoXCIuL3Zkb20vY3JlYXRlLWVsZW1lbnQuanNcIik7XG5cbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gY3JlYXRlRWxlbWVudDtcbiAgICAgICAgfSwgeyBcIi4vdmRvbS9jcmVhdGUtZWxlbWVudC5qc1wiOiAxNSB9XSwgMjogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHtcbiAgICAgICAgICAgIHZhciBkaWZmID0gcmVxdWlyZShcIi4vdnRyZWUvZGlmZi5qc1wiKTtcblxuICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBkaWZmO1xuICAgICAgICB9LCB7IFwiLi92dHJlZS9kaWZmLmpzXCI6IDM1IH1dLCAzOiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge1xuICAgICAgICAgICAgdmFyIGggPSByZXF1aXJlKFwiLi92aXJ0dWFsLWh5cGVyc2NyaXB0L2luZGV4LmpzXCIpO1xuXG4gICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IGg7XG4gICAgICAgIH0sIHsgXCIuL3ZpcnR1YWwtaHlwZXJzY3JpcHQvaW5kZXguanNcIjogMjIgfV0sIDQ6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICB2YXIgZGlmZiA9IHJlcXVpcmUoXCIuL2RpZmYuanNcIik7XG4gICAgICAgICAgICB2YXIgcGF0Y2ggPSByZXF1aXJlKFwiLi9wYXRjaC5qc1wiKTtcbiAgICAgICAgICAgIHZhciBoID0gcmVxdWlyZShcIi4vaC5qc1wiKTtcbiAgICAgICAgICAgIHZhciBjcmVhdGUgPSByZXF1aXJlKFwiLi9jcmVhdGUtZWxlbWVudC5qc1wiKTtcbiAgICAgICAgICAgIHZhciBWTm9kZSA9IHJlcXVpcmUoXCIuL3Zub2RlL3Zub2RlLmpzXCIpO1xuICAgICAgICAgICAgdmFyIFZUZXh0ID0gcmVxdWlyZShcIi4vdm5vZGUvdnRleHQuanNcIik7XG5cbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0ge1xuICAgICAgICAgICAgICAgIGRpZmY6IGRpZmYsXG4gICAgICAgICAgICAgICAgcGF0Y2g6IHBhdGNoLFxuICAgICAgICAgICAgICAgIGg6IGgsXG4gICAgICAgICAgICAgICAgY3JlYXRlOiBjcmVhdGUsXG4gICAgICAgICAgICAgICAgVk5vZGU6IFZOb2RlLFxuICAgICAgICAgICAgICAgIFZUZXh0OiBWVGV4dFxuICAgICAgICAgICAgfTtcbiAgICAgICAgfSwgeyBcIi4vY3JlYXRlLWVsZW1lbnQuanNcIjogMSwgXCIuL2RpZmYuanNcIjogMiwgXCIuL2guanNcIjogMywgXCIuL3BhdGNoLmpzXCI6IDEzLCBcIi4vdm5vZGUvdm5vZGUuanNcIjogMzEsIFwiLi92bm9kZS92dGV4dC5qc1wiOiAzMyB9XSwgNTogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHtcbiAgICAgICAgICAgIC8qIVxuICAgICAgICAgICAgICogQ3Jvc3MtQnJvd3NlciBTcGxpdCAxLjEuMVxuICAgICAgICAgICAgICogQ29weXJpZ2h0IDIwMDctMjAxMiBTdGV2ZW4gTGV2aXRoYW4gPHN0ZXZlbmxldml0aGFuLmNvbT5cbiAgICAgICAgICAgICAqIEF2YWlsYWJsZSB1bmRlciB0aGUgTUlUIExpY2Vuc2VcbiAgICAgICAgICAgICAqIEVDTUFTY3JpcHQgY29tcGxpYW50LCB1bmlmb3JtIGNyb3NzLWJyb3dzZXIgc3BsaXQgbWV0aG9kXG4gICAgICAgICAgICAgKi9cblxuICAgICAgICAgICAgLyoqXG4gICAgICAgICAgICAgKiBTcGxpdHMgYSBzdHJpbmcgaW50byBhbiBhcnJheSBvZiBzdHJpbmdzIHVzaW5nIGEgcmVnZXggb3Igc3RyaW5nIHNlcGFyYXRvci4gTWF0Y2hlcyBvZiB0aGVcbiAgICAgICAgICAgICAqIHNlcGFyYXRvciBhcmUgbm90IGluY2x1ZGVkIGluIHRoZSByZXN1bHQgYXJyYXkuIEhvd2V2ZXIsIGlmIGBzZXBhcmF0b3JgIGlzIGEgcmVnZXggdGhhdCBjb250YWluc1xuICAgICAgICAgICAgICogY2FwdHVyaW5nIGdyb3VwcywgYmFja3JlZmVyZW5jZXMgYXJlIHNwbGljZWQgaW50byB0aGUgcmVzdWx0IGVhY2ggdGltZSBgc2VwYXJhdG9yYCBpcyBtYXRjaGVkLlxuICAgICAgICAgICAgICogRml4ZXMgYnJvd3NlciBidWdzIGNvbXBhcmVkIHRvIHRoZSBuYXRpdmUgYFN0cmluZy5wcm90b3R5cGUuc3BsaXRgIGFuZCBjYW4gYmUgdXNlZCByZWxpYWJseVxuICAgICAgICAgICAgICogY3Jvc3MtYnJvd3Nlci5cbiAgICAgICAgICAgICAqIEBwYXJhbSB7U3RyaW5nfSBzdHIgU3RyaW5nIHRvIHNwbGl0LlxuICAgICAgICAgICAgICogQHBhcmFtIHtSZWdFeHB8U3RyaW5nfSBzZXBhcmF0b3IgUmVnZXggb3Igc3RyaW5nIHRvIHVzZSBmb3Igc2VwYXJhdGluZyB0aGUgc3RyaW5nLlxuICAgICAgICAgICAgICogQHBhcmFtIHtOdW1iZXJ9IFtsaW1pdF0gTWF4aW11bSBudW1iZXIgb2YgaXRlbXMgdG8gaW5jbHVkZSBpbiB0aGUgcmVzdWx0IGFycmF5LlxuICAgICAgICAgICAgICogQHJldHVybnMge0FycmF5fSBBcnJheSBvZiBzdWJzdHJpbmdzLlxuICAgICAgICAgICAgICogQGV4YW1wbGVcbiAgICAgICAgICAgICAqXG4gICAgICAgICAgICAgKiAvLyBCYXNpYyB1c2VcbiAgICAgICAgICAgICAqIHNwbGl0KCdhIGIgYyBkJywgJyAnKTtcbiAgICAgICAgICAgICAqIC8vIC0+IFsnYScsICdiJywgJ2MnLCAnZCddXG4gICAgICAgICAgICAgKlxuICAgICAgICAgICAgICogLy8gV2l0aCBsaW1pdFxuICAgICAgICAgICAgICogc3BsaXQoJ2EgYiBjIGQnLCAnICcsIDIpO1xuICAgICAgICAgICAgICogLy8gLT4gWydhJywgJ2InXVxuICAgICAgICAgICAgICpcbiAgICAgICAgICAgICAqIC8vIEJhY2tyZWZlcmVuY2VzIGluIHJlc3VsdCBhcnJheVxuICAgICAgICAgICAgICogc3BsaXQoJy4ud29yZDEgd29yZDIuLicsIC8oW2Etel0rKShcXGQrKS9pKTtcbiAgICAgICAgICAgICAqIC8vIC0+IFsnLi4nLCAnd29yZCcsICcxJywgJyAnLCAnd29yZCcsICcyJywgJy4uJ11cbiAgICAgICAgICAgICAqL1xuICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSAoZnVuY3Rpb24gc3BsaXQodW5kZWYpIHtcblxuICAgICAgICAgICAgICAgIHZhciBuYXRpdmVTcGxpdCA9IFN0cmluZy5wcm90b3R5cGUuc3BsaXQsXG4gICAgICAgICAgICAgICAgICAgIGNvbXBsaWFudEV4ZWNOcGNnID0gLygpPz8vLmV4ZWMoXCJcIilbMV0gPT09IHVuZGVmLFxuXG4gICAgICAgICAgICAgICAgLy8gTlBDRzogbm9ucGFydGljaXBhdGluZyBjYXB0dXJpbmcgZ3JvdXBcbiAgICAgICAgICAgICAgICBzZWxmO1xuXG4gICAgICAgICAgICAgICAgc2VsZiA9IGZ1bmN0aW9uIChzdHIsIHNlcGFyYXRvciwgbGltaXQpIHtcbiAgICAgICAgICAgICAgICAgICAgLy8gSWYgYHNlcGFyYXRvcmAgaXMgbm90IGEgcmVnZXgsIHVzZSBgbmF0aXZlU3BsaXRgXG4gICAgICAgICAgICAgICAgICAgIGlmIChPYmplY3QucHJvdG90eXBlLnRvU3RyaW5nLmNhbGwoc2VwYXJhdG9yKSAhPT0gXCJbb2JqZWN0IFJlZ0V4cF1cIikge1xuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIG5hdGl2ZVNwbGl0LmNhbGwoc3RyLCBzZXBhcmF0b3IsIGxpbWl0KTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB2YXIgb3V0cHV0ID0gW10sXG4gICAgICAgICAgICAgICAgICAgICAgICBmbGFncyA9IChzZXBhcmF0b3IuaWdub3JlQ2FzZSA/IFwiaVwiIDogXCJcIikgKyAoc2VwYXJhdG9yLm11bHRpbGluZSA/IFwibVwiIDogXCJcIikgKyAoc2VwYXJhdG9yLmV4dGVuZGVkID8gXCJ4XCIgOiBcIlwiKSArIChzZXBhcmF0b3Iuc3RpY2t5ID8gXCJ5XCIgOiBcIlwiKSxcblxuICAgICAgICAgICAgICAgICAgICAvLyBGaXJlZm94IDMrXG4gICAgICAgICAgICAgICAgICAgIGxhc3RMYXN0SW5kZXggPSAwLFxuXG4gICAgICAgICAgICAgICAgICAgIC8vIE1ha2UgYGdsb2JhbGAgYW5kIGF2b2lkIGBsYXN0SW5kZXhgIGlzc3VlcyBieSB3b3JraW5nIHdpdGggYSBjb3B5XG4gICAgICAgICAgICAgICAgICAgIHNlcGFyYXRvciA9IG5ldyBSZWdFeHAoc2VwYXJhdG9yLnNvdXJjZSwgZmxhZ3MgKyBcImdcIiksXG4gICAgICAgICAgICAgICAgICAgICAgICBzZXBhcmF0b3IyLFxuICAgICAgICAgICAgICAgICAgICAgICAgbWF0Y2gsXG4gICAgICAgICAgICAgICAgICAgICAgICBsYXN0SW5kZXgsXG4gICAgICAgICAgICAgICAgICAgICAgICBsYXN0TGVuZ3RoO1xuICAgICAgICAgICAgICAgICAgICBzdHIgKz0gXCJcIjsgLy8gVHlwZS1jb252ZXJ0XG4gICAgICAgICAgICAgICAgICAgIGlmICghY29tcGxpYW50RXhlY05wY2cpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIERvZXNuJ3QgbmVlZCBmbGFncyBneSwgYnV0IHRoZXkgZG9uJ3QgaHVydFxuICAgICAgICAgICAgICAgICAgICAgICAgc2VwYXJhdG9yMiA9IG5ldyBSZWdFeHAoXCJeXCIgKyBzZXBhcmF0b3Iuc291cmNlICsgXCIkKD8hXFxcXHMpXCIsIGZsYWdzKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAvKiBWYWx1ZXMgZm9yIGBsaW1pdGAsIHBlciB0aGUgc3BlYzpcbiAgICAgICAgICAgICAgICAgICAgICogSWYgdW5kZWZpbmVkOiA0Mjk0OTY3Mjk1IC8vIE1hdGgucG93KDIsIDMyKSAtIDFcbiAgICAgICAgICAgICAgICAgICAgICogSWYgMCwgSW5maW5pdHksIG9yIE5hTjogMFxuICAgICAgICAgICAgICAgICAgICAgKiBJZiBwb3NpdGl2ZSBudW1iZXI6IGxpbWl0ID0gTWF0aC5mbG9vcihsaW1pdCk7IGlmIChsaW1pdCA+IDQyOTQ5NjcyOTUpIGxpbWl0IC09IDQyOTQ5NjcyOTY7XG4gICAgICAgICAgICAgICAgICAgICAqIElmIG5lZ2F0aXZlIG51bWJlcjogNDI5NDk2NzI5NiAtIE1hdGguZmxvb3IoTWF0aC5hYnMobGltaXQpKVxuICAgICAgICAgICAgICAgICAgICAgKiBJZiBvdGhlcjogVHlwZS1jb252ZXJ0LCB0aGVuIHVzZSB0aGUgYWJvdmUgcnVsZXNcbiAgICAgICAgICAgICAgICAgICAgICovXG4gICAgICAgICAgICAgICAgICAgIGxpbWl0ID0gbGltaXQgPT09IHVuZGVmID8gLTEgPj4+IDAgOiAvLyBNYXRoLnBvdygyLCAzMikgLSAxXG4gICAgICAgICAgICAgICAgICAgIGxpbWl0ID4+PiAwOyAvLyBUb1VpbnQzMihsaW1pdClcbiAgICAgICAgICAgICAgICAgICAgd2hpbGUgKG1hdGNoID0gc2VwYXJhdG9yLmV4ZWMoc3RyKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgLy8gYHNlcGFyYXRvci5sYXN0SW5kZXhgIGlzIG5vdCByZWxpYWJsZSBjcm9zcy1icm93c2VyXG4gICAgICAgICAgICAgICAgICAgICAgICBsYXN0SW5kZXggPSBtYXRjaC5pbmRleCArIG1hdGNoWzBdLmxlbmd0aDtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChsYXN0SW5kZXggPiBsYXN0TGFzdEluZGV4KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgb3V0cHV0LnB1c2goc3RyLnNsaWNlKGxhc3RMYXN0SW5kZXgsIG1hdGNoLmluZGV4KSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gRml4IGJyb3dzZXJzIHdob3NlIGBleGVjYCBtZXRob2RzIGRvbid0IGNvbnNpc3RlbnRseSByZXR1cm4gYHVuZGVmaW5lZGAgZm9yXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gbm9ucGFydGljaXBhdGluZyBjYXB0dXJpbmcgZ3JvdXBzXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKCFjb21wbGlhbnRFeGVjTnBjZyAmJiBtYXRjaC5sZW5ndGggPiAxKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1hdGNoWzBdLnJlcGxhY2Uoc2VwYXJhdG9yMiwgZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZm9yICh2YXIgaSA9IDE7IGkgPCBhcmd1bWVudHMubGVuZ3RoIC0gMjsgaSsrKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGFyZ3VtZW50c1tpXSA9PT0gdW5kZWYpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbWF0Y2hbaV0gPSB1bmRlZjtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAobWF0Y2gubGVuZ3RoID4gMSAmJiBtYXRjaC5pbmRleCA8IHN0ci5sZW5ndGgpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgQXJyYXkucHJvdG90eXBlLnB1c2guYXBwbHkob3V0cHV0LCBtYXRjaC5zbGljZSgxKSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxhc3RMZW5ndGggPSBtYXRjaFswXS5sZW5ndGg7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgbGFzdExhc3RJbmRleCA9IGxhc3RJbmRleDtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAob3V0cHV0Lmxlbmd0aCA+PSBsaW1pdCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoc2VwYXJhdG9yLmxhc3RJbmRleCA9PT0gbWF0Y2guaW5kZXgpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBzZXBhcmF0b3IubGFzdEluZGV4Kys7IC8vIEF2b2lkIGFuIGluZmluaXRlIGxvb3BcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICBpZiAobGFzdExhc3RJbmRleCA9PT0gc3RyLmxlbmd0aCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGxhc3RMZW5ndGggfHwgIXNlcGFyYXRvci50ZXN0KFwiXCIpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgb3V0cHV0LnB1c2goXCJcIik7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBvdXRwdXQucHVzaChzdHIuc2xpY2UobGFzdExhc3RJbmRleCkpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBvdXRwdXQubGVuZ3RoID4gbGltaXQgPyBvdXRwdXQuc2xpY2UoMCwgbGltaXQpIDogb3V0cHV0O1xuICAgICAgICAgICAgICAgIH07XG5cbiAgICAgICAgICAgICAgICByZXR1cm4gc2VsZjtcbiAgICAgICAgICAgIH0pKCk7XG4gICAgICAgIH0sIHt9XSwgNjogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHt9LCB7fV0sIDc6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICBcInVzZSBzdHJpY3RcIjtcblxuICAgICAgICAgICAgdmFyIE9uZVZlcnNpb25Db25zdHJhaW50ID0gcmVxdWlyZShcImluZGl2aWR1YWwvb25lLXZlcnNpb25cIik7XG5cbiAgICAgICAgICAgIHZhciBNWV9WRVJTSU9OID0gXCI3XCI7XG4gICAgICAgICAgICBPbmVWZXJzaW9uQ29uc3RyYWludChcImV2LXN0b3JlXCIsIE1ZX1ZFUlNJT04pO1xuXG4gICAgICAgICAgICB2YXIgaGFzaEtleSA9IFwiX19FVl9TVE9SRV9LRVlAXCIgKyBNWV9WRVJTSU9OO1xuXG4gICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IEV2U3RvcmU7XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIEV2U3RvcmUoZWxlbSkge1xuICAgICAgICAgICAgICAgIHZhciBoYXNoID0gZWxlbVtoYXNoS2V5XTtcblxuICAgICAgICAgICAgICAgIGlmICghaGFzaCkge1xuICAgICAgICAgICAgICAgICAgICBoYXNoID0gZWxlbVtoYXNoS2V5XSA9IHt9O1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHJldHVybiBoYXNoO1xuICAgICAgICAgICAgfVxuICAgICAgICB9LCB7IFwiaW5kaXZpZHVhbC9vbmUtdmVyc2lvblwiOiA5IH1dLCA4OiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge1xuICAgICAgICAgICAgKGZ1bmN0aW9uIChnbG9iYWwpIHtcbiAgICAgICAgICAgICAgICBcInVzZSBzdHJpY3RcIjtcblxuICAgICAgICAgICAgICAgIC8qZ2xvYmFsIHdpbmRvdywgZ2xvYmFsKi9cblxuICAgICAgICAgICAgICAgIHZhciByb290ID0gdHlwZW9mIHdpbmRvdyAhPT0gXCJ1bmRlZmluZWRcIiA/IHdpbmRvdyA6IHR5cGVvZiBnbG9iYWwgIT09IFwidW5kZWZpbmVkXCIgPyBnbG9iYWwgOiB7fTtcblxuICAgICAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gSW5kaXZpZHVhbDtcblxuICAgICAgICAgICAgICAgIGZ1bmN0aW9uIEluZGl2aWR1YWwoa2V5LCB2YWx1ZSkge1xuICAgICAgICAgICAgICAgICAgICBpZiAoa2V5IGluIHJvb3QpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiByb290W2tleV07XG4gICAgICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgICAgICByb290W2tleV0gPSB2YWx1ZTtcblxuICAgICAgICAgICAgICAgICAgICByZXR1cm4gdmFsdWU7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSkuY2FsbCh0aGlzLCB0eXBlb2YgZ2xvYmFsICE9PSBcInVuZGVmaW5lZFwiID8gZ2xvYmFsIDogdHlwZW9mIHNlbGYgIT09IFwidW5kZWZpbmVkXCIgPyBzZWxmIDogdHlwZW9mIHdpbmRvdyAhPT0gXCJ1bmRlZmluZWRcIiA/IHdpbmRvdyA6IHt9KTtcbiAgICAgICAgfSwge31dLCA5OiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge1xuICAgICAgICAgICAgXCJ1c2Ugc3RyaWN0XCI7XG5cbiAgICAgICAgICAgIHZhciBJbmRpdmlkdWFsID0gcmVxdWlyZShcIi4vaW5kZXguanNcIik7XG5cbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gT25lVmVyc2lvbjtcblxuICAgICAgICAgICAgZnVuY3Rpb24gT25lVmVyc2lvbihtb2R1bGVOYW1lLCB2ZXJzaW9uLCBkZWZhdWx0VmFsdWUpIHtcbiAgICAgICAgICAgICAgICB2YXIga2V5ID0gXCJfX0lORElWSURVQUxfT05FX1ZFUlNJT05fXCIgKyBtb2R1bGVOYW1lO1xuICAgICAgICAgICAgICAgIHZhciBlbmZvcmNlS2V5ID0ga2V5ICsgXCJfRU5GT1JDRV9TSU5HTEVUT05cIjtcblxuICAgICAgICAgICAgICAgIHZhciB2ZXJzaW9uVmFsdWUgPSBJbmRpdmlkdWFsKGVuZm9yY2VLZXksIHZlcnNpb24pO1xuXG4gICAgICAgICAgICAgICAgaWYgKHZlcnNpb25WYWx1ZSAhPT0gdmVyc2lvbikge1xuICAgICAgICAgICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoXCJDYW4gb25seSBoYXZlIG9uZSBjb3B5IG9mIFwiICsgbW9kdWxlTmFtZSArIFwiLlxcblwiICsgXCJZb3UgYWxyZWFkeSBoYXZlIHZlcnNpb24gXCIgKyB2ZXJzaW9uVmFsdWUgKyBcIiBpbnN0YWxsZWQuXFxuXCIgKyBcIlRoaXMgbWVhbnMgeW91IGNhbm5vdCBpbnN0YWxsIHZlcnNpb24gXCIgKyB2ZXJzaW9uKTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICByZXR1cm4gSW5kaXZpZHVhbChrZXksIGRlZmF1bHRWYWx1ZSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0sIHsgXCIuL2luZGV4LmpzXCI6IDggfV0sIDEwOiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge1xuICAgICAgICAgICAgKGZ1bmN0aW9uIChnbG9iYWwpIHtcbiAgICAgICAgICAgICAgICB2YXIgdG9wTGV2ZWwgPSB0eXBlb2YgZ2xvYmFsICE9PSBcInVuZGVmaW5lZFwiID8gZ2xvYmFsIDogdHlwZW9mIHdpbmRvdyAhPT0gXCJ1bmRlZmluZWRcIiA/IHdpbmRvdyA6IHt9O1xuICAgICAgICAgICAgICAgIHZhciBtaW5Eb2MgPSByZXF1aXJlKFwibWluLWRvY3VtZW50XCIpO1xuXG4gICAgICAgICAgICAgICAgaWYgKHR5cGVvZiBkb2N1bWVudCAhPT0gXCJ1bmRlZmluZWRcIikge1xuICAgICAgICAgICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IGRvY3VtZW50O1xuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciBkb2NjeSA9IHRvcExldmVsW1wiX19HTE9CQUxfRE9DVU1FTlRfQ0FDSEVANFwiXTtcblxuICAgICAgICAgICAgICAgICAgICBpZiAoIWRvY2N5KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBkb2NjeSA9IHRvcExldmVsW1wiX19HTE9CQUxfRE9DVU1FTlRfQ0FDSEVANFwiXSA9IG1pbkRvYztcbiAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gZG9jY3k7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSkuY2FsbCh0aGlzLCB0eXBlb2YgZ2xvYmFsICE9PSBcInVuZGVmaW5lZFwiID8gZ2xvYmFsIDogdHlwZW9mIHNlbGYgIT09IFwidW5kZWZpbmVkXCIgPyBzZWxmIDogdHlwZW9mIHdpbmRvdyAhPT0gXCJ1bmRlZmluZWRcIiA/IHdpbmRvdyA6IHt9KTtcbiAgICAgICAgfSwgeyBcIm1pbi1kb2N1bWVudFwiOiA2IH1dLCAxMTogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHtcbiAgICAgICAgICAgIFwidXNlIHN0cmljdFwiO1xuXG4gICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uIGlzT2JqZWN0KHgpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gdHlwZW9mIHggPT09IFwib2JqZWN0XCIgJiYgeCAhPT0gbnVsbDtcbiAgICAgICAgICAgIH07XG4gICAgICAgIH0sIHt9XSwgMTI6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICB2YXIgbmF0aXZlSXNBcnJheSA9IEFycmF5LmlzQXJyYXk7XG4gICAgICAgICAgICB2YXIgdG9TdHJpbmcgPSBPYmplY3QucHJvdG90eXBlLnRvU3RyaW5nO1xuXG4gICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IG5hdGl2ZUlzQXJyYXkgfHwgaXNBcnJheTtcblxuICAgICAgICAgICAgZnVuY3Rpb24gaXNBcnJheShvYmopIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gdG9TdHJpbmcuY2FsbChvYmopID09PSBcIltvYmplY3QgQXJyYXldXCI7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0sIHt9XSwgMTM6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICB2YXIgcGF0Y2ggPSByZXF1aXJlKFwiLi92ZG9tL3BhdGNoLmpzXCIpO1xuXG4gICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IHBhdGNoO1xuICAgICAgICB9LCB7IFwiLi92ZG9tL3BhdGNoLmpzXCI6IDE4IH1dLCAxNDogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHtcbiAgICAgICAgICAgIHZhciBpc09iamVjdCA9IHJlcXVpcmUoXCJpcy1vYmplY3RcIik7XG4gICAgICAgICAgICB2YXIgaXNIb29rID0gcmVxdWlyZShcIi4uL3Zub2RlL2lzLXZob29rLmpzXCIpO1xuXG4gICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IGFwcGx5UHJvcGVydGllcztcblxuICAgICAgICAgICAgZnVuY3Rpb24gYXBwbHlQcm9wZXJ0aWVzKG5vZGUsIHByb3BzLCBwcmV2aW91cykge1xuICAgICAgICAgICAgICAgIGZvciAodmFyIHByb3BOYW1lIGluIHByb3BzKSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciBwcm9wVmFsdWUgPSBwcm9wc1twcm9wTmFtZV07XG5cbiAgICAgICAgICAgICAgICAgICAgaWYgKHByb3BWYWx1ZSA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICByZW1vdmVQcm9wZXJ0eShub2RlLCBwcm9wTmFtZSwgcHJvcFZhbHVlLCBwcmV2aW91cyk7XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoaXNIb29rKHByb3BWYWx1ZSkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJlbW92ZVByb3BlcnR5KG5vZGUsIHByb3BOYW1lLCBwcm9wVmFsdWUsIHByZXZpb3VzKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChwcm9wVmFsdWUuaG9vaykge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHByb3BWYWx1ZS5ob29rKG5vZGUsIHByb3BOYW1lLCBwcmV2aW91cyA/IHByZXZpb3VzW3Byb3BOYW1lXSA6IHVuZGVmaW5lZCk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoaXNPYmplY3QocHJvcFZhbHVlKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHBhdGNoT2JqZWN0KG5vZGUsIHByb3BzLCBwcmV2aW91cywgcHJvcE5hbWUsIHByb3BWYWx1ZSk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIG5vZGVbcHJvcE5hbWVdID0gcHJvcFZhbHVlO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBmdW5jdGlvbiByZW1vdmVQcm9wZXJ0eShub2RlLCBwcm9wTmFtZSwgcHJvcFZhbHVlLCBwcmV2aW91cykge1xuICAgICAgICAgICAgICAgIGlmIChwcmV2aW91cykge1xuICAgICAgICAgICAgICAgICAgICB2YXIgcHJldmlvdXNWYWx1ZSA9IHByZXZpb3VzW3Byb3BOYW1lXTtcblxuICAgICAgICAgICAgICAgICAgICBpZiAoIWlzSG9vayhwcmV2aW91c1ZhbHVlKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHByb3BOYW1lID09PSBcImF0dHJpYnV0ZXNcIikge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZvciAodmFyIGF0dHJOYW1lIGluIHByZXZpb3VzVmFsdWUpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbm9kZS5yZW1vdmVBdHRyaWJ1dGUoYXR0ck5hbWUpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAocHJvcE5hbWUgPT09IFwic3R5bGVcIikge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZvciAodmFyIGkgaW4gcHJldmlvdXNWYWx1ZSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBub2RlLnN0eWxlW2ldID0gXCJcIjtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKHR5cGVvZiBwcmV2aW91c1ZhbHVlID09PSBcInN0cmluZ1wiKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgbm9kZVtwcm9wTmFtZV0gPSBcIlwiO1xuICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBub2RlW3Byb3BOYW1lXSA9IG51bGw7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAocHJldmlvdXNWYWx1ZS51bmhvb2spIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHByZXZpb3VzVmFsdWUudW5ob29rKG5vZGUsIHByb3BOYW1lLCBwcm9wVmFsdWUpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBmdW5jdGlvbiBwYXRjaE9iamVjdChub2RlLCBwcm9wcywgcHJldmlvdXMsIHByb3BOYW1lLCBwcm9wVmFsdWUpIHtcbiAgICAgICAgICAgICAgICB2YXIgcHJldmlvdXNWYWx1ZSA9IHByZXZpb3VzID8gcHJldmlvdXNbcHJvcE5hbWVdIDogdW5kZWZpbmVkO1xuXG4gICAgICAgICAgICAgICAgLy8gU2V0IGF0dHJpYnV0ZXNcbiAgICAgICAgICAgICAgICBpZiAocHJvcE5hbWUgPT09IFwiYXR0cmlidXRlc1wiKSB7XG4gICAgICAgICAgICAgICAgICAgIGZvciAodmFyIGF0dHJOYW1lIGluIHByb3BWYWx1ZSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgdmFyIGF0dHJWYWx1ZSA9IHByb3BWYWx1ZVthdHRyTmFtZV07XG5cbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChhdHRyVmFsdWUgPT09IHVuZGVmaW5lZCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIG5vZGUucmVtb3ZlQXR0cmlidXRlKGF0dHJOYW1lKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgbm9kZS5zZXRBdHRyaWJ1dGUoYXR0ck5hbWUsIGF0dHJWYWx1ZSk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgaWYgKHByZXZpb3VzVmFsdWUgJiYgaXNPYmplY3QocHJldmlvdXNWYWx1ZSkgJiYgZ2V0UHJvdG90eXBlKHByZXZpb3VzVmFsdWUpICE9PSBnZXRQcm90b3R5cGUocHJvcFZhbHVlKSkge1xuICAgICAgICAgICAgICAgICAgICBub2RlW3Byb3BOYW1lXSA9IHByb3BWYWx1ZTtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIGlmICghaXNPYmplY3Qobm9kZVtwcm9wTmFtZV0pKSB7XG4gICAgICAgICAgICAgICAgICAgIG5vZGVbcHJvcE5hbWVdID0ge307XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgdmFyIHJlcGxhY2VyID0gcHJvcE5hbWUgPT09IFwic3R5bGVcIiA/IFwiXCIgOiB1bmRlZmluZWQ7XG5cbiAgICAgICAgICAgICAgICBmb3IgKHZhciBrIGluIHByb3BWYWx1ZSkge1xuICAgICAgICAgICAgICAgICAgICB2YXIgdmFsdWUgPSBwcm9wVmFsdWVba107XG4gICAgICAgICAgICAgICAgICAgIG5vZGVbcHJvcE5hbWVdW2tdID0gdmFsdWUgPT09IHVuZGVmaW5lZCA/IHJlcGxhY2VyIDogdmFsdWU7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBmdW5jdGlvbiBnZXRQcm90b3R5cGUodmFsdWUpIHtcbiAgICAgICAgICAgICAgICBpZiAoT2JqZWN0LmdldFByb3RvdHlwZU9mKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBPYmplY3QuZ2V0UHJvdG90eXBlT2YodmFsdWUpO1xuICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAodmFsdWUuX19wcm90b19fKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiB2YWx1ZS5fX3Byb3RvX187XG4gICAgICAgICAgICAgICAgfSBlbHNlIGlmICh2YWx1ZS5jb25zdHJ1Y3Rvcikge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gdmFsdWUuY29uc3RydWN0b3IucHJvdG90eXBlO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgfSwgeyBcIi4uL3Zub2RlL2lzLXZob29rLmpzXCI6IDI2LCBcImlzLW9iamVjdFwiOiAxMSB9XSwgMTU6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICB2YXIgZG9jdW1lbnQgPSByZXF1aXJlKFwiZ2xvYmFsL2RvY3VtZW50XCIpO1xuXG4gICAgICAgICAgICB2YXIgYXBwbHlQcm9wZXJ0aWVzID0gcmVxdWlyZShcIi4vYXBwbHktcHJvcGVydGllc1wiKTtcblxuICAgICAgICAgICAgdmFyIGlzVk5vZGUgPSByZXF1aXJlKFwiLi4vdm5vZGUvaXMtdm5vZGUuanNcIik7XG4gICAgICAgICAgICB2YXIgaXNWVGV4dCA9IHJlcXVpcmUoXCIuLi92bm9kZS9pcy12dGV4dC5qc1wiKTtcbiAgICAgICAgICAgIHZhciBpc1dpZGdldCA9IHJlcXVpcmUoXCIuLi92bm9kZS9pcy13aWRnZXQuanNcIik7XG4gICAgICAgICAgICB2YXIgaGFuZGxlVGh1bmsgPSByZXF1aXJlKFwiLi4vdm5vZGUvaGFuZGxlLXRodW5rLmpzXCIpO1xuXG4gICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IGNyZWF0ZUVsZW1lbnQ7XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIGNyZWF0ZUVsZW1lbnQodm5vZGUsIG9wdHMpIHtcbiAgICAgICAgICAgICAgICB2YXIgZG9jID0gb3B0cyA/IG9wdHMuZG9jdW1lbnQgfHwgZG9jdW1lbnQgOiBkb2N1bWVudDtcbiAgICAgICAgICAgICAgICB2YXIgd2FybiA9IG9wdHMgPyBvcHRzLndhcm4gOiBudWxsO1xuXG4gICAgICAgICAgICAgICAgdm5vZGUgPSBoYW5kbGVUaHVuayh2bm9kZSkuYTtcblxuICAgICAgICAgICAgICAgIGlmIChpc1dpZGdldCh2bm9kZSkpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHZub2RlLmluaXQoKTtcbiAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKGlzVlRleHQodm5vZGUpKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBkb2MuY3JlYXRlVGV4dE5vZGUodm5vZGUudGV4dCk7XG4gICAgICAgICAgICAgICAgfSBlbHNlIGlmICghaXNWTm9kZSh2bm9kZSkpIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKHdhcm4pIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHdhcm4oXCJJdGVtIGlzIG5vdCBhIHZhbGlkIHZpcnR1YWwgZG9tIG5vZGVcIiwgdm5vZGUpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBudWxsO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHZhciBub2RlID0gdm5vZGUubmFtZXNwYWNlID09PSBudWxsID8gZG9jLmNyZWF0ZUVsZW1lbnQodm5vZGUudGFnTmFtZSkgOiBkb2MuY3JlYXRlRWxlbWVudE5TKHZub2RlLm5hbWVzcGFjZSwgdm5vZGUudGFnTmFtZSk7XG5cbiAgICAgICAgICAgICAgICB2YXIgcHJvcHMgPSB2bm9kZS5wcm9wZXJ0aWVzO1xuICAgICAgICAgICAgICAgIGFwcGx5UHJvcGVydGllcyhub2RlLCBwcm9wcyk7XG5cbiAgICAgICAgICAgICAgICB2YXIgY2hpbGRyZW4gPSB2bm9kZS5jaGlsZHJlbjtcblxuICAgICAgICAgICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgY2hpbGRyZW4ubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgICAgICAgICAgdmFyIGNoaWxkTm9kZSA9IGNyZWF0ZUVsZW1lbnQoY2hpbGRyZW5baV0sIG9wdHMpO1xuICAgICAgICAgICAgICAgICAgICBpZiAoY2hpbGROb2RlKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBub2RlLmFwcGVuZENoaWxkKGNoaWxkTm9kZSk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICByZXR1cm4gbm9kZTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSwgeyBcIi4uL3Zub2RlL2hhbmRsZS10aHVuay5qc1wiOiAyNCwgXCIuLi92bm9kZS9pcy12bm9kZS5qc1wiOiAyNywgXCIuLi92bm9kZS9pcy12dGV4dC5qc1wiOiAyOCwgXCIuLi92bm9kZS9pcy13aWRnZXQuanNcIjogMjksIFwiLi9hcHBseS1wcm9wZXJ0aWVzXCI6IDE0LCBcImdsb2JhbC9kb2N1bWVudFwiOiAxMCB9XSwgMTY6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICAvLyBNYXBzIGEgdmlydHVhbCBET00gdHJlZSBvbnRvIGEgcmVhbCBET00gdHJlZSBpbiBhbiBlZmZpY2llbnQgbWFubmVyLlxuICAgICAgICAgICAgLy8gV2UgZG9uJ3Qgd2FudCB0byByZWFkIGFsbCBvZiB0aGUgRE9NIG5vZGVzIGluIHRoZSB0cmVlIHNvIHdlIHVzZVxuICAgICAgICAgICAgLy8gdGhlIGluLW9yZGVyIHRyZWUgaW5kZXhpbmcgdG8gZWxpbWluYXRlIHJlY3Vyc2lvbiBkb3duIGNlcnRhaW4gYnJhbmNoZXMuXG4gICAgICAgICAgICAvLyBXZSBvbmx5IHJlY3Vyc2UgaW50byBhIERPTSBub2RlIGlmIHdlIGtub3cgdGhhdCBpdCBjb250YWlucyBhIGNoaWxkIG9mXG4gICAgICAgICAgICAvLyBpbnRlcmVzdC5cblxuICAgICAgICAgICAgdmFyIG5vQ2hpbGQgPSB7fTtcblxuICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBkb21JbmRleDtcblxuICAgICAgICAgICAgZnVuY3Rpb24gZG9tSW5kZXgocm9vdE5vZGUsIHRyZWUsIGluZGljZXMsIG5vZGVzKSB7XG4gICAgICAgICAgICAgICAgaWYgKCFpbmRpY2VzIHx8IGluZGljZXMubGVuZ3RoID09PSAwKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiB7fTtcbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICBpbmRpY2VzLnNvcnQoYXNjZW5kaW5nKTtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHJlY3Vyc2Uocm9vdE5vZGUsIHRyZWUsIGluZGljZXMsIG5vZGVzLCAwKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIHJlY3Vyc2Uocm9vdE5vZGUsIHRyZWUsIGluZGljZXMsIG5vZGVzLCByb290SW5kZXgpIHtcbiAgICAgICAgICAgICAgICBub2RlcyA9IG5vZGVzIHx8IHt9O1xuXG4gICAgICAgICAgICAgICAgaWYgKHJvb3ROb2RlKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmIChpbmRleEluUmFuZ2UoaW5kaWNlcywgcm9vdEluZGV4LCByb290SW5kZXgpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBub2Rlc1tyb290SW5kZXhdID0gcm9vdE5vZGU7XG4gICAgICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgICAgICB2YXIgdkNoaWxkcmVuID0gdHJlZS5jaGlsZHJlbjtcblxuICAgICAgICAgICAgICAgICAgICBpZiAodkNoaWxkcmVuKSB7XG5cbiAgICAgICAgICAgICAgICAgICAgICAgIHZhciBjaGlsZE5vZGVzID0gcm9vdE5vZGUuY2hpbGROb2RlcztcblxuICAgICAgICAgICAgICAgICAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCB0cmVlLmNoaWxkcmVuLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcm9vdEluZGV4ICs9IDE7XG5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB2YXIgdkNoaWxkID0gdkNoaWxkcmVuW2ldIHx8IG5vQ2hpbGQ7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdmFyIG5leHRJbmRleCA9IHJvb3RJbmRleCArICh2Q2hpbGQuY291bnQgfHwgMCk7XG5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBza2lwIHJlY3Vyc2lvbiBkb3duIHRoZSB0cmVlIGlmIHRoZXJlIGFyZSBubyBub2RlcyBkb3duIGhlcmVcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoaW5kZXhJblJhbmdlKGluZGljZXMsIHJvb3RJbmRleCwgbmV4dEluZGV4KSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICByZWN1cnNlKGNoaWxkTm9kZXNbaV0sIHZDaGlsZCwgaW5kaWNlcywgbm9kZXMsIHJvb3RJbmRleCk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcm9vdEluZGV4ID0gbmV4dEluZGV4O1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgcmV0dXJuIG5vZGVzO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAvLyBCaW5hcnkgc2VhcmNoIGZvciBhbiBpbmRleCBpbiB0aGUgaW50ZXJ2YWwgW2xlZnQsIHJpZ2h0XVxuICAgICAgICAgICAgZnVuY3Rpb24gaW5kZXhJblJhbmdlKGluZGljZXMsIGxlZnQsIHJpZ2h0KSB7XG4gICAgICAgICAgICAgICAgaWYgKGluZGljZXMubGVuZ3RoID09PSAwKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICB2YXIgbWluSW5kZXggPSAwO1xuICAgICAgICAgICAgICAgIHZhciBtYXhJbmRleCA9IGluZGljZXMubGVuZ3RoIC0gMTtcbiAgICAgICAgICAgICAgICB2YXIgY3VycmVudEluZGV4O1xuICAgICAgICAgICAgICAgIHZhciBjdXJyZW50SXRlbTtcblxuICAgICAgICAgICAgICAgIHdoaWxlIChtaW5JbmRleCA8PSBtYXhJbmRleCkge1xuICAgICAgICAgICAgICAgICAgICBjdXJyZW50SW5kZXggPSAobWF4SW5kZXggKyBtaW5JbmRleCkgLyAyID4+IDA7XG4gICAgICAgICAgICAgICAgICAgIGN1cnJlbnRJdGVtID0gaW5kaWNlc1tjdXJyZW50SW5kZXhdO1xuXG4gICAgICAgICAgICAgICAgICAgIGlmIChtaW5JbmRleCA9PT0gbWF4SW5kZXgpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBjdXJyZW50SXRlbSA+PSBsZWZ0ICYmIGN1cnJlbnRJdGVtIDw9IHJpZ2h0O1xuICAgICAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKGN1cnJlbnRJdGVtIDwgbGVmdCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgbWluSW5kZXggPSBjdXJyZW50SW5kZXggKyAxO1xuICAgICAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKGN1cnJlbnRJdGVtID4gcmlnaHQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIG1heEluZGV4ID0gY3VycmVudEluZGV4IC0gMTtcbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBmdW5jdGlvbiBhc2NlbmRpbmcoYSwgYikge1xuICAgICAgICAgICAgICAgIHJldHVybiBhID4gYiA/IDEgOiAtMTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSwge31dLCAxNzogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHtcbiAgICAgICAgICAgIHZhciBhcHBseVByb3BlcnRpZXMgPSByZXF1aXJlKFwiLi9hcHBseS1wcm9wZXJ0aWVzXCIpO1xuXG4gICAgICAgICAgICB2YXIgaXNXaWRnZXQgPSByZXF1aXJlKFwiLi4vdm5vZGUvaXMtd2lkZ2V0LmpzXCIpO1xuICAgICAgICAgICAgdmFyIFZQYXRjaCA9IHJlcXVpcmUoXCIuLi92bm9kZS92cGF0Y2guanNcIik7XG5cbiAgICAgICAgICAgIHZhciB1cGRhdGVXaWRnZXQgPSByZXF1aXJlKFwiLi91cGRhdGUtd2lkZ2V0XCIpO1xuXG4gICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IGFwcGx5UGF0Y2g7XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIGFwcGx5UGF0Y2godnBhdGNoLCBkb21Ob2RlLCByZW5kZXJPcHRpb25zKSB7XG4gICAgICAgICAgICAgICAgdmFyIHR5cGUgPSB2cGF0Y2gudHlwZTtcbiAgICAgICAgICAgICAgICB2YXIgdk5vZGUgPSB2cGF0Y2gudk5vZGU7XG4gICAgICAgICAgICAgICAgdmFyIHBhdGNoID0gdnBhdGNoLnBhdGNoO1xuXG4gICAgICAgICAgICAgICAgc3dpdGNoICh0eXBlKSB7XG4gICAgICAgICAgICAgICAgICAgIGNhc2UgVlBhdGNoLlJFTU9WRTpcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiByZW1vdmVOb2RlKGRvbU5vZGUsIHZOb2RlKTtcbiAgICAgICAgICAgICAgICAgICAgY2FzZSBWUGF0Y2guSU5TRVJUOlxuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGluc2VydE5vZGUoZG9tTm9kZSwgcGF0Y2gsIHJlbmRlck9wdGlvbnMpO1xuICAgICAgICAgICAgICAgICAgICBjYXNlIFZQYXRjaC5WVEVYVDpcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBzdHJpbmdQYXRjaChkb21Ob2RlLCB2Tm9kZSwgcGF0Y2gsIHJlbmRlck9wdGlvbnMpO1xuICAgICAgICAgICAgICAgICAgICBjYXNlIFZQYXRjaC5XSURHRVQ6XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gd2lkZ2V0UGF0Y2goZG9tTm9kZSwgdk5vZGUsIHBhdGNoLCByZW5kZXJPcHRpb25zKTtcbiAgICAgICAgICAgICAgICAgICAgY2FzZSBWUGF0Y2guVk5PREU6XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gdk5vZGVQYXRjaChkb21Ob2RlLCB2Tm9kZSwgcGF0Y2gsIHJlbmRlck9wdGlvbnMpO1xuICAgICAgICAgICAgICAgICAgICBjYXNlIFZQYXRjaC5PUkRFUjpcbiAgICAgICAgICAgICAgICAgICAgICAgIHJlb3JkZXJDaGlsZHJlbihkb21Ob2RlLCBwYXRjaCk7XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gZG9tTm9kZTtcbiAgICAgICAgICAgICAgICAgICAgY2FzZSBWUGF0Y2guUFJPUFM6XG4gICAgICAgICAgICAgICAgICAgICAgICBhcHBseVByb3BlcnRpZXMoZG9tTm9kZSwgcGF0Y2gsIHZOb2RlLnByb3BlcnRpZXMpO1xuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGRvbU5vZGU7XG4gICAgICAgICAgICAgICAgICAgIGNhc2UgVlBhdGNoLlRIVU5LOlxuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHJlcGxhY2VSb290KGRvbU5vZGUsIHJlbmRlck9wdGlvbnMucGF0Y2goZG9tTm9kZSwgcGF0Y2gsIHJlbmRlck9wdGlvbnMpKTtcbiAgICAgICAgICAgICAgICAgICAgZGVmYXVsdDpcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBkb21Ob2RlO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZnVuY3Rpb24gcmVtb3ZlTm9kZShkb21Ob2RlLCB2Tm9kZSkge1xuICAgICAgICAgICAgICAgIHZhciBwYXJlbnROb2RlID0gZG9tTm9kZS5wYXJlbnROb2RlO1xuXG4gICAgICAgICAgICAgICAgaWYgKHBhcmVudE5vZGUpIHtcbiAgICAgICAgICAgICAgICAgICAgcGFyZW50Tm9kZS5yZW1vdmVDaGlsZChkb21Ob2RlKTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICBkZXN0cm95V2lkZ2V0KGRvbU5vZGUsIHZOb2RlKTtcblxuICAgICAgICAgICAgICAgIHJldHVybiBudWxsO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBmdW5jdGlvbiBpbnNlcnROb2RlKHBhcmVudE5vZGUsIHZOb2RlLCByZW5kZXJPcHRpb25zKSB7XG4gICAgICAgICAgICAgICAgdmFyIG5ld05vZGUgPSByZW5kZXJPcHRpb25zLnJlbmRlcih2Tm9kZSwgcmVuZGVyT3B0aW9ucyk7XG5cbiAgICAgICAgICAgICAgICBpZiAocGFyZW50Tm9kZSkge1xuICAgICAgICAgICAgICAgICAgICBwYXJlbnROb2RlLmFwcGVuZENoaWxkKG5ld05vZGUpO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHJldHVybiBwYXJlbnROb2RlO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBmdW5jdGlvbiBzdHJpbmdQYXRjaChkb21Ob2RlLCBsZWZ0Vk5vZGUsIHZUZXh0LCByZW5kZXJPcHRpb25zKSB7XG4gICAgICAgICAgICAgICAgdmFyIG5ld05vZGU7XG5cbiAgICAgICAgICAgICAgICBpZiAoZG9tTm9kZS5ub2RlVHlwZSA9PT0gMykge1xuICAgICAgICAgICAgICAgICAgICBkb21Ob2RlLnJlcGxhY2VEYXRhKDAsIGRvbU5vZGUubGVuZ3RoLCB2VGV4dC50ZXh0KTtcbiAgICAgICAgICAgICAgICAgICAgbmV3Tm9kZSA9IGRvbU5vZGU7XG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgdmFyIHBhcmVudE5vZGUgPSBkb21Ob2RlLnBhcmVudE5vZGU7XG4gICAgICAgICAgICAgICAgICAgIG5ld05vZGUgPSByZW5kZXJPcHRpb25zLnJlbmRlcih2VGV4dCwgcmVuZGVyT3B0aW9ucyk7XG5cbiAgICAgICAgICAgICAgICAgICAgaWYgKHBhcmVudE5vZGUgJiYgbmV3Tm9kZSAhPT0gZG9tTm9kZSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgcGFyZW50Tm9kZS5yZXBsYWNlQ2hpbGQobmV3Tm9kZSwgZG9tTm9kZSk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICByZXR1cm4gbmV3Tm9kZTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZnVuY3Rpb24gd2lkZ2V0UGF0Y2goZG9tTm9kZSwgbGVmdFZOb2RlLCB3aWRnZXQsIHJlbmRlck9wdGlvbnMpIHtcbiAgICAgICAgICAgICAgICB2YXIgdXBkYXRpbmcgPSB1cGRhdGVXaWRnZXQobGVmdFZOb2RlLCB3aWRnZXQpO1xuICAgICAgICAgICAgICAgIHZhciBuZXdOb2RlO1xuXG4gICAgICAgICAgICAgICAgaWYgKHVwZGF0aW5nKSB7XG4gICAgICAgICAgICAgICAgICAgIG5ld05vZGUgPSB3aWRnZXQudXBkYXRlKGxlZnRWTm9kZSwgZG9tTm9kZSkgfHwgZG9tTm9kZTtcbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICBuZXdOb2RlID0gcmVuZGVyT3B0aW9ucy5yZW5kZXIod2lkZ2V0LCByZW5kZXJPcHRpb25zKTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICB2YXIgcGFyZW50Tm9kZSA9IGRvbU5vZGUucGFyZW50Tm9kZTtcblxuICAgICAgICAgICAgICAgIGlmIChwYXJlbnROb2RlICYmIG5ld05vZGUgIT09IGRvbU5vZGUpIHtcbiAgICAgICAgICAgICAgICAgICAgcGFyZW50Tm9kZS5yZXBsYWNlQ2hpbGQobmV3Tm9kZSwgZG9tTm9kZSk7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgaWYgKCF1cGRhdGluZykge1xuICAgICAgICAgICAgICAgICAgICBkZXN0cm95V2lkZ2V0KGRvbU5vZGUsIGxlZnRWTm9kZSk7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgcmV0dXJuIG5ld05vZGU7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIHZOb2RlUGF0Y2goZG9tTm9kZSwgbGVmdFZOb2RlLCB2Tm9kZSwgcmVuZGVyT3B0aW9ucykge1xuICAgICAgICAgICAgICAgIHZhciBwYXJlbnROb2RlID0gZG9tTm9kZS5wYXJlbnROb2RlO1xuICAgICAgICAgICAgICAgIHZhciBuZXdOb2RlID0gcmVuZGVyT3B0aW9ucy5yZW5kZXIodk5vZGUsIHJlbmRlck9wdGlvbnMpO1xuXG4gICAgICAgICAgICAgICAgaWYgKHBhcmVudE5vZGUgJiYgbmV3Tm9kZSAhPT0gZG9tTm9kZSkge1xuICAgICAgICAgICAgICAgICAgICBwYXJlbnROb2RlLnJlcGxhY2VDaGlsZChuZXdOb2RlLCBkb21Ob2RlKTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICByZXR1cm4gbmV3Tm9kZTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZnVuY3Rpb24gZGVzdHJveVdpZGdldChkb21Ob2RlLCB3KSB7XG4gICAgICAgICAgICAgICAgaWYgKHR5cGVvZiB3LmRlc3Ryb3kgPT09IFwiZnVuY3Rpb25cIiAmJiBpc1dpZGdldCh3KSkge1xuICAgICAgICAgICAgICAgICAgICB3LmRlc3Ryb3koZG9tTm9kZSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBmdW5jdGlvbiByZW9yZGVyQ2hpbGRyZW4oZG9tTm9kZSwgbW92ZXMpIHtcbiAgICAgICAgICAgICAgICB2YXIgY2hpbGROb2RlcyA9IGRvbU5vZGUuY2hpbGROb2RlcztcbiAgICAgICAgICAgICAgICB2YXIga2V5TWFwID0ge307XG4gICAgICAgICAgICAgICAgdmFyIG5vZGU7XG4gICAgICAgICAgICAgICAgdmFyIHJlbW92ZTtcbiAgICAgICAgICAgICAgICB2YXIgaW5zZXJ0O1xuXG4gICAgICAgICAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCBtb3Zlcy5yZW1vdmVzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICAgICAgICAgIHJlbW92ZSA9IG1vdmVzLnJlbW92ZXNbaV07XG4gICAgICAgICAgICAgICAgICAgIG5vZGUgPSBjaGlsZE5vZGVzW3JlbW92ZS5mcm9tXTtcbiAgICAgICAgICAgICAgICAgICAgaWYgKHJlbW92ZS5rZXkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGtleU1hcFtyZW1vdmUua2V5XSA9IG5vZGU7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgZG9tTm9kZS5yZW1vdmVDaGlsZChub2RlKTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICB2YXIgbGVuZ3RoID0gY2hpbGROb2Rlcy5sZW5ndGg7XG4gICAgICAgICAgICAgICAgZm9yICh2YXIgaiA9IDA7IGogPCBtb3Zlcy5pbnNlcnRzLmxlbmd0aDsgaisrKSB7XG4gICAgICAgICAgICAgICAgICAgIGluc2VydCA9IG1vdmVzLmluc2VydHNbal07XG4gICAgICAgICAgICAgICAgICAgIG5vZGUgPSBrZXlNYXBbaW5zZXJ0LmtleV07XG4gICAgICAgICAgICAgICAgICAgIC8vIHRoaXMgaXMgdGhlIHdlaXJkZXN0IGJ1ZyBpJ3ZlIGV2ZXIgc2VlbiBpbiB3ZWJraXRcbiAgICAgICAgICAgICAgICAgICAgZG9tTm9kZS5pbnNlcnRCZWZvcmUobm9kZSwgaW5zZXJ0LnRvID49IGxlbmd0aCsrID8gbnVsbCA6IGNoaWxkTm9kZXNbaW5zZXJ0LnRvXSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBmdW5jdGlvbiByZXBsYWNlUm9vdChvbGRSb290LCBuZXdSb290KSB7XG4gICAgICAgICAgICAgICAgaWYgKG9sZFJvb3QgJiYgbmV3Um9vdCAmJiBvbGRSb290ICE9PSBuZXdSb290ICYmIG9sZFJvb3QucGFyZW50Tm9kZSkge1xuICAgICAgICAgICAgICAgICAgICBvbGRSb290LnBhcmVudE5vZGUucmVwbGFjZUNoaWxkKG5ld1Jvb3QsIG9sZFJvb3QpO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHJldHVybiBuZXdSb290O1xuICAgICAgICAgICAgfVxuICAgICAgICB9LCB7IFwiLi4vdm5vZGUvaXMtd2lkZ2V0LmpzXCI6IDI5LCBcIi4uL3Zub2RlL3ZwYXRjaC5qc1wiOiAzMiwgXCIuL2FwcGx5LXByb3BlcnRpZXNcIjogMTQsIFwiLi91cGRhdGUtd2lkZ2V0XCI6IDE5IH1dLCAxODogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHtcbiAgICAgICAgICAgIHZhciBkb2N1bWVudCA9IHJlcXVpcmUoXCJnbG9iYWwvZG9jdW1lbnRcIik7XG4gICAgICAgICAgICB2YXIgaXNBcnJheSA9IHJlcXVpcmUoXCJ4LWlzLWFycmF5XCIpO1xuXG4gICAgICAgICAgICB2YXIgcmVuZGVyID0gcmVxdWlyZShcIi4vY3JlYXRlLWVsZW1lbnRcIik7XG4gICAgICAgICAgICB2YXIgZG9tSW5kZXggPSByZXF1aXJlKFwiLi9kb20taW5kZXhcIik7XG4gICAgICAgICAgICB2YXIgcGF0Y2hPcCA9IHJlcXVpcmUoXCIuL3BhdGNoLW9wXCIpO1xuICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBwYXRjaDtcblxuICAgICAgICAgICAgZnVuY3Rpb24gcGF0Y2gocm9vdE5vZGUsIHBhdGNoZXMsIHJlbmRlck9wdGlvbnMpIHtcbiAgICAgICAgICAgICAgICByZW5kZXJPcHRpb25zID0gcmVuZGVyT3B0aW9ucyB8fCB7fTtcbiAgICAgICAgICAgICAgICByZW5kZXJPcHRpb25zLnBhdGNoID0gcmVuZGVyT3B0aW9ucy5wYXRjaCAmJiByZW5kZXJPcHRpb25zLnBhdGNoICE9PSBwYXRjaCA/IHJlbmRlck9wdGlvbnMucGF0Y2ggOiBwYXRjaFJlY3Vyc2l2ZTtcbiAgICAgICAgICAgICAgICByZW5kZXJPcHRpb25zLnJlbmRlciA9IHJlbmRlck9wdGlvbnMucmVuZGVyIHx8IHJlbmRlcjtcblxuICAgICAgICAgICAgICAgIHJldHVybiByZW5kZXJPcHRpb25zLnBhdGNoKHJvb3ROb2RlLCBwYXRjaGVzLCByZW5kZXJPcHRpb25zKTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZnVuY3Rpb24gcGF0Y2hSZWN1cnNpdmUocm9vdE5vZGUsIHBhdGNoZXMsIHJlbmRlck9wdGlvbnMpIHtcbiAgICAgICAgICAgICAgICB2YXIgaW5kaWNlcyA9IHBhdGNoSW5kaWNlcyhwYXRjaGVzKTtcblxuICAgICAgICAgICAgICAgIGlmIChpbmRpY2VzLmxlbmd0aCA9PT0gMCkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gcm9vdE5vZGU7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgdmFyIGluZGV4ID0gZG9tSW5kZXgocm9vdE5vZGUsIHBhdGNoZXMuYSwgaW5kaWNlcyk7XG4gICAgICAgICAgICAgICAgdmFyIG93bmVyRG9jdW1lbnQgPSByb290Tm9kZS5vd25lckRvY3VtZW50O1xuXG4gICAgICAgICAgICAgICAgaWYgKCFyZW5kZXJPcHRpb25zLmRvY3VtZW50ICYmIG93bmVyRG9jdW1lbnQgIT09IGRvY3VtZW50KSB7XG4gICAgICAgICAgICAgICAgICAgIHJlbmRlck9wdGlvbnMuZG9jdW1lbnQgPSBvd25lckRvY3VtZW50O1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgaW5kaWNlcy5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgICAgICAgICB2YXIgbm9kZUluZGV4ID0gaW5kaWNlc1tpXTtcbiAgICAgICAgICAgICAgICAgICAgcm9vdE5vZGUgPSBhcHBseVBhdGNoKHJvb3ROb2RlLCBpbmRleFtub2RlSW5kZXhdLCBwYXRjaGVzW25vZGVJbmRleF0sIHJlbmRlck9wdGlvbnMpO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHJldHVybiByb290Tm9kZTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZnVuY3Rpb24gYXBwbHlQYXRjaChyb290Tm9kZSwgZG9tTm9kZSwgcGF0Y2hMaXN0LCByZW5kZXJPcHRpb25zKSB7XG4gICAgICAgICAgICAgICAgaWYgKCFkb21Ob2RlKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiByb290Tm9kZTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICB2YXIgbmV3Tm9kZTtcblxuICAgICAgICAgICAgICAgIGlmIChpc0FycmF5KHBhdGNoTGlzdCkpIHtcbiAgICAgICAgICAgICAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCBwYXRjaExpc3QubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIG5ld05vZGUgPSBwYXRjaE9wKHBhdGNoTGlzdFtpXSwgZG9tTm9kZSwgcmVuZGVyT3B0aW9ucyk7XG5cbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChkb21Ob2RlID09PSByb290Tm9kZSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJvb3ROb2RlID0gbmV3Tm9kZTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIG5ld05vZGUgPSBwYXRjaE9wKHBhdGNoTGlzdCwgZG9tTm9kZSwgcmVuZGVyT3B0aW9ucyk7XG5cbiAgICAgICAgICAgICAgICAgICAgaWYgKGRvbU5vZGUgPT09IHJvb3ROb2RlKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICByb290Tm9kZSA9IG5ld05vZGU7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICByZXR1cm4gcm9vdE5vZGU7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIHBhdGNoSW5kaWNlcyhwYXRjaGVzKSB7XG4gICAgICAgICAgICAgICAgdmFyIGluZGljZXMgPSBbXTtcblxuICAgICAgICAgICAgICAgIGZvciAodmFyIGtleSBpbiBwYXRjaGVzKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmIChrZXkgIT09IFwiYVwiKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBpbmRpY2VzLnB1c2goTnVtYmVyKGtleSkpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgcmV0dXJuIGluZGljZXM7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0sIHsgXCIuL2NyZWF0ZS1lbGVtZW50XCI6IDE1LCBcIi4vZG9tLWluZGV4XCI6IDE2LCBcIi4vcGF0Y2gtb3BcIjogMTcsIFwiZ2xvYmFsL2RvY3VtZW50XCI6IDEwLCBcIngtaXMtYXJyYXlcIjogMTIgfV0sIDE5OiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge1xuICAgICAgICAgICAgdmFyIGlzV2lkZ2V0ID0gcmVxdWlyZShcIi4uL3Zub2RlL2lzLXdpZGdldC5qc1wiKTtcblxuICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSB1cGRhdGVXaWRnZXQ7XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIHVwZGF0ZVdpZGdldChhLCBiKSB7XG4gICAgICAgICAgICAgICAgaWYgKGlzV2lkZ2V0KGEpICYmIGlzV2lkZ2V0KGIpKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmIChcIm5hbWVcIiBpbiBhICYmIFwibmFtZVwiIGluIGIpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBhLmlkID09PSBiLmlkO1xuICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGEuaW5pdCA9PT0gYi5pbml0O1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICAgICAgfVxuICAgICAgICB9LCB7IFwiLi4vdm5vZGUvaXMtd2lkZ2V0LmpzXCI6IDI5IH1dLCAyMDogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHtcbiAgICAgICAgICAgIFwidXNlIHN0cmljdFwiO1xuXG4gICAgICAgICAgICB2YXIgRXZTdG9yZSA9IHJlcXVpcmUoXCJldi1zdG9yZVwiKTtcblxuICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBFdkhvb2s7XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIEV2SG9vayh2YWx1ZSkge1xuICAgICAgICAgICAgICAgIGlmICghKHRoaXMgaW5zdGFuY2VvZiBFdkhvb2spKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBuZXcgRXZIb29rKHZhbHVlKTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICB0aGlzLnZhbHVlID0gdmFsdWU7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIEV2SG9vay5wcm90b3R5cGUuaG9vayA9IGZ1bmN0aW9uIChub2RlLCBwcm9wZXJ0eU5hbWUpIHtcbiAgICAgICAgICAgICAgICB2YXIgZXMgPSBFdlN0b3JlKG5vZGUpO1xuICAgICAgICAgICAgICAgIHZhciBwcm9wTmFtZSA9IHByb3BlcnR5TmFtZS5zdWJzdHIoMyk7XG5cbiAgICAgICAgICAgICAgICBlc1twcm9wTmFtZV0gPSB0aGlzLnZhbHVlO1xuICAgICAgICAgICAgfTtcblxuICAgICAgICAgICAgRXZIb29rLnByb3RvdHlwZS51bmhvb2sgPSBmdW5jdGlvbiAobm9kZSwgcHJvcGVydHlOYW1lKSB7XG4gICAgICAgICAgICAgICAgdmFyIGVzID0gRXZTdG9yZShub2RlKTtcbiAgICAgICAgICAgICAgICB2YXIgcHJvcE5hbWUgPSBwcm9wZXJ0eU5hbWUuc3Vic3RyKDMpO1xuXG4gICAgICAgICAgICAgICAgZXNbcHJvcE5hbWVdID0gdW5kZWZpbmVkO1xuICAgICAgICAgICAgfTtcbiAgICAgICAgfSwgeyBcImV2LXN0b3JlXCI6IDcgfV0sIDIxOiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge1xuICAgICAgICAgICAgXCJ1c2Ugc3RyaWN0XCI7XG5cbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gU29mdFNldEhvb2s7XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIFNvZnRTZXRIb29rKHZhbHVlKSB7XG4gICAgICAgICAgICAgICAgaWYgKCEodGhpcyBpbnN0YW5jZW9mIFNvZnRTZXRIb29rKSkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gbmV3IFNvZnRTZXRIb29rKHZhbHVlKTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICB0aGlzLnZhbHVlID0gdmFsdWU7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIFNvZnRTZXRIb29rLnByb3RvdHlwZS5ob29rID0gZnVuY3Rpb24gKG5vZGUsIHByb3BlcnR5TmFtZSkge1xuICAgICAgICAgICAgICAgIGlmIChub2RlW3Byb3BlcnR5TmFtZV0gIT09IHRoaXMudmFsdWUpIHtcbiAgICAgICAgICAgICAgICAgICAgbm9kZVtwcm9wZXJ0eU5hbWVdID0gdGhpcy52YWx1ZTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9O1xuICAgICAgICB9LCB7fV0sIDIyOiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge1xuICAgICAgICAgICAgXCJ1c2Ugc3RyaWN0XCI7XG5cbiAgICAgICAgICAgIHZhciBpc0FycmF5ID0gcmVxdWlyZShcIngtaXMtYXJyYXlcIik7XG5cbiAgICAgICAgICAgIHZhciBWTm9kZSA9IHJlcXVpcmUoXCIuLi92bm9kZS92bm9kZS5qc1wiKTtcbiAgICAgICAgICAgIHZhciBWVGV4dCA9IHJlcXVpcmUoXCIuLi92bm9kZS92dGV4dC5qc1wiKTtcbiAgICAgICAgICAgIHZhciBpc1ZOb2RlID0gcmVxdWlyZShcIi4uL3Zub2RlL2lzLXZub2RlXCIpO1xuICAgICAgICAgICAgdmFyIGlzVlRleHQgPSByZXF1aXJlKFwiLi4vdm5vZGUvaXMtdnRleHRcIik7XG4gICAgICAgICAgICB2YXIgaXNXaWRnZXQgPSByZXF1aXJlKFwiLi4vdm5vZGUvaXMtd2lkZ2V0XCIpO1xuICAgICAgICAgICAgdmFyIGlzSG9vayA9IHJlcXVpcmUoXCIuLi92bm9kZS9pcy12aG9va1wiKTtcbiAgICAgICAgICAgIHZhciBpc1ZUaHVuayA9IHJlcXVpcmUoXCIuLi92bm9kZS9pcy10aHVua1wiKTtcblxuICAgICAgICAgICAgdmFyIHBhcnNlVGFnID0gcmVxdWlyZShcIi4vcGFyc2UtdGFnLmpzXCIpO1xuICAgICAgICAgICAgdmFyIHNvZnRTZXRIb29rID0gcmVxdWlyZShcIi4vaG9va3Mvc29mdC1zZXQtaG9vay5qc1wiKTtcbiAgICAgICAgICAgIHZhciBldkhvb2sgPSByZXF1aXJlKFwiLi9ob29rcy9ldi1ob29rLmpzXCIpO1xuXG4gICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IGg7XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIGgodGFnTmFtZSwgcHJvcGVydGllcywgY2hpbGRyZW4pIHtcbiAgICAgICAgICAgICAgICB2YXIgY2hpbGROb2RlcyA9IFtdO1xuICAgICAgICAgICAgICAgIHZhciB0YWcsIHByb3BzLCBrZXksIG5hbWVzcGFjZTtcblxuICAgICAgICAgICAgICAgIGlmICghY2hpbGRyZW4gJiYgaXNDaGlsZHJlbihwcm9wZXJ0aWVzKSkge1xuICAgICAgICAgICAgICAgICAgICBjaGlsZHJlbiA9IHByb3BlcnRpZXM7XG4gICAgICAgICAgICAgICAgICAgIHByb3BzID0ge307XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgcHJvcHMgPSBwcm9wcyB8fCBwcm9wZXJ0aWVzIHx8IHt9O1xuICAgICAgICAgICAgICAgIHRhZyA9IHBhcnNlVGFnKHRhZ05hbWUsIHByb3BzKTtcblxuICAgICAgICAgICAgICAgIC8vIHN1cHBvcnQga2V5c1xuICAgICAgICAgICAgICAgIGlmIChwcm9wcy5oYXNPd25Qcm9wZXJ0eShcImtleVwiKSkge1xuICAgICAgICAgICAgICAgICAgICBrZXkgPSBwcm9wcy5rZXk7XG4gICAgICAgICAgICAgICAgICAgIHByb3BzLmtleSA9IHVuZGVmaW5lZDtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAvLyBzdXBwb3J0IG5hbWVzcGFjZVxuICAgICAgICAgICAgICAgIGlmIChwcm9wcy5oYXNPd25Qcm9wZXJ0eShcIm5hbWVzcGFjZVwiKSkge1xuICAgICAgICAgICAgICAgICAgICBuYW1lc3BhY2UgPSBwcm9wcy5uYW1lc3BhY2U7XG4gICAgICAgICAgICAgICAgICAgIHByb3BzLm5hbWVzcGFjZSA9IHVuZGVmaW5lZDtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAvLyBmaXggY3Vyc29yIGJ1Z1xuICAgICAgICAgICAgICAgIGlmICh0YWcgPT09IFwiSU5QVVRcIiAmJiAhbmFtZXNwYWNlICYmIHByb3BzLmhhc093blByb3BlcnR5KFwidmFsdWVcIikgJiYgcHJvcHMudmFsdWUgIT09IHVuZGVmaW5lZCAmJiAhaXNIb29rKHByb3BzLnZhbHVlKSkge1xuICAgICAgICAgICAgICAgICAgICBwcm9wcy52YWx1ZSA9IHNvZnRTZXRIb29rKHByb3BzLnZhbHVlKTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICB0cmFuc2Zvcm1Qcm9wZXJ0aWVzKHByb3BzKTtcblxuICAgICAgICAgICAgICAgIGlmIChjaGlsZHJlbiAhPT0gdW5kZWZpbmVkICYmIGNoaWxkcmVuICE9PSBudWxsKSB7XG4gICAgICAgICAgICAgICAgICAgIGFkZENoaWxkKGNoaWxkcmVuLCBjaGlsZE5vZGVzLCB0YWcsIHByb3BzKTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICByZXR1cm4gbmV3IFZOb2RlKHRhZywgcHJvcHMsIGNoaWxkTm9kZXMsIGtleSwgbmFtZXNwYWNlKTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZnVuY3Rpb24gYWRkQ2hpbGQoYywgY2hpbGROb2RlcywgdGFnLCBwcm9wcykge1xuICAgICAgICAgICAgICAgIGlmICh0eXBlb2YgYyA9PT0gXCJzdHJpbmdcIikge1xuICAgICAgICAgICAgICAgICAgICBjaGlsZE5vZGVzLnB1c2gobmV3IFZUZXh0KGMpKTtcbiAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKHR5cGVvZiBjID09PSBcIm51bWJlclwiKSB7XG4gICAgICAgICAgICAgICAgICAgIGNoaWxkTm9kZXMucHVzaChuZXcgVlRleHQoU3RyaW5nKGMpKSk7XG4gICAgICAgICAgICAgICAgfSBlbHNlIGlmIChpc0NoaWxkKGMpKSB7XG4gICAgICAgICAgICAgICAgICAgIGNoaWxkTm9kZXMucHVzaChjKTtcbiAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKGlzQXJyYXkoYykpIHtcbiAgICAgICAgICAgICAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCBjLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBhZGRDaGlsZChjW2ldLCBjaGlsZE5vZGVzLCB0YWcsIHByb3BzKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoYyA9PT0gbnVsbCB8fCBjID09PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIHRocm93IFVuZXhwZWN0ZWRWaXJ0dWFsRWxlbWVudCh7XG4gICAgICAgICAgICAgICAgICAgICAgICBmb3JlaWduT2JqZWN0OiBjLFxuICAgICAgICAgICAgICAgICAgICAgICAgcGFyZW50Vm5vZGU6IHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0YWdOYW1lOiB0YWcsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcHJvcGVydGllczogcHJvcHNcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBmdW5jdGlvbiB0cmFuc2Zvcm1Qcm9wZXJ0aWVzKHByb3BzKSB7XG4gICAgICAgICAgICAgICAgZm9yICh2YXIgcHJvcE5hbWUgaW4gcHJvcHMpIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKHByb3BzLmhhc093blByb3BlcnR5KHByb3BOYW1lKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgdmFyIHZhbHVlID0gcHJvcHNbcHJvcE5hbWVdO1xuXG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoaXNIb29rKHZhbHVlKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnRpbnVlO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAocHJvcE5hbWUuc3Vic3RyKDAsIDMpID09PSBcImV2LVwiKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gYWRkIGV2LWZvbyBzdXBwb3J0XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcHJvcHNbcHJvcE5hbWVdID0gZXZIb29rKHZhbHVlKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZnVuY3Rpb24gaXNDaGlsZCh4KSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGlzVk5vZGUoeCkgfHwgaXNWVGV4dCh4KSB8fCBpc1dpZGdldCh4KSB8fCBpc1ZUaHVuayh4KTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZnVuY3Rpb24gaXNDaGlsZHJlbih4KSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHR5cGVvZiB4ID09PSBcInN0cmluZ1wiIHx8IGlzQXJyYXkoeCkgfHwgaXNDaGlsZCh4KTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZnVuY3Rpb24gVW5leHBlY3RlZFZpcnR1YWxFbGVtZW50KGRhdGEpIHtcbiAgICAgICAgICAgICAgICB2YXIgZXJyID0gbmV3IEVycm9yKCk7XG5cbiAgICAgICAgICAgICAgICBlcnIudHlwZSA9IFwidmlydHVhbC1oeXBlcnNjcmlwdC51bmV4cGVjdGVkLnZpcnR1YWwtZWxlbWVudFwiO1xuICAgICAgICAgICAgICAgIGVyci5tZXNzYWdlID0gXCJVbmV4cGVjdGVkIHZpcnR1YWwgY2hpbGQgcGFzc2VkIHRvIGgoKS5cXG5cIiArIFwiRXhwZWN0ZWQgYSBWTm9kZSAvIFZ0aHVuayAvIFZXaWRnZXQgLyBzdHJpbmcgYnV0OlxcblwiICsgXCJnb3Q6XFxuXCIgKyBlcnJvclN0cmluZyhkYXRhLmZvcmVpZ25PYmplY3QpICsgXCIuXFxuXCIgKyBcIlRoZSBwYXJlbnQgdm5vZGUgaXM6XFxuXCIgKyBlcnJvclN0cmluZyhkYXRhLnBhcmVudFZub2RlKTtcbiAgICAgICAgICAgICAgICBcIlxcblwiICsgXCJTdWdnZXN0ZWQgZml4OiBjaGFuZ2UgeW91ciBgaCguLi4sIFsgLi4uIF0pYCBjYWxsc2l0ZS5cIjtcbiAgICAgICAgICAgICAgICBlcnIuZm9yZWlnbk9iamVjdCA9IGRhdGEuZm9yZWlnbk9iamVjdDtcbiAgICAgICAgICAgICAgICBlcnIucGFyZW50Vm5vZGUgPSBkYXRhLnBhcmVudFZub2RlO1xuXG4gICAgICAgICAgICAgICAgcmV0dXJuIGVycjtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZnVuY3Rpb24gZXJyb3JTdHJpbmcob2JqKSB7XG4gICAgICAgICAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIEpTT04uc3RyaW5naWZ5KG9iaiwgbnVsbCwgXCIgICAgXCIpO1xuICAgICAgICAgICAgICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIFN0cmluZyhvYmopO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgfSwgeyBcIi4uL3Zub2RlL2lzLXRodW5rXCI6IDI1LCBcIi4uL3Zub2RlL2lzLXZob29rXCI6IDI2LCBcIi4uL3Zub2RlL2lzLXZub2RlXCI6IDI3LCBcIi4uL3Zub2RlL2lzLXZ0ZXh0XCI6IDI4LCBcIi4uL3Zub2RlL2lzLXdpZGdldFwiOiAyOSwgXCIuLi92bm9kZS92bm9kZS5qc1wiOiAzMSwgXCIuLi92bm9kZS92dGV4dC5qc1wiOiAzMywgXCIuL2hvb2tzL2V2LWhvb2suanNcIjogMjAsIFwiLi9ob29rcy9zb2Z0LXNldC1ob29rLmpzXCI6IDIxLCBcIi4vcGFyc2UtdGFnLmpzXCI6IDIzLCBcIngtaXMtYXJyYXlcIjogMTIgfV0sIDIzOiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge1xuICAgICAgICAgICAgXCJ1c2Ugc3RyaWN0XCI7XG5cbiAgICAgICAgICAgIHZhciBzcGxpdCA9IHJlcXVpcmUoXCJicm93c2VyLXNwbGl0XCIpO1xuXG4gICAgICAgICAgICB2YXIgY2xhc3NJZFNwbGl0ID0gLyhbXFwuI10/W2EtekEtWjAtOVxcdTAwN0YtXFx1RkZGRl86LV0rKS87XG4gICAgICAgICAgICB2YXIgbm90Q2xhc3NJZCA9IC9eXFwufCMvO1xuXG4gICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IHBhcnNlVGFnO1xuXG4gICAgICAgICAgICBmdW5jdGlvbiBwYXJzZVRhZyh0YWcsIHByb3BzKSB7XG4gICAgICAgICAgICAgICAgaWYgKCF0YWcpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIFwiRElWXCI7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgdmFyIG5vSWQgPSAhcHJvcHMuaGFzT3duUHJvcGVydHkoXCJpZFwiKTtcblxuICAgICAgICAgICAgICAgIHZhciB0YWdQYXJ0cyA9IHNwbGl0KHRhZywgY2xhc3NJZFNwbGl0KTtcbiAgICAgICAgICAgICAgICB2YXIgdGFnTmFtZSA9IG51bGw7XG5cbiAgICAgICAgICAgICAgICBpZiAobm90Q2xhc3NJZC50ZXN0KHRhZ1BhcnRzWzFdKSkge1xuICAgICAgICAgICAgICAgICAgICB0YWdOYW1lID0gXCJESVZcIjtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICB2YXIgY2xhc3NlcywgcGFydCwgdHlwZSwgaTtcblxuICAgICAgICAgICAgICAgIGZvciAoaSA9IDA7IGkgPCB0YWdQYXJ0cy5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgICAgICAgICBwYXJ0ID0gdGFnUGFydHNbaV07XG5cbiAgICAgICAgICAgICAgICAgICAgaWYgKCFwYXJ0KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBjb250aW51ZTtcbiAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgIHR5cGUgPSBwYXJ0LmNoYXJBdCgwKTtcblxuICAgICAgICAgICAgICAgICAgICBpZiAoIXRhZ05hbWUpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHRhZ05hbWUgPSBwYXJ0O1xuICAgICAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKHR5cGUgPT09IFwiLlwiKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBjbGFzc2VzID0gY2xhc3NlcyB8fCBbXTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGNsYXNzZXMucHVzaChwYXJ0LnN1YnN0cmluZygxLCBwYXJ0Lmxlbmd0aCkpO1xuICAgICAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKHR5cGUgPT09IFwiI1wiICYmIG5vSWQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHByb3BzLmlkID0gcGFydC5zdWJzdHJpbmcoMSwgcGFydC5sZW5ndGgpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgaWYgKGNsYXNzZXMpIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKHByb3BzLmNsYXNzTmFtZSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgY2xhc3Nlcy5wdXNoKHByb3BzLmNsYXNzTmFtZSk7XG4gICAgICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgICAgICBwcm9wcy5jbGFzc05hbWUgPSBjbGFzc2VzLmpvaW4oXCIgXCIpO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHJldHVybiBwcm9wcy5uYW1lc3BhY2UgPyB0YWdOYW1lIDogdGFnTmFtZS50b1VwcGVyQ2FzZSgpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9LCB7IFwiYnJvd3Nlci1zcGxpdFwiOiA1IH1dLCAyNDogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHtcbiAgICAgICAgICAgIHZhciBpc1ZOb2RlID0gcmVxdWlyZShcIi4vaXMtdm5vZGVcIik7XG4gICAgICAgICAgICB2YXIgaXNWVGV4dCA9IHJlcXVpcmUoXCIuL2lzLXZ0ZXh0XCIpO1xuICAgICAgICAgICAgdmFyIGlzV2lkZ2V0ID0gcmVxdWlyZShcIi4vaXMtd2lkZ2V0XCIpO1xuICAgICAgICAgICAgdmFyIGlzVGh1bmsgPSByZXF1aXJlKFwiLi9pcy10aHVua1wiKTtcblxuICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBoYW5kbGVUaHVuaztcblxuICAgICAgICAgICAgZnVuY3Rpb24gaGFuZGxlVGh1bmsoYSwgYikge1xuICAgICAgICAgICAgICAgIHZhciByZW5kZXJlZEEgPSBhO1xuICAgICAgICAgICAgICAgIHZhciByZW5kZXJlZEIgPSBiO1xuXG4gICAgICAgICAgICAgICAgaWYgKGlzVGh1bmsoYikpIHtcbiAgICAgICAgICAgICAgICAgICAgcmVuZGVyZWRCID0gcmVuZGVyVGh1bmsoYiwgYSk7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgaWYgKGlzVGh1bmsoYSkpIHtcbiAgICAgICAgICAgICAgICAgICAgcmVuZGVyZWRBID0gcmVuZGVyVGh1bmsoYSwgbnVsbCk7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgICAgICAgICAgYTogcmVuZGVyZWRBLFxuICAgICAgICAgICAgICAgICAgICBiOiByZW5kZXJlZEJcbiAgICAgICAgICAgICAgICB9O1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBmdW5jdGlvbiByZW5kZXJUaHVuayh0aHVuaywgcHJldmlvdXMpIHtcbiAgICAgICAgICAgICAgICB2YXIgcmVuZGVyZWRUaHVuayA9IHRodW5rLnZub2RlO1xuXG4gICAgICAgICAgICAgICAgaWYgKCFyZW5kZXJlZFRodW5rKSB7XG4gICAgICAgICAgICAgICAgICAgIHJlbmRlcmVkVGh1bmsgPSB0aHVuay52bm9kZSA9IHRodW5rLnJlbmRlcihwcmV2aW91cyk7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgaWYgKCEoaXNWTm9kZShyZW5kZXJlZFRodW5rKSB8fCBpc1ZUZXh0KHJlbmRlcmVkVGh1bmspIHx8IGlzV2lkZ2V0KHJlbmRlcmVkVGh1bmspKSkge1xuICAgICAgICAgICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoXCJ0aHVuayBkaWQgbm90IHJldHVybiBhIHZhbGlkIG5vZGVcIik7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgcmV0dXJuIHJlbmRlcmVkVGh1bms7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0sIHsgXCIuL2lzLXRodW5rXCI6IDI1LCBcIi4vaXMtdm5vZGVcIjogMjcsIFwiLi9pcy12dGV4dFwiOiAyOCwgXCIuL2lzLXdpZGdldFwiOiAyOSB9XSwgMjU6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IGlzVGh1bms7XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIGlzVGh1bmsodCkge1xuICAgICAgICAgICAgICAgIHJldHVybiB0ICYmIHQudHlwZSA9PT0gXCJUaHVua1wiO1xuICAgICAgICAgICAgfVxuICAgICAgICB9LCB7fV0sIDI2OiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge1xuICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBpc0hvb2s7XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIGlzSG9vayhob29rKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGhvb2sgJiYgKHR5cGVvZiBob29rLmhvb2sgPT09IFwiZnVuY3Rpb25cIiAmJiAhaG9vay5oYXNPd25Qcm9wZXJ0eShcImhvb2tcIikgfHwgdHlwZW9mIGhvb2sudW5ob29rID09PSBcImZ1bmN0aW9uXCIgJiYgIWhvb2suaGFzT3duUHJvcGVydHkoXCJ1bmhvb2tcIikpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9LCB7fV0sIDI3OiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge1xuICAgICAgICAgICAgdmFyIHZlcnNpb24gPSByZXF1aXJlKFwiLi92ZXJzaW9uXCIpO1xuXG4gICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IGlzVmlydHVhbE5vZGU7XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIGlzVmlydHVhbE5vZGUoeCkge1xuICAgICAgICAgICAgICAgIHJldHVybiB4ICYmIHgudHlwZSA9PT0gXCJWaXJ0dWFsTm9kZVwiICYmIHgudmVyc2lvbiA9PT0gdmVyc2lvbjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSwgeyBcIi4vdmVyc2lvblwiOiAzMCB9XSwgMjg6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICB2YXIgdmVyc2lvbiA9IHJlcXVpcmUoXCIuL3ZlcnNpb25cIik7XG5cbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gaXNWaXJ0dWFsVGV4dDtcblxuICAgICAgICAgICAgZnVuY3Rpb24gaXNWaXJ0dWFsVGV4dCh4KSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHggJiYgeC50eXBlID09PSBcIlZpcnR1YWxUZXh0XCIgJiYgeC52ZXJzaW9uID09PSB2ZXJzaW9uO1xuICAgICAgICAgICAgfVxuICAgICAgICB9LCB7IFwiLi92ZXJzaW9uXCI6IDMwIH1dLCAyOTogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHtcbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gaXNXaWRnZXQ7XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIGlzV2lkZ2V0KHcpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gdyAmJiB3LnR5cGUgPT09IFwiV2lkZ2V0XCI7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0sIHt9XSwgMzA6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IFwiMlwiO1xuICAgICAgICB9LCB7fV0sIDMxOiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge1xuICAgICAgICAgICAgdmFyIHZlcnNpb24gPSByZXF1aXJlKFwiLi92ZXJzaW9uXCIpO1xuICAgICAgICAgICAgdmFyIGlzVk5vZGUgPSByZXF1aXJlKFwiLi9pcy12bm9kZVwiKTtcbiAgICAgICAgICAgIHZhciBpc1dpZGdldCA9IHJlcXVpcmUoXCIuL2lzLXdpZGdldFwiKTtcbiAgICAgICAgICAgIHZhciBpc1RodW5rID0gcmVxdWlyZShcIi4vaXMtdGh1bmtcIik7XG4gICAgICAgICAgICB2YXIgaXNWSG9vayA9IHJlcXVpcmUoXCIuL2lzLXZob29rXCIpO1xuXG4gICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IFZpcnR1YWxOb2RlO1xuXG4gICAgICAgICAgICB2YXIgbm9Qcm9wZXJ0aWVzID0ge307XG4gICAgICAgICAgICB2YXIgbm9DaGlsZHJlbiA9IFtdO1xuXG4gICAgICAgICAgICBmdW5jdGlvbiBWaXJ0dWFsTm9kZSh0YWdOYW1lLCBwcm9wZXJ0aWVzLCBjaGlsZHJlbiwga2V5LCBuYW1lc3BhY2UpIHtcbiAgICAgICAgICAgICAgICB0aGlzLnRhZ05hbWUgPSB0YWdOYW1lO1xuICAgICAgICAgICAgICAgIHRoaXMucHJvcGVydGllcyA9IHByb3BlcnRpZXMgfHwgbm9Qcm9wZXJ0aWVzO1xuICAgICAgICAgICAgICAgIHRoaXMuY2hpbGRyZW4gPSBjaGlsZHJlbiB8fCBub0NoaWxkcmVuO1xuICAgICAgICAgICAgICAgIHRoaXMua2V5ID0ga2V5ICE9IG51bGwgPyBTdHJpbmcoa2V5KSA6IHVuZGVmaW5lZDtcbiAgICAgICAgICAgICAgICB0aGlzLm5hbWVzcGFjZSA9IHR5cGVvZiBuYW1lc3BhY2UgPT09IFwic3RyaW5nXCIgPyBuYW1lc3BhY2UgOiBudWxsO1xuXG4gICAgICAgICAgICAgICAgdmFyIGNvdW50ID0gY2hpbGRyZW4gJiYgY2hpbGRyZW4ubGVuZ3RoIHx8IDA7XG4gICAgICAgICAgICAgICAgdmFyIGRlc2NlbmRhbnRzID0gMDtcbiAgICAgICAgICAgICAgICB2YXIgaGFzV2lkZ2V0cyA9IGZhbHNlO1xuICAgICAgICAgICAgICAgIHZhciBoYXNUaHVua3MgPSBmYWxzZTtcbiAgICAgICAgICAgICAgICB2YXIgZGVzY2VuZGFudEhvb2tzID0gZmFsc2U7XG4gICAgICAgICAgICAgICAgdmFyIGhvb2tzO1xuXG4gICAgICAgICAgICAgICAgZm9yICh2YXIgcHJvcE5hbWUgaW4gcHJvcGVydGllcykge1xuICAgICAgICAgICAgICAgICAgICBpZiAocHJvcGVydGllcy5oYXNPd25Qcm9wZXJ0eShwcm9wTmFtZSkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHZhciBwcm9wZXJ0eSA9IHByb3BlcnRpZXNbcHJvcE5hbWVdO1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGlzVkhvb2socHJvcGVydHkpICYmIHByb3BlcnR5LnVuaG9vaykge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmICghaG9va3MpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaG9va3MgPSB7fTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBob29rc1twcm9wTmFtZV0gPSBwcm9wZXJ0eTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgY291bnQ7IGkrKykge1xuICAgICAgICAgICAgICAgICAgICB2YXIgY2hpbGQgPSBjaGlsZHJlbltpXTtcbiAgICAgICAgICAgICAgICAgICAgaWYgKGlzVk5vZGUoY2hpbGQpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBkZXNjZW5kYW50cyArPSBjaGlsZC5jb3VudCB8fCAwO1xuXG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoIWhhc1dpZGdldHMgJiYgY2hpbGQuaGFzV2lkZ2V0cykge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGhhc1dpZGdldHMgPSB0cnVlO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoIWhhc1RodW5rcyAmJiBjaGlsZC5oYXNUaHVua3MpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBoYXNUaHVua3MgPSB0cnVlO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoIWRlc2NlbmRhbnRIb29rcyAmJiAoY2hpbGQuaG9va3MgfHwgY2hpbGQuZGVzY2VuZGFudEhvb2tzKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRlc2NlbmRhbnRIb29rcyA9IHRydWU7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoIWhhc1dpZGdldHMgJiYgaXNXaWRnZXQoY2hpbGQpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAodHlwZW9mIGNoaWxkLmRlc3Ryb3kgPT09IFwiZnVuY3Rpb25cIikge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGhhc1dpZGdldHMgPSB0cnVlO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKCFoYXNUaHVua3MgJiYgaXNUaHVuayhjaGlsZCkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGhhc1RodW5rcyA9IHRydWU7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICB0aGlzLmNvdW50ID0gY291bnQgKyBkZXNjZW5kYW50cztcbiAgICAgICAgICAgICAgICB0aGlzLmhhc1dpZGdldHMgPSBoYXNXaWRnZXRzO1xuICAgICAgICAgICAgICAgIHRoaXMuaGFzVGh1bmtzID0gaGFzVGh1bmtzO1xuICAgICAgICAgICAgICAgIHRoaXMuaG9va3MgPSBob29rcztcbiAgICAgICAgICAgICAgICB0aGlzLmRlc2NlbmRhbnRIb29rcyA9IGRlc2NlbmRhbnRIb29rcztcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgVmlydHVhbE5vZGUucHJvdG90eXBlLnZlcnNpb24gPSB2ZXJzaW9uO1xuICAgICAgICAgICAgVmlydHVhbE5vZGUucHJvdG90eXBlLnR5cGUgPSBcIlZpcnR1YWxOb2RlXCI7XG4gICAgICAgIH0sIHsgXCIuL2lzLXRodW5rXCI6IDI1LCBcIi4vaXMtdmhvb2tcIjogMjYsIFwiLi9pcy12bm9kZVwiOiAyNywgXCIuL2lzLXdpZGdldFwiOiAyOSwgXCIuL3ZlcnNpb25cIjogMzAgfV0sIDMyOiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge1xuICAgICAgICAgICAgdmFyIHZlcnNpb24gPSByZXF1aXJlKFwiLi92ZXJzaW9uXCIpO1xuXG4gICAgICAgICAgICBWaXJ0dWFsUGF0Y2guTk9ORSA9IDA7XG4gICAgICAgICAgICBWaXJ0dWFsUGF0Y2guVlRFWFQgPSAxO1xuICAgICAgICAgICAgVmlydHVhbFBhdGNoLlZOT0RFID0gMjtcbiAgICAgICAgICAgIFZpcnR1YWxQYXRjaC5XSURHRVQgPSAzO1xuICAgICAgICAgICAgVmlydHVhbFBhdGNoLlBST1BTID0gNDtcbiAgICAgICAgICAgIFZpcnR1YWxQYXRjaC5PUkRFUiA9IDU7XG4gICAgICAgICAgICBWaXJ0dWFsUGF0Y2guSU5TRVJUID0gNjtcbiAgICAgICAgICAgIFZpcnR1YWxQYXRjaC5SRU1PVkUgPSA3O1xuICAgICAgICAgICAgVmlydHVhbFBhdGNoLlRIVU5LID0gODtcblxuICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBWaXJ0dWFsUGF0Y2g7XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIFZpcnR1YWxQYXRjaCh0eXBlLCB2Tm9kZSwgcGF0Y2gpIHtcbiAgICAgICAgICAgICAgICB0aGlzLnR5cGUgPSBOdW1iZXIodHlwZSk7XG4gICAgICAgICAgICAgICAgdGhpcy52Tm9kZSA9IHZOb2RlO1xuICAgICAgICAgICAgICAgIHRoaXMucGF0Y2ggPSBwYXRjaDtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgVmlydHVhbFBhdGNoLnByb3RvdHlwZS52ZXJzaW9uID0gdmVyc2lvbjtcbiAgICAgICAgICAgIFZpcnR1YWxQYXRjaC5wcm90b3R5cGUudHlwZSA9IFwiVmlydHVhbFBhdGNoXCI7XG4gICAgICAgIH0sIHsgXCIuL3ZlcnNpb25cIjogMzAgfV0sIDMzOiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge1xuICAgICAgICAgICAgdmFyIHZlcnNpb24gPSByZXF1aXJlKFwiLi92ZXJzaW9uXCIpO1xuXG4gICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IFZpcnR1YWxUZXh0O1xuXG4gICAgICAgICAgICBmdW5jdGlvbiBWaXJ0dWFsVGV4dCh0ZXh0KSB7XG4gICAgICAgICAgICAgICAgdGhpcy50ZXh0ID0gU3RyaW5nKHRleHQpO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBWaXJ0dWFsVGV4dC5wcm90b3R5cGUudmVyc2lvbiA9IHZlcnNpb247XG4gICAgICAgICAgICBWaXJ0dWFsVGV4dC5wcm90b3R5cGUudHlwZSA9IFwiVmlydHVhbFRleHRcIjtcbiAgICAgICAgfSwgeyBcIi4vdmVyc2lvblwiOiAzMCB9XSwgMzQ6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICB2YXIgaXNPYmplY3QgPSByZXF1aXJlKFwiaXMtb2JqZWN0XCIpO1xuICAgICAgICAgICAgdmFyIGlzSG9vayA9IHJlcXVpcmUoXCIuLi92bm9kZS9pcy12aG9va1wiKTtcblxuICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBkaWZmUHJvcHM7XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIGRpZmZQcm9wcyhhLCBiKSB7XG4gICAgICAgICAgICAgICAgdmFyIGRpZmY7XG5cbiAgICAgICAgICAgICAgICBmb3IgKHZhciBhS2V5IGluIGEpIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKCEoYUtleSBpbiBiKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgZGlmZiA9IGRpZmYgfHwge307XG4gICAgICAgICAgICAgICAgICAgICAgICBkaWZmW2FLZXldID0gdW5kZWZpbmVkO1xuICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgdmFyIGFWYWx1ZSA9IGFbYUtleV07XG4gICAgICAgICAgICAgICAgICAgIHZhciBiVmFsdWUgPSBiW2FLZXldO1xuXG4gICAgICAgICAgICAgICAgICAgIGlmIChhVmFsdWUgPT09IGJWYWx1ZSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgY29udGludWU7XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoaXNPYmplY3QoYVZhbHVlKSAmJiBpc09iamVjdChiVmFsdWUpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoZ2V0UHJvdG90eXBlKGJWYWx1ZSkgIT09IGdldFByb3RvdHlwZShhVmFsdWUpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgZGlmZiA9IGRpZmYgfHwge307XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgZGlmZlthS2V5XSA9IGJWYWx1ZTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoaXNIb29rKGJWYWx1ZSkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBkaWZmID0gZGlmZiB8fCB7fTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBkaWZmW2FLZXldID0gYlZhbHVlO1xuICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB2YXIgb2JqZWN0RGlmZiA9IGRpZmZQcm9wcyhhVmFsdWUsIGJWYWx1ZSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKG9iamVjdERpZmYpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZGlmZiA9IGRpZmYgfHwge307XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRpZmZbYUtleV0gPSBvYmplY3REaWZmO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGRpZmYgPSBkaWZmIHx8IHt9O1xuICAgICAgICAgICAgICAgICAgICAgICAgZGlmZlthS2V5XSA9IGJWYWx1ZTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIGZvciAodmFyIGJLZXkgaW4gYikge1xuICAgICAgICAgICAgICAgICAgICBpZiAoIShiS2V5IGluIGEpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBkaWZmID0gZGlmZiB8fCB7fTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGRpZmZbYktleV0gPSBiW2JLZXldO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgcmV0dXJuIGRpZmY7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIGdldFByb3RvdHlwZSh2YWx1ZSkge1xuICAgICAgICAgICAgICAgIGlmIChPYmplY3QuZ2V0UHJvdG90eXBlT2YpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIE9iamVjdC5nZXRQcm90b3R5cGVPZih2YWx1ZSk7XG4gICAgICAgICAgICAgICAgfSBlbHNlIGlmICh2YWx1ZS5fX3Byb3RvX18pIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHZhbHVlLl9fcHJvdG9fXztcbiAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKHZhbHVlLmNvbnN0cnVjdG9yKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiB2YWx1ZS5jb25zdHJ1Y3Rvci5wcm90b3R5cGU7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9LCB7IFwiLi4vdm5vZGUvaXMtdmhvb2tcIjogMjYsIFwiaXMtb2JqZWN0XCI6IDExIH1dLCAzNTogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHtcbiAgICAgICAgICAgIHZhciBpc0FycmF5ID0gcmVxdWlyZShcIngtaXMtYXJyYXlcIik7XG5cbiAgICAgICAgICAgIHZhciBWUGF0Y2ggPSByZXF1aXJlKFwiLi4vdm5vZGUvdnBhdGNoXCIpO1xuICAgICAgICAgICAgdmFyIGlzVk5vZGUgPSByZXF1aXJlKFwiLi4vdm5vZGUvaXMtdm5vZGVcIik7XG4gICAgICAgICAgICB2YXIgaXNWVGV4dCA9IHJlcXVpcmUoXCIuLi92bm9kZS9pcy12dGV4dFwiKTtcbiAgICAgICAgICAgIHZhciBpc1dpZGdldCA9IHJlcXVpcmUoXCIuLi92bm9kZS9pcy13aWRnZXRcIik7XG4gICAgICAgICAgICB2YXIgaXNUaHVuayA9IHJlcXVpcmUoXCIuLi92bm9kZS9pcy10aHVua1wiKTtcbiAgICAgICAgICAgIHZhciBoYW5kbGVUaHVuayA9IHJlcXVpcmUoXCIuLi92bm9kZS9oYW5kbGUtdGh1bmtcIik7XG5cbiAgICAgICAgICAgIHZhciBkaWZmUHJvcHMgPSByZXF1aXJlKFwiLi9kaWZmLXByb3BzXCIpO1xuXG4gICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IGRpZmY7XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIGRpZmYoYSwgYikge1xuICAgICAgICAgICAgICAgIHZhciBwYXRjaCA9IHsgYTogYSB9O1xuICAgICAgICAgICAgICAgIHdhbGsoYSwgYiwgcGF0Y2gsIDApO1xuICAgICAgICAgICAgICAgIHJldHVybiBwYXRjaDtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZnVuY3Rpb24gd2FsayhhLCBiLCBwYXRjaCwgaW5kZXgpIHtcbiAgICAgICAgICAgICAgICBpZiAoYSA9PT0gYikge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgdmFyIGFwcGx5ID0gcGF0Y2hbaW5kZXhdO1xuICAgICAgICAgICAgICAgIHZhciBhcHBseUNsZWFyID0gZmFsc2U7XG5cbiAgICAgICAgICAgICAgICBpZiAoaXNUaHVuayhhKSB8fCBpc1RodW5rKGIpKSB7XG4gICAgICAgICAgICAgICAgICAgIHRodW5rcyhhLCBiLCBwYXRjaCwgaW5kZXgpO1xuICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoYiA9PSBudWxsKSB7XG5cbiAgICAgICAgICAgICAgICAgICAgLy8gSWYgYSBpcyBhIHdpZGdldCB3ZSB3aWxsIGFkZCBhIHJlbW92ZSBwYXRjaCBmb3IgaXRcbiAgICAgICAgICAgICAgICAgICAgLy8gT3RoZXJ3aXNlIGFueSBjaGlsZCB3aWRnZXRzL2hvb2tzIG11c3QgYmUgZGVzdHJveWVkLlxuICAgICAgICAgICAgICAgICAgICAvLyBUaGlzIHByZXZlbnRzIGFkZGluZyB0d28gcmVtb3ZlIHBhdGNoZXMgZm9yIGEgd2lkZ2V0LlxuICAgICAgICAgICAgICAgICAgICBpZiAoIWlzV2lkZ2V0KGEpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBjbGVhclN0YXRlKGEsIHBhdGNoLCBpbmRleCk7XG4gICAgICAgICAgICAgICAgICAgICAgICBhcHBseSA9IHBhdGNoW2luZGV4XTtcbiAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgIGFwcGx5ID0gYXBwZW5kUGF0Y2goYXBwbHksIG5ldyBWUGF0Y2goVlBhdGNoLlJFTU9WRSwgYSwgYikpO1xuICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoaXNWTm9kZShiKSkge1xuICAgICAgICAgICAgICAgICAgICBpZiAoaXNWTm9kZShhKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGEudGFnTmFtZSA9PT0gYi50YWdOYW1lICYmIGEubmFtZXNwYWNlID09PSBiLm5hbWVzcGFjZSAmJiBhLmtleSA9PT0gYi5rZXkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB2YXIgcHJvcHNQYXRjaCA9IGRpZmZQcm9wcyhhLnByb3BlcnRpZXMsIGIucHJvcGVydGllcyk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHByb3BzUGF0Y2gpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYXBwbHkgPSBhcHBlbmRQYXRjaChhcHBseSwgbmV3IFZQYXRjaChWUGF0Y2guUFJPUFMsIGEsIHByb3BzUGF0Y2gpKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgYXBwbHkgPSBkaWZmQ2hpbGRyZW4oYSwgYiwgcGF0Y2gsIGFwcGx5LCBpbmRleCk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGFwcGx5ID0gYXBwZW5kUGF0Y2goYXBwbHksIG5ldyBWUGF0Y2goVlBhdGNoLlZOT0RFLCBhLCBiKSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgYXBwbHlDbGVhciA9IHRydWU7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBhcHBseSA9IGFwcGVuZFBhdGNoKGFwcGx5LCBuZXcgVlBhdGNoKFZQYXRjaC5WTk9ERSwgYSwgYikpO1xuICAgICAgICAgICAgICAgICAgICAgICAgYXBwbHlDbGVhciA9IHRydWU7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKGlzVlRleHQoYikpIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKCFpc1ZUZXh0KGEpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBhcHBseSA9IGFwcGVuZFBhdGNoKGFwcGx5LCBuZXcgVlBhdGNoKFZQYXRjaC5WVEVYVCwgYSwgYikpO1xuICAgICAgICAgICAgICAgICAgICAgICAgYXBwbHlDbGVhciA9IHRydWU7XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoYS50ZXh0ICE9PSBiLnRleHQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGFwcGx5ID0gYXBwZW5kUGF0Y2goYXBwbHksIG5ldyBWUGF0Y2goVlBhdGNoLlZURVhULCBhLCBiKSk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKGlzV2lkZ2V0KGIpKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmICghaXNXaWRnZXQoYSkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGFwcGx5Q2xlYXIgPSB0cnVlO1xuICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgYXBwbHkgPSBhcHBlbmRQYXRjaChhcHBseSwgbmV3IFZQYXRjaChWUGF0Y2guV0lER0VULCBhLCBiKSk7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgaWYgKGFwcGx5KSB7XG4gICAgICAgICAgICAgICAgICAgIHBhdGNoW2luZGV4XSA9IGFwcGx5O1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIGlmIChhcHBseUNsZWFyKSB7XG4gICAgICAgICAgICAgICAgICAgIGNsZWFyU3RhdGUoYSwgcGF0Y2gsIGluZGV4KTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIGRpZmZDaGlsZHJlbihhLCBiLCBwYXRjaCwgYXBwbHksIGluZGV4KSB7XG4gICAgICAgICAgICAgICAgdmFyIGFDaGlsZHJlbiA9IGEuY2hpbGRyZW47XG4gICAgICAgICAgICAgICAgdmFyIG9yZGVyZWRTZXQgPSByZW9yZGVyKGFDaGlsZHJlbiwgYi5jaGlsZHJlbik7XG4gICAgICAgICAgICAgICAgdmFyIGJDaGlsZHJlbiA9IG9yZGVyZWRTZXQuY2hpbGRyZW47XG5cbiAgICAgICAgICAgICAgICB2YXIgYUxlbiA9IGFDaGlsZHJlbi5sZW5ndGg7XG4gICAgICAgICAgICAgICAgdmFyIGJMZW4gPSBiQ2hpbGRyZW4ubGVuZ3RoO1xuICAgICAgICAgICAgICAgIHZhciBsZW4gPSBhTGVuID4gYkxlbiA/IGFMZW4gOiBiTGVuO1xuXG4gICAgICAgICAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCBsZW47IGkrKykge1xuICAgICAgICAgICAgICAgICAgICB2YXIgbGVmdE5vZGUgPSBhQ2hpbGRyZW5baV07XG4gICAgICAgICAgICAgICAgICAgIHZhciByaWdodE5vZGUgPSBiQ2hpbGRyZW5baV07XG4gICAgICAgICAgICAgICAgICAgIGluZGV4ICs9IDE7XG5cbiAgICAgICAgICAgICAgICAgICAgaWYgKCFsZWZ0Tm9kZSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHJpZ2h0Tm9kZSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIEV4Y2VzcyBub2RlcyBpbiBiIG5lZWQgdG8gYmUgYWRkZWRcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBhcHBseSA9IGFwcGVuZFBhdGNoKGFwcGx5LCBuZXcgVlBhdGNoKFZQYXRjaC5JTlNFUlQsIG51bGwsIHJpZ2h0Tm9kZSkpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgd2FsayhsZWZ0Tm9kZSwgcmlnaHROb2RlLCBwYXRjaCwgaW5kZXgpO1xuICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgaWYgKGlzVk5vZGUobGVmdE5vZGUpICYmIGxlZnROb2RlLmNvdW50KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBpbmRleCArPSBsZWZ0Tm9kZS5jb3VudDtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIGlmIChvcmRlcmVkU2V0Lm1vdmVzKSB7XG4gICAgICAgICAgICAgICAgICAgIC8vIFJlb3JkZXIgbm9kZXMgbGFzdFxuICAgICAgICAgICAgICAgICAgICBhcHBseSA9IGFwcGVuZFBhdGNoKGFwcGx5LCBuZXcgVlBhdGNoKFZQYXRjaC5PUkRFUiwgYSwgb3JkZXJlZFNldC5tb3ZlcykpO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHJldHVybiBhcHBseTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZnVuY3Rpb24gY2xlYXJTdGF0ZSh2Tm9kZSwgcGF0Y2gsIGluZGV4KSB7XG4gICAgICAgICAgICAgICAgLy8gVE9ETzogTWFrZSB0aGlzIGEgc2luZ2xlIHdhbGssIG5vdCB0d29cbiAgICAgICAgICAgICAgICB1bmhvb2sodk5vZGUsIHBhdGNoLCBpbmRleCk7XG4gICAgICAgICAgICAgICAgZGVzdHJveVdpZGdldHModk5vZGUsIHBhdGNoLCBpbmRleCk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIC8vIFBhdGNoIHJlY29yZHMgZm9yIGFsbCBkZXN0cm95ZWQgd2lkZ2V0cyBtdXN0IGJlIGFkZGVkIGJlY2F1c2Ugd2UgbmVlZFxuICAgICAgICAgICAgLy8gYSBET00gbm9kZSByZWZlcmVuY2UgZm9yIHRoZSBkZXN0cm95IGZ1bmN0aW9uXG4gICAgICAgICAgICBmdW5jdGlvbiBkZXN0cm95V2lkZ2V0cyh2Tm9kZSwgcGF0Y2gsIGluZGV4KSB7XG4gICAgICAgICAgICAgICAgaWYgKGlzV2lkZ2V0KHZOb2RlKSkge1xuICAgICAgICAgICAgICAgICAgICBpZiAodHlwZW9mIHZOb2RlLmRlc3Ryb3kgPT09IFwiZnVuY3Rpb25cIikge1xuICAgICAgICAgICAgICAgICAgICAgICAgcGF0Y2hbaW5kZXhdID0gYXBwZW5kUGF0Y2gocGF0Y2hbaW5kZXhdLCBuZXcgVlBhdGNoKFZQYXRjaC5SRU1PVkUsIHZOb2RlLCBudWxsKSk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKGlzVk5vZGUodk5vZGUpICYmICh2Tm9kZS5oYXNXaWRnZXRzIHx8IHZOb2RlLmhhc1RodW5rcykpIHtcbiAgICAgICAgICAgICAgICAgICAgdmFyIGNoaWxkcmVuID0gdk5vZGUuY2hpbGRyZW47XG4gICAgICAgICAgICAgICAgICAgIHZhciBsZW4gPSBjaGlsZHJlbi5sZW5ndGg7XG4gICAgICAgICAgICAgICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgbGVuOyBpKyspIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHZhciBjaGlsZCA9IGNoaWxkcmVuW2ldO1xuICAgICAgICAgICAgICAgICAgICAgICAgaW5kZXggKz0gMTtcblxuICAgICAgICAgICAgICAgICAgICAgICAgZGVzdHJveVdpZGdldHMoY2hpbGQsIHBhdGNoLCBpbmRleCk7XG5cbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChpc1ZOb2RlKGNoaWxkKSAmJiBjaGlsZC5jb3VudCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGluZGV4ICs9IGNoaWxkLmNvdW50O1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfSBlbHNlIGlmIChpc1RodW5rKHZOb2RlKSkge1xuICAgICAgICAgICAgICAgICAgICB0aHVua3Modk5vZGUsIG51bGwsIHBhdGNoLCBpbmRleCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAvLyBDcmVhdGUgYSBzdWItcGF0Y2ggZm9yIHRodW5rc1xuICAgICAgICAgICAgZnVuY3Rpb24gdGh1bmtzKGEsIGIsIHBhdGNoLCBpbmRleCkge1xuICAgICAgICAgICAgICAgIHZhciBub2RlcyA9IGhhbmRsZVRodW5rKGEsIGIpO1xuICAgICAgICAgICAgICAgIHZhciB0aHVua1BhdGNoID0gZGlmZihub2Rlcy5hLCBub2Rlcy5iKTtcbiAgICAgICAgICAgICAgICBpZiAoaGFzUGF0Y2hlcyh0aHVua1BhdGNoKSkge1xuICAgICAgICAgICAgICAgICAgICBwYXRjaFtpbmRleF0gPSBuZXcgVlBhdGNoKFZQYXRjaC5USFVOSywgbnVsbCwgdGh1bmtQYXRjaCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBmdW5jdGlvbiBoYXNQYXRjaGVzKHBhdGNoKSB7XG4gICAgICAgICAgICAgICAgZm9yICh2YXIgaW5kZXggaW4gcGF0Y2gpIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKGluZGV4ICE9PSBcImFcIikge1xuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIC8vIEV4ZWN1dGUgaG9va3Mgd2hlbiB0d28gbm9kZXMgYXJlIGlkZW50aWNhbFxuICAgICAgICAgICAgZnVuY3Rpb24gdW5ob29rKHZOb2RlLCBwYXRjaCwgaW5kZXgpIHtcbiAgICAgICAgICAgICAgICBpZiAoaXNWTm9kZSh2Tm9kZSkpIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKHZOb2RlLmhvb2tzKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBwYXRjaFtpbmRleF0gPSBhcHBlbmRQYXRjaChwYXRjaFtpbmRleF0sIG5ldyBWUGF0Y2goVlBhdGNoLlBST1BTLCB2Tm9kZSwgdW5kZWZpbmVkS2V5cyh2Tm9kZS5ob29rcykpKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgIGlmICh2Tm9kZS5kZXNjZW5kYW50SG9va3MgfHwgdk5vZGUuaGFzVGh1bmtzKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICB2YXIgY2hpbGRyZW4gPSB2Tm9kZS5jaGlsZHJlbjtcbiAgICAgICAgICAgICAgICAgICAgICAgIHZhciBsZW4gPSBjaGlsZHJlbi5sZW5ndGg7XG4gICAgICAgICAgICAgICAgICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IGxlbjsgaSsrKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdmFyIGNoaWxkID0gY2hpbGRyZW5baV07XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaW5kZXggKz0gMTtcblxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHVuaG9vayhjaGlsZCwgcGF0Y2gsIGluZGV4KTtcblxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChpc1ZOb2RlKGNoaWxkKSAmJiBjaGlsZC5jb3VudCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpbmRleCArPSBjaGlsZC5jb3VudDtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKGlzVGh1bmsodk5vZGUpKSB7XG4gICAgICAgICAgICAgICAgICAgIHRodW5rcyh2Tm9kZSwgbnVsbCwgcGF0Y2gsIGluZGV4KTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIHVuZGVmaW5lZEtleXMob2JqKSB7XG4gICAgICAgICAgICAgICAgdmFyIHJlc3VsdCA9IHt9O1xuXG4gICAgICAgICAgICAgICAgZm9yICh2YXIga2V5IGluIG9iaikge1xuICAgICAgICAgICAgICAgICAgICByZXN1bHRba2V5XSA9IHVuZGVmaW5lZDtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICByZXR1cm4gcmVzdWx0O1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAvLyBMaXN0IGRpZmYsIG5haXZlIGxlZnQgdG8gcmlnaHQgcmVvcmRlcmluZ1xuICAgICAgICAgICAgZnVuY3Rpb24gcmVvcmRlcihhQ2hpbGRyZW4sIGJDaGlsZHJlbikge1xuICAgICAgICAgICAgICAgIC8vIE8oTSkgdGltZSwgTyhNKSBtZW1vcnlcbiAgICAgICAgICAgICAgICB2YXIgYkNoaWxkSW5kZXggPSBrZXlJbmRleChiQ2hpbGRyZW4pO1xuICAgICAgICAgICAgICAgIHZhciBiS2V5cyA9IGJDaGlsZEluZGV4LmtleXM7XG4gICAgICAgICAgICAgICAgdmFyIGJGcmVlID0gYkNoaWxkSW5kZXguZnJlZTtcblxuICAgICAgICAgICAgICAgIGlmIChiRnJlZS5sZW5ndGggPT09IGJDaGlsZHJlbi5sZW5ndGgpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGNoaWxkcmVuOiBiQ2hpbGRyZW4sXG4gICAgICAgICAgICAgICAgICAgICAgICBtb3ZlczogbnVsbFxuICAgICAgICAgICAgICAgICAgICB9O1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIC8vIE8oTikgdGltZSwgTyhOKSBtZW1vcnlcbiAgICAgICAgICAgICAgICB2YXIgYUNoaWxkSW5kZXggPSBrZXlJbmRleChhQ2hpbGRyZW4pO1xuICAgICAgICAgICAgICAgIHZhciBhS2V5cyA9IGFDaGlsZEluZGV4LmtleXM7XG4gICAgICAgICAgICAgICAgdmFyIGFGcmVlID0gYUNoaWxkSW5kZXguZnJlZTtcblxuICAgICAgICAgICAgICAgIGlmIChhRnJlZS5sZW5ndGggPT09IGFDaGlsZHJlbi5sZW5ndGgpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGNoaWxkcmVuOiBiQ2hpbGRyZW4sXG4gICAgICAgICAgICAgICAgICAgICAgICBtb3ZlczogbnVsbFxuICAgICAgICAgICAgICAgICAgICB9O1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIC8vIE8oTUFYKE4sIE0pKSBtZW1vcnlcbiAgICAgICAgICAgICAgICB2YXIgbmV3Q2hpbGRyZW4gPSBbXTtcblxuICAgICAgICAgICAgICAgIHZhciBmcmVlSW5kZXggPSAwO1xuICAgICAgICAgICAgICAgIHZhciBmcmVlQ291bnQgPSBiRnJlZS5sZW5ndGg7XG4gICAgICAgICAgICAgICAgdmFyIGRlbGV0ZWRJdGVtcyA9IDA7XG5cbiAgICAgICAgICAgICAgICAvLyBJdGVyYXRlIHRocm91Z2ggYSBhbmQgbWF0Y2ggYSBub2RlIGluIGJcbiAgICAgICAgICAgICAgICAvLyBPKE4pIHRpbWUsXG4gICAgICAgICAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCBhQ2hpbGRyZW4ubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgICAgICAgICAgdmFyIGFJdGVtID0gYUNoaWxkcmVuW2ldO1xuICAgICAgICAgICAgICAgICAgICB2YXIgaXRlbUluZGV4O1xuXG4gICAgICAgICAgICAgICAgICAgIGlmIChhSXRlbS5rZXkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChiS2V5cy5oYXNPd25Qcm9wZXJ0eShhSXRlbS5rZXkpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gTWF0Y2ggdXAgdGhlIG9sZCBrZXlzXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaXRlbUluZGV4ID0gYktleXNbYUl0ZW0ua2V5XTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBuZXdDaGlsZHJlbi5wdXNoKGJDaGlsZHJlbltpdGVtSW5kZXhdKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gUmVtb3ZlIG9sZCBrZXllZCBpdGVtc1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGl0ZW1JbmRleCA9IGkgLSBkZWxldGVkSXRlbXMrKztcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBuZXdDaGlsZHJlbi5wdXNoKG51bGwpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgLy8gTWF0Y2ggdGhlIGl0ZW0gaW4gYSB3aXRoIHRoZSBuZXh0IGZyZWUgaXRlbSBpbiBiXG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoZnJlZUluZGV4IDwgZnJlZUNvdW50KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaXRlbUluZGV4ID0gYkZyZWVbZnJlZUluZGV4KytdO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIG5ld0NoaWxkcmVuLnB1c2goYkNoaWxkcmVuW2l0ZW1JbmRleF0pO1xuICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBUaGVyZSBhcmUgbm8gZnJlZSBpdGVtcyBpbiBiIHRvIG1hdGNoIHdpdGhcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyB0aGUgZnJlZSBpdGVtcyBpbiBhLCBzbyB0aGUgZXh0cmEgZnJlZSBub2Rlc1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIGFyZSBkZWxldGVkLlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGl0ZW1JbmRleCA9IGkgLSBkZWxldGVkSXRlbXMrKztcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBuZXdDaGlsZHJlbi5wdXNoKG51bGwpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgdmFyIGxhc3RGcmVlSW5kZXggPSBmcmVlSW5kZXggPj0gYkZyZWUubGVuZ3RoID8gYkNoaWxkcmVuLmxlbmd0aCA6IGJGcmVlW2ZyZWVJbmRleF07XG5cbiAgICAgICAgICAgICAgICAvLyBJdGVyYXRlIHRocm91Z2ggYiBhbmQgYXBwZW5kIGFueSBuZXcga2V5c1xuICAgICAgICAgICAgICAgIC8vIE8oTSkgdGltZVxuICAgICAgICAgICAgICAgIGZvciAodmFyIGogPSAwOyBqIDwgYkNoaWxkcmVuLmxlbmd0aDsgaisrKSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciBuZXdJdGVtID0gYkNoaWxkcmVuW2pdO1xuXG4gICAgICAgICAgICAgICAgICAgIGlmIChuZXdJdGVtLmtleSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKCFhS2V5cy5oYXNPd25Qcm9wZXJ0eShuZXdJdGVtLmtleSkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBBZGQgYW55IG5ldyBrZXllZCBpdGVtc1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIFdlIGFyZSBhZGRpbmcgbmV3IGl0ZW1zIHRvIHRoZSBlbmQgYW5kIHRoZW4gc29ydGluZyB0aGVtXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gaW4gcGxhY2UuIEluIGZ1dHVyZSB3ZSBzaG91bGQgaW5zZXJ0IG5ldyBpdGVtcyBpbiBwbGFjZS5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBuZXdDaGlsZHJlbi5wdXNoKG5ld0l0ZW0pO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKGogPj0gbGFzdEZyZWVJbmRleCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgLy8gQWRkIGFueSBsZWZ0b3ZlciBub24ta2V5ZWQgaXRlbXNcbiAgICAgICAgICAgICAgICAgICAgICAgIG5ld0NoaWxkcmVuLnB1c2gobmV3SXRlbSk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICB2YXIgc2ltdWxhdGUgPSBuZXdDaGlsZHJlbi5zbGljZSgpO1xuICAgICAgICAgICAgICAgIHZhciBzaW11bGF0ZUluZGV4ID0gMDtcbiAgICAgICAgICAgICAgICB2YXIgcmVtb3ZlcyA9IFtdO1xuICAgICAgICAgICAgICAgIHZhciBpbnNlcnRzID0gW107XG4gICAgICAgICAgICAgICAgdmFyIHNpbXVsYXRlSXRlbTtcblxuICAgICAgICAgICAgICAgIGZvciAodmFyIGsgPSAwOyBrIDwgYkNoaWxkcmVuLmxlbmd0aDspIHtcbiAgICAgICAgICAgICAgICAgICAgdmFyIHdhbnRlZEl0ZW0gPSBiQ2hpbGRyZW5ba107XG4gICAgICAgICAgICAgICAgICAgIHNpbXVsYXRlSXRlbSA9IHNpbXVsYXRlW3NpbXVsYXRlSW5kZXhdO1xuXG4gICAgICAgICAgICAgICAgICAgIC8vIHJlbW92ZSBpdGVtc1xuICAgICAgICAgICAgICAgICAgICB3aGlsZSAoc2ltdWxhdGVJdGVtID09PSBudWxsICYmIHNpbXVsYXRlLmxlbmd0aCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgcmVtb3Zlcy5wdXNoKHJlbW92ZShzaW11bGF0ZSwgc2ltdWxhdGVJbmRleCwgbnVsbCkpO1xuICAgICAgICAgICAgICAgICAgICAgICAgc2ltdWxhdGVJdGVtID0gc2ltdWxhdGVbc2ltdWxhdGVJbmRleF07XG4gICAgICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgICAgICBpZiAoIXNpbXVsYXRlSXRlbSB8fCBzaW11bGF0ZUl0ZW0ua2V5ICE9PSB3YW50ZWRJdGVtLmtleSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgLy8gaWYgd2UgbmVlZCBhIGtleSBpbiB0aGlzIHBvc2l0aW9uLi4uXG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAod2FudGVkSXRlbS5rZXkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoc2ltdWxhdGVJdGVtICYmIHNpbXVsYXRlSXRlbS5rZXkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gaWYgYW4gaW5zZXJ0IGRvZXNuJ3QgcHV0IHRoaXMga2V5IGluIHBsYWNlLCBpdCBuZWVkcyB0byBtb3ZlXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChiS2V5c1tzaW11bGF0ZUl0ZW0ua2V5XSAhPT0gayArIDEpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlbW92ZXMucHVzaChyZW1vdmUoc2ltdWxhdGUsIHNpbXVsYXRlSW5kZXgsIHNpbXVsYXRlSXRlbS5rZXkpKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNpbXVsYXRlSXRlbSA9IHNpbXVsYXRlW3NpbXVsYXRlSW5kZXhdO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gaWYgdGhlIHJlbW92ZSBkaWRuJ3QgcHV0IHRoZSB3YW50ZWQgaXRlbSBpbiBwbGFjZSwgd2UgbmVlZCB0byBpbnNlcnQgaXRcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmICghc2ltdWxhdGVJdGVtIHx8IHNpbXVsYXRlSXRlbS5rZXkgIT09IHdhbnRlZEl0ZW0ua2V5KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaW5zZXJ0cy5wdXNoKHsga2V5OiB3YW50ZWRJdGVtLmtleSwgdG86IGsgfSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBpdGVtcyBhcmUgbWF0Y2hpbmcsIHNvIHNraXAgYWhlYWRcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNpbXVsYXRlSW5kZXgrKztcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGluc2VydHMucHVzaCh7IGtleTogd2FudGVkSXRlbS5rZXksIHRvOiBrIH0pO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaW5zZXJ0cy5wdXNoKHsga2V5OiB3YW50ZWRJdGVtLmtleSwgdG86IGsgfSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGsrKztcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIGEga2V5IGluIHNpbXVsYXRlIGhhcyBubyBtYXRjaGluZyB3YW50ZWQga2V5LCByZW1vdmUgaXRcbiAgICAgICAgICAgICAgICAgICAgICAgIGVsc2UgaWYgKHNpbXVsYXRlSXRlbSAmJiBzaW11bGF0ZUl0ZW0ua2V5KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcmVtb3Zlcy5wdXNoKHJlbW92ZShzaW11bGF0ZSwgc2ltdWxhdGVJbmRleCwgc2ltdWxhdGVJdGVtLmtleSkpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgc2ltdWxhdGVJbmRleCsrO1xuICAgICAgICAgICAgICAgICAgICAgICAgaysrO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgLy8gcmVtb3ZlIGFsbCB0aGUgcmVtYWluaW5nIG5vZGVzIGZyb20gc2ltdWxhdGVcbiAgICAgICAgICAgICAgICB3aGlsZSAoc2ltdWxhdGVJbmRleCA8IHNpbXVsYXRlLmxlbmd0aCkge1xuICAgICAgICAgICAgICAgICAgICBzaW11bGF0ZUl0ZW0gPSBzaW11bGF0ZVtzaW11bGF0ZUluZGV4XTtcbiAgICAgICAgICAgICAgICAgICAgcmVtb3Zlcy5wdXNoKHJlbW92ZShzaW11bGF0ZSwgc2ltdWxhdGVJbmRleCwgc2ltdWxhdGVJdGVtICYmIHNpbXVsYXRlSXRlbS5rZXkpKTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAvLyBJZiB0aGUgb25seSBtb3ZlcyB3ZSBoYXZlIGFyZSBkZWxldGVzIHRoZW4gd2UgY2FuIGp1c3RcbiAgICAgICAgICAgICAgICAvLyBsZXQgdGhlIGRlbGV0ZSBwYXRjaCByZW1vdmUgdGhlc2UgaXRlbXMuXG4gICAgICAgICAgICAgICAgaWYgKHJlbW92ZXMubGVuZ3RoID09PSBkZWxldGVkSXRlbXMgJiYgIWluc2VydHMubGVuZ3RoKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiB7XG4gICAgICAgICAgICAgICAgICAgICAgICBjaGlsZHJlbjogbmV3Q2hpbGRyZW4sXG4gICAgICAgICAgICAgICAgICAgICAgICBtb3ZlczogbnVsbFxuICAgICAgICAgICAgICAgICAgICB9O1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHJldHVybiB7XG4gICAgICAgICAgICAgICAgICAgIGNoaWxkcmVuOiBuZXdDaGlsZHJlbixcbiAgICAgICAgICAgICAgICAgICAgbW92ZXM6IHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJlbW92ZXM6IHJlbW92ZXMsXG4gICAgICAgICAgICAgICAgICAgICAgICBpbnNlcnRzOiBpbnNlcnRzXG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9O1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBmdW5jdGlvbiByZW1vdmUoYXJyLCBpbmRleCwga2V5KSB7XG4gICAgICAgICAgICAgICAgYXJyLnNwbGljZShpbmRleCwgMSk7XG5cbiAgICAgICAgICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgICAgICAgICBmcm9tOiBpbmRleCxcbiAgICAgICAgICAgICAgICAgICAga2V5OiBrZXlcbiAgICAgICAgICAgICAgICB9O1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBmdW5jdGlvbiBrZXlJbmRleChjaGlsZHJlbikge1xuICAgICAgICAgICAgICAgIHZhciBrZXlzID0ge307XG4gICAgICAgICAgICAgICAgdmFyIGZyZWUgPSBbXTtcbiAgICAgICAgICAgICAgICB2YXIgbGVuZ3RoID0gY2hpbGRyZW4ubGVuZ3RoO1xuXG4gICAgICAgICAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCBsZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgICAgICAgICB2YXIgY2hpbGQgPSBjaGlsZHJlbltpXTtcblxuICAgICAgICAgICAgICAgICAgICBpZiAoY2hpbGQua2V5KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBrZXlzW2NoaWxkLmtleV0gPSBpO1xuICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgZnJlZS5wdXNoKGkpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgICAgICAgICAga2V5czoga2V5cywgLy8gQSBoYXNoIG9mIGtleSBuYW1lIHRvIGluZGV4XG4gICAgICAgICAgICAgICAgICAgIGZyZWU6IGZyZWUgLy8gQW4gYXJyYXkgb2YgdW5rZXllZCBpdGVtIGluZGljZXNcbiAgICAgICAgICAgICAgICB9O1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBmdW5jdGlvbiBhcHBlbmRQYXRjaChhcHBseSwgcGF0Y2gpIHtcbiAgICAgICAgICAgICAgICBpZiAoYXBwbHkpIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKGlzQXJyYXkoYXBwbHkpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBhcHBseS5wdXNoKHBhdGNoKTtcbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGFwcGx5ID0gW2FwcGx5LCBwYXRjaF07XG4gICAgICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgICAgICByZXR1cm4gYXBwbHk7XG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHBhdGNoO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgfSwgeyBcIi4uL3Zub2RlL2hhbmRsZS10aHVua1wiOiAyNCwgXCIuLi92bm9kZS9pcy10aHVua1wiOiAyNSwgXCIuLi92bm9kZS9pcy12bm9kZVwiOiAyNywgXCIuLi92bm9kZS9pcy12dGV4dFwiOiAyOCwgXCIuLi92bm9kZS9pcy13aWRnZXRcIjogMjksIFwiLi4vdm5vZGUvdnBhdGNoXCI6IDMyLCBcIi4vZGlmZi1wcm9wc1wiOiAzNCwgXCJ4LWlzLWFycmF5XCI6IDEyIH1dIH0sIHt9LCBbNF0pKDQpO1xufSk7XG5cbmNvbnN0IENvcmUgPSBDO1xuXG5leHBvcnQgeyBDb3JlLCBLZXJuZWwsIEVudW0sIExpc3QsIEtleXdvcmQsIGJpdHdpc2UgYXMgQml0d2lzZSwgbWFwIGFzIE1hcCwgbWFwX3NldCBhcyBNYXBTZXQsIFZpcnR1YWxET00gfTsiXSwiZmlsZSI6IkVsaXhpci5qcyIsInNvdXJjZVJvb3QiOiIvc291cmNlLyJ9 \ No newline at end of file From 21fb2259275b37702718bbf95a6de41cdffca146 Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Mon, 28 Dec 2015 20:32:38 -0600 Subject: [PATCH 097/860] Moved the special_forms js module inside of core --- lib/elixir_script/translator/primitive.ex | 13 +- lib/elixir_script/translator/try.ex | 2 +- priv/Elixir.js | 711 ++++++++++----------- src/javascript/lib/core.js | 4 +- src/javascript/lib/core/special_forms.js | 136 ++++ src/javascript/lib/kernel.js | 4 +- src/javascript/lib/list.js | 34 +- src/javascript/lib/map.js | 49 +- src/javascript/lib/map_set.js | 13 +- src/javascript/tests/bit_string.spec.js | 11 +- src/javascript/tests/case.spec.js | 6 +- src/javascript/tests/cond.spec.js | 4 +- src/javascript/tests/enum.spec.js | 8 - src/javascript/tests/for.spec.js | 10 +- src/javascript/tests/kernel.spec.js | 8 +- src/javascript/tests/list.spec.js | 14 +- src/javascript/tests/map.spec.js | 6 +- src/javascript/tests/special_forms.spec.js | 2 +- src/javascript/tests/try.spec.js | 3 +- test/elixir_script_test.exs | 2 +- test/lib/js_test.exs | 2 +- test/lib/kernel_test.exs | 2 +- test/translator/assignment_test.exs | 20 +- test/translator/bitstring_test.exs | 24 +- test/translator/bug_test.exs | 6 +- test/translator/capture_test.exs | 4 +- test/translator/case_test.exs | 2 +- test/translator/cond_test.exs | 12 +- test/translator/defmodule_test.exs | 4 +- test/translator/for_test.exs | 34 +- test/translator/function_test.exs | 20 +- test/translator/kernel_test.exs | 8 +- test/translator/list_test.exs | 12 +- test/translator/map_test.exs | 12 +- test/translator/protocol_test.exs | 2 +- test/translator/quote_test.exs | 30 +- test/translator/string_test.exs | 6 +- test/translator/struct_test.exs | 10 +- test/translator/try_test.exs | 20 +- test/translator/tuple_test.exs | 10 +- 40 files changed, 688 insertions(+), 592 deletions(-) create mode 100644 src/javascript/lib/core/special_forms.js delete mode 100644 src/javascript/tests/enum.spec.js diff --git a/lib/elixir_script/translator/primitive.ex b/lib/elixir_script/translator/primitive.ex index 8736dd6f..0fa79249 100644 --- a/lib/elixir_script/translator/primitive.ex +++ b/lib/elixir_script/translator/primitive.ex @@ -9,7 +9,7 @@ defmodule ElixirScript.Translator.Primitive do JS.member_expression( JS.identifier("Elixir"), JS.member_expression( - JS.identifier("Kernel"), + JS.identifier("Core"), JS.identifier("SpecialForms") ) ) @@ -21,10 +21,10 @@ defmodule ElixirScript.Translator.Primitive do JS.identifier("Elixir"), JS.member_expression( JS.identifier("Core"), - JS.identifier("Functions") + JS.identifier("SpecialForms") ) ), - JS.identifier("new_tuple") + JS.identifier("tuple") ) end @@ -42,9 +42,12 @@ defmodule ElixirScript.Translator.Primitive do JS.member_expression( JS.member_expression( JS.identifier("Elixir"), - JS.identifier("Core") + JS.member_expression( + JS.identifier("Core"), + JS.identifier("SpecialForms") + ) ), - JS.identifier("List") + JS.identifier("list") ) end diff --git a/lib/elixir_script/translator/try.ex b/lib/elixir_script/translator/try.ex index ee9bf1e9..3568427a 100644 --- a/lib/elixir_script/translator/try.ex +++ b/lib/elixir_script/translator/try.ex @@ -92,7 +92,7 @@ defmodule ElixirScript.Translator.Try do defp process_after_block(after_block, env) do { translated_body, _ } = Function.prepare_function_body(after_block, env) translated_body = JS.block_statement(translated_body) - + JS.function_expression([], [], translated_body) end diff --git a/priv/Elixir.js b/priv/Elixir.js index 82c2961a..2f924514 100644 --- a/priv/Elixir.js +++ b/priv/Elixir.js @@ -50,7 +50,7 @@ class Process { } } -class Tuple { +class Tuple$1 { constructor(...args) { this.values = Object.freeze(args); @@ -1082,7 +1082,7 @@ function is_number$1(x) { } function is_tuple$1(x) { - return x instanceof Tuple; + return x instanceof Tuple$1; } function is_pid$1(x) { @@ -1130,7 +1130,7 @@ function apply$1(...args) { } function new_tuple(...args) { - return new Tuple(...args); + return new Tuple$1(...args); } function duplicate(data, size) { @@ -1281,385 +1281,151 @@ var Functions = { b64EncodeUnicode }; -Functions.get_global().processes = Functions.get_global().processes || new ProcessSystem(); - - - -var C = Object.freeze({ - ProcessSystem: ProcessSystem, - Tuple: Tuple, - PID: PID, - BitString: BitString, - Patterns: Patterns, - Integer: Integer, - Float: Float, - Functions: Functions, - List: List$1 -}); - -let Enum = { - - all__qmark__: function (collection, fun = x => x) { - for (let elem of collection) { - if (!fun(elem)) { - return false; - } - } - - return true; - }, - - any__qmark__: function (collection, fun = x => x) { - for (let elem of collection) { - if (fun(elem)) { - return true; - } - } - - return false; - }, - - at: function (collection, n, the_default = null) { - if (n > this.count(collection) || n < 0) { - return the_default; - } - - return collection[n]; - }, - - concat: function (...enumables) { - return enumables[0].concat(enumables[1]); - }, - - count: function (collection, fun = null) { - if (fun == null) { - return collection.length; - } else { - return collection.filter(fun).length; - } - }, - - drop: function (collection, count) { - return collection.slice(count); - }, - - drop_while: function (collection, fun) { - let count = 0; - - for (let elem of collection) { - if (fun(elem)) { - count = count + 1; - } else { - break; - } - } - - return collection.slice(count); - }, - - each: function (collection, fun) { - for (let elem of collection) { - fun(elem); - } - }, - - empty__qmark__: function (collection) { - return collection.length === 0; - }, - - fetch: function (collection, n) { - if (Kernel.is_list(collection)) { - if (n < this.count(collection) && n >= 0) { - return new Tuple(Symbol.for('ok'), collection[n]); - } else { - return Symbol.for('error'); - } - } - - throw new Error('collection is not an Enumerable'); - }, +function list(...args) { + return Object.freeze(args); +} - fetch__emark__: function (collection, n) { - if (Kernel.is_list(collection)) { - if (n < this.count(collection) && n >= 0) { - return collection[n]; - } else { - throw new Error('out of bounds error'); - } - } +function bitstring(...args) { + return new BitString(...args); +} - throw new Error('collection is not an Enumerable'); - }, +function tuple(...args) { + return new Tuple(...args); +} - filter: function (collection, fun) { - let result = []; +function _case(condition, clauses) { + return Patterns.defmatch(...clauses)(condition); +} - for (let elem of collection) { - if (fun(elem)) { - result.push(elem); - } +function cond(clauses) { + for (let clause of clauses) { + if (clause[0]) { + return clause[1](); } + } - return result; - }, - - filter_map: function (collection, filter, mapper) { - return Enum.map(Enum.filter(collection, filter), mapper); - }, + throw new Error(); +} - find: function (collection, if_none = null, fun) { - for (let elem of collection) { - if (fun(elem)) { - return elem; - } - } +function map$1(obj) { + return Object.freeze(obj); +} - return if_none; - }, +function map_update(map, values) { + return Object.freeze(Object.assign(Object.create(map.constructor.prototype), map, values)); +} - into: function (collection, list) { - return list.concat(collection); - }, +function _for(collections, fun, filter = () => true, into = [], previousValues = []) { + let pattern = collections[0][0]; + let collection = collections[0][1]; - map: function (collection, fun) { - let result = []; + if (collections.length === 1) { for (let elem of collection) { - result.push(fun(elem)); - } - - return result; - }, - - map_reduce: function (collection, acc, fun) { - let mapped = List$1(); - let the_acc = acc; - - for (var i = 0; i < this.count(collection); i++) { - let tuple = fun(collection[i], the_acc); - - the_acc = tuple.get(1); - mapped = List$1(...mapped.concat([tuple.get(0)])); - } - - return new Tuple(mapped, the_acc); - }, - - member__qmark__: function (collection, value) { - return collection.includes(value); - }, - - reduce: function (collection, acc, fun) { - let the_acc = acc; - - for (var i = 0; i < this.count(collection); i++) { - let tuple = fun(collection[i], the_acc); - - the_acc = tuple.get(1); - } - - return the_acc; - }, - - take: function (collection, count) { - return collection.slice(0, count); - }, - - take_every: function (collection, nth) { - let result = []; - let index = 0; + let r = Patterns.match_no_throw(pattern, elem); + let args = previousValues.concat(r); - for (let elem of collection) { - if (index % nth === 0) { - result.push(elem); + if (r && filter.apply(this, args)) { + into = Enum.into([fun.apply(this, args)], into); } } - return List$1(...result); - }, - - take_while: function (collection, fun) { - let count = 0; + return into; + } else { + let _into = []; for (let elem of collection) { - if (fun(elem)) { - count = count + 1; - } else { - break; + let r = Patterns.match_no_throw(pattern, elem); + if (r) { + _into = Enum.into(this._for(collections.slice(1), fun, filter, _into, previousValues.concat(r)), into); } } - return collection.slice(0, count); - }, - - to_list: function (collection) { - return collection; + return _into; } -}; - -let SpecialForms$1 = { - - atom: function (_value) { - return Symbol.for(_value); - }, - - list: function (...args) { - return Object.freeze(args); - }, - - bitstring: function (...args) { - return new BitString(...args); - }, - - bound: function (_var) { - return Patterns.bound(_var); - }, - - _case: function (condition, clauses) { - return Patterns.defmatch(...clauses)(condition); - }, - - cond: function (clauses) { - for (let clause of clauses) { - if (clause[0]) { - return clause[1](); - } - } - - throw new Error(); - }, - - fn: function (clauses) { - return Patterns.defmatch(clauses); - }, - - map: function (obj) { - return Object.freeze(obj); - }, - - map_update: function (map, values) { - return Object.freeze(Object.assign(Object.create(map.constructor.prototype), map, values)); - }, - - _for: function (collections, fun, filter = () => true, into = [], previousValues = []) { - let pattern = collections[0][0]; - let collection = collections[0][1]; - - if (collections.length === 1) { +} - for (let elem of collection) { - let r = Patterns.match_no_throw(pattern, elem); - let args = previousValues.concat(r); +function _try(do_fun, rescue_function, catch_fun, else_function, after_function) { + let result = null; - if (r && filter.apply(this, args)) { - into = Enum.into([fun.apply(this, args)], into); - } - } - - return into; - } else { - let _into = []; + try { + result = do_fun(); + } catch (e) { + let ex_result = null; - for (let elem of collection) { - let r = Patterns.match_no_throw(pattern, elem); - if (r) { - _into = Enum.into(this._for(collections.slice(1), fun, filter, _into, previousValues.concat(r)), into); + if (rescue_function) { + try { + ex_result = rescue_function(e); + return ex_result; + } catch (ex) { + if (ex instanceof Patterns.MatchError) { + throw ex; } } - - return _into; } - }, - receive: function (receive_fun, timeout_in_ms = null, timeout_fn = time => true) { - if (timeout_in_ms == null || timeout_in_ms === System.for('infinity')) { - while (true) { - if (self.mailbox.length !== 0) { - let message = self.mailbox[0]; - self.mailbox = self.mailbox.slice(1); - return receive_fun(message); - } - } - } else if (timeout_in_ms === 0) { - if (self.mailbox.length !== 0) { - let message = self.mailbox[0]; - self.mailbox = self.mailbox.slice(1); - return receive_fun(message); - } else { - return null; - } - } else { - let now = Date.now(); - while (Date.now() < now + timeout_in_ms) { - if (self.mailbox.length !== 0) { - let message = self.mailbox[0]; - self.mailbox = self.mailbox.slice(1); - return receive_fun(message); + if (catch_fun) { + try { + ex_result = catch_fun(e); + return ex_result; + } catch (ex) { + if (ex instanceof Patterns.MatchError) { + throw ex; } } - - return timeout_fn(timeout_in_ms); } - }, - - tuple: function (...args) { - return new Tuple(...args); - }, - _try: function (do_fun, rescue_function, catch_fun, else_function, after_function) { - let result = null; + throw e; + } finally { + if (after_function) { + after_function(); + } + } + if (else_function) { try { - result = do_fun(); - } catch (e) { - let ex_result = null; - - if (rescue_function) { - try { - ex_result = rescue_function(e); - return ex_result; - } catch (ex) { - if (ex instanceof Patterns.MatchError) { - throw ex; - } - } - } - - if (catch_fun) { - try { - ex_result = catch_fun(e); - return ex_result; - } catch (ex) { - if (ex instanceof Patterns.MatchError) { - throw ex; - } - } + return else_function(result); + } catch (ex) { + if (ex instanceof Patterns.MatchError) { + throw new Error('No Match Found in Else'); } - throw e; - } finally { - if (after_function) { - after_function(); - } - } - - if (else_function) { - try { - return else_function(result); - } catch (ex) { - if (ex instanceof Patterns.MatchError) { - throw new Error('No Match Found in Else'); - } - - throw ex; - } - } else { - return result; + throw ex; } + } else { + return result; } +} +var SpecialForms$1 = { + list, + bitstring, + tuple, + _case, + cond, + map: map$1, + map_update, + _for, + _try }; +Functions.get_global().processes = Functions.get_global().processes || new ProcessSystem(); + + + +var C = Object.freeze({ + ProcessSystem: ProcessSystem, + Tuple: Tuple$1, + PID: PID, + BitString: BitString, + Patterns: Patterns, + Integer: Integer, + Float: Float, + Functions: Functions, + List: List$1, + SpecialForms: SpecialForms$1 +}); + function tl(list) { return SpecialForms$1.list(...list.slice(1)); } @@ -1709,7 +1475,7 @@ function is_number(x) { } function is_tuple(x) { - return x instanceof Tuple; + return x instanceof Tuple$1; } function length(x) { @@ -1805,7 +1571,6 @@ function match__qmark__(pattern, expr, guard = () => true) { } var Kernel = { - SpecialForms: SpecialForms$1, tl, hd, is_nil, @@ -1838,6 +1603,206 @@ var Kernel = { match__qmark__ }; +let Enum$1 = { + + all__qmark__: function (collection, fun = x => x) { + for (let elem of collection) { + if (!fun(elem)) { + return false; + } + } + + return true; + }, + + any__qmark__: function (collection, fun = x => x) { + for (let elem of collection) { + if (fun(elem)) { + return true; + } + } + + return false; + }, + + at: function (collection, n, the_default = null) { + if (n > this.count(collection) || n < 0) { + return the_default; + } + + return collection[n]; + }, + + concat: function (...enumables) { + return enumables[0].concat(enumables[1]); + }, + + count: function (collection, fun = null) { + if (fun == null) { + return collection.length; + } else { + return collection.filter(fun).length; + } + }, + + drop: function (collection, count) { + return collection.slice(count); + }, + + drop_while: function (collection, fun) { + let count = 0; + + for (let elem of collection) { + if (fun(elem)) { + count = count + 1; + } else { + break; + } + } + + return collection.slice(count); + }, + + each: function (collection, fun) { + for (let elem of collection) { + fun(elem); + } + }, + + empty__qmark__: function (collection) { + return collection.length === 0; + }, + + fetch: function (collection, n) { + if (Kernel.is_list(collection)) { + if (n < this.count(collection) && n >= 0) { + return new Tuple$1(Symbol.for('ok'), collection[n]); + } else { + return Symbol.for('error'); + } + } + + throw new Error('collection is not an Enumerable'); + }, + + fetch__emark__: function (collection, n) { + if (Kernel.is_list(collection)) { + if (n < this.count(collection) && n >= 0) { + return collection[n]; + } else { + throw new Error('out of bounds error'); + } + } + + throw new Error('collection is not an Enumerable'); + }, + + filter: function (collection, fun) { + let result = []; + + for (let elem of collection) { + if (fun(elem)) { + result.push(elem); + } + } + + return result; + }, + + filter_map: function (collection, filter, mapper) { + return Enum$1.map(Enum$1.filter(collection, filter), mapper); + }, + + find: function (collection, if_none = null, fun) { + for (let elem of collection) { + if (fun(elem)) { + return elem; + } + } + + return if_none; + }, + + into: function (collection, list) { + return list.concat(collection); + }, + + map: function (collection, fun) { + let result = []; + + for (let elem of collection) { + result.push(fun(elem)); + } + + return result; + }, + + map_reduce: function (collection, acc, fun) { + let mapped = List$1(); + let the_acc = acc; + + for (var i = 0; i < this.count(collection); i++) { + let tuple = fun(collection[i], the_acc); + + the_acc = tuple.get(1); + mapped = List$1(...mapped.concat([tuple.get(0)])); + } + + return new Tuple$1(mapped, the_acc); + }, + + member__qmark__: function (collection, value) { + return collection.includes(value); + }, + + reduce: function (collection, acc, fun) { + let the_acc = acc; + + for (var i = 0; i < this.count(collection); i++) { + let tuple = fun(collection[i], the_acc); + + the_acc = tuple.get(1); + } + + return the_acc; + }, + + take: function (collection, count) { + return collection.slice(0, count); + }, + + take_every: function (collection, nth) { + let result = []; + let index = 0; + + for (let elem of collection) { + if (index % nth === 0) { + result.push(elem); + } + } + + return List$1(...result); + }, + + take_while: function (collection, fun) { + let count = 0; + + for (let elem of collection) { + if (fun(elem)) { + count = count + 1; + } else { + break; + } + } + + return collection.slice(0, count); + }, + + to_list: function (collection) { + return collection; + } +}; + let List = {}; List.delete = function (list, item) { @@ -1853,7 +1818,7 @@ List.delete = function (list, item) { } } - return List$1(...new_value); + return SpecialForms$1.list(...new_value); }; List.delete_at = function (list, index) { @@ -1865,7 +1830,7 @@ List.delete_at = function (list, index) { } } - return List$1(...new_value); + return SpecialForms$1.list(...new_value); }; List.duplicate = function (elem, n) { @@ -1875,14 +1840,14 @@ List.duplicate = function (elem, n) { new_value.push(elem); } - return List$1(...new_value); + return SpecialForms$1.list(...new_value); }; List.first = function (list) { return list[0]; }; -List.flatten = function (list, tail = List$1()) { +List.flatten = function (list, tail = SpecialForms$1.list()) { let new_value = []; for (let x of list) { @@ -1895,7 +1860,7 @@ List.flatten = function (list, tail = List$1()) { new_value = new_value.concat(tail); - return List$1(...new_value); + return SpecialForms$1.list(...new_value); }; List.foldl = function (list, acc, func) { @@ -1924,7 +1889,7 @@ List.insert_at = function (list, index, value) { } } - return List$1(...new_value); + return SpecialForms$1.list(...new_value); }; List.keydelete = function (list, key, position) { @@ -1936,7 +1901,7 @@ List.keydelete = function (list, key, position) { } } - return List$1(...new_list); + return SpecialForms$1.list(...new_list); }; List.keyfind = function (list, key, position, _default = null) { @@ -1972,7 +1937,7 @@ List.keyreplace = function (list, key, position, new_tuple) { } } - return List$1(...new_list); + return SpecialForms$1.list(...new_list); }; List.keysort = function (list, position) { @@ -2002,7 +1967,7 @@ List.keysort = function (list, position) { } }); - return List$1(...new_list); + return SpecialForms$1.list(...new_list); }; List.keystore = function (list, key, position, new_tuple) { @@ -2022,7 +1987,7 @@ List.keystore = function (list, key, position, new_tuple) { new_list.push(new_tuple); } - return List$1(...new_list); + return SpecialForms$1.list(...new_list); }; List.last = function (list) { @@ -2040,7 +2005,7 @@ List.replace_at = function (list, index, value) { } } - return List$1(...new_value); + return SpecialForms$1.list(...new_value); }; List.update_at = function (list, index, fun) { @@ -2061,15 +2026,15 @@ List.wrap = function (list) { if (Kernel.is_list(list)) { return list; } else if (list == null) { - return List$1(); + return SpecialForms$1.list(); } else { - return List$1(list); + return SpecialForms$1.list(list); } }; List.zip = function (list_of_lists) { if (list_of_lists.length === 0) { - return List$1(); + return SpecialForms$1.list(); } let new_value = []; @@ -2087,22 +2052,22 @@ List.zip = function (list_of_lists) { current_value.push(list_of_lists[j][i]); } - new_value.push(new Tuple(...current_value)); + new_value.push(new Tuple$1(...current_value)); } - return List$1(...new_value); + return SpecialForms$1.list(...new_value); }; List.to_tuple = function (list) { - return new Tuple(...list); + return new Tuple$1(...list); }; List.append = function (list, value) { - return List$1(...list.concat([value])); + return SpecialForms$1.list(...list.concat([value])); }; List.prepend = function (list, value) { - return List$1(...[value].concat(list)); + return SpecialForms$1.list(...[value].concat(list)); }; List.concat = function (left, right) { @@ -2181,7 +2146,7 @@ function to_list(map) { let list = []; for (let key of map_keys) { - list.push(new Tuple(key, map[key])); + list.push(new Tuple$1(key, map[key])); } return List$1(...list); @@ -2200,7 +2165,7 @@ function values(map) { function from_struct(struct) { let map = Object.assign({}, struct); - delete map[Symbol.for('__struct__')]; + delete map[Symbol.for("__struct__")]; return SpecialForms$1.map(map); } @@ -2222,15 +2187,15 @@ function fetch__emark__(map, key) { return map[key]; } - throw new Error('Key not found.'); + throw new Error("Key not found."); } function fetch(map, key) { if (key in map) { - return new Tuple(Symbol.for('ok'), map[key]); + return new Tuple$1(Symbol.for("ok"), map[key]); } - return Symbol.for('error'); + return Symbol.for("error"); } function has_key__qmark__(map, key) { @@ -2249,7 +2214,7 @@ function split(map, keys) { } } - return new Tuple(SpecialForms$1.map(split1), SpecialForms$1.map(split2)); + return new Tuple$1(SpecialForms$1.map(split1), SpecialForms$1.map(split2)); } function take(map, keys) { @@ -2311,26 +2276,26 @@ function get_and_update(map, key, fun) { function pop_lazy(map, key, fun) { if (!key in map) { - return new Tuple(fun(), map); + return new Tuple$1(fun(), map); } let new_map = Object.assign({}, map); let value = fun(new_map[key]); delete new_map[key]; - return new Tuple(value, new_map); + return new Tuple$1(value, new_map); } function pop(map, key, _default = null) { if (!key in map) { - return new Tuple(_default, map); + return new Tuple$1(_default, map); } let new_map = Object.assign({}, map); let value = new_map[key]; delete new_map[key]; - return new Tuple(value, new_map); + return new Tuple$1(value, new_map); } function get_lazy(map, key, fun) { @@ -2358,7 +2323,7 @@ function put(map, key, val) { function update__emark__(map, key, fun) { if (!key in map) { - throw new Error('Key not found'); + throw new Error("Key not found"); } let new_map = Object({}, map); @@ -4125,4 +4090,4 @@ let VirtualDOM = (function (e) { const Core = C; export { Core, Kernel, Enum, List, Keyword, bitwise as Bitwise, map as Map, map_set as MapSet, VirtualDOM }; -//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiIiwic291cmNlcyI6WyJFbGl4aXIuanMiXSwic291cmNlc0NvbnRlbnQiOlsiLyogQGZsb3cgKi9cblxuY2xhc3MgTWFpbGJveCB7XG5cbiAgY29uc3RydWN0b3IoKSB7XG4gICAgdGhpcy5tZXNzYWdlcyA9IFtdO1xuICB9XG5cbiAgZGVsaXZlcihtZXNzYWdlKSB7XG4gICAgdGhpcy5tZXNzYWdlcy5wdXNoKG1lc3NhZ2UpO1xuICAgIHJldHVybiBtZXNzYWdlO1xuICB9XG5cbiAgZ2V0KCkge1xuICAgIHJldHVybiB0aGlzLm1lc3NhZ2VzO1xuICB9XG5cbiAgaXNFbXB0eSgpIHtcbiAgICByZXR1cm4gdGhpcy5tZXNzYWdlcy5sZW5ndGggPT09IDA7XG4gIH1cblxuICByZW1vdmVBdChpbmRleCkge1xuICAgIHRoaXMubWVzc2FnZXMuc3BsaWNlKGluZGV4LCAxKTtcbiAgfVxufVxuXG52YXIgU3RhdGVzID0ge1xuICBOT1JNQUw6IFN5bWJvbC5mb3IoXCJub3JtYWxcIiksXG4gIEtJTEw6IFN5bWJvbC5mb3IoXCJraWxsXCIpLFxuICBTVVNQRU5EOiBTeW1ib2wuZm9yKFwic3VzcGVuZFwiKSxcbiAgQ09OVElOVUU6IFN5bWJvbC5mb3IoXCJjb250aW51ZVwiKSxcbiAgUkVDRUlWRTogU3ltYm9sLmZvcihcInJlY2VpdmVcIiksXG4gIFNFTkQ6IFN5bWJvbC5mb3IoXCJzZW5kXCIpLFxuICBTTEVFUElORzogU3ltYm9sLmZvcihcInNsZWVwaW5nXCIpLFxuICBSVU5OSU5HOiBTeW1ib2wuZm9yKFwicnVubmluZ1wiKSxcbiAgU1VTUEVOREVEOiBTeW1ib2wuZm9yKFwic3VzcGVuZGVkXCIpLFxuICBTVE9QUEVEOiBTeW1ib2wuZm9yKFwic3RvcHBlZFwiKSxcbiAgU0xFRVA6IFN5bWJvbC5mb3IoXCJzbGVlcFwiKSxcbiAgRVhJVDogU3ltYm9sLmZvcihcImV4aXRcIiksXG4gIE5PTUFUQ0g6IFN5bWJvbC5mb3IoXCJub19tYXRjaFwiKVxufTtcblxuY2xhc3MgUHJvY2VzcyB7XG5cbiAgY29uc3RydWN0b3IocGlkLCBtYWlsYm94KSB7XG4gICAgdGhpcy5waWQgPSBwaWQ7XG4gICAgdGhpcy5tYWlsYm94ID0gbWFpbGJveDtcbiAgICB0aGlzLnN0YXR1cyA9IFN0YXRlcy5TVE9QUEVEO1xuICAgIHRoaXMuZGljdCA9IHt9O1xuICB9XG59XG5cbmNsYXNzIFR1cGxlIHtcblxuICBjb25zdHJ1Y3RvciguLi5hcmdzKSB7XG4gICAgdGhpcy52YWx1ZXMgPSBPYmplY3QuZnJlZXplKGFyZ3MpO1xuICAgIHRoaXMubGVuZ3RoID0gdGhpcy52YWx1ZXMubGVuZ3RoO1xuICB9XG5cbiAgZ2V0KGluZGV4KSB7XG4gICAgcmV0dXJuIHRoaXMudmFsdWVzW2luZGV4XTtcbiAgfVxuXG4gIGNvdW50KCkge1xuICAgIHJldHVybiB0aGlzLnZhbHVlcy5sZW5ndGg7XG4gIH1cblxuICBbU3ltYm9sLml0ZXJhdG9yXSgpIHtcbiAgICByZXR1cm4gdGhpcy52YWx1ZXNbU3ltYm9sLml0ZXJhdG9yXSgpO1xuICB9XG5cbiAgdG9TdHJpbmcoKSB7XG4gICAgdmFyIGksXG4gICAgICAgIHMgPSBcIlwiO1xuICAgIGZvciAoaSA9IDA7IGkgPCB0aGlzLnZhbHVlcy5sZW5ndGg7IGkrKykge1xuICAgICAgaWYgKHMgIT09IFwiXCIpIHtcbiAgICAgICAgcyArPSBcIiwgXCI7XG4gICAgICB9XG4gICAgICBzICs9IHRoaXMudmFsdWVzW2ldLnRvU3RyaW5nKCk7XG4gICAgfVxuXG4gICAgcmV0dXJuIFwie1wiICsgcyArIFwifVwiO1xuICB9XG5cbn1cblxubGV0IHByb2Nlc3NfY291bnRlciA9IC0xO1xuXG5jbGFzcyBQSUQge1xuICBjb25zdHJ1Y3RvcigpIHtcbiAgICBwcm9jZXNzX2NvdW50ZXIgPSBwcm9jZXNzX2NvdW50ZXIgKyAxO1xuICAgIHRoaXMuaWQgPSBwcm9jZXNzX2NvdW50ZXI7XG4gIH1cblxuICB0b1N0cmluZygpIHtcbiAgICByZXR1cm4gXCJQSUQjPDAuXCIgKyB0aGlzLmlkICsgXCIuMD5cIjtcbiAgfVxufVxuXG5jbGFzcyBJbnRlZ2VyIHt9XG5jbGFzcyBGbG9hdCB7fVxuXG5mdW5jdGlvbiBMaXN0JDEoLi4uYXJncykge1xuICByZXR1cm4gT2JqZWN0LmZyZWV6ZShhcmdzKTtcbn1cblxuY2xhc3MgUHJvY2Vzc1N5c3RlbSB7XG5cbiAgY29uc3RydWN0b3IoKSB7XG4gICAgdGhpcy5waWRzID0gbmV3IE1hcCgpO1xuICAgIHRoaXMubWFpbGJveGVzID0gbmV3IE1hcCgpO1xuICAgIHRoaXMubmFtZXMgPSBuZXcgTWFwKCk7XG4gICAgdGhpcy5saW5rcyA9IG5ldyBNYXAoKTtcblxuICAgIHRoaXMuY3VycmVudF9wcm9jZXNzID0gbnVsbDtcbiAgICB0aGlzLnN1c3BlbmRlZCA9IG5ldyBNYXAoKTtcblxuICAgIHRoaXMubWFpbl9wcm9jZXNzX3BpZCA9IHRoaXMuc3Bhd24oKTtcbiAgICB0aGlzLnNldF9jdXJyZW50KHRoaXMubWFpbl9wcm9jZXNzX3BpZCk7XG4gIH1cblxuICBzcGF3bigpIHtcbiAgICByZXR1cm4gdGhpcy5hZGRfcHJvYyhmYWxzZSkucGlkO1xuICB9XG5cbiAgc3Bhd25fbGluaygpIHtcbiAgICByZXR1cm4gdGhpcy5hZGRfcHJvYyh0cnVlKS5waWQ7XG4gIH1cblxuICBsaW5rKHBpZCkge1xuICAgIHRoaXMubGlua3MuZ2V0KHRoaXMucGlkKCkpLmFkZChwaWQpO1xuICAgIHRoaXMubGlua3MuZ2V0KHBpZCkuYWRkKHRoaXMucGlkKCkpO1xuICB9XG5cbiAgdW5saW5rKHBpZCkge1xuICAgIHRoaXMubGlua3MuZ2V0KHRoaXMucGlkKCkpLmRlbGV0ZShwaWQpO1xuICAgIHRoaXMubGlua3MuZ2V0KHBpZCkuZGVsZXRlKHRoaXMucGlkKCkpO1xuICB9XG5cbiAgc2V0X2N1cnJlbnQoaWQpIHtcbiAgICBsZXQgcGlkID0gdGhpcy5waWRvZihpZCk7XG4gICAgaWYgKHBpZCAhPT0gbnVsbCkge1xuICAgICAgdGhpcy5jdXJyZW50X3Byb2Nlc3MgPSB0aGlzLnBpZHMuZ2V0KHBpZCk7XG4gICAgICB0aGlzLmN1cnJlbnRfcHJvY2Vzcy5zdGF0dXMgPSBTdGF0ZXMuUlVOTklORztcbiAgICB9XG4gIH1cblxuICBhZGRfcHJvYyhsaW5rZWQpIHtcbiAgICBsZXQgbmV3cGlkID0gbmV3IFBJRCgpO1xuICAgIGxldCBtYWlsYm94ID0gbmV3IE1haWxib3goKTtcbiAgICBsZXQgbmV3cHJvYyA9IG5ldyBQcm9jZXNzKG5ld3BpZCwgbWFpbGJveCk7XG5cbiAgICB0aGlzLnBpZHMuc2V0KG5ld3BpZCwgbmV3cHJvYyk7XG4gICAgdGhpcy5tYWlsYm94ZXMuc2V0KG5ld3BpZCwgbWFpbGJveCk7XG4gICAgdGhpcy5saW5rcy5zZXQobmV3cGlkLCBuZXcgU2V0KCkpO1xuXG4gICAgaWYgKGxpbmtlZCkge1xuICAgICAgdGhpcy5saW5rKG5ld3BpZCk7XG4gICAgfVxuXG4gICAgcmV0dXJuIG5ld3Byb2M7XG4gIH1cblxuICByZW1vdmVfcHJvYyhwaWQpIHtcbiAgICB0aGlzLnBpZHMuZGVsZXRlKHBpZCk7XG4gICAgdGhpcy51bnJlZ2lzdGVyKHBpZCk7XG5cbiAgICBpZiAodGhpcy5saW5rcy5oYXMocGlkKSkge1xuICAgICAgZm9yIChsZXQgbGlua3BpZCBvZiB0aGlzLmxpbmtzLmdldChwaWQpKSB7XG4gICAgICAgIHRoaXMubGlua3MuZ2V0KGxpbmtwaWQpLmRlbGV0ZShwaWQpO1xuICAgICAgfVxuXG4gICAgICB0aGlzLmxpbmtzLmRlbGV0ZShwaWQpO1xuICAgIH1cbiAgfVxuXG4gIGV4aXQoaWQpIHtcbiAgICBsZXQgcGlkID0gdGhpcy5waWRvZihpZCk7XG4gICAgdGhpcy5yZW1vdmVfcHJvYyhpZCk7XG4gIH1cblxuICByZWdpc3RlcihuYW1lLCBwaWQpIHtcbiAgICBpZiAoIXRoaXMubmFtZXMuaGFzKG5hbWUpKSB7XG4gICAgICB0aGlzLm5hbWVzLnNldChuYW1lLCBwaWQpO1xuICAgICAgcmV0dXJuIG5hbWU7XG4gICAgfSBlbHNlIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcihcIk5hbWUgaXMgYWxyZWFkeSByZWdpc3RlcmVkIHRvIGFub3RoZXIgcHJvY2Vzc1wiKTtcbiAgICB9XG4gIH1cblxuICByZWdpc3RlcmVkKG5hbWUpIHtcbiAgICByZXR1cm4gdGhpcy5uYW1lcy5oYXMobmFtZSkgPyB0aGlzLm5hbWVzLmdldChuYW1lKSA6IG51bGw7XG4gIH1cblxuICB1bnJlZ2lzdGVyKHBpZCkge1xuICAgIGZvciAobGV0IG5hbWUgb2YgdGhpcy5uYW1lcy5rZXlzKCkpIHtcbiAgICAgIGlmICh0aGlzLm5hbWVzLmhhcyhuYW1lKSAmJiB0aGlzLm5hbWVzLmdldChuYW1lKSA9PT0gcGlkKSB7XG4gICAgICAgIHRoaXMubmFtZXMuZGVsZXRlKG5hbWUpO1xuICAgICAgfVxuICAgIH1cbiAgfVxuXG4gIHBpZCgpIHtcbiAgICByZXR1cm4gdGhpcy5jdXJyZW50X3Byb2Nlc3MucGlkO1xuICB9XG5cbiAgcGlkb2YoaWQpIHtcbiAgICBpZiAoaWQgaW5zdGFuY2VvZiBQSUQpIHtcbiAgICAgIHJldHVybiB0aGlzLnBpZHMuaGFzKGlkKSA/IGlkIDogbnVsbDtcbiAgICB9IGVsc2UgaWYgKGlkIGluc3RhbmNlb2YgUHJvY2Vzcykge1xuICAgICAgcmV0dXJuIGlkLnBpZDtcbiAgICB9IGVsc2Uge1xuICAgICAgbGV0IHBpZCA9IHRoaXMucmVnaXN0ZXJlZChpZCk7XG4gICAgICBpZiAocGlkID09PSBudWxsKSB0aHJvdyBcIlByb2Nlc3MgbmFtZSBub3QgcmVnaXN0ZXJlZDogXCIgKyBpZCArIFwiIChcIiArIHR5cGVvZiBpZCArIFwiKVwiO1xuICAgICAgcmV0dXJuIHBpZDtcbiAgICB9XG4gIH1cblxuICBwdXQoaWQsIGtleSwgdmFsdWUpIHtcbiAgICBsZXQgcGlkID0gdGhpcy5waWRvZihpZCk7XG4gICAgbGV0IHByb2Nlc3MgPSB0aGlzLnBpZHMuZ2V0KHBpZCk7XG4gICAgcHJvY2Vzcy5kaWN0W2tleV0gPSB2YWx1ZTtcbiAgfVxuXG4gIGdldChpZCwga2V5KSB7XG4gICAgbGV0IHBpZCA9IHRoaXMucGlkb2YoaWQpO1xuICAgIGxldCBwcm9jZXNzID0gdGhpcy5waWRzLmdldChwaWQpO1xuXG4gICAgaWYgKGtleSAhPSBudWxsKSB7XG4gICAgICByZXR1cm4gcHJvY2Vzcy5kaWN0W2tleV07XG4gICAgfSBlbHNlIHtcbiAgICAgIHJldHVybiBwcm9jZXNzLmRpY3Q7XG4gICAgfVxuICB9XG5cbiAgZ2V0X2tleXMoaWQpIHtcbiAgICBsZXQgcGlkID0gdGhpcy5waWRvZihpZCk7XG4gICAgbGV0IHByb2Nlc3MgPSB0aGlzLnBpZHMuZ2V0KHBpZCk7XG5cbiAgICByZXR1cm4gT2JqZWN0LmtleXMocHJvY2Vzcy5kaWN0KTtcbiAgfVxuXG4gIGVyYXNlKGlkLCBrZXkpIHtcbiAgICBsZXQgcGlkID0gdGhpcy5waWRvZihpZCk7XG4gICAgbGV0IHByb2Nlc3MgPSB0aGlzLnBpZHMuZ2V0KHBpZCk7XG5cbiAgICBpZiAoa2V5ICE9IG51bGwpIHtcbiAgICAgIGRlbGV0ZSBwcm9jZXNzLmRpY3Rba2V5XTtcbiAgICB9IGVsc2Uge1xuICAgICAgcHJvY2Vzcy5kaWN0ID0ge307XG4gICAgfVxuICB9XG59XG5cbmNsYXNzIEJpdFN0cmluZyB7XG4gIGNvbnN0cnVjdG9yKC4uLmFyZ3MpIHtcbiAgICB0aGlzLnJhd192YWx1ZSA9IGZ1bmN0aW9uICgpIHtcbiAgICAgIHJldHVybiBPYmplY3QuZnJlZXplKGFyZ3MpO1xuICAgIH07XG5cbiAgICB0aGlzLnZhbHVlID0gT2JqZWN0LmZyZWV6ZSh0aGlzLnByb2Nlc3MoYXJncykpO1xuICB9XG5cbiAgZ2V0KGluZGV4KSB7XG4gICAgcmV0dXJuIHRoaXMudmFsdWVbaW5kZXhdO1xuICB9XG5cbiAgY291bnQoKSB7XG4gICAgcmV0dXJuIHRoaXMudmFsdWUubGVuZ3RoO1xuICB9XG5cbiAgW1N5bWJvbC5pdGVyYXRvcl0oKSB7XG4gICAgcmV0dXJuIHRoaXMudmFsdWVbU3ltYm9sLml0ZXJhdG9yXSgpO1xuICB9XG5cbiAgdG9TdHJpbmcoKSB7XG4gICAgdmFyIGksXG4gICAgICAgIHMgPSBcIlwiO1xuICAgIGZvciAoaSA9IDA7IGkgPCB0aGlzLmNvdW50KCk7IGkrKykge1xuICAgICAgaWYgKHMgIT09IFwiXCIpIHtcbiAgICAgICAgcyArPSBcIiwgXCI7XG4gICAgICB9XG4gICAgICBzICs9IHRoaXNbaV0udG9TdHJpbmcoKTtcbiAgICB9XG5cbiAgICByZXR1cm4gXCI8PFwiICsgcyArIFwiPj5cIjtcbiAgfVxuXG4gIHByb2Nlc3MoKSB7XG4gICAgbGV0IHByb2Nlc3NlZF92YWx1ZXMgPSBbXTtcblxuICAgIHZhciBpO1xuICAgIGZvciAoaSA9IDA7IGkgPCB0aGlzLnJhd192YWx1ZSgpLmxlbmd0aDsgaSsrKSB7XG4gICAgICBsZXQgcHJvY2Vzc2VkX3ZhbHVlID0gdGhpc1tcInByb2Nlc3NfXCIgKyB0aGlzLnJhd192YWx1ZSgpW2ldLnR5cGVdKHRoaXMucmF3X3ZhbHVlKClbaV0pO1xuXG4gICAgICBmb3IgKGxldCBhdHRyIG9mIHRoaXMucmF3X3ZhbHVlKClbaV0uYXR0cmlidXRlcykge1xuICAgICAgICBwcm9jZXNzZWRfdmFsdWUgPSB0aGlzW1wicHJvY2Vzc19cIiArIGF0dHJdKHByb2Nlc3NlZF92YWx1ZSk7XG4gICAgICB9XG5cbiAgICAgIHByb2Nlc3NlZF92YWx1ZXMgPSBwcm9jZXNzZWRfdmFsdWVzLmNvbmNhdChwcm9jZXNzZWRfdmFsdWUpO1xuICAgIH1cblxuICAgIHJldHVybiBwcm9jZXNzZWRfdmFsdWVzO1xuICB9XG5cbiAgcHJvY2Vzc19pbnRlZ2VyKHZhbHVlKSB7XG4gICAgcmV0dXJuIHZhbHVlLnZhbHVlO1xuICB9XG5cbiAgcHJvY2Vzc19mbG9hdCh2YWx1ZSkge1xuICAgIGlmICh2YWx1ZS5zaXplID09PSA2NCkge1xuICAgICAgcmV0dXJuIEJpdFN0cmluZy5mbG9hdDY0VG9CeXRlcyh2YWx1ZS52YWx1ZSk7XG4gICAgfSBlbHNlIGlmICh2YWx1ZS5zaXplID09PSAzMikge1xuICAgICAgcmV0dXJuIEJpdFN0cmluZy5mbG9hdDMyVG9CeXRlcyh2YWx1ZS52YWx1ZSk7XG4gICAgfVxuXG4gICAgdGhyb3cgbmV3IEVycm9yKFwiSW52YWxpZCBzaXplIGZvciBmbG9hdFwiKTtcbiAgfVxuXG4gIHByb2Nlc3NfYml0c3RyaW5nKHZhbHVlKSB7XG4gICAgcmV0dXJuIHZhbHVlLnZhbHVlLnZhbHVlO1xuICB9XG5cbiAgcHJvY2Vzc19iaW5hcnkodmFsdWUpIHtcbiAgICByZXR1cm4gQml0U3RyaW5nLnRvVVRGOEFycmF5KHZhbHVlLnZhbHVlKTtcbiAgfVxuXG4gIHByb2Nlc3NfdXRmOCh2YWx1ZSkge1xuICAgIHJldHVybiBCaXRTdHJpbmcudG9VVEY4QXJyYXkodmFsdWUudmFsdWUpO1xuICB9XG5cbiAgcHJvY2Vzc191dGYxNih2YWx1ZSkge1xuICAgIHJldHVybiBCaXRTdHJpbmcudG9VVEYxNkFycmF5KHZhbHVlLnZhbHVlKTtcbiAgfVxuXG4gIHByb2Nlc3NfdXRmMzIodmFsdWUpIHtcbiAgICByZXR1cm4gQml0U3RyaW5nLnRvVVRGMzJBcnJheSh2YWx1ZS52YWx1ZSk7XG4gIH1cblxuICBwcm9jZXNzX3NpZ25lZCh2YWx1ZSkge1xuICAgIHJldHVybiBuZXcgVWludDhBcnJheShbdmFsdWVdKVswXTtcbiAgfVxuXG4gIHByb2Nlc3NfdW5zaWduZWQodmFsdWUpIHtcbiAgICByZXR1cm4gdmFsdWU7XG4gIH1cblxuICBwcm9jZXNzX25hdGl2ZSh2YWx1ZSkge1xuICAgIHJldHVybiB2YWx1ZTtcbiAgfVxuXG4gIHByb2Nlc3NfYmlnKHZhbHVlKSB7XG4gICAgcmV0dXJuIHZhbHVlO1xuICB9XG5cbiAgcHJvY2Vzc19saXR0bGUodmFsdWUpIHtcbiAgICByZXR1cm4gdmFsdWUucmV2ZXJzZSgpO1xuICB9XG5cbiAgcHJvY2Vzc19zaXplKHZhbHVlKSB7XG4gICAgcmV0dXJuIHZhbHVlO1xuICB9XG5cbiAgcHJvY2Vzc191bml0KHZhbHVlKSB7XG4gICAgcmV0dXJuIHZhbHVlO1xuICB9XG5cbiAgc3RhdGljIGludGVnZXIodmFsdWUpIHtcbiAgICByZXR1cm4gQml0U3RyaW5nLndyYXAodmFsdWUsIHsgXCJ0eXBlXCI6IFwiaW50ZWdlclwiLCBcInVuaXRcIjogMSwgXCJzaXplXCI6IDggfSk7XG4gIH1cblxuICBzdGF0aWMgZmxvYXQodmFsdWUpIHtcbiAgICByZXR1cm4gQml0U3RyaW5nLndyYXAodmFsdWUsIHsgXCJ0eXBlXCI6IFwiZmxvYXRcIiwgXCJ1bml0XCI6IDEsIFwic2l6ZVwiOiA2NCB9KTtcbiAgfVxuXG4gIHN0YXRpYyBiaXRzdHJpbmcodmFsdWUpIHtcbiAgICByZXR1cm4gQml0U3RyaW5nLndyYXAodmFsdWUsIHsgXCJ0eXBlXCI6IFwiYml0c3RyaW5nXCIsIFwidW5pdFwiOiAxLCBcInNpemVcIjogdmFsdWUubGVuZ3RoIH0pO1xuICB9XG5cbiAgc3RhdGljIGJpdHModmFsdWUpIHtcbiAgICByZXR1cm4gQml0U3RyaW5nLmJpdHN0cmluZyh2YWx1ZSk7XG4gIH1cblxuICBzdGF0aWMgYmluYXJ5KHZhbHVlKSB7XG4gICAgcmV0dXJuIEJpdFN0cmluZy53cmFwKHZhbHVlLCB7IFwidHlwZVwiOiBcImJpbmFyeVwiLCBcInVuaXRcIjogOCwgXCJzaXplXCI6IHZhbHVlLmxlbmd0aCB9KTtcbiAgfVxuXG4gIHN0YXRpYyBieXRlcyh2YWx1ZSkge1xuICAgIHJldHVybiBCaXRTdHJpbmcuYmluYXJ5KHZhbHVlKTtcbiAgfVxuXG4gIHN0YXRpYyB1dGY4KHZhbHVlKSB7XG4gICAgcmV0dXJuIEJpdFN0cmluZy53cmFwKHZhbHVlLCB7IFwidHlwZVwiOiBcInV0ZjhcIiB9KTtcbiAgfVxuXG4gIHN0YXRpYyB1dGYxNih2YWx1ZSkge1xuICAgIHJldHVybiBCaXRTdHJpbmcud3JhcCh2YWx1ZSwgeyBcInR5cGVcIjogXCJ1dGYxNlwiIH0pO1xuICB9XG5cbiAgc3RhdGljIHV0ZjMyKHZhbHVlKSB7XG4gICAgcmV0dXJuIEJpdFN0cmluZy53cmFwKHZhbHVlLCB7IFwidHlwZVwiOiBcInV0ZjMyXCIgfSk7XG4gIH1cblxuICBzdGF0aWMgc2lnbmVkKHZhbHVlKSB7XG4gICAgcmV0dXJuIEJpdFN0cmluZy53cmFwKHZhbHVlLCB7fSwgXCJzaWduZWRcIik7XG4gIH1cblxuICBzdGF0aWMgdW5zaWduZWQodmFsdWUpIHtcbiAgICByZXR1cm4gQml0U3RyaW5nLndyYXAodmFsdWUsIHt9LCBcInVuc2lnbmVkXCIpO1xuICB9XG5cbiAgc3RhdGljIG5hdGl2ZSh2YWx1ZSkge1xuICAgIHJldHVybiBCaXRTdHJpbmcud3JhcCh2YWx1ZSwge30sIFwibmF0aXZlXCIpO1xuICB9XG5cbiAgc3RhdGljIGJpZyh2YWx1ZSkge1xuICAgIHJldHVybiBCaXRTdHJpbmcud3JhcCh2YWx1ZSwge30sIFwiYmlnXCIpO1xuICB9XG5cbiAgc3RhdGljIGxpdHRsZSh2YWx1ZSkge1xuICAgIHJldHVybiBCaXRTdHJpbmcud3JhcCh2YWx1ZSwge30sIFwibGl0dGxlXCIpO1xuICB9XG5cbiAgc3RhdGljIHNpemUodmFsdWUsIGNvdW50KSB7XG4gICAgcmV0dXJuIEJpdFN0cmluZy53cmFwKHZhbHVlLCB7IFwic2l6ZVwiOiBjb3VudCB9KTtcbiAgfVxuXG4gIHN0YXRpYyB1bml0KHZhbHVlLCBjb3VudCkge1xuICAgIHJldHVybiBCaXRTdHJpbmcud3JhcCh2YWx1ZSwgeyBcInVuaXRcIjogY291bnQgfSk7XG4gIH1cblxuICBzdGF0aWMgd3JhcCh2YWx1ZSwgb3B0LCBuZXdfYXR0cmlidXRlID0gbnVsbCkge1xuICAgIGxldCB0aGVfdmFsdWUgPSB2YWx1ZTtcblxuICAgIGlmICghKHZhbHVlIGluc3RhbmNlb2YgT2JqZWN0KSkge1xuICAgICAgdGhlX3ZhbHVlID0geyBcInZhbHVlXCI6IHZhbHVlLCBcImF0dHJpYnV0ZXNcIjogW10gfTtcbiAgICB9XG5cbiAgICB0aGVfdmFsdWUgPSBPYmplY3QuYXNzaWduKHRoZV92YWx1ZSwgb3B0KTtcblxuICAgIGlmIChuZXdfYXR0cmlidXRlKSB7XG4gICAgICB0aGVfdmFsdWUuYXR0cmlidXRlcy5wdXNoKG5ld19hdHRyaWJ1dGUpO1xuICAgIH1cblxuICAgIHJldHVybiB0aGVfdmFsdWU7XG4gIH1cblxuICBzdGF0aWMgdG9VVEY4QXJyYXkoc3RyKSB7XG4gICAgdmFyIHV0ZjggPSBbXTtcbiAgICBmb3IgKHZhciBpID0gMDsgaSA8IHN0ci5sZW5ndGg7IGkrKykge1xuICAgICAgdmFyIGNoYXJjb2RlID0gc3RyLmNoYXJDb2RlQXQoaSk7XG4gICAgICBpZiAoY2hhcmNvZGUgPCAxMjgpIHtcbiAgICAgICAgdXRmOC5wdXNoKGNoYXJjb2RlKTtcbiAgICAgIH0gZWxzZSBpZiAoY2hhcmNvZGUgPCAyMDQ4KSB7XG4gICAgICAgIHV0ZjgucHVzaCgxOTIgfCBjaGFyY29kZSA+PiA2LCAxMjggfCBjaGFyY29kZSAmIDYzKTtcbiAgICAgIH0gZWxzZSBpZiAoY2hhcmNvZGUgPCA1NTI5NiB8fCBjaGFyY29kZSA+PSA1NzM0NCkge1xuICAgICAgICB1dGY4LnB1c2goMjI0IHwgY2hhcmNvZGUgPj4gMTIsIDEyOCB8IGNoYXJjb2RlID4+IDYgJiA2MywgMTI4IHwgY2hhcmNvZGUgJiA2Myk7XG4gICAgICB9XG4gICAgICAvLyBzdXJyb2dhdGUgcGFpclxuICAgICAgZWxzZSB7XG4gICAgICAgIGkrKztcbiAgICAgICAgLy8gVVRGLTE2IGVuY29kZXMgMHgxMDAwMC0weDEwRkZGRiBieVxuICAgICAgICAvLyBzdWJ0cmFjdGluZyAweDEwMDAwIGFuZCBzcGxpdHRpbmcgdGhlXG4gICAgICAgIC8vIDIwIGJpdHMgb2YgMHgwLTB4RkZGRkYgaW50byB0d28gaGFsdmVzXG4gICAgICAgIGNoYXJjb2RlID0gNjU1MzYgKyAoKGNoYXJjb2RlICYgMTAyMykgPDwgMTAgfCBzdHIuY2hhckNvZGVBdChpKSAmIDEwMjMpO1xuICAgICAgICB1dGY4LnB1c2goMjQwIHwgY2hhcmNvZGUgPj4gMTgsIDEyOCB8IGNoYXJjb2RlID4+IDEyICYgNjMsIDEyOCB8IGNoYXJjb2RlID4+IDYgJiA2MywgMTI4IHwgY2hhcmNvZGUgJiA2Myk7XG4gICAgICB9XG4gICAgfVxuICAgIHJldHVybiB1dGY4O1xuICB9XG5cbiAgc3RhdGljIHRvVVRGMTZBcnJheShzdHIpIHtcbiAgICB2YXIgdXRmMTYgPSBbXTtcbiAgICBmb3IgKHZhciBpID0gMDsgaSA8IHN0ci5sZW5ndGg7IGkrKykge1xuICAgICAgdmFyIGNvZGVQb2ludCA9IHN0ci5jb2RlUG9pbnRBdChpKTtcblxuICAgICAgaWYgKGNvZGVQb2ludCA8PSAyNTUpIHtcbiAgICAgICAgdXRmMTYucHVzaCgwKTtcbiAgICAgICAgdXRmMTYucHVzaChjb2RlUG9pbnQpO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgdXRmMTYucHVzaChjb2RlUG9pbnQgPj4gOCAmIDI1NSk7XG4gICAgICAgIHV0ZjE2LnB1c2goY29kZVBvaW50ICYgMjU1KTtcbiAgICAgIH1cbiAgICB9XG4gICAgcmV0dXJuIHV0ZjE2O1xuICB9XG5cbiAgc3RhdGljIHRvVVRGMzJBcnJheShzdHIpIHtcbiAgICB2YXIgdXRmMzIgPSBbXTtcbiAgICBmb3IgKHZhciBpID0gMDsgaSA8IHN0ci5sZW5ndGg7IGkrKykge1xuICAgICAgdmFyIGNvZGVQb2ludCA9IHN0ci5jb2RlUG9pbnRBdChpKTtcblxuICAgICAgaWYgKGNvZGVQb2ludCA8PSAyNTUpIHtcbiAgICAgICAgdXRmMzIucHVzaCgwKTtcbiAgICAgICAgdXRmMzIucHVzaCgwKTtcbiAgICAgICAgdXRmMzIucHVzaCgwKTtcbiAgICAgICAgdXRmMzIucHVzaChjb2RlUG9pbnQpO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgdXRmMzIucHVzaCgwKTtcbiAgICAgICAgdXRmMzIucHVzaCgwKTtcbiAgICAgICAgdXRmMzIucHVzaChjb2RlUG9pbnQgPj4gOCAmIDI1NSk7XG4gICAgICAgIHV0ZjMyLnB1c2goY29kZVBvaW50ICYgMjU1KTtcbiAgICAgIH1cbiAgICB9XG4gICAgcmV0dXJuIHV0ZjMyO1xuICB9XG5cbiAgLy9odHRwOi8vc3RhY2tvdmVyZmxvdy5jb20vcXVlc3Rpb25zLzIwMDM0OTMvamF2YXNjcmlwdC1mbG9hdC1mcm9tLXRvLWJpdHNcbiAgc3RhdGljIGZsb2F0MzJUb0J5dGVzKGYpIHtcbiAgICB2YXIgYnl0ZXMgPSBbXTtcblxuICAgIHZhciBidWYgPSBuZXcgQXJyYXlCdWZmZXIoNCk7XG4gICAgbmV3IEZsb2F0MzJBcnJheShidWYpWzBdID0gZjtcblxuICAgIGxldCBpbnRWZXJzaW9uID0gbmV3IFVpbnQzMkFycmF5KGJ1ZilbMF07XG5cbiAgICBieXRlcy5wdXNoKGludFZlcnNpb24gPj4gMjQgJiAyNTUpO1xuICAgIGJ5dGVzLnB1c2goaW50VmVyc2lvbiA+PiAxNiAmIDI1NSk7XG4gICAgYnl0ZXMucHVzaChpbnRWZXJzaW9uID4+IDggJiAyNTUpO1xuICAgIGJ5dGVzLnB1c2goaW50VmVyc2lvbiAmIDI1NSk7XG5cbiAgICByZXR1cm4gYnl0ZXM7XG4gIH1cblxuICBzdGF0aWMgZmxvYXQ2NFRvQnl0ZXMoZikge1xuICAgIHZhciBieXRlcyA9IFtdO1xuXG4gICAgdmFyIGJ1ZiA9IG5ldyBBcnJheUJ1ZmZlcig4KTtcbiAgICBuZXcgRmxvYXQ2NEFycmF5KGJ1ZilbMF0gPSBmO1xuXG4gICAgdmFyIGludFZlcnNpb24xID0gbmV3IFVpbnQzMkFycmF5KGJ1ZilbMF07XG4gICAgdmFyIGludFZlcnNpb24yID0gbmV3IFVpbnQzMkFycmF5KGJ1ZilbMV07XG5cbiAgICBieXRlcy5wdXNoKGludFZlcnNpb24yID4+IDI0ICYgMjU1KTtcbiAgICBieXRlcy5wdXNoKGludFZlcnNpb24yID4+IDE2ICYgMjU1KTtcbiAgICBieXRlcy5wdXNoKGludFZlcnNpb24yID4+IDggJiAyNTUpO1xuICAgIGJ5dGVzLnB1c2goaW50VmVyc2lvbjIgJiAyNTUpO1xuXG4gICAgYnl0ZXMucHVzaChpbnRWZXJzaW9uMSA+PiAyNCAmIDI1NSk7XG4gICAgYnl0ZXMucHVzaChpbnRWZXJzaW9uMSA+PiAxNiAmIDI1NSk7XG4gICAgYnl0ZXMucHVzaChpbnRWZXJzaW9uMSA+PiA4ICYgMjU1KTtcbiAgICBieXRlcy5wdXNoKGludFZlcnNpb24xICYgMjU1KTtcblxuICAgIHJldHVybiBieXRlcztcbiAgfVxufVxuXG4vKiBAZmxvdyAqL1xuXG5jbGFzcyBWYXJpYWJsZSB7XG5cbiAgY29uc3RydWN0b3IobmFtZSA9IG51bGwpIHtcbiAgICB0aGlzLm5hbWUgPSBuYW1lO1xuICB9XG59XG5cbmNsYXNzIFdpbGRjYXJkIHtcbiAgY29uc3RydWN0b3IoKSB7fVxufVxuXG5jbGFzcyBTdGFydHNXaXRoIHtcblxuICBjb25zdHJ1Y3RvcihwcmVmaXgpIHtcbiAgICB0aGlzLnByZWZpeCA9IHByZWZpeDtcbiAgfVxufVxuXG5jbGFzcyBDYXB0dXJlIHtcblxuICBjb25zdHJ1Y3Rvcih2YWx1ZSkge1xuICAgIHRoaXMudmFsdWUgPSB2YWx1ZTtcbiAgfVxufVxuXG5jbGFzcyBIZWFkVGFpbCB7XG4gIGNvbnN0cnVjdG9yKCkge31cbn1cblxuY2xhc3MgVHlwZSB7XG5cbiAgY29uc3RydWN0b3IodHlwZSwgb2JqUGF0dGVybiA9IHt9KSB7XG4gICAgdGhpcy50eXBlID0gdHlwZTtcbiAgICB0aGlzLm9ialBhdHRlcm4gPSBvYmpQYXR0ZXJuO1xuICB9XG59XG5cbmNsYXNzIEJvdW5kIHtcblxuICBjb25zdHJ1Y3Rvcih2YWx1ZSkge1xuICAgIHRoaXMudmFsdWUgPSB2YWx1ZTtcbiAgfVxufVxuXG5mdW5jdGlvbiB2YXJpYWJsZShuYW1lID0gbnVsbCkge1xuICByZXR1cm4gbmV3IFZhcmlhYmxlKG5hbWUpO1xufVxuXG5mdW5jdGlvbiB3aWxkY2FyZCgpIHtcbiAgcmV0dXJuIG5ldyBXaWxkY2FyZCgpO1xufVxuXG5mdW5jdGlvbiBzdGFydHNXaXRoKHByZWZpeCkge1xuICByZXR1cm4gbmV3IFN0YXJ0c1dpdGgocHJlZml4KTtcbn1cblxuZnVuY3Rpb24gY2FwdHVyZSh2YWx1ZSkge1xuICByZXR1cm4gbmV3IENhcHR1cmUodmFsdWUpO1xufVxuXG5mdW5jdGlvbiBoZWFkVGFpbCgpIHtcbiAgcmV0dXJuIG5ldyBIZWFkVGFpbCgpO1xufVxuXG5mdW5jdGlvbiB0eXBlKHR5cGUsIG9ialBhdHRlcm4gPSB7fSkge1xuICByZXR1cm4gbmV3IFR5cGUodHlwZSwgb2JqUGF0dGVybik7XG59XG5cbmZ1bmN0aW9uIGJvdW5kKHZhbHVlKSB7XG4gIHJldHVybiBuZXcgQm91bmQodmFsdWUpO1xufVxuXG5mdW5jdGlvbiBpc19udW1iZXIkMih2YWx1ZSkge1xuICByZXR1cm4gdHlwZW9mIHZhbHVlID09PSAnbnVtYmVyJztcbn1cblxuZnVuY3Rpb24gaXNfc3RyaW5nKHZhbHVlKSB7XG4gIHJldHVybiB0eXBlb2YgdmFsdWUgPT09ICdzdHJpbmcnO1xufVxuXG5mdW5jdGlvbiBpc19ib29sZWFuJDIodmFsdWUpIHtcbiAgcmV0dXJuIHR5cGVvZiB2YWx1ZSA9PT0gJ2Jvb2xlYW4nO1xufVxuXG5mdW5jdGlvbiBpc19zeW1ib2wodmFsdWUpIHtcbiAgcmV0dXJuIHR5cGVvZiB2YWx1ZSA9PT0gJ3N5bWJvbCc7XG59XG5cbmZ1bmN0aW9uIGlzX251bGwodmFsdWUpIHtcbiAgcmV0dXJuIHZhbHVlID09PSBudWxsO1xufVxuXG5mdW5jdGlvbiBpc191bmRlZmluZWQodmFsdWUpIHtcbiAgcmV0dXJuIHR5cGVvZiB2YWx1ZSA9PT0gJ3VuZGVmaW5lZCc7XG59XG5cbmZ1bmN0aW9uIGlzX2Z1bmN0aW9uJDIodmFsdWUpIHtcbiAgcmV0dXJuIE9iamVjdC5wcm90b3R5cGUudG9TdHJpbmcuY2FsbCh2YWx1ZSkgPT0gJ1tvYmplY3QgRnVuY3Rpb25dJztcbn1cblxuZnVuY3Rpb24gaXNfdmFyaWFibGUodmFsdWUpIHtcbiAgcmV0dXJuIHZhbHVlIGluc3RhbmNlb2YgVmFyaWFibGU7XG59XG5cbmZ1bmN0aW9uIGlzX3dpbGRjYXJkKHZhbHVlKSB7XG4gIHJldHVybiB2YWx1ZSBpbnN0YW5jZW9mIFdpbGRjYXJkO1xufVxuXG5mdW5jdGlvbiBpc19oZWFkVGFpbCh2YWx1ZSkge1xuICByZXR1cm4gdmFsdWUgaW5zdGFuY2VvZiBIZWFkVGFpbDtcbn1cblxuZnVuY3Rpb24gaXNfY2FwdHVyZSh2YWx1ZSkge1xuICByZXR1cm4gdmFsdWUgaW5zdGFuY2VvZiBDYXB0dXJlO1xufVxuXG5mdW5jdGlvbiBpc190eXBlKHZhbHVlKSB7XG4gIHJldHVybiB2YWx1ZSBpbnN0YW5jZW9mIFR5cGU7XG59XG5cbmZ1bmN0aW9uIGlzX3N0YXJ0c1dpdGgodmFsdWUpIHtcbiAgcmV0dXJuIHZhbHVlIGluc3RhbmNlb2YgU3RhcnRzV2l0aDtcbn1cblxuZnVuY3Rpb24gaXNfYm91bmQodmFsdWUpIHtcbiAgcmV0dXJuIHZhbHVlIGluc3RhbmNlb2YgQm91bmQ7XG59XG5cbmZ1bmN0aW9uIGlzX29iamVjdCh2YWx1ZSkge1xuICByZXR1cm4gdHlwZW9mIHZhbHVlID09PSAnb2JqZWN0Jztcbn1cblxuZnVuY3Rpb24gaXNfYXJyYXkodmFsdWUpIHtcbiAgcmV0dXJuIEFycmF5LmlzQXJyYXkodmFsdWUpO1xufVxuXG52YXIgQ2hlY2tzID0ge1xuICBpc19udW1iZXI6IGlzX251bWJlciQyLFxuICBpc19zdHJpbmcsXG4gIGlzX2Jvb2xlYW46IGlzX2Jvb2xlYW4kMixcbiAgaXNfc3ltYm9sLFxuICBpc19udWxsLFxuICBpc191bmRlZmluZWQsXG4gIGlzX2Z1bmN0aW9uOiBpc19mdW5jdGlvbiQyLFxuICBpc192YXJpYWJsZSxcbiAgaXNfd2lsZGNhcmQsXG4gIGlzX2hlYWRUYWlsLFxuICBpc19jYXB0dXJlLFxuICBpc190eXBlLFxuICBpc19zdGFydHNXaXRoLFxuICBpc19ib3VuZCxcbiAgaXNfb2JqZWN0LFxuICBpc19hcnJheVxufTtcblxuZnVuY3Rpb24gcmVzb2x2ZVN5bWJvbChwYXR0ZXJuKSB7XG4gIHJldHVybiBmdW5jdGlvbiAodmFsdWUpIHtcbiAgICByZXR1cm4gQ2hlY2tzLmlzX3N5bWJvbCh2YWx1ZSkgJiYgdmFsdWUgPT09IHBhdHRlcm47XG4gIH07XG59XG5cbmZ1bmN0aW9uIHJlc29sdmVTdHJpbmcocGF0dGVybikge1xuICByZXR1cm4gZnVuY3Rpb24gKHZhbHVlKSB7XG4gICAgcmV0dXJuIENoZWNrcy5pc19zdHJpbmcodmFsdWUpICYmIHZhbHVlID09PSBwYXR0ZXJuO1xuICB9O1xufVxuXG5mdW5jdGlvbiByZXNvbHZlTnVtYmVyKHBhdHRlcm4pIHtcbiAgcmV0dXJuIGZ1bmN0aW9uICh2YWx1ZSkge1xuICAgIHJldHVybiBDaGVja3MuaXNfbnVtYmVyKHZhbHVlKSAmJiB2YWx1ZSA9PT0gcGF0dGVybjtcbiAgfTtcbn1cblxuZnVuY3Rpb24gcmVzb2x2ZUJvb2xlYW4ocGF0dGVybikge1xuICByZXR1cm4gZnVuY3Rpb24gKHZhbHVlKSB7XG4gICAgcmV0dXJuIENoZWNrcy5pc19ib29sZWFuKHZhbHVlKSAmJiB2YWx1ZSA9PT0gcGF0dGVybjtcbiAgfTtcbn1cblxuZnVuY3Rpb24gcmVzb2x2ZUZ1bmN0aW9uKHBhdHRlcm4pIHtcbiAgcmV0dXJuIGZ1bmN0aW9uICh2YWx1ZSkge1xuICAgIHJldHVybiBDaGVja3MuaXNfZnVuY3Rpb24odmFsdWUpICYmIHZhbHVlID09PSBwYXR0ZXJuO1xuICB9O1xufVxuXG5mdW5jdGlvbiByZXNvbHZlTnVsbChwYXR0ZXJuKSB7XG4gIHJldHVybiBmdW5jdGlvbiAodmFsdWUpIHtcbiAgICByZXR1cm4gQ2hlY2tzLmlzX251bGwodmFsdWUpO1xuICB9O1xufVxuXG5mdW5jdGlvbiByZXNvbHZlQm91bmQocGF0dGVybikge1xuICByZXR1cm4gZnVuY3Rpb24gKHZhbHVlLCBhcmdzKSB7XG4gICAgaWYgKHR5cGVvZiB2YWx1ZSA9PT0gdHlwZW9mIHBhdHRlcm4udmFsdWUgJiYgdmFsdWUgPT09IHBhdHRlcm4udmFsdWUpIHtcbiAgICAgIGFyZ3MucHVzaCh2YWx1ZSk7XG4gICAgICByZXR1cm4gdHJ1ZTtcbiAgICB9XG5cbiAgICByZXR1cm4gZmFsc2U7XG4gIH07XG59XG5cbmZ1bmN0aW9uIHJlc29sdmVXaWxkY2FyZCgpIHtcbiAgcmV0dXJuIGZ1bmN0aW9uICgpIHtcbiAgICByZXR1cm4gdHJ1ZTtcbiAgfTtcbn1cblxuZnVuY3Rpb24gcmVzb2x2ZVZhcmlhYmxlKCkge1xuICByZXR1cm4gZnVuY3Rpb24gKHZhbHVlLCBhcmdzKSB7XG4gICAgYXJncy5wdXNoKHZhbHVlKTtcbiAgICByZXR1cm4gdHJ1ZTtcbiAgfTtcbn1cblxuZnVuY3Rpb24gcmVzb2x2ZUhlYWRUYWlsKCkge1xuICByZXR1cm4gZnVuY3Rpb24gKHZhbHVlLCBhcmdzKSB7XG4gICAgaWYgKCFDaGVja3MuaXNfYXJyYXkodmFsdWUpIHx8IHZhbHVlLmxlbmd0aCA8IDIpIHtcbiAgICAgIHJldHVybiBmYWxzZTtcbiAgICB9XG5cbiAgICBjb25zdCBoZWFkID0gdmFsdWVbMF07XG4gICAgY29uc3QgdGFpbCA9IHZhbHVlLnNsaWNlKDEpO1xuXG4gICAgYXJncy5wdXNoKGhlYWQpO1xuICAgIGFyZ3MucHVzaCh0YWlsKTtcblxuICAgIHJldHVybiB0cnVlO1xuICB9O1xufVxuXG5mdW5jdGlvbiByZXNvbHZlQ2FwdHVyZShwYXR0ZXJuKSB7XG4gIGNvbnN0IG1hdGNoZXMgPSBidWlsZE1hdGNoKHBhdHRlcm4udmFsdWUpO1xuXG4gIHJldHVybiBmdW5jdGlvbiAodmFsdWUsIGFyZ3MpIHtcbiAgICBpZiAobWF0Y2hlcyh2YWx1ZSwgYXJncykpIHtcbiAgICAgIGFyZ3MucHVzaCh2YWx1ZSk7XG4gICAgICByZXR1cm4gdHJ1ZTtcbiAgICB9XG5cbiAgICByZXR1cm4gZmFsc2U7XG4gIH07XG59XG5cbmZ1bmN0aW9uIHJlc29sdmVTdGFydHNXaXRoKHBhdHRlcm4pIHtcbiAgY29uc3QgcHJlZml4ID0gcGF0dGVybi5wcmVmaXg7XG5cbiAgcmV0dXJuIGZ1bmN0aW9uICh2YWx1ZSwgYXJncykge1xuICAgIGlmIChDaGVja3MuaXNfc3RyaW5nKHZhbHVlKSAmJiB2YWx1ZS5zdGFydHNXaXRoKHByZWZpeCkpIHtcbiAgICAgIGFyZ3MucHVzaCh2YWx1ZS5zdWJzdHJpbmcocHJlZml4Lmxlbmd0aCkpO1xuICAgICAgcmV0dXJuIHRydWU7XG4gICAgfVxuXG4gICAgcmV0dXJuIGZhbHNlO1xuICB9O1xufVxuXG5mdW5jdGlvbiByZXNvbHZlVHlwZShwYXR0ZXJuKSB7XG4gIHJldHVybiBmdW5jdGlvbiAodmFsdWUsIGFyZ3MpIHtcbiAgICBpZiAodmFsdWUgaW5zdGFuY2VvZiBwYXR0ZXJuLnR5cGUpIHtcbiAgICAgIGNvbnN0IG1hdGNoZXMgPSBidWlsZE1hdGNoKHBhdHRlcm4ub2JqUGF0dGVybik7XG4gICAgICByZXR1cm4gbWF0Y2hlcyh2YWx1ZSwgYXJncykgJiYgYXJncy5wdXNoKHZhbHVlKSA+IDA7XG4gICAgfVxuXG4gICAgcmV0dXJuIGZhbHNlO1xuICB9O1xufVxuXG5mdW5jdGlvbiByZXNvbHZlQXJyYXkocGF0dGVybikge1xuICBjb25zdCBtYXRjaGVzID0gcGF0dGVybi5tYXAoeCA9PiBidWlsZE1hdGNoKHgpKTtcblxuICByZXR1cm4gZnVuY3Rpb24gKHZhbHVlLCBhcmdzKSB7XG4gICAgaWYgKCFDaGVja3MuaXNfYXJyYXkodmFsdWUpIHx8IHZhbHVlLmxlbmd0aCAhPSBwYXR0ZXJuLmxlbmd0aCkge1xuICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH1cblxuICAgIHJldHVybiB2YWx1ZS5ldmVyeShmdW5jdGlvbiAodiwgaSkge1xuICAgICAgcmV0dXJuIG1hdGNoZXNbaV0odmFsdWVbaV0sIGFyZ3MpO1xuICAgIH0pO1xuICB9O1xufVxuXG5mdW5jdGlvbiByZXNvbHZlT2JqZWN0KHBhdHRlcm4pIHtcbiAgbGV0IG1hdGNoZXMgPSB7fTtcblxuICBmb3IgKGxldCBrZXkgb2YgT2JqZWN0LmtleXMocGF0dGVybikuY29uY2F0KE9iamVjdC5nZXRPd25Qcm9wZXJ0eVN5bWJvbHMocGF0dGVybikpKSB7XG4gICAgbWF0Y2hlc1trZXldID0gYnVpbGRNYXRjaChwYXR0ZXJuW2tleV0pO1xuICB9XG5cbiAgcmV0dXJuIGZ1bmN0aW9uICh2YWx1ZSwgYXJncykge1xuICAgIGlmICghQ2hlY2tzLmlzX29iamVjdCh2YWx1ZSkgfHwgcGF0dGVybi5sZW5ndGggPiB2YWx1ZS5sZW5ndGgpIHtcbiAgICAgIHJldHVybiBmYWxzZTtcbiAgICB9XG5cbiAgICBmb3IgKGxldCBrZXkgb2YgT2JqZWN0LmtleXMocGF0dGVybikuY29uY2F0KE9iamVjdC5nZXRPd25Qcm9wZXJ0eVN5bWJvbHMocGF0dGVybikpKSB7XG4gICAgICBpZiAoIShrZXkgaW4gdmFsdWUpIHx8ICFtYXRjaGVzW2tleV0odmFsdWVba2V5XSwgYXJncykpIHtcbiAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgfVxuICAgIH1cblxuICAgIHJldHVybiB0cnVlO1xuICB9O1xufVxuXG5mdW5jdGlvbiByZXNvbHZlTm9NYXRjaCgpIHtcbiAgcmV0dXJuIGZ1bmN0aW9uICgpIHtcbiAgICByZXR1cm4gZmFsc2U7XG4gIH07XG59XG5cbnZhciBSZXNvbHZlcnMgPSB7XG4gIHJlc29sdmVCb3VuZCxcbiAgcmVzb2x2ZVdpbGRjYXJkLFxuICByZXNvbHZlVmFyaWFibGUsXG4gIHJlc29sdmVIZWFkVGFpbCxcbiAgcmVzb2x2ZUNhcHR1cmUsXG4gIHJlc29sdmVTdGFydHNXaXRoLFxuICByZXNvbHZlVHlwZSxcbiAgcmVzb2x2ZUFycmF5LFxuICByZXNvbHZlT2JqZWN0LFxuICByZXNvbHZlTm9NYXRjaCxcbiAgcmVzb2x2ZVN5bWJvbCxcbiAgcmVzb2x2ZVN0cmluZyxcbiAgcmVzb2x2ZU51bWJlcixcbiAgcmVzb2x2ZUJvb2xlYW4sXG4gIHJlc29sdmVGdW5jdGlvbixcbiAgcmVzb2x2ZU51bGxcbn07XG5cbmZ1bmN0aW9uIGJ1aWxkTWF0Y2gocGF0dGVybikge1xuXG4gIGlmIChDaGVja3MuaXNfdmFyaWFibGUocGF0dGVybikpIHtcbiAgICByZXR1cm4gUmVzb2x2ZXJzLnJlc29sdmVWYXJpYWJsZShwYXR0ZXJuKTtcbiAgfVxuXG4gIGlmIChDaGVja3MuaXNfd2lsZGNhcmQocGF0dGVybikpIHtcbiAgICByZXR1cm4gUmVzb2x2ZXJzLnJlc29sdmVXaWxkY2FyZChwYXR0ZXJuKTtcbiAgfVxuXG4gIGlmIChDaGVja3MuaXNfdW5kZWZpbmVkKHBhdHRlcm4pKSB7XG4gICAgcmV0dXJuIFJlc29sdmVycy5yZXNvbHZlV2lsZGNhcmQocGF0dGVybik7XG4gIH1cblxuICBpZiAoQ2hlY2tzLmlzX2hlYWRUYWlsKHBhdHRlcm4pKSB7XG4gICAgcmV0dXJuIFJlc29sdmVycy5yZXNvbHZlSGVhZFRhaWwocGF0dGVybik7XG4gIH1cblxuICBpZiAoQ2hlY2tzLmlzX3N0YXJ0c1dpdGgocGF0dGVybikpIHtcbiAgICByZXR1cm4gUmVzb2x2ZXJzLnJlc29sdmVTdGFydHNXaXRoKHBhdHRlcm4pO1xuICB9XG5cbiAgaWYgKENoZWNrcy5pc19jYXB0dXJlKHBhdHRlcm4pKSB7XG4gICAgcmV0dXJuIFJlc29sdmVycy5yZXNvbHZlQ2FwdHVyZShwYXR0ZXJuKTtcbiAgfVxuXG4gIGlmIChDaGVja3MuaXNfYm91bmQocGF0dGVybikpIHtcbiAgICByZXR1cm4gUmVzb2x2ZXJzLnJlc29sdmVCb3VuZChwYXR0ZXJuKTtcbiAgfVxuXG4gIGlmIChDaGVja3MuaXNfdHlwZShwYXR0ZXJuKSkge1xuICAgIHJldHVybiBSZXNvbHZlcnMucmVzb2x2ZVR5cGUocGF0dGVybik7XG4gIH1cblxuICBpZiAoQ2hlY2tzLmlzX2FycmF5KHBhdHRlcm4pKSB7XG4gICAgcmV0dXJuIFJlc29sdmVycy5yZXNvbHZlQXJyYXkocGF0dGVybik7XG4gIH1cblxuICBpZiAoQ2hlY2tzLmlzX251bWJlcihwYXR0ZXJuKSkge1xuICAgIHJldHVybiBSZXNvbHZlcnMucmVzb2x2ZU51bWJlcihwYXR0ZXJuKTtcbiAgfVxuXG4gIGlmIChDaGVja3MuaXNfc3RyaW5nKHBhdHRlcm4pKSB7XG4gICAgcmV0dXJuIFJlc29sdmVycy5yZXNvbHZlU3RyaW5nKHBhdHRlcm4pO1xuICB9XG5cbiAgaWYgKENoZWNrcy5pc19ib29sZWFuKHBhdHRlcm4pKSB7XG4gICAgcmV0dXJuIFJlc29sdmVycy5yZXNvbHZlQm9vbGVhbihwYXR0ZXJuKTtcbiAgfVxuXG4gIGlmIChDaGVja3MuaXNfc3ltYm9sKHBhdHRlcm4pKSB7XG4gICAgcmV0dXJuIFJlc29sdmVycy5yZXNvbHZlU3ltYm9sKHBhdHRlcm4pO1xuICB9XG5cbiAgaWYgKENoZWNrcy5pc19udWxsKHBhdHRlcm4pKSB7XG4gICAgcmV0dXJuIFJlc29sdmVycy5yZXNvbHZlTnVsbChwYXR0ZXJuKTtcbiAgfVxuXG4gIGlmIChDaGVja3MuaXNfb2JqZWN0KHBhdHRlcm4pKSB7XG4gICAgcmV0dXJuIFJlc29sdmVycy5yZXNvbHZlT2JqZWN0KHBhdHRlcm4pO1xuICB9XG5cbiAgcmV0dXJuIFJlc29sdmVycy5yZXNvbHZlTm9NYXRjaCgpO1xufVxuXG5jbGFzcyBNYXRjaEVycm9yIGV4dGVuZHMgRXJyb3Ige1xuICBjb25zdHJ1Y3RvcihhcmcpIHtcbiAgICBzdXBlcigpO1xuXG4gICAgaWYgKHR5cGVvZiBhcmcgPT09ICdzeW1ib2wnKSB7XG4gICAgICB0aGlzLm1lc3NhZ2UgPSAnTm8gbWF0Y2ggZm9yOiAnICsgYXJnLnRvU3RyaW5nKCk7XG4gICAgfSBlbHNlIGlmIChBcnJheS5pc0FycmF5KGFyZykpIHtcbiAgICAgIGxldCBtYXBwZWRWYWx1ZXMgPSBhcmcubWFwKHggPT4geC50b1N0cmluZygpKTtcbiAgICAgIHRoaXMubWVzc2FnZSA9ICdObyBtYXRjaCBmb3I6ICcgKyBtYXBwZWRWYWx1ZXM7XG4gICAgfSBlbHNlIHtcbiAgICAgIHRoaXMubWVzc2FnZSA9ICdObyBtYXRjaCBmb3I6ICcgKyBhcmc7XG4gICAgfVxuXG4gICAgdGhpcy5zdGFjayA9IG5ldyBFcnJvcigpLnN0YWNrO1xuICAgIHRoaXMubmFtZSA9IHRoaXMuY29uc3RydWN0b3IubmFtZTtcbiAgfVxufVxuXG5jbGFzcyBDYXNlIHtcblxuICBjb25zdHJ1Y3RvcihwYXR0ZXJuLCBmbiwgZ3VhcmQgPSAoKSA9PiB0cnVlKSB7XG4gICAgdGhpcy5wYXR0ZXJuID0gYnVpbGRNYXRjaChwYXR0ZXJuKTtcbiAgICB0aGlzLmZuID0gZm47XG4gICAgdGhpcy5ndWFyZCA9IGd1YXJkO1xuICB9XG59XG5cbmZ1bmN0aW9uIG1ha2VfY2FzZShwYXR0ZXJuLCBmbiwgZ3VhcmQgPSAoKSA9PiB0cnVlKSB7XG4gIHJldHVybiBuZXcgQ2FzZShwYXR0ZXJuLCBmbiwgZ3VhcmQpO1xufVxuXG5mdW5jdGlvbiBkZWZtYXRjaCguLi5jYXNlcykge1xuICByZXR1cm4gZnVuY3Rpb24gKC4uLmFyZ3MpIHtcbiAgICBmb3IgKGxldCBwcm9jZXNzZWRDYXNlIG9mIGNhc2VzKSB7XG4gICAgICBsZXQgcmVzdWx0ID0gW107XG4gICAgICBpZiAocHJvY2Vzc2VkQ2FzZS5wYXR0ZXJuKGFyZ3MsIHJlc3VsdCkgJiYgcHJvY2Vzc2VkQ2FzZS5ndWFyZC5hcHBseSh0aGlzLCByZXN1bHQpKSB7XG4gICAgICAgIHJldHVybiBwcm9jZXNzZWRDYXNlLmZuLmFwcGx5KHRoaXMsIHJlc3VsdCk7XG4gICAgICB9XG4gICAgfVxuXG4gICAgdGhyb3cgbmV3IE1hdGNoRXJyb3IoYXJncyk7XG4gIH07XG59XG5cbmZ1bmN0aW9uIG1hdGNoKHBhdHRlcm4sIGV4cHIsIGd1YXJkID0gKCkgPT4gdHJ1ZSkge1xuICBsZXQgcmVzdWx0ID0gW107XG4gIGxldCBwcm9jZXNzZWRQYXR0ZXJuID0gYnVpbGRNYXRjaChwYXR0ZXJuKTtcbiAgaWYgKHByb2Nlc3NlZFBhdHRlcm4oZXhwciwgcmVzdWx0KSAmJiBndWFyZC5hcHBseSh0aGlzLCByZXN1bHQpKSB7XG4gICAgcmV0dXJuIHJlc3VsdDtcbiAgfSBlbHNlIHtcbiAgICB0aHJvdyBuZXcgTWF0Y2hFcnJvcihleHByKTtcbiAgfVxufVxuXG5mdW5jdGlvbiBtYXRjaF9ub190aHJvdyhwYXR0ZXJuLCBleHByLCBndWFyZCA9ICgpID0+IHRydWUpIHtcbiAgdHJ5IHtcbiAgICByZXR1cm4gbWF0Y2gocGF0dGVybiwgZXhwciwgZ3VhcmQpO1xuICB9IGNhdGNoIChlKSB7XG4gICAgaWYgKGUgaW5zdGFuY2VvZiBNYXRjaEVycm9yKSB7XG4gICAgICByZXR1cm4gbnVsbDtcbiAgICB9XG5cbiAgICB0aHJvdyBlO1xuICB9XG59XG5cbnZhciBQYXR0ZXJucyA9IHtcbiAgZGVmbWF0Y2gsIG1hdGNoLCBNYXRjaEVycm9yLCBtYXRjaF9ub190aHJvdyxcbiAgdmFyaWFibGUsIHdpbGRjYXJkLCBzdGFydHNXaXRoLFxuICBjYXB0dXJlLCBoZWFkVGFpbCwgdHlwZSwgYm91bmQsIENhc2UsIG1ha2VfY2FzZVxufTtcblxuZnVuY3Rpb24gY2FsbF9wcm9wZXJ0eShpdGVtLCBwcm9wZXJ0eSkge1xuICBpZiAocHJvcGVydHkgaW4gaXRlbSkge1xuICAgIGl0ZW1bcHJvcGVydHldO1xuICAgIGlmIChpdGVtW3Byb3BlcnR5XSBpbnN0YW5jZW9mIEZ1bmN0aW9uKSB7XG4gICAgICByZXR1cm4gaXRlbVtwcm9wZXJ0eV0oKTtcbiAgICB9IGVsc2Uge1xuICAgICAgcmV0dXJuIGl0ZW1bcHJvcGVydHldO1xuICAgIH1cbiAgfSBlbHNlIGlmIChTeW1ib2wuZm9yKHByb3BlcnR5KSBpbiBpdGVtKSB7XG4gICAgbGV0IHByb3AgPSBTeW1ib2wuZm9yKHByb3BlcnR5KTtcbiAgICBpZiAoaXRlbVtwcm9wXSBpbnN0YW5jZW9mIEZ1bmN0aW9uKSB7XG4gICAgICByZXR1cm4gaXRlbVtwcm9wXSgpO1xuICAgIH0gZWxzZSB7XG4gICAgICByZXR1cm4gaXRlbVtwcm9wXTtcbiAgICB9XG4gIH1cblxuICB0aHJvdyBuZXcgRXJyb3IoYFByb3BlcnR5ICR7IHByb3BlcnR5IH0gbm90IGZvdW5kIGluICR7IGl0ZW0gfWApO1xufVxuXG5mdW5jdGlvbiBpc19pbnN0YW5jZV9vZih2YWx1ZSwgdHlwZSkge1xuICByZXR1cm4gdmFsdWUgaW5zdGFuY2VvZiB0eXBlO1xufVxuXG5mdW5jdGlvbiBzaXplJDIodGVybSkge1xuICByZXR1cm4gdGVybS5sZW5ndGg7XG59XG5cbmZ1bmN0aW9uIGlzX25pbCQxKHgpIHtcbiAgcmV0dXJuIHggPT09IG51bGw7XG59XG5cbmZ1bmN0aW9uIGlzX2F0b20kMSh4KSB7XG4gIHJldHVybiB0eXBlb2YgeCA9PT0gJ3N5bWJvbCc7XG59XG5cbmZ1bmN0aW9uIGlzX2JpbmFyeSQxKHgpIHtcbiAgcmV0dXJuIHR5cGVvZiB4ID09PSAnc3RyaW5nJyB8fCB4IGluc3RhbmNlb2YgU3RyaW5nO1xufVxuXG5mdW5jdGlvbiBpc19ib29sZWFuJDEoeCkge1xuICByZXR1cm4gdHlwZW9mIHggPT09ICdib29sZWFuJyB8fCB4IGluc3RhbmNlb2YgQm9vbGVhbjtcbn1cblxuZnVuY3Rpb24gaXNfZnVuY3Rpb24kMSh4LCBhcml0eSA9IC0xKSB7XG4gIHJldHVybiB0eXBlb2YgeCA9PT0gJ2Z1bmN0aW9uJyB8fCB4IGluc3RhbmNlb2YgRnVuY3Rpb247XG59XG5cbmZ1bmN0aW9uIGlzX2Zsb2F0JDEoeCkge1xuICByZXR1cm4gaXNfbnVtYmVyJDEoeCkgJiYgIU51bWJlci5pc0ludGVnZXIoeCk7XG59XG5cbmZ1bmN0aW9uIGlzX2ludGVnZXIkMSh4KSB7XG4gIHJldHVybiBOdW1iZXIuaXNJbnRlZ2VyKHgpO1xufVxuXG5mdW5jdGlvbiBpc19saXN0JDEoeCkge1xuICByZXR1cm4geCBpbnN0YW5jZW9mIEFycmF5O1xufVxuXG5mdW5jdGlvbiBpc19tYXAkMSh4KSB7XG4gIHJldHVybiB0eXBlb2YgeCA9PT0gJ29iamVjdCcgfHwgeCBpbnN0YW5jZW9mIE9iamVjdDtcbn1cblxuZnVuY3Rpb24gaXNfbnVtYmVyJDEoeCkge1xuICByZXR1cm4gdHlwZW9mIHggPT09ICdudW1iZXInO1xufVxuXG5mdW5jdGlvbiBpc190dXBsZSQxKHgpIHtcbiAgcmV0dXJuIHggaW5zdGFuY2VvZiBUdXBsZTtcbn1cblxuZnVuY3Rpb24gaXNfcGlkJDEoeCkge1xuICByZXR1cm4geCBpbnN0YW5jZW9mIFBJRDtcbn1cblxuZnVuY3Rpb24gaXNfcG9ydCQxKHgpIHtcbiAgcmV0dXJuIGZhbHNlO1xufVxuXG5mdW5jdGlvbiBpc19yZWZlcmVuY2UkMSh4KSB7XG4gIHJldHVybiBmYWxzZTtcbn1cblxuZnVuY3Rpb24gaXNfYml0c3RyaW5nJDEoeCkge1xuICByZXR1cm4gaXNfYmluYXJ5JDEoeCkgfHwgeCBpbnN0YW5jZW9mIEJpdFN0cmluZztcbn1cblxuZnVuY3Rpb24gYWRkKG9uZSwgdHdvKSB7XG4gIHJldHVybiBvbmUgKyB0d287XG59XG5cbmZ1bmN0aW9uIHN1YnRyYWN0KG9uZSwgdHdvKSB7XG4gIHJldHVybiBvbmUgKyB0d287XG59XG5cbmZ1bmN0aW9uIG11bHRpcGx5KG9uZSwgdHdvKSB7XG4gIHJldHVybiBvbmUgKyB0d287XG59XG5cbmZ1bmN0aW9uIGRpdmlkZShvbmUsIHR3bykge1xuICByZXR1cm4gb25lICsgdHdvO1xufVxuXG5mdW5jdGlvbiByZW1haW5kZXIob25lLCB0d28pIHtcbiAgcmV0dXJuIG9uZSArIHR3bztcbn1cblxuZnVuY3Rpb24gYXBwbHkkMSguLi5hcmdzKSB7XG4gIGlmIChhcmdzLmxlbmd0aCA9PT0gMikge1xuICAgIGFyZ3NbMF0uYXBwbHkobnVsbCwgYXJncy5zbGljZSgxKSk7XG4gIH0gZWxzZSB7XG4gICAgYXJnc1swXVthcmdzWzFdXS5hcHBseShudWxsLCBhcmdzLnNsaWNlKDIpKTtcbiAgfVxufVxuXG5mdW5jdGlvbiBuZXdfdHVwbGUoLi4uYXJncykge1xuICByZXR1cm4gbmV3IFR1cGxlKC4uLmFyZ3MpO1xufVxuXG5mdW5jdGlvbiBkdXBsaWNhdGUoZGF0YSwgc2l6ZSkge1xuICBsZXQgYXJyYXkgPSBbXTtcblxuICBmb3IgKHZhciBpID0gc2l6ZSAtIDE7IGkgPj0gMDsgaS0tKSB7XG4gICAgYXJyYXkucHVzaChkYXRhKTtcbiAgfVxuXG4gIHJldHVybiBhcnJheTtcbn1cblxuZnVuY3Rpb24gY29udGFpbnMobGVmdCwgcmlnaHQpIHtcbiAgZm9yIChsZXQgeCBvZiByaWdodCkge1xuICAgIGlmIChQYXR0ZXJucy5tYXRjaF9ub190aHJvdyhsZWZ0LCB4KSAhPSBudWxsKSB7XG4gICAgICByZXR1cm4gdHJ1ZTtcbiAgICB9XG4gIH1cblxuICByZXR1cm4gZmFsc2U7XG59XG5cbmZ1bmN0aW9uIHJldmVyc2UobGlzdCkge1xuICByZXR1cm4gbGlzdC5jb25jYXQoW10pLnJldmVyc2UoKTtcbn1cblxuZnVuY3Rpb24gZ2V0X2dsb2JhbCgpIHtcbiAgaWYgKHR5cGVvZiBzZWxmICE9PSAndW5kZWZpbmVkJykge1xuICAgIHJldHVybiBzZWxmO1xuICB9IGVsc2UgaWYgKHR5cGVvZiB3aW5kb3cgIT09ICd1bmRlZmluZWQnKSB7XG4gICAgcmV0dXJuIHdpbmRvdztcbiAgfSBlbHNlIGlmICh0eXBlb2YgZ2xvYmFsICE9PSAndW5kZWZpbmVkJykge1xuICAgIHJldHVybiBnbG9iYWw7XG4gIH1cblxuICB0aHJvdyBuZXcgRXJyb3IoJ05vIGdsb2JhbCBzdGF0ZSBmb3VuZCcpO1xufVxuXG5mdW5jdGlvbiBjb25jYXRfbGlzdHMobGVmdCwgcmlnaHQpIHtcbiAgcmV0dXJuIGxlZnQuY29uY2F0KHJpZ2h0KTtcbn1cblxuZnVuY3Rpb24gcHJlcGVuZF90b19saXN0KGxpc3QsIGl0ZW0pIHtcbiAgcmV0dXJuIFtpdGVtXS5jb25jYXQobGlzdCk7XG59XG5cbmZ1bmN0aW9uIGRlZnN0cnVjdChkZWZhdWx0cykge1xuICByZXR1cm4gY2xhc3Mge1xuICAgIGNvbnN0cnVjdG9yKHVwZGF0ZSA9IHt9KSB7XG4gICAgICBsZXQgdGhlX3ZhbHVlcyA9IE9iamVjdC5hc3NpZ24oZGVmYXVsdHMsIHVwZGF0ZSk7XG4gICAgICBPYmplY3QuYXNzaWduKHRoaXMsIHRoZV92YWx1ZXMpO1xuICAgIH1cblxuICAgIHN0YXRpYyBjcmVhdGUodXBkYXRlcyA9IHt9KSB7XG4gICAgICBsZXQgeCA9IG5ldyB0aGlzKHVwZGF0ZXMpO1xuICAgICAgcmV0dXJuIE9iamVjdC5mcmVlemUoeCk7XG4gICAgfVxuICB9O1xufVxuXG5mdW5jdGlvbiBkZWZleGNlcHRpb24oZGVmYXVsdHMpIHtcbiAgcmV0dXJuIGNsYXNzIGV4dGVuZHMgRXJyb3Ige1xuICAgIGNvbnN0cnVjdG9yKHVwZGF0ZSA9IHt9KSB7XG4gICAgICBsZXQgbWVzc2FnZSA9IHVwZGF0ZS5tZXNzYWdlIHx8ICcnO1xuICAgICAgc3VwZXIobWVzc2FnZSk7XG5cbiAgICAgIGxldCB0aGVfdmFsdWVzID0gT2JqZWN0LmFzc2lnbihkZWZhdWx0cywgdXBkYXRlKTtcbiAgICAgIE9iamVjdC5hc3NpZ24odGhpcywgdGhlX3ZhbHVlcyk7XG5cbiAgICAgIHRoaXMubmFtZSA9IHRoaXMuY29uc3RydWN0b3IubmFtZTtcbiAgICAgIHRoaXMubWVzc2FnZSA9IG1lc3NhZ2U7XG4gICAgICB0aGlzW1NwZWNpYWxGb3Jtcy5hdG9tKCdfX2V4Y2VwdGlvbl9fJyldID0gdHJ1ZTtcbiAgICAgIEVycm9yLmNhcHR1cmVTdGFja1RyYWNlKHRoaXMsIHRoaXMuY29uc3RydWN0b3IubmFtZSk7XG4gICAgfVxuXG4gICAgc3RhdGljIGNyZWF0ZSh1cGRhdGVzID0ge30pIHtcbiAgICAgIGxldCB4ID0gbmV3IHRoaXModXBkYXRlcyk7XG4gICAgICByZXR1cm4gT2JqZWN0LmZyZWV6ZSh4KTtcbiAgICB9XG4gIH07XG59XG5cbmZ1bmN0aW9uIGRlZnByb3RvY29sKHNwZWMpIHtcbiAgcmV0dXJuIG5ldyBQcm90b2NvbChzcGVjKTtcbn1cblxuZnVuY3Rpb24gZGVmaW1wbChwcm90b2NvbCwgdHlwZSwgaW1wbCkge1xuICBwcm90b2NvbC5pbXBsZW1lbnRhdGlvbih0eXBlLCBpbXBsKTtcbn1cblxuZnVuY3Rpb24gZ2V0X29iamVjdF9rZXlzKG9iaikge1xuICByZXR1cm4gT2JqZWN0LmtleXMob2JqKS5jb25jYXQoT2JqZWN0LmdldE93blByb3BlcnR5U3ltYm9scyhvYmopKTtcbn1cblxuZnVuY3Rpb24gaXNfdmFsaWRfY2hhcmFjdGVyKGNvZGVwb2ludCkge1xuICB0cnkge1xuICAgIHJldHVybiBTdHJpbmcuZnJvbUNvZGVQb2ludChjb2RlcG9pbnQpICE9IG51bGw7XG4gIH0gY2F0Y2ggKGUpIHtcbiAgICByZXR1cm4gZmFsc2U7XG4gIH1cbn1cblxuLy9odHRwczovL2RldmVsb3Blci5tb3ppbGxhLm9yZy9lbi1VUy9kb2NzL1dlYi9BUEkvV2luZG93QmFzZTY0L0Jhc2U2NF9lbmNvZGluZ19hbmRfZGVjb2RpbmcjU29sdXRpb25fMl8lRTIlODAlOTNfcmV3cml0ZV90aGVfRE9Nc19hdG9iKClfYW5kX2J0b2EoKV91c2luZ19KYXZhU2NyaXB0J3NfVHlwZWRBcnJheXNfYW5kX1VURi04XG5mdW5jdGlvbiBiNjRFbmNvZGVVbmljb2RlKHN0cikge1xuICByZXR1cm4gYnRvYShlbmNvZGVVUklDb21wb25lbnQoc3RyKS5yZXBsYWNlKC8lKFswLTlBLUZdezJ9KS9nLCBmdW5jdGlvbiAobWF0Y2gsIHAxKSB7XG4gICAgcmV0dXJuIFN0cmluZy5mcm9tQ2hhckNvZGUoJzB4JyArIHAxKTtcbiAgfSkpO1xufVxuXG52YXIgRnVuY3Rpb25zID0ge1xuICBjYWxsX3Byb3BlcnR5LFxuICBpc19pbnN0YW5jZV9vZixcbiAgc2l6ZTogc2l6ZSQyLFxuICBpc19uaWw6IGlzX25pbCQxLFxuICBpc19hdG9tOiBpc19hdG9tJDEsXG4gIGlzX2JpbmFyeTogaXNfYmluYXJ5JDEsXG4gIGlzX2Jvb2xlYW46IGlzX2Jvb2xlYW4kMSxcbiAgaXNfZnVuY3Rpb246IGlzX2Z1bmN0aW9uJDEsXG4gIGlzX2Zsb2F0OiBpc19mbG9hdCQxLFxuICBpc19pbnRlZ2VyOiBpc19pbnRlZ2VyJDEsXG4gIGlzX2xpc3Q6IGlzX2xpc3QkMSxcbiAgaXNfbWFwOiBpc19tYXAkMSxcbiAgaXNfbnVtYmVyOiBpc19udW1iZXIkMSxcbiAgaXNfdHVwbGU6IGlzX3R1cGxlJDEsXG4gIGlzX3BpZDogaXNfcGlkJDEsXG4gIGlzX3BvcnQ6IGlzX3BvcnQkMSxcbiAgaXNfcmVmZXJlbmNlOiBpc19yZWZlcmVuY2UkMSxcbiAgaXNfYml0c3RyaW5nOiBpc19iaXRzdHJpbmckMSxcbiAgYWRkLFxuICBzdWJ0cmFjdCxcbiAgbXVsdGlwbHksXG4gIGRpdmlkZSxcbiAgcmVtYWluZGVyLFxuICBhcHBseTogYXBwbHkkMSxcbiAgbmV3X3R1cGxlLFxuICBkdXBsaWNhdGUsXG4gIGNvbnRhaW5zLFxuICByZXZlcnNlLFxuICBnZXRfZ2xvYmFsLFxuICBjb25jYXRfbGlzdHMsXG4gIHByZXBlbmRfdG9fbGlzdCxcbiAgZGVmc3RydWN0LFxuICBkZWZleGNlcHRpb24sXG4gIGRlZnByb3RvY29sLFxuICBkZWZpbXBsLFxuICBnZXRfb2JqZWN0X2tleXMsXG4gIGlzX3ZhbGlkX2NoYXJhY3RlcixcbiAgYjY0RW5jb2RlVW5pY29kZVxufTtcblxuRnVuY3Rpb25zLmdldF9nbG9iYWwoKS5wcm9jZXNzZXMgPSBGdW5jdGlvbnMuZ2V0X2dsb2JhbCgpLnByb2Nlc3NlcyB8fCBuZXcgUHJvY2Vzc1N5c3RlbSgpO1xuXG5cblxudmFyIEMgPSBPYmplY3QuZnJlZXplKHtcblx0UHJvY2Vzc1N5c3RlbTogUHJvY2Vzc1N5c3RlbSxcblx0VHVwbGU6IFR1cGxlLFxuXHRQSUQ6IFBJRCxcblx0Qml0U3RyaW5nOiBCaXRTdHJpbmcsXG5cdFBhdHRlcm5zOiBQYXR0ZXJucyxcblx0SW50ZWdlcjogSW50ZWdlcixcblx0RmxvYXQ6IEZsb2F0LFxuXHRGdW5jdGlvbnM6IEZ1bmN0aW9ucyxcblx0TGlzdDogTGlzdCQxXG59KTtcblxubGV0IEVudW0gPSB7XG5cbiAgYWxsX19xbWFya19fOiBmdW5jdGlvbiAoY29sbGVjdGlvbiwgZnVuID0geCA9PiB4KSB7XG4gICAgZm9yIChsZXQgZWxlbSBvZiBjb2xsZWN0aW9uKSB7XG4gICAgICBpZiAoIWZ1bihlbGVtKSkge1xuICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICB9XG4gICAgfVxuXG4gICAgcmV0dXJuIHRydWU7XG4gIH0sXG5cbiAgYW55X19xbWFya19fOiBmdW5jdGlvbiAoY29sbGVjdGlvbiwgZnVuID0geCA9PiB4KSB7XG4gICAgZm9yIChsZXQgZWxlbSBvZiBjb2xsZWN0aW9uKSB7XG4gICAgICBpZiAoZnVuKGVsZW0pKSB7XG4gICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgfVxuICAgIH1cblxuICAgIHJldHVybiBmYWxzZTtcbiAgfSxcblxuICBhdDogZnVuY3Rpb24gKGNvbGxlY3Rpb24sIG4sIHRoZV9kZWZhdWx0ID0gbnVsbCkge1xuICAgIGlmIChuID4gdGhpcy5jb3VudChjb2xsZWN0aW9uKSB8fCBuIDwgMCkge1xuICAgICAgcmV0dXJuIHRoZV9kZWZhdWx0O1xuICAgIH1cblxuICAgIHJldHVybiBjb2xsZWN0aW9uW25dO1xuICB9LFxuXG4gIGNvbmNhdDogZnVuY3Rpb24gKC4uLmVudW1hYmxlcykge1xuICAgIHJldHVybiBlbnVtYWJsZXNbMF0uY29uY2F0KGVudW1hYmxlc1sxXSk7XG4gIH0sXG5cbiAgY291bnQ6IGZ1bmN0aW9uIChjb2xsZWN0aW9uLCBmdW4gPSBudWxsKSB7XG4gICAgaWYgKGZ1biA9PSBudWxsKSB7XG4gICAgICByZXR1cm4gY29sbGVjdGlvbi5sZW5ndGg7XG4gICAgfSBlbHNlIHtcbiAgICAgIHJldHVybiBjb2xsZWN0aW9uLmZpbHRlcihmdW4pLmxlbmd0aDtcbiAgICB9XG4gIH0sXG5cbiAgZHJvcDogZnVuY3Rpb24gKGNvbGxlY3Rpb24sIGNvdW50KSB7XG4gICAgcmV0dXJuIGNvbGxlY3Rpb24uc2xpY2UoY291bnQpO1xuICB9LFxuXG4gIGRyb3Bfd2hpbGU6IGZ1bmN0aW9uIChjb2xsZWN0aW9uLCBmdW4pIHtcbiAgICBsZXQgY291bnQgPSAwO1xuXG4gICAgZm9yIChsZXQgZWxlbSBvZiBjb2xsZWN0aW9uKSB7XG4gICAgICBpZiAoZnVuKGVsZW0pKSB7XG4gICAgICAgIGNvdW50ID0gY291bnQgKyAxO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgYnJlYWs7XG4gICAgICB9XG4gICAgfVxuXG4gICAgcmV0dXJuIGNvbGxlY3Rpb24uc2xpY2UoY291bnQpO1xuICB9LFxuXG4gIGVhY2g6IGZ1bmN0aW9uIChjb2xsZWN0aW9uLCBmdW4pIHtcbiAgICBmb3IgKGxldCBlbGVtIG9mIGNvbGxlY3Rpb24pIHtcbiAgICAgIGZ1bihlbGVtKTtcbiAgICB9XG4gIH0sXG5cbiAgZW1wdHlfX3FtYXJrX186IGZ1bmN0aW9uIChjb2xsZWN0aW9uKSB7XG4gICAgcmV0dXJuIGNvbGxlY3Rpb24ubGVuZ3RoID09PSAwO1xuICB9LFxuXG4gIGZldGNoOiBmdW5jdGlvbiAoY29sbGVjdGlvbiwgbikge1xuICAgIGlmIChLZXJuZWwuaXNfbGlzdChjb2xsZWN0aW9uKSkge1xuICAgICAgaWYgKG4gPCB0aGlzLmNvdW50KGNvbGxlY3Rpb24pICYmIG4gPj0gMCkge1xuICAgICAgICByZXR1cm4gbmV3IFR1cGxlKFN5bWJvbC5mb3IoJ29rJyksIGNvbGxlY3Rpb25bbl0pO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgcmV0dXJuIFN5bWJvbC5mb3IoJ2Vycm9yJyk7XG4gICAgICB9XG4gICAgfVxuXG4gICAgdGhyb3cgbmV3IEVycm9yKCdjb2xsZWN0aW9uIGlzIG5vdCBhbiBFbnVtZXJhYmxlJyk7XG4gIH0sXG5cbiAgZmV0Y2hfX2VtYXJrX186IGZ1bmN0aW9uIChjb2xsZWN0aW9uLCBuKSB7XG4gICAgaWYgKEtlcm5lbC5pc19saXN0KGNvbGxlY3Rpb24pKSB7XG4gICAgICBpZiAobiA8IHRoaXMuY291bnQoY29sbGVjdGlvbikgJiYgbiA+PSAwKSB7XG4gICAgICAgIHJldHVybiBjb2xsZWN0aW9uW25dO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdvdXQgb2YgYm91bmRzIGVycm9yJyk7XG4gICAgICB9XG4gICAgfVxuXG4gICAgdGhyb3cgbmV3IEVycm9yKCdjb2xsZWN0aW9uIGlzIG5vdCBhbiBFbnVtZXJhYmxlJyk7XG4gIH0sXG5cbiAgZmlsdGVyOiBmdW5jdGlvbiAoY29sbGVjdGlvbiwgZnVuKSB7XG4gICAgbGV0IHJlc3VsdCA9IFtdO1xuXG4gICAgZm9yIChsZXQgZWxlbSBvZiBjb2xsZWN0aW9uKSB7XG4gICAgICBpZiAoZnVuKGVsZW0pKSB7XG4gICAgICAgIHJlc3VsdC5wdXNoKGVsZW0pO1xuICAgICAgfVxuICAgIH1cblxuICAgIHJldHVybiByZXN1bHQ7XG4gIH0sXG5cbiAgZmlsdGVyX21hcDogZnVuY3Rpb24gKGNvbGxlY3Rpb24sIGZpbHRlciwgbWFwcGVyKSB7XG4gICAgcmV0dXJuIEVudW0ubWFwKEVudW0uZmlsdGVyKGNvbGxlY3Rpb24sIGZpbHRlciksIG1hcHBlcik7XG4gIH0sXG5cbiAgZmluZDogZnVuY3Rpb24gKGNvbGxlY3Rpb24sIGlmX25vbmUgPSBudWxsLCBmdW4pIHtcbiAgICBmb3IgKGxldCBlbGVtIG9mIGNvbGxlY3Rpb24pIHtcbiAgICAgIGlmIChmdW4oZWxlbSkpIHtcbiAgICAgICAgcmV0dXJuIGVsZW07XG4gICAgICB9XG4gICAgfVxuXG4gICAgcmV0dXJuIGlmX25vbmU7XG4gIH0sXG5cbiAgaW50bzogZnVuY3Rpb24gKGNvbGxlY3Rpb24sIGxpc3QpIHtcbiAgICByZXR1cm4gbGlzdC5jb25jYXQoY29sbGVjdGlvbik7XG4gIH0sXG5cbiAgbWFwOiBmdW5jdGlvbiAoY29sbGVjdGlvbiwgZnVuKSB7XG4gICAgbGV0IHJlc3VsdCA9IFtdO1xuXG4gICAgZm9yIChsZXQgZWxlbSBvZiBjb2xsZWN0aW9uKSB7XG4gICAgICByZXN1bHQucHVzaChmdW4oZWxlbSkpO1xuICAgIH1cblxuICAgIHJldHVybiByZXN1bHQ7XG4gIH0sXG5cbiAgbWFwX3JlZHVjZTogZnVuY3Rpb24gKGNvbGxlY3Rpb24sIGFjYywgZnVuKSB7XG4gICAgbGV0IG1hcHBlZCA9IExpc3QkMSgpO1xuICAgIGxldCB0aGVfYWNjID0gYWNjO1xuXG4gICAgZm9yICh2YXIgaSA9IDA7IGkgPCB0aGlzLmNvdW50KGNvbGxlY3Rpb24pOyBpKyspIHtcbiAgICAgIGxldCB0dXBsZSA9IGZ1bihjb2xsZWN0aW9uW2ldLCB0aGVfYWNjKTtcblxuICAgICAgdGhlX2FjYyA9IHR1cGxlLmdldCgxKTtcbiAgICAgIG1hcHBlZCA9IExpc3QkMSguLi5tYXBwZWQuY29uY2F0KFt0dXBsZS5nZXQoMCldKSk7XG4gICAgfVxuXG4gICAgcmV0dXJuIG5ldyBUdXBsZShtYXBwZWQsIHRoZV9hY2MpO1xuICB9LFxuXG4gIG1lbWJlcl9fcW1hcmtfXzogZnVuY3Rpb24gKGNvbGxlY3Rpb24sIHZhbHVlKSB7XG4gICAgcmV0dXJuIGNvbGxlY3Rpb24uaW5jbHVkZXModmFsdWUpO1xuICB9LFxuXG4gIHJlZHVjZTogZnVuY3Rpb24gKGNvbGxlY3Rpb24sIGFjYywgZnVuKSB7XG4gICAgbGV0IHRoZV9hY2MgPSBhY2M7XG5cbiAgICBmb3IgKHZhciBpID0gMDsgaSA8IHRoaXMuY291bnQoY29sbGVjdGlvbik7IGkrKykge1xuICAgICAgbGV0IHR1cGxlID0gZnVuKGNvbGxlY3Rpb25baV0sIHRoZV9hY2MpO1xuXG4gICAgICB0aGVfYWNjID0gdHVwbGUuZ2V0KDEpO1xuICAgIH1cblxuICAgIHJldHVybiB0aGVfYWNjO1xuICB9LFxuXG4gIHRha2U6IGZ1bmN0aW9uIChjb2xsZWN0aW9uLCBjb3VudCkge1xuICAgIHJldHVybiBjb2xsZWN0aW9uLnNsaWNlKDAsIGNvdW50KTtcbiAgfSxcblxuICB0YWtlX2V2ZXJ5OiBmdW5jdGlvbiAoY29sbGVjdGlvbiwgbnRoKSB7XG4gICAgbGV0IHJlc3VsdCA9IFtdO1xuICAgIGxldCBpbmRleCA9IDA7XG5cbiAgICBmb3IgKGxldCBlbGVtIG9mIGNvbGxlY3Rpb24pIHtcbiAgICAgIGlmIChpbmRleCAlIG50aCA9PT0gMCkge1xuICAgICAgICByZXN1bHQucHVzaChlbGVtKTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICByZXR1cm4gTGlzdCQxKC4uLnJlc3VsdCk7XG4gIH0sXG5cbiAgdGFrZV93aGlsZTogZnVuY3Rpb24gKGNvbGxlY3Rpb24sIGZ1bikge1xuICAgIGxldCBjb3VudCA9IDA7XG5cbiAgICBmb3IgKGxldCBlbGVtIG9mIGNvbGxlY3Rpb24pIHtcbiAgICAgIGlmIChmdW4oZWxlbSkpIHtcbiAgICAgICAgY291bnQgPSBjb3VudCArIDE7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBicmVhaztcbiAgICAgIH1cbiAgICB9XG5cbiAgICByZXR1cm4gY29sbGVjdGlvbi5zbGljZSgwLCBjb3VudCk7XG4gIH0sXG5cbiAgdG9fbGlzdDogZnVuY3Rpb24gKGNvbGxlY3Rpb24pIHtcbiAgICByZXR1cm4gY29sbGVjdGlvbjtcbiAgfVxufTtcblxubGV0IFNwZWNpYWxGb3JtcyQxID0ge1xuXG4gIGF0b206IGZ1bmN0aW9uIChfdmFsdWUpIHtcbiAgICByZXR1cm4gU3ltYm9sLmZvcihfdmFsdWUpO1xuICB9LFxuXG4gIGxpc3Q6IGZ1bmN0aW9uICguLi5hcmdzKSB7XG4gICAgcmV0dXJuIE9iamVjdC5mcmVlemUoYXJncyk7XG4gIH0sXG5cbiAgYml0c3RyaW5nOiBmdW5jdGlvbiAoLi4uYXJncykge1xuICAgIHJldHVybiBuZXcgQml0U3RyaW5nKC4uLmFyZ3MpO1xuICB9LFxuXG4gIGJvdW5kOiBmdW5jdGlvbiAoX3Zhcikge1xuICAgIHJldHVybiBQYXR0ZXJucy5ib3VuZChfdmFyKTtcbiAgfSxcblxuICBfY2FzZTogZnVuY3Rpb24gKGNvbmRpdGlvbiwgY2xhdXNlcykge1xuICAgIHJldHVybiBQYXR0ZXJucy5kZWZtYXRjaCguLi5jbGF1c2VzKShjb25kaXRpb24pO1xuICB9LFxuXG4gIGNvbmQ6IGZ1bmN0aW9uIChjbGF1c2VzKSB7XG4gICAgZm9yIChsZXQgY2xhdXNlIG9mIGNsYXVzZXMpIHtcbiAgICAgIGlmIChjbGF1c2VbMF0pIHtcbiAgICAgICAgcmV0dXJuIGNsYXVzZVsxXSgpO1xuICAgICAgfVxuICAgIH1cblxuICAgIHRocm93IG5ldyBFcnJvcigpO1xuICB9LFxuXG4gIGZuOiBmdW5jdGlvbiAoY2xhdXNlcykge1xuICAgIHJldHVybiBQYXR0ZXJucy5kZWZtYXRjaChjbGF1c2VzKTtcbiAgfSxcblxuICBtYXA6IGZ1bmN0aW9uIChvYmopIHtcbiAgICByZXR1cm4gT2JqZWN0LmZyZWV6ZShvYmopO1xuICB9LFxuXG4gIG1hcF91cGRhdGU6IGZ1bmN0aW9uIChtYXAsIHZhbHVlcykge1xuICAgIHJldHVybiBPYmplY3QuZnJlZXplKE9iamVjdC5hc3NpZ24oT2JqZWN0LmNyZWF0ZShtYXAuY29uc3RydWN0b3IucHJvdG90eXBlKSwgbWFwLCB2YWx1ZXMpKTtcbiAgfSxcblxuICBfZm9yOiBmdW5jdGlvbiAoY29sbGVjdGlvbnMsIGZ1biwgZmlsdGVyID0gKCkgPT4gdHJ1ZSwgaW50byA9IFtdLCBwcmV2aW91c1ZhbHVlcyA9IFtdKSB7XG4gICAgbGV0IHBhdHRlcm4gPSBjb2xsZWN0aW9uc1swXVswXTtcbiAgICBsZXQgY29sbGVjdGlvbiA9IGNvbGxlY3Rpb25zWzBdWzFdO1xuXG4gICAgaWYgKGNvbGxlY3Rpb25zLmxlbmd0aCA9PT0gMSkge1xuXG4gICAgICBmb3IgKGxldCBlbGVtIG9mIGNvbGxlY3Rpb24pIHtcbiAgICAgICAgbGV0IHIgPSBQYXR0ZXJucy5tYXRjaF9ub190aHJvdyhwYXR0ZXJuLCBlbGVtKTtcbiAgICAgICAgbGV0IGFyZ3MgPSBwcmV2aW91c1ZhbHVlcy5jb25jYXQocik7XG5cbiAgICAgICAgaWYgKHIgJiYgZmlsdGVyLmFwcGx5KHRoaXMsIGFyZ3MpKSB7XG4gICAgICAgICAgaW50byA9IEVudW0uaW50byhbZnVuLmFwcGx5KHRoaXMsIGFyZ3MpXSwgaW50byk7XG4gICAgICAgIH1cbiAgICAgIH1cblxuICAgICAgcmV0dXJuIGludG87XG4gICAgfSBlbHNlIHtcbiAgICAgIGxldCBfaW50byA9IFtdO1xuXG4gICAgICBmb3IgKGxldCBlbGVtIG9mIGNvbGxlY3Rpb24pIHtcbiAgICAgICAgbGV0IHIgPSBQYXR0ZXJucy5tYXRjaF9ub190aHJvdyhwYXR0ZXJuLCBlbGVtKTtcbiAgICAgICAgaWYgKHIpIHtcbiAgICAgICAgICBfaW50byA9IEVudW0uaW50byh0aGlzLl9mb3IoY29sbGVjdGlvbnMuc2xpY2UoMSksIGZ1biwgZmlsdGVyLCBfaW50bywgcHJldmlvdXNWYWx1ZXMuY29uY2F0KHIpKSwgaW50byk7XG4gICAgICAgIH1cbiAgICAgIH1cblxuICAgICAgcmV0dXJuIF9pbnRvO1xuICAgIH1cbiAgfSxcblxuICByZWNlaXZlOiBmdW5jdGlvbiAocmVjZWl2ZV9mdW4sIHRpbWVvdXRfaW5fbXMgPSBudWxsLCB0aW1lb3V0X2ZuID0gdGltZSA9PiB0cnVlKSB7XG4gICAgaWYgKHRpbWVvdXRfaW5fbXMgPT0gbnVsbCB8fCB0aW1lb3V0X2luX21zID09PSBTeXN0ZW0uZm9yKCdpbmZpbml0eScpKSB7XG4gICAgICB3aGlsZSAodHJ1ZSkge1xuICAgICAgICBpZiAoc2VsZi5tYWlsYm94Lmxlbmd0aCAhPT0gMCkge1xuICAgICAgICAgIGxldCBtZXNzYWdlID0gc2VsZi5tYWlsYm94WzBdO1xuICAgICAgICAgIHNlbGYubWFpbGJveCA9IHNlbGYubWFpbGJveC5zbGljZSgxKTtcbiAgICAgICAgICByZXR1cm4gcmVjZWl2ZV9mdW4obWVzc2FnZSk7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9IGVsc2UgaWYgKHRpbWVvdXRfaW5fbXMgPT09IDApIHtcbiAgICAgIGlmIChzZWxmLm1haWxib3gubGVuZ3RoICE9PSAwKSB7XG4gICAgICAgIGxldCBtZXNzYWdlID0gc2VsZi5tYWlsYm94WzBdO1xuICAgICAgICBzZWxmLm1haWxib3ggPSBzZWxmLm1haWxib3guc2xpY2UoMSk7XG4gICAgICAgIHJldHVybiByZWNlaXZlX2Z1bihtZXNzYWdlKTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHJldHVybiBudWxsO1xuICAgICAgfVxuICAgIH0gZWxzZSB7XG4gICAgICBsZXQgbm93ID0gRGF0ZS5ub3coKTtcbiAgICAgIHdoaWxlIChEYXRlLm5vdygpIDwgbm93ICsgdGltZW91dF9pbl9tcykge1xuICAgICAgICBpZiAoc2VsZi5tYWlsYm94Lmxlbmd0aCAhPT0gMCkge1xuICAgICAgICAgIGxldCBtZXNzYWdlID0gc2VsZi5tYWlsYm94WzBdO1xuICAgICAgICAgIHNlbGYubWFpbGJveCA9IHNlbGYubWFpbGJveC5zbGljZSgxKTtcbiAgICAgICAgICByZXR1cm4gcmVjZWl2ZV9mdW4obWVzc2FnZSk7XG4gICAgICAgIH1cbiAgICAgIH1cblxuICAgICAgcmV0dXJuIHRpbWVvdXRfZm4odGltZW91dF9pbl9tcyk7XG4gICAgfVxuICB9LFxuXG4gIHR1cGxlOiBmdW5jdGlvbiAoLi4uYXJncykge1xuICAgIHJldHVybiBuZXcgVHVwbGUoLi4uYXJncyk7XG4gIH0sXG5cbiAgX3RyeTogZnVuY3Rpb24gKGRvX2Z1biwgcmVzY3VlX2Z1bmN0aW9uLCBjYXRjaF9mdW4sIGVsc2VfZnVuY3Rpb24sIGFmdGVyX2Z1bmN0aW9uKSB7XG4gICAgbGV0IHJlc3VsdCA9IG51bGw7XG5cbiAgICB0cnkge1xuICAgICAgcmVzdWx0ID0gZG9fZnVuKCk7XG4gICAgfSBjYXRjaCAoZSkge1xuICAgICAgbGV0IGV4X3Jlc3VsdCA9IG51bGw7XG5cbiAgICAgIGlmIChyZXNjdWVfZnVuY3Rpb24pIHtcbiAgICAgICAgdHJ5IHtcbiAgICAgICAgICBleF9yZXN1bHQgPSByZXNjdWVfZnVuY3Rpb24oZSk7XG4gICAgICAgICAgcmV0dXJuIGV4X3Jlc3VsdDtcbiAgICAgICAgfSBjYXRjaCAoZXgpIHtcbiAgICAgICAgICBpZiAoZXggaW5zdGFuY2VvZiBQYXR0ZXJucy5NYXRjaEVycm9yKSB7XG4gICAgICAgICAgICB0aHJvdyBleDtcbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgIH1cblxuICAgICAgaWYgKGNhdGNoX2Z1bikge1xuICAgICAgICB0cnkge1xuICAgICAgICAgIGV4X3Jlc3VsdCA9IGNhdGNoX2Z1bihlKTtcbiAgICAgICAgICByZXR1cm4gZXhfcmVzdWx0O1xuICAgICAgICB9IGNhdGNoIChleCkge1xuICAgICAgICAgIGlmIChleCBpbnN0YW5jZW9mIFBhdHRlcm5zLk1hdGNoRXJyb3IpIHtcbiAgICAgICAgICAgIHRocm93IGV4O1xuICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgfVxuXG4gICAgICB0aHJvdyBlO1xuICAgIH0gZmluYWxseSB7XG4gICAgICBpZiAoYWZ0ZXJfZnVuY3Rpb24pIHtcbiAgICAgICAgYWZ0ZXJfZnVuY3Rpb24oKTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICBpZiAoZWxzZV9mdW5jdGlvbikge1xuICAgICAgdHJ5IHtcbiAgICAgICAgcmV0dXJuIGVsc2VfZnVuY3Rpb24ocmVzdWx0KTtcbiAgICAgIH0gY2F0Y2ggKGV4KSB7XG4gICAgICAgIGlmIChleCBpbnN0YW5jZW9mIFBhdHRlcm5zLk1hdGNoRXJyb3IpIHtcbiAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ05vIE1hdGNoIEZvdW5kIGluIEVsc2UnKTtcbiAgICAgICAgfVxuXG4gICAgICAgIHRocm93IGV4O1xuICAgICAgfVxuICAgIH0gZWxzZSB7XG4gICAgICByZXR1cm4gcmVzdWx0O1xuICAgIH1cbiAgfVxuXG59O1xuXG5mdW5jdGlvbiB0bChsaXN0KSB7XG4gIHJldHVybiBTcGVjaWFsRm9ybXMkMS5saXN0KC4uLmxpc3Quc2xpY2UoMSkpO1xufVxuXG5mdW5jdGlvbiBoZChsaXN0KSB7XG4gIHJldHVybiBsaXN0WzBdO1xufVxuXG5mdW5jdGlvbiBpc19uaWwoeCkge1xuICByZXR1cm4geCA9PT0gbnVsbDtcbn1cblxuZnVuY3Rpb24gaXNfYXRvbSh4KSB7XG4gIHJldHVybiB0eXBlb2YgeCA9PT0gJ3N5bWJvbCc7XG59XG5cbmZ1bmN0aW9uIGlzX2JpbmFyeSh4KSB7XG4gIHJldHVybiB0eXBlb2YgeCA9PT0gJ3N0cmluZycgfHwgeCBpbnN0YW5jZW9mIFN0cmluZztcbn1cblxuZnVuY3Rpb24gaXNfYm9vbGVhbih4KSB7XG4gIHJldHVybiB0eXBlb2YgeCA9PT0gJ2Jvb2xlYW4nIHx8IHggaW5zdGFuY2VvZiBCb29sZWFuO1xufVxuXG5mdW5jdGlvbiBpc19mdW5jdGlvbih4LCBhcml0eSA9IC0xKSB7XG4gIHJldHVybiB0eXBlb2YgeCA9PT0gJ2Z1bmN0aW9uJyB8fCB4IGluc3RhbmNlb2YgRnVuY3Rpb247XG59XG5cbmZ1bmN0aW9uIGlzX2Zsb2F0KHgpIHtcbiAgcmV0dXJuIGlzX251bWJlcih4KSAmJiAhTnVtYmVyLmlzSW50ZWdlcih4KTtcbn1cblxuZnVuY3Rpb24gaXNfaW50ZWdlcih4KSB7XG4gIHJldHVybiBOdW1iZXIuaXNJbnRlZ2VyKHgpO1xufVxuXG5mdW5jdGlvbiBpc19saXN0KHgpIHtcbiAgcmV0dXJuIHggaW5zdGFuY2VvZiBBcnJheTtcbn1cblxuZnVuY3Rpb24gaXNfbWFwKHgpIHtcbiAgcmV0dXJuIHR5cGVvZiB4ID09PSAnb2JqZWN0JyB8fCB4IGluc3RhbmNlb2YgT2JqZWN0O1xufVxuXG5mdW5jdGlvbiBpc19udW1iZXIoeCkge1xuICByZXR1cm4gdHlwZW9mIHggPT09ICdudW1iZXInO1xufVxuXG5mdW5jdGlvbiBpc190dXBsZSh4KSB7XG4gIHJldHVybiB4IGluc3RhbmNlb2YgVHVwbGU7XG59XG5cbmZ1bmN0aW9uIGxlbmd0aCh4KSB7XG4gIHJldHVybiB4Lmxlbmd0aDtcbn1cblxuZnVuY3Rpb24gaXNfcGlkKHgpIHtcbiAgcmV0dXJuIHggaW5zdGFuY2VvZiBQSUQ7XG59XG5cbmZ1bmN0aW9uIGlzX3BvcnQoeCkge1xuICByZXR1cm4gZmFsc2U7XG59XG5cbmZ1bmN0aW9uIGlzX3JlZmVyZW5jZSh4KSB7XG4gIHJldHVybiBmYWxzZTtcbn1cblxuZnVuY3Rpb24gaXNfYml0c3RyaW5nKHgpIHtcbiAgcmV0dXJuIGlzX2JpbmFyeSh4KSB8fCB4IGluc3RhbmNlb2YgQml0U3RyaW5nO1xufVxuXG5mdW5jdGlvbiBfX2luX18obGVmdCwgcmlnaHQpIHtcbiAgZm9yIChsZXQgeCBvZiByaWdodCkge1xuICAgIGlmIChtYXRjaF9fcW1hcmtfXyhsZWZ0LCB4KSkge1xuICAgICAgcmV0dXJuIHRydWU7XG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIGZhbHNlO1xufVxuXG5mdW5jdGlvbiBhYnMobnVtYmVyKSB7XG4gIHJldHVybiBNYXRoLmFicyhudW1iZXIpO1xufVxuXG5mdW5jdGlvbiByb3VuZChudW1iZXIpIHtcbiAgcmV0dXJuIE1hdGgucm91bmQobnVtYmVyKTtcbn1cblxuZnVuY3Rpb24gZWxlbSh0dXBsZSwgaW5kZXgpIHtcbiAgaWYgKGlzX2xpc3QodHVwbGUpKSB7XG4gICAgcmV0dXJuIHR1cGxlW2luZGV4XTtcbiAgfVxuXG4gIHJldHVybiB0dXBsZS5nZXQoaW5kZXgpO1xufVxuXG5mdW5jdGlvbiByZW0obGVmdCwgcmlnaHQpIHtcbiAgcmV0dXJuIGxlZnQgJSByaWdodDtcbn1cblxuZnVuY3Rpb24gZGl2KGxlZnQsIHJpZ2h0KSB7XG4gIHJldHVybiBsZWZ0IC8gcmlnaHQ7XG59XG5cbmZ1bmN0aW9uIGFuZChsZWZ0LCByaWdodCkge1xuICByZXR1cm4gbGVmdCAmJiByaWdodDtcbn1cblxuZnVuY3Rpb24gb3IobGVmdCwgcmlnaHQpIHtcbiAgcmV0dXJuIGxlZnQgfHwgcmlnaHQ7XG59XG5cbmZ1bmN0aW9uIG5vdChhcmcpIHtcbiAgcmV0dXJuICFhcmc7XG59XG5cbmZ1bmN0aW9uIGFwcGx5KC4uLmFyZ3MpIHtcbiAgaWYgKGFyZ3MubGVuZ3RoID09PSAzKSB7XG4gICAgbGV0IG1vZCA9IGFyZ3NbMF07XG4gICAgbGV0IGZ1bmMgPSBhcmdzWzFdO1xuICAgIGxldCBmdW5jX2FyZ3MgPSBhcmdzWzJdO1xuICAgIHJldHVybiBtb2RbZnVuY10uYXBwbHkobnVsbCwgZnVuY19hcmdzKTtcbiAgfSBlbHNlIHtcbiAgICBsZXQgZnVuYyA9IGFyZ3NbMF07XG4gICAgbGV0IGZ1bmNfYXJncyA9IGFyZ3NbMV07XG5cbiAgICByZXR1cm4gZnVuYy5hcHBseShudWxsLCBmdW5jX2FyZ3MpO1xuICB9XG59XG5cbmZ1bmN0aW9uIHRvX3N0cmluZyhhcmcpIHtcbiAgaWYgKGlzX3R1cGxlKGFyZykpIHtcbiAgICByZXR1cm4gYXJnLnRvU3RyaW5nKCk7XG4gIH1cblxuICByZXR1cm4gYXJnLnRvU3RyaW5nKCk7XG59XG5cbmZ1bmN0aW9uIG1hdGNoX19xbWFya19fKHBhdHRlcm4sIGV4cHIsIGd1YXJkID0gKCkgPT4gdHJ1ZSkge1xuICByZXR1cm4gUGF0dGVybnMubWF0Y2hfbm9fdGhyb3cocGF0dGVybiwgZXhwciwgZ3VhcmQpICE9IG51bGw7XG59XG5cbnZhciBLZXJuZWwgPSB7XG4gIFNwZWNpYWxGb3JtczogU3BlY2lhbEZvcm1zJDEsXG4gIHRsLFxuICBoZCxcbiAgaXNfbmlsLFxuICBpc19hdG9tLFxuICBpc19iaW5hcnksXG4gIGlzX2Jvb2xlYW4sXG4gIGlzX2Z1bmN0aW9uLFxuICBpc19mbG9hdCxcbiAgaXNfaW50ZWdlcixcbiAgaXNfbGlzdCxcbiAgaXNfbWFwLFxuICBpc19udW1iZXIsXG4gIGlzX3R1cGxlLFxuICBsZW5ndGgsXG4gIGlzX3BpZCxcbiAgaXNfcG9ydCxcbiAgaXNfcmVmZXJlbmNlLFxuICBpc19iaXRzdHJpbmcsXG4gIGluOiBfX2luX18sXG4gIGFicyxcbiAgcm91bmQsXG4gIGVsZW0sXG4gIHJlbSxcbiAgZGl2LFxuICBhbmQsXG4gIG9yLFxuICBub3QsXG4gIGFwcGx5LFxuICB0b19zdHJpbmcsXG4gIG1hdGNoX19xbWFya19fXG59O1xuXG5sZXQgTGlzdCA9IHt9O1xuXG5MaXN0LmRlbGV0ZSA9IGZ1bmN0aW9uIChsaXN0LCBpdGVtKSB7XG4gIGxldCBuZXdfdmFsdWUgPSBbXTtcbiAgbGV0IHZhbHVlX2ZvdW5kID0gZmFsc2U7XG5cbiAgZm9yIChsZXQgeCBvZiBsaXN0KSB7XG4gICAgaWYgKHggPT09IGl0ZW0gJiYgdmFsdWVfZm91bmQgIT09IGZhbHNlKSB7XG4gICAgICBuZXdfdmFsdWUucHVzaCh4KTtcbiAgICAgIHZhbHVlX2ZvdW5kID0gdHJ1ZTtcbiAgICB9IGVsc2UgaWYgKHggIT09IGl0ZW0pIHtcbiAgICAgIG5ld192YWx1ZS5wdXNoKHgpO1xuICAgIH1cbiAgfVxuXG4gIHJldHVybiBMaXN0JDEoLi4ubmV3X3ZhbHVlKTtcbn07XG5cbkxpc3QuZGVsZXRlX2F0ID0gZnVuY3Rpb24gKGxpc3QsIGluZGV4KSB7XG4gIGxldCBuZXdfdmFsdWUgPSBbXTtcblxuICBmb3IgKGxldCBpID0gMDsgaSA8IGxpc3QubGVuZ3RoOyBpKyspIHtcbiAgICBpZiAoaSAhPT0gaW5kZXgpIHtcbiAgICAgIG5ld192YWx1ZS5wdXNoKGxpc3RbaV0pO1xuICAgIH1cbiAgfVxuXG4gIHJldHVybiBMaXN0JDEoLi4ubmV3X3ZhbHVlKTtcbn07XG5cbkxpc3QuZHVwbGljYXRlID0gZnVuY3Rpb24gKGVsZW0sIG4pIHtcbiAgbGV0IG5ld192YWx1ZSA9IFtdO1xuXG4gIGZvciAodmFyIGkgPSAwOyBpIDwgbjsgaSsrKSB7XG4gICAgbmV3X3ZhbHVlLnB1c2goZWxlbSk7XG4gIH1cblxuICByZXR1cm4gTGlzdCQxKC4uLm5ld192YWx1ZSk7XG59O1xuXG5MaXN0LmZpcnN0ID0gZnVuY3Rpb24gKGxpc3QpIHtcbiAgcmV0dXJuIGxpc3RbMF07XG59O1xuXG5MaXN0LmZsYXR0ZW4gPSBmdW5jdGlvbiAobGlzdCwgdGFpbCA9IExpc3QkMSgpKSB7XG4gIGxldCBuZXdfdmFsdWUgPSBbXTtcblxuICBmb3IgKGxldCB4IG9mIGxpc3QpIHtcbiAgICBpZiAoS2VybmVsLmlzX2xpc3QoeCkpIHtcbiAgICAgIG5ld192YWx1ZSA9IG5ld192YWx1ZS5jb25jYXQoTGlzdC5mbGF0dGVuKHgpKTtcbiAgICB9IGVsc2Uge1xuICAgICAgbmV3X3ZhbHVlLnB1c2goeCk7XG4gICAgfVxuICB9XG5cbiAgbmV3X3ZhbHVlID0gbmV3X3ZhbHVlLmNvbmNhdCh0YWlsKTtcblxuICByZXR1cm4gTGlzdCQxKC4uLm5ld192YWx1ZSk7XG59O1xuXG5MaXN0LmZvbGRsID0gZnVuY3Rpb24gKGxpc3QsIGFjYywgZnVuYykge1xuICByZXR1cm4gbGlzdC5yZWR1Y2UoZnVuYywgYWNjKTtcbn07XG5cbkxpc3QuZm9sZHIgPSBmdW5jdGlvbiAobGlzdCwgYWNjLCBmdW5jKSB7XG4gIGxldCBuZXdfYWNjID0gYWNjO1xuXG4gIGZvciAodmFyIGkgPSBsaXN0Lmxlbmd0aCAtIDE7IGkgPj0gMDsgaS0tKSB7XG4gICAgbmV3X2FjYyA9IGZ1bmMobGlzdFtpXSwgbmV3X2FjYyk7XG4gIH1cblxuICByZXR1cm4gbmV3X2FjYztcbn07XG5cbkxpc3QuaW5zZXJ0X2F0ID0gZnVuY3Rpb24gKGxpc3QsIGluZGV4LCB2YWx1ZSkge1xuICBsZXQgbmV3X3ZhbHVlID0gW107XG5cbiAgZm9yIChsZXQgaSA9IDA7IGkgPCBsaXN0Lmxlbmd0aDsgaSsrKSB7XG4gICAgaWYgKGkgPT09IGluZGV4KSB7XG4gICAgICBuZXdfdmFsdWUucHVzaCh2YWx1ZSk7XG4gICAgICBuZXdfdmFsdWUucHVzaChsaXN0W2ldKTtcbiAgICB9IGVsc2Uge1xuICAgICAgbmV3X3ZhbHVlLnB1c2gobGlzdFtpXSk7XG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIExpc3QkMSguLi5uZXdfdmFsdWUpO1xufTtcblxuTGlzdC5rZXlkZWxldGUgPSBmdW5jdGlvbiAobGlzdCwga2V5LCBwb3NpdGlvbikge1xuICBsZXQgbmV3X2xpc3QgPSBbXTtcblxuICBmb3IgKGxldCBpID0gMDsgaSA8IGxpc3QubGVuZ3RoOyBpKyspIHtcbiAgICBpZiAoIUtlcm5lbC5tYXRjaF9fcW1hcmtfXyhsaXN0W2ldW3Bvc2l0aW9uXSwga2V5KSkge1xuICAgICAgbmV3X2xpc3QucHVzaChsaXN0W2ldKTtcbiAgICB9XG4gIH1cblxuICByZXR1cm4gTGlzdCQxKC4uLm5ld19saXN0KTtcbn07XG5cbkxpc3Qua2V5ZmluZCA9IGZ1bmN0aW9uIChsaXN0LCBrZXksIHBvc2l0aW9uLCBfZGVmYXVsdCA9IG51bGwpIHtcblxuICBmb3IgKGxldCBpID0gMDsgaSA8IGxpc3QubGVuZ3RoOyBpKyspIHtcbiAgICBpZiAoS2VybmVsLm1hdGNoX19xbWFya19fKGxpc3RbaV1bcG9zaXRpb25dLCBrZXkpKSB7XG4gICAgICByZXR1cm4gbGlzdFtpXTtcbiAgICB9XG4gIH1cblxuICByZXR1cm4gX2RlZmF1bHQ7XG59O1xuXG5MaXN0LmtleW1lbWJlcl9fcW1hcmtfXyA9IGZ1bmN0aW9uIChsaXN0LCBrZXksIHBvc2l0aW9uKSB7XG5cbiAgZm9yIChsZXQgaSA9IDA7IGkgPCBsaXN0Lmxlbmd0aDsgaSsrKSB7XG4gICAgaWYgKEtlcm5lbC5tYXRjaF9fcW1hcmtfXyhsaXN0W2ldW3Bvc2l0aW9uXSwga2V5KSkge1xuICAgICAgcmV0dXJuIHRydWU7XG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIGZhbHNlO1xufTtcblxuTGlzdC5rZXlyZXBsYWNlID0gZnVuY3Rpb24gKGxpc3QsIGtleSwgcG9zaXRpb24sIG5ld190dXBsZSkge1xuICBsZXQgbmV3X2xpc3QgPSBbXTtcblxuICBmb3IgKGxldCBpID0gMDsgaSA8IGxpc3QubGVuZ3RoOyBpKyspIHtcbiAgICBpZiAoIUtlcm5lbC5tYXRjaF9fcW1hcmtfXyhsaXN0W2ldW3Bvc2l0aW9uXSwga2V5KSkge1xuICAgICAgbmV3X2xpc3QucHVzaChsaXN0W2ldKTtcbiAgICB9IGVsc2Uge1xuICAgICAgbmV3X2xpc3QucHVzaChuZXdfdHVwbGUpO1xuICAgIH1cbiAgfVxuXG4gIHJldHVybiBMaXN0JDEoLi4ubmV3X2xpc3QpO1xufTtcblxuTGlzdC5rZXlzb3J0ID0gZnVuY3Rpb24gKGxpc3QsIHBvc2l0aW9uKSB7XG4gIGxldCBuZXdfbGlzdCA9IGxpc3Q7XG5cbiAgbmV3X2xpc3Quc29ydChmdW5jdGlvbiAoYSwgYikge1xuICAgIGlmIChwb3NpdGlvbiA9PT0gMCkge1xuICAgICAgaWYgKGFbcG9zaXRpb25dLnZhbHVlIDwgYltwb3NpdGlvbl0udmFsdWUpIHtcbiAgICAgICAgcmV0dXJuIC0xO1xuICAgICAgfVxuXG4gICAgICBpZiAoYVtwb3NpdGlvbl0udmFsdWUgPiBiW3Bvc2l0aW9uXS52YWx1ZSkge1xuICAgICAgICByZXR1cm4gMTtcbiAgICAgIH1cblxuICAgICAgcmV0dXJuIDA7XG4gICAgfSBlbHNlIHtcbiAgICAgIGlmIChhW3Bvc2l0aW9uXSA8IGJbcG9zaXRpb25dKSB7XG4gICAgICAgIHJldHVybiAtMTtcbiAgICAgIH1cblxuICAgICAgaWYgKGFbcG9zaXRpb25dID4gYltwb3NpdGlvbl0pIHtcbiAgICAgICAgcmV0dXJuIDE7XG4gICAgICB9XG5cbiAgICAgIHJldHVybiAwO1xuICAgIH1cbiAgfSk7XG5cbiAgcmV0dXJuIExpc3QkMSguLi5uZXdfbGlzdCk7XG59O1xuXG5MaXN0LmtleXN0b3JlID0gZnVuY3Rpb24gKGxpc3QsIGtleSwgcG9zaXRpb24sIG5ld190dXBsZSkge1xuICBsZXQgbmV3X2xpc3QgPSBbXTtcbiAgbGV0IHJlcGxhY2VkID0gZmFsc2U7XG5cbiAgZm9yIChsZXQgaSA9IDA7IGkgPCBsaXN0Lmxlbmd0aDsgaSsrKSB7XG4gICAgaWYgKCFLZXJuZWwubWF0Y2hfX3FtYXJrX18obGlzdFtpXVtwb3NpdGlvbl0sIGtleSkpIHtcbiAgICAgIG5ld19saXN0LnB1c2gobGlzdFtpXSk7XG4gICAgfSBlbHNlIHtcbiAgICAgIG5ld19saXN0LnB1c2gobmV3X3R1cGxlKTtcbiAgICAgIHJlcGxhY2VkID0gdHJ1ZTtcbiAgICB9XG4gIH1cblxuICBpZiAoIXJlcGxhY2VkKSB7XG4gICAgbmV3X2xpc3QucHVzaChuZXdfdHVwbGUpO1xuICB9XG5cbiAgcmV0dXJuIExpc3QkMSguLi5uZXdfbGlzdCk7XG59O1xuXG5MaXN0Lmxhc3QgPSBmdW5jdGlvbiAobGlzdCkge1xuICByZXR1cm4gbGlzdFtsaXN0Lmxlbmd0aCAtIDFdO1xufTtcblxuTGlzdC5yZXBsYWNlX2F0ID0gZnVuY3Rpb24gKGxpc3QsIGluZGV4LCB2YWx1ZSkge1xuICBsZXQgbmV3X3ZhbHVlID0gW107XG5cbiAgZm9yIChsZXQgaSA9IDA7IGkgPCBsaXN0Lmxlbmd0aDsgaSsrKSB7XG4gICAgaWYgKGkgPT09IGluZGV4KSB7XG4gICAgICBuZXdfdmFsdWUucHVzaCh2YWx1ZSk7XG4gICAgfSBlbHNlIHtcbiAgICAgIG5ld192YWx1ZS5wdXNoKGxpc3RbaV0pO1xuICAgIH1cbiAgfVxuXG4gIHJldHVybiBMaXN0JDEoLi4ubmV3X3ZhbHVlKTtcbn07XG5cbkxpc3QudXBkYXRlX2F0ID0gZnVuY3Rpb24gKGxpc3QsIGluZGV4LCBmdW4pIHtcbiAgbGV0IG5ld192YWx1ZSA9IFtdO1xuXG4gIGZvciAobGV0IGkgPSAwOyBpIDwgbGlzdC5jb3VudCgpOyBpKyspIHtcbiAgICBpZiAoaSA9PT0gaW5kZXgpIHtcbiAgICAgIG5ld192YWx1ZS5wdXNoKGZ1bihsaXN0LmdldChpKSkpO1xuICAgIH0gZWxzZSB7XG4gICAgICBuZXdfdmFsdWUucHVzaChsaXN0LmdldChpKSk7XG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIG5ld192YWx1ZTtcbn07XG5cbkxpc3Qud3JhcCA9IGZ1bmN0aW9uIChsaXN0KSB7XG4gIGlmIChLZXJuZWwuaXNfbGlzdChsaXN0KSkge1xuICAgIHJldHVybiBsaXN0O1xuICB9IGVsc2UgaWYgKGxpc3QgPT0gbnVsbCkge1xuICAgIHJldHVybiBMaXN0JDEoKTtcbiAgfSBlbHNlIHtcbiAgICByZXR1cm4gTGlzdCQxKGxpc3QpO1xuICB9XG59O1xuXG5MaXN0LnppcCA9IGZ1bmN0aW9uIChsaXN0X29mX2xpc3RzKSB7XG4gIGlmIChsaXN0X29mX2xpc3RzLmxlbmd0aCA9PT0gMCkge1xuICAgIHJldHVybiBMaXN0JDEoKTtcbiAgfVxuXG4gIGxldCBuZXdfdmFsdWUgPSBbXTtcbiAgbGV0IHNtYWxsZXN0X2xlbmd0aCA9IGxpc3Rfb2ZfbGlzdHNbMF07XG5cbiAgZm9yIChsZXQgeCBvZiBsaXN0X29mX2xpc3RzKSB7XG4gICAgaWYgKHgubGVuZ3RoIDwgc21hbGxlc3RfbGVuZ3RoKSB7XG4gICAgICBzbWFsbGVzdF9sZW5ndGggPSB4Lmxlbmd0aDtcbiAgICB9XG4gIH1cblxuICBmb3IgKGxldCBpID0gMDsgaSA8IHNtYWxsZXN0X2xlbmd0aDsgaSsrKSB7XG4gICAgbGV0IGN1cnJlbnRfdmFsdWUgPSBbXTtcbiAgICBmb3IgKGxldCBqID0gMDsgaiA8IGxpc3Rfb2ZfbGlzdHMubGVuZ3RoOyBqKyspIHtcbiAgICAgIGN1cnJlbnRfdmFsdWUucHVzaChsaXN0X29mX2xpc3RzW2pdW2ldKTtcbiAgICB9XG5cbiAgICBuZXdfdmFsdWUucHVzaChuZXcgVHVwbGUoLi4uY3VycmVudF92YWx1ZSkpO1xuICB9XG5cbiAgcmV0dXJuIExpc3QkMSguLi5uZXdfdmFsdWUpO1xufTtcblxuTGlzdC50b190dXBsZSA9IGZ1bmN0aW9uIChsaXN0KSB7XG4gIHJldHVybiBuZXcgVHVwbGUoLi4ubGlzdCk7XG59O1xuXG5MaXN0LmFwcGVuZCA9IGZ1bmN0aW9uIChsaXN0LCB2YWx1ZSkge1xuICByZXR1cm4gTGlzdCQxKC4uLmxpc3QuY29uY2F0KFt2YWx1ZV0pKTtcbn07XG5cbkxpc3QucHJlcGVuZCA9IGZ1bmN0aW9uIChsaXN0LCB2YWx1ZSkge1xuICByZXR1cm4gTGlzdCQxKC4uLlt2YWx1ZV0uY29uY2F0KGxpc3QpKTtcbn07XG5cbkxpc3QuY29uY2F0ID0gZnVuY3Rpb24gKGxlZnQsIHJpZ2h0KSB7XG4gIHJldHVybiBsZWZ0LmNvbmNhdChyaWdodCk7XG59O1xuXG5sZXQgS2V5d29yZCA9IHt9O1xuXG5LZXl3b3JkLmhhc19rZXlfX3FtYXJrX18gPSBmdW5jdGlvbiAoa2V5d29yZHMsIGtleSkge1xuICBmb3IgKGxldCBrZXl3b3JkIG9mIGtleXdvcmRzKSB7XG4gICAgaWYgKEtlcm5lbC5lbGVtKGtleXdvcmQsIDApID09IGtleSkge1xuICAgICAgcmV0dXJuIHRydWU7XG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIGZhbHNlO1xufTtcblxuS2V5d29yZC5nZXQgPSBmdW5jdGlvbiAoa2V5d29yZHMsIGtleSwgdGhlX2RlZmF1bHQgPSBudWxsKSB7XG4gIGZvciAobGV0IGtleXdvcmQgb2Yga2V5d29yZHMpIHtcbiAgICBpZiAoS2VybmVsLmVsZW0oa2V5d29yZCwgMCkgPT0ga2V5KSB7XG4gICAgICByZXR1cm4gS2VybmVsLmVsZW0oa2V5d29yZCwgMSk7XG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIHRoZV9kZWZhdWx0O1xufTtcblxuZnVuY3Rpb24gYm5vdChleHByKSB7XG4gIHJldHVybiB+ZXhwcjtcbn1cblxuZnVuY3Rpb24gYmFuZChsZWZ0LCByaWdodCkge1xuICByZXR1cm4gbGVmdCAmIHJpZ2h0O1xufVxuXG5mdW5jdGlvbiBib3IobGVmdCwgcmlnaHQpIHtcbiAgcmV0dXJuIGxlZnQgfCByaWdodDtcbn1cblxuZnVuY3Rpb24gYnNsKGxlZnQsIHJpZ2h0KSB7XG4gIHJldHVybiBsZWZ0IDw8IHJpZ2h0O1xufVxuXG5mdW5jdGlvbiBic3IobGVmdCwgcmlnaHQpIHtcbiAgcmV0dXJuIGxlZnQgPj4gcmlnaHQ7XG59XG5cbmZ1bmN0aW9uIGJ4b3IobGVmdCwgcmlnaHQpIHtcbiAgcmV0dXJuIGxlZnQgXiByaWdodDtcbn1cblxudmFyIGJpdHdpc2UgPSB7XG4gIGJub3QsXG4gIGJhbmQsXG4gIGJvcixcbiAgYnNsLFxuICBic3IsXG4gIGJ4b3Jcbn07XG5cbmZ1bmN0aW9uIF9fbmV3X18oKSB7XG4gIHJldHVybiBTcGVjaWFsRm9ybXMkMS5tYXAoe30pO1xufVxuXG5mdW5jdGlvbiBrZXlzKG1hcCkge1xuICByZXR1cm4gRnVuY3Rpb25zLmdldF9vYmplY3Rfa2V5cyhtYXApO1xufVxuXG5mdW5jdGlvbiBzaXplKG1hcCkge1xuICByZXR1cm4ga2V5cyhtYXApLmxlbmd0aDtcbn1cblxuZnVuY3Rpb24gdG9fbGlzdChtYXApIHtcbiAgbGV0IG1hcF9rZXlzID0ga2V5cyhtYXApO1xuICBsZXQgbGlzdCA9IFtdO1xuXG4gIGZvciAobGV0IGtleSBvZiBtYXBfa2V5cykge1xuICAgIGxpc3QucHVzaChuZXcgVHVwbGUoa2V5LCBtYXBba2V5XSkpO1xuICB9XG5cbiAgcmV0dXJuIExpc3QkMSguLi5saXN0KTtcbn1cblxuZnVuY3Rpb24gdmFsdWVzKG1hcCkge1xuICBsZXQgbWFwX2tleXMgPSBrZXlzKG1hcCk7XG4gIGxldCBsaXN0ID0gW107XG5cbiAgZm9yIChsZXQga2V5IG9mIG1hcF9rZXlzKSB7XG4gICAgbGlzdC5wdXNoKG1hcFtrZXldKTtcbiAgfVxuXG4gIHJldHVybiBMaXN0JDEoLi4ubGlzdCk7XG59XG5cbmZ1bmN0aW9uIGZyb21fc3RydWN0KHN0cnVjdCkge1xuICBsZXQgbWFwID0gT2JqZWN0LmFzc2lnbih7fSwgc3RydWN0KTtcbiAgZGVsZXRlIG1hcFtTeW1ib2wuZm9yKCdfX3N0cnVjdF9fJyldO1xuXG4gIHJldHVybiBTcGVjaWFsRm9ybXMkMS5tYXAobWFwKTtcbn1cblxuZnVuY3Rpb24gX19kZWxldGVfXyhtYXAsIGtleSkge1xuICBsZXQgbmV3X21hcCA9IE9iamVjdC5hc3NpZ24oe30sIG1hcCk7XG5cbiAgZGVsZXRlIG5ld19tYXBba2V5XTtcblxuICByZXR1cm4gU3BlY2lhbEZvcm1zJDEubWFwKG5ld19tYXApO1xufVxuXG5mdW5jdGlvbiBlcXVhbF9fcW1hcmtfXyhtYXAxLCBtYXAyKSB7XG4gIHJldHVybiBtYXAxID09PSBtYXAyO1xufVxuXG5mdW5jdGlvbiBmZXRjaF9fZW1hcmtfXyhtYXAsIGtleSkge1xuICBpZiAoa2V5IGluIG1hcCkge1xuICAgIHJldHVybiBtYXBba2V5XTtcbiAgfVxuXG4gIHRocm93IG5ldyBFcnJvcignS2V5IG5vdCBmb3VuZC4nKTtcbn1cblxuZnVuY3Rpb24gZmV0Y2gobWFwLCBrZXkpIHtcbiAgaWYgKGtleSBpbiBtYXApIHtcbiAgICByZXR1cm4gbmV3IFR1cGxlKFN5bWJvbC5mb3IoJ29rJyksIG1hcFtrZXldKTtcbiAgfVxuXG4gIHJldHVybiBTeW1ib2wuZm9yKCdlcnJvcicpO1xufVxuXG5mdW5jdGlvbiBoYXNfa2V5X19xbWFya19fKG1hcCwga2V5KSB7XG4gIHJldHVybiBrZXkgaW4gbWFwO1xufVxuXG5mdW5jdGlvbiBzcGxpdChtYXAsIGtleXMpIHtcbiAgbGV0IHNwbGl0MSA9IHt9O1xuICBsZXQgc3BsaXQyID0ge307XG5cbiAgZm9yIChsZXQga2V5IG9mIEZ1bmN0aW9ucy5nZXRfb2JqZWN0X2tleXMobWFwKSkge1xuICAgIGlmIChrZXlzLmluZGV4T2Yoa2V5KSA+IC0xKSB7XG4gICAgICBzcGxpdDFba2V5XSA9IG1hcFtrZXldO1xuICAgIH0gZWxzZSB7XG4gICAgICBzcGxpdDJba2V5XSA9IG1hcFtrZXldO1xuICAgIH1cbiAgfVxuXG4gIHJldHVybiBuZXcgVHVwbGUoU3BlY2lhbEZvcm1zJDEubWFwKHNwbGl0MSksIFNwZWNpYWxGb3JtcyQxLm1hcChzcGxpdDIpKTtcbn1cblxuZnVuY3Rpb24gdGFrZShtYXAsIGtleXMpIHtcbiAgbGV0IHNwbGl0MSA9IHt9O1xuXG4gIGZvciAobGV0IGtleSBvZiBGdW5jdGlvbnMuZ2V0X29iamVjdF9rZXlzKG1hcCkpIHtcbiAgICBpZiAoa2V5cy5pbmRleE9mKGtleSkgPiAtMSkge1xuICAgICAgc3BsaXQxW2tleV0gPSBtYXBba2V5XTtcbiAgICB9XG4gIH1cblxuICByZXR1cm4gU3BlY2lhbEZvcm1zJDEubWFwKHNwbGl0MSk7XG59XG5cbmZ1bmN0aW9uIGRyb3AobWFwLCBrZXlzKSB7XG4gIGxldCBzcGxpdDEgPSB7fTtcblxuICBmb3IgKGxldCBrZXkgb2YgRnVuY3Rpb25zLmdldF9vYmplY3Rfa2V5cyhtYXApKSB7XG4gICAgaWYgKGtleXMuaW5kZXhPZihrZXkpID09PSAtMSkge1xuICAgICAgc3BsaXQxW2tleV0gPSBtYXBba2V5XTtcbiAgICB9XG4gIH1cblxuICByZXR1cm4gU3BlY2lhbEZvcm1zJDEubWFwKHNwbGl0MSk7XG59XG5cbmZ1bmN0aW9uIHB1dF9uZXcobWFwLCBrZXksIHZhbHVlKSB7XG4gIGlmIChrZXkgaW4gbWFwKSB7XG4gICAgcmV0dXJuIG1hcDtcbiAgfVxuXG4gIGxldCBuZXdfbWFwID0gT2JqZWN0LmFzc2lnbih7fSwgbWFwKTtcbiAgbmV3X21hcFtrZXldID0gdmFsdWU7XG5cbiAgcmV0dXJuIFNwZWNpYWxGb3JtcyQxLm1hcChuZXdfbWFwKTtcbn1cblxuZnVuY3Rpb24gcHV0X25ld19sYXp5KG1hcCwga2V5LCBmdW4pIHtcbiAgaWYgKGtleSBpbiBtYXApIHtcbiAgICByZXR1cm4gbWFwO1xuICB9XG5cbiAgbGV0IG5ld19tYXAgPSBPYmplY3QuYXNzaWduKHt9LCBtYXApO1xuICBuZXdfbWFwW2tleV0gPSBmdW4oKTtcblxuICByZXR1cm4gU3BlY2lhbEZvcm1zJDEubWFwKG5ld19tYXApO1xufVxuXG5mdW5jdGlvbiBnZXRfYW5kX3VwZGF0ZShtYXAsIGtleSwgZnVuKSB7XG4gIGlmIChrZXkgaW4gbWFwKSB7XG4gICAgcmV0dXJuIG1hcDtcbiAgfVxuXG4gIGxldCBuZXdfbWFwID0gT2JqZWN0LmFzc2lnbih7fSwgbWFwKTtcbiAgbmV3X21hcFtrZXldID0gZnVuKG1hcFtrZXldKTtcblxuICByZXR1cm4gU3BlY2lhbEZvcm1zJDEubWFwKG5ld19tYXApO1xufVxuXG5mdW5jdGlvbiBwb3BfbGF6eShtYXAsIGtleSwgZnVuKSB7XG4gIGlmICgha2V5IGluIG1hcCkge1xuICAgIHJldHVybiBuZXcgVHVwbGUoZnVuKCksIG1hcCk7XG4gIH1cblxuICBsZXQgbmV3X21hcCA9IE9iamVjdC5hc3NpZ24oe30sIG1hcCk7XG4gIGxldCB2YWx1ZSA9IGZ1bihuZXdfbWFwW2tleV0pO1xuICBkZWxldGUgbmV3X21hcFtrZXldO1xuXG4gIHJldHVybiBuZXcgVHVwbGUodmFsdWUsIG5ld19tYXApO1xufVxuXG5mdW5jdGlvbiBwb3AobWFwLCBrZXksIF9kZWZhdWx0ID0gbnVsbCkge1xuICBpZiAoIWtleSBpbiBtYXApIHtcbiAgICByZXR1cm4gbmV3IFR1cGxlKF9kZWZhdWx0LCBtYXApO1xuICB9XG5cbiAgbGV0IG5ld19tYXAgPSBPYmplY3QuYXNzaWduKHt9LCBtYXApO1xuICBsZXQgdmFsdWUgPSBuZXdfbWFwW2tleV07XG4gIGRlbGV0ZSBuZXdfbWFwW2tleV07XG5cbiAgcmV0dXJuIG5ldyBUdXBsZSh2YWx1ZSwgbmV3X21hcCk7XG59XG5cbmZ1bmN0aW9uIGdldF9sYXp5KG1hcCwga2V5LCBmdW4pIHtcbiAgaWYgKCFrZXkgaW4gbWFwKSB7XG4gICAgcmV0dXJuIGZ1bigpO1xuICB9XG5cbiAgcmV0dXJuIGZ1bihtYXBba2V5XSk7XG59XG5cbmZ1bmN0aW9uIGdldChtYXAsIGtleSwgX2RlZmF1bHQgPSBudWxsKSB7XG4gIGlmICgha2V5IGluIG1hcCkge1xuICAgIHJldHVybiBfZGVmYXVsdDtcbiAgfVxuXG4gIHJldHVybiBtYXBba2V5XTtcbn1cblxuZnVuY3Rpb24gcHV0KG1hcCwga2V5LCB2YWwpIHtcbiAgbGV0IG5ld19tYXAgPSBPYmplY3Qoe30sIG1hcCk7XG4gIG5ld19tYXBba2V5XSA9IHZhbDtcblxuICByZXR1cm4gU3BlY2lhbEZvcm1zJDEubWFwKG5ld19tYXApO1xufVxuXG5mdW5jdGlvbiB1cGRhdGVfX2VtYXJrX18obWFwLCBrZXksIGZ1bikge1xuICBpZiAoIWtleSBpbiBtYXApIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoJ0tleSBub3QgZm91bmQnKTtcbiAgfVxuXG4gIGxldCBuZXdfbWFwID0gT2JqZWN0KHt9LCBtYXApO1xuICBuZXdfbWFwW2tleV0gPSBmdW4obWFwW2tleV0pO1xuXG4gIHJldHVybiBTcGVjaWFsRm9ybXMkMS5tYXAobmV3X21hcCk7XG59XG5cbmZ1bmN0aW9uIHVwZGF0ZShtYXAsIGtleSwgaW5pdGlhbCwgZnVuKSB7XG4gIGxldCBuZXdfbWFwID0gT2JqZWN0KHt9LCBtYXApO1xuXG4gIGlmICgha2V5IGluIG1hcCkge1xuICAgIG5ld19tYXBba2V5XSA9IGluaXRpYWw7XG4gIH0gZWxzZSB7XG4gICAgbmV3X21hcFtrZXldID0gZnVuKG1hcFtrZXldKTtcbiAgfVxuXG4gIHJldHVybiBTcGVjaWFsRm9ybXMkMS5tYXAobmV3X21hcCk7XG59XG5cbnZhciBtYXAgPSB7XG4gIG5ldzogX19uZXdfXyxcbiAga2V5cyxcbiAgc2l6ZSxcbiAgdG9fbGlzdCxcbiAgdmFsdWVzLFxuICBmcm9tX3N0cnVjdCxcbiAgZGVsZXRlOiBfX2RlbGV0ZV9fLFxuICBkcm9wLFxuICBlcXVhbF9fcW1hcmtfXyxcbiAgZmV0Y2hfX2VtYXJrX18sXG4gIGZldGNoLFxuICBoYXNfa2V5X19xbWFya19fLFxuICBzcGxpdCxcbiAgdGFrZSxcbiAgcHV0X25ldyxcbiAgcHV0X25ld19sYXp5LFxuICBnZXRfYW5kX3VwZGF0ZSxcbiAgcG9wX2xhenksXG4gIHBvcCxcbiAgZ2V0X2xhenksXG4gIGdldCxcbiAgcHV0LFxuICB1cGRhdGVfX2VtYXJrX18sXG4gIHVwZGF0ZVxufTtcblxuZnVuY3Rpb24gX19uZXdfXyQxKCkge1xuICByZXR1cm4gU3BlY2lhbEZvcm1zJDEubWFwKHsgW1N5bWJvbC5mb3IoJ19fc3RydWN0X18nKV06IFN5bWJvbC5mb3IoJ01hcFNldCcpLCBzZXQ6IExpc3QkMSgpIH0pO1xufVxuXG5mdW5jdGlvbiBzaXplJDEobWFwKSB7XG4gIHJldHVybiBtYXAuc2V0Lmxlbmd0aDtcbn1cblxuZnVuY3Rpb24gdG9fbGlzdCQxKG1hcCkge1xuICByZXR1cm4gbWFwLnNldDtcbn1cblxuZnVuY3Rpb24gX19kZWxldGVfXyQxKHNldCwgdGVybSkge1xuICBsZXQgbmV3X2xpc3QgPSBMaXN0LmRlbGV0ZShzZXQuc2V0LCB0ZXJtKTtcblxuICBsZXQgbmV3X21hcCA9IE9iamVjdC5hc3NpZ24oe30sIHNldCk7XG4gIG5ld19tYXAuc2V0ID0gbmV3X2xpc3Q7XG4gIHJldHVybiBTcGVjaWFsRm9ybXMkMS5tYXAobmV3X21hcCk7XG59XG5cbmZ1bmN0aW9uIHB1dCQxKHNldCwgdGVybSkge1xuICBpZiAoc2V0LnNldC5pbmRleE9mKHRlcm0pID09PSAtMSkge1xuICAgIGxldCBuZXdfbGlzdCA9IExpc3QuYXBwZW5kKHNldC5zZXQsIHRlcm0pO1xuXG4gICAgbGV0IG5ld19tYXAgPSBPYmplY3QuYXNzaWduKHt9LCBzZXQpO1xuICAgIG5ld19tYXAuc2V0ID0gbmV3X2xpc3Q7XG4gICAgcmV0dXJuIFNwZWNpYWxGb3JtcyQxLm1hcChuZXdfbWFwKTtcbiAgfVxuXG4gIHJldHVybiBzZXQ7XG59XG5cbmZ1bmN0aW9uIGRpZmZlcmVuY2Uoc2V0MSwgc2V0Mikge1xuICBsZXQgbmV3X21hcCA9IE9iamVjdC5hc3NpZ24oe30sIHNldDEpO1xuXG4gIGZvciAobGV0IHZhbCBvZiBzZXQxLnNldCkge1xuICAgIGlmIChtZW1iZXJfX3FtYXJrX18oc2V0MiwgdmFsKSkge1xuICAgICAgbmV3X21hcC5zZXQgPSBMaXN0LmRlbGV0ZShuZXdfbWFwLnNldCwgdmFsKTtcbiAgICB9XG4gIH1cblxuICByZXR1cm4gU3BlY2lhbEZvcm1zJDEubWFwKG5ld19tYXApO1xufVxuXG5mdW5jdGlvbiBpbnRlcnNlY3Rpb24oc2V0MSwgc2V0Mikge1xuICBsZXQgbmV3X21hcCA9IE9iamVjdC5hc3NpZ24oe30sIHNldDEpO1xuXG4gIGZvciAobGV0IHZhbCBvZiBzZXQxLnNldCkge1xuICAgIGlmICghbWVtYmVyX19xbWFya19fKHNldDIsIHZhbCkpIHtcbiAgICAgIG5ld19tYXAuc2V0ID0gTGlzdC5kZWxldGUobmV3X21hcC5zZXQsIHZhbCk7XG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIFNwZWNpYWxGb3JtcyQxLm1hcChuZXdfbWFwKTtcbn1cblxuZnVuY3Rpb24gdW5pb24oc2V0MSwgc2V0Mikge1xuICBsZXQgbmV3X21hcCA9IHNldDE7XG5cbiAgZm9yIChsZXQgdmFsIG9mIHNldDIuc2V0KSB7XG4gICAgbmV3X21hcCA9IHB1dCQxKG5ld19tYXAsIHZhbCk7XG4gIH1cblxuICByZXR1cm4gU3BlY2lhbEZvcm1zJDEubWFwKG5ld19tYXApO1xufVxuXG5mdW5jdGlvbiBkaXNqb2luX19xbWFya19fKHNldDEsIHNldDIpIHtcbiAgZm9yIChsZXQgdmFsIG9mIHNldDEuc2V0KSB7XG4gICAgaWYgKG1lbWJlcl9fcW1hcmtfXyhzZXQyLCB2YWwpKSB7XG4gICAgICByZXR1cm4gZmFsc2U7XG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIHRydWU7XG59XG5cbmZ1bmN0aW9uIG1lbWJlcl9fcW1hcmtfXyhzZXQsIHZhbHVlKSB7XG4gIHJldHVybiBzZXQuc2V0LmluZGV4T2YodmFsdWUpID49IDA7XG59XG5cbmZ1bmN0aW9uIGVxdWFsX19xbWFya19fJDEoc2V0MSwgc2V0Mikge1xuICByZXR1cm4gc2V0MS5zZXQgPT09IHNldDIuc2V0O1xufVxuXG5mdW5jdGlvbiBzdWJzZXRfX3FtYXJrX18oc2V0MSwgc2V0Mikge1xuICBmb3IgKGxldCB2YWwgb2Ygc2V0MS5zZXQpIHtcbiAgICBpZiAoIW1lbWJlcl9fcW1hcmtfXyhzZXQyLCB2YWwpKSB7XG4gICAgICByZXR1cm4gZmFsc2U7XG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIHRydWU7XG59XG5cbnZhciBtYXBfc2V0ID0ge1xuICBuZXc6IF9fbmV3X18kMSxcbiAgc2l6ZTogc2l6ZSQxLFxuICB0b19saXN0OiB0b19saXN0JDEsXG4gIGRpc2pvaW5fX3FtYXJrX18sXG4gIGRlbGV0ZTogX19kZWxldGVfXyQxLFxuICBzdWJzZXRfX3FtYXJrX18sXG4gIGVxdWFsX19xbWFya19fOiBlcXVhbF9fcW1hcmtfXyQxLFxuICBtZW1iZXJfX3FtYXJrX18sXG4gIHB1dDogcHV0JDEsXG4gIHVuaW9uLFxuICBpbnRlcnNlY3Rpb24sXG4gIGRpZmZlcmVuY2Vcbn07XG5cbmxldCBWaXJ0dWFsRE9NID0gKGZ1bmN0aW9uIChlKSB7XG4gICAgcmV0dXJuIGUoKTtcbn0pKGZ1bmN0aW9uICgpIHtcbiAgICB2YXIgZGVmaW5lLCBtb2R1bGUsIGV4cG9ydHM7XG4gICAgcmV0dXJuIChmdW5jdGlvbiBlKHQsIG4sIHIpIHtcbiAgICAgICAgZnVuY3Rpb24gcyhvLCB1KSB7XG4gICAgICAgICAgICBpZiAoIW5bb10pIHtcbiAgICAgICAgICAgICAgICBpZiAoIXRbb10pIHtcbiAgICAgICAgICAgICAgICAgICAgdmFyIGEgPSB0eXBlb2YgcmVxdWlyZSA9PSBcImZ1bmN0aW9uXCIgJiYgcmVxdWlyZTtcbiAgICAgICAgICAgICAgICAgICAgaWYgKCF1ICYmIGEpIHJldHVybiBhKG8sICEwKTtcbiAgICAgICAgICAgICAgICAgICAgaWYgKGkpIHJldHVybiBpKG8sICEwKTtcbiAgICAgICAgICAgICAgICAgICAgdmFyIGYgPSBuZXcgRXJyb3IoXCJDYW5ub3QgZmluZCBtb2R1bGUgJ1wiICsgbyArIFwiJ1wiKTtcbiAgICAgICAgICAgICAgICAgICAgdGhyb3cgKGYuY29kZSA9IFwiTU9EVUxFX05PVF9GT1VORFwiLCBmKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgdmFyIGwgPSBuW29dID0ge1xuICAgICAgICAgICAgICAgICAgICBleHBvcnRzOiB7fVxuICAgICAgICAgICAgICAgIH07XG4gICAgICAgICAgICAgICAgdFtvXVswXS5jYWxsKGwuZXhwb3J0cywgZnVuY3Rpb24gKGUpIHtcbiAgICAgICAgICAgICAgICAgICAgdmFyIG4gPSB0W29dWzFdW2VdO1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gcyhuID8gbiA6IGUpO1xuICAgICAgICAgICAgICAgIH0sIGwsIGwuZXhwb3J0cywgZSwgdCwgbiwgcik7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXR1cm4gbltvXS5leHBvcnRzO1xuICAgICAgICB9XG4gICAgICAgIHZhciBpID0gdHlwZW9mIHJlcXVpcmUgPT0gXCJmdW5jdGlvblwiICYmIHJlcXVpcmU7XG4gICAgICAgIGZvciAodmFyIG8gPSAwOyBvIDwgci5sZW5ndGg7IG8rKykgcyhyW29dKTtcbiAgICAgICAgcmV0dXJuIHM7XG4gICAgfSkoe1xuICAgICAgICAxOiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge1xuXG4gICAgICAgICAgICB2YXIgY3JlYXRlRWxlbWVudCA9IHJlcXVpcmUoXCIuL3Zkb20vY3JlYXRlLWVsZW1lbnQuanNcIik7XG5cbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gY3JlYXRlRWxlbWVudDtcbiAgICAgICAgfSwgeyBcIi4vdmRvbS9jcmVhdGUtZWxlbWVudC5qc1wiOiAxNSB9XSwgMjogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHtcbiAgICAgICAgICAgIHZhciBkaWZmID0gcmVxdWlyZShcIi4vdnRyZWUvZGlmZi5qc1wiKTtcblxuICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBkaWZmO1xuICAgICAgICB9LCB7IFwiLi92dHJlZS9kaWZmLmpzXCI6IDM1IH1dLCAzOiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge1xuICAgICAgICAgICAgdmFyIGggPSByZXF1aXJlKFwiLi92aXJ0dWFsLWh5cGVyc2NyaXB0L2luZGV4LmpzXCIpO1xuXG4gICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IGg7XG4gICAgICAgIH0sIHsgXCIuL3ZpcnR1YWwtaHlwZXJzY3JpcHQvaW5kZXguanNcIjogMjIgfV0sIDQ6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICB2YXIgZGlmZiA9IHJlcXVpcmUoXCIuL2RpZmYuanNcIik7XG4gICAgICAgICAgICB2YXIgcGF0Y2ggPSByZXF1aXJlKFwiLi9wYXRjaC5qc1wiKTtcbiAgICAgICAgICAgIHZhciBoID0gcmVxdWlyZShcIi4vaC5qc1wiKTtcbiAgICAgICAgICAgIHZhciBjcmVhdGUgPSByZXF1aXJlKFwiLi9jcmVhdGUtZWxlbWVudC5qc1wiKTtcbiAgICAgICAgICAgIHZhciBWTm9kZSA9IHJlcXVpcmUoXCIuL3Zub2RlL3Zub2RlLmpzXCIpO1xuICAgICAgICAgICAgdmFyIFZUZXh0ID0gcmVxdWlyZShcIi4vdm5vZGUvdnRleHQuanNcIik7XG5cbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0ge1xuICAgICAgICAgICAgICAgIGRpZmY6IGRpZmYsXG4gICAgICAgICAgICAgICAgcGF0Y2g6IHBhdGNoLFxuICAgICAgICAgICAgICAgIGg6IGgsXG4gICAgICAgICAgICAgICAgY3JlYXRlOiBjcmVhdGUsXG4gICAgICAgICAgICAgICAgVk5vZGU6IFZOb2RlLFxuICAgICAgICAgICAgICAgIFZUZXh0OiBWVGV4dFxuICAgICAgICAgICAgfTtcbiAgICAgICAgfSwgeyBcIi4vY3JlYXRlLWVsZW1lbnQuanNcIjogMSwgXCIuL2RpZmYuanNcIjogMiwgXCIuL2guanNcIjogMywgXCIuL3BhdGNoLmpzXCI6IDEzLCBcIi4vdm5vZGUvdm5vZGUuanNcIjogMzEsIFwiLi92bm9kZS92dGV4dC5qc1wiOiAzMyB9XSwgNTogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHtcbiAgICAgICAgICAgIC8qIVxuICAgICAgICAgICAgICogQ3Jvc3MtQnJvd3NlciBTcGxpdCAxLjEuMVxuICAgICAgICAgICAgICogQ29weXJpZ2h0IDIwMDctMjAxMiBTdGV2ZW4gTGV2aXRoYW4gPHN0ZXZlbmxldml0aGFuLmNvbT5cbiAgICAgICAgICAgICAqIEF2YWlsYWJsZSB1bmRlciB0aGUgTUlUIExpY2Vuc2VcbiAgICAgICAgICAgICAqIEVDTUFTY3JpcHQgY29tcGxpYW50LCB1bmlmb3JtIGNyb3NzLWJyb3dzZXIgc3BsaXQgbWV0aG9kXG4gICAgICAgICAgICAgKi9cblxuICAgICAgICAgICAgLyoqXG4gICAgICAgICAgICAgKiBTcGxpdHMgYSBzdHJpbmcgaW50byBhbiBhcnJheSBvZiBzdHJpbmdzIHVzaW5nIGEgcmVnZXggb3Igc3RyaW5nIHNlcGFyYXRvci4gTWF0Y2hlcyBvZiB0aGVcbiAgICAgICAgICAgICAqIHNlcGFyYXRvciBhcmUgbm90IGluY2x1ZGVkIGluIHRoZSByZXN1bHQgYXJyYXkuIEhvd2V2ZXIsIGlmIGBzZXBhcmF0b3JgIGlzIGEgcmVnZXggdGhhdCBjb250YWluc1xuICAgICAgICAgICAgICogY2FwdHVyaW5nIGdyb3VwcywgYmFja3JlZmVyZW5jZXMgYXJlIHNwbGljZWQgaW50byB0aGUgcmVzdWx0IGVhY2ggdGltZSBgc2VwYXJhdG9yYCBpcyBtYXRjaGVkLlxuICAgICAgICAgICAgICogRml4ZXMgYnJvd3NlciBidWdzIGNvbXBhcmVkIHRvIHRoZSBuYXRpdmUgYFN0cmluZy5wcm90b3R5cGUuc3BsaXRgIGFuZCBjYW4gYmUgdXNlZCByZWxpYWJseVxuICAgICAgICAgICAgICogY3Jvc3MtYnJvd3Nlci5cbiAgICAgICAgICAgICAqIEBwYXJhbSB7U3RyaW5nfSBzdHIgU3RyaW5nIHRvIHNwbGl0LlxuICAgICAgICAgICAgICogQHBhcmFtIHtSZWdFeHB8U3RyaW5nfSBzZXBhcmF0b3IgUmVnZXggb3Igc3RyaW5nIHRvIHVzZSBmb3Igc2VwYXJhdGluZyB0aGUgc3RyaW5nLlxuICAgICAgICAgICAgICogQHBhcmFtIHtOdW1iZXJ9IFtsaW1pdF0gTWF4aW11bSBudW1iZXIgb2YgaXRlbXMgdG8gaW5jbHVkZSBpbiB0aGUgcmVzdWx0IGFycmF5LlxuICAgICAgICAgICAgICogQHJldHVybnMge0FycmF5fSBBcnJheSBvZiBzdWJzdHJpbmdzLlxuICAgICAgICAgICAgICogQGV4YW1wbGVcbiAgICAgICAgICAgICAqXG4gICAgICAgICAgICAgKiAvLyBCYXNpYyB1c2VcbiAgICAgICAgICAgICAqIHNwbGl0KCdhIGIgYyBkJywgJyAnKTtcbiAgICAgICAgICAgICAqIC8vIC0+IFsnYScsICdiJywgJ2MnLCAnZCddXG4gICAgICAgICAgICAgKlxuICAgICAgICAgICAgICogLy8gV2l0aCBsaW1pdFxuICAgICAgICAgICAgICogc3BsaXQoJ2EgYiBjIGQnLCAnICcsIDIpO1xuICAgICAgICAgICAgICogLy8gLT4gWydhJywgJ2InXVxuICAgICAgICAgICAgICpcbiAgICAgICAgICAgICAqIC8vIEJhY2tyZWZlcmVuY2VzIGluIHJlc3VsdCBhcnJheVxuICAgICAgICAgICAgICogc3BsaXQoJy4ud29yZDEgd29yZDIuLicsIC8oW2Etel0rKShcXGQrKS9pKTtcbiAgICAgICAgICAgICAqIC8vIC0+IFsnLi4nLCAnd29yZCcsICcxJywgJyAnLCAnd29yZCcsICcyJywgJy4uJ11cbiAgICAgICAgICAgICAqL1xuICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSAoZnVuY3Rpb24gc3BsaXQodW5kZWYpIHtcblxuICAgICAgICAgICAgICAgIHZhciBuYXRpdmVTcGxpdCA9IFN0cmluZy5wcm90b3R5cGUuc3BsaXQsXG4gICAgICAgICAgICAgICAgICAgIGNvbXBsaWFudEV4ZWNOcGNnID0gLygpPz8vLmV4ZWMoXCJcIilbMV0gPT09IHVuZGVmLFxuXG4gICAgICAgICAgICAgICAgLy8gTlBDRzogbm9ucGFydGljaXBhdGluZyBjYXB0dXJpbmcgZ3JvdXBcbiAgICAgICAgICAgICAgICBzZWxmO1xuXG4gICAgICAgICAgICAgICAgc2VsZiA9IGZ1bmN0aW9uIChzdHIsIHNlcGFyYXRvciwgbGltaXQpIHtcbiAgICAgICAgICAgICAgICAgICAgLy8gSWYgYHNlcGFyYXRvcmAgaXMgbm90IGEgcmVnZXgsIHVzZSBgbmF0aXZlU3BsaXRgXG4gICAgICAgICAgICAgICAgICAgIGlmIChPYmplY3QucHJvdG90eXBlLnRvU3RyaW5nLmNhbGwoc2VwYXJhdG9yKSAhPT0gXCJbb2JqZWN0IFJlZ0V4cF1cIikge1xuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIG5hdGl2ZVNwbGl0LmNhbGwoc3RyLCBzZXBhcmF0b3IsIGxpbWl0KTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB2YXIgb3V0cHV0ID0gW10sXG4gICAgICAgICAgICAgICAgICAgICAgICBmbGFncyA9IChzZXBhcmF0b3IuaWdub3JlQ2FzZSA/IFwiaVwiIDogXCJcIikgKyAoc2VwYXJhdG9yLm11bHRpbGluZSA/IFwibVwiIDogXCJcIikgKyAoc2VwYXJhdG9yLmV4dGVuZGVkID8gXCJ4XCIgOiBcIlwiKSArIChzZXBhcmF0b3Iuc3RpY2t5ID8gXCJ5XCIgOiBcIlwiKSxcblxuICAgICAgICAgICAgICAgICAgICAvLyBGaXJlZm94IDMrXG4gICAgICAgICAgICAgICAgICAgIGxhc3RMYXN0SW5kZXggPSAwLFxuXG4gICAgICAgICAgICAgICAgICAgIC8vIE1ha2UgYGdsb2JhbGAgYW5kIGF2b2lkIGBsYXN0SW5kZXhgIGlzc3VlcyBieSB3b3JraW5nIHdpdGggYSBjb3B5XG4gICAgICAgICAgICAgICAgICAgIHNlcGFyYXRvciA9IG5ldyBSZWdFeHAoc2VwYXJhdG9yLnNvdXJjZSwgZmxhZ3MgKyBcImdcIiksXG4gICAgICAgICAgICAgICAgICAgICAgICBzZXBhcmF0b3IyLFxuICAgICAgICAgICAgICAgICAgICAgICAgbWF0Y2gsXG4gICAgICAgICAgICAgICAgICAgICAgICBsYXN0SW5kZXgsXG4gICAgICAgICAgICAgICAgICAgICAgICBsYXN0TGVuZ3RoO1xuICAgICAgICAgICAgICAgICAgICBzdHIgKz0gXCJcIjsgLy8gVHlwZS1jb252ZXJ0XG4gICAgICAgICAgICAgICAgICAgIGlmICghY29tcGxpYW50RXhlY05wY2cpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIERvZXNuJ3QgbmVlZCBmbGFncyBneSwgYnV0IHRoZXkgZG9uJ3QgaHVydFxuICAgICAgICAgICAgICAgICAgICAgICAgc2VwYXJhdG9yMiA9IG5ldyBSZWdFeHAoXCJeXCIgKyBzZXBhcmF0b3Iuc291cmNlICsgXCIkKD8hXFxcXHMpXCIsIGZsYWdzKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAvKiBWYWx1ZXMgZm9yIGBsaW1pdGAsIHBlciB0aGUgc3BlYzpcbiAgICAgICAgICAgICAgICAgICAgICogSWYgdW5kZWZpbmVkOiA0Mjk0OTY3Mjk1IC8vIE1hdGgucG93KDIsIDMyKSAtIDFcbiAgICAgICAgICAgICAgICAgICAgICogSWYgMCwgSW5maW5pdHksIG9yIE5hTjogMFxuICAgICAgICAgICAgICAgICAgICAgKiBJZiBwb3NpdGl2ZSBudW1iZXI6IGxpbWl0ID0gTWF0aC5mbG9vcihsaW1pdCk7IGlmIChsaW1pdCA+IDQyOTQ5NjcyOTUpIGxpbWl0IC09IDQyOTQ5NjcyOTY7XG4gICAgICAgICAgICAgICAgICAgICAqIElmIG5lZ2F0aXZlIG51bWJlcjogNDI5NDk2NzI5NiAtIE1hdGguZmxvb3IoTWF0aC5hYnMobGltaXQpKVxuICAgICAgICAgICAgICAgICAgICAgKiBJZiBvdGhlcjogVHlwZS1jb252ZXJ0LCB0aGVuIHVzZSB0aGUgYWJvdmUgcnVsZXNcbiAgICAgICAgICAgICAgICAgICAgICovXG4gICAgICAgICAgICAgICAgICAgIGxpbWl0ID0gbGltaXQgPT09IHVuZGVmID8gLTEgPj4+IDAgOiAvLyBNYXRoLnBvdygyLCAzMikgLSAxXG4gICAgICAgICAgICAgICAgICAgIGxpbWl0ID4+PiAwOyAvLyBUb1VpbnQzMihsaW1pdClcbiAgICAgICAgICAgICAgICAgICAgd2hpbGUgKG1hdGNoID0gc2VwYXJhdG9yLmV4ZWMoc3RyKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgLy8gYHNlcGFyYXRvci5sYXN0SW5kZXhgIGlzIG5vdCByZWxpYWJsZSBjcm9zcy1icm93c2VyXG4gICAgICAgICAgICAgICAgICAgICAgICBsYXN0SW5kZXggPSBtYXRjaC5pbmRleCArIG1hdGNoWzBdLmxlbmd0aDtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChsYXN0SW5kZXggPiBsYXN0TGFzdEluZGV4KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgb3V0cHV0LnB1c2goc3RyLnNsaWNlKGxhc3RMYXN0SW5kZXgsIG1hdGNoLmluZGV4KSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gRml4IGJyb3dzZXJzIHdob3NlIGBleGVjYCBtZXRob2RzIGRvbid0IGNvbnNpc3RlbnRseSByZXR1cm4gYHVuZGVmaW5lZGAgZm9yXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gbm9ucGFydGljaXBhdGluZyBjYXB0dXJpbmcgZ3JvdXBzXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKCFjb21wbGlhbnRFeGVjTnBjZyAmJiBtYXRjaC5sZW5ndGggPiAxKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1hdGNoWzBdLnJlcGxhY2Uoc2VwYXJhdG9yMiwgZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZm9yICh2YXIgaSA9IDE7IGkgPCBhcmd1bWVudHMubGVuZ3RoIC0gMjsgaSsrKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGFyZ3VtZW50c1tpXSA9PT0gdW5kZWYpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbWF0Y2hbaV0gPSB1bmRlZjtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAobWF0Y2gubGVuZ3RoID4gMSAmJiBtYXRjaC5pbmRleCA8IHN0ci5sZW5ndGgpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgQXJyYXkucHJvdG90eXBlLnB1c2guYXBwbHkob3V0cHV0LCBtYXRjaC5zbGljZSgxKSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxhc3RMZW5ndGggPSBtYXRjaFswXS5sZW5ndGg7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgbGFzdExhc3RJbmRleCA9IGxhc3RJbmRleDtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAob3V0cHV0Lmxlbmd0aCA+PSBsaW1pdCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoc2VwYXJhdG9yLmxhc3RJbmRleCA9PT0gbWF0Y2guaW5kZXgpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBzZXBhcmF0b3IubGFzdEluZGV4Kys7IC8vIEF2b2lkIGFuIGluZmluaXRlIGxvb3BcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICBpZiAobGFzdExhc3RJbmRleCA9PT0gc3RyLmxlbmd0aCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGxhc3RMZW5ndGggfHwgIXNlcGFyYXRvci50ZXN0KFwiXCIpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgb3V0cHV0LnB1c2goXCJcIik7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBvdXRwdXQucHVzaChzdHIuc2xpY2UobGFzdExhc3RJbmRleCkpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBvdXRwdXQubGVuZ3RoID4gbGltaXQgPyBvdXRwdXQuc2xpY2UoMCwgbGltaXQpIDogb3V0cHV0O1xuICAgICAgICAgICAgICAgIH07XG5cbiAgICAgICAgICAgICAgICByZXR1cm4gc2VsZjtcbiAgICAgICAgICAgIH0pKCk7XG4gICAgICAgIH0sIHt9XSwgNjogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHt9LCB7fV0sIDc6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICBcInVzZSBzdHJpY3RcIjtcblxuICAgICAgICAgICAgdmFyIE9uZVZlcnNpb25Db25zdHJhaW50ID0gcmVxdWlyZShcImluZGl2aWR1YWwvb25lLXZlcnNpb25cIik7XG5cbiAgICAgICAgICAgIHZhciBNWV9WRVJTSU9OID0gXCI3XCI7XG4gICAgICAgICAgICBPbmVWZXJzaW9uQ29uc3RyYWludChcImV2LXN0b3JlXCIsIE1ZX1ZFUlNJT04pO1xuXG4gICAgICAgICAgICB2YXIgaGFzaEtleSA9IFwiX19FVl9TVE9SRV9LRVlAXCIgKyBNWV9WRVJTSU9OO1xuXG4gICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IEV2U3RvcmU7XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIEV2U3RvcmUoZWxlbSkge1xuICAgICAgICAgICAgICAgIHZhciBoYXNoID0gZWxlbVtoYXNoS2V5XTtcblxuICAgICAgICAgICAgICAgIGlmICghaGFzaCkge1xuICAgICAgICAgICAgICAgICAgICBoYXNoID0gZWxlbVtoYXNoS2V5XSA9IHt9O1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHJldHVybiBoYXNoO1xuICAgICAgICAgICAgfVxuICAgICAgICB9LCB7IFwiaW5kaXZpZHVhbC9vbmUtdmVyc2lvblwiOiA5IH1dLCA4OiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge1xuICAgICAgICAgICAgKGZ1bmN0aW9uIChnbG9iYWwpIHtcbiAgICAgICAgICAgICAgICBcInVzZSBzdHJpY3RcIjtcblxuICAgICAgICAgICAgICAgIC8qZ2xvYmFsIHdpbmRvdywgZ2xvYmFsKi9cblxuICAgICAgICAgICAgICAgIHZhciByb290ID0gdHlwZW9mIHdpbmRvdyAhPT0gXCJ1bmRlZmluZWRcIiA/IHdpbmRvdyA6IHR5cGVvZiBnbG9iYWwgIT09IFwidW5kZWZpbmVkXCIgPyBnbG9iYWwgOiB7fTtcblxuICAgICAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gSW5kaXZpZHVhbDtcblxuICAgICAgICAgICAgICAgIGZ1bmN0aW9uIEluZGl2aWR1YWwoa2V5LCB2YWx1ZSkge1xuICAgICAgICAgICAgICAgICAgICBpZiAoa2V5IGluIHJvb3QpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiByb290W2tleV07XG4gICAgICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgICAgICByb290W2tleV0gPSB2YWx1ZTtcblxuICAgICAgICAgICAgICAgICAgICByZXR1cm4gdmFsdWU7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSkuY2FsbCh0aGlzLCB0eXBlb2YgZ2xvYmFsICE9PSBcInVuZGVmaW5lZFwiID8gZ2xvYmFsIDogdHlwZW9mIHNlbGYgIT09IFwidW5kZWZpbmVkXCIgPyBzZWxmIDogdHlwZW9mIHdpbmRvdyAhPT0gXCJ1bmRlZmluZWRcIiA/IHdpbmRvdyA6IHt9KTtcbiAgICAgICAgfSwge31dLCA5OiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge1xuICAgICAgICAgICAgXCJ1c2Ugc3RyaWN0XCI7XG5cbiAgICAgICAgICAgIHZhciBJbmRpdmlkdWFsID0gcmVxdWlyZShcIi4vaW5kZXguanNcIik7XG5cbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gT25lVmVyc2lvbjtcblxuICAgICAgICAgICAgZnVuY3Rpb24gT25lVmVyc2lvbihtb2R1bGVOYW1lLCB2ZXJzaW9uLCBkZWZhdWx0VmFsdWUpIHtcbiAgICAgICAgICAgICAgICB2YXIga2V5ID0gXCJfX0lORElWSURVQUxfT05FX1ZFUlNJT05fXCIgKyBtb2R1bGVOYW1lO1xuICAgICAgICAgICAgICAgIHZhciBlbmZvcmNlS2V5ID0ga2V5ICsgXCJfRU5GT1JDRV9TSU5HTEVUT05cIjtcblxuICAgICAgICAgICAgICAgIHZhciB2ZXJzaW9uVmFsdWUgPSBJbmRpdmlkdWFsKGVuZm9yY2VLZXksIHZlcnNpb24pO1xuXG4gICAgICAgICAgICAgICAgaWYgKHZlcnNpb25WYWx1ZSAhPT0gdmVyc2lvbikge1xuICAgICAgICAgICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoXCJDYW4gb25seSBoYXZlIG9uZSBjb3B5IG9mIFwiICsgbW9kdWxlTmFtZSArIFwiLlxcblwiICsgXCJZb3UgYWxyZWFkeSBoYXZlIHZlcnNpb24gXCIgKyB2ZXJzaW9uVmFsdWUgKyBcIiBpbnN0YWxsZWQuXFxuXCIgKyBcIlRoaXMgbWVhbnMgeW91IGNhbm5vdCBpbnN0YWxsIHZlcnNpb24gXCIgKyB2ZXJzaW9uKTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICByZXR1cm4gSW5kaXZpZHVhbChrZXksIGRlZmF1bHRWYWx1ZSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0sIHsgXCIuL2luZGV4LmpzXCI6IDggfV0sIDEwOiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge1xuICAgICAgICAgICAgKGZ1bmN0aW9uIChnbG9iYWwpIHtcbiAgICAgICAgICAgICAgICB2YXIgdG9wTGV2ZWwgPSB0eXBlb2YgZ2xvYmFsICE9PSBcInVuZGVmaW5lZFwiID8gZ2xvYmFsIDogdHlwZW9mIHdpbmRvdyAhPT0gXCJ1bmRlZmluZWRcIiA/IHdpbmRvdyA6IHt9O1xuICAgICAgICAgICAgICAgIHZhciBtaW5Eb2MgPSByZXF1aXJlKFwibWluLWRvY3VtZW50XCIpO1xuXG4gICAgICAgICAgICAgICAgaWYgKHR5cGVvZiBkb2N1bWVudCAhPT0gXCJ1bmRlZmluZWRcIikge1xuICAgICAgICAgICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IGRvY3VtZW50O1xuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciBkb2NjeSA9IHRvcExldmVsW1wiX19HTE9CQUxfRE9DVU1FTlRfQ0FDSEVANFwiXTtcblxuICAgICAgICAgICAgICAgICAgICBpZiAoIWRvY2N5KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBkb2NjeSA9IHRvcExldmVsW1wiX19HTE9CQUxfRE9DVU1FTlRfQ0FDSEVANFwiXSA9IG1pbkRvYztcbiAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gZG9jY3k7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSkuY2FsbCh0aGlzLCB0eXBlb2YgZ2xvYmFsICE9PSBcInVuZGVmaW5lZFwiID8gZ2xvYmFsIDogdHlwZW9mIHNlbGYgIT09IFwidW5kZWZpbmVkXCIgPyBzZWxmIDogdHlwZW9mIHdpbmRvdyAhPT0gXCJ1bmRlZmluZWRcIiA/IHdpbmRvdyA6IHt9KTtcbiAgICAgICAgfSwgeyBcIm1pbi1kb2N1bWVudFwiOiA2IH1dLCAxMTogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHtcbiAgICAgICAgICAgIFwidXNlIHN0cmljdFwiO1xuXG4gICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uIGlzT2JqZWN0KHgpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gdHlwZW9mIHggPT09IFwib2JqZWN0XCIgJiYgeCAhPT0gbnVsbDtcbiAgICAgICAgICAgIH07XG4gICAgICAgIH0sIHt9XSwgMTI6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICB2YXIgbmF0aXZlSXNBcnJheSA9IEFycmF5LmlzQXJyYXk7XG4gICAgICAgICAgICB2YXIgdG9TdHJpbmcgPSBPYmplY3QucHJvdG90eXBlLnRvU3RyaW5nO1xuXG4gICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IG5hdGl2ZUlzQXJyYXkgfHwgaXNBcnJheTtcblxuICAgICAgICAgICAgZnVuY3Rpb24gaXNBcnJheShvYmopIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gdG9TdHJpbmcuY2FsbChvYmopID09PSBcIltvYmplY3QgQXJyYXldXCI7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0sIHt9XSwgMTM6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICB2YXIgcGF0Y2ggPSByZXF1aXJlKFwiLi92ZG9tL3BhdGNoLmpzXCIpO1xuXG4gICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IHBhdGNoO1xuICAgICAgICB9LCB7IFwiLi92ZG9tL3BhdGNoLmpzXCI6IDE4IH1dLCAxNDogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHtcbiAgICAgICAgICAgIHZhciBpc09iamVjdCA9IHJlcXVpcmUoXCJpcy1vYmplY3RcIik7XG4gICAgICAgICAgICB2YXIgaXNIb29rID0gcmVxdWlyZShcIi4uL3Zub2RlL2lzLXZob29rLmpzXCIpO1xuXG4gICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IGFwcGx5UHJvcGVydGllcztcblxuICAgICAgICAgICAgZnVuY3Rpb24gYXBwbHlQcm9wZXJ0aWVzKG5vZGUsIHByb3BzLCBwcmV2aW91cykge1xuICAgICAgICAgICAgICAgIGZvciAodmFyIHByb3BOYW1lIGluIHByb3BzKSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciBwcm9wVmFsdWUgPSBwcm9wc1twcm9wTmFtZV07XG5cbiAgICAgICAgICAgICAgICAgICAgaWYgKHByb3BWYWx1ZSA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICByZW1vdmVQcm9wZXJ0eShub2RlLCBwcm9wTmFtZSwgcHJvcFZhbHVlLCBwcmV2aW91cyk7XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoaXNIb29rKHByb3BWYWx1ZSkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJlbW92ZVByb3BlcnR5KG5vZGUsIHByb3BOYW1lLCBwcm9wVmFsdWUsIHByZXZpb3VzKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChwcm9wVmFsdWUuaG9vaykge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHByb3BWYWx1ZS5ob29rKG5vZGUsIHByb3BOYW1lLCBwcmV2aW91cyA/IHByZXZpb3VzW3Byb3BOYW1lXSA6IHVuZGVmaW5lZCk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoaXNPYmplY3QocHJvcFZhbHVlKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHBhdGNoT2JqZWN0KG5vZGUsIHByb3BzLCBwcmV2aW91cywgcHJvcE5hbWUsIHByb3BWYWx1ZSk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIG5vZGVbcHJvcE5hbWVdID0gcHJvcFZhbHVlO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBmdW5jdGlvbiByZW1vdmVQcm9wZXJ0eShub2RlLCBwcm9wTmFtZSwgcHJvcFZhbHVlLCBwcmV2aW91cykge1xuICAgICAgICAgICAgICAgIGlmIChwcmV2aW91cykge1xuICAgICAgICAgICAgICAgICAgICB2YXIgcHJldmlvdXNWYWx1ZSA9IHByZXZpb3VzW3Byb3BOYW1lXTtcblxuICAgICAgICAgICAgICAgICAgICBpZiAoIWlzSG9vayhwcmV2aW91c1ZhbHVlKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHByb3BOYW1lID09PSBcImF0dHJpYnV0ZXNcIikge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZvciAodmFyIGF0dHJOYW1lIGluIHByZXZpb3VzVmFsdWUpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbm9kZS5yZW1vdmVBdHRyaWJ1dGUoYXR0ck5hbWUpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAocHJvcE5hbWUgPT09IFwic3R5bGVcIikge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZvciAodmFyIGkgaW4gcHJldmlvdXNWYWx1ZSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBub2RlLnN0eWxlW2ldID0gXCJcIjtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKHR5cGVvZiBwcmV2aW91c1ZhbHVlID09PSBcInN0cmluZ1wiKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgbm9kZVtwcm9wTmFtZV0gPSBcIlwiO1xuICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBub2RlW3Byb3BOYW1lXSA9IG51bGw7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAocHJldmlvdXNWYWx1ZS51bmhvb2spIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHByZXZpb3VzVmFsdWUudW5ob29rKG5vZGUsIHByb3BOYW1lLCBwcm9wVmFsdWUpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBmdW5jdGlvbiBwYXRjaE9iamVjdChub2RlLCBwcm9wcywgcHJldmlvdXMsIHByb3BOYW1lLCBwcm9wVmFsdWUpIHtcbiAgICAgICAgICAgICAgICB2YXIgcHJldmlvdXNWYWx1ZSA9IHByZXZpb3VzID8gcHJldmlvdXNbcHJvcE5hbWVdIDogdW5kZWZpbmVkO1xuXG4gICAgICAgICAgICAgICAgLy8gU2V0IGF0dHJpYnV0ZXNcbiAgICAgICAgICAgICAgICBpZiAocHJvcE5hbWUgPT09IFwiYXR0cmlidXRlc1wiKSB7XG4gICAgICAgICAgICAgICAgICAgIGZvciAodmFyIGF0dHJOYW1lIGluIHByb3BWYWx1ZSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgdmFyIGF0dHJWYWx1ZSA9IHByb3BWYWx1ZVthdHRyTmFtZV07XG5cbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChhdHRyVmFsdWUgPT09IHVuZGVmaW5lZCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIG5vZGUucmVtb3ZlQXR0cmlidXRlKGF0dHJOYW1lKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgbm9kZS5zZXRBdHRyaWJ1dGUoYXR0ck5hbWUsIGF0dHJWYWx1ZSk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgaWYgKHByZXZpb3VzVmFsdWUgJiYgaXNPYmplY3QocHJldmlvdXNWYWx1ZSkgJiYgZ2V0UHJvdG90eXBlKHByZXZpb3VzVmFsdWUpICE9PSBnZXRQcm90b3R5cGUocHJvcFZhbHVlKSkge1xuICAgICAgICAgICAgICAgICAgICBub2RlW3Byb3BOYW1lXSA9IHByb3BWYWx1ZTtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIGlmICghaXNPYmplY3Qobm9kZVtwcm9wTmFtZV0pKSB7XG4gICAgICAgICAgICAgICAgICAgIG5vZGVbcHJvcE5hbWVdID0ge307XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgdmFyIHJlcGxhY2VyID0gcHJvcE5hbWUgPT09IFwic3R5bGVcIiA/IFwiXCIgOiB1bmRlZmluZWQ7XG5cbiAgICAgICAgICAgICAgICBmb3IgKHZhciBrIGluIHByb3BWYWx1ZSkge1xuICAgICAgICAgICAgICAgICAgICB2YXIgdmFsdWUgPSBwcm9wVmFsdWVba107XG4gICAgICAgICAgICAgICAgICAgIG5vZGVbcHJvcE5hbWVdW2tdID0gdmFsdWUgPT09IHVuZGVmaW5lZCA/IHJlcGxhY2VyIDogdmFsdWU7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBmdW5jdGlvbiBnZXRQcm90b3R5cGUodmFsdWUpIHtcbiAgICAgICAgICAgICAgICBpZiAoT2JqZWN0LmdldFByb3RvdHlwZU9mKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBPYmplY3QuZ2V0UHJvdG90eXBlT2YodmFsdWUpO1xuICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAodmFsdWUuX19wcm90b19fKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiB2YWx1ZS5fX3Byb3RvX187XG4gICAgICAgICAgICAgICAgfSBlbHNlIGlmICh2YWx1ZS5jb25zdHJ1Y3Rvcikge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gdmFsdWUuY29uc3RydWN0b3IucHJvdG90eXBlO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgfSwgeyBcIi4uL3Zub2RlL2lzLXZob29rLmpzXCI6IDI2LCBcImlzLW9iamVjdFwiOiAxMSB9XSwgMTU6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICB2YXIgZG9jdW1lbnQgPSByZXF1aXJlKFwiZ2xvYmFsL2RvY3VtZW50XCIpO1xuXG4gICAgICAgICAgICB2YXIgYXBwbHlQcm9wZXJ0aWVzID0gcmVxdWlyZShcIi4vYXBwbHktcHJvcGVydGllc1wiKTtcblxuICAgICAgICAgICAgdmFyIGlzVk5vZGUgPSByZXF1aXJlKFwiLi4vdm5vZGUvaXMtdm5vZGUuanNcIik7XG4gICAgICAgICAgICB2YXIgaXNWVGV4dCA9IHJlcXVpcmUoXCIuLi92bm9kZS9pcy12dGV4dC5qc1wiKTtcbiAgICAgICAgICAgIHZhciBpc1dpZGdldCA9IHJlcXVpcmUoXCIuLi92bm9kZS9pcy13aWRnZXQuanNcIik7XG4gICAgICAgICAgICB2YXIgaGFuZGxlVGh1bmsgPSByZXF1aXJlKFwiLi4vdm5vZGUvaGFuZGxlLXRodW5rLmpzXCIpO1xuXG4gICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IGNyZWF0ZUVsZW1lbnQ7XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIGNyZWF0ZUVsZW1lbnQodm5vZGUsIG9wdHMpIHtcbiAgICAgICAgICAgICAgICB2YXIgZG9jID0gb3B0cyA/IG9wdHMuZG9jdW1lbnQgfHwgZG9jdW1lbnQgOiBkb2N1bWVudDtcbiAgICAgICAgICAgICAgICB2YXIgd2FybiA9IG9wdHMgPyBvcHRzLndhcm4gOiBudWxsO1xuXG4gICAgICAgICAgICAgICAgdm5vZGUgPSBoYW5kbGVUaHVuayh2bm9kZSkuYTtcblxuICAgICAgICAgICAgICAgIGlmIChpc1dpZGdldCh2bm9kZSkpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHZub2RlLmluaXQoKTtcbiAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKGlzVlRleHQodm5vZGUpKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBkb2MuY3JlYXRlVGV4dE5vZGUodm5vZGUudGV4dCk7XG4gICAgICAgICAgICAgICAgfSBlbHNlIGlmICghaXNWTm9kZSh2bm9kZSkpIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKHdhcm4pIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHdhcm4oXCJJdGVtIGlzIG5vdCBhIHZhbGlkIHZpcnR1YWwgZG9tIG5vZGVcIiwgdm5vZGUpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBudWxsO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHZhciBub2RlID0gdm5vZGUubmFtZXNwYWNlID09PSBudWxsID8gZG9jLmNyZWF0ZUVsZW1lbnQodm5vZGUudGFnTmFtZSkgOiBkb2MuY3JlYXRlRWxlbWVudE5TKHZub2RlLm5hbWVzcGFjZSwgdm5vZGUudGFnTmFtZSk7XG5cbiAgICAgICAgICAgICAgICB2YXIgcHJvcHMgPSB2bm9kZS5wcm9wZXJ0aWVzO1xuICAgICAgICAgICAgICAgIGFwcGx5UHJvcGVydGllcyhub2RlLCBwcm9wcyk7XG5cbiAgICAgICAgICAgICAgICB2YXIgY2hpbGRyZW4gPSB2bm9kZS5jaGlsZHJlbjtcblxuICAgICAgICAgICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgY2hpbGRyZW4ubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgICAgICAgICAgdmFyIGNoaWxkTm9kZSA9IGNyZWF0ZUVsZW1lbnQoY2hpbGRyZW5baV0sIG9wdHMpO1xuICAgICAgICAgICAgICAgICAgICBpZiAoY2hpbGROb2RlKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBub2RlLmFwcGVuZENoaWxkKGNoaWxkTm9kZSk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICByZXR1cm4gbm9kZTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSwgeyBcIi4uL3Zub2RlL2hhbmRsZS10aHVuay5qc1wiOiAyNCwgXCIuLi92bm9kZS9pcy12bm9kZS5qc1wiOiAyNywgXCIuLi92bm9kZS9pcy12dGV4dC5qc1wiOiAyOCwgXCIuLi92bm9kZS9pcy13aWRnZXQuanNcIjogMjksIFwiLi9hcHBseS1wcm9wZXJ0aWVzXCI6IDE0LCBcImdsb2JhbC9kb2N1bWVudFwiOiAxMCB9XSwgMTY6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICAvLyBNYXBzIGEgdmlydHVhbCBET00gdHJlZSBvbnRvIGEgcmVhbCBET00gdHJlZSBpbiBhbiBlZmZpY2llbnQgbWFubmVyLlxuICAgICAgICAgICAgLy8gV2UgZG9uJ3Qgd2FudCB0byByZWFkIGFsbCBvZiB0aGUgRE9NIG5vZGVzIGluIHRoZSB0cmVlIHNvIHdlIHVzZVxuICAgICAgICAgICAgLy8gdGhlIGluLW9yZGVyIHRyZWUgaW5kZXhpbmcgdG8gZWxpbWluYXRlIHJlY3Vyc2lvbiBkb3duIGNlcnRhaW4gYnJhbmNoZXMuXG4gICAgICAgICAgICAvLyBXZSBvbmx5IHJlY3Vyc2UgaW50byBhIERPTSBub2RlIGlmIHdlIGtub3cgdGhhdCBpdCBjb250YWlucyBhIGNoaWxkIG9mXG4gICAgICAgICAgICAvLyBpbnRlcmVzdC5cblxuICAgICAgICAgICAgdmFyIG5vQ2hpbGQgPSB7fTtcblxuICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBkb21JbmRleDtcblxuICAgICAgICAgICAgZnVuY3Rpb24gZG9tSW5kZXgocm9vdE5vZGUsIHRyZWUsIGluZGljZXMsIG5vZGVzKSB7XG4gICAgICAgICAgICAgICAgaWYgKCFpbmRpY2VzIHx8IGluZGljZXMubGVuZ3RoID09PSAwKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiB7fTtcbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICBpbmRpY2VzLnNvcnQoYXNjZW5kaW5nKTtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHJlY3Vyc2Uocm9vdE5vZGUsIHRyZWUsIGluZGljZXMsIG5vZGVzLCAwKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIHJlY3Vyc2Uocm9vdE5vZGUsIHRyZWUsIGluZGljZXMsIG5vZGVzLCByb290SW5kZXgpIHtcbiAgICAgICAgICAgICAgICBub2RlcyA9IG5vZGVzIHx8IHt9O1xuXG4gICAgICAgICAgICAgICAgaWYgKHJvb3ROb2RlKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmIChpbmRleEluUmFuZ2UoaW5kaWNlcywgcm9vdEluZGV4LCByb290SW5kZXgpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBub2Rlc1tyb290SW5kZXhdID0gcm9vdE5vZGU7XG4gICAgICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgICAgICB2YXIgdkNoaWxkcmVuID0gdHJlZS5jaGlsZHJlbjtcblxuICAgICAgICAgICAgICAgICAgICBpZiAodkNoaWxkcmVuKSB7XG5cbiAgICAgICAgICAgICAgICAgICAgICAgIHZhciBjaGlsZE5vZGVzID0gcm9vdE5vZGUuY2hpbGROb2RlcztcblxuICAgICAgICAgICAgICAgICAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCB0cmVlLmNoaWxkcmVuLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcm9vdEluZGV4ICs9IDE7XG5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB2YXIgdkNoaWxkID0gdkNoaWxkcmVuW2ldIHx8IG5vQ2hpbGQ7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdmFyIG5leHRJbmRleCA9IHJvb3RJbmRleCArICh2Q2hpbGQuY291bnQgfHwgMCk7XG5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBza2lwIHJlY3Vyc2lvbiBkb3duIHRoZSB0cmVlIGlmIHRoZXJlIGFyZSBubyBub2RlcyBkb3duIGhlcmVcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoaW5kZXhJblJhbmdlKGluZGljZXMsIHJvb3RJbmRleCwgbmV4dEluZGV4KSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICByZWN1cnNlKGNoaWxkTm9kZXNbaV0sIHZDaGlsZCwgaW5kaWNlcywgbm9kZXMsIHJvb3RJbmRleCk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcm9vdEluZGV4ID0gbmV4dEluZGV4O1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgcmV0dXJuIG5vZGVzO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAvLyBCaW5hcnkgc2VhcmNoIGZvciBhbiBpbmRleCBpbiB0aGUgaW50ZXJ2YWwgW2xlZnQsIHJpZ2h0XVxuICAgICAgICAgICAgZnVuY3Rpb24gaW5kZXhJblJhbmdlKGluZGljZXMsIGxlZnQsIHJpZ2h0KSB7XG4gICAgICAgICAgICAgICAgaWYgKGluZGljZXMubGVuZ3RoID09PSAwKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICB2YXIgbWluSW5kZXggPSAwO1xuICAgICAgICAgICAgICAgIHZhciBtYXhJbmRleCA9IGluZGljZXMubGVuZ3RoIC0gMTtcbiAgICAgICAgICAgICAgICB2YXIgY3VycmVudEluZGV4O1xuICAgICAgICAgICAgICAgIHZhciBjdXJyZW50SXRlbTtcblxuICAgICAgICAgICAgICAgIHdoaWxlIChtaW5JbmRleCA8PSBtYXhJbmRleCkge1xuICAgICAgICAgICAgICAgICAgICBjdXJyZW50SW5kZXggPSAobWF4SW5kZXggKyBtaW5JbmRleCkgLyAyID4+IDA7XG4gICAgICAgICAgICAgICAgICAgIGN1cnJlbnRJdGVtID0gaW5kaWNlc1tjdXJyZW50SW5kZXhdO1xuXG4gICAgICAgICAgICAgICAgICAgIGlmIChtaW5JbmRleCA9PT0gbWF4SW5kZXgpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBjdXJyZW50SXRlbSA+PSBsZWZ0ICYmIGN1cnJlbnRJdGVtIDw9IHJpZ2h0O1xuICAgICAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKGN1cnJlbnRJdGVtIDwgbGVmdCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgbWluSW5kZXggPSBjdXJyZW50SW5kZXggKyAxO1xuICAgICAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKGN1cnJlbnRJdGVtID4gcmlnaHQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIG1heEluZGV4ID0gY3VycmVudEluZGV4IC0gMTtcbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBmdW5jdGlvbiBhc2NlbmRpbmcoYSwgYikge1xuICAgICAgICAgICAgICAgIHJldHVybiBhID4gYiA/IDEgOiAtMTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSwge31dLCAxNzogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHtcbiAgICAgICAgICAgIHZhciBhcHBseVByb3BlcnRpZXMgPSByZXF1aXJlKFwiLi9hcHBseS1wcm9wZXJ0aWVzXCIpO1xuXG4gICAgICAgICAgICB2YXIgaXNXaWRnZXQgPSByZXF1aXJlKFwiLi4vdm5vZGUvaXMtd2lkZ2V0LmpzXCIpO1xuICAgICAgICAgICAgdmFyIFZQYXRjaCA9IHJlcXVpcmUoXCIuLi92bm9kZS92cGF0Y2guanNcIik7XG5cbiAgICAgICAgICAgIHZhciB1cGRhdGVXaWRnZXQgPSByZXF1aXJlKFwiLi91cGRhdGUtd2lkZ2V0XCIpO1xuXG4gICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IGFwcGx5UGF0Y2g7XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIGFwcGx5UGF0Y2godnBhdGNoLCBkb21Ob2RlLCByZW5kZXJPcHRpb25zKSB7XG4gICAgICAgICAgICAgICAgdmFyIHR5cGUgPSB2cGF0Y2gudHlwZTtcbiAgICAgICAgICAgICAgICB2YXIgdk5vZGUgPSB2cGF0Y2gudk5vZGU7XG4gICAgICAgICAgICAgICAgdmFyIHBhdGNoID0gdnBhdGNoLnBhdGNoO1xuXG4gICAgICAgICAgICAgICAgc3dpdGNoICh0eXBlKSB7XG4gICAgICAgICAgICAgICAgICAgIGNhc2UgVlBhdGNoLlJFTU9WRTpcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiByZW1vdmVOb2RlKGRvbU5vZGUsIHZOb2RlKTtcbiAgICAgICAgICAgICAgICAgICAgY2FzZSBWUGF0Y2guSU5TRVJUOlxuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGluc2VydE5vZGUoZG9tTm9kZSwgcGF0Y2gsIHJlbmRlck9wdGlvbnMpO1xuICAgICAgICAgICAgICAgICAgICBjYXNlIFZQYXRjaC5WVEVYVDpcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBzdHJpbmdQYXRjaChkb21Ob2RlLCB2Tm9kZSwgcGF0Y2gsIHJlbmRlck9wdGlvbnMpO1xuICAgICAgICAgICAgICAgICAgICBjYXNlIFZQYXRjaC5XSURHRVQ6XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gd2lkZ2V0UGF0Y2goZG9tTm9kZSwgdk5vZGUsIHBhdGNoLCByZW5kZXJPcHRpb25zKTtcbiAgICAgICAgICAgICAgICAgICAgY2FzZSBWUGF0Y2guVk5PREU6XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gdk5vZGVQYXRjaChkb21Ob2RlLCB2Tm9kZSwgcGF0Y2gsIHJlbmRlck9wdGlvbnMpO1xuICAgICAgICAgICAgICAgICAgICBjYXNlIFZQYXRjaC5PUkRFUjpcbiAgICAgICAgICAgICAgICAgICAgICAgIHJlb3JkZXJDaGlsZHJlbihkb21Ob2RlLCBwYXRjaCk7XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gZG9tTm9kZTtcbiAgICAgICAgICAgICAgICAgICAgY2FzZSBWUGF0Y2guUFJPUFM6XG4gICAgICAgICAgICAgICAgICAgICAgICBhcHBseVByb3BlcnRpZXMoZG9tTm9kZSwgcGF0Y2gsIHZOb2RlLnByb3BlcnRpZXMpO1xuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGRvbU5vZGU7XG4gICAgICAgICAgICAgICAgICAgIGNhc2UgVlBhdGNoLlRIVU5LOlxuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHJlcGxhY2VSb290KGRvbU5vZGUsIHJlbmRlck9wdGlvbnMucGF0Y2goZG9tTm9kZSwgcGF0Y2gsIHJlbmRlck9wdGlvbnMpKTtcbiAgICAgICAgICAgICAgICAgICAgZGVmYXVsdDpcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBkb21Ob2RlO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZnVuY3Rpb24gcmVtb3ZlTm9kZShkb21Ob2RlLCB2Tm9kZSkge1xuICAgICAgICAgICAgICAgIHZhciBwYXJlbnROb2RlID0gZG9tTm9kZS5wYXJlbnROb2RlO1xuXG4gICAgICAgICAgICAgICAgaWYgKHBhcmVudE5vZGUpIHtcbiAgICAgICAgICAgICAgICAgICAgcGFyZW50Tm9kZS5yZW1vdmVDaGlsZChkb21Ob2RlKTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICBkZXN0cm95V2lkZ2V0KGRvbU5vZGUsIHZOb2RlKTtcblxuICAgICAgICAgICAgICAgIHJldHVybiBudWxsO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBmdW5jdGlvbiBpbnNlcnROb2RlKHBhcmVudE5vZGUsIHZOb2RlLCByZW5kZXJPcHRpb25zKSB7XG4gICAgICAgICAgICAgICAgdmFyIG5ld05vZGUgPSByZW5kZXJPcHRpb25zLnJlbmRlcih2Tm9kZSwgcmVuZGVyT3B0aW9ucyk7XG5cbiAgICAgICAgICAgICAgICBpZiAocGFyZW50Tm9kZSkge1xuICAgICAgICAgICAgICAgICAgICBwYXJlbnROb2RlLmFwcGVuZENoaWxkKG5ld05vZGUpO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHJldHVybiBwYXJlbnROb2RlO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBmdW5jdGlvbiBzdHJpbmdQYXRjaChkb21Ob2RlLCBsZWZ0Vk5vZGUsIHZUZXh0LCByZW5kZXJPcHRpb25zKSB7XG4gICAgICAgICAgICAgICAgdmFyIG5ld05vZGU7XG5cbiAgICAgICAgICAgICAgICBpZiAoZG9tTm9kZS5ub2RlVHlwZSA9PT0gMykge1xuICAgICAgICAgICAgICAgICAgICBkb21Ob2RlLnJlcGxhY2VEYXRhKDAsIGRvbU5vZGUubGVuZ3RoLCB2VGV4dC50ZXh0KTtcbiAgICAgICAgICAgICAgICAgICAgbmV3Tm9kZSA9IGRvbU5vZGU7XG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgdmFyIHBhcmVudE5vZGUgPSBkb21Ob2RlLnBhcmVudE5vZGU7XG4gICAgICAgICAgICAgICAgICAgIG5ld05vZGUgPSByZW5kZXJPcHRpb25zLnJlbmRlcih2VGV4dCwgcmVuZGVyT3B0aW9ucyk7XG5cbiAgICAgICAgICAgICAgICAgICAgaWYgKHBhcmVudE5vZGUgJiYgbmV3Tm9kZSAhPT0gZG9tTm9kZSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgcGFyZW50Tm9kZS5yZXBsYWNlQ2hpbGQobmV3Tm9kZSwgZG9tTm9kZSk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICByZXR1cm4gbmV3Tm9kZTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZnVuY3Rpb24gd2lkZ2V0UGF0Y2goZG9tTm9kZSwgbGVmdFZOb2RlLCB3aWRnZXQsIHJlbmRlck9wdGlvbnMpIHtcbiAgICAgICAgICAgICAgICB2YXIgdXBkYXRpbmcgPSB1cGRhdGVXaWRnZXQobGVmdFZOb2RlLCB3aWRnZXQpO1xuICAgICAgICAgICAgICAgIHZhciBuZXdOb2RlO1xuXG4gICAgICAgICAgICAgICAgaWYgKHVwZGF0aW5nKSB7XG4gICAgICAgICAgICAgICAgICAgIG5ld05vZGUgPSB3aWRnZXQudXBkYXRlKGxlZnRWTm9kZSwgZG9tTm9kZSkgfHwgZG9tTm9kZTtcbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICBuZXdOb2RlID0gcmVuZGVyT3B0aW9ucy5yZW5kZXIod2lkZ2V0LCByZW5kZXJPcHRpb25zKTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICB2YXIgcGFyZW50Tm9kZSA9IGRvbU5vZGUucGFyZW50Tm9kZTtcblxuICAgICAgICAgICAgICAgIGlmIChwYXJlbnROb2RlICYmIG5ld05vZGUgIT09IGRvbU5vZGUpIHtcbiAgICAgICAgICAgICAgICAgICAgcGFyZW50Tm9kZS5yZXBsYWNlQ2hpbGQobmV3Tm9kZSwgZG9tTm9kZSk7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgaWYgKCF1cGRhdGluZykge1xuICAgICAgICAgICAgICAgICAgICBkZXN0cm95V2lkZ2V0KGRvbU5vZGUsIGxlZnRWTm9kZSk7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgcmV0dXJuIG5ld05vZGU7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIHZOb2RlUGF0Y2goZG9tTm9kZSwgbGVmdFZOb2RlLCB2Tm9kZSwgcmVuZGVyT3B0aW9ucykge1xuICAgICAgICAgICAgICAgIHZhciBwYXJlbnROb2RlID0gZG9tTm9kZS5wYXJlbnROb2RlO1xuICAgICAgICAgICAgICAgIHZhciBuZXdOb2RlID0gcmVuZGVyT3B0aW9ucy5yZW5kZXIodk5vZGUsIHJlbmRlck9wdGlvbnMpO1xuXG4gICAgICAgICAgICAgICAgaWYgKHBhcmVudE5vZGUgJiYgbmV3Tm9kZSAhPT0gZG9tTm9kZSkge1xuICAgICAgICAgICAgICAgICAgICBwYXJlbnROb2RlLnJlcGxhY2VDaGlsZChuZXdOb2RlLCBkb21Ob2RlKTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICByZXR1cm4gbmV3Tm9kZTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZnVuY3Rpb24gZGVzdHJveVdpZGdldChkb21Ob2RlLCB3KSB7XG4gICAgICAgICAgICAgICAgaWYgKHR5cGVvZiB3LmRlc3Ryb3kgPT09IFwiZnVuY3Rpb25cIiAmJiBpc1dpZGdldCh3KSkge1xuICAgICAgICAgICAgICAgICAgICB3LmRlc3Ryb3koZG9tTm9kZSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBmdW5jdGlvbiByZW9yZGVyQ2hpbGRyZW4oZG9tTm9kZSwgbW92ZXMpIHtcbiAgICAgICAgICAgICAgICB2YXIgY2hpbGROb2RlcyA9IGRvbU5vZGUuY2hpbGROb2RlcztcbiAgICAgICAgICAgICAgICB2YXIga2V5TWFwID0ge307XG4gICAgICAgICAgICAgICAgdmFyIG5vZGU7XG4gICAgICAgICAgICAgICAgdmFyIHJlbW92ZTtcbiAgICAgICAgICAgICAgICB2YXIgaW5zZXJ0O1xuXG4gICAgICAgICAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCBtb3Zlcy5yZW1vdmVzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICAgICAgICAgIHJlbW92ZSA9IG1vdmVzLnJlbW92ZXNbaV07XG4gICAgICAgICAgICAgICAgICAgIG5vZGUgPSBjaGlsZE5vZGVzW3JlbW92ZS5mcm9tXTtcbiAgICAgICAgICAgICAgICAgICAgaWYgKHJlbW92ZS5rZXkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGtleU1hcFtyZW1vdmUua2V5XSA9IG5vZGU7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgZG9tTm9kZS5yZW1vdmVDaGlsZChub2RlKTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICB2YXIgbGVuZ3RoID0gY2hpbGROb2Rlcy5sZW5ndGg7XG4gICAgICAgICAgICAgICAgZm9yICh2YXIgaiA9IDA7IGogPCBtb3Zlcy5pbnNlcnRzLmxlbmd0aDsgaisrKSB7XG4gICAgICAgICAgICAgICAgICAgIGluc2VydCA9IG1vdmVzLmluc2VydHNbal07XG4gICAgICAgICAgICAgICAgICAgIG5vZGUgPSBrZXlNYXBbaW5zZXJ0LmtleV07XG4gICAgICAgICAgICAgICAgICAgIC8vIHRoaXMgaXMgdGhlIHdlaXJkZXN0IGJ1ZyBpJ3ZlIGV2ZXIgc2VlbiBpbiB3ZWJraXRcbiAgICAgICAgICAgICAgICAgICAgZG9tTm9kZS5pbnNlcnRCZWZvcmUobm9kZSwgaW5zZXJ0LnRvID49IGxlbmd0aCsrID8gbnVsbCA6IGNoaWxkTm9kZXNbaW5zZXJ0LnRvXSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBmdW5jdGlvbiByZXBsYWNlUm9vdChvbGRSb290LCBuZXdSb290KSB7XG4gICAgICAgICAgICAgICAgaWYgKG9sZFJvb3QgJiYgbmV3Um9vdCAmJiBvbGRSb290ICE9PSBuZXdSb290ICYmIG9sZFJvb3QucGFyZW50Tm9kZSkge1xuICAgICAgICAgICAgICAgICAgICBvbGRSb290LnBhcmVudE5vZGUucmVwbGFjZUNoaWxkKG5ld1Jvb3QsIG9sZFJvb3QpO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHJldHVybiBuZXdSb290O1xuICAgICAgICAgICAgfVxuICAgICAgICB9LCB7IFwiLi4vdm5vZGUvaXMtd2lkZ2V0LmpzXCI6IDI5LCBcIi4uL3Zub2RlL3ZwYXRjaC5qc1wiOiAzMiwgXCIuL2FwcGx5LXByb3BlcnRpZXNcIjogMTQsIFwiLi91cGRhdGUtd2lkZ2V0XCI6IDE5IH1dLCAxODogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHtcbiAgICAgICAgICAgIHZhciBkb2N1bWVudCA9IHJlcXVpcmUoXCJnbG9iYWwvZG9jdW1lbnRcIik7XG4gICAgICAgICAgICB2YXIgaXNBcnJheSA9IHJlcXVpcmUoXCJ4LWlzLWFycmF5XCIpO1xuXG4gICAgICAgICAgICB2YXIgcmVuZGVyID0gcmVxdWlyZShcIi4vY3JlYXRlLWVsZW1lbnRcIik7XG4gICAgICAgICAgICB2YXIgZG9tSW5kZXggPSByZXF1aXJlKFwiLi9kb20taW5kZXhcIik7XG4gICAgICAgICAgICB2YXIgcGF0Y2hPcCA9IHJlcXVpcmUoXCIuL3BhdGNoLW9wXCIpO1xuICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBwYXRjaDtcblxuICAgICAgICAgICAgZnVuY3Rpb24gcGF0Y2gocm9vdE5vZGUsIHBhdGNoZXMsIHJlbmRlck9wdGlvbnMpIHtcbiAgICAgICAgICAgICAgICByZW5kZXJPcHRpb25zID0gcmVuZGVyT3B0aW9ucyB8fCB7fTtcbiAgICAgICAgICAgICAgICByZW5kZXJPcHRpb25zLnBhdGNoID0gcmVuZGVyT3B0aW9ucy5wYXRjaCAmJiByZW5kZXJPcHRpb25zLnBhdGNoICE9PSBwYXRjaCA/IHJlbmRlck9wdGlvbnMucGF0Y2ggOiBwYXRjaFJlY3Vyc2l2ZTtcbiAgICAgICAgICAgICAgICByZW5kZXJPcHRpb25zLnJlbmRlciA9IHJlbmRlck9wdGlvbnMucmVuZGVyIHx8IHJlbmRlcjtcblxuICAgICAgICAgICAgICAgIHJldHVybiByZW5kZXJPcHRpb25zLnBhdGNoKHJvb3ROb2RlLCBwYXRjaGVzLCByZW5kZXJPcHRpb25zKTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZnVuY3Rpb24gcGF0Y2hSZWN1cnNpdmUocm9vdE5vZGUsIHBhdGNoZXMsIHJlbmRlck9wdGlvbnMpIHtcbiAgICAgICAgICAgICAgICB2YXIgaW5kaWNlcyA9IHBhdGNoSW5kaWNlcyhwYXRjaGVzKTtcblxuICAgICAgICAgICAgICAgIGlmIChpbmRpY2VzLmxlbmd0aCA9PT0gMCkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gcm9vdE5vZGU7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgdmFyIGluZGV4ID0gZG9tSW5kZXgocm9vdE5vZGUsIHBhdGNoZXMuYSwgaW5kaWNlcyk7XG4gICAgICAgICAgICAgICAgdmFyIG93bmVyRG9jdW1lbnQgPSByb290Tm9kZS5vd25lckRvY3VtZW50O1xuXG4gICAgICAgICAgICAgICAgaWYgKCFyZW5kZXJPcHRpb25zLmRvY3VtZW50ICYmIG93bmVyRG9jdW1lbnQgIT09IGRvY3VtZW50KSB7XG4gICAgICAgICAgICAgICAgICAgIHJlbmRlck9wdGlvbnMuZG9jdW1lbnQgPSBvd25lckRvY3VtZW50O1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgaW5kaWNlcy5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgICAgICAgICB2YXIgbm9kZUluZGV4ID0gaW5kaWNlc1tpXTtcbiAgICAgICAgICAgICAgICAgICAgcm9vdE5vZGUgPSBhcHBseVBhdGNoKHJvb3ROb2RlLCBpbmRleFtub2RlSW5kZXhdLCBwYXRjaGVzW25vZGVJbmRleF0sIHJlbmRlck9wdGlvbnMpO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHJldHVybiByb290Tm9kZTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZnVuY3Rpb24gYXBwbHlQYXRjaChyb290Tm9kZSwgZG9tTm9kZSwgcGF0Y2hMaXN0LCByZW5kZXJPcHRpb25zKSB7XG4gICAgICAgICAgICAgICAgaWYgKCFkb21Ob2RlKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiByb290Tm9kZTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICB2YXIgbmV3Tm9kZTtcblxuICAgICAgICAgICAgICAgIGlmIChpc0FycmF5KHBhdGNoTGlzdCkpIHtcbiAgICAgICAgICAgICAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCBwYXRjaExpc3QubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIG5ld05vZGUgPSBwYXRjaE9wKHBhdGNoTGlzdFtpXSwgZG9tTm9kZSwgcmVuZGVyT3B0aW9ucyk7XG5cbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChkb21Ob2RlID09PSByb290Tm9kZSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJvb3ROb2RlID0gbmV3Tm9kZTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIG5ld05vZGUgPSBwYXRjaE9wKHBhdGNoTGlzdCwgZG9tTm9kZSwgcmVuZGVyT3B0aW9ucyk7XG5cbiAgICAgICAgICAgICAgICAgICAgaWYgKGRvbU5vZGUgPT09IHJvb3ROb2RlKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICByb290Tm9kZSA9IG5ld05vZGU7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICByZXR1cm4gcm9vdE5vZGU7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIHBhdGNoSW5kaWNlcyhwYXRjaGVzKSB7XG4gICAgICAgICAgICAgICAgdmFyIGluZGljZXMgPSBbXTtcblxuICAgICAgICAgICAgICAgIGZvciAodmFyIGtleSBpbiBwYXRjaGVzKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmIChrZXkgIT09IFwiYVwiKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBpbmRpY2VzLnB1c2goTnVtYmVyKGtleSkpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgcmV0dXJuIGluZGljZXM7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0sIHsgXCIuL2NyZWF0ZS1lbGVtZW50XCI6IDE1LCBcIi4vZG9tLWluZGV4XCI6IDE2LCBcIi4vcGF0Y2gtb3BcIjogMTcsIFwiZ2xvYmFsL2RvY3VtZW50XCI6IDEwLCBcIngtaXMtYXJyYXlcIjogMTIgfV0sIDE5OiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge1xuICAgICAgICAgICAgdmFyIGlzV2lkZ2V0ID0gcmVxdWlyZShcIi4uL3Zub2RlL2lzLXdpZGdldC5qc1wiKTtcblxuICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSB1cGRhdGVXaWRnZXQ7XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIHVwZGF0ZVdpZGdldChhLCBiKSB7XG4gICAgICAgICAgICAgICAgaWYgKGlzV2lkZ2V0KGEpICYmIGlzV2lkZ2V0KGIpKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmIChcIm5hbWVcIiBpbiBhICYmIFwibmFtZVwiIGluIGIpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBhLmlkID09PSBiLmlkO1xuICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGEuaW5pdCA9PT0gYi5pbml0O1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICAgICAgfVxuICAgICAgICB9LCB7IFwiLi4vdm5vZGUvaXMtd2lkZ2V0LmpzXCI6IDI5IH1dLCAyMDogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHtcbiAgICAgICAgICAgIFwidXNlIHN0cmljdFwiO1xuXG4gICAgICAgICAgICB2YXIgRXZTdG9yZSA9IHJlcXVpcmUoXCJldi1zdG9yZVwiKTtcblxuICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBFdkhvb2s7XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIEV2SG9vayh2YWx1ZSkge1xuICAgICAgICAgICAgICAgIGlmICghKHRoaXMgaW5zdGFuY2VvZiBFdkhvb2spKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBuZXcgRXZIb29rKHZhbHVlKTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICB0aGlzLnZhbHVlID0gdmFsdWU7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIEV2SG9vay5wcm90b3R5cGUuaG9vayA9IGZ1bmN0aW9uIChub2RlLCBwcm9wZXJ0eU5hbWUpIHtcbiAgICAgICAgICAgICAgICB2YXIgZXMgPSBFdlN0b3JlKG5vZGUpO1xuICAgICAgICAgICAgICAgIHZhciBwcm9wTmFtZSA9IHByb3BlcnR5TmFtZS5zdWJzdHIoMyk7XG5cbiAgICAgICAgICAgICAgICBlc1twcm9wTmFtZV0gPSB0aGlzLnZhbHVlO1xuICAgICAgICAgICAgfTtcblxuICAgICAgICAgICAgRXZIb29rLnByb3RvdHlwZS51bmhvb2sgPSBmdW5jdGlvbiAobm9kZSwgcHJvcGVydHlOYW1lKSB7XG4gICAgICAgICAgICAgICAgdmFyIGVzID0gRXZTdG9yZShub2RlKTtcbiAgICAgICAgICAgICAgICB2YXIgcHJvcE5hbWUgPSBwcm9wZXJ0eU5hbWUuc3Vic3RyKDMpO1xuXG4gICAgICAgICAgICAgICAgZXNbcHJvcE5hbWVdID0gdW5kZWZpbmVkO1xuICAgICAgICAgICAgfTtcbiAgICAgICAgfSwgeyBcImV2LXN0b3JlXCI6IDcgfV0sIDIxOiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge1xuICAgICAgICAgICAgXCJ1c2Ugc3RyaWN0XCI7XG5cbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gU29mdFNldEhvb2s7XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIFNvZnRTZXRIb29rKHZhbHVlKSB7XG4gICAgICAgICAgICAgICAgaWYgKCEodGhpcyBpbnN0YW5jZW9mIFNvZnRTZXRIb29rKSkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gbmV3IFNvZnRTZXRIb29rKHZhbHVlKTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICB0aGlzLnZhbHVlID0gdmFsdWU7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIFNvZnRTZXRIb29rLnByb3RvdHlwZS5ob29rID0gZnVuY3Rpb24gKG5vZGUsIHByb3BlcnR5TmFtZSkge1xuICAgICAgICAgICAgICAgIGlmIChub2RlW3Byb3BlcnR5TmFtZV0gIT09IHRoaXMudmFsdWUpIHtcbiAgICAgICAgICAgICAgICAgICAgbm9kZVtwcm9wZXJ0eU5hbWVdID0gdGhpcy52YWx1ZTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9O1xuICAgICAgICB9LCB7fV0sIDIyOiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge1xuICAgICAgICAgICAgXCJ1c2Ugc3RyaWN0XCI7XG5cbiAgICAgICAgICAgIHZhciBpc0FycmF5ID0gcmVxdWlyZShcIngtaXMtYXJyYXlcIik7XG5cbiAgICAgICAgICAgIHZhciBWTm9kZSA9IHJlcXVpcmUoXCIuLi92bm9kZS92bm9kZS5qc1wiKTtcbiAgICAgICAgICAgIHZhciBWVGV4dCA9IHJlcXVpcmUoXCIuLi92bm9kZS92dGV4dC5qc1wiKTtcbiAgICAgICAgICAgIHZhciBpc1ZOb2RlID0gcmVxdWlyZShcIi4uL3Zub2RlL2lzLXZub2RlXCIpO1xuICAgICAgICAgICAgdmFyIGlzVlRleHQgPSByZXF1aXJlKFwiLi4vdm5vZGUvaXMtdnRleHRcIik7XG4gICAgICAgICAgICB2YXIgaXNXaWRnZXQgPSByZXF1aXJlKFwiLi4vdm5vZGUvaXMtd2lkZ2V0XCIpO1xuICAgICAgICAgICAgdmFyIGlzSG9vayA9IHJlcXVpcmUoXCIuLi92bm9kZS9pcy12aG9va1wiKTtcbiAgICAgICAgICAgIHZhciBpc1ZUaHVuayA9IHJlcXVpcmUoXCIuLi92bm9kZS9pcy10aHVua1wiKTtcblxuICAgICAgICAgICAgdmFyIHBhcnNlVGFnID0gcmVxdWlyZShcIi4vcGFyc2UtdGFnLmpzXCIpO1xuICAgICAgICAgICAgdmFyIHNvZnRTZXRIb29rID0gcmVxdWlyZShcIi4vaG9va3Mvc29mdC1zZXQtaG9vay5qc1wiKTtcbiAgICAgICAgICAgIHZhciBldkhvb2sgPSByZXF1aXJlKFwiLi9ob29rcy9ldi1ob29rLmpzXCIpO1xuXG4gICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IGg7XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIGgodGFnTmFtZSwgcHJvcGVydGllcywgY2hpbGRyZW4pIHtcbiAgICAgICAgICAgICAgICB2YXIgY2hpbGROb2RlcyA9IFtdO1xuICAgICAgICAgICAgICAgIHZhciB0YWcsIHByb3BzLCBrZXksIG5hbWVzcGFjZTtcblxuICAgICAgICAgICAgICAgIGlmICghY2hpbGRyZW4gJiYgaXNDaGlsZHJlbihwcm9wZXJ0aWVzKSkge1xuICAgICAgICAgICAgICAgICAgICBjaGlsZHJlbiA9IHByb3BlcnRpZXM7XG4gICAgICAgICAgICAgICAgICAgIHByb3BzID0ge307XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgcHJvcHMgPSBwcm9wcyB8fCBwcm9wZXJ0aWVzIHx8IHt9O1xuICAgICAgICAgICAgICAgIHRhZyA9IHBhcnNlVGFnKHRhZ05hbWUsIHByb3BzKTtcblxuICAgICAgICAgICAgICAgIC8vIHN1cHBvcnQga2V5c1xuICAgICAgICAgICAgICAgIGlmIChwcm9wcy5oYXNPd25Qcm9wZXJ0eShcImtleVwiKSkge1xuICAgICAgICAgICAgICAgICAgICBrZXkgPSBwcm9wcy5rZXk7XG4gICAgICAgICAgICAgICAgICAgIHByb3BzLmtleSA9IHVuZGVmaW5lZDtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAvLyBzdXBwb3J0IG5hbWVzcGFjZVxuICAgICAgICAgICAgICAgIGlmIChwcm9wcy5oYXNPd25Qcm9wZXJ0eShcIm5hbWVzcGFjZVwiKSkge1xuICAgICAgICAgICAgICAgICAgICBuYW1lc3BhY2UgPSBwcm9wcy5uYW1lc3BhY2U7XG4gICAgICAgICAgICAgICAgICAgIHByb3BzLm5hbWVzcGFjZSA9IHVuZGVmaW5lZDtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAvLyBmaXggY3Vyc29yIGJ1Z1xuICAgICAgICAgICAgICAgIGlmICh0YWcgPT09IFwiSU5QVVRcIiAmJiAhbmFtZXNwYWNlICYmIHByb3BzLmhhc093blByb3BlcnR5KFwidmFsdWVcIikgJiYgcHJvcHMudmFsdWUgIT09IHVuZGVmaW5lZCAmJiAhaXNIb29rKHByb3BzLnZhbHVlKSkge1xuICAgICAgICAgICAgICAgICAgICBwcm9wcy52YWx1ZSA9IHNvZnRTZXRIb29rKHByb3BzLnZhbHVlKTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICB0cmFuc2Zvcm1Qcm9wZXJ0aWVzKHByb3BzKTtcblxuICAgICAgICAgICAgICAgIGlmIChjaGlsZHJlbiAhPT0gdW5kZWZpbmVkICYmIGNoaWxkcmVuICE9PSBudWxsKSB7XG4gICAgICAgICAgICAgICAgICAgIGFkZENoaWxkKGNoaWxkcmVuLCBjaGlsZE5vZGVzLCB0YWcsIHByb3BzKTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICByZXR1cm4gbmV3IFZOb2RlKHRhZywgcHJvcHMsIGNoaWxkTm9kZXMsIGtleSwgbmFtZXNwYWNlKTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZnVuY3Rpb24gYWRkQ2hpbGQoYywgY2hpbGROb2RlcywgdGFnLCBwcm9wcykge1xuICAgICAgICAgICAgICAgIGlmICh0eXBlb2YgYyA9PT0gXCJzdHJpbmdcIikge1xuICAgICAgICAgICAgICAgICAgICBjaGlsZE5vZGVzLnB1c2gobmV3IFZUZXh0KGMpKTtcbiAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKHR5cGVvZiBjID09PSBcIm51bWJlclwiKSB7XG4gICAgICAgICAgICAgICAgICAgIGNoaWxkTm9kZXMucHVzaChuZXcgVlRleHQoU3RyaW5nKGMpKSk7XG4gICAgICAgICAgICAgICAgfSBlbHNlIGlmIChpc0NoaWxkKGMpKSB7XG4gICAgICAgICAgICAgICAgICAgIGNoaWxkTm9kZXMucHVzaChjKTtcbiAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKGlzQXJyYXkoYykpIHtcbiAgICAgICAgICAgICAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCBjLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBhZGRDaGlsZChjW2ldLCBjaGlsZE5vZGVzLCB0YWcsIHByb3BzKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoYyA9PT0gbnVsbCB8fCBjID09PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIHRocm93IFVuZXhwZWN0ZWRWaXJ0dWFsRWxlbWVudCh7XG4gICAgICAgICAgICAgICAgICAgICAgICBmb3JlaWduT2JqZWN0OiBjLFxuICAgICAgICAgICAgICAgICAgICAgICAgcGFyZW50Vm5vZGU6IHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0YWdOYW1lOiB0YWcsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcHJvcGVydGllczogcHJvcHNcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBmdW5jdGlvbiB0cmFuc2Zvcm1Qcm9wZXJ0aWVzKHByb3BzKSB7XG4gICAgICAgICAgICAgICAgZm9yICh2YXIgcHJvcE5hbWUgaW4gcHJvcHMpIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKHByb3BzLmhhc093blByb3BlcnR5KHByb3BOYW1lKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgdmFyIHZhbHVlID0gcHJvcHNbcHJvcE5hbWVdO1xuXG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoaXNIb29rKHZhbHVlKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnRpbnVlO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAocHJvcE5hbWUuc3Vic3RyKDAsIDMpID09PSBcImV2LVwiKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gYWRkIGV2LWZvbyBzdXBwb3J0XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcHJvcHNbcHJvcE5hbWVdID0gZXZIb29rKHZhbHVlKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZnVuY3Rpb24gaXNDaGlsZCh4KSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGlzVk5vZGUoeCkgfHwgaXNWVGV4dCh4KSB8fCBpc1dpZGdldCh4KSB8fCBpc1ZUaHVuayh4KTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZnVuY3Rpb24gaXNDaGlsZHJlbih4KSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHR5cGVvZiB4ID09PSBcInN0cmluZ1wiIHx8IGlzQXJyYXkoeCkgfHwgaXNDaGlsZCh4KTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZnVuY3Rpb24gVW5leHBlY3RlZFZpcnR1YWxFbGVtZW50KGRhdGEpIHtcbiAgICAgICAgICAgICAgICB2YXIgZXJyID0gbmV3IEVycm9yKCk7XG5cbiAgICAgICAgICAgICAgICBlcnIudHlwZSA9IFwidmlydHVhbC1oeXBlcnNjcmlwdC51bmV4cGVjdGVkLnZpcnR1YWwtZWxlbWVudFwiO1xuICAgICAgICAgICAgICAgIGVyci5tZXNzYWdlID0gXCJVbmV4cGVjdGVkIHZpcnR1YWwgY2hpbGQgcGFzc2VkIHRvIGgoKS5cXG5cIiArIFwiRXhwZWN0ZWQgYSBWTm9kZSAvIFZ0aHVuayAvIFZXaWRnZXQgLyBzdHJpbmcgYnV0OlxcblwiICsgXCJnb3Q6XFxuXCIgKyBlcnJvclN0cmluZyhkYXRhLmZvcmVpZ25PYmplY3QpICsgXCIuXFxuXCIgKyBcIlRoZSBwYXJlbnQgdm5vZGUgaXM6XFxuXCIgKyBlcnJvclN0cmluZyhkYXRhLnBhcmVudFZub2RlKTtcbiAgICAgICAgICAgICAgICBcIlxcblwiICsgXCJTdWdnZXN0ZWQgZml4OiBjaGFuZ2UgeW91ciBgaCguLi4sIFsgLi4uIF0pYCBjYWxsc2l0ZS5cIjtcbiAgICAgICAgICAgICAgICBlcnIuZm9yZWlnbk9iamVjdCA9IGRhdGEuZm9yZWlnbk9iamVjdDtcbiAgICAgICAgICAgICAgICBlcnIucGFyZW50Vm5vZGUgPSBkYXRhLnBhcmVudFZub2RlO1xuXG4gICAgICAgICAgICAgICAgcmV0dXJuIGVycjtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZnVuY3Rpb24gZXJyb3JTdHJpbmcob2JqKSB7XG4gICAgICAgICAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIEpTT04uc3RyaW5naWZ5KG9iaiwgbnVsbCwgXCIgICAgXCIpO1xuICAgICAgICAgICAgICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIFN0cmluZyhvYmopO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgfSwgeyBcIi4uL3Zub2RlL2lzLXRodW5rXCI6IDI1LCBcIi4uL3Zub2RlL2lzLXZob29rXCI6IDI2LCBcIi4uL3Zub2RlL2lzLXZub2RlXCI6IDI3LCBcIi4uL3Zub2RlL2lzLXZ0ZXh0XCI6IDI4LCBcIi4uL3Zub2RlL2lzLXdpZGdldFwiOiAyOSwgXCIuLi92bm9kZS92bm9kZS5qc1wiOiAzMSwgXCIuLi92bm9kZS92dGV4dC5qc1wiOiAzMywgXCIuL2hvb2tzL2V2LWhvb2suanNcIjogMjAsIFwiLi9ob29rcy9zb2Z0LXNldC1ob29rLmpzXCI6IDIxLCBcIi4vcGFyc2UtdGFnLmpzXCI6IDIzLCBcIngtaXMtYXJyYXlcIjogMTIgfV0sIDIzOiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge1xuICAgICAgICAgICAgXCJ1c2Ugc3RyaWN0XCI7XG5cbiAgICAgICAgICAgIHZhciBzcGxpdCA9IHJlcXVpcmUoXCJicm93c2VyLXNwbGl0XCIpO1xuXG4gICAgICAgICAgICB2YXIgY2xhc3NJZFNwbGl0ID0gLyhbXFwuI10/W2EtekEtWjAtOVxcdTAwN0YtXFx1RkZGRl86LV0rKS87XG4gICAgICAgICAgICB2YXIgbm90Q2xhc3NJZCA9IC9eXFwufCMvO1xuXG4gICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IHBhcnNlVGFnO1xuXG4gICAgICAgICAgICBmdW5jdGlvbiBwYXJzZVRhZyh0YWcsIHByb3BzKSB7XG4gICAgICAgICAgICAgICAgaWYgKCF0YWcpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIFwiRElWXCI7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgdmFyIG5vSWQgPSAhcHJvcHMuaGFzT3duUHJvcGVydHkoXCJpZFwiKTtcblxuICAgICAgICAgICAgICAgIHZhciB0YWdQYXJ0cyA9IHNwbGl0KHRhZywgY2xhc3NJZFNwbGl0KTtcbiAgICAgICAgICAgICAgICB2YXIgdGFnTmFtZSA9IG51bGw7XG5cbiAgICAgICAgICAgICAgICBpZiAobm90Q2xhc3NJZC50ZXN0KHRhZ1BhcnRzWzFdKSkge1xuICAgICAgICAgICAgICAgICAgICB0YWdOYW1lID0gXCJESVZcIjtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICB2YXIgY2xhc3NlcywgcGFydCwgdHlwZSwgaTtcblxuICAgICAgICAgICAgICAgIGZvciAoaSA9IDA7IGkgPCB0YWdQYXJ0cy5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgICAgICAgICBwYXJ0ID0gdGFnUGFydHNbaV07XG5cbiAgICAgICAgICAgICAgICAgICAgaWYgKCFwYXJ0KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBjb250aW51ZTtcbiAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgIHR5cGUgPSBwYXJ0LmNoYXJBdCgwKTtcblxuICAgICAgICAgICAgICAgICAgICBpZiAoIXRhZ05hbWUpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHRhZ05hbWUgPSBwYXJ0O1xuICAgICAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKHR5cGUgPT09IFwiLlwiKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBjbGFzc2VzID0gY2xhc3NlcyB8fCBbXTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGNsYXNzZXMucHVzaChwYXJ0LnN1YnN0cmluZygxLCBwYXJ0Lmxlbmd0aCkpO1xuICAgICAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKHR5cGUgPT09IFwiI1wiICYmIG5vSWQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHByb3BzLmlkID0gcGFydC5zdWJzdHJpbmcoMSwgcGFydC5sZW5ndGgpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgaWYgKGNsYXNzZXMpIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKHByb3BzLmNsYXNzTmFtZSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgY2xhc3Nlcy5wdXNoKHByb3BzLmNsYXNzTmFtZSk7XG4gICAgICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgICAgICBwcm9wcy5jbGFzc05hbWUgPSBjbGFzc2VzLmpvaW4oXCIgXCIpO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHJldHVybiBwcm9wcy5uYW1lc3BhY2UgPyB0YWdOYW1lIDogdGFnTmFtZS50b1VwcGVyQ2FzZSgpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9LCB7IFwiYnJvd3Nlci1zcGxpdFwiOiA1IH1dLCAyNDogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHtcbiAgICAgICAgICAgIHZhciBpc1ZOb2RlID0gcmVxdWlyZShcIi4vaXMtdm5vZGVcIik7XG4gICAgICAgICAgICB2YXIgaXNWVGV4dCA9IHJlcXVpcmUoXCIuL2lzLXZ0ZXh0XCIpO1xuICAgICAgICAgICAgdmFyIGlzV2lkZ2V0ID0gcmVxdWlyZShcIi4vaXMtd2lkZ2V0XCIpO1xuICAgICAgICAgICAgdmFyIGlzVGh1bmsgPSByZXF1aXJlKFwiLi9pcy10aHVua1wiKTtcblxuICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBoYW5kbGVUaHVuaztcblxuICAgICAgICAgICAgZnVuY3Rpb24gaGFuZGxlVGh1bmsoYSwgYikge1xuICAgICAgICAgICAgICAgIHZhciByZW5kZXJlZEEgPSBhO1xuICAgICAgICAgICAgICAgIHZhciByZW5kZXJlZEIgPSBiO1xuXG4gICAgICAgICAgICAgICAgaWYgKGlzVGh1bmsoYikpIHtcbiAgICAgICAgICAgICAgICAgICAgcmVuZGVyZWRCID0gcmVuZGVyVGh1bmsoYiwgYSk7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgaWYgKGlzVGh1bmsoYSkpIHtcbiAgICAgICAgICAgICAgICAgICAgcmVuZGVyZWRBID0gcmVuZGVyVGh1bmsoYSwgbnVsbCk7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgICAgICAgICAgYTogcmVuZGVyZWRBLFxuICAgICAgICAgICAgICAgICAgICBiOiByZW5kZXJlZEJcbiAgICAgICAgICAgICAgICB9O1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBmdW5jdGlvbiByZW5kZXJUaHVuayh0aHVuaywgcHJldmlvdXMpIHtcbiAgICAgICAgICAgICAgICB2YXIgcmVuZGVyZWRUaHVuayA9IHRodW5rLnZub2RlO1xuXG4gICAgICAgICAgICAgICAgaWYgKCFyZW5kZXJlZFRodW5rKSB7XG4gICAgICAgICAgICAgICAgICAgIHJlbmRlcmVkVGh1bmsgPSB0aHVuay52bm9kZSA9IHRodW5rLnJlbmRlcihwcmV2aW91cyk7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgaWYgKCEoaXNWTm9kZShyZW5kZXJlZFRodW5rKSB8fCBpc1ZUZXh0KHJlbmRlcmVkVGh1bmspIHx8IGlzV2lkZ2V0KHJlbmRlcmVkVGh1bmspKSkge1xuICAgICAgICAgICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoXCJ0aHVuayBkaWQgbm90IHJldHVybiBhIHZhbGlkIG5vZGVcIik7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgcmV0dXJuIHJlbmRlcmVkVGh1bms7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0sIHsgXCIuL2lzLXRodW5rXCI6IDI1LCBcIi4vaXMtdm5vZGVcIjogMjcsIFwiLi9pcy12dGV4dFwiOiAyOCwgXCIuL2lzLXdpZGdldFwiOiAyOSB9XSwgMjU6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IGlzVGh1bms7XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIGlzVGh1bmsodCkge1xuICAgICAgICAgICAgICAgIHJldHVybiB0ICYmIHQudHlwZSA9PT0gXCJUaHVua1wiO1xuICAgICAgICAgICAgfVxuICAgICAgICB9LCB7fV0sIDI2OiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge1xuICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBpc0hvb2s7XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIGlzSG9vayhob29rKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGhvb2sgJiYgKHR5cGVvZiBob29rLmhvb2sgPT09IFwiZnVuY3Rpb25cIiAmJiAhaG9vay5oYXNPd25Qcm9wZXJ0eShcImhvb2tcIikgfHwgdHlwZW9mIGhvb2sudW5ob29rID09PSBcImZ1bmN0aW9uXCIgJiYgIWhvb2suaGFzT3duUHJvcGVydHkoXCJ1bmhvb2tcIikpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9LCB7fV0sIDI3OiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge1xuICAgICAgICAgICAgdmFyIHZlcnNpb24gPSByZXF1aXJlKFwiLi92ZXJzaW9uXCIpO1xuXG4gICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IGlzVmlydHVhbE5vZGU7XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIGlzVmlydHVhbE5vZGUoeCkge1xuICAgICAgICAgICAgICAgIHJldHVybiB4ICYmIHgudHlwZSA9PT0gXCJWaXJ0dWFsTm9kZVwiICYmIHgudmVyc2lvbiA9PT0gdmVyc2lvbjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSwgeyBcIi4vdmVyc2lvblwiOiAzMCB9XSwgMjg6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICB2YXIgdmVyc2lvbiA9IHJlcXVpcmUoXCIuL3ZlcnNpb25cIik7XG5cbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gaXNWaXJ0dWFsVGV4dDtcblxuICAgICAgICAgICAgZnVuY3Rpb24gaXNWaXJ0dWFsVGV4dCh4KSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHggJiYgeC50eXBlID09PSBcIlZpcnR1YWxUZXh0XCIgJiYgeC52ZXJzaW9uID09PSB2ZXJzaW9uO1xuICAgICAgICAgICAgfVxuICAgICAgICB9LCB7IFwiLi92ZXJzaW9uXCI6IDMwIH1dLCAyOTogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHtcbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gaXNXaWRnZXQ7XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIGlzV2lkZ2V0KHcpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gdyAmJiB3LnR5cGUgPT09IFwiV2lkZ2V0XCI7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0sIHt9XSwgMzA6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IFwiMlwiO1xuICAgICAgICB9LCB7fV0sIDMxOiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge1xuICAgICAgICAgICAgdmFyIHZlcnNpb24gPSByZXF1aXJlKFwiLi92ZXJzaW9uXCIpO1xuICAgICAgICAgICAgdmFyIGlzVk5vZGUgPSByZXF1aXJlKFwiLi9pcy12bm9kZVwiKTtcbiAgICAgICAgICAgIHZhciBpc1dpZGdldCA9IHJlcXVpcmUoXCIuL2lzLXdpZGdldFwiKTtcbiAgICAgICAgICAgIHZhciBpc1RodW5rID0gcmVxdWlyZShcIi4vaXMtdGh1bmtcIik7XG4gICAgICAgICAgICB2YXIgaXNWSG9vayA9IHJlcXVpcmUoXCIuL2lzLXZob29rXCIpO1xuXG4gICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IFZpcnR1YWxOb2RlO1xuXG4gICAgICAgICAgICB2YXIgbm9Qcm9wZXJ0aWVzID0ge307XG4gICAgICAgICAgICB2YXIgbm9DaGlsZHJlbiA9IFtdO1xuXG4gICAgICAgICAgICBmdW5jdGlvbiBWaXJ0dWFsTm9kZSh0YWdOYW1lLCBwcm9wZXJ0aWVzLCBjaGlsZHJlbiwga2V5LCBuYW1lc3BhY2UpIHtcbiAgICAgICAgICAgICAgICB0aGlzLnRhZ05hbWUgPSB0YWdOYW1lO1xuICAgICAgICAgICAgICAgIHRoaXMucHJvcGVydGllcyA9IHByb3BlcnRpZXMgfHwgbm9Qcm9wZXJ0aWVzO1xuICAgICAgICAgICAgICAgIHRoaXMuY2hpbGRyZW4gPSBjaGlsZHJlbiB8fCBub0NoaWxkcmVuO1xuICAgICAgICAgICAgICAgIHRoaXMua2V5ID0ga2V5ICE9IG51bGwgPyBTdHJpbmcoa2V5KSA6IHVuZGVmaW5lZDtcbiAgICAgICAgICAgICAgICB0aGlzLm5hbWVzcGFjZSA9IHR5cGVvZiBuYW1lc3BhY2UgPT09IFwic3RyaW5nXCIgPyBuYW1lc3BhY2UgOiBudWxsO1xuXG4gICAgICAgICAgICAgICAgdmFyIGNvdW50ID0gY2hpbGRyZW4gJiYgY2hpbGRyZW4ubGVuZ3RoIHx8IDA7XG4gICAgICAgICAgICAgICAgdmFyIGRlc2NlbmRhbnRzID0gMDtcbiAgICAgICAgICAgICAgICB2YXIgaGFzV2lkZ2V0cyA9IGZhbHNlO1xuICAgICAgICAgICAgICAgIHZhciBoYXNUaHVua3MgPSBmYWxzZTtcbiAgICAgICAgICAgICAgICB2YXIgZGVzY2VuZGFudEhvb2tzID0gZmFsc2U7XG4gICAgICAgICAgICAgICAgdmFyIGhvb2tzO1xuXG4gICAgICAgICAgICAgICAgZm9yICh2YXIgcHJvcE5hbWUgaW4gcHJvcGVydGllcykge1xuICAgICAgICAgICAgICAgICAgICBpZiAocHJvcGVydGllcy5oYXNPd25Qcm9wZXJ0eShwcm9wTmFtZSkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHZhciBwcm9wZXJ0eSA9IHByb3BlcnRpZXNbcHJvcE5hbWVdO1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGlzVkhvb2socHJvcGVydHkpICYmIHByb3BlcnR5LnVuaG9vaykge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmICghaG9va3MpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaG9va3MgPSB7fTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBob29rc1twcm9wTmFtZV0gPSBwcm9wZXJ0eTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgY291bnQ7IGkrKykge1xuICAgICAgICAgICAgICAgICAgICB2YXIgY2hpbGQgPSBjaGlsZHJlbltpXTtcbiAgICAgICAgICAgICAgICAgICAgaWYgKGlzVk5vZGUoY2hpbGQpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBkZXNjZW5kYW50cyArPSBjaGlsZC5jb3VudCB8fCAwO1xuXG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoIWhhc1dpZGdldHMgJiYgY2hpbGQuaGFzV2lkZ2V0cykge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGhhc1dpZGdldHMgPSB0cnVlO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoIWhhc1RodW5rcyAmJiBjaGlsZC5oYXNUaHVua3MpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBoYXNUaHVua3MgPSB0cnVlO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoIWRlc2NlbmRhbnRIb29rcyAmJiAoY2hpbGQuaG9va3MgfHwgY2hpbGQuZGVzY2VuZGFudEhvb2tzKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRlc2NlbmRhbnRIb29rcyA9IHRydWU7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoIWhhc1dpZGdldHMgJiYgaXNXaWRnZXQoY2hpbGQpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAodHlwZW9mIGNoaWxkLmRlc3Ryb3kgPT09IFwiZnVuY3Rpb25cIikge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGhhc1dpZGdldHMgPSB0cnVlO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKCFoYXNUaHVua3MgJiYgaXNUaHVuayhjaGlsZCkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGhhc1RodW5rcyA9IHRydWU7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICB0aGlzLmNvdW50ID0gY291bnQgKyBkZXNjZW5kYW50cztcbiAgICAgICAgICAgICAgICB0aGlzLmhhc1dpZGdldHMgPSBoYXNXaWRnZXRzO1xuICAgICAgICAgICAgICAgIHRoaXMuaGFzVGh1bmtzID0gaGFzVGh1bmtzO1xuICAgICAgICAgICAgICAgIHRoaXMuaG9va3MgPSBob29rcztcbiAgICAgICAgICAgICAgICB0aGlzLmRlc2NlbmRhbnRIb29rcyA9IGRlc2NlbmRhbnRIb29rcztcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgVmlydHVhbE5vZGUucHJvdG90eXBlLnZlcnNpb24gPSB2ZXJzaW9uO1xuICAgICAgICAgICAgVmlydHVhbE5vZGUucHJvdG90eXBlLnR5cGUgPSBcIlZpcnR1YWxOb2RlXCI7XG4gICAgICAgIH0sIHsgXCIuL2lzLXRodW5rXCI6IDI1LCBcIi4vaXMtdmhvb2tcIjogMjYsIFwiLi9pcy12bm9kZVwiOiAyNywgXCIuL2lzLXdpZGdldFwiOiAyOSwgXCIuL3ZlcnNpb25cIjogMzAgfV0sIDMyOiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge1xuICAgICAgICAgICAgdmFyIHZlcnNpb24gPSByZXF1aXJlKFwiLi92ZXJzaW9uXCIpO1xuXG4gICAgICAgICAgICBWaXJ0dWFsUGF0Y2guTk9ORSA9IDA7XG4gICAgICAgICAgICBWaXJ0dWFsUGF0Y2guVlRFWFQgPSAxO1xuICAgICAgICAgICAgVmlydHVhbFBhdGNoLlZOT0RFID0gMjtcbiAgICAgICAgICAgIFZpcnR1YWxQYXRjaC5XSURHRVQgPSAzO1xuICAgICAgICAgICAgVmlydHVhbFBhdGNoLlBST1BTID0gNDtcbiAgICAgICAgICAgIFZpcnR1YWxQYXRjaC5PUkRFUiA9IDU7XG4gICAgICAgICAgICBWaXJ0dWFsUGF0Y2guSU5TRVJUID0gNjtcbiAgICAgICAgICAgIFZpcnR1YWxQYXRjaC5SRU1PVkUgPSA3O1xuICAgICAgICAgICAgVmlydHVhbFBhdGNoLlRIVU5LID0gODtcblxuICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBWaXJ0dWFsUGF0Y2g7XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIFZpcnR1YWxQYXRjaCh0eXBlLCB2Tm9kZSwgcGF0Y2gpIHtcbiAgICAgICAgICAgICAgICB0aGlzLnR5cGUgPSBOdW1iZXIodHlwZSk7XG4gICAgICAgICAgICAgICAgdGhpcy52Tm9kZSA9IHZOb2RlO1xuICAgICAgICAgICAgICAgIHRoaXMucGF0Y2ggPSBwYXRjaDtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgVmlydHVhbFBhdGNoLnByb3RvdHlwZS52ZXJzaW9uID0gdmVyc2lvbjtcbiAgICAgICAgICAgIFZpcnR1YWxQYXRjaC5wcm90b3R5cGUudHlwZSA9IFwiVmlydHVhbFBhdGNoXCI7XG4gICAgICAgIH0sIHsgXCIuL3ZlcnNpb25cIjogMzAgfV0sIDMzOiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge1xuICAgICAgICAgICAgdmFyIHZlcnNpb24gPSByZXF1aXJlKFwiLi92ZXJzaW9uXCIpO1xuXG4gICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IFZpcnR1YWxUZXh0O1xuXG4gICAgICAgICAgICBmdW5jdGlvbiBWaXJ0dWFsVGV4dCh0ZXh0KSB7XG4gICAgICAgICAgICAgICAgdGhpcy50ZXh0ID0gU3RyaW5nKHRleHQpO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBWaXJ0dWFsVGV4dC5wcm90b3R5cGUudmVyc2lvbiA9IHZlcnNpb247XG4gICAgICAgICAgICBWaXJ0dWFsVGV4dC5wcm90b3R5cGUudHlwZSA9IFwiVmlydHVhbFRleHRcIjtcbiAgICAgICAgfSwgeyBcIi4vdmVyc2lvblwiOiAzMCB9XSwgMzQ6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICB2YXIgaXNPYmplY3QgPSByZXF1aXJlKFwiaXMtb2JqZWN0XCIpO1xuICAgICAgICAgICAgdmFyIGlzSG9vayA9IHJlcXVpcmUoXCIuLi92bm9kZS9pcy12aG9va1wiKTtcblxuICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBkaWZmUHJvcHM7XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIGRpZmZQcm9wcyhhLCBiKSB7XG4gICAgICAgICAgICAgICAgdmFyIGRpZmY7XG5cbiAgICAgICAgICAgICAgICBmb3IgKHZhciBhS2V5IGluIGEpIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKCEoYUtleSBpbiBiKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgZGlmZiA9IGRpZmYgfHwge307XG4gICAgICAgICAgICAgICAgICAgICAgICBkaWZmW2FLZXldID0gdW5kZWZpbmVkO1xuICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgdmFyIGFWYWx1ZSA9IGFbYUtleV07XG4gICAgICAgICAgICAgICAgICAgIHZhciBiVmFsdWUgPSBiW2FLZXldO1xuXG4gICAgICAgICAgICAgICAgICAgIGlmIChhVmFsdWUgPT09IGJWYWx1ZSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgY29udGludWU7XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoaXNPYmplY3QoYVZhbHVlKSAmJiBpc09iamVjdChiVmFsdWUpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoZ2V0UHJvdG90eXBlKGJWYWx1ZSkgIT09IGdldFByb3RvdHlwZShhVmFsdWUpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgZGlmZiA9IGRpZmYgfHwge307XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgZGlmZlthS2V5XSA9IGJWYWx1ZTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoaXNIb29rKGJWYWx1ZSkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBkaWZmID0gZGlmZiB8fCB7fTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBkaWZmW2FLZXldID0gYlZhbHVlO1xuICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB2YXIgb2JqZWN0RGlmZiA9IGRpZmZQcm9wcyhhVmFsdWUsIGJWYWx1ZSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKG9iamVjdERpZmYpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZGlmZiA9IGRpZmYgfHwge307XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRpZmZbYUtleV0gPSBvYmplY3REaWZmO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGRpZmYgPSBkaWZmIHx8IHt9O1xuICAgICAgICAgICAgICAgICAgICAgICAgZGlmZlthS2V5XSA9IGJWYWx1ZTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIGZvciAodmFyIGJLZXkgaW4gYikge1xuICAgICAgICAgICAgICAgICAgICBpZiAoIShiS2V5IGluIGEpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBkaWZmID0gZGlmZiB8fCB7fTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGRpZmZbYktleV0gPSBiW2JLZXldO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgcmV0dXJuIGRpZmY7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIGdldFByb3RvdHlwZSh2YWx1ZSkge1xuICAgICAgICAgICAgICAgIGlmIChPYmplY3QuZ2V0UHJvdG90eXBlT2YpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIE9iamVjdC5nZXRQcm90b3R5cGVPZih2YWx1ZSk7XG4gICAgICAgICAgICAgICAgfSBlbHNlIGlmICh2YWx1ZS5fX3Byb3RvX18pIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHZhbHVlLl9fcHJvdG9fXztcbiAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKHZhbHVlLmNvbnN0cnVjdG9yKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiB2YWx1ZS5jb25zdHJ1Y3Rvci5wcm90b3R5cGU7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9LCB7IFwiLi4vdm5vZGUvaXMtdmhvb2tcIjogMjYsIFwiaXMtb2JqZWN0XCI6IDExIH1dLCAzNTogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHtcbiAgICAgICAgICAgIHZhciBpc0FycmF5ID0gcmVxdWlyZShcIngtaXMtYXJyYXlcIik7XG5cbiAgICAgICAgICAgIHZhciBWUGF0Y2ggPSByZXF1aXJlKFwiLi4vdm5vZGUvdnBhdGNoXCIpO1xuICAgICAgICAgICAgdmFyIGlzVk5vZGUgPSByZXF1aXJlKFwiLi4vdm5vZGUvaXMtdm5vZGVcIik7XG4gICAgICAgICAgICB2YXIgaXNWVGV4dCA9IHJlcXVpcmUoXCIuLi92bm9kZS9pcy12dGV4dFwiKTtcbiAgICAgICAgICAgIHZhciBpc1dpZGdldCA9IHJlcXVpcmUoXCIuLi92bm9kZS9pcy13aWRnZXRcIik7XG4gICAgICAgICAgICB2YXIgaXNUaHVuayA9IHJlcXVpcmUoXCIuLi92bm9kZS9pcy10aHVua1wiKTtcbiAgICAgICAgICAgIHZhciBoYW5kbGVUaHVuayA9IHJlcXVpcmUoXCIuLi92bm9kZS9oYW5kbGUtdGh1bmtcIik7XG5cbiAgICAgICAgICAgIHZhciBkaWZmUHJvcHMgPSByZXF1aXJlKFwiLi9kaWZmLXByb3BzXCIpO1xuXG4gICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IGRpZmY7XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIGRpZmYoYSwgYikge1xuICAgICAgICAgICAgICAgIHZhciBwYXRjaCA9IHsgYTogYSB9O1xuICAgICAgICAgICAgICAgIHdhbGsoYSwgYiwgcGF0Y2gsIDApO1xuICAgICAgICAgICAgICAgIHJldHVybiBwYXRjaDtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZnVuY3Rpb24gd2FsayhhLCBiLCBwYXRjaCwgaW5kZXgpIHtcbiAgICAgICAgICAgICAgICBpZiAoYSA9PT0gYikge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgdmFyIGFwcGx5ID0gcGF0Y2hbaW5kZXhdO1xuICAgICAgICAgICAgICAgIHZhciBhcHBseUNsZWFyID0gZmFsc2U7XG5cbiAgICAgICAgICAgICAgICBpZiAoaXNUaHVuayhhKSB8fCBpc1RodW5rKGIpKSB7XG4gICAgICAgICAgICAgICAgICAgIHRodW5rcyhhLCBiLCBwYXRjaCwgaW5kZXgpO1xuICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoYiA9PSBudWxsKSB7XG5cbiAgICAgICAgICAgICAgICAgICAgLy8gSWYgYSBpcyBhIHdpZGdldCB3ZSB3aWxsIGFkZCBhIHJlbW92ZSBwYXRjaCBmb3IgaXRcbiAgICAgICAgICAgICAgICAgICAgLy8gT3RoZXJ3aXNlIGFueSBjaGlsZCB3aWRnZXRzL2hvb2tzIG11c3QgYmUgZGVzdHJveWVkLlxuICAgICAgICAgICAgICAgICAgICAvLyBUaGlzIHByZXZlbnRzIGFkZGluZyB0d28gcmVtb3ZlIHBhdGNoZXMgZm9yIGEgd2lkZ2V0LlxuICAgICAgICAgICAgICAgICAgICBpZiAoIWlzV2lkZ2V0KGEpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBjbGVhclN0YXRlKGEsIHBhdGNoLCBpbmRleCk7XG4gICAgICAgICAgICAgICAgICAgICAgICBhcHBseSA9IHBhdGNoW2luZGV4XTtcbiAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgIGFwcGx5ID0gYXBwZW5kUGF0Y2goYXBwbHksIG5ldyBWUGF0Y2goVlBhdGNoLlJFTU9WRSwgYSwgYikpO1xuICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoaXNWTm9kZShiKSkge1xuICAgICAgICAgICAgICAgICAgICBpZiAoaXNWTm9kZShhKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGEudGFnTmFtZSA9PT0gYi50YWdOYW1lICYmIGEubmFtZXNwYWNlID09PSBiLm5hbWVzcGFjZSAmJiBhLmtleSA9PT0gYi5rZXkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB2YXIgcHJvcHNQYXRjaCA9IGRpZmZQcm9wcyhhLnByb3BlcnRpZXMsIGIucHJvcGVydGllcyk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHByb3BzUGF0Y2gpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYXBwbHkgPSBhcHBlbmRQYXRjaChhcHBseSwgbmV3IFZQYXRjaChWUGF0Y2guUFJPUFMsIGEsIHByb3BzUGF0Y2gpKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgYXBwbHkgPSBkaWZmQ2hpbGRyZW4oYSwgYiwgcGF0Y2gsIGFwcGx5LCBpbmRleCk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGFwcGx5ID0gYXBwZW5kUGF0Y2goYXBwbHksIG5ldyBWUGF0Y2goVlBhdGNoLlZOT0RFLCBhLCBiKSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgYXBwbHlDbGVhciA9IHRydWU7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBhcHBseSA9IGFwcGVuZFBhdGNoKGFwcGx5LCBuZXcgVlBhdGNoKFZQYXRjaC5WTk9ERSwgYSwgYikpO1xuICAgICAgICAgICAgICAgICAgICAgICAgYXBwbHlDbGVhciA9IHRydWU7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKGlzVlRleHQoYikpIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKCFpc1ZUZXh0KGEpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBhcHBseSA9IGFwcGVuZFBhdGNoKGFwcGx5LCBuZXcgVlBhdGNoKFZQYXRjaC5WVEVYVCwgYSwgYikpO1xuICAgICAgICAgICAgICAgICAgICAgICAgYXBwbHlDbGVhciA9IHRydWU7XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoYS50ZXh0ICE9PSBiLnRleHQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGFwcGx5ID0gYXBwZW5kUGF0Y2goYXBwbHksIG5ldyBWUGF0Y2goVlBhdGNoLlZURVhULCBhLCBiKSk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKGlzV2lkZ2V0KGIpKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmICghaXNXaWRnZXQoYSkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGFwcGx5Q2xlYXIgPSB0cnVlO1xuICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgYXBwbHkgPSBhcHBlbmRQYXRjaChhcHBseSwgbmV3IFZQYXRjaChWUGF0Y2guV0lER0VULCBhLCBiKSk7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgaWYgKGFwcGx5KSB7XG4gICAgICAgICAgICAgICAgICAgIHBhdGNoW2luZGV4XSA9IGFwcGx5O1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIGlmIChhcHBseUNsZWFyKSB7XG4gICAgICAgICAgICAgICAgICAgIGNsZWFyU3RhdGUoYSwgcGF0Y2gsIGluZGV4KTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIGRpZmZDaGlsZHJlbihhLCBiLCBwYXRjaCwgYXBwbHksIGluZGV4KSB7XG4gICAgICAgICAgICAgICAgdmFyIGFDaGlsZHJlbiA9IGEuY2hpbGRyZW47XG4gICAgICAgICAgICAgICAgdmFyIG9yZGVyZWRTZXQgPSByZW9yZGVyKGFDaGlsZHJlbiwgYi5jaGlsZHJlbik7XG4gICAgICAgICAgICAgICAgdmFyIGJDaGlsZHJlbiA9IG9yZGVyZWRTZXQuY2hpbGRyZW47XG5cbiAgICAgICAgICAgICAgICB2YXIgYUxlbiA9IGFDaGlsZHJlbi5sZW5ndGg7XG4gICAgICAgICAgICAgICAgdmFyIGJMZW4gPSBiQ2hpbGRyZW4ubGVuZ3RoO1xuICAgICAgICAgICAgICAgIHZhciBsZW4gPSBhTGVuID4gYkxlbiA/IGFMZW4gOiBiTGVuO1xuXG4gICAgICAgICAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCBsZW47IGkrKykge1xuICAgICAgICAgICAgICAgICAgICB2YXIgbGVmdE5vZGUgPSBhQ2hpbGRyZW5baV07XG4gICAgICAgICAgICAgICAgICAgIHZhciByaWdodE5vZGUgPSBiQ2hpbGRyZW5baV07XG4gICAgICAgICAgICAgICAgICAgIGluZGV4ICs9IDE7XG5cbiAgICAgICAgICAgICAgICAgICAgaWYgKCFsZWZ0Tm9kZSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHJpZ2h0Tm9kZSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIEV4Y2VzcyBub2RlcyBpbiBiIG5lZWQgdG8gYmUgYWRkZWRcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBhcHBseSA9IGFwcGVuZFBhdGNoKGFwcGx5LCBuZXcgVlBhdGNoKFZQYXRjaC5JTlNFUlQsIG51bGwsIHJpZ2h0Tm9kZSkpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgd2FsayhsZWZ0Tm9kZSwgcmlnaHROb2RlLCBwYXRjaCwgaW5kZXgpO1xuICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgaWYgKGlzVk5vZGUobGVmdE5vZGUpICYmIGxlZnROb2RlLmNvdW50KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBpbmRleCArPSBsZWZ0Tm9kZS5jb3VudDtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIGlmIChvcmRlcmVkU2V0Lm1vdmVzKSB7XG4gICAgICAgICAgICAgICAgICAgIC8vIFJlb3JkZXIgbm9kZXMgbGFzdFxuICAgICAgICAgICAgICAgICAgICBhcHBseSA9IGFwcGVuZFBhdGNoKGFwcGx5LCBuZXcgVlBhdGNoKFZQYXRjaC5PUkRFUiwgYSwgb3JkZXJlZFNldC5tb3ZlcykpO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHJldHVybiBhcHBseTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZnVuY3Rpb24gY2xlYXJTdGF0ZSh2Tm9kZSwgcGF0Y2gsIGluZGV4KSB7XG4gICAgICAgICAgICAgICAgLy8gVE9ETzogTWFrZSB0aGlzIGEgc2luZ2xlIHdhbGssIG5vdCB0d29cbiAgICAgICAgICAgICAgICB1bmhvb2sodk5vZGUsIHBhdGNoLCBpbmRleCk7XG4gICAgICAgICAgICAgICAgZGVzdHJveVdpZGdldHModk5vZGUsIHBhdGNoLCBpbmRleCk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIC8vIFBhdGNoIHJlY29yZHMgZm9yIGFsbCBkZXN0cm95ZWQgd2lkZ2V0cyBtdXN0IGJlIGFkZGVkIGJlY2F1c2Ugd2UgbmVlZFxuICAgICAgICAgICAgLy8gYSBET00gbm9kZSByZWZlcmVuY2UgZm9yIHRoZSBkZXN0cm95IGZ1bmN0aW9uXG4gICAgICAgICAgICBmdW5jdGlvbiBkZXN0cm95V2lkZ2V0cyh2Tm9kZSwgcGF0Y2gsIGluZGV4KSB7XG4gICAgICAgICAgICAgICAgaWYgKGlzV2lkZ2V0KHZOb2RlKSkge1xuICAgICAgICAgICAgICAgICAgICBpZiAodHlwZW9mIHZOb2RlLmRlc3Ryb3kgPT09IFwiZnVuY3Rpb25cIikge1xuICAgICAgICAgICAgICAgICAgICAgICAgcGF0Y2hbaW5kZXhdID0gYXBwZW5kUGF0Y2gocGF0Y2hbaW5kZXhdLCBuZXcgVlBhdGNoKFZQYXRjaC5SRU1PVkUsIHZOb2RlLCBudWxsKSk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKGlzVk5vZGUodk5vZGUpICYmICh2Tm9kZS5oYXNXaWRnZXRzIHx8IHZOb2RlLmhhc1RodW5rcykpIHtcbiAgICAgICAgICAgICAgICAgICAgdmFyIGNoaWxkcmVuID0gdk5vZGUuY2hpbGRyZW47XG4gICAgICAgICAgICAgICAgICAgIHZhciBsZW4gPSBjaGlsZHJlbi5sZW5ndGg7XG4gICAgICAgICAgICAgICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgbGVuOyBpKyspIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHZhciBjaGlsZCA9IGNoaWxkcmVuW2ldO1xuICAgICAgICAgICAgICAgICAgICAgICAgaW5kZXggKz0gMTtcblxuICAgICAgICAgICAgICAgICAgICAgICAgZGVzdHJveVdpZGdldHMoY2hpbGQsIHBhdGNoLCBpbmRleCk7XG5cbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChpc1ZOb2RlKGNoaWxkKSAmJiBjaGlsZC5jb3VudCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGluZGV4ICs9IGNoaWxkLmNvdW50O1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfSBlbHNlIGlmIChpc1RodW5rKHZOb2RlKSkge1xuICAgICAgICAgICAgICAgICAgICB0aHVua3Modk5vZGUsIG51bGwsIHBhdGNoLCBpbmRleCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAvLyBDcmVhdGUgYSBzdWItcGF0Y2ggZm9yIHRodW5rc1xuICAgICAgICAgICAgZnVuY3Rpb24gdGh1bmtzKGEsIGIsIHBhdGNoLCBpbmRleCkge1xuICAgICAgICAgICAgICAgIHZhciBub2RlcyA9IGhhbmRsZVRodW5rKGEsIGIpO1xuICAgICAgICAgICAgICAgIHZhciB0aHVua1BhdGNoID0gZGlmZihub2Rlcy5hLCBub2Rlcy5iKTtcbiAgICAgICAgICAgICAgICBpZiAoaGFzUGF0Y2hlcyh0aHVua1BhdGNoKSkge1xuICAgICAgICAgICAgICAgICAgICBwYXRjaFtpbmRleF0gPSBuZXcgVlBhdGNoKFZQYXRjaC5USFVOSywgbnVsbCwgdGh1bmtQYXRjaCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBmdW5jdGlvbiBoYXNQYXRjaGVzKHBhdGNoKSB7XG4gICAgICAgICAgICAgICAgZm9yICh2YXIgaW5kZXggaW4gcGF0Y2gpIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKGluZGV4ICE9PSBcImFcIikge1xuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIC8vIEV4ZWN1dGUgaG9va3Mgd2hlbiB0d28gbm9kZXMgYXJlIGlkZW50aWNhbFxuICAgICAgICAgICAgZnVuY3Rpb24gdW5ob29rKHZOb2RlLCBwYXRjaCwgaW5kZXgpIHtcbiAgICAgICAgICAgICAgICBpZiAoaXNWTm9kZSh2Tm9kZSkpIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKHZOb2RlLmhvb2tzKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBwYXRjaFtpbmRleF0gPSBhcHBlbmRQYXRjaChwYXRjaFtpbmRleF0sIG5ldyBWUGF0Y2goVlBhdGNoLlBST1BTLCB2Tm9kZSwgdW5kZWZpbmVkS2V5cyh2Tm9kZS5ob29rcykpKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgIGlmICh2Tm9kZS5kZXNjZW5kYW50SG9va3MgfHwgdk5vZGUuaGFzVGh1bmtzKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICB2YXIgY2hpbGRyZW4gPSB2Tm9kZS5jaGlsZHJlbjtcbiAgICAgICAgICAgICAgICAgICAgICAgIHZhciBsZW4gPSBjaGlsZHJlbi5sZW5ndGg7XG4gICAgICAgICAgICAgICAgICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IGxlbjsgaSsrKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdmFyIGNoaWxkID0gY2hpbGRyZW5baV07XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaW5kZXggKz0gMTtcblxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHVuaG9vayhjaGlsZCwgcGF0Y2gsIGluZGV4KTtcblxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChpc1ZOb2RlKGNoaWxkKSAmJiBjaGlsZC5jb3VudCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpbmRleCArPSBjaGlsZC5jb3VudDtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKGlzVGh1bmsodk5vZGUpKSB7XG4gICAgICAgICAgICAgICAgICAgIHRodW5rcyh2Tm9kZSwgbnVsbCwgcGF0Y2gsIGluZGV4KTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIHVuZGVmaW5lZEtleXMob2JqKSB7XG4gICAgICAgICAgICAgICAgdmFyIHJlc3VsdCA9IHt9O1xuXG4gICAgICAgICAgICAgICAgZm9yICh2YXIga2V5IGluIG9iaikge1xuICAgICAgICAgICAgICAgICAgICByZXN1bHRba2V5XSA9IHVuZGVmaW5lZDtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICByZXR1cm4gcmVzdWx0O1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAvLyBMaXN0IGRpZmYsIG5haXZlIGxlZnQgdG8gcmlnaHQgcmVvcmRlcmluZ1xuICAgICAgICAgICAgZnVuY3Rpb24gcmVvcmRlcihhQ2hpbGRyZW4sIGJDaGlsZHJlbikge1xuICAgICAgICAgICAgICAgIC8vIE8oTSkgdGltZSwgTyhNKSBtZW1vcnlcbiAgICAgICAgICAgICAgICB2YXIgYkNoaWxkSW5kZXggPSBrZXlJbmRleChiQ2hpbGRyZW4pO1xuICAgICAgICAgICAgICAgIHZhciBiS2V5cyA9IGJDaGlsZEluZGV4LmtleXM7XG4gICAgICAgICAgICAgICAgdmFyIGJGcmVlID0gYkNoaWxkSW5kZXguZnJlZTtcblxuICAgICAgICAgICAgICAgIGlmIChiRnJlZS5sZW5ndGggPT09IGJDaGlsZHJlbi5sZW5ndGgpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGNoaWxkcmVuOiBiQ2hpbGRyZW4sXG4gICAgICAgICAgICAgICAgICAgICAgICBtb3ZlczogbnVsbFxuICAgICAgICAgICAgICAgICAgICB9O1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIC8vIE8oTikgdGltZSwgTyhOKSBtZW1vcnlcbiAgICAgICAgICAgICAgICB2YXIgYUNoaWxkSW5kZXggPSBrZXlJbmRleChhQ2hpbGRyZW4pO1xuICAgICAgICAgICAgICAgIHZhciBhS2V5cyA9IGFDaGlsZEluZGV4LmtleXM7XG4gICAgICAgICAgICAgICAgdmFyIGFGcmVlID0gYUNoaWxkSW5kZXguZnJlZTtcblxuICAgICAgICAgICAgICAgIGlmIChhRnJlZS5sZW5ndGggPT09IGFDaGlsZHJlbi5sZW5ndGgpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGNoaWxkcmVuOiBiQ2hpbGRyZW4sXG4gICAgICAgICAgICAgICAgICAgICAgICBtb3ZlczogbnVsbFxuICAgICAgICAgICAgICAgICAgICB9O1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIC8vIE8oTUFYKE4sIE0pKSBtZW1vcnlcbiAgICAgICAgICAgICAgICB2YXIgbmV3Q2hpbGRyZW4gPSBbXTtcblxuICAgICAgICAgICAgICAgIHZhciBmcmVlSW5kZXggPSAwO1xuICAgICAgICAgICAgICAgIHZhciBmcmVlQ291bnQgPSBiRnJlZS5sZW5ndGg7XG4gICAgICAgICAgICAgICAgdmFyIGRlbGV0ZWRJdGVtcyA9IDA7XG5cbiAgICAgICAgICAgICAgICAvLyBJdGVyYXRlIHRocm91Z2ggYSBhbmQgbWF0Y2ggYSBub2RlIGluIGJcbiAgICAgICAgICAgICAgICAvLyBPKE4pIHRpbWUsXG4gICAgICAgICAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCBhQ2hpbGRyZW4ubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgICAgICAgICAgdmFyIGFJdGVtID0gYUNoaWxkcmVuW2ldO1xuICAgICAgICAgICAgICAgICAgICB2YXIgaXRlbUluZGV4O1xuXG4gICAgICAgICAgICAgICAgICAgIGlmIChhSXRlbS5rZXkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChiS2V5cy5oYXNPd25Qcm9wZXJ0eShhSXRlbS5rZXkpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gTWF0Y2ggdXAgdGhlIG9sZCBrZXlzXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaXRlbUluZGV4ID0gYktleXNbYUl0ZW0ua2V5XTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBuZXdDaGlsZHJlbi5wdXNoKGJDaGlsZHJlbltpdGVtSW5kZXhdKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gUmVtb3ZlIG9sZCBrZXllZCBpdGVtc1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGl0ZW1JbmRleCA9IGkgLSBkZWxldGVkSXRlbXMrKztcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBuZXdDaGlsZHJlbi5wdXNoKG51bGwpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgLy8gTWF0Y2ggdGhlIGl0ZW0gaW4gYSB3aXRoIHRoZSBuZXh0IGZyZWUgaXRlbSBpbiBiXG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoZnJlZUluZGV4IDwgZnJlZUNvdW50KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaXRlbUluZGV4ID0gYkZyZWVbZnJlZUluZGV4KytdO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIG5ld0NoaWxkcmVuLnB1c2goYkNoaWxkcmVuW2l0ZW1JbmRleF0pO1xuICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBUaGVyZSBhcmUgbm8gZnJlZSBpdGVtcyBpbiBiIHRvIG1hdGNoIHdpdGhcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyB0aGUgZnJlZSBpdGVtcyBpbiBhLCBzbyB0aGUgZXh0cmEgZnJlZSBub2Rlc1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIGFyZSBkZWxldGVkLlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGl0ZW1JbmRleCA9IGkgLSBkZWxldGVkSXRlbXMrKztcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBuZXdDaGlsZHJlbi5wdXNoKG51bGwpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgdmFyIGxhc3RGcmVlSW5kZXggPSBmcmVlSW5kZXggPj0gYkZyZWUubGVuZ3RoID8gYkNoaWxkcmVuLmxlbmd0aCA6IGJGcmVlW2ZyZWVJbmRleF07XG5cbiAgICAgICAgICAgICAgICAvLyBJdGVyYXRlIHRocm91Z2ggYiBhbmQgYXBwZW5kIGFueSBuZXcga2V5c1xuICAgICAgICAgICAgICAgIC8vIE8oTSkgdGltZVxuICAgICAgICAgICAgICAgIGZvciAodmFyIGogPSAwOyBqIDwgYkNoaWxkcmVuLmxlbmd0aDsgaisrKSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciBuZXdJdGVtID0gYkNoaWxkcmVuW2pdO1xuXG4gICAgICAgICAgICAgICAgICAgIGlmIChuZXdJdGVtLmtleSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKCFhS2V5cy5oYXNPd25Qcm9wZXJ0eShuZXdJdGVtLmtleSkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBBZGQgYW55IG5ldyBrZXllZCBpdGVtc1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIFdlIGFyZSBhZGRpbmcgbmV3IGl0ZW1zIHRvIHRoZSBlbmQgYW5kIHRoZW4gc29ydGluZyB0aGVtXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gaW4gcGxhY2UuIEluIGZ1dHVyZSB3ZSBzaG91bGQgaW5zZXJ0IG5ldyBpdGVtcyBpbiBwbGFjZS5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBuZXdDaGlsZHJlbi5wdXNoKG5ld0l0ZW0pO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKGogPj0gbGFzdEZyZWVJbmRleCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgLy8gQWRkIGFueSBsZWZ0b3ZlciBub24ta2V5ZWQgaXRlbXNcbiAgICAgICAgICAgICAgICAgICAgICAgIG5ld0NoaWxkcmVuLnB1c2gobmV3SXRlbSk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICB2YXIgc2ltdWxhdGUgPSBuZXdDaGlsZHJlbi5zbGljZSgpO1xuICAgICAgICAgICAgICAgIHZhciBzaW11bGF0ZUluZGV4ID0gMDtcbiAgICAgICAgICAgICAgICB2YXIgcmVtb3ZlcyA9IFtdO1xuICAgICAgICAgICAgICAgIHZhciBpbnNlcnRzID0gW107XG4gICAgICAgICAgICAgICAgdmFyIHNpbXVsYXRlSXRlbTtcblxuICAgICAgICAgICAgICAgIGZvciAodmFyIGsgPSAwOyBrIDwgYkNoaWxkcmVuLmxlbmd0aDspIHtcbiAgICAgICAgICAgICAgICAgICAgdmFyIHdhbnRlZEl0ZW0gPSBiQ2hpbGRyZW5ba107XG4gICAgICAgICAgICAgICAgICAgIHNpbXVsYXRlSXRlbSA9IHNpbXVsYXRlW3NpbXVsYXRlSW5kZXhdO1xuXG4gICAgICAgICAgICAgICAgICAgIC8vIHJlbW92ZSBpdGVtc1xuICAgICAgICAgICAgICAgICAgICB3aGlsZSAoc2ltdWxhdGVJdGVtID09PSBudWxsICYmIHNpbXVsYXRlLmxlbmd0aCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgcmVtb3Zlcy5wdXNoKHJlbW92ZShzaW11bGF0ZSwgc2ltdWxhdGVJbmRleCwgbnVsbCkpO1xuICAgICAgICAgICAgICAgICAgICAgICAgc2ltdWxhdGVJdGVtID0gc2ltdWxhdGVbc2ltdWxhdGVJbmRleF07XG4gICAgICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgICAgICBpZiAoIXNpbXVsYXRlSXRlbSB8fCBzaW11bGF0ZUl0ZW0ua2V5ICE9PSB3YW50ZWRJdGVtLmtleSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgLy8gaWYgd2UgbmVlZCBhIGtleSBpbiB0aGlzIHBvc2l0aW9uLi4uXG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAod2FudGVkSXRlbS5rZXkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoc2ltdWxhdGVJdGVtICYmIHNpbXVsYXRlSXRlbS5rZXkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gaWYgYW4gaW5zZXJ0IGRvZXNuJ3QgcHV0IHRoaXMga2V5IGluIHBsYWNlLCBpdCBuZWVkcyB0byBtb3ZlXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChiS2V5c1tzaW11bGF0ZUl0ZW0ua2V5XSAhPT0gayArIDEpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlbW92ZXMucHVzaChyZW1vdmUoc2ltdWxhdGUsIHNpbXVsYXRlSW5kZXgsIHNpbXVsYXRlSXRlbS5rZXkpKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNpbXVsYXRlSXRlbSA9IHNpbXVsYXRlW3NpbXVsYXRlSW5kZXhdO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gaWYgdGhlIHJlbW92ZSBkaWRuJ3QgcHV0IHRoZSB3YW50ZWQgaXRlbSBpbiBwbGFjZSwgd2UgbmVlZCB0byBpbnNlcnQgaXRcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmICghc2ltdWxhdGVJdGVtIHx8IHNpbXVsYXRlSXRlbS5rZXkgIT09IHdhbnRlZEl0ZW0ua2V5KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaW5zZXJ0cy5wdXNoKHsga2V5OiB3YW50ZWRJdGVtLmtleSwgdG86IGsgfSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBpdGVtcyBhcmUgbWF0Y2hpbmcsIHNvIHNraXAgYWhlYWRcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNpbXVsYXRlSW5kZXgrKztcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGluc2VydHMucHVzaCh7IGtleTogd2FudGVkSXRlbS5rZXksIHRvOiBrIH0pO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaW5zZXJ0cy5wdXNoKHsga2V5OiB3YW50ZWRJdGVtLmtleSwgdG86IGsgfSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGsrKztcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIGEga2V5IGluIHNpbXVsYXRlIGhhcyBubyBtYXRjaGluZyB3YW50ZWQga2V5LCByZW1vdmUgaXRcbiAgICAgICAgICAgICAgICAgICAgICAgIGVsc2UgaWYgKHNpbXVsYXRlSXRlbSAmJiBzaW11bGF0ZUl0ZW0ua2V5KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcmVtb3Zlcy5wdXNoKHJlbW92ZShzaW11bGF0ZSwgc2ltdWxhdGVJbmRleCwgc2ltdWxhdGVJdGVtLmtleSkpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgc2ltdWxhdGVJbmRleCsrO1xuICAgICAgICAgICAgICAgICAgICAgICAgaysrO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgLy8gcmVtb3ZlIGFsbCB0aGUgcmVtYWluaW5nIG5vZGVzIGZyb20gc2ltdWxhdGVcbiAgICAgICAgICAgICAgICB3aGlsZSAoc2ltdWxhdGVJbmRleCA8IHNpbXVsYXRlLmxlbmd0aCkge1xuICAgICAgICAgICAgICAgICAgICBzaW11bGF0ZUl0ZW0gPSBzaW11bGF0ZVtzaW11bGF0ZUluZGV4XTtcbiAgICAgICAgICAgICAgICAgICAgcmVtb3Zlcy5wdXNoKHJlbW92ZShzaW11bGF0ZSwgc2ltdWxhdGVJbmRleCwgc2ltdWxhdGVJdGVtICYmIHNpbXVsYXRlSXRlbS5rZXkpKTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAvLyBJZiB0aGUgb25seSBtb3ZlcyB3ZSBoYXZlIGFyZSBkZWxldGVzIHRoZW4gd2UgY2FuIGp1c3RcbiAgICAgICAgICAgICAgICAvLyBsZXQgdGhlIGRlbGV0ZSBwYXRjaCByZW1vdmUgdGhlc2UgaXRlbXMuXG4gICAgICAgICAgICAgICAgaWYgKHJlbW92ZXMubGVuZ3RoID09PSBkZWxldGVkSXRlbXMgJiYgIWluc2VydHMubGVuZ3RoKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiB7XG4gICAgICAgICAgICAgICAgICAgICAgICBjaGlsZHJlbjogbmV3Q2hpbGRyZW4sXG4gICAgICAgICAgICAgICAgICAgICAgICBtb3ZlczogbnVsbFxuICAgICAgICAgICAgICAgICAgICB9O1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHJldHVybiB7XG4gICAgICAgICAgICAgICAgICAgIGNoaWxkcmVuOiBuZXdDaGlsZHJlbixcbiAgICAgICAgICAgICAgICAgICAgbW92ZXM6IHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJlbW92ZXM6IHJlbW92ZXMsXG4gICAgICAgICAgICAgICAgICAgICAgICBpbnNlcnRzOiBpbnNlcnRzXG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9O1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBmdW5jdGlvbiByZW1vdmUoYXJyLCBpbmRleCwga2V5KSB7XG4gICAgICAgICAgICAgICAgYXJyLnNwbGljZShpbmRleCwgMSk7XG5cbiAgICAgICAgICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgICAgICAgICBmcm9tOiBpbmRleCxcbiAgICAgICAgICAgICAgICAgICAga2V5OiBrZXlcbiAgICAgICAgICAgICAgICB9O1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBmdW5jdGlvbiBrZXlJbmRleChjaGlsZHJlbikge1xuICAgICAgICAgICAgICAgIHZhciBrZXlzID0ge307XG4gICAgICAgICAgICAgICAgdmFyIGZyZWUgPSBbXTtcbiAgICAgICAgICAgICAgICB2YXIgbGVuZ3RoID0gY2hpbGRyZW4ubGVuZ3RoO1xuXG4gICAgICAgICAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCBsZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgICAgICAgICB2YXIgY2hpbGQgPSBjaGlsZHJlbltpXTtcblxuICAgICAgICAgICAgICAgICAgICBpZiAoY2hpbGQua2V5KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBrZXlzW2NoaWxkLmtleV0gPSBpO1xuICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgZnJlZS5wdXNoKGkpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgICAgICAgICAga2V5czoga2V5cywgLy8gQSBoYXNoIG9mIGtleSBuYW1lIHRvIGluZGV4XG4gICAgICAgICAgICAgICAgICAgIGZyZWU6IGZyZWUgLy8gQW4gYXJyYXkgb2YgdW5rZXllZCBpdGVtIGluZGljZXNcbiAgICAgICAgICAgICAgICB9O1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBmdW5jdGlvbiBhcHBlbmRQYXRjaChhcHBseSwgcGF0Y2gpIHtcbiAgICAgICAgICAgICAgICBpZiAoYXBwbHkpIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKGlzQXJyYXkoYXBwbHkpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBhcHBseS5wdXNoKHBhdGNoKTtcbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGFwcGx5ID0gW2FwcGx5LCBwYXRjaF07XG4gICAgICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgICAgICByZXR1cm4gYXBwbHk7XG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHBhdGNoO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgfSwgeyBcIi4uL3Zub2RlL2hhbmRsZS10aHVua1wiOiAyNCwgXCIuLi92bm9kZS9pcy10aHVua1wiOiAyNSwgXCIuLi92bm9kZS9pcy12bm9kZVwiOiAyNywgXCIuLi92bm9kZS9pcy12dGV4dFwiOiAyOCwgXCIuLi92bm9kZS9pcy13aWRnZXRcIjogMjksIFwiLi4vdm5vZGUvdnBhdGNoXCI6IDMyLCBcIi4vZGlmZi1wcm9wc1wiOiAzNCwgXCJ4LWlzLWFycmF5XCI6IDEyIH1dIH0sIHt9LCBbNF0pKDQpO1xufSk7XG5cbmNvbnN0IENvcmUgPSBDO1xuXG5leHBvcnQgeyBDb3JlLCBLZXJuZWwsIEVudW0sIExpc3QsIEtleXdvcmQsIGJpdHdpc2UgYXMgQml0d2lzZSwgbWFwIGFzIE1hcCwgbWFwX3NldCBhcyBNYXBTZXQsIFZpcnR1YWxET00gfTsiXSwiZmlsZSI6IkVsaXhpci5qcyIsInNvdXJjZVJvb3QiOiIvc291cmNlLyJ9 \ No newline at end of file +//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiIiwic291cmNlcyI6WyJFbGl4aXIuanMiXSwic291cmNlc0NvbnRlbnQiOlsiLyogQGZsb3cgKi9cblxuY2xhc3MgTWFpbGJveCB7XG5cbiAgY29uc3RydWN0b3IoKSB7XG4gICAgdGhpcy5tZXNzYWdlcyA9IFtdO1xuICB9XG5cbiAgZGVsaXZlcihtZXNzYWdlKSB7XG4gICAgdGhpcy5tZXNzYWdlcy5wdXNoKG1lc3NhZ2UpO1xuICAgIHJldHVybiBtZXNzYWdlO1xuICB9XG5cbiAgZ2V0KCkge1xuICAgIHJldHVybiB0aGlzLm1lc3NhZ2VzO1xuICB9XG5cbiAgaXNFbXB0eSgpIHtcbiAgICByZXR1cm4gdGhpcy5tZXNzYWdlcy5sZW5ndGggPT09IDA7XG4gIH1cblxuICByZW1vdmVBdChpbmRleCkge1xuICAgIHRoaXMubWVzc2FnZXMuc3BsaWNlKGluZGV4LCAxKTtcbiAgfVxufVxuXG52YXIgU3RhdGVzID0ge1xuICBOT1JNQUw6IFN5bWJvbC5mb3IoXCJub3JtYWxcIiksXG4gIEtJTEw6IFN5bWJvbC5mb3IoXCJraWxsXCIpLFxuICBTVVNQRU5EOiBTeW1ib2wuZm9yKFwic3VzcGVuZFwiKSxcbiAgQ09OVElOVUU6IFN5bWJvbC5mb3IoXCJjb250aW51ZVwiKSxcbiAgUkVDRUlWRTogU3ltYm9sLmZvcihcInJlY2VpdmVcIiksXG4gIFNFTkQ6IFN5bWJvbC5mb3IoXCJzZW5kXCIpLFxuICBTTEVFUElORzogU3ltYm9sLmZvcihcInNsZWVwaW5nXCIpLFxuICBSVU5OSU5HOiBTeW1ib2wuZm9yKFwicnVubmluZ1wiKSxcbiAgU1VTUEVOREVEOiBTeW1ib2wuZm9yKFwic3VzcGVuZGVkXCIpLFxuICBTVE9QUEVEOiBTeW1ib2wuZm9yKFwic3RvcHBlZFwiKSxcbiAgU0xFRVA6IFN5bWJvbC5mb3IoXCJzbGVlcFwiKSxcbiAgRVhJVDogU3ltYm9sLmZvcihcImV4aXRcIiksXG4gIE5PTUFUQ0g6IFN5bWJvbC5mb3IoXCJub19tYXRjaFwiKVxufTtcblxuY2xhc3MgUHJvY2VzcyB7XG5cbiAgY29uc3RydWN0b3IocGlkLCBtYWlsYm94KSB7XG4gICAgdGhpcy5waWQgPSBwaWQ7XG4gICAgdGhpcy5tYWlsYm94ID0gbWFpbGJveDtcbiAgICB0aGlzLnN0YXR1cyA9IFN0YXRlcy5TVE9QUEVEO1xuICAgIHRoaXMuZGljdCA9IHt9O1xuICB9XG59XG5cbmNsYXNzIFR1cGxlJDEge1xuXG4gIGNvbnN0cnVjdG9yKC4uLmFyZ3MpIHtcbiAgICB0aGlzLnZhbHVlcyA9IE9iamVjdC5mcmVlemUoYXJncyk7XG4gICAgdGhpcy5sZW5ndGggPSB0aGlzLnZhbHVlcy5sZW5ndGg7XG4gIH1cblxuICBnZXQoaW5kZXgpIHtcbiAgICByZXR1cm4gdGhpcy52YWx1ZXNbaW5kZXhdO1xuICB9XG5cbiAgY291bnQoKSB7XG4gICAgcmV0dXJuIHRoaXMudmFsdWVzLmxlbmd0aDtcbiAgfVxuXG4gIFtTeW1ib2wuaXRlcmF0b3JdKCkge1xuICAgIHJldHVybiB0aGlzLnZhbHVlc1tTeW1ib2wuaXRlcmF0b3JdKCk7XG4gIH1cblxuICB0b1N0cmluZygpIHtcbiAgICB2YXIgaSxcbiAgICAgICAgcyA9IFwiXCI7XG4gICAgZm9yIChpID0gMDsgaSA8IHRoaXMudmFsdWVzLmxlbmd0aDsgaSsrKSB7XG4gICAgICBpZiAocyAhPT0gXCJcIikge1xuICAgICAgICBzICs9IFwiLCBcIjtcbiAgICAgIH1cbiAgICAgIHMgKz0gdGhpcy52YWx1ZXNbaV0udG9TdHJpbmcoKTtcbiAgICB9XG5cbiAgICByZXR1cm4gXCJ7XCIgKyBzICsgXCJ9XCI7XG4gIH1cblxufVxuXG5sZXQgcHJvY2Vzc19jb3VudGVyID0gLTE7XG5cbmNsYXNzIFBJRCB7XG4gIGNvbnN0cnVjdG9yKCkge1xuICAgIHByb2Nlc3NfY291bnRlciA9IHByb2Nlc3NfY291bnRlciArIDE7XG4gICAgdGhpcy5pZCA9IHByb2Nlc3NfY291bnRlcjtcbiAgfVxuXG4gIHRvU3RyaW5nKCkge1xuICAgIHJldHVybiBcIlBJRCM8MC5cIiArIHRoaXMuaWQgKyBcIi4wPlwiO1xuICB9XG59XG5cbmNsYXNzIEludGVnZXIge31cbmNsYXNzIEZsb2F0IHt9XG5cbmZ1bmN0aW9uIExpc3QkMSguLi5hcmdzKSB7XG4gIHJldHVybiBPYmplY3QuZnJlZXplKGFyZ3MpO1xufVxuXG5jbGFzcyBQcm9jZXNzU3lzdGVtIHtcblxuICBjb25zdHJ1Y3RvcigpIHtcbiAgICB0aGlzLnBpZHMgPSBuZXcgTWFwKCk7XG4gICAgdGhpcy5tYWlsYm94ZXMgPSBuZXcgTWFwKCk7XG4gICAgdGhpcy5uYW1lcyA9IG5ldyBNYXAoKTtcbiAgICB0aGlzLmxpbmtzID0gbmV3IE1hcCgpO1xuXG4gICAgdGhpcy5jdXJyZW50X3Byb2Nlc3MgPSBudWxsO1xuICAgIHRoaXMuc3VzcGVuZGVkID0gbmV3IE1hcCgpO1xuXG4gICAgdGhpcy5tYWluX3Byb2Nlc3NfcGlkID0gdGhpcy5zcGF3bigpO1xuICAgIHRoaXMuc2V0X2N1cnJlbnQodGhpcy5tYWluX3Byb2Nlc3NfcGlkKTtcbiAgfVxuXG4gIHNwYXduKCkge1xuICAgIHJldHVybiB0aGlzLmFkZF9wcm9jKGZhbHNlKS5waWQ7XG4gIH1cblxuICBzcGF3bl9saW5rKCkge1xuICAgIHJldHVybiB0aGlzLmFkZF9wcm9jKHRydWUpLnBpZDtcbiAgfVxuXG4gIGxpbmsocGlkKSB7XG4gICAgdGhpcy5saW5rcy5nZXQodGhpcy5waWQoKSkuYWRkKHBpZCk7XG4gICAgdGhpcy5saW5rcy5nZXQocGlkKS5hZGQodGhpcy5waWQoKSk7XG4gIH1cblxuICB1bmxpbmsocGlkKSB7XG4gICAgdGhpcy5saW5rcy5nZXQodGhpcy5waWQoKSkuZGVsZXRlKHBpZCk7XG4gICAgdGhpcy5saW5rcy5nZXQocGlkKS5kZWxldGUodGhpcy5waWQoKSk7XG4gIH1cblxuICBzZXRfY3VycmVudChpZCkge1xuICAgIGxldCBwaWQgPSB0aGlzLnBpZG9mKGlkKTtcbiAgICBpZiAocGlkICE9PSBudWxsKSB7XG4gICAgICB0aGlzLmN1cnJlbnRfcHJvY2VzcyA9IHRoaXMucGlkcy5nZXQocGlkKTtcbiAgICAgIHRoaXMuY3VycmVudF9wcm9jZXNzLnN0YXR1cyA9IFN0YXRlcy5SVU5OSU5HO1xuICAgIH1cbiAgfVxuXG4gIGFkZF9wcm9jKGxpbmtlZCkge1xuICAgIGxldCBuZXdwaWQgPSBuZXcgUElEKCk7XG4gICAgbGV0IG1haWxib3ggPSBuZXcgTWFpbGJveCgpO1xuICAgIGxldCBuZXdwcm9jID0gbmV3IFByb2Nlc3MobmV3cGlkLCBtYWlsYm94KTtcblxuICAgIHRoaXMucGlkcy5zZXQobmV3cGlkLCBuZXdwcm9jKTtcbiAgICB0aGlzLm1haWxib3hlcy5zZXQobmV3cGlkLCBtYWlsYm94KTtcbiAgICB0aGlzLmxpbmtzLnNldChuZXdwaWQsIG5ldyBTZXQoKSk7XG5cbiAgICBpZiAobGlua2VkKSB7XG4gICAgICB0aGlzLmxpbmsobmV3cGlkKTtcbiAgICB9XG5cbiAgICByZXR1cm4gbmV3cHJvYztcbiAgfVxuXG4gIHJlbW92ZV9wcm9jKHBpZCkge1xuICAgIHRoaXMucGlkcy5kZWxldGUocGlkKTtcbiAgICB0aGlzLnVucmVnaXN0ZXIocGlkKTtcblxuICAgIGlmICh0aGlzLmxpbmtzLmhhcyhwaWQpKSB7XG4gICAgICBmb3IgKGxldCBsaW5rcGlkIG9mIHRoaXMubGlua3MuZ2V0KHBpZCkpIHtcbiAgICAgICAgdGhpcy5saW5rcy5nZXQobGlua3BpZCkuZGVsZXRlKHBpZCk7XG4gICAgICB9XG5cbiAgICAgIHRoaXMubGlua3MuZGVsZXRlKHBpZCk7XG4gICAgfVxuICB9XG5cbiAgZXhpdChpZCkge1xuICAgIGxldCBwaWQgPSB0aGlzLnBpZG9mKGlkKTtcbiAgICB0aGlzLnJlbW92ZV9wcm9jKGlkKTtcbiAgfVxuXG4gIHJlZ2lzdGVyKG5hbWUsIHBpZCkge1xuICAgIGlmICghdGhpcy5uYW1lcy5oYXMobmFtZSkpIHtcbiAgICAgIHRoaXMubmFtZXMuc2V0KG5hbWUsIHBpZCk7XG4gICAgICByZXR1cm4gbmFtZTtcbiAgICB9IGVsc2Uge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKFwiTmFtZSBpcyBhbHJlYWR5IHJlZ2lzdGVyZWQgdG8gYW5vdGhlciBwcm9jZXNzXCIpO1xuICAgIH1cbiAgfVxuXG4gIHJlZ2lzdGVyZWQobmFtZSkge1xuICAgIHJldHVybiB0aGlzLm5hbWVzLmhhcyhuYW1lKSA/IHRoaXMubmFtZXMuZ2V0KG5hbWUpIDogbnVsbDtcbiAgfVxuXG4gIHVucmVnaXN0ZXIocGlkKSB7XG4gICAgZm9yIChsZXQgbmFtZSBvZiB0aGlzLm5hbWVzLmtleXMoKSkge1xuICAgICAgaWYgKHRoaXMubmFtZXMuaGFzKG5hbWUpICYmIHRoaXMubmFtZXMuZ2V0KG5hbWUpID09PSBwaWQpIHtcbiAgICAgICAgdGhpcy5uYW1lcy5kZWxldGUobmFtZSk7XG4gICAgICB9XG4gICAgfVxuICB9XG5cbiAgcGlkKCkge1xuICAgIHJldHVybiB0aGlzLmN1cnJlbnRfcHJvY2Vzcy5waWQ7XG4gIH1cblxuICBwaWRvZihpZCkge1xuICAgIGlmIChpZCBpbnN0YW5jZW9mIFBJRCkge1xuICAgICAgcmV0dXJuIHRoaXMucGlkcy5oYXMoaWQpID8gaWQgOiBudWxsO1xuICAgIH0gZWxzZSBpZiAoaWQgaW5zdGFuY2VvZiBQcm9jZXNzKSB7XG4gICAgICByZXR1cm4gaWQucGlkO1xuICAgIH0gZWxzZSB7XG4gICAgICBsZXQgcGlkID0gdGhpcy5yZWdpc3RlcmVkKGlkKTtcbiAgICAgIGlmIChwaWQgPT09IG51bGwpIHRocm93IFwiUHJvY2VzcyBuYW1lIG5vdCByZWdpc3RlcmVkOiBcIiArIGlkICsgXCIgKFwiICsgdHlwZW9mIGlkICsgXCIpXCI7XG4gICAgICByZXR1cm4gcGlkO1xuICAgIH1cbiAgfVxuXG4gIHB1dChpZCwga2V5LCB2YWx1ZSkge1xuICAgIGxldCBwaWQgPSB0aGlzLnBpZG9mKGlkKTtcbiAgICBsZXQgcHJvY2VzcyA9IHRoaXMucGlkcy5nZXQocGlkKTtcbiAgICBwcm9jZXNzLmRpY3Rba2V5XSA9IHZhbHVlO1xuICB9XG5cbiAgZ2V0KGlkLCBrZXkpIHtcbiAgICBsZXQgcGlkID0gdGhpcy5waWRvZihpZCk7XG4gICAgbGV0IHByb2Nlc3MgPSB0aGlzLnBpZHMuZ2V0KHBpZCk7XG5cbiAgICBpZiAoa2V5ICE9IG51bGwpIHtcbiAgICAgIHJldHVybiBwcm9jZXNzLmRpY3Rba2V5XTtcbiAgICB9IGVsc2Uge1xuICAgICAgcmV0dXJuIHByb2Nlc3MuZGljdDtcbiAgICB9XG4gIH1cblxuICBnZXRfa2V5cyhpZCkge1xuICAgIGxldCBwaWQgPSB0aGlzLnBpZG9mKGlkKTtcbiAgICBsZXQgcHJvY2VzcyA9IHRoaXMucGlkcy5nZXQocGlkKTtcblxuICAgIHJldHVybiBPYmplY3Qua2V5cyhwcm9jZXNzLmRpY3QpO1xuICB9XG5cbiAgZXJhc2UoaWQsIGtleSkge1xuICAgIGxldCBwaWQgPSB0aGlzLnBpZG9mKGlkKTtcbiAgICBsZXQgcHJvY2VzcyA9IHRoaXMucGlkcy5nZXQocGlkKTtcblxuICAgIGlmIChrZXkgIT0gbnVsbCkge1xuICAgICAgZGVsZXRlIHByb2Nlc3MuZGljdFtrZXldO1xuICAgIH0gZWxzZSB7XG4gICAgICBwcm9jZXNzLmRpY3QgPSB7fTtcbiAgICB9XG4gIH1cbn1cblxuY2xhc3MgQml0U3RyaW5nIHtcbiAgY29uc3RydWN0b3IoLi4uYXJncykge1xuICAgIHRoaXMucmF3X3ZhbHVlID0gZnVuY3Rpb24gKCkge1xuICAgICAgcmV0dXJuIE9iamVjdC5mcmVlemUoYXJncyk7XG4gICAgfTtcblxuICAgIHRoaXMudmFsdWUgPSBPYmplY3QuZnJlZXplKHRoaXMucHJvY2VzcyhhcmdzKSk7XG4gIH1cblxuICBnZXQoaW5kZXgpIHtcbiAgICByZXR1cm4gdGhpcy52YWx1ZVtpbmRleF07XG4gIH1cblxuICBjb3VudCgpIHtcbiAgICByZXR1cm4gdGhpcy52YWx1ZS5sZW5ndGg7XG4gIH1cblxuICBbU3ltYm9sLml0ZXJhdG9yXSgpIHtcbiAgICByZXR1cm4gdGhpcy52YWx1ZVtTeW1ib2wuaXRlcmF0b3JdKCk7XG4gIH1cblxuICB0b1N0cmluZygpIHtcbiAgICB2YXIgaSxcbiAgICAgICAgcyA9IFwiXCI7XG4gICAgZm9yIChpID0gMDsgaSA8IHRoaXMuY291bnQoKTsgaSsrKSB7XG4gICAgICBpZiAocyAhPT0gXCJcIikge1xuICAgICAgICBzICs9IFwiLCBcIjtcbiAgICAgIH1cbiAgICAgIHMgKz0gdGhpc1tpXS50b1N0cmluZygpO1xuICAgIH1cblxuICAgIHJldHVybiBcIjw8XCIgKyBzICsgXCI+PlwiO1xuICB9XG5cbiAgcHJvY2VzcygpIHtcbiAgICBsZXQgcHJvY2Vzc2VkX3ZhbHVlcyA9IFtdO1xuXG4gICAgdmFyIGk7XG4gICAgZm9yIChpID0gMDsgaSA8IHRoaXMucmF3X3ZhbHVlKCkubGVuZ3RoOyBpKyspIHtcbiAgICAgIGxldCBwcm9jZXNzZWRfdmFsdWUgPSB0aGlzW1wicHJvY2Vzc19cIiArIHRoaXMucmF3X3ZhbHVlKClbaV0udHlwZV0odGhpcy5yYXdfdmFsdWUoKVtpXSk7XG5cbiAgICAgIGZvciAobGV0IGF0dHIgb2YgdGhpcy5yYXdfdmFsdWUoKVtpXS5hdHRyaWJ1dGVzKSB7XG4gICAgICAgIHByb2Nlc3NlZF92YWx1ZSA9IHRoaXNbXCJwcm9jZXNzX1wiICsgYXR0cl0ocHJvY2Vzc2VkX3ZhbHVlKTtcbiAgICAgIH1cblxuICAgICAgcHJvY2Vzc2VkX3ZhbHVlcyA9IHByb2Nlc3NlZF92YWx1ZXMuY29uY2F0KHByb2Nlc3NlZF92YWx1ZSk7XG4gICAgfVxuXG4gICAgcmV0dXJuIHByb2Nlc3NlZF92YWx1ZXM7XG4gIH1cblxuICBwcm9jZXNzX2ludGVnZXIodmFsdWUpIHtcbiAgICByZXR1cm4gdmFsdWUudmFsdWU7XG4gIH1cblxuICBwcm9jZXNzX2Zsb2F0KHZhbHVlKSB7XG4gICAgaWYgKHZhbHVlLnNpemUgPT09IDY0KSB7XG4gICAgICByZXR1cm4gQml0U3RyaW5nLmZsb2F0NjRUb0J5dGVzKHZhbHVlLnZhbHVlKTtcbiAgICB9IGVsc2UgaWYgKHZhbHVlLnNpemUgPT09IDMyKSB7XG4gICAgICByZXR1cm4gQml0U3RyaW5nLmZsb2F0MzJUb0J5dGVzKHZhbHVlLnZhbHVlKTtcbiAgICB9XG5cbiAgICB0aHJvdyBuZXcgRXJyb3IoXCJJbnZhbGlkIHNpemUgZm9yIGZsb2F0XCIpO1xuICB9XG5cbiAgcHJvY2Vzc19iaXRzdHJpbmcodmFsdWUpIHtcbiAgICByZXR1cm4gdmFsdWUudmFsdWUudmFsdWU7XG4gIH1cblxuICBwcm9jZXNzX2JpbmFyeSh2YWx1ZSkge1xuICAgIHJldHVybiBCaXRTdHJpbmcudG9VVEY4QXJyYXkodmFsdWUudmFsdWUpO1xuICB9XG5cbiAgcHJvY2Vzc191dGY4KHZhbHVlKSB7XG4gICAgcmV0dXJuIEJpdFN0cmluZy50b1VURjhBcnJheSh2YWx1ZS52YWx1ZSk7XG4gIH1cblxuICBwcm9jZXNzX3V0ZjE2KHZhbHVlKSB7XG4gICAgcmV0dXJuIEJpdFN0cmluZy50b1VURjE2QXJyYXkodmFsdWUudmFsdWUpO1xuICB9XG5cbiAgcHJvY2Vzc191dGYzMih2YWx1ZSkge1xuICAgIHJldHVybiBCaXRTdHJpbmcudG9VVEYzMkFycmF5KHZhbHVlLnZhbHVlKTtcbiAgfVxuXG4gIHByb2Nlc3Nfc2lnbmVkKHZhbHVlKSB7XG4gICAgcmV0dXJuIG5ldyBVaW50OEFycmF5KFt2YWx1ZV0pWzBdO1xuICB9XG5cbiAgcHJvY2Vzc191bnNpZ25lZCh2YWx1ZSkge1xuICAgIHJldHVybiB2YWx1ZTtcbiAgfVxuXG4gIHByb2Nlc3NfbmF0aXZlKHZhbHVlKSB7XG4gICAgcmV0dXJuIHZhbHVlO1xuICB9XG5cbiAgcHJvY2Vzc19iaWcodmFsdWUpIHtcbiAgICByZXR1cm4gdmFsdWU7XG4gIH1cblxuICBwcm9jZXNzX2xpdHRsZSh2YWx1ZSkge1xuICAgIHJldHVybiB2YWx1ZS5yZXZlcnNlKCk7XG4gIH1cblxuICBwcm9jZXNzX3NpemUodmFsdWUpIHtcbiAgICByZXR1cm4gdmFsdWU7XG4gIH1cblxuICBwcm9jZXNzX3VuaXQodmFsdWUpIHtcbiAgICByZXR1cm4gdmFsdWU7XG4gIH1cblxuICBzdGF0aWMgaW50ZWdlcih2YWx1ZSkge1xuICAgIHJldHVybiBCaXRTdHJpbmcud3JhcCh2YWx1ZSwgeyBcInR5cGVcIjogXCJpbnRlZ2VyXCIsIFwidW5pdFwiOiAxLCBcInNpemVcIjogOCB9KTtcbiAgfVxuXG4gIHN0YXRpYyBmbG9hdCh2YWx1ZSkge1xuICAgIHJldHVybiBCaXRTdHJpbmcud3JhcCh2YWx1ZSwgeyBcInR5cGVcIjogXCJmbG9hdFwiLCBcInVuaXRcIjogMSwgXCJzaXplXCI6IDY0IH0pO1xuICB9XG5cbiAgc3RhdGljIGJpdHN0cmluZyh2YWx1ZSkge1xuICAgIHJldHVybiBCaXRTdHJpbmcud3JhcCh2YWx1ZSwgeyBcInR5cGVcIjogXCJiaXRzdHJpbmdcIiwgXCJ1bml0XCI6IDEsIFwic2l6ZVwiOiB2YWx1ZS5sZW5ndGggfSk7XG4gIH1cblxuICBzdGF0aWMgYml0cyh2YWx1ZSkge1xuICAgIHJldHVybiBCaXRTdHJpbmcuYml0c3RyaW5nKHZhbHVlKTtcbiAgfVxuXG4gIHN0YXRpYyBiaW5hcnkodmFsdWUpIHtcbiAgICByZXR1cm4gQml0U3RyaW5nLndyYXAodmFsdWUsIHsgXCJ0eXBlXCI6IFwiYmluYXJ5XCIsIFwidW5pdFwiOiA4LCBcInNpemVcIjogdmFsdWUubGVuZ3RoIH0pO1xuICB9XG5cbiAgc3RhdGljIGJ5dGVzKHZhbHVlKSB7XG4gICAgcmV0dXJuIEJpdFN0cmluZy5iaW5hcnkodmFsdWUpO1xuICB9XG5cbiAgc3RhdGljIHV0ZjgodmFsdWUpIHtcbiAgICByZXR1cm4gQml0U3RyaW5nLndyYXAodmFsdWUsIHsgXCJ0eXBlXCI6IFwidXRmOFwiIH0pO1xuICB9XG5cbiAgc3RhdGljIHV0ZjE2KHZhbHVlKSB7XG4gICAgcmV0dXJuIEJpdFN0cmluZy53cmFwKHZhbHVlLCB7IFwidHlwZVwiOiBcInV0ZjE2XCIgfSk7XG4gIH1cblxuICBzdGF0aWMgdXRmMzIodmFsdWUpIHtcbiAgICByZXR1cm4gQml0U3RyaW5nLndyYXAodmFsdWUsIHsgXCJ0eXBlXCI6IFwidXRmMzJcIiB9KTtcbiAgfVxuXG4gIHN0YXRpYyBzaWduZWQodmFsdWUpIHtcbiAgICByZXR1cm4gQml0U3RyaW5nLndyYXAodmFsdWUsIHt9LCBcInNpZ25lZFwiKTtcbiAgfVxuXG4gIHN0YXRpYyB1bnNpZ25lZCh2YWx1ZSkge1xuICAgIHJldHVybiBCaXRTdHJpbmcud3JhcCh2YWx1ZSwge30sIFwidW5zaWduZWRcIik7XG4gIH1cblxuICBzdGF0aWMgbmF0aXZlKHZhbHVlKSB7XG4gICAgcmV0dXJuIEJpdFN0cmluZy53cmFwKHZhbHVlLCB7fSwgXCJuYXRpdmVcIik7XG4gIH1cblxuICBzdGF0aWMgYmlnKHZhbHVlKSB7XG4gICAgcmV0dXJuIEJpdFN0cmluZy53cmFwKHZhbHVlLCB7fSwgXCJiaWdcIik7XG4gIH1cblxuICBzdGF0aWMgbGl0dGxlKHZhbHVlKSB7XG4gICAgcmV0dXJuIEJpdFN0cmluZy53cmFwKHZhbHVlLCB7fSwgXCJsaXR0bGVcIik7XG4gIH1cblxuICBzdGF0aWMgc2l6ZSh2YWx1ZSwgY291bnQpIHtcbiAgICByZXR1cm4gQml0U3RyaW5nLndyYXAodmFsdWUsIHsgXCJzaXplXCI6IGNvdW50IH0pO1xuICB9XG5cbiAgc3RhdGljIHVuaXQodmFsdWUsIGNvdW50KSB7XG4gICAgcmV0dXJuIEJpdFN0cmluZy53cmFwKHZhbHVlLCB7IFwidW5pdFwiOiBjb3VudCB9KTtcbiAgfVxuXG4gIHN0YXRpYyB3cmFwKHZhbHVlLCBvcHQsIG5ld19hdHRyaWJ1dGUgPSBudWxsKSB7XG4gICAgbGV0IHRoZV92YWx1ZSA9IHZhbHVlO1xuXG4gICAgaWYgKCEodmFsdWUgaW5zdGFuY2VvZiBPYmplY3QpKSB7XG4gICAgICB0aGVfdmFsdWUgPSB7IFwidmFsdWVcIjogdmFsdWUsIFwiYXR0cmlidXRlc1wiOiBbXSB9O1xuICAgIH1cblxuICAgIHRoZV92YWx1ZSA9IE9iamVjdC5hc3NpZ24odGhlX3ZhbHVlLCBvcHQpO1xuXG4gICAgaWYgKG5ld19hdHRyaWJ1dGUpIHtcbiAgICAgIHRoZV92YWx1ZS5hdHRyaWJ1dGVzLnB1c2gobmV3X2F0dHJpYnV0ZSk7XG4gICAgfVxuXG4gICAgcmV0dXJuIHRoZV92YWx1ZTtcbiAgfVxuXG4gIHN0YXRpYyB0b1VURjhBcnJheShzdHIpIHtcbiAgICB2YXIgdXRmOCA9IFtdO1xuICAgIGZvciAodmFyIGkgPSAwOyBpIDwgc3RyLmxlbmd0aDsgaSsrKSB7XG4gICAgICB2YXIgY2hhcmNvZGUgPSBzdHIuY2hhckNvZGVBdChpKTtcbiAgICAgIGlmIChjaGFyY29kZSA8IDEyOCkge1xuICAgICAgICB1dGY4LnB1c2goY2hhcmNvZGUpO1xuICAgICAgfSBlbHNlIGlmIChjaGFyY29kZSA8IDIwNDgpIHtcbiAgICAgICAgdXRmOC5wdXNoKDE5MiB8IGNoYXJjb2RlID4+IDYsIDEyOCB8IGNoYXJjb2RlICYgNjMpO1xuICAgICAgfSBlbHNlIGlmIChjaGFyY29kZSA8IDU1Mjk2IHx8IGNoYXJjb2RlID49IDU3MzQ0KSB7XG4gICAgICAgIHV0ZjgucHVzaCgyMjQgfCBjaGFyY29kZSA+PiAxMiwgMTI4IHwgY2hhcmNvZGUgPj4gNiAmIDYzLCAxMjggfCBjaGFyY29kZSAmIDYzKTtcbiAgICAgIH1cbiAgICAgIC8vIHN1cnJvZ2F0ZSBwYWlyXG4gICAgICBlbHNlIHtcbiAgICAgICAgaSsrO1xuICAgICAgICAvLyBVVEYtMTYgZW5jb2RlcyAweDEwMDAwLTB4MTBGRkZGIGJ5XG4gICAgICAgIC8vIHN1YnRyYWN0aW5nIDB4MTAwMDAgYW5kIHNwbGl0dGluZyB0aGVcbiAgICAgICAgLy8gMjAgYml0cyBvZiAweDAtMHhGRkZGRiBpbnRvIHR3byBoYWx2ZXNcbiAgICAgICAgY2hhcmNvZGUgPSA2NTUzNiArICgoY2hhcmNvZGUgJiAxMDIzKSA8PCAxMCB8IHN0ci5jaGFyQ29kZUF0KGkpICYgMTAyMyk7XG4gICAgICAgIHV0ZjgucHVzaCgyNDAgfCBjaGFyY29kZSA+PiAxOCwgMTI4IHwgY2hhcmNvZGUgPj4gMTIgJiA2MywgMTI4IHwgY2hhcmNvZGUgPj4gNiAmIDYzLCAxMjggfCBjaGFyY29kZSAmIDYzKTtcbiAgICAgIH1cbiAgICB9XG4gICAgcmV0dXJuIHV0Zjg7XG4gIH1cblxuICBzdGF0aWMgdG9VVEYxNkFycmF5KHN0cikge1xuICAgIHZhciB1dGYxNiA9IFtdO1xuICAgIGZvciAodmFyIGkgPSAwOyBpIDwgc3RyLmxlbmd0aDsgaSsrKSB7XG4gICAgICB2YXIgY29kZVBvaW50ID0gc3RyLmNvZGVQb2ludEF0KGkpO1xuXG4gICAgICBpZiAoY29kZVBvaW50IDw9IDI1NSkge1xuICAgICAgICB1dGYxNi5wdXNoKDApO1xuICAgICAgICB1dGYxNi5wdXNoKGNvZGVQb2ludCk7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICB1dGYxNi5wdXNoKGNvZGVQb2ludCA+PiA4ICYgMjU1KTtcbiAgICAgICAgdXRmMTYucHVzaChjb2RlUG9pbnQgJiAyNTUpO1xuICAgICAgfVxuICAgIH1cbiAgICByZXR1cm4gdXRmMTY7XG4gIH1cblxuICBzdGF0aWMgdG9VVEYzMkFycmF5KHN0cikge1xuICAgIHZhciB1dGYzMiA9IFtdO1xuICAgIGZvciAodmFyIGkgPSAwOyBpIDwgc3RyLmxlbmd0aDsgaSsrKSB7XG4gICAgICB2YXIgY29kZVBvaW50ID0gc3RyLmNvZGVQb2ludEF0KGkpO1xuXG4gICAgICBpZiAoY29kZVBvaW50IDw9IDI1NSkge1xuICAgICAgICB1dGYzMi5wdXNoKDApO1xuICAgICAgICB1dGYzMi5wdXNoKDApO1xuICAgICAgICB1dGYzMi5wdXNoKDApO1xuICAgICAgICB1dGYzMi5wdXNoKGNvZGVQb2ludCk7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICB1dGYzMi5wdXNoKDApO1xuICAgICAgICB1dGYzMi5wdXNoKDApO1xuICAgICAgICB1dGYzMi5wdXNoKGNvZGVQb2ludCA+PiA4ICYgMjU1KTtcbiAgICAgICAgdXRmMzIucHVzaChjb2RlUG9pbnQgJiAyNTUpO1xuICAgICAgfVxuICAgIH1cbiAgICByZXR1cm4gdXRmMzI7XG4gIH1cblxuICAvL2h0dHA6Ly9zdGFja292ZXJmbG93LmNvbS9xdWVzdGlvbnMvMjAwMzQ5My9qYXZhc2NyaXB0LWZsb2F0LWZyb20tdG8tYml0c1xuICBzdGF0aWMgZmxvYXQzMlRvQnl0ZXMoZikge1xuICAgIHZhciBieXRlcyA9IFtdO1xuXG4gICAgdmFyIGJ1ZiA9IG5ldyBBcnJheUJ1ZmZlcig0KTtcbiAgICBuZXcgRmxvYXQzMkFycmF5KGJ1ZilbMF0gPSBmO1xuXG4gICAgbGV0IGludFZlcnNpb24gPSBuZXcgVWludDMyQXJyYXkoYnVmKVswXTtcblxuICAgIGJ5dGVzLnB1c2goaW50VmVyc2lvbiA+PiAyNCAmIDI1NSk7XG4gICAgYnl0ZXMucHVzaChpbnRWZXJzaW9uID4+IDE2ICYgMjU1KTtcbiAgICBieXRlcy5wdXNoKGludFZlcnNpb24gPj4gOCAmIDI1NSk7XG4gICAgYnl0ZXMucHVzaChpbnRWZXJzaW9uICYgMjU1KTtcblxuICAgIHJldHVybiBieXRlcztcbiAgfVxuXG4gIHN0YXRpYyBmbG9hdDY0VG9CeXRlcyhmKSB7XG4gICAgdmFyIGJ5dGVzID0gW107XG5cbiAgICB2YXIgYnVmID0gbmV3IEFycmF5QnVmZmVyKDgpO1xuICAgIG5ldyBGbG9hdDY0QXJyYXkoYnVmKVswXSA9IGY7XG5cbiAgICB2YXIgaW50VmVyc2lvbjEgPSBuZXcgVWludDMyQXJyYXkoYnVmKVswXTtcbiAgICB2YXIgaW50VmVyc2lvbjIgPSBuZXcgVWludDMyQXJyYXkoYnVmKVsxXTtcblxuICAgIGJ5dGVzLnB1c2goaW50VmVyc2lvbjIgPj4gMjQgJiAyNTUpO1xuICAgIGJ5dGVzLnB1c2goaW50VmVyc2lvbjIgPj4gMTYgJiAyNTUpO1xuICAgIGJ5dGVzLnB1c2goaW50VmVyc2lvbjIgPj4gOCAmIDI1NSk7XG4gICAgYnl0ZXMucHVzaChpbnRWZXJzaW9uMiAmIDI1NSk7XG5cbiAgICBieXRlcy5wdXNoKGludFZlcnNpb24xID4+IDI0ICYgMjU1KTtcbiAgICBieXRlcy5wdXNoKGludFZlcnNpb24xID4+IDE2ICYgMjU1KTtcbiAgICBieXRlcy5wdXNoKGludFZlcnNpb24xID4+IDggJiAyNTUpO1xuICAgIGJ5dGVzLnB1c2goaW50VmVyc2lvbjEgJiAyNTUpO1xuXG4gICAgcmV0dXJuIGJ5dGVzO1xuICB9XG59XG5cbi8qIEBmbG93ICovXG5cbmNsYXNzIFZhcmlhYmxlIHtcblxuICBjb25zdHJ1Y3RvcihuYW1lID0gbnVsbCkge1xuICAgIHRoaXMubmFtZSA9IG5hbWU7XG4gIH1cbn1cblxuY2xhc3MgV2lsZGNhcmQge1xuICBjb25zdHJ1Y3RvcigpIHt9XG59XG5cbmNsYXNzIFN0YXJ0c1dpdGgge1xuXG4gIGNvbnN0cnVjdG9yKHByZWZpeCkge1xuICAgIHRoaXMucHJlZml4ID0gcHJlZml4O1xuICB9XG59XG5cbmNsYXNzIENhcHR1cmUge1xuXG4gIGNvbnN0cnVjdG9yKHZhbHVlKSB7XG4gICAgdGhpcy52YWx1ZSA9IHZhbHVlO1xuICB9XG59XG5cbmNsYXNzIEhlYWRUYWlsIHtcbiAgY29uc3RydWN0b3IoKSB7fVxufVxuXG5jbGFzcyBUeXBlIHtcblxuICBjb25zdHJ1Y3Rvcih0eXBlLCBvYmpQYXR0ZXJuID0ge30pIHtcbiAgICB0aGlzLnR5cGUgPSB0eXBlO1xuICAgIHRoaXMub2JqUGF0dGVybiA9IG9ialBhdHRlcm47XG4gIH1cbn1cblxuY2xhc3MgQm91bmQge1xuXG4gIGNvbnN0cnVjdG9yKHZhbHVlKSB7XG4gICAgdGhpcy52YWx1ZSA9IHZhbHVlO1xuICB9XG59XG5cbmZ1bmN0aW9uIHZhcmlhYmxlKG5hbWUgPSBudWxsKSB7XG4gIHJldHVybiBuZXcgVmFyaWFibGUobmFtZSk7XG59XG5cbmZ1bmN0aW9uIHdpbGRjYXJkKCkge1xuICByZXR1cm4gbmV3IFdpbGRjYXJkKCk7XG59XG5cbmZ1bmN0aW9uIHN0YXJ0c1dpdGgocHJlZml4KSB7XG4gIHJldHVybiBuZXcgU3RhcnRzV2l0aChwcmVmaXgpO1xufVxuXG5mdW5jdGlvbiBjYXB0dXJlKHZhbHVlKSB7XG4gIHJldHVybiBuZXcgQ2FwdHVyZSh2YWx1ZSk7XG59XG5cbmZ1bmN0aW9uIGhlYWRUYWlsKCkge1xuICByZXR1cm4gbmV3IEhlYWRUYWlsKCk7XG59XG5cbmZ1bmN0aW9uIHR5cGUodHlwZSwgb2JqUGF0dGVybiA9IHt9KSB7XG4gIHJldHVybiBuZXcgVHlwZSh0eXBlLCBvYmpQYXR0ZXJuKTtcbn1cblxuZnVuY3Rpb24gYm91bmQodmFsdWUpIHtcbiAgcmV0dXJuIG5ldyBCb3VuZCh2YWx1ZSk7XG59XG5cbmZ1bmN0aW9uIGlzX251bWJlciQyKHZhbHVlKSB7XG4gIHJldHVybiB0eXBlb2YgdmFsdWUgPT09ICdudW1iZXInO1xufVxuXG5mdW5jdGlvbiBpc19zdHJpbmcodmFsdWUpIHtcbiAgcmV0dXJuIHR5cGVvZiB2YWx1ZSA9PT0gJ3N0cmluZyc7XG59XG5cbmZ1bmN0aW9uIGlzX2Jvb2xlYW4kMih2YWx1ZSkge1xuICByZXR1cm4gdHlwZW9mIHZhbHVlID09PSAnYm9vbGVhbic7XG59XG5cbmZ1bmN0aW9uIGlzX3N5bWJvbCh2YWx1ZSkge1xuICByZXR1cm4gdHlwZW9mIHZhbHVlID09PSAnc3ltYm9sJztcbn1cblxuZnVuY3Rpb24gaXNfbnVsbCh2YWx1ZSkge1xuICByZXR1cm4gdmFsdWUgPT09IG51bGw7XG59XG5cbmZ1bmN0aW9uIGlzX3VuZGVmaW5lZCh2YWx1ZSkge1xuICByZXR1cm4gdHlwZW9mIHZhbHVlID09PSAndW5kZWZpbmVkJztcbn1cblxuZnVuY3Rpb24gaXNfZnVuY3Rpb24kMih2YWx1ZSkge1xuICByZXR1cm4gT2JqZWN0LnByb3RvdHlwZS50b1N0cmluZy5jYWxsKHZhbHVlKSA9PSAnW29iamVjdCBGdW5jdGlvbl0nO1xufVxuXG5mdW5jdGlvbiBpc192YXJpYWJsZSh2YWx1ZSkge1xuICByZXR1cm4gdmFsdWUgaW5zdGFuY2VvZiBWYXJpYWJsZTtcbn1cblxuZnVuY3Rpb24gaXNfd2lsZGNhcmQodmFsdWUpIHtcbiAgcmV0dXJuIHZhbHVlIGluc3RhbmNlb2YgV2lsZGNhcmQ7XG59XG5cbmZ1bmN0aW9uIGlzX2hlYWRUYWlsKHZhbHVlKSB7XG4gIHJldHVybiB2YWx1ZSBpbnN0YW5jZW9mIEhlYWRUYWlsO1xufVxuXG5mdW5jdGlvbiBpc19jYXB0dXJlKHZhbHVlKSB7XG4gIHJldHVybiB2YWx1ZSBpbnN0YW5jZW9mIENhcHR1cmU7XG59XG5cbmZ1bmN0aW9uIGlzX3R5cGUodmFsdWUpIHtcbiAgcmV0dXJuIHZhbHVlIGluc3RhbmNlb2YgVHlwZTtcbn1cblxuZnVuY3Rpb24gaXNfc3RhcnRzV2l0aCh2YWx1ZSkge1xuICByZXR1cm4gdmFsdWUgaW5zdGFuY2VvZiBTdGFydHNXaXRoO1xufVxuXG5mdW5jdGlvbiBpc19ib3VuZCh2YWx1ZSkge1xuICByZXR1cm4gdmFsdWUgaW5zdGFuY2VvZiBCb3VuZDtcbn1cblxuZnVuY3Rpb24gaXNfb2JqZWN0KHZhbHVlKSB7XG4gIHJldHVybiB0eXBlb2YgdmFsdWUgPT09ICdvYmplY3QnO1xufVxuXG5mdW5jdGlvbiBpc19hcnJheSh2YWx1ZSkge1xuICByZXR1cm4gQXJyYXkuaXNBcnJheSh2YWx1ZSk7XG59XG5cbnZhciBDaGVja3MgPSB7XG4gIGlzX251bWJlcjogaXNfbnVtYmVyJDIsXG4gIGlzX3N0cmluZyxcbiAgaXNfYm9vbGVhbjogaXNfYm9vbGVhbiQyLFxuICBpc19zeW1ib2wsXG4gIGlzX251bGwsXG4gIGlzX3VuZGVmaW5lZCxcbiAgaXNfZnVuY3Rpb246IGlzX2Z1bmN0aW9uJDIsXG4gIGlzX3ZhcmlhYmxlLFxuICBpc193aWxkY2FyZCxcbiAgaXNfaGVhZFRhaWwsXG4gIGlzX2NhcHR1cmUsXG4gIGlzX3R5cGUsXG4gIGlzX3N0YXJ0c1dpdGgsXG4gIGlzX2JvdW5kLFxuICBpc19vYmplY3QsXG4gIGlzX2FycmF5XG59O1xuXG5mdW5jdGlvbiByZXNvbHZlU3ltYm9sKHBhdHRlcm4pIHtcbiAgcmV0dXJuIGZ1bmN0aW9uICh2YWx1ZSkge1xuICAgIHJldHVybiBDaGVja3MuaXNfc3ltYm9sKHZhbHVlKSAmJiB2YWx1ZSA9PT0gcGF0dGVybjtcbiAgfTtcbn1cblxuZnVuY3Rpb24gcmVzb2x2ZVN0cmluZyhwYXR0ZXJuKSB7XG4gIHJldHVybiBmdW5jdGlvbiAodmFsdWUpIHtcbiAgICByZXR1cm4gQ2hlY2tzLmlzX3N0cmluZyh2YWx1ZSkgJiYgdmFsdWUgPT09IHBhdHRlcm47XG4gIH07XG59XG5cbmZ1bmN0aW9uIHJlc29sdmVOdW1iZXIocGF0dGVybikge1xuICByZXR1cm4gZnVuY3Rpb24gKHZhbHVlKSB7XG4gICAgcmV0dXJuIENoZWNrcy5pc19udW1iZXIodmFsdWUpICYmIHZhbHVlID09PSBwYXR0ZXJuO1xuICB9O1xufVxuXG5mdW5jdGlvbiByZXNvbHZlQm9vbGVhbihwYXR0ZXJuKSB7XG4gIHJldHVybiBmdW5jdGlvbiAodmFsdWUpIHtcbiAgICByZXR1cm4gQ2hlY2tzLmlzX2Jvb2xlYW4odmFsdWUpICYmIHZhbHVlID09PSBwYXR0ZXJuO1xuICB9O1xufVxuXG5mdW5jdGlvbiByZXNvbHZlRnVuY3Rpb24ocGF0dGVybikge1xuICByZXR1cm4gZnVuY3Rpb24gKHZhbHVlKSB7XG4gICAgcmV0dXJuIENoZWNrcy5pc19mdW5jdGlvbih2YWx1ZSkgJiYgdmFsdWUgPT09IHBhdHRlcm47XG4gIH07XG59XG5cbmZ1bmN0aW9uIHJlc29sdmVOdWxsKHBhdHRlcm4pIHtcbiAgcmV0dXJuIGZ1bmN0aW9uICh2YWx1ZSkge1xuICAgIHJldHVybiBDaGVja3MuaXNfbnVsbCh2YWx1ZSk7XG4gIH07XG59XG5cbmZ1bmN0aW9uIHJlc29sdmVCb3VuZChwYXR0ZXJuKSB7XG4gIHJldHVybiBmdW5jdGlvbiAodmFsdWUsIGFyZ3MpIHtcbiAgICBpZiAodHlwZW9mIHZhbHVlID09PSB0eXBlb2YgcGF0dGVybi52YWx1ZSAmJiB2YWx1ZSA9PT0gcGF0dGVybi52YWx1ZSkge1xuICAgICAgYXJncy5wdXNoKHZhbHVlKTtcbiAgICAgIHJldHVybiB0cnVlO1xuICAgIH1cblxuICAgIHJldHVybiBmYWxzZTtcbiAgfTtcbn1cblxuZnVuY3Rpb24gcmVzb2x2ZVdpbGRjYXJkKCkge1xuICByZXR1cm4gZnVuY3Rpb24gKCkge1xuICAgIHJldHVybiB0cnVlO1xuICB9O1xufVxuXG5mdW5jdGlvbiByZXNvbHZlVmFyaWFibGUoKSB7XG4gIHJldHVybiBmdW5jdGlvbiAodmFsdWUsIGFyZ3MpIHtcbiAgICBhcmdzLnB1c2godmFsdWUpO1xuICAgIHJldHVybiB0cnVlO1xuICB9O1xufVxuXG5mdW5jdGlvbiByZXNvbHZlSGVhZFRhaWwoKSB7XG4gIHJldHVybiBmdW5jdGlvbiAodmFsdWUsIGFyZ3MpIHtcbiAgICBpZiAoIUNoZWNrcy5pc19hcnJheSh2YWx1ZSkgfHwgdmFsdWUubGVuZ3RoIDwgMikge1xuICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH1cblxuICAgIGNvbnN0IGhlYWQgPSB2YWx1ZVswXTtcbiAgICBjb25zdCB0YWlsID0gdmFsdWUuc2xpY2UoMSk7XG5cbiAgICBhcmdzLnB1c2goaGVhZCk7XG4gICAgYXJncy5wdXNoKHRhaWwpO1xuXG4gICAgcmV0dXJuIHRydWU7XG4gIH07XG59XG5cbmZ1bmN0aW9uIHJlc29sdmVDYXB0dXJlKHBhdHRlcm4pIHtcbiAgY29uc3QgbWF0Y2hlcyA9IGJ1aWxkTWF0Y2gocGF0dGVybi52YWx1ZSk7XG5cbiAgcmV0dXJuIGZ1bmN0aW9uICh2YWx1ZSwgYXJncykge1xuICAgIGlmIChtYXRjaGVzKHZhbHVlLCBhcmdzKSkge1xuICAgICAgYXJncy5wdXNoKHZhbHVlKTtcbiAgICAgIHJldHVybiB0cnVlO1xuICAgIH1cblxuICAgIHJldHVybiBmYWxzZTtcbiAgfTtcbn1cblxuZnVuY3Rpb24gcmVzb2x2ZVN0YXJ0c1dpdGgocGF0dGVybikge1xuICBjb25zdCBwcmVmaXggPSBwYXR0ZXJuLnByZWZpeDtcblxuICByZXR1cm4gZnVuY3Rpb24gKHZhbHVlLCBhcmdzKSB7XG4gICAgaWYgKENoZWNrcy5pc19zdHJpbmcodmFsdWUpICYmIHZhbHVlLnN0YXJ0c1dpdGgocHJlZml4KSkge1xuICAgICAgYXJncy5wdXNoKHZhbHVlLnN1YnN0cmluZyhwcmVmaXgubGVuZ3RoKSk7XG4gICAgICByZXR1cm4gdHJ1ZTtcbiAgICB9XG5cbiAgICByZXR1cm4gZmFsc2U7XG4gIH07XG59XG5cbmZ1bmN0aW9uIHJlc29sdmVUeXBlKHBhdHRlcm4pIHtcbiAgcmV0dXJuIGZ1bmN0aW9uICh2YWx1ZSwgYXJncykge1xuICAgIGlmICh2YWx1ZSBpbnN0YW5jZW9mIHBhdHRlcm4udHlwZSkge1xuICAgICAgY29uc3QgbWF0Y2hlcyA9IGJ1aWxkTWF0Y2gocGF0dGVybi5vYmpQYXR0ZXJuKTtcbiAgICAgIHJldHVybiBtYXRjaGVzKHZhbHVlLCBhcmdzKSAmJiBhcmdzLnB1c2godmFsdWUpID4gMDtcbiAgICB9XG5cbiAgICByZXR1cm4gZmFsc2U7XG4gIH07XG59XG5cbmZ1bmN0aW9uIHJlc29sdmVBcnJheShwYXR0ZXJuKSB7XG4gIGNvbnN0IG1hdGNoZXMgPSBwYXR0ZXJuLm1hcCh4ID0+IGJ1aWxkTWF0Y2goeCkpO1xuXG4gIHJldHVybiBmdW5jdGlvbiAodmFsdWUsIGFyZ3MpIHtcbiAgICBpZiAoIUNoZWNrcy5pc19hcnJheSh2YWx1ZSkgfHwgdmFsdWUubGVuZ3RoICE9IHBhdHRlcm4ubGVuZ3RoKSB7XG4gICAgICByZXR1cm4gZmFsc2U7XG4gICAgfVxuXG4gICAgcmV0dXJuIHZhbHVlLmV2ZXJ5KGZ1bmN0aW9uICh2LCBpKSB7XG4gICAgICByZXR1cm4gbWF0Y2hlc1tpXSh2YWx1ZVtpXSwgYXJncyk7XG4gICAgfSk7XG4gIH07XG59XG5cbmZ1bmN0aW9uIHJlc29sdmVPYmplY3QocGF0dGVybikge1xuICBsZXQgbWF0Y2hlcyA9IHt9O1xuXG4gIGZvciAobGV0IGtleSBvZiBPYmplY3Qua2V5cyhwYXR0ZXJuKS5jb25jYXQoT2JqZWN0LmdldE93blByb3BlcnR5U3ltYm9scyhwYXR0ZXJuKSkpIHtcbiAgICBtYXRjaGVzW2tleV0gPSBidWlsZE1hdGNoKHBhdHRlcm5ba2V5XSk7XG4gIH1cblxuICByZXR1cm4gZnVuY3Rpb24gKHZhbHVlLCBhcmdzKSB7XG4gICAgaWYgKCFDaGVja3MuaXNfb2JqZWN0KHZhbHVlKSB8fCBwYXR0ZXJuLmxlbmd0aCA+IHZhbHVlLmxlbmd0aCkge1xuICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH1cblxuICAgIGZvciAobGV0IGtleSBvZiBPYmplY3Qua2V5cyhwYXR0ZXJuKS5jb25jYXQoT2JqZWN0LmdldE93blByb3BlcnR5U3ltYm9scyhwYXR0ZXJuKSkpIHtcbiAgICAgIGlmICghKGtleSBpbiB2YWx1ZSkgfHwgIW1hdGNoZXNba2V5XSh2YWx1ZVtrZXldLCBhcmdzKSkge1xuICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICB9XG4gICAgfVxuXG4gICAgcmV0dXJuIHRydWU7XG4gIH07XG59XG5cbmZ1bmN0aW9uIHJlc29sdmVOb01hdGNoKCkge1xuICByZXR1cm4gZnVuY3Rpb24gKCkge1xuICAgIHJldHVybiBmYWxzZTtcbiAgfTtcbn1cblxudmFyIFJlc29sdmVycyA9IHtcbiAgcmVzb2x2ZUJvdW5kLFxuICByZXNvbHZlV2lsZGNhcmQsXG4gIHJlc29sdmVWYXJpYWJsZSxcbiAgcmVzb2x2ZUhlYWRUYWlsLFxuICByZXNvbHZlQ2FwdHVyZSxcbiAgcmVzb2x2ZVN0YXJ0c1dpdGgsXG4gIHJlc29sdmVUeXBlLFxuICByZXNvbHZlQXJyYXksXG4gIHJlc29sdmVPYmplY3QsXG4gIHJlc29sdmVOb01hdGNoLFxuICByZXNvbHZlU3ltYm9sLFxuICByZXNvbHZlU3RyaW5nLFxuICByZXNvbHZlTnVtYmVyLFxuICByZXNvbHZlQm9vbGVhbixcbiAgcmVzb2x2ZUZ1bmN0aW9uLFxuICByZXNvbHZlTnVsbFxufTtcblxuZnVuY3Rpb24gYnVpbGRNYXRjaChwYXR0ZXJuKSB7XG5cbiAgaWYgKENoZWNrcy5pc192YXJpYWJsZShwYXR0ZXJuKSkge1xuICAgIHJldHVybiBSZXNvbHZlcnMucmVzb2x2ZVZhcmlhYmxlKHBhdHRlcm4pO1xuICB9XG5cbiAgaWYgKENoZWNrcy5pc193aWxkY2FyZChwYXR0ZXJuKSkge1xuICAgIHJldHVybiBSZXNvbHZlcnMucmVzb2x2ZVdpbGRjYXJkKHBhdHRlcm4pO1xuICB9XG5cbiAgaWYgKENoZWNrcy5pc191bmRlZmluZWQocGF0dGVybikpIHtcbiAgICByZXR1cm4gUmVzb2x2ZXJzLnJlc29sdmVXaWxkY2FyZChwYXR0ZXJuKTtcbiAgfVxuXG4gIGlmIChDaGVja3MuaXNfaGVhZFRhaWwocGF0dGVybikpIHtcbiAgICByZXR1cm4gUmVzb2x2ZXJzLnJlc29sdmVIZWFkVGFpbChwYXR0ZXJuKTtcbiAgfVxuXG4gIGlmIChDaGVja3MuaXNfc3RhcnRzV2l0aChwYXR0ZXJuKSkge1xuICAgIHJldHVybiBSZXNvbHZlcnMucmVzb2x2ZVN0YXJ0c1dpdGgocGF0dGVybik7XG4gIH1cblxuICBpZiAoQ2hlY2tzLmlzX2NhcHR1cmUocGF0dGVybikpIHtcbiAgICByZXR1cm4gUmVzb2x2ZXJzLnJlc29sdmVDYXB0dXJlKHBhdHRlcm4pO1xuICB9XG5cbiAgaWYgKENoZWNrcy5pc19ib3VuZChwYXR0ZXJuKSkge1xuICAgIHJldHVybiBSZXNvbHZlcnMucmVzb2x2ZUJvdW5kKHBhdHRlcm4pO1xuICB9XG5cbiAgaWYgKENoZWNrcy5pc190eXBlKHBhdHRlcm4pKSB7XG4gICAgcmV0dXJuIFJlc29sdmVycy5yZXNvbHZlVHlwZShwYXR0ZXJuKTtcbiAgfVxuXG4gIGlmIChDaGVja3MuaXNfYXJyYXkocGF0dGVybikpIHtcbiAgICByZXR1cm4gUmVzb2x2ZXJzLnJlc29sdmVBcnJheShwYXR0ZXJuKTtcbiAgfVxuXG4gIGlmIChDaGVja3MuaXNfbnVtYmVyKHBhdHRlcm4pKSB7XG4gICAgcmV0dXJuIFJlc29sdmVycy5yZXNvbHZlTnVtYmVyKHBhdHRlcm4pO1xuICB9XG5cbiAgaWYgKENoZWNrcy5pc19zdHJpbmcocGF0dGVybikpIHtcbiAgICByZXR1cm4gUmVzb2x2ZXJzLnJlc29sdmVTdHJpbmcocGF0dGVybik7XG4gIH1cblxuICBpZiAoQ2hlY2tzLmlzX2Jvb2xlYW4ocGF0dGVybikpIHtcbiAgICByZXR1cm4gUmVzb2x2ZXJzLnJlc29sdmVCb29sZWFuKHBhdHRlcm4pO1xuICB9XG5cbiAgaWYgKENoZWNrcy5pc19zeW1ib2wocGF0dGVybikpIHtcbiAgICByZXR1cm4gUmVzb2x2ZXJzLnJlc29sdmVTeW1ib2wocGF0dGVybik7XG4gIH1cblxuICBpZiAoQ2hlY2tzLmlzX251bGwocGF0dGVybikpIHtcbiAgICByZXR1cm4gUmVzb2x2ZXJzLnJlc29sdmVOdWxsKHBhdHRlcm4pO1xuICB9XG5cbiAgaWYgKENoZWNrcy5pc19vYmplY3QocGF0dGVybikpIHtcbiAgICByZXR1cm4gUmVzb2x2ZXJzLnJlc29sdmVPYmplY3QocGF0dGVybik7XG4gIH1cblxuICByZXR1cm4gUmVzb2x2ZXJzLnJlc29sdmVOb01hdGNoKCk7XG59XG5cbmNsYXNzIE1hdGNoRXJyb3IgZXh0ZW5kcyBFcnJvciB7XG4gIGNvbnN0cnVjdG9yKGFyZykge1xuICAgIHN1cGVyKCk7XG5cbiAgICBpZiAodHlwZW9mIGFyZyA9PT0gJ3N5bWJvbCcpIHtcbiAgICAgIHRoaXMubWVzc2FnZSA9ICdObyBtYXRjaCBmb3I6ICcgKyBhcmcudG9TdHJpbmcoKTtcbiAgICB9IGVsc2UgaWYgKEFycmF5LmlzQXJyYXkoYXJnKSkge1xuICAgICAgbGV0IG1hcHBlZFZhbHVlcyA9IGFyZy5tYXAoeCA9PiB4LnRvU3RyaW5nKCkpO1xuICAgICAgdGhpcy5tZXNzYWdlID0gJ05vIG1hdGNoIGZvcjogJyArIG1hcHBlZFZhbHVlcztcbiAgICB9IGVsc2Uge1xuICAgICAgdGhpcy5tZXNzYWdlID0gJ05vIG1hdGNoIGZvcjogJyArIGFyZztcbiAgICB9XG5cbiAgICB0aGlzLnN0YWNrID0gbmV3IEVycm9yKCkuc3RhY2s7XG4gICAgdGhpcy5uYW1lID0gdGhpcy5jb25zdHJ1Y3Rvci5uYW1lO1xuICB9XG59XG5cbmNsYXNzIENhc2Uge1xuXG4gIGNvbnN0cnVjdG9yKHBhdHRlcm4sIGZuLCBndWFyZCA9ICgpID0+IHRydWUpIHtcbiAgICB0aGlzLnBhdHRlcm4gPSBidWlsZE1hdGNoKHBhdHRlcm4pO1xuICAgIHRoaXMuZm4gPSBmbjtcbiAgICB0aGlzLmd1YXJkID0gZ3VhcmQ7XG4gIH1cbn1cblxuZnVuY3Rpb24gbWFrZV9jYXNlKHBhdHRlcm4sIGZuLCBndWFyZCA9ICgpID0+IHRydWUpIHtcbiAgcmV0dXJuIG5ldyBDYXNlKHBhdHRlcm4sIGZuLCBndWFyZCk7XG59XG5cbmZ1bmN0aW9uIGRlZm1hdGNoKC4uLmNhc2VzKSB7XG4gIHJldHVybiBmdW5jdGlvbiAoLi4uYXJncykge1xuICAgIGZvciAobGV0IHByb2Nlc3NlZENhc2Ugb2YgY2FzZXMpIHtcbiAgICAgIGxldCByZXN1bHQgPSBbXTtcbiAgICAgIGlmIChwcm9jZXNzZWRDYXNlLnBhdHRlcm4oYXJncywgcmVzdWx0KSAmJiBwcm9jZXNzZWRDYXNlLmd1YXJkLmFwcGx5KHRoaXMsIHJlc3VsdCkpIHtcbiAgICAgICAgcmV0dXJuIHByb2Nlc3NlZENhc2UuZm4uYXBwbHkodGhpcywgcmVzdWx0KTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICB0aHJvdyBuZXcgTWF0Y2hFcnJvcihhcmdzKTtcbiAgfTtcbn1cblxuZnVuY3Rpb24gbWF0Y2gocGF0dGVybiwgZXhwciwgZ3VhcmQgPSAoKSA9PiB0cnVlKSB7XG4gIGxldCByZXN1bHQgPSBbXTtcbiAgbGV0IHByb2Nlc3NlZFBhdHRlcm4gPSBidWlsZE1hdGNoKHBhdHRlcm4pO1xuICBpZiAocHJvY2Vzc2VkUGF0dGVybihleHByLCByZXN1bHQpICYmIGd1YXJkLmFwcGx5KHRoaXMsIHJlc3VsdCkpIHtcbiAgICByZXR1cm4gcmVzdWx0O1xuICB9IGVsc2Uge1xuICAgIHRocm93IG5ldyBNYXRjaEVycm9yKGV4cHIpO1xuICB9XG59XG5cbmZ1bmN0aW9uIG1hdGNoX25vX3Rocm93KHBhdHRlcm4sIGV4cHIsIGd1YXJkID0gKCkgPT4gdHJ1ZSkge1xuICB0cnkge1xuICAgIHJldHVybiBtYXRjaChwYXR0ZXJuLCBleHByLCBndWFyZCk7XG4gIH0gY2F0Y2ggKGUpIHtcbiAgICBpZiAoZSBpbnN0YW5jZW9mIE1hdGNoRXJyb3IpIHtcbiAgICAgIHJldHVybiBudWxsO1xuICAgIH1cblxuICAgIHRocm93IGU7XG4gIH1cbn1cblxudmFyIFBhdHRlcm5zID0ge1xuICBkZWZtYXRjaCwgbWF0Y2gsIE1hdGNoRXJyb3IsIG1hdGNoX25vX3Rocm93LFxuICB2YXJpYWJsZSwgd2lsZGNhcmQsIHN0YXJ0c1dpdGgsXG4gIGNhcHR1cmUsIGhlYWRUYWlsLCB0eXBlLCBib3VuZCwgQ2FzZSwgbWFrZV9jYXNlXG59O1xuXG5mdW5jdGlvbiBjYWxsX3Byb3BlcnR5KGl0ZW0sIHByb3BlcnR5KSB7XG4gIGlmIChwcm9wZXJ0eSBpbiBpdGVtKSB7XG4gICAgaXRlbVtwcm9wZXJ0eV07XG4gICAgaWYgKGl0ZW1bcHJvcGVydHldIGluc3RhbmNlb2YgRnVuY3Rpb24pIHtcbiAgICAgIHJldHVybiBpdGVtW3Byb3BlcnR5XSgpO1xuICAgIH0gZWxzZSB7XG4gICAgICByZXR1cm4gaXRlbVtwcm9wZXJ0eV07XG4gICAgfVxuICB9IGVsc2UgaWYgKFN5bWJvbC5mb3IocHJvcGVydHkpIGluIGl0ZW0pIHtcbiAgICBsZXQgcHJvcCA9IFN5bWJvbC5mb3IocHJvcGVydHkpO1xuICAgIGlmIChpdGVtW3Byb3BdIGluc3RhbmNlb2YgRnVuY3Rpb24pIHtcbiAgICAgIHJldHVybiBpdGVtW3Byb3BdKCk7XG4gICAgfSBlbHNlIHtcbiAgICAgIHJldHVybiBpdGVtW3Byb3BdO1xuICAgIH1cbiAgfVxuXG4gIHRocm93IG5ldyBFcnJvcihgUHJvcGVydHkgJHsgcHJvcGVydHkgfSBub3QgZm91bmQgaW4gJHsgaXRlbSB9YCk7XG59XG5cbmZ1bmN0aW9uIGlzX2luc3RhbmNlX29mKHZhbHVlLCB0eXBlKSB7XG4gIHJldHVybiB2YWx1ZSBpbnN0YW5jZW9mIHR5cGU7XG59XG5cbmZ1bmN0aW9uIHNpemUkMih0ZXJtKSB7XG4gIHJldHVybiB0ZXJtLmxlbmd0aDtcbn1cblxuZnVuY3Rpb24gaXNfbmlsJDEoeCkge1xuICByZXR1cm4geCA9PT0gbnVsbDtcbn1cblxuZnVuY3Rpb24gaXNfYXRvbSQxKHgpIHtcbiAgcmV0dXJuIHR5cGVvZiB4ID09PSAnc3ltYm9sJztcbn1cblxuZnVuY3Rpb24gaXNfYmluYXJ5JDEoeCkge1xuICByZXR1cm4gdHlwZW9mIHggPT09ICdzdHJpbmcnIHx8IHggaW5zdGFuY2VvZiBTdHJpbmc7XG59XG5cbmZ1bmN0aW9uIGlzX2Jvb2xlYW4kMSh4KSB7XG4gIHJldHVybiB0eXBlb2YgeCA9PT0gJ2Jvb2xlYW4nIHx8IHggaW5zdGFuY2VvZiBCb29sZWFuO1xufVxuXG5mdW5jdGlvbiBpc19mdW5jdGlvbiQxKHgsIGFyaXR5ID0gLTEpIHtcbiAgcmV0dXJuIHR5cGVvZiB4ID09PSAnZnVuY3Rpb24nIHx8IHggaW5zdGFuY2VvZiBGdW5jdGlvbjtcbn1cblxuZnVuY3Rpb24gaXNfZmxvYXQkMSh4KSB7XG4gIHJldHVybiBpc19udW1iZXIkMSh4KSAmJiAhTnVtYmVyLmlzSW50ZWdlcih4KTtcbn1cblxuZnVuY3Rpb24gaXNfaW50ZWdlciQxKHgpIHtcbiAgcmV0dXJuIE51bWJlci5pc0ludGVnZXIoeCk7XG59XG5cbmZ1bmN0aW9uIGlzX2xpc3QkMSh4KSB7XG4gIHJldHVybiB4IGluc3RhbmNlb2YgQXJyYXk7XG59XG5cbmZ1bmN0aW9uIGlzX21hcCQxKHgpIHtcbiAgcmV0dXJuIHR5cGVvZiB4ID09PSAnb2JqZWN0JyB8fCB4IGluc3RhbmNlb2YgT2JqZWN0O1xufVxuXG5mdW5jdGlvbiBpc19udW1iZXIkMSh4KSB7XG4gIHJldHVybiB0eXBlb2YgeCA9PT0gJ251bWJlcic7XG59XG5cbmZ1bmN0aW9uIGlzX3R1cGxlJDEoeCkge1xuICByZXR1cm4geCBpbnN0YW5jZW9mIFR1cGxlJDE7XG59XG5cbmZ1bmN0aW9uIGlzX3BpZCQxKHgpIHtcbiAgcmV0dXJuIHggaW5zdGFuY2VvZiBQSUQ7XG59XG5cbmZ1bmN0aW9uIGlzX3BvcnQkMSh4KSB7XG4gIHJldHVybiBmYWxzZTtcbn1cblxuZnVuY3Rpb24gaXNfcmVmZXJlbmNlJDEoeCkge1xuICByZXR1cm4gZmFsc2U7XG59XG5cbmZ1bmN0aW9uIGlzX2JpdHN0cmluZyQxKHgpIHtcbiAgcmV0dXJuIGlzX2JpbmFyeSQxKHgpIHx8IHggaW5zdGFuY2VvZiBCaXRTdHJpbmc7XG59XG5cbmZ1bmN0aW9uIGFkZChvbmUsIHR3bykge1xuICByZXR1cm4gb25lICsgdHdvO1xufVxuXG5mdW5jdGlvbiBzdWJ0cmFjdChvbmUsIHR3bykge1xuICByZXR1cm4gb25lICsgdHdvO1xufVxuXG5mdW5jdGlvbiBtdWx0aXBseShvbmUsIHR3bykge1xuICByZXR1cm4gb25lICsgdHdvO1xufVxuXG5mdW5jdGlvbiBkaXZpZGUob25lLCB0d28pIHtcbiAgcmV0dXJuIG9uZSArIHR3bztcbn1cblxuZnVuY3Rpb24gcmVtYWluZGVyKG9uZSwgdHdvKSB7XG4gIHJldHVybiBvbmUgKyB0d287XG59XG5cbmZ1bmN0aW9uIGFwcGx5JDEoLi4uYXJncykge1xuICBpZiAoYXJncy5sZW5ndGggPT09IDIpIHtcbiAgICBhcmdzWzBdLmFwcGx5KG51bGwsIGFyZ3Muc2xpY2UoMSkpO1xuICB9IGVsc2Uge1xuICAgIGFyZ3NbMF1bYXJnc1sxXV0uYXBwbHkobnVsbCwgYXJncy5zbGljZSgyKSk7XG4gIH1cbn1cblxuZnVuY3Rpb24gbmV3X3R1cGxlKC4uLmFyZ3MpIHtcbiAgcmV0dXJuIG5ldyBUdXBsZSQxKC4uLmFyZ3MpO1xufVxuXG5mdW5jdGlvbiBkdXBsaWNhdGUoZGF0YSwgc2l6ZSkge1xuICBsZXQgYXJyYXkgPSBbXTtcblxuICBmb3IgKHZhciBpID0gc2l6ZSAtIDE7IGkgPj0gMDsgaS0tKSB7XG4gICAgYXJyYXkucHVzaChkYXRhKTtcbiAgfVxuXG4gIHJldHVybiBhcnJheTtcbn1cblxuZnVuY3Rpb24gY29udGFpbnMobGVmdCwgcmlnaHQpIHtcbiAgZm9yIChsZXQgeCBvZiByaWdodCkge1xuICAgIGlmIChQYXR0ZXJucy5tYXRjaF9ub190aHJvdyhsZWZ0LCB4KSAhPSBudWxsKSB7XG4gICAgICByZXR1cm4gdHJ1ZTtcbiAgICB9XG4gIH1cblxuICByZXR1cm4gZmFsc2U7XG59XG5cbmZ1bmN0aW9uIHJldmVyc2UobGlzdCkge1xuICByZXR1cm4gbGlzdC5jb25jYXQoW10pLnJldmVyc2UoKTtcbn1cblxuZnVuY3Rpb24gZ2V0X2dsb2JhbCgpIHtcbiAgaWYgKHR5cGVvZiBzZWxmICE9PSAndW5kZWZpbmVkJykge1xuICAgIHJldHVybiBzZWxmO1xuICB9IGVsc2UgaWYgKHR5cGVvZiB3aW5kb3cgIT09ICd1bmRlZmluZWQnKSB7XG4gICAgcmV0dXJuIHdpbmRvdztcbiAgfSBlbHNlIGlmICh0eXBlb2YgZ2xvYmFsICE9PSAndW5kZWZpbmVkJykge1xuICAgIHJldHVybiBnbG9iYWw7XG4gIH1cblxuICB0aHJvdyBuZXcgRXJyb3IoJ05vIGdsb2JhbCBzdGF0ZSBmb3VuZCcpO1xufVxuXG5mdW5jdGlvbiBjb25jYXRfbGlzdHMobGVmdCwgcmlnaHQpIHtcbiAgcmV0dXJuIGxlZnQuY29uY2F0KHJpZ2h0KTtcbn1cblxuZnVuY3Rpb24gcHJlcGVuZF90b19saXN0KGxpc3QsIGl0ZW0pIHtcbiAgcmV0dXJuIFtpdGVtXS5jb25jYXQobGlzdCk7XG59XG5cbmZ1bmN0aW9uIGRlZnN0cnVjdChkZWZhdWx0cykge1xuICByZXR1cm4gY2xhc3Mge1xuICAgIGNvbnN0cnVjdG9yKHVwZGF0ZSA9IHt9KSB7XG4gICAgICBsZXQgdGhlX3ZhbHVlcyA9IE9iamVjdC5hc3NpZ24oZGVmYXVsdHMsIHVwZGF0ZSk7XG4gICAgICBPYmplY3QuYXNzaWduKHRoaXMsIHRoZV92YWx1ZXMpO1xuICAgIH1cblxuICAgIHN0YXRpYyBjcmVhdGUodXBkYXRlcyA9IHt9KSB7XG4gICAgICBsZXQgeCA9IG5ldyB0aGlzKHVwZGF0ZXMpO1xuICAgICAgcmV0dXJuIE9iamVjdC5mcmVlemUoeCk7XG4gICAgfVxuICB9O1xufVxuXG5mdW5jdGlvbiBkZWZleGNlcHRpb24oZGVmYXVsdHMpIHtcbiAgcmV0dXJuIGNsYXNzIGV4dGVuZHMgRXJyb3Ige1xuICAgIGNvbnN0cnVjdG9yKHVwZGF0ZSA9IHt9KSB7XG4gICAgICBsZXQgbWVzc2FnZSA9IHVwZGF0ZS5tZXNzYWdlIHx8ICcnO1xuICAgICAgc3VwZXIobWVzc2FnZSk7XG5cbiAgICAgIGxldCB0aGVfdmFsdWVzID0gT2JqZWN0LmFzc2lnbihkZWZhdWx0cywgdXBkYXRlKTtcbiAgICAgIE9iamVjdC5hc3NpZ24odGhpcywgdGhlX3ZhbHVlcyk7XG5cbiAgICAgIHRoaXMubmFtZSA9IHRoaXMuY29uc3RydWN0b3IubmFtZTtcbiAgICAgIHRoaXMubWVzc2FnZSA9IG1lc3NhZ2U7XG4gICAgICB0aGlzW1NwZWNpYWxGb3Jtcy5hdG9tKCdfX2V4Y2VwdGlvbl9fJyldID0gdHJ1ZTtcbiAgICAgIEVycm9yLmNhcHR1cmVTdGFja1RyYWNlKHRoaXMsIHRoaXMuY29uc3RydWN0b3IubmFtZSk7XG4gICAgfVxuXG4gICAgc3RhdGljIGNyZWF0ZSh1cGRhdGVzID0ge30pIHtcbiAgICAgIGxldCB4ID0gbmV3IHRoaXModXBkYXRlcyk7XG4gICAgICByZXR1cm4gT2JqZWN0LmZyZWV6ZSh4KTtcbiAgICB9XG4gIH07XG59XG5cbmZ1bmN0aW9uIGRlZnByb3RvY29sKHNwZWMpIHtcbiAgcmV0dXJuIG5ldyBQcm90b2NvbChzcGVjKTtcbn1cblxuZnVuY3Rpb24gZGVmaW1wbChwcm90b2NvbCwgdHlwZSwgaW1wbCkge1xuICBwcm90b2NvbC5pbXBsZW1lbnRhdGlvbih0eXBlLCBpbXBsKTtcbn1cblxuZnVuY3Rpb24gZ2V0X29iamVjdF9rZXlzKG9iaikge1xuICByZXR1cm4gT2JqZWN0LmtleXMob2JqKS5jb25jYXQoT2JqZWN0LmdldE93blByb3BlcnR5U3ltYm9scyhvYmopKTtcbn1cblxuZnVuY3Rpb24gaXNfdmFsaWRfY2hhcmFjdGVyKGNvZGVwb2ludCkge1xuICB0cnkge1xuICAgIHJldHVybiBTdHJpbmcuZnJvbUNvZGVQb2ludChjb2RlcG9pbnQpICE9IG51bGw7XG4gIH0gY2F0Y2ggKGUpIHtcbiAgICByZXR1cm4gZmFsc2U7XG4gIH1cbn1cblxuLy9odHRwczovL2RldmVsb3Blci5tb3ppbGxhLm9yZy9lbi1VUy9kb2NzL1dlYi9BUEkvV2luZG93QmFzZTY0L0Jhc2U2NF9lbmNvZGluZ19hbmRfZGVjb2RpbmcjU29sdXRpb25fMl8lRTIlODAlOTNfcmV3cml0ZV90aGVfRE9Nc19hdG9iKClfYW5kX2J0b2EoKV91c2luZ19KYXZhU2NyaXB0J3NfVHlwZWRBcnJheXNfYW5kX1VURi04XG5mdW5jdGlvbiBiNjRFbmNvZGVVbmljb2RlKHN0cikge1xuICByZXR1cm4gYnRvYShlbmNvZGVVUklDb21wb25lbnQoc3RyKS5yZXBsYWNlKC8lKFswLTlBLUZdezJ9KS9nLCBmdW5jdGlvbiAobWF0Y2gsIHAxKSB7XG4gICAgcmV0dXJuIFN0cmluZy5mcm9tQ2hhckNvZGUoJzB4JyArIHAxKTtcbiAgfSkpO1xufVxuXG52YXIgRnVuY3Rpb25zID0ge1xuICBjYWxsX3Byb3BlcnR5LFxuICBpc19pbnN0YW5jZV9vZixcbiAgc2l6ZTogc2l6ZSQyLFxuICBpc19uaWw6IGlzX25pbCQxLFxuICBpc19hdG9tOiBpc19hdG9tJDEsXG4gIGlzX2JpbmFyeTogaXNfYmluYXJ5JDEsXG4gIGlzX2Jvb2xlYW46IGlzX2Jvb2xlYW4kMSxcbiAgaXNfZnVuY3Rpb246IGlzX2Z1bmN0aW9uJDEsXG4gIGlzX2Zsb2F0OiBpc19mbG9hdCQxLFxuICBpc19pbnRlZ2VyOiBpc19pbnRlZ2VyJDEsXG4gIGlzX2xpc3Q6IGlzX2xpc3QkMSxcbiAgaXNfbWFwOiBpc19tYXAkMSxcbiAgaXNfbnVtYmVyOiBpc19udW1iZXIkMSxcbiAgaXNfdHVwbGU6IGlzX3R1cGxlJDEsXG4gIGlzX3BpZDogaXNfcGlkJDEsXG4gIGlzX3BvcnQ6IGlzX3BvcnQkMSxcbiAgaXNfcmVmZXJlbmNlOiBpc19yZWZlcmVuY2UkMSxcbiAgaXNfYml0c3RyaW5nOiBpc19iaXRzdHJpbmckMSxcbiAgYWRkLFxuICBzdWJ0cmFjdCxcbiAgbXVsdGlwbHksXG4gIGRpdmlkZSxcbiAgcmVtYWluZGVyLFxuICBhcHBseTogYXBwbHkkMSxcbiAgbmV3X3R1cGxlLFxuICBkdXBsaWNhdGUsXG4gIGNvbnRhaW5zLFxuICByZXZlcnNlLFxuICBnZXRfZ2xvYmFsLFxuICBjb25jYXRfbGlzdHMsXG4gIHByZXBlbmRfdG9fbGlzdCxcbiAgZGVmc3RydWN0LFxuICBkZWZleGNlcHRpb24sXG4gIGRlZnByb3RvY29sLFxuICBkZWZpbXBsLFxuICBnZXRfb2JqZWN0X2tleXMsXG4gIGlzX3ZhbGlkX2NoYXJhY3RlcixcbiAgYjY0RW5jb2RlVW5pY29kZVxufTtcblxuZnVuY3Rpb24gbGlzdCguLi5hcmdzKSB7XG4gIHJldHVybiBPYmplY3QuZnJlZXplKGFyZ3MpO1xufVxuXG5mdW5jdGlvbiBiaXRzdHJpbmcoLi4uYXJncykge1xuICByZXR1cm4gbmV3IEJpdFN0cmluZyguLi5hcmdzKTtcbn1cblxuZnVuY3Rpb24gdHVwbGUoLi4uYXJncykge1xuICByZXR1cm4gbmV3IFR1cGxlKC4uLmFyZ3MpO1xufVxuXG5mdW5jdGlvbiBfY2FzZShjb25kaXRpb24sIGNsYXVzZXMpIHtcbiAgcmV0dXJuIFBhdHRlcm5zLmRlZm1hdGNoKC4uLmNsYXVzZXMpKGNvbmRpdGlvbik7XG59XG5cbmZ1bmN0aW9uIGNvbmQoY2xhdXNlcykge1xuICBmb3IgKGxldCBjbGF1c2Ugb2YgY2xhdXNlcykge1xuICAgIGlmIChjbGF1c2VbMF0pIHtcbiAgICAgIHJldHVybiBjbGF1c2VbMV0oKTtcbiAgICB9XG4gIH1cblxuICB0aHJvdyBuZXcgRXJyb3IoKTtcbn1cblxuZnVuY3Rpb24gbWFwJDEob2JqKSB7XG4gIHJldHVybiBPYmplY3QuZnJlZXplKG9iaik7XG59XG5cbmZ1bmN0aW9uIG1hcF91cGRhdGUobWFwLCB2YWx1ZXMpIHtcbiAgcmV0dXJuIE9iamVjdC5mcmVlemUoT2JqZWN0LmFzc2lnbihPYmplY3QuY3JlYXRlKG1hcC5jb25zdHJ1Y3Rvci5wcm90b3R5cGUpLCBtYXAsIHZhbHVlcykpO1xufVxuXG5mdW5jdGlvbiBfZm9yKGNvbGxlY3Rpb25zLCBmdW4sIGZpbHRlciA9ICgpID0+IHRydWUsIGludG8gPSBbXSwgcHJldmlvdXNWYWx1ZXMgPSBbXSkge1xuICBsZXQgcGF0dGVybiA9IGNvbGxlY3Rpb25zWzBdWzBdO1xuICBsZXQgY29sbGVjdGlvbiA9IGNvbGxlY3Rpb25zWzBdWzFdO1xuXG4gIGlmIChjb2xsZWN0aW9ucy5sZW5ndGggPT09IDEpIHtcblxuICAgIGZvciAobGV0IGVsZW0gb2YgY29sbGVjdGlvbikge1xuICAgICAgbGV0IHIgPSBQYXR0ZXJucy5tYXRjaF9ub190aHJvdyhwYXR0ZXJuLCBlbGVtKTtcbiAgICAgIGxldCBhcmdzID0gcHJldmlvdXNWYWx1ZXMuY29uY2F0KHIpO1xuXG4gICAgICBpZiAociAmJiBmaWx0ZXIuYXBwbHkodGhpcywgYXJncykpIHtcbiAgICAgICAgaW50byA9IEVudW0uaW50byhbZnVuLmFwcGx5KHRoaXMsIGFyZ3MpXSwgaW50byk7XG4gICAgICB9XG4gICAgfVxuXG4gICAgcmV0dXJuIGludG87XG4gIH0gZWxzZSB7XG4gICAgbGV0IF9pbnRvID0gW107XG5cbiAgICBmb3IgKGxldCBlbGVtIG9mIGNvbGxlY3Rpb24pIHtcbiAgICAgIGxldCByID0gUGF0dGVybnMubWF0Y2hfbm9fdGhyb3cocGF0dGVybiwgZWxlbSk7XG4gICAgICBpZiAocikge1xuICAgICAgICBfaW50byA9IEVudW0uaW50byh0aGlzLl9mb3IoY29sbGVjdGlvbnMuc2xpY2UoMSksIGZ1biwgZmlsdGVyLCBfaW50bywgcHJldmlvdXNWYWx1ZXMuY29uY2F0KHIpKSwgaW50byk7XG4gICAgICB9XG4gICAgfVxuXG4gICAgcmV0dXJuIF9pbnRvO1xuICB9XG59XG5cbmZ1bmN0aW9uIF90cnkoZG9fZnVuLCByZXNjdWVfZnVuY3Rpb24sIGNhdGNoX2Z1biwgZWxzZV9mdW5jdGlvbiwgYWZ0ZXJfZnVuY3Rpb24pIHtcbiAgbGV0IHJlc3VsdCA9IG51bGw7XG5cbiAgdHJ5IHtcbiAgICByZXN1bHQgPSBkb19mdW4oKTtcbiAgfSBjYXRjaCAoZSkge1xuICAgIGxldCBleF9yZXN1bHQgPSBudWxsO1xuXG4gICAgaWYgKHJlc2N1ZV9mdW5jdGlvbikge1xuICAgICAgdHJ5IHtcbiAgICAgICAgZXhfcmVzdWx0ID0gcmVzY3VlX2Z1bmN0aW9uKGUpO1xuICAgICAgICByZXR1cm4gZXhfcmVzdWx0O1xuICAgICAgfSBjYXRjaCAoZXgpIHtcbiAgICAgICAgaWYgKGV4IGluc3RhbmNlb2YgUGF0dGVybnMuTWF0Y2hFcnJvcikge1xuICAgICAgICAgIHRocm93IGV4O1xuICAgICAgICB9XG4gICAgICB9XG4gICAgfVxuXG4gICAgaWYgKGNhdGNoX2Z1bikge1xuICAgICAgdHJ5IHtcbiAgICAgICAgZXhfcmVzdWx0ID0gY2F0Y2hfZnVuKGUpO1xuICAgICAgICByZXR1cm4gZXhfcmVzdWx0O1xuICAgICAgfSBjYXRjaCAoZXgpIHtcbiAgICAgICAgaWYgKGV4IGluc3RhbmNlb2YgUGF0dGVybnMuTWF0Y2hFcnJvcikge1xuICAgICAgICAgIHRocm93IGV4O1xuICAgICAgICB9XG4gICAgICB9XG4gICAgfVxuXG4gICAgdGhyb3cgZTtcbiAgfSBmaW5hbGx5IHtcbiAgICBpZiAoYWZ0ZXJfZnVuY3Rpb24pIHtcbiAgICAgIGFmdGVyX2Z1bmN0aW9uKCk7XG4gICAgfVxuICB9XG5cbiAgaWYgKGVsc2VfZnVuY3Rpb24pIHtcbiAgICB0cnkge1xuICAgICAgcmV0dXJuIGVsc2VfZnVuY3Rpb24ocmVzdWx0KTtcbiAgICB9IGNhdGNoIChleCkge1xuICAgICAgaWYgKGV4IGluc3RhbmNlb2YgUGF0dGVybnMuTWF0Y2hFcnJvcikge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ05vIE1hdGNoIEZvdW5kIGluIEVsc2UnKTtcbiAgICAgIH1cblxuICAgICAgdGhyb3cgZXg7XG4gICAgfVxuICB9IGVsc2Uge1xuICAgIHJldHVybiByZXN1bHQ7XG4gIH1cbn1cblxudmFyIFNwZWNpYWxGb3JtcyQxID0ge1xuICBsaXN0LFxuICBiaXRzdHJpbmcsXG4gIHR1cGxlLFxuICBfY2FzZSxcbiAgY29uZCxcbiAgbWFwOiBtYXAkMSxcbiAgbWFwX3VwZGF0ZSxcbiAgX2ZvcixcbiAgX3RyeVxufTtcblxuRnVuY3Rpb25zLmdldF9nbG9iYWwoKS5wcm9jZXNzZXMgPSBGdW5jdGlvbnMuZ2V0X2dsb2JhbCgpLnByb2Nlc3NlcyB8fCBuZXcgUHJvY2Vzc1N5c3RlbSgpO1xuXG5cblxudmFyIEMgPSBPYmplY3QuZnJlZXplKHtcblx0UHJvY2Vzc1N5c3RlbTogUHJvY2Vzc1N5c3RlbSxcblx0VHVwbGU6IFR1cGxlJDEsXG5cdFBJRDogUElELFxuXHRCaXRTdHJpbmc6IEJpdFN0cmluZyxcblx0UGF0dGVybnM6IFBhdHRlcm5zLFxuXHRJbnRlZ2VyOiBJbnRlZ2VyLFxuXHRGbG9hdDogRmxvYXQsXG5cdEZ1bmN0aW9uczogRnVuY3Rpb25zLFxuXHRMaXN0OiBMaXN0JDEsXG5cdFNwZWNpYWxGb3JtczogU3BlY2lhbEZvcm1zJDFcbn0pO1xuXG5mdW5jdGlvbiB0bChsaXN0KSB7XG4gIHJldHVybiBTcGVjaWFsRm9ybXMkMS5saXN0KC4uLmxpc3Quc2xpY2UoMSkpO1xufVxuXG5mdW5jdGlvbiBoZChsaXN0KSB7XG4gIHJldHVybiBsaXN0WzBdO1xufVxuXG5mdW5jdGlvbiBpc19uaWwoeCkge1xuICByZXR1cm4geCA9PT0gbnVsbDtcbn1cblxuZnVuY3Rpb24gaXNfYXRvbSh4KSB7XG4gIHJldHVybiB0eXBlb2YgeCA9PT0gJ3N5bWJvbCc7XG59XG5cbmZ1bmN0aW9uIGlzX2JpbmFyeSh4KSB7XG4gIHJldHVybiB0eXBlb2YgeCA9PT0gJ3N0cmluZycgfHwgeCBpbnN0YW5jZW9mIFN0cmluZztcbn1cblxuZnVuY3Rpb24gaXNfYm9vbGVhbih4KSB7XG4gIHJldHVybiB0eXBlb2YgeCA9PT0gJ2Jvb2xlYW4nIHx8IHggaW5zdGFuY2VvZiBCb29sZWFuO1xufVxuXG5mdW5jdGlvbiBpc19mdW5jdGlvbih4LCBhcml0eSA9IC0xKSB7XG4gIHJldHVybiB0eXBlb2YgeCA9PT0gJ2Z1bmN0aW9uJyB8fCB4IGluc3RhbmNlb2YgRnVuY3Rpb247XG59XG5cbmZ1bmN0aW9uIGlzX2Zsb2F0KHgpIHtcbiAgcmV0dXJuIGlzX251bWJlcih4KSAmJiAhTnVtYmVyLmlzSW50ZWdlcih4KTtcbn1cblxuZnVuY3Rpb24gaXNfaW50ZWdlcih4KSB7XG4gIHJldHVybiBOdW1iZXIuaXNJbnRlZ2VyKHgpO1xufVxuXG5mdW5jdGlvbiBpc19saXN0KHgpIHtcbiAgcmV0dXJuIHggaW5zdGFuY2VvZiBBcnJheTtcbn1cblxuZnVuY3Rpb24gaXNfbWFwKHgpIHtcbiAgcmV0dXJuIHR5cGVvZiB4ID09PSAnb2JqZWN0JyB8fCB4IGluc3RhbmNlb2YgT2JqZWN0O1xufVxuXG5mdW5jdGlvbiBpc19udW1iZXIoeCkge1xuICByZXR1cm4gdHlwZW9mIHggPT09ICdudW1iZXInO1xufVxuXG5mdW5jdGlvbiBpc190dXBsZSh4KSB7XG4gIHJldHVybiB4IGluc3RhbmNlb2YgVHVwbGUkMTtcbn1cblxuZnVuY3Rpb24gbGVuZ3RoKHgpIHtcbiAgcmV0dXJuIHgubGVuZ3RoO1xufVxuXG5mdW5jdGlvbiBpc19waWQoeCkge1xuICByZXR1cm4geCBpbnN0YW5jZW9mIFBJRDtcbn1cblxuZnVuY3Rpb24gaXNfcG9ydCh4KSB7XG4gIHJldHVybiBmYWxzZTtcbn1cblxuZnVuY3Rpb24gaXNfcmVmZXJlbmNlKHgpIHtcbiAgcmV0dXJuIGZhbHNlO1xufVxuXG5mdW5jdGlvbiBpc19iaXRzdHJpbmcoeCkge1xuICByZXR1cm4gaXNfYmluYXJ5KHgpIHx8IHggaW5zdGFuY2VvZiBCaXRTdHJpbmc7XG59XG5cbmZ1bmN0aW9uIF9faW5fXyhsZWZ0LCByaWdodCkge1xuICBmb3IgKGxldCB4IG9mIHJpZ2h0KSB7XG4gICAgaWYgKG1hdGNoX19xbWFya19fKGxlZnQsIHgpKSB7XG4gICAgICByZXR1cm4gdHJ1ZTtcbiAgICB9XG4gIH1cblxuICByZXR1cm4gZmFsc2U7XG59XG5cbmZ1bmN0aW9uIGFicyhudW1iZXIpIHtcbiAgcmV0dXJuIE1hdGguYWJzKG51bWJlcik7XG59XG5cbmZ1bmN0aW9uIHJvdW5kKG51bWJlcikge1xuICByZXR1cm4gTWF0aC5yb3VuZChudW1iZXIpO1xufVxuXG5mdW5jdGlvbiBlbGVtKHR1cGxlLCBpbmRleCkge1xuICBpZiAoaXNfbGlzdCh0dXBsZSkpIHtcbiAgICByZXR1cm4gdHVwbGVbaW5kZXhdO1xuICB9XG5cbiAgcmV0dXJuIHR1cGxlLmdldChpbmRleCk7XG59XG5cbmZ1bmN0aW9uIHJlbShsZWZ0LCByaWdodCkge1xuICByZXR1cm4gbGVmdCAlIHJpZ2h0O1xufVxuXG5mdW5jdGlvbiBkaXYobGVmdCwgcmlnaHQpIHtcbiAgcmV0dXJuIGxlZnQgLyByaWdodDtcbn1cblxuZnVuY3Rpb24gYW5kKGxlZnQsIHJpZ2h0KSB7XG4gIHJldHVybiBsZWZ0ICYmIHJpZ2h0O1xufVxuXG5mdW5jdGlvbiBvcihsZWZ0LCByaWdodCkge1xuICByZXR1cm4gbGVmdCB8fCByaWdodDtcbn1cblxuZnVuY3Rpb24gbm90KGFyZykge1xuICByZXR1cm4gIWFyZztcbn1cblxuZnVuY3Rpb24gYXBwbHkoLi4uYXJncykge1xuICBpZiAoYXJncy5sZW5ndGggPT09IDMpIHtcbiAgICBsZXQgbW9kID0gYXJnc1swXTtcbiAgICBsZXQgZnVuYyA9IGFyZ3NbMV07XG4gICAgbGV0IGZ1bmNfYXJncyA9IGFyZ3NbMl07XG4gICAgcmV0dXJuIG1vZFtmdW5jXS5hcHBseShudWxsLCBmdW5jX2FyZ3MpO1xuICB9IGVsc2Uge1xuICAgIGxldCBmdW5jID0gYXJnc1swXTtcbiAgICBsZXQgZnVuY19hcmdzID0gYXJnc1sxXTtcblxuICAgIHJldHVybiBmdW5jLmFwcGx5KG51bGwsIGZ1bmNfYXJncyk7XG4gIH1cbn1cblxuZnVuY3Rpb24gdG9fc3RyaW5nKGFyZykge1xuICBpZiAoaXNfdHVwbGUoYXJnKSkge1xuICAgIHJldHVybiBhcmcudG9TdHJpbmcoKTtcbiAgfVxuXG4gIHJldHVybiBhcmcudG9TdHJpbmcoKTtcbn1cblxuZnVuY3Rpb24gbWF0Y2hfX3FtYXJrX18ocGF0dGVybiwgZXhwciwgZ3VhcmQgPSAoKSA9PiB0cnVlKSB7XG4gIHJldHVybiBQYXR0ZXJucy5tYXRjaF9ub190aHJvdyhwYXR0ZXJuLCBleHByLCBndWFyZCkgIT0gbnVsbDtcbn1cblxudmFyIEtlcm5lbCA9IHtcbiAgdGwsXG4gIGhkLFxuICBpc19uaWwsXG4gIGlzX2F0b20sXG4gIGlzX2JpbmFyeSxcbiAgaXNfYm9vbGVhbixcbiAgaXNfZnVuY3Rpb24sXG4gIGlzX2Zsb2F0LFxuICBpc19pbnRlZ2VyLFxuICBpc19saXN0LFxuICBpc19tYXAsXG4gIGlzX251bWJlcixcbiAgaXNfdHVwbGUsXG4gIGxlbmd0aCxcbiAgaXNfcGlkLFxuICBpc19wb3J0LFxuICBpc19yZWZlcmVuY2UsXG4gIGlzX2JpdHN0cmluZyxcbiAgaW46IF9faW5fXyxcbiAgYWJzLFxuICByb3VuZCxcbiAgZWxlbSxcbiAgcmVtLFxuICBkaXYsXG4gIGFuZCxcbiAgb3IsXG4gIG5vdCxcbiAgYXBwbHksXG4gIHRvX3N0cmluZyxcbiAgbWF0Y2hfX3FtYXJrX19cbn07XG5cbmxldCBFbnVtJDEgPSB7XG5cbiAgYWxsX19xbWFya19fOiBmdW5jdGlvbiAoY29sbGVjdGlvbiwgZnVuID0geCA9PiB4KSB7XG4gICAgZm9yIChsZXQgZWxlbSBvZiBjb2xsZWN0aW9uKSB7XG4gICAgICBpZiAoIWZ1bihlbGVtKSkge1xuICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICB9XG4gICAgfVxuXG4gICAgcmV0dXJuIHRydWU7XG4gIH0sXG5cbiAgYW55X19xbWFya19fOiBmdW5jdGlvbiAoY29sbGVjdGlvbiwgZnVuID0geCA9PiB4KSB7XG4gICAgZm9yIChsZXQgZWxlbSBvZiBjb2xsZWN0aW9uKSB7XG4gICAgICBpZiAoZnVuKGVsZW0pKSB7XG4gICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgfVxuICAgIH1cblxuICAgIHJldHVybiBmYWxzZTtcbiAgfSxcblxuICBhdDogZnVuY3Rpb24gKGNvbGxlY3Rpb24sIG4sIHRoZV9kZWZhdWx0ID0gbnVsbCkge1xuICAgIGlmIChuID4gdGhpcy5jb3VudChjb2xsZWN0aW9uKSB8fCBuIDwgMCkge1xuICAgICAgcmV0dXJuIHRoZV9kZWZhdWx0O1xuICAgIH1cblxuICAgIHJldHVybiBjb2xsZWN0aW9uW25dO1xuICB9LFxuXG4gIGNvbmNhdDogZnVuY3Rpb24gKC4uLmVudW1hYmxlcykge1xuICAgIHJldHVybiBlbnVtYWJsZXNbMF0uY29uY2F0KGVudW1hYmxlc1sxXSk7XG4gIH0sXG5cbiAgY291bnQ6IGZ1bmN0aW9uIChjb2xsZWN0aW9uLCBmdW4gPSBudWxsKSB7XG4gICAgaWYgKGZ1biA9PSBudWxsKSB7XG4gICAgICByZXR1cm4gY29sbGVjdGlvbi5sZW5ndGg7XG4gICAgfSBlbHNlIHtcbiAgICAgIHJldHVybiBjb2xsZWN0aW9uLmZpbHRlcihmdW4pLmxlbmd0aDtcbiAgICB9XG4gIH0sXG5cbiAgZHJvcDogZnVuY3Rpb24gKGNvbGxlY3Rpb24sIGNvdW50KSB7XG4gICAgcmV0dXJuIGNvbGxlY3Rpb24uc2xpY2UoY291bnQpO1xuICB9LFxuXG4gIGRyb3Bfd2hpbGU6IGZ1bmN0aW9uIChjb2xsZWN0aW9uLCBmdW4pIHtcbiAgICBsZXQgY291bnQgPSAwO1xuXG4gICAgZm9yIChsZXQgZWxlbSBvZiBjb2xsZWN0aW9uKSB7XG4gICAgICBpZiAoZnVuKGVsZW0pKSB7XG4gICAgICAgIGNvdW50ID0gY291bnQgKyAxO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgYnJlYWs7XG4gICAgICB9XG4gICAgfVxuXG4gICAgcmV0dXJuIGNvbGxlY3Rpb24uc2xpY2UoY291bnQpO1xuICB9LFxuXG4gIGVhY2g6IGZ1bmN0aW9uIChjb2xsZWN0aW9uLCBmdW4pIHtcbiAgICBmb3IgKGxldCBlbGVtIG9mIGNvbGxlY3Rpb24pIHtcbiAgICAgIGZ1bihlbGVtKTtcbiAgICB9XG4gIH0sXG5cbiAgZW1wdHlfX3FtYXJrX186IGZ1bmN0aW9uIChjb2xsZWN0aW9uKSB7XG4gICAgcmV0dXJuIGNvbGxlY3Rpb24ubGVuZ3RoID09PSAwO1xuICB9LFxuXG4gIGZldGNoOiBmdW5jdGlvbiAoY29sbGVjdGlvbiwgbikge1xuICAgIGlmIChLZXJuZWwuaXNfbGlzdChjb2xsZWN0aW9uKSkge1xuICAgICAgaWYgKG4gPCB0aGlzLmNvdW50KGNvbGxlY3Rpb24pICYmIG4gPj0gMCkge1xuICAgICAgICByZXR1cm4gbmV3IFR1cGxlJDEoU3ltYm9sLmZvcignb2snKSwgY29sbGVjdGlvbltuXSk7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICByZXR1cm4gU3ltYm9sLmZvcignZXJyb3InKTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICB0aHJvdyBuZXcgRXJyb3IoJ2NvbGxlY3Rpb24gaXMgbm90IGFuIEVudW1lcmFibGUnKTtcbiAgfSxcblxuICBmZXRjaF9fZW1hcmtfXzogZnVuY3Rpb24gKGNvbGxlY3Rpb24sIG4pIHtcbiAgICBpZiAoS2VybmVsLmlzX2xpc3QoY29sbGVjdGlvbikpIHtcbiAgICAgIGlmIChuIDwgdGhpcy5jb3VudChjb2xsZWN0aW9uKSAmJiBuID49IDApIHtcbiAgICAgICAgcmV0dXJuIGNvbGxlY3Rpb25bbl07XG4gICAgICB9IGVsc2Uge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ291dCBvZiBib3VuZHMgZXJyb3InKTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICB0aHJvdyBuZXcgRXJyb3IoJ2NvbGxlY3Rpb24gaXMgbm90IGFuIEVudW1lcmFibGUnKTtcbiAgfSxcblxuICBmaWx0ZXI6IGZ1bmN0aW9uIChjb2xsZWN0aW9uLCBmdW4pIHtcbiAgICBsZXQgcmVzdWx0ID0gW107XG5cbiAgICBmb3IgKGxldCBlbGVtIG9mIGNvbGxlY3Rpb24pIHtcbiAgICAgIGlmIChmdW4oZWxlbSkpIHtcbiAgICAgICAgcmVzdWx0LnB1c2goZWxlbSk7XG4gICAgICB9XG4gICAgfVxuXG4gICAgcmV0dXJuIHJlc3VsdDtcbiAgfSxcblxuICBmaWx0ZXJfbWFwOiBmdW5jdGlvbiAoY29sbGVjdGlvbiwgZmlsdGVyLCBtYXBwZXIpIHtcbiAgICByZXR1cm4gRW51bSQxLm1hcChFbnVtJDEuZmlsdGVyKGNvbGxlY3Rpb24sIGZpbHRlciksIG1hcHBlcik7XG4gIH0sXG5cbiAgZmluZDogZnVuY3Rpb24gKGNvbGxlY3Rpb24sIGlmX25vbmUgPSBudWxsLCBmdW4pIHtcbiAgICBmb3IgKGxldCBlbGVtIG9mIGNvbGxlY3Rpb24pIHtcbiAgICAgIGlmIChmdW4oZWxlbSkpIHtcbiAgICAgICAgcmV0dXJuIGVsZW07XG4gICAgICB9XG4gICAgfVxuXG4gICAgcmV0dXJuIGlmX25vbmU7XG4gIH0sXG5cbiAgaW50bzogZnVuY3Rpb24gKGNvbGxlY3Rpb24sIGxpc3QpIHtcbiAgICByZXR1cm4gbGlzdC5jb25jYXQoY29sbGVjdGlvbik7XG4gIH0sXG5cbiAgbWFwOiBmdW5jdGlvbiAoY29sbGVjdGlvbiwgZnVuKSB7XG4gICAgbGV0IHJlc3VsdCA9IFtdO1xuXG4gICAgZm9yIChsZXQgZWxlbSBvZiBjb2xsZWN0aW9uKSB7XG4gICAgICByZXN1bHQucHVzaChmdW4oZWxlbSkpO1xuICAgIH1cblxuICAgIHJldHVybiByZXN1bHQ7XG4gIH0sXG5cbiAgbWFwX3JlZHVjZTogZnVuY3Rpb24gKGNvbGxlY3Rpb24sIGFjYywgZnVuKSB7XG4gICAgbGV0IG1hcHBlZCA9IExpc3QkMSgpO1xuICAgIGxldCB0aGVfYWNjID0gYWNjO1xuXG4gICAgZm9yICh2YXIgaSA9IDA7IGkgPCB0aGlzLmNvdW50KGNvbGxlY3Rpb24pOyBpKyspIHtcbiAgICAgIGxldCB0dXBsZSA9IGZ1bihjb2xsZWN0aW9uW2ldLCB0aGVfYWNjKTtcblxuICAgICAgdGhlX2FjYyA9IHR1cGxlLmdldCgxKTtcbiAgICAgIG1hcHBlZCA9IExpc3QkMSguLi5tYXBwZWQuY29uY2F0KFt0dXBsZS5nZXQoMCldKSk7XG4gICAgfVxuXG4gICAgcmV0dXJuIG5ldyBUdXBsZSQxKG1hcHBlZCwgdGhlX2FjYyk7XG4gIH0sXG5cbiAgbWVtYmVyX19xbWFya19fOiBmdW5jdGlvbiAoY29sbGVjdGlvbiwgdmFsdWUpIHtcbiAgICByZXR1cm4gY29sbGVjdGlvbi5pbmNsdWRlcyh2YWx1ZSk7XG4gIH0sXG5cbiAgcmVkdWNlOiBmdW5jdGlvbiAoY29sbGVjdGlvbiwgYWNjLCBmdW4pIHtcbiAgICBsZXQgdGhlX2FjYyA9IGFjYztcblxuICAgIGZvciAodmFyIGkgPSAwOyBpIDwgdGhpcy5jb3VudChjb2xsZWN0aW9uKTsgaSsrKSB7XG4gICAgICBsZXQgdHVwbGUgPSBmdW4oY29sbGVjdGlvbltpXSwgdGhlX2FjYyk7XG5cbiAgICAgIHRoZV9hY2MgPSB0dXBsZS5nZXQoMSk7XG4gICAgfVxuXG4gICAgcmV0dXJuIHRoZV9hY2M7XG4gIH0sXG5cbiAgdGFrZTogZnVuY3Rpb24gKGNvbGxlY3Rpb24sIGNvdW50KSB7XG4gICAgcmV0dXJuIGNvbGxlY3Rpb24uc2xpY2UoMCwgY291bnQpO1xuICB9LFxuXG4gIHRha2VfZXZlcnk6IGZ1bmN0aW9uIChjb2xsZWN0aW9uLCBudGgpIHtcbiAgICBsZXQgcmVzdWx0ID0gW107XG4gICAgbGV0IGluZGV4ID0gMDtcblxuICAgIGZvciAobGV0IGVsZW0gb2YgY29sbGVjdGlvbikge1xuICAgICAgaWYgKGluZGV4ICUgbnRoID09PSAwKSB7XG4gICAgICAgIHJlc3VsdC5wdXNoKGVsZW0pO1xuICAgICAgfVxuICAgIH1cblxuICAgIHJldHVybiBMaXN0JDEoLi4ucmVzdWx0KTtcbiAgfSxcblxuICB0YWtlX3doaWxlOiBmdW5jdGlvbiAoY29sbGVjdGlvbiwgZnVuKSB7XG4gICAgbGV0IGNvdW50ID0gMDtcblxuICAgIGZvciAobGV0IGVsZW0gb2YgY29sbGVjdGlvbikge1xuICAgICAgaWYgKGZ1bihlbGVtKSkge1xuICAgICAgICBjb3VudCA9IGNvdW50ICsgMTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIGJyZWFrO1xuICAgICAgfVxuICAgIH1cblxuICAgIHJldHVybiBjb2xsZWN0aW9uLnNsaWNlKDAsIGNvdW50KTtcbiAgfSxcblxuICB0b19saXN0OiBmdW5jdGlvbiAoY29sbGVjdGlvbikge1xuICAgIHJldHVybiBjb2xsZWN0aW9uO1xuICB9XG59O1xuXG5sZXQgTGlzdCA9IHt9O1xuXG5MaXN0LmRlbGV0ZSA9IGZ1bmN0aW9uIChsaXN0LCBpdGVtKSB7XG4gIGxldCBuZXdfdmFsdWUgPSBbXTtcbiAgbGV0IHZhbHVlX2ZvdW5kID0gZmFsc2U7XG5cbiAgZm9yIChsZXQgeCBvZiBsaXN0KSB7XG4gICAgaWYgKHggPT09IGl0ZW0gJiYgdmFsdWVfZm91bmQgIT09IGZhbHNlKSB7XG4gICAgICBuZXdfdmFsdWUucHVzaCh4KTtcbiAgICAgIHZhbHVlX2ZvdW5kID0gdHJ1ZTtcbiAgICB9IGVsc2UgaWYgKHggIT09IGl0ZW0pIHtcbiAgICAgIG5ld192YWx1ZS5wdXNoKHgpO1xuICAgIH1cbiAgfVxuXG4gIHJldHVybiBTcGVjaWFsRm9ybXMkMS5saXN0KC4uLm5ld192YWx1ZSk7XG59O1xuXG5MaXN0LmRlbGV0ZV9hdCA9IGZ1bmN0aW9uIChsaXN0LCBpbmRleCkge1xuICBsZXQgbmV3X3ZhbHVlID0gW107XG5cbiAgZm9yIChsZXQgaSA9IDA7IGkgPCBsaXN0Lmxlbmd0aDsgaSsrKSB7XG4gICAgaWYgKGkgIT09IGluZGV4KSB7XG4gICAgICBuZXdfdmFsdWUucHVzaChsaXN0W2ldKTtcbiAgICB9XG4gIH1cblxuICByZXR1cm4gU3BlY2lhbEZvcm1zJDEubGlzdCguLi5uZXdfdmFsdWUpO1xufTtcblxuTGlzdC5kdXBsaWNhdGUgPSBmdW5jdGlvbiAoZWxlbSwgbikge1xuICBsZXQgbmV3X3ZhbHVlID0gW107XG5cbiAgZm9yICh2YXIgaSA9IDA7IGkgPCBuOyBpKyspIHtcbiAgICBuZXdfdmFsdWUucHVzaChlbGVtKTtcbiAgfVxuXG4gIHJldHVybiBTcGVjaWFsRm9ybXMkMS5saXN0KC4uLm5ld192YWx1ZSk7XG59O1xuXG5MaXN0LmZpcnN0ID0gZnVuY3Rpb24gKGxpc3QpIHtcbiAgcmV0dXJuIGxpc3RbMF07XG59O1xuXG5MaXN0LmZsYXR0ZW4gPSBmdW5jdGlvbiAobGlzdCwgdGFpbCA9IFNwZWNpYWxGb3JtcyQxLmxpc3QoKSkge1xuICBsZXQgbmV3X3ZhbHVlID0gW107XG5cbiAgZm9yIChsZXQgeCBvZiBsaXN0KSB7XG4gICAgaWYgKEtlcm5lbC5pc19saXN0KHgpKSB7XG4gICAgICBuZXdfdmFsdWUgPSBuZXdfdmFsdWUuY29uY2F0KExpc3QuZmxhdHRlbih4KSk7XG4gICAgfSBlbHNlIHtcbiAgICAgIG5ld192YWx1ZS5wdXNoKHgpO1xuICAgIH1cbiAgfVxuXG4gIG5ld192YWx1ZSA9IG5ld192YWx1ZS5jb25jYXQodGFpbCk7XG5cbiAgcmV0dXJuIFNwZWNpYWxGb3JtcyQxLmxpc3QoLi4ubmV3X3ZhbHVlKTtcbn07XG5cbkxpc3QuZm9sZGwgPSBmdW5jdGlvbiAobGlzdCwgYWNjLCBmdW5jKSB7XG4gIHJldHVybiBsaXN0LnJlZHVjZShmdW5jLCBhY2MpO1xufTtcblxuTGlzdC5mb2xkciA9IGZ1bmN0aW9uIChsaXN0LCBhY2MsIGZ1bmMpIHtcbiAgbGV0IG5ld19hY2MgPSBhY2M7XG5cbiAgZm9yICh2YXIgaSA9IGxpc3QubGVuZ3RoIC0gMTsgaSA+PSAwOyBpLS0pIHtcbiAgICBuZXdfYWNjID0gZnVuYyhsaXN0W2ldLCBuZXdfYWNjKTtcbiAgfVxuXG4gIHJldHVybiBuZXdfYWNjO1xufTtcblxuTGlzdC5pbnNlcnRfYXQgPSBmdW5jdGlvbiAobGlzdCwgaW5kZXgsIHZhbHVlKSB7XG4gIGxldCBuZXdfdmFsdWUgPSBbXTtcblxuICBmb3IgKGxldCBpID0gMDsgaSA8IGxpc3QubGVuZ3RoOyBpKyspIHtcbiAgICBpZiAoaSA9PT0gaW5kZXgpIHtcbiAgICAgIG5ld192YWx1ZS5wdXNoKHZhbHVlKTtcbiAgICAgIG5ld192YWx1ZS5wdXNoKGxpc3RbaV0pO1xuICAgIH0gZWxzZSB7XG4gICAgICBuZXdfdmFsdWUucHVzaChsaXN0W2ldKTtcbiAgICB9XG4gIH1cblxuICByZXR1cm4gU3BlY2lhbEZvcm1zJDEubGlzdCguLi5uZXdfdmFsdWUpO1xufTtcblxuTGlzdC5rZXlkZWxldGUgPSBmdW5jdGlvbiAobGlzdCwga2V5LCBwb3NpdGlvbikge1xuICBsZXQgbmV3X2xpc3QgPSBbXTtcblxuICBmb3IgKGxldCBpID0gMDsgaSA8IGxpc3QubGVuZ3RoOyBpKyspIHtcbiAgICBpZiAoIUtlcm5lbC5tYXRjaF9fcW1hcmtfXyhsaXN0W2ldW3Bvc2l0aW9uXSwga2V5KSkge1xuICAgICAgbmV3X2xpc3QucHVzaChsaXN0W2ldKTtcbiAgICB9XG4gIH1cblxuICByZXR1cm4gU3BlY2lhbEZvcm1zJDEubGlzdCguLi5uZXdfbGlzdCk7XG59O1xuXG5MaXN0LmtleWZpbmQgPSBmdW5jdGlvbiAobGlzdCwga2V5LCBwb3NpdGlvbiwgX2RlZmF1bHQgPSBudWxsKSB7XG5cbiAgZm9yIChsZXQgaSA9IDA7IGkgPCBsaXN0Lmxlbmd0aDsgaSsrKSB7XG4gICAgaWYgKEtlcm5lbC5tYXRjaF9fcW1hcmtfXyhsaXN0W2ldW3Bvc2l0aW9uXSwga2V5KSkge1xuICAgICAgcmV0dXJuIGxpc3RbaV07XG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIF9kZWZhdWx0O1xufTtcblxuTGlzdC5rZXltZW1iZXJfX3FtYXJrX18gPSBmdW5jdGlvbiAobGlzdCwga2V5LCBwb3NpdGlvbikge1xuXG4gIGZvciAobGV0IGkgPSAwOyBpIDwgbGlzdC5sZW5ndGg7IGkrKykge1xuICAgIGlmIChLZXJuZWwubWF0Y2hfX3FtYXJrX18obGlzdFtpXVtwb3NpdGlvbl0sIGtleSkpIHtcbiAgICAgIHJldHVybiB0cnVlO1xuICAgIH1cbiAgfVxuXG4gIHJldHVybiBmYWxzZTtcbn07XG5cbkxpc3Qua2V5cmVwbGFjZSA9IGZ1bmN0aW9uIChsaXN0LCBrZXksIHBvc2l0aW9uLCBuZXdfdHVwbGUpIHtcbiAgbGV0IG5ld19saXN0ID0gW107XG5cbiAgZm9yIChsZXQgaSA9IDA7IGkgPCBsaXN0Lmxlbmd0aDsgaSsrKSB7XG4gICAgaWYgKCFLZXJuZWwubWF0Y2hfX3FtYXJrX18obGlzdFtpXVtwb3NpdGlvbl0sIGtleSkpIHtcbiAgICAgIG5ld19saXN0LnB1c2gobGlzdFtpXSk7XG4gICAgfSBlbHNlIHtcbiAgICAgIG5ld19saXN0LnB1c2gobmV3X3R1cGxlKTtcbiAgICB9XG4gIH1cblxuICByZXR1cm4gU3BlY2lhbEZvcm1zJDEubGlzdCguLi5uZXdfbGlzdCk7XG59O1xuXG5MaXN0LmtleXNvcnQgPSBmdW5jdGlvbiAobGlzdCwgcG9zaXRpb24pIHtcbiAgbGV0IG5ld19saXN0ID0gbGlzdDtcblxuICBuZXdfbGlzdC5zb3J0KGZ1bmN0aW9uIChhLCBiKSB7XG4gICAgaWYgKHBvc2l0aW9uID09PSAwKSB7XG4gICAgICBpZiAoYVtwb3NpdGlvbl0udmFsdWUgPCBiW3Bvc2l0aW9uXS52YWx1ZSkge1xuICAgICAgICByZXR1cm4gLTE7XG4gICAgICB9XG5cbiAgICAgIGlmIChhW3Bvc2l0aW9uXS52YWx1ZSA+IGJbcG9zaXRpb25dLnZhbHVlKSB7XG4gICAgICAgIHJldHVybiAxO1xuICAgICAgfVxuXG4gICAgICByZXR1cm4gMDtcbiAgICB9IGVsc2Uge1xuICAgICAgaWYgKGFbcG9zaXRpb25dIDwgYltwb3NpdGlvbl0pIHtcbiAgICAgICAgcmV0dXJuIC0xO1xuICAgICAgfVxuXG4gICAgICBpZiAoYVtwb3NpdGlvbl0gPiBiW3Bvc2l0aW9uXSkge1xuICAgICAgICByZXR1cm4gMTtcbiAgICAgIH1cblxuICAgICAgcmV0dXJuIDA7XG4gICAgfVxuICB9KTtcblxuICByZXR1cm4gU3BlY2lhbEZvcm1zJDEubGlzdCguLi5uZXdfbGlzdCk7XG59O1xuXG5MaXN0LmtleXN0b3JlID0gZnVuY3Rpb24gKGxpc3QsIGtleSwgcG9zaXRpb24sIG5ld190dXBsZSkge1xuICBsZXQgbmV3X2xpc3QgPSBbXTtcbiAgbGV0IHJlcGxhY2VkID0gZmFsc2U7XG5cbiAgZm9yIChsZXQgaSA9IDA7IGkgPCBsaXN0Lmxlbmd0aDsgaSsrKSB7XG4gICAgaWYgKCFLZXJuZWwubWF0Y2hfX3FtYXJrX18obGlzdFtpXVtwb3NpdGlvbl0sIGtleSkpIHtcbiAgICAgIG5ld19saXN0LnB1c2gobGlzdFtpXSk7XG4gICAgfSBlbHNlIHtcbiAgICAgIG5ld19saXN0LnB1c2gobmV3X3R1cGxlKTtcbiAgICAgIHJlcGxhY2VkID0gdHJ1ZTtcbiAgICB9XG4gIH1cblxuICBpZiAoIXJlcGxhY2VkKSB7XG4gICAgbmV3X2xpc3QucHVzaChuZXdfdHVwbGUpO1xuICB9XG5cbiAgcmV0dXJuIFNwZWNpYWxGb3JtcyQxLmxpc3QoLi4ubmV3X2xpc3QpO1xufTtcblxuTGlzdC5sYXN0ID0gZnVuY3Rpb24gKGxpc3QpIHtcbiAgcmV0dXJuIGxpc3RbbGlzdC5sZW5ndGggLSAxXTtcbn07XG5cbkxpc3QucmVwbGFjZV9hdCA9IGZ1bmN0aW9uIChsaXN0LCBpbmRleCwgdmFsdWUpIHtcbiAgbGV0IG5ld192YWx1ZSA9IFtdO1xuXG4gIGZvciAobGV0IGkgPSAwOyBpIDwgbGlzdC5sZW5ndGg7IGkrKykge1xuICAgIGlmIChpID09PSBpbmRleCkge1xuICAgICAgbmV3X3ZhbHVlLnB1c2godmFsdWUpO1xuICAgIH0gZWxzZSB7XG4gICAgICBuZXdfdmFsdWUucHVzaChsaXN0W2ldKTtcbiAgICB9XG4gIH1cblxuICByZXR1cm4gU3BlY2lhbEZvcm1zJDEubGlzdCguLi5uZXdfdmFsdWUpO1xufTtcblxuTGlzdC51cGRhdGVfYXQgPSBmdW5jdGlvbiAobGlzdCwgaW5kZXgsIGZ1bikge1xuICBsZXQgbmV3X3ZhbHVlID0gW107XG5cbiAgZm9yIChsZXQgaSA9IDA7IGkgPCBsaXN0LmNvdW50KCk7IGkrKykge1xuICAgIGlmIChpID09PSBpbmRleCkge1xuICAgICAgbmV3X3ZhbHVlLnB1c2goZnVuKGxpc3QuZ2V0KGkpKSk7XG4gICAgfSBlbHNlIHtcbiAgICAgIG5ld192YWx1ZS5wdXNoKGxpc3QuZ2V0KGkpKTtcbiAgICB9XG4gIH1cblxuICByZXR1cm4gbmV3X3ZhbHVlO1xufTtcblxuTGlzdC53cmFwID0gZnVuY3Rpb24gKGxpc3QpIHtcbiAgaWYgKEtlcm5lbC5pc19saXN0KGxpc3QpKSB7XG4gICAgcmV0dXJuIGxpc3Q7XG4gIH0gZWxzZSBpZiAobGlzdCA9PSBudWxsKSB7XG4gICAgcmV0dXJuIFNwZWNpYWxGb3JtcyQxLmxpc3QoKTtcbiAgfSBlbHNlIHtcbiAgICByZXR1cm4gU3BlY2lhbEZvcm1zJDEubGlzdChsaXN0KTtcbiAgfVxufTtcblxuTGlzdC56aXAgPSBmdW5jdGlvbiAobGlzdF9vZl9saXN0cykge1xuICBpZiAobGlzdF9vZl9saXN0cy5sZW5ndGggPT09IDApIHtcbiAgICByZXR1cm4gU3BlY2lhbEZvcm1zJDEubGlzdCgpO1xuICB9XG5cbiAgbGV0IG5ld192YWx1ZSA9IFtdO1xuICBsZXQgc21hbGxlc3RfbGVuZ3RoID0gbGlzdF9vZl9saXN0c1swXTtcblxuICBmb3IgKGxldCB4IG9mIGxpc3Rfb2ZfbGlzdHMpIHtcbiAgICBpZiAoeC5sZW5ndGggPCBzbWFsbGVzdF9sZW5ndGgpIHtcbiAgICAgIHNtYWxsZXN0X2xlbmd0aCA9IHgubGVuZ3RoO1xuICAgIH1cbiAgfVxuXG4gIGZvciAobGV0IGkgPSAwOyBpIDwgc21hbGxlc3RfbGVuZ3RoOyBpKyspIHtcbiAgICBsZXQgY3VycmVudF92YWx1ZSA9IFtdO1xuICAgIGZvciAobGV0IGogPSAwOyBqIDwgbGlzdF9vZl9saXN0cy5sZW5ndGg7IGorKykge1xuICAgICAgY3VycmVudF92YWx1ZS5wdXNoKGxpc3Rfb2ZfbGlzdHNbal1baV0pO1xuICAgIH1cblxuICAgIG5ld192YWx1ZS5wdXNoKG5ldyBUdXBsZSQxKC4uLmN1cnJlbnRfdmFsdWUpKTtcbiAgfVxuXG4gIHJldHVybiBTcGVjaWFsRm9ybXMkMS5saXN0KC4uLm5ld192YWx1ZSk7XG59O1xuXG5MaXN0LnRvX3R1cGxlID0gZnVuY3Rpb24gKGxpc3QpIHtcbiAgcmV0dXJuIG5ldyBUdXBsZSQxKC4uLmxpc3QpO1xufTtcblxuTGlzdC5hcHBlbmQgPSBmdW5jdGlvbiAobGlzdCwgdmFsdWUpIHtcbiAgcmV0dXJuIFNwZWNpYWxGb3JtcyQxLmxpc3QoLi4ubGlzdC5jb25jYXQoW3ZhbHVlXSkpO1xufTtcblxuTGlzdC5wcmVwZW5kID0gZnVuY3Rpb24gKGxpc3QsIHZhbHVlKSB7XG4gIHJldHVybiBTcGVjaWFsRm9ybXMkMS5saXN0KC4uLlt2YWx1ZV0uY29uY2F0KGxpc3QpKTtcbn07XG5cbkxpc3QuY29uY2F0ID0gZnVuY3Rpb24gKGxlZnQsIHJpZ2h0KSB7XG4gIHJldHVybiBsZWZ0LmNvbmNhdChyaWdodCk7XG59O1xuXG5sZXQgS2V5d29yZCA9IHt9O1xuXG5LZXl3b3JkLmhhc19rZXlfX3FtYXJrX18gPSBmdW5jdGlvbiAoa2V5d29yZHMsIGtleSkge1xuICBmb3IgKGxldCBrZXl3b3JkIG9mIGtleXdvcmRzKSB7XG4gICAgaWYgKEtlcm5lbC5lbGVtKGtleXdvcmQsIDApID09IGtleSkge1xuICAgICAgcmV0dXJuIHRydWU7XG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIGZhbHNlO1xufTtcblxuS2V5d29yZC5nZXQgPSBmdW5jdGlvbiAoa2V5d29yZHMsIGtleSwgdGhlX2RlZmF1bHQgPSBudWxsKSB7XG4gIGZvciAobGV0IGtleXdvcmQgb2Yga2V5d29yZHMpIHtcbiAgICBpZiAoS2VybmVsLmVsZW0oa2V5d29yZCwgMCkgPT0ga2V5KSB7XG4gICAgICByZXR1cm4gS2VybmVsLmVsZW0oa2V5d29yZCwgMSk7XG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIHRoZV9kZWZhdWx0O1xufTtcblxuZnVuY3Rpb24gYm5vdChleHByKSB7XG4gIHJldHVybiB+ZXhwcjtcbn1cblxuZnVuY3Rpb24gYmFuZChsZWZ0LCByaWdodCkge1xuICByZXR1cm4gbGVmdCAmIHJpZ2h0O1xufVxuXG5mdW5jdGlvbiBib3IobGVmdCwgcmlnaHQpIHtcbiAgcmV0dXJuIGxlZnQgfCByaWdodDtcbn1cblxuZnVuY3Rpb24gYnNsKGxlZnQsIHJpZ2h0KSB7XG4gIHJldHVybiBsZWZ0IDw8IHJpZ2h0O1xufVxuXG5mdW5jdGlvbiBic3IobGVmdCwgcmlnaHQpIHtcbiAgcmV0dXJuIGxlZnQgPj4gcmlnaHQ7XG59XG5cbmZ1bmN0aW9uIGJ4b3IobGVmdCwgcmlnaHQpIHtcbiAgcmV0dXJuIGxlZnQgXiByaWdodDtcbn1cblxudmFyIGJpdHdpc2UgPSB7XG4gIGJub3QsXG4gIGJhbmQsXG4gIGJvcixcbiAgYnNsLFxuICBic3IsXG4gIGJ4b3Jcbn07XG5cbmZ1bmN0aW9uIF9fbmV3X18oKSB7XG4gIHJldHVybiBTcGVjaWFsRm9ybXMkMS5tYXAoe30pO1xufVxuXG5mdW5jdGlvbiBrZXlzKG1hcCkge1xuICByZXR1cm4gRnVuY3Rpb25zLmdldF9vYmplY3Rfa2V5cyhtYXApO1xufVxuXG5mdW5jdGlvbiBzaXplKG1hcCkge1xuICByZXR1cm4ga2V5cyhtYXApLmxlbmd0aDtcbn1cblxuZnVuY3Rpb24gdG9fbGlzdChtYXApIHtcbiAgbGV0IG1hcF9rZXlzID0ga2V5cyhtYXApO1xuICBsZXQgbGlzdCA9IFtdO1xuXG4gIGZvciAobGV0IGtleSBvZiBtYXBfa2V5cykge1xuICAgIGxpc3QucHVzaChuZXcgVHVwbGUkMShrZXksIG1hcFtrZXldKSk7XG4gIH1cblxuICByZXR1cm4gTGlzdCQxKC4uLmxpc3QpO1xufVxuXG5mdW5jdGlvbiB2YWx1ZXMobWFwKSB7XG4gIGxldCBtYXBfa2V5cyA9IGtleXMobWFwKTtcbiAgbGV0IGxpc3QgPSBbXTtcblxuICBmb3IgKGxldCBrZXkgb2YgbWFwX2tleXMpIHtcbiAgICBsaXN0LnB1c2gobWFwW2tleV0pO1xuICB9XG5cbiAgcmV0dXJuIExpc3QkMSguLi5saXN0KTtcbn1cblxuZnVuY3Rpb24gZnJvbV9zdHJ1Y3Qoc3RydWN0KSB7XG4gIGxldCBtYXAgPSBPYmplY3QuYXNzaWduKHt9LCBzdHJ1Y3QpO1xuICBkZWxldGUgbWFwW1N5bWJvbC5mb3IoXCJfX3N0cnVjdF9fXCIpXTtcblxuICByZXR1cm4gU3BlY2lhbEZvcm1zJDEubWFwKG1hcCk7XG59XG5cbmZ1bmN0aW9uIF9fZGVsZXRlX18obWFwLCBrZXkpIHtcbiAgbGV0IG5ld19tYXAgPSBPYmplY3QuYXNzaWduKHt9LCBtYXApO1xuXG4gIGRlbGV0ZSBuZXdfbWFwW2tleV07XG5cbiAgcmV0dXJuIFNwZWNpYWxGb3JtcyQxLm1hcChuZXdfbWFwKTtcbn1cblxuZnVuY3Rpb24gZXF1YWxfX3FtYXJrX18obWFwMSwgbWFwMikge1xuICByZXR1cm4gbWFwMSA9PT0gbWFwMjtcbn1cblxuZnVuY3Rpb24gZmV0Y2hfX2VtYXJrX18obWFwLCBrZXkpIHtcbiAgaWYgKGtleSBpbiBtYXApIHtcbiAgICByZXR1cm4gbWFwW2tleV07XG4gIH1cblxuICB0aHJvdyBuZXcgRXJyb3IoXCJLZXkgbm90IGZvdW5kLlwiKTtcbn1cblxuZnVuY3Rpb24gZmV0Y2gobWFwLCBrZXkpIHtcbiAgaWYgKGtleSBpbiBtYXApIHtcbiAgICByZXR1cm4gbmV3IFR1cGxlJDEoU3ltYm9sLmZvcihcIm9rXCIpLCBtYXBba2V5XSk7XG4gIH1cblxuICByZXR1cm4gU3ltYm9sLmZvcihcImVycm9yXCIpO1xufVxuXG5mdW5jdGlvbiBoYXNfa2V5X19xbWFya19fKG1hcCwga2V5KSB7XG4gIHJldHVybiBrZXkgaW4gbWFwO1xufVxuXG5mdW5jdGlvbiBzcGxpdChtYXAsIGtleXMpIHtcbiAgbGV0IHNwbGl0MSA9IHt9O1xuICBsZXQgc3BsaXQyID0ge307XG5cbiAgZm9yIChsZXQga2V5IG9mIEZ1bmN0aW9ucy5nZXRfb2JqZWN0X2tleXMobWFwKSkge1xuICAgIGlmIChrZXlzLmluZGV4T2Yoa2V5KSA+IC0xKSB7XG4gICAgICBzcGxpdDFba2V5XSA9IG1hcFtrZXldO1xuICAgIH0gZWxzZSB7XG4gICAgICBzcGxpdDJba2V5XSA9IG1hcFtrZXldO1xuICAgIH1cbiAgfVxuXG4gIHJldHVybiBuZXcgVHVwbGUkMShTcGVjaWFsRm9ybXMkMS5tYXAoc3BsaXQxKSwgU3BlY2lhbEZvcm1zJDEubWFwKHNwbGl0MikpO1xufVxuXG5mdW5jdGlvbiB0YWtlKG1hcCwga2V5cykge1xuICBsZXQgc3BsaXQxID0ge307XG5cbiAgZm9yIChsZXQga2V5IG9mIEZ1bmN0aW9ucy5nZXRfb2JqZWN0X2tleXMobWFwKSkge1xuICAgIGlmIChrZXlzLmluZGV4T2Yoa2V5KSA+IC0xKSB7XG4gICAgICBzcGxpdDFba2V5XSA9IG1hcFtrZXldO1xuICAgIH1cbiAgfVxuXG4gIHJldHVybiBTcGVjaWFsRm9ybXMkMS5tYXAoc3BsaXQxKTtcbn1cblxuZnVuY3Rpb24gZHJvcChtYXAsIGtleXMpIHtcbiAgbGV0IHNwbGl0MSA9IHt9O1xuXG4gIGZvciAobGV0IGtleSBvZiBGdW5jdGlvbnMuZ2V0X29iamVjdF9rZXlzKG1hcCkpIHtcbiAgICBpZiAoa2V5cy5pbmRleE9mKGtleSkgPT09IC0xKSB7XG4gICAgICBzcGxpdDFba2V5XSA9IG1hcFtrZXldO1xuICAgIH1cbiAgfVxuXG4gIHJldHVybiBTcGVjaWFsRm9ybXMkMS5tYXAoc3BsaXQxKTtcbn1cblxuZnVuY3Rpb24gcHV0X25ldyhtYXAsIGtleSwgdmFsdWUpIHtcbiAgaWYgKGtleSBpbiBtYXApIHtcbiAgICByZXR1cm4gbWFwO1xuICB9XG5cbiAgbGV0IG5ld19tYXAgPSBPYmplY3QuYXNzaWduKHt9LCBtYXApO1xuICBuZXdfbWFwW2tleV0gPSB2YWx1ZTtcblxuICByZXR1cm4gU3BlY2lhbEZvcm1zJDEubWFwKG5ld19tYXApO1xufVxuXG5mdW5jdGlvbiBwdXRfbmV3X2xhenkobWFwLCBrZXksIGZ1bikge1xuICBpZiAoa2V5IGluIG1hcCkge1xuICAgIHJldHVybiBtYXA7XG4gIH1cblxuICBsZXQgbmV3X21hcCA9IE9iamVjdC5hc3NpZ24oe30sIG1hcCk7XG4gIG5ld19tYXBba2V5XSA9IGZ1bigpO1xuXG4gIHJldHVybiBTcGVjaWFsRm9ybXMkMS5tYXAobmV3X21hcCk7XG59XG5cbmZ1bmN0aW9uIGdldF9hbmRfdXBkYXRlKG1hcCwga2V5LCBmdW4pIHtcbiAgaWYgKGtleSBpbiBtYXApIHtcbiAgICByZXR1cm4gbWFwO1xuICB9XG5cbiAgbGV0IG5ld19tYXAgPSBPYmplY3QuYXNzaWduKHt9LCBtYXApO1xuICBuZXdfbWFwW2tleV0gPSBmdW4obWFwW2tleV0pO1xuXG4gIHJldHVybiBTcGVjaWFsRm9ybXMkMS5tYXAobmV3X21hcCk7XG59XG5cbmZ1bmN0aW9uIHBvcF9sYXp5KG1hcCwga2V5LCBmdW4pIHtcbiAgaWYgKCFrZXkgaW4gbWFwKSB7XG4gICAgcmV0dXJuIG5ldyBUdXBsZSQxKGZ1bigpLCBtYXApO1xuICB9XG5cbiAgbGV0IG5ld19tYXAgPSBPYmplY3QuYXNzaWduKHt9LCBtYXApO1xuICBsZXQgdmFsdWUgPSBmdW4obmV3X21hcFtrZXldKTtcbiAgZGVsZXRlIG5ld19tYXBba2V5XTtcblxuICByZXR1cm4gbmV3IFR1cGxlJDEodmFsdWUsIG5ld19tYXApO1xufVxuXG5mdW5jdGlvbiBwb3AobWFwLCBrZXksIF9kZWZhdWx0ID0gbnVsbCkge1xuICBpZiAoIWtleSBpbiBtYXApIHtcbiAgICByZXR1cm4gbmV3IFR1cGxlJDEoX2RlZmF1bHQsIG1hcCk7XG4gIH1cblxuICBsZXQgbmV3X21hcCA9IE9iamVjdC5hc3NpZ24oe30sIG1hcCk7XG4gIGxldCB2YWx1ZSA9IG5ld19tYXBba2V5XTtcbiAgZGVsZXRlIG5ld19tYXBba2V5XTtcblxuICByZXR1cm4gbmV3IFR1cGxlJDEodmFsdWUsIG5ld19tYXApO1xufVxuXG5mdW5jdGlvbiBnZXRfbGF6eShtYXAsIGtleSwgZnVuKSB7XG4gIGlmICgha2V5IGluIG1hcCkge1xuICAgIHJldHVybiBmdW4oKTtcbiAgfVxuXG4gIHJldHVybiBmdW4obWFwW2tleV0pO1xufVxuXG5mdW5jdGlvbiBnZXQobWFwLCBrZXksIF9kZWZhdWx0ID0gbnVsbCkge1xuICBpZiAoIWtleSBpbiBtYXApIHtcbiAgICByZXR1cm4gX2RlZmF1bHQ7XG4gIH1cblxuICByZXR1cm4gbWFwW2tleV07XG59XG5cbmZ1bmN0aW9uIHB1dChtYXAsIGtleSwgdmFsKSB7XG4gIGxldCBuZXdfbWFwID0gT2JqZWN0KHt9LCBtYXApO1xuICBuZXdfbWFwW2tleV0gPSB2YWw7XG5cbiAgcmV0dXJuIFNwZWNpYWxGb3JtcyQxLm1hcChuZXdfbWFwKTtcbn1cblxuZnVuY3Rpb24gdXBkYXRlX19lbWFya19fKG1hcCwga2V5LCBmdW4pIHtcbiAgaWYgKCFrZXkgaW4gbWFwKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKFwiS2V5IG5vdCBmb3VuZFwiKTtcbiAgfVxuXG4gIGxldCBuZXdfbWFwID0gT2JqZWN0KHt9LCBtYXApO1xuICBuZXdfbWFwW2tleV0gPSBmdW4obWFwW2tleV0pO1xuXG4gIHJldHVybiBTcGVjaWFsRm9ybXMkMS5tYXAobmV3X21hcCk7XG59XG5cbmZ1bmN0aW9uIHVwZGF0ZShtYXAsIGtleSwgaW5pdGlhbCwgZnVuKSB7XG4gIGxldCBuZXdfbWFwID0gT2JqZWN0KHt9LCBtYXApO1xuXG4gIGlmICgha2V5IGluIG1hcCkge1xuICAgIG5ld19tYXBba2V5XSA9IGluaXRpYWw7XG4gIH0gZWxzZSB7XG4gICAgbmV3X21hcFtrZXldID0gZnVuKG1hcFtrZXldKTtcbiAgfVxuXG4gIHJldHVybiBTcGVjaWFsRm9ybXMkMS5tYXAobmV3X21hcCk7XG59XG5cbnZhciBtYXAgPSB7XG4gIG5ldzogX19uZXdfXyxcbiAga2V5cyxcbiAgc2l6ZSxcbiAgdG9fbGlzdCxcbiAgdmFsdWVzLFxuICBmcm9tX3N0cnVjdCxcbiAgZGVsZXRlOiBfX2RlbGV0ZV9fLFxuICBkcm9wLFxuICBlcXVhbF9fcW1hcmtfXyxcbiAgZmV0Y2hfX2VtYXJrX18sXG4gIGZldGNoLFxuICBoYXNfa2V5X19xbWFya19fLFxuICBzcGxpdCxcbiAgdGFrZSxcbiAgcHV0X25ldyxcbiAgcHV0X25ld19sYXp5LFxuICBnZXRfYW5kX3VwZGF0ZSxcbiAgcG9wX2xhenksXG4gIHBvcCxcbiAgZ2V0X2xhenksXG4gIGdldCxcbiAgcHV0LFxuICB1cGRhdGVfX2VtYXJrX18sXG4gIHVwZGF0ZVxufTtcblxuZnVuY3Rpb24gX19uZXdfXyQxKCkge1xuICByZXR1cm4gU3BlY2lhbEZvcm1zJDEubWFwKHsgW1N5bWJvbC5mb3IoJ19fc3RydWN0X18nKV06IFN5bWJvbC5mb3IoJ01hcFNldCcpLCBzZXQ6IExpc3QkMSgpIH0pO1xufVxuXG5mdW5jdGlvbiBzaXplJDEobWFwKSB7XG4gIHJldHVybiBtYXAuc2V0Lmxlbmd0aDtcbn1cblxuZnVuY3Rpb24gdG9fbGlzdCQxKG1hcCkge1xuICByZXR1cm4gbWFwLnNldDtcbn1cblxuZnVuY3Rpb24gX19kZWxldGVfXyQxKHNldCwgdGVybSkge1xuICBsZXQgbmV3X2xpc3QgPSBMaXN0LmRlbGV0ZShzZXQuc2V0LCB0ZXJtKTtcblxuICBsZXQgbmV3X21hcCA9IE9iamVjdC5hc3NpZ24oe30sIHNldCk7XG4gIG5ld19tYXAuc2V0ID0gbmV3X2xpc3Q7XG4gIHJldHVybiBTcGVjaWFsRm9ybXMkMS5tYXAobmV3X21hcCk7XG59XG5cbmZ1bmN0aW9uIHB1dCQxKHNldCwgdGVybSkge1xuICBpZiAoc2V0LnNldC5pbmRleE9mKHRlcm0pID09PSAtMSkge1xuICAgIGxldCBuZXdfbGlzdCA9IExpc3QuYXBwZW5kKHNldC5zZXQsIHRlcm0pO1xuXG4gICAgbGV0IG5ld19tYXAgPSBPYmplY3QuYXNzaWduKHt9LCBzZXQpO1xuICAgIG5ld19tYXAuc2V0ID0gbmV3X2xpc3Q7XG4gICAgcmV0dXJuIFNwZWNpYWxGb3JtcyQxLm1hcChuZXdfbWFwKTtcbiAgfVxuXG4gIHJldHVybiBzZXQ7XG59XG5cbmZ1bmN0aW9uIGRpZmZlcmVuY2Uoc2V0MSwgc2V0Mikge1xuICBsZXQgbmV3X21hcCA9IE9iamVjdC5hc3NpZ24oe30sIHNldDEpO1xuXG4gIGZvciAobGV0IHZhbCBvZiBzZXQxLnNldCkge1xuICAgIGlmIChtZW1iZXJfX3FtYXJrX18oc2V0MiwgdmFsKSkge1xuICAgICAgbmV3X21hcC5zZXQgPSBMaXN0LmRlbGV0ZShuZXdfbWFwLnNldCwgdmFsKTtcbiAgICB9XG4gIH1cblxuICByZXR1cm4gU3BlY2lhbEZvcm1zJDEubWFwKG5ld19tYXApO1xufVxuXG5mdW5jdGlvbiBpbnRlcnNlY3Rpb24oc2V0MSwgc2V0Mikge1xuICBsZXQgbmV3X21hcCA9IE9iamVjdC5hc3NpZ24oe30sIHNldDEpO1xuXG4gIGZvciAobGV0IHZhbCBvZiBzZXQxLnNldCkge1xuICAgIGlmICghbWVtYmVyX19xbWFya19fKHNldDIsIHZhbCkpIHtcbiAgICAgIG5ld19tYXAuc2V0ID0gTGlzdC5kZWxldGUobmV3X21hcC5zZXQsIHZhbCk7XG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIFNwZWNpYWxGb3JtcyQxLm1hcChuZXdfbWFwKTtcbn1cblxuZnVuY3Rpb24gdW5pb24oc2V0MSwgc2V0Mikge1xuICBsZXQgbmV3X21hcCA9IHNldDE7XG5cbiAgZm9yIChsZXQgdmFsIG9mIHNldDIuc2V0KSB7XG4gICAgbmV3X21hcCA9IHB1dCQxKG5ld19tYXAsIHZhbCk7XG4gIH1cblxuICByZXR1cm4gU3BlY2lhbEZvcm1zJDEubWFwKG5ld19tYXApO1xufVxuXG5mdW5jdGlvbiBkaXNqb2luX19xbWFya19fKHNldDEsIHNldDIpIHtcbiAgZm9yIChsZXQgdmFsIG9mIHNldDEuc2V0KSB7XG4gICAgaWYgKG1lbWJlcl9fcW1hcmtfXyhzZXQyLCB2YWwpKSB7XG4gICAgICByZXR1cm4gZmFsc2U7XG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIHRydWU7XG59XG5cbmZ1bmN0aW9uIG1lbWJlcl9fcW1hcmtfXyhzZXQsIHZhbHVlKSB7XG4gIHJldHVybiBzZXQuc2V0LmluZGV4T2YodmFsdWUpID49IDA7XG59XG5cbmZ1bmN0aW9uIGVxdWFsX19xbWFya19fJDEoc2V0MSwgc2V0Mikge1xuICByZXR1cm4gc2V0MS5zZXQgPT09IHNldDIuc2V0O1xufVxuXG5mdW5jdGlvbiBzdWJzZXRfX3FtYXJrX18oc2V0MSwgc2V0Mikge1xuICBmb3IgKGxldCB2YWwgb2Ygc2V0MS5zZXQpIHtcbiAgICBpZiAoIW1lbWJlcl9fcW1hcmtfXyhzZXQyLCB2YWwpKSB7XG4gICAgICByZXR1cm4gZmFsc2U7XG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIHRydWU7XG59XG5cbnZhciBtYXBfc2V0ID0ge1xuICBuZXc6IF9fbmV3X18kMSxcbiAgc2l6ZTogc2l6ZSQxLFxuICB0b19saXN0OiB0b19saXN0JDEsXG4gIGRpc2pvaW5fX3FtYXJrX18sXG4gIGRlbGV0ZTogX19kZWxldGVfXyQxLFxuICBzdWJzZXRfX3FtYXJrX18sXG4gIGVxdWFsX19xbWFya19fOiBlcXVhbF9fcW1hcmtfXyQxLFxuICBtZW1iZXJfX3FtYXJrX18sXG4gIHB1dDogcHV0JDEsXG4gIHVuaW9uLFxuICBpbnRlcnNlY3Rpb24sXG4gIGRpZmZlcmVuY2Vcbn07XG5cbmxldCBWaXJ0dWFsRE9NID0gKGZ1bmN0aW9uIChlKSB7XG4gICAgcmV0dXJuIGUoKTtcbn0pKGZ1bmN0aW9uICgpIHtcbiAgICB2YXIgZGVmaW5lLCBtb2R1bGUsIGV4cG9ydHM7XG4gICAgcmV0dXJuIChmdW5jdGlvbiBlKHQsIG4sIHIpIHtcbiAgICAgICAgZnVuY3Rpb24gcyhvLCB1KSB7XG4gICAgICAgICAgICBpZiAoIW5bb10pIHtcbiAgICAgICAgICAgICAgICBpZiAoIXRbb10pIHtcbiAgICAgICAgICAgICAgICAgICAgdmFyIGEgPSB0eXBlb2YgcmVxdWlyZSA9PSBcImZ1bmN0aW9uXCIgJiYgcmVxdWlyZTtcbiAgICAgICAgICAgICAgICAgICAgaWYgKCF1ICYmIGEpIHJldHVybiBhKG8sICEwKTtcbiAgICAgICAgICAgICAgICAgICAgaWYgKGkpIHJldHVybiBpKG8sICEwKTtcbiAgICAgICAgICAgICAgICAgICAgdmFyIGYgPSBuZXcgRXJyb3IoXCJDYW5ub3QgZmluZCBtb2R1bGUgJ1wiICsgbyArIFwiJ1wiKTtcbiAgICAgICAgICAgICAgICAgICAgdGhyb3cgKGYuY29kZSA9IFwiTU9EVUxFX05PVF9GT1VORFwiLCBmKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgdmFyIGwgPSBuW29dID0ge1xuICAgICAgICAgICAgICAgICAgICBleHBvcnRzOiB7fVxuICAgICAgICAgICAgICAgIH07XG4gICAgICAgICAgICAgICAgdFtvXVswXS5jYWxsKGwuZXhwb3J0cywgZnVuY3Rpb24gKGUpIHtcbiAgICAgICAgICAgICAgICAgICAgdmFyIG4gPSB0W29dWzFdW2VdO1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gcyhuID8gbiA6IGUpO1xuICAgICAgICAgICAgICAgIH0sIGwsIGwuZXhwb3J0cywgZSwgdCwgbiwgcik7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXR1cm4gbltvXS5leHBvcnRzO1xuICAgICAgICB9XG4gICAgICAgIHZhciBpID0gdHlwZW9mIHJlcXVpcmUgPT0gXCJmdW5jdGlvblwiICYmIHJlcXVpcmU7XG4gICAgICAgIGZvciAodmFyIG8gPSAwOyBvIDwgci5sZW5ndGg7IG8rKykgcyhyW29dKTtcbiAgICAgICAgcmV0dXJuIHM7XG4gICAgfSkoe1xuICAgICAgICAxOiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge1xuXG4gICAgICAgICAgICB2YXIgY3JlYXRlRWxlbWVudCA9IHJlcXVpcmUoXCIuL3Zkb20vY3JlYXRlLWVsZW1lbnQuanNcIik7XG5cbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gY3JlYXRlRWxlbWVudDtcbiAgICAgICAgfSwgeyBcIi4vdmRvbS9jcmVhdGUtZWxlbWVudC5qc1wiOiAxNSB9XSwgMjogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHtcbiAgICAgICAgICAgIHZhciBkaWZmID0gcmVxdWlyZShcIi4vdnRyZWUvZGlmZi5qc1wiKTtcblxuICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBkaWZmO1xuICAgICAgICB9LCB7IFwiLi92dHJlZS9kaWZmLmpzXCI6IDM1IH1dLCAzOiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge1xuICAgICAgICAgICAgdmFyIGggPSByZXF1aXJlKFwiLi92aXJ0dWFsLWh5cGVyc2NyaXB0L2luZGV4LmpzXCIpO1xuXG4gICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IGg7XG4gICAgICAgIH0sIHsgXCIuL3ZpcnR1YWwtaHlwZXJzY3JpcHQvaW5kZXguanNcIjogMjIgfV0sIDQ6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICB2YXIgZGlmZiA9IHJlcXVpcmUoXCIuL2RpZmYuanNcIik7XG4gICAgICAgICAgICB2YXIgcGF0Y2ggPSByZXF1aXJlKFwiLi9wYXRjaC5qc1wiKTtcbiAgICAgICAgICAgIHZhciBoID0gcmVxdWlyZShcIi4vaC5qc1wiKTtcbiAgICAgICAgICAgIHZhciBjcmVhdGUgPSByZXF1aXJlKFwiLi9jcmVhdGUtZWxlbWVudC5qc1wiKTtcbiAgICAgICAgICAgIHZhciBWTm9kZSA9IHJlcXVpcmUoXCIuL3Zub2RlL3Zub2RlLmpzXCIpO1xuICAgICAgICAgICAgdmFyIFZUZXh0ID0gcmVxdWlyZShcIi4vdm5vZGUvdnRleHQuanNcIik7XG5cbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0ge1xuICAgICAgICAgICAgICAgIGRpZmY6IGRpZmYsXG4gICAgICAgICAgICAgICAgcGF0Y2g6IHBhdGNoLFxuICAgICAgICAgICAgICAgIGg6IGgsXG4gICAgICAgICAgICAgICAgY3JlYXRlOiBjcmVhdGUsXG4gICAgICAgICAgICAgICAgVk5vZGU6IFZOb2RlLFxuICAgICAgICAgICAgICAgIFZUZXh0OiBWVGV4dFxuICAgICAgICAgICAgfTtcbiAgICAgICAgfSwgeyBcIi4vY3JlYXRlLWVsZW1lbnQuanNcIjogMSwgXCIuL2RpZmYuanNcIjogMiwgXCIuL2guanNcIjogMywgXCIuL3BhdGNoLmpzXCI6IDEzLCBcIi4vdm5vZGUvdm5vZGUuanNcIjogMzEsIFwiLi92bm9kZS92dGV4dC5qc1wiOiAzMyB9XSwgNTogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHtcbiAgICAgICAgICAgIC8qIVxuICAgICAgICAgICAgICogQ3Jvc3MtQnJvd3NlciBTcGxpdCAxLjEuMVxuICAgICAgICAgICAgICogQ29weXJpZ2h0IDIwMDctMjAxMiBTdGV2ZW4gTGV2aXRoYW4gPHN0ZXZlbmxldml0aGFuLmNvbT5cbiAgICAgICAgICAgICAqIEF2YWlsYWJsZSB1bmRlciB0aGUgTUlUIExpY2Vuc2VcbiAgICAgICAgICAgICAqIEVDTUFTY3JpcHQgY29tcGxpYW50LCB1bmlmb3JtIGNyb3NzLWJyb3dzZXIgc3BsaXQgbWV0aG9kXG4gICAgICAgICAgICAgKi9cblxuICAgICAgICAgICAgLyoqXG4gICAgICAgICAgICAgKiBTcGxpdHMgYSBzdHJpbmcgaW50byBhbiBhcnJheSBvZiBzdHJpbmdzIHVzaW5nIGEgcmVnZXggb3Igc3RyaW5nIHNlcGFyYXRvci4gTWF0Y2hlcyBvZiB0aGVcbiAgICAgICAgICAgICAqIHNlcGFyYXRvciBhcmUgbm90IGluY2x1ZGVkIGluIHRoZSByZXN1bHQgYXJyYXkuIEhvd2V2ZXIsIGlmIGBzZXBhcmF0b3JgIGlzIGEgcmVnZXggdGhhdCBjb250YWluc1xuICAgICAgICAgICAgICogY2FwdHVyaW5nIGdyb3VwcywgYmFja3JlZmVyZW5jZXMgYXJlIHNwbGljZWQgaW50byB0aGUgcmVzdWx0IGVhY2ggdGltZSBgc2VwYXJhdG9yYCBpcyBtYXRjaGVkLlxuICAgICAgICAgICAgICogRml4ZXMgYnJvd3NlciBidWdzIGNvbXBhcmVkIHRvIHRoZSBuYXRpdmUgYFN0cmluZy5wcm90b3R5cGUuc3BsaXRgIGFuZCBjYW4gYmUgdXNlZCByZWxpYWJseVxuICAgICAgICAgICAgICogY3Jvc3MtYnJvd3Nlci5cbiAgICAgICAgICAgICAqIEBwYXJhbSB7U3RyaW5nfSBzdHIgU3RyaW5nIHRvIHNwbGl0LlxuICAgICAgICAgICAgICogQHBhcmFtIHtSZWdFeHB8U3RyaW5nfSBzZXBhcmF0b3IgUmVnZXggb3Igc3RyaW5nIHRvIHVzZSBmb3Igc2VwYXJhdGluZyB0aGUgc3RyaW5nLlxuICAgICAgICAgICAgICogQHBhcmFtIHtOdW1iZXJ9IFtsaW1pdF0gTWF4aW11bSBudW1iZXIgb2YgaXRlbXMgdG8gaW5jbHVkZSBpbiB0aGUgcmVzdWx0IGFycmF5LlxuICAgICAgICAgICAgICogQHJldHVybnMge0FycmF5fSBBcnJheSBvZiBzdWJzdHJpbmdzLlxuICAgICAgICAgICAgICogQGV4YW1wbGVcbiAgICAgICAgICAgICAqXG4gICAgICAgICAgICAgKiAvLyBCYXNpYyB1c2VcbiAgICAgICAgICAgICAqIHNwbGl0KCdhIGIgYyBkJywgJyAnKTtcbiAgICAgICAgICAgICAqIC8vIC0+IFsnYScsICdiJywgJ2MnLCAnZCddXG4gICAgICAgICAgICAgKlxuICAgICAgICAgICAgICogLy8gV2l0aCBsaW1pdFxuICAgICAgICAgICAgICogc3BsaXQoJ2EgYiBjIGQnLCAnICcsIDIpO1xuICAgICAgICAgICAgICogLy8gLT4gWydhJywgJ2InXVxuICAgICAgICAgICAgICpcbiAgICAgICAgICAgICAqIC8vIEJhY2tyZWZlcmVuY2VzIGluIHJlc3VsdCBhcnJheVxuICAgICAgICAgICAgICogc3BsaXQoJy4ud29yZDEgd29yZDIuLicsIC8oW2Etel0rKShcXGQrKS9pKTtcbiAgICAgICAgICAgICAqIC8vIC0+IFsnLi4nLCAnd29yZCcsICcxJywgJyAnLCAnd29yZCcsICcyJywgJy4uJ11cbiAgICAgICAgICAgICAqL1xuICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSAoZnVuY3Rpb24gc3BsaXQodW5kZWYpIHtcblxuICAgICAgICAgICAgICAgIHZhciBuYXRpdmVTcGxpdCA9IFN0cmluZy5wcm90b3R5cGUuc3BsaXQsXG4gICAgICAgICAgICAgICAgICAgIGNvbXBsaWFudEV4ZWNOcGNnID0gLygpPz8vLmV4ZWMoXCJcIilbMV0gPT09IHVuZGVmLFxuXG4gICAgICAgICAgICAgICAgLy8gTlBDRzogbm9ucGFydGljaXBhdGluZyBjYXB0dXJpbmcgZ3JvdXBcbiAgICAgICAgICAgICAgICBzZWxmO1xuXG4gICAgICAgICAgICAgICAgc2VsZiA9IGZ1bmN0aW9uIChzdHIsIHNlcGFyYXRvciwgbGltaXQpIHtcbiAgICAgICAgICAgICAgICAgICAgLy8gSWYgYHNlcGFyYXRvcmAgaXMgbm90IGEgcmVnZXgsIHVzZSBgbmF0aXZlU3BsaXRgXG4gICAgICAgICAgICAgICAgICAgIGlmIChPYmplY3QucHJvdG90eXBlLnRvU3RyaW5nLmNhbGwoc2VwYXJhdG9yKSAhPT0gXCJbb2JqZWN0IFJlZ0V4cF1cIikge1xuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIG5hdGl2ZVNwbGl0LmNhbGwoc3RyLCBzZXBhcmF0b3IsIGxpbWl0KTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB2YXIgb3V0cHV0ID0gW10sXG4gICAgICAgICAgICAgICAgICAgICAgICBmbGFncyA9IChzZXBhcmF0b3IuaWdub3JlQ2FzZSA/IFwiaVwiIDogXCJcIikgKyAoc2VwYXJhdG9yLm11bHRpbGluZSA/IFwibVwiIDogXCJcIikgKyAoc2VwYXJhdG9yLmV4dGVuZGVkID8gXCJ4XCIgOiBcIlwiKSArIChzZXBhcmF0b3Iuc3RpY2t5ID8gXCJ5XCIgOiBcIlwiKSxcblxuICAgICAgICAgICAgICAgICAgICAvLyBGaXJlZm94IDMrXG4gICAgICAgICAgICAgICAgICAgIGxhc3RMYXN0SW5kZXggPSAwLFxuXG4gICAgICAgICAgICAgICAgICAgIC8vIE1ha2UgYGdsb2JhbGAgYW5kIGF2b2lkIGBsYXN0SW5kZXhgIGlzc3VlcyBieSB3b3JraW5nIHdpdGggYSBjb3B5XG4gICAgICAgICAgICAgICAgICAgIHNlcGFyYXRvciA9IG5ldyBSZWdFeHAoc2VwYXJhdG9yLnNvdXJjZSwgZmxhZ3MgKyBcImdcIiksXG4gICAgICAgICAgICAgICAgICAgICAgICBzZXBhcmF0b3IyLFxuICAgICAgICAgICAgICAgICAgICAgICAgbWF0Y2gsXG4gICAgICAgICAgICAgICAgICAgICAgICBsYXN0SW5kZXgsXG4gICAgICAgICAgICAgICAgICAgICAgICBsYXN0TGVuZ3RoO1xuICAgICAgICAgICAgICAgICAgICBzdHIgKz0gXCJcIjsgLy8gVHlwZS1jb252ZXJ0XG4gICAgICAgICAgICAgICAgICAgIGlmICghY29tcGxpYW50RXhlY05wY2cpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIERvZXNuJ3QgbmVlZCBmbGFncyBneSwgYnV0IHRoZXkgZG9uJ3QgaHVydFxuICAgICAgICAgICAgICAgICAgICAgICAgc2VwYXJhdG9yMiA9IG5ldyBSZWdFeHAoXCJeXCIgKyBzZXBhcmF0b3Iuc291cmNlICsgXCIkKD8hXFxcXHMpXCIsIGZsYWdzKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAvKiBWYWx1ZXMgZm9yIGBsaW1pdGAsIHBlciB0aGUgc3BlYzpcbiAgICAgICAgICAgICAgICAgICAgICogSWYgdW5kZWZpbmVkOiA0Mjk0OTY3Mjk1IC8vIE1hdGgucG93KDIsIDMyKSAtIDFcbiAgICAgICAgICAgICAgICAgICAgICogSWYgMCwgSW5maW5pdHksIG9yIE5hTjogMFxuICAgICAgICAgICAgICAgICAgICAgKiBJZiBwb3NpdGl2ZSBudW1iZXI6IGxpbWl0ID0gTWF0aC5mbG9vcihsaW1pdCk7IGlmIChsaW1pdCA+IDQyOTQ5NjcyOTUpIGxpbWl0IC09IDQyOTQ5NjcyOTY7XG4gICAgICAgICAgICAgICAgICAgICAqIElmIG5lZ2F0aXZlIG51bWJlcjogNDI5NDk2NzI5NiAtIE1hdGguZmxvb3IoTWF0aC5hYnMobGltaXQpKVxuICAgICAgICAgICAgICAgICAgICAgKiBJZiBvdGhlcjogVHlwZS1jb252ZXJ0LCB0aGVuIHVzZSB0aGUgYWJvdmUgcnVsZXNcbiAgICAgICAgICAgICAgICAgICAgICovXG4gICAgICAgICAgICAgICAgICAgIGxpbWl0ID0gbGltaXQgPT09IHVuZGVmID8gLTEgPj4+IDAgOiAvLyBNYXRoLnBvdygyLCAzMikgLSAxXG4gICAgICAgICAgICAgICAgICAgIGxpbWl0ID4+PiAwOyAvLyBUb1VpbnQzMihsaW1pdClcbiAgICAgICAgICAgICAgICAgICAgd2hpbGUgKG1hdGNoID0gc2VwYXJhdG9yLmV4ZWMoc3RyKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgLy8gYHNlcGFyYXRvci5sYXN0SW5kZXhgIGlzIG5vdCByZWxpYWJsZSBjcm9zcy1icm93c2VyXG4gICAgICAgICAgICAgICAgICAgICAgICBsYXN0SW5kZXggPSBtYXRjaC5pbmRleCArIG1hdGNoWzBdLmxlbmd0aDtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChsYXN0SW5kZXggPiBsYXN0TGFzdEluZGV4KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgb3V0cHV0LnB1c2goc3RyLnNsaWNlKGxhc3RMYXN0SW5kZXgsIG1hdGNoLmluZGV4KSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gRml4IGJyb3dzZXJzIHdob3NlIGBleGVjYCBtZXRob2RzIGRvbid0IGNvbnNpc3RlbnRseSByZXR1cm4gYHVuZGVmaW5lZGAgZm9yXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gbm9ucGFydGljaXBhdGluZyBjYXB0dXJpbmcgZ3JvdXBzXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKCFjb21wbGlhbnRFeGVjTnBjZyAmJiBtYXRjaC5sZW5ndGggPiAxKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1hdGNoWzBdLnJlcGxhY2Uoc2VwYXJhdG9yMiwgZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZm9yICh2YXIgaSA9IDE7IGkgPCBhcmd1bWVudHMubGVuZ3RoIC0gMjsgaSsrKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGFyZ3VtZW50c1tpXSA9PT0gdW5kZWYpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbWF0Y2hbaV0gPSB1bmRlZjtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAobWF0Y2gubGVuZ3RoID4gMSAmJiBtYXRjaC5pbmRleCA8IHN0ci5sZW5ndGgpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgQXJyYXkucHJvdG90eXBlLnB1c2guYXBwbHkob3V0cHV0LCBtYXRjaC5zbGljZSgxKSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxhc3RMZW5ndGggPSBtYXRjaFswXS5sZW5ndGg7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgbGFzdExhc3RJbmRleCA9IGxhc3RJbmRleDtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAob3V0cHV0Lmxlbmd0aCA+PSBsaW1pdCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoc2VwYXJhdG9yLmxhc3RJbmRleCA9PT0gbWF0Y2guaW5kZXgpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBzZXBhcmF0b3IubGFzdEluZGV4Kys7IC8vIEF2b2lkIGFuIGluZmluaXRlIGxvb3BcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICBpZiAobGFzdExhc3RJbmRleCA9PT0gc3RyLmxlbmd0aCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGxhc3RMZW5ndGggfHwgIXNlcGFyYXRvci50ZXN0KFwiXCIpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgb3V0cHV0LnB1c2goXCJcIik7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBvdXRwdXQucHVzaChzdHIuc2xpY2UobGFzdExhc3RJbmRleCkpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBvdXRwdXQubGVuZ3RoID4gbGltaXQgPyBvdXRwdXQuc2xpY2UoMCwgbGltaXQpIDogb3V0cHV0O1xuICAgICAgICAgICAgICAgIH07XG5cbiAgICAgICAgICAgICAgICByZXR1cm4gc2VsZjtcbiAgICAgICAgICAgIH0pKCk7XG4gICAgICAgIH0sIHt9XSwgNjogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHt9LCB7fV0sIDc6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICBcInVzZSBzdHJpY3RcIjtcblxuICAgICAgICAgICAgdmFyIE9uZVZlcnNpb25Db25zdHJhaW50ID0gcmVxdWlyZShcImluZGl2aWR1YWwvb25lLXZlcnNpb25cIik7XG5cbiAgICAgICAgICAgIHZhciBNWV9WRVJTSU9OID0gXCI3XCI7XG4gICAgICAgICAgICBPbmVWZXJzaW9uQ29uc3RyYWludChcImV2LXN0b3JlXCIsIE1ZX1ZFUlNJT04pO1xuXG4gICAgICAgICAgICB2YXIgaGFzaEtleSA9IFwiX19FVl9TVE9SRV9LRVlAXCIgKyBNWV9WRVJTSU9OO1xuXG4gICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IEV2U3RvcmU7XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIEV2U3RvcmUoZWxlbSkge1xuICAgICAgICAgICAgICAgIHZhciBoYXNoID0gZWxlbVtoYXNoS2V5XTtcblxuICAgICAgICAgICAgICAgIGlmICghaGFzaCkge1xuICAgICAgICAgICAgICAgICAgICBoYXNoID0gZWxlbVtoYXNoS2V5XSA9IHt9O1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHJldHVybiBoYXNoO1xuICAgICAgICAgICAgfVxuICAgICAgICB9LCB7IFwiaW5kaXZpZHVhbC9vbmUtdmVyc2lvblwiOiA5IH1dLCA4OiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge1xuICAgICAgICAgICAgKGZ1bmN0aW9uIChnbG9iYWwpIHtcbiAgICAgICAgICAgICAgICBcInVzZSBzdHJpY3RcIjtcblxuICAgICAgICAgICAgICAgIC8qZ2xvYmFsIHdpbmRvdywgZ2xvYmFsKi9cblxuICAgICAgICAgICAgICAgIHZhciByb290ID0gdHlwZW9mIHdpbmRvdyAhPT0gXCJ1bmRlZmluZWRcIiA/IHdpbmRvdyA6IHR5cGVvZiBnbG9iYWwgIT09IFwidW5kZWZpbmVkXCIgPyBnbG9iYWwgOiB7fTtcblxuICAgICAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gSW5kaXZpZHVhbDtcblxuICAgICAgICAgICAgICAgIGZ1bmN0aW9uIEluZGl2aWR1YWwoa2V5LCB2YWx1ZSkge1xuICAgICAgICAgICAgICAgICAgICBpZiAoa2V5IGluIHJvb3QpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiByb290W2tleV07XG4gICAgICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgICAgICByb290W2tleV0gPSB2YWx1ZTtcblxuICAgICAgICAgICAgICAgICAgICByZXR1cm4gdmFsdWU7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSkuY2FsbCh0aGlzLCB0eXBlb2YgZ2xvYmFsICE9PSBcInVuZGVmaW5lZFwiID8gZ2xvYmFsIDogdHlwZW9mIHNlbGYgIT09IFwidW5kZWZpbmVkXCIgPyBzZWxmIDogdHlwZW9mIHdpbmRvdyAhPT0gXCJ1bmRlZmluZWRcIiA/IHdpbmRvdyA6IHt9KTtcbiAgICAgICAgfSwge31dLCA5OiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge1xuICAgICAgICAgICAgXCJ1c2Ugc3RyaWN0XCI7XG5cbiAgICAgICAgICAgIHZhciBJbmRpdmlkdWFsID0gcmVxdWlyZShcIi4vaW5kZXguanNcIik7XG5cbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gT25lVmVyc2lvbjtcblxuICAgICAgICAgICAgZnVuY3Rpb24gT25lVmVyc2lvbihtb2R1bGVOYW1lLCB2ZXJzaW9uLCBkZWZhdWx0VmFsdWUpIHtcbiAgICAgICAgICAgICAgICB2YXIga2V5ID0gXCJfX0lORElWSURVQUxfT05FX1ZFUlNJT05fXCIgKyBtb2R1bGVOYW1lO1xuICAgICAgICAgICAgICAgIHZhciBlbmZvcmNlS2V5ID0ga2V5ICsgXCJfRU5GT1JDRV9TSU5HTEVUT05cIjtcblxuICAgICAgICAgICAgICAgIHZhciB2ZXJzaW9uVmFsdWUgPSBJbmRpdmlkdWFsKGVuZm9yY2VLZXksIHZlcnNpb24pO1xuXG4gICAgICAgICAgICAgICAgaWYgKHZlcnNpb25WYWx1ZSAhPT0gdmVyc2lvbikge1xuICAgICAgICAgICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoXCJDYW4gb25seSBoYXZlIG9uZSBjb3B5IG9mIFwiICsgbW9kdWxlTmFtZSArIFwiLlxcblwiICsgXCJZb3UgYWxyZWFkeSBoYXZlIHZlcnNpb24gXCIgKyB2ZXJzaW9uVmFsdWUgKyBcIiBpbnN0YWxsZWQuXFxuXCIgKyBcIlRoaXMgbWVhbnMgeW91IGNhbm5vdCBpbnN0YWxsIHZlcnNpb24gXCIgKyB2ZXJzaW9uKTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICByZXR1cm4gSW5kaXZpZHVhbChrZXksIGRlZmF1bHRWYWx1ZSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0sIHsgXCIuL2luZGV4LmpzXCI6IDggfV0sIDEwOiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge1xuICAgICAgICAgICAgKGZ1bmN0aW9uIChnbG9iYWwpIHtcbiAgICAgICAgICAgICAgICB2YXIgdG9wTGV2ZWwgPSB0eXBlb2YgZ2xvYmFsICE9PSBcInVuZGVmaW5lZFwiID8gZ2xvYmFsIDogdHlwZW9mIHdpbmRvdyAhPT0gXCJ1bmRlZmluZWRcIiA/IHdpbmRvdyA6IHt9O1xuICAgICAgICAgICAgICAgIHZhciBtaW5Eb2MgPSByZXF1aXJlKFwibWluLWRvY3VtZW50XCIpO1xuXG4gICAgICAgICAgICAgICAgaWYgKHR5cGVvZiBkb2N1bWVudCAhPT0gXCJ1bmRlZmluZWRcIikge1xuICAgICAgICAgICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IGRvY3VtZW50O1xuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciBkb2NjeSA9IHRvcExldmVsW1wiX19HTE9CQUxfRE9DVU1FTlRfQ0FDSEVANFwiXTtcblxuICAgICAgICAgICAgICAgICAgICBpZiAoIWRvY2N5KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBkb2NjeSA9IHRvcExldmVsW1wiX19HTE9CQUxfRE9DVU1FTlRfQ0FDSEVANFwiXSA9IG1pbkRvYztcbiAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gZG9jY3k7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSkuY2FsbCh0aGlzLCB0eXBlb2YgZ2xvYmFsICE9PSBcInVuZGVmaW5lZFwiID8gZ2xvYmFsIDogdHlwZW9mIHNlbGYgIT09IFwidW5kZWZpbmVkXCIgPyBzZWxmIDogdHlwZW9mIHdpbmRvdyAhPT0gXCJ1bmRlZmluZWRcIiA/IHdpbmRvdyA6IHt9KTtcbiAgICAgICAgfSwgeyBcIm1pbi1kb2N1bWVudFwiOiA2IH1dLCAxMTogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHtcbiAgICAgICAgICAgIFwidXNlIHN0cmljdFwiO1xuXG4gICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uIGlzT2JqZWN0KHgpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gdHlwZW9mIHggPT09IFwib2JqZWN0XCIgJiYgeCAhPT0gbnVsbDtcbiAgICAgICAgICAgIH07XG4gICAgICAgIH0sIHt9XSwgMTI6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICB2YXIgbmF0aXZlSXNBcnJheSA9IEFycmF5LmlzQXJyYXk7XG4gICAgICAgICAgICB2YXIgdG9TdHJpbmcgPSBPYmplY3QucHJvdG90eXBlLnRvU3RyaW5nO1xuXG4gICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IG5hdGl2ZUlzQXJyYXkgfHwgaXNBcnJheTtcblxuICAgICAgICAgICAgZnVuY3Rpb24gaXNBcnJheShvYmopIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gdG9TdHJpbmcuY2FsbChvYmopID09PSBcIltvYmplY3QgQXJyYXldXCI7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0sIHt9XSwgMTM6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICB2YXIgcGF0Y2ggPSByZXF1aXJlKFwiLi92ZG9tL3BhdGNoLmpzXCIpO1xuXG4gICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IHBhdGNoO1xuICAgICAgICB9LCB7IFwiLi92ZG9tL3BhdGNoLmpzXCI6IDE4IH1dLCAxNDogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHtcbiAgICAgICAgICAgIHZhciBpc09iamVjdCA9IHJlcXVpcmUoXCJpcy1vYmplY3RcIik7XG4gICAgICAgICAgICB2YXIgaXNIb29rID0gcmVxdWlyZShcIi4uL3Zub2RlL2lzLXZob29rLmpzXCIpO1xuXG4gICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IGFwcGx5UHJvcGVydGllcztcblxuICAgICAgICAgICAgZnVuY3Rpb24gYXBwbHlQcm9wZXJ0aWVzKG5vZGUsIHByb3BzLCBwcmV2aW91cykge1xuICAgICAgICAgICAgICAgIGZvciAodmFyIHByb3BOYW1lIGluIHByb3BzKSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciBwcm9wVmFsdWUgPSBwcm9wc1twcm9wTmFtZV07XG5cbiAgICAgICAgICAgICAgICAgICAgaWYgKHByb3BWYWx1ZSA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICByZW1vdmVQcm9wZXJ0eShub2RlLCBwcm9wTmFtZSwgcHJvcFZhbHVlLCBwcmV2aW91cyk7XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoaXNIb29rKHByb3BWYWx1ZSkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJlbW92ZVByb3BlcnR5KG5vZGUsIHByb3BOYW1lLCBwcm9wVmFsdWUsIHByZXZpb3VzKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChwcm9wVmFsdWUuaG9vaykge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHByb3BWYWx1ZS5ob29rKG5vZGUsIHByb3BOYW1lLCBwcmV2aW91cyA/IHByZXZpb3VzW3Byb3BOYW1lXSA6IHVuZGVmaW5lZCk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoaXNPYmplY3QocHJvcFZhbHVlKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHBhdGNoT2JqZWN0KG5vZGUsIHByb3BzLCBwcmV2aW91cywgcHJvcE5hbWUsIHByb3BWYWx1ZSk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIG5vZGVbcHJvcE5hbWVdID0gcHJvcFZhbHVlO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBmdW5jdGlvbiByZW1vdmVQcm9wZXJ0eShub2RlLCBwcm9wTmFtZSwgcHJvcFZhbHVlLCBwcmV2aW91cykge1xuICAgICAgICAgICAgICAgIGlmIChwcmV2aW91cykge1xuICAgICAgICAgICAgICAgICAgICB2YXIgcHJldmlvdXNWYWx1ZSA9IHByZXZpb3VzW3Byb3BOYW1lXTtcblxuICAgICAgICAgICAgICAgICAgICBpZiAoIWlzSG9vayhwcmV2aW91c1ZhbHVlKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHByb3BOYW1lID09PSBcImF0dHJpYnV0ZXNcIikge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZvciAodmFyIGF0dHJOYW1lIGluIHByZXZpb3VzVmFsdWUpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbm9kZS5yZW1vdmVBdHRyaWJ1dGUoYXR0ck5hbWUpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAocHJvcE5hbWUgPT09IFwic3R5bGVcIikge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZvciAodmFyIGkgaW4gcHJldmlvdXNWYWx1ZSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBub2RlLnN0eWxlW2ldID0gXCJcIjtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKHR5cGVvZiBwcmV2aW91c1ZhbHVlID09PSBcInN0cmluZ1wiKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgbm9kZVtwcm9wTmFtZV0gPSBcIlwiO1xuICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBub2RlW3Byb3BOYW1lXSA9IG51bGw7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAocHJldmlvdXNWYWx1ZS51bmhvb2spIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHByZXZpb3VzVmFsdWUudW5ob29rKG5vZGUsIHByb3BOYW1lLCBwcm9wVmFsdWUpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBmdW5jdGlvbiBwYXRjaE9iamVjdChub2RlLCBwcm9wcywgcHJldmlvdXMsIHByb3BOYW1lLCBwcm9wVmFsdWUpIHtcbiAgICAgICAgICAgICAgICB2YXIgcHJldmlvdXNWYWx1ZSA9IHByZXZpb3VzID8gcHJldmlvdXNbcHJvcE5hbWVdIDogdW5kZWZpbmVkO1xuXG4gICAgICAgICAgICAgICAgLy8gU2V0IGF0dHJpYnV0ZXNcbiAgICAgICAgICAgICAgICBpZiAocHJvcE5hbWUgPT09IFwiYXR0cmlidXRlc1wiKSB7XG4gICAgICAgICAgICAgICAgICAgIGZvciAodmFyIGF0dHJOYW1lIGluIHByb3BWYWx1ZSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgdmFyIGF0dHJWYWx1ZSA9IHByb3BWYWx1ZVthdHRyTmFtZV07XG5cbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChhdHRyVmFsdWUgPT09IHVuZGVmaW5lZCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIG5vZGUucmVtb3ZlQXR0cmlidXRlKGF0dHJOYW1lKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgbm9kZS5zZXRBdHRyaWJ1dGUoYXR0ck5hbWUsIGF0dHJWYWx1ZSk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgaWYgKHByZXZpb3VzVmFsdWUgJiYgaXNPYmplY3QocHJldmlvdXNWYWx1ZSkgJiYgZ2V0UHJvdG90eXBlKHByZXZpb3VzVmFsdWUpICE9PSBnZXRQcm90b3R5cGUocHJvcFZhbHVlKSkge1xuICAgICAgICAgICAgICAgICAgICBub2RlW3Byb3BOYW1lXSA9IHByb3BWYWx1ZTtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIGlmICghaXNPYmplY3Qobm9kZVtwcm9wTmFtZV0pKSB7XG4gICAgICAgICAgICAgICAgICAgIG5vZGVbcHJvcE5hbWVdID0ge307XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgdmFyIHJlcGxhY2VyID0gcHJvcE5hbWUgPT09IFwic3R5bGVcIiA/IFwiXCIgOiB1bmRlZmluZWQ7XG5cbiAgICAgICAgICAgICAgICBmb3IgKHZhciBrIGluIHByb3BWYWx1ZSkge1xuICAgICAgICAgICAgICAgICAgICB2YXIgdmFsdWUgPSBwcm9wVmFsdWVba107XG4gICAgICAgICAgICAgICAgICAgIG5vZGVbcHJvcE5hbWVdW2tdID0gdmFsdWUgPT09IHVuZGVmaW5lZCA/IHJlcGxhY2VyIDogdmFsdWU7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBmdW5jdGlvbiBnZXRQcm90b3R5cGUodmFsdWUpIHtcbiAgICAgICAgICAgICAgICBpZiAoT2JqZWN0LmdldFByb3RvdHlwZU9mKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBPYmplY3QuZ2V0UHJvdG90eXBlT2YodmFsdWUpO1xuICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAodmFsdWUuX19wcm90b19fKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiB2YWx1ZS5fX3Byb3RvX187XG4gICAgICAgICAgICAgICAgfSBlbHNlIGlmICh2YWx1ZS5jb25zdHJ1Y3Rvcikge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gdmFsdWUuY29uc3RydWN0b3IucHJvdG90eXBlO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgfSwgeyBcIi4uL3Zub2RlL2lzLXZob29rLmpzXCI6IDI2LCBcImlzLW9iamVjdFwiOiAxMSB9XSwgMTU6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICB2YXIgZG9jdW1lbnQgPSByZXF1aXJlKFwiZ2xvYmFsL2RvY3VtZW50XCIpO1xuXG4gICAgICAgICAgICB2YXIgYXBwbHlQcm9wZXJ0aWVzID0gcmVxdWlyZShcIi4vYXBwbHktcHJvcGVydGllc1wiKTtcblxuICAgICAgICAgICAgdmFyIGlzVk5vZGUgPSByZXF1aXJlKFwiLi4vdm5vZGUvaXMtdm5vZGUuanNcIik7XG4gICAgICAgICAgICB2YXIgaXNWVGV4dCA9IHJlcXVpcmUoXCIuLi92bm9kZS9pcy12dGV4dC5qc1wiKTtcbiAgICAgICAgICAgIHZhciBpc1dpZGdldCA9IHJlcXVpcmUoXCIuLi92bm9kZS9pcy13aWRnZXQuanNcIik7XG4gICAgICAgICAgICB2YXIgaGFuZGxlVGh1bmsgPSByZXF1aXJlKFwiLi4vdm5vZGUvaGFuZGxlLXRodW5rLmpzXCIpO1xuXG4gICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IGNyZWF0ZUVsZW1lbnQ7XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIGNyZWF0ZUVsZW1lbnQodm5vZGUsIG9wdHMpIHtcbiAgICAgICAgICAgICAgICB2YXIgZG9jID0gb3B0cyA/IG9wdHMuZG9jdW1lbnQgfHwgZG9jdW1lbnQgOiBkb2N1bWVudDtcbiAgICAgICAgICAgICAgICB2YXIgd2FybiA9IG9wdHMgPyBvcHRzLndhcm4gOiBudWxsO1xuXG4gICAgICAgICAgICAgICAgdm5vZGUgPSBoYW5kbGVUaHVuayh2bm9kZSkuYTtcblxuICAgICAgICAgICAgICAgIGlmIChpc1dpZGdldCh2bm9kZSkpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHZub2RlLmluaXQoKTtcbiAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKGlzVlRleHQodm5vZGUpKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBkb2MuY3JlYXRlVGV4dE5vZGUodm5vZGUudGV4dCk7XG4gICAgICAgICAgICAgICAgfSBlbHNlIGlmICghaXNWTm9kZSh2bm9kZSkpIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKHdhcm4pIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHdhcm4oXCJJdGVtIGlzIG5vdCBhIHZhbGlkIHZpcnR1YWwgZG9tIG5vZGVcIiwgdm5vZGUpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBudWxsO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHZhciBub2RlID0gdm5vZGUubmFtZXNwYWNlID09PSBudWxsID8gZG9jLmNyZWF0ZUVsZW1lbnQodm5vZGUudGFnTmFtZSkgOiBkb2MuY3JlYXRlRWxlbWVudE5TKHZub2RlLm5hbWVzcGFjZSwgdm5vZGUudGFnTmFtZSk7XG5cbiAgICAgICAgICAgICAgICB2YXIgcHJvcHMgPSB2bm9kZS5wcm9wZXJ0aWVzO1xuICAgICAgICAgICAgICAgIGFwcGx5UHJvcGVydGllcyhub2RlLCBwcm9wcyk7XG5cbiAgICAgICAgICAgICAgICB2YXIgY2hpbGRyZW4gPSB2bm9kZS5jaGlsZHJlbjtcblxuICAgICAgICAgICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgY2hpbGRyZW4ubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgICAgICAgICAgdmFyIGNoaWxkTm9kZSA9IGNyZWF0ZUVsZW1lbnQoY2hpbGRyZW5baV0sIG9wdHMpO1xuICAgICAgICAgICAgICAgICAgICBpZiAoY2hpbGROb2RlKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBub2RlLmFwcGVuZENoaWxkKGNoaWxkTm9kZSk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICByZXR1cm4gbm9kZTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSwgeyBcIi4uL3Zub2RlL2hhbmRsZS10aHVuay5qc1wiOiAyNCwgXCIuLi92bm9kZS9pcy12bm9kZS5qc1wiOiAyNywgXCIuLi92bm9kZS9pcy12dGV4dC5qc1wiOiAyOCwgXCIuLi92bm9kZS9pcy13aWRnZXQuanNcIjogMjksIFwiLi9hcHBseS1wcm9wZXJ0aWVzXCI6IDE0LCBcImdsb2JhbC9kb2N1bWVudFwiOiAxMCB9XSwgMTY6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICAvLyBNYXBzIGEgdmlydHVhbCBET00gdHJlZSBvbnRvIGEgcmVhbCBET00gdHJlZSBpbiBhbiBlZmZpY2llbnQgbWFubmVyLlxuICAgICAgICAgICAgLy8gV2UgZG9uJ3Qgd2FudCB0byByZWFkIGFsbCBvZiB0aGUgRE9NIG5vZGVzIGluIHRoZSB0cmVlIHNvIHdlIHVzZVxuICAgICAgICAgICAgLy8gdGhlIGluLW9yZGVyIHRyZWUgaW5kZXhpbmcgdG8gZWxpbWluYXRlIHJlY3Vyc2lvbiBkb3duIGNlcnRhaW4gYnJhbmNoZXMuXG4gICAgICAgICAgICAvLyBXZSBvbmx5IHJlY3Vyc2UgaW50byBhIERPTSBub2RlIGlmIHdlIGtub3cgdGhhdCBpdCBjb250YWlucyBhIGNoaWxkIG9mXG4gICAgICAgICAgICAvLyBpbnRlcmVzdC5cblxuICAgICAgICAgICAgdmFyIG5vQ2hpbGQgPSB7fTtcblxuICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBkb21JbmRleDtcblxuICAgICAgICAgICAgZnVuY3Rpb24gZG9tSW5kZXgocm9vdE5vZGUsIHRyZWUsIGluZGljZXMsIG5vZGVzKSB7XG4gICAgICAgICAgICAgICAgaWYgKCFpbmRpY2VzIHx8IGluZGljZXMubGVuZ3RoID09PSAwKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiB7fTtcbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICBpbmRpY2VzLnNvcnQoYXNjZW5kaW5nKTtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHJlY3Vyc2Uocm9vdE5vZGUsIHRyZWUsIGluZGljZXMsIG5vZGVzLCAwKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIHJlY3Vyc2Uocm9vdE5vZGUsIHRyZWUsIGluZGljZXMsIG5vZGVzLCByb290SW5kZXgpIHtcbiAgICAgICAgICAgICAgICBub2RlcyA9IG5vZGVzIHx8IHt9O1xuXG4gICAgICAgICAgICAgICAgaWYgKHJvb3ROb2RlKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmIChpbmRleEluUmFuZ2UoaW5kaWNlcywgcm9vdEluZGV4LCByb290SW5kZXgpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBub2Rlc1tyb290SW5kZXhdID0gcm9vdE5vZGU7XG4gICAgICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgICAgICB2YXIgdkNoaWxkcmVuID0gdHJlZS5jaGlsZHJlbjtcblxuICAgICAgICAgICAgICAgICAgICBpZiAodkNoaWxkcmVuKSB7XG5cbiAgICAgICAgICAgICAgICAgICAgICAgIHZhciBjaGlsZE5vZGVzID0gcm9vdE5vZGUuY2hpbGROb2RlcztcblxuICAgICAgICAgICAgICAgICAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCB0cmVlLmNoaWxkcmVuLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcm9vdEluZGV4ICs9IDE7XG5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB2YXIgdkNoaWxkID0gdkNoaWxkcmVuW2ldIHx8IG5vQ2hpbGQ7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdmFyIG5leHRJbmRleCA9IHJvb3RJbmRleCArICh2Q2hpbGQuY291bnQgfHwgMCk7XG5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBza2lwIHJlY3Vyc2lvbiBkb3duIHRoZSB0cmVlIGlmIHRoZXJlIGFyZSBubyBub2RlcyBkb3duIGhlcmVcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoaW5kZXhJblJhbmdlKGluZGljZXMsIHJvb3RJbmRleCwgbmV4dEluZGV4KSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICByZWN1cnNlKGNoaWxkTm9kZXNbaV0sIHZDaGlsZCwgaW5kaWNlcywgbm9kZXMsIHJvb3RJbmRleCk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcm9vdEluZGV4ID0gbmV4dEluZGV4O1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgcmV0dXJuIG5vZGVzO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAvLyBCaW5hcnkgc2VhcmNoIGZvciBhbiBpbmRleCBpbiB0aGUgaW50ZXJ2YWwgW2xlZnQsIHJpZ2h0XVxuICAgICAgICAgICAgZnVuY3Rpb24gaW5kZXhJblJhbmdlKGluZGljZXMsIGxlZnQsIHJpZ2h0KSB7XG4gICAgICAgICAgICAgICAgaWYgKGluZGljZXMubGVuZ3RoID09PSAwKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICB2YXIgbWluSW5kZXggPSAwO1xuICAgICAgICAgICAgICAgIHZhciBtYXhJbmRleCA9IGluZGljZXMubGVuZ3RoIC0gMTtcbiAgICAgICAgICAgICAgICB2YXIgY3VycmVudEluZGV4O1xuICAgICAgICAgICAgICAgIHZhciBjdXJyZW50SXRlbTtcblxuICAgICAgICAgICAgICAgIHdoaWxlIChtaW5JbmRleCA8PSBtYXhJbmRleCkge1xuICAgICAgICAgICAgICAgICAgICBjdXJyZW50SW5kZXggPSAobWF4SW5kZXggKyBtaW5JbmRleCkgLyAyID4+IDA7XG4gICAgICAgICAgICAgICAgICAgIGN1cnJlbnRJdGVtID0gaW5kaWNlc1tjdXJyZW50SW5kZXhdO1xuXG4gICAgICAgICAgICAgICAgICAgIGlmIChtaW5JbmRleCA9PT0gbWF4SW5kZXgpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBjdXJyZW50SXRlbSA+PSBsZWZ0ICYmIGN1cnJlbnRJdGVtIDw9IHJpZ2h0O1xuICAgICAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKGN1cnJlbnRJdGVtIDwgbGVmdCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgbWluSW5kZXggPSBjdXJyZW50SW5kZXggKyAxO1xuICAgICAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKGN1cnJlbnRJdGVtID4gcmlnaHQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIG1heEluZGV4ID0gY3VycmVudEluZGV4IC0gMTtcbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBmdW5jdGlvbiBhc2NlbmRpbmcoYSwgYikge1xuICAgICAgICAgICAgICAgIHJldHVybiBhID4gYiA/IDEgOiAtMTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSwge31dLCAxNzogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHtcbiAgICAgICAgICAgIHZhciBhcHBseVByb3BlcnRpZXMgPSByZXF1aXJlKFwiLi9hcHBseS1wcm9wZXJ0aWVzXCIpO1xuXG4gICAgICAgICAgICB2YXIgaXNXaWRnZXQgPSByZXF1aXJlKFwiLi4vdm5vZGUvaXMtd2lkZ2V0LmpzXCIpO1xuICAgICAgICAgICAgdmFyIFZQYXRjaCA9IHJlcXVpcmUoXCIuLi92bm9kZS92cGF0Y2guanNcIik7XG5cbiAgICAgICAgICAgIHZhciB1cGRhdGVXaWRnZXQgPSByZXF1aXJlKFwiLi91cGRhdGUtd2lkZ2V0XCIpO1xuXG4gICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IGFwcGx5UGF0Y2g7XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIGFwcGx5UGF0Y2godnBhdGNoLCBkb21Ob2RlLCByZW5kZXJPcHRpb25zKSB7XG4gICAgICAgICAgICAgICAgdmFyIHR5cGUgPSB2cGF0Y2gudHlwZTtcbiAgICAgICAgICAgICAgICB2YXIgdk5vZGUgPSB2cGF0Y2gudk5vZGU7XG4gICAgICAgICAgICAgICAgdmFyIHBhdGNoID0gdnBhdGNoLnBhdGNoO1xuXG4gICAgICAgICAgICAgICAgc3dpdGNoICh0eXBlKSB7XG4gICAgICAgICAgICAgICAgICAgIGNhc2UgVlBhdGNoLlJFTU9WRTpcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiByZW1vdmVOb2RlKGRvbU5vZGUsIHZOb2RlKTtcbiAgICAgICAgICAgICAgICAgICAgY2FzZSBWUGF0Y2guSU5TRVJUOlxuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGluc2VydE5vZGUoZG9tTm9kZSwgcGF0Y2gsIHJlbmRlck9wdGlvbnMpO1xuICAgICAgICAgICAgICAgICAgICBjYXNlIFZQYXRjaC5WVEVYVDpcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBzdHJpbmdQYXRjaChkb21Ob2RlLCB2Tm9kZSwgcGF0Y2gsIHJlbmRlck9wdGlvbnMpO1xuICAgICAgICAgICAgICAgICAgICBjYXNlIFZQYXRjaC5XSURHRVQ6XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gd2lkZ2V0UGF0Y2goZG9tTm9kZSwgdk5vZGUsIHBhdGNoLCByZW5kZXJPcHRpb25zKTtcbiAgICAgICAgICAgICAgICAgICAgY2FzZSBWUGF0Y2guVk5PREU6XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gdk5vZGVQYXRjaChkb21Ob2RlLCB2Tm9kZSwgcGF0Y2gsIHJlbmRlck9wdGlvbnMpO1xuICAgICAgICAgICAgICAgICAgICBjYXNlIFZQYXRjaC5PUkRFUjpcbiAgICAgICAgICAgICAgICAgICAgICAgIHJlb3JkZXJDaGlsZHJlbihkb21Ob2RlLCBwYXRjaCk7XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gZG9tTm9kZTtcbiAgICAgICAgICAgICAgICAgICAgY2FzZSBWUGF0Y2guUFJPUFM6XG4gICAgICAgICAgICAgICAgICAgICAgICBhcHBseVByb3BlcnRpZXMoZG9tTm9kZSwgcGF0Y2gsIHZOb2RlLnByb3BlcnRpZXMpO1xuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGRvbU5vZGU7XG4gICAgICAgICAgICAgICAgICAgIGNhc2UgVlBhdGNoLlRIVU5LOlxuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHJlcGxhY2VSb290KGRvbU5vZGUsIHJlbmRlck9wdGlvbnMucGF0Y2goZG9tTm9kZSwgcGF0Y2gsIHJlbmRlck9wdGlvbnMpKTtcbiAgICAgICAgICAgICAgICAgICAgZGVmYXVsdDpcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBkb21Ob2RlO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZnVuY3Rpb24gcmVtb3ZlTm9kZShkb21Ob2RlLCB2Tm9kZSkge1xuICAgICAgICAgICAgICAgIHZhciBwYXJlbnROb2RlID0gZG9tTm9kZS5wYXJlbnROb2RlO1xuXG4gICAgICAgICAgICAgICAgaWYgKHBhcmVudE5vZGUpIHtcbiAgICAgICAgICAgICAgICAgICAgcGFyZW50Tm9kZS5yZW1vdmVDaGlsZChkb21Ob2RlKTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICBkZXN0cm95V2lkZ2V0KGRvbU5vZGUsIHZOb2RlKTtcblxuICAgICAgICAgICAgICAgIHJldHVybiBudWxsO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBmdW5jdGlvbiBpbnNlcnROb2RlKHBhcmVudE5vZGUsIHZOb2RlLCByZW5kZXJPcHRpb25zKSB7XG4gICAgICAgICAgICAgICAgdmFyIG5ld05vZGUgPSByZW5kZXJPcHRpb25zLnJlbmRlcih2Tm9kZSwgcmVuZGVyT3B0aW9ucyk7XG5cbiAgICAgICAgICAgICAgICBpZiAocGFyZW50Tm9kZSkge1xuICAgICAgICAgICAgICAgICAgICBwYXJlbnROb2RlLmFwcGVuZENoaWxkKG5ld05vZGUpO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHJldHVybiBwYXJlbnROb2RlO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBmdW5jdGlvbiBzdHJpbmdQYXRjaChkb21Ob2RlLCBsZWZ0Vk5vZGUsIHZUZXh0LCByZW5kZXJPcHRpb25zKSB7XG4gICAgICAgICAgICAgICAgdmFyIG5ld05vZGU7XG5cbiAgICAgICAgICAgICAgICBpZiAoZG9tTm9kZS5ub2RlVHlwZSA9PT0gMykge1xuICAgICAgICAgICAgICAgICAgICBkb21Ob2RlLnJlcGxhY2VEYXRhKDAsIGRvbU5vZGUubGVuZ3RoLCB2VGV4dC50ZXh0KTtcbiAgICAgICAgICAgICAgICAgICAgbmV3Tm9kZSA9IGRvbU5vZGU7XG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgdmFyIHBhcmVudE5vZGUgPSBkb21Ob2RlLnBhcmVudE5vZGU7XG4gICAgICAgICAgICAgICAgICAgIG5ld05vZGUgPSByZW5kZXJPcHRpb25zLnJlbmRlcih2VGV4dCwgcmVuZGVyT3B0aW9ucyk7XG5cbiAgICAgICAgICAgICAgICAgICAgaWYgKHBhcmVudE5vZGUgJiYgbmV3Tm9kZSAhPT0gZG9tTm9kZSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgcGFyZW50Tm9kZS5yZXBsYWNlQ2hpbGQobmV3Tm9kZSwgZG9tTm9kZSk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICByZXR1cm4gbmV3Tm9kZTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZnVuY3Rpb24gd2lkZ2V0UGF0Y2goZG9tTm9kZSwgbGVmdFZOb2RlLCB3aWRnZXQsIHJlbmRlck9wdGlvbnMpIHtcbiAgICAgICAgICAgICAgICB2YXIgdXBkYXRpbmcgPSB1cGRhdGVXaWRnZXQobGVmdFZOb2RlLCB3aWRnZXQpO1xuICAgICAgICAgICAgICAgIHZhciBuZXdOb2RlO1xuXG4gICAgICAgICAgICAgICAgaWYgKHVwZGF0aW5nKSB7XG4gICAgICAgICAgICAgICAgICAgIG5ld05vZGUgPSB3aWRnZXQudXBkYXRlKGxlZnRWTm9kZSwgZG9tTm9kZSkgfHwgZG9tTm9kZTtcbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICBuZXdOb2RlID0gcmVuZGVyT3B0aW9ucy5yZW5kZXIod2lkZ2V0LCByZW5kZXJPcHRpb25zKTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICB2YXIgcGFyZW50Tm9kZSA9IGRvbU5vZGUucGFyZW50Tm9kZTtcblxuICAgICAgICAgICAgICAgIGlmIChwYXJlbnROb2RlICYmIG5ld05vZGUgIT09IGRvbU5vZGUpIHtcbiAgICAgICAgICAgICAgICAgICAgcGFyZW50Tm9kZS5yZXBsYWNlQ2hpbGQobmV3Tm9kZSwgZG9tTm9kZSk7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgaWYgKCF1cGRhdGluZykge1xuICAgICAgICAgICAgICAgICAgICBkZXN0cm95V2lkZ2V0KGRvbU5vZGUsIGxlZnRWTm9kZSk7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgcmV0dXJuIG5ld05vZGU7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIHZOb2RlUGF0Y2goZG9tTm9kZSwgbGVmdFZOb2RlLCB2Tm9kZSwgcmVuZGVyT3B0aW9ucykge1xuICAgICAgICAgICAgICAgIHZhciBwYXJlbnROb2RlID0gZG9tTm9kZS5wYXJlbnROb2RlO1xuICAgICAgICAgICAgICAgIHZhciBuZXdOb2RlID0gcmVuZGVyT3B0aW9ucy5yZW5kZXIodk5vZGUsIHJlbmRlck9wdGlvbnMpO1xuXG4gICAgICAgICAgICAgICAgaWYgKHBhcmVudE5vZGUgJiYgbmV3Tm9kZSAhPT0gZG9tTm9kZSkge1xuICAgICAgICAgICAgICAgICAgICBwYXJlbnROb2RlLnJlcGxhY2VDaGlsZChuZXdOb2RlLCBkb21Ob2RlKTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICByZXR1cm4gbmV3Tm9kZTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZnVuY3Rpb24gZGVzdHJveVdpZGdldChkb21Ob2RlLCB3KSB7XG4gICAgICAgICAgICAgICAgaWYgKHR5cGVvZiB3LmRlc3Ryb3kgPT09IFwiZnVuY3Rpb25cIiAmJiBpc1dpZGdldCh3KSkge1xuICAgICAgICAgICAgICAgICAgICB3LmRlc3Ryb3koZG9tTm9kZSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBmdW5jdGlvbiByZW9yZGVyQ2hpbGRyZW4oZG9tTm9kZSwgbW92ZXMpIHtcbiAgICAgICAgICAgICAgICB2YXIgY2hpbGROb2RlcyA9IGRvbU5vZGUuY2hpbGROb2RlcztcbiAgICAgICAgICAgICAgICB2YXIga2V5TWFwID0ge307XG4gICAgICAgICAgICAgICAgdmFyIG5vZGU7XG4gICAgICAgICAgICAgICAgdmFyIHJlbW92ZTtcbiAgICAgICAgICAgICAgICB2YXIgaW5zZXJ0O1xuXG4gICAgICAgICAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCBtb3Zlcy5yZW1vdmVzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICAgICAgICAgIHJlbW92ZSA9IG1vdmVzLnJlbW92ZXNbaV07XG4gICAgICAgICAgICAgICAgICAgIG5vZGUgPSBjaGlsZE5vZGVzW3JlbW92ZS5mcm9tXTtcbiAgICAgICAgICAgICAgICAgICAgaWYgKHJlbW92ZS5rZXkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGtleU1hcFtyZW1vdmUua2V5XSA9IG5vZGU7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgZG9tTm9kZS5yZW1vdmVDaGlsZChub2RlKTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICB2YXIgbGVuZ3RoID0gY2hpbGROb2Rlcy5sZW5ndGg7XG4gICAgICAgICAgICAgICAgZm9yICh2YXIgaiA9IDA7IGogPCBtb3Zlcy5pbnNlcnRzLmxlbmd0aDsgaisrKSB7XG4gICAgICAgICAgICAgICAgICAgIGluc2VydCA9IG1vdmVzLmluc2VydHNbal07XG4gICAgICAgICAgICAgICAgICAgIG5vZGUgPSBrZXlNYXBbaW5zZXJ0LmtleV07XG4gICAgICAgICAgICAgICAgICAgIC8vIHRoaXMgaXMgdGhlIHdlaXJkZXN0IGJ1ZyBpJ3ZlIGV2ZXIgc2VlbiBpbiB3ZWJraXRcbiAgICAgICAgICAgICAgICAgICAgZG9tTm9kZS5pbnNlcnRCZWZvcmUobm9kZSwgaW5zZXJ0LnRvID49IGxlbmd0aCsrID8gbnVsbCA6IGNoaWxkTm9kZXNbaW5zZXJ0LnRvXSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBmdW5jdGlvbiByZXBsYWNlUm9vdChvbGRSb290LCBuZXdSb290KSB7XG4gICAgICAgICAgICAgICAgaWYgKG9sZFJvb3QgJiYgbmV3Um9vdCAmJiBvbGRSb290ICE9PSBuZXdSb290ICYmIG9sZFJvb3QucGFyZW50Tm9kZSkge1xuICAgICAgICAgICAgICAgICAgICBvbGRSb290LnBhcmVudE5vZGUucmVwbGFjZUNoaWxkKG5ld1Jvb3QsIG9sZFJvb3QpO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHJldHVybiBuZXdSb290O1xuICAgICAgICAgICAgfVxuICAgICAgICB9LCB7IFwiLi4vdm5vZGUvaXMtd2lkZ2V0LmpzXCI6IDI5LCBcIi4uL3Zub2RlL3ZwYXRjaC5qc1wiOiAzMiwgXCIuL2FwcGx5LXByb3BlcnRpZXNcIjogMTQsIFwiLi91cGRhdGUtd2lkZ2V0XCI6IDE5IH1dLCAxODogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHtcbiAgICAgICAgICAgIHZhciBkb2N1bWVudCA9IHJlcXVpcmUoXCJnbG9iYWwvZG9jdW1lbnRcIik7XG4gICAgICAgICAgICB2YXIgaXNBcnJheSA9IHJlcXVpcmUoXCJ4LWlzLWFycmF5XCIpO1xuXG4gICAgICAgICAgICB2YXIgcmVuZGVyID0gcmVxdWlyZShcIi4vY3JlYXRlLWVsZW1lbnRcIik7XG4gICAgICAgICAgICB2YXIgZG9tSW5kZXggPSByZXF1aXJlKFwiLi9kb20taW5kZXhcIik7XG4gICAgICAgICAgICB2YXIgcGF0Y2hPcCA9IHJlcXVpcmUoXCIuL3BhdGNoLW9wXCIpO1xuICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBwYXRjaDtcblxuICAgICAgICAgICAgZnVuY3Rpb24gcGF0Y2gocm9vdE5vZGUsIHBhdGNoZXMsIHJlbmRlck9wdGlvbnMpIHtcbiAgICAgICAgICAgICAgICByZW5kZXJPcHRpb25zID0gcmVuZGVyT3B0aW9ucyB8fCB7fTtcbiAgICAgICAgICAgICAgICByZW5kZXJPcHRpb25zLnBhdGNoID0gcmVuZGVyT3B0aW9ucy5wYXRjaCAmJiByZW5kZXJPcHRpb25zLnBhdGNoICE9PSBwYXRjaCA/IHJlbmRlck9wdGlvbnMucGF0Y2ggOiBwYXRjaFJlY3Vyc2l2ZTtcbiAgICAgICAgICAgICAgICByZW5kZXJPcHRpb25zLnJlbmRlciA9IHJlbmRlck9wdGlvbnMucmVuZGVyIHx8IHJlbmRlcjtcblxuICAgICAgICAgICAgICAgIHJldHVybiByZW5kZXJPcHRpb25zLnBhdGNoKHJvb3ROb2RlLCBwYXRjaGVzLCByZW5kZXJPcHRpb25zKTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZnVuY3Rpb24gcGF0Y2hSZWN1cnNpdmUocm9vdE5vZGUsIHBhdGNoZXMsIHJlbmRlck9wdGlvbnMpIHtcbiAgICAgICAgICAgICAgICB2YXIgaW5kaWNlcyA9IHBhdGNoSW5kaWNlcyhwYXRjaGVzKTtcblxuICAgICAgICAgICAgICAgIGlmIChpbmRpY2VzLmxlbmd0aCA9PT0gMCkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gcm9vdE5vZGU7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgdmFyIGluZGV4ID0gZG9tSW5kZXgocm9vdE5vZGUsIHBhdGNoZXMuYSwgaW5kaWNlcyk7XG4gICAgICAgICAgICAgICAgdmFyIG93bmVyRG9jdW1lbnQgPSByb290Tm9kZS5vd25lckRvY3VtZW50O1xuXG4gICAgICAgICAgICAgICAgaWYgKCFyZW5kZXJPcHRpb25zLmRvY3VtZW50ICYmIG93bmVyRG9jdW1lbnQgIT09IGRvY3VtZW50KSB7XG4gICAgICAgICAgICAgICAgICAgIHJlbmRlck9wdGlvbnMuZG9jdW1lbnQgPSBvd25lckRvY3VtZW50O1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgaW5kaWNlcy5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgICAgICAgICB2YXIgbm9kZUluZGV4ID0gaW5kaWNlc1tpXTtcbiAgICAgICAgICAgICAgICAgICAgcm9vdE5vZGUgPSBhcHBseVBhdGNoKHJvb3ROb2RlLCBpbmRleFtub2RlSW5kZXhdLCBwYXRjaGVzW25vZGVJbmRleF0sIHJlbmRlck9wdGlvbnMpO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHJldHVybiByb290Tm9kZTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZnVuY3Rpb24gYXBwbHlQYXRjaChyb290Tm9kZSwgZG9tTm9kZSwgcGF0Y2hMaXN0LCByZW5kZXJPcHRpb25zKSB7XG4gICAgICAgICAgICAgICAgaWYgKCFkb21Ob2RlKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiByb290Tm9kZTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICB2YXIgbmV3Tm9kZTtcblxuICAgICAgICAgICAgICAgIGlmIChpc0FycmF5KHBhdGNoTGlzdCkpIHtcbiAgICAgICAgICAgICAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCBwYXRjaExpc3QubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIG5ld05vZGUgPSBwYXRjaE9wKHBhdGNoTGlzdFtpXSwgZG9tTm9kZSwgcmVuZGVyT3B0aW9ucyk7XG5cbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChkb21Ob2RlID09PSByb290Tm9kZSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJvb3ROb2RlID0gbmV3Tm9kZTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIG5ld05vZGUgPSBwYXRjaE9wKHBhdGNoTGlzdCwgZG9tTm9kZSwgcmVuZGVyT3B0aW9ucyk7XG5cbiAgICAgICAgICAgICAgICAgICAgaWYgKGRvbU5vZGUgPT09IHJvb3ROb2RlKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICByb290Tm9kZSA9IG5ld05vZGU7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICByZXR1cm4gcm9vdE5vZGU7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIHBhdGNoSW5kaWNlcyhwYXRjaGVzKSB7XG4gICAgICAgICAgICAgICAgdmFyIGluZGljZXMgPSBbXTtcblxuICAgICAgICAgICAgICAgIGZvciAodmFyIGtleSBpbiBwYXRjaGVzKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmIChrZXkgIT09IFwiYVwiKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBpbmRpY2VzLnB1c2goTnVtYmVyKGtleSkpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgcmV0dXJuIGluZGljZXM7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0sIHsgXCIuL2NyZWF0ZS1lbGVtZW50XCI6IDE1LCBcIi4vZG9tLWluZGV4XCI6IDE2LCBcIi4vcGF0Y2gtb3BcIjogMTcsIFwiZ2xvYmFsL2RvY3VtZW50XCI6IDEwLCBcIngtaXMtYXJyYXlcIjogMTIgfV0sIDE5OiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge1xuICAgICAgICAgICAgdmFyIGlzV2lkZ2V0ID0gcmVxdWlyZShcIi4uL3Zub2RlL2lzLXdpZGdldC5qc1wiKTtcblxuICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSB1cGRhdGVXaWRnZXQ7XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIHVwZGF0ZVdpZGdldChhLCBiKSB7XG4gICAgICAgICAgICAgICAgaWYgKGlzV2lkZ2V0KGEpICYmIGlzV2lkZ2V0KGIpKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmIChcIm5hbWVcIiBpbiBhICYmIFwibmFtZVwiIGluIGIpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBhLmlkID09PSBiLmlkO1xuICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGEuaW5pdCA9PT0gYi5pbml0O1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICAgICAgfVxuICAgICAgICB9LCB7IFwiLi4vdm5vZGUvaXMtd2lkZ2V0LmpzXCI6IDI5IH1dLCAyMDogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHtcbiAgICAgICAgICAgIFwidXNlIHN0cmljdFwiO1xuXG4gICAgICAgICAgICB2YXIgRXZTdG9yZSA9IHJlcXVpcmUoXCJldi1zdG9yZVwiKTtcblxuICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBFdkhvb2s7XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIEV2SG9vayh2YWx1ZSkge1xuICAgICAgICAgICAgICAgIGlmICghKHRoaXMgaW5zdGFuY2VvZiBFdkhvb2spKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBuZXcgRXZIb29rKHZhbHVlKTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICB0aGlzLnZhbHVlID0gdmFsdWU7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIEV2SG9vay5wcm90b3R5cGUuaG9vayA9IGZ1bmN0aW9uIChub2RlLCBwcm9wZXJ0eU5hbWUpIHtcbiAgICAgICAgICAgICAgICB2YXIgZXMgPSBFdlN0b3JlKG5vZGUpO1xuICAgICAgICAgICAgICAgIHZhciBwcm9wTmFtZSA9IHByb3BlcnR5TmFtZS5zdWJzdHIoMyk7XG5cbiAgICAgICAgICAgICAgICBlc1twcm9wTmFtZV0gPSB0aGlzLnZhbHVlO1xuICAgICAgICAgICAgfTtcblxuICAgICAgICAgICAgRXZIb29rLnByb3RvdHlwZS51bmhvb2sgPSBmdW5jdGlvbiAobm9kZSwgcHJvcGVydHlOYW1lKSB7XG4gICAgICAgICAgICAgICAgdmFyIGVzID0gRXZTdG9yZShub2RlKTtcbiAgICAgICAgICAgICAgICB2YXIgcHJvcE5hbWUgPSBwcm9wZXJ0eU5hbWUuc3Vic3RyKDMpO1xuXG4gICAgICAgICAgICAgICAgZXNbcHJvcE5hbWVdID0gdW5kZWZpbmVkO1xuICAgICAgICAgICAgfTtcbiAgICAgICAgfSwgeyBcImV2LXN0b3JlXCI6IDcgfV0sIDIxOiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge1xuICAgICAgICAgICAgXCJ1c2Ugc3RyaWN0XCI7XG5cbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gU29mdFNldEhvb2s7XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIFNvZnRTZXRIb29rKHZhbHVlKSB7XG4gICAgICAgICAgICAgICAgaWYgKCEodGhpcyBpbnN0YW5jZW9mIFNvZnRTZXRIb29rKSkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gbmV3IFNvZnRTZXRIb29rKHZhbHVlKTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICB0aGlzLnZhbHVlID0gdmFsdWU7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIFNvZnRTZXRIb29rLnByb3RvdHlwZS5ob29rID0gZnVuY3Rpb24gKG5vZGUsIHByb3BlcnR5TmFtZSkge1xuICAgICAgICAgICAgICAgIGlmIChub2RlW3Byb3BlcnR5TmFtZV0gIT09IHRoaXMudmFsdWUpIHtcbiAgICAgICAgICAgICAgICAgICAgbm9kZVtwcm9wZXJ0eU5hbWVdID0gdGhpcy52YWx1ZTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9O1xuICAgICAgICB9LCB7fV0sIDIyOiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge1xuICAgICAgICAgICAgXCJ1c2Ugc3RyaWN0XCI7XG5cbiAgICAgICAgICAgIHZhciBpc0FycmF5ID0gcmVxdWlyZShcIngtaXMtYXJyYXlcIik7XG5cbiAgICAgICAgICAgIHZhciBWTm9kZSA9IHJlcXVpcmUoXCIuLi92bm9kZS92bm9kZS5qc1wiKTtcbiAgICAgICAgICAgIHZhciBWVGV4dCA9IHJlcXVpcmUoXCIuLi92bm9kZS92dGV4dC5qc1wiKTtcbiAgICAgICAgICAgIHZhciBpc1ZOb2RlID0gcmVxdWlyZShcIi4uL3Zub2RlL2lzLXZub2RlXCIpO1xuICAgICAgICAgICAgdmFyIGlzVlRleHQgPSByZXF1aXJlKFwiLi4vdm5vZGUvaXMtdnRleHRcIik7XG4gICAgICAgICAgICB2YXIgaXNXaWRnZXQgPSByZXF1aXJlKFwiLi4vdm5vZGUvaXMtd2lkZ2V0XCIpO1xuICAgICAgICAgICAgdmFyIGlzSG9vayA9IHJlcXVpcmUoXCIuLi92bm9kZS9pcy12aG9va1wiKTtcbiAgICAgICAgICAgIHZhciBpc1ZUaHVuayA9IHJlcXVpcmUoXCIuLi92bm9kZS9pcy10aHVua1wiKTtcblxuICAgICAgICAgICAgdmFyIHBhcnNlVGFnID0gcmVxdWlyZShcIi4vcGFyc2UtdGFnLmpzXCIpO1xuICAgICAgICAgICAgdmFyIHNvZnRTZXRIb29rID0gcmVxdWlyZShcIi4vaG9va3Mvc29mdC1zZXQtaG9vay5qc1wiKTtcbiAgICAgICAgICAgIHZhciBldkhvb2sgPSByZXF1aXJlKFwiLi9ob29rcy9ldi1ob29rLmpzXCIpO1xuXG4gICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IGg7XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIGgodGFnTmFtZSwgcHJvcGVydGllcywgY2hpbGRyZW4pIHtcbiAgICAgICAgICAgICAgICB2YXIgY2hpbGROb2RlcyA9IFtdO1xuICAgICAgICAgICAgICAgIHZhciB0YWcsIHByb3BzLCBrZXksIG5hbWVzcGFjZTtcblxuICAgICAgICAgICAgICAgIGlmICghY2hpbGRyZW4gJiYgaXNDaGlsZHJlbihwcm9wZXJ0aWVzKSkge1xuICAgICAgICAgICAgICAgICAgICBjaGlsZHJlbiA9IHByb3BlcnRpZXM7XG4gICAgICAgICAgICAgICAgICAgIHByb3BzID0ge307XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgcHJvcHMgPSBwcm9wcyB8fCBwcm9wZXJ0aWVzIHx8IHt9O1xuICAgICAgICAgICAgICAgIHRhZyA9IHBhcnNlVGFnKHRhZ05hbWUsIHByb3BzKTtcblxuICAgICAgICAgICAgICAgIC8vIHN1cHBvcnQga2V5c1xuICAgICAgICAgICAgICAgIGlmIChwcm9wcy5oYXNPd25Qcm9wZXJ0eShcImtleVwiKSkge1xuICAgICAgICAgICAgICAgICAgICBrZXkgPSBwcm9wcy5rZXk7XG4gICAgICAgICAgICAgICAgICAgIHByb3BzLmtleSA9IHVuZGVmaW5lZDtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAvLyBzdXBwb3J0IG5hbWVzcGFjZVxuICAgICAgICAgICAgICAgIGlmIChwcm9wcy5oYXNPd25Qcm9wZXJ0eShcIm5hbWVzcGFjZVwiKSkge1xuICAgICAgICAgICAgICAgICAgICBuYW1lc3BhY2UgPSBwcm9wcy5uYW1lc3BhY2U7XG4gICAgICAgICAgICAgICAgICAgIHByb3BzLm5hbWVzcGFjZSA9IHVuZGVmaW5lZDtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAvLyBmaXggY3Vyc29yIGJ1Z1xuICAgICAgICAgICAgICAgIGlmICh0YWcgPT09IFwiSU5QVVRcIiAmJiAhbmFtZXNwYWNlICYmIHByb3BzLmhhc093blByb3BlcnR5KFwidmFsdWVcIikgJiYgcHJvcHMudmFsdWUgIT09IHVuZGVmaW5lZCAmJiAhaXNIb29rKHByb3BzLnZhbHVlKSkge1xuICAgICAgICAgICAgICAgICAgICBwcm9wcy52YWx1ZSA9IHNvZnRTZXRIb29rKHByb3BzLnZhbHVlKTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICB0cmFuc2Zvcm1Qcm9wZXJ0aWVzKHByb3BzKTtcblxuICAgICAgICAgICAgICAgIGlmIChjaGlsZHJlbiAhPT0gdW5kZWZpbmVkICYmIGNoaWxkcmVuICE9PSBudWxsKSB7XG4gICAgICAgICAgICAgICAgICAgIGFkZENoaWxkKGNoaWxkcmVuLCBjaGlsZE5vZGVzLCB0YWcsIHByb3BzKTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICByZXR1cm4gbmV3IFZOb2RlKHRhZywgcHJvcHMsIGNoaWxkTm9kZXMsIGtleSwgbmFtZXNwYWNlKTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZnVuY3Rpb24gYWRkQ2hpbGQoYywgY2hpbGROb2RlcywgdGFnLCBwcm9wcykge1xuICAgICAgICAgICAgICAgIGlmICh0eXBlb2YgYyA9PT0gXCJzdHJpbmdcIikge1xuICAgICAgICAgICAgICAgICAgICBjaGlsZE5vZGVzLnB1c2gobmV3IFZUZXh0KGMpKTtcbiAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKHR5cGVvZiBjID09PSBcIm51bWJlclwiKSB7XG4gICAgICAgICAgICAgICAgICAgIGNoaWxkTm9kZXMucHVzaChuZXcgVlRleHQoU3RyaW5nKGMpKSk7XG4gICAgICAgICAgICAgICAgfSBlbHNlIGlmIChpc0NoaWxkKGMpKSB7XG4gICAgICAgICAgICAgICAgICAgIGNoaWxkTm9kZXMucHVzaChjKTtcbiAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKGlzQXJyYXkoYykpIHtcbiAgICAgICAgICAgICAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCBjLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBhZGRDaGlsZChjW2ldLCBjaGlsZE5vZGVzLCB0YWcsIHByb3BzKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoYyA9PT0gbnVsbCB8fCBjID09PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIHRocm93IFVuZXhwZWN0ZWRWaXJ0dWFsRWxlbWVudCh7XG4gICAgICAgICAgICAgICAgICAgICAgICBmb3JlaWduT2JqZWN0OiBjLFxuICAgICAgICAgICAgICAgICAgICAgICAgcGFyZW50Vm5vZGU6IHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0YWdOYW1lOiB0YWcsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcHJvcGVydGllczogcHJvcHNcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBmdW5jdGlvbiB0cmFuc2Zvcm1Qcm9wZXJ0aWVzKHByb3BzKSB7XG4gICAgICAgICAgICAgICAgZm9yICh2YXIgcHJvcE5hbWUgaW4gcHJvcHMpIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKHByb3BzLmhhc093blByb3BlcnR5KHByb3BOYW1lKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgdmFyIHZhbHVlID0gcHJvcHNbcHJvcE5hbWVdO1xuXG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoaXNIb29rKHZhbHVlKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnRpbnVlO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAocHJvcE5hbWUuc3Vic3RyKDAsIDMpID09PSBcImV2LVwiKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gYWRkIGV2LWZvbyBzdXBwb3J0XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcHJvcHNbcHJvcE5hbWVdID0gZXZIb29rKHZhbHVlKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZnVuY3Rpb24gaXNDaGlsZCh4KSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGlzVk5vZGUoeCkgfHwgaXNWVGV4dCh4KSB8fCBpc1dpZGdldCh4KSB8fCBpc1ZUaHVuayh4KTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZnVuY3Rpb24gaXNDaGlsZHJlbih4KSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHR5cGVvZiB4ID09PSBcInN0cmluZ1wiIHx8IGlzQXJyYXkoeCkgfHwgaXNDaGlsZCh4KTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZnVuY3Rpb24gVW5leHBlY3RlZFZpcnR1YWxFbGVtZW50KGRhdGEpIHtcbiAgICAgICAgICAgICAgICB2YXIgZXJyID0gbmV3IEVycm9yKCk7XG5cbiAgICAgICAgICAgICAgICBlcnIudHlwZSA9IFwidmlydHVhbC1oeXBlcnNjcmlwdC51bmV4cGVjdGVkLnZpcnR1YWwtZWxlbWVudFwiO1xuICAgICAgICAgICAgICAgIGVyci5tZXNzYWdlID0gXCJVbmV4cGVjdGVkIHZpcnR1YWwgY2hpbGQgcGFzc2VkIHRvIGgoKS5cXG5cIiArIFwiRXhwZWN0ZWQgYSBWTm9kZSAvIFZ0aHVuayAvIFZXaWRnZXQgLyBzdHJpbmcgYnV0OlxcblwiICsgXCJnb3Q6XFxuXCIgKyBlcnJvclN0cmluZyhkYXRhLmZvcmVpZ25PYmplY3QpICsgXCIuXFxuXCIgKyBcIlRoZSBwYXJlbnQgdm5vZGUgaXM6XFxuXCIgKyBlcnJvclN0cmluZyhkYXRhLnBhcmVudFZub2RlKTtcbiAgICAgICAgICAgICAgICBcIlxcblwiICsgXCJTdWdnZXN0ZWQgZml4OiBjaGFuZ2UgeW91ciBgaCguLi4sIFsgLi4uIF0pYCBjYWxsc2l0ZS5cIjtcbiAgICAgICAgICAgICAgICBlcnIuZm9yZWlnbk9iamVjdCA9IGRhdGEuZm9yZWlnbk9iamVjdDtcbiAgICAgICAgICAgICAgICBlcnIucGFyZW50Vm5vZGUgPSBkYXRhLnBhcmVudFZub2RlO1xuXG4gICAgICAgICAgICAgICAgcmV0dXJuIGVycjtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZnVuY3Rpb24gZXJyb3JTdHJpbmcob2JqKSB7XG4gICAgICAgICAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIEpTT04uc3RyaW5naWZ5KG9iaiwgbnVsbCwgXCIgICAgXCIpO1xuICAgICAgICAgICAgICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIFN0cmluZyhvYmopO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgfSwgeyBcIi4uL3Zub2RlL2lzLXRodW5rXCI6IDI1LCBcIi4uL3Zub2RlL2lzLXZob29rXCI6IDI2LCBcIi4uL3Zub2RlL2lzLXZub2RlXCI6IDI3LCBcIi4uL3Zub2RlL2lzLXZ0ZXh0XCI6IDI4LCBcIi4uL3Zub2RlL2lzLXdpZGdldFwiOiAyOSwgXCIuLi92bm9kZS92bm9kZS5qc1wiOiAzMSwgXCIuLi92bm9kZS92dGV4dC5qc1wiOiAzMywgXCIuL2hvb2tzL2V2LWhvb2suanNcIjogMjAsIFwiLi9ob29rcy9zb2Z0LXNldC1ob29rLmpzXCI6IDIxLCBcIi4vcGFyc2UtdGFnLmpzXCI6IDIzLCBcIngtaXMtYXJyYXlcIjogMTIgfV0sIDIzOiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge1xuICAgICAgICAgICAgXCJ1c2Ugc3RyaWN0XCI7XG5cbiAgICAgICAgICAgIHZhciBzcGxpdCA9IHJlcXVpcmUoXCJicm93c2VyLXNwbGl0XCIpO1xuXG4gICAgICAgICAgICB2YXIgY2xhc3NJZFNwbGl0ID0gLyhbXFwuI10/W2EtekEtWjAtOVxcdTAwN0YtXFx1RkZGRl86LV0rKS87XG4gICAgICAgICAgICB2YXIgbm90Q2xhc3NJZCA9IC9eXFwufCMvO1xuXG4gICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IHBhcnNlVGFnO1xuXG4gICAgICAgICAgICBmdW5jdGlvbiBwYXJzZVRhZyh0YWcsIHByb3BzKSB7XG4gICAgICAgICAgICAgICAgaWYgKCF0YWcpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIFwiRElWXCI7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgdmFyIG5vSWQgPSAhcHJvcHMuaGFzT3duUHJvcGVydHkoXCJpZFwiKTtcblxuICAgICAgICAgICAgICAgIHZhciB0YWdQYXJ0cyA9IHNwbGl0KHRhZywgY2xhc3NJZFNwbGl0KTtcbiAgICAgICAgICAgICAgICB2YXIgdGFnTmFtZSA9IG51bGw7XG5cbiAgICAgICAgICAgICAgICBpZiAobm90Q2xhc3NJZC50ZXN0KHRhZ1BhcnRzWzFdKSkge1xuICAgICAgICAgICAgICAgICAgICB0YWdOYW1lID0gXCJESVZcIjtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICB2YXIgY2xhc3NlcywgcGFydCwgdHlwZSwgaTtcblxuICAgICAgICAgICAgICAgIGZvciAoaSA9IDA7IGkgPCB0YWdQYXJ0cy5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgICAgICAgICBwYXJ0ID0gdGFnUGFydHNbaV07XG5cbiAgICAgICAgICAgICAgICAgICAgaWYgKCFwYXJ0KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBjb250aW51ZTtcbiAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgIHR5cGUgPSBwYXJ0LmNoYXJBdCgwKTtcblxuICAgICAgICAgICAgICAgICAgICBpZiAoIXRhZ05hbWUpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHRhZ05hbWUgPSBwYXJ0O1xuICAgICAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKHR5cGUgPT09IFwiLlwiKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBjbGFzc2VzID0gY2xhc3NlcyB8fCBbXTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGNsYXNzZXMucHVzaChwYXJ0LnN1YnN0cmluZygxLCBwYXJ0Lmxlbmd0aCkpO1xuICAgICAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKHR5cGUgPT09IFwiI1wiICYmIG5vSWQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHByb3BzLmlkID0gcGFydC5zdWJzdHJpbmcoMSwgcGFydC5sZW5ndGgpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgaWYgKGNsYXNzZXMpIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKHByb3BzLmNsYXNzTmFtZSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgY2xhc3Nlcy5wdXNoKHByb3BzLmNsYXNzTmFtZSk7XG4gICAgICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgICAgICBwcm9wcy5jbGFzc05hbWUgPSBjbGFzc2VzLmpvaW4oXCIgXCIpO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHJldHVybiBwcm9wcy5uYW1lc3BhY2UgPyB0YWdOYW1lIDogdGFnTmFtZS50b1VwcGVyQ2FzZSgpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9LCB7IFwiYnJvd3Nlci1zcGxpdFwiOiA1IH1dLCAyNDogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHtcbiAgICAgICAgICAgIHZhciBpc1ZOb2RlID0gcmVxdWlyZShcIi4vaXMtdm5vZGVcIik7XG4gICAgICAgICAgICB2YXIgaXNWVGV4dCA9IHJlcXVpcmUoXCIuL2lzLXZ0ZXh0XCIpO1xuICAgICAgICAgICAgdmFyIGlzV2lkZ2V0ID0gcmVxdWlyZShcIi4vaXMtd2lkZ2V0XCIpO1xuICAgICAgICAgICAgdmFyIGlzVGh1bmsgPSByZXF1aXJlKFwiLi9pcy10aHVua1wiKTtcblxuICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBoYW5kbGVUaHVuaztcblxuICAgICAgICAgICAgZnVuY3Rpb24gaGFuZGxlVGh1bmsoYSwgYikge1xuICAgICAgICAgICAgICAgIHZhciByZW5kZXJlZEEgPSBhO1xuICAgICAgICAgICAgICAgIHZhciByZW5kZXJlZEIgPSBiO1xuXG4gICAgICAgICAgICAgICAgaWYgKGlzVGh1bmsoYikpIHtcbiAgICAgICAgICAgICAgICAgICAgcmVuZGVyZWRCID0gcmVuZGVyVGh1bmsoYiwgYSk7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgaWYgKGlzVGh1bmsoYSkpIHtcbiAgICAgICAgICAgICAgICAgICAgcmVuZGVyZWRBID0gcmVuZGVyVGh1bmsoYSwgbnVsbCk7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgICAgICAgICAgYTogcmVuZGVyZWRBLFxuICAgICAgICAgICAgICAgICAgICBiOiByZW5kZXJlZEJcbiAgICAgICAgICAgICAgICB9O1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBmdW5jdGlvbiByZW5kZXJUaHVuayh0aHVuaywgcHJldmlvdXMpIHtcbiAgICAgICAgICAgICAgICB2YXIgcmVuZGVyZWRUaHVuayA9IHRodW5rLnZub2RlO1xuXG4gICAgICAgICAgICAgICAgaWYgKCFyZW5kZXJlZFRodW5rKSB7XG4gICAgICAgICAgICAgICAgICAgIHJlbmRlcmVkVGh1bmsgPSB0aHVuay52bm9kZSA9IHRodW5rLnJlbmRlcihwcmV2aW91cyk7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgaWYgKCEoaXNWTm9kZShyZW5kZXJlZFRodW5rKSB8fCBpc1ZUZXh0KHJlbmRlcmVkVGh1bmspIHx8IGlzV2lkZ2V0KHJlbmRlcmVkVGh1bmspKSkge1xuICAgICAgICAgICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoXCJ0aHVuayBkaWQgbm90IHJldHVybiBhIHZhbGlkIG5vZGVcIik7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgcmV0dXJuIHJlbmRlcmVkVGh1bms7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0sIHsgXCIuL2lzLXRodW5rXCI6IDI1LCBcIi4vaXMtdm5vZGVcIjogMjcsIFwiLi9pcy12dGV4dFwiOiAyOCwgXCIuL2lzLXdpZGdldFwiOiAyOSB9XSwgMjU6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IGlzVGh1bms7XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIGlzVGh1bmsodCkge1xuICAgICAgICAgICAgICAgIHJldHVybiB0ICYmIHQudHlwZSA9PT0gXCJUaHVua1wiO1xuICAgICAgICAgICAgfVxuICAgICAgICB9LCB7fV0sIDI2OiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge1xuICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBpc0hvb2s7XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIGlzSG9vayhob29rKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGhvb2sgJiYgKHR5cGVvZiBob29rLmhvb2sgPT09IFwiZnVuY3Rpb25cIiAmJiAhaG9vay5oYXNPd25Qcm9wZXJ0eShcImhvb2tcIikgfHwgdHlwZW9mIGhvb2sudW5ob29rID09PSBcImZ1bmN0aW9uXCIgJiYgIWhvb2suaGFzT3duUHJvcGVydHkoXCJ1bmhvb2tcIikpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9LCB7fV0sIDI3OiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge1xuICAgICAgICAgICAgdmFyIHZlcnNpb24gPSByZXF1aXJlKFwiLi92ZXJzaW9uXCIpO1xuXG4gICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IGlzVmlydHVhbE5vZGU7XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIGlzVmlydHVhbE5vZGUoeCkge1xuICAgICAgICAgICAgICAgIHJldHVybiB4ICYmIHgudHlwZSA9PT0gXCJWaXJ0dWFsTm9kZVwiICYmIHgudmVyc2lvbiA9PT0gdmVyc2lvbjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSwgeyBcIi4vdmVyc2lvblwiOiAzMCB9XSwgMjg6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICB2YXIgdmVyc2lvbiA9IHJlcXVpcmUoXCIuL3ZlcnNpb25cIik7XG5cbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gaXNWaXJ0dWFsVGV4dDtcblxuICAgICAgICAgICAgZnVuY3Rpb24gaXNWaXJ0dWFsVGV4dCh4KSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHggJiYgeC50eXBlID09PSBcIlZpcnR1YWxUZXh0XCIgJiYgeC52ZXJzaW9uID09PSB2ZXJzaW9uO1xuICAgICAgICAgICAgfVxuICAgICAgICB9LCB7IFwiLi92ZXJzaW9uXCI6IDMwIH1dLCAyOTogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHtcbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gaXNXaWRnZXQ7XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIGlzV2lkZ2V0KHcpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gdyAmJiB3LnR5cGUgPT09IFwiV2lkZ2V0XCI7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0sIHt9XSwgMzA6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IFwiMlwiO1xuICAgICAgICB9LCB7fV0sIDMxOiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge1xuICAgICAgICAgICAgdmFyIHZlcnNpb24gPSByZXF1aXJlKFwiLi92ZXJzaW9uXCIpO1xuICAgICAgICAgICAgdmFyIGlzVk5vZGUgPSByZXF1aXJlKFwiLi9pcy12bm9kZVwiKTtcbiAgICAgICAgICAgIHZhciBpc1dpZGdldCA9IHJlcXVpcmUoXCIuL2lzLXdpZGdldFwiKTtcbiAgICAgICAgICAgIHZhciBpc1RodW5rID0gcmVxdWlyZShcIi4vaXMtdGh1bmtcIik7XG4gICAgICAgICAgICB2YXIgaXNWSG9vayA9IHJlcXVpcmUoXCIuL2lzLXZob29rXCIpO1xuXG4gICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IFZpcnR1YWxOb2RlO1xuXG4gICAgICAgICAgICB2YXIgbm9Qcm9wZXJ0aWVzID0ge307XG4gICAgICAgICAgICB2YXIgbm9DaGlsZHJlbiA9IFtdO1xuXG4gICAgICAgICAgICBmdW5jdGlvbiBWaXJ0dWFsTm9kZSh0YWdOYW1lLCBwcm9wZXJ0aWVzLCBjaGlsZHJlbiwga2V5LCBuYW1lc3BhY2UpIHtcbiAgICAgICAgICAgICAgICB0aGlzLnRhZ05hbWUgPSB0YWdOYW1lO1xuICAgICAgICAgICAgICAgIHRoaXMucHJvcGVydGllcyA9IHByb3BlcnRpZXMgfHwgbm9Qcm9wZXJ0aWVzO1xuICAgICAgICAgICAgICAgIHRoaXMuY2hpbGRyZW4gPSBjaGlsZHJlbiB8fCBub0NoaWxkcmVuO1xuICAgICAgICAgICAgICAgIHRoaXMua2V5ID0ga2V5ICE9IG51bGwgPyBTdHJpbmcoa2V5KSA6IHVuZGVmaW5lZDtcbiAgICAgICAgICAgICAgICB0aGlzLm5hbWVzcGFjZSA9IHR5cGVvZiBuYW1lc3BhY2UgPT09IFwic3RyaW5nXCIgPyBuYW1lc3BhY2UgOiBudWxsO1xuXG4gICAgICAgICAgICAgICAgdmFyIGNvdW50ID0gY2hpbGRyZW4gJiYgY2hpbGRyZW4ubGVuZ3RoIHx8IDA7XG4gICAgICAgICAgICAgICAgdmFyIGRlc2NlbmRhbnRzID0gMDtcbiAgICAgICAgICAgICAgICB2YXIgaGFzV2lkZ2V0cyA9IGZhbHNlO1xuICAgICAgICAgICAgICAgIHZhciBoYXNUaHVua3MgPSBmYWxzZTtcbiAgICAgICAgICAgICAgICB2YXIgZGVzY2VuZGFudEhvb2tzID0gZmFsc2U7XG4gICAgICAgICAgICAgICAgdmFyIGhvb2tzO1xuXG4gICAgICAgICAgICAgICAgZm9yICh2YXIgcHJvcE5hbWUgaW4gcHJvcGVydGllcykge1xuICAgICAgICAgICAgICAgICAgICBpZiAocHJvcGVydGllcy5oYXNPd25Qcm9wZXJ0eShwcm9wTmFtZSkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHZhciBwcm9wZXJ0eSA9IHByb3BlcnRpZXNbcHJvcE5hbWVdO1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGlzVkhvb2socHJvcGVydHkpICYmIHByb3BlcnR5LnVuaG9vaykge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmICghaG9va3MpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaG9va3MgPSB7fTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBob29rc1twcm9wTmFtZV0gPSBwcm9wZXJ0eTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgY291bnQ7IGkrKykge1xuICAgICAgICAgICAgICAgICAgICB2YXIgY2hpbGQgPSBjaGlsZHJlbltpXTtcbiAgICAgICAgICAgICAgICAgICAgaWYgKGlzVk5vZGUoY2hpbGQpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBkZXNjZW5kYW50cyArPSBjaGlsZC5jb3VudCB8fCAwO1xuXG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoIWhhc1dpZGdldHMgJiYgY2hpbGQuaGFzV2lkZ2V0cykge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGhhc1dpZGdldHMgPSB0cnVlO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoIWhhc1RodW5rcyAmJiBjaGlsZC5oYXNUaHVua3MpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBoYXNUaHVua3MgPSB0cnVlO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoIWRlc2NlbmRhbnRIb29rcyAmJiAoY2hpbGQuaG9va3MgfHwgY2hpbGQuZGVzY2VuZGFudEhvb2tzKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRlc2NlbmRhbnRIb29rcyA9IHRydWU7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoIWhhc1dpZGdldHMgJiYgaXNXaWRnZXQoY2hpbGQpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAodHlwZW9mIGNoaWxkLmRlc3Ryb3kgPT09IFwiZnVuY3Rpb25cIikge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGhhc1dpZGdldHMgPSB0cnVlO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKCFoYXNUaHVua3MgJiYgaXNUaHVuayhjaGlsZCkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGhhc1RodW5rcyA9IHRydWU7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICB0aGlzLmNvdW50ID0gY291bnQgKyBkZXNjZW5kYW50cztcbiAgICAgICAgICAgICAgICB0aGlzLmhhc1dpZGdldHMgPSBoYXNXaWRnZXRzO1xuICAgICAgICAgICAgICAgIHRoaXMuaGFzVGh1bmtzID0gaGFzVGh1bmtzO1xuICAgICAgICAgICAgICAgIHRoaXMuaG9va3MgPSBob29rcztcbiAgICAgICAgICAgICAgICB0aGlzLmRlc2NlbmRhbnRIb29rcyA9IGRlc2NlbmRhbnRIb29rcztcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgVmlydHVhbE5vZGUucHJvdG90eXBlLnZlcnNpb24gPSB2ZXJzaW9uO1xuICAgICAgICAgICAgVmlydHVhbE5vZGUucHJvdG90eXBlLnR5cGUgPSBcIlZpcnR1YWxOb2RlXCI7XG4gICAgICAgIH0sIHsgXCIuL2lzLXRodW5rXCI6IDI1LCBcIi4vaXMtdmhvb2tcIjogMjYsIFwiLi9pcy12bm9kZVwiOiAyNywgXCIuL2lzLXdpZGdldFwiOiAyOSwgXCIuL3ZlcnNpb25cIjogMzAgfV0sIDMyOiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge1xuICAgICAgICAgICAgdmFyIHZlcnNpb24gPSByZXF1aXJlKFwiLi92ZXJzaW9uXCIpO1xuXG4gICAgICAgICAgICBWaXJ0dWFsUGF0Y2guTk9ORSA9IDA7XG4gICAgICAgICAgICBWaXJ0dWFsUGF0Y2guVlRFWFQgPSAxO1xuICAgICAgICAgICAgVmlydHVhbFBhdGNoLlZOT0RFID0gMjtcbiAgICAgICAgICAgIFZpcnR1YWxQYXRjaC5XSURHRVQgPSAzO1xuICAgICAgICAgICAgVmlydHVhbFBhdGNoLlBST1BTID0gNDtcbiAgICAgICAgICAgIFZpcnR1YWxQYXRjaC5PUkRFUiA9IDU7XG4gICAgICAgICAgICBWaXJ0dWFsUGF0Y2guSU5TRVJUID0gNjtcbiAgICAgICAgICAgIFZpcnR1YWxQYXRjaC5SRU1PVkUgPSA3O1xuICAgICAgICAgICAgVmlydHVhbFBhdGNoLlRIVU5LID0gODtcblxuICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBWaXJ0dWFsUGF0Y2g7XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIFZpcnR1YWxQYXRjaCh0eXBlLCB2Tm9kZSwgcGF0Y2gpIHtcbiAgICAgICAgICAgICAgICB0aGlzLnR5cGUgPSBOdW1iZXIodHlwZSk7XG4gICAgICAgICAgICAgICAgdGhpcy52Tm9kZSA9IHZOb2RlO1xuICAgICAgICAgICAgICAgIHRoaXMucGF0Y2ggPSBwYXRjaDtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgVmlydHVhbFBhdGNoLnByb3RvdHlwZS52ZXJzaW9uID0gdmVyc2lvbjtcbiAgICAgICAgICAgIFZpcnR1YWxQYXRjaC5wcm90b3R5cGUudHlwZSA9IFwiVmlydHVhbFBhdGNoXCI7XG4gICAgICAgIH0sIHsgXCIuL3ZlcnNpb25cIjogMzAgfV0sIDMzOiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge1xuICAgICAgICAgICAgdmFyIHZlcnNpb24gPSByZXF1aXJlKFwiLi92ZXJzaW9uXCIpO1xuXG4gICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IFZpcnR1YWxUZXh0O1xuXG4gICAgICAgICAgICBmdW5jdGlvbiBWaXJ0dWFsVGV4dCh0ZXh0KSB7XG4gICAgICAgICAgICAgICAgdGhpcy50ZXh0ID0gU3RyaW5nKHRleHQpO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBWaXJ0dWFsVGV4dC5wcm90b3R5cGUudmVyc2lvbiA9IHZlcnNpb247XG4gICAgICAgICAgICBWaXJ0dWFsVGV4dC5wcm90b3R5cGUudHlwZSA9IFwiVmlydHVhbFRleHRcIjtcbiAgICAgICAgfSwgeyBcIi4vdmVyc2lvblwiOiAzMCB9XSwgMzQ6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICB2YXIgaXNPYmplY3QgPSByZXF1aXJlKFwiaXMtb2JqZWN0XCIpO1xuICAgICAgICAgICAgdmFyIGlzSG9vayA9IHJlcXVpcmUoXCIuLi92bm9kZS9pcy12aG9va1wiKTtcblxuICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBkaWZmUHJvcHM7XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIGRpZmZQcm9wcyhhLCBiKSB7XG4gICAgICAgICAgICAgICAgdmFyIGRpZmY7XG5cbiAgICAgICAgICAgICAgICBmb3IgKHZhciBhS2V5IGluIGEpIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKCEoYUtleSBpbiBiKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgZGlmZiA9IGRpZmYgfHwge307XG4gICAgICAgICAgICAgICAgICAgICAgICBkaWZmW2FLZXldID0gdW5kZWZpbmVkO1xuICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgdmFyIGFWYWx1ZSA9IGFbYUtleV07XG4gICAgICAgICAgICAgICAgICAgIHZhciBiVmFsdWUgPSBiW2FLZXldO1xuXG4gICAgICAgICAgICAgICAgICAgIGlmIChhVmFsdWUgPT09IGJWYWx1ZSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgY29udGludWU7XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoaXNPYmplY3QoYVZhbHVlKSAmJiBpc09iamVjdChiVmFsdWUpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoZ2V0UHJvdG90eXBlKGJWYWx1ZSkgIT09IGdldFByb3RvdHlwZShhVmFsdWUpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgZGlmZiA9IGRpZmYgfHwge307XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgZGlmZlthS2V5XSA9IGJWYWx1ZTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoaXNIb29rKGJWYWx1ZSkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBkaWZmID0gZGlmZiB8fCB7fTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBkaWZmW2FLZXldID0gYlZhbHVlO1xuICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB2YXIgb2JqZWN0RGlmZiA9IGRpZmZQcm9wcyhhVmFsdWUsIGJWYWx1ZSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKG9iamVjdERpZmYpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZGlmZiA9IGRpZmYgfHwge307XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRpZmZbYUtleV0gPSBvYmplY3REaWZmO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGRpZmYgPSBkaWZmIHx8IHt9O1xuICAgICAgICAgICAgICAgICAgICAgICAgZGlmZlthS2V5XSA9IGJWYWx1ZTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIGZvciAodmFyIGJLZXkgaW4gYikge1xuICAgICAgICAgICAgICAgICAgICBpZiAoIShiS2V5IGluIGEpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBkaWZmID0gZGlmZiB8fCB7fTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGRpZmZbYktleV0gPSBiW2JLZXldO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgcmV0dXJuIGRpZmY7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIGdldFByb3RvdHlwZSh2YWx1ZSkge1xuICAgICAgICAgICAgICAgIGlmIChPYmplY3QuZ2V0UHJvdG90eXBlT2YpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIE9iamVjdC5nZXRQcm90b3R5cGVPZih2YWx1ZSk7XG4gICAgICAgICAgICAgICAgfSBlbHNlIGlmICh2YWx1ZS5fX3Byb3RvX18pIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHZhbHVlLl9fcHJvdG9fXztcbiAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKHZhbHVlLmNvbnN0cnVjdG9yKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiB2YWx1ZS5jb25zdHJ1Y3Rvci5wcm90b3R5cGU7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9LCB7IFwiLi4vdm5vZGUvaXMtdmhvb2tcIjogMjYsIFwiaXMtb2JqZWN0XCI6IDExIH1dLCAzNTogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHtcbiAgICAgICAgICAgIHZhciBpc0FycmF5ID0gcmVxdWlyZShcIngtaXMtYXJyYXlcIik7XG5cbiAgICAgICAgICAgIHZhciBWUGF0Y2ggPSByZXF1aXJlKFwiLi4vdm5vZGUvdnBhdGNoXCIpO1xuICAgICAgICAgICAgdmFyIGlzVk5vZGUgPSByZXF1aXJlKFwiLi4vdm5vZGUvaXMtdm5vZGVcIik7XG4gICAgICAgICAgICB2YXIgaXNWVGV4dCA9IHJlcXVpcmUoXCIuLi92bm9kZS9pcy12dGV4dFwiKTtcbiAgICAgICAgICAgIHZhciBpc1dpZGdldCA9IHJlcXVpcmUoXCIuLi92bm9kZS9pcy13aWRnZXRcIik7XG4gICAgICAgICAgICB2YXIgaXNUaHVuayA9IHJlcXVpcmUoXCIuLi92bm9kZS9pcy10aHVua1wiKTtcbiAgICAgICAgICAgIHZhciBoYW5kbGVUaHVuayA9IHJlcXVpcmUoXCIuLi92bm9kZS9oYW5kbGUtdGh1bmtcIik7XG5cbiAgICAgICAgICAgIHZhciBkaWZmUHJvcHMgPSByZXF1aXJlKFwiLi9kaWZmLXByb3BzXCIpO1xuXG4gICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IGRpZmY7XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIGRpZmYoYSwgYikge1xuICAgICAgICAgICAgICAgIHZhciBwYXRjaCA9IHsgYTogYSB9O1xuICAgICAgICAgICAgICAgIHdhbGsoYSwgYiwgcGF0Y2gsIDApO1xuICAgICAgICAgICAgICAgIHJldHVybiBwYXRjaDtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZnVuY3Rpb24gd2FsayhhLCBiLCBwYXRjaCwgaW5kZXgpIHtcbiAgICAgICAgICAgICAgICBpZiAoYSA9PT0gYikge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgdmFyIGFwcGx5ID0gcGF0Y2hbaW5kZXhdO1xuICAgICAgICAgICAgICAgIHZhciBhcHBseUNsZWFyID0gZmFsc2U7XG5cbiAgICAgICAgICAgICAgICBpZiAoaXNUaHVuayhhKSB8fCBpc1RodW5rKGIpKSB7XG4gICAgICAgICAgICAgICAgICAgIHRodW5rcyhhLCBiLCBwYXRjaCwgaW5kZXgpO1xuICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoYiA9PSBudWxsKSB7XG5cbiAgICAgICAgICAgICAgICAgICAgLy8gSWYgYSBpcyBhIHdpZGdldCB3ZSB3aWxsIGFkZCBhIHJlbW92ZSBwYXRjaCBmb3IgaXRcbiAgICAgICAgICAgICAgICAgICAgLy8gT3RoZXJ3aXNlIGFueSBjaGlsZCB3aWRnZXRzL2hvb2tzIG11c3QgYmUgZGVzdHJveWVkLlxuICAgICAgICAgICAgICAgICAgICAvLyBUaGlzIHByZXZlbnRzIGFkZGluZyB0d28gcmVtb3ZlIHBhdGNoZXMgZm9yIGEgd2lkZ2V0LlxuICAgICAgICAgICAgICAgICAgICBpZiAoIWlzV2lkZ2V0KGEpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBjbGVhclN0YXRlKGEsIHBhdGNoLCBpbmRleCk7XG4gICAgICAgICAgICAgICAgICAgICAgICBhcHBseSA9IHBhdGNoW2luZGV4XTtcbiAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgIGFwcGx5ID0gYXBwZW5kUGF0Y2goYXBwbHksIG5ldyBWUGF0Y2goVlBhdGNoLlJFTU9WRSwgYSwgYikpO1xuICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoaXNWTm9kZShiKSkge1xuICAgICAgICAgICAgICAgICAgICBpZiAoaXNWTm9kZShhKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGEudGFnTmFtZSA9PT0gYi50YWdOYW1lICYmIGEubmFtZXNwYWNlID09PSBiLm5hbWVzcGFjZSAmJiBhLmtleSA9PT0gYi5rZXkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB2YXIgcHJvcHNQYXRjaCA9IGRpZmZQcm9wcyhhLnByb3BlcnRpZXMsIGIucHJvcGVydGllcyk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHByb3BzUGF0Y2gpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYXBwbHkgPSBhcHBlbmRQYXRjaChhcHBseSwgbmV3IFZQYXRjaChWUGF0Y2guUFJPUFMsIGEsIHByb3BzUGF0Y2gpKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgYXBwbHkgPSBkaWZmQ2hpbGRyZW4oYSwgYiwgcGF0Y2gsIGFwcGx5LCBpbmRleCk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGFwcGx5ID0gYXBwZW5kUGF0Y2goYXBwbHksIG5ldyBWUGF0Y2goVlBhdGNoLlZOT0RFLCBhLCBiKSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgYXBwbHlDbGVhciA9IHRydWU7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBhcHBseSA9IGFwcGVuZFBhdGNoKGFwcGx5LCBuZXcgVlBhdGNoKFZQYXRjaC5WTk9ERSwgYSwgYikpO1xuICAgICAgICAgICAgICAgICAgICAgICAgYXBwbHlDbGVhciA9IHRydWU7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKGlzVlRleHQoYikpIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKCFpc1ZUZXh0KGEpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBhcHBseSA9IGFwcGVuZFBhdGNoKGFwcGx5LCBuZXcgVlBhdGNoKFZQYXRjaC5WVEVYVCwgYSwgYikpO1xuICAgICAgICAgICAgICAgICAgICAgICAgYXBwbHlDbGVhciA9IHRydWU7XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoYS50ZXh0ICE9PSBiLnRleHQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGFwcGx5ID0gYXBwZW5kUGF0Y2goYXBwbHksIG5ldyBWUGF0Y2goVlBhdGNoLlZURVhULCBhLCBiKSk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKGlzV2lkZ2V0KGIpKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmICghaXNXaWRnZXQoYSkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGFwcGx5Q2xlYXIgPSB0cnVlO1xuICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgYXBwbHkgPSBhcHBlbmRQYXRjaChhcHBseSwgbmV3IFZQYXRjaChWUGF0Y2guV0lER0VULCBhLCBiKSk7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgaWYgKGFwcGx5KSB7XG4gICAgICAgICAgICAgICAgICAgIHBhdGNoW2luZGV4XSA9IGFwcGx5O1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIGlmIChhcHBseUNsZWFyKSB7XG4gICAgICAgICAgICAgICAgICAgIGNsZWFyU3RhdGUoYSwgcGF0Y2gsIGluZGV4KTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIGRpZmZDaGlsZHJlbihhLCBiLCBwYXRjaCwgYXBwbHksIGluZGV4KSB7XG4gICAgICAgICAgICAgICAgdmFyIGFDaGlsZHJlbiA9IGEuY2hpbGRyZW47XG4gICAgICAgICAgICAgICAgdmFyIG9yZGVyZWRTZXQgPSByZW9yZGVyKGFDaGlsZHJlbiwgYi5jaGlsZHJlbik7XG4gICAgICAgICAgICAgICAgdmFyIGJDaGlsZHJlbiA9IG9yZGVyZWRTZXQuY2hpbGRyZW47XG5cbiAgICAgICAgICAgICAgICB2YXIgYUxlbiA9IGFDaGlsZHJlbi5sZW5ndGg7XG4gICAgICAgICAgICAgICAgdmFyIGJMZW4gPSBiQ2hpbGRyZW4ubGVuZ3RoO1xuICAgICAgICAgICAgICAgIHZhciBsZW4gPSBhTGVuID4gYkxlbiA/IGFMZW4gOiBiTGVuO1xuXG4gICAgICAgICAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCBsZW47IGkrKykge1xuICAgICAgICAgICAgICAgICAgICB2YXIgbGVmdE5vZGUgPSBhQ2hpbGRyZW5baV07XG4gICAgICAgICAgICAgICAgICAgIHZhciByaWdodE5vZGUgPSBiQ2hpbGRyZW5baV07XG4gICAgICAgICAgICAgICAgICAgIGluZGV4ICs9IDE7XG5cbiAgICAgICAgICAgICAgICAgICAgaWYgKCFsZWZ0Tm9kZSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHJpZ2h0Tm9kZSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIEV4Y2VzcyBub2RlcyBpbiBiIG5lZWQgdG8gYmUgYWRkZWRcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBhcHBseSA9IGFwcGVuZFBhdGNoKGFwcGx5LCBuZXcgVlBhdGNoKFZQYXRjaC5JTlNFUlQsIG51bGwsIHJpZ2h0Tm9kZSkpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgd2FsayhsZWZ0Tm9kZSwgcmlnaHROb2RlLCBwYXRjaCwgaW5kZXgpO1xuICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgaWYgKGlzVk5vZGUobGVmdE5vZGUpICYmIGxlZnROb2RlLmNvdW50KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBpbmRleCArPSBsZWZ0Tm9kZS5jb3VudDtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIGlmIChvcmRlcmVkU2V0Lm1vdmVzKSB7XG4gICAgICAgICAgICAgICAgICAgIC8vIFJlb3JkZXIgbm9kZXMgbGFzdFxuICAgICAgICAgICAgICAgICAgICBhcHBseSA9IGFwcGVuZFBhdGNoKGFwcGx5LCBuZXcgVlBhdGNoKFZQYXRjaC5PUkRFUiwgYSwgb3JkZXJlZFNldC5tb3ZlcykpO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHJldHVybiBhcHBseTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZnVuY3Rpb24gY2xlYXJTdGF0ZSh2Tm9kZSwgcGF0Y2gsIGluZGV4KSB7XG4gICAgICAgICAgICAgICAgLy8gVE9ETzogTWFrZSB0aGlzIGEgc2luZ2xlIHdhbGssIG5vdCB0d29cbiAgICAgICAgICAgICAgICB1bmhvb2sodk5vZGUsIHBhdGNoLCBpbmRleCk7XG4gICAgICAgICAgICAgICAgZGVzdHJveVdpZGdldHModk5vZGUsIHBhdGNoLCBpbmRleCk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIC8vIFBhdGNoIHJlY29yZHMgZm9yIGFsbCBkZXN0cm95ZWQgd2lkZ2V0cyBtdXN0IGJlIGFkZGVkIGJlY2F1c2Ugd2UgbmVlZFxuICAgICAgICAgICAgLy8gYSBET00gbm9kZSByZWZlcmVuY2UgZm9yIHRoZSBkZXN0cm95IGZ1bmN0aW9uXG4gICAgICAgICAgICBmdW5jdGlvbiBkZXN0cm95V2lkZ2V0cyh2Tm9kZSwgcGF0Y2gsIGluZGV4KSB7XG4gICAgICAgICAgICAgICAgaWYgKGlzV2lkZ2V0KHZOb2RlKSkge1xuICAgICAgICAgICAgICAgICAgICBpZiAodHlwZW9mIHZOb2RlLmRlc3Ryb3kgPT09IFwiZnVuY3Rpb25cIikge1xuICAgICAgICAgICAgICAgICAgICAgICAgcGF0Y2hbaW5kZXhdID0gYXBwZW5kUGF0Y2gocGF0Y2hbaW5kZXhdLCBuZXcgVlBhdGNoKFZQYXRjaC5SRU1PVkUsIHZOb2RlLCBudWxsKSk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKGlzVk5vZGUodk5vZGUpICYmICh2Tm9kZS5oYXNXaWRnZXRzIHx8IHZOb2RlLmhhc1RodW5rcykpIHtcbiAgICAgICAgICAgICAgICAgICAgdmFyIGNoaWxkcmVuID0gdk5vZGUuY2hpbGRyZW47XG4gICAgICAgICAgICAgICAgICAgIHZhciBsZW4gPSBjaGlsZHJlbi5sZW5ndGg7XG4gICAgICAgICAgICAgICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgbGVuOyBpKyspIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHZhciBjaGlsZCA9IGNoaWxkcmVuW2ldO1xuICAgICAgICAgICAgICAgICAgICAgICAgaW5kZXggKz0gMTtcblxuICAgICAgICAgICAgICAgICAgICAgICAgZGVzdHJveVdpZGdldHMoY2hpbGQsIHBhdGNoLCBpbmRleCk7XG5cbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChpc1ZOb2RlKGNoaWxkKSAmJiBjaGlsZC5jb3VudCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGluZGV4ICs9IGNoaWxkLmNvdW50O1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfSBlbHNlIGlmIChpc1RodW5rKHZOb2RlKSkge1xuICAgICAgICAgICAgICAgICAgICB0aHVua3Modk5vZGUsIG51bGwsIHBhdGNoLCBpbmRleCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAvLyBDcmVhdGUgYSBzdWItcGF0Y2ggZm9yIHRodW5rc1xuICAgICAgICAgICAgZnVuY3Rpb24gdGh1bmtzKGEsIGIsIHBhdGNoLCBpbmRleCkge1xuICAgICAgICAgICAgICAgIHZhciBub2RlcyA9IGhhbmRsZVRodW5rKGEsIGIpO1xuICAgICAgICAgICAgICAgIHZhciB0aHVua1BhdGNoID0gZGlmZihub2Rlcy5hLCBub2Rlcy5iKTtcbiAgICAgICAgICAgICAgICBpZiAoaGFzUGF0Y2hlcyh0aHVua1BhdGNoKSkge1xuICAgICAgICAgICAgICAgICAgICBwYXRjaFtpbmRleF0gPSBuZXcgVlBhdGNoKFZQYXRjaC5USFVOSywgbnVsbCwgdGh1bmtQYXRjaCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBmdW5jdGlvbiBoYXNQYXRjaGVzKHBhdGNoKSB7XG4gICAgICAgICAgICAgICAgZm9yICh2YXIgaW5kZXggaW4gcGF0Y2gpIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKGluZGV4ICE9PSBcImFcIikge1xuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIC8vIEV4ZWN1dGUgaG9va3Mgd2hlbiB0d28gbm9kZXMgYXJlIGlkZW50aWNhbFxuICAgICAgICAgICAgZnVuY3Rpb24gdW5ob29rKHZOb2RlLCBwYXRjaCwgaW5kZXgpIHtcbiAgICAgICAgICAgICAgICBpZiAoaXNWTm9kZSh2Tm9kZSkpIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKHZOb2RlLmhvb2tzKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBwYXRjaFtpbmRleF0gPSBhcHBlbmRQYXRjaChwYXRjaFtpbmRleF0sIG5ldyBWUGF0Y2goVlBhdGNoLlBST1BTLCB2Tm9kZSwgdW5kZWZpbmVkS2V5cyh2Tm9kZS5ob29rcykpKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgIGlmICh2Tm9kZS5kZXNjZW5kYW50SG9va3MgfHwgdk5vZGUuaGFzVGh1bmtzKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICB2YXIgY2hpbGRyZW4gPSB2Tm9kZS5jaGlsZHJlbjtcbiAgICAgICAgICAgICAgICAgICAgICAgIHZhciBsZW4gPSBjaGlsZHJlbi5sZW5ndGg7XG4gICAgICAgICAgICAgICAgICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IGxlbjsgaSsrKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdmFyIGNoaWxkID0gY2hpbGRyZW5baV07XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaW5kZXggKz0gMTtcblxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHVuaG9vayhjaGlsZCwgcGF0Y2gsIGluZGV4KTtcblxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChpc1ZOb2RlKGNoaWxkKSAmJiBjaGlsZC5jb3VudCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpbmRleCArPSBjaGlsZC5jb3VudDtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKGlzVGh1bmsodk5vZGUpKSB7XG4gICAgICAgICAgICAgICAgICAgIHRodW5rcyh2Tm9kZSwgbnVsbCwgcGF0Y2gsIGluZGV4KTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIHVuZGVmaW5lZEtleXMob2JqKSB7XG4gICAgICAgICAgICAgICAgdmFyIHJlc3VsdCA9IHt9O1xuXG4gICAgICAgICAgICAgICAgZm9yICh2YXIga2V5IGluIG9iaikge1xuICAgICAgICAgICAgICAgICAgICByZXN1bHRba2V5XSA9IHVuZGVmaW5lZDtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICByZXR1cm4gcmVzdWx0O1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAvLyBMaXN0IGRpZmYsIG5haXZlIGxlZnQgdG8gcmlnaHQgcmVvcmRlcmluZ1xuICAgICAgICAgICAgZnVuY3Rpb24gcmVvcmRlcihhQ2hpbGRyZW4sIGJDaGlsZHJlbikge1xuICAgICAgICAgICAgICAgIC8vIE8oTSkgdGltZSwgTyhNKSBtZW1vcnlcbiAgICAgICAgICAgICAgICB2YXIgYkNoaWxkSW5kZXggPSBrZXlJbmRleChiQ2hpbGRyZW4pO1xuICAgICAgICAgICAgICAgIHZhciBiS2V5cyA9IGJDaGlsZEluZGV4LmtleXM7XG4gICAgICAgICAgICAgICAgdmFyIGJGcmVlID0gYkNoaWxkSW5kZXguZnJlZTtcblxuICAgICAgICAgICAgICAgIGlmIChiRnJlZS5sZW5ndGggPT09IGJDaGlsZHJlbi5sZW5ndGgpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGNoaWxkcmVuOiBiQ2hpbGRyZW4sXG4gICAgICAgICAgICAgICAgICAgICAgICBtb3ZlczogbnVsbFxuICAgICAgICAgICAgICAgICAgICB9O1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIC8vIE8oTikgdGltZSwgTyhOKSBtZW1vcnlcbiAgICAgICAgICAgICAgICB2YXIgYUNoaWxkSW5kZXggPSBrZXlJbmRleChhQ2hpbGRyZW4pO1xuICAgICAgICAgICAgICAgIHZhciBhS2V5cyA9IGFDaGlsZEluZGV4LmtleXM7XG4gICAgICAgICAgICAgICAgdmFyIGFGcmVlID0gYUNoaWxkSW5kZXguZnJlZTtcblxuICAgICAgICAgICAgICAgIGlmIChhRnJlZS5sZW5ndGggPT09IGFDaGlsZHJlbi5sZW5ndGgpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGNoaWxkcmVuOiBiQ2hpbGRyZW4sXG4gICAgICAgICAgICAgICAgICAgICAgICBtb3ZlczogbnVsbFxuICAgICAgICAgICAgICAgICAgICB9O1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIC8vIE8oTUFYKE4sIE0pKSBtZW1vcnlcbiAgICAgICAgICAgICAgICB2YXIgbmV3Q2hpbGRyZW4gPSBbXTtcblxuICAgICAgICAgICAgICAgIHZhciBmcmVlSW5kZXggPSAwO1xuICAgICAgICAgICAgICAgIHZhciBmcmVlQ291bnQgPSBiRnJlZS5sZW5ndGg7XG4gICAgICAgICAgICAgICAgdmFyIGRlbGV0ZWRJdGVtcyA9IDA7XG5cbiAgICAgICAgICAgICAgICAvLyBJdGVyYXRlIHRocm91Z2ggYSBhbmQgbWF0Y2ggYSBub2RlIGluIGJcbiAgICAgICAgICAgICAgICAvLyBPKE4pIHRpbWUsXG4gICAgICAgICAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCBhQ2hpbGRyZW4ubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgICAgICAgICAgdmFyIGFJdGVtID0gYUNoaWxkcmVuW2ldO1xuICAgICAgICAgICAgICAgICAgICB2YXIgaXRlbUluZGV4O1xuXG4gICAgICAgICAgICAgICAgICAgIGlmIChhSXRlbS5rZXkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChiS2V5cy5oYXNPd25Qcm9wZXJ0eShhSXRlbS5rZXkpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gTWF0Y2ggdXAgdGhlIG9sZCBrZXlzXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaXRlbUluZGV4ID0gYktleXNbYUl0ZW0ua2V5XTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBuZXdDaGlsZHJlbi5wdXNoKGJDaGlsZHJlbltpdGVtSW5kZXhdKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gUmVtb3ZlIG9sZCBrZXllZCBpdGVtc1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGl0ZW1JbmRleCA9IGkgLSBkZWxldGVkSXRlbXMrKztcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBuZXdDaGlsZHJlbi5wdXNoKG51bGwpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgLy8gTWF0Y2ggdGhlIGl0ZW0gaW4gYSB3aXRoIHRoZSBuZXh0IGZyZWUgaXRlbSBpbiBiXG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoZnJlZUluZGV4IDwgZnJlZUNvdW50KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaXRlbUluZGV4ID0gYkZyZWVbZnJlZUluZGV4KytdO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIG5ld0NoaWxkcmVuLnB1c2goYkNoaWxkcmVuW2l0ZW1JbmRleF0pO1xuICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBUaGVyZSBhcmUgbm8gZnJlZSBpdGVtcyBpbiBiIHRvIG1hdGNoIHdpdGhcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyB0aGUgZnJlZSBpdGVtcyBpbiBhLCBzbyB0aGUgZXh0cmEgZnJlZSBub2Rlc1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIGFyZSBkZWxldGVkLlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGl0ZW1JbmRleCA9IGkgLSBkZWxldGVkSXRlbXMrKztcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBuZXdDaGlsZHJlbi5wdXNoKG51bGwpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgdmFyIGxhc3RGcmVlSW5kZXggPSBmcmVlSW5kZXggPj0gYkZyZWUubGVuZ3RoID8gYkNoaWxkcmVuLmxlbmd0aCA6IGJGcmVlW2ZyZWVJbmRleF07XG5cbiAgICAgICAgICAgICAgICAvLyBJdGVyYXRlIHRocm91Z2ggYiBhbmQgYXBwZW5kIGFueSBuZXcga2V5c1xuICAgICAgICAgICAgICAgIC8vIE8oTSkgdGltZVxuICAgICAgICAgICAgICAgIGZvciAodmFyIGogPSAwOyBqIDwgYkNoaWxkcmVuLmxlbmd0aDsgaisrKSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciBuZXdJdGVtID0gYkNoaWxkcmVuW2pdO1xuXG4gICAgICAgICAgICAgICAgICAgIGlmIChuZXdJdGVtLmtleSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKCFhS2V5cy5oYXNPd25Qcm9wZXJ0eShuZXdJdGVtLmtleSkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBBZGQgYW55IG5ldyBrZXllZCBpdGVtc1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIFdlIGFyZSBhZGRpbmcgbmV3IGl0ZW1zIHRvIHRoZSBlbmQgYW5kIHRoZW4gc29ydGluZyB0aGVtXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gaW4gcGxhY2UuIEluIGZ1dHVyZSB3ZSBzaG91bGQgaW5zZXJ0IG5ldyBpdGVtcyBpbiBwbGFjZS5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBuZXdDaGlsZHJlbi5wdXNoKG5ld0l0ZW0pO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKGogPj0gbGFzdEZyZWVJbmRleCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgLy8gQWRkIGFueSBsZWZ0b3ZlciBub24ta2V5ZWQgaXRlbXNcbiAgICAgICAgICAgICAgICAgICAgICAgIG5ld0NoaWxkcmVuLnB1c2gobmV3SXRlbSk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICB2YXIgc2ltdWxhdGUgPSBuZXdDaGlsZHJlbi5zbGljZSgpO1xuICAgICAgICAgICAgICAgIHZhciBzaW11bGF0ZUluZGV4ID0gMDtcbiAgICAgICAgICAgICAgICB2YXIgcmVtb3ZlcyA9IFtdO1xuICAgICAgICAgICAgICAgIHZhciBpbnNlcnRzID0gW107XG4gICAgICAgICAgICAgICAgdmFyIHNpbXVsYXRlSXRlbTtcblxuICAgICAgICAgICAgICAgIGZvciAodmFyIGsgPSAwOyBrIDwgYkNoaWxkcmVuLmxlbmd0aDspIHtcbiAgICAgICAgICAgICAgICAgICAgdmFyIHdhbnRlZEl0ZW0gPSBiQ2hpbGRyZW5ba107XG4gICAgICAgICAgICAgICAgICAgIHNpbXVsYXRlSXRlbSA9IHNpbXVsYXRlW3NpbXVsYXRlSW5kZXhdO1xuXG4gICAgICAgICAgICAgICAgICAgIC8vIHJlbW92ZSBpdGVtc1xuICAgICAgICAgICAgICAgICAgICB3aGlsZSAoc2ltdWxhdGVJdGVtID09PSBudWxsICYmIHNpbXVsYXRlLmxlbmd0aCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgcmVtb3Zlcy5wdXNoKHJlbW92ZShzaW11bGF0ZSwgc2ltdWxhdGVJbmRleCwgbnVsbCkpO1xuICAgICAgICAgICAgICAgICAgICAgICAgc2ltdWxhdGVJdGVtID0gc2ltdWxhdGVbc2ltdWxhdGVJbmRleF07XG4gICAgICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgICAgICBpZiAoIXNpbXVsYXRlSXRlbSB8fCBzaW11bGF0ZUl0ZW0ua2V5ICE9PSB3YW50ZWRJdGVtLmtleSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgLy8gaWYgd2UgbmVlZCBhIGtleSBpbiB0aGlzIHBvc2l0aW9uLi4uXG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAod2FudGVkSXRlbS5rZXkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoc2ltdWxhdGVJdGVtICYmIHNpbXVsYXRlSXRlbS5rZXkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gaWYgYW4gaW5zZXJ0IGRvZXNuJ3QgcHV0IHRoaXMga2V5IGluIHBsYWNlLCBpdCBuZWVkcyB0byBtb3ZlXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChiS2V5c1tzaW11bGF0ZUl0ZW0ua2V5XSAhPT0gayArIDEpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlbW92ZXMucHVzaChyZW1vdmUoc2ltdWxhdGUsIHNpbXVsYXRlSW5kZXgsIHNpbXVsYXRlSXRlbS5rZXkpKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNpbXVsYXRlSXRlbSA9IHNpbXVsYXRlW3NpbXVsYXRlSW5kZXhdO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gaWYgdGhlIHJlbW92ZSBkaWRuJ3QgcHV0IHRoZSB3YW50ZWQgaXRlbSBpbiBwbGFjZSwgd2UgbmVlZCB0byBpbnNlcnQgaXRcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmICghc2ltdWxhdGVJdGVtIHx8IHNpbXVsYXRlSXRlbS5rZXkgIT09IHdhbnRlZEl0ZW0ua2V5KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaW5zZXJ0cy5wdXNoKHsga2V5OiB3YW50ZWRJdGVtLmtleSwgdG86IGsgfSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBpdGVtcyBhcmUgbWF0Y2hpbmcsIHNvIHNraXAgYWhlYWRcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNpbXVsYXRlSW5kZXgrKztcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGluc2VydHMucHVzaCh7IGtleTogd2FudGVkSXRlbS5rZXksIHRvOiBrIH0pO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaW5zZXJ0cy5wdXNoKHsga2V5OiB3YW50ZWRJdGVtLmtleSwgdG86IGsgfSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGsrKztcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIGEga2V5IGluIHNpbXVsYXRlIGhhcyBubyBtYXRjaGluZyB3YW50ZWQga2V5LCByZW1vdmUgaXRcbiAgICAgICAgICAgICAgICAgICAgICAgIGVsc2UgaWYgKHNpbXVsYXRlSXRlbSAmJiBzaW11bGF0ZUl0ZW0ua2V5KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcmVtb3Zlcy5wdXNoKHJlbW92ZShzaW11bGF0ZSwgc2ltdWxhdGVJbmRleCwgc2ltdWxhdGVJdGVtLmtleSkpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgc2ltdWxhdGVJbmRleCsrO1xuICAgICAgICAgICAgICAgICAgICAgICAgaysrO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgLy8gcmVtb3ZlIGFsbCB0aGUgcmVtYWluaW5nIG5vZGVzIGZyb20gc2ltdWxhdGVcbiAgICAgICAgICAgICAgICB3aGlsZSAoc2ltdWxhdGVJbmRleCA8IHNpbXVsYXRlLmxlbmd0aCkge1xuICAgICAgICAgICAgICAgICAgICBzaW11bGF0ZUl0ZW0gPSBzaW11bGF0ZVtzaW11bGF0ZUluZGV4XTtcbiAgICAgICAgICAgICAgICAgICAgcmVtb3Zlcy5wdXNoKHJlbW92ZShzaW11bGF0ZSwgc2ltdWxhdGVJbmRleCwgc2ltdWxhdGVJdGVtICYmIHNpbXVsYXRlSXRlbS5rZXkpKTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAvLyBJZiB0aGUgb25seSBtb3ZlcyB3ZSBoYXZlIGFyZSBkZWxldGVzIHRoZW4gd2UgY2FuIGp1c3RcbiAgICAgICAgICAgICAgICAvLyBsZXQgdGhlIGRlbGV0ZSBwYXRjaCByZW1vdmUgdGhlc2UgaXRlbXMuXG4gICAgICAgICAgICAgICAgaWYgKHJlbW92ZXMubGVuZ3RoID09PSBkZWxldGVkSXRlbXMgJiYgIWluc2VydHMubGVuZ3RoKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiB7XG4gICAgICAgICAgICAgICAgICAgICAgICBjaGlsZHJlbjogbmV3Q2hpbGRyZW4sXG4gICAgICAgICAgICAgICAgICAgICAgICBtb3ZlczogbnVsbFxuICAgICAgICAgICAgICAgICAgICB9O1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHJldHVybiB7XG4gICAgICAgICAgICAgICAgICAgIGNoaWxkcmVuOiBuZXdDaGlsZHJlbixcbiAgICAgICAgICAgICAgICAgICAgbW92ZXM6IHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJlbW92ZXM6IHJlbW92ZXMsXG4gICAgICAgICAgICAgICAgICAgICAgICBpbnNlcnRzOiBpbnNlcnRzXG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9O1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBmdW5jdGlvbiByZW1vdmUoYXJyLCBpbmRleCwga2V5KSB7XG4gICAgICAgICAgICAgICAgYXJyLnNwbGljZShpbmRleCwgMSk7XG5cbiAgICAgICAgICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgICAgICAgICBmcm9tOiBpbmRleCxcbiAgICAgICAgICAgICAgICAgICAga2V5OiBrZXlcbiAgICAgICAgICAgICAgICB9O1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBmdW5jdGlvbiBrZXlJbmRleChjaGlsZHJlbikge1xuICAgICAgICAgICAgICAgIHZhciBrZXlzID0ge307XG4gICAgICAgICAgICAgICAgdmFyIGZyZWUgPSBbXTtcbiAgICAgICAgICAgICAgICB2YXIgbGVuZ3RoID0gY2hpbGRyZW4ubGVuZ3RoO1xuXG4gICAgICAgICAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCBsZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgICAgICAgICB2YXIgY2hpbGQgPSBjaGlsZHJlbltpXTtcblxuICAgICAgICAgICAgICAgICAgICBpZiAoY2hpbGQua2V5KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBrZXlzW2NoaWxkLmtleV0gPSBpO1xuICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgZnJlZS5wdXNoKGkpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgICAgICAgICAga2V5czoga2V5cywgLy8gQSBoYXNoIG9mIGtleSBuYW1lIHRvIGluZGV4XG4gICAgICAgICAgICAgICAgICAgIGZyZWU6IGZyZWUgLy8gQW4gYXJyYXkgb2YgdW5rZXllZCBpdGVtIGluZGljZXNcbiAgICAgICAgICAgICAgICB9O1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBmdW5jdGlvbiBhcHBlbmRQYXRjaChhcHBseSwgcGF0Y2gpIHtcbiAgICAgICAgICAgICAgICBpZiAoYXBwbHkpIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKGlzQXJyYXkoYXBwbHkpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBhcHBseS5wdXNoKHBhdGNoKTtcbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGFwcGx5ID0gW2FwcGx5LCBwYXRjaF07XG4gICAgICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgICAgICByZXR1cm4gYXBwbHk7XG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHBhdGNoO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgfSwgeyBcIi4uL3Zub2RlL2hhbmRsZS10aHVua1wiOiAyNCwgXCIuLi92bm9kZS9pcy10aHVua1wiOiAyNSwgXCIuLi92bm9kZS9pcy12bm9kZVwiOiAyNywgXCIuLi92bm9kZS9pcy12dGV4dFwiOiAyOCwgXCIuLi92bm9kZS9pcy13aWRnZXRcIjogMjksIFwiLi4vdm5vZGUvdnBhdGNoXCI6IDMyLCBcIi4vZGlmZi1wcm9wc1wiOiAzNCwgXCJ4LWlzLWFycmF5XCI6IDEyIH1dIH0sIHt9LCBbNF0pKDQpO1xufSk7XG5cbmNvbnN0IENvcmUgPSBDO1xuXG5leHBvcnQgeyBDb3JlLCBLZXJuZWwsIEVudW0sIExpc3QsIEtleXdvcmQsIGJpdHdpc2UgYXMgQml0d2lzZSwgbWFwIGFzIE1hcCwgbWFwX3NldCBhcyBNYXBTZXQsIFZpcnR1YWxET00gfTsiXSwiZmlsZSI6IkVsaXhpci5qcyIsInNvdXJjZVJvb3QiOiIvc291cmNlLyJ9 \ No newline at end of file diff --git a/src/javascript/lib/core.js b/src/javascript/lib/core.js index 4414bb3e..10708900 100644 --- a/src/javascript/lib/core.js +++ b/src/javascript/lib/core.js @@ -3,6 +3,7 @@ import { Tuple, PID, Integer, Float, List } from './core/primitives'; import BitString from './core/bit_string'; import Patterns from './core/patterns'; import Functions from './core/functions'; +import SpecialForms from './core/special_forms'; Functions.get_global().processes = Functions.get_global().processes || new ProcessSystem(); @@ -15,5 +16,6 @@ export { Integer, Float, Functions, - List + List, + SpecialForms } diff --git a/src/javascript/lib/core/special_forms.js b/src/javascript/lib/core/special_forms.js new file mode 100644 index 00000000..dc6d235f --- /dev/null +++ b/src/javascript/lib/core/special_forms.js @@ -0,0 +1,136 @@ +import BitString from './bit_string'; +import Patterns from './patterns'; +import { Tuple } from './primitives'; + +function list(...args){ + return Object.freeze(args); +} + +function bitstring(...args){ + return new BitString(...args); +} + +function tuple(...args){ + return new Tuple(...args); +} + +function _case(condition, clauses){ + return Patterns.defmatch(...clauses)(condition); +} + +function cond(clauses){ + for(let clause of clauses){ + if(clause[0]){ + return clause[1](); + } + } + + throw new Error(); +} + +function map(obj){ + return Object.freeze(obj); +} + +function map_update(map, values){ + return Object.freeze( + Object.assign( + Object.create(map.constructor.prototype), map, values + ) + ); +} + +function _for(collections, fun, filter = () => true, into = [], previousValues = []){ + let pattern = collections[0][0]; + let collection = collections[0][1]; + + if(collections.length === 1){ + + for(let elem of collection){ + let r = Patterns.match_no_throw(pattern, elem); + let args = previousValues.concat(r); + + if(r && filter.apply(this, args)){ + into = into.concat([fun.apply(this, args)]); + } + } + + return into; + }else{ + let _into = [] + + for(let elem of collection){ + let r = Patterns.match_no_throw(pattern, elem); + if(r){ + _into = into.concat(this._for(collections.slice(1), fun, filter, _into, previousValues.concat(r))); + } + } + + return _into; + } +} + +function _try(do_fun, rescue_function, catch_fun, else_function, after_function){ + let result = null; + + try{ + result = do_fun(); + }catch(e){ + let ex_result = null; + + if(rescue_function){ + try{ + ex_result = rescue_function(e); + return ex_result; + }catch(ex){ + if(ex instanceof Patterns.MatchError){ + throw ex; + } + } + } + + if(catch_fun){ + try{ + ex_result = catch_fun(e); + return ex_result; + }catch(ex){ + if(ex instanceof Patterns.MatchError){ + throw ex; + } + } + } + + throw e; + + }finally{ + if(after_function){ + after_function(); + } + } + + if(else_function){ + try{ + return else_function(result); + }catch(ex){ + if(ex instanceof Patterns.MatchError){ + throw new Error("No Match Found in Else"); + } + + throw ex; + } + }else{ + return result; + } +} + +export default { + list, + bitstring, + tuple, + _case, + cond, + map, + map_update, + _for, + _try +}; diff --git a/src/javascript/lib/kernel.js b/src/javascript/lib/kernel.js index a80eeac0..5bb1f203 100644 --- a/src/javascript/lib/kernel.js +++ b/src/javascript/lib/kernel.js @@ -1,8 +1,7 @@ -import SpecialForms from './kernel/special_forms'; import * as Core from './core'; function tl(list){ - return SpecialForms.list(...list.slice(1)); + return Core.SpecialForms.list(...list.slice(1)); } function hd(list){ @@ -146,7 +145,6 @@ function match__qmark__(pattern, expr, guard = () => true){ } export default { - SpecialForms, tl, hd, is_nil, diff --git a/src/javascript/lib/list.js b/src/javascript/lib/list.js index 06b98c74..f8b9a3e4 100644 --- a/src/javascript/lib/list.js +++ b/src/javascript/lib/list.js @@ -16,7 +16,7 @@ List.delete = function(list, item){ } } - return Core.List(...new_value); + return Core.SpecialForms.list(...new_value); }; List.delete_at = function(list, index){ @@ -28,7 +28,7 @@ List.delete_at = function(list, index){ } } - return Core.List(...new_value); + return Core.SpecialForms.list(...new_value); }; List.duplicate = function(elem, n){ @@ -38,14 +38,14 @@ List.duplicate = function(elem, n){ new_value.push(elem); } - return Core.List(...new_value); + return Core.SpecialForms.list(...new_value); }; List.first = function(list){ return list[0]; }; -List.flatten = function(list, tail = Core.List()){ +List.flatten = function(list, tail = Core.SpecialForms.list()){ let new_value = []; for(let x of list){ @@ -58,7 +58,7 @@ List.flatten = function(list, tail = Core.List()){ new_value = new_value.concat(tail); - return Core.List(...new_value); + return Core.SpecialForms.list(...new_value); }; List.foldl = function(list, acc, func){ @@ -87,7 +87,7 @@ List.insert_at = function(list, index, value){ } } - return Core.List(...new_value); + return Core.SpecialForms.list(...new_value); }; List.keydelete = function(list, key, position){ @@ -99,7 +99,7 @@ List.keydelete = function(list, key, position){ } } - return Core.List(...new_list); + return Core.SpecialForms.list(...new_list); }; List.keyfind = function(list, key, position, _default = null){ @@ -135,7 +135,7 @@ List.keyreplace = function(list, key, position, new_tuple){ } } - return Core.List(...new_list); + return Core.SpecialForms.list(...new_list); }; @@ -167,7 +167,7 @@ List.keysort = function(list, position){ }); - return Core.List(...new_list); + return Core.SpecialForms.list(...new_list); }; List.keystore = function(list, key, position, new_tuple){ @@ -187,7 +187,7 @@ List.keystore = function(list, key, position, new_tuple){ new_list.push(new_tuple); } - return Core.List(...new_list); + return Core.SpecialForms.list(...new_list); }; List.last = function(list){ @@ -205,7 +205,7 @@ List.replace_at = function(list, index, value){ } } - return Core.List(...new_value); + return Core.SpecialForms.list(...new_value); }; List.update_at = function(list, index, fun){ @@ -226,15 +226,15 @@ List.wrap = function(list){ if(Kernel.is_list(list)){ return list; }else if(list == null){ - return Core.List(); + return Core.SpecialForms.list(); }else{ - return Core.List(list); + return Core.SpecialForms.list(list); } }; List.zip = function(list_of_lists){ if(list_of_lists.length === 0){ - return Core.List(); + return Core.SpecialForms.list(); } let new_value = []; @@ -255,7 +255,7 @@ List.zip = function(list_of_lists){ new_value.push(new Core.Tuple(...current_value)); } - return Core.List(...new_value); + return Core.SpecialForms.list(...new_value); }; List.to_tuple = function(list){ @@ -263,11 +263,11 @@ List.to_tuple = function(list){ }; List.append = function(list, value){ - return Core.List(...list.concat([value])); + return Core.SpecialForms.list(...list.concat([value])); }; List.prepend = function(list, value){ - return Core.List(...[value].concat(list)); + return Core.SpecialForms.list(...[value].concat(list)); }; List.concat = function(left, right){ diff --git a/src/javascript/lib/map.js b/src/javascript/lib/map.js index 9939af0b..f2743434 100644 --- a/src/javascript/lib/map.js +++ b/src/javascript/lib/map.js @@ -1,8 +1,7 @@ -import SpecialForms from './kernel/special_forms'; import * as Core from './core'; function __new__(){ - return SpecialForms.map({}); + return Core.SpecialForms.map({}); } function keys(map){ @@ -18,10 +17,10 @@ function to_list(map){ let list = []; for(let key of map_keys){ - list.push(new Core.Tuple(key, map[key])); + list.push(Core.SpecialForms.tuple(key, map[key])); } - return Core.List(...list); + return Core.SpecialForms.list(...list); } function values(map){ @@ -32,14 +31,14 @@ function values(map){ list.push(map[key]); } - return Core.List(...list); + return Core.SpecialForms.list(...list); } function from_struct(struct){ let map = Object.assign({}, struct); delete map[Symbol.for("__struct__")]; - return SpecialForms.map(map); + return Core.SpecialForms.map(map); } function __delete__(map, key){ @@ -47,7 +46,7 @@ function __delete__(map, key){ delete new_map[key]; - return SpecialForms.map(new_map); + return Core.SpecialForms.map(new_map); } function drop(map, keys){ @@ -57,7 +56,7 @@ function drop(map, keys){ delete new_map[key]; } - return SpecialForms.map(new_map); + return Core.SpecialForms.map(new_map); } @@ -75,7 +74,7 @@ function fetch__emark__(map, key){ function fetch(map, key){ if(key in map){ - return new Core.Tuple(Symbol.for("ok"), map[key]); + return Core.SpecialForms.tuple(Symbol.for("ok"), map[key]); } return Symbol.for("error"); @@ -86,7 +85,7 @@ function has_key__qmark__(map, key){ } function merge(map1, map2){ - return SpecialForms.map_update(map1, map2); + return Core.SpecialForms.map_update(map1, map2); } function split(map, keys){ @@ -101,9 +100,9 @@ function split(map, keys){ } } - return new Core.Tuple( - SpecialForms.map(split1), - SpecialForms.map(split2) + return Core.SpecialForms.tuple( + Core.SpecialForms.map(split1), + Core.SpecialForms.map(split2) ); } @@ -116,7 +115,7 @@ function take(map, keys){ } } - return SpecialForms.map(split1); + return Core.SpecialForms.map(split1); } function drop(map, keys){ @@ -128,7 +127,7 @@ function drop(map, keys){ } } - return SpecialForms.map(split1); + return Core.SpecialForms.map(split1); } function put_new(map, key, value){ @@ -139,7 +138,7 @@ function put_new(map, key, value){ let new_map = Object.assign({}, map); new_map[key] = value; - return SpecialForms.map(new_map); + return Core.SpecialForms.map(new_map); } function put_new_lazy(map, key, fun){ @@ -150,7 +149,7 @@ function put_new_lazy(map, key, fun){ let new_map = Object.assign({}, map); new_map[key] = fun(); - return SpecialForms.map(new_map); + return Core.SpecialForms.map(new_map); } function get_and_update(map, key, fun){ @@ -161,32 +160,32 @@ function get_and_update(map, key, fun){ let new_map = Object.assign({}, map); new_map[key] = fun(map[key]); - return SpecialForms.map(new_map); + return Core.SpecialForms.map(new_map); } function pop_lazy(map, key, fun){ if(!key in map){ - return new Core.Tuple(fun(), map); + return Core.SpecialForms.tuple(fun(), map); } let new_map = Object.assign({}, map); let value = fun(new_map[key]); delete new_map[key]; - return new Core.Tuple(value, new_map); + return Core.SpecialForms.tuple(value, new_map); } function pop(map, key, _default = null){ if(!key in map){ - return new Core.Tuple(_default, map); + return Core.SpecialForms.tuple(_default, map); } let new_map = Object.assign({}, map); let value = new_map[key]; delete new_map[key]; - return new Core.Tuple(value, new_map); + return Core.SpecialForms.tuple(value, new_map); } function get_lazy(map, key, fun){ @@ -210,7 +209,7 @@ function put(map, key, val){ let new_map = Object({}, map); new_map[key] = val; - return SpecialForms.map(new_map); + return Core.SpecialForms.map(new_map); } function update__emark__(map, key, fun){ @@ -221,7 +220,7 @@ function update__emark__(map, key, fun){ let new_map = Object({}, map); new_map[key] = fun(map[key]); - return SpecialForms.map(new_map); + return Core.SpecialForms.map(new_map); } function update(map, key, initial, fun){ @@ -233,7 +232,7 @@ function update(map, key, initial, fun){ new_map[key] = fun(map[key]); } - return SpecialForms.map(new_map); + return Core.SpecialForms.map(new_map); } diff --git a/src/javascript/lib/map_set.js b/src/javascript/lib/map_set.js index 0e8e3cc2..37d8bd17 100644 --- a/src/javascript/lib/map_set.js +++ b/src/javascript/lib/map_set.js @@ -1,9 +1,8 @@ -import SpecialForms from './kernel/special_forms'; import List from './list'; import * as Core from './core'; function __new__(){ - return SpecialForms.map({ [Symbol.for("__struct__")]: Symbol.for("MapSet"), set: Core.List() }); + return Core.SpecialForms.map({ [Symbol.for("__struct__")]: Symbol.for("MapSet"), set: Core.List() }); } function size(map){ @@ -19,7 +18,7 @@ function __delete__(set, term){ let new_map = Object.assign({}, set); new_map.set = new_list; - return SpecialForms.map(new_map); + return Core.SpecialForms.map(new_map); } function put(set, term){ @@ -28,7 +27,7 @@ function put(set, term){ let new_map = Object.assign({}, set); new_map.set = new_list; - return SpecialForms.map(new_map); + return Core.SpecialForms.map(new_map); } return set; @@ -43,7 +42,7 @@ function difference(set1, set2){ } } - return SpecialForms.map(new_map); + return Core.SpecialForms.map(new_map); } @@ -56,7 +55,7 @@ function intersection(set1, set2){ } } - return SpecialForms.map(new_map); + return Core.SpecialForms.map(new_map); } @@ -67,7 +66,7 @@ function union(set1, set2){ new_map = put(new_map, val); } - return SpecialForms.map(new_map); + return Core.SpecialForms.map(new_map); } diff --git a/src/javascript/tests/bit_string.spec.js b/src/javascript/tests/bit_string.spec.js index f1d8f642..6fe37917 100644 --- a/src/javascript/tests/bit_string.spec.js +++ b/src/javascript/tests/bit_string.spec.js @@ -1,24 +1,25 @@ var BitString = require('../lib/core').BitString; var Kernel = require('../lib/kernel'); +var SpecialForms = require('../lib/core').SpecialForms; var expect = require('chai').expect; describe('BitString', function(){ describe('creation', function(){ it('create properly', function(){ - let bs = Kernel.SpecialForms.bitstring(BitString.integer(1)); + let bs = SpecialForms.bitstring(BitString.integer(1)); expect(Kernel.match__qmark__(bs.value, [1])).to.equal(true); - bs = Kernel.SpecialForms.bitstring(BitString.binary("foo")); + bs = SpecialForms.bitstring(BitString.binary("foo")); expect(Kernel.match__qmark__(bs.value, [102, 111, 111])).to.equal(true); - bs = Kernel.SpecialForms.bitstring(BitString.integer(0), BitString.binary("foo")); + bs = SpecialForms.bitstring(BitString.integer(0), BitString.binary("foo")); expect(Kernel.match__qmark__(bs.value, [0, 102, 111, 111])).to.equal(true); - bs = Kernel.SpecialForms.bitstring(BitString.float(3.14)); + bs = SpecialForms.bitstring(BitString.float(3.14)); expect(Kernel.match__qmark__(bs.value, [64, 9, 30, 184, 81, 235, 133, 31])).to.equal(true); - bs = Kernel.SpecialForms.bitstring(BitString.signed(BitString.integer(-100))); + bs = SpecialForms.bitstring(BitString.signed(BitString.integer(-100))); expect(Kernel.match__qmark__(bs.value, [156])).to.equal(true); }); }); diff --git a/src/javascript/tests/case.spec.js b/src/javascript/tests/case.spec.js index 1bc6d231..366ce313 100644 --- a/src/javascript/tests/case.spec.js +++ b/src/javascript/tests/case.spec.js @@ -1,6 +1,6 @@ var Patterns = require("../lib/core/patterns"); var Enum = require('../lib/enum'); -var Kernel = require('../lib/kernel'); +var SpecialForms = require('../lib/core').SpecialForms; var expect = require('chai').expect; @@ -9,7 +9,7 @@ describe('case', () => { it('case', () => { let clauses = [ Patterns.make_case( - [Kernel.SpecialForms.tuple(Symbol.for("selector"), Patterns.variable(), Patterns.variable())], + [SpecialForms.tuple(Symbol.for("selector"), Patterns.variable(), Patterns.variable())], function(i, value){ return value; }, function(i){ return Kernel.is_integer(i); } ), @@ -19,7 +19,7 @@ describe('case', () => { ) ]; - let result = Kernel.SpecialForms._case("thing", clauses); + let result = SpecialForms._case("thing", clauses); expect(result).to.equal("thing"); }); diff --git a/src/javascript/tests/cond.spec.js b/src/javascript/tests/cond.spec.js index 64de0089..ff53a9d2 100644 --- a/src/javascript/tests/cond.spec.js +++ b/src/javascript/tests/cond.spec.js @@ -1,6 +1,6 @@ var Patterns = require("../lib/core/patterns"); var Enum = require('../lib/enum'); -var Kernel = require('../lib/kernel'); +var SpecialForms = require('../lib/core').SpecialForms; var expect = require('chai').expect; @@ -13,7 +13,7 @@ describe('cond', () => { [ true, () => "This will"], ]; - let result = Kernel.SpecialForms.cond(clauses); + let result = SpecialForms.cond(clauses); expect(result).to.equal("This will"); }); diff --git a/src/javascript/tests/enum.spec.js b/src/javascript/tests/enum.spec.js deleted file mode 100644 index bbe29285..00000000 --- a/src/javascript/tests/enum.spec.js +++ /dev/null @@ -1,8 +0,0 @@ -var Enum = require('../lib/enum'); -var List = require('../lib/list'); -var expect = require('chai').expect; - -describe('Enum', function(){ - -}) - diff --git a/src/javascript/tests/for.spec.js b/src/javascript/tests/for.spec.js index 7bee1b0e..c8effdb0 100644 --- a/src/javascript/tests/for.spec.js +++ b/src/javascript/tests/for.spec.js @@ -1,6 +1,6 @@ var Patterns = require("../lib/core").Patterns; var Enum = require('../lib/enum'); -var Kernel = require('../lib/kernel'); +var SpecialForms = require('../lib/core').SpecialForms; var expect = require('chai').expect; const $ = Patterns.variable(); @@ -11,7 +11,7 @@ describe('for', () => { [$, [1, 2, 3, 4]] ]; - let result = Kernel.SpecialForms._for(collections, (n) => n * 2); + let result = SpecialForms._for(collections, (n) => n * 2); expect(result).to.eql([2, 4, 6, 8]); }); @@ -23,7 +23,7 @@ describe('for', () => { [$, [2, 3]] ]; - let result = Kernel.SpecialForms._for(collections, (x, y) => x * y); + let result = SpecialForms._for(collections, (x, y) => x * y); expect(result).to.eql([2, 3, 4, 6]); }); @@ -35,7 +35,7 @@ describe('for', () => { [$, [1, 2, 3, 4, 5, 6]] ]; - let result = Kernel.SpecialForms._for(collections, (n) => n, (n) => n % 2 == 0); + let result = SpecialForms._for(collections, (n) => n, (n) => n % 2 == 0); expect(result).to.eql([2, 4, 6]); }); @@ -48,7 +48,7 @@ describe('for', () => { [[Symbol.for("user"), $], [[Symbol.for("user"), "john"], [Symbol.for("admin"), "john"], [Symbol.for("user"), "meg"]]] ]; - let result = Kernel.SpecialForms._for(collections, (name) => name.toUpperCase()); + let result = SpecialForms._for(collections, (name) => name.toUpperCase()); expect(result).to.eql(["JOHN", "MEG"]); }); diff --git a/src/javascript/tests/kernel.spec.js b/src/javascript/tests/kernel.spec.js index e86df3ef..ee3a2ac0 100644 --- a/src/javascript/tests/kernel.spec.js +++ b/src/javascript/tests/kernel.spec.js @@ -1,4 +1,5 @@ var Kernel = require('../lib/kernel'); +var SpecialForms = require('../lib/core').SpecialForms; var expect = require('chai').expect; describe('Kernel', function(){ @@ -26,9 +27,9 @@ describe('Kernel', function(){ }); it('match tuples', function(){ - expect(Kernel.match__qmark__(Kernel.SpecialForms.tuple(1, 2, 3), Kernel.SpecialForms.tuple(1, 2, 3))).to.equal(true); - expect(Kernel.match__qmark__(Kernel.SpecialForms.tuple(1, undefined, 3), Kernel.SpecialForms.tuple(1, 2, 3))).to.equal(true); - expect(Kernel.match__qmark__(Kernel.SpecialForms.tuple(1, 2, 3), Kernel.SpecialForms.tuple(1, 2))).to.equal(false); + expect(Kernel.match__qmark__(SpecialForms.tuple(1, 2, 3), SpecialForms.tuple(1, 2, 3))).to.equal(true); + expect(Kernel.match__qmark__(SpecialForms.tuple(1, undefined, 3), SpecialForms.tuple(1, 2, 3))).to.equal(true); + expect(Kernel.match__qmark__(SpecialForms.tuple(1, 2, 3), SpecialForms.tuple(1, 2))).to.equal(false); }); it('match list', function(){ @@ -50,4 +51,3 @@ describe('Kernel', function(){ }); }); }); - diff --git a/src/javascript/tests/list.spec.js b/src/javascript/tests/list.spec.js index 3e42a162..21d68d66 100644 --- a/src/javascript/tests/list.spec.js +++ b/src/javascript/tests/list.spec.js @@ -1,5 +1,6 @@ var List = require('../lib/list'); var Kernel = require('../lib/kernel'); +var SpecialForms = require('../lib/core').SpecialForms; var expect = require('chai').expect; describe('List', function(){ @@ -20,7 +21,7 @@ describe('List', function(){ describe('delete_at', function(){ it('must delete first item', function(){ - let t = Kernel.SpecialForms.list(1, 2, 3); + let t = SpecialForms.list(1, 2, 3); t = List.delete_at(t, 0); expect(t[0]).to.equal(2); }) @@ -28,7 +29,7 @@ describe('List', function(){ describe('delete', function(){ it('delete item in list', function(){ - let t = Kernel.SpecialForms.list(Symbol.for("a"), Symbol.for("b"), Symbol.for("c")); + let t = SpecialForms.list(Symbol.for("a"), Symbol.for("b"), Symbol.for("c")); t = List.delete(t, Symbol.for("b")); expect(t[1]).to.equal(Symbol.for("c")); }) @@ -36,7 +37,7 @@ describe('List', function(){ describe('flatten', function(){ it('must flatten a list into one list', function(){ - let t = Kernel.SpecialForms.list(1, Kernel.SpecialForms.list(2), 3); + let t = SpecialForms.list(1, SpecialForms.list(2), 3); t = List.flatten(t); @@ -46,7 +47,7 @@ describe('List', function(){ }) it('must flatten a deeply nested list into one list', function(){ - let t = Kernel.SpecialForms.list(1, Kernel.SpecialForms.list(2, Kernel.SpecialForms.list(4)), 3); + let t = SpecialForms.list(1, SpecialForms.list(2, SpecialForms.list(4)), 3); t = List.flatten(t); @@ -59,14 +60,14 @@ describe('List', function(){ describe('toString', function(){ it('must display correctly', function(){ - let t = Kernel.SpecialForms.list(1, 2, 3); + let t = SpecialForms.list(1, 2, 3); expect(t.toString()).to.equal('1,2,3'); }) }) describe('destructuring', function(){ it('destructure into an array', function(){ - let t = Kernel.SpecialForms.list(1, 2, 3); + let t = SpecialForms.list(1, 2, 3); let [a, b, c] = t; expect(a).to.equal(1); expect(b).to.equal(2); @@ -74,4 +75,3 @@ describe('List', function(){ }) }) }) - diff --git a/src/javascript/tests/map.spec.js b/src/javascript/tests/map.spec.js index 3e3c99cd..6f8e4539 100644 --- a/src/javascript/tests/map.spec.js +++ b/src/javascript/tests/map.spec.js @@ -1,5 +1,6 @@ var Map = require('../lib/map'); var Kernel = require('../lib/kernel'); +var SpecialForms = require('../lib/core').SpecialForms; var expect = require('chai').expect; describe('Map', function(){ @@ -22,7 +23,7 @@ describe('Map', function(){ let map = Map.new(); map = Map.put(map, "hello", "world"); - expect(Map.to_list(map)).to.deep.equal([Kernel.SpecialForms.tuple("hello", "world")]); + expect(Map.to_list(map)).to.deep.equal([SpecialForms.tuple("hello", "world")]); }); it('delete', function(){ @@ -32,8 +33,7 @@ describe('Map', function(){ expect(Map.keys(map).length).to.equal(1); map = Map.delete(map, "hello") - expect(Map.keys(map).length).to.equal(0); + expect(Map.keys(map).length).to.equal(0); }); }) - diff --git a/src/javascript/tests/special_forms.spec.js b/src/javascript/tests/special_forms.spec.js index 1650cd7f..8d628e7b 100644 --- a/src/javascript/tests/special_forms.spec.js +++ b/src/javascript/tests/special_forms.spec.js @@ -1,4 +1,4 @@ -var SpecialForms = require('../lib/kernel/special_forms'); +var SpecialForms = require('../lib/core').SpecialForms; var expect = require('chai').expect; describe('SpecialForms', function(){ diff --git a/src/javascript/tests/try.spec.js b/src/javascript/tests/try.spec.js index 4bb50436..f28af45f 100644 --- a/src/javascript/tests/try.spec.js +++ b/src/javascript/tests/try.spec.js @@ -1,6 +1,7 @@ var Patterns = require("../lib/core/patterns"); var Enum = require('../lib/enum'); var Kernel = require('../lib/kernel'); +var SpecialForms = require('../lib/core').SpecialForms; var expect = require('chai').expect; @@ -21,7 +22,7 @@ describe('try', () => { let x = 1; - let value = Kernel.SpecialForms._try(function() { + let value = SpecialForms._try(function() { return 1 / x; }, null, null, Patterns.defmatch(Patterns.make_case([Patterns.variable()], function(y) { return Symbol.for('small'); diff --git a/test/elixir_script_test.exs b/test/elixir_script_test.exs index 7735f87c..9c2aed13 100644 --- a/test/elixir_script_test.exs +++ b/test/elixir_script_test.exs @@ -72,7 +72,7 @@ defmodule ElixirScript.Test do import * as Elixir$ElixirScript$Kernel from './Elixir.ElixirScript.Kernel'; import * as Elixir$Animals$Elephant from './Elixir.Animals.Elephant'; const something = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([],function() { - return Elixir$Animals$Elephant.Elixir$Animals$Elephant.create(Elixir.Kernel.SpecialForms.map({})); + return Elixir$Animals$Elephant.Elixir$Animals$Elephant.create(Elixir.Core.SpecialForms.map({})); })); export { something diff --git a/test/lib/js_test.exs b/test/lib/js_test.exs index 9433a4ef..74fa3070 100644 --- a/test/lib/js_test.exs +++ b/test/lib/js_test.exs @@ -30,7 +30,7 @@ defmodule ElixirScript.Lib.JS.Test do end js_code = """ - A['b'] = Elixir.Core.List(1, 2, 3) + A['b'] = Elixir.Core.SpecialForms.list(1, 2, 3) """ assert_translation(ex_ast, js_code) diff --git a/test/lib/kernel_test.exs b/test/lib/kernel_test.exs index e27dfa70..9563f847 100644 --- a/test/lib/kernel_test.exs +++ b/test/lib/kernel_test.exs @@ -8,7 +8,7 @@ defmodule ElixirScript.Lib.Elixir.Kernel.Test do end js_code = """ - Elixir$ElixirScript$Range.Elixir$ElixirScript$Range.create(Elixir.Kernel.SpecialForms.map({ + Elixir$ElixirScript$Range.Elixir$ElixirScript$Range.create(Elixir.Core.SpecialForms.map({ [Symbol.for('first')]: 1, [Symbol.for('last')]: 4 })) diff --git a/test/translator/assignment_test.exs b/test/translator/assignment_test.exs index 363e1e7e..363fd801 100644 --- a/test/translator/assignment_test.exs +++ b/test/translator/assignment_test.exs @@ -21,8 +21,8 @@ defmodule ElixirScript.Translator.Assignment.Test do js_code = """ let [a, b] = Elixir.Core.Patterns.match(Elixir.Core.Patterns.type(Elixir.Core.Tuple, { values: [Elixir.Core.Patterns.variable(), Elixir.Core.Patterns.variable()] - }), Elixir.Core.Functions.new_tuple(1, 2)); - let _ref = Elixir.Core.Functions.new_tuple(a, b); + }), Elixir.Core.SpecialForms.tuple(1, 2)); + let _ref = Elixir.Core.SpecialForms.tuple(a, b); """ assert_translation(ex_ast, js_code) @@ -31,8 +31,8 @@ defmodule ElixirScript.Translator.Assignment.Test do js_code = """ let [a, undefined, c] = Elixir.Core.Patterns.match(Elixir.Core.Patterns.type(Elixir.Core.Tuple, { values: [Elixir.Core.Patterns.variable(), Elixir.Core.Patterns.wildcard(), Elixir.Core.Patterns.variable()] - }), Elixir.Core.Functions.new_tuple(1, 2, 3)); - let _ref = Elixir.Core.Functions.new_tuple(a, undefined, c); + }), Elixir.Core.SpecialForms.tuple(1, 2, 3)); + let _ref = Elixir.Core.SpecialForms.tuple(a, undefined, c); """ assert_translation(ex_ast, js_code) @@ -42,8 +42,8 @@ defmodule ElixirScript.Translator.Assignment.Test do js_code = """ let [, undefined, c] = Elixir.Core.Patterns.match(Elixir.Core.Patterns.type(Elixir.Core.Tuple, { values: [Elixir.Core.Patterns.bound(a), Elixir.Core.Patterns.wildcard(), Elixir.Core.Patterns.variable()] - }), Elixir.Core.Functions.new_tuple(1, 2, 3)); - let _ref = Elixir.Core.Functions.new_tuple(undefined, undefined, c); + }), Elixir.Core.SpecialForms.tuple(1, 2, 3)); + let _ref = Elixir.Core.SpecialForms.tuple(undefined, undefined, c); """ assert_translation(ex_ast, js_code) @@ -61,8 +61,8 @@ defmodule ElixirScript.Translator.Assignment.Test do should "translate list assignment" do ex_ast = quote do: [a, b] = [1, 2] js_code = """ - let [a, b] = Elixir.Core.Patterns.match(Elixir.Core.List(Elixir.Core.Patterns.variable(), Elixir.Core.Patterns.variable()), Elixir.Core.List(1, 2)); - let _ref = Elixir.Core.List(a, b); + let [a, b] = Elixir.Core.Patterns.match(Elixir.Core.SpecialForms.list(Elixir.Core.Patterns.variable(), Elixir.Core.Patterns.variable()), Elixir.Core.SpecialForms.list(1, 2)); + let _ref = Elixir.Core.SpecialForms.list(a, b); """ assert_translation(ex_ast, js_code) @@ -71,8 +71,8 @@ defmodule ElixirScript.Translator.Assignment.Test do should "translate head/tail assignment" do ex_ast = quote do: [a | b] = [1, 2, 3, 4] js_code = """ - let [a,b] = Elixir.Core.Patterns.match(Elixir.Core.Patterns.headTail(),Elixir.Core.List(1,2,3,4)); - let _ref = Elixir.Core.List(a,b); + let [a,b] = Elixir.Core.Patterns.match(Elixir.Core.Patterns.headTail(),Elixir.Core.SpecialForms.list(1,2,3,4)); + let _ref = Elixir.Core.SpecialForms.list(a,b); """ assert_translation(ex_ast, js_code) diff --git a/test/translator/bitstring_test.exs b/test/translator/bitstring_test.exs index d2e1a335..886565ed 100644 --- a/test/translator/bitstring_test.exs +++ b/test/translator/bitstring_test.exs @@ -4,39 +4,39 @@ defmodule ElixirScript.Translator.Bitstring.Test do should "translate bitstring" do ex_ast = quote do: <<1, 2, 3>> - assert_translation(ex_ast, "Elixir.Kernel.SpecialForms.bitstring(Elixir.Core.BitString.integer(1), Elixir.Core.BitString.integer(2), Elixir.Core.BitString.integer(3))") + assert_translation(ex_ast, "Elixir.Core.SpecialForms.bitstring(Elixir.Core.BitString.integer(1), Elixir.Core.BitString.integer(2), Elixir.Core.BitString.integer(3))") ex_ast = quote do: <<1, "foo">> - assert_translation(ex_ast, "Elixir.Kernel.SpecialForms.bitstring(Elixir.Core.BitString.integer(1), Elixir.Core.BitString.binary('foo'))") + assert_translation(ex_ast, "Elixir.Core.SpecialForms.bitstring(Elixir.Core.BitString.integer(1), Elixir.Core.BitString.binary('foo'))") ex_ast = quote do: <<1, "foo" :: binary>> - assert_translation(ex_ast, "Elixir.Kernel.SpecialForms.bitstring(Elixir.Core.BitString.integer(1), Elixir.Core.BitString.binary('foo'))") + assert_translation(ex_ast, "Elixir.Core.SpecialForms.bitstring(Elixir.Core.BitString.integer(1), Elixir.Core.BitString.binary('foo'))") ex_ast = quote do: <<1, "foo" :: utf8, "bar" :: utf32>> - assert_translation(ex_ast, "Elixir.Kernel.SpecialForms.bitstring(Elixir.Core.BitString.integer(1), Elixir.Core.BitString.utf8('foo'), Elixir.Core.BitString.utf32('bar'))") + assert_translation(ex_ast, "Elixir.Core.SpecialForms.bitstring(Elixir.Core.BitString.integer(1), Elixir.Core.BitString.utf8('foo'), Elixir.Core.BitString.utf32('bar'))") ex_ast = quote do: <<102 :: integer-native, rest :: binary>> - assert_translation(ex_ast, "Elixir.Kernel.SpecialForms.bitstring(Elixir.Core.BitString.native(Elixir.Core.BitString.integer(102)), Elixir.Core.BitString.binary(rest))") + assert_translation(ex_ast, "Elixir.Core.SpecialForms.bitstring(Elixir.Core.BitString.native(Elixir.Core.BitString.integer(102)), Elixir.Core.BitString.binary(rest))") ex_ast = quote do: <<102 :: unsigned-big-integer, rest :: binary>> - assert_translation(ex_ast, "Elixir.Kernel.SpecialForms.bitstring(Elixir.Core.BitString.integer(Elixir.Core.BitString.big(Elixir.Core.BitString.unsigned(102))), Elixir.Core.BitString.binary(rest))") + assert_translation(ex_ast, "Elixir.Core.SpecialForms.bitstring(Elixir.Core.BitString.integer(Elixir.Core.BitString.big(Elixir.Core.BitString.unsigned(102))), Elixir.Core.BitString.binary(rest))") ex_ast = quote do: <<102, _rest :: size(16)>> - assert_translation(ex_ast, "Elixir.Kernel.SpecialForms.bitstring(Elixir.Core.BitString.integer(102), Elixir.Core.BitString.size(_rest, 16))") + assert_translation(ex_ast, "Elixir.Core.SpecialForms.bitstring(Elixir.Core.BitString.integer(102), Elixir.Core.BitString.size(_rest, 16))") ex_ast = quote do: <<102, _rest :: size(16)-unit(4)>> - assert_translation(ex_ast, "Elixir.Kernel.SpecialForms.bitstring(Elixir.Core.BitString.integer(102), Elixir.Core.BitString.unit(Elixir.Core.BitString.size(_rest, 16), 4))") + assert_translation(ex_ast, "Elixir.Core.SpecialForms.bitstring(Elixir.Core.BitString.integer(102), Elixir.Core.BitString.unit(Elixir.Core.BitString.size(_rest, 16), 4))") ex_ast = quote do: <<102, _rest :: 16 * 4>> - assert_translation(ex_ast, "Elixir.Kernel.SpecialForms.bitstring(Elixir.Core.BitString.integer(102), Elixir.Core.BitString.unit(Elixir.Core.BitString.size(_rest, 16), 4))") + assert_translation(ex_ast, "Elixir.Core.SpecialForms.bitstring(Elixir.Core.BitString.integer(102), Elixir.Core.BitString.unit(Elixir.Core.BitString.size(_rest, 16), 4))") ex_ast = quote do: <<102, _rest :: _ * 4>> - assert_translation(ex_ast, "Elixir.Kernel.SpecialForms.bitstring(Elixir.Core.BitString.integer(102), Elixir.Core.BitString.unit(Elixir.Core.BitString.size(_rest, undefined), 4))") + assert_translation(ex_ast, "Elixir.Core.SpecialForms.bitstring(Elixir.Core.BitString.integer(102), Elixir.Core.BitString.unit(Elixir.Core.BitString.size(_rest, undefined), 4))") ex_ast = quote do: <<102, _rest :: 16>> - assert_translation(ex_ast, "Elixir.Kernel.SpecialForms.bitstring(Elixir.Core.BitString.integer(102), Elixir.Core.BitString.size(_rest, 16))") + assert_translation(ex_ast, "Elixir.Core.SpecialForms.bitstring(Elixir.Core.BitString.integer(102), Elixir.Core.BitString.size(_rest, 16))") ex_ast = quote do: << 1, <<2>> >> - assert_translation(ex_ast, "Elixir.Kernel.SpecialForms.bitstring(Elixir.Core.BitString.integer(1), Elixir.Kernel.SpecialForms.bitstring(Elixir.Core.BitString.integer(2)))") + assert_translation(ex_ast, "Elixir.Core.SpecialForms.bitstring(Elixir.Core.BitString.integer(1), Elixir.Core.SpecialForms.bitstring(Elixir.Core.BitString.integer(2)))") end end diff --git a/test/translator/bug_test.exs b/test/translator/bug_test.exs index 19858c9e..5c9ba2ea 100644 --- a/test/translator/bug_test.exs +++ b/test/translator/bug_test.exs @@ -28,7 +28,7 @@ defmodule ElixirScript.Translator.Bug.Test do end js_code = """ - React.createElement(React.Text,Elixir.Kernel.SpecialForms.map({ + React.createElement(React.Text,Elixir.Core.SpecialForms.map({ style: Elixir.Core.Functions.call_property(styles,'welcome') }),'Welcome to React Native!') """ @@ -118,7 +118,7 @@ defmodule ElixirScript.Translator.Bug.Test do js_code = """ const getDispatcher = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([],function() { - return DeLorean.Flux.createDispatcher(Elixir.Kernel.SpecialForms.map({ + return DeLorean.Flux.createDispatcher(Elixir.Core.SpecialForms.map({ [Symbol.for('startPainting')]: Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([],function() { return this.dispatch('startPainting'); })), [Symbol.for('stopPainting')]: Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([],function() { @@ -126,7 +126,7 @@ defmodule ElixirScript.Translator.Bug.Test do })), [Symbol.for('addPoint')]: Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable()],function(data) { return this.dispatch('addPoint',data); })), [Symbol.for('getStores')]: Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([],function() { - return Elixir.Kernel.SpecialForms.map({ + return Elixir.Core.SpecialForms.map({ [Symbol.for('graphic')]: GraphicStore }); })) diff --git a/test/translator/capture_test.exs b/test/translator/capture_test.exs index 1039a855..6c75f7a2 100644 --- a/test/translator/capture_test.exs +++ b/test/translator/capture_test.exs @@ -74,7 +74,7 @@ defmodule ElixirScript.Translator.Capture.Test do js_code = """ let [fun] = Elixir.Core.Patterns.match(Elixir.Core.Patterns.variable(),Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable(), Elixir.Core.Patterns.variable()],function(__1,__2) { - return Elixir.Core.Functions.new_tuple(__1,__2); + return Elixir.Core.SpecialForms.tuple(__1,__2); }))); """ @@ -86,7 +86,7 @@ defmodule ElixirScript.Translator.Capture.Test do js_code = """ let [fun] = Elixir.Core.Patterns.match(Elixir.Core.Patterns.variable(),Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable(), Elixir.Core.Patterns.variable(), Elixir.Core.Patterns.variable()],function(__1,__2,__3) { - return Elixir.Core.Functions.new_tuple(__1,__2,__3); + return Elixir.Core.SpecialForms.tuple(__1,__2,__3); }))); """ diff --git a/test/translator/case_test.exs b/test/translator/case_test.exs index 297ca27b..29a245d8 100644 --- a/test/translator/case_test.exs +++ b/test/translator/case_test.exs @@ -75,7 +75,7 @@ defmodule ElixirScript.Translator.Case.Test do let [value] = Elixir.Core.Patterns.match(Elixir.Core.Patterns.variable(),13); return value; },function(number) { - return Elixir.Core.Functions.contains(number,Elixir.Core.List(1,2,3,4)); + return Elixir.Core.Functions.contains(number,Elixir.Core.SpecialForms.list(1,2,3,4)); }),Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.wildcard()],function() { return true; })).call(this,data) diff --git a/test/translator/cond_test.exs b/test/translator/cond_test.exs index 3e066f58..363dcab4 100644 --- a/test/translator/cond_test.exs +++ b/test/translator/cond_test.exs @@ -15,11 +15,11 @@ defmodule ElixirScript.Translator.Cond.Test do end js_code = """ - Elixir.Kernel.SpecialForms.cond(Elixir.Core.List(1 + 1 == 1,function() { + Elixir.Core.SpecialForms.cond(Elixir.Core.SpecialForms.list(1 + 1 == 1,function() { return 'This will never match'; - }),Elixir.Core.List(2 * 2 != 4,function() { + }),Elixir.Core.SpecialForms.list(2 * 2 != 4,function() { return 'Nor this'; - }),Elixir.Core.List(true,function() { + }),Elixir.Core.SpecialForms.list(true,function() { return 'This will'; })) """ @@ -41,13 +41,13 @@ defmodule ElixirScript.Translator.Cond.Test do end js_code = """ - Elixir.Kernel.SpecialForms.cond(Elixir.Core.List(1 + 1 == 1,function() { + Elixir.Core.SpecialForms.cond(Elixir.Core.SpecialForms.list(1 + 1 == 1,function() { let [a] = Elixir.Core.Patterns.match(Elixir.Core.Patterns.variable(),1); return 'This will never match'; - }),Elixir.Core.List(2 * 2 != 4,function() { + }),Elixir.Core.SpecialForms.list(2 * 2 != 4,function() { let [a] = Elixir.Core.Patterns.match(Elixir.Core.Patterns.variable(),2); return 'Nor this'; - }),Elixir.Core.List(true,function() { + }),Elixir.Core.SpecialForms.list(true,function() { let [a] = Elixir.Core.Patterns.match(Elixir.Core.Patterns.variable(),3); return 'This will'; })) diff --git a/test/translator/defmodule_test.exs b/test/translator/defmodule_test.exs index 640ba3d1..fb87a6af 100644 --- a/test/translator/defmodule_test.exs +++ b/test/translator/defmodule_test.exs @@ -74,7 +74,7 @@ defmodule ElixirScript.Translator.Defmodule.Test do })); const something = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([],function() { - return Elixir$Animals$Elephant.Elixir$Animals$Elephant.create(Elixir.Kernel.SpecialForms.map({})); + return Elixir$Animals$Elephant.Elixir$Animals$Elephant.create(Elixir.Core.SpecialForms.map({})); })); export { @@ -125,7 +125,7 @@ defmodule ElixirScript.Translator.Defmodule.Test do return null; })); const something = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([],function() { - return Elixir$Animals$Elephant.Elixir$Animals$Elephant.create(Elixir.Kernel.SpecialForms.map({})); + return Elixir$Animals$Elephant.Elixir$Animals$Elephant.create(Elixir.Core.SpecialForms.map({})); })); export { diff --git a/test/translator/for_test.exs b/test/translator/for_test.exs index 4b2b94f7..ad9b8550 100644 --- a/test/translator/for_test.exs +++ b/test/translator/for_test.exs @@ -8,11 +8,11 @@ defmodule ElixirScript.Translator.For.Test do end js_code = """ - Elixir.Kernel.SpecialForms._for(Elixir.Core.List(Elixir.Core.List(Elixir.Core.Patterns.variable(),Elixir.Core.List(1,2,3,4))),function(n) { + Elixir.Core.SpecialForms._for(Elixir.Core.SpecialForms.list(Elixir.Core.SpecialForms.list(Elixir.Core.Patterns.variable(),Elixir.Core.SpecialForms.list(1,2,3,4))),function(n) { return n * 2; },function() { return true; - },Elixir.Core.List()) + },Elixir.Core.SpecialForms.list()) """ assert_translation(ex_ast, js_code) @@ -24,11 +24,11 @@ defmodule ElixirScript.Translator.For.Test do end js_code = """ - Elixir.Kernel.SpecialForms._for(Elixir.Core.List(Elixir.Core.List(Elixir.Core.Patterns.variable(),Elixir.Core.List(1,2,3,4))),function(n) { + Elixir.Core.SpecialForms._for(Elixir.Core.SpecialForms.list(Elixir.Core.SpecialForms.list(Elixir.Core.Patterns.variable(),Elixir.Core.SpecialForms.list(1,2,3,4))),function(n) { return n * 2; },function() { return true; - },Elixir.Core.List()) + },Elixir.Core.SpecialForms.list()) """ assert_translation(ex_ast, js_code) @@ -40,11 +40,11 @@ defmodule ElixirScript.Translator.For.Test do end js_code = """ - Elixir.Kernel.SpecialForms._for(Elixir.Core.List(Elixir.Core.List(Elixir.Core.Patterns.variable(),'Opera')),function(n) { + Elixir.Core.SpecialForms._for(Elixir.Core.SpecialForms.list(Elixir.Core.SpecialForms.list(Elixir.Core.Patterns.variable(),'Opera')),function(n) { return n; },function() { return true; - },Elixir.Core.List()) + },Elixir.Core.SpecialForms.list()) """ assert_translation(ex_ast, js_code) @@ -56,13 +56,13 @@ defmodule ElixirScript.Translator.For.Test do end js_code = """ - Elixir.Kernel.SpecialForms._for(Elixir.Core.List( - Elixir.Core.List(Elixir.Core.Patterns.variable(), Elixir.Core.List(1,2)), - Elixir.Core.List(Elixir.Core.Patterns.variable(), Elixir.Core.List(2,3))), function(x,y) { + Elixir.Core.SpecialForms._for(Elixir.Core.SpecialForms.list( + Elixir.Core.SpecialForms.list(Elixir.Core.Patterns.variable(), Elixir.Core.SpecialForms.list(1,2)), + Elixir.Core.SpecialForms.list(Elixir.Core.Patterns.variable(), Elixir.Core.SpecialForms.list(2,3))), function(x,y) { return x * y; },function() { return true; - },Elixir.Core.List()) + },Elixir.Core.SpecialForms.list()) """ assert_translation(ex_ast, js_code) @@ -76,11 +76,11 @@ defmodule ElixirScript.Translator.For.Test do end js_code = """ - let [r] = Elixir.Core.Patterns.match(Elixir.Core.Patterns.variable(),Elixir.Kernel.SpecialForms._for(Elixir.Core.List(Elixir.Core.List(Elixir.Core.Patterns.variable(),Elixir.Core.List(1,2)),Elixir.Core.List(Elixir.Core.Patterns.variable(),Elixir.Core.List(2,3))),function(x,y) { + let [r] = Elixir.Core.Patterns.match(Elixir.Core.Patterns.variable(),Elixir.Core.SpecialForms._for(Elixir.Core.SpecialForms.list(Elixir.Core.SpecialForms.list(Elixir.Core.Patterns.variable(),Elixir.Core.SpecialForms.list(1,2)),Elixir.Core.SpecialForms.list(Elixir.Core.Patterns.variable(),Elixir.Core.SpecialForms.list(2,3))),function(x,y) { return x * y; },function() { return true; - },Elixir.Core.List())); + },Elixir.Core.SpecialForms.list())); """ assert_translation(ex_ast, js_code) @@ -92,11 +92,11 @@ defmodule ElixirScript.Translator.For.Test do end js_code = """ - Elixir.Kernel.SpecialForms._for(Elixir.Core.List(Elixir.Core.List(Elixir.Core.Patterns.variable(),Elixir.Core.List(1,2,3,4,5,6))),function(n) { + Elixir.Core.SpecialForms._for(Elixir.Core.SpecialForms.list(Elixir.Core.SpecialForms.list(Elixir.Core.Patterns.variable(),Elixir.Core.SpecialForms.list(1,2,3,4,5,6))),function(n) { return n; },function(n) { return n % 2 == 0; - },Elixir.Core.List()) + },Elixir.Core.SpecialForms.list()) """ assert_translation(ex_ast, js_code) @@ -110,13 +110,13 @@ defmodule ElixirScript.Translator.For.Test do end js_code = """ - Elixir.Kernel.SpecialForms._for(Elixir.Core.List(Elixir.Core.List(Elixir.Core.Patterns.type(Elixir.Core.Tuple,{ + Elixir.Core.SpecialForms._for(Elixir.Core.SpecialForms.list(Elixir.Core.SpecialForms.list(Elixir.Core.Patterns.type(Elixir.Core.Tuple,{ values: [Symbol.for('user'), Elixir.Core.Patterns.variable()] - }),Elixir.Core.List(Elixir.Core.Functions.new_tuple(Symbol.for('user'),'john'),Elixir.Core.Functions.new_tuple(Symbol.for('admin'),'john'),Elixir.Core.Functions.new_tuple(Symbol.for('user'),'meg')))),function(name) { + }),Elixir.Core.SpecialForms.list(Elixir.Core.SpecialForms.tuple(Symbol.for('user'),'john'),Elixir.Core.SpecialForms.tuple(Symbol.for('admin'),'john'),Elixir.Core.SpecialForms.tuple(Symbol.for('user'),'meg')))),function(name) { return Elixir$ElixirScript$String.upcase(name); },function() { return true; - },Elixir.Core.List()) + },Elixir.Core.SpecialForms.list()) """ assert_translation(ex_ast, js_code) diff --git a/test/translator/function_test.exs b/test/translator/function_test.exs index 8b167ade..70765ca8 100644 --- a/test/translator/function_test.exs +++ b/test/translator/function_test.exs @@ -89,7 +89,7 @@ defmodule ElixirScript.Translator.Function.Test do return Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable()],function(x) { return 2; },function(x) { - return Elixir.Enum.member__qmark__(Elixir.Core.List(false,null), x); + return Elixir.Enum.member__qmark__(Elixir.Core.SpecialForms.list(false,null), x); }),Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.wildcard()],function() { return 1; })).call(this,1 == 1); @@ -117,13 +117,13 @@ defmodule ElixirScript.Translator.Function.Test do return Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable()],function(x) { return 2; },function(x) { - return Elixir.Enum.member__qmark__(Elixir.Core.List(false,null),x); + return Elixir.Enum.member__qmark__(Elixir.Core.SpecialForms.list(false,null),x); }),Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.wildcard()],function() { return Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable()],function(x) { let [a] = Elixir.Core.Patterns.match(Elixir.Core.Patterns.variable(), 1); return a; },function(x) { - return Elixir.Enum.member__qmark__(Elixir.Core.List(false,null),x); + return Elixir.Enum.member__qmark__(Elixir.Core.SpecialForms.list(false,null),x); }),Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.wildcard()],function() { return 4; })).call(this,2 == 2); @@ -143,8 +143,8 @@ defmodule ElixirScript.Translator.Function.Test do const test1 = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable(), Elixir.Core.Patterns.variable()], function(alpha, beta) { let [a, b] = Elixir.Core.Patterns.match(Elixir.Core.Patterns.type(Elixir.Core.Tuple, { values: [Elixir.Core.Patterns.variable(), Elixir.Core.Patterns.variable()] - }), Elixir.Core.Functions.new_tuple(1, 2)); - let _ref = Elixir.Core.Functions.new_tuple(a, b); + }), Elixir.Core.SpecialForms.tuple(1, 2)); + let _ref = Elixir.Core.SpecialForms.tuple(a, b); return _ref; })); """ @@ -404,7 +404,7 @@ defmodule ElixirScript.Translator.Function.Test do const something = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable(), Elixir.Core.Patterns.variable()],function(one,two) { return null; },function(one,two) { - return Elixir.Core.Functions.contains(one,Elixir.Core.List(1,2,3)); + return Elixir.Core.Functions.contains(one,Elixir.Core.SpecialForms.list(1,2,3)); })); """ @@ -425,7 +425,7 @@ defmodule ElixirScript.Translator.Function.Test do const something = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable()],function(one) { return null; },function(one) { - return Elixir.Core.Functions.contains(one,Elixir.Core.List(1,2,3)); + return Elixir.Core.Functions.contains(one,Elixir.Core.SpecialForms.list(1,2,3)); }),Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable()],function(one) { return null; },function(one) { @@ -479,7 +479,7 @@ defmodule ElixirScript.Translator.Function.Test do js_code = """ - const something = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Core.List(Elixir.Core.Patterns.variable(),Elixir.Core.Patterns.variable(),Elixir.Core.Patterns.variable())],function(apple,pear,banana) { + const something = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Core.SpecialForms.list(Elixir.Core.Patterns.variable(),Elixir.Core.Patterns.variable(),Elixir.Core.Patterns.variable())],function(apple,pear,banana) { return null; })); """ @@ -720,8 +720,8 @@ defmodule ElixirScript.Translator.Function.Test do js_code = """ const test1 = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable(), Elixir.Core.Patterns.variable()],function(alpha,beta) { let [a] = Elixir.Core.Patterns.match(Elixir.Core.Patterns.variable(),1); - let [a1,b,c] = Elixir.Core.Patterns.match(Elixir.Core.List(Elixir.Core.Patterns.variable(),Elixir.Core.Patterns.variable(),Elixir.Core.Patterns.variable()),Elixir.Core.List(a,2,3)); - let _ref = Elixir.Core.List(a1,b,c); + let [a1,b,c] = Elixir.Core.Patterns.match(Elixir.Core.SpecialForms.list(Elixir.Core.Patterns.variable(),Elixir.Core.Patterns.variable(),Elixir.Core.Patterns.variable()),Elixir.Core.SpecialForms.list(a,2,3)); + let _ref = Elixir.Core.SpecialForms.list(a1,b,c); return _ref; })); """ diff --git a/test/translator/kernel_test.exs b/test/translator/kernel_test.exs index b647d0d4..ed0c4314 100644 --- a/test/translator/kernel_test.exs +++ b/test/translator/kernel_test.exs @@ -21,7 +21,7 @@ defmodule ElixirScript.Translator.Kernel.Test do end js_code = """ - Elixir$ElixirScript$Kernel.apply(fun, Elixir.Core.List(1,2,3)) + Elixir$ElixirScript$Kernel.apply(fun, Elixir.Core.SpecialForms.list(1,2,3)) """ assert_translation(ex_ast, js_code) @@ -34,7 +34,7 @@ defmodule ElixirScript.Translator.Kernel.Test do end js_code = """ - Elixir$ElixirScript$Kernel.apply(Enum,Symbol.for('reverse'),Elixir.Core.List(1,2,3)) + Elixir$ElixirScript$Kernel.apply(Enum,Symbol.for('reverse'),Elixir.Core.SpecialForms.list(1,2,3)) """ assert_translation(ex_ast, js_code) @@ -47,7 +47,7 @@ defmodule ElixirScript.Translator.Kernel.Test do end js_code = """ - Elixir$ElixirScript$Kernel.hd(Elixir.Core.List(1,2,3)) + Elixir$ElixirScript$Kernel.hd(Elixir.Core.SpecialForms.list(1,2,3)) """ assert_translation(ex_ast, js_code) @@ -60,7 +60,7 @@ defmodule ElixirScript.Translator.Kernel.Test do end js_code = """ - Elixir$ElixirScript$Kernel.tl(Elixir.Core.List(1,2,3)) + Elixir$ElixirScript$Kernel.tl(Elixir.Core.SpecialForms.list(1,2,3)) """ assert_translation(ex_ast, js_code) diff --git a/test/translator/list_test.exs b/test/translator/list_test.exs index 24fc6e85..1fd127ca 100644 --- a/test/translator/list_test.exs +++ b/test/translator/list_test.exs @@ -4,34 +4,34 @@ defmodule ElixirScript.Translator.List.Test do should "translate list" do ex_ast = quote do: [1, 2, 3] - js_code = "Elixir.Core.List(1, 2, 3)" + js_code = "Elixir.Core.SpecialForms.list(1, 2, 3)" assert_translation(ex_ast, js_code) ex_ast = quote do: ["a", "b", "c"] - js_code = "Elixir.Core.List('a', 'b', 'c')" + js_code = "Elixir.Core.SpecialForms.list('a', 'b', 'c')" assert_translation(ex_ast, js_code) ex_ast = quote do: [:a, :b, :c] - js_code = "Elixir.Core.List(Symbol.for('a'), Symbol.for('b'), Symbol.for('c'))" + js_code = "Elixir.Core.SpecialForms.list(Symbol.for('a'), Symbol.for('b'), Symbol.for('c'))" assert_translation(ex_ast, js_code) ex_ast = quote do: [:a, 2, "c"] - js_code = "Elixir.Core.List(Symbol.for('a'), 2, 'c')" + js_code = "Elixir.Core.SpecialForms.list(Symbol.for('a'), 2, 'c')" assert_translation(ex_ast, js_code) end should "concatenate lists" do ex_ast = quote do: [1, 2, 3] ++ [4, 5, 6] - js_code = "Elixir.Core.Functions.concat_lists(Elixir.Core.List(1,2,3),Elixir.Core.List(4,5,6))" + js_code = "Elixir.Core.Functions.concat_lists(Elixir.Core.SpecialForms.list(1,2,3),Elixir.Core.SpecialForms.list(4,5,6))" assert_translation(ex_ast, js_code) ex_ast = quote do: this.list ++ [4, 5, 6] - js_code = "Elixir.Core.Functions.concat_lists(Elixir.Core.Functions.call_property(this,'list'),Elixir.Core.List(4,5,6))" + js_code = "Elixir.Core.Functions.concat_lists(Elixir.Core.Functions.call_property(this,'list'),Elixir.Core.SpecialForms.list(4,5,6))" assert_translation(ex_ast, js_code) end diff --git a/test/translator/map_test.exs b/test/translator/map_test.exs index 04291cf1..8d740b77 100644 --- a/test/translator/map_test.exs +++ b/test/translator/map_test.exs @@ -4,14 +4,14 @@ defmodule ElixirScript.Translator.Map.Test do should "translate empty map" do ex_ast = quote do: %{} - js_code = "Elixir.Kernel.SpecialForms.map({})" + js_code = "Elixir.Core.SpecialForms.map({})" assert_translation(ex_ast, js_code) end should "translate map with elements" do ex_ast = quote do: %{one: "one", two: "two"} - js_code = "Elixir.Kernel.SpecialForms.map({[Symbol.for('one')]: 'one', [Symbol.for('two')]: 'two'})" + js_code = "Elixir.Core.SpecialForms.map({[Symbol.for('one')]: 'one', [Symbol.for('two')]: 'two'})" assert_translation(ex_ast, js_code) end @@ -19,9 +19,9 @@ defmodule ElixirScript.Translator.Map.Test do should "translate map within map" do ex_ast = quote do: %{one: "one", two: %{three: "three"}} js_code = """ - Elixir.Kernel.SpecialForms.map({ + Elixir.Core.SpecialForms.map({ [Symbol.for('one')]: 'one', - [Symbol.for('two')]: Elixir.Kernel.SpecialForms.map({ + [Symbol.for('two')]: Elixir.Core.SpecialForms.map({ [Symbol.for('three')]: 'three' }) }) @@ -33,7 +33,7 @@ defmodule ElixirScript.Translator.Map.Test do should "translate map with string keys" do ex_ast = quote do: %{"one" => "one", "two" => "two"} js_code = """ - Elixir.Kernel.SpecialForms.map({ + Elixir.Core.SpecialForms.map({ one: 'one', two: 'two' }) """ @@ -45,7 +45,7 @@ defmodule ElixirScript.Translator.Map.Test do should "translate map update" do ex_ast = quote do: %{ map | value: 1 } js_code = """ - Elixir.Kernel.SpecialForms.map_update(map,{ + Elixir.Core.SpecialForms.map_update(map,{ [Symbol.for('value')]: 1 }) """ diff --git a/test/translator/protocol_test.exs b/test/translator/protocol_test.exs index 70d51940..45c10b37 100644 --- a/test/translator/protocol_test.exs +++ b/test/translator/protocol_test.exs @@ -32,7 +32,7 @@ defmodule ElixirScript.Translator.Protocol.Test do })) }); Elixir.Core.Functions.defimpl(Elixir$Blank, Array,{ - blank__qmark__: Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Core.List()],function() { + blank__qmark__: Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Core.SpecialForms.list()],function() { return true; }),Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.wildcard()],function() { return false; diff --git a/test/translator/quote_test.exs b/test/translator/quote_test.exs index 4d150a63..5cd43336 100644 --- a/test/translator/quote_test.exs +++ b/test/translator/quote_test.exs @@ -28,7 +28,7 @@ defmodule ElixirScript.Translator.Quote.Test do quote do: {1, 2} end - js_code = "Elixir.Core.Functions.new_tuple(1, 2)" + js_code = "Elixir.Core.SpecialForms.tuple(1, 2)" assert_translation(ex_ast, js_code) end @@ -39,7 +39,7 @@ defmodule ElixirScript.Translator.Quote.Test do quote do: {1, 2, 3} end - js_code = "Elixir.Core.Functions.new_tuple(Symbol.for('{}'), Elixir.Core.List(), Elixir.Core.List(1, 2, 3))" + js_code = "Elixir.Core.SpecialForms.tuple(Symbol.for('{}'), Elixir.Core.SpecialForms.list(), Elixir.Core.SpecialForms.list(1, 2, 3))" assert_translation(ex_ast, js_code) end @@ -50,9 +50,9 @@ defmodule ElixirScript.Translator.Quote.Test do quote do: test(1) end - js_code = "Elixir.Core.Functions.new_tuple(Symbol.for('test'), - Elixir.Core.List(Elixir.Core.Functions.new_tuple(Symbol.for('context'),Symbol.for('Elixir.ElixirScript.Translator.Quote.Test')),Elixir.Core.Functions.new_tuple(Symbol.for('import'),Symbol.for('Elixir.ExUnit.Case'))), - Elixir.Core.List(1))" + js_code = "Elixir.Core.SpecialForms.tuple(Symbol.for('test'), + Elixir.Core.SpecialForms.list(Elixir.Core.SpecialForms.tuple(Symbol.for('context'),Symbol.for('Elixir.ElixirScript.Translator.Quote.Test')),Elixir.Core.SpecialForms.tuple(Symbol.for('import'),Symbol.for('Elixir.ExUnit.Case'))), + Elixir.Core.SpecialForms.list(1))" assert_translation(ex_ast, js_code) end @@ -63,10 +63,10 @@ defmodule ElixirScript.Translator.Quote.Test do quote do: test(x) end - js_code = "Elixir.Core.Functions.new_tuple( + js_code = "Elixir.Core.SpecialForms.tuple( Symbol.for('test'), - Elixir.Core.List(Elixir.Core.Functions.new_tuple(Symbol.for('context'),Symbol.for('Elixir.ElixirScript.Translator.Quote.Test')),Elixir.Core.Functions.new_tuple(Symbol.for('import'),Symbol.for('Elixir.ExUnit.Case'))), - Elixir.Core.List(Elixir.Core.Functions.new_tuple(Symbol.for('x'),Elixir.Core.List(),Symbol.for('Elixir.ElixirScript.Translator.Quote.Test'))) + Elixir.Core.SpecialForms.list(Elixir.Core.SpecialForms.tuple(Symbol.for('context'),Symbol.for('Elixir.ElixirScript.Translator.Quote.Test')),Elixir.Core.SpecialForms.tuple(Symbol.for('import'),Symbol.for('Elixir.ExUnit.Case'))), + Elixir.Core.SpecialForms.list(Elixir.Core.SpecialForms.tuple(Symbol.for('x'),Elixir.Core.SpecialForms.list(),Symbol.for('Elixir.ElixirScript.Translator.Quote.Test'))) )" assert_translation(ex_ast, js_code) @@ -78,10 +78,10 @@ defmodule ElixirScript.Translator.Quote.Test do quote do: test(unquote(x)) end - js_code = "Elixir.Core.Functions.new_tuple( + js_code = "Elixir.Core.SpecialForms.tuple( Symbol.for('test'), - Elixir.Core.List(Elixir.Core.Functions.new_tuple(Symbol.for('context'),Symbol.for('Elixir.ElixirScript.Translator.Quote.Test')),Elixir.Core.Functions.new_tuple(Symbol.for('import'),Symbol.for('Elixir.ExUnit.Case'))), - Elixir.Core.List(x) + Elixir.Core.SpecialForms.list(Elixir.Core.SpecialForms.tuple(Symbol.for('context'),Symbol.for('Elixir.ElixirScript.Translator.Quote.Test')),Elixir.Core.SpecialForms.tuple(Symbol.for('import'),Symbol.for('Elixir.ExUnit.Case'))), + Elixir.Core.SpecialForms.list(x) )" assert_translation(ex_ast, js_code) @@ -93,7 +93,7 @@ defmodule ElixirScript.Translator.Quote.Test do quote do: sum(1, unquote_splicing(values), 5) end - js_code = "Elixir.Core.Functions.new_tuple(Symbol.for('sum'), Elixir.Core.List(), Elixir.Enum.concat(Elixir.Core.List(1), values, Elixir.Core.List(5)))" + js_code = "Elixir.Core.SpecialForms.tuple(Symbol.for('sum'), Elixir.Core.SpecialForms.list(), Elixir.Enum.concat(Elixir.Core.SpecialForms.list(1), values, Elixir.Core.SpecialForms.list(5)))" assert_translation(ex_ast, js_code) end @@ -105,10 +105,10 @@ defmodule ElixirScript.Translator.Quote.Test do end end - js_code = "Elixir.Core.Functions.new_tuple( + js_code = "Elixir.Core.SpecialForms.tuple( Symbol.for('*'), - Elixir.Core.List(Elixir.Core.Functions.new_tuple(Symbol.for('context'),Symbol.for('Elixir.ElixirScript.Translator.Quote.Test')),Elixir.Core.Functions.new_tuple(Symbol.for('import'),Symbol.for('Elixir.ElixirScript.Kernel'))), - Elixir.Core.List(x, x) + Elixir.Core.SpecialForms.list(Elixir.Core.SpecialForms.tuple(Symbol.for('context'),Symbol.for('Elixir.ElixirScript.Translator.Quote.Test')),Elixir.Core.SpecialForms.tuple(Symbol.for('import'),Symbol.for('Elixir.ElixirScript.Kernel'))), + Elixir.Core.SpecialForms.list(x, x) )" assert_translation(ex_ast, js_code) diff --git a/test/translator/string_test.exs b/test/translator/string_test.exs index a8ff8524..1080e38d 100644 --- a/test/translator/string_test.exs +++ b/test/translator/string_test.exs @@ -25,19 +25,19 @@ defmodule ElixirScript.Translator.String.Test do assert_translation(ex_ast, "'Hello ' + 'world'") ex_ast = quote do: "Hello #{length([])}" - assert_translation(ex_ast, "'Hello ' + Elixir$ElixirScript$String$Chars.to_string(Elixir$ElixirScript$Kernel.length(Elixir.Core.List()))") + assert_translation(ex_ast, "'Hello ' + Elixir$ElixirScript$String$Chars.to_string(Elixir$ElixirScript$Kernel.length(Elixir.Core.SpecialForms.list()))") end should "translate multiline string interpolation" do ex_ast = quote do: """ Hello #{length([])} """ - assert_translation(ex_ast, "'Hello ' + (Elixir$ElixirScript$String$Chars.to_string(Elixir$ElixirScript$Kernel.length(Elixir.Core.List())) + '\\n')") + assert_translation(ex_ast, "'Hello ' + (Elixir$ElixirScript$String$Chars.to_string(Elixir$ElixirScript$Kernel.length(Elixir.Core.SpecialForms.list())) + '\\n')") ex_ast = quote do: """ Hello #{length([])} How are you, #{length([])}? """ - assert_translation(ex_ast, "'Hello ' + (Elixir$ElixirScript$String$Chars.to_string(Elixir$ElixirScript$Kernel.length(Elixir.Core.List())) + ('\\nHow are you, ' + (Elixir$ElixirScript$String$Chars.to_string(Elixir$ElixirScript$Kernel.length(Elixir.Core.List())) + '?\\n')))") + assert_translation(ex_ast, "'Hello ' + (Elixir$ElixirScript$String$Chars.to_string(Elixir$ElixirScript$Kernel.length(Elixir.Core.SpecialForms.list())) + ('\\nHow are you, ' + (Elixir$ElixirScript$String$Chars.to_string(Elixir$ElixirScript$Kernel.length(Elixir.Core.SpecialForms.list())) + '?\\n')))") end end diff --git a/test/translator/struct_test.exs b/test/translator/struct_test.exs index c50025b0..94dfbabb 100644 --- a/test/translator/struct_test.exs +++ b/test/translator/struct_test.exs @@ -59,7 +59,7 @@ defmodule ElixirScript.Translator.Struct.Test do end js_code = """ - let [user] = Elixir.Core.Patterns.match(Elixir.Core.Patterns.variable(), Elixir$User.Elixir$User.create(Elixir.Kernel.SpecialForms.map({}))); + let [user] = Elixir.Core.Patterns.match(Elixir.Core.Patterns.variable(), Elixir$User.Elixir$User.create(Elixir.Core.SpecialForms.map({}))); import * as Elixir$ElixirScript$Kernel from './Elixir.ElixirScript.Kernel'; const Elixir$User = Elixir.Core.Functions.defstruct({ @@ -84,7 +84,7 @@ defmodule ElixirScript.Translator.Struct.Test do end js_code = """ - let [user] = Elixir.Core.Patterns.match(Elixir.Core.Patterns.variable(),Elixir$User.Elixir$User.create(Elixir.Kernel.SpecialForms.map({ + let [user] = Elixir.Core.Patterns.match(Elixir.Core.Patterns.variable(),Elixir$User.Elixir$User.create(Elixir.Core.SpecialForms.map({ [Symbol.for('name')]: 'John' }))); @@ -108,7 +108,7 @@ defmodule ElixirScript.Translator.Struct.Test do end js_code = """ - let [user] = Elixir.Core.Patterns.match(Elixir.Core.Patterns.variable(),Elixir.Kernel.SpecialForms.map_update(map,{ + let [user] = Elixir.Core.Patterns.match(Elixir.Core.Patterns.variable(),Elixir.Core.SpecialForms.map_update(map,{ [Symbol.for('key')]: value })); """ @@ -121,7 +121,7 @@ defmodule ElixirScript.Translator.Struct.Test do end js_code = """ - let [user] = Elixir.Core.Patterns.match(Elixir.Core.Patterns.variable(),Elixir.Kernel.SpecialForms.map_update(map,{ + let [user] = Elixir.Core.Patterns.match(Elixir.Core.Patterns.variable(),Elixir.Core.SpecialForms.map_update(map,{ [Symbol.for('key')]: value, [Symbol.for('key1')]: value1 })); """ @@ -183,7 +183,7 @@ defmodule ElixirScript.Translator.Struct.Test do end js_code = """ - throw Elixir$MyAppError.Elixir$MyAppError.create(Elixir.Kernel.SpecialForms.map({ + throw Elixir$MyAppError.Elixir$MyAppError.create(Elixir.Core.SpecialForms.map({ [Symbol.for('message')]: 'did not get what was expected' })); diff --git a/test/translator/try_test.exs b/test/translator/try_test.exs index 75963481..553ec286 100644 --- a/test/translator/try_test.exs +++ b/test/translator/try_test.exs @@ -13,7 +13,7 @@ defmodule ElixirScript.Translator.Try.Test do end js_code = """ - Elixir.Kernel.SpecialForms._try(function() { + Elixir.Core.SpecialForms._try(function() { return do_something_that_may_fail(some_arg); }, Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.type(ArgumentError, {})], function() { return IO.puts('Invalid argument given'); @@ -34,7 +34,7 @@ defmodule ElixirScript.Translator.Try.Test do end js_code = """ - Elixir.Kernel.SpecialForms._try(function() { + Elixir.Core.SpecialForms._try(function() { return do_something_that_may_fail(some_arg); }, Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.type(ArgumentError, {})], function() { return IO.puts('Invalid argument given'); @@ -55,12 +55,12 @@ defmodule ElixirScript.Translator.Try.Test do end js_code = """ - Elixir.Kernel.SpecialForms._try(function() { + Elixir.Core.SpecialForms._try(function() { return do_something_that_may_fail(some_arg); }, Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable()], function(x) { return IO.puts('Invalid argument given'); }, function(x) { - return Elixir.Core.Functions.contains(x,Elixir.Core.List(ArgumentError.create(Elixir.Kernel.SpecialForms.map({})))); + return Elixir.Core.Functions.contains(x,Elixir.Core.SpecialForms.list(ArgumentError.create(Elixir.Core.SpecialForms.map({})))); })), null, null, null) """ @@ -78,7 +78,7 @@ defmodule ElixirScript.Translator.Try.Test do end js_code = """ - Elixir.Kernel.SpecialForms._try(function() { + Elixir.Core.SpecialForms._try(function() { return do_something_that_may_fail(some_arg); },Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable()],function(x) { return IO.puts('Invalid argument given'); @@ -102,7 +102,7 @@ defmodule ElixirScript.Translator.Try.Test do end js_code = """ - Elixir.Kernel.SpecialForms._try(function() { + Elixir.Core.SpecialForms._try(function() { return do_something_that_may_fail(some_arg); }, Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.type(ArgumentError, {})], function() { return IO.puts('ArgumentError'); @@ -127,7 +127,7 @@ defmodule ElixirScript.Translator.Try.Test do end js_code = """ - Elixir.Kernel.SpecialForms._try(function() { + Elixir.Core.SpecialForms._try(function() { return do_something_that_may_fail(some_arg); }, Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.type(ArgumentError, {})], function() { return IO.puts('Invalid argument given'); @@ -149,7 +149,7 @@ defmodule ElixirScript.Translator.Try.Test do end js_code = """ - Elixir.Kernel.SpecialForms._try(function() { + Elixir.Core.SpecialForms._try(function() { return do_something_that_may_fail(some_arg); },null,null,null,function() { return IO.puts('This is printed regardless if it failed or succeed'); @@ -172,7 +172,7 @@ defmodule ElixirScript.Translator.Try.Test do end js_code = """ - Elixir.Kernel.SpecialForms._try(function() { + Elixir.Core.SpecialForms._try(function() { return 1 / x; },null,null,Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable()],function(y) { return Symbol.for('small'); @@ -200,7 +200,7 @@ defmodule ElixirScript.Translator.Try.Test do end js_code = """ - Elixir.Kernel.SpecialForms._try(function() { + Elixir.Core.SpecialForms._try(function() { return do_something_that_may_fail(some_arg); }, Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.type(ArgumentError, {})], function() { return IO.puts('Invalid argument given'); diff --git a/test/translator/tuple_test.exs b/test/translator/tuple_test.exs index 3738a81e..33c3abd2 100644 --- a/test/translator/tuple_test.exs +++ b/test/translator/tuple_test.exs @@ -4,31 +4,31 @@ defmodule ElixirScript.Translator.Tuple.Test do should "translate 2 item tuple" do ex_ast = quote do: {1, 2} - js_code = "Elixir.Core.Functions.new_tuple(1, 2)" + js_code = "Elixir.Core.SpecialForms.tuple(1, 2)" assert_translation(ex_ast, js_code) end should "translate multiple item tuple" do ex_ast = quote do: {1, 2, 3, 4, 5} - js_code = "Elixir.Core.Functions.new_tuple(1, 2, 3, 4, 5)" + js_code = "Elixir.Core.SpecialForms.tuple(1, 2, 3, 4, 5)" assert_translation(ex_ast, js_code) end should "translate tuples of different typed items" do ex_ast = quote do: {"a", "b", "c"} - js_code = "Elixir.Core.Functions.new_tuple('a', 'b', 'c')" + js_code = "Elixir.Core.SpecialForms.tuple('a', 'b', 'c')" assert_translation(ex_ast, js_code) ex_ast = quote do: {:a, :b, :c} - js_code = "Elixir.Core.Functions.new_tuple(Symbol.for('a'), Symbol.for('b'), Symbol.for('c'))" + js_code = "Elixir.Core.SpecialForms.tuple(Symbol.for('a'), Symbol.for('b'), Symbol.for('c'))" assert_translation(ex_ast, js_code) ex_ast = quote do: {:a, 2, "c"} - js_code = "Elixir.Core.Functions.new_tuple(Symbol.for('a'), 2, 'c')" + js_code = "Elixir.Core.SpecialForms.tuple(Symbol.for('a'), 2, 'c')" assert_translation(ex_ast, js_code) end From 2502ce21caae62946aed7d97507be93fda8685d4 Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Wed, 30 Dec 2015 19:40:22 -0600 Subject: [PATCH 098/860] Added Map module. Updated tuple translation --- lib/elixir_script/prelude/map.ex | 202 ++++++++++++++++ lib/elixir_script/translator.ex | 20 +- lib/elixir_script/translator/assignment.ex | 57 ++++- lib/elixir_script/translator/state.ex | 1 + src/javascript/lib/core/functions.js | 23 +- src/javascript/lib/map.js | 264 --------------------- 6 files changed, 286 insertions(+), 281 deletions(-) create mode 100644 lib/elixir_script/prelude/map.ex delete mode 100644 src/javascript/lib/map.js diff --git a/lib/elixir_script/prelude/map.ex b/lib/elixir_script/prelude/map.ex new file mode 100644 index 00000000..6aeb6f16 --- /dev/null +++ b/lib/elixir_script/prelude/map.ex @@ -0,0 +1,202 @@ +defmodule ElixirScript.Map do + + def new() do + %{} + end + + def keys(map) do + Elixir.Core.Functions.get_object_keys(map) + end + + def size(map) do + keys(map).length + end + + def to_list(map) do + do_to_list(map, []) + end + + def do_to_list(map, list) do + case size(map) do + 0 -> + list + _ -> + key = hd(keys(map)) + value = map[key] + do_to_list(Map.delete(map, key), list ++ [{key, value}]) + end + end + + def values(map) do + Object.values(map) + end + + def from_struct(struct) do + struct + |> Elixir.Core.Functions.class_to_obj + |> delete(:__struct__) + end + + def delete(map, key) do + map + |> Elixir.Core.Functions.delete_property_from_map(key) + end + + def equal?(map1, map2) do + map1 === map2 + end + + def fetch!(map, key) do + case key in keys(map) do + true -> + map[key] + false -> + raise "#{key} not found in map" + end + end + + def fetch(map, key) do + case key in keys(map) do + true -> + { :ok, map[key] } + false -> + :error + end + end + + def has_key?(map, key) do + key in keys(map) + end + + def merge(map1, map2) do + Elixir.Core.SpecialForms.map_update(map1, map2) + end + + def split(map, keys) do + do_split(map, keys, { %{}, %{} }) + end + + defp do_split(_, [], split_tuple) do + split_tuple + end + + defp do_split(map, keys, { key_map, non_key_map }) do + key = hd(keys) + + new_split_tuple = case key in keys(map) do + true -> + { Map.put(key_map, key, map[key]), non_key_map } + false -> + { key_map, Map.put(non_key_map, key, map[key]) } + end + + do_split(map, tl(keys), new_split_tuple) + end + + def take(map, keys) do + {key_map, _} = split(map, keys) + key_map + end + + def drop(map, keys) do + {_, non_key_map} = split(map, keys) + non_key_map + end + + def put_new(map, key, value) do + case key in keys(map) do + true -> + map + false -> + Map.put(map, key, value) + end + end + + def put_new_lazy(map, key, func) do + case key in keys(map) do + true -> + map + false -> + Map.put(map, key, func.()) + end + end + + def put(map, key, value) do + Elixir.Core.Functions.add_property_to_map(map, key, value) + end + + def get(map, key) do + get(map, key, nil) + end + + def get(map, key, default) do + case key in keys(map) do + true -> + map[key] + false -> + default + end + end + + def get_lazy(map, key, func) do + case key in keys(map) do + true -> + func.(map[key]) + false -> + func.() + end + end + + def get_and_update(map, key, func) do + case key in keys(map) do + true -> + { nil, map } + false -> + new_value = func.(map[key]) + { new_value, Map.put(map, key, new_value) } + end + end + + def pop(map, key) do + pop(map, key, nil) + end + + def pop(map, key, default) do + case key in keys(map) do + true -> + { map[key], Map.delete(map, key) } + false -> + { default, map } + end + end + + def pop_lazy(map, key, func) do + case key in keys(map) do + true -> + { func.(map[key]), Map.delete(map, key) } + false -> + { func.(), map } + end + end + + + def update!(map, key, func) do + case key in keys(map) do + true -> + Map.put(map, key, func.(map[key])) + false -> + raise "#{key} not found in map" + end + end + + + def update(map, key, initial, func) do + case key in keys(map) do + true -> + Map.put(map, key, func.(map[key])) + false -> + Map.put(map, key, initial) + end + end + +end diff --git a/lib/elixir_script/translator.ex b/lib/elixir_script/translator.ex index e17dd659..fc521fa0 100644 --- a/lib/elixir_script/translator.ex +++ b/lib/elixir_script/translator.ex @@ -41,7 +41,13 @@ defmodule ElixirScript.Translator do end defp do_translate(ast, env) when is_atom(ast) do - { Primitive.make_atom(ast), env } + str = Atom.to_string(ast) + + quoted = quote do + Symbol.for(unquote(str)) + end + + translate(quoted, env) end defp do_translate(ast, env) when is_list(ast) do @@ -49,7 +55,11 @@ defmodule ElixirScript.Translator do end defp do_translate({ one, two }, env) do - Primitive.make_tuple({one, two}, env) + quoted = quote do + JS.new(Elixir.Core.Tuple, [unquote(one), unquote(two)]) + end + + translate(quoted, env) end defp do_translate({operator, _, [value]}, env) when operator in [:-, :!, :+] do @@ -343,7 +353,11 @@ defmodule ElixirScript.Translator do end defp do_translate({:{}, _, elements}, env) do - Primitive.make_tuple(elements, env) + quoted = quote do + JS.new(Elixir.Core.Tuple, unquote(elements)) + end + + translate(quoted, env) end defp do_translate({:=, _, [left, right]}, env) do diff --git a/lib/elixir_script/translator/assignment.ex b/lib/elixir_script/translator/assignment.ex index 12299176..7d9f2ed8 100644 --- a/lib/elixir_script/translator/assignment.ex +++ b/lib/elixir_script/translator/assignment.ex @@ -31,11 +31,11 @@ defmodule ElixirScript.Translator.Assignment do js_ast = case left do list when is_list(list) -> - make_ref(array_pattern, params, Primitive.list_ast()) - {_left1, _left2} -> - make_ref(array_pattern, params, Primitive.new_tuple_function()) - {:{}, _, _} -> - make_ref(array_pattern, params, Primitive.new_tuple_function()) + make_list_ref(array_pattern, params) + { _, _ } -> + make_tuple_ref(array_pattern, params) + {:{}, _, _ } -> + make_tuple_ref(array_pattern, params) _ -> array_pattern end @@ -43,22 +43,53 @@ defmodule ElixirScript.Translator.Assignment do { js_ast, env } end - defp make_ref(array_pattern, params, ast) do - ref = JS.identifier("_ref") - - params = Enum.map(params, fn - (nil) -> JS.identifier(:undefined) - (x) -> x - end) + defp make_list_ref(array_pattern, params) do + {ref, params} = make_params(params) ref_declarator = JS.variable_declarator( ref, JS.call_expression( - ast, + Primitive.list_ast(), + params + ) + ) + + make_variable_declaration_and_group(ref_declarator, array_pattern) + end + + defp make_tuple_ref(array_pattern, params) do + {ref, params} = make_params(params) + + ref_declarator = JS.variable_declarator( + ref, + JS.new_expression( + JS.member_expression( + JS.identifier("Elixir"), + JS.member_expression( + JS.identifier("Core"), + JS.identifier("Tuple") + ) + ), params ) ) + make_variable_declaration_and_group(ref_declarator, array_pattern) + end + + + defp make_params(params) do + ref = JS.identifier("_ref") + + params = Enum.map(params, fn + (nil) -> JS.identifier(:undefined) + (x) -> x + end) + + { ref, params } + end + + defp make_variable_declaration_and_group(ref_declarator, array_pattern) do ref_declaration = JS.variable_declaration([ref_declarator], :let) %ElixirScript.Translator.Group{ body: [array_pattern, ref_declaration] } end diff --git a/lib/elixir_script/translator/state.ex b/lib/elixir_script/translator/state.ex index 88ebebe4..9f8ef234 100644 --- a/lib/elixir_script/translator/state.ex +++ b/lib/elixir_script/translator/state.ex @@ -24,6 +24,7 @@ defmodule ElixirScript.Translator.State do |> Map.put(String, ElixirScript.String) |> Map.put(Base, ElixirScript.Base) |> Map.put(Module, ElixirScript.Module) + |> Map.put(Map, ElixirScript.Map) end def add_module(module) do diff --git a/src/javascript/lib/core/functions.js b/src/javascript/lib/core/functions.js index 0ba2725d..562ea411 100644 --- a/src/javascript/lib/core/functions.js +++ b/src/javascript/lib/core/functions.js @@ -278,6 +278,24 @@ function can_decode64(data) { } } +function delete_property_from_map(map, property){ + let new_map = Object.assign(Object.create(map.constructor.prototype), map) + delete new_map[property] + + return Object.freeze(new_map); +} + +function class_to_obj(map){ + let new_map = Object.assign({}, map) + return Object.freeze(new_map); +} + +function add_property_to_map(map, property, value){ + let new_map = Object.assign({}, map); + new_map[property] = value; + return Object.freeze(new_map); +} + export default { call_property, is_instance_of, @@ -316,5 +334,8 @@ export default { defimpl, get_object_keys, is_valid_character, - b64EncodeUnicode + b64EncodeUnicode, + delete_property_from_map, + add_property_to_map, + class_to_obj }; diff --git a/src/javascript/lib/map.js b/src/javascript/lib/map.js deleted file mode 100644 index f2743434..00000000 --- a/src/javascript/lib/map.js +++ /dev/null @@ -1,264 +0,0 @@ -import * as Core from './core'; - -function __new__(){ - return Core.SpecialForms.map({}); -} - -function keys(map){ - return Core.Functions.get_object_keys(map); -} - -function size(map){ - return keys(map).length; -} - -function to_list(map){ - let map_keys = keys(map); - let list = []; - - for(let key of map_keys){ - list.push(Core.SpecialForms.tuple(key, map[key])); - } - - return Core.SpecialForms.list(...list); -} - -function values(map){ - let map_keys = keys(map); - let list = []; - - for(let key of map_keys){ - list.push(map[key]); - } - - return Core.SpecialForms.list(...list); -} - -function from_struct(struct){ - let map = Object.assign({}, struct); - delete map[Symbol.for("__struct__")]; - - return Core.SpecialForms.map(map); -} - -function __delete__(map, key){ - let new_map = Object.assign({}, map); - - delete new_map[key]; - - return Core.SpecialForms.map(new_map); -} - -function drop(map, keys){ - let new_map = Object.assign({}, map); - - for(let key of keys){ - delete new_map[key]; - } - - return Core.SpecialForms.map(new_map); -} - - -function equal__qmark__(map1, map2){ - return map1 === map2; -} - -function fetch__emark__(map, key){ - if(key in map){ - return map[key] - } - - throw new Error("Key not found."); -} - -function fetch(map, key){ - if(key in map){ - return Core.SpecialForms.tuple(Symbol.for("ok"), map[key]); - } - - return Symbol.for("error"); -} - -function has_key__qmark__(map, key){ - return key in map; -} - -function merge(map1, map2){ - return Core.SpecialForms.map_update(map1, map2); -} - -function split(map, keys){ - let split1 = {}; - let split2 = {}; - - for(let key of Core.Functions.get_object_keys(map) ){ - if(keys.indexOf(key) > -1){ - split1[key] = map[key]; - }else{ - split2[key] = map[key]; - } - } - - return Core.SpecialForms.tuple( - Core.SpecialForms.map(split1), - Core.SpecialForms.map(split2) - ); -} - -function take(map, keys){ - let split1 = {}; - - for(let key of Core.Functions.get_object_keys(map) ){ - if(keys.indexOf(key) > -1){ - split1[key] = map[key]; - } - } - - return Core.SpecialForms.map(split1); -} - -function drop(map, keys){ - let split1 = {}; - - for(let key of Core.Functions.get_object_keys(map) ){ - if(keys.indexOf(key) === -1){ - split1[key] = map[key]; - } - } - - return Core.SpecialForms.map(split1); -} - -function put_new(map, key, value){ - if(key in map){ - return map; - } - - let new_map = Object.assign({}, map); - new_map[key] = value; - - return Core.SpecialForms.map(new_map); -} - -function put_new_lazy(map, key, fun){ - if(key in map){ - return map; - } - - let new_map = Object.assign({}, map); - new_map[key] = fun(); - - return Core.SpecialForms.map(new_map); -} - -function get_and_update(map, key, fun){ - if(key in map){ - return map; - } - - let new_map = Object.assign({}, map); - new_map[key] = fun(map[key]); - - return Core.SpecialForms.map(new_map); -} - -function pop_lazy(map, key, fun){ - if(!key in map){ - return Core.SpecialForms.tuple(fun(), map); - } - - let new_map = Object.assign({}, map); - let value = fun(new_map[key]); - delete new_map[key]; - - return Core.SpecialForms.tuple(value, new_map); -} - - -function pop(map, key, _default = null){ - if(!key in map){ - return Core.SpecialForms.tuple(_default, map); - } - - let new_map = Object.assign({}, map); - let value = new_map[key]; - delete new_map[key]; - - return Core.SpecialForms.tuple(value, new_map); -} - -function get_lazy(map, key, fun){ - if(!key in map){ - return fun(); - } - - return fun(map[key]); -} - - -function get(map, key, _default = null){ - if(!key in map){ - return _default; - } - - return map[key]; -} - -function put(map, key, val){ - let new_map = Object({}, map); - new_map[key] = val; - - return Core.SpecialForms.map(new_map); -} - -function update__emark__(map, key, fun){ - if(!key in map){ - throw new Error("Key not found"); - } - - let new_map = Object({}, map); - new_map[key] = fun(map[key]); - - return Core.SpecialForms.map(new_map); -} - -function update(map, key, initial, fun){ - let new_map = Object({}, map); - - if(!key in map){ - new_map[key] = initial; - }else{ - new_map[key] = fun(map[key]); - } - - return Core.SpecialForms.map(new_map); -} - - -export default { - new: __new__, - keys, - size, - to_list, - values, - from_struct, - delete: __delete__, - drop, - equal__qmark__, - fetch__emark__, - fetch, - has_key__qmark__, - split, - take, - put_new, - put_new_lazy, - get_and_update, - pop_lazy, - pop, - get_lazy, - get, - put, - update__emark__, - update -} From 1fe2833d6ba5e39f4b14714cee1ab29d24e915e7 Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Wed, 30 Dec 2015 20:01:55 -0600 Subject: [PATCH 099/860] Added Keyword module functions that were implemented in JavaScript --- lib/elixir_script/prelude/keyword.ex | 41 +++++++++++++++++++++++++++ lib/elixir_script/translator/state.ex | 1 + src/javascript/lib/keyword.js | 25 ---------------- src/javascript/tests/map.spec.js | 39 ------------------------- 4 files changed, 42 insertions(+), 64 deletions(-) create mode 100644 lib/elixir_script/prelude/keyword.ex delete mode 100644 src/javascript/lib/keyword.js delete mode 100644 src/javascript/tests/map.spec.js diff --git a/lib/elixir_script/prelude/keyword.ex b/lib/elixir_script/prelude/keyword.ex new file mode 100644 index 00000000..13751db1 --- /dev/null +++ b/lib/elixir_script/prelude/keyword.ex @@ -0,0 +1,41 @@ +defmodule ElixirScript.Keyword do + + def has_key?(kw, key) do + do_has_key?(kw, key) + end + + defp do_has_key?([], _) do + false + end + + defp do_has_key?(kw, key) do + case hd(kw) do + {the_key, _} when the_key == key -> + true + _ -> + do_has_key?(tl(kw), key) + end + end + + def get(kw, key) do + get(kw, key, nil) + end + + def get(kw, key, default) do + case has_key?(kw, key) do + true -> + do_get(kw, key) + false -> + default + end + end + + defp do_get(kw, key) do + case hd(kw) do + { kw_key, value } when kw_key == key -> + value + _ -> + do_get(tl(kw), key) + end + end +end diff --git a/lib/elixir_script/translator/state.ex b/lib/elixir_script/translator/state.ex index 9f8ef234..992391e5 100644 --- a/lib/elixir_script/translator/state.ex +++ b/lib/elixir_script/translator/state.ex @@ -25,6 +25,7 @@ defmodule ElixirScript.Translator.State do |> Map.put(Base, ElixirScript.Base) |> Map.put(Module, ElixirScript.Module) |> Map.put(Map, ElixirScript.Map) + |> Map.put(Keyword, ElixirScript.Keyword) end def add_module(module) do diff --git a/src/javascript/lib/keyword.js b/src/javascript/lib/keyword.js deleted file mode 100644 index 2fc61b78..00000000 --- a/src/javascript/lib/keyword.js +++ /dev/null @@ -1,25 +0,0 @@ -import Kernel from './kernel'; - -let Keyword = {}; - -Keyword.has_key__qmark__ = function(keywords, key){ - for(let keyword of keywords){ - if(Kernel.elem(keyword, 0) == key){ - return true; - } - } - - return false; -} - -Keyword.get = function(keywords, key, the_default = null){ - for(let keyword of keywords){ - if(Kernel.elem(keyword, 0) == key){ - return Kernel.elem(keyword, 1); - } - } - - return the_default; -} - -export default Keyword; diff --git a/src/javascript/tests/map.spec.js b/src/javascript/tests/map.spec.js deleted file mode 100644 index 6f8e4539..00000000 --- a/src/javascript/tests/map.spec.js +++ /dev/null @@ -1,39 +0,0 @@ -var Map = require('../lib/map'); -var Kernel = require('../lib/kernel'); -var SpecialForms = require('../lib/core').SpecialForms; -var expect = require('chai').expect; - -describe('Map', function(){ - - it('new', function(){ - let map = Map.new(); - - expect(Object.keys(map).length).to.equal(0); - }); - - it('keys', function(){ - let map = Map.new(); - expect(Map.keys(map)).to.deep.equal([]); - - map = Map.put(map, "hello", "world"); - expect(Map.keys(map)).to.deep.equal(["hello"]); - }); - - it('to_list', function(){ - let map = Map.new(); - - map = Map.put(map, "hello", "world"); - expect(Map.to_list(map)).to.deep.equal([SpecialForms.tuple("hello", "world")]); - }); - - it('delete', function(){ - let map = Map.new(); - - map = Map.put(map, "hello", "world"); - expect(Map.keys(map).length).to.equal(1); - - map = Map.delete(map, "hello") - expect(Map.keys(map).length).to.equal(0); - }); - -}) From dc5034102055f2292d378e6632b07a9218fd5a1e Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Wed, 30 Dec 2015 20:34:34 -0600 Subject: [PATCH 100/860] Added Bitwise module --- lib/elixir_script/prelude/bitwise.ex | 74 +++++++++++++++++++++++++++ lib/elixir_script/translator/state.ex | 1 + src/javascript/lib/bitwise.js | 32 ------------ src/javascript/lib/core/functions.js | 32 +++++++++++- src/javascript/lib/enum.js | 5 +- src/javascript/lib/list.js | 4 +- 6 files changed, 110 insertions(+), 38 deletions(-) create mode 100644 lib/elixir_script/prelude/bitwise.ex delete mode 100644 src/javascript/lib/bitwise.js diff --git a/lib/elixir_script/prelude/bitwise.ex b/lib/elixir_script/prelude/bitwise.ex new file mode 100644 index 00000000..06fa0064 --- /dev/null +++ b/lib/elixir_script/prelude/bitwise.ex @@ -0,0 +1,74 @@ +defmodule ElixirScript.Bitwise do + + defmacro bnot(expr) do + quote do + Elixir.Core.bnot(unquote(expr)) + end + end + + defmacro ~~~(expr) do + quote do + Elixir.Core.bnot(unquote(expr)) + end + end + + defmacro band(left, right) do + quote do + Elixir.Core.band(unquote(left), unquote(right)) + end + end + + defmacro left &&& right do + quote do + Elixir.Core.band(unquote(left), unquote(right)) + end + end + + defmacro bor(left, right) do + quote do + Elixir.Core.bor(unquote(left), unquote(right)) + end + end + + defmacro left ||| right do + quote do + Elixir.Core.bor(unquote(left), unquote(right)) + end + end + + defmacro bxor(left, right) do + quote do + Elixir.Core.bxor(unquote(left), unquote(right)) + end + end + + defmacro left ^^^ right do + quote do + Elixir.Core.bxor(unquote(left), unquote(right)) + end + end + + defmacro bsl(left, right) do + quote do + Elixir.Core.bsl(unquote(left), unquote(right)) + end + end + + defmacro left <<< right do + quote do + Elixir.Core.bsl(unquote(left), unquote(right)) + end + end + + defmacro bsr(left, right) do + quote do + Elixir.Core.bsr(unquote(left), unquote(right)) + end + end + + defmacro left >>> right do + quote do + Elixir.Core.bsr(unquote(left), unquote(right)) + end + end +end diff --git a/lib/elixir_script/translator/state.ex b/lib/elixir_script/translator/state.ex index 992391e5..12e428ff 100644 --- a/lib/elixir_script/translator/state.ex +++ b/lib/elixir_script/translator/state.ex @@ -26,6 +26,7 @@ defmodule ElixirScript.Translator.State do |> Map.put(Module, ElixirScript.Module) |> Map.put(Map, ElixirScript.Map) |> Map.put(Keyword, ElixirScript.Keyword) + |> Map.put(Bitwise, ElixirScript.Bitwise) end def add_module(module) do diff --git a/src/javascript/lib/bitwise.js b/src/javascript/lib/bitwise.js deleted file mode 100644 index b42ec1e6..00000000 --- a/src/javascript/lib/bitwise.js +++ /dev/null @@ -1,32 +0,0 @@ -function bnot(expr){ - return ~expr; -} - -function band(left, right){ - return left & right; -} - -function bor(left, right){ - return left | right; -} - -function bsl(left, right){ - return left << right; -} - -function bsr(left, right){ - return left >> right; -} - -function bxor(left, right){ - return left ^ right; -} - -export default { - bnot, - band, - bor, - bsl, - bsr, - bxor -} \ No newline at end of file diff --git a/src/javascript/lib/core/functions.js b/src/javascript/lib/core/functions.js index 562ea411..291da362 100644 --- a/src/javascript/lib/core/functions.js +++ b/src/javascript/lib/core/functions.js @@ -296,6 +296,30 @@ function add_property_to_map(map, property, value){ return Object.freeze(new_map); } +function bnot(expr){ + return ~expr; +} + +function band(left, right){ + return left & right; +} + +function bor(left, right){ + return left | right; +} + +function bsl(left, right){ + return left << right; +} + +function bsr(left, right){ + return left >> right; +} + +function bxor(left, right){ + return left ^ right; +} + export default { call_property, is_instance_of, @@ -337,5 +361,11 @@ export default { b64EncodeUnicode, delete_property_from_map, add_property_to_map, - class_to_obj + class_to_obj, + bnot, + band, + bor, + bsl, + bsr, + bxor }; diff --git a/src/javascript/lib/enum.js b/src/javascript/lib/enum.js index bb8f10d5..5806efeb 100644 --- a/src/javascript/lib/enum.js +++ b/src/javascript/lib/enum.js @@ -1,4 +1,3 @@ -import Kernel from './kernel'; import * as Core from './core'; let Enum = { @@ -72,7 +71,7 @@ let Enum = { }, fetch: function(collection, n){ - if(Kernel.is_list(collection)){ + if(Array.isArray(collection)){ if(n < this.count(collection) && n >= 0){ return new Core.Tuple(Symbol.for("ok"), collection[n]); }else{ @@ -84,7 +83,7 @@ let Enum = { }, fetch__emark__: function(collection, n){ - if(Kernel.is_list(collection)){ + if(Array.isArray(collection)){ if(n < this.count(collection) && n >= 0){ return collection[n]; }else{ diff --git a/src/javascript/lib/list.js b/src/javascript/lib/list.js index f8b9a3e4..aa4adcff 100644 --- a/src/javascript/lib/list.js +++ b/src/javascript/lib/list.js @@ -49,7 +49,7 @@ List.flatten = function(list, tail = Core.SpecialForms.list()){ let new_value = []; for(let x of list){ - if(Kernel.is_list(x)){ + if(Array.isArray(x)){ new_value = new_value.concat(List.flatten(x)); }else{ new_value.push(x); @@ -223,7 +223,7 @@ List.update_at = function(list, index, fun){ }; List.wrap = function(list){ - if(Kernel.is_list(list)){ + if(Array.isArray(list)){ return list; }else if(list == null){ return Core.SpecialForms.list(); From 21ce49e9ce8b330fee6f9f0dc867513a1fe9a241 Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Wed, 30 Dec 2015 21:01:06 -0600 Subject: [PATCH 101/860] Added MapSet module --- lib/elixir_script/prelude/map_set.ex | 100 ++++++++++++++++++++++ lib/elixir_script/translator/state.ex | 1 + src/javascript/lib/map_set.js | 115 -------------------------- 3 files changed, 101 insertions(+), 115 deletions(-) create mode 100644 lib/elixir_script/prelude/map_set.ex delete mode 100644 src/javascript/lib/map_set.js diff --git a/lib/elixir_script/prelude/map_set.ex b/lib/elixir_script/prelude/map_set.ex new file mode 100644 index 00000000..52e5e35b --- /dev/null +++ b/lib/elixir_script/prelude/map_set.ex @@ -0,0 +1,100 @@ +defmodule ElixirScript.MapSet do + + defstruct set: [] + + def new() do + %MapSet{} + end + + def size(set) do + length(set.set) + end + + def to_list(set) do + set.set + end + + def delete(set, term) do + %{ set | set: Elixir.List.remove(set.set, term) } + end + + def put(set, term) do + case member?(set, term) do + false -> + %{ set | set: set.set ++ term } + true -> + set + end + end + + def member?(set, term) do + set.set.indexOf(term) >= 0 + end + + def equal?(set1, set2) do + set1 === set2 + end + + def difference(set1, set2) do + do_difference(to_list(set1), set2, new()) + end + + def do_difference([], _, difference_set) do + difference_set + end + + def do_difference(set1_list, set2, difference_set) do + term = hd(set1_list) + case member?(set2, term) do + true -> + do_difference(tl(set1_list), set2, difference_set) + false -> + do_difference(tl(set1_list), set2, %{ difference_set | set: difference_set.set ++ [term]}) + end + end + + def intersection(set1, set2) do + do_intersection(to_list(set1), set2, new()) + end + + def do_intersection([], _, intersection_set) do + intersection_set + end + + def do_intersection(set1_list, set2, intersection_set) do + term = hd(set1_list) + case member?(set2, term) do + false -> + do_intersection(tl(set1_list), set2, intersection_set) + true -> + do_intersection(tl(set1_list), set2, %{ intersection_set | set: intersection_set.set ++ [term]}) + end + end + + def union(set1, set2) do + %{ set1 | set: set1.set ++ set2.set} + end + + def disjoint?(set1, set2) do + size(intersection(set1, set2)) == 0 + end + + def subset?(set1, set2) do + do_subset?(to_list(set1), set2) + end + + def do_subset?([], _) do + true + end + + def do_subset?(set1_list, set2) do + term = hd(set1_list) + case member?(set2, term) do + false -> + false + true -> + do_subset?(tl(set1_list), set2) + end + end + +end diff --git a/lib/elixir_script/translator/state.ex b/lib/elixir_script/translator/state.ex index 12e428ff..6b5f1673 100644 --- a/lib/elixir_script/translator/state.ex +++ b/lib/elixir_script/translator/state.ex @@ -27,6 +27,7 @@ defmodule ElixirScript.Translator.State do |> Map.put(Map, ElixirScript.Map) |> Map.put(Keyword, ElixirScript.Keyword) |> Map.put(Bitwise, ElixirScript.Bitwise) + |> Map.put(MapSet, ElixirScript.MapSet) end def add_module(module) do diff --git a/src/javascript/lib/map_set.js b/src/javascript/lib/map_set.js deleted file mode 100644 index 37d8bd17..00000000 --- a/src/javascript/lib/map_set.js +++ /dev/null @@ -1,115 +0,0 @@ -import List from './list'; -import * as Core from './core'; - -function __new__(){ - return Core.SpecialForms.map({ [Symbol.for("__struct__")]: Symbol.for("MapSet"), set: Core.List() }); -} - -function size(map){ - return map.set.length; -} - -function to_list(map){ - return map.set; -} - -function __delete__(set, term){ - let new_list = List.delete(set.set, term); - - let new_map = Object.assign({}, set); - new_map.set = new_list; - return Core.SpecialForms.map(new_map); -} - -function put(set, term){ - if(set.set.indexOf(term) === -1){ - let new_list = List.append(set.set, term); - - let new_map = Object.assign({}, set); - new_map.set = new_list; - return Core.SpecialForms.map(new_map); - } - - return set; -} - -function difference(set1, set2){ - let new_map = Object.assign({}, set1); - - for(let val of set1.set){ - if(member__qmark__(set2, val)){ - new_map.set = List.delete(new_map.set, val); - } - } - - return Core.SpecialForms.map(new_map); -} - - -function intersection(set1, set2){ - let new_map = Object.assign({}, set1); - - for(let val of set1.set){ - if(!member__qmark__(set2, val)){ - new_map.set = List.delete(new_map.set, val); - } - } - - return Core.SpecialForms.map(new_map); -} - - -function union(set1, set2){ - let new_map = set1; - - for(let val of set2.set){ - new_map = put(new_map, val); - } - - return Core.SpecialForms.map(new_map); -} - - -function disjoin__qmark__(set1, set2){ - for(let val of set1.set){ - if(member__qmark__(set2, val)){ - return false; - } - } - - return true; -} - -function member__qmark__(set, value){ - return set.set.indexOf(value) >= 0; -} - -function equal__qmark__(set1, set2){ - return set1.set === set2.set; -} - -function subset__qmark__(set1, set2){ - for(let val of set1.set){ - if(!member__qmark__(set2, val)){ - return false; - } - } - - return true; -} - - -export default { - new: __new__, - size, - to_list, - disjoin__qmark__, - delete: __delete__, - subset__qmark__, - equal__qmark__, - member__qmark__, - put, - union, - intersection, - difference -} From 75f5512ee3a3101dff5fd9e79689c079a3eddadf Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Fri, 1 Jan 2016 15:48:10 -0600 Subject: [PATCH 102/860] Added List module. switched tests to ExUnit --- .travis.yml | 2 +- bench/elixir_script_bench.exs | 34 - lib/elixir_script/prelude/list.ex | 250 +++++++ lib/elixir_script/prelude/map.ex | 4 +- lib/elixir_script/prelude/tuple.ex | 46 +- lib/elixir_script/translator/js.ex | 8 +- lib/elixir_script/translator/module.ex | 4 + lib/elixir_script/translator/primitive.ex | 6 +- lib/elixir_script/translator/state.ex | 1 + mix.exs | 2 - mix.lock | 12 +- priv/Elixir.js | 815 +++------------------- src/javascript/elixir.js | 5 - src/javascript/lib/core/functions.js | 29 +- src/javascript/lib/list.js | 277 -------- src/javascript/tests/list.spec.js | 77 -- test/elixir_script_test.exs | 16 +- test/lib/js_test.exs | 8 +- test/lib/kernel_test.exs | 4 +- test/pattern_matching/match_test.exs | 34 +- test/test_helper.exs | 4 +- test/translator/access_test.exs | 6 +- test/translator/assignment_test.exs | 24 +- test/translator/atom_test.exs | 6 +- test/translator/bitstring_test.exs | 4 +- test/translator/bug_test.exs | 16 +- test/translator/capture_test.exs | 18 +- test/translator/case_test.exs | 12 +- test/translator/cond_test.exs | 6 +- test/translator/defmodule_test.exs | 18 +- test/translator/for_test.exs | 18 +- test/translator/function_test.exs | 50 +- test/translator/kernel_test.exs | 12 +- test/translator/list_test.exs | 10 +- test/translator/map_test.exs | 12 +- test/translator/nil_test.exs | 6 +- test/translator/number_test.exs | 6 +- test/translator/protocol_test.exs | 2 +- test/translator/quote_test.exs | 26 +- test/translator/string_test.exs | 12 +- test/translator/struct_test.exs | 14 +- test/translator/try_test.exs | 20 +- test/translator/tuple_test.exs | 22 +- 43 files changed, 642 insertions(+), 1316 deletions(-) delete mode 100644 bench/elixir_script_bench.exs create mode 100644 lib/elixir_script/prelude/list.ex delete mode 100644 src/javascript/lib/list.js delete mode 100644 src/javascript/tests/list.spec.js diff --git a/.travis.yml b/.travis.yml index e743ec45..fb501c9b 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,7 +1,7 @@ sudo: false language: elixir elixir: - - 1.1.0 + - 1.2.0 otp_release: - 18.0 before_script: diff --git a/bench/elixir_script_bench.exs b/bench/elixir_script_bench.exs deleted file mode 100644 index b1a3ad6c..00000000 --- a/bench/elixir_script_bench.exs +++ /dev/null @@ -1,34 +0,0 @@ -defmodule ElixirScript.Bench do - use Benchfella - - bench "compile number" do - ElixirScript.compile("1") - :ok - end - - bench "compile string" do - ElixirScript.compile("\"1\"") - :ok - end - - bench "compile atom" do - ElixirScript.compile(":atom") - :ok - end - - bench "compile list" do - ElixirScript.compile("[1, 2, 3, 4]") - :ok - end - - bench "compile tuple" do - ElixirScript.compile("{1, 2, 3, 4}") - :ok - end - - bench "compile map" do - ElixirScript.compile("%{ a: 1, b: 2, c: :atom }") - :ok - end - -end \ No newline at end of file diff --git a/lib/elixir_script/prelude/list.ex b/lib/elixir_script/prelude/list.ex new file mode 100644 index 00000000..97f5114c --- /dev/null +++ b/lib/elixir_script/prelude/list.ex @@ -0,0 +1,250 @@ +defmodule ElixirScript.List do + + def duplicate(data, size) do + do_duplicate(data, size, []) + end + + defp do_duplicate(_, 0, list) do + list + end + + defp do_duplicate(data, size, list) do + do_duplicate(data, size - 1, list ++ [data]) + end + + def to_tuple(list) do + JS.new(Elixir.Core.Tuple, list) + end + + def wrap(list) when is_list(list), do: list + def wrap(nil), do: [] + def wrap(term), do: [term] + + def append(list, term) do + concat(list, [term]) + end + + def prepend(list, term) do + concat([term], list) + end + + def concat(list_a, list_b) do + list_a.concat(list_b) + end + + def first(list) do + list[0] + end + + def last(list) do + list[length(list) - 1] + end + + def delete(list, item) do + do_delete(list, item, 0, []) + end + + defp do_delete(list, item, current_index, new_list) do + if current_index == length(list) do + new_list + else + new_list = case list[current_index] do + ^item -> + new_list + _ -> + new_list ++ [list[current_index]] + end + + do_delete(list, item, current_index + 1, new_list) + end + end + + def delete_at(list, index) do + do_delete_at(list, index, 0, []) + end + + defp do_delete_at(list, index, current_index, new_list) do + if current_index == length(list) do + new_list + else + new_list = case current_index == index do + true -> + new_list + _ -> + new_list ++ [list[current_index]] + end + + do_delete_at(list, index, current_index + 1, new_list) + end + end + + def insert_at(list, index, value) do + do_insert_at(list, index, value, 0, []) + end + + defp do_insert_at(list, index, value, current_index, new_list) do + if current_index == length(list) do + new_list + else + new_list = case current_index == index do + true -> + new_list ++ [value, list[current_index]] + _ -> + new_list ++ [list[current_index]] + end + + do_insert_at(list, index, value, current_index + 1, new_list) + end + end + + def replace_at(list, index, value) do + do_replace_at(list, index, value, 0, []) + end + + defp do_replace_at(list, index, value, current_index, new_list) do + if current_index == length(list) do + new_list + else + new_list = case current_index == index do + true -> + new_list ++ [value] + _ -> + new_list ++ [list[current_index]] + end + + do_replace_at(list, index, value, current_index + 1, new_list) + end + end + + + def update_at(list, index, func) do + do_update_at(list, index, func, 0, []) + end + + defp do_update_at(list, index, func, current_index, new_list) do + if current_index == length(list) do + new_list + else + new_list = case current_index == index do + true -> + new_list ++ [func.(list[current_index])] + _ -> + new_list ++ [list[current_index]] + end + + do_update_at(list, index, func, current_index + 1, new_list) + end + end + + + def foldl(list, acc, func) do + do_foldl(list, acc, func, []) + end + + def foldr(list, acc, func) do + do_foldl(list.concat([]).reverse(), acc, func, []) + end + + defp do_foldl([], acc, _, new_list) do + { acc, new_list } + end + + defp do_foldl(list, acc, func, new_list) do + { acc, value } = func.(hd(list), acc) + do_foldl(tl(list), acc, func, new_list ++ [value]) + end + + def flatten(list) do + do_flatten(list, []) + end + + def flatten(list, tail) do + do_flatten(list, []) ++ tail + end + + defp do_flatten([], flattened_list) do + flattened_list + end + + defp do_flatten(list, flattened_list) do + flattened_list = case hd(list) do + l when is_list(l) -> + flattened_list ++ do_flatten(l, []) + item -> + flattened_list ++ [item] + end + + do_flatten(tl(list), flattened_list) + end + + + def keydelete(list, key, position) do + do_keydelete(list, key, position, []) + end + + defp do_keydelete([], _, _, new_list) do + new_list + end + + defp do_keydelete(list, key, position, new_list) do + current_value = hd(list) + + new_list = if elem(current_value, position) == key do + new_list + else + new_list ++ [current_value] + end + + do_keydelete(tl(list), key, position, new_list) + end + + def keyfind(list, key, position) do + do_keyfind(list, key, position, nil) + end + + def keyfind(list, key, position, default) do + do_keyfind(list, key, position, default) + end + + defp do_keyfind([], _, _, default) do + default + end + + defp do_keyfind(list, key, position, default) do + current_value = hd(list) + + if elem(current_value, position) == key do + current_value + else + do_keyfind(tl(list), key, position, default) + end + end + + def keymember?(list, key, position) do + keyfind(list, key, position) != nil + end + + def keyreplace(list, key, position, new_tuple) do + do_keyreplace(list, key, position, [], new_tuple) + end + + defp do_keyreplace([], _, _, new_list, _) do + new_list + end + + defp do_keyreplace(list, key, position, new_list, new_tuple) do + current_value = hd(list) + + new_list = if elem(current_value, position) == key do + new_list ++ [new_tuple] + else + new_list ++ [current_value] + end + + do_keyreplace(tl(list), key, position, new_list, new_tuple) + end + + def zip(list_of_lists) do + Elixir.Core.Functions.zip(list_of_lists) + end +end diff --git a/lib/elixir_script/prelude/map.ex b/lib/elixir_script/prelude/map.ex index 6aeb6f16..8e5f0b52 100644 --- a/lib/elixir_script/prelude/map.ex +++ b/lib/elixir_script/prelude/map.ex @@ -51,7 +51,7 @@ defmodule ElixirScript.Map do true -> map[key] false -> - raise "#{key} not found in map" + raise "" end end @@ -185,7 +185,7 @@ defmodule ElixirScript.Map do true -> Map.put(map, key, func.(map[key])) false -> - raise "#{key} not found in map" + raise "" end end diff --git a/lib/elixir_script/prelude/tuple.ex b/lib/elixir_script/prelude/tuple.ex index 2f91079d..e0896ad7 100644 --- a/lib/elixir_script/prelude/tuple.ex +++ b/lib/elixir_script/prelude/tuple.ex @@ -1,7 +1,15 @@ defmodule ElixirScript.Tuple do def duplicate(data, size) do - Elixir.Core.Functions.make_tuple(size, data) + JS.new(Elixir.Core.Tuple, do_duplicate(data, size, [])) + end + + defp do_duplicate(_, 0, list) do + list + end + + defp do_duplicate(data, size, list) do + do_duplicate(data, size - 1, list ++ [data]) end def to_list(tuple) do @@ -9,15 +17,45 @@ defmodule ElixirScript.Tuple do end def insert_at(tuple, index, value) do - Elixir.Core.Functions.insert_at(tuple, index, value) + JS.new(Elixir.Core.Tuple, do_insert_at(tuple, index, value, 0, [])) + end + + defp do_insert_at(tuple, index, value, current_index, list) do + if current_index == length(tuple) do + list + else + list = case index == current_index do + true -> + list ++ [value, tuple.get(current_index)] + false -> + list ++ [tuple.get(current_index)] + end + + do_insert_at(tuple, index, value, current_index + 1, list) + end end def delete_at(tuple, index) do - Elixir.Core.Functions.delete_at(tuple, index) + JS.new(Elixir.Core.Tuple, delete_at(tuple, index, 0, [])) + end + + defp delete_at(tuple, index, current_index, list) do + if current_index == length(tuple) do + list + else + list = case index == current_index do + true -> + list + false -> + list ++ [tuple.get(current_index)] + end + + delete_at(tuple, index, current_index + 1, list) + end end def append(tuple, value) do - Elixir.Core.Functions.new_tuple.apply(nil, to_list(tuple) ++ value) + #JS.new(Elixir.Core.Tuple, to_list(tuple) ++ [value]) end end diff --git a/lib/elixir_script/translator/js.ex b/lib/elixir_script/translator/js.ex index 4917ba19..a9e9fd3c 100644 --- a/lib/elixir_script/translator/js.ex +++ b/lib/elixir_script/translator/js.ex @@ -10,16 +10,16 @@ defmodule ElixirScript.Translator.JS do { do_translate({name, [], params}, env), env } end - defp do_translate({:new, _, [{:__aliases__, _, module_name}, params]}, env) do + defp do_translate({:new, _, [module_name, params]}, env) when not is_list(params) do Builder.new_expression( - Utils.make_module_expression_tree(module_name, false, env), - Enum.map(params, &Translator.translate!(&1, env)) + Translator.translate!(module_name, env), + [Builder.rest_element(Translator.translate!(params, env))] ) end defp do_translate({:new, _, [module_name, params]}, env) do Builder.new_expression( - Translator.translate(module_name, env), + Translator.translate!(module_name, env), Enum.map(params, &Translator.translate!(&1, env)) ) end diff --git a/lib/elixir_script/translator/module.ex b/lib/elixir_script/translator/module.ex index 34bf11b2..0be24ff5 100644 --- a/lib/elixir_script/translator/module.ex +++ b/lib/elixir_script/translator/module.ex @@ -78,6 +78,10 @@ defmodule ElixirScript.Translator.Module do Macro.expand_once(using_ast, ElixirScript.Translator.State.get().compiler_opts.env) end + defp expand__using__({:__block__, _, [{:__block__, _, [{:require, _, _}, {{:., _, [_, :__using__]}, _, _} = using_ast]}]}) do + Macro.expand_once(using_ast, ElixirScript.Translator.State.get().compiler_opts.env) + end + def translate_body(body, env) do { body, env } = Translator.translate(body, env) diff --git a/lib/elixir_script/translator/primitive.ex b/lib/elixir_script/translator/primitive.ex index 0fa79249..718fa8c7 100644 --- a/lib/elixir_script/translator/primitive.ex +++ b/lib/elixir_script/translator/primitive.ex @@ -114,7 +114,7 @@ defmodule ElixirScript.Translator.Primitive do def make_tuple(elements, env) do list = Enum.map(elements, &Translator.translate!(&1, env)) - js_ast = JS.call_expression(new_tuple_function, list) + js_ast = JS.new_expression(tuple_class, list) { js_ast, env } end @@ -124,8 +124,8 @@ defmodule ElixirScript.Translator.Primitive do end def make_tuple_quoted(opts, elements, env) do - JS.call_expression( - new_tuple_function, + JS.new_expression( + tuple_class, Enum.map(elements, fn(x) -> Quote.make_quote(opts, x, env) end) ) end diff --git a/lib/elixir_script/translator/state.ex b/lib/elixir_script/translator/state.ex index 6b5f1673..1fee0366 100644 --- a/lib/elixir_script/translator/state.ex +++ b/lib/elixir_script/translator/state.ex @@ -28,6 +28,7 @@ defmodule ElixirScript.Translator.State do |> Map.put(Keyword, ElixirScript.Keyword) |> Map.put(Bitwise, ElixirScript.Bitwise) |> Map.put(MapSet, ElixirScript.MapSet) + |> Map.put(List, ElixirScript.List) end def add_module(module) do diff --git a/mix.exs b/mix.exs index 22f3ecd1..c7f2e513 100644 --- a/mix.exs +++ b/mix.exs @@ -29,10 +29,8 @@ defmodule ElixirScript.Mixfile do defp deps do [ {:estree, "~> 2.0"}, - {:shouldi, only: :test }, {:earmark, "~> 0.1", only: :dev }, {:ex_doc, "~> 0.10", only: :dev }, - {:benchfella, "~> 0.2", only: :test}, {:excoveralls, "~> 0.4", only: :test}, {:credo, "~> 0.2.0", only: [:dev, :test]} ] diff --git a/mix.lock b/mix.lock index a001ef8b..45a322e5 100644 --- a/mix.lock +++ b/mix.lock @@ -1,18 +1,18 @@ -%{"benchfella": {:hex, :benchfella, "0.3.0"}, +%{"benchfella": {:hex, :benchfella, "0.3.1"}, "bunt": {:hex, :bunt, "0.1.4"}, "certifi": {:hex, :certifi, "0.3.0"}, - "credo": {:hex, :credo, "0.2.2"}, + "credo": {:hex, :credo, "0.2.5"}, "dogma": {:hex, :dogma, "0.0.7"}, - "earmark": {:hex, :earmark, "0.1.19"}, + "earmark": {:hex, :earmark, "0.2.0"}, "estree": {:hex, :estree, "2.1.1"}, - "ex_doc": {:hex, :ex_doc, "0.11.1"}, + "ex_doc": {:hex, :ex_doc, "0.11.3"}, "excoveralls": {:hex, :excoveralls, "0.4.3"}, "exjsx": {:hex, :exjsx, "3.2.0"}, - "hackney": {:hex, :hackney, "1.4.6"}, + "hackney": {:hex, :hackney, "1.4.7"}, "idna": {:hex, :idna, "1.0.2"}, "inflex": {:hex, :inflex, "1.5.0"}, "jsx": {:hex, :jsx, "2.6.2"}, - "mimerl": {:hex, :mimerl, "1.0.0"}, + "mimerl": {:hex, :mimerl, "1.0.2"}, "poison": {:hex, :poison, "1.5.0"}, "shouldi": {:hex, :shouldi, "0.2.3"}, "ssl_verify_hostname": {:hex, :ssl_verify_hostname, "1.0.5"}} diff --git a/priv/Elixir.js b/priv/Elixir.js index 2f924514..4f45feac 100644 --- a/priv/Elixir.js +++ b/priv/Elixir.js @@ -50,7 +50,7 @@ class Process { } } -class Tuple$1 { +class Tuple { constructor(...args) { this.values = Object.freeze(args); @@ -100,7 +100,7 @@ class PID { class Integer {} class Float {} -function List$1(...args) { +function List(...args) { return Object.freeze(args); } @@ -1037,7 +1037,7 @@ function is_instance_of(value, type) { return value instanceof type; } -function size$2(term) { +function size(term) { return term.length; } @@ -1082,7 +1082,7 @@ function is_number$1(x) { } function is_tuple$1(x) { - return x instanceof Tuple$1; + return x instanceof Tuple; } function is_pid$1(x) { @@ -1130,7 +1130,7 @@ function apply$1(...args) { } function new_tuple(...args) { - return new Tuple$1(...args); + return new Tuple(...args); } function duplicate(data, size) { @@ -1240,10 +1240,78 @@ function b64EncodeUnicode(str) { })); } +function delete_property_from_map(map, property) { + let new_map = Object.assign(Object.create(map.constructor.prototype), map); + delete new_map[property]; + + return Object.freeze(new_map); +} + +function class_to_obj(map) { + let new_map = Object.assign({}, map); + return Object.freeze(new_map); +} + +function add_property_to_map(map, property, value) { + let new_map = Object.assign({}, map); + new_map[property] = value; + return Object.freeze(new_map); +} + +function bnot(expr) { + return ~expr; +} + +function band(left, right) { + return left & right; +} + +function bor(left, right) { + return left | right; +} + +function bsl(left, right) { + return left << right; +} + +function bsr(left, right) { + return left >> right; +} + +function bxor(left, right) { + return left ^ right; +} + +function zip(list_of_lists) { + if (list_of_lists.length === 0) { + return Object.freeze([]); + } + + let new_value = []; + let smallest_length = list_of_lists[0]; + + for (let x of list_of_lists) { + if (x.length < smallest_length) { + smallest_length = x.length; + } + } + + for (let i = 0; i < smallest_length; i++) { + let current_value = []; + for (let j = 0; j < list_of_lists.length; j++) { + current_value.push(list_of_lists[j][i]); + } + + new_value.push(new Tuple(...current_value)); + } + + return Object.freeze(new_value); +} + var Functions = { call_property, is_instance_of, - size: size$2, + size, is_nil: is_nil$1, is_atom: is_atom$1, is_binary: is_binary$1, @@ -1278,7 +1346,17 @@ var Functions = { defimpl, get_object_keys, is_valid_character, - b64EncodeUnicode + b64EncodeUnicode, + delete_property_from_map, + add_property_to_map, + class_to_obj, + bnot, + band, + bor, + bsl, + bsr, + bxor, + zip }; function list(...args) { @@ -1307,7 +1385,7 @@ function cond(clauses) { throw new Error(); } -function map$1(obj) { +function map(obj) { return Object.freeze(obj); } @@ -1326,7 +1404,7 @@ function _for(collections, fun, filter = () => true, into = [], previousValues = let args = previousValues.concat(r); if (r && filter.apply(this, args)) { - into = Enum.into([fun.apply(this, args)], into); + into = into.concat([fun.apply(this, args)]); } } @@ -1337,7 +1415,7 @@ function _for(collections, fun, filter = () => true, into = [], previousValues = for (let elem of collection) { let r = Patterns.match_no_throw(pattern, elem); if (r) { - _into = Enum.into(this._for(collections.slice(1), fun, filter, _into, previousValues.concat(r)), into); + _into = into.concat(this._for(collections.slice(1), fun, filter, _into, previousValues.concat(r))); } } @@ -1403,7 +1481,7 @@ var SpecialForms$1 = { tuple, _case, cond, - map: map$1, + map, map_update, _for, _try @@ -1415,14 +1493,14 @@ Functions.get_global().processes = Functions.get_global().processes || new Proce var C = Object.freeze({ ProcessSystem: ProcessSystem, - Tuple: Tuple$1, + Tuple: Tuple, PID: PID, BitString: BitString, Patterns: Patterns, Integer: Integer, Float: Float, Functions: Functions, - List: List$1, + List: List, SpecialForms: SpecialForms$1 }); @@ -1475,7 +1553,7 @@ function is_number(x) { } function is_tuple(x) { - return x instanceof Tuple$1; + return x instanceof Tuple; } function length(x) { @@ -1570,7 +1648,7 @@ function match__qmark__(pattern, expr, guard = () => true) { return Patterns.match_no_throw(pattern, expr, guard) != null; } -var Kernel = { +var kernel = { tl, hd, is_nil, @@ -1603,7 +1681,7 @@ var Kernel = { match__qmark__ }; -let Enum$1 = { +let Enum = { all__qmark__: function (collection, fun = x => x) { for (let elem of collection) { @@ -1674,27 +1752,27 @@ let Enum$1 = { }, fetch: function (collection, n) { - if (Kernel.is_list(collection)) { + if (Array.isArray(collection)) { if (n < this.count(collection) && n >= 0) { - return new Tuple$1(Symbol.for('ok'), collection[n]); + return new Tuple(Symbol.for("ok"), collection[n]); } else { - return Symbol.for('error'); + return Symbol.for("error"); } } - throw new Error('collection is not an Enumerable'); + throw new Error("collection is not an Enumerable"); }, fetch__emark__: function (collection, n) { - if (Kernel.is_list(collection)) { + if (Array.isArray(collection)) { if (n < this.count(collection) && n >= 0) { return collection[n]; } else { - throw new Error('out of bounds error'); + throw new Error("out of bounds error"); } } - throw new Error('collection is not an Enumerable'); + throw new Error("collection is not an Enumerable"); }, filter: function (collection, fun) { @@ -1710,7 +1788,7 @@ let Enum$1 = { }, filter_map: function (collection, filter, mapper) { - return Enum$1.map(Enum$1.filter(collection, filter), mapper); + return Enum.map(Enum.filter(collection, filter), mapper); }, find: function (collection, if_none = null, fun) { @@ -1738,17 +1816,17 @@ let Enum$1 = { }, map_reduce: function (collection, acc, fun) { - let mapped = List$1(); + let mapped = List(); let the_acc = acc; for (var i = 0; i < this.count(collection); i++) { let tuple = fun(collection[i], the_acc); the_acc = tuple.get(1); - mapped = List$1(...mapped.concat([tuple.get(0)])); + mapped = List(...mapped.concat([tuple.get(0)])); } - return new Tuple$1(mapped, the_acc); + return new Tuple(mapped, the_acc); }, member__qmark__: function (collection, value) { @@ -1781,7 +1859,7 @@ let Enum$1 = { } } - return List$1(...result); + return List(...result); }, take_while: function (collection, fun) { @@ -1803,683 +1881,6 @@ let Enum$1 = { } }; -let List = {}; - -List.delete = function (list, item) { - let new_value = []; - let value_found = false; - - for (let x of list) { - if (x === item && value_found !== false) { - new_value.push(x); - value_found = true; - } else if (x !== item) { - new_value.push(x); - } - } - - return SpecialForms$1.list(...new_value); -}; - -List.delete_at = function (list, index) { - let new_value = []; - - for (let i = 0; i < list.length; i++) { - if (i !== index) { - new_value.push(list[i]); - } - } - - return SpecialForms$1.list(...new_value); -}; - -List.duplicate = function (elem, n) { - let new_value = []; - - for (var i = 0; i < n; i++) { - new_value.push(elem); - } - - return SpecialForms$1.list(...new_value); -}; - -List.first = function (list) { - return list[0]; -}; - -List.flatten = function (list, tail = SpecialForms$1.list()) { - let new_value = []; - - for (let x of list) { - if (Kernel.is_list(x)) { - new_value = new_value.concat(List.flatten(x)); - } else { - new_value.push(x); - } - } - - new_value = new_value.concat(tail); - - return SpecialForms$1.list(...new_value); -}; - -List.foldl = function (list, acc, func) { - return list.reduce(func, acc); -}; - -List.foldr = function (list, acc, func) { - let new_acc = acc; - - for (var i = list.length - 1; i >= 0; i--) { - new_acc = func(list[i], new_acc); - } - - return new_acc; -}; - -List.insert_at = function (list, index, value) { - let new_value = []; - - for (let i = 0; i < list.length; i++) { - if (i === index) { - new_value.push(value); - new_value.push(list[i]); - } else { - new_value.push(list[i]); - } - } - - return SpecialForms$1.list(...new_value); -}; - -List.keydelete = function (list, key, position) { - let new_list = []; - - for (let i = 0; i < list.length; i++) { - if (!Kernel.match__qmark__(list[i][position], key)) { - new_list.push(list[i]); - } - } - - return SpecialForms$1.list(...new_list); -}; - -List.keyfind = function (list, key, position, _default = null) { - - for (let i = 0; i < list.length; i++) { - if (Kernel.match__qmark__(list[i][position], key)) { - return list[i]; - } - } - - return _default; -}; - -List.keymember__qmark__ = function (list, key, position) { - - for (let i = 0; i < list.length; i++) { - if (Kernel.match__qmark__(list[i][position], key)) { - return true; - } - } - - return false; -}; - -List.keyreplace = function (list, key, position, new_tuple) { - let new_list = []; - - for (let i = 0; i < list.length; i++) { - if (!Kernel.match__qmark__(list[i][position], key)) { - new_list.push(list[i]); - } else { - new_list.push(new_tuple); - } - } - - return SpecialForms$1.list(...new_list); -}; - -List.keysort = function (list, position) { - let new_list = list; - - new_list.sort(function (a, b) { - if (position === 0) { - if (a[position].value < b[position].value) { - return -1; - } - - if (a[position].value > b[position].value) { - return 1; - } - - return 0; - } else { - if (a[position] < b[position]) { - return -1; - } - - if (a[position] > b[position]) { - return 1; - } - - return 0; - } - }); - - return SpecialForms$1.list(...new_list); -}; - -List.keystore = function (list, key, position, new_tuple) { - let new_list = []; - let replaced = false; - - for (let i = 0; i < list.length; i++) { - if (!Kernel.match__qmark__(list[i][position], key)) { - new_list.push(list[i]); - } else { - new_list.push(new_tuple); - replaced = true; - } - } - - if (!replaced) { - new_list.push(new_tuple); - } - - return SpecialForms$1.list(...new_list); -}; - -List.last = function (list) { - return list[list.length - 1]; -}; - -List.replace_at = function (list, index, value) { - let new_value = []; - - for (let i = 0; i < list.length; i++) { - if (i === index) { - new_value.push(value); - } else { - new_value.push(list[i]); - } - } - - return SpecialForms$1.list(...new_value); -}; - -List.update_at = function (list, index, fun) { - let new_value = []; - - for (let i = 0; i < list.count(); i++) { - if (i === index) { - new_value.push(fun(list.get(i))); - } else { - new_value.push(list.get(i)); - } - } - - return new_value; -}; - -List.wrap = function (list) { - if (Kernel.is_list(list)) { - return list; - } else if (list == null) { - return SpecialForms$1.list(); - } else { - return SpecialForms$1.list(list); - } -}; - -List.zip = function (list_of_lists) { - if (list_of_lists.length === 0) { - return SpecialForms$1.list(); - } - - let new_value = []; - let smallest_length = list_of_lists[0]; - - for (let x of list_of_lists) { - if (x.length < smallest_length) { - smallest_length = x.length; - } - } - - for (let i = 0; i < smallest_length; i++) { - let current_value = []; - for (let j = 0; j < list_of_lists.length; j++) { - current_value.push(list_of_lists[j][i]); - } - - new_value.push(new Tuple$1(...current_value)); - } - - return SpecialForms$1.list(...new_value); -}; - -List.to_tuple = function (list) { - return new Tuple$1(...list); -}; - -List.append = function (list, value) { - return SpecialForms$1.list(...list.concat([value])); -}; - -List.prepend = function (list, value) { - return SpecialForms$1.list(...[value].concat(list)); -}; - -List.concat = function (left, right) { - return left.concat(right); -}; - -let Keyword = {}; - -Keyword.has_key__qmark__ = function (keywords, key) { - for (let keyword of keywords) { - if (Kernel.elem(keyword, 0) == key) { - return true; - } - } - - return false; -}; - -Keyword.get = function (keywords, key, the_default = null) { - for (let keyword of keywords) { - if (Kernel.elem(keyword, 0) == key) { - return Kernel.elem(keyword, 1); - } - } - - return the_default; -}; - -function bnot(expr) { - return ~expr; -} - -function band(left, right) { - return left & right; -} - -function bor(left, right) { - return left | right; -} - -function bsl(left, right) { - return left << right; -} - -function bsr(left, right) { - return left >> right; -} - -function bxor(left, right) { - return left ^ right; -} - -var bitwise = { - bnot, - band, - bor, - bsl, - bsr, - bxor -}; - -function __new__() { - return SpecialForms$1.map({}); -} - -function keys(map) { - return Functions.get_object_keys(map); -} - -function size(map) { - return keys(map).length; -} - -function to_list(map) { - let map_keys = keys(map); - let list = []; - - for (let key of map_keys) { - list.push(new Tuple$1(key, map[key])); - } - - return List$1(...list); -} - -function values(map) { - let map_keys = keys(map); - let list = []; - - for (let key of map_keys) { - list.push(map[key]); - } - - return List$1(...list); -} - -function from_struct(struct) { - let map = Object.assign({}, struct); - delete map[Symbol.for("__struct__")]; - - return SpecialForms$1.map(map); -} - -function __delete__(map, key) { - let new_map = Object.assign({}, map); - - delete new_map[key]; - - return SpecialForms$1.map(new_map); -} - -function equal__qmark__(map1, map2) { - return map1 === map2; -} - -function fetch__emark__(map, key) { - if (key in map) { - return map[key]; - } - - throw new Error("Key not found."); -} - -function fetch(map, key) { - if (key in map) { - return new Tuple$1(Symbol.for("ok"), map[key]); - } - - return Symbol.for("error"); -} - -function has_key__qmark__(map, key) { - return key in map; -} - -function split(map, keys) { - let split1 = {}; - let split2 = {}; - - for (let key of Functions.get_object_keys(map)) { - if (keys.indexOf(key) > -1) { - split1[key] = map[key]; - } else { - split2[key] = map[key]; - } - } - - return new Tuple$1(SpecialForms$1.map(split1), SpecialForms$1.map(split2)); -} - -function take(map, keys) { - let split1 = {}; - - for (let key of Functions.get_object_keys(map)) { - if (keys.indexOf(key) > -1) { - split1[key] = map[key]; - } - } - - return SpecialForms$1.map(split1); -} - -function drop(map, keys) { - let split1 = {}; - - for (let key of Functions.get_object_keys(map)) { - if (keys.indexOf(key) === -1) { - split1[key] = map[key]; - } - } - - return SpecialForms$1.map(split1); -} - -function put_new(map, key, value) { - if (key in map) { - return map; - } - - let new_map = Object.assign({}, map); - new_map[key] = value; - - return SpecialForms$1.map(new_map); -} - -function put_new_lazy(map, key, fun) { - if (key in map) { - return map; - } - - let new_map = Object.assign({}, map); - new_map[key] = fun(); - - return SpecialForms$1.map(new_map); -} - -function get_and_update(map, key, fun) { - if (key in map) { - return map; - } - - let new_map = Object.assign({}, map); - new_map[key] = fun(map[key]); - - return SpecialForms$1.map(new_map); -} - -function pop_lazy(map, key, fun) { - if (!key in map) { - return new Tuple$1(fun(), map); - } - - let new_map = Object.assign({}, map); - let value = fun(new_map[key]); - delete new_map[key]; - - return new Tuple$1(value, new_map); -} - -function pop(map, key, _default = null) { - if (!key in map) { - return new Tuple$1(_default, map); - } - - let new_map = Object.assign({}, map); - let value = new_map[key]; - delete new_map[key]; - - return new Tuple$1(value, new_map); -} - -function get_lazy(map, key, fun) { - if (!key in map) { - return fun(); - } - - return fun(map[key]); -} - -function get(map, key, _default = null) { - if (!key in map) { - return _default; - } - - return map[key]; -} - -function put(map, key, val) { - let new_map = Object({}, map); - new_map[key] = val; - - return SpecialForms$1.map(new_map); -} - -function update__emark__(map, key, fun) { - if (!key in map) { - throw new Error("Key not found"); - } - - let new_map = Object({}, map); - new_map[key] = fun(map[key]); - - return SpecialForms$1.map(new_map); -} - -function update(map, key, initial, fun) { - let new_map = Object({}, map); - - if (!key in map) { - new_map[key] = initial; - } else { - new_map[key] = fun(map[key]); - } - - return SpecialForms$1.map(new_map); -} - -var map = { - new: __new__, - keys, - size, - to_list, - values, - from_struct, - delete: __delete__, - drop, - equal__qmark__, - fetch__emark__, - fetch, - has_key__qmark__, - split, - take, - put_new, - put_new_lazy, - get_and_update, - pop_lazy, - pop, - get_lazy, - get, - put, - update__emark__, - update -}; - -function __new__$1() { - return SpecialForms$1.map({ [Symbol.for('__struct__')]: Symbol.for('MapSet'), set: List$1() }); -} - -function size$1(map) { - return map.set.length; -} - -function to_list$1(map) { - return map.set; -} - -function __delete__$1(set, term) { - let new_list = List.delete(set.set, term); - - let new_map = Object.assign({}, set); - new_map.set = new_list; - return SpecialForms$1.map(new_map); -} - -function put$1(set, term) { - if (set.set.indexOf(term) === -1) { - let new_list = List.append(set.set, term); - - let new_map = Object.assign({}, set); - new_map.set = new_list; - return SpecialForms$1.map(new_map); - } - - return set; -} - -function difference(set1, set2) { - let new_map = Object.assign({}, set1); - - for (let val of set1.set) { - if (member__qmark__(set2, val)) { - new_map.set = List.delete(new_map.set, val); - } - } - - return SpecialForms$1.map(new_map); -} - -function intersection(set1, set2) { - let new_map = Object.assign({}, set1); - - for (let val of set1.set) { - if (!member__qmark__(set2, val)) { - new_map.set = List.delete(new_map.set, val); - } - } - - return SpecialForms$1.map(new_map); -} - -function union(set1, set2) { - let new_map = set1; - - for (let val of set2.set) { - new_map = put$1(new_map, val); - } - - return SpecialForms$1.map(new_map); -} - -function disjoin__qmark__(set1, set2) { - for (let val of set1.set) { - if (member__qmark__(set2, val)) { - return false; - } - } - - return true; -} - -function member__qmark__(set, value) { - return set.set.indexOf(value) >= 0; -} - -function equal__qmark__$1(set1, set2) { - return set1.set === set2.set; -} - -function subset__qmark__(set1, set2) { - for (let val of set1.set) { - if (!member__qmark__(set2, val)) { - return false; - } - } - - return true; -} - -var map_set = { - new: __new__$1, - size: size$1, - to_list: to_list$1, - disjoin__qmark__, - delete: __delete__$1, - subset__qmark__, - equal__qmark__: equal__qmark__$1, - member__qmark__, - put: put$1, - union, - intersection, - difference -}; - let VirtualDOM = (function (e) { return e(); })(function () { @@ -4089,5 +3490,5 @@ let VirtualDOM = (function (e) { const Core = C; -export { Core, Kernel, Enum, List, Keyword, bitwise as Bitwise, map as Map, map_set as MapSet, VirtualDOM }; -//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiIiwic291cmNlcyI6WyJFbGl4aXIuanMiXSwic291cmNlc0NvbnRlbnQiOlsiLyogQGZsb3cgKi9cblxuY2xhc3MgTWFpbGJveCB7XG5cbiAgY29uc3RydWN0b3IoKSB7XG4gICAgdGhpcy5tZXNzYWdlcyA9IFtdO1xuICB9XG5cbiAgZGVsaXZlcihtZXNzYWdlKSB7XG4gICAgdGhpcy5tZXNzYWdlcy5wdXNoKG1lc3NhZ2UpO1xuICAgIHJldHVybiBtZXNzYWdlO1xuICB9XG5cbiAgZ2V0KCkge1xuICAgIHJldHVybiB0aGlzLm1lc3NhZ2VzO1xuICB9XG5cbiAgaXNFbXB0eSgpIHtcbiAgICByZXR1cm4gdGhpcy5tZXNzYWdlcy5sZW5ndGggPT09IDA7XG4gIH1cblxuICByZW1vdmVBdChpbmRleCkge1xuICAgIHRoaXMubWVzc2FnZXMuc3BsaWNlKGluZGV4LCAxKTtcbiAgfVxufVxuXG52YXIgU3RhdGVzID0ge1xuICBOT1JNQUw6IFN5bWJvbC5mb3IoXCJub3JtYWxcIiksXG4gIEtJTEw6IFN5bWJvbC5mb3IoXCJraWxsXCIpLFxuICBTVVNQRU5EOiBTeW1ib2wuZm9yKFwic3VzcGVuZFwiKSxcbiAgQ09OVElOVUU6IFN5bWJvbC5mb3IoXCJjb250aW51ZVwiKSxcbiAgUkVDRUlWRTogU3ltYm9sLmZvcihcInJlY2VpdmVcIiksXG4gIFNFTkQ6IFN5bWJvbC5mb3IoXCJzZW5kXCIpLFxuICBTTEVFUElORzogU3ltYm9sLmZvcihcInNsZWVwaW5nXCIpLFxuICBSVU5OSU5HOiBTeW1ib2wuZm9yKFwicnVubmluZ1wiKSxcbiAgU1VTUEVOREVEOiBTeW1ib2wuZm9yKFwic3VzcGVuZGVkXCIpLFxuICBTVE9QUEVEOiBTeW1ib2wuZm9yKFwic3RvcHBlZFwiKSxcbiAgU0xFRVA6IFN5bWJvbC5mb3IoXCJzbGVlcFwiKSxcbiAgRVhJVDogU3ltYm9sLmZvcihcImV4aXRcIiksXG4gIE5PTUFUQ0g6IFN5bWJvbC5mb3IoXCJub19tYXRjaFwiKVxufTtcblxuY2xhc3MgUHJvY2VzcyB7XG5cbiAgY29uc3RydWN0b3IocGlkLCBtYWlsYm94KSB7XG4gICAgdGhpcy5waWQgPSBwaWQ7XG4gICAgdGhpcy5tYWlsYm94ID0gbWFpbGJveDtcbiAgICB0aGlzLnN0YXR1cyA9IFN0YXRlcy5TVE9QUEVEO1xuICAgIHRoaXMuZGljdCA9IHt9O1xuICB9XG59XG5cbmNsYXNzIFR1cGxlJDEge1xuXG4gIGNvbnN0cnVjdG9yKC4uLmFyZ3MpIHtcbiAgICB0aGlzLnZhbHVlcyA9IE9iamVjdC5mcmVlemUoYXJncyk7XG4gICAgdGhpcy5sZW5ndGggPSB0aGlzLnZhbHVlcy5sZW5ndGg7XG4gIH1cblxuICBnZXQoaW5kZXgpIHtcbiAgICByZXR1cm4gdGhpcy52YWx1ZXNbaW5kZXhdO1xuICB9XG5cbiAgY291bnQoKSB7XG4gICAgcmV0dXJuIHRoaXMudmFsdWVzLmxlbmd0aDtcbiAgfVxuXG4gIFtTeW1ib2wuaXRlcmF0b3JdKCkge1xuICAgIHJldHVybiB0aGlzLnZhbHVlc1tTeW1ib2wuaXRlcmF0b3JdKCk7XG4gIH1cblxuICB0b1N0cmluZygpIHtcbiAgICB2YXIgaSxcbiAgICAgICAgcyA9IFwiXCI7XG4gICAgZm9yIChpID0gMDsgaSA8IHRoaXMudmFsdWVzLmxlbmd0aDsgaSsrKSB7XG4gICAgICBpZiAocyAhPT0gXCJcIikge1xuICAgICAgICBzICs9IFwiLCBcIjtcbiAgICAgIH1cbiAgICAgIHMgKz0gdGhpcy52YWx1ZXNbaV0udG9TdHJpbmcoKTtcbiAgICB9XG5cbiAgICByZXR1cm4gXCJ7XCIgKyBzICsgXCJ9XCI7XG4gIH1cblxufVxuXG5sZXQgcHJvY2Vzc19jb3VudGVyID0gLTE7XG5cbmNsYXNzIFBJRCB7XG4gIGNvbnN0cnVjdG9yKCkge1xuICAgIHByb2Nlc3NfY291bnRlciA9IHByb2Nlc3NfY291bnRlciArIDE7XG4gICAgdGhpcy5pZCA9IHByb2Nlc3NfY291bnRlcjtcbiAgfVxuXG4gIHRvU3RyaW5nKCkge1xuICAgIHJldHVybiBcIlBJRCM8MC5cIiArIHRoaXMuaWQgKyBcIi4wPlwiO1xuICB9XG59XG5cbmNsYXNzIEludGVnZXIge31cbmNsYXNzIEZsb2F0IHt9XG5cbmZ1bmN0aW9uIExpc3QkMSguLi5hcmdzKSB7XG4gIHJldHVybiBPYmplY3QuZnJlZXplKGFyZ3MpO1xufVxuXG5jbGFzcyBQcm9jZXNzU3lzdGVtIHtcblxuICBjb25zdHJ1Y3RvcigpIHtcbiAgICB0aGlzLnBpZHMgPSBuZXcgTWFwKCk7XG4gICAgdGhpcy5tYWlsYm94ZXMgPSBuZXcgTWFwKCk7XG4gICAgdGhpcy5uYW1lcyA9IG5ldyBNYXAoKTtcbiAgICB0aGlzLmxpbmtzID0gbmV3IE1hcCgpO1xuXG4gICAgdGhpcy5jdXJyZW50X3Byb2Nlc3MgPSBudWxsO1xuICAgIHRoaXMuc3VzcGVuZGVkID0gbmV3IE1hcCgpO1xuXG4gICAgdGhpcy5tYWluX3Byb2Nlc3NfcGlkID0gdGhpcy5zcGF3bigpO1xuICAgIHRoaXMuc2V0X2N1cnJlbnQodGhpcy5tYWluX3Byb2Nlc3NfcGlkKTtcbiAgfVxuXG4gIHNwYXduKCkge1xuICAgIHJldHVybiB0aGlzLmFkZF9wcm9jKGZhbHNlKS5waWQ7XG4gIH1cblxuICBzcGF3bl9saW5rKCkge1xuICAgIHJldHVybiB0aGlzLmFkZF9wcm9jKHRydWUpLnBpZDtcbiAgfVxuXG4gIGxpbmsocGlkKSB7XG4gICAgdGhpcy5saW5rcy5nZXQodGhpcy5waWQoKSkuYWRkKHBpZCk7XG4gICAgdGhpcy5saW5rcy5nZXQocGlkKS5hZGQodGhpcy5waWQoKSk7XG4gIH1cblxuICB1bmxpbmsocGlkKSB7XG4gICAgdGhpcy5saW5rcy5nZXQodGhpcy5waWQoKSkuZGVsZXRlKHBpZCk7XG4gICAgdGhpcy5saW5rcy5nZXQocGlkKS5kZWxldGUodGhpcy5waWQoKSk7XG4gIH1cblxuICBzZXRfY3VycmVudChpZCkge1xuICAgIGxldCBwaWQgPSB0aGlzLnBpZG9mKGlkKTtcbiAgICBpZiAocGlkICE9PSBudWxsKSB7XG4gICAgICB0aGlzLmN1cnJlbnRfcHJvY2VzcyA9IHRoaXMucGlkcy5nZXQocGlkKTtcbiAgICAgIHRoaXMuY3VycmVudF9wcm9jZXNzLnN0YXR1cyA9IFN0YXRlcy5SVU5OSU5HO1xuICAgIH1cbiAgfVxuXG4gIGFkZF9wcm9jKGxpbmtlZCkge1xuICAgIGxldCBuZXdwaWQgPSBuZXcgUElEKCk7XG4gICAgbGV0IG1haWxib3ggPSBuZXcgTWFpbGJveCgpO1xuICAgIGxldCBuZXdwcm9jID0gbmV3IFByb2Nlc3MobmV3cGlkLCBtYWlsYm94KTtcblxuICAgIHRoaXMucGlkcy5zZXQobmV3cGlkLCBuZXdwcm9jKTtcbiAgICB0aGlzLm1haWxib3hlcy5zZXQobmV3cGlkLCBtYWlsYm94KTtcbiAgICB0aGlzLmxpbmtzLnNldChuZXdwaWQsIG5ldyBTZXQoKSk7XG5cbiAgICBpZiAobGlua2VkKSB7XG4gICAgICB0aGlzLmxpbmsobmV3cGlkKTtcbiAgICB9XG5cbiAgICByZXR1cm4gbmV3cHJvYztcbiAgfVxuXG4gIHJlbW92ZV9wcm9jKHBpZCkge1xuICAgIHRoaXMucGlkcy5kZWxldGUocGlkKTtcbiAgICB0aGlzLnVucmVnaXN0ZXIocGlkKTtcblxuICAgIGlmICh0aGlzLmxpbmtzLmhhcyhwaWQpKSB7XG4gICAgICBmb3IgKGxldCBsaW5rcGlkIG9mIHRoaXMubGlua3MuZ2V0KHBpZCkpIHtcbiAgICAgICAgdGhpcy5saW5rcy5nZXQobGlua3BpZCkuZGVsZXRlKHBpZCk7XG4gICAgICB9XG5cbiAgICAgIHRoaXMubGlua3MuZGVsZXRlKHBpZCk7XG4gICAgfVxuICB9XG5cbiAgZXhpdChpZCkge1xuICAgIGxldCBwaWQgPSB0aGlzLnBpZG9mKGlkKTtcbiAgICB0aGlzLnJlbW92ZV9wcm9jKGlkKTtcbiAgfVxuXG4gIHJlZ2lzdGVyKG5hbWUsIHBpZCkge1xuICAgIGlmICghdGhpcy5uYW1lcy5oYXMobmFtZSkpIHtcbiAgICAgIHRoaXMubmFtZXMuc2V0KG5hbWUsIHBpZCk7XG4gICAgICByZXR1cm4gbmFtZTtcbiAgICB9IGVsc2Uge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKFwiTmFtZSBpcyBhbHJlYWR5IHJlZ2lzdGVyZWQgdG8gYW5vdGhlciBwcm9jZXNzXCIpO1xuICAgIH1cbiAgfVxuXG4gIHJlZ2lzdGVyZWQobmFtZSkge1xuICAgIHJldHVybiB0aGlzLm5hbWVzLmhhcyhuYW1lKSA/IHRoaXMubmFtZXMuZ2V0KG5hbWUpIDogbnVsbDtcbiAgfVxuXG4gIHVucmVnaXN0ZXIocGlkKSB7XG4gICAgZm9yIChsZXQgbmFtZSBvZiB0aGlzLm5hbWVzLmtleXMoKSkge1xuICAgICAgaWYgKHRoaXMubmFtZXMuaGFzKG5hbWUpICYmIHRoaXMubmFtZXMuZ2V0KG5hbWUpID09PSBwaWQpIHtcbiAgICAgICAgdGhpcy5uYW1lcy5kZWxldGUobmFtZSk7XG4gICAgICB9XG4gICAgfVxuICB9XG5cbiAgcGlkKCkge1xuICAgIHJldHVybiB0aGlzLmN1cnJlbnRfcHJvY2Vzcy5waWQ7XG4gIH1cblxuICBwaWRvZihpZCkge1xuICAgIGlmIChpZCBpbnN0YW5jZW9mIFBJRCkge1xuICAgICAgcmV0dXJuIHRoaXMucGlkcy5oYXMoaWQpID8gaWQgOiBudWxsO1xuICAgIH0gZWxzZSBpZiAoaWQgaW5zdGFuY2VvZiBQcm9jZXNzKSB7XG4gICAgICByZXR1cm4gaWQucGlkO1xuICAgIH0gZWxzZSB7XG4gICAgICBsZXQgcGlkID0gdGhpcy5yZWdpc3RlcmVkKGlkKTtcbiAgICAgIGlmIChwaWQgPT09IG51bGwpIHRocm93IFwiUHJvY2VzcyBuYW1lIG5vdCByZWdpc3RlcmVkOiBcIiArIGlkICsgXCIgKFwiICsgdHlwZW9mIGlkICsgXCIpXCI7XG4gICAgICByZXR1cm4gcGlkO1xuICAgIH1cbiAgfVxuXG4gIHB1dChpZCwga2V5LCB2YWx1ZSkge1xuICAgIGxldCBwaWQgPSB0aGlzLnBpZG9mKGlkKTtcbiAgICBsZXQgcHJvY2VzcyA9IHRoaXMucGlkcy5nZXQocGlkKTtcbiAgICBwcm9jZXNzLmRpY3Rba2V5XSA9IHZhbHVlO1xuICB9XG5cbiAgZ2V0KGlkLCBrZXkpIHtcbiAgICBsZXQgcGlkID0gdGhpcy5waWRvZihpZCk7XG4gICAgbGV0IHByb2Nlc3MgPSB0aGlzLnBpZHMuZ2V0KHBpZCk7XG5cbiAgICBpZiAoa2V5ICE9IG51bGwpIHtcbiAgICAgIHJldHVybiBwcm9jZXNzLmRpY3Rba2V5XTtcbiAgICB9IGVsc2Uge1xuICAgICAgcmV0dXJuIHByb2Nlc3MuZGljdDtcbiAgICB9XG4gIH1cblxuICBnZXRfa2V5cyhpZCkge1xuICAgIGxldCBwaWQgPSB0aGlzLnBpZG9mKGlkKTtcbiAgICBsZXQgcHJvY2VzcyA9IHRoaXMucGlkcy5nZXQocGlkKTtcblxuICAgIHJldHVybiBPYmplY3Qua2V5cyhwcm9jZXNzLmRpY3QpO1xuICB9XG5cbiAgZXJhc2UoaWQsIGtleSkge1xuICAgIGxldCBwaWQgPSB0aGlzLnBpZG9mKGlkKTtcbiAgICBsZXQgcHJvY2VzcyA9IHRoaXMucGlkcy5nZXQocGlkKTtcblxuICAgIGlmIChrZXkgIT0gbnVsbCkge1xuICAgICAgZGVsZXRlIHByb2Nlc3MuZGljdFtrZXldO1xuICAgIH0gZWxzZSB7XG4gICAgICBwcm9jZXNzLmRpY3QgPSB7fTtcbiAgICB9XG4gIH1cbn1cblxuY2xhc3MgQml0U3RyaW5nIHtcbiAgY29uc3RydWN0b3IoLi4uYXJncykge1xuICAgIHRoaXMucmF3X3ZhbHVlID0gZnVuY3Rpb24gKCkge1xuICAgICAgcmV0dXJuIE9iamVjdC5mcmVlemUoYXJncyk7XG4gICAgfTtcblxuICAgIHRoaXMudmFsdWUgPSBPYmplY3QuZnJlZXplKHRoaXMucHJvY2VzcyhhcmdzKSk7XG4gIH1cblxuICBnZXQoaW5kZXgpIHtcbiAgICByZXR1cm4gdGhpcy52YWx1ZVtpbmRleF07XG4gIH1cblxuICBjb3VudCgpIHtcbiAgICByZXR1cm4gdGhpcy52YWx1ZS5sZW5ndGg7XG4gIH1cblxuICBbU3ltYm9sLml0ZXJhdG9yXSgpIHtcbiAgICByZXR1cm4gdGhpcy52YWx1ZVtTeW1ib2wuaXRlcmF0b3JdKCk7XG4gIH1cblxuICB0b1N0cmluZygpIHtcbiAgICB2YXIgaSxcbiAgICAgICAgcyA9IFwiXCI7XG4gICAgZm9yIChpID0gMDsgaSA8IHRoaXMuY291bnQoKTsgaSsrKSB7XG4gICAgICBpZiAocyAhPT0gXCJcIikge1xuICAgICAgICBzICs9IFwiLCBcIjtcbiAgICAgIH1cbiAgICAgIHMgKz0gdGhpc1tpXS50b1N0cmluZygpO1xuICAgIH1cblxuICAgIHJldHVybiBcIjw8XCIgKyBzICsgXCI+PlwiO1xuICB9XG5cbiAgcHJvY2VzcygpIHtcbiAgICBsZXQgcHJvY2Vzc2VkX3ZhbHVlcyA9IFtdO1xuXG4gICAgdmFyIGk7XG4gICAgZm9yIChpID0gMDsgaSA8IHRoaXMucmF3X3ZhbHVlKCkubGVuZ3RoOyBpKyspIHtcbiAgICAgIGxldCBwcm9jZXNzZWRfdmFsdWUgPSB0aGlzW1wicHJvY2Vzc19cIiArIHRoaXMucmF3X3ZhbHVlKClbaV0udHlwZV0odGhpcy5yYXdfdmFsdWUoKVtpXSk7XG5cbiAgICAgIGZvciAobGV0IGF0dHIgb2YgdGhpcy5yYXdfdmFsdWUoKVtpXS5hdHRyaWJ1dGVzKSB7XG4gICAgICAgIHByb2Nlc3NlZF92YWx1ZSA9IHRoaXNbXCJwcm9jZXNzX1wiICsgYXR0cl0ocHJvY2Vzc2VkX3ZhbHVlKTtcbiAgICAgIH1cblxuICAgICAgcHJvY2Vzc2VkX3ZhbHVlcyA9IHByb2Nlc3NlZF92YWx1ZXMuY29uY2F0KHByb2Nlc3NlZF92YWx1ZSk7XG4gICAgfVxuXG4gICAgcmV0dXJuIHByb2Nlc3NlZF92YWx1ZXM7XG4gIH1cblxuICBwcm9jZXNzX2ludGVnZXIodmFsdWUpIHtcbiAgICByZXR1cm4gdmFsdWUudmFsdWU7XG4gIH1cblxuICBwcm9jZXNzX2Zsb2F0KHZhbHVlKSB7XG4gICAgaWYgKHZhbHVlLnNpemUgPT09IDY0KSB7XG4gICAgICByZXR1cm4gQml0U3RyaW5nLmZsb2F0NjRUb0J5dGVzKHZhbHVlLnZhbHVlKTtcbiAgICB9IGVsc2UgaWYgKHZhbHVlLnNpemUgPT09IDMyKSB7XG4gICAgICByZXR1cm4gQml0U3RyaW5nLmZsb2F0MzJUb0J5dGVzKHZhbHVlLnZhbHVlKTtcbiAgICB9XG5cbiAgICB0aHJvdyBuZXcgRXJyb3IoXCJJbnZhbGlkIHNpemUgZm9yIGZsb2F0XCIpO1xuICB9XG5cbiAgcHJvY2Vzc19iaXRzdHJpbmcodmFsdWUpIHtcbiAgICByZXR1cm4gdmFsdWUudmFsdWUudmFsdWU7XG4gIH1cblxuICBwcm9jZXNzX2JpbmFyeSh2YWx1ZSkge1xuICAgIHJldHVybiBCaXRTdHJpbmcudG9VVEY4QXJyYXkodmFsdWUudmFsdWUpO1xuICB9XG5cbiAgcHJvY2Vzc191dGY4KHZhbHVlKSB7XG4gICAgcmV0dXJuIEJpdFN0cmluZy50b1VURjhBcnJheSh2YWx1ZS52YWx1ZSk7XG4gIH1cblxuICBwcm9jZXNzX3V0ZjE2KHZhbHVlKSB7XG4gICAgcmV0dXJuIEJpdFN0cmluZy50b1VURjE2QXJyYXkodmFsdWUudmFsdWUpO1xuICB9XG5cbiAgcHJvY2Vzc191dGYzMih2YWx1ZSkge1xuICAgIHJldHVybiBCaXRTdHJpbmcudG9VVEYzMkFycmF5KHZhbHVlLnZhbHVlKTtcbiAgfVxuXG4gIHByb2Nlc3Nfc2lnbmVkKHZhbHVlKSB7XG4gICAgcmV0dXJuIG5ldyBVaW50OEFycmF5KFt2YWx1ZV0pWzBdO1xuICB9XG5cbiAgcHJvY2Vzc191bnNpZ25lZCh2YWx1ZSkge1xuICAgIHJldHVybiB2YWx1ZTtcbiAgfVxuXG4gIHByb2Nlc3NfbmF0aXZlKHZhbHVlKSB7XG4gICAgcmV0dXJuIHZhbHVlO1xuICB9XG5cbiAgcHJvY2Vzc19iaWcodmFsdWUpIHtcbiAgICByZXR1cm4gdmFsdWU7XG4gIH1cblxuICBwcm9jZXNzX2xpdHRsZSh2YWx1ZSkge1xuICAgIHJldHVybiB2YWx1ZS5yZXZlcnNlKCk7XG4gIH1cblxuICBwcm9jZXNzX3NpemUodmFsdWUpIHtcbiAgICByZXR1cm4gdmFsdWU7XG4gIH1cblxuICBwcm9jZXNzX3VuaXQodmFsdWUpIHtcbiAgICByZXR1cm4gdmFsdWU7XG4gIH1cblxuICBzdGF0aWMgaW50ZWdlcih2YWx1ZSkge1xuICAgIHJldHVybiBCaXRTdHJpbmcud3JhcCh2YWx1ZSwgeyBcInR5cGVcIjogXCJpbnRlZ2VyXCIsIFwidW5pdFwiOiAxLCBcInNpemVcIjogOCB9KTtcbiAgfVxuXG4gIHN0YXRpYyBmbG9hdCh2YWx1ZSkge1xuICAgIHJldHVybiBCaXRTdHJpbmcud3JhcCh2YWx1ZSwgeyBcInR5cGVcIjogXCJmbG9hdFwiLCBcInVuaXRcIjogMSwgXCJzaXplXCI6IDY0IH0pO1xuICB9XG5cbiAgc3RhdGljIGJpdHN0cmluZyh2YWx1ZSkge1xuICAgIHJldHVybiBCaXRTdHJpbmcud3JhcCh2YWx1ZSwgeyBcInR5cGVcIjogXCJiaXRzdHJpbmdcIiwgXCJ1bml0XCI6IDEsIFwic2l6ZVwiOiB2YWx1ZS5sZW5ndGggfSk7XG4gIH1cblxuICBzdGF0aWMgYml0cyh2YWx1ZSkge1xuICAgIHJldHVybiBCaXRTdHJpbmcuYml0c3RyaW5nKHZhbHVlKTtcbiAgfVxuXG4gIHN0YXRpYyBiaW5hcnkodmFsdWUpIHtcbiAgICByZXR1cm4gQml0U3RyaW5nLndyYXAodmFsdWUsIHsgXCJ0eXBlXCI6IFwiYmluYXJ5XCIsIFwidW5pdFwiOiA4LCBcInNpemVcIjogdmFsdWUubGVuZ3RoIH0pO1xuICB9XG5cbiAgc3RhdGljIGJ5dGVzKHZhbHVlKSB7XG4gICAgcmV0dXJuIEJpdFN0cmluZy5iaW5hcnkodmFsdWUpO1xuICB9XG5cbiAgc3RhdGljIHV0ZjgodmFsdWUpIHtcbiAgICByZXR1cm4gQml0U3RyaW5nLndyYXAodmFsdWUsIHsgXCJ0eXBlXCI6IFwidXRmOFwiIH0pO1xuICB9XG5cbiAgc3RhdGljIHV0ZjE2KHZhbHVlKSB7XG4gICAgcmV0dXJuIEJpdFN0cmluZy53cmFwKHZhbHVlLCB7IFwidHlwZVwiOiBcInV0ZjE2XCIgfSk7XG4gIH1cblxuICBzdGF0aWMgdXRmMzIodmFsdWUpIHtcbiAgICByZXR1cm4gQml0U3RyaW5nLndyYXAodmFsdWUsIHsgXCJ0eXBlXCI6IFwidXRmMzJcIiB9KTtcbiAgfVxuXG4gIHN0YXRpYyBzaWduZWQodmFsdWUpIHtcbiAgICByZXR1cm4gQml0U3RyaW5nLndyYXAodmFsdWUsIHt9LCBcInNpZ25lZFwiKTtcbiAgfVxuXG4gIHN0YXRpYyB1bnNpZ25lZCh2YWx1ZSkge1xuICAgIHJldHVybiBCaXRTdHJpbmcud3JhcCh2YWx1ZSwge30sIFwidW5zaWduZWRcIik7XG4gIH1cblxuICBzdGF0aWMgbmF0aXZlKHZhbHVlKSB7XG4gICAgcmV0dXJuIEJpdFN0cmluZy53cmFwKHZhbHVlLCB7fSwgXCJuYXRpdmVcIik7XG4gIH1cblxuICBzdGF0aWMgYmlnKHZhbHVlKSB7XG4gICAgcmV0dXJuIEJpdFN0cmluZy53cmFwKHZhbHVlLCB7fSwgXCJiaWdcIik7XG4gIH1cblxuICBzdGF0aWMgbGl0dGxlKHZhbHVlKSB7XG4gICAgcmV0dXJuIEJpdFN0cmluZy53cmFwKHZhbHVlLCB7fSwgXCJsaXR0bGVcIik7XG4gIH1cblxuICBzdGF0aWMgc2l6ZSh2YWx1ZSwgY291bnQpIHtcbiAgICByZXR1cm4gQml0U3RyaW5nLndyYXAodmFsdWUsIHsgXCJzaXplXCI6IGNvdW50IH0pO1xuICB9XG5cbiAgc3RhdGljIHVuaXQodmFsdWUsIGNvdW50KSB7XG4gICAgcmV0dXJuIEJpdFN0cmluZy53cmFwKHZhbHVlLCB7IFwidW5pdFwiOiBjb3VudCB9KTtcbiAgfVxuXG4gIHN0YXRpYyB3cmFwKHZhbHVlLCBvcHQsIG5ld19hdHRyaWJ1dGUgPSBudWxsKSB7XG4gICAgbGV0IHRoZV92YWx1ZSA9IHZhbHVlO1xuXG4gICAgaWYgKCEodmFsdWUgaW5zdGFuY2VvZiBPYmplY3QpKSB7XG4gICAgICB0aGVfdmFsdWUgPSB7IFwidmFsdWVcIjogdmFsdWUsIFwiYXR0cmlidXRlc1wiOiBbXSB9O1xuICAgIH1cblxuICAgIHRoZV92YWx1ZSA9IE9iamVjdC5hc3NpZ24odGhlX3ZhbHVlLCBvcHQpO1xuXG4gICAgaWYgKG5ld19hdHRyaWJ1dGUpIHtcbiAgICAgIHRoZV92YWx1ZS5hdHRyaWJ1dGVzLnB1c2gobmV3X2F0dHJpYnV0ZSk7XG4gICAgfVxuXG4gICAgcmV0dXJuIHRoZV92YWx1ZTtcbiAgfVxuXG4gIHN0YXRpYyB0b1VURjhBcnJheShzdHIpIHtcbiAgICB2YXIgdXRmOCA9IFtdO1xuICAgIGZvciAodmFyIGkgPSAwOyBpIDwgc3RyLmxlbmd0aDsgaSsrKSB7XG4gICAgICB2YXIgY2hhcmNvZGUgPSBzdHIuY2hhckNvZGVBdChpKTtcbiAgICAgIGlmIChjaGFyY29kZSA8IDEyOCkge1xuICAgICAgICB1dGY4LnB1c2goY2hhcmNvZGUpO1xuICAgICAgfSBlbHNlIGlmIChjaGFyY29kZSA8IDIwNDgpIHtcbiAgICAgICAgdXRmOC5wdXNoKDE5MiB8IGNoYXJjb2RlID4+IDYsIDEyOCB8IGNoYXJjb2RlICYgNjMpO1xuICAgICAgfSBlbHNlIGlmIChjaGFyY29kZSA8IDU1Mjk2IHx8IGNoYXJjb2RlID49IDU3MzQ0KSB7XG4gICAgICAgIHV0ZjgucHVzaCgyMjQgfCBjaGFyY29kZSA+PiAxMiwgMTI4IHwgY2hhcmNvZGUgPj4gNiAmIDYzLCAxMjggfCBjaGFyY29kZSAmIDYzKTtcbiAgICAgIH1cbiAgICAgIC8vIHN1cnJvZ2F0ZSBwYWlyXG4gICAgICBlbHNlIHtcbiAgICAgICAgaSsrO1xuICAgICAgICAvLyBVVEYtMTYgZW5jb2RlcyAweDEwMDAwLTB4MTBGRkZGIGJ5XG4gICAgICAgIC8vIHN1YnRyYWN0aW5nIDB4MTAwMDAgYW5kIHNwbGl0dGluZyB0aGVcbiAgICAgICAgLy8gMjAgYml0cyBvZiAweDAtMHhGRkZGRiBpbnRvIHR3byBoYWx2ZXNcbiAgICAgICAgY2hhcmNvZGUgPSA2NTUzNiArICgoY2hhcmNvZGUgJiAxMDIzKSA8PCAxMCB8IHN0ci5jaGFyQ29kZUF0KGkpICYgMTAyMyk7XG4gICAgICAgIHV0ZjgucHVzaCgyNDAgfCBjaGFyY29kZSA+PiAxOCwgMTI4IHwgY2hhcmNvZGUgPj4gMTIgJiA2MywgMTI4IHwgY2hhcmNvZGUgPj4gNiAmIDYzLCAxMjggfCBjaGFyY29kZSAmIDYzKTtcbiAgICAgIH1cbiAgICB9XG4gICAgcmV0dXJuIHV0Zjg7XG4gIH1cblxuICBzdGF0aWMgdG9VVEYxNkFycmF5KHN0cikge1xuICAgIHZhciB1dGYxNiA9IFtdO1xuICAgIGZvciAodmFyIGkgPSAwOyBpIDwgc3RyLmxlbmd0aDsgaSsrKSB7XG4gICAgICB2YXIgY29kZVBvaW50ID0gc3RyLmNvZGVQb2ludEF0KGkpO1xuXG4gICAgICBpZiAoY29kZVBvaW50IDw9IDI1NSkge1xuICAgICAgICB1dGYxNi5wdXNoKDApO1xuICAgICAgICB1dGYxNi5wdXNoKGNvZGVQb2ludCk7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICB1dGYxNi5wdXNoKGNvZGVQb2ludCA+PiA4ICYgMjU1KTtcbiAgICAgICAgdXRmMTYucHVzaChjb2RlUG9pbnQgJiAyNTUpO1xuICAgICAgfVxuICAgIH1cbiAgICByZXR1cm4gdXRmMTY7XG4gIH1cblxuICBzdGF0aWMgdG9VVEYzMkFycmF5KHN0cikge1xuICAgIHZhciB1dGYzMiA9IFtdO1xuICAgIGZvciAodmFyIGkgPSAwOyBpIDwgc3RyLmxlbmd0aDsgaSsrKSB7XG4gICAgICB2YXIgY29kZVBvaW50ID0gc3RyLmNvZGVQb2ludEF0KGkpO1xuXG4gICAgICBpZiAoY29kZVBvaW50IDw9IDI1NSkge1xuICAgICAgICB1dGYzMi5wdXNoKDApO1xuICAgICAgICB1dGYzMi5wdXNoKDApO1xuICAgICAgICB1dGYzMi5wdXNoKDApO1xuICAgICAgICB1dGYzMi5wdXNoKGNvZGVQb2ludCk7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICB1dGYzMi5wdXNoKDApO1xuICAgICAgICB1dGYzMi5wdXNoKDApO1xuICAgICAgICB1dGYzMi5wdXNoKGNvZGVQb2ludCA+PiA4ICYgMjU1KTtcbiAgICAgICAgdXRmMzIucHVzaChjb2RlUG9pbnQgJiAyNTUpO1xuICAgICAgfVxuICAgIH1cbiAgICByZXR1cm4gdXRmMzI7XG4gIH1cblxuICAvL2h0dHA6Ly9zdGFja292ZXJmbG93LmNvbS9xdWVzdGlvbnMvMjAwMzQ5My9qYXZhc2NyaXB0LWZsb2F0LWZyb20tdG8tYml0c1xuICBzdGF0aWMgZmxvYXQzMlRvQnl0ZXMoZikge1xuICAgIHZhciBieXRlcyA9IFtdO1xuXG4gICAgdmFyIGJ1ZiA9IG5ldyBBcnJheUJ1ZmZlcig0KTtcbiAgICBuZXcgRmxvYXQzMkFycmF5KGJ1ZilbMF0gPSBmO1xuXG4gICAgbGV0IGludFZlcnNpb24gPSBuZXcgVWludDMyQXJyYXkoYnVmKVswXTtcblxuICAgIGJ5dGVzLnB1c2goaW50VmVyc2lvbiA+PiAyNCAmIDI1NSk7XG4gICAgYnl0ZXMucHVzaChpbnRWZXJzaW9uID4+IDE2ICYgMjU1KTtcbiAgICBieXRlcy5wdXNoKGludFZlcnNpb24gPj4gOCAmIDI1NSk7XG4gICAgYnl0ZXMucHVzaChpbnRWZXJzaW9uICYgMjU1KTtcblxuICAgIHJldHVybiBieXRlcztcbiAgfVxuXG4gIHN0YXRpYyBmbG9hdDY0VG9CeXRlcyhmKSB7XG4gICAgdmFyIGJ5dGVzID0gW107XG5cbiAgICB2YXIgYnVmID0gbmV3IEFycmF5QnVmZmVyKDgpO1xuICAgIG5ldyBGbG9hdDY0QXJyYXkoYnVmKVswXSA9IGY7XG5cbiAgICB2YXIgaW50VmVyc2lvbjEgPSBuZXcgVWludDMyQXJyYXkoYnVmKVswXTtcbiAgICB2YXIgaW50VmVyc2lvbjIgPSBuZXcgVWludDMyQXJyYXkoYnVmKVsxXTtcblxuICAgIGJ5dGVzLnB1c2goaW50VmVyc2lvbjIgPj4gMjQgJiAyNTUpO1xuICAgIGJ5dGVzLnB1c2goaW50VmVyc2lvbjIgPj4gMTYgJiAyNTUpO1xuICAgIGJ5dGVzLnB1c2goaW50VmVyc2lvbjIgPj4gOCAmIDI1NSk7XG4gICAgYnl0ZXMucHVzaChpbnRWZXJzaW9uMiAmIDI1NSk7XG5cbiAgICBieXRlcy5wdXNoKGludFZlcnNpb24xID4+IDI0ICYgMjU1KTtcbiAgICBieXRlcy5wdXNoKGludFZlcnNpb24xID4+IDE2ICYgMjU1KTtcbiAgICBieXRlcy5wdXNoKGludFZlcnNpb24xID4+IDggJiAyNTUpO1xuICAgIGJ5dGVzLnB1c2goaW50VmVyc2lvbjEgJiAyNTUpO1xuXG4gICAgcmV0dXJuIGJ5dGVzO1xuICB9XG59XG5cbi8qIEBmbG93ICovXG5cbmNsYXNzIFZhcmlhYmxlIHtcblxuICBjb25zdHJ1Y3RvcihuYW1lID0gbnVsbCkge1xuICAgIHRoaXMubmFtZSA9IG5hbWU7XG4gIH1cbn1cblxuY2xhc3MgV2lsZGNhcmQge1xuICBjb25zdHJ1Y3RvcigpIHt9XG59XG5cbmNsYXNzIFN0YXJ0c1dpdGgge1xuXG4gIGNvbnN0cnVjdG9yKHByZWZpeCkge1xuICAgIHRoaXMucHJlZml4ID0gcHJlZml4O1xuICB9XG59XG5cbmNsYXNzIENhcHR1cmUge1xuXG4gIGNvbnN0cnVjdG9yKHZhbHVlKSB7XG4gICAgdGhpcy52YWx1ZSA9IHZhbHVlO1xuICB9XG59XG5cbmNsYXNzIEhlYWRUYWlsIHtcbiAgY29uc3RydWN0b3IoKSB7fVxufVxuXG5jbGFzcyBUeXBlIHtcblxuICBjb25zdHJ1Y3Rvcih0eXBlLCBvYmpQYXR0ZXJuID0ge30pIHtcbiAgICB0aGlzLnR5cGUgPSB0eXBlO1xuICAgIHRoaXMub2JqUGF0dGVybiA9IG9ialBhdHRlcm47XG4gIH1cbn1cblxuY2xhc3MgQm91bmQge1xuXG4gIGNvbnN0cnVjdG9yKHZhbHVlKSB7XG4gICAgdGhpcy52YWx1ZSA9IHZhbHVlO1xuICB9XG59XG5cbmZ1bmN0aW9uIHZhcmlhYmxlKG5hbWUgPSBudWxsKSB7XG4gIHJldHVybiBuZXcgVmFyaWFibGUobmFtZSk7XG59XG5cbmZ1bmN0aW9uIHdpbGRjYXJkKCkge1xuICByZXR1cm4gbmV3IFdpbGRjYXJkKCk7XG59XG5cbmZ1bmN0aW9uIHN0YXJ0c1dpdGgocHJlZml4KSB7XG4gIHJldHVybiBuZXcgU3RhcnRzV2l0aChwcmVmaXgpO1xufVxuXG5mdW5jdGlvbiBjYXB0dXJlKHZhbHVlKSB7XG4gIHJldHVybiBuZXcgQ2FwdHVyZSh2YWx1ZSk7XG59XG5cbmZ1bmN0aW9uIGhlYWRUYWlsKCkge1xuICByZXR1cm4gbmV3IEhlYWRUYWlsKCk7XG59XG5cbmZ1bmN0aW9uIHR5cGUodHlwZSwgb2JqUGF0dGVybiA9IHt9KSB7XG4gIHJldHVybiBuZXcgVHlwZSh0eXBlLCBvYmpQYXR0ZXJuKTtcbn1cblxuZnVuY3Rpb24gYm91bmQodmFsdWUpIHtcbiAgcmV0dXJuIG5ldyBCb3VuZCh2YWx1ZSk7XG59XG5cbmZ1bmN0aW9uIGlzX251bWJlciQyKHZhbHVlKSB7XG4gIHJldHVybiB0eXBlb2YgdmFsdWUgPT09ICdudW1iZXInO1xufVxuXG5mdW5jdGlvbiBpc19zdHJpbmcodmFsdWUpIHtcbiAgcmV0dXJuIHR5cGVvZiB2YWx1ZSA9PT0gJ3N0cmluZyc7XG59XG5cbmZ1bmN0aW9uIGlzX2Jvb2xlYW4kMih2YWx1ZSkge1xuICByZXR1cm4gdHlwZW9mIHZhbHVlID09PSAnYm9vbGVhbic7XG59XG5cbmZ1bmN0aW9uIGlzX3N5bWJvbCh2YWx1ZSkge1xuICByZXR1cm4gdHlwZW9mIHZhbHVlID09PSAnc3ltYm9sJztcbn1cblxuZnVuY3Rpb24gaXNfbnVsbCh2YWx1ZSkge1xuICByZXR1cm4gdmFsdWUgPT09IG51bGw7XG59XG5cbmZ1bmN0aW9uIGlzX3VuZGVmaW5lZCh2YWx1ZSkge1xuICByZXR1cm4gdHlwZW9mIHZhbHVlID09PSAndW5kZWZpbmVkJztcbn1cblxuZnVuY3Rpb24gaXNfZnVuY3Rpb24kMih2YWx1ZSkge1xuICByZXR1cm4gT2JqZWN0LnByb3RvdHlwZS50b1N0cmluZy5jYWxsKHZhbHVlKSA9PSAnW29iamVjdCBGdW5jdGlvbl0nO1xufVxuXG5mdW5jdGlvbiBpc192YXJpYWJsZSh2YWx1ZSkge1xuICByZXR1cm4gdmFsdWUgaW5zdGFuY2VvZiBWYXJpYWJsZTtcbn1cblxuZnVuY3Rpb24gaXNfd2lsZGNhcmQodmFsdWUpIHtcbiAgcmV0dXJuIHZhbHVlIGluc3RhbmNlb2YgV2lsZGNhcmQ7XG59XG5cbmZ1bmN0aW9uIGlzX2hlYWRUYWlsKHZhbHVlKSB7XG4gIHJldHVybiB2YWx1ZSBpbnN0YW5jZW9mIEhlYWRUYWlsO1xufVxuXG5mdW5jdGlvbiBpc19jYXB0dXJlKHZhbHVlKSB7XG4gIHJldHVybiB2YWx1ZSBpbnN0YW5jZW9mIENhcHR1cmU7XG59XG5cbmZ1bmN0aW9uIGlzX3R5cGUodmFsdWUpIHtcbiAgcmV0dXJuIHZhbHVlIGluc3RhbmNlb2YgVHlwZTtcbn1cblxuZnVuY3Rpb24gaXNfc3RhcnRzV2l0aCh2YWx1ZSkge1xuICByZXR1cm4gdmFsdWUgaW5zdGFuY2VvZiBTdGFydHNXaXRoO1xufVxuXG5mdW5jdGlvbiBpc19ib3VuZCh2YWx1ZSkge1xuICByZXR1cm4gdmFsdWUgaW5zdGFuY2VvZiBCb3VuZDtcbn1cblxuZnVuY3Rpb24gaXNfb2JqZWN0KHZhbHVlKSB7XG4gIHJldHVybiB0eXBlb2YgdmFsdWUgPT09ICdvYmplY3QnO1xufVxuXG5mdW5jdGlvbiBpc19hcnJheSh2YWx1ZSkge1xuICByZXR1cm4gQXJyYXkuaXNBcnJheSh2YWx1ZSk7XG59XG5cbnZhciBDaGVja3MgPSB7XG4gIGlzX251bWJlcjogaXNfbnVtYmVyJDIsXG4gIGlzX3N0cmluZyxcbiAgaXNfYm9vbGVhbjogaXNfYm9vbGVhbiQyLFxuICBpc19zeW1ib2wsXG4gIGlzX251bGwsXG4gIGlzX3VuZGVmaW5lZCxcbiAgaXNfZnVuY3Rpb246IGlzX2Z1bmN0aW9uJDIsXG4gIGlzX3ZhcmlhYmxlLFxuICBpc193aWxkY2FyZCxcbiAgaXNfaGVhZFRhaWwsXG4gIGlzX2NhcHR1cmUsXG4gIGlzX3R5cGUsXG4gIGlzX3N0YXJ0c1dpdGgsXG4gIGlzX2JvdW5kLFxuICBpc19vYmplY3QsXG4gIGlzX2FycmF5XG59O1xuXG5mdW5jdGlvbiByZXNvbHZlU3ltYm9sKHBhdHRlcm4pIHtcbiAgcmV0dXJuIGZ1bmN0aW9uICh2YWx1ZSkge1xuICAgIHJldHVybiBDaGVja3MuaXNfc3ltYm9sKHZhbHVlKSAmJiB2YWx1ZSA9PT0gcGF0dGVybjtcbiAgfTtcbn1cblxuZnVuY3Rpb24gcmVzb2x2ZVN0cmluZyhwYXR0ZXJuKSB7XG4gIHJldHVybiBmdW5jdGlvbiAodmFsdWUpIHtcbiAgICByZXR1cm4gQ2hlY2tzLmlzX3N0cmluZyh2YWx1ZSkgJiYgdmFsdWUgPT09IHBhdHRlcm47XG4gIH07XG59XG5cbmZ1bmN0aW9uIHJlc29sdmVOdW1iZXIocGF0dGVybikge1xuICByZXR1cm4gZnVuY3Rpb24gKHZhbHVlKSB7XG4gICAgcmV0dXJuIENoZWNrcy5pc19udW1iZXIodmFsdWUpICYmIHZhbHVlID09PSBwYXR0ZXJuO1xuICB9O1xufVxuXG5mdW5jdGlvbiByZXNvbHZlQm9vbGVhbihwYXR0ZXJuKSB7XG4gIHJldHVybiBmdW5jdGlvbiAodmFsdWUpIHtcbiAgICByZXR1cm4gQ2hlY2tzLmlzX2Jvb2xlYW4odmFsdWUpICYmIHZhbHVlID09PSBwYXR0ZXJuO1xuICB9O1xufVxuXG5mdW5jdGlvbiByZXNvbHZlRnVuY3Rpb24ocGF0dGVybikge1xuICByZXR1cm4gZnVuY3Rpb24gKHZhbHVlKSB7XG4gICAgcmV0dXJuIENoZWNrcy5pc19mdW5jdGlvbih2YWx1ZSkgJiYgdmFsdWUgPT09IHBhdHRlcm47XG4gIH07XG59XG5cbmZ1bmN0aW9uIHJlc29sdmVOdWxsKHBhdHRlcm4pIHtcbiAgcmV0dXJuIGZ1bmN0aW9uICh2YWx1ZSkge1xuICAgIHJldHVybiBDaGVja3MuaXNfbnVsbCh2YWx1ZSk7XG4gIH07XG59XG5cbmZ1bmN0aW9uIHJlc29sdmVCb3VuZChwYXR0ZXJuKSB7XG4gIHJldHVybiBmdW5jdGlvbiAodmFsdWUsIGFyZ3MpIHtcbiAgICBpZiAodHlwZW9mIHZhbHVlID09PSB0eXBlb2YgcGF0dGVybi52YWx1ZSAmJiB2YWx1ZSA9PT0gcGF0dGVybi52YWx1ZSkge1xuICAgICAgYXJncy5wdXNoKHZhbHVlKTtcbiAgICAgIHJldHVybiB0cnVlO1xuICAgIH1cblxuICAgIHJldHVybiBmYWxzZTtcbiAgfTtcbn1cblxuZnVuY3Rpb24gcmVzb2x2ZVdpbGRjYXJkKCkge1xuICByZXR1cm4gZnVuY3Rpb24gKCkge1xuICAgIHJldHVybiB0cnVlO1xuICB9O1xufVxuXG5mdW5jdGlvbiByZXNvbHZlVmFyaWFibGUoKSB7XG4gIHJldHVybiBmdW5jdGlvbiAodmFsdWUsIGFyZ3MpIHtcbiAgICBhcmdzLnB1c2godmFsdWUpO1xuICAgIHJldHVybiB0cnVlO1xuICB9O1xufVxuXG5mdW5jdGlvbiByZXNvbHZlSGVhZFRhaWwoKSB7XG4gIHJldHVybiBmdW5jdGlvbiAodmFsdWUsIGFyZ3MpIHtcbiAgICBpZiAoIUNoZWNrcy5pc19hcnJheSh2YWx1ZSkgfHwgdmFsdWUubGVuZ3RoIDwgMikge1xuICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH1cblxuICAgIGNvbnN0IGhlYWQgPSB2YWx1ZVswXTtcbiAgICBjb25zdCB0YWlsID0gdmFsdWUuc2xpY2UoMSk7XG5cbiAgICBhcmdzLnB1c2goaGVhZCk7XG4gICAgYXJncy5wdXNoKHRhaWwpO1xuXG4gICAgcmV0dXJuIHRydWU7XG4gIH07XG59XG5cbmZ1bmN0aW9uIHJlc29sdmVDYXB0dXJlKHBhdHRlcm4pIHtcbiAgY29uc3QgbWF0Y2hlcyA9IGJ1aWxkTWF0Y2gocGF0dGVybi52YWx1ZSk7XG5cbiAgcmV0dXJuIGZ1bmN0aW9uICh2YWx1ZSwgYXJncykge1xuICAgIGlmIChtYXRjaGVzKHZhbHVlLCBhcmdzKSkge1xuICAgICAgYXJncy5wdXNoKHZhbHVlKTtcbiAgICAgIHJldHVybiB0cnVlO1xuICAgIH1cblxuICAgIHJldHVybiBmYWxzZTtcbiAgfTtcbn1cblxuZnVuY3Rpb24gcmVzb2x2ZVN0YXJ0c1dpdGgocGF0dGVybikge1xuICBjb25zdCBwcmVmaXggPSBwYXR0ZXJuLnByZWZpeDtcblxuICByZXR1cm4gZnVuY3Rpb24gKHZhbHVlLCBhcmdzKSB7XG4gICAgaWYgKENoZWNrcy5pc19zdHJpbmcodmFsdWUpICYmIHZhbHVlLnN0YXJ0c1dpdGgocHJlZml4KSkge1xuICAgICAgYXJncy5wdXNoKHZhbHVlLnN1YnN0cmluZyhwcmVmaXgubGVuZ3RoKSk7XG4gICAgICByZXR1cm4gdHJ1ZTtcbiAgICB9XG5cbiAgICByZXR1cm4gZmFsc2U7XG4gIH07XG59XG5cbmZ1bmN0aW9uIHJlc29sdmVUeXBlKHBhdHRlcm4pIHtcbiAgcmV0dXJuIGZ1bmN0aW9uICh2YWx1ZSwgYXJncykge1xuICAgIGlmICh2YWx1ZSBpbnN0YW5jZW9mIHBhdHRlcm4udHlwZSkge1xuICAgICAgY29uc3QgbWF0Y2hlcyA9IGJ1aWxkTWF0Y2gocGF0dGVybi5vYmpQYXR0ZXJuKTtcbiAgICAgIHJldHVybiBtYXRjaGVzKHZhbHVlLCBhcmdzKSAmJiBhcmdzLnB1c2godmFsdWUpID4gMDtcbiAgICB9XG5cbiAgICByZXR1cm4gZmFsc2U7XG4gIH07XG59XG5cbmZ1bmN0aW9uIHJlc29sdmVBcnJheShwYXR0ZXJuKSB7XG4gIGNvbnN0IG1hdGNoZXMgPSBwYXR0ZXJuLm1hcCh4ID0+IGJ1aWxkTWF0Y2goeCkpO1xuXG4gIHJldHVybiBmdW5jdGlvbiAodmFsdWUsIGFyZ3MpIHtcbiAgICBpZiAoIUNoZWNrcy5pc19hcnJheSh2YWx1ZSkgfHwgdmFsdWUubGVuZ3RoICE9IHBhdHRlcm4ubGVuZ3RoKSB7XG4gICAgICByZXR1cm4gZmFsc2U7XG4gICAgfVxuXG4gICAgcmV0dXJuIHZhbHVlLmV2ZXJ5KGZ1bmN0aW9uICh2LCBpKSB7XG4gICAgICByZXR1cm4gbWF0Y2hlc1tpXSh2YWx1ZVtpXSwgYXJncyk7XG4gICAgfSk7XG4gIH07XG59XG5cbmZ1bmN0aW9uIHJlc29sdmVPYmplY3QocGF0dGVybikge1xuICBsZXQgbWF0Y2hlcyA9IHt9O1xuXG4gIGZvciAobGV0IGtleSBvZiBPYmplY3Qua2V5cyhwYXR0ZXJuKS5jb25jYXQoT2JqZWN0LmdldE93blByb3BlcnR5U3ltYm9scyhwYXR0ZXJuKSkpIHtcbiAgICBtYXRjaGVzW2tleV0gPSBidWlsZE1hdGNoKHBhdHRlcm5ba2V5XSk7XG4gIH1cblxuICByZXR1cm4gZnVuY3Rpb24gKHZhbHVlLCBhcmdzKSB7XG4gICAgaWYgKCFDaGVja3MuaXNfb2JqZWN0KHZhbHVlKSB8fCBwYXR0ZXJuLmxlbmd0aCA+IHZhbHVlLmxlbmd0aCkge1xuICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH1cblxuICAgIGZvciAobGV0IGtleSBvZiBPYmplY3Qua2V5cyhwYXR0ZXJuKS5jb25jYXQoT2JqZWN0LmdldE93blByb3BlcnR5U3ltYm9scyhwYXR0ZXJuKSkpIHtcbiAgICAgIGlmICghKGtleSBpbiB2YWx1ZSkgfHwgIW1hdGNoZXNba2V5XSh2YWx1ZVtrZXldLCBhcmdzKSkge1xuICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICB9XG4gICAgfVxuXG4gICAgcmV0dXJuIHRydWU7XG4gIH07XG59XG5cbmZ1bmN0aW9uIHJlc29sdmVOb01hdGNoKCkge1xuICByZXR1cm4gZnVuY3Rpb24gKCkge1xuICAgIHJldHVybiBmYWxzZTtcbiAgfTtcbn1cblxudmFyIFJlc29sdmVycyA9IHtcbiAgcmVzb2x2ZUJvdW5kLFxuICByZXNvbHZlV2lsZGNhcmQsXG4gIHJlc29sdmVWYXJpYWJsZSxcbiAgcmVzb2x2ZUhlYWRUYWlsLFxuICByZXNvbHZlQ2FwdHVyZSxcbiAgcmVzb2x2ZVN0YXJ0c1dpdGgsXG4gIHJlc29sdmVUeXBlLFxuICByZXNvbHZlQXJyYXksXG4gIHJlc29sdmVPYmplY3QsXG4gIHJlc29sdmVOb01hdGNoLFxuICByZXNvbHZlU3ltYm9sLFxuICByZXNvbHZlU3RyaW5nLFxuICByZXNvbHZlTnVtYmVyLFxuICByZXNvbHZlQm9vbGVhbixcbiAgcmVzb2x2ZUZ1bmN0aW9uLFxuICByZXNvbHZlTnVsbFxufTtcblxuZnVuY3Rpb24gYnVpbGRNYXRjaChwYXR0ZXJuKSB7XG5cbiAgaWYgKENoZWNrcy5pc192YXJpYWJsZShwYXR0ZXJuKSkge1xuICAgIHJldHVybiBSZXNvbHZlcnMucmVzb2x2ZVZhcmlhYmxlKHBhdHRlcm4pO1xuICB9XG5cbiAgaWYgKENoZWNrcy5pc193aWxkY2FyZChwYXR0ZXJuKSkge1xuICAgIHJldHVybiBSZXNvbHZlcnMucmVzb2x2ZVdpbGRjYXJkKHBhdHRlcm4pO1xuICB9XG5cbiAgaWYgKENoZWNrcy5pc191bmRlZmluZWQocGF0dGVybikpIHtcbiAgICByZXR1cm4gUmVzb2x2ZXJzLnJlc29sdmVXaWxkY2FyZChwYXR0ZXJuKTtcbiAgfVxuXG4gIGlmIChDaGVja3MuaXNfaGVhZFRhaWwocGF0dGVybikpIHtcbiAgICByZXR1cm4gUmVzb2x2ZXJzLnJlc29sdmVIZWFkVGFpbChwYXR0ZXJuKTtcbiAgfVxuXG4gIGlmIChDaGVja3MuaXNfc3RhcnRzV2l0aChwYXR0ZXJuKSkge1xuICAgIHJldHVybiBSZXNvbHZlcnMucmVzb2x2ZVN0YXJ0c1dpdGgocGF0dGVybik7XG4gIH1cblxuICBpZiAoQ2hlY2tzLmlzX2NhcHR1cmUocGF0dGVybikpIHtcbiAgICByZXR1cm4gUmVzb2x2ZXJzLnJlc29sdmVDYXB0dXJlKHBhdHRlcm4pO1xuICB9XG5cbiAgaWYgKENoZWNrcy5pc19ib3VuZChwYXR0ZXJuKSkge1xuICAgIHJldHVybiBSZXNvbHZlcnMucmVzb2x2ZUJvdW5kKHBhdHRlcm4pO1xuICB9XG5cbiAgaWYgKENoZWNrcy5pc190eXBlKHBhdHRlcm4pKSB7XG4gICAgcmV0dXJuIFJlc29sdmVycy5yZXNvbHZlVHlwZShwYXR0ZXJuKTtcbiAgfVxuXG4gIGlmIChDaGVja3MuaXNfYXJyYXkocGF0dGVybikpIHtcbiAgICByZXR1cm4gUmVzb2x2ZXJzLnJlc29sdmVBcnJheShwYXR0ZXJuKTtcbiAgfVxuXG4gIGlmIChDaGVja3MuaXNfbnVtYmVyKHBhdHRlcm4pKSB7XG4gICAgcmV0dXJuIFJlc29sdmVycy5yZXNvbHZlTnVtYmVyKHBhdHRlcm4pO1xuICB9XG5cbiAgaWYgKENoZWNrcy5pc19zdHJpbmcocGF0dGVybikpIHtcbiAgICByZXR1cm4gUmVzb2x2ZXJzLnJlc29sdmVTdHJpbmcocGF0dGVybik7XG4gIH1cblxuICBpZiAoQ2hlY2tzLmlzX2Jvb2xlYW4ocGF0dGVybikpIHtcbiAgICByZXR1cm4gUmVzb2x2ZXJzLnJlc29sdmVCb29sZWFuKHBhdHRlcm4pO1xuICB9XG5cbiAgaWYgKENoZWNrcy5pc19zeW1ib2wocGF0dGVybikpIHtcbiAgICByZXR1cm4gUmVzb2x2ZXJzLnJlc29sdmVTeW1ib2wocGF0dGVybik7XG4gIH1cblxuICBpZiAoQ2hlY2tzLmlzX251bGwocGF0dGVybikpIHtcbiAgICByZXR1cm4gUmVzb2x2ZXJzLnJlc29sdmVOdWxsKHBhdHRlcm4pO1xuICB9XG5cbiAgaWYgKENoZWNrcy5pc19vYmplY3QocGF0dGVybikpIHtcbiAgICByZXR1cm4gUmVzb2x2ZXJzLnJlc29sdmVPYmplY3QocGF0dGVybik7XG4gIH1cblxuICByZXR1cm4gUmVzb2x2ZXJzLnJlc29sdmVOb01hdGNoKCk7XG59XG5cbmNsYXNzIE1hdGNoRXJyb3IgZXh0ZW5kcyBFcnJvciB7XG4gIGNvbnN0cnVjdG9yKGFyZykge1xuICAgIHN1cGVyKCk7XG5cbiAgICBpZiAodHlwZW9mIGFyZyA9PT0gJ3N5bWJvbCcpIHtcbiAgICAgIHRoaXMubWVzc2FnZSA9ICdObyBtYXRjaCBmb3I6ICcgKyBhcmcudG9TdHJpbmcoKTtcbiAgICB9IGVsc2UgaWYgKEFycmF5LmlzQXJyYXkoYXJnKSkge1xuICAgICAgbGV0IG1hcHBlZFZhbHVlcyA9IGFyZy5tYXAoeCA9PiB4LnRvU3RyaW5nKCkpO1xuICAgICAgdGhpcy5tZXNzYWdlID0gJ05vIG1hdGNoIGZvcjogJyArIG1hcHBlZFZhbHVlcztcbiAgICB9IGVsc2Uge1xuICAgICAgdGhpcy5tZXNzYWdlID0gJ05vIG1hdGNoIGZvcjogJyArIGFyZztcbiAgICB9XG5cbiAgICB0aGlzLnN0YWNrID0gbmV3IEVycm9yKCkuc3RhY2s7XG4gICAgdGhpcy5uYW1lID0gdGhpcy5jb25zdHJ1Y3Rvci5uYW1lO1xuICB9XG59XG5cbmNsYXNzIENhc2Uge1xuXG4gIGNvbnN0cnVjdG9yKHBhdHRlcm4sIGZuLCBndWFyZCA9ICgpID0+IHRydWUpIHtcbiAgICB0aGlzLnBhdHRlcm4gPSBidWlsZE1hdGNoKHBhdHRlcm4pO1xuICAgIHRoaXMuZm4gPSBmbjtcbiAgICB0aGlzLmd1YXJkID0gZ3VhcmQ7XG4gIH1cbn1cblxuZnVuY3Rpb24gbWFrZV9jYXNlKHBhdHRlcm4sIGZuLCBndWFyZCA9ICgpID0+IHRydWUpIHtcbiAgcmV0dXJuIG5ldyBDYXNlKHBhdHRlcm4sIGZuLCBndWFyZCk7XG59XG5cbmZ1bmN0aW9uIGRlZm1hdGNoKC4uLmNhc2VzKSB7XG4gIHJldHVybiBmdW5jdGlvbiAoLi4uYXJncykge1xuICAgIGZvciAobGV0IHByb2Nlc3NlZENhc2Ugb2YgY2FzZXMpIHtcbiAgICAgIGxldCByZXN1bHQgPSBbXTtcbiAgICAgIGlmIChwcm9jZXNzZWRDYXNlLnBhdHRlcm4oYXJncywgcmVzdWx0KSAmJiBwcm9jZXNzZWRDYXNlLmd1YXJkLmFwcGx5KHRoaXMsIHJlc3VsdCkpIHtcbiAgICAgICAgcmV0dXJuIHByb2Nlc3NlZENhc2UuZm4uYXBwbHkodGhpcywgcmVzdWx0KTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICB0aHJvdyBuZXcgTWF0Y2hFcnJvcihhcmdzKTtcbiAgfTtcbn1cblxuZnVuY3Rpb24gbWF0Y2gocGF0dGVybiwgZXhwciwgZ3VhcmQgPSAoKSA9PiB0cnVlKSB7XG4gIGxldCByZXN1bHQgPSBbXTtcbiAgbGV0IHByb2Nlc3NlZFBhdHRlcm4gPSBidWlsZE1hdGNoKHBhdHRlcm4pO1xuICBpZiAocHJvY2Vzc2VkUGF0dGVybihleHByLCByZXN1bHQpICYmIGd1YXJkLmFwcGx5KHRoaXMsIHJlc3VsdCkpIHtcbiAgICByZXR1cm4gcmVzdWx0O1xuICB9IGVsc2Uge1xuICAgIHRocm93IG5ldyBNYXRjaEVycm9yKGV4cHIpO1xuICB9XG59XG5cbmZ1bmN0aW9uIG1hdGNoX25vX3Rocm93KHBhdHRlcm4sIGV4cHIsIGd1YXJkID0gKCkgPT4gdHJ1ZSkge1xuICB0cnkge1xuICAgIHJldHVybiBtYXRjaChwYXR0ZXJuLCBleHByLCBndWFyZCk7XG4gIH0gY2F0Y2ggKGUpIHtcbiAgICBpZiAoZSBpbnN0YW5jZW9mIE1hdGNoRXJyb3IpIHtcbiAgICAgIHJldHVybiBudWxsO1xuICAgIH1cblxuICAgIHRocm93IGU7XG4gIH1cbn1cblxudmFyIFBhdHRlcm5zID0ge1xuICBkZWZtYXRjaCwgbWF0Y2gsIE1hdGNoRXJyb3IsIG1hdGNoX25vX3Rocm93LFxuICB2YXJpYWJsZSwgd2lsZGNhcmQsIHN0YXJ0c1dpdGgsXG4gIGNhcHR1cmUsIGhlYWRUYWlsLCB0eXBlLCBib3VuZCwgQ2FzZSwgbWFrZV9jYXNlXG59O1xuXG5mdW5jdGlvbiBjYWxsX3Byb3BlcnR5KGl0ZW0sIHByb3BlcnR5KSB7XG4gIGlmIChwcm9wZXJ0eSBpbiBpdGVtKSB7XG4gICAgaXRlbVtwcm9wZXJ0eV07XG4gICAgaWYgKGl0ZW1bcHJvcGVydHldIGluc3RhbmNlb2YgRnVuY3Rpb24pIHtcbiAgICAgIHJldHVybiBpdGVtW3Byb3BlcnR5XSgpO1xuICAgIH0gZWxzZSB7XG4gICAgICByZXR1cm4gaXRlbVtwcm9wZXJ0eV07XG4gICAgfVxuICB9IGVsc2UgaWYgKFN5bWJvbC5mb3IocHJvcGVydHkpIGluIGl0ZW0pIHtcbiAgICBsZXQgcHJvcCA9IFN5bWJvbC5mb3IocHJvcGVydHkpO1xuICAgIGlmIChpdGVtW3Byb3BdIGluc3RhbmNlb2YgRnVuY3Rpb24pIHtcbiAgICAgIHJldHVybiBpdGVtW3Byb3BdKCk7XG4gICAgfSBlbHNlIHtcbiAgICAgIHJldHVybiBpdGVtW3Byb3BdO1xuICAgIH1cbiAgfVxuXG4gIHRocm93IG5ldyBFcnJvcihgUHJvcGVydHkgJHsgcHJvcGVydHkgfSBub3QgZm91bmQgaW4gJHsgaXRlbSB9YCk7XG59XG5cbmZ1bmN0aW9uIGlzX2luc3RhbmNlX29mKHZhbHVlLCB0eXBlKSB7XG4gIHJldHVybiB2YWx1ZSBpbnN0YW5jZW9mIHR5cGU7XG59XG5cbmZ1bmN0aW9uIHNpemUkMih0ZXJtKSB7XG4gIHJldHVybiB0ZXJtLmxlbmd0aDtcbn1cblxuZnVuY3Rpb24gaXNfbmlsJDEoeCkge1xuICByZXR1cm4geCA9PT0gbnVsbDtcbn1cblxuZnVuY3Rpb24gaXNfYXRvbSQxKHgpIHtcbiAgcmV0dXJuIHR5cGVvZiB4ID09PSAnc3ltYm9sJztcbn1cblxuZnVuY3Rpb24gaXNfYmluYXJ5JDEoeCkge1xuICByZXR1cm4gdHlwZW9mIHggPT09ICdzdHJpbmcnIHx8IHggaW5zdGFuY2VvZiBTdHJpbmc7XG59XG5cbmZ1bmN0aW9uIGlzX2Jvb2xlYW4kMSh4KSB7XG4gIHJldHVybiB0eXBlb2YgeCA9PT0gJ2Jvb2xlYW4nIHx8IHggaW5zdGFuY2VvZiBCb29sZWFuO1xufVxuXG5mdW5jdGlvbiBpc19mdW5jdGlvbiQxKHgsIGFyaXR5ID0gLTEpIHtcbiAgcmV0dXJuIHR5cGVvZiB4ID09PSAnZnVuY3Rpb24nIHx8IHggaW5zdGFuY2VvZiBGdW5jdGlvbjtcbn1cblxuZnVuY3Rpb24gaXNfZmxvYXQkMSh4KSB7XG4gIHJldHVybiBpc19udW1iZXIkMSh4KSAmJiAhTnVtYmVyLmlzSW50ZWdlcih4KTtcbn1cblxuZnVuY3Rpb24gaXNfaW50ZWdlciQxKHgpIHtcbiAgcmV0dXJuIE51bWJlci5pc0ludGVnZXIoeCk7XG59XG5cbmZ1bmN0aW9uIGlzX2xpc3QkMSh4KSB7XG4gIHJldHVybiB4IGluc3RhbmNlb2YgQXJyYXk7XG59XG5cbmZ1bmN0aW9uIGlzX21hcCQxKHgpIHtcbiAgcmV0dXJuIHR5cGVvZiB4ID09PSAnb2JqZWN0JyB8fCB4IGluc3RhbmNlb2YgT2JqZWN0O1xufVxuXG5mdW5jdGlvbiBpc19udW1iZXIkMSh4KSB7XG4gIHJldHVybiB0eXBlb2YgeCA9PT0gJ251bWJlcic7XG59XG5cbmZ1bmN0aW9uIGlzX3R1cGxlJDEoeCkge1xuICByZXR1cm4geCBpbnN0YW5jZW9mIFR1cGxlJDE7XG59XG5cbmZ1bmN0aW9uIGlzX3BpZCQxKHgpIHtcbiAgcmV0dXJuIHggaW5zdGFuY2VvZiBQSUQ7XG59XG5cbmZ1bmN0aW9uIGlzX3BvcnQkMSh4KSB7XG4gIHJldHVybiBmYWxzZTtcbn1cblxuZnVuY3Rpb24gaXNfcmVmZXJlbmNlJDEoeCkge1xuICByZXR1cm4gZmFsc2U7XG59XG5cbmZ1bmN0aW9uIGlzX2JpdHN0cmluZyQxKHgpIHtcbiAgcmV0dXJuIGlzX2JpbmFyeSQxKHgpIHx8IHggaW5zdGFuY2VvZiBCaXRTdHJpbmc7XG59XG5cbmZ1bmN0aW9uIGFkZChvbmUsIHR3bykge1xuICByZXR1cm4gb25lICsgdHdvO1xufVxuXG5mdW5jdGlvbiBzdWJ0cmFjdChvbmUsIHR3bykge1xuICByZXR1cm4gb25lICsgdHdvO1xufVxuXG5mdW5jdGlvbiBtdWx0aXBseShvbmUsIHR3bykge1xuICByZXR1cm4gb25lICsgdHdvO1xufVxuXG5mdW5jdGlvbiBkaXZpZGUob25lLCB0d28pIHtcbiAgcmV0dXJuIG9uZSArIHR3bztcbn1cblxuZnVuY3Rpb24gcmVtYWluZGVyKG9uZSwgdHdvKSB7XG4gIHJldHVybiBvbmUgKyB0d287XG59XG5cbmZ1bmN0aW9uIGFwcGx5JDEoLi4uYXJncykge1xuICBpZiAoYXJncy5sZW5ndGggPT09IDIpIHtcbiAgICBhcmdzWzBdLmFwcGx5KG51bGwsIGFyZ3Muc2xpY2UoMSkpO1xuICB9IGVsc2Uge1xuICAgIGFyZ3NbMF1bYXJnc1sxXV0uYXBwbHkobnVsbCwgYXJncy5zbGljZSgyKSk7XG4gIH1cbn1cblxuZnVuY3Rpb24gbmV3X3R1cGxlKC4uLmFyZ3MpIHtcbiAgcmV0dXJuIG5ldyBUdXBsZSQxKC4uLmFyZ3MpO1xufVxuXG5mdW5jdGlvbiBkdXBsaWNhdGUoZGF0YSwgc2l6ZSkge1xuICBsZXQgYXJyYXkgPSBbXTtcblxuICBmb3IgKHZhciBpID0gc2l6ZSAtIDE7IGkgPj0gMDsgaS0tKSB7XG4gICAgYXJyYXkucHVzaChkYXRhKTtcbiAgfVxuXG4gIHJldHVybiBhcnJheTtcbn1cblxuZnVuY3Rpb24gY29udGFpbnMobGVmdCwgcmlnaHQpIHtcbiAgZm9yIChsZXQgeCBvZiByaWdodCkge1xuICAgIGlmIChQYXR0ZXJucy5tYXRjaF9ub190aHJvdyhsZWZ0LCB4KSAhPSBudWxsKSB7XG4gICAgICByZXR1cm4gdHJ1ZTtcbiAgICB9XG4gIH1cblxuICByZXR1cm4gZmFsc2U7XG59XG5cbmZ1bmN0aW9uIHJldmVyc2UobGlzdCkge1xuICByZXR1cm4gbGlzdC5jb25jYXQoW10pLnJldmVyc2UoKTtcbn1cblxuZnVuY3Rpb24gZ2V0X2dsb2JhbCgpIHtcbiAgaWYgKHR5cGVvZiBzZWxmICE9PSAndW5kZWZpbmVkJykge1xuICAgIHJldHVybiBzZWxmO1xuICB9IGVsc2UgaWYgKHR5cGVvZiB3aW5kb3cgIT09ICd1bmRlZmluZWQnKSB7XG4gICAgcmV0dXJuIHdpbmRvdztcbiAgfSBlbHNlIGlmICh0eXBlb2YgZ2xvYmFsICE9PSAndW5kZWZpbmVkJykge1xuICAgIHJldHVybiBnbG9iYWw7XG4gIH1cblxuICB0aHJvdyBuZXcgRXJyb3IoJ05vIGdsb2JhbCBzdGF0ZSBmb3VuZCcpO1xufVxuXG5mdW5jdGlvbiBjb25jYXRfbGlzdHMobGVmdCwgcmlnaHQpIHtcbiAgcmV0dXJuIGxlZnQuY29uY2F0KHJpZ2h0KTtcbn1cblxuZnVuY3Rpb24gcHJlcGVuZF90b19saXN0KGxpc3QsIGl0ZW0pIHtcbiAgcmV0dXJuIFtpdGVtXS5jb25jYXQobGlzdCk7XG59XG5cbmZ1bmN0aW9uIGRlZnN0cnVjdChkZWZhdWx0cykge1xuICByZXR1cm4gY2xhc3Mge1xuICAgIGNvbnN0cnVjdG9yKHVwZGF0ZSA9IHt9KSB7XG4gICAgICBsZXQgdGhlX3ZhbHVlcyA9IE9iamVjdC5hc3NpZ24oZGVmYXVsdHMsIHVwZGF0ZSk7XG4gICAgICBPYmplY3QuYXNzaWduKHRoaXMsIHRoZV92YWx1ZXMpO1xuICAgIH1cblxuICAgIHN0YXRpYyBjcmVhdGUodXBkYXRlcyA9IHt9KSB7XG4gICAgICBsZXQgeCA9IG5ldyB0aGlzKHVwZGF0ZXMpO1xuICAgICAgcmV0dXJuIE9iamVjdC5mcmVlemUoeCk7XG4gICAgfVxuICB9O1xufVxuXG5mdW5jdGlvbiBkZWZleGNlcHRpb24oZGVmYXVsdHMpIHtcbiAgcmV0dXJuIGNsYXNzIGV4dGVuZHMgRXJyb3Ige1xuICAgIGNvbnN0cnVjdG9yKHVwZGF0ZSA9IHt9KSB7XG4gICAgICBsZXQgbWVzc2FnZSA9IHVwZGF0ZS5tZXNzYWdlIHx8ICcnO1xuICAgICAgc3VwZXIobWVzc2FnZSk7XG5cbiAgICAgIGxldCB0aGVfdmFsdWVzID0gT2JqZWN0LmFzc2lnbihkZWZhdWx0cywgdXBkYXRlKTtcbiAgICAgIE9iamVjdC5hc3NpZ24odGhpcywgdGhlX3ZhbHVlcyk7XG5cbiAgICAgIHRoaXMubmFtZSA9IHRoaXMuY29uc3RydWN0b3IubmFtZTtcbiAgICAgIHRoaXMubWVzc2FnZSA9IG1lc3NhZ2U7XG4gICAgICB0aGlzW1NwZWNpYWxGb3Jtcy5hdG9tKCdfX2V4Y2VwdGlvbl9fJyldID0gdHJ1ZTtcbiAgICAgIEVycm9yLmNhcHR1cmVTdGFja1RyYWNlKHRoaXMsIHRoaXMuY29uc3RydWN0b3IubmFtZSk7XG4gICAgfVxuXG4gICAgc3RhdGljIGNyZWF0ZSh1cGRhdGVzID0ge30pIHtcbiAgICAgIGxldCB4ID0gbmV3IHRoaXModXBkYXRlcyk7XG4gICAgICByZXR1cm4gT2JqZWN0LmZyZWV6ZSh4KTtcbiAgICB9XG4gIH07XG59XG5cbmZ1bmN0aW9uIGRlZnByb3RvY29sKHNwZWMpIHtcbiAgcmV0dXJuIG5ldyBQcm90b2NvbChzcGVjKTtcbn1cblxuZnVuY3Rpb24gZGVmaW1wbChwcm90b2NvbCwgdHlwZSwgaW1wbCkge1xuICBwcm90b2NvbC5pbXBsZW1lbnRhdGlvbih0eXBlLCBpbXBsKTtcbn1cblxuZnVuY3Rpb24gZ2V0X29iamVjdF9rZXlzKG9iaikge1xuICByZXR1cm4gT2JqZWN0LmtleXMob2JqKS5jb25jYXQoT2JqZWN0LmdldE93blByb3BlcnR5U3ltYm9scyhvYmopKTtcbn1cblxuZnVuY3Rpb24gaXNfdmFsaWRfY2hhcmFjdGVyKGNvZGVwb2ludCkge1xuICB0cnkge1xuICAgIHJldHVybiBTdHJpbmcuZnJvbUNvZGVQb2ludChjb2RlcG9pbnQpICE9IG51bGw7XG4gIH0gY2F0Y2ggKGUpIHtcbiAgICByZXR1cm4gZmFsc2U7XG4gIH1cbn1cblxuLy9odHRwczovL2RldmVsb3Blci5tb3ppbGxhLm9yZy9lbi1VUy9kb2NzL1dlYi9BUEkvV2luZG93QmFzZTY0L0Jhc2U2NF9lbmNvZGluZ19hbmRfZGVjb2RpbmcjU29sdXRpb25fMl8lRTIlODAlOTNfcmV3cml0ZV90aGVfRE9Nc19hdG9iKClfYW5kX2J0b2EoKV91c2luZ19KYXZhU2NyaXB0J3NfVHlwZWRBcnJheXNfYW5kX1VURi04XG5mdW5jdGlvbiBiNjRFbmNvZGVVbmljb2RlKHN0cikge1xuICByZXR1cm4gYnRvYShlbmNvZGVVUklDb21wb25lbnQoc3RyKS5yZXBsYWNlKC8lKFswLTlBLUZdezJ9KS9nLCBmdW5jdGlvbiAobWF0Y2gsIHAxKSB7XG4gICAgcmV0dXJuIFN0cmluZy5mcm9tQ2hhckNvZGUoJzB4JyArIHAxKTtcbiAgfSkpO1xufVxuXG52YXIgRnVuY3Rpb25zID0ge1xuICBjYWxsX3Byb3BlcnR5LFxuICBpc19pbnN0YW5jZV9vZixcbiAgc2l6ZTogc2l6ZSQyLFxuICBpc19uaWw6IGlzX25pbCQxLFxuICBpc19hdG9tOiBpc19hdG9tJDEsXG4gIGlzX2JpbmFyeTogaXNfYmluYXJ5JDEsXG4gIGlzX2Jvb2xlYW46IGlzX2Jvb2xlYW4kMSxcbiAgaXNfZnVuY3Rpb246IGlzX2Z1bmN0aW9uJDEsXG4gIGlzX2Zsb2F0OiBpc19mbG9hdCQxLFxuICBpc19pbnRlZ2VyOiBpc19pbnRlZ2VyJDEsXG4gIGlzX2xpc3Q6IGlzX2xpc3QkMSxcbiAgaXNfbWFwOiBpc19tYXAkMSxcbiAgaXNfbnVtYmVyOiBpc19udW1iZXIkMSxcbiAgaXNfdHVwbGU6IGlzX3R1cGxlJDEsXG4gIGlzX3BpZDogaXNfcGlkJDEsXG4gIGlzX3BvcnQ6IGlzX3BvcnQkMSxcbiAgaXNfcmVmZXJlbmNlOiBpc19yZWZlcmVuY2UkMSxcbiAgaXNfYml0c3RyaW5nOiBpc19iaXRzdHJpbmckMSxcbiAgYWRkLFxuICBzdWJ0cmFjdCxcbiAgbXVsdGlwbHksXG4gIGRpdmlkZSxcbiAgcmVtYWluZGVyLFxuICBhcHBseTogYXBwbHkkMSxcbiAgbmV3X3R1cGxlLFxuICBkdXBsaWNhdGUsXG4gIGNvbnRhaW5zLFxuICByZXZlcnNlLFxuICBnZXRfZ2xvYmFsLFxuICBjb25jYXRfbGlzdHMsXG4gIHByZXBlbmRfdG9fbGlzdCxcbiAgZGVmc3RydWN0LFxuICBkZWZleGNlcHRpb24sXG4gIGRlZnByb3RvY29sLFxuICBkZWZpbXBsLFxuICBnZXRfb2JqZWN0X2tleXMsXG4gIGlzX3ZhbGlkX2NoYXJhY3RlcixcbiAgYjY0RW5jb2RlVW5pY29kZVxufTtcblxuZnVuY3Rpb24gbGlzdCguLi5hcmdzKSB7XG4gIHJldHVybiBPYmplY3QuZnJlZXplKGFyZ3MpO1xufVxuXG5mdW5jdGlvbiBiaXRzdHJpbmcoLi4uYXJncykge1xuICByZXR1cm4gbmV3IEJpdFN0cmluZyguLi5hcmdzKTtcbn1cblxuZnVuY3Rpb24gdHVwbGUoLi4uYXJncykge1xuICByZXR1cm4gbmV3IFR1cGxlKC4uLmFyZ3MpO1xufVxuXG5mdW5jdGlvbiBfY2FzZShjb25kaXRpb24sIGNsYXVzZXMpIHtcbiAgcmV0dXJuIFBhdHRlcm5zLmRlZm1hdGNoKC4uLmNsYXVzZXMpKGNvbmRpdGlvbik7XG59XG5cbmZ1bmN0aW9uIGNvbmQoY2xhdXNlcykge1xuICBmb3IgKGxldCBjbGF1c2Ugb2YgY2xhdXNlcykge1xuICAgIGlmIChjbGF1c2VbMF0pIHtcbiAgICAgIHJldHVybiBjbGF1c2VbMV0oKTtcbiAgICB9XG4gIH1cblxuICB0aHJvdyBuZXcgRXJyb3IoKTtcbn1cblxuZnVuY3Rpb24gbWFwJDEob2JqKSB7XG4gIHJldHVybiBPYmplY3QuZnJlZXplKG9iaik7XG59XG5cbmZ1bmN0aW9uIG1hcF91cGRhdGUobWFwLCB2YWx1ZXMpIHtcbiAgcmV0dXJuIE9iamVjdC5mcmVlemUoT2JqZWN0LmFzc2lnbihPYmplY3QuY3JlYXRlKG1hcC5jb25zdHJ1Y3Rvci5wcm90b3R5cGUpLCBtYXAsIHZhbHVlcykpO1xufVxuXG5mdW5jdGlvbiBfZm9yKGNvbGxlY3Rpb25zLCBmdW4sIGZpbHRlciA9ICgpID0+IHRydWUsIGludG8gPSBbXSwgcHJldmlvdXNWYWx1ZXMgPSBbXSkge1xuICBsZXQgcGF0dGVybiA9IGNvbGxlY3Rpb25zWzBdWzBdO1xuICBsZXQgY29sbGVjdGlvbiA9IGNvbGxlY3Rpb25zWzBdWzFdO1xuXG4gIGlmIChjb2xsZWN0aW9ucy5sZW5ndGggPT09IDEpIHtcblxuICAgIGZvciAobGV0IGVsZW0gb2YgY29sbGVjdGlvbikge1xuICAgICAgbGV0IHIgPSBQYXR0ZXJucy5tYXRjaF9ub190aHJvdyhwYXR0ZXJuLCBlbGVtKTtcbiAgICAgIGxldCBhcmdzID0gcHJldmlvdXNWYWx1ZXMuY29uY2F0KHIpO1xuXG4gICAgICBpZiAociAmJiBmaWx0ZXIuYXBwbHkodGhpcywgYXJncykpIHtcbiAgICAgICAgaW50byA9IEVudW0uaW50byhbZnVuLmFwcGx5KHRoaXMsIGFyZ3MpXSwgaW50byk7XG4gICAgICB9XG4gICAgfVxuXG4gICAgcmV0dXJuIGludG87XG4gIH0gZWxzZSB7XG4gICAgbGV0IF9pbnRvID0gW107XG5cbiAgICBmb3IgKGxldCBlbGVtIG9mIGNvbGxlY3Rpb24pIHtcbiAgICAgIGxldCByID0gUGF0dGVybnMubWF0Y2hfbm9fdGhyb3cocGF0dGVybiwgZWxlbSk7XG4gICAgICBpZiAocikge1xuICAgICAgICBfaW50byA9IEVudW0uaW50byh0aGlzLl9mb3IoY29sbGVjdGlvbnMuc2xpY2UoMSksIGZ1biwgZmlsdGVyLCBfaW50bywgcHJldmlvdXNWYWx1ZXMuY29uY2F0KHIpKSwgaW50byk7XG4gICAgICB9XG4gICAgfVxuXG4gICAgcmV0dXJuIF9pbnRvO1xuICB9XG59XG5cbmZ1bmN0aW9uIF90cnkoZG9fZnVuLCByZXNjdWVfZnVuY3Rpb24sIGNhdGNoX2Z1biwgZWxzZV9mdW5jdGlvbiwgYWZ0ZXJfZnVuY3Rpb24pIHtcbiAgbGV0IHJlc3VsdCA9IG51bGw7XG5cbiAgdHJ5IHtcbiAgICByZXN1bHQgPSBkb19mdW4oKTtcbiAgfSBjYXRjaCAoZSkge1xuICAgIGxldCBleF9yZXN1bHQgPSBudWxsO1xuXG4gICAgaWYgKHJlc2N1ZV9mdW5jdGlvbikge1xuICAgICAgdHJ5IHtcbiAgICAgICAgZXhfcmVzdWx0ID0gcmVzY3VlX2Z1bmN0aW9uKGUpO1xuICAgICAgICByZXR1cm4gZXhfcmVzdWx0O1xuICAgICAgfSBjYXRjaCAoZXgpIHtcbiAgICAgICAgaWYgKGV4IGluc3RhbmNlb2YgUGF0dGVybnMuTWF0Y2hFcnJvcikge1xuICAgICAgICAgIHRocm93IGV4O1xuICAgICAgICB9XG4gICAgICB9XG4gICAgfVxuXG4gICAgaWYgKGNhdGNoX2Z1bikge1xuICAgICAgdHJ5IHtcbiAgICAgICAgZXhfcmVzdWx0ID0gY2F0Y2hfZnVuKGUpO1xuICAgICAgICByZXR1cm4gZXhfcmVzdWx0O1xuICAgICAgfSBjYXRjaCAoZXgpIHtcbiAgICAgICAgaWYgKGV4IGluc3RhbmNlb2YgUGF0dGVybnMuTWF0Y2hFcnJvcikge1xuICAgICAgICAgIHRocm93IGV4O1xuICAgICAgICB9XG4gICAgICB9XG4gICAgfVxuXG4gICAgdGhyb3cgZTtcbiAgfSBmaW5hbGx5IHtcbiAgICBpZiAoYWZ0ZXJfZnVuY3Rpb24pIHtcbiAgICAgIGFmdGVyX2Z1bmN0aW9uKCk7XG4gICAgfVxuICB9XG5cbiAgaWYgKGVsc2VfZnVuY3Rpb24pIHtcbiAgICB0cnkge1xuICAgICAgcmV0dXJuIGVsc2VfZnVuY3Rpb24ocmVzdWx0KTtcbiAgICB9IGNhdGNoIChleCkge1xuICAgICAgaWYgKGV4IGluc3RhbmNlb2YgUGF0dGVybnMuTWF0Y2hFcnJvcikge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ05vIE1hdGNoIEZvdW5kIGluIEVsc2UnKTtcbiAgICAgIH1cblxuICAgICAgdGhyb3cgZXg7XG4gICAgfVxuICB9IGVsc2Uge1xuICAgIHJldHVybiByZXN1bHQ7XG4gIH1cbn1cblxudmFyIFNwZWNpYWxGb3JtcyQxID0ge1xuICBsaXN0LFxuICBiaXRzdHJpbmcsXG4gIHR1cGxlLFxuICBfY2FzZSxcbiAgY29uZCxcbiAgbWFwOiBtYXAkMSxcbiAgbWFwX3VwZGF0ZSxcbiAgX2ZvcixcbiAgX3RyeVxufTtcblxuRnVuY3Rpb25zLmdldF9nbG9iYWwoKS5wcm9jZXNzZXMgPSBGdW5jdGlvbnMuZ2V0X2dsb2JhbCgpLnByb2Nlc3NlcyB8fCBuZXcgUHJvY2Vzc1N5c3RlbSgpO1xuXG5cblxudmFyIEMgPSBPYmplY3QuZnJlZXplKHtcblx0UHJvY2Vzc1N5c3RlbTogUHJvY2Vzc1N5c3RlbSxcblx0VHVwbGU6IFR1cGxlJDEsXG5cdFBJRDogUElELFxuXHRCaXRTdHJpbmc6IEJpdFN0cmluZyxcblx0UGF0dGVybnM6IFBhdHRlcm5zLFxuXHRJbnRlZ2VyOiBJbnRlZ2VyLFxuXHRGbG9hdDogRmxvYXQsXG5cdEZ1bmN0aW9uczogRnVuY3Rpb25zLFxuXHRMaXN0OiBMaXN0JDEsXG5cdFNwZWNpYWxGb3JtczogU3BlY2lhbEZvcm1zJDFcbn0pO1xuXG5mdW5jdGlvbiB0bChsaXN0KSB7XG4gIHJldHVybiBTcGVjaWFsRm9ybXMkMS5saXN0KC4uLmxpc3Quc2xpY2UoMSkpO1xufVxuXG5mdW5jdGlvbiBoZChsaXN0KSB7XG4gIHJldHVybiBsaXN0WzBdO1xufVxuXG5mdW5jdGlvbiBpc19uaWwoeCkge1xuICByZXR1cm4geCA9PT0gbnVsbDtcbn1cblxuZnVuY3Rpb24gaXNfYXRvbSh4KSB7XG4gIHJldHVybiB0eXBlb2YgeCA9PT0gJ3N5bWJvbCc7XG59XG5cbmZ1bmN0aW9uIGlzX2JpbmFyeSh4KSB7XG4gIHJldHVybiB0eXBlb2YgeCA9PT0gJ3N0cmluZycgfHwgeCBpbnN0YW5jZW9mIFN0cmluZztcbn1cblxuZnVuY3Rpb24gaXNfYm9vbGVhbih4KSB7XG4gIHJldHVybiB0eXBlb2YgeCA9PT0gJ2Jvb2xlYW4nIHx8IHggaW5zdGFuY2VvZiBCb29sZWFuO1xufVxuXG5mdW5jdGlvbiBpc19mdW5jdGlvbih4LCBhcml0eSA9IC0xKSB7XG4gIHJldHVybiB0eXBlb2YgeCA9PT0gJ2Z1bmN0aW9uJyB8fCB4IGluc3RhbmNlb2YgRnVuY3Rpb247XG59XG5cbmZ1bmN0aW9uIGlzX2Zsb2F0KHgpIHtcbiAgcmV0dXJuIGlzX251bWJlcih4KSAmJiAhTnVtYmVyLmlzSW50ZWdlcih4KTtcbn1cblxuZnVuY3Rpb24gaXNfaW50ZWdlcih4KSB7XG4gIHJldHVybiBOdW1iZXIuaXNJbnRlZ2VyKHgpO1xufVxuXG5mdW5jdGlvbiBpc19saXN0KHgpIHtcbiAgcmV0dXJuIHggaW5zdGFuY2VvZiBBcnJheTtcbn1cblxuZnVuY3Rpb24gaXNfbWFwKHgpIHtcbiAgcmV0dXJuIHR5cGVvZiB4ID09PSAnb2JqZWN0JyB8fCB4IGluc3RhbmNlb2YgT2JqZWN0O1xufVxuXG5mdW5jdGlvbiBpc19udW1iZXIoeCkge1xuICByZXR1cm4gdHlwZW9mIHggPT09ICdudW1iZXInO1xufVxuXG5mdW5jdGlvbiBpc190dXBsZSh4KSB7XG4gIHJldHVybiB4IGluc3RhbmNlb2YgVHVwbGUkMTtcbn1cblxuZnVuY3Rpb24gbGVuZ3RoKHgpIHtcbiAgcmV0dXJuIHgubGVuZ3RoO1xufVxuXG5mdW5jdGlvbiBpc19waWQoeCkge1xuICByZXR1cm4geCBpbnN0YW5jZW9mIFBJRDtcbn1cblxuZnVuY3Rpb24gaXNfcG9ydCh4KSB7XG4gIHJldHVybiBmYWxzZTtcbn1cblxuZnVuY3Rpb24gaXNfcmVmZXJlbmNlKHgpIHtcbiAgcmV0dXJuIGZhbHNlO1xufVxuXG5mdW5jdGlvbiBpc19iaXRzdHJpbmcoeCkge1xuICByZXR1cm4gaXNfYmluYXJ5KHgpIHx8IHggaW5zdGFuY2VvZiBCaXRTdHJpbmc7XG59XG5cbmZ1bmN0aW9uIF9faW5fXyhsZWZ0LCByaWdodCkge1xuICBmb3IgKGxldCB4IG9mIHJpZ2h0KSB7XG4gICAgaWYgKG1hdGNoX19xbWFya19fKGxlZnQsIHgpKSB7XG4gICAgICByZXR1cm4gdHJ1ZTtcbiAgICB9XG4gIH1cblxuICByZXR1cm4gZmFsc2U7XG59XG5cbmZ1bmN0aW9uIGFicyhudW1iZXIpIHtcbiAgcmV0dXJuIE1hdGguYWJzKG51bWJlcik7XG59XG5cbmZ1bmN0aW9uIHJvdW5kKG51bWJlcikge1xuICByZXR1cm4gTWF0aC5yb3VuZChudW1iZXIpO1xufVxuXG5mdW5jdGlvbiBlbGVtKHR1cGxlLCBpbmRleCkge1xuICBpZiAoaXNfbGlzdCh0dXBsZSkpIHtcbiAgICByZXR1cm4gdHVwbGVbaW5kZXhdO1xuICB9XG5cbiAgcmV0dXJuIHR1cGxlLmdldChpbmRleCk7XG59XG5cbmZ1bmN0aW9uIHJlbShsZWZ0LCByaWdodCkge1xuICByZXR1cm4gbGVmdCAlIHJpZ2h0O1xufVxuXG5mdW5jdGlvbiBkaXYobGVmdCwgcmlnaHQpIHtcbiAgcmV0dXJuIGxlZnQgLyByaWdodDtcbn1cblxuZnVuY3Rpb24gYW5kKGxlZnQsIHJpZ2h0KSB7XG4gIHJldHVybiBsZWZ0ICYmIHJpZ2h0O1xufVxuXG5mdW5jdGlvbiBvcihsZWZ0LCByaWdodCkge1xuICByZXR1cm4gbGVmdCB8fCByaWdodDtcbn1cblxuZnVuY3Rpb24gbm90KGFyZykge1xuICByZXR1cm4gIWFyZztcbn1cblxuZnVuY3Rpb24gYXBwbHkoLi4uYXJncykge1xuICBpZiAoYXJncy5sZW5ndGggPT09IDMpIHtcbiAgICBsZXQgbW9kID0gYXJnc1swXTtcbiAgICBsZXQgZnVuYyA9IGFyZ3NbMV07XG4gICAgbGV0IGZ1bmNfYXJncyA9IGFyZ3NbMl07XG4gICAgcmV0dXJuIG1vZFtmdW5jXS5hcHBseShudWxsLCBmdW5jX2FyZ3MpO1xuICB9IGVsc2Uge1xuICAgIGxldCBmdW5jID0gYXJnc1swXTtcbiAgICBsZXQgZnVuY19hcmdzID0gYXJnc1sxXTtcblxuICAgIHJldHVybiBmdW5jLmFwcGx5KG51bGwsIGZ1bmNfYXJncyk7XG4gIH1cbn1cblxuZnVuY3Rpb24gdG9fc3RyaW5nKGFyZykge1xuICBpZiAoaXNfdHVwbGUoYXJnKSkge1xuICAgIHJldHVybiBhcmcudG9TdHJpbmcoKTtcbiAgfVxuXG4gIHJldHVybiBhcmcudG9TdHJpbmcoKTtcbn1cblxuZnVuY3Rpb24gbWF0Y2hfX3FtYXJrX18ocGF0dGVybiwgZXhwciwgZ3VhcmQgPSAoKSA9PiB0cnVlKSB7XG4gIHJldHVybiBQYXR0ZXJucy5tYXRjaF9ub190aHJvdyhwYXR0ZXJuLCBleHByLCBndWFyZCkgIT0gbnVsbDtcbn1cblxudmFyIEtlcm5lbCA9IHtcbiAgdGwsXG4gIGhkLFxuICBpc19uaWwsXG4gIGlzX2F0b20sXG4gIGlzX2JpbmFyeSxcbiAgaXNfYm9vbGVhbixcbiAgaXNfZnVuY3Rpb24sXG4gIGlzX2Zsb2F0LFxuICBpc19pbnRlZ2VyLFxuICBpc19saXN0LFxuICBpc19tYXAsXG4gIGlzX251bWJlcixcbiAgaXNfdHVwbGUsXG4gIGxlbmd0aCxcbiAgaXNfcGlkLFxuICBpc19wb3J0LFxuICBpc19yZWZlcmVuY2UsXG4gIGlzX2JpdHN0cmluZyxcbiAgaW46IF9faW5fXyxcbiAgYWJzLFxuICByb3VuZCxcbiAgZWxlbSxcbiAgcmVtLFxuICBkaXYsXG4gIGFuZCxcbiAgb3IsXG4gIG5vdCxcbiAgYXBwbHksXG4gIHRvX3N0cmluZyxcbiAgbWF0Y2hfX3FtYXJrX19cbn07XG5cbmxldCBFbnVtJDEgPSB7XG5cbiAgYWxsX19xbWFya19fOiBmdW5jdGlvbiAoY29sbGVjdGlvbiwgZnVuID0geCA9PiB4KSB7XG4gICAgZm9yIChsZXQgZWxlbSBvZiBjb2xsZWN0aW9uKSB7XG4gICAgICBpZiAoIWZ1bihlbGVtKSkge1xuICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICB9XG4gICAgfVxuXG4gICAgcmV0dXJuIHRydWU7XG4gIH0sXG5cbiAgYW55X19xbWFya19fOiBmdW5jdGlvbiAoY29sbGVjdGlvbiwgZnVuID0geCA9PiB4KSB7XG4gICAgZm9yIChsZXQgZWxlbSBvZiBjb2xsZWN0aW9uKSB7XG4gICAgICBpZiAoZnVuKGVsZW0pKSB7XG4gICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgfVxuICAgIH1cblxuICAgIHJldHVybiBmYWxzZTtcbiAgfSxcblxuICBhdDogZnVuY3Rpb24gKGNvbGxlY3Rpb24sIG4sIHRoZV9kZWZhdWx0ID0gbnVsbCkge1xuICAgIGlmIChuID4gdGhpcy5jb3VudChjb2xsZWN0aW9uKSB8fCBuIDwgMCkge1xuICAgICAgcmV0dXJuIHRoZV9kZWZhdWx0O1xuICAgIH1cblxuICAgIHJldHVybiBjb2xsZWN0aW9uW25dO1xuICB9LFxuXG4gIGNvbmNhdDogZnVuY3Rpb24gKC4uLmVudW1hYmxlcykge1xuICAgIHJldHVybiBlbnVtYWJsZXNbMF0uY29uY2F0KGVudW1hYmxlc1sxXSk7XG4gIH0sXG5cbiAgY291bnQ6IGZ1bmN0aW9uIChjb2xsZWN0aW9uLCBmdW4gPSBudWxsKSB7XG4gICAgaWYgKGZ1biA9PSBudWxsKSB7XG4gICAgICByZXR1cm4gY29sbGVjdGlvbi5sZW5ndGg7XG4gICAgfSBlbHNlIHtcbiAgICAgIHJldHVybiBjb2xsZWN0aW9uLmZpbHRlcihmdW4pLmxlbmd0aDtcbiAgICB9XG4gIH0sXG5cbiAgZHJvcDogZnVuY3Rpb24gKGNvbGxlY3Rpb24sIGNvdW50KSB7XG4gICAgcmV0dXJuIGNvbGxlY3Rpb24uc2xpY2UoY291bnQpO1xuICB9LFxuXG4gIGRyb3Bfd2hpbGU6IGZ1bmN0aW9uIChjb2xsZWN0aW9uLCBmdW4pIHtcbiAgICBsZXQgY291bnQgPSAwO1xuXG4gICAgZm9yIChsZXQgZWxlbSBvZiBjb2xsZWN0aW9uKSB7XG4gICAgICBpZiAoZnVuKGVsZW0pKSB7XG4gICAgICAgIGNvdW50ID0gY291bnQgKyAxO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgYnJlYWs7XG4gICAgICB9XG4gICAgfVxuXG4gICAgcmV0dXJuIGNvbGxlY3Rpb24uc2xpY2UoY291bnQpO1xuICB9LFxuXG4gIGVhY2g6IGZ1bmN0aW9uIChjb2xsZWN0aW9uLCBmdW4pIHtcbiAgICBmb3IgKGxldCBlbGVtIG9mIGNvbGxlY3Rpb24pIHtcbiAgICAgIGZ1bihlbGVtKTtcbiAgICB9XG4gIH0sXG5cbiAgZW1wdHlfX3FtYXJrX186IGZ1bmN0aW9uIChjb2xsZWN0aW9uKSB7XG4gICAgcmV0dXJuIGNvbGxlY3Rpb24ubGVuZ3RoID09PSAwO1xuICB9LFxuXG4gIGZldGNoOiBmdW5jdGlvbiAoY29sbGVjdGlvbiwgbikge1xuICAgIGlmIChLZXJuZWwuaXNfbGlzdChjb2xsZWN0aW9uKSkge1xuICAgICAgaWYgKG4gPCB0aGlzLmNvdW50KGNvbGxlY3Rpb24pICYmIG4gPj0gMCkge1xuICAgICAgICByZXR1cm4gbmV3IFR1cGxlJDEoU3ltYm9sLmZvcignb2snKSwgY29sbGVjdGlvbltuXSk7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICByZXR1cm4gU3ltYm9sLmZvcignZXJyb3InKTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICB0aHJvdyBuZXcgRXJyb3IoJ2NvbGxlY3Rpb24gaXMgbm90IGFuIEVudW1lcmFibGUnKTtcbiAgfSxcblxuICBmZXRjaF9fZW1hcmtfXzogZnVuY3Rpb24gKGNvbGxlY3Rpb24sIG4pIHtcbiAgICBpZiAoS2VybmVsLmlzX2xpc3QoY29sbGVjdGlvbikpIHtcbiAgICAgIGlmIChuIDwgdGhpcy5jb3VudChjb2xsZWN0aW9uKSAmJiBuID49IDApIHtcbiAgICAgICAgcmV0dXJuIGNvbGxlY3Rpb25bbl07XG4gICAgICB9IGVsc2Uge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ291dCBvZiBib3VuZHMgZXJyb3InKTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICB0aHJvdyBuZXcgRXJyb3IoJ2NvbGxlY3Rpb24gaXMgbm90IGFuIEVudW1lcmFibGUnKTtcbiAgfSxcblxuICBmaWx0ZXI6IGZ1bmN0aW9uIChjb2xsZWN0aW9uLCBmdW4pIHtcbiAgICBsZXQgcmVzdWx0ID0gW107XG5cbiAgICBmb3IgKGxldCBlbGVtIG9mIGNvbGxlY3Rpb24pIHtcbiAgICAgIGlmIChmdW4oZWxlbSkpIHtcbiAgICAgICAgcmVzdWx0LnB1c2goZWxlbSk7XG4gICAgICB9XG4gICAgfVxuXG4gICAgcmV0dXJuIHJlc3VsdDtcbiAgfSxcblxuICBmaWx0ZXJfbWFwOiBmdW5jdGlvbiAoY29sbGVjdGlvbiwgZmlsdGVyLCBtYXBwZXIpIHtcbiAgICByZXR1cm4gRW51bSQxLm1hcChFbnVtJDEuZmlsdGVyKGNvbGxlY3Rpb24sIGZpbHRlciksIG1hcHBlcik7XG4gIH0sXG5cbiAgZmluZDogZnVuY3Rpb24gKGNvbGxlY3Rpb24sIGlmX25vbmUgPSBudWxsLCBmdW4pIHtcbiAgICBmb3IgKGxldCBlbGVtIG9mIGNvbGxlY3Rpb24pIHtcbiAgICAgIGlmIChmdW4oZWxlbSkpIHtcbiAgICAgICAgcmV0dXJuIGVsZW07XG4gICAgICB9XG4gICAgfVxuXG4gICAgcmV0dXJuIGlmX25vbmU7XG4gIH0sXG5cbiAgaW50bzogZnVuY3Rpb24gKGNvbGxlY3Rpb24sIGxpc3QpIHtcbiAgICByZXR1cm4gbGlzdC5jb25jYXQoY29sbGVjdGlvbik7XG4gIH0sXG5cbiAgbWFwOiBmdW5jdGlvbiAoY29sbGVjdGlvbiwgZnVuKSB7XG4gICAgbGV0IHJlc3VsdCA9IFtdO1xuXG4gICAgZm9yIChsZXQgZWxlbSBvZiBjb2xsZWN0aW9uKSB7XG4gICAgICByZXN1bHQucHVzaChmdW4oZWxlbSkpO1xuICAgIH1cblxuICAgIHJldHVybiByZXN1bHQ7XG4gIH0sXG5cbiAgbWFwX3JlZHVjZTogZnVuY3Rpb24gKGNvbGxlY3Rpb24sIGFjYywgZnVuKSB7XG4gICAgbGV0IG1hcHBlZCA9IExpc3QkMSgpO1xuICAgIGxldCB0aGVfYWNjID0gYWNjO1xuXG4gICAgZm9yICh2YXIgaSA9IDA7IGkgPCB0aGlzLmNvdW50KGNvbGxlY3Rpb24pOyBpKyspIHtcbiAgICAgIGxldCB0dXBsZSA9IGZ1bihjb2xsZWN0aW9uW2ldLCB0aGVfYWNjKTtcblxuICAgICAgdGhlX2FjYyA9IHR1cGxlLmdldCgxKTtcbiAgICAgIG1hcHBlZCA9IExpc3QkMSguLi5tYXBwZWQuY29uY2F0KFt0dXBsZS5nZXQoMCldKSk7XG4gICAgfVxuXG4gICAgcmV0dXJuIG5ldyBUdXBsZSQxKG1hcHBlZCwgdGhlX2FjYyk7XG4gIH0sXG5cbiAgbWVtYmVyX19xbWFya19fOiBmdW5jdGlvbiAoY29sbGVjdGlvbiwgdmFsdWUpIHtcbiAgICByZXR1cm4gY29sbGVjdGlvbi5pbmNsdWRlcyh2YWx1ZSk7XG4gIH0sXG5cbiAgcmVkdWNlOiBmdW5jdGlvbiAoY29sbGVjdGlvbiwgYWNjLCBmdW4pIHtcbiAgICBsZXQgdGhlX2FjYyA9IGFjYztcblxuICAgIGZvciAodmFyIGkgPSAwOyBpIDwgdGhpcy5jb3VudChjb2xsZWN0aW9uKTsgaSsrKSB7XG4gICAgICBsZXQgdHVwbGUgPSBmdW4oY29sbGVjdGlvbltpXSwgdGhlX2FjYyk7XG5cbiAgICAgIHRoZV9hY2MgPSB0dXBsZS5nZXQoMSk7XG4gICAgfVxuXG4gICAgcmV0dXJuIHRoZV9hY2M7XG4gIH0sXG5cbiAgdGFrZTogZnVuY3Rpb24gKGNvbGxlY3Rpb24sIGNvdW50KSB7XG4gICAgcmV0dXJuIGNvbGxlY3Rpb24uc2xpY2UoMCwgY291bnQpO1xuICB9LFxuXG4gIHRha2VfZXZlcnk6IGZ1bmN0aW9uIChjb2xsZWN0aW9uLCBudGgpIHtcbiAgICBsZXQgcmVzdWx0ID0gW107XG4gICAgbGV0IGluZGV4ID0gMDtcblxuICAgIGZvciAobGV0IGVsZW0gb2YgY29sbGVjdGlvbikge1xuICAgICAgaWYgKGluZGV4ICUgbnRoID09PSAwKSB7XG4gICAgICAgIHJlc3VsdC5wdXNoKGVsZW0pO1xuICAgICAgfVxuICAgIH1cblxuICAgIHJldHVybiBMaXN0JDEoLi4ucmVzdWx0KTtcbiAgfSxcblxuICB0YWtlX3doaWxlOiBmdW5jdGlvbiAoY29sbGVjdGlvbiwgZnVuKSB7XG4gICAgbGV0IGNvdW50ID0gMDtcblxuICAgIGZvciAobGV0IGVsZW0gb2YgY29sbGVjdGlvbikge1xuICAgICAgaWYgKGZ1bihlbGVtKSkge1xuICAgICAgICBjb3VudCA9IGNvdW50ICsgMTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIGJyZWFrO1xuICAgICAgfVxuICAgIH1cblxuICAgIHJldHVybiBjb2xsZWN0aW9uLnNsaWNlKDAsIGNvdW50KTtcbiAgfSxcblxuICB0b19saXN0OiBmdW5jdGlvbiAoY29sbGVjdGlvbikge1xuICAgIHJldHVybiBjb2xsZWN0aW9uO1xuICB9XG59O1xuXG5sZXQgTGlzdCA9IHt9O1xuXG5MaXN0LmRlbGV0ZSA9IGZ1bmN0aW9uIChsaXN0LCBpdGVtKSB7XG4gIGxldCBuZXdfdmFsdWUgPSBbXTtcbiAgbGV0IHZhbHVlX2ZvdW5kID0gZmFsc2U7XG5cbiAgZm9yIChsZXQgeCBvZiBsaXN0KSB7XG4gICAgaWYgKHggPT09IGl0ZW0gJiYgdmFsdWVfZm91bmQgIT09IGZhbHNlKSB7XG4gICAgICBuZXdfdmFsdWUucHVzaCh4KTtcbiAgICAgIHZhbHVlX2ZvdW5kID0gdHJ1ZTtcbiAgICB9IGVsc2UgaWYgKHggIT09IGl0ZW0pIHtcbiAgICAgIG5ld192YWx1ZS5wdXNoKHgpO1xuICAgIH1cbiAgfVxuXG4gIHJldHVybiBTcGVjaWFsRm9ybXMkMS5saXN0KC4uLm5ld192YWx1ZSk7XG59O1xuXG5MaXN0LmRlbGV0ZV9hdCA9IGZ1bmN0aW9uIChsaXN0LCBpbmRleCkge1xuICBsZXQgbmV3X3ZhbHVlID0gW107XG5cbiAgZm9yIChsZXQgaSA9IDA7IGkgPCBsaXN0Lmxlbmd0aDsgaSsrKSB7XG4gICAgaWYgKGkgIT09IGluZGV4KSB7XG4gICAgICBuZXdfdmFsdWUucHVzaChsaXN0W2ldKTtcbiAgICB9XG4gIH1cblxuICByZXR1cm4gU3BlY2lhbEZvcm1zJDEubGlzdCguLi5uZXdfdmFsdWUpO1xufTtcblxuTGlzdC5kdXBsaWNhdGUgPSBmdW5jdGlvbiAoZWxlbSwgbikge1xuICBsZXQgbmV3X3ZhbHVlID0gW107XG5cbiAgZm9yICh2YXIgaSA9IDA7IGkgPCBuOyBpKyspIHtcbiAgICBuZXdfdmFsdWUucHVzaChlbGVtKTtcbiAgfVxuXG4gIHJldHVybiBTcGVjaWFsRm9ybXMkMS5saXN0KC4uLm5ld192YWx1ZSk7XG59O1xuXG5MaXN0LmZpcnN0ID0gZnVuY3Rpb24gKGxpc3QpIHtcbiAgcmV0dXJuIGxpc3RbMF07XG59O1xuXG5MaXN0LmZsYXR0ZW4gPSBmdW5jdGlvbiAobGlzdCwgdGFpbCA9IFNwZWNpYWxGb3JtcyQxLmxpc3QoKSkge1xuICBsZXQgbmV3X3ZhbHVlID0gW107XG5cbiAgZm9yIChsZXQgeCBvZiBsaXN0KSB7XG4gICAgaWYgKEtlcm5lbC5pc19saXN0KHgpKSB7XG4gICAgICBuZXdfdmFsdWUgPSBuZXdfdmFsdWUuY29uY2F0KExpc3QuZmxhdHRlbih4KSk7XG4gICAgfSBlbHNlIHtcbiAgICAgIG5ld192YWx1ZS5wdXNoKHgpO1xuICAgIH1cbiAgfVxuXG4gIG5ld192YWx1ZSA9IG5ld192YWx1ZS5jb25jYXQodGFpbCk7XG5cbiAgcmV0dXJuIFNwZWNpYWxGb3JtcyQxLmxpc3QoLi4ubmV3X3ZhbHVlKTtcbn07XG5cbkxpc3QuZm9sZGwgPSBmdW5jdGlvbiAobGlzdCwgYWNjLCBmdW5jKSB7XG4gIHJldHVybiBsaXN0LnJlZHVjZShmdW5jLCBhY2MpO1xufTtcblxuTGlzdC5mb2xkciA9IGZ1bmN0aW9uIChsaXN0LCBhY2MsIGZ1bmMpIHtcbiAgbGV0IG5ld19hY2MgPSBhY2M7XG5cbiAgZm9yICh2YXIgaSA9IGxpc3QubGVuZ3RoIC0gMTsgaSA+PSAwOyBpLS0pIHtcbiAgICBuZXdfYWNjID0gZnVuYyhsaXN0W2ldLCBuZXdfYWNjKTtcbiAgfVxuXG4gIHJldHVybiBuZXdfYWNjO1xufTtcblxuTGlzdC5pbnNlcnRfYXQgPSBmdW5jdGlvbiAobGlzdCwgaW5kZXgsIHZhbHVlKSB7XG4gIGxldCBuZXdfdmFsdWUgPSBbXTtcblxuICBmb3IgKGxldCBpID0gMDsgaSA8IGxpc3QubGVuZ3RoOyBpKyspIHtcbiAgICBpZiAoaSA9PT0gaW5kZXgpIHtcbiAgICAgIG5ld192YWx1ZS5wdXNoKHZhbHVlKTtcbiAgICAgIG5ld192YWx1ZS5wdXNoKGxpc3RbaV0pO1xuICAgIH0gZWxzZSB7XG4gICAgICBuZXdfdmFsdWUucHVzaChsaXN0W2ldKTtcbiAgICB9XG4gIH1cblxuICByZXR1cm4gU3BlY2lhbEZvcm1zJDEubGlzdCguLi5uZXdfdmFsdWUpO1xufTtcblxuTGlzdC5rZXlkZWxldGUgPSBmdW5jdGlvbiAobGlzdCwga2V5LCBwb3NpdGlvbikge1xuICBsZXQgbmV3X2xpc3QgPSBbXTtcblxuICBmb3IgKGxldCBpID0gMDsgaSA8IGxpc3QubGVuZ3RoOyBpKyspIHtcbiAgICBpZiAoIUtlcm5lbC5tYXRjaF9fcW1hcmtfXyhsaXN0W2ldW3Bvc2l0aW9uXSwga2V5KSkge1xuICAgICAgbmV3X2xpc3QucHVzaChsaXN0W2ldKTtcbiAgICB9XG4gIH1cblxuICByZXR1cm4gU3BlY2lhbEZvcm1zJDEubGlzdCguLi5uZXdfbGlzdCk7XG59O1xuXG5MaXN0LmtleWZpbmQgPSBmdW5jdGlvbiAobGlzdCwga2V5LCBwb3NpdGlvbiwgX2RlZmF1bHQgPSBudWxsKSB7XG5cbiAgZm9yIChsZXQgaSA9IDA7IGkgPCBsaXN0Lmxlbmd0aDsgaSsrKSB7XG4gICAgaWYgKEtlcm5lbC5tYXRjaF9fcW1hcmtfXyhsaXN0W2ldW3Bvc2l0aW9uXSwga2V5KSkge1xuICAgICAgcmV0dXJuIGxpc3RbaV07XG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIF9kZWZhdWx0O1xufTtcblxuTGlzdC5rZXltZW1iZXJfX3FtYXJrX18gPSBmdW5jdGlvbiAobGlzdCwga2V5LCBwb3NpdGlvbikge1xuXG4gIGZvciAobGV0IGkgPSAwOyBpIDwgbGlzdC5sZW5ndGg7IGkrKykge1xuICAgIGlmIChLZXJuZWwubWF0Y2hfX3FtYXJrX18obGlzdFtpXVtwb3NpdGlvbl0sIGtleSkpIHtcbiAgICAgIHJldHVybiB0cnVlO1xuICAgIH1cbiAgfVxuXG4gIHJldHVybiBmYWxzZTtcbn07XG5cbkxpc3Qua2V5cmVwbGFjZSA9IGZ1bmN0aW9uIChsaXN0LCBrZXksIHBvc2l0aW9uLCBuZXdfdHVwbGUpIHtcbiAgbGV0IG5ld19saXN0ID0gW107XG5cbiAgZm9yIChsZXQgaSA9IDA7IGkgPCBsaXN0Lmxlbmd0aDsgaSsrKSB7XG4gICAgaWYgKCFLZXJuZWwubWF0Y2hfX3FtYXJrX18obGlzdFtpXVtwb3NpdGlvbl0sIGtleSkpIHtcbiAgICAgIG5ld19saXN0LnB1c2gobGlzdFtpXSk7XG4gICAgfSBlbHNlIHtcbiAgICAgIG5ld19saXN0LnB1c2gobmV3X3R1cGxlKTtcbiAgICB9XG4gIH1cblxuICByZXR1cm4gU3BlY2lhbEZvcm1zJDEubGlzdCguLi5uZXdfbGlzdCk7XG59O1xuXG5MaXN0LmtleXNvcnQgPSBmdW5jdGlvbiAobGlzdCwgcG9zaXRpb24pIHtcbiAgbGV0IG5ld19saXN0ID0gbGlzdDtcblxuICBuZXdfbGlzdC5zb3J0KGZ1bmN0aW9uIChhLCBiKSB7XG4gICAgaWYgKHBvc2l0aW9uID09PSAwKSB7XG4gICAgICBpZiAoYVtwb3NpdGlvbl0udmFsdWUgPCBiW3Bvc2l0aW9uXS52YWx1ZSkge1xuICAgICAgICByZXR1cm4gLTE7XG4gICAgICB9XG5cbiAgICAgIGlmIChhW3Bvc2l0aW9uXS52YWx1ZSA+IGJbcG9zaXRpb25dLnZhbHVlKSB7XG4gICAgICAgIHJldHVybiAxO1xuICAgICAgfVxuXG4gICAgICByZXR1cm4gMDtcbiAgICB9IGVsc2Uge1xuICAgICAgaWYgKGFbcG9zaXRpb25dIDwgYltwb3NpdGlvbl0pIHtcbiAgICAgICAgcmV0dXJuIC0xO1xuICAgICAgfVxuXG4gICAgICBpZiAoYVtwb3NpdGlvbl0gPiBiW3Bvc2l0aW9uXSkge1xuICAgICAgICByZXR1cm4gMTtcbiAgICAgIH1cblxuICAgICAgcmV0dXJuIDA7XG4gICAgfVxuICB9KTtcblxuICByZXR1cm4gU3BlY2lhbEZvcm1zJDEubGlzdCguLi5uZXdfbGlzdCk7XG59O1xuXG5MaXN0LmtleXN0b3JlID0gZnVuY3Rpb24gKGxpc3QsIGtleSwgcG9zaXRpb24sIG5ld190dXBsZSkge1xuICBsZXQgbmV3X2xpc3QgPSBbXTtcbiAgbGV0IHJlcGxhY2VkID0gZmFsc2U7XG5cbiAgZm9yIChsZXQgaSA9IDA7IGkgPCBsaXN0Lmxlbmd0aDsgaSsrKSB7XG4gICAgaWYgKCFLZXJuZWwubWF0Y2hfX3FtYXJrX18obGlzdFtpXVtwb3NpdGlvbl0sIGtleSkpIHtcbiAgICAgIG5ld19saXN0LnB1c2gobGlzdFtpXSk7XG4gICAgfSBlbHNlIHtcbiAgICAgIG5ld19saXN0LnB1c2gobmV3X3R1cGxlKTtcbiAgICAgIHJlcGxhY2VkID0gdHJ1ZTtcbiAgICB9XG4gIH1cblxuICBpZiAoIXJlcGxhY2VkKSB7XG4gICAgbmV3X2xpc3QucHVzaChuZXdfdHVwbGUpO1xuICB9XG5cbiAgcmV0dXJuIFNwZWNpYWxGb3JtcyQxLmxpc3QoLi4ubmV3X2xpc3QpO1xufTtcblxuTGlzdC5sYXN0ID0gZnVuY3Rpb24gKGxpc3QpIHtcbiAgcmV0dXJuIGxpc3RbbGlzdC5sZW5ndGggLSAxXTtcbn07XG5cbkxpc3QucmVwbGFjZV9hdCA9IGZ1bmN0aW9uIChsaXN0LCBpbmRleCwgdmFsdWUpIHtcbiAgbGV0IG5ld192YWx1ZSA9IFtdO1xuXG4gIGZvciAobGV0IGkgPSAwOyBpIDwgbGlzdC5sZW5ndGg7IGkrKykge1xuICAgIGlmIChpID09PSBpbmRleCkge1xuICAgICAgbmV3X3ZhbHVlLnB1c2godmFsdWUpO1xuICAgIH0gZWxzZSB7XG4gICAgICBuZXdfdmFsdWUucHVzaChsaXN0W2ldKTtcbiAgICB9XG4gIH1cblxuICByZXR1cm4gU3BlY2lhbEZvcm1zJDEubGlzdCguLi5uZXdfdmFsdWUpO1xufTtcblxuTGlzdC51cGRhdGVfYXQgPSBmdW5jdGlvbiAobGlzdCwgaW5kZXgsIGZ1bikge1xuICBsZXQgbmV3X3ZhbHVlID0gW107XG5cbiAgZm9yIChsZXQgaSA9IDA7IGkgPCBsaXN0LmNvdW50KCk7IGkrKykge1xuICAgIGlmIChpID09PSBpbmRleCkge1xuICAgICAgbmV3X3ZhbHVlLnB1c2goZnVuKGxpc3QuZ2V0KGkpKSk7XG4gICAgfSBlbHNlIHtcbiAgICAgIG5ld192YWx1ZS5wdXNoKGxpc3QuZ2V0KGkpKTtcbiAgICB9XG4gIH1cblxuICByZXR1cm4gbmV3X3ZhbHVlO1xufTtcblxuTGlzdC53cmFwID0gZnVuY3Rpb24gKGxpc3QpIHtcbiAgaWYgKEtlcm5lbC5pc19saXN0KGxpc3QpKSB7XG4gICAgcmV0dXJuIGxpc3Q7XG4gIH0gZWxzZSBpZiAobGlzdCA9PSBudWxsKSB7XG4gICAgcmV0dXJuIFNwZWNpYWxGb3JtcyQxLmxpc3QoKTtcbiAgfSBlbHNlIHtcbiAgICByZXR1cm4gU3BlY2lhbEZvcm1zJDEubGlzdChsaXN0KTtcbiAgfVxufTtcblxuTGlzdC56aXAgPSBmdW5jdGlvbiAobGlzdF9vZl9saXN0cykge1xuICBpZiAobGlzdF9vZl9saXN0cy5sZW5ndGggPT09IDApIHtcbiAgICByZXR1cm4gU3BlY2lhbEZvcm1zJDEubGlzdCgpO1xuICB9XG5cbiAgbGV0IG5ld192YWx1ZSA9IFtdO1xuICBsZXQgc21hbGxlc3RfbGVuZ3RoID0gbGlzdF9vZl9saXN0c1swXTtcblxuICBmb3IgKGxldCB4IG9mIGxpc3Rfb2ZfbGlzdHMpIHtcbiAgICBpZiAoeC5sZW5ndGggPCBzbWFsbGVzdF9sZW5ndGgpIHtcbiAgICAgIHNtYWxsZXN0X2xlbmd0aCA9IHgubGVuZ3RoO1xuICAgIH1cbiAgfVxuXG4gIGZvciAobGV0IGkgPSAwOyBpIDwgc21hbGxlc3RfbGVuZ3RoOyBpKyspIHtcbiAgICBsZXQgY3VycmVudF92YWx1ZSA9IFtdO1xuICAgIGZvciAobGV0IGogPSAwOyBqIDwgbGlzdF9vZl9saXN0cy5sZW5ndGg7IGorKykge1xuICAgICAgY3VycmVudF92YWx1ZS5wdXNoKGxpc3Rfb2ZfbGlzdHNbal1baV0pO1xuICAgIH1cblxuICAgIG5ld192YWx1ZS5wdXNoKG5ldyBUdXBsZSQxKC4uLmN1cnJlbnRfdmFsdWUpKTtcbiAgfVxuXG4gIHJldHVybiBTcGVjaWFsRm9ybXMkMS5saXN0KC4uLm5ld192YWx1ZSk7XG59O1xuXG5MaXN0LnRvX3R1cGxlID0gZnVuY3Rpb24gKGxpc3QpIHtcbiAgcmV0dXJuIG5ldyBUdXBsZSQxKC4uLmxpc3QpO1xufTtcblxuTGlzdC5hcHBlbmQgPSBmdW5jdGlvbiAobGlzdCwgdmFsdWUpIHtcbiAgcmV0dXJuIFNwZWNpYWxGb3JtcyQxLmxpc3QoLi4ubGlzdC5jb25jYXQoW3ZhbHVlXSkpO1xufTtcblxuTGlzdC5wcmVwZW5kID0gZnVuY3Rpb24gKGxpc3QsIHZhbHVlKSB7XG4gIHJldHVybiBTcGVjaWFsRm9ybXMkMS5saXN0KC4uLlt2YWx1ZV0uY29uY2F0KGxpc3QpKTtcbn07XG5cbkxpc3QuY29uY2F0ID0gZnVuY3Rpb24gKGxlZnQsIHJpZ2h0KSB7XG4gIHJldHVybiBsZWZ0LmNvbmNhdChyaWdodCk7XG59O1xuXG5sZXQgS2V5d29yZCA9IHt9O1xuXG5LZXl3b3JkLmhhc19rZXlfX3FtYXJrX18gPSBmdW5jdGlvbiAoa2V5d29yZHMsIGtleSkge1xuICBmb3IgKGxldCBrZXl3b3JkIG9mIGtleXdvcmRzKSB7XG4gICAgaWYgKEtlcm5lbC5lbGVtKGtleXdvcmQsIDApID09IGtleSkge1xuICAgICAgcmV0dXJuIHRydWU7XG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIGZhbHNlO1xufTtcblxuS2V5d29yZC5nZXQgPSBmdW5jdGlvbiAoa2V5d29yZHMsIGtleSwgdGhlX2RlZmF1bHQgPSBudWxsKSB7XG4gIGZvciAobGV0IGtleXdvcmQgb2Yga2V5d29yZHMpIHtcbiAgICBpZiAoS2VybmVsLmVsZW0oa2V5d29yZCwgMCkgPT0ga2V5KSB7XG4gICAgICByZXR1cm4gS2VybmVsLmVsZW0oa2V5d29yZCwgMSk7XG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIHRoZV9kZWZhdWx0O1xufTtcblxuZnVuY3Rpb24gYm5vdChleHByKSB7XG4gIHJldHVybiB+ZXhwcjtcbn1cblxuZnVuY3Rpb24gYmFuZChsZWZ0LCByaWdodCkge1xuICByZXR1cm4gbGVmdCAmIHJpZ2h0O1xufVxuXG5mdW5jdGlvbiBib3IobGVmdCwgcmlnaHQpIHtcbiAgcmV0dXJuIGxlZnQgfCByaWdodDtcbn1cblxuZnVuY3Rpb24gYnNsKGxlZnQsIHJpZ2h0KSB7XG4gIHJldHVybiBsZWZ0IDw8IHJpZ2h0O1xufVxuXG5mdW5jdGlvbiBic3IobGVmdCwgcmlnaHQpIHtcbiAgcmV0dXJuIGxlZnQgPj4gcmlnaHQ7XG59XG5cbmZ1bmN0aW9uIGJ4b3IobGVmdCwgcmlnaHQpIHtcbiAgcmV0dXJuIGxlZnQgXiByaWdodDtcbn1cblxudmFyIGJpdHdpc2UgPSB7XG4gIGJub3QsXG4gIGJhbmQsXG4gIGJvcixcbiAgYnNsLFxuICBic3IsXG4gIGJ4b3Jcbn07XG5cbmZ1bmN0aW9uIF9fbmV3X18oKSB7XG4gIHJldHVybiBTcGVjaWFsRm9ybXMkMS5tYXAoe30pO1xufVxuXG5mdW5jdGlvbiBrZXlzKG1hcCkge1xuICByZXR1cm4gRnVuY3Rpb25zLmdldF9vYmplY3Rfa2V5cyhtYXApO1xufVxuXG5mdW5jdGlvbiBzaXplKG1hcCkge1xuICByZXR1cm4ga2V5cyhtYXApLmxlbmd0aDtcbn1cblxuZnVuY3Rpb24gdG9fbGlzdChtYXApIHtcbiAgbGV0IG1hcF9rZXlzID0ga2V5cyhtYXApO1xuICBsZXQgbGlzdCA9IFtdO1xuXG4gIGZvciAobGV0IGtleSBvZiBtYXBfa2V5cykge1xuICAgIGxpc3QucHVzaChuZXcgVHVwbGUkMShrZXksIG1hcFtrZXldKSk7XG4gIH1cblxuICByZXR1cm4gTGlzdCQxKC4uLmxpc3QpO1xufVxuXG5mdW5jdGlvbiB2YWx1ZXMobWFwKSB7XG4gIGxldCBtYXBfa2V5cyA9IGtleXMobWFwKTtcbiAgbGV0IGxpc3QgPSBbXTtcblxuICBmb3IgKGxldCBrZXkgb2YgbWFwX2tleXMpIHtcbiAgICBsaXN0LnB1c2gobWFwW2tleV0pO1xuICB9XG5cbiAgcmV0dXJuIExpc3QkMSguLi5saXN0KTtcbn1cblxuZnVuY3Rpb24gZnJvbV9zdHJ1Y3Qoc3RydWN0KSB7XG4gIGxldCBtYXAgPSBPYmplY3QuYXNzaWduKHt9LCBzdHJ1Y3QpO1xuICBkZWxldGUgbWFwW1N5bWJvbC5mb3IoXCJfX3N0cnVjdF9fXCIpXTtcblxuICByZXR1cm4gU3BlY2lhbEZvcm1zJDEubWFwKG1hcCk7XG59XG5cbmZ1bmN0aW9uIF9fZGVsZXRlX18obWFwLCBrZXkpIHtcbiAgbGV0IG5ld19tYXAgPSBPYmplY3QuYXNzaWduKHt9LCBtYXApO1xuXG4gIGRlbGV0ZSBuZXdfbWFwW2tleV07XG5cbiAgcmV0dXJuIFNwZWNpYWxGb3JtcyQxLm1hcChuZXdfbWFwKTtcbn1cblxuZnVuY3Rpb24gZXF1YWxfX3FtYXJrX18obWFwMSwgbWFwMikge1xuICByZXR1cm4gbWFwMSA9PT0gbWFwMjtcbn1cblxuZnVuY3Rpb24gZmV0Y2hfX2VtYXJrX18obWFwLCBrZXkpIHtcbiAgaWYgKGtleSBpbiBtYXApIHtcbiAgICByZXR1cm4gbWFwW2tleV07XG4gIH1cblxuICB0aHJvdyBuZXcgRXJyb3IoXCJLZXkgbm90IGZvdW5kLlwiKTtcbn1cblxuZnVuY3Rpb24gZmV0Y2gobWFwLCBrZXkpIHtcbiAgaWYgKGtleSBpbiBtYXApIHtcbiAgICByZXR1cm4gbmV3IFR1cGxlJDEoU3ltYm9sLmZvcihcIm9rXCIpLCBtYXBba2V5XSk7XG4gIH1cblxuICByZXR1cm4gU3ltYm9sLmZvcihcImVycm9yXCIpO1xufVxuXG5mdW5jdGlvbiBoYXNfa2V5X19xbWFya19fKG1hcCwga2V5KSB7XG4gIHJldHVybiBrZXkgaW4gbWFwO1xufVxuXG5mdW5jdGlvbiBzcGxpdChtYXAsIGtleXMpIHtcbiAgbGV0IHNwbGl0MSA9IHt9O1xuICBsZXQgc3BsaXQyID0ge307XG5cbiAgZm9yIChsZXQga2V5IG9mIEZ1bmN0aW9ucy5nZXRfb2JqZWN0X2tleXMobWFwKSkge1xuICAgIGlmIChrZXlzLmluZGV4T2Yoa2V5KSA+IC0xKSB7XG4gICAgICBzcGxpdDFba2V5XSA9IG1hcFtrZXldO1xuICAgIH0gZWxzZSB7XG4gICAgICBzcGxpdDJba2V5XSA9IG1hcFtrZXldO1xuICAgIH1cbiAgfVxuXG4gIHJldHVybiBuZXcgVHVwbGUkMShTcGVjaWFsRm9ybXMkMS5tYXAoc3BsaXQxKSwgU3BlY2lhbEZvcm1zJDEubWFwKHNwbGl0MikpO1xufVxuXG5mdW5jdGlvbiB0YWtlKG1hcCwga2V5cykge1xuICBsZXQgc3BsaXQxID0ge307XG5cbiAgZm9yIChsZXQga2V5IG9mIEZ1bmN0aW9ucy5nZXRfb2JqZWN0X2tleXMobWFwKSkge1xuICAgIGlmIChrZXlzLmluZGV4T2Yoa2V5KSA+IC0xKSB7XG4gICAgICBzcGxpdDFba2V5XSA9IG1hcFtrZXldO1xuICAgIH1cbiAgfVxuXG4gIHJldHVybiBTcGVjaWFsRm9ybXMkMS5tYXAoc3BsaXQxKTtcbn1cblxuZnVuY3Rpb24gZHJvcChtYXAsIGtleXMpIHtcbiAgbGV0IHNwbGl0MSA9IHt9O1xuXG4gIGZvciAobGV0IGtleSBvZiBGdW5jdGlvbnMuZ2V0X29iamVjdF9rZXlzKG1hcCkpIHtcbiAgICBpZiAoa2V5cy5pbmRleE9mKGtleSkgPT09IC0xKSB7XG4gICAgICBzcGxpdDFba2V5XSA9IG1hcFtrZXldO1xuICAgIH1cbiAgfVxuXG4gIHJldHVybiBTcGVjaWFsRm9ybXMkMS5tYXAoc3BsaXQxKTtcbn1cblxuZnVuY3Rpb24gcHV0X25ldyhtYXAsIGtleSwgdmFsdWUpIHtcbiAgaWYgKGtleSBpbiBtYXApIHtcbiAgICByZXR1cm4gbWFwO1xuICB9XG5cbiAgbGV0IG5ld19tYXAgPSBPYmplY3QuYXNzaWduKHt9LCBtYXApO1xuICBuZXdfbWFwW2tleV0gPSB2YWx1ZTtcblxuICByZXR1cm4gU3BlY2lhbEZvcm1zJDEubWFwKG5ld19tYXApO1xufVxuXG5mdW5jdGlvbiBwdXRfbmV3X2xhenkobWFwLCBrZXksIGZ1bikge1xuICBpZiAoa2V5IGluIG1hcCkge1xuICAgIHJldHVybiBtYXA7XG4gIH1cblxuICBsZXQgbmV3X21hcCA9IE9iamVjdC5hc3NpZ24oe30sIG1hcCk7XG4gIG5ld19tYXBba2V5XSA9IGZ1bigpO1xuXG4gIHJldHVybiBTcGVjaWFsRm9ybXMkMS5tYXAobmV3X21hcCk7XG59XG5cbmZ1bmN0aW9uIGdldF9hbmRfdXBkYXRlKG1hcCwga2V5LCBmdW4pIHtcbiAgaWYgKGtleSBpbiBtYXApIHtcbiAgICByZXR1cm4gbWFwO1xuICB9XG5cbiAgbGV0IG5ld19tYXAgPSBPYmplY3QuYXNzaWduKHt9LCBtYXApO1xuICBuZXdfbWFwW2tleV0gPSBmdW4obWFwW2tleV0pO1xuXG4gIHJldHVybiBTcGVjaWFsRm9ybXMkMS5tYXAobmV3X21hcCk7XG59XG5cbmZ1bmN0aW9uIHBvcF9sYXp5KG1hcCwga2V5LCBmdW4pIHtcbiAgaWYgKCFrZXkgaW4gbWFwKSB7XG4gICAgcmV0dXJuIG5ldyBUdXBsZSQxKGZ1bigpLCBtYXApO1xuICB9XG5cbiAgbGV0IG5ld19tYXAgPSBPYmplY3QuYXNzaWduKHt9LCBtYXApO1xuICBsZXQgdmFsdWUgPSBmdW4obmV3X21hcFtrZXldKTtcbiAgZGVsZXRlIG5ld19tYXBba2V5XTtcblxuICByZXR1cm4gbmV3IFR1cGxlJDEodmFsdWUsIG5ld19tYXApO1xufVxuXG5mdW5jdGlvbiBwb3AobWFwLCBrZXksIF9kZWZhdWx0ID0gbnVsbCkge1xuICBpZiAoIWtleSBpbiBtYXApIHtcbiAgICByZXR1cm4gbmV3IFR1cGxlJDEoX2RlZmF1bHQsIG1hcCk7XG4gIH1cblxuICBsZXQgbmV3X21hcCA9IE9iamVjdC5hc3NpZ24oe30sIG1hcCk7XG4gIGxldCB2YWx1ZSA9IG5ld19tYXBba2V5XTtcbiAgZGVsZXRlIG5ld19tYXBba2V5XTtcblxuICByZXR1cm4gbmV3IFR1cGxlJDEodmFsdWUsIG5ld19tYXApO1xufVxuXG5mdW5jdGlvbiBnZXRfbGF6eShtYXAsIGtleSwgZnVuKSB7XG4gIGlmICgha2V5IGluIG1hcCkge1xuICAgIHJldHVybiBmdW4oKTtcbiAgfVxuXG4gIHJldHVybiBmdW4obWFwW2tleV0pO1xufVxuXG5mdW5jdGlvbiBnZXQobWFwLCBrZXksIF9kZWZhdWx0ID0gbnVsbCkge1xuICBpZiAoIWtleSBpbiBtYXApIHtcbiAgICByZXR1cm4gX2RlZmF1bHQ7XG4gIH1cblxuICByZXR1cm4gbWFwW2tleV07XG59XG5cbmZ1bmN0aW9uIHB1dChtYXAsIGtleSwgdmFsKSB7XG4gIGxldCBuZXdfbWFwID0gT2JqZWN0KHt9LCBtYXApO1xuICBuZXdfbWFwW2tleV0gPSB2YWw7XG5cbiAgcmV0dXJuIFNwZWNpYWxGb3JtcyQxLm1hcChuZXdfbWFwKTtcbn1cblxuZnVuY3Rpb24gdXBkYXRlX19lbWFya19fKG1hcCwga2V5LCBmdW4pIHtcbiAgaWYgKCFrZXkgaW4gbWFwKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKFwiS2V5IG5vdCBmb3VuZFwiKTtcbiAgfVxuXG4gIGxldCBuZXdfbWFwID0gT2JqZWN0KHt9LCBtYXApO1xuICBuZXdfbWFwW2tleV0gPSBmdW4obWFwW2tleV0pO1xuXG4gIHJldHVybiBTcGVjaWFsRm9ybXMkMS5tYXAobmV3X21hcCk7XG59XG5cbmZ1bmN0aW9uIHVwZGF0ZShtYXAsIGtleSwgaW5pdGlhbCwgZnVuKSB7XG4gIGxldCBuZXdfbWFwID0gT2JqZWN0KHt9LCBtYXApO1xuXG4gIGlmICgha2V5IGluIG1hcCkge1xuICAgIG5ld19tYXBba2V5XSA9IGluaXRpYWw7XG4gIH0gZWxzZSB7XG4gICAgbmV3X21hcFtrZXldID0gZnVuKG1hcFtrZXldKTtcbiAgfVxuXG4gIHJldHVybiBTcGVjaWFsRm9ybXMkMS5tYXAobmV3X21hcCk7XG59XG5cbnZhciBtYXAgPSB7XG4gIG5ldzogX19uZXdfXyxcbiAga2V5cyxcbiAgc2l6ZSxcbiAgdG9fbGlzdCxcbiAgdmFsdWVzLFxuICBmcm9tX3N0cnVjdCxcbiAgZGVsZXRlOiBfX2RlbGV0ZV9fLFxuICBkcm9wLFxuICBlcXVhbF9fcW1hcmtfXyxcbiAgZmV0Y2hfX2VtYXJrX18sXG4gIGZldGNoLFxuICBoYXNfa2V5X19xbWFya19fLFxuICBzcGxpdCxcbiAgdGFrZSxcbiAgcHV0X25ldyxcbiAgcHV0X25ld19sYXp5LFxuICBnZXRfYW5kX3VwZGF0ZSxcbiAgcG9wX2xhenksXG4gIHBvcCxcbiAgZ2V0X2xhenksXG4gIGdldCxcbiAgcHV0LFxuICB1cGRhdGVfX2VtYXJrX18sXG4gIHVwZGF0ZVxufTtcblxuZnVuY3Rpb24gX19uZXdfXyQxKCkge1xuICByZXR1cm4gU3BlY2lhbEZvcm1zJDEubWFwKHsgW1N5bWJvbC5mb3IoJ19fc3RydWN0X18nKV06IFN5bWJvbC5mb3IoJ01hcFNldCcpLCBzZXQ6IExpc3QkMSgpIH0pO1xufVxuXG5mdW5jdGlvbiBzaXplJDEobWFwKSB7XG4gIHJldHVybiBtYXAuc2V0Lmxlbmd0aDtcbn1cblxuZnVuY3Rpb24gdG9fbGlzdCQxKG1hcCkge1xuICByZXR1cm4gbWFwLnNldDtcbn1cblxuZnVuY3Rpb24gX19kZWxldGVfXyQxKHNldCwgdGVybSkge1xuICBsZXQgbmV3X2xpc3QgPSBMaXN0LmRlbGV0ZShzZXQuc2V0LCB0ZXJtKTtcblxuICBsZXQgbmV3X21hcCA9IE9iamVjdC5hc3NpZ24oe30sIHNldCk7XG4gIG5ld19tYXAuc2V0ID0gbmV3X2xpc3Q7XG4gIHJldHVybiBTcGVjaWFsRm9ybXMkMS5tYXAobmV3X21hcCk7XG59XG5cbmZ1bmN0aW9uIHB1dCQxKHNldCwgdGVybSkge1xuICBpZiAoc2V0LnNldC5pbmRleE9mKHRlcm0pID09PSAtMSkge1xuICAgIGxldCBuZXdfbGlzdCA9IExpc3QuYXBwZW5kKHNldC5zZXQsIHRlcm0pO1xuXG4gICAgbGV0IG5ld19tYXAgPSBPYmplY3QuYXNzaWduKHt9LCBzZXQpO1xuICAgIG5ld19tYXAuc2V0ID0gbmV3X2xpc3Q7XG4gICAgcmV0dXJuIFNwZWNpYWxGb3JtcyQxLm1hcChuZXdfbWFwKTtcbiAgfVxuXG4gIHJldHVybiBzZXQ7XG59XG5cbmZ1bmN0aW9uIGRpZmZlcmVuY2Uoc2V0MSwgc2V0Mikge1xuICBsZXQgbmV3X21hcCA9IE9iamVjdC5hc3NpZ24oe30sIHNldDEpO1xuXG4gIGZvciAobGV0IHZhbCBvZiBzZXQxLnNldCkge1xuICAgIGlmIChtZW1iZXJfX3FtYXJrX18oc2V0MiwgdmFsKSkge1xuICAgICAgbmV3X21hcC5zZXQgPSBMaXN0LmRlbGV0ZShuZXdfbWFwLnNldCwgdmFsKTtcbiAgICB9XG4gIH1cblxuICByZXR1cm4gU3BlY2lhbEZvcm1zJDEubWFwKG5ld19tYXApO1xufVxuXG5mdW5jdGlvbiBpbnRlcnNlY3Rpb24oc2V0MSwgc2V0Mikge1xuICBsZXQgbmV3X21hcCA9IE9iamVjdC5hc3NpZ24oe30sIHNldDEpO1xuXG4gIGZvciAobGV0IHZhbCBvZiBzZXQxLnNldCkge1xuICAgIGlmICghbWVtYmVyX19xbWFya19fKHNldDIsIHZhbCkpIHtcbiAgICAgIG5ld19tYXAuc2V0ID0gTGlzdC5kZWxldGUobmV3X21hcC5zZXQsIHZhbCk7XG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIFNwZWNpYWxGb3JtcyQxLm1hcChuZXdfbWFwKTtcbn1cblxuZnVuY3Rpb24gdW5pb24oc2V0MSwgc2V0Mikge1xuICBsZXQgbmV3X21hcCA9IHNldDE7XG5cbiAgZm9yIChsZXQgdmFsIG9mIHNldDIuc2V0KSB7XG4gICAgbmV3X21hcCA9IHB1dCQxKG5ld19tYXAsIHZhbCk7XG4gIH1cblxuICByZXR1cm4gU3BlY2lhbEZvcm1zJDEubWFwKG5ld19tYXApO1xufVxuXG5mdW5jdGlvbiBkaXNqb2luX19xbWFya19fKHNldDEsIHNldDIpIHtcbiAgZm9yIChsZXQgdmFsIG9mIHNldDEuc2V0KSB7XG4gICAgaWYgKG1lbWJlcl9fcW1hcmtfXyhzZXQyLCB2YWwpKSB7XG4gICAgICByZXR1cm4gZmFsc2U7XG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIHRydWU7XG59XG5cbmZ1bmN0aW9uIG1lbWJlcl9fcW1hcmtfXyhzZXQsIHZhbHVlKSB7XG4gIHJldHVybiBzZXQuc2V0LmluZGV4T2YodmFsdWUpID49IDA7XG59XG5cbmZ1bmN0aW9uIGVxdWFsX19xbWFya19fJDEoc2V0MSwgc2V0Mikge1xuICByZXR1cm4gc2V0MS5zZXQgPT09IHNldDIuc2V0O1xufVxuXG5mdW5jdGlvbiBzdWJzZXRfX3FtYXJrX18oc2V0MSwgc2V0Mikge1xuICBmb3IgKGxldCB2YWwgb2Ygc2V0MS5zZXQpIHtcbiAgICBpZiAoIW1lbWJlcl9fcW1hcmtfXyhzZXQyLCB2YWwpKSB7XG4gICAgICByZXR1cm4gZmFsc2U7XG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIHRydWU7XG59XG5cbnZhciBtYXBfc2V0ID0ge1xuICBuZXc6IF9fbmV3X18kMSxcbiAgc2l6ZTogc2l6ZSQxLFxuICB0b19saXN0OiB0b19saXN0JDEsXG4gIGRpc2pvaW5fX3FtYXJrX18sXG4gIGRlbGV0ZTogX19kZWxldGVfXyQxLFxuICBzdWJzZXRfX3FtYXJrX18sXG4gIGVxdWFsX19xbWFya19fOiBlcXVhbF9fcW1hcmtfXyQxLFxuICBtZW1iZXJfX3FtYXJrX18sXG4gIHB1dDogcHV0JDEsXG4gIHVuaW9uLFxuICBpbnRlcnNlY3Rpb24sXG4gIGRpZmZlcmVuY2Vcbn07XG5cbmxldCBWaXJ0dWFsRE9NID0gKGZ1bmN0aW9uIChlKSB7XG4gICAgcmV0dXJuIGUoKTtcbn0pKGZ1bmN0aW9uICgpIHtcbiAgICB2YXIgZGVmaW5lLCBtb2R1bGUsIGV4cG9ydHM7XG4gICAgcmV0dXJuIChmdW5jdGlvbiBlKHQsIG4sIHIpIHtcbiAgICAgICAgZnVuY3Rpb24gcyhvLCB1KSB7XG4gICAgICAgICAgICBpZiAoIW5bb10pIHtcbiAgICAgICAgICAgICAgICBpZiAoIXRbb10pIHtcbiAgICAgICAgICAgICAgICAgICAgdmFyIGEgPSB0eXBlb2YgcmVxdWlyZSA9PSBcImZ1bmN0aW9uXCIgJiYgcmVxdWlyZTtcbiAgICAgICAgICAgICAgICAgICAgaWYgKCF1ICYmIGEpIHJldHVybiBhKG8sICEwKTtcbiAgICAgICAgICAgICAgICAgICAgaWYgKGkpIHJldHVybiBpKG8sICEwKTtcbiAgICAgICAgICAgICAgICAgICAgdmFyIGYgPSBuZXcgRXJyb3IoXCJDYW5ub3QgZmluZCBtb2R1bGUgJ1wiICsgbyArIFwiJ1wiKTtcbiAgICAgICAgICAgICAgICAgICAgdGhyb3cgKGYuY29kZSA9IFwiTU9EVUxFX05PVF9GT1VORFwiLCBmKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgdmFyIGwgPSBuW29dID0ge1xuICAgICAgICAgICAgICAgICAgICBleHBvcnRzOiB7fVxuICAgICAgICAgICAgICAgIH07XG4gICAgICAgICAgICAgICAgdFtvXVswXS5jYWxsKGwuZXhwb3J0cywgZnVuY3Rpb24gKGUpIHtcbiAgICAgICAgICAgICAgICAgICAgdmFyIG4gPSB0W29dWzFdW2VdO1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gcyhuID8gbiA6IGUpO1xuICAgICAgICAgICAgICAgIH0sIGwsIGwuZXhwb3J0cywgZSwgdCwgbiwgcik7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXR1cm4gbltvXS5leHBvcnRzO1xuICAgICAgICB9XG4gICAgICAgIHZhciBpID0gdHlwZW9mIHJlcXVpcmUgPT0gXCJmdW5jdGlvblwiICYmIHJlcXVpcmU7XG4gICAgICAgIGZvciAodmFyIG8gPSAwOyBvIDwgci5sZW5ndGg7IG8rKykgcyhyW29dKTtcbiAgICAgICAgcmV0dXJuIHM7XG4gICAgfSkoe1xuICAgICAgICAxOiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge1xuXG4gICAgICAgICAgICB2YXIgY3JlYXRlRWxlbWVudCA9IHJlcXVpcmUoXCIuL3Zkb20vY3JlYXRlLWVsZW1lbnQuanNcIik7XG5cbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gY3JlYXRlRWxlbWVudDtcbiAgICAgICAgfSwgeyBcIi4vdmRvbS9jcmVhdGUtZWxlbWVudC5qc1wiOiAxNSB9XSwgMjogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHtcbiAgICAgICAgICAgIHZhciBkaWZmID0gcmVxdWlyZShcIi4vdnRyZWUvZGlmZi5qc1wiKTtcblxuICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBkaWZmO1xuICAgICAgICB9LCB7IFwiLi92dHJlZS9kaWZmLmpzXCI6IDM1IH1dLCAzOiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge1xuICAgICAgICAgICAgdmFyIGggPSByZXF1aXJlKFwiLi92aXJ0dWFsLWh5cGVyc2NyaXB0L2luZGV4LmpzXCIpO1xuXG4gICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IGg7XG4gICAgICAgIH0sIHsgXCIuL3ZpcnR1YWwtaHlwZXJzY3JpcHQvaW5kZXguanNcIjogMjIgfV0sIDQ6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICB2YXIgZGlmZiA9IHJlcXVpcmUoXCIuL2RpZmYuanNcIik7XG4gICAgICAgICAgICB2YXIgcGF0Y2ggPSByZXF1aXJlKFwiLi9wYXRjaC5qc1wiKTtcbiAgICAgICAgICAgIHZhciBoID0gcmVxdWlyZShcIi4vaC5qc1wiKTtcbiAgICAgICAgICAgIHZhciBjcmVhdGUgPSByZXF1aXJlKFwiLi9jcmVhdGUtZWxlbWVudC5qc1wiKTtcbiAgICAgICAgICAgIHZhciBWTm9kZSA9IHJlcXVpcmUoXCIuL3Zub2RlL3Zub2RlLmpzXCIpO1xuICAgICAgICAgICAgdmFyIFZUZXh0ID0gcmVxdWlyZShcIi4vdm5vZGUvdnRleHQuanNcIik7XG5cbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0ge1xuICAgICAgICAgICAgICAgIGRpZmY6IGRpZmYsXG4gICAgICAgICAgICAgICAgcGF0Y2g6IHBhdGNoLFxuICAgICAgICAgICAgICAgIGg6IGgsXG4gICAgICAgICAgICAgICAgY3JlYXRlOiBjcmVhdGUsXG4gICAgICAgICAgICAgICAgVk5vZGU6IFZOb2RlLFxuICAgICAgICAgICAgICAgIFZUZXh0OiBWVGV4dFxuICAgICAgICAgICAgfTtcbiAgICAgICAgfSwgeyBcIi4vY3JlYXRlLWVsZW1lbnQuanNcIjogMSwgXCIuL2RpZmYuanNcIjogMiwgXCIuL2guanNcIjogMywgXCIuL3BhdGNoLmpzXCI6IDEzLCBcIi4vdm5vZGUvdm5vZGUuanNcIjogMzEsIFwiLi92bm9kZS92dGV4dC5qc1wiOiAzMyB9XSwgNTogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHtcbiAgICAgICAgICAgIC8qIVxuICAgICAgICAgICAgICogQ3Jvc3MtQnJvd3NlciBTcGxpdCAxLjEuMVxuICAgICAgICAgICAgICogQ29weXJpZ2h0IDIwMDctMjAxMiBTdGV2ZW4gTGV2aXRoYW4gPHN0ZXZlbmxldml0aGFuLmNvbT5cbiAgICAgICAgICAgICAqIEF2YWlsYWJsZSB1bmRlciB0aGUgTUlUIExpY2Vuc2VcbiAgICAgICAgICAgICAqIEVDTUFTY3JpcHQgY29tcGxpYW50LCB1bmlmb3JtIGNyb3NzLWJyb3dzZXIgc3BsaXQgbWV0aG9kXG4gICAgICAgICAgICAgKi9cblxuICAgICAgICAgICAgLyoqXG4gICAgICAgICAgICAgKiBTcGxpdHMgYSBzdHJpbmcgaW50byBhbiBhcnJheSBvZiBzdHJpbmdzIHVzaW5nIGEgcmVnZXggb3Igc3RyaW5nIHNlcGFyYXRvci4gTWF0Y2hlcyBvZiB0aGVcbiAgICAgICAgICAgICAqIHNlcGFyYXRvciBhcmUgbm90IGluY2x1ZGVkIGluIHRoZSByZXN1bHQgYXJyYXkuIEhvd2V2ZXIsIGlmIGBzZXBhcmF0b3JgIGlzIGEgcmVnZXggdGhhdCBjb250YWluc1xuICAgICAgICAgICAgICogY2FwdHVyaW5nIGdyb3VwcywgYmFja3JlZmVyZW5jZXMgYXJlIHNwbGljZWQgaW50byB0aGUgcmVzdWx0IGVhY2ggdGltZSBgc2VwYXJhdG9yYCBpcyBtYXRjaGVkLlxuICAgICAgICAgICAgICogRml4ZXMgYnJvd3NlciBidWdzIGNvbXBhcmVkIHRvIHRoZSBuYXRpdmUgYFN0cmluZy5wcm90b3R5cGUuc3BsaXRgIGFuZCBjYW4gYmUgdXNlZCByZWxpYWJseVxuICAgICAgICAgICAgICogY3Jvc3MtYnJvd3Nlci5cbiAgICAgICAgICAgICAqIEBwYXJhbSB7U3RyaW5nfSBzdHIgU3RyaW5nIHRvIHNwbGl0LlxuICAgICAgICAgICAgICogQHBhcmFtIHtSZWdFeHB8U3RyaW5nfSBzZXBhcmF0b3IgUmVnZXggb3Igc3RyaW5nIHRvIHVzZSBmb3Igc2VwYXJhdGluZyB0aGUgc3RyaW5nLlxuICAgICAgICAgICAgICogQHBhcmFtIHtOdW1iZXJ9IFtsaW1pdF0gTWF4aW11bSBudW1iZXIgb2YgaXRlbXMgdG8gaW5jbHVkZSBpbiB0aGUgcmVzdWx0IGFycmF5LlxuICAgICAgICAgICAgICogQHJldHVybnMge0FycmF5fSBBcnJheSBvZiBzdWJzdHJpbmdzLlxuICAgICAgICAgICAgICogQGV4YW1wbGVcbiAgICAgICAgICAgICAqXG4gICAgICAgICAgICAgKiAvLyBCYXNpYyB1c2VcbiAgICAgICAgICAgICAqIHNwbGl0KCdhIGIgYyBkJywgJyAnKTtcbiAgICAgICAgICAgICAqIC8vIC0+IFsnYScsICdiJywgJ2MnLCAnZCddXG4gICAgICAgICAgICAgKlxuICAgICAgICAgICAgICogLy8gV2l0aCBsaW1pdFxuICAgICAgICAgICAgICogc3BsaXQoJ2EgYiBjIGQnLCAnICcsIDIpO1xuICAgICAgICAgICAgICogLy8gLT4gWydhJywgJ2InXVxuICAgICAgICAgICAgICpcbiAgICAgICAgICAgICAqIC8vIEJhY2tyZWZlcmVuY2VzIGluIHJlc3VsdCBhcnJheVxuICAgICAgICAgICAgICogc3BsaXQoJy4ud29yZDEgd29yZDIuLicsIC8oW2Etel0rKShcXGQrKS9pKTtcbiAgICAgICAgICAgICAqIC8vIC0+IFsnLi4nLCAnd29yZCcsICcxJywgJyAnLCAnd29yZCcsICcyJywgJy4uJ11cbiAgICAgICAgICAgICAqL1xuICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSAoZnVuY3Rpb24gc3BsaXQodW5kZWYpIHtcblxuICAgICAgICAgICAgICAgIHZhciBuYXRpdmVTcGxpdCA9IFN0cmluZy5wcm90b3R5cGUuc3BsaXQsXG4gICAgICAgICAgICAgICAgICAgIGNvbXBsaWFudEV4ZWNOcGNnID0gLygpPz8vLmV4ZWMoXCJcIilbMV0gPT09IHVuZGVmLFxuXG4gICAgICAgICAgICAgICAgLy8gTlBDRzogbm9ucGFydGljaXBhdGluZyBjYXB0dXJpbmcgZ3JvdXBcbiAgICAgICAgICAgICAgICBzZWxmO1xuXG4gICAgICAgICAgICAgICAgc2VsZiA9IGZ1bmN0aW9uIChzdHIsIHNlcGFyYXRvciwgbGltaXQpIHtcbiAgICAgICAgICAgICAgICAgICAgLy8gSWYgYHNlcGFyYXRvcmAgaXMgbm90IGEgcmVnZXgsIHVzZSBgbmF0aXZlU3BsaXRgXG4gICAgICAgICAgICAgICAgICAgIGlmIChPYmplY3QucHJvdG90eXBlLnRvU3RyaW5nLmNhbGwoc2VwYXJhdG9yKSAhPT0gXCJbb2JqZWN0IFJlZ0V4cF1cIikge1xuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIG5hdGl2ZVNwbGl0LmNhbGwoc3RyLCBzZXBhcmF0b3IsIGxpbWl0KTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB2YXIgb3V0cHV0ID0gW10sXG4gICAgICAgICAgICAgICAgICAgICAgICBmbGFncyA9IChzZXBhcmF0b3IuaWdub3JlQ2FzZSA/IFwiaVwiIDogXCJcIikgKyAoc2VwYXJhdG9yLm11bHRpbGluZSA/IFwibVwiIDogXCJcIikgKyAoc2VwYXJhdG9yLmV4dGVuZGVkID8gXCJ4XCIgOiBcIlwiKSArIChzZXBhcmF0b3Iuc3RpY2t5ID8gXCJ5XCIgOiBcIlwiKSxcblxuICAgICAgICAgICAgICAgICAgICAvLyBGaXJlZm94IDMrXG4gICAgICAgICAgICAgICAgICAgIGxhc3RMYXN0SW5kZXggPSAwLFxuXG4gICAgICAgICAgICAgICAgICAgIC8vIE1ha2UgYGdsb2JhbGAgYW5kIGF2b2lkIGBsYXN0SW5kZXhgIGlzc3VlcyBieSB3b3JraW5nIHdpdGggYSBjb3B5XG4gICAgICAgICAgICAgICAgICAgIHNlcGFyYXRvciA9IG5ldyBSZWdFeHAoc2VwYXJhdG9yLnNvdXJjZSwgZmxhZ3MgKyBcImdcIiksXG4gICAgICAgICAgICAgICAgICAgICAgICBzZXBhcmF0b3IyLFxuICAgICAgICAgICAgICAgICAgICAgICAgbWF0Y2gsXG4gICAgICAgICAgICAgICAgICAgICAgICBsYXN0SW5kZXgsXG4gICAgICAgICAgICAgICAgICAgICAgICBsYXN0TGVuZ3RoO1xuICAgICAgICAgICAgICAgICAgICBzdHIgKz0gXCJcIjsgLy8gVHlwZS1jb252ZXJ0XG4gICAgICAgICAgICAgICAgICAgIGlmICghY29tcGxpYW50RXhlY05wY2cpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIERvZXNuJ3QgbmVlZCBmbGFncyBneSwgYnV0IHRoZXkgZG9uJ3QgaHVydFxuICAgICAgICAgICAgICAgICAgICAgICAgc2VwYXJhdG9yMiA9IG5ldyBSZWdFeHAoXCJeXCIgKyBzZXBhcmF0b3Iuc291cmNlICsgXCIkKD8hXFxcXHMpXCIsIGZsYWdzKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAvKiBWYWx1ZXMgZm9yIGBsaW1pdGAsIHBlciB0aGUgc3BlYzpcbiAgICAgICAgICAgICAgICAgICAgICogSWYgdW5kZWZpbmVkOiA0Mjk0OTY3Mjk1IC8vIE1hdGgucG93KDIsIDMyKSAtIDFcbiAgICAgICAgICAgICAgICAgICAgICogSWYgMCwgSW5maW5pdHksIG9yIE5hTjogMFxuICAgICAgICAgICAgICAgICAgICAgKiBJZiBwb3NpdGl2ZSBudW1iZXI6IGxpbWl0ID0gTWF0aC5mbG9vcihsaW1pdCk7IGlmIChsaW1pdCA+IDQyOTQ5NjcyOTUpIGxpbWl0IC09IDQyOTQ5NjcyOTY7XG4gICAgICAgICAgICAgICAgICAgICAqIElmIG5lZ2F0aXZlIG51bWJlcjogNDI5NDk2NzI5NiAtIE1hdGguZmxvb3IoTWF0aC5hYnMobGltaXQpKVxuICAgICAgICAgICAgICAgICAgICAgKiBJZiBvdGhlcjogVHlwZS1jb252ZXJ0LCB0aGVuIHVzZSB0aGUgYWJvdmUgcnVsZXNcbiAgICAgICAgICAgICAgICAgICAgICovXG4gICAgICAgICAgICAgICAgICAgIGxpbWl0ID0gbGltaXQgPT09IHVuZGVmID8gLTEgPj4+IDAgOiAvLyBNYXRoLnBvdygyLCAzMikgLSAxXG4gICAgICAgICAgICAgICAgICAgIGxpbWl0ID4+PiAwOyAvLyBUb1VpbnQzMihsaW1pdClcbiAgICAgICAgICAgICAgICAgICAgd2hpbGUgKG1hdGNoID0gc2VwYXJhdG9yLmV4ZWMoc3RyKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgLy8gYHNlcGFyYXRvci5sYXN0SW5kZXhgIGlzIG5vdCByZWxpYWJsZSBjcm9zcy1icm93c2VyXG4gICAgICAgICAgICAgICAgICAgICAgICBsYXN0SW5kZXggPSBtYXRjaC5pbmRleCArIG1hdGNoWzBdLmxlbmd0aDtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChsYXN0SW5kZXggPiBsYXN0TGFzdEluZGV4KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgb3V0cHV0LnB1c2goc3RyLnNsaWNlKGxhc3RMYXN0SW5kZXgsIG1hdGNoLmluZGV4KSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gRml4IGJyb3dzZXJzIHdob3NlIGBleGVjYCBtZXRob2RzIGRvbid0IGNvbnNpc3RlbnRseSByZXR1cm4gYHVuZGVmaW5lZGAgZm9yXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gbm9ucGFydGljaXBhdGluZyBjYXB0dXJpbmcgZ3JvdXBzXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKCFjb21wbGlhbnRFeGVjTnBjZyAmJiBtYXRjaC5sZW5ndGggPiAxKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1hdGNoWzBdLnJlcGxhY2Uoc2VwYXJhdG9yMiwgZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZm9yICh2YXIgaSA9IDE7IGkgPCBhcmd1bWVudHMubGVuZ3RoIC0gMjsgaSsrKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGFyZ3VtZW50c1tpXSA9PT0gdW5kZWYpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbWF0Y2hbaV0gPSB1bmRlZjtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAobWF0Y2gubGVuZ3RoID4gMSAmJiBtYXRjaC5pbmRleCA8IHN0ci5sZW5ndGgpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgQXJyYXkucHJvdG90eXBlLnB1c2guYXBwbHkob3V0cHV0LCBtYXRjaC5zbGljZSgxKSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxhc3RMZW5ndGggPSBtYXRjaFswXS5sZW5ndGg7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgbGFzdExhc3RJbmRleCA9IGxhc3RJbmRleDtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAob3V0cHV0Lmxlbmd0aCA+PSBsaW1pdCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoc2VwYXJhdG9yLmxhc3RJbmRleCA9PT0gbWF0Y2guaW5kZXgpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBzZXBhcmF0b3IubGFzdEluZGV4Kys7IC8vIEF2b2lkIGFuIGluZmluaXRlIGxvb3BcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICBpZiAobGFzdExhc3RJbmRleCA9PT0gc3RyLmxlbmd0aCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGxhc3RMZW5ndGggfHwgIXNlcGFyYXRvci50ZXN0KFwiXCIpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgb3V0cHV0LnB1c2goXCJcIik7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBvdXRwdXQucHVzaChzdHIuc2xpY2UobGFzdExhc3RJbmRleCkpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBvdXRwdXQubGVuZ3RoID4gbGltaXQgPyBvdXRwdXQuc2xpY2UoMCwgbGltaXQpIDogb3V0cHV0O1xuICAgICAgICAgICAgICAgIH07XG5cbiAgICAgICAgICAgICAgICByZXR1cm4gc2VsZjtcbiAgICAgICAgICAgIH0pKCk7XG4gICAgICAgIH0sIHt9XSwgNjogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHt9LCB7fV0sIDc6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICBcInVzZSBzdHJpY3RcIjtcblxuICAgICAgICAgICAgdmFyIE9uZVZlcnNpb25Db25zdHJhaW50ID0gcmVxdWlyZShcImluZGl2aWR1YWwvb25lLXZlcnNpb25cIik7XG5cbiAgICAgICAgICAgIHZhciBNWV9WRVJTSU9OID0gXCI3XCI7XG4gICAgICAgICAgICBPbmVWZXJzaW9uQ29uc3RyYWludChcImV2LXN0b3JlXCIsIE1ZX1ZFUlNJT04pO1xuXG4gICAgICAgICAgICB2YXIgaGFzaEtleSA9IFwiX19FVl9TVE9SRV9LRVlAXCIgKyBNWV9WRVJTSU9OO1xuXG4gICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IEV2U3RvcmU7XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIEV2U3RvcmUoZWxlbSkge1xuICAgICAgICAgICAgICAgIHZhciBoYXNoID0gZWxlbVtoYXNoS2V5XTtcblxuICAgICAgICAgICAgICAgIGlmICghaGFzaCkge1xuICAgICAgICAgICAgICAgICAgICBoYXNoID0gZWxlbVtoYXNoS2V5XSA9IHt9O1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHJldHVybiBoYXNoO1xuICAgICAgICAgICAgfVxuICAgICAgICB9LCB7IFwiaW5kaXZpZHVhbC9vbmUtdmVyc2lvblwiOiA5IH1dLCA4OiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge1xuICAgICAgICAgICAgKGZ1bmN0aW9uIChnbG9iYWwpIHtcbiAgICAgICAgICAgICAgICBcInVzZSBzdHJpY3RcIjtcblxuICAgICAgICAgICAgICAgIC8qZ2xvYmFsIHdpbmRvdywgZ2xvYmFsKi9cblxuICAgICAgICAgICAgICAgIHZhciByb290ID0gdHlwZW9mIHdpbmRvdyAhPT0gXCJ1bmRlZmluZWRcIiA/IHdpbmRvdyA6IHR5cGVvZiBnbG9iYWwgIT09IFwidW5kZWZpbmVkXCIgPyBnbG9iYWwgOiB7fTtcblxuICAgICAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gSW5kaXZpZHVhbDtcblxuICAgICAgICAgICAgICAgIGZ1bmN0aW9uIEluZGl2aWR1YWwoa2V5LCB2YWx1ZSkge1xuICAgICAgICAgICAgICAgICAgICBpZiAoa2V5IGluIHJvb3QpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiByb290W2tleV07XG4gICAgICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgICAgICByb290W2tleV0gPSB2YWx1ZTtcblxuICAgICAgICAgICAgICAgICAgICByZXR1cm4gdmFsdWU7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSkuY2FsbCh0aGlzLCB0eXBlb2YgZ2xvYmFsICE9PSBcInVuZGVmaW5lZFwiID8gZ2xvYmFsIDogdHlwZW9mIHNlbGYgIT09IFwidW5kZWZpbmVkXCIgPyBzZWxmIDogdHlwZW9mIHdpbmRvdyAhPT0gXCJ1bmRlZmluZWRcIiA/IHdpbmRvdyA6IHt9KTtcbiAgICAgICAgfSwge31dLCA5OiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge1xuICAgICAgICAgICAgXCJ1c2Ugc3RyaWN0XCI7XG5cbiAgICAgICAgICAgIHZhciBJbmRpdmlkdWFsID0gcmVxdWlyZShcIi4vaW5kZXguanNcIik7XG5cbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gT25lVmVyc2lvbjtcblxuICAgICAgICAgICAgZnVuY3Rpb24gT25lVmVyc2lvbihtb2R1bGVOYW1lLCB2ZXJzaW9uLCBkZWZhdWx0VmFsdWUpIHtcbiAgICAgICAgICAgICAgICB2YXIga2V5ID0gXCJfX0lORElWSURVQUxfT05FX1ZFUlNJT05fXCIgKyBtb2R1bGVOYW1lO1xuICAgICAgICAgICAgICAgIHZhciBlbmZvcmNlS2V5ID0ga2V5ICsgXCJfRU5GT1JDRV9TSU5HTEVUT05cIjtcblxuICAgICAgICAgICAgICAgIHZhciB2ZXJzaW9uVmFsdWUgPSBJbmRpdmlkdWFsKGVuZm9yY2VLZXksIHZlcnNpb24pO1xuXG4gICAgICAgICAgICAgICAgaWYgKHZlcnNpb25WYWx1ZSAhPT0gdmVyc2lvbikge1xuICAgICAgICAgICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoXCJDYW4gb25seSBoYXZlIG9uZSBjb3B5IG9mIFwiICsgbW9kdWxlTmFtZSArIFwiLlxcblwiICsgXCJZb3UgYWxyZWFkeSBoYXZlIHZlcnNpb24gXCIgKyB2ZXJzaW9uVmFsdWUgKyBcIiBpbnN0YWxsZWQuXFxuXCIgKyBcIlRoaXMgbWVhbnMgeW91IGNhbm5vdCBpbnN0YWxsIHZlcnNpb24gXCIgKyB2ZXJzaW9uKTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICByZXR1cm4gSW5kaXZpZHVhbChrZXksIGRlZmF1bHRWYWx1ZSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0sIHsgXCIuL2luZGV4LmpzXCI6IDggfV0sIDEwOiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge1xuICAgICAgICAgICAgKGZ1bmN0aW9uIChnbG9iYWwpIHtcbiAgICAgICAgICAgICAgICB2YXIgdG9wTGV2ZWwgPSB0eXBlb2YgZ2xvYmFsICE9PSBcInVuZGVmaW5lZFwiID8gZ2xvYmFsIDogdHlwZW9mIHdpbmRvdyAhPT0gXCJ1bmRlZmluZWRcIiA/IHdpbmRvdyA6IHt9O1xuICAgICAgICAgICAgICAgIHZhciBtaW5Eb2MgPSByZXF1aXJlKFwibWluLWRvY3VtZW50XCIpO1xuXG4gICAgICAgICAgICAgICAgaWYgKHR5cGVvZiBkb2N1bWVudCAhPT0gXCJ1bmRlZmluZWRcIikge1xuICAgICAgICAgICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IGRvY3VtZW50O1xuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciBkb2NjeSA9IHRvcExldmVsW1wiX19HTE9CQUxfRE9DVU1FTlRfQ0FDSEVANFwiXTtcblxuICAgICAgICAgICAgICAgICAgICBpZiAoIWRvY2N5KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBkb2NjeSA9IHRvcExldmVsW1wiX19HTE9CQUxfRE9DVU1FTlRfQ0FDSEVANFwiXSA9IG1pbkRvYztcbiAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gZG9jY3k7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSkuY2FsbCh0aGlzLCB0eXBlb2YgZ2xvYmFsICE9PSBcInVuZGVmaW5lZFwiID8gZ2xvYmFsIDogdHlwZW9mIHNlbGYgIT09IFwidW5kZWZpbmVkXCIgPyBzZWxmIDogdHlwZW9mIHdpbmRvdyAhPT0gXCJ1bmRlZmluZWRcIiA/IHdpbmRvdyA6IHt9KTtcbiAgICAgICAgfSwgeyBcIm1pbi1kb2N1bWVudFwiOiA2IH1dLCAxMTogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHtcbiAgICAgICAgICAgIFwidXNlIHN0cmljdFwiO1xuXG4gICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uIGlzT2JqZWN0KHgpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gdHlwZW9mIHggPT09IFwib2JqZWN0XCIgJiYgeCAhPT0gbnVsbDtcbiAgICAgICAgICAgIH07XG4gICAgICAgIH0sIHt9XSwgMTI6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICB2YXIgbmF0aXZlSXNBcnJheSA9IEFycmF5LmlzQXJyYXk7XG4gICAgICAgICAgICB2YXIgdG9TdHJpbmcgPSBPYmplY3QucHJvdG90eXBlLnRvU3RyaW5nO1xuXG4gICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IG5hdGl2ZUlzQXJyYXkgfHwgaXNBcnJheTtcblxuICAgICAgICAgICAgZnVuY3Rpb24gaXNBcnJheShvYmopIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gdG9TdHJpbmcuY2FsbChvYmopID09PSBcIltvYmplY3QgQXJyYXldXCI7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0sIHt9XSwgMTM6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICB2YXIgcGF0Y2ggPSByZXF1aXJlKFwiLi92ZG9tL3BhdGNoLmpzXCIpO1xuXG4gICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IHBhdGNoO1xuICAgICAgICB9LCB7IFwiLi92ZG9tL3BhdGNoLmpzXCI6IDE4IH1dLCAxNDogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHtcbiAgICAgICAgICAgIHZhciBpc09iamVjdCA9IHJlcXVpcmUoXCJpcy1vYmplY3RcIik7XG4gICAgICAgICAgICB2YXIgaXNIb29rID0gcmVxdWlyZShcIi4uL3Zub2RlL2lzLXZob29rLmpzXCIpO1xuXG4gICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IGFwcGx5UHJvcGVydGllcztcblxuICAgICAgICAgICAgZnVuY3Rpb24gYXBwbHlQcm9wZXJ0aWVzKG5vZGUsIHByb3BzLCBwcmV2aW91cykge1xuICAgICAgICAgICAgICAgIGZvciAodmFyIHByb3BOYW1lIGluIHByb3BzKSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciBwcm9wVmFsdWUgPSBwcm9wc1twcm9wTmFtZV07XG5cbiAgICAgICAgICAgICAgICAgICAgaWYgKHByb3BWYWx1ZSA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICByZW1vdmVQcm9wZXJ0eShub2RlLCBwcm9wTmFtZSwgcHJvcFZhbHVlLCBwcmV2aW91cyk7XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoaXNIb29rKHByb3BWYWx1ZSkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJlbW92ZVByb3BlcnR5KG5vZGUsIHByb3BOYW1lLCBwcm9wVmFsdWUsIHByZXZpb3VzKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChwcm9wVmFsdWUuaG9vaykge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHByb3BWYWx1ZS5ob29rKG5vZGUsIHByb3BOYW1lLCBwcmV2aW91cyA/IHByZXZpb3VzW3Byb3BOYW1lXSA6IHVuZGVmaW5lZCk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoaXNPYmplY3QocHJvcFZhbHVlKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHBhdGNoT2JqZWN0KG5vZGUsIHByb3BzLCBwcmV2aW91cywgcHJvcE5hbWUsIHByb3BWYWx1ZSk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIG5vZGVbcHJvcE5hbWVdID0gcHJvcFZhbHVlO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBmdW5jdGlvbiByZW1vdmVQcm9wZXJ0eShub2RlLCBwcm9wTmFtZSwgcHJvcFZhbHVlLCBwcmV2aW91cykge1xuICAgICAgICAgICAgICAgIGlmIChwcmV2aW91cykge1xuICAgICAgICAgICAgICAgICAgICB2YXIgcHJldmlvdXNWYWx1ZSA9IHByZXZpb3VzW3Byb3BOYW1lXTtcblxuICAgICAgICAgICAgICAgICAgICBpZiAoIWlzSG9vayhwcmV2aW91c1ZhbHVlKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHByb3BOYW1lID09PSBcImF0dHJpYnV0ZXNcIikge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZvciAodmFyIGF0dHJOYW1lIGluIHByZXZpb3VzVmFsdWUpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbm9kZS5yZW1vdmVBdHRyaWJ1dGUoYXR0ck5hbWUpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAocHJvcE5hbWUgPT09IFwic3R5bGVcIikge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZvciAodmFyIGkgaW4gcHJldmlvdXNWYWx1ZSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBub2RlLnN0eWxlW2ldID0gXCJcIjtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKHR5cGVvZiBwcmV2aW91c1ZhbHVlID09PSBcInN0cmluZ1wiKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgbm9kZVtwcm9wTmFtZV0gPSBcIlwiO1xuICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBub2RlW3Byb3BOYW1lXSA9IG51bGw7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAocHJldmlvdXNWYWx1ZS51bmhvb2spIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHByZXZpb3VzVmFsdWUudW5ob29rKG5vZGUsIHByb3BOYW1lLCBwcm9wVmFsdWUpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBmdW5jdGlvbiBwYXRjaE9iamVjdChub2RlLCBwcm9wcywgcHJldmlvdXMsIHByb3BOYW1lLCBwcm9wVmFsdWUpIHtcbiAgICAgICAgICAgICAgICB2YXIgcHJldmlvdXNWYWx1ZSA9IHByZXZpb3VzID8gcHJldmlvdXNbcHJvcE5hbWVdIDogdW5kZWZpbmVkO1xuXG4gICAgICAgICAgICAgICAgLy8gU2V0IGF0dHJpYnV0ZXNcbiAgICAgICAgICAgICAgICBpZiAocHJvcE5hbWUgPT09IFwiYXR0cmlidXRlc1wiKSB7XG4gICAgICAgICAgICAgICAgICAgIGZvciAodmFyIGF0dHJOYW1lIGluIHByb3BWYWx1ZSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgdmFyIGF0dHJWYWx1ZSA9IHByb3BWYWx1ZVthdHRyTmFtZV07XG5cbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChhdHRyVmFsdWUgPT09IHVuZGVmaW5lZCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIG5vZGUucmVtb3ZlQXR0cmlidXRlKGF0dHJOYW1lKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgbm9kZS5zZXRBdHRyaWJ1dGUoYXR0ck5hbWUsIGF0dHJWYWx1ZSk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgaWYgKHByZXZpb3VzVmFsdWUgJiYgaXNPYmplY3QocHJldmlvdXNWYWx1ZSkgJiYgZ2V0UHJvdG90eXBlKHByZXZpb3VzVmFsdWUpICE9PSBnZXRQcm90b3R5cGUocHJvcFZhbHVlKSkge1xuICAgICAgICAgICAgICAgICAgICBub2RlW3Byb3BOYW1lXSA9IHByb3BWYWx1ZTtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIGlmICghaXNPYmplY3Qobm9kZVtwcm9wTmFtZV0pKSB7XG4gICAgICAgICAgICAgICAgICAgIG5vZGVbcHJvcE5hbWVdID0ge307XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgdmFyIHJlcGxhY2VyID0gcHJvcE5hbWUgPT09IFwic3R5bGVcIiA/IFwiXCIgOiB1bmRlZmluZWQ7XG5cbiAgICAgICAgICAgICAgICBmb3IgKHZhciBrIGluIHByb3BWYWx1ZSkge1xuICAgICAgICAgICAgICAgICAgICB2YXIgdmFsdWUgPSBwcm9wVmFsdWVba107XG4gICAgICAgICAgICAgICAgICAgIG5vZGVbcHJvcE5hbWVdW2tdID0gdmFsdWUgPT09IHVuZGVmaW5lZCA/IHJlcGxhY2VyIDogdmFsdWU7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBmdW5jdGlvbiBnZXRQcm90b3R5cGUodmFsdWUpIHtcbiAgICAgICAgICAgICAgICBpZiAoT2JqZWN0LmdldFByb3RvdHlwZU9mKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBPYmplY3QuZ2V0UHJvdG90eXBlT2YodmFsdWUpO1xuICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAodmFsdWUuX19wcm90b19fKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiB2YWx1ZS5fX3Byb3RvX187XG4gICAgICAgICAgICAgICAgfSBlbHNlIGlmICh2YWx1ZS5jb25zdHJ1Y3Rvcikge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gdmFsdWUuY29uc3RydWN0b3IucHJvdG90eXBlO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgfSwgeyBcIi4uL3Zub2RlL2lzLXZob29rLmpzXCI6IDI2LCBcImlzLW9iamVjdFwiOiAxMSB9XSwgMTU6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICB2YXIgZG9jdW1lbnQgPSByZXF1aXJlKFwiZ2xvYmFsL2RvY3VtZW50XCIpO1xuXG4gICAgICAgICAgICB2YXIgYXBwbHlQcm9wZXJ0aWVzID0gcmVxdWlyZShcIi4vYXBwbHktcHJvcGVydGllc1wiKTtcblxuICAgICAgICAgICAgdmFyIGlzVk5vZGUgPSByZXF1aXJlKFwiLi4vdm5vZGUvaXMtdm5vZGUuanNcIik7XG4gICAgICAgICAgICB2YXIgaXNWVGV4dCA9IHJlcXVpcmUoXCIuLi92bm9kZS9pcy12dGV4dC5qc1wiKTtcbiAgICAgICAgICAgIHZhciBpc1dpZGdldCA9IHJlcXVpcmUoXCIuLi92bm9kZS9pcy13aWRnZXQuanNcIik7XG4gICAgICAgICAgICB2YXIgaGFuZGxlVGh1bmsgPSByZXF1aXJlKFwiLi4vdm5vZGUvaGFuZGxlLXRodW5rLmpzXCIpO1xuXG4gICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IGNyZWF0ZUVsZW1lbnQ7XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIGNyZWF0ZUVsZW1lbnQodm5vZGUsIG9wdHMpIHtcbiAgICAgICAgICAgICAgICB2YXIgZG9jID0gb3B0cyA/IG9wdHMuZG9jdW1lbnQgfHwgZG9jdW1lbnQgOiBkb2N1bWVudDtcbiAgICAgICAgICAgICAgICB2YXIgd2FybiA9IG9wdHMgPyBvcHRzLndhcm4gOiBudWxsO1xuXG4gICAgICAgICAgICAgICAgdm5vZGUgPSBoYW5kbGVUaHVuayh2bm9kZSkuYTtcblxuICAgICAgICAgICAgICAgIGlmIChpc1dpZGdldCh2bm9kZSkpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHZub2RlLmluaXQoKTtcbiAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKGlzVlRleHQodm5vZGUpKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBkb2MuY3JlYXRlVGV4dE5vZGUodm5vZGUudGV4dCk7XG4gICAgICAgICAgICAgICAgfSBlbHNlIGlmICghaXNWTm9kZSh2bm9kZSkpIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKHdhcm4pIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHdhcm4oXCJJdGVtIGlzIG5vdCBhIHZhbGlkIHZpcnR1YWwgZG9tIG5vZGVcIiwgdm5vZGUpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBudWxsO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHZhciBub2RlID0gdm5vZGUubmFtZXNwYWNlID09PSBudWxsID8gZG9jLmNyZWF0ZUVsZW1lbnQodm5vZGUudGFnTmFtZSkgOiBkb2MuY3JlYXRlRWxlbWVudE5TKHZub2RlLm5hbWVzcGFjZSwgdm5vZGUudGFnTmFtZSk7XG5cbiAgICAgICAgICAgICAgICB2YXIgcHJvcHMgPSB2bm9kZS5wcm9wZXJ0aWVzO1xuICAgICAgICAgICAgICAgIGFwcGx5UHJvcGVydGllcyhub2RlLCBwcm9wcyk7XG5cbiAgICAgICAgICAgICAgICB2YXIgY2hpbGRyZW4gPSB2bm9kZS5jaGlsZHJlbjtcblxuICAgICAgICAgICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgY2hpbGRyZW4ubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgICAgICAgICAgdmFyIGNoaWxkTm9kZSA9IGNyZWF0ZUVsZW1lbnQoY2hpbGRyZW5baV0sIG9wdHMpO1xuICAgICAgICAgICAgICAgICAgICBpZiAoY2hpbGROb2RlKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBub2RlLmFwcGVuZENoaWxkKGNoaWxkTm9kZSk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICByZXR1cm4gbm9kZTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSwgeyBcIi4uL3Zub2RlL2hhbmRsZS10aHVuay5qc1wiOiAyNCwgXCIuLi92bm9kZS9pcy12bm9kZS5qc1wiOiAyNywgXCIuLi92bm9kZS9pcy12dGV4dC5qc1wiOiAyOCwgXCIuLi92bm9kZS9pcy13aWRnZXQuanNcIjogMjksIFwiLi9hcHBseS1wcm9wZXJ0aWVzXCI6IDE0LCBcImdsb2JhbC9kb2N1bWVudFwiOiAxMCB9XSwgMTY6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICAvLyBNYXBzIGEgdmlydHVhbCBET00gdHJlZSBvbnRvIGEgcmVhbCBET00gdHJlZSBpbiBhbiBlZmZpY2llbnQgbWFubmVyLlxuICAgICAgICAgICAgLy8gV2UgZG9uJ3Qgd2FudCB0byByZWFkIGFsbCBvZiB0aGUgRE9NIG5vZGVzIGluIHRoZSB0cmVlIHNvIHdlIHVzZVxuICAgICAgICAgICAgLy8gdGhlIGluLW9yZGVyIHRyZWUgaW5kZXhpbmcgdG8gZWxpbWluYXRlIHJlY3Vyc2lvbiBkb3duIGNlcnRhaW4gYnJhbmNoZXMuXG4gICAgICAgICAgICAvLyBXZSBvbmx5IHJlY3Vyc2UgaW50byBhIERPTSBub2RlIGlmIHdlIGtub3cgdGhhdCBpdCBjb250YWlucyBhIGNoaWxkIG9mXG4gICAgICAgICAgICAvLyBpbnRlcmVzdC5cblxuICAgICAgICAgICAgdmFyIG5vQ2hpbGQgPSB7fTtcblxuICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBkb21JbmRleDtcblxuICAgICAgICAgICAgZnVuY3Rpb24gZG9tSW5kZXgocm9vdE5vZGUsIHRyZWUsIGluZGljZXMsIG5vZGVzKSB7XG4gICAgICAgICAgICAgICAgaWYgKCFpbmRpY2VzIHx8IGluZGljZXMubGVuZ3RoID09PSAwKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiB7fTtcbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICBpbmRpY2VzLnNvcnQoYXNjZW5kaW5nKTtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHJlY3Vyc2Uocm9vdE5vZGUsIHRyZWUsIGluZGljZXMsIG5vZGVzLCAwKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIHJlY3Vyc2Uocm9vdE5vZGUsIHRyZWUsIGluZGljZXMsIG5vZGVzLCByb290SW5kZXgpIHtcbiAgICAgICAgICAgICAgICBub2RlcyA9IG5vZGVzIHx8IHt9O1xuXG4gICAgICAgICAgICAgICAgaWYgKHJvb3ROb2RlKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmIChpbmRleEluUmFuZ2UoaW5kaWNlcywgcm9vdEluZGV4LCByb290SW5kZXgpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBub2Rlc1tyb290SW5kZXhdID0gcm9vdE5vZGU7XG4gICAgICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgICAgICB2YXIgdkNoaWxkcmVuID0gdHJlZS5jaGlsZHJlbjtcblxuICAgICAgICAgICAgICAgICAgICBpZiAodkNoaWxkcmVuKSB7XG5cbiAgICAgICAgICAgICAgICAgICAgICAgIHZhciBjaGlsZE5vZGVzID0gcm9vdE5vZGUuY2hpbGROb2RlcztcblxuICAgICAgICAgICAgICAgICAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCB0cmVlLmNoaWxkcmVuLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcm9vdEluZGV4ICs9IDE7XG5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB2YXIgdkNoaWxkID0gdkNoaWxkcmVuW2ldIHx8IG5vQ2hpbGQ7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdmFyIG5leHRJbmRleCA9IHJvb3RJbmRleCArICh2Q2hpbGQuY291bnQgfHwgMCk7XG5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBza2lwIHJlY3Vyc2lvbiBkb3duIHRoZSB0cmVlIGlmIHRoZXJlIGFyZSBubyBub2RlcyBkb3duIGhlcmVcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoaW5kZXhJblJhbmdlKGluZGljZXMsIHJvb3RJbmRleCwgbmV4dEluZGV4KSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICByZWN1cnNlKGNoaWxkTm9kZXNbaV0sIHZDaGlsZCwgaW5kaWNlcywgbm9kZXMsIHJvb3RJbmRleCk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcm9vdEluZGV4ID0gbmV4dEluZGV4O1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgcmV0dXJuIG5vZGVzO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAvLyBCaW5hcnkgc2VhcmNoIGZvciBhbiBpbmRleCBpbiB0aGUgaW50ZXJ2YWwgW2xlZnQsIHJpZ2h0XVxuICAgICAgICAgICAgZnVuY3Rpb24gaW5kZXhJblJhbmdlKGluZGljZXMsIGxlZnQsIHJpZ2h0KSB7XG4gICAgICAgICAgICAgICAgaWYgKGluZGljZXMubGVuZ3RoID09PSAwKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICB2YXIgbWluSW5kZXggPSAwO1xuICAgICAgICAgICAgICAgIHZhciBtYXhJbmRleCA9IGluZGljZXMubGVuZ3RoIC0gMTtcbiAgICAgICAgICAgICAgICB2YXIgY3VycmVudEluZGV4O1xuICAgICAgICAgICAgICAgIHZhciBjdXJyZW50SXRlbTtcblxuICAgICAgICAgICAgICAgIHdoaWxlIChtaW5JbmRleCA8PSBtYXhJbmRleCkge1xuICAgICAgICAgICAgICAgICAgICBjdXJyZW50SW5kZXggPSAobWF4SW5kZXggKyBtaW5JbmRleCkgLyAyID4+IDA7XG4gICAgICAgICAgICAgICAgICAgIGN1cnJlbnRJdGVtID0gaW5kaWNlc1tjdXJyZW50SW5kZXhdO1xuXG4gICAgICAgICAgICAgICAgICAgIGlmIChtaW5JbmRleCA9PT0gbWF4SW5kZXgpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBjdXJyZW50SXRlbSA+PSBsZWZ0ICYmIGN1cnJlbnRJdGVtIDw9IHJpZ2h0O1xuICAgICAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKGN1cnJlbnRJdGVtIDwgbGVmdCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgbWluSW5kZXggPSBjdXJyZW50SW5kZXggKyAxO1xuICAgICAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKGN1cnJlbnRJdGVtID4gcmlnaHQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIG1heEluZGV4ID0gY3VycmVudEluZGV4IC0gMTtcbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBmdW5jdGlvbiBhc2NlbmRpbmcoYSwgYikge1xuICAgICAgICAgICAgICAgIHJldHVybiBhID4gYiA/IDEgOiAtMTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSwge31dLCAxNzogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHtcbiAgICAgICAgICAgIHZhciBhcHBseVByb3BlcnRpZXMgPSByZXF1aXJlKFwiLi9hcHBseS1wcm9wZXJ0aWVzXCIpO1xuXG4gICAgICAgICAgICB2YXIgaXNXaWRnZXQgPSByZXF1aXJlKFwiLi4vdm5vZGUvaXMtd2lkZ2V0LmpzXCIpO1xuICAgICAgICAgICAgdmFyIFZQYXRjaCA9IHJlcXVpcmUoXCIuLi92bm9kZS92cGF0Y2guanNcIik7XG5cbiAgICAgICAgICAgIHZhciB1cGRhdGVXaWRnZXQgPSByZXF1aXJlKFwiLi91cGRhdGUtd2lkZ2V0XCIpO1xuXG4gICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IGFwcGx5UGF0Y2g7XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIGFwcGx5UGF0Y2godnBhdGNoLCBkb21Ob2RlLCByZW5kZXJPcHRpb25zKSB7XG4gICAgICAgICAgICAgICAgdmFyIHR5cGUgPSB2cGF0Y2gudHlwZTtcbiAgICAgICAgICAgICAgICB2YXIgdk5vZGUgPSB2cGF0Y2gudk5vZGU7XG4gICAgICAgICAgICAgICAgdmFyIHBhdGNoID0gdnBhdGNoLnBhdGNoO1xuXG4gICAgICAgICAgICAgICAgc3dpdGNoICh0eXBlKSB7XG4gICAgICAgICAgICAgICAgICAgIGNhc2UgVlBhdGNoLlJFTU9WRTpcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiByZW1vdmVOb2RlKGRvbU5vZGUsIHZOb2RlKTtcbiAgICAgICAgICAgICAgICAgICAgY2FzZSBWUGF0Y2guSU5TRVJUOlxuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGluc2VydE5vZGUoZG9tTm9kZSwgcGF0Y2gsIHJlbmRlck9wdGlvbnMpO1xuICAgICAgICAgICAgICAgICAgICBjYXNlIFZQYXRjaC5WVEVYVDpcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBzdHJpbmdQYXRjaChkb21Ob2RlLCB2Tm9kZSwgcGF0Y2gsIHJlbmRlck9wdGlvbnMpO1xuICAgICAgICAgICAgICAgICAgICBjYXNlIFZQYXRjaC5XSURHRVQ6XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gd2lkZ2V0UGF0Y2goZG9tTm9kZSwgdk5vZGUsIHBhdGNoLCByZW5kZXJPcHRpb25zKTtcbiAgICAgICAgICAgICAgICAgICAgY2FzZSBWUGF0Y2guVk5PREU6XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gdk5vZGVQYXRjaChkb21Ob2RlLCB2Tm9kZSwgcGF0Y2gsIHJlbmRlck9wdGlvbnMpO1xuICAgICAgICAgICAgICAgICAgICBjYXNlIFZQYXRjaC5PUkRFUjpcbiAgICAgICAgICAgICAgICAgICAgICAgIHJlb3JkZXJDaGlsZHJlbihkb21Ob2RlLCBwYXRjaCk7XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gZG9tTm9kZTtcbiAgICAgICAgICAgICAgICAgICAgY2FzZSBWUGF0Y2guUFJPUFM6XG4gICAgICAgICAgICAgICAgICAgICAgICBhcHBseVByb3BlcnRpZXMoZG9tTm9kZSwgcGF0Y2gsIHZOb2RlLnByb3BlcnRpZXMpO1xuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGRvbU5vZGU7XG4gICAgICAgICAgICAgICAgICAgIGNhc2UgVlBhdGNoLlRIVU5LOlxuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHJlcGxhY2VSb290KGRvbU5vZGUsIHJlbmRlck9wdGlvbnMucGF0Y2goZG9tTm9kZSwgcGF0Y2gsIHJlbmRlck9wdGlvbnMpKTtcbiAgICAgICAgICAgICAgICAgICAgZGVmYXVsdDpcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBkb21Ob2RlO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZnVuY3Rpb24gcmVtb3ZlTm9kZShkb21Ob2RlLCB2Tm9kZSkge1xuICAgICAgICAgICAgICAgIHZhciBwYXJlbnROb2RlID0gZG9tTm9kZS5wYXJlbnROb2RlO1xuXG4gICAgICAgICAgICAgICAgaWYgKHBhcmVudE5vZGUpIHtcbiAgICAgICAgICAgICAgICAgICAgcGFyZW50Tm9kZS5yZW1vdmVDaGlsZChkb21Ob2RlKTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICBkZXN0cm95V2lkZ2V0KGRvbU5vZGUsIHZOb2RlKTtcblxuICAgICAgICAgICAgICAgIHJldHVybiBudWxsO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBmdW5jdGlvbiBpbnNlcnROb2RlKHBhcmVudE5vZGUsIHZOb2RlLCByZW5kZXJPcHRpb25zKSB7XG4gICAgICAgICAgICAgICAgdmFyIG5ld05vZGUgPSByZW5kZXJPcHRpb25zLnJlbmRlcih2Tm9kZSwgcmVuZGVyT3B0aW9ucyk7XG5cbiAgICAgICAgICAgICAgICBpZiAocGFyZW50Tm9kZSkge1xuICAgICAgICAgICAgICAgICAgICBwYXJlbnROb2RlLmFwcGVuZENoaWxkKG5ld05vZGUpO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHJldHVybiBwYXJlbnROb2RlO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBmdW5jdGlvbiBzdHJpbmdQYXRjaChkb21Ob2RlLCBsZWZ0Vk5vZGUsIHZUZXh0LCByZW5kZXJPcHRpb25zKSB7XG4gICAgICAgICAgICAgICAgdmFyIG5ld05vZGU7XG5cbiAgICAgICAgICAgICAgICBpZiAoZG9tTm9kZS5ub2RlVHlwZSA9PT0gMykge1xuICAgICAgICAgICAgICAgICAgICBkb21Ob2RlLnJlcGxhY2VEYXRhKDAsIGRvbU5vZGUubGVuZ3RoLCB2VGV4dC50ZXh0KTtcbiAgICAgICAgICAgICAgICAgICAgbmV3Tm9kZSA9IGRvbU5vZGU7XG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgdmFyIHBhcmVudE5vZGUgPSBkb21Ob2RlLnBhcmVudE5vZGU7XG4gICAgICAgICAgICAgICAgICAgIG5ld05vZGUgPSByZW5kZXJPcHRpb25zLnJlbmRlcih2VGV4dCwgcmVuZGVyT3B0aW9ucyk7XG5cbiAgICAgICAgICAgICAgICAgICAgaWYgKHBhcmVudE5vZGUgJiYgbmV3Tm9kZSAhPT0gZG9tTm9kZSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgcGFyZW50Tm9kZS5yZXBsYWNlQ2hpbGQobmV3Tm9kZSwgZG9tTm9kZSk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICByZXR1cm4gbmV3Tm9kZTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZnVuY3Rpb24gd2lkZ2V0UGF0Y2goZG9tTm9kZSwgbGVmdFZOb2RlLCB3aWRnZXQsIHJlbmRlck9wdGlvbnMpIHtcbiAgICAgICAgICAgICAgICB2YXIgdXBkYXRpbmcgPSB1cGRhdGVXaWRnZXQobGVmdFZOb2RlLCB3aWRnZXQpO1xuICAgICAgICAgICAgICAgIHZhciBuZXdOb2RlO1xuXG4gICAgICAgICAgICAgICAgaWYgKHVwZGF0aW5nKSB7XG4gICAgICAgICAgICAgICAgICAgIG5ld05vZGUgPSB3aWRnZXQudXBkYXRlKGxlZnRWTm9kZSwgZG9tTm9kZSkgfHwgZG9tTm9kZTtcbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICBuZXdOb2RlID0gcmVuZGVyT3B0aW9ucy5yZW5kZXIod2lkZ2V0LCByZW5kZXJPcHRpb25zKTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICB2YXIgcGFyZW50Tm9kZSA9IGRvbU5vZGUucGFyZW50Tm9kZTtcblxuICAgICAgICAgICAgICAgIGlmIChwYXJlbnROb2RlICYmIG5ld05vZGUgIT09IGRvbU5vZGUpIHtcbiAgICAgICAgICAgICAgICAgICAgcGFyZW50Tm9kZS5yZXBsYWNlQ2hpbGQobmV3Tm9kZSwgZG9tTm9kZSk7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgaWYgKCF1cGRhdGluZykge1xuICAgICAgICAgICAgICAgICAgICBkZXN0cm95V2lkZ2V0KGRvbU5vZGUsIGxlZnRWTm9kZSk7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgcmV0dXJuIG5ld05vZGU7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIHZOb2RlUGF0Y2goZG9tTm9kZSwgbGVmdFZOb2RlLCB2Tm9kZSwgcmVuZGVyT3B0aW9ucykge1xuICAgICAgICAgICAgICAgIHZhciBwYXJlbnROb2RlID0gZG9tTm9kZS5wYXJlbnROb2RlO1xuICAgICAgICAgICAgICAgIHZhciBuZXdOb2RlID0gcmVuZGVyT3B0aW9ucy5yZW5kZXIodk5vZGUsIHJlbmRlck9wdGlvbnMpO1xuXG4gICAgICAgICAgICAgICAgaWYgKHBhcmVudE5vZGUgJiYgbmV3Tm9kZSAhPT0gZG9tTm9kZSkge1xuICAgICAgICAgICAgICAgICAgICBwYXJlbnROb2RlLnJlcGxhY2VDaGlsZChuZXdOb2RlLCBkb21Ob2RlKTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICByZXR1cm4gbmV3Tm9kZTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZnVuY3Rpb24gZGVzdHJveVdpZGdldChkb21Ob2RlLCB3KSB7XG4gICAgICAgICAgICAgICAgaWYgKHR5cGVvZiB3LmRlc3Ryb3kgPT09IFwiZnVuY3Rpb25cIiAmJiBpc1dpZGdldCh3KSkge1xuICAgICAgICAgICAgICAgICAgICB3LmRlc3Ryb3koZG9tTm9kZSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBmdW5jdGlvbiByZW9yZGVyQ2hpbGRyZW4oZG9tTm9kZSwgbW92ZXMpIHtcbiAgICAgICAgICAgICAgICB2YXIgY2hpbGROb2RlcyA9IGRvbU5vZGUuY2hpbGROb2RlcztcbiAgICAgICAgICAgICAgICB2YXIga2V5TWFwID0ge307XG4gICAgICAgICAgICAgICAgdmFyIG5vZGU7XG4gICAgICAgICAgICAgICAgdmFyIHJlbW92ZTtcbiAgICAgICAgICAgICAgICB2YXIgaW5zZXJ0O1xuXG4gICAgICAgICAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCBtb3Zlcy5yZW1vdmVzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICAgICAgICAgIHJlbW92ZSA9IG1vdmVzLnJlbW92ZXNbaV07XG4gICAgICAgICAgICAgICAgICAgIG5vZGUgPSBjaGlsZE5vZGVzW3JlbW92ZS5mcm9tXTtcbiAgICAgICAgICAgICAgICAgICAgaWYgKHJlbW92ZS5rZXkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGtleU1hcFtyZW1vdmUua2V5XSA9IG5vZGU7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgZG9tTm9kZS5yZW1vdmVDaGlsZChub2RlKTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICB2YXIgbGVuZ3RoID0gY2hpbGROb2Rlcy5sZW5ndGg7XG4gICAgICAgICAgICAgICAgZm9yICh2YXIgaiA9IDA7IGogPCBtb3Zlcy5pbnNlcnRzLmxlbmd0aDsgaisrKSB7XG4gICAgICAgICAgICAgICAgICAgIGluc2VydCA9IG1vdmVzLmluc2VydHNbal07XG4gICAgICAgICAgICAgICAgICAgIG5vZGUgPSBrZXlNYXBbaW5zZXJ0LmtleV07XG4gICAgICAgICAgICAgICAgICAgIC8vIHRoaXMgaXMgdGhlIHdlaXJkZXN0IGJ1ZyBpJ3ZlIGV2ZXIgc2VlbiBpbiB3ZWJraXRcbiAgICAgICAgICAgICAgICAgICAgZG9tTm9kZS5pbnNlcnRCZWZvcmUobm9kZSwgaW5zZXJ0LnRvID49IGxlbmd0aCsrID8gbnVsbCA6IGNoaWxkTm9kZXNbaW5zZXJ0LnRvXSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBmdW5jdGlvbiByZXBsYWNlUm9vdChvbGRSb290LCBuZXdSb290KSB7XG4gICAgICAgICAgICAgICAgaWYgKG9sZFJvb3QgJiYgbmV3Um9vdCAmJiBvbGRSb290ICE9PSBuZXdSb290ICYmIG9sZFJvb3QucGFyZW50Tm9kZSkge1xuICAgICAgICAgICAgICAgICAgICBvbGRSb290LnBhcmVudE5vZGUucmVwbGFjZUNoaWxkKG5ld1Jvb3QsIG9sZFJvb3QpO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHJldHVybiBuZXdSb290O1xuICAgICAgICAgICAgfVxuICAgICAgICB9LCB7IFwiLi4vdm5vZGUvaXMtd2lkZ2V0LmpzXCI6IDI5LCBcIi4uL3Zub2RlL3ZwYXRjaC5qc1wiOiAzMiwgXCIuL2FwcGx5LXByb3BlcnRpZXNcIjogMTQsIFwiLi91cGRhdGUtd2lkZ2V0XCI6IDE5IH1dLCAxODogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHtcbiAgICAgICAgICAgIHZhciBkb2N1bWVudCA9IHJlcXVpcmUoXCJnbG9iYWwvZG9jdW1lbnRcIik7XG4gICAgICAgICAgICB2YXIgaXNBcnJheSA9IHJlcXVpcmUoXCJ4LWlzLWFycmF5XCIpO1xuXG4gICAgICAgICAgICB2YXIgcmVuZGVyID0gcmVxdWlyZShcIi4vY3JlYXRlLWVsZW1lbnRcIik7XG4gICAgICAgICAgICB2YXIgZG9tSW5kZXggPSByZXF1aXJlKFwiLi9kb20taW5kZXhcIik7XG4gICAgICAgICAgICB2YXIgcGF0Y2hPcCA9IHJlcXVpcmUoXCIuL3BhdGNoLW9wXCIpO1xuICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBwYXRjaDtcblxuICAgICAgICAgICAgZnVuY3Rpb24gcGF0Y2gocm9vdE5vZGUsIHBhdGNoZXMsIHJlbmRlck9wdGlvbnMpIHtcbiAgICAgICAgICAgICAgICByZW5kZXJPcHRpb25zID0gcmVuZGVyT3B0aW9ucyB8fCB7fTtcbiAgICAgICAgICAgICAgICByZW5kZXJPcHRpb25zLnBhdGNoID0gcmVuZGVyT3B0aW9ucy5wYXRjaCAmJiByZW5kZXJPcHRpb25zLnBhdGNoICE9PSBwYXRjaCA/IHJlbmRlck9wdGlvbnMucGF0Y2ggOiBwYXRjaFJlY3Vyc2l2ZTtcbiAgICAgICAgICAgICAgICByZW5kZXJPcHRpb25zLnJlbmRlciA9IHJlbmRlck9wdGlvbnMucmVuZGVyIHx8IHJlbmRlcjtcblxuICAgICAgICAgICAgICAgIHJldHVybiByZW5kZXJPcHRpb25zLnBhdGNoKHJvb3ROb2RlLCBwYXRjaGVzLCByZW5kZXJPcHRpb25zKTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZnVuY3Rpb24gcGF0Y2hSZWN1cnNpdmUocm9vdE5vZGUsIHBhdGNoZXMsIHJlbmRlck9wdGlvbnMpIHtcbiAgICAgICAgICAgICAgICB2YXIgaW5kaWNlcyA9IHBhdGNoSW5kaWNlcyhwYXRjaGVzKTtcblxuICAgICAgICAgICAgICAgIGlmIChpbmRpY2VzLmxlbmd0aCA9PT0gMCkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gcm9vdE5vZGU7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgdmFyIGluZGV4ID0gZG9tSW5kZXgocm9vdE5vZGUsIHBhdGNoZXMuYSwgaW5kaWNlcyk7XG4gICAgICAgICAgICAgICAgdmFyIG93bmVyRG9jdW1lbnQgPSByb290Tm9kZS5vd25lckRvY3VtZW50O1xuXG4gICAgICAgICAgICAgICAgaWYgKCFyZW5kZXJPcHRpb25zLmRvY3VtZW50ICYmIG93bmVyRG9jdW1lbnQgIT09IGRvY3VtZW50KSB7XG4gICAgICAgICAgICAgICAgICAgIHJlbmRlck9wdGlvbnMuZG9jdW1lbnQgPSBvd25lckRvY3VtZW50O1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgaW5kaWNlcy5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgICAgICAgICB2YXIgbm9kZUluZGV4ID0gaW5kaWNlc1tpXTtcbiAgICAgICAgICAgICAgICAgICAgcm9vdE5vZGUgPSBhcHBseVBhdGNoKHJvb3ROb2RlLCBpbmRleFtub2RlSW5kZXhdLCBwYXRjaGVzW25vZGVJbmRleF0sIHJlbmRlck9wdGlvbnMpO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHJldHVybiByb290Tm9kZTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZnVuY3Rpb24gYXBwbHlQYXRjaChyb290Tm9kZSwgZG9tTm9kZSwgcGF0Y2hMaXN0LCByZW5kZXJPcHRpb25zKSB7XG4gICAgICAgICAgICAgICAgaWYgKCFkb21Ob2RlKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiByb290Tm9kZTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICB2YXIgbmV3Tm9kZTtcblxuICAgICAgICAgICAgICAgIGlmIChpc0FycmF5KHBhdGNoTGlzdCkpIHtcbiAgICAgICAgICAgICAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCBwYXRjaExpc3QubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIG5ld05vZGUgPSBwYXRjaE9wKHBhdGNoTGlzdFtpXSwgZG9tTm9kZSwgcmVuZGVyT3B0aW9ucyk7XG5cbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChkb21Ob2RlID09PSByb290Tm9kZSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJvb3ROb2RlID0gbmV3Tm9kZTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIG5ld05vZGUgPSBwYXRjaE9wKHBhdGNoTGlzdCwgZG9tTm9kZSwgcmVuZGVyT3B0aW9ucyk7XG5cbiAgICAgICAgICAgICAgICAgICAgaWYgKGRvbU5vZGUgPT09IHJvb3ROb2RlKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICByb290Tm9kZSA9IG5ld05vZGU7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICByZXR1cm4gcm9vdE5vZGU7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIHBhdGNoSW5kaWNlcyhwYXRjaGVzKSB7XG4gICAgICAgICAgICAgICAgdmFyIGluZGljZXMgPSBbXTtcblxuICAgICAgICAgICAgICAgIGZvciAodmFyIGtleSBpbiBwYXRjaGVzKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmIChrZXkgIT09IFwiYVwiKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBpbmRpY2VzLnB1c2goTnVtYmVyKGtleSkpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgcmV0dXJuIGluZGljZXM7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0sIHsgXCIuL2NyZWF0ZS1lbGVtZW50XCI6IDE1LCBcIi4vZG9tLWluZGV4XCI6IDE2LCBcIi4vcGF0Y2gtb3BcIjogMTcsIFwiZ2xvYmFsL2RvY3VtZW50XCI6IDEwLCBcIngtaXMtYXJyYXlcIjogMTIgfV0sIDE5OiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge1xuICAgICAgICAgICAgdmFyIGlzV2lkZ2V0ID0gcmVxdWlyZShcIi4uL3Zub2RlL2lzLXdpZGdldC5qc1wiKTtcblxuICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSB1cGRhdGVXaWRnZXQ7XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIHVwZGF0ZVdpZGdldChhLCBiKSB7XG4gICAgICAgICAgICAgICAgaWYgKGlzV2lkZ2V0KGEpICYmIGlzV2lkZ2V0KGIpKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmIChcIm5hbWVcIiBpbiBhICYmIFwibmFtZVwiIGluIGIpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBhLmlkID09PSBiLmlkO1xuICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGEuaW5pdCA9PT0gYi5pbml0O1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICAgICAgfVxuICAgICAgICB9LCB7IFwiLi4vdm5vZGUvaXMtd2lkZ2V0LmpzXCI6IDI5IH1dLCAyMDogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHtcbiAgICAgICAgICAgIFwidXNlIHN0cmljdFwiO1xuXG4gICAgICAgICAgICB2YXIgRXZTdG9yZSA9IHJlcXVpcmUoXCJldi1zdG9yZVwiKTtcblxuICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBFdkhvb2s7XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIEV2SG9vayh2YWx1ZSkge1xuICAgICAgICAgICAgICAgIGlmICghKHRoaXMgaW5zdGFuY2VvZiBFdkhvb2spKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBuZXcgRXZIb29rKHZhbHVlKTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICB0aGlzLnZhbHVlID0gdmFsdWU7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIEV2SG9vay5wcm90b3R5cGUuaG9vayA9IGZ1bmN0aW9uIChub2RlLCBwcm9wZXJ0eU5hbWUpIHtcbiAgICAgICAgICAgICAgICB2YXIgZXMgPSBFdlN0b3JlKG5vZGUpO1xuICAgICAgICAgICAgICAgIHZhciBwcm9wTmFtZSA9IHByb3BlcnR5TmFtZS5zdWJzdHIoMyk7XG5cbiAgICAgICAgICAgICAgICBlc1twcm9wTmFtZV0gPSB0aGlzLnZhbHVlO1xuICAgICAgICAgICAgfTtcblxuICAgICAgICAgICAgRXZIb29rLnByb3RvdHlwZS51bmhvb2sgPSBmdW5jdGlvbiAobm9kZSwgcHJvcGVydHlOYW1lKSB7XG4gICAgICAgICAgICAgICAgdmFyIGVzID0gRXZTdG9yZShub2RlKTtcbiAgICAgICAgICAgICAgICB2YXIgcHJvcE5hbWUgPSBwcm9wZXJ0eU5hbWUuc3Vic3RyKDMpO1xuXG4gICAgICAgICAgICAgICAgZXNbcHJvcE5hbWVdID0gdW5kZWZpbmVkO1xuICAgICAgICAgICAgfTtcbiAgICAgICAgfSwgeyBcImV2LXN0b3JlXCI6IDcgfV0sIDIxOiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge1xuICAgICAgICAgICAgXCJ1c2Ugc3RyaWN0XCI7XG5cbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gU29mdFNldEhvb2s7XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIFNvZnRTZXRIb29rKHZhbHVlKSB7XG4gICAgICAgICAgICAgICAgaWYgKCEodGhpcyBpbnN0YW5jZW9mIFNvZnRTZXRIb29rKSkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gbmV3IFNvZnRTZXRIb29rKHZhbHVlKTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICB0aGlzLnZhbHVlID0gdmFsdWU7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIFNvZnRTZXRIb29rLnByb3RvdHlwZS5ob29rID0gZnVuY3Rpb24gKG5vZGUsIHByb3BlcnR5TmFtZSkge1xuICAgICAgICAgICAgICAgIGlmIChub2RlW3Byb3BlcnR5TmFtZV0gIT09IHRoaXMudmFsdWUpIHtcbiAgICAgICAgICAgICAgICAgICAgbm9kZVtwcm9wZXJ0eU5hbWVdID0gdGhpcy52YWx1ZTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9O1xuICAgICAgICB9LCB7fV0sIDIyOiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge1xuICAgICAgICAgICAgXCJ1c2Ugc3RyaWN0XCI7XG5cbiAgICAgICAgICAgIHZhciBpc0FycmF5ID0gcmVxdWlyZShcIngtaXMtYXJyYXlcIik7XG5cbiAgICAgICAgICAgIHZhciBWTm9kZSA9IHJlcXVpcmUoXCIuLi92bm9kZS92bm9kZS5qc1wiKTtcbiAgICAgICAgICAgIHZhciBWVGV4dCA9IHJlcXVpcmUoXCIuLi92bm9kZS92dGV4dC5qc1wiKTtcbiAgICAgICAgICAgIHZhciBpc1ZOb2RlID0gcmVxdWlyZShcIi4uL3Zub2RlL2lzLXZub2RlXCIpO1xuICAgICAgICAgICAgdmFyIGlzVlRleHQgPSByZXF1aXJlKFwiLi4vdm5vZGUvaXMtdnRleHRcIik7XG4gICAgICAgICAgICB2YXIgaXNXaWRnZXQgPSByZXF1aXJlKFwiLi4vdm5vZGUvaXMtd2lkZ2V0XCIpO1xuICAgICAgICAgICAgdmFyIGlzSG9vayA9IHJlcXVpcmUoXCIuLi92bm9kZS9pcy12aG9va1wiKTtcbiAgICAgICAgICAgIHZhciBpc1ZUaHVuayA9IHJlcXVpcmUoXCIuLi92bm9kZS9pcy10aHVua1wiKTtcblxuICAgICAgICAgICAgdmFyIHBhcnNlVGFnID0gcmVxdWlyZShcIi4vcGFyc2UtdGFnLmpzXCIpO1xuICAgICAgICAgICAgdmFyIHNvZnRTZXRIb29rID0gcmVxdWlyZShcIi4vaG9va3Mvc29mdC1zZXQtaG9vay5qc1wiKTtcbiAgICAgICAgICAgIHZhciBldkhvb2sgPSByZXF1aXJlKFwiLi9ob29rcy9ldi1ob29rLmpzXCIpO1xuXG4gICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IGg7XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIGgodGFnTmFtZSwgcHJvcGVydGllcywgY2hpbGRyZW4pIHtcbiAgICAgICAgICAgICAgICB2YXIgY2hpbGROb2RlcyA9IFtdO1xuICAgICAgICAgICAgICAgIHZhciB0YWcsIHByb3BzLCBrZXksIG5hbWVzcGFjZTtcblxuICAgICAgICAgICAgICAgIGlmICghY2hpbGRyZW4gJiYgaXNDaGlsZHJlbihwcm9wZXJ0aWVzKSkge1xuICAgICAgICAgICAgICAgICAgICBjaGlsZHJlbiA9IHByb3BlcnRpZXM7XG4gICAgICAgICAgICAgICAgICAgIHByb3BzID0ge307XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgcHJvcHMgPSBwcm9wcyB8fCBwcm9wZXJ0aWVzIHx8IHt9O1xuICAgICAgICAgICAgICAgIHRhZyA9IHBhcnNlVGFnKHRhZ05hbWUsIHByb3BzKTtcblxuICAgICAgICAgICAgICAgIC8vIHN1cHBvcnQga2V5c1xuICAgICAgICAgICAgICAgIGlmIChwcm9wcy5oYXNPd25Qcm9wZXJ0eShcImtleVwiKSkge1xuICAgICAgICAgICAgICAgICAgICBrZXkgPSBwcm9wcy5rZXk7XG4gICAgICAgICAgICAgICAgICAgIHByb3BzLmtleSA9IHVuZGVmaW5lZDtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAvLyBzdXBwb3J0IG5hbWVzcGFjZVxuICAgICAgICAgICAgICAgIGlmIChwcm9wcy5oYXNPd25Qcm9wZXJ0eShcIm5hbWVzcGFjZVwiKSkge1xuICAgICAgICAgICAgICAgICAgICBuYW1lc3BhY2UgPSBwcm9wcy5uYW1lc3BhY2U7XG4gICAgICAgICAgICAgICAgICAgIHByb3BzLm5hbWVzcGFjZSA9IHVuZGVmaW5lZDtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAvLyBmaXggY3Vyc29yIGJ1Z1xuICAgICAgICAgICAgICAgIGlmICh0YWcgPT09IFwiSU5QVVRcIiAmJiAhbmFtZXNwYWNlICYmIHByb3BzLmhhc093blByb3BlcnR5KFwidmFsdWVcIikgJiYgcHJvcHMudmFsdWUgIT09IHVuZGVmaW5lZCAmJiAhaXNIb29rKHByb3BzLnZhbHVlKSkge1xuICAgICAgICAgICAgICAgICAgICBwcm9wcy52YWx1ZSA9IHNvZnRTZXRIb29rKHByb3BzLnZhbHVlKTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICB0cmFuc2Zvcm1Qcm9wZXJ0aWVzKHByb3BzKTtcblxuICAgICAgICAgICAgICAgIGlmIChjaGlsZHJlbiAhPT0gdW5kZWZpbmVkICYmIGNoaWxkcmVuICE9PSBudWxsKSB7XG4gICAgICAgICAgICAgICAgICAgIGFkZENoaWxkKGNoaWxkcmVuLCBjaGlsZE5vZGVzLCB0YWcsIHByb3BzKTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICByZXR1cm4gbmV3IFZOb2RlKHRhZywgcHJvcHMsIGNoaWxkTm9kZXMsIGtleSwgbmFtZXNwYWNlKTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZnVuY3Rpb24gYWRkQ2hpbGQoYywgY2hpbGROb2RlcywgdGFnLCBwcm9wcykge1xuICAgICAgICAgICAgICAgIGlmICh0eXBlb2YgYyA9PT0gXCJzdHJpbmdcIikge1xuICAgICAgICAgICAgICAgICAgICBjaGlsZE5vZGVzLnB1c2gobmV3IFZUZXh0KGMpKTtcbiAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKHR5cGVvZiBjID09PSBcIm51bWJlclwiKSB7XG4gICAgICAgICAgICAgICAgICAgIGNoaWxkTm9kZXMucHVzaChuZXcgVlRleHQoU3RyaW5nKGMpKSk7XG4gICAgICAgICAgICAgICAgfSBlbHNlIGlmIChpc0NoaWxkKGMpKSB7XG4gICAgICAgICAgICAgICAgICAgIGNoaWxkTm9kZXMucHVzaChjKTtcbiAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKGlzQXJyYXkoYykpIHtcbiAgICAgICAgICAgICAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCBjLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBhZGRDaGlsZChjW2ldLCBjaGlsZE5vZGVzLCB0YWcsIHByb3BzKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoYyA9PT0gbnVsbCB8fCBjID09PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIHRocm93IFVuZXhwZWN0ZWRWaXJ0dWFsRWxlbWVudCh7XG4gICAgICAgICAgICAgICAgICAgICAgICBmb3JlaWduT2JqZWN0OiBjLFxuICAgICAgICAgICAgICAgICAgICAgICAgcGFyZW50Vm5vZGU6IHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0YWdOYW1lOiB0YWcsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcHJvcGVydGllczogcHJvcHNcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBmdW5jdGlvbiB0cmFuc2Zvcm1Qcm9wZXJ0aWVzKHByb3BzKSB7XG4gICAgICAgICAgICAgICAgZm9yICh2YXIgcHJvcE5hbWUgaW4gcHJvcHMpIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKHByb3BzLmhhc093blByb3BlcnR5KHByb3BOYW1lKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgdmFyIHZhbHVlID0gcHJvcHNbcHJvcE5hbWVdO1xuXG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoaXNIb29rKHZhbHVlKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnRpbnVlO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAocHJvcE5hbWUuc3Vic3RyKDAsIDMpID09PSBcImV2LVwiKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gYWRkIGV2LWZvbyBzdXBwb3J0XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcHJvcHNbcHJvcE5hbWVdID0gZXZIb29rKHZhbHVlKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZnVuY3Rpb24gaXNDaGlsZCh4KSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGlzVk5vZGUoeCkgfHwgaXNWVGV4dCh4KSB8fCBpc1dpZGdldCh4KSB8fCBpc1ZUaHVuayh4KTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZnVuY3Rpb24gaXNDaGlsZHJlbih4KSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHR5cGVvZiB4ID09PSBcInN0cmluZ1wiIHx8IGlzQXJyYXkoeCkgfHwgaXNDaGlsZCh4KTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZnVuY3Rpb24gVW5leHBlY3RlZFZpcnR1YWxFbGVtZW50KGRhdGEpIHtcbiAgICAgICAgICAgICAgICB2YXIgZXJyID0gbmV3IEVycm9yKCk7XG5cbiAgICAgICAgICAgICAgICBlcnIudHlwZSA9IFwidmlydHVhbC1oeXBlcnNjcmlwdC51bmV4cGVjdGVkLnZpcnR1YWwtZWxlbWVudFwiO1xuICAgICAgICAgICAgICAgIGVyci5tZXNzYWdlID0gXCJVbmV4cGVjdGVkIHZpcnR1YWwgY2hpbGQgcGFzc2VkIHRvIGgoKS5cXG5cIiArIFwiRXhwZWN0ZWQgYSBWTm9kZSAvIFZ0aHVuayAvIFZXaWRnZXQgLyBzdHJpbmcgYnV0OlxcblwiICsgXCJnb3Q6XFxuXCIgKyBlcnJvclN0cmluZyhkYXRhLmZvcmVpZ25PYmplY3QpICsgXCIuXFxuXCIgKyBcIlRoZSBwYXJlbnQgdm5vZGUgaXM6XFxuXCIgKyBlcnJvclN0cmluZyhkYXRhLnBhcmVudFZub2RlKTtcbiAgICAgICAgICAgICAgICBcIlxcblwiICsgXCJTdWdnZXN0ZWQgZml4OiBjaGFuZ2UgeW91ciBgaCguLi4sIFsgLi4uIF0pYCBjYWxsc2l0ZS5cIjtcbiAgICAgICAgICAgICAgICBlcnIuZm9yZWlnbk9iamVjdCA9IGRhdGEuZm9yZWlnbk9iamVjdDtcbiAgICAgICAgICAgICAgICBlcnIucGFyZW50Vm5vZGUgPSBkYXRhLnBhcmVudFZub2RlO1xuXG4gICAgICAgICAgICAgICAgcmV0dXJuIGVycjtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZnVuY3Rpb24gZXJyb3JTdHJpbmcob2JqKSB7XG4gICAgICAgICAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIEpTT04uc3RyaW5naWZ5KG9iaiwgbnVsbCwgXCIgICAgXCIpO1xuICAgICAgICAgICAgICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIFN0cmluZyhvYmopO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgfSwgeyBcIi4uL3Zub2RlL2lzLXRodW5rXCI6IDI1LCBcIi4uL3Zub2RlL2lzLXZob29rXCI6IDI2LCBcIi4uL3Zub2RlL2lzLXZub2RlXCI6IDI3LCBcIi4uL3Zub2RlL2lzLXZ0ZXh0XCI6IDI4LCBcIi4uL3Zub2RlL2lzLXdpZGdldFwiOiAyOSwgXCIuLi92bm9kZS92bm9kZS5qc1wiOiAzMSwgXCIuLi92bm9kZS92dGV4dC5qc1wiOiAzMywgXCIuL2hvb2tzL2V2LWhvb2suanNcIjogMjAsIFwiLi9ob29rcy9zb2Z0LXNldC1ob29rLmpzXCI6IDIxLCBcIi4vcGFyc2UtdGFnLmpzXCI6IDIzLCBcIngtaXMtYXJyYXlcIjogMTIgfV0sIDIzOiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge1xuICAgICAgICAgICAgXCJ1c2Ugc3RyaWN0XCI7XG5cbiAgICAgICAgICAgIHZhciBzcGxpdCA9IHJlcXVpcmUoXCJicm93c2VyLXNwbGl0XCIpO1xuXG4gICAgICAgICAgICB2YXIgY2xhc3NJZFNwbGl0ID0gLyhbXFwuI10/W2EtekEtWjAtOVxcdTAwN0YtXFx1RkZGRl86LV0rKS87XG4gICAgICAgICAgICB2YXIgbm90Q2xhc3NJZCA9IC9eXFwufCMvO1xuXG4gICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IHBhcnNlVGFnO1xuXG4gICAgICAgICAgICBmdW5jdGlvbiBwYXJzZVRhZyh0YWcsIHByb3BzKSB7XG4gICAgICAgICAgICAgICAgaWYgKCF0YWcpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIFwiRElWXCI7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgdmFyIG5vSWQgPSAhcHJvcHMuaGFzT3duUHJvcGVydHkoXCJpZFwiKTtcblxuICAgICAgICAgICAgICAgIHZhciB0YWdQYXJ0cyA9IHNwbGl0KHRhZywgY2xhc3NJZFNwbGl0KTtcbiAgICAgICAgICAgICAgICB2YXIgdGFnTmFtZSA9IG51bGw7XG5cbiAgICAgICAgICAgICAgICBpZiAobm90Q2xhc3NJZC50ZXN0KHRhZ1BhcnRzWzFdKSkge1xuICAgICAgICAgICAgICAgICAgICB0YWdOYW1lID0gXCJESVZcIjtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICB2YXIgY2xhc3NlcywgcGFydCwgdHlwZSwgaTtcblxuICAgICAgICAgICAgICAgIGZvciAoaSA9IDA7IGkgPCB0YWdQYXJ0cy5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgICAgICAgICBwYXJ0ID0gdGFnUGFydHNbaV07XG5cbiAgICAgICAgICAgICAgICAgICAgaWYgKCFwYXJ0KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBjb250aW51ZTtcbiAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgIHR5cGUgPSBwYXJ0LmNoYXJBdCgwKTtcblxuICAgICAgICAgICAgICAgICAgICBpZiAoIXRhZ05hbWUpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHRhZ05hbWUgPSBwYXJ0O1xuICAgICAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKHR5cGUgPT09IFwiLlwiKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBjbGFzc2VzID0gY2xhc3NlcyB8fCBbXTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGNsYXNzZXMucHVzaChwYXJ0LnN1YnN0cmluZygxLCBwYXJ0Lmxlbmd0aCkpO1xuICAgICAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKHR5cGUgPT09IFwiI1wiICYmIG5vSWQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHByb3BzLmlkID0gcGFydC5zdWJzdHJpbmcoMSwgcGFydC5sZW5ndGgpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgaWYgKGNsYXNzZXMpIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKHByb3BzLmNsYXNzTmFtZSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgY2xhc3Nlcy5wdXNoKHByb3BzLmNsYXNzTmFtZSk7XG4gICAgICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgICAgICBwcm9wcy5jbGFzc05hbWUgPSBjbGFzc2VzLmpvaW4oXCIgXCIpO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHJldHVybiBwcm9wcy5uYW1lc3BhY2UgPyB0YWdOYW1lIDogdGFnTmFtZS50b1VwcGVyQ2FzZSgpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9LCB7IFwiYnJvd3Nlci1zcGxpdFwiOiA1IH1dLCAyNDogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHtcbiAgICAgICAgICAgIHZhciBpc1ZOb2RlID0gcmVxdWlyZShcIi4vaXMtdm5vZGVcIik7XG4gICAgICAgICAgICB2YXIgaXNWVGV4dCA9IHJlcXVpcmUoXCIuL2lzLXZ0ZXh0XCIpO1xuICAgICAgICAgICAgdmFyIGlzV2lkZ2V0ID0gcmVxdWlyZShcIi4vaXMtd2lkZ2V0XCIpO1xuICAgICAgICAgICAgdmFyIGlzVGh1bmsgPSByZXF1aXJlKFwiLi9pcy10aHVua1wiKTtcblxuICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBoYW5kbGVUaHVuaztcblxuICAgICAgICAgICAgZnVuY3Rpb24gaGFuZGxlVGh1bmsoYSwgYikge1xuICAgICAgICAgICAgICAgIHZhciByZW5kZXJlZEEgPSBhO1xuICAgICAgICAgICAgICAgIHZhciByZW5kZXJlZEIgPSBiO1xuXG4gICAgICAgICAgICAgICAgaWYgKGlzVGh1bmsoYikpIHtcbiAgICAgICAgICAgICAgICAgICAgcmVuZGVyZWRCID0gcmVuZGVyVGh1bmsoYiwgYSk7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgaWYgKGlzVGh1bmsoYSkpIHtcbiAgICAgICAgICAgICAgICAgICAgcmVuZGVyZWRBID0gcmVuZGVyVGh1bmsoYSwgbnVsbCk7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgICAgICAgICAgYTogcmVuZGVyZWRBLFxuICAgICAgICAgICAgICAgICAgICBiOiByZW5kZXJlZEJcbiAgICAgICAgICAgICAgICB9O1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBmdW5jdGlvbiByZW5kZXJUaHVuayh0aHVuaywgcHJldmlvdXMpIHtcbiAgICAgICAgICAgICAgICB2YXIgcmVuZGVyZWRUaHVuayA9IHRodW5rLnZub2RlO1xuXG4gICAgICAgICAgICAgICAgaWYgKCFyZW5kZXJlZFRodW5rKSB7XG4gICAgICAgICAgICAgICAgICAgIHJlbmRlcmVkVGh1bmsgPSB0aHVuay52bm9kZSA9IHRodW5rLnJlbmRlcihwcmV2aW91cyk7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgaWYgKCEoaXNWTm9kZShyZW5kZXJlZFRodW5rKSB8fCBpc1ZUZXh0KHJlbmRlcmVkVGh1bmspIHx8IGlzV2lkZ2V0KHJlbmRlcmVkVGh1bmspKSkge1xuICAgICAgICAgICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoXCJ0aHVuayBkaWQgbm90IHJldHVybiBhIHZhbGlkIG5vZGVcIik7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgcmV0dXJuIHJlbmRlcmVkVGh1bms7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0sIHsgXCIuL2lzLXRodW5rXCI6IDI1LCBcIi4vaXMtdm5vZGVcIjogMjcsIFwiLi9pcy12dGV4dFwiOiAyOCwgXCIuL2lzLXdpZGdldFwiOiAyOSB9XSwgMjU6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IGlzVGh1bms7XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIGlzVGh1bmsodCkge1xuICAgICAgICAgICAgICAgIHJldHVybiB0ICYmIHQudHlwZSA9PT0gXCJUaHVua1wiO1xuICAgICAgICAgICAgfVxuICAgICAgICB9LCB7fV0sIDI2OiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge1xuICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBpc0hvb2s7XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIGlzSG9vayhob29rKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGhvb2sgJiYgKHR5cGVvZiBob29rLmhvb2sgPT09IFwiZnVuY3Rpb25cIiAmJiAhaG9vay5oYXNPd25Qcm9wZXJ0eShcImhvb2tcIikgfHwgdHlwZW9mIGhvb2sudW5ob29rID09PSBcImZ1bmN0aW9uXCIgJiYgIWhvb2suaGFzT3duUHJvcGVydHkoXCJ1bmhvb2tcIikpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9LCB7fV0sIDI3OiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge1xuICAgICAgICAgICAgdmFyIHZlcnNpb24gPSByZXF1aXJlKFwiLi92ZXJzaW9uXCIpO1xuXG4gICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IGlzVmlydHVhbE5vZGU7XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIGlzVmlydHVhbE5vZGUoeCkge1xuICAgICAgICAgICAgICAgIHJldHVybiB4ICYmIHgudHlwZSA9PT0gXCJWaXJ0dWFsTm9kZVwiICYmIHgudmVyc2lvbiA9PT0gdmVyc2lvbjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSwgeyBcIi4vdmVyc2lvblwiOiAzMCB9XSwgMjg6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICB2YXIgdmVyc2lvbiA9IHJlcXVpcmUoXCIuL3ZlcnNpb25cIik7XG5cbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gaXNWaXJ0dWFsVGV4dDtcblxuICAgICAgICAgICAgZnVuY3Rpb24gaXNWaXJ0dWFsVGV4dCh4KSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHggJiYgeC50eXBlID09PSBcIlZpcnR1YWxUZXh0XCIgJiYgeC52ZXJzaW9uID09PSB2ZXJzaW9uO1xuICAgICAgICAgICAgfVxuICAgICAgICB9LCB7IFwiLi92ZXJzaW9uXCI6IDMwIH1dLCAyOTogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHtcbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gaXNXaWRnZXQ7XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIGlzV2lkZ2V0KHcpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gdyAmJiB3LnR5cGUgPT09IFwiV2lkZ2V0XCI7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0sIHt9XSwgMzA6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IFwiMlwiO1xuICAgICAgICB9LCB7fV0sIDMxOiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge1xuICAgICAgICAgICAgdmFyIHZlcnNpb24gPSByZXF1aXJlKFwiLi92ZXJzaW9uXCIpO1xuICAgICAgICAgICAgdmFyIGlzVk5vZGUgPSByZXF1aXJlKFwiLi9pcy12bm9kZVwiKTtcbiAgICAgICAgICAgIHZhciBpc1dpZGdldCA9IHJlcXVpcmUoXCIuL2lzLXdpZGdldFwiKTtcbiAgICAgICAgICAgIHZhciBpc1RodW5rID0gcmVxdWlyZShcIi4vaXMtdGh1bmtcIik7XG4gICAgICAgICAgICB2YXIgaXNWSG9vayA9IHJlcXVpcmUoXCIuL2lzLXZob29rXCIpO1xuXG4gICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IFZpcnR1YWxOb2RlO1xuXG4gICAgICAgICAgICB2YXIgbm9Qcm9wZXJ0aWVzID0ge307XG4gICAgICAgICAgICB2YXIgbm9DaGlsZHJlbiA9IFtdO1xuXG4gICAgICAgICAgICBmdW5jdGlvbiBWaXJ0dWFsTm9kZSh0YWdOYW1lLCBwcm9wZXJ0aWVzLCBjaGlsZHJlbiwga2V5LCBuYW1lc3BhY2UpIHtcbiAgICAgICAgICAgICAgICB0aGlzLnRhZ05hbWUgPSB0YWdOYW1lO1xuICAgICAgICAgICAgICAgIHRoaXMucHJvcGVydGllcyA9IHByb3BlcnRpZXMgfHwgbm9Qcm9wZXJ0aWVzO1xuICAgICAgICAgICAgICAgIHRoaXMuY2hpbGRyZW4gPSBjaGlsZHJlbiB8fCBub0NoaWxkcmVuO1xuICAgICAgICAgICAgICAgIHRoaXMua2V5ID0ga2V5ICE9IG51bGwgPyBTdHJpbmcoa2V5KSA6IHVuZGVmaW5lZDtcbiAgICAgICAgICAgICAgICB0aGlzLm5hbWVzcGFjZSA9IHR5cGVvZiBuYW1lc3BhY2UgPT09IFwic3RyaW5nXCIgPyBuYW1lc3BhY2UgOiBudWxsO1xuXG4gICAgICAgICAgICAgICAgdmFyIGNvdW50ID0gY2hpbGRyZW4gJiYgY2hpbGRyZW4ubGVuZ3RoIHx8IDA7XG4gICAgICAgICAgICAgICAgdmFyIGRlc2NlbmRhbnRzID0gMDtcbiAgICAgICAgICAgICAgICB2YXIgaGFzV2lkZ2V0cyA9IGZhbHNlO1xuICAgICAgICAgICAgICAgIHZhciBoYXNUaHVua3MgPSBmYWxzZTtcbiAgICAgICAgICAgICAgICB2YXIgZGVzY2VuZGFudEhvb2tzID0gZmFsc2U7XG4gICAgICAgICAgICAgICAgdmFyIGhvb2tzO1xuXG4gICAgICAgICAgICAgICAgZm9yICh2YXIgcHJvcE5hbWUgaW4gcHJvcGVydGllcykge1xuICAgICAgICAgICAgICAgICAgICBpZiAocHJvcGVydGllcy5oYXNPd25Qcm9wZXJ0eShwcm9wTmFtZSkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHZhciBwcm9wZXJ0eSA9IHByb3BlcnRpZXNbcHJvcE5hbWVdO1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGlzVkhvb2socHJvcGVydHkpICYmIHByb3BlcnR5LnVuaG9vaykge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmICghaG9va3MpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaG9va3MgPSB7fTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBob29rc1twcm9wTmFtZV0gPSBwcm9wZXJ0eTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgY291bnQ7IGkrKykge1xuICAgICAgICAgICAgICAgICAgICB2YXIgY2hpbGQgPSBjaGlsZHJlbltpXTtcbiAgICAgICAgICAgICAgICAgICAgaWYgKGlzVk5vZGUoY2hpbGQpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBkZXNjZW5kYW50cyArPSBjaGlsZC5jb3VudCB8fCAwO1xuXG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoIWhhc1dpZGdldHMgJiYgY2hpbGQuaGFzV2lkZ2V0cykge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGhhc1dpZGdldHMgPSB0cnVlO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoIWhhc1RodW5rcyAmJiBjaGlsZC5oYXNUaHVua3MpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBoYXNUaHVua3MgPSB0cnVlO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoIWRlc2NlbmRhbnRIb29rcyAmJiAoY2hpbGQuaG9va3MgfHwgY2hpbGQuZGVzY2VuZGFudEhvb2tzKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRlc2NlbmRhbnRIb29rcyA9IHRydWU7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoIWhhc1dpZGdldHMgJiYgaXNXaWRnZXQoY2hpbGQpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAodHlwZW9mIGNoaWxkLmRlc3Ryb3kgPT09IFwiZnVuY3Rpb25cIikge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGhhc1dpZGdldHMgPSB0cnVlO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKCFoYXNUaHVua3MgJiYgaXNUaHVuayhjaGlsZCkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGhhc1RodW5rcyA9IHRydWU7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICB0aGlzLmNvdW50ID0gY291bnQgKyBkZXNjZW5kYW50cztcbiAgICAgICAgICAgICAgICB0aGlzLmhhc1dpZGdldHMgPSBoYXNXaWRnZXRzO1xuICAgICAgICAgICAgICAgIHRoaXMuaGFzVGh1bmtzID0gaGFzVGh1bmtzO1xuICAgICAgICAgICAgICAgIHRoaXMuaG9va3MgPSBob29rcztcbiAgICAgICAgICAgICAgICB0aGlzLmRlc2NlbmRhbnRIb29rcyA9IGRlc2NlbmRhbnRIb29rcztcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgVmlydHVhbE5vZGUucHJvdG90eXBlLnZlcnNpb24gPSB2ZXJzaW9uO1xuICAgICAgICAgICAgVmlydHVhbE5vZGUucHJvdG90eXBlLnR5cGUgPSBcIlZpcnR1YWxOb2RlXCI7XG4gICAgICAgIH0sIHsgXCIuL2lzLXRodW5rXCI6IDI1LCBcIi4vaXMtdmhvb2tcIjogMjYsIFwiLi9pcy12bm9kZVwiOiAyNywgXCIuL2lzLXdpZGdldFwiOiAyOSwgXCIuL3ZlcnNpb25cIjogMzAgfV0sIDMyOiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge1xuICAgICAgICAgICAgdmFyIHZlcnNpb24gPSByZXF1aXJlKFwiLi92ZXJzaW9uXCIpO1xuXG4gICAgICAgICAgICBWaXJ0dWFsUGF0Y2guTk9ORSA9IDA7XG4gICAgICAgICAgICBWaXJ0dWFsUGF0Y2guVlRFWFQgPSAxO1xuICAgICAgICAgICAgVmlydHVhbFBhdGNoLlZOT0RFID0gMjtcbiAgICAgICAgICAgIFZpcnR1YWxQYXRjaC5XSURHRVQgPSAzO1xuICAgICAgICAgICAgVmlydHVhbFBhdGNoLlBST1BTID0gNDtcbiAgICAgICAgICAgIFZpcnR1YWxQYXRjaC5PUkRFUiA9IDU7XG4gICAgICAgICAgICBWaXJ0dWFsUGF0Y2guSU5TRVJUID0gNjtcbiAgICAgICAgICAgIFZpcnR1YWxQYXRjaC5SRU1PVkUgPSA3O1xuICAgICAgICAgICAgVmlydHVhbFBhdGNoLlRIVU5LID0gODtcblxuICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBWaXJ0dWFsUGF0Y2g7XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIFZpcnR1YWxQYXRjaCh0eXBlLCB2Tm9kZSwgcGF0Y2gpIHtcbiAgICAgICAgICAgICAgICB0aGlzLnR5cGUgPSBOdW1iZXIodHlwZSk7XG4gICAgICAgICAgICAgICAgdGhpcy52Tm9kZSA9IHZOb2RlO1xuICAgICAgICAgICAgICAgIHRoaXMucGF0Y2ggPSBwYXRjaDtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgVmlydHVhbFBhdGNoLnByb3RvdHlwZS52ZXJzaW9uID0gdmVyc2lvbjtcbiAgICAgICAgICAgIFZpcnR1YWxQYXRjaC5wcm90b3R5cGUudHlwZSA9IFwiVmlydHVhbFBhdGNoXCI7XG4gICAgICAgIH0sIHsgXCIuL3ZlcnNpb25cIjogMzAgfV0sIDMzOiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge1xuICAgICAgICAgICAgdmFyIHZlcnNpb24gPSByZXF1aXJlKFwiLi92ZXJzaW9uXCIpO1xuXG4gICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IFZpcnR1YWxUZXh0O1xuXG4gICAgICAgICAgICBmdW5jdGlvbiBWaXJ0dWFsVGV4dCh0ZXh0KSB7XG4gICAgICAgICAgICAgICAgdGhpcy50ZXh0ID0gU3RyaW5nKHRleHQpO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBWaXJ0dWFsVGV4dC5wcm90b3R5cGUudmVyc2lvbiA9IHZlcnNpb247XG4gICAgICAgICAgICBWaXJ0dWFsVGV4dC5wcm90b3R5cGUudHlwZSA9IFwiVmlydHVhbFRleHRcIjtcbiAgICAgICAgfSwgeyBcIi4vdmVyc2lvblwiOiAzMCB9XSwgMzQ6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICB2YXIgaXNPYmplY3QgPSByZXF1aXJlKFwiaXMtb2JqZWN0XCIpO1xuICAgICAgICAgICAgdmFyIGlzSG9vayA9IHJlcXVpcmUoXCIuLi92bm9kZS9pcy12aG9va1wiKTtcblxuICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBkaWZmUHJvcHM7XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIGRpZmZQcm9wcyhhLCBiKSB7XG4gICAgICAgICAgICAgICAgdmFyIGRpZmY7XG5cbiAgICAgICAgICAgICAgICBmb3IgKHZhciBhS2V5IGluIGEpIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKCEoYUtleSBpbiBiKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgZGlmZiA9IGRpZmYgfHwge307XG4gICAgICAgICAgICAgICAgICAgICAgICBkaWZmW2FLZXldID0gdW5kZWZpbmVkO1xuICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgdmFyIGFWYWx1ZSA9IGFbYUtleV07XG4gICAgICAgICAgICAgICAgICAgIHZhciBiVmFsdWUgPSBiW2FLZXldO1xuXG4gICAgICAgICAgICAgICAgICAgIGlmIChhVmFsdWUgPT09IGJWYWx1ZSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgY29udGludWU7XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoaXNPYmplY3QoYVZhbHVlKSAmJiBpc09iamVjdChiVmFsdWUpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoZ2V0UHJvdG90eXBlKGJWYWx1ZSkgIT09IGdldFByb3RvdHlwZShhVmFsdWUpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgZGlmZiA9IGRpZmYgfHwge307XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgZGlmZlthS2V5XSA9IGJWYWx1ZTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoaXNIb29rKGJWYWx1ZSkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBkaWZmID0gZGlmZiB8fCB7fTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBkaWZmW2FLZXldID0gYlZhbHVlO1xuICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB2YXIgb2JqZWN0RGlmZiA9IGRpZmZQcm9wcyhhVmFsdWUsIGJWYWx1ZSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKG9iamVjdERpZmYpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZGlmZiA9IGRpZmYgfHwge307XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRpZmZbYUtleV0gPSBvYmplY3REaWZmO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGRpZmYgPSBkaWZmIHx8IHt9O1xuICAgICAgICAgICAgICAgICAgICAgICAgZGlmZlthS2V5XSA9IGJWYWx1ZTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIGZvciAodmFyIGJLZXkgaW4gYikge1xuICAgICAgICAgICAgICAgICAgICBpZiAoIShiS2V5IGluIGEpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBkaWZmID0gZGlmZiB8fCB7fTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGRpZmZbYktleV0gPSBiW2JLZXldO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgcmV0dXJuIGRpZmY7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIGdldFByb3RvdHlwZSh2YWx1ZSkge1xuICAgICAgICAgICAgICAgIGlmIChPYmplY3QuZ2V0UHJvdG90eXBlT2YpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIE9iamVjdC5nZXRQcm90b3R5cGVPZih2YWx1ZSk7XG4gICAgICAgICAgICAgICAgfSBlbHNlIGlmICh2YWx1ZS5fX3Byb3RvX18pIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHZhbHVlLl9fcHJvdG9fXztcbiAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKHZhbHVlLmNvbnN0cnVjdG9yKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiB2YWx1ZS5jb25zdHJ1Y3Rvci5wcm90b3R5cGU7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9LCB7IFwiLi4vdm5vZGUvaXMtdmhvb2tcIjogMjYsIFwiaXMtb2JqZWN0XCI6IDExIH1dLCAzNTogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHtcbiAgICAgICAgICAgIHZhciBpc0FycmF5ID0gcmVxdWlyZShcIngtaXMtYXJyYXlcIik7XG5cbiAgICAgICAgICAgIHZhciBWUGF0Y2ggPSByZXF1aXJlKFwiLi4vdm5vZGUvdnBhdGNoXCIpO1xuICAgICAgICAgICAgdmFyIGlzVk5vZGUgPSByZXF1aXJlKFwiLi4vdm5vZGUvaXMtdm5vZGVcIik7XG4gICAgICAgICAgICB2YXIgaXNWVGV4dCA9IHJlcXVpcmUoXCIuLi92bm9kZS9pcy12dGV4dFwiKTtcbiAgICAgICAgICAgIHZhciBpc1dpZGdldCA9IHJlcXVpcmUoXCIuLi92bm9kZS9pcy13aWRnZXRcIik7XG4gICAgICAgICAgICB2YXIgaXNUaHVuayA9IHJlcXVpcmUoXCIuLi92bm9kZS9pcy10aHVua1wiKTtcbiAgICAgICAgICAgIHZhciBoYW5kbGVUaHVuayA9IHJlcXVpcmUoXCIuLi92bm9kZS9oYW5kbGUtdGh1bmtcIik7XG5cbiAgICAgICAgICAgIHZhciBkaWZmUHJvcHMgPSByZXF1aXJlKFwiLi9kaWZmLXByb3BzXCIpO1xuXG4gICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IGRpZmY7XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIGRpZmYoYSwgYikge1xuICAgICAgICAgICAgICAgIHZhciBwYXRjaCA9IHsgYTogYSB9O1xuICAgICAgICAgICAgICAgIHdhbGsoYSwgYiwgcGF0Y2gsIDApO1xuICAgICAgICAgICAgICAgIHJldHVybiBwYXRjaDtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZnVuY3Rpb24gd2FsayhhLCBiLCBwYXRjaCwgaW5kZXgpIHtcbiAgICAgICAgICAgICAgICBpZiAoYSA9PT0gYikge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgdmFyIGFwcGx5ID0gcGF0Y2hbaW5kZXhdO1xuICAgICAgICAgICAgICAgIHZhciBhcHBseUNsZWFyID0gZmFsc2U7XG5cbiAgICAgICAgICAgICAgICBpZiAoaXNUaHVuayhhKSB8fCBpc1RodW5rKGIpKSB7XG4gICAgICAgICAgICAgICAgICAgIHRodW5rcyhhLCBiLCBwYXRjaCwgaW5kZXgpO1xuICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoYiA9PSBudWxsKSB7XG5cbiAgICAgICAgICAgICAgICAgICAgLy8gSWYgYSBpcyBhIHdpZGdldCB3ZSB3aWxsIGFkZCBhIHJlbW92ZSBwYXRjaCBmb3IgaXRcbiAgICAgICAgICAgICAgICAgICAgLy8gT3RoZXJ3aXNlIGFueSBjaGlsZCB3aWRnZXRzL2hvb2tzIG11c3QgYmUgZGVzdHJveWVkLlxuICAgICAgICAgICAgICAgICAgICAvLyBUaGlzIHByZXZlbnRzIGFkZGluZyB0d28gcmVtb3ZlIHBhdGNoZXMgZm9yIGEgd2lkZ2V0LlxuICAgICAgICAgICAgICAgICAgICBpZiAoIWlzV2lkZ2V0KGEpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBjbGVhclN0YXRlKGEsIHBhdGNoLCBpbmRleCk7XG4gICAgICAgICAgICAgICAgICAgICAgICBhcHBseSA9IHBhdGNoW2luZGV4XTtcbiAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgIGFwcGx5ID0gYXBwZW5kUGF0Y2goYXBwbHksIG5ldyBWUGF0Y2goVlBhdGNoLlJFTU9WRSwgYSwgYikpO1xuICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoaXNWTm9kZShiKSkge1xuICAgICAgICAgICAgICAgICAgICBpZiAoaXNWTm9kZShhKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGEudGFnTmFtZSA9PT0gYi50YWdOYW1lICYmIGEubmFtZXNwYWNlID09PSBiLm5hbWVzcGFjZSAmJiBhLmtleSA9PT0gYi5rZXkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB2YXIgcHJvcHNQYXRjaCA9IGRpZmZQcm9wcyhhLnByb3BlcnRpZXMsIGIucHJvcGVydGllcyk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHByb3BzUGF0Y2gpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYXBwbHkgPSBhcHBlbmRQYXRjaChhcHBseSwgbmV3IFZQYXRjaChWUGF0Y2guUFJPUFMsIGEsIHByb3BzUGF0Y2gpKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgYXBwbHkgPSBkaWZmQ2hpbGRyZW4oYSwgYiwgcGF0Y2gsIGFwcGx5LCBpbmRleCk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGFwcGx5ID0gYXBwZW5kUGF0Y2goYXBwbHksIG5ldyBWUGF0Y2goVlBhdGNoLlZOT0RFLCBhLCBiKSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgYXBwbHlDbGVhciA9IHRydWU7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBhcHBseSA9IGFwcGVuZFBhdGNoKGFwcGx5LCBuZXcgVlBhdGNoKFZQYXRjaC5WTk9ERSwgYSwgYikpO1xuICAgICAgICAgICAgICAgICAgICAgICAgYXBwbHlDbGVhciA9IHRydWU7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKGlzVlRleHQoYikpIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKCFpc1ZUZXh0KGEpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBhcHBseSA9IGFwcGVuZFBhdGNoKGFwcGx5LCBuZXcgVlBhdGNoKFZQYXRjaC5WVEVYVCwgYSwgYikpO1xuICAgICAgICAgICAgICAgICAgICAgICAgYXBwbHlDbGVhciA9IHRydWU7XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoYS50ZXh0ICE9PSBiLnRleHQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGFwcGx5ID0gYXBwZW5kUGF0Y2goYXBwbHksIG5ldyBWUGF0Y2goVlBhdGNoLlZURVhULCBhLCBiKSk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKGlzV2lkZ2V0KGIpKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmICghaXNXaWRnZXQoYSkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGFwcGx5Q2xlYXIgPSB0cnVlO1xuICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgYXBwbHkgPSBhcHBlbmRQYXRjaChhcHBseSwgbmV3IFZQYXRjaChWUGF0Y2guV0lER0VULCBhLCBiKSk7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgaWYgKGFwcGx5KSB7XG4gICAgICAgICAgICAgICAgICAgIHBhdGNoW2luZGV4XSA9IGFwcGx5O1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIGlmIChhcHBseUNsZWFyKSB7XG4gICAgICAgICAgICAgICAgICAgIGNsZWFyU3RhdGUoYSwgcGF0Y2gsIGluZGV4KTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIGRpZmZDaGlsZHJlbihhLCBiLCBwYXRjaCwgYXBwbHksIGluZGV4KSB7XG4gICAgICAgICAgICAgICAgdmFyIGFDaGlsZHJlbiA9IGEuY2hpbGRyZW47XG4gICAgICAgICAgICAgICAgdmFyIG9yZGVyZWRTZXQgPSByZW9yZGVyKGFDaGlsZHJlbiwgYi5jaGlsZHJlbik7XG4gICAgICAgICAgICAgICAgdmFyIGJDaGlsZHJlbiA9IG9yZGVyZWRTZXQuY2hpbGRyZW47XG5cbiAgICAgICAgICAgICAgICB2YXIgYUxlbiA9IGFDaGlsZHJlbi5sZW5ndGg7XG4gICAgICAgICAgICAgICAgdmFyIGJMZW4gPSBiQ2hpbGRyZW4ubGVuZ3RoO1xuICAgICAgICAgICAgICAgIHZhciBsZW4gPSBhTGVuID4gYkxlbiA/IGFMZW4gOiBiTGVuO1xuXG4gICAgICAgICAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCBsZW47IGkrKykge1xuICAgICAgICAgICAgICAgICAgICB2YXIgbGVmdE5vZGUgPSBhQ2hpbGRyZW5baV07XG4gICAgICAgICAgICAgICAgICAgIHZhciByaWdodE5vZGUgPSBiQ2hpbGRyZW5baV07XG4gICAgICAgICAgICAgICAgICAgIGluZGV4ICs9IDE7XG5cbiAgICAgICAgICAgICAgICAgICAgaWYgKCFsZWZ0Tm9kZSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHJpZ2h0Tm9kZSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIEV4Y2VzcyBub2RlcyBpbiBiIG5lZWQgdG8gYmUgYWRkZWRcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBhcHBseSA9IGFwcGVuZFBhdGNoKGFwcGx5LCBuZXcgVlBhdGNoKFZQYXRjaC5JTlNFUlQsIG51bGwsIHJpZ2h0Tm9kZSkpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgd2FsayhsZWZ0Tm9kZSwgcmlnaHROb2RlLCBwYXRjaCwgaW5kZXgpO1xuICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgaWYgKGlzVk5vZGUobGVmdE5vZGUpICYmIGxlZnROb2RlLmNvdW50KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBpbmRleCArPSBsZWZ0Tm9kZS5jb3VudDtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIGlmIChvcmRlcmVkU2V0Lm1vdmVzKSB7XG4gICAgICAgICAgICAgICAgICAgIC8vIFJlb3JkZXIgbm9kZXMgbGFzdFxuICAgICAgICAgICAgICAgICAgICBhcHBseSA9IGFwcGVuZFBhdGNoKGFwcGx5LCBuZXcgVlBhdGNoKFZQYXRjaC5PUkRFUiwgYSwgb3JkZXJlZFNldC5tb3ZlcykpO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHJldHVybiBhcHBseTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZnVuY3Rpb24gY2xlYXJTdGF0ZSh2Tm9kZSwgcGF0Y2gsIGluZGV4KSB7XG4gICAgICAgICAgICAgICAgLy8gVE9ETzogTWFrZSB0aGlzIGEgc2luZ2xlIHdhbGssIG5vdCB0d29cbiAgICAgICAgICAgICAgICB1bmhvb2sodk5vZGUsIHBhdGNoLCBpbmRleCk7XG4gICAgICAgICAgICAgICAgZGVzdHJveVdpZGdldHModk5vZGUsIHBhdGNoLCBpbmRleCk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIC8vIFBhdGNoIHJlY29yZHMgZm9yIGFsbCBkZXN0cm95ZWQgd2lkZ2V0cyBtdXN0IGJlIGFkZGVkIGJlY2F1c2Ugd2UgbmVlZFxuICAgICAgICAgICAgLy8gYSBET00gbm9kZSByZWZlcmVuY2UgZm9yIHRoZSBkZXN0cm95IGZ1bmN0aW9uXG4gICAgICAgICAgICBmdW5jdGlvbiBkZXN0cm95V2lkZ2V0cyh2Tm9kZSwgcGF0Y2gsIGluZGV4KSB7XG4gICAgICAgICAgICAgICAgaWYgKGlzV2lkZ2V0KHZOb2RlKSkge1xuICAgICAgICAgICAgICAgICAgICBpZiAodHlwZW9mIHZOb2RlLmRlc3Ryb3kgPT09IFwiZnVuY3Rpb25cIikge1xuICAgICAgICAgICAgICAgICAgICAgICAgcGF0Y2hbaW5kZXhdID0gYXBwZW5kUGF0Y2gocGF0Y2hbaW5kZXhdLCBuZXcgVlBhdGNoKFZQYXRjaC5SRU1PVkUsIHZOb2RlLCBudWxsKSk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKGlzVk5vZGUodk5vZGUpICYmICh2Tm9kZS5oYXNXaWRnZXRzIHx8IHZOb2RlLmhhc1RodW5rcykpIHtcbiAgICAgICAgICAgICAgICAgICAgdmFyIGNoaWxkcmVuID0gdk5vZGUuY2hpbGRyZW47XG4gICAgICAgICAgICAgICAgICAgIHZhciBsZW4gPSBjaGlsZHJlbi5sZW5ndGg7XG4gICAgICAgICAgICAgICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgbGVuOyBpKyspIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHZhciBjaGlsZCA9IGNoaWxkcmVuW2ldO1xuICAgICAgICAgICAgICAgICAgICAgICAgaW5kZXggKz0gMTtcblxuICAgICAgICAgICAgICAgICAgICAgICAgZGVzdHJveVdpZGdldHMoY2hpbGQsIHBhdGNoLCBpbmRleCk7XG5cbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChpc1ZOb2RlKGNoaWxkKSAmJiBjaGlsZC5jb3VudCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGluZGV4ICs9IGNoaWxkLmNvdW50O1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfSBlbHNlIGlmIChpc1RodW5rKHZOb2RlKSkge1xuICAgICAgICAgICAgICAgICAgICB0aHVua3Modk5vZGUsIG51bGwsIHBhdGNoLCBpbmRleCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAvLyBDcmVhdGUgYSBzdWItcGF0Y2ggZm9yIHRodW5rc1xuICAgICAgICAgICAgZnVuY3Rpb24gdGh1bmtzKGEsIGIsIHBhdGNoLCBpbmRleCkge1xuICAgICAgICAgICAgICAgIHZhciBub2RlcyA9IGhhbmRsZVRodW5rKGEsIGIpO1xuICAgICAgICAgICAgICAgIHZhciB0aHVua1BhdGNoID0gZGlmZihub2Rlcy5hLCBub2Rlcy5iKTtcbiAgICAgICAgICAgICAgICBpZiAoaGFzUGF0Y2hlcyh0aHVua1BhdGNoKSkge1xuICAgICAgICAgICAgICAgICAgICBwYXRjaFtpbmRleF0gPSBuZXcgVlBhdGNoKFZQYXRjaC5USFVOSywgbnVsbCwgdGh1bmtQYXRjaCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBmdW5jdGlvbiBoYXNQYXRjaGVzKHBhdGNoKSB7XG4gICAgICAgICAgICAgICAgZm9yICh2YXIgaW5kZXggaW4gcGF0Y2gpIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKGluZGV4ICE9PSBcImFcIikge1xuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIC8vIEV4ZWN1dGUgaG9va3Mgd2hlbiB0d28gbm9kZXMgYXJlIGlkZW50aWNhbFxuICAgICAgICAgICAgZnVuY3Rpb24gdW5ob29rKHZOb2RlLCBwYXRjaCwgaW5kZXgpIHtcbiAgICAgICAgICAgICAgICBpZiAoaXNWTm9kZSh2Tm9kZSkpIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKHZOb2RlLmhvb2tzKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBwYXRjaFtpbmRleF0gPSBhcHBlbmRQYXRjaChwYXRjaFtpbmRleF0sIG5ldyBWUGF0Y2goVlBhdGNoLlBST1BTLCB2Tm9kZSwgdW5kZWZpbmVkS2V5cyh2Tm9kZS5ob29rcykpKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgIGlmICh2Tm9kZS5kZXNjZW5kYW50SG9va3MgfHwgdk5vZGUuaGFzVGh1bmtzKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICB2YXIgY2hpbGRyZW4gPSB2Tm9kZS5jaGlsZHJlbjtcbiAgICAgICAgICAgICAgICAgICAgICAgIHZhciBsZW4gPSBjaGlsZHJlbi5sZW5ndGg7XG4gICAgICAgICAgICAgICAgICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IGxlbjsgaSsrKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdmFyIGNoaWxkID0gY2hpbGRyZW5baV07XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaW5kZXggKz0gMTtcblxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHVuaG9vayhjaGlsZCwgcGF0Y2gsIGluZGV4KTtcblxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChpc1ZOb2RlKGNoaWxkKSAmJiBjaGlsZC5jb3VudCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpbmRleCArPSBjaGlsZC5jb3VudDtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKGlzVGh1bmsodk5vZGUpKSB7XG4gICAgICAgICAgICAgICAgICAgIHRodW5rcyh2Tm9kZSwgbnVsbCwgcGF0Y2gsIGluZGV4KTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIHVuZGVmaW5lZEtleXMob2JqKSB7XG4gICAgICAgICAgICAgICAgdmFyIHJlc3VsdCA9IHt9O1xuXG4gICAgICAgICAgICAgICAgZm9yICh2YXIga2V5IGluIG9iaikge1xuICAgICAgICAgICAgICAgICAgICByZXN1bHRba2V5XSA9IHVuZGVmaW5lZDtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICByZXR1cm4gcmVzdWx0O1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAvLyBMaXN0IGRpZmYsIG5haXZlIGxlZnQgdG8gcmlnaHQgcmVvcmRlcmluZ1xuICAgICAgICAgICAgZnVuY3Rpb24gcmVvcmRlcihhQ2hpbGRyZW4sIGJDaGlsZHJlbikge1xuICAgICAgICAgICAgICAgIC8vIE8oTSkgdGltZSwgTyhNKSBtZW1vcnlcbiAgICAgICAgICAgICAgICB2YXIgYkNoaWxkSW5kZXggPSBrZXlJbmRleChiQ2hpbGRyZW4pO1xuICAgICAgICAgICAgICAgIHZhciBiS2V5cyA9IGJDaGlsZEluZGV4LmtleXM7XG4gICAgICAgICAgICAgICAgdmFyIGJGcmVlID0gYkNoaWxkSW5kZXguZnJlZTtcblxuICAgICAgICAgICAgICAgIGlmIChiRnJlZS5sZW5ndGggPT09IGJDaGlsZHJlbi5sZW5ndGgpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGNoaWxkcmVuOiBiQ2hpbGRyZW4sXG4gICAgICAgICAgICAgICAgICAgICAgICBtb3ZlczogbnVsbFxuICAgICAgICAgICAgICAgICAgICB9O1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIC8vIE8oTikgdGltZSwgTyhOKSBtZW1vcnlcbiAgICAgICAgICAgICAgICB2YXIgYUNoaWxkSW5kZXggPSBrZXlJbmRleChhQ2hpbGRyZW4pO1xuICAgICAgICAgICAgICAgIHZhciBhS2V5cyA9IGFDaGlsZEluZGV4LmtleXM7XG4gICAgICAgICAgICAgICAgdmFyIGFGcmVlID0gYUNoaWxkSW5kZXguZnJlZTtcblxuICAgICAgICAgICAgICAgIGlmIChhRnJlZS5sZW5ndGggPT09IGFDaGlsZHJlbi5sZW5ndGgpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGNoaWxkcmVuOiBiQ2hpbGRyZW4sXG4gICAgICAgICAgICAgICAgICAgICAgICBtb3ZlczogbnVsbFxuICAgICAgICAgICAgICAgICAgICB9O1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIC8vIE8oTUFYKE4sIE0pKSBtZW1vcnlcbiAgICAgICAgICAgICAgICB2YXIgbmV3Q2hpbGRyZW4gPSBbXTtcblxuICAgICAgICAgICAgICAgIHZhciBmcmVlSW5kZXggPSAwO1xuICAgICAgICAgICAgICAgIHZhciBmcmVlQ291bnQgPSBiRnJlZS5sZW5ndGg7XG4gICAgICAgICAgICAgICAgdmFyIGRlbGV0ZWRJdGVtcyA9IDA7XG5cbiAgICAgICAgICAgICAgICAvLyBJdGVyYXRlIHRocm91Z2ggYSBhbmQgbWF0Y2ggYSBub2RlIGluIGJcbiAgICAgICAgICAgICAgICAvLyBPKE4pIHRpbWUsXG4gICAgICAgICAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCBhQ2hpbGRyZW4ubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgICAgICAgICAgdmFyIGFJdGVtID0gYUNoaWxkcmVuW2ldO1xuICAgICAgICAgICAgICAgICAgICB2YXIgaXRlbUluZGV4O1xuXG4gICAgICAgICAgICAgICAgICAgIGlmIChhSXRlbS5rZXkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChiS2V5cy5oYXNPd25Qcm9wZXJ0eShhSXRlbS5rZXkpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gTWF0Y2ggdXAgdGhlIG9sZCBrZXlzXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaXRlbUluZGV4ID0gYktleXNbYUl0ZW0ua2V5XTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBuZXdDaGlsZHJlbi5wdXNoKGJDaGlsZHJlbltpdGVtSW5kZXhdKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gUmVtb3ZlIG9sZCBrZXllZCBpdGVtc1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGl0ZW1JbmRleCA9IGkgLSBkZWxldGVkSXRlbXMrKztcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBuZXdDaGlsZHJlbi5wdXNoKG51bGwpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgLy8gTWF0Y2ggdGhlIGl0ZW0gaW4gYSB3aXRoIHRoZSBuZXh0IGZyZWUgaXRlbSBpbiBiXG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoZnJlZUluZGV4IDwgZnJlZUNvdW50KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaXRlbUluZGV4ID0gYkZyZWVbZnJlZUluZGV4KytdO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIG5ld0NoaWxkcmVuLnB1c2goYkNoaWxkcmVuW2l0ZW1JbmRleF0pO1xuICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBUaGVyZSBhcmUgbm8gZnJlZSBpdGVtcyBpbiBiIHRvIG1hdGNoIHdpdGhcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyB0aGUgZnJlZSBpdGVtcyBpbiBhLCBzbyB0aGUgZXh0cmEgZnJlZSBub2Rlc1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIGFyZSBkZWxldGVkLlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGl0ZW1JbmRleCA9IGkgLSBkZWxldGVkSXRlbXMrKztcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBuZXdDaGlsZHJlbi5wdXNoKG51bGwpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgdmFyIGxhc3RGcmVlSW5kZXggPSBmcmVlSW5kZXggPj0gYkZyZWUubGVuZ3RoID8gYkNoaWxkcmVuLmxlbmd0aCA6IGJGcmVlW2ZyZWVJbmRleF07XG5cbiAgICAgICAgICAgICAgICAvLyBJdGVyYXRlIHRocm91Z2ggYiBhbmQgYXBwZW5kIGFueSBuZXcga2V5c1xuICAgICAgICAgICAgICAgIC8vIE8oTSkgdGltZVxuICAgICAgICAgICAgICAgIGZvciAodmFyIGogPSAwOyBqIDwgYkNoaWxkcmVuLmxlbmd0aDsgaisrKSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciBuZXdJdGVtID0gYkNoaWxkcmVuW2pdO1xuXG4gICAgICAgICAgICAgICAgICAgIGlmIChuZXdJdGVtLmtleSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKCFhS2V5cy5oYXNPd25Qcm9wZXJ0eShuZXdJdGVtLmtleSkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBBZGQgYW55IG5ldyBrZXllZCBpdGVtc1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIFdlIGFyZSBhZGRpbmcgbmV3IGl0ZW1zIHRvIHRoZSBlbmQgYW5kIHRoZW4gc29ydGluZyB0aGVtXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gaW4gcGxhY2UuIEluIGZ1dHVyZSB3ZSBzaG91bGQgaW5zZXJ0IG5ldyBpdGVtcyBpbiBwbGFjZS5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBuZXdDaGlsZHJlbi5wdXNoKG5ld0l0ZW0pO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKGogPj0gbGFzdEZyZWVJbmRleCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgLy8gQWRkIGFueSBsZWZ0b3ZlciBub24ta2V5ZWQgaXRlbXNcbiAgICAgICAgICAgICAgICAgICAgICAgIG5ld0NoaWxkcmVuLnB1c2gobmV3SXRlbSk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICB2YXIgc2ltdWxhdGUgPSBuZXdDaGlsZHJlbi5zbGljZSgpO1xuICAgICAgICAgICAgICAgIHZhciBzaW11bGF0ZUluZGV4ID0gMDtcbiAgICAgICAgICAgICAgICB2YXIgcmVtb3ZlcyA9IFtdO1xuICAgICAgICAgICAgICAgIHZhciBpbnNlcnRzID0gW107XG4gICAgICAgICAgICAgICAgdmFyIHNpbXVsYXRlSXRlbTtcblxuICAgICAgICAgICAgICAgIGZvciAodmFyIGsgPSAwOyBrIDwgYkNoaWxkcmVuLmxlbmd0aDspIHtcbiAgICAgICAgICAgICAgICAgICAgdmFyIHdhbnRlZEl0ZW0gPSBiQ2hpbGRyZW5ba107XG4gICAgICAgICAgICAgICAgICAgIHNpbXVsYXRlSXRlbSA9IHNpbXVsYXRlW3NpbXVsYXRlSW5kZXhdO1xuXG4gICAgICAgICAgICAgICAgICAgIC8vIHJlbW92ZSBpdGVtc1xuICAgICAgICAgICAgICAgICAgICB3aGlsZSAoc2ltdWxhdGVJdGVtID09PSBudWxsICYmIHNpbXVsYXRlLmxlbmd0aCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgcmVtb3Zlcy5wdXNoKHJlbW92ZShzaW11bGF0ZSwgc2ltdWxhdGVJbmRleCwgbnVsbCkpO1xuICAgICAgICAgICAgICAgICAgICAgICAgc2ltdWxhdGVJdGVtID0gc2ltdWxhdGVbc2ltdWxhdGVJbmRleF07XG4gICAgICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgICAgICBpZiAoIXNpbXVsYXRlSXRlbSB8fCBzaW11bGF0ZUl0ZW0ua2V5ICE9PSB3YW50ZWRJdGVtLmtleSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgLy8gaWYgd2UgbmVlZCBhIGtleSBpbiB0aGlzIHBvc2l0aW9uLi4uXG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAod2FudGVkSXRlbS5rZXkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoc2ltdWxhdGVJdGVtICYmIHNpbXVsYXRlSXRlbS5rZXkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gaWYgYW4gaW5zZXJ0IGRvZXNuJ3QgcHV0IHRoaXMga2V5IGluIHBsYWNlLCBpdCBuZWVkcyB0byBtb3ZlXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChiS2V5c1tzaW11bGF0ZUl0ZW0ua2V5XSAhPT0gayArIDEpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlbW92ZXMucHVzaChyZW1vdmUoc2ltdWxhdGUsIHNpbXVsYXRlSW5kZXgsIHNpbXVsYXRlSXRlbS5rZXkpKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNpbXVsYXRlSXRlbSA9IHNpbXVsYXRlW3NpbXVsYXRlSW5kZXhdO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gaWYgdGhlIHJlbW92ZSBkaWRuJ3QgcHV0IHRoZSB3YW50ZWQgaXRlbSBpbiBwbGFjZSwgd2UgbmVlZCB0byBpbnNlcnQgaXRcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmICghc2ltdWxhdGVJdGVtIHx8IHNpbXVsYXRlSXRlbS5rZXkgIT09IHdhbnRlZEl0ZW0ua2V5KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaW5zZXJ0cy5wdXNoKHsga2V5OiB3YW50ZWRJdGVtLmtleSwgdG86IGsgfSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBpdGVtcyBhcmUgbWF0Y2hpbmcsIHNvIHNraXAgYWhlYWRcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNpbXVsYXRlSW5kZXgrKztcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGluc2VydHMucHVzaCh7IGtleTogd2FudGVkSXRlbS5rZXksIHRvOiBrIH0pO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaW5zZXJ0cy5wdXNoKHsga2V5OiB3YW50ZWRJdGVtLmtleSwgdG86IGsgfSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGsrKztcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIGEga2V5IGluIHNpbXVsYXRlIGhhcyBubyBtYXRjaGluZyB3YW50ZWQga2V5LCByZW1vdmUgaXRcbiAgICAgICAgICAgICAgICAgICAgICAgIGVsc2UgaWYgKHNpbXVsYXRlSXRlbSAmJiBzaW11bGF0ZUl0ZW0ua2V5KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcmVtb3Zlcy5wdXNoKHJlbW92ZShzaW11bGF0ZSwgc2ltdWxhdGVJbmRleCwgc2ltdWxhdGVJdGVtLmtleSkpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgc2ltdWxhdGVJbmRleCsrO1xuICAgICAgICAgICAgICAgICAgICAgICAgaysrO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgLy8gcmVtb3ZlIGFsbCB0aGUgcmVtYWluaW5nIG5vZGVzIGZyb20gc2ltdWxhdGVcbiAgICAgICAgICAgICAgICB3aGlsZSAoc2ltdWxhdGVJbmRleCA8IHNpbXVsYXRlLmxlbmd0aCkge1xuICAgICAgICAgICAgICAgICAgICBzaW11bGF0ZUl0ZW0gPSBzaW11bGF0ZVtzaW11bGF0ZUluZGV4XTtcbiAgICAgICAgICAgICAgICAgICAgcmVtb3Zlcy5wdXNoKHJlbW92ZShzaW11bGF0ZSwgc2ltdWxhdGVJbmRleCwgc2ltdWxhdGVJdGVtICYmIHNpbXVsYXRlSXRlbS5rZXkpKTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAvLyBJZiB0aGUgb25seSBtb3ZlcyB3ZSBoYXZlIGFyZSBkZWxldGVzIHRoZW4gd2UgY2FuIGp1c3RcbiAgICAgICAgICAgICAgICAvLyBsZXQgdGhlIGRlbGV0ZSBwYXRjaCByZW1vdmUgdGhlc2UgaXRlbXMuXG4gICAgICAgICAgICAgICAgaWYgKHJlbW92ZXMubGVuZ3RoID09PSBkZWxldGVkSXRlbXMgJiYgIWluc2VydHMubGVuZ3RoKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiB7XG4gICAgICAgICAgICAgICAgICAgICAgICBjaGlsZHJlbjogbmV3Q2hpbGRyZW4sXG4gICAgICAgICAgICAgICAgICAgICAgICBtb3ZlczogbnVsbFxuICAgICAgICAgICAgICAgICAgICB9O1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHJldHVybiB7XG4gICAgICAgICAgICAgICAgICAgIGNoaWxkcmVuOiBuZXdDaGlsZHJlbixcbiAgICAgICAgICAgICAgICAgICAgbW92ZXM6IHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJlbW92ZXM6IHJlbW92ZXMsXG4gICAgICAgICAgICAgICAgICAgICAgICBpbnNlcnRzOiBpbnNlcnRzXG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9O1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBmdW5jdGlvbiByZW1vdmUoYXJyLCBpbmRleCwga2V5KSB7XG4gICAgICAgICAgICAgICAgYXJyLnNwbGljZShpbmRleCwgMSk7XG5cbiAgICAgICAgICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgICAgICAgICBmcm9tOiBpbmRleCxcbiAgICAgICAgICAgICAgICAgICAga2V5OiBrZXlcbiAgICAgICAgICAgICAgICB9O1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBmdW5jdGlvbiBrZXlJbmRleChjaGlsZHJlbikge1xuICAgICAgICAgICAgICAgIHZhciBrZXlzID0ge307XG4gICAgICAgICAgICAgICAgdmFyIGZyZWUgPSBbXTtcbiAgICAgICAgICAgICAgICB2YXIgbGVuZ3RoID0gY2hpbGRyZW4ubGVuZ3RoO1xuXG4gICAgICAgICAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCBsZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgICAgICAgICB2YXIgY2hpbGQgPSBjaGlsZHJlbltpXTtcblxuICAgICAgICAgICAgICAgICAgICBpZiAoY2hpbGQua2V5KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBrZXlzW2NoaWxkLmtleV0gPSBpO1xuICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgZnJlZS5wdXNoKGkpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgICAgICAgICAga2V5czoga2V5cywgLy8gQSBoYXNoIG9mIGtleSBuYW1lIHRvIGluZGV4XG4gICAgICAgICAgICAgICAgICAgIGZyZWU6IGZyZWUgLy8gQW4gYXJyYXkgb2YgdW5rZXllZCBpdGVtIGluZGljZXNcbiAgICAgICAgICAgICAgICB9O1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBmdW5jdGlvbiBhcHBlbmRQYXRjaChhcHBseSwgcGF0Y2gpIHtcbiAgICAgICAgICAgICAgICBpZiAoYXBwbHkpIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKGlzQXJyYXkoYXBwbHkpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBhcHBseS5wdXNoKHBhdGNoKTtcbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGFwcGx5ID0gW2FwcGx5LCBwYXRjaF07XG4gICAgICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgICAgICByZXR1cm4gYXBwbHk7XG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHBhdGNoO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgfSwgeyBcIi4uL3Zub2RlL2hhbmRsZS10aHVua1wiOiAyNCwgXCIuLi92bm9kZS9pcy10aHVua1wiOiAyNSwgXCIuLi92bm9kZS9pcy12bm9kZVwiOiAyNywgXCIuLi92bm9kZS9pcy12dGV4dFwiOiAyOCwgXCIuLi92bm9kZS9pcy13aWRnZXRcIjogMjksIFwiLi4vdm5vZGUvdnBhdGNoXCI6IDMyLCBcIi4vZGlmZi1wcm9wc1wiOiAzNCwgXCJ4LWlzLWFycmF5XCI6IDEyIH1dIH0sIHt9LCBbNF0pKDQpO1xufSk7XG5cbmNvbnN0IENvcmUgPSBDO1xuXG5leHBvcnQgeyBDb3JlLCBLZXJuZWwsIEVudW0sIExpc3QsIEtleXdvcmQsIGJpdHdpc2UgYXMgQml0d2lzZSwgbWFwIGFzIE1hcCwgbWFwX3NldCBhcyBNYXBTZXQsIFZpcnR1YWxET00gfTsiXSwiZmlsZSI6IkVsaXhpci5qcyIsInNvdXJjZVJvb3QiOiIvc291cmNlLyJ9 \ No newline at end of file +export { Core, kernel as Kernel, Enum, VirtualDOM }; +//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiIiwic291cmNlcyI6WyJFbGl4aXIuanMiXSwic291cmNlc0NvbnRlbnQiOlsiLyogQGZsb3cgKi9cblxuY2xhc3MgTWFpbGJveCB7XG5cbiAgY29uc3RydWN0b3IoKSB7XG4gICAgdGhpcy5tZXNzYWdlcyA9IFtdO1xuICB9XG5cbiAgZGVsaXZlcihtZXNzYWdlKSB7XG4gICAgdGhpcy5tZXNzYWdlcy5wdXNoKG1lc3NhZ2UpO1xuICAgIHJldHVybiBtZXNzYWdlO1xuICB9XG5cbiAgZ2V0KCkge1xuICAgIHJldHVybiB0aGlzLm1lc3NhZ2VzO1xuICB9XG5cbiAgaXNFbXB0eSgpIHtcbiAgICByZXR1cm4gdGhpcy5tZXNzYWdlcy5sZW5ndGggPT09IDA7XG4gIH1cblxuICByZW1vdmVBdChpbmRleCkge1xuICAgIHRoaXMubWVzc2FnZXMuc3BsaWNlKGluZGV4LCAxKTtcbiAgfVxufVxuXG52YXIgU3RhdGVzID0ge1xuICBOT1JNQUw6IFN5bWJvbC5mb3IoXCJub3JtYWxcIiksXG4gIEtJTEw6IFN5bWJvbC5mb3IoXCJraWxsXCIpLFxuICBTVVNQRU5EOiBTeW1ib2wuZm9yKFwic3VzcGVuZFwiKSxcbiAgQ09OVElOVUU6IFN5bWJvbC5mb3IoXCJjb250aW51ZVwiKSxcbiAgUkVDRUlWRTogU3ltYm9sLmZvcihcInJlY2VpdmVcIiksXG4gIFNFTkQ6IFN5bWJvbC5mb3IoXCJzZW5kXCIpLFxuICBTTEVFUElORzogU3ltYm9sLmZvcihcInNsZWVwaW5nXCIpLFxuICBSVU5OSU5HOiBTeW1ib2wuZm9yKFwicnVubmluZ1wiKSxcbiAgU1VTUEVOREVEOiBTeW1ib2wuZm9yKFwic3VzcGVuZGVkXCIpLFxuICBTVE9QUEVEOiBTeW1ib2wuZm9yKFwic3RvcHBlZFwiKSxcbiAgU0xFRVA6IFN5bWJvbC5mb3IoXCJzbGVlcFwiKSxcbiAgRVhJVDogU3ltYm9sLmZvcihcImV4aXRcIiksXG4gIE5PTUFUQ0g6IFN5bWJvbC5mb3IoXCJub19tYXRjaFwiKVxufTtcblxuY2xhc3MgUHJvY2VzcyB7XG5cbiAgY29uc3RydWN0b3IocGlkLCBtYWlsYm94KSB7XG4gICAgdGhpcy5waWQgPSBwaWQ7XG4gICAgdGhpcy5tYWlsYm94ID0gbWFpbGJveDtcbiAgICB0aGlzLnN0YXR1cyA9IFN0YXRlcy5TVE9QUEVEO1xuICAgIHRoaXMuZGljdCA9IHt9O1xuICB9XG59XG5cbmNsYXNzIFR1cGxlIHtcblxuICBjb25zdHJ1Y3RvciguLi5hcmdzKSB7XG4gICAgdGhpcy52YWx1ZXMgPSBPYmplY3QuZnJlZXplKGFyZ3MpO1xuICAgIHRoaXMubGVuZ3RoID0gdGhpcy52YWx1ZXMubGVuZ3RoO1xuICB9XG5cbiAgZ2V0KGluZGV4KSB7XG4gICAgcmV0dXJuIHRoaXMudmFsdWVzW2luZGV4XTtcbiAgfVxuXG4gIGNvdW50KCkge1xuICAgIHJldHVybiB0aGlzLnZhbHVlcy5sZW5ndGg7XG4gIH1cblxuICBbU3ltYm9sLml0ZXJhdG9yXSgpIHtcbiAgICByZXR1cm4gdGhpcy52YWx1ZXNbU3ltYm9sLml0ZXJhdG9yXSgpO1xuICB9XG5cbiAgdG9TdHJpbmcoKSB7XG4gICAgdmFyIGksXG4gICAgICAgIHMgPSBcIlwiO1xuICAgIGZvciAoaSA9IDA7IGkgPCB0aGlzLnZhbHVlcy5sZW5ndGg7IGkrKykge1xuICAgICAgaWYgKHMgIT09IFwiXCIpIHtcbiAgICAgICAgcyArPSBcIiwgXCI7XG4gICAgICB9XG4gICAgICBzICs9IHRoaXMudmFsdWVzW2ldLnRvU3RyaW5nKCk7XG4gICAgfVxuXG4gICAgcmV0dXJuIFwie1wiICsgcyArIFwifVwiO1xuICB9XG5cbn1cblxubGV0IHByb2Nlc3NfY291bnRlciA9IC0xO1xuXG5jbGFzcyBQSUQge1xuICBjb25zdHJ1Y3RvcigpIHtcbiAgICBwcm9jZXNzX2NvdW50ZXIgPSBwcm9jZXNzX2NvdW50ZXIgKyAxO1xuICAgIHRoaXMuaWQgPSBwcm9jZXNzX2NvdW50ZXI7XG4gIH1cblxuICB0b1N0cmluZygpIHtcbiAgICByZXR1cm4gXCJQSUQjPDAuXCIgKyB0aGlzLmlkICsgXCIuMD5cIjtcbiAgfVxufVxuXG5jbGFzcyBJbnRlZ2VyIHt9XG5jbGFzcyBGbG9hdCB7fVxuXG5mdW5jdGlvbiBMaXN0KC4uLmFyZ3MpIHtcbiAgcmV0dXJuIE9iamVjdC5mcmVlemUoYXJncyk7XG59XG5cbmNsYXNzIFByb2Nlc3NTeXN0ZW0ge1xuXG4gIGNvbnN0cnVjdG9yKCkge1xuICAgIHRoaXMucGlkcyA9IG5ldyBNYXAoKTtcbiAgICB0aGlzLm1haWxib3hlcyA9IG5ldyBNYXAoKTtcbiAgICB0aGlzLm5hbWVzID0gbmV3IE1hcCgpO1xuICAgIHRoaXMubGlua3MgPSBuZXcgTWFwKCk7XG5cbiAgICB0aGlzLmN1cnJlbnRfcHJvY2VzcyA9IG51bGw7XG4gICAgdGhpcy5zdXNwZW5kZWQgPSBuZXcgTWFwKCk7XG5cbiAgICB0aGlzLm1haW5fcHJvY2Vzc19waWQgPSB0aGlzLnNwYXduKCk7XG4gICAgdGhpcy5zZXRfY3VycmVudCh0aGlzLm1haW5fcHJvY2Vzc19waWQpO1xuICB9XG5cbiAgc3Bhd24oKSB7XG4gICAgcmV0dXJuIHRoaXMuYWRkX3Byb2MoZmFsc2UpLnBpZDtcbiAgfVxuXG4gIHNwYXduX2xpbmsoKSB7XG4gICAgcmV0dXJuIHRoaXMuYWRkX3Byb2ModHJ1ZSkucGlkO1xuICB9XG5cbiAgbGluayhwaWQpIHtcbiAgICB0aGlzLmxpbmtzLmdldCh0aGlzLnBpZCgpKS5hZGQocGlkKTtcbiAgICB0aGlzLmxpbmtzLmdldChwaWQpLmFkZCh0aGlzLnBpZCgpKTtcbiAgfVxuXG4gIHVubGluayhwaWQpIHtcbiAgICB0aGlzLmxpbmtzLmdldCh0aGlzLnBpZCgpKS5kZWxldGUocGlkKTtcbiAgICB0aGlzLmxpbmtzLmdldChwaWQpLmRlbGV0ZSh0aGlzLnBpZCgpKTtcbiAgfVxuXG4gIHNldF9jdXJyZW50KGlkKSB7XG4gICAgbGV0IHBpZCA9IHRoaXMucGlkb2YoaWQpO1xuICAgIGlmIChwaWQgIT09IG51bGwpIHtcbiAgICAgIHRoaXMuY3VycmVudF9wcm9jZXNzID0gdGhpcy5waWRzLmdldChwaWQpO1xuICAgICAgdGhpcy5jdXJyZW50X3Byb2Nlc3Muc3RhdHVzID0gU3RhdGVzLlJVTk5JTkc7XG4gICAgfVxuICB9XG5cbiAgYWRkX3Byb2MobGlua2VkKSB7XG4gICAgbGV0IG5ld3BpZCA9IG5ldyBQSUQoKTtcbiAgICBsZXQgbWFpbGJveCA9IG5ldyBNYWlsYm94KCk7XG4gICAgbGV0IG5ld3Byb2MgPSBuZXcgUHJvY2VzcyhuZXdwaWQsIG1haWxib3gpO1xuXG4gICAgdGhpcy5waWRzLnNldChuZXdwaWQsIG5ld3Byb2MpO1xuICAgIHRoaXMubWFpbGJveGVzLnNldChuZXdwaWQsIG1haWxib3gpO1xuICAgIHRoaXMubGlua3Muc2V0KG5ld3BpZCwgbmV3IFNldCgpKTtcblxuICAgIGlmIChsaW5rZWQpIHtcbiAgICAgIHRoaXMubGluayhuZXdwaWQpO1xuICAgIH1cblxuICAgIHJldHVybiBuZXdwcm9jO1xuICB9XG5cbiAgcmVtb3ZlX3Byb2MocGlkKSB7XG4gICAgdGhpcy5waWRzLmRlbGV0ZShwaWQpO1xuICAgIHRoaXMudW5yZWdpc3RlcihwaWQpO1xuXG4gICAgaWYgKHRoaXMubGlua3MuaGFzKHBpZCkpIHtcbiAgICAgIGZvciAobGV0IGxpbmtwaWQgb2YgdGhpcy5saW5rcy5nZXQocGlkKSkge1xuICAgICAgICB0aGlzLmxpbmtzLmdldChsaW5rcGlkKS5kZWxldGUocGlkKTtcbiAgICAgIH1cblxuICAgICAgdGhpcy5saW5rcy5kZWxldGUocGlkKTtcbiAgICB9XG4gIH1cblxuICBleGl0KGlkKSB7XG4gICAgbGV0IHBpZCA9IHRoaXMucGlkb2YoaWQpO1xuICAgIHRoaXMucmVtb3ZlX3Byb2MoaWQpO1xuICB9XG5cbiAgcmVnaXN0ZXIobmFtZSwgcGlkKSB7XG4gICAgaWYgKCF0aGlzLm5hbWVzLmhhcyhuYW1lKSkge1xuICAgICAgdGhpcy5uYW1lcy5zZXQobmFtZSwgcGlkKTtcbiAgICAgIHJldHVybiBuYW1lO1xuICAgIH0gZWxzZSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoXCJOYW1lIGlzIGFscmVhZHkgcmVnaXN0ZXJlZCB0byBhbm90aGVyIHByb2Nlc3NcIik7XG4gICAgfVxuICB9XG5cbiAgcmVnaXN0ZXJlZChuYW1lKSB7XG4gICAgcmV0dXJuIHRoaXMubmFtZXMuaGFzKG5hbWUpID8gdGhpcy5uYW1lcy5nZXQobmFtZSkgOiBudWxsO1xuICB9XG5cbiAgdW5yZWdpc3RlcihwaWQpIHtcbiAgICBmb3IgKGxldCBuYW1lIG9mIHRoaXMubmFtZXMua2V5cygpKSB7XG4gICAgICBpZiAodGhpcy5uYW1lcy5oYXMobmFtZSkgJiYgdGhpcy5uYW1lcy5nZXQobmFtZSkgPT09IHBpZCkge1xuICAgICAgICB0aGlzLm5hbWVzLmRlbGV0ZShuYW1lKTtcbiAgICAgIH1cbiAgICB9XG4gIH1cblxuICBwaWQoKSB7XG4gICAgcmV0dXJuIHRoaXMuY3VycmVudF9wcm9jZXNzLnBpZDtcbiAgfVxuXG4gIHBpZG9mKGlkKSB7XG4gICAgaWYgKGlkIGluc3RhbmNlb2YgUElEKSB7XG4gICAgICByZXR1cm4gdGhpcy5waWRzLmhhcyhpZCkgPyBpZCA6IG51bGw7XG4gICAgfSBlbHNlIGlmIChpZCBpbnN0YW5jZW9mIFByb2Nlc3MpIHtcbiAgICAgIHJldHVybiBpZC5waWQ7XG4gICAgfSBlbHNlIHtcbiAgICAgIGxldCBwaWQgPSB0aGlzLnJlZ2lzdGVyZWQoaWQpO1xuICAgICAgaWYgKHBpZCA9PT0gbnVsbCkgdGhyb3cgXCJQcm9jZXNzIG5hbWUgbm90IHJlZ2lzdGVyZWQ6IFwiICsgaWQgKyBcIiAoXCIgKyB0eXBlb2YgaWQgKyBcIilcIjtcbiAgICAgIHJldHVybiBwaWQ7XG4gICAgfVxuICB9XG5cbiAgcHV0KGlkLCBrZXksIHZhbHVlKSB7XG4gICAgbGV0IHBpZCA9IHRoaXMucGlkb2YoaWQpO1xuICAgIGxldCBwcm9jZXNzID0gdGhpcy5waWRzLmdldChwaWQpO1xuICAgIHByb2Nlc3MuZGljdFtrZXldID0gdmFsdWU7XG4gIH1cblxuICBnZXQoaWQsIGtleSkge1xuICAgIGxldCBwaWQgPSB0aGlzLnBpZG9mKGlkKTtcbiAgICBsZXQgcHJvY2VzcyA9IHRoaXMucGlkcy5nZXQocGlkKTtcblxuICAgIGlmIChrZXkgIT0gbnVsbCkge1xuICAgICAgcmV0dXJuIHByb2Nlc3MuZGljdFtrZXldO1xuICAgIH0gZWxzZSB7XG4gICAgICByZXR1cm4gcHJvY2Vzcy5kaWN0O1xuICAgIH1cbiAgfVxuXG4gIGdldF9rZXlzKGlkKSB7XG4gICAgbGV0IHBpZCA9IHRoaXMucGlkb2YoaWQpO1xuICAgIGxldCBwcm9jZXNzID0gdGhpcy5waWRzLmdldChwaWQpO1xuXG4gICAgcmV0dXJuIE9iamVjdC5rZXlzKHByb2Nlc3MuZGljdCk7XG4gIH1cblxuICBlcmFzZShpZCwga2V5KSB7XG4gICAgbGV0IHBpZCA9IHRoaXMucGlkb2YoaWQpO1xuICAgIGxldCBwcm9jZXNzID0gdGhpcy5waWRzLmdldChwaWQpO1xuXG4gICAgaWYgKGtleSAhPSBudWxsKSB7XG4gICAgICBkZWxldGUgcHJvY2Vzcy5kaWN0W2tleV07XG4gICAgfSBlbHNlIHtcbiAgICAgIHByb2Nlc3MuZGljdCA9IHt9O1xuICAgIH1cbiAgfVxufVxuXG5jbGFzcyBCaXRTdHJpbmcge1xuICBjb25zdHJ1Y3RvciguLi5hcmdzKSB7XG4gICAgdGhpcy5yYXdfdmFsdWUgPSBmdW5jdGlvbiAoKSB7XG4gICAgICByZXR1cm4gT2JqZWN0LmZyZWV6ZShhcmdzKTtcbiAgICB9O1xuXG4gICAgdGhpcy52YWx1ZSA9IE9iamVjdC5mcmVlemUodGhpcy5wcm9jZXNzKGFyZ3MpKTtcbiAgfVxuXG4gIGdldChpbmRleCkge1xuICAgIHJldHVybiB0aGlzLnZhbHVlW2luZGV4XTtcbiAgfVxuXG4gIGNvdW50KCkge1xuICAgIHJldHVybiB0aGlzLnZhbHVlLmxlbmd0aDtcbiAgfVxuXG4gIFtTeW1ib2wuaXRlcmF0b3JdKCkge1xuICAgIHJldHVybiB0aGlzLnZhbHVlW1N5bWJvbC5pdGVyYXRvcl0oKTtcbiAgfVxuXG4gIHRvU3RyaW5nKCkge1xuICAgIHZhciBpLFxuICAgICAgICBzID0gXCJcIjtcbiAgICBmb3IgKGkgPSAwOyBpIDwgdGhpcy5jb3VudCgpOyBpKyspIHtcbiAgICAgIGlmIChzICE9PSBcIlwiKSB7XG4gICAgICAgIHMgKz0gXCIsIFwiO1xuICAgICAgfVxuICAgICAgcyArPSB0aGlzW2ldLnRvU3RyaW5nKCk7XG4gICAgfVxuXG4gICAgcmV0dXJuIFwiPDxcIiArIHMgKyBcIj4+XCI7XG4gIH1cblxuICBwcm9jZXNzKCkge1xuICAgIGxldCBwcm9jZXNzZWRfdmFsdWVzID0gW107XG5cbiAgICB2YXIgaTtcbiAgICBmb3IgKGkgPSAwOyBpIDwgdGhpcy5yYXdfdmFsdWUoKS5sZW5ndGg7IGkrKykge1xuICAgICAgbGV0IHByb2Nlc3NlZF92YWx1ZSA9IHRoaXNbXCJwcm9jZXNzX1wiICsgdGhpcy5yYXdfdmFsdWUoKVtpXS50eXBlXSh0aGlzLnJhd192YWx1ZSgpW2ldKTtcblxuICAgICAgZm9yIChsZXQgYXR0ciBvZiB0aGlzLnJhd192YWx1ZSgpW2ldLmF0dHJpYnV0ZXMpIHtcbiAgICAgICAgcHJvY2Vzc2VkX3ZhbHVlID0gdGhpc1tcInByb2Nlc3NfXCIgKyBhdHRyXShwcm9jZXNzZWRfdmFsdWUpO1xuICAgICAgfVxuXG4gICAgICBwcm9jZXNzZWRfdmFsdWVzID0gcHJvY2Vzc2VkX3ZhbHVlcy5jb25jYXQocHJvY2Vzc2VkX3ZhbHVlKTtcbiAgICB9XG5cbiAgICByZXR1cm4gcHJvY2Vzc2VkX3ZhbHVlcztcbiAgfVxuXG4gIHByb2Nlc3NfaW50ZWdlcih2YWx1ZSkge1xuICAgIHJldHVybiB2YWx1ZS52YWx1ZTtcbiAgfVxuXG4gIHByb2Nlc3NfZmxvYXQodmFsdWUpIHtcbiAgICBpZiAodmFsdWUuc2l6ZSA9PT0gNjQpIHtcbiAgICAgIHJldHVybiBCaXRTdHJpbmcuZmxvYXQ2NFRvQnl0ZXModmFsdWUudmFsdWUpO1xuICAgIH0gZWxzZSBpZiAodmFsdWUuc2l6ZSA9PT0gMzIpIHtcbiAgICAgIHJldHVybiBCaXRTdHJpbmcuZmxvYXQzMlRvQnl0ZXModmFsdWUudmFsdWUpO1xuICAgIH1cblxuICAgIHRocm93IG5ldyBFcnJvcihcIkludmFsaWQgc2l6ZSBmb3IgZmxvYXRcIik7XG4gIH1cblxuICBwcm9jZXNzX2JpdHN0cmluZyh2YWx1ZSkge1xuICAgIHJldHVybiB2YWx1ZS52YWx1ZS52YWx1ZTtcbiAgfVxuXG4gIHByb2Nlc3NfYmluYXJ5KHZhbHVlKSB7XG4gICAgcmV0dXJuIEJpdFN0cmluZy50b1VURjhBcnJheSh2YWx1ZS52YWx1ZSk7XG4gIH1cblxuICBwcm9jZXNzX3V0ZjgodmFsdWUpIHtcbiAgICByZXR1cm4gQml0U3RyaW5nLnRvVVRGOEFycmF5KHZhbHVlLnZhbHVlKTtcbiAgfVxuXG4gIHByb2Nlc3NfdXRmMTYodmFsdWUpIHtcbiAgICByZXR1cm4gQml0U3RyaW5nLnRvVVRGMTZBcnJheSh2YWx1ZS52YWx1ZSk7XG4gIH1cblxuICBwcm9jZXNzX3V0ZjMyKHZhbHVlKSB7XG4gICAgcmV0dXJuIEJpdFN0cmluZy50b1VURjMyQXJyYXkodmFsdWUudmFsdWUpO1xuICB9XG5cbiAgcHJvY2Vzc19zaWduZWQodmFsdWUpIHtcbiAgICByZXR1cm4gbmV3IFVpbnQ4QXJyYXkoW3ZhbHVlXSlbMF07XG4gIH1cblxuICBwcm9jZXNzX3Vuc2lnbmVkKHZhbHVlKSB7XG4gICAgcmV0dXJuIHZhbHVlO1xuICB9XG5cbiAgcHJvY2Vzc19uYXRpdmUodmFsdWUpIHtcbiAgICByZXR1cm4gdmFsdWU7XG4gIH1cblxuICBwcm9jZXNzX2JpZyh2YWx1ZSkge1xuICAgIHJldHVybiB2YWx1ZTtcbiAgfVxuXG4gIHByb2Nlc3NfbGl0dGxlKHZhbHVlKSB7XG4gICAgcmV0dXJuIHZhbHVlLnJldmVyc2UoKTtcbiAgfVxuXG4gIHByb2Nlc3Nfc2l6ZSh2YWx1ZSkge1xuICAgIHJldHVybiB2YWx1ZTtcbiAgfVxuXG4gIHByb2Nlc3NfdW5pdCh2YWx1ZSkge1xuICAgIHJldHVybiB2YWx1ZTtcbiAgfVxuXG4gIHN0YXRpYyBpbnRlZ2VyKHZhbHVlKSB7XG4gICAgcmV0dXJuIEJpdFN0cmluZy53cmFwKHZhbHVlLCB7IFwidHlwZVwiOiBcImludGVnZXJcIiwgXCJ1bml0XCI6IDEsIFwic2l6ZVwiOiA4IH0pO1xuICB9XG5cbiAgc3RhdGljIGZsb2F0KHZhbHVlKSB7XG4gICAgcmV0dXJuIEJpdFN0cmluZy53cmFwKHZhbHVlLCB7IFwidHlwZVwiOiBcImZsb2F0XCIsIFwidW5pdFwiOiAxLCBcInNpemVcIjogNjQgfSk7XG4gIH1cblxuICBzdGF0aWMgYml0c3RyaW5nKHZhbHVlKSB7XG4gICAgcmV0dXJuIEJpdFN0cmluZy53cmFwKHZhbHVlLCB7IFwidHlwZVwiOiBcImJpdHN0cmluZ1wiLCBcInVuaXRcIjogMSwgXCJzaXplXCI6IHZhbHVlLmxlbmd0aCB9KTtcbiAgfVxuXG4gIHN0YXRpYyBiaXRzKHZhbHVlKSB7XG4gICAgcmV0dXJuIEJpdFN0cmluZy5iaXRzdHJpbmcodmFsdWUpO1xuICB9XG5cbiAgc3RhdGljIGJpbmFyeSh2YWx1ZSkge1xuICAgIHJldHVybiBCaXRTdHJpbmcud3JhcCh2YWx1ZSwgeyBcInR5cGVcIjogXCJiaW5hcnlcIiwgXCJ1bml0XCI6IDgsIFwic2l6ZVwiOiB2YWx1ZS5sZW5ndGggfSk7XG4gIH1cblxuICBzdGF0aWMgYnl0ZXModmFsdWUpIHtcbiAgICByZXR1cm4gQml0U3RyaW5nLmJpbmFyeSh2YWx1ZSk7XG4gIH1cblxuICBzdGF0aWMgdXRmOCh2YWx1ZSkge1xuICAgIHJldHVybiBCaXRTdHJpbmcud3JhcCh2YWx1ZSwgeyBcInR5cGVcIjogXCJ1dGY4XCIgfSk7XG4gIH1cblxuICBzdGF0aWMgdXRmMTYodmFsdWUpIHtcbiAgICByZXR1cm4gQml0U3RyaW5nLndyYXAodmFsdWUsIHsgXCJ0eXBlXCI6IFwidXRmMTZcIiB9KTtcbiAgfVxuXG4gIHN0YXRpYyB1dGYzMih2YWx1ZSkge1xuICAgIHJldHVybiBCaXRTdHJpbmcud3JhcCh2YWx1ZSwgeyBcInR5cGVcIjogXCJ1dGYzMlwiIH0pO1xuICB9XG5cbiAgc3RhdGljIHNpZ25lZCh2YWx1ZSkge1xuICAgIHJldHVybiBCaXRTdHJpbmcud3JhcCh2YWx1ZSwge30sIFwic2lnbmVkXCIpO1xuICB9XG5cbiAgc3RhdGljIHVuc2lnbmVkKHZhbHVlKSB7XG4gICAgcmV0dXJuIEJpdFN0cmluZy53cmFwKHZhbHVlLCB7fSwgXCJ1bnNpZ25lZFwiKTtcbiAgfVxuXG4gIHN0YXRpYyBuYXRpdmUodmFsdWUpIHtcbiAgICByZXR1cm4gQml0U3RyaW5nLndyYXAodmFsdWUsIHt9LCBcIm5hdGl2ZVwiKTtcbiAgfVxuXG4gIHN0YXRpYyBiaWcodmFsdWUpIHtcbiAgICByZXR1cm4gQml0U3RyaW5nLndyYXAodmFsdWUsIHt9LCBcImJpZ1wiKTtcbiAgfVxuXG4gIHN0YXRpYyBsaXR0bGUodmFsdWUpIHtcbiAgICByZXR1cm4gQml0U3RyaW5nLndyYXAodmFsdWUsIHt9LCBcImxpdHRsZVwiKTtcbiAgfVxuXG4gIHN0YXRpYyBzaXplKHZhbHVlLCBjb3VudCkge1xuICAgIHJldHVybiBCaXRTdHJpbmcud3JhcCh2YWx1ZSwgeyBcInNpemVcIjogY291bnQgfSk7XG4gIH1cblxuICBzdGF0aWMgdW5pdCh2YWx1ZSwgY291bnQpIHtcbiAgICByZXR1cm4gQml0U3RyaW5nLndyYXAodmFsdWUsIHsgXCJ1bml0XCI6IGNvdW50IH0pO1xuICB9XG5cbiAgc3RhdGljIHdyYXAodmFsdWUsIG9wdCwgbmV3X2F0dHJpYnV0ZSA9IG51bGwpIHtcbiAgICBsZXQgdGhlX3ZhbHVlID0gdmFsdWU7XG5cbiAgICBpZiAoISh2YWx1ZSBpbnN0YW5jZW9mIE9iamVjdCkpIHtcbiAgICAgIHRoZV92YWx1ZSA9IHsgXCJ2YWx1ZVwiOiB2YWx1ZSwgXCJhdHRyaWJ1dGVzXCI6IFtdIH07XG4gICAgfVxuXG4gICAgdGhlX3ZhbHVlID0gT2JqZWN0LmFzc2lnbih0aGVfdmFsdWUsIG9wdCk7XG5cbiAgICBpZiAobmV3X2F0dHJpYnV0ZSkge1xuICAgICAgdGhlX3ZhbHVlLmF0dHJpYnV0ZXMucHVzaChuZXdfYXR0cmlidXRlKTtcbiAgICB9XG5cbiAgICByZXR1cm4gdGhlX3ZhbHVlO1xuICB9XG5cbiAgc3RhdGljIHRvVVRGOEFycmF5KHN0cikge1xuICAgIHZhciB1dGY4ID0gW107XG4gICAgZm9yICh2YXIgaSA9IDA7IGkgPCBzdHIubGVuZ3RoOyBpKyspIHtcbiAgICAgIHZhciBjaGFyY29kZSA9IHN0ci5jaGFyQ29kZUF0KGkpO1xuICAgICAgaWYgKGNoYXJjb2RlIDwgMTI4KSB7XG4gICAgICAgIHV0ZjgucHVzaChjaGFyY29kZSk7XG4gICAgICB9IGVsc2UgaWYgKGNoYXJjb2RlIDwgMjA0OCkge1xuICAgICAgICB1dGY4LnB1c2goMTkyIHwgY2hhcmNvZGUgPj4gNiwgMTI4IHwgY2hhcmNvZGUgJiA2Myk7XG4gICAgICB9IGVsc2UgaWYgKGNoYXJjb2RlIDwgNTUyOTYgfHwgY2hhcmNvZGUgPj0gNTczNDQpIHtcbiAgICAgICAgdXRmOC5wdXNoKDIyNCB8IGNoYXJjb2RlID4+IDEyLCAxMjggfCBjaGFyY29kZSA+PiA2ICYgNjMsIDEyOCB8IGNoYXJjb2RlICYgNjMpO1xuICAgICAgfVxuICAgICAgLy8gc3Vycm9nYXRlIHBhaXJcbiAgICAgIGVsc2Uge1xuICAgICAgICBpKys7XG4gICAgICAgIC8vIFVURi0xNiBlbmNvZGVzIDB4MTAwMDAtMHgxMEZGRkYgYnlcbiAgICAgICAgLy8gc3VidHJhY3RpbmcgMHgxMDAwMCBhbmQgc3BsaXR0aW5nIHRoZVxuICAgICAgICAvLyAyMCBiaXRzIG9mIDB4MC0weEZGRkZGIGludG8gdHdvIGhhbHZlc1xuICAgICAgICBjaGFyY29kZSA9IDY1NTM2ICsgKChjaGFyY29kZSAmIDEwMjMpIDw8IDEwIHwgc3RyLmNoYXJDb2RlQXQoaSkgJiAxMDIzKTtcbiAgICAgICAgdXRmOC5wdXNoKDI0MCB8IGNoYXJjb2RlID4+IDE4LCAxMjggfCBjaGFyY29kZSA+PiAxMiAmIDYzLCAxMjggfCBjaGFyY29kZSA+PiA2ICYgNjMsIDEyOCB8IGNoYXJjb2RlICYgNjMpO1xuICAgICAgfVxuICAgIH1cbiAgICByZXR1cm4gdXRmODtcbiAgfVxuXG4gIHN0YXRpYyB0b1VURjE2QXJyYXkoc3RyKSB7XG4gICAgdmFyIHV0ZjE2ID0gW107XG4gICAgZm9yICh2YXIgaSA9IDA7IGkgPCBzdHIubGVuZ3RoOyBpKyspIHtcbiAgICAgIHZhciBjb2RlUG9pbnQgPSBzdHIuY29kZVBvaW50QXQoaSk7XG5cbiAgICAgIGlmIChjb2RlUG9pbnQgPD0gMjU1KSB7XG4gICAgICAgIHV0ZjE2LnB1c2goMCk7XG4gICAgICAgIHV0ZjE2LnB1c2goY29kZVBvaW50KTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHV0ZjE2LnB1c2goY29kZVBvaW50ID4+IDggJiAyNTUpO1xuICAgICAgICB1dGYxNi5wdXNoKGNvZGVQb2ludCAmIDI1NSk7XG4gICAgICB9XG4gICAgfVxuICAgIHJldHVybiB1dGYxNjtcbiAgfVxuXG4gIHN0YXRpYyB0b1VURjMyQXJyYXkoc3RyKSB7XG4gICAgdmFyIHV0ZjMyID0gW107XG4gICAgZm9yICh2YXIgaSA9IDA7IGkgPCBzdHIubGVuZ3RoOyBpKyspIHtcbiAgICAgIHZhciBjb2RlUG9pbnQgPSBzdHIuY29kZVBvaW50QXQoaSk7XG5cbiAgICAgIGlmIChjb2RlUG9pbnQgPD0gMjU1KSB7XG4gICAgICAgIHV0ZjMyLnB1c2goMCk7XG4gICAgICAgIHV0ZjMyLnB1c2goMCk7XG4gICAgICAgIHV0ZjMyLnB1c2goMCk7XG4gICAgICAgIHV0ZjMyLnB1c2goY29kZVBvaW50KTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHV0ZjMyLnB1c2goMCk7XG4gICAgICAgIHV0ZjMyLnB1c2goMCk7XG4gICAgICAgIHV0ZjMyLnB1c2goY29kZVBvaW50ID4+IDggJiAyNTUpO1xuICAgICAgICB1dGYzMi5wdXNoKGNvZGVQb2ludCAmIDI1NSk7XG4gICAgICB9XG4gICAgfVxuICAgIHJldHVybiB1dGYzMjtcbiAgfVxuXG4gIC8vaHR0cDovL3N0YWNrb3ZlcmZsb3cuY29tL3F1ZXN0aW9ucy8yMDAzNDkzL2phdmFzY3JpcHQtZmxvYXQtZnJvbS10by1iaXRzXG4gIHN0YXRpYyBmbG9hdDMyVG9CeXRlcyhmKSB7XG4gICAgdmFyIGJ5dGVzID0gW107XG5cbiAgICB2YXIgYnVmID0gbmV3IEFycmF5QnVmZmVyKDQpO1xuICAgIG5ldyBGbG9hdDMyQXJyYXkoYnVmKVswXSA9IGY7XG5cbiAgICBsZXQgaW50VmVyc2lvbiA9IG5ldyBVaW50MzJBcnJheShidWYpWzBdO1xuXG4gICAgYnl0ZXMucHVzaChpbnRWZXJzaW9uID4+IDI0ICYgMjU1KTtcbiAgICBieXRlcy5wdXNoKGludFZlcnNpb24gPj4gMTYgJiAyNTUpO1xuICAgIGJ5dGVzLnB1c2goaW50VmVyc2lvbiA+PiA4ICYgMjU1KTtcbiAgICBieXRlcy5wdXNoKGludFZlcnNpb24gJiAyNTUpO1xuXG4gICAgcmV0dXJuIGJ5dGVzO1xuICB9XG5cbiAgc3RhdGljIGZsb2F0NjRUb0J5dGVzKGYpIHtcbiAgICB2YXIgYnl0ZXMgPSBbXTtcblxuICAgIHZhciBidWYgPSBuZXcgQXJyYXlCdWZmZXIoOCk7XG4gICAgbmV3IEZsb2F0NjRBcnJheShidWYpWzBdID0gZjtcblxuICAgIHZhciBpbnRWZXJzaW9uMSA9IG5ldyBVaW50MzJBcnJheShidWYpWzBdO1xuICAgIHZhciBpbnRWZXJzaW9uMiA9IG5ldyBVaW50MzJBcnJheShidWYpWzFdO1xuXG4gICAgYnl0ZXMucHVzaChpbnRWZXJzaW9uMiA+PiAyNCAmIDI1NSk7XG4gICAgYnl0ZXMucHVzaChpbnRWZXJzaW9uMiA+PiAxNiAmIDI1NSk7XG4gICAgYnl0ZXMucHVzaChpbnRWZXJzaW9uMiA+PiA4ICYgMjU1KTtcbiAgICBieXRlcy5wdXNoKGludFZlcnNpb24yICYgMjU1KTtcblxuICAgIGJ5dGVzLnB1c2goaW50VmVyc2lvbjEgPj4gMjQgJiAyNTUpO1xuICAgIGJ5dGVzLnB1c2goaW50VmVyc2lvbjEgPj4gMTYgJiAyNTUpO1xuICAgIGJ5dGVzLnB1c2goaW50VmVyc2lvbjEgPj4gOCAmIDI1NSk7XG4gICAgYnl0ZXMucHVzaChpbnRWZXJzaW9uMSAmIDI1NSk7XG5cbiAgICByZXR1cm4gYnl0ZXM7XG4gIH1cbn1cblxuLyogQGZsb3cgKi9cblxuY2xhc3MgVmFyaWFibGUge1xuXG4gIGNvbnN0cnVjdG9yKG5hbWUgPSBudWxsKSB7XG4gICAgdGhpcy5uYW1lID0gbmFtZTtcbiAgfVxufVxuXG5jbGFzcyBXaWxkY2FyZCB7XG4gIGNvbnN0cnVjdG9yKCkge31cbn1cblxuY2xhc3MgU3RhcnRzV2l0aCB7XG5cbiAgY29uc3RydWN0b3IocHJlZml4KSB7XG4gICAgdGhpcy5wcmVmaXggPSBwcmVmaXg7XG4gIH1cbn1cblxuY2xhc3MgQ2FwdHVyZSB7XG5cbiAgY29uc3RydWN0b3IodmFsdWUpIHtcbiAgICB0aGlzLnZhbHVlID0gdmFsdWU7XG4gIH1cbn1cblxuY2xhc3MgSGVhZFRhaWwge1xuICBjb25zdHJ1Y3RvcigpIHt9XG59XG5cbmNsYXNzIFR5cGUge1xuXG4gIGNvbnN0cnVjdG9yKHR5cGUsIG9ialBhdHRlcm4gPSB7fSkge1xuICAgIHRoaXMudHlwZSA9IHR5cGU7XG4gICAgdGhpcy5vYmpQYXR0ZXJuID0gb2JqUGF0dGVybjtcbiAgfVxufVxuXG5jbGFzcyBCb3VuZCB7XG5cbiAgY29uc3RydWN0b3IodmFsdWUpIHtcbiAgICB0aGlzLnZhbHVlID0gdmFsdWU7XG4gIH1cbn1cblxuZnVuY3Rpb24gdmFyaWFibGUobmFtZSA9IG51bGwpIHtcbiAgcmV0dXJuIG5ldyBWYXJpYWJsZShuYW1lKTtcbn1cblxuZnVuY3Rpb24gd2lsZGNhcmQoKSB7XG4gIHJldHVybiBuZXcgV2lsZGNhcmQoKTtcbn1cblxuZnVuY3Rpb24gc3RhcnRzV2l0aChwcmVmaXgpIHtcbiAgcmV0dXJuIG5ldyBTdGFydHNXaXRoKHByZWZpeCk7XG59XG5cbmZ1bmN0aW9uIGNhcHR1cmUodmFsdWUpIHtcbiAgcmV0dXJuIG5ldyBDYXB0dXJlKHZhbHVlKTtcbn1cblxuZnVuY3Rpb24gaGVhZFRhaWwoKSB7XG4gIHJldHVybiBuZXcgSGVhZFRhaWwoKTtcbn1cblxuZnVuY3Rpb24gdHlwZSh0eXBlLCBvYmpQYXR0ZXJuID0ge30pIHtcbiAgcmV0dXJuIG5ldyBUeXBlKHR5cGUsIG9ialBhdHRlcm4pO1xufVxuXG5mdW5jdGlvbiBib3VuZCh2YWx1ZSkge1xuICByZXR1cm4gbmV3IEJvdW5kKHZhbHVlKTtcbn1cblxuZnVuY3Rpb24gaXNfbnVtYmVyJDIodmFsdWUpIHtcbiAgcmV0dXJuIHR5cGVvZiB2YWx1ZSA9PT0gJ251bWJlcic7XG59XG5cbmZ1bmN0aW9uIGlzX3N0cmluZyh2YWx1ZSkge1xuICByZXR1cm4gdHlwZW9mIHZhbHVlID09PSAnc3RyaW5nJztcbn1cblxuZnVuY3Rpb24gaXNfYm9vbGVhbiQyKHZhbHVlKSB7XG4gIHJldHVybiB0eXBlb2YgdmFsdWUgPT09ICdib29sZWFuJztcbn1cblxuZnVuY3Rpb24gaXNfc3ltYm9sKHZhbHVlKSB7XG4gIHJldHVybiB0eXBlb2YgdmFsdWUgPT09ICdzeW1ib2wnO1xufVxuXG5mdW5jdGlvbiBpc19udWxsKHZhbHVlKSB7XG4gIHJldHVybiB2YWx1ZSA9PT0gbnVsbDtcbn1cblxuZnVuY3Rpb24gaXNfdW5kZWZpbmVkKHZhbHVlKSB7XG4gIHJldHVybiB0eXBlb2YgdmFsdWUgPT09ICd1bmRlZmluZWQnO1xufVxuXG5mdW5jdGlvbiBpc19mdW5jdGlvbiQyKHZhbHVlKSB7XG4gIHJldHVybiBPYmplY3QucHJvdG90eXBlLnRvU3RyaW5nLmNhbGwodmFsdWUpID09ICdbb2JqZWN0IEZ1bmN0aW9uXSc7XG59XG5cbmZ1bmN0aW9uIGlzX3ZhcmlhYmxlKHZhbHVlKSB7XG4gIHJldHVybiB2YWx1ZSBpbnN0YW5jZW9mIFZhcmlhYmxlO1xufVxuXG5mdW5jdGlvbiBpc193aWxkY2FyZCh2YWx1ZSkge1xuICByZXR1cm4gdmFsdWUgaW5zdGFuY2VvZiBXaWxkY2FyZDtcbn1cblxuZnVuY3Rpb24gaXNfaGVhZFRhaWwodmFsdWUpIHtcbiAgcmV0dXJuIHZhbHVlIGluc3RhbmNlb2YgSGVhZFRhaWw7XG59XG5cbmZ1bmN0aW9uIGlzX2NhcHR1cmUodmFsdWUpIHtcbiAgcmV0dXJuIHZhbHVlIGluc3RhbmNlb2YgQ2FwdHVyZTtcbn1cblxuZnVuY3Rpb24gaXNfdHlwZSh2YWx1ZSkge1xuICByZXR1cm4gdmFsdWUgaW5zdGFuY2VvZiBUeXBlO1xufVxuXG5mdW5jdGlvbiBpc19zdGFydHNXaXRoKHZhbHVlKSB7XG4gIHJldHVybiB2YWx1ZSBpbnN0YW5jZW9mIFN0YXJ0c1dpdGg7XG59XG5cbmZ1bmN0aW9uIGlzX2JvdW5kKHZhbHVlKSB7XG4gIHJldHVybiB2YWx1ZSBpbnN0YW5jZW9mIEJvdW5kO1xufVxuXG5mdW5jdGlvbiBpc19vYmplY3QodmFsdWUpIHtcbiAgcmV0dXJuIHR5cGVvZiB2YWx1ZSA9PT0gJ29iamVjdCc7XG59XG5cbmZ1bmN0aW9uIGlzX2FycmF5KHZhbHVlKSB7XG4gIHJldHVybiBBcnJheS5pc0FycmF5KHZhbHVlKTtcbn1cblxudmFyIENoZWNrcyA9IHtcbiAgaXNfbnVtYmVyOiBpc19udW1iZXIkMixcbiAgaXNfc3RyaW5nLFxuICBpc19ib29sZWFuOiBpc19ib29sZWFuJDIsXG4gIGlzX3N5bWJvbCxcbiAgaXNfbnVsbCxcbiAgaXNfdW5kZWZpbmVkLFxuICBpc19mdW5jdGlvbjogaXNfZnVuY3Rpb24kMixcbiAgaXNfdmFyaWFibGUsXG4gIGlzX3dpbGRjYXJkLFxuICBpc19oZWFkVGFpbCxcbiAgaXNfY2FwdHVyZSxcbiAgaXNfdHlwZSxcbiAgaXNfc3RhcnRzV2l0aCxcbiAgaXNfYm91bmQsXG4gIGlzX29iamVjdCxcbiAgaXNfYXJyYXlcbn07XG5cbmZ1bmN0aW9uIHJlc29sdmVTeW1ib2wocGF0dGVybikge1xuICByZXR1cm4gZnVuY3Rpb24gKHZhbHVlKSB7XG4gICAgcmV0dXJuIENoZWNrcy5pc19zeW1ib2wodmFsdWUpICYmIHZhbHVlID09PSBwYXR0ZXJuO1xuICB9O1xufVxuXG5mdW5jdGlvbiByZXNvbHZlU3RyaW5nKHBhdHRlcm4pIHtcbiAgcmV0dXJuIGZ1bmN0aW9uICh2YWx1ZSkge1xuICAgIHJldHVybiBDaGVja3MuaXNfc3RyaW5nKHZhbHVlKSAmJiB2YWx1ZSA9PT0gcGF0dGVybjtcbiAgfTtcbn1cblxuZnVuY3Rpb24gcmVzb2x2ZU51bWJlcihwYXR0ZXJuKSB7XG4gIHJldHVybiBmdW5jdGlvbiAodmFsdWUpIHtcbiAgICByZXR1cm4gQ2hlY2tzLmlzX251bWJlcih2YWx1ZSkgJiYgdmFsdWUgPT09IHBhdHRlcm47XG4gIH07XG59XG5cbmZ1bmN0aW9uIHJlc29sdmVCb29sZWFuKHBhdHRlcm4pIHtcbiAgcmV0dXJuIGZ1bmN0aW9uICh2YWx1ZSkge1xuICAgIHJldHVybiBDaGVja3MuaXNfYm9vbGVhbih2YWx1ZSkgJiYgdmFsdWUgPT09IHBhdHRlcm47XG4gIH07XG59XG5cbmZ1bmN0aW9uIHJlc29sdmVGdW5jdGlvbihwYXR0ZXJuKSB7XG4gIHJldHVybiBmdW5jdGlvbiAodmFsdWUpIHtcbiAgICByZXR1cm4gQ2hlY2tzLmlzX2Z1bmN0aW9uKHZhbHVlKSAmJiB2YWx1ZSA9PT0gcGF0dGVybjtcbiAgfTtcbn1cblxuZnVuY3Rpb24gcmVzb2x2ZU51bGwocGF0dGVybikge1xuICByZXR1cm4gZnVuY3Rpb24gKHZhbHVlKSB7XG4gICAgcmV0dXJuIENoZWNrcy5pc19udWxsKHZhbHVlKTtcbiAgfTtcbn1cblxuZnVuY3Rpb24gcmVzb2x2ZUJvdW5kKHBhdHRlcm4pIHtcbiAgcmV0dXJuIGZ1bmN0aW9uICh2YWx1ZSwgYXJncykge1xuICAgIGlmICh0eXBlb2YgdmFsdWUgPT09IHR5cGVvZiBwYXR0ZXJuLnZhbHVlICYmIHZhbHVlID09PSBwYXR0ZXJuLnZhbHVlKSB7XG4gICAgICBhcmdzLnB1c2godmFsdWUpO1xuICAgICAgcmV0dXJuIHRydWU7XG4gICAgfVxuXG4gICAgcmV0dXJuIGZhbHNlO1xuICB9O1xufVxuXG5mdW5jdGlvbiByZXNvbHZlV2lsZGNhcmQoKSB7XG4gIHJldHVybiBmdW5jdGlvbiAoKSB7XG4gICAgcmV0dXJuIHRydWU7XG4gIH07XG59XG5cbmZ1bmN0aW9uIHJlc29sdmVWYXJpYWJsZSgpIHtcbiAgcmV0dXJuIGZ1bmN0aW9uICh2YWx1ZSwgYXJncykge1xuICAgIGFyZ3MucHVzaCh2YWx1ZSk7XG4gICAgcmV0dXJuIHRydWU7XG4gIH07XG59XG5cbmZ1bmN0aW9uIHJlc29sdmVIZWFkVGFpbCgpIHtcbiAgcmV0dXJuIGZ1bmN0aW9uICh2YWx1ZSwgYXJncykge1xuICAgIGlmICghQ2hlY2tzLmlzX2FycmF5KHZhbHVlKSB8fCB2YWx1ZS5sZW5ndGggPCAyKSB7XG4gICAgICByZXR1cm4gZmFsc2U7XG4gICAgfVxuXG4gICAgY29uc3QgaGVhZCA9IHZhbHVlWzBdO1xuICAgIGNvbnN0IHRhaWwgPSB2YWx1ZS5zbGljZSgxKTtcblxuICAgIGFyZ3MucHVzaChoZWFkKTtcbiAgICBhcmdzLnB1c2godGFpbCk7XG5cbiAgICByZXR1cm4gdHJ1ZTtcbiAgfTtcbn1cblxuZnVuY3Rpb24gcmVzb2x2ZUNhcHR1cmUocGF0dGVybikge1xuICBjb25zdCBtYXRjaGVzID0gYnVpbGRNYXRjaChwYXR0ZXJuLnZhbHVlKTtcblxuICByZXR1cm4gZnVuY3Rpb24gKHZhbHVlLCBhcmdzKSB7XG4gICAgaWYgKG1hdGNoZXModmFsdWUsIGFyZ3MpKSB7XG4gICAgICBhcmdzLnB1c2godmFsdWUpO1xuICAgICAgcmV0dXJuIHRydWU7XG4gICAgfVxuXG4gICAgcmV0dXJuIGZhbHNlO1xuICB9O1xufVxuXG5mdW5jdGlvbiByZXNvbHZlU3RhcnRzV2l0aChwYXR0ZXJuKSB7XG4gIGNvbnN0IHByZWZpeCA9IHBhdHRlcm4ucHJlZml4O1xuXG4gIHJldHVybiBmdW5jdGlvbiAodmFsdWUsIGFyZ3MpIHtcbiAgICBpZiAoQ2hlY2tzLmlzX3N0cmluZyh2YWx1ZSkgJiYgdmFsdWUuc3RhcnRzV2l0aChwcmVmaXgpKSB7XG4gICAgICBhcmdzLnB1c2godmFsdWUuc3Vic3RyaW5nKHByZWZpeC5sZW5ndGgpKTtcbiAgICAgIHJldHVybiB0cnVlO1xuICAgIH1cblxuICAgIHJldHVybiBmYWxzZTtcbiAgfTtcbn1cblxuZnVuY3Rpb24gcmVzb2x2ZVR5cGUocGF0dGVybikge1xuICByZXR1cm4gZnVuY3Rpb24gKHZhbHVlLCBhcmdzKSB7XG4gICAgaWYgKHZhbHVlIGluc3RhbmNlb2YgcGF0dGVybi50eXBlKSB7XG4gICAgICBjb25zdCBtYXRjaGVzID0gYnVpbGRNYXRjaChwYXR0ZXJuLm9ialBhdHRlcm4pO1xuICAgICAgcmV0dXJuIG1hdGNoZXModmFsdWUsIGFyZ3MpICYmIGFyZ3MucHVzaCh2YWx1ZSkgPiAwO1xuICAgIH1cblxuICAgIHJldHVybiBmYWxzZTtcbiAgfTtcbn1cblxuZnVuY3Rpb24gcmVzb2x2ZUFycmF5KHBhdHRlcm4pIHtcbiAgY29uc3QgbWF0Y2hlcyA9IHBhdHRlcm4ubWFwKHggPT4gYnVpbGRNYXRjaCh4KSk7XG5cbiAgcmV0dXJuIGZ1bmN0aW9uICh2YWx1ZSwgYXJncykge1xuICAgIGlmICghQ2hlY2tzLmlzX2FycmF5KHZhbHVlKSB8fCB2YWx1ZS5sZW5ndGggIT0gcGF0dGVybi5sZW5ndGgpIHtcbiAgICAgIHJldHVybiBmYWxzZTtcbiAgICB9XG5cbiAgICByZXR1cm4gdmFsdWUuZXZlcnkoZnVuY3Rpb24gKHYsIGkpIHtcbiAgICAgIHJldHVybiBtYXRjaGVzW2ldKHZhbHVlW2ldLCBhcmdzKTtcbiAgICB9KTtcbiAgfTtcbn1cblxuZnVuY3Rpb24gcmVzb2x2ZU9iamVjdChwYXR0ZXJuKSB7XG4gIGxldCBtYXRjaGVzID0ge307XG5cbiAgZm9yIChsZXQga2V5IG9mIE9iamVjdC5rZXlzKHBhdHRlcm4pLmNvbmNhdChPYmplY3QuZ2V0T3duUHJvcGVydHlTeW1ib2xzKHBhdHRlcm4pKSkge1xuICAgIG1hdGNoZXNba2V5XSA9IGJ1aWxkTWF0Y2gocGF0dGVybltrZXldKTtcbiAgfVxuXG4gIHJldHVybiBmdW5jdGlvbiAodmFsdWUsIGFyZ3MpIHtcbiAgICBpZiAoIUNoZWNrcy5pc19vYmplY3QodmFsdWUpIHx8IHBhdHRlcm4ubGVuZ3RoID4gdmFsdWUubGVuZ3RoKSB7XG4gICAgICByZXR1cm4gZmFsc2U7XG4gICAgfVxuXG4gICAgZm9yIChsZXQga2V5IG9mIE9iamVjdC5rZXlzKHBhdHRlcm4pLmNvbmNhdChPYmplY3QuZ2V0T3duUHJvcGVydHlTeW1ib2xzKHBhdHRlcm4pKSkge1xuICAgICAgaWYgKCEoa2V5IGluIHZhbHVlKSB8fCAhbWF0Y2hlc1trZXldKHZhbHVlW2tleV0sIGFyZ3MpKSB7XG4gICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICByZXR1cm4gdHJ1ZTtcbiAgfTtcbn1cblxuZnVuY3Rpb24gcmVzb2x2ZU5vTWF0Y2goKSB7XG4gIHJldHVybiBmdW5jdGlvbiAoKSB7XG4gICAgcmV0dXJuIGZhbHNlO1xuICB9O1xufVxuXG52YXIgUmVzb2x2ZXJzID0ge1xuICByZXNvbHZlQm91bmQsXG4gIHJlc29sdmVXaWxkY2FyZCxcbiAgcmVzb2x2ZVZhcmlhYmxlLFxuICByZXNvbHZlSGVhZFRhaWwsXG4gIHJlc29sdmVDYXB0dXJlLFxuICByZXNvbHZlU3RhcnRzV2l0aCxcbiAgcmVzb2x2ZVR5cGUsXG4gIHJlc29sdmVBcnJheSxcbiAgcmVzb2x2ZU9iamVjdCxcbiAgcmVzb2x2ZU5vTWF0Y2gsXG4gIHJlc29sdmVTeW1ib2wsXG4gIHJlc29sdmVTdHJpbmcsXG4gIHJlc29sdmVOdW1iZXIsXG4gIHJlc29sdmVCb29sZWFuLFxuICByZXNvbHZlRnVuY3Rpb24sXG4gIHJlc29sdmVOdWxsXG59O1xuXG5mdW5jdGlvbiBidWlsZE1hdGNoKHBhdHRlcm4pIHtcblxuICBpZiAoQ2hlY2tzLmlzX3ZhcmlhYmxlKHBhdHRlcm4pKSB7XG4gICAgcmV0dXJuIFJlc29sdmVycy5yZXNvbHZlVmFyaWFibGUocGF0dGVybik7XG4gIH1cblxuICBpZiAoQ2hlY2tzLmlzX3dpbGRjYXJkKHBhdHRlcm4pKSB7XG4gICAgcmV0dXJuIFJlc29sdmVycy5yZXNvbHZlV2lsZGNhcmQocGF0dGVybik7XG4gIH1cblxuICBpZiAoQ2hlY2tzLmlzX3VuZGVmaW5lZChwYXR0ZXJuKSkge1xuICAgIHJldHVybiBSZXNvbHZlcnMucmVzb2x2ZVdpbGRjYXJkKHBhdHRlcm4pO1xuICB9XG5cbiAgaWYgKENoZWNrcy5pc19oZWFkVGFpbChwYXR0ZXJuKSkge1xuICAgIHJldHVybiBSZXNvbHZlcnMucmVzb2x2ZUhlYWRUYWlsKHBhdHRlcm4pO1xuICB9XG5cbiAgaWYgKENoZWNrcy5pc19zdGFydHNXaXRoKHBhdHRlcm4pKSB7XG4gICAgcmV0dXJuIFJlc29sdmVycy5yZXNvbHZlU3RhcnRzV2l0aChwYXR0ZXJuKTtcbiAgfVxuXG4gIGlmIChDaGVja3MuaXNfY2FwdHVyZShwYXR0ZXJuKSkge1xuICAgIHJldHVybiBSZXNvbHZlcnMucmVzb2x2ZUNhcHR1cmUocGF0dGVybik7XG4gIH1cblxuICBpZiAoQ2hlY2tzLmlzX2JvdW5kKHBhdHRlcm4pKSB7XG4gICAgcmV0dXJuIFJlc29sdmVycy5yZXNvbHZlQm91bmQocGF0dGVybik7XG4gIH1cblxuICBpZiAoQ2hlY2tzLmlzX3R5cGUocGF0dGVybikpIHtcbiAgICByZXR1cm4gUmVzb2x2ZXJzLnJlc29sdmVUeXBlKHBhdHRlcm4pO1xuICB9XG5cbiAgaWYgKENoZWNrcy5pc19hcnJheShwYXR0ZXJuKSkge1xuICAgIHJldHVybiBSZXNvbHZlcnMucmVzb2x2ZUFycmF5KHBhdHRlcm4pO1xuICB9XG5cbiAgaWYgKENoZWNrcy5pc19udW1iZXIocGF0dGVybikpIHtcbiAgICByZXR1cm4gUmVzb2x2ZXJzLnJlc29sdmVOdW1iZXIocGF0dGVybik7XG4gIH1cblxuICBpZiAoQ2hlY2tzLmlzX3N0cmluZyhwYXR0ZXJuKSkge1xuICAgIHJldHVybiBSZXNvbHZlcnMucmVzb2x2ZVN0cmluZyhwYXR0ZXJuKTtcbiAgfVxuXG4gIGlmIChDaGVja3MuaXNfYm9vbGVhbihwYXR0ZXJuKSkge1xuICAgIHJldHVybiBSZXNvbHZlcnMucmVzb2x2ZUJvb2xlYW4ocGF0dGVybik7XG4gIH1cblxuICBpZiAoQ2hlY2tzLmlzX3N5bWJvbChwYXR0ZXJuKSkge1xuICAgIHJldHVybiBSZXNvbHZlcnMucmVzb2x2ZVN5bWJvbChwYXR0ZXJuKTtcbiAgfVxuXG4gIGlmIChDaGVja3MuaXNfbnVsbChwYXR0ZXJuKSkge1xuICAgIHJldHVybiBSZXNvbHZlcnMucmVzb2x2ZU51bGwocGF0dGVybik7XG4gIH1cblxuICBpZiAoQ2hlY2tzLmlzX29iamVjdChwYXR0ZXJuKSkge1xuICAgIHJldHVybiBSZXNvbHZlcnMucmVzb2x2ZU9iamVjdChwYXR0ZXJuKTtcbiAgfVxuXG4gIHJldHVybiBSZXNvbHZlcnMucmVzb2x2ZU5vTWF0Y2goKTtcbn1cblxuY2xhc3MgTWF0Y2hFcnJvciBleHRlbmRzIEVycm9yIHtcbiAgY29uc3RydWN0b3IoYXJnKSB7XG4gICAgc3VwZXIoKTtcblxuICAgIGlmICh0eXBlb2YgYXJnID09PSAnc3ltYm9sJykge1xuICAgICAgdGhpcy5tZXNzYWdlID0gJ05vIG1hdGNoIGZvcjogJyArIGFyZy50b1N0cmluZygpO1xuICAgIH0gZWxzZSBpZiAoQXJyYXkuaXNBcnJheShhcmcpKSB7XG4gICAgICBsZXQgbWFwcGVkVmFsdWVzID0gYXJnLm1hcCh4ID0+IHgudG9TdHJpbmcoKSk7XG4gICAgICB0aGlzLm1lc3NhZ2UgPSAnTm8gbWF0Y2ggZm9yOiAnICsgbWFwcGVkVmFsdWVzO1xuICAgIH0gZWxzZSB7XG4gICAgICB0aGlzLm1lc3NhZ2UgPSAnTm8gbWF0Y2ggZm9yOiAnICsgYXJnO1xuICAgIH1cblxuICAgIHRoaXMuc3RhY2sgPSBuZXcgRXJyb3IoKS5zdGFjaztcbiAgICB0aGlzLm5hbWUgPSB0aGlzLmNvbnN0cnVjdG9yLm5hbWU7XG4gIH1cbn1cblxuY2xhc3MgQ2FzZSB7XG5cbiAgY29uc3RydWN0b3IocGF0dGVybiwgZm4sIGd1YXJkID0gKCkgPT4gdHJ1ZSkge1xuICAgIHRoaXMucGF0dGVybiA9IGJ1aWxkTWF0Y2gocGF0dGVybik7XG4gICAgdGhpcy5mbiA9IGZuO1xuICAgIHRoaXMuZ3VhcmQgPSBndWFyZDtcbiAgfVxufVxuXG5mdW5jdGlvbiBtYWtlX2Nhc2UocGF0dGVybiwgZm4sIGd1YXJkID0gKCkgPT4gdHJ1ZSkge1xuICByZXR1cm4gbmV3IENhc2UocGF0dGVybiwgZm4sIGd1YXJkKTtcbn1cblxuZnVuY3Rpb24gZGVmbWF0Y2goLi4uY2FzZXMpIHtcbiAgcmV0dXJuIGZ1bmN0aW9uICguLi5hcmdzKSB7XG4gICAgZm9yIChsZXQgcHJvY2Vzc2VkQ2FzZSBvZiBjYXNlcykge1xuICAgICAgbGV0IHJlc3VsdCA9IFtdO1xuICAgICAgaWYgKHByb2Nlc3NlZENhc2UucGF0dGVybihhcmdzLCByZXN1bHQpICYmIHByb2Nlc3NlZENhc2UuZ3VhcmQuYXBwbHkodGhpcywgcmVzdWx0KSkge1xuICAgICAgICByZXR1cm4gcHJvY2Vzc2VkQ2FzZS5mbi5hcHBseSh0aGlzLCByZXN1bHQpO1xuICAgICAgfVxuICAgIH1cblxuICAgIHRocm93IG5ldyBNYXRjaEVycm9yKGFyZ3MpO1xuICB9O1xufVxuXG5mdW5jdGlvbiBtYXRjaChwYXR0ZXJuLCBleHByLCBndWFyZCA9ICgpID0+IHRydWUpIHtcbiAgbGV0IHJlc3VsdCA9IFtdO1xuICBsZXQgcHJvY2Vzc2VkUGF0dGVybiA9IGJ1aWxkTWF0Y2gocGF0dGVybik7XG4gIGlmIChwcm9jZXNzZWRQYXR0ZXJuKGV4cHIsIHJlc3VsdCkgJiYgZ3VhcmQuYXBwbHkodGhpcywgcmVzdWx0KSkge1xuICAgIHJldHVybiByZXN1bHQ7XG4gIH0gZWxzZSB7XG4gICAgdGhyb3cgbmV3IE1hdGNoRXJyb3IoZXhwcik7XG4gIH1cbn1cblxuZnVuY3Rpb24gbWF0Y2hfbm9fdGhyb3cocGF0dGVybiwgZXhwciwgZ3VhcmQgPSAoKSA9PiB0cnVlKSB7XG4gIHRyeSB7XG4gICAgcmV0dXJuIG1hdGNoKHBhdHRlcm4sIGV4cHIsIGd1YXJkKTtcbiAgfSBjYXRjaCAoZSkge1xuICAgIGlmIChlIGluc3RhbmNlb2YgTWF0Y2hFcnJvcikge1xuICAgICAgcmV0dXJuIG51bGw7XG4gICAgfVxuXG4gICAgdGhyb3cgZTtcbiAgfVxufVxuXG52YXIgUGF0dGVybnMgPSB7XG4gIGRlZm1hdGNoLCBtYXRjaCwgTWF0Y2hFcnJvciwgbWF0Y2hfbm9fdGhyb3csXG4gIHZhcmlhYmxlLCB3aWxkY2FyZCwgc3RhcnRzV2l0aCxcbiAgY2FwdHVyZSwgaGVhZFRhaWwsIHR5cGUsIGJvdW5kLCBDYXNlLCBtYWtlX2Nhc2Vcbn07XG5cbmZ1bmN0aW9uIGNhbGxfcHJvcGVydHkoaXRlbSwgcHJvcGVydHkpIHtcbiAgaWYgKHByb3BlcnR5IGluIGl0ZW0pIHtcbiAgICBpdGVtW3Byb3BlcnR5XTtcbiAgICBpZiAoaXRlbVtwcm9wZXJ0eV0gaW5zdGFuY2VvZiBGdW5jdGlvbikge1xuICAgICAgcmV0dXJuIGl0ZW1bcHJvcGVydHldKCk7XG4gICAgfSBlbHNlIHtcbiAgICAgIHJldHVybiBpdGVtW3Byb3BlcnR5XTtcbiAgICB9XG4gIH0gZWxzZSBpZiAoU3ltYm9sLmZvcihwcm9wZXJ0eSkgaW4gaXRlbSkge1xuICAgIGxldCBwcm9wID0gU3ltYm9sLmZvcihwcm9wZXJ0eSk7XG4gICAgaWYgKGl0ZW1bcHJvcF0gaW5zdGFuY2VvZiBGdW5jdGlvbikge1xuICAgICAgcmV0dXJuIGl0ZW1bcHJvcF0oKTtcbiAgICB9IGVsc2Uge1xuICAgICAgcmV0dXJuIGl0ZW1bcHJvcF07XG4gICAgfVxuICB9XG5cbiAgdGhyb3cgbmV3IEVycm9yKGBQcm9wZXJ0eSAkeyBwcm9wZXJ0eSB9IG5vdCBmb3VuZCBpbiAkeyBpdGVtIH1gKTtcbn1cblxuZnVuY3Rpb24gaXNfaW5zdGFuY2Vfb2YodmFsdWUsIHR5cGUpIHtcbiAgcmV0dXJuIHZhbHVlIGluc3RhbmNlb2YgdHlwZTtcbn1cblxuZnVuY3Rpb24gc2l6ZSh0ZXJtKSB7XG4gIHJldHVybiB0ZXJtLmxlbmd0aDtcbn1cblxuZnVuY3Rpb24gaXNfbmlsJDEoeCkge1xuICByZXR1cm4geCA9PT0gbnVsbDtcbn1cblxuZnVuY3Rpb24gaXNfYXRvbSQxKHgpIHtcbiAgcmV0dXJuIHR5cGVvZiB4ID09PSAnc3ltYm9sJztcbn1cblxuZnVuY3Rpb24gaXNfYmluYXJ5JDEoeCkge1xuICByZXR1cm4gdHlwZW9mIHggPT09ICdzdHJpbmcnIHx8IHggaW5zdGFuY2VvZiBTdHJpbmc7XG59XG5cbmZ1bmN0aW9uIGlzX2Jvb2xlYW4kMSh4KSB7XG4gIHJldHVybiB0eXBlb2YgeCA9PT0gJ2Jvb2xlYW4nIHx8IHggaW5zdGFuY2VvZiBCb29sZWFuO1xufVxuXG5mdW5jdGlvbiBpc19mdW5jdGlvbiQxKHgsIGFyaXR5ID0gLTEpIHtcbiAgcmV0dXJuIHR5cGVvZiB4ID09PSAnZnVuY3Rpb24nIHx8IHggaW5zdGFuY2VvZiBGdW5jdGlvbjtcbn1cblxuZnVuY3Rpb24gaXNfZmxvYXQkMSh4KSB7XG4gIHJldHVybiBpc19udW1iZXIkMSh4KSAmJiAhTnVtYmVyLmlzSW50ZWdlcih4KTtcbn1cblxuZnVuY3Rpb24gaXNfaW50ZWdlciQxKHgpIHtcbiAgcmV0dXJuIE51bWJlci5pc0ludGVnZXIoeCk7XG59XG5cbmZ1bmN0aW9uIGlzX2xpc3QkMSh4KSB7XG4gIHJldHVybiB4IGluc3RhbmNlb2YgQXJyYXk7XG59XG5cbmZ1bmN0aW9uIGlzX21hcCQxKHgpIHtcbiAgcmV0dXJuIHR5cGVvZiB4ID09PSAnb2JqZWN0JyB8fCB4IGluc3RhbmNlb2YgT2JqZWN0O1xufVxuXG5mdW5jdGlvbiBpc19udW1iZXIkMSh4KSB7XG4gIHJldHVybiB0eXBlb2YgeCA9PT0gJ251bWJlcic7XG59XG5cbmZ1bmN0aW9uIGlzX3R1cGxlJDEoeCkge1xuICByZXR1cm4geCBpbnN0YW5jZW9mIFR1cGxlO1xufVxuXG5mdW5jdGlvbiBpc19waWQkMSh4KSB7XG4gIHJldHVybiB4IGluc3RhbmNlb2YgUElEO1xufVxuXG5mdW5jdGlvbiBpc19wb3J0JDEoeCkge1xuICByZXR1cm4gZmFsc2U7XG59XG5cbmZ1bmN0aW9uIGlzX3JlZmVyZW5jZSQxKHgpIHtcbiAgcmV0dXJuIGZhbHNlO1xufVxuXG5mdW5jdGlvbiBpc19iaXRzdHJpbmckMSh4KSB7XG4gIHJldHVybiBpc19iaW5hcnkkMSh4KSB8fCB4IGluc3RhbmNlb2YgQml0U3RyaW5nO1xufVxuXG5mdW5jdGlvbiBhZGQob25lLCB0d28pIHtcbiAgcmV0dXJuIG9uZSArIHR3bztcbn1cblxuZnVuY3Rpb24gc3VidHJhY3Qob25lLCB0d28pIHtcbiAgcmV0dXJuIG9uZSArIHR3bztcbn1cblxuZnVuY3Rpb24gbXVsdGlwbHkob25lLCB0d28pIHtcbiAgcmV0dXJuIG9uZSArIHR3bztcbn1cblxuZnVuY3Rpb24gZGl2aWRlKG9uZSwgdHdvKSB7XG4gIHJldHVybiBvbmUgKyB0d287XG59XG5cbmZ1bmN0aW9uIHJlbWFpbmRlcihvbmUsIHR3bykge1xuICByZXR1cm4gb25lICsgdHdvO1xufVxuXG5mdW5jdGlvbiBhcHBseSQxKC4uLmFyZ3MpIHtcbiAgaWYgKGFyZ3MubGVuZ3RoID09PSAyKSB7XG4gICAgYXJnc1swXS5hcHBseShudWxsLCBhcmdzLnNsaWNlKDEpKTtcbiAgfSBlbHNlIHtcbiAgICBhcmdzWzBdW2FyZ3NbMV1dLmFwcGx5KG51bGwsIGFyZ3Muc2xpY2UoMikpO1xuICB9XG59XG5cbmZ1bmN0aW9uIG5ld190dXBsZSguLi5hcmdzKSB7XG4gIHJldHVybiBuZXcgVHVwbGUoLi4uYXJncyk7XG59XG5cbmZ1bmN0aW9uIGR1cGxpY2F0ZShkYXRhLCBzaXplKSB7XG4gIGxldCBhcnJheSA9IFtdO1xuXG4gIGZvciAodmFyIGkgPSBzaXplIC0gMTsgaSA+PSAwOyBpLS0pIHtcbiAgICBhcnJheS5wdXNoKGRhdGEpO1xuICB9XG5cbiAgcmV0dXJuIGFycmF5O1xufVxuXG5mdW5jdGlvbiBjb250YWlucyhsZWZ0LCByaWdodCkge1xuICBmb3IgKGxldCB4IG9mIHJpZ2h0KSB7XG4gICAgaWYgKFBhdHRlcm5zLm1hdGNoX25vX3Rocm93KGxlZnQsIHgpICE9IG51bGwpIHtcbiAgICAgIHJldHVybiB0cnVlO1xuICAgIH1cbiAgfVxuXG4gIHJldHVybiBmYWxzZTtcbn1cblxuZnVuY3Rpb24gcmV2ZXJzZShsaXN0KSB7XG4gIHJldHVybiBsaXN0LmNvbmNhdChbXSkucmV2ZXJzZSgpO1xufVxuXG5mdW5jdGlvbiBnZXRfZ2xvYmFsKCkge1xuICBpZiAodHlwZW9mIHNlbGYgIT09ICd1bmRlZmluZWQnKSB7XG4gICAgcmV0dXJuIHNlbGY7XG4gIH0gZWxzZSBpZiAodHlwZW9mIHdpbmRvdyAhPT0gJ3VuZGVmaW5lZCcpIHtcbiAgICByZXR1cm4gd2luZG93O1xuICB9IGVsc2UgaWYgKHR5cGVvZiBnbG9iYWwgIT09ICd1bmRlZmluZWQnKSB7XG4gICAgcmV0dXJuIGdsb2JhbDtcbiAgfVxuXG4gIHRocm93IG5ldyBFcnJvcignTm8gZ2xvYmFsIHN0YXRlIGZvdW5kJyk7XG59XG5cbmZ1bmN0aW9uIGNvbmNhdF9saXN0cyhsZWZ0LCByaWdodCkge1xuICByZXR1cm4gbGVmdC5jb25jYXQocmlnaHQpO1xufVxuXG5mdW5jdGlvbiBwcmVwZW5kX3RvX2xpc3QobGlzdCwgaXRlbSkge1xuICByZXR1cm4gW2l0ZW1dLmNvbmNhdChsaXN0KTtcbn1cblxuZnVuY3Rpb24gZGVmc3RydWN0KGRlZmF1bHRzKSB7XG4gIHJldHVybiBjbGFzcyB7XG4gICAgY29uc3RydWN0b3IodXBkYXRlID0ge30pIHtcbiAgICAgIGxldCB0aGVfdmFsdWVzID0gT2JqZWN0LmFzc2lnbihkZWZhdWx0cywgdXBkYXRlKTtcbiAgICAgIE9iamVjdC5hc3NpZ24odGhpcywgdGhlX3ZhbHVlcyk7XG4gICAgfVxuXG4gICAgc3RhdGljIGNyZWF0ZSh1cGRhdGVzID0ge30pIHtcbiAgICAgIGxldCB4ID0gbmV3IHRoaXModXBkYXRlcyk7XG4gICAgICByZXR1cm4gT2JqZWN0LmZyZWV6ZSh4KTtcbiAgICB9XG4gIH07XG59XG5cbmZ1bmN0aW9uIGRlZmV4Y2VwdGlvbihkZWZhdWx0cykge1xuICByZXR1cm4gY2xhc3MgZXh0ZW5kcyBFcnJvciB7XG4gICAgY29uc3RydWN0b3IodXBkYXRlID0ge30pIHtcbiAgICAgIGxldCBtZXNzYWdlID0gdXBkYXRlLm1lc3NhZ2UgfHwgJyc7XG4gICAgICBzdXBlcihtZXNzYWdlKTtcblxuICAgICAgbGV0IHRoZV92YWx1ZXMgPSBPYmplY3QuYXNzaWduKGRlZmF1bHRzLCB1cGRhdGUpO1xuICAgICAgT2JqZWN0LmFzc2lnbih0aGlzLCB0aGVfdmFsdWVzKTtcblxuICAgICAgdGhpcy5uYW1lID0gdGhpcy5jb25zdHJ1Y3Rvci5uYW1lO1xuICAgICAgdGhpcy5tZXNzYWdlID0gbWVzc2FnZTtcbiAgICAgIHRoaXNbU3BlY2lhbEZvcm1zLmF0b20oJ19fZXhjZXB0aW9uX18nKV0gPSB0cnVlO1xuICAgICAgRXJyb3IuY2FwdHVyZVN0YWNrVHJhY2UodGhpcywgdGhpcy5jb25zdHJ1Y3Rvci5uYW1lKTtcbiAgICB9XG5cbiAgICBzdGF0aWMgY3JlYXRlKHVwZGF0ZXMgPSB7fSkge1xuICAgICAgbGV0IHggPSBuZXcgdGhpcyh1cGRhdGVzKTtcbiAgICAgIHJldHVybiBPYmplY3QuZnJlZXplKHgpO1xuICAgIH1cbiAgfTtcbn1cblxuZnVuY3Rpb24gZGVmcHJvdG9jb2woc3BlYykge1xuICByZXR1cm4gbmV3IFByb3RvY29sKHNwZWMpO1xufVxuXG5mdW5jdGlvbiBkZWZpbXBsKHByb3RvY29sLCB0eXBlLCBpbXBsKSB7XG4gIHByb3RvY29sLmltcGxlbWVudGF0aW9uKHR5cGUsIGltcGwpO1xufVxuXG5mdW5jdGlvbiBnZXRfb2JqZWN0X2tleXMob2JqKSB7XG4gIHJldHVybiBPYmplY3Qua2V5cyhvYmopLmNvbmNhdChPYmplY3QuZ2V0T3duUHJvcGVydHlTeW1ib2xzKG9iaikpO1xufVxuXG5mdW5jdGlvbiBpc192YWxpZF9jaGFyYWN0ZXIoY29kZXBvaW50KSB7XG4gIHRyeSB7XG4gICAgcmV0dXJuIFN0cmluZy5mcm9tQ29kZVBvaW50KGNvZGVwb2ludCkgIT0gbnVsbDtcbiAgfSBjYXRjaCAoZSkge1xuICAgIHJldHVybiBmYWxzZTtcbiAgfVxufVxuXG4vL2h0dHBzOi8vZGV2ZWxvcGVyLm1vemlsbGEub3JnL2VuLVVTL2RvY3MvV2ViL0FQSS9XaW5kb3dCYXNlNjQvQmFzZTY0X2VuY29kaW5nX2FuZF9kZWNvZGluZyNTb2x1dGlvbl8yXyVFMiU4MCU5M19yZXdyaXRlX3RoZV9ET01zX2F0b2IoKV9hbmRfYnRvYSgpX3VzaW5nX0phdmFTY3JpcHQnc19UeXBlZEFycmF5c19hbmRfVVRGLThcbmZ1bmN0aW9uIGI2NEVuY29kZVVuaWNvZGUoc3RyKSB7XG4gIHJldHVybiBidG9hKGVuY29kZVVSSUNvbXBvbmVudChzdHIpLnJlcGxhY2UoLyUoWzAtOUEtRl17Mn0pL2csIGZ1bmN0aW9uIChtYXRjaCwgcDEpIHtcbiAgICByZXR1cm4gU3RyaW5nLmZyb21DaGFyQ29kZSgnMHgnICsgcDEpO1xuICB9KSk7XG59XG5cbmZ1bmN0aW9uIGRlbGV0ZV9wcm9wZXJ0eV9mcm9tX21hcChtYXAsIHByb3BlcnR5KSB7XG4gIGxldCBuZXdfbWFwID0gT2JqZWN0LmFzc2lnbihPYmplY3QuY3JlYXRlKG1hcC5jb25zdHJ1Y3Rvci5wcm90b3R5cGUpLCBtYXApO1xuICBkZWxldGUgbmV3X21hcFtwcm9wZXJ0eV07XG5cbiAgcmV0dXJuIE9iamVjdC5mcmVlemUobmV3X21hcCk7XG59XG5cbmZ1bmN0aW9uIGNsYXNzX3RvX29iaihtYXApIHtcbiAgbGV0IG5ld19tYXAgPSBPYmplY3QuYXNzaWduKHt9LCBtYXApO1xuICByZXR1cm4gT2JqZWN0LmZyZWV6ZShuZXdfbWFwKTtcbn1cblxuZnVuY3Rpb24gYWRkX3Byb3BlcnR5X3RvX21hcChtYXAsIHByb3BlcnR5LCB2YWx1ZSkge1xuICBsZXQgbmV3X21hcCA9IE9iamVjdC5hc3NpZ24oe30sIG1hcCk7XG4gIG5ld19tYXBbcHJvcGVydHldID0gdmFsdWU7XG4gIHJldHVybiBPYmplY3QuZnJlZXplKG5ld19tYXApO1xufVxuXG5mdW5jdGlvbiBibm90KGV4cHIpIHtcbiAgcmV0dXJuIH5leHByO1xufVxuXG5mdW5jdGlvbiBiYW5kKGxlZnQsIHJpZ2h0KSB7XG4gIHJldHVybiBsZWZ0ICYgcmlnaHQ7XG59XG5cbmZ1bmN0aW9uIGJvcihsZWZ0LCByaWdodCkge1xuICByZXR1cm4gbGVmdCB8IHJpZ2h0O1xufVxuXG5mdW5jdGlvbiBic2wobGVmdCwgcmlnaHQpIHtcbiAgcmV0dXJuIGxlZnQgPDwgcmlnaHQ7XG59XG5cbmZ1bmN0aW9uIGJzcihsZWZ0LCByaWdodCkge1xuICByZXR1cm4gbGVmdCA+PiByaWdodDtcbn1cblxuZnVuY3Rpb24gYnhvcihsZWZ0LCByaWdodCkge1xuICByZXR1cm4gbGVmdCBeIHJpZ2h0O1xufVxuXG5mdW5jdGlvbiB6aXAobGlzdF9vZl9saXN0cykge1xuICBpZiAobGlzdF9vZl9saXN0cy5sZW5ndGggPT09IDApIHtcbiAgICByZXR1cm4gT2JqZWN0LmZyZWV6ZShbXSk7XG4gIH1cblxuICBsZXQgbmV3X3ZhbHVlID0gW107XG4gIGxldCBzbWFsbGVzdF9sZW5ndGggPSBsaXN0X29mX2xpc3RzWzBdO1xuXG4gIGZvciAobGV0IHggb2YgbGlzdF9vZl9saXN0cykge1xuICAgIGlmICh4Lmxlbmd0aCA8IHNtYWxsZXN0X2xlbmd0aCkge1xuICAgICAgc21hbGxlc3RfbGVuZ3RoID0geC5sZW5ndGg7XG4gICAgfVxuICB9XG5cbiAgZm9yIChsZXQgaSA9IDA7IGkgPCBzbWFsbGVzdF9sZW5ndGg7IGkrKykge1xuICAgIGxldCBjdXJyZW50X3ZhbHVlID0gW107XG4gICAgZm9yIChsZXQgaiA9IDA7IGogPCBsaXN0X29mX2xpc3RzLmxlbmd0aDsgaisrKSB7XG4gICAgICBjdXJyZW50X3ZhbHVlLnB1c2gobGlzdF9vZl9saXN0c1tqXVtpXSk7XG4gICAgfVxuXG4gICAgbmV3X3ZhbHVlLnB1c2gobmV3IFR1cGxlKC4uLmN1cnJlbnRfdmFsdWUpKTtcbiAgfVxuXG4gIHJldHVybiBPYmplY3QuZnJlZXplKG5ld192YWx1ZSk7XG59XG5cbnZhciBGdW5jdGlvbnMgPSB7XG4gIGNhbGxfcHJvcGVydHksXG4gIGlzX2luc3RhbmNlX29mLFxuICBzaXplLFxuICBpc19uaWw6IGlzX25pbCQxLFxuICBpc19hdG9tOiBpc19hdG9tJDEsXG4gIGlzX2JpbmFyeTogaXNfYmluYXJ5JDEsXG4gIGlzX2Jvb2xlYW46IGlzX2Jvb2xlYW4kMSxcbiAgaXNfZnVuY3Rpb246IGlzX2Z1bmN0aW9uJDEsXG4gIGlzX2Zsb2F0OiBpc19mbG9hdCQxLFxuICBpc19pbnRlZ2VyOiBpc19pbnRlZ2VyJDEsXG4gIGlzX2xpc3Q6IGlzX2xpc3QkMSxcbiAgaXNfbWFwOiBpc19tYXAkMSxcbiAgaXNfbnVtYmVyOiBpc19udW1iZXIkMSxcbiAgaXNfdHVwbGU6IGlzX3R1cGxlJDEsXG4gIGlzX3BpZDogaXNfcGlkJDEsXG4gIGlzX3BvcnQ6IGlzX3BvcnQkMSxcbiAgaXNfcmVmZXJlbmNlOiBpc19yZWZlcmVuY2UkMSxcbiAgaXNfYml0c3RyaW5nOiBpc19iaXRzdHJpbmckMSxcbiAgYWRkLFxuICBzdWJ0cmFjdCxcbiAgbXVsdGlwbHksXG4gIGRpdmlkZSxcbiAgcmVtYWluZGVyLFxuICBhcHBseTogYXBwbHkkMSxcbiAgbmV3X3R1cGxlLFxuICBkdXBsaWNhdGUsXG4gIGNvbnRhaW5zLFxuICByZXZlcnNlLFxuICBnZXRfZ2xvYmFsLFxuICBjb25jYXRfbGlzdHMsXG4gIHByZXBlbmRfdG9fbGlzdCxcbiAgZGVmc3RydWN0LFxuICBkZWZleGNlcHRpb24sXG4gIGRlZnByb3RvY29sLFxuICBkZWZpbXBsLFxuICBnZXRfb2JqZWN0X2tleXMsXG4gIGlzX3ZhbGlkX2NoYXJhY3RlcixcbiAgYjY0RW5jb2RlVW5pY29kZSxcbiAgZGVsZXRlX3Byb3BlcnR5X2Zyb21fbWFwLFxuICBhZGRfcHJvcGVydHlfdG9fbWFwLFxuICBjbGFzc190b19vYmosXG4gIGJub3QsXG4gIGJhbmQsXG4gIGJvcixcbiAgYnNsLFxuICBic3IsXG4gIGJ4b3IsXG4gIHppcFxufTtcblxuZnVuY3Rpb24gbGlzdCguLi5hcmdzKSB7XG4gIHJldHVybiBPYmplY3QuZnJlZXplKGFyZ3MpO1xufVxuXG5mdW5jdGlvbiBiaXRzdHJpbmcoLi4uYXJncykge1xuICByZXR1cm4gbmV3IEJpdFN0cmluZyguLi5hcmdzKTtcbn1cblxuZnVuY3Rpb24gdHVwbGUoLi4uYXJncykge1xuICByZXR1cm4gbmV3IFR1cGxlKC4uLmFyZ3MpO1xufVxuXG5mdW5jdGlvbiBfY2FzZShjb25kaXRpb24sIGNsYXVzZXMpIHtcbiAgcmV0dXJuIFBhdHRlcm5zLmRlZm1hdGNoKC4uLmNsYXVzZXMpKGNvbmRpdGlvbik7XG59XG5cbmZ1bmN0aW9uIGNvbmQoY2xhdXNlcykge1xuICBmb3IgKGxldCBjbGF1c2Ugb2YgY2xhdXNlcykge1xuICAgIGlmIChjbGF1c2VbMF0pIHtcbiAgICAgIHJldHVybiBjbGF1c2VbMV0oKTtcbiAgICB9XG4gIH1cblxuICB0aHJvdyBuZXcgRXJyb3IoKTtcbn1cblxuZnVuY3Rpb24gbWFwKG9iaikge1xuICByZXR1cm4gT2JqZWN0LmZyZWV6ZShvYmopO1xufVxuXG5mdW5jdGlvbiBtYXBfdXBkYXRlKG1hcCwgdmFsdWVzKSB7XG4gIHJldHVybiBPYmplY3QuZnJlZXplKE9iamVjdC5hc3NpZ24oT2JqZWN0LmNyZWF0ZShtYXAuY29uc3RydWN0b3IucHJvdG90eXBlKSwgbWFwLCB2YWx1ZXMpKTtcbn1cblxuZnVuY3Rpb24gX2Zvcihjb2xsZWN0aW9ucywgZnVuLCBmaWx0ZXIgPSAoKSA9PiB0cnVlLCBpbnRvID0gW10sIHByZXZpb3VzVmFsdWVzID0gW10pIHtcbiAgbGV0IHBhdHRlcm4gPSBjb2xsZWN0aW9uc1swXVswXTtcbiAgbGV0IGNvbGxlY3Rpb24gPSBjb2xsZWN0aW9uc1swXVsxXTtcblxuICBpZiAoY29sbGVjdGlvbnMubGVuZ3RoID09PSAxKSB7XG5cbiAgICBmb3IgKGxldCBlbGVtIG9mIGNvbGxlY3Rpb24pIHtcbiAgICAgIGxldCByID0gUGF0dGVybnMubWF0Y2hfbm9fdGhyb3cocGF0dGVybiwgZWxlbSk7XG4gICAgICBsZXQgYXJncyA9IHByZXZpb3VzVmFsdWVzLmNvbmNhdChyKTtcblxuICAgICAgaWYgKHIgJiYgZmlsdGVyLmFwcGx5KHRoaXMsIGFyZ3MpKSB7XG4gICAgICAgIGludG8gPSBpbnRvLmNvbmNhdChbZnVuLmFwcGx5KHRoaXMsIGFyZ3MpXSk7XG4gICAgICB9XG4gICAgfVxuXG4gICAgcmV0dXJuIGludG87XG4gIH0gZWxzZSB7XG4gICAgbGV0IF9pbnRvID0gW107XG5cbiAgICBmb3IgKGxldCBlbGVtIG9mIGNvbGxlY3Rpb24pIHtcbiAgICAgIGxldCByID0gUGF0dGVybnMubWF0Y2hfbm9fdGhyb3cocGF0dGVybiwgZWxlbSk7XG4gICAgICBpZiAocikge1xuICAgICAgICBfaW50byA9IGludG8uY29uY2F0KHRoaXMuX2Zvcihjb2xsZWN0aW9ucy5zbGljZSgxKSwgZnVuLCBmaWx0ZXIsIF9pbnRvLCBwcmV2aW91c1ZhbHVlcy5jb25jYXQocikpKTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICByZXR1cm4gX2ludG87XG4gIH1cbn1cblxuZnVuY3Rpb24gX3RyeShkb19mdW4sIHJlc2N1ZV9mdW5jdGlvbiwgY2F0Y2hfZnVuLCBlbHNlX2Z1bmN0aW9uLCBhZnRlcl9mdW5jdGlvbikge1xuICBsZXQgcmVzdWx0ID0gbnVsbDtcblxuICB0cnkge1xuICAgIHJlc3VsdCA9IGRvX2Z1bigpO1xuICB9IGNhdGNoIChlKSB7XG4gICAgbGV0IGV4X3Jlc3VsdCA9IG51bGw7XG5cbiAgICBpZiAocmVzY3VlX2Z1bmN0aW9uKSB7XG4gICAgICB0cnkge1xuICAgICAgICBleF9yZXN1bHQgPSByZXNjdWVfZnVuY3Rpb24oZSk7XG4gICAgICAgIHJldHVybiBleF9yZXN1bHQ7XG4gICAgICB9IGNhdGNoIChleCkge1xuICAgICAgICBpZiAoZXggaW5zdGFuY2VvZiBQYXR0ZXJucy5NYXRjaEVycm9yKSB7XG4gICAgICAgICAgdGhyb3cgZXg7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9XG5cbiAgICBpZiAoY2F0Y2hfZnVuKSB7XG4gICAgICB0cnkge1xuICAgICAgICBleF9yZXN1bHQgPSBjYXRjaF9mdW4oZSk7XG4gICAgICAgIHJldHVybiBleF9yZXN1bHQ7XG4gICAgICB9IGNhdGNoIChleCkge1xuICAgICAgICBpZiAoZXggaW5zdGFuY2VvZiBQYXR0ZXJucy5NYXRjaEVycm9yKSB7XG4gICAgICAgICAgdGhyb3cgZXg7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9XG5cbiAgICB0aHJvdyBlO1xuICB9IGZpbmFsbHkge1xuICAgIGlmIChhZnRlcl9mdW5jdGlvbikge1xuICAgICAgYWZ0ZXJfZnVuY3Rpb24oKTtcbiAgICB9XG4gIH1cblxuICBpZiAoZWxzZV9mdW5jdGlvbikge1xuICAgIHRyeSB7XG4gICAgICByZXR1cm4gZWxzZV9mdW5jdGlvbihyZXN1bHQpO1xuICAgIH0gY2F0Y2ggKGV4KSB7XG4gICAgICBpZiAoZXggaW5zdGFuY2VvZiBQYXR0ZXJucy5NYXRjaEVycm9yKSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcignTm8gTWF0Y2ggRm91bmQgaW4gRWxzZScpO1xuICAgICAgfVxuXG4gICAgICB0aHJvdyBleDtcbiAgICB9XG4gIH0gZWxzZSB7XG4gICAgcmV0dXJuIHJlc3VsdDtcbiAgfVxufVxuXG52YXIgU3BlY2lhbEZvcm1zJDEgPSB7XG4gIGxpc3QsXG4gIGJpdHN0cmluZyxcbiAgdHVwbGUsXG4gIF9jYXNlLFxuICBjb25kLFxuICBtYXAsXG4gIG1hcF91cGRhdGUsXG4gIF9mb3IsXG4gIF90cnlcbn07XG5cbkZ1bmN0aW9ucy5nZXRfZ2xvYmFsKCkucHJvY2Vzc2VzID0gRnVuY3Rpb25zLmdldF9nbG9iYWwoKS5wcm9jZXNzZXMgfHwgbmV3IFByb2Nlc3NTeXN0ZW0oKTtcblxuXG5cbnZhciBDID0gT2JqZWN0LmZyZWV6ZSh7XG5cdFByb2Nlc3NTeXN0ZW06IFByb2Nlc3NTeXN0ZW0sXG5cdFR1cGxlOiBUdXBsZSxcblx0UElEOiBQSUQsXG5cdEJpdFN0cmluZzogQml0U3RyaW5nLFxuXHRQYXR0ZXJuczogUGF0dGVybnMsXG5cdEludGVnZXI6IEludGVnZXIsXG5cdEZsb2F0OiBGbG9hdCxcblx0RnVuY3Rpb25zOiBGdW5jdGlvbnMsXG5cdExpc3Q6IExpc3QsXG5cdFNwZWNpYWxGb3JtczogU3BlY2lhbEZvcm1zJDFcbn0pO1xuXG5mdW5jdGlvbiB0bChsaXN0KSB7XG4gIHJldHVybiBTcGVjaWFsRm9ybXMkMS5saXN0KC4uLmxpc3Quc2xpY2UoMSkpO1xufVxuXG5mdW5jdGlvbiBoZChsaXN0KSB7XG4gIHJldHVybiBsaXN0WzBdO1xufVxuXG5mdW5jdGlvbiBpc19uaWwoeCkge1xuICByZXR1cm4geCA9PT0gbnVsbDtcbn1cblxuZnVuY3Rpb24gaXNfYXRvbSh4KSB7XG4gIHJldHVybiB0eXBlb2YgeCA9PT0gJ3N5bWJvbCc7XG59XG5cbmZ1bmN0aW9uIGlzX2JpbmFyeSh4KSB7XG4gIHJldHVybiB0eXBlb2YgeCA9PT0gJ3N0cmluZycgfHwgeCBpbnN0YW5jZW9mIFN0cmluZztcbn1cblxuZnVuY3Rpb24gaXNfYm9vbGVhbih4KSB7XG4gIHJldHVybiB0eXBlb2YgeCA9PT0gJ2Jvb2xlYW4nIHx8IHggaW5zdGFuY2VvZiBCb29sZWFuO1xufVxuXG5mdW5jdGlvbiBpc19mdW5jdGlvbih4LCBhcml0eSA9IC0xKSB7XG4gIHJldHVybiB0eXBlb2YgeCA9PT0gJ2Z1bmN0aW9uJyB8fCB4IGluc3RhbmNlb2YgRnVuY3Rpb247XG59XG5cbmZ1bmN0aW9uIGlzX2Zsb2F0KHgpIHtcbiAgcmV0dXJuIGlzX251bWJlcih4KSAmJiAhTnVtYmVyLmlzSW50ZWdlcih4KTtcbn1cblxuZnVuY3Rpb24gaXNfaW50ZWdlcih4KSB7XG4gIHJldHVybiBOdW1iZXIuaXNJbnRlZ2VyKHgpO1xufVxuXG5mdW5jdGlvbiBpc19saXN0KHgpIHtcbiAgcmV0dXJuIHggaW5zdGFuY2VvZiBBcnJheTtcbn1cblxuZnVuY3Rpb24gaXNfbWFwKHgpIHtcbiAgcmV0dXJuIHR5cGVvZiB4ID09PSAnb2JqZWN0JyB8fCB4IGluc3RhbmNlb2YgT2JqZWN0O1xufVxuXG5mdW5jdGlvbiBpc19udW1iZXIoeCkge1xuICByZXR1cm4gdHlwZW9mIHggPT09ICdudW1iZXInO1xufVxuXG5mdW5jdGlvbiBpc190dXBsZSh4KSB7XG4gIHJldHVybiB4IGluc3RhbmNlb2YgVHVwbGU7XG59XG5cbmZ1bmN0aW9uIGxlbmd0aCh4KSB7XG4gIHJldHVybiB4Lmxlbmd0aDtcbn1cblxuZnVuY3Rpb24gaXNfcGlkKHgpIHtcbiAgcmV0dXJuIHggaW5zdGFuY2VvZiBQSUQ7XG59XG5cbmZ1bmN0aW9uIGlzX3BvcnQoeCkge1xuICByZXR1cm4gZmFsc2U7XG59XG5cbmZ1bmN0aW9uIGlzX3JlZmVyZW5jZSh4KSB7XG4gIHJldHVybiBmYWxzZTtcbn1cblxuZnVuY3Rpb24gaXNfYml0c3RyaW5nKHgpIHtcbiAgcmV0dXJuIGlzX2JpbmFyeSh4KSB8fCB4IGluc3RhbmNlb2YgQml0U3RyaW5nO1xufVxuXG5mdW5jdGlvbiBfX2luX18obGVmdCwgcmlnaHQpIHtcbiAgZm9yIChsZXQgeCBvZiByaWdodCkge1xuICAgIGlmIChtYXRjaF9fcW1hcmtfXyhsZWZ0LCB4KSkge1xuICAgICAgcmV0dXJuIHRydWU7XG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIGZhbHNlO1xufVxuXG5mdW5jdGlvbiBhYnMobnVtYmVyKSB7XG4gIHJldHVybiBNYXRoLmFicyhudW1iZXIpO1xufVxuXG5mdW5jdGlvbiByb3VuZChudW1iZXIpIHtcbiAgcmV0dXJuIE1hdGgucm91bmQobnVtYmVyKTtcbn1cblxuZnVuY3Rpb24gZWxlbSh0dXBsZSwgaW5kZXgpIHtcbiAgaWYgKGlzX2xpc3QodHVwbGUpKSB7XG4gICAgcmV0dXJuIHR1cGxlW2luZGV4XTtcbiAgfVxuXG4gIHJldHVybiB0dXBsZS5nZXQoaW5kZXgpO1xufVxuXG5mdW5jdGlvbiByZW0obGVmdCwgcmlnaHQpIHtcbiAgcmV0dXJuIGxlZnQgJSByaWdodDtcbn1cblxuZnVuY3Rpb24gZGl2KGxlZnQsIHJpZ2h0KSB7XG4gIHJldHVybiBsZWZ0IC8gcmlnaHQ7XG59XG5cbmZ1bmN0aW9uIGFuZChsZWZ0LCByaWdodCkge1xuICByZXR1cm4gbGVmdCAmJiByaWdodDtcbn1cblxuZnVuY3Rpb24gb3IobGVmdCwgcmlnaHQpIHtcbiAgcmV0dXJuIGxlZnQgfHwgcmlnaHQ7XG59XG5cbmZ1bmN0aW9uIG5vdChhcmcpIHtcbiAgcmV0dXJuICFhcmc7XG59XG5cbmZ1bmN0aW9uIGFwcGx5KC4uLmFyZ3MpIHtcbiAgaWYgKGFyZ3MubGVuZ3RoID09PSAzKSB7XG4gICAgbGV0IG1vZCA9IGFyZ3NbMF07XG4gICAgbGV0IGZ1bmMgPSBhcmdzWzFdO1xuICAgIGxldCBmdW5jX2FyZ3MgPSBhcmdzWzJdO1xuICAgIHJldHVybiBtb2RbZnVuY10uYXBwbHkobnVsbCwgZnVuY19hcmdzKTtcbiAgfSBlbHNlIHtcbiAgICBsZXQgZnVuYyA9IGFyZ3NbMF07XG4gICAgbGV0IGZ1bmNfYXJncyA9IGFyZ3NbMV07XG5cbiAgICByZXR1cm4gZnVuYy5hcHBseShudWxsLCBmdW5jX2FyZ3MpO1xuICB9XG59XG5cbmZ1bmN0aW9uIHRvX3N0cmluZyhhcmcpIHtcbiAgaWYgKGlzX3R1cGxlKGFyZykpIHtcbiAgICByZXR1cm4gYXJnLnRvU3RyaW5nKCk7XG4gIH1cblxuICByZXR1cm4gYXJnLnRvU3RyaW5nKCk7XG59XG5cbmZ1bmN0aW9uIG1hdGNoX19xbWFya19fKHBhdHRlcm4sIGV4cHIsIGd1YXJkID0gKCkgPT4gdHJ1ZSkge1xuICByZXR1cm4gUGF0dGVybnMubWF0Y2hfbm9fdGhyb3cocGF0dGVybiwgZXhwciwgZ3VhcmQpICE9IG51bGw7XG59XG5cbnZhciBrZXJuZWwgPSB7XG4gIHRsLFxuICBoZCxcbiAgaXNfbmlsLFxuICBpc19hdG9tLFxuICBpc19iaW5hcnksXG4gIGlzX2Jvb2xlYW4sXG4gIGlzX2Z1bmN0aW9uLFxuICBpc19mbG9hdCxcbiAgaXNfaW50ZWdlcixcbiAgaXNfbGlzdCxcbiAgaXNfbWFwLFxuICBpc19udW1iZXIsXG4gIGlzX3R1cGxlLFxuICBsZW5ndGgsXG4gIGlzX3BpZCxcbiAgaXNfcG9ydCxcbiAgaXNfcmVmZXJlbmNlLFxuICBpc19iaXRzdHJpbmcsXG4gIGluOiBfX2luX18sXG4gIGFicyxcbiAgcm91bmQsXG4gIGVsZW0sXG4gIHJlbSxcbiAgZGl2LFxuICBhbmQsXG4gIG9yLFxuICBub3QsXG4gIGFwcGx5LFxuICB0b19zdHJpbmcsXG4gIG1hdGNoX19xbWFya19fXG59O1xuXG5sZXQgRW51bSA9IHtcblxuICBhbGxfX3FtYXJrX186IGZ1bmN0aW9uIChjb2xsZWN0aW9uLCBmdW4gPSB4ID0+IHgpIHtcbiAgICBmb3IgKGxldCBlbGVtIG9mIGNvbGxlY3Rpb24pIHtcbiAgICAgIGlmICghZnVuKGVsZW0pKSB7XG4gICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICByZXR1cm4gdHJ1ZTtcbiAgfSxcblxuICBhbnlfX3FtYXJrX186IGZ1bmN0aW9uIChjb2xsZWN0aW9uLCBmdW4gPSB4ID0+IHgpIHtcbiAgICBmb3IgKGxldCBlbGVtIG9mIGNvbGxlY3Rpb24pIHtcbiAgICAgIGlmIChmdW4oZWxlbSkpIHtcbiAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICB9XG4gICAgfVxuXG4gICAgcmV0dXJuIGZhbHNlO1xuICB9LFxuXG4gIGF0OiBmdW5jdGlvbiAoY29sbGVjdGlvbiwgbiwgdGhlX2RlZmF1bHQgPSBudWxsKSB7XG4gICAgaWYgKG4gPiB0aGlzLmNvdW50KGNvbGxlY3Rpb24pIHx8IG4gPCAwKSB7XG4gICAgICByZXR1cm4gdGhlX2RlZmF1bHQ7XG4gICAgfVxuXG4gICAgcmV0dXJuIGNvbGxlY3Rpb25bbl07XG4gIH0sXG5cbiAgY29uY2F0OiBmdW5jdGlvbiAoLi4uZW51bWFibGVzKSB7XG4gICAgcmV0dXJuIGVudW1hYmxlc1swXS5jb25jYXQoZW51bWFibGVzWzFdKTtcbiAgfSxcblxuICBjb3VudDogZnVuY3Rpb24gKGNvbGxlY3Rpb24sIGZ1biA9IG51bGwpIHtcbiAgICBpZiAoZnVuID09IG51bGwpIHtcbiAgICAgIHJldHVybiBjb2xsZWN0aW9uLmxlbmd0aDtcbiAgICB9IGVsc2Uge1xuICAgICAgcmV0dXJuIGNvbGxlY3Rpb24uZmlsdGVyKGZ1bikubGVuZ3RoO1xuICAgIH1cbiAgfSxcblxuICBkcm9wOiBmdW5jdGlvbiAoY29sbGVjdGlvbiwgY291bnQpIHtcbiAgICByZXR1cm4gY29sbGVjdGlvbi5zbGljZShjb3VudCk7XG4gIH0sXG5cbiAgZHJvcF93aGlsZTogZnVuY3Rpb24gKGNvbGxlY3Rpb24sIGZ1bikge1xuICAgIGxldCBjb3VudCA9IDA7XG5cbiAgICBmb3IgKGxldCBlbGVtIG9mIGNvbGxlY3Rpb24pIHtcbiAgICAgIGlmIChmdW4oZWxlbSkpIHtcbiAgICAgICAgY291bnQgPSBjb3VudCArIDE7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBicmVhaztcbiAgICAgIH1cbiAgICB9XG5cbiAgICByZXR1cm4gY29sbGVjdGlvbi5zbGljZShjb3VudCk7XG4gIH0sXG5cbiAgZWFjaDogZnVuY3Rpb24gKGNvbGxlY3Rpb24sIGZ1bikge1xuICAgIGZvciAobGV0IGVsZW0gb2YgY29sbGVjdGlvbikge1xuICAgICAgZnVuKGVsZW0pO1xuICAgIH1cbiAgfSxcblxuICBlbXB0eV9fcW1hcmtfXzogZnVuY3Rpb24gKGNvbGxlY3Rpb24pIHtcbiAgICByZXR1cm4gY29sbGVjdGlvbi5sZW5ndGggPT09IDA7XG4gIH0sXG5cbiAgZmV0Y2g6IGZ1bmN0aW9uIChjb2xsZWN0aW9uLCBuKSB7XG4gICAgaWYgKEFycmF5LmlzQXJyYXkoY29sbGVjdGlvbikpIHtcbiAgICAgIGlmIChuIDwgdGhpcy5jb3VudChjb2xsZWN0aW9uKSAmJiBuID49IDApIHtcbiAgICAgICAgcmV0dXJuIG5ldyBUdXBsZShTeW1ib2wuZm9yKFwib2tcIiksIGNvbGxlY3Rpb25bbl0pO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgcmV0dXJuIFN5bWJvbC5mb3IoXCJlcnJvclwiKTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICB0aHJvdyBuZXcgRXJyb3IoXCJjb2xsZWN0aW9uIGlzIG5vdCBhbiBFbnVtZXJhYmxlXCIpO1xuICB9LFxuXG4gIGZldGNoX19lbWFya19fOiBmdW5jdGlvbiAoY29sbGVjdGlvbiwgbikge1xuICAgIGlmIChBcnJheS5pc0FycmF5KGNvbGxlY3Rpb24pKSB7XG4gICAgICBpZiAobiA8IHRoaXMuY291bnQoY29sbGVjdGlvbikgJiYgbiA+PSAwKSB7XG4gICAgICAgIHJldHVybiBjb2xsZWN0aW9uW25dO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKFwib3V0IG9mIGJvdW5kcyBlcnJvclwiKTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICB0aHJvdyBuZXcgRXJyb3IoXCJjb2xsZWN0aW9uIGlzIG5vdCBhbiBFbnVtZXJhYmxlXCIpO1xuICB9LFxuXG4gIGZpbHRlcjogZnVuY3Rpb24gKGNvbGxlY3Rpb24sIGZ1bikge1xuICAgIGxldCByZXN1bHQgPSBbXTtcblxuICAgIGZvciAobGV0IGVsZW0gb2YgY29sbGVjdGlvbikge1xuICAgICAgaWYgKGZ1bihlbGVtKSkge1xuICAgICAgICByZXN1bHQucHVzaChlbGVtKTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICByZXR1cm4gcmVzdWx0O1xuICB9LFxuXG4gIGZpbHRlcl9tYXA6IGZ1bmN0aW9uIChjb2xsZWN0aW9uLCBmaWx0ZXIsIG1hcHBlcikge1xuICAgIHJldHVybiBFbnVtLm1hcChFbnVtLmZpbHRlcihjb2xsZWN0aW9uLCBmaWx0ZXIpLCBtYXBwZXIpO1xuICB9LFxuXG4gIGZpbmQ6IGZ1bmN0aW9uIChjb2xsZWN0aW9uLCBpZl9ub25lID0gbnVsbCwgZnVuKSB7XG4gICAgZm9yIChsZXQgZWxlbSBvZiBjb2xsZWN0aW9uKSB7XG4gICAgICBpZiAoZnVuKGVsZW0pKSB7XG4gICAgICAgIHJldHVybiBlbGVtO1xuICAgICAgfVxuICAgIH1cblxuICAgIHJldHVybiBpZl9ub25lO1xuICB9LFxuXG4gIGludG86IGZ1bmN0aW9uIChjb2xsZWN0aW9uLCBsaXN0KSB7XG4gICAgcmV0dXJuIGxpc3QuY29uY2F0KGNvbGxlY3Rpb24pO1xuICB9LFxuXG4gIG1hcDogZnVuY3Rpb24gKGNvbGxlY3Rpb24sIGZ1bikge1xuICAgIGxldCByZXN1bHQgPSBbXTtcblxuICAgIGZvciAobGV0IGVsZW0gb2YgY29sbGVjdGlvbikge1xuICAgICAgcmVzdWx0LnB1c2goZnVuKGVsZW0pKTtcbiAgICB9XG5cbiAgICByZXR1cm4gcmVzdWx0O1xuICB9LFxuXG4gIG1hcF9yZWR1Y2U6IGZ1bmN0aW9uIChjb2xsZWN0aW9uLCBhY2MsIGZ1bikge1xuICAgIGxldCBtYXBwZWQgPSBMaXN0KCk7XG4gICAgbGV0IHRoZV9hY2MgPSBhY2M7XG5cbiAgICBmb3IgKHZhciBpID0gMDsgaSA8IHRoaXMuY291bnQoY29sbGVjdGlvbik7IGkrKykge1xuICAgICAgbGV0IHR1cGxlID0gZnVuKGNvbGxlY3Rpb25baV0sIHRoZV9hY2MpO1xuXG4gICAgICB0aGVfYWNjID0gdHVwbGUuZ2V0KDEpO1xuICAgICAgbWFwcGVkID0gTGlzdCguLi5tYXBwZWQuY29uY2F0KFt0dXBsZS5nZXQoMCldKSk7XG4gICAgfVxuXG4gICAgcmV0dXJuIG5ldyBUdXBsZShtYXBwZWQsIHRoZV9hY2MpO1xuICB9LFxuXG4gIG1lbWJlcl9fcW1hcmtfXzogZnVuY3Rpb24gKGNvbGxlY3Rpb24sIHZhbHVlKSB7XG4gICAgcmV0dXJuIGNvbGxlY3Rpb24uaW5jbHVkZXModmFsdWUpO1xuICB9LFxuXG4gIHJlZHVjZTogZnVuY3Rpb24gKGNvbGxlY3Rpb24sIGFjYywgZnVuKSB7XG4gICAgbGV0IHRoZV9hY2MgPSBhY2M7XG5cbiAgICBmb3IgKHZhciBpID0gMDsgaSA8IHRoaXMuY291bnQoY29sbGVjdGlvbik7IGkrKykge1xuICAgICAgbGV0IHR1cGxlID0gZnVuKGNvbGxlY3Rpb25baV0sIHRoZV9hY2MpO1xuXG4gICAgICB0aGVfYWNjID0gdHVwbGUuZ2V0KDEpO1xuICAgIH1cblxuICAgIHJldHVybiB0aGVfYWNjO1xuICB9LFxuXG4gIHRha2U6IGZ1bmN0aW9uIChjb2xsZWN0aW9uLCBjb3VudCkge1xuICAgIHJldHVybiBjb2xsZWN0aW9uLnNsaWNlKDAsIGNvdW50KTtcbiAgfSxcblxuICB0YWtlX2V2ZXJ5OiBmdW5jdGlvbiAoY29sbGVjdGlvbiwgbnRoKSB7XG4gICAgbGV0IHJlc3VsdCA9IFtdO1xuICAgIGxldCBpbmRleCA9IDA7XG5cbiAgICBmb3IgKGxldCBlbGVtIG9mIGNvbGxlY3Rpb24pIHtcbiAgICAgIGlmIChpbmRleCAlIG50aCA9PT0gMCkge1xuICAgICAgICByZXN1bHQucHVzaChlbGVtKTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICByZXR1cm4gTGlzdCguLi5yZXN1bHQpO1xuICB9LFxuXG4gIHRha2Vfd2hpbGU6IGZ1bmN0aW9uIChjb2xsZWN0aW9uLCBmdW4pIHtcbiAgICBsZXQgY291bnQgPSAwO1xuXG4gICAgZm9yIChsZXQgZWxlbSBvZiBjb2xsZWN0aW9uKSB7XG4gICAgICBpZiAoZnVuKGVsZW0pKSB7XG4gICAgICAgIGNvdW50ID0gY291bnQgKyAxO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgYnJlYWs7XG4gICAgICB9XG4gICAgfVxuXG4gICAgcmV0dXJuIGNvbGxlY3Rpb24uc2xpY2UoMCwgY291bnQpO1xuICB9LFxuXG4gIHRvX2xpc3Q6IGZ1bmN0aW9uIChjb2xsZWN0aW9uKSB7XG4gICAgcmV0dXJuIGNvbGxlY3Rpb247XG4gIH1cbn07XG5cbmxldCBWaXJ0dWFsRE9NID0gKGZ1bmN0aW9uIChlKSB7XG4gICAgcmV0dXJuIGUoKTtcbn0pKGZ1bmN0aW9uICgpIHtcbiAgICB2YXIgZGVmaW5lLCBtb2R1bGUsIGV4cG9ydHM7XG4gICAgcmV0dXJuIChmdW5jdGlvbiBlKHQsIG4sIHIpIHtcbiAgICAgICAgZnVuY3Rpb24gcyhvLCB1KSB7XG4gICAgICAgICAgICBpZiAoIW5bb10pIHtcbiAgICAgICAgICAgICAgICBpZiAoIXRbb10pIHtcbiAgICAgICAgICAgICAgICAgICAgdmFyIGEgPSB0eXBlb2YgcmVxdWlyZSA9PSBcImZ1bmN0aW9uXCIgJiYgcmVxdWlyZTtcbiAgICAgICAgICAgICAgICAgICAgaWYgKCF1ICYmIGEpIHJldHVybiBhKG8sICEwKTtcbiAgICAgICAgICAgICAgICAgICAgaWYgKGkpIHJldHVybiBpKG8sICEwKTtcbiAgICAgICAgICAgICAgICAgICAgdmFyIGYgPSBuZXcgRXJyb3IoXCJDYW5ub3QgZmluZCBtb2R1bGUgJ1wiICsgbyArIFwiJ1wiKTtcbiAgICAgICAgICAgICAgICAgICAgdGhyb3cgKGYuY29kZSA9IFwiTU9EVUxFX05PVF9GT1VORFwiLCBmKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgdmFyIGwgPSBuW29dID0ge1xuICAgICAgICAgICAgICAgICAgICBleHBvcnRzOiB7fVxuICAgICAgICAgICAgICAgIH07XG4gICAgICAgICAgICAgICAgdFtvXVswXS5jYWxsKGwuZXhwb3J0cywgZnVuY3Rpb24gKGUpIHtcbiAgICAgICAgICAgICAgICAgICAgdmFyIG4gPSB0W29dWzFdW2VdO1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gcyhuID8gbiA6IGUpO1xuICAgICAgICAgICAgICAgIH0sIGwsIGwuZXhwb3J0cywgZSwgdCwgbiwgcik7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXR1cm4gbltvXS5leHBvcnRzO1xuICAgICAgICB9XG4gICAgICAgIHZhciBpID0gdHlwZW9mIHJlcXVpcmUgPT0gXCJmdW5jdGlvblwiICYmIHJlcXVpcmU7XG4gICAgICAgIGZvciAodmFyIG8gPSAwOyBvIDwgci5sZW5ndGg7IG8rKykgcyhyW29dKTtcbiAgICAgICAgcmV0dXJuIHM7XG4gICAgfSkoe1xuICAgICAgICAxOiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge1xuXG4gICAgICAgICAgICB2YXIgY3JlYXRlRWxlbWVudCA9IHJlcXVpcmUoXCIuL3Zkb20vY3JlYXRlLWVsZW1lbnQuanNcIik7XG5cbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gY3JlYXRlRWxlbWVudDtcbiAgICAgICAgfSwgeyBcIi4vdmRvbS9jcmVhdGUtZWxlbWVudC5qc1wiOiAxNSB9XSwgMjogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHtcbiAgICAgICAgICAgIHZhciBkaWZmID0gcmVxdWlyZShcIi4vdnRyZWUvZGlmZi5qc1wiKTtcblxuICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBkaWZmO1xuICAgICAgICB9LCB7IFwiLi92dHJlZS9kaWZmLmpzXCI6IDM1IH1dLCAzOiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge1xuICAgICAgICAgICAgdmFyIGggPSByZXF1aXJlKFwiLi92aXJ0dWFsLWh5cGVyc2NyaXB0L2luZGV4LmpzXCIpO1xuXG4gICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IGg7XG4gICAgICAgIH0sIHsgXCIuL3ZpcnR1YWwtaHlwZXJzY3JpcHQvaW5kZXguanNcIjogMjIgfV0sIDQ6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICB2YXIgZGlmZiA9IHJlcXVpcmUoXCIuL2RpZmYuanNcIik7XG4gICAgICAgICAgICB2YXIgcGF0Y2ggPSByZXF1aXJlKFwiLi9wYXRjaC5qc1wiKTtcbiAgICAgICAgICAgIHZhciBoID0gcmVxdWlyZShcIi4vaC5qc1wiKTtcbiAgICAgICAgICAgIHZhciBjcmVhdGUgPSByZXF1aXJlKFwiLi9jcmVhdGUtZWxlbWVudC5qc1wiKTtcbiAgICAgICAgICAgIHZhciBWTm9kZSA9IHJlcXVpcmUoXCIuL3Zub2RlL3Zub2RlLmpzXCIpO1xuICAgICAgICAgICAgdmFyIFZUZXh0ID0gcmVxdWlyZShcIi4vdm5vZGUvdnRleHQuanNcIik7XG5cbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0ge1xuICAgICAgICAgICAgICAgIGRpZmY6IGRpZmYsXG4gICAgICAgICAgICAgICAgcGF0Y2g6IHBhdGNoLFxuICAgICAgICAgICAgICAgIGg6IGgsXG4gICAgICAgICAgICAgICAgY3JlYXRlOiBjcmVhdGUsXG4gICAgICAgICAgICAgICAgVk5vZGU6IFZOb2RlLFxuICAgICAgICAgICAgICAgIFZUZXh0OiBWVGV4dFxuICAgICAgICAgICAgfTtcbiAgICAgICAgfSwgeyBcIi4vY3JlYXRlLWVsZW1lbnQuanNcIjogMSwgXCIuL2RpZmYuanNcIjogMiwgXCIuL2guanNcIjogMywgXCIuL3BhdGNoLmpzXCI6IDEzLCBcIi4vdm5vZGUvdm5vZGUuanNcIjogMzEsIFwiLi92bm9kZS92dGV4dC5qc1wiOiAzMyB9XSwgNTogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHtcbiAgICAgICAgICAgIC8qIVxuICAgICAgICAgICAgICogQ3Jvc3MtQnJvd3NlciBTcGxpdCAxLjEuMVxuICAgICAgICAgICAgICogQ29weXJpZ2h0IDIwMDctMjAxMiBTdGV2ZW4gTGV2aXRoYW4gPHN0ZXZlbmxldml0aGFuLmNvbT5cbiAgICAgICAgICAgICAqIEF2YWlsYWJsZSB1bmRlciB0aGUgTUlUIExpY2Vuc2VcbiAgICAgICAgICAgICAqIEVDTUFTY3JpcHQgY29tcGxpYW50LCB1bmlmb3JtIGNyb3NzLWJyb3dzZXIgc3BsaXQgbWV0aG9kXG4gICAgICAgICAgICAgKi9cblxuICAgICAgICAgICAgLyoqXG4gICAgICAgICAgICAgKiBTcGxpdHMgYSBzdHJpbmcgaW50byBhbiBhcnJheSBvZiBzdHJpbmdzIHVzaW5nIGEgcmVnZXggb3Igc3RyaW5nIHNlcGFyYXRvci4gTWF0Y2hlcyBvZiB0aGVcbiAgICAgICAgICAgICAqIHNlcGFyYXRvciBhcmUgbm90IGluY2x1ZGVkIGluIHRoZSByZXN1bHQgYXJyYXkuIEhvd2V2ZXIsIGlmIGBzZXBhcmF0b3JgIGlzIGEgcmVnZXggdGhhdCBjb250YWluc1xuICAgICAgICAgICAgICogY2FwdHVyaW5nIGdyb3VwcywgYmFja3JlZmVyZW5jZXMgYXJlIHNwbGljZWQgaW50byB0aGUgcmVzdWx0IGVhY2ggdGltZSBgc2VwYXJhdG9yYCBpcyBtYXRjaGVkLlxuICAgICAgICAgICAgICogRml4ZXMgYnJvd3NlciBidWdzIGNvbXBhcmVkIHRvIHRoZSBuYXRpdmUgYFN0cmluZy5wcm90b3R5cGUuc3BsaXRgIGFuZCBjYW4gYmUgdXNlZCByZWxpYWJseVxuICAgICAgICAgICAgICogY3Jvc3MtYnJvd3Nlci5cbiAgICAgICAgICAgICAqIEBwYXJhbSB7U3RyaW5nfSBzdHIgU3RyaW5nIHRvIHNwbGl0LlxuICAgICAgICAgICAgICogQHBhcmFtIHtSZWdFeHB8U3RyaW5nfSBzZXBhcmF0b3IgUmVnZXggb3Igc3RyaW5nIHRvIHVzZSBmb3Igc2VwYXJhdGluZyB0aGUgc3RyaW5nLlxuICAgICAgICAgICAgICogQHBhcmFtIHtOdW1iZXJ9IFtsaW1pdF0gTWF4aW11bSBudW1iZXIgb2YgaXRlbXMgdG8gaW5jbHVkZSBpbiB0aGUgcmVzdWx0IGFycmF5LlxuICAgICAgICAgICAgICogQHJldHVybnMge0FycmF5fSBBcnJheSBvZiBzdWJzdHJpbmdzLlxuICAgICAgICAgICAgICogQGV4YW1wbGVcbiAgICAgICAgICAgICAqXG4gICAgICAgICAgICAgKiAvLyBCYXNpYyB1c2VcbiAgICAgICAgICAgICAqIHNwbGl0KCdhIGIgYyBkJywgJyAnKTtcbiAgICAgICAgICAgICAqIC8vIC0+IFsnYScsICdiJywgJ2MnLCAnZCddXG4gICAgICAgICAgICAgKlxuICAgICAgICAgICAgICogLy8gV2l0aCBsaW1pdFxuICAgICAgICAgICAgICogc3BsaXQoJ2EgYiBjIGQnLCAnICcsIDIpO1xuICAgICAgICAgICAgICogLy8gLT4gWydhJywgJ2InXVxuICAgICAgICAgICAgICpcbiAgICAgICAgICAgICAqIC8vIEJhY2tyZWZlcmVuY2VzIGluIHJlc3VsdCBhcnJheVxuICAgICAgICAgICAgICogc3BsaXQoJy4ud29yZDEgd29yZDIuLicsIC8oW2Etel0rKShcXGQrKS9pKTtcbiAgICAgICAgICAgICAqIC8vIC0+IFsnLi4nLCAnd29yZCcsICcxJywgJyAnLCAnd29yZCcsICcyJywgJy4uJ11cbiAgICAgICAgICAgICAqL1xuICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSAoZnVuY3Rpb24gc3BsaXQodW5kZWYpIHtcblxuICAgICAgICAgICAgICAgIHZhciBuYXRpdmVTcGxpdCA9IFN0cmluZy5wcm90b3R5cGUuc3BsaXQsXG4gICAgICAgICAgICAgICAgICAgIGNvbXBsaWFudEV4ZWNOcGNnID0gLygpPz8vLmV4ZWMoXCJcIilbMV0gPT09IHVuZGVmLFxuXG4gICAgICAgICAgICAgICAgLy8gTlBDRzogbm9ucGFydGljaXBhdGluZyBjYXB0dXJpbmcgZ3JvdXBcbiAgICAgICAgICAgICAgICBzZWxmO1xuXG4gICAgICAgICAgICAgICAgc2VsZiA9IGZ1bmN0aW9uIChzdHIsIHNlcGFyYXRvciwgbGltaXQpIHtcbiAgICAgICAgICAgICAgICAgICAgLy8gSWYgYHNlcGFyYXRvcmAgaXMgbm90IGEgcmVnZXgsIHVzZSBgbmF0aXZlU3BsaXRgXG4gICAgICAgICAgICAgICAgICAgIGlmIChPYmplY3QucHJvdG90eXBlLnRvU3RyaW5nLmNhbGwoc2VwYXJhdG9yKSAhPT0gXCJbb2JqZWN0IFJlZ0V4cF1cIikge1xuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIG5hdGl2ZVNwbGl0LmNhbGwoc3RyLCBzZXBhcmF0b3IsIGxpbWl0KTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB2YXIgb3V0cHV0ID0gW10sXG4gICAgICAgICAgICAgICAgICAgICAgICBmbGFncyA9IChzZXBhcmF0b3IuaWdub3JlQ2FzZSA/IFwiaVwiIDogXCJcIikgKyAoc2VwYXJhdG9yLm11bHRpbGluZSA/IFwibVwiIDogXCJcIikgKyAoc2VwYXJhdG9yLmV4dGVuZGVkID8gXCJ4XCIgOiBcIlwiKSArIChzZXBhcmF0b3Iuc3RpY2t5ID8gXCJ5XCIgOiBcIlwiKSxcblxuICAgICAgICAgICAgICAgICAgICAvLyBGaXJlZm94IDMrXG4gICAgICAgICAgICAgICAgICAgIGxhc3RMYXN0SW5kZXggPSAwLFxuXG4gICAgICAgICAgICAgICAgICAgIC8vIE1ha2UgYGdsb2JhbGAgYW5kIGF2b2lkIGBsYXN0SW5kZXhgIGlzc3VlcyBieSB3b3JraW5nIHdpdGggYSBjb3B5XG4gICAgICAgICAgICAgICAgICAgIHNlcGFyYXRvciA9IG5ldyBSZWdFeHAoc2VwYXJhdG9yLnNvdXJjZSwgZmxhZ3MgKyBcImdcIiksXG4gICAgICAgICAgICAgICAgICAgICAgICBzZXBhcmF0b3IyLFxuICAgICAgICAgICAgICAgICAgICAgICAgbWF0Y2gsXG4gICAgICAgICAgICAgICAgICAgICAgICBsYXN0SW5kZXgsXG4gICAgICAgICAgICAgICAgICAgICAgICBsYXN0TGVuZ3RoO1xuICAgICAgICAgICAgICAgICAgICBzdHIgKz0gXCJcIjsgLy8gVHlwZS1jb252ZXJ0XG4gICAgICAgICAgICAgICAgICAgIGlmICghY29tcGxpYW50RXhlY05wY2cpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIERvZXNuJ3QgbmVlZCBmbGFncyBneSwgYnV0IHRoZXkgZG9uJ3QgaHVydFxuICAgICAgICAgICAgICAgICAgICAgICAgc2VwYXJhdG9yMiA9IG5ldyBSZWdFeHAoXCJeXCIgKyBzZXBhcmF0b3Iuc291cmNlICsgXCIkKD8hXFxcXHMpXCIsIGZsYWdzKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAvKiBWYWx1ZXMgZm9yIGBsaW1pdGAsIHBlciB0aGUgc3BlYzpcbiAgICAgICAgICAgICAgICAgICAgICogSWYgdW5kZWZpbmVkOiA0Mjk0OTY3Mjk1IC8vIE1hdGgucG93KDIsIDMyKSAtIDFcbiAgICAgICAgICAgICAgICAgICAgICogSWYgMCwgSW5maW5pdHksIG9yIE5hTjogMFxuICAgICAgICAgICAgICAgICAgICAgKiBJZiBwb3NpdGl2ZSBudW1iZXI6IGxpbWl0ID0gTWF0aC5mbG9vcihsaW1pdCk7IGlmIChsaW1pdCA+IDQyOTQ5NjcyOTUpIGxpbWl0IC09IDQyOTQ5NjcyOTY7XG4gICAgICAgICAgICAgICAgICAgICAqIElmIG5lZ2F0aXZlIG51bWJlcjogNDI5NDk2NzI5NiAtIE1hdGguZmxvb3IoTWF0aC5hYnMobGltaXQpKVxuICAgICAgICAgICAgICAgICAgICAgKiBJZiBvdGhlcjogVHlwZS1jb252ZXJ0LCB0aGVuIHVzZSB0aGUgYWJvdmUgcnVsZXNcbiAgICAgICAgICAgICAgICAgICAgICovXG4gICAgICAgICAgICAgICAgICAgIGxpbWl0ID0gbGltaXQgPT09IHVuZGVmID8gLTEgPj4+IDAgOiAvLyBNYXRoLnBvdygyLCAzMikgLSAxXG4gICAgICAgICAgICAgICAgICAgIGxpbWl0ID4+PiAwOyAvLyBUb1VpbnQzMihsaW1pdClcbiAgICAgICAgICAgICAgICAgICAgd2hpbGUgKG1hdGNoID0gc2VwYXJhdG9yLmV4ZWMoc3RyKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgLy8gYHNlcGFyYXRvci5sYXN0SW5kZXhgIGlzIG5vdCByZWxpYWJsZSBjcm9zcy1icm93c2VyXG4gICAgICAgICAgICAgICAgICAgICAgICBsYXN0SW5kZXggPSBtYXRjaC5pbmRleCArIG1hdGNoWzBdLmxlbmd0aDtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChsYXN0SW5kZXggPiBsYXN0TGFzdEluZGV4KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgb3V0cHV0LnB1c2goc3RyLnNsaWNlKGxhc3RMYXN0SW5kZXgsIG1hdGNoLmluZGV4KSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gRml4IGJyb3dzZXJzIHdob3NlIGBleGVjYCBtZXRob2RzIGRvbid0IGNvbnNpc3RlbnRseSByZXR1cm4gYHVuZGVmaW5lZGAgZm9yXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gbm9ucGFydGljaXBhdGluZyBjYXB0dXJpbmcgZ3JvdXBzXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKCFjb21wbGlhbnRFeGVjTnBjZyAmJiBtYXRjaC5sZW5ndGggPiAxKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1hdGNoWzBdLnJlcGxhY2Uoc2VwYXJhdG9yMiwgZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZm9yICh2YXIgaSA9IDE7IGkgPCBhcmd1bWVudHMubGVuZ3RoIC0gMjsgaSsrKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGFyZ3VtZW50c1tpXSA9PT0gdW5kZWYpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbWF0Y2hbaV0gPSB1bmRlZjtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAobWF0Y2gubGVuZ3RoID4gMSAmJiBtYXRjaC5pbmRleCA8IHN0ci5sZW5ndGgpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgQXJyYXkucHJvdG90eXBlLnB1c2guYXBwbHkob3V0cHV0LCBtYXRjaC5zbGljZSgxKSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxhc3RMZW5ndGggPSBtYXRjaFswXS5sZW5ndGg7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgbGFzdExhc3RJbmRleCA9IGxhc3RJbmRleDtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAob3V0cHV0Lmxlbmd0aCA+PSBsaW1pdCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoc2VwYXJhdG9yLmxhc3RJbmRleCA9PT0gbWF0Y2guaW5kZXgpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBzZXBhcmF0b3IubGFzdEluZGV4Kys7IC8vIEF2b2lkIGFuIGluZmluaXRlIGxvb3BcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICBpZiAobGFzdExhc3RJbmRleCA9PT0gc3RyLmxlbmd0aCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGxhc3RMZW5ndGggfHwgIXNlcGFyYXRvci50ZXN0KFwiXCIpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgb3V0cHV0LnB1c2goXCJcIik7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBvdXRwdXQucHVzaChzdHIuc2xpY2UobGFzdExhc3RJbmRleCkpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBvdXRwdXQubGVuZ3RoID4gbGltaXQgPyBvdXRwdXQuc2xpY2UoMCwgbGltaXQpIDogb3V0cHV0O1xuICAgICAgICAgICAgICAgIH07XG5cbiAgICAgICAgICAgICAgICByZXR1cm4gc2VsZjtcbiAgICAgICAgICAgIH0pKCk7XG4gICAgICAgIH0sIHt9XSwgNjogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHt9LCB7fV0sIDc6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICBcInVzZSBzdHJpY3RcIjtcblxuICAgICAgICAgICAgdmFyIE9uZVZlcnNpb25Db25zdHJhaW50ID0gcmVxdWlyZShcImluZGl2aWR1YWwvb25lLXZlcnNpb25cIik7XG5cbiAgICAgICAgICAgIHZhciBNWV9WRVJTSU9OID0gXCI3XCI7XG4gICAgICAgICAgICBPbmVWZXJzaW9uQ29uc3RyYWludChcImV2LXN0b3JlXCIsIE1ZX1ZFUlNJT04pO1xuXG4gICAgICAgICAgICB2YXIgaGFzaEtleSA9IFwiX19FVl9TVE9SRV9LRVlAXCIgKyBNWV9WRVJTSU9OO1xuXG4gICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IEV2U3RvcmU7XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIEV2U3RvcmUoZWxlbSkge1xuICAgICAgICAgICAgICAgIHZhciBoYXNoID0gZWxlbVtoYXNoS2V5XTtcblxuICAgICAgICAgICAgICAgIGlmICghaGFzaCkge1xuICAgICAgICAgICAgICAgICAgICBoYXNoID0gZWxlbVtoYXNoS2V5XSA9IHt9O1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHJldHVybiBoYXNoO1xuICAgICAgICAgICAgfVxuICAgICAgICB9LCB7IFwiaW5kaXZpZHVhbC9vbmUtdmVyc2lvblwiOiA5IH1dLCA4OiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge1xuICAgICAgICAgICAgKGZ1bmN0aW9uIChnbG9iYWwpIHtcbiAgICAgICAgICAgICAgICBcInVzZSBzdHJpY3RcIjtcblxuICAgICAgICAgICAgICAgIC8qZ2xvYmFsIHdpbmRvdywgZ2xvYmFsKi9cblxuICAgICAgICAgICAgICAgIHZhciByb290ID0gdHlwZW9mIHdpbmRvdyAhPT0gXCJ1bmRlZmluZWRcIiA/IHdpbmRvdyA6IHR5cGVvZiBnbG9iYWwgIT09IFwidW5kZWZpbmVkXCIgPyBnbG9iYWwgOiB7fTtcblxuICAgICAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gSW5kaXZpZHVhbDtcblxuICAgICAgICAgICAgICAgIGZ1bmN0aW9uIEluZGl2aWR1YWwoa2V5LCB2YWx1ZSkge1xuICAgICAgICAgICAgICAgICAgICBpZiAoa2V5IGluIHJvb3QpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiByb290W2tleV07XG4gICAgICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgICAgICByb290W2tleV0gPSB2YWx1ZTtcblxuICAgICAgICAgICAgICAgICAgICByZXR1cm4gdmFsdWU7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSkuY2FsbCh0aGlzLCB0eXBlb2YgZ2xvYmFsICE9PSBcInVuZGVmaW5lZFwiID8gZ2xvYmFsIDogdHlwZW9mIHNlbGYgIT09IFwidW5kZWZpbmVkXCIgPyBzZWxmIDogdHlwZW9mIHdpbmRvdyAhPT0gXCJ1bmRlZmluZWRcIiA/IHdpbmRvdyA6IHt9KTtcbiAgICAgICAgfSwge31dLCA5OiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge1xuICAgICAgICAgICAgXCJ1c2Ugc3RyaWN0XCI7XG5cbiAgICAgICAgICAgIHZhciBJbmRpdmlkdWFsID0gcmVxdWlyZShcIi4vaW5kZXguanNcIik7XG5cbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gT25lVmVyc2lvbjtcblxuICAgICAgICAgICAgZnVuY3Rpb24gT25lVmVyc2lvbihtb2R1bGVOYW1lLCB2ZXJzaW9uLCBkZWZhdWx0VmFsdWUpIHtcbiAgICAgICAgICAgICAgICB2YXIga2V5ID0gXCJfX0lORElWSURVQUxfT05FX1ZFUlNJT05fXCIgKyBtb2R1bGVOYW1lO1xuICAgICAgICAgICAgICAgIHZhciBlbmZvcmNlS2V5ID0ga2V5ICsgXCJfRU5GT1JDRV9TSU5HTEVUT05cIjtcblxuICAgICAgICAgICAgICAgIHZhciB2ZXJzaW9uVmFsdWUgPSBJbmRpdmlkdWFsKGVuZm9yY2VLZXksIHZlcnNpb24pO1xuXG4gICAgICAgICAgICAgICAgaWYgKHZlcnNpb25WYWx1ZSAhPT0gdmVyc2lvbikge1xuICAgICAgICAgICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoXCJDYW4gb25seSBoYXZlIG9uZSBjb3B5IG9mIFwiICsgbW9kdWxlTmFtZSArIFwiLlxcblwiICsgXCJZb3UgYWxyZWFkeSBoYXZlIHZlcnNpb24gXCIgKyB2ZXJzaW9uVmFsdWUgKyBcIiBpbnN0YWxsZWQuXFxuXCIgKyBcIlRoaXMgbWVhbnMgeW91IGNhbm5vdCBpbnN0YWxsIHZlcnNpb24gXCIgKyB2ZXJzaW9uKTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICByZXR1cm4gSW5kaXZpZHVhbChrZXksIGRlZmF1bHRWYWx1ZSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0sIHsgXCIuL2luZGV4LmpzXCI6IDggfV0sIDEwOiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge1xuICAgICAgICAgICAgKGZ1bmN0aW9uIChnbG9iYWwpIHtcbiAgICAgICAgICAgICAgICB2YXIgdG9wTGV2ZWwgPSB0eXBlb2YgZ2xvYmFsICE9PSBcInVuZGVmaW5lZFwiID8gZ2xvYmFsIDogdHlwZW9mIHdpbmRvdyAhPT0gXCJ1bmRlZmluZWRcIiA/IHdpbmRvdyA6IHt9O1xuICAgICAgICAgICAgICAgIHZhciBtaW5Eb2MgPSByZXF1aXJlKFwibWluLWRvY3VtZW50XCIpO1xuXG4gICAgICAgICAgICAgICAgaWYgKHR5cGVvZiBkb2N1bWVudCAhPT0gXCJ1bmRlZmluZWRcIikge1xuICAgICAgICAgICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IGRvY3VtZW50O1xuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciBkb2NjeSA9IHRvcExldmVsW1wiX19HTE9CQUxfRE9DVU1FTlRfQ0FDSEVANFwiXTtcblxuICAgICAgICAgICAgICAgICAgICBpZiAoIWRvY2N5KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBkb2NjeSA9IHRvcExldmVsW1wiX19HTE9CQUxfRE9DVU1FTlRfQ0FDSEVANFwiXSA9IG1pbkRvYztcbiAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gZG9jY3k7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSkuY2FsbCh0aGlzLCB0eXBlb2YgZ2xvYmFsICE9PSBcInVuZGVmaW5lZFwiID8gZ2xvYmFsIDogdHlwZW9mIHNlbGYgIT09IFwidW5kZWZpbmVkXCIgPyBzZWxmIDogdHlwZW9mIHdpbmRvdyAhPT0gXCJ1bmRlZmluZWRcIiA/IHdpbmRvdyA6IHt9KTtcbiAgICAgICAgfSwgeyBcIm1pbi1kb2N1bWVudFwiOiA2IH1dLCAxMTogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHtcbiAgICAgICAgICAgIFwidXNlIHN0cmljdFwiO1xuXG4gICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uIGlzT2JqZWN0KHgpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gdHlwZW9mIHggPT09IFwib2JqZWN0XCIgJiYgeCAhPT0gbnVsbDtcbiAgICAgICAgICAgIH07XG4gICAgICAgIH0sIHt9XSwgMTI6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICB2YXIgbmF0aXZlSXNBcnJheSA9IEFycmF5LmlzQXJyYXk7XG4gICAgICAgICAgICB2YXIgdG9TdHJpbmcgPSBPYmplY3QucHJvdG90eXBlLnRvU3RyaW5nO1xuXG4gICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IG5hdGl2ZUlzQXJyYXkgfHwgaXNBcnJheTtcblxuICAgICAgICAgICAgZnVuY3Rpb24gaXNBcnJheShvYmopIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gdG9TdHJpbmcuY2FsbChvYmopID09PSBcIltvYmplY3QgQXJyYXldXCI7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0sIHt9XSwgMTM6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICB2YXIgcGF0Y2ggPSByZXF1aXJlKFwiLi92ZG9tL3BhdGNoLmpzXCIpO1xuXG4gICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IHBhdGNoO1xuICAgICAgICB9LCB7IFwiLi92ZG9tL3BhdGNoLmpzXCI6IDE4IH1dLCAxNDogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHtcbiAgICAgICAgICAgIHZhciBpc09iamVjdCA9IHJlcXVpcmUoXCJpcy1vYmplY3RcIik7XG4gICAgICAgICAgICB2YXIgaXNIb29rID0gcmVxdWlyZShcIi4uL3Zub2RlL2lzLXZob29rLmpzXCIpO1xuXG4gICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IGFwcGx5UHJvcGVydGllcztcblxuICAgICAgICAgICAgZnVuY3Rpb24gYXBwbHlQcm9wZXJ0aWVzKG5vZGUsIHByb3BzLCBwcmV2aW91cykge1xuICAgICAgICAgICAgICAgIGZvciAodmFyIHByb3BOYW1lIGluIHByb3BzKSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciBwcm9wVmFsdWUgPSBwcm9wc1twcm9wTmFtZV07XG5cbiAgICAgICAgICAgICAgICAgICAgaWYgKHByb3BWYWx1ZSA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICByZW1vdmVQcm9wZXJ0eShub2RlLCBwcm9wTmFtZSwgcHJvcFZhbHVlLCBwcmV2aW91cyk7XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoaXNIb29rKHByb3BWYWx1ZSkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJlbW92ZVByb3BlcnR5KG5vZGUsIHByb3BOYW1lLCBwcm9wVmFsdWUsIHByZXZpb3VzKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChwcm9wVmFsdWUuaG9vaykge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHByb3BWYWx1ZS5ob29rKG5vZGUsIHByb3BOYW1lLCBwcmV2aW91cyA/IHByZXZpb3VzW3Byb3BOYW1lXSA6IHVuZGVmaW5lZCk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoaXNPYmplY3QocHJvcFZhbHVlKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHBhdGNoT2JqZWN0KG5vZGUsIHByb3BzLCBwcmV2aW91cywgcHJvcE5hbWUsIHByb3BWYWx1ZSk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIG5vZGVbcHJvcE5hbWVdID0gcHJvcFZhbHVlO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBmdW5jdGlvbiByZW1vdmVQcm9wZXJ0eShub2RlLCBwcm9wTmFtZSwgcHJvcFZhbHVlLCBwcmV2aW91cykge1xuICAgICAgICAgICAgICAgIGlmIChwcmV2aW91cykge1xuICAgICAgICAgICAgICAgICAgICB2YXIgcHJldmlvdXNWYWx1ZSA9IHByZXZpb3VzW3Byb3BOYW1lXTtcblxuICAgICAgICAgICAgICAgICAgICBpZiAoIWlzSG9vayhwcmV2aW91c1ZhbHVlKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHByb3BOYW1lID09PSBcImF0dHJpYnV0ZXNcIikge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZvciAodmFyIGF0dHJOYW1lIGluIHByZXZpb3VzVmFsdWUpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbm9kZS5yZW1vdmVBdHRyaWJ1dGUoYXR0ck5hbWUpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAocHJvcE5hbWUgPT09IFwic3R5bGVcIikge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZvciAodmFyIGkgaW4gcHJldmlvdXNWYWx1ZSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBub2RlLnN0eWxlW2ldID0gXCJcIjtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKHR5cGVvZiBwcmV2aW91c1ZhbHVlID09PSBcInN0cmluZ1wiKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgbm9kZVtwcm9wTmFtZV0gPSBcIlwiO1xuICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBub2RlW3Byb3BOYW1lXSA9IG51bGw7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAocHJldmlvdXNWYWx1ZS51bmhvb2spIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHByZXZpb3VzVmFsdWUudW5ob29rKG5vZGUsIHByb3BOYW1lLCBwcm9wVmFsdWUpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBmdW5jdGlvbiBwYXRjaE9iamVjdChub2RlLCBwcm9wcywgcHJldmlvdXMsIHByb3BOYW1lLCBwcm9wVmFsdWUpIHtcbiAgICAgICAgICAgICAgICB2YXIgcHJldmlvdXNWYWx1ZSA9IHByZXZpb3VzID8gcHJldmlvdXNbcHJvcE5hbWVdIDogdW5kZWZpbmVkO1xuXG4gICAgICAgICAgICAgICAgLy8gU2V0IGF0dHJpYnV0ZXNcbiAgICAgICAgICAgICAgICBpZiAocHJvcE5hbWUgPT09IFwiYXR0cmlidXRlc1wiKSB7XG4gICAgICAgICAgICAgICAgICAgIGZvciAodmFyIGF0dHJOYW1lIGluIHByb3BWYWx1ZSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgdmFyIGF0dHJWYWx1ZSA9IHByb3BWYWx1ZVthdHRyTmFtZV07XG5cbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChhdHRyVmFsdWUgPT09IHVuZGVmaW5lZCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIG5vZGUucmVtb3ZlQXR0cmlidXRlKGF0dHJOYW1lKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgbm9kZS5zZXRBdHRyaWJ1dGUoYXR0ck5hbWUsIGF0dHJWYWx1ZSk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgaWYgKHByZXZpb3VzVmFsdWUgJiYgaXNPYmplY3QocHJldmlvdXNWYWx1ZSkgJiYgZ2V0UHJvdG90eXBlKHByZXZpb3VzVmFsdWUpICE9PSBnZXRQcm90b3R5cGUocHJvcFZhbHVlKSkge1xuICAgICAgICAgICAgICAgICAgICBub2RlW3Byb3BOYW1lXSA9IHByb3BWYWx1ZTtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIGlmICghaXNPYmplY3Qobm9kZVtwcm9wTmFtZV0pKSB7XG4gICAgICAgICAgICAgICAgICAgIG5vZGVbcHJvcE5hbWVdID0ge307XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgdmFyIHJlcGxhY2VyID0gcHJvcE5hbWUgPT09IFwic3R5bGVcIiA/IFwiXCIgOiB1bmRlZmluZWQ7XG5cbiAgICAgICAgICAgICAgICBmb3IgKHZhciBrIGluIHByb3BWYWx1ZSkge1xuICAgICAgICAgICAgICAgICAgICB2YXIgdmFsdWUgPSBwcm9wVmFsdWVba107XG4gICAgICAgICAgICAgICAgICAgIG5vZGVbcHJvcE5hbWVdW2tdID0gdmFsdWUgPT09IHVuZGVmaW5lZCA/IHJlcGxhY2VyIDogdmFsdWU7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBmdW5jdGlvbiBnZXRQcm90b3R5cGUodmFsdWUpIHtcbiAgICAgICAgICAgICAgICBpZiAoT2JqZWN0LmdldFByb3RvdHlwZU9mKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBPYmplY3QuZ2V0UHJvdG90eXBlT2YodmFsdWUpO1xuICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAodmFsdWUuX19wcm90b19fKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiB2YWx1ZS5fX3Byb3RvX187XG4gICAgICAgICAgICAgICAgfSBlbHNlIGlmICh2YWx1ZS5jb25zdHJ1Y3Rvcikge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gdmFsdWUuY29uc3RydWN0b3IucHJvdG90eXBlO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgfSwgeyBcIi4uL3Zub2RlL2lzLXZob29rLmpzXCI6IDI2LCBcImlzLW9iamVjdFwiOiAxMSB9XSwgMTU6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICB2YXIgZG9jdW1lbnQgPSByZXF1aXJlKFwiZ2xvYmFsL2RvY3VtZW50XCIpO1xuXG4gICAgICAgICAgICB2YXIgYXBwbHlQcm9wZXJ0aWVzID0gcmVxdWlyZShcIi4vYXBwbHktcHJvcGVydGllc1wiKTtcblxuICAgICAgICAgICAgdmFyIGlzVk5vZGUgPSByZXF1aXJlKFwiLi4vdm5vZGUvaXMtdm5vZGUuanNcIik7XG4gICAgICAgICAgICB2YXIgaXNWVGV4dCA9IHJlcXVpcmUoXCIuLi92bm9kZS9pcy12dGV4dC5qc1wiKTtcbiAgICAgICAgICAgIHZhciBpc1dpZGdldCA9IHJlcXVpcmUoXCIuLi92bm9kZS9pcy13aWRnZXQuanNcIik7XG4gICAgICAgICAgICB2YXIgaGFuZGxlVGh1bmsgPSByZXF1aXJlKFwiLi4vdm5vZGUvaGFuZGxlLXRodW5rLmpzXCIpO1xuXG4gICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IGNyZWF0ZUVsZW1lbnQ7XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIGNyZWF0ZUVsZW1lbnQodm5vZGUsIG9wdHMpIHtcbiAgICAgICAgICAgICAgICB2YXIgZG9jID0gb3B0cyA/IG9wdHMuZG9jdW1lbnQgfHwgZG9jdW1lbnQgOiBkb2N1bWVudDtcbiAgICAgICAgICAgICAgICB2YXIgd2FybiA9IG9wdHMgPyBvcHRzLndhcm4gOiBudWxsO1xuXG4gICAgICAgICAgICAgICAgdm5vZGUgPSBoYW5kbGVUaHVuayh2bm9kZSkuYTtcblxuICAgICAgICAgICAgICAgIGlmIChpc1dpZGdldCh2bm9kZSkpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHZub2RlLmluaXQoKTtcbiAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKGlzVlRleHQodm5vZGUpKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBkb2MuY3JlYXRlVGV4dE5vZGUodm5vZGUudGV4dCk7XG4gICAgICAgICAgICAgICAgfSBlbHNlIGlmICghaXNWTm9kZSh2bm9kZSkpIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKHdhcm4pIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHdhcm4oXCJJdGVtIGlzIG5vdCBhIHZhbGlkIHZpcnR1YWwgZG9tIG5vZGVcIiwgdm5vZGUpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBudWxsO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHZhciBub2RlID0gdm5vZGUubmFtZXNwYWNlID09PSBudWxsID8gZG9jLmNyZWF0ZUVsZW1lbnQodm5vZGUudGFnTmFtZSkgOiBkb2MuY3JlYXRlRWxlbWVudE5TKHZub2RlLm5hbWVzcGFjZSwgdm5vZGUudGFnTmFtZSk7XG5cbiAgICAgICAgICAgICAgICB2YXIgcHJvcHMgPSB2bm9kZS5wcm9wZXJ0aWVzO1xuICAgICAgICAgICAgICAgIGFwcGx5UHJvcGVydGllcyhub2RlLCBwcm9wcyk7XG5cbiAgICAgICAgICAgICAgICB2YXIgY2hpbGRyZW4gPSB2bm9kZS5jaGlsZHJlbjtcblxuICAgICAgICAgICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgY2hpbGRyZW4ubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgICAgICAgICAgdmFyIGNoaWxkTm9kZSA9IGNyZWF0ZUVsZW1lbnQoY2hpbGRyZW5baV0sIG9wdHMpO1xuICAgICAgICAgICAgICAgICAgICBpZiAoY2hpbGROb2RlKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBub2RlLmFwcGVuZENoaWxkKGNoaWxkTm9kZSk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICByZXR1cm4gbm9kZTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSwgeyBcIi4uL3Zub2RlL2hhbmRsZS10aHVuay5qc1wiOiAyNCwgXCIuLi92bm9kZS9pcy12bm9kZS5qc1wiOiAyNywgXCIuLi92bm9kZS9pcy12dGV4dC5qc1wiOiAyOCwgXCIuLi92bm9kZS9pcy13aWRnZXQuanNcIjogMjksIFwiLi9hcHBseS1wcm9wZXJ0aWVzXCI6IDE0LCBcImdsb2JhbC9kb2N1bWVudFwiOiAxMCB9XSwgMTY6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICAvLyBNYXBzIGEgdmlydHVhbCBET00gdHJlZSBvbnRvIGEgcmVhbCBET00gdHJlZSBpbiBhbiBlZmZpY2llbnQgbWFubmVyLlxuICAgICAgICAgICAgLy8gV2UgZG9uJ3Qgd2FudCB0byByZWFkIGFsbCBvZiB0aGUgRE9NIG5vZGVzIGluIHRoZSB0cmVlIHNvIHdlIHVzZVxuICAgICAgICAgICAgLy8gdGhlIGluLW9yZGVyIHRyZWUgaW5kZXhpbmcgdG8gZWxpbWluYXRlIHJlY3Vyc2lvbiBkb3duIGNlcnRhaW4gYnJhbmNoZXMuXG4gICAgICAgICAgICAvLyBXZSBvbmx5IHJlY3Vyc2UgaW50byBhIERPTSBub2RlIGlmIHdlIGtub3cgdGhhdCBpdCBjb250YWlucyBhIGNoaWxkIG9mXG4gICAgICAgICAgICAvLyBpbnRlcmVzdC5cblxuICAgICAgICAgICAgdmFyIG5vQ2hpbGQgPSB7fTtcblxuICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBkb21JbmRleDtcblxuICAgICAgICAgICAgZnVuY3Rpb24gZG9tSW5kZXgocm9vdE5vZGUsIHRyZWUsIGluZGljZXMsIG5vZGVzKSB7XG4gICAgICAgICAgICAgICAgaWYgKCFpbmRpY2VzIHx8IGluZGljZXMubGVuZ3RoID09PSAwKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiB7fTtcbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICBpbmRpY2VzLnNvcnQoYXNjZW5kaW5nKTtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHJlY3Vyc2Uocm9vdE5vZGUsIHRyZWUsIGluZGljZXMsIG5vZGVzLCAwKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIHJlY3Vyc2Uocm9vdE5vZGUsIHRyZWUsIGluZGljZXMsIG5vZGVzLCByb290SW5kZXgpIHtcbiAgICAgICAgICAgICAgICBub2RlcyA9IG5vZGVzIHx8IHt9O1xuXG4gICAgICAgICAgICAgICAgaWYgKHJvb3ROb2RlKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmIChpbmRleEluUmFuZ2UoaW5kaWNlcywgcm9vdEluZGV4LCByb290SW5kZXgpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBub2Rlc1tyb290SW5kZXhdID0gcm9vdE5vZGU7XG4gICAgICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgICAgICB2YXIgdkNoaWxkcmVuID0gdHJlZS5jaGlsZHJlbjtcblxuICAgICAgICAgICAgICAgICAgICBpZiAodkNoaWxkcmVuKSB7XG5cbiAgICAgICAgICAgICAgICAgICAgICAgIHZhciBjaGlsZE5vZGVzID0gcm9vdE5vZGUuY2hpbGROb2RlcztcblxuICAgICAgICAgICAgICAgICAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCB0cmVlLmNoaWxkcmVuLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcm9vdEluZGV4ICs9IDE7XG5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB2YXIgdkNoaWxkID0gdkNoaWxkcmVuW2ldIHx8IG5vQ2hpbGQ7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdmFyIG5leHRJbmRleCA9IHJvb3RJbmRleCArICh2Q2hpbGQuY291bnQgfHwgMCk7XG5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBza2lwIHJlY3Vyc2lvbiBkb3duIHRoZSB0cmVlIGlmIHRoZXJlIGFyZSBubyBub2RlcyBkb3duIGhlcmVcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoaW5kZXhJblJhbmdlKGluZGljZXMsIHJvb3RJbmRleCwgbmV4dEluZGV4KSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICByZWN1cnNlKGNoaWxkTm9kZXNbaV0sIHZDaGlsZCwgaW5kaWNlcywgbm9kZXMsIHJvb3RJbmRleCk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcm9vdEluZGV4ID0gbmV4dEluZGV4O1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgcmV0dXJuIG5vZGVzO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAvLyBCaW5hcnkgc2VhcmNoIGZvciBhbiBpbmRleCBpbiB0aGUgaW50ZXJ2YWwgW2xlZnQsIHJpZ2h0XVxuICAgICAgICAgICAgZnVuY3Rpb24gaW5kZXhJblJhbmdlKGluZGljZXMsIGxlZnQsIHJpZ2h0KSB7XG4gICAgICAgICAgICAgICAgaWYgKGluZGljZXMubGVuZ3RoID09PSAwKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICB2YXIgbWluSW5kZXggPSAwO1xuICAgICAgICAgICAgICAgIHZhciBtYXhJbmRleCA9IGluZGljZXMubGVuZ3RoIC0gMTtcbiAgICAgICAgICAgICAgICB2YXIgY3VycmVudEluZGV4O1xuICAgICAgICAgICAgICAgIHZhciBjdXJyZW50SXRlbTtcblxuICAgICAgICAgICAgICAgIHdoaWxlIChtaW5JbmRleCA8PSBtYXhJbmRleCkge1xuICAgICAgICAgICAgICAgICAgICBjdXJyZW50SW5kZXggPSAobWF4SW5kZXggKyBtaW5JbmRleCkgLyAyID4+IDA7XG4gICAgICAgICAgICAgICAgICAgIGN1cnJlbnRJdGVtID0gaW5kaWNlc1tjdXJyZW50SW5kZXhdO1xuXG4gICAgICAgICAgICAgICAgICAgIGlmIChtaW5JbmRleCA9PT0gbWF4SW5kZXgpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBjdXJyZW50SXRlbSA+PSBsZWZ0ICYmIGN1cnJlbnRJdGVtIDw9IHJpZ2h0O1xuICAgICAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKGN1cnJlbnRJdGVtIDwgbGVmdCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgbWluSW5kZXggPSBjdXJyZW50SW5kZXggKyAxO1xuICAgICAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKGN1cnJlbnRJdGVtID4gcmlnaHQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIG1heEluZGV4ID0gY3VycmVudEluZGV4IC0gMTtcbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBmdW5jdGlvbiBhc2NlbmRpbmcoYSwgYikge1xuICAgICAgICAgICAgICAgIHJldHVybiBhID4gYiA/IDEgOiAtMTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSwge31dLCAxNzogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHtcbiAgICAgICAgICAgIHZhciBhcHBseVByb3BlcnRpZXMgPSByZXF1aXJlKFwiLi9hcHBseS1wcm9wZXJ0aWVzXCIpO1xuXG4gICAgICAgICAgICB2YXIgaXNXaWRnZXQgPSByZXF1aXJlKFwiLi4vdm5vZGUvaXMtd2lkZ2V0LmpzXCIpO1xuICAgICAgICAgICAgdmFyIFZQYXRjaCA9IHJlcXVpcmUoXCIuLi92bm9kZS92cGF0Y2guanNcIik7XG5cbiAgICAgICAgICAgIHZhciB1cGRhdGVXaWRnZXQgPSByZXF1aXJlKFwiLi91cGRhdGUtd2lkZ2V0XCIpO1xuXG4gICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IGFwcGx5UGF0Y2g7XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIGFwcGx5UGF0Y2godnBhdGNoLCBkb21Ob2RlLCByZW5kZXJPcHRpb25zKSB7XG4gICAgICAgICAgICAgICAgdmFyIHR5cGUgPSB2cGF0Y2gudHlwZTtcbiAgICAgICAgICAgICAgICB2YXIgdk5vZGUgPSB2cGF0Y2gudk5vZGU7XG4gICAgICAgICAgICAgICAgdmFyIHBhdGNoID0gdnBhdGNoLnBhdGNoO1xuXG4gICAgICAgICAgICAgICAgc3dpdGNoICh0eXBlKSB7XG4gICAgICAgICAgICAgICAgICAgIGNhc2UgVlBhdGNoLlJFTU9WRTpcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiByZW1vdmVOb2RlKGRvbU5vZGUsIHZOb2RlKTtcbiAgICAgICAgICAgICAgICAgICAgY2FzZSBWUGF0Y2guSU5TRVJUOlxuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGluc2VydE5vZGUoZG9tTm9kZSwgcGF0Y2gsIHJlbmRlck9wdGlvbnMpO1xuICAgICAgICAgICAgICAgICAgICBjYXNlIFZQYXRjaC5WVEVYVDpcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBzdHJpbmdQYXRjaChkb21Ob2RlLCB2Tm9kZSwgcGF0Y2gsIHJlbmRlck9wdGlvbnMpO1xuICAgICAgICAgICAgICAgICAgICBjYXNlIFZQYXRjaC5XSURHRVQ6XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gd2lkZ2V0UGF0Y2goZG9tTm9kZSwgdk5vZGUsIHBhdGNoLCByZW5kZXJPcHRpb25zKTtcbiAgICAgICAgICAgICAgICAgICAgY2FzZSBWUGF0Y2guVk5PREU6XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gdk5vZGVQYXRjaChkb21Ob2RlLCB2Tm9kZSwgcGF0Y2gsIHJlbmRlck9wdGlvbnMpO1xuICAgICAgICAgICAgICAgICAgICBjYXNlIFZQYXRjaC5PUkRFUjpcbiAgICAgICAgICAgICAgICAgICAgICAgIHJlb3JkZXJDaGlsZHJlbihkb21Ob2RlLCBwYXRjaCk7XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gZG9tTm9kZTtcbiAgICAgICAgICAgICAgICAgICAgY2FzZSBWUGF0Y2guUFJPUFM6XG4gICAgICAgICAgICAgICAgICAgICAgICBhcHBseVByb3BlcnRpZXMoZG9tTm9kZSwgcGF0Y2gsIHZOb2RlLnByb3BlcnRpZXMpO1xuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGRvbU5vZGU7XG4gICAgICAgICAgICAgICAgICAgIGNhc2UgVlBhdGNoLlRIVU5LOlxuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHJlcGxhY2VSb290KGRvbU5vZGUsIHJlbmRlck9wdGlvbnMucGF0Y2goZG9tTm9kZSwgcGF0Y2gsIHJlbmRlck9wdGlvbnMpKTtcbiAgICAgICAgICAgICAgICAgICAgZGVmYXVsdDpcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBkb21Ob2RlO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZnVuY3Rpb24gcmVtb3ZlTm9kZShkb21Ob2RlLCB2Tm9kZSkge1xuICAgICAgICAgICAgICAgIHZhciBwYXJlbnROb2RlID0gZG9tTm9kZS5wYXJlbnROb2RlO1xuXG4gICAgICAgICAgICAgICAgaWYgKHBhcmVudE5vZGUpIHtcbiAgICAgICAgICAgICAgICAgICAgcGFyZW50Tm9kZS5yZW1vdmVDaGlsZChkb21Ob2RlKTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICBkZXN0cm95V2lkZ2V0KGRvbU5vZGUsIHZOb2RlKTtcblxuICAgICAgICAgICAgICAgIHJldHVybiBudWxsO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBmdW5jdGlvbiBpbnNlcnROb2RlKHBhcmVudE5vZGUsIHZOb2RlLCByZW5kZXJPcHRpb25zKSB7XG4gICAgICAgICAgICAgICAgdmFyIG5ld05vZGUgPSByZW5kZXJPcHRpb25zLnJlbmRlcih2Tm9kZSwgcmVuZGVyT3B0aW9ucyk7XG5cbiAgICAgICAgICAgICAgICBpZiAocGFyZW50Tm9kZSkge1xuICAgICAgICAgICAgICAgICAgICBwYXJlbnROb2RlLmFwcGVuZENoaWxkKG5ld05vZGUpO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHJldHVybiBwYXJlbnROb2RlO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBmdW5jdGlvbiBzdHJpbmdQYXRjaChkb21Ob2RlLCBsZWZ0Vk5vZGUsIHZUZXh0LCByZW5kZXJPcHRpb25zKSB7XG4gICAgICAgICAgICAgICAgdmFyIG5ld05vZGU7XG5cbiAgICAgICAgICAgICAgICBpZiAoZG9tTm9kZS5ub2RlVHlwZSA9PT0gMykge1xuICAgICAgICAgICAgICAgICAgICBkb21Ob2RlLnJlcGxhY2VEYXRhKDAsIGRvbU5vZGUubGVuZ3RoLCB2VGV4dC50ZXh0KTtcbiAgICAgICAgICAgICAgICAgICAgbmV3Tm9kZSA9IGRvbU5vZGU7XG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgdmFyIHBhcmVudE5vZGUgPSBkb21Ob2RlLnBhcmVudE5vZGU7XG4gICAgICAgICAgICAgICAgICAgIG5ld05vZGUgPSByZW5kZXJPcHRpb25zLnJlbmRlcih2VGV4dCwgcmVuZGVyT3B0aW9ucyk7XG5cbiAgICAgICAgICAgICAgICAgICAgaWYgKHBhcmVudE5vZGUgJiYgbmV3Tm9kZSAhPT0gZG9tTm9kZSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgcGFyZW50Tm9kZS5yZXBsYWNlQ2hpbGQobmV3Tm9kZSwgZG9tTm9kZSk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICByZXR1cm4gbmV3Tm9kZTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZnVuY3Rpb24gd2lkZ2V0UGF0Y2goZG9tTm9kZSwgbGVmdFZOb2RlLCB3aWRnZXQsIHJlbmRlck9wdGlvbnMpIHtcbiAgICAgICAgICAgICAgICB2YXIgdXBkYXRpbmcgPSB1cGRhdGVXaWRnZXQobGVmdFZOb2RlLCB3aWRnZXQpO1xuICAgICAgICAgICAgICAgIHZhciBuZXdOb2RlO1xuXG4gICAgICAgICAgICAgICAgaWYgKHVwZGF0aW5nKSB7XG4gICAgICAgICAgICAgICAgICAgIG5ld05vZGUgPSB3aWRnZXQudXBkYXRlKGxlZnRWTm9kZSwgZG9tTm9kZSkgfHwgZG9tTm9kZTtcbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICBuZXdOb2RlID0gcmVuZGVyT3B0aW9ucy5yZW5kZXIod2lkZ2V0LCByZW5kZXJPcHRpb25zKTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICB2YXIgcGFyZW50Tm9kZSA9IGRvbU5vZGUucGFyZW50Tm9kZTtcblxuICAgICAgICAgICAgICAgIGlmIChwYXJlbnROb2RlICYmIG5ld05vZGUgIT09IGRvbU5vZGUpIHtcbiAgICAgICAgICAgICAgICAgICAgcGFyZW50Tm9kZS5yZXBsYWNlQ2hpbGQobmV3Tm9kZSwgZG9tTm9kZSk7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgaWYgKCF1cGRhdGluZykge1xuICAgICAgICAgICAgICAgICAgICBkZXN0cm95V2lkZ2V0KGRvbU5vZGUsIGxlZnRWTm9kZSk7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgcmV0dXJuIG5ld05vZGU7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIHZOb2RlUGF0Y2goZG9tTm9kZSwgbGVmdFZOb2RlLCB2Tm9kZSwgcmVuZGVyT3B0aW9ucykge1xuICAgICAgICAgICAgICAgIHZhciBwYXJlbnROb2RlID0gZG9tTm9kZS5wYXJlbnROb2RlO1xuICAgICAgICAgICAgICAgIHZhciBuZXdOb2RlID0gcmVuZGVyT3B0aW9ucy5yZW5kZXIodk5vZGUsIHJlbmRlck9wdGlvbnMpO1xuXG4gICAgICAgICAgICAgICAgaWYgKHBhcmVudE5vZGUgJiYgbmV3Tm9kZSAhPT0gZG9tTm9kZSkge1xuICAgICAgICAgICAgICAgICAgICBwYXJlbnROb2RlLnJlcGxhY2VDaGlsZChuZXdOb2RlLCBkb21Ob2RlKTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICByZXR1cm4gbmV3Tm9kZTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZnVuY3Rpb24gZGVzdHJveVdpZGdldChkb21Ob2RlLCB3KSB7XG4gICAgICAgICAgICAgICAgaWYgKHR5cGVvZiB3LmRlc3Ryb3kgPT09IFwiZnVuY3Rpb25cIiAmJiBpc1dpZGdldCh3KSkge1xuICAgICAgICAgICAgICAgICAgICB3LmRlc3Ryb3koZG9tTm9kZSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBmdW5jdGlvbiByZW9yZGVyQ2hpbGRyZW4oZG9tTm9kZSwgbW92ZXMpIHtcbiAgICAgICAgICAgICAgICB2YXIgY2hpbGROb2RlcyA9IGRvbU5vZGUuY2hpbGROb2RlcztcbiAgICAgICAgICAgICAgICB2YXIga2V5TWFwID0ge307XG4gICAgICAgICAgICAgICAgdmFyIG5vZGU7XG4gICAgICAgICAgICAgICAgdmFyIHJlbW92ZTtcbiAgICAgICAgICAgICAgICB2YXIgaW5zZXJ0O1xuXG4gICAgICAgICAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCBtb3Zlcy5yZW1vdmVzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICAgICAgICAgIHJlbW92ZSA9IG1vdmVzLnJlbW92ZXNbaV07XG4gICAgICAgICAgICAgICAgICAgIG5vZGUgPSBjaGlsZE5vZGVzW3JlbW92ZS5mcm9tXTtcbiAgICAgICAgICAgICAgICAgICAgaWYgKHJlbW92ZS5rZXkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGtleU1hcFtyZW1vdmUua2V5XSA9IG5vZGU7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgZG9tTm9kZS5yZW1vdmVDaGlsZChub2RlKTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICB2YXIgbGVuZ3RoID0gY2hpbGROb2Rlcy5sZW5ndGg7XG4gICAgICAgICAgICAgICAgZm9yICh2YXIgaiA9IDA7IGogPCBtb3Zlcy5pbnNlcnRzLmxlbmd0aDsgaisrKSB7XG4gICAgICAgICAgICAgICAgICAgIGluc2VydCA9IG1vdmVzLmluc2VydHNbal07XG4gICAgICAgICAgICAgICAgICAgIG5vZGUgPSBrZXlNYXBbaW5zZXJ0LmtleV07XG4gICAgICAgICAgICAgICAgICAgIC8vIHRoaXMgaXMgdGhlIHdlaXJkZXN0IGJ1ZyBpJ3ZlIGV2ZXIgc2VlbiBpbiB3ZWJraXRcbiAgICAgICAgICAgICAgICAgICAgZG9tTm9kZS5pbnNlcnRCZWZvcmUobm9kZSwgaW5zZXJ0LnRvID49IGxlbmd0aCsrID8gbnVsbCA6IGNoaWxkTm9kZXNbaW5zZXJ0LnRvXSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBmdW5jdGlvbiByZXBsYWNlUm9vdChvbGRSb290LCBuZXdSb290KSB7XG4gICAgICAgICAgICAgICAgaWYgKG9sZFJvb3QgJiYgbmV3Um9vdCAmJiBvbGRSb290ICE9PSBuZXdSb290ICYmIG9sZFJvb3QucGFyZW50Tm9kZSkge1xuICAgICAgICAgICAgICAgICAgICBvbGRSb290LnBhcmVudE5vZGUucmVwbGFjZUNoaWxkKG5ld1Jvb3QsIG9sZFJvb3QpO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHJldHVybiBuZXdSb290O1xuICAgICAgICAgICAgfVxuICAgICAgICB9LCB7IFwiLi4vdm5vZGUvaXMtd2lkZ2V0LmpzXCI6IDI5LCBcIi4uL3Zub2RlL3ZwYXRjaC5qc1wiOiAzMiwgXCIuL2FwcGx5LXByb3BlcnRpZXNcIjogMTQsIFwiLi91cGRhdGUtd2lkZ2V0XCI6IDE5IH1dLCAxODogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHtcbiAgICAgICAgICAgIHZhciBkb2N1bWVudCA9IHJlcXVpcmUoXCJnbG9iYWwvZG9jdW1lbnRcIik7XG4gICAgICAgICAgICB2YXIgaXNBcnJheSA9IHJlcXVpcmUoXCJ4LWlzLWFycmF5XCIpO1xuXG4gICAgICAgICAgICB2YXIgcmVuZGVyID0gcmVxdWlyZShcIi4vY3JlYXRlLWVsZW1lbnRcIik7XG4gICAgICAgICAgICB2YXIgZG9tSW5kZXggPSByZXF1aXJlKFwiLi9kb20taW5kZXhcIik7XG4gICAgICAgICAgICB2YXIgcGF0Y2hPcCA9IHJlcXVpcmUoXCIuL3BhdGNoLW9wXCIpO1xuICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBwYXRjaDtcblxuICAgICAgICAgICAgZnVuY3Rpb24gcGF0Y2gocm9vdE5vZGUsIHBhdGNoZXMsIHJlbmRlck9wdGlvbnMpIHtcbiAgICAgICAgICAgICAgICByZW5kZXJPcHRpb25zID0gcmVuZGVyT3B0aW9ucyB8fCB7fTtcbiAgICAgICAgICAgICAgICByZW5kZXJPcHRpb25zLnBhdGNoID0gcmVuZGVyT3B0aW9ucy5wYXRjaCAmJiByZW5kZXJPcHRpb25zLnBhdGNoICE9PSBwYXRjaCA/IHJlbmRlck9wdGlvbnMucGF0Y2ggOiBwYXRjaFJlY3Vyc2l2ZTtcbiAgICAgICAgICAgICAgICByZW5kZXJPcHRpb25zLnJlbmRlciA9IHJlbmRlck9wdGlvbnMucmVuZGVyIHx8IHJlbmRlcjtcblxuICAgICAgICAgICAgICAgIHJldHVybiByZW5kZXJPcHRpb25zLnBhdGNoKHJvb3ROb2RlLCBwYXRjaGVzLCByZW5kZXJPcHRpb25zKTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZnVuY3Rpb24gcGF0Y2hSZWN1cnNpdmUocm9vdE5vZGUsIHBhdGNoZXMsIHJlbmRlck9wdGlvbnMpIHtcbiAgICAgICAgICAgICAgICB2YXIgaW5kaWNlcyA9IHBhdGNoSW5kaWNlcyhwYXRjaGVzKTtcblxuICAgICAgICAgICAgICAgIGlmIChpbmRpY2VzLmxlbmd0aCA9PT0gMCkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gcm9vdE5vZGU7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgdmFyIGluZGV4ID0gZG9tSW5kZXgocm9vdE5vZGUsIHBhdGNoZXMuYSwgaW5kaWNlcyk7XG4gICAgICAgICAgICAgICAgdmFyIG93bmVyRG9jdW1lbnQgPSByb290Tm9kZS5vd25lckRvY3VtZW50O1xuXG4gICAgICAgICAgICAgICAgaWYgKCFyZW5kZXJPcHRpb25zLmRvY3VtZW50ICYmIG93bmVyRG9jdW1lbnQgIT09IGRvY3VtZW50KSB7XG4gICAgICAgICAgICAgICAgICAgIHJlbmRlck9wdGlvbnMuZG9jdW1lbnQgPSBvd25lckRvY3VtZW50O1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgaW5kaWNlcy5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgICAgICAgICB2YXIgbm9kZUluZGV4ID0gaW5kaWNlc1tpXTtcbiAgICAgICAgICAgICAgICAgICAgcm9vdE5vZGUgPSBhcHBseVBhdGNoKHJvb3ROb2RlLCBpbmRleFtub2RlSW5kZXhdLCBwYXRjaGVzW25vZGVJbmRleF0sIHJlbmRlck9wdGlvbnMpO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHJldHVybiByb290Tm9kZTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZnVuY3Rpb24gYXBwbHlQYXRjaChyb290Tm9kZSwgZG9tTm9kZSwgcGF0Y2hMaXN0LCByZW5kZXJPcHRpb25zKSB7XG4gICAgICAgICAgICAgICAgaWYgKCFkb21Ob2RlKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiByb290Tm9kZTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICB2YXIgbmV3Tm9kZTtcblxuICAgICAgICAgICAgICAgIGlmIChpc0FycmF5KHBhdGNoTGlzdCkpIHtcbiAgICAgICAgICAgICAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCBwYXRjaExpc3QubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIG5ld05vZGUgPSBwYXRjaE9wKHBhdGNoTGlzdFtpXSwgZG9tTm9kZSwgcmVuZGVyT3B0aW9ucyk7XG5cbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChkb21Ob2RlID09PSByb290Tm9kZSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJvb3ROb2RlID0gbmV3Tm9kZTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIG5ld05vZGUgPSBwYXRjaE9wKHBhdGNoTGlzdCwgZG9tTm9kZSwgcmVuZGVyT3B0aW9ucyk7XG5cbiAgICAgICAgICAgICAgICAgICAgaWYgKGRvbU5vZGUgPT09IHJvb3ROb2RlKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICByb290Tm9kZSA9IG5ld05vZGU7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICByZXR1cm4gcm9vdE5vZGU7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIHBhdGNoSW5kaWNlcyhwYXRjaGVzKSB7XG4gICAgICAgICAgICAgICAgdmFyIGluZGljZXMgPSBbXTtcblxuICAgICAgICAgICAgICAgIGZvciAodmFyIGtleSBpbiBwYXRjaGVzKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmIChrZXkgIT09IFwiYVwiKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBpbmRpY2VzLnB1c2goTnVtYmVyKGtleSkpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgcmV0dXJuIGluZGljZXM7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0sIHsgXCIuL2NyZWF0ZS1lbGVtZW50XCI6IDE1LCBcIi4vZG9tLWluZGV4XCI6IDE2LCBcIi4vcGF0Y2gtb3BcIjogMTcsIFwiZ2xvYmFsL2RvY3VtZW50XCI6IDEwLCBcIngtaXMtYXJyYXlcIjogMTIgfV0sIDE5OiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge1xuICAgICAgICAgICAgdmFyIGlzV2lkZ2V0ID0gcmVxdWlyZShcIi4uL3Zub2RlL2lzLXdpZGdldC5qc1wiKTtcblxuICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSB1cGRhdGVXaWRnZXQ7XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIHVwZGF0ZVdpZGdldChhLCBiKSB7XG4gICAgICAgICAgICAgICAgaWYgKGlzV2lkZ2V0KGEpICYmIGlzV2lkZ2V0KGIpKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmIChcIm5hbWVcIiBpbiBhICYmIFwibmFtZVwiIGluIGIpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBhLmlkID09PSBiLmlkO1xuICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGEuaW5pdCA9PT0gYi5pbml0O1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICAgICAgfVxuICAgICAgICB9LCB7IFwiLi4vdm5vZGUvaXMtd2lkZ2V0LmpzXCI6IDI5IH1dLCAyMDogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHtcbiAgICAgICAgICAgIFwidXNlIHN0cmljdFwiO1xuXG4gICAgICAgICAgICB2YXIgRXZTdG9yZSA9IHJlcXVpcmUoXCJldi1zdG9yZVwiKTtcblxuICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBFdkhvb2s7XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIEV2SG9vayh2YWx1ZSkge1xuICAgICAgICAgICAgICAgIGlmICghKHRoaXMgaW5zdGFuY2VvZiBFdkhvb2spKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBuZXcgRXZIb29rKHZhbHVlKTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICB0aGlzLnZhbHVlID0gdmFsdWU7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIEV2SG9vay5wcm90b3R5cGUuaG9vayA9IGZ1bmN0aW9uIChub2RlLCBwcm9wZXJ0eU5hbWUpIHtcbiAgICAgICAgICAgICAgICB2YXIgZXMgPSBFdlN0b3JlKG5vZGUpO1xuICAgICAgICAgICAgICAgIHZhciBwcm9wTmFtZSA9IHByb3BlcnR5TmFtZS5zdWJzdHIoMyk7XG5cbiAgICAgICAgICAgICAgICBlc1twcm9wTmFtZV0gPSB0aGlzLnZhbHVlO1xuICAgICAgICAgICAgfTtcblxuICAgICAgICAgICAgRXZIb29rLnByb3RvdHlwZS51bmhvb2sgPSBmdW5jdGlvbiAobm9kZSwgcHJvcGVydHlOYW1lKSB7XG4gICAgICAgICAgICAgICAgdmFyIGVzID0gRXZTdG9yZShub2RlKTtcbiAgICAgICAgICAgICAgICB2YXIgcHJvcE5hbWUgPSBwcm9wZXJ0eU5hbWUuc3Vic3RyKDMpO1xuXG4gICAgICAgICAgICAgICAgZXNbcHJvcE5hbWVdID0gdW5kZWZpbmVkO1xuICAgICAgICAgICAgfTtcbiAgICAgICAgfSwgeyBcImV2LXN0b3JlXCI6IDcgfV0sIDIxOiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge1xuICAgICAgICAgICAgXCJ1c2Ugc3RyaWN0XCI7XG5cbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gU29mdFNldEhvb2s7XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIFNvZnRTZXRIb29rKHZhbHVlKSB7XG4gICAgICAgICAgICAgICAgaWYgKCEodGhpcyBpbnN0YW5jZW9mIFNvZnRTZXRIb29rKSkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gbmV3IFNvZnRTZXRIb29rKHZhbHVlKTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICB0aGlzLnZhbHVlID0gdmFsdWU7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIFNvZnRTZXRIb29rLnByb3RvdHlwZS5ob29rID0gZnVuY3Rpb24gKG5vZGUsIHByb3BlcnR5TmFtZSkge1xuICAgICAgICAgICAgICAgIGlmIChub2RlW3Byb3BlcnR5TmFtZV0gIT09IHRoaXMudmFsdWUpIHtcbiAgICAgICAgICAgICAgICAgICAgbm9kZVtwcm9wZXJ0eU5hbWVdID0gdGhpcy52YWx1ZTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9O1xuICAgICAgICB9LCB7fV0sIDIyOiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge1xuICAgICAgICAgICAgXCJ1c2Ugc3RyaWN0XCI7XG5cbiAgICAgICAgICAgIHZhciBpc0FycmF5ID0gcmVxdWlyZShcIngtaXMtYXJyYXlcIik7XG5cbiAgICAgICAgICAgIHZhciBWTm9kZSA9IHJlcXVpcmUoXCIuLi92bm9kZS92bm9kZS5qc1wiKTtcbiAgICAgICAgICAgIHZhciBWVGV4dCA9IHJlcXVpcmUoXCIuLi92bm9kZS92dGV4dC5qc1wiKTtcbiAgICAgICAgICAgIHZhciBpc1ZOb2RlID0gcmVxdWlyZShcIi4uL3Zub2RlL2lzLXZub2RlXCIpO1xuICAgICAgICAgICAgdmFyIGlzVlRleHQgPSByZXF1aXJlKFwiLi4vdm5vZGUvaXMtdnRleHRcIik7XG4gICAgICAgICAgICB2YXIgaXNXaWRnZXQgPSByZXF1aXJlKFwiLi4vdm5vZGUvaXMtd2lkZ2V0XCIpO1xuICAgICAgICAgICAgdmFyIGlzSG9vayA9IHJlcXVpcmUoXCIuLi92bm9kZS9pcy12aG9va1wiKTtcbiAgICAgICAgICAgIHZhciBpc1ZUaHVuayA9IHJlcXVpcmUoXCIuLi92bm9kZS9pcy10aHVua1wiKTtcblxuICAgICAgICAgICAgdmFyIHBhcnNlVGFnID0gcmVxdWlyZShcIi4vcGFyc2UtdGFnLmpzXCIpO1xuICAgICAgICAgICAgdmFyIHNvZnRTZXRIb29rID0gcmVxdWlyZShcIi4vaG9va3Mvc29mdC1zZXQtaG9vay5qc1wiKTtcbiAgICAgICAgICAgIHZhciBldkhvb2sgPSByZXF1aXJlKFwiLi9ob29rcy9ldi1ob29rLmpzXCIpO1xuXG4gICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IGg7XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIGgodGFnTmFtZSwgcHJvcGVydGllcywgY2hpbGRyZW4pIHtcbiAgICAgICAgICAgICAgICB2YXIgY2hpbGROb2RlcyA9IFtdO1xuICAgICAgICAgICAgICAgIHZhciB0YWcsIHByb3BzLCBrZXksIG5hbWVzcGFjZTtcblxuICAgICAgICAgICAgICAgIGlmICghY2hpbGRyZW4gJiYgaXNDaGlsZHJlbihwcm9wZXJ0aWVzKSkge1xuICAgICAgICAgICAgICAgICAgICBjaGlsZHJlbiA9IHByb3BlcnRpZXM7XG4gICAgICAgICAgICAgICAgICAgIHByb3BzID0ge307XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgcHJvcHMgPSBwcm9wcyB8fCBwcm9wZXJ0aWVzIHx8IHt9O1xuICAgICAgICAgICAgICAgIHRhZyA9IHBhcnNlVGFnKHRhZ05hbWUsIHByb3BzKTtcblxuICAgICAgICAgICAgICAgIC8vIHN1cHBvcnQga2V5c1xuICAgICAgICAgICAgICAgIGlmIChwcm9wcy5oYXNPd25Qcm9wZXJ0eShcImtleVwiKSkge1xuICAgICAgICAgICAgICAgICAgICBrZXkgPSBwcm9wcy5rZXk7XG4gICAgICAgICAgICAgICAgICAgIHByb3BzLmtleSA9IHVuZGVmaW5lZDtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAvLyBzdXBwb3J0IG5hbWVzcGFjZVxuICAgICAgICAgICAgICAgIGlmIChwcm9wcy5oYXNPd25Qcm9wZXJ0eShcIm5hbWVzcGFjZVwiKSkge1xuICAgICAgICAgICAgICAgICAgICBuYW1lc3BhY2UgPSBwcm9wcy5uYW1lc3BhY2U7XG4gICAgICAgICAgICAgICAgICAgIHByb3BzLm5hbWVzcGFjZSA9IHVuZGVmaW5lZDtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAvLyBmaXggY3Vyc29yIGJ1Z1xuICAgICAgICAgICAgICAgIGlmICh0YWcgPT09IFwiSU5QVVRcIiAmJiAhbmFtZXNwYWNlICYmIHByb3BzLmhhc093blByb3BlcnR5KFwidmFsdWVcIikgJiYgcHJvcHMudmFsdWUgIT09IHVuZGVmaW5lZCAmJiAhaXNIb29rKHByb3BzLnZhbHVlKSkge1xuICAgICAgICAgICAgICAgICAgICBwcm9wcy52YWx1ZSA9IHNvZnRTZXRIb29rKHByb3BzLnZhbHVlKTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICB0cmFuc2Zvcm1Qcm9wZXJ0aWVzKHByb3BzKTtcblxuICAgICAgICAgICAgICAgIGlmIChjaGlsZHJlbiAhPT0gdW5kZWZpbmVkICYmIGNoaWxkcmVuICE9PSBudWxsKSB7XG4gICAgICAgICAgICAgICAgICAgIGFkZENoaWxkKGNoaWxkcmVuLCBjaGlsZE5vZGVzLCB0YWcsIHByb3BzKTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICByZXR1cm4gbmV3IFZOb2RlKHRhZywgcHJvcHMsIGNoaWxkTm9kZXMsIGtleSwgbmFtZXNwYWNlKTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZnVuY3Rpb24gYWRkQ2hpbGQoYywgY2hpbGROb2RlcywgdGFnLCBwcm9wcykge1xuICAgICAgICAgICAgICAgIGlmICh0eXBlb2YgYyA9PT0gXCJzdHJpbmdcIikge1xuICAgICAgICAgICAgICAgICAgICBjaGlsZE5vZGVzLnB1c2gobmV3IFZUZXh0KGMpKTtcbiAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKHR5cGVvZiBjID09PSBcIm51bWJlclwiKSB7XG4gICAgICAgICAgICAgICAgICAgIGNoaWxkTm9kZXMucHVzaChuZXcgVlRleHQoU3RyaW5nKGMpKSk7XG4gICAgICAgICAgICAgICAgfSBlbHNlIGlmIChpc0NoaWxkKGMpKSB7XG4gICAgICAgICAgICAgICAgICAgIGNoaWxkTm9kZXMucHVzaChjKTtcbiAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKGlzQXJyYXkoYykpIHtcbiAgICAgICAgICAgICAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCBjLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBhZGRDaGlsZChjW2ldLCBjaGlsZE5vZGVzLCB0YWcsIHByb3BzKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoYyA9PT0gbnVsbCB8fCBjID09PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIHRocm93IFVuZXhwZWN0ZWRWaXJ0dWFsRWxlbWVudCh7XG4gICAgICAgICAgICAgICAgICAgICAgICBmb3JlaWduT2JqZWN0OiBjLFxuICAgICAgICAgICAgICAgICAgICAgICAgcGFyZW50Vm5vZGU6IHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0YWdOYW1lOiB0YWcsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcHJvcGVydGllczogcHJvcHNcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBmdW5jdGlvbiB0cmFuc2Zvcm1Qcm9wZXJ0aWVzKHByb3BzKSB7XG4gICAgICAgICAgICAgICAgZm9yICh2YXIgcHJvcE5hbWUgaW4gcHJvcHMpIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKHByb3BzLmhhc093blByb3BlcnR5KHByb3BOYW1lKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgdmFyIHZhbHVlID0gcHJvcHNbcHJvcE5hbWVdO1xuXG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoaXNIb29rKHZhbHVlKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnRpbnVlO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAocHJvcE5hbWUuc3Vic3RyKDAsIDMpID09PSBcImV2LVwiKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gYWRkIGV2LWZvbyBzdXBwb3J0XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcHJvcHNbcHJvcE5hbWVdID0gZXZIb29rKHZhbHVlKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZnVuY3Rpb24gaXNDaGlsZCh4KSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGlzVk5vZGUoeCkgfHwgaXNWVGV4dCh4KSB8fCBpc1dpZGdldCh4KSB8fCBpc1ZUaHVuayh4KTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZnVuY3Rpb24gaXNDaGlsZHJlbih4KSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHR5cGVvZiB4ID09PSBcInN0cmluZ1wiIHx8IGlzQXJyYXkoeCkgfHwgaXNDaGlsZCh4KTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZnVuY3Rpb24gVW5leHBlY3RlZFZpcnR1YWxFbGVtZW50KGRhdGEpIHtcbiAgICAgICAgICAgICAgICB2YXIgZXJyID0gbmV3IEVycm9yKCk7XG5cbiAgICAgICAgICAgICAgICBlcnIudHlwZSA9IFwidmlydHVhbC1oeXBlcnNjcmlwdC51bmV4cGVjdGVkLnZpcnR1YWwtZWxlbWVudFwiO1xuICAgICAgICAgICAgICAgIGVyci5tZXNzYWdlID0gXCJVbmV4cGVjdGVkIHZpcnR1YWwgY2hpbGQgcGFzc2VkIHRvIGgoKS5cXG5cIiArIFwiRXhwZWN0ZWQgYSBWTm9kZSAvIFZ0aHVuayAvIFZXaWRnZXQgLyBzdHJpbmcgYnV0OlxcblwiICsgXCJnb3Q6XFxuXCIgKyBlcnJvclN0cmluZyhkYXRhLmZvcmVpZ25PYmplY3QpICsgXCIuXFxuXCIgKyBcIlRoZSBwYXJlbnQgdm5vZGUgaXM6XFxuXCIgKyBlcnJvclN0cmluZyhkYXRhLnBhcmVudFZub2RlKTtcbiAgICAgICAgICAgICAgICBcIlxcblwiICsgXCJTdWdnZXN0ZWQgZml4OiBjaGFuZ2UgeW91ciBgaCguLi4sIFsgLi4uIF0pYCBjYWxsc2l0ZS5cIjtcbiAgICAgICAgICAgICAgICBlcnIuZm9yZWlnbk9iamVjdCA9IGRhdGEuZm9yZWlnbk9iamVjdDtcbiAgICAgICAgICAgICAgICBlcnIucGFyZW50Vm5vZGUgPSBkYXRhLnBhcmVudFZub2RlO1xuXG4gICAgICAgICAgICAgICAgcmV0dXJuIGVycjtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZnVuY3Rpb24gZXJyb3JTdHJpbmcob2JqKSB7XG4gICAgICAgICAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIEpTT04uc3RyaW5naWZ5KG9iaiwgbnVsbCwgXCIgICAgXCIpO1xuICAgICAgICAgICAgICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIFN0cmluZyhvYmopO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgfSwgeyBcIi4uL3Zub2RlL2lzLXRodW5rXCI6IDI1LCBcIi4uL3Zub2RlL2lzLXZob29rXCI6IDI2LCBcIi4uL3Zub2RlL2lzLXZub2RlXCI6IDI3LCBcIi4uL3Zub2RlL2lzLXZ0ZXh0XCI6IDI4LCBcIi4uL3Zub2RlL2lzLXdpZGdldFwiOiAyOSwgXCIuLi92bm9kZS92bm9kZS5qc1wiOiAzMSwgXCIuLi92bm9kZS92dGV4dC5qc1wiOiAzMywgXCIuL2hvb2tzL2V2LWhvb2suanNcIjogMjAsIFwiLi9ob29rcy9zb2Z0LXNldC1ob29rLmpzXCI6IDIxLCBcIi4vcGFyc2UtdGFnLmpzXCI6IDIzLCBcIngtaXMtYXJyYXlcIjogMTIgfV0sIDIzOiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge1xuICAgICAgICAgICAgXCJ1c2Ugc3RyaWN0XCI7XG5cbiAgICAgICAgICAgIHZhciBzcGxpdCA9IHJlcXVpcmUoXCJicm93c2VyLXNwbGl0XCIpO1xuXG4gICAgICAgICAgICB2YXIgY2xhc3NJZFNwbGl0ID0gLyhbXFwuI10/W2EtekEtWjAtOVxcdTAwN0YtXFx1RkZGRl86LV0rKS87XG4gICAgICAgICAgICB2YXIgbm90Q2xhc3NJZCA9IC9eXFwufCMvO1xuXG4gICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IHBhcnNlVGFnO1xuXG4gICAgICAgICAgICBmdW5jdGlvbiBwYXJzZVRhZyh0YWcsIHByb3BzKSB7XG4gICAgICAgICAgICAgICAgaWYgKCF0YWcpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIFwiRElWXCI7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgdmFyIG5vSWQgPSAhcHJvcHMuaGFzT3duUHJvcGVydHkoXCJpZFwiKTtcblxuICAgICAgICAgICAgICAgIHZhciB0YWdQYXJ0cyA9IHNwbGl0KHRhZywgY2xhc3NJZFNwbGl0KTtcbiAgICAgICAgICAgICAgICB2YXIgdGFnTmFtZSA9IG51bGw7XG5cbiAgICAgICAgICAgICAgICBpZiAobm90Q2xhc3NJZC50ZXN0KHRhZ1BhcnRzWzFdKSkge1xuICAgICAgICAgICAgICAgICAgICB0YWdOYW1lID0gXCJESVZcIjtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICB2YXIgY2xhc3NlcywgcGFydCwgdHlwZSwgaTtcblxuICAgICAgICAgICAgICAgIGZvciAoaSA9IDA7IGkgPCB0YWdQYXJ0cy5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgICAgICAgICBwYXJ0ID0gdGFnUGFydHNbaV07XG5cbiAgICAgICAgICAgICAgICAgICAgaWYgKCFwYXJ0KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBjb250aW51ZTtcbiAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgIHR5cGUgPSBwYXJ0LmNoYXJBdCgwKTtcblxuICAgICAgICAgICAgICAgICAgICBpZiAoIXRhZ05hbWUpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHRhZ05hbWUgPSBwYXJ0O1xuICAgICAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKHR5cGUgPT09IFwiLlwiKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBjbGFzc2VzID0gY2xhc3NlcyB8fCBbXTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGNsYXNzZXMucHVzaChwYXJ0LnN1YnN0cmluZygxLCBwYXJ0Lmxlbmd0aCkpO1xuICAgICAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKHR5cGUgPT09IFwiI1wiICYmIG5vSWQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHByb3BzLmlkID0gcGFydC5zdWJzdHJpbmcoMSwgcGFydC5sZW5ndGgpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgaWYgKGNsYXNzZXMpIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKHByb3BzLmNsYXNzTmFtZSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgY2xhc3Nlcy5wdXNoKHByb3BzLmNsYXNzTmFtZSk7XG4gICAgICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgICAgICBwcm9wcy5jbGFzc05hbWUgPSBjbGFzc2VzLmpvaW4oXCIgXCIpO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHJldHVybiBwcm9wcy5uYW1lc3BhY2UgPyB0YWdOYW1lIDogdGFnTmFtZS50b1VwcGVyQ2FzZSgpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9LCB7IFwiYnJvd3Nlci1zcGxpdFwiOiA1IH1dLCAyNDogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHtcbiAgICAgICAgICAgIHZhciBpc1ZOb2RlID0gcmVxdWlyZShcIi4vaXMtdm5vZGVcIik7XG4gICAgICAgICAgICB2YXIgaXNWVGV4dCA9IHJlcXVpcmUoXCIuL2lzLXZ0ZXh0XCIpO1xuICAgICAgICAgICAgdmFyIGlzV2lkZ2V0ID0gcmVxdWlyZShcIi4vaXMtd2lkZ2V0XCIpO1xuICAgICAgICAgICAgdmFyIGlzVGh1bmsgPSByZXF1aXJlKFwiLi9pcy10aHVua1wiKTtcblxuICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBoYW5kbGVUaHVuaztcblxuICAgICAgICAgICAgZnVuY3Rpb24gaGFuZGxlVGh1bmsoYSwgYikge1xuICAgICAgICAgICAgICAgIHZhciByZW5kZXJlZEEgPSBhO1xuICAgICAgICAgICAgICAgIHZhciByZW5kZXJlZEIgPSBiO1xuXG4gICAgICAgICAgICAgICAgaWYgKGlzVGh1bmsoYikpIHtcbiAgICAgICAgICAgICAgICAgICAgcmVuZGVyZWRCID0gcmVuZGVyVGh1bmsoYiwgYSk7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgaWYgKGlzVGh1bmsoYSkpIHtcbiAgICAgICAgICAgICAgICAgICAgcmVuZGVyZWRBID0gcmVuZGVyVGh1bmsoYSwgbnVsbCk7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgICAgICAgICAgYTogcmVuZGVyZWRBLFxuICAgICAgICAgICAgICAgICAgICBiOiByZW5kZXJlZEJcbiAgICAgICAgICAgICAgICB9O1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBmdW5jdGlvbiByZW5kZXJUaHVuayh0aHVuaywgcHJldmlvdXMpIHtcbiAgICAgICAgICAgICAgICB2YXIgcmVuZGVyZWRUaHVuayA9IHRodW5rLnZub2RlO1xuXG4gICAgICAgICAgICAgICAgaWYgKCFyZW5kZXJlZFRodW5rKSB7XG4gICAgICAgICAgICAgICAgICAgIHJlbmRlcmVkVGh1bmsgPSB0aHVuay52bm9kZSA9IHRodW5rLnJlbmRlcihwcmV2aW91cyk7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgaWYgKCEoaXNWTm9kZShyZW5kZXJlZFRodW5rKSB8fCBpc1ZUZXh0KHJlbmRlcmVkVGh1bmspIHx8IGlzV2lkZ2V0KHJlbmRlcmVkVGh1bmspKSkge1xuICAgICAgICAgICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoXCJ0aHVuayBkaWQgbm90IHJldHVybiBhIHZhbGlkIG5vZGVcIik7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgcmV0dXJuIHJlbmRlcmVkVGh1bms7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0sIHsgXCIuL2lzLXRodW5rXCI6IDI1LCBcIi4vaXMtdm5vZGVcIjogMjcsIFwiLi9pcy12dGV4dFwiOiAyOCwgXCIuL2lzLXdpZGdldFwiOiAyOSB9XSwgMjU6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IGlzVGh1bms7XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIGlzVGh1bmsodCkge1xuICAgICAgICAgICAgICAgIHJldHVybiB0ICYmIHQudHlwZSA9PT0gXCJUaHVua1wiO1xuICAgICAgICAgICAgfVxuICAgICAgICB9LCB7fV0sIDI2OiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge1xuICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBpc0hvb2s7XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIGlzSG9vayhob29rKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGhvb2sgJiYgKHR5cGVvZiBob29rLmhvb2sgPT09IFwiZnVuY3Rpb25cIiAmJiAhaG9vay5oYXNPd25Qcm9wZXJ0eShcImhvb2tcIikgfHwgdHlwZW9mIGhvb2sudW5ob29rID09PSBcImZ1bmN0aW9uXCIgJiYgIWhvb2suaGFzT3duUHJvcGVydHkoXCJ1bmhvb2tcIikpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9LCB7fV0sIDI3OiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge1xuICAgICAgICAgICAgdmFyIHZlcnNpb24gPSByZXF1aXJlKFwiLi92ZXJzaW9uXCIpO1xuXG4gICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IGlzVmlydHVhbE5vZGU7XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIGlzVmlydHVhbE5vZGUoeCkge1xuICAgICAgICAgICAgICAgIHJldHVybiB4ICYmIHgudHlwZSA9PT0gXCJWaXJ0dWFsTm9kZVwiICYmIHgudmVyc2lvbiA9PT0gdmVyc2lvbjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSwgeyBcIi4vdmVyc2lvblwiOiAzMCB9XSwgMjg6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICB2YXIgdmVyc2lvbiA9IHJlcXVpcmUoXCIuL3ZlcnNpb25cIik7XG5cbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gaXNWaXJ0dWFsVGV4dDtcblxuICAgICAgICAgICAgZnVuY3Rpb24gaXNWaXJ0dWFsVGV4dCh4KSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHggJiYgeC50eXBlID09PSBcIlZpcnR1YWxUZXh0XCIgJiYgeC52ZXJzaW9uID09PSB2ZXJzaW9uO1xuICAgICAgICAgICAgfVxuICAgICAgICB9LCB7IFwiLi92ZXJzaW9uXCI6IDMwIH1dLCAyOTogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHtcbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gaXNXaWRnZXQ7XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIGlzV2lkZ2V0KHcpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gdyAmJiB3LnR5cGUgPT09IFwiV2lkZ2V0XCI7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0sIHt9XSwgMzA6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IFwiMlwiO1xuICAgICAgICB9LCB7fV0sIDMxOiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge1xuICAgICAgICAgICAgdmFyIHZlcnNpb24gPSByZXF1aXJlKFwiLi92ZXJzaW9uXCIpO1xuICAgICAgICAgICAgdmFyIGlzVk5vZGUgPSByZXF1aXJlKFwiLi9pcy12bm9kZVwiKTtcbiAgICAgICAgICAgIHZhciBpc1dpZGdldCA9IHJlcXVpcmUoXCIuL2lzLXdpZGdldFwiKTtcbiAgICAgICAgICAgIHZhciBpc1RodW5rID0gcmVxdWlyZShcIi4vaXMtdGh1bmtcIik7XG4gICAgICAgICAgICB2YXIgaXNWSG9vayA9IHJlcXVpcmUoXCIuL2lzLXZob29rXCIpO1xuXG4gICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IFZpcnR1YWxOb2RlO1xuXG4gICAgICAgICAgICB2YXIgbm9Qcm9wZXJ0aWVzID0ge307XG4gICAgICAgICAgICB2YXIgbm9DaGlsZHJlbiA9IFtdO1xuXG4gICAgICAgICAgICBmdW5jdGlvbiBWaXJ0dWFsTm9kZSh0YWdOYW1lLCBwcm9wZXJ0aWVzLCBjaGlsZHJlbiwga2V5LCBuYW1lc3BhY2UpIHtcbiAgICAgICAgICAgICAgICB0aGlzLnRhZ05hbWUgPSB0YWdOYW1lO1xuICAgICAgICAgICAgICAgIHRoaXMucHJvcGVydGllcyA9IHByb3BlcnRpZXMgfHwgbm9Qcm9wZXJ0aWVzO1xuICAgICAgICAgICAgICAgIHRoaXMuY2hpbGRyZW4gPSBjaGlsZHJlbiB8fCBub0NoaWxkcmVuO1xuICAgICAgICAgICAgICAgIHRoaXMua2V5ID0ga2V5ICE9IG51bGwgPyBTdHJpbmcoa2V5KSA6IHVuZGVmaW5lZDtcbiAgICAgICAgICAgICAgICB0aGlzLm5hbWVzcGFjZSA9IHR5cGVvZiBuYW1lc3BhY2UgPT09IFwic3RyaW5nXCIgPyBuYW1lc3BhY2UgOiBudWxsO1xuXG4gICAgICAgICAgICAgICAgdmFyIGNvdW50ID0gY2hpbGRyZW4gJiYgY2hpbGRyZW4ubGVuZ3RoIHx8IDA7XG4gICAgICAgICAgICAgICAgdmFyIGRlc2NlbmRhbnRzID0gMDtcbiAgICAgICAgICAgICAgICB2YXIgaGFzV2lkZ2V0cyA9IGZhbHNlO1xuICAgICAgICAgICAgICAgIHZhciBoYXNUaHVua3MgPSBmYWxzZTtcbiAgICAgICAgICAgICAgICB2YXIgZGVzY2VuZGFudEhvb2tzID0gZmFsc2U7XG4gICAgICAgICAgICAgICAgdmFyIGhvb2tzO1xuXG4gICAgICAgICAgICAgICAgZm9yICh2YXIgcHJvcE5hbWUgaW4gcHJvcGVydGllcykge1xuICAgICAgICAgICAgICAgICAgICBpZiAocHJvcGVydGllcy5oYXNPd25Qcm9wZXJ0eShwcm9wTmFtZSkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHZhciBwcm9wZXJ0eSA9IHByb3BlcnRpZXNbcHJvcE5hbWVdO1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGlzVkhvb2socHJvcGVydHkpICYmIHByb3BlcnR5LnVuaG9vaykge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmICghaG9va3MpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaG9va3MgPSB7fTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBob29rc1twcm9wTmFtZV0gPSBwcm9wZXJ0eTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgY291bnQ7IGkrKykge1xuICAgICAgICAgICAgICAgICAgICB2YXIgY2hpbGQgPSBjaGlsZHJlbltpXTtcbiAgICAgICAgICAgICAgICAgICAgaWYgKGlzVk5vZGUoY2hpbGQpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBkZXNjZW5kYW50cyArPSBjaGlsZC5jb3VudCB8fCAwO1xuXG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoIWhhc1dpZGdldHMgJiYgY2hpbGQuaGFzV2lkZ2V0cykge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGhhc1dpZGdldHMgPSB0cnVlO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoIWhhc1RodW5rcyAmJiBjaGlsZC5oYXNUaHVua3MpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBoYXNUaHVua3MgPSB0cnVlO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoIWRlc2NlbmRhbnRIb29rcyAmJiAoY2hpbGQuaG9va3MgfHwgY2hpbGQuZGVzY2VuZGFudEhvb2tzKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRlc2NlbmRhbnRIb29rcyA9IHRydWU7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoIWhhc1dpZGdldHMgJiYgaXNXaWRnZXQoY2hpbGQpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAodHlwZW9mIGNoaWxkLmRlc3Ryb3kgPT09IFwiZnVuY3Rpb25cIikge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGhhc1dpZGdldHMgPSB0cnVlO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKCFoYXNUaHVua3MgJiYgaXNUaHVuayhjaGlsZCkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGhhc1RodW5rcyA9IHRydWU7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICB0aGlzLmNvdW50ID0gY291bnQgKyBkZXNjZW5kYW50cztcbiAgICAgICAgICAgICAgICB0aGlzLmhhc1dpZGdldHMgPSBoYXNXaWRnZXRzO1xuICAgICAgICAgICAgICAgIHRoaXMuaGFzVGh1bmtzID0gaGFzVGh1bmtzO1xuICAgICAgICAgICAgICAgIHRoaXMuaG9va3MgPSBob29rcztcbiAgICAgICAgICAgICAgICB0aGlzLmRlc2NlbmRhbnRIb29rcyA9IGRlc2NlbmRhbnRIb29rcztcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgVmlydHVhbE5vZGUucHJvdG90eXBlLnZlcnNpb24gPSB2ZXJzaW9uO1xuICAgICAgICAgICAgVmlydHVhbE5vZGUucHJvdG90eXBlLnR5cGUgPSBcIlZpcnR1YWxOb2RlXCI7XG4gICAgICAgIH0sIHsgXCIuL2lzLXRodW5rXCI6IDI1LCBcIi4vaXMtdmhvb2tcIjogMjYsIFwiLi9pcy12bm9kZVwiOiAyNywgXCIuL2lzLXdpZGdldFwiOiAyOSwgXCIuL3ZlcnNpb25cIjogMzAgfV0sIDMyOiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge1xuICAgICAgICAgICAgdmFyIHZlcnNpb24gPSByZXF1aXJlKFwiLi92ZXJzaW9uXCIpO1xuXG4gICAgICAgICAgICBWaXJ0dWFsUGF0Y2guTk9ORSA9IDA7XG4gICAgICAgICAgICBWaXJ0dWFsUGF0Y2guVlRFWFQgPSAxO1xuICAgICAgICAgICAgVmlydHVhbFBhdGNoLlZOT0RFID0gMjtcbiAgICAgICAgICAgIFZpcnR1YWxQYXRjaC5XSURHRVQgPSAzO1xuICAgICAgICAgICAgVmlydHVhbFBhdGNoLlBST1BTID0gNDtcbiAgICAgICAgICAgIFZpcnR1YWxQYXRjaC5PUkRFUiA9IDU7XG4gICAgICAgICAgICBWaXJ0dWFsUGF0Y2guSU5TRVJUID0gNjtcbiAgICAgICAgICAgIFZpcnR1YWxQYXRjaC5SRU1PVkUgPSA3O1xuICAgICAgICAgICAgVmlydHVhbFBhdGNoLlRIVU5LID0gODtcblxuICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBWaXJ0dWFsUGF0Y2g7XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIFZpcnR1YWxQYXRjaCh0eXBlLCB2Tm9kZSwgcGF0Y2gpIHtcbiAgICAgICAgICAgICAgICB0aGlzLnR5cGUgPSBOdW1iZXIodHlwZSk7XG4gICAgICAgICAgICAgICAgdGhpcy52Tm9kZSA9IHZOb2RlO1xuICAgICAgICAgICAgICAgIHRoaXMucGF0Y2ggPSBwYXRjaDtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgVmlydHVhbFBhdGNoLnByb3RvdHlwZS52ZXJzaW9uID0gdmVyc2lvbjtcbiAgICAgICAgICAgIFZpcnR1YWxQYXRjaC5wcm90b3R5cGUudHlwZSA9IFwiVmlydHVhbFBhdGNoXCI7XG4gICAgICAgIH0sIHsgXCIuL3ZlcnNpb25cIjogMzAgfV0sIDMzOiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge1xuICAgICAgICAgICAgdmFyIHZlcnNpb24gPSByZXF1aXJlKFwiLi92ZXJzaW9uXCIpO1xuXG4gICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IFZpcnR1YWxUZXh0O1xuXG4gICAgICAgICAgICBmdW5jdGlvbiBWaXJ0dWFsVGV4dCh0ZXh0KSB7XG4gICAgICAgICAgICAgICAgdGhpcy50ZXh0ID0gU3RyaW5nKHRleHQpO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBWaXJ0dWFsVGV4dC5wcm90b3R5cGUudmVyc2lvbiA9IHZlcnNpb247XG4gICAgICAgICAgICBWaXJ0dWFsVGV4dC5wcm90b3R5cGUudHlwZSA9IFwiVmlydHVhbFRleHRcIjtcbiAgICAgICAgfSwgeyBcIi4vdmVyc2lvblwiOiAzMCB9XSwgMzQ6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICB2YXIgaXNPYmplY3QgPSByZXF1aXJlKFwiaXMtb2JqZWN0XCIpO1xuICAgICAgICAgICAgdmFyIGlzSG9vayA9IHJlcXVpcmUoXCIuLi92bm9kZS9pcy12aG9va1wiKTtcblxuICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBkaWZmUHJvcHM7XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIGRpZmZQcm9wcyhhLCBiKSB7XG4gICAgICAgICAgICAgICAgdmFyIGRpZmY7XG5cbiAgICAgICAgICAgICAgICBmb3IgKHZhciBhS2V5IGluIGEpIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKCEoYUtleSBpbiBiKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgZGlmZiA9IGRpZmYgfHwge307XG4gICAgICAgICAgICAgICAgICAgICAgICBkaWZmW2FLZXldID0gdW5kZWZpbmVkO1xuICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgdmFyIGFWYWx1ZSA9IGFbYUtleV07XG4gICAgICAgICAgICAgICAgICAgIHZhciBiVmFsdWUgPSBiW2FLZXldO1xuXG4gICAgICAgICAgICAgICAgICAgIGlmIChhVmFsdWUgPT09IGJWYWx1ZSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgY29udGludWU7XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoaXNPYmplY3QoYVZhbHVlKSAmJiBpc09iamVjdChiVmFsdWUpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoZ2V0UHJvdG90eXBlKGJWYWx1ZSkgIT09IGdldFByb3RvdHlwZShhVmFsdWUpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgZGlmZiA9IGRpZmYgfHwge307XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgZGlmZlthS2V5XSA9IGJWYWx1ZTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoaXNIb29rKGJWYWx1ZSkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBkaWZmID0gZGlmZiB8fCB7fTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBkaWZmW2FLZXldID0gYlZhbHVlO1xuICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB2YXIgb2JqZWN0RGlmZiA9IGRpZmZQcm9wcyhhVmFsdWUsIGJWYWx1ZSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKG9iamVjdERpZmYpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZGlmZiA9IGRpZmYgfHwge307XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRpZmZbYUtleV0gPSBvYmplY3REaWZmO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGRpZmYgPSBkaWZmIHx8IHt9O1xuICAgICAgICAgICAgICAgICAgICAgICAgZGlmZlthS2V5XSA9IGJWYWx1ZTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIGZvciAodmFyIGJLZXkgaW4gYikge1xuICAgICAgICAgICAgICAgICAgICBpZiAoIShiS2V5IGluIGEpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBkaWZmID0gZGlmZiB8fCB7fTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGRpZmZbYktleV0gPSBiW2JLZXldO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgcmV0dXJuIGRpZmY7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIGdldFByb3RvdHlwZSh2YWx1ZSkge1xuICAgICAgICAgICAgICAgIGlmIChPYmplY3QuZ2V0UHJvdG90eXBlT2YpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIE9iamVjdC5nZXRQcm90b3R5cGVPZih2YWx1ZSk7XG4gICAgICAgICAgICAgICAgfSBlbHNlIGlmICh2YWx1ZS5fX3Byb3RvX18pIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHZhbHVlLl9fcHJvdG9fXztcbiAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKHZhbHVlLmNvbnN0cnVjdG9yKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiB2YWx1ZS5jb25zdHJ1Y3Rvci5wcm90b3R5cGU7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9LCB7IFwiLi4vdm5vZGUvaXMtdmhvb2tcIjogMjYsIFwiaXMtb2JqZWN0XCI6IDExIH1dLCAzNTogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHtcbiAgICAgICAgICAgIHZhciBpc0FycmF5ID0gcmVxdWlyZShcIngtaXMtYXJyYXlcIik7XG5cbiAgICAgICAgICAgIHZhciBWUGF0Y2ggPSByZXF1aXJlKFwiLi4vdm5vZGUvdnBhdGNoXCIpO1xuICAgICAgICAgICAgdmFyIGlzVk5vZGUgPSByZXF1aXJlKFwiLi4vdm5vZGUvaXMtdm5vZGVcIik7XG4gICAgICAgICAgICB2YXIgaXNWVGV4dCA9IHJlcXVpcmUoXCIuLi92bm9kZS9pcy12dGV4dFwiKTtcbiAgICAgICAgICAgIHZhciBpc1dpZGdldCA9IHJlcXVpcmUoXCIuLi92bm9kZS9pcy13aWRnZXRcIik7XG4gICAgICAgICAgICB2YXIgaXNUaHVuayA9IHJlcXVpcmUoXCIuLi92bm9kZS9pcy10aHVua1wiKTtcbiAgICAgICAgICAgIHZhciBoYW5kbGVUaHVuayA9IHJlcXVpcmUoXCIuLi92bm9kZS9oYW5kbGUtdGh1bmtcIik7XG5cbiAgICAgICAgICAgIHZhciBkaWZmUHJvcHMgPSByZXF1aXJlKFwiLi9kaWZmLXByb3BzXCIpO1xuXG4gICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IGRpZmY7XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIGRpZmYoYSwgYikge1xuICAgICAgICAgICAgICAgIHZhciBwYXRjaCA9IHsgYTogYSB9O1xuICAgICAgICAgICAgICAgIHdhbGsoYSwgYiwgcGF0Y2gsIDApO1xuICAgICAgICAgICAgICAgIHJldHVybiBwYXRjaDtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZnVuY3Rpb24gd2FsayhhLCBiLCBwYXRjaCwgaW5kZXgpIHtcbiAgICAgICAgICAgICAgICBpZiAoYSA9PT0gYikge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgdmFyIGFwcGx5ID0gcGF0Y2hbaW5kZXhdO1xuICAgICAgICAgICAgICAgIHZhciBhcHBseUNsZWFyID0gZmFsc2U7XG5cbiAgICAgICAgICAgICAgICBpZiAoaXNUaHVuayhhKSB8fCBpc1RodW5rKGIpKSB7XG4gICAgICAgICAgICAgICAgICAgIHRodW5rcyhhLCBiLCBwYXRjaCwgaW5kZXgpO1xuICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoYiA9PSBudWxsKSB7XG5cbiAgICAgICAgICAgICAgICAgICAgLy8gSWYgYSBpcyBhIHdpZGdldCB3ZSB3aWxsIGFkZCBhIHJlbW92ZSBwYXRjaCBmb3IgaXRcbiAgICAgICAgICAgICAgICAgICAgLy8gT3RoZXJ3aXNlIGFueSBjaGlsZCB3aWRnZXRzL2hvb2tzIG11c3QgYmUgZGVzdHJveWVkLlxuICAgICAgICAgICAgICAgICAgICAvLyBUaGlzIHByZXZlbnRzIGFkZGluZyB0d28gcmVtb3ZlIHBhdGNoZXMgZm9yIGEgd2lkZ2V0LlxuICAgICAgICAgICAgICAgICAgICBpZiAoIWlzV2lkZ2V0KGEpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBjbGVhclN0YXRlKGEsIHBhdGNoLCBpbmRleCk7XG4gICAgICAgICAgICAgICAgICAgICAgICBhcHBseSA9IHBhdGNoW2luZGV4XTtcbiAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgIGFwcGx5ID0gYXBwZW5kUGF0Y2goYXBwbHksIG5ldyBWUGF0Y2goVlBhdGNoLlJFTU9WRSwgYSwgYikpO1xuICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoaXNWTm9kZShiKSkge1xuICAgICAgICAgICAgICAgICAgICBpZiAoaXNWTm9kZShhKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGEudGFnTmFtZSA9PT0gYi50YWdOYW1lICYmIGEubmFtZXNwYWNlID09PSBiLm5hbWVzcGFjZSAmJiBhLmtleSA9PT0gYi5rZXkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB2YXIgcHJvcHNQYXRjaCA9IGRpZmZQcm9wcyhhLnByb3BlcnRpZXMsIGIucHJvcGVydGllcyk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHByb3BzUGF0Y2gpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYXBwbHkgPSBhcHBlbmRQYXRjaChhcHBseSwgbmV3IFZQYXRjaChWUGF0Y2guUFJPUFMsIGEsIHByb3BzUGF0Y2gpKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgYXBwbHkgPSBkaWZmQ2hpbGRyZW4oYSwgYiwgcGF0Y2gsIGFwcGx5LCBpbmRleCk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGFwcGx5ID0gYXBwZW5kUGF0Y2goYXBwbHksIG5ldyBWUGF0Y2goVlBhdGNoLlZOT0RFLCBhLCBiKSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgYXBwbHlDbGVhciA9IHRydWU7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBhcHBseSA9IGFwcGVuZFBhdGNoKGFwcGx5LCBuZXcgVlBhdGNoKFZQYXRjaC5WTk9ERSwgYSwgYikpO1xuICAgICAgICAgICAgICAgICAgICAgICAgYXBwbHlDbGVhciA9IHRydWU7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKGlzVlRleHQoYikpIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKCFpc1ZUZXh0KGEpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBhcHBseSA9IGFwcGVuZFBhdGNoKGFwcGx5LCBuZXcgVlBhdGNoKFZQYXRjaC5WVEVYVCwgYSwgYikpO1xuICAgICAgICAgICAgICAgICAgICAgICAgYXBwbHlDbGVhciA9IHRydWU7XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoYS50ZXh0ICE9PSBiLnRleHQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGFwcGx5ID0gYXBwZW5kUGF0Y2goYXBwbHksIG5ldyBWUGF0Y2goVlBhdGNoLlZURVhULCBhLCBiKSk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKGlzV2lkZ2V0KGIpKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmICghaXNXaWRnZXQoYSkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGFwcGx5Q2xlYXIgPSB0cnVlO1xuICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgYXBwbHkgPSBhcHBlbmRQYXRjaChhcHBseSwgbmV3IFZQYXRjaChWUGF0Y2guV0lER0VULCBhLCBiKSk7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgaWYgKGFwcGx5KSB7XG4gICAgICAgICAgICAgICAgICAgIHBhdGNoW2luZGV4XSA9IGFwcGx5O1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIGlmIChhcHBseUNsZWFyKSB7XG4gICAgICAgICAgICAgICAgICAgIGNsZWFyU3RhdGUoYSwgcGF0Y2gsIGluZGV4KTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIGRpZmZDaGlsZHJlbihhLCBiLCBwYXRjaCwgYXBwbHksIGluZGV4KSB7XG4gICAgICAgICAgICAgICAgdmFyIGFDaGlsZHJlbiA9IGEuY2hpbGRyZW47XG4gICAgICAgICAgICAgICAgdmFyIG9yZGVyZWRTZXQgPSByZW9yZGVyKGFDaGlsZHJlbiwgYi5jaGlsZHJlbik7XG4gICAgICAgICAgICAgICAgdmFyIGJDaGlsZHJlbiA9IG9yZGVyZWRTZXQuY2hpbGRyZW47XG5cbiAgICAgICAgICAgICAgICB2YXIgYUxlbiA9IGFDaGlsZHJlbi5sZW5ndGg7XG4gICAgICAgICAgICAgICAgdmFyIGJMZW4gPSBiQ2hpbGRyZW4ubGVuZ3RoO1xuICAgICAgICAgICAgICAgIHZhciBsZW4gPSBhTGVuID4gYkxlbiA/IGFMZW4gOiBiTGVuO1xuXG4gICAgICAgICAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCBsZW47IGkrKykge1xuICAgICAgICAgICAgICAgICAgICB2YXIgbGVmdE5vZGUgPSBhQ2hpbGRyZW5baV07XG4gICAgICAgICAgICAgICAgICAgIHZhciByaWdodE5vZGUgPSBiQ2hpbGRyZW5baV07XG4gICAgICAgICAgICAgICAgICAgIGluZGV4ICs9IDE7XG5cbiAgICAgICAgICAgICAgICAgICAgaWYgKCFsZWZ0Tm9kZSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHJpZ2h0Tm9kZSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIEV4Y2VzcyBub2RlcyBpbiBiIG5lZWQgdG8gYmUgYWRkZWRcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBhcHBseSA9IGFwcGVuZFBhdGNoKGFwcGx5LCBuZXcgVlBhdGNoKFZQYXRjaC5JTlNFUlQsIG51bGwsIHJpZ2h0Tm9kZSkpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgd2FsayhsZWZ0Tm9kZSwgcmlnaHROb2RlLCBwYXRjaCwgaW5kZXgpO1xuICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgaWYgKGlzVk5vZGUobGVmdE5vZGUpICYmIGxlZnROb2RlLmNvdW50KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBpbmRleCArPSBsZWZ0Tm9kZS5jb3VudDtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIGlmIChvcmRlcmVkU2V0Lm1vdmVzKSB7XG4gICAgICAgICAgICAgICAgICAgIC8vIFJlb3JkZXIgbm9kZXMgbGFzdFxuICAgICAgICAgICAgICAgICAgICBhcHBseSA9IGFwcGVuZFBhdGNoKGFwcGx5LCBuZXcgVlBhdGNoKFZQYXRjaC5PUkRFUiwgYSwgb3JkZXJlZFNldC5tb3ZlcykpO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHJldHVybiBhcHBseTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZnVuY3Rpb24gY2xlYXJTdGF0ZSh2Tm9kZSwgcGF0Y2gsIGluZGV4KSB7XG4gICAgICAgICAgICAgICAgLy8gVE9ETzogTWFrZSB0aGlzIGEgc2luZ2xlIHdhbGssIG5vdCB0d29cbiAgICAgICAgICAgICAgICB1bmhvb2sodk5vZGUsIHBhdGNoLCBpbmRleCk7XG4gICAgICAgICAgICAgICAgZGVzdHJveVdpZGdldHModk5vZGUsIHBhdGNoLCBpbmRleCk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIC8vIFBhdGNoIHJlY29yZHMgZm9yIGFsbCBkZXN0cm95ZWQgd2lkZ2V0cyBtdXN0IGJlIGFkZGVkIGJlY2F1c2Ugd2UgbmVlZFxuICAgICAgICAgICAgLy8gYSBET00gbm9kZSByZWZlcmVuY2UgZm9yIHRoZSBkZXN0cm95IGZ1bmN0aW9uXG4gICAgICAgICAgICBmdW5jdGlvbiBkZXN0cm95V2lkZ2V0cyh2Tm9kZSwgcGF0Y2gsIGluZGV4KSB7XG4gICAgICAgICAgICAgICAgaWYgKGlzV2lkZ2V0KHZOb2RlKSkge1xuICAgICAgICAgICAgICAgICAgICBpZiAodHlwZW9mIHZOb2RlLmRlc3Ryb3kgPT09IFwiZnVuY3Rpb25cIikge1xuICAgICAgICAgICAgICAgICAgICAgICAgcGF0Y2hbaW5kZXhdID0gYXBwZW5kUGF0Y2gocGF0Y2hbaW5kZXhdLCBuZXcgVlBhdGNoKFZQYXRjaC5SRU1PVkUsIHZOb2RlLCBudWxsKSk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKGlzVk5vZGUodk5vZGUpICYmICh2Tm9kZS5oYXNXaWRnZXRzIHx8IHZOb2RlLmhhc1RodW5rcykpIHtcbiAgICAgICAgICAgICAgICAgICAgdmFyIGNoaWxkcmVuID0gdk5vZGUuY2hpbGRyZW47XG4gICAgICAgICAgICAgICAgICAgIHZhciBsZW4gPSBjaGlsZHJlbi5sZW5ndGg7XG4gICAgICAgICAgICAgICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgbGVuOyBpKyspIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHZhciBjaGlsZCA9IGNoaWxkcmVuW2ldO1xuICAgICAgICAgICAgICAgICAgICAgICAgaW5kZXggKz0gMTtcblxuICAgICAgICAgICAgICAgICAgICAgICAgZGVzdHJveVdpZGdldHMoY2hpbGQsIHBhdGNoLCBpbmRleCk7XG5cbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChpc1ZOb2RlKGNoaWxkKSAmJiBjaGlsZC5jb3VudCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGluZGV4ICs9IGNoaWxkLmNvdW50O1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfSBlbHNlIGlmIChpc1RodW5rKHZOb2RlKSkge1xuICAgICAgICAgICAgICAgICAgICB0aHVua3Modk5vZGUsIG51bGwsIHBhdGNoLCBpbmRleCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAvLyBDcmVhdGUgYSBzdWItcGF0Y2ggZm9yIHRodW5rc1xuICAgICAgICAgICAgZnVuY3Rpb24gdGh1bmtzKGEsIGIsIHBhdGNoLCBpbmRleCkge1xuICAgICAgICAgICAgICAgIHZhciBub2RlcyA9IGhhbmRsZVRodW5rKGEsIGIpO1xuICAgICAgICAgICAgICAgIHZhciB0aHVua1BhdGNoID0gZGlmZihub2Rlcy5hLCBub2Rlcy5iKTtcbiAgICAgICAgICAgICAgICBpZiAoaGFzUGF0Y2hlcyh0aHVua1BhdGNoKSkge1xuICAgICAgICAgICAgICAgICAgICBwYXRjaFtpbmRleF0gPSBuZXcgVlBhdGNoKFZQYXRjaC5USFVOSywgbnVsbCwgdGh1bmtQYXRjaCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBmdW5jdGlvbiBoYXNQYXRjaGVzKHBhdGNoKSB7XG4gICAgICAgICAgICAgICAgZm9yICh2YXIgaW5kZXggaW4gcGF0Y2gpIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKGluZGV4ICE9PSBcImFcIikge1xuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIC8vIEV4ZWN1dGUgaG9va3Mgd2hlbiB0d28gbm9kZXMgYXJlIGlkZW50aWNhbFxuICAgICAgICAgICAgZnVuY3Rpb24gdW5ob29rKHZOb2RlLCBwYXRjaCwgaW5kZXgpIHtcbiAgICAgICAgICAgICAgICBpZiAoaXNWTm9kZSh2Tm9kZSkpIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKHZOb2RlLmhvb2tzKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBwYXRjaFtpbmRleF0gPSBhcHBlbmRQYXRjaChwYXRjaFtpbmRleF0sIG5ldyBWUGF0Y2goVlBhdGNoLlBST1BTLCB2Tm9kZSwgdW5kZWZpbmVkS2V5cyh2Tm9kZS5ob29rcykpKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgIGlmICh2Tm9kZS5kZXNjZW5kYW50SG9va3MgfHwgdk5vZGUuaGFzVGh1bmtzKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICB2YXIgY2hpbGRyZW4gPSB2Tm9kZS5jaGlsZHJlbjtcbiAgICAgICAgICAgICAgICAgICAgICAgIHZhciBsZW4gPSBjaGlsZHJlbi5sZW5ndGg7XG4gICAgICAgICAgICAgICAgICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IGxlbjsgaSsrKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdmFyIGNoaWxkID0gY2hpbGRyZW5baV07XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaW5kZXggKz0gMTtcblxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHVuaG9vayhjaGlsZCwgcGF0Y2gsIGluZGV4KTtcblxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChpc1ZOb2RlKGNoaWxkKSAmJiBjaGlsZC5jb3VudCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpbmRleCArPSBjaGlsZC5jb3VudDtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKGlzVGh1bmsodk5vZGUpKSB7XG4gICAgICAgICAgICAgICAgICAgIHRodW5rcyh2Tm9kZSwgbnVsbCwgcGF0Y2gsIGluZGV4KTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIHVuZGVmaW5lZEtleXMob2JqKSB7XG4gICAgICAgICAgICAgICAgdmFyIHJlc3VsdCA9IHt9O1xuXG4gICAgICAgICAgICAgICAgZm9yICh2YXIga2V5IGluIG9iaikge1xuICAgICAgICAgICAgICAgICAgICByZXN1bHRba2V5XSA9IHVuZGVmaW5lZDtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICByZXR1cm4gcmVzdWx0O1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAvLyBMaXN0IGRpZmYsIG5haXZlIGxlZnQgdG8gcmlnaHQgcmVvcmRlcmluZ1xuICAgICAgICAgICAgZnVuY3Rpb24gcmVvcmRlcihhQ2hpbGRyZW4sIGJDaGlsZHJlbikge1xuICAgICAgICAgICAgICAgIC8vIE8oTSkgdGltZSwgTyhNKSBtZW1vcnlcbiAgICAgICAgICAgICAgICB2YXIgYkNoaWxkSW5kZXggPSBrZXlJbmRleChiQ2hpbGRyZW4pO1xuICAgICAgICAgICAgICAgIHZhciBiS2V5cyA9IGJDaGlsZEluZGV4LmtleXM7XG4gICAgICAgICAgICAgICAgdmFyIGJGcmVlID0gYkNoaWxkSW5kZXguZnJlZTtcblxuICAgICAgICAgICAgICAgIGlmIChiRnJlZS5sZW5ndGggPT09IGJDaGlsZHJlbi5sZW5ndGgpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGNoaWxkcmVuOiBiQ2hpbGRyZW4sXG4gICAgICAgICAgICAgICAgICAgICAgICBtb3ZlczogbnVsbFxuICAgICAgICAgICAgICAgICAgICB9O1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIC8vIE8oTikgdGltZSwgTyhOKSBtZW1vcnlcbiAgICAgICAgICAgICAgICB2YXIgYUNoaWxkSW5kZXggPSBrZXlJbmRleChhQ2hpbGRyZW4pO1xuICAgICAgICAgICAgICAgIHZhciBhS2V5cyA9IGFDaGlsZEluZGV4LmtleXM7XG4gICAgICAgICAgICAgICAgdmFyIGFGcmVlID0gYUNoaWxkSW5kZXguZnJlZTtcblxuICAgICAgICAgICAgICAgIGlmIChhRnJlZS5sZW5ndGggPT09IGFDaGlsZHJlbi5sZW5ndGgpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGNoaWxkcmVuOiBiQ2hpbGRyZW4sXG4gICAgICAgICAgICAgICAgICAgICAgICBtb3ZlczogbnVsbFxuICAgICAgICAgICAgICAgICAgICB9O1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIC8vIE8oTUFYKE4sIE0pKSBtZW1vcnlcbiAgICAgICAgICAgICAgICB2YXIgbmV3Q2hpbGRyZW4gPSBbXTtcblxuICAgICAgICAgICAgICAgIHZhciBmcmVlSW5kZXggPSAwO1xuICAgICAgICAgICAgICAgIHZhciBmcmVlQ291bnQgPSBiRnJlZS5sZW5ndGg7XG4gICAgICAgICAgICAgICAgdmFyIGRlbGV0ZWRJdGVtcyA9IDA7XG5cbiAgICAgICAgICAgICAgICAvLyBJdGVyYXRlIHRocm91Z2ggYSBhbmQgbWF0Y2ggYSBub2RlIGluIGJcbiAgICAgICAgICAgICAgICAvLyBPKE4pIHRpbWUsXG4gICAgICAgICAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCBhQ2hpbGRyZW4ubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgICAgICAgICAgdmFyIGFJdGVtID0gYUNoaWxkcmVuW2ldO1xuICAgICAgICAgICAgICAgICAgICB2YXIgaXRlbUluZGV4O1xuXG4gICAgICAgICAgICAgICAgICAgIGlmIChhSXRlbS5rZXkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChiS2V5cy5oYXNPd25Qcm9wZXJ0eShhSXRlbS5rZXkpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gTWF0Y2ggdXAgdGhlIG9sZCBrZXlzXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaXRlbUluZGV4ID0gYktleXNbYUl0ZW0ua2V5XTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBuZXdDaGlsZHJlbi5wdXNoKGJDaGlsZHJlbltpdGVtSW5kZXhdKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gUmVtb3ZlIG9sZCBrZXllZCBpdGVtc1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGl0ZW1JbmRleCA9IGkgLSBkZWxldGVkSXRlbXMrKztcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBuZXdDaGlsZHJlbi5wdXNoKG51bGwpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgLy8gTWF0Y2ggdGhlIGl0ZW0gaW4gYSB3aXRoIHRoZSBuZXh0IGZyZWUgaXRlbSBpbiBiXG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoZnJlZUluZGV4IDwgZnJlZUNvdW50KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaXRlbUluZGV4ID0gYkZyZWVbZnJlZUluZGV4KytdO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIG5ld0NoaWxkcmVuLnB1c2goYkNoaWxkcmVuW2l0ZW1JbmRleF0pO1xuICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBUaGVyZSBhcmUgbm8gZnJlZSBpdGVtcyBpbiBiIHRvIG1hdGNoIHdpdGhcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyB0aGUgZnJlZSBpdGVtcyBpbiBhLCBzbyB0aGUgZXh0cmEgZnJlZSBub2Rlc1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIGFyZSBkZWxldGVkLlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGl0ZW1JbmRleCA9IGkgLSBkZWxldGVkSXRlbXMrKztcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBuZXdDaGlsZHJlbi5wdXNoKG51bGwpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgdmFyIGxhc3RGcmVlSW5kZXggPSBmcmVlSW5kZXggPj0gYkZyZWUubGVuZ3RoID8gYkNoaWxkcmVuLmxlbmd0aCA6IGJGcmVlW2ZyZWVJbmRleF07XG5cbiAgICAgICAgICAgICAgICAvLyBJdGVyYXRlIHRocm91Z2ggYiBhbmQgYXBwZW5kIGFueSBuZXcga2V5c1xuICAgICAgICAgICAgICAgIC8vIE8oTSkgdGltZVxuICAgICAgICAgICAgICAgIGZvciAodmFyIGogPSAwOyBqIDwgYkNoaWxkcmVuLmxlbmd0aDsgaisrKSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciBuZXdJdGVtID0gYkNoaWxkcmVuW2pdO1xuXG4gICAgICAgICAgICAgICAgICAgIGlmIChuZXdJdGVtLmtleSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKCFhS2V5cy5oYXNPd25Qcm9wZXJ0eShuZXdJdGVtLmtleSkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBBZGQgYW55IG5ldyBrZXllZCBpdGVtc1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIFdlIGFyZSBhZGRpbmcgbmV3IGl0ZW1zIHRvIHRoZSBlbmQgYW5kIHRoZW4gc29ydGluZyB0aGVtXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gaW4gcGxhY2UuIEluIGZ1dHVyZSB3ZSBzaG91bGQgaW5zZXJ0IG5ldyBpdGVtcyBpbiBwbGFjZS5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBuZXdDaGlsZHJlbi5wdXNoKG5ld0l0ZW0pO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKGogPj0gbGFzdEZyZWVJbmRleCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgLy8gQWRkIGFueSBsZWZ0b3ZlciBub24ta2V5ZWQgaXRlbXNcbiAgICAgICAgICAgICAgICAgICAgICAgIG5ld0NoaWxkcmVuLnB1c2gobmV3SXRlbSk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICB2YXIgc2ltdWxhdGUgPSBuZXdDaGlsZHJlbi5zbGljZSgpO1xuICAgICAgICAgICAgICAgIHZhciBzaW11bGF0ZUluZGV4ID0gMDtcbiAgICAgICAgICAgICAgICB2YXIgcmVtb3ZlcyA9IFtdO1xuICAgICAgICAgICAgICAgIHZhciBpbnNlcnRzID0gW107XG4gICAgICAgICAgICAgICAgdmFyIHNpbXVsYXRlSXRlbTtcblxuICAgICAgICAgICAgICAgIGZvciAodmFyIGsgPSAwOyBrIDwgYkNoaWxkcmVuLmxlbmd0aDspIHtcbiAgICAgICAgICAgICAgICAgICAgdmFyIHdhbnRlZEl0ZW0gPSBiQ2hpbGRyZW5ba107XG4gICAgICAgICAgICAgICAgICAgIHNpbXVsYXRlSXRlbSA9IHNpbXVsYXRlW3NpbXVsYXRlSW5kZXhdO1xuXG4gICAgICAgICAgICAgICAgICAgIC8vIHJlbW92ZSBpdGVtc1xuICAgICAgICAgICAgICAgICAgICB3aGlsZSAoc2ltdWxhdGVJdGVtID09PSBudWxsICYmIHNpbXVsYXRlLmxlbmd0aCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgcmVtb3Zlcy5wdXNoKHJlbW92ZShzaW11bGF0ZSwgc2ltdWxhdGVJbmRleCwgbnVsbCkpO1xuICAgICAgICAgICAgICAgICAgICAgICAgc2ltdWxhdGVJdGVtID0gc2ltdWxhdGVbc2ltdWxhdGVJbmRleF07XG4gICAgICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgICAgICBpZiAoIXNpbXVsYXRlSXRlbSB8fCBzaW11bGF0ZUl0ZW0ua2V5ICE9PSB3YW50ZWRJdGVtLmtleSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgLy8gaWYgd2UgbmVlZCBhIGtleSBpbiB0aGlzIHBvc2l0aW9uLi4uXG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAod2FudGVkSXRlbS5rZXkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoc2ltdWxhdGVJdGVtICYmIHNpbXVsYXRlSXRlbS5rZXkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gaWYgYW4gaW5zZXJ0IGRvZXNuJ3QgcHV0IHRoaXMga2V5IGluIHBsYWNlLCBpdCBuZWVkcyB0byBtb3ZlXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChiS2V5c1tzaW11bGF0ZUl0ZW0ua2V5XSAhPT0gayArIDEpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlbW92ZXMucHVzaChyZW1vdmUoc2ltdWxhdGUsIHNpbXVsYXRlSW5kZXgsIHNpbXVsYXRlSXRlbS5rZXkpKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNpbXVsYXRlSXRlbSA9IHNpbXVsYXRlW3NpbXVsYXRlSW5kZXhdO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gaWYgdGhlIHJlbW92ZSBkaWRuJ3QgcHV0IHRoZSB3YW50ZWQgaXRlbSBpbiBwbGFjZSwgd2UgbmVlZCB0byBpbnNlcnQgaXRcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmICghc2ltdWxhdGVJdGVtIHx8IHNpbXVsYXRlSXRlbS5rZXkgIT09IHdhbnRlZEl0ZW0ua2V5KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaW5zZXJ0cy5wdXNoKHsga2V5OiB3YW50ZWRJdGVtLmtleSwgdG86IGsgfSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBpdGVtcyBhcmUgbWF0Y2hpbmcsIHNvIHNraXAgYWhlYWRcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNpbXVsYXRlSW5kZXgrKztcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGluc2VydHMucHVzaCh7IGtleTogd2FudGVkSXRlbS5rZXksIHRvOiBrIH0pO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaW5zZXJ0cy5wdXNoKHsga2V5OiB3YW50ZWRJdGVtLmtleSwgdG86IGsgfSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGsrKztcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIGEga2V5IGluIHNpbXVsYXRlIGhhcyBubyBtYXRjaGluZyB3YW50ZWQga2V5LCByZW1vdmUgaXRcbiAgICAgICAgICAgICAgICAgICAgICAgIGVsc2UgaWYgKHNpbXVsYXRlSXRlbSAmJiBzaW11bGF0ZUl0ZW0ua2V5KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcmVtb3Zlcy5wdXNoKHJlbW92ZShzaW11bGF0ZSwgc2ltdWxhdGVJbmRleCwgc2ltdWxhdGVJdGVtLmtleSkpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgc2ltdWxhdGVJbmRleCsrO1xuICAgICAgICAgICAgICAgICAgICAgICAgaysrO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgLy8gcmVtb3ZlIGFsbCB0aGUgcmVtYWluaW5nIG5vZGVzIGZyb20gc2ltdWxhdGVcbiAgICAgICAgICAgICAgICB3aGlsZSAoc2ltdWxhdGVJbmRleCA8IHNpbXVsYXRlLmxlbmd0aCkge1xuICAgICAgICAgICAgICAgICAgICBzaW11bGF0ZUl0ZW0gPSBzaW11bGF0ZVtzaW11bGF0ZUluZGV4XTtcbiAgICAgICAgICAgICAgICAgICAgcmVtb3Zlcy5wdXNoKHJlbW92ZShzaW11bGF0ZSwgc2ltdWxhdGVJbmRleCwgc2ltdWxhdGVJdGVtICYmIHNpbXVsYXRlSXRlbS5rZXkpKTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAvLyBJZiB0aGUgb25seSBtb3ZlcyB3ZSBoYXZlIGFyZSBkZWxldGVzIHRoZW4gd2UgY2FuIGp1c3RcbiAgICAgICAgICAgICAgICAvLyBsZXQgdGhlIGRlbGV0ZSBwYXRjaCByZW1vdmUgdGhlc2UgaXRlbXMuXG4gICAgICAgICAgICAgICAgaWYgKHJlbW92ZXMubGVuZ3RoID09PSBkZWxldGVkSXRlbXMgJiYgIWluc2VydHMubGVuZ3RoKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiB7XG4gICAgICAgICAgICAgICAgICAgICAgICBjaGlsZHJlbjogbmV3Q2hpbGRyZW4sXG4gICAgICAgICAgICAgICAgICAgICAgICBtb3ZlczogbnVsbFxuICAgICAgICAgICAgICAgICAgICB9O1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHJldHVybiB7XG4gICAgICAgICAgICAgICAgICAgIGNoaWxkcmVuOiBuZXdDaGlsZHJlbixcbiAgICAgICAgICAgICAgICAgICAgbW92ZXM6IHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJlbW92ZXM6IHJlbW92ZXMsXG4gICAgICAgICAgICAgICAgICAgICAgICBpbnNlcnRzOiBpbnNlcnRzXG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9O1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBmdW5jdGlvbiByZW1vdmUoYXJyLCBpbmRleCwga2V5KSB7XG4gICAgICAgICAgICAgICAgYXJyLnNwbGljZShpbmRleCwgMSk7XG5cbiAgICAgICAgICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgICAgICAgICBmcm9tOiBpbmRleCxcbiAgICAgICAgICAgICAgICAgICAga2V5OiBrZXlcbiAgICAgICAgICAgICAgICB9O1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBmdW5jdGlvbiBrZXlJbmRleChjaGlsZHJlbikge1xuICAgICAgICAgICAgICAgIHZhciBrZXlzID0ge307XG4gICAgICAgICAgICAgICAgdmFyIGZyZWUgPSBbXTtcbiAgICAgICAgICAgICAgICB2YXIgbGVuZ3RoID0gY2hpbGRyZW4ubGVuZ3RoO1xuXG4gICAgICAgICAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCBsZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgICAgICAgICB2YXIgY2hpbGQgPSBjaGlsZHJlbltpXTtcblxuICAgICAgICAgICAgICAgICAgICBpZiAoY2hpbGQua2V5KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBrZXlzW2NoaWxkLmtleV0gPSBpO1xuICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgZnJlZS5wdXNoKGkpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgICAgICAgICAga2V5czoga2V5cywgLy8gQSBoYXNoIG9mIGtleSBuYW1lIHRvIGluZGV4XG4gICAgICAgICAgICAgICAgICAgIGZyZWU6IGZyZWUgLy8gQW4gYXJyYXkgb2YgdW5rZXllZCBpdGVtIGluZGljZXNcbiAgICAgICAgICAgICAgICB9O1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBmdW5jdGlvbiBhcHBlbmRQYXRjaChhcHBseSwgcGF0Y2gpIHtcbiAgICAgICAgICAgICAgICBpZiAoYXBwbHkpIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKGlzQXJyYXkoYXBwbHkpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBhcHBseS5wdXNoKHBhdGNoKTtcbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGFwcGx5ID0gW2FwcGx5LCBwYXRjaF07XG4gICAgICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgICAgICByZXR1cm4gYXBwbHk7XG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHBhdGNoO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgfSwgeyBcIi4uL3Zub2RlL2hhbmRsZS10aHVua1wiOiAyNCwgXCIuLi92bm9kZS9pcy10aHVua1wiOiAyNSwgXCIuLi92bm9kZS9pcy12bm9kZVwiOiAyNywgXCIuLi92bm9kZS9pcy12dGV4dFwiOiAyOCwgXCIuLi92bm9kZS9pcy13aWRnZXRcIjogMjksIFwiLi4vdm5vZGUvdnBhdGNoXCI6IDMyLCBcIi4vZGlmZi1wcm9wc1wiOiAzNCwgXCJ4LWlzLWFycmF5XCI6IDEyIH1dIH0sIHt9LCBbNF0pKDQpO1xufSk7XG5cbmNvbnN0IENvcmUgPSBDO1xuXG5leHBvcnQgeyBDb3JlLCBrZXJuZWwgYXMgS2VybmVsLCBFbnVtLCBWaXJ0dWFsRE9NIH07Il0sImZpbGUiOiJFbGl4aXIuanMiLCJzb3VyY2VSb290IjoiL3NvdXJjZS8ifQ== \ No newline at end of file diff --git a/src/javascript/elixir.js b/src/javascript/elixir.js index 745d15be..34edc259 100644 --- a/src/javascript/elixir.js +++ b/src/javascript/elixir.js @@ -3,9 +3,4 @@ import * as C from './lib/core'; export const Core = C; export { default as Kernel } from './lib/kernel'; export { default as Enum } from './lib/enum'; -export { default as List } from './lib/list'; -export { default as Keyword } from './lib/keyword'; -export { default as Bitwise } from './lib/bitwise'; -export { default as Map } from './lib/map'; -export { default as MapSet } from './lib/map_set'; export { default as VirtualDOM } from './lib/virtual-dom'; diff --git a/src/javascript/lib/core/functions.js b/src/javascript/lib/core/functions.js index 291da362..f2282184 100644 --- a/src/javascript/lib/core/functions.js +++ b/src/javascript/lib/core/functions.js @@ -320,6 +320,32 @@ function bxor(left, right){ return left ^ right; } +function zip(list_of_lists){ + if(list_of_lists.length === 0){ + return Object.freeze([]); + } + + let new_value = []; + let smallest_length = list_of_lists[0]; + + for(let x of list_of_lists){ + if(x.length < smallest_length){ + smallest_length = x.length; + } + } + + for(let i = 0; i < smallest_length; i++){ + let current_value = []; + for(let j = 0; j < list_of_lists.length; j++){ + current_value.push(list_of_lists[j][i]); + } + + new_value.push(new Tuple(...current_value)); + } + + return Object.freeze(new_value); +} + export default { call_property, is_instance_of, @@ -367,5 +393,6 @@ export default { bor, bsl, bsr, - bxor + bxor, + zip }; diff --git a/src/javascript/lib/list.js b/src/javascript/lib/list.js deleted file mode 100644 index aa4adcff..00000000 --- a/src/javascript/lib/list.js +++ /dev/null @@ -1,277 +0,0 @@ -import Kernel from './kernel'; -import * as Core from './core'; - -let List = {}; - -List.delete = function(list, item){ - let new_value = []; - let value_found = false; - - for(let x of list){ - if(x === item && value_found !== false){ - new_value.push(x); - value_found = true; - }else if(x !== item){ - new_value.push(x); - } - } - - return Core.SpecialForms.list(...new_value); -}; - -List.delete_at = function(list, index){ - let new_value = []; - - for(let i = 0; i < list.length; i++){ - if(i !== index){ - new_value.push(list[i]); - } - } - - return Core.SpecialForms.list(...new_value); -}; - -List.duplicate = function(elem, n){ - let new_value = []; - - for (var i = 0; i < n; i++) { - new_value.push(elem); - } - - return Core.SpecialForms.list(...new_value); -}; - -List.first = function(list){ - return list[0]; -}; - -List.flatten = function(list, tail = Core.SpecialForms.list()){ - let new_value = []; - - for(let x of list){ - if(Array.isArray(x)){ - new_value = new_value.concat(List.flatten(x)); - }else{ - new_value.push(x); - } - } - - new_value = new_value.concat(tail); - - return Core.SpecialForms.list(...new_value); -}; - -List.foldl = function(list, acc, func){ - return list.reduce(func, acc); -}; - -List.foldr = function(list, acc, func){ - let new_acc = acc; - - for (var i = list.length - 1; i >= 0; i--) { - new_acc = func(list[i], new_acc); - } - - return new_acc; -}; - -List.insert_at = function(list, index, value){ - let new_value = []; - - for(let i = 0; i < list.length; i++){ - if(i === index){ - new_value.push(value); - new_value.push(list[i]); - }else{ - new_value.push(list[i]); - } - } - - return Core.SpecialForms.list(...new_value); -}; - -List.keydelete = function(list, key, position){ - let new_list = []; - - for(let i = 0; i < list.length; i++){ - if(!Kernel.match__qmark__(list[i][position], key)){ - new_list.push(list[i]); - } - } - - return Core.SpecialForms.list(...new_list); -}; - -List.keyfind = function(list, key, position, _default = null){ - - for(let i = 0; i < list.length; i++){ - if(Kernel.match__qmark__(list[i][position], key)){ - return list[i]; - } - } - - return _default; -}; - -List.keymember__qmark__ = function(list, key, position){ - - for(let i = 0; i < list.length; i++){ - if(Kernel.match__qmark__(list[i][position], key)){ - return true; - } - } - - return false; -}; - -List.keyreplace = function(list, key, position, new_tuple){ - let new_list = []; - - for(let i = 0; i < list.length; i++){ - if(!Kernel.match__qmark__(list[i][position], key)){ - new_list.push(list[i]); - }else{ - new_list.push(new_tuple); - } - } - - return Core.SpecialForms.list(...new_list); -}; - - -List.keysort = function(list, position){ - let new_list = list; - - new_list.sort(function(a, b){ - if(position === 0){ - if(a[position].value < b[position].value){ - return -1; - } - - if(a[position].value > b[position].value){ - return 1; - } - - return 0; - }else{ - if(a[position] < b[position]){ - return -1; - } - - if(a[position] > b[position]){ - return 1; - } - - return 0; - } - - }); - - return Core.SpecialForms.list(...new_list); -}; - -List.keystore = function(list, key, position, new_tuple){ - let new_list = []; - let replaced = false; - - for(let i = 0; i < list.length; i++){ - if(!Kernel.match__qmark__(list[i][position], key)){ - new_list.push(list[i]); - }else{ - new_list.push(new_tuple); - replaced = true; - } - } - - if(!replaced){ - new_list.push(new_tuple); - } - - return Core.SpecialForms.list(...new_list); -}; - -List.last = function(list){ - return list[list.length - 1]; -}; - -List.replace_at = function(list, index, value){ - let new_value = []; - - for(let i = 0; i < list.length; i++){ - if(i === index){ - new_value.push(value); - }else{ - new_value.push(list[i]); - } - } - - return Core.SpecialForms.list(...new_value); -}; - -List.update_at = function(list, index, fun){ - let new_value = []; - - for(let i = 0; i < list.count(); i++){ - if(i === index){ - new_value.push(fun(list.get(i))); - }else{ - new_value.push(list.get(i)); - } - } - - return new_value; -}; - -List.wrap = function(list){ - if(Array.isArray(list)){ - return list; - }else if(list == null){ - return Core.SpecialForms.list(); - }else{ - return Core.SpecialForms.list(list); - } -}; - -List.zip = function(list_of_lists){ - if(list_of_lists.length === 0){ - return Core.SpecialForms.list(); - } - - let new_value = []; - let smallest_length = list_of_lists[0]; - - for(let x of list_of_lists){ - if(x.length < smallest_length){ - smallest_length = x.length; - } - } - - for(let i = 0; i < smallest_length; i++){ - let current_value = []; - for(let j = 0; j < list_of_lists.length; j++){ - current_value.push(list_of_lists[j][i]); - } - - new_value.push(new Core.Tuple(...current_value)); - } - - return Core.SpecialForms.list(...new_value); -}; - -List.to_tuple = function(list){ - return new Core.Tuple(...list); -}; - -List.append = function(list, value){ - return Core.SpecialForms.list(...list.concat([value])); -}; - -List.prepend = function(list, value){ - return Core.SpecialForms.list(...[value].concat(list)); -}; - -List.concat = function(left, right){ - return left.concat(right); -}; - -export default List; diff --git a/src/javascript/tests/list.spec.js b/src/javascript/tests/list.spec.js deleted file mode 100644 index 21d68d66..00000000 --- a/src/javascript/tests/list.spec.js +++ /dev/null @@ -1,77 +0,0 @@ -var List = require('../lib/list'); -var Kernel = require('../lib/kernel'); -var SpecialForms = require('../lib/core').SpecialForms; -var expect = require('chai').expect; - -describe('List', function(){ - - describe('duplicate', function(){ - it('must make a tuple with the value duplicated the specified amount of times', function(){ - let t = List.duplicate("value", 3); - - expect(t.length).to.equal(3); - expect(t[0]).to.equal("value"); - expect(t[1]).to.equal("value"); - expect(t[2]).to.equal("value"); - - t = List.duplicate("value", 0); - expect(t.length).to.equal(0); - }) - }) - - describe('delete_at', function(){ - it('must delete first item', function(){ - let t = SpecialForms.list(1, 2, 3); - t = List.delete_at(t, 0); - expect(t[0]).to.equal(2); - }) - }) - - describe('delete', function(){ - it('delete item in list', function(){ - let t = SpecialForms.list(Symbol.for("a"), Symbol.for("b"), Symbol.for("c")); - t = List.delete(t, Symbol.for("b")); - expect(t[1]).to.equal(Symbol.for("c")); - }) - }) - - describe('flatten', function(){ - it('must flatten a list into one list', function(){ - let t = SpecialForms.list(1, SpecialForms.list(2), 3); - - t = List.flatten(t); - - expect(t[0]).to.equal(1); - expect(t[1]).to.equal(2); - expect(t[2]).to.equal(3); - }) - - it('must flatten a deeply nested list into one list', function(){ - let t = SpecialForms.list(1, SpecialForms.list(2, SpecialForms.list(4)), 3); - - t = List.flatten(t); - - expect(t[0]).to.equal(1); - expect(t[1]).to.equal(2); - expect(t[2]).to.equal(4); - expect(t[3]).to.equal(3); - }) - }) - - describe('toString', function(){ - it('must display correctly', function(){ - let t = SpecialForms.list(1, 2, 3); - expect(t.toString()).to.equal('1,2,3'); - }) - }) - - describe('destructuring', function(){ - it('destructure into an array', function(){ - let t = SpecialForms.list(1, 2, 3); - let [a, b, c] = t; - expect(a).to.equal(1); - expect(b).to.equal(2); - expect(c).to.equal(3); - }) - }) -}) diff --git a/test/elixir_script_test.exs b/test/elixir_script_test.exs index 9c2aed13..c204543f 100644 --- a/test/elixir_script_test.exs +++ b/test/elixir_script_test.exs @@ -1,8 +1,8 @@ defmodule ElixirScript.Test do - use ShouldI + use ExUnit.Case import ElixirScript.TestHelper - should "chain methods" do + test "chain methods" do js_code = ElixirScript.compile(""" JQuery.("
").text(html) """) @@ -10,12 +10,12 @@ defmodule ElixirScript.Test do assert Enum.join(js_code, "\n") =~ "JQuery('
').text(html)" end - should "turn javascript ast into javascript code strings" do + test "turn javascript ast into javascript code strings" do js_code = ElixirScript.compile(":atom") assert Enum.join(js_code, "\n") =~ "Symbol.for('atom')" end - should "parse one module correctly" do + test "parse one module correctly" do js_code = ElixirScript.compile(""" defmodule Elephant do @@ -50,7 +50,7 @@ defmodule ElixirScript.Test do """, hd(js_code) end - should "parse multiple modules correctly" do + test "parse multiple modules correctly" do js_code = ElixirScript.compile(""" defmodule Animals do @@ -93,7 +93,7 @@ defmodule ElixirScript.Test do end - should "parse macros" do + test "parse macros" do js_code = ElixirScript.compile(""" defmodule Animals do @@ -122,7 +122,7 @@ defmodule ElixirScript.Test do end - should "expand Html macros" do + test "expand Html macros" do js_code = ElixirScript.compile(""" tree = Html.div [id: "myDiv"] do Html.span do @@ -146,7 +146,7 @@ defmodule ElixirScript.Test do end - should "set standard lib path" do + test "set standard lib path" do js_code = ElixirScript.compile(""" defmodule Animals do diff --git a/test/lib/js_test.exs b/test/lib/js_test.exs index 74fa3070..0680d836 100644 --- a/test/lib/js_test.exs +++ b/test/lib/js_test.exs @@ -1,8 +1,8 @@ defmodule ElixirScript.Lib.JS.Test do - use ShouldI + use ExUnit.Case import ElixirScript.TestHelper - should "translate new" do + test "translate new" do ex_ast = quote do JS.new A.B, [1, 2, 3] end @@ -24,7 +24,7 @@ defmodule ElixirScript.Lib.JS.Test do assert_translation(ex_ast, js_code) end - should "translate update" do + test "translate update" do ex_ast = quote do JS.update A, "b", [1, 2, 3] end @@ -35,4 +35,4 @@ defmodule ElixirScript.Lib.JS.Test do assert_translation(ex_ast, js_code) end -end \ No newline at end of file +end diff --git a/test/lib/kernel_test.exs b/test/lib/kernel_test.exs index 9563f847..0ae653fc 100644 --- a/test/lib/kernel_test.exs +++ b/test/lib/kernel_test.exs @@ -1,8 +1,8 @@ defmodule ElixirScript.Lib.Elixir.Kernel.Test do - use ShouldI + use ExUnit.Case import ElixirScript.TestHelper - should "translate range" do + test "translate range" do ex_ast = quote do 1..4 end diff --git a/test/pattern_matching/match_test.exs b/test/pattern_matching/match_test.exs index fe168c53..44c73a76 100644 --- a/test/pattern_matching/match_test.exs +++ b/test/pattern_matching/match_test.exs @@ -1,12 +1,12 @@ defmodule ElixirScript.PatternMatching.Match.Test do - use ShouldI + use ExUnit.Case alias ElixirScript.Translator alias ElixirScript.Translator.Primitive alias ElixirScript.PatternMatching.Match alias ElixirScript.Translator.Map alias ESTree.Tools.Builder, as: JS -# should "match wildcard" do +# test "match wildcard" do # params = [{:_, [], Test}] # result = Match.build_match(params, ElixirScript.Translator.Env.module_env(ElixirScript.Temp, "temp.ex") ) # expected_result = { [Match.wildcard], [JS.identifier(:undefined)] } @@ -14,7 +14,7 @@ defmodule ElixirScript.PatternMatching.Match.Test do # assert result == expected_result # end # -# should "match one identifier param" do +# test "match one identifier param" do # params = [{:a, [], Test}] # result = Match.build_match(params, ElixirScript.Translator.Env.module_env(ElixirScript.Temp, "temp.ex") ) # expected_result = {[Match.parameter], [JS.identifier("a")]} @@ -22,7 +22,7 @@ defmodule ElixirScript.PatternMatching.Match.Test do # assert result == expected_result # end # -# should "match multiple identifier params" do +# test "match multiple identifier params" do # params = [{:a, [], Test}, {:b, [], Test}, {:c, [], Test}] # result = Match.build_match(params, ElixirScript.Translator.Env.module_env(ElixirScript.Temp, "temp.ex") ) # expected_result = { @@ -33,7 +33,7 @@ defmodule ElixirScript.PatternMatching.Match.Test do # assert result == expected_result # end # -# should "match head and tail param" do +# test "match head and tail param" do # params = [[{:|, [], [{:head, [], Elixir}, {:tail, [], Elixir}]}]] # result = Match.build_match(params, ElixirScript.Translator.Env.module_env(ElixirScript.Temp, "temp.ex") ) # expected_result = { @@ -44,7 +44,7 @@ defmodule ElixirScript.PatternMatching.Match.Test do # assert result == expected_result # end # -# should "match prefix param" do +# test "match prefix param" do # params = [{:<>, [context: Elixir, import: Elixir.Kernel], ["Bearer ", {:token, [], Elixir}]}] # result = Match.build_match(params, ElixirScript.Translator.Env.module_env(ElixirScript.Temp, "temp.ex") ) # expected_result = { @@ -55,7 +55,7 @@ defmodule ElixirScript.PatternMatching.Match.Test do # assert result == expected_result # end # -# should "match list" do +# test "match list" do # params = [[{:a, [], Elixir}, {:b, [], Elixir}, {:c, [], Elixir}]] # result = Match.build_match(params, ElixirScript.Translator.Env.module_env(ElixirScript.Temp, "temp.ex") ) # expected_result = { @@ -66,7 +66,7 @@ defmodule ElixirScript.PatternMatching.Match.Test do # assert result == expected_result # end # -# should "match list with a literal" do +# test "match list with a literal" do # params = [[1, {:b, [], Elixir}, {:c, [], Elixir}]] # result = Match.build_match(params, ElixirScript.Translator.Env.module_env(ElixirScript.Temp, "temp.ex") ) # expected_result = { @@ -77,7 +77,7 @@ defmodule ElixirScript.PatternMatching.Match.Test do # assert result == expected_result # end # -# should "match number" do +# test "match number" do # params = [1] # result = Match.build_match(params, ElixirScript.Translator.Env.module_env(ElixirScript.Temp, "temp.ex") ) # expected_result = { @@ -88,7 +88,7 @@ defmodule ElixirScript.PatternMatching.Match.Test do # assert result == expected_result # end # -# should "match struct pattern" do +# test "match struct pattern" do # ElixirScript.Translator.State.start_link(nil, nil) # # params = [{:%, [], [{:__aliases__, [alias: false], [:Hello]}, {:%{}, [], []}]}] @@ -103,7 +103,7 @@ defmodule ElixirScript.PatternMatching.Match.Test do # ElixirScript.Translator.State.stop() # end # -# should "match struct pattern with property" do +# test "match struct pattern with property" do # ElixirScript.Translator.State.start_link(nil, nil) # # params = [{:%, [], [{:__aliases__, [alias: false], [:Hello]}, {:%{}, [], [key: 1]}]}] @@ -121,7 +121,7 @@ defmodule ElixirScript.PatternMatching.Match.Test do # ElixirScript.Translator.State.stop() # end # -# should "match struct pattern with property param" do +# test "match struct pattern with property param" do # ElixirScript.Translator.State.start_link(nil, nil) # # params = [{:%, [], [{:__aliases__, [alias: false], [:Hello]}, {:%{}, [], [key: {:key, [], Elixir }]}]}] @@ -140,7 +140,7 @@ defmodule ElixirScript.PatternMatching.Match.Test do # # end # -# should "capture parameter when assigning it" do +# test "capture parameter when assigning it" do # ElixirScript.Translator.State.start_link(nil, nil) # # params = [{:=, [], [1, {:a, [], Elixir}]}] @@ -175,7 +175,7 @@ defmodule ElixirScript.PatternMatching.Match.Test do # ElixirScript.Translator.State.stop() # end # -# should "match and assign list" do +# test "match and assign list" do # params = [{:=, [], [[{:a, [], Elixir}, {:b, [], Elixir}, {:c, [], Elixir}], {:d, [], Elixir}]}] # result = Match.build_match(params, ElixirScript.Translator.Env.module_env(ElixirScript.Temp, "temp.ex") ) # expected_result = { @@ -186,7 +186,7 @@ defmodule ElixirScript.PatternMatching.Match.Test do # assert result == expected_result # end # -# should "match on tuple" do +# test "match on tuple" do # params = [{:{}, [], [1, {:b, [], Elixir}, 3]}] # result = Match.build_match(params, ElixirScript.Translator.Env.module_env(ElixirScript.Temp, "temp.ex") ) # expected_result = { @@ -212,7 +212,7 @@ defmodule ElixirScript.PatternMatching.Match.Test do # assert result == expected_result # end # -# should "match on map" do +# test "match on map" do # params = [{:%{}, [], [which: 13]}] # result = Match.build_match(params, ElixirScript.Translator.Env.module_env(ElixirScript.Temp, "temp.ex") ) # @@ -227,7 +227,7 @@ defmodule ElixirScript.PatternMatching.Match.Test do # end # # -# should "match on bound value" do +# test "match on bound value" do # params = [{:^, [], [{:a, [], Elixir}]}] # result = Match.build_match(params, ElixirScript.Translator.Env.module_env(ElixirScript.Temp, "temp.ex") ) # diff --git a/test/test_helper.exs b/test/test_helper.exs index 0040f746..d5b1bcbf 100644 --- a/test/test_helper.exs +++ b/test/test_helper.exs @@ -1,6 +1,6 @@ exclude = if Node.alive?, do: [], else: [skip: true] -ExUnit.start(exclude: exclude, formatters: [ShouldI.CLIFormatter]) +ExUnit.start(exclude: exclude) defmodule ElixirScript.Math do defmacro squared(x) do @@ -20,7 +20,7 @@ defmodule ElixirScript.Using do end defmodule ElixirScript.TestHelper do - use ShouldI + use ExUnit.Case def make_custom_env do use ElixirScript diff --git a/test/translator/access_test.exs b/test/translator/access_test.exs index db076418..fb7080e1 100644 --- a/test/translator/access_test.exs +++ b/test/translator/access_test.exs @@ -1,8 +1,8 @@ defmodule ElixirScript.Translator.Access.Test do - use ShouldI + use ExUnit.Case import ElixirScript.TestHelper - should "translate access" do + test "translate access" do ex_ast = quote do: a[:b] js_code = "a[Symbol.for('b')]" @@ -13,4 +13,4 @@ defmodule ElixirScript.Translator.Access.Test do assert_translation(ex_ast, js_code) end -end \ No newline at end of file +end diff --git a/test/translator/assignment_test.exs b/test/translator/assignment_test.exs index 363fd801..851d3baa 100644 --- a/test/translator/assignment_test.exs +++ b/test/translator/assignment_test.exs @@ -1,8 +1,8 @@ defmodule ElixirScript.Translator.Assignment.Test do - use ShouldI + use ExUnit.Case import ElixirScript.TestHelper - should "translate simple assignment" do + test "translate simple assignment" do ex_ast = quote do: a = 1 js_code = "let [a] = Elixir.Core.Patterns.match(Elixir.Core.Patterns.variable(), 1);" @@ -14,15 +14,15 @@ defmodule ElixirScript.Translator.Assignment.Test do assert_translation(ex_ast, js_code) end - should "translate tuple assignment" do + test "translate tuple assignment" do ex_ast = quote do {a, b} = {1, 2} end js_code = """ let [a, b] = Elixir.Core.Patterns.match(Elixir.Core.Patterns.type(Elixir.Core.Tuple, { values: [Elixir.Core.Patterns.variable(), Elixir.Core.Patterns.variable()] - }), Elixir.Core.SpecialForms.tuple(1, 2)); - let _ref = Elixir.Core.SpecialForms.tuple(a, b); + }), new Elixir.Core.Tuple(1, 2)); + let _ref = new Elixir.Core.Tuple(a, b); """ assert_translation(ex_ast, js_code) @@ -31,8 +31,8 @@ defmodule ElixirScript.Translator.Assignment.Test do js_code = """ let [a, undefined, c] = Elixir.Core.Patterns.match(Elixir.Core.Patterns.type(Elixir.Core.Tuple, { values: [Elixir.Core.Patterns.variable(), Elixir.Core.Patterns.wildcard(), Elixir.Core.Patterns.variable()] - }), Elixir.Core.SpecialForms.tuple(1, 2, 3)); - let _ref = Elixir.Core.SpecialForms.tuple(a, undefined, c); + }), new Elixir.Core.Tuple(1, 2, 3)); + let _ref = new Elixir.Core.Tuple(a, undefined, c); """ assert_translation(ex_ast, js_code) @@ -42,14 +42,14 @@ defmodule ElixirScript.Translator.Assignment.Test do js_code = """ let [, undefined, c] = Elixir.Core.Patterns.match(Elixir.Core.Patterns.type(Elixir.Core.Tuple, { values: [Elixir.Core.Patterns.bound(a), Elixir.Core.Patterns.wildcard(), Elixir.Core.Patterns.variable()] - }), Elixir.Core.SpecialForms.tuple(1, 2, 3)); - let _ref = Elixir.Core.SpecialForms.tuple(undefined, undefined, c); + }), new Elixir.Core.Tuple(1, 2, 3)); + let _ref = new Elixir.Core.Tuple(undefined, undefined, c); """ assert_translation(ex_ast, js_code) end - should "translate bound assignment" do + test "translate bound assignment" do ex_ast = quote do: ^a = 1 js_code = """ let [] = Elixir.Core.Patterns.match(Elixir.Core.Patterns.bound(a),1); @@ -58,7 +58,7 @@ defmodule ElixirScript.Translator.Assignment.Test do assert_translation(ex_ast, js_code) end - should "translate list assignment" do + test "translate list assignment" do ex_ast = quote do: [a, b] = [1, 2] js_code = """ let [a, b] = Elixir.Core.Patterns.match(Elixir.Core.SpecialForms.list(Elixir.Core.Patterns.variable(), Elixir.Core.Patterns.variable()), Elixir.Core.SpecialForms.list(1, 2)); @@ -68,7 +68,7 @@ defmodule ElixirScript.Translator.Assignment.Test do assert_translation(ex_ast, js_code) end - should "translate head/tail assignment" do + test "translate head/tail assignment" do ex_ast = quote do: [a | b] = [1, 2, 3, 4] js_code = """ let [a,b] = Elixir.Core.Patterns.match(Elixir.Core.Patterns.headTail(),Elixir.Core.SpecialForms.list(1,2,3,4)); diff --git a/test/translator/atom_test.exs b/test/translator/atom_test.exs index f4f37367..c06273a5 100644 --- a/test/translator/atom_test.exs +++ b/test/translator/atom_test.exs @@ -1,13 +1,13 @@ defmodule ElixirScript.Translator.Atom.Test do - use ShouldI + use ExUnit.Case import ElixirScript.TestHelper - should "translate atom" do + test "translate atom" do ex_ast = quote do: :atom assert_translation(ex_ast, "Symbol.for('atom')") end - should "Call Atom module" do + test "Call Atom module" do ex_ast = quote do: Atom.to_string(:atom) assert_translation(ex_ast, "Elixir$ElixirScript$Atom.to_string(Symbol.for('atom'))") end diff --git a/test/translator/bitstring_test.exs b/test/translator/bitstring_test.exs index 886565ed..53fc9e07 100644 --- a/test/translator/bitstring_test.exs +++ b/test/translator/bitstring_test.exs @@ -1,8 +1,8 @@ defmodule ElixirScript.Translator.Bitstring.Test do - use ShouldI + use ExUnit.Case import ElixirScript.TestHelper - should "translate bitstring" do + test "translate bitstring" do ex_ast = quote do: <<1, 2, 3>> assert_translation(ex_ast, "Elixir.Core.SpecialForms.bitstring(Elixir.Core.BitString.integer(1), Elixir.Core.BitString.integer(2), Elixir.Core.BitString.integer(3))") diff --git a/test/translator/bug_test.exs b/test/translator/bug_test.exs index 5c9ba2ea..54c2bbd4 100644 --- a/test/translator/bug_test.exs +++ b/test/translator/bug_test.exs @@ -1,8 +1,8 @@ defmodule ElixirScript.Translator.Bug.Test do - use ShouldI + use ExUnit.Case import ElixirScript.TestHelper - should "Translate function with 0 arguments" do + test "Translate function with 0 arguments" do ex_ast = quote do def test do :atom @@ -18,7 +18,7 @@ defmodule ElixirScript.Translator.Bug.Test do assert_translation(ex_ast, js_code) end - should "Translate react element" do + test "Translate react element" do ex_ast = quote do React.createElement( React.Text, @@ -37,7 +37,7 @@ defmodule ElixirScript.Translator.Bug.Test do end - should "correctly not create 2 imports" do + test "correctly not create 2 imports" do ex_ast = quote do defmodule App.Todo do JS.import JQuery, "jquery" @@ -55,7 +55,7 @@ defmodule ElixirScript.Translator.Bug.Test do assert_translation(ex_ast, js_code) end - should "correctly translate module names when used" do + test "correctly translate module names when used" do ex_ast = quote do @graphic_store App.Stores.GraphicStore.create_store() end @@ -68,7 +68,7 @@ defmodule ElixirScript.Translator.Bug.Test do assert_translation(ex_ast, js_code) end - should "replace !" do + test "replace !" do ex_ast = quote do Elixir.Enum.fetch!(data, i) end @@ -80,7 +80,7 @@ defmodule ElixirScript.Translator.Bug.Test do assert_translation(ex_ast, js_code) end - should "chain calls correctly" do + test "chain calls correctly" do ex_ast = quote do :this.getRawCanvas().getContext("2d") end @@ -103,7 +103,7 @@ defmodule ElixirScript.Translator.Bug.Test do assert_translation(ex_ast, js_code) end - should "correctly call multi-module functions" do + test "correctly call multi-module functions" do ex_ast = quote do def getDispatcher() do DeLorean.Flux.createDispatcher(%{ diff --git a/test/translator/capture_test.exs b/test/translator/capture_test.exs index 6c75f7a2..bec406c9 100644 --- a/test/translator/capture_test.exs +++ b/test/translator/capture_test.exs @@ -1,8 +1,8 @@ defmodule ElixirScript.Translator.Capture.Test do - use ShouldI + use ExUnit.Case import ElixirScript.TestHelper - should "translate capture operator with Module, function, and arity" do + test "translate capture operator with Module, function, and arity" do ex_ast = quote do fun = &Elixir.Kernel.is_atom/1 end @@ -17,7 +17,7 @@ defmodule ElixirScript.Translator.Capture.Test do end - should "translate capture operator with function, and parameters" do + test "translate capture operator with function, and parameters" do ex_ast = quote do fun = &is_atom(&1) @@ -34,7 +34,7 @@ defmodule ElixirScript.Translator.Capture.Test do end - should "translate capture operator with function, and arity" do + test "translate capture operator with function, and arity" do ex_ast = quote do fun = &local_function/1 @@ -50,7 +50,7 @@ defmodule ElixirScript.Translator.Capture.Test do end - should "translate capture operator with anonymous function" do + test "translate capture operator with anonymous function" do ex_ast = quote do fun = &(&1 * 2) @@ -66,7 +66,7 @@ defmodule ElixirScript.Translator.Capture.Test do end - should "translate capture operator with anonymous function tuple" do + test "translate capture operator with anonymous function tuple" do ex_ast = quote do fun = &{&1, &2} @@ -74,7 +74,7 @@ defmodule ElixirScript.Translator.Capture.Test do js_code = """ let [fun] = Elixir.Core.Patterns.match(Elixir.Core.Patterns.variable(),Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable(), Elixir.Core.Patterns.variable()],function(__1,__2) { - return Elixir.Core.SpecialForms.tuple(__1,__2); + return new Elixir.Core.Tuple(__1,__2); }))); """ @@ -86,7 +86,7 @@ defmodule ElixirScript.Translator.Capture.Test do js_code = """ let [fun] = Elixir.Core.Patterns.match(Elixir.Core.Patterns.variable(),Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable(), Elixir.Core.Patterns.variable(), Elixir.Core.Patterns.variable()],function(__1,__2,__3) { - return Elixir.Core.SpecialForms.tuple(__1,__2,__3); + return new Elixir.Core.Tuple(__1,__2,__3); }))); """ @@ -95,7 +95,7 @@ defmodule ElixirScript.Translator.Capture.Test do end - should "translate capture operator with anonymous functions as parameters" do + test "translate capture operator with anonymous functions as parameters" do ex_ast = quote do Elixir.Enum.map(items, &process(&1)) diff --git a/test/translator/case_test.exs b/test/translator/case_test.exs index 29a245d8..db944222 100644 --- a/test/translator/case_test.exs +++ b/test/translator/case_test.exs @@ -1,8 +1,8 @@ defmodule ElixirScript.Translator.Case.Test do - use ShouldI + use ExUnit.Case import ElixirScript.TestHelper - should "translate case" do + test "translate case" do ex_ast = quote do case data do @@ -60,7 +60,7 @@ defmodule ElixirScript.Translator.Case.Test do assert_translation(ex_ast, js_code) end - should "translate case with guard" do + test "translate case with guard" do ex_ast = quote do case data do number when number in [1,2,3,4] -> @@ -84,7 +84,7 @@ defmodule ElixirScript.Translator.Case.Test do assert_translation(ex_ast, js_code) end - should "translate case with multiple statements in body" do + test "translate case with multiple statements in body" do ex_ast = quote do case data do :ok -> @@ -107,7 +107,7 @@ defmodule ElixirScript.Translator.Case.Test do assert_translation(ex_ast, js_code) end - should "translate case with destructing" do + test "translate case with destructing" do ex_ast = quote do case data do { one, two } -> @@ -130,7 +130,7 @@ defmodule ElixirScript.Translator.Case.Test do assert_translation(ex_ast, js_code) end - should "translate case with nested destructing" do + test "translate case with nested destructing" do ex_ast = quote do case data do { {one, two} , three } -> diff --git a/test/translator/cond_test.exs b/test/translator/cond_test.exs index 363dcab4..5888619d 100644 --- a/test/translator/cond_test.exs +++ b/test/translator/cond_test.exs @@ -1,8 +1,8 @@ defmodule ElixirScript.Translator.Cond.Test do - use ShouldI + use ExUnit.Case import ElixirScript.TestHelper - should "translate cond" do + test "translate cond" do ex_ast = quote do cond do 1 + 1 == 1 -> @@ -55,4 +55,4 @@ defmodule ElixirScript.Translator.Cond.Test do assert_translation(ex_ast, js_code) end -end \ No newline at end of file +end diff --git a/test/translator/defmodule_test.exs b/test/translator/defmodule_test.exs index fb87a6af..ca77670f 100644 --- a/test/translator/defmodule_test.exs +++ b/test/translator/defmodule_test.exs @@ -1,8 +1,8 @@ defmodule ElixirScript.Translator.Defmodule.Test do - use ShouldI + use ExUnit.Case import ElixirScript.TestHelper - should "translate empty module" do + test "translate empty module" do ex_ast = quote do defmodule Elephant do end @@ -16,7 +16,7 @@ defmodule ElixirScript.Translator.Defmodule.Test do assert_translation(ex_ast, js_code) end - should "translate defmodules" do + test "translate defmodules" do ex_ast = quote do defmodule Elephant do @ul JQuery.("#todo-list") @@ -48,7 +48,7 @@ defmodule ElixirScript.Translator.Defmodule.Test do assert_translation(ex_ast, js_code) end - should "translate modules with inner modules" do + test "translate modules with inner modules" do ex_ast = quote do defmodule Animals do @@ -95,7 +95,7 @@ defmodule ElixirScript.Translator.Defmodule.Test do end - should "translate modules with inner module that has inner module" do + test "translate modules with inner module that has inner module" do ex_ast = quote do defmodule Animals do @@ -156,7 +156,7 @@ defmodule ElixirScript.Translator.Defmodule.Test do assert_translation(ex_ast, js_code) end - should "Pull out module references and make them into imports if modules listed" do + test "Pull out module references and make them into imports if modules listed" do ex_ast = quote do defmodule Animals do Lions.Tigers.oh_my() @@ -181,7 +181,7 @@ defmodule ElixirScript.Translator.Defmodule.Test do assert_translation(ex_ast, js_code) end - should "ignore aliases already added" do + test "ignore aliases already added" do ex_ast = quote do defmodule Animals do alias Lions.Tigers @@ -216,7 +216,7 @@ defmodule ElixirScript.Translator.Defmodule.Test do assert_translation(ex_ast, js_code) end - should "import only" do + test "import only" do ex_ast = quote do defmodule Lions.Tigers do def oh_my() do @@ -256,7 +256,7 @@ defmodule ElixirScript.Translator.Defmodule.Test do assert_translation(ex_ast, js_code) end - should "import except" do + test "import except" do ex_ast = quote do defmodule Lions.Tigers do def oh_my() do diff --git a/test/translator/for_test.exs b/test/translator/for_test.exs index ad9b8550..2920f59b 100644 --- a/test/translator/for_test.exs +++ b/test/translator/for_test.exs @@ -1,8 +1,8 @@ defmodule ElixirScript.Translator.For.Test do - use ShouldI + use ExUnit.Case import ElixirScript.TestHelper - should "translate simple for" do + test "translate simple for" do ex_ast = quote do for n <- [1, 2, 3, 4], do: n * 2 end @@ -18,7 +18,7 @@ defmodule ElixirScript.Translator.For.Test do assert_translation(ex_ast, js_code) end - should "translate simple for with into" do + test "translate simple for with into" do ex_ast = quote do for n <- [1, 2, 3, 4], into: [], do: n * 2 end @@ -34,7 +34,7 @@ defmodule ElixirScript.Translator.For.Test do assert_translation(ex_ast, js_code) end - should "translate for with string" do + test "translate for with string" do ex_ast = quote do for n <- "Opera", do: n end @@ -50,7 +50,7 @@ defmodule ElixirScript.Translator.For.Test do assert_translation(ex_ast, js_code) end - should "translate multiple generator for" do + test "translate multiple generator for" do ex_ast = quote do for x <- [1, 2], y <- [2, 3], do: x*y end @@ -68,7 +68,7 @@ defmodule ElixirScript.Translator.For.Test do assert_translation(ex_ast, js_code) end - should "translate multiple generator for, assignment, and do block" do + test "translate multiple generator for, assignment, and do block" do ex_ast = quote do r = for x <- [1, 2], y <- [2, 3] do x*y @@ -86,7 +86,7 @@ defmodule ElixirScript.Translator.For.Test do assert_translation(ex_ast, js_code) end - should "translate for with filter" do + test "translate for with filter" do ex_ast = quote do for n <- [1, 2, 3, 4, 5, 6], rem(n, 2) == 0, do: n end @@ -102,7 +102,7 @@ defmodule ElixirScript.Translator.For.Test do assert_translation(ex_ast, js_code) end - should "translate for with pattern matched input" do + test "translate for with pattern matched input" do ex_ast = quote do for {:user, name} <- [user: "john", admin: "john", user: "meg"] do Elixir.String.upcase(name) @@ -112,7 +112,7 @@ defmodule ElixirScript.Translator.For.Test do js_code = """ Elixir.Core.SpecialForms._for(Elixir.Core.SpecialForms.list(Elixir.Core.SpecialForms.list(Elixir.Core.Patterns.type(Elixir.Core.Tuple,{ values: [Symbol.for('user'), Elixir.Core.Patterns.variable()] - }),Elixir.Core.SpecialForms.list(Elixir.Core.SpecialForms.tuple(Symbol.for('user'),'john'),Elixir.Core.SpecialForms.tuple(Symbol.for('admin'),'john'),Elixir.Core.SpecialForms.tuple(Symbol.for('user'),'meg')))),function(name) { + }),Elixir.Core.SpecialForms.list(new Elixir.Core.Tuple(Symbol.for('user'),'john'),new Elixir.Core.Tuple(Symbol.for('admin'),'john'),new Elixir.Core.Tuple(Symbol.for('user'),'meg')))),function(name) { return Elixir$ElixirScript$String.upcase(name); },function() { return true; diff --git a/test/translator/function_test.exs b/test/translator/function_test.exs index 70765ca8..5fb8d23c 100644 --- a/test/translator/function_test.exs +++ b/test/translator/function_test.exs @@ -1,8 +1,8 @@ defmodule ElixirScript.Translator.Function.Test do - use ShouldI + use ExUnit.Case import ElixirScript.TestHelper - should "call fun" do + test "call fun" do ex_ast = quote do fun.(:atom) end @@ -16,7 +16,7 @@ defmodule ElixirScript.Translator.Function.Test do end - should "translate function with a macro" do + test "translate function with a macro" do ex_ast = quote do def test1() do ElixirScript.Math.squared(1) @@ -32,7 +32,7 @@ defmodule ElixirScript.Translator.Function.Test do assert_translation(ex_ast, js_code) end - should "translate functions" do + test "translate functions" do ex_ast = quote do def test1() do end @@ -143,8 +143,8 @@ defmodule ElixirScript.Translator.Function.Test do const test1 = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable(), Elixir.Core.Patterns.variable()], function(alpha, beta) { let [a, b] = Elixir.Core.Patterns.match(Elixir.Core.Patterns.type(Elixir.Core.Tuple, { values: [Elixir.Core.Patterns.variable(), Elixir.Core.Patterns.variable()] - }), Elixir.Core.SpecialForms.tuple(1, 2)); - let _ref = Elixir.Core.SpecialForms.tuple(a, b); + }), new Elixir.Core.Tuple(1, 2)); + let _ref = new Elixir.Core.Tuple(a, b); return _ref; })); """ @@ -152,7 +152,7 @@ defmodule ElixirScript.Translator.Function.Test do assert_translation(ex_ast, js_code) end - should "translate function calls" do + test "translate function calls" do ex_ast = quote do test1() end @@ -203,7 +203,7 @@ defmodule ElixirScript.Translator.Function.Test do end - should "translate anonymous functions" do + test "translate anonymous functions" do ex_ast = quote do Elixir.Enum.map(list, fn(x) -> x * 2 end) end @@ -217,7 +217,7 @@ defmodule ElixirScript.Translator.Function.Test do assert_translation(ex_ast, js_code) end - should "translate function arity" do + test "translate function arity" do ex_ast = quote do defmodule Example do @@ -315,7 +315,7 @@ defmodule ElixirScript.Translator.Function.Test do end - should "test |> operator" do + test "test |> operator" do ex_ast = quote do 1 |> Taco.test end @@ -334,7 +334,7 @@ defmodule ElixirScript.Translator.Function.Test do end - should "test Elixir.Kernel function" do + test "test Elixir.Kernel function" do ex_ast = quote do is_atom(:atom) end @@ -344,7 +344,7 @@ defmodule ElixirScript.Translator.Function.Test do assert_translation(ex_ast, js_code) end - should "guards" do + test "guards" do ex_ast = quote do def something(one) when is_number(one) do end @@ -439,7 +439,7 @@ defmodule ElixirScript.Translator.Function.Test do end - should "pattern match function with literal" do + test "pattern match function with literal" do ex_ast = quote do def something(1) do end @@ -455,7 +455,7 @@ defmodule ElixirScript.Translator.Function.Test do assert_translation(ex_ast, js_code) end - should "pattern match function with list" do + test "pattern match function with list" do ex_ast = quote do def something([apple | fruits]) do end @@ -471,7 +471,7 @@ defmodule ElixirScript.Translator.Function.Test do assert_translation(ex_ast, js_code) end - should "pattern match function with multiple items in list" do + test "pattern match function with multiple items in list" do ex_ast = quote do def something([apple, pear, banana]) do end @@ -487,7 +487,7 @@ defmodule ElixirScript.Translator.Function.Test do assert_translation(ex_ast, js_code) end - should "pattern match function with tuple" do + test "pattern match function with tuple" do ex_ast = quote do def something({ apple , fruits }) do end @@ -505,7 +505,7 @@ defmodule ElixirScript.Translator.Function.Test do assert_translation(ex_ast, js_code) end - should "pattern match function with struct" do + test "pattern match function with struct" do ex_ast = quote do def something(%AStruct{}) do end @@ -521,7 +521,7 @@ defmodule ElixirScript.Translator.Function.Test do assert_translation(ex_ast, js_code) end - should "pattern match function with struct reference" do + test "pattern match function with struct reference" do ex_ast = quote do def something(%AStruct{} = a) do end @@ -535,7 +535,7 @@ defmodule ElixirScript.Translator.Function.Test do assert_translation(ex_ast, js_code) end - should "pattern match function with map reference" do + test "pattern match function with map reference" do ex_ast = quote do def something(%{ which: 13 } = a) do end @@ -552,7 +552,7 @@ defmodule ElixirScript.Translator.Function.Test do assert_translation(ex_ast, js_code) end - should "pattern match function with struct decontructed" do + test "pattern match function with struct decontructed" do ex_ast = quote do def something(%AStruct{key: value, key1: 2}) do end @@ -588,7 +588,7 @@ defmodule ElixirScript.Translator.Function.Test do assert_translation(ex_ast, js_code) end - should "pattern match function with binary part" do + test "pattern match function with binary part" do ex_ast = quote do def something("Bearer " <> token) do end @@ -632,7 +632,7 @@ defmodule ElixirScript.Translator.Function.Test do assert_translation(ex_ast, js_code) end - should "combine pattern matched functions of same arity" do + test "combine pattern matched functions of same arity" do ex_ast = quote do defmodule Example do def something(1) do @@ -673,7 +673,7 @@ defmodule ElixirScript.Translator.Function.Test do end - should "translate varible declaration correctly" do + test "translate varible declaration correctly" do ex_ast = quote do def test1(alpha, beta) do a = 1 @@ -729,7 +729,7 @@ defmodule ElixirScript.Translator.Function.Test do assert_translation(ex_ast, js_code) end - should "translate function variables with ? or !" do + test "translate function variables with ? or !" do ex_ast = quote do def test1(alpha?, beta!) do a? = 1 @@ -748,7 +748,7 @@ defmodule ElixirScript.Translator.Function.Test do assert_translation(ex_ast, js_code) end - should "translate function params with defaults" do + test "translate function params with defaults" do ex_ast = quote do def test1(alpha, beta \\ 0) do end diff --git a/test/translator/kernel_test.exs b/test/translator/kernel_test.exs index ed0c4314..ead45061 100644 --- a/test/translator/kernel_test.exs +++ b/test/translator/kernel_test.exs @@ -1,8 +1,8 @@ defmodule ElixirScript.Translator.Kernel.Test do - use ShouldI + use ExUnit.Case import ElixirScript.TestHelper - should "max" do + test "max" do ex_ast = quote do max(1, 2) end @@ -15,7 +15,7 @@ defmodule ElixirScript.Translator.Kernel.Test do end - should "apply/2" do + test "apply/2" do ex_ast = quote do apply(fun, [1, 2, 3]) end @@ -28,7 +28,7 @@ defmodule ElixirScript.Translator.Kernel.Test do end - should "apply/3" do + test "apply/3" do ex_ast = quote do apply(Enum, :reverse, [1, 2, 3]) end @@ -41,7 +41,7 @@ defmodule ElixirScript.Translator.Kernel.Test do end - should "hd" do + test "hd" do ex_ast = quote do hd([1, 2, 3]) end @@ -54,7 +54,7 @@ defmodule ElixirScript.Translator.Kernel.Test do end - should "tl" do + test "tl" do ex_ast = quote do tl([1, 2, 3]) end diff --git a/test/translator/list_test.exs b/test/translator/list_test.exs index 1fd127ca..a39262ab 100644 --- a/test/translator/list_test.exs +++ b/test/translator/list_test.exs @@ -1,8 +1,8 @@ defmodule ElixirScript.Translator.List.Test do - use ShouldI + use ExUnit.Case import ElixirScript.TestHelper - should "translate list" do + test "translate list" do ex_ast = quote do: [1, 2, 3] js_code = "Elixir.Core.SpecialForms.list(1, 2, 3)" @@ -24,7 +24,7 @@ defmodule ElixirScript.Translator.List.Test do assert_translation(ex_ast, js_code) end - should "concatenate lists" do + test "concatenate lists" do ex_ast = quote do: [1, 2, 3] ++ [4, 5, 6] js_code = "Elixir.Core.Functions.concat_lists(Elixir.Core.SpecialForms.list(1,2,3),Elixir.Core.SpecialForms.list(4,5,6))" @@ -36,7 +36,7 @@ defmodule ElixirScript.Translator.List.Test do assert_translation(ex_ast, js_code) end - should "prepend element" do + test "prepend element" do ex_ast = quote do: [x|list] js_code = "Elixir.Core.prepend_to_list(list,x)" @@ -44,7 +44,7 @@ defmodule ElixirScript.Translator.List.Test do assert_translation(ex_ast, js_code) end - should "prepend element in function" do + test "prepend element in function" do ex_ast = quote do fn (_) -> [x|list] end end diff --git a/test/translator/map_test.exs b/test/translator/map_test.exs index 8d740b77..a663b94d 100644 --- a/test/translator/map_test.exs +++ b/test/translator/map_test.exs @@ -1,22 +1,22 @@ defmodule ElixirScript.Translator.Map.Test do - use ShouldI + use ExUnit.Case import ElixirScript.TestHelper - should "translate empty map" do + test "translate empty map" do ex_ast = quote do: %{} js_code = "Elixir.Core.SpecialForms.map({})" assert_translation(ex_ast, js_code) end - should "translate map with elements" do + test "translate map with elements" do ex_ast = quote do: %{one: "one", two: "two"} js_code = "Elixir.Core.SpecialForms.map({[Symbol.for('one')]: 'one', [Symbol.for('two')]: 'two'})" assert_translation(ex_ast, js_code) end - should "translate map within map" do + test "translate map within map" do ex_ast = quote do: %{one: "one", two: %{three: "three"}} js_code = """ Elixir.Core.SpecialForms.map({ @@ -30,7 +30,7 @@ defmodule ElixirScript.Translator.Map.Test do assert_translation(ex_ast, js_code) end - should "translate map with string keys" do + test "translate map with string keys" do ex_ast = quote do: %{"one" => "one", "two" => "two"} js_code = """ Elixir.Core.SpecialForms.map({ @@ -42,7 +42,7 @@ defmodule ElixirScript.Translator.Map.Test do end - should "translate map update" do + test "translate map update" do ex_ast = quote do: %{ map | value: 1 } js_code = """ Elixir.Core.SpecialForms.map_update(map,{ diff --git a/test/translator/nil_test.exs b/test/translator/nil_test.exs index 04e130e9..4c77bed1 100644 --- a/test/translator/nil_test.exs +++ b/test/translator/nil_test.exs @@ -1,9 +1,9 @@ defmodule ElixirScript.Translator.Nil.Test do - use ShouldI + use ExUnit.Case import ElixirScript.TestHelper - should "translate nil" do + test "translate nil" do ex_ast = quote do: nil assert_translation(ex_ast, "null") end -end \ No newline at end of file +end diff --git a/test/translator/number_test.exs b/test/translator/number_test.exs index 0719659d..6d2fe4f4 100644 --- a/test/translator/number_test.exs +++ b/test/translator/number_test.exs @@ -1,8 +1,8 @@ defmodule ElixirScript.Translator.Number.Test do - use ShouldI + use ExUnit.Case import ElixirScript.TestHelper - should "translate numbers" do + test "translate numbers" do ex_ast = quote do: 1 assert_translation(ex_ast, "1") @@ -15,4 +15,4 @@ defmodule ElixirScript.Translator.Number.Test do ex_ast = quote do: -1.1 assert_translation(ex_ast, "-1.1") end -end \ No newline at end of file +end diff --git a/test/translator/protocol_test.exs b/test/translator/protocol_test.exs index 45c10b37..7c12f196 100644 --- a/test/translator/protocol_test.exs +++ b/test/translator/protocol_test.exs @@ -1,5 +1,5 @@ defmodule ElixirScript.Translator.Protocol.Test do - use ShouldI + use ExUnit.Case import ElixirScript.TestHelper test "parse protocol spec with implementations" do diff --git a/test/translator/quote_test.exs b/test/translator/quote_test.exs index 5cd43336..79018a1f 100644 --- a/test/translator/quote_test.exs +++ b/test/translator/quote_test.exs @@ -1,5 +1,5 @@ defmodule ElixirScript.Translator.Quote.Test do - use ShouldI + use ExUnit.Case import ElixirScript.TestHelper test "quote number" do @@ -28,7 +28,7 @@ defmodule ElixirScript.Translator.Quote.Test do quote do: {1, 2} end - js_code = "Elixir.Core.SpecialForms.tuple(1, 2)" + js_code = "new Elixir.Core.Tuple(1, 2)" assert_translation(ex_ast, js_code) end @@ -39,7 +39,7 @@ defmodule ElixirScript.Translator.Quote.Test do quote do: {1, 2, 3} end - js_code = "Elixir.Core.SpecialForms.tuple(Symbol.for('{}'), Elixir.Core.SpecialForms.list(), Elixir.Core.SpecialForms.list(1, 2, 3))" + js_code = "new Elixir.Core.Tuple(Symbol.for('{}'), Elixir.Core.SpecialForms.list(), Elixir.Core.SpecialForms.list(1, 2, 3))" assert_translation(ex_ast, js_code) end @@ -50,8 +50,8 @@ defmodule ElixirScript.Translator.Quote.Test do quote do: test(1) end - js_code = "Elixir.Core.SpecialForms.tuple(Symbol.for('test'), - Elixir.Core.SpecialForms.list(Elixir.Core.SpecialForms.tuple(Symbol.for('context'),Symbol.for('Elixir.ElixirScript.Translator.Quote.Test')),Elixir.Core.SpecialForms.tuple(Symbol.for('import'),Symbol.for('Elixir.ExUnit.Case'))), + js_code = "new Elixir.Core.Tuple(Symbol.for('test'), + Elixir.Core.SpecialForms.list(new Elixir.Core.Tuple(Symbol.for('context'),Symbol.for('Elixir.ElixirScript.Translator.Quote.Test')),new Elixir.Core.Tuple(Symbol.for('import'),Symbol.for('Elixir.ExUnit.Case'))), Elixir.Core.SpecialForms.list(1))" assert_translation(ex_ast, js_code) @@ -63,10 +63,10 @@ defmodule ElixirScript.Translator.Quote.Test do quote do: test(x) end - js_code = "Elixir.Core.SpecialForms.tuple( + js_code = "new Elixir.Core.Tuple( Symbol.for('test'), - Elixir.Core.SpecialForms.list(Elixir.Core.SpecialForms.tuple(Symbol.for('context'),Symbol.for('Elixir.ElixirScript.Translator.Quote.Test')),Elixir.Core.SpecialForms.tuple(Symbol.for('import'),Symbol.for('Elixir.ExUnit.Case'))), - Elixir.Core.SpecialForms.list(Elixir.Core.SpecialForms.tuple(Symbol.for('x'),Elixir.Core.SpecialForms.list(),Symbol.for('Elixir.ElixirScript.Translator.Quote.Test'))) + Elixir.Core.SpecialForms.list(new Elixir.Core.Tuple(Symbol.for('context'),Symbol.for('Elixir.ElixirScript.Translator.Quote.Test')),new Elixir.Core.Tuple(Symbol.for('import'),Symbol.for('Elixir.ExUnit.Case'))), + Elixir.Core.SpecialForms.list(new Elixir.Core.Tuple(Symbol.for('x'),Elixir.Core.SpecialForms.list(),Symbol.for('Elixir.ElixirScript.Translator.Quote.Test'))) )" assert_translation(ex_ast, js_code) @@ -78,9 +78,9 @@ defmodule ElixirScript.Translator.Quote.Test do quote do: test(unquote(x)) end - js_code = "Elixir.Core.SpecialForms.tuple( + js_code = "new Elixir.Core.Tuple( Symbol.for('test'), - Elixir.Core.SpecialForms.list(Elixir.Core.SpecialForms.tuple(Symbol.for('context'),Symbol.for('Elixir.ElixirScript.Translator.Quote.Test')),Elixir.Core.SpecialForms.tuple(Symbol.for('import'),Symbol.for('Elixir.ExUnit.Case'))), + Elixir.Core.SpecialForms.list(new Elixir.Core.Tuple(Symbol.for('context'),Symbol.for('Elixir.ElixirScript.Translator.Quote.Test')),new Elixir.Core.Tuple(Symbol.for('import'),Symbol.for('Elixir.ExUnit.Case'))), Elixir.Core.SpecialForms.list(x) )" @@ -93,7 +93,7 @@ defmodule ElixirScript.Translator.Quote.Test do quote do: sum(1, unquote_splicing(values), 5) end - js_code = "Elixir.Core.SpecialForms.tuple(Symbol.for('sum'), Elixir.Core.SpecialForms.list(), Elixir.Enum.concat(Elixir.Core.SpecialForms.list(1), values, Elixir.Core.SpecialForms.list(5)))" + js_code = "new Elixir.Core.Tuple(Symbol.for('sum'), Elixir.Core.SpecialForms.list(), Elixir.Enum.concat(Elixir.Core.SpecialForms.list(1), values, Elixir.Core.SpecialForms.list(5)))" assert_translation(ex_ast, js_code) end @@ -105,9 +105,9 @@ defmodule ElixirScript.Translator.Quote.Test do end end - js_code = "Elixir.Core.SpecialForms.tuple( + js_code = "new Elixir.Core.Tuple( Symbol.for('*'), - Elixir.Core.SpecialForms.list(Elixir.Core.SpecialForms.tuple(Symbol.for('context'),Symbol.for('Elixir.ElixirScript.Translator.Quote.Test')),Elixir.Core.SpecialForms.tuple(Symbol.for('import'),Symbol.for('Elixir.ElixirScript.Kernel'))), + Elixir.Core.SpecialForms.list(new Elixir.Core.Tuple(Symbol.for('context'),Symbol.for('Elixir.ElixirScript.Translator.Quote.Test')),new Elixir.Core.Tuple(Symbol.for('import'),Symbol.for('Elixir.ElixirScript.Kernel'))), Elixir.Core.SpecialForms.list(x, x) )" diff --git a/test/translator/string_test.exs b/test/translator/string_test.exs index 1080e38d..ade3e814 100644 --- a/test/translator/string_test.exs +++ b/test/translator/string_test.exs @@ -1,13 +1,13 @@ defmodule ElixirScript.Translator.String.Test do - use ShouldI + use ExUnit.Case import ElixirScript.TestHelper - should "translate string" do + test "translate string" do ex_ast = quote do: "Hello" assert_translation(ex_ast, "'Hello'") end - should "translate multiline string" do + test "translate multiline string" do ex_ast = quote do: """ Hello This is another line @@ -15,12 +15,12 @@ defmodule ElixirScript.Translator.String.Test do assert_translation(ex_ast, "'Hello\\nThis is another line\\n'") end - should "translate string concatenation" do + test "translate string concatenation" do ex_ast = quote do: "Hello" <> "World" assert_translation(ex_ast, "'Hello' + 'World'") end - should "translate string interpolation" do + test "translate string interpolation" do ex_ast = quote do: "Hello #{"world"}" assert_translation(ex_ast, "'Hello ' + 'world'") @@ -28,7 +28,7 @@ defmodule ElixirScript.Translator.String.Test do assert_translation(ex_ast, "'Hello ' + Elixir$ElixirScript$String$Chars.to_string(Elixir$ElixirScript$Kernel.length(Elixir.Core.SpecialForms.list()))") end - should "translate multiline string interpolation" do + test "translate multiline string interpolation" do ex_ast = quote do: """ Hello #{length([])} """ diff --git a/test/translator/struct_test.exs b/test/translator/struct_test.exs index 94dfbabb..f844dcbe 100644 --- a/test/translator/struct_test.exs +++ b/test/translator/struct_test.exs @@ -1,8 +1,8 @@ defmodule ElixirScript.Translator.Struct.Test do - use ShouldI + use ExUnit.Case import ElixirScript.TestHelper - should "translate struct with default values" do + test "translate struct with default values" do ex_ast = quote do defmodule User do defstruct name: "john", age: 27 @@ -25,7 +25,7 @@ defmodule ElixirScript.Translator.Struct.Test do assert_translation(ex_ast, js_code) end - should "translate struct without default values" do + test "translate struct without default values" do ex_ast = quote do defmodule User do @@ -49,7 +49,7 @@ defmodule ElixirScript.Translator.Struct.Test do end - should "translate struct creation" do + test "translate struct creation" do ex_ast = quote do defmodule User do defstruct :name, :age @@ -102,7 +102,7 @@ defmodule ElixirScript.Translator.Struct.Test do assert_translation(ex_ast, js_code) end - should "translate struct update" do + test "translate struct update" do ex_ast = quote do user = %{ map | key: value } end @@ -129,7 +129,7 @@ defmodule ElixirScript.Translator.Struct.Test do assert_translation(ex_ast, js_code) end - should "translate defexception" do + test "translate defexception" do ex_ast = quote do defmodule MyAppError do defexception message: "This is a message" @@ -173,7 +173,7 @@ defmodule ElixirScript.Translator.Struct.Test do end - should "translate raise exception" do + test "translate raise exception" do ex_ast = quote do defmodule MyAppError do defexception [:message] diff --git a/test/translator/try_test.exs b/test/translator/try_test.exs index 553ec286..e8573167 100644 --- a/test/translator/try_test.exs +++ b/test/translator/try_test.exs @@ -1,8 +1,8 @@ defmodule ElixirScript.Translator.Try.Test do - use ShouldI + use ExUnit.Case import ElixirScript.TestHelper - should "translate with a rescue with one match" do + test "translate with a rescue with one match" do ex_ast = quote do try do do_something_that_may_fail(some_arg) @@ -23,7 +23,7 @@ defmodule ElixirScript.Translator.Try.Test do assert_translation(ex_ast, js_code) end - should "translate with a rescue with a list match" do + test "translate with a rescue with a list match" do ex_ast = quote do try do do_something_that_may_fail(some_arg) @@ -44,7 +44,7 @@ defmodule ElixirScript.Translator.Try.Test do assert_translation(ex_ast, js_code) end - should "translate with a rescue with an in guard" do + test "translate with a rescue with an in guard" do ex_ast = quote do try do do_something_that_may_fail(some_arg) @@ -67,7 +67,7 @@ defmodule ElixirScript.Translator.Try.Test do assert_translation(ex_ast, js_code) end - should "translate with a rescue with an identifier" do + test "translate with a rescue with an identifier" do ex_ast = quote do try do do_something_that_may_fail(some_arg) @@ -89,7 +89,7 @@ defmodule ElixirScript.Translator.Try.Test do end - should "translate with a rescue with multiple patterns" do + test "translate with a rescue with multiple patterns" do ex_ast = quote do try do do_something_that_may_fail(some_arg) @@ -114,7 +114,7 @@ defmodule ElixirScript.Translator.Try.Test do assert_translation(ex_ast, js_code) end - should "translate with a rescue and after clause" do + test "translate with a rescue and after clause" do ex_ast = quote do try do do_something_that_may_fail(some_arg) @@ -139,7 +139,7 @@ defmodule ElixirScript.Translator.Try.Test do assert_translation(ex_ast, js_code) end - should "translate with an after clause" do + test "translate with an after clause" do ex_ast = quote do try do do_something_that_may_fail(some_arg) @@ -159,7 +159,7 @@ defmodule ElixirScript.Translator.Try.Test do assert_translation(ex_ast, js_code) end - should "translate else" do + test "translate else" do ex_ast = quote do try do 1 / x @@ -186,7 +186,7 @@ defmodule ElixirScript.Translator.Try.Test do assert_translation(ex_ast, js_code) end - should "translate catch" do + test "translate catch" do ex_ast = quote do try do do_something_that_may_fail(some_arg) diff --git a/test/translator/tuple_test.exs b/test/translator/tuple_test.exs index 33c3abd2..afe44e63 100644 --- a/test/translator/tuple_test.exs +++ b/test/translator/tuple_test.exs @@ -1,35 +1,35 @@ defmodule ElixirScript.Translator.Tuple.Test do - use ShouldI + use ExUnit.Case import ElixirScript.TestHelper - should "translate 2 item tuple" do + test "translate 2 item tuple" do ex_ast = quote do: {1, 2} - js_code = "Elixir.Core.SpecialForms.tuple(1, 2)" + js_code = "new Elixir.Core.Tuple(1, 2)" assert_translation(ex_ast, js_code) end - should "translate multiple item tuple" do + test "translate multiple item tuple" do ex_ast = quote do: {1, 2, 3, 4, 5} - js_code = "Elixir.Core.SpecialForms.tuple(1, 2, 3, 4, 5)" + js_code = "new Elixir.Core.Tuple(1, 2, 3, 4, 5)" assert_translation(ex_ast, js_code) end - should "translate tuples of different typed items" do + test "translate tuples of different typed items" do ex_ast = quote do: {"a", "b", "c"} - js_code = "Elixir.Core.SpecialForms.tuple('a', 'b', 'c')" + js_code = "new Elixir.Core.Tuple('a', 'b', 'c')" assert_translation(ex_ast, js_code) ex_ast = quote do: {:a, :b, :c} - js_code = "Elixir.Core.SpecialForms.tuple(Symbol.for('a'), Symbol.for('b'), Symbol.for('c'))" - + js_code = "new Elixir.Core.Tuple(Symbol.for('a'), Symbol.for('b'), Symbol.for('c'))" + assert_translation(ex_ast, js_code) ex_ast = quote do: {:a, 2, "c"} - js_code = "Elixir.Core.SpecialForms.tuple(Symbol.for('a'), 2, 'c')" + js_code = "new Elixir.Core.Tuple(Symbol.for('a'), 2, 'c')" assert_translation(ex_ast, js_code) end -end \ No newline at end of file +end From c84d8056aef15965272b2c0dd7d6aae5736c1e49 Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Fri, 1 Jan 2016 15:54:26 -0600 Subject: [PATCH 103/860] Fixed raise error when value is an interpolated string --- lib/elixir_script/prelude/map.ex | 4 ++-- lib/elixir_script/translator.ex | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/lib/elixir_script/prelude/map.ex b/lib/elixir_script/prelude/map.ex index 8e5f0b52..6aeb6f16 100644 --- a/lib/elixir_script/prelude/map.ex +++ b/lib/elixir_script/prelude/map.ex @@ -51,7 +51,7 @@ defmodule ElixirScript.Map do true -> map[key] false -> - raise "" + raise "#{key} not found in map" end end @@ -185,7 +185,7 @@ defmodule ElixirScript.Map do true -> Map.put(map, key, func.(map[key])) false -> - raise "" + raise "#{key} not found in map" end end diff --git a/lib/elixir_script/translator.ex b/lib/elixir_script/translator.ex index fc521fa0..36e46350 100644 --- a/lib/elixir_script/translator.ex +++ b/lib/elixir_script/translator.ex @@ -426,7 +426,7 @@ defmodule ElixirScript.Translator do [ Map.make_property(translate!(:__struct__, env), translate!(:RuntimeError, env)), Map.make_property(translate!(:__exception__, env), translate!(true, env)), - Map.make_property(translate!(:message, env), JS.literal(message)) + Map.make_property(translate!(:message, env), translate!(message, env)) ] ) ) From 9f35f4f293a4e382e8566cb6d0322d1522a4307b Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Fri, 1 Jan 2016 16:32:49 -0600 Subject: [PATCH 104/860] stopped using 'default' as variable name. it's a keyword in javascript --- lib/elixir_script/prelude/keyword.ex | 4 ++-- lib/elixir_script/prelude/map.ex | 8 ++++---- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/lib/elixir_script/prelude/keyword.ex b/lib/elixir_script/prelude/keyword.ex index 13751db1..22247563 100644 --- a/lib/elixir_script/prelude/keyword.ex +++ b/lib/elixir_script/prelude/keyword.ex @@ -21,12 +21,12 @@ defmodule ElixirScript.Keyword do get(kw, key, nil) end - def get(kw, key, default) do + def get(kw, key, default_value) do case has_key?(kw, key) do true -> do_get(kw, key) false -> - default + default_value end end diff --git a/lib/elixir_script/prelude/map.ex b/lib/elixir_script/prelude/map.ex index 6aeb6f16..0cdceb13 100644 --- a/lib/elixir_script/prelude/map.ex +++ b/lib/elixir_script/prelude/map.ex @@ -129,12 +129,12 @@ defmodule ElixirScript.Map do get(map, key, nil) end - def get(map, key, default) do + def get(map, key, default_value) do case key in keys(map) do true -> map[key] false -> - default + default_value end end @@ -161,12 +161,12 @@ defmodule ElixirScript.Map do pop(map, key, nil) end - def pop(map, key, default) do + def pop(map, key, default_value) do case key in keys(map) do true -> { map[key], Map.delete(map, key) } false -> - { default, map } + { default_value, map } end end From b251f821a5d14d8bbc6f22d24c02e8066f22b59b Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Fri, 1 Jan 2016 18:18:03 -0600 Subject: [PATCH 105/860] Added JS.import/1. Updated ast output for JS.import to use default import specifier --- lib/elixir_script/lib/js.ex | 15 ++++++++++++++- lib/elixir_script/translator/js.ex | 22 +++++++++++++++++++--- test/elixir_script_test.exs | 8 ++++++++ test/translator/bug_test.exs | 2 +- 4 files changed, 42 insertions(+), 5 deletions(-) diff --git a/lib/elixir_script/lib/js.ex b/lib/elixir_script/lib/js.ex index ae58012b..b59d256a 100644 --- a/lib/elixir_script/lib/js.ex +++ b/lib/elixir_script/lib/js.ex @@ -31,11 +31,24 @@ defmodule ElixirScript.JS do otherwise it is not. ex: - JS.import A, "a" #translates to "import {default as A} from 'a'" + JS.import A, "a" #translates to "import A from 'a'" JS.import [A, B, C], "a" #translates to "import {A, B, C} from 'a'" """ defmacro import(module, from) do end + + @doc """ + Imports a JavaScript module. + + Works like import/2, but tries to infer the path to the module. + Only works for default imports. Uses `Macro.underscore` to infer path. + + ex: + JS.import React #translates to "import React from 'react'" + """ + defmacro import(module) do + end + end diff --git a/lib/elixir_script/translator/js.ex b/lib/elixir_script/translator/js.ex index a9e9fd3c..909bb97a 100644 --- a/lib/elixir_script/translator/js.ex +++ b/lib/elixir_script/translator/js.ex @@ -49,14 +49,30 @@ defmodule ElixirScript.Translator.JS do defp do_translate({:import, _, [module_name, from]}, env) do - import_specifier = Builder.import_specifier( - Builder.identifier("default"), - Translator.translate!(module_name, env) + translated = Translator.translate!(module_name, env) + + import_specifier = Builder.import_default_specifier( + translated, + translated ) build_import_declaration([import_specifier], from) end + defp do_translate({:import, _, [module_name]}, env) do + + translated = Translator.translate!(module_name, env) + + import_specifier = Builder.import_default_specifier( + translated, + translated + ) + + {from, _ } = Code.eval_quoted(module_name) + + build_import_declaration([import_specifier], Macro.underscore(from)) + end + defp build_import_declaration(import_specifiers, from) do Builder.import_declaration( import_specifiers, diff --git a/test/elixir_script_test.exs b/test/elixir_script_test.exs index c204543f..e814f24d 100644 --- a/test/elixir_script_test.exs +++ b/test/elixir_script_test.exs @@ -10,6 +10,14 @@ defmodule ElixirScript.Test do assert Enum.join(js_code, "\n") =~ "JQuery('
').text(html)" end + test "JS.import/1" do + js_code = ElixirScript.compile(""" + JS.import React + """) + + assert Enum.join(js_code, "\n") =~ "import React from 'react'" + end + test "turn javascript ast into javascript code strings" do js_code = ElixirScript.compile(":atom") assert Enum.join(js_code, "\n") =~ "Symbol.for('atom')" diff --git a/test/translator/bug_test.exs b/test/translator/bug_test.exs index 54c2bbd4..4a64c8d2 100644 --- a/test/translator/bug_test.exs +++ b/test/translator/bug_test.exs @@ -46,7 +46,7 @@ defmodule ElixirScript.Translator.Bug.Test do end js_code = """ - import { default as JQuery } from 'jquery'; + import JQuery from 'jquery'; import * as Elixir$ElixirScript$Kernel from './Elixir.ElixirScript.Kernel'; JQuery(Elixir.Core.Functions.call_property(e,'target')); export {}; From 44356bfdff865222f76e2cffd0388776c6a8ef04 Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Fri, 1 Jan 2016 18:19:33 -0600 Subject: [PATCH 106/860] Fixed incorrect alias and removed unused one --- lib/elixir_script/translator/js.ex | 1 - 1 file changed, 1 deletion(-) diff --git a/lib/elixir_script/translator/js.ex b/lib/elixir_script/translator/js.ex index 909bb97a..23b2b804 100644 --- a/lib/elixir_script/translator/js.ex +++ b/lib/elixir_script/translator/js.ex @@ -3,7 +3,6 @@ defmodule ElixirScript.Translator.JS do alias ESTree.Tools.Builder alias ElixirScript.Translator - alias ElixirScript.Translator.Utils @doc false def translate_js_function(name, params, env) do From c91877e5f9d44b8d2f12a035e4e353bfe720b032 Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Fri, 1 Jan 2016 18:20:26 -0600 Subject: [PATCH 107/860] Updated changelog --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 6ec0de54..134a13e6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,7 @@ * `alias`, `require`, and `import` now work inside lexical scopes * `__ENV__` and `__CALLER__` are now supported * Began writing some of the standard libraries in Elixir instead of JavaScript + * Added `JS.import/1` * Breaking * `compile`, `compile_path`, and `compile_quoted` opts parameter now expects a map From 01fa0ef84a64307c2682715d189acaaceec02166 Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Fri, 1 Jan 2016 18:33:29 -0600 Subject: [PATCH 108/860] Refactoring --- lib/elixir_script.ex | 2 +- lib/elixir_script/translator/assignment.ex | 4 +- lib/elixir_script/translator/capture.ex | 4 +- lib/elixir_script/translator/for.ex | 4 +- lib/elixir_script/translator/function.ex | 4 +- .../module_collector.ex} | 2 +- .../pattern_matching.ex} | 2 +- ...tch_test.exs => pattern_matching_test.exs} | 82 +++++++++---------- 8 files changed, 52 insertions(+), 52 deletions(-) rename lib/elixir_script/{preprocess/modules.ex => translator/module_collector.ex} (99%) rename lib/elixir_script/{pattern_matching/match.ex => translator/pattern_matching.ex} (99%) rename test/pattern_matching/{match_test.exs => pattern_matching_test.exs} (57%) diff --git a/lib/elixir_script.ex b/lib/elixir_script.ex index bf080df5..472ef8e8 100644 --- a/lib/elixir_script.ex +++ b/lib/elixir_script.ex @@ -106,7 +106,7 @@ defmodule ElixirScript do defp build_environment(code_list) do code_list - |> ElixirScript.Preprocess.Modules.process_modules + |> ElixirScript.Translator.ModuleCollector.process_modules end defp updated_quoted(quoted) do diff --git a/lib/elixir_script/translator/assignment.ex b/lib/elixir_script/translator/assignment.ex index 7d9f2ed8..57e3b1c7 100644 --- a/lib/elixir_script/translator/assignment.ex +++ b/lib/elixir_script/translator/assignment.ex @@ -2,13 +2,13 @@ defmodule ElixirScript.Translator.Assignment do @moduledoc false alias ESTree.Tools.Builder, as: JS alias ElixirScript.Translator - alias ElixirScript.PatternMatching.Match + alias ElixirScript.Translator.PatternMatching alias ElixirScript.Translator.Primitive def make_assignment(left, right, env) do { right_ast, env } = Translator.translate(right, env) - { patterns, params, env } = Match.process_match([left], env) + { patterns, params, env } = PatternMatching.process_match([left], env) declarator = JS.variable_declarator( JS.array_pattern(params), diff --git a/lib/elixir_script/translator/capture.ex b/lib/elixir_script/translator/capture.ex index 07d631c1..6aaaebfd 100644 --- a/lib/elixir_script/translator/capture.ex +++ b/lib/elixir_script/translator/capture.ex @@ -2,7 +2,7 @@ defmodule ElixirScript.Translator.Capture do @moduledoc false alias ESTree.Tools.Builder, as: JS - alias ElixirScript.PatternMatching.Match + alias ElixirScript.Translator.PatternMatching alias ElixirScript.Translator.Function def make_capture(function_name, arity, env) do @@ -44,7 +44,7 @@ defmodule ElixirScript.Translator.Capture do defp process_params(arity, env) do params = Enum.map(1..arity, fn(x) -> {String.to_atom("__#{x}"), [], ElixirScript.Translator.Capture} end) - Match.process_match(params, env) + PatternMatching.process_match(params, env) end defp make_capture_function(patterns, params, body) do diff --git a/lib/elixir_script/translator/for.ex b/lib/elixir_script/translator/for.ex index 02b50a29..40d0d24a 100644 --- a/lib/elixir_script/translator/for.ex +++ b/lib/elixir_script/translator/for.ex @@ -2,7 +2,7 @@ defmodule ElixirScript.Translator.For do @moduledoc false alias ESTree.Tools.Builder, as: JS alias ElixirScript.Translator - alias ElixirScript.PatternMatching.Match + alias ElixirScript.Translator.PatternMatching alias ElixirScript.Translator.Primitive alias ElixirScript.Translator.Function @@ -29,7 +29,7 @@ defmodule ElixirScript.Translator.For do defp handle_args(generators, env) do Enum.reduce(generators, %{collections: [], args: [], filter: nil, fun: nil, into: nil}, fn ({:<-, [], [identifier, enum]}, state) -> - { patterns, params, env } = Match.process_match([identifier], env) + { patterns, params, env } = PatternMatching.process_match([identifier], env) list = Primitive.make_list_no_translate([hd(patterns), Translator.translate!(enum, env)]) diff --git a/lib/elixir_script/translator/function.ex b/lib/elixir_script/translator/function.ex index ca55447f..5071d744 100644 --- a/lib/elixir_script/translator/function.ex +++ b/lib/elixir_script/translator/function.ex @@ -3,7 +3,7 @@ defmodule ElixirScript.Translator.Function do alias ESTree.Tools.Builder, as: JS alias ElixirScript.Translator alias ElixirScript.Translator.Utils - alias ElixirScript.PatternMatching.Match + alias ElixirScript.Translator.PatternMatching @patterns JS.member_expression( JS.member_expression( @@ -96,7 +96,7 @@ defmodule ElixirScript.Translator.Function do defp process_params(params, env) do params = wrap_params(params) - { patterns, params, env } = Match.process_match(params, env) + { patterns, params, env } = PatternMatching.process_match(params, env) { patterns, make_params(params), env } end diff --git a/lib/elixir_script/preprocess/modules.ex b/lib/elixir_script/translator/module_collector.ex similarity index 99% rename from lib/elixir_script/preprocess/modules.ex rename to lib/elixir_script/translator/module_collector.ex index 1f035118..912f09e7 100644 --- a/lib/elixir_script/preprocess/modules.ex +++ b/lib/elixir_script/translator/module_collector.ex @@ -1,4 +1,4 @@ -defmodule ElixirScript.Preprocess.Modules do +defmodule ElixirScript.Translator.ModuleCollector do @moduledoc false alias ElixirScript.Translator.State diff --git a/lib/elixir_script/pattern_matching/match.ex b/lib/elixir_script/translator/pattern_matching.ex similarity index 99% rename from lib/elixir_script/pattern_matching/match.ex rename to lib/elixir_script/translator/pattern_matching.ex index bdddc737..4d8c55c5 100644 --- a/lib/elixir_script/pattern_matching/match.ex +++ b/lib/elixir_script/translator/pattern_matching.ex @@ -1,4 +1,4 @@ -defmodule ElixirScript.PatternMatching.Match do +defmodule ElixirScript.Translator.PatternMatching do @moduledoc false alias ESTree.Tools.Builder, as: JS diff --git a/test/pattern_matching/match_test.exs b/test/pattern_matching/pattern_matching_test.exs similarity index 57% rename from test/pattern_matching/match_test.exs rename to test/pattern_matching/pattern_matching_test.exs index 44c73a76..9e0dca5c 100644 --- a/test/pattern_matching/match_test.exs +++ b/test/pattern_matching/pattern_matching_test.exs @@ -1,32 +1,32 @@ -defmodule ElixirScript.PatternMatching.Match.Test do +defmodule ElixirScript.Translator.PatternMatching.Test do use ExUnit.Case alias ElixirScript.Translator alias ElixirScript.Translator.Primitive - alias ElixirScript.PatternMatching.Match + alias ElixirScript.Translator.PatternMatching alias ElixirScript.Translator.Map alias ESTree.Tools.Builder, as: JS # test "match wildcard" do # params = [{:_, [], Test}] -# result = Match.build_match(params, ElixirScript.Translator.Env.module_env(ElixirScript.Temp, "temp.ex") ) -# expected_result = { [Match.wildcard], [JS.identifier(:undefined)] } +# result = PatternMatching.build_match(params, ElixirScript.Translator.Env.module_env(ElixirScript.Temp, "temp.ex") ) +# expected_result = { [PatternMatching.wildcard], [JS.identifier(:undefined)] } # # assert result == expected_result # end # # test "match one identifier param" do # params = [{:a, [], Test}] -# result = Match.build_match(params, ElixirScript.Translator.Env.module_env(ElixirScript.Temp, "temp.ex") ) -# expected_result = {[Match.parameter], [JS.identifier("a")]} +# result = PatternMatching.build_match(params, ElixirScript.Translator.Env.module_env(ElixirScript.Temp, "temp.ex") ) +# expected_result = {[PatternMatching.parameter], [JS.identifier("a")]} # # assert result == expected_result # end # # test "match multiple identifier params" do # params = [{:a, [], Test}, {:b, [], Test}, {:c, [], Test}] -# result = Match.build_match(params, ElixirScript.Translator.Env.module_env(ElixirScript.Temp, "temp.ex") ) +# result = PatternMatching.build_match(params, ElixirScript.Translator.Env.module_env(ElixirScript.Temp, "temp.ex") ) # expected_result = { -# List.duplicate(Match.parameter, 3), +# List.duplicate(PatternMatching.parameter, 3), # [JS.identifier("a"), JS.identifier("b"), JS.identifier("c")] # } # @@ -35,9 +35,9 @@ defmodule ElixirScript.PatternMatching.Match.Test do # # test "match head and tail param" do # params = [[{:|, [], [{:head, [], Elixir}, {:tail, [], Elixir}]}]] -# result = Match.build_match(params, ElixirScript.Translator.Env.module_env(ElixirScript.Temp, "temp.ex") ) +# result = PatternMatching.build_match(params, ElixirScript.Translator.Env.module_env(ElixirScript.Temp, "temp.ex") ) # expected_result = { -# [Match.head_tail], +# [PatternMatching.head_tail], # [JS.identifier("head"), JS.identifier("tail")] # } # @@ -46,9 +46,9 @@ defmodule ElixirScript.PatternMatching.Match.Test do # # test "match prefix param" do # params = [{:<>, [context: Elixir, import: Elixir.Kernel], ["Bearer ", {:token, [], Elixir}]}] -# result = Match.build_match(params, ElixirScript.Translator.Env.module_env(ElixirScript.Temp, "temp.ex") ) +# result = PatternMatching.build_match(params, ElixirScript.Translator.Env.module_env(ElixirScript.Temp, "temp.ex") ) # expected_result = { -# [Match.starts_with("Bearer ")], +# [PatternMatching.starts_with("Bearer ")], # [JS.identifier("token")] # } # @@ -57,9 +57,9 @@ defmodule ElixirScript.PatternMatching.Match.Test do # # test "match list" do # params = [[{:a, [], Elixir}, {:b, [], Elixir}, {:c, [], Elixir}]] -# result = Match.build_match(params, ElixirScript.Translator.Env.module_env(ElixirScript.Temp, "temp.ex") ) +# result = PatternMatching.build_match(params, ElixirScript.Translator.Env.module_env(ElixirScript.Temp, "temp.ex") ) # expected_result = { -# [Primitive.make_list_no_translate(List.duplicate(Match.parameter, 3))], +# [Primitive.make_list_no_translate(List.duplicate(PatternMatching.parameter, 3))], # [JS.identifier("a"), JS.identifier("b"), JS.identifier("c")] # } # @@ -68,9 +68,9 @@ defmodule ElixirScript.PatternMatching.Match.Test do # # test "match list with a literal" do # params = [[1, {:b, [], Elixir}, {:c, [], Elixir}]] -# result = Match.build_match(params, ElixirScript.Translator.Env.module_env(ElixirScript.Temp, "temp.ex") ) +# result = PatternMatching.build_match(params, ElixirScript.Translator.Env.module_env(ElixirScript.Temp, "temp.ex") ) # expected_result = { -# [Primitive.make_list_no_translate([JS.literal(1), Match.parameter, Match.parameter])], +# [Primitive.make_list_no_translate([JS.literal(1), PatternMatching.parameter, PatternMatching.parameter])], # [JS.identifier("b"), JS.identifier("c")] # } # @@ -79,7 +79,7 @@ defmodule ElixirScript.PatternMatching.Match.Test do # # test "match number" do # params = [1] -# result = Match.build_match(params, ElixirScript.Translator.Env.module_env(ElixirScript.Temp, "temp.ex") ) +# result = PatternMatching.build_match(params, ElixirScript.Translator.Env.module_env(ElixirScript.Temp, "temp.ex") ) # expected_result = { # [JS.literal(1)], # [] @@ -92,9 +92,9 @@ defmodule ElixirScript.PatternMatching.Match.Test do # ElixirScript.Translator.State.start_link(nil, nil) # # params = [{:%, [], [{:__aliases__, [alias: false], [:Hello]}, {:%{}, [], []}]}] -# result = Match.build_match(params, ElixirScript.Translator.Env.module_env(ElixirScript.Temp, "temp.ex") ) +# result = PatternMatching.build_match(params, ElixirScript.Translator.Env.module_env(ElixirScript.Temp, "temp.ex") ) # expected_result = { -# [Match.type(JS.identifier(:Hello), JS.object_expression([]))], +# [PatternMatching.type(JS.identifier(:Hello), JS.object_expression([]))], # [] # } # @@ -107,9 +107,9 @@ defmodule ElixirScript.PatternMatching.Match.Test do # ElixirScript.Translator.State.start_link(nil, nil) # # params = [{:%, [], [{:__aliases__, [alias: false], [:Hello]}, {:%{}, [], [key: 1]}]}] -# result = Match.build_match(params, ElixirScript.Translator.Env.module_env(ElixirScript.Temp, "temp.ex") ) +# result = PatternMatching.build_match(params, ElixirScript.Translator.Env.module_env(ElixirScript.Temp, "temp.ex") ) # expected_result = { -# [Match.type(JS.identifier(:Hello), JS.object_expression([ +# [PatternMatching.type(JS.identifier(:Hello), JS.object_expression([ # Map.make_property(Translator.translate!(:key, ElixirScript.Translator.Env.module_env(ElixirScript.Temp, "temp.ex") ), Translator.translate!(1, ElixirScript.Translator.Env.module_env(ElixirScript.Temp, "temp.ex") )) # ])) # ], @@ -125,10 +125,10 @@ defmodule ElixirScript.PatternMatching.Match.Test do # ElixirScript.Translator.State.start_link(nil, nil) # # params = [{:%, [], [{:__aliases__, [alias: false], [:Hello]}, {:%{}, [], [key: {:key, [], Elixir }]}]}] -# result = Match.build_match(params, ElixirScript.Translator.Env.module_env(ElixirScript.Temp, "temp.ex") ) +# result = PatternMatching.build_match(params, ElixirScript.Translator.Env.module_env(ElixirScript.Temp, "temp.ex") ) # expected_result = { -# [Match.type(JS.identifier(:Hello), JS.object_expression([ -# Map.make_property(Translator.translate!(:key, ElixirScript.Translator.Env.module_env(ElixirScript.Temp, "temp.ex") ), Match.parameter) +# [PatternMatching.type(JS.identifier(:Hello), JS.object_expression([ +# Map.make_property(Translator.translate!(:key, ElixirScript.Translator.Env.module_env(ElixirScript.Temp, "temp.ex") ), PatternMatching.parameter) # ])) # ], # [JS.identifier("key")] @@ -144,9 +144,9 @@ defmodule ElixirScript.PatternMatching.Match.Test do # ElixirScript.Translator.State.start_link(nil, nil) # # params = [{:=, [], [1, {:a, [], Elixir}]}] -# result = Match.build_match(params, ElixirScript.Translator.Env.module_env(ElixirScript.Temp, "temp.ex") ) +# result = PatternMatching.build_match(params, ElixirScript.Translator.Env.module_env(ElixirScript.Temp, "temp.ex") ) # expected_result = { -# [Match.capture(JS.literal(1))], +# [PatternMatching.capture(JS.literal(1))], # [JS.identifier("a")] # } # @@ -154,9 +154,9 @@ defmodule ElixirScript.PatternMatching.Match.Test do # # # params = [{:=, [], [{:a, [], Elixir}, 1]}] -# result = Match.build_match(params, ElixirScript.Translator.Env.module_env(ElixirScript.Temp, "temp.ex") ) +# result = PatternMatching.build_match(params, ElixirScript.Translator.Env.module_env(ElixirScript.Temp, "temp.ex") ) # expected_result = { -# [Match.capture(JS.literal(1))], +# [PatternMatching.capture(JS.literal(1))], # [JS.identifier("a")] # } # @@ -164,9 +164,9 @@ defmodule ElixirScript.PatternMatching.Match.Test do # # # params = [{:=, [], [{:%, [], [{:__aliases__, [alias: false], [:AStruct]}, {:%{}, [], []}]}, {:a, [], ElixirScript.Translator.Function.Test}]}] -# result = Match.build_match(params, ElixirScript.Translator.Env.module_env(ElixirScript.Temp, "temp.ex") ) +# result = PatternMatching.build_match(params, ElixirScript.Translator.Env.module_env(ElixirScript.Temp, "temp.ex") ) # expected_result = { -# [Match.capture(Match.type(JS.identifier(:AStruct), JS.object_expression([])))], +# [PatternMatching.capture(PatternMatching.type(JS.identifier(:AStruct), JS.object_expression([])))], # [JS.identifier("a")] # } # @@ -177,9 +177,9 @@ defmodule ElixirScript.PatternMatching.Match.Test do # # test "match and assign list" do # params = [{:=, [], [[{:a, [], Elixir}, {:b, [], Elixir}, {:c, [], Elixir}], {:d, [], Elixir}]}] -# result = Match.build_match(params, ElixirScript.Translator.Env.module_env(ElixirScript.Temp, "temp.ex") ) +# result = PatternMatching.build_match(params, ElixirScript.Translator.Env.module_env(ElixirScript.Temp, "temp.ex") ) # expected_result = { -# [Match.capture(Primitive.make_list_no_translate([Match.parameter, Match.parameter, Match.parameter]))], +# [PatternMatching.capture(Primitive.make_list_no_translate([PatternMatching.parameter, PatternMatching.parameter, PatternMatching.parameter]))], # [JS.identifier("a"), JS.identifier("b"), JS.identifier("c"), JS.identifier("d")] # } # @@ -188,11 +188,11 @@ defmodule ElixirScript.PatternMatching.Match.Test do # # test "match on tuple" do # params = [{:{}, [], [1, {:b, [], Elixir}, 3]}] -# result = Match.build_match(params, ElixirScript.Translator.Env.module_env(ElixirScript.Temp, "temp.ex") ) +# result = PatternMatching.build_match(params, ElixirScript.Translator.Env.module_env(ElixirScript.Temp, "temp.ex") ) # expected_result = { -# [Match.type(Primitive.tuple_class, JS.object_expression([JS.property( +# [PatternMatching.type(Primitive.tuple_class, JS.object_expression([JS.property( # JS.identifier("values"), -# JS.array_expression([JS.literal(1), Match.parameter, JS.literal(3)]) +# JS.array_expression([JS.literal(1), PatternMatching.parameter, JS.literal(3)]) # ) ] )) ], # [JS.identifier("b")] # } @@ -200,11 +200,11 @@ defmodule ElixirScript.PatternMatching.Match.Test do # assert result == expected_result # # params = [{1, {:b, [], Elixir}}] -# result = Match.build_match(params, ElixirScript.Translator.Env.module_env(ElixirScript.Temp, "temp.ex") ) +# result = PatternMatching.build_match(params, ElixirScript.Translator.Env.module_env(ElixirScript.Temp, "temp.ex") ) # expected_result = { -# [Match.type(Primitive.tuple_class, JS.object_expression([JS.property( +# [PatternMatching.type(Primitive.tuple_class, JS.object_expression([JS.property( # JS.identifier("values"), -# JS.array_expression([JS.literal(1), Match.parameter]) +# JS.array_expression([JS.literal(1), PatternMatching.parameter]) # ) ] )) ], # [JS.identifier("b")] # } @@ -214,7 +214,7 @@ defmodule ElixirScript.PatternMatching.Match.Test do # # test "match on map" do # params = [{:%{}, [], [which: 13]}] -# result = Match.build_match(params, ElixirScript.Translator.Env.module_env(ElixirScript.Temp, "temp.ex") ) +# result = PatternMatching.build_match(params, ElixirScript.Translator.Env.module_env(ElixirScript.Temp, "temp.ex") ) # # expected_result = { # [JS.object_expression([ @@ -229,10 +229,10 @@ defmodule ElixirScript.PatternMatching.Match.Test do # # test "match on bound value" do # params = [{:^, [], [{:a, [], Elixir}]}] -# result = Match.build_match(params, ElixirScript.Translator.Env.module_env(ElixirScript.Temp, "temp.ex") ) +# result = PatternMatching.build_match(params, ElixirScript.Translator.Env.module_env(ElixirScript.Temp, "temp.ex") ) # # expected_result = { -# [Match.bound(JS.identifier("a"))], +# [PatternMatching.bound(JS.identifier("a"))], # [nil] # } # From d29fa881247ce5c82203fbe17c703800ce46db5a Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Fri, 1 Jan 2016 18:51:55 -0600 Subject: [PATCH 109/860] Moved modules in lib folder into prelude --- lib/elixir_script/{lib => prelude}/html.ex | 0 lib/elixir_script/{lib => prelude}/js.ex | 0 lib/elixir_script/{lib => prelude}/tags.txt | 0 lib/elixir_script/{lib => prelude}/v_dom.ex | 0 lib/elixir_script/translator/state.ex | 3 +++ test/{lib => prelude}/js_test.exs | 0 test/{lib => prelude}/kernel_test.exs | 0 .../{pattern_matching => translator}/pattern_matching_test.exs | 0 8 files changed, 3 insertions(+) rename lib/elixir_script/{lib => prelude}/html.ex (100%) rename lib/elixir_script/{lib => prelude}/js.ex (100%) rename lib/elixir_script/{lib => prelude}/tags.txt (100%) rename lib/elixir_script/{lib => prelude}/v_dom.ex (100%) rename test/{lib => prelude}/js_test.exs (100%) rename test/{lib => prelude}/kernel_test.exs (100%) rename test/{pattern_matching => translator}/pattern_matching_test.exs (100%) diff --git a/lib/elixir_script/lib/html.ex b/lib/elixir_script/prelude/html.ex similarity index 100% rename from lib/elixir_script/lib/html.ex rename to lib/elixir_script/prelude/html.ex diff --git a/lib/elixir_script/lib/js.ex b/lib/elixir_script/prelude/js.ex similarity index 100% rename from lib/elixir_script/lib/js.ex rename to lib/elixir_script/prelude/js.ex diff --git a/lib/elixir_script/lib/tags.txt b/lib/elixir_script/prelude/tags.txt similarity index 100% rename from lib/elixir_script/lib/tags.txt rename to lib/elixir_script/prelude/tags.txt diff --git a/lib/elixir_script/lib/v_dom.ex b/lib/elixir_script/prelude/v_dom.ex similarity index 100% rename from lib/elixir_script/lib/v_dom.ex rename to lib/elixir_script/prelude/v_dom.ex diff --git a/lib/elixir_script/translator/state.ex b/lib/elixir_script/translator/state.ex index 1fee0366..0daf0d29 100644 --- a/lib/elixir_script/translator/state.ex +++ b/lib/elixir_script/translator/state.ex @@ -29,6 +29,9 @@ defmodule ElixirScript.Translator.State do |> Map.put(Bitwise, ElixirScript.Bitwise) |> Map.put(MapSet, ElixirScript.MapSet) |> Map.put(List, ElixirScript.List) + |> Map.put(JS, ElixirScript.JS) + |> Map.put(VDom, ElixirScript.VDom) + |> Map.put(Html, ElixirScript.Html) end def add_module(module) do diff --git a/test/lib/js_test.exs b/test/prelude/js_test.exs similarity index 100% rename from test/lib/js_test.exs rename to test/prelude/js_test.exs diff --git a/test/lib/kernel_test.exs b/test/prelude/kernel_test.exs similarity index 100% rename from test/lib/kernel_test.exs rename to test/prelude/kernel_test.exs diff --git a/test/pattern_matching/pattern_matching_test.exs b/test/translator/pattern_matching_test.exs similarity index 100% rename from test/pattern_matching/pattern_matching_test.exs rename to test/translator/pattern_matching_test.exs From 750c5b3610687d0474ec8c8b9207d97c77c40bdf Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Sat, 2 Jan 2016 09:54:37 -0600 Subject: [PATCH 110/860] Removed functions from Core. Removed kernel.js and kernel/special_forms.js --- lib/elixir_script/prelude/kernel.ex | 56 ++-- lib/elixir_script/translator.ex | 16 +- lib/elixir_script/translator/function.ex | 14 + lib/elixir_script/translator/primitive.ex | 4 - priv/Elixir.js | 352 ++------------------- src/javascript/elixir.js | 1 - src/javascript/lib/core.js | 3 +- src/javascript/lib/core/functions.js | 198 +----------- src/javascript/lib/core/primitives.js | 6 +- src/javascript/lib/core/special_forms.js | 5 - src/javascript/lib/kernel.js | 178 ----------- src/javascript/lib/kernel/special_forms.js | 173 ---------- src/javascript/tests/bit_string.spec.js | 26 +- src/javascript/tests/kernel.spec.js | 53 ---- src/javascript/tests/try.spec.js | 1 - test/translator/list_test.exs | 10 +- 16 files changed, 120 insertions(+), 976 deletions(-) delete mode 100644 src/javascript/lib/kernel.js delete mode 100644 src/javascript/lib/kernel/special_forms.js delete mode 100644 src/javascript/tests/kernel.spec.js diff --git a/lib/elixir_script/prelude/kernel.ex b/lib/elixir_script/prelude/kernel.ex index 0940b3a2..8b20a77f 100644 --- a/lib/elixir_script/prelude/kernel.ex +++ b/lib/elixir_script/prelude/kernel.ex @@ -1,6 +1,6 @@ defmodule ElixirScript.Kernel do import Kernel, only: [defmodule: 2, def: 1, def: 2, defp: 2, - defmacro: 1, defmacro: 2, defmacrop: 2, ||: 2, !: 1, ++: 2, in: 2, &&: 2] + defmacro: 1, defmacro: 2, defmacrop: 2, ||: 2, !: 1, ++: 2, in: 2, &&: 2, ===: 2] defmacro if(condition, clauses) do build_if(condition, clauses) @@ -60,64 +60,84 @@ defmodule ElixirScript.Kernel do list.slice(1) end + def get_type(term) do + Elixir.Core.Functions.get_type(term) + end + + def is_instance_of(term, type) do + Elixir.Core.Functions.is_instance_of(term, type) + end + + def global() do + Elixir.Core.Functions.get_global() + end + def is_atom(term) do - Elixir.Core.Functions.is_atom(term) + get_type(term) === 'symbol' end def is_binary(term) do - Elixir.Core.Functions.is_binary(term) + get_type(term) === 'string' end def is_bitstring(term) do - Elixir.Core.Functions.is_bitstring(term) + is_binary(term) || is_instance_of(term, Elixir.Core.BitString) end def is_boolean(term) do - Elixir.Core.Functions.is_boolean(term) + get_type(term) === 'boolean' || is_instance_of(term, Boolean) end def is_float(term) do - Elixir.Core.Functions.is_float(term) + is_number(term) && !Number.isInteger(term) end def is_function(term) do - Elixir.Core.Functions.is_function(term) + is_function(term, 0) end - def is_function(term, arity) do - Elixir.Core.Functions.is_function(term, arity) + def is_function(term, _) do + get_type(term) === 'function' || is_instance_of(term, Function) end def is_integer(term) do - Elixir.Core.Functions.is_integer(term) + Number.isInteger(term) end def is_list(term) do - Elixir.Core.Functions.is_list(term) + Array.isArray(term) end def is_number(term) do - Elixir.Core.Functions.is_integer(term) || Elixir.Core.Functions.is_float(term) + get_type(term) === 'number' || is_instance_of(term, Number) end def is_pid(term) do - Elixir.Core.Functions.is_pid(term) + is_instance_of(term, Elixir.Core.PID) end def is_tuple(term) do - Elixir.Core.Functions.is_tuple(term) + is_instance_of(term, Elixir.Core.Tuple) end def is_map(term) do - Elixir.Core.Functions.is_map(term) + get_type(term) === 'object' || is_instance_of(term, Object) + end + + def is_port(_) do + false + end + + def is_reference(_) do + false end def length(term) do - Elixir.Core.Functions.size(term) + term.length end def map_size(term) do - Elixir.Core.Functions.size(Object.keys(term)) + Object.keys(term).length end def max(first, second) do @@ -145,7 +165,7 @@ defmodule ElixirScript.Kernel do end def is_nil(term) do - Elixir.Core.Functions.is_nil(term) + term === nil end defmacro match?(left, right) do diff --git a/lib/elixir_script/translator.ex b/lib/elixir_script/translator.ex index 36e46350..6176fba9 100644 --- a/lib/elixir_script/translator.ex +++ b/lib/elixir_script/translator.ex @@ -50,6 +50,14 @@ defmodule ElixirScript.Translator do translate(quoted, env) end + defp do_translate([ {:|, _, [left, right] } ], env) do + quoted = quote do + [unquote(left)].concat(unquote(right)) + end + + translate(quoted, env) + end + defp do_translate(ast, env) when is_list(ast) do Primitive.make_list(ast, env) end @@ -100,11 +108,7 @@ defmodule ElixirScript.Translator do end defp do_translate({:++, _, [left, right]}, env) do - quoted = quote do - Elixir.Core.Functions.concat_lists(unquote(left),unquote(right)) - end - - translate(quoted, env) + translate({{:., [], [left, :concat]}, [], [right]}, env) end defp do_translate({:&, _, [number]}, env) when is_number(number) do @@ -406,7 +410,7 @@ defmodule ElixirScript.Translator do defp do_translate({:|, _, [item, list]}, env) do quoted = quote do - Elixir.Core.prepend_to_list(unquote(list), unquote(item)) + [unquote(item)].concat(unquote(list)) end translate(quoted, env) diff --git a/lib/elixir_script/translator/function.ex b/lib/elixir_script/translator/function.ex index 5071d744..1a620c86 100644 --- a/lib/elixir_script/translator/function.ex +++ b/lib/elixir_script/translator/function.ex @@ -153,6 +153,8 @@ defmodule ElixirScript.Translator.Function do ast {{:., _, [{:__aliases__, _, _}]}, _, _} = ast -> ast + ast when is_list(ast) -> + ast name -> get_js_name(name, env) end @@ -166,6 +168,18 @@ defmodule ElixirScript.Translator.Function do { Utils.make_call_expression(Utils.filter_name(function_name), params, env), env } end + def make_function_call(module_name, function_name, params, env) when is_list(module_name) do + call = JS.call_expression( + JS.member_expression( + Translator.translate!(module_name, env), + JS.identifier(Utils.filter_name(function_name)) + ), + Enum.map(params, &Translator.translate!(&1, env)) + ) + + { call, env } + end + def make_function_call(module_name, function_name, params, env) do the_name = get_module_name_for_function(module_name, env) { Utils.make_call_expression(the_name, Utils.filter_name(function_name), params, env), env } diff --git a/lib/elixir_script/translator/primitive.ex b/lib/elixir_script/translator/primitive.ex index 718fa8c7..3c8ac68b 100644 --- a/lib/elixir_script/translator/primitive.ex +++ b/lib/elixir_script/translator/primitive.ex @@ -78,10 +78,6 @@ defmodule ElixirScript.Translator.Primitive do ) end - def make_list([{:|, _, [_, _]} = ast], env) do - Translator.translate(ast, env) - end - def make_list(ast, env) when is_list(ast) do list = Enum.map(ast, &Translator.translate!(&1, env)) diff --git a/priv/Elixir.js b/priv/Elixir.js index 4f45feac..0a5c99b9 100644 --- a/priv/Elixir.js +++ b/priv/Elixir.js @@ -619,7 +619,7 @@ function bound(value) { return new Bound(value); } -function is_number$2(value) { +function is_number(value) { return typeof value === 'number'; } @@ -627,7 +627,7 @@ function is_string(value) { return typeof value === 'string'; } -function is_boolean$2(value) { +function is_boolean(value) { return typeof value === 'boolean'; } @@ -643,7 +643,7 @@ function is_undefined(value) { return typeof value === 'undefined'; } -function is_function$2(value) { +function is_function(value) { return Object.prototype.toString.call(value) == '[object Function]'; } @@ -684,13 +684,13 @@ function is_array(value) { } var Checks = { - is_number: is_number$2, + is_number, is_string, - is_boolean: is_boolean$2, + is_boolean, is_symbol, is_null, is_undefined, - is_function: is_function$2, + is_function, is_variable, is_wildcard, is_headTail, @@ -1033,95 +1033,7 @@ function call_property(item, property) { throw new Error(`Property ${ property } not found in ${ item }`); } -function is_instance_of(value, type) { - return value instanceof type; -} - -function size(term) { - return term.length; -} - -function is_nil$1(x) { - return x === null; -} - -function is_atom$1(x) { - return typeof x === 'symbol'; -} - -function is_binary$1(x) { - return typeof x === 'string' || x instanceof String; -} - -function is_boolean$1(x) { - return typeof x === 'boolean' || x instanceof Boolean; -} - -function is_function$1(x, arity = -1) { - return typeof x === 'function' || x instanceof Function; -} - -function is_float$1(x) { - return is_number$1(x) && !Number.isInteger(x); -} - -function is_integer$1(x) { - return Number.isInteger(x); -} - -function is_list$1(x) { - return x instanceof Array; -} - -function is_map$1(x) { - return typeof x === 'object' || x instanceof Object; -} - -function is_number$1(x) { - return typeof x === 'number'; -} - -function is_tuple$1(x) { - return x instanceof Tuple; -} - -function is_pid$1(x) { - return x instanceof PID; -} - -function is_port$1(x) { - return false; -} - -function is_reference$1(x) { - return false; -} - -function is_bitstring$1(x) { - return is_binary$1(x) || x instanceof BitString; -} - -function add(one, two) { - return one + two; -} - -function subtract(one, two) { - return one + two; -} - -function multiply(one, two) { - return one + two; -} - -function divide(one, two) { - return one + two; -} - -function remainder(one, two) { - return one + two; -} - -function apply$1(...args) { +function apply(...args) { if (args.length === 2) { args[0].apply(null, args.slice(1)); } else { @@ -1129,20 +1041,6 @@ function apply$1(...args) { } } -function new_tuple(...args) { - return new Tuple(...args); -} - -function duplicate(data, size) { - let array = []; - - for (var i = size - 1; i >= 0; i--) { - array.push(data); - } - - return array; -} - function contains(left, right) { for (let x of right) { if (Patterns.match_no_throw(left, x) != null) { @@ -1153,10 +1051,6 @@ function contains(left, right) { return false; } -function reverse(list) { - return list.concat([]).reverse(); -} - function get_global() { if (typeof self !== 'undefined') { return self; @@ -1169,14 +1063,6 @@ function get_global() { throw new Error('No global state found'); } -function concat_lists(left, right) { - return left.concat(right); -} - -function prepend_to_list(list, item) { - return [item].concat(list); -} - function defstruct(defaults) { return class { constructor(update = {}) { @@ -1308,38 +1194,20 @@ function zip(list_of_lists) { return Object.freeze(new_value); } +function can_decode64(data) { + try { + atob(data); + return true; + } catch (e) { + return false; + } +} + var Functions = { call_property, - is_instance_of, - size, - is_nil: is_nil$1, - is_atom: is_atom$1, - is_binary: is_binary$1, - is_boolean: is_boolean$1, - is_function: is_function$1, - is_float: is_float$1, - is_integer: is_integer$1, - is_list: is_list$1, - is_map: is_map$1, - is_number: is_number$1, - is_tuple: is_tuple$1, - is_pid: is_pid$1, - is_port: is_port$1, - is_reference: is_reference$1, - is_bitstring: is_bitstring$1, - add, - subtract, - multiply, - divide, - remainder, - apply: apply$1, - new_tuple, - duplicate, + apply, contains, - reverse, get_global, - concat_lists, - prepend_to_list, defstruct, defexception, defprotocol, @@ -1350,6 +1218,7 @@ var Functions = { delete_property_from_map, add_property_to_map, class_to_obj, + can_decode64, bnot, band, bor, @@ -1475,7 +1344,7 @@ function _try(do_fun, rescue_function, catch_fun, else_function, after_function) } } -var SpecialForms$1 = { +var special_forms = { list, bitstring, tuple, @@ -1501,186 +1370,9 @@ var C = Object.freeze({ Float: Float, Functions: Functions, List: List, - SpecialForms: SpecialForms$1 + SpecialForms: special_forms }); -function tl(list) { - return SpecialForms$1.list(...list.slice(1)); -} - -function hd(list) { - return list[0]; -} - -function is_nil(x) { - return x === null; -} - -function is_atom(x) { - return typeof x === 'symbol'; -} - -function is_binary(x) { - return typeof x === 'string' || x instanceof String; -} - -function is_boolean(x) { - return typeof x === 'boolean' || x instanceof Boolean; -} - -function is_function(x, arity = -1) { - return typeof x === 'function' || x instanceof Function; -} - -function is_float(x) { - return is_number(x) && !Number.isInteger(x); -} - -function is_integer(x) { - return Number.isInteger(x); -} - -function is_list(x) { - return x instanceof Array; -} - -function is_map(x) { - return typeof x === 'object' || x instanceof Object; -} - -function is_number(x) { - return typeof x === 'number'; -} - -function is_tuple(x) { - return x instanceof Tuple; -} - -function length(x) { - return x.length; -} - -function is_pid(x) { - return x instanceof PID; -} - -function is_port(x) { - return false; -} - -function is_reference(x) { - return false; -} - -function is_bitstring(x) { - return is_binary(x) || x instanceof BitString; -} - -function __in__(left, right) { - for (let x of right) { - if (match__qmark__(left, x)) { - return true; - } - } - - return false; -} - -function abs(number) { - return Math.abs(number); -} - -function round(number) { - return Math.round(number); -} - -function elem(tuple, index) { - if (is_list(tuple)) { - return tuple[index]; - } - - return tuple.get(index); -} - -function rem(left, right) { - return left % right; -} - -function div(left, right) { - return left / right; -} - -function and(left, right) { - return left && right; -} - -function or(left, right) { - return left || right; -} - -function not(arg) { - return !arg; -} - -function apply(...args) { - if (args.length === 3) { - let mod = args[0]; - let func = args[1]; - let func_args = args[2]; - return mod[func].apply(null, func_args); - } else { - let func = args[0]; - let func_args = args[1]; - - return func.apply(null, func_args); - } -} - -function to_string(arg) { - if (is_tuple(arg)) { - return arg.toString(); - } - - return arg.toString(); -} - -function match__qmark__(pattern, expr, guard = () => true) { - return Patterns.match_no_throw(pattern, expr, guard) != null; -} - -var kernel = { - tl, - hd, - is_nil, - is_atom, - is_binary, - is_boolean, - is_function, - is_float, - is_integer, - is_list, - is_map, - is_number, - is_tuple, - length, - is_pid, - is_port, - is_reference, - is_bitstring, - in: __in__, - abs, - round, - elem, - rem, - div, - and, - or, - not, - apply, - to_string, - match__qmark__ -}; - let Enum = { all__qmark__: function (collection, fun = x => x) { @@ -3490,5 +3182,5 @@ let VirtualDOM = (function (e) { const Core = C; -export { Core, kernel as Kernel, Enum, VirtualDOM }; -//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiIiwic291cmNlcyI6WyJFbGl4aXIuanMiXSwic291cmNlc0NvbnRlbnQiOlsiLyogQGZsb3cgKi9cblxuY2xhc3MgTWFpbGJveCB7XG5cbiAgY29uc3RydWN0b3IoKSB7XG4gICAgdGhpcy5tZXNzYWdlcyA9IFtdO1xuICB9XG5cbiAgZGVsaXZlcihtZXNzYWdlKSB7XG4gICAgdGhpcy5tZXNzYWdlcy5wdXNoKG1lc3NhZ2UpO1xuICAgIHJldHVybiBtZXNzYWdlO1xuICB9XG5cbiAgZ2V0KCkge1xuICAgIHJldHVybiB0aGlzLm1lc3NhZ2VzO1xuICB9XG5cbiAgaXNFbXB0eSgpIHtcbiAgICByZXR1cm4gdGhpcy5tZXNzYWdlcy5sZW5ndGggPT09IDA7XG4gIH1cblxuICByZW1vdmVBdChpbmRleCkge1xuICAgIHRoaXMubWVzc2FnZXMuc3BsaWNlKGluZGV4LCAxKTtcbiAgfVxufVxuXG52YXIgU3RhdGVzID0ge1xuICBOT1JNQUw6IFN5bWJvbC5mb3IoXCJub3JtYWxcIiksXG4gIEtJTEw6IFN5bWJvbC5mb3IoXCJraWxsXCIpLFxuICBTVVNQRU5EOiBTeW1ib2wuZm9yKFwic3VzcGVuZFwiKSxcbiAgQ09OVElOVUU6IFN5bWJvbC5mb3IoXCJjb250aW51ZVwiKSxcbiAgUkVDRUlWRTogU3ltYm9sLmZvcihcInJlY2VpdmVcIiksXG4gIFNFTkQ6IFN5bWJvbC5mb3IoXCJzZW5kXCIpLFxuICBTTEVFUElORzogU3ltYm9sLmZvcihcInNsZWVwaW5nXCIpLFxuICBSVU5OSU5HOiBTeW1ib2wuZm9yKFwicnVubmluZ1wiKSxcbiAgU1VTUEVOREVEOiBTeW1ib2wuZm9yKFwic3VzcGVuZGVkXCIpLFxuICBTVE9QUEVEOiBTeW1ib2wuZm9yKFwic3RvcHBlZFwiKSxcbiAgU0xFRVA6IFN5bWJvbC5mb3IoXCJzbGVlcFwiKSxcbiAgRVhJVDogU3ltYm9sLmZvcihcImV4aXRcIiksXG4gIE5PTUFUQ0g6IFN5bWJvbC5mb3IoXCJub19tYXRjaFwiKVxufTtcblxuY2xhc3MgUHJvY2VzcyB7XG5cbiAgY29uc3RydWN0b3IocGlkLCBtYWlsYm94KSB7XG4gICAgdGhpcy5waWQgPSBwaWQ7XG4gICAgdGhpcy5tYWlsYm94ID0gbWFpbGJveDtcbiAgICB0aGlzLnN0YXR1cyA9IFN0YXRlcy5TVE9QUEVEO1xuICAgIHRoaXMuZGljdCA9IHt9O1xuICB9XG59XG5cbmNsYXNzIFR1cGxlIHtcblxuICBjb25zdHJ1Y3RvciguLi5hcmdzKSB7XG4gICAgdGhpcy52YWx1ZXMgPSBPYmplY3QuZnJlZXplKGFyZ3MpO1xuICAgIHRoaXMubGVuZ3RoID0gdGhpcy52YWx1ZXMubGVuZ3RoO1xuICB9XG5cbiAgZ2V0KGluZGV4KSB7XG4gICAgcmV0dXJuIHRoaXMudmFsdWVzW2luZGV4XTtcbiAgfVxuXG4gIGNvdW50KCkge1xuICAgIHJldHVybiB0aGlzLnZhbHVlcy5sZW5ndGg7XG4gIH1cblxuICBbU3ltYm9sLml0ZXJhdG9yXSgpIHtcbiAgICByZXR1cm4gdGhpcy52YWx1ZXNbU3ltYm9sLml0ZXJhdG9yXSgpO1xuICB9XG5cbiAgdG9TdHJpbmcoKSB7XG4gICAgdmFyIGksXG4gICAgICAgIHMgPSBcIlwiO1xuICAgIGZvciAoaSA9IDA7IGkgPCB0aGlzLnZhbHVlcy5sZW5ndGg7IGkrKykge1xuICAgICAgaWYgKHMgIT09IFwiXCIpIHtcbiAgICAgICAgcyArPSBcIiwgXCI7XG4gICAgICB9XG4gICAgICBzICs9IHRoaXMudmFsdWVzW2ldLnRvU3RyaW5nKCk7XG4gICAgfVxuXG4gICAgcmV0dXJuIFwie1wiICsgcyArIFwifVwiO1xuICB9XG5cbn1cblxubGV0IHByb2Nlc3NfY291bnRlciA9IC0xO1xuXG5jbGFzcyBQSUQge1xuICBjb25zdHJ1Y3RvcigpIHtcbiAgICBwcm9jZXNzX2NvdW50ZXIgPSBwcm9jZXNzX2NvdW50ZXIgKyAxO1xuICAgIHRoaXMuaWQgPSBwcm9jZXNzX2NvdW50ZXI7XG4gIH1cblxuICB0b1N0cmluZygpIHtcbiAgICByZXR1cm4gXCJQSUQjPDAuXCIgKyB0aGlzLmlkICsgXCIuMD5cIjtcbiAgfVxufVxuXG5jbGFzcyBJbnRlZ2VyIHt9XG5jbGFzcyBGbG9hdCB7fVxuXG5mdW5jdGlvbiBMaXN0KC4uLmFyZ3MpIHtcbiAgcmV0dXJuIE9iamVjdC5mcmVlemUoYXJncyk7XG59XG5cbmNsYXNzIFByb2Nlc3NTeXN0ZW0ge1xuXG4gIGNvbnN0cnVjdG9yKCkge1xuICAgIHRoaXMucGlkcyA9IG5ldyBNYXAoKTtcbiAgICB0aGlzLm1haWxib3hlcyA9IG5ldyBNYXAoKTtcbiAgICB0aGlzLm5hbWVzID0gbmV3IE1hcCgpO1xuICAgIHRoaXMubGlua3MgPSBuZXcgTWFwKCk7XG5cbiAgICB0aGlzLmN1cnJlbnRfcHJvY2VzcyA9IG51bGw7XG4gICAgdGhpcy5zdXNwZW5kZWQgPSBuZXcgTWFwKCk7XG5cbiAgICB0aGlzLm1haW5fcHJvY2Vzc19waWQgPSB0aGlzLnNwYXduKCk7XG4gICAgdGhpcy5zZXRfY3VycmVudCh0aGlzLm1haW5fcHJvY2Vzc19waWQpO1xuICB9XG5cbiAgc3Bhd24oKSB7XG4gICAgcmV0dXJuIHRoaXMuYWRkX3Byb2MoZmFsc2UpLnBpZDtcbiAgfVxuXG4gIHNwYXduX2xpbmsoKSB7XG4gICAgcmV0dXJuIHRoaXMuYWRkX3Byb2ModHJ1ZSkucGlkO1xuICB9XG5cbiAgbGluayhwaWQpIHtcbiAgICB0aGlzLmxpbmtzLmdldCh0aGlzLnBpZCgpKS5hZGQocGlkKTtcbiAgICB0aGlzLmxpbmtzLmdldChwaWQpLmFkZCh0aGlzLnBpZCgpKTtcbiAgfVxuXG4gIHVubGluayhwaWQpIHtcbiAgICB0aGlzLmxpbmtzLmdldCh0aGlzLnBpZCgpKS5kZWxldGUocGlkKTtcbiAgICB0aGlzLmxpbmtzLmdldChwaWQpLmRlbGV0ZSh0aGlzLnBpZCgpKTtcbiAgfVxuXG4gIHNldF9jdXJyZW50KGlkKSB7XG4gICAgbGV0IHBpZCA9IHRoaXMucGlkb2YoaWQpO1xuICAgIGlmIChwaWQgIT09IG51bGwpIHtcbiAgICAgIHRoaXMuY3VycmVudF9wcm9jZXNzID0gdGhpcy5waWRzLmdldChwaWQpO1xuICAgICAgdGhpcy5jdXJyZW50X3Byb2Nlc3Muc3RhdHVzID0gU3RhdGVzLlJVTk5JTkc7XG4gICAgfVxuICB9XG5cbiAgYWRkX3Byb2MobGlua2VkKSB7XG4gICAgbGV0IG5ld3BpZCA9IG5ldyBQSUQoKTtcbiAgICBsZXQgbWFpbGJveCA9IG5ldyBNYWlsYm94KCk7XG4gICAgbGV0IG5ld3Byb2MgPSBuZXcgUHJvY2VzcyhuZXdwaWQsIG1haWxib3gpO1xuXG4gICAgdGhpcy5waWRzLnNldChuZXdwaWQsIG5ld3Byb2MpO1xuICAgIHRoaXMubWFpbGJveGVzLnNldChuZXdwaWQsIG1haWxib3gpO1xuICAgIHRoaXMubGlua3Muc2V0KG5ld3BpZCwgbmV3IFNldCgpKTtcblxuICAgIGlmIChsaW5rZWQpIHtcbiAgICAgIHRoaXMubGluayhuZXdwaWQpO1xuICAgIH1cblxuICAgIHJldHVybiBuZXdwcm9jO1xuICB9XG5cbiAgcmVtb3ZlX3Byb2MocGlkKSB7XG4gICAgdGhpcy5waWRzLmRlbGV0ZShwaWQpO1xuICAgIHRoaXMudW5yZWdpc3RlcihwaWQpO1xuXG4gICAgaWYgKHRoaXMubGlua3MuaGFzKHBpZCkpIHtcbiAgICAgIGZvciAobGV0IGxpbmtwaWQgb2YgdGhpcy5saW5rcy5nZXQocGlkKSkge1xuICAgICAgICB0aGlzLmxpbmtzLmdldChsaW5rcGlkKS5kZWxldGUocGlkKTtcbiAgICAgIH1cblxuICAgICAgdGhpcy5saW5rcy5kZWxldGUocGlkKTtcbiAgICB9XG4gIH1cblxuICBleGl0KGlkKSB7XG4gICAgbGV0IHBpZCA9IHRoaXMucGlkb2YoaWQpO1xuICAgIHRoaXMucmVtb3ZlX3Byb2MoaWQpO1xuICB9XG5cbiAgcmVnaXN0ZXIobmFtZSwgcGlkKSB7XG4gICAgaWYgKCF0aGlzLm5hbWVzLmhhcyhuYW1lKSkge1xuICAgICAgdGhpcy5uYW1lcy5zZXQobmFtZSwgcGlkKTtcbiAgICAgIHJldHVybiBuYW1lO1xuICAgIH0gZWxzZSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoXCJOYW1lIGlzIGFscmVhZHkgcmVnaXN0ZXJlZCB0byBhbm90aGVyIHByb2Nlc3NcIik7XG4gICAgfVxuICB9XG5cbiAgcmVnaXN0ZXJlZChuYW1lKSB7XG4gICAgcmV0dXJuIHRoaXMubmFtZXMuaGFzKG5hbWUpID8gdGhpcy5uYW1lcy5nZXQobmFtZSkgOiBudWxsO1xuICB9XG5cbiAgdW5yZWdpc3RlcihwaWQpIHtcbiAgICBmb3IgKGxldCBuYW1lIG9mIHRoaXMubmFtZXMua2V5cygpKSB7XG4gICAgICBpZiAodGhpcy5uYW1lcy5oYXMobmFtZSkgJiYgdGhpcy5uYW1lcy5nZXQobmFtZSkgPT09IHBpZCkge1xuICAgICAgICB0aGlzLm5hbWVzLmRlbGV0ZShuYW1lKTtcbiAgICAgIH1cbiAgICB9XG4gIH1cblxuICBwaWQoKSB7XG4gICAgcmV0dXJuIHRoaXMuY3VycmVudF9wcm9jZXNzLnBpZDtcbiAgfVxuXG4gIHBpZG9mKGlkKSB7XG4gICAgaWYgKGlkIGluc3RhbmNlb2YgUElEKSB7XG4gICAgICByZXR1cm4gdGhpcy5waWRzLmhhcyhpZCkgPyBpZCA6IG51bGw7XG4gICAgfSBlbHNlIGlmIChpZCBpbnN0YW5jZW9mIFByb2Nlc3MpIHtcbiAgICAgIHJldHVybiBpZC5waWQ7XG4gICAgfSBlbHNlIHtcbiAgICAgIGxldCBwaWQgPSB0aGlzLnJlZ2lzdGVyZWQoaWQpO1xuICAgICAgaWYgKHBpZCA9PT0gbnVsbCkgdGhyb3cgXCJQcm9jZXNzIG5hbWUgbm90IHJlZ2lzdGVyZWQ6IFwiICsgaWQgKyBcIiAoXCIgKyB0eXBlb2YgaWQgKyBcIilcIjtcbiAgICAgIHJldHVybiBwaWQ7XG4gICAgfVxuICB9XG5cbiAgcHV0KGlkLCBrZXksIHZhbHVlKSB7XG4gICAgbGV0IHBpZCA9IHRoaXMucGlkb2YoaWQpO1xuICAgIGxldCBwcm9jZXNzID0gdGhpcy5waWRzLmdldChwaWQpO1xuICAgIHByb2Nlc3MuZGljdFtrZXldID0gdmFsdWU7XG4gIH1cblxuICBnZXQoaWQsIGtleSkge1xuICAgIGxldCBwaWQgPSB0aGlzLnBpZG9mKGlkKTtcbiAgICBsZXQgcHJvY2VzcyA9IHRoaXMucGlkcy5nZXQocGlkKTtcblxuICAgIGlmIChrZXkgIT0gbnVsbCkge1xuICAgICAgcmV0dXJuIHByb2Nlc3MuZGljdFtrZXldO1xuICAgIH0gZWxzZSB7XG4gICAgICByZXR1cm4gcHJvY2Vzcy5kaWN0O1xuICAgIH1cbiAgfVxuXG4gIGdldF9rZXlzKGlkKSB7XG4gICAgbGV0IHBpZCA9IHRoaXMucGlkb2YoaWQpO1xuICAgIGxldCBwcm9jZXNzID0gdGhpcy5waWRzLmdldChwaWQpO1xuXG4gICAgcmV0dXJuIE9iamVjdC5rZXlzKHByb2Nlc3MuZGljdCk7XG4gIH1cblxuICBlcmFzZShpZCwga2V5KSB7XG4gICAgbGV0IHBpZCA9IHRoaXMucGlkb2YoaWQpO1xuICAgIGxldCBwcm9jZXNzID0gdGhpcy5waWRzLmdldChwaWQpO1xuXG4gICAgaWYgKGtleSAhPSBudWxsKSB7XG4gICAgICBkZWxldGUgcHJvY2Vzcy5kaWN0W2tleV07XG4gICAgfSBlbHNlIHtcbiAgICAgIHByb2Nlc3MuZGljdCA9IHt9O1xuICAgIH1cbiAgfVxufVxuXG5jbGFzcyBCaXRTdHJpbmcge1xuICBjb25zdHJ1Y3RvciguLi5hcmdzKSB7XG4gICAgdGhpcy5yYXdfdmFsdWUgPSBmdW5jdGlvbiAoKSB7XG4gICAgICByZXR1cm4gT2JqZWN0LmZyZWV6ZShhcmdzKTtcbiAgICB9O1xuXG4gICAgdGhpcy52YWx1ZSA9IE9iamVjdC5mcmVlemUodGhpcy5wcm9jZXNzKGFyZ3MpKTtcbiAgfVxuXG4gIGdldChpbmRleCkge1xuICAgIHJldHVybiB0aGlzLnZhbHVlW2luZGV4XTtcbiAgfVxuXG4gIGNvdW50KCkge1xuICAgIHJldHVybiB0aGlzLnZhbHVlLmxlbmd0aDtcbiAgfVxuXG4gIFtTeW1ib2wuaXRlcmF0b3JdKCkge1xuICAgIHJldHVybiB0aGlzLnZhbHVlW1N5bWJvbC5pdGVyYXRvcl0oKTtcbiAgfVxuXG4gIHRvU3RyaW5nKCkge1xuICAgIHZhciBpLFxuICAgICAgICBzID0gXCJcIjtcbiAgICBmb3IgKGkgPSAwOyBpIDwgdGhpcy5jb3VudCgpOyBpKyspIHtcbiAgICAgIGlmIChzICE9PSBcIlwiKSB7XG4gICAgICAgIHMgKz0gXCIsIFwiO1xuICAgICAgfVxuICAgICAgcyArPSB0aGlzW2ldLnRvU3RyaW5nKCk7XG4gICAgfVxuXG4gICAgcmV0dXJuIFwiPDxcIiArIHMgKyBcIj4+XCI7XG4gIH1cblxuICBwcm9jZXNzKCkge1xuICAgIGxldCBwcm9jZXNzZWRfdmFsdWVzID0gW107XG5cbiAgICB2YXIgaTtcbiAgICBmb3IgKGkgPSAwOyBpIDwgdGhpcy5yYXdfdmFsdWUoKS5sZW5ndGg7IGkrKykge1xuICAgICAgbGV0IHByb2Nlc3NlZF92YWx1ZSA9IHRoaXNbXCJwcm9jZXNzX1wiICsgdGhpcy5yYXdfdmFsdWUoKVtpXS50eXBlXSh0aGlzLnJhd192YWx1ZSgpW2ldKTtcblxuICAgICAgZm9yIChsZXQgYXR0ciBvZiB0aGlzLnJhd192YWx1ZSgpW2ldLmF0dHJpYnV0ZXMpIHtcbiAgICAgICAgcHJvY2Vzc2VkX3ZhbHVlID0gdGhpc1tcInByb2Nlc3NfXCIgKyBhdHRyXShwcm9jZXNzZWRfdmFsdWUpO1xuICAgICAgfVxuXG4gICAgICBwcm9jZXNzZWRfdmFsdWVzID0gcHJvY2Vzc2VkX3ZhbHVlcy5jb25jYXQocHJvY2Vzc2VkX3ZhbHVlKTtcbiAgICB9XG5cbiAgICByZXR1cm4gcHJvY2Vzc2VkX3ZhbHVlcztcbiAgfVxuXG4gIHByb2Nlc3NfaW50ZWdlcih2YWx1ZSkge1xuICAgIHJldHVybiB2YWx1ZS52YWx1ZTtcbiAgfVxuXG4gIHByb2Nlc3NfZmxvYXQodmFsdWUpIHtcbiAgICBpZiAodmFsdWUuc2l6ZSA9PT0gNjQpIHtcbiAgICAgIHJldHVybiBCaXRTdHJpbmcuZmxvYXQ2NFRvQnl0ZXModmFsdWUudmFsdWUpO1xuICAgIH0gZWxzZSBpZiAodmFsdWUuc2l6ZSA9PT0gMzIpIHtcbiAgICAgIHJldHVybiBCaXRTdHJpbmcuZmxvYXQzMlRvQnl0ZXModmFsdWUudmFsdWUpO1xuICAgIH1cblxuICAgIHRocm93IG5ldyBFcnJvcihcIkludmFsaWQgc2l6ZSBmb3IgZmxvYXRcIik7XG4gIH1cblxuICBwcm9jZXNzX2JpdHN0cmluZyh2YWx1ZSkge1xuICAgIHJldHVybiB2YWx1ZS52YWx1ZS52YWx1ZTtcbiAgfVxuXG4gIHByb2Nlc3NfYmluYXJ5KHZhbHVlKSB7XG4gICAgcmV0dXJuIEJpdFN0cmluZy50b1VURjhBcnJheSh2YWx1ZS52YWx1ZSk7XG4gIH1cblxuICBwcm9jZXNzX3V0ZjgodmFsdWUpIHtcbiAgICByZXR1cm4gQml0U3RyaW5nLnRvVVRGOEFycmF5KHZhbHVlLnZhbHVlKTtcbiAgfVxuXG4gIHByb2Nlc3NfdXRmMTYodmFsdWUpIHtcbiAgICByZXR1cm4gQml0U3RyaW5nLnRvVVRGMTZBcnJheSh2YWx1ZS52YWx1ZSk7XG4gIH1cblxuICBwcm9jZXNzX3V0ZjMyKHZhbHVlKSB7XG4gICAgcmV0dXJuIEJpdFN0cmluZy50b1VURjMyQXJyYXkodmFsdWUudmFsdWUpO1xuICB9XG5cbiAgcHJvY2Vzc19zaWduZWQodmFsdWUpIHtcbiAgICByZXR1cm4gbmV3IFVpbnQ4QXJyYXkoW3ZhbHVlXSlbMF07XG4gIH1cblxuICBwcm9jZXNzX3Vuc2lnbmVkKHZhbHVlKSB7XG4gICAgcmV0dXJuIHZhbHVlO1xuICB9XG5cbiAgcHJvY2Vzc19uYXRpdmUodmFsdWUpIHtcbiAgICByZXR1cm4gdmFsdWU7XG4gIH1cblxuICBwcm9jZXNzX2JpZyh2YWx1ZSkge1xuICAgIHJldHVybiB2YWx1ZTtcbiAgfVxuXG4gIHByb2Nlc3NfbGl0dGxlKHZhbHVlKSB7XG4gICAgcmV0dXJuIHZhbHVlLnJldmVyc2UoKTtcbiAgfVxuXG4gIHByb2Nlc3Nfc2l6ZSh2YWx1ZSkge1xuICAgIHJldHVybiB2YWx1ZTtcbiAgfVxuXG4gIHByb2Nlc3NfdW5pdCh2YWx1ZSkge1xuICAgIHJldHVybiB2YWx1ZTtcbiAgfVxuXG4gIHN0YXRpYyBpbnRlZ2VyKHZhbHVlKSB7XG4gICAgcmV0dXJuIEJpdFN0cmluZy53cmFwKHZhbHVlLCB7IFwidHlwZVwiOiBcImludGVnZXJcIiwgXCJ1bml0XCI6IDEsIFwic2l6ZVwiOiA4IH0pO1xuICB9XG5cbiAgc3RhdGljIGZsb2F0KHZhbHVlKSB7XG4gICAgcmV0dXJuIEJpdFN0cmluZy53cmFwKHZhbHVlLCB7IFwidHlwZVwiOiBcImZsb2F0XCIsIFwidW5pdFwiOiAxLCBcInNpemVcIjogNjQgfSk7XG4gIH1cblxuICBzdGF0aWMgYml0c3RyaW5nKHZhbHVlKSB7XG4gICAgcmV0dXJuIEJpdFN0cmluZy53cmFwKHZhbHVlLCB7IFwidHlwZVwiOiBcImJpdHN0cmluZ1wiLCBcInVuaXRcIjogMSwgXCJzaXplXCI6IHZhbHVlLmxlbmd0aCB9KTtcbiAgfVxuXG4gIHN0YXRpYyBiaXRzKHZhbHVlKSB7XG4gICAgcmV0dXJuIEJpdFN0cmluZy5iaXRzdHJpbmcodmFsdWUpO1xuICB9XG5cbiAgc3RhdGljIGJpbmFyeSh2YWx1ZSkge1xuICAgIHJldHVybiBCaXRTdHJpbmcud3JhcCh2YWx1ZSwgeyBcInR5cGVcIjogXCJiaW5hcnlcIiwgXCJ1bml0XCI6IDgsIFwic2l6ZVwiOiB2YWx1ZS5sZW5ndGggfSk7XG4gIH1cblxuICBzdGF0aWMgYnl0ZXModmFsdWUpIHtcbiAgICByZXR1cm4gQml0U3RyaW5nLmJpbmFyeSh2YWx1ZSk7XG4gIH1cblxuICBzdGF0aWMgdXRmOCh2YWx1ZSkge1xuICAgIHJldHVybiBCaXRTdHJpbmcud3JhcCh2YWx1ZSwgeyBcInR5cGVcIjogXCJ1dGY4XCIgfSk7XG4gIH1cblxuICBzdGF0aWMgdXRmMTYodmFsdWUpIHtcbiAgICByZXR1cm4gQml0U3RyaW5nLndyYXAodmFsdWUsIHsgXCJ0eXBlXCI6IFwidXRmMTZcIiB9KTtcbiAgfVxuXG4gIHN0YXRpYyB1dGYzMih2YWx1ZSkge1xuICAgIHJldHVybiBCaXRTdHJpbmcud3JhcCh2YWx1ZSwgeyBcInR5cGVcIjogXCJ1dGYzMlwiIH0pO1xuICB9XG5cbiAgc3RhdGljIHNpZ25lZCh2YWx1ZSkge1xuICAgIHJldHVybiBCaXRTdHJpbmcud3JhcCh2YWx1ZSwge30sIFwic2lnbmVkXCIpO1xuICB9XG5cbiAgc3RhdGljIHVuc2lnbmVkKHZhbHVlKSB7XG4gICAgcmV0dXJuIEJpdFN0cmluZy53cmFwKHZhbHVlLCB7fSwgXCJ1bnNpZ25lZFwiKTtcbiAgfVxuXG4gIHN0YXRpYyBuYXRpdmUodmFsdWUpIHtcbiAgICByZXR1cm4gQml0U3RyaW5nLndyYXAodmFsdWUsIHt9LCBcIm5hdGl2ZVwiKTtcbiAgfVxuXG4gIHN0YXRpYyBiaWcodmFsdWUpIHtcbiAgICByZXR1cm4gQml0U3RyaW5nLndyYXAodmFsdWUsIHt9LCBcImJpZ1wiKTtcbiAgfVxuXG4gIHN0YXRpYyBsaXR0bGUodmFsdWUpIHtcbiAgICByZXR1cm4gQml0U3RyaW5nLndyYXAodmFsdWUsIHt9LCBcImxpdHRsZVwiKTtcbiAgfVxuXG4gIHN0YXRpYyBzaXplKHZhbHVlLCBjb3VudCkge1xuICAgIHJldHVybiBCaXRTdHJpbmcud3JhcCh2YWx1ZSwgeyBcInNpemVcIjogY291bnQgfSk7XG4gIH1cblxuICBzdGF0aWMgdW5pdCh2YWx1ZSwgY291bnQpIHtcbiAgICByZXR1cm4gQml0U3RyaW5nLndyYXAodmFsdWUsIHsgXCJ1bml0XCI6IGNvdW50IH0pO1xuICB9XG5cbiAgc3RhdGljIHdyYXAodmFsdWUsIG9wdCwgbmV3X2F0dHJpYnV0ZSA9IG51bGwpIHtcbiAgICBsZXQgdGhlX3ZhbHVlID0gdmFsdWU7XG5cbiAgICBpZiAoISh2YWx1ZSBpbnN0YW5jZW9mIE9iamVjdCkpIHtcbiAgICAgIHRoZV92YWx1ZSA9IHsgXCJ2YWx1ZVwiOiB2YWx1ZSwgXCJhdHRyaWJ1dGVzXCI6IFtdIH07XG4gICAgfVxuXG4gICAgdGhlX3ZhbHVlID0gT2JqZWN0LmFzc2lnbih0aGVfdmFsdWUsIG9wdCk7XG5cbiAgICBpZiAobmV3X2F0dHJpYnV0ZSkge1xuICAgICAgdGhlX3ZhbHVlLmF0dHJpYnV0ZXMucHVzaChuZXdfYXR0cmlidXRlKTtcbiAgICB9XG5cbiAgICByZXR1cm4gdGhlX3ZhbHVlO1xuICB9XG5cbiAgc3RhdGljIHRvVVRGOEFycmF5KHN0cikge1xuICAgIHZhciB1dGY4ID0gW107XG4gICAgZm9yICh2YXIgaSA9IDA7IGkgPCBzdHIubGVuZ3RoOyBpKyspIHtcbiAgICAgIHZhciBjaGFyY29kZSA9IHN0ci5jaGFyQ29kZUF0KGkpO1xuICAgICAgaWYgKGNoYXJjb2RlIDwgMTI4KSB7XG4gICAgICAgIHV0ZjgucHVzaChjaGFyY29kZSk7XG4gICAgICB9IGVsc2UgaWYgKGNoYXJjb2RlIDwgMjA0OCkge1xuICAgICAgICB1dGY4LnB1c2goMTkyIHwgY2hhcmNvZGUgPj4gNiwgMTI4IHwgY2hhcmNvZGUgJiA2Myk7XG4gICAgICB9IGVsc2UgaWYgKGNoYXJjb2RlIDwgNTUyOTYgfHwgY2hhcmNvZGUgPj0gNTczNDQpIHtcbiAgICAgICAgdXRmOC5wdXNoKDIyNCB8IGNoYXJjb2RlID4+IDEyLCAxMjggfCBjaGFyY29kZSA+PiA2ICYgNjMsIDEyOCB8IGNoYXJjb2RlICYgNjMpO1xuICAgICAgfVxuICAgICAgLy8gc3Vycm9nYXRlIHBhaXJcbiAgICAgIGVsc2Uge1xuICAgICAgICBpKys7XG4gICAgICAgIC8vIFVURi0xNiBlbmNvZGVzIDB4MTAwMDAtMHgxMEZGRkYgYnlcbiAgICAgICAgLy8gc3VidHJhY3RpbmcgMHgxMDAwMCBhbmQgc3BsaXR0aW5nIHRoZVxuICAgICAgICAvLyAyMCBiaXRzIG9mIDB4MC0weEZGRkZGIGludG8gdHdvIGhhbHZlc1xuICAgICAgICBjaGFyY29kZSA9IDY1NTM2ICsgKChjaGFyY29kZSAmIDEwMjMpIDw8IDEwIHwgc3RyLmNoYXJDb2RlQXQoaSkgJiAxMDIzKTtcbiAgICAgICAgdXRmOC5wdXNoKDI0MCB8IGNoYXJjb2RlID4+IDE4LCAxMjggfCBjaGFyY29kZSA+PiAxMiAmIDYzLCAxMjggfCBjaGFyY29kZSA+PiA2ICYgNjMsIDEyOCB8IGNoYXJjb2RlICYgNjMpO1xuICAgICAgfVxuICAgIH1cbiAgICByZXR1cm4gdXRmODtcbiAgfVxuXG4gIHN0YXRpYyB0b1VURjE2QXJyYXkoc3RyKSB7XG4gICAgdmFyIHV0ZjE2ID0gW107XG4gICAgZm9yICh2YXIgaSA9IDA7IGkgPCBzdHIubGVuZ3RoOyBpKyspIHtcbiAgICAgIHZhciBjb2RlUG9pbnQgPSBzdHIuY29kZVBvaW50QXQoaSk7XG5cbiAgICAgIGlmIChjb2RlUG9pbnQgPD0gMjU1KSB7XG4gICAgICAgIHV0ZjE2LnB1c2goMCk7XG4gICAgICAgIHV0ZjE2LnB1c2goY29kZVBvaW50KTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHV0ZjE2LnB1c2goY29kZVBvaW50ID4+IDggJiAyNTUpO1xuICAgICAgICB1dGYxNi5wdXNoKGNvZGVQb2ludCAmIDI1NSk7XG4gICAgICB9XG4gICAgfVxuICAgIHJldHVybiB1dGYxNjtcbiAgfVxuXG4gIHN0YXRpYyB0b1VURjMyQXJyYXkoc3RyKSB7XG4gICAgdmFyIHV0ZjMyID0gW107XG4gICAgZm9yICh2YXIgaSA9IDA7IGkgPCBzdHIubGVuZ3RoOyBpKyspIHtcbiAgICAgIHZhciBjb2RlUG9pbnQgPSBzdHIuY29kZVBvaW50QXQoaSk7XG5cbiAgICAgIGlmIChjb2RlUG9pbnQgPD0gMjU1KSB7XG4gICAgICAgIHV0ZjMyLnB1c2goMCk7XG4gICAgICAgIHV0ZjMyLnB1c2goMCk7XG4gICAgICAgIHV0ZjMyLnB1c2goMCk7XG4gICAgICAgIHV0ZjMyLnB1c2goY29kZVBvaW50KTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHV0ZjMyLnB1c2goMCk7XG4gICAgICAgIHV0ZjMyLnB1c2goMCk7XG4gICAgICAgIHV0ZjMyLnB1c2goY29kZVBvaW50ID4+IDggJiAyNTUpO1xuICAgICAgICB1dGYzMi5wdXNoKGNvZGVQb2ludCAmIDI1NSk7XG4gICAgICB9XG4gICAgfVxuICAgIHJldHVybiB1dGYzMjtcbiAgfVxuXG4gIC8vaHR0cDovL3N0YWNrb3ZlcmZsb3cuY29tL3F1ZXN0aW9ucy8yMDAzNDkzL2phdmFzY3JpcHQtZmxvYXQtZnJvbS10by1iaXRzXG4gIHN0YXRpYyBmbG9hdDMyVG9CeXRlcyhmKSB7XG4gICAgdmFyIGJ5dGVzID0gW107XG5cbiAgICB2YXIgYnVmID0gbmV3IEFycmF5QnVmZmVyKDQpO1xuICAgIG5ldyBGbG9hdDMyQXJyYXkoYnVmKVswXSA9IGY7XG5cbiAgICBsZXQgaW50VmVyc2lvbiA9IG5ldyBVaW50MzJBcnJheShidWYpWzBdO1xuXG4gICAgYnl0ZXMucHVzaChpbnRWZXJzaW9uID4+IDI0ICYgMjU1KTtcbiAgICBieXRlcy5wdXNoKGludFZlcnNpb24gPj4gMTYgJiAyNTUpO1xuICAgIGJ5dGVzLnB1c2goaW50VmVyc2lvbiA+PiA4ICYgMjU1KTtcbiAgICBieXRlcy5wdXNoKGludFZlcnNpb24gJiAyNTUpO1xuXG4gICAgcmV0dXJuIGJ5dGVzO1xuICB9XG5cbiAgc3RhdGljIGZsb2F0NjRUb0J5dGVzKGYpIHtcbiAgICB2YXIgYnl0ZXMgPSBbXTtcblxuICAgIHZhciBidWYgPSBuZXcgQXJyYXlCdWZmZXIoOCk7XG4gICAgbmV3IEZsb2F0NjRBcnJheShidWYpWzBdID0gZjtcblxuICAgIHZhciBpbnRWZXJzaW9uMSA9IG5ldyBVaW50MzJBcnJheShidWYpWzBdO1xuICAgIHZhciBpbnRWZXJzaW9uMiA9IG5ldyBVaW50MzJBcnJheShidWYpWzFdO1xuXG4gICAgYnl0ZXMucHVzaChpbnRWZXJzaW9uMiA+PiAyNCAmIDI1NSk7XG4gICAgYnl0ZXMucHVzaChpbnRWZXJzaW9uMiA+PiAxNiAmIDI1NSk7XG4gICAgYnl0ZXMucHVzaChpbnRWZXJzaW9uMiA+PiA4ICYgMjU1KTtcbiAgICBieXRlcy5wdXNoKGludFZlcnNpb24yICYgMjU1KTtcblxuICAgIGJ5dGVzLnB1c2goaW50VmVyc2lvbjEgPj4gMjQgJiAyNTUpO1xuICAgIGJ5dGVzLnB1c2goaW50VmVyc2lvbjEgPj4gMTYgJiAyNTUpO1xuICAgIGJ5dGVzLnB1c2goaW50VmVyc2lvbjEgPj4gOCAmIDI1NSk7XG4gICAgYnl0ZXMucHVzaChpbnRWZXJzaW9uMSAmIDI1NSk7XG5cbiAgICByZXR1cm4gYnl0ZXM7XG4gIH1cbn1cblxuLyogQGZsb3cgKi9cblxuY2xhc3MgVmFyaWFibGUge1xuXG4gIGNvbnN0cnVjdG9yKG5hbWUgPSBudWxsKSB7XG4gICAgdGhpcy5uYW1lID0gbmFtZTtcbiAgfVxufVxuXG5jbGFzcyBXaWxkY2FyZCB7XG4gIGNvbnN0cnVjdG9yKCkge31cbn1cblxuY2xhc3MgU3RhcnRzV2l0aCB7XG5cbiAgY29uc3RydWN0b3IocHJlZml4KSB7XG4gICAgdGhpcy5wcmVmaXggPSBwcmVmaXg7XG4gIH1cbn1cblxuY2xhc3MgQ2FwdHVyZSB7XG5cbiAgY29uc3RydWN0b3IodmFsdWUpIHtcbiAgICB0aGlzLnZhbHVlID0gdmFsdWU7XG4gIH1cbn1cblxuY2xhc3MgSGVhZFRhaWwge1xuICBjb25zdHJ1Y3RvcigpIHt9XG59XG5cbmNsYXNzIFR5cGUge1xuXG4gIGNvbnN0cnVjdG9yKHR5cGUsIG9ialBhdHRlcm4gPSB7fSkge1xuICAgIHRoaXMudHlwZSA9IHR5cGU7XG4gICAgdGhpcy5vYmpQYXR0ZXJuID0gb2JqUGF0dGVybjtcbiAgfVxufVxuXG5jbGFzcyBCb3VuZCB7XG5cbiAgY29uc3RydWN0b3IodmFsdWUpIHtcbiAgICB0aGlzLnZhbHVlID0gdmFsdWU7XG4gIH1cbn1cblxuZnVuY3Rpb24gdmFyaWFibGUobmFtZSA9IG51bGwpIHtcbiAgcmV0dXJuIG5ldyBWYXJpYWJsZShuYW1lKTtcbn1cblxuZnVuY3Rpb24gd2lsZGNhcmQoKSB7XG4gIHJldHVybiBuZXcgV2lsZGNhcmQoKTtcbn1cblxuZnVuY3Rpb24gc3RhcnRzV2l0aChwcmVmaXgpIHtcbiAgcmV0dXJuIG5ldyBTdGFydHNXaXRoKHByZWZpeCk7XG59XG5cbmZ1bmN0aW9uIGNhcHR1cmUodmFsdWUpIHtcbiAgcmV0dXJuIG5ldyBDYXB0dXJlKHZhbHVlKTtcbn1cblxuZnVuY3Rpb24gaGVhZFRhaWwoKSB7XG4gIHJldHVybiBuZXcgSGVhZFRhaWwoKTtcbn1cblxuZnVuY3Rpb24gdHlwZSh0eXBlLCBvYmpQYXR0ZXJuID0ge30pIHtcbiAgcmV0dXJuIG5ldyBUeXBlKHR5cGUsIG9ialBhdHRlcm4pO1xufVxuXG5mdW5jdGlvbiBib3VuZCh2YWx1ZSkge1xuICByZXR1cm4gbmV3IEJvdW5kKHZhbHVlKTtcbn1cblxuZnVuY3Rpb24gaXNfbnVtYmVyJDIodmFsdWUpIHtcbiAgcmV0dXJuIHR5cGVvZiB2YWx1ZSA9PT0gJ251bWJlcic7XG59XG5cbmZ1bmN0aW9uIGlzX3N0cmluZyh2YWx1ZSkge1xuICByZXR1cm4gdHlwZW9mIHZhbHVlID09PSAnc3RyaW5nJztcbn1cblxuZnVuY3Rpb24gaXNfYm9vbGVhbiQyKHZhbHVlKSB7XG4gIHJldHVybiB0eXBlb2YgdmFsdWUgPT09ICdib29sZWFuJztcbn1cblxuZnVuY3Rpb24gaXNfc3ltYm9sKHZhbHVlKSB7XG4gIHJldHVybiB0eXBlb2YgdmFsdWUgPT09ICdzeW1ib2wnO1xufVxuXG5mdW5jdGlvbiBpc19udWxsKHZhbHVlKSB7XG4gIHJldHVybiB2YWx1ZSA9PT0gbnVsbDtcbn1cblxuZnVuY3Rpb24gaXNfdW5kZWZpbmVkKHZhbHVlKSB7XG4gIHJldHVybiB0eXBlb2YgdmFsdWUgPT09ICd1bmRlZmluZWQnO1xufVxuXG5mdW5jdGlvbiBpc19mdW5jdGlvbiQyKHZhbHVlKSB7XG4gIHJldHVybiBPYmplY3QucHJvdG90eXBlLnRvU3RyaW5nLmNhbGwodmFsdWUpID09ICdbb2JqZWN0IEZ1bmN0aW9uXSc7XG59XG5cbmZ1bmN0aW9uIGlzX3ZhcmlhYmxlKHZhbHVlKSB7XG4gIHJldHVybiB2YWx1ZSBpbnN0YW5jZW9mIFZhcmlhYmxlO1xufVxuXG5mdW5jdGlvbiBpc193aWxkY2FyZCh2YWx1ZSkge1xuICByZXR1cm4gdmFsdWUgaW5zdGFuY2VvZiBXaWxkY2FyZDtcbn1cblxuZnVuY3Rpb24gaXNfaGVhZFRhaWwodmFsdWUpIHtcbiAgcmV0dXJuIHZhbHVlIGluc3RhbmNlb2YgSGVhZFRhaWw7XG59XG5cbmZ1bmN0aW9uIGlzX2NhcHR1cmUodmFsdWUpIHtcbiAgcmV0dXJuIHZhbHVlIGluc3RhbmNlb2YgQ2FwdHVyZTtcbn1cblxuZnVuY3Rpb24gaXNfdHlwZSh2YWx1ZSkge1xuICByZXR1cm4gdmFsdWUgaW5zdGFuY2VvZiBUeXBlO1xufVxuXG5mdW5jdGlvbiBpc19zdGFydHNXaXRoKHZhbHVlKSB7XG4gIHJldHVybiB2YWx1ZSBpbnN0YW5jZW9mIFN0YXJ0c1dpdGg7XG59XG5cbmZ1bmN0aW9uIGlzX2JvdW5kKHZhbHVlKSB7XG4gIHJldHVybiB2YWx1ZSBpbnN0YW5jZW9mIEJvdW5kO1xufVxuXG5mdW5jdGlvbiBpc19vYmplY3QodmFsdWUpIHtcbiAgcmV0dXJuIHR5cGVvZiB2YWx1ZSA9PT0gJ29iamVjdCc7XG59XG5cbmZ1bmN0aW9uIGlzX2FycmF5KHZhbHVlKSB7XG4gIHJldHVybiBBcnJheS5pc0FycmF5KHZhbHVlKTtcbn1cblxudmFyIENoZWNrcyA9IHtcbiAgaXNfbnVtYmVyOiBpc19udW1iZXIkMixcbiAgaXNfc3RyaW5nLFxuICBpc19ib29sZWFuOiBpc19ib29sZWFuJDIsXG4gIGlzX3N5bWJvbCxcbiAgaXNfbnVsbCxcbiAgaXNfdW5kZWZpbmVkLFxuICBpc19mdW5jdGlvbjogaXNfZnVuY3Rpb24kMixcbiAgaXNfdmFyaWFibGUsXG4gIGlzX3dpbGRjYXJkLFxuICBpc19oZWFkVGFpbCxcbiAgaXNfY2FwdHVyZSxcbiAgaXNfdHlwZSxcbiAgaXNfc3RhcnRzV2l0aCxcbiAgaXNfYm91bmQsXG4gIGlzX29iamVjdCxcbiAgaXNfYXJyYXlcbn07XG5cbmZ1bmN0aW9uIHJlc29sdmVTeW1ib2wocGF0dGVybikge1xuICByZXR1cm4gZnVuY3Rpb24gKHZhbHVlKSB7XG4gICAgcmV0dXJuIENoZWNrcy5pc19zeW1ib2wodmFsdWUpICYmIHZhbHVlID09PSBwYXR0ZXJuO1xuICB9O1xufVxuXG5mdW5jdGlvbiByZXNvbHZlU3RyaW5nKHBhdHRlcm4pIHtcbiAgcmV0dXJuIGZ1bmN0aW9uICh2YWx1ZSkge1xuICAgIHJldHVybiBDaGVja3MuaXNfc3RyaW5nKHZhbHVlKSAmJiB2YWx1ZSA9PT0gcGF0dGVybjtcbiAgfTtcbn1cblxuZnVuY3Rpb24gcmVzb2x2ZU51bWJlcihwYXR0ZXJuKSB7XG4gIHJldHVybiBmdW5jdGlvbiAodmFsdWUpIHtcbiAgICByZXR1cm4gQ2hlY2tzLmlzX251bWJlcih2YWx1ZSkgJiYgdmFsdWUgPT09IHBhdHRlcm47XG4gIH07XG59XG5cbmZ1bmN0aW9uIHJlc29sdmVCb29sZWFuKHBhdHRlcm4pIHtcbiAgcmV0dXJuIGZ1bmN0aW9uICh2YWx1ZSkge1xuICAgIHJldHVybiBDaGVja3MuaXNfYm9vbGVhbih2YWx1ZSkgJiYgdmFsdWUgPT09IHBhdHRlcm47XG4gIH07XG59XG5cbmZ1bmN0aW9uIHJlc29sdmVGdW5jdGlvbihwYXR0ZXJuKSB7XG4gIHJldHVybiBmdW5jdGlvbiAodmFsdWUpIHtcbiAgICByZXR1cm4gQ2hlY2tzLmlzX2Z1bmN0aW9uKHZhbHVlKSAmJiB2YWx1ZSA9PT0gcGF0dGVybjtcbiAgfTtcbn1cblxuZnVuY3Rpb24gcmVzb2x2ZU51bGwocGF0dGVybikge1xuICByZXR1cm4gZnVuY3Rpb24gKHZhbHVlKSB7XG4gICAgcmV0dXJuIENoZWNrcy5pc19udWxsKHZhbHVlKTtcbiAgfTtcbn1cblxuZnVuY3Rpb24gcmVzb2x2ZUJvdW5kKHBhdHRlcm4pIHtcbiAgcmV0dXJuIGZ1bmN0aW9uICh2YWx1ZSwgYXJncykge1xuICAgIGlmICh0eXBlb2YgdmFsdWUgPT09IHR5cGVvZiBwYXR0ZXJuLnZhbHVlICYmIHZhbHVlID09PSBwYXR0ZXJuLnZhbHVlKSB7XG4gICAgICBhcmdzLnB1c2godmFsdWUpO1xuICAgICAgcmV0dXJuIHRydWU7XG4gICAgfVxuXG4gICAgcmV0dXJuIGZhbHNlO1xuICB9O1xufVxuXG5mdW5jdGlvbiByZXNvbHZlV2lsZGNhcmQoKSB7XG4gIHJldHVybiBmdW5jdGlvbiAoKSB7XG4gICAgcmV0dXJuIHRydWU7XG4gIH07XG59XG5cbmZ1bmN0aW9uIHJlc29sdmVWYXJpYWJsZSgpIHtcbiAgcmV0dXJuIGZ1bmN0aW9uICh2YWx1ZSwgYXJncykge1xuICAgIGFyZ3MucHVzaCh2YWx1ZSk7XG4gICAgcmV0dXJuIHRydWU7XG4gIH07XG59XG5cbmZ1bmN0aW9uIHJlc29sdmVIZWFkVGFpbCgpIHtcbiAgcmV0dXJuIGZ1bmN0aW9uICh2YWx1ZSwgYXJncykge1xuICAgIGlmICghQ2hlY2tzLmlzX2FycmF5KHZhbHVlKSB8fCB2YWx1ZS5sZW5ndGggPCAyKSB7XG4gICAgICByZXR1cm4gZmFsc2U7XG4gICAgfVxuXG4gICAgY29uc3QgaGVhZCA9IHZhbHVlWzBdO1xuICAgIGNvbnN0IHRhaWwgPSB2YWx1ZS5zbGljZSgxKTtcblxuICAgIGFyZ3MucHVzaChoZWFkKTtcbiAgICBhcmdzLnB1c2godGFpbCk7XG5cbiAgICByZXR1cm4gdHJ1ZTtcbiAgfTtcbn1cblxuZnVuY3Rpb24gcmVzb2x2ZUNhcHR1cmUocGF0dGVybikge1xuICBjb25zdCBtYXRjaGVzID0gYnVpbGRNYXRjaChwYXR0ZXJuLnZhbHVlKTtcblxuICByZXR1cm4gZnVuY3Rpb24gKHZhbHVlLCBhcmdzKSB7XG4gICAgaWYgKG1hdGNoZXModmFsdWUsIGFyZ3MpKSB7XG4gICAgICBhcmdzLnB1c2godmFsdWUpO1xuICAgICAgcmV0dXJuIHRydWU7XG4gICAgfVxuXG4gICAgcmV0dXJuIGZhbHNlO1xuICB9O1xufVxuXG5mdW5jdGlvbiByZXNvbHZlU3RhcnRzV2l0aChwYXR0ZXJuKSB7XG4gIGNvbnN0IHByZWZpeCA9IHBhdHRlcm4ucHJlZml4O1xuXG4gIHJldHVybiBmdW5jdGlvbiAodmFsdWUsIGFyZ3MpIHtcbiAgICBpZiAoQ2hlY2tzLmlzX3N0cmluZyh2YWx1ZSkgJiYgdmFsdWUuc3RhcnRzV2l0aChwcmVmaXgpKSB7XG4gICAgICBhcmdzLnB1c2godmFsdWUuc3Vic3RyaW5nKHByZWZpeC5sZW5ndGgpKTtcbiAgICAgIHJldHVybiB0cnVlO1xuICAgIH1cblxuICAgIHJldHVybiBmYWxzZTtcbiAgfTtcbn1cblxuZnVuY3Rpb24gcmVzb2x2ZVR5cGUocGF0dGVybikge1xuICByZXR1cm4gZnVuY3Rpb24gKHZhbHVlLCBhcmdzKSB7XG4gICAgaWYgKHZhbHVlIGluc3RhbmNlb2YgcGF0dGVybi50eXBlKSB7XG4gICAgICBjb25zdCBtYXRjaGVzID0gYnVpbGRNYXRjaChwYXR0ZXJuLm9ialBhdHRlcm4pO1xuICAgICAgcmV0dXJuIG1hdGNoZXModmFsdWUsIGFyZ3MpICYmIGFyZ3MucHVzaCh2YWx1ZSkgPiAwO1xuICAgIH1cblxuICAgIHJldHVybiBmYWxzZTtcbiAgfTtcbn1cblxuZnVuY3Rpb24gcmVzb2x2ZUFycmF5KHBhdHRlcm4pIHtcbiAgY29uc3QgbWF0Y2hlcyA9IHBhdHRlcm4ubWFwKHggPT4gYnVpbGRNYXRjaCh4KSk7XG5cbiAgcmV0dXJuIGZ1bmN0aW9uICh2YWx1ZSwgYXJncykge1xuICAgIGlmICghQ2hlY2tzLmlzX2FycmF5KHZhbHVlKSB8fCB2YWx1ZS5sZW5ndGggIT0gcGF0dGVybi5sZW5ndGgpIHtcbiAgICAgIHJldHVybiBmYWxzZTtcbiAgICB9XG5cbiAgICByZXR1cm4gdmFsdWUuZXZlcnkoZnVuY3Rpb24gKHYsIGkpIHtcbiAgICAgIHJldHVybiBtYXRjaGVzW2ldKHZhbHVlW2ldLCBhcmdzKTtcbiAgICB9KTtcbiAgfTtcbn1cblxuZnVuY3Rpb24gcmVzb2x2ZU9iamVjdChwYXR0ZXJuKSB7XG4gIGxldCBtYXRjaGVzID0ge307XG5cbiAgZm9yIChsZXQga2V5IG9mIE9iamVjdC5rZXlzKHBhdHRlcm4pLmNvbmNhdChPYmplY3QuZ2V0T3duUHJvcGVydHlTeW1ib2xzKHBhdHRlcm4pKSkge1xuICAgIG1hdGNoZXNba2V5XSA9IGJ1aWxkTWF0Y2gocGF0dGVybltrZXldKTtcbiAgfVxuXG4gIHJldHVybiBmdW5jdGlvbiAodmFsdWUsIGFyZ3MpIHtcbiAgICBpZiAoIUNoZWNrcy5pc19vYmplY3QodmFsdWUpIHx8IHBhdHRlcm4ubGVuZ3RoID4gdmFsdWUubGVuZ3RoKSB7XG4gICAgICByZXR1cm4gZmFsc2U7XG4gICAgfVxuXG4gICAgZm9yIChsZXQga2V5IG9mIE9iamVjdC5rZXlzKHBhdHRlcm4pLmNvbmNhdChPYmplY3QuZ2V0T3duUHJvcGVydHlTeW1ib2xzKHBhdHRlcm4pKSkge1xuICAgICAgaWYgKCEoa2V5IGluIHZhbHVlKSB8fCAhbWF0Y2hlc1trZXldKHZhbHVlW2tleV0sIGFyZ3MpKSB7XG4gICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICByZXR1cm4gdHJ1ZTtcbiAgfTtcbn1cblxuZnVuY3Rpb24gcmVzb2x2ZU5vTWF0Y2goKSB7XG4gIHJldHVybiBmdW5jdGlvbiAoKSB7XG4gICAgcmV0dXJuIGZhbHNlO1xuICB9O1xufVxuXG52YXIgUmVzb2x2ZXJzID0ge1xuICByZXNvbHZlQm91bmQsXG4gIHJlc29sdmVXaWxkY2FyZCxcbiAgcmVzb2x2ZVZhcmlhYmxlLFxuICByZXNvbHZlSGVhZFRhaWwsXG4gIHJlc29sdmVDYXB0dXJlLFxuICByZXNvbHZlU3RhcnRzV2l0aCxcbiAgcmVzb2x2ZVR5cGUsXG4gIHJlc29sdmVBcnJheSxcbiAgcmVzb2x2ZU9iamVjdCxcbiAgcmVzb2x2ZU5vTWF0Y2gsXG4gIHJlc29sdmVTeW1ib2wsXG4gIHJlc29sdmVTdHJpbmcsXG4gIHJlc29sdmVOdW1iZXIsXG4gIHJlc29sdmVCb29sZWFuLFxuICByZXNvbHZlRnVuY3Rpb24sXG4gIHJlc29sdmVOdWxsXG59O1xuXG5mdW5jdGlvbiBidWlsZE1hdGNoKHBhdHRlcm4pIHtcblxuICBpZiAoQ2hlY2tzLmlzX3ZhcmlhYmxlKHBhdHRlcm4pKSB7XG4gICAgcmV0dXJuIFJlc29sdmVycy5yZXNvbHZlVmFyaWFibGUocGF0dGVybik7XG4gIH1cblxuICBpZiAoQ2hlY2tzLmlzX3dpbGRjYXJkKHBhdHRlcm4pKSB7XG4gICAgcmV0dXJuIFJlc29sdmVycy5yZXNvbHZlV2lsZGNhcmQocGF0dGVybik7XG4gIH1cblxuICBpZiAoQ2hlY2tzLmlzX3VuZGVmaW5lZChwYXR0ZXJuKSkge1xuICAgIHJldHVybiBSZXNvbHZlcnMucmVzb2x2ZVdpbGRjYXJkKHBhdHRlcm4pO1xuICB9XG5cbiAgaWYgKENoZWNrcy5pc19oZWFkVGFpbChwYXR0ZXJuKSkge1xuICAgIHJldHVybiBSZXNvbHZlcnMucmVzb2x2ZUhlYWRUYWlsKHBhdHRlcm4pO1xuICB9XG5cbiAgaWYgKENoZWNrcy5pc19zdGFydHNXaXRoKHBhdHRlcm4pKSB7XG4gICAgcmV0dXJuIFJlc29sdmVycy5yZXNvbHZlU3RhcnRzV2l0aChwYXR0ZXJuKTtcbiAgfVxuXG4gIGlmIChDaGVja3MuaXNfY2FwdHVyZShwYXR0ZXJuKSkge1xuICAgIHJldHVybiBSZXNvbHZlcnMucmVzb2x2ZUNhcHR1cmUocGF0dGVybik7XG4gIH1cblxuICBpZiAoQ2hlY2tzLmlzX2JvdW5kKHBhdHRlcm4pKSB7XG4gICAgcmV0dXJuIFJlc29sdmVycy5yZXNvbHZlQm91bmQocGF0dGVybik7XG4gIH1cblxuICBpZiAoQ2hlY2tzLmlzX3R5cGUocGF0dGVybikpIHtcbiAgICByZXR1cm4gUmVzb2x2ZXJzLnJlc29sdmVUeXBlKHBhdHRlcm4pO1xuICB9XG5cbiAgaWYgKENoZWNrcy5pc19hcnJheShwYXR0ZXJuKSkge1xuICAgIHJldHVybiBSZXNvbHZlcnMucmVzb2x2ZUFycmF5KHBhdHRlcm4pO1xuICB9XG5cbiAgaWYgKENoZWNrcy5pc19udW1iZXIocGF0dGVybikpIHtcbiAgICByZXR1cm4gUmVzb2x2ZXJzLnJlc29sdmVOdW1iZXIocGF0dGVybik7XG4gIH1cblxuICBpZiAoQ2hlY2tzLmlzX3N0cmluZyhwYXR0ZXJuKSkge1xuICAgIHJldHVybiBSZXNvbHZlcnMucmVzb2x2ZVN0cmluZyhwYXR0ZXJuKTtcbiAgfVxuXG4gIGlmIChDaGVja3MuaXNfYm9vbGVhbihwYXR0ZXJuKSkge1xuICAgIHJldHVybiBSZXNvbHZlcnMucmVzb2x2ZUJvb2xlYW4ocGF0dGVybik7XG4gIH1cblxuICBpZiAoQ2hlY2tzLmlzX3N5bWJvbChwYXR0ZXJuKSkge1xuICAgIHJldHVybiBSZXNvbHZlcnMucmVzb2x2ZVN5bWJvbChwYXR0ZXJuKTtcbiAgfVxuXG4gIGlmIChDaGVja3MuaXNfbnVsbChwYXR0ZXJuKSkge1xuICAgIHJldHVybiBSZXNvbHZlcnMucmVzb2x2ZU51bGwocGF0dGVybik7XG4gIH1cblxuICBpZiAoQ2hlY2tzLmlzX29iamVjdChwYXR0ZXJuKSkge1xuICAgIHJldHVybiBSZXNvbHZlcnMucmVzb2x2ZU9iamVjdChwYXR0ZXJuKTtcbiAgfVxuXG4gIHJldHVybiBSZXNvbHZlcnMucmVzb2x2ZU5vTWF0Y2goKTtcbn1cblxuY2xhc3MgTWF0Y2hFcnJvciBleHRlbmRzIEVycm9yIHtcbiAgY29uc3RydWN0b3IoYXJnKSB7XG4gICAgc3VwZXIoKTtcblxuICAgIGlmICh0eXBlb2YgYXJnID09PSAnc3ltYm9sJykge1xuICAgICAgdGhpcy5tZXNzYWdlID0gJ05vIG1hdGNoIGZvcjogJyArIGFyZy50b1N0cmluZygpO1xuICAgIH0gZWxzZSBpZiAoQXJyYXkuaXNBcnJheShhcmcpKSB7XG4gICAgICBsZXQgbWFwcGVkVmFsdWVzID0gYXJnLm1hcCh4ID0+IHgudG9TdHJpbmcoKSk7XG4gICAgICB0aGlzLm1lc3NhZ2UgPSAnTm8gbWF0Y2ggZm9yOiAnICsgbWFwcGVkVmFsdWVzO1xuICAgIH0gZWxzZSB7XG4gICAgICB0aGlzLm1lc3NhZ2UgPSAnTm8gbWF0Y2ggZm9yOiAnICsgYXJnO1xuICAgIH1cblxuICAgIHRoaXMuc3RhY2sgPSBuZXcgRXJyb3IoKS5zdGFjaztcbiAgICB0aGlzLm5hbWUgPSB0aGlzLmNvbnN0cnVjdG9yLm5hbWU7XG4gIH1cbn1cblxuY2xhc3MgQ2FzZSB7XG5cbiAgY29uc3RydWN0b3IocGF0dGVybiwgZm4sIGd1YXJkID0gKCkgPT4gdHJ1ZSkge1xuICAgIHRoaXMucGF0dGVybiA9IGJ1aWxkTWF0Y2gocGF0dGVybik7XG4gICAgdGhpcy5mbiA9IGZuO1xuICAgIHRoaXMuZ3VhcmQgPSBndWFyZDtcbiAgfVxufVxuXG5mdW5jdGlvbiBtYWtlX2Nhc2UocGF0dGVybiwgZm4sIGd1YXJkID0gKCkgPT4gdHJ1ZSkge1xuICByZXR1cm4gbmV3IENhc2UocGF0dGVybiwgZm4sIGd1YXJkKTtcbn1cblxuZnVuY3Rpb24gZGVmbWF0Y2goLi4uY2FzZXMpIHtcbiAgcmV0dXJuIGZ1bmN0aW9uICguLi5hcmdzKSB7XG4gICAgZm9yIChsZXQgcHJvY2Vzc2VkQ2FzZSBvZiBjYXNlcykge1xuICAgICAgbGV0IHJlc3VsdCA9IFtdO1xuICAgICAgaWYgKHByb2Nlc3NlZENhc2UucGF0dGVybihhcmdzLCByZXN1bHQpICYmIHByb2Nlc3NlZENhc2UuZ3VhcmQuYXBwbHkodGhpcywgcmVzdWx0KSkge1xuICAgICAgICByZXR1cm4gcHJvY2Vzc2VkQ2FzZS5mbi5hcHBseSh0aGlzLCByZXN1bHQpO1xuICAgICAgfVxuICAgIH1cblxuICAgIHRocm93IG5ldyBNYXRjaEVycm9yKGFyZ3MpO1xuICB9O1xufVxuXG5mdW5jdGlvbiBtYXRjaChwYXR0ZXJuLCBleHByLCBndWFyZCA9ICgpID0+IHRydWUpIHtcbiAgbGV0IHJlc3VsdCA9IFtdO1xuICBsZXQgcHJvY2Vzc2VkUGF0dGVybiA9IGJ1aWxkTWF0Y2gocGF0dGVybik7XG4gIGlmIChwcm9jZXNzZWRQYXR0ZXJuKGV4cHIsIHJlc3VsdCkgJiYgZ3VhcmQuYXBwbHkodGhpcywgcmVzdWx0KSkge1xuICAgIHJldHVybiByZXN1bHQ7XG4gIH0gZWxzZSB7XG4gICAgdGhyb3cgbmV3IE1hdGNoRXJyb3IoZXhwcik7XG4gIH1cbn1cblxuZnVuY3Rpb24gbWF0Y2hfbm9fdGhyb3cocGF0dGVybiwgZXhwciwgZ3VhcmQgPSAoKSA9PiB0cnVlKSB7XG4gIHRyeSB7XG4gICAgcmV0dXJuIG1hdGNoKHBhdHRlcm4sIGV4cHIsIGd1YXJkKTtcbiAgfSBjYXRjaCAoZSkge1xuICAgIGlmIChlIGluc3RhbmNlb2YgTWF0Y2hFcnJvcikge1xuICAgICAgcmV0dXJuIG51bGw7XG4gICAgfVxuXG4gICAgdGhyb3cgZTtcbiAgfVxufVxuXG52YXIgUGF0dGVybnMgPSB7XG4gIGRlZm1hdGNoLCBtYXRjaCwgTWF0Y2hFcnJvciwgbWF0Y2hfbm9fdGhyb3csXG4gIHZhcmlhYmxlLCB3aWxkY2FyZCwgc3RhcnRzV2l0aCxcbiAgY2FwdHVyZSwgaGVhZFRhaWwsIHR5cGUsIGJvdW5kLCBDYXNlLCBtYWtlX2Nhc2Vcbn07XG5cbmZ1bmN0aW9uIGNhbGxfcHJvcGVydHkoaXRlbSwgcHJvcGVydHkpIHtcbiAgaWYgKHByb3BlcnR5IGluIGl0ZW0pIHtcbiAgICBpdGVtW3Byb3BlcnR5XTtcbiAgICBpZiAoaXRlbVtwcm9wZXJ0eV0gaW5zdGFuY2VvZiBGdW5jdGlvbikge1xuICAgICAgcmV0dXJuIGl0ZW1bcHJvcGVydHldKCk7XG4gICAgfSBlbHNlIHtcbiAgICAgIHJldHVybiBpdGVtW3Byb3BlcnR5XTtcbiAgICB9XG4gIH0gZWxzZSBpZiAoU3ltYm9sLmZvcihwcm9wZXJ0eSkgaW4gaXRlbSkge1xuICAgIGxldCBwcm9wID0gU3ltYm9sLmZvcihwcm9wZXJ0eSk7XG4gICAgaWYgKGl0ZW1bcHJvcF0gaW5zdGFuY2VvZiBGdW5jdGlvbikge1xuICAgICAgcmV0dXJuIGl0ZW1bcHJvcF0oKTtcbiAgICB9IGVsc2Uge1xuICAgICAgcmV0dXJuIGl0ZW1bcHJvcF07XG4gICAgfVxuICB9XG5cbiAgdGhyb3cgbmV3IEVycm9yKGBQcm9wZXJ0eSAkeyBwcm9wZXJ0eSB9IG5vdCBmb3VuZCBpbiAkeyBpdGVtIH1gKTtcbn1cblxuZnVuY3Rpb24gaXNfaW5zdGFuY2Vfb2YodmFsdWUsIHR5cGUpIHtcbiAgcmV0dXJuIHZhbHVlIGluc3RhbmNlb2YgdHlwZTtcbn1cblxuZnVuY3Rpb24gc2l6ZSh0ZXJtKSB7XG4gIHJldHVybiB0ZXJtLmxlbmd0aDtcbn1cblxuZnVuY3Rpb24gaXNfbmlsJDEoeCkge1xuICByZXR1cm4geCA9PT0gbnVsbDtcbn1cblxuZnVuY3Rpb24gaXNfYXRvbSQxKHgpIHtcbiAgcmV0dXJuIHR5cGVvZiB4ID09PSAnc3ltYm9sJztcbn1cblxuZnVuY3Rpb24gaXNfYmluYXJ5JDEoeCkge1xuICByZXR1cm4gdHlwZW9mIHggPT09ICdzdHJpbmcnIHx8IHggaW5zdGFuY2VvZiBTdHJpbmc7XG59XG5cbmZ1bmN0aW9uIGlzX2Jvb2xlYW4kMSh4KSB7XG4gIHJldHVybiB0eXBlb2YgeCA9PT0gJ2Jvb2xlYW4nIHx8IHggaW5zdGFuY2VvZiBCb29sZWFuO1xufVxuXG5mdW5jdGlvbiBpc19mdW5jdGlvbiQxKHgsIGFyaXR5ID0gLTEpIHtcbiAgcmV0dXJuIHR5cGVvZiB4ID09PSAnZnVuY3Rpb24nIHx8IHggaW5zdGFuY2VvZiBGdW5jdGlvbjtcbn1cblxuZnVuY3Rpb24gaXNfZmxvYXQkMSh4KSB7XG4gIHJldHVybiBpc19udW1iZXIkMSh4KSAmJiAhTnVtYmVyLmlzSW50ZWdlcih4KTtcbn1cblxuZnVuY3Rpb24gaXNfaW50ZWdlciQxKHgpIHtcbiAgcmV0dXJuIE51bWJlci5pc0ludGVnZXIoeCk7XG59XG5cbmZ1bmN0aW9uIGlzX2xpc3QkMSh4KSB7XG4gIHJldHVybiB4IGluc3RhbmNlb2YgQXJyYXk7XG59XG5cbmZ1bmN0aW9uIGlzX21hcCQxKHgpIHtcbiAgcmV0dXJuIHR5cGVvZiB4ID09PSAnb2JqZWN0JyB8fCB4IGluc3RhbmNlb2YgT2JqZWN0O1xufVxuXG5mdW5jdGlvbiBpc19udW1iZXIkMSh4KSB7XG4gIHJldHVybiB0eXBlb2YgeCA9PT0gJ251bWJlcic7XG59XG5cbmZ1bmN0aW9uIGlzX3R1cGxlJDEoeCkge1xuICByZXR1cm4geCBpbnN0YW5jZW9mIFR1cGxlO1xufVxuXG5mdW5jdGlvbiBpc19waWQkMSh4KSB7XG4gIHJldHVybiB4IGluc3RhbmNlb2YgUElEO1xufVxuXG5mdW5jdGlvbiBpc19wb3J0JDEoeCkge1xuICByZXR1cm4gZmFsc2U7XG59XG5cbmZ1bmN0aW9uIGlzX3JlZmVyZW5jZSQxKHgpIHtcbiAgcmV0dXJuIGZhbHNlO1xufVxuXG5mdW5jdGlvbiBpc19iaXRzdHJpbmckMSh4KSB7XG4gIHJldHVybiBpc19iaW5hcnkkMSh4KSB8fCB4IGluc3RhbmNlb2YgQml0U3RyaW5nO1xufVxuXG5mdW5jdGlvbiBhZGQob25lLCB0d28pIHtcbiAgcmV0dXJuIG9uZSArIHR3bztcbn1cblxuZnVuY3Rpb24gc3VidHJhY3Qob25lLCB0d28pIHtcbiAgcmV0dXJuIG9uZSArIHR3bztcbn1cblxuZnVuY3Rpb24gbXVsdGlwbHkob25lLCB0d28pIHtcbiAgcmV0dXJuIG9uZSArIHR3bztcbn1cblxuZnVuY3Rpb24gZGl2aWRlKG9uZSwgdHdvKSB7XG4gIHJldHVybiBvbmUgKyB0d287XG59XG5cbmZ1bmN0aW9uIHJlbWFpbmRlcihvbmUsIHR3bykge1xuICByZXR1cm4gb25lICsgdHdvO1xufVxuXG5mdW5jdGlvbiBhcHBseSQxKC4uLmFyZ3MpIHtcbiAgaWYgKGFyZ3MubGVuZ3RoID09PSAyKSB7XG4gICAgYXJnc1swXS5hcHBseShudWxsLCBhcmdzLnNsaWNlKDEpKTtcbiAgfSBlbHNlIHtcbiAgICBhcmdzWzBdW2FyZ3NbMV1dLmFwcGx5KG51bGwsIGFyZ3Muc2xpY2UoMikpO1xuICB9XG59XG5cbmZ1bmN0aW9uIG5ld190dXBsZSguLi5hcmdzKSB7XG4gIHJldHVybiBuZXcgVHVwbGUoLi4uYXJncyk7XG59XG5cbmZ1bmN0aW9uIGR1cGxpY2F0ZShkYXRhLCBzaXplKSB7XG4gIGxldCBhcnJheSA9IFtdO1xuXG4gIGZvciAodmFyIGkgPSBzaXplIC0gMTsgaSA+PSAwOyBpLS0pIHtcbiAgICBhcnJheS5wdXNoKGRhdGEpO1xuICB9XG5cbiAgcmV0dXJuIGFycmF5O1xufVxuXG5mdW5jdGlvbiBjb250YWlucyhsZWZ0LCByaWdodCkge1xuICBmb3IgKGxldCB4IG9mIHJpZ2h0KSB7XG4gICAgaWYgKFBhdHRlcm5zLm1hdGNoX25vX3Rocm93KGxlZnQsIHgpICE9IG51bGwpIHtcbiAgICAgIHJldHVybiB0cnVlO1xuICAgIH1cbiAgfVxuXG4gIHJldHVybiBmYWxzZTtcbn1cblxuZnVuY3Rpb24gcmV2ZXJzZShsaXN0KSB7XG4gIHJldHVybiBsaXN0LmNvbmNhdChbXSkucmV2ZXJzZSgpO1xufVxuXG5mdW5jdGlvbiBnZXRfZ2xvYmFsKCkge1xuICBpZiAodHlwZW9mIHNlbGYgIT09ICd1bmRlZmluZWQnKSB7XG4gICAgcmV0dXJuIHNlbGY7XG4gIH0gZWxzZSBpZiAodHlwZW9mIHdpbmRvdyAhPT0gJ3VuZGVmaW5lZCcpIHtcbiAgICByZXR1cm4gd2luZG93O1xuICB9IGVsc2UgaWYgKHR5cGVvZiBnbG9iYWwgIT09ICd1bmRlZmluZWQnKSB7XG4gICAgcmV0dXJuIGdsb2JhbDtcbiAgfVxuXG4gIHRocm93IG5ldyBFcnJvcignTm8gZ2xvYmFsIHN0YXRlIGZvdW5kJyk7XG59XG5cbmZ1bmN0aW9uIGNvbmNhdF9saXN0cyhsZWZ0LCByaWdodCkge1xuICByZXR1cm4gbGVmdC5jb25jYXQocmlnaHQpO1xufVxuXG5mdW5jdGlvbiBwcmVwZW5kX3RvX2xpc3QobGlzdCwgaXRlbSkge1xuICByZXR1cm4gW2l0ZW1dLmNvbmNhdChsaXN0KTtcbn1cblxuZnVuY3Rpb24gZGVmc3RydWN0KGRlZmF1bHRzKSB7XG4gIHJldHVybiBjbGFzcyB7XG4gICAgY29uc3RydWN0b3IodXBkYXRlID0ge30pIHtcbiAgICAgIGxldCB0aGVfdmFsdWVzID0gT2JqZWN0LmFzc2lnbihkZWZhdWx0cywgdXBkYXRlKTtcbiAgICAgIE9iamVjdC5hc3NpZ24odGhpcywgdGhlX3ZhbHVlcyk7XG4gICAgfVxuXG4gICAgc3RhdGljIGNyZWF0ZSh1cGRhdGVzID0ge30pIHtcbiAgICAgIGxldCB4ID0gbmV3IHRoaXModXBkYXRlcyk7XG4gICAgICByZXR1cm4gT2JqZWN0LmZyZWV6ZSh4KTtcbiAgICB9XG4gIH07XG59XG5cbmZ1bmN0aW9uIGRlZmV4Y2VwdGlvbihkZWZhdWx0cykge1xuICByZXR1cm4gY2xhc3MgZXh0ZW5kcyBFcnJvciB7XG4gICAgY29uc3RydWN0b3IodXBkYXRlID0ge30pIHtcbiAgICAgIGxldCBtZXNzYWdlID0gdXBkYXRlLm1lc3NhZ2UgfHwgJyc7XG4gICAgICBzdXBlcihtZXNzYWdlKTtcblxuICAgICAgbGV0IHRoZV92YWx1ZXMgPSBPYmplY3QuYXNzaWduKGRlZmF1bHRzLCB1cGRhdGUpO1xuICAgICAgT2JqZWN0LmFzc2lnbih0aGlzLCB0aGVfdmFsdWVzKTtcblxuICAgICAgdGhpcy5uYW1lID0gdGhpcy5jb25zdHJ1Y3Rvci5uYW1lO1xuICAgICAgdGhpcy5tZXNzYWdlID0gbWVzc2FnZTtcbiAgICAgIHRoaXNbU3BlY2lhbEZvcm1zLmF0b20oJ19fZXhjZXB0aW9uX18nKV0gPSB0cnVlO1xuICAgICAgRXJyb3IuY2FwdHVyZVN0YWNrVHJhY2UodGhpcywgdGhpcy5jb25zdHJ1Y3Rvci5uYW1lKTtcbiAgICB9XG5cbiAgICBzdGF0aWMgY3JlYXRlKHVwZGF0ZXMgPSB7fSkge1xuICAgICAgbGV0IHggPSBuZXcgdGhpcyh1cGRhdGVzKTtcbiAgICAgIHJldHVybiBPYmplY3QuZnJlZXplKHgpO1xuICAgIH1cbiAgfTtcbn1cblxuZnVuY3Rpb24gZGVmcHJvdG9jb2woc3BlYykge1xuICByZXR1cm4gbmV3IFByb3RvY29sKHNwZWMpO1xufVxuXG5mdW5jdGlvbiBkZWZpbXBsKHByb3RvY29sLCB0eXBlLCBpbXBsKSB7XG4gIHByb3RvY29sLmltcGxlbWVudGF0aW9uKHR5cGUsIGltcGwpO1xufVxuXG5mdW5jdGlvbiBnZXRfb2JqZWN0X2tleXMob2JqKSB7XG4gIHJldHVybiBPYmplY3Qua2V5cyhvYmopLmNvbmNhdChPYmplY3QuZ2V0T3duUHJvcGVydHlTeW1ib2xzKG9iaikpO1xufVxuXG5mdW5jdGlvbiBpc192YWxpZF9jaGFyYWN0ZXIoY29kZXBvaW50KSB7XG4gIHRyeSB7XG4gICAgcmV0dXJuIFN0cmluZy5mcm9tQ29kZVBvaW50KGNvZGVwb2ludCkgIT0gbnVsbDtcbiAgfSBjYXRjaCAoZSkge1xuICAgIHJldHVybiBmYWxzZTtcbiAgfVxufVxuXG4vL2h0dHBzOi8vZGV2ZWxvcGVyLm1vemlsbGEub3JnL2VuLVVTL2RvY3MvV2ViL0FQSS9XaW5kb3dCYXNlNjQvQmFzZTY0X2VuY29kaW5nX2FuZF9kZWNvZGluZyNTb2x1dGlvbl8yXyVFMiU4MCU5M19yZXdyaXRlX3RoZV9ET01zX2F0b2IoKV9hbmRfYnRvYSgpX3VzaW5nX0phdmFTY3JpcHQnc19UeXBlZEFycmF5c19hbmRfVVRGLThcbmZ1bmN0aW9uIGI2NEVuY29kZVVuaWNvZGUoc3RyKSB7XG4gIHJldHVybiBidG9hKGVuY29kZVVSSUNvbXBvbmVudChzdHIpLnJlcGxhY2UoLyUoWzAtOUEtRl17Mn0pL2csIGZ1bmN0aW9uIChtYXRjaCwgcDEpIHtcbiAgICByZXR1cm4gU3RyaW5nLmZyb21DaGFyQ29kZSgnMHgnICsgcDEpO1xuICB9KSk7XG59XG5cbmZ1bmN0aW9uIGRlbGV0ZV9wcm9wZXJ0eV9mcm9tX21hcChtYXAsIHByb3BlcnR5KSB7XG4gIGxldCBuZXdfbWFwID0gT2JqZWN0LmFzc2lnbihPYmplY3QuY3JlYXRlKG1hcC5jb25zdHJ1Y3Rvci5wcm90b3R5cGUpLCBtYXApO1xuICBkZWxldGUgbmV3X21hcFtwcm9wZXJ0eV07XG5cbiAgcmV0dXJuIE9iamVjdC5mcmVlemUobmV3X21hcCk7XG59XG5cbmZ1bmN0aW9uIGNsYXNzX3RvX29iaihtYXApIHtcbiAgbGV0IG5ld19tYXAgPSBPYmplY3QuYXNzaWduKHt9LCBtYXApO1xuICByZXR1cm4gT2JqZWN0LmZyZWV6ZShuZXdfbWFwKTtcbn1cblxuZnVuY3Rpb24gYWRkX3Byb3BlcnR5X3RvX21hcChtYXAsIHByb3BlcnR5LCB2YWx1ZSkge1xuICBsZXQgbmV3X21hcCA9IE9iamVjdC5hc3NpZ24oe30sIG1hcCk7XG4gIG5ld19tYXBbcHJvcGVydHldID0gdmFsdWU7XG4gIHJldHVybiBPYmplY3QuZnJlZXplKG5ld19tYXApO1xufVxuXG5mdW5jdGlvbiBibm90KGV4cHIpIHtcbiAgcmV0dXJuIH5leHByO1xufVxuXG5mdW5jdGlvbiBiYW5kKGxlZnQsIHJpZ2h0KSB7XG4gIHJldHVybiBsZWZ0ICYgcmlnaHQ7XG59XG5cbmZ1bmN0aW9uIGJvcihsZWZ0LCByaWdodCkge1xuICByZXR1cm4gbGVmdCB8IHJpZ2h0O1xufVxuXG5mdW5jdGlvbiBic2wobGVmdCwgcmlnaHQpIHtcbiAgcmV0dXJuIGxlZnQgPDwgcmlnaHQ7XG59XG5cbmZ1bmN0aW9uIGJzcihsZWZ0LCByaWdodCkge1xuICByZXR1cm4gbGVmdCA+PiByaWdodDtcbn1cblxuZnVuY3Rpb24gYnhvcihsZWZ0LCByaWdodCkge1xuICByZXR1cm4gbGVmdCBeIHJpZ2h0O1xufVxuXG5mdW5jdGlvbiB6aXAobGlzdF9vZl9saXN0cykge1xuICBpZiAobGlzdF9vZl9saXN0cy5sZW5ndGggPT09IDApIHtcbiAgICByZXR1cm4gT2JqZWN0LmZyZWV6ZShbXSk7XG4gIH1cblxuICBsZXQgbmV3X3ZhbHVlID0gW107XG4gIGxldCBzbWFsbGVzdF9sZW5ndGggPSBsaXN0X29mX2xpc3RzWzBdO1xuXG4gIGZvciAobGV0IHggb2YgbGlzdF9vZl9saXN0cykge1xuICAgIGlmICh4Lmxlbmd0aCA8IHNtYWxsZXN0X2xlbmd0aCkge1xuICAgICAgc21hbGxlc3RfbGVuZ3RoID0geC5sZW5ndGg7XG4gICAgfVxuICB9XG5cbiAgZm9yIChsZXQgaSA9IDA7IGkgPCBzbWFsbGVzdF9sZW5ndGg7IGkrKykge1xuICAgIGxldCBjdXJyZW50X3ZhbHVlID0gW107XG4gICAgZm9yIChsZXQgaiA9IDA7IGogPCBsaXN0X29mX2xpc3RzLmxlbmd0aDsgaisrKSB7XG4gICAgICBjdXJyZW50X3ZhbHVlLnB1c2gobGlzdF9vZl9saXN0c1tqXVtpXSk7XG4gICAgfVxuXG4gICAgbmV3X3ZhbHVlLnB1c2gobmV3IFR1cGxlKC4uLmN1cnJlbnRfdmFsdWUpKTtcbiAgfVxuXG4gIHJldHVybiBPYmplY3QuZnJlZXplKG5ld192YWx1ZSk7XG59XG5cbnZhciBGdW5jdGlvbnMgPSB7XG4gIGNhbGxfcHJvcGVydHksXG4gIGlzX2luc3RhbmNlX29mLFxuICBzaXplLFxuICBpc19uaWw6IGlzX25pbCQxLFxuICBpc19hdG9tOiBpc19hdG9tJDEsXG4gIGlzX2JpbmFyeTogaXNfYmluYXJ5JDEsXG4gIGlzX2Jvb2xlYW46IGlzX2Jvb2xlYW4kMSxcbiAgaXNfZnVuY3Rpb246IGlzX2Z1bmN0aW9uJDEsXG4gIGlzX2Zsb2F0OiBpc19mbG9hdCQxLFxuICBpc19pbnRlZ2VyOiBpc19pbnRlZ2VyJDEsXG4gIGlzX2xpc3Q6IGlzX2xpc3QkMSxcbiAgaXNfbWFwOiBpc19tYXAkMSxcbiAgaXNfbnVtYmVyOiBpc19udW1iZXIkMSxcbiAgaXNfdHVwbGU6IGlzX3R1cGxlJDEsXG4gIGlzX3BpZDogaXNfcGlkJDEsXG4gIGlzX3BvcnQ6IGlzX3BvcnQkMSxcbiAgaXNfcmVmZXJlbmNlOiBpc19yZWZlcmVuY2UkMSxcbiAgaXNfYml0c3RyaW5nOiBpc19iaXRzdHJpbmckMSxcbiAgYWRkLFxuICBzdWJ0cmFjdCxcbiAgbXVsdGlwbHksXG4gIGRpdmlkZSxcbiAgcmVtYWluZGVyLFxuICBhcHBseTogYXBwbHkkMSxcbiAgbmV3X3R1cGxlLFxuICBkdXBsaWNhdGUsXG4gIGNvbnRhaW5zLFxuICByZXZlcnNlLFxuICBnZXRfZ2xvYmFsLFxuICBjb25jYXRfbGlzdHMsXG4gIHByZXBlbmRfdG9fbGlzdCxcbiAgZGVmc3RydWN0LFxuICBkZWZleGNlcHRpb24sXG4gIGRlZnByb3RvY29sLFxuICBkZWZpbXBsLFxuICBnZXRfb2JqZWN0X2tleXMsXG4gIGlzX3ZhbGlkX2NoYXJhY3RlcixcbiAgYjY0RW5jb2RlVW5pY29kZSxcbiAgZGVsZXRlX3Byb3BlcnR5X2Zyb21fbWFwLFxuICBhZGRfcHJvcGVydHlfdG9fbWFwLFxuICBjbGFzc190b19vYmosXG4gIGJub3QsXG4gIGJhbmQsXG4gIGJvcixcbiAgYnNsLFxuICBic3IsXG4gIGJ4b3IsXG4gIHppcFxufTtcblxuZnVuY3Rpb24gbGlzdCguLi5hcmdzKSB7XG4gIHJldHVybiBPYmplY3QuZnJlZXplKGFyZ3MpO1xufVxuXG5mdW5jdGlvbiBiaXRzdHJpbmcoLi4uYXJncykge1xuICByZXR1cm4gbmV3IEJpdFN0cmluZyguLi5hcmdzKTtcbn1cblxuZnVuY3Rpb24gdHVwbGUoLi4uYXJncykge1xuICByZXR1cm4gbmV3IFR1cGxlKC4uLmFyZ3MpO1xufVxuXG5mdW5jdGlvbiBfY2FzZShjb25kaXRpb24sIGNsYXVzZXMpIHtcbiAgcmV0dXJuIFBhdHRlcm5zLmRlZm1hdGNoKC4uLmNsYXVzZXMpKGNvbmRpdGlvbik7XG59XG5cbmZ1bmN0aW9uIGNvbmQoY2xhdXNlcykge1xuICBmb3IgKGxldCBjbGF1c2Ugb2YgY2xhdXNlcykge1xuICAgIGlmIChjbGF1c2VbMF0pIHtcbiAgICAgIHJldHVybiBjbGF1c2VbMV0oKTtcbiAgICB9XG4gIH1cblxuICB0aHJvdyBuZXcgRXJyb3IoKTtcbn1cblxuZnVuY3Rpb24gbWFwKG9iaikge1xuICByZXR1cm4gT2JqZWN0LmZyZWV6ZShvYmopO1xufVxuXG5mdW5jdGlvbiBtYXBfdXBkYXRlKG1hcCwgdmFsdWVzKSB7XG4gIHJldHVybiBPYmplY3QuZnJlZXplKE9iamVjdC5hc3NpZ24oT2JqZWN0LmNyZWF0ZShtYXAuY29uc3RydWN0b3IucHJvdG90eXBlKSwgbWFwLCB2YWx1ZXMpKTtcbn1cblxuZnVuY3Rpb24gX2Zvcihjb2xsZWN0aW9ucywgZnVuLCBmaWx0ZXIgPSAoKSA9PiB0cnVlLCBpbnRvID0gW10sIHByZXZpb3VzVmFsdWVzID0gW10pIHtcbiAgbGV0IHBhdHRlcm4gPSBjb2xsZWN0aW9uc1swXVswXTtcbiAgbGV0IGNvbGxlY3Rpb24gPSBjb2xsZWN0aW9uc1swXVsxXTtcblxuICBpZiAoY29sbGVjdGlvbnMubGVuZ3RoID09PSAxKSB7XG5cbiAgICBmb3IgKGxldCBlbGVtIG9mIGNvbGxlY3Rpb24pIHtcbiAgICAgIGxldCByID0gUGF0dGVybnMubWF0Y2hfbm9fdGhyb3cocGF0dGVybiwgZWxlbSk7XG4gICAgICBsZXQgYXJncyA9IHByZXZpb3VzVmFsdWVzLmNvbmNhdChyKTtcblxuICAgICAgaWYgKHIgJiYgZmlsdGVyLmFwcGx5KHRoaXMsIGFyZ3MpKSB7XG4gICAgICAgIGludG8gPSBpbnRvLmNvbmNhdChbZnVuLmFwcGx5KHRoaXMsIGFyZ3MpXSk7XG4gICAgICB9XG4gICAgfVxuXG4gICAgcmV0dXJuIGludG87XG4gIH0gZWxzZSB7XG4gICAgbGV0IF9pbnRvID0gW107XG5cbiAgICBmb3IgKGxldCBlbGVtIG9mIGNvbGxlY3Rpb24pIHtcbiAgICAgIGxldCByID0gUGF0dGVybnMubWF0Y2hfbm9fdGhyb3cocGF0dGVybiwgZWxlbSk7XG4gICAgICBpZiAocikge1xuICAgICAgICBfaW50byA9IGludG8uY29uY2F0KHRoaXMuX2Zvcihjb2xsZWN0aW9ucy5zbGljZSgxKSwgZnVuLCBmaWx0ZXIsIF9pbnRvLCBwcmV2aW91c1ZhbHVlcy5jb25jYXQocikpKTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICByZXR1cm4gX2ludG87XG4gIH1cbn1cblxuZnVuY3Rpb24gX3RyeShkb19mdW4sIHJlc2N1ZV9mdW5jdGlvbiwgY2F0Y2hfZnVuLCBlbHNlX2Z1bmN0aW9uLCBhZnRlcl9mdW5jdGlvbikge1xuICBsZXQgcmVzdWx0ID0gbnVsbDtcblxuICB0cnkge1xuICAgIHJlc3VsdCA9IGRvX2Z1bigpO1xuICB9IGNhdGNoIChlKSB7XG4gICAgbGV0IGV4X3Jlc3VsdCA9IG51bGw7XG5cbiAgICBpZiAocmVzY3VlX2Z1bmN0aW9uKSB7XG4gICAgICB0cnkge1xuICAgICAgICBleF9yZXN1bHQgPSByZXNjdWVfZnVuY3Rpb24oZSk7XG4gICAgICAgIHJldHVybiBleF9yZXN1bHQ7XG4gICAgICB9IGNhdGNoIChleCkge1xuICAgICAgICBpZiAoZXggaW5zdGFuY2VvZiBQYXR0ZXJucy5NYXRjaEVycm9yKSB7XG4gICAgICAgICAgdGhyb3cgZXg7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9XG5cbiAgICBpZiAoY2F0Y2hfZnVuKSB7XG4gICAgICB0cnkge1xuICAgICAgICBleF9yZXN1bHQgPSBjYXRjaF9mdW4oZSk7XG4gICAgICAgIHJldHVybiBleF9yZXN1bHQ7XG4gICAgICB9IGNhdGNoIChleCkge1xuICAgICAgICBpZiAoZXggaW5zdGFuY2VvZiBQYXR0ZXJucy5NYXRjaEVycm9yKSB7XG4gICAgICAgICAgdGhyb3cgZXg7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9XG5cbiAgICB0aHJvdyBlO1xuICB9IGZpbmFsbHkge1xuICAgIGlmIChhZnRlcl9mdW5jdGlvbikge1xuICAgICAgYWZ0ZXJfZnVuY3Rpb24oKTtcbiAgICB9XG4gIH1cblxuICBpZiAoZWxzZV9mdW5jdGlvbikge1xuICAgIHRyeSB7XG4gICAgICByZXR1cm4gZWxzZV9mdW5jdGlvbihyZXN1bHQpO1xuICAgIH0gY2F0Y2ggKGV4KSB7XG4gICAgICBpZiAoZXggaW5zdGFuY2VvZiBQYXR0ZXJucy5NYXRjaEVycm9yKSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcignTm8gTWF0Y2ggRm91bmQgaW4gRWxzZScpO1xuICAgICAgfVxuXG4gICAgICB0aHJvdyBleDtcbiAgICB9XG4gIH0gZWxzZSB7XG4gICAgcmV0dXJuIHJlc3VsdDtcbiAgfVxufVxuXG52YXIgU3BlY2lhbEZvcm1zJDEgPSB7XG4gIGxpc3QsXG4gIGJpdHN0cmluZyxcbiAgdHVwbGUsXG4gIF9jYXNlLFxuICBjb25kLFxuICBtYXAsXG4gIG1hcF91cGRhdGUsXG4gIF9mb3IsXG4gIF90cnlcbn07XG5cbkZ1bmN0aW9ucy5nZXRfZ2xvYmFsKCkucHJvY2Vzc2VzID0gRnVuY3Rpb25zLmdldF9nbG9iYWwoKS5wcm9jZXNzZXMgfHwgbmV3IFByb2Nlc3NTeXN0ZW0oKTtcblxuXG5cbnZhciBDID0gT2JqZWN0LmZyZWV6ZSh7XG5cdFByb2Nlc3NTeXN0ZW06IFByb2Nlc3NTeXN0ZW0sXG5cdFR1cGxlOiBUdXBsZSxcblx0UElEOiBQSUQsXG5cdEJpdFN0cmluZzogQml0U3RyaW5nLFxuXHRQYXR0ZXJuczogUGF0dGVybnMsXG5cdEludGVnZXI6IEludGVnZXIsXG5cdEZsb2F0OiBGbG9hdCxcblx0RnVuY3Rpb25zOiBGdW5jdGlvbnMsXG5cdExpc3Q6IExpc3QsXG5cdFNwZWNpYWxGb3JtczogU3BlY2lhbEZvcm1zJDFcbn0pO1xuXG5mdW5jdGlvbiB0bChsaXN0KSB7XG4gIHJldHVybiBTcGVjaWFsRm9ybXMkMS5saXN0KC4uLmxpc3Quc2xpY2UoMSkpO1xufVxuXG5mdW5jdGlvbiBoZChsaXN0KSB7XG4gIHJldHVybiBsaXN0WzBdO1xufVxuXG5mdW5jdGlvbiBpc19uaWwoeCkge1xuICByZXR1cm4geCA9PT0gbnVsbDtcbn1cblxuZnVuY3Rpb24gaXNfYXRvbSh4KSB7XG4gIHJldHVybiB0eXBlb2YgeCA9PT0gJ3N5bWJvbCc7XG59XG5cbmZ1bmN0aW9uIGlzX2JpbmFyeSh4KSB7XG4gIHJldHVybiB0eXBlb2YgeCA9PT0gJ3N0cmluZycgfHwgeCBpbnN0YW5jZW9mIFN0cmluZztcbn1cblxuZnVuY3Rpb24gaXNfYm9vbGVhbih4KSB7XG4gIHJldHVybiB0eXBlb2YgeCA9PT0gJ2Jvb2xlYW4nIHx8IHggaW5zdGFuY2VvZiBCb29sZWFuO1xufVxuXG5mdW5jdGlvbiBpc19mdW5jdGlvbih4LCBhcml0eSA9IC0xKSB7XG4gIHJldHVybiB0eXBlb2YgeCA9PT0gJ2Z1bmN0aW9uJyB8fCB4IGluc3RhbmNlb2YgRnVuY3Rpb247XG59XG5cbmZ1bmN0aW9uIGlzX2Zsb2F0KHgpIHtcbiAgcmV0dXJuIGlzX251bWJlcih4KSAmJiAhTnVtYmVyLmlzSW50ZWdlcih4KTtcbn1cblxuZnVuY3Rpb24gaXNfaW50ZWdlcih4KSB7XG4gIHJldHVybiBOdW1iZXIuaXNJbnRlZ2VyKHgpO1xufVxuXG5mdW5jdGlvbiBpc19saXN0KHgpIHtcbiAgcmV0dXJuIHggaW5zdGFuY2VvZiBBcnJheTtcbn1cblxuZnVuY3Rpb24gaXNfbWFwKHgpIHtcbiAgcmV0dXJuIHR5cGVvZiB4ID09PSAnb2JqZWN0JyB8fCB4IGluc3RhbmNlb2YgT2JqZWN0O1xufVxuXG5mdW5jdGlvbiBpc19udW1iZXIoeCkge1xuICByZXR1cm4gdHlwZW9mIHggPT09ICdudW1iZXInO1xufVxuXG5mdW5jdGlvbiBpc190dXBsZSh4KSB7XG4gIHJldHVybiB4IGluc3RhbmNlb2YgVHVwbGU7XG59XG5cbmZ1bmN0aW9uIGxlbmd0aCh4KSB7XG4gIHJldHVybiB4Lmxlbmd0aDtcbn1cblxuZnVuY3Rpb24gaXNfcGlkKHgpIHtcbiAgcmV0dXJuIHggaW5zdGFuY2VvZiBQSUQ7XG59XG5cbmZ1bmN0aW9uIGlzX3BvcnQoeCkge1xuICByZXR1cm4gZmFsc2U7XG59XG5cbmZ1bmN0aW9uIGlzX3JlZmVyZW5jZSh4KSB7XG4gIHJldHVybiBmYWxzZTtcbn1cblxuZnVuY3Rpb24gaXNfYml0c3RyaW5nKHgpIHtcbiAgcmV0dXJuIGlzX2JpbmFyeSh4KSB8fCB4IGluc3RhbmNlb2YgQml0U3RyaW5nO1xufVxuXG5mdW5jdGlvbiBfX2luX18obGVmdCwgcmlnaHQpIHtcbiAgZm9yIChsZXQgeCBvZiByaWdodCkge1xuICAgIGlmIChtYXRjaF9fcW1hcmtfXyhsZWZ0LCB4KSkge1xuICAgICAgcmV0dXJuIHRydWU7XG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIGZhbHNlO1xufVxuXG5mdW5jdGlvbiBhYnMobnVtYmVyKSB7XG4gIHJldHVybiBNYXRoLmFicyhudW1iZXIpO1xufVxuXG5mdW5jdGlvbiByb3VuZChudW1iZXIpIHtcbiAgcmV0dXJuIE1hdGgucm91bmQobnVtYmVyKTtcbn1cblxuZnVuY3Rpb24gZWxlbSh0dXBsZSwgaW5kZXgpIHtcbiAgaWYgKGlzX2xpc3QodHVwbGUpKSB7XG4gICAgcmV0dXJuIHR1cGxlW2luZGV4XTtcbiAgfVxuXG4gIHJldHVybiB0dXBsZS5nZXQoaW5kZXgpO1xufVxuXG5mdW5jdGlvbiByZW0obGVmdCwgcmlnaHQpIHtcbiAgcmV0dXJuIGxlZnQgJSByaWdodDtcbn1cblxuZnVuY3Rpb24gZGl2KGxlZnQsIHJpZ2h0KSB7XG4gIHJldHVybiBsZWZ0IC8gcmlnaHQ7XG59XG5cbmZ1bmN0aW9uIGFuZChsZWZ0LCByaWdodCkge1xuICByZXR1cm4gbGVmdCAmJiByaWdodDtcbn1cblxuZnVuY3Rpb24gb3IobGVmdCwgcmlnaHQpIHtcbiAgcmV0dXJuIGxlZnQgfHwgcmlnaHQ7XG59XG5cbmZ1bmN0aW9uIG5vdChhcmcpIHtcbiAgcmV0dXJuICFhcmc7XG59XG5cbmZ1bmN0aW9uIGFwcGx5KC4uLmFyZ3MpIHtcbiAgaWYgKGFyZ3MubGVuZ3RoID09PSAzKSB7XG4gICAgbGV0IG1vZCA9IGFyZ3NbMF07XG4gICAgbGV0IGZ1bmMgPSBhcmdzWzFdO1xuICAgIGxldCBmdW5jX2FyZ3MgPSBhcmdzWzJdO1xuICAgIHJldHVybiBtb2RbZnVuY10uYXBwbHkobnVsbCwgZnVuY19hcmdzKTtcbiAgfSBlbHNlIHtcbiAgICBsZXQgZnVuYyA9IGFyZ3NbMF07XG4gICAgbGV0IGZ1bmNfYXJncyA9IGFyZ3NbMV07XG5cbiAgICByZXR1cm4gZnVuYy5hcHBseShudWxsLCBmdW5jX2FyZ3MpO1xuICB9XG59XG5cbmZ1bmN0aW9uIHRvX3N0cmluZyhhcmcpIHtcbiAgaWYgKGlzX3R1cGxlKGFyZykpIHtcbiAgICByZXR1cm4gYXJnLnRvU3RyaW5nKCk7XG4gIH1cblxuICByZXR1cm4gYXJnLnRvU3RyaW5nKCk7XG59XG5cbmZ1bmN0aW9uIG1hdGNoX19xbWFya19fKHBhdHRlcm4sIGV4cHIsIGd1YXJkID0gKCkgPT4gdHJ1ZSkge1xuICByZXR1cm4gUGF0dGVybnMubWF0Y2hfbm9fdGhyb3cocGF0dGVybiwgZXhwciwgZ3VhcmQpICE9IG51bGw7XG59XG5cbnZhciBrZXJuZWwgPSB7XG4gIHRsLFxuICBoZCxcbiAgaXNfbmlsLFxuICBpc19hdG9tLFxuICBpc19iaW5hcnksXG4gIGlzX2Jvb2xlYW4sXG4gIGlzX2Z1bmN0aW9uLFxuICBpc19mbG9hdCxcbiAgaXNfaW50ZWdlcixcbiAgaXNfbGlzdCxcbiAgaXNfbWFwLFxuICBpc19udW1iZXIsXG4gIGlzX3R1cGxlLFxuICBsZW5ndGgsXG4gIGlzX3BpZCxcbiAgaXNfcG9ydCxcbiAgaXNfcmVmZXJlbmNlLFxuICBpc19iaXRzdHJpbmcsXG4gIGluOiBfX2luX18sXG4gIGFicyxcbiAgcm91bmQsXG4gIGVsZW0sXG4gIHJlbSxcbiAgZGl2LFxuICBhbmQsXG4gIG9yLFxuICBub3QsXG4gIGFwcGx5LFxuICB0b19zdHJpbmcsXG4gIG1hdGNoX19xbWFya19fXG59O1xuXG5sZXQgRW51bSA9IHtcblxuICBhbGxfX3FtYXJrX186IGZ1bmN0aW9uIChjb2xsZWN0aW9uLCBmdW4gPSB4ID0+IHgpIHtcbiAgICBmb3IgKGxldCBlbGVtIG9mIGNvbGxlY3Rpb24pIHtcbiAgICAgIGlmICghZnVuKGVsZW0pKSB7XG4gICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICByZXR1cm4gdHJ1ZTtcbiAgfSxcblxuICBhbnlfX3FtYXJrX186IGZ1bmN0aW9uIChjb2xsZWN0aW9uLCBmdW4gPSB4ID0+IHgpIHtcbiAgICBmb3IgKGxldCBlbGVtIG9mIGNvbGxlY3Rpb24pIHtcbiAgICAgIGlmIChmdW4oZWxlbSkpIHtcbiAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICB9XG4gICAgfVxuXG4gICAgcmV0dXJuIGZhbHNlO1xuICB9LFxuXG4gIGF0OiBmdW5jdGlvbiAoY29sbGVjdGlvbiwgbiwgdGhlX2RlZmF1bHQgPSBudWxsKSB7XG4gICAgaWYgKG4gPiB0aGlzLmNvdW50KGNvbGxlY3Rpb24pIHx8IG4gPCAwKSB7XG4gICAgICByZXR1cm4gdGhlX2RlZmF1bHQ7XG4gICAgfVxuXG4gICAgcmV0dXJuIGNvbGxlY3Rpb25bbl07XG4gIH0sXG5cbiAgY29uY2F0OiBmdW5jdGlvbiAoLi4uZW51bWFibGVzKSB7XG4gICAgcmV0dXJuIGVudW1hYmxlc1swXS5jb25jYXQoZW51bWFibGVzWzFdKTtcbiAgfSxcblxuICBjb3VudDogZnVuY3Rpb24gKGNvbGxlY3Rpb24sIGZ1biA9IG51bGwpIHtcbiAgICBpZiAoZnVuID09IG51bGwpIHtcbiAgICAgIHJldHVybiBjb2xsZWN0aW9uLmxlbmd0aDtcbiAgICB9IGVsc2Uge1xuICAgICAgcmV0dXJuIGNvbGxlY3Rpb24uZmlsdGVyKGZ1bikubGVuZ3RoO1xuICAgIH1cbiAgfSxcblxuICBkcm9wOiBmdW5jdGlvbiAoY29sbGVjdGlvbiwgY291bnQpIHtcbiAgICByZXR1cm4gY29sbGVjdGlvbi5zbGljZShjb3VudCk7XG4gIH0sXG5cbiAgZHJvcF93aGlsZTogZnVuY3Rpb24gKGNvbGxlY3Rpb24sIGZ1bikge1xuICAgIGxldCBjb3VudCA9IDA7XG5cbiAgICBmb3IgKGxldCBlbGVtIG9mIGNvbGxlY3Rpb24pIHtcbiAgICAgIGlmIChmdW4oZWxlbSkpIHtcbiAgICAgICAgY291bnQgPSBjb3VudCArIDE7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBicmVhaztcbiAgICAgIH1cbiAgICB9XG5cbiAgICByZXR1cm4gY29sbGVjdGlvbi5zbGljZShjb3VudCk7XG4gIH0sXG5cbiAgZWFjaDogZnVuY3Rpb24gKGNvbGxlY3Rpb24sIGZ1bikge1xuICAgIGZvciAobGV0IGVsZW0gb2YgY29sbGVjdGlvbikge1xuICAgICAgZnVuKGVsZW0pO1xuICAgIH1cbiAgfSxcblxuICBlbXB0eV9fcW1hcmtfXzogZnVuY3Rpb24gKGNvbGxlY3Rpb24pIHtcbiAgICByZXR1cm4gY29sbGVjdGlvbi5sZW5ndGggPT09IDA7XG4gIH0sXG5cbiAgZmV0Y2g6IGZ1bmN0aW9uIChjb2xsZWN0aW9uLCBuKSB7XG4gICAgaWYgKEFycmF5LmlzQXJyYXkoY29sbGVjdGlvbikpIHtcbiAgICAgIGlmIChuIDwgdGhpcy5jb3VudChjb2xsZWN0aW9uKSAmJiBuID49IDApIHtcbiAgICAgICAgcmV0dXJuIG5ldyBUdXBsZShTeW1ib2wuZm9yKFwib2tcIiksIGNvbGxlY3Rpb25bbl0pO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgcmV0dXJuIFN5bWJvbC5mb3IoXCJlcnJvclwiKTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICB0aHJvdyBuZXcgRXJyb3IoXCJjb2xsZWN0aW9uIGlzIG5vdCBhbiBFbnVtZXJhYmxlXCIpO1xuICB9LFxuXG4gIGZldGNoX19lbWFya19fOiBmdW5jdGlvbiAoY29sbGVjdGlvbiwgbikge1xuICAgIGlmIChBcnJheS5pc0FycmF5KGNvbGxlY3Rpb24pKSB7XG4gICAgICBpZiAobiA8IHRoaXMuY291bnQoY29sbGVjdGlvbikgJiYgbiA+PSAwKSB7XG4gICAgICAgIHJldHVybiBjb2xsZWN0aW9uW25dO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKFwib3V0IG9mIGJvdW5kcyBlcnJvclwiKTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICB0aHJvdyBuZXcgRXJyb3IoXCJjb2xsZWN0aW9uIGlzIG5vdCBhbiBFbnVtZXJhYmxlXCIpO1xuICB9LFxuXG4gIGZpbHRlcjogZnVuY3Rpb24gKGNvbGxlY3Rpb24sIGZ1bikge1xuICAgIGxldCByZXN1bHQgPSBbXTtcblxuICAgIGZvciAobGV0IGVsZW0gb2YgY29sbGVjdGlvbikge1xuICAgICAgaWYgKGZ1bihlbGVtKSkge1xuICAgICAgICByZXN1bHQucHVzaChlbGVtKTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICByZXR1cm4gcmVzdWx0O1xuICB9LFxuXG4gIGZpbHRlcl9tYXA6IGZ1bmN0aW9uIChjb2xsZWN0aW9uLCBmaWx0ZXIsIG1hcHBlcikge1xuICAgIHJldHVybiBFbnVtLm1hcChFbnVtLmZpbHRlcihjb2xsZWN0aW9uLCBmaWx0ZXIpLCBtYXBwZXIpO1xuICB9LFxuXG4gIGZpbmQ6IGZ1bmN0aW9uIChjb2xsZWN0aW9uLCBpZl9ub25lID0gbnVsbCwgZnVuKSB7XG4gICAgZm9yIChsZXQgZWxlbSBvZiBjb2xsZWN0aW9uKSB7XG4gICAgICBpZiAoZnVuKGVsZW0pKSB7XG4gICAgICAgIHJldHVybiBlbGVtO1xuICAgICAgfVxuICAgIH1cblxuICAgIHJldHVybiBpZl9ub25lO1xuICB9LFxuXG4gIGludG86IGZ1bmN0aW9uIChjb2xsZWN0aW9uLCBsaXN0KSB7XG4gICAgcmV0dXJuIGxpc3QuY29uY2F0KGNvbGxlY3Rpb24pO1xuICB9LFxuXG4gIG1hcDogZnVuY3Rpb24gKGNvbGxlY3Rpb24sIGZ1bikge1xuICAgIGxldCByZXN1bHQgPSBbXTtcblxuICAgIGZvciAobGV0IGVsZW0gb2YgY29sbGVjdGlvbikge1xuICAgICAgcmVzdWx0LnB1c2goZnVuKGVsZW0pKTtcbiAgICB9XG5cbiAgICByZXR1cm4gcmVzdWx0O1xuICB9LFxuXG4gIG1hcF9yZWR1Y2U6IGZ1bmN0aW9uIChjb2xsZWN0aW9uLCBhY2MsIGZ1bikge1xuICAgIGxldCBtYXBwZWQgPSBMaXN0KCk7XG4gICAgbGV0IHRoZV9hY2MgPSBhY2M7XG5cbiAgICBmb3IgKHZhciBpID0gMDsgaSA8IHRoaXMuY291bnQoY29sbGVjdGlvbik7IGkrKykge1xuICAgICAgbGV0IHR1cGxlID0gZnVuKGNvbGxlY3Rpb25baV0sIHRoZV9hY2MpO1xuXG4gICAgICB0aGVfYWNjID0gdHVwbGUuZ2V0KDEpO1xuICAgICAgbWFwcGVkID0gTGlzdCguLi5tYXBwZWQuY29uY2F0KFt0dXBsZS5nZXQoMCldKSk7XG4gICAgfVxuXG4gICAgcmV0dXJuIG5ldyBUdXBsZShtYXBwZWQsIHRoZV9hY2MpO1xuICB9LFxuXG4gIG1lbWJlcl9fcW1hcmtfXzogZnVuY3Rpb24gKGNvbGxlY3Rpb24sIHZhbHVlKSB7XG4gICAgcmV0dXJuIGNvbGxlY3Rpb24uaW5jbHVkZXModmFsdWUpO1xuICB9LFxuXG4gIHJlZHVjZTogZnVuY3Rpb24gKGNvbGxlY3Rpb24sIGFjYywgZnVuKSB7XG4gICAgbGV0IHRoZV9hY2MgPSBhY2M7XG5cbiAgICBmb3IgKHZhciBpID0gMDsgaSA8IHRoaXMuY291bnQoY29sbGVjdGlvbik7IGkrKykge1xuICAgICAgbGV0IHR1cGxlID0gZnVuKGNvbGxlY3Rpb25baV0sIHRoZV9hY2MpO1xuXG4gICAgICB0aGVfYWNjID0gdHVwbGUuZ2V0KDEpO1xuICAgIH1cblxuICAgIHJldHVybiB0aGVfYWNjO1xuICB9LFxuXG4gIHRha2U6IGZ1bmN0aW9uIChjb2xsZWN0aW9uLCBjb3VudCkge1xuICAgIHJldHVybiBjb2xsZWN0aW9uLnNsaWNlKDAsIGNvdW50KTtcbiAgfSxcblxuICB0YWtlX2V2ZXJ5OiBmdW5jdGlvbiAoY29sbGVjdGlvbiwgbnRoKSB7XG4gICAgbGV0IHJlc3VsdCA9IFtdO1xuICAgIGxldCBpbmRleCA9IDA7XG5cbiAgICBmb3IgKGxldCBlbGVtIG9mIGNvbGxlY3Rpb24pIHtcbiAgICAgIGlmIChpbmRleCAlIG50aCA9PT0gMCkge1xuICAgICAgICByZXN1bHQucHVzaChlbGVtKTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICByZXR1cm4gTGlzdCguLi5yZXN1bHQpO1xuICB9LFxuXG4gIHRha2Vfd2hpbGU6IGZ1bmN0aW9uIChjb2xsZWN0aW9uLCBmdW4pIHtcbiAgICBsZXQgY291bnQgPSAwO1xuXG4gICAgZm9yIChsZXQgZWxlbSBvZiBjb2xsZWN0aW9uKSB7XG4gICAgICBpZiAoZnVuKGVsZW0pKSB7XG4gICAgICAgIGNvdW50ID0gY291bnQgKyAxO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgYnJlYWs7XG4gICAgICB9XG4gICAgfVxuXG4gICAgcmV0dXJuIGNvbGxlY3Rpb24uc2xpY2UoMCwgY291bnQpO1xuICB9LFxuXG4gIHRvX2xpc3Q6IGZ1bmN0aW9uIChjb2xsZWN0aW9uKSB7XG4gICAgcmV0dXJuIGNvbGxlY3Rpb247XG4gIH1cbn07XG5cbmxldCBWaXJ0dWFsRE9NID0gKGZ1bmN0aW9uIChlKSB7XG4gICAgcmV0dXJuIGUoKTtcbn0pKGZ1bmN0aW9uICgpIHtcbiAgICB2YXIgZGVmaW5lLCBtb2R1bGUsIGV4cG9ydHM7XG4gICAgcmV0dXJuIChmdW5jdGlvbiBlKHQsIG4sIHIpIHtcbiAgICAgICAgZnVuY3Rpb24gcyhvLCB1KSB7XG4gICAgICAgICAgICBpZiAoIW5bb10pIHtcbiAgICAgICAgICAgICAgICBpZiAoIXRbb10pIHtcbiAgICAgICAgICAgICAgICAgICAgdmFyIGEgPSB0eXBlb2YgcmVxdWlyZSA9PSBcImZ1bmN0aW9uXCIgJiYgcmVxdWlyZTtcbiAgICAgICAgICAgICAgICAgICAgaWYgKCF1ICYmIGEpIHJldHVybiBhKG8sICEwKTtcbiAgICAgICAgICAgICAgICAgICAgaWYgKGkpIHJldHVybiBpKG8sICEwKTtcbiAgICAgICAgICAgICAgICAgICAgdmFyIGYgPSBuZXcgRXJyb3IoXCJDYW5ub3QgZmluZCBtb2R1bGUgJ1wiICsgbyArIFwiJ1wiKTtcbiAgICAgICAgICAgICAgICAgICAgdGhyb3cgKGYuY29kZSA9IFwiTU9EVUxFX05PVF9GT1VORFwiLCBmKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgdmFyIGwgPSBuW29dID0ge1xuICAgICAgICAgICAgICAgICAgICBleHBvcnRzOiB7fVxuICAgICAgICAgICAgICAgIH07XG4gICAgICAgICAgICAgICAgdFtvXVswXS5jYWxsKGwuZXhwb3J0cywgZnVuY3Rpb24gKGUpIHtcbiAgICAgICAgICAgICAgICAgICAgdmFyIG4gPSB0W29dWzFdW2VdO1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gcyhuID8gbiA6IGUpO1xuICAgICAgICAgICAgICAgIH0sIGwsIGwuZXhwb3J0cywgZSwgdCwgbiwgcik7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXR1cm4gbltvXS5leHBvcnRzO1xuICAgICAgICB9XG4gICAgICAgIHZhciBpID0gdHlwZW9mIHJlcXVpcmUgPT0gXCJmdW5jdGlvblwiICYmIHJlcXVpcmU7XG4gICAgICAgIGZvciAodmFyIG8gPSAwOyBvIDwgci5sZW5ndGg7IG8rKykgcyhyW29dKTtcbiAgICAgICAgcmV0dXJuIHM7XG4gICAgfSkoe1xuICAgICAgICAxOiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge1xuXG4gICAgICAgICAgICB2YXIgY3JlYXRlRWxlbWVudCA9IHJlcXVpcmUoXCIuL3Zkb20vY3JlYXRlLWVsZW1lbnQuanNcIik7XG5cbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gY3JlYXRlRWxlbWVudDtcbiAgICAgICAgfSwgeyBcIi4vdmRvbS9jcmVhdGUtZWxlbWVudC5qc1wiOiAxNSB9XSwgMjogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHtcbiAgICAgICAgICAgIHZhciBkaWZmID0gcmVxdWlyZShcIi4vdnRyZWUvZGlmZi5qc1wiKTtcblxuICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBkaWZmO1xuICAgICAgICB9LCB7IFwiLi92dHJlZS9kaWZmLmpzXCI6IDM1IH1dLCAzOiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge1xuICAgICAgICAgICAgdmFyIGggPSByZXF1aXJlKFwiLi92aXJ0dWFsLWh5cGVyc2NyaXB0L2luZGV4LmpzXCIpO1xuXG4gICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IGg7XG4gICAgICAgIH0sIHsgXCIuL3ZpcnR1YWwtaHlwZXJzY3JpcHQvaW5kZXguanNcIjogMjIgfV0sIDQ6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICB2YXIgZGlmZiA9IHJlcXVpcmUoXCIuL2RpZmYuanNcIik7XG4gICAgICAgICAgICB2YXIgcGF0Y2ggPSByZXF1aXJlKFwiLi9wYXRjaC5qc1wiKTtcbiAgICAgICAgICAgIHZhciBoID0gcmVxdWlyZShcIi4vaC5qc1wiKTtcbiAgICAgICAgICAgIHZhciBjcmVhdGUgPSByZXF1aXJlKFwiLi9jcmVhdGUtZWxlbWVudC5qc1wiKTtcbiAgICAgICAgICAgIHZhciBWTm9kZSA9IHJlcXVpcmUoXCIuL3Zub2RlL3Zub2RlLmpzXCIpO1xuICAgICAgICAgICAgdmFyIFZUZXh0ID0gcmVxdWlyZShcIi4vdm5vZGUvdnRleHQuanNcIik7XG5cbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0ge1xuICAgICAgICAgICAgICAgIGRpZmY6IGRpZmYsXG4gICAgICAgICAgICAgICAgcGF0Y2g6IHBhdGNoLFxuICAgICAgICAgICAgICAgIGg6IGgsXG4gICAgICAgICAgICAgICAgY3JlYXRlOiBjcmVhdGUsXG4gICAgICAgICAgICAgICAgVk5vZGU6IFZOb2RlLFxuICAgICAgICAgICAgICAgIFZUZXh0OiBWVGV4dFxuICAgICAgICAgICAgfTtcbiAgICAgICAgfSwgeyBcIi4vY3JlYXRlLWVsZW1lbnQuanNcIjogMSwgXCIuL2RpZmYuanNcIjogMiwgXCIuL2guanNcIjogMywgXCIuL3BhdGNoLmpzXCI6IDEzLCBcIi4vdm5vZGUvdm5vZGUuanNcIjogMzEsIFwiLi92bm9kZS92dGV4dC5qc1wiOiAzMyB9XSwgNTogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHtcbiAgICAgICAgICAgIC8qIVxuICAgICAgICAgICAgICogQ3Jvc3MtQnJvd3NlciBTcGxpdCAxLjEuMVxuICAgICAgICAgICAgICogQ29weXJpZ2h0IDIwMDctMjAxMiBTdGV2ZW4gTGV2aXRoYW4gPHN0ZXZlbmxldml0aGFuLmNvbT5cbiAgICAgICAgICAgICAqIEF2YWlsYWJsZSB1bmRlciB0aGUgTUlUIExpY2Vuc2VcbiAgICAgICAgICAgICAqIEVDTUFTY3JpcHQgY29tcGxpYW50LCB1bmlmb3JtIGNyb3NzLWJyb3dzZXIgc3BsaXQgbWV0aG9kXG4gICAgICAgICAgICAgKi9cblxuICAgICAgICAgICAgLyoqXG4gICAgICAgICAgICAgKiBTcGxpdHMgYSBzdHJpbmcgaW50byBhbiBhcnJheSBvZiBzdHJpbmdzIHVzaW5nIGEgcmVnZXggb3Igc3RyaW5nIHNlcGFyYXRvci4gTWF0Y2hlcyBvZiB0aGVcbiAgICAgICAgICAgICAqIHNlcGFyYXRvciBhcmUgbm90IGluY2x1ZGVkIGluIHRoZSByZXN1bHQgYXJyYXkuIEhvd2V2ZXIsIGlmIGBzZXBhcmF0b3JgIGlzIGEgcmVnZXggdGhhdCBjb250YWluc1xuICAgICAgICAgICAgICogY2FwdHVyaW5nIGdyb3VwcywgYmFja3JlZmVyZW5jZXMgYXJlIHNwbGljZWQgaW50byB0aGUgcmVzdWx0IGVhY2ggdGltZSBgc2VwYXJhdG9yYCBpcyBtYXRjaGVkLlxuICAgICAgICAgICAgICogRml4ZXMgYnJvd3NlciBidWdzIGNvbXBhcmVkIHRvIHRoZSBuYXRpdmUgYFN0cmluZy5wcm90b3R5cGUuc3BsaXRgIGFuZCBjYW4gYmUgdXNlZCByZWxpYWJseVxuICAgICAgICAgICAgICogY3Jvc3MtYnJvd3Nlci5cbiAgICAgICAgICAgICAqIEBwYXJhbSB7U3RyaW5nfSBzdHIgU3RyaW5nIHRvIHNwbGl0LlxuICAgICAgICAgICAgICogQHBhcmFtIHtSZWdFeHB8U3RyaW5nfSBzZXBhcmF0b3IgUmVnZXggb3Igc3RyaW5nIHRvIHVzZSBmb3Igc2VwYXJhdGluZyB0aGUgc3RyaW5nLlxuICAgICAgICAgICAgICogQHBhcmFtIHtOdW1iZXJ9IFtsaW1pdF0gTWF4aW11bSBudW1iZXIgb2YgaXRlbXMgdG8gaW5jbHVkZSBpbiB0aGUgcmVzdWx0IGFycmF5LlxuICAgICAgICAgICAgICogQHJldHVybnMge0FycmF5fSBBcnJheSBvZiBzdWJzdHJpbmdzLlxuICAgICAgICAgICAgICogQGV4YW1wbGVcbiAgICAgICAgICAgICAqXG4gICAgICAgICAgICAgKiAvLyBCYXNpYyB1c2VcbiAgICAgICAgICAgICAqIHNwbGl0KCdhIGIgYyBkJywgJyAnKTtcbiAgICAgICAgICAgICAqIC8vIC0+IFsnYScsICdiJywgJ2MnLCAnZCddXG4gICAgICAgICAgICAgKlxuICAgICAgICAgICAgICogLy8gV2l0aCBsaW1pdFxuICAgICAgICAgICAgICogc3BsaXQoJ2EgYiBjIGQnLCAnICcsIDIpO1xuICAgICAgICAgICAgICogLy8gLT4gWydhJywgJ2InXVxuICAgICAgICAgICAgICpcbiAgICAgICAgICAgICAqIC8vIEJhY2tyZWZlcmVuY2VzIGluIHJlc3VsdCBhcnJheVxuICAgICAgICAgICAgICogc3BsaXQoJy4ud29yZDEgd29yZDIuLicsIC8oW2Etel0rKShcXGQrKS9pKTtcbiAgICAgICAgICAgICAqIC8vIC0+IFsnLi4nLCAnd29yZCcsICcxJywgJyAnLCAnd29yZCcsICcyJywgJy4uJ11cbiAgICAgICAgICAgICAqL1xuICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSAoZnVuY3Rpb24gc3BsaXQodW5kZWYpIHtcblxuICAgICAgICAgICAgICAgIHZhciBuYXRpdmVTcGxpdCA9IFN0cmluZy5wcm90b3R5cGUuc3BsaXQsXG4gICAgICAgICAgICAgICAgICAgIGNvbXBsaWFudEV4ZWNOcGNnID0gLygpPz8vLmV4ZWMoXCJcIilbMV0gPT09IHVuZGVmLFxuXG4gICAgICAgICAgICAgICAgLy8gTlBDRzogbm9ucGFydGljaXBhdGluZyBjYXB0dXJpbmcgZ3JvdXBcbiAgICAgICAgICAgICAgICBzZWxmO1xuXG4gICAgICAgICAgICAgICAgc2VsZiA9IGZ1bmN0aW9uIChzdHIsIHNlcGFyYXRvciwgbGltaXQpIHtcbiAgICAgICAgICAgICAgICAgICAgLy8gSWYgYHNlcGFyYXRvcmAgaXMgbm90IGEgcmVnZXgsIHVzZSBgbmF0aXZlU3BsaXRgXG4gICAgICAgICAgICAgICAgICAgIGlmIChPYmplY3QucHJvdG90eXBlLnRvU3RyaW5nLmNhbGwoc2VwYXJhdG9yKSAhPT0gXCJbb2JqZWN0IFJlZ0V4cF1cIikge1xuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIG5hdGl2ZVNwbGl0LmNhbGwoc3RyLCBzZXBhcmF0b3IsIGxpbWl0KTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB2YXIgb3V0cHV0ID0gW10sXG4gICAgICAgICAgICAgICAgICAgICAgICBmbGFncyA9IChzZXBhcmF0b3IuaWdub3JlQ2FzZSA/IFwiaVwiIDogXCJcIikgKyAoc2VwYXJhdG9yLm11bHRpbGluZSA/IFwibVwiIDogXCJcIikgKyAoc2VwYXJhdG9yLmV4dGVuZGVkID8gXCJ4XCIgOiBcIlwiKSArIChzZXBhcmF0b3Iuc3RpY2t5ID8gXCJ5XCIgOiBcIlwiKSxcblxuICAgICAgICAgICAgICAgICAgICAvLyBGaXJlZm94IDMrXG4gICAgICAgICAgICAgICAgICAgIGxhc3RMYXN0SW5kZXggPSAwLFxuXG4gICAgICAgICAgICAgICAgICAgIC8vIE1ha2UgYGdsb2JhbGAgYW5kIGF2b2lkIGBsYXN0SW5kZXhgIGlzc3VlcyBieSB3b3JraW5nIHdpdGggYSBjb3B5XG4gICAgICAgICAgICAgICAgICAgIHNlcGFyYXRvciA9IG5ldyBSZWdFeHAoc2VwYXJhdG9yLnNvdXJjZSwgZmxhZ3MgKyBcImdcIiksXG4gICAgICAgICAgICAgICAgICAgICAgICBzZXBhcmF0b3IyLFxuICAgICAgICAgICAgICAgICAgICAgICAgbWF0Y2gsXG4gICAgICAgICAgICAgICAgICAgICAgICBsYXN0SW5kZXgsXG4gICAgICAgICAgICAgICAgICAgICAgICBsYXN0TGVuZ3RoO1xuICAgICAgICAgICAgICAgICAgICBzdHIgKz0gXCJcIjsgLy8gVHlwZS1jb252ZXJ0XG4gICAgICAgICAgICAgICAgICAgIGlmICghY29tcGxpYW50RXhlY05wY2cpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIERvZXNuJ3QgbmVlZCBmbGFncyBneSwgYnV0IHRoZXkgZG9uJ3QgaHVydFxuICAgICAgICAgICAgICAgICAgICAgICAgc2VwYXJhdG9yMiA9IG5ldyBSZWdFeHAoXCJeXCIgKyBzZXBhcmF0b3Iuc291cmNlICsgXCIkKD8hXFxcXHMpXCIsIGZsYWdzKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAvKiBWYWx1ZXMgZm9yIGBsaW1pdGAsIHBlciB0aGUgc3BlYzpcbiAgICAgICAgICAgICAgICAgICAgICogSWYgdW5kZWZpbmVkOiA0Mjk0OTY3Mjk1IC8vIE1hdGgucG93KDIsIDMyKSAtIDFcbiAgICAgICAgICAgICAgICAgICAgICogSWYgMCwgSW5maW5pdHksIG9yIE5hTjogMFxuICAgICAgICAgICAgICAgICAgICAgKiBJZiBwb3NpdGl2ZSBudW1iZXI6IGxpbWl0ID0gTWF0aC5mbG9vcihsaW1pdCk7IGlmIChsaW1pdCA+IDQyOTQ5NjcyOTUpIGxpbWl0IC09IDQyOTQ5NjcyOTY7XG4gICAgICAgICAgICAgICAgICAgICAqIElmIG5lZ2F0aXZlIG51bWJlcjogNDI5NDk2NzI5NiAtIE1hdGguZmxvb3IoTWF0aC5hYnMobGltaXQpKVxuICAgICAgICAgICAgICAgICAgICAgKiBJZiBvdGhlcjogVHlwZS1jb252ZXJ0LCB0aGVuIHVzZSB0aGUgYWJvdmUgcnVsZXNcbiAgICAgICAgICAgICAgICAgICAgICovXG4gICAgICAgICAgICAgICAgICAgIGxpbWl0ID0gbGltaXQgPT09IHVuZGVmID8gLTEgPj4+IDAgOiAvLyBNYXRoLnBvdygyLCAzMikgLSAxXG4gICAgICAgICAgICAgICAgICAgIGxpbWl0ID4+PiAwOyAvLyBUb1VpbnQzMihsaW1pdClcbiAgICAgICAgICAgICAgICAgICAgd2hpbGUgKG1hdGNoID0gc2VwYXJhdG9yLmV4ZWMoc3RyKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgLy8gYHNlcGFyYXRvci5sYXN0SW5kZXhgIGlzIG5vdCByZWxpYWJsZSBjcm9zcy1icm93c2VyXG4gICAgICAgICAgICAgICAgICAgICAgICBsYXN0SW5kZXggPSBtYXRjaC5pbmRleCArIG1hdGNoWzBdLmxlbmd0aDtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChsYXN0SW5kZXggPiBsYXN0TGFzdEluZGV4KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgb3V0cHV0LnB1c2goc3RyLnNsaWNlKGxhc3RMYXN0SW5kZXgsIG1hdGNoLmluZGV4KSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gRml4IGJyb3dzZXJzIHdob3NlIGBleGVjYCBtZXRob2RzIGRvbid0IGNvbnNpc3RlbnRseSByZXR1cm4gYHVuZGVmaW5lZGAgZm9yXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gbm9ucGFydGljaXBhdGluZyBjYXB0dXJpbmcgZ3JvdXBzXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKCFjb21wbGlhbnRFeGVjTnBjZyAmJiBtYXRjaC5sZW5ndGggPiAxKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1hdGNoWzBdLnJlcGxhY2Uoc2VwYXJhdG9yMiwgZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZm9yICh2YXIgaSA9IDE7IGkgPCBhcmd1bWVudHMubGVuZ3RoIC0gMjsgaSsrKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGFyZ3VtZW50c1tpXSA9PT0gdW5kZWYpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbWF0Y2hbaV0gPSB1bmRlZjtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAobWF0Y2gubGVuZ3RoID4gMSAmJiBtYXRjaC5pbmRleCA8IHN0ci5sZW5ndGgpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgQXJyYXkucHJvdG90eXBlLnB1c2guYXBwbHkob3V0cHV0LCBtYXRjaC5zbGljZSgxKSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxhc3RMZW5ndGggPSBtYXRjaFswXS5sZW5ndGg7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgbGFzdExhc3RJbmRleCA9IGxhc3RJbmRleDtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAob3V0cHV0Lmxlbmd0aCA+PSBsaW1pdCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoc2VwYXJhdG9yLmxhc3RJbmRleCA9PT0gbWF0Y2guaW5kZXgpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBzZXBhcmF0b3IubGFzdEluZGV4Kys7IC8vIEF2b2lkIGFuIGluZmluaXRlIGxvb3BcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICBpZiAobGFzdExhc3RJbmRleCA9PT0gc3RyLmxlbmd0aCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGxhc3RMZW5ndGggfHwgIXNlcGFyYXRvci50ZXN0KFwiXCIpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgb3V0cHV0LnB1c2goXCJcIik7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBvdXRwdXQucHVzaChzdHIuc2xpY2UobGFzdExhc3RJbmRleCkpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBvdXRwdXQubGVuZ3RoID4gbGltaXQgPyBvdXRwdXQuc2xpY2UoMCwgbGltaXQpIDogb3V0cHV0O1xuICAgICAgICAgICAgICAgIH07XG5cbiAgICAgICAgICAgICAgICByZXR1cm4gc2VsZjtcbiAgICAgICAgICAgIH0pKCk7XG4gICAgICAgIH0sIHt9XSwgNjogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHt9LCB7fV0sIDc6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICBcInVzZSBzdHJpY3RcIjtcblxuICAgICAgICAgICAgdmFyIE9uZVZlcnNpb25Db25zdHJhaW50ID0gcmVxdWlyZShcImluZGl2aWR1YWwvb25lLXZlcnNpb25cIik7XG5cbiAgICAgICAgICAgIHZhciBNWV9WRVJTSU9OID0gXCI3XCI7XG4gICAgICAgICAgICBPbmVWZXJzaW9uQ29uc3RyYWludChcImV2LXN0b3JlXCIsIE1ZX1ZFUlNJT04pO1xuXG4gICAgICAgICAgICB2YXIgaGFzaEtleSA9IFwiX19FVl9TVE9SRV9LRVlAXCIgKyBNWV9WRVJTSU9OO1xuXG4gICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IEV2U3RvcmU7XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIEV2U3RvcmUoZWxlbSkge1xuICAgICAgICAgICAgICAgIHZhciBoYXNoID0gZWxlbVtoYXNoS2V5XTtcblxuICAgICAgICAgICAgICAgIGlmICghaGFzaCkge1xuICAgICAgICAgICAgICAgICAgICBoYXNoID0gZWxlbVtoYXNoS2V5XSA9IHt9O1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHJldHVybiBoYXNoO1xuICAgICAgICAgICAgfVxuICAgICAgICB9LCB7IFwiaW5kaXZpZHVhbC9vbmUtdmVyc2lvblwiOiA5IH1dLCA4OiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge1xuICAgICAgICAgICAgKGZ1bmN0aW9uIChnbG9iYWwpIHtcbiAgICAgICAgICAgICAgICBcInVzZSBzdHJpY3RcIjtcblxuICAgICAgICAgICAgICAgIC8qZ2xvYmFsIHdpbmRvdywgZ2xvYmFsKi9cblxuICAgICAgICAgICAgICAgIHZhciByb290ID0gdHlwZW9mIHdpbmRvdyAhPT0gXCJ1bmRlZmluZWRcIiA/IHdpbmRvdyA6IHR5cGVvZiBnbG9iYWwgIT09IFwidW5kZWZpbmVkXCIgPyBnbG9iYWwgOiB7fTtcblxuICAgICAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gSW5kaXZpZHVhbDtcblxuICAgICAgICAgICAgICAgIGZ1bmN0aW9uIEluZGl2aWR1YWwoa2V5LCB2YWx1ZSkge1xuICAgICAgICAgICAgICAgICAgICBpZiAoa2V5IGluIHJvb3QpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiByb290W2tleV07XG4gICAgICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgICAgICByb290W2tleV0gPSB2YWx1ZTtcblxuICAgICAgICAgICAgICAgICAgICByZXR1cm4gdmFsdWU7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSkuY2FsbCh0aGlzLCB0eXBlb2YgZ2xvYmFsICE9PSBcInVuZGVmaW5lZFwiID8gZ2xvYmFsIDogdHlwZW9mIHNlbGYgIT09IFwidW5kZWZpbmVkXCIgPyBzZWxmIDogdHlwZW9mIHdpbmRvdyAhPT0gXCJ1bmRlZmluZWRcIiA/IHdpbmRvdyA6IHt9KTtcbiAgICAgICAgfSwge31dLCA5OiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge1xuICAgICAgICAgICAgXCJ1c2Ugc3RyaWN0XCI7XG5cbiAgICAgICAgICAgIHZhciBJbmRpdmlkdWFsID0gcmVxdWlyZShcIi4vaW5kZXguanNcIik7XG5cbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gT25lVmVyc2lvbjtcblxuICAgICAgICAgICAgZnVuY3Rpb24gT25lVmVyc2lvbihtb2R1bGVOYW1lLCB2ZXJzaW9uLCBkZWZhdWx0VmFsdWUpIHtcbiAgICAgICAgICAgICAgICB2YXIga2V5ID0gXCJfX0lORElWSURVQUxfT05FX1ZFUlNJT05fXCIgKyBtb2R1bGVOYW1lO1xuICAgICAgICAgICAgICAgIHZhciBlbmZvcmNlS2V5ID0ga2V5ICsgXCJfRU5GT1JDRV9TSU5HTEVUT05cIjtcblxuICAgICAgICAgICAgICAgIHZhciB2ZXJzaW9uVmFsdWUgPSBJbmRpdmlkdWFsKGVuZm9yY2VLZXksIHZlcnNpb24pO1xuXG4gICAgICAgICAgICAgICAgaWYgKHZlcnNpb25WYWx1ZSAhPT0gdmVyc2lvbikge1xuICAgICAgICAgICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoXCJDYW4gb25seSBoYXZlIG9uZSBjb3B5IG9mIFwiICsgbW9kdWxlTmFtZSArIFwiLlxcblwiICsgXCJZb3UgYWxyZWFkeSBoYXZlIHZlcnNpb24gXCIgKyB2ZXJzaW9uVmFsdWUgKyBcIiBpbnN0YWxsZWQuXFxuXCIgKyBcIlRoaXMgbWVhbnMgeW91IGNhbm5vdCBpbnN0YWxsIHZlcnNpb24gXCIgKyB2ZXJzaW9uKTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICByZXR1cm4gSW5kaXZpZHVhbChrZXksIGRlZmF1bHRWYWx1ZSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0sIHsgXCIuL2luZGV4LmpzXCI6IDggfV0sIDEwOiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge1xuICAgICAgICAgICAgKGZ1bmN0aW9uIChnbG9iYWwpIHtcbiAgICAgICAgICAgICAgICB2YXIgdG9wTGV2ZWwgPSB0eXBlb2YgZ2xvYmFsICE9PSBcInVuZGVmaW5lZFwiID8gZ2xvYmFsIDogdHlwZW9mIHdpbmRvdyAhPT0gXCJ1bmRlZmluZWRcIiA/IHdpbmRvdyA6IHt9O1xuICAgICAgICAgICAgICAgIHZhciBtaW5Eb2MgPSByZXF1aXJlKFwibWluLWRvY3VtZW50XCIpO1xuXG4gICAgICAgICAgICAgICAgaWYgKHR5cGVvZiBkb2N1bWVudCAhPT0gXCJ1bmRlZmluZWRcIikge1xuICAgICAgICAgICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IGRvY3VtZW50O1xuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciBkb2NjeSA9IHRvcExldmVsW1wiX19HTE9CQUxfRE9DVU1FTlRfQ0FDSEVANFwiXTtcblxuICAgICAgICAgICAgICAgICAgICBpZiAoIWRvY2N5KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBkb2NjeSA9IHRvcExldmVsW1wiX19HTE9CQUxfRE9DVU1FTlRfQ0FDSEVANFwiXSA9IG1pbkRvYztcbiAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gZG9jY3k7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSkuY2FsbCh0aGlzLCB0eXBlb2YgZ2xvYmFsICE9PSBcInVuZGVmaW5lZFwiID8gZ2xvYmFsIDogdHlwZW9mIHNlbGYgIT09IFwidW5kZWZpbmVkXCIgPyBzZWxmIDogdHlwZW9mIHdpbmRvdyAhPT0gXCJ1bmRlZmluZWRcIiA/IHdpbmRvdyA6IHt9KTtcbiAgICAgICAgfSwgeyBcIm1pbi1kb2N1bWVudFwiOiA2IH1dLCAxMTogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHtcbiAgICAgICAgICAgIFwidXNlIHN0cmljdFwiO1xuXG4gICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uIGlzT2JqZWN0KHgpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gdHlwZW9mIHggPT09IFwib2JqZWN0XCIgJiYgeCAhPT0gbnVsbDtcbiAgICAgICAgICAgIH07XG4gICAgICAgIH0sIHt9XSwgMTI6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICB2YXIgbmF0aXZlSXNBcnJheSA9IEFycmF5LmlzQXJyYXk7XG4gICAgICAgICAgICB2YXIgdG9TdHJpbmcgPSBPYmplY3QucHJvdG90eXBlLnRvU3RyaW5nO1xuXG4gICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IG5hdGl2ZUlzQXJyYXkgfHwgaXNBcnJheTtcblxuICAgICAgICAgICAgZnVuY3Rpb24gaXNBcnJheShvYmopIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gdG9TdHJpbmcuY2FsbChvYmopID09PSBcIltvYmplY3QgQXJyYXldXCI7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0sIHt9XSwgMTM6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICB2YXIgcGF0Y2ggPSByZXF1aXJlKFwiLi92ZG9tL3BhdGNoLmpzXCIpO1xuXG4gICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IHBhdGNoO1xuICAgICAgICB9LCB7IFwiLi92ZG9tL3BhdGNoLmpzXCI6IDE4IH1dLCAxNDogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHtcbiAgICAgICAgICAgIHZhciBpc09iamVjdCA9IHJlcXVpcmUoXCJpcy1vYmplY3RcIik7XG4gICAgICAgICAgICB2YXIgaXNIb29rID0gcmVxdWlyZShcIi4uL3Zub2RlL2lzLXZob29rLmpzXCIpO1xuXG4gICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IGFwcGx5UHJvcGVydGllcztcblxuICAgICAgICAgICAgZnVuY3Rpb24gYXBwbHlQcm9wZXJ0aWVzKG5vZGUsIHByb3BzLCBwcmV2aW91cykge1xuICAgICAgICAgICAgICAgIGZvciAodmFyIHByb3BOYW1lIGluIHByb3BzKSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciBwcm9wVmFsdWUgPSBwcm9wc1twcm9wTmFtZV07XG5cbiAgICAgICAgICAgICAgICAgICAgaWYgKHByb3BWYWx1ZSA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICByZW1vdmVQcm9wZXJ0eShub2RlLCBwcm9wTmFtZSwgcHJvcFZhbHVlLCBwcmV2aW91cyk7XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoaXNIb29rKHByb3BWYWx1ZSkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJlbW92ZVByb3BlcnR5KG5vZGUsIHByb3BOYW1lLCBwcm9wVmFsdWUsIHByZXZpb3VzKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChwcm9wVmFsdWUuaG9vaykge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHByb3BWYWx1ZS5ob29rKG5vZGUsIHByb3BOYW1lLCBwcmV2aW91cyA/IHByZXZpb3VzW3Byb3BOYW1lXSA6IHVuZGVmaW5lZCk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoaXNPYmplY3QocHJvcFZhbHVlKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHBhdGNoT2JqZWN0KG5vZGUsIHByb3BzLCBwcmV2aW91cywgcHJvcE5hbWUsIHByb3BWYWx1ZSk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIG5vZGVbcHJvcE5hbWVdID0gcHJvcFZhbHVlO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBmdW5jdGlvbiByZW1vdmVQcm9wZXJ0eShub2RlLCBwcm9wTmFtZSwgcHJvcFZhbHVlLCBwcmV2aW91cykge1xuICAgICAgICAgICAgICAgIGlmIChwcmV2aW91cykge1xuICAgICAgICAgICAgICAgICAgICB2YXIgcHJldmlvdXNWYWx1ZSA9IHByZXZpb3VzW3Byb3BOYW1lXTtcblxuICAgICAgICAgICAgICAgICAgICBpZiAoIWlzSG9vayhwcmV2aW91c1ZhbHVlKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHByb3BOYW1lID09PSBcImF0dHJpYnV0ZXNcIikge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZvciAodmFyIGF0dHJOYW1lIGluIHByZXZpb3VzVmFsdWUpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbm9kZS5yZW1vdmVBdHRyaWJ1dGUoYXR0ck5hbWUpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAocHJvcE5hbWUgPT09IFwic3R5bGVcIikge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZvciAodmFyIGkgaW4gcHJldmlvdXNWYWx1ZSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBub2RlLnN0eWxlW2ldID0gXCJcIjtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKHR5cGVvZiBwcmV2aW91c1ZhbHVlID09PSBcInN0cmluZ1wiKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgbm9kZVtwcm9wTmFtZV0gPSBcIlwiO1xuICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBub2RlW3Byb3BOYW1lXSA9IG51bGw7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAocHJldmlvdXNWYWx1ZS51bmhvb2spIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHByZXZpb3VzVmFsdWUudW5ob29rKG5vZGUsIHByb3BOYW1lLCBwcm9wVmFsdWUpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBmdW5jdGlvbiBwYXRjaE9iamVjdChub2RlLCBwcm9wcywgcHJldmlvdXMsIHByb3BOYW1lLCBwcm9wVmFsdWUpIHtcbiAgICAgICAgICAgICAgICB2YXIgcHJldmlvdXNWYWx1ZSA9IHByZXZpb3VzID8gcHJldmlvdXNbcHJvcE5hbWVdIDogdW5kZWZpbmVkO1xuXG4gICAgICAgICAgICAgICAgLy8gU2V0IGF0dHJpYnV0ZXNcbiAgICAgICAgICAgICAgICBpZiAocHJvcE5hbWUgPT09IFwiYXR0cmlidXRlc1wiKSB7XG4gICAgICAgICAgICAgICAgICAgIGZvciAodmFyIGF0dHJOYW1lIGluIHByb3BWYWx1ZSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgdmFyIGF0dHJWYWx1ZSA9IHByb3BWYWx1ZVthdHRyTmFtZV07XG5cbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChhdHRyVmFsdWUgPT09IHVuZGVmaW5lZCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIG5vZGUucmVtb3ZlQXR0cmlidXRlKGF0dHJOYW1lKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgbm9kZS5zZXRBdHRyaWJ1dGUoYXR0ck5hbWUsIGF0dHJWYWx1ZSk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgaWYgKHByZXZpb3VzVmFsdWUgJiYgaXNPYmplY3QocHJldmlvdXNWYWx1ZSkgJiYgZ2V0UHJvdG90eXBlKHByZXZpb3VzVmFsdWUpICE9PSBnZXRQcm90b3R5cGUocHJvcFZhbHVlKSkge1xuICAgICAgICAgICAgICAgICAgICBub2RlW3Byb3BOYW1lXSA9IHByb3BWYWx1ZTtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIGlmICghaXNPYmplY3Qobm9kZVtwcm9wTmFtZV0pKSB7XG4gICAgICAgICAgICAgICAgICAgIG5vZGVbcHJvcE5hbWVdID0ge307XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgdmFyIHJlcGxhY2VyID0gcHJvcE5hbWUgPT09IFwic3R5bGVcIiA/IFwiXCIgOiB1bmRlZmluZWQ7XG5cbiAgICAgICAgICAgICAgICBmb3IgKHZhciBrIGluIHByb3BWYWx1ZSkge1xuICAgICAgICAgICAgICAgICAgICB2YXIgdmFsdWUgPSBwcm9wVmFsdWVba107XG4gICAgICAgICAgICAgICAgICAgIG5vZGVbcHJvcE5hbWVdW2tdID0gdmFsdWUgPT09IHVuZGVmaW5lZCA/IHJlcGxhY2VyIDogdmFsdWU7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBmdW5jdGlvbiBnZXRQcm90b3R5cGUodmFsdWUpIHtcbiAgICAgICAgICAgICAgICBpZiAoT2JqZWN0LmdldFByb3RvdHlwZU9mKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBPYmplY3QuZ2V0UHJvdG90eXBlT2YodmFsdWUpO1xuICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAodmFsdWUuX19wcm90b19fKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiB2YWx1ZS5fX3Byb3RvX187XG4gICAgICAgICAgICAgICAgfSBlbHNlIGlmICh2YWx1ZS5jb25zdHJ1Y3Rvcikge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gdmFsdWUuY29uc3RydWN0b3IucHJvdG90eXBlO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgfSwgeyBcIi4uL3Zub2RlL2lzLXZob29rLmpzXCI6IDI2LCBcImlzLW9iamVjdFwiOiAxMSB9XSwgMTU6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICB2YXIgZG9jdW1lbnQgPSByZXF1aXJlKFwiZ2xvYmFsL2RvY3VtZW50XCIpO1xuXG4gICAgICAgICAgICB2YXIgYXBwbHlQcm9wZXJ0aWVzID0gcmVxdWlyZShcIi4vYXBwbHktcHJvcGVydGllc1wiKTtcblxuICAgICAgICAgICAgdmFyIGlzVk5vZGUgPSByZXF1aXJlKFwiLi4vdm5vZGUvaXMtdm5vZGUuanNcIik7XG4gICAgICAgICAgICB2YXIgaXNWVGV4dCA9IHJlcXVpcmUoXCIuLi92bm9kZS9pcy12dGV4dC5qc1wiKTtcbiAgICAgICAgICAgIHZhciBpc1dpZGdldCA9IHJlcXVpcmUoXCIuLi92bm9kZS9pcy13aWRnZXQuanNcIik7XG4gICAgICAgICAgICB2YXIgaGFuZGxlVGh1bmsgPSByZXF1aXJlKFwiLi4vdm5vZGUvaGFuZGxlLXRodW5rLmpzXCIpO1xuXG4gICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IGNyZWF0ZUVsZW1lbnQ7XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIGNyZWF0ZUVsZW1lbnQodm5vZGUsIG9wdHMpIHtcbiAgICAgICAgICAgICAgICB2YXIgZG9jID0gb3B0cyA/IG9wdHMuZG9jdW1lbnQgfHwgZG9jdW1lbnQgOiBkb2N1bWVudDtcbiAgICAgICAgICAgICAgICB2YXIgd2FybiA9IG9wdHMgPyBvcHRzLndhcm4gOiBudWxsO1xuXG4gICAgICAgICAgICAgICAgdm5vZGUgPSBoYW5kbGVUaHVuayh2bm9kZSkuYTtcblxuICAgICAgICAgICAgICAgIGlmIChpc1dpZGdldCh2bm9kZSkpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHZub2RlLmluaXQoKTtcbiAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKGlzVlRleHQodm5vZGUpKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBkb2MuY3JlYXRlVGV4dE5vZGUodm5vZGUudGV4dCk7XG4gICAgICAgICAgICAgICAgfSBlbHNlIGlmICghaXNWTm9kZSh2bm9kZSkpIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKHdhcm4pIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHdhcm4oXCJJdGVtIGlzIG5vdCBhIHZhbGlkIHZpcnR1YWwgZG9tIG5vZGVcIiwgdm5vZGUpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBudWxsO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHZhciBub2RlID0gdm5vZGUubmFtZXNwYWNlID09PSBudWxsID8gZG9jLmNyZWF0ZUVsZW1lbnQodm5vZGUudGFnTmFtZSkgOiBkb2MuY3JlYXRlRWxlbWVudE5TKHZub2RlLm5hbWVzcGFjZSwgdm5vZGUudGFnTmFtZSk7XG5cbiAgICAgICAgICAgICAgICB2YXIgcHJvcHMgPSB2bm9kZS5wcm9wZXJ0aWVzO1xuICAgICAgICAgICAgICAgIGFwcGx5UHJvcGVydGllcyhub2RlLCBwcm9wcyk7XG5cbiAgICAgICAgICAgICAgICB2YXIgY2hpbGRyZW4gPSB2bm9kZS5jaGlsZHJlbjtcblxuICAgICAgICAgICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgY2hpbGRyZW4ubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgICAgICAgICAgdmFyIGNoaWxkTm9kZSA9IGNyZWF0ZUVsZW1lbnQoY2hpbGRyZW5baV0sIG9wdHMpO1xuICAgICAgICAgICAgICAgICAgICBpZiAoY2hpbGROb2RlKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBub2RlLmFwcGVuZENoaWxkKGNoaWxkTm9kZSk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICByZXR1cm4gbm9kZTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSwgeyBcIi4uL3Zub2RlL2hhbmRsZS10aHVuay5qc1wiOiAyNCwgXCIuLi92bm9kZS9pcy12bm9kZS5qc1wiOiAyNywgXCIuLi92bm9kZS9pcy12dGV4dC5qc1wiOiAyOCwgXCIuLi92bm9kZS9pcy13aWRnZXQuanNcIjogMjksIFwiLi9hcHBseS1wcm9wZXJ0aWVzXCI6IDE0LCBcImdsb2JhbC9kb2N1bWVudFwiOiAxMCB9XSwgMTY6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICAvLyBNYXBzIGEgdmlydHVhbCBET00gdHJlZSBvbnRvIGEgcmVhbCBET00gdHJlZSBpbiBhbiBlZmZpY2llbnQgbWFubmVyLlxuICAgICAgICAgICAgLy8gV2UgZG9uJ3Qgd2FudCB0byByZWFkIGFsbCBvZiB0aGUgRE9NIG5vZGVzIGluIHRoZSB0cmVlIHNvIHdlIHVzZVxuICAgICAgICAgICAgLy8gdGhlIGluLW9yZGVyIHRyZWUgaW5kZXhpbmcgdG8gZWxpbWluYXRlIHJlY3Vyc2lvbiBkb3duIGNlcnRhaW4gYnJhbmNoZXMuXG4gICAgICAgICAgICAvLyBXZSBvbmx5IHJlY3Vyc2UgaW50byBhIERPTSBub2RlIGlmIHdlIGtub3cgdGhhdCBpdCBjb250YWlucyBhIGNoaWxkIG9mXG4gICAgICAgICAgICAvLyBpbnRlcmVzdC5cblxuICAgICAgICAgICAgdmFyIG5vQ2hpbGQgPSB7fTtcblxuICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBkb21JbmRleDtcblxuICAgICAgICAgICAgZnVuY3Rpb24gZG9tSW5kZXgocm9vdE5vZGUsIHRyZWUsIGluZGljZXMsIG5vZGVzKSB7XG4gICAgICAgICAgICAgICAgaWYgKCFpbmRpY2VzIHx8IGluZGljZXMubGVuZ3RoID09PSAwKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiB7fTtcbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICBpbmRpY2VzLnNvcnQoYXNjZW5kaW5nKTtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHJlY3Vyc2Uocm9vdE5vZGUsIHRyZWUsIGluZGljZXMsIG5vZGVzLCAwKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIHJlY3Vyc2Uocm9vdE5vZGUsIHRyZWUsIGluZGljZXMsIG5vZGVzLCByb290SW5kZXgpIHtcbiAgICAgICAgICAgICAgICBub2RlcyA9IG5vZGVzIHx8IHt9O1xuXG4gICAgICAgICAgICAgICAgaWYgKHJvb3ROb2RlKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmIChpbmRleEluUmFuZ2UoaW5kaWNlcywgcm9vdEluZGV4LCByb290SW5kZXgpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBub2Rlc1tyb290SW5kZXhdID0gcm9vdE5vZGU7XG4gICAgICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgICAgICB2YXIgdkNoaWxkcmVuID0gdHJlZS5jaGlsZHJlbjtcblxuICAgICAgICAgICAgICAgICAgICBpZiAodkNoaWxkcmVuKSB7XG5cbiAgICAgICAgICAgICAgICAgICAgICAgIHZhciBjaGlsZE5vZGVzID0gcm9vdE5vZGUuY2hpbGROb2RlcztcblxuICAgICAgICAgICAgICAgICAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCB0cmVlLmNoaWxkcmVuLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcm9vdEluZGV4ICs9IDE7XG5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB2YXIgdkNoaWxkID0gdkNoaWxkcmVuW2ldIHx8IG5vQ2hpbGQ7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdmFyIG5leHRJbmRleCA9IHJvb3RJbmRleCArICh2Q2hpbGQuY291bnQgfHwgMCk7XG5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBza2lwIHJlY3Vyc2lvbiBkb3duIHRoZSB0cmVlIGlmIHRoZXJlIGFyZSBubyBub2RlcyBkb3duIGhlcmVcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoaW5kZXhJblJhbmdlKGluZGljZXMsIHJvb3RJbmRleCwgbmV4dEluZGV4KSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICByZWN1cnNlKGNoaWxkTm9kZXNbaV0sIHZDaGlsZCwgaW5kaWNlcywgbm9kZXMsIHJvb3RJbmRleCk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcm9vdEluZGV4ID0gbmV4dEluZGV4O1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgcmV0dXJuIG5vZGVzO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAvLyBCaW5hcnkgc2VhcmNoIGZvciBhbiBpbmRleCBpbiB0aGUgaW50ZXJ2YWwgW2xlZnQsIHJpZ2h0XVxuICAgICAgICAgICAgZnVuY3Rpb24gaW5kZXhJblJhbmdlKGluZGljZXMsIGxlZnQsIHJpZ2h0KSB7XG4gICAgICAgICAgICAgICAgaWYgKGluZGljZXMubGVuZ3RoID09PSAwKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICB2YXIgbWluSW5kZXggPSAwO1xuICAgICAgICAgICAgICAgIHZhciBtYXhJbmRleCA9IGluZGljZXMubGVuZ3RoIC0gMTtcbiAgICAgICAgICAgICAgICB2YXIgY3VycmVudEluZGV4O1xuICAgICAgICAgICAgICAgIHZhciBjdXJyZW50SXRlbTtcblxuICAgICAgICAgICAgICAgIHdoaWxlIChtaW5JbmRleCA8PSBtYXhJbmRleCkge1xuICAgICAgICAgICAgICAgICAgICBjdXJyZW50SW5kZXggPSAobWF4SW5kZXggKyBtaW5JbmRleCkgLyAyID4+IDA7XG4gICAgICAgICAgICAgICAgICAgIGN1cnJlbnRJdGVtID0gaW5kaWNlc1tjdXJyZW50SW5kZXhdO1xuXG4gICAgICAgICAgICAgICAgICAgIGlmIChtaW5JbmRleCA9PT0gbWF4SW5kZXgpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBjdXJyZW50SXRlbSA+PSBsZWZ0ICYmIGN1cnJlbnRJdGVtIDw9IHJpZ2h0O1xuICAgICAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKGN1cnJlbnRJdGVtIDwgbGVmdCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgbWluSW5kZXggPSBjdXJyZW50SW5kZXggKyAxO1xuICAgICAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKGN1cnJlbnRJdGVtID4gcmlnaHQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIG1heEluZGV4ID0gY3VycmVudEluZGV4IC0gMTtcbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBmdW5jdGlvbiBhc2NlbmRpbmcoYSwgYikge1xuICAgICAgICAgICAgICAgIHJldHVybiBhID4gYiA/IDEgOiAtMTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSwge31dLCAxNzogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHtcbiAgICAgICAgICAgIHZhciBhcHBseVByb3BlcnRpZXMgPSByZXF1aXJlKFwiLi9hcHBseS1wcm9wZXJ0aWVzXCIpO1xuXG4gICAgICAgICAgICB2YXIgaXNXaWRnZXQgPSByZXF1aXJlKFwiLi4vdm5vZGUvaXMtd2lkZ2V0LmpzXCIpO1xuICAgICAgICAgICAgdmFyIFZQYXRjaCA9IHJlcXVpcmUoXCIuLi92bm9kZS92cGF0Y2guanNcIik7XG5cbiAgICAgICAgICAgIHZhciB1cGRhdGVXaWRnZXQgPSByZXF1aXJlKFwiLi91cGRhdGUtd2lkZ2V0XCIpO1xuXG4gICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IGFwcGx5UGF0Y2g7XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIGFwcGx5UGF0Y2godnBhdGNoLCBkb21Ob2RlLCByZW5kZXJPcHRpb25zKSB7XG4gICAgICAgICAgICAgICAgdmFyIHR5cGUgPSB2cGF0Y2gudHlwZTtcbiAgICAgICAgICAgICAgICB2YXIgdk5vZGUgPSB2cGF0Y2gudk5vZGU7XG4gICAgICAgICAgICAgICAgdmFyIHBhdGNoID0gdnBhdGNoLnBhdGNoO1xuXG4gICAgICAgICAgICAgICAgc3dpdGNoICh0eXBlKSB7XG4gICAgICAgICAgICAgICAgICAgIGNhc2UgVlBhdGNoLlJFTU9WRTpcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiByZW1vdmVOb2RlKGRvbU5vZGUsIHZOb2RlKTtcbiAgICAgICAgICAgICAgICAgICAgY2FzZSBWUGF0Y2guSU5TRVJUOlxuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGluc2VydE5vZGUoZG9tTm9kZSwgcGF0Y2gsIHJlbmRlck9wdGlvbnMpO1xuICAgICAgICAgICAgICAgICAgICBjYXNlIFZQYXRjaC5WVEVYVDpcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBzdHJpbmdQYXRjaChkb21Ob2RlLCB2Tm9kZSwgcGF0Y2gsIHJlbmRlck9wdGlvbnMpO1xuICAgICAgICAgICAgICAgICAgICBjYXNlIFZQYXRjaC5XSURHRVQ6XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gd2lkZ2V0UGF0Y2goZG9tTm9kZSwgdk5vZGUsIHBhdGNoLCByZW5kZXJPcHRpb25zKTtcbiAgICAgICAgICAgICAgICAgICAgY2FzZSBWUGF0Y2guVk5PREU6XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gdk5vZGVQYXRjaChkb21Ob2RlLCB2Tm9kZSwgcGF0Y2gsIHJlbmRlck9wdGlvbnMpO1xuICAgICAgICAgICAgICAgICAgICBjYXNlIFZQYXRjaC5PUkRFUjpcbiAgICAgICAgICAgICAgICAgICAgICAgIHJlb3JkZXJDaGlsZHJlbihkb21Ob2RlLCBwYXRjaCk7XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gZG9tTm9kZTtcbiAgICAgICAgICAgICAgICAgICAgY2FzZSBWUGF0Y2guUFJPUFM6XG4gICAgICAgICAgICAgICAgICAgICAgICBhcHBseVByb3BlcnRpZXMoZG9tTm9kZSwgcGF0Y2gsIHZOb2RlLnByb3BlcnRpZXMpO1xuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGRvbU5vZGU7XG4gICAgICAgICAgICAgICAgICAgIGNhc2UgVlBhdGNoLlRIVU5LOlxuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHJlcGxhY2VSb290KGRvbU5vZGUsIHJlbmRlck9wdGlvbnMucGF0Y2goZG9tTm9kZSwgcGF0Y2gsIHJlbmRlck9wdGlvbnMpKTtcbiAgICAgICAgICAgICAgICAgICAgZGVmYXVsdDpcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBkb21Ob2RlO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZnVuY3Rpb24gcmVtb3ZlTm9kZShkb21Ob2RlLCB2Tm9kZSkge1xuICAgICAgICAgICAgICAgIHZhciBwYXJlbnROb2RlID0gZG9tTm9kZS5wYXJlbnROb2RlO1xuXG4gICAgICAgICAgICAgICAgaWYgKHBhcmVudE5vZGUpIHtcbiAgICAgICAgICAgICAgICAgICAgcGFyZW50Tm9kZS5yZW1vdmVDaGlsZChkb21Ob2RlKTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICBkZXN0cm95V2lkZ2V0KGRvbU5vZGUsIHZOb2RlKTtcblxuICAgICAgICAgICAgICAgIHJldHVybiBudWxsO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBmdW5jdGlvbiBpbnNlcnROb2RlKHBhcmVudE5vZGUsIHZOb2RlLCByZW5kZXJPcHRpb25zKSB7XG4gICAgICAgICAgICAgICAgdmFyIG5ld05vZGUgPSByZW5kZXJPcHRpb25zLnJlbmRlcih2Tm9kZSwgcmVuZGVyT3B0aW9ucyk7XG5cbiAgICAgICAgICAgICAgICBpZiAocGFyZW50Tm9kZSkge1xuICAgICAgICAgICAgICAgICAgICBwYXJlbnROb2RlLmFwcGVuZENoaWxkKG5ld05vZGUpO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHJldHVybiBwYXJlbnROb2RlO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBmdW5jdGlvbiBzdHJpbmdQYXRjaChkb21Ob2RlLCBsZWZ0Vk5vZGUsIHZUZXh0LCByZW5kZXJPcHRpb25zKSB7XG4gICAgICAgICAgICAgICAgdmFyIG5ld05vZGU7XG5cbiAgICAgICAgICAgICAgICBpZiAoZG9tTm9kZS5ub2RlVHlwZSA9PT0gMykge1xuICAgICAgICAgICAgICAgICAgICBkb21Ob2RlLnJlcGxhY2VEYXRhKDAsIGRvbU5vZGUubGVuZ3RoLCB2VGV4dC50ZXh0KTtcbiAgICAgICAgICAgICAgICAgICAgbmV3Tm9kZSA9IGRvbU5vZGU7XG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgdmFyIHBhcmVudE5vZGUgPSBkb21Ob2RlLnBhcmVudE5vZGU7XG4gICAgICAgICAgICAgICAgICAgIG5ld05vZGUgPSByZW5kZXJPcHRpb25zLnJlbmRlcih2VGV4dCwgcmVuZGVyT3B0aW9ucyk7XG5cbiAgICAgICAgICAgICAgICAgICAgaWYgKHBhcmVudE5vZGUgJiYgbmV3Tm9kZSAhPT0gZG9tTm9kZSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgcGFyZW50Tm9kZS5yZXBsYWNlQ2hpbGQobmV3Tm9kZSwgZG9tTm9kZSk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICByZXR1cm4gbmV3Tm9kZTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZnVuY3Rpb24gd2lkZ2V0UGF0Y2goZG9tTm9kZSwgbGVmdFZOb2RlLCB3aWRnZXQsIHJlbmRlck9wdGlvbnMpIHtcbiAgICAgICAgICAgICAgICB2YXIgdXBkYXRpbmcgPSB1cGRhdGVXaWRnZXQobGVmdFZOb2RlLCB3aWRnZXQpO1xuICAgICAgICAgICAgICAgIHZhciBuZXdOb2RlO1xuXG4gICAgICAgICAgICAgICAgaWYgKHVwZGF0aW5nKSB7XG4gICAgICAgICAgICAgICAgICAgIG5ld05vZGUgPSB3aWRnZXQudXBkYXRlKGxlZnRWTm9kZSwgZG9tTm9kZSkgfHwgZG9tTm9kZTtcbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICBuZXdOb2RlID0gcmVuZGVyT3B0aW9ucy5yZW5kZXIod2lkZ2V0LCByZW5kZXJPcHRpb25zKTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICB2YXIgcGFyZW50Tm9kZSA9IGRvbU5vZGUucGFyZW50Tm9kZTtcblxuICAgICAgICAgICAgICAgIGlmIChwYXJlbnROb2RlICYmIG5ld05vZGUgIT09IGRvbU5vZGUpIHtcbiAgICAgICAgICAgICAgICAgICAgcGFyZW50Tm9kZS5yZXBsYWNlQ2hpbGQobmV3Tm9kZSwgZG9tTm9kZSk7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgaWYgKCF1cGRhdGluZykge1xuICAgICAgICAgICAgICAgICAgICBkZXN0cm95V2lkZ2V0KGRvbU5vZGUsIGxlZnRWTm9kZSk7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgcmV0dXJuIG5ld05vZGU7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIHZOb2RlUGF0Y2goZG9tTm9kZSwgbGVmdFZOb2RlLCB2Tm9kZSwgcmVuZGVyT3B0aW9ucykge1xuICAgICAgICAgICAgICAgIHZhciBwYXJlbnROb2RlID0gZG9tTm9kZS5wYXJlbnROb2RlO1xuICAgICAgICAgICAgICAgIHZhciBuZXdOb2RlID0gcmVuZGVyT3B0aW9ucy5yZW5kZXIodk5vZGUsIHJlbmRlck9wdGlvbnMpO1xuXG4gICAgICAgICAgICAgICAgaWYgKHBhcmVudE5vZGUgJiYgbmV3Tm9kZSAhPT0gZG9tTm9kZSkge1xuICAgICAgICAgICAgICAgICAgICBwYXJlbnROb2RlLnJlcGxhY2VDaGlsZChuZXdOb2RlLCBkb21Ob2RlKTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICByZXR1cm4gbmV3Tm9kZTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZnVuY3Rpb24gZGVzdHJveVdpZGdldChkb21Ob2RlLCB3KSB7XG4gICAgICAgICAgICAgICAgaWYgKHR5cGVvZiB3LmRlc3Ryb3kgPT09IFwiZnVuY3Rpb25cIiAmJiBpc1dpZGdldCh3KSkge1xuICAgICAgICAgICAgICAgICAgICB3LmRlc3Ryb3koZG9tTm9kZSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBmdW5jdGlvbiByZW9yZGVyQ2hpbGRyZW4oZG9tTm9kZSwgbW92ZXMpIHtcbiAgICAgICAgICAgICAgICB2YXIgY2hpbGROb2RlcyA9IGRvbU5vZGUuY2hpbGROb2RlcztcbiAgICAgICAgICAgICAgICB2YXIga2V5TWFwID0ge307XG4gICAgICAgICAgICAgICAgdmFyIG5vZGU7XG4gICAgICAgICAgICAgICAgdmFyIHJlbW92ZTtcbiAgICAgICAgICAgICAgICB2YXIgaW5zZXJ0O1xuXG4gICAgICAgICAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCBtb3Zlcy5yZW1vdmVzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICAgICAgICAgIHJlbW92ZSA9IG1vdmVzLnJlbW92ZXNbaV07XG4gICAgICAgICAgICAgICAgICAgIG5vZGUgPSBjaGlsZE5vZGVzW3JlbW92ZS5mcm9tXTtcbiAgICAgICAgICAgICAgICAgICAgaWYgKHJlbW92ZS5rZXkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGtleU1hcFtyZW1vdmUua2V5XSA9IG5vZGU7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgZG9tTm9kZS5yZW1vdmVDaGlsZChub2RlKTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICB2YXIgbGVuZ3RoID0gY2hpbGROb2Rlcy5sZW5ndGg7XG4gICAgICAgICAgICAgICAgZm9yICh2YXIgaiA9IDA7IGogPCBtb3Zlcy5pbnNlcnRzLmxlbmd0aDsgaisrKSB7XG4gICAgICAgICAgICAgICAgICAgIGluc2VydCA9IG1vdmVzLmluc2VydHNbal07XG4gICAgICAgICAgICAgICAgICAgIG5vZGUgPSBrZXlNYXBbaW5zZXJ0LmtleV07XG4gICAgICAgICAgICAgICAgICAgIC8vIHRoaXMgaXMgdGhlIHdlaXJkZXN0IGJ1ZyBpJ3ZlIGV2ZXIgc2VlbiBpbiB3ZWJraXRcbiAgICAgICAgICAgICAgICAgICAgZG9tTm9kZS5pbnNlcnRCZWZvcmUobm9kZSwgaW5zZXJ0LnRvID49IGxlbmd0aCsrID8gbnVsbCA6IGNoaWxkTm9kZXNbaW5zZXJ0LnRvXSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBmdW5jdGlvbiByZXBsYWNlUm9vdChvbGRSb290LCBuZXdSb290KSB7XG4gICAgICAgICAgICAgICAgaWYgKG9sZFJvb3QgJiYgbmV3Um9vdCAmJiBvbGRSb290ICE9PSBuZXdSb290ICYmIG9sZFJvb3QucGFyZW50Tm9kZSkge1xuICAgICAgICAgICAgICAgICAgICBvbGRSb290LnBhcmVudE5vZGUucmVwbGFjZUNoaWxkKG5ld1Jvb3QsIG9sZFJvb3QpO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHJldHVybiBuZXdSb290O1xuICAgICAgICAgICAgfVxuICAgICAgICB9LCB7IFwiLi4vdm5vZGUvaXMtd2lkZ2V0LmpzXCI6IDI5LCBcIi4uL3Zub2RlL3ZwYXRjaC5qc1wiOiAzMiwgXCIuL2FwcGx5LXByb3BlcnRpZXNcIjogMTQsIFwiLi91cGRhdGUtd2lkZ2V0XCI6IDE5IH1dLCAxODogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHtcbiAgICAgICAgICAgIHZhciBkb2N1bWVudCA9IHJlcXVpcmUoXCJnbG9iYWwvZG9jdW1lbnRcIik7XG4gICAgICAgICAgICB2YXIgaXNBcnJheSA9IHJlcXVpcmUoXCJ4LWlzLWFycmF5XCIpO1xuXG4gICAgICAgICAgICB2YXIgcmVuZGVyID0gcmVxdWlyZShcIi4vY3JlYXRlLWVsZW1lbnRcIik7XG4gICAgICAgICAgICB2YXIgZG9tSW5kZXggPSByZXF1aXJlKFwiLi9kb20taW5kZXhcIik7XG4gICAgICAgICAgICB2YXIgcGF0Y2hPcCA9IHJlcXVpcmUoXCIuL3BhdGNoLW9wXCIpO1xuICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBwYXRjaDtcblxuICAgICAgICAgICAgZnVuY3Rpb24gcGF0Y2gocm9vdE5vZGUsIHBhdGNoZXMsIHJlbmRlck9wdGlvbnMpIHtcbiAgICAgICAgICAgICAgICByZW5kZXJPcHRpb25zID0gcmVuZGVyT3B0aW9ucyB8fCB7fTtcbiAgICAgICAgICAgICAgICByZW5kZXJPcHRpb25zLnBhdGNoID0gcmVuZGVyT3B0aW9ucy5wYXRjaCAmJiByZW5kZXJPcHRpb25zLnBhdGNoICE9PSBwYXRjaCA/IHJlbmRlck9wdGlvbnMucGF0Y2ggOiBwYXRjaFJlY3Vyc2l2ZTtcbiAgICAgICAgICAgICAgICByZW5kZXJPcHRpb25zLnJlbmRlciA9IHJlbmRlck9wdGlvbnMucmVuZGVyIHx8IHJlbmRlcjtcblxuICAgICAgICAgICAgICAgIHJldHVybiByZW5kZXJPcHRpb25zLnBhdGNoKHJvb3ROb2RlLCBwYXRjaGVzLCByZW5kZXJPcHRpb25zKTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZnVuY3Rpb24gcGF0Y2hSZWN1cnNpdmUocm9vdE5vZGUsIHBhdGNoZXMsIHJlbmRlck9wdGlvbnMpIHtcbiAgICAgICAgICAgICAgICB2YXIgaW5kaWNlcyA9IHBhdGNoSW5kaWNlcyhwYXRjaGVzKTtcblxuICAgICAgICAgICAgICAgIGlmIChpbmRpY2VzLmxlbmd0aCA9PT0gMCkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gcm9vdE5vZGU7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgdmFyIGluZGV4ID0gZG9tSW5kZXgocm9vdE5vZGUsIHBhdGNoZXMuYSwgaW5kaWNlcyk7XG4gICAgICAgICAgICAgICAgdmFyIG93bmVyRG9jdW1lbnQgPSByb290Tm9kZS5vd25lckRvY3VtZW50O1xuXG4gICAgICAgICAgICAgICAgaWYgKCFyZW5kZXJPcHRpb25zLmRvY3VtZW50ICYmIG93bmVyRG9jdW1lbnQgIT09IGRvY3VtZW50KSB7XG4gICAgICAgICAgICAgICAgICAgIHJlbmRlck9wdGlvbnMuZG9jdW1lbnQgPSBvd25lckRvY3VtZW50O1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgaW5kaWNlcy5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgICAgICAgICB2YXIgbm9kZUluZGV4ID0gaW5kaWNlc1tpXTtcbiAgICAgICAgICAgICAgICAgICAgcm9vdE5vZGUgPSBhcHBseVBhdGNoKHJvb3ROb2RlLCBpbmRleFtub2RlSW5kZXhdLCBwYXRjaGVzW25vZGVJbmRleF0sIHJlbmRlck9wdGlvbnMpO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHJldHVybiByb290Tm9kZTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZnVuY3Rpb24gYXBwbHlQYXRjaChyb290Tm9kZSwgZG9tTm9kZSwgcGF0Y2hMaXN0LCByZW5kZXJPcHRpb25zKSB7XG4gICAgICAgICAgICAgICAgaWYgKCFkb21Ob2RlKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiByb290Tm9kZTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICB2YXIgbmV3Tm9kZTtcblxuICAgICAgICAgICAgICAgIGlmIChpc0FycmF5KHBhdGNoTGlzdCkpIHtcbiAgICAgICAgICAgICAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCBwYXRjaExpc3QubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIG5ld05vZGUgPSBwYXRjaE9wKHBhdGNoTGlzdFtpXSwgZG9tTm9kZSwgcmVuZGVyT3B0aW9ucyk7XG5cbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChkb21Ob2RlID09PSByb290Tm9kZSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJvb3ROb2RlID0gbmV3Tm9kZTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIG5ld05vZGUgPSBwYXRjaE9wKHBhdGNoTGlzdCwgZG9tTm9kZSwgcmVuZGVyT3B0aW9ucyk7XG5cbiAgICAgICAgICAgICAgICAgICAgaWYgKGRvbU5vZGUgPT09IHJvb3ROb2RlKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICByb290Tm9kZSA9IG5ld05vZGU7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICByZXR1cm4gcm9vdE5vZGU7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIHBhdGNoSW5kaWNlcyhwYXRjaGVzKSB7XG4gICAgICAgICAgICAgICAgdmFyIGluZGljZXMgPSBbXTtcblxuICAgICAgICAgICAgICAgIGZvciAodmFyIGtleSBpbiBwYXRjaGVzKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmIChrZXkgIT09IFwiYVwiKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBpbmRpY2VzLnB1c2goTnVtYmVyKGtleSkpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgcmV0dXJuIGluZGljZXM7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0sIHsgXCIuL2NyZWF0ZS1lbGVtZW50XCI6IDE1LCBcIi4vZG9tLWluZGV4XCI6IDE2LCBcIi4vcGF0Y2gtb3BcIjogMTcsIFwiZ2xvYmFsL2RvY3VtZW50XCI6IDEwLCBcIngtaXMtYXJyYXlcIjogMTIgfV0sIDE5OiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge1xuICAgICAgICAgICAgdmFyIGlzV2lkZ2V0ID0gcmVxdWlyZShcIi4uL3Zub2RlL2lzLXdpZGdldC5qc1wiKTtcblxuICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSB1cGRhdGVXaWRnZXQ7XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIHVwZGF0ZVdpZGdldChhLCBiKSB7XG4gICAgICAgICAgICAgICAgaWYgKGlzV2lkZ2V0KGEpICYmIGlzV2lkZ2V0KGIpKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmIChcIm5hbWVcIiBpbiBhICYmIFwibmFtZVwiIGluIGIpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBhLmlkID09PSBiLmlkO1xuICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGEuaW5pdCA9PT0gYi5pbml0O1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICAgICAgfVxuICAgICAgICB9LCB7IFwiLi4vdm5vZGUvaXMtd2lkZ2V0LmpzXCI6IDI5IH1dLCAyMDogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHtcbiAgICAgICAgICAgIFwidXNlIHN0cmljdFwiO1xuXG4gICAgICAgICAgICB2YXIgRXZTdG9yZSA9IHJlcXVpcmUoXCJldi1zdG9yZVwiKTtcblxuICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBFdkhvb2s7XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIEV2SG9vayh2YWx1ZSkge1xuICAgICAgICAgICAgICAgIGlmICghKHRoaXMgaW5zdGFuY2VvZiBFdkhvb2spKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBuZXcgRXZIb29rKHZhbHVlKTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICB0aGlzLnZhbHVlID0gdmFsdWU7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIEV2SG9vay5wcm90b3R5cGUuaG9vayA9IGZ1bmN0aW9uIChub2RlLCBwcm9wZXJ0eU5hbWUpIHtcbiAgICAgICAgICAgICAgICB2YXIgZXMgPSBFdlN0b3JlKG5vZGUpO1xuICAgICAgICAgICAgICAgIHZhciBwcm9wTmFtZSA9IHByb3BlcnR5TmFtZS5zdWJzdHIoMyk7XG5cbiAgICAgICAgICAgICAgICBlc1twcm9wTmFtZV0gPSB0aGlzLnZhbHVlO1xuICAgICAgICAgICAgfTtcblxuICAgICAgICAgICAgRXZIb29rLnByb3RvdHlwZS51bmhvb2sgPSBmdW5jdGlvbiAobm9kZSwgcHJvcGVydHlOYW1lKSB7XG4gICAgICAgICAgICAgICAgdmFyIGVzID0gRXZTdG9yZShub2RlKTtcbiAgICAgICAgICAgICAgICB2YXIgcHJvcE5hbWUgPSBwcm9wZXJ0eU5hbWUuc3Vic3RyKDMpO1xuXG4gICAgICAgICAgICAgICAgZXNbcHJvcE5hbWVdID0gdW5kZWZpbmVkO1xuICAgICAgICAgICAgfTtcbiAgICAgICAgfSwgeyBcImV2LXN0b3JlXCI6IDcgfV0sIDIxOiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge1xuICAgICAgICAgICAgXCJ1c2Ugc3RyaWN0XCI7XG5cbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gU29mdFNldEhvb2s7XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIFNvZnRTZXRIb29rKHZhbHVlKSB7XG4gICAgICAgICAgICAgICAgaWYgKCEodGhpcyBpbnN0YW5jZW9mIFNvZnRTZXRIb29rKSkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gbmV3IFNvZnRTZXRIb29rKHZhbHVlKTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICB0aGlzLnZhbHVlID0gdmFsdWU7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIFNvZnRTZXRIb29rLnByb3RvdHlwZS5ob29rID0gZnVuY3Rpb24gKG5vZGUsIHByb3BlcnR5TmFtZSkge1xuICAgICAgICAgICAgICAgIGlmIChub2RlW3Byb3BlcnR5TmFtZV0gIT09IHRoaXMudmFsdWUpIHtcbiAgICAgICAgICAgICAgICAgICAgbm9kZVtwcm9wZXJ0eU5hbWVdID0gdGhpcy52YWx1ZTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9O1xuICAgICAgICB9LCB7fV0sIDIyOiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge1xuICAgICAgICAgICAgXCJ1c2Ugc3RyaWN0XCI7XG5cbiAgICAgICAgICAgIHZhciBpc0FycmF5ID0gcmVxdWlyZShcIngtaXMtYXJyYXlcIik7XG5cbiAgICAgICAgICAgIHZhciBWTm9kZSA9IHJlcXVpcmUoXCIuLi92bm9kZS92bm9kZS5qc1wiKTtcbiAgICAgICAgICAgIHZhciBWVGV4dCA9IHJlcXVpcmUoXCIuLi92bm9kZS92dGV4dC5qc1wiKTtcbiAgICAgICAgICAgIHZhciBpc1ZOb2RlID0gcmVxdWlyZShcIi4uL3Zub2RlL2lzLXZub2RlXCIpO1xuICAgICAgICAgICAgdmFyIGlzVlRleHQgPSByZXF1aXJlKFwiLi4vdm5vZGUvaXMtdnRleHRcIik7XG4gICAgICAgICAgICB2YXIgaXNXaWRnZXQgPSByZXF1aXJlKFwiLi4vdm5vZGUvaXMtd2lkZ2V0XCIpO1xuICAgICAgICAgICAgdmFyIGlzSG9vayA9IHJlcXVpcmUoXCIuLi92bm9kZS9pcy12aG9va1wiKTtcbiAgICAgICAgICAgIHZhciBpc1ZUaHVuayA9IHJlcXVpcmUoXCIuLi92bm9kZS9pcy10aHVua1wiKTtcblxuICAgICAgICAgICAgdmFyIHBhcnNlVGFnID0gcmVxdWlyZShcIi4vcGFyc2UtdGFnLmpzXCIpO1xuICAgICAgICAgICAgdmFyIHNvZnRTZXRIb29rID0gcmVxdWlyZShcIi4vaG9va3Mvc29mdC1zZXQtaG9vay5qc1wiKTtcbiAgICAgICAgICAgIHZhciBldkhvb2sgPSByZXF1aXJlKFwiLi9ob29rcy9ldi1ob29rLmpzXCIpO1xuXG4gICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IGg7XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIGgodGFnTmFtZSwgcHJvcGVydGllcywgY2hpbGRyZW4pIHtcbiAgICAgICAgICAgICAgICB2YXIgY2hpbGROb2RlcyA9IFtdO1xuICAgICAgICAgICAgICAgIHZhciB0YWcsIHByb3BzLCBrZXksIG5hbWVzcGFjZTtcblxuICAgICAgICAgICAgICAgIGlmICghY2hpbGRyZW4gJiYgaXNDaGlsZHJlbihwcm9wZXJ0aWVzKSkge1xuICAgICAgICAgICAgICAgICAgICBjaGlsZHJlbiA9IHByb3BlcnRpZXM7XG4gICAgICAgICAgICAgICAgICAgIHByb3BzID0ge307XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgcHJvcHMgPSBwcm9wcyB8fCBwcm9wZXJ0aWVzIHx8IHt9O1xuICAgICAgICAgICAgICAgIHRhZyA9IHBhcnNlVGFnKHRhZ05hbWUsIHByb3BzKTtcblxuICAgICAgICAgICAgICAgIC8vIHN1cHBvcnQga2V5c1xuICAgICAgICAgICAgICAgIGlmIChwcm9wcy5oYXNPd25Qcm9wZXJ0eShcImtleVwiKSkge1xuICAgICAgICAgICAgICAgICAgICBrZXkgPSBwcm9wcy5rZXk7XG4gICAgICAgICAgICAgICAgICAgIHByb3BzLmtleSA9IHVuZGVmaW5lZDtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAvLyBzdXBwb3J0IG5hbWVzcGFjZVxuICAgICAgICAgICAgICAgIGlmIChwcm9wcy5oYXNPd25Qcm9wZXJ0eShcIm5hbWVzcGFjZVwiKSkge1xuICAgICAgICAgICAgICAgICAgICBuYW1lc3BhY2UgPSBwcm9wcy5uYW1lc3BhY2U7XG4gICAgICAgICAgICAgICAgICAgIHByb3BzLm5hbWVzcGFjZSA9IHVuZGVmaW5lZDtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAvLyBmaXggY3Vyc29yIGJ1Z1xuICAgICAgICAgICAgICAgIGlmICh0YWcgPT09IFwiSU5QVVRcIiAmJiAhbmFtZXNwYWNlICYmIHByb3BzLmhhc093blByb3BlcnR5KFwidmFsdWVcIikgJiYgcHJvcHMudmFsdWUgIT09IHVuZGVmaW5lZCAmJiAhaXNIb29rKHByb3BzLnZhbHVlKSkge1xuICAgICAgICAgICAgICAgICAgICBwcm9wcy52YWx1ZSA9IHNvZnRTZXRIb29rKHByb3BzLnZhbHVlKTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICB0cmFuc2Zvcm1Qcm9wZXJ0aWVzKHByb3BzKTtcblxuICAgICAgICAgICAgICAgIGlmIChjaGlsZHJlbiAhPT0gdW5kZWZpbmVkICYmIGNoaWxkcmVuICE9PSBudWxsKSB7XG4gICAgICAgICAgICAgICAgICAgIGFkZENoaWxkKGNoaWxkcmVuLCBjaGlsZE5vZGVzLCB0YWcsIHByb3BzKTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICByZXR1cm4gbmV3IFZOb2RlKHRhZywgcHJvcHMsIGNoaWxkTm9kZXMsIGtleSwgbmFtZXNwYWNlKTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZnVuY3Rpb24gYWRkQ2hpbGQoYywgY2hpbGROb2RlcywgdGFnLCBwcm9wcykge1xuICAgICAgICAgICAgICAgIGlmICh0eXBlb2YgYyA9PT0gXCJzdHJpbmdcIikge1xuICAgICAgICAgICAgICAgICAgICBjaGlsZE5vZGVzLnB1c2gobmV3IFZUZXh0KGMpKTtcbiAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKHR5cGVvZiBjID09PSBcIm51bWJlclwiKSB7XG4gICAgICAgICAgICAgICAgICAgIGNoaWxkTm9kZXMucHVzaChuZXcgVlRleHQoU3RyaW5nKGMpKSk7XG4gICAgICAgICAgICAgICAgfSBlbHNlIGlmIChpc0NoaWxkKGMpKSB7XG4gICAgICAgICAgICAgICAgICAgIGNoaWxkTm9kZXMucHVzaChjKTtcbiAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKGlzQXJyYXkoYykpIHtcbiAgICAgICAgICAgICAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCBjLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBhZGRDaGlsZChjW2ldLCBjaGlsZE5vZGVzLCB0YWcsIHByb3BzKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoYyA9PT0gbnVsbCB8fCBjID09PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIHRocm93IFVuZXhwZWN0ZWRWaXJ0dWFsRWxlbWVudCh7XG4gICAgICAgICAgICAgICAgICAgICAgICBmb3JlaWduT2JqZWN0OiBjLFxuICAgICAgICAgICAgICAgICAgICAgICAgcGFyZW50Vm5vZGU6IHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0YWdOYW1lOiB0YWcsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcHJvcGVydGllczogcHJvcHNcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBmdW5jdGlvbiB0cmFuc2Zvcm1Qcm9wZXJ0aWVzKHByb3BzKSB7XG4gICAgICAgICAgICAgICAgZm9yICh2YXIgcHJvcE5hbWUgaW4gcHJvcHMpIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKHByb3BzLmhhc093blByb3BlcnR5KHByb3BOYW1lKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgdmFyIHZhbHVlID0gcHJvcHNbcHJvcE5hbWVdO1xuXG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoaXNIb29rKHZhbHVlKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnRpbnVlO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAocHJvcE5hbWUuc3Vic3RyKDAsIDMpID09PSBcImV2LVwiKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gYWRkIGV2LWZvbyBzdXBwb3J0XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcHJvcHNbcHJvcE5hbWVdID0gZXZIb29rKHZhbHVlKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZnVuY3Rpb24gaXNDaGlsZCh4KSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGlzVk5vZGUoeCkgfHwgaXNWVGV4dCh4KSB8fCBpc1dpZGdldCh4KSB8fCBpc1ZUaHVuayh4KTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZnVuY3Rpb24gaXNDaGlsZHJlbih4KSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHR5cGVvZiB4ID09PSBcInN0cmluZ1wiIHx8IGlzQXJyYXkoeCkgfHwgaXNDaGlsZCh4KTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZnVuY3Rpb24gVW5leHBlY3RlZFZpcnR1YWxFbGVtZW50KGRhdGEpIHtcbiAgICAgICAgICAgICAgICB2YXIgZXJyID0gbmV3IEVycm9yKCk7XG5cbiAgICAgICAgICAgICAgICBlcnIudHlwZSA9IFwidmlydHVhbC1oeXBlcnNjcmlwdC51bmV4cGVjdGVkLnZpcnR1YWwtZWxlbWVudFwiO1xuICAgICAgICAgICAgICAgIGVyci5tZXNzYWdlID0gXCJVbmV4cGVjdGVkIHZpcnR1YWwgY2hpbGQgcGFzc2VkIHRvIGgoKS5cXG5cIiArIFwiRXhwZWN0ZWQgYSBWTm9kZSAvIFZ0aHVuayAvIFZXaWRnZXQgLyBzdHJpbmcgYnV0OlxcblwiICsgXCJnb3Q6XFxuXCIgKyBlcnJvclN0cmluZyhkYXRhLmZvcmVpZ25PYmplY3QpICsgXCIuXFxuXCIgKyBcIlRoZSBwYXJlbnQgdm5vZGUgaXM6XFxuXCIgKyBlcnJvclN0cmluZyhkYXRhLnBhcmVudFZub2RlKTtcbiAgICAgICAgICAgICAgICBcIlxcblwiICsgXCJTdWdnZXN0ZWQgZml4OiBjaGFuZ2UgeW91ciBgaCguLi4sIFsgLi4uIF0pYCBjYWxsc2l0ZS5cIjtcbiAgICAgICAgICAgICAgICBlcnIuZm9yZWlnbk9iamVjdCA9IGRhdGEuZm9yZWlnbk9iamVjdDtcbiAgICAgICAgICAgICAgICBlcnIucGFyZW50Vm5vZGUgPSBkYXRhLnBhcmVudFZub2RlO1xuXG4gICAgICAgICAgICAgICAgcmV0dXJuIGVycjtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZnVuY3Rpb24gZXJyb3JTdHJpbmcob2JqKSB7XG4gICAgICAgICAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIEpTT04uc3RyaW5naWZ5KG9iaiwgbnVsbCwgXCIgICAgXCIpO1xuICAgICAgICAgICAgICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIFN0cmluZyhvYmopO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgfSwgeyBcIi4uL3Zub2RlL2lzLXRodW5rXCI6IDI1LCBcIi4uL3Zub2RlL2lzLXZob29rXCI6IDI2LCBcIi4uL3Zub2RlL2lzLXZub2RlXCI6IDI3LCBcIi4uL3Zub2RlL2lzLXZ0ZXh0XCI6IDI4LCBcIi4uL3Zub2RlL2lzLXdpZGdldFwiOiAyOSwgXCIuLi92bm9kZS92bm9kZS5qc1wiOiAzMSwgXCIuLi92bm9kZS92dGV4dC5qc1wiOiAzMywgXCIuL2hvb2tzL2V2LWhvb2suanNcIjogMjAsIFwiLi9ob29rcy9zb2Z0LXNldC1ob29rLmpzXCI6IDIxLCBcIi4vcGFyc2UtdGFnLmpzXCI6IDIzLCBcIngtaXMtYXJyYXlcIjogMTIgfV0sIDIzOiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge1xuICAgICAgICAgICAgXCJ1c2Ugc3RyaWN0XCI7XG5cbiAgICAgICAgICAgIHZhciBzcGxpdCA9IHJlcXVpcmUoXCJicm93c2VyLXNwbGl0XCIpO1xuXG4gICAgICAgICAgICB2YXIgY2xhc3NJZFNwbGl0ID0gLyhbXFwuI10/W2EtekEtWjAtOVxcdTAwN0YtXFx1RkZGRl86LV0rKS87XG4gICAgICAgICAgICB2YXIgbm90Q2xhc3NJZCA9IC9eXFwufCMvO1xuXG4gICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IHBhcnNlVGFnO1xuXG4gICAgICAgICAgICBmdW5jdGlvbiBwYXJzZVRhZyh0YWcsIHByb3BzKSB7XG4gICAgICAgICAgICAgICAgaWYgKCF0YWcpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIFwiRElWXCI7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgdmFyIG5vSWQgPSAhcHJvcHMuaGFzT3duUHJvcGVydHkoXCJpZFwiKTtcblxuICAgICAgICAgICAgICAgIHZhciB0YWdQYXJ0cyA9IHNwbGl0KHRhZywgY2xhc3NJZFNwbGl0KTtcbiAgICAgICAgICAgICAgICB2YXIgdGFnTmFtZSA9IG51bGw7XG5cbiAgICAgICAgICAgICAgICBpZiAobm90Q2xhc3NJZC50ZXN0KHRhZ1BhcnRzWzFdKSkge1xuICAgICAgICAgICAgICAgICAgICB0YWdOYW1lID0gXCJESVZcIjtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICB2YXIgY2xhc3NlcywgcGFydCwgdHlwZSwgaTtcblxuICAgICAgICAgICAgICAgIGZvciAoaSA9IDA7IGkgPCB0YWdQYXJ0cy5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgICAgICAgICBwYXJ0ID0gdGFnUGFydHNbaV07XG5cbiAgICAgICAgICAgICAgICAgICAgaWYgKCFwYXJ0KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBjb250aW51ZTtcbiAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgIHR5cGUgPSBwYXJ0LmNoYXJBdCgwKTtcblxuICAgICAgICAgICAgICAgICAgICBpZiAoIXRhZ05hbWUpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHRhZ05hbWUgPSBwYXJ0O1xuICAgICAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKHR5cGUgPT09IFwiLlwiKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBjbGFzc2VzID0gY2xhc3NlcyB8fCBbXTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGNsYXNzZXMucHVzaChwYXJ0LnN1YnN0cmluZygxLCBwYXJ0Lmxlbmd0aCkpO1xuICAgICAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKHR5cGUgPT09IFwiI1wiICYmIG5vSWQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHByb3BzLmlkID0gcGFydC5zdWJzdHJpbmcoMSwgcGFydC5sZW5ndGgpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgaWYgKGNsYXNzZXMpIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKHByb3BzLmNsYXNzTmFtZSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgY2xhc3Nlcy5wdXNoKHByb3BzLmNsYXNzTmFtZSk7XG4gICAgICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgICAgICBwcm9wcy5jbGFzc05hbWUgPSBjbGFzc2VzLmpvaW4oXCIgXCIpO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHJldHVybiBwcm9wcy5uYW1lc3BhY2UgPyB0YWdOYW1lIDogdGFnTmFtZS50b1VwcGVyQ2FzZSgpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9LCB7IFwiYnJvd3Nlci1zcGxpdFwiOiA1IH1dLCAyNDogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHtcbiAgICAgICAgICAgIHZhciBpc1ZOb2RlID0gcmVxdWlyZShcIi4vaXMtdm5vZGVcIik7XG4gICAgICAgICAgICB2YXIgaXNWVGV4dCA9IHJlcXVpcmUoXCIuL2lzLXZ0ZXh0XCIpO1xuICAgICAgICAgICAgdmFyIGlzV2lkZ2V0ID0gcmVxdWlyZShcIi4vaXMtd2lkZ2V0XCIpO1xuICAgICAgICAgICAgdmFyIGlzVGh1bmsgPSByZXF1aXJlKFwiLi9pcy10aHVua1wiKTtcblxuICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBoYW5kbGVUaHVuaztcblxuICAgICAgICAgICAgZnVuY3Rpb24gaGFuZGxlVGh1bmsoYSwgYikge1xuICAgICAgICAgICAgICAgIHZhciByZW5kZXJlZEEgPSBhO1xuICAgICAgICAgICAgICAgIHZhciByZW5kZXJlZEIgPSBiO1xuXG4gICAgICAgICAgICAgICAgaWYgKGlzVGh1bmsoYikpIHtcbiAgICAgICAgICAgICAgICAgICAgcmVuZGVyZWRCID0gcmVuZGVyVGh1bmsoYiwgYSk7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgaWYgKGlzVGh1bmsoYSkpIHtcbiAgICAgICAgICAgICAgICAgICAgcmVuZGVyZWRBID0gcmVuZGVyVGh1bmsoYSwgbnVsbCk7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgICAgICAgICAgYTogcmVuZGVyZWRBLFxuICAgICAgICAgICAgICAgICAgICBiOiByZW5kZXJlZEJcbiAgICAgICAgICAgICAgICB9O1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBmdW5jdGlvbiByZW5kZXJUaHVuayh0aHVuaywgcHJldmlvdXMpIHtcbiAgICAgICAgICAgICAgICB2YXIgcmVuZGVyZWRUaHVuayA9IHRodW5rLnZub2RlO1xuXG4gICAgICAgICAgICAgICAgaWYgKCFyZW5kZXJlZFRodW5rKSB7XG4gICAgICAgICAgICAgICAgICAgIHJlbmRlcmVkVGh1bmsgPSB0aHVuay52bm9kZSA9IHRodW5rLnJlbmRlcihwcmV2aW91cyk7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgaWYgKCEoaXNWTm9kZShyZW5kZXJlZFRodW5rKSB8fCBpc1ZUZXh0KHJlbmRlcmVkVGh1bmspIHx8IGlzV2lkZ2V0KHJlbmRlcmVkVGh1bmspKSkge1xuICAgICAgICAgICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoXCJ0aHVuayBkaWQgbm90IHJldHVybiBhIHZhbGlkIG5vZGVcIik7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgcmV0dXJuIHJlbmRlcmVkVGh1bms7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0sIHsgXCIuL2lzLXRodW5rXCI6IDI1LCBcIi4vaXMtdm5vZGVcIjogMjcsIFwiLi9pcy12dGV4dFwiOiAyOCwgXCIuL2lzLXdpZGdldFwiOiAyOSB9XSwgMjU6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IGlzVGh1bms7XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIGlzVGh1bmsodCkge1xuICAgICAgICAgICAgICAgIHJldHVybiB0ICYmIHQudHlwZSA9PT0gXCJUaHVua1wiO1xuICAgICAgICAgICAgfVxuICAgICAgICB9LCB7fV0sIDI2OiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge1xuICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBpc0hvb2s7XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIGlzSG9vayhob29rKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGhvb2sgJiYgKHR5cGVvZiBob29rLmhvb2sgPT09IFwiZnVuY3Rpb25cIiAmJiAhaG9vay5oYXNPd25Qcm9wZXJ0eShcImhvb2tcIikgfHwgdHlwZW9mIGhvb2sudW5ob29rID09PSBcImZ1bmN0aW9uXCIgJiYgIWhvb2suaGFzT3duUHJvcGVydHkoXCJ1bmhvb2tcIikpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9LCB7fV0sIDI3OiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge1xuICAgICAgICAgICAgdmFyIHZlcnNpb24gPSByZXF1aXJlKFwiLi92ZXJzaW9uXCIpO1xuXG4gICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IGlzVmlydHVhbE5vZGU7XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIGlzVmlydHVhbE5vZGUoeCkge1xuICAgICAgICAgICAgICAgIHJldHVybiB4ICYmIHgudHlwZSA9PT0gXCJWaXJ0dWFsTm9kZVwiICYmIHgudmVyc2lvbiA9PT0gdmVyc2lvbjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSwgeyBcIi4vdmVyc2lvblwiOiAzMCB9XSwgMjg6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICB2YXIgdmVyc2lvbiA9IHJlcXVpcmUoXCIuL3ZlcnNpb25cIik7XG5cbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gaXNWaXJ0dWFsVGV4dDtcblxuICAgICAgICAgICAgZnVuY3Rpb24gaXNWaXJ0dWFsVGV4dCh4KSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHggJiYgeC50eXBlID09PSBcIlZpcnR1YWxUZXh0XCIgJiYgeC52ZXJzaW9uID09PSB2ZXJzaW9uO1xuICAgICAgICAgICAgfVxuICAgICAgICB9LCB7IFwiLi92ZXJzaW9uXCI6IDMwIH1dLCAyOTogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHtcbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gaXNXaWRnZXQ7XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIGlzV2lkZ2V0KHcpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gdyAmJiB3LnR5cGUgPT09IFwiV2lkZ2V0XCI7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0sIHt9XSwgMzA6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IFwiMlwiO1xuICAgICAgICB9LCB7fV0sIDMxOiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge1xuICAgICAgICAgICAgdmFyIHZlcnNpb24gPSByZXF1aXJlKFwiLi92ZXJzaW9uXCIpO1xuICAgICAgICAgICAgdmFyIGlzVk5vZGUgPSByZXF1aXJlKFwiLi9pcy12bm9kZVwiKTtcbiAgICAgICAgICAgIHZhciBpc1dpZGdldCA9IHJlcXVpcmUoXCIuL2lzLXdpZGdldFwiKTtcbiAgICAgICAgICAgIHZhciBpc1RodW5rID0gcmVxdWlyZShcIi4vaXMtdGh1bmtcIik7XG4gICAgICAgICAgICB2YXIgaXNWSG9vayA9IHJlcXVpcmUoXCIuL2lzLXZob29rXCIpO1xuXG4gICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IFZpcnR1YWxOb2RlO1xuXG4gICAgICAgICAgICB2YXIgbm9Qcm9wZXJ0aWVzID0ge307XG4gICAgICAgICAgICB2YXIgbm9DaGlsZHJlbiA9IFtdO1xuXG4gICAgICAgICAgICBmdW5jdGlvbiBWaXJ0dWFsTm9kZSh0YWdOYW1lLCBwcm9wZXJ0aWVzLCBjaGlsZHJlbiwga2V5LCBuYW1lc3BhY2UpIHtcbiAgICAgICAgICAgICAgICB0aGlzLnRhZ05hbWUgPSB0YWdOYW1lO1xuICAgICAgICAgICAgICAgIHRoaXMucHJvcGVydGllcyA9IHByb3BlcnRpZXMgfHwgbm9Qcm9wZXJ0aWVzO1xuICAgICAgICAgICAgICAgIHRoaXMuY2hpbGRyZW4gPSBjaGlsZHJlbiB8fCBub0NoaWxkcmVuO1xuICAgICAgICAgICAgICAgIHRoaXMua2V5ID0ga2V5ICE9IG51bGwgPyBTdHJpbmcoa2V5KSA6IHVuZGVmaW5lZDtcbiAgICAgICAgICAgICAgICB0aGlzLm5hbWVzcGFjZSA9IHR5cGVvZiBuYW1lc3BhY2UgPT09IFwic3RyaW5nXCIgPyBuYW1lc3BhY2UgOiBudWxsO1xuXG4gICAgICAgICAgICAgICAgdmFyIGNvdW50ID0gY2hpbGRyZW4gJiYgY2hpbGRyZW4ubGVuZ3RoIHx8IDA7XG4gICAgICAgICAgICAgICAgdmFyIGRlc2NlbmRhbnRzID0gMDtcbiAgICAgICAgICAgICAgICB2YXIgaGFzV2lkZ2V0cyA9IGZhbHNlO1xuICAgICAgICAgICAgICAgIHZhciBoYXNUaHVua3MgPSBmYWxzZTtcbiAgICAgICAgICAgICAgICB2YXIgZGVzY2VuZGFudEhvb2tzID0gZmFsc2U7XG4gICAgICAgICAgICAgICAgdmFyIGhvb2tzO1xuXG4gICAgICAgICAgICAgICAgZm9yICh2YXIgcHJvcE5hbWUgaW4gcHJvcGVydGllcykge1xuICAgICAgICAgICAgICAgICAgICBpZiAocHJvcGVydGllcy5oYXNPd25Qcm9wZXJ0eShwcm9wTmFtZSkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHZhciBwcm9wZXJ0eSA9IHByb3BlcnRpZXNbcHJvcE5hbWVdO1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGlzVkhvb2socHJvcGVydHkpICYmIHByb3BlcnR5LnVuaG9vaykge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmICghaG9va3MpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaG9va3MgPSB7fTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBob29rc1twcm9wTmFtZV0gPSBwcm9wZXJ0eTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgY291bnQ7IGkrKykge1xuICAgICAgICAgICAgICAgICAgICB2YXIgY2hpbGQgPSBjaGlsZHJlbltpXTtcbiAgICAgICAgICAgICAgICAgICAgaWYgKGlzVk5vZGUoY2hpbGQpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBkZXNjZW5kYW50cyArPSBjaGlsZC5jb3VudCB8fCAwO1xuXG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoIWhhc1dpZGdldHMgJiYgY2hpbGQuaGFzV2lkZ2V0cykge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGhhc1dpZGdldHMgPSB0cnVlO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoIWhhc1RodW5rcyAmJiBjaGlsZC5oYXNUaHVua3MpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBoYXNUaHVua3MgPSB0cnVlO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoIWRlc2NlbmRhbnRIb29rcyAmJiAoY2hpbGQuaG9va3MgfHwgY2hpbGQuZGVzY2VuZGFudEhvb2tzKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRlc2NlbmRhbnRIb29rcyA9IHRydWU7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoIWhhc1dpZGdldHMgJiYgaXNXaWRnZXQoY2hpbGQpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAodHlwZW9mIGNoaWxkLmRlc3Ryb3kgPT09IFwiZnVuY3Rpb25cIikge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGhhc1dpZGdldHMgPSB0cnVlO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKCFoYXNUaHVua3MgJiYgaXNUaHVuayhjaGlsZCkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGhhc1RodW5rcyA9IHRydWU7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICB0aGlzLmNvdW50ID0gY291bnQgKyBkZXNjZW5kYW50cztcbiAgICAgICAgICAgICAgICB0aGlzLmhhc1dpZGdldHMgPSBoYXNXaWRnZXRzO1xuICAgICAgICAgICAgICAgIHRoaXMuaGFzVGh1bmtzID0gaGFzVGh1bmtzO1xuICAgICAgICAgICAgICAgIHRoaXMuaG9va3MgPSBob29rcztcbiAgICAgICAgICAgICAgICB0aGlzLmRlc2NlbmRhbnRIb29rcyA9IGRlc2NlbmRhbnRIb29rcztcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgVmlydHVhbE5vZGUucHJvdG90eXBlLnZlcnNpb24gPSB2ZXJzaW9uO1xuICAgICAgICAgICAgVmlydHVhbE5vZGUucHJvdG90eXBlLnR5cGUgPSBcIlZpcnR1YWxOb2RlXCI7XG4gICAgICAgIH0sIHsgXCIuL2lzLXRodW5rXCI6IDI1LCBcIi4vaXMtdmhvb2tcIjogMjYsIFwiLi9pcy12bm9kZVwiOiAyNywgXCIuL2lzLXdpZGdldFwiOiAyOSwgXCIuL3ZlcnNpb25cIjogMzAgfV0sIDMyOiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge1xuICAgICAgICAgICAgdmFyIHZlcnNpb24gPSByZXF1aXJlKFwiLi92ZXJzaW9uXCIpO1xuXG4gICAgICAgICAgICBWaXJ0dWFsUGF0Y2guTk9ORSA9IDA7XG4gICAgICAgICAgICBWaXJ0dWFsUGF0Y2guVlRFWFQgPSAxO1xuICAgICAgICAgICAgVmlydHVhbFBhdGNoLlZOT0RFID0gMjtcbiAgICAgICAgICAgIFZpcnR1YWxQYXRjaC5XSURHRVQgPSAzO1xuICAgICAgICAgICAgVmlydHVhbFBhdGNoLlBST1BTID0gNDtcbiAgICAgICAgICAgIFZpcnR1YWxQYXRjaC5PUkRFUiA9IDU7XG4gICAgICAgICAgICBWaXJ0dWFsUGF0Y2guSU5TRVJUID0gNjtcbiAgICAgICAgICAgIFZpcnR1YWxQYXRjaC5SRU1PVkUgPSA3O1xuICAgICAgICAgICAgVmlydHVhbFBhdGNoLlRIVU5LID0gODtcblxuICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBWaXJ0dWFsUGF0Y2g7XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIFZpcnR1YWxQYXRjaCh0eXBlLCB2Tm9kZSwgcGF0Y2gpIHtcbiAgICAgICAgICAgICAgICB0aGlzLnR5cGUgPSBOdW1iZXIodHlwZSk7XG4gICAgICAgICAgICAgICAgdGhpcy52Tm9kZSA9IHZOb2RlO1xuICAgICAgICAgICAgICAgIHRoaXMucGF0Y2ggPSBwYXRjaDtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgVmlydHVhbFBhdGNoLnByb3RvdHlwZS52ZXJzaW9uID0gdmVyc2lvbjtcbiAgICAgICAgICAgIFZpcnR1YWxQYXRjaC5wcm90b3R5cGUudHlwZSA9IFwiVmlydHVhbFBhdGNoXCI7XG4gICAgICAgIH0sIHsgXCIuL3ZlcnNpb25cIjogMzAgfV0sIDMzOiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge1xuICAgICAgICAgICAgdmFyIHZlcnNpb24gPSByZXF1aXJlKFwiLi92ZXJzaW9uXCIpO1xuXG4gICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IFZpcnR1YWxUZXh0O1xuXG4gICAgICAgICAgICBmdW5jdGlvbiBWaXJ0dWFsVGV4dCh0ZXh0KSB7XG4gICAgICAgICAgICAgICAgdGhpcy50ZXh0ID0gU3RyaW5nKHRleHQpO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBWaXJ0dWFsVGV4dC5wcm90b3R5cGUudmVyc2lvbiA9IHZlcnNpb247XG4gICAgICAgICAgICBWaXJ0dWFsVGV4dC5wcm90b3R5cGUudHlwZSA9IFwiVmlydHVhbFRleHRcIjtcbiAgICAgICAgfSwgeyBcIi4vdmVyc2lvblwiOiAzMCB9XSwgMzQ6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICB2YXIgaXNPYmplY3QgPSByZXF1aXJlKFwiaXMtb2JqZWN0XCIpO1xuICAgICAgICAgICAgdmFyIGlzSG9vayA9IHJlcXVpcmUoXCIuLi92bm9kZS9pcy12aG9va1wiKTtcblxuICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBkaWZmUHJvcHM7XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIGRpZmZQcm9wcyhhLCBiKSB7XG4gICAgICAgICAgICAgICAgdmFyIGRpZmY7XG5cbiAgICAgICAgICAgICAgICBmb3IgKHZhciBhS2V5IGluIGEpIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKCEoYUtleSBpbiBiKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgZGlmZiA9IGRpZmYgfHwge307XG4gICAgICAgICAgICAgICAgICAgICAgICBkaWZmW2FLZXldID0gdW5kZWZpbmVkO1xuICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgdmFyIGFWYWx1ZSA9IGFbYUtleV07XG4gICAgICAgICAgICAgICAgICAgIHZhciBiVmFsdWUgPSBiW2FLZXldO1xuXG4gICAgICAgICAgICAgICAgICAgIGlmIChhVmFsdWUgPT09IGJWYWx1ZSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgY29udGludWU7XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoaXNPYmplY3QoYVZhbHVlKSAmJiBpc09iamVjdChiVmFsdWUpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoZ2V0UHJvdG90eXBlKGJWYWx1ZSkgIT09IGdldFByb3RvdHlwZShhVmFsdWUpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgZGlmZiA9IGRpZmYgfHwge307XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgZGlmZlthS2V5XSA9IGJWYWx1ZTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoaXNIb29rKGJWYWx1ZSkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBkaWZmID0gZGlmZiB8fCB7fTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBkaWZmW2FLZXldID0gYlZhbHVlO1xuICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB2YXIgb2JqZWN0RGlmZiA9IGRpZmZQcm9wcyhhVmFsdWUsIGJWYWx1ZSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKG9iamVjdERpZmYpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZGlmZiA9IGRpZmYgfHwge307XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRpZmZbYUtleV0gPSBvYmplY3REaWZmO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGRpZmYgPSBkaWZmIHx8IHt9O1xuICAgICAgICAgICAgICAgICAgICAgICAgZGlmZlthS2V5XSA9IGJWYWx1ZTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIGZvciAodmFyIGJLZXkgaW4gYikge1xuICAgICAgICAgICAgICAgICAgICBpZiAoIShiS2V5IGluIGEpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBkaWZmID0gZGlmZiB8fCB7fTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGRpZmZbYktleV0gPSBiW2JLZXldO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgcmV0dXJuIGRpZmY7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIGdldFByb3RvdHlwZSh2YWx1ZSkge1xuICAgICAgICAgICAgICAgIGlmIChPYmplY3QuZ2V0UHJvdG90eXBlT2YpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIE9iamVjdC5nZXRQcm90b3R5cGVPZih2YWx1ZSk7XG4gICAgICAgICAgICAgICAgfSBlbHNlIGlmICh2YWx1ZS5fX3Byb3RvX18pIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHZhbHVlLl9fcHJvdG9fXztcbiAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKHZhbHVlLmNvbnN0cnVjdG9yKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiB2YWx1ZS5jb25zdHJ1Y3Rvci5wcm90b3R5cGU7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9LCB7IFwiLi4vdm5vZGUvaXMtdmhvb2tcIjogMjYsIFwiaXMtb2JqZWN0XCI6IDExIH1dLCAzNTogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHtcbiAgICAgICAgICAgIHZhciBpc0FycmF5ID0gcmVxdWlyZShcIngtaXMtYXJyYXlcIik7XG5cbiAgICAgICAgICAgIHZhciBWUGF0Y2ggPSByZXF1aXJlKFwiLi4vdm5vZGUvdnBhdGNoXCIpO1xuICAgICAgICAgICAgdmFyIGlzVk5vZGUgPSByZXF1aXJlKFwiLi4vdm5vZGUvaXMtdm5vZGVcIik7XG4gICAgICAgICAgICB2YXIgaXNWVGV4dCA9IHJlcXVpcmUoXCIuLi92bm9kZS9pcy12dGV4dFwiKTtcbiAgICAgICAgICAgIHZhciBpc1dpZGdldCA9IHJlcXVpcmUoXCIuLi92bm9kZS9pcy13aWRnZXRcIik7XG4gICAgICAgICAgICB2YXIgaXNUaHVuayA9IHJlcXVpcmUoXCIuLi92bm9kZS9pcy10aHVua1wiKTtcbiAgICAgICAgICAgIHZhciBoYW5kbGVUaHVuayA9IHJlcXVpcmUoXCIuLi92bm9kZS9oYW5kbGUtdGh1bmtcIik7XG5cbiAgICAgICAgICAgIHZhciBkaWZmUHJvcHMgPSByZXF1aXJlKFwiLi9kaWZmLXByb3BzXCIpO1xuXG4gICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IGRpZmY7XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIGRpZmYoYSwgYikge1xuICAgICAgICAgICAgICAgIHZhciBwYXRjaCA9IHsgYTogYSB9O1xuICAgICAgICAgICAgICAgIHdhbGsoYSwgYiwgcGF0Y2gsIDApO1xuICAgICAgICAgICAgICAgIHJldHVybiBwYXRjaDtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZnVuY3Rpb24gd2FsayhhLCBiLCBwYXRjaCwgaW5kZXgpIHtcbiAgICAgICAgICAgICAgICBpZiAoYSA9PT0gYikge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgdmFyIGFwcGx5ID0gcGF0Y2hbaW5kZXhdO1xuICAgICAgICAgICAgICAgIHZhciBhcHBseUNsZWFyID0gZmFsc2U7XG5cbiAgICAgICAgICAgICAgICBpZiAoaXNUaHVuayhhKSB8fCBpc1RodW5rKGIpKSB7XG4gICAgICAgICAgICAgICAgICAgIHRodW5rcyhhLCBiLCBwYXRjaCwgaW5kZXgpO1xuICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoYiA9PSBudWxsKSB7XG5cbiAgICAgICAgICAgICAgICAgICAgLy8gSWYgYSBpcyBhIHdpZGdldCB3ZSB3aWxsIGFkZCBhIHJlbW92ZSBwYXRjaCBmb3IgaXRcbiAgICAgICAgICAgICAgICAgICAgLy8gT3RoZXJ3aXNlIGFueSBjaGlsZCB3aWRnZXRzL2hvb2tzIG11c3QgYmUgZGVzdHJveWVkLlxuICAgICAgICAgICAgICAgICAgICAvLyBUaGlzIHByZXZlbnRzIGFkZGluZyB0d28gcmVtb3ZlIHBhdGNoZXMgZm9yIGEgd2lkZ2V0LlxuICAgICAgICAgICAgICAgICAgICBpZiAoIWlzV2lkZ2V0KGEpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBjbGVhclN0YXRlKGEsIHBhdGNoLCBpbmRleCk7XG4gICAgICAgICAgICAgICAgICAgICAgICBhcHBseSA9IHBhdGNoW2luZGV4XTtcbiAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgIGFwcGx5ID0gYXBwZW5kUGF0Y2goYXBwbHksIG5ldyBWUGF0Y2goVlBhdGNoLlJFTU9WRSwgYSwgYikpO1xuICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoaXNWTm9kZShiKSkge1xuICAgICAgICAgICAgICAgICAgICBpZiAoaXNWTm9kZShhKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGEudGFnTmFtZSA9PT0gYi50YWdOYW1lICYmIGEubmFtZXNwYWNlID09PSBiLm5hbWVzcGFjZSAmJiBhLmtleSA9PT0gYi5rZXkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB2YXIgcHJvcHNQYXRjaCA9IGRpZmZQcm9wcyhhLnByb3BlcnRpZXMsIGIucHJvcGVydGllcyk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHByb3BzUGF0Y2gpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYXBwbHkgPSBhcHBlbmRQYXRjaChhcHBseSwgbmV3IFZQYXRjaChWUGF0Y2guUFJPUFMsIGEsIHByb3BzUGF0Y2gpKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgYXBwbHkgPSBkaWZmQ2hpbGRyZW4oYSwgYiwgcGF0Y2gsIGFwcGx5LCBpbmRleCk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGFwcGx5ID0gYXBwZW5kUGF0Y2goYXBwbHksIG5ldyBWUGF0Y2goVlBhdGNoLlZOT0RFLCBhLCBiKSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgYXBwbHlDbGVhciA9IHRydWU7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBhcHBseSA9IGFwcGVuZFBhdGNoKGFwcGx5LCBuZXcgVlBhdGNoKFZQYXRjaC5WTk9ERSwgYSwgYikpO1xuICAgICAgICAgICAgICAgICAgICAgICAgYXBwbHlDbGVhciA9IHRydWU7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKGlzVlRleHQoYikpIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKCFpc1ZUZXh0KGEpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBhcHBseSA9IGFwcGVuZFBhdGNoKGFwcGx5LCBuZXcgVlBhdGNoKFZQYXRjaC5WVEVYVCwgYSwgYikpO1xuICAgICAgICAgICAgICAgICAgICAgICAgYXBwbHlDbGVhciA9IHRydWU7XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoYS50ZXh0ICE9PSBiLnRleHQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGFwcGx5ID0gYXBwZW5kUGF0Y2goYXBwbHksIG5ldyBWUGF0Y2goVlBhdGNoLlZURVhULCBhLCBiKSk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKGlzV2lkZ2V0KGIpKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmICghaXNXaWRnZXQoYSkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGFwcGx5Q2xlYXIgPSB0cnVlO1xuICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgYXBwbHkgPSBhcHBlbmRQYXRjaChhcHBseSwgbmV3IFZQYXRjaChWUGF0Y2guV0lER0VULCBhLCBiKSk7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgaWYgKGFwcGx5KSB7XG4gICAgICAgICAgICAgICAgICAgIHBhdGNoW2luZGV4XSA9IGFwcGx5O1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIGlmIChhcHBseUNsZWFyKSB7XG4gICAgICAgICAgICAgICAgICAgIGNsZWFyU3RhdGUoYSwgcGF0Y2gsIGluZGV4KTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIGRpZmZDaGlsZHJlbihhLCBiLCBwYXRjaCwgYXBwbHksIGluZGV4KSB7XG4gICAgICAgICAgICAgICAgdmFyIGFDaGlsZHJlbiA9IGEuY2hpbGRyZW47XG4gICAgICAgICAgICAgICAgdmFyIG9yZGVyZWRTZXQgPSByZW9yZGVyKGFDaGlsZHJlbiwgYi5jaGlsZHJlbik7XG4gICAgICAgICAgICAgICAgdmFyIGJDaGlsZHJlbiA9IG9yZGVyZWRTZXQuY2hpbGRyZW47XG5cbiAgICAgICAgICAgICAgICB2YXIgYUxlbiA9IGFDaGlsZHJlbi5sZW5ndGg7XG4gICAgICAgICAgICAgICAgdmFyIGJMZW4gPSBiQ2hpbGRyZW4ubGVuZ3RoO1xuICAgICAgICAgICAgICAgIHZhciBsZW4gPSBhTGVuID4gYkxlbiA/IGFMZW4gOiBiTGVuO1xuXG4gICAgICAgICAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCBsZW47IGkrKykge1xuICAgICAgICAgICAgICAgICAgICB2YXIgbGVmdE5vZGUgPSBhQ2hpbGRyZW5baV07XG4gICAgICAgICAgICAgICAgICAgIHZhciByaWdodE5vZGUgPSBiQ2hpbGRyZW5baV07XG4gICAgICAgICAgICAgICAgICAgIGluZGV4ICs9IDE7XG5cbiAgICAgICAgICAgICAgICAgICAgaWYgKCFsZWZ0Tm9kZSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHJpZ2h0Tm9kZSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIEV4Y2VzcyBub2RlcyBpbiBiIG5lZWQgdG8gYmUgYWRkZWRcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBhcHBseSA9IGFwcGVuZFBhdGNoKGFwcGx5LCBuZXcgVlBhdGNoKFZQYXRjaC5JTlNFUlQsIG51bGwsIHJpZ2h0Tm9kZSkpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgd2FsayhsZWZ0Tm9kZSwgcmlnaHROb2RlLCBwYXRjaCwgaW5kZXgpO1xuICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgaWYgKGlzVk5vZGUobGVmdE5vZGUpICYmIGxlZnROb2RlLmNvdW50KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBpbmRleCArPSBsZWZ0Tm9kZS5jb3VudDtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIGlmIChvcmRlcmVkU2V0Lm1vdmVzKSB7XG4gICAgICAgICAgICAgICAgICAgIC8vIFJlb3JkZXIgbm9kZXMgbGFzdFxuICAgICAgICAgICAgICAgICAgICBhcHBseSA9IGFwcGVuZFBhdGNoKGFwcGx5LCBuZXcgVlBhdGNoKFZQYXRjaC5PUkRFUiwgYSwgb3JkZXJlZFNldC5tb3ZlcykpO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHJldHVybiBhcHBseTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZnVuY3Rpb24gY2xlYXJTdGF0ZSh2Tm9kZSwgcGF0Y2gsIGluZGV4KSB7XG4gICAgICAgICAgICAgICAgLy8gVE9ETzogTWFrZSB0aGlzIGEgc2luZ2xlIHdhbGssIG5vdCB0d29cbiAgICAgICAgICAgICAgICB1bmhvb2sodk5vZGUsIHBhdGNoLCBpbmRleCk7XG4gICAgICAgICAgICAgICAgZGVzdHJveVdpZGdldHModk5vZGUsIHBhdGNoLCBpbmRleCk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIC8vIFBhdGNoIHJlY29yZHMgZm9yIGFsbCBkZXN0cm95ZWQgd2lkZ2V0cyBtdXN0IGJlIGFkZGVkIGJlY2F1c2Ugd2UgbmVlZFxuICAgICAgICAgICAgLy8gYSBET00gbm9kZSByZWZlcmVuY2UgZm9yIHRoZSBkZXN0cm95IGZ1bmN0aW9uXG4gICAgICAgICAgICBmdW5jdGlvbiBkZXN0cm95V2lkZ2V0cyh2Tm9kZSwgcGF0Y2gsIGluZGV4KSB7XG4gICAgICAgICAgICAgICAgaWYgKGlzV2lkZ2V0KHZOb2RlKSkge1xuICAgICAgICAgICAgICAgICAgICBpZiAodHlwZW9mIHZOb2RlLmRlc3Ryb3kgPT09IFwiZnVuY3Rpb25cIikge1xuICAgICAgICAgICAgICAgICAgICAgICAgcGF0Y2hbaW5kZXhdID0gYXBwZW5kUGF0Y2gocGF0Y2hbaW5kZXhdLCBuZXcgVlBhdGNoKFZQYXRjaC5SRU1PVkUsIHZOb2RlLCBudWxsKSk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKGlzVk5vZGUodk5vZGUpICYmICh2Tm9kZS5oYXNXaWRnZXRzIHx8IHZOb2RlLmhhc1RodW5rcykpIHtcbiAgICAgICAgICAgICAgICAgICAgdmFyIGNoaWxkcmVuID0gdk5vZGUuY2hpbGRyZW47XG4gICAgICAgICAgICAgICAgICAgIHZhciBsZW4gPSBjaGlsZHJlbi5sZW5ndGg7XG4gICAgICAgICAgICAgICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgbGVuOyBpKyspIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHZhciBjaGlsZCA9IGNoaWxkcmVuW2ldO1xuICAgICAgICAgICAgICAgICAgICAgICAgaW5kZXggKz0gMTtcblxuICAgICAgICAgICAgICAgICAgICAgICAgZGVzdHJveVdpZGdldHMoY2hpbGQsIHBhdGNoLCBpbmRleCk7XG5cbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChpc1ZOb2RlKGNoaWxkKSAmJiBjaGlsZC5jb3VudCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGluZGV4ICs9IGNoaWxkLmNvdW50O1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfSBlbHNlIGlmIChpc1RodW5rKHZOb2RlKSkge1xuICAgICAgICAgICAgICAgICAgICB0aHVua3Modk5vZGUsIG51bGwsIHBhdGNoLCBpbmRleCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAvLyBDcmVhdGUgYSBzdWItcGF0Y2ggZm9yIHRodW5rc1xuICAgICAgICAgICAgZnVuY3Rpb24gdGh1bmtzKGEsIGIsIHBhdGNoLCBpbmRleCkge1xuICAgICAgICAgICAgICAgIHZhciBub2RlcyA9IGhhbmRsZVRodW5rKGEsIGIpO1xuICAgICAgICAgICAgICAgIHZhciB0aHVua1BhdGNoID0gZGlmZihub2Rlcy5hLCBub2Rlcy5iKTtcbiAgICAgICAgICAgICAgICBpZiAoaGFzUGF0Y2hlcyh0aHVua1BhdGNoKSkge1xuICAgICAgICAgICAgICAgICAgICBwYXRjaFtpbmRleF0gPSBuZXcgVlBhdGNoKFZQYXRjaC5USFVOSywgbnVsbCwgdGh1bmtQYXRjaCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBmdW5jdGlvbiBoYXNQYXRjaGVzKHBhdGNoKSB7XG4gICAgICAgICAgICAgICAgZm9yICh2YXIgaW5kZXggaW4gcGF0Y2gpIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKGluZGV4ICE9PSBcImFcIikge1xuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIC8vIEV4ZWN1dGUgaG9va3Mgd2hlbiB0d28gbm9kZXMgYXJlIGlkZW50aWNhbFxuICAgICAgICAgICAgZnVuY3Rpb24gdW5ob29rKHZOb2RlLCBwYXRjaCwgaW5kZXgpIHtcbiAgICAgICAgICAgICAgICBpZiAoaXNWTm9kZSh2Tm9kZSkpIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKHZOb2RlLmhvb2tzKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBwYXRjaFtpbmRleF0gPSBhcHBlbmRQYXRjaChwYXRjaFtpbmRleF0sIG5ldyBWUGF0Y2goVlBhdGNoLlBST1BTLCB2Tm9kZSwgdW5kZWZpbmVkS2V5cyh2Tm9kZS5ob29rcykpKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgIGlmICh2Tm9kZS5kZXNjZW5kYW50SG9va3MgfHwgdk5vZGUuaGFzVGh1bmtzKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICB2YXIgY2hpbGRyZW4gPSB2Tm9kZS5jaGlsZHJlbjtcbiAgICAgICAgICAgICAgICAgICAgICAgIHZhciBsZW4gPSBjaGlsZHJlbi5sZW5ndGg7XG4gICAgICAgICAgICAgICAgICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IGxlbjsgaSsrKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdmFyIGNoaWxkID0gY2hpbGRyZW5baV07XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaW5kZXggKz0gMTtcblxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHVuaG9vayhjaGlsZCwgcGF0Y2gsIGluZGV4KTtcblxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChpc1ZOb2RlKGNoaWxkKSAmJiBjaGlsZC5jb3VudCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpbmRleCArPSBjaGlsZC5jb3VudDtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKGlzVGh1bmsodk5vZGUpKSB7XG4gICAgICAgICAgICAgICAgICAgIHRodW5rcyh2Tm9kZSwgbnVsbCwgcGF0Y2gsIGluZGV4KTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIHVuZGVmaW5lZEtleXMob2JqKSB7XG4gICAgICAgICAgICAgICAgdmFyIHJlc3VsdCA9IHt9O1xuXG4gICAgICAgICAgICAgICAgZm9yICh2YXIga2V5IGluIG9iaikge1xuICAgICAgICAgICAgICAgICAgICByZXN1bHRba2V5XSA9IHVuZGVmaW5lZDtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICByZXR1cm4gcmVzdWx0O1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAvLyBMaXN0IGRpZmYsIG5haXZlIGxlZnQgdG8gcmlnaHQgcmVvcmRlcmluZ1xuICAgICAgICAgICAgZnVuY3Rpb24gcmVvcmRlcihhQ2hpbGRyZW4sIGJDaGlsZHJlbikge1xuICAgICAgICAgICAgICAgIC8vIE8oTSkgdGltZSwgTyhNKSBtZW1vcnlcbiAgICAgICAgICAgICAgICB2YXIgYkNoaWxkSW5kZXggPSBrZXlJbmRleChiQ2hpbGRyZW4pO1xuICAgICAgICAgICAgICAgIHZhciBiS2V5cyA9IGJDaGlsZEluZGV4LmtleXM7XG4gICAgICAgICAgICAgICAgdmFyIGJGcmVlID0gYkNoaWxkSW5kZXguZnJlZTtcblxuICAgICAgICAgICAgICAgIGlmIChiRnJlZS5sZW5ndGggPT09IGJDaGlsZHJlbi5sZW5ndGgpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGNoaWxkcmVuOiBiQ2hpbGRyZW4sXG4gICAgICAgICAgICAgICAgICAgICAgICBtb3ZlczogbnVsbFxuICAgICAgICAgICAgICAgICAgICB9O1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIC8vIE8oTikgdGltZSwgTyhOKSBtZW1vcnlcbiAgICAgICAgICAgICAgICB2YXIgYUNoaWxkSW5kZXggPSBrZXlJbmRleChhQ2hpbGRyZW4pO1xuICAgICAgICAgICAgICAgIHZhciBhS2V5cyA9IGFDaGlsZEluZGV4LmtleXM7XG4gICAgICAgICAgICAgICAgdmFyIGFGcmVlID0gYUNoaWxkSW5kZXguZnJlZTtcblxuICAgICAgICAgICAgICAgIGlmIChhRnJlZS5sZW5ndGggPT09IGFDaGlsZHJlbi5sZW5ndGgpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGNoaWxkcmVuOiBiQ2hpbGRyZW4sXG4gICAgICAgICAgICAgICAgICAgICAgICBtb3ZlczogbnVsbFxuICAgICAgICAgICAgICAgICAgICB9O1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIC8vIE8oTUFYKE4sIE0pKSBtZW1vcnlcbiAgICAgICAgICAgICAgICB2YXIgbmV3Q2hpbGRyZW4gPSBbXTtcblxuICAgICAgICAgICAgICAgIHZhciBmcmVlSW5kZXggPSAwO1xuICAgICAgICAgICAgICAgIHZhciBmcmVlQ291bnQgPSBiRnJlZS5sZW5ndGg7XG4gICAgICAgICAgICAgICAgdmFyIGRlbGV0ZWRJdGVtcyA9IDA7XG5cbiAgICAgICAgICAgICAgICAvLyBJdGVyYXRlIHRocm91Z2ggYSBhbmQgbWF0Y2ggYSBub2RlIGluIGJcbiAgICAgICAgICAgICAgICAvLyBPKE4pIHRpbWUsXG4gICAgICAgICAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCBhQ2hpbGRyZW4ubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgICAgICAgICAgdmFyIGFJdGVtID0gYUNoaWxkcmVuW2ldO1xuICAgICAgICAgICAgICAgICAgICB2YXIgaXRlbUluZGV4O1xuXG4gICAgICAgICAgICAgICAgICAgIGlmIChhSXRlbS5rZXkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChiS2V5cy5oYXNPd25Qcm9wZXJ0eShhSXRlbS5rZXkpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gTWF0Y2ggdXAgdGhlIG9sZCBrZXlzXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaXRlbUluZGV4ID0gYktleXNbYUl0ZW0ua2V5XTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBuZXdDaGlsZHJlbi5wdXNoKGJDaGlsZHJlbltpdGVtSW5kZXhdKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gUmVtb3ZlIG9sZCBrZXllZCBpdGVtc1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGl0ZW1JbmRleCA9IGkgLSBkZWxldGVkSXRlbXMrKztcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBuZXdDaGlsZHJlbi5wdXNoKG51bGwpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgLy8gTWF0Y2ggdGhlIGl0ZW0gaW4gYSB3aXRoIHRoZSBuZXh0IGZyZWUgaXRlbSBpbiBiXG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoZnJlZUluZGV4IDwgZnJlZUNvdW50KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaXRlbUluZGV4ID0gYkZyZWVbZnJlZUluZGV4KytdO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIG5ld0NoaWxkcmVuLnB1c2goYkNoaWxkcmVuW2l0ZW1JbmRleF0pO1xuICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBUaGVyZSBhcmUgbm8gZnJlZSBpdGVtcyBpbiBiIHRvIG1hdGNoIHdpdGhcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyB0aGUgZnJlZSBpdGVtcyBpbiBhLCBzbyB0aGUgZXh0cmEgZnJlZSBub2Rlc1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIGFyZSBkZWxldGVkLlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGl0ZW1JbmRleCA9IGkgLSBkZWxldGVkSXRlbXMrKztcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBuZXdDaGlsZHJlbi5wdXNoKG51bGwpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgdmFyIGxhc3RGcmVlSW5kZXggPSBmcmVlSW5kZXggPj0gYkZyZWUubGVuZ3RoID8gYkNoaWxkcmVuLmxlbmd0aCA6IGJGcmVlW2ZyZWVJbmRleF07XG5cbiAgICAgICAgICAgICAgICAvLyBJdGVyYXRlIHRocm91Z2ggYiBhbmQgYXBwZW5kIGFueSBuZXcga2V5c1xuICAgICAgICAgICAgICAgIC8vIE8oTSkgdGltZVxuICAgICAgICAgICAgICAgIGZvciAodmFyIGogPSAwOyBqIDwgYkNoaWxkcmVuLmxlbmd0aDsgaisrKSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciBuZXdJdGVtID0gYkNoaWxkcmVuW2pdO1xuXG4gICAgICAgICAgICAgICAgICAgIGlmIChuZXdJdGVtLmtleSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKCFhS2V5cy5oYXNPd25Qcm9wZXJ0eShuZXdJdGVtLmtleSkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBBZGQgYW55IG5ldyBrZXllZCBpdGVtc1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIFdlIGFyZSBhZGRpbmcgbmV3IGl0ZW1zIHRvIHRoZSBlbmQgYW5kIHRoZW4gc29ydGluZyB0aGVtXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gaW4gcGxhY2UuIEluIGZ1dHVyZSB3ZSBzaG91bGQgaW5zZXJ0IG5ldyBpdGVtcyBpbiBwbGFjZS5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBuZXdDaGlsZHJlbi5wdXNoKG5ld0l0ZW0pO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKGogPj0gbGFzdEZyZWVJbmRleCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgLy8gQWRkIGFueSBsZWZ0b3ZlciBub24ta2V5ZWQgaXRlbXNcbiAgICAgICAgICAgICAgICAgICAgICAgIG5ld0NoaWxkcmVuLnB1c2gobmV3SXRlbSk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICB2YXIgc2ltdWxhdGUgPSBuZXdDaGlsZHJlbi5zbGljZSgpO1xuICAgICAgICAgICAgICAgIHZhciBzaW11bGF0ZUluZGV4ID0gMDtcbiAgICAgICAgICAgICAgICB2YXIgcmVtb3ZlcyA9IFtdO1xuICAgICAgICAgICAgICAgIHZhciBpbnNlcnRzID0gW107XG4gICAgICAgICAgICAgICAgdmFyIHNpbXVsYXRlSXRlbTtcblxuICAgICAgICAgICAgICAgIGZvciAodmFyIGsgPSAwOyBrIDwgYkNoaWxkcmVuLmxlbmd0aDspIHtcbiAgICAgICAgICAgICAgICAgICAgdmFyIHdhbnRlZEl0ZW0gPSBiQ2hpbGRyZW5ba107XG4gICAgICAgICAgICAgICAgICAgIHNpbXVsYXRlSXRlbSA9IHNpbXVsYXRlW3NpbXVsYXRlSW5kZXhdO1xuXG4gICAgICAgICAgICAgICAgICAgIC8vIHJlbW92ZSBpdGVtc1xuICAgICAgICAgICAgICAgICAgICB3aGlsZSAoc2ltdWxhdGVJdGVtID09PSBudWxsICYmIHNpbXVsYXRlLmxlbmd0aCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgcmVtb3Zlcy5wdXNoKHJlbW92ZShzaW11bGF0ZSwgc2ltdWxhdGVJbmRleCwgbnVsbCkpO1xuICAgICAgICAgICAgICAgICAgICAgICAgc2ltdWxhdGVJdGVtID0gc2ltdWxhdGVbc2ltdWxhdGVJbmRleF07XG4gICAgICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgICAgICBpZiAoIXNpbXVsYXRlSXRlbSB8fCBzaW11bGF0ZUl0ZW0ua2V5ICE9PSB3YW50ZWRJdGVtLmtleSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgLy8gaWYgd2UgbmVlZCBhIGtleSBpbiB0aGlzIHBvc2l0aW9uLi4uXG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAod2FudGVkSXRlbS5rZXkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoc2ltdWxhdGVJdGVtICYmIHNpbXVsYXRlSXRlbS5rZXkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gaWYgYW4gaW5zZXJ0IGRvZXNuJ3QgcHV0IHRoaXMga2V5IGluIHBsYWNlLCBpdCBuZWVkcyB0byBtb3ZlXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChiS2V5c1tzaW11bGF0ZUl0ZW0ua2V5XSAhPT0gayArIDEpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlbW92ZXMucHVzaChyZW1vdmUoc2ltdWxhdGUsIHNpbXVsYXRlSW5kZXgsIHNpbXVsYXRlSXRlbS5rZXkpKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNpbXVsYXRlSXRlbSA9IHNpbXVsYXRlW3NpbXVsYXRlSW5kZXhdO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gaWYgdGhlIHJlbW92ZSBkaWRuJ3QgcHV0IHRoZSB3YW50ZWQgaXRlbSBpbiBwbGFjZSwgd2UgbmVlZCB0byBpbnNlcnQgaXRcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmICghc2ltdWxhdGVJdGVtIHx8IHNpbXVsYXRlSXRlbS5rZXkgIT09IHdhbnRlZEl0ZW0ua2V5KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaW5zZXJ0cy5wdXNoKHsga2V5OiB3YW50ZWRJdGVtLmtleSwgdG86IGsgfSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBpdGVtcyBhcmUgbWF0Y2hpbmcsIHNvIHNraXAgYWhlYWRcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNpbXVsYXRlSW5kZXgrKztcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGluc2VydHMucHVzaCh7IGtleTogd2FudGVkSXRlbS5rZXksIHRvOiBrIH0pO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaW5zZXJ0cy5wdXNoKHsga2V5OiB3YW50ZWRJdGVtLmtleSwgdG86IGsgfSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGsrKztcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIGEga2V5IGluIHNpbXVsYXRlIGhhcyBubyBtYXRjaGluZyB3YW50ZWQga2V5LCByZW1vdmUgaXRcbiAgICAgICAgICAgICAgICAgICAgICAgIGVsc2UgaWYgKHNpbXVsYXRlSXRlbSAmJiBzaW11bGF0ZUl0ZW0ua2V5KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcmVtb3Zlcy5wdXNoKHJlbW92ZShzaW11bGF0ZSwgc2ltdWxhdGVJbmRleCwgc2ltdWxhdGVJdGVtLmtleSkpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgc2ltdWxhdGVJbmRleCsrO1xuICAgICAgICAgICAgICAgICAgICAgICAgaysrO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgLy8gcmVtb3ZlIGFsbCB0aGUgcmVtYWluaW5nIG5vZGVzIGZyb20gc2ltdWxhdGVcbiAgICAgICAgICAgICAgICB3aGlsZSAoc2ltdWxhdGVJbmRleCA8IHNpbXVsYXRlLmxlbmd0aCkge1xuICAgICAgICAgICAgICAgICAgICBzaW11bGF0ZUl0ZW0gPSBzaW11bGF0ZVtzaW11bGF0ZUluZGV4XTtcbiAgICAgICAgICAgICAgICAgICAgcmVtb3Zlcy5wdXNoKHJlbW92ZShzaW11bGF0ZSwgc2ltdWxhdGVJbmRleCwgc2ltdWxhdGVJdGVtICYmIHNpbXVsYXRlSXRlbS5rZXkpKTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAvLyBJZiB0aGUgb25seSBtb3ZlcyB3ZSBoYXZlIGFyZSBkZWxldGVzIHRoZW4gd2UgY2FuIGp1c3RcbiAgICAgICAgICAgICAgICAvLyBsZXQgdGhlIGRlbGV0ZSBwYXRjaCByZW1vdmUgdGhlc2UgaXRlbXMuXG4gICAgICAgICAgICAgICAgaWYgKHJlbW92ZXMubGVuZ3RoID09PSBkZWxldGVkSXRlbXMgJiYgIWluc2VydHMubGVuZ3RoKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiB7XG4gICAgICAgICAgICAgICAgICAgICAgICBjaGlsZHJlbjogbmV3Q2hpbGRyZW4sXG4gICAgICAgICAgICAgICAgICAgICAgICBtb3ZlczogbnVsbFxuICAgICAgICAgICAgICAgICAgICB9O1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHJldHVybiB7XG4gICAgICAgICAgICAgICAgICAgIGNoaWxkcmVuOiBuZXdDaGlsZHJlbixcbiAgICAgICAgICAgICAgICAgICAgbW92ZXM6IHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJlbW92ZXM6IHJlbW92ZXMsXG4gICAgICAgICAgICAgICAgICAgICAgICBpbnNlcnRzOiBpbnNlcnRzXG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9O1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBmdW5jdGlvbiByZW1vdmUoYXJyLCBpbmRleCwga2V5KSB7XG4gICAgICAgICAgICAgICAgYXJyLnNwbGljZShpbmRleCwgMSk7XG5cbiAgICAgICAgICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgICAgICAgICBmcm9tOiBpbmRleCxcbiAgICAgICAgICAgICAgICAgICAga2V5OiBrZXlcbiAgICAgICAgICAgICAgICB9O1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBmdW5jdGlvbiBrZXlJbmRleChjaGlsZHJlbikge1xuICAgICAgICAgICAgICAgIHZhciBrZXlzID0ge307XG4gICAgICAgICAgICAgICAgdmFyIGZyZWUgPSBbXTtcbiAgICAgICAgICAgICAgICB2YXIgbGVuZ3RoID0gY2hpbGRyZW4ubGVuZ3RoO1xuXG4gICAgICAgICAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCBsZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgICAgICAgICB2YXIgY2hpbGQgPSBjaGlsZHJlbltpXTtcblxuICAgICAgICAgICAgICAgICAgICBpZiAoY2hpbGQua2V5KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBrZXlzW2NoaWxkLmtleV0gPSBpO1xuICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgZnJlZS5wdXNoKGkpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgICAgICAgICAga2V5czoga2V5cywgLy8gQSBoYXNoIG9mIGtleSBuYW1lIHRvIGluZGV4XG4gICAgICAgICAgICAgICAgICAgIGZyZWU6IGZyZWUgLy8gQW4gYXJyYXkgb2YgdW5rZXllZCBpdGVtIGluZGljZXNcbiAgICAgICAgICAgICAgICB9O1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBmdW5jdGlvbiBhcHBlbmRQYXRjaChhcHBseSwgcGF0Y2gpIHtcbiAgICAgICAgICAgICAgICBpZiAoYXBwbHkpIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKGlzQXJyYXkoYXBwbHkpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBhcHBseS5wdXNoKHBhdGNoKTtcbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGFwcGx5ID0gW2FwcGx5LCBwYXRjaF07XG4gICAgICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgICAgICByZXR1cm4gYXBwbHk7XG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHBhdGNoO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgfSwgeyBcIi4uL3Zub2RlL2hhbmRsZS10aHVua1wiOiAyNCwgXCIuLi92bm9kZS9pcy10aHVua1wiOiAyNSwgXCIuLi92bm9kZS9pcy12bm9kZVwiOiAyNywgXCIuLi92bm9kZS9pcy12dGV4dFwiOiAyOCwgXCIuLi92bm9kZS9pcy13aWRnZXRcIjogMjksIFwiLi4vdm5vZGUvdnBhdGNoXCI6IDMyLCBcIi4vZGlmZi1wcm9wc1wiOiAzNCwgXCJ4LWlzLWFycmF5XCI6IDEyIH1dIH0sIHt9LCBbNF0pKDQpO1xufSk7XG5cbmNvbnN0IENvcmUgPSBDO1xuXG5leHBvcnQgeyBDb3JlLCBrZXJuZWwgYXMgS2VybmVsLCBFbnVtLCBWaXJ0dWFsRE9NIH07Il0sImZpbGUiOiJFbGl4aXIuanMiLCJzb3VyY2VSb290IjoiL3NvdXJjZS8ifQ== \ No newline at end of file +export { Core, Enum, VirtualDOM }; +//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiIiwic291cmNlcyI6WyJFbGl4aXIuanMiXSwic291cmNlc0NvbnRlbnQiOlsiLyogQGZsb3cgKi9cblxuY2xhc3MgTWFpbGJveCB7XG5cbiAgY29uc3RydWN0b3IoKSB7XG4gICAgdGhpcy5tZXNzYWdlcyA9IFtdO1xuICB9XG5cbiAgZGVsaXZlcihtZXNzYWdlKSB7XG4gICAgdGhpcy5tZXNzYWdlcy5wdXNoKG1lc3NhZ2UpO1xuICAgIHJldHVybiBtZXNzYWdlO1xuICB9XG5cbiAgZ2V0KCkge1xuICAgIHJldHVybiB0aGlzLm1lc3NhZ2VzO1xuICB9XG5cbiAgaXNFbXB0eSgpIHtcbiAgICByZXR1cm4gdGhpcy5tZXNzYWdlcy5sZW5ndGggPT09IDA7XG4gIH1cblxuICByZW1vdmVBdChpbmRleCkge1xuICAgIHRoaXMubWVzc2FnZXMuc3BsaWNlKGluZGV4LCAxKTtcbiAgfVxufVxuXG52YXIgU3RhdGVzID0ge1xuICBOT1JNQUw6IFN5bWJvbC5mb3IoXCJub3JtYWxcIiksXG4gIEtJTEw6IFN5bWJvbC5mb3IoXCJraWxsXCIpLFxuICBTVVNQRU5EOiBTeW1ib2wuZm9yKFwic3VzcGVuZFwiKSxcbiAgQ09OVElOVUU6IFN5bWJvbC5mb3IoXCJjb250aW51ZVwiKSxcbiAgUkVDRUlWRTogU3ltYm9sLmZvcihcInJlY2VpdmVcIiksXG4gIFNFTkQ6IFN5bWJvbC5mb3IoXCJzZW5kXCIpLFxuICBTTEVFUElORzogU3ltYm9sLmZvcihcInNsZWVwaW5nXCIpLFxuICBSVU5OSU5HOiBTeW1ib2wuZm9yKFwicnVubmluZ1wiKSxcbiAgU1VTUEVOREVEOiBTeW1ib2wuZm9yKFwic3VzcGVuZGVkXCIpLFxuICBTVE9QUEVEOiBTeW1ib2wuZm9yKFwic3RvcHBlZFwiKSxcbiAgU0xFRVA6IFN5bWJvbC5mb3IoXCJzbGVlcFwiKSxcbiAgRVhJVDogU3ltYm9sLmZvcihcImV4aXRcIiksXG4gIE5PTUFUQ0g6IFN5bWJvbC5mb3IoXCJub19tYXRjaFwiKVxufTtcblxuY2xhc3MgUHJvY2VzcyB7XG5cbiAgY29uc3RydWN0b3IocGlkLCBtYWlsYm94KSB7XG4gICAgdGhpcy5waWQgPSBwaWQ7XG4gICAgdGhpcy5tYWlsYm94ID0gbWFpbGJveDtcbiAgICB0aGlzLnN0YXR1cyA9IFN0YXRlcy5TVE9QUEVEO1xuICAgIHRoaXMuZGljdCA9IHt9O1xuICB9XG59XG5cbmNsYXNzIFR1cGxlIHtcblxuICBjb25zdHJ1Y3RvciguLi5hcmdzKSB7XG4gICAgdGhpcy52YWx1ZXMgPSBPYmplY3QuZnJlZXplKGFyZ3MpO1xuICAgIHRoaXMubGVuZ3RoID0gdGhpcy52YWx1ZXMubGVuZ3RoO1xuICB9XG5cbiAgZ2V0KGluZGV4KSB7XG4gICAgcmV0dXJuIHRoaXMudmFsdWVzW2luZGV4XTtcbiAgfVxuXG4gIGNvdW50KCkge1xuICAgIHJldHVybiB0aGlzLnZhbHVlcy5sZW5ndGg7XG4gIH1cblxuICBbU3ltYm9sLml0ZXJhdG9yXSgpIHtcbiAgICByZXR1cm4gdGhpcy52YWx1ZXNbU3ltYm9sLml0ZXJhdG9yXSgpO1xuICB9XG5cbiAgdG9TdHJpbmcoKSB7XG4gICAgdmFyIGksXG4gICAgICAgIHMgPSBcIlwiO1xuICAgIGZvciAoaSA9IDA7IGkgPCB0aGlzLnZhbHVlcy5sZW5ndGg7IGkrKykge1xuICAgICAgaWYgKHMgIT09IFwiXCIpIHtcbiAgICAgICAgcyArPSBcIiwgXCI7XG4gICAgICB9XG4gICAgICBzICs9IHRoaXMudmFsdWVzW2ldLnRvU3RyaW5nKCk7XG4gICAgfVxuXG4gICAgcmV0dXJuIFwie1wiICsgcyArIFwifVwiO1xuICB9XG5cbn1cblxubGV0IHByb2Nlc3NfY291bnRlciA9IC0xO1xuXG5jbGFzcyBQSUQge1xuICBjb25zdHJ1Y3RvcigpIHtcbiAgICBwcm9jZXNzX2NvdW50ZXIgPSBwcm9jZXNzX2NvdW50ZXIgKyAxO1xuICAgIHRoaXMuaWQgPSBwcm9jZXNzX2NvdW50ZXI7XG4gIH1cblxuICB0b1N0cmluZygpIHtcbiAgICByZXR1cm4gXCJQSUQjPDAuXCIgKyB0aGlzLmlkICsgXCIuMD5cIjtcbiAgfVxufVxuXG5jbGFzcyBJbnRlZ2VyIHt9XG5jbGFzcyBGbG9hdCB7fVxuXG5mdW5jdGlvbiBMaXN0KC4uLmFyZ3MpIHtcbiAgcmV0dXJuIE9iamVjdC5mcmVlemUoYXJncyk7XG59XG5cbmNsYXNzIFByb2Nlc3NTeXN0ZW0ge1xuXG4gIGNvbnN0cnVjdG9yKCkge1xuICAgIHRoaXMucGlkcyA9IG5ldyBNYXAoKTtcbiAgICB0aGlzLm1haWxib3hlcyA9IG5ldyBNYXAoKTtcbiAgICB0aGlzLm5hbWVzID0gbmV3IE1hcCgpO1xuICAgIHRoaXMubGlua3MgPSBuZXcgTWFwKCk7XG5cbiAgICB0aGlzLmN1cnJlbnRfcHJvY2VzcyA9IG51bGw7XG4gICAgdGhpcy5zdXNwZW5kZWQgPSBuZXcgTWFwKCk7XG5cbiAgICB0aGlzLm1haW5fcHJvY2Vzc19waWQgPSB0aGlzLnNwYXduKCk7XG4gICAgdGhpcy5zZXRfY3VycmVudCh0aGlzLm1haW5fcHJvY2Vzc19waWQpO1xuICB9XG5cbiAgc3Bhd24oKSB7XG4gICAgcmV0dXJuIHRoaXMuYWRkX3Byb2MoZmFsc2UpLnBpZDtcbiAgfVxuXG4gIHNwYXduX2xpbmsoKSB7XG4gICAgcmV0dXJuIHRoaXMuYWRkX3Byb2ModHJ1ZSkucGlkO1xuICB9XG5cbiAgbGluayhwaWQpIHtcbiAgICB0aGlzLmxpbmtzLmdldCh0aGlzLnBpZCgpKS5hZGQocGlkKTtcbiAgICB0aGlzLmxpbmtzLmdldChwaWQpLmFkZCh0aGlzLnBpZCgpKTtcbiAgfVxuXG4gIHVubGluayhwaWQpIHtcbiAgICB0aGlzLmxpbmtzLmdldCh0aGlzLnBpZCgpKS5kZWxldGUocGlkKTtcbiAgICB0aGlzLmxpbmtzLmdldChwaWQpLmRlbGV0ZSh0aGlzLnBpZCgpKTtcbiAgfVxuXG4gIHNldF9jdXJyZW50KGlkKSB7XG4gICAgbGV0IHBpZCA9IHRoaXMucGlkb2YoaWQpO1xuICAgIGlmIChwaWQgIT09IG51bGwpIHtcbiAgICAgIHRoaXMuY3VycmVudF9wcm9jZXNzID0gdGhpcy5waWRzLmdldChwaWQpO1xuICAgICAgdGhpcy5jdXJyZW50X3Byb2Nlc3Muc3RhdHVzID0gU3RhdGVzLlJVTk5JTkc7XG4gICAgfVxuICB9XG5cbiAgYWRkX3Byb2MobGlua2VkKSB7XG4gICAgbGV0IG5ld3BpZCA9IG5ldyBQSUQoKTtcbiAgICBsZXQgbWFpbGJveCA9IG5ldyBNYWlsYm94KCk7XG4gICAgbGV0IG5ld3Byb2MgPSBuZXcgUHJvY2VzcyhuZXdwaWQsIG1haWxib3gpO1xuXG4gICAgdGhpcy5waWRzLnNldChuZXdwaWQsIG5ld3Byb2MpO1xuICAgIHRoaXMubWFpbGJveGVzLnNldChuZXdwaWQsIG1haWxib3gpO1xuICAgIHRoaXMubGlua3Muc2V0KG5ld3BpZCwgbmV3IFNldCgpKTtcblxuICAgIGlmIChsaW5rZWQpIHtcbiAgICAgIHRoaXMubGluayhuZXdwaWQpO1xuICAgIH1cblxuICAgIHJldHVybiBuZXdwcm9jO1xuICB9XG5cbiAgcmVtb3ZlX3Byb2MocGlkKSB7XG4gICAgdGhpcy5waWRzLmRlbGV0ZShwaWQpO1xuICAgIHRoaXMudW5yZWdpc3RlcihwaWQpO1xuXG4gICAgaWYgKHRoaXMubGlua3MuaGFzKHBpZCkpIHtcbiAgICAgIGZvciAobGV0IGxpbmtwaWQgb2YgdGhpcy5saW5rcy5nZXQocGlkKSkge1xuICAgICAgICB0aGlzLmxpbmtzLmdldChsaW5rcGlkKS5kZWxldGUocGlkKTtcbiAgICAgIH1cblxuICAgICAgdGhpcy5saW5rcy5kZWxldGUocGlkKTtcbiAgICB9XG4gIH1cblxuICBleGl0KGlkKSB7XG4gICAgbGV0IHBpZCA9IHRoaXMucGlkb2YoaWQpO1xuICAgIHRoaXMucmVtb3ZlX3Byb2MoaWQpO1xuICB9XG5cbiAgcmVnaXN0ZXIobmFtZSwgcGlkKSB7XG4gICAgaWYgKCF0aGlzLm5hbWVzLmhhcyhuYW1lKSkge1xuICAgICAgdGhpcy5uYW1lcy5zZXQobmFtZSwgcGlkKTtcbiAgICAgIHJldHVybiBuYW1lO1xuICAgIH0gZWxzZSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoXCJOYW1lIGlzIGFscmVhZHkgcmVnaXN0ZXJlZCB0byBhbm90aGVyIHByb2Nlc3NcIik7XG4gICAgfVxuICB9XG5cbiAgcmVnaXN0ZXJlZChuYW1lKSB7XG4gICAgcmV0dXJuIHRoaXMubmFtZXMuaGFzKG5hbWUpID8gdGhpcy5uYW1lcy5nZXQobmFtZSkgOiBudWxsO1xuICB9XG5cbiAgdW5yZWdpc3RlcihwaWQpIHtcbiAgICBmb3IgKGxldCBuYW1lIG9mIHRoaXMubmFtZXMua2V5cygpKSB7XG4gICAgICBpZiAodGhpcy5uYW1lcy5oYXMobmFtZSkgJiYgdGhpcy5uYW1lcy5nZXQobmFtZSkgPT09IHBpZCkge1xuICAgICAgICB0aGlzLm5hbWVzLmRlbGV0ZShuYW1lKTtcbiAgICAgIH1cbiAgICB9XG4gIH1cblxuICBwaWQoKSB7XG4gICAgcmV0dXJuIHRoaXMuY3VycmVudF9wcm9jZXNzLnBpZDtcbiAgfVxuXG4gIHBpZG9mKGlkKSB7XG4gICAgaWYgKGlkIGluc3RhbmNlb2YgUElEKSB7XG4gICAgICByZXR1cm4gdGhpcy5waWRzLmhhcyhpZCkgPyBpZCA6IG51bGw7XG4gICAgfSBlbHNlIGlmIChpZCBpbnN0YW5jZW9mIFByb2Nlc3MpIHtcbiAgICAgIHJldHVybiBpZC5waWQ7XG4gICAgfSBlbHNlIHtcbiAgICAgIGxldCBwaWQgPSB0aGlzLnJlZ2lzdGVyZWQoaWQpO1xuICAgICAgaWYgKHBpZCA9PT0gbnVsbCkgdGhyb3cgXCJQcm9jZXNzIG5hbWUgbm90IHJlZ2lzdGVyZWQ6IFwiICsgaWQgKyBcIiAoXCIgKyB0eXBlb2YgaWQgKyBcIilcIjtcbiAgICAgIHJldHVybiBwaWQ7XG4gICAgfVxuICB9XG5cbiAgcHV0KGlkLCBrZXksIHZhbHVlKSB7XG4gICAgbGV0IHBpZCA9IHRoaXMucGlkb2YoaWQpO1xuICAgIGxldCBwcm9jZXNzID0gdGhpcy5waWRzLmdldChwaWQpO1xuICAgIHByb2Nlc3MuZGljdFtrZXldID0gdmFsdWU7XG4gIH1cblxuICBnZXQoaWQsIGtleSkge1xuICAgIGxldCBwaWQgPSB0aGlzLnBpZG9mKGlkKTtcbiAgICBsZXQgcHJvY2VzcyA9IHRoaXMucGlkcy5nZXQocGlkKTtcblxuICAgIGlmIChrZXkgIT0gbnVsbCkge1xuICAgICAgcmV0dXJuIHByb2Nlc3MuZGljdFtrZXldO1xuICAgIH0gZWxzZSB7XG4gICAgICByZXR1cm4gcHJvY2Vzcy5kaWN0O1xuICAgIH1cbiAgfVxuXG4gIGdldF9rZXlzKGlkKSB7XG4gICAgbGV0IHBpZCA9IHRoaXMucGlkb2YoaWQpO1xuICAgIGxldCBwcm9jZXNzID0gdGhpcy5waWRzLmdldChwaWQpO1xuXG4gICAgcmV0dXJuIE9iamVjdC5rZXlzKHByb2Nlc3MuZGljdCk7XG4gIH1cblxuICBlcmFzZShpZCwga2V5KSB7XG4gICAgbGV0IHBpZCA9IHRoaXMucGlkb2YoaWQpO1xuICAgIGxldCBwcm9jZXNzID0gdGhpcy5waWRzLmdldChwaWQpO1xuXG4gICAgaWYgKGtleSAhPSBudWxsKSB7XG4gICAgICBkZWxldGUgcHJvY2Vzcy5kaWN0W2tleV07XG4gICAgfSBlbHNlIHtcbiAgICAgIHByb2Nlc3MuZGljdCA9IHt9O1xuICAgIH1cbiAgfVxufVxuXG5jbGFzcyBCaXRTdHJpbmcge1xuICBjb25zdHJ1Y3RvciguLi5hcmdzKSB7XG4gICAgdGhpcy5yYXdfdmFsdWUgPSBmdW5jdGlvbiAoKSB7XG4gICAgICByZXR1cm4gT2JqZWN0LmZyZWV6ZShhcmdzKTtcbiAgICB9O1xuXG4gICAgdGhpcy52YWx1ZSA9IE9iamVjdC5mcmVlemUodGhpcy5wcm9jZXNzKGFyZ3MpKTtcbiAgfVxuXG4gIGdldChpbmRleCkge1xuICAgIHJldHVybiB0aGlzLnZhbHVlW2luZGV4XTtcbiAgfVxuXG4gIGNvdW50KCkge1xuICAgIHJldHVybiB0aGlzLnZhbHVlLmxlbmd0aDtcbiAgfVxuXG4gIFtTeW1ib2wuaXRlcmF0b3JdKCkge1xuICAgIHJldHVybiB0aGlzLnZhbHVlW1N5bWJvbC5pdGVyYXRvcl0oKTtcbiAgfVxuXG4gIHRvU3RyaW5nKCkge1xuICAgIHZhciBpLFxuICAgICAgICBzID0gXCJcIjtcbiAgICBmb3IgKGkgPSAwOyBpIDwgdGhpcy5jb3VudCgpOyBpKyspIHtcbiAgICAgIGlmIChzICE9PSBcIlwiKSB7XG4gICAgICAgIHMgKz0gXCIsIFwiO1xuICAgICAgfVxuICAgICAgcyArPSB0aGlzW2ldLnRvU3RyaW5nKCk7XG4gICAgfVxuXG4gICAgcmV0dXJuIFwiPDxcIiArIHMgKyBcIj4+XCI7XG4gIH1cblxuICBwcm9jZXNzKCkge1xuICAgIGxldCBwcm9jZXNzZWRfdmFsdWVzID0gW107XG5cbiAgICB2YXIgaTtcbiAgICBmb3IgKGkgPSAwOyBpIDwgdGhpcy5yYXdfdmFsdWUoKS5sZW5ndGg7IGkrKykge1xuICAgICAgbGV0IHByb2Nlc3NlZF92YWx1ZSA9IHRoaXNbXCJwcm9jZXNzX1wiICsgdGhpcy5yYXdfdmFsdWUoKVtpXS50eXBlXSh0aGlzLnJhd192YWx1ZSgpW2ldKTtcblxuICAgICAgZm9yIChsZXQgYXR0ciBvZiB0aGlzLnJhd192YWx1ZSgpW2ldLmF0dHJpYnV0ZXMpIHtcbiAgICAgICAgcHJvY2Vzc2VkX3ZhbHVlID0gdGhpc1tcInByb2Nlc3NfXCIgKyBhdHRyXShwcm9jZXNzZWRfdmFsdWUpO1xuICAgICAgfVxuXG4gICAgICBwcm9jZXNzZWRfdmFsdWVzID0gcHJvY2Vzc2VkX3ZhbHVlcy5jb25jYXQocHJvY2Vzc2VkX3ZhbHVlKTtcbiAgICB9XG5cbiAgICByZXR1cm4gcHJvY2Vzc2VkX3ZhbHVlcztcbiAgfVxuXG4gIHByb2Nlc3NfaW50ZWdlcih2YWx1ZSkge1xuICAgIHJldHVybiB2YWx1ZS52YWx1ZTtcbiAgfVxuXG4gIHByb2Nlc3NfZmxvYXQodmFsdWUpIHtcbiAgICBpZiAodmFsdWUuc2l6ZSA9PT0gNjQpIHtcbiAgICAgIHJldHVybiBCaXRTdHJpbmcuZmxvYXQ2NFRvQnl0ZXModmFsdWUudmFsdWUpO1xuICAgIH0gZWxzZSBpZiAodmFsdWUuc2l6ZSA9PT0gMzIpIHtcbiAgICAgIHJldHVybiBCaXRTdHJpbmcuZmxvYXQzMlRvQnl0ZXModmFsdWUudmFsdWUpO1xuICAgIH1cblxuICAgIHRocm93IG5ldyBFcnJvcihcIkludmFsaWQgc2l6ZSBmb3IgZmxvYXRcIik7XG4gIH1cblxuICBwcm9jZXNzX2JpdHN0cmluZyh2YWx1ZSkge1xuICAgIHJldHVybiB2YWx1ZS52YWx1ZS52YWx1ZTtcbiAgfVxuXG4gIHByb2Nlc3NfYmluYXJ5KHZhbHVlKSB7XG4gICAgcmV0dXJuIEJpdFN0cmluZy50b1VURjhBcnJheSh2YWx1ZS52YWx1ZSk7XG4gIH1cblxuICBwcm9jZXNzX3V0ZjgodmFsdWUpIHtcbiAgICByZXR1cm4gQml0U3RyaW5nLnRvVVRGOEFycmF5KHZhbHVlLnZhbHVlKTtcbiAgfVxuXG4gIHByb2Nlc3NfdXRmMTYodmFsdWUpIHtcbiAgICByZXR1cm4gQml0U3RyaW5nLnRvVVRGMTZBcnJheSh2YWx1ZS52YWx1ZSk7XG4gIH1cblxuICBwcm9jZXNzX3V0ZjMyKHZhbHVlKSB7XG4gICAgcmV0dXJuIEJpdFN0cmluZy50b1VURjMyQXJyYXkodmFsdWUudmFsdWUpO1xuICB9XG5cbiAgcHJvY2Vzc19zaWduZWQodmFsdWUpIHtcbiAgICByZXR1cm4gbmV3IFVpbnQ4QXJyYXkoW3ZhbHVlXSlbMF07XG4gIH1cblxuICBwcm9jZXNzX3Vuc2lnbmVkKHZhbHVlKSB7XG4gICAgcmV0dXJuIHZhbHVlO1xuICB9XG5cbiAgcHJvY2Vzc19uYXRpdmUodmFsdWUpIHtcbiAgICByZXR1cm4gdmFsdWU7XG4gIH1cblxuICBwcm9jZXNzX2JpZyh2YWx1ZSkge1xuICAgIHJldHVybiB2YWx1ZTtcbiAgfVxuXG4gIHByb2Nlc3NfbGl0dGxlKHZhbHVlKSB7XG4gICAgcmV0dXJuIHZhbHVlLnJldmVyc2UoKTtcbiAgfVxuXG4gIHByb2Nlc3Nfc2l6ZSh2YWx1ZSkge1xuICAgIHJldHVybiB2YWx1ZTtcbiAgfVxuXG4gIHByb2Nlc3NfdW5pdCh2YWx1ZSkge1xuICAgIHJldHVybiB2YWx1ZTtcbiAgfVxuXG4gIHN0YXRpYyBpbnRlZ2VyKHZhbHVlKSB7XG4gICAgcmV0dXJuIEJpdFN0cmluZy53cmFwKHZhbHVlLCB7IFwidHlwZVwiOiBcImludGVnZXJcIiwgXCJ1bml0XCI6IDEsIFwic2l6ZVwiOiA4IH0pO1xuICB9XG5cbiAgc3RhdGljIGZsb2F0KHZhbHVlKSB7XG4gICAgcmV0dXJuIEJpdFN0cmluZy53cmFwKHZhbHVlLCB7IFwidHlwZVwiOiBcImZsb2F0XCIsIFwidW5pdFwiOiAxLCBcInNpemVcIjogNjQgfSk7XG4gIH1cblxuICBzdGF0aWMgYml0c3RyaW5nKHZhbHVlKSB7XG4gICAgcmV0dXJuIEJpdFN0cmluZy53cmFwKHZhbHVlLCB7IFwidHlwZVwiOiBcImJpdHN0cmluZ1wiLCBcInVuaXRcIjogMSwgXCJzaXplXCI6IHZhbHVlLmxlbmd0aCB9KTtcbiAgfVxuXG4gIHN0YXRpYyBiaXRzKHZhbHVlKSB7XG4gICAgcmV0dXJuIEJpdFN0cmluZy5iaXRzdHJpbmcodmFsdWUpO1xuICB9XG5cbiAgc3RhdGljIGJpbmFyeSh2YWx1ZSkge1xuICAgIHJldHVybiBCaXRTdHJpbmcud3JhcCh2YWx1ZSwgeyBcInR5cGVcIjogXCJiaW5hcnlcIiwgXCJ1bml0XCI6IDgsIFwic2l6ZVwiOiB2YWx1ZS5sZW5ndGggfSk7XG4gIH1cblxuICBzdGF0aWMgYnl0ZXModmFsdWUpIHtcbiAgICByZXR1cm4gQml0U3RyaW5nLmJpbmFyeSh2YWx1ZSk7XG4gIH1cblxuICBzdGF0aWMgdXRmOCh2YWx1ZSkge1xuICAgIHJldHVybiBCaXRTdHJpbmcud3JhcCh2YWx1ZSwgeyBcInR5cGVcIjogXCJ1dGY4XCIgfSk7XG4gIH1cblxuICBzdGF0aWMgdXRmMTYodmFsdWUpIHtcbiAgICByZXR1cm4gQml0U3RyaW5nLndyYXAodmFsdWUsIHsgXCJ0eXBlXCI6IFwidXRmMTZcIiB9KTtcbiAgfVxuXG4gIHN0YXRpYyB1dGYzMih2YWx1ZSkge1xuICAgIHJldHVybiBCaXRTdHJpbmcud3JhcCh2YWx1ZSwgeyBcInR5cGVcIjogXCJ1dGYzMlwiIH0pO1xuICB9XG5cbiAgc3RhdGljIHNpZ25lZCh2YWx1ZSkge1xuICAgIHJldHVybiBCaXRTdHJpbmcud3JhcCh2YWx1ZSwge30sIFwic2lnbmVkXCIpO1xuICB9XG5cbiAgc3RhdGljIHVuc2lnbmVkKHZhbHVlKSB7XG4gICAgcmV0dXJuIEJpdFN0cmluZy53cmFwKHZhbHVlLCB7fSwgXCJ1bnNpZ25lZFwiKTtcbiAgfVxuXG4gIHN0YXRpYyBuYXRpdmUodmFsdWUpIHtcbiAgICByZXR1cm4gQml0U3RyaW5nLndyYXAodmFsdWUsIHt9LCBcIm5hdGl2ZVwiKTtcbiAgfVxuXG4gIHN0YXRpYyBiaWcodmFsdWUpIHtcbiAgICByZXR1cm4gQml0U3RyaW5nLndyYXAodmFsdWUsIHt9LCBcImJpZ1wiKTtcbiAgfVxuXG4gIHN0YXRpYyBsaXR0bGUodmFsdWUpIHtcbiAgICByZXR1cm4gQml0U3RyaW5nLndyYXAodmFsdWUsIHt9LCBcImxpdHRsZVwiKTtcbiAgfVxuXG4gIHN0YXRpYyBzaXplKHZhbHVlLCBjb3VudCkge1xuICAgIHJldHVybiBCaXRTdHJpbmcud3JhcCh2YWx1ZSwgeyBcInNpemVcIjogY291bnQgfSk7XG4gIH1cblxuICBzdGF0aWMgdW5pdCh2YWx1ZSwgY291bnQpIHtcbiAgICByZXR1cm4gQml0U3RyaW5nLndyYXAodmFsdWUsIHsgXCJ1bml0XCI6IGNvdW50IH0pO1xuICB9XG5cbiAgc3RhdGljIHdyYXAodmFsdWUsIG9wdCwgbmV3X2F0dHJpYnV0ZSA9IG51bGwpIHtcbiAgICBsZXQgdGhlX3ZhbHVlID0gdmFsdWU7XG5cbiAgICBpZiAoISh2YWx1ZSBpbnN0YW5jZW9mIE9iamVjdCkpIHtcbiAgICAgIHRoZV92YWx1ZSA9IHsgXCJ2YWx1ZVwiOiB2YWx1ZSwgXCJhdHRyaWJ1dGVzXCI6IFtdIH07XG4gICAgfVxuXG4gICAgdGhlX3ZhbHVlID0gT2JqZWN0LmFzc2lnbih0aGVfdmFsdWUsIG9wdCk7XG5cbiAgICBpZiAobmV3X2F0dHJpYnV0ZSkge1xuICAgICAgdGhlX3ZhbHVlLmF0dHJpYnV0ZXMucHVzaChuZXdfYXR0cmlidXRlKTtcbiAgICB9XG5cbiAgICByZXR1cm4gdGhlX3ZhbHVlO1xuICB9XG5cbiAgc3RhdGljIHRvVVRGOEFycmF5KHN0cikge1xuICAgIHZhciB1dGY4ID0gW107XG4gICAgZm9yICh2YXIgaSA9IDA7IGkgPCBzdHIubGVuZ3RoOyBpKyspIHtcbiAgICAgIHZhciBjaGFyY29kZSA9IHN0ci5jaGFyQ29kZUF0KGkpO1xuICAgICAgaWYgKGNoYXJjb2RlIDwgMTI4KSB7XG4gICAgICAgIHV0ZjgucHVzaChjaGFyY29kZSk7XG4gICAgICB9IGVsc2UgaWYgKGNoYXJjb2RlIDwgMjA0OCkge1xuICAgICAgICB1dGY4LnB1c2goMTkyIHwgY2hhcmNvZGUgPj4gNiwgMTI4IHwgY2hhcmNvZGUgJiA2Myk7XG4gICAgICB9IGVsc2UgaWYgKGNoYXJjb2RlIDwgNTUyOTYgfHwgY2hhcmNvZGUgPj0gNTczNDQpIHtcbiAgICAgICAgdXRmOC5wdXNoKDIyNCB8IGNoYXJjb2RlID4+IDEyLCAxMjggfCBjaGFyY29kZSA+PiA2ICYgNjMsIDEyOCB8IGNoYXJjb2RlICYgNjMpO1xuICAgICAgfVxuICAgICAgLy8gc3Vycm9nYXRlIHBhaXJcbiAgICAgIGVsc2Uge1xuICAgICAgICBpKys7XG4gICAgICAgIC8vIFVURi0xNiBlbmNvZGVzIDB4MTAwMDAtMHgxMEZGRkYgYnlcbiAgICAgICAgLy8gc3VidHJhY3RpbmcgMHgxMDAwMCBhbmQgc3BsaXR0aW5nIHRoZVxuICAgICAgICAvLyAyMCBiaXRzIG9mIDB4MC0weEZGRkZGIGludG8gdHdvIGhhbHZlc1xuICAgICAgICBjaGFyY29kZSA9IDY1NTM2ICsgKChjaGFyY29kZSAmIDEwMjMpIDw8IDEwIHwgc3RyLmNoYXJDb2RlQXQoaSkgJiAxMDIzKTtcbiAgICAgICAgdXRmOC5wdXNoKDI0MCB8IGNoYXJjb2RlID4+IDE4LCAxMjggfCBjaGFyY29kZSA+PiAxMiAmIDYzLCAxMjggfCBjaGFyY29kZSA+PiA2ICYgNjMsIDEyOCB8IGNoYXJjb2RlICYgNjMpO1xuICAgICAgfVxuICAgIH1cbiAgICByZXR1cm4gdXRmODtcbiAgfVxuXG4gIHN0YXRpYyB0b1VURjE2QXJyYXkoc3RyKSB7XG4gICAgdmFyIHV0ZjE2ID0gW107XG4gICAgZm9yICh2YXIgaSA9IDA7IGkgPCBzdHIubGVuZ3RoOyBpKyspIHtcbiAgICAgIHZhciBjb2RlUG9pbnQgPSBzdHIuY29kZVBvaW50QXQoaSk7XG5cbiAgICAgIGlmIChjb2RlUG9pbnQgPD0gMjU1KSB7XG4gICAgICAgIHV0ZjE2LnB1c2goMCk7XG4gICAgICAgIHV0ZjE2LnB1c2goY29kZVBvaW50KTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHV0ZjE2LnB1c2goY29kZVBvaW50ID4+IDggJiAyNTUpO1xuICAgICAgICB1dGYxNi5wdXNoKGNvZGVQb2ludCAmIDI1NSk7XG4gICAgICB9XG4gICAgfVxuICAgIHJldHVybiB1dGYxNjtcbiAgfVxuXG4gIHN0YXRpYyB0b1VURjMyQXJyYXkoc3RyKSB7XG4gICAgdmFyIHV0ZjMyID0gW107XG4gICAgZm9yICh2YXIgaSA9IDA7IGkgPCBzdHIubGVuZ3RoOyBpKyspIHtcbiAgICAgIHZhciBjb2RlUG9pbnQgPSBzdHIuY29kZVBvaW50QXQoaSk7XG5cbiAgICAgIGlmIChjb2RlUG9pbnQgPD0gMjU1KSB7XG4gICAgICAgIHV0ZjMyLnB1c2goMCk7XG4gICAgICAgIHV0ZjMyLnB1c2goMCk7XG4gICAgICAgIHV0ZjMyLnB1c2goMCk7XG4gICAgICAgIHV0ZjMyLnB1c2goY29kZVBvaW50KTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHV0ZjMyLnB1c2goMCk7XG4gICAgICAgIHV0ZjMyLnB1c2goMCk7XG4gICAgICAgIHV0ZjMyLnB1c2goY29kZVBvaW50ID4+IDggJiAyNTUpO1xuICAgICAgICB1dGYzMi5wdXNoKGNvZGVQb2ludCAmIDI1NSk7XG4gICAgICB9XG4gICAgfVxuICAgIHJldHVybiB1dGYzMjtcbiAgfVxuXG4gIC8vaHR0cDovL3N0YWNrb3ZlcmZsb3cuY29tL3F1ZXN0aW9ucy8yMDAzNDkzL2phdmFzY3JpcHQtZmxvYXQtZnJvbS10by1iaXRzXG4gIHN0YXRpYyBmbG9hdDMyVG9CeXRlcyhmKSB7XG4gICAgdmFyIGJ5dGVzID0gW107XG5cbiAgICB2YXIgYnVmID0gbmV3IEFycmF5QnVmZmVyKDQpO1xuICAgIG5ldyBGbG9hdDMyQXJyYXkoYnVmKVswXSA9IGY7XG5cbiAgICBsZXQgaW50VmVyc2lvbiA9IG5ldyBVaW50MzJBcnJheShidWYpWzBdO1xuXG4gICAgYnl0ZXMucHVzaChpbnRWZXJzaW9uID4+IDI0ICYgMjU1KTtcbiAgICBieXRlcy5wdXNoKGludFZlcnNpb24gPj4gMTYgJiAyNTUpO1xuICAgIGJ5dGVzLnB1c2goaW50VmVyc2lvbiA+PiA4ICYgMjU1KTtcbiAgICBieXRlcy5wdXNoKGludFZlcnNpb24gJiAyNTUpO1xuXG4gICAgcmV0dXJuIGJ5dGVzO1xuICB9XG5cbiAgc3RhdGljIGZsb2F0NjRUb0J5dGVzKGYpIHtcbiAgICB2YXIgYnl0ZXMgPSBbXTtcblxuICAgIHZhciBidWYgPSBuZXcgQXJyYXlCdWZmZXIoOCk7XG4gICAgbmV3IEZsb2F0NjRBcnJheShidWYpWzBdID0gZjtcblxuICAgIHZhciBpbnRWZXJzaW9uMSA9IG5ldyBVaW50MzJBcnJheShidWYpWzBdO1xuICAgIHZhciBpbnRWZXJzaW9uMiA9IG5ldyBVaW50MzJBcnJheShidWYpWzFdO1xuXG4gICAgYnl0ZXMucHVzaChpbnRWZXJzaW9uMiA+PiAyNCAmIDI1NSk7XG4gICAgYnl0ZXMucHVzaChpbnRWZXJzaW9uMiA+PiAxNiAmIDI1NSk7XG4gICAgYnl0ZXMucHVzaChpbnRWZXJzaW9uMiA+PiA4ICYgMjU1KTtcbiAgICBieXRlcy5wdXNoKGludFZlcnNpb24yICYgMjU1KTtcblxuICAgIGJ5dGVzLnB1c2goaW50VmVyc2lvbjEgPj4gMjQgJiAyNTUpO1xuICAgIGJ5dGVzLnB1c2goaW50VmVyc2lvbjEgPj4gMTYgJiAyNTUpO1xuICAgIGJ5dGVzLnB1c2goaW50VmVyc2lvbjEgPj4gOCAmIDI1NSk7XG4gICAgYnl0ZXMucHVzaChpbnRWZXJzaW9uMSAmIDI1NSk7XG5cbiAgICByZXR1cm4gYnl0ZXM7XG4gIH1cbn1cblxuLyogQGZsb3cgKi9cblxuY2xhc3MgVmFyaWFibGUge1xuXG4gIGNvbnN0cnVjdG9yKG5hbWUgPSBudWxsKSB7XG4gICAgdGhpcy5uYW1lID0gbmFtZTtcbiAgfVxufVxuXG5jbGFzcyBXaWxkY2FyZCB7XG4gIGNvbnN0cnVjdG9yKCkge31cbn1cblxuY2xhc3MgU3RhcnRzV2l0aCB7XG5cbiAgY29uc3RydWN0b3IocHJlZml4KSB7XG4gICAgdGhpcy5wcmVmaXggPSBwcmVmaXg7XG4gIH1cbn1cblxuY2xhc3MgQ2FwdHVyZSB7XG5cbiAgY29uc3RydWN0b3IodmFsdWUpIHtcbiAgICB0aGlzLnZhbHVlID0gdmFsdWU7XG4gIH1cbn1cblxuY2xhc3MgSGVhZFRhaWwge1xuICBjb25zdHJ1Y3RvcigpIHt9XG59XG5cbmNsYXNzIFR5cGUge1xuXG4gIGNvbnN0cnVjdG9yKHR5cGUsIG9ialBhdHRlcm4gPSB7fSkge1xuICAgIHRoaXMudHlwZSA9IHR5cGU7XG4gICAgdGhpcy5vYmpQYXR0ZXJuID0gb2JqUGF0dGVybjtcbiAgfVxufVxuXG5jbGFzcyBCb3VuZCB7XG5cbiAgY29uc3RydWN0b3IodmFsdWUpIHtcbiAgICB0aGlzLnZhbHVlID0gdmFsdWU7XG4gIH1cbn1cblxuZnVuY3Rpb24gdmFyaWFibGUobmFtZSA9IG51bGwpIHtcbiAgcmV0dXJuIG5ldyBWYXJpYWJsZShuYW1lKTtcbn1cblxuZnVuY3Rpb24gd2lsZGNhcmQoKSB7XG4gIHJldHVybiBuZXcgV2lsZGNhcmQoKTtcbn1cblxuZnVuY3Rpb24gc3RhcnRzV2l0aChwcmVmaXgpIHtcbiAgcmV0dXJuIG5ldyBTdGFydHNXaXRoKHByZWZpeCk7XG59XG5cbmZ1bmN0aW9uIGNhcHR1cmUodmFsdWUpIHtcbiAgcmV0dXJuIG5ldyBDYXB0dXJlKHZhbHVlKTtcbn1cblxuZnVuY3Rpb24gaGVhZFRhaWwoKSB7XG4gIHJldHVybiBuZXcgSGVhZFRhaWwoKTtcbn1cblxuZnVuY3Rpb24gdHlwZSh0eXBlLCBvYmpQYXR0ZXJuID0ge30pIHtcbiAgcmV0dXJuIG5ldyBUeXBlKHR5cGUsIG9ialBhdHRlcm4pO1xufVxuXG5mdW5jdGlvbiBib3VuZCh2YWx1ZSkge1xuICByZXR1cm4gbmV3IEJvdW5kKHZhbHVlKTtcbn1cblxuZnVuY3Rpb24gaXNfbnVtYmVyKHZhbHVlKSB7XG4gIHJldHVybiB0eXBlb2YgdmFsdWUgPT09ICdudW1iZXInO1xufVxuXG5mdW5jdGlvbiBpc19zdHJpbmcodmFsdWUpIHtcbiAgcmV0dXJuIHR5cGVvZiB2YWx1ZSA9PT0gJ3N0cmluZyc7XG59XG5cbmZ1bmN0aW9uIGlzX2Jvb2xlYW4odmFsdWUpIHtcbiAgcmV0dXJuIHR5cGVvZiB2YWx1ZSA9PT0gJ2Jvb2xlYW4nO1xufVxuXG5mdW5jdGlvbiBpc19zeW1ib2wodmFsdWUpIHtcbiAgcmV0dXJuIHR5cGVvZiB2YWx1ZSA9PT0gJ3N5bWJvbCc7XG59XG5cbmZ1bmN0aW9uIGlzX251bGwodmFsdWUpIHtcbiAgcmV0dXJuIHZhbHVlID09PSBudWxsO1xufVxuXG5mdW5jdGlvbiBpc191bmRlZmluZWQodmFsdWUpIHtcbiAgcmV0dXJuIHR5cGVvZiB2YWx1ZSA9PT0gJ3VuZGVmaW5lZCc7XG59XG5cbmZ1bmN0aW9uIGlzX2Z1bmN0aW9uKHZhbHVlKSB7XG4gIHJldHVybiBPYmplY3QucHJvdG90eXBlLnRvU3RyaW5nLmNhbGwodmFsdWUpID09ICdbb2JqZWN0IEZ1bmN0aW9uXSc7XG59XG5cbmZ1bmN0aW9uIGlzX3ZhcmlhYmxlKHZhbHVlKSB7XG4gIHJldHVybiB2YWx1ZSBpbnN0YW5jZW9mIFZhcmlhYmxlO1xufVxuXG5mdW5jdGlvbiBpc193aWxkY2FyZCh2YWx1ZSkge1xuICByZXR1cm4gdmFsdWUgaW5zdGFuY2VvZiBXaWxkY2FyZDtcbn1cblxuZnVuY3Rpb24gaXNfaGVhZFRhaWwodmFsdWUpIHtcbiAgcmV0dXJuIHZhbHVlIGluc3RhbmNlb2YgSGVhZFRhaWw7XG59XG5cbmZ1bmN0aW9uIGlzX2NhcHR1cmUodmFsdWUpIHtcbiAgcmV0dXJuIHZhbHVlIGluc3RhbmNlb2YgQ2FwdHVyZTtcbn1cblxuZnVuY3Rpb24gaXNfdHlwZSh2YWx1ZSkge1xuICByZXR1cm4gdmFsdWUgaW5zdGFuY2VvZiBUeXBlO1xufVxuXG5mdW5jdGlvbiBpc19zdGFydHNXaXRoKHZhbHVlKSB7XG4gIHJldHVybiB2YWx1ZSBpbnN0YW5jZW9mIFN0YXJ0c1dpdGg7XG59XG5cbmZ1bmN0aW9uIGlzX2JvdW5kKHZhbHVlKSB7XG4gIHJldHVybiB2YWx1ZSBpbnN0YW5jZW9mIEJvdW5kO1xufVxuXG5mdW5jdGlvbiBpc19vYmplY3QodmFsdWUpIHtcbiAgcmV0dXJuIHR5cGVvZiB2YWx1ZSA9PT0gJ29iamVjdCc7XG59XG5cbmZ1bmN0aW9uIGlzX2FycmF5KHZhbHVlKSB7XG4gIHJldHVybiBBcnJheS5pc0FycmF5KHZhbHVlKTtcbn1cblxudmFyIENoZWNrcyA9IHtcbiAgaXNfbnVtYmVyLFxuICBpc19zdHJpbmcsXG4gIGlzX2Jvb2xlYW4sXG4gIGlzX3N5bWJvbCxcbiAgaXNfbnVsbCxcbiAgaXNfdW5kZWZpbmVkLFxuICBpc19mdW5jdGlvbixcbiAgaXNfdmFyaWFibGUsXG4gIGlzX3dpbGRjYXJkLFxuICBpc19oZWFkVGFpbCxcbiAgaXNfY2FwdHVyZSxcbiAgaXNfdHlwZSxcbiAgaXNfc3RhcnRzV2l0aCxcbiAgaXNfYm91bmQsXG4gIGlzX29iamVjdCxcbiAgaXNfYXJyYXlcbn07XG5cbmZ1bmN0aW9uIHJlc29sdmVTeW1ib2wocGF0dGVybikge1xuICByZXR1cm4gZnVuY3Rpb24gKHZhbHVlKSB7XG4gICAgcmV0dXJuIENoZWNrcy5pc19zeW1ib2wodmFsdWUpICYmIHZhbHVlID09PSBwYXR0ZXJuO1xuICB9O1xufVxuXG5mdW5jdGlvbiByZXNvbHZlU3RyaW5nKHBhdHRlcm4pIHtcbiAgcmV0dXJuIGZ1bmN0aW9uICh2YWx1ZSkge1xuICAgIHJldHVybiBDaGVja3MuaXNfc3RyaW5nKHZhbHVlKSAmJiB2YWx1ZSA9PT0gcGF0dGVybjtcbiAgfTtcbn1cblxuZnVuY3Rpb24gcmVzb2x2ZU51bWJlcihwYXR0ZXJuKSB7XG4gIHJldHVybiBmdW5jdGlvbiAodmFsdWUpIHtcbiAgICByZXR1cm4gQ2hlY2tzLmlzX251bWJlcih2YWx1ZSkgJiYgdmFsdWUgPT09IHBhdHRlcm47XG4gIH07XG59XG5cbmZ1bmN0aW9uIHJlc29sdmVCb29sZWFuKHBhdHRlcm4pIHtcbiAgcmV0dXJuIGZ1bmN0aW9uICh2YWx1ZSkge1xuICAgIHJldHVybiBDaGVja3MuaXNfYm9vbGVhbih2YWx1ZSkgJiYgdmFsdWUgPT09IHBhdHRlcm47XG4gIH07XG59XG5cbmZ1bmN0aW9uIHJlc29sdmVGdW5jdGlvbihwYXR0ZXJuKSB7XG4gIHJldHVybiBmdW5jdGlvbiAodmFsdWUpIHtcbiAgICByZXR1cm4gQ2hlY2tzLmlzX2Z1bmN0aW9uKHZhbHVlKSAmJiB2YWx1ZSA9PT0gcGF0dGVybjtcbiAgfTtcbn1cblxuZnVuY3Rpb24gcmVzb2x2ZU51bGwocGF0dGVybikge1xuICByZXR1cm4gZnVuY3Rpb24gKHZhbHVlKSB7XG4gICAgcmV0dXJuIENoZWNrcy5pc19udWxsKHZhbHVlKTtcbiAgfTtcbn1cblxuZnVuY3Rpb24gcmVzb2x2ZUJvdW5kKHBhdHRlcm4pIHtcbiAgcmV0dXJuIGZ1bmN0aW9uICh2YWx1ZSwgYXJncykge1xuICAgIGlmICh0eXBlb2YgdmFsdWUgPT09IHR5cGVvZiBwYXR0ZXJuLnZhbHVlICYmIHZhbHVlID09PSBwYXR0ZXJuLnZhbHVlKSB7XG4gICAgICBhcmdzLnB1c2godmFsdWUpO1xuICAgICAgcmV0dXJuIHRydWU7XG4gICAgfVxuXG4gICAgcmV0dXJuIGZhbHNlO1xuICB9O1xufVxuXG5mdW5jdGlvbiByZXNvbHZlV2lsZGNhcmQoKSB7XG4gIHJldHVybiBmdW5jdGlvbiAoKSB7XG4gICAgcmV0dXJuIHRydWU7XG4gIH07XG59XG5cbmZ1bmN0aW9uIHJlc29sdmVWYXJpYWJsZSgpIHtcbiAgcmV0dXJuIGZ1bmN0aW9uICh2YWx1ZSwgYXJncykge1xuICAgIGFyZ3MucHVzaCh2YWx1ZSk7XG4gICAgcmV0dXJuIHRydWU7XG4gIH07XG59XG5cbmZ1bmN0aW9uIHJlc29sdmVIZWFkVGFpbCgpIHtcbiAgcmV0dXJuIGZ1bmN0aW9uICh2YWx1ZSwgYXJncykge1xuICAgIGlmICghQ2hlY2tzLmlzX2FycmF5KHZhbHVlKSB8fCB2YWx1ZS5sZW5ndGggPCAyKSB7XG4gICAgICByZXR1cm4gZmFsc2U7XG4gICAgfVxuXG4gICAgY29uc3QgaGVhZCA9IHZhbHVlWzBdO1xuICAgIGNvbnN0IHRhaWwgPSB2YWx1ZS5zbGljZSgxKTtcblxuICAgIGFyZ3MucHVzaChoZWFkKTtcbiAgICBhcmdzLnB1c2godGFpbCk7XG5cbiAgICByZXR1cm4gdHJ1ZTtcbiAgfTtcbn1cblxuZnVuY3Rpb24gcmVzb2x2ZUNhcHR1cmUocGF0dGVybikge1xuICBjb25zdCBtYXRjaGVzID0gYnVpbGRNYXRjaChwYXR0ZXJuLnZhbHVlKTtcblxuICByZXR1cm4gZnVuY3Rpb24gKHZhbHVlLCBhcmdzKSB7XG4gICAgaWYgKG1hdGNoZXModmFsdWUsIGFyZ3MpKSB7XG4gICAgICBhcmdzLnB1c2godmFsdWUpO1xuICAgICAgcmV0dXJuIHRydWU7XG4gICAgfVxuXG4gICAgcmV0dXJuIGZhbHNlO1xuICB9O1xufVxuXG5mdW5jdGlvbiByZXNvbHZlU3RhcnRzV2l0aChwYXR0ZXJuKSB7XG4gIGNvbnN0IHByZWZpeCA9IHBhdHRlcm4ucHJlZml4O1xuXG4gIHJldHVybiBmdW5jdGlvbiAodmFsdWUsIGFyZ3MpIHtcbiAgICBpZiAoQ2hlY2tzLmlzX3N0cmluZyh2YWx1ZSkgJiYgdmFsdWUuc3RhcnRzV2l0aChwcmVmaXgpKSB7XG4gICAgICBhcmdzLnB1c2godmFsdWUuc3Vic3RyaW5nKHByZWZpeC5sZW5ndGgpKTtcbiAgICAgIHJldHVybiB0cnVlO1xuICAgIH1cblxuICAgIHJldHVybiBmYWxzZTtcbiAgfTtcbn1cblxuZnVuY3Rpb24gcmVzb2x2ZVR5cGUocGF0dGVybikge1xuICByZXR1cm4gZnVuY3Rpb24gKHZhbHVlLCBhcmdzKSB7XG4gICAgaWYgKHZhbHVlIGluc3RhbmNlb2YgcGF0dGVybi50eXBlKSB7XG4gICAgICBjb25zdCBtYXRjaGVzID0gYnVpbGRNYXRjaChwYXR0ZXJuLm9ialBhdHRlcm4pO1xuICAgICAgcmV0dXJuIG1hdGNoZXModmFsdWUsIGFyZ3MpICYmIGFyZ3MucHVzaCh2YWx1ZSkgPiAwO1xuICAgIH1cblxuICAgIHJldHVybiBmYWxzZTtcbiAgfTtcbn1cblxuZnVuY3Rpb24gcmVzb2x2ZUFycmF5KHBhdHRlcm4pIHtcbiAgY29uc3QgbWF0Y2hlcyA9IHBhdHRlcm4ubWFwKHggPT4gYnVpbGRNYXRjaCh4KSk7XG5cbiAgcmV0dXJuIGZ1bmN0aW9uICh2YWx1ZSwgYXJncykge1xuICAgIGlmICghQ2hlY2tzLmlzX2FycmF5KHZhbHVlKSB8fCB2YWx1ZS5sZW5ndGggIT0gcGF0dGVybi5sZW5ndGgpIHtcbiAgICAgIHJldHVybiBmYWxzZTtcbiAgICB9XG5cbiAgICByZXR1cm4gdmFsdWUuZXZlcnkoZnVuY3Rpb24gKHYsIGkpIHtcbiAgICAgIHJldHVybiBtYXRjaGVzW2ldKHZhbHVlW2ldLCBhcmdzKTtcbiAgICB9KTtcbiAgfTtcbn1cblxuZnVuY3Rpb24gcmVzb2x2ZU9iamVjdChwYXR0ZXJuKSB7XG4gIGxldCBtYXRjaGVzID0ge307XG5cbiAgZm9yIChsZXQga2V5IG9mIE9iamVjdC5rZXlzKHBhdHRlcm4pLmNvbmNhdChPYmplY3QuZ2V0T3duUHJvcGVydHlTeW1ib2xzKHBhdHRlcm4pKSkge1xuICAgIG1hdGNoZXNba2V5XSA9IGJ1aWxkTWF0Y2gocGF0dGVybltrZXldKTtcbiAgfVxuXG4gIHJldHVybiBmdW5jdGlvbiAodmFsdWUsIGFyZ3MpIHtcbiAgICBpZiAoIUNoZWNrcy5pc19vYmplY3QodmFsdWUpIHx8IHBhdHRlcm4ubGVuZ3RoID4gdmFsdWUubGVuZ3RoKSB7XG4gICAgICByZXR1cm4gZmFsc2U7XG4gICAgfVxuXG4gICAgZm9yIChsZXQga2V5IG9mIE9iamVjdC5rZXlzKHBhdHRlcm4pLmNvbmNhdChPYmplY3QuZ2V0T3duUHJvcGVydHlTeW1ib2xzKHBhdHRlcm4pKSkge1xuICAgICAgaWYgKCEoa2V5IGluIHZhbHVlKSB8fCAhbWF0Y2hlc1trZXldKHZhbHVlW2tleV0sIGFyZ3MpKSB7XG4gICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICByZXR1cm4gdHJ1ZTtcbiAgfTtcbn1cblxuZnVuY3Rpb24gcmVzb2x2ZU5vTWF0Y2goKSB7XG4gIHJldHVybiBmdW5jdGlvbiAoKSB7XG4gICAgcmV0dXJuIGZhbHNlO1xuICB9O1xufVxuXG52YXIgUmVzb2x2ZXJzID0ge1xuICByZXNvbHZlQm91bmQsXG4gIHJlc29sdmVXaWxkY2FyZCxcbiAgcmVzb2x2ZVZhcmlhYmxlLFxuICByZXNvbHZlSGVhZFRhaWwsXG4gIHJlc29sdmVDYXB0dXJlLFxuICByZXNvbHZlU3RhcnRzV2l0aCxcbiAgcmVzb2x2ZVR5cGUsXG4gIHJlc29sdmVBcnJheSxcbiAgcmVzb2x2ZU9iamVjdCxcbiAgcmVzb2x2ZU5vTWF0Y2gsXG4gIHJlc29sdmVTeW1ib2wsXG4gIHJlc29sdmVTdHJpbmcsXG4gIHJlc29sdmVOdW1iZXIsXG4gIHJlc29sdmVCb29sZWFuLFxuICByZXNvbHZlRnVuY3Rpb24sXG4gIHJlc29sdmVOdWxsXG59O1xuXG5mdW5jdGlvbiBidWlsZE1hdGNoKHBhdHRlcm4pIHtcblxuICBpZiAoQ2hlY2tzLmlzX3ZhcmlhYmxlKHBhdHRlcm4pKSB7XG4gICAgcmV0dXJuIFJlc29sdmVycy5yZXNvbHZlVmFyaWFibGUocGF0dGVybik7XG4gIH1cblxuICBpZiAoQ2hlY2tzLmlzX3dpbGRjYXJkKHBhdHRlcm4pKSB7XG4gICAgcmV0dXJuIFJlc29sdmVycy5yZXNvbHZlV2lsZGNhcmQocGF0dGVybik7XG4gIH1cblxuICBpZiAoQ2hlY2tzLmlzX3VuZGVmaW5lZChwYXR0ZXJuKSkge1xuICAgIHJldHVybiBSZXNvbHZlcnMucmVzb2x2ZVdpbGRjYXJkKHBhdHRlcm4pO1xuICB9XG5cbiAgaWYgKENoZWNrcy5pc19oZWFkVGFpbChwYXR0ZXJuKSkge1xuICAgIHJldHVybiBSZXNvbHZlcnMucmVzb2x2ZUhlYWRUYWlsKHBhdHRlcm4pO1xuICB9XG5cbiAgaWYgKENoZWNrcy5pc19zdGFydHNXaXRoKHBhdHRlcm4pKSB7XG4gICAgcmV0dXJuIFJlc29sdmVycy5yZXNvbHZlU3RhcnRzV2l0aChwYXR0ZXJuKTtcbiAgfVxuXG4gIGlmIChDaGVja3MuaXNfY2FwdHVyZShwYXR0ZXJuKSkge1xuICAgIHJldHVybiBSZXNvbHZlcnMucmVzb2x2ZUNhcHR1cmUocGF0dGVybik7XG4gIH1cblxuICBpZiAoQ2hlY2tzLmlzX2JvdW5kKHBhdHRlcm4pKSB7XG4gICAgcmV0dXJuIFJlc29sdmVycy5yZXNvbHZlQm91bmQocGF0dGVybik7XG4gIH1cblxuICBpZiAoQ2hlY2tzLmlzX3R5cGUocGF0dGVybikpIHtcbiAgICByZXR1cm4gUmVzb2x2ZXJzLnJlc29sdmVUeXBlKHBhdHRlcm4pO1xuICB9XG5cbiAgaWYgKENoZWNrcy5pc19hcnJheShwYXR0ZXJuKSkge1xuICAgIHJldHVybiBSZXNvbHZlcnMucmVzb2x2ZUFycmF5KHBhdHRlcm4pO1xuICB9XG5cbiAgaWYgKENoZWNrcy5pc19udW1iZXIocGF0dGVybikpIHtcbiAgICByZXR1cm4gUmVzb2x2ZXJzLnJlc29sdmVOdW1iZXIocGF0dGVybik7XG4gIH1cblxuICBpZiAoQ2hlY2tzLmlzX3N0cmluZyhwYXR0ZXJuKSkge1xuICAgIHJldHVybiBSZXNvbHZlcnMucmVzb2x2ZVN0cmluZyhwYXR0ZXJuKTtcbiAgfVxuXG4gIGlmIChDaGVja3MuaXNfYm9vbGVhbihwYXR0ZXJuKSkge1xuICAgIHJldHVybiBSZXNvbHZlcnMucmVzb2x2ZUJvb2xlYW4ocGF0dGVybik7XG4gIH1cblxuICBpZiAoQ2hlY2tzLmlzX3N5bWJvbChwYXR0ZXJuKSkge1xuICAgIHJldHVybiBSZXNvbHZlcnMucmVzb2x2ZVN5bWJvbChwYXR0ZXJuKTtcbiAgfVxuXG4gIGlmIChDaGVja3MuaXNfbnVsbChwYXR0ZXJuKSkge1xuICAgIHJldHVybiBSZXNvbHZlcnMucmVzb2x2ZU51bGwocGF0dGVybik7XG4gIH1cblxuICBpZiAoQ2hlY2tzLmlzX29iamVjdChwYXR0ZXJuKSkge1xuICAgIHJldHVybiBSZXNvbHZlcnMucmVzb2x2ZU9iamVjdChwYXR0ZXJuKTtcbiAgfVxuXG4gIHJldHVybiBSZXNvbHZlcnMucmVzb2x2ZU5vTWF0Y2goKTtcbn1cblxuY2xhc3MgTWF0Y2hFcnJvciBleHRlbmRzIEVycm9yIHtcbiAgY29uc3RydWN0b3IoYXJnKSB7XG4gICAgc3VwZXIoKTtcblxuICAgIGlmICh0eXBlb2YgYXJnID09PSAnc3ltYm9sJykge1xuICAgICAgdGhpcy5tZXNzYWdlID0gJ05vIG1hdGNoIGZvcjogJyArIGFyZy50b1N0cmluZygpO1xuICAgIH0gZWxzZSBpZiAoQXJyYXkuaXNBcnJheShhcmcpKSB7XG4gICAgICBsZXQgbWFwcGVkVmFsdWVzID0gYXJnLm1hcCh4ID0+IHgudG9TdHJpbmcoKSk7XG4gICAgICB0aGlzLm1lc3NhZ2UgPSAnTm8gbWF0Y2ggZm9yOiAnICsgbWFwcGVkVmFsdWVzO1xuICAgIH0gZWxzZSB7XG4gICAgICB0aGlzLm1lc3NhZ2UgPSAnTm8gbWF0Y2ggZm9yOiAnICsgYXJnO1xuICAgIH1cblxuICAgIHRoaXMuc3RhY2sgPSBuZXcgRXJyb3IoKS5zdGFjaztcbiAgICB0aGlzLm5hbWUgPSB0aGlzLmNvbnN0cnVjdG9yLm5hbWU7XG4gIH1cbn1cblxuY2xhc3MgQ2FzZSB7XG5cbiAgY29uc3RydWN0b3IocGF0dGVybiwgZm4sIGd1YXJkID0gKCkgPT4gdHJ1ZSkge1xuICAgIHRoaXMucGF0dGVybiA9IGJ1aWxkTWF0Y2gocGF0dGVybik7XG4gICAgdGhpcy5mbiA9IGZuO1xuICAgIHRoaXMuZ3VhcmQgPSBndWFyZDtcbiAgfVxufVxuXG5mdW5jdGlvbiBtYWtlX2Nhc2UocGF0dGVybiwgZm4sIGd1YXJkID0gKCkgPT4gdHJ1ZSkge1xuICByZXR1cm4gbmV3IENhc2UocGF0dGVybiwgZm4sIGd1YXJkKTtcbn1cblxuZnVuY3Rpb24gZGVmbWF0Y2goLi4uY2FzZXMpIHtcbiAgcmV0dXJuIGZ1bmN0aW9uICguLi5hcmdzKSB7XG4gICAgZm9yIChsZXQgcHJvY2Vzc2VkQ2FzZSBvZiBjYXNlcykge1xuICAgICAgbGV0IHJlc3VsdCA9IFtdO1xuICAgICAgaWYgKHByb2Nlc3NlZENhc2UucGF0dGVybihhcmdzLCByZXN1bHQpICYmIHByb2Nlc3NlZENhc2UuZ3VhcmQuYXBwbHkodGhpcywgcmVzdWx0KSkge1xuICAgICAgICByZXR1cm4gcHJvY2Vzc2VkQ2FzZS5mbi5hcHBseSh0aGlzLCByZXN1bHQpO1xuICAgICAgfVxuICAgIH1cblxuICAgIHRocm93IG5ldyBNYXRjaEVycm9yKGFyZ3MpO1xuICB9O1xufVxuXG5mdW5jdGlvbiBtYXRjaChwYXR0ZXJuLCBleHByLCBndWFyZCA9ICgpID0+IHRydWUpIHtcbiAgbGV0IHJlc3VsdCA9IFtdO1xuICBsZXQgcHJvY2Vzc2VkUGF0dGVybiA9IGJ1aWxkTWF0Y2gocGF0dGVybik7XG4gIGlmIChwcm9jZXNzZWRQYXR0ZXJuKGV4cHIsIHJlc3VsdCkgJiYgZ3VhcmQuYXBwbHkodGhpcywgcmVzdWx0KSkge1xuICAgIHJldHVybiByZXN1bHQ7XG4gIH0gZWxzZSB7XG4gICAgdGhyb3cgbmV3IE1hdGNoRXJyb3IoZXhwcik7XG4gIH1cbn1cblxuZnVuY3Rpb24gbWF0Y2hfbm9fdGhyb3cocGF0dGVybiwgZXhwciwgZ3VhcmQgPSAoKSA9PiB0cnVlKSB7XG4gIHRyeSB7XG4gICAgcmV0dXJuIG1hdGNoKHBhdHRlcm4sIGV4cHIsIGd1YXJkKTtcbiAgfSBjYXRjaCAoZSkge1xuICAgIGlmIChlIGluc3RhbmNlb2YgTWF0Y2hFcnJvcikge1xuICAgICAgcmV0dXJuIG51bGw7XG4gICAgfVxuXG4gICAgdGhyb3cgZTtcbiAgfVxufVxuXG52YXIgUGF0dGVybnMgPSB7XG4gIGRlZm1hdGNoLCBtYXRjaCwgTWF0Y2hFcnJvciwgbWF0Y2hfbm9fdGhyb3csXG4gIHZhcmlhYmxlLCB3aWxkY2FyZCwgc3RhcnRzV2l0aCxcbiAgY2FwdHVyZSwgaGVhZFRhaWwsIHR5cGUsIGJvdW5kLCBDYXNlLCBtYWtlX2Nhc2Vcbn07XG5cbmZ1bmN0aW9uIGNhbGxfcHJvcGVydHkoaXRlbSwgcHJvcGVydHkpIHtcbiAgaWYgKHByb3BlcnR5IGluIGl0ZW0pIHtcbiAgICBpdGVtW3Byb3BlcnR5XTtcbiAgICBpZiAoaXRlbVtwcm9wZXJ0eV0gaW5zdGFuY2VvZiBGdW5jdGlvbikge1xuICAgICAgcmV0dXJuIGl0ZW1bcHJvcGVydHldKCk7XG4gICAgfSBlbHNlIHtcbiAgICAgIHJldHVybiBpdGVtW3Byb3BlcnR5XTtcbiAgICB9XG4gIH0gZWxzZSBpZiAoU3ltYm9sLmZvcihwcm9wZXJ0eSkgaW4gaXRlbSkge1xuICAgIGxldCBwcm9wID0gU3ltYm9sLmZvcihwcm9wZXJ0eSk7XG4gICAgaWYgKGl0ZW1bcHJvcF0gaW5zdGFuY2VvZiBGdW5jdGlvbikge1xuICAgICAgcmV0dXJuIGl0ZW1bcHJvcF0oKTtcbiAgICB9IGVsc2Uge1xuICAgICAgcmV0dXJuIGl0ZW1bcHJvcF07XG4gICAgfVxuICB9XG5cbiAgdGhyb3cgbmV3IEVycm9yKGBQcm9wZXJ0eSAkeyBwcm9wZXJ0eSB9IG5vdCBmb3VuZCBpbiAkeyBpdGVtIH1gKTtcbn1cblxuZnVuY3Rpb24gYXBwbHkoLi4uYXJncykge1xuICBpZiAoYXJncy5sZW5ndGggPT09IDIpIHtcbiAgICBhcmdzWzBdLmFwcGx5KG51bGwsIGFyZ3Muc2xpY2UoMSkpO1xuICB9IGVsc2Uge1xuICAgIGFyZ3NbMF1bYXJnc1sxXV0uYXBwbHkobnVsbCwgYXJncy5zbGljZSgyKSk7XG4gIH1cbn1cblxuZnVuY3Rpb24gY29udGFpbnMobGVmdCwgcmlnaHQpIHtcbiAgZm9yIChsZXQgeCBvZiByaWdodCkge1xuICAgIGlmIChQYXR0ZXJucy5tYXRjaF9ub190aHJvdyhsZWZ0LCB4KSAhPSBudWxsKSB7XG4gICAgICByZXR1cm4gdHJ1ZTtcbiAgICB9XG4gIH1cblxuICByZXR1cm4gZmFsc2U7XG59XG5cbmZ1bmN0aW9uIGdldF9nbG9iYWwoKSB7XG4gIGlmICh0eXBlb2Ygc2VsZiAhPT0gJ3VuZGVmaW5lZCcpIHtcbiAgICByZXR1cm4gc2VsZjtcbiAgfSBlbHNlIGlmICh0eXBlb2Ygd2luZG93ICE9PSAndW5kZWZpbmVkJykge1xuICAgIHJldHVybiB3aW5kb3c7XG4gIH0gZWxzZSBpZiAodHlwZW9mIGdsb2JhbCAhPT0gJ3VuZGVmaW5lZCcpIHtcbiAgICByZXR1cm4gZ2xvYmFsO1xuICB9XG5cbiAgdGhyb3cgbmV3IEVycm9yKCdObyBnbG9iYWwgc3RhdGUgZm91bmQnKTtcbn1cblxuZnVuY3Rpb24gZGVmc3RydWN0KGRlZmF1bHRzKSB7XG4gIHJldHVybiBjbGFzcyB7XG4gICAgY29uc3RydWN0b3IodXBkYXRlID0ge30pIHtcbiAgICAgIGxldCB0aGVfdmFsdWVzID0gT2JqZWN0LmFzc2lnbihkZWZhdWx0cywgdXBkYXRlKTtcbiAgICAgIE9iamVjdC5hc3NpZ24odGhpcywgdGhlX3ZhbHVlcyk7XG4gICAgfVxuXG4gICAgc3RhdGljIGNyZWF0ZSh1cGRhdGVzID0ge30pIHtcbiAgICAgIGxldCB4ID0gbmV3IHRoaXModXBkYXRlcyk7XG4gICAgICByZXR1cm4gT2JqZWN0LmZyZWV6ZSh4KTtcbiAgICB9XG4gIH07XG59XG5cbmZ1bmN0aW9uIGRlZmV4Y2VwdGlvbihkZWZhdWx0cykge1xuICByZXR1cm4gY2xhc3MgZXh0ZW5kcyBFcnJvciB7XG4gICAgY29uc3RydWN0b3IodXBkYXRlID0ge30pIHtcbiAgICAgIGxldCBtZXNzYWdlID0gdXBkYXRlLm1lc3NhZ2UgfHwgJyc7XG4gICAgICBzdXBlcihtZXNzYWdlKTtcblxuICAgICAgbGV0IHRoZV92YWx1ZXMgPSBPYmplY3QuYXNzaWduKGRlZmF1bHRzLCB1cGRhdGUpO1xuICAgICAgT2JqZWN0LmFzc2lnbih0aGlzLCB0aGVfdmFsdWVzKTtcblxuICAgICAgdGhpcy5uYW1lID0gdGhpcy5jb25zdHJ1Y3Rvci5uYW1lO1xuICAgICAgdGhpcy5tZXNzYWdlID0gbWVzc2FnZTtcbiAgICAgIHRoaXNbU3BlY2lhbEZvcm1zLmF0b20oJ19fZXhjZXB0aW9uX18nKV0gPSB0cnVlO1xuICAgICAgRXJyb3IuY2FwdHVyZVN0YWNrVHJhY2UodGhpcywgdGhpcy5jb25zdHJ1Y3Rvci5uYW1lKTtcbiAgICB9XG5cbiAgICBzdGF0aWMgY3JlYXRlKHVwZGF0ZXMgPSB7fSkge1xuICAgICAgbGV0IHggPSBuZXcgdGhpcyh1cGRhdGVzKTtcbiAgICAgIHJldHVybiBPYmplY3QuZnJlZXplKHgpO1xuICAgIH1cbiAgfTtcbn1cblxuZnVuY3Rpb24gZGVmcHJvdG9jb2woc3BlYykge1xuICByZXR1cm4gbmV3IFByb3RvY29sKHNwZWMpO1xufVxuXG5mdW5jdGlvbiBkZWZpbXBsKHByb3RvY29sLCB0eXBlLCBpbXBsKSB7XG4gIHByb3RvY29sLmltcGxlbWVudGF0aW9uKHR5cGUsIGltcGwpO1xufVxuXG5mdW5jdGlvbiBnZXRfb2JqZWN0X2tleXMob2JqKSB7XG4gIHJldHVybiBPYmplY3Qua2V5cyhvYmopLmNvbmNhdChPYmplY3QuZ2V0T3duUHJvcGVydHlTeW1ib2xzKG9iaikpO1xufVxuXG5mdW5jdGlvbiBpc192YWxpZF9jaGFyYWN0ZXIoY29kZXBvaW50KSB7XG4gIHRyeSB7XG4gICAgcmV0dXJuIFN0cmluZy5mcm9tQ29kZVBvaW50KGNvZGVwb2ludCkgIT0gbnVsbDtcbiAgfSBjYXRjaCAoZSkge1xuICAgIHJldHVybiBmYWxzZTtcbiAgfVxufVxuXG4vL2h0dHBzOi8vZGV2ZWxvcGVyLm1vemlsbGEub3JnL2VuLVVTL2RvY3MvV2ViL0FQSS9XaW5kb3dCYXNlNjQvQmFzZTY0X2VuY29kaW5nX2FuZF9kZWNvZGluZyNTb2x1dGlvbl8yXyVFMiU4MCU5M19yZXdyaXRlX3RoZV9ET01zX2F0b2IoKV9hbmRfYnRvYSgpX3VzaW5nX0phdmFTY3JpcHQnc19UeXBlZEFycmF5c19hbmRfVVRGLThcbmZ1bmN0aW9uIGI2NEVuY29kZVVuaWNvZGUoc3RyKSB7XG4gIHJldHVybiBidG9hKGVuY29kZVVSSUNvbXBvbmVudChzdHIpLnJlcGxhY2UoLyUoWzAtOUEtRl17Mn0pL2csIGZ1bmN0aW9uIChtYXRjaCwgcDEpIHtcbiAgICByZXR1cm4gU3RyaW5nLmZyb21DaGFyQ29kZSgnMHgnICsgcDEpO1xuICB9KSk7XG59XG5cbmZ1bmN0aW9uIGRlbGV0ZV9wcm9wZXJ0eV9mcm9tX21hcChtYXAsIHByb3BlcnR5KSB7XG4gIGxldCBuZXdfbWFwID0gT2JqZWN0LmFzc2lnbihPYmplY3QuY3JlYXRlKG1hcC5jb25zdHJ1Y3Rvci5wcm90b3R5cGUpLCBtYXApO1xuICBkZWxldGUgbmV3X21hcFtwcm9wZXJ0eV07XG5cbiAgcmV0dXJuIE9iamVjdC5mcmVlemUobmV3X21hcCk7XG59XG5cbmZ1bmN0aW9uIGNsYXNzX3RvX29iaihtYXApIHtcbiAgbGV0IG5ld19tYXAgPSBPYmplY3QuYXNzaWduKHt9LCBtYXApO1xuICByZXR1cm4gT2JqZWN0LmZyZWV6ZShuZXdfbWFwKTtcbn1cblxuZnVuY3Rpb24gYWRkX3Byb3BlcnR5X3RvX21hcChtYXAsIHByb3BlcnR5LCB2YWx1ZSkge1xuICBsZXQgbmV3X21hcCA9IE9iamVjdC5hc3NpZ24oe30sIG1hcCk7XG4gIG5ld19tYXBbcHJvcGVydHldID0gdmFsdWU7XG4gIHJldHVybiBPYmplY3QuZnJlZXplKG5ld19tYXApO1xufVxuXG5mdW5jdGlvbiBibm90KGV4cHIpIHtcbiAgcmV0dXJuIH5leHByO1xufVxuXG5mdW5jdGlvbiBiYW5kKGxlZnQsIHJpZ2h0KSB7XG4gIHJldHVybiBsZWZ0ICYgcmlnaHQ7XG59XG5cbmZ1bmN0aW9uIGJvcihsZWZ0LCByaWdodCkge1xuICByZXR1cm4gbGVmdCB8IHJpZ2h0O1xufVxuXG5mdW5jdGlvbiBic2wobGVmdCwgcmlnaHQpIHtcbiAgcmV0dXJuIGxlZnQgPDwgcmlnaHQ7XG59XG5cbmZ1bmN0aW9uIGJzcihsZWZ0LCByaWdodCkge1xuICByZXR1cm4gbGVmdCA+PiByaWdodDtcbn1cblxuZnVuY3Rpb24gYnhvcihsZWZ0LCByaWdodCkge1xuICByZXR1cm4gbGVmdCBeIHJpZ2h0O1xufVxuXG5mdW5jdGlvbiB6aXAobGlzdF9vZl9saXN0cykge1xuICBpZiAobGlzdF9vZl9saXN0cy5sZW5ndGggPT09IDApIHtcbiAgICByZXR1cm4gT2JqZWN0LmZyZWV6ZShbXSk7XG4gIH1cblxuICBsZXQgbmV3X3ZhbHVlID0gW107XG4gIGxldCBzbWFsbGVzdF9sZW5ndGggPSBsaXN0X29mX2xpc3RzWzBdO1xuXG4gIGZvciAobGV0IHggb2YgbGlzdF9vZl9saXN0cykge1xuICAgIGlmICh4Lmxlbmd0aCA8IHNtYWxsZXN0X2xlbmd0aCkge1xuICAgICAgc21hbGxlc3RfbGVuZ3RoID0geC5sZW5ndGg7XG4gICAgfVxuICB9XG5cbiAgZm9yIChsZXQgaSA9IDA7IGkgPCBzbWFsbGVzdF9sZW5ndGg7IGkrKykge1xuICAgIGxldCBjdXJyZW50X3ZhbHVlID0gW107XG4gICAgZm9yIChsZXQgaiA9IDA7IGogPCBsaXN0X29mX2xpc3RzLmxlbmd0aDsgaisrKSB7XG4gICAgICBjdXJyZW50X3ZhbHVlLnB1c2gobGlzdF9vZl9saXN0c1tqXVtpXSk7XG4gICAgfVxuXG4gICAgbmV3X3ZhbHVlLnB1c2gobmV3IFR1cGxlKC4uLmN1cnJlbnRfdmFsdWUpKTtcbiAgfVxuXG4gIHJldHVybiBPYmplY3QuZnJlZXplKG5ld192YWx1ZSk7XG59XG5cbmZ1bmN0aW9uIGNhbl9kZWNvZGU2NChkYXRhKSB7XG4gIHRyeSB7XG4gICAgYXRvYihkYXRhKTtcbiAgICByZXR1cm4gdHJ1ZTtcbiAgfSBjYXRjaCAoZSkge1xuICAgIHJldHVybiBmYWxzZTtcbiAgfVxufVxuXG52YXIgRnVuY3Rpb25zID0ge1xuICBjYWxsX3Byb3BlcnR5LFxuICBhcHBseSxcbiAgY29udGFpbnMsXG4gIGdldF9nbG9iYWwsXG4gIGRlZnN0cnVjdCxcbiAgZGVmZXhjZXB0aW9uLFxuICBkZWZwcm90b2NvbCxcbiAgZGVmaW1wbCxcbiAgZ2V0X29iamVjdF9rZXlzLFxuICBpc192YWxpZF9jaGFyYWN0ZXIsXG4gIGI2NEVuY29kZVVuaWNvZGUsXG4gIGRlbGV0ZV9wcm9wZXJ0eV9mcm9tX21hcCxcbiAgYWRkX3Byb3BlcnR5X3RvX21hcCxcbiAgY2xhc3NfdG9fb2JqLFxuICBjYW5fZGVjb2RlNjQsXG4gIGJub3QsXG4gIGJhbmQsXG4gIGJvcixcbiAgYnNsLFxuICBic3IsXG4gIGJ4b3IsXG4gIHppcFxufTtcblxuZnVuY3Rpb24gbGlzdCguLi5hcmdzKSB7XG4gIHJldHVybiBPYmplY3QuZnJlZXplKGFyZ3MpO1xufVxuXG5mdW5jdGlvbiBiaXRzdHJpbmcoLi4uYXJncykge1xuICByZXR1cm4gbmV3IEJpdFN0cmluZyguLi5hcmdzKTtcbn1cblxuZnVuY3Rpb24gdHVwbGUoLi4uYXJncykge1xuICByZXR1cm4gbmV3IFR1cGxlKC4uLmFyZ3MpO1xufVxuXG5mdW5jdGlvbiBfY2FzZShjb25kaXRpb24sIGNsYXVzZXMpIHtcbiAgcmV0dXJuIFBhdHRlcm5zLmRlZm1hdGNoKC4uLmNsYXVzZXMpKGNvbmRpdGlvbik7XG59XG5cbmZ1bmN0aW9uIGNvbmQoY2xhdXNlcykge1xuICBmb3IgKGxldCBjbGF1c2Ugb2YgY2xhdXNlcykge1xuICAgIGlmIChjbGF1c2VbMF0pIHtcbiAgICAgIHJldHVybiBjbGF1c2VbMV0oKTtcbiAgICB9XG4gIH1cblxuICB0aHJvdyBuZXcgRXJyb3IoKTtcbn1cblxuZnVuY3Rpb24gbWFwKG9iaikge1xuICByZXR1cm4gT2JqZWN0LmZyZWV6ZShvYmopO1xufVxuXG5mdW5jdGlvbiBtYXBfdXBkYXRlKG1hcCwgdmFsdWVzKSB7XG4gIHJldHVybiBPYmplY3QuZnJlZXplKE9iamVjdC5hc3NpZ24oT2JqZWN0LmNyZWF0ZShtYXAuY29uc3RydWN0b3IucHJvdG90eXBlKSwgbWFwLCB2YWx1ZXMpKTtcbn1cblxuZnVuY3Rpb24gX2Zvcihjb2xsZWN0aW9ucywgZnVuLCBmaWx0ZXIgPSAoKSA9PiB0cnVlLCBpbnRvID0gW10sIHByZXZpb3VzVmFsdWVzID0gW10pIHtcbiAgbGV0IHBhdHRlcm4gPSBjb2xsZWN0aW9uc1swXVswXTtcbiAgbGV0IGNvbGxlY3Rpb24gPSBjb2xsZWN0aW9uc1swXVsxXTtcblxuICBpZiAoY29sbGVjdGlvbnMubGVuZ3RoID09PSAxKSB7XG5cbiAgICBmb3IgKGxldCBlbGVtIG9mIGNvbGxlY3Rpb24pIHtcbiAgICAgIGxldCByID0gUGF0dGVybnMubWF0Y2hfbm9fdGhyb3cocGF0dGVybiwgZWxlbSk7XG4gICAgICBsZXQgYXJncyA9IHByZXZpb3VzVmFsdWVzLmNvbmNhdChyKTtcblxuICAgICAgaWYgKHIgJiYgZmlsdGVyLmFwcGx5KHRoaXMsIGFyZ3MpKSB7XG4gICAgICAgIGludG8gPSBpbnRvLmNvbmNhdChbZnVuLmFwcGx5KHRoaXMsIGFyZ3MpXSk7XG4gICAgICB9XG4gICAgfVxuXG4gICAgcmV0dXJuIGludG87XG4gIH0gZWxzZSB7XG4gICAgbGV0IF9pbnRvID0gW107XG5cbiAgICBmb3IgKGxldCBlbGVtIG9mIGNvbGxlY3Rpb24pIHtcbiAgICAgIGxldCByID0gUGF0dGVybnMubWF0Y2hfbm9fdGhyb3cocGF0dGVybiwgZWxlbSk7XG4gICAgICBpZiAocikge1xuICAgICAgICBfaW50byA9IGludG8uY29uY2F0KHRoaXMuX2Zvcihjb2xsZWN0aW9ucy5zbGljZSgxKSwgZnVuLCBmaWx0ZXIsIF9pbnRvLCBwcmV2aW91c1ZhbHVlcy5jb25jYXQocikpKTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICByZXR1cm4gX2ludG87XG4gIH1cbn1cblxuZnVuY3Rpb24gX3RyeShkb19mdW4sIHJlc2N1ZV9mdW5jdGlvbiwgY2F0Y2hfZnVuLCBlbHNlX2Z1bmN0aW9uLCBhZnRlcl9mdW5jdGlvbikge1xuICBsZXQgcmVzdWx0ID0gbnVsbDtcblxuICB0cnkge1xuICAgIHJlc3VsdCA9IGRvX2Z1bigpO1xuICB9IGNhdGNoIChlKSB7XG4gICAgbGV0IGV4X3Jlc3VsdCA9IG51bGw7XG5cbiAgICBpZiAocmVzY3VlX2Z1bmN0aW9uKSB7XG4gICAgICB0cnkge1xuICAgICAgICBleF9yZXN1bHQgPSByZXNjdWVfZnVuY3Rpb24oZSk7XG4gICAgICAgIHJldHVybiBleF9yZXN1bHQ7XG4gICAgICB9IGNhdGNoIChleCkge1xuICAgICAgICBpZiAoZXggaW5zdGFuY2VvZiBQYXR0ZXJucy5NYXRjaEVycm9yKSB7XG4gICAgICAgICAgdGhyb3cgZXg7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9XG5cbiAgICBpZiAoY2F0Y2hfZnVuKSB7XG4gICAgICB0cnkge1xuICAgICAgICBleF9yZXN1bHQgPSBjYXRjaF9mdW4oZSk7XG4gICAgICAgIHJldHVybiBleF9yZXN1bHQ7XG4gICAgICB9IGNhdGNoIChleCkge1xuICAgICAgICBpZiAoZXggaW5zdGFuY2VvZiBQYXR0ZXJucy5NYXRjaEVycm9yKSB7XG4gICAgICAgICAgdGhyb3cgZXg7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9XG5cbiAgICB0aHJvdyBlO1xuICB9IGZpbmFsbHkge1xuICAgIGlmIChhZnRlcl9mdW5jdGlvbikge1xuICAgICAgYWZ0ZXJfZnVuY3Rpb24oKTtcbiAgICB9XG4gIH1cblxuICBpZiAoZWxzZV9mdW5jdGlvbikge1xuICAgIHRyeSB7XG4gICAgICByZXR1cm4gZWxzZV9mdW5jdGlvbihyZXN1bHQpO1xuICAgIH0gY2F0Y2ggKGV4KSB7XG4gICAgICBpZiAoZXggaW5zdGFuY2VvZiBQYXR0ZXJucy5NYXRjaEVycm9yKSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcignTm8gTWF0Y2ggRm91bmQgaW4gRWxzZScpO1xuICAgICAgfVxuXG4gICAgICB0aHJvdyBleDtcbiAgICB9XG4gIH0gZWxzZSB7XG4gICAgcmV0dXJuIHJlc3VsdDtcbiAgfVxufVxuXG52YXIgc3BlY2lhbF9mb3JtcyA9IHtcbiAgbGlzdCxcbiAgYml0c3RyaW5nLFxuICB0dXBsZSxcbiAgX2Nhc2UsXG4gIGNvbmQsXG4gIG1hcCxcbiAgbWFwX3VwZGF0ZSxcbiAgX2ZvcixcbiAgX3RyeVxufTtcblxuRnVuY3Rpb25zLmdldF9nbG9iYWwoKS5wcm9jZXNzZXMgPSBGdW5jdGlvbnMuZ2V0X2dsb2JhbCgpLnByb2Nlc3NlcyB8fCBuZXcgUHJvY2Vzc1N5c3RlbSgpO1xuXG5cblxudmFyIEMgPSBPYmplY3QuZnJlZXplKHtcblx0UHJvY2Vzc1N5c3RlbTogUHJvY2Vzc1N5c3RlbSxcblx0VHVwbGU6IFR1cGxlLFxuXHRQSUQ6IFBJRCxcblx0Qml0U3RyaW5nOiBCaXRTdHJpbmcsXG5cdFBhdHRlcm5zOiBQYXR0ZXJucyxcblx0SW50ZWdlcjogSW50ZWdlcixcblx0RmxvYXQ6IEZsb2F0LFxuXHRGdW5jdGlvbnM6IEZ1bmN0aW9ucyxcblx0TGlzdDogTGlzdCxcblx0U3BlY2lhbEZvcm1zOiBzcGVjaWFsX2Zvcm1zXG59KTtcblxubGV0IEVudW0gPSB7XG5cbiAgYWxsX19xbWFya19fOiBmdW5jdGlvbiAoY29sbGVjdGlvbiwgZnVuID0geCA9PiB4KSB7XG4gICAgZm9yIChsZXQgZWxlbSBvZiBjb2xsZWN0aW9uKSB7XG4gICAgICBpZiAoIWZ1bihlbGVtKSkge1xuICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICB9XG4gICAgfVxuXG4gICAgcmV0dXJuIHRydWU7XG4gIH0sXG5cbiAgYW55X19xbWFya19fOiBmdW5jdGlvbiAoY29sbGVjdGlvbiwgZnVuID0geCA9PiB4KSB7XG4gICAgZm9yIChsZXQgZWxlbSBvZiBjb2xsZWN0aW9uKSB7XG4gICAgICBpZiAoZnVuKGVsZW0pKSB7XG4gICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgfVxuICAgIH1cblxuICAgIHJldHVybiBmYWxzZTtcbiAgfSxcblxuICBhdDogZnVuY3Rpb24gKGNvbGxlY3Rpb24sIG4sIHRoZV9kZWZhdWx0ID0gbnVsbCkge1xuICAgIGlmIChuID4gdGhpcy5jb3VudChjb2xsZWN0aW9uKSB8fCBuIDwgMCkge1xuICAgICAgcmV0dXJuIHRoZV9kZWZhdWx0O1xuICAgIH1cblxuICAgIHJldHVybiBjb2xsZWN0aW9uW25dO1xuICB9LFxuXG4gIGNvbmNhdDogZnVuY3Rpb24gKC4uLmVudW1hYmxlcykge1xuICAgIHJldHVybiBlbnVtYWJsZXNbMF0uY29uY2F0KGVudW1hYmxlc1sxXSk7XG4gIH0sXG5cbiAgY291bnQ6IGZ1bmN0aW9uIChjb2xsZWN0aW9uLCBmdW4gPSBudWxsKSB7XG4gICAgaWYgKGZ1biA9PSBudWxsKSB7XG4gICAgICByZXR1cm4gY29sbGVjdGlvbi5sZW5ndGg7XG4gICAgfSBlbHNlIHtcbiAgICAgIHJldHVybiBjb2xsZWN0aW9uLmZpbHRlcihmdW4pLmxlbmd0aDtcbiAgICB9XG4gIH0sXG5cbiAgZHJvcDogZnVuY3Rpb24gKGNvbGxlY3Rpb24sIGNvdW50KSB7XG4gICAgcmV0dXJuIGNvbGxlY3Rpb24uc2xpY2UoY291bnQpO1xuICB9LFxuXG4gIGRyb3Bfd2hpbGU6IGZ1bmN0aW9uIChjb2xsZWN0aW9uLCBmdW4pIHtcbiAgICBsZXQgY291bnQgPSAwO1xuXG4gICAgZm9yIChsZXQgZWxlbSBvZiBjb2xsZWN0aW9uKSB7XG4gICAgICBpZiAoZnVuKGVsZW0pKSB7XG4gICAgICAgIGNvdW50ID0gY291bnQgKyAxO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgYnJlYWs7XG4gICAgICB9XG4gICAgfVxuXG4gICAgcmV0dXJuIGNvbGxlY3Rpb24uc2xpY2UoY291bnQpO1xuICB9LFxuXG4gIGVhY2g6IGZ1bmN0aW9uIChjb2xsZWN0aW9uLCBmdW4pIHtcbiAgICBmb3IgKGxldCBlbGVtIG9mIGNvbGxlY3Rpb24pIHtcbiAgICAgIGZ1bihlbGVtKTtcbiAgICB9XG4gIH0sXG5cbiAgZW1wdHlfX3FtYXJrX186IGZ1bmN0aW9uIChjb2xsZWN0aW9uKSB7XG4gICAgcmV0dXJuIGNvbGxlY3Rpb24ubGVuZ3RoID09PSAwO1xuICB9LFxuXG4gIGZldGNoOiBmdW5jdGlvbiAoY29sbGVjdGlvbiwgbikge1xuICAgIGlmIChBcnJheS5pc0FycmF5KGNvbGxlY3Rpb24pKSB7XG4gICAgICBpZiAobiA8IHRoaXMuY291bnQoY29sbGVjdGlvbikgJiYgbiA+PSAwKSB7XG4gICAgICAgIHJldHVybiBuZXcgVHVwbGUoU3ltYm9sLmZvcihcIm9rXCIpLCBjb2xsZWN0aW9uW25dKTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHJldHVybiBTeW1ib2wuZm9yKFwiZXJyb3JcIik7XG4gICAgICB9XG4gICAgfVxuXG4gICAgdGhyb3cgbmV3IEVycm9yKFwiY29sbGVjdGlvbiBpcyBub3QgYW4gRW51bWVyYWJsZVwiKTtcbiAgfSxcblxuICBmZXRjaF9fZW1hcmtfXzogZnVuY3Rpb24gKGNvbGxlY3Rpb24sIG4pIHtcbiAgICBpZiAoQXJyYXkuaXNBcnJheShjb2xsZWN0aW9uKSkge1xuICAgICAgaWYgKG4gPCB0aGlzLmNvdW50KGNvbGxlY3Rpb24pICYmIG4gPj0gMCkge1xuICAgICAgICByZXR1cm4gY29sbGVjdGlvbltuXTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcihcIm91dCBvZiBib3VuZHMgZXJyb3JcIik7XG4gICAgICB9XG4gICAgfVxuXG4gICAgdGhyb3cgbmV3IEVycm9yKFwiY29sbGVjdGlvbiBpcyBub3QgYW4gRW51bWVyYWJsZVwiKTtcbiAgfSxcblxuICBmaWx0ZXI6IGZ1bmN0aW9uIChjb2xsZWN0aW9uLCBmdW4pIHtcbiAgICBsZXQgcmVzdWx0ID0gW107XG5cbiAgICBmb3IgKGxldCBlbGVtIG9mIGNvbGxlY3Rpb24pIHtcbiAgICAgIGlmIChmdW4oZWxlbSkpIHtcbiAgICAgICAgcmVzdWx0LnB1c2goZWxlbSk7XG4gICAgICB9XG4gICAgfVxuXG4gICAgcmV0dXJuIHJlc3VsdDtcbiAgfSxcblxuICBmaWx0ZXJfbWFwOiBmdW5jdGlvbiAoY29sbGVjdGlvbiwgZmlsdGVyLCBtYXBwZXIpIHtcbiAgICByZXR1cm4gRW51bS5tYXAoRW51bS5maWx0ZXIoY29sbGVjdGlvbiwgZmlsdGVyKSwgbWFwcGVyKTtcbiAgfSxcblxuICBmaW5kOiBmdW5jdGlvbiAoY29sbGVjdGlvbiwgaWZfbm9uZSA9IG51bGwsIGZ1bikge1xuICAgIGZvciAobGV0IGVsZW0gb2YgY29sbGVjdGlvbikge1xuICAgICAgaWYgKGZ1bihlbGVtKSkge1xuICAgICAgICByZXR1cm4gZWxlbTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICByZXR1cm4gaWZfbm9uZTtcbiAgfSxcblxuICBpbnRvOiBmdW5jdGlvbiAoY29sbGVjdGlvbiwgbGlzdCkge1xuICAgIHJldHVybiBsaXN0LmNvbmNhdChjb2xsZWN0aW9uKTtcbiAgfSxcblxuICBtYXA6IGZ1bmN0aW9uIChjb2xsZWN0aW9uLCBmdW4pIHtcbiAgICBsZXQgcmVzdWx0ID0gW107XG5cbiAgICBmb3IgKGxldCBlbGVtIG9mIGNvbGxlY3Rpb24pIHtcbiAgICAgIHJlc3VsdC5wdXNoKGZ1bihlbGVtKSk7XG4gICAgfVxuXG4gICAgcmV0dXJuIHJlc3VsdDtcbiAgfSxcblxuICBtYXBfcmVkdWNlOiBmdW5jdGlvbiAoY29sbGVjdGlvbiwgYWNjLCBmdW4pIHtcbiAgICBsZXQgbWFwcGVkID0gTGlzdCgpO1xuICAgIGxldCB0aGVfYWNjID0gYWNjO1xuXG4gICAgZm9yICh2YXIgaSA9IDA7IGkgPCB0aGlzLmNvdW50KGNvbGxlY3Rpb24pOyBpKyspIHtcbiAgICAgIGxldCB0dXBsZSA9IGZ1bihjb2xsZWN0aW9uW2ldLCB0aGVfYWNjKTtcblxuICAgICAgdGhlX2FjYyA9IHR1cGxlLmdldCgxKTtcbiAgICAgIG1hcHBlZCA9IExpc3QoLi4ubWFwcGVkLmNvbmNhdChbdHVwbGUuZ2V0KDApXSkpO1xuICAgIH1cblxuICAgIHJldHVybiBuZXcgVHVwbGUobWFwcGVkLCB0aGVfYWNjKTtcbiAgfSxcblxuICBtZW1iZXJfX3FtYXJrX186IGZ1bmN0aW9uIChjb2xsZWN0aW9uLCB2YWx1ZSkge1xuICAgIHJldHVybiBjb2xsZWN0aW9uLmluY2x1ZGVzKHZhbHVlKTtcbiAgfSxcblxuICByZWR1Y2U6IGZ1bmN0aW9uIChjb2xsZWN0aW9uLCBhY2MsIGZ1bikge1xuICAgIGxldCB0aGVfYWNjID0gYWNjO1xuXG4gICAgZm9yICh2YXIgaSA9IDA7IGkgPCB0aGlzLmNvdW50KGNvbGxlY3Rpb24pOyBpKyspIHtcbiAgICAgIGxldCB0dXBsZSA9IGZ1bihjb2xsZWN0aW9uW2ldLCB0aGVfYWNjKTtcblxuICAgICAgdGhlX2FjYyA9IHR1cGxlLmdldCgxKTtcbiAgICB9XG5cbiAgICByZXR1cm4gdGhlX2FjYztcbiAgfSxcblxuICB0YWtlOiBmdW5jdGlvbiAoY29sbGVjdGlvbiwgY291bnQpIHtcbiAgICByZXR1cm4gY29sbGVjdGlvbi5zbGljZSgwLCBjb3VudCk7XG4gIH0sXG5cbiAgdGFrZV9ldmVyeTogZnVuY3Rpb24gKGNvbGxlY3Rpb24sIG50aCkge1xuICAgIGxldCByZXN1bHQgPSBbXTtcbiAgICBsZXQgaW5kZXggPSAwO1xuXG4gICAgZm9yIChsZXQgZWxlbSBvZiBjb2xsZWN0aW9uKSB7XG4gICAgICBpZiAoaW5kZXggJSBudGggPT09IDApIHtcbiAgICAgICAgcmVzdWx0LnB1c2goZWxlbSk7XG4gICAgICB9XG4gICAgfVxuXG4gICAgcmV0dXJuIExpc3QoLi4ucmVzdWx0KTtcbiAgfSxcblxuICB0YWtlX3doaWxlOiBmdW5jdGlvbiAoY29sbGVjdGlvbiwgZnVuKSB7XG4gICAgbGV0IGNvdW50ID0gMDtcblxuICAgIGZvciAobGV0IGVsZW0gb2YgY29sbGVjdGlvbikge1xuICAgICAgaWYgKGZ1bihlbGVtKSkge1xuICAgICAgICBjb3VudCA9IGNvdW50ICsgMTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIGJyZWFrO1xuICAgICAgfVxuICAgIH1cblxuICAgIHJldHVybiBjb2xsZWN0aW9uLnNsaWNlKDAsIGNvdW50KTtcbiAgfSxcblxuICB0b19saXN0OiBmdW5jdGlvbiAoY29sbGVjdGlvbikge1xuICAgIHJldHVybiBjb2xsZWN0aW9uO1xuICB9XG59O1xuXG5sZXQgVmlydHVhbERPTSA9IChmdW5jdGlvbiAoZSkge1xuICAgIHJldHVybiBlKCk7XG59KShmdW5jdGlvbiAoKSB7XG4gICAgdmFyIGRlZmluZSwgbW9kdWxlLCBleHBvcnRzO1xuICAgIHJldHVybiAoZnVuY3Rpb24gZSh0LCBuLCByKSB7XG4gICAgICAgIGZ1bmN0aW9uIHMobywgdSkge1xuICAgICAgICAgICAgaWYgKCFuW29dKSB7XG4gICAgICAgICAgICAgICAgaWYgKCF0W29dKSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciBhID0gdHlwZW9mIHJlcXVpcmUgPT0gXCJmdW5jdGlvblwiICYmIHJlcXVpcmU7XG4gICAgICAgICAgICAgICAgICAgIGlmICghdSAmJiBhKSByZXR1cm4gYShvLCAhMCk7XG4gICAgICAgICAgICAgICAgICAgIGlmIChpKSByZXR1cm4gaShvLCAhMCk7XG4gICAgICAgICAgICAgICAgICAgIHZhciBmID0gbmV3IEVycm9yKFwiQ2Fubm90IGZpbmQgbW9kdWxlICdcIiArIG8gKyBcIidcIik7XG4gICAgICAgICAgICAgICAgICAgIHRocm93IChmLmNvZGUgPSBcIk1PRFVMRV9OT1RfRk9VTkRcIiwgZik7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHZhciBsID0gbltvXSA9IHtcbiAgICAgICAgICAgICAgICAgICAgZXhwb3J0czoge31cbiAgICAgICAgICAgICAgICB9O1xuICAgICAgICAgICAgICAgIHRbb11bMF0uY2FsbChsLmV4cG9ydHMsIGZ1bmN0aW9uIChlKSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciBuID0gdFtvXVsxXVtlXTtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHMobiA/IG4gOiBlKTtcbiAgICAgICAgICAgICAgICB9LCBsLCBsLmV4cG9ydHMsIGUsIHQsIG4sIHIpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmV0dXJuIG5bb10uZXhwb3J0cztcbiAgICAgICAgfVxuICAgICAgICB2YXIgaSA9IHR5cGVvZiByZXF1aXJlID09IFwiZnVuY3Rpb25cIiAmJiByZXF1aXJlO1xuICAgICAgICBmb3IgKHZhciBvID0gMDsgbyA8IHIubGVuZ3RoOyBvKyspIHMocltvXSk7XG4gICAgICAgIHJldHVybiBzO1xuICAgIH0pKHtcbiAgICAgICAgMTogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHtcblxuICAgICAgICAgICAgdmFyIGNyZWF0ZUVsZW1lbnQgPSByZXF1aXJlKFwiLi92ZG9tL2NyZWF0ZS1lbGVtZW50LmpzXCIpO1xuXG4gICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IGNyZWF0ZUVsZW1lbnQ7XG4gICAgICAgIH0sIHsgXCIuL3Zkb20vY3JlYXRlLWVsZW1lbnQuanNcIjogMTUgfV0sIDI6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICB2YXIgZGlmZiA9IHJlcXVpcmUoXCIuL3Z0cmVlL2RpZmYuanNcIik7XG5cbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gZGlmZjtcbiAgICAgICAgfSwgeyBcIi4vdnRyZWUvZGlmZi5qc1wiOiAzNSB9XSwgMzogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHtcbiAgICAgICAgICAgIHZhciBoID0gcmVxdWlyZShcIi4vdmlydHVhbC1oeXBlcnNjcmlwdC9pbmRleC5qc1wiKTtcblxuICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBoO1xuICAgICAgICB9LCB7IFwiLi92aXJ0dWFsLWh5cGVyc2NyaXB0L2luZGV4LmpzXCI6IDIyIH1dLCA0OiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge1xuICAgICAgICAgICAgdmFyIGRpZmYgPSByZXF1aXJlKFwiLi9kaWZmLmpzXCIpO1xuICAgICAgICAgICAgdmFyIHBhdGNoID0gcmVxdWlyZShcIi4vcGF0Y2guanNcIik7XG4gICAgICAgICAgICB2YXIgaCA9IHJlcXVpcmUoXCIuL2guanNcIik7XG4gICAgICAgICAgICB2YXIgY3JlYXRlID0gcmVxdWlyZShcIi4vY3JlYXRlLWVsZW1lbnQuanNcIik7XG4gICAgICAgICAgICB2YXIgVk5vZGUgPSByZXF1aXJlKFwiLi92bm9kZS92bm9kZS5qc1wiKTtcbiAgICAgICAgICAgIHZhciBWVGV4dCA9IHJlcXVpcmUoXCIuL3Zub2RlL3Z0ZXh0LmpzXCIpO1xuXG4gICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IHtcbiAgICAgICAgICAgICAgICBkaWZmOiBkaWZmLFxuICAgICAgICAgICAgICAgIHBhdGNoOiBwYXRjaCxcbiAgICAgICAgICAgICAgICBoOiBoLFxuICAgICAgICAgICAgICAgIGNyZWF0ZTogY3JlYXRlLFxuICAgICAgICAgICAgICAgIFZOb2RlOiBWTm9kZSxcbiAgICAgICAgICAgICAgICBWVGV4dDogVlRleHRcbiAgICAgICAgICAgIH07XG4gICAgICAgIH0sIHsgXCIuL2NyZWF0ZS1lbGVtZW50LmpzXCI6IDEsIFwiLi9kaWZmLmpzXCI6IDIsIFwiLi9oLmpzXCI6IDMsIFwiLi9wYXRjaC5qc1wiOiAxMywgXCIuL3Zub2RlL3Zub2RlLmpzXCI6IDMxLCBcIi4vdm5vZGUvdnRleHQuanNcIjogMzMgfV0sIDU6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICAvKiFcbiAgICAgICAgICAgICAqIENyb3NzLUJyb3dzZXIgU3BsaXQgMS4xLjFcbiAgICAgICAgICAgICAqIENvcHlyaWdodCAyMDA3LTIwMTIgU3RldmVuIExldml0aGFuIDxzdGV2ZW5sZXZpdGhhbi5jb20+XG4gICAgICAgICAgICAgKiBBdmFpbGFibGUgdW5kZXIgdGhlIE1JVCBMaWNlbnNlXG4gICAgICAgICAgICAgKiBFQ01BU2NyaXB0IGNvbXBsaWFudCwgdW5pZm9ybSBjcm9zcy1icm93c2VyIHNwbGl0IG1ldGhvZFxuICAgICAgICAgICAgICovXG5cbiAgICAgICAgICAgIC8qKlxuICAgICAgICAgICAgICogU3BsaXRzIGEgc3RyaW5nIGludG8gYW4gYXJyYXkgb2Ygc3RyaW5ncyB1c2luZyBhIHJlZ2V4IG9yIHN0cmluZyBzZXBhcmF0b3IuIE1hdGNoZXMgb2YgdGhlXG4gICAgICAgICAgICAgKiBzZXBhcmF0b3IgYXJlIG5vdCBpbmNsdWRlZCBpbiB0aGUgcmVzdWx0IGFycmF5LiBIb3dldmVyLCBpZiBgc2VwYXJhdG9yYCBpcyBhIHJlZ2V4IHRoYXQgY29udGFpbnNcbiAgICAgICAgICAgICAqIGNhcHR1cmluZyBncm91cHMsIGJhY2tyZWZlcmVuY2VzIGFyZSBzcGxpY2VkIGludG8gdGhlIHJlc3VsdCBlYWNoIHRpbWUgYHNlcGFyYXRvcmAgaXMgbWF0Y2hlZC5cbiAgICAgICAgICAgICAqIEZpeGVzIGJyb3dzZXIgYnVncyBjb21wYXJlZCB0byB0aGUgbmF0aXZlIGBTdHJpbmcucHJvdG90eXBlLnNwbGl0YCBhbmQgY2FuIGJlIHVzZWQgcmVsaWFibHlcbiAgICAgICAgICAgICAqIGNyb3NzLWJyb3dzZXIuXG4gICAgICAgICAgICAgKiBAcGFyYW0ge1N0cmluZ30gc3RyIFN0cmluZyB0byBzcGxpdC5cbiAgICAgICAgICAgICAqIEBwYXJhbSB7UmVnRXhwfFN0cmluZ30gc2VwYXJhdG9yIFJlZ2V4IG9yIHN0cmluZyB0byB1c2UgZm9yIHNlcGFyYXRpbmcgdGhlIHN0cmluZy5cbiAgICAgICAgICAgICAqIEBwYXJhbSB7TnVtYmVyfSBbbGltaXRdIE1heGltdW0gbnVtYmVyIG9mIGl0ZW1zIHRvIGluY2x1ZGUgaW4gdGhlIHJlc3VsdCBhcnJheS5cbiAgICAgICAgICAgICAqIEByZXR1cm5zIHtBcnJheX0gQXJyYXkgb2Ygc3Vic3RyaW5ncy5cbiAgICAgICAgICAgICAqIEBleGFtcGxlXG4gICAgICAgICAgICAgKlxuICAgICAgICAgICAgICogLy8gQmFzaWMgdXNlXG4gICAgICAgICAgICAgKiBzcGxpdCgnYSBiIGMgZCcsICcgJyk7XG4gICAgICAgICAgICAgKiAvLyAtPiBbJ2EnLCAnYicsICdjJywgJ2QnXVxuICAgICAgICAgICAgICpcbiAgICAgICAgICAgICAqIC8vIFdpdGggbGltaXRcbiAgICAgICAgICAgICAqIHNwbGl0KCdhIGIgYyBkJywgJyAnLCAyKTtcbiAgICAgICAgICAgICAqIC8vIC0+IFsnYScsICdiJ11cbiAgICAgICAgICAgICAqXG4gICAgICAgICAgICAgKiAvLyBCYWNrcmVmZXJlbmNlcyBpbiByZXN1bHQgYXJyYXlcbiAgICAgICAgICAgICAqIHNwbGl0KCcuLndvcmQxIHdvcmQyLi4nLCAvKFthLXpdKykoXFxkKykvaSk7XG4gICAgICAgICAgICAgKiAvLyAtPiBbJy4uJywgJ3dvcmQnLCAnMScsICcgJywgJ3dvcmQnLCAnMicsICcuLiddXG4gICAgICAgICAgICAgKi9cbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gKGZ1bmN0aW9uIHNwbGl0KHVuZGVmKSB7XG5cbiAgICAgICAgICAgICAgICB2YXIgbmF0aXZlU3BsaXQgPSBTdHJpbmcucHJvdG90eXBlLnNwbGl0LFxuICAgICAgICAgICAgICAgICAgICBjb21wbGlhbnRFeGVjTnBjZyA9IC8oKT8/Ly5leGVjKFwiXCIpWzFdID09PSB1bmRlZixcblxuICAgICAgICAgICAgICAgIC8vIE5QQ0c6IG5vbnBhcnRpY2lwYXRpbmcgY2FwdHVyaW5nIGdyb3VwXG4gICAgICAgICAgICAgICAgc2VsZjtcblxuICAgICAgICAgICAgICAgIHNlbGYgPSBmdW5jdGlvbiAoc3RyLCBzZXBhcmF0b3IsIGxpbWl0KSB7XG4gICAgICAgICAgICAgICAgICAgIC8vIElmIGBzZXBhcmF0b3JgIGlzIG5vdCBhIHJlZ2V4LCB1c2UgYG5hdGl2ZVNwbGl0YFxuICAgICAgICAgICAgICAgICAgICBpZiAoT2JqZWN0LnByb3RvdHlwZS50b1N0cmluZy5jYWxsKHNlcGFyYXRvcikgIT09IFwiW29iamVjdCBSZWdFeHBdXCIpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBuYXRpdmVTcGxpdC5jYWxsKHN0ciwgc2VwYXJhdG9yLCBsaW1pdCk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgdmFyIG91dHB1dCA9IFtdLFxuICAgICAgICAgICAgICAgICAgICAgICAgZmxhZ3MgPSAoc2VwYXJhdG9yLmlnbm9yZUNhc2UgPyBcImlcIiA6IFwiXCIpICsgKHNlcGFyYXRvci5tdWx0aWxpbmUgPyBcIm1cIiA6IFwiXCIpICsgKHNlcGFyYXRvci5leHRlbmRlZCA/IFwieFwiIDogXCJcIikgKyAoc2VwYXJhdG9yLnN0aWNreSA/IFwieVwiIDogXCJcIiksXG5cbiAgICAgICAgICAgICAgICAgICAgLy8gRmlyZWZveCAzK1xuICAgICAgICAgICAgICAgICAgICBsYXN0TGFzdEluZGV4ID0gMCxcblxuICAgICAgICAgICAgICAgICAgICAvLyBNYWtlIGBnbG9iYWxgIGFuZCBhdm9pZCBgbGFzdEluZGV4YCBpc3N1ZXMgYnkgd29ya2luZyB3aXRoIGEgY29weVxuICAgICAgICAgICAgICAgICAgICBzZXBhcmF0b3IgPSBuZXcgUmVnRXhwKHNlcGFyYXRvci5zb3VyY2UsIGZsYWdzICsgXCJnXCIpLFxuICAgICAgICAgICAgICAgICAgICAgICAgc2VwYXJhdG9yMixcbiAgICAgICAgICAgICAgICAgICAgICAgIG1hdGNoLFxuICAgICAgICAgICAgICAgICAgICAgICAgbGFzdEluZGV4LFxuICAgICAgICAgICAgICAgICAgICAgICAgbGFzdExlbmd0aDtcbiAgICAgICAgICAgICAgICAgICAgc3RyICs9IFwiXCI7IC8vIFR5cGUtY29udmVydFxuICAgICAgICAgICAgICAgICAgICBpZiAoIWNvbXBsaWFudEV4ZWNOcGNnKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAvLyBEb2Vzbid0IG5lZWQgZmxhZ3MgZ3ksIGJ1dCB0aGV5IGRvbid0IGh1cnRcbiAgICAgICAgICAgICAgICAgICAgICAgIHNlcGFyYXRvcjIgPSBuZXcgUmVnRXhwKFwiXlwiICsgc2VwYXJhdG9yLnNvdXJjZSArIFwiJCg/IVxcXFxzKVwiLCBmbGFncyk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgLyogVmFsdWVzIGZvciBgbGltaXRgLCBwZXIgdGhlIHNwZWM6XG4gICAgICAgICAgICAgICAgICAgICAqIElmIHVuZGVmaW5lZDogNDI5NDk2NzI5NSAvLyBNYXRoLnBvdygyLCAzMikgLSAxXG4gICAgICAgICAgICAgICAgICAgICAqIElmIDAsIEluZmluaXR5LCBvciBOYU46IDBcbiAgICAgICAgICAgICAgICAgICAgICogSWYgcG9zaXRpdmUgbnVtYmVyOiBsaW1pdCA9IE1hdGguZmxvb3IobGltaXQpOyBpZiAobGltaXQgPiA0Mjk0OTY3Mjk1KSBsaW1pdCAtPSA0Mjk0OTY3Mjk2O1xuICAgICAgICAgICAgICAgICAgICAgKiBJZiBuZWdhdGl2ZSBudW1iZXI6IDQyOTQ5NjcyOTYgLSBNYXRoLmZsb29yKE1hdGguYWJzKGxpbWl0KSlcbiAgICAgICAgICAgICAgICAgICAgICogSWYgb3RoZXI6IFR5cGUtY29udmVydCwgdGhlbiB1c2UgdGhlIGFib3ZlIHJ1bGVzXG4gICAgICAgICAgICAgICAgICAgICAqL1xuICAgICAgICAgICAgICAgICAgICBsaW1pdCA9IGxpbWl0ID09PSB1bmRlZiA/IC0xID4+PiAwIDogLy8gTWF0aC5wb3coMiwgMzIpIC0gMVxuICAgICAgICAgICAgICAgICAgICBsaW1pdCA+Pj4gMDsgLy8gVG9VaW50MzIobGltaXQpXG4gICAgICAgICAgICAgICAgICAgIHdoaWxlIChtYXRjaCA9IHNlcGFyYXRvci5leGVjKHN0cikpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIGBzZXBhcmF0b3IubGFzdEluZGV4YCBpcyBub3QgcmVsaWFibGUgY3Jvc3MtYnJvd3NlclxuICAgICAgICAgICAgICAgICAgICAgICAgbGFzdEluZGV4ID0gbWF0Y2guaW5kZXggKyBtYXRjaFswXS5sZW5ndGg7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAobGFzdEluZGV4ID4gbGFzdExhc3RJbmRleCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIG91dHB1dC5wdXNoKHN0ci5zbGljZShsYXN0TGFzdEluZGV4LCBtYXRjaC5pbmRleCkpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIEZpeCBicm93c2VycyB3aG9zZSBgZXhlY2AgbWV0aG9kcyBkb24ndCBjb25zaXN0ZW50bHkgcmV0dXJuIGB1bmRlZmluZWRgIGZvclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIG5vbnBhcnRpY2lwYXRpbmcgY2FwdHVyaW5nIGdyb3Vwc1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmICghY29tcGxpYW50RXhlY05wY2cgJiYgbWF0Y2gubGVuZ3RoID4gMSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBtYXRjaFswXS5yZXBsYWNlKHNlcGFyYXRvcjIsIGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZvciAodmFyIGkgPSAxOyBpIDwgYXJndW1lbnRzLmxlbmd0aCAtIDI7IGkrKykge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChhcmd1bWVudHNbaV0gPT09IHVuZGVmKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1hdGNoW2ldID0gdW5kZWY7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKG1hdGNoLmxlbmd0aCA+IDEgJiYgbWF0Y2guaW5kZXggPCBzdHIubGVuZ3RoKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIEFycmF5LnByb3RvdHlwZS5wdXNoLmFwcGx5KG91dHB1dCwgbWF0Y2guc2xpY2UoMSkpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBsYXN0TGVuZ3RoID0gbWF0Y2hbMF0ubGVuZ3RoO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxhc3RMYXN0SW5kZXggPSBsYXN0SW5kZXg7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKG91dHB1dC5sZW5ndGggPj0gbGltaXQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHNlcGFyYXRvci5sYXN0SW5kZXggPT09IG1hdGNoLmluZGV4KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgc2VwYXJhdG9yLmxhc3RJbmRleCsrOyAvLyBBdm9pZCBhbiBpbmZpbml0ZSBsb29wXG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgaWYgKGxhc3RMYXN0SW5kZXggPT09IHN0ci5sZW5ndGgpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChsYXN0TGVuZ3RoIHx8ICFzZXBhcmF0b3IudGVzdChcIlwiKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIG91dHB1dC5wdXNoKFwiXCIpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgb3V0cHV0LnB1c2goc3RyLnNsaWNlKGxhc3RMYXN0SW5kZXgpKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICByZXR1cm4gb3V0cHV0Lmxlbmd0aCA+IGxpbWl0ID8gb3V0cHV0LnNsaWNlKDAsIGxpbWl0KSA6IG91dHB1dDtcbiAgICAgICAgICAgICAgICB9O1xuXG4gICAgICAgICAgICAgICAgcmV0dXJuIHNlbGY7XG4gICAgICAgICAgICB9KSgpO1xuICAgICAgICB9LCB7fV0sIDY6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7fSwge31dLCA3OiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge1xuICAgICAgICAgICAgXCJ1c2Ugc3RyaWN0XCI7XG5cbiAgICAgICAgICAgIHZhciBPbmVWZXJzaW9uQ29uc3RyYWludCA9IHJlcXVpcmUoXCJpbmRpdmlkdWFsL29uZS12ZXJzaW9uXCIpO1xuXG4gICAgICAgICAgICB2YXIgTVlfVkVSU0lPTiA9IFwiN1wiO1xuICAgICAgICAgICAgT25lVmVyc2lvbkNvbnN0cmFpbnQoXCJldi1zdG9yZVwiLCBNWV9WRVJTSU9OKTtcblxuICAgICAgICAgICAgdmFyIGhhc2hLZXkgPSBcIl9fRVZfU1RPUkVfS0VZQFwiICsgTVlfVkVSU0lPTjtcblxuICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBFdlN0b3JlO1xuXG4gICAgICAgICAgICBmdW5jdGlvbiBFdlN0b3JlKGVsZW0pIHtcbiAgICAgICAgICAgICAgICB2YXIgaGFzaCA9IGVsZW1baGFzaEtleV07XG5cbiAgICAgICAgICAgICAgICBpZiAoIWhhc2gpIHtcbiAgICAgICAgICAgICAgICAgICAgaGFzaCA9IGVsZW1baGFzaEtleV0gPSB7fTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICByZXR1cm4gaGFzaDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSwgeyBcImluZGl2aWR1YWwvb25lLXZlcnNpb25cIjogOSB9XSwgODogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHtcbiAgICAgICAgICAgIChmdW5jdGlvbiAoZ2xvYmFsKSB7XG4gICAgICAgICAgICAgICAgXCJ1c2Ugc3RyaWN0XCI7XG5cbiAgICAgICAgICAgICAgICAvKmdsb2JhbCB3aW5kb3csIGdsb2JhbCovXG5cbiAgICAgICAgICAgICAgICB2YXIgcm9vdCA9IHR5cGVvZiB3aW5kb3cgIT09IFwidW5kZWZpbmVkXCIgPyB3aW5kb3cgOiB0eXBlb2YgZ2xvYmFsICE9PSBcInVuZGVmaW5lZFwiID8gZ2xvYmFsIDoge307XG5cbiAgICAgICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IEluZGl2aWR1YWw7XG5cbiAgICAgICAgICAgICAgICBmdW5jdGlvbiBJbmRpdmlkdWFsKGtleSwgdmFsdWUpIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKGtleSBpbiByb290KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gcm9vdFtrZXldO1xuICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgcm9vdFtrZXldID0gdmFsdWU7XG5cbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHZhbHVlO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0pLmNhbGwodGhpcywgdHlwZW9mIGdsb2JhbCAhPT0gXCJ1bmRlZmluZWRcIiA/IGdsb2JhbCA6IHR5cGVvZiBzZWxmICE9PSBcInVuZGVmaW5lZFwiID8gc2VsZiA6IHR5cGVvZiB3aW5kb3cgIT09IFwidW5kZWZpbmVkXCIgPyB3aW5kb3cgOiB7fSk7XG4gICAgICAgIH0sIHt9XSwgOTogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHtcbiAgICAgICAgICAgIFwidXNlIHN0cmljdFwiO1xuXG4gICAgICAgICAgICB2YXIgSW5kaXZpZHVhbCA9IHJlcXVpcmUoXCIuL2luZGV4LmpzXCIpO1xuXG4gICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IE9uZVZlcnNpb247XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIE9uZVZlcnNpb24obW9kdWxlTmFtZSwgdmVyc2lvbiwgZGVmYXVsdFZhbHVlKSB7XG4gICAgICAgICAgICAgICAgdmFyIGtleSA9IFwiX19JTkRJVklEVUFMX09ORV9WRVJTSU9OX1wiICsgbW9kdWxlTmFtZTtcbiAgICAgICAgICAgICAgICB2YXIgZW5mb3JjZUtleSA9IGtleSArIFwiX0VORk9SQ0VfU0lOR0xFVE9OXCI7XG5cbiAgICAgICAgICAgICAgICB2YXIgdmVyc2lvblZhbHVlID0gSW5kaXZpZHVhbChlbmZvcmNlS2V5LCB2ZXJzaW9uKTtcblxuICAgICAgICAgICAgICAgIGlmICh2ZXJzaW9uVmFsdWUgIT09IHZlcnNpb24pIHtcbiAgICAgICAgICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKFwiQ2FuIG9ubHkgaGF2ZSBvbmUgY29weSBvZiBcIiArIG1vZHVsZU5hbWUgKyBcIi5cXG5cIiArIFwiWW91IGFscmVhZHkgaGF2ZSB2ZXJzaW9uIFwiICsgdmVyc2lvblZhbHVlICsgXCIgaW5zdGFsbGVkLlxcblwiICsgXCJUaGlzIG1lYW5zIHlvdSBjYW5ub3QgaW5zdGFsbCB2ZXJzaW9uIFwiICsgdmVyc2lvbik7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgcmV0dXJuIEluZGl2aWR1YWwoa2V5LCBkZWZhdWx0VmFsdWUpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9LCB7IFwiLi9pbmRleC5qc1wiOiA4IH1dLCAxMDogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHtcbiAgICAgICAgICAgIChmdW5jdGlvbiAoZ2xvYmFsKSB7XG4gICAgICAgICAgICAgICAgdmFyIHRvcExldmVsID0gdHlwZW9mIGdsb2JhbCAhPT0gXCJ1bmRlZmluZWRcIiA/IGdsb2JhbCA6IHR5cGVvZiB3aW5kb3cgIT09IFwidW5kZWZpbmVkXCIgPyB3aW5kb3cgOiB7fTtcbiAgICAgICAgICAgICAgICB2YXIgbWluRG9jID0gcmVxdWlyZShcIm1pbi1kb2N1bWVudFwiKTtcblxuICAgICAgICAgICAgICAgIGlmICh0eXBlb2YgZG9jdW1lbnQgIT09IFwidW5kZWZpbmVkXCIpIHtcbiAgICAgICAgICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBkb2N1bWVudDtcbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICB2YXIgZG9jY3kgPSB0b3BMZXZlbFtcIl9fR0xPQkFMX0RPQ1VNRU5UX0NBQ0hFQDRcIl07XG5cbiAgICAgICAgICAgICAgICAgICAgaWYgKCFkb2NjeSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgZG9jY3kgPSB0b3BMZXZlbFtcIl9fR0xPQkFMX0RPQ1VNRU5UX0NBQ0hFQDRcIl0gPSBtaW5Eb2M7XG4gICAgICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IGRvY2N5O1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0pLmNhbGwodGhpcywgdHlwZW9mIGdsb2JhbCAhPT0gXCJ1bmRlZmluZWRcIiA/IGdsb2JhbCA6IHR5cGVvZiBzZWxmICE9PSBcInVuZGVmaW5lZFwiID8gc2VsZiA6IHR5cGVvZiB3aW5kb3cgIT09IFwidW5kZWZpbmVkXCIgPyB3aW5kb3cgOiB7fSk7XG4gICAgICAgIH0sIHsgXCJtaW4tZG9jdW1lbnRcIjogNiB9XSwgMTE6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICBcInVzZSBzdHJpY3RcIjtcblxuICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiBpc09iamVjdCh4KSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHR5cGVvZiB4ID09PSBcIm9iamVjdFwiICYmIHggIT09IG51bGw7XG4gICAgICAgICAgICB9O1xuICAgICAgICB9LCB7fV0sIDEyOiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge1xuICAgICAgICAgICAgdmFyIG5hdGl2ZUlzQXJyYXkgPSBBcnJheS5pc0FycmF5O1xuICAgICAgICAgICAgdmFyIHRvU3RyaW5nID0gT2JqZWN0LnByb3RvdHlwZS50b1N0cmluZztcblxuICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBuYXRpdmVJc0FycmF5IHx8IGlzQXJyYXk7XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIGlzQXJyYXkob2JqKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHRvU3RyaW5nLmNhbGwob2JqKSA9PT0gXCJbb2JqZWN0IEFycmF5XVwiO1xuICAgICAgICAgICAgfVxuICAgICAgICB9LCB7fV0sIDEzOiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge1xuICAgICAgICAgICAgdmFyIHBhdGNoID0gcmVxdWlyZShcIi4vdmRvbS9wYXRjaC5qc1wiKTtcblxuICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBwYXRjaDtcbiAgICAgICAgfSwgeyBcIi4vdmRvbS9wYXRjaC5qc1wiOiAxOCB9XSwgMTQ6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICB2YXIgaXNPYmplY3QgPSByZXF1aXJlKFwiaXMtb2JqZWN0XCIpO1xuICAgICAgICAgICAgdmFyIGlzSG9vayA9IHJlcXVpcmUoXCIuLi92bm9kZS9pcy12aG9vay5qc1wiKTtcblxuICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBhcHBseVByb3BlcnRpZXM7XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIGFwcGx5UHJvcGVydGllcyhub2RlLCBwcm9wcywgcHJldmlvdXMpIHtcbiAgICAgICAgICAgICAgICBmb3IgKHZhciBwcm9wTmFtZSBpbiBwcm9wcykge1xuICAgICAgICAgICAgICAgICAgICB2YXIgcHJvcFZhbHVlID0gcHJvcHNbcHJvcE5hbWVdO1xuXG4gICAgICAgICAgICAgICAgICAgIGlmIChwcm9wVmFsdWUgPT09IHVuZGVmaW5lZCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgcmVtb3ZlUHJvcGVydHkobm9kZSwgcHJvcE5hbWUsIHByb3BWYWx1ZSwgcHJldmlvdXMpO1xuICAgICAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKGlzSG9vayhwcm9wVmFsdWUpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICByZW1vdmVQcm9wZXJ0eShub2RlLCBwcm9wTmFtZSwgcHJvcFZhbHVlLCBwcmV2aW91cyk7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAocHJvcFZhbHVlLmhvb2spIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBwcm9wVmFsdWUuaG9vayhub2RlLCBwcm9wTmFtZSwgcHJldmlvdXMgPyBwcmV2aW91c1twcm9wTmFtZV0gOiB1bmRlZmluZWQpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGlzT2JqZWN0KHByb3BWYWx1ZSkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBwYXRjaE9iamVjdChub2RlLCBwcm9wcywgcHJldmlvdXMsIHByb3BOYW1lLCBwcm9wVmFsdWUpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBub2RlW3Byb3BOYW1lXSA9IHByb3BWYWx1ZTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZnVuY3Rpb24gcmVtb3ZlUHJvcGVydHkobm9kZSwgcHJvcE5hbWUsIHByb3BWYWx1ZSwgcHJldmlvdXMpIHtcbiAgICAgICAgICAgICAgICBpZiAocHJldmlvdXMpIHtcbiAgICAgICAgICAgICAgICAgICAgdmFyIHByZXZpb3VzVmFsdWUgPSBwcmV2aW91c1twcm9wTmFtZV07XG5cbiAgICAgICAgICAgICAgICAgICAgaWYgKCFpc0hvb2socHJldmlvdXNWYWx1ZSkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChwcm9wTmFtZSA9PT0gXCJhdHRyaWJ1dGVzXCIpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBmb3IgKHZhciBhdHRyTmFtZSBpbiBwcmV2aW91c1ZhbHVlKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG5vZGUucmVtb3ZlQXR0cmlidXRlKGF0dHJOYW1lKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKHByb3BOYW1lID09PSBcInN0eWxlXCIpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBmb3IgKHZhciBpIGluIHByZXZpb3VzVmFsdWUpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbm9kZS5zdHlsZVtpXSA9IFwiXCI7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIGlmICh0eXBlb2YgcHJldmlvdXNWYWx1ZSA9PT0gXCJzdHJpbmdcIikge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIG5vZGVbcHJvcE5hbWVdID0gXCJcIjtcbiAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgbm9kZVtwcm9wTmFtZV0gPSBudWxsO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKHByZXZpb3VzVmFsdWUudW5ob29rKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBwcmV2aW91c1ZhbHVlLnVuaG9vayhub2RlLCBwcm9wTmFtZSwgcHJvcFZhbHVlKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZnVuY3Rpb24gcGF0Y2hPYmplY3Qobm9kZSwgcHJvcHMsIHByZXZpb3VzLCBwcm9wTmFtZSwgcHJvcFZhbHVlKSB7XG4gICAgICAgICAgICAgICAgdmFyIHByZXZpb3VzVmFsdWUgPSBwcmV2aW91cyA/IHByZXZpb3VzW3Byb3BOYW1lXSA6IHVuZGVmaW5lZDtcblxuICAgICAgICAgICAgICAgIC8vIFNldCBhdHRyaWJ1dGVzXG4gICAgICAgICAgICAgICAgaWYgKHByb3BOYW1lID09PSBcImF0dHJpYnV0ZXNcIikge1xuICAgICAgICAgICAgICAgICAgICBmb3IgKHZhciBhdHRyTmFtZSBpbiBwcm9wVmFsdWUpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHZhciBhdHRyVmFsdWUgPSBwcm9wVmFsdWVbYXR0ck5hbWVdO1xuXG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoYXR0clZhbHVlID09PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBub2RlLnJlbW92ZUF0dHJpYnV0ZShhdHRyTmFtZSk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIG5vZGUuc2V0QXR0cmlidXRlKGF0dHJOYW1lLCBhdHRyVmFsdWUpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIGlmIChwcmV2aW91c1ZhbHVlICYmIGlzT2JqZWN0KHByZXZpb3VzVmFsdWUpICYmIGdldFByb3RvdHlwZShwcmV2aW91c1ZhbHVlKSAhPT0gZ2V0UHJvdG90eXBlKHByb3BWYWx1ZSkpIHtcbiAgICAgICAgICAgICAgICAgICAgbm9kZVtwcm9wTmFtZV0gPSBwcm9wVmFsdWU7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICBpZiAoIWlzT2JqZWN0KG5vZGVbcHJvcE5hbWVdKSkge1xuICAgICAgICAgICAgICAgICAgICBub2RlW3Byb3BOYW1lXSA9IHt9O1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHZhciByZXBsYWNlciA9IHByb3BOYW1lID09PSBcInN0eWxlXCIgPyBcIlwiIDogdW5kZWZpbmVkO1xuXG4gICAgICAgICAgICAgICAgZm9yICh2YXIgayBpbiBwcm9wVmFsdWUpIHtcbiAgICAgICAgICAgICAgICAgICAgdmFyIHZhbHVlID0gcHJvcFZhbHVlW2tdO1xuICAgICAgICAgICAgICAgICAgICBub2RlW3Byb3BOYW1lXVtrXSA9IHZhbHVlID09PSB1bmRlZmluZWQgPyByZXBsYWNlciA6IHZhbHVlO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZnVuY3Rpb24gZ2V0UHJvdG90eXBlKHZhbHVlKSB7XG4gICAgICAgICAgICAgICAgaWYgKE9iamVjdC5nZXRQcm90b3R5cGVPZikge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gT2JqZWN0LmdldFByb3RvdHlwZU9mKHZhbHVlKTtcbiAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKHZhbHVlLl9fcHJvdG9fXykge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gdmFsdWUuX19wcm90b19fO1xuICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAodmFsdWUuY29uc3RydWN0b3IpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHZhbHVlLmNvbnN0cnVjdG9yLnByb3RvdHlwZTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH0sIHsgXCIuLi92bm9kZS9pcy12aG9vay5qc1wiOiAyNiwgXCJpcy1vYmplY3RcIjogMTEgfV0sIDE1OiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge1xuICAgICAgICAgICAgdmFyIGRvY3VtZW50ID0gcmVxdWlyZShcImdsb2JhbC9kb2N1bWVudFwiKTtcblxuICAgICAgICAgICAgdmFyIGFwcGx5UHJvcGVydGllcyA9IHJlcXVpcmUoXCIuL2FwcGx5LXByb3BlcnRpZXNcIik7XG5cbiAgICAgICAgICAgIHZhciBpc1ZOb2RlID0gcmVxdWlyZShcIi4uL3Zub2RlL2lzLXZub2RlLmpzXCIpO1xuICAgICAgICAgICAgdmFyIGlzVlRleHQgPSByZXF1aXJlKFwiLi4vdm5vZGUvaXMtdnRleHQuanNcIik7XG4gICAgICAgICAgICB2YXIgaXNXaWRnZXQgPSByZXF1aXJlKFwiLi4vdm5vZGUvaXMtd2lkZ2V0LmpzXCIpO1xuICAgICAgICAgICAgdmFyIGhhbmRsZVRodW5rID0gcmVxdWlyZShcIi4uL3Zub2RlL2hhbmRsZS10aHVuay5qc1wiKTtcblxuICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBjcmVhdGVFbGVtZW50O1xuXG4gICAgICAgICAgICBmdW5jdGlvbiBjcmVhdGVFbGVtZW50KHZub2RlLCBvcHRzKSB7XG4gICAgICAgICAgICAgICAgdmFyIGRvYyA9IG9wdHMgPyBvcHRzLmRvY3VtZW50IHx8IGRvY3VtZW50IDogZG9jdW1lbnQ7XG4gICAgICAgICAgICAgICAgdmFyIHdhcm4gPSBvcHRzID8gb3B0cy53YXJuIDogbnVsbDtcblxuICAgICAgICAgICAgICAgIHZub2RlID0gaGFuZGxlVGh1bmsodm5vZGUpLmE7XG5cbiAgICAgICAgICAgICAgICBpZiAoaXNXaWRnZXQodm5vZGUpKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiB2bm9kZS5pbml0KCk7XG4gICAgICAgICAgICAgICAgfSBlbHNlIGlmIChpc1ZUZXh0KHZub2RlKSkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gZG9jLmNyZWF0ZVRleHROb2RlKHZub2RlLnRleHQpO1xuICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoIWlzVk5vZGUodm5vZGUpKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmICh3YXJuKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICB3YXJuKFwiSXRlbSBpcyBub3QgYSB2YWxpZCB2aXJ0dWFsIGRvbSBub2RlXCIsIHZub2RlKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICByZXR1cm4gbnVsbDtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICB2YXIgbm9kZSA9IHZub2RlLm5hbWVzcGFjZSA9PT0gbnVsbCA/IGRvYy5jcmVhdGVFbGVtZW50KHZub2RlLnRhZ05hbWUpIDogZG9jLmNyZWF0ZUVsZW1lbnROUyh2bm9kZS5uYW1lc3BhY2UsIHZub2RlLnRhZ05hbWUpO1xuXG4gICAgICAgICAgICAgICAgdmFyIHByb3BzID0gdm5vZGUucHJvcGVydGllcztcbiAgICAgICAgICAgICAgICBhcHBseVByb3BlcnRpZXMobm9kZSwgcHJvcHMpO1xuXG4gICAgICAgICAgICAgICAgdmFyIGNoaWxkcmVuID0gdm5vZGUuY2hpbGRyZW47XG5cbiAgICAgICAgICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IGNoaWxkcmVuLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciBjaGlsZE5vZGUgPSBjcmVhdGVFbGVtZW50KGNoaWxkcmVuW2ldLCBvcHRzKTtcbiAgICAgICAgICAgICAgICAgICAgaWYgKGNoaWxkTm9kZSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgbm9kZS5hcHBlbmRDaGlsZChjaGlsZE5vZGUpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgcmV0dXJuIG5vZGU7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0sIHsgXCIuLi92bm9kZS9oYW5kbGUtdGh1bmsuanNcIjogMjQsIFwiLi4vdm5vZGUvaXMtdm5vZGUuanNcIjogMjcsIFwiLi4vdm5vZGUvaXMtdnRleHQuanNcIjogMjgsIFwiLi4vdm5vZGUvaXMtd2lkZ2V0LmpzXCI6IDI5LCBcIi4vYXBwbHktcHJvcGVydGllc1wiOiAxNCwgXCJnbG9iYWwvZG9jdW1lbnRcIjogMTAgfV0sIDE2OiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge1xuICAgICAgICAgICAgLy8gTWFwcyBhIHZpcnR1YWwgRE9NIHRyZWUgb250byBhIHJlYWwgRE9NIHRyZWUgaW4gYW4gZWZmaWNpZW50IG1hbm5lci5cbiAgICAgICAgICAgIC8vIFdlIGRvbid0IHdhbnQgdG8gcmVhZCBhbGwgb2YgdGhlIERPTSBub2RlcyBpbiB0aGUgdHJlZSBzbyB3ZSB1c2VcbiAgICAgICAgICAgIC8vIHRoZSBpbi1vcmRlciB0cmVlIGluZGV4aW5nIHRvIGVsaW1pbmF0ZSByZWN1cnNpb24gZG93biBjZXJ0YWluIGJyYW5jaGVzLlxuICAgICAgICAgICAgLy8gV2Ugb25seSByZWN1cnNlIGludG8gYSBET00gbm9kZSBpZiB3ZSBrbm93IHRoYXQgaXQgY29udGFpbnMgYSBjaGlsZCBvZlxuICAgICAgICAgICAgLy8gaW50ZXJlc3QuXG5cbiAgICAgICAgICAgIHZhciBub0NoaWxkID0ge307XG5cbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gZG9tSW5kZXg7XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIGRvbUluZGV4KHJvb3ROb2RlLCB0cmVlLCBpbmRpY2VzLCBub2Rlcykge1xuICAgICAgICAgICAgICAgIGlmICghaW5kaWNlcyB8fCBpbmRpY2VzLmxlbmd0aCA9PT0gMCkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4ge307XG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgaW5kaWNlcy5zb3J0KGFzY2VuZGluZyk7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiByZWN1cnNlKHJvb3ROb2RlLCB0cmVlLCBpbmRpY2VzLCBub2RlcywgMCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBmdW5jdGlvbiByZWN1cnNlKHJvb3ROb2RlLCB0cmVlLCBpbmRpY2VzLCBub2Rlcywgcm9vdEluZGV4KSB7XG4gICAgICAgICAgICAgICAgbm9kZXMgPSBub2RlcyB8fCB7fTtcblxuICAgICAgICAgICAgICAgIGlmIChyb290Tm9kZSkge1xuICAgICAgICAgICAgICAgICAgICBpZiAoaW5kZXhJblJhbmdlKGluZGljZXMsIHJvb3RJbmRleCwgcm9vdEluZGV4KSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgbm9kZXNbcm9vdEluZGV4XSA9IHJvb3ROb2RlO1xuICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgdmFyIHZDaGlsZHJlbiA9IHRyZWUuY2hpbGRyZW47XG5cbiAgICAgICAgICAgICAgICAgICAgaWYgKHZDaGlsZHJlbikge1xuXG4gICAgICAgICAgICAgICAgICAgICAgICB2YXIgY2hpbGROb2RlcyA9IHJvb3ROb2RlLmNoaWxkTm9kZXM7XG5cbiAgICAgICAgICAgICAgICAgICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgdHJlZS5jaGlsZHJlbi5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJvb3RJbmRleCArPSAxO1xuXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdmFyIHZDaGlsZCA9IHZDaGlsZHJlbltpXSB8fCBub0NoaWxkO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZhciBuZXh0SW5kZXggPSByb290SW5kZXggKyAodkNoaWxkLmNvdW50IHx8IDApO1xuXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gc2tpcCByZWN1cnNpb24gZG93biB0aGUgdHJlZSBpZiB0aGVyZSBhcmUgbm8gbm9kZXMgZG93biBoZXJlXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGluZGV4SW5SYW5nZShpbmRpY2VzLCByb290SW5kZXgsIG5leHRJbmRleCkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmVjdXJzZShjaGlsZE5vZGVzW2ldLCB2Q2hpbGQsIGluZGljZXMsIG5vZGVzLCByb290SW5kZXgpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJvb3RJbmRleCA9IG5leHRJbmRleDtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHJldHVybiBub2RlcztcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgLy8gQmluYXJ5IHNlYXJjaCBmb3IgYW4gaW5kZXggaW4gdGhlIGludGVydmFsIFtsZWZ0LCByaWdodF1cbiAgICAgICAgICAgIGZ1bmN0aW9uIGluZGV4SW5SYW5nZShpbmRpY2VzLCBsZWZ0LCByaWdodCkge1xuICAgICAgICAgICAgICAgIGlmIChpbmRpY2VzLmxlbmd0aCA9PT0gMCkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgdmFyIG1pbkluZGV4ID0gMDtcbiAgICAgICAgICAgICAgICB2YXIgbWF4SW5kZXggPSBpbmRpY2VzLmxlbmd0aCAtIDE7XG4gICAgICAgICAgICAgICAgdmFyIGN1cnJlbnRJbmRleDtcbiAgICAgICAgICAgICAgICB2YXIgY3VycmVudEl0ZW07XG5cbiAgICAgICAgICAgICAgICB3aGlsZSAobWluSW5kZXggPD0gbWF4SW5kZXgpIHtcbiAgICAgICAgICAgICAgICAgICAgY3VycmVudEluZGV4ID0gKG1heEluZGV4ICsgbWluSW5kZXgpIC8gMiA+PiAwO1xuICAgICAgICAgICAgICAgICAgICBjdXJyZW50SXRlbSA9IGluZGljZXNbY3VycmVudEluZGV4XTtcblxuICAgICAgICAgICAgICAgICAgICBpZiAobWluSW5kZXggPT09IG1heEluZGV4KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gY3VycmVudEl0ZW0gPj0gbGVmdCAmJiBjdXJyZW50SXRlbSA8PSByaWdodDtcbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIGlmIChjdXJyZW50SXRlbSA8IGxlZnQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIG1pbkluZGV4ID0gY3VycmVudEluZGV4ICsgMTtcbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIGlmIChjdXJyZW50SXRlbSA+IHJpZ2h0KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBtYXhJbmRleCA9IGN1cnJlbnRJbmRleCAtIDE7XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZnVuY3Rpb24gYXNjZW5kaW5nKGEsIGIpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gYSA+IGIgPyAxIDogLTE7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0sIHt9XSwgMTc6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICB2YXIgYXBwbHlQcm9wZXJ0aWVzID0gcmVxdWlyZShcIi4vYXBwbHktcHJvcGVydGllc1wiKTtcblxuICAgICAgICAgICAgdmFyIGlzV2lkZ2V0ID0gcmVxdWlyZShcIi4uL3Zub2RlL2lzLXdpZGdldC5qc1wiKTtcbiAgICAgICAgICAgIHZhciBWUGF0Y2ggPSByZXF1aXJlKFwiLi4vdm5vZGUvdnBhdGNoLmpzXCIpO1xuXG4gICAgICAgICAgICB2YXIgdXBkYXRlV2lkZ2V0ID0gcmVxdWlyZShcIi4vdXBkYXRlLXdpZGdldFwiKTtcblxuICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBhcHBseVBhdGNoO1xuXG4gICAgICAgICAgICBmdW5jdGlvbiBhcHBseVBhdGNoKHZwYXRjaCwgZG9tTm9kZSwgcmVuZGVyT3B0aW9ucykge1xuICAgICAgICAgICAgICAgIHZhciB0eXBlID0gdnBhdGNoLnR5cGU7XG4gICAgICAgICAgICAgICAgdmFyIHZOb2RlID0gdnBhdGNoLnZOb2RlO1xuICAgICAgICAgICAgICAgIHZhciBwYXRjaCA9IHZwYXRjaC5wYXRjaDtcblxuICAgICAgICAgICAgICAgIHN3aXRjaCAodHlwZSkge1xuICAgICAgICAgICAgICAgICAgICBjYXNlIFZQYXRjaC5SRU1PVkU6XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gcmVtb3ZlTm9kZShkb21Ob2RlLCB2Tm9kZSk7XG4gICAgICAgICAgICAgICAgICAgIGNhc2UgVlBhdGNoLklOU0VSVDpcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBpbnNlcnROb2RlKGRvbU5vZGUsIHBhdGNoLCByZW5kZXJPcHRpb25zKTtcbiAgICAgICAgICAgICAgICAgICAgY2FzZSBWUGF0Y2guVlRFWFQ6XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gc3RyaW5nUGF0Y2goZG9tTm9kZSwgdk5vZGUsIHBhdGNoLCByZW5kZXJPcHRpb25zKTtcbiAgICAgICAgICAgICAgICAgICAgY2FzZSBWUGF0Y2guV0lER0VUOlxuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHdpZGdldFBhdGNoKGRvbU5vZGUsIHZOb2RlLCBwYXRjaCwgcmVuZGVyT3B0aW9ucyk7XG4gICAgICAgICAgICAgICAgICAgIGNhc2UgVlBhdGNoLlZOT0RFOlxuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHZOb2RlUGF0Y2goZG9tTm9kZSwgdk5vZGUsIHBhdGNoLCByZW5kZXJPcHRpb25zKTtcbiAgICAgICAgICAgICAgICAgICAgY2FzZSBWUGF0Y2guT1JERVI6XG4gICAgICAgICAgICAgICAgICAgICAgICByZW9yZGVyQ2hpbGRyZW4oZG9tTm9kZSwgcGF0Y2gpO1xuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGRvbU5vZGU7XG4gICAgICAgICAgICAgICAgICAgIGNhc2UgVlBhdGNoLlBST1BTOlxuICAgICAgICAgICAgICAgICAgICAgICAgYXBwbHlQcm9wZXJ0aWVzKGRvbU5vZGUsIHBhdGNoLCB2Tm9kZS5wcm9wZXJ0aWVzKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBkb21Ob2RlO1xuICAgICAgICAgICAgICAgICAgICBjYXNlIFZQYXRjaC5USFVOSzpcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiByZXBsYWNlUm9vdChkb21Ob2RlLCByZW5kZXJPcHRpb25zLnBhdGNoKGRvbU5vZGUsIHBhdGNoLCByZW5kZXJPcHRpb25zKSk7XG4gICAgICAgICAgICAgICAgICAgIGRlZmF1bHQ6XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gZG9tTm9kZTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIHJlbW92ZU5vZGUoZG9tTm9kZSwgdk5vZGUpIHtcbiAgICAgICAgICAgICAgICB2YXIgcGFyZW50Tm9kZSA9IGRvbU5vZGUucGFyZW50Tm9kZTtcblxuICAgICAgICAgICAgICAgIGlmIChwYXJlbnROb2RlKSB7XG4gICAgICAgICAgICAgICAgICAgIHBhcmVudE5vZGUucmVtb3ZlQ2hpbGQoZG9tTm9kZSk7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgZGVzdHJveVdpZGdldChkb21Ob2RlLCB2Tm9kZSk7XG5cbiAgICAgICAgICAgICAgICByZXR1cm4gbnVsbDtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZnVuY3Rpb24gaW5zZXJ0Tm9kZShwYXJlbnROb2RlLCB2Tm9kZSwgcmVuZGVyT3B0aW9ucykge1xuICAgICAgICAgICAgICAgIHZhciBuZXdOb2RlID0gcmVuZGVyT3B0aW9ucy5yZW5kZXIodk5vZGUsIHJlbmRlck9wdGlvbnMpO1xuXG4gICAgICAgICAgICAgICAgaWYgKHBhcmVudE5vZGUpIHtcbiAgICAgICAgICAgICAgICAgICAgcGFyZW50Tm9kZS5hcHBlbmRDaGlsZChuZXdOb2RlKTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICByZXR1cm4gcGFyZW50Tm9kZTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZnVuY3Rpb24gc3RyaW5nUGF0Y2goZG9tTm9kZSwgbGVmdFZOb2RlLCB2VGV4dCwgcmVuZGVyT3B0aW9ucykge1xuICAgICAgICAgICAgICAgIHZhciBuZXdOb2RlO1xuXG4gICAgICAgICAgICAgICAgaWYgKGRvbU5vZGUubm9kZVR5cGUgPT09IDMpIHtcbiAgICAgICAgICAgICAgICAgICAgZG9tTm9kZS5yZXBsYWNlRGF0YSgwLCBkb21Ob2RlLmxlbmd0aCwgdlRleHQudGV4dCk7XG4gICAgICAgICAgICAgICAgICAgIG5ld05vZGUgPSBkb21Ob2RlO1xuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciBwYXJlbnROb2RlID0gZG9tTm9kZS5wYXJlbnROb2RlO1xuICAgICAgICAgICAgICAgICAgICBuZXdOb2RlID0gcmVuZGVyT3B0aW9ucy5yZW5kZXIodlRleHQsIHJlbmRlck9wdGlvbnMpO1xuXG4gICAgICAgICAgICAgICAgICAgIGlmIChwYXJlbnROb2RlICYmIG5ld05vZGUgIT09IGRvbU5vZGUpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHBhcmVudE5vZGUucmVwbGFjZUNoaWxkKG5ld05vZGUsIGRvbU5vZGUpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgcmV0dXJuIG5ld05vZGU7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIHdpZGdldFBhdGNoKGRvbU5vZGUsIGxlZnRWTm9kZSwgd2lkZ2V0LCByZW5kZXJPcHRpb25zKSB7XG4gICAgICAgICAgICAgICAgdmFyIHVwZGF0aW5nID0gdXBkYXRlV2lkZ2V0KGxlZnRWTm9kZSwgd2lkZ2V0KTtcbiAgICAgICAgICAgICAgICB2YXIgbmV3Tm9kZTtcblxuICAgICAgICAgICAgICAgIGlmICh1cGRhdGluZykge1xuICAgICAgICAgICAgICAgICAgICBuZXdOb2RlID0gd2lkZ2V0LnVwZGF0ZShsZWZ0Vk5vZGUsIGRvbU5vZGUpIHx8IGRvbU5vZGU7XG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgbmV3Tm9kZSA9IHJlbmRlck9wdGlvbnMucmVuZGVyKHdpZGdldCwgcmVuZGVyT3B0aW9ucyk7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgdmFyIHBhcmVudE5vZGUgPSBkb21Ob2RlLnBhcmVudE5vZGU7XG5cbiAgICAgICAgICAgICAgICBpZiAocGFyZW50Tm9kZSAmJiBuZXdOb2RlICE9PSBkb21Ob2RlKSB7XG4gICAgICAgICAgICAgICAgICAgIHBhcmVudE5vZGUucmVwbGFjZUNoaWxkKG5ld05vZGUsIGRvbU5vZGUpO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIGlmICghdXBkYXRpbmcpIHtcbiAgICAgICAgICAgICAgICAgICAgZGVzdHJveVdpZGdldChkb21Ob2RlLCBsZWZ0Vk5vZGUpO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHJldHVybiBuZXdOb2RlO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBmdW5jdGlvbiB2Tm9kZVBhdGNoKGRvbU5vZGUsIGxlZnRWTm9kZSwgdk5vZGUsIHJlbmRlck9wdGlvbnMpIHtcbiAgICAgICAgICAgICAgICB2YXIgcGFyZW50Tm9kZSA9IGRvbU5vZGUucGFyZW50Tm9kZTtcbiAgICAgICAgICAgICAgICB2YXIgbmV3Tm9kZSA9IHJlbmRlck9wdGlvbnMucmVuZGVyKHZOb2RlLCByZW5kZXJPcHRpb25zKTtcblxuICAgICAgICAgICAgICAgIGlmIChwYXJlbnROb2RlICYmIG5ld05vZGUgIT09IGRvbU5vZGUpIHtcbiAgICAgICAgICAgICAgICAgICAgcGFyZW50Tm9kZS5yZXBsYWNlQ2hpbGQobmV3Tm9kZSwgZG9tTm9kZSk7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgcmV0dXJuIG5ld05vZGU7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIGRlc3Ryb3lXaWRnZXQoZG9tTm9kZSwgdykge1xuICAgICAgICAgICAgICAgIGlmICh0eXBlb2Ygdy5kZXN0cm95ID09PSBcImZ1bmN0aW9uXCIgJiYgaXNXaWRnZXQodykpIHtcbiAgICAgICAgICAgICAgICAgICAgdy5kZXN0cm95KGRvbU5vZGUpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZnVuY3Rpb24gcmVvcmRlckNoaWxkcmVuKGRvbU5vZGUsIG1vdmVzKSB7XG4gICAgICAgICAgICAgICAgdmFyIGNoaWxkTm9kZXMgPSBkb21Ob2RlLmNoaWxkTm9kZXM7XG4gICAgICAgICAgICAgICAgdmFyIGtleU1hcCA9IHt9O1xuICAgICAgICAgICAgICAgIHZhciBub2RlO1xuICAgICAgICAgICAgICAgIHZhciByZW1vdmU7XG4gICAgICAgICAgICAgICAgdmFyIGluc2VydDtcblxuICAgICAgICAgICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgbW92ZXMucmVtb3Zlcy5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgICAgICAgICByZW1vdmUgPSBtb3Zlcy5yZW1vdmVzW2ldO1xuICAgICAgICAgICAgICAgICAgICBub2RlID0gY2hpbGROb2Rlc1tyZW1vdmUuZnJvbV07XG4gICAgICAgICAgICAgICAgICAgIGlmIChyZW1vdmUua2V5KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBrZXlNYXBbcmVtb3ZlLmtleV0gPSBub2RlO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIGRvbU5vZGUucmVtb3ZlQ2hpbGQobm9kZSk7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgdmFyIGxlbmd0aCA9IGNoaWxkTm9kZXMubGVuZ3RoO1xuICAgICAgICAgICAgICAgIGZvciAodmFyIGogPSAwOyBqIDwgbW92ZXMuaW5zZXJ0cy5sZW5ndGg7IGorKykge1xuICAgICAgICAgICAgICAgICAgICBpbnNlcnQgPSBtb3Zlcy5pbnNlcnRzW2pdO1xuICAgICAgICAgICAgICAgICAgICBub2RlID0ga2V5TWFwW2luc2VydC5rZXldO1xuICAgICAgICAgICAgICAgICAgICAvLyB0aGlzIGlzIHRoZSB3ZWlyZGVzdCBidWcgaSd2ZSBldmVyIHNlZW4gaW4gd2Via2l0XG4gICAgICAgICAgICAgICAgICAgIGRvbU5vZGUuaW5zZXJ0QmVmb3JlKG5vZGUsIGluc2VydC50byA+PSBsZW5ndGgrKyA/IG51bGwgOiBjaGlsZE5vZGVzW2luc2VydC50b10pO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZnVuY3Rpb24gcmVwbGFjZVJvb3Qob2xkUm9vdCwgbmV3Um9vdCkge1xuICAgICAgICAgICAgICAgIGlmIChvbGRSb290ICYmIG5ld1Jvb3QgJiYgb2xkUm9vdCAhPT0gbmV3Um9vdCAmJiBvbGRSb290LnBhcmVudE5vZGUpIHtcbiAgICAgICAgICAgICAgICAgICAgb2xkUm9vdC5wYXJlbnROb2RlLnJlcGxhY2VDaGlsZChuZXdSb290LCBvbGRSb290KTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICByZXR1cm4gbmV3Um9vdDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSwgeyBcIi4uL3Zub2RlL2lzLXdpZGdldC5qc1wiOiAyOSwgXCIuLi92bm9kZS92cGF0Y2guanNcIjogMzIsIFwiLi9hcHBseS1wcm9wZXJ0aWVzXCI6IDE0LCBcIi4vdXBkYXRlLXdpZGdldFwiOiAxOSB9XSwgMTg6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICB2YXIgZG9jdW1lbnQgPSByZXF1aXJlKFwiZ2xvYmFsL2RvY3VtZW50XCIpO1xuICAgICAgICAgICAgdmFyIGlzQXJyYXkgPSByZXF1aXJlKFwieC1pcy1hcnJheVwiKTtcblxuICAgICAgICAgICAgdmFyIHJlbmRlciA9IHJlcXVpcmUoXCIuL2NyZWF0ZS1lbGVtZW50XCIpO1xuICAgICAgICAgICAgdmFyIGRvbUluZGV4ID0gcmVxdWlyZShcIi4vZG9tLWluZGV4XCIpO1xuICAgICAgICAgICAgdmFyIHBhdGNoT3AgPSByZXF1aXJlKFwiLi9wYXRjaC1vcFwiKTtcbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gcGF0Y2g7XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIHBhdGNoKHJvb3ROb2RlLCBwYXRjaGVzLCByZW5kZXJPcHRpb25zKSB7XG4gICAgICAgICAgICAgICAgcmVuZGVyT3B0aW9ucyA9IHJlbmRlck9wdGlvbnMgfHwge307XG4gICAgICAgICAgICAgICAgcmVuZGVyT3B0aW9ucy5wYXRjaCA9IHJlbmRlck9wdGlvbnMucGF0Y2ggJiYgcmVuZGVyT3B0aW9ucy5wYXRjaCAhPT0gcGF0Y2ggPyByZW5kZXJPcHRpb25zLnBhdGNoIDogcGF0Y2hSZWN1cnNpdmU7XG4gICAgICAgICAgICAgICAgcmVuZGVyT3B0aW9ucy5yZW5kZXIgPSByZW5kZXJPcHRpb25zLnJlbmRlciB8fCByZW5kZXI7XG5cbiAgICAgICAgICAgICAgICByZXR1cm4gcmVuZGVyT3B0aW9ucy5wYXRjaChyb290Tm9kZSwgcGF0Y2hlcywgcmVuZGVyT3B0aW9ucyk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIHBhdGNoUmVjdXJzaXZlKHJvb3ROb2RlLCBwYXRjaGVzLCByZW5kZXJPcHRpb25zKSB7XG4gICAgICAgICAgICAgICAgdmFyIGluZGljZXMgPSBwYXRjaEluZGljZXMocGF0Y2hlcyk7XG5cbiAgICAgICAgICAgICAgICBpZiAoaW5kaWNlcy5sZW5ndGggPT09IDApIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHJvb3ROb2RlO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHZhciBpbmRleCA9IGRvbUluZGV4KHJvb3ROb2RlLCBwYXRjaGVzLmEsIGluZGljZXMpO1xuICAgICAgICAgICAgICAgIHZhciBvd25lckRvY3VtZW50ID0gcm9vdE5vZGUub3duZXJEb2N1bWVudDtcblxuICAgICAgICAgICAgICAgIGlmICghcmVuZGVyT3B0aW9ucy5kb2N1bWVudCAmJiBvd25lckRvY3VtZW50ICE9PSBkb2N1bWVudCkge1xuICAgICAgICAgICAgICAgICAgICByZW5kZXJPcHRpb25zLmRvY3VtZW50ID0gb3duZXJEb2N1bWVudDtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IGluZGljZXMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgICAgICAgICAgdmFyIG5vZGVJbmRleCA9IGluZGljZXNbaV07XG4gICAgICAgICAgICAgICAgICAgIHJvb3ROb2RlID0gYXBwbHlQYXRjaChyb290Tm9kZSwgaW5kZXhbbm9kZUluZGV4XSwgcGF0Y2hlc1tub2RlSW5kZXhdLCByZW5kZXJPcHRpb25zKTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICByZXR1cm4gcm9vdE5vZGU7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIGFwcGx5UGF0Y2gocm9vdE5vZGUsIGRvbU5vZGUsIHBhdGNoTGlzdCwgcmVuZGVyT3B0aW9ucykge1xuICAgICAgICAgICAgICAgIGlmICghZG9tTm9kZSkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gcm9vdE5vZGU7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgdmFyIG5ld05vZGU7XG5cbiAgICAgICAgICAgICAgICBpZiAoaXNBcnJheShwYXRjaExpc3QpKSB7XG4gICAgICAgICAgICAgICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgcGF0Y2hMaXN0Lmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBuZXdOb2RlID0gcGF0Y2hPcChwYXRjaExpc3RbaV0sIGRvbU5vZGUsIHJlbmRlck9wdGlvbnMpO1xuXG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoZG9tTm9kZSA9PT0gcm9vdE5vZGUpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICByb290Tm9kZSA9IG5ld05vZGU7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICBuZXdOb2RlID0gcGF0Y2hPcChwYXRjaExpc3QsIGRvbU5vZGUsIHJlbmRlck9wdGlvbnMpO1xuXG4gICAgICAgICAgICAgICAgICAgIGlmIChkb21Ob2RlID09PSByb290Tm9kZSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgcm9vdE5vZGUgPSBuZXdOb2RlO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgcmV0dXJuIHJvb3ROb2RlO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBmdW5jdGlvbiBwYXRjaEluZGljZXMocGF0Y2hlcykge1xuICAgICAgICAgICAgICAgIHZhciBpbmRpY2VzID0gW107XG5cbiAgICAgICAgICAgICAgICBmb3IgKHZhciBrZXkgaW4gcGF0Y2hlcykge1xuICAgICAgICAgICAgICAgICAgICBpZiAoa2V5ICE9PSBcImFcIikge1xuICAgICAgICAgICAgICAgICAgICAgICAgaW5kaWNlcy5wdXNoKE51bWJlcihrZXkpKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHJldHVybiBpbmRpY2VzO1xuICAgICAgICAgICAgfVxuICAgICAgICB9LCB7IFwiLi9jcmVhdGUtZWxlbWVudFwiOiAxNSwgXCIuL2RvbS1pbmRleFwiOiAxNiwgXCIuL3BhdGNoLW9wXCI6IDE3LCBcImdsb2JhbC9kb2N1bWVudFwiOiAxMCwgXCJ4LWlzLWFycmF5XCI6IDEyIH1dLCAxOTogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHtcbiAgICAgICAgICAgIHZhciBpc1dpZGdldCA9IHJlcXVpcmUoXCIuLi92bm9kZS9pcy13aWRnZXQuanNcIik7XG5cbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gdXBkYXRlV2lkZ2V0O1xuXG4gICAgICAgICAgICBmdW5jdGlvbiB1cGRhdGVXaWRnZXQoYSwgYikge1xuICAgICAgICAgICAgICAgIGlmIChpc1dpZGdldChhKSAmJiBpc1dpZGdldChiKSkge1xuICAgICAgICAgICAgICAgICAgICBpZiAoXCJuYW1lXCIgaW4gYSAmJiBcIm5hbWVcIiBpbiBiKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gYS5pZCA9PT0gYi5pZDtcbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBhLmluaXQgPT09IGIuaW5pdDtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSwgeyBcIi4uL3Zub2RlL2lzLXdpZGdldC5qc1wiOiAyOSB9XSwgMjA6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICBcInVzZSBzdHJpY3RcIjtcblxuICAgICAgICAgICAgdmFyIEV2U3RvcmUgPSByZXF1aXJlKFwiZXYtc3RvcmVcIik7XG5cbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gRXZIb29rO1xuXG4gICAgICAgICAgICBmdW5jdGlvbiBFdkhvb2sodmFsdWUpIHtcbiAgICAgICAgICAgICAgICBpZiAoISh0aGlzIGluc3RhbmNlb2YgRXZIb29rKSkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gbmV3IEV2SG9vayh2YWx1ZSk7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgdGhpcy52YWx1ZSA9IHZhbHVlO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBFdkhvb2sucHJvdG90eXBlLmhvb2sgPSBmdW5jdGlvbiAobm9kZSwgcHJvcGVydHlOYW1lKSB7XG4gICAgICAgICAgICAgICAgdmFyIGVzID0gRXZTdG9yZShub2RlKTtcbiAgICAgICAgICAgICAgICB2YXIgcHJvcE5hbWUgPSBwcm9wZXJ0eU5hbWUuc3Vic3RyKDMpO1xuXG4gICAgICAgICAgICAgICAgZXNbcHJvcE5hbWVdID0gdGhpcy52YWx1ZTtcbiAgICAgICAgICAgIH07XG5cbiAgICAgICAgICAgIEV2SG9vay5wcm90b3R5cGUudW5ob29rID0gZnVuY3Rpb24gKG5vZGUsIHByb3BlcnR5TmFtZSkge1xuICAgICAgICAgICAgICAgIHZhciBlcyA9IEV2U3RvcmUobm9kZSk7XG4gICAgICAgICAgICAgICAgdmFyIHByb3BOYW1lID0gcHJvcGVydHlOYW1lLnN1YnN0cigzKTtcblxuICAgICAgICAgICAgICAgIGVzW3Byb3BOYW1lXSA9IHVuZGVmaW5lZDtcbiAgICAgICAgICAgIH07XG4gICAgICAgIH0sIHsgXCJldi1zdG9yZVwiOiA3IH1dLCAyMTogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHtcbiAgICAgICAgICAgIFwidXNlIHN0cmljdFwiO1xuXG4gICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IFNvZnRTZXRIb29rO1xuXG4gICAgICAgICAgICBmdW5jdGlvbiBTb2Z0U2V0SG9vayh2YWx1ZSkge1xuICAgICAgICAgICAgICAgIGlmICghKHRoaXMgaW5zdGFuY2VvZiBTb2Z0U2V0SG9vaykpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIG5ldyBTb2Z0U2V0SG9vayh2YWx1ZSk7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgdGhpcy52YWx1ZSA9IHZhbHVlO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBTb2Z0U2V0SG9vay5wcm90b3R5cGUuaG9vayA9IGZ1bmN0aW9uIChub2RlLCBwcm9wZXJ0eU5hbWUpIHtcbiAgICAgICAgICAgICAgICBpZiAobm9kZVtwcm9wZXJ0eU5hbWVdICE9PSB0aGlzLnZhbHVlKSB7XG4gICAgICAgICAgICAgICAgICAgIG5vZGVbcHJvcGVydHlOYW1lXSA9IHRoaXMudmFsdWU7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfTtcbiAgICAgICAgfSwge31dLCAyMjogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHtcbiAgICAgICAgICAgIFwidXNlIHN0cmljdFwiO1xuXG4gICAgICAgICAgICB2YXIgaXNBcnJheSA9IHJlcXVpcmUoXCJ4LWlzLWFycmF5XCIpO1xuXG4gICAgICAgICAgICB2YXIgVk5vZGUgPSByZXF1aXJlKFwiLi4vdm5vZGUvdm5vZGUuanNcIik7XG4gICAgICAgICAgICB2YXIgVlRleHQgPSByZXF1aXJlKFwiLi4vdm5vZGUvdnRleHQuanNcIik7XG4gICAgICAgICAgICB2YXIgaXNWTm9kZSA9IHJlcXVpcmUoXCIuLi92bm9kZS9pcy12bm9kZVwiKTtcbiAgICAgICAgICAgIHZhciBpc1ZUZXh0ID0gcmVxdWlyZShcIi4uL3Zub2RlL2lzLXZ0ZXh0XCIpO1xuICAgICAgICAgICAgdmFyIGlzV2lkZ2V0ID0gcmVxdWlyZShcIi4uL3Zub2RlL2lzLXdpZGdldFwiKTtcbiAgICAgICAgICAgIHZhciBpc0hvb2sgPSByZXF1aXJlKFwiLi4vdm5vZGUvaXMtdmhvb2tcIik7XG4gICAgICAgICAgICB2YXIgaXNWVGh1bmsgPSByZXF1aXJlKFwiLi4vdm5vZGUvaXMtdGh1bmtcIik7XG5cbiAgICAgICAgICAgIHZhciBwYXJzZVRhZyA9IHJlcXVpcmUoXCIuL3BhcnNlLXRhZy5qc1wiKTtcbiAgICAgICAgICAgIHZhciBzb2Z0U2V0SG9vayA9IHJlcXVpcmUoXCIuL2hvb2tzL3NvZnQtc2V0LWhvb2suanNcIik7XG4gICAgICAgICAgICB2YXIgZXZIb29rID0gcmVxdWlyZShcIi4vaG9va3MvZXYtaG9vay5qc1wiKTtcblxuICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBoO1xuXG4gICAgICAgICAgICBmdW5jdGlvbiBoKHRhZ05hbWUsIHByb3BlcnRpZXMsIGNoaWxkcmVuKSB7XG4gICAgICAgICAgICAgICAgdmFyIGNoaWxkTm9kZXMgPSBbXTtcbiAgICAgICAgICAgICAgICB2YXIgdGFnLCBwcm9wcywga2V5LCBuYW1lc3BhY2U7XG5cbiAgICAgICAgICAgICAgICBpZiAoIWNoaWxkcmVuICYmIGlzQ2hpbGRyZW4ocHJvcGVydGllcykpIHtcbiAgICAgICAgICAgICAgICAgICAgY2hpbGRyZW4gPSBwcm9wZXJ0aWVzO1xuICAgICAgICAgICAgICAgICAgICBwcm9wcyA9IHt9O1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHByb3BzID0gcHJvcHMgfHwgcHJvcGVydGllcyB8fCB7fTtcbiAgICAgICAgICAgICAgICB0YWcgPSBwYXJzZVRhZyh0YWdOYW1lLCBwcm9wcyk7XG5cbiAgICAgICAgICAgICAgICAvLyBzdXBwb3J0IGtleXNcbiAgICAgICAgICAgICAgICBpZiAocHJvcHMuaGFzT3duUHJvcGVydHkoXCJrZXlcIikpIHtcbiAgICAgICAgICAgICAgICAgICAga2V5ID0gcHJvcHMua2V5O1xuICAgICAgICAgICAgICAgICAgICBwcm9wcy5rZXkgPSB1bmRlZmluZWQ7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgLy8gc3VwcG9ydCBuYW1lc3BhY2VcbiAgICAgICAgICAgICAgICBpZiAocHJvcHMuaGFzT3duUHJvcGVydHkoXCJuYW1lc3BhY2VcIikpIHtcbiAgICAgICAgICAgICAgICAgICAgbmFtZXNwYWNlID0gcHJvcHMubmFtZXNwYWNlO1xuICAgICAgICAgICAgICAgICAgICBwcm9wcy5uYW1lc3BhY2UgPSB1bmRlZmluZWQ7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgLy8gZml4IGN1cnNvciBidWdcbiAgICAgICAgICAgICAgICBpZiAodGFnID09PSBcIklOUFVUXCIgJiYgIW5hbWVzcGFjZSAmJiBwcm9wcy5oYXNPd25Qcm9wZXJ0eShcInZhbHVlXCIpICYmIHByb3BzLnZhbHVlICE9PSB1bmRlZmluZWQgJiYgIWlzSG9vayhwcm9wcy52YWx1ZSkpIHtcbiAgICAgICAgICAgICAgICAgICAgcHJvcHMudmFsdWUgPSBzb2Z0U2V0SG9vayhwcm9wcy52YWx1ZSk7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgdHJhbnNmb3JtUHJvcGVydGllcyhwcm9wcyk7XG5cbiAgICAgICAgICAgICAgICBpZiAoY2hpbGRyZW4gIT09IHVuZGVmaW5lZCAmJiBjaGlsZHJlbiAhPT0gbnVsbCkge1xuICAgICAgICAgICAgICAgICAgICBhZGRDaGlsZChjaGlsZHJlbiwgY2hpbGROb2RlcywgdGFnLCBwcm9wcyk7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgcmV0dXJuIG5ldyBWTm9kZSh0YWcsIHByb3BzLCBjaGlsZE5vZGVzLCBrZXksIG5hbWVzcGFjZSk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIGFkZENoaWxkKGMsIGNoaWxkTm9kZXMsIHRhZywgcHJvcHMpIHtcbiAgICAgICAgICAgICAgICBpZiAodHlwZW9mIGMgPT09IFwic3RyaW5nXCIpIHtcbiAgICAgICAgICAgICAgICAgICAgY2hpbGROb2Rlcy5wdXNoKG5ldyBWVGV4dChjKSk7XG4gICAgICAgICAgICAgICAgfSBlbHNlIGlmICh0eXBlb2YgYyA9PT0gXCJudW1iZXJcIikge1xuICAgICAgICAgICAgICAgICAgICBjaGlsZE5vZGVzLnB1c2gobmV3IFZUZXh0KFN0cmluZyhjKSkpO1xuICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoaXNDaGlsZChjKSkge1xuICAgICAgICAgICAgICAgICAgICBjaGlsZE5vZGVzLnB1c2goYyk7XG4gICAgICAgICAgICAgICAgfSBlbHNlIGlmIChpc0FycmF5KGMpKSB7XG4gICAgICAgICAgICAgICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgYy5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgICAgICAgICAgICAgYWRkQ2hpbGQoY1tpXSwgY2hpbGROb2RlcywgdGFnLCBwcm9wcyk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKGMgPT09IG51bGwgfHwgYyA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICB0aHJvdyBVbmV4cGVjdGVkVmlydHVhbEVsZW1lbnQoe1xuICAgICAgICAgICAgICAgICAgICAgICAgZm9yZWlnbk9iamVjdDogYyxcbiAgICAgICAgICAgICAgICAgICAgICAgIHBhcmVudFZub2RlOiB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdGFnTmFtZTogdGFnLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHByb3BlcnRpZXM6IHByb3BzXG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZnVuY3Rpb24gdHJhbnNmb3JtUHJvcGVydGllcyhwcm9wcykge1xuICAgICAgICAgICAgICAgIGZvciAodmFyIHByb3BOYW1lIGluIHByb3BzKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmIChwcm9wcy5oYXNPd25Qcm9wZXJ0eShwcm9wTmFtZSkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHZhciB2YWx1ZSA9IHByb3BzW3Byb3BOYW1lXTtcblxuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGlzSG9vayh2YWx1ZSkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb250aW51ZTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHByb3BOYW1lLnN1YnN0cigwLCAzKSA9PT0gXCJldi1cIikge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIGFkZCBldi1mb28gc3VwcG9ydFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHByb3BzW3Byb3BOYW1lXSA9IGV2SG9vayh2YWx1ZSk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIGlzQ2hpbGQoeCkge1xuICAgICAgICAgICAgICAgIHJldHVybiBpc1ZOb2RlKHgpIHx8IGlzVlRleHQoeCkgfHwgaXNXaWRnZXQoeCkgfHwgaXNWVGh1bmsoeCk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIGlzQ2hpbGRyZW4oeCkge1xuICAgICAgICAgICAgICAgIHJldHVybiB0eXBlb2YgeCA9PT0gXCJzdHJpbmdcIiB8fCBpc0FycmF5KHgpIHx8IGlzQ2hpbGQoeCk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIFVuZXhwZWN0ZWRWaXJ0dWFsRWxlbWVudChkYXRhKSB7XG4gICAgICAgICAgICAgICAgdmFyIGVyciA9IG5ldyBFcnJvcigpO1xuXG4gICAgICAgICAgICAgICAgZXJyLnR5cGUgPSBcInZpcnR1YWwtaHlwZXJzY3JpcHQudW5leHBlY3RlZC52aXJ0dWFsLWVsZW1lbnRcIjtcbiAgICAgICAgICAgICAgICBlcnIubWVzc2FnZSA9IFwiVW5leHBlY3RlZCB2aXJ0dWFsIGNoaWxkIHBhc3NlZCB0byBoKCkuXFxuXCIgKyBcIkV4cGVjdGVkIGEgVk5vZGUgLyBWdGh1bmsgLyBWV2lkZ2V0IC8gc3RyaW5nIGJ1dDpcXG5cIiArIFwiZ290OlxcblwiICsgZXJyb3JTdHJpbmcoZGF0YS5mb3JlaWduT2JqZWN0KSArIFwiLlxcblwiICsgXCJUaGUgcGFyZW50IHZub2RlIGlzOlxcblwiICsgZXJyb3JTdHJpbmcoZGF0YS5wYXJlbnRWbm9kZSk7XG4gICAgICAgICAgICAgICAgXCJcXG5cIiArIFwiU3VnZ2VzdGVkIGZpeDogY2hhbmdlIHlvdXIgYGgoLi4uLCBbIC4uLiBdKWAgY2FsbHNpdGUuXCI7XG4gICAgICAgICAgICAgICAgZXJyLmZvcmVpZ25PYmplY3QgPSBkYXRhLmZvcmVpZ25PYmplY3Q7XG4gICAgICAgICAgICAgICAgZXJyLnBhcmVudFZub2RlID0gZGF0YS5wYXJlbnRWbm9kZTtcblxuICAgICAgICAgICAgICAgIHJldHVybiBlcnI7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIGVycm9yU3RyaW5nKG9iaikge1xuICAgICAgICAgICAgICAgIHRyeSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBKU09OLnN0cmluZ2lmeShvYmosIG51bGwsIFwiICAgIFwiKTtcbiAgICAgICAgICAgICAgICB9IGNhdGNoIChlKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBTdHJpbmcob2JqKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH0sIHsgXCIuLi92bm9kZS9pcy10aHVua1wiOiAyNSwgXCIuLi92bm9kZS9pcy12aG9va1wiOiAyNiwgXCIuLi92bm9kZS9pcy12bm9kZVwiOiAyNywgXCIuLi92bm9kZS9pcy12dGV4dFwiOiAyOCwgXCIuLi92bm9kZS9pcy13aWRnZXRcIjogMjksIFwiLi4vdm5vZGUvdm5vZGUuanNcIjogMzEsIFwiLi4vdm5vZGUvdnRleHQuanNcIjogMzMsIFwiLi9ob29rcy9ldi1ob29rLmpzXCI6IDIwLCBcIi4vaG9va3Mvc29mdC1zZXQtaG9vay5qc1wiOiAyMSwgXCIuL3BhcnNlLXRhZy5qc1wiOiAyMywgXCJ4LWlzLWFycmF5XCI6IDEyIH1dLCAyMzogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHtcbiAgICAgICAgICAgIFwidXNlIHN0cmljdFwiO1xuXG4gICAgICAgICAgICB2YXIgc3BsaXQgPSByZXF1aXJlKFwiYnJvd3Nlci1zcGxpdFwiKTtcblxuICAgICAgICAgICAgdmFyIGNsYXNzSWRTcGxpdCA9IC8oW1xcLiNdP1thLXpBLVowLTlcXHUwMDdGLVxcdUZGRkZfOi1dKykvO1xuICAgICAgICAgICAgdmFyIG5vdENsYXNzSWQgPSAvXlxcLnwjLztcblxuICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBwYXJzZVRhZztcblxuICAgICAgICAgICAgZnVuY3Rpb24gcGFyc2VUYWcodGFnLCBwcm9wcykge1xuICAgICAgICAgICAgICAgIGlmICghdGFnKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBcIkRJVlwiO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHZhciBub0lkID0gIXByb3BzLmhhc093blByb3BlcnR5KFwiaWRcIik7XG5cbiAgICAgICAgICAgICAgICB2YXIgdGFnUGFydHMgPSBzcGxpdCh0YWcsIGNsYXNzSWRTcGxpdCk7XG4gICAgICAgICAgICAgICAgdmFyIHRhZ05hbWUgPSBudWxsO1xuXG4gICAgICAgICAgICAgICAgaWYgKG5vdENsYXNzSWQudGVzdCh0YWdQYXJ0c1sxXSkpIHtcbiAgICAgICAgICAgICAgICAgICAgdGFnTmFtZSA9IFwiRElWXCI7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgdmFyIGNsYXNzZXMsIHBhcnQsIHR5cGUsIGk7XG5cbiAgICAgICAgICAgICAgICBmb3IgKGkgPSAwOyBpIDwgdGFnUGFydHMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgICAgICAgICAgcGFydCA9IHRhZ1BhcnRzW2ldO1xuXG4gICAgICAgICAgICAgICAgICAgIGlmICghcGFydCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgY29udGludWU7XG4gICAgICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgICAgICB0eXBlID0gcGFydC5jaGFyQXQoMCk7XG5cbiAgICAgICAgICAgICAgICAgICAgaWYgKCF0YWdOYW1lKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICB0YWdOYW1lID0gcGFydDtcbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIGlmICh0eXBlID09PSBcIi5cIikge1xuICAgICAgICAgICAgICAgICAgICAgICAgY2xhc3NlcyA9IGNsYXNzZXMgfHwgW107XG4gICAgICAgICAgICAgICAgICAgICAgICBjbGFzc2VzLnB1c2gocGFydC5zdWJzdHJpbmcoMSwgcGFydC5sZW5ndGgpKTtcbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIGlmICh0eXBlID09PSBcIiNcIiAmJiBub0lkKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBwcm9wcy5pZCA9IHBhcnQuc3Vic3RyaW5nKDEsIHBhcnQubGVuZ3RoKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIGlmIChjbGFzc2VzKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmIChwcm9wcy5jbGFzc05hbWUpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGNsYXNzZXMucHVzaChwcm9wcy5jbGFzc05hbWUpO1xuICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgcHJvcHMuY2xhc3NOYW1lID0gY2xhc3Nlcy5qb2luKFwiIFwiKTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICByZXR1cm4gcHJvcHMubmFtZXNwYWNlID8gdGFnTmFtZSA6IHRhZ05hbWUudG9VcHBlckNhc2UoKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSwgeyBcImJyb3dzZXItc3BsaXRcIjogNSB9XSwgMjQ6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICB2YXIgaXNWTm9kZSA9IHJlcXVpcmUoXCIuL2lzLXZub2RlXCIpO1xuICAgICAgICAgICAgdmFyIGlzVlRleHQgPSByZXF1aXJlKFwiLi9pcy12dGV4dFwiKTtcbiAgICAgICAgICAgIHZhciBpc1dpZGdldCA9IHJlcXVpcmUoXCIuL2lzLXdpZGdldFwiKTtcbiAgICAgICAgICAgIHZhciBpc1RodW5rID0gcmVxdWlyZShcIi4vaXMtdGh1bmtcIik7XG5cbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gaGFuZGxlVGh1bms7XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIGhhbmRsZVRodW5rKGEsIGIpIHtcbiAgICAgICAgICAgICAgICB2YXIgcmVuZGVyZWRBID0gYTtcbiAgICAgICAgICAgICAgICB2YXIgcmVuZGVyZWRCID0gYjtcblxuICAgICAgICAgICAgICAgIGlmIChpc1RodW5rKGIpKSB7XG4gICAgICAgICAgICAgICAgICAgIHJlbmRlcmVkQiA9IHJlbmRlclRodW5rKGIsIGEpO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIGlmIChpc1RodW5rKGEpKSB7XG4gICAgICAgICAgICAgICAgICAgIHJlbmRlcmVkQSA9IHJlbmRlclRodW5rKGEsIG51bGwpO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHJldHVybiB7XG4gICAgICAgICAgICAgICAgICAgIGE6IHJlbmRlcmVkQSxcbiAgICAgICAgICAgICAgICAgICAgYjogcmVuZGVyZWRCXG4gICAgICAgICAgICAgICAgfTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZnVuY3Rpb24gcmVuZGVyVGh1bmsodGh1bmssIHByZXZpb3VzKSB7XG4gICAgICAgICAgICAgICAgdmFyIHJlbmRlcmVkVGh1bmsgPSB0aHVuay52bm9kZTtcblxuICAgICAgICAgICAgICAgIGlmICghcmVuZGVyZWRUaHVuaykge1xuICAgICAgICAgICAgICAgICAgICByZW5kZXJlZFRodW5rID0gdGh1bmsudm5vZGUgPSB0aHVuay5yZW5kZXIocHJldmlvdXMpO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIGlmICghKGlzVk5vZGUocmVuZGVyZWRUaHVuaykgfHwgaXNWVGV4dChyZW5kZXJlZFRodW5rKSB8fCBpc1dpZGdldChyZW5kZXJlZFRodW5rKSkpIHtcbiAgICAgICAgICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKFwidGh1bmsgZGlkIG5vdCByZXR1cm4gYSB2YWxpZCBub2RlXCIpO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHJldHVybiByZW5kZXJlZFRodW5rO1xuICAgICAgICAgICAgfVxuICAgICAgICB9LCB7IFwiLi9pcy10aHVua1wiOiAyNSwgXCIuL2lzLXZub2RlXCI6IDI3LCBcIi4vaXMtdnRleHRcIjogMjgsIFwiLi9pcy13aWRnZXRcIjogMjkgfV0sIDI1OiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge1xuICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBpc1RodW5rO1xuXG4gICAgICAgICAgICBmdW5jdGlvbiBpc1RodW5rKHQpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gdCAmJiB0LnR5cGUgPT09IFwiVGh1bmtcIjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSwge31dLCAyNjogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHtcbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gaXNIb29rO1xuXG4gICAgICAgICAgICBmdW5jdGlvbiBpc0hvb2soaG9vaykge1xuICAgICAgICAgICAgICAgIHJldHVybiBob29rICYmICh0eXBlb2YgaG9vay5ob29rID09PSBcImZ1bmN0aW9uXCIgJiYgIWhvb2suaGFzT3duUHJvcGVydHkoXCJob29rXCIpIHx8IHR5cGVvZiBob29rLnVuaG9vayA9PT0gXCJmdW5jdGlvblwiICYmICFob29rLmhhc093blByb3BlcnR5KFwidW5ob29rXCIpKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSwge31dLCAyNzogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHtcbiAgICAgICAgICAgIHZhciB2ZXJzaW9uID0gcmVxdWlyZShcIi4vdmVyc2lvblwiKTtcblxuICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBpc1ZpcnR1YWxOb2RlO1xuXG4gICAgICAgICAgICBmdW5jdGlvbiBpc1ZpcnR1YWxOb2RlKHgpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4geCAmJiB4LnR5cGUgPT09IFwiVmlydHVhbE5vZGVcIiAmJiB4LnZlcnNpb24gPT09IHZlcnNpb247XG4gICAgICAgICAgICB9XG4gICAgICAgIH0sIHsgXCIuL3ZlcnNpb25cIjogMzAgfV0sIDI4OiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge1xuICAgICAgICAgICAgdmFyIHZlcnNpb24gPSByZXF1aXJlKFwiLi92ZXJzaW9uXCIpO1xuXG4gICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IGlzVmlydHVhbFRleHQ7XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIGlzVmlydHVhbFRleHQoeCkge1xuICAgICAgICAgICAgICAgIHJldHVybiB4ICYmIHgudHlwZSA9PT0gXCJWaXJ0dWFsVGV4dFwiICYmIHgudmVyc2lvbiA9PT0gdmVyc2lvbjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSwgeyBcIi4vdmVyc2lvblwiOiAzMCB9XSwgMjk6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IGlzV2lkZ2V0O1xuXG4gICAgICAgICAgICBmdW5jdGlvbiBpc1dpZGdldCh3KSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHcgJiYgdy50eXBlID09PSBcIldpZGdldFwiO1xuICAgICAgICAgICAgfVxuICAgICAgICB9LCB7fV0sIDMwOiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge1xuICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBcIjJcIjtcbiAgICAgICAgfSwge31dLCAzMTogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHtcbiAgICAgICAgICAgIHZhciB2ZXJzaW9uID0gcmVxdWlyZShcIi4vdmVyc2lvblwiKTtcbiAgICAgICAgICAgIHZhciBpc1ZOb2RlID0gcmVxdWlyZShcIi4vaXMtdm5vZGVcIik7XG4gICAgICAgICAgICB2YXIgaXNXaWRnZXQgPSByZXF1aXJlKFwiLi9pcy13aWRnZXRcIik7XG4gICAgICAgICAgICB2YXIgaXNUaHVuayA9IHJlcXVpcmUoXCIuL2lzLXRodW5rXCIpO1xuICAgICAgICAgICAgdmFyIGlzVkhvb2sgPSByZXF1aXJlKFwiLi9pcy12aG9va1wiKTtcblxuICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBWaXJ0dWFsTm9kZTtcblxuICAgICAgICAgICAgdmFyIG5vUHJvcGVydGllcyA9IHt9O1xuICAgICAgICAgICAgdmFyIG5vQ2hpbGRyZW4gPSBbXTtcblxuICAgICAgICAgICAgZnVuY3Rpb24gVmlydHVhbE5vZGUodGFnTmFtZSwgcHJvcGVydGllcywgY2hpbGRyZW4sIGtleSwgbmFtZXNwYWNlKSB7XG4gICAgICAgICAgICAgICAgdGhpcy50YWdOYW1lID0gdGFnTmFtZTtcbiAgICAgICAgICAgICAgICB0aGlzLnByb3BlcnRpZXMgPSBwcm9wZXJ0aWVzIHx8IG5vUHJvcGVydGllcztcbiAgICAgICAgICAgICAgICB0aGlzLmNoaWxkcmVuID0gY2hpbGRyZW4gfHwgbm9DaGlsZHJlbjtcbiAgICAgICAgICAgICAgICB0aGlzLmtleSA9IGtleSAhPSBudWxsID8gU3RyaW5nKGtleSkgOiB1bmRlZmluZWQ7XG4gICAgICAgICAgICAgICAgdGhpcy5uYW1lc3BhY2UgPSB0eXBlb2YgbmFtZXNwYWNlID09PSBcInN0cmluZ1wiID8gbmFtZXNwYWNlIDogbnVsbDtcblxuICAgICAgICAgICAgICAgIHZhciBjb3VudCA9IGNoaWxkcmVuICYmIGNoaWxkcmVuLmxlbmd0aCB8fCAwO1xuICAgICAgICAgICAgICAgIHZhciBkZXNjZW5kYW50cyA9IDA7XG4gICAgICAgICAgICAgICAgdmFyIGhhc1dpZGdldHMgPSBmYWxzZTtcbiAgICAgICAgICAgICAgICB2YXIgaGFzVGh1bmtzID0gZmFsc2U7XG4gICAgICAgICAgICAgICAgdmFyIGRlc2NlbmRhbnRIb29rcyA9IGZhbHNlO1xuICAgICAgICAgICAgICAgIHZhciBob29rcztcblxuICAgICAgICAgICAgICAgIGZvciAodmFyIHByb3BOYW1lIGluIHByb3BlcnRpZXMpIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKHByb3BlcnRpZXMuaGFzT3duUHJvcGVydHkocHJvcE5hbWUpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICB2YXIgcHJvcGVydHkgPSBwcm9wZXJ0aWVzW3Byb3BOYW1lXTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChpc1ZIb29rKHByb3BlcnR5KSAmJiBwcm9wZXJ0eS51bmhvb2spIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoIWhvb2tzKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGhvb2tzID0ge307XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaG9va3NbcHJvcE5hbWVdID0gcHJvcGVydHk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IGNvdW50OyBpKyspIHtcbiAgICAgICAgICAgICAgICAgICAgdmFyIGNoaWxkID0gY2hpbGRyZW5baV07XG4gICAgICAgICAgICAgICAgICAgIGlmIChpc1ZOb2RlKGNoaWxkKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgZGVzY2VuZGFudHMgKz0gY2hpbGQuY291bnQgfHwgMDtcblxuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKCFoYXNXaWRnZXRzICYmIGNoaWxkLmhhc1dpZGdldHMpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBoYXNXaWRnZXRzID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKCFoYXNUaHVua3MgJiYgY2hpbGQuaGFzVGh1bmtzKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaGFzVGh1bmtzID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKCFkZXNjZW5kYW50SG9va3MgJiYgKGNoaWxkLmhvb2tzIHx8IGNoaWxkLmRlc2NlbmRhbnRIb29rcykpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBkZXNjZW5kYW50SG9va3MgPSB0cnVlO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKCFoYXNXaWRnZXRzICYmIGlzV2lkZ2V0KGNoaWxkKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHR5cGVvZiBjaGlsZC5kZXN0cm95ID09PSBcImZ1bmN0aW9uXCIpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBoYXNXaWRnZXRzID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIGlmICghaGFzVGh1bmtzICYmIGlzVGh1bmsoY2hpbGQpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBoYXNUaHVua3MgPSB0cnVlO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgdGhpcy5jb3VudCA9IGNvdW50ICsgZGVzY2VuZGFudHM7XG4gICAgICAgICAgICAgICAgdGhpcy5oYXNXaWRnZXRzID0gaGFzV2lkZ2V0cztcbiAgICAgICAgICAgICAgICB0aGlzLmhhc1RodW5rcyA9IGhhc1RodW5rcztcbiAgICAgICAgICAgICAgICB0aGlzLmhvb2tzID0gaG9va3M7XG4gICAgICAgICAgICAgICAgdGhpcy5kZXNjZW5kYW50SG9va3MgPSBkZXNjZW5kYW50SG9va3M7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIFZpcnR1YWxOb2RlLnByb3RvdHlwZS52ZXJzaW9uID0gdmVyc2lvbjtcbiAgICAgICAgICAgIFZpcnR1YWxOb2RlLnByb3RvdHlwZS50eXBlID0gXCJWaXJ0dWFsTm9kZVwiO1xuICAgICAgICB9LCB7IFwiLi9pcy10aHVua1wiOiAyNSwgXCIuL2lzLXZob29rXCI6IDI2LCBcIi4vaXMtdm5vZGVcIjogMjcsIFwiLi9pcy13aWRnZXRcIjogMjksIFwiLi92ZXJzaW9uXCI6IDMwIH1dLCAzMjogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHtcbiAgICAgICAgICAgIHZhciB2ZXJzaW9uID0gcmVxdWlyZShcIi4vdmVyc2lvblwiKTtcblxuICAgICAgICAgICAgVmlydHVhbFBhdGNoLk5PTkUgPSAwO1xuICAgICAgICAgICAgVmlydHVhbFBhdGNoLlZURVhUID0gMTtcbiAgICAgICAgICAgIFZpcnR1YWxQYXRjaC5WTk9ERSA9IDI7XG4gICAgICAgICAgICBWaXJ0dWFsUGF0Y2guV0lER0VUID0gMztcbiAgICAgICAgICAgIFZpcnR1YWxQYXRjaC5QUk9QUyA9IDQ7XG4gICAgICAgICAgICBWaXJ0dWFsUGF0Y2guT1JERVIgPSA1O1xuICAgICAgICAgICAgVmlydHVhbFBhdGNoLklOU0VSVCA9IDY7XG4gICAgICAgICAgICBWaXJ0dWFsUGF0Y2guUkVNT1ZFID0gNztcbiAgICAgICAgICAgIFZpcnR1YWxQYXRjaC5USFVOSyA9IDg7XG5cbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gVmlydHVhbFBhdGNoO1xuXG4gICAgICAgICAgICBmdW5jdGlvbiBWaXJ0dWFsUGF0Y2godHlwZSwgdk5vZGUsIHBhdGNoKSB7XG4gICAgICAgICAgICAgICAgdGhpcy50eXBlID0gTnVtYmVyKHR5cGUpO1xuICAgICAgICAgICAgICAgIHRoaXMudk5vZGUgPSB2Tm9kZTtcbiAgICAgICAgICAgICAgICB0aGlzLnBhdGNoID0gcGF0Y2g7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIFZpcnR1YWxQYXRjaC5wcm90b3R5cGUudmVyc2lvbiA9IHZlcnNpb247XG4gICAgICAgICAgICBWaXJ0dWFsUGF0Y2gucHJvdG90eXBlLnR5cGUgPSBcIlZpcnR1YWxQYXRjaFwiO1xuICAgICAgICB9LCB7IFwiLi92ZXJzaW9uXCI6IDMwIH1dLCAzMzogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHtcbiAgICAgICAgICAgIHZhciB2ZXJzaW9uID0gcmVxdWlyZShcIi4vdmVyc2lvblwiKTtcblxuICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBWaXJ0dWFsVGV4dDtcblxuICAgICAgICAgICAgZnVuY3Rpb24gVmlydHVhbFRleHQodGV4dCkge1xuICAgICAgICAgICAgICAgIHRoaXMudGV4dCA9IFN0cmluZyh0ZXh0KTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgVmlydHVhbFRleHQucHJvdG90eXBlLnZlcnNpb24gPSB2ZXJzaW9uO1xuICAgICAgICAgICAgVmlydHVhbFRleHQucHJvdG90eXBlLnR5cGUgPSBcIlZpcnR1YWxUZXh0XCI7XG4gICAgICAgIH0sIHsgXCIuL3ZlcnNpb25cIjogMzAgfV0sIDM0OiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge1xuICAgICAgICAgICAgdmFyIGlzT2JqZWN0ID0gcmVxdWlyZShcImlzLW9iamVjdFwiKTtcbiAgICAgICAgICAgIHZhciBpc0hvb2sgPSByZXF1aXJlKFwiLi4vdm5vZGUvaXMtdmhvb2tcIik7XG5cbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gZGlmZlByb3BzO1xuXG4gICAgICAgICAgICBmdW5jdGlvbiBkaWZmUHJvcHMoYSwgYikge1xuICAgICAgICAgICAgICAgIHZhciBkaWZmO1xuXG4gICAgICAgICAgICAgICAgZm9yICh2YXIgYUtleSBpbiBhKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmICghKGFLZXkgaW4gYikpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGRpZmYgPSBkaWZmIHx8IHt9O1xuICAgICAgICAgICAgICAgICAgICAgICAgZGlmZlthS2V5XSA9IHVuZGVmaW5lZDtcbiAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgIHZhciBhVmFsdWUgPSBhW2FLZXldO1xuICAgICAgICAgICAgICAgICAgICB2YXIgYlZhbHVlID0gYlthS2V5XTtcblxuICAgICAgICAgICAgICAgICAgICBpZiAoYVZhbHVlID09PSBiVmFsdWUpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnRpbnVlO1xuICAgICAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKGlzT2JqZWN0KGFWYWx1ZSkgJiYgaXNPYmplY3QoYlZhbHVlKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGdldFByb3RvdHlwZShiVmFsdWUpICE9PSBnZXRQcm90b3R5cGUoYVZhbHVlKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRpZmYgPSBkaWZmIHx8IHt9O1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRpZmZbYUtleV0gPSBiVmFsdWU7XG4gICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKGlzSG9vayhiVmFsdWUpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgZGlmZiA9IGRpZmYgfHwge307XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgZGlmZlthS2V5XSA9IGJWYWx1ZTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdmFyIG9iamVjdERpZmYgPSBkaWZmUHJvcHMoYVZhbHVlLCBiVmFsdWUpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChvYmplY3REaWZmKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRpZmYgPSBkaWZmIHx8IHt9O1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBkaWZmW2FLZXldID0gb2JqZWN0RGlmZjtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBkaWZmID0gZGlmZiB8fCB7fTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGRpZmZbYUtleV0gPSBiVmFsdWU7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICBmb3IgKHZhciBiS2V5IGluIGIpIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKCEoYktleSBpbiBhKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgZGlmZiA9IGRpZmYgfHwge307XG4gICAgICAgICAgICAgICAgICAgICAgICBkaWZmW2JLZXldID0gYltiS2V5XTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHJldHVybiBkaWZmO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBmdW5jdGlvbiBnZXRQcm90b3R5cGUodmFsdWUpIHtcbiAgICAgICAgICAgICAgICBpZiAoT2JqZWN0LmdldFByb3RvdHlwZU9mKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBPYmplY3QuZ2V0UHJvdG90eXBlT2YodmFsdWUpO1xuICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAodmFsdWUuX19wcm90b19fKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiB2YWx1ZS5fX3Byb3RvX187XG4gICAgICAgICAgICAgICAgfSBlbHNlIGlmICh2YWx1ZS5jb25zdHJ1Y3Rvcikge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gdmFsdWUuY29uc3RydWN0b3IucHJvdG90eXBlO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgfSwgeyBcIi4uL3Zub2RlL2lzLXZob29rXCI6IDI2LCBcImlzLW9iamVjdFwiOiAxMSB9XSwgMzU6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICB2YXIgaXNBcnJheSA9IHJlcXVpcmUoXCJ4LWlzLWFycmF5XCIpO1xuXG4gICAgICAgICAgICB2YXIgVlBhdGNoID0gcmVxdWlyZShcIi4uL3Zub2RlL3ZwYXRjaFwiKTtcbiAgICAgICAgICAgIHZhciBpc1ZOb2RlID0gcmVxdWlyZShcIi4uL3Zub2RlL2lzLXZub2RlXCIpO1xuICAgICAgICAgICAgdmFyIGlzVlRleHQgPSByZXF1aXJlKFwiLi4vdm5vZGUvaXMtdnRleHRcIik7XG4gICAgICAgICAgICB2YXIgaXNXaWRnZXQgPSByZXF1aXJlKFwiLi4vdm5vZGUvaXMtd2lkZ2V0XCIpO1xuICAgICAgICAgICAgdmFyIGlzVGh1bmsgPSByZXF1aXJlKFwiLi4vdm5vZGUvaXMtdGh1bmtcIik7XG4gICAgICAgICAgICB2YXIgaGFuZGxlVGh1bmsgPSByZXF1aXJlKFwiLi4vdm5vZGUvaGFuZGxlLXRodW5rXCIpO1xuXG4gICAgICAgICAgICB2YXIgZGlmZlByb3BzID0gcmVxdWlyZShcIi4vZGlmZi1wcm9wc1wiKTtcblxuICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBkaWZmO1xuXG4gICAgICAgICAgICBmdW5jdGlvbiBkaWZmKGEsIGIpIHtcbiAgICAgICAgICAgICAgICB2YXIgcGF0Y2ggPSB7IGE6IGEgfTtcbiAgICAgICAgICAgICAgICB3YWxrKGEsIGIsIHBhdGNoLCAwKTtcbiAgICAgICAgICAgICAgICByZXR1cm4gcGF0Y2g7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIHdhbGsoYSwgYiwgcGF0Y2gsIGluZGV4KSB7XG4gICAgICAgICAgICAgICAgaWYgKGEgPT09IGIpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHZhciBhcHBseSA9IHBhdGNoW2luZGV4XTtcbiAgICAgICAgICAgICAgICB2YXIgYXBwbHlDbGVhciA9IGZhbHNlO1xuXG4gICAgICAgICAgICAgICAgaWYgKGlzVGh1bmsoYSkgfHwgaXNUaHVuayhiKSkge1xuICAgICAgICAgICAgICAgICAgICB0aHVua3MoYSwgYiwgcGF0Y2gsIGluZGV4KTtcbiAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKGIgPT0gbnVsbCkge1xuXG4gICAgICAgICAgICAgICAgICAgIC8vIElmIGEgaXMgYSB3aWRnZXQgd2Ugd2lsbCBhZGQgYSByZW1vdmUgcGF0Y2ggZm9yIGl0XG4gICAgICAgICAgICAgICAgICAgIC8vIE90aGVyd2lzZSBhbnkgY2hpbGQgd2lkZ2V0cy9ob29rcyBtdXN0IGJlIGRlc3Ryb3llZC5cbiAgICAgICAgICAgICAgICAgICAgLy8gVGhpcyBwcmV2ZW50cyBhZGRpbmcgdHdvIHJlbW92ZSBwYXRjaGVzIGZvciBhIHdpZGdldC5cbiAgICAgICAgICAgICAgICAgICAgaWYgKCFpc1dpZGdldChhKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgY2xlYXJTdGF0ZShhLCBwYXRjaCwgaW5kZXgpO1xuICAgICAgICAgICAgICAgICAgICAgICAgYXBwbHkgPSBwYXRjaFtpbmRleF07XG4gICAgICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgICAgICBhcHBseSA9IGFwcGVuZFBhdGNoKGFwcGx5LCBuZXcgVlBhdGNoKFZQYXRjaC5SRU1PVkUsIGEsIGIpKTtcbiAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKGlzVk5vZGUoYikpIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKGlzVk5vZGUoYSkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChhLnRhZ05hbWUgPT09IGIudGFnTmFtZSAmJiBhLm5hbWVzcGFjZSA9PT0gYi5uYW1lc3BhY2UgJiYgYS5rZXkgPT09IGIua2V5KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdmFyIHByb3BzUGF0Y2ggPSBkaWZmUHJvcHMoYS5wcm9wZXJ0aWVzLCBiLnByb3BlcnRpZXMpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChwcm9wc1BhdGNoKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGFwcGx5ID0gYXBwZW5kUGF0Y2goYXBwbHksIG5ldyBWUGF0Y2goVlBhdGNoLlBST1BTLCBhLCBwcm9wc1BhdGNoKSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGFwcGx5ID0gZGlmZkNoaWxkcmVuKGEsIGIsIHBhdGNoLCBhcHBseSwgaW5kZXgpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBhcHBseSA9IGFwcGVuZFBhdGNoKGFwcGx5LCBuZXcgVlBhdGNoKFZQYXRjaC5WTk9ERSwgYSwgYikpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGFwcGx5Q2xlYXIgPSB0cnVlO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgYXBwbHkgPSBhcHBlbmRQYXRjaChhcHBseSwgbmV3IFZQYXRjaChWUGF0Y2guVk5PREUsIGEsIGIpKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGFwcGx5Q2xlYXIgPSB0cnVlO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfSBlbHNlIGlmIChpc1ZUZXh0KGIpKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmICghaXNWVGV4dChhKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgYXBwbHkgPSBhcHBlbmRQYXRjaChhcHBseSwgbmV3IFZQYXRjaChWUGF0Y2guVlRFWFQsIGEsIGIpKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGFwcGx5Q2xlYXIgPSB0cnVlO1xuICAgICAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKGEudGV4dCAhPT0gYi50ZXh0KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBhcHBseSA9IGFwcGVuZFBhdGNoKGFwcGx5LCBuZXcgVlBhdGNoKFZQYXRjaC5WVEVYVCwgYSwgYikpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfSBlbHNlIGlmIChpc1dpZGdldChiKSkge1xuICAgICAgICAgICAgICAgICAgICBpZiAoIWlzV2lkZ2V0KGEpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBhcHBseUNsZWFyID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgIGFwcGx5ID0gYXBwZW5kUGF0Y2goYXBwbHksIG5ldyBWUGF0Y2goVlBhdGNoLldJREdFVCwgYSwgYikpO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIGlmIChhcHBseSkge1xuICAgICAgICAgICAgICAgICAgICBwYXRjaFtpbmRleF0gPSBhcHBseTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICBpZiAoYXBwbHlDbGVhcikge1xuICAgICAgICAgICAgICAgICAgICBjbGVhclN0YXRlKGEsIHBhdGNoLCBpbmRleCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBmdW5jdGlvbiBkaWZmQ2hpbGRyZW4oYSwgYiwgcGF0Y2gsIGFwcGx5LCBpbmRleCkge1xuICAgICAgICAgICAgICAgIHZhciBhQ2hpbGRyZW4gPSBhLmNoaWxkcmVuO1xuICAgICAgICAgICAgICAgIHZhciBvcmRlcmVkU2V0ID0gcmVvcmRlcihhQ2hpbGRyZW4sIGIuY2hpbGRyZW4pO1xuICAgICAgICAgICAgICAgIHZhciBiQ2hpbGRyZW4gPSBvcmRlcmVkU2V0LmNoaWxkcmVuO1xuXG4gICAgICAgICAgICAgICAgdmFyIGFMZW4gPSBhQ2hpbGRyZW4ubGVuZ3RoO1xuICAgICAgICAgICAgICAgIHZhciBiTGVuID0gYkNoaWxkcmVuLmxlbmd0aDtcbiAgICAgICAgICAgICAgICB2YXIgbGVuID0gYUxlbiA+IGJMZW4gPyBhTGVuIDogYkxlbjtcblxuICAgICAgICAgICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgbGVuOyBpKyspIHtcbiAgICAgICAgICAgICAgICAgICAgdmFyIGxlZnROb2RlID0gYUNoaWxkcmVuW2ldO1xuICAgICAgICAgICAgICAgICAgICB2YXIgcmlnaHROb2RlID0gYkNoaWxkcmVuW2ldO1xuICAgICAgICAgICAgICAgICAgICBpbmRleCArPSAxO1xuXG4gICAgICAgICAgICAgICAgICAgIGlmICghbGVmdE5vZGUpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChyaWdodE5vZGUpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBFeGNlc3Mgbm9kZXMgaW4gYiBuZWVkIHRvIGJlIGFkZGVkXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgYXBwbHkgPSBhcHBlbmRQYXRjaChhcHBseSwgbmV3IFZQYXRjaChWUGF0Y2guSU5TRVJULCBudWxsLCByaWdodE5vZGUpKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHdhbGsobGVmdE5vZGUsIHJpZ2h0Tm9kZSwgcGF0Y2gsIGluZGV4KTtcbiAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgIGlmIChpc1ZOb2RlKGxlZnROb2RlKSAmJiBsZWZ0Tm9kZS5jb3VudCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgaW5kZXggKz0gbGVmdE5vZGUuY291bnQ7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICBpZiAob3JkZXJlZFNldC5tb3Zlcykge1xuICAgICAgICAgICAgICAgICAgICAvLyBSZW9yZGVyIG5vZGVzIGxhc3RcbiAgICAgICAgICAgICAgICAgICAgYXBwbHkgPSBhcHBlbmRQYXRjaChhcHBseSwgbmV3IFZQYXRjaChWUGF0Y2guT1JERVIsIGEsIG9yZGVyZWRTZXQubW92ZXMpKTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICByZXR1cm4gYXBwbHk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIGNsZWFyU3RhdGUodk5vZGUsIHBhdGNoLCBpbmRleCkge1xuICAgICAgICAgICAgICAgIC8vIFRPRE86IE1ha2UgdGhpcyBhIHNpbmdsZSB3YWxrLCBub3QgdHdvXG4gICAgICAgICAgICAgICAgdW5ob29rKHZOb2RlLCBwYXRjaCwgaW5kZXgpO1xuICAgICAgICAgICAgICAgIGRlc3Ryb3lXaWRnZXRzKHZOb2RlLCBwYXRjaCwgaW5kZXgpO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAvLyBQYXRjaCByZWNvcmRzIGZvciBhbGwgZGVzdHJveWVkIHdpZGdldHMgbXVzdCBiZSBhZGRlZCBiZWNhdXNlIHdlIG5lZWRcbiAgICAgICAgICAgIC8vIGEgRE9NIG5vZGUgcmVmZXJlbmNlIGZvciB0aGUgZGVzdHJveSBmdW5jdGlvblxuICAgICAgICAgICAgZnVuY3Rpb24gZGVzdHJveVdpZGdldHModk5vZGUsIHBhdGNoLCBpbmRleCkge1xuICAgICAgICAgICAgICAgIGlmIChpc1dpZGdldCh2Tm9kZSkpIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKHR5cGVvZiB2Tm9kZS5kZXN0cm95ID09PSBcImZ1bmN0aW9uXCIpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHBhdGNoW2luZGV4XSA9IGFwcGVuZFBhdGNoKHBhdGNoW2luZGV4XSwgbmV3IFZQYXRjaChWUGF0Y2guUkVNT1ZFLCB2Tm9kZSwgbnVsbCkpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfSBlbHNlIGlmIChpc1ZOb2RlKHZOb2RlKSAmJiAodk5vZGUuaGFzV2lkZ2V0cyB8fCB2Tm9kZS5oYXNUaHVua3MpKSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciBjaGlsZHJlbiA9IHZOb2RlLmNoaWxkcmVuO1xuICAgICAgICAgICAgICAgICAgICB2YXIgbGVuID0gY2hpbGRyZW4ubGVuZ3RoO1xuICAgICAgICAgICAgICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IGxlbjsgaSsrKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICB2YXIgY2hpbGQgPSBjaGlsZHJlbltpXTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGluZGV4ICs9IDE7XG5cbiAgICAgICAgICAgICAgICAgICAgICAgIGRlc3Ryb3lXaWRnZXRzKGNoaWxkLCBwYXRjaCwgaW5kZXgpO1xuXG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoaXNWTm9kZShjaGlsZCkgJiYgY2hpbGQuY291bnQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpbmRleCArPSBjaGlsZC5jb3VudDtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoaXNUaHVuayh2Tm9kZSkpIHtcbiAgICAgICAgICAgICAgICAgICAgdGh1bmtzKHZOb2RlLCBudWxsLCBwYXRjaCwgaW5kZXgpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgLy8gQ3JlYXRlIGEgc3ViLXBhdGNoIGZvciB0aHVua3NcbiAgICAgICAgICAgIGZ1bmN0aW9uIHRodW5rcyhhLCBiLCBwYXRjaCwgaW5kZXgpIHtcbiAgICAgICAgICAgICAgICB2YXIgbm9kZXMgPSBoYW5kbGVUaHVuayhhLCBiKTtcbiAgICAgICAgICAgICAgICB2YXIgdGh1bmtQYXRjaCA9IGRpZmYobm9kZXMuYSwgbm9kZXMuYik7XG4gICAgICAgICAgICAgICAgaWYgKGhhc1BhdGNoZXModGh1bmtQYXRjaCkpIHtcbiAgICAgICAgICAgICAgICAgICAgcGF0Y2hbaW5kZXhdID0gbmV3IFZQYXRjaChWUGF0Y2guVEhVTkssIG51bGwsIHRodW5rUGF0Y2gpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZnVuY3Rpb24gaGFzUGF0Y2hlcyhwYXRjaCkge1xuICAgICAgICAgICAgICAgIGZvciAodmFyIGluZGV4IGluIHBhdGNoKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmIChpbmRleCAhPT0gXCJhXCIpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAvLyBFeGVjdXRlIGhvb2tzIHdoZW4gdHdvIG5vZGVzIGFyZSBpZGVudGljYWxcbiAgICAgICAgICAgIGZ1bmN0aW9uIHVuaG9vayh2Tm9kZSwgcGF0Y2gsIGluZGV4KSB7XG4gICAgICAgICAgICAgICAgaWYgKGlzVk5vZGUodk5vZGUpKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmICh2Tm9kZS5ob29rcykge1xuICAgICAgICAgICAgICAgICAgICAgICAgcGF0Y2hbaW5kZXhdID0gYXBwZW5kUGF0Y2gocGF0Y2hbaW5kZXhdLCBuZXcgVlBhdGNoKFZQYXRjaC5QUk9QUywgdk5vZGUsIHVuZGVmaW5lZEtleXModk5vZGUuaG9va3MpKSk7XG4gICAgICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgICAgICBpZiAodk5vZGUuZGVzY2VuZGFudEhvb2tzIHx8IHZOb2RlLmhhc1RodW5rcykge1xuICAgICAgICAgICAgICAgICAgICAgICAgdmFyIGNoaWxkcmVuID0gdk5vZGUuY2hpbGRyZW47XG4gICAgICAgICAgICAgICAgICAgICAgICB2YXIgbGVuID0gY2hpbGRyZW4ubGVuZ3RoO1xuICAgICAgICAgICAgICAgICAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCBsZW47IGkrKykge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZhciBjaGlsZCA9IGNoaWxkcmVuW2ldO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGluZGV4ICs9IDE7XG5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB1bmhvb2soY2hpbGQsIHBhdGNoLCBpbmRleCk7XG5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoaXNWTm9kZShjaGlsZCkgJiYgY2hpbGQuY291bnQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaW5kZXggKz0gY2hpbGQuY291bnQ7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfSBlbHNlIGlmIChpc1RodW5rKHZOb2RlKSkge1xuICAgICAgICAgICAgICAgICAgICB0aHVua3Modk5vZGUsIG51bGwsIHBhdGNoLCBpbmRleCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBmdW5jdGlvbiB1bmRlZmluZWRLZXlzKG9iaikge1xuICAgICAgICAgICAgICAgIHZhciByZXN1bHQgPSB7fTtcblxuICAgICAgICAgICAgICAgIGZvciAodmFyIGtleSBpbiBvYmopIHtcbiAgICAgICAgICAgICAgICAgICAgcmVzdWx0W2tleV0gPSB1bmRlZmluZWQ7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgcmV0dXJuIHJlc3VsdDtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgLy8gTGlzdCBkaWZmLCBuYWl2ZSBsZWZ0IHRvIHJpZ2h0IHJlb3JkZXJpbmdcbiAgICAgICAgICAgIGZ1bmN0aW9uIHJlb3JkZXIoYUNoaWxkcmVuLCBiQ2hpbGRyZW4pIHtcbiAgICAgICAgICAgICAgICAvLyBPKE0pIHRpbWUsIE8oTSkgbWVtb3J5XG4gICAgICAgICAgICAgICAgdmFyIGJDaGlsZEluZGV4ID0ga2V5SW5kZXgoYkNoaWxkcmVuKTtcbiAgICAgICAgICAgICAgICB2YXIgYktleXMgPSBiQ2hpbGRJbmRleC5rZXlzO1xuICAgICAgICAgICAgICAgIHZhciBiRnJlZSA9IGJDaGlsZEluZGV4LmZyZWU7XG5cbiAgICAgICAgICAgICAgICBpZiAoYkZyZWUubGVuZ3RoID09PSBiQ2hpbGRyZW4ubGVuZ3RoKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiB7XG4gICAgICAgICAgICAgICAgICAgICAgICBjaGlsZHJlbjogYkNoaWxkcmVuLFxuICAgICAgICAgICAgICAgICAgICAgICAgbW92ZXM6IG51bGxcbiAgICAgICAgICAgICAgICAgICAgfTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAvLyBPKE4pIHRpbWUsIE8oTikgbWVtb3J5XG4gICAgICAgICAgICAgICAgdmFyIGFDaGlsZEluZGV4ID0ga2V5SW5kZXgoYUNoaWxkcmVuKTtcbiAgICAgICAgICAgICAgICB2YXIgYUtleXMgPSBhQ2hpbGRJbmRleC5rZXlzO1xuICAgICAgICAgICAgICAgIHZhciBhRnJlZSA9IGFDaGlsZEluZGV4LmZyZWU7XG5cbiAgICAgICAgICAgICAgICBpZiAoYUZyZWUubGVuZ3RoID09PSBhQ2hpbGRyZW4ubGVuZ3RoKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiB7XG4gICAgICAgICAgICAgICAgICAgICAgICBjaGlsZHJlbjogYkNoaWxkcmVuLFxuICAgICAgICAgICAgICAgICAgICAgICAgbW92ZXM6IG51bGxcbiAgICAgICAgICAgICAgICAgICAgfTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAvLyBPKE1BWChOLCBNKSkgbWVtb3J5XG4gICAgICAgICAgICAgICAgdmFyIG5ld0NoaWxkcmVuID0gW107XG5cbiAgICAgICAgICAgICAgICB2YXIgZnJlZUluZGV4ID0gMDtcbiAgICAgICAgICAgICAgICB2YXIgZnJlZUNvdW50ID0gYkZyZWUubGVuZ3RoO1xuICAgICAgICAgICAgICAgIHZhciBkZWxldGVkSXRlbXMgPSAwO1xuXG4gICAgICAgICAgICAgICAgLy8gSXRlcmF0ZSB0aHJvdWdoIGEgYW5kIG1hdGNoIGEgbm9kZSBpbiBiXG4gICAgICAgICAgICAgICAgLy8gTyhOKSB0aW1lLFxuICAgICAgICAgICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgYUNoaWxkcmVuLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciBhSXRlbSA9IGFDaGlsZHJlbltpXTtcbiAgICAgICAgICAgICAgICAgICAgdmFyIGl0ZW1JbmRleDtcblxuICAgICAgICAgICAgICAgICAgICBpZiAoYUl0ZW0ua2V5KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoYktleXMuaGFzT3duUHJvcGVydHkoYUl0ZW0ua2V5KSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIE1hdGNoIHVwIHRoZSBvbGQga2V5c1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGl0ZW1JbmRleCA9IGJLZXlzW2FJdGVtLmtleV07XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgbmV3Q2hpbGRyZW4ucHVzaChiQ2hpbGRyZW5baXRlbUluZGV4XSk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIFJlbW92ZSBvbGQga2V5ZWQgaXRlbXNcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpdGVtSW5kZXggPSBpIC0gZGVsZXRlZEl0ZW1zKys7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgbmV3Q2hpbGRyZW4ucHVzaChudWxsKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIE1hdGNoIHRoZSBpdGVtIGluIGEgd2l0aCB0aGUgbmV4dCBmcmVlIGl0ZW0gaW4gYlxuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGZyZWVJbmRleCA8IGZyZWVDb3VudCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGl0ZW1JbmRleCA9IGJGcmVlW2ZyZWVJbmRleCsrXTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBuZXdDaGlsZHJlbi5wdXNoKGJDaGlsZHJlbltpdGVtSW5kZXhdKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gVGhlcmUgYXJlIG5vIGZyZWUgaXRlbXMgaW4gYiB0byBtYXRjaCB3aXRoXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gdGhlIGZyZWUgaXRlbXMgaW4gYSwgc28gdGhlIGV4dHJhIGZyZWUgbm9kZXNcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBhcmUgZGVsZXRlZC5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpdGVtSW5kZXggPSBpIC0gZGVsZXRlZEl0ZW1zKys7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgbmV3Q2hpbGRyZW4ucHVzaChudWxsKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHZhciBsYXN0RnJlZUluZGV4ID0gZnJlZUluZGV4ID49IGJGcmVlLmxlbmd0aCA/IGJDaGlsZHJlbi5sZW5ndGggOiBiRnJlZVtmcmVlSW5kZXhdO1xuXG4gICAgICAgICAgICAgICAgLy8gSXRlcmF0ZSB0aHJvdWdoIGIgYW5kIGFwcGVuZCBhbnkgbmV3IGtleXNcbiAgICAgICAgICAgICAgICAvLyBPKE0pIHRpbWVcbiAgICAgICAgICAgICAgICBmb3IgKHZhciBqID0gMDsgaiA8IGJDaGlsZHJlbi5sZW5ndGg7IGorKykge1xuICAgICAgICAgICAgICAgICAgICB2YXIgbmV3SXRlbSA9IGJDaGlsZHJlbltqXTtcblxuICAgICAgICAgICAgICAgICAgICBpZiAobmV3SXRlbS5rZXkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmICghYUtleXMuaGFzT3duUHJvcGVydHkobmV3SXRlbS5rZXkpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gQWRkIGFueSBuZXcga2V5ZWQgaXRlbXNcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBXZSBhcmUgYWRkaW5nIG5ldyBpdGVtcyB0byB0aGUgZW5kIGFuZCB0aGVuIHNvcnRpbmcgdGhlbVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIGluIHBsYWNlLiBJbiBmdXR1cmUgd2Ugc2hvdWxkIGluc2VydCBuZXcgaXRlbXMgaW4gcGxhY2UuXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgbmV3Q2hpbGRyZW4ucHVzaChuZXdJdGVtKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIGlmIChqID49IGxhc3RGcmVlSW5kZXgpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIEFkZCBhbnkgbGVmdG92ZXIgbm9uLWtleWVkIGl0ZW1zXG4gICAgICAgICAgICAgICAgICAgICAgICBuZXdDaGlsZHJlbi5wdXNoKG5ld0l0ZW0pO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgdmFyIHNpbXVsYXRlID0gbmV3Q2hpbGRyZW4uc2xpY2UoKTtcbiAgICAgICAgICAgICAgICB2YXIgc2ltdWxhdGVJbmRleCA9IDA7XG4gICAgICAgICAgICAgICAgdmFyIHJlbW92ZXMgPSBbXTtcbiAgICAgICAgICAgICAgICB2YXIgaW5zZXJ0cyA9IFtdO1xuICAgICAgICAgICAgICAgIHZhciBzaW11bGF0ZUl0ZW07XG5cbiAgICAgICAgICAgICAgICBmb3IgKHZhciBrID0gMDsgayA8IGJDaGlsZHJlbi5sZW5ndGg7KSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciB3YW50ZWRJdGVtID0gYkNoaWxkcmVuW2tdO1xuICAgICAgICAgICAgICAgICAgICBzaW11bGF0ZUl0ZW0gPSBzaW11bGF0ZVtzaW11bGF0ZUluZGV4XTtcblxuICAgICAgICAgICAgICAgICAgICAvLyByZW1vdmUgaXRlbXNcbiAgICAgICAgICAgICAgICAgICAgd2hpbGUgKHNpbXVsYXRlSXRlbSA9PT0gbnVsbCAmJiBzaW11bGF0ZS5sZW5ndGgpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJlbW92ZXMucHVzaChyZW1vdmUoc2ltdWxhdGUsIHNpbXVsYXRlSW5kZXgsIG51bGwpKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIHNpbXVsYXRlSXRlbSA9IHNpbXVsYXRlW3NpbXVsYXRlSW5kZXhdO1xuICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgaWYgKCFzaW11bGF0ZUl0ZW0gfHwgc2ltdWxhdGVJdGVtLmtleSAhPT0gd2FudGVkSXRlbS5rZXkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIGlmIHdlIG5lZWQgYSBrZXkgaW4gdGhpcyBwb3NpdGlvbi4uLlxuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHdhbnRlZEl0ZW0ua2V5KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHNpbXVsYXRlSXRlbSAmJiBzaW11bGF0ZUl0ZW0ua2V5KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIGlmIGFuIGluc2VydCBkb2Vzbid0IHB1dCB0aGlzIGtleSBpbiBwbGFjZSwgaXQgbmVlZHMgdG8gbW92ZVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoYktleXNbc2ltdWxhdGVJdGVtLmtleV0gIT09IGsgKyAxKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICByZW1vdmVzLnB1c2gocmVtb3ZlKHNpbXVsYXRlLCBzaW11bGF0ZUluZGV4LCBzaW11bGF0ZUl0ZW0ua2V5KSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzaW11bGF0ZUl0ZW0gPSBzaW11bGF0ZVtzaW11bGF0ZUluZGV4XTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIGlmIHRoZSByZW1vdmUgZGlkbid0IHB1dCB0aGUgd2FudGVkIGl0ZW0gaW4gcGxhY2UsIHdlIG5lZWQgdG8gaW5zZXJ0IGl0XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoIXNpbXVsYXRlSXRlbSB8fCBzaW11bGF0ZUl0ZW0ua2V5ICE9PSB3YW50ZWRJdGVtLmtleSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGluc2VydHMucHVzaCh7IGtleTogd2FudGVkSXRlbS5rZXksIHRvOiBrIH0pO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gaXRlbXMgYXJlIG1hdGNoaW5nLCBzbyBza2lwIGFoZWFkXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzaW11bGF0ZUluZGV4Kys7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpbnNlcnRzLnB1c2goeyBrZXk6IHdhbnRlZEl0ZW0ua2V5LCB0bzogayB9KTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGluc2VydHMucHVzaCh7IGtleTogd2FudGVkSXRlbS5rZXksIHRvOiBrIH0pO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBrKys7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAvLyBhIGtleSBpbiBzaW11bGF0ZSBoYXMgbm8gbWF0Y2hpbmcgd2FudGVkIGtleSwgcmVtb3ZlIGl0XG4gICAgICAgICAgICAgICAgICAgICAgICBlbHNlIGlmIChzaW11bGF0ZUl0ZW0gJiYgc2ltdWxhdGVJdGVtLmtleSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlbW92ZXMucHVzaChyZW1vdmUoc2ltdWxhdGUsIHNpbXVsYXRlSW5kZXgsIHNpbXVsYXRlSXRlbS5rZXkpKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHNpbXVsYXRlSW5kZXgrKztcbiAgICAgICAgICAgICAgICAgICAgICAgIGsrKztcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIC8vIHJlbW92ZSBhbGwgdGhlIHJlbWFpbmluZyBub2RlcyBmcm9tIHNpbXVsYXRlXG4gICAgICAgICAgICAgICAgd2hpbGUgKHNpbXVsYXRlSW5kZXggPCBzaW11bGF0ZS5sZW5ndGgpIHtcbiAgICAgICAgICAgICAgICAgICAgc2ltdWxhdGVJdGVtID0gc2ltdWxhdGVbc2ltdWxhdGVJbmRleF07XG4gICAgICAgICAgICAgICAgICAgIHJlbW92ZXMucHVzaChyZW1vdmUoc2ltdWxhdGUsIHNpbXVsYXRlSW5kZXgsIHNpbXVsYXRlSXRlbSAmJiBzaW11bGF0ZUl0ZW0ua2V5KSk7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgLy8gSWYgdGhlIG9ubHkgbW92ZXMgd2UgaGF2ZSBhcmUgZGVsZXRlcyB0aGVuIHdlIGNhbiBqdXN0XG4gICAgICAgICAgICAgICAgLy8gbGV0IHRoZSBkZWxldGUgcGF0Y2ggcmVtb3ZlIHRoZXNlIGl0ZW1zLlxuICAgICAgICAgICAgICAgIGlmIChyZW1vdmVzLmxlbmd0aCA9PT0gZGVsZXRlZEl0ZW1zICYmICFpbnNlcnRzLmxlbmd0aCkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgICAgICAgICAgICAgY2hpbGRyZW46IG5ld0NoaWxkcmVuLFxuICAgICAgICAgICAgICAgICAgICAgICAgbW92ZXM6IG51bGxcbiAgICAgICAgICAgICAgICAgICAgfTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgICAgICAgICBjaGlsZHJlbjogbmV3Q2hpbGRyZW4sXG4gICAgICAgICAgICAgICAgICAgIG1vdmVzOiB7XG4gICAgICAgICAgICAgICAgICAgICAgICByZW1vdmVzOiByZW1vdmVzLFxuICAgICAgICAgICAgICAgICAgICAgICAgaW5zZXJ0czogaW5zZXJ0c1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZnVuY3Rpb24gcmVtb3ZlKGFyciwgaW5kZXgsIGtleSkge1xuICAgICAgICAgICAgICAgIGFyci5zcGxpY2UoaW5kZXgsIDEpO1xuXG4gICAgICAgICAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgICAgICAgICAgZnJvbTogaW5kZXgsXG4gICAgICAgICAgICAgICAgICAgIGtleToga2V5XG4gICAgICAgICAgICAgICAgfTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZnVuY3Rpb24ga2V5SW5kZXgoY2hpbGRyZW4pIHtcbiAgICAgICAgICAgICAgICB2YXIga2V5cyA9IHt9O1xuICAgICAgICAgICAgICAgIHZhciBmcmVlID0gW107XG4gICAgICAgICAgICAgICAgdmFyIGxlbmd0aCA9IGNoaWxkcmVuLmxlbmd0aDtcblxuICAgICAgICAgICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgbGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgICAgICAgICAgdmFyIGNoaWxkID0gY2hpbGRyZW5baV07XG5cbiAgICAgICAgICAgICAgICAgICAgaWYgKGNoaWxkLmtleSkge1xuICAgICAgICAgICAgICAgICAgICAgICAga2V5c1tjaGlsZC5rZXldID0gaTtcbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGZyZWUucHVzaChpKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHJldHVybiB7XG4gICAgICAgICAgICAgICAgICAgIGtleXM6IGtleXMsIC8vIEEgaGFzaCBvZiBrZXkgbmFtZSB0byBpbmRleFxuICAgICAgICAgICAgICAgICAgICBmcmVlOiBmcmVlIC8vIEFuIGFycmF5IG9mIHVua2V5ZWQgaXRlbSBpbmRpY2VzXG4gICAgICAgICAgICAgICAgfTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZnVuY3Rpb24gYXBwZW5kUGF0Y2goYXBwbHksIHBhdGNoKSB7XG4gICAgICAgICAgICAgICAgaWYgKGFwcGx5KSB7XG4gICAgICAgICAgICAgICAgICAgIGlmIChpc0FycmF5KGFwcGx5KSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgYXBwbHkucHVzaChwYXRjaCk7XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBhcHBseSA9IFthcHBseSwgcGF0Y2hdO1xuICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGFwcGx5O1xuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBwYXRjaDtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH0sIHsgXCIuLi92bm9kZS9oYW5kbGUtdGh1bmtcIjogMjQsIFwiLi4vdm5vZGUvaXMtdGh1bmtcIjogMjUsIFwiLi4vdm5vZGUvaXMtdm5vZGVcIjogMjcsIFwiLi4vdm5vZGUvaXMtdnRleHRcIjogMjgsIFwiLi4vdm5vZGUvaXMtd2lkZ2V0XCI6IDI5LCBcIi4uL3Zub2RlL3ZwYXRjaFwiOiAzMiwgXCIuL2RpZmYtcHJvcHNcIjogMzQsIFwieC1pcy1hcnJheVwiOiAxMiB9XSB9LCB7fSwgWzRdKSg0KTtcbn0pO1xuXG5jb25zdCBDb3JlID0gQztcblxuZXhwb3J0IHsgQ29yZSwgRW51bSwgVmlydHVhbERPTSB9OyJdLCJmaWxlIjoiRWxpeGlyLmpzIiwic291cmNlUm9vdCI6Ii9zb3VyY2UvIn0= \ No newline at end of file diff --git a/src/javascript/elixir.js b/src/javascript/elixir.js index 34edc259..c6ba77ac 100644 --- a/src/javascript/elixir.js +++ b/src/javascript/elixir.js @@ -1,6 +1,5 @@ import * as C from './lib/core'; export const Core = C; -export { default as Kernel } from './lib/kernel'; export { default as Enum } from './lib/enum'; export { default as VirtualDOM } from './lib/virtual-dom'; diff --git a/src/javascript/lib/core.js b/src/javascript/lib/core.js index 10708900..5aadd909 100644 --- a/src/javascript/lib/core.js +++ b/src/javascript/lib/core.js @@ -1,5 +1,5 @@ import ProcessSystem from './core/processes/process_system'; -import { Tuple, PID, Integer, Float, List } from './core/primitives'; +import { Tuple, PID, Integer, Float } from './core/primitives'; import BitString from './core/bit_string'; import Patterns from './core/patterns'; import Functions from './core/functions'; @@ -16,6 +16,5 @@ export { Integer, Float, Functions, - List, SpecialForms } diff --git a/src/javascript/lib/core/functions.js b/src/javascript/lib/core/functions.js index f2282184..600961cc 100644 --- a/src/javascript/lib/core/functions.js +++ b/src/javascript/lib/core/functions.js @@ -23,92 +23,12 @@ function call_property(item, property){ throw new Error(`Property ${property} not found in ${item}`); } -function is_instance_of(value, type){ - return value instanceof type; +function get_type(x){ + return typeof x; } -function size(term){ - return term.length; -} - -function is_nil(x){ - return x === null; -} - -function is_atom(x){ - return typeof x === 'symbol'; -} - -function is_binary(x){ - return typeof x === 'string' || x instanceof String; -} - -function is_boolean(x){ - return typeof x === 'boolean' || x instanceof Boolean; -} - -function is_function(x, arity = -1){ - return typeof x === 'function' || x instanceof Function; -} - -function is_float(x){ - return is_number(x) && !Number.isInteger(x); -} - -function is_integer(x){ - return Number.isInteger(x); -} - -function is_list(x){ - return x instanceof Array; -} - -function is_map(x){ - return typeof x === 'object' || x instanceof Object; -} - -function is_number(x){ - return typeof x === "number"; -} - -function is_tuple(x){ - return x instanceof Tuple; -} - -function is_pid(x){ - return x instanceof PID; -} - -function is_port(x){ - return false; -} - -function is_reference(x){ - return false; -} - -function is_bitstring(x){ - return is_binary(x) || x instanceof BitString; -} - -function add(one, two){ - return one + two; -} - -function subtract(one, two){ - return one + two; -} - -function multiply(one, two){ - return one + two; -} - -function divide(one, two){ - return one + two; -} - -function remainder(one, two){ - return one + two; +function is_instance_of(x, type){ + return x instanceof type; } function apply(...args){ @@ -119,58 +39,6 @@ function apply(...args){ } } -function new_tuple(...args){ - return new Tuple(...args); -} - -function make_tuple(data, size){ - let array = []; - - for (var i = size - 1; i >= 0; i--) { - array.push(data); - } - - return new Tuple(...array); -} - -function insert_at(tuple, index, term){ - let new_tuple = []; - - for (var i = 0; i <= tuple.count(); i++) { - if(i === index){ - new_tuple.push(term); - i++; - new_tuple.push(tuple.get(i)); - }else{ - new_tuple.push(tuple.get(i)); - } - } - - return new Tuple(...new_tuple); -} - -function duplicate(data, size){ - let array = []; - - for (var i = size - 1; i >= 0; i--) { - array.push(data); - } - - return array; -} - -function delete_at(tuple, index){ - let new_list = []; - - for (var i = 0; i < tuple.count(); i++) { - if(i !== index){ - new_list.push(tuple.get(i)); - } - } - - return new Tuple(...new_list); -}; - function contains(left, right){ for(let x of right){ if(Patterns.match_no_throw(left, x) != null){ @@ -181,10 +49,6 @@ function contains(left, right){ return false; } -function reverse(list){ - return list.concat([]).reverse(); -} - function get_global(){ if(typeof(self) !== "undefined"){ return self; @@ -197,14 +61,6 @@ function get_global(){ throw new Error("No global state found"); } -function concat_lists(left, right){ - return left.concat(right); -} - -function prepend_to_list(list, item){ - return [item].concat(list); -} - function defstruct(defaults){ return class { constructor(update = {}){ @@ -269,15 +125,6 @@ function b64EncodeUnicode(str) { })); } -function can_decode64(data) { - try{ - atob(data); - return true; - }catch(e){ - return false; - } -} - function delete_property_from_map(map, property){ let new_map = Object.assign(Object.create(map.constructor.prototype), map) delete new_map[property] @@ -346,38 +193,20 @@ function zip(list_of_lists){ return Object.freeze(new_value); } +function can_decode64(data) { + try{ + atob(data); + return true; + }catch(e){ + return false; + } +} + export default { call_property, - is_instance_of, - size, - is_nil, - is_atom, - is_binary, - is_boolean, - is_function, - is_float, - is_integer, - is_list, - is_map, - is_number, - is_tuple, - is_pid, - is_port, - is_reference, - is_bitstring, - add, - subtract, - multiply, - divide, - remainder, apply, - new_tuple, - duplicate, contains, - reverse, get_global, - concat_lists, - prepend_to_list, defstruct, defexception, defprotocol, @@ -388,6 +217,7 @@ export default { delete_property_from_map, add_property_to_map, class_to_obj, + can_decode64, bnot, band, bor, diff --git a/src/javascript/lib/core/primitives.js b/src/javascript/lib/core/primitives.js index 4ac7c456..2521eb63 100644 --- a/src/javascript/lib/core/primitives.js +++ b/src/javascript/lib/core/primitives.js @@ -48,8 +48,4 @@ class PID { class Integer {} class Float {} -function List(...args){ - return Object.freeze(args); -} - -export { PID, Tuple, Integer, Float, List }; +export { PID, Tuple, Integer, Float }; diff --git a/src/javascript/lib/core/special_forms.js b/src/javascript/lib/core/special_forms.js index dc6d235f..15e03a32 100644 --- a/src/javascript/lib/core/special_forms.js +++ b/src/javascript/lib/core/special_forms.js @@ -10,10 +10,6 @@ function bitstring(...args){ return new BitString(...args); } -function tuple(...args){ - return new Tuple(...args); -} - function _case(condition, clauses){ return Patterns.defmatch(...clauses)(condition); } @@ -126,7 +122,6 @@ function _try(do_fun, rescue_function, catch_fun, else_function, after_function) export default { list, bitstring, - tuple, _case, cond, map, diff --git a/src/javascript/lib/kernel.js b/src/javascript/lib/kernel.js deleted file mode 100644 index 5bb1f203..00000000 --- a/src/javascript/lib/kernel.js +++ /dev/null @@ -1,178 +0,0 @@ -import * as Core from './core'; - -function tl(list){ - return Core.SpecialForms.list(...list.slice(1)); -} - -function hd(list){ - return list[0]; -} - -function is_nil(x){ - return x === null; -} - -function is_atom(x){ - return typeof x === 'symbol'; -} - -function is_binary(x){ - return typeof x === 'string' || x instanceof String; -} - -function is_boolean(x){ - return typeof x === 'boolean' || x instanceof Boolean; -} - -function is_function(x, arity = -1){ - return typeof x === 'function' || x instanceof Function; -} - -function is_float(x){ - return is_number(x) && !Number.isInteger(x); -} - -function is_integer(x){ - return Number.isInteger(x); -} - -function is_list(x){ - return x instanceof Array; -} - -function is_map(x){ - return typeof x === 'object' || x instanceof Object; -} - -function is_number(x){ - return typeof x === "number"; -} - -function is_tuple(x){ - return x instanceof Core.Tuple; -} - -function length(x){ - return x.length; -} - -function is_pid(x){ - return x instanceof Core.PID; -} - -function is_port(x){ - return false; -} - -function is_reference(x){ - return false; -} - -function is_bitstring(x){ - return is_binary(x) || x instanceof Core.BitString; -} - -function __in__(left, right){ - for(let x of right){ - if(match__qmark__(left, x)){ - return true; - } - } - - return false; -} - -function abs(number){ - return Math.abs(number); -} - -function round(number){ - return Math.round(number); -} - -function elem(tuple, index){ - if(is_list(tuple)){ - return tuple[index]; - } - - return tuple.get(index); -} - -function rem(left, right){ - return left % right; -} - -function div(left, right){ - return left / right; -} - -function and(left, right){ - return left && right; -} - -function or(left, right){ - return left || right; -} - -function not(arg){ - return !arg; -} - -function apply(...args){ - if(args.length === 3){ - let mod = args[0]; - let func = args[1]; - let func_args = args[2]; - return mod[func].apply(null, func_args); - }else{ - let func = args[0]; - let func_args = args[1]; - - return func.apply(null, func_args); - } -} - -function to_string(arg){ - if(is_tuple(arg)){ - return arg.toString(); - } - - return arg.toString(); -} - -function match__qmark__(pattern, expr, guard = () => true){ - return Core.Patterns.match_no_throw(pattern, expr, guard) != null; -} - -export default { - tl, - hd, - is_nil, - is_atom, - is_binary, - is_boolean, - is_function, - is_float, - is_integer, - is_list, - is_map, - is_number, - is_tuple, - length, - is_pid, - is_port, - is_reference, - is_bitstring, - in: __in__, - abs, - round, - elem, - rem, - div, - and, - or, - not, - apply, - to_string, - match__qmark__ -}; diff --git a/src/javascript/lib/kernel/special_forms.js b/src/javascript/lib/kernel/special_forms.js deleted file mode 100644 index 7a5301b5..00000000 --- a/src/javascript/lib/kernel/special_forms.js +++ /dev/null @@ -1,173 +0,0 @@ -import * as Core from '../core'; -import Enum from '../enum'; - -let SpecialForms = { - - atom: function(_value) { - return Symbol.for(_value); - }, - - list: function(...args){ - return Object.freeze(args); - }, - - bitstring: function(...args){ - return new Core.BitString(...args); - }, - - bound: function(_var){ - return Core.Patterns.bound(_var); - }, - - _case: function(condition, clauses){ - return Core.Patterns.defmatch(...clauses)(condition); - }, - - cond: function(clauses){ - for(let clause of clauses){ - if(clause[0]){ - return clause[1](); - } - } - - throw new Error(); - }, - - fn: function(clauses){ - return Core.Patterns.defmatch(clauses); - }, - - map: function(obj){ - return Object.freeze(obj); - }, - - map_update: function(map, values){ - return Object.freeze( - Object.assign( - Object.create(map.constructor.prototype), map, values - ) - ); - }, - - _for: function(collections, fun, filter = () => true, into = [], previousValues = []){ - let pattern = collections[0][0]; - let collection = collections[0][1]; - - if(collections.length === 1){ - - for(let elem of collection){ - let r = Core.Patterns.match_no_throw(pattern, elem); - let args = previousValues.concat(r); - - if(r && filter.apply(this, args)){ - into = Enum.into([fun.apply(this, args)], into); - } - } - - return into; - }else{ - let _into = [] - - for(let elem of collection){ - let r = Core.Patterns.match_no_throw(pattern, elem); - if(r){ - _into = Enum.into(this._for(collections.slice(1), fun, filter, _into, previousValues.concat(r)), into); - } - } - - return _into; - } - }, - - receive: function(receive_fun, timeout_in_ms = null, timeout_fn = (time) => true){ - if (timeout_in_ms == null || timeout_in_ms === System.for('infinity')) { - while(true){ - if(self.mailbox.length !== 0){ - let message = self.mailbox[0]; - self.mailbox = self.mailbox.slice(1); - return receive_fun(message); - } - } - }else if(timeout_in_ms === 0){ - if(self.mailbox.length !== 0){ - let message = self.mailbox[0]; - self.mailbox = self.mailbox.slice(1); - return receive_fun(message); - }else{ - return null; - } - }else{ - let now = Date.now(); - while(Date.now() < (now + timeout_in_ms)){ - if(self.mailbox.length !== 0){ - let message = self.mailbox[0]; - self.mailbox = self.mailbox.slice(1); - return receive_fun(message); - } - } - - return timeout_fn(timeout_in_ms); - } - }, - - tuple: function(...args){ - return new Core.Tuple(...args); - }, - - - _try: function(do_fun, rescue_function, catch_fun, else_function, after_function){ - let result = null; - - try{ - result = do_fun(); - }catch(e){ - let ex_result = null; - - if(rescue_function){ - try{ - ex_result = rescue_function(e); - return ex_result; - }catch(ex){ - if(ex instanceof Core.Patterns.MatchError){ - throw ex; - } - } - } - - if(catch_fun){ - try{ - ex_result = catch_fun(e); - return ex_result; - }catch(ex){ - if(ex instanceof Core.Patterns.MatchError){ - throw ex; - } - } - } - - throw e; - - }finally{ - if(after_function){ - after_function(); - } - } - - if(else_function){ - try{ - return else_function(result); - }catch(ex){ - if(ex instanceof Core.Patterns.MatchError){ - throw new Error("No Match Found in Else"); - } - - throw ex; - } - }else{ - return result; - } - } - -}; - -export default SpecialForms; diff --git a/src/javascript/tests/bit_string.spec.js b/src/javascript/tests/bit_string.spec.js index 6fe37917..f64d9c67 100644 --- a/src/javascript/tests/bit_string.spec.js +++ b/src/javascript/tests/bit_string.spec.js @@ -1,55 +1,59 @@ var BitString = require('../lib/core').BitString; -var Kernel = require('../lib/kernel'); var SpecialForms = require('../lib/core').SpecialForms; +var Patterns = require('../lib/core').Patterns; var expect = require('chai').expect; +function is_match(pattern, expr, guard = () => true){ + return Patterns.match_no_throw(pattern, expr, guard) != null; +} + describe('BitString', function(){ describe('creation', function(){ it('create properly', function(){ let bs = SpecialForms.bitstring(BitString.integer(1)); - expect(Kernel.match__qmark__(bs.value, [1])).to.equal(true); + expect(is_match(bs.value, [1])).to.equal(true); bs = SpecialForms.bitstring(BitString.binary("foo")); - expect(Kernel.match__qmark__(bs.value, [102, 111, 111])).to.equal(true); + expect(is_match(bs.value, [102, 111, 111])).to.equal(true); bs = SpecialForms.bitstring(BitString.integer(0), BitString.binary("foo")); - expect(Kernel.match__qmark__(bs.value, [0, 102, 111, 111])).to.equal(true); + expect(is_match(bs.value, [0, 102, 111, 111])).to.equal(true); bs = SpecialForms.bitstring(BitString.float(3.14)); - expect(Kernel.match__qmark__(bs.value, [64, 9, 30, 184, 81, 235, 133, 31])).to.equal(true); + expect(is_match(bs.value, [64, 9, 30, 184, 81, 235, 133, 31])).to.equal(true); bs = SpecialForms.bitstring(BitString.signed(BitString.integer(-100))); - expect(Kernel.match__qmark__(bs.value, [156])).to.equal(true); + expect(is_match(bs.value, [156])).to.equal(true); }); }); describe('UTF conversions', function(){ it('toUTF8Array', function(){ let bs = BitString.toUTF8Array("fo≈"); - expect(Kernel.match__qmark__(bs, [102, 111, 226, 137, 136])).to.equal(true); + expect(is_match(bs, [102, 111, 226, 137, 136])).to.equal(true); }); it('toUTF16Array', function(){ let bs = BitString.toUTF16Array("fo≈"); - expect(Kernel.match__qmark__(bs, [0, 102, 0, 111, 34, 72])).to.equal(true); + expect(is_match(bs, [0, 102, 0, 111, 34, 72])).to.equal(true); }); it('toUTF32Array', function(){ let bs = BitString.toUTF32Array("fo≈"); - expect(Kernel.match__qmark__(bs, [0, 0, 0, 102, 0, 0, 0, 111, 0, 0, 34, 72])).to.equal(true); + expect(is_match(bs, [0, 0, 0, 102, 0, 0, 0, 111, 0, 0, 34, 72])).to.equal(true); }); }); describe('Float conversions', function(){ it('float32ToBytes', function(){ let bs = BitString.float32ToBytes(3.14); - expect(Kernel.match__qmark__(bs, [64, 72, 245, 195])).to.equal(true); + expect(is_match(bs, [64, 72, 245, 195])).to.equal(true); }); it('float64ToBytes', function(){ let bs = BitString.float64ToBytes(3.14); - expect(Kernel.match__qmark__(bs, [64, 9, 30, 184, 81, 235, 133, 31])).to.equal(true); + expect(is_match(bs, [64, 9, 30, 184, 81, 235, 133, 31])).to.equal(true); }); }); }); diff --git a/src/javascript/tests/kernel.spec.js b/src/javascript/tests/kernel.spec.js deleted file mode 100644 index ee3a2ac0..00000000 --- a/src/javascript/tests/kernel.spec.js +++ /dev/null @@ -1,53 +0,0 @@ -var Kernel = require('../lib/kernel'); -var SpecialForms = require('../lib/core').SpecialForms; -var expect = require('chai').expect; - -describe('Kernel', function(){ - - describe('match?', function(){ - it('match numbers', function(){ - expect(Kernel.match__qmark__(1, 1)).to.equal(true); - expect(Kernel.match__qmark__(1.0, 1)).to.equal(true); - expect(Kernel.match__qmark__(2, 1)).to.equal(false); - expect(Kernel.match__qmark__(2, 1 + 1)).to.equal(true); - expect(Kernel.match__qmark__(undefined, 1 + 1)).to.equal(true); - expect(Kernel.match__qmark__(undefined, 1 + 1)).to.equal(true); - }); - - it('match strings', function(){ - expect(Kernel.match__qmark__("", "")).to.equal(true); - expect(Kernel.match__qmark__('', "")).to.equal(true); - expect(Kernel.match__qmark__("Hello", "Hell")).to.equal(false); - expect(Kernel.match__qmark__("Hello", "Hell" + "o")).to.equal(true); - }); - - it('match atoms', function(){ - expect(Kernel.match__qmark__(Symbol.for("test"), Symbol.for("test"))).to.equal(true); - expect(Kernel.match__qmark__(Symbol.for("test"), Symbol.for("notest"))).to.equal(false); - }); - - it('match tuples', function(){ - expect(Kernel.match__qmark__(SpecialForms.tuple(1, 2, 3), SpecialForms.tuple(1, 2, 3))).to.equal(true); - expect(Kernel.match__qmark__(SpecialForms.tuple(1, undefined, 3), SpecialForms.tuple(1, 2, 3))).to.equal(true); - expect(Kernel.match__qmark__(SpecialForms.tuple(1, 2, 3), SpecialForms.tuple(1, 2))).to.equal(false); - }); - - it('match list', function(){ - expect(Kernel.match__qmark__([1, 2, 3], [1, 2, 3])).to.equal(true); - expect(Kernel.match__qmark__([1, undefined, 3], [1, 2, 3])).to.equal(true); - expect(Kernel.match__qmark__([1, 2, 3], [1, 2])).to.equal(false); - }); - - it('match map', function(){ - expect(Kernel.match__qmark__({a: 1, b: 2}, {a: 1, b: 2})).to.equal(true); - expect(Kernel.match__qmark__({a: 1}, {a: 1, b: 2})).to.equal(true); - expect(Kernel.match__qmark__({a: undefined}, {a: 1, b: 2})).to.equal(true); - expect(Kernel.match__qmark__({c: 1}, {a: 1, b: 2})).to.equal(false); - expect(Kernel.match__qmark__({c: undefined}, {a: 1, b: 2})).to.equal(false); - }); - - it('match numbers with guards', function(){ - expect(Kernel.match__qmark__(1, 1, () => Kernel.is_number(1))).to.equal(true); - }); - }); -}); diff --git a/src/javascript/tests/try.spec.js b/src/javascript/tests/try.spec.js index f28af45f..df6b9971 100644 --- a/src/javascript/tests/try.spec.js +++ b/src/javascript/tests/try.spec.js @@ -1,6 +1,5 @@ var Patterns = require("../lib/core/patterns"); var Enum = require('../lib/enum'); -var Kernel = require('../lib/kernel'); var SpecialForms = require('../lib/core').SpecialForms; var expect = require('chai').expect; diff --git a/test/translator/list_test.exs b/test/translator/list_test.exs index a39262ab..6543f751 100644 --- a/test/translator/list_test.exs +++ b/test/translator/list_test.exs @@ -26,20 +26,20 @@ defmodule ElixirScript.Translator.List.Test do test "concatenate lists" do ex_ast = quote do: [1, 2, 3] ++ [4, 5, 6] - js_code = "Elixir.Core.Functions.concat_lists(Elixir.Core.SpecialForms.list(1,2,3),Elixir.Core.SpecialForms.list(4,5,6))" + js_code = "Elixir.Core.SpecialForms.list(1,2,3).concat(Elixir.Core.SpecialForms.list(4,5,6))" assert_translation(ex_ast, js_code) ex_ast = quote do: this.list ++ [4, 5, 6] - js_code = "Elixir.Core.Functions.concat_lists(Elixir.Core.Functions.call_property(this,'list'),Elixir.Core.SpecialForms.list(4,5,6))" + js_code = "Elixir.Core.Functions.call_property(this,'list').concat(Elixir.Core.SpecialForms.list(4,5,6))" assert_translation(ex_ast, js_code) end test "prepend element" do - ex_ast = quote do: [x|list] + ex_ast = quote do: [x | list] - js_code = "Elixir.Core.prepend_to_list(list,x)" + js_code = "Elixir.Core.SpecialForms.list(x).concat(list)" assert_translation(ex_ast, js_code) end @@ -51,7 +51,7 @@ defmodule ElixirScript.Translator.List.Test do js_code = """ Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.wildcard()],function(){ - return Elixir.Core.prepend_to_list(list,x); + return Elixir.Core.SpecialForms.list(x).concat(list); })) """ From 66343f7404ed2ebc1fb7f5d2a599007665829c83 Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Sat, 2 Jan 2016 17:43:35 -0600 Subject: [PATCH 111/860] Directly translating list, and bitstring instead of using javascript functions in special_forms.js --- lib/elixir_script/prelude/enumerable.ex | 5 -- lib/elixir_script/translator.ex | 2 +- lib/elixir_script/translator/assignment.ex | 5 +- lib/elixir_script/translator/bitstring.ex | 17 ++++--- lib/elixir_script/translator/map.ex | 19 +++----- lib/elixir_script/translator/primitive.ex | 52 +++++--------------- priv/Elixir.js | 33 ++----------- src/javascript/lib/core/special_forms.js | 15 ------ src/javascript/lib/enum.js | 6 +-- test/elixir_script_test.exs | 2 +- test/prelude/js_test.exs | 2 +- test/prelude/kernel_test.exs | 2 +- test/translator/assignment_test.exs | 8 ++-- test/translator/bitstring_test.exs | 24 +++++----- test/translator/bug_test.exs | 6 +-- test/translator/case_test.exs | 2 +- test/translator/cond_test.exs | 16 +++---- test/translator/defmodule_test.exs | 4 +- test/translator/for_test.exs | 50 ++++++++++--------- test/translator/function_test.exs | 56 +++++++++++----------- test/translator/kernel_test.exs | 8 ++-- test/translator/list_test.exs | 16 +++---- test/translator/map_test.exs | 14 +++--- test/translator/protocol_test.exs | 2 +- test/translator/quote_test.exs | 41 +++++++++------- test/translator/string_test.exs | 6 +-- test/translator/struct_test.exs | 10 ++-- test/translator/try_test.exs | 14 +++--- 28 files changed, 183 insertions(+), 254 deletions(-) delete mode 100644 lib/elixir_script/prelude/enumerable.ex diff --git a/lib/elixir_script/prelude/enumerable.ex b/lib/elixir_script/prelude/enumerable.ex deleted file mode 100644 index ffbad71f..00000000 --- a/lib/elixir_script/prelude/enumerable.ex +++ /dev/null @@ -1,5 +0,0 @@ -defprotocol ElixirScript.Enumerable do - def reduce(collection, acc, fun) - def member?(collection, value) - def count(collection) -end diff --git a/lib/elixir_script/translator.ex b/lib/elixir_script/translator.ex index 6176fba9..f645d403 100644 --- a/lib/elixir_script/translator.ex +++ b/lib/elixir_script/translator.ex @@ -150,7 +150,7 @@ defmodule ElixirScript.Translator do end defp do_translate({:%{}, _, [{:|, _, [map, data]}]}, env) do - { Map.make_map_update(map, data, env), env } + Map.make_map_update(map, data, env) end defp do_translate({:%{}, _, properties}, env) do diff --git a/lib/elixir_script/translator/assignment.ex b/lib/elixir_script/translator/assignment.ex index 57e3b1c7..368cc1b9 100644 --- a/lib/elixir_script/translator/assignment.ex +++ b/lib/elixir_script/translator/assignment.ex @@ -48,10 +48,7 @@ defmodule ElixirScript.Translator.Assignment do ref_declarator = JS.variable_declarator( ref, - JS.call_expression( - Primitive.list_ast(), - params - ) + Primitive.do_make_list(params) ) make_variable_declaration_and_group(ref_declarator, array_pattern) diff --git a/lib/elixir_script/translator/bitstring.ex b/lib/elixir_script/translator/bitstring.ex index eb32ffdd..19ea4ded 100644 --- a/lib/elixir_script/translator/bitstring.ex +++ b/lib/elixir_script/translator/bitstring.ex @@ -6,13 +6,16 @@ defmodule ElixirScript.Translator.Bitstring do def make_bitstring(elements, env) do - js_ast = JS.call_expression( - JS.member_expression( - Primitive.special_forms(), - JS.identifier("bitstring") - ), - Enum.map(elements, &make_bitstring_element(&1, env)) - ) + js_ast = JS.new_expression( + JS.member_expression( + JS.member_expression( + JS.identifier("Elixir"), + JS.identifier("Core") + ), + JS.identifier("BitString") + ), + Enum.map(elements, &make_bitstring_element(&1, env)) + ) { js_ast, env } end diff --git a/lib/elixir_script/translator/map.ex b/lib/elixir_script/translator/map.ex index 1ec8d4e9..31f65247 100644 --- a/lib/elixir_script/translator/map.ex +++ b/lib/elixir_script/translator/map.ex @@ -7,8 +7,8 @@ defmodule ElixirScript.Translator.Map do def make_map(object_expression) do JS.call_expression( JS.member_expression( - Primitive.special_forms(), - JS.identifier("map") + JS.identifier(:Object), + JS.identifier(:freeze) ), [object_expression] ) @@ -57,22 +57,17 @@ defmodule ElixirScript.Translator.Map do def make_map_update(map, data, env) do map = Translator.translate!(map, env) + data = Translator.translate!({:%{}, [], data}, env) - map_update = JS.object_expression( - Enum.map(data, - fn({key, value}) -> - make_property(Translator.translate!(key, env), Translator.translate!(value, env)) - end - ) - ) - - JS.call_expression( + js_ast = JS.call_expression( JS.member_expression( Primitive.special_forms(), JS.identifier("map_update") ), - [map, map_update] + [map, data] ) + + { js_ast, env } end end diff --git a/lib/elixir_script/translator/primitive.ex b/lib/elixir_script/translator/primitive.ex index 3c8ac68b..1910173c 100644 --- a/lib/elixir_script/translator/primitive.ex +++ b/lib/elixir_script/translator/primitive.ex @@ -15,19 +15,6 @@ defmodule ElixirScript.Translator.Primitive do ) end - def new_tuple_function() do - JS.member_expression( - JS.member_expression( - JS.identifier("Elixir"), - JS.member_expression( - JS.identifier("Core"), - JS.identifier("SpecialForms") - ) - ), - JS.identifier("tuple") - ) - end - def tuple_class() do JS.member_expression( JS.member_expression( @@ -68,38 +55,29 @@ defmodule ElixirScript.Translator.Primitive do JS.literal(ast) end - def make_atom(ast) when is_atom(ast) do - JS.call_expression( - JS.member_expression( - JS.identifier("Symbol"), - JS.identifier("for") - ), - [JS.literal(ast)] - ) - end - def make_list(ast, env) when is_list(ast) do - list = Enum.map(ast, &Translator.translate!(&1, env)) - - js_ast = JS.call_expression( - list_ast(), - list - ) + js_ast = Enum.map(ast, &Translator.translate!(&1, env)) + |> do_make_list { js_ast, env } end def make_list_quoted(opts, ast, env) when is_list(ast) do - JS.call_expression( - list_ast(), - Enum.map(ast, fn(x) -> Quote.make_quote(opts, x, env) end) - ) + Enum.map(ast, fn(x) -> Quote.make_quote(opts, x, env) end) + |> do_make_list end def make_list_no_translate(ast) when is_list(ast) do + do_make_list(ast) + end + + def do_make_list(ast) do JS.call_expression( - list_ast(), - ast + JS.member_expression( + JS.identifier(:Object), + JS.identifier(:freeze) + ), + [JS.array_expression(ast)] ) end @@ -115,10 +93,6 @@ defmodule ElixirScript.Translator.Primitive do { js_ast, env } end - def make_tuple_no_translate(elements) do - JS.call_expression(new_tuple_function, elements) - end - def make_tuple_quoted(opts, elements, env) do JS.new_expression( tuple_class, diff --git a/priv/Elixir.js b/priv/Elixir.js index 0a5c99b9..b9000b49 100644 --- a/priv/Elixir.js +++ b/priv/Elixir.js @@ -100,10 +100,6 @@ class PID { class Integer {} class Float {} -function List(...args) { - return Object.freeze(args); -} - class ProcessSystem { constructor() { @@ -1228,18 +1224,6 @@ var Functions = { zip }; -function list(...args) { - return Object.freeze(args); -} - -function bitstring(...args) { - return new BitString(...args); -} - -function tuple(...args) { - return new Tuple(...args); -} - function _case(condition, clauses) { return Patterns.defmatch(...clauses)(condition); } @@ -1254,10 +1238,6 @@ function cond(clauses) { throw new Error(); } -function map(obj) { - return Object.freeze(obj); -} - function map_update(map, values) { return Object.freeze(Object.assign(Object.create(map.constructor.prototype), map, values)); } @@ -1345,12 +1325,8 @@ function _try(do_fun, rescue_function, catch_fun, else_function, after_function) } var special_forms = { - list, - bitstring, - tuple, _case, cond, - map, map_update, _for, _try @@ -1369,7 +1345,6 @@ var C = Object.freeze({ Integer: Integer, Float: Float, Functions: Functions, - List: List, SpecialForms: special_forms }); @@ -1508,14 +1483,14 @@ let Enum = { }, map_reduce: function (collection, acc, fun) { - let mapped = List(); + let mapped = Object.freeze([]); let the_acc = acc; for (var i = 0; i < this.count(collection); i++) { let tuple = fun(collection[i], the_acc); the_acc = tuple.get(1); - mapped = List(...mapped.concat([tuple.get(0)])); + mapped = Object.freeze(mapped.concat([tuple.get(0)])); } return new Tuple(mapped, the_acc); @@ -1551,7 +1526,7 @@ let Enum = { } } - return List(...result); + return Object.freeze(result); }, take_while: function (collection, fun) { @@ -3183,4 +3158,4 @@ let VirtualDOM = (function (e) { const Core = C; export { Core, Enum, VirtualDOM }; -//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiIiwic291cmNlcyI6WyJFbGl4aXIuanMiXSwic291cmNlc0NvbnRlbnQiOlsiLyogQGZsb3cgKi9cblxuY2xhc3MgTWFpbGJveCB7XG5cbiAgY29uc3RydWN0b3IoKSB7XG4gICAgdGhpcy5tZXNzYWdlcyA9IFtdO1xuICB9XG5cbiAgZGVsaXZlcihtZXNzYWdlKSB7XG4gICAgdGhpcy5tZXNzYWdlcy5wdXNoKG1lc3NhZ2UpO1xuICAgIHJldHVybiBtZXNzYWdlO1xuICB9XG5cbiAgZ2V0KCkge1xuICAgIHJldHVybiB0aGlzLm1lc3NhZ2VzO1xuICB9XG5cbiAgaXNFbXB0eSgpIHtcbiAgICByZXR1cm4gdGhpcy5tZXNzYWdlcy5sZW5ndGggPT09IDA7XG4gIH1cblxuICByZW1vdmVBdChpbmRleCkge1xuICAgIHRoaXMubWVzc2FnZXMuc3BsaWNlKGluZGV4LCAxKTtcbiAgfVxufVxuXG52YXIgU3RhdGVzID0ge1xuICBOT1JNQUw6IFN5bWJvbC5mb3IoXCJub3JtYWxcIiksXG4gIEtJTEw6IFN5bWJvbC5mb3IoXCJraWxsXCIpLFxuICBTVVNQRU5EOiBTeW1ib2wuZm9yKFwic3VzcGVuZFwiKSxcbiAgQ09OVElOVUU6IFN5bWJvbC5mb3IoXCJjb250aW51ZVwiKSxcbiAgUkVDRUlWRTogU3ltYm9sLmZvcihcInJlY2VpdmVcIiksXG4gIFNFTkQ6IFN5bWJvbC5mb3IoXCJzZW5kXCIpLFxuICBTTEVFUElORzogU3ltYm9sLmZvcihcInNsZWVwaW5nXCIpLFxuICBSVU5OSU5HOiBTeW1ib2wuZm9yKFwicnVubmluZ1wiKSxcbiAgU1VTUEVOREVEOiBTeW1ib2wuZm9yKFwic3VzcGVuZGVkXCIpLFxuICBTVE9QUEVEOiBTeW1ib2wuZm9yKFwic3RvcHBlZFwiKSxcbiAgU0xFRVA6IFN5bWJvbC5mb3IoXCJzbGVlcFwiKSxcbiAgRVhJVDogU3ltYm9sLmZvcihcImV4aXRcIiksXG4gIE5PTUFUQ0g6IFN5bWJvbC5mb3IoXCJub19tYXRjaFwiKVxufTtcblxuY2xhc3MgUHJvY2VzcyB7XG5cbiAgY29uc3RydWN0b3IocGlkLCBtYWlsYm94KSB7XG4gICAgdGhpcy5waWQgPSBwaWQ7XG4gICAgdGhpcy5tYWlsYm94ID0gbWFpbGJveDtcbiAgICB0aGlzLnN0YXR1cyA9IFN0YXRlcy5TVE9QUEVEO1xuICAgIHRoaXMuZGljdCA9IHt9O1xuICB9XG59XG5cbmNsYXNzIFR1cGxlIHtcblxuICBjb25zdHJ1Y3RvciguLi5hcmdzKSB7XG4gICAgdGhpcy52YWx1ZXMgPSBPYmplY3QuZnJlZXplKGFyZ3MpO1xuICAgIHRoaXMubGVuZ3RoID0gdGhpcy52YWx1ZXMubGVuZ3RoO1xuICB9XG5cbiAgZ2V0KGluZGV4KSB7XG4gICAgcmV0dXJuIHRoaXMudmFsdWVzW2luZGV4XTtcbiAgfVxuXG4gIGNvdW50KCkge1xuICAgIHJldHVybiB0aGlzLnZhbHVlcy5sZW5ndGg7XG4gIH1cblxuICBbU3ltYm9sLml0ZXJhdG9yXSgpIHtcbiAgICByZXR1cm4gdGhpcy52YWx1ZXNbU3ltYm9sLml0ZXJhdG9yXSgpO1xuICB9XG5cbiAgdG9TdHJpbmcoKSB7XG4gICAgdmFyIGksXG4gICAgICAgIHMgPSBcIlwiO1xuICAgIGZvciAoaSA9IDA7IGkgPCB0aGlzLnZhbHVlcy5sZW5ndGg7IGkrKykge1xuICAgICAgaWYgKHMgIT09IFwiXCIpIHtcbiAgICAgICAgcyArPSBcIiwgXCI7XG4gICAgICB9XG4gICAgICBzICs9IHRoaXMudmFsdWVzW2ldLnRvU3RyaW5nKCk7XG4gICAgfVxuXG4gICAgcmV0dXJuIFwie1wiICsgcyArIFwifVwiO1xuICB9XG5cbn1cblxubGV0IHByb2Nlc3NfY291bnRlciA9IC0xO1xuXG5jbGFzcyBQSUQge1xuICBjb25zdHJ1Y3RvcigpIHtcbiAgICBwcm9jZXNzX2NvdW50ZXIgPSBwcm9jZXNzX2NvdW50ZXIgKyAxO1xuICAgIHRoaXMuaWQgPSBwcm9jZXNzX2NvdW50ZXI7XG4gIH1cblxuICB0b1N0cmluZygpIHtcbiAgICByZXR1cm4gXCJQSUQjPDAuXCIgKyB0aGlzLmlkICsgXCIuMD5cIjtcbiAgfVxufVxuXG5jbGFzcyBJbnRlZ2VyIHt9XG5jbGFzcyBGbG9hdCB7fVxuXG5mdW5jdGlvbiBMaXN0KC4uLmFyZ3MpIHtcbiAgcmV0dXJuIE9iamVjdC5mcmVlemUoYXJncyk7XG59XG5cbmNsYXNzIFByb2Nlc3NTeXN0ZW0ge1xuXG4gIGNvbnN0cnVjdG9yKCkge1xuICAgIHRoaXMucGlkcyA9IG5ldyBNYXAoKTtcbiAgICB0aGlzLm1haWxib3hlcyA9IG5ldyBNYXAoKTtcbiAgICB0aGlzLm5hbWVzID0gbmV3IE1hcCgpO1xuICAgIHRoaXMubGlua3MgPSBuZXcgTWFwKCk7XG5cbiAgICB0aGlzLmN1cnJlbnRfcHJvY2VzcyA9IG51bGw7XG4gICAgdGhpcy5zdXNwZW5kZWQgPSBuZXcgTWFwKCk7XG5cbiAgICB0aGlzLm1haW5fcHJvY2Vzc19waWQgPSB0aGlzLnNwYXduKCk7XG4gICAgdGhpcy5zZXRfY3VycmVudCh0aGlzLm1haW5fcHJvY2Vzc19waWQpO1xuICB9XG5cbiAgc3Bhd24oKSB7XG4gICAgcmV0dXJuIHRoaXMuYWRkX3Byb2MoZmFsc2UpLnBpZDtcbiAgfVxuXG4gIHNwYXduX2xpbmsoKSB7XG4gICAgcmV0dXJuIHRoaXMuYWRkX3Byb2ModHJ1ZSkucGlkO1xuICB9XG5cbiAgbGluayhwaWQpIHtcbiAgICB0aGlzLmxpbmtzLmdldCh0aGlzLnBpZCgpKS5hZGQocGlkKTtcbiAgICB0aGlzLmxpbmtzLmdldChwaWQpLmFkZCh0aGlzLnBpZCgpKTtcbiAgfVxuXG4gIHVubGluayhwaWQpIHtcbiAgICB0aGlzLmxpbmtzLmdldCh0aGlzLnBpZCgpKS5kZWxldGUocGlkKTtcbiAgICB0aGlzLmxpbmtzLmdldChwaWQpLmRlbGV0ZSh0aGlzLnBpZCgpKTtcbiAgfVxuXG4gIHNldF9jdXJyZW50KGlkKSB7XG4gICAgbGV0IHBpZCA9IHRoaXMucGlkb2YoaWQpO1xuICAgIGlmIChwaWQgIT09IG51bGwpIHtcbiAgICAgIHRoaXMuY3VycmVudF9wcm9jZXNzID0gdGhpcy5waWRzLmdldChwaWQpO1xuICAgICAgdGhpcy5jdXJyZW50X3Byb2Nlc3Muc3RhdHVzID0gU3RhdGVzLlJVTk5JTkc7XG4gICAgfVxuICB9XG5cbiAgYWRkX3Byb2MobGlua2VkKSB7XG4gICAgbGV0IG5ld3BpZCA9IG5ldyBQSUQoKTtcbiAgICBsZXQgbWFpbGJveCA9IG5ldyBNYWlsYm94KCk7XG4gICAgbGV0IG5ld3Byb2MgPSBuZXcgUHJvY2VzcyhuZXdwaWQsIG1haWxib3gpO1xuXG4gICAgdGhpcy5waWRzLnNldChuZXdwaWQsIG5ld3Byb2MpO1xuICAgIHRoaXMubWFpbGJveGVzLnNldChuZXdwaWQsIG1haWxib3gpO1xuICAgIHRoaXMubGlua3Muc2V0KG5ld3BpZCwgbmV3IFNldCgpKTtcblxuICAgIGlmIChsaW5rZWQpIHtcbiAgICAgIHRoaXMubGluayhuZXdwaWQpO1xuICAgIH1cblxuICAgIHJldHVybiBuZXdwcm9jO1xuICB9XG5cbiAgcmVtb3ZlX3Byb2MocGlkKSB7XG4gICAgdGhpcy5waWRzLmRlbGV0ZShwaWQpO1xuICAgIHRoaXMudW5yZWdpc3RlcihwaWQpO1xuXG4gICAgaWYgKHRoaXMubGlua3MuaGFzKHBpZCkpIHtcbiAgICAgIGZvciAobGV0IGxpbmtwaWQgb2YgdGhpcy5saW5rcy5nZXQocGlkKSkge1xuICAgICAgICB0aGlzLmxpbmtzLmdldChsaW5rcGlkKS5kZWxldGUocGlkKTtcbiAgICAgIH1cblxuICAgICAgdGhpcy5saW5rcy5kZWxldGUocGlkKTtcbiAgICB9XG4gIH1cblxuICBleGl0KGlkKSB7XG4gICAgbGV0IHBpZCA9IHRoaXMucGlkb2YoaWQpO1xuICAgIHRoaXMucmVtb3ZlX3Byb2MoaWQpO1xuICB9XG5cbiAgcmVnaXN0ZXIobmFtZSwgcGlkKSB7XG4gICAgaWYgKCF0aGlzLm5hbWVzLmhhcyhuYW1lKSkge1xuICAgICAgdGhpcy5uYW1lcy5zZXQobmFtZSwgcGlkKTtcbiAgICAgIHJldHVybiBuYW1lO1xuICAgIH0gZWxzZSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoXCJOYW1lIGlzIGFscmVhZHkgcmVnaXN0ZXJlZCB0byBhbm90aGVyIHByb2Nlc3NcIik7XG4gICAgfVxuICB9XG5cbiAgcmVnaXN0ZXJlZChuYW1lKSB7XG4gICAgcmV0dXJuIHRoaXMubmFtZXMuaGFzKG5hbWUpID8gdGhpcy5uYW1lcy5nZXQobmFtZSkgOiBudWxsO1xuICB9XG5cbiAgdW5yZWdpc3RlcihwaWQpIHtcbiAgICBmb3IgKGxldCBuYW1lIG9mIHRoaXMubmFtZXMua2V5cygpKSB7XG4gICAgICBpZiAodGhpcy5uYW1lcy5oYXMobmFtZSkgJiYgdGhpcy5uYW1lcy5nZXQobmFtZSkgPT09IHBpZCkge1xuICAgICAgICB0aGlzLm5hbWVzLmRlbGV0ZShuYW1lKTtcbiAgICAgIH1cbiAgICB9XG4gIH1cblxuICBwaWQoKSB7XG4gICAgcmV0dXJuIHRoaXMuY3VycmVudF9wcm9jZXNzLnBpZDtcbiAgfVxuXG4gIHBpZG9mKGlkKSB7XG4gICAgaWYgKGlkIGluc3RhbmNlb2YgUElEKSB7XG4gICAgICByZXR1cm4gdGhpcy5waWRzLmhhcyhpZCkgPyBpZCA6IG51bGw7XG4gICAgfSBlbHNlIGlmIChpZCBpbnN0YW5jZW9mIFByb2Nlc3MpIHtcbiAgICAgIHJldHVybiBpZC5waWQ7XG4gICAgfSBlbHNlIHtcbiAgICAgIGxldCBwaWQgPSB0aGlzLnJlZ2lzdGVyZWQoaWQpO1xuICAgICAgaWYgKHBpZCA9PT0gbnVsbCkgdGhyb3cgXCJQcm9jZXNzIG5hbWUgbm90IHJlZ2lzdGVyZWQ6IFwiICsgaWQgKyBcIiAoXCIgKyB0eXBlb2YgaWQgKyBcIilcIjtcbiAgICAgIHJldHVybiBwaWQ7XG4gICAgfVxuICB9XG5cbiAgcHV0KGlkLCBrZXksIHZhbHVlKSB7XG4gICAgbGV0IHBpZCA9IHRoaXMucGlkb2YoaWQpO1xuICAgIGxldCBwcm9jZXNzID0gdGhpcy5waWRzLmdldChwaWQpO1xuICAgIHByb2Nlc3MuZGljdFtrZXldID0gdmFsdWU7XG4gIH1cblxuICBnZXQoaWQsIGtleSkge1xuICAgIGxldCBwaWQgPSB0aGlzLnBpZG9mKGlkKTtcbiAgICBsZXQgcHJvY2VzcyA9IHRoaXMucGlkcy5nZXQocGlkKTtcblxuICAgIGlmIChrZXkgIT0gbnVsbCkge1xuICAgICAgcmV0dXJuIHByb2Nlc3MuZGljdFtrZXldO1xuICAgIH0gZWxzZSB7XG4gICAgICByZXR1cm4gcHJvY2Vzcy5kaWN0O1xuICAgIH1cbiAgfVxuXG4gIGdldF9rZXlzKGlkKSB7XG4gICAgbGV0IHBpZCA9IHRoaXMucGlkb2YoaWQpO1xuICAgIGxldCBwcm9jZXNzID0gdGhpcy5waWRzLmdldChwaWQpO1xuXG4gICAgcmV0dXJuIE9iamVjdC5rZXlzKHByb2Nlc3MuZGljdCk7XG4gIH1cblxuICBlcmFzZShpZCwga2V5KSB7XG4gICAgbGV0IHBpZCA9IHRoaXMucGlkb2YoaWQpO1xuICAgIGxldCBwcm9jZXNzID0gdGhpcy5waWRzLmdldChwaWQpO1xuXG4gICAgaWYgKGtleSAhPSBudWxsKSB7XG4gICAgICBkZWxldGUgcHJvY2Vzcy5kaWN0W2tleV07XG4gICAgfSBlbHNlIHtcbiAgICAgIHByb2Nlc3MuZGljdCA9IHt9O1xuICAgIH1cbiAgfVxufVxuXG5jbGFzcyBCaXRTdHJpbmcge1xuICBjb25zdHJ1Y3RvciguLi5hcmdzKSB7XG4gICAgdGhpcy5yYXdfdmFsdWUgPSBmdW5jdGlvbiAoKSB7XG4gICAgICByZXR1cm4gT2JqZWN0LmZyZWV6ZShhcmdzKTtcbiAgICB9O1xuXG4gICAgdGhpcy52YWx1ZSA9IE9iamVjdC5mcmVlemUodGhpcy5wcm9jZXNzKGFyZ3MpKTtcbiAgfVxuXG4gIGdldChpbmRleCkge1xuICAgIHJldHVybiB0aGlzLnZhbHVlW2luZGV4XTtcbiAgfVxuXG4gIGNvdW50KCkge1xuICAgIHJldHVybiB0aGlzLnZhbHVlLmxlbmd0aDtcbiAgfVxuXG4gIFtTeW1ib2wuaXRlcmF0b3JdKCkge1xuICAgIHJldHVybiB0aGlzLnZhbHVlW1N5bWJvbC5pdGVyYXRvcl0oKTtcbiAgfVxuXG4gIHRvU3RyaW5nKCkge1xuICAgIHZhciBpLFxuICAgICAgICBzID0gXCJcIjtcbiAgICBmb3IgKGkgPSAwOyBpIDwgdGhpcy5jb3VudCgpOyBpKyspIHtcbiAgICAgIGlmIChzICE9PSBcIlwiKSB7XG4gICAgICAgIHMgKz0gXCIsIFwiO1xuICAgICAgfVxuICAgICAgcyArPSB0aGlzW2ldLnRvU3RyaW5nKCk7XG4gICAgfVxuXG4gICAgcmV0dXJuIFwiPDxcIiArIHMgKyBcIj4+XCI7XG4gIH1cblxuICBwcm9jZXNzKCkge1xuICAgIGxldCBwcm9jZXNzZWRfdmFsdWVzID0gW107XG5cbiAgICB2YXIgaTtcbiAgICBmb3IgKGkgPSAwOyBpIDwgdGhpcy5yYXdfdmFsdWUoKS5sZW5ndGg7IGkrKykge1xuICAgICAgbGV0IHByb2Nlc3NlZF92YWx1ZSA9IHRoaXNbXCJwcm9jZXNzX1wiICsgdGhpcy5yYXdfdmFsdWUoKVtpXS50eXBlXSh0aGlzLnJhd192YWx1ZSgpW2ldKTtcblxuICAgICAgZm9yIChsZXQgYXR0ciBvZiB0aGlzLnJhd192YWx1ZSgpW2ldLmF0dHJpYnV0ZXMpIHtcbiAgICAgICAgcHJvY2Vzc2VkX3ZhbHVlID0gdGhpc1tcInByb2Nlc3NfXCIgKyBhdHRyXShwcm9jZXNzZWRfdmFsdWUpO1xuICAgICAgfVxuXG4gICAgICBwcm9jZXNzZWRfdmFsdWVzID0gcHJvY2Vzc2VkX3ZhbHVlcy5jb25jYXQocHJvY2Vzc2VkX3ZhbHVlKTtcbiAgICB9XG5cbiAgICByZXR1cm4gcHJvY2Vzc2VkX3ZhbHVlcztcbiAgfVxuXG4gIHByb2Nlc3NfaW50ZWdlcih2YWx1ZSkge1xuICAgIHJldHVybiB2YWx1ZS52YWx1ZTtcbiAgfVxuXG4gIHByb2Nlc3NfZmxvYXQodmFsdWUpIHtcbiAgICBpZiAodmFsdWUuc2l6ZSA9PT0gNjQpIHtcbiAgICAgIHJldHVybiBCaXRTdHJpbmcuZmxvYXQ2NFRvQnl0ZXModmFsdWUudmFsdWUpO1xuICAgIH0gZWxzZSBpZiAodmFsdWUuc2l6ZSA9PT0gMzIpIHtcbiAgICAgIHJldHVybiBCaXRTdHJpbmcuZmxvYXQzMlRvQnl0ZXModmFsdWUudmFsdWUpO1xuICAgIH1cblxuICAgIHRocm93IG5ldyBFcnJvcihcIkludmFsaWQgc2l6ZSBmb3IgZmxvYXRcIik7XG4gIH1cblxuICBwcm9jZXNzX2JpdHN0cmluZyh2YWx1ZSkge1xuICAgIHJldHVybiB2YWx1ZS52YWx1ZS52YWx1ZTtcbiAgfVxuXG4gIHByb2Nlc3NfYmluYXJ5KHZhbHVlKSB7XG4gICAgcmV0dXJuIEJpdFN0cmluZy50b1VURjhBcnJheSh2YWx1ZS52YWx1ZSk7XG4gIH1cblxuICBwcm9jZXNzX3V0ZjgodmFsdWUpIHtcbiAgICByZXR1cm4gQml0U3RyaW5nLnRvVVRGOEFycmF5KHZhbHVlLnZhbHVlKTtcbiAgfVxuXG4gIHByb2Nlc3NfdXRmMTYodmFsdWUpIHtcbiAgICByZXR1cm4gQml0U3RyaW5nLnRvVVRGMTZBcnJheSh2YWx1ZS52YWx1ZSk7XG4gIH1cblxuICBwcm9jZXNzX3V0ZjMyKHZhbHVlKSB7XG4gICAgcmV0dXJuIEJpdFN0cmluZy50b1VURjMyQXJyYXkodmFsdWUudmFsdWUpO1xuICB9XG5cbiAgcHJvY2Vzc19zaWduZWQodmFsdWUpIHtcbiAgICByZXR1cm4gbmV3IFVpbnQ4QXJyYXkoW3ZhbHVlXSlbMF07XG4gIH1cblxuICBwcm9jZXNzX3Vuc2lnbmVkKHZhbHVlKSB7XG4gICAgcmV0dXJuIHZhbHVlO1xuICB9XG5cbiAgcHJvY2Vzc19uYXRpdmUodmFsdWUpIHtcbiAgICByZXR1cm4gdmFsdWU7XG4gIH1cblxuICBwcm9jZXNzX2JpZyh2YWx1ZSkge1xuICAgIHJldHVybiB2YWx1ZTtcbiAgfVxuXG4gIHByb2Nlc3NfbGl0dGxlKHZhbHVlKSB7XG4gICAgcmV0dXJuIHZhbHVlLnJldmVyc2UoKTtcbiAgfVxuXG4gIHByb2Nlc3Nfc2l6ZSh2YWx1ZSkge1xuICAgIHJldHVybiB2YWx1ZTtcbiAgfVxuXG4gIHByb2Nlc3NfdW5pdCh2YWx1ZSkge1xuICAgIHJldHVybiB2YWx1ZTtcbiAgfVxuXG4gIHN0YXRpYyBpbnRlZ2VyKHZhbHVlKSB7XG4gICAgcmV0dXJuIEJpdFN0cmluZy53cmFwKHZhbHVlLCB7IFwidHlwZVwiOiBcImludGVnZXJcIiwgXCJ1bml0XCI6IDEsIFwic2l6ZVwiOiA4IH0pO1xuICB9XG5cbiAgc3RhdGljIGZsb2F0KHZhbHVlKSB7XG4gICAgcmV0dXJuIEJpdFN0cmluZy53cmFwKHZhbHVlLCB7IFwidHlwZVwiOiBcImZsb2F0XCIsIFwidW5pdFwiOiAxLCBcInNpemVcIjogNjQgfSk7XG4gIH1cblxuICBzdGF0aWMgYml0c3RyaW5nKHZhbHVlKSB7XG4gICAgcmV0dXJuIEJpdFN0cmluZy53cmFwKHZhbHVlLCB7IFwidHlwZVwiOiBcImJpdHN0cmluZ1wiLCBcInVuaXRcIjogMSwgXCJzaXplXCI6IHZhbHVlLmxlbmd0aCB9KTtcbiAgfVxuXG4gIHN0YXRpYyBiaXRzKHZhbHVlKSB7XG4gICAgcmV0dXJuIEJpdFN0cmluZy5iaXRzdHJpbmcodmFsdWUpO1xuICB9XG5cbiAgc3RhdGljIGJpbmFyeSh2YWx1ZSkge1xuICAgIHJldHVybiBCaXRTdHJpbmcud3JhcCh2YWx1ZSwgeyBcInR5cGVcIjogXCJiaW5hcnlcIiwgXCJ1bml0XCI6IDgsIFwic2l6ZVwiOiB2YWx1ZS5sZW5ndGggfSk7XG4gIH1cblxuICBzdGF0aWMgYnl0ZXModmFsdWUpIHtcbiAgICByZXR1cm4gQml0U3RyaW5nLmJpbmFyeSh2YWx1ZSk7XG4gIH1cblxuICBzdGF0aWMgdXRmOCh2YWx1ZSkge1xuICAgIHJldHVybiBCaXRTdHJpbmcud3JhcCh2YWx1ZSwgeyBcInR5cGVcIjogXCJ1dGY4XCIgfSk7XG4gIH1cblxuICBzdGF0aWMgdXRmMTYodmFsdWUpIHtcbiAgICByZXR1cm4gQml0U3RyaW5nLndyYXAodmFsdWUsIHsgXCJ0eXBlXCI6IFwidXRmMTZcIiB9KTtcbiAgfVxuXG4gIHN0YXRpYyB1dGYzMih2YWx1ZSkge1xuICAgIHJldHVybiBCaXRTdHJpbmcud3JhcCh2YWx1ZSwgeyBcInR5cGVcIjogXCJ1dGYzMlwiIH0pO1xuICB9XG5cbiAgc3RhdGljIHNpZ25lZCh2YWx1ZSkge1xuICAgIHJldHVybiBCaXRTdHJpbmcud3JhcCh2YWx1ZSwge30sIFwic2lnbmVkXCIpO1xuICB9XG5cbiAgc3RhdGljIHVuc2lnbmVkKHZhbHVlKSB7XG4gICAgcmV0dXJuIEJpdFN0cmluZy53cmFwKHZhbHVlLCB7fSwgXCJ1bnNpZ25lZFwiKTtcbiAgfVxuXG4gIHN0YXRpYyBuYXRpdmUodmFsdWUpIHtcbiAgICByZXR1cm4gQml0U3RyaW5nLndyYXAodmFsdWUsIHt9LCBcIm5hdGl2ZVwiKTtcbiAgfVxuXG4gIHN0YXRpYyBiaWcodmFsdWUpIHtcbiAgICByZXR1cm4gQml0U3RyaW5nLndyYXAodmFsdWUsIHt9LCBcImJpZ1wiKTtcbiAgfVxuXG4gIHN0YXRpYyBsaXR0bGUodmFsdWUpIHtcbiAgICByZXR1cm4gQml0U3RyaW5nLndyYXAodmFsdWUsIHt9LCBcImxpdHRsZVwiKTtcbiAgfVxuXG4gIHN0YXRpYyBzaXplKHZhbHVlLCBjb3VudCkge1xuICAgIHJldHVybiBCaXRTdHJpbmcud3JhcCh2YWx1ZSwgeyBcInNpemVcIjogY291bnQgfSk7XG4gIH1cblxuICBzdGF0aWMgdW5pdCh2YWx1ZSwgY291bnQpIHtcbiAgICByZXR1cm4gQml0U3RyaW5nLndyYXAodmFsdWUsIHsgXCJ1bml0XCI6IGNvdW50IH0pO1xuICB9XG5cbiAgc3RhdGljIHdyYXAodmFsdWUsIG9wdCwgbmV3X2F0dHJpYnV0ZSA9IG51bGwpIHtcbiAgICBsZXQgdGhlX3ZhbHVlID0gdmFsdWU7XG5cbiAgICBpZiAoISh2YWx1ZSBpbnN0YW5jZW9mIE9iamVjdCkpIHtcbiAgICAgIHRoZV92YWx1ZSA9IHsgXCJ2YWx1ZVwiOiB2YWx1ZSwgXCJhdHRyaWJ1dGVzXCI6IFtdIH07XG4gICAgfVxuXG4gICAgdGhlX3ZhbHVlID0gT2JqZWN0LmFzc2lnbih0aGVfdmFsdWUsIG9wdCk7XG5cbiAgICBpZiAobmV3X2F0dHJpYnV0ZSkge1xuICAgICAgdGhlX3ZhbHVlLmF0dHJpYnV0ZXMucHVzaChuZXdfYXR0cmlidXRlKTtcbiAgICB9XG5cbiAgICByZXR1cm4gdGhlX3ZhbHVlO1xuICB9XG5cbiAgc3RhdGljIHRvVVRGOEFycmF5KHN0cikge1xuICAgIHZhciB1dGY4ID0gW107XG4gICAgZm9yICh2YXIgaSA9IDA7IGkgPCBzdHIubGVuZ3RoOyBpKyspIHtcbiAgICAgIHZhciBjaGFyY29kZSA9IHN0ci5jaGFyQ29kZUF0KGkpO1xuICAgICAgaWYgKGNoYXJjb2RlIDwgMTI4KSB7XG4gICAgICAgIHV0ZjgucHVzaChjaGFyY29kZSk7XG4gICAgICB9IGVsc2UgaWYgKGNoYXJjb2RlIDwgMjA0OCkge1xuICAgICAgICB1dGY4LnB1c2goMTkyIHwgY2hhcmNvZGUgPj4gNiwgMTI4IHwgY2hhcmNvZGUgJiA2Myk7XG4gICAgICB9IGVsc2UgaWYgKGNoYXJjb2RlIDwgNTUyOTYgfHwgY2hhcmNvZGUgPj0gNTczNDQpIHtcbiAgICAgICAgdXRmOC5wdXNoKDIyNCB8IGNoYXJjb2RlID4+IDEyLCAxMjggfCBjaGFyY29kZSA+PiA2ICYgNjMsIDEyOCB8IGNoYXJjb2RlICYgNjMpO1xuICAgICAgfVxuICAgICAgLy8gc3Vycm9nYXRlIHBhaXJcbiAgICAgIGVsc2Uge1xuICAgICAgICBpKys7XG4gICAgICAgIC8vIFVURi0xNiBlbmNvZGVzIDB4MTAwMDAtMHgxMEZGRkYgYnlcbiAgICAgICAgLy8gc3VidHJhY3RpbmcgMHgxMDAwMCBhbmQgc3BsaXR0aW5nIHRoZVxuICAgICAgICAvLyAyMCBiaXRzIG9mIDB4MC0weEZGRkZGIGludG8gdHdvIGhhbHZlc1xuICAgICAgICBjaGFyY29kZSA9IDY1NTM2ICsgKChjaGFyY29kZSAmIDEwMjMpIDw8IDEwIHwgc3RyLmNoYXJDb2RlQXQoaSkgJiAxMDIzKTtcbiAgICAgICAgdXRmOC5wdXNoKDI0MCB8IGNoYXJjb2RlID4+IDE4LCAxMjggfCBjaGFyY29kZSA+PiAxMiAmIDYzLCAxMjggfCBjaGFyY29kZSA+PiA2ICYgNjMsIDEyOCB8IGNoYXJjb2RlICYgNjMpO1xuICAgICAgfVxuICAgIH1cbiAgICByZXR1cm4gdXRmODtcbiAgfVxuXG4gIHN0YXRpYyB0b1VURjE2QXJyYXkoc3RyKSB7XG4gICAgdmFyIHV0ZjE2ID0gW107XG4gICAgZm9yICh2YXIgaSA9IDA7IGkgPCBzdHIubGVuZ3RoOyBpKyspIHtcbiAgICAgIHZhciBjb2RlUG9pbnQgPSBzdHIuY29kZVBvaW50QXQoaSk7XG5cbiAgICAgIGlmIChjb2RlUG9pbnQgPD0gMjU1KSB7XG4gICAgICAgIHV0ZjE2LnB1c2goMCk7XG4gICAgICAgIHV0ZjE2LnB1c2goY29kZVBvaW50KTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHV0ZjE2LnB1c2goY29kZVBvaW50ID4+IDggJiAyNTUpO1xuICAgICAgICB1dGYxNi5wdXNoKGNvZGVQb2ludCAmIDI1NSk7XG4gICAgICB9XG4gICAgfVxuICAgIHJldHVybiB1dGYxNjtcbiAgfVxuXG4gIHN0YXRpYyB0b1VURjMyQXJyYXkoc3RyKSB7XG4gICAgdmFyIHV0ZjMyID0gW107XG4gICAgZm9yICh2YXIgaSA9IDA7IGkgPCBzdHIubGVuZ3RoOyBpKyspIHtcbiAgICAgIHZhciBjb2RlUG9pbnQgPSBzdHIuY29kZVBvaW50QXQoaSk7XG5cbiAgICAgIGlmIChjb2RlUG9pbnQgPD0gMjU1KSB7XG4gICAgICAgIHV0ZjMyLnB1c2goMCk7XG4gICAgICAgIHV0ZjMyLnB1c2goMCk7XG4gICAgICAgIHV0ZjMyLnB1c2goMCk7XG4gICAgICAgIHV0ZjMyLnB1c2goY29kZVBvaW50KTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHV0ZjMyLnB1c2goMCk7XG4gICAgICAgIHV0ZjMyLnB1c2goMCk7XG4gICAgICAgIHV0ZjMyLnB1c2goY29kZVBvaW50ID4+IDggJiAyNTUpO1xuICAgICAgICB1dGYzMi5wdXNoKGNvZGVQb2ludCAmIDI1NSk7XG4gICAgICB9XG4gICAgfVxuICAgIHJldHVybiB1dGYzMjtcbiAgfVxuXG4gIC8vaHR0cDovL3N0YWNrb3ZlcmZsb3cuY29tL3F1ZXN0aW9ucy8yMDAzNDkzL2phdmFzY3JpcHQtZmxvYXQtZnJvbS10by1iaXRzXG4gIHN0YXRpYyBmbG9hdDMyVG9CeXRlcyhmKSB7XG4gICAgdmFyIGJ5dGVzID0gW107XG5cbiAgICB2YXIgYnVmID0gbmV3IEFycmF5QnVmZmVyKDQpO1xuICAgIG5ldyBGbG9hdDMyQXJyYXkoYnVmKVswXSA9IGY7XG5cbiAgICBsZXQgaW50VmVyc2lvbiA9IG5ldyBVaW50MzJBcnJheShidWYpWzBdO1xuXG4gICAgYnl0ZXMucHVzaChpbnRWZXJzaW9uID4+IDI0ICYgMjU1KTtcbiAgICBieXRlcy5wdXNoKGludFZlcnNpb24gPj4gMTYgJiAyNTUpO1xuICAgIGJ5dGVzLnB1c2goaW50VmVyc2lvbiA+PiA4ICYgMjU1KTtcbiAgICBieXRlcy5wdXNoKGludFZlcnNpb24gJiAyNTUpO1xuXG4gICAgcmV0dXJuIGJ5dGVzO1xuICB9XG5cbiAgc3RhdGljIGZsb2F0NjRUb0J5dGVzKGYpIHtcbiAgICB2YXIgYnl0ZXMgPSBbXTtcblxuICAgIHZhciBidWYgPSBuZXcgQXJyYXlCdWZmZXIoOCk7XG4gICAgbmV3IEZsb2F0NjRBcnJheShidWYpWzBdID0gZjtcblxuICAgIHZhciBpbnRWZXJzaW9uMSA9IG5ldyBVaW50MzJBcnJheShidWYpWzBdO1xuICAgIHZhciBpbnRWZXJzaW9uMiA9IG5ldyBVaW50MzJBcnJheShidWYpWzFdO1xuXG4gICAgYnl0ZXMucHVzaChpbnRWZXJzaW9uMiA+PiAyNCAmIDI1NSk7XG4gICAgYnl0ZXMucHVzaChpbnRWZXJzaW9uMiA+PiAxNiAmIDI1NSk7XG4gICAgYnl0ZXMucHVzaChpbnRWZXJzaW9uMiA+PiA4ICYgMjU1KTtcbiAgICBieXRlcy5wdXNoKGludFZlcnNpb24yICYgMjU1KTtcblxuICAgIGJ5dGVzLnB1c2goaW50VmVyc2lvbjEgPj4gMjQgJiAyNTUpO1xuICAgIGJ5dGVzLnB1c2goaW50VmVyc2lvbjEgPj4gMTYgJiAyNTUpO1xuICAgIGJ5dGVzLnB1c2goaW50VmVyc2lvbjEgPj4gOCAmIDI1NSk7XG4gICAgYnl0ZXMucHVzaChpbnRWZXJzaW9uMSAmIDI1NSk7XG5cbiAgICByZXR1cm4gYnl0ZXM7XG4gIH1cbn1cblxuLyogQGZsb3cgKi9cblxuY2xhc3MgVmFyaWFibGUge1xuXG4gIGNvbnN0cnVjdG9yKG5hbWUgPSBudWxsKSB7XG4gICAgdGhpcy5uYW1lID0gbmFtZTtcbiAgfVxufVxuXG5jbGFzcyBXaWxkY2FyZCB7XG4gIGNvbnN0cnVjdG9yKCkge31cbn1cblxuY2xhc3MgU3RhcnRzV2l0aCB7XG5cbiAgY29uc3RydWN0b3IocHJlZml4KSB7XG4gICAgdGhpcy5wcmVmaXggPSBwcmVmaXg7XG4gIH1cbn1cblxuY2xhc3MgQ2FwdHVyZSB7XG5cbiAgY29uc3RydWN0b3IodmFsdWUpIHtcbiAgICB0aGlzLnZhbHVlID0gdmFsdWU7XG4gIH1cbn1cblxuY2xhc3MgSGVhZFRhaWwge1xuICBjb25zdHJ1Y3RvcigpIHt9XG59XG5cbmNsYXNzIFR5cGUge1xuXG4gIGNvbnN0cnVjdG9yKHR5cGUsIG9ialBhdHRlcm4gPSB7fSkge1xuICAgIHRoaXMudHlwZSA9IHR5cGU7XG4gICAgdGhpcy5vYmpQYXR0ZXJuID0gb2JqUGF0dGVybjtcbiAgfVxufVxuXG5jbGFzcyBCb3VuZCB7XG5cbiAgY29uc3RydWN0b3IodmFsdWUpIHtcbiAgICB0aGlzLnZhbHVlID0gdmFsdWU7XG4gIH1cbn1cblxuZnVuY3Rpb24gdmFyaWFibGUobmFtZSA9IG51bGwpIHtcbiAgcmV0dXJuIG5ldyBWYXJpYWJsZShuYW1lKTtcbn1cblxuZnVuY3Rpb24gd2lsZGNhcmQoKSB7XG4gIHJldHVybiBuZXcgV2lsZGNhcmQoKTtcbn1cblxuZnVuY3Rpb24gc3RhcnRzV2l0aChwcmVmaXgpIHtcbiAgcmV0dXJuIG5ldyBTdGFydHNXaXRoKHByZWZpeCk7XG59XG5cbmZ1bmN0aW9uIGNhcHR1cmUodmFsdWUpIHtcbiAgcmV0dXJuIG5ldyBDYXB0dXJlKHZhbHVlKTtcbn1cblxuZnVuY3Rpb24gaGVhZFRhaWwoKSB7XG4gIHJldHVybiBuZXcgSGVhZFRhaWwoKTtcbn1cblxuZnVuY3Rpb24gdHlwZSh0eXBlLCBvYmpQYXR0ZXJuID0ge30pIHtcbiAgcmV0dXJuIG5ldyBUeXBlKHR5cGUsIG9ialBhdHRlcm4pO1xufVxuXG5mdW5jdGlvbiBib3VuZCh2YWx1ZSkge1xuICByZXR1cm4gbmV3IEJvdW5kKHZhbHVlKTtcbn1cblxuZnVuY3Rpb24gaXNfbnVtYmVyKHZhbHVlKSB7XG4gIHJldHVybiB0eXBlb2YgdmFsdWUgPT09ICdudW1iZXInO1xufVxuXG5mdW5jdGlvbiBpc19zdHJpbmcodmFsdWUpIHtcbiAgcmV0dXJuIHR5cGVvZiB2YWx1ZSA9PT0gJ3N0cmluZyc7XG59XG5cbmZ1bmN0aW9uIGlzX2Jvb2xlYW4odmFsdWUpIHtcbiAgcmV0dXJuIHR5cGVvZiB2YWx1ZSA9PT0gJ2Jvb2xlYW4nO1xufVxuXG5mdW5jdGlvbiBpc19zeW1ib2wodmFsdWUpIHtcbiAgcmV0dXJuIHR5cGVvZiB2YWx1ZSA9PT0gJ3N5bWJvbCc7XG59XG5cbmZ1bmN0aW9uIGlzX251bGwodmFsdWUpIHtcbiAgcmV0dXJuIHZhbHVlID09PSBudWxsO1xufVxuXG5mdW5jdGlvbiBpc191bmRlZmluZWQodmFsdWUpIHtcbiAgcmV0dXJuIHR5cGVvZiB2YWx1ZSA9PT0gJ3VuZGVmaW5lZCc7XG59XG5cbmZ1bmN0aW9uIGlzX2Z1bmN0aW9uKHZhbHVlKSB7XG4gIHJldHVybiBPYmplY3QucHJvdG90eXBlLnRvU3RyaW5nLmNhbGwodmFsdWUpID09ICdbb2JqZWN0IEZ1bmN0aW9uXSc7XG59XG5cbmZ1bmN0aW9uIGlzX3ZhcmlhYmxlKHZhbHVlKSB7XG4gIHJldHVybiB2YWx1ZSBpbnN0YW5jZW9mIFZhcmlhYmxlO1xufVxuXG5mdW5jdGlvbiBpc193aWxkY2FyZCh2YWx1ZSkge1xuICByZXR1cm4gdmFsdWUgaW5zdGFuY2VvZiBXaWxkY2FyZDtcbn1cblxuZnVuY3Rpb24gaXNfaGVhZFRhaWwodmFsdWUpIHtcbiAgcmV0dXJuIHZhbHVlIGluc3RhbmNlb2YgSGVhZFRhaWw7XG59XG5cbmZ1bmN0aW9uIGlzX2NhcHR1cmUodmFsdWUpIHtcbiAgcmV0dXJuIHZhbHVlIGluc3RhbmNlb2YgQ2FwdHVyZTtcbn1cblxuZnVuY3Rpb24gaXNfdHlwZSh2YWx1ZSkge1xuICByZXR1cm4gdmFsdWUgaW5zdGFuY2VvZiBUeXBlO1xufVxuXG5mdW5jdGlvbiBpc19zdGFydHNXaXRoKHZhbHVlKSB7XG4gIHJldHVybiB2YWx1ZSBpbnN0YW5jZW9mIFN0YXJ0c1dpdGg7XG59XG5cbmZ1bmN0aW9uIGlzX2JvdW5kKHZhbHVlKSB7XG4gIHJldHVybiB2YWx1ZSBpbnN0YW5jZW9mIEJvdW5kO1xufVxuXG5mdW5jdGlvbiBpc19vYmplY3QodmFsdWUpIHtcbiAgcmV0dXJuIHR5cGVvZiB2YWx1ZSA9PT0gJ29iamVjdCc7XG59XG5cbmZ1bmN0aW9uIGlzX2FycmF5KHZhbHVlKSB7XG4gIHJldHVybiBBcnJheS5pc0FycmF5KHZhbHVlKTtcbn1cblxudmFyIENoZWNrcyA9IHtcbiAgaXNfbnVtYmVyLFxuICBpc19zdHJpbmcsXG4gIGlzX2Jvb2xlYW4sXG4gIGlzX3N5bWJvbCxcbiAgaXNfbnVsbCxcbiAgaXNfdW5kZWZpbmVkLFxuICBpc19mdW5jdGlvbixcbiAgaXNfdmFyaWFibGUsXG4gIGlzX3dpbGRjYXJkLFxuICBpc19oZWFkVGFpbCxcbiAgaXNfY2FwdHVyZSxcbiAgaXNfdHlwZSxcbiAgaXNfc3RhcnRzV2l0aCxcbiAgaXNfYm91bmQsXG4gIGlzX29iamVjdCxcbiAgaXNfYXJyYXlcbn07XG5cbmZ1bmN0aW9uIHJlc29sdmVTeW1ib2wocGF0dGVybikge1xuICByZXR1cm4gZnVuY3Rpb24gKHZhbHVlKSB7XG4gICAgcmV0dXJuIENoZWNrcy5pc19zeW1ib2wodmFsdWUpICYmIHZhbHVlID09PSBwYXR0ZXJuO1xuICB9O1xufVxuXG5mdW5jdGlvbiByZXNvbHZlU3RyaW5nKHBhdHRlcm4pIHtcbiAgcmV0dXJuIGZ1bmN0aW9uICh2YWx1ZSkge1xuICAgIHJldHVybiBDaGVja3MuaXNfc3RyaW5nKHZhbHVlKSAmJiB2YWx1ZSA9PT0gcGF0dGVybjtcbiAgfTtcbn1cblxuZnVuY3Rpb24gcmVzb2x2ZU51bWJlcihwYXR0ZXJuKSB7XG4gIHJldHVybiBmdW5jdGlvbiAodmFsdWUpIHtcbiAgICByZXR1cm4gQ2hlY2tzLmlzX251bWJlcih2YWx1ZSkgJiYgdmFsdWUgPT09IHBhdHRlcm47XG4gIH07XG59XG5cbmZ1bmN0aW9uIHJlc29sdmVCb29sZWFuKHBhdHRlcm4pIHtcbiAgcmV0dXJuIGZ1bmN0aW9uICh2YWx1ZSkge1xuICAgIHJldHVybiBDaGVja3MuaXNfYm9vbGVhbih2YWx1ZSkgJiYgdmFsdWUgPT09IHBhdHRlcm47XG4gIH07XG59XG5cbmZ1bmN0aW9uIHJlc29sdmVGdW5jdGlvbihwYXR0ZXJuKSB7XG4gIHJldHVybiBmdW5jdGlvbiAodmFsdWUpIHtcbiAgICByZXR1cm4gQ2hlY2tzLmlzX2Z1bmN0aW9uKHZhbHVlKSAmJiB2YWx1ZSA9PT0gcGF0dGVybjtcbiAgfTtcbn1cblxuZnVuY3Rpb24gcmVzb2x2ZU51bGwocGF0dGVybikge1xuICByZXR1cm4gZnVuY3Rpb24gKHZhbHVlKSB7XG4gICAgcmV0dXJuIENoZWNrcy5pc19udWxsKHZhbHVlKTtcbiAgfTtcbn1cblxuZnVuY3Rpb24gcmVzb2x2ZUJvdW5kKHBhdHRlcm4pIHtcbiAgcmV0dXJuIGZ1bmN0aW9uICh2YWx1ZSwgYXJncykge1xuICAgIGlmICh0eXBlb2YgdmFsdWUgPT09IHR5cGVvZiBwYXR0ZXJuLnZhbHVlICYmIHZhbHVlID09PSBwYXR0ZXJuLnZhbHVlKSB7XG4gICAgICBhcmdzLnB1c2godmFsdWUpO1xuICAgICAgcmV0dXJuIHRydWU7XG4gICAgfVxuXG4gICAgcmV0dXJuIGZhbHNlO1xuICB9O1xufVxuXG5mdW5jdGlvbiByZXNvbHZlV2lsZGNhcmQoKSB7XG4gIHJldHVybiBmdW5jdGlvbiAoKSB7XG4gICAgcmV0dXJuIHRydWU7XG4gIH07XG59XG5cbmZ1bmN0aW9uIHJlc29sdmVWYXJpYWJsZSgpIHtcbiAgcmV0dXJuIGZ1bmN0aW9uICh2YWx1ZSwgYXJncykge1xuICAgIGFyZ3MucHVzaCh2YWx1ZSk7XG4gICAgcmV0dXJuIHRydWU7XG4gIH07XG59XG5cbmZ1bmN0aW9uIHJlc29sdmVIZWFkVGFpbCgpIHtcbiAgcmV0dXJuIGZ1bmN0aW9uICh2YWx1ZSwgYXJncykge1xuICAgIGlmICghQ2hlY2tzLmlzX2FycmF5KHZhbHVlKSB8fCB2YWx1ZS5sZW5ndGggPCAyKSB7XG4gICAgICByZXR1cm4gZmFsc2U7XG4gICAgfVxuXG4gICAgY29uc3QgaGVhZCA9IHZhbHVlWzBdO1xuICAgIGNvbnN0IHRhaWwgPSB2YWx1ZS5zbGljZSgxKTtcblxuICAgIGFyZ3MucHVzaChoZWFkKTtcbiAgICBhcmdzLnB1c2godGFpbCk7XG5cbiAgICByZXR1cm4gdHJ1ZTtcbiAgfTtcbn1cblxuZnVuY3Rpb24gcmVzb2x2ZUNhcHR1cmUocGF0dGVybikge1xuICBjb25zdCBtYXRjaGVzID0gYnVpbGRNYXRjaChwYXR0ZXJuLnZhbHVlKTtcblxuICByZXR1cm4gZnVuY3Rpb24gKHZhbHVlLCBhcmdzKSB7XG4gICAgaWYgKG1hdGNoZXModmFsdWUsIGFyZ3MpKSB7XG4gICAgICBhcmdzLnB1c2godmFsdWUpO1xuICAgICAgcmV0dXJuIHRydWU7XG4gICAgfVxuXG4gICAgcmV0dXJuIGZhbHNlO1xuICB9O1xufVxuXG5mdW5jdGlvbiByZXNvbHZlU3RhcnRzV2l0aChwYXR0ZXJuKSB7XG4gIGNvbnN0IHByZWZpeCA9IHBhdHRlcm4ucHJlZml4O1xuXG4gIHJldHVybiBmdW5jdGlvbiAodmFsdWUsIGFyZ3MpIHtcbiAgICBpZiAoQ2hlY2tzLmlzX3N0cmluZyh2YWx1ZSkgJiYgdmFsdWUuc3RhcnRzV2l0aChwcmVmaXgpKSB7XG4gICAgICBhcmdzLnB1c2godmFsdWUuc3Vic3RyaW5nKHByZWZpeC5sZW5ndGgpKTtcbiAgICAgIHJldHVybiB0cnVlO1xuICAgIH1cblxuICAgIHJldHVybiBmYWxzZTtcbiAgfTtcbn1cblxuZnVuY3Rpb24gcmVzb2x2ZVR5cGUocGF0dGVybikge1xuICByZXR1cm4gZnVuY3Rpb24gKHZhbHVlLCBhcmdzKSB7XG4gICAgaWYgKHZhbHVlIGluc3RhbmNlb2YgcGF0dGVybi50eXBlKSB7XG4gICAgICBjb25zdCBtYXRjaGVzID0gYnVpbGRNYXRjaChwYXR0ZXJuLm9ialBhdHRlcm4pO1xuICAgICAgcmV0dXJuIG1hdGNoZXModmFsdWUsIGFyZ3MpICYmIGFyZ3MucHVzaCh2YWx1ZSkgPiAwO1xuICAgIH1cblxuICAgIHJldHVybiBmYWxzZTtcbiAgfTtcbn1cblxuZnVuY3Rpb24gcmVzb2x2ZUFycmF5KHBhdHRlcm4pIHtcbiAgY29uc3QgbWF0Y2hlcyA9IHBhdHRlcm4ubWFwKHggPT4gYnVpbGRNYXRjaCh4KSk7XG5cbiAgcmV0dXJuIGZ1bmN0aW9uICh2YWx1ZSwgYXJncykge1xuICAgIGlmICghQ2hlY2tzLmlzX2FycmF5KHZhbHVlKSB8fCB2YWx1ZS5sZW5ndGggIT0gcGF0dGVybi5sZW5ndGgpIHtcbiAgICAgIHJldHVybiBmYWxzZTtcbiAgICB9XG5cbiAgICByZXR1cm4gdmFsdWUuZXZlcnkoZnVuY3Rpb24gKHYsIGkpIHtcbiAgICAgIHJldHVybiBtYXRjaGVzW2ldKHZhbHVlW2ldLCBhcmdzKTtcbiAgICB9KTtcbiAgfTtcbn1cblxuZnVuY3Rpb24gcmVzb2x2ZU9iamVjdChwYXR0ZXJuKSB7XG4gIGxldCBtYXRjaGVzID0ge307XG5cbiAgZm9yIChsZXQga2V5IG9mIE9iamVjdC5rZXlzKHBhdHRlcm4pLmNvbmNhdChPYmplY3QuZ2V0T3duUHJvcGVydHlTeW1ib2xzKHBhdHRlcm4pKSkge1xuICAgIG1hdGNoZXNba2V5XSA9IGJ1aWxkTWF0Y2gocGF0dGVybltrZXldKTtcbiAgfVxuXG4gIHJldHVybiBmdW5jdGlvbiAodmFsdWUsIGFyZ3MpIHtcbiAgICBpZiAoIUNoZWNrcy5pc19vYmplY3QodmFsdWUpIHx8IHBhdHRlcm4ubGVuZ3RoID4gdmFsdWUubGVuZ3RoKSB7XG4gICAgICByZXR1cm4gZmFsc2U7XG4gICAgfVxuXG4gICAgZm9yIChsZXQga2V5IG9mIE9iamVjdC5rZXlzKHBhdHRlcm4pLmNvbmNhdChPYmplY3QuZ2V0T3duUHJvcGVydHlTeW1ib2xzKHBhdHRlcm4pKSkge1xuICAgICAgaWYgKCEoa2V5IGluIHZhbHVlKSB8fCAhbWF0Y2hlc1trZXldKHZhbHVlW2tleV0sIGFyZ3MpKSB7XG4gICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICByZXR1cm4gdHJ1ZTtcbiAgfTtcbn1cblxuZnVuY3Rpb24gcmVzb2x2ZU5vTWF0Y2goKSB7XG4gIHJldHVybiBmdW5jdGlvbiAoKSB7XG4gICAgcmV0dXJuIGZhbHNlO1xuICB9O1xufVxuXG52YXIgUmVzb2x2ZXJzID0ge1xuICByZXNvbHZlQm91bmQsXG4gIHJlc29sdmVXaWxkY2FyZCxcbiAgcmVzb2x2ZVZhcmlhYmxlLFxuICByZXNvbHZlSGVhZFRhaWwsXG4gIHJlc29sdmVDYXB0dXJlLFxuICByZXNvbHZlU3RhcnRzV2l0aCxcbiAgcmVzb2x2ZVR5cGUsXG4gIHJlc29sdmVBcnJheSxcbiAgcmVzb2x2ZU9iamVjdCxcbiAgcmVzb2x2ZU5vTWF0Y2gsXG4gIHJlc29sdmVTeW1ib2wsXG4gIHJlc29sdmVTdHJpbmcsXG4gIHJlc29sdmVOdW1iZXIsXG4gIHJlc29sdmVCb29sZWFuLFxuICByZXNvbHZlRnVuY3Rpb24sXG4gIHJlc29sdmVOdWxsXG59O1xuXG5mdW5jdGlvbiBidWlsZE1hdGNoKHBhdHRlcm4pIHtcblxuICBpZiAoQ2hlY2tzLmlzX3ZhcmlhYmxlKHBhdHRlcm4pKSB7XG4gICAgcmV0dXJuIFJlc29sdmVycy5yZXNvbHZlVmFyaWFibGUocGF0dGVybik7XG4gIH1cblxuICBpZiAoQ2hlY2tzLmlzX3dpbGRjYXJkKHBhdHRlcm4pKSB7XG4gICAgcmV0dXJuIFJlc29sdmVycy5yZXNvbHZlV2lsZGNhcmQocGF0dGVybik7XG4gIH1cblxuICBpZiAoQ2hlY2tzLmlzX3VuZGVmaW5lZChwYXR0ZXJuKSkge1xuICAgIHJldHVybiBSZXNvbHZlcnMucmVzb2x2ZVdpbGRjYXJkKHBhdHRlcm4pO1xuICB9XG5cbiAgaWYgKENoZWNrcy5pc19oZWFkVGFpbChwYXR0ZXJuKSkge1xuICAgIHJldHVybiBSZXNvbHZlcnMucmVzb2x2ZUhlYWRUYWlsKHBhdHRlcm4pO1xuICB9XG5cbiAgaWYgKENoZWNrcy5pc19zdGFydHNXaXRoKHBhdHRlcm4pKSB7XG4gICAgcmV0dXJuIFJlc29sdmVycy5yZXNvbHZlU3RhcnRzV2l0aChwYXR0ZXJuKTtcbiAgfVxuXG4gIGlmIChDaGVja3MuaXNfY2FwdHVyZShwYXR0ZXJuKSkge1xuICAgIHJldHVybiBSZXNvbHZlcnMucmVzb2x2ZUNhcHR1cmUocGF0dGVybik7XG4gIH1cblxuICBpZiAoQ2hlY2tzLmlzX2JvdW5kKHBhdHRlcm4pKSB7XG4gICAgcmV0dXJuIFJlc29sdmVycy5yZXNvbHZlQm91bmQocGF0dGVybik7XG4gIH1cblxuICBpZiAoQ2hlY2tzLmlzX3R5cGUocGF0dGVybikpIHtcbiAgICByZXR1cm4gUmVzb2x2ZXJzLnJlc29sdmVUeXBlKHBhdHRlcm4pO1xuICB9XG5cbiAgaWYgKENoZWNrcy5pc19hcnJheShwYXR0ZXJuKSkge1xuICAgIHJldHVybiBSZXNvbHZlcnMucmVzb2x2ZUFycmF5KHBhdHRlcm4pO1xuICB9XG5cbiAgaWYgKENoZWNrcy5pc19udW1iZXIocGF0dGVybikpIHtcbiAgICByZXR1cm4gUmVzb2x2ZXJzLnJlc29sdmVOdW1iZXIocGF0dGVybik7XG4gIH1cblxuICBpZiAoQ2hlY2tzLmlzX3N0cmluZyhwYXR0ZXJuKSkge1xuICAgIHJldHVybiBSZXNvbHZlcnMucmVzb2x2ZVN0cmluZyhwYXR0ZXJuKTtcbiAgfVxuXG4gIGlmIChDaGVja3MuaXNfYm9vbGVhbihwYXR0ZXJuKSkge1xuICAgIHJldHVybiBSZXNvbHZlcnMucmVzb2x2ZUJvb2xlYW4ocGF0dGVybik7XG4gIH1cblxuICBpZiAoQ2hlY2tzLmlzX3N5bWJvbChwYXR0ZXJuKSkge1xuICAgIHJldHVybiBSZXNvbHZlcnMucmVzb2x2ZVN5bWJvbChwYXR0ZXJuKTtcbiAgfVxuXG4gIGlmIChDaGVja3MuaXNfbnVsbChwYXR0ZXJuKSkge1xuICAgIHJldHVybiBSZXNvbHZlcnMucmVzb2x2ZU51bGwocGF0dGVybik7XG4gIH1cblxuICBpZiAoQ2hlY2tzLmlzX29iamVjdChwYXR0ZXJuKSkge1xuICAgIHJldHVybiBSZXNvbHZlcnMucmVzb2x2ZU9iamVjdChwYXR0ZXJuKTtcbiAgfVxuXG4gIHJldHVybiBSZXNvbHZlcnMucmVzb2x2ZU5vTWF0Y2goKTtcbn1cblxuY2xhc3MgTWF0Y2hFcnJvciBleHRlbmRzIEVycm9yIHtcbiAgY29uc3RydWN0b3IoYXJnKSB7XG4gICAgc3VwZXIoKTtcblxuICAgIGlmICh0eXBlb2YgYXJnID09PSAnc3ltYm9sJykge1xuICAgICAgdGhpcy5tZXNzYWdlID0gJ05vIG1hdGNoIGZvcjogJyArIGFyZy50b1N0cmluZygpO1xuICAgIH0gZWxzZSBpZiAoQXJyYXkuaXNBcnJheShhcmcpKSB7XG4gICAgICBsZXQgbWFwcGVkVmFsdWVzID0gYXJnLm1hcCh4ID0+IHgudG9TdHJpbmcoKSk7XG4gICAgICB0aGlzLm1lc3NhZ2UgPSAnTm8gbWF0Y2ggZm9yOiAnICsgbWFwcGVkVmFsdWVzO1xuICAgIH0gZWxzZSB7XG4gICAgICB0aGlzLm1lc3NhZ2UgPSAnTm8gbWF0Y2ggZm9yOiAnICsgYXJnO1xuICAgIH1cblxuICAgIHRoaXMuc3RhY2sgPSBuZXcgRXJyb3IoKS5zdGFjaztcbiAgICB0aGlzLm5hbWUgPSB0aGlzLmNvbnN0cnVjdG9yLm5hbWU7XG4gIH1cbn1cblxuY2xhc3MgQ2FzZSB7XG5cbiAgY29uc3RydWN0b3IocGF0dGVybiwgZm4sIGd1YXJkID0gKCkgPT4gdHJ1ZSkge1xuICAgIHRoaXMucGF0dGVybiA9IGJ1aWxkTWF0Y2gocGF0dGVybik7XG4gICAgdGhpcy5mbiA9IGZuO1xuICAgIHRoaXMuZ3VhcmQgPSBndWFyZDtcbiAgfVxufVxuXG5mdW5jdGlvbiBtYWtlX2Nhc2UocGF0dGVybiwgZm4sIGd1YXJkID0gKCkgPT4gdHJ1ZSkge1xuICByZXR1cm4gbmV3IENhc2UocGF0dGVybiwgZm4sIGd1YXJkKTtcbn1cblxuZnVuY3Rpb24gZGVmbWF0Y2goLi4uY2FzZXMpIHtcbiAgcmV0dXJuIGZ1bmN0aW9uICguLi5hcmdzKSB7XG4gICAgZm9yIChsZXQgcHJvY2Vzc2VkQ2FzZSBvZiBjYXNlcykge1xuICAgICAgbGV0IHJlc3VsdCA9IFtdO1xuICAgICAgaWYgKHByb2Nlc3NlZENhc2UucGF0dGVybihhcmdzLCByZXN1bHQpICYmIHByb2Nlc3NlZENhc2UuZ3VhcmQuYXBwbHkodGhpcywgcmVzdWx0KSkge1xuICAgICAgICByZXR1cm4gcHJvY2Vzc2VkQ2FzZS5mbi5hcHBseSh0aGlzLCByZXN1bHQpO1xuICAgICAgfVxuICAgIH1cblxuICAgIHRocm93IG5ldyBNYXRjaEVycm9yKGFyZ3MpO1xuICB9O1xufVxuXG5mdW5jdGlvbiBtYXRjaChwYXR0ZXJuLCBleHByLCBndWFyZCA9ICgpID0+IHRydWUpIHtcbiAgbGV0IHJlc3VsdCA9IFtdO1xuICBsZXQgcHJvY2Vzc2VkUGF0dGVybiA9IGJ1aWxkTWF0Y2gocGF0dGVybik7XG4gIGlmIChwcm9jZXNzZWRQYXR0ZXJuKGV4cHIsIHJlc3VsdCkgJiYgZ3VhcmQuYXBwbHkodGhpcywgcmVzdWx0KSkge1xuICAgIHJldHVybiByZXN1bHQ7XG4gIH0gZWxzZSB7XG4gICAgdGhyb3cgbmV3IE1hdGNoRXJyb3IoZXhwcik7XG4gIH1cbn1cblxuZnVuY3Rpb24gbWF0Y2hfbm9fdGhyb3cocGF0dGVybiwgZXhwciwgZ3VhcmQgPSAoKSA9PiB0cnVlKSB7XG4gIHRyeSB7XG4gICAgcmV0dXJuIG1hdGNoKHBhdHRlcm4sIGV4cHIsIGd1YXJkKTtcbiAgfSBjYXRjaCAoZSkge1xuICAgIGlmIChlIGluc3RhbmNlb2YgTWF0Y2hFcnJvcikge1xuICAgICAgcmV0dXJuIG51bGw7XG4gICAgfVxuXG4gICAgdGhyb3cgZTtcbiAgfVxufVxuXG52YXIgUGF0dGVybnMgPSB7XG4gIGRlZm1hdGNoLCBtYXRjaCwgTWF0Y2hFcnJvciwgbWF0Y2hfbm9fdGhyb3csXG4gIHZhcmlhYmxlLCB3aWxkY2FyZCwgc3RhcnRzV2l0aCxcbiAgY2FwdHVyZSwgaGVhZFRhaWwsIHR5cGUsIGJvdW5kLCBDYXNlLCBtYWtlX2Nhc2Vcbn07XG5cbmZ1bmN0aW9uIGNhbGxfcHJvcGVydHkoaXRlbSwgcHJvcGVydHkpIHtcbiAgaWYgKHByb3BlcnR5IGluIGl0ZW0pIHtcbiAgICBpdGVtW3Byb3BlcnR5XTtcbiAgICBpZiAoaXRlbVtwcm9wZXJ0eV0gaW5zdGFuY2VvZiBGdW5jdGlvbikge1xuICAgICAgcmV0dXJuIGl0ZW1bcHJvcGVydHldKCk7XG4gICAgfSBlbHNlIHtcbiAgICAgIHJldHVybiBpdGVtW3Byb3BlcnR5XTtcbiAgICB9XG4gIH0gZWxzZSBpZiAoU3ltYm9sLmZvcihwcm9wZXJ0eSkgaW4gaXRlbSkge1xuICAgIGxldCBwcm9wID0gU3ltYm9sLmZvcihwcm9wZXJ0eSk7XG4gICAgaWYgKGl0ZW1bcHJvcF0gaW5zdGFuY2VvZiBGdW5jdGlvbikge1xuICAgICAgcmV0dXJuIGl0ZW1bcHJvcF0oKTtcbiAgICB9IGVsc2Uge1xuICAgICAgcmV0dXJuIGl0ZW1bcHJvcF07XG4gICAgfVxuICB9XG5cbiAgdGhyb3cgbmV3IEVycm9yKGBQcm9wZXJ0eSAkeyBwcm9wZXJ0eSB9IG5vdCBmb3VuZCBpbiAkeyBpdGVtIH1gKTtcbn1cblxuZnVuY3Rpb24gYXBwbHkoLi4uYXJncykge1xuICBpZiAoYXJncy5sZW5ndGggPT09IDIpIHtcbiAgICBhcmdzWzBdLmFwcGx5KG51bGwsIGFyZ3Muc2xpY2UoMSkpO1xuICB9IGVsc2Uge1xuICAgIGFyZ3NbMF1bYXJnc1sxXV0uYXBwbHkobnVsbCwgYXJncy5zbGljZSgyKSk7XG4gIH1cbn1cblxuZnVuY3Rpb24gY29udGFpbnMobGVmdCwgcmlnaHQpIHtcbiAgZm9yIChsZXQgeCBvZiByaWdodCkge1xuICAgIGlmIChQYXR0ZXJucy5tYXRjaF9ub190aHJvdyhsZWZ0LCB4KSAhPSBudWxsKSB7XG4gICAgICByZXR1cm4gdHJ1ZTtcbiAgICB9XG4gIH1cblxuICByZXR1cm4gZmFsc2U7XG59XG5cbmZ1bmN0aW9uIGdldF9nbG9iYWwoKSB7XG4gIGlmICh0eXBlb2Ygc2VsZiAhPT0gJ3VuZGVmaW5lZCcpIHtcbiAgICByZXR1cm4gc2VsZjtcbiAgfSBlbHNlIGlmICh0eXBlb2Ygd2luZG93ICE9PSAndW5kZWZpbmVkJykge1xuICAgIHJldHVybiB3aW5kb3c7XG4gIH0gZWxzZSBpZiAodHlwZW9mIGdsb2JhbCAhPT0gJ3VuZGVmaW5lZCcpIHtcbiAgICByZXR1cm4gZ2xvYmFsO1xuICB9XG5cbiAgdGhyb3cgbmV3IEVycm9yKCdObyBnbG9iYWwgc3RhdGUgZm91bmQnKTtcbn1cblxuZnVuY3Rpb24gZGVmc3RydWN0KGRlZmF1bHRzKSB7XG4gIHJldHVybiBjbGFzcyB7XG4gICAgY29uc3RydWN0b3IodXBkYXRlID0ge30pIHtcbiAgICAgIGxldCB0aGVfdmFsdWVzID0gT2JqZWN0LmFzc2lnbihkZWZhdWx0cywgdXBkYXRlKTtcbiAgICAgIE9iamVjdC5hc3NpZ24odGhpcywgdGhlX3ZhbHVlcyk7XG4gICAgfVxuXG4gICAgc3RhdGljIGNyZWF0ZSh1cGRhdGVzID0ge30pIHtcbiAgICAgIGxldCB4ID0gbmV3IHRoaXModXBkYXRlcyk7XG4gICAgICByZXR1cm4gT2JqZWN0LmZyZWV6ZSh4KTtcbiAgICB9XG4gIH07XG59XG5cbmZ1bmN0aW9uIGRlZmV4Y2VwdGlvbihkZWZhdWx0cykge1xuICByZXR1cm4gY2xhc3MgZXh0ZW5kcyBFcnJvciB7XG4gICAgY29uc3RydWN0b3IodXBkYXRlID0ge30pIHtcbiAgICAgIGxldCBtZXNzYWdlID0gdXBkYXRlLm1lc3NhZ2UgfHwgJyc7XG4gICAgICBzdXBlcihtZXNzYWdlKTtcblxuICAgICAgbGV0IHRoZV92YWx1ZXMgPSBPYmplY3QuYXNzaWduKGRlZmF1bHRzLCB1cGRhdGUpO1xuICAgICAgT2JqZWN0LmFzc2lnbih0aGlzLCB0aGVfdmFsdWVzKTtcblxuICAgICAgdGhpcy5uYW1lID0gdGhpcy5jb25zdHJ1Y3Rvci5uYW1lO1xuICAgICAgdGhpcy5tZXNzYWdlID0gbWVzc2FnZTtcbiAgICAgIHRoaXNbU3BlY2lhbEZvcm1zLmF0b20oJ19fZXhjZXB0aW9uX18nKV0gPSB0cnVlO1xuICAgICAgRXJyb3IuY2FwdHVyZVN0YWNrVHJhY2UodGhpcywgdGhpcy5jb25zdHJ1Y3Rvci5uYW1lKTtcbiAgICB9XG5cbiAgICBzdGF0aWMgY3JlYXRlKHVwZGF0ZXMgPSB7fSkge1xuICAgICAgbGV0IHggPSBuZXcgdGhpcyh1cGRhdGVzKTtcbiAgICAgIHJldHVybiBPYmplY3QuZnJlZXplKHgpO1xuICAgIH1cbiAgfTtcbn1cblxuZnVuY3Rpb24gZGVmcHJvdG9jb2woc3BlYykge1xuICByZXR1cm4gbmV3IFByb3RvY29sKHNwZWMpO1xufVxuXG5mdW5jdGlvbiBkZWZpbXBsKHByb3RvY29sLCB0eXBlLCBpbXBsKSB7XG4gIHByb3RvY29sLmltcGxlbWVudGF0aW9uKHR5cGUsIGltcGwpO1xufVxuXG5mdW5jdGlvbiBnZXRfb2JqZWN0X2tleXMob2JqKSB7XG4gIHJldHVybiBPYmplY3Qua2V5cyhvYmopLmNvbmNhdChPYmplY3QuZ2V0T3duUHJvcGVydHlTeW1ib2xzKG9iaikpO1xufVxuXG5mdW5jdGlvbiBpc192YWxpZF9jaGFyYWN0ZXIoY29kZXBvaW50KSB7XG4gIHRyeSB7XG4gICAgcmV0dXJuIFN0cmluZy5mcm9tQ29kZVBvaW50KGNvZGVwb2ludCkgIT0gbnVsbDtcbiAgfSBjYXRjaCAoZSkge1xuICAgIHJldHVybiBmYWxzZTtcbiAgfVxufVxuXG4vL2h0dHBzOi8vZGV2ZWxvcGVyLm1vemlsbGEub3JnL2VuLVVTL2RvY3MvV2ViL0FQSS9XaW5kb3dCYXNlNjQvQmFzZTY0X2VuY29kaW5nX2FuZF9kZWNvZGluZyNTb2x1dGlvbl8yXyVFMiU4MCU5M19yZXdyaXRlX3RoZV9ET01zX2F0b2IoKV9hbmRfYnRvYSgpX3VzaW5nX0phdmFTY3JpcHQnc19UeXBlZEFycmF5c19hbmRfVVRGLThcbmZ1bmN0aW9uIGI2NEVuY29kZVVuaWNvZGUoc3RyKSB7XG4gIHJldHVybiBidG9hKGVuY29kZVVSSUNvbXBvbmVudChzdHIpLnJlcGxhY2UoLyUoWzAtOUEtRl17Mn0pL2csIGZ1bmN0aW9uIChtYXRjaCwgcDEpIHtcbiAgICByZXR1cm4gU3RyaW5nLmZyb21DaGFyQ29kZSgnMHgnICsgcDEpO1xuICB9KSk7XG59XG5cbmZ1bmN0aW9uIGRlbGV0ZV9wcm9wZXJ0eV9mcm9tX21hcChtYXAsIHByb3BlcnR5KSB7XG4gIGxldCBuZXdfbWFwID0gT2JqZWN0LmFzc2lnbihPYmplY3QuY3JlYXRlKG1hcC5jb25zdHJ1Y3Rvci5wcm90b3R5cGUpLCBtYXApO1xuICBkZWxldGUgbmV3X21hcFtwcm9wZXJ0eV07XG5cbiAgcmV0dXJuIE9iamVjdC5mcmVlemUobmV3X21hcCk7XG59XG5cbmZ1bmN0aW9uIGNsYXNzX3RvX29iaihtYXApIHtcbiAgbGV0IG5ld19tYXAgPSBPYmplY3QuYXNzaWduKHt9LCBtYXApO1xuICByZXR1cm4gT2JqZWN0LmZyZWV6ZShuZXdfbWFwKTtcbn1cblxuZnVuY3Rpb24gYWRkX3Byb3BlcnR5X3RvX21hcChtYXAsIHByb3BlcnR5LCB2YWx1ZSkge1xuICBsZXQgbmV3X21hcCA9IE9iamVjdC5hc3NpZ24oe30sIG1hcCk7XG4gIG5ld19tYXBbcHJvcGVydHldID0gdmFsdWU7XG4gIHJldHVybiBPYmplY3QuZnJlZXplKG5ld19tYXApO1xufVxuXG5mdW5jdGlvbiBibm90KGV4cHIpIHtcbiAgcmV0dXJuIH5leHByO1xufVxuXG5mdW5jdGlvbiBiYW5kKGxlZnQsIHJpZ2h0KSB7XG4gIHJldHVybiBsZWZ0ICYgcmlnaHQ7XG59XG5cbmZ1bmN0aW9uIGJvcihsZWZ0LCByaWdodCkge1xuICByZXR1cm4gbGVmdCB8IHJpZ2h0O1xufVxuXG5mdW5jdGlvbiBic2wobGVmdCwgcmlnaHQpIHtcbiAgcmV0dXJuIGxlZnQgPDwgcmlnaHQ7XG59XG5cbmZ1bmN0aW9uIGJzcihsZWZ0LCByaWdodCkge1xuICByZXR1cm4gbGVmdCA+PiByaWdodDtcbn1cblxuZnVuY3Rpb24gYnhvcihsZWZ0LCByaWdodCkge1xuICByZXR1cm4gbGVmdCBeIHJpZ2h0O1xufVxuXG5mdW5jdGlvbiB6aXAobGlzdF9vZl9saXN0cykge1xuICBpZiAobGlzdF9vZl9saXN0cy5sZW5ndGggPT09IDApIHtcbiAgICByZXR1cm4gT2JqZWN0LmZyZWV6ZShbXSk7XG4gIH1cblxuICBsZXQgbmV3X3ZhbHVlID0gW107XG4gIGxldCBzbWFsbGVzdF9sZW5ndGggPSBsaXN0X29mX2xpc3RzWzBdO1xuXG4gIGZvciAobGV0IHggb2YgbGlzdF9vZl9saXN0cykge1xuICAgIGlmICh4Lmxlbmd0aCA8IHNtYWxsZXN0X2xlbmd0aCkge1xuICAgICAgc21hbGxlc3RfbGVuZ3RoID0geC5sZW5ndGg7XG4gICAgfVxuICB9XG5cbiAgZm9yIChsZXQgaSA9IDA7IGkgPCBzbWFsbGVzdF9sZW5ndGg7IGkrKykge1xuICAgIGxldCBjdXJyZW50X3ZhbHVlID0gW107XG4gICAgZm9yIChsZXQgaiA9IDA7IGogPCBsaXN0X29mX2xpc3RzLmxlbmd0aDsgaisrKSB7XG4gICAgICBjdXJyZW50X3ZhbHVlLnB1c2gobGlzdF9vZl9saXN0c1tqXVtpXSk7XG4gICAgfVxuXG4gICAgbmV3X3ZhbHVlLnB1c2gobmV3IFR1cGxlKC4uLmN1cnJlbnRfdmFsdWUpKTtcbiAgfVxuXG4gIHJldHVybiBPYmplY3QuZnJlZXplKG5ld192YWx1ZSk7XG59XG5cbmZ1bmN0aW9uIGNhbl9kZWNvZGU2NChkYXRhKSB7XG4gIHRyeSB7XG4gICAgYXRvYihkYXRhKTtcbiAgICByZXR1cm4gdHJ1ZTtcbiAgfSBjYXRjaCAoZSkge1xuICAgIHJldHVybiBmYWxzZTtcbiAgfVxufVxuXG52YXIgRnVuY3Rpb25zID0ge1xuICBjYWxsX3Byb3BlcnR5LFxuICBhcHBseSxcbiAgY29udGFpbnMsXG4gIGdldF9nbG9iYWwsXG4gIGRlZnN0cnVjdCxcbiAgZGVmZXhjZXB0aW9uLFxuICBkZWZwcm90b2NvbCxcbiAgZGVmaW1wbCxcbiAgZ2V0X29iamVjdF9rZXlzLFxuICBpc192YWxpZF9jaGFyYWN0ZXIsXG4gIGI2NEVuY29kZVVuaWNvZGUsXG4gIGRlbGV0ZV9wcm9wZXJ0eV9mcm9tX21hcCxcbiAgYWRkX3Byb3BlcnR5X3RvX21hcCxcbiAgY2xhc3NfdG9fb2JqLFxuICBjYW5fZGVjb2RlNjQsXG4gIGJub3QsXG4gIGJhbmQsXG4gIGJvcixcbiAgYnNsLFxuICBic3IsXG4gIGJ4b3IsXG4gIHppcFxufTtcblxuZnVuY3Rpb24gbGlzdCguLi5hcmdzKSB7XG4gIHJldHVybiBPYmplY3QuZnJlZXplKGFyZ3MpO1xufVxuXG5mdW5jdGlvbiBiaXRzdHJpbmcoLi4uYXJncykge1xuICByZXR1cm4gbmV3IEJpdFN0cmluZyguLi5hcmdzKTtcbn1cblxuZnVuY3Rpb24gdHVwbGUoLi4uYXJncykge1xuICByZXR1cm4gbmV3IFR1cGxlKC4uLmFyZ3MpO1xufVxuXG5mdW5jdGlvbiBfY2FzZShjb25kaXRpb24sIGNsYXVzZXMpIHtcbiAgcmV0dXJuIFBhdHRlcm5zLmRlZm1hdGNoKC4uLmNsYXVzZXMpKGNvbmRpdGlvbik7XG59XG5cbmZ1bmN0aW9uIGNvbmQoY2xhdXNlcykge1xuICBmb3IgKGxldCBjbGF1c2Ugb2YgY2xhdXNlcykge1xuICAgIGlmIChjbGF1c2VbMF0pIHtcbiAgICAgIHJldHVybiBjbGF1c2VbMV0oKTtcbiAgICB9XG4gIH1cblxuICB0aHJvdyBuZXcgRXJyb3IoKTtcbn1cblxuZnVuY3Rpb24gbWFwKG9iaikge1xuICByZXR1cm4gT2JqZWN0LmZyZWV6ZShvYmopO1xufVxuXG5mdW5jdGlvbiBtYXBfdXBkYXRlKG1hcCwgdmFsdWVzKSB7XG4gIHJldHVybiBPYmplY3QuZnJlZXplKE9iamVjdC5hc3NpZ24oT2JqZWN0LmNyZWF0ZShtYXAuY29uc3RydWN0b3IucHJvdG90eXBlKSwgbWFwLCB2YWx1ZXMpKTtcbn1cblxuZnVuY3Rpb24gX2Zvcihjb2xsZWN0aW9ucywgZnVuLCBmaWx0ZXIgPSAoKSA9PiB0cnVlLCBpbnRvID0gW10sIHByZXZpb3VzVmFsdWVzID0gW10pIHtcbiAgbGV0IHBhdHRlcm4gPSBjb2xsZWN0aW9uc1swXVswXTtcbiAgbGV0IGNvbGxlY3Rpb24gPSBjb2xsZWN0aW9uc1swXVsxXTtcblxuICBpZiAoY29sbGVjdGlvbnMubGVuZ3RoID09PSAxKSB7XG5cbiAgICBmb3IgKGxldCBlbGVtIG9mIGNvbGxlY3Rpb24pIHtcbiAgICAgIGxldCByID0gUGF0dGVybnMubWF0Y2hfbm9fdGhyb3cocGF0dGVybiwgZWxlbSk7XG4gICAgICBsZXQgYXJncyA9IHByZXZpb3VzVmFsdWVzLmNvbmNhdChyKTtcblxuICAgICAgaWYgKHIgJiYgZmlsdGVyLmFwcGx5KHRoaXMsIGFyZ3MpKSB7XG4gICAgICAgIGludG8gPSBpbnRvLmNvbmNhdChbZnVuLmFwcGx5KHRoaXMsIGFyZ3MpXSk7XG4gICAgICB9XG4gICAgfVxuXG4gICAgcmV0dXJuIGludG87XG4gIH0gZWxzZSB7XG4gICAgbGV0IF9pbnRvID0gW107XG5cbiAgICBmb3IgKGxldCBlbGVtIG9mIGNvbGxlY3Rpb24pIHtcbiAgICAgIGxldCByID0gUGF0dGVybnMubWF0Y2hfbm9fdGhyb3cocGF0dGVybiwgZWxlbSk7XG4gICAgICBpZiAocikge1xuICAgICAgICBfaW50byA9IGludG8uY29uY2F0KHRoaXMuX2Zvcihjb2xsZWN0aW9ucy5zbGljZSgxKSwgZnVuLCBmaWx0ZXIsIF9pbnRvLCBwcmV2aW91c1ZhbHVlcy5jb25jYXQocikpKTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICByZXR1cm4gX2ludG87XG4gIH1cbn1cblxuZnVuY3Rpb24gX3RyeShkb19mdW4sIHJlc2N1ZV9mdW5jdGlvbiwgY2F0Y2hfZnVuLCBlbHNlX2Z1bmN0aW9uLCBhZnRlcl9mdW5jdGlvbikge1xuICBsZXQgcmVzdWx0ID0gbnVsbDtcblxuICB0cnkge1xuICAgIHJlc3VsdCA9IGRvX2Z1bigpO1xuICB9IGNhdGNoIChlKSB7XG4gICAgbGV0IGV4X3Jlc3VsdCA9IG51bGw7XG5cbiAgICBpZiAocmVzY3VlX2Z1bmN0aW9uKSB7XG4gICAgICB0cnkge1xuICAgICAgICBleF9yZXN1bHQgPSByZXNjdWVfZnVuY3Rpb24oZSk7XG4gICAgICAgIHJldHVybiBleF9yZXN1bHQ7XG4gICAgICB9IGNhdGNoIChleCkge1xuICAgICAgICBpZiAoZXggaW5zdGFuY2VvZiBQYXR0ZXJucy5NYXRjaEVycm9yKSB7XG4gICAgICAgICAgdGhyb3cgZXg7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9XG5cbiAgICBpZiAoY2F0Y2hfZnVuKSB7XG4gICAgICB0cnkge1xuICAgICAgICBleF9yZXN1bHQgPSBjYXRjaF9mdW4oZSk7XG4gICAgICAgIHJldHVybiBleF9yZXN1bHQ7XG4gICAgICB9IGNhdGNoIChleCkge1xuICAgICAgICBpZiAoZXggaW5zdGFuY2VvZiBQYXR0ZXJucy5NYXRjaEVycm9yKSB7XG4gICAgICAgICAgdGhyb3cgZXg7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9XG5cbiAgICB0aHJvdyBlO1xuICB9IGZpbmFsbHkge1xuICAgIGlmIChhZnRlcl9mdW5jdGlvbikge1xuICAgICAgYWZ0ZXJfZnVuY3Rpb24oKTtcbiAgICB9XG4gIH1cblxuICBpZiAoZWxzZV9mdW5jdGlvbikge1xuICAgIHRyeSB7XG4gICAgICByZXR1cm4gZWxzZV9mdW5jdGlvbihyZXN1bHQpO1xuICAgIH0gY2F0Y2ggKGV4KSB7XG4gICAgICBpZiAoZXggaW5zdGFuY2VvZiBQYXR0ZXJucy5NYXRjaEVycm9yKSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcignTm8gTWF0Y2ggRm91bmQgaW4gRWxzZScpO1xuICAgICAgfVxuXG4gICAgICB0aHJvdyBleDtcbiAgICB9XG4gIH0gZWxzZSB7XG4gICAgcmV0dXJuIHJlc3VsdDtcbiAgfVxufVxuXG52YXIgc3BlY2lhbF9mb3JtcyA9IHtcbiAgbGlzdCxcbiAgYml0c3RyaW5nLFxuICB0dXBsZSxcbiAgX2Nhc2UsXG4gIGNvbmQsXG4gIG1hcCxcbiAgbWFwX3VwZGF0ZSxcbiAgX2ZvcixcbiAgX3RyeVxufTtcblxuRnVuY3Rpb25zLmdldF9nbG9iYWwoKS5wcm9jZXNzZXMgPSBGdW5jdGlvbnMuZ2V0X2dsb2JhbCgpLnByb2Nlc3NlcyB8fCBuZXcgUHJvY2Vzc1N5c3RlbSgpO1xuXG5cblxudmFyIEMgPSBPYmplY3QuZnJlZXplKHtcblx0UHJvY2Vzc1N5c3RlbTogUHJvY2Vzc1N5c3RlbSxcblx0VHVwbGU6IFR1cGxlLFxuXHRQSUQ6IFBJRCxcblx0Qml0U3RyaW5nOiBCaXRTdHJpbmcsXG5cdFBhdHRlcm5zOiBQYXR0ZXJucyxcblx0SW50ZWdlcjogSW50ZWdlcixcblx0RmxvYXQ6IEZsb2F0LFxuXHRGdW5jdGlvbnM6IEZ1bmN0aW9ucyxcblx0TGlzdDogTGlzdCxcblx0U3BlY2lhbEZvcm1zOiBzcGVjaWFsX2Zvcm1zXG59KTtcblxubGV0IEVudW0gPSB7XG5cbiAgYWxsX19xbWFya19fOiBmdW5jdGlvbiAoY29sbGVjdGlvbiwgZnVuID0geCA9PiB4KSB7XG4gICAgZm9yIChsZXQgZWxlbSBvZiBjb2xsZWN0aW9uKSB7XG4gICAgICBpZiAoIWZ1bihlbGVtKSkge1xuICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICB9XG4gICAgfVxuXG4gICAgcmV0dXJuIHRydWU7XG4gIH0sXG5cbiAgYW55X19xbWFya19fOiBmdW5jdGlvbiAoY29sbGVjdGlvbiwgZnVuID0geCA9PiB4KSB7XG4gICAgZm9yIChsZXQgZWxlbSBvZiBjb2xsZWN0aW9uKSB7XG4gICAgICBpZiAoZnVuKGVsZW0pKSB7XG4gICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgfVxuICAgIH1cblxuICAgIHJldHVybiBmYWxzZTtcbiAgfSxcblxuICBhdDogZnVuY3Rpb24gKGNvbGxlY3Rpb24sIG4sIHRoZV9kZWZhdWx0ID0gbnVsbCkge1xuICAgIGlmIChuID4gdGhpcy5jb3VudChjb2xsZWN0aW9uKSB8fCBuIDwgMCkge1xuICAgICAgcmV0dXJuIHRoZV9kZWZhdWx0O1xuICAgIH1cblxuICAgIHJldHVybiBjb2xsZWN0aW9uW25dO1xuICB9LFxuXG4gIGNvbmNhdDogZnVuY3Rpb24gKC4uLmVudW1hYmxlcykge1xuICAgIHJldHVybiBlbnVtYWJsZXNbMF0uY29uY2F0KGVudW1hYmxlc1sxXSk7XG4gIH0sXG5cbiAgY291bnQ6IGZ1bmN0aW9uIChjb2xsZWN0aW9uLCBmdW4gPSBudWxsKSB7XG4gICAgaWYgKGZ1biA9PSBudWxsKSB7XG4gICAgICByZXR1cm4gY29sbGVjdGlvbi5sZW5ndGg7XG4gICAgfSBlbHNlIHtcbiAgICAgIHJldHVybiBjb2xsZWN0aW9uLmZpbHRlcihmdW4pLmxlbmd0aDtcbiAgICB9XG4gIH0sXG5cbiAgZHJvcDogZnVuY3Rpb24gKGNvbGxlY3Rpb24sIGNvdW50KSB7XG4gICAgcmV0dXJuIGNvbGxlY3Rpb24uc2xpY2UoY291bnQpO1xuICB9LFxuXG4gIGRyb3Bfd2hpbGU6IGZ1bmN0aW9uIChjb2xsZWN0aW9uLCBmdW4pIHtcbiAgICBsZXQgY291bnQgPSAwO1xuXG4gICAgZm9yIChsZXQgZWxlbSBvZiBjb2xsZWN0aW9uKSB7XG4gICAgICBpZiAoZnVuKGVsZW0pKSB7XG4gICAgICAgIGNvdW50ID0gY291bnQgKyAxO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgYnJlYWs7XG4gICAgICB9XG4gICAgfVxuXG4gICAgcmV0dXJuIGNvbGxlY3Rpb24uc2xpY2UoY291bnQpO1xuICB9LFxuXG4gIGVhY2g6IGZ1bmN0aW9uIChjb2xsZWN0aW9uLCBmdW4pIHtcbiAgICBmb3IgKGxldCBlbGVtIG9mIGNvbGxlY3Rpb24pIHtcbiAgICAgIGZ1bihlbGVtKTtcbiAgICB9XG4gIH0sXG5cbiAgZW1wdHlfX3FtYXJrX186IGZ1bmN0aW9uIChjb2xsZWN0aW9uKSB7XG4gICAgcmV0dXJuIGNvbGxlY3Rpb24ubGVuZ3RoID09PSAwO1xuICB9LFxuXG4gIGZldGNoOiBmdW5jdGlvbiAoY29sbGVjdGlvbiwgbikge1xuICAgIGlmIChBcnJheS5pc0FycmF5KGNvbGxlY3Rpb24pKSB7XG4gICAgICBpZiAobiA8IHRoaXMuY291bnQoY29sbGVjdGlvbikgJiYgbiA+PSAwKSB7XG4gICAgICAgIHJldHVybiBuZXcgVHVwbGUoU3ltYm9sLmZvcihcIm9rXCIpLCBjb2xsZWN0aW9uW25dKTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHJldHVybiBTeW1ib2wuZm9yKFwiZXJyb3JcIik7XG4gICAgICB9XG4gICAgfVxuXG4gICAgdGhyb3cgbmV3IEVycm9yKFwiY29sbGVjdGlvbiBpcyBub3QgYW4gRW51bWVyYWJsZVwiKTtcbiAgfSxcblxuICBmZXRjaF9fZW1hcmtfXzogZnVuY3Rpb24gKGNvbGxlY3Rpb24sIG4pIHtcbiAgICBpZiAoQXJyYXkuaXNBcnJheShjb2xsZWN0aW9uKSkge1xuICAgICAgaWYgKG4gPCB0aGlzLmNvdW50KGNvbGxlY3Rpb24pICYmIG4gPj0gMCkge1xuICAgICAgICByZXR1cm4gY29sbGVjdGlvbltuXTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcihcIm91dCBvZiBib3VuZHMgZXJyb3JcIik7XG4gICAgICB9XG4gICAgfVxuXG4gICAgdGhyb3cgbmV3IEVycm9yKFwiY29sbGVjdGlvbiBpcyBub3QgYW4gRW51bWVyYWJsZVwiKTtcbiAgfSxcblxuICBmaWx0ZXI6IGZ1bmN0aW9uIChjb2xsZWN0aW9uLCBmdW4pIHtcbiAgICBsZXQgcmVzdWx0ID0gW107XG5cbiAgICBmb3IgKGxldCBlbGVtIG9mIGNvbGxlY3Rpb24pIHtcbiAgICAgIGlmIChmdW4oZWxlbSkpIHtcbiAgICAgICAgcmVzdWx0LnB1c2goZWxlbSk7XG4gICAgICB9XG4gICAgfVxuXG4gICAgcmV0dXJuIHJlc3VsdDtcbiAgfSxcblxuICBmaWx0ZXJfbWFwOiBmdW5jdGlvbiAoY29sbGVjdGlvbiwgZmlsdGVyLCBtYXBwZXIpIHtcbiAgICByZXR1cm4gRW51bS5tYXAoRW51bS5maWx0ZXIoY29sbGVjdGlvbiwgZmlsdGVyKSwgbWFwcGVyKTtcbiAgfSxcblxuICBmaW5kOiBmdW5jdGlvbiAoY29sbGVjdGlvbiwgaWZfbm9uZSA9IG51bGwsIGZ1bikge1xuICAgIGZvciAobGV0IGVsZW0gb2YgY29sbGVjdGlvbikge1xuICAgICAgaWYgKGZ1bihlbGVtKSkge1xuICAgICAgICByZXR1cm4gZWxlbTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICByZXR1cm4gaWZfbm9uZTtcbiAgfSxcblxuICBpbnRvOiBmdW5jdGlvbiAoY29sbGVjdGlvbiwgbGlzdCkge1xuICAgIHJldHVybiBsaXN0LmNvbmNhdChjb2xsZWN0aW9uKTtcbiAgfSxcblxuICBtYXA6IGZ1bmN0aW9uIChjb2xsZWN0aW9uLCBmdW4pIHtcbiAgICBsZXQgcmVzdWx0ID0gW107XG5cbiAgICBmb3IgKGxldCBlbGVtIG9mIGNvbGxlY3Rpb24pIHtcbiAgICAgIHJlc3VsdC5wdXNoKGZ1bihlbGVtKSk7XG4gICAgfVxuXG4gICAgcmV0dXJuIHJlc3VsdDtcbiAgfSxcblxuICBtYXBfcmVkdWNlOiBmdW5jdGlvbiAoY29sbGVjdGlvbiwgYWNjLCBmdW4pIHtcbiAgICBsZXQgbWFwcGVkID0gTGlzdCgpO1xuICAgIGxldCB0aGVfYWNjID0gYWNjO1xuXG4gICAgZm9yICh2YXIgaSA9IDA7IGkgPCB0aGlzLmNvdW50KGNvbGxlY3Rpb24pOyBpKyspIHtcbiAgICAgIGxldCB0dXBsZSA9IGZ1bihjb2xsZWN0aW9uW2ldLCB0aGVfYWNjKTtcblxuICAgICAgdGhlX2FjYyA9IHR1cGxlLmdldCgxKTtcbiAgICAgIG1hcHBlZCA9IExpc3QoLi4ubWFwcGVkLmNvbmNhdChbdHVwbGUuZ2V0KDApXSkpO1xuICAgIH1cblxuICAgIHJldHVybiBuZXcgVHVwbGUobWFwcGVkLCB0aGVfYWNjKTtcbiAgfSxcblxuICBtZW1iZXJfX3FtYXJrX186IGZ1bmN0aW9uIChjb2xsZWN0aW9uLCB2YWx1ZSkge1xuICAgIHJldHVybiBjb2xsZWN0aW9uLmluY2x1ZGVzKHZhbHVlKTtcbiAgfSxcblxuICByZWR1Y2U6IGZ1bmN0aW9uIChjb2xsZWN0aW9uLCBhY2MsIGZ1bikge1xuICAgIGxldCB0aGVfYWNjID0gYWNjO1xuXG4gICAgZm9yICh2YXIgaSA9IDA7IGkgPCB0aGlzLmNvdW50KGNvbGxlY3Rpb24pOyBpKyspIHtcbiAgICAgIGxldCB0dXBsZSA9IGZ1bihjb2xsZWN0aW9uW2ldLCB0aGVfYWNjKTtcblxuICAgICAgdGhlX2FjYyA9IHR1cGxlLmdldCgxKTtcbiAgICB9XG5cbiAgICByZXR1cm4gdGhlX2FjYztcbiAgfSxcblxuICB0YWtlOiBmdW5jdGlvbiAoY29sbGVjdGlvbiwgY291bnQpIHtcbiAgICByZXR1cm4gY29sbGVjdGlvbi5zbGljZSgwLCBjb3VudCk7XG4gIH0sXG5cbiAgdGFrZV9ldmVyeTogZnVuY3Rpb24gKGNvbGxlY3Rpb24sIG50aCkge1xuICAgIGxldCByZXN1bHQgPSBbXTtcbiAgICBsZXQgaW5kZXggPSAwO1xuXG4gICAgZm9yIChsZXQgZWxlbSBvZiBjb2xsZWN0aW9uKSB7XG4gICAgICBpZiAoaW5kZXggJSBudGggPT09IDApIHtcbiAgICAgICAgcmVzdWx0LnB1c2goZWxlbSk7XG4gICAgICB9XG4gICAgfVxuXG4gICAgcmV0dXJuIExpc3QoLi4ucmVzdWx0KTtcbiAgfSxcblxuICB0YWtlX3doaWxlOiBmdW5jdGlvbiAoY29sbGVjdGlvbiwgZnVuKSB7XG4gICAgbGV0IGNvdW50ID0gMDtcblxuICAgIGZvciAobGV0IGVsZW0gb2YgY29sbGVjdGlvbikge1xuICAgICAgaWYgKGZ1bihlbGVtKSkge1xuICAgICAgICBjb3VudCA9IGNvdW50ICsgMTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIGJyZWFrO1xuICAgICAgfVxuICAgIH1cblxuICAgIHJldHVybiBjb2xsZWN0aW9uLnNsaWNlKDAsIGNvdW50KTtcbiAgfSxcblxuICB0b19saXN0OiBmdW5jdGlvbiAoY29sbGVjdGlvbikge1xuICAgIHJldHVybiBjb2xsZWN0aW9uO1xuICB9XG59O1xuXG5sZXQgVmlydHVhbERPTSA9IChmdW5jdGlvbiAoZSkge1xuICAgIHJldHVybiBlKCk7XG59KShmdW5jdGlvbiAoKSB7XG4gICAgdmFyIGRlZmluZSwgbW9kdWxlLCBleHBvcnRzO1xuICAgIHJldHVybiAoZnVuY3Rpb24gZSh0LCBuLCByKSB7XG4gICAgICAgIGZ1bmN0aW9uIHMobywgdSkge1xuICAgICAgICAgICAgaWYgKCFuW29dKSB7XG4gICAgICAgICAgICAgICAgaWYgKCF0W29dKSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciBhID0gdHlwZW9mIHJlcXVpcmUgPT0gXCJmdW5jdGlvblwiICYmIHJlcXVpcmU7XG4gICAgICAgICAgICAgICAgICAgIGlmICghdSAmJiBhKSByZXR1cm4gYShvLCAhMCk7XG4gICAgICAgICAgICAgICAgICAgIGlmIChpKSByZXR1cm4gaShvLCAhMCk7XG4gICAgICAgICAgICAgICAgICAgIHZhciBmID0gbmV3IEVycm9yKFwiQ2Fubm90IGZpbmQgbW9kdWxlICdcIiArIG8gKyBcIidcIik7XG4gICAgICAgICAgICAgICAgICAgIHRocm93IChmLmNvZGUgPSBcIk1PRFVMRV9OT1RfRk9VTkRcIiwgZik7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHZhciBsID0gbltvXSA9IHtcbiAgICAgICAgICAgICAgICAgICAgZXhwb3J0czoge31cbiAgICAgICAgICAgICAgICB9O1xuICAgICAgICAgICAgICAgIHRbb11bMF0uY2FsbChsLmV4cG9ydHMsIGZ1bmN0aW9uIChlKSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciBuID0gdFtvXVsxXVtlXTtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHMobiA/IG4gOiBlKTtcbiAgICAgICAgICAgICAgICB9LCBsLCBsLmV4cG9ydHMsIGUsIHQsIG4sIHIpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmV0dXJuIG5bb10uZXhwb3J0cztcbiAgICAgICAgfVxuICAgICAgICB2YXIgaSA9IHR5cGVvZiByZXF1aXJlID09IFwiZnVuY3Rpb25cIiAmJiByZXF1aXJlO1xuICAgICAgICBmb3IgKHZhciBvID0gMDsgbyA8IHIubGVuZ3RoOyBvKyspIHMocltvXSk7XG4gICAgICAgIHJldHVybiBzO1xuICAgIH0pKHtcbiAgICAgICAgMTogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHtcblxuICAgICAgICAgICAgdmFyIGNyZWF0ZUVsZW1lbnQgPSByZXF1aXJlKFwiLi92ZG9tL2NyZWF0ZS1lbGVtZW50LmpzXCIpO1xuXG4gICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IGNyZWF0ZUVsZW1lbnQ7XG4gICAgICAgIH0sIHsgXCIuL3Zkb20vY3JlYXRlLWVsZW1lbnQuanNcIjogMTUgfV0sIDI6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICB2YXIgZGlmZiA9IHJlcXVpcmUoXCIuL3Z0cmVlL2RpZmYuanNcIik7XG5cbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gZGlmZjtcbiAgICAgICAgfSwgeyBcIi4vdnRyZWUvZGlmZi5qc1wiOiAzNSB9XSwgMzogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHtcbiAgICAgICAgICAgIHZhciBoID0gcmVxdWlyZShcIi4vdmlydHVhbC1oeXBlcnNjcmlwdC9pbmRleC5qc1wiKTtcblxuICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBoO1xuICAgICAgICB9LCB7IFwiLi92aXJ0dWFsLWh5cGVyc2NyaXB0L2luZGV4LmpzXCI6IDIyIH1dLCA0OiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge1xuICAgICAgICAgICAgdmFyIGRpZmYgPSByZXF1aXJlKFwiLi9kaWZmLmpzXCIpO1xuICAgICAgICAgICAgdmFyIHBhdGNoID0gcmVxdWlyZShcIi4vcGF0Y2guanNcIik7XG4gICAgICAgICAgICB2YXIgaCA9IHJlcXVpcmUoXCIuL2guanNcIik7XG4gICAgICAgICAgICB2YXIgY3JlYXRlID0gcmVxdWlyZShcIi4vY3JlYXRlLWVsZW1lbnQuanNcIik7XG4gICAgICAgICAgICB2YXIgVk5vZGUgPSByZXF1aXJlKFwiLi92bm9kZS92bm9kZS5qc1wiKTtcbiAgICAgICAgICAgIHZhciBWVGV4dCA9IHJlcXVpcmUoXCIuL3Zub2RlL3Z0ZXh0LmpzXCIpO1xuXG4gICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IHtcbiAgICAgICAgICAgICAgICBkaWZmOiBkaWZmLFxuICAgICAgICAgICAgICAgIHBhdGNoOiBwYXRjaCxcbiAgICAgICAgICAgICAgICBoOiBoLFxuICAgICAgICAgICAgICAgIGNyZWF0ZTogY3JlYXRlLFxuICAgICAgICAgICAgICAgIFZOb2RlOiBWTm9kZSxcbiAgICAgICAgICAgICAgICBWVGV4dDogVlRleHRcbiAgICAgICAgICAgIH07XG4gICAgICAgIH0sIHsgXCIuL2NyZWF0ZS1lbGVtZW50LmpzXCI6IDEsIFwiLi9kaWZmLmpzXCI6IDIsIFwiLi9oLmpzXCI6IDMsIFwiLi9wYXRjaC5qc1wiOiAxMywgXCIuL3Zub2RlL3Zub2RlLmpzXCI6IDMxLCBcIi4vdm5vZGUvdnRleHQuanNcIjogMzMgfV0sIDU6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICAvKiFcbiAgICAgICAgICAgICAqIENyb3NzLUJyb3dzZXIgU3BsaXQgMS4xLjFcbiAgICAgICAgICAgICAqIENvcHlyaWdodCAyMDA3LTIwMTIgU3RldmVuIExldml0aGFuIDxzdGV2ZW5sZXZpdGhhbi5jb20+XG4gICAgICAgICAgICAgKiBBdmFpbGFibGUgdW5kZXIgdGhlIE1JVCBMaWNlbnNlXG4gICAgICAgICAgICAgKiBFQ01BU2NyaXB0IGNvbXBsaWFudCwgdW5pZm9ybSBjcm9zcy1icm93c2VyIHNwbGl0IG1ldGhvZFxuICAgICAgICAgICAgICovXG5cbiAgICAgICAgICAgIC8qKlxuICAgICAgICAgICAgICogU3BsaXRzIGEgc3RyaW5nIGludG8gYW4gYXJyYXkgb2Ygc3RyaW5ncyB1c2luZyBhIHJlZ2V4IG9yIHN0cmluZyBzZXBhcmF0b3IuIE1hdGNoZXMgb2YgdGhlXG4gICAgICAgICAgICAgKiBzZXBhcmF0b3IgYXJlIG5vdCBpbmNsdWRlZCBpbiB0aGUgcmVzdWx0IGFycmF5LiBIb3dldmVyLCBpZiBgc2VwYXJhdG9yYCBpcyBhIHJlZ2V4IHRoYXQgY29udGFpbnNcbiAgICAgICAgICAgICAqIGNhcHR1cmluZyBncm91cHMsIGJhY2tyZWZlcmVuY2VzIGFyZSBzcGxpY2VkIGludG8gdGhlIHJlc3VsdCBlYWNoIHRpbWUgYHNlcGFyYXRvcmAgaXMgbWF0Y2hlZC5cbiAgICAgICAgICAgICAqIEZpeGVzIGJyb3dzZXIgYnVncyBjb21wYXJlZCB0byB0aGUgbmF0aXZlIGBTdHJpbmcucHJvdG90eXBlLnNwbGl0YCBhbmQgY2FuIGJlIHVzZWQgcmVsaWFibHlcbiAgICAgICAgICAgICAqIGNyb3NzLWJyb3dzZXIuXG4gICAgICAgICAgICAgKiBAcGFyYW0ge1N0cmluZ30gc3RyIFN0cmluZyB0byBzcGxpdC5cbiAgICAgICAgICAgICAqIEBwYXJhbSB7UmVnRXhwfFN0cmluZ30gc2VwYXJhdG9yIFJlZ2V4IG9yIHN0cmluZyB0byB1c2UgZm9yIHNlcGFyYXRpbmcgdGhlIHN0cmluZy5cbiAgICAgICAgICAgICAqIEBwYXJhbSB7TnVtYmVyfSBbbGltaXRdIE1heGltdW0gbnVtYmVyIG9mIGl0ZW1zIHRvIGluY2x1ZGUgaW4gdGhlIHJlc3VsdCBhcnJheS5cbiAgICAgICAgICAgICAqIEByZXR1cm5zIHtBcnJheX0gQXJyYXkgb2Ygc3Vic3RyaW5ncy5cbiAgICAgICAgICAgICAqIEBleGFtcGxlXG4gICAgICAgICAgICAgKlxuICAgICAgICAgICAgICogLy8gQmFzaWMgdXNlXG4gICAgICAgICAgICAgKiBzcGxpdCgnYSBiIGMgZCcsICcgJyk7XG4gICAgICAgICAgICAgKiAvLyAtPiBbJ2EnLCAnYicsICdjJywgJ2QnXVxuICAgICAgICAgICAgICpcbiAgICAgICAgICAgICAqIC8vIFdpdGggbGltaXRcbiAgICAgICAgICAgICAqIHNwbGl0KCdhIGIgYyBkJywgJyAnLCAyKTtcbiAgICAgICAgICAgICAqIC8vIC0+IFsnYScsICdiJ11cbiAgICAgICAgICAgICAqXG4gICAgICAgICAgICAgKiAvLyBCYWNrcmVmZXJlbmNlcyBpbiByZXN1bHQgYXJyYXlcbiAgICAgICAgICAgICAqIHNwbGl0KCcuLndvcmQxIHdvcmQyLi4nLCAvKFthLXpdKykoXFxkKykvaSk7XG4gICAgICAgICAgICAgKiAvLyAtPiBbJy4uJywgJ3dvcmQnLCAnMScsICcgJywgJ3dvcmQnLCAnMicsICcuLiddXG4gICAgICAgICAgICAgKi9cbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gKGZ1bmN0aW9uIHNwbGl0KHVuZGVmKSB7XG5cbiAgICAgICAgICAgICAgICB2YXIgbmF0aXZlU3BsaXQgPSBTdHJpbmcucHJvdG90eXBlLnNwbGl0LFxuICAgICAgICAgICAgICAgICAgICBjb21wbGlhbnRFeGVjTnBjZyA9IC8oKT8/Ly5leGVjKFwiXCIpWzFdID09PSB1bmRlZixcblxuICAgICAgICAgICAgICAgIC8vIE5QQ0c6IG5vbnBhcnRpY2lwYXRpbmcgY2FwdHVyaW5nIGdyb3VwXG4gICAgICAgICAgICAgICAgc2VsZjtcblxuICAgICAgICAgICAgICAgIHNlbGYgPSBmdW5jdGlvbiAoc3RyLCBzZXBhcmF0b3IsIGxpbWl0KSB7XG4gICAgICAgICAgICAgICAgICAgIC8vIElmIGBzZXBhcmF0b3JgIGlzIG5vdCBhIHJlZ2V4LCB1c2UgYG5hdGl2ZVNwbGl0YFxuICAgICAgICAgICAgICAgICAgICBpZiAoT2JqZWN0LnByb3RvdHlwZS50b1N0cmluZy5jYWxsKHNlcGFyYXRvcikgIT09IFwiW29iamVjdCBSZWdFeHBdXCIpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBuYXRpdmVTcGxpdC5jYWxsKHN0ciwgc2VwYXJhdG9yLCBsaW1pdCk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgdmFyIG91dHB1dCA9IFtdLFxuICAgICAgICAgICAgICAgICAgICAgICAgZmxhZ3MgPSAoc2VwYXJhdG9yLmlnbm9yZUNhc2UgPyBcImlcIiA6IFwiXCIpICsgKHNlcGFyYXRvci5tdWx0aWxpbmUgPyBcIm1cIiA6IFwiXCIpICsgKHNlcGFyYXRvci5leHRlbmRlZCA/IFwieFwiIDogXCJcIikgKyAoc2VwYXJhdG9yLnN0aWNreSA/IFwieVwiIDogXCJcIiksXG5cbiAgICAgICAgICAgICAgICAgICAgLy8gRmlyZWZveCAzK1xuICAgICAgICAgICAgICAgICAgICBsYXN0TGFzdEluZGV4ID0gMCxcblxuICAgICAgICAgICAgICAgICAgICAvLyBNYWtlIGBnbG9iYWxgIGFuZCBhdm9pZCBgbGFzdEluZGV4YCBpc3N1ZXMgYnkgd29ya2luZyB3aXRoIGEgY29weVxuICAgICAgICAgICAgICAgICAgICBzZXBhcmF0b3IgPSBuZXcgUmVnRXhwKHNlcGFyYXRvci5zb3VyY2UsIGZsYWdzICsgXCJnXCIpLFxuICAgICAgICAgICAgICAgICAgICAgICAgc2VwYXJhdG9yMixcbiAgICAgICAgICAgICAgICAgICAgICAgIG1hdGNoLFxuICAgICAgICAgICAgICAgICAgICAgICAgbGFzdEluZGV4LFxuICAgICAgICAgICAgICAgICAgICAgICAgbGFzdExlbmd0aDtcbiAgICAgICAgICAgICAgICAgICAgc3RyICs9IFwiXCI7IC8vIFR5cGUtY29udmVydFxuICAgICAgICAgICAgICAgICAgICBpZiAoIWNvbXBsaWFudEV4ZWNOcGNnKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAvLyBEb2Vzbid0IG5lZWQgZmxhZ3MgZ3ksIGJ1dCB0aGV5IGRvbid0IGh1cnRcbiAgICAgICAgICAgICAgICAgICAgICAgIHNlcGFyYXRvcjIgPSBuZXcgUmVnRXhwKFwiXlwiICsgc2VwYXJhdG9yLnNvdXJjZSArIFwiJCg/IVxcXFxzKVwiLCBmbGFncyk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgLyogVmFsdWVzIGZvciBgbGltaXRgLCBwZXIgdGhlIHNwZWM6XG4gICAgICAgICAgICAgICAgICAgICAqIElmIHVuZGVmaW5lZDogNDI5NDk2NzI5NSAvLyBNYXRoLnBvdygyLCAzMikgLSAxXG4gICAgICAgICAgICAgICAgICAgICAqIElmIDAsIEluZmluaXR5LCBvciBOYU46IDBcbiAgICAgICAgICAgICAgICAgICAgICogSWYgcG9zaXRpdmUgbnVtYmVyOiBsaW1pdCA9IE1hdGguZmxvb3IobGltaXQpOyBpZiAobGltaXQgPiA0Mjk0OTY3Mjk1KSBsaW1pdCAtPSA0Mjk0OTY3Mjk2O1xuICAgICAgICAgICAgICAgICAgICAgKiBJZiBuZWdhdGl2ZSBudW1iZXI6IDQyOTQ5NjcyOTYgLSBNYXRoLmZsb29yKE1hdGguYWJzKGxpbWl0KSlcbiAgICAgICAgICAgICAgICAgICAgICogSWYgb3RoZXI6IFR5cGUtY29udmVydCwgdGhlbiB1c2UgdGhlIGFib3ZlIHJ1bGVzXG4gICAgICAgICAgICAgICAgICAgICAqL1xuICAgICAgICAgICAgICAgICAgICBsaW1pdCA9IGxpbWl0ID09PSB1bmRlZiA/IC0xID4+PiAwIDogLy8gTWF0aC5wb3coMiwgMzIpIC0gMVxuICAgICAgICAgICAgICAgICAgICBsaW1pdCA+Pj4gMDsgLy8gVG9VaW50MzIobGltaXQpXG4gICAgICAgICAgICAgICAgICAgIHdoaWxlIChtYXRjaCA9IHNlcGFyYXRvci5leGVjKHN0cikpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIGBzZXBhcmF0b3IubGFzdEluZGV4YCBpcyBub3QgcmVsaWFibGUgY3Jvc3MtYnJvd3NlclxuICAgICAgICAgICAgICAgICAgICAgICAgbGFzdEluZGV4ID0gbWF0Y2guaW5kZXggKyBtYXRjaFswXS5sZW5ndGg7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAobGFzdEluZGV4ID4gbGFzdExhc3RJbmRleCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIG91dHB1dC5wdXNoKHN0ci5zbGljZShsYXN0TGFzdEluZGV4LCBtYXRjaC5pbmRleCkpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIEZpeCBicm93c2VycyB3aG9zZSBgZXhlY2AgbWV0aG9kcyBkb24ndCBjb25zaXN0ZW50bHkgcmV0dXJuIGB1bmRlZmluZWRgIGZvclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIG5vbnBhcnRpY2lwYXRpbmcgY2FwdHVyaW5nIGdyb3Vwc1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmICghY29tcGxpYW50RXhlY05wY2cgJiYgbWF0Y2gubGVuZ3RoID4gMSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBtYXRjaFswXS5yZXBsYWNlKHNlcGFyYXRvcjIsIGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZvciAodmFyIGkgPSAxOyBpIDwgYXJndW1lbnRzLmxlbmd0aCAtIDI7IGkrKykge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChhcmd1bWVudHNbaV0gPT09IHVuZGVmKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1hdGNoW2ldID0gdW5kZWY7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKG1hdGNoLmxlbmd0aCA+IDEgJiYgbWF0Y2guaW5kZXggPCBzdHIubGVuZ3RoKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIEFycmF5LnByb3RvdHlwZS5wdXNoLmFwcGx5KG91dHB1dCwgbWF0Y2guc2xpY2UoMSkpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBsYXN0TGVuZ3RoID0gbWF0Y2hbMF0ubGVuZ3RoO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxhc3RMYXN0SW5kZXggPSBsYXN0SW5kZXg7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKG91dHB1dC5sZW5ndGggPj0gbGltaXQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHNlcGFyYXRvci5sYXN0SW5kZXggPT09IG1hdGNoLmluZGV4KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgc2VwYXJhdG9yLmxhc3RJbmRleCsrOyAvLyBBdm9pZCBhbiBpbmZpbml0ZSBsb29wXG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgaWYgKGxhc3RMYXN0SW5kZXggPT09IHN0ci5sZW5ndGgpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChsYXN0TGVuZ3RoIHx8ICFzZXBhcmF0b3IudGVzdChcIlwiKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIG91dHB1dC5wdXNoKFwiXCIpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgb3V0cHV0LnB1c2goc3RyLnNsaWNlKGxhc3RMYXN0SW5kZXgpKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICByZXR1cm4gb3V0cHV0Lmxlbmd0aCA+IGxpbWl0ID8gb3V0cHV0LnNsaWNlKDAsIGxpbWl0KSA6IG91dHB1dDtcbiAgICAgICAgICAgICAgICB9O1xuXG4gICAgICAgICAgICAgICAgcmV0dXJuIHNlbGY7XG4gICAgICAgICAgICB9KSgpO1xuICAgICAgICB9LCB7fV0sIDY6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7fSwge31dLCA3OiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge1xuICAgICAgICAgICAgXCJ1c2Ugc3RyaWN0XCI7XG5cbiAgICAgICAgICAgIHZhciBPbmVWZXJzaW9uQ29uc3RyYWludCA9IHJlcXVpcmUoXCJpbmRpdmlkdWFsL29uZS12ZXJzaW9uXCIpO1xuXG4gICAgICAgICAgICB2YXIgTVlfVkVSU0lPTiA9IFwiN1wiO1xuICAgICAgICAgICAgT25lVmVyc2lvbkNvbnN0cmFpbnQoXCJldi1zdG9yZVwiLCBNWV9WRVJTSU9OKTtcblxuICAgICAgICAgICAgdmFyIGhhc2hLZXkgPSBcIl9fRVZfU1RPUkVfS0VZQFwiICsgTVlfVkVSU0lPTjtcblxuICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBFdlN0b3JlO1xuXG4gICAgICAgICAgICBmdW5jdGlvbiBFdlN0b3JlKGVsZW0pIHtcbiAgICAgICAgICAgICAgICB2YXIgaGFzaCA9IGVsZW1baGFzaEtleV07XG5cbiAgICAgICAgICAgICAgICBpZiAoIWhhc2gpIHtcbiAgICAgICAgICAgICAgICAgICAgaGFzaCA9IGVsZW1baGFzaEtleV0gPSB7fTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICByZXR1cm4gaGFzaDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSwgeyBcImluZGl2aWR1YWwvb25lLXZlcnNpb25cIjogOSB9XSwgODogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHtcbiAgICAgICAgICAgIChmdW5jdGlvbiAoZ2xvYmFsKSB7XG4gICAgICAgICAgICAgICAgXCJ1c2Ugc3RyaWN0XCI7XG5cbiAgICAgICAgICAgICAgICAvKmdsb2JhbCB3aW5kb3csIGdsb2JhbCovXG5cbiAgICAgICAgICAgICAgICB2YXIgcm9vdCA9IHR5cGVvZiB3aW5kb3cgIT09IFwidW5kZWZpbmVkXCIgPyB3aW5kb3cgOiB0eXBlb2YgZ2xvYmFsICE9PSBcInVuZGVmaW5lZFwiID8gZ2xvYmFsIDoge307XG5cbiAgICAgICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IEluZGl2aWR1YWw7XG5cbiAgICAgICAgICAgICAgICBmdW5jdGlvbiBJbmRpdmlkdWFsKGtleSwgdmFsdWUpIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKGtleSBpbiByb290KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gcm9vdFtrZXldO1xuICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgcm9vdFtrZXldID0gdmFsdWU7XG5cbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHZhbHVlO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0pLmNhbGwodGhpcywgdHlwZW9mIGdsb2JhbCAhPT0gXCJ1bmRlZmluZWRcIiA/IGdsb2JhbCA6IHR5cGVvZiBzZWxmICE9PSBcInVuZGVmaW5lZFwiID8gc2VsZiA6IHR5cGVvZiB3aW5kb3cgIT09IFwidW5kZWZpbmVkXCIgPyB3aW5kb3cgOiB7fSk7XG4gICAgICAgIH0sIHt9XSwgOTogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHtcbiAgICAgICAgICAgIFwidXNlIHN0cmljdFwiO1xuXG4gICAgICAgICAgICB2YXIgSW5kaXZpZHVhbCA9IHJlcXVpcmUoXCIuL2luZGV4LmpzXCIpO1xuXG4gICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IE9uZVZlcnNpb247XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIE9uZVZlcnNpb24obW9kdWxlTmFtZSwgdmVyc2lvbiwgZGVmYXVsdFZhbHVlKSB7XG4gICAgICAgICAgICAgICAgdmFyIGtleSA9IFwiX19JTkRJVklEVUFMX09ORV9WRVJTSU9OX1wiICsgbW9kdWxlTmFtZTtcbiAgICAgICAgICAgICAgICB2YXIgZW5mb3JjZUtleSA9IGtleSArIFwiX0VORk9SQ0VfU0lOR0xFVE9OXCI7XG5cbiAgICAgICAgICAgICAgICB2YXIgdmVyc2lvblZhbHVlID0gSW5kaXZpZHVhbChlbmZvcmNlS2V5LCB2ZXJzaW9uKTtcblxuICAgICAgICAgICAgICAgIGlmICh2ZXJzaW9uVmFsdWUgIT09IHZlcnNpb24pIHtcbiAgICAgICAgICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKFwiQ2FuIG9ubHkgaGF2ZSBvbmUgY29weSBvZiBcIiArIG1vZHVsZU5hbWUgKyBcIi5cXG5cIiArIFwiWW91IGFscmVhZHkgaGF2ZSB2ZXJzaW9uIFwiICsgdmVyc2lvblZhbHVlICsgXCIgaW5zdGFsbGVkLlxcblwiICsgXCJUaGlzIG1lYW5zIHlvdSBjYW5ub3QgaW5zdGFsbCB2ZXJzaW9uIFwiICsgdmVyc2lvbik7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgcmV0dXJuIEluZGl2aWR1YWwoa2V5LCBkZWZhdWx0VmFsdWUpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9LCB7IFwiLi9pbmRleC5qc1wiOiA4IH1dLCAxMDogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHtcbiAgICAgICAgICAgIChmdW5jdGlvbiAoZ2xvYmFsKSB7XG4gICAgICAgICAgICAgICAgdmFyIHRvcExldmVsID0gdHlwZW9mIGdsb2JhbCAhPT0gXCJ1bmRlZmluZWRcIiA/IGdsb2JhbCA6IHR5cGVvZiB3aW5kb3cgIT09IFwidW5kZWZpbmVkXCIgPyB3aW5kb3cgOiB7fTtcbiAgICAgICAgICAgICAgICB2YXIgbWluRG9jID0gcmVxdWlyZShcIm1pbi1kb2N1bWVudFwiKTtcblxuICAgICAgICAgICAgICAgIGlmICh0eXBlb2YgZG9jdW1lbnQgIT09IFwidW5kZWZpbmVkXCIpIHtcbiAgICAgICAgICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBkb2N1bWVudDtcbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICB2YXIgZG9jY3kgPSB0b3BMZXZlbFtcIl9fR0xPQkFMX0RPQ1VNRU5UX0NBQ0hFQDRcIl07XG5cbiAgICAgICAgICAgICAgICAgICAgaWYgKCFkb2NjeSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgZG9jY3kgPSB0b3BMZXZlbFtcIl9fR0xPQkFMX0RPQ1VNRU5UX0NBQ0hFQDRcIl0gPSBtaW5Eb2M7XG4gICAgICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IGRvY2N5O1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0pLmNhbGwodGhpcywgdHlwZW9mIGdsb2JhbCAhPT0gXCJ1bmRlZmluZWRcIiA/IGdsb2JhbCA6IHR5cGVvZiBzZWxmICE9PSBcInVuZGVmaW5lZFwiID8gc2VsZiA6IHR5cGVvZiB3aW5kb3cgIT09IFwidW5kZWZpbmVkXCIgPyB3aW5kb3cgOiB7fSk7XG4gICAgICAgIH0sIHsgXCJtaW4tZG9jdW1lbnRcIjogNiB9XSwgMTE6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICBcInVzZSBzdHJpY3RcIjtcblxuICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiBpc09iamVjdCh4KSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHR5cGVvZiB4ID09PSBcIm9iamVjdFwiICYmIHggIT09IG51bGw7XG4gICAgICAgICAgICB9O1xuICAgICAgICB9LCB7fV0sIDEyOiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge1xuICAgICAgICAgICAgdmFyIG5hdGl2ZUlzQXJyYXkgPSBBcnJheS5pc0FycmF5O1xuICAgICAgICAgICAgdmFyIHRvU3RyaW5nID0gT2JqZWN0LnByb3RvdHlwZS50b1N0cmluZztcblxuICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBuYXRpdmVJc0FycmF5IHx8IGlzQXJyYXk7XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIGlzQXJyYXkob2JqKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHRvU3RyaW5nLmNhbGwob2JqKSA9PT0gXCJbb2JqZWN0IEFycmF5XVwiO1xuICAgICAgICAgICAgfVxuICAgICAgICB9LCB7fV0sIDEzOiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge1xuICAgICAgICAgICAgdmFyIHBhdGNoID0gcmVxdWlyZShcIi4vdmRvbS9wYXRjaC5qc1wiKTtcblxuICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBwYXRjaDtcbiAgICAgICAgfSwgeyBcIi4vdmRvbS9wYXRjaC5qc1wiOiAxOCB9XSwgMTQ6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICB2YXIgaXNPYmplY3QgPSByZXF1aXJlKFwiaXMtb2JqZWN0XCIpO1xuICAgICAgICAgICAgdmFyIGlzSG9vayA9IHJlcXVpcmUoXCIuLi92bm9kZS9pcy12aG9vay5qc1wiKTtcblxuICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBhcHBseVByb3BlcnRpZXM7XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIGFwcGx5UHJvcGVydGllcyhub2RlLCBwcm9wcywgcHJldmlvdXMpIHtcbiAgICAgICAgICAgICAgICBmb3IgKHZhciBwcm9wTmFtZSBpbiBwcm9wcykge1xuICAgICAgICAgICAgICAgICAgICB2YXIgcHJvcFZhbHVlID0gcHJvcHNbcHJvcE5hbWVdO1xuXG4gICAgICAgICAgICAgICAgICAgIGlmIChwcm9wVmFsdWUgPT09IHVuZGVmaW5lZCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgcmVtb3ZlUHJvcGVydHkobm9kZSwgcHJvcE5hbWUsIHByb3BWYWx1ZSwgcHJldmlvdXMpO1xuICAgICAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKGlzSG9vayhwcm9wVmFsdWUpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICByZW1vdmVQcm9wZXJ0eShub2RlLCBwcm9wTmFtZSwgcHJvcFZhbHVlLCBwcmV2aW91cyk7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAocHJvcFZhbHVlLmhvb2spIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBwcm9wVmFsdWUuaG9vayhub2RlLCBwcm9wTmFtZSwgcHJldmlvdXMgPyBwcmV2aW91c1twcm9wTmFtZV0gOiB1bmRlZmluZWQpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGlzT2JqZWN0KHByb3BWYWx1ZSkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBwYXRjaE9iamVjdChub2RlLCBwcm9wcywgcHJldmlvdXMsIHByb3BOYW1lLCBwcm9wVmFsdWUpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBub2RlW3Byb3BOYW1lXSA9IHByb3BWYWx1ZTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZnVuY3Rpb24gcmVtb3ZlUHJvcGVydHkobm9kZSwgcHJvcE5hbWUsIHByb3BWYWx1ZSwgcHJldmlvdXMpIHtcbiAgICAgICAgICAgICAgICBpZiAocHJldmlvdXMpIHtcbiAgICAgICAgICAgICAgICAgICAgdmFyIHByZXZpb3VzVmFsdWUgPSBwcmV2aW91c1twcm9wTmFtZV07XG5cbiAgICAgICAgICAgICAgICAgICAgaWYgKCFpc0hvb2socHJldmlvdXNWYWx1ZSkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChwcm9wTmFtZSA9PT0gXCJhdHRyaWJ1dGVzXCIpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBmb3IgKHZhciBhdHRyTmFtZSBpbiBwcmV2aW91c1ZhbHVlKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG5vZGUucmVtb3ZlQXR0cmlidXRlKGF0dHJOYW1lKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKHByb3BOYW1lID09PSBcInN0eWxlXCIpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBmb3IgKHZhciBpIGluIHByZXZpb3VzVmFsdWUpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbm9kZS5zdHlsZVtpXSA9IFwiXCI7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIGlmICh0eXBlb2YgcHJldmlvdXNWYWx1ZSA9PT0gXCJzdHJpbmdcIikge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIG5vZGVbcHJvcE5hbWVdID0gXCJcIjtcbiAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgbm9kZVtwcm9wTmFtZV0gPSBudWxsO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKHByZXZpb3VzVmFsdWUudW5ob29rKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBwcmV2aW91c1ZhbHVlLnVuaG9vayhub2RlLCBwcm9wTmFtZSwgcHJvcFZhbHVlKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZnVuY3Rpb24gcGF0Y2hPYmplY3Qobm9kZSwgcHJvcHMsIHByZXZpb3VzLCBwcm9wTmFtZSwgcHJvcFZhbHVlKSB7XG4gICAgICAgICAgICAgICAgdmFyIHByZXZpb3VzVmFsdWUgPSBwcmV2aW91cyA/IHByZXZpb3VzW3Byb3BOYW1lXSA6IHVuZGVmaW5lZDtcblxuICAgICAgICAgICAgICAgIC8vIFNldCBhdHRyaWJ1dGVzXG4gICAgICAgICAgICAgICAgaWYgKHByb3BOYW1lID09PSBcImF0dHJpYnV0ZXNcIikge1xuICAgICAgICAgICAgICAgICAgICBmb3IgKHZhciBhdHRyTmFtZSBpbiBwcm9wVmFsdWUpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHZhciBhdHRyVmFsdWUgPSBwcm9wVmFsdWVbYXR0ck5hbWVdO1xuXG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoYXR0clZhbHVlID09PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBub2RlLnJlbW92ZUF0dHJpYnV0ZShhdHRyTmFtZSk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIG5vZGUuc2V0QXR0cmlidXRlKGF0dHJOYW1lLCBhdHRyVmFsdWUpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIGlmIChwcmV2aW91c1ZhbHVlICYmIGlzT2JqZWN0KHByZXZpb3VzVmFsdWUpICYmIGdldFByb3RvdHlwZShwcmV2aW91c1ZhbHVlKSAhPT0gZ2V0UHJvdG90eXBlKHByb3BWYWx1ZSkpIHtcbiAgICAgICAgICAgICAgICAgICAgbm9kZVtwcm9wTmFtZV0gPSBwcm9wVmFsdWU7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICBpZiAoIWlzT2JqZWN0KG5vZGVbcHJvcE5hbWVdKSkge1xuICAgICAgICAgICAgICAgICAgICBub2RlW3Byb3BOYW1lXSA9IHt9O1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHZhciByZXBsYWNlciA9IHByb3BOYW1lID09PSBcInN0eWxlXCIgPyBcIlwiIDogdW5kZWZpbmVkO1xuXG4gICAgICAgICAgICAgICAgZm9yICh2YXIgayBpbiBwcm9wVmFsdWUpIHtcbiAgICAgICAgICAgICAgICAgICAgdmFyIHZhbHVlID0gcHJvcFZhbHVlW2tdO1xuICAgICAgICAgICAgICAgICAgICBub2RlW3Byb3BOYW1lXVtrXSA9IHZhbHVlID09PSB1bmRlZmluZWQgPyByZXBsYWNlciA6IHZhbHVlO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZnVuY3Rpb24gZ2V0UHJvdG90eXBlKHZhbHVlKSB7XG4gICAgICAgICAgICAgICAgaWYgKE9iamVjdC5nZXRQcm90b3R5cGVPZikge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gT2JqZWN0LmdldFByb3RvdHlwZU9mKHZhbHVlKTtcbiAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKHZhbHVlLl9fcHJvdG9fXykge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gdmFsdWUuX19wcm90b19fO1xuICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAodmFsdWUuY29uc3RydWN0b3IpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHZhbHVlLmNvbnN0cnVjdG9yLnByb3RvdHlwZTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH0sIHsgXCIuLi92bm9kZS9pcy12aG9vay5qc1wiOiAyNiwgXCJpcy1vYmplY3RcIjogMTEgfV0sIDE1OiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge1xuICAgICAgICAgICAgdmFyIGRvY3VtZW50ID0gcmVxdWlyZShcImdsb2JhbC9kb2N1bWVudFwiKTtcblxuICAgICAgICAgICAgdmFyIGFwcGx5UHJvcGVydGllcyA9IHJlcXVpcmUoXCIuL2FwcGx5LXByb3BlcnRpZXNcIik7XG5cbiAgICAgICAgICAgIHZhciBpc1ZOb2RlID0gcmVxdWlyZShcIi4uL3Zub2RlL2lzLXZub2RlLmpzXCIpO1xuICAgICAgICAgICAgdmFyIGlzVlRleHQgPSByZXF1aXJlKFwiLi4vdm5vZGUvaXMtdnRleHQuanNcIik7XG4gICAgICAgICAgICB2YXIgaXNXaWRnZXQgPSByZXF1aXJlKFwiLi4vdm5vZGUvaXMtd2lkZ2V0LmpzXCIpO1xuICAgICAgICAgICAgdmFyIGhhbmRsZVRodW5rID0gcmVxdWlyZShcIi4uL3Zub2RlL2hhbmRsZS10aHVuay5qc1wiKTtcblxuICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBjcmVhdGVFbGVtZW50O1xuXG4gICAgICAgICAgICBmdW5jdGlvbiBjcmVhdGVFbGVtZW50KHZub2RlLCBvcHRzKSB7XG4gICAgICAgICAgICAgICAgdmFyIGRvYyA9IG9wdHMgPyBvcHRzLmRvY3VtZW50IHx8IGRvY3VtZW50IDogZG9jdW1lbnQ7XG4gICAgICAgICAgICAgICAgdmFyIHdhcm4gPSBvcHRzID8gb3B0cy53YXJuIDogbnVsbDtcblxuICAgICAgICAgICAgICAgIHZub2RlID0gaGFuZGxlVGh1bmsodm5vZGUpLmE7XG5cbiAgICAgICAgICAgICAgICBpZiAoaXNXaWRnZXQodm5vZGUpKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiB2bm9kZS5pbml0KCk7XG4gICAgICAgICAgICAgICAgfSBlbHNlIGlmIChpc1ZUZXh0KHZub2RlKSkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gZG9jLmNyZWF0ZVRleHROb2RlKHZub2RlLnRleHQpO1xuICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoIWlzVk5vZGUodm5vZGUpKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmICh3YXJuKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICB3YXJuKFwiSXRlbSBpcyBub3QgYSB2YWxpZCB2aXJ0dWFsIGRvbSBub2RlXCIsIHZub2RlKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICByZXR1cm4gbnVsbDtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICB2YXIgbm9kZSA9IHZub2RlLm5hbWVzcGFjZSA9PT0gbnVsbCA/IGRvYy5jcmVhdGVFbGVtZW50KHZub2RlLnRhZ05hbWUpIDogZG9jLmNyZWF0ZUVsZW1lbnROUyh2bm9kZS5uYW1lc3BhY2UsIHZub2RlLnRhZ05hbWUpO1xuXG4gICAgICAgICAgICAgICAgdmFyIHByb3BzID0gdm5vZGUucHJvcGVydGllcztcbiAgICAgICAgICAgICAgICBhcHBseVByb3BlcnRpZXMobm9kZSwgcHJvcHMpO1xuXG4gICAgICAgICAgICAgICAgdmFyIGNoaWxkcmVuID0gdm5vZGUuY2hpbGRyZW47XG5cbiAgICAgICAgICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IGNoaWxkcmVuLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciBjaGlsZE5vZGUgPSBjcmVhdGVFbGVtZW50KGNoaWxkcmVuW2ldLCBvcHRzKTtcbiAgICAgICAgICAgICAgICAgICAgaWYgKGNoaWxkTm9kZSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgbm9kZS5hcHBlbmRDaGlsZChjaGlsZE5vZGUpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgcmV0dXJuIG5vZGU7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0sIHsgXCIuLi92bm9kZS9oYW5kbGUtdGh1bmsuanNcIjogMjQsIFwiLi4vdm5vZGUvaXMtdm5vZGUuanNcIjogMjcsIFwiLi4vdm5vZGUvaXMtdnRleHQuanNcIjogMjgsIFwiLi4vdm5vZGUvaXMtd2lkZ2V0LmpzXCI6IDI5LCBcIi4vYXBwbHktcHJvcGVydGllc1wiOiAxNCwgXCJnbG9iYWwvZG9jdW1lbnRcIjogMTAgfV0sIDE2OiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge1xuICAgICAgICAgICAgLy8gTWFwcyBhIHZpcnR1YWwgRE9NIHRyZWUgb250byBhIHJlYWwgRE9NIHRyZWUgaW4gYW4gZWZmaWNpZW50IG1hbm5lci5cbiAgICAgICAgICAgIC8vIFdlIGRvbid0IHdhbnQgdG8gcmVhZCBhbGwgb2YgdGhlIERPTSBub2RlcyBpbiB0aGUgdHJlZSBzbyB3ZSB1c2VcbiAgICAgICAgICAgIC8vIHRoZSBpbi1vcmRlciB0cmVlIGluZGV4aW5nIHRvIGVsaW1pbmF0ZSByZWN1cnNpb24gZG93biBjZXJ0YWluIGJyYW5jaGVzLlxuICAgICAgICAgICAgLy8gV2Ugb25seSByZWN1cnNlIGludG8gYSBET00gbm9kZSBpZiB3ZSBrbm93IHRoYXQgaXQgY29udGFpbnMgYSBjaGlsZCBvZlxuICAgICAgICAgICAgLy8gaW50ZXJlc3QuXG5cbiAgICAgICAgICAgIHZhciBub0NoaWxkID0ge307XG5cbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gZG9tSW5kZXg7XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIGRvbUluZGV4KHJvb3ROb2RlLCB0cmVlLCBpbmRpY2VzLCBub2Rlcykge1xuICAgICAgICAgICAgICAgIGlmICghaW5kaWNlcyB8fCBpbmRpY2VzLmxlbmd0aCA9PT0gMCkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4ge307XG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgaW5kaWNlcy5zb3J0KGFzY2VuZGluZyk7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiByZWN1cnNlKHJvb3ROb2RlLCB0cmVlLCBpbmRpY2VzLCBub2RlcywgMCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBmdW5jdGlvbiByZWN1cnNlKHJvb3ROb2RlLCB0cmVlLCBpbmRpY2VzLCBub2Rlcywgcm9vdEluZGV4KSB7XG4gICAgICAgICAgICAgICAgbm9kZXMgPSBub2RlcyB8fCB7fTtcblxuICAgICAgICAgICAgICAgIGlmIChyb290Tm9kZSkge1xuICAgICAgICAgICAgICAgICAgICBpZiAoaW5kZXhJblJhbmdlKGluZGljZXMsIHJvb3RJbmRleCwgcm9vdEluZGV4KSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgbm9kZXNbcm9vdEluZGV4XSA9IHJvb3ROb2RlO1xuICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgdmFyIHZDaGlsZHJlbiA9IHRyZWUuY2hpbGRyZW47XG5cbiAgICAgICAgICAgICAgICAgICAgaWYgKHZDaGlsZHJlbikge1xuXG4gICAgICAgICAgICAgICAgICAgICAgICB2YXIgY2hpbGROb2RlcyA9IHJvb3ROb2RlLmNoaWxkTm9kZXM7XG5cbiAgICAgICAgICAgICAgICAgICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgdHJlZS5jaGlsZHJlbi5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJvb3RJbmRleCArPSAxO1xuXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdmFyIHZDaGlsZCA9IHZDaGlsZHJlbltpXSB8fCBub0NoaWxkO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZhciBuZXh0SW5kZXggPSByb290SW5kZXggKyAodkNoaWxkLmNvdW50IHx8IDApO1xuXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gc2tpcCByZWN1cnNpb24gZG93biB0aGUgdHJlZSBpZiB0aGVyZSBhcmUgbm8gbm9kZXMgZG93biBoZXJlXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGluZGV4SW5SYW5nZShpbmRpY2VzLCByb290SW5kZXgsIG5leHRJbmRleCkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmVjdXJzZShjaGlsZE5vZGVzW2ldLCB2Q2hpbGQsIGluZGljZXMsIG5vZGVzLCByb290SW5kZXgpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJvb3RJbmRleCA9IG5leHRJbmRleDtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHJldHVybiBub2RlcztcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgLy8gQmluYXJ5IHNlYXJjaCBmb3IgYW4gaW5kZXggaW4gdGhlIGludGVydmFsIFtsZWZ0LCByaWdodF1cbiAgICAgICAgICAgIGZ1bmN0aW9uIGluZGV4SW5SYW5nZShpbmRpY2VzLCBsZWZ0LCByaWdodCkge1xuICAgICAgICAgICAgICAgIGlmIChpbmRpY2VzLmxlbmd0aCA9PT0gMCkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgdmFyIG1pbkluZGV4ID0gMDtcbiAgICAgICAgICAgICAgICB2YXIgbWF4SW5kZXggPSBpbmRpY2VzLmxlbmd0aCAtIDE7XG4gICAgICAgICAgICAgICAgdmFyIGN1cnJlbnRJbmRleDtcbiAgICAgICAgICAgICAgICB2YXIgY3VycmVudEl0ZW07XG5cbiAgICAgICAgICAgICAgICB3aGlsZSAobWluSW5kZXggPD0gbWF4SW5kZXgpIHtcbiAgICAgICAgICAgICAgICAgICAgY3VycmVudEluZGV4ID0gKG1heEluZGV4ICsgbWluSW5kZXgpIC8gMiA+PiAwO1xuICAgICAgICAgICAgICAgICAgICBjdXJyZW50SXRlbSA9IGluZGljZXNbY3VycmVudEluZGV4XTtcblxuICAgICAgICAgICAgICAgICAgICBpZiAobWluSW5kZXggPT09IG1heEluZGV4KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gY3VycmVudEl0ZW0gPj0gbGVmdCAmJiBjdXJyZW50SXRlbSA8PSByaWdodDtcbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIGlmIChjdXJyZW50SXRlbSA8IGxlZnQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIG1pbkluZGV4ID0gY3VycmVudEluZGV4ICsgMTtcbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIGlmIChjdXJyZW50SXRlbSA+IHJpZ2h0KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBtYXhJbmRleCA9IGN1cnJlbnRJbmRleCAtIDE7XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZnVuY3Rpb24gYXNjZW5kaW5nKGEsIGIpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gYSA+IGIgPyAxIDogLTE7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0sIHt9XSwgMTc6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICB2YXIgYXBwbHlQcm9wZXJ0aWVzID0gcmVxdWlyZShcIi4vYXBwbHktcHJvcGVydGllc1wiKTtcblxuICAgICAgICAgICAgdmFyIGlzV2lkZ2V0ID0gcmVxdWlyZShcIi4uL3Zub2RlL2lzLXdpZGdldC5qc1wiKTtcbiAgICAgICAgICAgIHZhciBWUGF0Y2ggPSByZXF1aXJlKFwiLi4vdm5vZGUvdnBhdGNoLmpzXCIpO1xuXG4gICAgICAgICAgICB2YXIgdXBkYXRlV2lkZ2V0ID0gcmVxdWlyZShcIi4vdXBkYXRlLXdpZGdldFwiKTtcblxuICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBhcHBseVBhdGNoO1xuXG4gICAgICAgICAgICBmdW5jdGlvbiBhcHBseVBhdGNoKHZwYXRjaCwgZG9tTm9kZSwgcmVuZGVyT3B0aW9ucykge1xuICAgICAgICAgICAgICAgIHZhciB0eXBlID0gdnBhdGNoLnR5cGU7XG4gICAgICAgICAgICAgICAgdmFyIHZOb2RlID0gdnBhdGNoLnZOb2RlO1xuICAgICAgICAgICAgICAgIHZhciBwYXRjaCA9IHZwYXRjaC5wYXRjaDtcblxuICAgICAgICAgICAgICAgIHN3aXRjaCAodHlwZSkge1xuICAgICAgICAgICAgICAgICAgICBjYXNlIFZQYXRjaC5SRU1PVkU6XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gcmVtb3ZlTm9kZShkb21Ob2RlLCB2Tm9kZSk7XG4gICAgICAgICAgICAgICAgICAgIGNhc2UgVlBhdGNoLklOU0VSVDpcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBpbnNlcnROb2RlKGRvbU5vZGUsIHBhdGNoLCByZW5kZXJPcHRpb25zKTtcbiAgICAgICAgICAgICAgICAgICAgY2FzZSBWUGF0Y2guVlRFWFQ6XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gc3RyaW5nUGF0Y2goZG9tTm9kZSwgdk5vZGUsIHBhdGNoLCByZW5kZXJPcHRpb25zKTtcbiAgICAgICAgICAgICAgICAgICAgY2FzZSBWUGF0Y2guV0lER0VUOlxuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHdpZGdldFBhdGNoKGRvbU5vZGUsIHZOb2RlLCBwYXRjaCwgcmVuZGVyT3B0aW9ucyk7XG4gICAgICAgICAgICAgICAgICAgIGNhc2UgVlBhdGNoLlZOT0RFOlxuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHZOb2RlUGF0Y2goZG9tTm9kZSwgdk5vZGUsIHBhdGNoLCByZW5kZXJPcHRpb25zKTtcbiAgICAgICAgICAgICAgICAgICAgY2FzZSBWUGF0Y2guT1JERVI6XG4gICAgICAgICAgICAgICAgICAgICAgICByZW9yZGVyQ2hpbGRyZW4oZG9tTm9kZSwgcGF0Y2gpO1xuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGRvbU5vZGU7XG4gICAgICAgICAgICAgICAgICAgIGNhc2UgVlBhdGNoLlBST1BTOlxuICAgICAgICAgICAgICAgICAgICAgICAgYXBwbHlQcm9wZXJ0aWVzKGRvbU5vZGUsIHBhdGNoLCB2Tm9kZS5wcm9wZXJ0aWVzKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBkb21Ob2RlO1xuICAgICAgICAgICAgICAgICAgICBjYXNlIFZQYXRjaC5USFVOSzpcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiByZXBsYWNlUm9vdChkb21Ob2RlLCByZW5kZXJPcHRpb25zLnBhdGNoKGRvbU5vZGUsIHBhdGNoLCByZW5kZXJPcHRpb25zKSk7XG4gICAgICAgICAgICAgICAgICAgIGRlZmF1bHQ6XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gZG9tTm9kZTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIHJlbW92ZU5vZGUoZG9tTm9kZSwgdk5vZGUpIHtcbiAgICAgICAgICAgICAgICB2YXIgcGFyZW50Tm9kZSA9IGRvbU5vZGUucGFyZW50Tm9kZTtcblxuICAgICAgICAgICAgICAgIGlmIChwYXJlbnROb2RlKSB7XG4gICAgICAgICAgICAgICAgICAgIHBhcmVudE5vZGUucmVtb3ZlQ2hpbGQoZG9tTm9kZSk7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgZGVzdHJveVdpZGdldChkb21Ob2RlLCB2Tm9kZSk7XG5cbiAgICAgICAgICAgICAgICByZXR1cm4gbnVsbDtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZnVuY3Rpb24gaW5zZXJ0Tm9kZShwYXJlbnROb2RlLCB2Tm9kZSwgcmVuZGVyT3B0aW9ucykge1xuICAgICAgICAgICAgICAgIHZhciBuZXdOb2RlID0gcmVuZGVyT3B0aW9ucy5yZW5kZXIodk5vZGUsIHJlbmRlck9wdGlvbnMpO1xuXG4gICAgICAgICAgICAgICAgaWYgKHBhcmVudE5vZGUpIHtcbiAgICAgICAgICAgICAgICAgICAgcGFyZW50Tm9kZS5hcHBlbmRDaGlsZChuZXdOb2RlKTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICByZXR1cm4gcGFyZW50Tm9kZTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZnVuY3Rpb24gc3RyaW5nUGF0Y2goZG9tTm9kZSwgbGVmdFZOb2RlLCB2VGV4dCwgcmVuZGVyT3B0aW9ucykge1xuICAgICAgICAgICAgICAgIHZhciBuZXdOb2RlO1xuXG4gICAgICAgICAgICAgICAgaWYgKGRvbU5vZGUubm9kZVR5cGUgPT09IDMpIHtcbiAgICAgICAgICAgICAgICAgICAgZG9tTm9kZS5yZXBsYWNlRGF0YSgwLCBkb21Ob2RlLmxlbmd0aCwgdlRleHQudGV4dCk7XG4gICAgICAgICAgICAgICAgICAgIG5ld05vZGUgPSBkb21Ob2RlO1xuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciBwYXJlbnROb2RlID0gZG9tTm9kZS5wYXJlbnROb2RlO1xuICAgICAgICAgICAgICAgICAgICBuZXdOb2RlID0gcmVuZGVyT3B0aW9ucy5yZW5kZXIodlRleHQsIHJlbmRlck9wdGlvbnMpO1xuXG4gICAgICAgICAgICAgICAgICAgIGlmIChwYXJlbnROb2RlICYmIG5ld05vZGUgIT09IGRvbU5vZGUpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHBhcmVudE5vZGUucmVwbGFjZUNoaWxkKG5ld05vZGUsIGRvbU5vZGUpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgcmV0dXJuIG5ld05vZGU7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIHdpZGdldFBhdGNoKGRvbU5vZGUsIGxlZnRWTm9kZSwgd2lkZ2V0LCByZW5kZXJPcHRpb25zKSB7XG4gICAgICAgICAgICAgICAgdmFyIHVwZGF0aW5nID0gdXBkYXRlV2lkZ2V0KGxlZnRWTm9kZSwgd2lkZ2V0KTtcbiAgICAgICAgICAgICAgICB2YXIgbmV3Tm9kZTtcblxuICAgICAgICAgICAgICAgIGlmICh1cGRhdGluZykge1xuICAgICAgICAgICAgICAgICAgICBuZXdOb2RlID0gd2lkZ2V0LnVwZGF0ZShsZWZ0Vk5vZGUsIGRvbU5vZGUpIHx8IGRvbU5vZGU7XG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgbmV3Tm9kZSA9IHJlbmRlck9wdGlvbnMucmVuZGVyKHdpZGdldCwgcmVuZGVyT3B0aW9ucyk7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgdmFyIHBhcmVudE5vZGUgPSBkb21Ob2RlLnBhcmVudE5vZGU7XG5cbiAgICAgICAgICAgICAgICBpZiAocGFyZW50Tm9kZSAmJiBuZXdOb2RlICE9PSBkb21Ob2RlKSB7XG4gICAgICAgICAgICAgICAgICAgIHBhcmVudE5vZGUucmVwbGFjZUNoaWxkKG5ld05vZGUsIGRvbU5vZGUpO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIGlmICghdXBkYXRpbmcpIHtcbiAgICAgICAgICAgICAgICAgICAgZGVzdHJveVdpZGdldChkb21Ob2RlLCBsZWZ0Vk5vZGUpO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHJldHVybiBuZXdOb2RlO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBmdW5jdGlvbiB2Tm9kZVBhdGNoKGRvbU5vZGUsIGxlZnRWTm9kZSwgdk5vZGUsIHJlbmRlck9wdGlvbnMpIHtcbiAgICAgICAgICAgICAgICB2YXIgcGFyZW50Tm9kZSA9IGRvbU5vZGUucGFyZW50Tm9kZTtcbiAgICAgICAgICAgICAgICB2YXIgbmV3Tm9kZSA9IHJlbmRlck9wdGlvbnMucmVuZGVyKHZOb2RlLCByZW5kZXJPcHRpb25zKTtcblxuICAgICAgICAgICAgICAgIGlmIChwYXJlbnROb2RlICYmIG5ld05vZGUgIT09IGRvbU5vZGUpIHtcbiAgICAgICAgICAgICAgICAgICAgcGFyZW50Tm9kZS5yZXBsYWNlQ2hpbGQobmV3Tm9kZSwgZG9tTm9kZSk7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgcmV0dXJuIG5ld05vZGU7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIGRlc3Ryb3lXaWRnZXQoZG9tTm9kZSwgdykge1xuICAgICAgICAgICAgICAgIGlmICh0eXBlb2Ygdy5kZXN0cm95ID09PSBcImZ1bmN0aW9uXCIgJiYgaXNXaWRnZXQodykpIHtcbiAgICAgICAgICAgICAgICAgICAgdy5kZXN0cm95KGRvbU5vZGUpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZnVuY3Rpb24gcmVvcmRlckNoaWxkcmVuKGRvbU5vZGUsIG1vdmVzKSB7XG4gICAgICAgICAgICAgICAgdmFyIGNoaWxkTm9kZXMgPSBkb21Ob2RlLmNoaWxkTm9kZXM7XG4gICAgICAgICAgICAgICAgdmFyIGtleU1hcCA9IHt9O1xuICAgICAgICAgICAgICAgIHZhciBub2RlO1xuICAgICAgICAgICAgICAgIHZhciByZW1vdmU7XG4gICAgICAgICAgICAgICAgdmFyIGluc2VydDtcblxuICAgICAgICAgICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgbW92ZXMucmVtb3Zlcy5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgICAgICAgICByZW1vdmUgPSBtb3Zlcy5yZW1vdmVzW2ldO1xuICAgICAgICAgICAgICAgICAgICBub2RlID0gY2hpbGROb2Rlc1tyZW1vdmUuZnJvbV07XG4gICAgICAgICAgICAgICAgICAgIGlmIChyZW1vdmUua2V5KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBrZXlNYXBbcmVtb3ZlLmtleV0gPSBub2RlO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIGRvbU5vZGUucmVtb3ZlQ2hpbGQobm9kZSk7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgdmFyIGxlbmd0aCA9IGNoaWxkTm9kZXMubGVuZ3RoO1xuICAgICAgICAgICAgICAgIGZvciAodmFyIGogPSAwOyBqIDwgbW92ZXMuaW5zZXJ0cy5sZW5ndGg7IGorKykge1xuICAgICAgICAgICAgICAgICAgICBpbnNlcnQgPSBtb3Zlcy5pbnNlcnRzW2pdO1xuICAgICAgICAgICAgICAgICAgICBub2RlID0ga2V5TWFwW2luc2VydC5rZXldO1xuICAgICAgICAgICAgICAgICAgICAvLyB0aGlzIGlzIHRoZSB3ZWlyZGVzdCBidWcgaSd2ZSBldmVyIHNlZW4gaW4gd2Via2l0XG4gICAgICAgICAgICAgICAgICAgIGRvbU5vZGUuaW5zZXJ0QmVmb3JlKG5vZGUsIGluc2VydC50byA+PSBsZW5ndGgrKyA/IG51bGwgOiBjaGlsZE5vZGVzW2luc2VydC50b10pO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZnVuY3Rpb24gcmVwbGFjZVJvb3Qob2xkUm9vdCwgbmV3Um9vdCkge1xuICAgICAgICAgICAgICAgIGlmIChvbGRSb290ICYmIG5ld1Jvb3QgJiYgb2xkUm9vdCAhPT0gbmV3Um9vdCAmJiBvbGRSb290LnBhcmVudE5vZGUpIHtcbiAgICAgICAgICAgICAgICAgICAgb2xkUm9vdC5wYXJlbnROb2RlLnJlcGxhY2VDaGlsZChuZXdSb290LCBvbGRSb290KTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICByZXR1cm4gbmV3Um9vdDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSwgeyBcIi4uL3Zub2RlL2lzLXdpZGdldC5qc1wiOiAyOSwgXCIuLi92bm9kZS92cGF0Y2guanNcIjogMzIsIFwiLi9hcHBseS1wcm9wZXJ0aWVzXCI6IDE0LCBcIi4vdXBkYXRlLXdpZGdldFwiOiAxOSB9XSwgMTg6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICB2YXIgZG9jdW1lbnQgPSByZXF1aXJlKFwiZ2xvYmFsL2RvY3VtZW50XCIpO1xuICAgICAgICAgICAgdmFyIGlzQXJyYXkgPSByZXF1aXJlKFwieC1pcy1hcnJheVwiKTtcblxuICAgICAgICAgICAgdmFyIHJlbmRlciA9IHJlcXVpcmUoXCIuL2NyZWF0ZS1lbGVtZW50XCIpO1xuICAgICAgICAgICAgdmFyIGRvbUluZGV4ID0gcmVxdWlyZShcIi4vZG9tLWluZGV4XCIpO1xuICAgICAgICAgICAgdmFyIHBhdGNoT3AgPSByZXF1aXJlKFwiLi9wYXRjaC1vcFwiKTtcbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gcGF0Y2g7XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIHBhdGNoKHJvb3ROb2RlLCBwYXRjaGVzLCByZW5kZXJPcHRpb25zKSB7XG4gICAgICAgICAgICAgICAgcmVuZGVyT3B0aW9ucyA9IHJlbmRlck9wdGlvbnMgfHwge307XG4gICAgICAgICAgICAgICAgcmVuZGVyT3B0aW9ucy5wYXRjaCA9IHJlbmRlck9wdGlvbnMucGF0Y2ggJiYgcmVuZGVyT3B0aW9ucy5wYXRjaCAhPT0gcGF0Y2ggPyByZW5kZXJPcHRpb25zLnBhdGNoIDogcGF0Y2hSZWN1cnNpdmU7XG4gICAgICAgICAgICAgICAgcmVuZGVyT3B0aW9ucy5yZW5kZXIgPSByZW5kZXJPcHRpb25zLnJlbmRlciB8fCByZW5kZXI7XG5cbiAgICAgICAgICAgICAgICByZXR1cm4gcmVuZGVyT3B0aW9ucy5wYXRjaChyb290Tm9kZSwgcGF0Y2hlcywgcmVuZGVyT3B0aW9ucyk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIHBhdGNoUmVjdXJzaXZlKHJvb3ROb2RlLCBwYXRjaGVzLCByZW5kZXJPcHRpb25zKSB7XG4gICAgICAgICAgICAgICAgdmFyIGluZGljZXMgPSBwYXRjaEluZGljZXMocGF0Y2hlcyk7XG5cbiAgICAgICAgICAgICAgICBpZiAoaW5kaWNlcy5sZW5ndGggPT09IDApIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHJvb3ROb2RlO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHZhciBpbmRleCA9IGRvbUluZGV4KHJvb3ROb2RlLCBwYXRjaGVzLmEsIGluZGljZXMpO1xuICAgICAgICAgICAgICAgIHZhciBvd25lckRvY3VtZW50ID0gcm9vdE5vZGUub3duZXJEb2N1bWVudDtcblxuICAgICAgICAgICAgICAgIGlmICghcmVuZGVyT3B0aW9ucy5kb2N1bWVudCAmJiBvd25lckRvY3VtZW50ICE9PSBkb2N1bWVudCkge1xuICAgICAgICAgICAgICAgICAgICByZW5kZXJPcHRpb25zLmRvY3VtZW50ID0gb3duZXJEb2N1bWVudDtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IGluZGljZXMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgICAgICAgICAgdmFyIG5vZGVJbmRleCA9IGluZGljZXNbaV07XG4gICAgICAgICAgICAgICAgICAgIHJvb3ROb2RlID0gYXBwbHlQYXRjaChyb290Tm9kZSwgaW5kZXhbbm9kZUluZGV4XSwgcGF0Y2hlc1tub2RlSW5kZXhdLCByZW5kZXJPcHRpb25zKTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICByZXR1cm4gcm9vdE5vZGU7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIGFwcGx5UGF0Y2gocm9vdE5vZGUsIGRvbU5vZGUsIHBhdGNoTGlzdCwgcmVuZGVyT3B0aW9ucykge1xuICAgICAgICAgICAgICAgIGlmICghZG9tTm9kZSkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gcm9vdE5vZGU7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgdmFyIG5ld05vZGU7XG5cbiAgICAgICAgICAgICAgICBpZiAoaXNBcnJheShwYXRjaExpc3QpKSB7XG4gICAgICAgICAgICAgICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgcGF0Y2hMaXN0Lmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBuZXdOb2RlID0gcGF0Y2hPcChwYXRjaExpc3RbaV0sIGRvbU5vZGUsIHJlbmRlck9wdGlvbnMpO1xuXG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoZG9tTm9kZSA9PT0gcm9vdE5vZGUpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICByb290Tm9kZSA9IG5ld05vZGU7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICBuZXdOb2RlID0gcGF0Y2hPcChwYXRjaExpc3QsIGRvbU5vZGUsIHJlbmRlck9wdGlvbnMpO1xuXG4gICAgICAgICAgICAgICAgICAgIGlmIChkb21Ob2RlID09PSByb290Tm9kZSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgcm9vdE5vZGUgPSBuZXdOb2RlO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgcmV0dXJuIHJvb3ROb2RlO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBmdW5jdGlvbiBwYXRjaEluZGljZXMocGF0Y2hlcykge1xuICAgICAgICAgICAgICAgIHZhciBpbmRpY2VzID0gW107XG5cbiAgICAgICAgICAgICAgICBmb3IgKHZhciBrZXkgaW4gcGF0Y2hlcykge1xuICAgICAgICAgICAgICAgICAgICBpZiAoa2V5ICE9PSBcImFcIikge1xuICAgICAgICAgICAgICAgICAgICAgICAgaW5kaWNlcy5wdXNoKE51bWJlcihrZXkpKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHJldHVybiBpbmRpY2VzO1xuICAgICAgICAgICAgfVxuICAgICAgICB9LCB7IFwiLi9jcmVhdGUtZWxlbWVudFwiOiAxNSwgXCIuL2RvbS1pbmRleFwiOiAxNiwgXCIuL3BhdGNoLW9wXCI6IDE3LCBcImdsb2JhbC9kb2N1bWVudFwiOiAxMCwgXCJ4LWlzLWFycmF5XCI6IDEyIH1dLCAxOTogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHtcbiAgICAgICAgICAgIHZhciBpc1dpZGdldCA9IHJlcXVpcmUoXCIuLi92bm9kZS9pcy13aWRnZXQuanNcIik7XG5cbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gdXBkYXRlV2lkZ2V0O1xuXG4gICAgICAgICAgICBmdW5jdGlvbiB1cGRhdGVXaWRnZXQoYSwgYikge1xuICAgICAgICAgICAgICAgIGlmIChpc1dpZGdldChhKSAmJiBpc1dpZGdldChiKSkge1xuICAgICAgICAgICAgICAgICAgICBpZiAoXCJuYW1lXCIgaW4gYSAmJiBcIm5hbWVcIiBpbiBiKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gYS5pZCA9PT0gYi5pZDtcbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBhLmluaXQgPT09IGIuaW5pdDtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSwgeyBcIi4uL3Zub2RlL2lzLXdpZGdldC5qc1wiOiAyOSB9XSwgMjA6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICBcInVzZSBzdHJpY3RcIjtcblxuICAgICAgICAgICAgdmFyIEV2U3RvcmUgPSByZXF1aXJlKFwiZXYtc3RvcmVcIik7XG5cbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gRXZIb29rO1xuXG4gICAgICAgICAgICBmdW5jdGlvbiBFdkhvb2sodmFsdWUpIHtcbiAgICAgICAgICAgICAgICBpZiAoISh0aGlzIGluc3RhbmNlb2YgRXZIb29rKSkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gbmV3IEV2SG9vayh2YWx1ZSk7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgdGhpcy52YWx1ZSA9IHZhbHVlO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBFdkhvb2sucHJvdG90eXBlLmhvb2sgPSBmdW5jdGlvbiAobm9kZSwgcHJvcGVydHlOYW1lKSB7XG4gICAgICAgICAgICAgICAgdmFyIGVzID0gRXZTdG9yZShub2RlKTtcbiAgICAgICAgICAgICAgICB2YXIgcHJvcE5hbWUgPSBwcm9wZXJ0eU5hbWUuc3Vic3RyKDMpO1xuXG4gICAgICAgICAgICAgICAgZXNbcHJvcE5hbWVdID0gdGhpcy52YWx1ZTtcbiAgICAgICAgICAgIH07XG5cbiAgICAgICAgICAgIEV2SG9vay5wcm90b3R5cGUudW5ob29rID0gZnVuY3Rpb24gKG5vZGUsIHByb3BlcnR5TmFtZSkge1xuICAgICAgICAgICAgICAgIHZhciBlcyA9IEV2U3RvcmUobm9kZSk7XG4gICAgICAgICAgICAgICAgdmFyIHByb3BOYW1lID0gcHJvcGVydHlOYW1lLnN1YnN0cigzKTtcblxuICAgICAgICAgICAgICAgIGVzW3Byb3BOYW1lXSA9IHVuZGVmaW5lZDtcbiAgICAgICAgICAgIH07XG4gICAgICAgIH0sIHsgXCJldi1zdG9yZVwiOiA3IH1dLCAyMTogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHtcbiAgICAgICAgICAgIFwidXNlIHN0cmljdFwiO1xuXG4gICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IFNvZnRTZXRIb29rO1xuXG4gICAgICAgICAgICBmdW5jdGlvbiBTb2Z0U2V0SG9vayh2YWx1ZSkge1xuICAgICAgICAgICAgICAgIGlmICghKHRoaXMgaW5zdGFuY2VvZiBTb2Z0U2V0SG9vaykpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIG5ldyBTb2Z0U2V0SG9vayh2YWx1ZSk7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgdGhpcy52YWx1ZSA9IHZhbHVlO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBTb2Z0U2V0SG9vay5wcm90b3R5cGUuaG9vayA9IGZ1bmN0aW9uIChub2RlLCBwcm9wZXJ0eU5hbWUpIHtcbiAgICAgICAgICAgICAgICBpZiAobm9kZVtwcm9wZXJ0eU5hbWVdICE9PSB0aGlzLnZhbHVlKSB7XG4gICAgICAgICAgICAgICAgICAgIG5vZGVbcHJvcGVydHlOYW1lXSA9IHRoaXMudmFsdWU7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfTtcbiAgICAgICAgfSwge31dLCAyMjogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHtcbiAgICAgICAgICAgIFwidXNlIHN0cmljdFwiO1xuXG4gICAgICAgICAgICB2YXIgaXNBcnJheSA9IHJlcXVpcmUoXCJ4LWlzLWFycmF5XCIpO1xuXG4gICAgICAgICAgICB2YXIgVk5vZGUgPSByZXF1aXJlKFwiLi4vdm5vZGUvdm5vZGUuanNcIik7XG4gICAgICAgICAgICB2YXIgVlRleHQgPSByZXF1aXJlKFwiLi4vdm5vZGUvdnRleHQuanNcIik7XG4gICAgICAgICAgICB2YXIgaXNWTm9kZSA9IHJlcXVpcmUoXCIuLi92bm9kZS9pcy12bm9kZVwiKTtcbiAgICAgICAgICAgIHZhciBpc1ZUZXh0ID0gcmVxdWlyZShcIi4uL3Zub2RlL2lzLXZ0ZXh0XCIpO1xuICAgICAgICAgICAgdmFyIGlzV2lkZ2V0ID0gcmVxdWlyZShcIi4uL3Zub2RlL2lzLXdpZGdldFwiKTtcbiAgICAgICAgICAgIHZhciBpc0hvb2sgPSByZXF1aXJlKFwiLi4vdm5vZGUvaXMtdmhvb2tcIik7XG4gICAgICAgICAgICB2YXIgaXNWVGh1bmsgPSByZXF1aXJlKFwiLi4vdm5vZGUvaXMtdGh1bmtcIik7XG5cbiAgICAgICAgICAgIHZhciBwYXJzZVRhZyA9IHJlcXVpcmUoXCIuL3BhcnNlLXRhZy5qc1wiKTtcbiAgICAgICAgICAgIHZhciBzb2Z0U2V0SG9vayA9IHJlcXVpcmUoXCIuL2hvb2tzL3NvZnQtc2V0LWhvb2suanNcIik7XG4gICAgICAgICAgICB2YXIgZXZIb29rID0gcmVxdWlyZShcIi4vaG9va3MvZXYtaG9vay5qc1wiKTtcblxuICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBoO1xuXG4gICAgICAgICAgICBmdW5jdGlvbiBoKHRhZ05hbWUsIHByb3BlcnRpZXMsIGNoaWxkcmVuKSB7XG4gICAgICAgICAgICAgICAgdmFyIGNoaWxkTm9kZXMgPSBbXTtcbiAgICAgICAgICAgICAgICB2YXIgdGFnLCBwcm9wcywga2V5LCBuYW1lc3BhY2U7XG5cbiAgICAgICAgICAgICAgICBpZiAoIWNoaWxkcmVuICYmIGlzQ2hpbGRyZW4ocHJvcGVydGllcykpIHtcbiAgICAgICAgICAgICAgICAgICAgY2hpbGRyZW4gPSBwcm9wZXJ0aWVzO1xuICAgICAgICAgICAgICAgICAgICBwcm9wcyA9IHt9O1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHByb3BzID0gcHJvcHMgfHwgcHJvcGVydGllcyB8fCB7fTtcbiAgICAgICAgICAgICAgICB0YWcgPSBwYXJzZVRhZyh0YWdOYW1lLCBwcm9wcyk7XG5cbiAgICAgICAgICAgICAgICAvLyBzdXBwb3J0IGtleXNcbiAgICAgICAgICAgICAgICBpZiAocHJvcHMuaGFzT3duUHJvcGVydHkoXCJrZXlcIikpIHtcbiAgICAgICAgICAgICAgICAgICAga2V5ID0gcHJvcHMua2V5O1xuICAgICAgICAgICAgICAgICAgICBwcm9wcy5rZXkgPSB1bmRlZmluZWQ7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgLy8gc3VwcG9ydCBuYW1lc3BhY2VcbiAgICAgICAgICAgICAgICBpZiAocHJvcHMuaGFzT3duUHJvcGVydHkoXCJuYW1lc3BhY2VcIikpIHtcbiAgICAgICAgICAgICAgICAgICAgbmFtZXNwYWNlID0gcHJvcHMubmFtZXNwYWNlO1xuICAgICAgICAgICAgICAgICAgICBwcm9wcy5uYW1lc3BhY2UgPSB1bmRlZmluZWQ7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgLy8gZml4IGN1cnNvciBidWdcbiAgICAgICAgICAgICAgICBpZiAodGFnID09PSBcIklOUFVUXCIgJiYgIW5hbWVzcGFjZSAmJiBwcm9wcy5oYXNPd25Qcm9wZXJ0eShcInZhbHVlXCIpICYmIHByb3BzLnZhbHVlICE9PSB1bmRlZmluZWQgJiYgIWlzSG9vayhwcm9wcy52YWx1ZSkpIHtcbiAgICAgICAgICAgICAgICAgICAgcHJvcHMudmFsdWUgPSBzb2Z0U2V0SG9vayhwcm9wcy52YWx1ZSk7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgdHJhbnNmb3JtUHJvcGVydGllcyhwcm9wcyk7XG5cbiAgICAgICAgICAgICAgICBpZiAoY2hpbGRyZW4gIT09IHVuZGVmaW5lZCAmJiBjaGlsZHJlbiAhPT0gbnVsbCkge1xuICAgICAgICAgICAgICAgICAgICBhZGRDaGlsZChjaGlsZHJlbiwgY2hpbGROb2RlcywgdGFnLCBwcm9wcyk7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgcmV0dXJuIG5ldyBWTm9kZSh0YWcsIHByb3BzLCBjaGlsZE5vZGVzLCBrZXksIG5hbWVzcGFjZSk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIGFkZENoaWxkKGMsIGNoaWxkTm9kZXMsIHRhZywgcHJvcHMpIHtcbiAgICAgICAgICAgICAgICBpZiAodHlwZW9mIGMgPT09IFwic3RyaW5nXCIpIHtcbiAgICAgICAgICAgICAgICAgICAgY2hpbGROb2Rlcy5wdXNoKG5ldyBWVGV4dChjKSk7XG4gICAgICAgICAgICAgICAgfSBlbHNlIGlmICh0eXBlb2YgYyA9PT0gXCJudW1iZXJcIikge1xuICAgICAgICAgICAgICAgICAgICBjaGlsZE5vZGVzLnB1c2gobmV3IFZUZXh0KFN0cmluZyhjKSkpO1xuICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoaXNDaGlsZChjKSkge1xuICAgICAgICAgICAgICAgICAgICBjaGlsZE5vZGVzLnB1c2goYyk7XG4gICAgICAgICAgICAgICAgfSBlbHNlIGlmIChpc0FycmF5KGMpKSB7XG4gICAgICAgICAgICAgICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgYy5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgICAgICAgICAgICAgYWRkQ2hpbGQoY1tpXSwgY2hpbGROb2RlcywgdGFnLCBwcm9wcyk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKGMgPT09IG51bGwgfHwgYyA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICB0aHJvdyBVbmV4cGVjdGVkVmlydHVhbEVsZW1lbnQoe1xuICAgICAgICAgICAgICAgICAgICAgICAgZm9yZWlnbk9iamVjdDogYyxcbiAgICAgICAgICAgICAgICAgICAgICAgIHBhcmVudFZub2RlOiB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdGFnTmFtZTogdGFnLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHByb3BlcnRpZXM6IHByb3BzXG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZnVuY3Rpb24gdHJhbnNmb3JtUHJvcGVydGllcyhwcm9wcykge1xuICAgICAgICAgICAgICAgIGZvciAodmFyIHByb3BOYW1lIGluIHByb3BzKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmIChwcm9wcy5oYXNPd25Qcm9wZXJ0eShwcm9wTmFtZSkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHZhciB2YWx1ZSA9IHByb3BzW3Byb3BOYW1lXTtcblxuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGlzSG9vayh2YWx1ZSkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb250aW51ZTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHByb3BOYW1lLnN1YnN0cigwLCAzKSA9PT0gXCJldi1cIikge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIGFkZCBldi1mb28gc3VwcG9ydFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHByb3BzW3Byb3BOYW1lXSA9IGV2SG9vayh2YWx1ZSk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIGlzQ2hpbGQoeCkge1xuICAgICAgICAgICAgICAgIHJldHVybiBpc1ZOb2RlKHgpIHx8IGlzVlRleHQoeCkgfHwgaXNXaWRnZXQoeCkgfHwgaXNWVGh1bmsoeCk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIGlzQ2hpbGRyZW4oeCkge1xuICAgICAgICAgICAgICAgIHJldHVybiB0eXBlb2YgeCA9PT0gXCJzdHJpbmdcIiB8fCBpc0FycmF5KHgpIHx8IGlzQ2hpbGQoeCk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIFVuZXhwZWN0ZWRWaXJ0dWFsRWxlbWVudChkYXRhKSB7XG4gICAgICAgICAgICAgICAgdmFyIGVyciA9IG5ldyBFcnJvcigpO1xuXG4gICAgICAgICAgICAgICAgZXJyLnR5cGUgPSBcInZpcnR1YWwtaHlwZXJzY3JpcHQudW5leHBlY3RlZC52aXJ0dWFsLWVsZW1lbnRcIjtcbiAgICAgICAgICAgICAgICBlcnIubWVzc2FnZSA9IFwiVW5leHBlY3RlZCB2aXJ0dWFsIGNoaWxkIHBhc3NlZCB0byBoKCkuXFxuXCIgKyBcIkV4cGVjdGVkIGEgVk5vZGUgLyBWdGh1bmsgLyBWV2lkZ2V0IC8gc3RyaW5nIGJ1dDpcXG5cIiArIFwiZ290OlxcblwiICsgZXJyb3JTdHJpbmcoZGF0YS5mb3JlaWduT2JqZWN0KSArIFwiLlxcblwiICsgXCJUaGUgcGFyZW50IHZub2RlIGlzOlxcblwiICsgZXJyb3JTdHJpbmcoZGF0YS5wYXJlbnRWbm9kZSk7XG4gICAgICAgICAgICAgICAgXCJcXG5cIiArIFwiU3VnZ2VzdGVkIGZpeDogY2hhbmdlIHlvdXIgYGgoLi4uLCBbIC4uLiBdKWAgY2FsbHNpdGUuXCI7XG4gICAgICAgICAgICAgICAgZXJyLmZvcmVpZ25PYmplY3QgPSBkYXRhLmZvcmVpZ25PYmplY3Q7XG4gICAgICAgICAgICAgICAgZXJyLnBhcmVudFZub2RlID0gZGF0YS5wYXJlbnRWbm9kZTtcblxuICAgICAgICAgICAgICAgIHJldHVybiBlcnI7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIGVycm9yU3RyaW5nKG9iaikge1xuICAgICAgICAgICAgICAgIHRyeSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBKU09OLnN0cmluZ2lmeShvYmosIG51bGwsIFwiICAgIFwiKTtcbiAgICAgICAgICAgICAgICB9IGNhdGNoIChlKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBTdHJpbmcob2JqKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH0sIHsgXCIuLi92bm9kZS9pcy10aHVua1wiOiAyNSwgXCIuLi92bm9kZS9pcy12aG9va1wiOiAyNiwgXCIuLi92bm9kZS9pcy12bm9kZVwiOiAyNywgXCIuLi92bm9kZS9pcy12dGV4dFwiOiAyOCwgXCIuLi92bm9kZS9pcy13aWRnZXRcIjogMjksIFwiLi4vdm5vZGUvdm5vZGUuanNcIjogMzEsIFwiLi4vdm5vZGUvdnRleHQuanNcIjogMzMsIFwiLi9ob29rcy9ldi1ob29rLmpzXCI6IDIwLCBcIi4vaG9va3Mvc29mdC1zZXQtaG9vay5qc1wiOiAyMSwgXCIuL3BhcnNlLXRhZy5qc1wiOiAyMywgXCJ4LWlzLWFycmF5XCI6IDEyIH1dLCAyMzogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHtcbiAgICAgICAgICAgIFwidXNlIHN0cmljdFwiO1xuXG4gICAgICAgICAgICB2YXIgc3BsaXQgPSByZXF1aXJlKFwiYnJvd3Nlci1zcGxpdFwiKTtcblxuICAgICAgICAgICAgdmFyIGNsYXNzSWRTcGxpdCA9IC8oW1xcLiNdP1thLXpBLVowLTlcXHUwMDdGLVxcdUZGRkZfOi1dKykvO1xuICAgICAgICAgICAgdmFyIG5vdENsYXNzSWQgPSAvXlxcLnwjLztcblxuICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBwYXJzZVRhZztcblxuICAgICAgICAgICAgZnVuY3Rpb24gcGFyc2VUYWcodGFnLCBwcm9wcykge1xuICAgICAgICAgICAgICAgIGlmICghdGFnKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBcIkRJVlwiO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHZhciBub0lkID0gIXByb3BzLmhhc093blByb3BlcnR5KFwiaWRcIik7XG5cbiAgICAgICAgICAgICAgICB2YXIgdGFnUGFydHMgPSBzcGxpdCh0YWcsIGNsYXNzSWRTcGxpdCk7XG4gICAgICAgICAgICAgICAgdmFyIHRhZ05hbWUgPSBudWxsO1xuXG4gICAgICAgICAgICAgICAgaWYgKG5vdENsYXNzSWQudGVzdCh0YWdQYXJ0c1sxXSkpIHtcbiAgICAgICAgICAgICAgICAgICAgdGFnTmFtZSA9IFwiRElWXCI7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgdmFyIGNsYXNzZXMsIHBhcnQsIHR5cGUsIGk7XG5cbiAgICAgICAgICAgICAgICBmb3IgKGkgPSAwOyBpIDwgdGFnUGFydHMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgICAgICAgICAgcGFydCA9IHRhZ1BhcnRzW2ldO1xuXG4gICAgICAgICAgICAgICAgICAgIGlmICghcGFydCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgY29udGludWU7XG4gICAgICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgICAgICB0eXBlID0gcGFydC5jaGFyQXQoMCk7XG5cbiAgICAgICAgICAgICAgICAgICAgaWYgKCF0YWdOYW1lKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICB0YWdOYW1lID0gcGFydDtcbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIGlmICh0eXBlID09PSBcIi5cIikge1xuICAgICAgICAgICAgICAgICAgICAgICAgY2xhc3NlcyA9IGNsYXNzZXMgfHwgW107XG4gICAgICAgICAgICAgICAgICAgICAgICBjbGFzc2VzLnB1c2gocGFydC5zdWJzdHJpbmcoMSwgcGFydC5sZW5ndGgpKTtcbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIGlmICh0eXBlID09PSBcIiNcIiAmJiBub0lkKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBwcm9wcy5pZCA9IHBhcnQuc3Vic3RyaW5nKDEsIHBhcnQubGVuZ3RoKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIGlmIChjbGFzc2VzKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmIChwcm9wcy5jbGFzc05hbWUpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGNsYXNzZXMucHVzaChwcm9wcy5jbGFzc05hbWUpO1xuICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgcHJvcHMuY2xhc3NOYW1lID0gY2xhc3Nlcy5qb2luKFwiIFwiKTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICByZXR1cm4gcHJvcHMubmFtZXNwYWNlID8gdGFnTmFtZSA6IHRhZ05hbWUudG9VcHBlckNhc2UoKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSwgeyBcImJyb3dzZXItc3BsaXRcIjogNSB9XSwgMjQ6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICB2YXIgaXNWTm9kZSA9IHJlcXVpcmUoXCIuL2lzLXZub2RlXCIpO1xuICAgICAgICAgICAgdmFyIGlzVlRleHQgPSByZXF1aXJlKFwiLi9pcy12dGV4dFwiKTtcbiAgICAgICAgICAgIHZhciBpc1dpZGdldCA9IHJlcXVpcmUoXCIuL2lzLXdpZGdldFwiKTtcbiAgICAgICAgICAgIHZhciBpc1RodW5rID0gcmVxdWlyZShcIi4vaXMtdGh1bmtcIik7XG5cbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gaGFuZGxlVGh1bms7XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIGhhbmRsZVRodW5rKGEsIGIpIHtcbiAgICAgICAgICAgICAgICB2YXIgcmVuZGVyZWRBID0gYTtcbiAgICAgICAgICAgICAgICB2YXIgcmVuZGVyZWRCID0gYjtcblxuICAgICAgICAgICAgICAgIGlmIChpc1RodW5rKGIpKSB7XG4gICAgICAgICAgICAgICAgICAgIHJlbmRlcmVkQiA9IHJlbmRlclRodW5rKGIsIGEpO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIGlmIChpc1RodW5rKGEpKSB7XG4gICAgICAgICAgICAgICAgICAgIHJlbmRlcmVkQSA9IHJlbmRlclRodW5rKGEsIG51bGwpO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHJldHVybiB7XG4gICAgICAgICAgICAgICAgICAgIGE6IHJlbmRlcmVkQSxcbiAgICAgICAgICAgICAgICAgICAgYjogcmVuZGVyZWRCXG4gICAgICAgICAgICAgICAgfTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZnVuY3Rpb24gcmVuZGVyVGh1bmsodGh1bmssIHByZXZpb3VzKSB7XG4gICAgICAgICAgICAgICAgdmFyIHJlbmRlcmVkVGh1bmsgPSB0aHVuay52bm9kZTtcblxuICAgICAgICAgICAgICAgIGlmICghcmVuZGVyZWRUaHVuaykge1xuICAgICAgICAgICAgICAgICAgICByZW5kZXJlZFRodW5rID0gdGh1bmsudm5vZGUgPSB0aHVuay5yZW5kZXIocHJldmlvdXMpO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIGlmICghKGlzVk5vZGUocmVuZGVyZWRUaHVuaykgfHwgaXNWVGV4dChyZW5kZXJlZFRodW5rKSB8fCBpc1dpZGdldChyZW5kZXJlZFRodW5rKSkpIHtcbiAgICAgICAgICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKFwidGh1bmsgZGlkIG5vdCByZXR1cm4gYSB2YWxpZCBub2RlXCIpO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHJldHVybiByZW5kZXJlZFRodW5rO1xuICAgICAgICAgICAgfVxuICAgICAgICB9LCB7IFwiLi9pcy10aHVua1wiOiAyNSwgXCIuL2lzLXZub2RlXCI6IDI3LCBcIi4vaXMtdnRleHRcIjogMjgsIFwiLi9pcy13aWRnZXRcIjogMjkgfV0sIDI1OiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge1xuICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBpc1RodW5rO1xuXG4gICAgICAgICAgICBmdW5jdGlvbiBpc1RodW5rKHQpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gdCAmJiB0LnR5cGUgPT09IFwiVGh1bmtcIjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSwge31dLCAyNjogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHtcbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gaXNIb29rO1xuXG4gICAgICAgICAgICBmdW5jdGlvbiBpc0hvb2soaG9vaykge1xuICAgICAgICAgICAgICAgIHJldHVybiBob29rICYmICh0eXBlb2YgaG9vay5ob29rID09PSBcImZ1bmN0aW9uXCIgJiYgIWhvb2suaGFzT3duUHJvcGVydHkoXCJob29rXCIpIHx8IHR5cGVvZiBob29rLnVuaG9vayA9PT0gXCJmdW5jdGlvblwiICYmICFob29rLmhhc093blByb3BlcnR5KFwidW5ob29rXCIpKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSwge31dLCAyNzogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHtcbiAgICAgICAgICAgIHZhciB2ZXJzaW9uID0gcmVxdWlyZShcIi4vdmVyc2lvblwiKTtcblxuICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBpc1ZpcnR1YWxOb2RlO1xuXG4gICAgICAgICAgICBmdW5jdGlvbiBpc1ZpcnR1YWxOb2RlKHgpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4geCAmJiB4LnR5cGUgPT09IFwiVmlydHVhbE5vZGVcIiAmJiB4LnZlcnNpb24gPT09IHZlcnNpb247XG4gICAgICAgICAgICB9XG4gICAgICAgIH0sIHsgXCIuL3ZlcnNpb25cIjogMzAgfV0sIDI4OiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge1xuICAgICAgICAgICAgdmFyIHZlcnNpb24gPSByZXF1aXJlKFwiLi92ZXJzaW9uXCIpO1xuXG4gICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IGlzVmlydHVhbFRleHQ7XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIGlzVmlydHVhbFRleHQoeCkge1xuICAgICAgICAgICAgICAgIHJldHVybiB4ICYmIHgudHlwZSA9PT0gXCJWaXJ0dWFsVGV4dFwiICYmIHgudmVyc2lvbiA9PT0gdmVyc2lvbjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSwgeyBcIi4vdmVyc2lvblwiOiAzMCB9XSwgMjk6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IGlzV2lkZ2V0O1xuXG4gICAgICAgICAgICBmdW5jdGlvbiBpc1dpZGdldCh3KSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHcgJiYgdy50eXBlID09PSBcIldpZGdldFwiO1xuICAgICAgICAgICAgfVxuICAgICAgICB9LCB7fV0sIDMwOiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge1xuICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBcIjJcIjtcbiAgICAgICAgfSwge31dLCAzMTogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHtcbiAgICAgICAgICAgIHZhciB2ZXJzaW9uID0gcmVxdWlyZShcIi4vdmVyc2lvblwiKTtcbiAgICAgICAgICAgIHZhciBpc1ZOb2RlID0gcmVxdWlyZShcIi4vaXMtdm5vZGVcIik7XG4gICAgICAgICAgICB2YXIgaXNXaWRnZXQgPSByZXF1aXJlKFwiLi9pcy13aWRnZXRcIik7XG4gICAgICAgICAgICB2YXIgaXNUaHVuayA9IHJlcXVpcmUoXCIuL2lzLXRodW5rXCIpO1xuICAgICAgICAgICAgdmFyIGlzVkhvb2sgPSByZXF1aXJlKFwiLi9pcy12aG9va1wiKTtcblxuICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBWaXJ0dWFsTm9kZTtcblxuICAgICAgICAgICAgdmFyIG5vUHJvcGVydGllcyA9IHt9O1xuICAgICAgICAgICAgdmFyIG5vQ2hpbGRyZW4gPSBbXTtcblxuICAgICAgICAgICAgZnVuY3Rpb24gVmlydHVhbE5vZGUodGFnTmFtZSwgcHJvcGVydGllcywgY2hpbGRyZW4sIGtleSwgbmFtZXNwYWNlKSB7XG4gICAgICAgICAgICAgICAgdGhpcy50YWdOYW1lID0gdGFnTmFtZTtcbiAgICAgICAgICAgICAgICB0aGlzLnByb3BlcnRpZXMgPSBwcm9wZXJ0aWVzIHx8IG5vUHJvcGVydGllcztcbiAgICAgICAgICAgICAgICB0aGlzLmNoaWxkcmVuID0gY2hpbGRyZW4gfHwgbm9DaGlsZHJlbjtcbiAgICAgICAgICAgICAgICB0aGlzLmtleSA9IGtleSAhPSBudWxsID8gU3RyaW5nKGtleSkgOiB1bmRlZmluZWQ7XG4gICAgICAgICAgICAgICAgdGhpcy5uYW1lc3BhY2UgPSB0eXBlb2YgbmFtZXNwYWNlID09PSBcInN0cmluZ1wiID8gbmFtZXNwYWNlIDogbnVsbDtcblxuICAgICAgICAgICAgICAgIHZhciBjb3VudCA9IGNoaWxkcmVuICYmIGNoaWxkcmVuLmxlbmd0aCB8fCAwO1xuICAgICAgICAgICAgICAgIHZhciBkZXNjZW5kYW50cyA9IDA7XG4gICAgICAgICAgICAgICAgdmFyIGhhc1dpZGdldHMgPSBmYWxzZTtcbiAgICAgICAgICAgICAgICB2YXIgaGFzVGh1bmtzID0gZmFsc2U7XG4gICAgICAgICAgICAgICAgdmFyIGRlc2NlbmRhbnRIb29rcyA9IGZhbHNlO1xuICAgICAgICAgICAgICAgIHZhciBob29rcztcblxuICAgICAgICAgICAgICAgIGZvciAodmFyIHByb3BOYW1lIGluIHByb3BlcnRpZXMpIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKHByb3BlcnRpZXMuaGFzT3duUHJvcGVydHkocHJvcE5hbWUpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICB2YXIgcHJvcGVydHkgPSBwcm9wZXJ0aWVzW3Byb3BOYW1lXTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChpc1ZIb29rKHByb3BlcnR5KSAmJiBwcm9wZXJ0eS51bmhvb2spIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoIWhvb2tzKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGhvb2tzID0ge307XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaG9va3NbcHJvcE5hbWVdID0gcHJvcGVydHk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IGNvdW50OyBpKyspIHtcbiAgICAgICAgICAgICAgICAgICAgdmFyIGNoaWxkID0gY2hpbGRyZW5baV07XG4gICAgICAgICAgICAgICAgICAgIGlmIChpc1ZOb2RlKGNoaWxkKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgZGVzY2VuZGFudHMgKz0gY2hpbGQuY291bnQgfHwgMDtcblxuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKCFoYXNXaWRnZXRzICYmIGNoaWxkLmhhc1dpZGdldHMpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBoYXNXaWRnZXRzID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKCFoYXNUaHVua3MgJiYgY2hpbGQuaGFzVGh1bmtzKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaGFzVGh1bmtzID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKCFkZXNjZW5kYW50SG9va3MgJiYgKGNoaWxkLmhvb2tzIHx8IGNoaWxkLmRlc2NlbmRhbnRIb29rcykpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBkZXNjZW5kYW50SG9va3MgPSB0cnVlO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKCFoYXNXaWRnZXRzICYmIGlzV2lkZ2V0KGNoaWxkKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHR5cGVvZiBjaGlsZC5kZXN0cm95ID09PSBcImZ1bmN0aW9uXCIpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBoYXNXaWRnZXRzID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIGlmICghaGFzVGh1bmtzICYmIGlzVGh1bmsoY2hpbGQpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBoYXNUaHVua3MgPSB0cnVlO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgdGhpcy5jb3VudCA9IGNvdW50ICsgZGVzY2VuZGFudHM7XG4gICAgICAgICAgICAgICAgdGhpcy5oYXNXaWRnZXRzID0gaGFzV2lkZ2V0cztcbiAgICAgICAgICAgICAgICB0aGlzLmhhc1RodW5rcyA9IGhhc1RodW5rcztcbiAgICAgICAgICAgICAgICB0aGlzLmhvb2tzID0gaG9va3M7XG4gICAgICAgICAgICAgICAgdGhpcy5kZXNjZW5kYW50SG9va3MgPSBkZXNjZW5kYW50SG9va3M7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIFZpcnR1YWxOb2RlLnByb3RvdHlwZS52ZXJzaW9uID0gdmVyc2lvbjtcbiAgICAgICAgICAgIFZpcnR1YWxOb2RlLnByb3RvdHlwZS50eXBlID0gXCJWaXJ0dWFsTm9kZVwiO1xuICAgICAgICB9LCB7IFwiLi9pcy10aHVua1wiOiAyNSwgXCIuL2lzLXZob29rXCI6IDI2LCBcIi4vaXMtdm5vZGVcIjogMjcsIFwiLi9pcy13aWRnZXRcIjogMjksIFwiLi92ZXJzaW9uXCI6IDMwIH1dLCAzMjogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHtcbiAgICAgICAgICAgIHZhciB2ZXJzaW9uID0gcmVxdWlyZShcIi4vdmVyc2lvblwiKTtcblxuICAgICAgICAgICAgVmlydHVhbFBhdGNoLk5PTkUgPSAwO1xuICAgICAgICAgICAgVmlydHVhbFBhdGNoLlZURVhUID0gMTtcbiAgICAgICAgICAgIFZpcnR1YWxQYXRjaC5WTk9ERSA9IDI7XG4gICAgICAgICAgICBWaXJ0dWFsUGF0Y2guV0lER0VUID0gMztcbiAgICAgICAgICAgIFZpcnR1YWxQYXRjaC5QUk9QUyA9IDQ7XG4gICAgICAgICAgICBWaXJ0dWFsUGF0Y2guT1JERVIgPSA1O1xuICAgICAgICAgICAgVmlydHVhbFBhdGNoLklOU0VSVCA9IDY7XG4gICAgICAgICAgICBWaXJ0dWFsUGF0Y2guUkVNT1ZFID0gNztcbiAgICAgICAgICAgIFZpcnR1YWxQYXRjaC5USFVOSyA9IDg7XG5cbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gVmlydHVhbFBhdGNoO1xuXG4gICAgICAgICAgICBmdW5jdGlvbiBWaXJ0dWFsUGF0Y2godHlwZSwgdk5vZGUsIHBhdGNoKSB7XG4gICAgICAgICAgICAgICAgdGhpcy50eXBlID0gTnVtYmVyKHR5cGUpO1xuICAgICAgICAgICAgICAgIHRoaXMudk5vZGUgPSB2Tm9kZTtcbiAgICAgICAgICAgICAgICB0aGlzLnBhdGNoID0gcGF0Y2g7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIFZpcnR1YWxQYXRjaC5wcm90b3R5cGUudmVyc2lvbiA9IHZlcnNpb247XG4gICAgICAgICAgICBWaXJ0dWFsUGF0Y2gucHJvdG90eXBlLnR5cGUgPSBcIlZpcnR1YWxQYXRjaFwiO1xuICAgICAgICB9LCB7IFwiLi92ZXJzaW9uXCI6IDMwIH1dLCAzMzogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHtcbiAgICAgICAgICAgIHZhciB2ZXJzaW9uID0gcmVxdWlyZShcIi4vdmVyc2lvblwiKTtcblxuICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBWaXJ0dWFsVGV4dDtcblxuICAgICAgICAgICAgZnVuY3Rpb24gVmlydHVhbFRleHQodGV4dCkge1xuICAgICAgICAgICAgICAgIHRoaXMudGV4dCA9IFN0cmluZyh0ZXh0KTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgVmlydHVhbFRleHQucHJvdG90eXBlLnZlcnNpb24gPSB2ZXJzaW9uO1xuICAgICAgICAgICAgVmlydHVhbFRleHQucHJvdG90eXBlLnR5cGUgPSBcIlZpcnR1YWxUZXh0XCI7XG4gICAgICAgIH0sIHsgXCIuL3ZlcnNpb25cIjogMzAgfV0sIDM0OiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge1xuICAgICAgICAgICAgdmFyIGlzT2JqZWN0ID0gcmVxdWlyZShcImlzLW9iamVjdFwiKTtcbiAgICAgICAgICAgIHZhciBpc0hvb2sgPSByZXF1aXJlKFwiLi4vdm5vZGUvaXMtdmhvb2tcIik7XG5cbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gZGlmZlByb3BzO1xuXG4gICAgICAgICAgICBmdW5jdGlvbiBkaWZmUHJvcHMoYSwgYikge1xuICAgICAgICAgICAgICAgIHZhciBkaWZmO1xuXG4gICAgICAgICAgICAgICAgZm9yICh2YXIgYUtleSBpbiBhKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmICghKGFLZXkgaW4gYikpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGRpZmYgPSBkaWZmIHx8IHt9O1xuICAgICAgICAgICAgICAgICAgICAgICAgZGlmZlthS2V5XSA9IHVuZGVmaW5lZDtcbiAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgIHZhciBhVmFsdWUgPSBhW2FLZXldO1xuICAgICAgICAgICAgICAgICAgICB2YXIgYlZhbHVlID0gYlthS2V5XTtcblxuICAgICAgICAgICAgICAgICAgICBpZiAoYVZhbHVlID09PSBiVmFsdWUpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnRpbnVlO1xuICAgICAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKGlzT2JqZWN0KGFWYWx1ZSkgJiYgaXNPYmplY3QoYlZhbHVlKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGdldFByb3RvdHlwZShiVmFsdWUpICE9PSBnZXRQcm90b3R5cGUoYVZhbHVlKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRpZmYgPSBkaWZmIHx8IHt9O1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRpZmZbYUtleV0gPSBiVmFsdWU7XG4gICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKGlzSG9vayhiVmFsdWUpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgZGlmZiA9IGRpZmYgfHwge307XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgZGlmZlthS2V5XSA9IGJWYWx1ZTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdmFyIG9iamVjdERpZmYgPSBkaWZmUHJvcHMoYVZhbHVlLCBiVmFsdWUpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChvYmplY3REaWZmKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRpZmYgPSBkaWZmIHx8IHt9O1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBkaWZmW2FLZXldID0gb2JqZWN0RGlmZjtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBkaWZmID0gZGlmZiB8fCB7fTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGRpZmZbYUtleV0gPSBiVmFsdWU7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICBmb3IgKHZhciBiS2V5IGluIGIpIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKCEoYktleSBpbiBhKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgZGlmZiA9IGRpZmYgfHwge307XG4gICAgICAgICAgICAgICAgICAgICAgICBkaWZmW2JLZXldID0gYltiS2V5XTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHJldHVybiBkaWZmO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBmdW5jdGlvbiBnZXRQcm90b3R5cGUodmFsdWUpIHtcbiAgICAgICAgICAgICAgICBpZiAoT2JqZWN0LmdldFByb3RvdHlwZU9mKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBPYmplY3QuZ2V0UHJvdG90eXBlT2YodmFsdWUpO1xuICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAodmFsdWUuX19wcm90b19fKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiB2YWx1ZS5fX3Byb3RvX187XG4gICAgICAgICAgICAgICAgfSBlbHNlIGlmICh2YWx1ZS5jb25zdHJ1Y3Rvcikge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gdmFsdWUuY29uc3RydWN0b3IucHJvdG90eXBlO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgfSwgeyBcIi4uL3Zub2RlL2lzLXZob29rXCI6IDI2LCBcImlzLW9iamVjdFwiOiAxMSB9XSwgMzU6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICB2YXIgaXNBcnJheSA9IHJlcXVpcmUoXCJ4LWlzLWFycmF5XCIpO1xuXG4gICAgICAgICAgICB2YXIgVlBhdGNoID0gcmVxdWlyZShcIi4uL3Zub2RlL3ZwYXRjaFwiKTtcbiAgICAgICAgICAgIHZhciBpc1ZOb2RlID0gcmVxdWlyZShcIi4uL3Zub2RlL2lzLXZub2RlXCIpO1xuICAgICAgICAgICAgdmFyIGlzVlRleHQgPSByZXF1aXJlKFwiLi4vdm5vZGUvaXMtdnRleHRcIik7XG4gICAgICAgICAgICB2YXIgaXNXaWRnZXQgPSByZXF1aXJlKFwiLi4vdm5vZGUvaXMtd2lkZ2V0XCIpO1xuICAgICAgICAgICAgdmFyIGlzVGh1bmsgPSByZXF1aXJlKFwiLi4vdm5vZGUvaXMtdGh1bmtcIik7XG4gICAgICAgICAgICB2YXIgaGFuZGxlVGh1bmsgPSByZXF1aXJlKFwiLi4vdm5vZGUvaGFuZGxlLXRodW5rXCIpO1xuXG4gICAgICAgICAgICB2YXIgZGlmZlByb3BzID0gcmVxdWlyZShcIi4vZGlmZi1wcm9wc1wiKTtcblxuICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBkaWZmO1xuXG4gICAgICAgICAgICBmdW5jdGlvbiBkaWZmKGEsIGIpIHtcbiAgICAgICAgICAgICAgICB2YXIgcGF0Y2ggPSB7IGE6IGEgfTtcbiAgICAgICAgICAgICAgICB3YWxrKGEsIGIsIHBhdGNoLCAwKTtcbiAgICAgICAgICAgICAgICByZXR1cm4gcGF0Y2g7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIHdhbGsoYSwgYiwgcGF0Y2gsIGluZGV4KSB7XG4gICAgICAgICAgICAgICAgaWYgKGEgPT09IGIpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHZhciBhcHBseSA9IHBhdGNoW2luZGV4XTtcbiAgICAgICAgICAgICAgICB2YXIgYXBwbHlDbGVhciA9IGZhbHNlO1xuXG4gICAgICAgICAgICAgICAgaWYgKGlzVGh1bmsoYSkgfHwgaXNUaHVuayhiKSkge1xuICAgICAgICAgICAgICAgICAgICB0aHVua3MoYSwgYiwgcGF0Y2gsIGluZGV4KTtcbiAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKGIgPT0gbnVsbCkge1xuXG4gICAgICAgICAgICAgICAgICAgIC8vIElmIGEgaXMgYSB3aWRnZXQgd2Ugd2lsbCBhZGQgYSByZW1vdmUgcGF0Y2ggZm9yIGl0XG4gICAgICAgICAgICAgICAgICAgIC8vIE90aGVyd2lzZSBhbnkgY2hpbGQgd2lkZ2V0cy9ob29rcyBtdXN0IGJlIGRlc3Ryb3llZC5cbiAgICAgICAgICAgICAgICAgICAgLy8gVGhpcyBwcmV2ZW50cyBhZGRpbmcgdHdvIHJlbW92ZSBwYXRjaGVzIGZvciBhIHdpZGdldC5cbiAgICAgICAgICAgICAgICAgICAgaWYgKCFpc1dpZGdldChhKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgY2xlYXJTdGF0ZShhLCBwYXRjaCwgaW5kZXgpO1xuICAgICAgICAgICAgICAgICAgICAgICAgYXBwbHkgPSBwYXRjaFtpbmRleF07XG4gICAgICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgICAgICBhcHBseSA9IGFwcGVuZFBhdGNoKGFwcGx5LCBuZXcgVlBhdGNoKFZQYXRjaC5SRU1PVkUsIGEsIGIpKTtcbiAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKGlzVk5vZGUoYikpIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKGlzVk5vZGUoYSkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChhLnRhZ05hbWUgPT09IGIudGFnTmFtZSAmJiBhLm5hbWVzcGFjZSA9PT0gYi5uYW1lc3BhY2UgJiYgYS5rZXkgPT09IGIua2V5KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdmFyIHByb3BzUGF0Y2ggPSBkaWZmUHJvcHMoYS5wcm9wZXJ0aWVzLCBiLnByb3BlcnRpZXMpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChwcm9wc1BhdGNoKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGFwcGx5ID0gYXBwZW5kUGF0Y2goYXBwbHksIG5ldyBWUGF0Y2goVlBhdGNoLlBST1BTLCBhLCBwcm9wc1BhdGNoKSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGFwcGx5ID0gZGlmZkNoaWxkcmVuKGEsIGIsIHBhdGNoLCBhcHBseSwgaW5kZXgpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBhcHBseSA9IGFwcGVuZFBhdGNoKGFwcGx5LCBuZXcgVlBhdGNoKFZQYXRjaC5WTk9ERSwgYSwgYikpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGFwcGx5Q2xlYXIgPSB0cnVlO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgYXBwbHkgPSBhcHBlbmRQYXRjaChhcHBseSwgbmV3IFZQYXRjaChWUGF0Y2guVk5PREUsIGEsIGIpKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGFwcGx5Q2xlYXIgPSB0cnVlO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfSBlbHNlIGlmIChpc1ZUZXh0KGIpKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmICghaXNWVGV4dChhKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgYXBwbHkgPSBhcHBlbmRQYXRjaChhcHBseSwgbmV3IFZQYXRjaChWUGF0Y2guVlRFWFQsIGEsIGIpKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGFwcGx5Q2xlYXIgPSB0cnVlO1xuICAgICAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKGEudGV4dCAhPT0gYi50ZXh0KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBhcHBseSA9IGFwcGVuZFBhdGNoKGFwcGx5LCBuZXcgVlBhdGNoKFZQYXRjaC5WVEVYVCwgYSwgYikpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfSBlbHNlIGlmIChpc1dpZGdldChiKSkge1xuICAgICAgICAgICAgICAgICAgICBpZiAoIWlzV2lkZ2V0KGEpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBhcHBseUNsZWFyID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgIGFwcGx5ID0gYXBwZW5kUGF0Y2goYXBwbHksIG5ldyBWUGF0Y2goVlBhdGNoLldJREdFVCwgYSwgYikpO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIGlmIChhcHBseSkge1xuICAgICAgICAgICAgICAgICAgICBwYXRjaFtpbmRleF0gPSBhcHBseTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICBpZiAoYXBwbHlDbGVhcikge1xuICAgICAgICAgICAgICAgICAgICBjbGVhclN0YXRlKGEsIHBhdGNoLCBpbmRleCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBmdW5jdGlvbiBkaWZmQ2hpbGRyZW4oYSwgYiwgcGF0Y2gsIGFwcGx5LCBpbmRleCkge1xuICAgICAgICAgICAgICAgIHZhciBhQ2hpbGRyZW4gPSBhLmNoaWxkcmVuO1xuICAgICAgICAgICAgICAgIHZhciBvcmRlcmVkU2V0ID0gcmVvcmRlcihhQ2hpbGRyZW4sIGIuY2hpbGRyZW4pO1xuICAgICAgICAgICAgICAgIHZhciBiQ2hpbGRyZW4gPSBvcmRlcmVkU2V0LmNoaWxkcmVuO1xuXG4gICAgICAgICAgICAgICAgdmFyIGFMZW4gPSBhQ2hpbGRyZW4ubGVuZ3RoO1xuICAgICAgICAgICAgICAgIHZhciBiTGVuID0gYkNoaWxkcmVuLmxlbmd0aDtcbiAgICAgICAgICAgICAgICB2YXIgbGVuID0gYUxlbiA+IGJMZW4gPyBhTGVuIDogYkxlbjtcblxuICAgICAgICAgICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgbGVuOyBpKyspIHtcbiAgICAgICAgICAgICAgICAgICAgdmFyIGxlZnROb2RlID0gYUNoaWxkcmVuW2ldO1xuICAgICAgICAgICAgICAgICAgICB2YXIgcmlnaHROb2RlID0gYkNoaWxkcmVuW2ldO1xuICAgICAgICAgICAgICAgICAgICBpbmRleCArPSAxO1xuXG4gICAgICAgICAgICAgICAgICAgIGlmICghbGVmdE5vZGUpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChyaWdodE5vZGUpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBFeGNlc3Mgbm9kZXMgaW4gYiBuZWVkIHRvIGJlIGFkZGVkXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgYXBwbHkgPSBhcHBlbmRQYXRjaChhcHBseSwgbmV3IFZQYXRjaChWUGF0Y2guSU5TRVJULCBudWxsLCByaWdodE5vZGUpKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHdhbGsobGVmdE5vZGUsIHJpZ2h0Tm9kZSwgcGF0Y2gsIGluZGV4KTtcbiAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgIGlmIChpc1ZOb2RlKGxlZnROb2RlKSAmJiBsZWZ0Tm9kZS5jb3VudCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgaW5kZXggKz0gbGVmdE5vZGUuY291bnQ7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICBpZiAob3JkZXJlZFNldC5tb3Zlcykge1xuICAgICAgICAgICAgICAgICAgICAvLyBSZW9yZGVyIG5vZGVzIGxhc3RcbiAgICAgICAgICAgICAgICAgICAgYXBwbHkgPSBhcHBlbmRQYXRjaChhcHBseSwgbmV3IFZQYXRjaChWUGF0Y2guT1JERVIsIGEsIG9yZGVyZWRTZXQubW92ZXMpKTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICByZXR1cm4gYXBwbHk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIGNsZWFyU3RhdGUodk5vZGUsIHBhdGNoLCBpbmRleCkge1xuICAgICAgICAgICAgICAgIC8vIFRPRE86IE1ha2UgdGhpcyBhIHNpbmdsZSB3YWxrLCBub3QgdHdvXG4gICAgICAgICAgICAgICAgdW5ob29rKHZOb2RlLCBwYXRjaCwgaW5kZXgpO1xuICAgICAgICAgICAgICAgIGRlc3Ryb3lXaWRnZXRzKHZOb2RlLCBwYXRjaCwgaW5kZXgpO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAvLyBQYXRjaCByZWNvcmRzIGZvciBhbGwgZGVzdHJveWVkIHdpZGdldHMgbXVzdCBiZSBhZGRlZCBiZWNhdXNlIHdlIG5lZWRcbiAgICAgICAgICAgIC8vIGEgRE9NIG5vZGUgcmVmZXJlbmNlIGZvciB0aGUgZGVzdHJveSBmdW5jdGlvblxuICAgICAgICAgICAgZnVuY3Rpb24gZGVzdHJveVdpZGdldHModk5vZGUsIHBhdGNoLCBpbmRleCkge1xuICAgICAgICAgICAgICAgIGlmIChpc1dpZGdldCh2Tm9kZSkpIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKHR5cGVvZiB2Tm9kZS5kZXN0cm95ID09PSBcImZ1bmN0aW9uXCIpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHBhdGNoW2luZGV4XSA9IGFwcGVuZFBhdGNoKHBhdGNoW2luZGV4XSwgbmV3IFZQYXRjaChWUGF0Y2guUkVNT1ZFLCB2Tm9kZSwgbnVsbCkpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfSBlbHNlIGlmIChpc1ZOb2RlKHZOb2RlKSAmJiAodk5vZGUuaGFzV2lkZ2V0cyB8fCB2Tm9kZS5oYXNUaHVua3MpKSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciBjaGlsZHJlbiA9IHZOb2RlLmNoaWxkcmVuO1xuICAgICAgICAgICAgICAgICAgICB2YXIgbGVuID0gY2hpbGRyZW4ubGVuZ3RoO1xuICAgICAgICAgICAgICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IGxlbjsgaSsrKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICB2YXIgY2hpbGQgPSBjaGlsZHJlbltpXTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGluZGV4ICs9IDE7XG5cbiAgICAgICAgICAgICAgICAgICAgICAgIGRlc3Ryb3lXaWRnZXRzKGNoaWxkLCBwYXRjaCwgaW5kZXgpO1xuXG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoaXNWTm9kZShjaGlsZCkgJiYgY2hpbGQuY291bnQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpbmRleCArPSBjaGlsZC5jb3VudDtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoaXNUaHVuayh2Tm9kZSkpIHtcbiAgICAgICAgICAgICAgICAgICAgdGh1bmtzKHZOb2RlLCBudWxsLCBwYXRjaCwgaW5kZXgpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgLy8gQ3JlYXRlIGEgc3ViLXBhdGNoIGZvciB0aHVua3NcbiAgICAgICAgICAgIGZ1bmN0aW9uIHRodW5rcyhhLCBiLCBwYXRjaCwgaW5kZXgpIHtcbiAgICAgICAgICAgICAgICB2YXIgbm9kZXMgPSBoYW5kbGVUaHVuayhhLCBiKTtcbiAgICAgICAgICAgICAgICB2YXIgdGh1bmtQYXRjaCA9IGRpZmYobm9kZXMuYSwgbm9kZXMuYik7XG4gICAgICAgICAgICAgICAgaWYgKGhhc1BhdGNoZXModGh1bmtQYXRjaCkpIHtcbiAgICAgICAgICAgICAgICAgICAgcGF0Y2hbaW5kZXhdID0gbmV3IFZQYXRjaChWUGF0Y2guVEhVTkssIG51bGwsIHRodW5rUGF0Y2gpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZnVuY3Rpb24gaGFzUGF0Y2hlcyhwYXRjaCkge1xuICAgICAgICAgICAgICAgIGZvciAodmFyIGluZGV4IGluIHBhdGNoKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmIChpbmRleCAhPT0gXCJhXCIpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAvLyBFeGVjdXRlIGhvb2tzIHdoZW4gdHdvIG5vZGVzIGFyZSBpZGVudGljYWxcbiAgICAgICAgICAgIGZ1bmN0aW9uIHVuaG9vayh2Tm9kZSwgcGF0Y2gsIGluZGV4KSB7XG4gICAgICAgICAgICAgICAgaWYgKGlzVk5vZGUodk5vZGUpKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmICh2Tm9kZS5ob29rcykge1xuICAgICAgICAgICAgICAgICAgICAgICAgcGF0Y2hbaW5kZXhdID0gYXBwZW5kUGF0Y2gocGF0Y2hbaW5kZXhdLCBuZXcgVlBhdGNoKFZQYXRjaC5QUk9QUywgdk5vZGUsIHVuZGVmaW5lZEtleXModk5vZGUuaG9va3MpKSk7XG4gICAgICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgICAgICBpZiAodk5vZGUuZGVzY2VuZGFudEhvb2tzIHx8IHZOb2RlLmhhc1RodW5rcykge1xuICAgICAgICAgICAgICAgICAgICAgICAgdmFyIGNoaWxkcmVuID0gdk5vZGUuY2hpbGRyZW47XG4gICAgICAgICAgICAgICAgICAgICAgICB2YXIgbGVuID0gY2hpbGRyZW4ubGVuZ3RoO1xuICAgICAgICAgICAgICAgICAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCBsZW47IGkrKykge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZhciBjaGlsZCA9IGNoaWxkcmVuW2ldO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGluZGV4ICs9IDE7XG5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB1bmhvb2soY2hpbGQsIHBhdGNoLCBpbmRleCk7XG5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoaXNWTm9kZShjaGlsZCkgJiYgY2hpbGQuY291bnQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaW5kZXggKz0gY2hpbGQuY291bnQ7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfSBlbHNlIGlmIChpc1RodW5rKHZOb2RlKSkge1xuICAgICAgICAgICAgICAgICAgICB0aHVua3Modk5vZGUsIG51bGwsIHBhdGNoLCBpbmRleCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBmdW5jdGlvbiB1bmRlZmluZWRLZXlzKG9iaikge1xuICAgICAgICAgICAgICAgIHZhciByZXN1bHQgPSB7fTtcblxuICAgICAgICAgICAgICAgIGZvciAodmFyIGtleSBpbiBvYmopIHtcbiAgICAgICAgICAgICAgICAgICAgcmVzdWx0W2tleV0gPSB1bmRlZmluZWQ7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgcmV0dXJuIHJlc3VsdDtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgLy8gTGlzdCBkaWZmLCBuYWl2ZSBsZWZ0IHRvIHJpZ2h0IHJlb3JkZXJpbmdcbiAgICAgICAgICAgIGZ1bmN0aW9uIHJlb3JkZXIoYUNoaWxkcmVuLCBiQ2hpbGRyZW4pIHtcbiAgICAgICAgICAgICAgICAvLyBPKE0pIHRpbWUsIE8oTSkgbWVtb3J5XG4gICAgICAgICAgICAgICAgdmFyIGJDaGlsZEluZGV4ID0ga2V5SW5kZXgoYkNoaWxkcmVuKTtcbiAgICAgICAgICAgICAgICB2YXIgYktleXMgPSBiQ2hpbGRJbmRleC5rZXlzO1xuICAgICAgICAgICAgICAgIHZhciBiRnJlZSA9IGJDaGlsZEluZGV4LmZyZWU7XG5cbiAgICAgICAgICAgICAgICBpZiAoYkZyZWUubGVuZ3RoID09PSBiQ2hpbGRyZW4ubGVuZ3RoKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiB7XG4gICAgICAgICAgICAgICAgICAgICAgICBjaGlsZHJlbjogYkNoaWxkcmVuLFxuICAgICAgICAgICAgICAgICAgICAgICAgbW92ZXM6IG51bGxcbiAgICAgICAgICAgICAgICAgICAgfTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAvLyBPKE4pIHRpbWUsIE8oTikgbWVtb3J5XG4gICAgICAgICAgICAgICAgdmFyIGFDaGlsZEluZGV4ID0ga2V5SW5kZXgoYUNoaWxkcmVuKTtcbiAgICAgICAgICAgICAgICB2YXIgYUtleXMgPSBhQ2hpbGRJbmRleC5rZXlzO1xuICAgICAgICAgICAgICAgIHZhciBhRnJlZSA9IGFDaGlsZEluZGV4LmZyZWU7XG5cbiAgICAgICAgICAgICAgICBpZiAoYUZyZWUubGVuZ3RoID09PSBhQ2hpbGRyZW4ubGVuZ3RoKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiB7XG4gICAgICAgICAgICAgICAgICAgICAgICBjaGlsZHJlbjogYkNoaWxkcmVuLFxuICAgICAgICAgICAgICAgICAgICAgICAgbW92ZXM6IG51bGxcbiAgICAgICAgICAgICAgICAgICAgfTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAvLyBPKE1BWChOLCBNKSkgbWVtb3J5XG4gICAgICAgICAgICAgICAgdmFyIG5ld0NoaWxkcmVuID0gW107XG5cbiAgICAgICAgICAgICAgICB2YXIgZnJlZUluZGV4ID0gMDtcbiAgICAgICAgICAgICAgICB2YXIgZnJlZUNvdW50ID0gYkZyZWUubGVuZ3RoO1xuICAgICAgICAgICAgICAgIHZhciBkZWxldGVkSXRlbXMgPSAwO1xuXG4gICAgICAgICAgICAgICAgLy8gSXRlcmF0ZSB0aHJvdWdoIGEgYW5kIG1hdGNoIGEgbm9kZSBpbiBiXG4gICAgICAgICAgICAgICAgLy8gTyhOKSB0aW1lLFxuICAgICAgICAgICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgYUNoaWxkcmVuLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciBhSXRlbSA9IGFDaGlsZHJlbltpXTtcbiAgICAgICAgICAgICAgICAgICAgdmFyIGl0ZW1JbmRleDtcblxuICAgICAgICAgICAgICAgICAgICBpZiAoYUl0ZW0ua2V5KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoYktleXMuaGFzT3duUHJvcGVydHkoYUl0ZW0ua2V5KSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIE1hdGNoIHVwIHRoZSBvbGQga2V5c1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGl0ZW1JbmRleCA9IGJLZXlzW2FJdGVtLmtleV07XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgbmV3Q2hpbGRyZW4ucHVzaChiQ2hpbGRyZW5baXRlbUluZGV4XSk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIFJlbW92ZSBvbGQga2V5ZWQgaXRlbXNcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpdGVtSW5kZXggPSBpIC0gZGVsZXRlZEl0ZW1zKys7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgbmV3Q2hpbGRyZW4ucHVzaChudWxsKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIE1hdGNoIHRoZSBpdGVtIGluIGEgd2l0aCB0aGUgbmV4dCBmcmVlIGl0ZW0gaW4gYlxuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGZyZWVJbmRleCA8IGZyZWVDb3VudCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGl0ZW1JbmRleCA9IGJGcmVlW2ZyZWVJbmRleCsrXTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBuZXdDaGlsZHJlbi5wdXNoKGJDaGlsZHJlbltpdGVtSW5kZXhdKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gVGhlcmUgYXJlIG5vIGZyZWUgaXRlbXMgaW4gYiB0byBtYXRjaCB3aXRoXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gdGhlIGZyZWUgaXRlbXMgaW4gYSwgc28gdGhlIGV4dHJhIGZyZWUgbm9kZXNcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBhcmUgZGVsZXRlZC5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpdGVtSW5kZXggPSBpIC0gZGVsZXRlZEl0ZW1zKys7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgbmV3Q2hpbGRyZW4ucHVzaChudWxsKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHZhciBsYXN0RnJlZUluZGV4ID0gZnJlZUluZGV4ID49IGJGcmVlLmxlbmd0aCA/IGJDaGlsZHJlbi5sZW5ndGggOiBiRnJlZVtmcmVlSW5kZXhdO1xuXG4gICAgICAgICAgICAgICAgLy8gSXRlcmF0ZSB0aHJvdWdoIGIgYW5kIGFwcGVuZCBhbnkgbmV3IGtleXNcbiAgICAgICAgICAgICAgICAvLyBPKE0pIHRpbWVcbiAgICAgICAgICAgICAgICBmb3IgKHZhciBqID0gMDsgaiA8IGJDaGlsZHJlbi5sZW5ndGg7IGorKykge1xuICAgICAgICAgICAgICAgICAgICB2YXIgbmV3SXRlbSA9IGJDaGlsZHJlbltqXTtcblxuICAgICAgICAgICAgICAgICAgICBpZiAobmV3SXRlbS5rZXkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmICghYUtleXMuaGFzT3duUHJvcGVydHkobmV3SXRlbS5rZXkpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gQWRkIGFueSBuZXcga2V5ZWQgaXRlbXNcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBXZSBhcmUgYWRkaW5nIG5ldyBpdGVtcyB0byB0aGUgZW5kIGFuZCB0aGVuIHNvcnRpbmcgdGhlbVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIGluIHBsYWNlLiBJbiBmdXR1cmUgd2Ugc2hvdWxkIGluc2VydCBuZXcgaXRlbXMgaW4gcGxhY2UuXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgbmV3Q2hpbGRyZW4ucHVzaChuZXdJdGVtKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIGlmIChqID49IGxhc3RGcmVlSW5kZXgpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIEFkZCBhbnkgbGVmdG92ZXIgbm9uLWtleWVkIGl0ZW1zXG4gICAgICAgICAgICAgICAgICAgICAgICBuZXdDaGlsZHJlbi5wdXNoKG5ld0l0ZW0pO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgdmFyIHNpbXVsYXRlID0gbmV3Q2hpbGRyZW4uc2xpY2UoKTtcbiAgICAgICAgICAgICAgICB2YXIgc2ltdWxhdGVJbmRleCA9IDA7XG4gICAgICAgICAgICAgICAgdmFyIHJlbW92ZXMgPSBbXTtcbiAgICAgICAgICAgICAgICB2YXIgaW5zZXJ0cyA9IFtdO1xuICAgICAgICAgICAgICAgIHZhciBzaW11bGF0ZUl0ZW07XG5cbiAgICAgICAgICAgICAgICBmb3IgKHZhciBrID0gMDsgayA8IGJDaGlsZHJlbi5sZW5ndGg7KSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciB3YW50ZWRJdGVtID0gYkNoaWxkcmVuW2tdO1xuICAgICAgICAgICAgICAgICAgICBzaW11bGF0ZUl0ZW0gPSBzaW11bGF0ZVtzaW11bGF0ZUluZGV4XTtcblxuICAgICAgICAgICAgICAgICAgICAvLyByZW1vdmUgaXRlbXNcbiAgICAgICAgICAgICAgICAgICAgd2hpbGUgKHNpbXVsYXRlSXRlbSA9PT0gbnVsbCAmJiBzaW11bGF0ZS5sZW5ndGgpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJlbW92ZXMucHVzaChyZW1vdmUoc2ltdWxhdGUsIHNpbXVsYXRlSW5kZXgsIG51bGwpKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIHNpbXVsYXRlSXRlbSA9IHNpbXVsYXRlW3NpbXVsYXRlSW5kZXhdO1xuICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgaWYgKCFzaW11bGF0ZUl0ZW0gfHwgc2ltdWxhdGVJdGVtLmtleSAhPT0gd2FudGVkSXRlbS5rZXkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIGlmIHdlIG5lZWQgYSBrZXkgaW4gdGhpcyBwb3NpdGlvbi4uLlxuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHdhbnRlZEl0ZW0ua2V5KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHNpbXVsYXRlSXRlbSAmJiBzaW11bGF0ZUl0ZW0ua2V5KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIGlmIGFuIGluc2VydCBkb2Vzbid0IHB1dCB0aGlzIGtleSBpbiBwbGFjZSwgaXQgbmVlZHMgdG8gbW92ZVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoYktleXNbc2ltdWxhdGVJdGVtLmtleV0gIT09IGsgKyAxKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICByZW1vdmVzLnB1c2gocmVtb3ZlKHNpbXVsYXRlLCBzaW11bGF0ZUluZGV4LCBzaW11bGF0ZUl0ZW0ua2V5KSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzaW11bGF0ZUl0ZW0gPSBzaW11bGF0ZVtzaW11bGF0ZUluZGV4XTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIGlmIHRoZSByZW1vdmUgZGlkbid0IHB1dCB0aGUgd2FudGVkIGl0ZW0gaW4gcGxhY2UsIHdlIG5lZWQgdG8gaW5zZXJ0IGl0XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoIXNpbXVsYXRlSXRlbSB8fCBzaW11bGF0ZUl0ZW0ua2V5ICE9PSB3YW50ZWRJdGVtLmtleSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGluc2VydHMucHVzaCh7IGtleTogd2FudGVkSXRlbS5rZXksIHRvOiBrIH0pO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gaXRlbXMgYXJlIG1hdGNoaW5nLCBzbyBza2lwIGFoZWFkXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzaW11bGF0ZUluZGV4Kys7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpbnNlcnRzLnB1c2goeyBrZXk6IHdhbnRlZEl0ZW0ua2V5LCB0bzogayB9KTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGluc2VydHMucHVzaCh7IGtleTogd2FudGVkSXRlbS5rZXksIHRvOiBrIH0pO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBrKys7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAvLyBhIGtleSBpbiBzaW11bGF0ZSBoYXMgbm8gbWF0Y2hpbmcgd2FudGVkIGtleSwgcmVtb3ZlIGl0XG4gICAgICAgICAgICAgICAgICAgICAgICBlbHNlIGlmIChzaW11bGF0ZUl0ZW0gJiYgc2ltdWxhdGVJdGVtLmtleSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlbW92ZXMucHVzaChyZW1vdmUoc2ltdWxhdGUsIHNpbXVsYXRlSW5kZXgsIHNpbXVsYXRlSXRlbS5rZXkpKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHNpbXVsYXRlSW5kZXgrKztcbiAgICAgICAgICAgICAgICAgICAgICAgIGsrKztcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIC8vIHJlbW92ZSBhbGwgdGhlIHJlbWFpbmluZyBub2RlcyBmcm9tIHNpbXVsYXRlXG4gICAgICAgICAgICAgICAgd2hpbGUgKHNpbXVsYXRlSW5kZXggPCBzaW11bGF0ZS5sZW5ndGgpIHtcbiAgICAgICAgICAgICAgICAgICAgc2ltdWxhdGVJdGVtID0gc2ltdWxhdGVbc2ltdWxhdGVJbmRleF07XG4gICAgICAgICAgICAgICAgICAgIHJlbW92ZXMucHVzaChyZW1vdmUoc2ltdWxhdGUsIHNpbXVsYXRlSW5kZXgsIHNpbXVsYXRlSXRlbSAmJiBzaW11bGF0ZUl0ZW0ua2V5KSk7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgLy8gSWYgdGhlIG9ubHkgbW92ZXMgd2UgaGF2ZSBhcmUgZGVsZXRlcyB0aGVuIHdlIGNhbiBqdXN0XG4gICAgICAgICAgICAgICAgLy8gbGV0IHRoZSBkZWxldGUgcGF0Y2ggcmVtb3ZlIHRoZXNlIGl0ZW1zLlxuICAgICAgICAgICAgICAgIGlmIChyZW1vdmVzLmxlbmd0aCA9PT0gZGVsZXRlZEl0ZW1zICYmICFpbnNlcnRzLmxlbmd0aCkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgICAgICAgICAgICAgY2hpbGRyZW46IG5ld0NoaWxkcmVuLFxuICAgICAgICAgICAgICAgICAgICAgICAgbW92ZXM6IG51bGxcbiAgICAgICAgICAgICAgICAgICAgfTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgICAgICAgICBjaGlsZHJlbjogbmV3Q2hpbGRyZW4sXG4gICAgICAgICAgICAgICAgICAgIG1vdmVzOiB7XG4gICAgICAgICAgICAgICAgICAgICAgICByZW1vdmVzOiByZW1vdmVzLFxuICAgICAgICAgICAgICAgICAgICAgICAgaW5zZXJ0czogaW5zZXJ0c1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZnVuY3Rpb24gcmVtb3ZlKGFyciwgaW5kZXgsIGtleSkge1xuICAgICAgICAgICAgICAgIGFyci5zcGxpY2UoaW5kZXgsIDEpO1xuXG4gICAgICAgICAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgICAgICAgICAgZnJvbTogaW5kZXgsXG4gICAgICAgICAgICAgICAgICAgIGtleToga2V5XG4gICAgICAgICAgICAgICAgfTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZnVuY3Rpb24ga2V5SW5kZXgoY2hpbGRyZW4pIHtcbiAgICAgICAgICAgICAgICB2YXIga2V5cyA9IHt9O1xuICAgICAgICAgICAgICAgIHZhciBmcmVlID0gW107XG4gICAgICAgICAgICAgICAgdmFyIGxlbmd0aCA9IGNoaWxkcmVuLmxlbmd0aDtcblxuICAgICAgICAgICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgbGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgICAgICAgICAgdmFyIGNoaWxkID0gY2hpbGRyZW5baV07XG5cbiAgICAgICAgICAgICAgICAgICAgaWYgKGNoaWxkLmtleSkge1xuICAgICAgICAgICAgICAgICAgICAgICAga2V5c1tjaGlsZC5rZXldID0gaTtcbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGZyZWUucHVzaChpKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHJldHVybiB7XG4gICAgICAgICAgICAgICAgICAgIGtleXM6IGtleXMsIC8vIEEgaGFzaCBvZiBrZXkgbmFtZSB0byBpbmRleFxuICAgICAgICAgICAgICAgICAgICBmcmVlOiBmcmVlIC8vIEFuIGFycmF5IG9mIHVua2V5ZWQgaXRlbSBpbmRpY2VzXG4gICAgICAgICAgICAgICAgfTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZnVuY3Rpb24gYXBwZW5kUGF0Y2goYXBwbHksIHBhdGNoKSB7XG4gICAgICAgICAgICAgICAgaWYgKGFwcGx5KSB7XG4gICAgICAgICAgICAgICAgICAgIGlmIChpc0FycmF5KGFwcGx5KSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgYXBwbHkucHVzaChwYXRjaCk7XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBhcHBseSA9IFthcHBseSwgcGF0Y2hdO1xuICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGFwcGx5O1xuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBwYXRjaDtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH0sIHsgXCIuLi92bm9kZS9oYW5kbGUtdGh1bmtcIjogMjQsIFwiLi4vdm5vZGUvaXMtdGh1bmtcIjogMjUsIFwiLi4vdm5vZGUvaXMtdm5vZGVcIjogMjcsIFwiLi4vdm5vZGUvaXMtdnRleHRcIjogMjgsIFwiLi4vdm5vZGUvaXMtd2lkZ2V0XCI6IDI5LCBcIi4uL3Zub2RlL3ZwYXRjaFwiOiAzMiwgXCIuL2RpZmYtcHJvcHNcIjogMzQsIFwieC1pcy1hcnJheVwiOiAxMiB9XSB9LCB7fSwgWzRdKSg0KTtcbn0pO1xuXG5jb25zdCBDb3JlID0gQztcblxuZXhwb3J0IHsgQ29yZSwgRW51bSwgVmlydHVhbERPTSB9OyJdLCJmaWxlIjoiRWxpeGlyLmpzIiwic291cmNlUm9vdCI6Ii9zb3VyY2UvIn0= \ No newline at end of file +//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiIiwic291cmNlcyI6WyJFbGl4aXIuanMiXSwic291cmNlc0NvbnRlbnQiOlsiLyogQGZsb3cgKi9cblxuY2xhc3MgTWFpbGJveCB7XG5cbiAgY29uc3RydWN0b3IoKSB7XG4gICAgdGhpcy5tZXNzYWdlcyA9IFtdO1xuICB9XG5cbiAgZGVsaXZlcihtZXNzYWdlKSB7XG4gICAgdGhpcy5tZXNzYWdlcy5wdXNoKG1lc3NhZ2UpO1xuICAgIHJldHVybiBtZXNzYWdlO1xuICB9XG5cbiAgZ2V0KCkge1xuICAgIHJldHVybiB0aGlzLm1lc3NhZ2VzO1xuICB9XG5cbiAgaXNFbXB0eSgpIHtcbiAgICByZXR1cm4gdGhpcy5tZXNzYWdlcy5sZW5ndGggPT09IDA7XG4gIH1cblxuICByZW1vdmVBdChpbmRleCkge1xuICAgIHRoaXMubWVzc2FnZXMuc3BsaWNlKGluZGV4LCAxKTtcbiAgfVxufVxuXG52YXIgU3RhdGVzID0ge1xuICBOT1JNQUw6IFN5bWJvbC5mb3IoXCJub3JtYWxcIiksXG4gIEtJTEw6IFN5bWJvbC5mb3IoXCJraWxsXCIpLFxuICBTVVNQRU5EOiBTeW1ib2wuZm9yKFwic3VzcGVuZFwiKSxcbiAgQ09OVElOVUU6IFN5bWJvbC5mb3IoXCJjb250aW51ZVwiKSxcbiAgUkVDRUlWRTogU3ltYm9sLmZvcihcInJlY2VpdmVcIiksXG4gIFNFTkQ6IFN5bWJvbC5mb3IoXCJzZW5kXCIpLFxuICBTTEVFUElORzogU3ltYm9sLmZvcihcInNsZWVwaW5nXCIpLFxuICBSVU5OSU5HOiBTeW1ib2wuZm9yKFwicnVubmluZ1wiKSxcbiAgU1VTUEVOREVEOiBTeW1ib2wuZm9yKFwic3VzcGVuZGVkXCIpLFxuICBTVE9QUEVEOiBTeW1ib2wuZm9yKFwic3RvcHBlZFwiKSxcbiAgU0xFRVA6IFN5bWJvbC5mb3IoXCJzbGVlcFwiKSxcbiAgRVhJVDogU3ltYm9sLmZvcihcImV4aXRcIiksXG4gIE5PTUFUQ0g6IFN5bWJvbC5mb3IoXCJub19tYXRjaFwiKVxufTtcblxuY2xhc3MgUHJvY2VzcyB7XG5cbiAgY29uc3RydWN0b3IocGlkLCBtYWlsYm94KSB7XG4gICAgdGhpcy5waWQgPSBwaWQ7XG4gICAgdGhpcy5tYWlsYm94ID0gbWFpbGJveDtcbiAgICB0aGlzLnN0YXR1cyA9IFN0YXRlcy5TVE9QUEVEO1xuICAgIHRoaXMuZGljdCA9IHt9O1xuICB9XG59XG5cbmNsYXNzIFR1cGxlIHtcblxuICBjb25zdHJ1Y3RvciguLi5hcmdzKSB7XG4gICAgdGhpcy52YWx1ZXMgPSBPYmplY3QuZnJlZXplKGFyZ3MpO1xuICAgIHRoaXMubGVuZ3RoID0gdGhpcy52YWx1ZXMubGVuZ3RoO1xuICB9XG5cbiAgZ2V0KGluZGV4KSB7XG4gICAgcmV0dXJuIHRoaXMudmFsdWVzW2luZGV4XTtcbiAgfVxuXG4gIGNvdW50KCkge1xuICAgIHJldHVybiB0aGlzLnZhbHVlcy5sZW5ndGg7XG4gIH1cblxuICBbU3ltYm9sLml0ZXJhdG9yXSgpIHtcbiAgICByZXR1cm4gdGhpcy52YWx1ZXNbU3ltYm9sLml0ZXJhdG9yXSgpO1xuICB9XG5cbiAgdG9TdHJpbmcoKSB7XG4gICAgdmFyIGksXG4gICAgICAgIHMgPSBcIlwiO1xuICAgIGZvciAoaSA9IDA7IGkgPCB0aGlzLnZhbHVlcy5sZW5ndGg7IGkrKykge1xuICAgICAgaWYgKHMgIT09IFwiXCIpIHtcbiAgICAgICAgcyArPSBcIiwgXCI7XG4gICAgICB9XG4gICAgICBzICs9IHRoaXMudmFsdWVzW2ldLnRvU3RyaW5nKCk7XG4gICAgfVxuXG4gICAgcmV0dXJuIFwie1wiICsgcyArIFwifVwiO1xuICB9XG5cbn1cblxubGV0IHByb2Nlc3NfY291bnRlciA9IC0xO1xuXG5jbGFzcyBQSUQge1xuICBjb25zdHJ1Y3RvcigpIHtcbiAgICBwcm9jZXNzX2NvdW50ZXIgPSBwcm9jZXNzX2NvdW50ZXIgKyAxO1xuICAgIHRoaXMuaWQgPSBwcm9jZXNzX2NvdW50ZXI7XG4gIH1cblxuICB0b1N0cmluZygpIHtcbiAgICByZXR1cm4gXCJQSUQjPDAuXCIgKyB0aGlzLmlkICsgXCIuMD5cIjtcbiAgfVxufVxuXG5jbGFzcyBJbnRlZ2VyIHt9XG5jbGFzcyBGbG9hdCB7fVxuXG5jbGFzcyBQcm9jZXNzU3lzdGVtIHtcblxuICBjb25zdHJ1Y3RvcigpIHtcbiAgICB0aGlzLnBpZHMgPSBuZXcgTWFwKCk7XG4gICAgdGhpcy5tYWlsYm94ZXMgPSBuZXcgTWFwKCk7XG4gICAgdGhpcy5uYW1lcyA9IG5ldyBNYXAoKTtcbiAgICB0aGlzLmxpbmtzID0gbmV3IE1hcCgpO1xuXG4gICAgdGhpcy5jdXJyZW50X3Byb2Nlc3MgPSBudWxsO1xuICAgIHRoaXMuc3VzcGVuZGVkID0gbmV3IE1hcCgpO1xuXG4gICAgdGhpcy5tYWluX3Byb2Nlc3NfcGlkID0gdGhpcy5zcGF3bigpO1xuICAgIHRoaXMuc2V0X2N1cnJlbnQodGhpcy5tYWluX3Byb2Nlc3NfcGlkKTtcbiAgfVxuXG4gIHNwYXduKCkge1xuICAgIHJldHVybiB0aGlzLmFkZF9wcm9jKGZhbHNlKS5waWQ7XG4gIH1cblxuICBzcGF3bl9saW5rKCkge1xuICAgIHJldHVybiB0aGlzLmFkZF9wcm9jKHRydWUpLnBpZDtcbiAgfVxuXG4gIGxpbmsocGlkKSB7XG4gICAgdGhpcy5saW5rcy5nZXQodGhpcy5waWQoKSkuYWRkKHBpZCk7XG4gICAgdGhpcy5saW5rcy5nZXQocGlkKS5hZGQodGhpcy5waWQoKSk7XG4gIH1cblxuICB1bmxpbmsocGlkKSB7XG4gICAgdGhpcy5saW5rcy5nZXQodGhpcy5waWQoKSkuZGVsZXRlKHBpZCk7XG4gICAgdGhpcy5saW5rcy5nZXQocGlkKS5kZWxldGUodGhpcy5waWQoKSk7XG4gIH1cblxuICBzZXRfY3VycmVudChpZCkge1xuICAgIGxldCBwaWQgPSB0aGlzLnBpZG9mKGlkKTtcbiAgICBpZiAocGlkICE9PSBudWxsKSB7XG4gICAgICB0aGlzLmN1cnJlbnRfcHJvY2VzcyA9IHRoaXMucGlkcy5nZXQocGlkKTtcbiAgICAgIHRoaXMuY3VycmVudF9wcm9jZXNzLnN0YXR1cyA9IFN0YXRlcy5SVU5OSU5HO1xuICAgIH1cbiAgfVxuXG4gIGFkZF9wcm9jKGxpbmtlZCkge1xuICAgIGxldCBuZXdwaWQgPSBuZXcgUElEKCk7XG4gICAgbGV0IG1haWxib3ggPSBuZXcgTWFpbGJveCgpO1xuICAgIGxldCBuZXdwcm9jID0gbmV3IFByb2Nlc3MobmV3cGlkLCBtYWlsYm94KTtcblxuICAgIHRoaXMucGlkcy5zZXQobmV3cGlkLCBuZXdwcm9jKTtcbiAgICB0aGlzLm1haWxib3hlcy5zZXQobmV3cGlkLCBtYWlsYm94KTtcbiAgICB0aGlzLmxpbmtzLnNldChuZXdwaWQsIG5ldyBTZXQoKSk7XG5cbiAgICBpZiAobGlua2VkKSB7XG4gICAgICB0aGlzLmxpbmsobmV3cGlkKTtcbiAgICB9XG5cbiAgICByZXR1cm4gbmV3cHJvYztcbiAgfVxuXG4gIHJlbW92ZV9wcm9jKHBpZCkge1xuICAgIHRoaXMucGlkcy5kZWxldGUocGlkKTtcbiAgICB0aGlzLnVucmVnaXN0ZXIocGlkKTtcblxuICAgIGlmICh0aGlzLmxpbmtzLmhhcyhwaWQpKSB7XG4gICAgICBmb3IgKGxldCBsaW5rcGlkIG9mIHRoaXMubGlua3MuZ2V0KHBpZCkpIHtcbiAgICAgICAgdGhpcy5saW5rcy5nZXQobGlua3BpZCkuZGVsZXRlKHBpZCk7XG4gICAgICB9XG5cbiAgICAgIHRoaXMubGlua3MuZGVsZXRlKHBpZCk7XG4gICAgfVxuICB9XG5cbiAgZXhpdChpZCkge1xuICAgIGxldCBwaWQgPSB0aGlzLnBpZG9mKGlkKTtcbiAgICB0aGlzLnJlbW92ZV9wcm9jKGlkKTtcbiAgfVxuXG4gIHJlZ2lzdGVyKG5hbWUsIHBpZCkge1xuICAgIGlmICghdGhpcy5uYW1lcy5oYXMobmFtZSkpIHtcbiAgICAgIHRoaXMubmFtZXMuc2V0KG5hbWUsIHBpZCk7XG4gICAgICByZXR1cm4gbmFtZTtcbiAgICB9IGVsc2Uge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKFwiTmFtZSBpcyBhbHJlYWR5IHJlZ2lzdGVyZWQgdG8gYW5vdGhlciBwcm9jZXNzXCIpO1xuICAgIH1cbiAgfVxuXG4gIHJlZ2lzdGVyZWQobmFtZSkge1xuICAgIHJldHVybiB0aGlzLm5hbWVzLmhhcyhuYW1lKSA/IHRoaXMubmFtZXMuZ2V0KG5hbWUpIDogbnVsbDtcbiAgfVxuXG4gIHVucmVnaXN0ZXIocGlkKSB7XG4gICAgZm9yIChsZXQgbmFtZSBvZiB0aGlzLm5hbWVzLmtleXMoKSkge1xuICAgICAgaWYgKHRoaXMubmFtZXMuaGFzKG5hbWUpICYmIHRoaXMubmFtZXMuZ2V0KG5hbWUpID09PSBwaWQpIHtcbiAgICAgICAgdGhpcy5uYW1lcy5kZWxldGUobmFtZSk7XG4gICAgICB9XG4gICAgfVxuICB9XG5cbiAgcGlkKCkge1xuICAgIHJldHVybiB0aGlzLmN1cnJlbnRfcHJvY2Vzcy5waWQ7XG4gIH1cblxuICBwaWRvZihpZCkge1xuICAgIGlmIChpZCBpbnN0YW5jZW9mIFBJRCkge1xuICAgICAgcmV0dXJuIHRoaXMucGlkcy5oYXMoaWQpID8gaWQgOiBudWxsO1xuICAgIH0gZWxzZSBpZiAoaWQgaW5zdGFuY2VvZiBQcm9jZXNzKSB7XG4gICAgICByZXR1cm4gaWQucGlkO1xuICAgIH0gZWxzZSB7XG4gICAgICBsZXQgcGlkID0gdGhpcy5yZWdpc3RlcmVkKGlkKTtcbiAgICAgIGlmIChwaWQgPT09IG51bGwpIHRocm93IFwiUHJvY2VzcyBuYW1lIG5vdCByZWdpc3RlcmVkOiBcIiArIGlkICsgXCIgKFwiICsgdHlwZW9mIGlkICsgXCIpXCI7XG4gICAgICByZXR1cm4gcGlkO1xuICAgIH1cbiAgfVxuXG4gIHB1dChpZCwga2V5LCB2YWx1ZSkge1xuICAgIGxldCBwaWQgPSB0aGlzLnBpZG9mKGlkKTtcbiAgICBsZXQgcHJvY2VzcyA9IHRoaXMucGlkcy5nZXQocGlkKTtcbiAgICBwcm9jZXNzLmRpY3Rba2V5XSA9IHZhbHVlO1xuICB9XG5cbiAgZ2V0KGlkLCBrZXkpIHtcbiAgICBsZXQgcGlkID0gdGhpcy5waWRvZihpZCk7XG4gICAgbGV0IHByb2Nlc3MgPSB0aGlzLnBpZHMuZ2V0KHBpZCk7XG5cbiAgICBpZiAoa2V5ICE9IG51bGwpIHtcbiAgICAgIHJldHVybiBwcm9jZXNzLmRpY3Rba2V5XTtcbiAgICB9IGVsc2Uge1xuICAgICAgcmV0dXJuIHByb2Nlc3MuZGljdDtcbiAgICB9XG4gIH1cblxuICBnZXRfa2V5cyhpZCkge1xuICAgIGxldCBwaWQgPSB0aGlzLnBpZG9mKGlkKTtcbiAgICBsZXQgcHJvY2VzcyA9IHRoaXMucGlkcy5nZXQocGlkKTtcblxuICAgIHJldHVybiBPYmplY3Qua2V5cyhwcm9jZXNzLmRpY3QpO1xuICB9XG5cbiAgZXJhc2UoaWQsIGtleSkge1xuICAgIGxldCBwaWQgPSB0aGlzLnBpZG9mKGlkKTtcbiAgICBsZXQgcHJvY2VzcyA9IHRoaXMucGlkcy5nZXQocGlkKTtcblxuICAgIGlmIChrZXkgIT0gbnVsbCkge1xuICAgICAgZGVsZXRlIHByb2Nlc3MuZGljdFtrZXldO1xuICAgIH0gZWxzZSB7XG4gICAgICBwcm9jZXNzLmRpY3QgPSB7fTtcbiAgICB9XG4gIH1cbn1cblxuY2xhc3MgQml0U3RyaW5nIHtcbiAgY29uc3RydWN0b3IoLi4uYXJncykge1xuICAgIHRoaXMucmF3X3ZhbHVlID0gZnVuY3Rpb24gKCkge1xuICAgICAgcmV0dXJuIE9iamVjdC5mcmVlemUoYXJncyk7XG4gICAgfTtcblxuICAgIHRoaXMudmFsdWUgPSBPYmplY3QuZnJlZXplKHRoaXMucHJvY2VzcyhhcmdzKSk7XG4gIH1cblxuICBnZXQoaW5kZXgpIHtcbiAgICByZXR1cm4gdGhpcy52YWx1ZVtpbmRleF07XG4gIH1cblxuICBjb3VudCgpIHtcbiAgICByZXR1cm4gdGhpcy52YWx1ZS5sZW5ndGg7XG4gIH1cblxuICBbU3ltYm9sLml0ZXJhdG9yXSgpIHtcbiAgICByZXR1cm4gdGhpcy52YWx1ZVtTeW1ib2wuaXRlcmF0b3JdKCk7XG4gIH1cblxuICB0b1N0cmluZygpIHtcbiAgICB2YXIgaSxcbiAgICAgICAgcyA9IFwiXCI7XG4gICAgZm9yIChpID0gMDsgaSA8IHRoaXMuY291bnQoKTsgaSsrKSB7XG4gICAgICBpZiAocyAhPT0gXCJcIikge1xuICAgICAgICBzICs9IFwiLCBcIjtcbiAgICAgIH1cbiAgICAgIHMgKz0gdGhpc1tpXS50b1N0cmluZygpO1xuICAgIH1cblxuICAgIHJldHVybiBcIjw8XCIgKyBzICsgXCI+PlwiO1xuICB9XG5cbiAgcHJvY2VzcygpIHtcbiAgICBsZXQgcHJvY2Vzc2VkX3ZhbHVlcyA9IFtdO1xuXG4gICAgdmFyIGk7XG4gICAgZm9yIChpID0gMDsgaSA8IHRoaXMucmF3X3ZhbHVlKCkubGVuZ3RoOyBpKyspIHtcbiAgICAgIGxldCBwcm9jZXNzZWRfdmFsdWUgPSB0aGlzW1wicHJvY2Vzc19cIiArIHRoaXMucmF3X3ZhbHVlKClbaV0udHlwZV0odGhpcy5yYXdfdmFsdWUoKVtpXSk7XG5cbiAgICAgIGZvciAobGV0IGF0dHIgb2YgdGhpcy5yYXdfdmFsdWUoKVtpXS5hdHRyaWJ1dGVzKSB7XG4gICAgICAgIHByb2Nlc3NlZF92YWx1ZSA9IHRoaXNbXCJwcm9jZXNzX1wiICsgYXR0cl0ocHJvY2Vzc2VkX3ZhbHVlKTtcbiAgICAgIH1cblxuICAgICAgcHJvY2Vzc2VkX3ZhbHVlcyA9IHByb2Nlc3NlZF92YWx1ZXMuY29uY2F0KHByb2Nlc3NlZF92YWx1ZSk7XG4gICAgfVxuXG4gICAgcmV0dXJuIHByb2Nlc3NlZF92YWx1ZXM7XG4gIH1cblxuICBwcm9jZXNzX2ludGVnZXIodmFsdWUpIHtcbiAgICByZXR1cm4gdmFsdWUudmFsdWU7XG4gIH1cblxuICBwcm9jZXNzX2Zsb2F0KHZhbHVlKSB7XG4gICAgaWYgKHZhbHVlLnNpemUgPT09IDY0KSB7XG4gICAgICByZXR1cm4gQml0U3RyaW5nLmZsb2F0NjRUb0J5dGVzKHZhbHVlLnZhbHVlKTtcbiAgICB9IGVsc2UgaWYgKHZhbHVlLnNpemUgPT09IDMyKSB7XG4gICAgICByZXR1cm4gQml0U3RyaW5nLmZsb2F0MzJUb0J5dGVzKHZhbHVlLnZhbHVlKTtcbiAgICB9XG5cbiAgICB0aHJvdyBuZXcgRXJyb3IoXCJJbnZhbGlkIHNpemUgZm9yIGZsb2F0XCIpO1xuICB9XG5cbiAgcHJvY2Vzc19iaXRzdHJpbmcodmFsdWUpIHtcbiAgICByZXR1cm4gdmFsdWUudmFsdWUudmFsdWU7XG4gIH1cblxuICBwcm9jZXNzX2JpbmFyeSh2YWx1ZSkge1xuICAgIHJldHVybiBCaXRTdHJpbmcudG9VVEY4QXJyYXkodmFsdWUudmFsdWUpO1xuICB9XG5cbiAgcHJvY2Vzc191dGY4KHZhbHVlKSB7XG4gICAgcmV0dXJuIEJpdFN0cmluZy50b1VURjhBcnJheSh2YWx1ZS52YWx1ZSk7XG4gIH1cblxuICBwcm9jZXNzX3V0ZjE2KHZhbHVlKSB7XG4gICAgcmV0dXJuIEJpdFN0cmluZy50b1VURjE2QXJyYXkodmFsdWUudmFsdWUpO1xuICB9XG5cbiAgcHJvY2Vzc191dGYzMih2YWx1ZSkge1xuICAgIHJldHVybiBCaXRTdHJpbmcudG9VVEYzMkFycmF5KHZhbHVlLnZhbHVlKTtcbiAgfVxuXG4gIHByb2Nlc3Nfc2lnbmVkKHZhbHVlKSB7XG4gICAgcmV0dXJuIG5ldyBVaW50OEFycmF5KFt2YWx1ZV0pWzBdO1xuICB9XG5cbiAgcHJvY2Vzc191bnNpZ25lZCh2YWx1ZSkge1xuICAgIHJldHVybiB2YWx1ZTtcbiAgfVxuXG4gIHByb2Nlc3NfbmF0aXZlKHZhbHVlKSB7XG4gICAgcmV0dXJuIHZhbHVlO1xuICB9XG5cbiAgcHJvY2Vzc19iaWcodmFsdWUpIHtcbiAgICByZXR1cm4gdmFsdWU7XG4gIH1cblxuICBwcm9jZXNzX2xpdHRsZSh2YWx1ZSkge1xuICAgIHJldHVybiB2YWx1ZS5yZXZlcnNlKCk7XG4gIH1cblxuICBwcm9jZXNzX3NpemUodmFsdWUpIHtcbiAgICByZXR1cm4gdmFsdWU7XG4gIH1cblxuICBwcm9jZXNzX3VuaXQodmFsdWUpIHtcbiAgICByZXR1cm4gdmFsdWU7XG4gIH1cblxuICBzdGF0aWMgaW50ZWdlcih2YWx1ZSkge1xuICAgIHJldHVybiBCaXRTdHJpbmcud3JhcCh2YWx1ZSwgeyBcInR5cGVcIjogXCJpbnRlZ2VyXCIsIFwidW5pdFwiOiAxLCBcInNpemVcIjogOCB9KTtcbiAgfVxuXG4gIHN0YXRpYyBmbG9hdCh2YWx1ZSkge1xuICAgIHJldHVybiBCaXRTdHJpbmcud3JhcCh2YWx1ZSwgeyBcInR5cGVcIjogXCJmbG9hdFwiLCBcInVuaXRcIjogMSwgXCJzaXplXCI6IDY0IH0pO1xuICB9XG5cbiAgc3RhdGljIGJpdHN0cmluZyh2YWx1ZSkge1xuICAgIHJldHVybiBCaXRTdHJpbmcud3JhcCh2YWx1ZSwgeyBcInR5cGVcIjogXCJiaXRzdHJpbmdcIiwgXCJ1bml0XCI6IDEsIFwic2l6ZVwiOiB2YWx1ZS5sZW5ndGggfSk7XG4gIH1cblxuICBzdGF0aWMgYml0cyh2YWx1ZSkge1xuICAgIHJldHVybiBCaXRTdHJpbmcuYml0c3RyaW5nKHZhbHVlKTtcbiAgfVxuXG4gIHN0YXRpYyBiaW5hcnkodmFsdWUpIHtcbiAgICByZXR1cm4gQml0U3RyaW5nLndyYXAodmFsdWUsIHsgXCJ0eXBlXCI6IFwiYmluYXJ5XCIsIFwidW5pdFwiOiA4LCBcInNpemVcIjogdmFsdWUubGVuZ3RoIH0pO1xuICB9XG5cbiAgc3RhdGljIGJ5dGVzKHZhbHVlKSB7XG4gICAgcmV0dXJuIEJpdFN0cmluZy5iaW5hcnkodmFsdWUpO1xuICB9XG5cbiAgc3RhdGljIHV0ZjgodmFsdWUpIHtcbiAgICByZXR1cm4gQml0U3RyaW5nLndyYXAodmFsdWUsIHsgXCJ0eXBlXCI6IFwidXRmOFwiIH0pO1xuICB9XG5cbiAgc3RhdGljIHV0ZjE2KHZhbHVlKSB7XG4gICAgcmV0dXJuIEJpdFN0cmluZy53cmFwKHZhbHVlLCB7IFwidHlwZVwiOiBcInV0ZjE2XCIgfSk7XG4gIH1cblxuICBzdGF0aWMgdXRmMzIodmFsdWUpIHtcbiAgICByZXR1cm4gQml0U3RyaW5nLndyYXAodmFsdWUsIHsgXCJ0eXBlXCI6IFwidXRmMzJcIiB9KTtcbiAgfVxuXG4gIHN0YXRpYyBzaWduZWQodmFsdWUpIHtcbiAgICByZXR1cm4gQml0U3RyaW5nLndyYXAodmFsdWUsIHt9LCBcInNpZ25lZFwiKTtcbiAgfVxuXG4gIHN0YXRpYyB1bnNpZ25lZCh2YWx1ZSkge1xuICAgIHJldHVybiBCaXRTdHJpbmcud3JhcCh2YWx1ZSwge30sIFwidW5zaWduZWRcIik7XG4gIH1cblxuICBzdGF0aWMgbmF0aXZlKHZhbHVlKSB7XG4gICAgcmV0dXJuIEJpdFN0cmluZy53cmFwKHZhbHVlLCB7fSwgXCJuYXRpdmVcIik7XG4gIH1cblxuICBzdGF0aWMgYmlnKHZhbHVlKSB7XG4gICAgcmV0dXJuIEJpdFN0cmluZy53cmFwKHZhbHVlLCB7fSwgXCJiaWdcIik7XG4gIH1cblxuICBzdGF0aWMgbGl0dGxlKHZhbHVlKSB7XG4gICAgcmV0dXJuIEJpdFN0cmluZy53cmFwKHZhbHVlLCB7fSwgXCJsaXR0bGVcIik7XG4gIH1cblxuICBzdGF0aWMgc2l6ZSh2YWx1ZSwgY291bnQpIHtcbiAgICByZXR1cm4gQml0U3RyaW5nLndyYXAodmFsdWUsIHsgXCJzaXplXCI6IGNvdW50IH0pO1xuICB9XG5cbiAgc3RhdGljIHVuaXQodmFsdWUsIGNvdW50KSB7XG4gICAgcmV0dXJuIEJpdFN0cmluZy53cmFwKHZhbHVlLCB7IFwidW5pdFwiOiBjb3VudCB9KTtcbiAgfVxuXG4gIHN0YXRpYyB3cmFwKHZhbHVlLCBvcHQsIG5ld19hdHRyaWJ1dGUgPSBudWxsKSB7XG4gICAgbGV0IHRoZV92YWx1ZSA9IHZhbHVlO1xuXG4gICAgaWYgKCEodmFsdWUgaW5zdGFuY2VvZiBPYmplY3QpKSB7XG4gICAgICB0aGVfdmFsdWUgPSB7IFwidmFsdWVcIjogdmFsdWUsIFwiYXR0cmlidXRlc1wiOiBbXSB9O1xuICAgIH1cblxuICAgIHRoZV92YWx1ZSA9IE9iamVjdC5hc3NpZ24odGhlX3ZhbHVlLCBvcHQpO1xuXG4gICAgaWYgKG5ld19hdHRyaWJ1dGUpIHtcbiAgICAgIHRoZV92YWx1ZS5hdHRyaWJ1dGVzLnB1c2gobmV3X2F0dHJpYnV0ZSk7XG4gICAgfVxuXG4gICAgcmV0dXJuIHRoZV92YWx1ZTtcbiAgfVxuXG4gIHN0YXRpYyB0b1VURjhBcnJheShzdHIpIHtcbiAgICB2YXIgdXRmOCA9IFtdO1xuICAgIGZvciAodmFyIGkgPSAwOyBpIDwgc3RyLmxlbmd0aDsgaSsrKSB7XG4gICAgICB2YXIgY2hhcmNvZGUgPSBzdHIuY2hhckNvZGVBdChpKTtcbiAgICAgIGlmIChjaGFyY29kZSA8IDEyOCkge1xuICAgICAgICB1dGY4LnB1c2goY2hhcmNvZGUpO1xuICAgICAgfSBlbHNlIGlmIChjaGFyY29kZSA8IDIwNDgpIHtcbiAgICAgICAgdXRmOC5wdXNoKDE5MiB8IGNoYXJjb2RlID4+IDYsIDEyOCB8IGNoYXJjb2RlICYgNjMpO1xuICAgICAgfSBlbHNlIGlmIChjaGFyY29kZSA8IDU1Mjk2IHx8IGNoYXJjb2RlID49IDU3MzQ0KSB7XG4gICAgICAgIHV0ZjgucHVzaCgyMjQgfCBjaGFyY29kZSA+PiAxMiwgMTI4IHwgY2hhcmNvZGUgPj4gNiAmIDYzLCAxMjggfCBjaGFyY29kZSAmIDYzKTtcbiAgICAgIH1cbiAgICAgIC8vIHN1cnJvZ2F0ZSBwYWlyXG4gICAgICBlbHNlIHtcbiAgICAgICAgaSsrO1xuICAgICAgICAvLyBVVEYtMTYgZW5jb2RlcyAweDEwMDAwLTB4MTBGRkZGIGJ5XG4gICAgICAgIC8vIHN1YnRyYWN0aW5nIDB4MTAwMDAgYW5kIHNwbGl0dGluZyB0aGVcbiAgICAgICAgLy8gMjAgYml0cyBvZiAweDAtMHhGRkZGRiBpbnRvIHR3byBoYWx2ZXNcbiAgICAgICAgY2hhcmNvZGUgPSA2NTUzNiArICgoY2hhcmNvZGUgJiAxMDIzKSA8PCAxMCB8IHN0ci5jaGFyQ29kZUF0KGkpICYgMTAyMyk7XG4gICAgICAgIHV0ZjgucHVzaCgyNDAgfCBjaGFyY29kZSA+PiAxOCwgMTI4IHwgY2hhcmNvZGUgPj4gMTIgJiA2MywgMTI4IHwgY2hhcmNvZGUgPj4gNiAmIDYzLCAxMjggfCBjaGFyY29kZSAmIDYzKTtcbiAgICAgIH1cbiAgICB9XG4gICAgcmV0dXJuIHV0Zjg7XG4gIH1cblxuICBzdGF0aWMgdG9VVEYxNkFycmF5KHN0cikge1xuICAgIHZhciB1dGYxNiA9IFtdO1xuICAgIGZvciAodmFyIGkgPSAwOyBpIDwgc3RyLmxlbmd0aDsgaSsrKSB7XG4gICAgICB2YXIgY29kZVBvaW50ID0gc3RyLmNvZGVQb2ludEF0KGkpO1xuXG4gICAgICBpZiAoY29kZVBvaW50IDw9IDI1NSkge1xuICAgICAgICB1dGYxNi5wdXNoKDApO1xuICAgICAgICB1dGYxNi5wdXNoKGNvZGVQb2ludCk7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICB1dGYxNi5wdXNoKGNvZGVQb2ludCA+PiA4ICYgMjU1KTtcbiAgICAgICAgdXRmMTYucHVzaChjb2RlUG9pbnQgJiAyNTUpO1xuICAgICAgfVxuICAgIH1cbiAgICByZXR1cm4gdXRmMTY7XG4gIH1cblxuICBzdGF0aWMgdG9VVEYzMkFycmF5KHN0cikge1xuICAgIHZhciB1dGYzMiA9IFtdO1xuICAgIGZvciAodmFyIGkgPSAwOyBpIDwgc3RyLmxlbmd0aDsgaSsrKSB7XG4gICAgICB2YXIgY29kZVBvaW50ID0gc3RyLmNvZGVQb2ludEF0KGkpO1xuXG4gICAgICBpZiAoY29kZVBvaW50IDw9IDI1NSkge1xuICAgICAgICB1dGYzMi5wdXNoKDApO1xuICAgICAgICB1dGYzMi5wdXNoKDApO1xuICAgICAgICB1dGYzMi5wdXNoKDApO1xuICAgICAgICB1dGYzMi5wdXNoKGNvZGVQb2ludCk7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICB1dGYzMi5wdXNoKDApO1xuICAgICAgICB1dGYzMi5wdXNoKDApO1xuICAgICAgICB1dGYzMi5wdXNoKGNvZGVQb2ludCA+PiA4ICYgMjU1KTtcbiAgICAgICAgdXRmMzIucHVzaChjb2RlUG9pbnQgJiAyNTUpO1xuICAgICAgfVxuICAgIH1cbiAgICByZXR1cm4gdXRmMzI7XG4gIH1cblxuICAvL2h0dHA6Ly9zdGFja292ZXJmbG93LmNvbS9xdWVzdGlvbnMvMjAwMzQ5My9qYXZhc2NyaXB0LWZsb2F0LWZyb20tdG8tYml0c1xuICBzdGF0aWMgZmxvYXQzMlRvQnl0ZXMoZikge1xuICAgIHZhciBieXRlcyA9IFtdO1xuXG4gICAgdmFyIGJ1ZiA9IG5ldyBBcnJheUJ1ZmZlcig0KTtcbiAgICBuZXcgRmxvYXQzMkFycmF5KGJ1ZilbMF0gPSBmO1xuXG4gICAgbGV0IGludFZlcnNpb24gPSBuZXcgVWludDMyQXJyYXkoYnVmKVswXTtcblxuICAgIGJ5dGVzLnB1c2goaW50VmVyc2lvbiA+PiAyNCAmIDI1NSk7XG4gICAgYnl0ZXMucHVzaChpbnRWZXJzaW9uID4+IDE2ICYgMjU1KTtcbiAgICBieXRlcy5wdXNoKGludFZlcnNpb24gPj4gOCAmIDI1NSk7XG4gICAgYnl0ZXMucHVzaChpbnRWZXJzaW9uICYgMjU1KTtcblxuICAgIHJldHVybiBieXRlcztcbiAgfVxuXG4gIHN0YXRpYyBmbG9hdDY0VG9CeXRlcyhmKSB7XG4gICAgdmFyIGJ5dGVzID0gW107XG5cbiAgICB2YXIgYnVmID0gbmV3IEFycmF5QnVmZmVyKDgpO1xuICAgIG5ldyBGbG9hdDY0QXJyYXkoYnVmKVswXSA9IGY7XG5cbiAgICB2YXIgaW50VmVyc2lvbjEgPSBuZXcgVWludDMyQXJyYXkoYnVmKVswXTtcbiAgICB2YXIgaW50VmVyc2lvbjIgPSBuZXcgVWludDMyQXJyYXkoYnVmKVsxXTtcblxuICAgIGJ5dGVzLnB1c2goaW50VmVyc2lvbjIgPj4gMjQgJiAyNTUpO1xuICAgIGJ5dGVzLnB1c2goaW50VmVyc2lvbjIgPj4gMTYgJiAyNTUpO1xuICAgIGJ5dGVzLnB1c2goaW50VmVyc2lvbjIgPj4gOCAmIDI1NSk7XG4gICAgYnl0ZXMucHVzaChpbnRWZXJzaW9uMiAmIDI1NSk7XG5cbiAgICBieXRlcy5wdXNoKGludFZlcnNpb24xID4+IDI0ICYgMjU1KTtcbiAgICBieXRlcy5wdXNoKGludFZlcnNpb24xID4+IDE2ICYgMjU1KTtcbiAgICBieXRlcy5wdXNoKGludFZlcnNpb24xID4+IDggJiAyNTUpO1xuICAgIGJ5dGVzLnB1c2goaW50VmVyc2lvbjEgJiAyNTUpO1xuXG4gICAgcmV0dXJuIGJ5dGVzO1xuICB9XG59XG5cbi8qIEBmbG93ICovXG5cbmNsYXNzIFZhcmlhYmxlIHtcblxuICBjb25zdHJ1Y3RvcihuYW1lID0gbnVsbCkge1xuICAgIHRoaXMubmFtZSA9IG5hbWU7XG4gIH1cbn1cblxuY2xhc3MgV2lsZGNhcmQge1xuICBjb25zdHJ1Y3RvcigpIHt9XG59XG5cbmNsYXNzIFN0YXJ0c1dpdGgge1xuXG4gIGNvbnN0cnVjdG9yKHByZWZpeCkge1xuICAgIHRoaXMucHJlZml4ID0gcHJlZml4O1xuICB9XG59XG5cbmNsYXNzIENhcHR1cmUge1xuXG4gIGNvbnN0cnVjdG9yKHZhbHVlKSB7XG4gICAgdGhpcy52YWx1ZSA9IHZhbHVlO1xuICB9XG59XG5cbmNsYXNzIEhlYWRUYWlsIHtcbiAgY29uc3RydWN0b3IoKSB7fVxufVxuXG5jbGFzcyBUeXBlIHtcblxuICBjb25zdHJ1Y3Rvcih0eXBlLCBvYmpQYXR0ZXJuID0ge30pIHtcbiAgICB0aGlzLnR5cGUgPSB0eXBlO1xuICAgIHRoaXMub2JqUGF0dGVybiA9IG9ialBhdHRlcm47XG4gIH1cbn1cblxuY2xhc3MgQm91bmQge1xuXG4gIGNvbnN0cnVjdG9yKHZhbHVlKSB7XG4gICAgdGhpcy52YWx1ZSA9IHZhbHVlO1xuICB9XG59XG5cbmZ1bmN0aW9uIHZhcmlhYmxlKG5hbWUgPSBudWxsKSB7XG4gIHJldHVybiBuZXcgVmFyaWFibGUobmFtZSk7XG59XG5cbmZ1bmN0aW9uIHdpbGRjYXJkKCkge1xuICByZXR1cm4gbmV3IFdpbGRjYXJkKCk7XG59XG5cbmZ1bmN0aW9uIHN0YXJ0c1dpdGgocHJlZml4KSB7XG4gIHJldHVybiBuZXcgU3RhcnRzV2l0aChwcmVmaXgpO1xufVxuXG5mdW5jdGlvbiBjYXB0dXJlKHZhbHVlKSB7XG4gIHJldHVybiBuZXcgQ2FwdHVyZSh2YWx1ZSk7XG59XG5cbmZ1bmN0aW9uIGhlYWRUYWlsKCkge1xuICByZXR1cm4gbmV3IEhlYWRUYWlsKCk7XG59XG5cbmZ1bmN0aW9uIHR5cGUodHlwZSwgb2JqUGF0dGVybiA9IHt9KSB7XG4gIHJldHVybiBuZXcgVHlwZSh0eXBlLCBvYmpQYXR0ZXJuKTtcbn1cblxuZnVuY3Rpb24gYm91bmQodmFsdWUpIHtcbiAgcmV0dXJuIG5ldyBCb3VuZCh2YWx1ZSk7XG59XG5cbmZ1bmN0aW9uIGlzX251bWJlcih2YWx1ZSkge1xuICByZXR1cm4gdHlwZW9mIHZhbHVlID09PSAnbnVtYmVyJztcbn1cblxuZnVuY3Rpb24gaXNfc3RyaW5nKHZhbHVlKSB7XG4gIHJldHVybiB0eXBlb2YgdmFsdWUgPT09ICdzdHJpbmcnO1xufVxuXG5mdW5jdGlvbiBpc19ib29sZWFuKHZhbHVlKSB7XG4gIHJldHVybiB0eXBlb2YgdmFsdWUgPT09ICdib29sZWFuJztcbn1cblxuZnVuY3Rpb24gaXNfc3ltYm9sKHZhbHVlKSB7XG4gIHJldHVybiB0eXBlb2YgdmFsdWUgPT09ICdzeW1ib2wnO1xufVxuXG5mdW5jdGlvbiBpc19udWxsKHZhbHVlKSB7XG4gIHJldHVybiB2YWx1ZSA9PT0gbnVsbDtcbn1cblxuZnVuY3Rpb24gaXNfdW5kZWZpbmVkKHZhbHVlKSB7XG4gIHJldHVybiB0eXBlb2YgdmFsdWUgPT09ICd1bmRlZmluZWQnO1xufVxuXG5mdW5jdGlvbiBpc19mdW5jdGlvbih2YWx1ZSkge1xuICByZXR1cm4gT2JqZWN0LnByb3RvdHlwZS50b1N0cmluZy5jYWxsKHZhbHVlKSA9PSAnW29iamVjdCBGdW5jdGlvbl0nO1xufVxuXG5mdW5jdGlvbiBpc192YXJpYWJsZSh2YWx1ZSkge1xuICByZXR1cm4gdmFsdWUgaW5zdGFuY2VvZiBWYXJpYWJsZTtcbn1cblxuZnVuY3Rpb24gaXNfd2lsZGNhcmQodmFsdWUpIHtcbiAgcmV0dXJuIHZhbHVlIGluc3RhbmNlb2YgV2lsZGNhcmQ7XG59XG5cbmZ1bmN0aW9uIGlzX2hlYWRUYWlsKHZhbHVlKSB7XG4gIHJldHVybiB2YWx1ZSBpbnN0YW5jZW9mIEhlYWRUYWlsO1xufVxuXG5mdW5jdGlvbiBpc19jYXB0dXJlKHZhbHVlKSB7XG4gIHJldHVybiB2YWx1ZSBpbnN0YW5jZW9mIENhcHR1cmU7XG59XG5cbmZ1bmN0aW9uIGlzX3R5cGUodmFsdWUpIHtcbiAgcmV0dXJuIHZhbHVlIGluc3RhbmNlb2YgVHlwZTtcbn1cblxuZnVuY3Rpb24gaXNfc3RhcnRzV2l0aCh2YWx1ZSkge1xuICByZXR1cm4gdmFsdWUgaW5zdGFuY2VvZiBTdGFydHNXaXRoO1xufVxuXG5mdW5jdGlvbiBpc19ib3VuZCh2YWx1ZSkge1xuICByZXR1cm4gdmFsdWUgaW5zdGFuY2VvZiBCb3VuZDtcbn1cblxuZnVuY3Rpb24gaXNfb2JqZWN0KHZhbHVlKSB7XG4gIHJldHVybiB0eXBlb2YgdmFsdWUgPT09ICdvYmplY3QnO1xufVxuXG5mdW5jdGlvbiBpc19hcnJheSh2YWx1ZSkge1xuICByZXR1cm4gQXJyYXkuaXNBcnJheSh2YWx1ZSk7XG59XG5cbnZhciBDaGVja3MgPSB7XG4gIGlzX251bWJlcixcbiAgaXNfc3RyaW5nLFxuICBpc19ib29sZWFuLFxuICBpc19zeW1ib2wsXG4gIGlzX251bGwsXG4gIGlzX3VuZGVmaW5lZCxcbiAgaXNfZnVuY3Rpb24sXG4gIGlzX3ZhcmlhYmxlLFxuICBpc193aWxkY2FyZCxcbiAgaXNfaGVhZFRhaWwsXG4gIGlzX2NhcHR1cmUsXG4gIGlzX3R5cGUsXG4gIGlzX3N0YXJ0c1dpdGgsXG4gIGlzX2JvdW5kLFxuICBpc19vYmplY3QsXG4gIGlzX2FycmF5XG59O1xuXG5mdW5jdGlvbiByZXNvbHZlU3ltYm9sKHBhdHRlcm4pIHtcbiAgcmV0dXJuIGZ1bmN0aW9uICh2YWx1ZSkge1xuICAgIHJldHVybiBDaGVja3MuaXNfc3ltYm9sKHZhbHVlKSAmJiB2YWx1ZSA9PT0gcGF0dGVybjtcbiAgfTtcbn1cblxuZnVuY3Rpb24gcmVzb2x2ZVN0cmluZyhwYXR0ZXJuKSB7XG4gIHJldHVybiBmdW5jdGlvbiAodmFsdWUpIHtcbiAgICByZXR1cm4gQ2hlY2tzLmlzX3N0cmluZyh2YWx1ZSkgJiYgdmFsdWUgPT09IHBhdHRlcm47XG4gIH07XG59XG5cbmZ1bmN0aW9uIHJlc29sdmVOdW1iZXIocGF0dGVybikge1xuICByZXR1cm4gZnVuY3Rpb24gKHZhbHVlKSB7XG4gICAgcmV0dXJuIENoZWNrcy5pc19udW1iZXIodmFsdWUpICYmIHZhbHVlID09PSBwYXR0ZXJuO1xuICB9O1xufVxuXG5mdW5jdGlvbiByZXNvbHZlQm9vbGVhbihwYXR0ZXJuKSB7XG4gIHJldHVybiBmdW5jdGlvbiAodmFsdWUpIHtcbiAgICByZXR1cm4gQ2hlY2tzLmlzX2Jvb2xlYW4odmFsdWUpICYmIHZhbHVlID09PSBwYXR0ZXJuO1xuICB9O1xufVxuXG5mdW5jdGlvbiByZXNvbHZlRnVuY3Rpb24ocGF0dGVybikge1xuICByZXR1cm4gZnVuY3Rpb24gKHZhbHVlKSB7XG4gICAgcmV0dXJuIENoZWNrcy5pc19mdW5jdGlvbih2YWx1ZSkgJiYgdmFsdWUgPT09IHBhdHRlcm47XG4gIH07XG59XG5cbmZ1bmN0aW9uIHJlc29sdmVOdWxsKHBhdHRlcm4pIHtcbiAgcmV0dXJuIGZ1bmN0aW9uICh2YWx1ZSkge1xuICAgIHJldHVybiBDaGVja3MuaXNfbnVsbCh2YWx1ZSk7XG4gIH07XG59XG5cbmZ1bmN0aW9uIHJlc29sdmVCb3VuZChwYXR0ZXJuKSB7XG4gIHJldHVybiBmdW5jdGlvbiAodmFsdWUsIGFyZ3MpIHtcbiAgICBpZiAodHlwZW9mIHZhbHVlID09PSB0eXBlb2YgcGF0dGVybi52YWx1ZSAmJiB2YWx1ZSA9PT0gcGF0dGVybi52YWx1ZSkge1xuICAgICAgYXJncy5wdXNoKHZhbHVlKTtcbiAgICAgIHJldHVybiB0cnVlO1xuICAgIH1cblxuICAgIHJldHVybiBmYWxzZTtcbiAgfTtcbn1cblxuZnVuY3Rpb24gcmVzb2x2ZVdpbGRjYXJkKCkge1xuICByZXR1cm4gZnVuY3Rpb24gKCkge1xuICAgIHJldHVybiB0cnVlO1xuICB9O1xufVxuXG5mdW5jdGlvbiByZXNvbHZlVmFyaWFibGUoKSB7XG4gIHJldHVybiBmdW5jdGlvbiAodmFsdWUsIGFyZ3MpIHtcbiAgICBhcmdzLnB1c2godmFsdWUpO1xuICAgIHJldHVybiB0cnVlO1xuICB9O1xufVxuXG5mdW5jdGlvbiByZXNvbHZlSGVhZFRhaWwoKSB7XG4gIHJldHVybiBmdW5jdGlvbiAodmFsdWUsIGFyZ3MpIHtcbiAgICBpZiAoIUNoZWNrcy5pc19hcnJheSh2YWx1ZSkgfHwgdmFsdWUubGVuZ3RoIDwgMikge1xuICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH1cblxuICAgIGNvbnN0IGhlYWQgPSB2YWx1ZVswXTtcbiAgICBjb25zdCB0YWlsID0gdmFsdWUuc2xpY2UoMSk7XG5cbiAgICBhcmdzLnB1c2goaGVhZCk7XG4gICAgYXJncy5wdXNoKHRhaWwpO1xuXG4gICAgcmV0dXJuIHRydWU7XG4gIH07XG59XG5cbmZ1bmN0aW9uIHJlc29sdmVDYXB0dXJlKHBhdHRlcm4pIHtcbiAgY29uc3QgbWF0Y2hlcyA9IGJ1aWxkTWF0Y2gocGF0dGVybi52YWx1ZSk7XG5cbiAgcmV0dXJuIGZ1bmN0aW9uICh2YWx1ZSwgYXJncykge1xuICAgIGlmIChtYXRjaGVzKHZhbHVlLCBhcmdzKSkge1xuICAgICAgYXJncy5wdXNoKHZhbHVlKTtcbiAgICAgIHJldHVybiB0cnVlO1xuICAgIH1cblxuICAgIHJldHVybiBmYWxzZTtcbiAgfTtcbn1cblxuZnVuY3Rpb24gcmVzb2x2ZVN0YXJ0c1dpdGgocGF0dGVybikge1xuICBjb25zdCBwcmVmaXggPSBwYXR0ZXJuLnByZWZpeDtcblxuICByZXR1cm4gZnVuY3Rpb24gKHZhbHVlLCBhcmdzKSB7XG4gICAgaWYgKENoZWNrcy5pc19zdHJpbmcodmFsdWUpICYmIHZhbHVlLnN0YXJ0c1dpdGgocHJlZml4KSkge1xuICAgICAgYXJncy5wdXNoKHZhbHVlLnN1YnN0cmluZyhwcmVmaXgubGVuZ3RoKSk7XG4gICAgICByZXR1cm4gdHJ1ZTtcbiAgICB9XG5cbiAgICByZXR1cm4gZmFsc2U7XG4gIH07XG59XG5cbmZ1bmN0aW9uIHJlc29sdmVUeXBlKHBhdHRlcm4pIHtcbiAgcmV0dXJuIGZ1bmN0aW9uICh2YWx1ZSwgYXJncykge1xuICAgIGlmICh2YWx1ZSBpbnN0YW5jZW9mIHBhdHRlcm4udHlwZSkge1xuICAgICAgY29uc3QgbWF0Y2hlcyA9IGJ1aWxkTWF0Y2gocGF0dGVybi5vYmpQYXR0ZXJuKTtcbiAgICAgIHJldHVybiBtYXRjaGVzKHZhbHVlLCBhcmdzKSAmJiBhcmdzLnB1c2godmFsdWUpID4gMDtcbiAgICB9XG5cbiAgICByZXR1cm4gZmFsc2U7XG4gIH07XG59XG5cbmZ1bmN0aW9uIHJlc29sdmVBcnJheShwYXR0ZXJuKSB7XG4gIGNvbnN0IG1hdGNoZXMgPSBwYXR0ZXJuLm1hcCh4ID0+IGJ1aWxkTWF0Y2goeCkpO1xuXG4gIHJldHVybiBmdW5jdGlvbiAodmFsdWUsIGFyZ3MpIHtcbiAgICBpZiAoIUNoZWNrcy5pc19hcnJheSh2YWx1ZSkgfHwgdmFsdWUubGVuZ3RoICE9IHBhdHRlcm4ubGVuZ3RoKSB7XG4gICAgICByZXR1cm4gZmFsc2U7XG4gICAgfVxuXG4gICAgcmV0dXJuIHZhbHVlLmV2ZXJ5KGZ1bmN0aW9uICh2LCBpKSB7XG4gICAgICByZXR1cm4gbWF0Y2hlc1tpXSh2YWx1ZVtpXSwgYXJncyk7XG4gICAgfSk7XG4gIH07XG59XG5cbmZ1bmN0aW9uIHJlc29sdmVPYmplY3QocGF0dGVybikge1xuICBsZXQgbWF0Y2hlcyA9IHt9O1xuXG4gIGZvciAobGV0IGtleSBvZiBPYmplY3Qua2V5cyhwYXR0ZXJuKS5jb25jYXQoT2JqZWN0LmdldE93blByb3BlcnR5U3ltYm9scyhwYXR0ZXJuKSkpIHtcbiAgICBtYXRjaGVzW2tleV0gPSBidWlsZE1hdGNoKHBhdHRlcm5ba2V5XSk7XG4gIH1cblxuICByZXR1cm4gZnVuY3Rpb24gKHZhbHVlLCBhcmdzKSB7XG4gICAgaWYgKCFDaGVja3MuaXNfb2JqZWN0KHZhbHVlKSB8fCBwYXR0ZXJuLmxlbmd0aCA+IHZhbHVlLmxlbmd0aCkge1xuICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH1cblxuICAgIGZvciAobGV0IGtleSBvZiBPYmplY3Qua2V5cyhwYXR0ZXJuKS5jb25jYXQoT2JqZWN0LmdldE93blByb3BlcnR5U3ltYm9scyhwYXR0ZXJuKSkpIHtcbiAgICAgIGlmICghKGtleSBpbiB2YWx1ZSkgfHwgIW1hdGNoZXNba2V5XSh2YWx1ZVtrZXldLCBhcmdzKSkge1xuICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICB9XG4gICAgfVxuXG4gICAgcmV0dXJuIHRydWU7XG4gIH07XG59XG5cbmZ1bmN0aW9uIHJlc29sdmVOb01hdGNoKCkge1xuICByZXR1cm4gZnVuY3Rpb24gKCkge1xuICAgIHJldHVybiBmYWxzZTtcbiAgfTtcbn1cblxudmFyIFJlc29sdmVycyA9IHtcbiAgcmVzb2x2ZUJvdW5kLFxuICByZXNvbHZlV2lsZGNhcmQsXG4gIHJlc29sdmVWYXJpYWJsZSxcbiAgcmVzb2x2ZUhlYWRUYWlsLFxuICByZXNvbHZlQ2FwdHVyZSxcbiAgcmVzb2x2ZVN0YXJ0c1dpdGgsXG4gIHJlc29sdmVUeXBlLFxuICByZXNvbHZlQXJyYXksXG4gIHJlc29sdmVPYmplY3QsXG4gIHJlc29sdmVOb01hdGNoLFxuICByZXNvbHZlU3ltYm9sLFxuICByZXNvbHZlU3RyaW5nLFxuICByZXNvbHZlTnVtYmVyLFxuICByZXNvbHZlQm9vbGVhbixcbiAgcmVzb2x2ZUZ1bmN0aW9uLFxuICByZXNvbHZlTnVsbFxufTtcblxuZnVuY3Rpb24gYnVpbGRNYXRjaChwYXR0ZXJuKSB7XG5cbiAgaWYgKENoZWNrcy5pc192YXJpYWJsZShwYXR0ZXJuKSkge1xuICAgIHJldHVybiBSZXNvbHZlcnMucmVzb2x2ZVZhcmlhYmxlKHBhdHRlcm4pO1xuICB9XG5cbiAgaWYgKENoZWNrcy5pc193aWxkY2FyZChwYXR0ZXJuKSkge1xuICAgIHJldHVybiBSZXNvbHZlcnMucmVzb2x2ZVdpbGRjYXJkKHBhdHRlcm4pO1xuICB9XG5cbiAgaWYgKENoZWNrcy5pc191bmRlZmluZWQocGF0dGVybikpIHtcbiAgICByZXR1cm4gUmVzb2x2ZXJzLnJlc29sdmVXaWxkY2FyZChwYXR0ZXJuKTtcbiAgfVxuXG4gIGlmIChDaGVja3MuaXNfaGVhZFRhaWwocGF0dGVybikpIHtcbiAgICByZXR1cm4gUmVzb2x2ZXJzLnJlc29sdmVIZWFkVGFpbChwYXR0ZXJuKTtcbiAgfVxuXG4gIGlmIChDaGVja3MuaXNfc3RhcnRzV2l0aChwYXR0ZXJuKSkge1xuICAgIHJldHVybiBSZXNvbHZlcnMucmVzb2x2ZVN0YXJ0c1dpdGgocGF0dGVybik7XG4gIH1cblxuICBpZiAoQ2hlY2tzLmlzX2NhcHR1cmUocGF0dGVybikpIHtcbiAgICByZXR1cm4gUmVzb2x2ZXJzLnJlc29sdmVDYXB0dXJlKHBhdHRlcm4pO1xuICB9XG5cbiAgaWYgKENoZWNrcy5pc19ib3VuZChwYXR0ZXJuKSkge1xuICAgIHJldHVybiBSZXNvbHZlcnMucmVzb2x2ZUJvdW5kKHBhdHRlcm4pO1xuICB9XG5cbiAgaWYgKENoZWNrcy5pc190eXBlKHBhdHRlcm4pKSB7XG4gICAgcmV0dXJuIFJlc29sdmVycy5yZXNvbHZlVHlwZShwYXR0ZXJuKTtcbiAgfVxuXG4gIGlmIChDaGVja3MuaXNfYXJyYXkocGF0dGVybikpIHtcbiAgICByZXR1cm4gUmVzb2x2ZXJzLnJlc29sdmVBcnJheShwYXR0ZXJuKTtcbiAgfVxuXG4gIGlmIChDaGVja3MuaXNfbnVtYmVyKHBhdHRlcm4pKSB7XG4gICAgcmV0dXJuIFJlc29sdmVycy5yZXNvbHZlTnVtYmVyKHBhdHRlcm4pO1xuICB9XG5cbiAgaWYgKENoZWNrcy5pc19zdHJpbmcocGF0dGVybikpIHtcbiAgICByZXR1cm4gUmVzb2x2ZXJzLnJlc29sdmVTdHJpbmcocGF0dGVybik7XG4gIH1cblxuICBpZiAoQ2hlY2tzLmlzX2Jvb2xlYW4ocGF0dGVybikpIHtcbiAgICByZXR1cm4gUmVzb2x2ZXJzLnJlc29sdmVCb29sZWFuKHBhdHRlcm4pO1xuICB9XG5cbiAgaWYgKENoZWNrcy5pc19zeW1ib2wocGF0dGVybikpIHtcbiAgICByZXR1cm4gUmVzb2x2ZXJzLnJlc29sdmVTeW1ib2wocGF0dGVybik7XG4gIH1cblxuICBpZiAoQ2hlY2tzLmlzX251bGwocGF0dGVybikpIHtcbiAgICByZXR1cm4gUmVzb2x2ZXJzLnJlc29sdmVOdWxsKHBhdHRlcm4pO1xuICB9XG5cbiAgaWYgKENoZWNrcy5pc19vYmplY3QocGF0dGVybikpIHtcbiAgICByZXR1cm4gUmVzb2x2ZXJzLnJlc29sdmVPYmplY3QocGF0dGVybik7XG4gIH1cblxuICByZXR1cm4gUmVzb2x2ZXJzLnJlc29sdmVOb01hdGNoKCk7XG59XG5cbmNsYXNzIE1hdGNoRXJyb3IgZXh0ZW5kcyBFcnJvciB7XG4gIGNvbnN0cnVjdG9yKGFyZykge1xuICAgIHN1cGVyKCk7XG5cbiAgICBpZiAodHlwZW9mIGFyZyA9PT0gJ3N5bWJvbCcpIHtcbiAgICAgIHRoaXMubWVzc2FnZSA9ICdObyBtYXRjaCBmb3I6ICcgKyBhcmcudG9TdHJpbmcoKTtcbiAgICB9IGVsc2UgaWYgKEFycmF5LmlzQXJyYXkoYXJnKSkge1xuICAgICAgbGV0IG1hcHBlZFZhbHVlcyA9IGFyZy5tYXAoeCA9PiB4LnRvU3RyaW5nKCkpO1xuICAgICAgdGhpcy5tZXNzYWdlID0gJ05vIG1hdGNoIGZvcjogJyArIG1hcHBlZFZhbHVlcztcbiAgICB9IGVsc2Uge1xuICAgICAgdGhpcy5tZXNzYWdlID0gJ05vIG1hdGNoIGZvcjogJyArIGFyZztcbiAgICB9XG5cbiAgICB0aGlzLnN0YWNrID0gbmV3IEVycm9yKCkuc3RhY2s7XG4gICAgdGhpcy5uYW1lID0gdGhpcy5jb25zdHJ1Y3Rvci5uYW1lO1xuICB9XG59XG5cbmNsYXNzIENhc2Uge1xuXG4gIGNvbnN0cnVjdG9yKHBhdHRlcm4sIGZuLCBndWFyZCA9ICgpID0+IHRydWUpIHtcbiAgICB0aGlzLnBhdHRlcm4gPSBidWlsZE1hdGNoKHBhdHRlcm4pO1xuICAgIHRoaXMuZm4gPSBmbjtcbiAgICB0aGlzLmd1YXJkID0gZ3VhcmQ7XG4gIH1cbn1cblxuZnVuY3Rpb24gbWFrZV9jYXNlKHBhdHRlcm4sIGZuLCBndWFyZCA9ICgpID0+IHRydWUpIHtcbiAgcmV0dXJuIG5ldyBDYXNlKHBhdHRlcm4sIGZuLCBndWFyZCk7XG59XG5cbmZ1bmN0aW9uIGRlZm1hdGNoKC4uLmNhc2VzKSB7XG4gIHJldHVybiBmdW5jdGlvbiAoLi4uYXJncykge1xuICAgIGZvciAobGV0IHByb2Nlc3NlZENhc2Ugb2YgY2FzZXMpIHtcbiAgICAgIGxldCByZXN1bHQgPSBbXTtcbiAgICAgIGlmIChwcm9jZXNzZWRDYXNlLnBhdHRlcm4oYXJncywgcmVzdWx0KSAmJiBwcm9jZXNzZWRDYXNlLmd1YXJkLmFwcGx5KHRoaXMsIHJlc3VsdCkpIHtcbiAgICAgICAgcmV0dXJuIHByb2Nlc3NlZENhc2UuZm4uYXBwbHkodGhpcywgcmVzdWx0KTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICB0aHJvdyBuZXcgTWF0Y2hFcnJvcihhcmdzKTtcbiAgfTtcbn1cblxuZnVuY3Rpb24gbWF0Y2gocGF0dGVybiwgZXhwciwgZ3VhcmQgPSAoKSA9PiB0cnVlKSB7XG4gIGxldCByZXN1bHQgPSBbXTtcbiAgbGV0IHByb2Nlc3NlZFBhdHRlcm4gPSBidWlsZE1hdGNoKHBhdHRlcm4pO1xuICBpZiAocHJvY2Vzc2VkUGF0dGVybihleHByLCByZXN1bHQpICYmIGd1YXJkLmFwcGx5KHRoaXMsIHJlc3VsdCkpIHtcbiAgICByZXR1cm4gcmVzdWx0O1xuICB9IGVsc2Uge1xuICAgIHRocm93IG5ldyBNYXRjaEVycm9yKGV4cHIpO1xuICB9XG59XG5cbmZ1bmN0aW9uIG1hdGNoX25vX3Rocm93KHBhdHRlcm4sIGV4cHIsIGd1YXJkID0gKCkgPT4gdHJ1ZSkge1xuICB0cnkge1xuICAgIHJldHVybiBtYXRjaChwYXR0ZXJuLCBleHByLCBndWFyZCk7XG4gIH0gY2F0Y2ggKGUpIHtcbiAgICBpZiAoZSBpbnN0YW5jZW9mIE1hdGNoRXJyb3IpIHtcbiAgICAgIHJldHVybiBudWxsO1xuICAgIH1cblxuICAgIHRocm93IGU7XG4gIH1cbn1cblxudmFyIFBhdHRlcm5zID0ge1xuICBkZWZtYXRjaCwgbWF0Y2gsIE1hdGNoRXJyb3IsIG1hdGNoX25vX3Rocm93LFxuICB2YXJpYWJsZSwgd2lsZGNhcmQsIHN0YXJ0c1dpdGgsXG4gIGNhcHR1cmUsIGhlYWRUYWlsLCB0eXBlLCBib3VuZCwgQ2FzZSwgbWFrZV9jYXNlXG59O1xuXG5mdW5jdGlvbiBjYWxsX3Byb3BlcnR5KGl0ZW0sIHByb3BlcnR5KSB7XG4gIGlmIChwcm9wZXJ0eSBpbiBpdGVtKSB7XG4gICAgaXRlbVtwcm9wZXJ0eV07XG4gICAgaWYgKGl0ZW1bcHJvcGVydHldIGluc3RhbmNlb2YgRnVuY3Rpb24pIHtcbiAgICAgIHJldHVybiBpdGVtW3Byb3BlcnR5XSgpO1xuICAgIH0gZWxzZSB7XG4gICAgICByZXR1cm4gaXRlbVtwcm9wZXJ0eV07XG4gICAgfVxuICB9IGVsc2UgaWYgKFN5bWJvbC5mb3IocHJvcGVydHkpIGluIGl0ZW0pIHtcbiAgICBsZXQgcHJvcCA9IFN5bWJvbC5mb3IocHJvcGVydHkpO1xuICAgIGlmIChpdGVtW3Byb3BdIGluc3RhbmNlb2YgRnVuY3Rpb24pIHtcbiAgICAgIHJldHVybiBpdGVtW3Byb3BdKCk7XG4gICAgfSBlbHNlIHtcbiAgICAgIHJldHVybiBpdGVtW3Byb3BdO1xuICAgIH1cbiAgfVxuXG4gIHRocm93IG5ldyBFcnJvcihgUHJvcGVydHkgJHsgcHJvcGVydHkgfSBub3QgZm91bmQgaW4gJHsgaXRlbSB9YCk7XG59XG5cbmZ1bmN0aW9uIGFwcGx5KC4uLmFyZ3MpIHtcbiAgaWYgKGFyZ3MubGVuZ3RoID09PSAyKSB7XG4gICAgYXJnc1swXS5hcHBseShudWxsLCBhcmdzLnNsaWNlKDEpKTtcbiAgfSBlbHNlIHtcbiAgICBhcmdzWzBdW2FyZ3NbMV1dLmFwcGx5KG51bGwsIGFyZ3Muc2xpY2UoMikpO1xuICB9XG59XG5cbmZ1bmN0aW9uIGNvbnRhaW5zKGxlZnQsIHJpZ2h0KSB7XG4gIGZvciAobGV0IHggb2YgcmlnaHQpIHtcbiAgICBpZiAoUGF0dGVybnMubWF0Y2hfbm9fdGhyb3cobGVmdCwgeCkgIT0gbnVsbCkge1xuICAgICAgcmV0dXJuIHRydWU7XG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIGZhbHNlO1xufVxuXG5mdW5jdGlvbiBnZXRfZ2xvYmFsKCkge1xuICBpZiAodHlwZW9mIHNlbGYgIT09ICd1bmRlZmluZWQnKSB7XG4gICAgcmV0dXJuIHNlbGY7XG4gIH0gZWxzZSBpZiAodHlwZW9mIHdpbmRvdyAhPT0gJ3VuZGVmaW5lZCcpIHtcbiAgICByZXR1cm4gd2luZG93O1xuICB9IGVsc2UgaWYgKHR5cGVvZiBnbG9iYWwgIT09ICd1bmRlZmluZWQnKSB7XG4gICAgcmV0dXJuIGdsb2JhbDtcbiAgfVxuXG4gIHRocm93IG5ldyBFcnJvcignTm8gZ2xvYmFsIHN0YXRlIGZvdW5kJyk7XG59XG5cbmZ1bmN0aW9uIGRlZnN0cnVjdChkZWZhdWx0cykge1xuICByZXR1cm4gY2xhc3Mge1xuICAgIGNvbnN0cnVjdG9yKHVwZGF0ZSA9IHt9KSB7XG4gICAgICBsZXQgdGhlX3ZhbHVlcyA9IE9iamVjdC5hc3NpZ24oZGVmYXVsdHMsIHVwZGF0ZSk7XG4gICAgICBPYmplY3QuYXNzaWduKHRoaXMsIHRoZV92YWx1ZXMpO1xuICAgIH1cblxuICAgIHN0YXRpYyBjcmVhdGUodXBkYXRlcyA9IHt9KSB7XG4gICAgICBsZXQgeCA9IG5ldyB0aGlzKHVwZGF0ZXMpO1xuICAgICAgcmV0dXJuIE9iamVjdC5mcmVlemUoeCk7XG4gICAgfVxuICB9O1xufVxuXG5mdW5jdGlvbiBkZWZleGNlcHRpb24oZGVmYXVsdHMpIHtcbiAgcmV0dXJuIGNsYXNzIGV4dGVuZHMgRXJyb3Ige1xuICAgIGNvbnN0cnVjdG9yKHVwZGF0ZSA9IHt9KSB7XG4gICAgICBsZXQgbWVzc2FnZSA9IHVwZGF0ZS5tZXNzYWdlIHx8ICcnO1xuICAgICAgc3VwZXIobWVzc2FnZSk7XG5cbiAgICAgIGxldCB0aGVfdmFsdWVzID0gT2JqZWN0LmFzc2lnbihkZWZhdWx0cywgdXBkYXRlKTtcbiAgICAgIE9iamVjdC5hc3NpZ24odGhpcywgdGhlX3ZhbHVlcyk7XG5cbiAgICAgIHRoaXMubmFtZSA9IHRoaXMuY29uc3RydWN0b3IubmFtZTtcbiAgICAgIHRoaXMubWVzc2FnZSA9IG1lc3NhZ2U7XG4gICAgICB0aGlzW1NwZWNpYWxGb3Jtcy5hdG9tKCdfX2V4Y2VwdGlvbl9fJyldID0gdHJ1ZTtcbiAgICAgIEVycm9yLmNhcHR1cmVTdGFja1RyYWNlKHRoaXMsIHRoaXMuY29uc3RydWN0b3IubmFtZSk7XG4gICAgfVxuXG4gICAgc3RhdGljIGNyZWF0ZSh1cGRhdGVzID0ge30pIHtcbiAgICAgIGxldCB4ID0gbmV3IHRoaXModXBkYXRlcyk7XG4gICAgICByZXR1cm4gT2JqZWN0LmZyZWV6ZSh4KTtcbiAgICB9XG4gIH07XG59XG5cbmZ1bmN0aW9uIGRlZnByb3RvY29sKHNwZWMpIHtcbiAgcmV0dXJuIG5ldyBQcm90b2NvbChzcGVjKTtcbn1cblxuZnVuY3Rpb24gZGVmaW1wbChwcm90b2NvbCwgdHlwZSwgaW1wbCkge1xuICBwcm90b2NvbC5pbXBsZW1lbnRhdGlvbih0eXBlLCBpbXBsKTtcbn1cblxuZnVuY3Rpb24gZ2V0X29iamVjdF9rZXlzKG9iaikge1xuICByZXR1cm4gT2JqZWN0LmtleXMob2JqKS5jb25jYXQoT2JqZWN0LmdldE93blByb3BlcnR5U3ltYm9scyhvYmopKTtcbn1cblxuZnVuY3Rpb24gaXNfdmFsaWRfY2hhcmFjdGVyKGNvZGVwb2ludCkge1xuICB0cnkge1xuICAgIHJldHVybiBTdHJpbmcuZnJvbUNvZGVQb2ludChjb2RlcG9pbnQpICE9IG51bGw7XG4gIH0gY2F0Y2ggKGUpIHtcbiAgICByZXR1cm4gZmFsc2U7XG4gIH1cbn1cblxuLy9odHRwczovL2RldmVsb3Blci5tb3ppbGxhLm9yZy9lbi1VUy9kb2NzL1dlYi9BUEkvV2luZG93QmFzZTY0L0Jhc2U2NF9lbmNvZGluZ19hbmRfZGVjb2RpbmcjU29sdXRpb25fMl8lRTIlODAlOTNfcmV3cml0ZV90aGVfRE9Nc19hdG9iKClfYW5kX2J0b2EoKV91c2luZ19KYXZhU2NyaXB0J3NfVHlwZWRBcnJheXNfYW5kX1VURi04XG5mdW5jdGlvbiBiNjRFbmNvZGVVbmljb2RlKHN0cikge1xuICByZXR1cm4gYnRvYShlbmNvZGVVUklDb21wb25lbnQoc3RyKS5yZXBsYWNlKC8lKFswLTlBLUZdezJ9KS9nLCBmdW5jdGlvbiAobWF0Y2gsIHAxKSB7XG4gICAgcmV0dXJuIFN0cmluZy5mcm9tQ2hhckNvZGUoJzB4JyArIHAxKTtcbiAgfSkpO1xufVxuXG5mdW5jdGlvbiBkZWxldGVfcHJvcGVydHlfZnJvbV9tYXAobWFwLCBwcm9wZXJ0eSkge1xuICBsZXQgbmV3X21hcCA9IE9iamVjdC5hc3NpZ24oT2JqZWN0LmNyZWF0ZShtYXAuY29uc3RydWN0b3IucHJvdG90eXBlKSwgbWFwKTtcbiAgZGVsZXRlIG5ld19tYXBbcHJvcGVydHldO1xuXG4gIHJldHVybiBPYmplY3QuZnJlZXplKG5ld19tYXApO1xufVxuXG5mdW5jdGlvbiBjbGFzc190b19vYmoobWFwKSB7XG4gIGxldCBuZXdfbWFwID0gT2JqZWN0LmFzc2lnbih7fSwgbWFwKTtcbiAgcmV0dXJuIE9iamVjdC5mcmVlemUobmV3X21hcCk7XG59XG5cbmZ1bmN0aW9uIGFkZF9wcm9wZXJ0eV90b19tYXAobWFwLCBwcm9wZXJ0eSwgdmFsdWUpIHtcbiAgbGV0IG5ld19tYXAgPSBPYmplY3QuYXNzaWduKHt9LCBtYXApO1xuICBuZXdfbWFwW3Byb3BlcnR5XSA9IHZhbHVlO1xuICByZXR1cm4gT2JqZWN0LmZyZWV6ZShuZXdfbWFwKTtcbn1cblxuZnVuY3Rpb24gYm5vdChleHByKSB7XG4gIHJldHVybiB+ZXhwcjtcbn1cblxuZnVuY3Rpb24gYmFuZChsZWZ0LCByaWdodCkge1xuICByZXR1cm4gbGVmdCAmIHJpZ2h0O1xufVxuXG5mdW5jdGlvbiBib3IobGVmdCwgcmlnaHQpIHtcbiAgcmV0dXJuIGxlZnQgfCByaWdodDtcbn1cblxuZnVuY3Rpb24gYnNsKGxlZnQsIHJpZ2h0KSB7XG4gIHJldHVybiBsZWZ0IDw8IHJpZ2h0O1xufVxuXG5mdW5jdGlvbiBic3IobGVmdCwgcmlnaHQpIHtcbiAgcmV0dXJuIGxlZnQgPj4gcmlnaHQ7XG59XG5cbmZ1bmN0aW9uIGJ4b3IobGVmdCwgcmlnaHQpIHtcbiAgcmV0dXJuIGxlZnQgXiByaWdodDtcbn1cblxuZnVuY3Rpb24gemlwKGxpc3Rfb2ZfbGlzdHMpIHtcbiAgaWYgKGxpc3Rfb2ZfbGlzdHMubGVuZ3RoID09PSAwKSB7XG4gICAgcmV0dXJuIE9iamVjdC5mcmVlemUoW10pO1xuICB9XG5cbiAgbGV0IG5ld192YWx1ZSA9IFtdO1xuICBsZXQgc21hbGxlc3RfbGVuZ3RoID0gbGlzdF9vZl9saXN0c1swXTtcblxuICBmb3IgKGxldCB4IG9mIGxpc3Rfb2ZfbGlzdHMpIHtcbiAgICBpZiAoeC5sZW5ndGggPCBzbWFsbGVzdF9sZW5ndGgpIHtcbiAgICAgIHNtYWxsZXN0X2xlbmd0aCA9IHgubGVuZ3RoO1xuICAgIH1cbiAgfVxuXG4gIGZvciAobGV0IGkgPSAwOyBpIDwgc21hbGxlc3RfbGVuZ3RoOyBpKyspIHtcbiAgICBsZXQgY3VycmVudF92YWx1ZSA9IFtdO1xuICAgIGZvciAobGV0IGogPSAwOyBqIDwgbGlzdF9vZl9saXN0cy5sZW5ndGg7IGorKykge1xuICAgICAgY3VycmVudF92YWx1ZS5wdXNoKGxpc3Rfb2ZfbGlzdHNbal1baV0pO1xuICAgIH1cblxuICAgIG5ld192YWx1ZS5wdXNoKG5ldyBUdXBsZSguLi5jdXJyZW50X3ZhbHVlKSk7XG4gIH1cblxuICByZXR1cm4gT2JqZWN0LmZyZWV6ZShuZXdfdmFsdWUpO1xufVxuXG5mdW5jdGlvbiBjYW5fZGVjb2RlNjQoZGF0YSkge1xuICB0cnkge1xuICAgIGF0b2IoZGF0YSk7XG4gICAgcmV0dXJuIHRydWU7XG4gIH0gY2F0Y2ggKGUpIHtcbiAgICByZXR1cm4gZmFsc2U7XG4gIH1cbn1cblxudmFyIEZ1bmN0aW9ucyA9IHtcbiAgY2FsbF9wcm9wZXJ0eSxcbiAgYXBwbHksXG4gIGNvbnRhaW5zLFxuICBnZXRfZ2xvYmFsLFxuICBkZWZzdHJ1Y3QsXG4gIGRlZmV4Y2VwdGlvbixcbiAgZGVmcHJvdG9jb2wsXG4gIGRlZmltcGwsXG4gIGdldF9vYmplY3Rfa2V5cyxcbiAgaXNfdmFsaWRfY2hhcmFjdGVyLFxuICBiNjRFbmNvZGVVbmljb2RlLFxuICBkZWxldGVfcHJvcGVydHlfZnJvbV9tYXAsXG4gIGFkZF9wcm9wZXJ0eV90b19tYXAsXG4gIGNsYXNzX3RvX29iaixcbiAgY2FuX2RlY29kZTY0LFxuICBibm90LFxuICBiYW5kLFxuICBib3IsXG4gIGJzbCxcbiAgYnNyLFxuICBieG9yLFxuICB6aXBcbn07XG5cbmZ1bmN0aW9uIF9jYXNlKGNvbmRpdGlvbiwgY2xhdXNlcykge1xuICByZXR1cm4gUGF0dGVybnMuZGVmbWF0Y2goLi4uY2xhdXNlcykoY29uZGl0aW9uKTtcbn1cblxuZnVuY3Rpb24gY29uZChjbGF1c2VzKSB7XG4gIGZvciAobGV0IGNsYXVzZSBvZiBjbGF1c2VzKSB7XG4gICAgaWYgKGNsYXVzZVswXSkge1xuICAgICAgcmV0dXJuIGNsYXVzZVsxXSgpO1xuICAgIH1cbiAgfVxuXG4gIHRocm93IG5ldyBFcnJvcigpO1xufVxuXG5mdW5jdGlvbiBtYXBfdXBkYXRlKG1hcCwgdmFsdWVzKSB7XG4gIHJldHVybiBPYmplY3QuZnJlZXplKE9iamVjdC5hc3NpZ24oT2JqZWN0LmNyZWF0ZShtYXAuY29uc3RydWN0b3IucHJvdG90eXBlKSwgbWFwLCB2YWx1ZXMpKTtcbn1cblxuZnVuY3Rpb24gX2Zvcihjb2xsZWN0aW9ucywgZnVuLCBmaWx0ZXIgPSAoKSA9PiB0cnVlLCBpbnRvID0gW10sIHByZXZpb3VzVmFsdWVzID0gW10pIHtcbiAgbGV0IHBhdHRlcm4gPSBjb2xsZWN0aW9uc1swXVswXTtcbiAgbGV0IGNvbGxlY3Rpb24gPSBjb2xsZWN0aW9uc1swXVsxXTtcblxuICBpZiAoY29sbGVjdGlvbnMubGVuZ3RoID09PSAxKSB7XG5cbiAgICBmb3IgKGxldCBlbGVtIG9mIGNvbGxlY3Rpb24pIHtcbiAgICAgIGxldCByID0gUGF0dGVybnMubWF0Y2hfbm9fdGhyb3cocGF0dGVybiwgZWxlbSk7XG4gICAgICBsZXQgYXJncyA9IHByZXZpb3VzVmFsdWVzLmNvbmNhdChyKTtcblxuICAgICAgaWYgKHIgJiYgZmlsdGVyLmFwcGx5KHRoaXMsIGFyZ3MpKSB7XG4gICAgICAgIGludG8gPSBpbnRvLmNvbmNhdChbZnVuLmFwcGx5KHRoaXMsIGFyZ3MpXSk7XG4gICAgICB9XG4gICAgfVxuXG4gICAgcmV0dXJuIGludG87XG4gIH0gZWxzZSB7XG4gICAgbGV0IF9pbnRvID0gW107XG5cbiAgICBmb3IgKGxldCBlbGVtIG9mIGNvbGxlY3Rpb24pIHtcbiAgICAgIGxldCByID0gUGF0dGVybnMubWF0Y2hfbm9fdGhyb3cocGF0dGVybiwgZWxlbSk7XG4gICAgICBpZiAocikge1xuICAgICAgICBfaW50byA9IGludG8uY29uY2F0KHRoaXMuX2Zvcihjb2xsZWN0aW9ucy5zbGljZSgxKSwgZnVuLCBmaWx0ZXIsIF9pbnRvLCBwcmV2aW91c1ZhbHVlcy5jb25jYXQocikpKTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICByZXR1cm4gX2ludG87XG4gIH1cbn1cblxuZnVuY3Rpb24gX3RyeShkb19mdW4sIHJlc2N1ZV9mdW5jdGlvbiwgY2F0Y2hfZnVuLCBlbHNlX2Z1bmN0aW9uLCBhZnRlcl9mdW5jdGlvbikge1xuICBsZXQgcmVzdWx0ID0gbnVsbDtcblxuICB0cnkge1xuICAgIHJlc3VsdCA9IGRvX2Z1bigpO1xuICB9IGNhdGNoIChlKSB7XG4gICAgbGV0IGV4X3Jlc3VsdCA9IG51bGw7XG5cbiAgICBpZiAocmVzY3VlX2Z1bmN0aW9uKSB7XG4gICAgICB0cnkge1xuICAgICAgICBleF9yZXN1bHQgPSByZXNjdWVfZnVuY3Rpb24oZSk7XG4gICAgICAgIHJldHVybiBleF9yZXN1bHQ7XG4gICAgICB9IGNhdGNoIChleCkge1xuICAgICAgICBpZiAoZXggaW5zdGFuY2VvZiBQYXR0ZXJucy5NYXRjaEVycm9yKSB7XG4gICAgICAgICAgdGhyb3cgZXg7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9XG5cbiAgICBpZiAoY2F0Y2hfZnVuKSB7XG4gICAgICB0cnkge1xuICAgICAgICBleF9yZXN1bHQgPSBjYXRjaF9mdW4oZSk7XG4gICAgICAgIHJldHVybiBleF9yZXN1bHQ7XG4gICAgICB9IGNhdGNoIChleCkge1xuICAgICAgICBpZiAoZXggaW5zdGFuY2VvZiBQYXR0ZXJucy5NYXRjaEVycm9yKSB7XG4gICAgICAgICAgdGhyb3cgZXg7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9XG5cbiAgICB0aHJvdyBlO1xuICB9IGZpbmFsbHkge1xuICAgIGlmIChhZnRlcl9mdW5jdGlvbikge1xuICAgICAgYWZ0ZXJfZnVuY3Rpb24oKTtcbiAgICB9XG4gIH1cblxuICBpZiAoZWxzZV9mdW5jdGlvbikge1xuICAgIHRyeSB7XG4gICAgICByZXR1cm4gZWxzZV9mdW5jdGlvbihyZXN1bHQpO1xuICAgIH0gY2F0Y2ggKGV4KSB7XG4gICAgICBpZiAoZXggaW5zdGFuY2VvZiBQYXR0ZXJucy5NYXRjaEVycm9yKSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcignTm8gTWF0Y2ggRm91bmQgaW4gRWxzZScpO1xuICAgICAgfVxuXG4gICAgICB0aHJvdyBleDtcbiAgICB9XG4gIH0gZWxzZSB7XG4gICAgcmV0dXJuIHJlc3VsdDtcbiAgfVxufVxuXG52YXIgc3BlY2lhbF9mb3JtcyA9IHtcbiAgX2Nhc2UsXG4gIGNvbmQsXG4gIG1hcF91cGRhdGUsXG4gIF9mb3IsXG4gIF90cnlcbn07XG5cbkZ1bmN0aW9ucy5nZXRfZ2xvYmFsKCkucHJvY2Vzc2VzID0gRnVuY3Rpb25zLmdldF9nbG9iYWwoKS5wcm9jZXNzZXMgfHwgbmV3IFByb2Nlc3NTeXN0ZW0oKTtcblxuXG5cbnZhciBDID0gT2JqZWN0LmZyZWV6ZSh7XG5cdFByb2Nlc3NTeXN0ZW06IFByb2Nlc3NTeXN0ZW0sXG5cdFR1cGxlOiBUdXBsZSxcblx0UElEOiBQSUQsXG5cdEJpdFN0cmluZzogQml0U3RyaW5nLFxuXHRQYXR0ZXJuczogUGF0dGVybnMsXG5cdEludGVnZXI6IEludGVnZXIsXG5cdEZsb2F0OiBGbG9hdCxcblx0RnVuY3Rpb25zOiBGdW5jdGlvbnMsXG5cdFNwZWNpYWxGb3Jtczogc3BlY2lhbF9mb3Jtc1xufSk7XG5cbmxldCBFbnVtID0ge1xuXG4gIGFsbF9fcW1hcmtfXzogZnVuY3Rpb24gKGNvbGxlY3Rpb24sIGZ1biA9IHggPT4geCkge1xuICAgIGZvciAobGV0IGVsZW0gb2YgY29sbGVjdGlvbikge1xuICAgICAgaWYgKCFmdW4oZWxlbSkpIHtcbiAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgfVxuICAgIH1cblxuICAgIHJldHVybiB0cnVlO1xuICB9LFxuXG4gIGFueV9fcW1hcmtfXzogZnVuY3Rpb24gKGNvbGxlY3Rpb24sIGZ1biA9IHggPT4geCkge1xuICAgIGZvciAobGV0IGVsZW0gb2YgY29sbGVjdGlvbikge1xuICAgICAgaWYgKGZ1bihlbGVtKSkge1xuICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICByZXR1cm4gZmFsc2U7XG4gIH0sXG5cbiAgYXQ6IGZ1bmN0aW9uIChjb2xsZWN0aW9uLCBuLCB0aGVfZGVmYXVsdCA9IG51bGwpIHtcbiAgICBpZiAobiA+IHRoaXMuY291bnQoY29sbGVjdGlvbikgfHwgbiA8IDApIHtcbiAgICAgIHJldHVybiB0aGVfZGVmYXVsdDtcbiAgICB9XG5cbiAgICByZXR1cm4gY29sbGVjdGlvbltuXTtcbiAgfSxcblxuICBjb25jYXQ6IGZ1bmN0aW9uICguLi5lbnVtYWJsZXMpIHtcbiAgICByZXR1cm4gZW51bWFibGVzWzBdLmNvbmNhdChlbnVtYWJsZXNbMV0pO1xuICB9LFxuXG4gIGNvdW50OiBmdW5jdGlvbiAoY29sbGVjdGlvbiwgZnVuID0gbnVsbCkge1xuICAgIGlmIChmdW4gPT0gbnVsbCkge1xuICAgICAgcmV0dXJuIGNvbGxlY3Rpb24ubGVuZ3RoO1xuICAgIH0gZWxzZSB7XG4gICAgICByZXR1cm4gY29sbGVjdGlvbi5maWx0ZXIoZnVuKS5sZW5ndGg7XG4gICAgfVxuICB9LFxuXG4gIGRyb3A6IGZ1bmN0aW9uIChjb2xsZWN0aW9uLCBjb3VudCkge1xuICAgIHJldHVybiBjb2xsZWN0aW9uLnNsaWNlKGNvdW50KTtcbiAgfSxcblxuICBkcm9wX3doaWxlOiBmdW5jdGlvbiAoY29sbGVjdGlvbiwgZnVuKSB7XG4gICAgbGV0IGNvdW50ID0gMDtcblxuICAgIGZvciAobGV0IGVsZW0gb2YgY29sbGVjdGlvbikge1xuICAgICAgaWYgKGZ1bihlbGVtKSkge1xuICAgICAgICBjb3VudCA9IGNvdW50ICsgMTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIGJyZWFrO1xuICAgICAgfVxuICAgIH1cblxuICAgIHJldHVybiBjb2xsZWN0aW9uLnNsaWNlKGNvdW50KTtcbiAgfSxcblxuICBlYWNoOiBmdW5jdGlvbiAoY29sbGVjdGlvbiwgZnVuKSB7XG4gICAgZm9yIChsZXQgZWxlbSBvZiBjb2xsZWN0aW9uKSB7XG4gICAgICBmdW4oZWxlbSk7XG4gICAgfVxuICB9LFxuXG4gIGVtcHR5X19xbWFya19fOiBmdW5jdGlvbiAoY29sbGVjdGlvbikge1xuICAgIHJldHVybiBjb2xsZWN0aW9uLmxlbmd0aCA9PT0gMDtcbiAgfSxcblxuICBmZXRjaDogZnVuY3Rpb24gKGNvbGxlY3Rpb24sIG4pIHtcbiAgICBpZiAoQXJyYXkuaXNBcnJheShjb2xsZWN0aW9uKSkge1xuICAgICAgaWYgKG4gPCB0aGlzLmNvdW50KGNvbGxlY3Rpb24pICYmIG4gPj0gMCkge1xuICAgICAgICByZXR1cm4gbmV3IFR1cGxlKFN5bWJvbC5mb3IoXCJva1wiKSwgY29sbGVjdGlvbltuXSk7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICByZXR1cm4gU3ltYm9sLmZvcihcImVycm9yXCIpO1xuICAgICAgfVxuICAgIH1cblxuICAgIHRocm93IG5ldyBFcnJvcihcImNvbGxlY3Rpb24gaXMgbm90IGFuIEVudW1lcmFibGVcIik7XG4gIH0sXG5cbiAgZmV0Y2hfX2VtYXJrX186IGZ1bmN0aW9uIChjb2xsZWN0aW9uLCBuKSB7XG4gICAgaWYgKEFycmF5LmlzQXJyYXkoY29sbGVjdGlvbikpIHtcbiAgICAgIGlmIChuIDwgdGhpcy5jb3VudChjb2xsZWN0aW9uKSAmJiBuID49IDApIHtcbiAgICAgICAgcmV0dXJuIGNvbGxlY3Rpb25bbl07XG4gICAgICB9IGVsc2Uge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoXCJvdXQgb2YgYm91bmRzIGVycm9yXCIpO1xuICAgICAgfVxuICAgIH1cblxuICAgIHRocm93IG5ldyBFcnJvcihcImNvbGxlY3Rpb24gaXMgbm90IGFuIEVudW1lcmFibGVcIik7XG4gIH0sXG5cbiAgZmlsdGVyOiBmdW5jdGlvbiAoY29sbGVjdGlvbiwgZnVuKSB7XG4gICAgbGV0IHJlc3VsdCA9IFtdO1xuXG4gICAgZm9yIChsZXQgZWxlbSBvZiBjb2xsZWN0aW9uKSB7XG4gICAgICBpZiAoZnVuKGVsZW0pKSB7XG4gICAgICAgIHJlc3VsdC5wdXNoKGVsZW0pO1xuICAgICAgfVxuICAgIH1cblxuICAgIHJldHVybiByZXN1bHQ7XG4gIH0sXG5cbiAgZmlsdGVyX21hcDogZnVuY3Rpb24gKGNvbGxlY3Rpb24sIGZpbHRlciwgbWFwcGVyKSB7XG4gICAgcmV0dXJuIEVudW0ubWFwKEVudW0uZmlsdGVyKGNvbGxlY3Rpb24sIGZpbHRlciksIG1hcHBlcik7XG4gIH0sXG5cbiAgZmluZDogZnVuY3Rpb24gKGNvbGxlY3Rpb24sIGlmX25vbmUgPSBudWxsLCBmdW4pIHtcbiAgICBmb3IgKGxldCBlbGVtIG9mIGNvbGxlY3Rpb24pIHtcbiAgICAgIGlmIChmdW4oZWxlbSkpIHtcbiAgICAgICAgcmV0dXJuIGVsZW07XG4gICAgICB9XG4gICAgfVxuXG4gICAgcmV0dXJuIGlmX25vbmU7XG4gIH0sXG5cbiAgaW50bzogZnVuY3Rpb24gKGNvbGxlY3Rpb24sIGxpc3QpIHtcbiAgICByZXR1cm4gbGlzdC5jb25jYXQoY29sbGVjdGlvbik7XG4gIH0sXG5cbiAgbWFwOiBmdW5jdGlvbiAoY29sbGVjdGlvbiwgZnVuKSB7XG4gICAgbGV0IHJlc3VsdCA9IFtdO1xuXG4gICAgZm9yIChsZXQgZWxlbSBvZiBjb2xsZWN0aW9uKSB7XG4gICAgICByZXN1bHQucHVzaChmdW4oZWxlbSkpO1xuICAgIH1cblxuICAgIHJldHVybiByZXN1bHQ7XG4gIH0sXG5cbiAgbWFwX3JlZHVjZTogZnVuY3Rpb24gKGNvbGxlY3Rpb24sIGFjYywgZnVuKSB7XG4gICAgbGV0IG1hcHBlZCA9IE9iamVjdC5mcmVlemUoW10pO1xuICAgIGxldCB0aGVfYWNjID0gYWNjO1xuXG4gICAgZm9yICh2YXIgaSA9IDA7IGkgPCB0aGlzLmNvdW50KGNvbGxlY3Rpb24pOyBpKyspIHtcbiAgICAgIGxldCB0dXBsZSA9IGZ1bihjb2xsZWN0aW9uW2ldLCB0aGVfYWNjKTtcblxuICAgICAgdGhlX2FjYyA9IHR1cGxlLmdldCgxKTtcbiAgICAgIG1hcHBlZCA9IE9iamVjdC5mcmVlemUobWFwcGVkLmNvbmNhdChbdHVwbGUuZ2V0KDApXSkpO1xuICAgIH1cblxuICAgIHJldHVybiBuZXcgVHVwbGUobWFwcGVkLCB0aGVfYWNjKTtcbiAgfSxcblxuICBtZW1iZXJfX3FtYXJrX186IGZ1bmN0aW9uIChjb2xsZWN0aW9uLCB2YWx1ZSkge1xuICAgIHJldHVybiBjb2xsZWN0aW9uLmluY2x1ZGVzKHZhbHVlKTtcbiAgfSxcblxuICByZWR1Y2U6IGZ1bmN0aW9uIChjb2xsZWN0aW9uLCBhY2MsIGZ1bikge1xuICAgIGxldCB0aGVfYWNjID0gYWNjO1xuXG4gICAgZm9yICh2YXIgaSA9IDA7IGkgPCB0aGlzLmNvdW50KGNvbGxlY3Rpb24pOyBpKyspIHtcbiAgICAgIGxldCB0dXBsZSA9IGZ1bihjb2xsZWN0aW9uW2ldLCB0aGVfYWNjKTtcblxuICAgICAgdGhlX2FjYyA9IHR1cGxlLmdldCgxKTtcbiAgICB9XG5cbiAgICByZXR1cm4gdGhlX2FjYztcbiAgfSxcblxuICB0YWtlOiBmdW5jdGlvbiAoY29sbGVjdGlvbiwgY291bnQpIHtcbiAgICByZXR1cm4gY29sbGVjdGlvbi5zbGljZSgwLCBjb3VudCk7XG4gIH0sXG5cbiAgdGFrZV9ldmVyeTogZnVuY3Rpb24gKGNvbGxlY3Rpb24sIG50aCkge1xuICAgIGxldCByZXN1bHQgPSBbXTtcbiAgICBsZXQgaW5kZXggPSAwO1xuXG4gICAgZm9yIChsZXQgZWxlbSBvZiBjb2xsZWN0aW9uKSB7XG4gICAgICBpZiAoaW5kZXggJSBudGggPT09IDApIHtcbiAgICAgICAgcmVzdWx0LnB1c2goZWxlbSk7XG4gICAgICB9XG4gICAgfVxuXG4gICAgcmV0dXJuIE9iamVjdC5mcmVlemUocmVzdWx0KTtcbiAgfSxcblxuICB0YWtlX3doaWxlOiBmdW5jdGlvbiAoY29sbGVjdGlvbiwgZnVuKSB7XG4gICAgbGV0IGNvdW50ID0gMDtcblxuICAgIGZvciAobGV0IGVsZW0gb2YgY29sbGVjdGlvbikge1xuICAgICAgaWYgKGZ1bihlbGVtKSkge1xuICAgICAgICBjb3VudCA9IGNvdW50ICsgMTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIGJyZWFrO1xuICAgICAgfVxuICAgIH1cblxuICAgIHJldHVybiBjb2xsZWN0aW9uLnNsaWNlKDAsIGNvdW50KTtcbiAgfSxcblxuICB0b19saXN0OiBmdW5jdGlvbiAoY29sbGVjdGlvbikge1xuICAgIHJldHVybiBjb2xsZWN0aW9uO1xuICB9XG59O1xuXG5sZXQgVmlydHVhbERPTSA9IChmdW5jdGlvbiAoZSkge1xuICAgIHJldHVybiBlKCk7XG59KShmdW5jdGlvbiAoKSB7XG4gICAgdmFyIGRlZmluZSwgbW9kdWxlLCBleHBvcnRzO1xuICAgIHJldHVybiAoZnVuY3Rpb24gZSh0LCBuLCByKSB7XG4gICAgICAgIGZ1bmN0aW9uIHMobywgdSkge1xuICAgICAgICAgICAgaWYgKCFuW29dKSB7XG4gICAgICAgICAgICAgICAgaWYgKCF0W29dKSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciBhID0gdHlwZW9mIHJlcXVpcmUgPT0gXCJmdW5jdGlvblwiICYmIHJlcXVpcmU7XG4gICAgICAgICAgICAgICAgICAgIGlmICghdSAmJiBhKSByZXR1cm4gYShvLCAhMCk7XG4gICAgICAgICAgICAgICAgICAgIGlmIChpKSByZXR1cm4gaShvLCAhMCk7XG4gICAgICAgICAgICAgICAgICAgIHZhciBmID0gbmV3IEVycm9yKFwiQ2Fubm90IGZpbmQgbW9kdWxlICdcIiArIG8gKyBcIidcIik7XG4gICAgICAgICAgICAgICAgICAgIHRocm93IChmLmNvZGUgPSBcIk1PRFVMRV9OT1RfRk9VTkRcIiwgZik7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHZhciBsID0gbltvXSA9IHtcbiAgICAgICAgICAgICAgICAgICAgZXhwb3J0czoge31cbiAgICAgICAgICAgICAgICB9O1xuICAgICAgICAgICAgICAgIHRbb11bMF0uY2FsbChsLmV4cG9ydHMsIGZ1bmN0aW9uIChlKSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciBuID0gdFtvXVsxXVtlXTtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHMobiA/IG4gOiBlKTtcbiAgICAgICAgICAgICAgICB9LCBsLCBsLmV4cG9ydHMsIGUsIHQsIG4sIHIpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmV0dXJuIG5bb10uZXhwb3J0cztcbiAgICAgICAgfVxuICAgICAgICB2YXIgaSA9IHR5cGVvZiByZXF1aXJlID09IFwiZnVuY3Rpb25cIiAmJiByZXF1aXJlO1xuICAgICAgICBmb3IgKHZhciBvID0gMDsgbyA8IHIubGVuZ3RoOyBvKyspIHMocltvXSk7XG4gICAgICAgIHJldHVybiBzO1xuICAgIH0pKHtcbiAgICAgICAgMTogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHtcblxuICAgICAgICAgICAgdmFyIGNyZWF0ZUVsZW1lbnQgPSByZXF1aXJlKFwiLi92ZG9tL2NyZWF0ZS1lbGVtZW50LmpzXCIpO1xuXG4gICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IGNyZWF0ZUVsZW1lbnQ7XG4gICAgICAgIH0sIHsgXCIuL3Zkb20vY3JlYXRlLWVsZW1lbnQuanNcIjogMTUgfV0sIDI6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICB2YXIgZGlmZiA9IHJlcXVpcmUoXCIuL3Z0cmVlL2RpZmYuanNcIik7XG5cbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gZGlmZjtcbiAgICAgICAgfSwgeyBcIi4vdnRyZWUvZGlmZi5qc1wiOiAzNSB9XSwgMzogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHtcbiAgICAgICAgICAgIHZhciBoID0gcmVxdWlyZShcIi4vdmlydHVhbC1oeXBlcnNjcmlwdC9pbmRleC5qc1wiKTtcblxuICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBoO1xuICAgICAgICB9LCB7IFwiLi92aXJ0dWFsLWh5cGVyc2NyaXB0L2luZGV4LmpzXCI6IDIyIH1dLCA0OiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge1xuICAgICAgICAgICAgdmFyIGRpZmYgPSByZXF1aXJlKFwiLi9kaWZmLmpzXCIpO1xuICAgICAgICAgICAgdmFyIHBhdGNoID0gcmVxdWlyZShcIi4vcGF0Y2guanNcIik7XG4gICAgICAgICAgICB2YXIgaCA9IHJlcXVpcmUoXCIuL2guanNcIik7XG4gICAgICAgICAgICB2YXIgY3JlYXRlID0gcmVxdWlyZShcIi4vY3JlYXRlLWVsZW1lbnQuanNcIik7XG4gICAgICAgICAgICB2YXIgVk5vZGUgPSByZXF1aXJlKFwiLi92bm9kZS92bm9kZS5qc1wiKTtcbiAgICAgICAgICAgIHZhciBWVGV4dCA9IHJlcXVpcmUoXCIuL3Zub2RlL3Z0ZXh0LmpzXCIpO1xuXG4gICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IHtcbiAgICAgICAgICAgICAgICBkaWZmOiBkaWZmLFxuICAgICAgICAgICAgICAgIHBhdGNoOiBwYXRjaCxcbiAgICAgICAgICAgICAgICBoOiBoLFxuICAgICAgICAgICAgICAgIGNyZWF0ZTogY3JlYXRlLFxuICAgICAgICAgICAgICAgIFZOb2RlOiBWTm9kZSxcbiAgICAgICAgICAgICAgICBWVGV4dDogVlRleHRcbiAgICAgICAgICAgIH07XG4gICAgICAgIH0sIHsgXCIuL2NyZWF0ZS1lbGVtZW50LmpzXCI6IDEsIFwiLi9kaWZmLmpzXCI6IDIsIFwiLi9oLmpzXCI6IDMsIFwiLi9wYXRjaC5qc1wiOiAxMywgXCIuL3Zub2RlL3Zub2RlLmpzXCI6IDMxLCBcIi4vdm5vZGUvdnRleHQuanNcIjogMzMgfV0sIDU6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICAvKiFcbiAgICAgICAgICAgICAqIENyb3NzLUJyb3dzZXIgU3BsaXQgMS4xLjFcbiAgICAgICAgICAgICAqIENvcHlyaWdodCAyMDA3LTIwMTIgU3RldmVuIExldml0aGFuIDxzdGV2ZW5sZXZpdGhhbi5jb20+XG4gICAgICAgICAgICAgKiBBdmFpbGFibGUgdW5kZXIgdGhlIE1JVCBMaWNlbnNlXG4gICAgICAgICAgICAgKiBFQ01BU2NyaXB0IGNvbXBsaWFudCwgdW5pZm9ybSBjcm9zcy1icm93c2VyIHNwbGl0IG1ldGhvZFxuICAgICAgICAgICAgICovXG5cbiAgICAgICAgICAgIC8qKlxuICAgICAgICAgICAgICogU3BsaXRzIGEgc3RyaW5nIGludG8gYW4gYXJyYXkgb2Ygc3RyaW5ncyB1c2luZyBhIHJlZ2V4IG9yIHN0cmluZyBzZXBhcmF0b3IuIE1hdGNoZXMgb2YgdGhlXG4gICAgICAgICAgICAgKiBzZXBhcmF0b3IgYXJlIG5vdCBpbmNsdWRlZCBpbiB0aGUgcmVzdWx0IGFycmF5LiBIb3dldmVyLCBpZiBgc2VwYXJhdG9yYCBpcyBhIHJlZ2V4IHRoYXQgY29udGFpbnNcbiAgICAgICAgICAgICAqIGNhcHR1cmluZyBncm91cHMsIGJhY2tyZWZlcmVuY2VzIGFyZSBzcGxpY2VkIGludG8gdGhlIHJlc3VsdCBlYWNoIHRpbWUgYHNlcGFyYXRvcmAgaXMgbWF0Y2hlZC5cbiAgICAgICAgICAgICAqIEZpeGVzIGJyb3dzZXIgYnVncyBjb21wYXJlZCB0byB0aGUgbmF0aXZlIGBTdHJpbmcucHJvdG90eXBlLnNwbGl0YCBhbmQgY2FuIGJlIHVzZWQgcmVsaWFibHlcbiAgICAgICAgICAgICAqIGNyb3NzLWJyb3dzZXIuXG4gICAgICAgICAgICAgKiBAcGFyYW0ge1N0cmluZ30gc3RyIFN0cmluZyB0byBzcGxpdC5cbiAgICAgICAgICAgICAqIEBwYXJhbSB7UmVnRXhwfFN0cmluZ30gc2VwYXJhdG9yIFJlZ2V4IG9yIHN0cmluZyB0byB1c2UgZm9yIHNlcGFyYXRpbmcgdGhlIHN0cmluZy5cbiAgICAgICAgICAgICAqIEBwYXJhbSB7TnVtYmVyfSBbbGltaXRdIE1heGltdW0gbnVtYmVyIG9mIGl0ZW1zIHRvIGluY2x1ZGUgaW4gdGhlIHJlc3VsdCBhcnJheS5cbiAgICAgICAgICAgICAqIEByZXR1cm5zIHtBcnJheX0gQXJyYXkgb2Ygc3Vic3RyaW5ncy5cbiAgICAgICAgICAgICAqIEBleGFtcGxlXG4gICAgICAgICAgICAgKlxuICAgICAgICAgICAgICogLy8gQmFzaWMgdXNlXG4gICAgICAgICAgICAgKiBzcGxpdCgnYSBiIGMgZCcsICcgJyk7XG4gICAgICAgICAgICAgKiAvLyAtPiBbJ2EnLCAnYicsICdjJywgJ2QnXVxuICAgICAgICAgICAgICpcbiAgICAgICAgICAgICAqIC8vIFdpdGggbGltaXRcbiAgICAgICAgICAgICAqIHNwbGl0KCdhIGIgYyBkJywgJyAnLCAyKTtcbiAgICAgICAgICAgICAqIC8vIC0+IFsnYScsICdiJ11cbiAgICAgICAgICAgICAqXG4gICAgICAgICAgICAgKiAvLyBCYWNrcmVmZXJlbmNlcyBpbiByZXN1bHQgYXJyYXlcbiAgICAgICAgICAgICAqIHNwbGl0KCcuLndvcmQxIHdvcmQyLi4nLCAvKFthLXpdKykoXFxkKykvaSk7XG4gICAgICAgICAgICAgKiAvLyAtPiBbJy4uJywgJ3dvcmQnLCAnMScsICcgJywgJ3dvcmQnLCAnMicsICcuLiddXG4gICAgICAgICAgICAgKi9cbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gKGZ1bmN0aW9uIHNwbGl0KHVuZGVmKSB7XG5cbiAgICAgICAgICAgICAgICB2YXIgbmF0aXZlU3BsaXQgPSBTdHJpbmcucHJvdG90eXBlLnNwbGl0LFxuICAgICAgICAgICAgICAgICAgICBjb21wbGlhbnRFeGVjTnBjZyA9IC8oKT8/Ly5leGVjKFwiXCIpWzFdID09PSB1bmRlZixcblxuICAgICAgICAgICAgICAgIC8vIE5QQ0c6IG5vbnBhcnRpY2lwYXRpbmcgY2FwdHVyaW5nIGdyb3VwXG4gICAgICAgICAgICAgICAgc2VsZjtcblxuICAgICAgICAgICAgICAgIHNlbGYgPSBmdW5jdGlvbiAoc3RyLCBzZXBhcmF0b3IsIGxpbWl0KSB7XG4gICAgICAgICAgICAgICAgICAgIC8vIElmIGBzZXBhcmF0b3JgIGlzIG5vdCBhIHJlZ2V4LCB1c2UgYG5hdGl2ZVNwbGl0YFxuICAgICAgICAgICAgICAgICAgICBpZiAoT2JqZWN0LnByb3RvdHlwZS50b1N0cmluZy5jYWxsKHNlcGFyYXRvcikgIT09IFwiW29iamVjdCBSZWdFeHBdXCIpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBuYXRpdmVTcGxpdC5jYWxsKHN0ciwgc2VwYXJhdG9yLCBsaW1pdCk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgdmFyIG91dHB1dCA9IFtdLFxuICAgICAgICAgICAgICAgICAgICAgICAgZmxhZ3MgPSAoc2VwYXJhdG9yLmlnbm9yZUNhc2UgPyBcImlcIiA6IFwiXCIpICsgKHNlcGFyYXRvci5tdWx0aWxpbmUgPyBcIm1cIiA6IFwiXCIpICsgKHNlcGFyYXRvci5leHRlbmRlZCA/IFwieFwiIDogXCJcIikgKyAoc2VwYXJhdG9yLnN0aWNreSA/IFwieVwiIDogXCJcIiksXG5cbiAgICAgICAgICAgICAgICAgICAgLy8gRmlyZWZveCAzK1xuICAgICAgICAgICAgICAgICAgICBsYXN0TGFzdEluZGV4ID0gMCxcblxuICAgICAgICAgICAgICAgICAgICAvLyBNYWtlIGBnbG9iYWxgIGFuZCBhdm9pZCBgbGFzdEluZGV4YCBpc3N1ZXMgYnkgd29ya2luZyB3aXRoIGEgY29weVxuICAgICAgICAgICAgICAgICAgICBzZXBhcmF0b3IgPSBuZXcgUmVnRXhwKHNlcGFyYXRvci5zb3VyY2UsIGZsYWdzICsgXCJnXCIpLFxuICAgICAgICAgICAgICAgICAgICAgICAgc2VwYXJhdG9yMixcbiAgICAgICAgICAgICAgICAgICAgICAgIG1hdGNoLFxuICAgICAgICAgICAgICAgICAgICAgICAgbGFzdEluZGV4LFxuICAgICAgICAgICAgICAgICAgICAgICAgbGFzdExlbmd0aDtcbiAgICAgICAgICAgICAgICAgICAgc3RyICs9IFwiXCI7IC8vIFR5cGUtY29udmVydFxuICAgICAgICAgICAgICAgICAgICBpZiAoIWNvbXBsaWFudEV4ZWNOcGNnKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAvLyBEb2Vzbid0IG5lZWQgZmxhZ3MgZ3ksIGJ1dCB0aGV5IGRvbid0IGh1cnRcbiAgICAgICAgICAgICAgICAgICAgICAgIHNlcGFyYXRvcjIgPSBuZXcgUmVnRXhwKFwiXlwiICsgc2VwYXJhdG9yLnNvdXJjZSArIFwiJCg/IVxcXFxzKVwiLCBmbGFncyk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgLyogVmFsdWVzIGZvciBgbGltaXRgLCBwZXIgdGhlIHNwZWM6XG4gICAgICAgICAgICAgICAgICAgICAqIElmIHVuZGVmaW5lZDogNDI5NDk2NzI5NSAvLyBNYXRoLnBvdygyLCAzMikgLSAxXG4gICAgICAgICAgICAgICAgICAgICAqIElmIDAsIEluZmluaXR5LCBvciBOYU46IDBcbiAgICAgICAgICAgICAgICAgICAgICogSWYgcG9zaXRpdmUgbnVtYmVyOiBsaW1pdCA9IE1hdGguZmxvb3IobGltaXQpOyBpZiAobGltaXQgPiA0Mjk0OTY3Mjk1KSBsaW1pdCAtPSA0Mjk0OTY3Mjk2O1xuICAgICAgICAgICAgICAgICAgICAgKiBJZiBuZWdhdGl2ZSBudW1iZXI6IDQyOTQ5NjcyOTYgLSBNYXRoLmZsb29yKE1hdGguYWJzKGxpbWl0KSlcbiAgICAgICAgICAgICAgICAgICAgICogSWYgb3RoZXI6IFR5cGUtY29udmVydCwgdGhlbiB1c2UgdGhlIGFib3ZlIHJ1bGVzXG4gICAgICAgICAgICAgICAgICAgICAqL1xuICAgICAgICAgICAgICAgICAgICBsaW1pdCA9IGxpbWl0ID09PSB1bmRlZiA/IC0xID4+PiAwIDogLy8gTWF0aC5wb3coMiwgMzIpIC0gMVxuICAgICAgICAgICAgICAgICAgICBsaW1pdCA+Pj4gMDsgLy8gVG9VaW50MzIobGltaXQpXG4gICAgICAgICAgICAgICAgICAgIHdoaWxlIChtYXRjaCA9IHNlcGFyYXRvci5leGVjKHN0cikpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIGBzZXBhcmF0b3IubGFzdEluZGV4YCBpcyBub3QgcmVsaWFibGUgY3Jvc3MtYnJvd3NlclxuICAgICAgICAgICAgICAgICAgICAgICAgbGFzdEluZGV4ID0gbWF0Y2guaW5kZXggKyBtYXRjaFswXS5sZW5ndGg7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAobGFzdEluZGV4ID4gbGFzdExhc3RJbmRleCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIG91dHB1dC5wdXNoKHN0ci5zbGljZShsYXN0TGFzdEluZGV4LCBtYXRjaC5pbmRleCkpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIEZpeCBicm93c2VycyB3aG9zZSBgZXhlY2AgbWV0aG9kcyBkb24ndCBjb25zaXN0ZW50bHkgcmV0dXJuIGB1bmRlZmluZWRgIGZvclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIG5vbnBhcnRpY2lwYXRpbmcgY2FwdHVyaW5nIGdyb3Vwc1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmICghY29tcGxpYW50RXhlY05wY2cgJiYgbWF0Y2gubGVuZ3RoID4gMSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBtYXRjaFswXS5yZXBsYWNlKHNlcGFyYXRvcjIsIGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZvciAodmFyIGkgPSAxOyBpIDwgYXJndW1lbnRzLmxlbmd0aCAtIDI7IGkrKykge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChhcmd1bWVudHNbaV0gPT09IHVuZGVmKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1hdGNoW2ldID0gdW5kZWY7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKG1hdGNoLmxlbmd0aCA+IDEgJiYgbWF0Y2guaW5kZXggPCBzdHIubGVuZ3RoKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIEFycmF5LnByb3RvdHlwZS5wdXNoLmFwcGx5KG91dHB1dCwgbWF0Y2guc2xpY2UoMSkpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBsYXN0TGVuZ3RoID0gbWF0Y2hbMF0ubGVuZ3RoO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxhc3RMYXN0SW5kZXggPSBsYXN0SW5kZXg7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKG91dHB1dC5sZW5ndGggPj0gbGltaXQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHNlcGFyYXRvci5sYXN0SW5kZXggPT09IG1hdGNoLmluZGV4KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgc2VwYXJhdG9yLmxhc3RJbmRleCsrOyAvLyBBdm9pZCBhbiBpbmZpbml0ZSBsb29wXG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgaWYgKGxhc3RMYXN0SW5kZXggPT09IHN0ci5sZW5ndGgpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChsYXN0TGVuZ3RoIHx8ICFzZXBhcmF0b3IudGVzdChcIlwiKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIG91dHB1dC5wdXNoKFwiXCIpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgb3V0cHV0LnB1c2goc3RyLnNsaWNlKGxhc3RMYXN0SW5kZXgpKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICByZXR1cm4gb3V0cHV0Lmxlbmd0aCA+IGxpbWl0ID8gb3V0cHV0LnNsaWNlKDAsIGxpbWl0KSA6IG91dHB1dDtcbiAgICAgICAgICAgICAgICB9O1xuXG4gICAgICAgICAgICAgICAgcmV0dXJuIHNlbGY7XG4gICAgICAgICAgICB9KSgpO1xuICAgICAgICB9LCB7fV0sIDY6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7fSwge31dLCA3OiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge1xuICAgICAgICAgICAgXCJ1c2Ugc3RyaWN0XCI7XG5cbiAgICAgICAgICAgIHZhciBPbmVWZXJzaW9uQ29uc3RyYWludCA9IHJlcXVpcmUoXCJpbmRpdmlkdWFsL29uZS12ZXJzaW9uXCIpO1xuXG4gICAgICAgICAgICB2YXIgTVlfVkVSU0lPTiA9IFwiN1wiO1xuICAgICAgICAgICAgT25lVmVyc2lvbkNvbnN0cmFpbnQoXCJldi1zdG9yZVwiLCBNWV9WRVJTSU9OKTtcblxuICAgICAgICAgICAgdmFyIGhhc2hLZXkgPSBcIl9fRVZfU1RPUkVfS0VZQFwiICsgTVlfVkVSU0lPTjtcblxuICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBFdlN0b3JlO1xuXG4gICAgICAgICAgICBmdW5jdGlvbiBFdlN0b3JlKGVsZW0pIHtcbiAgICAgICAgICAgICAgICB2YXIgaGFzaCA9IGVsZW1baGFzaEtleV07XG5cbiAgICAgICAgICAgICAgICBpZiAoIWhhc2gpIHtcbiAgICAgICAgICAgICAgICAgICAgaGFzaCA9IGVsZW1baGFzaEtleV0gPSB7fTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICByZXR1cm4gaGFzaDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSwgeyBcImluZGl2aWR1YWwvb25lLXZlcnNpb25cIjogOSB9XSwgODogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHtcbiAgICAgICAgICAgIChmdW5jdGlvbiAoZ2xvYmFsKSB7XG4gICAgICAgICAgICAgICAgXCJ1c2Ugc3RyaWN0XCI7XG5cbiAgICAgICAgICAgICAgICAvKmdsb2JhbCB3aW5kb3csIGdsb2JhbCovXG5cbiAgICAgICAgICAgICAgICB2YXIgcm9vdCA9IHR5cGVvZiB3aW5kb3cgIT09IFwidW5kZWZpbmVkXCIgPyB3aW5kb3cgOiB0eXBlb2YgZ2xvYmFsICE9PSBcInVuZGVmaW5lZFwiID8gZ2xvYmFsIDoge307XG5cbiAgICAgICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IEluZGl2aWR1YWw7XG5cbiAgICAgICAgICAgICAgICBmdW5jdGlvbiBJbmRpdmlkdWFsKGtleSwgdmFsdWUpIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKGtleSBpbiByb290KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gcm9vdFtrZXldO1xuICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgcm9vdFtrZXldID0gdmFsdWU7XG5cbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHZhbHVlO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0pLmNhbGwodGhpcywgdHlwZW9mIGdsb2JhbCAhPT0gXCJ1bmRlZmluZWRcIiA/IGdsb2JhbCA6IHR5cGVvZiBzZWxmICE9PSBcInVuZGVmaW5lZFwiID8gc2VsZiA6IHR5cGVvZiB3aW5kb3cgIT09IFwidW5kZWZpbmVkXCIgPyB3aW5kb3cgOiB7fSk7XG4gICAgICAgIH0sIHt9XSwgOTogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHtcbiAgICAgICAgICAgIFwidXNlIHN0cmljdFwiO1xuXG4gICAgICAgICAgICB2YXIgSW5kaXZpZHVhbCA9IHJlcXVpcmUoXCIuL2luZGV4LmpzXCIpO1xuXG4gICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IE9uZVZlcnNpb247XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIE9uZVZlcnNpb24obW9kdWxlTmFtZSwgdmVyc2lvbiwgZGVmYXVsdFZhbHVlKSB7XG4gICAgICAgICAgICAgICAgdmFyIGtleSA9IFwiX19JTkRJVklEVUFMX09ORV9WRVJTSU9OX1wiICsgbW9kdWxlTmFtZTtcbiAgICAgICAgICAgICAgICB2YXIgZW5mb3JjZUtleSA9IGtleSArIFwiX0VORk9SQ0VfU0lOR0xFVE9OXCI7XG5cbiAgICAgICAgICAgICAgICB2YXIgdmVyc2lvblZhbHVlID0gSW5kaXZpZHVhbChlbmZvcmNlS2V5LCB2ZXJzaW9uKTtcblxuICAgICAgICAgICAgICAgIGlmICh2ZXJzaW9uVmFsdWUgIT09IHZlcnNpb24pIHtcbiAgICAgICAgICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKFwiQ2FuIG9ubHkgaGF2ZSBvbmUgY29weSBvZiBcIiArIG1vZHVsZU5hbWUgKyBcIi5cXG5cIiArIFwiWW91IGFscmVhZHkgaGF2ZSB2ZXJzaW9uIFwiICsgdmVyc2lvblZhbHVlICsgXCIgaW5zdGFsbGVkLlxcblwiICsgXCJUaGlzIG1lYW5zIHlvdSBjYW5ub3QgaW5zdGFsbCB2ZXJzaW9uIFwiICsgdmVyc2lvbik7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgcmV0dXJuIEluZGl2aWR1YWwoa2V5LCBkZWZhdWx0VmFsdWUpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9LCB7IFwiLi9pbmRleC5qc1wiOiA4IH1dLCAxMDogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHtcbiAgICAgICAgICAgIChmdW5jdGlvbiAoZ2xvYmFsKSB7XG4gICAgICAgICAgICAgICAgdmFyIHRvcExldmVsID0gdHlwZW9mIGdsb2JhbCAhPT0gXCJ1bmRlZmluZWRcIiA/IGdsb2JhbCA6IHR5cGVvZiB3aW5kb3cgIT09IFwidW5kZWZpbmVkXCIgPyB3aW5kb3cgOiB7fTtcbiAgICAgICAgICAgICAgICB2YXIgbWluRG9jID0gcmVxdWlyZShcIm1pbi1kb2N1bWVudFwiKTtcblxuICAgICAgICAgICAgICAgIGlmICh0eXBlb2YgZG9jdW1lbnQgIT09IFwidW5kZWZpbmVkXCIpIHtcbiAgICAgICAgICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBkb2N1bWVudDtcbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICB2YXIgZG9jY3kgPSB0b3BMZXZlbFtcIl9fR0xPQkFMX0RPQ1VNRU5UX0NBQ0hFQDRcIl07XG5cbiAgICAgICAgICAgICAgICAgICAgaWYgKCFkb2NjeSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgZG9jY3kgPSB0b3BMZXZlbFtcIl9fR0xPQkFMX0RPQ1VNRU5UX0NBQ0hFQDRcIl0gPSBtaW5Eb2M7XG4gICAgICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IGRvY2N5O1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0pLmNhbGwodGhpcywgdHlwZW9mIGdsb2JhbCAhPT0gXCJ1bmRlZmluZWRcIiA/IGdsb2JhbCA6IHR5cGVvZiBzZWxmICE9PSBcInVuZGVmaW5lZFwiID8gc2VsZiA6IHR5cGVvZiB3aW5kb3cgIT09IFwidW5kZWZpbmVkXCIgPyB3aW5kb3cgOiB7fSk7XG4gICAgICAgIH0sIHsgXCJtaW4tZG9jdW1lbnRcIjogNiB9XSwgMTE6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICBcInVzZSBzdHJpY3RcIjtcblxuICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiBpc09iamVjdCh4KSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHR5cGVvZiB4ID09PSBcIm9iamVjdFwiICYmIHggIT09IG51bGw7XG4gICAgICAgICAgICB9O1xuICAgICAgICB9LCB7fV0sIDEyOiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge1xuICAgICAgICAgICAgdmFyIG5hdGl2ZUlzQXJyYXkgPSBBcnJheS5pc0FycmF5O1xuICAgICAgICAgICAgdmFyIHRvU3RyaW5nID0gT2JqZWN0LnByb3RvdHlwZS50b1N0cmluZztcblxuICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBuYXRpdmVJc0FycmF5IHx8IGlzQXJyYXk7XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIGlzQXJyYXkob2JqKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHRvU3RyaW5nLmNhbGwob2JqKSA9PT0gXCJbb2JqZWN0IEFycmF5XVwiO1xuICAgICAgICAgICAgfVxuICAgICAgICB9LCB7fV0sIDEzOiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge1xuICAgICAgICAgICAgdmFyIHBhdGNoID0gcmVxdWlyZShcIi4vdmRvbS9wYXRjaC5qc1wiKTtcblxuICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBwYXRjaDtcbiAgICAgICAgfSwgeyBcIi4vdmRvbS9wYXRjaC5qc1wiOiAxOCB9XSwgMTQ6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICB2YXIgaXNPYmplY3QgPSByZXF1aXJlKFwiaXMtb2JqZWN0XCIpO1xuICAgICAgICAgICAgdmFyIGlzSG9vayA9IHJlcXVpcmUoXCIuLi92bm9kZS9pcy12aG9vay5qc1wiKTtcblxuICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBhcHBseVByb3BlcnRpZXM7XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIGFwcGx5UHJvcGVydGllcyhub2RlLCBwcm9wcywgcHJldmlvdXMpIHtcbiAgICAgICAgICAgICAgICBmb3IgKHZhciBwcm9wTmFtZSBpbiBwcm9wcykge1xuICAgICAgICAgICAgICAgICAgICB2YXIgcHJvcFZhbHVlID0gcHJvcHNbcHJvcE5hbWVdO1xuXG4gICAgICAgICAgICAgICAgICAgIGlmIChwcm9wVmFsdWUgPT09IHVuZGVmaW5lZCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgcmVtb3ZlUHJvcGVydHkobm9kZSwgcHJvcE5hbWUsIHByb3BWYWx1ZSwgcHJldmlvdXMpO1xuICAgICAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKGlzSG9vayhwcm9wVmFsdWUpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICByZW1vdmVQcm9wZXJ0eShub2RlLCBwcm9wTmFtZSwgcHJvcFZhbHVlLCBwcmV2aW91cyk7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAocHJvcFZhbHVlLmhvb2spIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBwcm9wVmFsdWUuaG9vayhub2RlLCBwcm9wTmFtZSwgcHJldmlvdXMgPyBwcmV2aW91c1twcm9wTmFtZV0gOiB1bmRlZmluZWQpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGlzT2JqZWN0KHByb3BWYWx1ZSkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBwYXRjaE9iamVjdChub2RlLCBwcm9wcywgcHJldmlvdXMsIHByb3BOYW1lLCBwcm9wVmFsdWUpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBub2RlW3Byb3BOYW1lXSA9IHByb3BWYWx1ZTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZnVuY3Rpb24gcmVtb3ZlUHJvcGVydHkobm9kZSwgcHJvcE5hbWUsIHByb3BWYWx1ZSwgcHJldmlvdXMpIHtcbiAgICAgICAgICAgICAgICBpZiAocHJldmlvdXMpIHtcbiAgICAgICAgICAgICAgICAgICAgdmFyIHByZXZpb3VzVmFsdWUgPSBwcmV2aW91c1twcm9wTmFtZV07XG5cbiAgICAgICAgICAgICAgICAgICAgaWYgKCFpc0hvb2socHJldmlvdXNWYWx1ZSkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChwcm9wTmFtZSA9PT0gXCJhdHRyaWJ1dGVzXCIpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBmb3IgKHZhciBhdHRyTmFtZSBpbiBwcmV2aW91c1ZhbHVlKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG5vZGUucmVtb3ZlQXR0cmlidXRlKGF0dHJOYW1lKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKHByb3BOYW1lID09PSBcInN0eWxlXCIpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBmb3IgKHZhciBpIGluIHByZXZpb3VzVmFsdWUpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbm9kZS5zdHlsZVtpXSA9IFwiXCI7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIGlmICh0eXBlb2YgcHJldmlvdXNWYWx1ZSA9PT0gXCJzdHJpbmdcIikge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIG5vZGVbcHJvcE5hbWVdID0gXCJcIjtcbiAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgbm9kZVtwcm9wTmFtZV0gPSBudWxsO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKHByZXZpb3VzVmFsdWUudW5ob29rKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBwcmV2aW91c1ZhbHVlLnVuaG9vayhub2RlLCBwcm9wTmFtZSwgcHJvcFZhbHVlKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZnVuY3Rpb24gcGF0Y2hPYmplY3Qobm9kZSwgcHJvcHMsIHByZXZpb3VzLCBwcm9wTmFtZSwgcHJvcFZhbHVlKSB7XG4gICAgICAgICAgICAgICAgdmFyIHByZXZpb3VzVmFsdWUgPSBwcmV2aW91cyA/IHByZXZpb3VzW3Byb3BOYW1lXSA6IHVuZGVmaW5lZDtcblxuICAgICAgICAgICAgICAgIC8vIFNldCBhdHRyaWJ1dGVzXG4gICAgICAgICAgICAgICAgaWYgKHByb3BOYW1lID09PSBcImF0dHJpYnV0ZXNcIikge1xuICAgICAgICAgICAgICAgICAgICBmb3IgKHZhciBhdHRyTmFtZSBpbiBwcm9wVmFsdWUpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHZhciBhdHRyVmFsdWUgPSBwcm9wVmFsdWVbYXR0ck5hbWVdO1xuXG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoYXR0clZhbHVlID09PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBub2RlLnJlbW92ZUF0dHJpYnV0ZShhdHRyTmFtZSk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIG5vZGUuc2V0QXR0cmlidXRlKGF0dHJOYW1lLCBhdHRyVmFsdWUpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIGlmIChwcmV2aW91c1ZhbHVlICYmIGlzT2JqZWN0KHByZXZpb3VzVmFsdWUpICYmIGdldFByb3RvdHlwZShwcmV2aW91c1ZhbHVlKSAhPT0gZ2V0UHJvdG90eXBlKHByb3BWYWx1ZSkpIHtcbiAgICAgICAgICAgICAgICAgICAgbm9kZVtwcm9wTmFtZV0gPSBwcm9wVmFsdWU7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICBpZiAoIWlzT2JqZWN0KG5vZGVbcHJvcE5hbWVdKSkge1xuICAgICAgICAgICAgICAgICAgICBub2RlW3Byb3BOYW1lXSA9IHt9O1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHZhciByZXBsYWNlciA9IHByb3BOYW1lID09PSBcInN0eWxlXCIgPyBcIlwiIDogdW5kZWZpbmVkO1xuXG4gICAgICAgICAgICAgICAgZm9yICh2YXIgayBpbiBwcm9wVmFsdWUpIHtcbiAgICAgICAgICAgICAgICAgICAgdmFyIHZhbHVlID0gcHJvcFZhbHVlW2tdO1xuICAgICAgICAgICAgICAgICAgICBub2RlW3Byb3BOYW1lXVtrXSA9IHZhbHVlID09PSB1bmRlZmluZWQgPyByZXBsYWNlciA6IHZhbHVlO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZnVuY3Rpb24gZ2V0UHJvdG90eXBlKHZhbHVlKSB7XG4gICAgICAgICAgICAgICAgaWYgKE9iamVjdC5nZXRQcm90b3R5cGVPZikge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gT2JqZWN0LmdldFByb3RvdHlwZU9mKHZhbHVlKTtcbiAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKHZhbHVlLl9fcHJvdG9fXykge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gdmFsdWUuX19wcm90b19fO1xuICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAodmFsdWUuY29uc3RydWN0b3IpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHZhbHVlLmNvbnN0cnVjdG9yLnByb3RvdHlwZTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH0sIHsgXCIuLi92bm9kZS9pcy12aG9vay5qc1wiOiAyNiwgXCJpcy1vYmplY3RcIjogMTEgfV0sIDE1OiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge1xuICAgICAgICAgICAgdmFyIGRvY3VtZW50ID0gcmVxdWlyZShcImdsb2JhbC9kb2N1bWVudFwiKTtcblxuICAgICAgICAgICAgdmFyIGFwcGx5UHJvcGVydGllcyA9IHJlcXVpcmUoXCIuL2FwcGx5LXByb3BlcnRpZXNcIik7XG5cbiAgICAgICAgICAgIHZhciBpc1ZOb2RlID0gcmVxdWlyZShcIi4uL3Zub2RlL2lzLXZub2RlLmpzXCIpO1xuICAgICAgICAgICAgdmFyIGlzVlRleHQgPSByZXF1aXJlKFwiLi4vdm5vZGUvaXMtdnRleHQuanNcIik7XG4gICAgICAgICAgICB2YXIgaXNXaWRnZXQgPSByZXF1aXJlKFwiLi4vdm5vZGUvaXMtd2lkZ2V0LmpzXCIpO1xuICAgICAgICAgICAgdmFyIGhhbmRsZVRodW5rID0gcmVxdWlyZShcIi4uL3Zub2RlL2hhbmRsZS10aHVuay5qc1wiKTtcblxuICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBjcmVhdGVFbGVtZW50O1xuXG4gICAgICAgICAgICBmdW5jdGlvbiBjcmVhdGVFbGVtZW50KHZub2RlLCBvcHRzKSB7XG4gICAgICAgICAgICAgICAgdmFyIGRvYyA9IG9wdHMgPyBvcHRzLmRvY3VtZW50IHx8IGRvY3VtZW50IDogZG9jdW1lbnQ7XG4gICAgICAgICAgICAgICAgdmFyIHdhcm4gPSBvcHRzID8gb3B0cy53YXJuIDogbnVsbDtcblxuICAgICAgICAgICAgICAgIHZub2RlID0gaGFuZGxlVGh1bmsodm5vZGUpLmE7XG5cbiAgICAgICAgICAgICAgICBpZiAoaXNXaWRnZXQodm5vZGUpKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiB2bm9kZS5pbml0KCk7XG4gICAgICAgICAgICAgICAgfSBlbHNlIGlmIChpc1ZUZXh0KHZub2RlKSkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gZG9jLmNyZWF0ZVRleHROb2RlKHZub2RlLnRleHQpO1xuICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoIWlzVk5vZGUodm5vZGUpKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmICh3YXJuKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICB3YXJuKFwiSXRlbSBpcyBub3QgYSB2YWxpZCB2aXJ0dWFsIGRvbSBub2RlXCIsIHZub2RlKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICByZXR1cm4gbnVsbDtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICB2YXIgbm9kZSA9IHZub2RlLm5hbWVzcGFjZSA9PT0gbnVsbCA/IGRvYy5jcmVhdGVFbGVtZW50KHZub2RlLnRhZ05hbWUpIDogZG9jLmNyZWF0ZUVsZW1lbnROUyh2bm9kZS5uYW1lc3BhY2UsIHZub2RlLnRhZ05hbWUpO1xuXG4gICAgICAgICAgICAgICAgdmFyIHByb3BzID0gdm5vZGUucHJvcGVydGllcztcbiAgICAgICAgICAgICAgICBhcHBseVByb3BlcnRpZXMobm9kZSwgcHJvcHMpO1xuXG4gICAgICAgICAgICAgICAgdmFyIGNoaWxkcmVuID0gdm5vZGUuY2hpbGRyZW47XG5cbiAgICAgICAgICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IGNoaWxkcmVuLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciBjaGlsZE5vZGUgPSBjcmVhdGVFbGVtZW50KGNoaWxkcmVuW2ldLCBvcHRzKTtcbiAgICAgICAgICAgICAgICAgICAgaWYgKGNoaWxkTm9kZSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgbm9kZS5hcHBlbmRDaGlsZChjaGlsZE5vZGUpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgcmV0dXJuIG5vZGU7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0sIHsgXCIuLi92bm9kZS9oYW5kbGUtdGh1bmsuanNcIjogMjQsIFwiLi4vdm5vZGUvaXMtdm5vZGUuanNcIjogMjcsIFwiLi4vdm5vZGUvaXMtdnRleHQuanNcIjogMjgsIFwiLi4vdm5vZGUvaXMtd2lkZ2V0LmpzXCI6IDI5LCBcIi4vYXBwbHktcHJvcGVydGllc1wiOiAxNCwgXCJnbG9iYWwvZG9jdW1lbnRcIjogMTAgfV0sIDE2OiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge1xuICAgICAgICAgICAgLy8gTWFwcyBhIHZpcnR1YWwgRE9NIHRyZWUgb250byBhIHJlYWwgRE9NIHRyZWUgaW4gYW4gZWZmaWNpZW50IG1hbm5lci5cbiAgICAgICAgICAgIC8vIFdlIGRvbid0IHdhbnQgdG8gcmVhZCBhbGwgb2YgdGhlIERPTSBub2RlcyBpbiB0aGUgdHJlZSBzbyB3ZSB1c2VcbiAgICAgICAgICAgIC8vIHRoZSBpbi1vcmRlciB0cmVlIGluZGV4aW5nIHRvIGVsaW1pbmF0ZSByZWN1cnNpb24gZG93biBjZXJ0YWluIGJyYW5jaGVzLlxuICAgICAgICAgICAgLy8gV2Ugb25seSByZWN1cnNlIGludG8gYSBET00gbm9kZSBpZiB3ZSBrbm93IHRoYXQgaXQgY29udGFpbnMgYSBjaGlsZCBvZlxuICAgICAgICAgICAgLy8gaW50ZXJlc3QuXG5cbiAgICAgICAgICAgIHZhciBub0NoaWxkID0ge307XG5cbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gZG9tSW5kZXg7XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIGRvbUluZGV4KHJvb3ROb2RlLCB0cmVlLCBpbmRpY2VzLCBub2Rlcykge1xuICAgICAgICAgICAgICAgIGlmICghaW5kaWNlcyB8fCBpbmRpY2VzLmxlbmd0aCA9PT0gMCkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4ge307XG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgaW5kaWNlcy5zb3J0KGFzY2VuZGluZyk7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiByZWN1cnNlKHJvb3ROb2RlLCB0cmVlLCBpbmRpY2VzLCBub2RlcywgMCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBmdW5jdGlvbiByZWN1cnNlKHJvb3ROb2RlLCB0cmVlLCBpbmRpY2VzLCBub2Rlcywgcm9vdEluZGV4KSB7XG4gICAgICAgICAgICAgICAgbm9kZXMgPSBub2RlcyB8fCB7fTtcblxuICAgICAgICAgICAgICAgIGlmIChyb290Tm9kZSkge1xuICAgICAgICAgICAgICAgICAgICBpZiAoaW5kZXhJblJhbmdlKGluZGljZXMsIHJvb3RJbmRleCwgcm9vdEluZGV4KSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgbm9kZXNbcm9vdEluZGV4XSA9IHJvb3ROb2RlO1xuICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgdmFyIHZDaGlsZHJlbiA9IHRyZWUuY2hpbGRyZW47XG5cbiAgICAgICAgICAgICAgICAgICAgaWYgKHZDaGlsZHJlbikge1xuXG4gICAgICAgICAgICAgICAgICAgICAgICB2YXIgY2hpbGROb2RlcyA9IHJvb3ROb2RlLmNoaWxkTm9kZXM7XG5cbiAgICAgICAgICAgICAgICAgICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgdHJlZS5jaGlsZHJlbi5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJvb3RJbmRleCArPSAxO1xuXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdmFyIHZDaGlsZCA9IHZDaGlsZHJlbltpXSB8fCBub0NoaWxkO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZhciBuZXh0SW5kZXggPSByb290SW5kZXggKyAodkNoaWxkLmNvdW50IHx8IDApO1xuXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gc2tpcCByZWN1cnNpb24gZG93biB0aGUgdHJlZSBpZiB0aGVyZSBhcmUgbm8gbm9kZXMgZG93biBoZXJlXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGluZGV4SW5SYW5nZShpbmRpY2VzLCByb290SW5kZXgsIG5leHRJbmRleCkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmVjdXJzZShjaGlsZE5vZGVzW2ldLCB2Q2hpbGQsIGluZGljZXMsIG5vZGVzLCByb290SW5kZXgpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJvb3RJbmRleCA9IG5leHRJbmRleDtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHJldHVybiBub2RlcztcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgLy8gQmluYXJ5IHNlYXJjaCBmb3IgYW4gaW5kZXggaW4gdGhlIGludGVydmFsIFtsZWZ0LCByaWdodF1cbiAgICAgICAgICAgIGZ1bmN0aW9uIGluZGV4SW5SYW5nZShpbmRpY2VzLCBsZWZ0LCByaWdodCkge1xuICAgICAgICAgICAgICAgIGlmIChpbmRpY2VzLmxlbmd0aCA9PT0gMCkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgdmFyIG1pbkluZGV4ID0gMDtcbiAgICAgICAgICAgICAgICB2YXIgbWF4SW5kZXggPSBpbmRpY2VzLmxlbmd0aCAtIDE7XG4gICAgICAgICAgICAgICAgdmFyIGN1cnJlbnRJbmRleDtcbiAgICAgICAgICAgICAgICB2YXIgY3VycmVudEl0ZW07XG5cbiAgICAgICAgICAgICAgICB3aGlsZSAobWluSW5kZXggPD0gbWF4SW5kZXgpIHtcbiAgICAgICAgICAgICAgICAgICAgY3VycmVudEluZGV4ID0gKG1heEluZGV4ICsgbWluSW5kZXgpIC8gMiA+PiAwO1xuICAgICAgICAgICAgICAgICAgICBjdXJyZW50SXRlbSA9IGluZGljZXNbY3VycmVudEluZGV4XTtcblxuICAgICAgICAgICAgICAgICAgICBpZiAobWluSW5kZXggPT09IG1heEluZGV4KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gY3VycmVudEl0ZW0gPj0gbGVmdCAmJiBjdXJyZW50SXRlbSA8PSByaWdodDtcbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIGlmIChjdXJyZW50SXRlbSA8IGxlZnQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIG1pbkluZGV4ID0gY3VycmVudEluZGV4ICsgMTtcbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIGlmIChjdXJyZW50SXRlbSA+IHJpZ2h0KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBtYXhJbmRleCA9IGN1cnJlbnRJbmRleCAtIDE7XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZnVuY3Rpb24gYXNjZW5kaW5nKGEsIGIpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gYSA+IGIgPyAxIDogLTE7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0sIHt9XSwgMTc6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICB2YXIgYXBwbHlQcm9wZXJ0aWVzID0gcmVxdWlyZShcIi4vYXBwbHktcHJvcGVydGllc1wiKTtcblxuICAgICAgICAgICAgdmFyIGlzV2lkZ2V0ID0gcmVxdWlyZShcIi4uL3Zub2RlL2lzLXdpZGdldC5qc1wiKTtcbiAgICAgICAgICAgIHZhciBWUGF0Y2ggPSByZXF1aXJlKFwiLi4vdm5vZGUvdnBhdGNoLmpzXCIpO1xuXG4gICAgICAgICAgICB2YXIgdXBkYXRlV2lkZ2V0ID0gcmVxdWlyZShcIi4vdXBkYXRlLXdpZGdldFwiKTtcblxuICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBhcHBseVBhdGNoO1xuXG4gICAgICAgICAgICBmdW5jdGlvbiBhcHBseVBhdGNoKHZwYXRjaCwgZG9tTm9kZSwgcmVuZGVyT3B0aW9ucykge1xuICAgICAgICAgICAgICAgIHZhciB0eXBlID0gdnBhdGNoLnR5cGU7XG4gICAgICAgICAgICAgICAgdmFyIHZOb2RlID0gdnBhdGNoLnZOb2RlO1xuICAgICAgICAgICAgICAgIHZhciBwYXRjaCA9IHZwYXRjaC5wYXRjaDtcblxuICAgICAgICAgICAgICAgIHN3aXRjaCAodHlwZSkge1xuICAgICAgICAgICAgICAgICAgICBjYXNlIFZQYXRjaC5SRU1PVkU6XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gcmVtb3ZlTm9kZShkb21Ob2RlLCB2Tm9kZSk7XG4gICAgICAgICAgICAgICAgICAgIGNhc2UgVlBhdGNoLklOU0VSVDpcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBpbnNlcnROb2RlKGRvbU5vZGUsIHBhdGNoLCByZW5kZXJPcHRpb25zKTtcbiAgICAgICAgICAgICAgICAgICAgY2FzZSBWUGF0Y2guVlRFWFQ6XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gc3RyaW5nUGF0Y2goZG9tTm9kZSwgdk5vZGUsIHBhdGNoLCByZW5kZXJPcHRpb25zKTtcbiAgICAgICAgICAgICAgICAgICAgY2FzZSBWUGF0Y2guV0lER0VUOlxuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHdpZGdldFBhdGNoKGRvbU5vZGUsIHZOb2RlLCBwYXRjaCwgcmVuZGVyT3B0aW9ucyk7XG4gICAgICAgICAgICAgICAgICAgIGNhc2UgVlBhdGNoLlZOT0RFOlxuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHZOb2RlUGF0Y2goZG9tTm9kZSwgdk5vZGUsIHBhdGNoLCByZW5kZXJPcHRpb25zKTtcbiAgICAgICAgICAgICAgICAgICAgY2FzZSBWUGF0Y2guT1JERVI6XG4gICAgICAgICAgICAgICAgICAgICAgICByZW9yZGVyQ2hpbGRyZW4oZG9tTm9kZSwgcGF0Y2gpO1xuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGRvbU5vZGU7XG4gICAgICAgICAgICAgICAgICAgIGNhc2UgVlBhdGNoLlBST1BTOlxuICAgICAgICAgICAgICAgICAgICAgICAgYXBwbHlQcm9wZXJ0aWVzKGRvbU5vZGUsIHBhdGNoLCB2Tm9kZS5wcm9wZXJ0aWVzKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBkb21Ob2RlO1xuICAgICAgICAgICAgICAgICAgICBjYXNlIFZQYXRjaC5USFVOSzpcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiByZXBsYWNlUm9vdChkb21Ob2RlLCByZW5kZXJPcHRpb25zLnBhdGNoKGRvbU5vZGUsIHBhdGNoLCByZW5kZXJPcHRpb25zKSk7XG4gICAgICAgICAgICAgICAgICAgIGRlZmF1bHQ6XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gZG9tTm9kZTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIHJlbW92ZU5vZGUoZG9tTm9kZSwgdk5vZGUpIHtcbiAgICAgICAgICAgICAgICB2YXIgcGFyZW50Tm9kZSA9IGRvbU5vZGUucGFyZW50Tm9kZTtcblxuICAgICAgICAgICAgICAgIGlmIChwYXJlbnROb2RlKSB7XG4gICAgICAgICAgICAgICAgICAgIHBhcmVudE5vZGUucmVtb3ZlQ2hpbGQoZG9tTm9kZSk7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgZGVzdHJveVdpZGdldChkb21Ob2RlLCB2Tm9kZSk7XG5cbiAgICAgICAgICAgICAgICByZXR1cm4gbnVsbDtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZnVuY3Rpb24gaW5zZXJ0Tm9kZShwYXJlbnROb2RlLCB2Tm9kZSwgcmVuZGVyT3B0aW9ucykge1xuICAgICAgICAgICAgICAgIHZhciBuZXdOb2RlID0gcmVuZGVyT3B0aW9ucy5yZW5kZXIodk5vZGUsIHJlbmRlck9wdGlvbnMpO1xuXG4gICAgICAgICAgICAgICAgaWYgKHBhcmVudE5vZGUpIHtcbiAgICAgICAgICAgICAgICAgICAgcGFyZW50Tm9kZS5hcHBlbmRDaGlsZChuZXdOb2RlKTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICByZXR1cm4gcGFyZW50Tm9kZTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZnVuY3Rpb24gc3RyaW5nUGF0Y2goZG9tTm9kZSwgbGVmdFZOb2RlLCB2VGV4dCwgcmVuZGVyT3B0aW9ucykge1xuICAgICAgICAgICAgICAgIHZhciBuZXdOb2RlO1xuXG4gICAgICAgICAgICAgICAgaWYgKGRvbU5vZGUubm9kZVR5cGUgPT09IDMpIHtcbiAgICAgICAgICAgICAgICAgICAgZG9tTm9kZS5yZXBsYWNlRGF0YSgwLCBkb21Ob2RlLmxlbmd0aCwgdlRleHQudGV4dCk7XG4gICAgICAgICAgICAgICAgICAgIG5ld05vZGUgPSBkb21Ob2RlO1xuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciBwYXJlbnROb2RlID0gZG9tTm9kZS5wYXJlbnROb2RlO1xuICAgICAgICAgICAgICAgICAgICBuZXdOb2RlID0gcmVuZGVyT3B0aW9ucy5yZW5kZXIodlRleHQsIHJlbmRlck9wdGlvbnMpO1xuXG4gICAgICAgICAgICAgICAgICAgIGlmIChwYXJlbnROb2RlICYmIG5ld05vZGUgIT09IGRvbU5vZGUpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHBhcmVudE5vZGUucmVwbGFjZUNoaWxkKG5ld05vZGUsIGRvbU5vZGUpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgcmV0dXJuIG5ld05vZGU7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIHdpZGdldFBhdGNoKGRvbU5vZGUsIGxlZnRWTm9kZSwgd2lkZ2V0LCByZW5kZXJPcHRpb25zKSB7XG4gICAgICAgICAgICAgICAgdmFyIHVwZGF0aW5nID0gdXBkYXRlV2lkZ2V0KGxlZnRWTm9kZSwgd2lkZ2V0KTtcbiAgICAgICAgICAgICAgICB2YXIgbmV3Tm9kZTtcblxuICAgICAgICAgICAgICAgIGlmICh1cGRhdGluZykge1xuICAgICAgICAgICAgICAgICAgICBuZXdOb2RlID0gd2lkZ2V0LnVwZGF0ZShsZWZ0Vk5vZGUsIGRvbU5vZGUpIHx8IGRvbU5vZGU7XG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgbmV3Tm9kZSA9IHJlbmRlck9wdGlvbnMucmVuZGVyKHdpZGdldCwgcmVuZGVyT3B0aW9ucyk7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgdmFyIHBhcmVudE5vZGUgPSBkb21Ob2RlLnBhcmVudE5vZGU7XG5cbiAgICAgICAgICAgICAgICBpZiAocGFyZW50Tm9kZSAmJiBuZXdOb2RlICE9PSBkb21Ob2RlKSB7XG4gICAgICAgICAgICAgICAgICAgIHBhcmVudE5vZGUucmVwbGFjZUNoaWxkKG5ld05vZGUsIGRvbU5vZGUpO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIGlmICghdXBkYXRpbmcpIHtcbiAgICAgICAgICAgICAgICAgICAgZGVzdHJveVdpZGdldChkb21Ob2RlLCBsZWZ0Vk5vZGUpO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHJldHVybiBuZXdOb2RlO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBmdW5jdGlvbiB2Tm9kZVBhdGNoKGRvbU5vZGUsIGxlZnRWTm9kZSwgdk5vZGUsIHJlbmRlck9wdGlvbnMpIHtcbiAgICAgICAgICAgICAgICB2YXIgcGFyZW50Tm9kZSA9IGRvbU5vZGUucGFyZW50Tm9kZTtcbiAgICAgICAgICAgICAgICB2YXIgbmV3Tm9kZSA9IHJlbmRlck9wdGlvbnMucmVuZGVyKHZOb2RlLCByZW5kZXJPcHRpb25zKTtcblxuICAgICAgICAgICAgICAgIGlmIChwYXJlbnROb2RlICYmIG5ld05vZGUgIT09IGRvbU5vZGUpIHtcbiAgICAgICAgICAgICAgICAgICAgcGFyZW50Tm9kZS5yZXBsYWNlQ2hpbGQobmV3Tm9kZSwgZG9tTm9kZSk7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgcmV0dXJuIG5ld05vZGU7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIGRlc3Ryb3lXaWRnZXQoZG9tTm9kZSwgdykge1xuICAgICAgICAgICAgICAgIGlmICh0eXBlb2Ygdy5kZXN0cm95ID09PSBcImZ1bmN0aW9uXCIgJiYgaXNXaWRnZXQodykpIHtcbiAgICAgICAgICAgICAgICAgICAgdy5kZXN0cm95KGRvbU5vZGUpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZnVuY3Rpb24gcmVvcmRlckNoaWxkcmVuKGRvbU5vZGUsIG1vdmVzKSB7XG4gICAgICAgICAgICAgICAgdmFyIGNoaWxkTm9kZXMgPSBkb21Ob2RlLmNoaWxkTm9kZXM7XG4gICAgICAgICAgICAgICAgdmFyIGtleU1hcCA9IHt9O1xuICAgICAgICAgICAgICAgIHZhciBub2RlO1xuICAgICAgICAgICAgICAgIHZhciByZW1vdmU7XG4gICAgICAgICAgICAgICAgdmFyIGluc2VydDtcblxuICAgICAgICAgICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgbW92ZXMucmVtb3Zlcy5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgICAgICAgICByZW1vdmUgPSBtb3Zlcy5yZW1vdmVzW2ldO1xuICAgICAgICAgICAgICAgICAgICBub2RlID0gY2hpbGROb2Rlc1tyZW1vdmUuZnJvbV07XG4gICAgICAgICAgICAgICAgICAgIGlmIChyZW1vdmUua2V5KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBrZXlNYXBbcmVtb3ZlLmtleV0gPSBub2RlO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIGRvbU5vZGUucmVtb3ZlQ2hpbGQobm9kZSk7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgdmFyIGxlbmd0aCA9IGNoaWxkTm9kZXMubGVuZ3RoO1xuICAgICAgICAgICAgICAgIGZvciAodmFyIGogPSAwOyBqIDwgbW92ZXMuaW5zZXJ0cy5sZW5ndGg7IGorKykge1xuICAgICAgICAgICAgICAgICAgICBpbnNlcnQgPSBtb3Zlcy5pbnNlcnRzW2pdO1xuICAgICAgICAgICAgICAgICAgICBub2RlID0ga2V5TWFwW2luc2VydC5rZXldO1xuICAgICAgICAgICAgICAgICAgICAvLyB0aGlzIGlzIHRoZSB3ZWlyZGVzdCBidWcgaSd2ZSBldmVyIHNlZW4gaW4gd2Via2l0XG4gICAgICAgICAgICAgICAgICAgIGRvbU5vZGUuaW5zZXJ0QmVmb3JlKG5vZGUsIGluc2VydC50byA+PSBsZW5ndGgrKyA/IG51bGwgOiBjaGlsZE5vZGVzW2luc2VydC50b10pO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZnVuY3Rpb24gcmVwbGFjZVJvb3Qob2xkUm9vdCwgbmV3Um9vdCkge1xuICAgICAgICAgICAgICAgIGlmIChvbGRSb290ICYmIG5ld1Jvb3QgJiYgb2xkUm9vdCAhPT0gbmV3Um9vdCAmJiBvbGRSb290LnBhcmVudE5vZGUpIHtcbiAgICAgICAgICAgICAgICAgICAgb2xkUm9vdC5wYXJlbnROb2RlLnJlcGxhY2VDaGlsZChuZXdSb290LCBvbGRSb290KTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICByZXR1cm4gbmV3Um9vdDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSwgeyBcIi4uL3Zub2RlL2lzLXdpZGdldC5qc1wiOiAyOSwgXCIuLi92bm9kZS92cGF0Y2guanNcIjogMzIsIFwiLi9hcHBseS1wcm9wZXJ0aWVzXCI6IDE0LCBcIi4vdXBkYXRlLXdpZGdldFwiOiAxOSB9XSwgMTg6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICB2YXIgZG9jdW1lbnQgPSByZXF1aXJlKFwiZ2xvYmFsL2RvY3VtZW50XCIpO1xuICAgICAgICAgICAgdmFyIGlzQXJyYXkgPSByZXF1aXJlKFwieC1pcy1hcnJheVwiKTtcblxuICAgICAgICAgICAgdmFyIHJlbmRlciA9IHJlcXVpcmUoXCIuL2NyZWF0ZS1lbGVtZW50XCIpO1xuICAgICAgICAgICAgdmFyIGRvbUluZGV4ID0gcmVxdWlyZShcIi4vZG9tLWluZGV4XCIpO1xuICAgICAgICAgICAgdmFyIHBhdGNoT3AgPSByZXF1aXJlKFwiLi9wYXRjaC1vcFwiKTtcbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gcGF0Y2g7XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIHBhdGNoKHJvb3ROb2RlLCBwYXRjaGVzLCByZW5kZXJPcHRpb25zKSB7XG4gICAgICAgICAgICAgICAgcmVuZGVyT3B0aW9ucyA9IHJlbmRlck9wdGlvbnMgfHwge307XG4gICAgICAgICAgICAgICAgcmVuZGVyT3B0aW9ucy5wYXRjaCA9IHJlbmRlck9wdGlvbnMucGF0Y2ggJiYgcmVuZGVyT3B0aW9ucy5wYXRjaCAhPT0gcGF0Y2ggPyByZW5kZXJPcHRpb25zLnBhdGNoIDogcGF0Y2hSZWN1cnNpdmU7XG4gICAgICAgICAgICAgICAgcmVuZGVyT3B0aW9ucy5yZW5kZXIgPSByZW5kZXJPcHRpb25zLnJlbmRlciB8fCByZW5kZXI7XG5cbiAgICAgICAgICAgICAgICByZXR1cm4gcmVuZGVyT3B0aW9ucy5wYXRjaChyb290Tm9kZSwgcGF0Y2hlcywgcmVuZGVyT3B0aW9ucyk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIHBhdGNoUmVjdXJzaXZlKHJvb3ROb2RlLCBwYXRjaGVzLCByZW5kZXJPcHRpb25zKSB7XG4gICAgICAgICAgICAgICAgdmFyIGluZGljZXMgPSBwYXRjaEluZGljZXMocGF0Y2hlcyk7XG5cbiAgICAgICAgICAgICAgICBpZiAoaW5kaWNlcy5sZW5ndGggPT09IDApIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHJvb3ROb2RlO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHZhciBpbmRleCA9IGRvbUluZGV4KHJvb3ROb2RlLCBwYXRjaGVzLmEsIGluZGljZXMpO1xuICAgICAgICAgICAgICAgIHZhciBvd25lckRvY3VtZW50ID0gcm9vdE5vZGUub3duZXJEb2N1bWVudDtcblxuICAgICAgICAgICAgICAgIGlmICghcmVuZGVyT3B0aW9ucy5kb2N1bWVudCAmJiBvd25lckRvY3VtZW50ICE9PSBkb2N1bWVudCkge1xuICAgICAgICAgICAgICAgICAgICByZW5kZXJPcHRpb25zLmRvY3VtZW50ID0gb3duZXJEb2N1bWVudDtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IGluZGljZXMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgICAgICAgICAgdmFyIG5vZGVJbmRleCA9IGluZGljZXNbaV07XG4gICAgICAgICAgICAgICAgICAgIHJvb3ROb2RlID0gYXBwbHlQYXRjaChyb290Tm9kZSwgaW5kZXhbbm9kZUluZGV4XSwgcGF0Y2hlc1tub2RlSW5kZXhdLCByZW5kZXJPcHRpb25zKTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICByZXR1cm4gcm9vdE5vZGU7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIGFwcGx5UGF0Y2gocm9vdE5vZGUsIGRvbU5vZGUsIHBhdGNoTGlzdCwgcmVuZGVyT3B0aW9ucykge1xuICAgICAgICAgICAgICAgIGlmICghZG9tTm9kZSkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gcm9vdE5vZGU7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgdmFyIG5ld05vZGU7XG5cbiAgICAgICAgICAgICAgICBpZiAoaXNBcnJheShwYXRjaExpc3QpKSB7XG4gICAgICAgICAgICAgICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgcGF0Y2hMaXN0Lmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBuZXdOb2RlID0gcGF0Y2hPcChwYXRjaExpc3RbaV0sIGRvbU5vZGUsIHJlbmRlck9wdGlvbnMpO1xuXG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoZG9tTm9kZSA9PT0gcm9vdE5vZGUpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICByb290Tm9kZSA9IG5ld05vZGU7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICBuZXdOb2RlID0gcGF0Y2hPcChwYXRjaExpc3QsIGRvbU5vZGUsIHJlbmRlck9wdGlvbnMpO1xuXG4gICAgICAgICAgICAgICAgICAgIGlmIChkb21Ob2RlID09PSByb290Tm9kZSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgcm9vdE5vZGUgPSBuZXdOb2RlO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgcmV0dXJuIHJvb3ROb2RlO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBmdW5jdGlvbiBwYXRjaEluZGljZXMocGF0Y2hlcykge1xuICAgICAgICAgICAgICAgIHZhciBpbmRpY2VzID0gW107XG5cbiAgICAgICAgICAgICAgICBmb3IgKHZhciBrZXkgaW4gcGF0Y2hlcykge1xuICAgICAgICAgICAgICAgICAgICBpZiAoa2V5ICE9PSBcImFcIikge1xuICAgICAgICAgICAgICAgICAgICAgICAgaW5kaWNlcy5wdXNoKE51bWJlcihrZXkpKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHJldHVybiBpbmRpY2VzO1xuICAgICAgICAgICAgfVxuICAgICAgICB9LCB7IFwiLi9jcmVhdGUtZWxlbWVudFwiOiAxNSwgXCIuL2RvbS1pbmRleFwiOiAxNiwgXCIuL3BhdGNoLW9wXCI6IDE3LCBcImdsb2JhbC9kb2N1bWVudFwiOiAxMCwgXCJ4LWlzLWFycmF5XCI6IDEyIH1dLCAxOTogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHtcbiAgICAgICAgICAgIHZhciBpc1dpZGdldCA9IHJlcXVpcmUoXCIuLi92bm9kZS9pcy13aWRnZXQuanNcIik7XG5cbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gdXBkYXRlV2lkZ2V0O1xuXG4gICAgICAgICAgICBmdW5jdGlvbiB1cGRhdGVXaWRnZXQoYSwgYikge1xuICAgICAgICAgICAgICAgIGlmIChpc1dpZGdldChhKSAmJiBpc1dpZGdldChiKSkge1xuICAgICAgICAgICAgICAgICAgICBpZiAoXCJuYW1lXCIgaW4gYSAmJiBcIm5hbWVcIiBpbiBiKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gYS5pZCA9PT0gYi5pZDtcbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBhLmluaXQgPT09IGIuaW5pdDtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSwgeyBcIi4uL3Zub2RlL2lzLXdpZGdldC5qc1wiOiAyOSB9XSwgMjA6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICBcInVzZSBzdHJpY3RcIjtcblxuICAgICAgICAgICAgdmFyIEV2U3RvcmUgPSByZXF1aXJlKFwiZXYtc3RvcmVcIik7XG5cbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gRXZIb29rO1xuXG4gICAgICAgICAgICBmdW5jdGlvbiBFdkhvb2sodmFsdWUpIHtcbiAgICAgICAgICAgICAgICBpZiAoISh0aGlzIGluc3RhbmNlb2YgRXZIb29rKSkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gbmV3IEV2SG9vayh2YWx1ZSk7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgdGhpcy52YWx1ZSA9IHZhbHVlO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBFdkhvb2sucHJvdG90eXBlLmhvb2sgPSBmdW5jdGlvbiAobm9kZSwgcHJvcGVydHlOYW1lKSB7XG4gICAgICAgICAgICAgICAgdmFyIGVzID0gRXZTdG9yZShub2RlKTtcbiAgICAgICAgICAgICAgICB2YXIgcHJvcE5hbWUgPSBwcm9wZXJ0eU5hbWUuc3Vic3RyKDMpO1xuXG4gICAgICAgICAgICAgICAgZXNbcHJvcE5hbWVdID0gdGhpcy52YWx1ZTtcbiAgICAgICAgICAgIH07XG5cbiAgICAgICAgICAgIEV2SG9vay5wcm90b3R5cGUudW5ob29rID0gZnVuY3Rpb24gKG5vZGUsIHByb3BlcnR5TmFtZSkge1xuICAgICAgICAgICAgICAgIHZhciBlcyA9IEV2U3RvcmUobm9kZSk7XG4gICAgICAgICAgICAgICAgdmFyIHByb3BOYW1lID0gcHJvcGVydHlOYW1lLnN1YnN0cigzKTtcblxuICAgICAgICAgICAgICAgIGVzW3Byb3BOYW1lXSA9IHVuZGVmaW5lZDtcbiAgICAgICAgICAgIH07XG4gICAgICAgIH0sIHsgXCJldi1zdG9yZVwiOiA3IH1dLCAyMTogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHtcbiAgICAgICAgICAgIFwidXNlIHN0cmljdFwiO1xuXG4gICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IFNvZnRTZXRIb29rO1xuXG4gICAgICAgICAgICBmdW5jdGlvbiBTb2Z0U2V0SG9vayh2YWx1ZSkge1xuICAgICAgICAgICAgICAgIGlmICghKHRoaXMgaW5zdGFuY2VvZiBTb2Z0U2V0SG9vaykpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIG5ldyBTb2Z0U2V0SG9vayh2YWx1ZSk7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgdGhpcy52YWx1ZSA9IHZhbHVlO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBTb2Z0U2V0SG9vay5wcm90b3R5cGUuaG9vayA9IGZ1bmN0aW9uIChub2RlLCBwcm9wZXJ0eU5hbWUpIHtcbiAgICAgICAgICAgICAgICBpZiAobm9kZVtwcm9wZXJ0eU5hbWVdICE9PSB0aGlzLnZhbHVlKSB7XG4gICAgICAgICAgICAgICAgICAgIG5vZGVbcHJvcGVydHlOYW1lXSA9IHRoaXMudmFsdWU7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfTtcbiAgICAgICAgfSwge31dLCAyMjogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHtcbiAgICAgICAgICAgIFwidXNlIHN0cmljdFwiO1xuXG4gICAgICAgICAgICB2YXIgaXNBcnJheSA9IHJlcXVpcmUoXCJ4LWlzLWFycmF5XCIpO1xuXG4gICAgICAgICAgICB2YXIgVk5vZGUgPSByZXF1aXJlKFwiLi4vdm5vZGUvdm5vZGUuanNcIik7XG4gICAgICAgICAgICB2YXIgVlRleHQgPSByZXF1aXJlKFwiLi4vdm5vZGUvdnRleHQuanNcIik7XG4gICAgICAgICAgICB2YXIgaXNWTm9kZSA9IHJlcXVpcmUoXCIuLi92bm9kZS9pcy12bm9kZVwiKTtcbiAgICAgICAgICAgIHZhciBpc1ZUZXh0ID0gcmVxdWlyZShcIi4uL3Zub2RlL2lzLXZ0ZXh0XCIpO1xuICAgICAgICAgICAgdmFyIGlzV2lkZ2V0ID0gcmVxdWlyZShcIi4uL3Zub2RlL2lzLXdpZGdldFwiKTtcbiAgICAgICAgICAgIHZhciBpc0hvb2sgPSByZXF1aXJlKFwiLi4vdm5vZGUvaXMtdmhvb2tcIik7XG4gICAgICAgICAgICB2YXIgaXNWVGh1bmsgPSByZXF1aXJlKFwiLi4vdm5vZGUvaXMtdGh1bmtcIik7XG5cbiAgICAgICAgICAgIHZhciBwYXJzZVRhZyA9IHJlcXVpcmUoXCIuL3BhcnNlLXRhZy5qc1wiKTtcbiAgICAgICAgICAgIHZhciBzb2Z0U2V0SG9vayA9IHJlcXVpcmUoXCIuL2hvb2tzL3NvZnQtc2V0LWhvb2suanNcIik7XG4gICAgICAgICAgICB2YXIgZXZIb29rID0gcmVxdWlyZShcIi4vaG9va3MvZXYtaG9vay5qc1wiKTtcblxuICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBoO1xuXG4gICAgICAgICAgICBmdW5jdGlvbiBoKHRhZ05hbWUsIHByb3BlcnRpZXMsIGNoaWxkcmVuKSB7XG4gICAgICAgICAgICAgICAgdmFyIGNoaWxkTm9kZXMgPSBbXTtcbiAgICAgICAgICAgICAgICB2YXIgdGFnLCBwcm9wcywga2V5LCBuYW1lc3BhY2U7XG5cbiAgICAgICAgICAgICAgICBpZiAoIWNoaWxkcmVuICYmIGlzQ2hpbGRyZW4ocHJvcGVydGllcykpIHtcbiAgICAgICAgICAgICAgICAgICAgY2hpbGRyZW4gPSBwcm9wZXJ0aWVzO1xuICAgICAgICAgICAgICAgICAgICBwcm9wcyA9IHt9O1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHByb3BzID0gcHJvcHMgfHwgcHJvcGVydGllcyB8fCB7fTtcbiAgICAgICAgICAgICAgICB0YWcgPSBwYXJzZVRhZyh0YWdOYW1lLCBwcm9wcyk7XG5cbiAgICAgICAgICAgICAgICAvLyBzdXBwb3J0IGtleXNcbiAgICAgICAgICAgICAgICBpZiAocHJvcHMuaGFzT3duUHJvcGVydHkoXCJrZXlcIikpIHtcbiAgICAgICAgICAgICAgICAgICAga2V5ID0gcHJvcHMua2V5O1xuICAgICAgICAgICAgICAgICAgICBwcm9wcy5rZXkgPSB1bmRlZmluZWQ7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgLy8gc3VwcG9ydCBuYW1lc3BhY2VcbiAgICAgICAgICAgICAgICBpZiAocHJvcHMuaGFzT3duUHJvcGVydHkoXCJuYW1lc3BhY2VcIikpIHtcbiAgICAgICAgICAgICAgICAgICAgbmFtZXNwYWNlID0gcHJvcHMubmFtZXNwYWNlO1xuICAgICAgICAgICAgICAgICAgICBwcm9wcy5uYW1lc3BhY2UgPSB1bmRlZmluZWQ7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgLy8gZml4IGN1cnNvciBidWdcbiAgICAgICAgICAgICAgICBpZiAodGFnID09PSBcIklOUFVUXCIgJiYgIW5hbWVzcGFjZSAmJiBwcm9wcy5oYXNPd25Qcm9wZXJ0eShcInZhbHVlXCIpICYmIHByb3BzLnZhbHVlICE9PSB1bmRlZmluZWQgJiYgIWlzSG9vayhwcm9wcy52YWx1ZSkpIHtcbiAgICAgICAgICAgICAgICAgICAgcHJvcHMudmFsdWUgPSBzb2Z0U2V0SG9vayhwcm9wcy52YWx1ZSk7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgdHJhbnNmb3JtUHJvcGVydGllcyhwcm9wcyk7XG5cbiAgICAgICAgICAgICAgICBpZiAoY2hpbGRyZW4gIT09IHVuZGVmaW5lZCAmJiBjaGlsZHJlbiAhPT0gbnVsbCkge1xuICAgICAgICAgICAgICAgICAgICBhZGRDaGlsZChjaGlsZHJlbiwgY2hpbGROb2RlcywgdGFnLCBwcm9wcyk7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgcmV0dXJuIG5ldyBWTm9kZSh0YWcsIHByb3BzLCBjaGlsZE5vZGVzLCBrZXksIG5hbWVzcGFjZSk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIGFkZENoaWxkKGMsIGNoaWxkTm9kZXMsIHRhZywgcHJvcHMpIHtcbiAgICAgICAgICAgICAgICBpZiAodHlwZW9mIGMgPT09IFwic3RyaW5nXCIpIHtcbiAgICAgICAgICAgICAgICAgICAgY2hpbGROb2Rlcy5wdXNoKG5ldyBWVGV4dChjKSk7XG4gICAgICAgICAgICAgICAgfSBlbHNlIGlmICh0eXBlb2YgYyA9PT0gXCJudW1iZXJcIikge1xuICAgICAgICAgICAgICAgICAgICBjaGlsZE5vZGVzLnB1c2gobmV3IFZUZXh0KFN0cmluZyhjKSkpO1xuICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoaXNDaGlsZChjKSkge1xuICAgICAgICAgICAgICAgICAgICBjaGlsZE5vZGVzLnB1c2goYyk7XG4gICAgICAgICAgICAgICAgfSBlbHNlIGlmIChpc0FycmF5KGMpKSB7XG4gICAgICAgICAgICAgICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgYy5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgICAgICAgICAgICAgYWRkQ2hpbGQoY1tpXSwgY2hpbGROb2RlcywgdGFnLCBwcm9wcyk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKGMgPT09IG51bGwgfHwgYyA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICB0aHJvdyBVbmV4cGVjdGVkVmlydHVhbEVsZW1lbnQoe1xuICAgICAgICAgICAgICAgICAgICAgICAgZm9yZWlnbk9iamVjdDogYyxcbiAgICAgICAgICAgICAgICAgICAgICAgIHBhcmVudFZub2RlOiB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdGFnTmFtZTogdGFnLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHByb3BlcnRpZXM6IHByb3BzXG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZnVuY3Rpb24gdHJhbnNmb3JtUHJvcGVydGllcyhwcm9wcykge1xuICAgICAgICAgICAgICAgIGZvciAodmFyIHByb3BOYW1lIGluIHByb3BzKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmIChwcm9wcy5oYXNPd25Qcm9wZXJ0eShwcm9wTmFtZSkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHZhciB2YWx1ZSA9IHByb3BzW3Byb3BOYW1lXTtcblxuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGlzSG9vayh2YWx1ZSkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb250aW51ZTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHByb3BOYW1lLnN1YnN0cigwLCAzKSA9PT0gXCJldi1cIikge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIGFkZCBldi1mb28gc3VwcG9ydFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHByb3BzW3Byb3BOYW1lXSA9IGV2SG9vayh2YWx1ZSk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIGlzQ2hpbGQoeCkge1xuICAgICAgICAgICAgICAgIHJldHVybiBpc1ZOb2RlKHgpIHx8IGlzVlRleHQoeCkgfHwgaXNXaWRnZXQoeCkgfHwgaXNWVGh1bmsoeCk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIGlzQ2hpbGRyZW4oeCkge1xuICAgICAgICAgICAgICAgIHJldHVybiB0eXBlb2YgeCA9PT0gXCJzdHJpbmdcIiB8fCBpc0FycmF5KHgpIHx8IGlzQ2hpbGQoeCk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIFVuZXhwZWN0ZWRWaXJ0dWFsRWxlbWVudChkYXRhKSB7XG4gICAgICAgICAgICAgICAgdmFyIGVyciA9IG5ldyBFcnJvcigpO1xuXG4gICAgICAgICAgICAgICAgZXJyLnR5cGUgPSBcInZpcnR1YWwtaHlwZXJzY3JpcHQudW5leHBlY3RlZC52aXJ0dWFsLWVsZW1lbnRcIjtcbiAgICAgICAgICAgICAgICBlcnIubWVzc2FnZSA9IFwiVW5leHBlY3RlZCB2aXJ0dWFsIGNoaWxkIHBhc3NlZCB0byBoKCkuXFxuXCIgKyBcIkV4cGVjdGVkIGEgVk5vZGUgLyBWdGh1bmsgLyBWV2lkZ2V0IC8gc3RyaW5nIGJ1dDpcXG5cIiArIFwiZ290OlxcblwiICsgZXJyb3JTdHJpbmcoZGF0YS5mb3JlaWduT2JqZWN0KSArIFwiLlxcblwiICsgXCJUaGUgcGFyZW50IHZub2RlIGlzOlxcblwiICsgZXJyb3JTdHJpbmcoZGF0YS5wYXJlbnRWbm9kZSk7XG4gICAgICAgICAgICAgICAgXCJcXG5cIiArIFwiU3VnZ2VzdGVkIGZpeDogY2hhbmdlIHlvdXIgYGgoLi4uLCBbIC4uLiBdKWAgY2FsbHNpdGUuXCI7XG4gICAgICAgICAgICAgICAgZXJyLmZvcmVpZ25PYmplY3QgPSBkYXRhLmZvcmVpZ25PYmplY3Q7XG4gICAgICAgICAgICAgICAgZXJyLnBhcmVudFZub2RlID0gZGF0YS5wYXJlbnRWbm9kZTtcblxuICAgICAgICAgICAgICAgIHJldHVybiBlcnI7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIGVycm9yU3RyaW5nKG9iaikge1xuICAgICAgICAgICAgICAgIHRyeSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBKU09OLnN0cmluZ2lmeShvYmosIG51bGwsIFwiICAgIFwiKTtcbiAgICAgICAgICAgICAgICB9IGNhdGNoIChlKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBTdHJpbmcob2JqKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH0sIHsgXCIuLi92bm9kZS9pcy10aHVua1wiOiAyNSwgXCIuLi92bm9kZS9pcy12aG9va1wiOiAyNiwgXCIuLi92bm9kZS9pcy12bm9kZVwiOiAyNywgXCIuLi92bm9kZS9pcy12dGV4dFwiOiAyOCwgXCIuLi92bm9kZS9pcy13aWRnZXRcIjogMjksIFwiLi4vdm5vZGUvdm5vZGUuanNcIjogMzEsIFwiLi4vdm5vZGUvdnRleHQuanNcIjogMzMsIFwiLi9ob29rcy9ldi1ob29rLmpzXCI6IDIwLCBcIi4vaG9va3Mvc29mdC1zZXQtaG9vay5qc1wiOiAyMSwgXCIuL3BhcnNlLXRhZy5qc1wiOiAyMywgXCJ4LWlzLWFycmF5XCI6IDEyIH1dLCAyMzogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHtcbiAgICAgICAgICAgIFwidXNlIHN0cmljdFwiO1xuXG4gICAgICAgICAgICB2YXIgc3BsaXQgPSByZXF1aXJlKFwiYnJvd3Nlci1zcGxpdFwiKTtcblxuICAgICAgICAgICAgdmFyIGNsYXNzSWRTcGxpdCA9IC8oW1xcLiNdP1thLXpBLVowLTlcXHUwMDdGLVxcdUZGRkZfOi1dKykvO1xuICAgICAgICAgICAgdmFyIG5vdENsYXNzSWQgPSAvXlxcLnwjLztcblxuICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBwYXJzZVRhZztcblxuICAgICAgICAgICAgZnVuY3Rpb24gcGFyc2VUYWcodGFnLCBwcm9wcykge1xuICAgICAgICAgICAgICAgIGlmICghdGFnKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBcIkRJVlwiO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHZhciBub0lkID0gIXByb3BzLmhhc093blByb3BlcnR5KFwiaWRcIik7XG5cbiAgICAgICAgICAgICAgICB2YXIgdGFnUGFydHMgPSBzcGxpdCh0YWcsIGNsYXNzSWRTcGxpdCk7XG4gICAgICAgICAgICAgICAgdmFyIHRhZ05hbWUgPSBudWxsO1xuXG4gICAgICAgICAgICAgICAgaWYgKG5vdENsYXNzSWQudGVzdCh0YWdQYXJ0c1sxXSkpIHtcbiAgICAgICAgICAgICAgICAgICAgdGFnTmFtZSA9IFwiRElWXCI7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgdmFyIGNsYXNzZXMsIHBhcnQsIHR5cGUsIGk7XG5cbiAgICAgICAgICAgICAgICBmb3IgKGkgPSAwOyBpIDwgdGFnUGFydHMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgICAgICAgICAgcGFydCA9IHRhZ1BhcnRzW2ldO1xuXG4gICAgICAgICAgICAgICAgICAgIGlmICghcGFydCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgY29udGludWU7XG4gICAgICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgICAgICB0eXBlID0gcGFydC5jaGFyQXQoMCk7XG5cbiAgICAgICAgICAgICAgICAgICAgaWYgKCF0YWdOYW1lKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICB0YWdOYW1lID0gcGFydDtcbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIGlmICh0eXBlID09PSBcIi5cIikge1xuICAgICAgICAgICAgICAgICAgICAgICAgY2xhc3NlcyA9IGNsYXNzZXMgfHwgW107XG4gICAgICAgICAgICAgICAgICAgICAgICBjbGFzc2VzLnB1c2gocGFydC5zdWJzdHJpbmcoMSwgcGFydC5sZW5ndGgpKTtcbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIGlmICh0eXBlID09PSBcIiNcIiAmJiBub0lkKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBwcm9wcy5pZCA9IHBhcnQuc3Vic3RyaW5nKDEsIHBhcnQubGVuZ3RoKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIGlmIChjbGFzc2VzKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmIChwcm9wcy5jbGFzc05hbWUpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGNsYXNzZXMucHVzaChwcm9wcy5jbGFzc05hbWUpO1xuICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgcHJvcHMuY2xhc3NOYW1lID0gY2xhc3Nlcy5qb2luKFwiIFwiKTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICByZXR1cm4gcHJvcHMubmFtZXNwYWNlID8gdGFnTmFtZSA6IHRhZ05hbWUudG9VcHBlckNhc2UoKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSwgeyBcImJyb3dzZXItc3BsaXRcIjogNSB9XSwgMjQ6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICB2YXIgaXNWTm9kZSA9IHJlcXVpcmUoXCIuL2lzLXZub2RlXCIpO1xuICAgICAgICAgICAgdmFyIGlzVlRleHQgPSByZXF1aXJlKFwiLi9pcy12dGV4dFwiKTtcbiAgICAgICAgICAgIHZhciBpc1dpZGdldCA9IHJlcXVpcmUoXCIuL2lzLXdpZGdldFwiKTtcbiAgICAgICAgICAgIHZhciBpc1RodW5rID0gcmVxdWlyZShcIi4vaXMtdGh1bmtcIik7XG5cbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gaGFuZGxlVGh1bms7XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIGhhbmRsZVRodW5rKGEsIGIpIHtcbiAgICAgICAgICAgICAgICB2YXIgcmVuZGVyZWRBID0gYTtcbiAgICAgICAgICAgICAgICB2YXIgcmVuZGVyZWRCID0gYjtcblxuICAgICAgICAgICAgICAgIGlmIChpc1RodW5rKGIpKSB7XG4gICAgICAgICAgICAgICAgICAgIHJlbmRlcmVkQiA9IHJlbmRlclRodW5rKGIsIGEpO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIGlmIChpc1RodW5rKGEpKSB7XG4gICAgICAgICAgICAgICAgICAgIHJlbmRlcmVkQSA9IHJlbmRlclRodW5rKGEsIG51bGwpO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHJldHVybiB7XG4gICAgICAgICAgICAgICAgICAgIGE6IHJlbmRlcmVkQSxcbiAgICAgICAgICAgICAgICAgICAgYjogcmVuZGVyZWRCXG4gICAgICAgICAgICAgICAgfTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZnVuY3Rpb24gcmVuZGVyVGh1bmsodGh1bmssIHByZXZpb3VzKSB7XG4gICAgICAgICAgICAgICAgdmFyIHJlbmRlcmVkVGh1bmsgPSB0aHVuay52bm9kZTtcblxuICAgICAgICAgICAgICAgIGlmICghcmVuZGVyZWRUaHVuaykge1xuICAgICAgICAgICAgICAgICAgICByZW5kZXJlZFRodW5rID0gdGh1bmsudm5vZGUgPSB0aHVuay5yZW5kZXIocHJldmlvdXMpO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIGlmICghKGlzVk5vZGUocmVuZGVyZWRUaHVuaykgfHwgaXNWVGV4dChyZW5kZXJlZFRodW5rKSB8fCBpc1dpZGdldChyZW5kZXJlZFRodW5rKSkpIHtcbiAgICAgICAgICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKFwidGh1bmsgZGlkIG5vdCByZXR1cm4gYSB2YWxpZCBub2RlXCIpO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHJldHVybiByZW5kZXJlZFRodW5rO1xuICAgICAgICAgICAgfVxuICAgICAgICB9LCB7IFwiLi9pcy10aHVua1wiOiAyNSwgXCIuL2lzLXZub2RlXCI6IDI3LCBcIi4vaXMtdnRleHRcIjogMjgsIFwiLi9pcy13aWRnZXRcIjogMjkgfV0sIDI1OiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge1xuICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBpc1RodW5rO1xuXG4gICAgICAgICAgICBmdW5jdGlvbiBpc1RodW5rKHQpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gdCAmJiB0LnR5cGUgPT09IFwiVGh1bmtcIjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSwge31dLCAyNjogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHtcbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gaXNIb29rO1xuXG4gICAgICAgICAgICBmdW5jdGlvbiBpc0hvb2soaG9vaykge1xuICAgICAgICAgICAgICAgIHJldHVybiBob29rICYmICh0eXBlb2YgaG9vay5ob29rID09PSBcImZ1bmN0aW9uXCIgJiYgIWhvb2suaGFzT3duUHJvcGVydHkoXCJob29rXCIpIHx8IHR5cGVvZiBob29rLnVuaG9vayA9PT0gXCJmdW5jdGlvblwiICYmICFob29rLmhhc093blByb3BlcnR5KFwidW5ob29rXCIpKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSwge31dLCAyNzogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHtcbiAgICAgICAgICAgIHZhciB2ZXJzaW9uID0gcmVxdWlyZShcIi4vdmVyc2lvblwiKTtcblxuICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBpc1ZpcnR1YWxOb2RlO1xuXG4gICAgICAgICAgICBmdW5jdGlvbiBpc1ZpcnR1YWxOb2RlKHgpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4geCAmJiB4LnR5cGUgPT09IFwiVmlydHVhbE5vZGVcIiAmJiB4LnZlcnNpb24gPT09IHZlcnNpb247XG4gICAgICAgICAgICB9XG4gICAgICAgIH0sIHsgXCIuL3ZlcnNpb25cIjogMzAgfV0sIDI4OiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge1xuICAgICAgICAgICAgdmFyIHZlcnNpb24gPSByZXF1aXJlKFwiLi92ZXJzaW9uXCIpO1xuXG4gICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IGlzVmlydHVhbFRleHQ7XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIGlzVmlydHVhbFRleHQoeCkge1xuICAgICAgICAgICAgICAgIHJldHVybiB4ICYmIHgudHlwZSA9PT0gXCJWaXJ0dWFsVGV4dFwiICYmIHgudmVyc2lvbiA9PT0gdmVyc2lvbjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSwgeyBcIi4vdmVyc2lvblwiOiAzMCB9XSwgMjk6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IGlzV2lkZ2V0O1xuXG4gICAgICAgICAgICBmdW5jdGlvbiBpc1dpZGdldCh3KSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHcgJiYgdy50eXBlID09PSBcIldpZGdldFwiO1xuICAgICAgICAgICAgfVxuICAgICAgICB9LCB7fV0sIDMwOiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge1xuICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBcIjJcIjtcbiAgICAgICAgfSwge31dLCAzMTogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHtcbiAgICAgICAgICAgIHZhciB2ZXJzaW9uID0gcmVxdWlyZShcIi4vdmVyc2lvblwiKTtcbiAgICAgICAgICAgIHZhciBpc1ZOb2RlID0gcmVxdWlyZShcIi4vaXMtdm5vZGVcIik7XG4gICAgICAgICAgICB2YXIgaXNXaWRnZXQgPSByZXF1aXJlKFwiLi9pcy13aWRnZXRcIik7XG4gICAgICAgICAgICB2YXIgaXNUaHVuayA9IHJlcXVpcmUoXCIuL2lzLXRodW5rXCIpO1xuICAgICAgICAgICAgdmFyIGlzVkhvb2sgPSByZXF1aXJlKFwiLi9pcy12aG9va1wiKTtcblxuICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBWaXJ0dWFsTm9kZTtcblxuICAgICAgICAgICAgdmFyIG5vUHJvcGVydGllcyA9IHt9O1xuICAgICAgICAgICAgdmFyIG5vQ2hpbGRyZW4gPSBbXTtcblxuICAgICAgICAgICAgZnVuY3Rpb24gVmlydHVhbE5vZGUodGFnTmFtZSwgcHJvcGVydGllcywgY2hpbGRyZW4sIGtleSwgbmFtZXNwYWNlKSB7XG4gICAgICAgICAgICAgICAgdGhpcy50YWdOYW1lID0gdGFnTmFtZTtcbiAgICAgICAgICAgICAgICB0aGlzLnByb3BlcnRpZXMgPSBwcm9wZXJ0aWVzIHx8IG5vUHJvcGVydGllcztcbiAgICAgICAgICAgICAgICB0aGlzLmNoaWxkcmVuID0gY2hpbGRyZW4gfHwgbm9DaGlsZHJlbjtcbiAgICAgICAgICAgICAgICB0aGlzLmtleSA9IGtleSAhPSBudWxsID8gU3RyaW5nKGtleSkgOiB1bmRlZmluZWQ7XG4gICAgICAgICAgICAgICAgdGhpcy5uYW1lc3BhY2UgPSB0eXBlb2YgbmFtZXNwYWNlID09PSBcInN0cmluZ1wiID8gbmFtZXNwYWNlIDogbnVsbDtcblxuICAgICAgICAgICAgICAgIHZhciBjb3VudCA9IGNoaWxkcmVuICYmIGNoaWxkcmVuLmxlbmd0aCB8fCAwO1xuICAgICAgICAgICAgICAgIHZhciBkZXNjZW5kYW50cyA9IDA7XG4gICAgICAgICAgICAgICAgdmFyIGhhc1dpZGdldHMgPSBmYWxzZTtcbiAgICAgICAgICAgICAgICB2YXIgaGFzVGh1bmtzID0gZmFsc2U7XG4gICAgICAgICAgICAgICAgdmFyIGRlc2NlbmRhbnRIb29rcyA9IGZhbHNlO1xuICAgICAgICAgICAgICAgIHZhciBob29rcztcblxuICAgICAgICAgICAgICAgIGZvciAodmFyIHByb3BOYW1lIGluIHByb3BlcnRpZXMpIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKHByb3BlcnRpZXMuaGFzT3duUHJvcGVydHkocHJvcE5hbWUpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICB2YXIgcHJvcGVydHkgPSBwcm9wZXJ0aWVzW3Byb3BOYW1lXTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChpc1ZIb29rKHByb3BlcnR5KSAmJiBwcm9wZXJ0eS51bmhvb2spIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoIWhvb2tzKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGhvb2tzID0ge307XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaG9va3NbcHJvcE5hbWVdID0gcHJvcGVydHk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IGNvdW50OyBpKyspIHtcbiAgICAgICAgICAgICAgICAgICAgdmFyIGNoaWxkID0gY2hpbGRyZW5baV07XG4gICAgICAgICAgICAgICAgICAgIGlmIChpc1ZOb2RlKGNoaWxkKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgZGVzY2VuZGFudHMgKz0gY2hpbGQuY291bnQgfHwgMDtcblxuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKCFoYXNXaWRnZXRzICYmIGNoaWxkLmhhc1dpZGdldHMpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBoYXNXaWRnZXRzID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKCFoYXNUaHVua3MgJiYgY2hpbGQuaGFzVGh1bmtzKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaGFzVGh1bmtzID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKCFkZXNjZW5kYW50SG9va3MgJiYgKGNoaWxkLmhvb2tzIHx8IGNoaWxkLmRlc2NlbmRhbnRIb29rcykpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBkZXNjZW5kYW50SG9va3MgPSB0cnVlO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKCFoYXNXaWRnZXRzICYmIGlzV2lkZ2V0KGNoaWxkKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHR5cGVvZiBjaGlsZC5kZXN0cm95ID09PSBcImZ1bmN0aW9uXCIpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBoYXNXaWRnZXRzID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIGlmICghaGFzVGh1bmtzICYmIGlzVGh1bmsoY2hpbGQpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBoYXNUaHVua3MgPSB0cnVlO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgdGhpcy5jb3VudCA9IGNvdW50ICsgZGVzY2VuZGFudHM7XG4gICAgICAgICAgICAgICAgdGhpcy5oYXNXaWRnZXRzID0gaGFzV2lkZ2V0cztcbiAgICAgICAgICAgICAgICB0aGlzLmhhc1RodW5rcyA9IGhhc1RodW5rcztcbiAgICAgICAgICAgICAgICB0aGlzLmhvb2tzID0gaG9va3M7XG4gICAgICAgICAgICAgICAgdGhpcy5kZXNjZW5kYW50SG9va3MgPSBkZXNjZW5kYW50SG9va3M7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIFZpcnR1YWxOb2RlLnByb3RvdHlwZS52ZXJzaW9uID0gdmVyc2lvbjtcbiAgICAgICAgICAgIFZpcnR1YWxOb2RlLnByb3RvdHlwZS50eXBlID0gXCJWaXJ0dWFsTm9kZVwiO1xuICAgICAgICB9LCB7IFwiLi9pcy10aHVua1wiOiAyNSwgXCIuL2lzLXZob29rXCI6IDI2LCBcIi4vaXMtdm5vZGVcIjogMjcsIFwiLi9pcy13aWRnZXRcIjogMjksIFwiLi92ZXJzaW9uXCI6IDMwIH1dLCAzMjogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHtcbiAgICAgICAgICAgIHZhciB2ZXJzaW9uID0gcmVxdWlyZShcIi4vdmVyc2lvblwiKTtcblxuICAgICAgICAgICAgVmlydHVhbFBhdGNoLk5PTkUgPSAwO1xuICAgICAgICAgICAgVmlydHVhbFBhdGNoLlZURVhUID0gMTtcbiAgICAgICAgICAgIFZpcnR1YWxQYXRjaC5WTk9ERSA9IDI7XG4gICAgICAgICAgICBWaXJ0dWFsUGF0Y2guV0lER0VUID0gMztcbiAgICAgICAgICAgIFZpcnR1YWxQYXRjaC5QUk9QUyA9IDQ7XG4gICAgICAgICAgICBWaXJ0dWFsUGF0Y2guT1JERVIgPSA1O1xuICAgICAgICAgICAgVmlydHVhbFBhdGNoLklOU0VSVCA9IDY7XG4gICAgICAgICAgICBWaXJ0dWFsUGF0Y2guUkVNT1ZFID0gNztcbiAgICAgICAgICAgIFZpcnR1YWxQYXRjaC5USFVOSyA9IDg7XG5cbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gVmlydHVhbFBhdGNoO1xuXG4gICAgICAgICAgICBmdW5jdGlvbiBWaXJ0dWFsUGF0Y2godHlwZSwgdk5vZGUsIHBhdGNoKSB7XG4gICAgICAgICAgICAgICAgdGhpcy50eXBlID0gTnVtYmVyKHR5cGUpO1xuICAgICAgICAgICAgICAgIHRoaXMudk5vZGUgPSB2Tm9kZTtcbiAgICAgICAgICAgICAgICB0aGlzLnBhdGNoID0gcGF0Y2g7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIFZpcnR1YWxQYXRjaC5wcm90b3R5cGUudmVyc2lvbiA9IHZlcnNpb247XG4gICAgICAgICAgICBWaXJ0dWFsUGF0Y2gucHJvdG90eXBlLnR5cGUgPSBcIlZpcnR1YWxQYXRjaFwiO1xuICAgICAgICB9LCB7IFwiLi92ZXJzaW9uXCI6IDMwIH1dLCAzMzogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHtcbiAgICAgICAgICAgIHZhciB2ZXJzaW9uID0gcmVxdWlyZShcIi4vdmVyc2lvblwiKTtcblxuICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBWaXJ0dWFsVGV4dDtcblxuICAgICAgICAgICAgZnVuY3Rpb24gVmlydHVhbFRleHQodGV4dCkge1xuICAgICAgICAgICAgICAgIHRoaXMudGV4dCA9IFN0cmluZyh0ZXh0KTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgVmlydHVhbFRleHQucHJvdG90eXBlLnZlcnNpb24gPSB2ZXJzaW9uO1xuICAgICAgICAgICAgVmlydHVhbFRleHQucHJvdG90eXBlLnR5cGUgPSBcIlZpcnR1YWxUZXh0XCI7XG4gICAgICAgIH0sIHsgXCIuL3ZlcnNpb25cIjogMzAgfV0sIDM0OiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge1xuICAgICAgICAgICAgdmFyIGlzT2JqZWN0ID0gcmVxdWlyZShcImlzLW9iamVjdFwiKTtcbiAgICAgICAgICAgIHZhciBpc0hvb2sgPSByZXF1aXJlKFwiLi4vdm5vZGUvaXMtdmhvb2tcIik7XG5cbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gZGlmZlByb3BzO1xuXG4gICAgICAgICAgICBmdW5jdGlvbiBkaWZmUHJvcHMoYSwgYikge1xuICAgICAgICAgICAgICAgIHZhciBkaWZmO1xuXG4gICAgICAgICAgICAgICAgZm9yICh2YXIgYUtleSBpbiBhKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmICghKGFLZXkgaW4gYikpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGRpZmYgPSBkaWZmIHx8IHt9O1xuICAgICAgICAgICAgICAgICAgICAgICAgZGlmZlthS2V5XSA9IHVuZGVmaW5lZDtcbiAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgIHZhciBhVmFsdWUgPSBhW2FLZXldO1xuICAgICAgICAgICAgICAgICAgICB2YXIgYlZhbHVlID0gYlthS2V5XTtcblxuICAgICAgICAgICAgICAgICAgICBpZiAoYVZhbHVlID09PSBiVmFsdWUpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnRpbnVlO1xuICAgICAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKGlzT2JqZWN0KGFWYWx1ZSkgJiYgaXNPYmplY3QoYlZhbHVlKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGdldFByb3RvdHlwZShiVmFsdWUpICE9PSBnZXRQcm90b3R5cGUoYVZhbHVlKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRpZmYgPSBkaWZmIHx8IHt9O1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRpZmZbYUtleV0gPSBiVmFsdWU7XG4gICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKGlzSG9vayhiVmFsdWUpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgZGlmZiA9IGRpZmYgfHwge307XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgZGlmZlthS2V5XSA9IGJWYWx1ZTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdmFyIG9iamVjdERpZmYgPSBkaWZmUHJvcHMoYVZhbHVlLCBiVmFsdWUpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChvYmplY3REaWZmKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRpZmYgPSBkaWZmIHx8IHt9O1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBkaWZmW2FLZXldID0gb2JqZWN0RGlmZjtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBkaWZmID0gZGlmZiB8fCB7fTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGRpZmZbYUtleV0gPSBiVmFsdWU7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICBmb3IgKHZhciBiS2V5IGluIGIpIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKCEoYktleSBpbiBhKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgZGlmZiA9IGRpZmYgfHwge307XG4gICAgICAgICAgICAgICAgICAgICAgICBkaWZmW2JLZXldID0gYltiS2V5XTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHJldHVybiBkaWZmO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBmdW5jdGlvbiBnZXRQcm90b3R5cGUodmFsdWUpIHtcbiAgICAgICAgICAgICAgICBpZiAoT2JqZWN0LmdldFByb3RvdHlwZU9mKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBPYmplY3QuZ2V0UHJvdG90eXBlT2YodmFsdWUpO1xuICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAodmFsdWUuX19wcm90b19fKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiB2YWx1ZS5fX3Byb3RvX187XG4gICAgICAgICAgICAgICAgfSBlbHNlIGlmICh2YWx1ZS5jb25zdHJ1Y3Rvcikge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gdmFsdWUuY29uc3RydWN0b3IucHJvdG90eXBlO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgfSwgeyBcIi4uL3Zub2RlL2lzLXZob29rXCI6IDI2LCBcImlzLW9iamVjdFwiOiAxMSB9XSwgMzU6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICB2YXIgaXNBcnJheSA9IHJlcXVpcmUoXCJ4LWlzLWFycmF5XCIpO1xuXG4gICAgICAgICAgICB2YXIgVlBhdGNoID0gcmVxdWlyZShcIi4uL3Zub2RlL3ZwYXRjaFwiKTtcbiAgICAgICAgICAgIHZhciBpc1ZOb2RlID0gcmVxdWlyZShcIi4uL3Zub2RlL2lzLXZub2RlXCIpO1xuICAgICAgICAgICAgdmFyIGlzVlRleHQgPSByZXF1aXJlKFwiLi4vdm5vZGUvaXMtdnRleHRcIik7XG4gICAgICAgICAgICB2YXIgaXNXaWRnZXQgPSByZXF1aXJlKFwiLi4vdm5vZGUvaXMtd2lkZ2V0XCIpO1xuICAgICAgICAgICAgdmFyIGlzVGh1bmsgPSByZXF1aXJlKFwiLi4vdm5vZGUvaXMtdGh1bmtcIik7XG4gICAgICAgICAgICB2YXIgaGFuZGxlVGh1bmsgPSByZXF1aXJlKFwiLi4vdm5vZGUvaGFuZGxlLXRodW5rXCIpO1xuXG4gICAgICAgICAgICB2YXIgZGlmZlByb3BzID0gcmVxdWlyZShcIi4vZGlmZi1wcm9wc1wiKTtcblxuICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBkaWZmO1xuXG4gICAgICAgICAgICBmdW5jdGlvbiBkaWZmKGEsIGIpIHtcbiAgICAgICAgICAgICAgICB2YXIgcGF0Y2ggPSB7IGE6IGEgfTtcbiAgICAgICAgICAgICAgICB3YWxrKGEsIGIsIHBhdGNoLCAwKTtcbiAgICAgICAgICAgICAgICByZXR1cm4gcGF0Y2g7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIHdhbGsoYSwgYiwgcGF0Y2gsIGluZGV4KSB7XG4gICAgICAgICAgICAgICAgaWYgKGEgPT09IGIpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHZhciBhcHBseSA9IHBhdGNoW2luZGV4XTtcbiAgICAgICAgICAgICAgICB2YXIgYXBwbHlDbGVhciA9IGZhbHNlO1xuXG4gICAgICAgICAgICAgICAgaWYgKGlzVGh1bmsoYSkgfHwgaXNUaHVuayhiKSkge1xuICAgICAgICAgICAgICAgICAgICB0aHVua3MoYSwgYiwgcGF0Y2gsIGluZGV4KTtcbiAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKGIgPT0gbnVsbCkge1xuXG4gICAgICAgICAgICAgICAgICAgIC8vIElmIGEgaXMgYSB3aWRnZXQgd2Ugd2lsbCBhZGQgYSByZW1vdmUgcGF0Y2ggZm9yIGl0XG4gICAgICAgICAgICAgICAgICAgIC8vIE90aGVyd2lzZSBhbnkgY2hpbGQgd2lkZ2V0cy9ob29rcyBtdXN0IGJlIGRlc3Ryb3llZC5cbiAgICAgICAgICAgICAgICAgICAgLy8gVGhpcyBwcmV2ZW50cyBhZGRpbmcgdHdvIHJlbW92ZSBwYXRjaGVzIGZvciBhIHdpZGdldC5cbiAgICAgICAgICAgICAgICAgICAgaWYgKCFpc1dpZGdldChhKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgY2xlYXJTdGF0ZShhLCBwYXRjaCwgaW5kZXgpO1xuICAgICAgICAgICAgICAgICAgICAgICAgYXBwbHkgPSBwYXRjaFtpbmRleF07XG4gICAgICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgICAgICBhcHBseSA9IGFwcGVuZFBhdGNoKGFwcGx5LCBuZXcgVlBhdGNoKFZQYXRjaC5SRU1PVkUsIGEsIGIpKTtcbiAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKGlzVk5vZGUoYikpIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKGlzVk5vZGUoYSkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChhLnRhZ05hbWUgPT09IGIudGFnTmFtZSAmJiBhLm5hbWVzcGFjZSA9PT0gYi5uYW1lc3BhY2UgJiYgYS5rZXkgPT09IGIua2V5KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdmFyIHByb3BzUGF0Y2ggPSBkaWZmUHJvcHMoYS5wcm9wZXJ0aWVzLCBiLnByb3BlcnRpZXMpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChwcm9wc1BhdGNoKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGFwcGx5ID0gYXBwZW5kUGF0Y2goYXBwbHksIG5ldyBWUGF0Y2goVlBhdGNoLlBST1BTLCBhLCBwcm9wc1BhdGNoKSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGFwcGx5ID0gZGlmZkNoaWxkcmVuKGEsIGIsIHBhdGNoLCBhcHBseSwgaW5kZXgpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBhcHBseSA9IGFwcGVuZFBhdGNoKGFwcGx5LCBuZXcgVlBhdGNoKFZQYXRjaC5WTk9ERSwgYSwgYikpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGFwcGx5Q2xlYXIgPSB0cnVlO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgYXBwbHkgPSBhcHBlbmRQYXRjaChhcHBseSwgbmV3IFZQYXRjaChWUGF0Y2guVk5PREUsIGEsIGIpKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGFwcGx5Q2xlYXIgPSB0cnVlO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfSBlbHNlIGlmIChpc1ZUZXh0KGIpKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmICghaXNWVGV4dChhKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgYXBwbHkgPSBhcHBlbmRQYXRjaChhcHBseSwgbmV3IFZQYXRjaChWUGF0Y2guVlRFWFQsIGEsIGIpKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGFwcGx5Q2xlYXIgPSB0cnVlO1xuICAgICAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKGEudGV4dCAhPT0gYi50ZXh0KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBhcHBseSA9IGFwcGVuZFBhdGNoKGFwcGx5LCBuZXcgVlBhdGNoKFZQYXRjaC5WVEVYVCwgYSwgYikpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfSBlbHNlIGlmIChpc1dpZGdldChiKSkge1xuICAgICAgICAgICAgICAgICAgICBpZiAoIWlzV2lkZ2V0KGEpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBhcHBseUNsZWFyID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgIGFwcGx5ID0gYXBwZW5kUGF0Y2goYXBwbHksIG5ldyBWUGF0Y2goVlBhdGNoLldJREdFVCwgYSwgYikpO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIGlmIChhcHBseSkge1xuICAgICAgICAgICAgICAgICAgICBwYXRjaFtpbmRleF0gPSBhcHBseTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICBpZiAoYXBwbHlDbGVhcikge1xuICAgICAgICAgICAgICAgICAgICBjbGVhclN0YXRlKGEsIHBhdGNoLCBpbmRleCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBmdW5jdGlvbiBkaWZmQ2hpbGRyZW4oYSwgYiwgcGF0Y2gsIGFwcGx5LCBpbmRleCkge1xuICAgICAgICAgICAgICAgIHZhciBhQ2hpbGRyZW4gPSBhLmNoaWxkcmVuO1xuICAgICAgICAgICAgICAgIHZhciBvcmRlcmVkU2V0ID0gcmVvcmRlcihhQ2hpbGRyZW4sIGIuY2hpbGRyZW4pO1xuICAgICAgICAgICAgICAgIHZhciBiQ2hpbGRyZW4gPSBvcmRlcmVkU2V0LmNoaWxkcmVuO1xuXG4gICAgICAgICAgICAgICAgdmFyIGFMZW4gPSBhQ2hpbGRyZW4ubGVuZ3RoO1xuICAgICAgICAgICAgICAgIHZhciBiTGVuID0gYkNoaWxkcmVuLmxlbmd0aDtcbiAgICAgICAgICAgICAgICB2YXIgbGVuID0gYUxlbiA+IGJMZW4gPyBhTGVuIDogYkxlbjtcblxuICAgICAgICAgICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgbGVuOyBpKyspIHtcbiAgICAgICAgICAgICAgICAgICAgdmFyIGxlZnROb2RlID0gYUNoaWxkcmVuW2ldO1xuICAgICAgICAgICAgICAgICAgICB2YXIgcmlnaHROb2RlID0gYkNoaWxkcmVuW2ldO1xuICAgICAgICAgICAgICAgICAgICBpbmRleCArPSAxO1xuXG4gICAgICAgICAgICAgICAgICAgIGlmICghbGVmdE5vZGUpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChyaWdodE5vZGUpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBFeGNlc3Mgbm9kZXMgaW4gYiBuZWVkIHRvIGJlIGFkZGVkXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgYXBwbHkgPSBhcHBlbmRQYXRjaChhcHBseSwgbmV3IFZQYXRjaChWUGF0Y2guSU5TRVJULCBudWxsLCByaWdodE5vZGUpKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHdhbGsobGVmdE5vZGUsIHJpZ2h0Tm9kZSwgcGF0Y2gsIGluZGV4KTtcbiAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgIGlmIChpc1ZOb2RlKGxlZnROb2RlKSAmJiBsZWZ0Tm9kZS5jb3VudCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgaW5kZXggKz0gbGVmdE5vZGUuY291bnQ7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICBpZiAob3JkZXJlZFNldC5tb3Zlcykge1xuICAgICAgICAgICAgICAgICAgICAvLyBSZW9yZGVyIG5vZGVzIGxhc3RcbiAgICAgICAgICAgICAgICAgICAgYXBwbHkgPSBhcHBlbmRQYXRjaChhcHBseSwgbmV3IFZQYXRjaChWUGF0Y2guT1JERVIsIGEsIG9yZGVyZWRTZXQubW92ZXMpKTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICByZXR1cm4gYXBwbHk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIGNsZWFyU3RhdGUodk5vZGUsIHBhdGNoLCBpbmRleCkge1xuICAgICAgICAgICAgICAgIC8vIFRPRE86IE1ha2UgdGhpcyBhIHNpbmdsZSB3YWxrLCBub3QgdHdvXG4gICAgICAgICAgICAgICAgdW5ob29rKHZOb2RlLCBwYXRjaCwgaW5kZXgpO1xuICAgICAgICAgICAgICAgIGRlc3Ryb3lXaWRnZXRzKHZOb2RlLCBwYXRjaCwgaW5kZXgpO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAvLyBQYXRjaCByZWNvcmRzIGZvciBhbGwgZGVzdHJveWVkIHdpZGdldHMgbXVzdCBiZSBhZGRlZCBiZWNhdXNlIHdlIG5lZWRcbiAgICAgICAgICAgIC8vIGEgRE9NIG5vZGUgcmVmZXJlbmNlIGZvciB0aGUgZGVzdHJveSBmdW5jdGlvblxuICAgICAgICAgICAgZnVuY3Rpb24gZGVzdHJveVdpZGdldHModk5vZGUsIHBhdGNoLCBpbmRleCkge1xuICAgICAgICAgICAgICAgIGlmIChpc1dpZGdldCh2Tm9kZSkpIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKHR5cGVvZiB2Tm9kZS5kZXN0cm95ID09PSBcImZ1bmN0aW9uXCIpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHBhdGNoW2luZGV4XSA9IGFwcGVuZFBhdGNoKHBhdGNoW2luZGV4XSwgbmV3IFZQYXRjaChWUGF0Y2guUkVNT1ZFLCB2Tm9kZSwgbnVsbCkpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfSBlbHNlIGlmIChpc1ZOb2RlKHZOb2RlKSAmJiAodk5vZGUuaGFzV2lkZ2V0cyB8fCB2Tm9kZS5oYXNUaHVua3MpKSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciBjaGlsZHJlbiA9IHZOb2RlLmNoaWxkcmVuO1xuICAgICAgICAgICAgICAgICAgICB2YXIgbGVuID0gY2hpbGRyZW4ubGVuZ3RoO1xuICAgICAgICAgICAgICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IGxlbjsgaSsrKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICB2YXIgY2hpbGQgPSBjaGlsZHJlbltpXTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGluZGV4ICs9IDE7XG5cbiAgICAgICAgICAgICAgICAgICAgICAgIGRlc3Ryb3lXaWRnZXRzKGNoaWxkLCBwYXRjaCwgaW5kZXgpO1xuXG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoaXNWTm9kZShjaGlsZCkgJiYgY2hpbGQuY291bnQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpbmRleCArPSBjaGlsZC5jb3VudDtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoaXNUaHVuayh2Tm9kZSkpIHtcbiAgICAgICAgICAgICAgICAgICAgdGh1bmtzKHZOb2RlLCBudWxsLCBwYXRjaCwgaW5kZXgpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgLy8gQ3JlYXRlIGEgc3ViLXBhdGNoIGZvciB0aHVua3NcbiAgICAgICAgICAgIGZ1bmN0aW9uIHRodW5rcyhhLCBiLCBwYXRjaCwgaW5kZXgpIHtcbiAgICAgICAgICAgICAgICB2YXIgbm9kZXMgPSBoYW5kbGVUaHVuayhhLCBiKTtcbiAgICAgICAgICAgICAgICB2YXIgdGh1bmtQYXRjaCA9IGRpZmYobm9kZXMuYSwgbm9kZXMuYik7XG4gICAgICAgICAgICAgICAgaWYgKGhhc1BhdGNoZXModGh1bmtQYXRjaCkpIHtcbiAgICAgICAgICAgICAgICAgICAgcGF0Y2hbaW5kZXhdID0gbmV3IFZQYXRjaChWUGF0Y2guVEhVTkssIG51bGwsIHRodW5rUGF0Y2gpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZnVuY3Rpb24gaGFzUGF0Y2hlcyhwYXRjaCkge1xuICAgICAgICAgICAgICAgIGZvciAodmFyIGluZGV4IGluIHBhdGNoKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmIChpbmRleCAhPT0gXCJhXCIpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAvLyBFeGVjdXRlIGhvb2tzIHdoZW4gdHdvIG5vZGVzIGFyZSBpZGVudGljYWxcbiAgICAgICAgICAgIGZ1bmN0aW9uIHVuaG9vayh2Tm9kZSwgcGF0Y2gsIGluZGV4KSB7XG4gICAgICAgICAgICAgICAgaWYgKGlzVk5vZGUodk5vZGUpKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmICh2Tm9kZS5ob29rcykge1xuICAgICAgICAgICAgICAgICAgICAgICAgcGF0Y2hbaW5kZXhdID0gYXBwZW5kUGF0Y2gocGF0Y2hbaW5kZXhdLCBuZXcgVlBhdGNoKFZQYXRjaC5QUk9QUywgdk5vZGUsIHVuZGVmaW5lZEtleXModk5vZGUuaG9va3MpKSk7XG4gICAgICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgICAgICBpZiAodk5vZGUuZGVzY2VuZGFudEhvb2tzIHx8IHZOb2RlLmhhc1RodW5rcykge1xuICAgICAgICAgICAgICAgICAgICAgICAgdmFyIGNoaWxkcmVuID0gdk5vZGUuY2hpbGRyZW47XG4gICAgICAgICAgICAgICAgICAgICAgICB2YXIgbGVuID0gY2hpbGRyZW4ubGVuZ3RoO1xuICAgICAgICAgICAgICAgICAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCBsZW47IGkrKykge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZhciBjaGlsZCA9IGNoaWxkcmVuW2ldO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGluZGV4ICs9IDE7XG5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB1bmhvb2soY2hpbGQsIHBhdGNoLCBpbmRleCk7XG5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoaXNWTm9kZShjaGlsZCkgJiYgY2hpbGQuY291bnQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaW5kZXggKz0gY2hpbGQuY291bnQ7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfSBlbHNlIGlmIChpc1RodW5rKHZOb2RlKSkge1xuICAgICAgICAgICAgICAgICAgICB0aHVua3Modk5vZGUsIG51bGwsIHBhdGNoLCBpbmRleCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBmdW5jdGlvbiB1bmRlZmluZWRLZXlzKG9iaikge1xuICAgICAgICAgICAgICAgIHZhciByZXN1bHQgPSB7fTtcblxuICAgICAgICAgICAgICAgIGZvciAodmFyIGtleSBpbiBvYmopIHtcbiAgICAgICAgICAgICAgICAgICAgcmVzdWx0W2tleV0gPSB1bmRlZmluZWQ7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgcmV0dXJuIHJlc3VsdDtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgLy8gTGlzdCBkaWZmLCBuYWl2ZSBsZWZ0IHRvIHJpZ2h0IHJlb3JkZXJpbmdcbiAgICAgICAgICAgIGZ1bmN0aW9uIHJlb3JkZXIoYUNoaWxkcmVuLCBiQ2hpbGRyZW4pIHtcbiAgICAgICAgICAgICAgICAvLyBPKE0pIHRpbWUsIE8oTSkgbWVtb3J5XG4gICAgICAgICAgICAgICAgdmFyIGJDaGlsZEluZGV4ID0ga2V5SW5kZXgoYkNoaWxkcmVuKTtcbiAgICAgICAgICAgICAgICB2YXIgYktleXMgPSBiQ2hpbGRJbmRleC5rZXlzO1xuICAgICAgICAgICAgICAgIHZhciBiRnJlZSA9IGJDaGlsZEluZGV4LmZyZWU7XG5cbiAgICAgICAgICAgICAgICBpZiAoYkZyZWUubGVuZ3RoID09PSBiQ2hpbGRyZW4ubGVuZ3RoKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiB7XG4gICAgICAgICAgICAgICAgICAgICAgICBjaGlsZHJlbjogYkNoaWxkcmVuLFxuICAgICAgICAgICAgICAgICAgICAgICAgbW92ZXM6IG51bGxcbiAgICAgICAgICAgICAgICAgICAgfTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAvLyBPKE4pIHRpbWUsIE8oTikgbWVtb3J5XG4gICAgICAgICAgICAgICAgdmFyIGFDaGlsZEluZGV4ID0ga2V5SW5kZXgoYUNoaWxkcmVuKTtcbiAgICAgICAgICAgICAgICB2YXIgYUtleXMgPSBhQ2hpbGRJbmRleC5rZXlzO1xuICAgICAgICAgICAgICAgIHZhciBhRnJlZSA9IGFDaGlsZEluZGV4LmZyZWU7XG5cbiAgICAgICAgICAgICAgICBpZiAoYUZyZWUubGVuZ3RoID09PSBhQ2hpbGRyZW4ubGVuZ3RoKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiB7XG4gICAgICAgICAgICAgICAgICAgICAgICBjaGlsZHJlbjogYkNoaWxkcmVuLFxuICAgICAgICAgICAgICAgICAgICAgICAgbW92ZXM6IG51bGxcbiAgICAgICAgICAgICAgICAgICAgfTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAvLyBPKE1BWChOLCBNKSkgbWVtb3J5XG4gICAgICAgICAgICAgICAgdmFyIG5ld0NoaWxkcmVuID0gW107XG5cbiAgICAgICAgICAgICAgICB2YXIgZnJlZUluZGV4ID0gMDtcbiAgICAgICAgICAgICAgICB2YXIgZnJlZUNvdW50ID0gYkZyZWUubGVuZ3RoO1xuICAgICAgICAgICAgICAgIHZhciBkZWxldGVkSXRlbXMgPSAwO1xuXG4gICAgICAgICAgICAgICAgLy8gSXRlcmF0ZSB0aHJvdWdoIGEgYW5kIG1hdGNoIGEgbm9kZSBpbiBiXG4gICAgICAgICAgICAgICAgLy8gTyhOKSB0aW1lLFxuICAgICAgICAgICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgYUNoaWxkcmVuLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciBhSXRlbSA9IGFDaGlsZHJlbltpXTtcbiAgICAgICAgICAgICAgICAgICAgdmFyIGl0ZW1JbmRleDtcblxuICAgICAgICAgICAgICAgICAgICBpZiAoYUl0ZW0ua2V5KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoYktleXMuaGFzT3duUHJvcGVydHkoYUl0ZW0ua2V5KSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIE1hdGNoIHVwIHRoZSBvbGQga2V5c1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGl0ZW1JbmRleCA9IGJLZXlzW2FJdGVtLmtleV07XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgbmV3Q2hpbGRyZW4ucHVzaChiQ2hpbGRyZW5baXRlbUluZGV4XSk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIFJlbW92ZSBvbGQga2V5ZWQgaXRlbXNcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpdGVtSW5kZXggPSBpIC0gZGVsZXRlZEl0ZW1zKys7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgbmV3Q2hpbGRyZW4ucHVzaChudWxsKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIE1hdGNoIHRoZSBpdGVtIGluIGEgd2l0aCB0aGUgbmV4dCBmcmVlIGl0ZW0gaW4gYlxuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGZyZWVJbmRleCA8IGZyZWVDb3VudCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGl0ZW1JbmRleCA9IGJGcmVlW2ZyZWVJbmRleCsrXTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBuZXdDaGlsZHJlbi5wdXNoKGJDaGlsZHJlbltpdGVtSW5kZXhdKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gVGhlcmUgYXJlIG5vIGZyZWUgaXRlbXMgaW4gYiB0byBtYXRjaCB3aXRoXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gdGhlIGZyZWUgaXRlbXMgaW4gYSwgc28gdGhlIGV4dHJhIGZyZWUgbm9kZXNcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBhcmUgZGVsZXRlZC5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpdGVtSW5kZXggPSBpIC0gZGVsZXRlZEl0ZW1zKys7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgbmV3Q2hpbGRyZW4ucHVzaChudWxsKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHZhciBsYXN0RnJlZUluZGV4ID0gZnJlZUluZGV4ID49IGJGcmVlLmxlbmd0aCA/IGJDaGlsZHJlbi5sZW5ndGggOiBiRnJlZVtmcmVlSW5kZXhdO1xuXG4gICAgICAgICAgICAgICAgLy8gSXRlcmF0ZSB0aHJvdWdoIGIgYW5kIGFwcGVuZCBhbnkgbmV3IGtleXNcbiAgICAgICAgICAgICAgICAvLyBPKE0pIHRpbWVcbiAgICAgICAgICAgICAgICBmb3IgKHZhciBqID0gMDsgaiA8IGJDaGlsZHJlbi5sZW5ndGg7IGorKykge1xuICAgICAgICAgICAgICAgICAgICB2YXIgbmV3SXRlbSA9IGJDaGlsZHJlbltqXTtcblxuICAgICAgICAgICAgICAgICAgICBpZiAobmV3SXRlbS5rZXkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmICghYUtleXMuaGFzT3duUHJvcGVydHkobmV3SXRlbS5rZXkpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gQWRkIGFueSBuZXcga2V5ZWQgaXRlbXNcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBXZSBhcmUgYWRkaW5nIG5ldyBpdGVtcyB0byB0aGUgZW5kIGFuZCB0aGVuIHNvcnRpbmcgdGhlbVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIGluIHBsYWNlLiBJbiBmdXR1cmUgd2Ugc2hvdWxkIGluc2VydCBuZXcgaXRlbXMgaW4gcGxhY2UuXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgbmV3Q2hpbGRyZW4ucHVzaChuZXdJdGVtKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIGlmIChqID49IGxhc3RGcmVlSW5kZXgpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIEFkZCBhbnkgbGVmdG92ZXIgbm9uLWtleWVkIGl0ZW1zXG4gICAgICAgICAgICAgICAgICAgICAgICBuZXdDaGlsZHJlbi5wdXNoKG5ld0l0ZW0pO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgdmFyIHNpbXVsYXRlID0gbmV3Q2hpbGRyZW4uc2xpY2UoKTtcbiAgICAgICAgICAgICAgICB2YXIgc2ltdWxhdGVJbmRleCA9IDA7XG4gICAgICAgICAgICAgICAgdmFyIHJlbW92ZXMgPSBbXTtcbiAgICAgICAgICAgICAgICB2YXIgaW5zZXJ0cyA9IFtdO1xuICAgICAgICAgICAgICAgIHZhciBzaW11bGF0ZUl0ZW07XG5cbiAgICAgICAgICAgICAgICBmb3IgKHZhciBrID0gMDsgayA8IGJDaGlsZHJlbi5sZW5ndGg7KSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciB3YW50ZWRJdGVtID0gYkNoaWxkcmVuW2tdO1xuICAgICAgICAgICAgICAgICAgICBzaW11bGF0ZUl0ZW0gPSBzaW11bGF0ZVtzaW11bGF0ZUluZGV4XTtcblxuICAgICAgICAgICAgICAgICAgICAvLyByZW1vdmUgaXRlbXNcbiAgICAgICAgICAgICAgICAgICAgd2hpbGUgKHNpbXVsYXRlSXRlbSA9PT0gbnVsbCAmJiBzaW11bGF0ZS5sZW5ndGgpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJlbW92ZXMucHVzaChyZW1vdmUoc2ltdWxhdGUsIHNpbXVsYXRlSW5kZXgsIG51bGwpKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIHNpbXVsYXRlSXRlbSA9IHNpbXVsYXRlW3NpbXVsYXRlSW5kZXhdO1xuICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgaWYgKCFzaW11bGF0ZUl0ZW0gfHwgc2ltdWxhdGVJdGVtLmtleSAhPT0gd2FudGVkSXRlbS5rZXkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIGlmIHdlIG5lZWQgYSBrZXkgaW4gdGhpcyBwb3NpdGlvbi4uLlxuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHdhbnRlZEl0ZW0ua2V5KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHNpbXVsYXRlSXRlbSAmJiBzaW11bGF0ZUl0ZW0ua2V5KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIGlmIGFuIGluc2VydCBkb2Vzbid0IHB1dCB0aGlzIGtleSBpbiBwbGFjZSwgaXQgbmVlZHMgdG8gbW92ZVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoYktleXNbc2ltdWxhdGVJdGVtLmtleV0gIT09IGsgKyAxKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICByZW1vdmVzLnB1c2gocmVtb3ZlKHNpbXVsYXRlLCBzaW11bGF0ZUluZGV4LCBzaW11bGF0ZUl0ZW0ua2V5KSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzaW11bGF0ZUl0ZW0gPSBzaW11bGF0ZVtzaW11bGF0ZUluZGV4XTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIGlmIHRoZSByZW1vdmUgZGlkbid0IHB1dCB0aGUgd2FudGVkIGl0ZW0gaW4gcGxhY2UsIHdlIG5lZWQgdG8gaW5zZXJ0IGl0XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoIXNpbXVsYXRlSXRlbSB8fCBzaW11bGF0ZUl0ZW0ua2V5ICE9PSB3YW50ZWRJdGVtLmtleSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGluc2VydHMucHVzaCh7IGtleTogd2FudGVkSXRlbS5rZXksIHRvOiBrIH0pO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gaXRlbXMgYXJlIG1hdGNoaW5nLCBzbyBza2lwIGFoZWFkXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzaW11bGF0ZUluZGV4Kys7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpbnNlcnRzLnB1c2goeyBrZXk6IHdhbnRlZEl0ZW0ua2V5LCB0bzogayB9KTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGluc2VydHMucHVzaCh7IGtleTogd2FudGVkSXRlbS5rZXksIHRvOiBrIH0pO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBrKys7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAvLyBhIGtleSBpbiBzaW11bGF0ZSBoYXMgbm8gbWF0Y2hpbmcgd2FudGVkIGtleSwgcmVtb3ZlIGl0XG4gICAgICAgICAgICAgICAgICAgICAgICBlbHNlIGlmIChzaW11bGF0ZUl0ZW0gJiYgc2ltdWxhdGVJdGVtLmtleSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlbW92ZXMucHVzaChyZW1vdmUoc2ltdWxhdGUsIHNpbXVsYXRlSW5kZXgsIHNpbXVsYXRlSXRlbS5rZXkpKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHNpbXVsYXRlSW5kZXgrKztcbiAgICAgICAgICAgICAgICAgICAgICAgIGsrKztcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIC8vIHJlbW92ZSBhbGwgdGhlIHJlbWFpbmluZyBub2RlcyBmcm9tIHNpbXVsYXRlXG4gICAgICAgICAgICAgICAgd2hpbGUgKHNpbXVsYXRlSW5kZXggPCBzaW11bGF0ZS5sZW5ndGgpIHtcbiAgICAgICAgICAgICAgICAgICAgc2ltdWxhdGVJdGVtID0gc2ltdWxhdGVbc2ltdWxhdGVJbmRleF07XG4gICAgICAgICAgICAgICAgICAgIHJlbW92ZXMucHVzaChyZW1vdmUoc2ltdWxhdGUsIHNpbXVsYXRlSW5kZXgsIHNpbXVsYXRlSXRlbSAmJiBzaW11bGF0ZUl0ZW0ua2V5KSk7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgLy8gSWYgdGhlIG9ubHkgbW92ZXMgd2UgaGF2ZSBhcmUgZGVsZXRlcyB0aGVuIHdlIGNhbiBqdXN0XG4gICAgICAgICAgICAgICAgLy8gbGV0IHRoZSBkZWxldGUgcGF0Y2ggcmVtb3ZlIHRoZXNlIGl0ZW1zLlxuICAgICAgICAgICAgICAgIGlmIChyZW1vdmVzLmxlbmd0aCA9PT0gZGVsZXRlZEl0ZW1zICYmICFpbnNlcnRzLmxlbmd0aCkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgICAgICAgICAgICAgY2hpbGRyZW46IG5ld0NoaWxkcmVuLFxuICAgICAgICAgICAgICAgICAgICAgICAgbW92ZXM6IG51bGxcbiAgICAgICAgICAgICAgICAgICAgfTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgICAgICAgICBjaGlsZHJlbjogbmV3Q2hpbGRyZW4sXG4gICAgICAgICAgICAgICAgICAgIG1vdmVzOiB7XG4gICAgICAgICAgICAgICAgICAgICAgICByZW1vdmVzOiByZW1vdmVzLFxuICAgICAgICAgICAgICAgICAgICAgICAgaW5zZXJ0czogaW5zZXJ0c1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZnVuY3Rpb24gcmVtb3ZlKGFyciwgaW5kZXgsIGtleSkge1xuICAgICAgICAgICAgICAgIGFyci5zcGxpY2UoaW5kZXgsIDEpO1xuXG4gICAgICAgICAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgICAgICAgICAgZnJvbTogaW5kZXgsXG4gICAgICAgICAgICAgICAgICAgIGtleToga2V5XG4gICAgICAgICAgICAgICAgfTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZnVuY3Rpb24ga2V5SW5kZXgoY2hpbGRyZW4pIHtcbiAgICAgICAgICAgICAgICB2YXIga2V5cyA9IHt9O1xuICAgICAgICAgICAgICAgIHZhciBmcmVlID0gW107XG4gICAgICAgICAgICAgICAgdmFyIGxlbmd0aCA9IGNoaWxkcmVuLmxlbmd0aDtcblxuICAgICAgICAgICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgbGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgICAgICAgICAgdmFyIGNoaWxkID0gY2hpbGRyZW5baV07XG5cbiAgICAgICAgICAgICAgICAgICAgaWYgKGNoaWxkLmtleSkge1xuICAgICAgICAgICAgICAgICAgICAgICAga2V5c1tjaGlsZC5rZXldID0gaTtcbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGZyZWUucHVzaChpKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHJldHVybiB7XG4gICAgICAgICAgICAgICAgICAgIGtleXM6IGtleXMsIC8vIEEgaGFzaCBvZiBrZXkgbmFtZSB0byBpbmRleFxuICAgICAgICAgICAgICAgICAgICBmcmVlOiBmcmVlIC8vIEFuIGFycmF5IG9mIHVua2V5ZWQgaXRlbSBpbmRpY2VzXG4gICAgICAgICAgICAgICAgfTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZnVuY3Rpb24gYXBwZW5kUGF0Y2goYXBwbHksIHBhdGNoKSB7XG4gICAgICAgICAgICAgICAgaWYgKGFwcGx5KSB7XG4gICAgICAgICAgICAgICAgICAgIGlmIChpc0FycmF5KGFwcGx5KSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgYXBwbHkucHVzaChwYXRjaCk7XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBhcHBseSA9IFthcHBseSwgcGF0Y2hdO1xuICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGFwcGx5O1xuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBwYXRjaDtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH0sIHsgXCIuLi92bm9kZS9oYW5kbGUtdGh1bmtcIjogMjQsIFwiLi4vdm5vZGUvaXMtdGh1bmtcIjogMjUsIFwiLi4vdm5vZGUvaXMtdm5vZGVcIjogMjcsIFwiLi4vdm5vZGUvaXMtdnRleHRcIjogMjgsIFwiLi4vdm5vZGUvaXMtd2lkZ2V0XCI6IDI5LCBcIi4uL3Zub2RlL3ZwYXRjaFwiOiAzMiwgXCIuL2RpZmYtcHJvcHNcIjogMzQsIFwieC1pcy1hcnJheVwiOiAxMiB9XSB9LCB7fSwgWzRdKSg0KTtcbn0pO1xuXG5jb25zdCBDb3JlID0gQztcblxuZXhwb3J0IHsgQ29yZSwgRW51bSwgVmlydHVhbERPTSB9OyJdLCJmaWxlIjoiRWxpeGlyLmpzIiwic291cmNlUm9vdCI6Ii9zb3VyY2UvIn0= \ No newline at end of file diff --git a/src/javascript/lib/core/special_forms.js b/src/javascript/lib/core/special_forms.js index 15e03a32..3e988613 100644 --- a/src/javascript/lib/core/special_forms.js +++ b/src/javascript/lib/core/special_forms.js @@ -2,14 +2,6 @@ import BitString from './bit_string'; import Patterns from './patterns'; import { Tuple } from './primitives'; -function list(...args){ - return Object.freeze(args); -} - -function bitstring(...args){ - return new BitString(...args); -} - function _case(condition, clauses){ return Patterns.defmatch(...clauses)(condition); } @@ -24,10 +16,6 @@ function cond(clauses){ throw new Error(); } -function map(obj){ - return Object.freeze(obj); -} - function map_update(map, values){ return Object.freeze( Object.assign( @@ -120,11 +108,8 @@ function _try(do_fun, rescue_function, catch_fun, else_function, after_function) } export default { - list, - bitstring, _case, cond, - map, map_update, _for, _try diff --git a/src/javascript/lib/enum.js b/src/javascript/lib/enum.js index 5806efeb..1e9dbfdd 100644 --- a/src/javascript/lib/enum.js +++ b/src/javascript/lib/enum.js @@ -135,14 +135,14 @@ let Enum = { }, map_reduce: function(collection, acc, fun){ - let mapped = Core.List(); + let mapped = Object.freeze([]); let the_acc = acc; for (var i = 0; i < this.count(collection); i++) { let tuple = fun(collection[i], the_acc); the_acc = tuple.get(1); - mapped = Core.List(...mapped.concat([tuple.get(0)])); + mapped = Object.freeze(mapped.concat([tuple.get(0)])); } return new Core.Tuple(mapped, the_acc); @@ -178,7 +178,7 @@ let Enum = { } } - return Core.List(...result); + return Object.freeze(result); }, take_while: function(collection, fun){ diff --git a/test/elixir_script_test.exs b/test/elixir_script_test.exs index e814f24d..88d9f63c 100644 --- a/test/elixir_script_test.exs +++ b/test/elixir_script_test.exs @@ -80,7 +80,7 @@ defmodule ElixirScript.Test do import * as Elixir$ElixirScript$Kernel from './Elixir.ElixirScript.Kernel'; import * as Elixir$Animals$Elephant from './Elixir.Animals.Elephant'; const something = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([],function() { - return Elixir$Animals$Elephant.Elixir$Animals$Elephant.create(Elixir.Core.SpecialForms.map({})); + return Elixir$Animals$Elephant.Elixir$Animals$Elephant.create(Object.freeze({})); })); export { something diff --git a/test/prelude/js_test.exs b/test/prelude/js_test.exs index 0680d836..fd5f800f 100644 --- a/test/prelude/js_test.exs +++ b/test/prelude/js_test.exs @@ -30,7 +30,7 @@ defmodule ElixirScript.Lib.JS.Test do end js_code = """ - A['b'] = Elixir.Core.SpecialForms.list(1, 2, 3) + A['b'] = Object.freeze([1, 2, 3]) """ assert_translation(ex_ast, js_code) diff --git a/test/prelude/kernel_test.exs b/test/prelude/kernel_test.exs index 0ae653fc..4eb7f06a 100644 --- a/test/prelude/kernel_test.exs +++ b/test/prelude/kernel_test.exs @@ -8,7 +8,7 @@ defmodule ElixirScript.Lib.Elixir.Kernel.Test do end js_code = """ - Elixir$ElixirScript$Range.Elixir$ElixirScript$Range.create(Elixir.Core.SpecialForms.map({ + Elixir$ElixirScript$Range.Elixir$ElixirScript$Range.create(Object.freeze({ [Symbol.for('first')]: 1, [Symbol.for('last')]: 4 })) diff --git a/test/translator/assignment_test.exs b/test/translator/assignment_test.exs index 851d3baa..a58f808a 100644 --- a/test/translator/assignment_test.exs +++ b/test/translator/assignment_test.exs @@ -61,8 +61,8 @@ defmodule ElixirScript.Translator.Assignment.Test do test "translate list assignment" do ex_ast = quote do: [a, b] = [1, 2] js_code = """ - let [a, b] = Elixir.Core.Patterns.match(Elixir.Core.SpecialForms.list(Elixir.Core.Patterns.variable(), Elixir.Core.Patterns.variable()), Elixir.Core.SpecialForms.list(1, 2)); - let _ref = Elixir.Core.SpecialForms.list(a, b); + let [a,b] = Elixir.Core.Patterns.match(Object.freeze([Elixir.Core.Patterns.variable(), Elixir.Core.Patterns.variable()]),Object.freeze([1, 2])); + let _ref = Object.freeze([a, b]); """ assert_translation(ex_ast, js_code) @@ -71,8 +71,8 @@ defmodule ElixirScript.Translator.Assignment.Test do test "translate head/tail assignment" do ex_ast = quote do: [a | b] = [1, 2, 3, 4] js_code = """ - let [a,b] = Elixir.Core.Patterns.match(Elixir.Core.Patterns.headTail(),Elixir.Core.SpecialForms.list(1,2,3,4)); - let _ref = Elixir.Core.SpecialForms.list(a,b); + let [a,b] = Elixir.Core.Patterns.match(Elixir.Core.Patterns.headTail(),Object.freeze([1, 2, 3, 4])); + let _ref = Object.freeze([a, b]); """ assert_translation(ex_ast, js_code) diff --git a/test/translator/bitstring_test.exs b/test/translator/bitstring_test.exs index 53fc9e07..c0ec38d2 100644 --- a/test/translator/bitstring_test.exs +++ b/test/translator/bitstring_test.exs @@ -4,39 +4,39 @@ defmodule ElixirScript.Translator.Bitstring.Test do test "translate bitstring" do ex_ast = quote do: <<1, 2, 3>> - assert_translation(ex_ast, "Elixir.Core.SpecialForms.bitstring(Elixir.Core.BitString.integer(1), Elixir.Core.BitString.integer(2), Elixir.Core.BitString.integer(3))") + assert_translation(ex_ast, "new Elixir.Core.BitString(Elixir.Core.BitString.integer(1), Elixir.Core.BitString.integer(2), Elixir.Core.BitString.integer(3))") ex_ast = quote do: <<1, "foo">> - assert_translation(ex_ast, "Elixir.Core.SpecialForms.bitstring(Elixir.Core.BitString.integer(1), Elixir.Core.BitString.binary('foo'))") + assert_translation(ex_ast, "new Elixir.Core.BitString(Elixir.Core.BitString.integer(1), Elixir.Core.BitString.binary('foo'))") ex_ast = quote do: <<1, "foo" :: binary>> - assert_translation(ex_ast, "Elixir.Core.SpecialForms.bitstring(Elixir.Core.BitString.integer(1), Elixir.Core.BitString.binary('foo'))") + assert_translation(ex_ast, "new Elixir.Core.BitString(Elixir.Core.BitString.integer(1), Elixir.Core.BitString.binary('foo'))") ex_ast = quote do: <<1, "foo" :: utf8, "bar" :: utf32>> - assert_translation(ex_ast, "Elixir.Core.SpecialForms.bitstring(Elixir.Core.BitString.integer(1), Elixir.Core.BitString.utf8('foo'), Elixir.Core.BitString.utf32('bar'))") + assert_translation(ex_ast, "new Elixir.Core.BitString(Elixir.Core.BitString.integer(1), Elixir.Core.BitString.utf8('foo'), Elixir.Core.BitString.utf32('bar'))") ex_ast = quote do: <<102 :: integer-native, rest :: binary>> - assert_translation(ex_ast, "Elixir.Core.SpecialForms.bitstring(Elixir.Core.BitString.native(Elixir.Core.BitString.integer(102)), Elixir.Core.BitString.binary(rest))") + assert_translation(ex_ast, "new Elixir.Core.BitString(Elixir.Core.BitString.native(Elixir.Core.BitString.integer(102)), Elixir.Core.BitString.binary(rest))") ex_ast = quote do: <<102 :: unsigned-big-integer, rest :: binary>> - assert_translation(ex_ast, "Elixir.Core.SpecialForms.bitstring(Elixir.Core.BitString.integer(Elixir.Core.BitString.big(Elixir.Core.BitString.unsigned(102))), Elixir.Core.BitString.binary(rest))") + assert_translation(ex_ast, "new Elixir.Core.BitString(Elixir.Core.BitString.integer(Elixir.Core.BitString.big(Elixir.Core.BitString.unsigned(102))), Elixir.Core.BitString.binary(rest))") ex_ast = quote do: <<102, _rest :: size(16)>> - assert_translation(ex_ast, "Elixir.Core.SpecialForms.bitstring(Elixir.Core.BitString.integer(102), Elixir.Core.BitString.size(_rest, 16))") + assert_translation(ex_ast, "new Elixir.Core.BitString(Elixir.Core.BitString.integer(102), Elixir.Core.BitString.size(_rest, 16))") ex_ast = quote do: <<102, _rest :: size(16)-unit(4)>> - assert_translation(ex_ast, "Elixir.Core.SpecialForms.bitstring(Elixir.Core.BitString.integer(102), Elixir.Core.BitString.unit(Elixir.Core.BitString.size(_rest, 16), 4))") + assert_translation(ex_ast, "new Elixir.Core.BitString(Elixir.Core.BitString.integer(102), Elixir.Core.BitString.unit(Elixir.Core.BitString.size(_rest, 16), 4))") ex_ast = quote do: <<102, _rest :: 16 * 4>> - assert_translation(ex_ast, "Elixir.Core.SpecialForms.bitstring(Elixir.Core.BitString.integer(102), Elixir.Core.BitString.unit(Elixir.Core.BitString.size(_rest, 16), 4))") + assert_translation(ex_ast, "new Elixir.Core.BitString(Elixir.Core.BitString.integer(102), Elixir.Core.BitString.unit(Elixir.Core.BitString.size(_rest, 16), 4))") ex_ast = quote do: <<102, _rest :: _ * 4>> - assert_translation(ex_ast, "Elixir.Core.SpecialForms.bitstring(Elixir.Core.BitString.integer(102), Elixir.Core.BitString.unit(Elixir.Core.BitString.size(_rest, undefined), 4))") + assert_translation(ex_ast, "new Elixir.Core.BitString(Elixir.Core.BitString.integer(102), Elixir.Core.BitString.unit(Elixir.Core.BitString.size(_rest, undefined), 4))") ex_ast = quote do: <<102, _rest :: 16>> - assert_translation(ex_ast, "Elixir.Core.SpecialForms.bitstring(Elixir.Core.BitString.integer(102), Elixir.Core.BitString.size(_rest, 16))") + assert_translation(ex_ast, "new Elixir.Core.BitString(Elixir.Core.BitString.integer(102), Elixir.Core.BitString.size(_rest, 16))") ex_ast = quote do: << 1, <<2>> >> - assert_translation(ex_ast, "Elixir.Core.SpecialForms.bitstring(Elixir.Core.BitString.integer(1), Elixir.Core.SpecialForms.bitstring(Elixir.Core.BitString.integer(2)))") + assert_translation(ex_ast, "new Elixir.Core.BitString(Elixir.Core.BitString.integer(1), new Elixir.Core.BitString(Elixir.Core.BitString.integer(2)))") end end diff --git a/test/translator/bug_test.exs b/test/translator/bug_test.exs index 4a64c8d2..e6dbb769 100644 --- a/test/translator/bug_test.exs +++ b/test/translator/bug_test.exs @@ -28,7 +28,7 @@ defmodule ElixirScript.Translator.Bug.Test do end js_code = """ - React.createElement(React.Text,Elixir.Core.SpecialForms.map({ + React.createElement(React.Text,Object.freeze({ style: Elixir.Core.Functions.call_property(styles,'welcome') }),'Welcome to React Native!') """ @@ -118,7 +118,7 @@ defmodule ElixirScript.Translator.Bug.Test do js_code = """ const getDispatcher = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([],function() { - return DeLorean.Flux.createDispatcher(Elixir.Core.SpecialForms.map({ + return DeLorean.Flux.createDispatcher(Object.freeze({ [Symbol.for('startPainting')]: Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([],function() { return this.dispatch('startPainting'); })), [Symbol.for('stopPainting')]: Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([],function() { @@ -126,7 +126,7 @@ defmodule ElixirScript.Translator.Bug.Test do })), [Symbol.for('addPoint')]: Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable()],function(data) { return this.dispatch('addPoint',data); })), [Symbol.for('getStores')]: Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([],function() { - return Elixir.Core.SpecialForms.map({ + return Object.freeze({ [Symbol.for('graphic')]: GraphicStore }); })) diff --git a/test/translator/case_test.exs b/test/translator/case_test.exs index db944222..d5b06678 100644 --- a/test/translator/case_test.exs +++ b/test/translator/case_test.exs @@ -75,7 +75,7 @@ defmodule ElixirScript.Translator.Case.Test do let [value] = Elixir.Core.Patterns.match(Elixir.Core.Patterns.variable(),13); return value; },function(number) { - return Elixir.Core.Functions.contains(number,Elixir.Core.SpecialForms.list(1,2,3,4)); + return Elixir.Core.Functions.contains(number,Object.freeze([1, 2, 3, 4])); }),Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.wildcard()],function() { return true; })).call(this,data) diff --git a/test/translator/cond_test.exs b/test/translator/cond_test.exs index 5888619d..7666d4f5 100644 --- a/test/translator/cond_test.exs +++ b/test/translator/cond_test.exs @@ -15,13 +15,13 @@ defmodule ElixirScript.Translator.Cond.Test do end js_code = """ - Elixir.Core.SpecialForms.cond(Elixir.Core.SpecialForms.list(1 + 1 == 1,function() { + Elixir.Core.SpecialForms.cond(Object.freeze([1 + 1 == 1, function() { return 'This will never match'; - }),Elixir.Core.SpecialForms.list(2 * 2 != 4,function() { + }]),Object.freeze([2 * 2 != 4, function() { return 'Nor this'; - }),Elixir.Core.SpecialForms.list(true,function() { + }]),Object.freeze([true, function() { return 'This will'; - })) + }])) """ assert_translation(ex_ast, js_code) @@ -41,16 +41,16 @@ defmodule ElixirScript.Translator.Cond.Test do end js_code = """ - Elixir.Core.SpecialForms.cond(Elixir.Core.SpecialForms.list(1 + 1 == 1,function() { + Elixir.Core.SpecialForms.cond(Object.freeze([1 + 1 == 1, function() { let [a] = Elixir.Core.Patterns.match(Elixir.Core.Patterns.variable(),1); return 'This will never match'; - }),Elixir.Core.SpecialForms.list(2 * 2 != 4,function() { + }]),Object.freeze([2 * 2 != 4, function() { let [a] = Elixir.Core.Patterns.match(Elixir.Core.Patterns.variable(),2); return 'Nor this'; - }),Elixir.Core.SpecialForms.list(true,function() { + }]),Object.freeze([true, function() { let [a] = Elixir.Core.Patterns.match(Elixir.Core.Patterns.variable(),3); return 'This will'; - })) + }])) """ assert_translation(ex_ast, js_code) diff --git a/test/translator/defmodule_test.exs b/test/translator/defmodule_test.exs index ca77670f..e032dd1f 100644 --- a/test/translator/defmodule_test.exs +++ b/test/translator/defmodule_test.exs @@ -74,7 +74,7 @@ defmodule ElixirScript.Translator.Defmodule.Test do })); const something = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([],function() { - return Elixir$Animals$Elephant.Elixir$Animals$Elephant.create(Elixir.Core.SpecialForms.map({})); + return Elixir$Animals$Elephant.Elixir$Animals$Elephant.create(Object.freeze({})); })); export { @@ -125,7 +125,7 @@ defmodule ElixirScript.Translator.Defmodule.Test do return null; })); const something = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([],function() { - return Elixir$Animals$Elephant.Elixir$Animals$Elephant.create(Elixir.Core.SpecialForms.map({})); + return Elixir$Animals$Elephant.Elixir$Animals$Elephant.create(Object.freeze({})); })); export { diff --git a/test/translator/for_test.exs b/test/translator/for_test.exs index 2920f59b..cbce5df3 100644 --- a/test/translator/for_test.exs +++ b/test/translator/for_test.exs @@ -8,11 +8,11 @@ defmodule ElixirScript.Translator.For.Test do end js_code = """ - Elixir.Core.SpecialForms._for(Elixir.Core.SpecialForms.list(Elixir.Core.SpecialForms.list(Elixir.Core.Patterns.variable(),Elixir.Core.SpecialForms.list(1,2,3,4))),function(n) { + Elixir.Core.SpecialForms._for(Object.freeze([Object.freeze([Elixir.Core.Patterns.variable(), Object.freeze([1, 2, 3, 4])])]),function(n) { return n * 2; },function() { return true; - },Elixir.Core.SpecialForms.list()) + },Object.freeze([])) """ assert_translation(ex_ast, js_code) @@ -24,11 +24,11 @@ defmodule ElixirScript.Translator.For.Test do end js_code = """ - Elixir.Core.SpecialForms._for(Elixir.Core.SpecialForms.list(Elixir.Core.SpecialForms.list(Elixir.Core.Patterns.variable(),Elixir.Core.SpecialForms.list(1,2,3,4))),function(n) { + Elixir.Core.SpecialForms._for(Object.freeze([Object.freeze([Elixir.Core.Patterns.variable(), Object.freeze([1, 2, 3, 4])])]),function(n) { return n * 2; },function() { return true; - },Elixir.Core.SpecialForms.list()) + },Object.freeze([])) """ assert_translation(ex_ast, js_code) @@ -40,11 +40,11 @@ defmodule ElixirScript.Translator.For.Test do end js_code = """ - Elixir.Core.SpecialForms._for(Elixir.Core.SpecialForms.list(Elixir.Core.SpecialForms.list(Elixir.Core.Patterns.variable(),'Opera')),function(n) { + Elixir.Core.SpecialForms._for(Object.freeze([Object.freeze([Elixir.Core.Patterns.variable(), 'Opera'])]),function(n) { return n; },function() { return true; - },Elixir.Core.SpecialForms.list()) + },Object.freeze([])) """ assert_translation(ex_ast, js_code) @@ -56,13 +56,11 @@ defmodule ElixirScript.Translator.For.Test do end js_code = """ - Elixir.Core.SpecialForms._for(Elixir.Core.SpecialForms.list( - Elixir.Core.SpecialForms.list(Elixir.Core.Patterns.variable(), Elixir.Core.SpecialForms.list(1,2)), - Elixir.Core.SpecialForms.list(Elixir.Core.Patterns.variable(), Elixir.Core.SpecialForms.list(2,3))), function(x,y) { - return x * y; - },function() { - return true; - },Elixir.Core.SpecialForms.list()) + Elixir.Core.SpecialForms._for(Object.freeze([Object.freeze([Elixir.Core.Patterns.variable(), Object.freeze([1, 2])]), Object.freeze([Elixir.Core.Patterns.variable(), Object.freeze([2, 3])])]),function(x,y) { + return x * y; + },function() { + return true; + },Object.freeze([])) """ assert_translation(ex_ast, js_code) @@ -76,11 +74,11 @@ defmodule ElixirScript.Translator.For.Test do end js_code = """ - let [r] = Elixir.Core.Patterns.match(Elixir.Core.Patterns.variable(),Elixir.Core.SpecialForms._for(Elixir.Core.SpecialForms.list(Elixir.Core.SpecialForms.list(Elixir.Core.Patterns.variable(),Elixir.Core.SpecialForms.list(1,2)),Elixir.Core.SpecialForms.list(Elixir.Core.Patterns.variable(),Elixir.Core.SpecialForms.list(2,3))),function(x,y) { + let [r] = Elixir.Core.Patterns.match(Elixir.Core.Patterns.variable(),Elixir.Core.SpecialForms._for(Object.freeze([Object.freeze([Elixir.Core.Patterns.variable(), Object.freeze([1, 2])]), Object.freeze([Elixir.Core.Patterns.variable(), Object.freeze([2, 3])])]),function(x,y) { return x * y; },function() { return true; - },Elixir.Core.SpecialForms.list())); + },Object.freeze([]))); """ assert_translation(ex_ast, js_code) @@ -92,11 +90,11 @@ defmodule ElixirScript.Translator.For.Test do end js_code = """ - Elixir.Core.SpecialForms._for(Elixir.Core.SpecialForms.list(Elixir.Core.SpecialForms.list(Elixir.Core.Patterns.variable(),Elixir.Core.SpecialForms.list(1,2,3,4,5,6))),function(n) { - return n; + Elixir.Core.SpecialForms._for(Object.freeze([Object.freeze([Elixir.Core.Patterns.variable(), Object.freeze([1, 2, 3, 4, 5, 6])])]),function(n) { + return n; },function(n) { - return n % 2 == 0; - },Elixir.Core.SpecialForms.list()) + return n % 2 == 0; + },Object.freeze([])) """ assert_translation(ex_ast, js_code) @@ -110,13 +108,13 @@ defmodule ElixirScript.Translator.For.Test do end js_code = """ - Elixir.Core.SpecialForms._for(Elixir.Core.SpecialForms.list(Elixir.Core.SpecialForms.list(Elixir.Core.Patterns.type(Elixir.Core.Tuple,{ - values: [Symbol.for('user'), Elixir.Core.Patterns.variable()] - }),Elixir.Core.SpecialForms.list(new Elixir.Core.Tuple(Symbol.for('user'),'john'),new Elixir.Core.Tuple(Symbol.for('admin'),'john'),new Elixir.Core.Tuple(Symbol.for('user'),'meg')))),function(name) { - return Elixir$ElixirScript$String.upcase(name); - },function() { - return true; - },Elixir.Core.SpecialForms.list()) + Elixir.Core.SpecialForms._for(Object.freeze([Object.freeze([Elixir.Core.Patterns.type(Elixir.Core.Tuple,{ + values: [Symbol.for('user'), Elixir.Core.Patterns.variable()] + }), Object.freeze([new Elixir.Core.Tuple(Symbol.for('user'),'john'), new Elixir.Core.Tuple(Symbol.for('admin'),'john'), new Elixir.Core.Tuple(Symbol.for('user'),'meg')])])]),function(name) { + return Elixir$ElixirScript$String.upcase(name); + },function() { + return true; + },Object.freeze([])) """ assert_translation(ex_ast, js_code) diff --git a/test/translator/function_test.exs b/test/translator/function_test.exs index 5fb8d23c..56fcdee7 100644 --- a/test/translator/function_test.exs +++ b/test/translator/function_test.exs @@ -85,11 +85,11 @@ defmodule ElixirScript.Translator.Function.Test do end js_code = """ - const test1 = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable(), Elixir.Core.Patterns.variable()],function(alpha,beta) { + const test1 = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable(), Elixir.Core.Patterns.variable()],function(alpha,beta) { return Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable()],function(x) { return 2; },function(x) { - return Elixir.Enum.member__qmark__(Elixir.Core.SpecialForms.list(false,null), x); + return Elixir.Enum.member__qmark__(Object.freeze([false, null]),x); }),Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.wildcard()],function() { return 1; })).call(this,1 == 1); @@ -113,22 +113,22 @@ defmodule ElixirScript.Translator.Function.Test do end js_code = """ - const test1 = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable(), Elixir.Core.Patterns.variable()],function(alpha,beta) { - return Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable()],function(x) { - return 2; - },function(x) { - return Elixir.Enum.member__qmark__(Elixir.Core.SpecialForms.list(false,null),x); - }),Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.wildcard()],function() { - return Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable()],function(x) { - let [a] = Elixir.Core.Patterns.match(Elixir.Core.Patterns.variable(), 1); - return a; - },function(x) { - return Elixir.Enum.member__qmark__(Elixir.Core.SpecialForms.list(false,null),x); - }),Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.wildcard()],function() { - return 4; - })).call(this,2 == 2); - })).call(this,1 == 1); - })); + const test1 = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable(), Elixir.Core.Patterns.variable()],function(alpha,beta) { + return Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable()],function(x) { + return 2; + },function(x) { + return Elixir.Enum.member__qmark__(Object.freeze([false, null]),x); + }),Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.wildcard()],function() { + return Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable()],function(x) { + let [a] = Elixir.Core.Patterns.match(Elixir.Core.Patterns.variable(),1); + return a; + },function(x) { + return Elixir.Enum.member__qmark__(Object.freeze([false, null]),x); + }),Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.wildcard()],function() { + return 4; + })).call(this,2 == 2); + })).call(this,1 == 1); + })); """ assert_translation(ex_ast, js_code) @@ -404,7 +404,7 @@ defmodule ElixirScript.Translator.Function.Test do const something = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable(), Elixir.Core.Patterns.variable()],function(one,two) { return null; },function(one,two) { - return Elixir.Core.Functions.contains(one,Elixir.Core.SpecialForms.list(1,2,3)); + return Elixir.Core.Functions.contains(one,Object.freeze([1, 2, 3])); })); """ @@ -425,7 +425,7 @@ defmodule ElixirScript.Translator.Function.Test do const something = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable()],function(one) { return null; },function(one) { - return Elixir.Core.Functions.contains(one,Elixir.Core.SpecialForms.list(1,2,3)); + return Elixir.Core.Functions.contains(one,Object.freeze([1, 2, 3])); }),Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable()],function(one) { return null; },function(one) { @@ -479,9 +479,9 @@ defmodule ElixirScript.Translator.Function.Test do js_code = """ - const something = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Core.SpecialForms.list(Elixir.Core.Patterns.variable(),Elixir.Core.Patterns.variable(),Elixir.Core.Patterns.variable())],function(apple,pear,banana) { - return null; - })); + const something = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Object.freeze([Elixir.Core.Patterns.variable(), Elixir.Core.Patterns.variable(), Elixir.Core.Patterns.variable()])],function(apple,pear,banana) { + return null; + })); """ assert_translation(ex_ast, js_code) @@ -719,11 +719,11 @@ defmodule ElixirScript.Translator.Function.Test do js_code = """ const test1 = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable(), Elixir.Core.Patterns.variable()],function(alpha,beta) { - let [a] = Elixir.Core.Patterns.match(Elixir.Core.Patterns.variable(),1); - let [a1,b,c] = Elixir.Core.Patterns.match(Elixir.Core.SpecialForms.list(Elixir.Core.Patterns.variable(),Elixir.Core.Patterns.variable(),Elixir.Core.Patterns.variable()),Elixir.Core.SpecialForms.list(a,2,3)); - let _ref = Elixir.Core.SpecialForms.list(a1,b,c); - return _ref; - })); + let [a] = Elixir.Core.Patterns.match(Elixir.Core.Patterns.variable(),1); + let [a1,b,c] = Elixir.Core.Patterns.match(Object.freeze([Elixir.Core.Patterns.variable(), Elixir.Core.Patterns.variable(), Elixir.Core.Patterns.variable()]),Object.freeze([a, 2, 3])); + let _ref = Object.freeze([a1, b, c]); + return _ref; + })); """ assert_translation(ex_ast, js_code) diff --git a/test/translator/kernel_test.exs b/test/translator/kernel_test.exs index ead45061..32afa525 100644 --- a/test/translator/kernel_test.exs +++ b/test/translator/kernel_test.exs @@ -21,7 +21,7 @@ defmodule ElixirScript.Translator.Kernel.Test do end js_code = """ - Elixir$ElixirScript$Kernel.apply(fun, Elixir.Core.SpecialForms.list(1,2,3)) + Elixir$ElixirScript$Kernel.apply(fun, Object.freeze([1, 2, 3])) """ assert_translation(ex_ast, js_code) @@ -34,7 +34,7 @@ defmodule ElixirScript.Translator.Kernel.Test do end js_code = """ - Elixir$ElixirScript$Kernel.apply(Enum,Symbol.for('reverse'),Elixir.Core.SpecialForms.list(1,2,3)) + Elixir$ElixirScript$Kernel.apply(Enum,Symbol.for('reverse'),Object.freeze([1, 2, 3])) """ assert_translation(ex_ast, js_code) @@ -47,7 +47,7 @@ defmodule ElixirScript.Translator.Kernel.Test do end js_code = """ - Elixir$ElixirScript$Kernel.hd(Elixir.Core.SpecialForms.list(1,2,3)) + Elixir$ElixirScript$Kernel.hd(Object.freeze([1, 2, 3])) """ assert_translation(ex_ast, js_code) @@ -60,7 +60,7 @@ defmodule ElixirScript.Translator.Kernel.Test do end js_code = """ - Elixir$ElixirScript$Kernel.tl(Elixir.Core.SpecialForms.list(1,2,3)) + Elixir$ElixirScript$Kernel.tl(Object.freeze([1, 2, 3])) """ assert_translation(ex_ast, js_code) diff --git a/test/translator/list_test.exs b/test/translator/list_test.exs index 6543f751..79567c77 100644 --- a/test/translator/list_test.exs +++ b/test/translator/list_test.exs @@ -4,34 +4,34 @@ defmodule ElixirScript.Translator.List.Test do test "translate list" do ex_ast = quote do: [1, 2, 3] - js_code = "Elixir.Core.SpecialForms.list(1, 2, 3)" + js_code = "Object.freeze([1, 2, 3])" assert_translation(ex_ast, js_code) ex_ast = quote do: ["a", "b", "c"] - js_code = "Elixir.Core.SpecialForms.list('a', 'b', 'c')" + js_code = "Object.freeze(['a', 'b', 'c'])" assert_translation(ex_ast, js_code) ex_ast = quote do: [:a, :b, :c] - js_code = "Elixir.Core.SpecialForms.list(Symbol.for('a'), Symbol.for('b'), Symbol.for('c'))" + js_code = "Object.freeze([Symbol.for('a'), Symbol.for('b'), Symbol.for('c')])" assert_translation(ex_ast, js_code) ex_ast = quote do: [:a, 2, "c"] - js_code = "Elixir.Core.SpecialForms.list(Symbol.for('a'), 2, 'c')" + js_code = "Object.freeze([Symbol.for('a'), 2, 'c'])" assert_translation(ex_ast, js_code) end test "concatenate lists" do ex_ast = quote do: [1, 2, 3] ++ [4, 5, 6] - js_code = "Elixir.Core.SpecialForms.list(1,2,3).concat(Elixir.Core.SpecialForms.list(4,5,6))" + js_code = "Object.freeze([1, 2, 3]).concat(Object.freeze([4, 5, 6]))" assert_translation(ex_ast, js_code) ex_ast = quote do: this.list ++ [4, 5, 6] - js_code = "Elixir.Core.Functions.call_property(this,'list').concat(Elixir.Core.SpecialForms.list(4,5,6))" + js_code = "Elixir.Core.Functions.call_property(this,'list').concat(Object.freeze([4, 5, 6]))" assert_translation(ex_ast, js_code) end @@ -39,7 +39,7 @@ defmodule ElixirScript.Translator.List.Test do test "prepend element" do ex_ast = quote do: [x | list] - js_code = "Elixir.Core.SpecialForms.list(x).concat(list)" + js_code = "Object.freeze([x]).concat(list)" assert_translation(ex_ast, js_code) end @@ -51,7 +51,7 @@ defmodule ElixirScript.Translator.List.Test do js_code = """ Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.wildcard()],function(){ - return Elixir.Core.SpecialForms.list(x).concat(list); + return Object.freeze([x]).concat(list); })) """ diff --git a/test/translator/map_test.exs b/test/translator/map_test.exs index a663b94d..356c2d0d 100644 --- a/test/translator/map_test.exs +++ b/test/translator/map_test.exs @@ -4,14 +4,14 @@ defmodule ElixirScript.Translator.Map.Test do test "translate empty map" do ex_ast = quote do: %{} - js_code = "Elixir.Core.SpecialForms.map({})" + js_code = "Object.freeze({})" assert_translation(ex_ast, js_code) end test "translate map with elements" do ex_ast = quote do: %{one: "one", two: "two"} - js_code = "Elixir.Core.SpecialForms.map({[Symbol.for('one')]: 'one', [Symbol.for('two')]: 'two'})" + js_code = "Object.freeze({[Symbol.for('one')]: 'one', [Symbol.for('two')]: 'two'})" assert_translation(ex_ast, js_code) end @@ -19,9 +19,9 @@ defmodule ElixirScript.Translator.Map.Test do test "translate map within map" do ex_ast = quote do: %{one: "one", two: %{three: "three"}} js_code = """ - Elixir.Core.SpecialForms.map({ + Object.freeze({ [Symbol.for('one')]: 'one', - [Symbol.for('two')]: Elixir.Core.SpecialForms.map({ + [Symbol.for('two')]: Object.freeze({ [Symbol.for('three')]: 'three' }) }) @@ -33,7 +33,7 @@ defmodule ElixirScript.Translator.Map.Test do test "translate map with string keys" do ex_ast = quote do: %{"one" => "one", "two" => "two"} js_code = """ - Elixir.Core.SpecialForms.map({ + Object.freeze({ one: 'one', two: 'two' }) """ @@ -45,9 +45,9 @@ defmodule ElixirScript.Translator.Map.Test do test "translate map update" do ex_ast = quote do: %{ map | value: 1 } js_code = """ - Elixir.Core.SpecialForms.map_update(map,{ + Elixir.Core.SpecialForms.map_update(map,Object.freeze({ [Symbol.for('value')]: 1 - }) + })) """ assert_translation(ex_ast, js_code) diff --git a/test/translator/protocol_test.exs b/test/translator/protocol_test.exs index 7c12f196..1f2df19a 100644 --- a/test/translator/protocol_test.exs +++ b/test/translator/protocol_test.exs @@ -32,7 +32,7 @@ defmodule ElixirScript.Translator.Protocol.Test do })) }); Elixir.Core.Functions.defimpl(Elixir$Blank, Array,{ - blank__qmark__: Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Core.SpecialForms.list()],function() { + blank__qmark__: Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Object.freeze([])],function() { return true; }),Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.wildcard()],function() { return false; diff --git a/test/translator/quote_test.exs b/test/translator/quote_test.exs index 79018a1f..21ee5107 100644 --- a/test/translator/quote_test.exs +++ b/test/translator/quote_test.exs @@ -39,7 +39,7 @@ defmodule ElixirScript.Translator.Quote.Test do quote do: {1, 2, 3} end - js_code = "new Elixir.Core.Tuple(Symbol.for('{}'), Elixir.Core.SpecialForms.list(), Elixir.Core.SpecialForms.list(1, 2, 3))" + js_code = "new Elixir.Core.Tuple(Symbol.for('{}'), Object.freeze([]), Object.freeze([1, 2, 3]))" assert_translation(ex_ast, js_code) end @@ -50,9 +50,12 @@ defmodule ElixirScript.Translator.Quote.Test do quote do: test(1) end - js_code = "new Elixir.Core.Tuple(Symbol.for('test'), - Elixir.Core.SpecialForms.list(new Elixir.Core.Tuple(Symbol.for('context'),Symbol.for('Elixir.ElixirScript.Translator.Quote.Test')),new Elixir.Core.Tuple(Symbol.for('import'),Symbol.for('Elixir.ExUnit.Case'))), - Elixir.Core.SpecialForms.list(1))" + js_code = """ + new Elixir.Core.Tuple( + Symbol.for('test'), + Object.freeze([new Elixir.Core.Tuple(Symbol.for('context'),Symbol.for('Elixir.ElixirScript.Translator.Quote.Test')), new Elixir.Core.Tuple(Symbol.for('import'),Symbol.for('Elixir.ExUnit.Case'))]),Object.freeze([1]) + ) + """ assert_translation(ex_ast, js_code) end @@ -63,11 +66,11 @@ defmodule ElixirScript.Translator.Quote.Test do quote do: test(x) end - js_code = "new Elixir.Core.Tuple( + js_code = """ + new Elixir.Core.Tuple( Symbol.for('test'), - Elixir.Core.SpecialForms.list(new Elixir.Core.Tuple(Symbol.for('context'),Symbol.for('Elixir.ElixirScript.Translator.Quote.Test')),new Elixir.Core.Tuple(Symbol.for('import'),Symbol.for('Elixir.ExUnit.Case'))), - Elixir.Core.SpecialForms.list(new Elixir.Core.Tuple(Symbol.for('x'),Elixir.Core.SpecialForms.list(),Symbol.for('Elixir.ElixirScript.Translator.Quote.Test'))) - )" + Object.freeze([new Elixir.Core.Tuple(Symbol.for('context'), Symbol.for('Elixir.ElixirScript.Translator.Quote.Test')), new Elixir.Core.Tuple(Symbol.for('import'),Symbol.for('Elixir.ExUnit.Case'))]),Object.freeze([new Elixir.Core.Tuple(Symbol.for('x'),Object.freeze([]),Symbol.for('Elixir.ElixirScript.Translator.Quote.Test'))])) + """ assert_translation(ex_ast, js_code) end @@ -78,11 +81,12 @@ defmodule ElixirScript.Translator.Quote.Test do quote do: test(unquote(x)) end - js_code = "new Elixir.Core.Tuple( + js_code = """ + new Elixir.Core.Tuple( Symbol.for('test'), - Elixir.Core.SpecialForms.list(new Elixir.Core.Tuple(Symbol.for('context'),Symbol.for('Elixir.ElixirScript.Translator.Quote.Test')),new Elixir.Core.Tuple(Symbol.for('import'),Symbol.for('Elixir.ExUnit.Case'))), - Elixir.Core.SpecialForms.list(x) - )" + Object.freeze([new Elixir.Core.Tuple(Symbol.for('context'),Symbol.for('Elixir.ElixirScript.Translator.Quote.Test')), new Elixir.Core.Tuple(Symbol.for('import'),Symbol.for('Elixir.ExUnit.Case'))]),Object.freeze([x]) + ) + """ assert_translation(ex_ast, js_code) end @@ -93,7 +97,9 @@ defmodule ElixirScript.Translator.Quote.Test do quote do: sum(1, unquote_splicing(values), 5) end - js_code = "new Elixir.Core.Tuple(Symbol.for('sum'), Elixir.Core.SpecialForms.list(), Elixir.Enum.concat(Elixir.Core.SpecialForms.list(1), values, Elixir.Core.SpecialForms.list(5)))" + js_code = """ + new Elixir.Core.Tuple(Symbol.for('sum'),Object.freeze([]),Elixir.Enum.concat(Object.freeze([1]),values,Object.freeze([5]))) + """ assert_translation(ex_ast, js_code) end @@ -105,11 +111,12 @@ defmodule ElixirScript.Translator.Quote.Test do end end - js_code = "new Elixir.Core.Tuple( + js_code = """ + new Elixir.Core.Tuple( Symbol.for('*'), - Elixir.Core.SpecialForms.list(new Elixir.Core.Tuple(Symbol.for('context'),Symbol.for('Elixir.ElixirScript.Translator.Quote.Test')),new Elixir.Core.Tuple(Symbol.for('import'),Symbol.for('Elixir.ElixirScript.Kernel'))), - Elixir.Core.SpecialForms.list(x, x) - )" + Object.freeze([new Elixir.Core.Tuple(Symbol.for('context'), Symbol.for('Elixir.ElixirScript.Translator.Quote.Test')), new Elixir.Core.Tuple(Symbol.for('import'),Symbol.for('Elixir.ElixirScript.Kernel'))]),Object.freeze([x, x]) + ) + """ assert_translation(ex_ast, js_code) end diff --git a/test/translator/string_test.exs b/test/translator/string_test.exs index ade3e814..5d1318ef 100644 --- a/test/translator/string_test.exs +++ b/test/translator/string_test.exs @@ -25,19 +25,19 @@ defmodule ElixirScript.Translator.String.Test do assert_translation(ex_ast, "'Hello ' + 'world'") ex_ast = quote do: "Hello #{length([])}" - assert_translation(ex_ast, "'Hello ' + Elixir$ElixirScript$String$Chars.to_string(Elixir$ElixirScript$Kernel.length(Elixir.Core.SpecialForms.list()))") + assert_translation(ex_ast, "'Hello ' + Elixir$ElixirScript$String$Chars.to_string(Elixir$ElixirScript$Kernel.length(Object.freeze([])))") end test "translate multiline string interpolation" do ex_ast = quote do: """ Hello #{length([])} """ - assert_translation(ex_ast, "'Hello ' + (Elixir$ElixirScript$String$Chars.to_string(Elixir$ElixirScript$Kernel.length(Elixir.Core.SpecialForms.list())) + '\\n')") + assert_translation(ex_ast, "'Hello ' + (Elixir$ElixirScript$String$Chars.to_string(Elixir$ElixirScript$Kernel.length(Object.freeze([]))) + '\\n')") ex_ast = quote do: """ Hello #{length([])} How are you, #{length([])}? """ - assert_translation(ex_ast, "'Hello ' + (Elixir$ElixirScript$String$Chars.to_string(Elixir$ElixirScript$Kernel.length(Elixir.Core.SpecialForms.list())) + ('\\nHow are you, ' + (Elixir$ElixirScript$String$Chars.to_string(Elixir$ElixirScript$Kernel.length(Elixir.Core.SpecialForms.list())) + '?\\n')))") + assert_translation(ex_ast, "'Hello ' + (Elixir$ElixirScript$String$Chars.to_string(Elixir$ElixirScript$Kernel.length(Object.freeze([]))) + ('\\nHow are you, ' + (Elixir$ElixirScript$String$Chars.to_string(Elixir$ElixirScript$Kernel.length(Object.freeze([]))) + '?\\n')))") end end diff --git a/test/translator/struct_test.exs b/test/translator/struct_test.exs index f844dcbe..88d94801 100644 --- a/test/translator/struct_test.exs +++ b/test/translator/struct_test.exs @@ -59,7 +59,7 @@ defmodule ElixirScript.Translator.Struct.Test do end js_code = """ - let [user] = Elixir.Core.Patterns.match(Elixir.Core.Patterns.variable(), Elixir$User.Elixir$User.create(Elixir.Core.SpecialForms.map({}))); + let [user] = Elixir.Core.Patterns.match(Elixir.Core.Patterns.variable(), Elixir$User.Elixir$User.create(Object.freeze({}))); import * as Elixir$ElixirScript$Kernel from './Elixir.ElixirScript.Kernel'; const Elixir$User = Elixir.Core.Functions.defstruct({ @@ -84,7 +84,7 @@ defmodule ElixirScript.Translator.Struct.Test do end js_code = """ - let [user] = Elixir.Core.Patterns.match(Elixir.Core.Patterns.variable(),Elixir$User.Elixir$User.create(Elixir.Core.SpecialForms.map({ + let [user] = Elixir.Core.Patterns.match(Elixir.Core.Patterns.variable(),Elixir$User.Elixir$User.create(Object.freeze({ [Symbol.for('name')]: 'John' }))); @@ -108,9 +108,9 @@ defmodule ElixirScript.Translator.Struct.Test do end js_code = """ - let [user] = Elixir.Core.Patterns.match(Elixir.Core.Patterns.variable(),Elixir.Core.SpecialForms.map_update(map,{ + let [user] = Elixir.Core.Patterns.match(Elixir.Core.Patterns.variable(),Elixir.Core.SpecialForms.map_update(map,Object.freeze({ [Symbol.for('key')]: value - })); + }))); """ assert_translation(ex_ast, js_code) @@ -183,7 +183,7 @@ defmodule ElixirScript.Translator.Struct.Test do end js_code = """ - throw Elixir$MyAppError.Elixir$MyAppError.create(Elixir.Core.SpecialForms.map({ + throw Elixir$MyAppError.Elixir$MyAppError.create(Object.freeze({ [Symbol.for('message')]: 'did not get what was expected' })); diff --git a/test/translator/try_test.exs b/test/translator/try_test.exs index e8573167..7be94ed7 100644 --- a/test/translator/try_test.exs +++ b/test/translator/try_test.exs @@ -55,13 +55,13 @@ defmodule ElixirScript.Translator.Try.Test do end js_code = """ - Elixir.Core.SpecialForms._try(function() { - return do_something_that_may_fail(some_arg); - }, Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable()], function(x) { - return IO.puts('Invalid argument given'); - }, function(x) { - return Elixir.Core.Functions.contains(x,Elixir.Core.SpecialForms.list(ArgumentError.create(Elixir.Core.SpecialForms.map({})))); - })), null, null, null) + Elixir.Core.SpecialForms._try(function() { + return do_something_that_may_fail(some_arg); + },Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable()],function(x) { + return IO.puts('Invalid argument given'); + },function(x) { + return Elixir.Core.Functions.contains(x,Object.freeze([ArgumentError.create(Object.freeze({}))])); + })),null,null,null) """ assert_translation(ex_ast, js_code) From 30d6cb077c86b29f12106ffd6562f1084a57954d Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Mon, 4 Jan 2016 19:26:43 -0600 Subject: [PATCH 112/860] Added JS.global, JS.typeof, and JS.instanceof. Added translate function head to turn Enum references to Elixir.Enum --- lib/elixir_script/prelude/agent.ex | 22 ++++++++++----------- lib/elixir_script/prelude/js.ex | 16 +++++++++++++++ lib/elixir_script/prelude/kernel.ex | 30 +++++++++-------------------- lib/elixir_script/prelude/view.ex | 16 +++++++-------- lib/elixir_script/translator.ex | 5 ++++- lib/elixir_script/translator/js.ex | 18 +++++++++++++++++ mix.exs | 4 ++-- mix.lock | 6 +++--- test/translator/struct_test.exs | 6 +++--- 9 files changed, 74 insertions(+), 49 deletions(-) diff --git a/lib/elixir_script/prelude/agent.ex b/lib/elixir_script/prelude/agent.ex index 096eb678..6e212eb4 100644 --- a/lib/elixir_script/prelude/agent.ex +++ b/lib/elixir_script/prelude/agent.ex @@ -1,42 +1,42 @@ defmodule ElixirScript.Agent do def start(fun) do - pid = Elixir.Core.Functions.get_global().processes.spawn() - Elixir.Core.Functions.get_global().processes.put(pid, "state", fun.()); + pid = JS.global().processes.spawn() + JS.global().processes.put(pid, "state", fun.()); { :ok, pid } end def start(fun, options) do - pid = Elixir.Core.Functions.get_global().processes.spawn() + pid = JS.global().processes.spawn() if Elixir.Keyword.has_key?(options, :name) do - pid = Elixir.Core.Functions.get_global().processes.register(Elixir.Keyword.get(options, :name), pid) + pid = JS.global().processes.register(Elixir.Keyword.get(options, :name), pid) end - Elixir.Core.Functions.get_global().processes.put(pid, "state", fun.()) + JS.global().processes.put(pid, "state", fun.()) { :ok, pid } end def stop(view) do - Elixir.Core.Functions.get_global().processes.exit(view) + JS.global().processes.exit(view) :ok end def update(agent, fun) do - current_state = Elixir.Core.Functions.get_global().processes.get(agent, "state") - Elixir.Core.Functions.get_global().processes.put(agent, "state", fun.(current_state)); + current_state = JS.global().processes.get(agent, "state") + JS.global().processes.put(agent, "state", fun.(current_state)); :ok end def get(agent, fun) do - current_state = Elixir.Core.Functions.get_global().processes.get(agent, "state") + current_state = JS.global().processes.get(agent, "state") fun.(current_state) end def get_and_update(agent, fun) do - current_state = Elixir.Core.Functions.get_global().processes.get(agent, "state") + current_state = JS.global().processes.get(agent, "state") {val, new_state} = fun.(current_state) - Elixir.Core.Functions.get_global().processes.put(agent, "state", new_state); + JS.global().processes.put(agent, "state", new_state); val end diff --git a/lib/elixir_script/prelude/js.ex b/lib/elixir_script/prelude/js.ex index b59d256a..034a9577 100644 --- a/lib/elixir_script/prelude/js.ex +++ b/lib/elixir_script/prelude/js.ex @@ -51,4 +51,20 @@ defmodule ElixirScript.JS do defmacro import(module) do end + + @doc """ + Returns a reference to the global object. + + In browsers this would be Window or WindowProxy. + In node this would be the global object. + """ + def global() do + Elixir.Core.Functions.get_global() + end + + + defmacro type_of(type) do + end + + end diff --git a/lib/elixir_script/prelude/kernel.ex b/lib/elixir_script/prelude/kernel.ex index 8b20a77f..bf3b2453 100644 --- a/lib/elixir_script/prelude/kernel.ex +++ b/lib/elixir_script/prelude/kernel.ex @@ -60,32 +60,20 @@ defmodule ElixirScript.Kernel do list.slice(1) end - def get_type(term) do - Elixir.Core.Functions.get_type(term) - end - - def is_instance_of(term, type) do - Elixir.Core.Functions.is_instance_of(term, type) - end - - def global() do - Elixir.Core.Functions.get_global() - end - def is_atom(term) do - get_type(term) === 'symbol' + JS.typeof(term) === "symbol" end def is_binary(term) do - get_type(term) === 'string' + JS.typeof(term) === "string" end def is_bitstring(term) do - is_binary(term) || is_instance_of(term, Elixir.Core.BitString) + is_binary(term) || JS.instanceof(term, Elixir.Core.BitString) end def is_boolean(term) do - get_type(term) === 'boolean' || is_instance_of(term, Boolean) + JS.typeof(term) === "boolean" || JS.instanceof(term, Boolean) end def is_float(term) do @@ -97,7 +85,7 @@ defmodule ElixirScript.Kernel do end def is_function(term, _) do - get_type(term) === 'function' || is_instance_of(term, Function) + JS.typeof(term) === "function" || JS.instanceof(term, Function) end def is_integer(term) do @@ -109,19 +97,19 @@ defmodule ElixirScript.Kernel do end def is_number(term) do - get_type(term) === 'number' || is_instance_of(term, Number) + JS.typeof(term) === "number" || JS.instanceof(term, Number) end def is_pid(term) do - is_instance_of(term, Elixir.Core.PID) + JS.instanceof(term, Elixir.Core.PID) end def is_tuple(term) do - is_instance_of(term, Elixir.Core.Tuple) + JS.instanceof(term, Elixir.Core.Tuple) end def is_map(term) do - get_type(term) === 'object' || is_instance_of(term, Object) + JS.typeof(term) === "object" || JS.instanceof(term, Object) end def is_port(_) do diff --git a/lib/elixir_script/prelude/view.ex b/lib/elixir_script/prelude/view.ex index df05796c..667bae0b 100644 --- a/lib/elixir_script/prelude/view.ex +++ b/lib/elixir_script/prelude/view.ex @@ -24,22 +24,22 @@ defmodule ElixirScript.View do render_func and the args """ def start(dom_root, render_func, args) do - pid = Elixir.Core.Functions.get_global().processes.spawn() + pid = JS.global().processes.spawn() tree = render_func.apply(nil, args); root_node = Elixir.VirtualDOM.create(tree); dom_root.appendChild(root_node); - Elixir.Core.Functions.get_global().processes.put(pid, "state", { root_node, tree, render_func }); + JS.global().processes.put(pid, "state", { root_node, tree, render_func }); { :ok, pid } end def start(dom_root, render_func, args, options) do - pid = Elixir.Core.Functions.get_global().processes.spawn() + pid = JS.global().processes.spawn() if Elixir.Keyword.has_key?(options, :name) do - pid = Elixir.Core.Functions.get_global().processes.register(Elixir.Keyword.get(options, :name), pid) + pid = JS.global().processes.register(Elixir.Keyword.get(options, :name), pid) end tree = render_func.apply(nil, args); @@ -47,7 +47,7 @@ defmodule ElixirScript.View do dom_root.appendChild(root_node); - Elixir.Core.Functions.get_global().processes.put(pid, "state", { root_node, tree, render_func }) + JS.global().processes.put(pid, "state", { root_node, tree, render_func }) { :ok, pid } end @@ -55,7 +55,7 @@ defmodule ElixirScript.View do Stops the View state """ def stop(view) do - Elixir.Core.Functions.get_global().processes.exit(view) + JS.global().processes.exit(view) :ok end @@ -63,14 +63,14 @@ defmodule ElixirScript.View do Updates the view by passing the args to the render_func """ def render(view, args) do - { root_node, tree, render_func } = Elixir.Core.Functions.get_global().processes.get(view, "state") + { root_node, tree, render_func } = JS.global().processes.get(view, "state") new_tree = render_func.apply(nil, args); patches = Elixir.VirtualDOM.diff(tree, new_tree) root_node = Elixir.VirtualDOM.patch(root_node, patches) - Elixir.Core.Functions.get_global().processes.put(view, "state", { root_node, new_tree, render_func }); + JS.global().processes.put(view, "state", { root_node, new_tree, render_func }); :ok end diff --git a/lib/elixir_script/translator.ex b/lib/elixir_script/translator.ex index f645d403..6bd4c16c 100644 --- a/lib/elixir_script/translator.ex +++ b/lib/elixir_script/translator.ex @@ -218,11 +218,14 @@ defmodule ElixirScript.Translator do end end + defp do_translate({{:., context1, [{:__aliases__, context2, [:Enum]}, function_name]}, context3, params }, env) do + translate({{:., context1, [{:__aliases__, context2, [:Elixir, :Enum]}, function_name]}, context3, params }, env) + end + defp do_translate({{:., _, [{:__aliases__, _, [:JS]}, function_name]}, _, params }, env) do JSLib.translate_js_function(function_name, params, env) end - defp do_translate({{:., _, [module_name, function_name]}, _, params } = ast, env) do expanded_ast = Macro.expand(ast, ElixirScript.Translator.State.get().compiler_opts.env) diff --git a/lib/elixir_script/translator/js.ex b/lib/elixir_script/translator/js.ex index 23b2b804..bcde40a7 100644 --- a/lib/elixir_script/translator/js.ex +++ b/lib/elixir_script/translator/js.ex @@ -9,6 +9,24 @@ defmodule ElixirScript.Translator.JS do { do_translate({name, [], params}, env), env } end + defp do_translate({:typeof, _, [param]}, env) do + Builder.unary_expression( + :typeof, + true, + Translator.translate!(param, env) + ) + end + + + defp do_translate({:instanceof, _, [value, type]}, env) do + Builder.binary_expression( + :instanceof, + Translator.translate!(value, env), + Translator.translate!(type, env) + ) + end + + defp do_translate({:new, _, [module_name, params]}, env) when not is_list(params) do Builder.new_expression( Translator.translate!(module_name, env), diff --git a/mix.exs b/mix.exs index c7f2e513..9e5ac309 100644 --- a/mix.exs +++ b/mix.exs @@ -29,8 +29,8 @@ defmodule ElixirScript.Mixfile do defp deps do [ {:estree, "~> 2.0"}, - {:earmark, "~> 0.1", only: :dev }, - {:ex_doc, "~> 0.10", only: :dev }, + {:earmark, "~> 0.2", only: :dev }, + {:ex_doc, "~> 0.11", only: :dev }, {:excoveralls, "~> 0.4", only: :test}, {:credo, "~> 0.2.0", only: [:dev, :test]} ] diff --git a/mix.lock b/mix.lock index 45a322e5..74ef82f2 100644 --- a/mix.lock +++ b/mix.lock @@ -4,12 +4,12 @@ "credo": {:hex, :credo, "0.2.5"}, "dogma": {:hex, :dogma, "0.0.7"}, "earmark": {:hex, :earmark, "0.2.0"}, - "estree": {:hex, :estree, "2.1.1"}, + "estree": {:hex, :estree, "2.1.2"}, "ex_doc": {:hex, :ex_doc, "0.11.3"}, "excoveralls": {:hex, :excoveralls, "0.4.3"}, "exjsx": {:hex, :exjsx, "3.2.0"}, - "hackney": {:hex, :hackney, "1.4.7"}, - "idna": {:hex, :idna, "1.0.2"}, + "hackney": {:hex, :hackney, "1.4.8"}, + "idna": {:hex, :idna, "1.0.3"}, "inflex": {:hex, :inflex, "1.5.0"}, "jsx": {:hex, :jsx, "2.6.2"}, "mimerl": {:hex, :mimerl, "1.0.2"}, diff --git a/test/translator/struct_test.exs b/test/translator/struct_test.exs index 88d94801..5a798af3 100644 --- a/test/translator/struct_test.exs +++ b/test/translator/struct_test.exs @@ -121,9 +121,9 @@ defmodule ElixirScript.Translator.Struct.Test do end js_code = """ - let [user] = Elixir.Core.Patterns.match(Elixir.Core.Patterns.variable(),Elixir.Core.SpecialForms.map_update(map,{ - [Symbol.for('key')]: value, [Symbol.for('key1')]: value1 - })); + let [user] = Elixir.Core.Patterns.match(Elixir.Core.Patterns.variable(),Elixir.Core.SpecialForms.map_update(map,Object.freeze({ + [Symbol.for('key')]: value, [Symbol.for('key1')]: value1 + }))); """ assert_translation(ex_ast, js_code) From 90d789dcbd998c1fb96aeb54dbb88b4de218cd01 Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Mon, 4 Jan 2016 19:44:09 -0600 Subject: [PATCH 113/860] Removed get_type and is_instance_of from core js module --- lib/elixir_script/prelude/js.ex | 18 +++++++++++++++++- src/javascript/lib/core/functions.js | 8 -------- 2 files changed, 17 insertions(+), 9 deletions(-) diff --git a/lib/elixir_script/prelude/js.ex b/lib/elixir_script/prelude/js.ex index 034a9577..38c84e24 100644 --- a/lib/elixir_script/prelude/js.ex +++ b/lib/elixir_script/prelude/js.ex @@ -1,4 +1,10 @@ defmodule ElixirScript.JS do + @moduledoc """ + This module defines macros and functions which implement + JavaScript functionality that may not translate easily to + Elixir. For instance, creating a new object, or updating + an existing one. + """ @doc """ Creates new JavaScript objects. @@ -63,7 +69,17 @@ defmodule ElixirScript.JS do end - defmacro type_of(type) do + @doc """ + Returns the type of the given value + """ + defmacro typeof(value) do + end + + + @doc """ + Determines if value is an instance of type. + """ + defmacro instanceof(value, type) do end diff --git a/src/javascript/lib/core/functions.js b/src/javascript/lib/core/functions.js index 600961cc..024b4d8c 100644 --- a/src/javascript/lib/core/functions.js +++ b/src/javascript/lib/core/functions.js @@ -23,14 +23,6 @@ function call_property(item, property){ throw new Error(`Property ${property} not found in ${item}`); } -function get_type(x){ - return typeof x; -} - -function is_instance_of(x, type){ - return x instanceof type; -} - function apply(...args){ if(args.length === 2){ args[0].apply(null, args.slice(1)); From 8a38f6cdc4ec329a92db414f2d3c1157552df37f Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Mon, 4 Jan 2016 19:53:49 -0600 Subject: [PATCH 114/860] Added list of javascript reserved words to filter --- lib/elixir_script/translator/utils.ex | 38 +++++++++++++++++++++++++-- 1 file changed, 36 insertions(+), 2 deletions(-) diff --git a/lib/elixir_script/translator/utils.ex b/lib/elixir_script/translator/utils.ex index 683b2267..4a443d0a 100644 --- a/lib/elixir_script/translator/utils.ex +++ b/lib/elixir_script/translator/utils.ex @@ -3,6 +3,40 @@ defmodule ElixirScript.Translator.Utils do alias ESTree.Tools.Builder, as: JS alias ElixirScript.Translator + @js_reserved_words [ + :break, + :case, + :class, + :catch, + :const, + :continue, + :debugger, + :default, + :delete, + :do, + :else, + :export, + :extends, + :finally, + :function, + :if, + :import, + :in, + :instanceof, + :new, + :return, + :super, + :switch, + :throw, + :try, + :typeof, + :var, + :void, + :while, + :with, + :yield + ] + def inflate_groups(body) do Enum.map(body, fn(x) -> case x do @@ -107,8 +141,8 @@ defmodule ElixirScript.Translator.Utils do end end - def filter_name(:new) do - "__new__" + def filter_name(reserved_word) when reserved_word in @js_reserved_words do + "__#{Atom.to_string(reserved_word)}__" end def filter_name(name) do From ee4f6520f1ee822cf32b532e0d82ffe5e286fa0b Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Tue, 5 Jan 2016 21:08:10 -0600 Subject: [PATCH 115/860] Refactoring of call_property function --- lib/elixir_script/prelude/js.ex | 23 ++++++++++------------- src/javascript/lib/core/functions.js | 25 +++++++++++-------------- 2 files changed, 21 insertions(+), 27 deletions(-) diff --git a/lib/elixir_script/prelude/js.ex b/lib/elixir_script/prelude/js.ex index 38c84e24..b961542e 100644 --- a/lib/elixir_script/prelude/js.ex +++ b/lib/elixir_script/prelude/js.ex @@ -57,25 +57,12 @@ defmodule ElixirScript.JS do defmacro import(module) do end - - @doc """ - Returns a reference to the global object. - - In browsers this would be Window or WindowProxy. - In node this would be the global object. - """ - def global() do - Elixir.Core.Functions.get_global() - end - - @doc """ Returns the type of the given value """ defmacro typeof(value) do end - @doc """ Determines if value is an instance of type. """ @@ -83,4 +70,14 @@ defmodule ElixirScript.JS do end + @doc """ + Returns a reference to the global object. + + In browsers this would be Window or WindowProxy. + In node this would be the global object. + """ + def global() do + Elixir.Core.Functions.get_global() + end + end diff --git a/src/javascript/lib/core/functions.js b/src/javascript/lib/core/functions.js index 024b4d8c..abe03fb0 100644 --- a/src/javascript/lib/core/functions.js +++ b/src/javascript/lib/core/functions.js @@ -3,24 +3,21 @@ import BitString from './bit_string'; import Patterns from './patterns'; function call_property(item, property){ - if(property in item){ - item[property]; - if(item[property] instanceof Function){ - return item[property](); - }else{ - return item[property]; - } + let prop = null; + if(property in item){ + prop = property }else if(Symbol.for(property) in item){ - let prop = Symbol.for(property) - if(item[prop] instanceof Function){ - return item[prop](); - }else{ - return item[prop]; - } + prop = Symbol.for(property); + }else{ + throw new Error(`Property ${property} not found in ${item}`); } - throw new Error(`Property ${property} not found in ${item}`); + if(item[prop] instanceof Function){ + return item[prop](); + }else{ + return item[prop]; + } } function apply(...args){ From da359cd563f67eaede903c9c54a981d89c18c5a8 Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Tue, 5 Jan 2016 21:38:05 -0600 Subject: [PATCH 116/860] Fixed broken javascript tests. Added specs for translate functions. --- lib/elixir_script/prelude/macro/env.ex | 18 +++++++++++++++ lib/elixir_script/translator.ex | 12 ++++++++-- priv/Elixir.js | 26 ++++++++++------------ src/javascript/lib/core/functions.js | 2 +- src/javascript/tests/bit_string.spec.js | 11 +++++---- src/javascript/tests/case.spec.js | 3 ++- src/javascript/tests/special_forms.spec.js | 2 +- 7 files changed, 49 insertions(+), 25 deletions(-) diff --git a/lib/elixir_script/prelude/macro/env.ex b/lib/elixir_script/prelude/macro/env.ex index d415657f..f634409d 100644 --- a/lib/elixir_script/prelude/macro/env.ex +++ b/lib/elixir_script/prelude/macro/env.ex @@ -1,4 +1,22 @@ defmodule ElixirScript.Macro.Env do + @type t :: %ElixirScript.Macro.Env{ + module: atom, + file: binary, + line: non_neg_integer, + function: { atom, non_neg_integer } | nil, + context: :match | :guard | nil, + aliases: [{atom, atom}], + requires: [atom], + functions: [{atom, [{ atom, non_neg_integer }]}], + macros: [{atom, [{ atom, non_neg_integer }]}], + macro_aliases: [{atom, {integer, atom}}], + context_modules: [atom], + vars: [{atom, atom | non_neg_integer}], + export_vars: [{atom, atom | non_neg_integer}] | nil, + lexical_tracker: nil, + caller: t | nil + } + defstruct [ module: nil, file: nil, diff --git a/lib/elixir_script/translator.ex b/lib/elixir_script/translator.ex index 6bd4c16c..e3ade1ce 100644 --- a/lib/elixir_script/translator.ex +++ b/lib/elixir_script/translator.ex @@ -1,6 +1,6 @@ defmodule ElixirScript.Translator do @moduledoc """ - Translates the given Elixir AST into JavaScript AST + Translates Elixir AST into JavaScript AST """ alias ElixirScript.Translator.Primitive alias ElixirScript.Translator.Expression @@ -25,12 +25,20 @@ defmodule ElixirScript.Translator do @doc """ - Translates Elixir AST to JavaScript AST + Translates the given Elixir AST to JavaScript AST. The given `env` is a `ElixirScript.Macro.Env` + used to track the variables, imports, aliases, and scopes like `Macro.Env`. The JavaScript AST and + the an updated `ElixirScript.Macro.Env` is returned """ + @spec translate(term, ElixirScript.Macro.Env.t) :: { ESTree.Node.t, ElixirScript.Macro.Env.t } def translate(ast, env) do do_translate(ast, env) end + + @doc """ + Same as `translate/2`, but returns only the JavaScript AST + """ + @spec translate!(term, ElixirScript.Macro.Env.t) :: ESTree.Node.t def translate!(ast, env) do { js_ast, _ } = translate(ast, env) js_ast diff --git a/priv/Elixir.js b/priv/Elixir.js index b9000b49..5e0e0c26 100644 --- a/priv/Elixir.js +++ b/priv/Elixir.js @@ -1010,23 +1010,21 @@ var Patterns = { }; function call_property(item, property) { + let prop = null; + if (property in item) { - item[property]; - if (item[property] instanceof Function) { - return item[property](); - } else { - return item[property]; - } + prop = property; } else if (Symbol.for(property) in item) { - let prop = Symbol.for(property); - if (item[prop] instanceof Function) { - return item[prop](); - } else { - return item[prop]; - } + prop = Symbol.for(property); + } else { + throw new Error(`Property ${ property } not found in ${ item }`); } - throw new Error(`Property ${ property } not found in ${ item }`); + if (item[prop] instanceof Function) { + return item[prop](); + } else { + return item[prop]; + } } function apply(...args) { @@ -3158,4 +3156,4 @@ let VirtualDOM = (function (e) { const Core = C; export { Core, Enum, VirtualDOM }; -//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiIiwic291cmNlcyI6WyJFbGl4aXIuanMiXSwic291cmNlc0NvbnRlbnQiOlsiLyogQGZsb3cgKi9cblxuY2xhc3MgTWFpbGJveCB7XG5cbiAgY29uc3RydWN0b3IoKSB7XG4gICAgdGhpcy5tZXNzYWdlcyA9IFtdO1xuICB9XG5cbiAgZGVsaXZlcihtZXNzYWdlKSB7XG4gICAgdGhpcy5tZXNzYWdlcy5wdXNoKG1lc3NhZ2UpO1xuICAgIHJldHVybiBtZXNzYWdlO1xuICB9XG5cbiAgZ2V0KCkge1xuICAgIHJldHVybiB0aGlzLm1lc3NhZ2VzO1xuICB9XG5cbiAgaXNFbXB0eSgpIHtcbiAgICByZXR1cm4gdGhpcy5tZXNzYWdlcy5sZW5ndGggPT09IDA7XG4gIH1cblxuICByZW1vdmVBdChpbmRleCkge1xuICAgIHRoaXMubWVzc2FnZXMuc3BsaWNlKGluZGV4LCAxKTtcbiAgfVxufVxuXG52YXIgU3RhdGVzID0ge1xuICBOT1JNQUw6IFN5bWJvbC5mb3IoXCJub3JtYWxcIiksXG4gIEtJTEw6IFN5bWJvbC5mb3IoXCJraWxsXCIpLFxuICBTVVNQRU5EOiBTeW1ib2wuZm9yKFwic3VzcGVuZFwiKSxcbiAgQ09OVElOVUU6IFN5bWJvbC5mb3IoXCJjb250aW51ZVwiKSxcbiAgUkVDRUlWRTogU3ltYm9sLmZvcihcInJlY2VpdmVcIiksXG4gIFNFTkQ6IFN5bWJvbC5mb3IoXCJzZW5kXCIpLFxuICBTTEVFUElORzogU3ltYm9sLmZvcihcInNsZWVwaW5nXCIpLFxuICBSVU5OSU5HOiBTeW1ib2wuZm9yKFwicnVubmluZ1wiKSxcbiAgU1VTUEVOREVEOiBTeW1ib2wuZm9yKFwic3VzcGVuZGVkXCIpLFxuICBTVE9QUEVEOiBTeW1ib2wuZm9yKFwic3RvcHBlZFwiKSxcbiAgU0xFRVA6IFN5bWJvbC5mb3IoXCJzbGVlcFwiKSxcbiAgRVhJVDogU3ltYm9sLmZvcihcImV4aXRcIiksXG4gIE5PTUFUQ0g6IFN5bWJvbC5mb3IoXCJub19tYXRjaFwiKVxufTtcblxuY2xhc3MgUHJvY2VzcyB7XG5cbiAgY29uc3RydWN0b3IocGlkLCBtYWlsYm94KSB7XG4gICAgdGhpcy5waWQgPSBwaWQ7XG4gICAgdGhpcy5tYWlsYm94ID0gbWFpbGJveDtcbiAgICB0aGlzLnN0YXR1cyA9IFN0YXRlcy5TVE9QUEVEO1xuICAgIHRoaXMuZGljdCA9IHt9O1xuICB9XG59XG5cbmNsYXNzIFR1cGxlIHtcblxuICBjb25zdHJ1Y3RvciguLi5hcmdzKSB7XG4gICAgdGhpcy52YWx1ZXMgPSBPYmplY3QuZnJlZXplKGFyZ3MpO1xuICAgIHRoaXMubGVuZ3RoID0gdGhpcy52YWx1ZXMubGVuZ3RoO1xuICB9XG5cbiAgZ2V0KGluZGV4KSB7XG4gICAgcmV0dXJuIHRoaXMudmFsdWVzW2luZGV4XTtcbiAgfVxuXG4gIGNvdW50KCkge1xuICAgIHJldHVybiB0aGlzLnZhbHVlcy5sZW5ndGg7XG4gIH1cblxuICBbU3ltYm9sLml0ZXJhdG9yXSgpIHtcbiAgICByZXR1cm4gdGhpcy52YWx1ZXNbU3ltYm9sLml0ZXJhdG9yXSgpO1xuICB9XG5cbiAgdG9TdHJpbmcoKSB7XG4gICAgdmFyIGksXG4gICAgICAgIHMgPSBcIlwiO1xuICAgIGZvciAoaSA9IDA7IGkgPCB0aGlzLnZhbHVlcy5sZW5ndGg7IGkrKykge1xuICAgICAgaWYgKHMgIT09IFwiXCIpIHtcbiAgICAgICAgcyArPSBcIiwgXCI7XG4gICAgICB9XG4gICAgICBzICs9IHRoaXMudmFsdWVzW2ldLnRvU3RyaW5nKCk7XG4gICAgfVxuXG4gICAgcmV0dXJuIFwie1wiICsgcyArIFwifVwiO1xuICB9XG5cbn1cblxubGV0IHByb2Nlc3NfY291bnRlciA9IC0xO1xuXG5jbGFzcyBQSUQge1xuICBjb25zdHJ1Y3RvcigpIHtcbiAgICBwcm9jZXNzX2NvdW50ZXIgPSBwcm9jZXNzX2NvdW50ZXIgKyAxO1xuICAgIHRoaXMuaWQgPSBwcm9jZXNzX2NvdW50ZXI7XG4gIH1cblxuICB0b1N0cmluZygpIHtcbiAgICByZXR1cm4gXCJQSUQjPDAuXCIgKyB0aGlzLmlkICsgXCIuMD5cIjtcbiAgfVxufVxuXG5jbGFzcyBJbnRlZ2VyIHt9XG5jbGFzcyBGbG9hdCB7fVxuXG5jbGFzcyBQcm9jZXNzU3lzdGVtIHtcblxuICBjb25zdHJ1Y3RvcigpIHtcbiAgICB0aGlzLnBpZHMgPSBuZXcgTWFwKCk7XG4gICAgdGhpcy5tYWlsYm94ZXMgPSBuZXcgTWFwKCk7XG4gICAgdGhpcy5uYW1lcyA9IG5ldyBNYXAoKTtcbiAgICB0aGlzLmxpbmtzID0gbmV3IE1hcCgpO1xuXG4gICAgdGhpcy5jdXJyZW50X3Byb2Nlc3MgPSBudWxsO1xuICAgIHRoaXMuc3VzcGVuZGVkID0gbmV3IE1hcCgpO1xuXG4gICAgdGhpcy5tYWluX3Byb2Nlc3NfcGlkID0gdGhpcy5zcGF3bigpO1xuICAgIHRoaXMuc2V0X2N1cnJlbnQodGhpcy5tYWluX3Byb2Nlc3NfcGlkKTtcbiAgfVxuXG4gIHNwYXduKCkge1xuICAgIHJldHVybiB0aGlzLmFkZF9wcm9jKGZhbHNlKS5waWQ7XG4gIH1cblxuICBzcGF3bl9saW5rKCkge1xuICAgIHJldHVybiB0aGlzLmFkZF9wcm9jKHRydWUpLnBpZDtcbiAgfVxuXG4gIGxpbmsocGlkKSB7XG4gICAgdGhpcy5saW5rcy5nZXQodGhpcy5waWQoKSkuYWRkKHBpZCk7XG4gICAgdGhpcy5saW5rcy5nZXQocGlkKS5hZGQodGhpcy5waWQoKSk7XG4gIH1cblxuICB1bmxpbmsocGlkKSB7XG4gICAgdGhpcy5saW5rcy5nZXQodGhpcy5waWQoKSkuZGVsZXRlKHBpZCk7XG4gICAgdGhpcy5saW5rcy5nZXQocGlkKS5kZWxldGUodGhpcy5waWQoKSk7XG4gIH1cblxuICBzZXRfY3VycmVudChpZCkge1xuICAgIGxldCBwaWQgPSB0aGlzLnBpZG9mKGlkKTtcbiAgICBpZiAocGlkICE9PSBudWxsKSB7XG4gICAgICB0aGlzLmN1cnJlbnRfcHJvY2VzcyA9IHRoaXMucGlkcy5nZXQocGlkKTtcbiAgICAgIHRoaXMuY3VycmVudF9wcm9jZXNzLnN0YXR1cyA9IFN0YXRlcy5SVU5OSU5HO1xuICAgIH1cbiAgfVxuXG4gIGFkZF9wcm9jKGxpbmtlZCkge1xuICAgIGxldCBuZXdwaWQgPSBuZXcgUElEKCk7XG4gICAgbGV0IG1haWxib3ggPSBuZXcgTWFpbGJveCgpO1xuICAgIGxldCBuZXdwcm9jID0gbmV3IFByb2Nlc3MobmV3cGlkLCBtYWlsYm94KTtcblxuICAgIHRoaXMucGlkcy5zZXQobmV3cGlkLCBuZXdwcm9jKTtcbiAgICB0aGlzLm1haWxib3hlcy5zZXQobmV3cGlkLCBtYWlsYm94KTtcbiAgICB0aGlzLmxpbmtzLnNldChuZXdwaWQsIG5ldyBTZXQoKSk7XG5cbiAgICBpZiAobGlua2VkKSB7XG4gICAgICB0aGlzLmxpbmsobmV3cGlkKTtcbiAgICB9XG5cbiAgICByZXR1cm4gbmV3cHJvYztcbiAgfVxuXG4gIHJlbW92ZV9wcm9jKHBpZCkge1xuICAgIHRoaXMucGlkcy5kZWxldGUocGlkKTtcbiAgICB0aGlzLnVucmVnaXN0ZXIocGlkKTtcblxuICAgIGlmICh0aGlzLmxpbmtzLmhhcyhwaWQpKSB7XG4gICAgICBmb3IgKGxldCBsaW5rcGlkIG9mIHRoaXMubGlua3MuZ2V0KHBpZCkpIHtcbiAgICAgICAgdGhpcy5saW5rcy5nZXQobGlua3BpZCkuZGVsZXRlKHBpZCk7XG4gICAgICB9XG5cbiAgICAgIHRoaXMubGlua3MuZGVsZXRlKHBpZCk7XG4gICAgfVxuICB9XG5cbiAgZXhpdChpZCkge1xuICAgIGxldCBwaWQgPSB0aGlzLnBpZG9mKGlkKTtcbiAgICB0aGlzLnJlbW92ZV9wcm9jKGlkKTtcbiAgfVxuXG4gIHJlZ2lzdGVyKG5hbWUsIHBpZCkge1xuICAgIGlmICghdGhpcy5uYW1lcy5oYXMobmFtZSkpIHtcbiAgICAgIHRoaXMubmFtZXMuc2V0KG5hbWUsIHBpZCk7XG4gICAgICByZXR1cm4gbmFtZTtcbiAgICB9IGVsc2Uge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKFwiTmFtZSBpcyBhbHJlYWR5IHJlZ2lzdGVyZWQgdG8gYW5vdGhlciBwcm9jZXNzXCIpO1xuICAgIH1cbiAgfVxuXG4gIHJlZ2lzdGVyZWQobmFtZSkge1xuICAgIHJldHVybiB0aGlzLm5hbWVzLmhhcyhuYW1lKSA/IHRoaXMubmFtZXMuZ2V0KG5hbWUpIDogbnVsbDtcbiAgfVxuXG4gIHVucmVnaXN0ZXIocGlkKSB7XG4gICAgZm9yIChsZXQgbmFtZSBvZiB0aGlzLm5hbWVzLmtleXMoKSkge1xuICAgICAgaWYgKHRoaXMubmFtZXMuaGFzKG5hbWUpICYmIHRoaXMubmFtZXMuZ2V0KG5hbWUpID09PSBwaWQpIHtcbiAgICAgICAgdGhpcy5uYW1lcy5kZWxldGUobmFtZSk7XG4gICAgICB9XG4gICAgfVxuICB9XG5cbiAgcGlkKCkge1xuICAgIHJldHVybiB0aGlzLmN1cnJlbnRfcHJvY2Vzcy5waWQ7XG4gIH1cblxuICBwaWRvZihpZCkge1xuICAgIGlmIChpZCBpbnN0YW5jZW9mIFBJRCkge1xuICAgICAgcmV0dXJuIHRoaXMucGlkcy5oYXMoaWQpID8gaWQgOiBudWxsO1xuICAgIH0gZWxzZSBpZiAoaWQgaW5zdGFuY2VvZiBQcm9jZXNzKSB7XG4gICAgICByZXR1cm4gaWQucGlkO1xuICAgIH0gZWxzZSB7XG4gICAgICBsZXQgcGlkID0gdGhpcy5yZWdpc3RlcmVkKGlkKTtcbiAgICAgIGlmIChwaWQgPT09IG51bGwpIHRocm93IFwiUHJvY2VzcyBuYW1lIG5vdCByZWdpc3RlcmVkOiBcIiArIGlkICsgXCIgKFwiICsgdHlwZW9mIGlkICsgXCIpXCI7XG4gICAgICByZXR1cm4gcGlkO1xuICAgIH1cbiAgfVxuXG4gIHB1dChpZCwga2V5LCB2YWx1ZSkge1xuICAgIGxldCBwaWQgPSB0aGlzLnBpZG9mKGlkKTtcbiAgICBsZXQgcHJvY2VzcyA9IHRoaXMucGlkcy5nZXQocGlkKTtcbiAgICBwcm9jZXNzLmRpY3Rba2V5XSA9IHZhbHVlO1xuICB9XG5cbiAgZ2V0KGlkLCBrZXkpIHtcbiAgICBsZXQgcGlkID0gdGhpcy5waWRvZihpZCk7XG4gICAgbGV0IHByb2Nlc3MgPSB0aGlzLnBpZHMuZ2V0KHBpZCk7XG5cbiAgICBpZiAoa2V5ICE9IG51bGwpIHtcbiAgICAgIHJldHVybiBwcm9jZXNzLmRpY3Rba2V5XTtcbiAgICB9IGVsc2Uge1xuICAgICAgcmV0dXJuIHByb2Nlc3MuZGljdDtcbiAgICB9XG4gIH1cblxuICBnZXRfa2V5cyhpZCkge1xuICAgIGxldCBwaWQgPSB0aGlzLnBpZG9mKGlkKTtcbiAgICBsZXQgcHJvY2VzcyA9IHRoaXMucGlkcy5nZXQocGlkKTtcblxuICAgIHJldHVybiBPYmplY3Qua2V5cyhwcm9jZXNzLmRpY3QpO1xuICB9XG5cbiAgZXJhc2UoaWQsIGtleSkge1xuICAgIGxldCBwaWQgPSB0aGlzLnBpZG9mKGlkKTtcbiAgICBsZXQgcHJvY2VzcyA9IHRoaXMucGlkcy5nZXQocGlkKTtcblxuICAgIGlmIChrZXkgIT0gbnVsbCkge1xuICAgICAgZGVsZXRlIHByb2Nlc3MuZGljdFtrZXldO1xuICAgIH0gZWxzZSB7XG4gICAgICBwcm9jZXNzLmRpY3QgPSB7fTtcbiAgICB9XG4gIH1cbn1cblxuY2xhc3MgQml0U3RyaW5nIHtcbiAgY29uc3RydWN0b3IoLi4uYXJncykge1xuICAgIHRoaXMucmF3X3ZhbHVlID0gZnVuY3Rpb24gKCkge1xuICAgICAgcmV0dXJuIE9iamVjdC5mcmVlemUoYXJncyk7XG4gICAgfTtcblxuICAgIHRoaXMudmFsdWUgPSBPYmplY3QuZnJlZXplKHRoaXMucHJvY2VzcyhhcmdzKSk7XG4gIH1cblxuICBnZXQoaW5kZXgpIHtcbiAgICByZXR1cm4gdGhpcy52YWx1ZVtpbmRleF07XG4gIH1cblxuICBjb3VudCgpIHtcbiAgICByZXR1cm4gdGhpcy52YWx1ZS5sZW5ndGg7XG4gIH1cblxuICBbU3ltYm9sLml0ZXJhdG9yXSgpIHtcbiAgICByZXR1cm4gdGhpcy52YWx1ZVtTeW1ib2wuaXRlcmF0b3JdKCk7XG4gIH1cblxuICB0b1N0cmluZygpIHtcbiAgICB2YXIgaSxcbiAgICAgICAgcyA9IFwiXCI7XG4gICAgZm9yIChpID0gMDsgaSA8IHRoaXMuY291bnQoKTsgaSsrKSB7XG4gICAgICBpZiAocyAhPT0gXCJcIikge1xuICAgICAgICBzICs9IFwiLCBcIjtcbiAgICAgIH1cbiAgICAgIHMgKz0gdGhpc1tpXS50b1N0cmluZygpO1xuICAgIH1cblxuICAgIHJldHVybiBcIjw8XCIgKyBzICsgXCI+PlwiO1xuICB9XG5cbiAgcHJvY2VzcygpIHtcbiAgICBsZXQgcHJvY2Vzc2VkX3ZhbHVlcyA9IFtdO1xuXG4gICAgdmFyIGk7XG4gICAgZm9yIChpID0gMDsgaSA8IHRoaXMucmF3X3ZhbHVlKCkubGVuZ3RoOyBpKyspIHtcbiAgICAgIGxldCBwcm9jZXNzZWRfdmFsdWUgPSB0aGlzW1wicHJvY2Vzc19cIiArIHRoaXMucmF3X3ZhbHVlKClbaV0udHlwZV0odGhpcy5yYXdfdmFsdWUoKVtpXSk7XG5cbiAgICAgIGZvciAobGV0IGF0dHIgb2YgdGhpcy5yYXdfdmFsdWUoKVtpXS5hdHRyaWJ1dGVzKSB7XG4gICAgICAgIHByb2Nlc3NlZF92YWx1ZSA9IHRoaXNbXCJwcm9jZXNzX1wiICsgYXR0cl0ocHJvY2Vzc2VkX3ZhbHVlKTtcbiAgICAgIH1cblxuICAgICAgcHJvY2Vzc2VkX3ZhbHVlcyA9IHByb2Nlc3NlZF92YWx1ZXMuY29uY2F0KHByb2Nlc3NlZF92YWx1ZSk7XG4gICAgfVxuXG4gICAgcmV0dXJuIHByb2Nlc3NlZF92YWx1ZXM7XG4gIH1cblxuICBwcm9jZXNzX2ludGVnZXIodmFsdWUpIHtcbiAgICByZXR1cm4gdmFsdWUudmFsdWU7XG4gIH1cblxuICBwcm9jZXNzX2Zsb2F0KHZhbHVlKSB7XG4gICAgaWYgKHZhbHVlLnNpemUgPT09IDY0KSB7XG4gICAgICByZXR1cm4gQml0U3RyaW5nLmZsb2F0NjRUb0J5dGVzKHZhbHVlLnZhbHVlKTtcbiAgICB9IGVsc2UgaWYgKHZhbHVlLnNpemUgPT09IDMyKSB7XG4gICAgICByZXR1cm4gQml0U3RyaW5nLmZsb2F0MzJUb0J5dGVzKHZhbHVlLnZhbHVlKTtcbiAgICB9XG5cbiAgICB0aHJvdyBuZXcgRXJyb3IoXCJJbnZhbGlkIHNpemUgZm9yIGZsb2F0XCIpO1xuICB9XG5cbiAgcHJvY2Vzc19iaXRzdHJpbmcodmFsdWUpIHtcbiAgICByZXR1cm4gdmFsdWUudmFsdWUudmFsdWU7XG4gIH1cblxuICBwcm9jZXNzX2JpbmFyeSh2YWx1ZSkge1xuICAgIHJldHVybiBCaXRTdHJpbmcudG9VVEY4QXJyYXkodmFsdWUudmFsdWUpO1xuICB9XG5cbiAgcHJvY2Vzc191dGY4KHZhbHVlKSB7XG4gICAgcmV0dXJuIEJpdFN0cmluZy50b1VURjhBcnJheSh2YWx1ZS52YWx1ZSk7XG4gIH1cblxuICBwcm9jZXNzX3V0ZjE2KHZhbHVlKSB7XG4gICAgcmV0dXJuIEJpdFN0cmluZy50b1VURjE2QXJyYXkodmFsdWUudmFsdWUpO1xuICB9XG5cbiAgcHJvY2Vzc191dGYzMih2YWx1ZSkge1xuICAgIHJldHVybiBCaXRTdHJpbmcudG9VVEYzMkFycmF5KHZhbHVlLnZhbHVlKTtcbiAgfVxuXG4gIHByb2Nlc3Nfc2lnbmVkKHZhbHVlKSB7XG4gICAgcmV0dXJuIG5ldyBVaW50OEFycmF5KFt2YWx1ZV0pWzBdO1xuICB9XG5cbiAgcHJvY2Vzc191bnNpZ25lZCh2YWx1ZSkge1xuICAgIHJldHVybiB2YWx1ZTtcbiAgfVxuXG4gIHByb2Nlc3NfbmF0aXZlKHZhbHVlKSB7XG4gICAgcmV0dXJuIHZhbHVlO1xuICB9XG5cbiAgcHJvY2Vzc19iaWcodmFsdWUpIHtcbiAgICByZXR1cm4gdmFsdWU7XG4gIH1cblxuICBwcm9jZXNzX2xpdHRsZSh2YWx1ZSkge1xuICAgIHJldHVybiB2YWx1ZS5yZXZlcnNlKCk7XG4gIH1cblxuICBwcm9jZXNzX3NpemUodmFsdWUpIHtcbiAgICByZXR1cm4gdmFsdWU7XG4gIH1cblxuICBwcm9jZXNzX3VuaXQodmFsdWUpIHtcbiAgICByZXR1cm4gdmFsdWU7XG4gIH1cblxuICBzdGF0aWMgaW50ZWdlcih2YWx1ZSkge1xuICAgIHJldHVybiBCaXRTdHJpbmcud3JhcCh2YWx1ZSwgeyBcInR5cGVcIjogXCJpbnRlZ2VyXCIsIFwidW5pdFwiOiAxLCBcInNpemVcIjogOCB9KTtcbiAgfVxuXG4gIHN0YXRpYyBmbG9hdCh2YWx1ZSkge1xuICAgIHJldHVybiBCaXRTdHJpbmcud3JhcCh2YWx1ZSwgeyBcInR5cGVcIjogXCJmbG9hdFwiLCBcInVuaXRcIjogMSwgXCJzaXplXCI6IDY0IH0pO1xuICB9XG5cbiAgc3RhdGljIGJpdHN0cmluZyh2YWx1ZSkge1xuICAgIHJldHVybiBCaXRTdHJpbmcud3JhcCh2YWx1ZSwgeyBcInR5cGVcIjogXCJiaXRzdHJpbmdcIiwgXCJ1bml0XCI6IDEsIFwic2l6ZVwiOiB2YWx1ZS5sZW5ndGggfSk7XG4gIH1cblxuICBzdGF0aWMgYml0cyh2YWx1ZSkge1xuICAgIHJldHVybiBCaXRTdHJpbmcuYml0c3RyaW5nKHZhbHVlKTtcbiAgfVxuXG4gIHN0YXRpYyBiaW5hcnkodmFsdWUpIHtcbiAgICByZXR1cm4gQml0U3RyaW5nLndyYXAodmFsdWUsIHsgXCJ0eXBlXCI6IFwiYmluYXJ5XCIsIFwidW5pdFwiOiA4LCBcInNpemVcIjogdmFsdWUubGVuZ3RoIH0pO1xuICB9XG5cbiAgc3RhdGljIGJ5dGVzKHZhbHVlKSB7XG4gICAgcmV0dXJuIEJpdFN0cmluZy5iaW5hcnkodmFsdWUpO1xuICB9XG5cbiAgc3RhdGljIHV0ZjgodmFsdWUpIHtcbiAgICByZXR1cm4gQml0U3RyaW5nLndyYXAodmFsdWUsIHsgXCJ0eXBlXCI6IFwidXRmOFwiIH0pO1xuICB9XG5cbiAgc3RhdGljIHV0ZjE2KHZhbHVlKSB7XG4gICAgcmV0dXJuIEJpdFN0cmluZy53cmFwKHZhbHVlLCB7IFwidHlwZVwiOiBcInV0ZjE2XCIgfSk7XG4gIH1cblxuICBzdGF0aWMgdXRmMzIodmFsdWUpIHtcbiAgICByZXR1cm4gQml0U3RyaW5nLndyYXAodmFsdWUsIHsgXCJ0eXBlXCI6IFwidXRmMzJcIiB9KTtcbiAgfVxuXG4gIHN0YXRpYyBzaWduZWQodmFsdWUpIHtcbiAgICByZXR1cm4gQml0U3RyaW5nLndyYXAodmFsdWUsIHt9LCBcInNpZ25lZFwiKTtcbiAgfVxuXG4gIHN0YXRpYyB1bnNpZ25lZCh2YWx1ZSkge1xuICAgIHJldHVybiBCaXRTdHJpbmcud3JhcCh2YWx1ZSwge30sIFwidW5zaWduZWRcIik7XG4gIH1cblxuICBzdGF0aWMgbmF0aXZlKHZhbHVlKSB7XG4gICAgcmV0dXJuIEJpdFN0cmluZy53cmFwKHZhbHVlLCB7fSwgXCJuYXRpdmVcIik7XG4gIH1cblxuICBzdGF0aWMgYmlnKHZhbHVlKSB7XG4gICAgcmV0dXJuIEJpdFN0cmluZy53cmFwKHZhbHVlLCB7fSwgXCJiaWdcIik7XG4gIH1cblxuICBzdGF0aWMgbGl0dGxlKHZhbHVlKSB7XG4gICAgcmV0dXJuIEJpdFN0cmluZy53cmFwKHZhbHVlLCB7fSwgXCJsaXR0bGVcIik7XG4gIH1cblxuICBzdGF0aWMgc2l6ZSh2YWx1ZSwgY291bnQpIHtcbiAgICByZXR1cm4gQml0U3RyaW5nLndyYXAodmFsdWUsIHsgXCJzaXplXCI6IGNvdW50IH0pO1xuICB9XG5cbiAgc3RhdGljIHVuaXQodmFsdWUsIGNvdW50KSB7XG4gICAgcmV0dXJuIEJpdFN0cmluZy53cmFwKHZhbHVlLCB7IFwidW5pdFwiOiBjb3VudCB9KTtcbiAgfVxuXG4gIHN0YXRpYyB3cmFwKHZhbHVlLCBvcHQsIG5ld19hdHRyaWJ1dGUgPSBudWxsKSB7XG4gICAgbGV0IHRoZV92YWx1ZSA9IHZhbHVlO1xuXG4gICAgaWYgKCEodmFsdWUgaW5zdGFuY2VvZiBPYmplY3QpKSB7XG4gICAgICB0aGVfdmFsdWUgPSB7IFwidmFsdWVcIjogdmFsdWUsIFwiYXR0cmlidXRlc1wiOiBbXSB9O1xuICAgIH1cblxuICAgIHRoZV92YWx1ZSA9IE9iamVjdC5hc3NpZ24odGhlX3ZhbHVlLCBvcHQpO1xuXG4gICAgaWYgKG5ld19hdHRyaWJ1dGUpIHtcbiAgICAgIHRoZV92YWx1ZS5hdHRyaWJ1dGVzLnB1c2gobmV3X2F0dHJpYnV0ZSk7XG4gICAgfVxuXG4gICAgcmV0dXJuIHRoZV92YWx1ZTtcbiAgfVxuXG4gIHN0YXRpYyB0b1VURjhBcnJheShzdHIpIHtcbiAgICB2YXIgdXRmOCA9IFtdO1xuICAgIGZvciAodmFyIGkgPSAwOyBpIDwgc3RyLmxlbmd0aDsgaSsrKSB7XG4gICAgICB2YXIgY2hhcmNvZGUgPSBzdHIuY2hhckNvZGVBdChpKTtcbiAgICAgIGlmIChjaGFyY29kZSA8IDEyOCkge1xuICAgICAgICB1dGY4LnB1c2goY2hhcmNvZGUpO1xuICAgICAgfSBlbHNlIGlmIChjaGFyY29kZSA8IDIwNDgpIHtcbiAgICAgICAgdXRmOC5wdXNoKDE5MiB8IGNoYXJjb2RlID4+IDYsIDEyOCB8IGNoYXJjb2RlICYgNjMpO1xuICAgICAgfSBlbHNlIGlmIChjaGFyY29kZSA8IDU1Mjk2IHx8IGNoYXJjb2RlID49IDU3MzQ0KSB7XG4gICAgICAgIHV0ZjgucHVzaCgyMjQgfCBjaGFyY29kZSA+PiAxMiwgMTI4IHwgY2hhcmNvZGUgPj4gNiAmIDYzLCAxMjggfCBjaGFyY29kZSAmIDYzKTtcbiAgICAgIH1cbiAgICAgIC8vIHN1cnJvZ2F0ZSBwYWlyXG4gICAgICBlbHNlIHtcbiAgICAgICAgaSsrO1xuICAgICAgICAvLyBVVEYtMTYgZW5jb2RlcyAweDEwMDAwLTB4MTBGRkZGIGJ5XG4gICAgICAgIC8vIHN1YnRyYWN0aW5nIDB4MTAwMDAgYW5kIHNwbGl0dGluZyB0aGVcbiAgICAgICAgLy8gMjAgYml0cyBvZiAweDAtMHhGRkZGRiBpbnRvIHR3byBoYWx2ZXNcbiAgICAgICAgY2hhcmNvZGUgPSA2NTUzNiArICgoY2hhcmNvZGUgJiAxMDIzKSA8PCAxMCB8IHN0ci5jaGFyQ29kZUF0KGkpICYgMTAyMyk7XG4gICAgICAgIHV0ZjgucHVzaCgyNDAgfCBjaGFyY29kZSA+PiAxOCwgMTI4IHwgY2hhcmNvZGUgPj4gMTIgJiA2MywgMTI4IHwgY2hhcmNvZGUgPj4gNiAmIDYzLCAxMjggfCBjaGFyY29kZSAmIDYzKTtcbiAgICAgIH1cbiAgICB9XG4gICAgcmV0dXJuIHV0Zjg7XG4gIH1cblxuICBzdGF0aWMgdG9VVEYxNkFycmF5KHN0cikge1xuICAgIHZhciB1dGYxNiA9IFtdO1xuICAgIGZvciAodmFyIGkgPSAwOyBpIDwgc3RyLmxlbmd0aDsgaSsrKSB7XG4gICAgICB2YXIgY29kZVBvaW50ID0gc3RyLmNvZGVQb2ludEF0KGkpO1xuXG4gICAgICBpZiAoY29kZVBvaW50IDw9IDI1NSkge1xuICAgICAgICB1dGYxNi5wdXNoKDApO1xuICAgICAgICB1dGYxNi5wdXNoKGNvZGVQb2ludCk7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICB1dGYxNi5wdXNoKGNvZGVQb2ludCA+PiA4ICYgMjU1KTtcbiAgICAgICAgdXRmMTYucHVzaChjb2RlUG9pbnQgJiAyNTUpO1xuICAgICAgfVxuICAgIH1cbiAgICByZXR1cm4gdXRmMTY7XG4gIH1cblxuICBzdGF0aWMgdG9VVEYzMkFycmF5KHN0cikge1xuICAgIHZhciB1dGYzMiA9IFtdO1xuICAgIGZvciAodmFyIGkgPSAwOyBpIDwgc3RyLmxlbmd0aDsgaSsrKSB7XG4gICAgICB2YXIgY29kZVBvaW50ID0gc3RyLmNvZGVQb2ludEF0KGkpO1xuXG4gICAgICBpZiAoY29kZVBvaW50IDw9IDI1NSkge1xuICAgICAgICB1dGYzMi5wdXNoKDApO1xuICAgICAgICB1dGYzMi5wdXNoKDApO1xuICAgICAgICB1dGYzMi5wdXNoKDApO1xuICAgICAgICB1dGYzMi5wdXNoKGNvZGVQb2ludCk7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICB1dGYzMi5wdXNoKDApO1xuICAgICAgICB1dGYzMi5wdXNoKDApO1xuICAgICAgICB1dGYzMi5wdXNoKGNvZGVQb2ludCA+PiA4ICYgMjU1KTtcbiAgICAgICAgdXRmMzIucHVzaChjb2RlUG9pbnQgJiAyNTUpO1xuICAgICAgfVxuICAgIH1cbiAgICByZXR1cm4gdXRmMzI7XG4gIH1cblxuICAvL2h0dHA6Ly9zdGFja292ZXJmbG93LmNvbS9xdWVzdGlvbnMvMjAwMzQ5My9qYXZhc2NyaXB0LWZsb2F0LWZyb20tdG8tYml0c1xuICBzdGF0aWMgZmxvYXQzMlRvQnl0ZXMoZikge1xuICAgIHZhciBieXRlcyA9IFtdO1xuXG4gICAgdmFyIGJ1ZiA9IG5ldyBBcnJheUJ1ZmZlcig0KTtcbiAgICBuZXcgRmxvYXQzMkFycmF5KGJ1ZilbMF0gPSBmO1xuXG4gICAgbGV0IGludFZlcnNpb24gPSBuZXcgVWludDMyQXJyYXkoYnVmKVswXTtcblxuICAgIGJ5dGVzLnB1c2goaW50VmVyc2lvbiA+PiAyNCAmIDI1NSk7XG4gICAgYnl0ZXMucHVzaChpbnRWZXJzaW9uID4+IDE2ICYgMjU1KTtcbiAgICBieXRlcy5wdXNoKGludFZlcnNpb24gPj4gOCAmIDI1NSk7XG4gICAgYnl0ZXMucHVzaChpbnRWZXJzaW9uICYgMjU1KTtcblxuICAgIHJldHVybiBieXRlcztcbiAgfVxuXG4gIHN0YXRpYyBmbG9hdDY0VG9CeXRlcyhmKSB7XG4gICAgdmFyIGJ5dGVzID0gW107XG5cbiAgICB2YXIgYnVmID0gbmV3IEFycmF5QnVmZmVyKDgpO1xuICAgIG5ldyBGbG9hdDY0QXJyYXkoYnVmKVswXSA9IGY7XG5cbiAgICB2YXIgaW50VmVyc2lvbjEgPSBuZXcgVWludDMyQXJyYXkoYnVmKVswXTtcbiAgICB2YXIgaW50VmVyc2lvbjIgPSBuZXcgVWludDMyQXJyYXkoYnVmKVsxXTtcblxuICAgIGJ5dGVzLnB1c2goaW50VmVyc2lvbjIgPj4gMjQgJiAyNTUpO1xuICAgIGJ5dGVzLnB1c2goaW50VmVyc2lvbjIgPj4gMTYgJiAyNTUpO1xuICAgIGJ5dGVzLnB1c2goaW50VmVyc2lvbjIgPj4gOCAmIDI1NSk7XG4gICAgYnl0ZXMucHVzaChpbnRWZXJzaW9uMiAmIDI1NSk7XG5cbiAgICBieXRlcy5wdXNoKGludFZlcnNpb24xID4+IDI0ICYgMjU1KTtcbiAgICBieXRlcy5wdXNoKGludFZlcnNpb24xID4+IDE2ICYgMjU1KTtcbiAgICBieXRlcy5wdXNoKGludFZlcnNpb24xID4+IDggJiAyNTUpO1xuICAgIGJ5dGVzLnB1c2goaW50VmVyc2lvbjEgJiAyNTUpO1xuXG4gICAgcmV0dXJuIGJ5dGVzO1xuICB9XG59XG5cbi8qIEBmbG93ICovXG5cbmNsYXNzIFZhcmlhYmxlIHtcblxuICBjb25zdHJ1Y3RvcihuYW1lID0gbnVsbCkge1xuICAgIHRoaXMubmFtZSA9IG5hbWU7XG4gIH1cbn1cblxuY2xhc3MgV2lsZGNhcmQge1xuICBjb25zdHJ1Y3RvcigpIHt9XG59XG5cbmNsYXNzIFN0YXJ0c1dpdGgge1xuXG4gIGNvbnN0cnVjdG9yKHByZWZpeCkge1xuICAgIHRoaXMucHJlZml4ID0gcHJlZml4O1xuICB9XG59XG5cbmNsYXNzIENhcHR1cmUge1xuXG4gIGNvbnN0cnVjdG9yKHZhbHVlKSB7XG4gICAgdGhpcy52YWx1ZSA9IHZhbHVlO1xuICB9XG59XG5cbmNsYXNzIEhlYWRUYWlsIHtcbiAgY29uc3RydWN0b3IoKSB7fVxufVxuXG5jbGFzcyBUeXBlIHtcblxuICBjb25zdHJ1Y3Rvcih0eXBlLCBvYmpQYXR0ZXJuID0ge30pIHtcbiAgICB0aGlzLnR5cGUgPSB0eXBlO1xuICAgIHRoaXMub2JqUGF0dGVybiA9IG9ialBhdHRlcm47XG4gIH1cbn1cblxuY2xhc3MgQm91bmQge1xuXG4gIGNvbnN0cnVjdG9yKHZhbHVlKSB7XG4gICAgdGhpcy52YWx1ZSA9IHZhbHVlO1xuICB9XG59XG5cbmZ1bmN0aW9uIHZhcmlhYmxlKG5hbWUgPSBudWxsKSB7XG4gIHJldHVybiBuZXcgVmFyaWFibGUobmFtZSk7XG59XG5cbmZ1bmN0aW9uIHdpbGRjYXJkKCkge1xuICByZXR1cm4gbmV3IFdpbGRjYXJkKCk7XG59XG5cbmZ1bmN0aW9uIHN0YXJ0c1dpdGgocHJlZml4KSB7XG4gIHJldHVybiBuZXcgU3RhcnRzV2l0aChwcmVmaXgpO1xufVxuXG5mdW5jdGlvbiBjYXB0dXJlKHZhbHVlKSB7XG4gIHJldHVybiBuZXcgQ2FwdHVyZSh2YWx1ZSk7XG59XG5cbmZ1bmN0aW9uIGhlYWRUYWlsKCkge1xuICByZXR1cm4gbmV3IEhlYWRUYWlsKCk7XG59XG5cbmZ1bmN0aW9uIHR5cGUodHlwZSwgb2JqUGF0dGVybiA9IHt9KSB7XG4gIHJldHVybiBuZXcgVHlwZSh0eXBlLCBvYmpQYXR0ZXJuKTtcbn1cblxuZnVuY3Rpb24gYm91bmQodmFsdWUpIHtcbiAgcmV0dXJuIG5ldyBCb3VuZCh2YWx1ZSk7XG59XG5cbmZ1bmN0aW9uIGlzX251bWJlcih2YWx1ZSkge1xuICByZXR1cm4gdHlwZW9mIHZhbHVlID09PSAnbnVtYmVyJztcbn1cblxuZnVuY3Rpb24gaXNfc3RyaW5nKHZhbHVlKSB7XG4gIHJldHVybiB0eXBlb2YgdmFsdWUgPT09ICdzdHJpbmcnO1xufVxuXG5mdW5jdGlvbiBpc19ib29sZWFuKHZhbHVlKSB7XG4gIHJldHVybiB0eXBlb2YgdmFsdWUgPT09ICdib29sZWFuJztcbn1cblxuZnVuY3Rpb24gaXNfc3ltYm9sKHZhbHVlKSB7XG4gIHJldHVybiB0eXBlb2YgdmFsdWUgPT09ICdzeW1ib2wnO1xufVxuXG5mdW5jdGlvbiBpc19udWxsKHZhbHVlKSB7XG4gIHJldHVybiB2YWx1ZSA9PT0gbnVsbDtcbn1cblxuZnVuY3Rpb24gaXNfdW5kZWZpbmVkKHZhbHVlKSB7XG4gIHJldHVybiB0eXBlb2YgdmFsdWUgPT09ICd1bmRlZmluZWQnO1xufVxuXG5mdW5jdGlvbiBpc19mdW5jdGlvbih2YWx1ZSkge1xuICByZXR1cm4gT2JqZWN0LnByb3RvdHlwZS50b1N0cmluZy5jYWxsKHZhbHVlKSA9PSAnW29iamVjdCBGdW5jdGlvbl0nO1xufVxuXG5mdW5jdGlvbiBpc192YXJpYWJsZSh2YWx1ZSkge1xuICByZXR1cm4gdmFsdWUgaW5zdGFuY2VvZiBWYXJpYWJsZTtcbn1cblxuZnVuY3Rpb24gaXNfd2lsZGNhcmQodmFsdWUpIHtcbiAgcmV0dXJuIHZhbHVlIGluc3RhbmNlb2YgV2lsZGNhcmQ7XG59XG5cbmZ1bmN0aW9uIGlzX2hlYWRUYWlsKHZhbHVlKSB7XG4gIHJldHVybiB2YWx1ZSBpbnN0YW5jZW9mIEhlYWRUYWlsO1xufVxuXG5mdW5jdGlvbiBpc19jYXB0dXJlKHZhbHVlKSB7XG4gIHJldHVybiB2YWx1ZSBpbnN0YW5jZW9mIENhcHR1cmU7XG59XG5cbmZ1bmN0aW9uIGlzX3R5cGUodmFsdWUpIHtcbiAgcmV0dXJuIHZhbHVlIGluc3RhbmNlb2YgVHlwZTtcbn1cblxuZnVuY3Rpb24gaXNfc3RhcnRzV2l0aCh2YWx1ZSkge1xuICByZXR1cm4gdmFsdWUgaW5zdGFuY2VvZiBTdGFydHNXaXRoO1xufVxuXG5mdW5jdGlvbiBpc19ib3VuZCh2YWx1ZSkge1xuICByZXR1cm4gdmFsdWUgaW5zdGFuY2VvZiBCb3VuZDtcbn1cblxuZnVuY3Rpb24gaXNfb2JqZWN0KHZhbHVlKSB7XG4gIHJldHVybiB0eXBlb2YgdmFsdWUgPT09ICdvYmplY3QnO1xufVxuXG5mdW5jdGlvbiBpc19hcnJheSh2YWx1ZSkge1xuICByZXR1cm4gQXJyYXkuaXNBcnJheSh2YWx1ZSk7XG59XG5cbnZhciBDaGVja3MgPSB7XG4gIGlzX251bWJlcixcbiAgaXNfc3RyaW5nLFxuICBpc19ib29sZWFuLFxuICBpc19zeW1ib2wsXG4gIGlzX251bGwsXG4gIGlzX3VuZGVmaW5lZCxcbiAgaXNfZnVuY3Rpb24sXG4gIGlzX3ZhcmlhYmxlLFxuICBpc193aWxkY2FyZCxcbiAgaXNfaGVhZFRhaWwsXG4gIGlzX2NhcHR1cmUsXG4gIGlzX3R5cGUsXG4gIGlzX3N0YXJ0c1dpdGgsXG4gIGlzX2JvdW5kLFxuICBpc19vYmplY3QsXG4gIGlzX2FycmF5XG59O1xuXG5mdW5jdGlvbiByZXNvbHZlU3ltYm9sKHBhdHRlcm4pIHtcbiAgcmV0dXJuIGZ1bmN0aW9uICh2YWx1ZSkge1xuICAgIHJldHVybiBDaGVja3MuaXNfc3ltYm9sKHZhbHVlKSAmJiB2YWx1ZSA9PT0gcGF0dGVybjtcbiAgfTtcbn1cblxuZnVuY3Rpb24gcmVzb2x2ZVN0cmluZyhwYXR0ZXJuKSB7XG4gIHJldHVybiBmdW5jdGlvbiAodmFsdWUpIHtcbiAgICByZXR1cm4gQ2hlY2tzLmlzX3N0cmluZyh2YWx1ZSkgJiYgdmFsdWUgPT09IHBhdHRlcm47XG4gIH07XG59XG5cbmZ1bmN0aW9uIHJlc29sdmVOdW1iZXIocGF0dGVybikge1xuICByZXR1cm4gZnVuY3Rpb24gKHZhbHVlKSB7XG4gICAgcmV0dXJuIENoZWNrcy5pc19udW1iZXIodmFsdWUpICYmIHZhbHVlID09PSBwYXR0ZXJuO1xuICB9O1xufVxuXG5mdW5jdGlvbiByZXNvbHZlQm9vbGVhbihwYXR0ZXJuKSB7XG4gIHJldHVybiBmdW5jdGlvbiAodmFsdWUpIHtcbiAgICByZXR1cm4gQ2hlY2tzLmlzX2Jvb2xlYW4odmFsdWUpICYmIHZhbHVlID09PSBwYXR0ZXJuO1xuICB9O1xufVxuXG5mdW5jdGlvbiByZXNvbHZlRnVuY3Rpb24ocGF0dGVybikge1xuICByZXR1cm4gZnVuY3Rpb24gKHZhbHVlKSB7XG4gICAgcmV0dXJuIENoZWNrcy5pc19mdW5jdGlvbih2YWx1ZSkgJiYgdmFsdWUgPT09IHBhdHRlcm47XG4gIH07XG59XG5cbmZ1bmN0aW9uIHJlc29sdmVOdWxsKHBhdHRlcm4pIHtcbiAgcmV0dXJuIGZ1bmN0aW9uICh2YWx1ZSkge1xuICAgIHJldHVybiBDaGVja3MuaXNfbnVsbCh2YWx1ZSk7XG4gIH07XG59XG5cbmZ1bmN0aW9uIHJlc29sdmVCb3VuZChwYXR0ZXJuKSB7XG4gIHJldHVybiBmdW5jdGlvbiAodmFsdWUsIGFyZ3MpIHtcbiAgICBpZiAodHlwZW9mIHZhbHVlID09PSB0eXBlb2YgcGF0dGVybi52YWx1ZSAmJiB2YWx1ZSA9PT0gcGF0dGVybi52YWx1ZSkge1xuICAgICAgYXJncy5wdXNoKHZhbHVlKTtcbiAgICAgIHJldHVybiB0cnVlO1xuICAgIH1cblxuICAgIHJldHVybiBmYWxzZTtcbiAgfTtcbn1cblxuZnVuY3Rpb24gcmVzb2x2ZVdpbGRjYXJkKCkge1xuICByZXR1cm4gZnVuY3Rpb24gKCkge1xuICAgIHJldHVybiB0cnVlO1xuICB9O1xufVxuXG5mdW5jdGlvbiByZXNvbHZlVmFyaWFibGUoKSB7XG4gIHJldHVybiBmdW5jdGlvbiAodmFsdWUsIGFyZ3MpIHtcbiAgICBhcmdzLnB1c2godmFsdWUpO1xuICAgIHJldHVybiB0cnVlO1xuICB9O1xufVxuXG5mdW5jdGlvbiByZXNvbHZlSGVhZFRhaWwoKSB7XG4gIHJldHVybiBmdW5jdGlvbiAodmFsdWUsIGFyZ3MpIHtcbiAgICBpZiAoIUNoZWNrcy5pc19hcnJheSh2YWx1ZSkgfHwgdmFsdWUubGVuZ3RoIDwgMikge1xuICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH1cblxuICAgIGNvbnN0IGhlYWQgPSB2YWx1ZVswXTtcbiAgICBjb25zdCB0YWlsID0gdmFsdWUuc2xpY2UoMSk7XG5cbiAgICBhcmdzLnB1c2goaGVhZCk7XG4gICAgYXJncy5wdXNoKHRhaWwpO1xuXG4gICAgcmV0dXJuIHRydWU7XG4gIH07XG59XG5cbmZ1bmN0aW9uIHJlc29sdmVDYXB0dXJlKHBhdHRlcm4pIHtcbiAgY29uc3QgbWF0Y2hlcyA9IGJ1aWxkTWF0Y2gocGF0dGVybi52YWx1ZSk7XG5cbiAgcmV0dXJuIGZ1bmN0aW9uICh2YWx1ZSwgYXJncykge1xuICAgIGlmIChtYXRjaGVzKHZhbHVlLCBhcmdzKSkge1xuICAgICAgYXJncy5wdXNoKHZhbHVlKTtcbiAgICAgIHJldHVybiB0cnVlO1xuICAgIH1cblxuICAgIHJldHVybiBmYWxzZTtcbiAgfTtcbn1cblxuZnVuY3Rpb24gcmVzb2x2ZVN0YXJ0c1dpdGgocGF0dGVybikge1xuICBjb25zdCBwcmVmaXggPSBwYXR0ZXJuLnByZWZpeDtcblxuICByZXR1cm4gZnVuY3Rpb24gKHZhbHVlLCBhcmdzKSB7XG4gICAgaWYgKENoZWNrcy5pc19zdHJpbmcodmFsdWUpICYmIHZhbHVlLnN0YXJ0c1dpdGgocHJlZml4KSkge1xuICAgICAgYXJncy5wdXNoKHZhbHVlLnN1YnN0cmluZyhwcmVmaXgubGVuZ3RoKSk7XG4gICAgICByZXR1cm4gdHJ1ZTtcbiAgICB9XG5cbiAgICByZXR1cm4gZmFsc2U7XG4gIH07XG59XG5cbmZ1bmN0aW9uIHJlc29sdmVUeXBlKHBhdHRlcm4pIHtcbiAgcmV0dXJuIGZ1bmN0aW9uICh2YWx1ZSwgYXJncykge1xuICAgIGlmICh2YWx1ZSBpbnN0YW5jZW9mIHBhdHRlcm4udHlwZSkge1xuICAgICAgY29uc3QgbWF0Y2hlcyA9IGJ1aWxkTWF0Y2gocGF0dGVybi5vYmpQYXR0ZXJuKTtcbiAgICAgIHJldHVybiBtYXRjaGVzKHZhbHVlLCBhcmdzKSAmJiBhcmdzLnB1c2godmFsdWUpID4gMDtcbiAgICB9XG5cbiAgICByZXR1cm4gZmFsc2U7XG4gIH07XG59XG5cbmZ1bmN0aW9uIHJlc29sdmVBcnJheShwYXR0ZXJuKSB7XG4gIGNvbnN0IG1hdGNoZXMgPSBwYXR0ZXJuLm1hcCh4ID0+IGJ1aWxkTWF0Y2goeCkpO1xuXG4gIHJldHVybiBmdW5jdGlvbiAodmFsdWUsIGFyZ3MpIHtcbiAgICBpZiAoIUNoZWNrcy5pc19hcnJheSh2YWx1ZSkgfHwgdmFsdWUubGVuZ3RoICE9IHBhdHRlcm4ubGVuZ3RoKSB7XG4gICAgICByZXR1cm4gZmFsc2U7XG4gICAgfVxuXG4gICAgcmV0dXJuIHZhbHVlLmV2ZXJ5KGZ1bmN0aW9uICh2LCBpKSB7XG4gICAgICByZXR1cm4gbWF0Y2hlc1tpXSh2YWx1ZVtpXSwgYXJncyk7XG4gICAgfSk7XG4gIH07XG59XG5cbmZ1bmN0aW9uIHJlc29sdmVPYmplY3QocGF0dGVybikge1xuICBsZXQgbWF0Y2hlcyA9IHt9O1xuXG4gIGZvciAobGV0IGtleSBvZiBPYmplY3Qua2V5cyhwYXR0ZXJuKS5jb25jYXQoT2JqZWN0LmdldE93blByb3BlcnR5U3ltYm9scyhwYXR0ZXJuKSkpIHtcbiAgICBtYXRjaGVzW2tleV0gPSBidWlsZE1hdGNoKHBhdHRlcm5ba2V5XSk7XG4gIH1cblxuICByZXR1cm4gZnVuY3Rpb24gKHZhbHVlLCBhcmdzKSB7XG4gICAgaWYgKCFDaGVja3MuaXNfb2JqZWN0KHZhbHVlKSB8fCBwYXR0ZXJuLmxlbmd0aCA+IHZhbHVlLmxlbmd0aCkge1xuICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH1cblxuICAgIGZvciAobGV0IGtleSBvZiBPYmplY3Qua2V5cyhwYXR0ZXJuKS5jb25jYXQoT2JqZWN0LmdldE93blByb3BlcnR5U3ltYm9scyhwYXR0ZXJuKSkpIHtcbiAgICAgIGlmICghKGtleSBpbiB2YWx1ZSkgfHwgIW1hdGNoZXNba2V5XSh2YWx1ZVtrZXldLCBhcmdzKSkge1xuICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICB9XG4gICAgfVxuXG4gICAgcmV0dXJuIHRydWU7XG4gIH07XG59XG5cbmZ1bmN0aW9uIHJlc29sdmVOb01hdGNoKCkge1xuICByZXR1cm4gZnVuY3Rpb24gKCkge1xuICAgIHJldHVybiBmYWxzZTtcbiAgfTtcbn1cblxudmFyIFJlc29sdmVycyA9IHtcbiAgcmVzb2x2ZUJvdW5kLFxuICByZXNvbHZlV2lsZGNhcmQsXG4gIHJlc29sdmVWYXJpYWJsZSxcbiAgcmVzb2x2ZUhlYWRUYWlsLFxuICByZXNvbHZlQ2FwdHVyZSxcbiAgcmVzb2x2ZVN0YXJ0c1dpdGgsXG4gIHJlc29sdmVUeXBlLFxuICByZXNvbHZlQXJyYXksXG4gIHJlc29sdmVPYmplY3QsXG4gIHJlc29sdmVOb01hdGNoLFxuICByZXNvbHZlU3ltYm9sLFxuICByZXNvbHZlU3RyaW5nLFxuICByZXNvbHZlTnVtYmVyLFxuICByZXNvbHZlQm9vbGVhbixcbiAgcmVzb2x2ZUZ1bmN0aW9uLFxuICByZXNvbHZlTnVsbFxufTtcblxuZnVuY3Rpb24gYnVpbGRNYXRjaChwYXR0ZXJuKSB7XG5cbiAgaWYgKENoZWNrcy5pc192YXJpYWJsZShwYXR0ZXJuKSkge1xuICAgIHJldHVybiBSZXNvbHZlcnMucmVzb2x2ZVZhcmlhYmxlKHBhdHRlcm4pO1xuICB9XG5cbiAgaWYgKENoZWNrcy5pc193aWxkY2FyZChwYXR0ZXJuKSkge1xuICAgIHJldHVybiBSZXNvbHZlcnMucmVzb2x2ZVdpbGRjYXJkKHBhdHRlcm4pO1xuICB9XG5cbiAgaWYgKENoZWNrcy5pc191bmRlZmluZWQocGF0dGVybikpIHtcbiAgICByZXR1cm4gUmVzb2x2ZXJzLnJlc29sdmVXaWxkY2FyZChwYXR0ZXJuKTtcbiAgfVxuXG4gIGlmIChDaGVja3MuaXNfaGVhZFRhaWwocGF0dGVybikpIHtcbiAgICByZXR1cm4gUmVzb2x2ZXJzLnJlc29sdmVIZWFkVGFpbChwYXR0ZXJuKTtcbiAgfVxuXG4gIGlmIChDaGVja3MuaXNfc3RhcnRzV2l0aChwYXR0ZXJuKSkge1xuICAgIHJldHVybiBSZXNvbHZlcnMucmVzb2x2ZVN0YXJ0c1dpdGgocGF0dGVybik7XG4gIH1cblxuICBpZiAoQ2hlY2tzLmlzX2NhcHR1cmUocGF0dGVybikpIHtcbiAgICByZXR1cm4gUmVzb2x2ZXJzLnJlc29sdmVDYXB0dXJlKHBhdHRlcm4pO1xuICB9XG5cbiAgaWYgKENoZWNrcy5pc19ib3VuZChwYXR0ZXJuKSkge1xuICAgIHJldHVybiBSZXNvbHZlcnMucmVzb2x2ZUJvdW5kKHBhdHRlcm4pO1xuICB9XG5cbiAgaWYgKENoZWNrcy5pc190eXBlKHBhdHRlcm4pKSB7XG4gICAgcmV0dXJuIFJlc29sdmVycy5yZXNvbHZlVHlwZShwYXR0ZXJuKTtcbiAgfVxuXG4gIGlmIChDaGVja3MuaXNfYXJyYXkocGF0dGVybikpIHtcbiAgICByZXR1cm4gUmVzb2x2ZXJzLnJlc29sdmVBcnJheShwYXR0ZXJuKTtcbiAgfVxuXG4gIGlmIChDaGVja3MuaXNfbnVtYmVyKHBhdHRlcm4pKSB7XG4gICAgcmV0dXJuIFJlc29sdmVycy5yZXNvbHZlTnVtYmVyKHBhdHRlcm4pO1xuICB9XG5cbiAgaWYgKENoZWNrcy5pc19zdHJpbmcocGF0dGVybikpIHtcbiAgICByZXR1cm4gUmVzb2x2ZXJzLnJlc29sdmVTdHJpbmcocGF0dGVybik7XG4gIH1cblxuICBpZiAoQ2hlY2tzLmlzX2Jvb2xlYW4ocGF0dGVybikpIHtcbiAgICByZXR1cm4gUmVzb2x2ZXJzLnJlc29sdmVCb29sZWFuKHBhdHRlcm4pO1xuICB9XG5cbiAgaWYgKENoZWNrcy5pc19zeW1ib2wocGF0dGVybikpIHtcbiAgICByZXR1cm4gUmVzb2x2ZXJzLnJlc29sdmVTeW1ib2wocGF0dGVybik7XG4gIH1cblxuICBpZiAoQ2hlY2tzLmlzX251bGwocGF0dGVybikpIHtcbiAgICByZXR1cm4gUmVzb2x2ZXJzLnJlc29sdmVOdWxsKHBhdHRlcm4pO1xuICB9XG5cbiAgaWYgKENoZWNrcy5pc19vYmplY3QocGF0dGVybikpIHtcbiAgICByZXR1cm4gUmVzb2x2ZXJzLnJlc29sdmVPYmplY3QocGF0dGVybik7XG4gIH1cblxuICByZXR1cm4gUmVzb2x2ZXJzLnJlc29sdmVOb01hdGNoKCk7XG59XG5cbmNsYXNzIE1hdGNoRXJyb3IgZXh0ZW5kcyBFcnJvciB7XG4gIGNvbnN0cnVjdG9yKGFyZykge1xuICAgIHN1cGVyKCk7XG5cbiAgICBpZiAodHlwZW9mIGFyZyA9PT0gJ3N5bWJvbCcpIHtcbiAgICAgIHRoaXMubWVzc2FnZSA9ICdObyBtYXRjaCBmb3I6ICcgKyBhcmcudG9TdHJpbmcoKTtcbiAgICB9IGVsc2UgaWYgKEFycmF5LmlzQXJyYXkoYXJnKSkge1xuICAgICAgbGV0IG1hcHBlZFZhbHVlcyA9IGFyZy5tYXAoeCA9PiB4LnRvU3RyaW5nKCkpO1xuICAgICAgdGhpcy5tZXNzYWdlID0gJ05vIG1hdGNoIGZvcjogJyArIG1hcHBlZFZhbHVlcztcbiAgICB9IGVsc2Uge1xuICAgICAgdGhpcy5tZXNzYWdlID0gJ05vIG1hdGNoIGZvcjogJyArIGFyZztcbiAgICB9XG5cbiAgICB0aGlzLnN0YWNrID0gbmV3IEVycm9yKCkuc3RhY2s7XG4gICAgdGhpcy5uYW1lID0gdGhpcy5jb25zdHJ1Y3Rvci5uYW1lO1xuICB9XG59XG5cbmNsYXNzIENhc2Uge1xuXG4gIGNvbnN0cnVjdG9yKHBhdHRlcm4sIGZuLCBndWFyZCA9ICgpID0+IHRydWUpIHtcbiAgICB0aGlzLnBhdHRlcm4gPSBidWlsZE1hdGNoKHBhdHRlcm4pO1xuICAgIHRoaXMuZm4gPSBmbjtcbiAgICB0aGlzLmd1YXJkID0gZ3VhcmQ7XG4gIH1cbn1cblxuZnVuY3Rpb24gbWFrZV9jYXNlKHBhdHRlcm4sIGZuLCBndWFyZCA9ICgpID0+IHRydWUpIHtcbiAgcmV0dXJuIG5ldyBDYXNlKHBhdHRlcm4sIGZuLCBndWFyZCk7XG59XG5cbmZ1bmN0aW9uIGRlZm1hdGNoKC4uLmNhc2VzKSB7XG4gIHJldHVybiBmdW5jdGlvbiAoLi4uYXJncykge1xuICAgIGZvciAobGV0IHByb2Nlc3NlZENhc2Ugb2YgY2FzZXMpIHtcbiAgICAgIGxldCByZXN1bHQgPSBbXTtcbiAgICAgIGlmIChwcm9jZXNzZWRDYXNlLnBhdHRlcm4oYXJncywgcmVzdWx0KSAmJiBwcm9jZXNzZWRDYXNlLmd1YXJkLmFwcGx5KHRoaXMsIHJlc3VsdCkpIHtcbiAgICAgICAgcmV0dXJuIHByb2Nlc3NlZENhc2UuZm4uYXBwbHkodGhpcywgcmVzdWx0KTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICB0aHJvdyBuZXcgTWF0Y2hFcnJvcihhcmdzKTtcbiAgfTtcbn1cblxuZnVuY3Rpb24gbWF0Y2gocGF0dGVybiwgZXhwciwgZ3VhcmQgPSAoKSA9PiB0cnVlKSB7XG4gIGxldCByZXN1bHQgPSBbXTtcbiAgbGV0IHByb2Nlc3NlZFBhdHRlcm4gPSBidWlsZE1hdGNoKHBhdHRlcm4pO1xuICBpZiAocHJvY2Vzc2VkUGF0dGVybihleHByLCByZXN1bHQpICYmIGd1YXJkLmFwcGx5KHRoaXMsIHJlc3VsdCkpIHtcbiAgICByZXR1cm4gcmVzdWx0O1xuICB9IGVsc2Uge1xuICAgIHRocm93IG5ldyBNYXRjaEVycm9yKGV4cHIpO1xuICB9XG59XG5cbmZ1bmN0aW9uIG1hdGNoX25vX3Rocm93KHBhdHRlcm4sIGV4cHIsIGd1YXJkID0gKCkgPT4gdHJ1ZSkge1xuICB0cnkge1xuICAgIHJldHVybiBtYXRjaChwYXR0ZXJuLCBleHByLCBndWFyZCk7XG4gIH0gY2F0Y2ggKGUpIHtcbiAgICBpZiAoZSBpbnN0YW5jZW9mIE1hdGNoRXJyb3IpIHtcbiAgICAgIHJldHVybiBudWxsO1xuICAgIH1cblxuICAgIHRocm93IGU7XG4gIH1cbn1cblxudmFyIFBhdHRlcm5zID0ge1xuICBkZWZtYXRjaCwgbWF0Y2gsIE1hdGNoRXJyb3IsIG1hdGNoX25vX3Rocm93LFxuICB2YXJpYWJsZSwgd2lsZGNhcmQsIHN0YXJ0c1dpdGgsXG4gIGNhcHR1cmUsIGhlYWRUYWlsLCB0eXBlLCBib3VuZCwgQ2FzZSwgbWFrZV9jYXNlXG59O1xuXG5mdW5jdGlvbiBjYWxsX3Byb3BlcnR5KGl0ZW0sIHByb3BlcnR5KSB7XG4gIGlmIChwcm9wZXJ0eSBpbiBpdGVtKSB7XG4gICAgaXRlbVtwcm9wZXJ0eV07XG4gICAgaWYgKGl0ZW1bcHJvcGVydHldIGluc3RhbmNlb2YgRnVuY3Rpb24pIHtcbiAgICAgIHJldHVybiBpdGVtW3Byb3BlcnR5XSgpO1xuICAgIH0gZWxzZSB7XG4gICAgICByZXR1cm4gaXRlbVtwcm9wZXJ0eV07XG4gICAgfVxuICB9IGVsc2UgaWYgKFN5bWJvbC5mb3IocHJvcGVydHkpIGluIGl0ZW0pIHtcbiAgICBsZXQgcHJvcCA9IFN5bWJvbC5mb3IocHJvcGVydHkpO1xuICAgIGlmIChpdGVtW3Byb3BdIGluc3RhbmNlb2YgRnVuY3Rpb24pIHtcbiAgICAgIHJldHVybiBpdGVtW3Byb3BdKCk7XG4gICAgfSBlbHNlIHtcbiAgICAgIHJldHVybiBpdGVtW3Byb3BdO1xuICAgIH1cbiAgfVxuXG4gIHRocm93IG5ldyBFcnJvcihgUHJvcGVydHkgJHsgcHJvcGVydHkgfSBub3QgZm91bmQgaW4gJHsgaXRlbSB9YCk7XG59XG5cbmZ1bmN0aW9uIGFwcGx5KC4uLmFyZ3MpIHtcbiAgaWYgKGFyZ3MubGVuZ3RoID09PSAyKSB7XG4gICAgYXJnc1swXS5hcHBseShudWxsLCBhcmdzLnNsaWNlKDEpKTtcbiAgfSBlbHNlIHtcbiAgICBhcmdzWzBdW2FyZ3NbMV1dLmFwcGx5KG51bGwsIGFyZ3Muc2xpY2UoMikpO1xuICB9XG59XG5cbmZ1bmN0aW9uIGNvbnRhaW5zKGxlZnQsIHJpZ2h0KSB7XG4gIGZvciAobGV0IHggb2YgcmlnaHQpIHtcbiAgICBpZiAoUGF0dGVybnMubWF0Y2hfbm9fdGhyb3cobGVmdCwgeCkgIT0gbnVsbCkge1xuICAgICAgcmV0dXJuIHRydWU7XG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIGZhbHNlO1xufVxuXG5mdW5jdGlvbiBnZXRfZ2xvYmFsKCkge1xuICBpZiAodHlwZW9mIHNlbGYgIT09ICd1bmRlZmluZWQnKSB7XG4gICAgcmV0dXJuIHNlbGY7XG4gIH0gZWxzZSBpZiAodHlwZW9mIHdpbmRvdyAhPT0gJ3VuZGVmaW5lZCcpIHtcbiAgICByZXR1cm4gd2luZG93O1xuICB9IGVsc2UgaWYgKHR5cGVvZiBnbG9iYWwgIT09ICd1bmRlZmluZWQnKSB7XG4gICAgcmV0dXJuIGdsb2JhbDtcbiAgfVxuXG4gIHRocm93IG5ldyBFcnJvcignTm8gZ2xvYmFsIHN0YXRlIGZvdW5kJyk7XG59XG5cbmZ1bmN0aW9uIGRlZnN0cnVjdChkZWZhdWx0cykge1xuICByZXR1cm4gY2xhc3Mge1xuICAgIGNvbnN0cnVjdG9yKHVwZGF0ZSA9IHt9KSB7XG4gICAgICBsZXQgdGhlX3ZhbHVlcyA9IE9iamVjdC5hc3NpZ24oZGVmYXVsdHMsIHVwZGF0ZSk7XG4gICAgICBPYmplY3QuYXNzaWduKHRoaXMsIHRoZV92YWx1ZXMpO1xuICAgIH1cblxuICAgIHN0YXRpYyBjcmVhdGUodXBkYXRlcyA9IHt9KSB7XG4gICAgICBsZXQgeCA9IG5ldyB0aGlzKHVwZGF0ZXMpO1xuICAgICAgcmV0dXJuIE9iamVjdC5mcmVlemUoeCk7XG4gICAgfVxuICB9O1xufVxuXG5mdW5jdGlvbiBkZWZleGNlcHRpb24oZGVmYXVsdHMpIHtcbiAgcmV0dXJuIGNsYXNzIGV4dGVuZHMgRXJyb3Ige1xuICAgIGNvbnN0cnVjdG9yKHVwZGF0ZSA9IHt9KSB7XG4gICAgICBsZXQgbWVzc2FnZSA9IHVwZGF0ZS5tZXNzYWdlIHx8ICcnO1xuICAgICAgc3VwZXIobWVzc2FnZSk7XG5cbiAgICAgIGxldCB0aGVfdmFsdWVzID0gT2JqZWN0LmFzc2lnbihkZWZhdWx0cywgdXBkYXRlKTtcbiAgICAgIE9iamVjdC5hc3NpZ24odGhpcywgdGhlX3ZhbHVlcyk7XG5cbiAgICAgIHRoaXMubmFtZSA9IHRoaXMuY29uc3RydWN0b3IubmFtZTtcbiAgICAgIHRoaXMubWVzc2FnZSA9IG1lc3NhZ2U7XG4gICAgICB0aGlzW1NwZWNpYWxGb3Jtcy5hdG9tKCdfX2V4Y2VwdGlvbl9fJyldID0gdHJ1ZTtcbiAgICAgIEVycm9yLmNhcHR1cmVTdGFja1RyYWNlKHRoaXMsIHRoaXMuY29uc3RydWN0b3IubmFtZSk7XG4gICAgfVxuXG4gICAgc3RhdGljIGNyZWF0ZSh1cGRhdGVzID0ge30pIHtcbiAgICAgIGxldCB4ID0gbmV3IHRoaXModXBkYXRlcyk7XG4gICAgICByZXR1cm4gT2JqZWN0LmZyZWV6ZSh4KTtcbiAgICB9XG4gIH07XG59XG5cbmZ1bmN0aW9uIGRlZnByb3RvY29sKHNwZWMpIHtcbiAgcmV0dXJuIG5ldyBQcm90b2NvbChzcGVjKTtcbn1cblxuZnVuY3Rpb24gZGVmaW1wbChwcm90b2NvbCwgdHlwZSwgaW1wbCkge1xuICBwcm90b2NvbC5pbXBsZW1lbnRhdGlvbih0eXBlLCBpbXBsKTtcbn1cblxuZnVuY3Rpb24gZ2V0X29iamVjdF9rZXlzKG9iaikge1xuICByZXR1cm4gT2JqZWN0LmtleXMob2JqKS5jb25jYXQoT2JqZWN0LmdldE93blByb3BlcnR5U3ltYm9scyhvYmopKTtcbn1cblxuZnVuY3Rpb24gaXNfdmFsaWRfY2hhcmFjdGVyKGNvZGVwb2ludCkge1xuICB0cnkge1xuICAgIHJldHVybiBTdHJpbmcuZnJvbUNvZGVQb2ludChjb2RlcG9pbnQpICE9IG51bGw7XG4gIH0gY2F0Y2ggKGUpIHtcbiAgICByZXR1cm4gZmFsc2U7XG4gIH1cbn1cblxuLy9odHRwczovL2RldmVsb3Blci5tb3ppbGxhLm9yZy9lbi1VUy9kb2NzL1dlYi9BUEkvV2luZG93QmFzZTY0L0Jhc2U2NF9lbmNvZGluZ19hbmRfZGVjb2RpbmcjU29sdXRpb25fMl8lRTIlODAlOTNfcmV3cml0ZV90aGVfRE9Nc19hdG9iKClfYW5kX2J0b2EoKV91c2luZ19KYXZhU2NyaXB0J3NfVHlwZWRBcnJheXNfYW5kX1VURi04XG5mdW5jdGlvbiBiNjRFbmNvZGVVbmljb2RlKHN0cikge1xuICByZXR1cm4gYnRvYShlbmNvZGVVUklDb21wb25lbnQoc3RyKS5yZXBsYWNlKC8lKFswLTlBLUZdezJ9KS9nLCBmdW5jdGlvbiAobWF0Y2gsIHAxKSB7XG4gICAgcmV0dXJuIFN0cmluZy5mcm9tQ2hhckNvZGUoJzB4JyArIHAxKTtcbiAgfSkpO1xufVxuXG5mdW5jdGlvbiBkZWxldGVfcHJvcGVydHlfZnJvbV9tYXAobWFwLCBwcm9wZXJ0eSkge1xuICBsZXQgbmV3X21hcCA9IE9iamVjdC5hc3NpZ24oT2JqZWN0LmNyZWF0ZShtYXAuY29uc3RydWN0b3IucHJvdG90eXBlKSwgbWFwKTtcbiAgZGVsZXRlIG5ld19tYXBbcHJvcGVydHldO1xuXG4gIHJldHVybiBPYmplY3QuZnJlZXplKG5ld19tYXApO1xufVxuXG5mdW5jdGlvbiBjbGFzc190b19vYmoobWFwKSB7XG4gIGxldCBuZXdfbWFwID0gT2JqZWN0LmFzc2lnbih7fSwgbWFwKTtcbiAgcmV0dXJuIE9iamVjdC5mcmVlemUobmV3X21hcCk7XG59XG5cbmZ1bmN0aW9uIGFkZF9wcm9wZXJ0eV90b19tYXAobWFwLCBwcm9wZXJ0eSwgdmFsdWUpIHtcbiAgbGV0IG5ld19tYXAgPSBPYmplY3QuYXNzaWduKHt9LCBtYXApO1xuICBuZXdfbWFwW3Byb3BlcnR5XSA9IHZhbHVlO1xuICByZXR1cm4gT2JqZWN0LmZyZWV6ZShuZXdfbWFwKTtcbn1cblxuZnVuY3Rpb24gYm5vdChleHByKSB7XG4gIHJldHVybiB+ZXhwcjtcbn1cblxuZnVuY3Rpb24gYmFuZChsZWZ0LCByaWdodCkge1xuICByZXR1cm4gbGVmdCAmIHJpZ2h0O1xufVxuXG5mdW5jdGlvbiBib3IobGVmdCwgcmlnaHQpIHtcbiAgcmV0dXJuIGxlZnQgfCByaWdodDtcbn1cblxuZnVuY3Rpb24gYnNsKGxlZnQsIHJpZ2h0KSB7XG4gIHJldHVybiBsZWZ0IDw8IHJpZ2h0O1xufVxuXG5mdW5jdGlvbiBic3IobGVmdCwgcmlnaHQpIHtcbiAgcmV0dXJuIGxlZnQgPj4gcmlnaHQ7XG59XG5cbmZ1bmN0aW9uIGJ4b3IobGVmdCwgcmlnaHQpIHtcbiAgcmV0dXJuIGxlZnQgXiByaWdodDtcbn1cblxuZnVuY3Rpb24gemlwKGxpc3Rfb2ZfbGlzdHMpIHtcbiAgaWYgKGxpc3Rfb2ZfbGlzdHMubGVuZ3RoID09PSAwKSB7XG4gICAgcmV0dXJuIE9iamVjdC5mcmVlemUoW10pO1xuICB9XG5cbiAgbGV0IG5ld192YWx1ZSA9IFtdO1xuICBsZXQgc21hbGxlc3RfbGVuZ3RoID0gbGlzdF9vZl9saXN0c1swXTtcblxuICBmb3IgKGxldCB4IG9mIGxpc3Rfb2ZfbGlzdHMpIHtcbiAgICBpZiAoeC5sZW5ndGggPCBzbWFsbGVzdF9sZW5ndGgpIHtcbiAgICAgIHNtYWxsZXN0X2xlbmd0aCA9IHgubGVuZ3RoO1xuICAgIH1cbiAgfVxuXG4gIGZvciAobGV0IGkgPSAwOyBpIDwgc21hbGxlc3RfbGVuZ3RoOyBpKyspIHtcbiAgICBsZXQgY3VycmVudF92YWx1ZSA9IFtdO1xuICAgIGZvciAobGV0IGogPSAwOyBqIDwgbGlzdF9vZl9saXN0cy5sZW5ndGg7IGorKykge1xuICAgICAgY3VycmVudF92YWx1ZS5wdXNoKGxpc3Rfb2ZfbGlzdHNbal1baV0pO1xuICAgIH1cblxuICAgIG5ld192YWx1ZS5wdXNoKG5ldyBUdXBsZSguLi5jdXJyZW50X3ZhbHVlKSk7XG4gIH1cblxuICByZXR1cm4gT2JqZWN0LmZyZWV6ZShuZXdfdmFsdWUpO1xufVxuXG5mdW5jdGlvbiBjYW5fZGVjb2RlNjQoZGF0YSkge1xuICB0cnkge1xuICAgIGF0b2IoZGF0YSk7XG4gICAgcmV0dXJuIHRydWU7XG4gIH0gY2F0Y2ggKGUpIHtcbiAgICByZXR1cm4gZmFsc2U7XG4gIH1cbn1cblxudmFyIEZ1bmN0aW9ucyA9IHtcbiAgY2FsbF9wcm9wZXJ0eSxcbiAgYXBwbHksXG4gIGNvbnRhaW5zLFxuICBnZXRfZ2xvYmFsLFxuICBkZWZzdHJ1Y3QsXG4gIGRlZmV4Y2VwdGlvbixcbiAgZGVmcHJvdG9jb2wsXG4gIGRlZmltcGwsXG4gIGdldF9vYmplY3Rfa2V5cyxcbiAgaXNfdmFsaWRfY2hhcmFjdGVyLFxuICBiNjRFbmNvZGVVbmljb2RlLFxuICBkZWxldGVfcHJvcGVydHlfZnJvbV9tYXAsXG4gIGFkZF9wcm9wZXJ0eV90b19tYXAsXG4gIGNsYXNzX3RvX29iaixcbiAgY2FuX2RlY29kZTY0LFxuICBibm90LFxuICBiYW5kLFxuICBib3IsXG4gIGJzbCxcbiAgYnNyLFxuICBieG9yLFxuICB6aXBcbn07XG5cbmZ1bmN0aW9uIF9jYXNlKGNvbmRpdGlvbiwgY2xhdXNlcykge1xuICByZXR1cm4gUGF0dGVybnMuZGVmbWF0Y2goLi4uY2xhdXNlcykoY29uZGl0aW9uKTtcbn1cblxuZnVuY3Rpb24gY29uZChjbGF1c2VzKSB7XG4gIGZvciAobGV0IGNsYXVzZSBvZiBjbGF1c2VzKSB7XG4gICAgaWYgKGNsYXVzZVswXSkge1xuICAgICAgcmV0dXJuIGNsYXVzZVsxXSgpO1xuICAgIH1cbiAgfVxuXG4gIHRocm93IG5ldyBFcnJvcigpO1xufVxuXG5mdW5jdGlvbiBtYXBfdXBkYXRlKG1hcCwgdmFsdWVzKSB7XG4gIHJldHVybiBPYmplY3QuZnJlZXplKE9iamVjdC5hc3NpZ24oT2JqZWN0LmNyZWF0ZShtYXAuY29uc3RydWN0b3IucHJvdG90eXBlKSwgbWFwLCB2YWx1ZXMpKTtcbn1cblxuZnVuY3Rpb24gX2Zvcihjb2xsZWN0aW9ucywgZnVuLCBmaWx0ZXIgPSAoKSA9PiB0cnVlLCBpbnRvID0gW10sIHByZXZpb3VzVmFsdWVzID0gW10pIHtcbiAgbGV0IHBhdHRlcm4gPSBjb2xsZWN0aW9uc1swXVswXTtcbiAgbGV0IGNvbGxlY3Rpb24gPSBjb2xsZWN0aW9uc1swXVsxXTtcblxuICBpZiAoY29sbGVjdGlvbnMubGVuZ3RoID09PSAxKSB7XG5cbiAgICBmb3IgKGxldCBlbGVtIG9mIGNvbGxlY3Rpb24pIHtcbiAgICAgIGxldCByID0gUGF0dGVybnMubWF0Y2hfbm9fdGhyb3cocGF0dGVybiwgZWxlbSk7XG4gICAgICBsZXQgYXJncyA9IHByZXZpb3VzVmFsdWVzLmNvbmNhdChyKTtcblxuICAgICAgaWYgKHIgJiYgZmlsdGVyLmFwcGx5KHRoaXMsIGFyZ3MpKSB7XG4gICAgICAgIGludG8gPSBpbnRvLmNvbmNhdChbZnVuLmFwcGx5KHRoaXMsIGFyZ3MpXSk7XG4gICAgICB9XG4gICAgfVxuXG4gICAgcmV0dXJuIGludG87XG4gIH0gZWxzZSB7XG4gICAgbGV0IF9pbnRvID0gW107XG5cbiAgICBmb3IgKGxldCBlbGVtIG9mIGNvbGxlY3Rpb24pIHtcbiAgICAgIGxldCByID0gUGF0dGVybnMubWF0Y2hfbm9fdGhyb3cocGF0dGVybiwgZWxlbSk7XG4gICAgICBpZiAocikge1xuICAgICAgICBfaW50byA9IGludG8uY29uY2F0KHRoaXMuX2Zvcihjb2xsZWN0aW9ucy5zbGljZSgxKSwgZnVuLCBmaWx0ZXIsIF9pbnRvLCBwcmV2aW91c1ZhbHVlcy5jb25jYXQocikpKTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICByZXR1cm4gX2ludG87XG4gIH1cbn1cblxuZnVuY3Rpb24gX3RyeShkb19mdW4sIHJlc2N1ZV9mdW5jdGlvbiwgY2F0Y2hfZnVuLCBlbHNlX2Z1bmN0aW9uLCBhZnRlcl9mdW5jdGlvbikge1xuICBsZXQgcmVzdWx0ID0gbnVsbDtcblxuICB0cnkge1xuICAgIHJlc3VsdCA9IGRvX2Z1bigpO1xuICB9IGNhdGNoIChlKSB7XG4gICAgbGV0IGV4X3Jlc3VsdCA9IG51bGw7XG5cbiAgICBpZiAocmVzY3VlX2Z1bmN0aW9uKSB7XG4gICAgICB0cnkge1xuICAgICAgICBleF9yZXN1bHQgPSByZXNjdWVfZnVuY3Rpb24oZSk7XG4gICAgICAgIHJldHVybiBleF9yZXN1bHQ7XG4gICAgICB9IGNhdGNoIChleCkge1xuICAgICAgICBpZiAoZXggaW5zdGFuY2VvZiBQYXR0ZXJucy5NYXRjaEVycm9yKSB7XG4gICAgICAgICAgdGhyb3cgZXg7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9XG5cbiAgICBpZiAoY2F0Y2hfZnVuKSB7XG4gICAgICB0cnkge1xuICAgICAgICBleF9yZXN1bHQgPSBjYXRjaF9mdW4oZSk7XG4gICAgICAgIHJldHVybiBleF9yZXN1bHQ7XG4gICAgICB9IGNhdGNoIChleCkge1xuICAgICAgICBpZiAoZXggaW5zdGFuY2VvZiBQYXR0ZXJucy5NYXRjaEVycm9yKSB7XG4gICAgICAgICAgdGhyb3cgZXg7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9XG5cbiAgICB0aHJvdyBlO1xuICB9IGZpbmFsbHkge1xuICAgIGlmIChhZnRlcl9mdW5jdGlvbikge1xuICAgICAgYWZ0ZXJfZnVuY3Rpb24oKTtcbiAgICB9XG4gIH1cblxuICBpZiAoZWxzZV9mdW5jdGlvbikge1xuICAgIHRyeSB7XG4gICAgICByZXR1cm4gZWxzZV9mdW5jdGlvbihyZXN1bHQpO1xuICAgIH0gY2F0Y2ggKGV4KSB7XG4gICAgICBpZiAoZXggaW5zdGFuY2VvZiBQYXR0ZXJucy5NYXRjaEVycm9yKSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcignTm8gTWF0Y2ggRm91bmQgaW4gRWxzZScpO1xuICAgICAgfVxuXG4gICAgICB0aHJvdyBleDtcbiAgICB9XG4gIH0gZWxzZSB7XG4gICAgcmV0dXJuIHJlc3VsdDtcbiAgfVxufVxuXG52YXIgc3BlY2lhbF9mb3JtcyA9IHtcbiAgX2Nhc2UsXG4gIGNvbmQsXG4gIG1hcF91cGRhdGUsXG4gIF9mb3IsXG4gIF90cnlcbn07XG5cbkZ1bmN0aW9ucy5nZXRfZ2xvYmFsKCkucHJvY2Vzc2VzID0gRnVuY3Rpb25zLmdldF9nbG9iYWwoKS5wcm9jZXNzZXMgfHwgbmV3IFByb2Nlc3NTeXN0ZW0oKTtcblxuXG5cbnZhciBDID0gT2JqZWN0LmZyZWV6ZSh7XG5cdFByb2Nlc3NTeXN0ZW06IFByb2Nlc3NTeXN0ZW0sXG5cdFR1cGxlOiBUdXBsZSxcblx0UElEOiBQSUQsXG5cdEJpdFN0cmluZzogQml0U3RyaW5nLFxuXHRQYXR0ZXJuczogUGF0dGVybnMsXG5cdEludGVnZXI6IEludGVnZXIsXG5cdEZsb2F0OiBGbG9hdCxcblx0RnVuY3Rpb25zOiBGdW5jdGlvbnMsXG5cdFNwZWNpYWxGb3Jtczogc3BlY2lhbF9mb3Jtc1xufSk7XG5cbmxldCBFbnVtID0ge1xuXG4gIGFsbF9fcW1hcmtfXzogZnVuY3Rpb24gKGNvbGxlY3Rpb24sIGZ1biA9IHggPT4geCkge1xuICAgIGZvciAobGV0IGVsZW0gb2YgY29sbGVjdGlvbikge1xuICAgICAgaWYgKCFmdW4oZWxlbSkpIHtcbiAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgfVxuICAgIH1cblxuICAgIHJldHVybiB0cnVlO1xuICB9LFxuXG4gIGFueV9fcW1hcmtfXzogZnVuY3Rpb24gKGNvbGxlY3Rpb24sIGZ1biA9IHggPT4geCkge1xuICAgIGZvciAobGV0IGVsZW0gb2YgY29sbGVjdGlvbikge1xuICAgICAgaWYgKGZ1bihlbGVtKSkge1xuICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICByZXR1cm4gZmFsc2U7XG4gIH0sXG5cbiAgYXQ6IGZ1bmN0aW9uIChjb2xsZWN0aW9uLCBuLCB0aGVfZGVmYXVsdCA9IG51bGwpIHtcbiAgICBpZiAobiA+IHRoaXMuY291bnQoY29sbGVjdGlvbikgfHwgbiA8IDApIHtcbiAgICAgIHJldHVybiB0aGVfZGVmYXVsdDtcbiAgICB9XG5cbiAgICByZXR1cm4gY29sbGVjdGlvbltuXTtcbiAgfSxcblxuICBjb25jYXQ6IGZ1bmN0aW9uICguLi5lbnVtYWJsZXMpIHtcbiAgICByZXR1cm4gZW51bWFibGVzWzBdLmNvbmNhdChlbnVtYWJsZXNbMV0pO1xuICB9LFxuXG4gIGNvdW50OiBmdW5jdGlvbiAoY29sbGVjdGlvbiwgZnVuID0gbnVsbCkge1xuICAgIGlmIChmdW4gPT0gbnVsbCkge1xuICAgICAgcmV0dXJuIGNvbGxlY3Rpb24ubGVuZ3RoO1xuICAgIH0gZWxzZSB7XG4gICAgICByZXR1cm4gY29sbGVjdGlvbi5maWx0ZXIoZnVuKS5sZW5ndGg7XG4gICAgfVxuICB9LFxuXG4gIGRyb3A6IGZ1bmN0aW9uIChjb2xsZWN0aW9uLCBjb3VudCkge1xuICAgIHJldHVybiBjb2xsZWN0aW9uLnNsaWNlKGNvdW50KTtcbiAgfSxcblxuICBkcm9wX3doaWxlOiBmdW5jdGlvbiAoY29sbGVjdGlvbiwgZnVuKSB7XG4gICAgbGV0IGNvdW50ID0gMDtcblxuICAgIGZvciAobGV0IGVsZW0gb2YgY29sbGVjdGlvbikge1xuICAgICAgaWYgKGZ1bihlbGVtKSkge1xuICAgICAgICBjb3VudCA9IGNvdW50ICsgMTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIGJyZWFrO1xuICAgICAgfVxuICAgIH1cblxuICAgIHJldHVybiBjb2xsZWN0aW9uLnNsaWNlKGNvdW50KTtcbiAgfSxcblxuICBlYWNoOiBmdW5jdGlvbiAoY29sbGVjdGlvbiwgZnVuKSB7XG4gICAgZm9yIChsZXQgZWxlbSBvZiBjb2xsZWN0aW9uKSB7XG4gICAgICBmdW4oZWxlbSk7XG4gICAgfVxuICB9LFxuXG4gIGVtcHR5X19xbWFya19fOiBmdW5jdGlvbiAoY29sbGVjdGlvbikge1xuICAgIHJldHVybiBjb2xsZWN0aW9uLmxlbmd0aCA9PT0gMDtcbiAgfSxcblxuICBmZXRjaDogZnVuY3Rpb24gKGNvbGxlY3Rpb24sIG4pIHtcbiAgICBpZiAoQXJyYXkuaXNBcnJheShjb2xsZWN0aW9uKSkge1xuICAgICAgaWYgKG4gPCB0aGlzLmNvdW50KGNvbGxlY3Rpb24pICYmIG4gPj0gMCkge1xuICAgICAgICByZXR1cm4gbmV3IFR1cGxlKFN5bWJvbC5mb3IoXCJva1wiKSwgY29sbGVjdGlvbltuXSk7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICByZXR1cm4gU3ltYm9sLmZvcihcImVycm9yXCIpO1xuICAgICAgfVxuICAgIH1cblxuICAgIHRocm93IG5ldyBFcnJvcihcImNvbGxlY3Rpb24gaXMgbm90IGFuIEVudW1lcmFibGVcIik7XG4gIH0sXG5cbiAgZmV0Y2hfX2VtYXJrX186IGZ1bmN0aW9uIChjb2xsZWN0aW9uLCBuKSB7XG4gICAgaWYgKEFycmF5LmlzQXJyYXkoY29sbGVjdGlvbikpIHtcbiAgICAgIGlmIChuIDwgdGhpcy5jb3VudChjb2xsZWN0aW9uKSAmJiBuID49IDApIHtcbiAgICAgICAgcmV0dXJuIGNvbGxlY3Rpb25bbl07XG4gICAgICB9IGVsc2Uge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoXCJvdXQgb2YgYm91bmRzIGVycm9yXCIpO1xuICAgICAgfVxuICAgIH1cblxuICAgIHRocm93IG5ldyBFcnJvcihcImNvbGxlY3Rpb24gaXMgbm90IGFuIEVudW1lcmFibGVcIik7XG4gIH0sXG5cbiAgZmlsdGVyOiBmdW5jdGlvbiAoY29sbGVjdGlvbiwgZnVuKSB7XG4gICAgbGV0IHJlc3VsdCA9IFtdO1xuXG4gICAgZm9yIChsZXQgZWxlbSBvZiBjb2xsZWN0aW9uKSB7XG4gICAgICBpZiAoZnVuKGVsZW0pKSB7XG4gICAgICAgIHJlc3VsdC5wdXNoKGVsZW0pO1xuICAgICAgfVxuICAgIH1cblxuICAgIHJldHVybiByZXN1bHQ7XG4gIH0sXG5cbiAgZmlsdGVyX21hcDogZnVuY3Rpb24gKGNvbGxlY3Rpb24sIGZpbHRlciwgbWFwcGVyKSB7XG4gICAgcmV0dXJuIEVudW0ubWFwKEVudW0uZmlsdGVyKGNvbGxlY3Rpb24sIGZpbHRlciksIG1hcHBlcik7XG4gIH0sXG5cbiAgZmluZDogZnVuY3Rpb24gKGNvbGxlY3Rpb24sIGlmX25vbmUgPSBudWxsLCBmdW4pIHtcbiAgICBmb3IgKGxldCBlbGVtIG9mIGNvbGxlY3Rpb24pIHtcbiAgICAgIGlmIChmdW4oZWxlbSkpIHtcbiAgICAgICAgcmV0dXJuIGVsZW07XG4gICAgICB9XG4gICAgfVxuXG4gICAgcmV0dXJuIGlmX25vbmU7XG4gIH0sXG5cbiAgaW50bzogZnVuY3Rpb24gKGNvbGxlY3Rpb24sIGxpc3QpIHtcbiAgICByZXR1cm4gbGlzdC5jb25jYXQoY29sbGVjdGlvbik7XG4gIH0sXG5cbiAgbWFwOiBmdW5jdGlvbiAoY29sbGVjdGlvbiwgZnVuKSB7XG4gICAgbGV0IHJlc3VsdCA9IFtdO1xuXG4gICAgZm9yIChsZXQgZWxlbSBvZiBjb2xsZWN0aW9uKSB7XG4gICAgICByZXN1bHQucHVzaChmdW4oZWxlbSkpO1xuICAgIH1cblxuICAgIHJldHVybiByZXN1bHQ7XG4gIH0sXG5cbiAgbWFwX3JlZHVjZTogZnVuY3Rpb24gKGNvbGxlY3Rpb24sIGFjYywgZnVuKSB7XG4gICAgbGV0IG1hcHBlZCA9IE9iamVjdC5mcmVlemUoW10pO1xuICAgIGxldCB0aGVfYWNjID0gYWNjO1xuXG4gICAgZm9yICh2YXIgaSA9IDA7IGkgPCB0aGlzLmNvdW50KGNvbGxlY3Rpb24pOyBpKyspIHtcbiAgICAgIGxldCB0dXBsZSA9IGZ1bihjb2xsZWN0aW9uW2ldLCB0aGVfYWNjKTtcblxuICAgICAgdGhlX2FjYyA9IHR1cGxlLmdldCgxKTtcbiAgICAgIG1hcHBlZCA9IE9iamVjdC5mcmVlemUobWFwcGVkLmNvbmNhdChbdHVwbGUuZ2V0KDApXSkpO1xuICAgIH1cblxuICAgIHJldHVybiBuZXcgVHVwbGUobWFwcGVkLCB0aGVfYWNjKTtcbiAgfSxcblxuICBtZW1iZXJfX3FtYXJrX186IGZ1bmN0aW9uIChjb2xsZWN0aW9uLCB2YWx1ZSkge1xuICAgIHJldHVybiBjb2xsZWN0aW9uLmluY2x1ZGVzKHZhbHVlKTtcbiAgfSxcblxuICByZWR1Y2U6IGZ1bmN0aW9uIChjb2xsZWN0aW9uLCBhY2MsIGZ1bikge1xuICAgIGxldCB0aGVfYWNjID0gYWNjO1xuXG4gICAgZm9yICh2YXIgaSA9IDA7IGkgPCB0aGlzLmNvdW50KGNvbGxlY3Rpb24pOyBpKyspIHtcbiAgICAgIGxldCB0dXBsZSA9IGZ1bihjb2xsZWN0aW9uW2ldLCB0aGVfYWNjKTtcblxuICAgICAgdGhlX2FjYyA9IHR1cGxlLmdldCgxKTtcbiAgICB9XG5cbiAgICByZXR1cm4gdGhlX2FjYztcbiAgfSxcblxuICB0YWtlOiBmdW5jdGlvbiAoY29sbGVjdGlvbiwgY291bnQpIHtcbiAgICByZXR1cm4gY29sbGVjdGlvbi5zbGljZSgwLCBjb3VudCk7XG4gIH0sXG5cbiAgdGFrZV9ldmVyeTogZnVuY3Rpb24gKGNvbGxlY3Rpb24sIG50aCkge1xuICAgIGxldCByZXN1bHQgPSBbXTtcbiAgICBsZXQgaW5kZXggPSAwO1xuXG4gICAgZm9yIChsZXQgZWxlbSBvZiBjb2xsZWN0aW9uKSB7XG4gICAgICBpZiAoaW5kZXggJSBudGggPT09IDApIHtcbiAgICAgICAgcmVzdWx0LnB1c2goZWxlbSk7XG4gICAgICB9XG4gICAgfVxuXG4gICAgcmV0dXJuIE9iamVjdC5mcmVlemUocmVzdWx0KTtcbiAgfSxcblxuICB0YWtlX3doaWxlOiBmdW5jdGlvbiAoY29sbGVjdGlvbiwgZnVuKSB7XG4gICAgbGV0IGNvdW50ID0gMDtcblxuICAgIGZvciAobGV0IGVsZW0gb2YgY29sbGVjdGlvbikge1xuICAgICAgaWYgKGZ1bihlbGVtKSkge1xuICAgICAgICBjb3VudCA9IGNvdW50ICsgMTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIGJyZWFrO1xuICAgICAgfVxuICAgIH1cblxuICAgIHJldHVybiBjb2xsZWN0aW9uLnNsaWNlKDAsIGNvdW50KTtcbiAgfSxcblxuICB0b19saXN0OiBmdW5jdGlvbiAoY29sbGVjdGlvbikge1xuICAgIHJldHVybiBjb2xsZWN0aW9uO1xuICB9XG59O1xuXG5sZXQgVmlydHVhbERPTSA9IChmdW5jdGlvbiAoZSkge1xuICAgIHJldHVybiBlKCk7XG59KShmdW5jdGlvbiAoKSB7XG4gICAgdmFyIGRlZmluZSwgbW9kdWxlLCBleHBvcnRzO1xuICAgIHJldHVybiAoZnVuY3Rpb24gZSh0LCBuLCByKSB7XG4gICAgICAgIGZ1bmN0aW9uIHMobywgdSkge1xuICAgICAgICAgICAgaWYgKCFuW29dKSB7XG4gICAgICAgICAgICAgICAgaWYgKCF0W29dKSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciBhID0gdHlwZW9mIHJlcXVpcmUgPT0gXCJmdW5jdGlvblwiICYmIHJlcXVpcmU7XG4gICAgICAgICAgICAgICAgICAgIGlmICghdSAmJiBhKSByZXR1cm4gYShvLCAhMCk7XG4gICAgICAgICAgICAgICAgICAgIGlmIChpKSByZXR1cm4gaShvLCAhMCk7XG4gICAgICAgICAgICAgICAgICAgIHZhciBmID0gbmV3IEVycm9yKFwiQ2Fubm90IGZpbmQgbW9kdWxlICdcIiArIG8gKyBcIidcIik7XG4gICAgICAgICAgICAgICAgICAgIHRocm93IChmLmNvZGUgPSBcIk1PRFVMRV9OT1RfRk9VTkRcIiwgZik7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHZhciBsID0gbltvXSA9IHtcbiAgICAgICAgICAgICAgICAgICAgZXhwb3J0czoge31cbiAgICAgICAgICAgICAgICB9O1xuICAgICAgICAgICAgICAgIHRbb11bMF0uY2FsbChsLmV4cG9ydHMsIGZ1bmN0aW9uIChlKSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciBuID0gdFtvXVsxXVtlXTtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHMobiA/IG4gOiBlKTtcbiAgICAgICAgICAgICAgICB9LCBsLCBsLmV4cG9ydHMsIGUsIHQsIG4sIHIpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmV0dXJuIG5bb10uZXhwb3J0cztcbiAgICAgICAgfVxuICAgICAgICB2YXIgaSA9IHR5cGVvZiByZXF1aXJlID09IFwiZnVuY3Rpb25cIiAmJiByZXF1aXJlO1xuICAgICAgICBmb3IgKHZhciBvID0gMDsgbyA8IHIubGVuZ3RoOyBvKyspIHMocltvXSk7XG4gICAgICAgIHJldHVybiBzO1xuICAgIH0pKHtcbiAgICAgICAgMTogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHtcblxuICAgICAgICAgICAgdmFyIGNyZWF0ZUVsZW1lbnQgPSByZXF1aXJlKFwiLi92ZG9tL2NyZWF0ZS1lbGVtZW50LmpzXCIpO1xuXG4gICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IGNyZWF0ZUVsZW1lbnQ7XG4gICAgICAgIH0sIHsgXCIuL3Zkb20vY3JlYXRlLWVsZW1lbnQuanNcIjogMTUgfV0sIDI6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICB2YXIgZGlmZiA9IHJlcXVpcmUoXCIuL3Z0cmVlL2RpZmYuanNcIik7XG5cbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gZGlmZjtcbiAgICAgICAgfSwgeyBcIi4vdnRyZWUvZGlmZi5qc1wiOiAzNSB9XSwgMzogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHtcbiAgICAgICAgICAgIHZhciBoID0gcmVxdWlyZShcIi4vdmlydHVhbC1oeXBlcnNjcmlwdC9pbmRleC5qc1wiKTtcblxuICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBoO1xuICAgICAgICB9LCB7IFwiLi92aXJ0dWFsLWh5cGVyc2NyaXB0L2luZGV4LmpzXCI6IDIyIH1dLCA0OiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge1xuICAgICAgICAgICAgdmFyIGRpZmYgPSByZXF1aXJlKFwiLi9kaWZmLmpzXCIpO1xuICAgICAgICAgICAgdmFyIHBhdGNoID0gcmVxdWlyZShcIi4vcGF0Y2guanNcIik7XG4gICAgICAgICAgICB2YXIgaCA9IHJlcXVpcmUoXCIuL2guanNcIik7XG4gICAgICAgICAgICB2YXIgY3JlYXRlID0gcmVxdWlyZShcIi4vY3JlYXRlLWVsZW1lbnQuanNcIik7XG4gICAgICAgICAgICB2YXIgVk5vZGUgPSByZXF1aXJlKFwiLi92bm9kZS92bm9kZS5qc1wiKTtcbiAgICAgICAgICAgIHZhciBWVGV4dCA9IHJlcXVpcmUoXCIuL3Zub2RlL3Z0ZXh0LmpzXCIpO1xuXG4gICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IHtcbiAgICAgICAgICAgICAgICBkaWZmOiBkaWZmLFxuICAgICAgICAgICAgICAgIHBhdGNoOiBwYXRjaCxcbiAgICAgICAgICAgICAgICBoOiBoLFxuICAgICAgICAgICAgICAgIGNyZWF0ZTogY3JlYXRlLFxuICAgICAgICAgICAgICAgIFZOb2RlOiBWTm9kZSxcbiAgICAgICAgICAgICAgICBWVGV4dDogVlRleHRcbiAgICAgICAgICAgIH07XG4gICAgICAgIH0sIHsgXCIuL2NyZWF0ZS1lbGVtZW50LmpzXCI6IDEsIFwiLi9kaWZmLmpzXCI6IDIsIFwiLi9oLmpzXCI6IDMsIFwiLi9wYXRjaC5qc1wiOiAxMywgXCIuL3Zub2RlL3Zub2RlLmpzXCI6IDMxLCBcIi4vdm5vZGUvdnRleHQuanNcIjogMzMgfV0sIDU6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICAvKiFcbiAgICAgICAgICAgICAqIENyb3NzLUJyb3dzZXIgU3BsaXQgMS4xLjFcbiAgICAgICAgICAgICAqIENvcHlyaWdodCAyMDA3LTIwMTIgU3RldmVuIExldml0aGFuIDxzdGV2ZW5sZXZpdGhhbi5jb20+XG4gICAgICAgICAgICAgKiBBdmFpbGFibGUgdW5kZXIgdGhlIE1JVCBMaWNlbnNlXG4gICAgICAgICAgICAgKiBFQ01BU2NyaXB0IGNvbXBsaWFudCwgdW5pZm9ybSBjcm9zcy1icm93c2VyIHNwbGl0IG1ldGhvZFxuICAgICAgICAgICAgICovXG5cbiAgICAgICAgICAgIC8qKlxuICAgICAgICAgICAgICogU3BsaXRzIGEgc3RyaW5nIGludG8gYW4gYXJyYXkgb2Ygc3RyaW5ncyB1c2luZyBhIHJlZ2V4IG9yIHN0cmluZyBzZXBhcmF0b3IuIE1hdGNoZXMgb2YgdGhlXG4gICAgICAgICAgICAgKiBzZXBhcmF0b3IgYXJlIG5vdCBpbmNsdWRlZCBpbiB0aGUgcmVzdWx0IGFycmF5LiBIb3dldmVyLCBpZiBgc2VwYXJhdG9yYCBpcyBhIHJlZ2V4IHRoYXQgY29udGFpbnNcbiAgICAgICAgICAgICAqIGNhcHR1cmluZyBncm91cHMsIGJhY2tyZWZlcmVuY2VzIGFyZSBzcGxpY2VkIGludG8gdGhlIHJlc3VsdCBlYWNoIHRpbWUgYHNlcGFyYXRvcmAgaXMgbWF0Y2hlZC5cbiAgICAgICAgICAgICAqIEZpeGVzIGJyb3dzZXIgYnVncyBjb21wYXJlZCB0byB0aGUgbmF0aXZlIGBTdHJpbmcucHJvdG90eXBlLnNwbGl0YCBhbmQgY2FuIGJlIHVzZWQgcmVsaWFibHlcbiAgICAgICAgICAgICAqIGNyb3NzLWJyb3dzZXIuXG4gICAgICAgICAgICAgKiBAcGFyYW0ge1N0cmluZ30gc3RyIFN0cmluZyB0byBzcGxpdC5cbiAgICAgICAgICAgICAqIEBwYXJhbSB7UmVnRXhwfFN0cmluZ30gc2VwYXJhdG9yIFJlZ2V4IG9yIHN0cmluZyB0byB1c2UgZm9yIHNlcGFyYXRpbmcgdGhlIHN0cmluZy5cbiAgICAgICAgICAgICAqIEBwYXJhbSB7TnVtYmVyfSBbbGltaXRdIE1heGltdW0gbnVtYmVyIG9mIGl0ZW1zIHRvIGluY2x1ZGUgaW4gdGhlIHJlc3VsdCBhcnJheS5cbiAgICAgICAgICAgICAqIEByZXR1cm5zIHtBcnJheX0gQXJyYXkgb2Ygc3Vic3RyaW5ncy5cbiAgICAgICAgICAgICAqIEBleGFtcGxlXG4gICAgICAgICAgICAgKlxuICAgICAgICAgICAgICogLy8gQmFzaWMgdXNlXG4gICAgICAgICAgICAgKiBzcGxpdCgnYSBiIGMgZCcsICcgJyk7XG4gICAgICAgICAgICAgKiAvLyAtPiBbJ2EnLCAnYicsICdjJywgJ2QnXVxuICAgICAgICAgICAgICpcbiAgICAgICAgICAgICAqIC8vIFdpdGggbGltaXRcbiAgICAgICAgICAgICAqIHNwbGl0KCdhIGIgYyBkJywgJyAnLCAyKTtcbiAgICAgICAgICAgICAqIC8vIC0+IFsnYScsICdiJ11cbiAgICAgICAgICAgICAqXG4gICAgICAgICAgICAgKiAvLyBCYWNrcmVmZXJlbmNlcyBpbiByZXN1bHQgYXJyYXlcbiAgICAgICAgICAgICAqIHNwbGl0KCcuLndvcmQxIHdvcmQyLi4nLCAvKFthLXpdKykoXFxkKykvaSk7XG4gICAgICAgICAgICAgKiAvLyAtPiBbJy4uJywgJ3dvcmQnLCAnMScsICcgJywgJ3dvcmQnLCAnMicsICcuLiddXG4gICAgICAgICAgICAgKi9cbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gKGZ1bmN0aW9uIHNwbGl0KHVuZGVmKSB7XG5cbiAgICAgICAgICAgICAgICB2YXIgbmF0aXZlU3BsaXQgPSBTdHJpbmcucHJvdG90eXBlLnNwbGl0LFxuICAgICAgICAgICAgICAgICAgICBjb21wbGlhbnRFeGVjTnBjZyA9IC8oKT8/Ly5leGVjKFwiXCIpWzFdID09PSB1bmRlZixcblxuICAgICAgICAgICAgICAgIC8vIE5QQ0c6IG5vbnBhcnRpY2lwYXRpbmcgY2FwdHVyaW5nIGdyb3VwXG4gICAgICAgICAgICAgICAgc2VsZjtcblxuICAgICAgICAgICAgICAgIHNlbGYgPSBmdW5jdGlvbiAoc3RyLCBzZXBhcmF0b3IsIGxpbWl0KSB7XG4gICAgICAgICAgICAgICAgICAgIC8vIElmIGBzZXBhcmF0b3JgIGlzIG5vdCBhIHJlZ2V4LCB1c2UgYG5hdGl2ZVNwbGl0YFxuICAgICAgICAgICAgICAgICAgICBpZiAoT2JqZWN0LnByb3RvdHlwZS50b1N0cmluZy5jYWxsKHNlcGFyYXRvcikgIT09IFwiW29iamVjdCBSZWdFeHBdXCIpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBuYXRpdmVTcGxpdC5jYWxsKHN0ciwgc2VwYXJhdG9yLCBsaW1pdCk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgdmFyIG91dHB1dCA9IFtdLFxuICAgICAgICAgICAgICAgICAgICAgICAgZmxhZ3MgPSAoc2VwYXJhdG9yLmlnbm9yZUNhc2UgPyBcImlcIiA6IFwiXCIpICsgKHNlcGFyYXRvci5tdWx0aWxpbmUgPyBcIm1cIiA6IFwiXCIpICsgKHNlcGFyYXRvci5leHRlbmRlZCA/IFwieFwiIDogXCJcIikgKyAoc2VwYXJhdG9yLnN0aWNreSA/IFwieVwiIDogXCJcIiksXG5cbiAgICAgICAgICAgICAgICAgICAgLy8gRmlyZWZveCAzK1xuICAgICAgICAgICAgICAgICAgICBsYXN0TGFzdEluZGV4ID0gMCxcblxuICAgICAgICAgICAgICAgICAgICAvLyBNYWtlIGBnbG9iYWxgIGFuZCBhdm9pZCBgbGFzdEluZGV4YCBpc3N1ZXMgYnkgd29ya2luZyB3aXRoIGEgY29weVxuICAgICAgICAgICAgICAgICAgICBzZXBhcmF0b3IgPSBuZXcgUmVnRXhwKHNlcGFyYXRvci5zb3VyY2UsIGZsYWdzICsgXCJnXCIpLFxuICAgICAgICAgICAgICAgICAgICAgICAgc2VwYXJhdG9yMixcbiAgICAgICAgICAgICAgICAgICAgICAgIG1hdGNoLFxuICAgICAgICAgICAgICAgICAgICAgICAgbGFzdEluZGV4LFxuICAgICAgICAgICAgICAgICAgICAgICAgbGFzdExlbmd0aDtcbiAgICAgICAgICAgICAgICAgICAgc3RyICs9IFwiXCI7IC8vIFR5cGUtY29udmVydFxuICAgICAgICAgICAgICAgICAgICBpZiAoIWNvbXBsaWFudEV4ZWNOcGNnKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAvLyBEb2Vzbid0IG5lZWQgZmxhZ3MgZ3ksIGJ1dCB0aGV5IGRvbid0IGh1cnRcbiAgICAgICAgICAgICAgICAgICAgICAgIHNlcGFyYXRvcjIgPSBuZXcgUmVnRXhwKFwiXlwiICsgc2VwYXJhdG9yLnNvdXJjZSArIFwiJCg/IVxcXFxzKVwiLCBmbGFncyk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgLyogVmFsdWVzIGZvciBgbGltaXRgLCBwZXIgdGhlIHNwZWM6XG4gICAgICAgICAgICAgICAgICAgICAqIElmIHVuZGVmaW5lZDogNDI5NDk2NzI5NSAvLyBNYXRoLnBvdygyLCAzMikgLSAxXG4gICAgICAgICAgICAgICAgICAgICAqIElmIDAsIEluZmluaXR5LCBvciBOYU46IDBcbiAgICAgICAgICAgICAgICAgICAgICogSWYgcG9zaXRpdmUgbnVtYmVyOiBsaW1pdCA9IE1hdGguZmxvb3IobGltaXQpOyBpZiAobGltaXQgPiA0Mjk0OTY3Mjk1KSBsaW1pdCAtPSA0Mjk0OTY3Mjk2O1xuICAgICAgICAgICAgICAgICAgICAgKiBJZiBuZWdhdGl2ZSBudW1iZXI6IDQyOTQ5NjcyOTYgLSBNYXRoLmZsb29yKE1hdGguYWJzKGxpbWl0KSlcbiAgICAgICAgICAgICAgICAgICAgICogSWYgb3RoZXI6IFR5cGUtY29udmVydCwgdGhlbiB1c2UgdGhlIGFib3ZlIHJ1bGVzXG4gICAgICAgICAgICAgICAgICAgICAqL1xuICAgICAgICAgICAgICAgICAgICBsaW1pdCA9IGxpbWl0ID09PSB1bmRlZiA/IC0xID4+PiAwIDogLy8gTWF0aC5wb3coMiwgMzIpIC0gMVxuICAgICAgICAgICAgICAgICAgICBsaW1pdCA+Pj4gMDsgLy8gVG9VaW50MzIobGltaXQpXG4gICAgICAgICAgICAgICAgICAgIHdoaWxlIChtYXRjaCA9IHNlcGFyYXRvci5leGVjKHN0cikpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIGBzZXBhcmF0b3IubGFzdEluZGV4YCBpcyBub3QgcmVsaWFibGUgY3Jvc3MtYnJvd3NlclxuICAgICAgICAgICAgICAgICAgICAgICAgbGFzdEluZGV4ID0gbWF0Y2guaW5kZXggKyBtYXRjaFswXS5sZW5ndGg7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAobGFzdEluZGV4ID4gbGFzdExhc3RJbmRleCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIG91dHB1dC5wdXNoKHN0ci5zbGljZShsYXN0TGFzdEluZGV4LCBtYXRjaC5pbmRleCkpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIEZpeCBicm93c2VycyB3aG9zZSBgZXhlY2AgbWV0aG9kcyBkb24ndCBjb25zaXN0ZW50bHkgcmV0dXJuIGB1bmRlZmluZWRgIGZvclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIG5vbnBhcnRpY2lwYXRpbmcgY2FwdHVyaW5nIGdyb3Vwc1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmICghY29tcGxpYW50RXhlY05wY2cgJiYgbWF0Y2gubGVuZ3RoID4gMSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBtYXRjaFswXS5yZXBsYWNlKHNlcGFyYXRvcjIsIGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZvciAodmFyIGkgPSAxOyBpIDwgYXJndW1lbnRzLmxlbmd0aCAtIDI7IGkrKykge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChhcmd1bWVudHNbaV0gPT09IHVuZGVmKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1hdGNoW2ldID0gdW5kZWY7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKG1hdGNoLmxlbmd0aCA+IDEgJiYgbWF0Y2guaW5kZXggPCBzdHIubGVuZ3RoKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIEFycmF5LnByb3RvdHlwZS5wdXNoLmFwcGx5KG91dHB1dCwgbWF0Y2guc2xpY2UoMSkpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBsYXN0TGVuZ3RoID0gbWF0Y2hbMF0ubGVuZ3RoO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxhc3RMYXN0SW5kZXggPSBsYXN0SW5kZXg7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKG91dHB1dC5sZW5ndGggPj0gbGltaXQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHNlcGFyYXRvci5sYXN0SW5kZXggPT09IG1hdGNoLmluZGV4KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgc2VwYXJhdG9yLmxhc3RJbmRleCsrOyAvLyBBdm9pZCBhbiBpbmZpbml0ZSBsb29wXG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgaWYgKGxhc3RMYXN0SW5kZXggPT09IHN0ci5sZW5ndGgpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChsYXN0TGVuZ3RoIHx8ICFzZXBhcmF0b3IudGVzdChcIlwiKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIG91dHB1dC5wdXNoKFwiXCIpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgb3V0cHV0LnB1c2goc3RyLnNsaWNlKGxhc3RMYXN0SW5kZXgpKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICByZXR1cm4gb3V0cHV0Lmxlbmd0aCA+IGxpbWl0ID8gb3V0cHV0LnNsaWNlKDAsIGxpbWl0KSA6IG91dHB1dDtcbiAgICAgICAgICAgICAgICB9O1xuXG4gICAgICAgICAgICAgICAgcmV0dXJuIHNlbGY7XG4gICAgICAgICAgICB9KSgpO1xuICAgICAgICB9LCB7fV0sIDY6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7fSwge31dLCA3OiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge1xuICAgICAgICAgICAgXCJ1c2Ugc3RyaWN0XCI7XG5cbiAgICAgICAgICAgIHZhciBPbmVWZXJzaW9uQ29uc3RyYWludCA9IHJlcXVpcmUoXCJpbmRpdmlkdWFsL29uZS12ZXJzaW9uXCIpO1xuXG4gICAgICAgICAgICB2YXIgTVlfVkVSU0lPTiA9IFwiN1wiO1xuICAgICAgICAgICAgT25lVmVyc2lvbkNvbnN0cmFpbnQoXCJldi1zdG9yZVwiLCBNWV9WRVJTSU9OKTtcblxuICAgICAgICAgICAgdmFyIGhhc2hLZXkgPSBcIl9fRVZfU1RPUkVfS0VZQFwiICsgTVlfVkVSU0lPTjtcblxuICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBFdlN0b3JlO1xuXG4gICAgICAgICAgICBmdW5jdGlvbiBFdlN0b3JlKGVsZW0pIHtcbiAgICAgICAgICAgICAgICB2YXIgaGFzaCA9IGVsZW1baGFzaEtleV07XG5cbiAgICAgICAgICAgICAgICBpZiAoIWhhc2gpIHtcbiAgICAgICAgICAgICAgICAgICAgaGFzaCA9IGVsZW1baGFzaEtleV0gPSB7fTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICByZXR1cm4gaGFzaDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSwgeyBcImluZGl2aWR1YWwvb25lLXZlcnNpb25cIjogOSB9XSwgODogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHtcbiAgICAgICAgICAgIChmdW5jdGlvbiAoZ2xvYmFsKSB7XG4gICAgICAgICAgICAgICAgXCJ1c2Ugc3RyaWN0XCI7XG5cbiAgICAgICAgICAgICAgICAvKmdsb2JhbCB3aW5kb3csIGdsb2JhbCovXG5cbiAgICAgICAgICAgICAgICB2YXIgcm9vdCA9IHR5cGVvZiB3aW5kb3cgIT09IFwidW5kZWZpbmVkXCIgPyB3aW5kb3cgOiB0eXBlb2YgZ2xvYmFsICE9PSBcInVuZGVmaW5lZFwiID8gZ2xvYmFsIDoge307XG5cbiAgICAgICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IEluZGl2aWR1YWw7XG5cbiAgICAgICAgICAgICAgICBmdW5jdGlvbiBJbmRpdmlkdWFsKGtleSwgdmFsdWUpIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKGtleSBpbiByb290KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gcm9vdFtrZXldO1xuICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgcm9vdFtrZXldID0gdmFsdWU7XG5cbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHZhbHVlO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0pLmNhbGwodGhpcywgdHlwZW9mIGdsb2JhbCAhPT0gXCJ1bmRlZmluZWRcIiA/IGdsb2JhbCA6IHR5cGVvZiBzZWxmICE9PSBcInVuZGVmaW5lZFwiID8gc2VsZiA6IHR5cGVvZiB3aW5kb3cgIT09IFwidW5kZWZpbmVkXCIgPyB3aW5kb3cgOiB7fSk7XG4gICAgICAgIH0sIHt9XSwgOTogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHtcbiAgICAgICAgICAgIFwidXNlIHN0cmljdFwiO1xuXG4gICAgICAgICAgICB2YXIgSW5kaXZpZHVhbCA9IHJlcXVpcmUoXCIuL2luZGV4LmpzXCIpO1xuXG4gICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IE9uZVZlcnNpb247XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIE9uZVZlcnNpb24obW9kdWxlTmFtZSwgdmVyc2lvbiwgZGVmYXVsdFZhbHVlKSB7XG4gICAgICAgICAgICAgICAgdmFyIGtleSA9IFwiX19JTkRJVklEVUFMX09ORV9WRVJTSU9OX1wiICsgbW9kdWxlTmFtZTtcbiAgICAgICAgICAgICAgICB2YXIgZW5mb3JjZUtleSA9IGtleSArIFwiX0VORk9SQ0VfU0lOR0xFVE9OXCI7XG5cbiAgICAgICAgICAgICAgICB2YXIgdmVyc2lvblZhbHVlID0gSW5kaXZpZHVhbChlbmZvcmNlS2V5LCB2ZXJzaW9uKTtcblxuICAgICAgICAgICAgICAgIGlmICh2ZXJzaW9uVmFsdWUgIT09IHZlcnNpb24pIHtcbiAgICAgICAgICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKFwiQ2FuIG9ubHkgaGF2ZSBvbmUgY29weSBvZiBcIiArIG1vZHVsZU5hbWUgKyBcIi5cXG5cIiArIFwiWW91IGFscmVhZHkgaGF2ZSB2ZXJzaW9uIFwiICsgdmVyc2lvblZhbHVlICsgXCIgaW5zdGFsbGVkLlxcblwiICsgXCJUaGlzIG1lYW5zIHlvdSBjYW5ub3QgaW5zdGFsbCB2ZXJzaW9uIFwiICsgdmVyc2lvbik7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgcmV0dXJuIEluZGl2aWR1YWwoa2V5LCBkZWZhdWx0VmFsdWUpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9LCB7IFwiLi9pbmRleC5qc1wiOiA4IH1dLCAxMDogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHtcbiAgICAgICAgICAgIChmdW5jdGlvbiAoZ2xvYmFsKSB7XG4gICAgICAgICAgICAgICAgdmFyIHRvcExldmVsID0gdHlwZW9mIGdsb2JhbCAhPT0gXCJ1bmRlZmluZWRcIiA/IGdsb2JhbCA6IHR5cGVvZiB3aW5kb3cgIT09IFwidW5kZWZpbmVkXCIgPyB3aW5kb3cgOiB7fTtcbiAgICAgICAgICAgICAgICB2YXIgbWluRG9jID0gcmVxdWlyZShcIm1pbi1kb2N1bWVudFwiKTtcblxuICAgICAgICAgICAgICAgIGlmICh0eXBlb2YgZG9jdW1lbnQgIT09IFwidW5kZWZpbmVkXCIpIHtcbiAgICAgICAgICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBkb2N1bWVudDtcbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICB2YXIgZG9jY3kgPSB0b3BMZXZlbFtcIl9fR0xPQkFMX0RPQ1VNRU5UX0NBQ0hFQDRcIl07XG5cbiAgICAgICAgICAgICAgICAgICAgaWYgKCFkb2NjeSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgZG9jY3kgPSB0b3BMZXZlbFtcIl9fR0xPQkFMX0RPQ1VNRU5UX0NBQ0hFQDRcIl0gPSBtaW5Eb2M7XG4gICAgICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IGRvY2N5O1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0pLmNhbGwodGhpcywgdHlwZW9mIGdsb2JhbCAhPT0gXCJ1bmRlZmluZWRcIiA/IGdsb2JhbCA6IHR5cGVvZiBzZWxmICE9PSBcInVuZGVmaW5lZFwiID8gc2VsZiA6IHR5cGVvZiB3aW5kb3cgIT09IFwidW5kZWZpbmVkXCIgPyB3aW5kb3cgOiB7fSk7XG4gICAgICAgIH0sIHsgXCJtaW4tZG9jdW1lbnRcIjogNiB9XSwgMTE6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICBcInVzZSBzdHJpY3RcIjtcblxuICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiBpc09iamVjdCh4KSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHR5cGVvZiB4ID09PSBcIm9iamVjdFwiICYmIHggIT09IG51bGw7XG4gICAgICAgICAgICB9O1xuICAgICAgICB9LCB7fV0sIDEyOiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge1xuICAgICAgICAgICAgdmFyIG5hdGl2ZUlzQXJyYXkgPSBBcnJheS5pc0FycmF5O1xuICAgICAgICAgICAgdmFyIHRvU3RyaW5nID0gT2JqZWN0LnByb3RvdHlwZS50b1N0cmluZztcblxuICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBuYXRpdmVJc0FycmF5IHx8IGlzQXJyYXk7XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIGlzQXJyYXkob2JqKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHRvU3RyaW5nLmNhbGwob2JqKSA9PT0gXCJbb2JqZWN0IEFycmF5XVwiO1xuICAgICAgICAgICAgfVxuICAgICAgICB9LCB7fV0sIDEzOiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge1xuICAgICAgICAgICAgdmFyIHBhdGNoID0gcmVxdWlyZShcIi4vdmRvbS9wYXRjaC5qc1wiKTtcblxuICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBwYXRjaDtcbiAgICAgICAgfSwgeyBcIi4vdmRvbS9wYXRjaC5qc1wiOiAxOCB9XSwgMTQ6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICB2YXIgaXNPYmplY3QgPSByZXF1aXJlKFwiaXMtb2JqZWN0XCIpO1xuICAgICAgICAgICAgdmFyIGlzSG9vayA9IHJlcXVpcmUoXCIuLi92bm9kZS9pcy12aG9vay5qc1wiKTtcblxuICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBhcHBseVByb3BlcnRpZXM7XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIGFwcGx5UHJvcGVydGllcyhub2RlLCBwcm9wcywgcHJldmlvdXMpIHtcbiAgICAgICAgICAgICAgICBmb3IgKHZhciBwcm9wTmFtZSBpbiBwcm9wcykge1xuICAgICAgICAgICAgICAgICAgICB2YXIgcHJvcFZhbHVlID0gcHJvcHNbcHJvcE5hbWVdO1xuXG4gICAgICAgICAgICAgICAgICAgIGlmIChwcm9wVmFsdWUgPT09IHVuZGVmaW5lZCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgcmVtb3ZlUHJvcGVydHkobm9kZSwgcHJvcE5hbWUsIHByb3BWYWx1ZSwgcHJldmlvdXMpO1xuICAgICAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKGlzSG9vayhwcm9wVmFsdWUpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICByZW1vdmVQcm9wZXJ0eShub2RlLCBwcm9wTmFtZSwgcHJvcFZhbHVlLCBwcmV2aW91cyk7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAocHJvcFZhbHVlLmhvb2spIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBwcm9wVmFsdWUuaG9vayhub2RlLCBwcm9wTmFtZSwgcHJldmlvdXMgPyBwcmV2aW91c1twcm9wTmFtZV0gOiB1bmRlZmluZWQpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGlzT2JqZWN0KHByb3BWYWx1ZSkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBwYXRjaE9iamVjdChub2RlLCBwcm9wcywgcHJldmlvdXMsIHByb3BOYW1lLCBwcm9wVmFsdWUpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBub2RlW3Byb3BOYW1lXSA9IHByb3BWYWx1ZTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZnVuY3Rpb24gcmVtb3ZlUHJvcGVydHkobm9kZSwgcHJvcE5hbWUsIHByb3BWYWx1ZSwgcHJldmlvdXMpIHtcbiAgICAgICAgICAgICAgICBpZiAocHJldmlvdXMpIHtcbiAgICAgICAgICAgICAgICAgICAgdmFyIHByZXZpb3VzVmFsdWUgPSBwcmV2aW91c1twcm9wTmFtZV07XG5cbiAgICAgICAgICAgICAgICAgICAgaWYgKCFpc0hvb2socHJldmlvdXNWYWx1ZSkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChwcm9wTmFtZSA9PT0gXCJhdHRyaWJ1dGVzXCIpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBmb3IgKHZhciBhdHRyTmFtZSBpbiBwcmV2aW91c1ZhbHVlKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG5vZGUucmVtb3ZlQXR0cmlidXRlKGF0dHJOYW1lKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKHByb3BOYW1lID09PSBcInN0eWxlXCIpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBmb3IgKHZhciBpIGluIHByZXZpb3VzVmFsdWUpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbm9kZS5zdHlsZVtpXSA9IFwiXCI7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIGlmICh0eXBlb2YgcHJldmlvdXNWYWx1ZSA9PT0gXCJzdHJpbmdcIikge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIG5vZGVbcHJvcE5hbWVdID0gXCJcIjtcbiAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgbm9kZVtwcm9wTmFtZV0gPSBudWxsO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKHByZXZpb3VzVmFsdWUudW5ob29rKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBwcmV2aW91c1ZhbHVlLnVuaG9vayhub2RlLCBwcm9wTmFtZSwgcHJvcFZhbHVlKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZnVuY3Rpb24gcGF0Y2hPYmplY3Qobm9kZSwgcHJvcHMsIHByZXZpb3VzLCBwcm9wTmFtZSwgcHJvcFZhbHVlKSB7XG4gICAgICAgICAgICAgICAgdmFyIHByZXZpb3VzVmFsdWUgPSBwcmV2aW91cyA/IHByZXZpb3VzW3Byb3BOYW1lXSA6IHVuZGVmaW5lZDtcblxuICAgICAgICAgICAgICAgIC8vIFNldCBhdHRyaWJ1dGVzXG4gICAgICAgICAgICAgICAgaWYgKHByb3BOYW1lID09PSBcImF0dHJpYnV0ZXNcIikge1xuICAgICAgICAgICAgICAgICAgICBmb3IgKHZhciBhdHRyTmFtZSBpbiBwcm9wVmFsdWUpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHZhciBhdHRyVmFsdWUgPSBwcm9wVmFsdWVbYXR0ck5hbWVdO1xuXG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoYXR0clZhbHVlID09PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBub2RlLnJlbW92ZUF0dHJpYnV0ZShhdHRyTmFtZSk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIG5vZGUuc2V0QXR0cmlidXRlKGF0dHJOYW1lLCBhdHRyVmFsdWUpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIGlmIChwcmV2aW91c1ZhbHVlICYmIGlzT2JqZWN0KHByZXZpb3VzVmFsdWUpICYmIGdldFByb3RvdHlwZShwcmV2aW91c1ZhbHVlKSAhPT0gZ2V0UHJvdG90eXBlKHByb3BWYWx1ZSkpIHtcbiAgICAgICAgICAgICAgICAgICAgbm9kZVtwcm9wTmFtZV0gPSBwcm9wVmFsdWU7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICBpZiAoIWlzT2JqZWN0KG5vZGVbcHJvcE5hbWVdKSkge1xuICAgICAgICAgICAgICAgICAgICBub2RlW3Byb3BOYW1lXSA9IHt9O1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHZhciByZXBsYWNlciA9IHByb3BOYW1lID09PSBcInN0eWxlXCIgPyBcIlwiIDogdW5kZWZpbmVkO1xuXG4gICAgICAgICAgICAgICAgZm9yICh2YXIgayBpbiBwcm9wVmFsdWUpIHtcbiAgICAgICAgICAgICAgICAgICAgdmFyIHZhbHVlID0gcHJvcFZhbHVlW2tdO1xuICAgICAgICAgICAgICAgICAgICBub2RlW3Byb3BOYW1lXVtrXSA9IHZhbHVlID09PSB1bmRlZmluZWQgPyByZXBsYWNlciA6IHZhbHVlO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZnVuY3Rpb24gZ2V0UHJvdG90eXBlKHZhbHVlKSB7XG4gICAgICAgICAgICAgICAgaWYgKE9iamVjdC5nZXRQcm90b3R5cGVPZikge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gT2JqZWN0LmdldFByb3RvdHlwZU9mKHZhbHVlKTtcbiAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKHZhbHVlLl9fcHJvdG9fXykge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gdmFsdWUuX19wcm90b19fO1xuICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAodmFsdWUuY29uc3RydWN0b3IpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHZhbHVlLmNvbnN0cnVjdG9yLnByb3RvdHlwZTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH0sIHsgXCIuLi92bm9kZS9pcy12aG9vay5qc1wiOiAyNiwgXCJpcy1vYmplY3RcIjogMTEgfV0sIDE1OiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge1xuICAgICAgICAgICAgdmFyIGRvY3VtZW50ID0gcmVxdWlyZShcImdsb2JhbC9kb2N1bWVudFwiKTtcblxuICAgICAgICAgICAgdmFyIGFwcGx5UHJvcGVydGllcyA9IHJlcXVpcmUoXCIuL2FwcGx5LXByb3BlcnRpZXNcIik7XG5cbiAgICAgICAgICAgIHZhciBpc1ZOb2RlID0gcmVxdWlyZShcIi4uL3Zub2RlL2lzLXZub2RlLmpzXCIpO1xuICAgICAgICAgICAgdmFyIGlzVlRleHQgPSByZXF1aXJlKFwiLi4vdm5vZGUvaXMtdnRleHQuanNcIik7XG4gICAgICAgICAgICB2YXIgaXNXaWRnZXQgPSByZXF1aXJlKFwiLi4vdm5vZGUvaXMtd2lkZ2V0LmpzXCIpO1xuICAgICAgICAgICAgdmFyIGhhbmRsZVRodW5rID0gcmVxdWlyZShcIi4uL3Zub2RlL2hhbmRsZS10aHVuay5qc1wiKTtcblxuICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBjcmVhdGVFbGVtZW50O1xuXG4gICAgICAgICAgICBmdW5jdGlvbiBjcmVhdGVFbGVtZW50KHZub2RlLCBvcHRzKSB7XG4gICAgICAgICAgICAgICAgdmFyIGRvYyA9IG9wdHMgPyBvcHRzLmRvY3VtZW50IHx8IGRvY3VtZW50IDogZG9jdW1lbnQ7XG4gICAgICAgICAgICAgICAgdmFyIHdhcm4gPSBvcHRzID8gb3B0cy53YXJuIDogbnVsbDtcblxuICAgICAgICAgICAgICAgIHZub2RlID0gaGFuZGxlVGh1bmsodm5vZGUpLmE7XG5cbiAgICAgICAgICAgICAgICBpZiAoaXNXaWRnZXQodm5vZGUpKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiB2bm9kZS5pbml0KCk7XG4gICAgICAgICAgICAgICAgfSBlbHNlIGlmIChpc1ZUZXh0KHZub2RlKSkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gZG9jLmNyZWF0ZVRleHROb2RlKHZub2RlLnRleHQpO1xuICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoIWlzVk5vZGUodm5vZGUpKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmICh3YXJuKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICB3YXJuKFwiSXRlbSBpcyBub3QgYSB2YWxpZCB2aXJ0dWFsIGRvbSBub2RlXCIsIHZub2RlKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICByZXR1cm4gbnVsbDtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICB2YXIgbm9kZSA9IHZub2RlLm5hbWVzcGFjZSA9PT0gbnVsbCA/IGRvYy5jcmVhdGVFbGVtZW50KHZub2RlLnRhZ05hbWUpIDogZG9jLmNyZWF0ZUVsZW1lbnROUyh2bm9kZS5uYW1lc3BhY2UsIHZub2RlLnRhZ05hbWUpO1xuXG4gICAgICAgICAgICAgICAgdmFyIHByb3BzID0gdm5vZGUucHJvcGVydGllcztcbiAgICAgICAgICAgICAgICBhcHBseVByb3BlcnRpZXMobm9kZSwgcHJvcHMpO1xuXG4gICAgICAgICAgICAgICAgdmFyIGNoaWxkcmVuID0gdm5vZGUuY2hpbGRyZW47XG5cbiAgICAgICAgICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IGNoaWxkcmVuLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciBjaGlsZE5vZGUgPSBjcmVhdGVFbGVtZW50KGNoaWxkcmVuW2ldLCBvcHRzKTtcbiAgICAgICAgICAgICAgICAgICAgaWYgKGNoaWxkTm9kZSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgbm9kZS5hcHBlbmRDaGlsZChjaGlsZE5vZGUpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgcmV0dXJuIG5vZGU7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0sIHsgXCIuLi92bm9kZS9oYW5kbGUtdGh1bmsuanNcIjogMjQsIFwiLi4vdm5vZGUvaXMtdm5vZGUuanNcIjogMjcsIFwiLi4vdm5vZGUvaXMtdnRleHQuanNcIjogMjgsIFwiLi4vdm5vZGUvaXMtd2lkZ2V0LmpzXCI6IDI5LCBcIi4vYXBwbHktcHJvcGVydGllc1wiOiAxNCwgXCJnbG9iYWwvZG9jdW1lbnRcIjogMTAgfV0sIDE2OiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge1xuICAgICAgICAgICAgLy8gTWFwcyBhIHZpcnR1YWwgRE9NIHRyZWUgb250byBhIHJlYWwgRE9NIHRyZWUgaW4gYW4gZWZmaWNpZW50IG1hbm5lci5cbiAgICAgICAgICAgIC8vIFdlIGRvbid0IHdhbnQgdG8gcmVhZCBhbGwgb2YgdGhlIERPTSBub2RlcyBpbiB0aGUgdHJlZSBzbyB3ZSB1c2VcbiAgICAgICAgICAgIC8vIHRoZSBpbi1vcmRlciB0cmVlIGluZGV4aW5nIHRvIGVsaW1pbmF0ZSByZWN1cnNpb24gZG93biBjZXJ0YWluIGJyYW5jaGVzLlxuICAgICAgICAgICAgLy8gV2Ugb25seSByZWN1cnNlIGludG8gYSBET00gbm9kZSBpZiB3ZSBrbm93IHRoYXQgaXQgY29udGFpbnMgYSBjaGlsZCBvZlxuICAgICAgICAgICAgLy8gaW50ZXJlc3QuXG5cbiAgICAgICAgICAgIHZhciBub0NoaWxkID0ge307XG5cbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gZG9tSW5kZXg7XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIGRvbUluZGV4KHJvb3ROb2RlLCB0cmVlLCBpbmRpY2VzLCBub2Rlcykge1xuICAgICAgICAgICAgICAgIGlmICghaW5kaWNlcyB8fCBpbmRpY2VzLmxlbmd0aCA9PT0gMCkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4ge307XG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgaW5kaWNlcy5zb3J0KGFzY2VuZGluZyk7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiByZWN1cnNlKHJvb3ROb2RlLCB0cmVlLCBpbmRpY2VzLCBub2RlcywgMCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBmdW5jdGlvbiByZWN1cnNlKHJvb3ROb2RlLCB0cmVlLCBpbmRpY2VzLCBub2Rlcywgcm9vdEluZGV4KSB7XG4gICAgICAgICAgICAgICAgbm9kZXMgPSBub2RlcyB8fCB7fTtcblxuICAgICAgICAgICAgICAgIGlmIChyb290Tm9kZSkge1xuICAgICAgICAgICAgICAgICAgICBpZiAoaW5kZXhJblJhbmdlKGluZGljZXMsIHJvb3RJbmRleCwgcm9vdEluZGV4KSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgbm9kZXNbcm9vdEluZGV4XSA9IHJvb3ROb2RlO1xuICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgdmFyIHZDaGlsZHJlbiA9IHRyZWUuY2hpbGRyZW47XG5cbiAgICAgICAgICAgICAgICAgICAgaWYgKHZDaGlsZHJlbikge1xuXG4gICAgICAgICAgICAgICAgICAgICAgICB2YXIgY2hpbGROb2RlcyA9IHJvb3ROb2RlLmNoaWxkTm9kZXM7XG5cbiAgICAgICAgICAgICAgICAgICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgdHJlZS5jaGlsZHJlbi5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJvb3RJbmRleCArPSAxO1xuXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdmFyIHZDaGlsZCA9IHZDaGlsZHJlbltpXSB8fCBub0NoaWxkO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZhciBuZXh0SW5kZXggPSByb290SW5kZXggKyAodkNoaWxkLmNvdW50IHx8IDApO1xuXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gc2tpcCByZWN1cnNpb24gZG93biB0aGUgdHJlZSBpZiB0aGVyZSBhcmUgbm8gbm9kZXMgZG93biBoZXJlXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGluZGV4SW5SYW5nZShpbmRpY2VzLCByb290SW5kZXgsIG5leHRJbmRleCkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmVjdXJzZShjaGlsZE5vZGVzW2ldLCB2Q2hpbGQsIGluZGljZXMsIG5vZGVzLCByb290SW5kZXgpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJvb3RJbmRleCA9IG5leHRJbmRleDtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHJldHVybiBub2RlcztcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgLy8gQmluYXJ5IHNlYXJjaCBmb3IgYW4gaW5kZXggaW4gdGhlIGludGVydmFsIFtsZWZ0LCByaWdodF1cbiAgICAgICAgICAgIGZ1bmN0aW9uIGluZGV4SW5SYW5nZShpbmRpY2VzLCBsZWZ0LCByaWdodCkge1xuICAgICAgICAgICAgICAgIGlmIChpbmRpY2VzLmxlbmd0aCA9PT0gMCkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgdmFyIG1pbkluZGV4ID0gMDtcbiAgICAgICAgICAgICAgICB2YXIgbWF4SW5kZXggPSBpbmRpY2VzLmxlbmd0aCAtIDE7XG4gICAgICAgICAgICAgICAgdmFyIGN1cnJlbnRJbmRleDtcbiAgICAgICAgICAgICAgICB2YXIgY3VycmVudEl0ZW07XG5cbiAgICAgICAgICAgICAgICB3aGlsZSAobWluSW5kZXggPD0gbWF4SW5kZXgpIHtcbiAgICAgICAgICAgICAgICAgICAgY3VycmVudEluZGV4ID0gKG1heEluZGV4ICsgbWluSW5kZXgpIC8gMiA+PiAwO1xuICAgICAgICAgICAgICAgICAgICBjdXJyZW50SXRlbSA9IGluZGljZXNbY3VycmVudEluZGV4XTtcblxuICAgICAgICAgICAgICAgICAgICBpZiAobWluSW5kZXggPT09IG1heEluZGV4KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gY3VycmVudEl0ZW0gPj0gbGVmdCAmJiBjdXJyZW50SXRlbSA8PSByaWdodDtcbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIGlmIChjdXJyZW50SXRlbSA8IGxlZnQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIG1pbkluZGV4ID0gY3VycmVudEluZGV4ICsgMTtcbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIGlmIChjdXJyZW50SXRlbSA+IHJpZ2h0KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBtYXhJbmRleCA9IGN1cnJlbnRJbmRleCAtIDE7XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZnVuY3Rpb24gYXNjZW5kaW5nKGEsIGIpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gYSA+IGIgPyAxIDogLTE7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0sIHt9XSwgMTc6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICB2YXIgYXBwbHlQcm9wZXJ0aWVzID0gcmVxdWlyZShcIi4vYXBwbHktcHJvcGVydGllc1wiKTtcblxuICAgICAgICAgICAgdmFyIGlzV2lkZ2V0ID0gcmVxdWlyZShcIi4uL3Zub2RlL2lzLXdpZGdldC5qc1wiKTtcbiAgICAgICAgICAgIHZhciBWUGF0Y2ggPSByZXF1aXJlKFwiLi4vdm5vZGUvdnBhdGNoLmpzXCIpO1xuXG4gICAgICAgICAgICB2YXIgdXBkYXRlV2lkZ2V0ID0gcmVxdWlyZShcIi4vdXBkYXRlLXdpZGdldFwiKTtcblxuICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBhcHBseVBhdGNoO1xuXG4gICAgICAgICAgICBmdW5jdGlvbiBhcHBseVBhdGNoKHZwYXRjaCwgZG9tTm9kZSwgcmVuZGVyT3B0aW9ucykge1xuICAgICAgICAgICAgICAgIHZhciB0eXBlID0gdnBhdGNoLnR5cGU7XG4gICAgICAgICAgICAgICAgdmFyIHZOb2RlID0gdnBhdGNoLnZOb2RlO1xuICAgICAgICAgICAgICAgIHZhciBwYXRjaCA9IHZwYXRjaC5wYXRjaDtcblxuICAgICAgICAgICAgICAgIHN3aXRjaCAodHlwZSkge1xuICAgICAgICAgICAgICAgICAgICBjYXNlIFZQYXRjaC5SRU1PVkU6XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gcmVtb3ZlTm9kZShkb21Ob2RlLCB2Tm9kZSk7XG4gICAgICAgICAgICAgICAgICAgIGNhc2UgVlBhdGNoLklOU0VSVDpcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBpbnNlcnROb2RlKGRvbU5vZGUsIHBhdGNoLCByZW5kZXJPcHRpb25zKTtcbiAgICAgICAgICAgICAgICAgICAgY2FzZSBWUGF0Y2guVlRFWFQ6XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gc3RyaW5nUGF0Y2goZG9tTm9kZSwgdk5vZGUsIHBhdGNoLCByZW5kZXJPcHRpb25zKTtcbiAgICAgICAgICAgICAgICAgICAgY2FzZSBWUGF0Y2guV0lER0VUOlxuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHdpZGdldFBhdGNoKGRvbU5vZGUsIHZOb2RlLCBwYXRjaCwgcmVuZGVyT3B0aW9ucyk7XG4gICAgICAgICAgICAgICAgICAgIGNhc2UgVlBhdGNoLlZOT0RFOlxuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHZOb2RlUGF0Y2goZG9tTm9kZSwgdk5vZGUsIHBhdGNoLCByZW5kZXJPcHRpb25zKTtcbiAgICAgICAgICAgICAgICAgICAgY2FzZSBWUGF0Y2guT1JERVI6XG4gICAgICAgICAgICAgICAgICAgICAgICByZW9yZGVyQ2hpbGRyZW4oZG9tTm9kZSwgcGF0Y2gpO1xuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGRvbU5vZGU7XG4gICAgICAgICAgICAgICAgICAgIGNhc2UgVlBhdGNoLlBST1BTOlxuICAgICAgICAgICAgICAgICAgICAgICAgYXBwbHlQcm9wZXJ0aWVzKGRvbU5vZGUsIHBhdGNoLCB2Tm9kZS5wcm9wZXJ0aWVzKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBkb21Ob2RlO1xuICAgICAgICAgICAgICAgICAgICBjYXNlIFZQYXRjaC5USFVOSzpcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiByZXBsYWNlUm9vdChkb21Ob2RlLCByZW5kZXJPcHRpb25zLnBhdGNoKGRvbU5vZGUsIHBhdGNoLCByZW5kZXJPcHRpb25zKSk7XG4gICAgICAgICAgICAgICAgICAgIGRlZmF1bHQ6XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gZG9tTm9kZTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIHJlbW92ZU5vZGUoZG9tTm9kZSwgdk5vZGUpIHtcbiAgICAgICAgICAgICAgICB2YXIgcGFyZW50Tm9kZSA9IGRvbU5vZGUucGFyZW50Tm9kZTtcblxuICAgICAgICAgICAgICAgIGlmIChwYXJlbnROb2RlKSB7XG4gICAgICAgICAgICAgICAgICAgIHBhcmVudE5vZGUucmVtb3ZlQ2hpbGQoZG9tTm9kZSk7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgZGVzdHJveVdpZGdldChkb21Ob2RlLCB2Tm9kZSk7XG5cbiAgICAgICAgICAgICAgICByZXR1cm4gbnVsbDtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZnVuY3Rpb24gaW5zZXJ0Tm9kZShwYXJlbnROb2RlLCB2Tm9kZSwgcmVuZGVyT3B0aW9ucykge1xuICAgICAgICAgICAgICAgIHZhciBuZXdOb2RlID0gcmVuZGVyT3B0aW9ucy5yZW5kZXIodk5vZGUsIHJlbmRlck9wdGlvbnMpO1xuXG4gICAgICAgICAgICAgICAgaWYgKHBhcmVudE5vZGUpIHtcbiAgICAgICAgICAgICAgICAgICAgcGFyZW50Tm9kZS5hcHBlbmRDaGlsZChuZXdOb2RlKTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICByZXR1cm4gcGFyZW50Tm9kZTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZnVuY3Rpb24gc3RyaW5nUGF0Y2goZG9tTm9kZSwgbGVmdFZOb2RlLCB2VGV4dCwgcmVuZGVyT3B0aW9ucykge1xuICAgICAgICAgICAgICAgIHZhciBuZXdOb2RlO1xuXG4gICAgICAgICAgICAgICAgaWYgKGRvbU5vZGUubm9kZVR5cGUgPT09IDMpIHtcbiAgICAgICAgICAgICAgICAgICAgZG9tTm9kZS5yZXBsYWNlRGF0YSgwLCBkb21Ob2RlLmxlbmd0aCwgdlRleHQudGV4dCk7XG4gICAgICAgICAgICAgICAgICAgIG5ld05vZGUgPSBkb21Ob2RlO1xuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciBwYXJlbnROb2RlID0gZG9tTm9kZS5wYXJlbnROb2RlO1xuICAgICAgICAgICAgICAgICAgICBuZXdOb2RlID0gcmVuZGVyT3B0aW9ucy5yZW5kZXIodlRleHQsIHJlbmRlck9wdGlvbnMpO1xuXG4gICAgICAgICAgICAgICAgICAgIGlmIChwYXJlbnROb2RlICYmIG5ld05vZGUgIT09IGRvbU5vZGUpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHBhcmVudE5vZGUucmVwbGFjZUNoaWxkKG5ld05vZGUsIGRvbU5vZGUpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgcmV0dXJuIG5ld05vZGU7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIHdpZGdldFBhdGNoKGRvbU5vZGUsIGxlZnRWTm9kZSwgd2lkZ2V0LCByZW5kZXJPcHRpb25zKSB7XG4gICAgICAgICAgICAgICAgdmFyIHVwZGF0aW5nID0gdXBkYXRlV2lkZ2V0KGxlZnRWTm9kZSwgd2lkZ2V0KTtcbiAgICAgICAgICAgICAgICB2YXIgbmV3Tm9kZTtcblxuICAgICAgICAgICAgICAgIGlmICh1cGRhdGluZykge1xuICAgICAgICAgICAgICAgICAgICBuZXdOb2RlID0gd2lkZ2V0LnVwZGF0ZShsZWZ0Vk5vZGUsIGRvbU5vZGUpIHx8IGRvbU5vZGU7XG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgbmV3Tm9kZSA9IHJlbmRlck9wdGlvbnMucmVuZGVyKHdpZGdldCwgcmVuZGVyT3B0aW9ucyk7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgdmFyIHBhcmVudE5vZGUgPSBkb21Ob2RlLnBhcmVudE5vZGU7XG5cbiAgICAgICAgICAgICAgICBpZiAocGFyZW50Tm9kZSAmJiBuZXdOb2RlICE9PSBkb21Ob2RlKSB7XG4gICAgICAgICAgICAgICAgICAgIHBhcmVudE5vZGUucmVwbGFjZUNoaWxkKG5ld05vZGUsIGRvbU5vZGUpO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIGlmICghdXBkYXRpbmcpIHtcbiAgICAgICAgICAgICAgICAgICAgZGVzdHJveVdpZGdldChkb21Ob2RlLCBsZWZ0Vk5vZGUpO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHJldHVybiBuZXdOb2RlO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBmdW5jdGlvbiB2Tm9kZVBhdGNoKGRvbU5vZGUsIGxlZnRWTm9kZSwgdk5vZGUsIHJlbmRlck9wdGlvbnMpIHtcbiAgICAgICAgICAgICAgICB2YXIgcGFyZW50Tm9kZSA9IGRvbU5vZGUucGFyZW50Tm9kZTtcbiAgICAgICAgICAgICAgICB2YXIgbmV3Tm9kZSA9IHJlbmRlck9wdGlvbnMucmVuZGVyKHZOb2RlLCByZW5kZXJPcHRpb25zKTtcblxuICAgICAgICAgICAgICAgIGlmIChwYXJlbnROb2RlICYmIG5ld05vZGUgIT09IGRvbU5vZGUpIHtcbiAgICAgICAgICAgICAgICAgICAgcGFyZW50Tm9kZS5yZXBsYWNlQ2hpbGQobmV3Tm9kZSwgZG9tTm9kZSk7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgcmV0dXJuIG5ld05vZGU7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIGRlc3Ryb3lXaWRnZXQoZG9tTm9kZSwgdykge1xuICAgICAgICAgICAgICAgIGlmICh0eXBlb2Ygdy5kZXN0cm95ID09PSBcImZ1bmN0aW9uXCIgJiYgaXNXaWRnZXQodykpIHtcbiAgICAgICAgICAgICAgICAgICAgdy5kZXN0cm95KGRvbU5vZGUpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZnVuY3Rpb24gcmVvcmRlckNoaWxkcmVuKGRvbU5vZGUsIG1vdmVzKSB7XG4gICAgICAgICAgICAgICAgdmFyIGNoaWxkTm9kZXMgPSBkb21Ob2RlLmNoaWxkTm9kZXM7XG4gICAgICAgICAgICAgICAgdmFyIGtleU1hcCA9IHt9O1xuICAgICAgICAgICAgICAgIHZhciBub2RlO1xuICAgICAgICAgICAgICAgIHZhciByZW1vdmU7XG4gICAgICAgICAgICAgICAgdmFyIGluc2VydDtcblxuICAgICAgICAgICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgbW92ZXMucmVtb3Zlcy5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgICAgICAgICByZW1vdmUgPSBtb3Zlcy5yZW1vdmVzW2ldO1xuICAgICAgICAgICAgICAgICAgICBub2RlID0gY2hpbGROb2Rlc1tyZW1vdmUuZnJvbV07XG4gICAgICAgICAgICAgICAgICAgIGlmIChyZW1vdmUua2V5KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBrZXlNYXBbcmVtb3ZlLmtleV0gPSBub2RlO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIGRvbU5vZGUucmVtb3ZlQ2hpbGQobm9kZSk7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgdmFyIGxlbmd0aCA9IGNoaWxkTm9kZXMubGVuZ3RoO1xuICAgICAgICAgICAgICAgIGZvciAodmFyIGogPSAwOyBqIDwgbW92ZXMuaW5zZXJ0cy5sZW5ndGg7IGorKykge1xuICAgICAgICAgICAgICAgICAgICBpbnNlcnQgPSBtb3Zlcy5pbnNlcnRzW2pdO1xuICAgICAgICAgICAgICAgICAgICBub2RlID0ga2V5TWFwW2luc2VydC5rZXldO1xuICAgICAgICAgICAgICAgICAgICAvLyB0aGlzIGlzIHRoZSB3ZWlyZGVzdCBidWcgaSd2ZSBldmVyIHNlZW4gaW4gd2Via2l0XG4gICAgICAgICAgICAgICAgICAgIGRvbU5vZGUuaW5zZXJ0QmVmb3JlKG5vZGUsIGluc2VydC50byA+PSBsZW5ndGgrKyA/IG51bGwgOiBjaGlsZE5vZGVzW2luc2VydC50b10pO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZnVuY3Rpb24gcmVwbGFjZVJvb3Qob2xkUm9vdCwgbmV3Um9vdCkge1xuICAgICAgICAgICAgICAgIGlmIChvbGRSb290ICYmIG5ld1Jvb3QgJiYgb2xkUm9vdCAhPT0gbmV3Um9vdCAmJiBvbGRSb290LnBhcmVudE5vZGUpIHtcbiAgICAgICAgICAgICAgICAgICAgb2xkUm9vdC5wYXJlbnROb2RlLnJlcGxhY2VDaGlsZChuZXdSb290LCBvbGRSb290KTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICByZXR1cm4gbmV3Um9vdDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSwgeyBcIi4uL3Zub2RlL2lzLXdpZGdldC5qc1wiOiAyOSwgXCIuLi92bm9kZS92cGF0Y2guanNcIjogMzIsIFwiLi9hcHBseS1wcm9wZXJ0aWVzXCI6IDE0LCBcIi4vdXBkYXRlLXdpZGdldFwiOiAxOSB9XSwgMTg6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICB2YXIgZG9jdW1lbnQgPSByZXF1aXJlKFwiZ2xvYmFsL2RvY3VtZW50XCIpO1xuICAgICAgICAgICAgdmFyIGlzQXJyYXkgPSByZXF1aXJlKFwieC1pcy1hcnJheVwiKTtcblxuICAgICAgICAgICAgdmFyIHJlbmRlciA9IHJlcXVpcmUoXCIuL2NyZWF0ZS1lbGVtZW50XCIpO1xuICAgICAgICAgICAgdmFyIGRvbUluZGV4ID0gcmVxdWlyZShcIi4vZG9tLWluZGV4XCIpO1xuICAgICAgICAgICAgdmFyIHBhdGNoT3AgPSByZXF1aXJlKFwiLi9wYXRjaC1vcFwiKTtcbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gcGF0Y2g7XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIHBhdGNoKHJvb3ROb2RlLCBwYXRjaGVzLCByZW5kZXJPcHRpb25zKSB7XG4gICAgICAgICAgICAgICAgcmVuZGVyT3B0aW9ucyA9IHJlbmRlck9wdGlvbnMgfHwge307XG4gICAgICAgICAgICAgICAgcmVuZGVyT3B0aW9ucy5wYXRjaCA9IHJlbmRlck9wdGlvbnMucGF0Y2ggJiYgcmVuZGVyT3B0aW9ucy5wYXRjaCAhPT0gcGF0Y2ggPyByZW5kZXJPcHRpb25zLnBhdGNoIDogcGF0Y2hSZWN1cnNpdmU7XG4gICAgICAgICAgICAgICAgcmVuZGVyT3B0aW9ucy5yZW5kZXIgPSByZW5kZXJPcHRpb25zLnJlbmRlciB8fCByZW5kZXI7XG5cbiAgICAgICAgICAgICAgICByZXR1cm4gcmVuZGVyT3B0aW9ucy5wYXRjaChyb290Tm9kZSwgcGF0Y2hlcywgcmVuZGVyT3B0aW9ucyk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIHBhdGNoUmVjdXJzaXZlKHJvb3ROb2RlLCBwYXRjaGVzLCByZW5kZXJPcHRpb25zKSB7XG4gICAgICAgICAgICAgICAgdmFyIGluZGljZXMgPSBwYXRjaEluZGljZXMocGF0Y2hlcyk7XG5cbiAgICAgICAgICAgICAgICBpZiAoaW5kaWNlcy5sZW5ndGggPT09IDApIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHJvb3ROb2RlO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHZhciBpbmRleCA9IGRvbUluZGV4KHJvb3ROb2RlLCBwYXRjaGVzLmEsIGluZGljZXMpO1xuICAgICAgICAgICAgICAgIHZhciBvd25lckRvY3VtZW50ID0gcm9vdE5vZGUub3duZXJEb2N1bWVudDtcblxuICAgICAgICAgICAgICAgIGlmICghcmVuZGVyT3B0aW9ucy5kb2N1bWVudCAmJiBvd25lckRvY3VtZW50ICE9PSBkb2N1bWVudCkge1xuICAgICAgICAgICAgICAgICAgICByZW5kZXJPcHRpb25zLmRvY3VtZW50ID0gb3duZXJEb2N1bWVudDtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IGluZGljZXMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgICAgICAgICAgdmFyIG5vZGVJbmRleCA9IGluZGljZXNbaV07XG4gICAgICAgICAgICAgICAgICAgIHJvb3ROb2RlID0gYXBwbHlQYXRjaChyb290Tm9kZSwgaW5kZXhbbm9kZUluZGV4XSwgcGF0Y2hlc1tub2RlSW5kZXhdLCByZW5kZXJPcHRpb25zKTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICByZXR1cm4gcm9vdE5vZGU7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIGFwcGx5UGF0Y2gocm9vdE5vZGUsIGRvbU5vZGUsIHBhdGNoTGlzdCwgcmVuZGVyT3B0aW9ucykge1xuICAgICAgICAgICAgICAgIGlmICghZG9tTm9kZSkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gcm9vdE5vZGU7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgdmFyIG5ld05vZGU7XG5cbiAgICAgICAgICAgICAgICBpZiAoaXNBcnJheShwYXRjaExpc3QpKSB7XG4gICAgICAgICAgICAgICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgcGF0Y2hMaXN0Lmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBuZXdOb2RlID0gcGF0Y2hPcChwYXRjaExpc3RbaV0sIGRvbU5vZGUsIHJlbmRlck9wdGlvbnMpO1xuXG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoZG9tTm9kZSA9PT0gcm9vdE5vZGUpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICByb290Tm9kZSA9IG5ld05vZGU7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICBuZXdOb2RlID0gcGF0Y2hPcChwYXRjaExpc3QsIGRvbU5vZGUsIHJlbmRlck9wdGlvbnMpO1xuXG4gICAgICAgICAgICAgICAgICAgIGlmIChkb21Ob2RlID09PSByb290Tm9kZSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgcm9vdE5vZGUgPSBuZXdOb2RlO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgcmV0dXJuIHJvb3ROb2RlO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBmdW5jdGlvbiBwYXRjaEluZGljZXMocGF0Y2hlcykge1xuICAgICAgICAgICAgICAgIHZhciBpbmRpY2VzID0gW107XG5cbiAgICAgICAgICAgICAgICBmb3IgKHZhciBrZXkgaW4gcGF0Y2hlcykge1xuICAgICAgICAgICAgICAgICAgICBpZiAoa2V5ICE9PSBcImFcIikge1xuICAgICAgICAgICAgICAgICAgICAgICAgaW5kaWNlcy5wdXNoKE51bWJlcihrZXkpKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHJldHVybiBpbmRpY2VzO1xuICAgICAgICAgICAgfVxuICAgICAgICB9LCB7IFwiLi9jcmVhdGUtZWxlbWVudFwiOiAxNSwgXCIuL2RvbS1pbmRleFwiOiAxNiwgXCIuL3BhdGNoLW9wXCI6IDE3LCBcImdsb2JhbC9kb2N1bWVudFwiOiAxMCwgXCJ4LWlzLWFycmF5XCI6IDEyIH1dLCAxOTogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHtcbiAgICAgICAgICAgIHZhciBpc1dpZGdldCA9IHJlcXVpcmUoXCIuLi92bm9kZS9pcy13aWRnZXQuanNcIik7XG5cbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gdXBkYXRlV2lkZ2V0O1xuXG4gICAgICAgICAgICBmdW5jdGlvbiB1cGRhdGVXaWRnZXQoYSwgYikge1xuICAgICAgICAgICAgICAgIGlmIChpc1dpZGdldChhKSAmJiBpc1dpZGdldChiKSkge1xuICAgICAgICAgICAgICAgICAgICBpZiAoXCJuYW1lXCIgaW4gYSAmJiBcIm5hbWVcIiBpbiBiKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gYS5pZCA9PT0gYi5pZDtcbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBhLmluaXQgPT09IGIuaW5pdDtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSwgeyBcIi4uL3Zub2RlL2lzLXdpZGdldC5qc1wiOiAyOSB9XSwgMjA6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICBcInVzZSBzdHJpY3RcIjtcblxuICAgICAgICAgICAgdmFyIEV2U3RvcmUgPSByZXF1aXJlKFwiZXYtc3RvcmVcIik7XG5cbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gRXZIb29rO1xuXG4gICAgICAgICAgICBmdW5jdGlvbiBFdkhvb2sodmFsdWUpIHtcbiAgICAgICAgICAgICAgICBpZiAoISh0aGlzIGluc3RhbmNlb2YgRXZIb29rKSkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gbmV3IEV2SG9vayh2YWx1ZSk7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgdGhpcy52YWx1ZSA9IHZhbHVlO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBFdkhvb2sucHJvdG90eXBlLmhvb2sgPSBmdW5jdGlvbiAobm9kZSwgcHJvcGVydHlOYW1lKSB7XG4gICAgICAgICAgICAgICAgdmFyIGVzID0gRXZTdG9yZShub2RlKTtcbiAgICAgICAgICAgICAgICB2YXIgcHJvcE5hbWUgPSBwcm9wZXJ0eU5hbWUuc3Vic3RyKDMpO1xuXG4gICAgICAgICAgICAgICAgZXNbcHJvcE5hbWVdID0gdGhpcy52YWx1ZTtcbiAgICAgICAgICAgIH07XG5cbiAgICAgICAgICAgIEV2SG9vay5wcm90b3R5cGUudW5ob29rID0gZnVuY3Rpb24gKG5vZGUsIHByb3BlcnR5TmFtZSkge1xuICAgICAgICAgICAgICAgIHZhciBlcyA9IEV2U3RvcmUobm9kZSk7XG4gICAgICAgICAgICAgICAgdmFyIHByb3BOYW1lID0gcHJvcGVydHlOYW1lLnN1YnN0cigzKTtcblxuICAgICAgICAgICAgICAgIGVzW3Byb3BOYW1lXSA9IHVuZGVmaW5lZDtcbiAgICAgICAgICAgIH07XG4gICAgICAgIH0sIHsgXCJldi1zdG9yZVwiOiA3IH1dLCAyMTogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHtcbiAgICAgICAgICAgIFwidXNlIHN0cmljdFwiO1xuXG4gICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IFNvZnRTZXRIb29rO1xuXG4gICAgICAgICAgICBmdW5jdGlvbiBTb2Z0U2V0SG9vayh2YWx1ZSkge1xuICAgICAgICAgICAgICAgIGlmICghKHRoaXMgaW5zdGFuY2VvZiBTb2Z0U2V0SG9vaykpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIG5ldyBTb2Z0U2V0SG9vayh2YWx1ZSk7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgdGhpcy52YWx1ZSA9IHZhbHVlO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBTb2Z0U2V0SG9vay5wcm90b3R5cGUuaG9vayA9IGZ1bmN0aW9uIChub2RlLCBwcm9wZXJ0eU5hbWUpIHtcbiAgICAgICAgICAgICAgICBpZiAobm9kZVtwcm9wZXJ0eU5hbWVdICE9PSB0aGlzLnZhbHVlKSB7XG4gICAgICAgICAgICAgICAgICAgIG5vZGVbcHJvcGVydHlOYW1lXSA9IHRoaXMudmFsdWU7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfTtcbiAgICAgICAgfSwge31dLCAyMjogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHtcbiAgICAgICAgICAgIFwidXNlIHN0cmljdFwiO1xuXG4gICAgICAgICAgICB2YXIgaXNBcnJheSA9IHJlcXVpcmUoXCJ4LWlzLWFycmF5XCIpO1xuXG4gICAgICAgICAgICB2YXIgVk5vZGUgPSByZXF1aXJlKFwiLi4vdm5vZGUvdm5vZGUuanNcIik7XG4gICAgICAgICAgICB2YXIgVlRleHQgPSByZXF1aXJlKFwiLi4vdm5vZGUvdnRleHQuanNcIik7XG4gICAgICAgICAgICB2YXIgaXNWTm9kZSA9IHJlcXVpcmUoXCIuLi92bm9kZS9pcy12bm9kZVwiKTtcbiAgICAgICAgICAgIHZhciBpc1ZUZXh0ID0gcmVxdWlyZShcIi4uL3Zub2RlL2lzLXZ0ZXh0XCIpO1xuICAgICAgICAgICAgdmFyIGlzV2lkZ2V0ID0gcmVxdWlyZShcIi4uL3Zub2RlL2lzLXdpZGdldFwiKTtcbiAgICAgICAgICAgIHZhciBpc0hvb2sgPSByZXF1aXJlKFwiLi4vdm5vZGUvaXMtdmhvb2tcIik7XG4gICAgICAgICAgICB2YXIgaXNWVGh1bmsgPSByZXF1aXJlKFwiLi4vdm5vZGUvaXMtdGh1bmtcIik7XG5cbiAgICAgICAgICAgIHZhciBwYXJzZVRhZyA9IHJlcXVpcmUoXCIuL3BhcnNlLXRhZy5qc1wiKTtcbiAgICAgICAgICAgIHZhciBzb2Z0U2V0SG9vayA9IHJlcXVpcmUoXCIuL2hvb2tzL3NvZnQtc2V0LWhvb2suanNcIik7XG4gICAgICAgICAgICB2YXIgZXZIb29rID0gcmVxdWlyZShcIi4vaG9va3MvZXYtaG9vay5qc1wiKTtcblxuICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBoO1xuXG4gICAgICAgICAgICBmdW5jdGlvbiBoKHRhZ05hbWUsIHByb3BlcnRpZXMsIGNoaWxkcmVuKSB7XG4gICAgICAgICAgICAgICAgdmFyIGNoaWxkTm9kZXMgPSBbXTtcbiAgICAgICAgICAgICAgICB2YXIgdGFnLCBwcm9wcywga2V5LCBuYW1lc3BhY2U7XG5cbiAgICAgICAgICAgICAgICBpZiAoIWNoaWxkcmVuICYmIGlzQ2hpbGRyZW4ocHJvcGVydGllcykpIHtcbiAgICAgICAgICAgICAgICAgICAgY2hpbGRyZW4gPSBwcm9wZXJ0aWVzO1xuICAgICAgICAgICAgICAgICAgICBwcm9wcyA9IHt9O1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHByb3BzID0gcHJvcHMgfHwgcHJvcGVydGllcyB8fCB7fTtcbiAgICAgICAgICAgICAgICB0YWcgPSBwYXJzZVRhZyh0YWdOYW1lLCBwcm9wcyk7XG5cbiAgICAgICAgICAgICAgICAvLyBzdXBwb3J0IGtleXNcbiAgICAgICAgICAgICAgICBpZiAocHJvcHMuaGFzT3duUHJvcGVydHkoXCJrZXlcIikpIHtcbiAgICAgICAgICAgICAgICAgICAga2V5ID0gcHJvcHMua2V5O1xuICAgICAgICAgICAgICAgICAgICBwcm9wcy5rZXkgPSB1bmRlZmluZWQ7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgLy8gc3VwcG9ydCBuYW1lc3BhY2VcbiAgICAgICAgICAgICAgICBpZiAocHJvcHMuaGFzT3duUHJvcGVydHkoXCJuYW1lc3BhY2VcIikpIHtcbiAgICAgICAgICAgICAgICAgICAgbmFtZXNwYWNlID0gcHJvcHMubmFtZXNwYWNlO1xuICAgICAgICAgICAgICAgICAgICBwcm9wcy5uYW1lc3BhY2UgPSB1bmRlZmluZWQ7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgLy8gZml4IGN1cnNvciBidWdcbiAgICAgICAgICAgICAgICBpZiAodGFnID09PSBcIklOUFVUXCIgJiYgIW5hbWVzcGFjZSAmJiBwcm9wcy5oYXNPd25Qcm9wZXJ0eShcInZhbHVlXCIpICYmIHByb3BzLnZhbHVlICE9PSB1bmRlZmluZWQgJiYgIWlzSG9vayhwcm9wcy52YWx1ZSkpIHtcbiAgICAgICAgICAgICAgICAgICAgcHJvcHMudmFsdWUgPSBzb2Z0U2V0SG9vayhwcm9wcy52YWx1ZSk7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgdHJhbnNmb3JtUHJvcGVydGllcyhwcm9wcyk7XG5cbiAgICAgICAgICAgICAgICBpZiAoY2hpbGRyZW4gIT09IHVuZGVmaW5lZCAmJiBjaGlsZHJlbiAhPT0gbnVsbCkge1xuICAgICAgICAgICAgICAgICAgICBhZGRDaGlsZChjaGlsZHJlbiwgY2hpbGROb2RlcywgdGFnLCBwcm9wcyk7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgcmV0dXJuIG5ldyBWTm9kZSh0YWcsIHByb3BzLCBjaGlsZE5vZGVzLCBrZXksIG5hbWVzcGFjZSk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIGFkZENoaWxkKGMsIGNoaWxkTm9kZXMsIHRhZywgcHJvcHMpIHtcbiAgICAgICAgICAgICAgICBpZiAodHlwZW9mIGMgPT09IFwic3RyaW5nXCIpIHtcbiAgICAgICAgICAgICAgICAgICAgY2hpbGROb2Rlcy5wdXNoKG5ldyBWVGV4dChjKSk7XG4gICAgICAgICAgICAgICAgfSBlbHNlIGlmICh0eXBlb2YgYyA9PT0gXCJudW1iZXJcIikge1xuICAgICAgICAgICAgICAgICAgICBjaGlsZE5vZGVzLnB1c2gobmV3IFZUZXh0KFN0cmluZyhjKSkpO1xuICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoaXNDaGlsZChjKSkge1xuICAgICAgICAgICAgICAgICAgICBjaGlsZE5vZGVzLnB1c2goYyk7XG4gICAgICAgICAgICAgICAgfSBlbHNlIGlmIChpc0FycmF5KGMpKSB7XG4gICAgICAgICAgICAgICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgYy5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgICAgICAgICAgICAgYWRkQ2hpbGQoY1tpXSwgY2hpbGROb2RlcywgdGFnLCBwcm9wcyk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKGMgPT09IG51bGwgfHwgYyA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICB0aHJvdyBVbmV4cGVjdGVkVmlydHVhbEVsZW1lbnQoe1xuICAgICAgICAgICAgICAgICAgICAgICAgZm9yZWlnbk9iamVjdDogYyxcbiAgICAgICAgICAgICAgICAgICAgICAgIHBhcmVudFZub2RlOiB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdGFnTmFtZTogdGFnLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHByb3BlcnRpZXM6IHByb3BzXG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZnVuY3Rpb24gdHJhbnNmb3JtUHJvcGVydGllcyhwcm9wcykge1xuICAgICAgICAgICAgICAgIGZvciAodmFyIHByb3BOYW1lIGluIHByb3BzKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmIChwcm9wcy5oYXNPd25Qcm9wZXJ0eShwcm9wTmFtZSkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHZhciB2YWx1ZSA9IHByb3BzW3Byb3BOYW1lXTtcblxuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGlzSG9vayh2YWx1ZSkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb250aW51ZTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHByb3BOYW1lLnN1YnN0cigwLCAzKSA9PT0gXCJldi1cIikge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIGFkZCBldi1mb28gc3VwcG9ydFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHByb3BzW3Byb3BOYW1lXSA9IGV2SG9vayh2YWx1ZSk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIGlzQ2hpbGQoeCkge1xuICAgICAgICAgICAgICAgIHJldHVybiBpc1ZOb2RlKHgpIHx8IGlzVlRleHQoeCkgfHwgaXNXaWRnZXQoeCkgfHwgaXNWVGh1bmsoeCk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIGlzQ2hpbGRyZW4oeCkge1xuICAgICAgICAgICAgICAgIHJldHVybiB0eXBlb2YgeCA9PT0gXCJzdHJpbmdcIiB8fCBpc0FycmF5KHgpIHx8IGlzQ2hpbGQoeCk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIFVuZXhwZWN0ZWRWaXJ0dWFsRWxlbWVudChkYXRhKSB7XG4gICAgICAgICAgICAgICAgdmFyIGVyciA9IG5ldyBFcnJvcigpO1xuXG4gICAgICAgICAgICAgICAgZXJyLnR5cGUgPSBcInZpcnR1YWwtaHlwZXJzY3JpcHQudW5leHBlY3RlZC52aXJ0dWFsLWVsZW1lbnRcIjtcbiAgICAgICAgICAgICAgICBlcnIubWVzc2FnZSA9IFwiVW5leHBlY3RlZCB2aXJ0dWFsIGNoaWxkIHBhc3NlZCB0byBoKCkuXFxuXCIgKyBcIkV4cGVjdGVkIGEgVk5vZGUgLyBWdGh1bmsgLyBWV2lkZ2V0IC8gc3RyaW5nIGJ1dDpcXG5cIiArIFwiZ290OlxcblwiICsgZXJyb3JTdHJpbmcoZGF0YS5mb3JlaWduT2JqZWN0KSArIFwiLlxcblwiICsgXCJUaGUgcGFyZW50IHZub2RlIGlzOlxcblwiICsgZXJyb3JTdHJpbmcoZGF0YS5wYXJlbnRWbm9kZSk7XG4gICAgICAgICAgICAgICAgXCJcXG5cIiArIFwiU3VnZ2VzdGVkIGZpeDogY2hhbmdlIHlvdXIgYGgoLi4uLCBbIC4uLiBdKWAgY2FsbHNpdGUuXCI7XG4gICAgICAgICAgICAgICAgZXJyLmZvcmVpZ25PYmplY3QgPSBkYXRhLmZvcmVpZ25PYmplY3Q7XG4gICAgICAgICAgICAgICAgZXJyLnBhcmVudFZub2RlID0gZGF0YS5wYXJlbnRWbm9kZTtcblxuICAgICAgICAgICAgICAgIHJldHVybiBlcnI7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIGVycm9yU3RyaW5nKG9iaikge1xuICAgICAgICAgICAgICAgIHRyeSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBKU09OLnN0cmluZ2lmeShvYmosIG51bGwsIFwiICAgIFwiKTtcbiAgICAgICAgICAgICAgICB9IGNhdGNoIChlKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBTdHJpbmcob2JqKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH0sIHsgXCIuLi92bm9kZS9pcy10aHVua1wiOiAyNSwgXCIuLi92bm9kZS9pcy12aG9va1wiOiAyNiwgXCIuLi92bm9kZS9pcy12bm9kZVwiOiAyNywgXCIuLi92bm9kZS9pcy12dGV4dFwiOiAyOCwgXCIuLi92bm9kZS9pcy13aWRnZXRcIjogMjksIFwiLi4vdm5vZGUvdm5vZGUuanNcIjogMzEsIFwiLi4vdm5vZGUvdnRleHQuanNcIjogMzMsIFwiLi9ob29rcy9ldi1ob29rLmpzXCI6IDIwLCBcIi4vaG9va3Mvc29mdC1zZXQtaG9vay5qc1wiOiAyMSwgXCIuL3BhcnNlLXRhZy5qc1wiOiAyMywgXCJ4LWlzLWFycmF5XCI6IDEyIH1dLCAyMzogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHtcbiAgICAgICAgICAgIFwidXNlIHN0cmljdFwiO1xuXG4gICAgICAgICAgICB2YXIgc3BsaXQgPSByZXF1aXJlKFwiYnJvd3Nlci1zcGxpdFwiKTtcblxuICAgICAgICAgICAgdmFyIGNsYXNzSWRTcGxpdCA9IC8oW1xcLiNdP1thLXpBLVowLTlcXHUwMDdGLVxcdUZGRkZfOi1dKykvO1xuICAgICAgICAgICAgdmFyIG5vdENsYXNzSWQgPSAvXlxcLnwjLztcblxuICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBwYXJzZVRhZztcblxuICAgICAgICAgICAgZnVuY3Rpb24gcGFyc2VUYWcodGFnLCBwcm9wcykge1xuICAgICAgICAgICAgICAgIGlmICghdGFnKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBcIkRJVlwiO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHZhciBub0lkID0gIXByb3BzLmhhc093blByb3BlcnR5KFwiaWRcIik7XG5cbiAgICAgICAgICAgICAgICB2YXIgdGFnUGFydHMgPSBzcGxpdCh0YWcsIGNsYXNzSWRTcGxpdCk7XG4gICAgICAgICAgICAgICAgdmFyIHRhZ05hbWUgPSBudWxsO1xuXG4gICAgICAgICAgICAgICAgaWYgKG5vdENsYXNzSWQudGVzdCh0YWdQYXJ0c1sxXSkpIHtcbiAgICAgICAgICAgICAgICAgICAgdGFnTmFtZSA9IFwiRElWXCI7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgdmFyIGNsYXNzZXMsIHBhcnQsIHR5cGUsIGk7XG5cbiAgICAgICAgICAgICAgICBmb3IgKGkgPSAwOyBpIDwgdGFnUGFydHMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgICAgICAgICAgcGFydCA9IHRhZ1BhcnRzW2ldO1xuXG4gICAgICAgICAgICAgICAgICAgIGlmICghcGFydCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgY29udGludWU7XG4gICAgICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgICAgICB0eXBlID0gcGFydC5jaGFyQXQoMCk7XG5cbiAgICAgICAgICAgICAgICAgICAgaWYgKCF0YWdOYW1lKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICB0YWdOYW1lID0gcGFydDtcbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIGlmICh0eXBlID09PSBcIi5cIikge1xuICAgICAgICAgICAgICAgICAgICAgICAgY2xhc3NlcyA9IGNsYXNzZXMgfHwgW107XG4gICAgICAgICAgICAgICAgICAgICAgICBjbGFzc2VzLnB1c2gocGFydC5zdWJzdHJpbmcoMSwgcGFydC5sZW5ndGgpKTtcbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIGlmICh0eXBlID09PSBcIiNcIiAmJiBub0lkKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBwcm9wcy5pZCA9IHBhcnQuc3Vic3RyaW5nKDEsIHBhcnQubGVuZ3RoKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIGlmIChjbGFzc2VzKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmIChwcm9wcy5jbGFzc05hbWUpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGNsYXNzZXMucHVzaChwcm9wcy5jbGFzc05hbWUpO1xuICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgcHJvcHMuY2xhc3NOYW1lID0gY2xhc3Nlcy5qb2luKFwiIFwiKTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICByZXR1cm4gcHJvcHMubmFtZXNwYWNlID8gdGFnTmFtZSA6IHRhZ05hbWUudG9VcHBlckNhc2UoKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSwgeyBcImJyb3dzZXItc3BsaXRcIjogNSB9XSwgMjQ6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICB2YXIgaXNWTm9kZSA9IHJlcXVpcmUoXCIuL2lzLXZub2RlXCIpO1xuICAgICAgICAgICAgdmFyIGlzVlRleHQgPSByZXF1aXJlKFwiLi9pcy12dGV4dFwiKTtcbiAgICAgICAgICAgIHZhciBpc1dpZGdldCA9IHJlcXVpcmUoXCIuL2lzLXdpZGdldFwiKTtcbiAgICAgICAgICAgIHZhciBpc1RodW5rID0gcmVxdWlyZShcIi4vaXMtdGh1bmtcIik7XG5cbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gaGFuZGxlVGh1bms7XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIGhhbmRsZVRodW5rKGEsIGIpIHtcbiAgICAgICAgICAgICAgICB2YXIgcmVuZGVyZWRBID0gYTtcbiAgICAgICAgICAgICAgICB2YXIgcmVuZGVyZWRCID0gYjtcblxuICAgICAgICAgICAgICAgIGlmIChpc1RodW5rKGIpKSB7XG4gICAgICAgICAgICAgICAgICAgIHJlbmRlcmVkQiA9IHJlbmRlclRodW5rKGIsIGEpO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIGlmIChpc1RodW5rKGEpKSB7XG4gICAgICAgICAgICAgICAgICAgIHJlbmRlcmVkQSA9IHJlbmRlclRodW5rKGEsIG51bGwpO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHJldHVybiB7XG4gICAgICAgICAgICAgICAgICAgIGE6IHJlbmRlcmVkQSxcbiAgICAgICAgICAgICAgICAgICAgYjogcmVuZGVyZWRCXG4gICAgICAgICAgICAgICAgfTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZnVuY3Rpb24gcmVuZGVyVGh1bmsodGh1bmssIHByZXZpb3VzKSB7XG4gICAgICAgICAgICAgICAgdmFyIHJlbmRlcmVkVGh1bmsgPSB0aHVuay52bm9kZTtcblxuICAgICAgICAgICAgICAgIGlmICghcmVuZGVyZWRUaHVuaykge1xuICAgICAgICAgICAgICAgICAgICByZW5kZXJlZFRodW5rID0gdGh1bmsudm5vZGUgPSB0aHVuay5yZW5kZXIocHJldmlvdXMpO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIGlmICghKGlzVk5vZGUocmVuZGVyZWRUaHVuaykgfHwgaXNWVGV4dChyZW5kZXJlZFRodW5rKSB8fCBpc1dpZGdldChyZW5kZXJlZFRodW5rKSkpIHtcbiAgICAgICAgICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKFwidGh1bmsgZGlkIG5vdCByZXR1cm4gYSB2YWxpZCBub2RlXCIpO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHJldHVybiByZW5kZXJlZFRodW5rO1xuICAgICAgICAgICAgfVxuICAgICAgICB9LCB7IFwiLi9pcy10aHVua1wiOiAyNSwgXCIuL2lzLXZub2RlXCI6IDI3LCBcIi4vaXMtdnRleHRcIjogMjgsIFwiLi9pcy13aWRnZXRcIjogMjkgfV0sIDI1OiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge1xuICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBpc1RodW5rO1xuXG4gICAgICAgICAgICBmdW5jdGlvbiBpc1RodW5rKHQpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gdCAmJiB0LnR5cGUgPT09IFwiVGh1bmtcIjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSwge31dLCAyNjogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHtcbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gaXNIb29rO1xuXG4gICAgICAgICAgICBmdW5jdGlvbiBpc0hvb2soaG9vaykge1xuICAgICAgICAgICAgICAgIHJldHVybiBob29rICYmICh0eXBlb2YgaG9vay5ob29rID09PSBcImZ1bmN0aW9uXCIgJiYgIWhvb2suaGFzT3duUHJvcGVydHkoXCJob29rXCIpIHx8IHR5cGVvZiBob29rLnVuaG9vayA9PT0gXCJmdW5jdGlvblwiICYmICFob29rLmhhc093blByb3BlcnR5KFwidW5ob29rXCIpKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSwge31dLCAyNzogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHtcbiAgICAgICAgICAgIHZhciB2ZXJzaW9uID0gcmVxdWlyZShcIi4vdmVyc2lvblwiKTtcblxuICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBpc1ZpcnR1YWxOb2RlO1xuXG4gICAgICAgICAgICBmdW5jdGlvbiBpc1ZpcnR1YWxOb2RlKHgpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4geCAmJiB4LnR5cGUgPT09IFwiVmlydHVhbE5vZGVcIiAmJiB4LnZlcnNpb24gPT09IHZlcnNpb247XG4gICAgICAgICAgICB9XG4gICAgICAgIH0sIHsgXCIuL3ZlcnNpb25cIjogMzAgfV0sIDI4OiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge1xuICAgICAgICAgICAgdmFyIHZlcnNpb24gPSByZXF1aXJlKFwiLi92ZXJzaW9uXCIpO1xuXG4gICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IGlzVmlydHVhbFRleHQ7XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIGlzVmlydHVhbFRleHQoeCkge1xuICAgICAgICAgICAgICAgIHJldHVybiB4ICYmIHgudHlwZSA9PT0gXCJWaXJ0dWFsVGV4dFwiICYmIHgudmVyc2lvbiA9PT0gdmVyc2lvbjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSwgeyBcIi4vdmVyc2lvblwiOiAzMCB9XSwgMjk6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IGlzV2lkZ2V0O1xuXG4gICAgICAgICAgICBmdW5jdGlvbiBpc1dpZGdldCh3KSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHcgJiYgdy50eXBlID09PSBcIldpZGdldFwiO1xuICAgICAgICAgICAgfVxuICAgICAgICB9LCB7fV0sIDMwOiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge1xuICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBcIjJcIjtcbiAgICAgICAgfSwge31dLCAzMTogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHtcbiAgICAgICAgICAgIHZhciB2ZXJzaW9uID0gcmVxdWlyZShcIi4vdmVyc2lvblwiKTtcbiAgICAgICAgICAgIHZhciBpc1ZOb2RlID0gcmVxdWlyZShcIi4vaXMtdm5vZGVcIik7XG4gICAgICAgICAgICB2YXIgaXNXaWRnZXQgPSByZXF1aXJlKFwiLi9pcy13aWRnZXRcIik7XG4gICAgICAgICAgICB2YXIgaXNUaHVuayA9IHJlcXVpcmUoXCIuL2lzLXRodW5rXCIpO1xuICAgICAgICAgICAgdmFyIGlzVkhvb2sgPSByZXF1aXJlKFwiLi9pcy12aG9va1wiKTtcblxuICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBWaXJ0dWFsTm9kZTtcblxuICAgICAgICAgICAgdmFyIG5vUHJvcGVydGllcyA9IHt9O1xuICAgICAgICAgICAgdmFyIG5vQ2hpbGRyZW4gPSBbXTtcblxuICAgICAgICAgICAgZnVuY3Rpb24gVmlydHVhbE5vZGUodGFnTmFtZSwgcHJvcGVydGllcywgY2hpbGRyZW4sIGtleSwgbmFtZXNwYWNlKSB7XG4gICAgICAgICAgICAgICAgdGhpcy50YWdOYW1lID0gdGFnTmFtZTtcbiAgICAgICAgICAgICAgICB0aGlzLnByb3BlcnRpZXMgPSBwcm9wZXJ0aWVzIHx8IG5vUHJvcGVydGllcztcbiAgICAgICAgICAgICAgICB0aGlzLmNoaWxkcmVuID0gY2hpbGRyZW4gfHwgbm9DaGlsZHJlbjtcbiAgICAgICAgICAgICAgICB0aGlzLmtleSA9IGtleSAhPSBudWxsID8gU3RyaW5nKGtleSkgOiB1bmRlZmluZWQ7XG4gICAgICAgICAgICAgICAgdGhpcy5uYW1lc3BhY2UgPSB0eXBlb2YgbmFtZXNwYWNlID09PSBcInN0cmluZ1wiID8gbmFtZXNwYWNlIDogbnVsbDtcblxuICAgICAgICAgICAgICAgIHZhciBjb3VudCA9IGNoaWxkcmVuICYmIGNoaWxkcmVuLmxlbmd0aCB8fCAwO1xuICAgICAgICAgICAgICAgIHZhciBkZXNjZW5kYW50cyA9IDA7XG4gICAgICAgICAgICAgICAgdmFyIGhhc1dpZGdldHMgPSBmYWxzZTtcbiAgICAgICAgICAgICAgICB2YXIgaGFzVGh1bmtzID0gZmFsc2U7XG4gICAgICAgICAgICAgICAgdmFyIGRlc2NlbmRhbnRIb29rcyA9IGZhbHNlO1xuICAgICAgICAgICAgICAgIHZhciBob29rcztcblxuICAgICAgICAgICAgICAgIGZvciAodmFyIHByb3BOYW1lIGluIHByb3BlcnRpZXMpIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKHByb3BlcnRpZXMuaGFzT3duUHJvcGVydHkocHJvcE5hbWUpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICB2YXIgcHJvcGVydHkgPSBwcm9wZXJ0aWVzW3Byb3BOYW1lXTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChpc1ZIb29rKHByb3BlcnR5KSAmJiBwcm9wZXJ0eS51bmhvb2spIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoIWhvb2tzKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGhvb2tzID0ge307XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaG9va3NbcHJvcE5hbWVdID0gcHJvcGVydHk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IGNvdW50OyBpKyspIHtcbiAgICAgICAgICAgICAgICAgICAgdmFyIGNoaWxkID0gY2hpbGRyZW5baV07XG4gICAgICAgICAgICAgICAgICAgIGlmIChpc1ZOb2RlKGNoaWxkKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgZGVzY2VuZGFudHMgKz0gY2hpbGQuY291bnQgfHwgMDtcblxuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKCFoYXNXaWRnZXRzICYmIGNoaWxkLmhhc1dpZGdldHMpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBoYXNXaWRnZXRzID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKCFoYXNUaHVua3MgJiYgY2hpbGQuaGFzVGh1bmtzKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaGFzVGh1bmtzID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKCFkZXNjZW5kYW50SG9va3MgJiYgKGNoaWxkLmhvb2tzIHx8IGNoaWxkLmRlc2NlbmRhbnRIb29rcykpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBkZXNjZW5kYW50SG9va3MgPSB0cnVlO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKCFoYXNXaWRnZXRzICYmIGlzV2lkZ2V0KGNoaWxkKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHR5cGVvZiBjaGlsZC5kZXN0cm95ID09PSBcImZ1bmN0aW9uXCIpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBoYXNXaWRnZXRzID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIGlmICghaGFzVGh1bmtzICYmIGlzVGh1bmsoY2hpbGQpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBoYXNUaHVua3MgPSB0cnVlO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgdGhpcy5jb3VudCA9IGNvdW50ICsgZGVzY2VuZGFudHM7XG4gICAgICAgICAgICAgICAgdGhpcy5oYXNXaWRnZXRzID0gaGFzV2lkZ2V0cztcbiAgICAgICAgICAgICAgICB0aGlzLmhhc1RodW5rcyA9IGhhc1RodW5rcztcbiAgICAgICAgICAgICAgICB0aGlzLmhvb2tzID0gaG9va3M7XG4gICAgICAgICAgICAgICAgdGhpcy5kZXNjZW5kYW50SG9va3MgPSBkZXNjZW5kYW50SG9va3M7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIFZpcnR1YWxOb2RlLnByb3RvdHlwZS52ZXJzaW9uID0gdmVyc2lvbjtcbiAgICAgICAgICAgIFZpcnR1YWxOb2RlLnByb3RvdHlwZS50eXBlID0gXCJWaXJ0dWFsTm9kZVwiO1xuICAgICAgICB9LCB7IFwiLi9pcy10aHVua1wiOiAyNSwgXCIuL2lzLXZob29rXCI6IDI2LCBcIi4vaXMtdm5vZGVcIjogMjcsIFwiLi9pcy13aWRnZXRcIjogMjksIFwiLi92ZXJzaW9uXCI6IDMwIH1dLCAzMjogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHtcbiAgICAgICAgICAgIHZhciB2ZXJzaW9uID0gcmVxdWlyZShcIi4vdmVyc2lvblwiKTtcblxuICAgICAgICAgICAgVmlydHVhbFBhdGNoLk5PTkUgPSAwO1xuICAgICAgICAgICAgVmlydHVhbFBhdGNoLlZURVhUID0gMTtcbiAgICAgICAgICAgIFZpcnR1YWxQYXRjaC5WTk9ERSA9IDI7XG4gICAgICAgICAgICBWaXJ0dWFsUGF0Y2guV0lER0VUID0gMztcbiAgICAgICAgICAgIFZpcnR1YWxQYXRjaC5QUk9QUyA9IDQ7XG4gICAgICAgICAgICBWaXJ0dWFsUGF0Y2guT1JERVIgPSA1O1xuICAgICAgICAgICAgVmlydHVhbFBhdGNoLklOU0VSVCA9IDY7XG4gICAgICAgICAgICBWaXJ0dWFsUGF0Y2guUkVNT1ZFID0gNztcbiAgICAgICAgICAgIFZpcnR1YWxQYXRjaC5USFVOSyA9IDg7XG5cbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gVmlydHVhbFBhdGNoO1xuXG4gICAgICAgICAgICBmdW5jdGlvbiBWaXJ0dWFsUGF0Y2godHlwZSwgdk5vZGUsIHBhdGNoKSB7XG4gICAgICAgICAgICAgICAgdGhpcy50eXBlID0gTnVtYmVyKHR5cGUpO1xuICAgICAgICAgICAgICAgIHRoaXMudk5vZGUgPSB2Tm9kZTtcbiAgICAgICAgICAgICAgICB0aGlzLnBhdGNoID0gcGF0Y2g7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIFZpcnR1YWxQYXRjaC5wcm90b3R5cGUudmVyc2lvbiA9IHZlcnNpb247XG4gICAgICAgICAgICBWaXJ0dWFsUGF0Y2gucHJvdG90eXBlLnR5cGUgPSBcIlZpcnR1YWxQYXRjaFwiO1xuICAgICAgICB9LCB7IFwiLi92ZXJzaW9uXCI6IDMwIH1dLCAzMzogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHtcbiAgICAgICAgICAgIHZhciB2ZXJzaW9uID0gcmVxdWlyZShcIi4vdmVyc2lvblwiKTtcblxuICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBWaXJ0dWFsVGV4dDtcblxuICAgICAgICAgICAgZnVuY3Rpb24gVmlydHVhbFRleHQodGV4dCkge1xuICAgICAgICAgICAgICAgIHRoaXMudGV4dCA9IFN0cmluZyh0ZXh0KTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgVmlydHVhbFRleHQucHJvdG90eXBlLnZlcnNpb24gPSB2ZXJzaW9uO1xuICAgICAgICAgICAgVmlydHVhbFRleHQucHJvdG90eXBlLnR5cGUgPSBcIlZpcnR1YWxUZXh0XCI7XG4gICAgICAgIH0sIHsgXCIuL3ZlcnNpb25cIjogMzAgfV0sIDM0OiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge1xuICAgICAgICAgICAgdmFyIGlzT2JqZWN0ID0gcmVxdWlyZShcImlzLW9iamVjdFwiKTtcbiAgICAgICAgICAgIHZhciBpc0hvb2sgPSByZXF1aXJlKFwiLi4vdm5vZGUvaXMtdmhvb2tcIik7XG5cbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gZGlmZlByb3BzO1xuXG4gICAgICAgICAgICBmdW5jdGlvbiBkaWZmUHJvcHMoYSwgYikge1xuICAgICAgICAgICAgICAgIHZhciBkaWZmO1xuXG4gICAgICAgICAgICAgICAgZm9yICh2YXIgYUtleSBpbiBhKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmICghKGFLZXkgaW4gYikpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGRpZmYgPSBkaWZmIHx8IHt9O1xuICAgICAgICAgICAgICAgICAgICAgICAgZGlmZlthS2V5XSA9IHVuZGVmaW5lZDtcbiAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgIHZhciBhVmFsdWUgPSBhW2FLZXldO1xuICAgICAgICAgICAgICAgICAgICB2YXIgYlZhbHVlID0gYlthS2V5XTtcblxuICAgICAgICAgICAgICAgICAgICBpZiAoYVZhbHVlID09PSBiVmFsdWUpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnRpbnVlO1xuICAgICAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKGlzT2JqZWN0KGFWYWx1ZSkgJiYgaXNPYmplY3QoYlZhbHVlKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGdldFByb3RvdHlwZShiVmFsdWUpICE9PSBnZXRQcm90b3R5cGUoYVZhbHVlKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRpZmYgPSBkaWZmIHx8IHt9O1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRpZmZbYUtleV0gPSBiVmFsdWU7XG4gICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKGlzSG9vayhiVmFsdWUpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgZGlmZiA9IGRpZmYgfHwge307XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgZGlmZlthS2V5XSA9IGJWYWx1ZTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdmFyIG9iamVjdERpZmYgPSBkaWZmUHJvcHMoYVZhbHVlLCBiVmFsdWUpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChvYmplY3REaWZmKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRpZmYgPSBkaWZmIHx8IHt9O1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBkaWZmW2FLZXldID0gb2JqZWN0RGlmZjtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBkaWZmID0gZGlmZiB8fCB7fTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGRpZmZbYUtleV0gPSBiVmFsdWU7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICBmb3IgKHZhciBiS2V5IGluIGIpIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKCEoYktleSBpbiBhKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgZGlmZiA9IGRpZmYgfHwge307XG4gICAgICAgICAgICAgICAgICAgICAgICBkaWZmW2JLZXldID0gYltiS2V5XTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHJldHVybiBkaWZmO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBmdW5jdGlvbiBnZXRQcm90b3R5cGUodmFsdWUpIHtcbiAgICAgICAgICAgICAgICBpZiAoT2JqZWN0LmdldFByb3RvdHlwZU9mKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBPYmplY3QuZ2V0UHJvdG90eXBlT2YodmFsdWUpO1xuICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAodmFsdWUuX19wcm90b19fKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiB2YWx1ZS5fX3Byb3RvX187XG4gICAgICAgICAgICAgICAgfSBlbHNlIGlmICh2YWx1ZS5jb25zdHJ1Y3Rvcikge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gdmFsdWUuY29uc3RydWN0b3IucHJvdG90eXBlO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgfSwgeyBcIi4uL3Zub2RlL2lzLXZob29rXCI6IDI2LCBcImlzLW9iamVjdFwiOiAxMSB9XSwgMzU6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICB2YXIgaXNBcnJheSA9IHJlcXVpcmUoXCJ4LWlzLWFycmF5XCIpO1xuXG4gICAgICAgICAgICB2YXIgVlBhdGNoID0gcmVxdWlyZShcIi4uL3Zub2RlL3ZwYXRjaFwiKTtcbiAgICAgICAgICAgIHZhciBpc1ZOb2RlID0gcmVxdWlyZShcIi4uL3Zub2RlL2lzLXZub2RlXCIpO1xuICAgICAgICAgICAgdmFyIGlzVlRleHQgPSByZXF1aXJlKFwiLi4vdm5vZGUvaXMtdnRleHRcIik7XG4gICAgICAgICAgICB2YXIgaXNXaWRnZXQgPSByZXF1aXJlKFwiLi4vdm5vZGUvaXMtd2lkZ2V0XCIpO1xuICAgICAgICAgICAgdmFyIGlzVGh1bmsgPSByZXF1aXJlKFwiLi4vdm5vZGUvaXMtdGh1bmtcIik7XG4gICAgICAgICAgICB2YXIgaGFuZGxlVGh1bmsgPSByZXF1aXJlKFwiLi4vdm5vZGUvaGFuZGxlLXRodW5rXCIpO1xuXG4gICAgICAgICAgICB2YXIgZGlmZlByb3BzID0gcmVxdWlyZShcIi4vZGlmZi1wcm9wc1wiKTtcblxuICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBkaWZmO1xuXG4gICAgICAgICAgICBmdW5jdGlvbiBkaWZmKGEsIGIpIHtcbiAgICAgICAgICAgICAgICB2YXIgcGF0Y2ggPSB7IGE6IGEgfTtcbiAgICAgICAgICAgICAgICB3YWxrKGEsIGIsIHBhdGNoLCAwKTtcbiAgICAgICAgICAgICAgICByZXR1cm4gcGF0Y2g7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIHdhbGsoYSwgYiwgcGF0Y2gsIGluZGV4KSB7XG4gICAgICAgICAgICAgICAgaWYgKGEgPT09IGIpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHZhciBhcHBseSA9IHBhdGNoW2luZGV4XTtcbiAgICAgICAgICAgICAgICB2YXIgYXBwbHlDbGVhciA9IGZhbHNlO1xuXG4gICAgICAgICAgICAgICAgaWYgKGlzVGh1bmsoYSkgfHwgaXNUaHVuayhiKSkge1xuICAgICAgICAgICAgICAgICAgICB0aHVua3MoYSwgYiwgcGF0Y2gsIGluZGV4KTtcbiAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKGIgPT0gbnVsbCkge1xuXG4gICAgICAgICAgICAgICAgICAgIC8vIElmIGEgaXMgYSB3aWRnZXQgd2Ugd2lsbCBhZGQgYSByZW1vdmUgcGF0Y2ggZm9yIGl0XG4gICAgICAgICAgICAgICAgICAgIC8vIE90aGVyd2lzZSBhbnkgY2hpbGQgd2lkZ2V0cy9ob29rcyBtdXN0IGJlIGRlc3Ryb3llZC5cbiAgICAgICAgICAgICAgICAgICAgLy8gVGhpcyBwcmV2ZW50cyBhZGRpbmcgdHdvIHJlbW92ZSBwYXRjaGVzIGZvciBhIHdpZGdldC5cbiAgICAgICAgICAgICAgICAgICAgaWYgKCFpc1dpZGdldChhKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgY2xlYXJTdGF0ZShhLCBwYXRjaCwgaW5kZXgpO1xuICAgICAgICAgICAgICAgICAgICAgICAgYXBwbHkgPSBwYXRjaFtpbmRleF07XG4gICAgICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgICAgICBhcHBseSA9IGFwcGVuZFBhdGNoKGFwcGx5LCBuZXcgVlBhdGNoKFZQYXRjaC5SRU1PVkUsIGEsIGIpKTtcbiAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKGlzVk5vZGUoYikpIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKGlzVk5vZGUoYSkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChhLnRhZ05hbWUgPT09IGIudGFnTmFtZSAmJiBhLm5hbWVzcGFjZSA9PT0gYi5uYW1lc3BhY2UgJiYgYS5rZXkgPT09IGIua2V5KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdmFyIHByb3BzUGF0Y2ggPSBkaWZmUHJvcHMoYS5wcm9wZXJ0aWVzLCBiLnByb3BlcnRpZXMpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChwcm9wc1BhdGNoKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGFwcGx5ID0gYXBwZW5kUGF0Y2goYXBwbHksIG5ldyBWUGF0Y2goVlBhdGNoLlBST1BTLCBhLCBwcm9wc1BhdGNoKSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGFwcGx5ID0gZGlmZkNoaWxkcmVuKGEsIGIsIHBhdGNoLCBhcHBseSwgaW5kZXgpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBhcHBseSA9IGFwcGVuZFBhdGNoKGFwcGx5LCBuZXcgVlBhdGNoKFZQYXRjaC5WTk9ERSwgYSwgYikpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGFwcGx5Q2xlYXIgPSB0cnVlO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgYXBwbHkgPSBhcHBlbmRQYXRjaChhcHBseSwgbmV3IFZQYXRjaChWUGF0Y2guVk5PREUsIGEsIGIpKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGFwcGx5Q2xlYXIgPSB0cnVlO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfSBlbHNlIGlmIChpc1ZUZXh0KGIpKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmICghaXNWVGV4dChhKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgYXBwbHkgPSBhcHBlbmRQYXRjaChhcHBseSwgbmV3IFZQYXRjaChWUGF0Y2guVlRFWFQsIGEsIGIpKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGFwcGx5Q2xlYXIgPSB0cnVlO1xuICAgICAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKGEudGV4dCAhPT0gYi50ZXh0KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBhcHBseSA9IGFwcGVuZFBhdGNoKGFwcGx5LCBuZXcgVlBhdGNoKFZQYXRjaC5WVEVYVCwgYSwgYikpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfSBlbHNlIGlmIChpc1dpZGdldChiKSkge1xuICAgICAgICAgICAgICAgICAgICBpZiAoIWlzV2lkZ2V0KGEpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBhcHBseUNsZWFyID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgIGFwcGx5ID0gYXBwZW5kUGF0Y2goYXBwbHksIG5ldyBWUGF0Y2goVlBhdGNoLldJREdFVCwgYSwgYikpO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIGlmIChhcHBseSkge1xuICAgICAgICAgICAgICAgICAgICBwYXRjaFtpbmRleF0gPSBhcHBseTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICBpZiAoYXBwbHlDbGVhcikge1xuICAgICAgICAgICAgICAgICAgICBjbGVhclN0YXRlKGEsIHBhdGNoLCBpbmRleCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBmdW5jdGlvbiBkaWZmQ2hpbGRyZW4oYSwgYiwgcGF0Y2gsIGFwcGx5LCBpbmRleCkge1xuICAgICAgICAgICAgICAgIHZhciBhQ2hpbGRyZW4gPSBhLmNoaWxkcmVuO1xuICAgICAgICAgICAgICAgIHZhciBvcmRlcmVkU2V0ID0gcmVvcmRlcihhQ2hpbGRyZW4sIGIuY2hpbGRyZW4pO1xuICAgICAgICAgICAgICAgIHZhciBiQ2hpbGRyZW4gPSBvcmRlcmVkU2V0LmNoaWxkcmVuO1xuXG4gICAgICAgICAgICAgICAgdmFyIGFMZW4gPSBhQ2hpbGRyZW4ubGVuZ3RoO1xuICAgICAgICAgICAgICAgIHZhciBiTGVuID0gYkNoaWxkcmVuLmxlbmd0aDtcbiAgICAgICAgICAgICAgICB2YXIgbGVuID0gYUxlbiA+IGJMZW4gPyBhTGVuIDogYkxlbjtcblxuICAgICAgICAgICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgbGVuOyBpKyspIHtcbiAgICAgICAgICAgICAgICAgICAgdmFyIGxlZnROb2RlID0gYUNoaWxkcmVuW2ldO1xuICAgICAgICAgICAgICAgICAgICB2YXIgcmlnaHROb2RlID0gYkNoaWxkcmVuW2ldO1xuICAgICAgICAgICAgICAgICAgICBpbmRleCArPSAxO1xuXG4gICAgICAgICAgICAgICAgICAgIGlmICghbGVmdE5vZGUpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChyaWdodE5vZGUpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBFeGNlc3Mgbm9kZXMgaW4gYiBuZWVkIHRvIGJlIGFkZGVkXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgYXBwbHkgPSBhcHBlbmRQYXRjaChhcHBseSwgbmV3IFZQYXRjaChWUGF0Y2guSU5TRVJULCBudWxsLCByaWdodE5vZGUpKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHdhbGsobGVmdE5vZGUsIHJpZ2h0Tm9kZSwgcGF0Y2gsIGluZGV4KTtcbiAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgIGlmIChpc1ZOb2RlKGxlZnROb2RlKSAmJiBsZWZ0Tm9kZS5jb3VudCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgaW5kZXggKz0gbGVmdE5vZGUuY291bnQ7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICBpZiAob3JkZXJlZFNldC5tb3Zlcykge1xuICAgICAgICAgICAgICAgICAgICAvLyBSZW9yZGVyIG5vZGVzIGxhc3RcbiAgICAgICAgICAgICAgICAgICAgYXBwbHkgPSBhcHBlbmRQYXRjaChhcHBseSwgbmV3IFZQYXRjaChWUGF0Y2guT1JERVIsIGEsIG9yZGVyZWRTZXQubW92ZXMpKTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICByZXR1cm4gYXBwbHk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIGNsZWFyU3RhdGUodk5vZGUsIHBhdGNoLCBpbmRleCkge1xuICAgICAgICAgICAgICAgIC8vIFRPRE86IE1ha2UgdGhpcyBhIHNpbmdsZSB3YWxrLCBub3QgdHdvXG4gICAgICAgICAgICAgICAgdW5ob29rKHZOb2RlLCBwYXRjaCwgaW5kZXgpO1xuICAgICAgICAgICAgICAgIGRlc3Ryb3lXaWRnZXRzKHZOb2RlLCBwYXRjaCwgaW5kZXgpO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAvLyBQYXRjaCByZWNvcmRzIGZvciBhbGwgZGVzdHJveWVkIHdpZGdldHMgbXVzdCBiZSBhZGRlZCBiZWNhdXNlIHdlIG5lZWRcbiAgICAgICAgICAgIC8vIGEgRE9NIG5vZGUgcmVmZXJlbmNlIGZvciB0aGUgZGVzdHJveSBmdW5jdGlvblxuICAgICAgICAgICAgZnVuY3Rpb24gZGVzdHJveVdpZGdldHModk5vZGUsIHBhdGNoLCBpbmRleCkge1xuICAgICAgICAgICAgICAgIGlmIChpc1dpZGdldCh2Tm9kZSkpIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKHR5cGVvZiB2Tm9kZS5kZXN0cm95ID09PSBcImZ1bmN0aW9uXCIpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHBhdGNoW2luZGV4XSA9IGFwcGVuZFBhdGNoKHBhdGNoW2luZGV4XSwgbmV3IFZQYXRjaChWUGF0Y2guUkVNT1ZFLCB2Tm9kZSwgbnVsbCkpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfSBlbHNlIGlmIChpc1ZOb2RlKHZOb2RlKSAmJiAodk5vZGUuaGFzV2lkZ2V0cyB8fCB2Tm9kZS5oYXNUaHVua3MpKSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciBjaGlsZHJlbiA9IHZOb2RlLmNoaWxkcmVuO1xuICAgICAgICAgICAgICAgICAgICB2YXIgbGVuID0gY2hpbGRyZW4ubGVuZ3RoO1xuICAgICAgICAgICAgICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IGxlbjsgaSsrKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICB2YXIgY2hpbGQgPSBjaGlsZHJlbltpXTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGluZGV4ICs9IDE7XG5cbiAgICAgICAgICAgICAgICAgICAgICAgIGRlc3Ryb3lXaWRnZXRzKGNoaWxkLCBwYXRjaCwgaW5kZXgpO1xuXG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoaXNWTm9kZShjaGlsZCkgJiYgY2hpbGQuY291bnQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpbmRleCArPSBjaGlsZC5jb3VudDtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoaXNUaHVuayh2Tm9kZSkpIHtcbiAgICAgICAgICAgICAgICAgICAgdGh1bmtzKHZOb2RlLCBudWxsLCBwYXRjaCwgaW5kZXgpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgLy8gQ3JlYXRlIGEgc3ViLXBhdGNoIGZvciB0aHVua3NcbiAgICAgICAgICAgIGZ1bmN0aW9uIHRodW5rcyhhLCBiLCBwYXRjaCwgaW5kZXgpIHtcbiAgICAgICAgICAgICAgICB2YXIgbm9kZXMgPSBoYW5kbGVUaHVuayhhLCBiKTtcbiAgICAgICAgICAgICAgICB2YXIgdGh1bmtQYXRjaCA9IGRpZmYobm9kZXMuYSwgbm9kZXMuYik7XG4gICAgICAgICAgICAgICAgaWYgKGhhc1BhdGNoZXModGh1bmtQYXRjaCkpIHtcbiAgICAgICAgICAgICAgICAgICAgcGF0Y2hbaW5kZXhdID0gbmV3IFZQYXRjaChWUGF0Y2guVEhVTkssIG51bGwsIHRodW5rUGF0Y2gpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZnVuY3Rpb24gaGFzUGF0Y2hlcyhwYXRjaCkge1xuICAgICAgICAgICAgICAgIGZvciAodmFyIGluZGV4IGluIHBhdGNoKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmIChpbmRleCAhPT0gXCJhXCIpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAvLyBFeGVjdXRlIGhvb2tzIHdoZW4gdHdvIG5vZGVzIGFyZSBpZGVudGljYWxcbiAgICAgICAgICAgIGZ1bmN0aW9uIHVuaG9vayh2Tm9kZSwgcGF0Y2gsIGluZGV4KSB7XG4gICAgICAgICAgICAgICAgaWYgKGlzVk5vZGUodk5vZGUpKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmICh2Tm9kZS5ob29rcykge1xuICAgICAgICAgICAgICAgICAgICAgICAgcGF0Y2hbaW5kZXhdID0gYXBwZW5kUGF0Y2gocGF0Y2hbaW5kZXhdLCBuZXcgVlBhdGNoKFZQYXRjaC5QUk9QUywgdk5vZGUsIHVuZGVmaW5lZEtleXModk5vZGUuaG9va3MpKSk7XG4gICAgICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgICAgICBpZiAodk5vZGUuZGVzY2VuZGFudEhvb2tzIHx8IHZOb2RlLmhhc1RodW5rcykge1xuICAgICAgICAgICAgICAgICAgICAgICAgdmFyIGNoaWxkcmVuID0gdk5vZGUuY2hpbGRyZW47XG4gICAgICAgICAgICAgICAgICAgICAgICB2YXIgbGVuID0gY2hpbGRyZW4ubGVuZ3RoO1xuICAgICAgICAgICAgICAgICAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCBsZW47IGkrKykge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZhciBjaGlsZCA9IGNoaWxkcmVuW2ldO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGluZGV4ICs9IDE7XG5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB1bmhvb2soY2hpbGQsIHBhdGNoLCBpbmRleCk7XG5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoaXNWTm9kZShjaGlsZCkgJiYgY2hpbGQuY291bnQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaW5kZXggKz0gY2hpbGQuY291bnQ7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfSBlbHNlIGlmIChpc1RodW5rKHZOb2RlKSkge1xuICAgICAgICAgICAgICAgICAgICB0aHVua3Modk5vZGUsIG51bGwsIHBhdGNoLCBpbmRleCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBmdW5jdGlvbiB1bmRlZmluZWRLZXlzKG9iaikge1xuICAgICAgICAgICAgICAgIHZhciByZXN1bHQgPSB7fTtcblxuICAgICAgICAgICAgICAgIGZvciAodmFyIGtleSBpbiBvYmopIHtcbiAgICAgICAgICAgICAgICAgICAgcmVzdWx0W2tleV0gPSB1bmRlZmluZWQ7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgcmV0dXJuIHJlc3VsdDtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgLy8gTGlzdCBkaWZmLCBuYWl2ZSBsZWZ0IHRvIHJpZ2h0IHJlb3JkZXJpbmdcbiAgICAgICAgICAgIGZ1bmN0aW9uIHJlb3JkZXIoYUNoaWxkcmVuLCBiQ2hpbGRyZW4pIHtcbiAgICAgICAgICAgICAgICAvLyBPKE0pIHRpbWUsIE8oTSkgbWVtb3J5XG4gICAgICAgICAgICAgICAgdmFyIGJDaGlsZEluZGV4ID0ga2V5SW5kZXgoYkNoaWxkcmVuKTtcbiAgICAgICAgICAgICAgICB2YXIgYktleXMgPSBiQ2hpbGRJbmRleC5rZXlzO1xuICAgICAgICAgICAgICAgIHZhciBiRnJlZSA9IGJDaGlsZEluZGV4LmZyZWU7XG5cbiAgICAgICAgICAgICAgICBpZiAoYkZyZWUubGVuZ3RoID09PSBiQ2hpbGRyZW4ubGVuZ3RoKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiB7XG4gICAgICAgICAgICAgICAgICAgICAgICBjaGlsZHJlbjogYkNoaWxkcmVuLFxuICAgICAgICAgICAgICAgICAgICAgICAgbW92ZXM6IG51bGxcbiAgICAgICAgICAgICAgICAgICAgfTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAvLyBPKE4pIHRpbWUsIE8oTikgbWVtb3J5XG4gICAgICAgICAgICAgICAgdmFyIGFDaGlsZEluZGV4ID0ga2V5SW5kZXgoYUNoaWxkcmVuKTtcbiAgICAgICAgICAgICAgICB2YXIgYUtleXMgPSBhQ2hpbGRJbmRleC5rZXlzO1xuICAgICAgICAgICAgICAgIHZhciBhRnJlZSA9IGFDaGlsZEluZGV4LmZyZWU7XG5cbiAgICAgICAgICAgICAgICBpZiAoYUZyZWUubGVuZ3RoID09PSBhQ2hpbGRyZW4ubGVuZ3RoKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiB7XG4gICAgICAgICAgICAgICAgICAgICAgICBjaGlsZHJlbjogYkNoaWxkcmVuLFxuICAgICAgICAgICAgICAgICAgICAgICAgbW92ZXM6IG51bGxcbiAgICAgICAgICAgICAgICAgICAgfTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAvLyBPKE1BWChOLCBNKSkgbWVtb3J5XG4gICAgICAgICAgICAgICAgdmFyIG5ld0NoaWxkcmVuID0gW107XG5cbiAgICAgICAgICAgICAgICB2YXIgZnJlZUluZGV4ID0gMDtcbiAgICAgICAgICAgICAgICB2YXIgZnJlZUNvdW50ID0gYkZyZWUubGVuZ3RoO1xuICAgICAgICAgICAgICAgIHZhciBkZWxldGVkSXRlbXMgPSAwO1xuXG4gICAgICAgICAgICAgICAgLy8gSXRlcmF0ZSB0aHJvdWdoIGEgYW5kIG1hdGNoIGEgbm9kZSBpbiBiXG4gICAgICAgICAgICAgICAgLy8gTyhOKSB0aW1lLFxuICAgICAgICAgICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgYUNoaWxkcmVuLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciBhSXRlbSA9IGFDaGlsZHJlbltpXTtcbiAgICAgICAgICAgICAgICAgICAgdmFyIGl0ZW1JbmRleDtcblxuICAgICAgICAgICAgICAgICAgICBpZiAoYUl0ZW0ua2V5KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoYktleXMuaGFzT3duUHJvcGVydHkoYUl0ZW0ua2V5KSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIE1hdGNoIHVwIHRoZSBvbGQga2V5c1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGl0ZW1JbmRleCA9IGJLZXlzW2FJdGVtLmtleV07XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgbmV3Q2hpbGRyZW4ucHVzaChiQ2hpbGRyZW5baXRlbUluZGV4XSk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIFJlbW92ZSBvbGQga2V5ZWQgaXRlbXNcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpdGVtSW5kZXggPSBpIC0gZGVsZXRlZEl0ZW1zKys7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgbmV3Q2hpbGRyZW4ucHVzaChudWxsKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIE1hdGNoIHRoZSBpdGVtIGluIGEgd2l0aCB0aGUgbmV4dCBmcmVlIGl0ZW0gaW4gYlxuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGZyZWVJbmRleCA8IGZyZWVDb3VudCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGl0ZW1JbmRleCA9IGJGcmVlW2ZyZWVJbmRleCsrXTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBuZXdDaGlsZHJlbi5wdXNoKGJDaGlsZHJlbltpdGVtSW5kZXhdKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gVGhlcmUgYXJlIG5vIGZyZWUgaXRlbXMgaW4gYiB0byBtYXRjaCB3aXRoXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gdGhlIGZyZWUgaXRlbXMgaW4gYSwgc28gdGhlIGV4dHJhIGZyZWUgbm9kZXNcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBhcmUgZGVsZXRlZC5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpdGVtSW5kZXggPSBpIC0gZGVsZXRlZEl0ZW1zKys7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgbmV3Q2hpbGRyZW4ucHVzaChudWxsKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHZhciBsYXN0RnJlZUluZGV4ID0gZnJlZUluZGV4ID49IGJGcmVlLmxlbmd0aCA/IGJDaGlsZHJlbi5sZW5ndGggOiBiRnJlZVtmcmVlSW5kZXhdO1xuXG4gICAgICAgICAgICAgICAgLy8gSXRlcmF0ZSB0aHJvdWdoIGIgYW5kIGFwcGVuZCBhbnkgbmV3IGtleXNcbiAgICAgICAgICAgICAgICAvLyBPKE0pIHRpbWVcbiAgICAgICAgICAgICAgICBmb3IgKHZhciBqID0gMDsgaiA8IGJDaGlsZHJlbi5sZW5ndGg7IGorKykge1xuICAgICAgICAgICAgICAgICAgICB2YXIgbmV3SXRlbSA9IGJDaGlsZHJlbltqXTtcblxuICAgICAgICAgICAgICAgICAgICBpZiAobmV3SXRlbS5rZXkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmICghYUtleXMuaGFzT3duUHJvcGVydHkobmV3SXRlbS5rZXkpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gQWRkIGFueSBuZXcga2V5ZWQgaXRlbXNcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBXZSBhcmUgYWRkaW5nIG5ldyBpdGVtcyB0byB0aGUgZW5kIGFuZCB0aGVuIHNvcnRpbmcgdGhlbVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIGluIHBsYWNlLiBJbiBmdXR1cmUgd2Ugc2hvdWxkIGluc2VydCBuZXcgaXRlbXMgaW4gcGxhY2UuXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgbmV3Q2hpbGRyZW4ucHVzaChuZXdJdGVtKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIGlmIChqID49IGxhc3RGcmVlSW5kZXgpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIEFkZCBhbnkgbGVmdG92ZXIgbm9uLWtleWVkIGl0ZW1zXG4gICAgICAgICAgICAgICAgICAgICAgICBuZXdDaGlsZHJlbi5wdXNoKG5ld0l0ZW0pO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgdmFyIHNpbXVsYXRlID0gbmV3Q2hpbGRyZW4uc2xpY2UoKTtcbiAgICAgICAgICAgICAgICB2YXIgc2ltdWxhdGVJbmRleCA9IDA7XG4gICAgICAgICAgICAgICAgdmFyIHJlbW92ZXMgPSBbXTtcbiAgICAgICAgICAgICAgICB2YXIgaW5zZXJ0cyA9IFtdO1xuICAgICAgICAgICAgICAgIHZhciBzaW11bGF0ZUl0ZW07XG5cbiAgICAgICAgICAgICAgICBmb3IgKHZhciBrID0gMDsgayA8IGJDaGlsZHJlbi5sZW5ndGg7KSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciB3YW50ZWRJdGVtID0gYkNoaWxkcmVuW2tdO1xuICAgICAgICAgICAgICAgICAgICBzaW11bGF0ZUl0ZW0gPSBzaW11bGF0ZVtzaW11bGF0ZUluZGV4XTtcblxuICAgICAgICAgICAgICAgICAgICAvLyByZW1vdmUgaXRlbXNcbiAgICAgICAgICAgICAgICAgICAgd2hpbGUgKHNpbXVsYXRlSXRlbSA9PT0gbnVsbCAmJiBzaW11bGF0ZS5sZW5ndGgpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJlbW92ZXMucHVzaChyZW1vdmUoc2ltdWxhdGUsIHNpbXVsYXRlSW5kZXgsIG51bGwpKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIHNpbXVsYXRlSXRlbSA9IHNpbXVsYXRlW3NpbXVsYXRlSW5kZXhdO1xuICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgaWYgKCFzaW11bGF0ZUl0ZW0gfHwgc2ltdWxhdGVJdGVtLmtleSAhPT0gd2FudGVkSXRlbS5rZXkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIGlmIHdlIG5lZWQgYSBrZXkgaW4gdGhpcyBwb3NpdGlvbi4uLlxuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHdhbnRlZEl0ZW0ua2V5KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHNpbXVsYXRlSXRlbSAmJiBzaW11bGF0ZUl0ZW0ua2V5KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIGlmIGFuIGluc2VydCBkb2Vzbid0IHB1dCB0aGlzIGtleSBpbiBwbGFjZSwgaXQgbmVlZHMgdG8gbW92ZVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoYktleXNbc2ltdWxhdGVJdGVtLmtleV0gIT09IGsgKyAxKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICByZW1vdmVzLnB1c2gocmVtb3ZlKHNpbXVsYXRlLCBzaW11bGF0ZUluZGV4LCBzaW11bGF0ZUl0ZW0ua2V5KSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzaW11bGF0ZUl0ZW0gPSBzaW11bGF0ZVtzaW11bGF0ZUluZGV4XTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIGlmIHRoZSByZW1vdmUgZGlkbid0IHB1dCB0aGUgd2FudGVkIGl0ZW0gaW4gcGxhY2UsIHdlIG5lZWQgdG8gaW5zZXJ0IGl0XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoIXNpbXVsYXRlSXRlbSB8fCBzaW11bGF0ZUl0ZW0ua2V5ICE9PSB3YW50ZWRJdGVtLmtleSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGluc2VydHMucHVzaCh7IGtleTogd2FudGVkSXRlbS5rZXksIHRvOiBrIH0pO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gaXRlbXMgYXJlIG1hdGNoaW5nLCBzbyBza2lwIGFoZWFkXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzaW11bGF0ZUluZGV4Kys7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpbnNlcnRzLnB1c2goeyBrZXk6IHdhbnRlZEl0ZW0ua2V5LCB0bzogayB9KTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGluc2VydHMucHVzaCh7IGtleTogd2FudGVkSXRlbS5rZXksIHRvOiBrIH0pO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBrKys7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAvLyBhIGtleSBpbiBzaW11bGF0ZSBoYXMgbm8gbWF0Y2hpbmcgd2FudGVkIGtleSwgcmVtb3ZlIGl0XG4gICAgICAgICAgICAgICAgICAgICAgICBlbHNlIGlmIChzaW11bGF0ZUl0ZW0gJiYgc2ltdWxhdGVJdGVtLmtleSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlbW92ZXMucHVzaChyZW1vdmUoc2ltdWxhdGUsIHNpbXVsYXRlSW5kZXgsIHNpbXVsYXRlSXRlbS5rZXkpKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHNpbXVsYXRlSW5kZXgrKztcbiAgICAgICAgICAgICAgICAgICAgICAgIGsrKztcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIC8vIHJlbW92ZSBhbGwgdGhlIHJlbWFpbmluZyBub2RlcyBmcm9tIHNpbXVsYXRlXG4gICAgICAgICAgICAgICAgd2hpbGUgKHNpbXVsYXRlSW5kZXggPCBzaW11bGF0ZS5sZW5ndGgpIHtcbiAgICAgICAgICAgICAgICAgICAgc2ltdWxhdGVJdGVtID0gc2ltdWxhdGVbc2ltdWxhdGVJbmRleF07XG4gICAgICAgICAgICAgICAgICAgIHJlbW92ZXMucHVzaChyZW1vdmUoc2ltdWxhdGUsIHNpbXVsYXRlSW5kZXgsIHNpbXVsYXRlSXRlbSAmJiBzaW11bGF0ZUl0ZW0ua2V5KSk7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgLy8gSWYgdGhlIG9ubHkgbW92ZXMgd2UgaGF2ZSBhcmUgZGVsZXRlcyB0aGVuIHdlIGNhbiBqdXN0XG4gICAgICAgICAgICAgICAgLy8gbGV0IHRoZSBkZWxldGUgcGF0Y2ggcmVtb3ZlIHRoZXNlIGl0ZW1zLlxuICAgICAgICAgICAgICAgIGlmIChyZW1vdmVzLmxlbmd0aCA9PT0gZGVsZXRlZEl0ZW1zICYmICFpbnNlcnRzLmxlbmd0aCkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgICAgICAgICAgICAgY2hpbGRyZW46IG5ld0NoaWxkcmVuLFxuICAgICAgICAgICAgICAgICAgICAgICAgbW92ZXM6IG51bGxcbiAgICAgICAgICAgICAgICAgICAgfTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgICAgICAgICBjaGlsZHJlbjogbmV3Q2hpbGRyZW4sXG4gICAgICAgICAgICAgICAgICAgIG1vdmVzOiB7XG4gICAgICAgICAgICAgICAgICAgICAgICByZW1vdmVzOiByZW1vdmVzLFxuICAgICAgICAgICAgICAgICAgICAgICAgaW5zZXJ0czogaW5zZXJ0c1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZnVuY3Rpb24gcmVtb3ZlKGFyciwgaW5kZXgsIGtleSkge1xuICAgICAgICAgICAgICAgIGFyci5zcGxpY2UoaW5kZXgsIDEpO1xuXG4gICAgICAgICAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgICAgICAgICAgZnJvbTogaW5kZXgsXG4gICAgICAgICAgICAgICAgICAgIGtleToga2V5XG4gICAgICAgICAgICAgICAgfTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZnVuY3Rpb24ga2V5SW5kZXgoY2hpbGRyZW4pIHtcbiAgICAgICAgICAgICAgICB2YXIga2V5cyA9IHt9O1xuICAgICAgICAgICAgICAgIHZhciBmcmVlID0gW107XG4gICAgICAgICAgICAgICAgdmFyIGxlbmd0aCA9IGNoaWxkcmVuLmxlbmd0aDtcblxuICAgICAgICAgICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgbGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgICAgICAgICAgdmFyIGNoaWxkID0gY2hpbGRyZW5baV07XG5cbiAgICAgICAgICAgICAgICAgICAgaWYgKGNoaWxkLmtleSkge1xuICAgICAgICAgICAgICAgICAgICAgICAga2V5c1tjaGlsZC5rZXldID0gaTtcbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGZyZWUucHVzaChpKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHJldHVybiB7XG4gICAgICAgICAgICAgICAgICAgIGtleXM6IGtleXMsIC8vIEEgaGFzaCBvZiBrZXkgbmFtZSB0byBpbmRleFxuICAgICAgICAgICAgICAgICAgICBmcmVlOiBmcmVlIC8vIEFuIGFycmF5IG9mIHVua2V5ZWQgaXRlbSBpbmRpY2VzXG4gICAgICAgICAgICAgICAgfTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZnVuY3Rpb24gYXBwZW5kUGF0Y2goYXBwbHksIHBhdGNoKSB7XG4gICAgICAgICAgICAgICAgaWYgKGFwcGx5KSB7XG4gICAgICAgICAgICAgICAgICAgIGlmIChpc0FycmF5KGFwcGx5KSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgYXBwbHkucHVzaChwYXRjaCk7XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBhcHBseSA9IFthcHBseSwgcGF0Y2hdO1xuICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGFwcGx5O1xuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBwYXRjaDtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH0sIHsgXCIuLi92bm9kZS9oYW5kbGUtdGh1bmtcIjogMjQsIFwiLi4vdm5vZGUvaXMtdGh1bmtcIjogMjUsIFwiLi4vdm5vZGUvaXMtdm5vZGVcIjogMjcsIFwiLi4vdm5vZGUvaXMtdnRleHRcIjogMjgsIFwiLi4vdm5vZGUvaXMtd2lkZ2V0XCI6IDI5LCBcIi4uL3Zub2RlL3ZwYXRjaFwiOiAzMiwgXCIuL2RpZmYtcHJvcHNcIjogMzQsIFwieC1pcy1hcnJheVwiOiAxMiB9XSB9LCB7fSwgWzRdKSg0KTtcbn0pO1xuXG5jb25zdCBDb3JlID0gQztcblxuZXhwb3J0IHsgQ29yZSwgRW51bSwgVmlydHVhbERPTSB9OyJdLCJmaWxlIjoiRWxpeGlyLmpzIiwic291cmNlUm9vdCI6Ii9zb3VyY2UvIn0= \ No newline at end of file +//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiIiwic291cmNlcyI6WyJFbGl4aXIuanMiXSwic291cmNlc0NvbnRlbnQiOlsiLyogQGZsb3cgKi9cblxuY2xhc3MgTWFpbGJveCB7XG5cbiAgY29uc3RydWN0b3IoKSB7XG4gICAgdGhpcy5tZXNzYWdlcyA9IFtdO1xuICB9XG5cbiAgZGVsaXZlcihtZXNzYWdlKSB7XG4gICAgdGhpcy5tZXNzYWdlcy5wdXNoKG1lc3NhZ2UpO1xuICAgIHJldHVybiBtZXNzYWdlO1xuICB9XG5cbiAgZ2V0KCkge1xuICAgIHJldHVybiB0aGlzLm1lc3NhZ2VzO1xuICB9XG5cbiAgaXNFbXB0eSgpIHtcbiAgICByZXR1cm4gdGhpcy5tZXNzYWdlcy5sZW5ndGggPT09IDA7XG4gIH1cblxuICByZW1vdmVBdChpbmRleCkge1xuICAgIHRoaXMubWVzc2FnZXMuc3BsaWNlKGluZGV4LCAxKTtcbiAgfVxufVxuXG52YXIgU3RhdGVzID0ge1xuICBOT1JNQUw6IFN5bWJvbC5mb3IoXCJub3JtYWxcIiksXG4gIEtJTEw6IFN5bWJvbC5mb3IoXCJraWxsXCIpLFxuICBTVVNQRU5EOiBTeW1ib2wuZm9yKFwic3VzcGVuZFwiKSxcbiAgQ09OVElOVUU6IFN5bWJvbC5mb3IoXCJjb250aW51ZVwiKSxcbiAgUkVDRUlWRTogU3ltYm9sLmZvcihcInJlY2VpdmVcIiksXG4gIFNFTkQ6IFN5bWJvbC5mb3IoXCJzZW5kXCIpLFxuICBTTEVFUElORzogU3ltYm9sLmZvcihcInNsZWVwaW5nXCIpLFxuICBSVU5OSU5HOiBTeW1ib2wuZm9yKFwicnVubmluZ1wiKSxcbiAgU1VTUEVOREVEOiBTeW1ib2wuZm9yKFwic3VzcGVuZGVkXCIpLFxuICBTVE9QUEVEOiBTeW1ib2wuZm9yKFwic3RvcHBlZFwiKSxcbiAgU0xFRVA6IFN5bWJvbC5mb3IoXCJzbGVlcFwiKSxcbiAgRVhJVDogU3ltYm9sLmZvcihcImV4aXRcIiksXG4gIE5PTUFUQ0g6IFN5bWJvbC5mb3IoXCJub19tYXRjaFwiKVxufTtcblxuY2xhc3MgUHJvY2VzcyB7XG5cbiAgY29uc3RydWN0b3IocGlkLCBtYWlsYm94KSB7XG4gICAgdGhpcy5waWQgPSBwaWQ7XG4gICAgdGhpcy5tYWlsYm94ID0gbWFpbGJveDtcbiAgICB0aGlzLnN0YXR1cyA9IFN0YXRlcy5TVE9QUEVEO1xuICAgIHRoaXMuZGljdCA9IHt9O1xuICB9XG59XG5cbmNsYXNzIFR1cGxlIHtcblxuICBjb25zdHJ1Y3RvciguLi5hcmdzKSB7XG4gICAgdGhpcy52YWx1ZXMgPSBPYmplY3QuZnJlZXplKGFyZ3MpO1xuICAgIHRoaXMubGVuZ3RoID0gdGhpcy52YWx1ZXMubGVuZ3RoO1xuICB9XG5cbiAgZ2V0KGluZGV4KSB7XG4gICAgcmV0dXJuIHRoaXMudmFsdWVzW2luZGV4XTtcbiAgfVxuXG4gIGNvdW50KCkge1xuICAgIHJldHVybiB0aGlzLnZhbHVlcy5sZW5ndGg7XG4gIH1cblxuICBbU3ltYm9sLml0ZXJhdG9yXSgpIHtcbiAgICByZXR1cm4gdGhpcy52YWx1ZXNbU3ltYm9sLml0ZXJhdG9yXSgpO1xuICB9XG5cbiAgdG9TdHJpbmcoKSB7XG4gICAgdmFyIGksXG4gICAgICAgIHMgPSBcIlwiO1xuICAgIGZvciAoaSA9IDA7IGkgPCB0aGlzLnZhbHVlcy5sZW5ndGg7IGkrKykge1xuICAgICAgaWYgKHMgIT09IFwiXCIpIHtcbiAgICAgICAgcyArPSBcIiwgXCI7XG4gICAgICB9XG4gICAgICBzICs9IHRoaXMudmFsdWVzW2ldLnRvU3RyaW5nKCk7XG4gICAgfVxuXG4gICAgcmV0dXJuIFwie1wiICsgcyArIFwifVwiO1xuICB9XG5cbn1cblxubGV0IHByb2Nlc3NfY291bnRlciA9IC0xO1xuXG5jbGFzcyBQSUQge1xuICBjb25zdHJ1Y3RvcigpIHtcbiAgICBwcm9jZXNzX2NvdW50ZXIgPSBwcm9jZXNzX2NvdW50ZXIgKyAxO1xuICAgIHRoaXMuaWQgPSBwcm9jZXNzX2NvdW50ZXI7XG4gIH1cblxuICB0b1N0cmluZygpIHtcbiAgICByZXR1cm4gXCJQSUQjPDAuXCIgKyB0aGlzLmlkICsgXCIuMD5cIjtcbiAgfVxufVxuXG5jbGFzcyBJbnRlZ2VyIHt9XG5jbGFzcyBGbG9hdCB7fVxuXG5jbGFzcyBQcm9jZXNzU3lzdGVtIHtcblxuICBjb25zdHJ1Y3RvcigpIHtcbiAgICB0aGlzLnBpZHMgPSBuZXcgTWFwKCk7XG4gICAgdGhpcy5tYWlsYm94ZXMgPSBuZXcgTWFwKCk7XG4gICAgdGhpcy5uYW1lcyA9IG5ldyBNYXAoKTtcbiAgICB0aGlzLmxpbmtzID0gbmV3IE1hcCgpO1xuXG4gICAgdGhpcy5jdXJyZW50X3Byb2Nlc3MgPSBudWxsO1xuICAgIHRoaXMuc3VzcGVuZGVkID0gbmV3IE1hcCgpO1xuXG4gICAgdGhpcy5tYWluX3Byb2Nlc3NfcGlkID0gdGhpcy5zcGF3bigpO1xuICAgIHRoaXMuc2V0X2N1cnJlbnQodGhpcy5tYWluX3Byb2Nlc3NfcGlkKTtcbiAgfVxuXG4gIHNwYXduKCkge1xuICAgIHJldHVybiB0aGlzLmFkZF9wcm9jKGZhbHNlKS5waWQ7XG4gIH1cblxuICBzcGF3bl9saW5rKCkge1xuICAgIHJldHVybiB0aGlzLmFkZF9wcm9jKHRydWUpLnBpZDtcbiAgfVxuXG4gIGxpbmsocGlkKSB7XG4gICAgdGhpcy5saW5rcy5nZXQodGhpcy5waWQoKSkuYWRkKHBpZCk7XG4gICAgdGhpcy5saW5rcy5nZXQocGlkKS5hZGQodGhpcy5waWQoKSk7XG4gIH1cblxuICB1bmxpbmsocGlkKSB7XG4gICAgdGhpcy5saW5rcy5nZXQodGhpcy5waWQoKSkuZGVsZXRlKHBpZCk7XG4gICAgdGhpcy5saW5rcy5nZXQocGlkKS5kZWxldGUodGhpcy5waWQoKSk7XG4gIH1cblxuICBzZXRfY3VycmVudChpZCkge1xuICAgIGxldCBwaWQgPSB0aGlzLnBpZG9mKGlkKTtcbiAgICBpZiAocGlkICE9PSBudWxsKSB7XG4gICAgICB0aGlzLmN1cnJlbnRfcHJvY2VzcyA9IHRoaXMucGlkcy5nZXQocGlkKTtcbiAgICAgIHRoaXMuY3VycmVudF9wcm9jZXNzLnN0YXR1cyA9IFN0YXRlcy5SVU5OSU5HO1xuICAgIH1cbiAgfVxuXG4gIGFkZF9wcm9jKGxpbmtlZCkge1xuICAgIGxldCBuZXdwaWQgPSBuZXcgUElEKCk7XG4gICAgbGV0IG1haWxib3ggPSBuZXcgTWFpbGJveCgpO1xuICAgIGxldCBuZXdwcm9jID0gbmV3IFByb2Nlc3MobmV3cGlkLCBtYWlsYm94KTtcblxuICAgIHRoaXMucGlkcy5zZXQobmV3cGlkLCBuZXdwcm9jKTtcbiAgICB0aGlzLm1haWxib3hlcy5zZXQobmV3cGlkLCBtYWlsYm94KTtcbiAgICB0aGlzLmxpbmtzLnNldChuZXdwaWQsIG5ldyBTZXQoKSk7XG5cbiAgICBpZiAobGlua2VkKSB7XG4gICAgICB0aGlzLmxpbmsobmV3cGlkKTtcbiAgICB9XG5cbiAgICByZXR1cm4gbmV3cHJvYztcbiAgfVxuXG4gIHJlbW92ZV9wcm9jKHBpZCkge1xuICAgIHRoaXMucGlkcy5kZWxldGUocGlkKTtcbiAgICB0aGlzLnVucmVnaXN0ZXIocGlkKTtcblxuICAgIGlmICh0aGlzLmxpbmtzLmhhcyhwaWQpKSB7XG4gICAgICBmb3IgKGxldCBsaW5rcGlkIG9mIHRoaXMubGlua3MuZ2V0KHBpZCkpIHtcbiAgICAgICAgdGhpcy5saW5rcy5nZXQobGlua3BpZCkuZGVsZXRlKHBpZCk7XG4gICAgICB9XG5cbiAgICAgIHRoaXMubGlua3MuZGVsZXRlKHBpZCk7XG4gICAgfVxuICB9XG5cbiAgZXhpdChpZCkge1xuICAgIGxldCBwaWQgPSB0aGlzLnBpZG9mKGlkKTtcbiAgICB0aGlzLnJlbW92ZV9wcm9jKGlkKTtcbiAgfVxuXG4gIHJlZ2lzdGVyKG5hbWUsIHBpZCkge1xuICAgIGlmICghdGhpcy5uYW1lcy5oYXMobmFtZSkpIHtcbiAgICAgIHRoaXMubmFtZXMuc2V0KG5hbWUsIHBpZCk7XG4gICAgICByZXR1cm4gbmFtZTtcbiAgICB9IGVsc2Uge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKFwiTmFtZSBpcyBhbHJlYWR5IHJlZ2lzdGVyZWQgdG8gYW5vdGhlciBwcm9jZXNzXCIpO1xuICAgIH1cbiAgfVxuXG4gIHJlZ2lzdGVyZWQobmFtZSkge1xuICAgIHJldHVybiB0aGlzLm5hbWVzLmhhcyhuYW1lKSA/IHRoaXMubmFtZXMuZ2V0KG5hbWUpIDogbnVsbDtcbiAgfVxuXG4gIHVucmVnaXN0ZXIocGlkKSB7XG4gICAgZm9yIChsZXQgbmFtZSBvZiB0aGlzLm5hbWVzLmtleXMoKSkge1xuICAgICAgaWYgKHRoaXMubmFtZXMuaGFzKG5hbWUpICYmIHRoaXMubmFtZXMuZ2V0KG5hbWUpID09PSBwaWQpIHtcbiAgICAgICAgdGhpcy5uYW1lcy5kZWxldGUobmFtZSk7XG4gICAgICB9XG4gICAgfVxuICB9XG5cbiAgcGlkKCkge1xuICAgIHJldHVybiB0aGlzLmN1cnJlbnRfcHJvY2Vzcy5waWQ7XG4gIH1cblxuICBwaWRvZihpZCkge1xuICAgIGlmIChpZCBpbnN0YW5jZW9mIFBJRCkge1xuICAgICAgcmV0dXJuIHRoaXMucGlkcy5oYXMoaWQpID8gaWQgOiBudWxsO1xuICAgIH0gZWxzZSBpZiAoaWQgaW5zdGFuY2VvZiBQcm9jZXNzKSB7XG4gICAgICByZXR1cm4gaWQucGlkO1xuICAgIH0gZWxzZSB7XG4gICAgICBsZXQgcGlkID0gdGhpcy5yZWdpc3RlcmVkKGlkKTtcbiAgICAgIGlmIChwaWQgPT09IG51bGwpIHRocm93IFwiUHJvY2VzcyBuYW1lIG5vdCByZWdpc3RlcmVkOiBcIiArIGlkICsgXCIgKFwiICsgdHlwZW9mIGlkICsgXCIpXCI7XG4gICAgICByZXR1cm4gcGlkO1xuICAgIH1cbiAgfVxuXG4gIHB1dChpZCwga2V5LCB2YWx1ZSkge1xuICAgIGxldCBwaWQgPSB0aGlzLnBpZG9mKGlkKTtcbiAgICBsZXQgcHJvY2VzcyA9IHRoaXMucGlkcy5nZXQocGlkKTtcbiAgICBwcm9jZXNzLmRpY3Rba2V5XSA9IHZhbHVlO1xuICB9XG5cbiAgZ2V0KGlkLCBrZXkpIHtcbiAgICBsZXQgcGlkID0gdGhpcy5waWRvZihpZCk7XG4gICAgbGV0IHByb2Nlc3MgPSB0aGlzLnBpZHMuZ2V0KHBpZCk7XG5cbiAgICBpZiAoa2V5ICE9IG51bGwpIHtcbiAgICAgIHJldHVybiBwcm9jZXNzLmRpY3Rba2V5XTtcbiAgICB9IGVsc2Uge1xuICAgICAgcmV0dXJuIHByb2Nlc3MuZGljdDtcbiAgICB9XG4gIH1cblxuICBnZXRfa2V5cyhpZCkge1xuICAgIGxldCBwaWQgPSB0aGlzLnBpZG9mKGlkKTtcbiAgICBsZXQgcHJvY2VzcyA9IHRoaXMucGlkcy5nZXQocGlkKTtcblxuICAgIHJldHVybiBPYmplY3Qua2V5cyhwcm9jZXNzLmRpY3QpO1xuICB9XG5cbiAgZXJhc2UoaWQsIGtleSkge1xuICAgIGxldCBwaWQgPSB0aGlzLnBpZG9mKGlkKTtcbiAgICBsZXQgcHJvY2VzcyA9IHRoaXMucGlkcy5nZXQocGlkKTtcblxuICAgIGlmIChrZXkgIT0gbnVsbCkge1xuICAgICAgZGVsZXRlIHByb2Nlc3MuZGljdFtrZXldO1xuICAgIH0gZWxzZSB7XG4gICAgICBwcm9jZXNzLmRpY3QgPSB7fTtcbiAgICB9XG4gIH1cbn1cblxuY2xhc3MgQml0U3RyaW5nIHtcbiAgY29uc3RydWN0b3IoLi4uYXJncykge1xuICAgIHRoaXMucmF3X3ZhbHVlID0gZnVuY3Rpb24gKCkge1xuICAgICAgcmV0dXJuIE9iamVjdC5mcmVlemUoYXJncyk7XG4gICAgfTtcblxuICAgIHRoaXMudmFsdWUgPSBPYmplY3QuZnJlZXplKHRoaXMucHJvY2VzcyhhcmdzKSk7XG4gIH1cblxuICBnZXQoaW5kZXgpIHtcbiAgICByZXR1cm4gdGhpcy52YWx1ZVtpbmRleF07XG4gIH1cblxuICBjb3VudCgpIHtcbiAgICByZXR1cm4gdGhpcy52YWx1ZS5sZW5ndGg7XG4gIH1cblxuICBbU3ltYm9sLml0ZXJhdG9yXSgpIHtcbiAgICByZXR1cm4gdGhpcy52YWx1ZVtTeW1ib2wuaXRlcmF0b3JdKCk7XG4gIH1cblxuICB0b1N0cmluZygpIHtcbiAgICB2YXIgaSxcbiAgICAgICAgcyA9IFwiXCI7XG4gICAgZm9yIChpID0gMDsgaSA8IHRoaXMuY291bnQoKTsgaSsrKSB7XG4gICAgICBpZiAocyAhPT0gXCJcIikge1xuICAgICAgICBzICs9IFwiLCBcIjtcbiAgICAgIH1cbiAgICAgIHMgKz0gdGhpc1tpXS50b1N0cmluZygpO1xuICAgIH1cblxuICAgIHJldHVybiBcIjw8XCIgKyBzICsgXCI+PlwiO1xuICB9XG5cbiAgcHJvY2VzcygpIHtcbiAgICBsZXQgcHJvY2Vzc2VkX3ZhbHVlcyA9IFtdO1xuXG4gICAgdmFyIGk7XG4gICAgZm9yIChpID0gMDsgaSA8IHRoaXMucmF3X3ZhbHVlKCkubGVuZ3RoOyBpKyspIHtcbiAgICAgIGxldCBwcm9jZXNzZWRfdmFsdWUgPSB0aGlzW1wicHJvY2Vzc19cIiArIHRoaXMucmF3X3ZhbHVlKClbaV0udHlwZV0odGhpcy5yYXdfdmFsdWUoKVtpXSk7XG5cbiAgICAgIGZvciAobGV0IGF0dHIgb2YgdGhpcy5yYXdfdmFsdWUoKVtpXS5hdHRyaWJ1dGVzKSB7XG4gICAgICAgIHByb2Nlc3NlZF92YWx1ZSA9IHRoaXNbXCJwcm9jZXNzX1wiICsgYXR0cl0ocHJvY2Vzc2VkX3ZhbHVlKTtcbiAgICAgIH1cblxuICAgICAgcHJvY2Vzc2VkX3ZhbHVlcyA9IHByb2Nlc3NlZF92YWx1ZXMuY29uY2F0KHByb2Nlc3NlZF92YWx1ZSk7XG4gICAgfVxuXG4gICAgcmV0dXJuIHByb2Nlc3NlZF92YWx1ZXM7XG4gIH1cblxuICBwcm9jZXNzX2ludGVnZXIodmFsdWUpIHtcbiAgICByZXR1cm4gdmFsdWUudmFsdWU7XG4gIH1cblxuICBwcm9jZXNzX2Zsb2F0KHZhbHVlKSB7XG4gICAgaWYgKHZhbHVlLnNpemUgPT09IDY0KSB7XG4gICAgICByZXR1cm4gQml0U3RyaW5nLmZsb2F0NjRUb0J5dGVzKHZhbHVlLnZhbHVlKTtcbiAgICB9IGVsc2UgaWYgKHZhbHVlLnNpemUgPT09IDMyKSB7XG4gICAgICByZXR1cm4gQml0U3RyaW5nLmZsb2F0MzJUb0J5dGVzKHZhbHVlLnZhbHVlKTtcbiAgICB9XG5cbiAgICB0aHJvdyBuZXcgRXJyb3IoXCJJbnZhbGlkIHNpemUgZm9yIGZsb2F0XCIpO1xuICB9XG5cbiAgcHJvY2Vzc19iaXRzdHJpbmcodmFsdWUpIHtcbiAgICByZXR1cm4gdmFsdWUudmFsdWUudmFsdWU7XG4gIH1cblxuICBwcm9jZXNzX2JpbmFyeSh2YWx1ZSkge1xuICAgIHJldHVybiBCaXRTdHJpbmcudG9VVEY4QXJyYXkodmFsdWUudmFsdWUpO1xuICB9XG5cbiAgcHJvY2Vzc191dGY4KHZhbHVlKSB7XG4gICAgcmV0dXJuIEJpdFN0cmluZy50b1VURjhBcnJheSh2YWx1ZS52YWx1ZSk7XG4gIH1cblxuICBwcm9jZXNzX3V0ZjE2KHZhbHVlKSB7XG4gICAgcmV0dXJuIEJpdFN0cmluZy50b1VURjE2QXJyYXkodmFsdWUudmFsdWUpO1xuICB9XG5cbiAgcHJvY2Vzc191dGYzMih2YWx1ZSkge1xuICAgIHJldHVybiBCaXRTdHJpbmcudG9VVEYzMkFycmF5KHZhbHVlLnZhbHVlKTtcbiAgfVxuXG4gIHByb2Nlc3Nfc2lnbmVkKHZhbHVlKSB7XG4gICAgcmV0dXJuIG5ldyBVaW50OEFycmF5KFt2YWx1ZV0pWzBdO1xuICB9XG5cbiAgcHJvY2Vzc191bnNpZ25lZCh2YWx1ZSkge1xuICAgIHJldHVybiB2YWx1ZTtcbiAgfVxuXG4gIHByb2Nlc3NfbmF0aXZlKHZhbHVlKSB7XG4gICAgcmV0dXJuIHZhbHVlO1xuICB9XG5cbiAgcHJvY2Vzc19iaWcodmFsdWUpIHtcbiAgICByZXR1cm4gdmFsdWU7XG4gIH1cblxuICBwcm9jZXNzX2xpdHRsZSh2YWx1ZSkge1xuICAgIHJldHVybiB2YWx1ZS5yZXZlcnNlKCk7XG4gIH1cblxuICBwcm9jZXNzX3NpemUodmFsdWUpIHtcbiAgICByZXR1cm4gdmFsdWU7XG4gIH1cblxuICBwcm9jZXNzX3VuaXQodmFsdWUpIHtcbiAgICByZXR1cm4gdmFsdWU7XG4gIH1cblxuICBzdGF0aWMgaW50ZWdlcih2YWx1ZSkge1xuICAgIHJldHVybiBCaXRTdHJpbmcud3JhcCh2YWx1ZSwgeyBcInR5cGVcIjogXCJpbnRlZ2VyXCIsIFwidW5pdFwiOiAxLCBcInNpemVcIjogOCB9KTtcbiAgfVxuXG4gIHN0YXRpYyBmbG9hdCh2YWx1ZSkge1xuICAgIHJldHVybiBCaXRTdHJpbmcud3JhcCh2YWx1ZSwgeyBcInR5cGVcIjogXCJmbG9hdFwiLCBcInVuaXRcIjogMSwgXCJzaXplXCI6IDY0IH0pO1xuICB9XG5cbiAgc3RhdGljIGJpdHN0cmluZyh2YWx1ZSkge1xuICAgIHJldHVybiBCaXRTdHJpbmcud3JhcCh2YWx1ZSwgeyBcInR5cGVcIjogXCJiaXRzdHJpbmdcIiwgXCJ1bml0XCI6IDEsIFwic2l6ZVwiOiB2YWx1ZS5sZW5ndGggfSk7XG4gIH1cblxuICBzdGF0aWMgYml0cyh2YWx1ZSkge1xuICAgIHJldHVybiBCaXRTdHJpbmcuYml0c3RyaW5nKHZhbHVlKTtcbiAgfVxuXG4gIHN0YXRpYyBiaW5hcnkodmFsdWUpIHtcbiAgICByZXR1cm4gQml0U3RyaW5nLndyYXAodmFsdWUsIHsgXCJ0eXBlXCI6IFwiYmluYXJ5XCIsIFwidW5pdFwiOiA4LCBcInNpemVcIjogdmFsdWUubGVuZ3RoIH0pO1xuICB9XG5cbiAgc3RhdGljIGJ5dGVzKHZhbHVlKSB7XG4gICAgcmV0dXJuIEJpdFN0cmluZy5iaW5hcnkodmFsdWUpO1xuICB9XG5cbiAgc3RhdGljIHV0ZjgodmFsdWUpIHtcbiAgICByZXR1cm4gQml0U3RyaW5nLndyYXAodmFsdWUsIHsgXCJ0eXBlXCI6IFwidXRmOFwiIH0pO1xuICB9XG5cbiAgc3RhdGljIHV0ZjE2KHZhbHVlKSB7XG4gICAgcmV0dXJuIEJpdFN0cmluZy53cmFwKHZhbHVlLCB7IFwidHlwZVwiOiBcInV0ZjE2XCIgfSk7XG4gIH1cblxuICBzdGF0aWMgdXRmMzIodmFsdWUpIHtcbiAgICByZXR1cm4gQml0U3RyaW5nLndyYXAodmFsdWUsIHsgXCJ0eXBlXCI6IFwidXRmMzJcIiB9KTtcbiAgfVxuXG4gIHN0YXRpYyBzaWduZWQodmFsdWUpIHtcbiAgICByZXR1cm4gQml0U3RyaW5nLndyYXAodmFsdWUsIHt9LCBcInNpZ25lZFwiKTtcbiAgfVxuXG4gIHN0YXRpYyB1bnNpZ25lZCh2YWx1ZSkge1xuICAgIHJldHVybiBCaXRTdHJpbmcud3JhcCh2YWx1ZSwge30sIFwidW5zaWduZWRcIik7XG4gIH1cblxuICBzdGF0aWMgbmF0aXZlKHZhbHVlKSB7XG4gICAgcmV0dXJuIEJpdFN0cmluZy53cmFwKHZhbHVlLCB7fSwgXCJuYXRpdmVcIik7XG4gIH1cblxuICBzdGF0aWMgYmlnKHZhbHVlKSB7XG4gICAgcmV0dXJuIEJpdFN0cmluZy53cmFwKHZhbHVlLCB7fSwgXCJiaWdcIik7XG4gIH1cblxuICBzdGF0aWMgbGl0dGxlKHZhbHVlKSB7XG4gICAgcmV0dXJuIEJpdFN0cmluZy53cmFwKHZhbHVlLCB7fSwgXCJsaXR0bGVcIik7XG4gIH1cblxuICBzdGF0aWMgc2l6ZSh2YWx1ZSwgY291bnQpIHtcbiAgICByZXR1cm4gQml0U3RyaW5nLndyYXAodmFsdWUsIHsgXCJzaXplXCI6IGNvdW50IH0pO1xuICB9XG5cbiAgc3RhdGljIHVuaXQodmFsdWUsIGNvdW50KSB7XG4gICAgcmV0dXJuIEJpdFN0cmluZy53cmFwKHZhbHVlLCB7IFwidW5pdFwiOiBjb3VudCB9KTtcbiAgfVxuXG4gIHN0YXRpYyB3cmFwKHZhbHVlLCBvcHQsIG5ld19hdHRyaWJ1dGUgPSBudWxsKSB7XG4gICAgbGV0IHRoZV92YWx1ZSA9IHZhbHVlO1xuXG4gICAgaWYgKCEodmFsdWUgaW5zdGFuY2VvZiBPYmplY3QpKSB7XG4gICAgICB0aGVfdmFsdWUgPSB7IFwidmFsdWVcIjogdmFsdWUsIFwiYXR0cmlidXRlc1wiOiBbXSB9O1xuICAgIH1cblxuICAgIHRoZV92YWx1ZSA9IE9iamVjdC5hc3NpZ24odGhlX3ZhbHVlLCBvcHQpO1xuXG4gICAgaWYgKG5ld19hdHRyaWJ1dGUpIHtcbiAgICAgIHRoZV92YWx1ZS5hdHRyaWJ1dGVzLnB1c2gobmV3X2F0dHJpYnV0ZSk7XG4gICAgfVxuXG4gICAgcmV0dXJuIHRoZV92YWx1ZTtcbiAgfVxuXG4gIHN0YXRpYyB0b1VURjhBcnJheShzdHIpIHtcbiAgICB2YXIgdXRmOCA9IFtdO1xuICAgIGZvciAodmFyIGkgPSAwOyBpIDwgc3RyLmxlbmd0aDsgaSsrKSB7XG4gICAgICB2YXIgY2hhcmNvZGUgPSBzdHIuY2hhckNvZGVBdChpKTtcbiAgICAgIGlmIChjaGFyY29kZSA8IDEyOCkge1xuICAgICAgICB1dGY4LnB1c2goY2hhcmNvZGUpO1xuICAgICAgfSBlbHNlIGlmIChjaGFyY29kZSA8IDIwNDgpIHtcbiAgICAgICAgdXRmOC5wdXNoKDE5MiB8IGNoYXJjb2RlID4+IDYsIDEyOCB8IGNoYXJjb2RlICYgNjMpO1xuICAgICAgfSBlbHNlIGlmIChjaGFyY29kZSA8IDU1Mjk2IHx8IGNoYXJjb2RlID49IDU3MzQ0KSB7XG4gICAgICAgIHV0ZjgucHVzaCgyMjQgfCBjaGFyY29kZSA+PiAxMiwgMTI4IHwgY2hhcmNvZGUgPj4gNiAmIDYzLCAxMjggfCBjaGFyY29kZSAmIDYzKTtcbiAgICAgIH1cbiAgICAgIC8vIHN1cnJvZ2F0ZSBwYWlyXG4gICAgICBlbHNlIHtcbiAgICAgICAgaSsrO1xuICAgICAgICAvLyBVVEYtMTYgZW5jb2RlcyAweDEwMDAwLTB4MTBGRkZGIGJ5XG4gICAgICAgIC8vIHN1YnRyYWN0aW5nIDB4MTAwMDAgYW5kIHNwbGl0dGluZyB0aGVcbiAgICAgICAgLy8gMjAgYml0cyBvZiAweDAtMHhGRkZGRiBpbnRvIHR3byBoYWx2ZXNcbiAgICAgICAgY2hhcmNvZGUgPSA2NTUzNiArICgoY2hhcmNvZGUgJiAxMDIzKSA8PCAxMCB8IHN0ci5jaGFyQ29kZUF0KGkpICYgMTAyMyk7XG4gICAgICAgIHV0ZjgucHVzaCgyNDAgfCBjaGFyY29kZSA+PiAxOCwgMTI4IHwgY2hhcmNvZGUgPj4gMTIgJiA2MywgMTI4IHwgY2hhcmNvZGUgPj4gNiAmIDYzLCAxMjggfCBjaGFyY29kZSAmIDYzKTtcbiAgICAgIH1cbiAgICB9XG4gICAgcmV0dXJuIHV0Zjg7XG4gIH1cblxuICBzdGF0aWMgdG9VVEYxNkFycmF5KHN0cikge1xuICAgIHZhciB1dGYxNiA9IFtdO1xuICAgIGZvciAodmFyIGkgPSAwOyBpIDwgc3RyLmxlbmd0aDsgaSsrKSB7XG4gICAgICB2YXIgY29kZVBvaW50ID0gc3RyLmNvZGVQb2ludEF0KGkpO1xuXG4gICAgICBpZiAoY29kZVBvaW50IDw9IDI1NSkge1xuICAgICAgICB1dGYxNi5wdXNoKDApO1xuICAgICAgICB1dGYxNi5wdXNoKGNvZGVQb2ludCk7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICB1dGYxNi5wdXNoKGNvZGVQb2ludCA+PiA4ICYgMjU1KTtcbiAgICAgICAgdXRmMTYucHVzaChjb2RlUG9pbnQgJiAyNTUpO1xuICAgICAgfVxuICAgIH1cbiAgICByZXR1cm4gdXRmMTY7XG4gIH1cblxuICBzdGF0aWMgdG9VVEYzMkFycmF5KHN0cikge1xuICAgIHZhciB1dGYzMiA9IFtdO1xuICAgIGZvciAodmFyIGkgPSAwOyBpIDwgc3RyLmxlbmd0aDsgaSsrKSB7XG4gICAgICB2YXIgY29kZVBvaW50ID0gc3RyLmNvZGVQb2ludEF0KGkpO1xuXG4gICAgICBpZiAoY29kZVBvaW50IDw9IDI1NSkge1xuICAgICAgICB1dGYzMi5wdXNoKDApO1xuICAgICAgICB1dGYzMi5wdXNoKDApO1xuICAgICAgICB1dGYzMi5wdXNoKDApO1xuICAgICAgICB1dGYzMi5wdXNoKGNvZGVQb2ludCk7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICB1dGYzMi5wdXNoKDApO1xuICAgICAgICB1dGYzMi5wdXNoKDApO1xuICAgICAgICB1dGYzMi5wdXNoKGNvZGVQb2ludCA+PiA4ICYgMjU1KTtcbiAgICAgICAgdXRmMzIucHVzaChjb2RlUG9pbnQgJiAyNTUpO1xuICAgICAgfVxuICAgIH1cbiAgICByZXR1cm4gdXRmMzI7XG4gIH1cblxuICAvL2h0dHA6Ly9zdGFja292ZXJmbG93LmNvbS9xdWVzdGlvbnMvMjAwMzQ5My9qYXZhc2NyaXB0LWZsb2F0LWZyb20tdG8tYml0c1xuICBzdGF0aWMgZmxvYXQzMlRvQnl0ZXMoZikge1xuICAgIHZhciBieXRlcyA9IFtdO1xuXG4gICAgdmFyIGJ1ZiA9IG5ldyBBcnJheUJ1ZmZlcig0KTtcbiAgICBuZXcgRmxvYXQzMkFycmF5KGJ1ZilbMF0gPSBmO1xuXG4gICAgbGV0IGludFZlcnNpb24gPSBuZXcgVWludDMyQXJyYXkoYnVmKVswXTtcblxuICAgIGJ5dGVzLnB1c2goaW50VmVyc2lvbiA+PiAyNCAmIDI1NSk7XG4gICAgYnl0ZXMucHVzaChpbnRWZXJzaW9uID4+IDE2ICYgMjU1KTtcbiAgICBieXRlcy5wdXNoKGludFZlcnNpb24gPj4gOCAmIDI1NSk7XG4gICAgYnl0ZXMucHVzaChpbnRWZXJzaW9uICYgMjU1KTtcblxuICAgIHJldHVybiBieXRlcztcbiAgfVxuXG4gIHN0YXRpYyBmbG9hdDY0VG9CeXRlcyhmKSB7XG4gICAgdmFyIGJ5dGVzID0gW107XG5cbiAgICB2YXIgYnVmID0gbmV3IEFycmF5QnVmZmVyKDgpO1xuICAgIG5ldyBGbG9hdDY0QXJyYXkoYnVmKVswXSA9IGY7XG5cbiAgICB2YXIgaW50VmVyc2lvbjEgPSBuZXcgVWludDMyQXJyYXkoYnVmKVswXTtcbiAgICB2YXIgaW50VmVyc2lvbjIgPSBuZXcgVWludDMyQXJyYXkoYnVmKVsxXTtcblxuICAgIGJ5dGVzLnB1c2goaW50VmVyc2lvbjIgPj4gMjQgJiAyNTUpO1xuICAgIGJ5dGVzLnB1c2goaW50VmVyc2lvbjIgPj4gMTYgJiAyNTUpO1xuICAgIGJ5dGVzLnB1c2goaW50VmVyc2lvbjIgPj4gOCAmIDI1NSk7XG4gICAgYnl0ZXMucHVzaChpbnRWZXJzaW9uMiAmIDI1NSk7XG5cbiAgICBieXRlcy5wdXNoKGludFZlcnNpb24xID4+IDI0ICYgMjU1KTtcbiAgICBieXRlcy5wdXNoKGludFZlcnNpb24xID4+IDE2ICYgMjU1KTtcbiAgICBieXRlcy5wdXNoKGludFZlcnNpb24xID4+IDggJiAyNTUpO1xuICAgIGJ5dGVzLnB1c2goaW50VmVyc2lvbjEgJiAyNTUpO1xuXG4gICAgcmV0dXJuIGJ5dGVzO1xuICB9XG59XG5cbi8qIEBmbG93ICovXG5cbmNsYXNzIFZhcmlhYmxlIHtcblxuICBjb25zdHJ1Y3RvcihuYW1lID0gbnVsbCkge1xuICAgIHRoaXMubmFtZSA9IG5hbWU7XG4gIH1cbn1cblxuY2xhc3MgV2lsZGNhcmQge1xuICBjb25zdHJ1Y3RvcigpIHt9XG59XG5cbmNsYXNzIFN0YXJ0c1dpdGgge1xuXG4gIGNvbnN0cnVjdG9yKHByZWZpeCkge1xuICAgIHRoaXMucHJlZml4ID0gcHJlZml4O1xuICB9XG59XG5cbmNsYXNzIENhcHR1cmUge1xuXG4gIGNvbnN0cnVjdG9yKHZhbHVlKSB7XG4gICAgdGhpcy52YWx1ZSA9IHZhbHVlO1xuICB9XG59XG5cbmNsYXNzIEhlYWRUYWlsIHtcbiAgY29uc3RydWN0b3IoKSB7fVxufVxuXG5jbGFzcyBUeXBlIHtcblxuICBjb25zdHJ1Y3Rvcih0eXBlLCBvYmpQYXR0ZXJuID0ge30pIHtcbiAgICB0aGlzLnR5cGUgPSB0eXBlO1xuICAgIHRoaXMub2JqUGF0dGVybiA9IG9ialBhdHRlcm47XG4gIH1cbn1cblxuY2xhc3MgQm91bmQge1xuXG4gIGNvbnN0cnVjdG9yKHZhbHVlKSB7XG4gICAgdGhpcy52YWx1ZSA9IHZhbHVlO1xuICB9XG59XG5cbmZ1bmN0aW9uIHZhcmlhYmxlKG5hbWUgPSBudWxsKSB7XG4gIHJldHVybiBuZXcgVmFyaWFibGUobmFtZSk7XG59XG5cbmZ1bmN0aW9uIHdpbGRjYXJkKCkge1xuICByZXR1cm4gbmV3IFdpbGRjYXJkKCk7XG59XG5cbmZ1bmN0aW9uIHN0YXJ0c1dpdGgocHJlZml4KSB7XG4gIHJldHVybiBuZXcgU3RhcnRzV2l0aChwcmVmaXgpO1xufVxuXG5mdW5jdGlvbiBjYXB0dXJlKHZhbHVlKSB7XG4gIHJldHVybiBuZXcgQ2FwdHVyZSh2YWx1ZSk7XG59XG5cbmZ1bmN0aW9uIGhlYWRUYWlsKCkge1xuICByZXR1cm4gbmV3IEhlYWRUYWlsKCk7XG59XG5cbmZ1bmN0aW9uIHR5cGUodHlwZSwgb2JqUGF0dGVybiA9IHt9KSB7XG4gIHJldHVybiBuZXcgVHlwZSh0eXBlLCBvYmpQYXR0ZXJuKTtcbn1cblxuZnVuY3Rpb24gYm91bmQodmFsdWUpIHtcbiAgcmV0dXJuIG5ldyBCb3VuZCh2YWx1ZSk7XG59XG5cbmZ1bmN0aW9uIGlzX251bWJlcih2YWx1ZSkge1xuICByZXR1cm4gdHlwZW9mIHZhbHVlID09PSAnbnVtYmVyJztcbn1cblxuZnVuY3Rpb24gaXNfc3RyaW5nKHZhbHVlKSB7XG4gIHJldHVybiB0eXBlb2YgdmFsdWUgPT09ICdzdHJpbmcnO1xufVxuXG5mdW5jdGlvbiBpc19ib29sZWFuKHZhbHVlKSB7XG4gIHJldHVybiB0eXBlb2YgdmFsdWUgPT09ICdib29sZWFuJztcbn1cblxuZnVuY3Rpb24gaXNfc3ltYm9sKHZhbHVlKSB7XG4gIHJldHVybiB0eXBlb2YgdmFsdWUgPT09ICdzeW1ib2wnO1xufVxuXG5mdW5jdGlvbiBpc19udWxsKHZhbHVlKSB7XG4gIHJldHVybiB2YWx1ZSA9PT0gbnVsbDtcbn1cblxuZnVuY3Rpb24gaXNfdW5kZWZpbmVkKHZhbHVlKSB7XG4gIHJldHVybiB0eXBlb2YgdmFsdWUgPT09ICd1bmRlZmluZWQnO1xufVxuXG5mdW5jdGlvbiBpc19mdW5jdGlvbih2YWx1ZSkge1xuICByZXR1cm4gT2JqZWN0LnByb3RvdHlwZS50b1N0cmluZy5jYWxsKHZhbHVlKSA9PSAnW29iamVjdCBGdW5jdGlvbl0nO1xufVxuXG5mdW5jdGlvbiBpc192YXJpYWJsZSh2YWx1ZSkge1xuICByZXR1cm4gdmFsdWUgaW5zdGFuY2VvZiBWYXJpYWJsZTtcbn1cblxuZnVuY3Rpb24gaXNfd2lsZGNhcmQodmFsdWUpIHtcbiAgcmV0dXJuIHZhbHVlIGluc3RhbmNlb2YgV2lsZGNhcmQ7XG59XG5cbmZ1bmN0aW9uIGlzX2hlYWRUYWlsKHZhbHVlKSB7XG4gIHJldHVybiB2YWx1ZSBpbnN0YW5jZW9mIEhlYWRUYWlsO1xufVxuXG5mdW5jdGlvbiBpc19jYXB0dXJlKHZhbHVlKSB7XG4gIHJldHVybiB2YWx1ZSBpbnN0YW5jZW9mIENhcHR1cmU7XG59XG5cbmZ1bmN0aW9uIGlzX3R5cGUodmFsdWUpIHtcbiAgcmV0dXJuIHZhbHVlIGluc3RhbmNlb2YgVHlwZTtcbn1cblxuZnVuY3Rpb24gaXNfc3RhcnRzV2l0aCh2YWx1ZSkge1xuICByZXR1cm4gdmFsdWUgaW5zdGFuY2VvZiBTdGFydHNXaXRoO1xufVxuXG5mdW5jdGlvbiBpc19ib3VuZCh2YWx1ZSkge1xuICByZXR1cm4gdmFsdWUgaW5zdGFuY2VvZiBCb3VuZDtcbn1cblxuZnVuY3Rpb24gaXNfb2JqZWN0KHZhbHVlKSB7XG4gIHJldHVybiB0eXBlb2YgdmFsdWUgPT09ICdvYmplY3QnO1xufVxuXG5mdW5jdGlvbiBpc19hcnJheSh2YWx1ZSkge1xuICByZXR1cm4gQXJyYXkuaXNBcnJheSh2YWx1ZSk7XG59XG5cbnZhciBDaGVja3MgPSB7XG4gIGlzX251bWJlcixcbiAgaXNfc3RyaW5nLFxuICBpc19ib29sZWFuLFxuICBpc19zeW1ib2wsXG4gIGlzX251bGwsXG4gIGlzX3VuZGVmaW5lZCxcbiAgaXNfZnVuY3Rpb24sXG4gIGlzX3ZhcmlhYmxlLFxuICBpc193aWxkY2FyZCxcbiAgaXNfaGVhZFRhaWwsXG4gIGlzX2NhcHR1cmUsXG4gIGlzX3R5cGUsXG4gIGlzX3N0YXJ0c1dpdGgsXG4gIGlzX2JvdW5kLFxuICBpc19vYmplY3QsXG4gIGlzX2FycmF5XG59O1xuXG5mdW5jdGlvbiByZXNvbHZlU3ltYm9sKHBhdHRlcm4pIHtcbiAgcmV0dXJuIGZ1bmN0aW9uICh2YWx1ZSkge1xuICAgIHJldHVybiBDaGVja3MuaXNfc3ltYm9sKHZhbHVlKSAmJiB2YWx1ZSA9PT0gcGF0dGVybjtcbiAgfTtcbn1cblxuZnVuY3Rpb24gcmVzb2x2ZVN0cmluZyhwYXR0ZXJuKSB7XG4gIHJldHVybiBmdW5jdGlvbiAodmFsdWUpIHtcbiAgICByZXR1cm4gQ2hlY2tzLmlzX3N0cmluZyh2YWx1ZSkgJiYgdmFsdWUgPT09IHBhdHRlcm47XG4gIH07XG59XG5cbmZ1bmN0aW9uIHJlc29sdmVOdW1iZXIocGF0dGVybikge1xuICByZXR1cm4gZnVuY3Rpb24gKHZhbHVlKSB7XG4gICAgcmV0dXJuIENoZWNrcy5pc19udW1iZXIodmFsdWUpICYmIHZhbHVlID09PSBwYXR0ZXJuO1xuICB9O1xufVxuXG5mdW5jdGlvbiByZXNvbHZlQm9vbGVhbihwYXR0ZXJuKSB7XG4gIHJldHVybiBmdW5jdGlvbiAodmFsdWUpIHtcbiAgICByZXR1cm4gQ2hlY2tzLmlzX2Jvb2xlYW4odmFsdWUpICYmIHZhbHVlID09PSBwYXR0ZXJuO1xuICB9O1xufVxuXG5mdW5jdGlvbiByZXNvbHZlRnVuY3Rpb24ocGF0dGVybikge1xuICByZXR1cm4gZnVuY3Rpb24gKHZhbHVlKSB7XG4gICAgcmV0dXJuIENoZWNrcy5pc19mdW5jdGlvbih2YWx1ZSkgJiYgdmFsdWUgPT09IHBhdHRlcm47XG4gIH07XG59XG5cbmZ1bmN0aW9uIHJlc29sdmVOdWxsKHBhdHRlcm4pIHtcbiAgcmV0dXJuIGZ1bmN0aW9uICh2YWx1ZSkge1xuICAgIHJldHVybiBDaGVja3MuaXNfbnVsbCh2YWx1ZSk7XG4gIH07XG59XG5cbmZ1bmN0aW9uIHJlc29sdmVCb3VuZChwYXR0ZXJuKSB7XG4gIHJldHVybiBmdW5jdGlvbiAodmFsdWUsIGFyZ3MpIHtcbiAgICBpZiAodHlwZW9mIHZhbHVlID09PSB0eXBlb2YgcGF0dGVybi52YWx1ZSAmJiB2YWx1ZSA9PT0gcGF0dGVybi52YWx1ZSkge1xuICAgICAgYXJncy5wdXNoKHZhbHVlKTtcbiAgICAgIHJldHVybiB0cnVlO1xuICAgIH1cblxuICAgIHJldHVybiBmYWxzZTtcbiAgfTtcbn1cblxuZnVuY3Rpb24gcmVzb2x2ZVdpbGRjYXJkKCkge1xuICByZXR1cm4gZnVuY3Rpb24gKCkge1xuICAgIHJldHVybiB0cnVlO1xuICB9O1xufVxuXG5mdW5jdGlvbiByZXNvbHZlVmFyaWFibGUoKSB7XG4gIHJldHVybiBmdW5jdGlvbiAodmFsdWUsIGFyZ3MpIHtcbiAgICBhcmdzLnB1c2godmFsdWUpO1xuICAgIHJldHVybiB0cnVlO1xuICB9O1xufVxuXG5mdW5jdGlvbiByZXNvbHZlSGVhZFRhaWwoKSB7XG4gIHJldHVybiBmdW5jdGlvbiAodmFsdWUsIGFyZ3MpIHtcbiAgICBpZiAoIUNoZWNrcy5pc19hcnJheSh2YWx1ZSkgfHwgdmFsdWUubGVuZ3RoIDwgMikge1xuICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH1cblxuICAgIGNvbnN0IGhlYWQgPSB2YWx1ZVswXTtcbiAgICBjb25zdCB0YWlsID0gdmFsdWUuc2xpY2UoMSk7XG5cbiAgICBhcmdzLnB1c2goaGVhZCk7XG4gICAgYXJncy5wdXNoKHRhaWwpO1xuXG4gICAgcmV0dXJuIHRydWU7XG4gIH07XG59XG5cbmZ1bmN0aW9uIHJlc29sdmVDYXB0dXJlKHBhdHRlcm4pIHtcbiAgY29uc3QgbWF0Y2hlcyA9IGJ1aWxkTWF0Y2gocGF0dGVybi52YWx1ZSk7XG5cbiAgcmV0dXJuIGZ1bmN0aW9uICh2YWx1ZSwgYXJncykge1xuICAgIGlmIChtYXRjaGVzKHZhbHVlLCBhcmdzKSkge1xuICAgICAgYXJncy5wdXNoKHZhbHVlKTtcbiAgICAgIHJldHVybiB0cnVlO1xuICAgIH1cblxuICAgIHJldHVybiBmYWxzZTtcbiAgfTtcbn1cblxuZnVuY3Rpb24gcmVzb2x2ZVN0YXJ0c1dpdGgocGF0dGVybikge1xuICBjb25zdCBwcmVmaXggPSBwYXR0ZXJuLnByZWZpeDtcblxuICByZXR1cm4gZnVuY3Rpb24gKHZhbHVlLCBhcmdzKSB7XG4gICAgaWYgKENoZWNrcy5pc19zdHJpbmcodmFsdWUpICYmIHZhbHVlLnN0YXJ0c1dpdGgocHJlZml4KSkge1xuICAgICAgYXJncy5wdXNoKHZhbHVlLnN1YnN0cmluZyhwcmVmaXgubGVuZ3RoKSk7XG4gICAgICByZXR1cm4gdHJ1ZTtcbiAgICB9XG5cbiAgICByZXR1cm4gZmFsc2U7XG4gIH07XG59XG5cbmZ1bmN0aW9uIHJlc29sdmVUeXBlKHBhdHRlcm4pIHtcbiAgcmV0dXJuIGZ1bmN0aW9uICh2YWx1ZSwgYXJncykge1xuICAgIGlmICh2YWx1ZSBpbnN0YW5jZW9mIHBhdHRlcm4udHlwZSkge1xuICAgICAgY29uc3QgbWF0Y2hlcyA9IGJ1aWxkTWF0Y2gocGF0dGVybi5vYmpQYXR0ZXJuKTtcbiAgICAgIHJldHVybiBtYXRjaGVzKHZhbHVlLCBhcmdzKSAmJiBhcmdzLnB1c2godmFsdWUpID4gMDtcbiAgICB9XG5cbiAgICByZXR1cm4gZmFsc2U7XG4gIH07XG59XG5cbmZ1bmN0aW9uIHJlc29sdmVBcnJheShwYXR0ZXJuKSB7XG4gIGNvbnN0IG1hdGNoZXMgPSBwYXR0ZXJuLm1hcCh4ID0+IGJ1aWxkTWF0Y2goeCkpO1xuXG4gIHJldHVybiBmdW5jdGlvbiAodmFsdWUsIGFyZ3MpIHtcbiAgICBpZiAoIUNoZWNrcy5pc19hcnJheSh2YWx1ZSkgfHwgdmFsdWUubGVuZ3RoICE9IHBhdHRlcm4ubGVuZ3RoKSB7XG4gICAgICByZXR1cm4gZmFsc2U7XG4gICAgfVxuXG4gICAgcmV0dXJuIHZhbHVlLmV2ZXJ5KGZ1bmN0aW9uICh2LCBpKSB7XG4gICAgICByZXR1cm4gbWF0Y2hlc1tpXSh2YWx1ZVtpXSwgYXJncyk7XG4gICAgfSk7XG4gIH07XG59XG5cbmZ1bmN0aW9uIHJlc29sdmVPYmplY3QocGF0dGVybikge1xuICBsZXQgbWF0Y2hlcyA9IHt9O1xuXG4gIGZvciAobGV0IGtleSBvZiBPYmplY3Qua2V5cyhwYXR0ZXJuKS5jb25jYXQoT2JqZWN0LmdldE93blByb3BlcnR5U3ltYm9scyhwYXR0ZXJuKSkpIHtcbiAgICBtYXRjaGVzW2tleV0gPSBidWlsZE1hdGNoKHBhdHRlcm5ba2V5XSk7XG4gIH1cblxuICByZXR1cm4gZnVuY3Rpb24gKHZhbHVlLCBhcmdzKSB7XG4gICAgaWYgKCFDaGVja3MuaXNfb2JqZWN0KHZhbHVlKSB8fCBwYXR0ZXJuLmxlbmd0aCA+IHZhbHVlLmxlbmd0aCkge1xuICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH1cblxuICAgIGZvciAobGV0IGtleSBvZiBPYmplY3Qua2V5cyhwYXR0ZXJuKS5jb25jYXQoT2JqZWN0LmdldE93blByb3BlcnR5U3ltYm9scyhwYXR0ZXJuKSkpIHtcbiAgICAgIGlmICghKGtleSBpbiB2YWx1ZSkgfHwgIW1hdGNoZXNba2V5XSh2YWx1ZVtrZXldLCBhcmdzKSkge1xuICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICB9XG4gICAgfVxuXG4gICAgcmV0dXJuIHRydWU7XG4gIH07XG59XG5cbmZ1bmN0aW9uIHJlc29sdmVOb01hdGNoKCkge1xuICByZXR1cm4gZnVuY3Rpb24gKCkge1xuICAgIHJldHVybiBmYWxzZTtcbiAgfTtcbn1cblxudmFyIFJlc29sdmVycyA9IHtcbiAgcmVzb2x2ZUJvdW5kLFxuICByZXNvbHZlV2lsZGNhcmQsXG4gIHJlc29sdmVWYXJpYWJsZSxcbiAgcmVzb2x2ZUhlYWRUYWlsLFxuICByZXNvbHZlQ2FwdHVyZSxcbiAgcmVzb2x2ZVN0YXJ0c1dpdGgsXG4gIHJlc29sdmVUeXBlLFxuICByZXNvbHZlQXJyYXksXG4gIHJlc29sdmVPYmplY3QsXG4gIHJlc29sdmVOb01hdGNoLFxuICByZXNvbHZlU3ltYm9sLFxuICByZXNvbHZlU3RyaW5nLFxuICByZXNvbHZlTnVtYmVyLFxuICByZXNvbHZlQm9vbGVhbixcbiAgcmVzb2x2ZUZ1bmN0aW9uLFxuICByZXNvbHZlTnVsbFxufTtcblxuZnVuY3Rpb24gYnVpbGRNYXRjaChwYXR0ZXJuKSB7XG5cbiAgaWYgKENoZWNrcy5pc192YXJpYWJsZShwYXR0ZXJuKSkge1xuICAgIHJldHVybiBSZXNvbHZlcnMucmVzb2x2ZVZhcmlhYmxlKHBhdHRlcm4pO1xuICB9XG5cbiAgaWYgKENoZWNrcy5pc193aWxkY2FyZChwYXR0ZXJuKSkge1xuICAgIHJldHVybiBSZXNvbHZlcnMucmVzb2x2ZVdpbGRjYXJkKHBhdHRlcm4pO1xuICB9XG5cbiAgaWYgKENoZWNrcy5pc191bmRlZmluZWQocGF0dGVybikpIHtcbiAgICByZXR1cm4gUmVzb2x2ZXJzLnJlc29sdmVXaWxkY2FyZChwYXR0ZXJuKTtcbiAgfVxuXG4gIGlmIChDaGVja3MuaXNfaGVhZFRhaWwocGF0dGVybikpIHtcbiAgICByZXR1cm4gUmVzb2x2ZXJzLnJlc29sdmVIZWFkVGFpbChwYXR0ZXJuKTtcbiAgfVxuXG4gIGlmIChDaGVja3MuaXNfc3RhcnRzV2l0aChwYXR0ZXJuKSkge1xuICAgIHJldHVybiBSZXNvbHZlcnMucmVzb2x2ZVN0YXJ0c1dpdGgocGF0dGVybik7XG4gIH1cblxuICBpZiAoQ2hlY2tzLmlzX2NhcHR1cmUocGF0dGVybikpIHtcbiAgICByZXR1cm4gUmVzb2x2ZXJzLnJlc29sdmVDYXB0dXJlKHBhdHRlcm4pO1xuICB9XG5cbiAgaWYgKENoZWNrcy5pc19ib3VuZChwYXR0ZXJuKSkge1xuICAgIHJldHVybiBSZXNvbHZlcnMucmVzb2x2ZUJvdW5kKHBhdHRlcm4pO1xuICB9XG5cbiAgaWYgKENoZWNrcy5pc190eXBlKHBhdHRlcm4pKSB7XG4gICAgcmV0dXJuIFJlc29sdmVycy5yZXNvbHZlVHlwZShwYXR0ZXJuKTtcbiAgfVxuXG4gIGlmIChDaGVja3MuaXNfYXJyYXkocGF0dGVybikpIHtcbiAgICByZXR1cm4gUmVzb2x2ZXJzLnJlc29sdmVBcnJheShwYXR0ZXJuKTtcbiAgfVxuXG4gIGlmIChDaGVja3MuaXNfbnVtYmVyKHBhdHRlcm4pKSB7XG4gICAgcmV0dXJuIFJlc29sdmVycy5yZXNvbHZlTnVtYmVyKHBhdHRlcm4pO1xuICB9XG5cbiAgaWYgKENoZWNrcy5pc19zdHJpbmcocGF0dGVybikpIHtcbiAgICByZXR1cm4gUmVzb2x2ZXJzLnJlc29sdmVTdHJpbmcocGF0dGVybik7XG4gIH1cblxuICBpZiAoQ2hlY2tzLmlzX2Jvb2xlYW4ocGF0dGVybikpIHtcbiAgICByZXR1cm4gUmVzb2x2ZXJzLnJlc29sdmVCb29sZWFuKHBhdHRlcm4pO1xuICB9XG5cbiAgaWYgKENoZWNrcy5pc19zeW1ib2wocGF0dGVybikpIHtcbiAgICByZXR1cm4gUmVzb2x2ZXJzLnJlc29sdmVTeW1ib2wocGF0dGVybik7XG4gIH1cblxuICBpZiAoQ2hlY2tzLmlzX251bGwocGF0dGVybikpIHtcbiAgICByZXR1cm4gUmVzb2x2ZXJzLnJlc29sdmVOdWxsKHBhdHRlcm4pO1xuICB9XG5cbiAgaWYgKENoZWNrcy5pc19vYmplY3QocGF0dGVybikpIHtcbiAgICByZXR1cm4gUmVzb2x2ZXJzLnJlc29sdmVPYmplY3QocGF0dGVybik7XG4gIH1cblxuICByZXR1cm4gUmVzb2x2ZXJzLnJlc29sdmVOb01hdGNoKCk7XG59XG5cbmNsYXNzIE1hdGNoRXJyb3IgZXh0ZW5kcyBFcnJvciB7XG4gIGNvbnN0cnVjdG9yKGFyZykge1xuICAgIHN1cGVyKCk7XG5cbiAgICBpZiAodHlwZW9mIGFyZyA9PT0gJ3N5bWJvbCcpIHtcbiAgICAgIHRoaXMubWVzc2FnZSA9ICdObyBtYXRjaCBmb3I6ICcgKyBhcmcudG9TdHJpbmcoKTtcbiAgICB9IGVsc2UgaWYgKEFycmF5LmlzQXJyYXkoYXJnKSkge1xuICAgICAgbGV0IG1hcHBlZFZhbHVlcyA9IGFyZy5tYXAoeCA9PiB4LnRvU3RyaW5nKCkpO1xuICAgICAgdGhpcy5tZXNzYWdlID0gJ05vIG1hdGNoIGZvcjogJyArIG1hcHBlZFZhbHVlcztcbiAgICB9IGVsc2Uge1xuICAgICAgdGhpcy5tZXNzYWdlID0gJ05vIG1hdGNoIGZvcjogJyArIGFyZztcbiAgICB9XG5cbiAgICB0aGlzLnN0YWNrID0gbmV3IEVycm9yKCkuc3RhY2s7XG4gICAgdGhpcy5uYW1lID0gdGhpcy5jb25zdHJ1Y3Rvci5uYW1lO1xuICB9XG59XG5cbmNsYXNzIENhc2Uge1xuXG4gIGNvbnN0cnVjdG9yKHBhdHRlcm4sIGZuLCBndWFyZCA9ICgpID0+IHRydWUpIHtcbiAgICB0aGlzLnBhdHRlcm4gPSBidWlsZE1hdGNoKHBhdHRlcm4pO1xuICAgIHRoaXMuZm4gPSBmbjtcbiAgICB0aGlzLmd1YXJkID0gZ3VhcmQ7XG4gIH1cbn1cblxuZnVuY3Rpb24gbWFrZV9jYXNlKHBhdHRlcm4sIGZuLCBndWFyZCA9ICgpID0+IHRydWUpIHtcbiAgcmV0dXJuIG5ldyBDYXNlKHBhdHRlcm4sIGZuLCBndWFyZCk7XG59XG5cbmZ1bmN0aW9uIGRlZm1hdGNoKC4uLmNhc2VzKSB7XG4gIHJldHVybiBmdW5jdGlvbiAoLi4uYXJncykge1xuICAgIGZvciAobGV0IHByb2Nlc3NlZENhc2Ugb2YgY2FzZXMpIHtcbiAgICAgIGxldCByZXN1bHQgPSBbXTtcbiAgICAgIGlmIChwcm9jZXNzZWRDYXNlLnBhdHRlcm4oYXJncywgcmVzdWx0KSAmJiBwcm9jZXNzZWRDYXNlLmd1YXJkLmFwcGx5KHRoaXMsIHJlc3VsdCkpIHtcbiAgICAgICAgcmV0dXJuIHByb2Nlc3NlZENhc2UuZm4uYXBwbHkodGhpcywgcmVzdWx0KTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICB0aHJvdyBuZXcgTWF0Y2hFcnJvcihhcmdzKTtcbiAgfTtcbn1cblxuZnVuY3Rpb24gbWF0Y2gocGF0dGVybiwgZXhwciwgZ3VhcmQgPSAoKSA9PiB0cnVlKSB7XG4gIGxldCByZXN1bHQgPSBbXTtcbiAgbGV0IHByb2Nlc3NlZFBhdHRlcm4gPSBidWlsZE1hdGNoKHBhdHRlcm4pO1xuICBpZiAocHJvY2Vzc2VkUGF0dGVybihleHByLCByZXN1bHQpICYmIGd1YXJkLmFwcGx5KHRoaXMsIHJlc3VsdCkpIHtcbiAgICByZXR1cm4gcmVzdWx0O1xuICB9IGVsc2Uge1xuICAgIHRocm93IG5ldyBNYXRjaEVycm9yKGV4cHIpO1xuICB9XG59XG5cbmZ1bmN0aW9uIG1hdGNoX25vX3Rocm93KHBhdHRlcm4sIGV4cHIsIGd1YXJkID0gKCkgPT4gdHJ1ZSkge1xuICB0cnkge1xuICAgIHJldHVybiBtYXRjaChwYXR0ZXJuLCBleHByLCBndWFyZCk7XG4gIH0gY2F0Y2ggKGUpIHtcbiAgICBpZiAoZSBpbnN0YW5jZW9mIE1hdGNoRXJyb3IpIHtcbiAgICAgIHJldHVybiBudWxsO1xuICAgIH1cblxuICAgIHRocm93IGU7XG4gIH1cbn1cblxudmFyIFBhdHRlcm5zID0ge1xuICBkZWZtYXRjaCwgbWF0Y2gsIE1hdGNoRXJyb3IsIG1hdGNoX25vX3Rocm93LFxuICB2YXJpYWJsZSwgd2lsZGNhcmQsIHN0YXJ0c1dpdGgsXG4gIGNhcHR1cmUsIGhlYWRUYWlsLCB0eXBlLCBib3VuZCwgQ2FzZSwgbWFrZV9jYXNlXG59O1xuXG5mdW5jdGlvbiBjYWxsX3Byb3BlcnR5KGl0ZW0sIHByb3BlcnR5KSB7XG4gIGxldCBwcm9wID0gbnVsbDtcblxuICBpZiAocHJvcGVydHkgaW4gaXRlbSkge1xuICAgIHByb3AgPSBwcm9wZXJ0eTtcbiAgfSBlbHNlIGlmIChTeW1ib2wuZm9yKHByb3BlcnR5KSBpbiBpdGVtKSB7XG4gICAgcHJvcCA9IFN5bWJvbC5mb3IocHJvcGVydHkpO1xuICB9IGVsc2Uge1xuICAgIHRocm93IG5ldyBFcnJvcihgUHJvcGVydHkgJHsgcHJvcGVydHkgfSBub3QgZm91bmQgaW4gJHsgaXRlbSB9YCk7XG4gIH1cblxuICBpZiAoaXRlbVtwcm9wXSBpbnN0YW5jZW9mIEZ1bmN0aW9uKSB7XG4gICAgcmV0dXJuIGl0ZW1bcHJvcF0oKTtcbiAgfSBlbHNlIHtcbiAgICByZXR1cm4gaXRlbVtwcm9wXTtcbiAgfVxufVxuXG5mdW5jdGlvbiBhcHBseSguLi5hcmdzKSB7XG4gIGlmIChhcmdzLmxlbmd0aCA9PT0gMikge1xuICAgIGFyZ3NbMF0uYXBwbHkobnVsbCwgYXJncy5zbGljZSgxKSk7XG4gIH0gZWxzZSB7XG4gICAgYXJnc1swXVthcmdzWzFdXS5hcHBseShudWxsLCBhcmdzLnNsaWNlKDIpKTtcbiAgfVxufVxuXG5mdW5jdGlvbiBjb250YWlucyhsZWZ0LCByaWdodCkge1xuICBmb3IgKGxldCB4IG9mIHJpZ2h0KSB7XG4gICAgaWYgKFBhdHRlcm5zLm1hdGNoX25vX3Rocm93KGxlZnQsIHgpICE9IG51bGwpIHtcbiAgICAgIHJldHVybiB0cnVlO1xuICAgIH1cbiAgfVxuXG4gIHJldHVybiBmYWxzZTtcbn1cblxuZnVuY3Rpb24gZ2V0X2dsb2JhbCgpIHtcbiAgaWYgKHR5cGVvZiBzZWxmICE9PSAndW5kZWZpbmVkJykge1xuICAgIHJldHVybiBzZWxmO1xuICB9IGVsc2UgaWYgKHR5cGVvZiB3aW5kb3cgIT09ICd1bmRlZmluZWQnKSB7XG4gICAgcmV0dXJuIHdpbmRvdztcbiAgfSBlbHNlIGlmICh0eXBlb2YgZ2xvYmFsICE9PSAndW5kZWZpbmVkJykge1xuICAgIHJldHVybiBnbG9iYWw7XG4gIH1cblxuICB0aHJvdyBuZXcgRXJyb3IoJ05vIGdsb2JhbCBzdGF0ZSBmb3VuZCcpO1xufVxuXG5mdW5jdGlvbiBkZWZzdHJ1Y3QoZGVmYXVsdHMpIHtcbiAgcmV0dXJuIGNsYXNzIHtcbiAgICBjb25zdHJ1Y3Rvcih1cGRhdGUgPSB7fSkge1xuICAgICAgbGV0IHRoZV92YWx1ZXMgPSBPYmplY3QuYXNzaWduKGRlZmF1bHRzLCB1cGRhdGUpO1xuICAgICAgT2JqZWN0LmFzc2lnbih0aGlzLCB0aGVfdmFsdWVzKTtcbiAgICB9XG5cbiAgICBzdGF0aWMgY3JlYXRlKHVwZGF0ZXMgPSB7fSkge1xuICAgICAgbGV0IHggPSBuZXcgdGhpcyh1cGRhdGVzKTtcbiAgICAgIHJldHVybiBPYmplY3QuZnJlZXplKHgpO1xuICAgIH1cbiAgfTtcbn1cblxuZnVuY3Rpb24gZGVmZXhjZXB0aW9uKGRlZmF1bHRzKSB7XG4gIHJldHVybiBjbGFzcyBleHRlbmRzIEVycm9yIHtcbiAgICBjb25zdHJ1Y3Rvcih1cGRhdGUgPSB7fSkge1xuICAgICAgbGV0IG1lc3NhZ2UgPSB1cGRhdGUubWVzc2FnZSB8fCAnJztcbiAgICAgIHN1cGVyKG1lc3NhZ2UpO1xuXG4gICAgICBsZXQgdGhlX3ZhbHVlcyA9IE9iamVjdC5hc3NpZ24oZGVmYXVsdHMsIHVwZGF0ZSk7XG4gICAgICBPYmplY3QuYXNzaWduKHRoaXMsIHRoZV92YWx1ZXMpO1xuXG4gICAgICB0aGlzLm5hbWUgPSB0aGlzLmNvbnN0cnVjdG9yLm5hbWU7XG4gICAgICB0aGlzLm1lc3NhZ2UgPSBtZXNzYWdlO1xuICAgICAgdGhpc1tTcGVjaWFsRm9ybXMuYXRvbSgnX19leGNlcHRpb25fXycpXSA9IHRydWU7XG4gICAgICBFcnJvci5jYXB0dXJlU3RhY2tUcmFjZSh0aGlzLCB0aGlzLmNvbnN0cnVjdG9yLm5hbWUpO1xuICAgIH1cblxuICAgIHN0YXRpYyBjcmVhdGUodXBkYXRlcyA9IHt9KSB7XG4gICAgICBsZXQgeCA9IG5ldyB0aGlzKHVwZGF0ZXMpO1xuICAgICAgcmV0dXJuIE9iamVjdC5mcmVlemUoeCk7XG4gICAgfVxuICB9O1xufVxuXG5mdW5jdGlvbiBkZWZwcm90b2NvbChzcGVjKSB7XG4gIHJldHVybiBuZXcgUHJvdG9jb2woc3BlYyk7XG59XG5cbmZ1bmN0aW9uIGRlZmltcGwocHJvdG9jb2wsIHR5cGUsIGltcGwpIHtcbiAgcHJvdG9jb2wuaW1wbGVtZW50YXRpb24odHlwZSwgaW1wbCk7XG59XG5cbmZ1bmN0aW9uIGdldF9vYmplY3Rfa2V5cyhvYmopIHtcbiAgcmV0dXJuIE9iamVjdC5rZXlzKG9iaikuY29uY2F0KE9iamVjdC5nZXRPd25Qcm9wZXJ0eVN5bWJvbHMob2JqKSk7XG59XG5cbmZ1bmN0aW9uIGlzX3ZhbGlkX2NoYXJhY3Rlcihjb2RlcG9pbnQpIHtcbiAgdHJ5IHtcbiAgICByZXR1cm4gU3RyaW5nLmZyb21Db2RlUG9pbnQoY29kZXBvaW50KSAhPSBudWxsO1xuICB9IGNhdGNoIChlKSB7XG4gICAgcmV0dXJuIGZhbHNlO1xuICB9XG59XG5cbi8vaHR0cHM6Ly9kZXZlbG9wZXIubW96aWxsYS5vcmcvZW4tVVMvZG9jcy9XZWIvQVBJL1dpbmRvd0Jhc2U2NC9CYXNlNjRfZW5jb2RpbmdfYW5kX2RlY29kaW5nI1NvbHV0aW9uXzJfJUUyJTgwJTkzX3Jld3JpdGVfdGhlX0RPTXNfYXRvYigpX2FuZF9idG9hKClfdXNpbmdfSmF2YVNjcmlwdCdzX1R5cGVkQXJyYXlzX2FuZF9VVEYtOFxuZnVuY3Rpb24gYjY0RW5jb2RlVW5pY29kZShzdHIpIHtcbiAgcmV0dXJuIGJ0b2EoZW5jb2RlVVJJQ29tcG9uZW50KHN0cikucmVwbGFjZSgvJShbMC05QS1GXXsyfSkvZywgZnVuY3Rpb24gKG1hdGNoLCBwMSkge1xuICAgIHJldHVybiBTdHJpbmcuZnJvbUNoYXJDb2RlKCcweCcgKyBwMSk7XG4gIH0pKTtcbn1cblxuZnVuY3Rpb24gZGVsZXRlX3Byb3BlcnR5X2Zyb21fbWFwKG1hcCwgcHJvcGVydHkpIHtcbiAgbGV0IG5ld19tYXAgPSBPYmplY3QuYXNzaWduKE9iamVjdC5jcmVhdGUobWFwLmNvbnN0cnVjdG9yLnByb3RvdHlwZSksIG1hcCk7XG4gIGRlbGV0ZSBuZXdfbWFwW3Byb3BlcnR5XTtcblxuICByZXR1cm4gT2JqZWN0LmZyZWV6ZShuZXdfbWFwKTtcbn1cblxuZnVuY3Rpb24gY2xhc3NfdG9fb2JqKG1hcCkge1xuICBsZXQgbmV3X21hcCA9IE9iamVjdC5hc3NpZ24oe30sIG1hcCk7XG4gIHJldHVybiBPYmplY3QuZnJlZXplKG5ld19tYXApO1xufVxuXG5mdW5jdGlvbiBhZGRfcHJvcGVydHlfdG9fbWFwKG1hcCwgcHJvcGVydHksIHZhbHVlKSB7XG4gIGxldCBuZXdfbWFwID0gT2JqZWN0LmFzc2lnbih7fSwgbWFwKTtcbiAgbmV3X21hcFtwcm9wZXJ0eV0gPSB2YWx1ZTtcbiAgcmV0dXJuIE9iamVjdC5mcmVlemUobmV3X21hcCk7XG59XG5cbmZ1bmN0aW9uIGJub3QoZXhwcikge1xuICByZXR1cm4gfmV4cHI7XG59XG5cbmZ1bmN0aW9uIGJhbmQobGVmdCwgcmlnaHQpIHtcbiAgcmV0dXJuIGxlZnQgJiByaWdodDtcbn1cblxuZnVuY3Rpb24gYm9yKGxlZnQsIHJpZ2h0KSB7XG4gIHJldHVybiBsZWZ0IHwgcmlnaHQ7XG59XG5cbmZ1bmN0aW9uIGJzbChsZWZ0LCByaWdodCkge1xuICByZXR1cm4gbGVmdCA8PCByaWdodDtcbn1cblxuZnVuY3Rpb24gYnNyKGxlZnQsIHJpZ2h0KSB7XG4gIHJldHVybiBsZWZ0ID4+IHJpZ2h0O1xufVxuXG5mdW5jdGlvbiBieG9yKGxlZnQsIHJpZ2h0KSB7XG4gIHJldHVybiBsZWZ0IF4gcmlnaHQ7XG59XG5cbmZ1bmN0aW9uIHppcChsaXN0X29mX2xpc3RzKSB7XG4gIGlmIChsaXN0X29mX2xpc3RzLmxlbmd0aCA9PT0gMCkge1xuICAgIHJldHVybiBPYmplY3QuZnJlZXplKFtdKTtcbiAgfVxuXG4gIGxldCBuZXdfdmFsdWUgPSBbXTtcbiAgbGV0IHNtYWxsZXN0X2xlbmd0aCA9IGxpc3Rfb2ZfbGlzdHNbMF07XG5cbiAgZm9yIChsZXQgeCBvZiBsaXN0X29mX2xpc3RzKSB7XG4gICAgaWYgKHgubGVuZ3RoIDwgc21hbGxlc3RfbGVuZ3RoKSB7XG4gICAgICBzbWFsbGVzdF9sZW5ndGggPSB4Lmxlbmd0aDtcbiAgICB9XG4gIH1cblxuICBmb3IgKGxldCBpID0gMDsgaSA8IHNtYWxsZXN0X2xlbmd0aDsgaSsrKSB7XG4gICAgbGV0IGN1cnJlbnRfdmFsdWUgPSBbXTtcbiAgICBmb3IgKGxldCBqID0gMDsgaiA8IGxpc3Rfb2ZfbGlzdHMubGVuZ3RoOyBqKyspIHtcbiAgICAgIGN1cnJlbnRfdmFsdWUucHVzaChsaXN0X29mX2xpc3RzW2pdW2ldKTtcbiAgICB9XG5cbiAgICBuZXdfdmFsdWUucHVzaChuZXcgVHVwbGUoLi4uY3VycmVudF92YWx1ZSkpO1xuICB9XG5cbiAgcmV0dXJuIE9iamVjdC5mcmVlemUobmV3X3ZhbHVlKTtcbn1cblxuZnVuY3Rpb24gY2FuX2RlY29kZTY0KGRhdGEpIHtcbiAgdHJ5IHtcbiAgICBhdG9iKGRhdGEpO1xuICAgIHJldHVybiB0cnVlO1xuICB9IGNhdGNoIChlKSB7XG4gICAgcmV0dXJuIGZhbHNlO1xuICB9XG59XG5cbnZhciBGdW5jdGlvbnMgPSB7XG4gIGNhbGxfcHJvcGVydHksXG4gIGFwcGx5LFxuICBjb250YWlucyxcbiAgZ2V0X2dsb2JhbCxcbiAgZGVmc3RydWN0LFxuICBkZWZleGNlcHRpb24sXG4gIGRlZnByb3RvY29sLFxuICBkZWZpbXBsLFxuICBnZXRfb2JqZWN0X2tleXMsXG4gIGlzX3ZhbGlkX2NoYXJhY3RlcixcbiAgYjY0RW5jb2RlVW5pY29kZSxcbiAgZGVsZXRlX3Byb3BlcnR5X2Zyb21fbWFwLFxuICBhZGRfcHJvcGVydHlfdG9fbWFwLFxuICBjbGFzc190b19vYmosXG4gIGNhbl9kZWNvZGU2NCxcbiAgYm5vdCxcbiAgYmFuZCxcbiAgYm9yLFxuICBic2wsXG4gIGJzcixcbiAgYnhvcixcbiAgemlwXG59O1xuXG5mdW5jdGlvbiBfY2FzZShjb25kaXRpb24sIGNsYXVzZXMpIHtcbiAgcmV0dXJuIFBhdHRlcm5zLmRlZm1hdGNoKC4uLmNsYXVzZXMpKGNvbmRpdGlvbik7XG59XG5cbmZ1bmN0aW9uIGNvbmQoY2xhdXNlcykge1xuICBmb3IgKGxldCBjbGF1c2Ugb2YgY2xhdXNlcykge1xuICAgIGlmIChjbGF1c2VbMF0pIHtcbiAgICAgIHJldHVybiBjbGF1c2VbMV0oKTtcbiAgICB9XG4gIH1cblxuICB0aHJvdyBuZXcgRXJyb3IoKTtcbn1cblxuZnVuY3Rpb24gbWFwX3VwZGF0ZShtYXAsIHZhbHVlcykge1xuICByZXR1cm4gT2JqZWN0LmZyZWV6ZShPYmplY3QuYXNzaWduKE9iamVjdC5jcmVhdGUobWFwLmNvbnN0cnVjdG9yLnByb3RvdHlwZSksIG1hcCwgdmFsdWVzKSk7XG59XG5cbmZ1bmN0aW9uIF9mb3IoY29sbGVjdGlvbnMsIGZ1biwgZmlsdGVyID0gKCkgPT4gdHJ1ZSwgaW50byA9IFtdLCBwcmV2aW91c1ZhbHVlcyA9IFtdKSB7XG4gIGxldCBwYXR0ZXJuID0gY29sbGVjdGlvbnNbMF1bMF07XG4gIGxldCBjb2xsZWN0aW9uID0gY29sbGVjdGlvbnNbMF1bMV07XG5cbiAgaWYgKGNvbGxlY3Rpb25zLmxlbmd0aCA9PT0gMSkge1xuXG4gICAgZm9yIChsZXQgZWxlbSBvZiBjb2xsZWN0aW9uKSB7XG4gICAgICBsZXQgciA9IFBhdHRlcm5zLm1hdGNoX25vX3Rocm93KHBhdHRlcm4sIGVsZW0pO1xuICAgICAgbGV0IGFyZ3MgPSBwcmV2aW91c1ZhbHVlcy5jb25jYXQocik7XG5cbiAgICAgIGlmIChyICYmIGZpbHRlci5hcHBseSh0aGlzLCBhcmdzKSkge1xuICAgICAgICBpbnRvID0gaW50by5jb25jYXQoW2Z1bi5hcHBseSh0aGlzLCBhcmdzKV0pO1xuICAgICAgfVxuICAgIH1cblxuICAgIHJldHVybiBpbnRvO1xuICB9IGVsc2Uge1xuICAgIGxldCBfaW50byA9IFtdO1xuXG4gICAgZm9yIChsZXQgZWxlbSBvZiBjb2xsZWN0aW9uKSB7XG4gICAgICBsZXQgciA9IFBhdHRlcm5zLm1hdGNoX25vX3Rocm93KHBhdHRlcm4sIGVsZW0pO1xuICAgICAgaWYgKHIpIHtcbiAgICAgICAgX2ludG8gPSBpbnRvLmNvbmNhdCh0aGlzLl9mb3IoY29sbGVjdGlvbnMuc2xpY2UoMSksIGZ1biwgZmlsdGVyLCBfaW50bywgcHJldmlvdXNWYWx1ZXMuY29uY2F0KHIpKSk7XG4gICAgICB9XG4gICAgfVxuXG4gICAgcmV0dXJuIF9pbnRvO1xuICB9XG59XG5cbmZ1bmN0aW9uIF90cnkoZG9fZnVuLCByZXNjdWVfZnVuY3Rpb24sIGNhdGNoX2Z1biwgZWxzZV9mdW5jdGlvbiwgYWZ0ZXJfZnVuY3Rpb24pIHtcbiAgbGV0IHJlc3VsdCA9IG51bGw7XG5cbiAgdHJ5IHtcbiAgICByZXN1bHQgPSBkb19mdW4oKTtcbiAgfSBjYXRjaCAoZSkge1xuICAgIGxldCBleF9yZXN1bHQgPSBudWxsO1xuXG4gICAgaWYgKHJlc2N1ZV9mdW5jdGlvbikge1xuICAgICAgdHJ5IHtcbiAgICAgICAgZXhfcmVzdWx0ID0gcmVzY3VlX2Z1bmN0aW9uKGUpO1xuICAgICAgICByZXR1cm4gZXhfcmVzdWx0O1xuICAgICAgfSBjYXRjaCAoZXgpIHtcbiAgICAgICAgaWYgKGV4IGluc3RhbmNlb2YgUGF0dGVybnMuTWF0Y2hFcnJvcikge1xuICAgICAgICAgIHRocm93IGV4O1xuICAgICAgICB9XG4gICAgICB9XG4gICAgfVxuXG4gICAgaWYgKGNhdGNoX2Z1bikge1xuICAgICAgdHJ5IHtcbiAgICAgICAgZXhfcmVzdWx0ID0gY2F0Y2hfZnVuKGUpO1xuICAgICAgICByZXR1cm4gZXhfcmVzdWx0O1xuICAgICAgfSBjYXRjaCAoZXgpIHtcbiAgICAgICAgaWYgKGV4IGluc3RhbmNlb2YgUGF0dGVybnMuTWF0Y2hFcnJvcikge1xuICAgICAgICAgIHRocm93IGV4O1xuICAgICAgICB9XG4gICAgICB9XG4gICAgfVxuXG4gICAgdGhyb3cgZTtcbiAgfSBmaW5hbGx5IHtcbiAgICBpZiAoYWZ0ZXJfZnVuY3Rpb24pIHtcbiAgICAgIGFmdGVyX2Z1bmN0aW9uKCk7XG4gICAgfVxuICB9XG5cbiAgaWYgKGVsc2VfZnVuY3Rpb24pIHtcbiAgICB0cnkge1xuICAgICAgcmV0dXJuIGVsc2VfZnVuY3Rpb24ocmVzdWx0KTtcbiAgICB9IGNhdGNoIChleCkge1xuICAgICAgaWYgKGV4IGluc3RhbmNlb2YgUGF0dGVybnMuTWF0Y2hFcnJvcikge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ05vIE1hdGNoIEZvdW5kIGluIEVsc2UnKTtcbiAgICAgIH1cblxuICAgICAgdGhyb3cgZXg7XG4gICAgfVxuICB9IGVsc2Uge1xuICAgIHJldHVybiByZXN1bHQ7XG4gIH1cbn1cblxudmFyIHNwZWNpYWxfZm9ybXMgPSB7XG4gIF9jYXNlLFxuICBjb25kLFxuICBtYXBfdXBkYXRlLFxuICBfZm9yLFxuICBfdHJ5XG59O1xuXG5GdW5jdGlvbnMuZ2V0X2dsb2JhbCgpLnByb2Nlc3NlcyA9IEZ1bmN0aW9ucy5nZXRfZ2xvYmFsKCkucHJvY2Vzc2VzIHx8IG5ldyBQcm9jZXNzU3lzdGVtKCk7XG5cblxuXG52YXIgQyA9IE9iamVjdC5mcmVlemUoe1xuXHRQcm9jZXNzU3lzdGVtOiBQcm9jZXNzU3lzdGVtLFxuXHRUdXBsZTogVHVwbGUsXG5cdFBJRDogUElELFxuXHRCaXRTdHJpbmc6IEJpdFN0cmluZyxcblx0UGF0dGVybnM6IFBhdHRlcm5zLFxuXHRJbnRlZ2VyOiBJbnRlZ2VyLFxuXHRGbG9hdDogRmxvYXQsXG5cdEZ1bmN0aW9uczogRnVuY3Rpb25zLFxuXHRTcGVjaWFsRm9ybXM6IHNwZWNpYWxfZm9ybXNcbn0pO1xuXG5sZXQgRW51bSA9IHtcblxuICBhbGxfX3FtYXJrX186IGZ1bmN0aW9uIChjb2xsZWN0aW9uLCBmdW4gPSB4ID0+IHgpIHtcbiAgICBmb3IgKGxldCBlbGVtIG9mIGNvbGxlY3Rpb24pIHtcbiAgICAgIGlmICghZnVuKGVsZW0pKSB7XG4gICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICByZXR1cm4gdHJ1ZTtcbiAgfSxcblxuICBhbnlfX3FtYXJrX186IGZ1bmN0aW9uIChjb2xsZWN0aW9uLCBmdW4gPSB4ID0+IHgpIHtcbiAgICBmb3IgKGxldCBlbGVtIG9mIGNvbGxlY3Rpb24pIHtcbiAgICAgIGlmIChmdW4oZWxlbSkpIHtcbiAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICB9XG4gICAgfVxuXG4gICAgcmV0dXJuIGZhbHNlO1xuICB9LFxuXG4gIGF0OiBmdW5jdGlvbiAoY29sbGVjdGlvbiwgbiwgdGhlX2RlZmF1bHQgPSBudWxsKSB7XG4gICAgaWYgKG4gPiB0aGlzLmNvdW50KGNvbGxlY3Rpb24pIHx8IG4gPCAwKSB7XG4gICAgICByZXR1cm4gdGhlX2RlZmF1bHQ7XG4gICAgfVxuXG4gICAgcmV0dXJuIGNvbGxlY3Rpb25bbl07XG4gIH0sXG5cbiAgY29uY2F0OiBmdW5jdGlvbiAoLi4uZW51bWFibGVzKSB7XG4gICAgcmV0dXJuIGVudW1hYmxlc1swXS5jb25jYXQoZW51bWFibGVzWzFdKTtcbiAgfSxcblxuICBjb3VudDogZnVuY3Rpb24gKGNvbGxlY3Rpb24sIGZ1biA9IG51bGwpIHtcbiAgICBpZiAoZnVuID09IG51bGwpIHtcbiAgICAgIHJldHVybiBjb2xsZWN0aW9uLmxlbmd0aDtcbiAgICB9IGVsc2Uge1xuICAgICAgcmV0dXJuIGNvbGxlY3Rpb24uZmlsdGVyKGZ1bikubGVuZ3RoO1xuICAgIH1cbiAgfSxcblxuICBkcm9wOiBmdW5jdGlvbiAoY29sbGVjdGlvbiwgY291bnQpIHtcbiAgICByZXR1cm4gY29sbGVjdGlvbi5zbGljZShjb3VudCk7XG4gIH0sXG5cbiAgZHJvcF93aGlsZTogZnVuY3Rpb24gKGNvbGxlY3Rpb24sIGZ1bikge1xuICAgIGxldCBjb3VudCA9IDA7XG5cbiAgICBmb3IgKGxldCBlbGVtIG9mIGNvbGxlY3Rpb24pIHtcbiAgICAgIGlmIChmdW4oZWxlbSkpIHtcbiAgICAgICAgY291bnQgPSBjb3VudCArIDE7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBicmVhaztcbiAgICAgIH1cbiAgICB9XG5cbiAgICByZXR1cm4gY29sbGVjdGlvbi5zbGljZShjb3VudCk7XG4gIH0sXG5cbiAgZWFjaDogZnVuY3Rpb24gKGNvbGxlY3Rpb24sIGZ1bikge1xuICAgIGZvciAobGV0IGVsZW0gb2YgY29sbGVjdGlvbikge1xuICAgICAgZnVuKGVsZW0pO1xuICAgIH1cbiAgfSxcblxuICBlbXB0eV9fcW1hcmtfXzogZnVuY3Rpb24gKGNvbGxlY3Rpb24pIHtcbiAgICByZXR1cm4gY29sbGVjdGlvbi5sZW5ndGggPT09IDA7XG4gIH0sXG5cbiAgZmV0Y2g6IGZ1bmN0aW9uIChjb2xsZWN0aW9uLCBuKSB7XG4gICAgaWYgKEFycmF5LmlzQXJyYXkoY29sbGVjdGlvbikpIHtcbiAgICAgIGlmIChuIDwgdGhpcy5jb3VudChjb2xsZWN0aW9uKSAmJiBuID49IDApIHtcbiAgICAgICAgcmV0dXJuIG5ldyBUdXBsZShTeW1ib2wuZm9yKFwib2tcIiksIGNvbGxlY3Rpb25bbl0pO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgcmV0dXJuIFN5bWJvbC5mb3IoXCJlcnJvclwiKTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICB0aHJvdyBuZXcgRXJyb3IoXCJjb2xsZWN0aW9uIGlzIG5vdCBhbiBFbnVtZXJhYmxlXCIpO1xuICB9LFxuXG4gIGZldGNoX19lbWFya19fOiBmdW5jdGlvbiAoY29sbGVjdGlvbiwgbikge1xuICAgIGlmIChBcnJheS5pc0FycmF5KGNvbGxlY3Rpb24pKSB7XG4gICAgICBpZiAobiA8IHRoaXMuY291bnQoY29sbGVjdGlvbikgJiYgbiA+PSAwKSB7XG4gICAgICAgIHJldHVybiBjb2xsZWN0aW9uW25dO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKFwib3V0IG9mIGJvdW5kcyBlcnJvclwiKTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICB0aHJvdyBuZXcgRXJyb3IoXCJjb2xsZWN0aW9uIGlzIG5vdCBhbiBFbnVtZXJhYmxlXCIpO1xuICB9LFxuXG4gIGZpbHRlcjogZnVuY3Rpb24gKGNvbGxlY3Rpb24sIGZ1bikge1xuICAgIGxldCByZXN1bHQgPSBbXTtcblxuICAgIGZvciAobGV0IGVsZW0gb2YgY29sbGVjdGlvbikge1xuICAgICAgaWYgKGZ1bihlbGVtKSkge1xuICAgICAgICByZXN1bHQucHVzaChlbGVtKTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICByZXR1cm4gcmVzdWx0O1xuICB9LFxuXG4gIGZpbHRlcl9tYXA6IGZ1bmN0aW9uIChjb2xsZWN0aW9uLCBmaWx0ZXIsIG1hcHBlcikge1xuICAgIHJldHVybiBFbnVtLm1hcChFbnVtLmZpbHRlcihjb2xsZWN0aW9uLCBmaWx0ZXIpLCBtYXBwZXIpO1xuICB9LFxuXG4gIGZpbmQ6IGZ1bmN0aW9uIChjb2xsZWN0aW9uLCBpZl9ub25lID0gbnVsbCwgZnVuKSB7XG4gICAgZm9yIChsZXQgZWxlbSBvZiBjb2xsZWN0aW9uKSB7XG4gICAgICBpZiAoZnVuKGVsZW0pKSB7XG4gICAgICAgIHJldHVybiBlbGVtO1xuICAgICAgfVxuICAgIH1cblxuICAgIHJldHVybiBpZl9ub25lO1xuICB9LFxuXG4gIGludG86IGZ1bmN0aW9uIChjb2xsZWN0aW9uLCBsaXN0KSB7XG4gICAgcmV0dXJuIGxpc3QuY29uY2F0KGNvbGxlY3Rpb24pO1xuICB9LFxuXG4gIG1hcDogZnVuY3Rpb24gKGNvbGxlY3Rpb24sIGZ1bikge1xuICAgIGxldCByZXN1bHQgPSBbXTtcblxuICAgIGZvciAobGV0IGVsZW0gb2YgY29sbGVjdGlvbikge1xuICAgICAgcmVzdWx0LnB1c2goZnVuKGVsZW0pKTtcbiAgICB9XG5cbiAgICByZXR1cm4gcmVzdWx0O1xuICB9LFxuXG4gIG1hcF9yZWR1Y2U6IGZ1bmN0aW9uIChjb2xsZWN0aW9uLCBhY2MsIGZ1bikge1xuICAgIGxldCBtYXBwZWQgPSBPYmplY3QuZnJlZXplKFtdKTtcbiAgICBsZXQgdGhlX2FjYyA9IGFjYztcblxuICAgIGZvciAodmFyIGkgPSAwOyBpIDwgdGhpcy5jb3VudChjb2xsZWN0aW9uKTsgaSsrKSB7XG4gICAgICBsZXQgdHVwbGUgPSBmdW4oY29sbGVjdGlvbltpXSwgdGhlX2FjYyk7XG5cbiAgICAgIHRoZV9hY2MgPSB0dXBsZS5nZXQoMSk7XG4gICAgICBtYXBwZWQgPSBPYmplY3QuZnJlZXplKG1hcHBlZC5jb25jYXQoW3R1cGxlLmdldCgwKV0pKTtcbiAgICB9XG5cbiAgICByZXR1cm4gbmV3IFR1cGxlKG1hcHBlZCwgdGhlX2FjYyk7XG4gIH0sXG5cbiAgbWVtYmVyX19xbWFya19fOiBmdW5jdGlvbiAoY29sbGVjdGlvbiwgdmFsdWUpIHtcbiAgICByZXR1cm4gY29sbGVjdGlvbi5pbmNsdWRlcyh2YWx1ZSk7XG4gIH0sXG5cbiAgcmVkdWNlOiBmdW5jdGlvbiAoY29sbGVjdGlvbiwgYWNjLCBmdW4pIHtcbiAgICBsZXQgdGhlX2FjYyA9IGFjYztcblxuICAgIGZvciAodmFyIGkgPSAwOyBpIDwgdGhpcy5jb3VudChjb2xsZWN0aW9uKTsgaSsrKSB7XG4gICAgICBsZXQgdHVwbGUgPSBmdW4oY29sbGVjdGlvbltpXSwgdGhlX2FjYyk7XG5cbiAgICAgIHRoZV9hY2MgPSB0dXBsZS5nZXQoMSk7XG4gICAgfVxuXG4gICAgcmV0dXJuIHRoZV9hY2M7XG4gIH0sXG5cbiAgdGFrZTogZnVuY3Rpb24gKGNvbGxlY3Rpb24sIGNvdW50KSB7XG4gICAgcmV0dXJuIGNvbGxlY3Rpb24uc2xpY2UoMCwgY291bnQpO1xuICB9LFxuXG4gIHRha2VfZXZlcnk6IGZ1bmN0aW9uIChjb2xsZWN0aW9uLCBudGgpIHtcbiAgICBsZXQgcmVzdWx0ID0gW107XG4gICAgbGV0IGluZGV4ID0gMDtcblxuICAgIGZvciAobGV0IGVsZW0gb2YgY29sbGVjdGlvbikge1xuICAgICAgaWYgKGluZGV4ICUgbnRoID09PSAwKSB7XG4gICAgICAgIHJlc3VsdC5wdXNoKGVsZW0pO1xuICAgICAgfVxuICAgIH1cblxuICAgIHJldHVybiBPYmplY3QuZnJlZXplKHJlc3VsdCk7XG4gIH0sXG5cbiAgdGFrZV93aGlsZTogZnVuY3Rpb24gKGNvbGxlY3Rpb24sIGZ1bikge1xuICAgIGxldCBjb3VudCA9IDA7XG5cbiAgICBmb3IgKGxldCBlbGVtIG9mIGNvbGxlY3Rpb24pIHtcbiAgICAgIGlmIChmdW4oZWxlbSkpIHtcbiAgICAgICAgY291bnQgPSBjb3VudCArIDE7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBicmVhaztcbiAgICAgIH1cbiAgICB9XG5cbiAgICByZXR1cm4gY29sbGVjdGlvbi5zbGljZSgwLCBjb3VudCk7XG4gIH0sXG5cbiAgdG9fbGlzdDogZnVuY3Rpb24gKGNvbGxlY3Rpb24pIHtcbiAgICByZXR1cm4gY29sbGVjdGlvbjtcbiAgfVxufTtcblxubGV0IFZpcnR1YWxET00gPSAoZnVuY3Rpb24gKGUpIHtcbiAgICByZXR1cm4gZSgpO1xufSkoZnVuY3Rpb24gKCkge1xuICAgIHZhciBkZWZpbmUsIG1vZHVsZSwgZXhwb3J0cztcbiAgICByZXR1cm4gKGZ1bmN0aW9uIGUodCwgbiwgcikge1xuICAgICAgICBmdW5jdGlvbiBzKG8sIHUpIHtcbiAgICAgICAgICAgIGlmICghbltvXSkge1xuICAgICAgICAgICAgICAgIGlmICghdFtvXSkge1xuICAgICAgICAgICAgICAgICAgICB2YXIgYSA9IHR5cGVvZiByZXF1aXJlID09IFwiZnVuY3Rpb25cIiAmJiByZXF1aXJlO1xuICAgICAgICAgICAgICAgICAgICBpZiAoIXUgJiYgYSkgcmV0dXJuIGEobywgITApO1xuICAgICAgICAgICAgICAgICAgICBpZiAoaSkgcmV0dXJuIGkobywgITApO1xuICAgICAgICAgICAgICAgICAgICB2YXIgZiA9IG5ldyBFcnJvcihcIkNhbm5vdCBmaW5kIG1vZHVsZSAnXCIgKyBvICsgXCInXCIpO1xuICAgICAgICAgICAgICAgICAgICB0aHJvdyAoZi5jb2RlID0gXCJNT0RVTEVfTk9UX0ZPVU5EXCIsIGYpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB2YXIgbCA9IG5bb10gPSB7XG4gICAgICAgICAgICAgICAgICAgIGV4cG9ydHM6IHt9XG4gICAgICAgICAgICAgICAgfTtcbiAgICAgICAgICAgICAgICB0W29dWzBdLmNhbGwobC5leHBvcnRzLCBmdW5jdGlvbiAoZSkge1xuICAgICAgICAgICAgICAgICAgICB2YXIgbiA9IHRbb11bMV1bZV07XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBzKG4gPyBuIDogZSk7XG4gICAgICAgICAgICAgICAgfSwgbCwgbC5leHBvcnRzLCBlLCB0LCBuLCByKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJldHVybiBuW29dLmV4cG9ydHM7XG4gICAgICAgIH1cbiAgICAgICAgdmFyIGkgPSB0eXBlb2YgcmVxdWlyZSA9PSBcImZ1bmN0aW9uXCIgJiYgcmVxdWlyZTtcbiAgICAgICAgZm9yICh2YXIgbyA9IDA7IG8gPCByLmxlbmd0aDsgbysrKSBzKHJbb10pO1xuICAgICAgICByZXR1cm4gcztcbiAgICB9KSh7XG4gICAgICAgIDE6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG5cbiAgICAgICAgICAgIHZhciBjcmVhdGVFbGVtZW50ID0gcmVxdWlyZShcIi4vdmRvbS9jcmVhdGUtZWxlbWVudC5qc1wiKTtcblxuICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBjcmVhdGVFbGVtZW50O1xuICAgICAgICB9LCB7IFwiLi92ZG9tL2NyZWF0ZS1lbGVtZW50LmpzXCI6IDE1IH1dLCAyOiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge1xuICAgICAgICAgICAgdmFyIGRpZmYgPSByZXF1aXJlKFwiLi92dHJlZS9kaWZmLmpzXCIpO1xuXG4gICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IGRpZmY7XG4gICAgICAgIH0sIHsgXCIuL3Z0cmVlL2RpZmYuanNcIjogMzUgfV0sIDM6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICB2YXIgaCA9IHJlcXVpcmUoXCIuL3ZpcnR1YWwtaHlwZXJzY3JpcHQvaW5kZXguanNcIik7XG5cbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gaDtcbiAgICAgICAgfSwgeyBcIi4vdmlydHVhbC1oeXBlcnNjcmlwdC9pbmRleC5qc1wiOiAyMiB9XSwgNDogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHtcbiAgICAgICAgICAgIHZhciBkaWZmID0gcmVxdWlyZShcIi4vZGlmZi5qc1wiKTtcbiAgICAgICAgICAgIHZhciBwYXRjaCA9IHJlcXVpcmUoXCIuL3BhdGNoLmpzXCIpO1xuICAgICAgICAgICAgdmFyIGggPSByZXF1aXJlKFwiLi9oLmpzXCIpO1xuICAgICAgICAgICAgdmFyIGNyZWF0ZSA9IHJlcXVpcmUoXCIuL2NyZWF0ZS1lbGVtZW50LmpzXCIpO1xuICAgICAgICAgICAgdmFyIFZOb2RlID0gcmVxdWlyZShcIi4vdm5vZGUvdm5vZGUuanNcIik7XG4gICAgICAgICAgICB2YXIgVlRleHQgPSByZXF1aXJlKFwiLi92bm9kZS92dGV4dC5qc1wiKTtcblxuICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSB7XG4gICAgICAgICAgICAgICAgZGlmZjogZGlmZixcbiAgICAgICAgICAgICAgICBwYXRjaDogcGF0Y2gsXG4gICAgICAgICAgICAgICAgaDogaCxcbiAgICAgICAgICAgICAgICBjcmVhdGU6IGNyZWF0ZSxcbiAgICAgICAgICAgICAgICBWTm9kZTogVk5vZGUsXG4gICAgICAgICAgICAgICAgVlRleHQ6IFZUZXh0XG4gICAgICAgICAgICB9O1xuICAgICAgICB9LCB7IFwiLi9jcmVhdGUtZWxlbWVudC5qc1wiOiAxLCBcIi4vZGlmZi5qc1wiOiAyLCBcIi4vaC5qc1wiOiAzLCBcIi4vcGF0Y2guanNcIjogMTMsIFwiLi92bm9kZS92bm9kZS5qc1wiOiAzMSwgXCIuL3Zub2RlL3Z0ZXh0LmpzXCI6IDMzIH1dLCA1OiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge1xuICAgICAgICAgICAgLyohXG4gICAgICAgICAgICAgKiBDcm9zcy1Ccm93c2VyIFNwbGl0IDEuMS4xXG4gICAgICAgICAgICAgKiBDb3B5cmlnaHQgMjAwNy0yMDEyIFN0ZXZlbiBMZXZpdGhhbiA8c3RldmVubGV2aXRoYW4uY29tPlxuICAgICAgICAgICAgICogQXZhaWxhYmxlIHVuZGVyIHRoZSBNSVQgTGljZW5zZVxuICAgICAgICAgICAgICogRUNNQVNjcmlwdCBjb21wbGlhbnQsIHVuaWZvcm0gY3Jvc3MtYnJvd3NlciBzcGxpdCBtZXRob2RcbiAgICAgICAgICAgICAqL1xuXG4gICAgICAgICAgICAvKipcbiAgICAgICAgICAgICAqIFNwbGl0cyBhIHN0cmluZyBpbnRvIGFuIGFycmF5IG9mIHN0cmluZ3MgdXNpbmcgYSByZWdleCBvciBzdHJpbmcgc2VwYXJhdG9yLiBNYXRjaGVzIG9mIHRoZVxuICAgICAgICAgICAgICogc2VwYXJhdG9yIGFyZSBub3QgaW5jbHVkZWQgaW4gdGhlIHJlc3VsdCBhcnJheS4gSG93ZXZlciwgaWYgYHNlcGFyYXRvcmAgaXMgYSByZWdleCB0aGF0IGNvbnRhaW5zXG4gICAgICAgICAgICAgKiBjYXB0dXJpbmcgZ3JvdXBzLCBiYWNrcmVmZXJlbmNlcyBhcmUgc3BsaWNlZCBpbnRvIHRoZSByZXN1bHQgZWFjaCB0aW1lIGBzZXBhcmF0b3JgIGlzIG1hdGNoZWQuXG4gICAgICAgICAgICAgKiBGaXhlcyBicm93c2VyIGJ1Z3MgY29tcGFyZWQgdG8gdGhlIG5hdGl2ZSBgU3RyaW5nLnByb3RvdHlwZS5zcGxpdGAgYW5kIGNhbiBiZSB1c2VkIHJlbGlhYmx5XG4gICAgICAgICAgICAgKiBjcm9zcy1icm93c2VyLlxuICAgICAgICAgICAgICogQHBhcmFtIHtTdHJpbmd9IHN0ciBTdHJpbmcgdG8gc3BsaXQuXG4gICAgICAgICAgICAgKiBAcGFyYW0ge1JlZ0V4cHxTdHJpbmd9IHNlcGFyYXRvciBSZWdleCBvciBzdHJpbmcgdG8gdXNlIGZvciBzZXBhcmF0aW5nIHRoZSBzdHJpbmcuXG4gICAgICAgICAgICAgKiBAcGFyYW0ge051bWJlcn0gW2xpbWl0XSBNYXhpbXVtIG51bWJlciBvZiBpdGVtcyB0byBpbmNsdWRlIGluIHRoZSByZXN1bHQgYXJyYXkuXG4gICAgICAgICAgICAgKiBAcmV0dXJucyB7QXJyYXl9IEFycmF5IG9mIHN1YnN0cmluZ3MuXG4gICAgICAgICAgICAgKiBAZXhhbXBsZVxuICAgICAgICAgICAgICpcbiAgICAgICAgICAgICAqIC8vIEJhc2ljIHVzZVxuICAgICAgICAgICAgICogc3BsaXQoJ2EgYiBjIGQnLCAnICcpO1xuICAgICAgICAgICAgICogLy8gLT4gWydhJywgJ2InLCAnYycsICdkJ11cbiAgICAgICAgICAgICAqXG4gICAgICAgICAgICAgKiAvLyBXaXRoIGxpbWl0XG4gICAgICAgICAgICAgKiBzcGxpdCgnYSBiIGMgZCcsICcgJywgMik7XG4gICAgICAgICAgICAgKiAvLyAtPiBbJ2EnLCAnYiddXG4gICAgICAgICAgICAgKlxuICAgICAgICAgICAgICogLy8gQmFja3JlZmVyZW5jZXMgaW4gcmVzdWx0IGFycmF5XG4gICAgICAgICAgICAgKiBzcGxpdCgnLi53b3JkMSB3b3JkMi4uJywgLyhbYS16XSspKFxcZCspL2kpO1xuICAgICAgICAgICAgICogLy8gLT4gWycuLicsICd3b3JkJywgJzEnLCAnICcsICd3b3JkJywgJzInLCAnLi4nXVxuICAgICAgICAgICAgICovXG4gICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IChmdW5jdGlvbiBzcGxpdCh1bmRlZikge1xuXG4gICAgICAgICAgICAgICAgdmFyIG5hdGl2ZVNwbGl0ID0gU3RyaW5nLnByb3RvdHlwZS5zcGxpdCxcbiAgICAgICAgICAgICAgICAgICAgY29tcGxpYW50RXhlY05wY2cgPSAvKCk/Py8uZXhlYyhcIlwiKVsxXSA9PT0gdW5kZWYsXG5cbiAgICAgICAgICAgICAgICAvLyBOUENHOiBub25wYXJ0aWNpcGF0aW5nIGNhcHR1cmluZyBncm91cFxuICAgICAgICAgICAgICAgIHNlbGY7XG5cbiAgICAgICAgICAgICAgICBzZWxmID0gZnVuY3Rpb24gKHN0ciwgc2VwYXJhdG9yLCBsaW1pdCkge1xuICAgICAgICAgICAgICAgICAgICAvLyBJZiBgc2VwYXJhdG9yYCBpcyBub3QgYSByZWdleCwgdXNlIGBuYXRpdmVTcGxpdGBcbiAgICAgICAgICAgICAgICAgICAgaWYgKE9iamVjdC5wcm90b3R5cGUudG9TdHJpbmcuY2FsbChzZXBhcmF0b3IpICE9PSBcIltvYmplY3QgUmVnRXhwXVwiKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gbmF0aXZlU3BsaXQuY2FsbChzdHIsIHNlcGFyYXRvciwgbGltaXQpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIHZhciBvdXRwdXQgPSBbXSxcbiAgICAgICAgICAgICAgICAgICAgICAgIGZsYWdzID0gKHNlcGFyYXRvci5pZ25vcmVDYXNlID8gXCJpXCIgOiBcIlwiKSArIChzZXBhcmF0b3IubXVsdGlsaW5lID8gXCJtXCIgOiBcIlwiKSArIChzZXBhcmF0b3IuZXh0ZW5kZWQgPyBcInhcIiA6IFwiXCIpICsgKHNlcGFyYXRvci5zdGlja3kgPyBcInlcIiA6IFwiXCIpLFxuXG4gICAgICAgICAgICAgICAgICAgIC8vIEZpcmVmb3ggMytcbiAgICAgICAgICAgICAgICAgICAgbGFzdExhc3RJbmRleCA9IDAsXG5cbiAgICAgICAgICAgICAgICAgICAgLy8gTWFrZSBgZ2xvYmFsYCBhbmQgYXZvaWQgYGxhc3RJbmRleGAgaXNzdWVzIGJ5IHdvcmtpbmcgd2l0aCBhIGNvcHlcbiAgICAgICAgICAgICAgICAgICAgc2VwYXJhdG9yID0gbmV3IFJlZ0V4cChzZXBhcmF0b3Iuc291cmNlLCBmbGFncyArIFwiZ1wiKSxcbiAgICAgICAgICAgICAgICAgICAgICAgIHNlcGFyYXRvcjIsXG4gICAgICAgICAgICAgICAgICAgICAgICBtYXRjaCxcbiAgICAgICAgICAgICAgICAgICAgICAgIGxhc3RJbmRleCxcbiAgICAgICAgICAgICAgICAgICAgICAgIGxhc3RMZW5ndGg7XG4gICAgICAgICAgICAgICAgICAgIHN0ciArPSBcIlwiOyAvLyBUeXBlLWNvbnZlcnRcbiAgICAgICAgICAgICAgICAgICAgaWYgKCFjb21wbGlhbnRFeGVjTnBjZykge1xuICAgICAgICAgICAgICAgICAgICAgICAgLy8gRG9lc24ndCBuZWVkIGZsYWdzIGd5LCBidXQgdGhleSBkb24ndCBodXJ0XG4gICAgICAgICAgICAgICAgICAgICAgICBzZXBhcmF0b3IyID0gbmV3IFJlZ0V4cChcIl5cIiArIHNlcGFyYXRvci5zb3VyY2UgKyBcIiQoPyFcXFxccylcIiwgZmxhZ3MpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIC8qIFZhbHVlcyBmb3IgYGxpbWl0YCwgcGVyIHRoZSBzcGVjOlxuICAgICAgICAgICAgICAgICAgICAgKiBJZiB1bmRlZmluZWQ6IDQyOTQ5NjcyOTUgLy8gTWF0aC5wb3coMiwgMzIpIC0gMVxuICAgICAgICAgICAgICAgICAgICAgKiBJZiAwLCBJbmZpbml0eSwgb3IgTmFOOiAwXG4gICAgICAgICAgICAgICAgICAgICAqIElmIHBvc2l0aXZlIG51bWJlcjogbGltaXQgPSBNYXRoLmZsb29yKGxpbWl0KTsgaWYgKGxpbWl0ID4gNDI5NDk2NzI5NSkgbGltaXQgLT0gNDI5NDk2NzI5NjtcbiAgICAgICAgICAgICAgICAgICAgICogSWYgbmVnYXRpdmUgbnVtYmVyOiA0Mjk0OTY3Mjk2IC0gTWF0aC5mbG9vcihNYXRoLmFicyhsaW1pdCkpXG4gICAgICAgICAgICAgICAgICAgICAqIElmIG90aGVyOiBUeXBlLWNvbnZlcnQsIHRoZW4gdXNlIHRoZSBhYm92ZSBydWxlc1xuICAgICAgICAgICAgICAgICAgICAgKi9cbiAgICAgICAgICAgICAgICAgICAgbGltaXQgPSBsaW1pdCA9PT0gdW5kZWYgPyAtMSA+Pj4gMCA6IC8vIE1hdGgucG93KDIsIDMyKSAtIDFcbiAgICAgICAgICAgICAgICAgICAgbGltaXQgPj4+IDA7IC8vIFRvVWludDMyKGxpbWl0KVxuICAgICAgICAgICAgICAgICAgICB3aGlsZSAobWF0Y2ggPSBzZXBhcmF0b3IuZXhlYyhzdHIpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAvLyBgc2VwYXJhdG9yLmxhc3RJbmRleGAgaXMgbm90IHJlbGlhYmxlIGNyb3NzLWJyb3dzZXJcbiAgICAgICAgICAgICAgICAgICAgICAgIGxhc3RJbmRleCA9IG1hdGNoLmluZGV4ICsgbWF0Y2hbMF0ubGVuZ3RoO1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGxhc3RJbmRleCA+IGxhc3RMYXN0SW5kZXgpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBvdXRwdXQucHVzaChzdHIuc2xpY2UobGFzdExhc3RJbmRleCwgbWF0Y2guaW5kZXgpKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBGaXggYnJvd3NlcnMgd2hvc2UgYGV4ZWNgIG1ldGhvZHMgZG9uJ3QgY29uc2lzdGVudGx5IHJldHVybiBgdW5kZWZpbmVkYCBmb3JcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBub25wYXJ0aWNpcGF0aW5nIGNhcHR1cmluZyBncm91cHNcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoIWNvbXBsaWFudEV4ZWNOcGNnICYmIG1hdGNoLmxlbmd0aCA+IDEpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbWF0Y2hbMF0ucmVwbGFjZShzZXBhcmF0b3IyLCBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBmb3IgKHZhciBpID0gMTsgaSA8IGFyZ3VtZW50cy5sZW5ndGggLSAyOyBpKyspIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoYXJndW1lbnRzW2ldID09PSB1bmRlZikge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBtYXRjaFtpXSA9IHVuZGVmO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChtYXRjaC5sZW5ndGggPiAxICYmIG1hdGNoLmluZGV4IDwgc3RyLmxlbmd0aCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBBcnJheS5wcm90b3R5cGUucHVzaC5hcHBseShvdXRwdXQsIG1hdGNoLnNsaWNlKDEpKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgbGFzdExlbmd0aCA9IG1hdGNoWzBdLmxlbmd0aDtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBsYXN0TGFzdEluZGV4ID0gbGFzdEluZGV4O1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChvdXRwdXQubGVuZ3RoID49IGxpbWl0KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChzZXBhcmF0b3IubGFzdEluZGV4ID09PSBtYXRjaC5pbmRleCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNlcGFyYXRvci5sYXN0SW5kZXgrKzsgLy8gQXZvaWQgYW4gaW5maW5pdGUgbG9vcFxuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIGlmIChsYXN0TGFzdEluZGV4ID09PSBzdHIubGVuZ3RoKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAobGFzdExlbmd0aCB8fCAhc2VwYXJhdG9yLnRlc3QoXCJcIikpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBvdXRwdXQucHVzaChcIlwiKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIG91dHB1dC5wdXNoKHN0ci5zbGljZShsYXN0TGFzdEluZGV4KSk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIG91dHB1dC5sZW5ndGggPiBsaW1pdCA/IG91dHB1dC5zbGljZSgwLCBsaW1pdCkgOiBvdXRwdXQ7XG4gICAgICAgICAgICAgICAgfTtcblxuICAgICAgICAgICAgICAgIHJldHVybiBzZWxmO1xuICAgICAgICAgICAgfSkoKTtcbiAgICAgICAgfSwge31dLCA2OiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge30sIHt9XSwgNzogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHtcbiAgICAgICAgICAgIFwidXNlIHN0cmljdFwiO1xuXG4gICAgICAgICAgICB2YXIgT25lVmVyc2lvbkNvbnN0cmFpbnQgPSByZXF1aXJlKFwiaW5kaXZpZHVhbC9vbmUtdmVyc2lvblwiKTtcblxuICAgICAgICAgICAgdmFyIE1ZX1ZFUlNJT04gPSBcIjdcIjtcbiAgICAgICAgICAgIE9uZVZlcnNpb25Db25zdHJhaW50KFwiZXYtc3RvcmVcIiwgTVlfVkVSU0lPTik7XG5cbiAgICAgICAgICAgIHZhciBoYXNoS2V5ID0gXCJfX0VWX1NUT1JFX0tFWUBcIiArIE1ZX1ZFUlNJT047XG5cbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gRXZTdG9yZTtcblxuICAgICAgICAgICAgZnVuY3Rpb24gRXZTdG9yZShlbGVtKSB7XG4gICAgICAgICAgICAgICAgdmFyIGhhc2ggPSBlbGVtW2hhc2hLZXldO1xuXG4gICAgICAgICAgICAgICAgaWYgKCFoYXNoKSB7XG4gICAgICAgICAgICAgICAgICAgIGhhc2ggPSBlbGVtW2hhc2hLZXldID0ge307XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgcmV0dXJuIGhhc2g7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0sIHsgXCJpbmRpdmlkdWFsL29uZS12ZXJzaW9uXCI6IDkgfV0sIDg6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICAoZnVuY3Rpb24gKGdsb2JhbCkge1xuICAgICAgICAgICAgICAgIFwidXNlIHN0cmljdFwiO1xuXG4gICAgICAgICAgICAgICAgLypnbG9iYWwgd2luZG93LCBnbG9iYWwqL1xuXG4gICAgICAgICAgICAgICAgdmFyIHJvb3QgPSB0eXBlb2Ygd2luZG93ICE9PSBcInVuZGVmaW5lZFwiID8gd2luZG93IDogdHlwZW9mIGdsb2JhbCAhPT0gXCJ1bmRlZmluZWRcIiA/IGdsb2JhbCA6IHt9O1xuXG4gICAgICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBJbmRpdmlkdWFsO1xuXG4gICAgICAgICAgICAgICAgZnVuY3Rpb24gSW5kaXZpZHVhbChrZXksIHZhbHVlKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmIChrZXkgaW4gcm9vdCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHJvb3Rba2V5XTtcbiAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgIHJvb3Rba2V5XSA9IHZhbHVlO1xuXG4gICAgICAgICAgICAgICAgICAgIHJldHVybiB2YWx1ZTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9KS5jYWxsKHRoaXMsIHR5cGVvZiBnbG9iYWwgIT09IFwidW5kZWZpbmVkXCIgPyBnbG9iYWwgOiB0eXBlb2Ygc2VsZiAhPT0gXCJ1bmRlZmluZWRcIiA/IHNlbGYgOiB0eXBlb2Ygd2luZG93ICE9PSBcInVuZGVmaW5lZFwiID8gd2luZG93IDoge30pO1xuICAgICAgICB9LCB7fV0sIDk6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICBcInVzZSBzdHJpY3RcIjtcblxuICAgICAgICAgICAgdmFyIEluZGl2aWR1YWwgPSByZXF1aXJlKFwiLi9pbmRleC5qc1wiKTtcblxuICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBPbmVWZXJzaW9uO1xuXG4gICAgICAgICAgICBmdW5jdGlvbiBPbmVWZXJzaW9uKG1vZHVsZU5hbWUsIHZlcnNpb24sIGRlZmF1bHRWYWx1ZSkge1xuICAgICAgICAgICAgICAgIHZhciBrZXkgPSBcIl9fSU5ESVZJRFVBTF9PTkVfVkVSU0lPTl9cIiArIG1vZHVsZU5hbWU7XG4gICAgICAgICAgICAgICAgdmFyIGVuZm9yY2VLZXkgPSBrZXkgKyBcIl9FTkZPUkNFX1NJTkdMRVRPTlwiO1xuXG4gICAgICAgICAgICAgICAgdmFyIHZlcnNpb25WYWx1ZSA9IEluZGl2aWR1YWwoZW5mb3JjZUtleSwgdmVyc2lvbik7XG5cbiAgICAgICAgICAgICAgICBpZiAodmVyc2lvblZhbHVlICE9PSB2ZXJzaW9uKSB7XG4gICAgICAgICAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcihcIkNhbiBvbmx5IGhhdmUgb25lIGNvcHkgb2YgXCIgKyBtb2R1bGVOYW1lICsgXCIuXFxuXCIgKyBcIllvdSBhbHJlYWR5IGhhdmUgdmVyc2lvbiBcIiArIHZlcnNpb25WYWx1ZSArIFwiIGluc3RhbGxlZC5cXG5cIiArIFwiVGhpcyBtZWFucyB5b3UgY2Fubm90IGluc3RhbGwgdmVyc2lvbiBcIiArIHZlcnNpb24pO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHJldHVybiBJbmRpdmlkdWFsKGtleSwgZGVmYXVsdFZhbHVlKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSwgeyBcIi4vaW5kZXguanNcIjogOCB9XSwgMTA6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICAoZnVuY3Rpb24gKGdsb2JhbCkge1xuICAgICAgICAgICAgICAgIHZhciB0b3BMZXZlbCA9IHR5cGVvZiBnbG9iYWwgIT09IFwidW5kZWZpbmVkXCIgPyBnbG9iYWwgOiB0eXBlb2Ygd2luZG93ICE9PSBcInVuZGVmaW5lZFwiID8gd2luZG93IDoge307XG4gICAgICAgICAgICAgICAgdmFyIG1pbkRvYyA9IHJlcXVpcmUoXCJtaW4tZG9jdW1lbnRcIik7XG5cbiAgICAgICAgICAgICAgICBpZiAodHlwZW9mIGRvY3VtZW50ICE9PSBcInVuZGVmaW5lZFwiKSB7XG4gICAgICAgICAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gZG9jdW1lbnQ7XG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgdmFyIGRvY2N5ID0gdG9wTGV2ZWxbXCJfX0dMT0JBTF9ET0NVTUVOVF9DQUNIRUA0XCJdO1xuXG4gICAgICAgICAgICAgICAgICAgIGlmICghZG9jY3kpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGRvY2N5ID0gdG9wTGV2ZWxbXCJfX0dMT0JBTF9ET0NVTUVOVF9DQUNIRUA0XCJdID0gbWluRG9jO1xuICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBkb2NjeTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9KS5jYWxsKHRoaXMsIHR5cGVvZiBnbG9iYWwgIT09IFwidW5kZWZpbmVkXCIgPyBnbG9iYWwgOiB0eXBlb2Ygc2VsZiAhPT0gXCJ1bmRlZmluZWRcIiA/IHNlbGYgOiB0eXBlb2Ygd2luZG93ICE9PSBcInVuZGVmaW5lZFwiID8gd2luZG93IDoge30pO1xuICAgICAgICB9LCB7IFwibWluLWRvY3VtZW50XCI6IDYgfV0sIDExOiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge1xuICAgICAgICAgICAgXCJ1c2Ugc3RyaWN0XCI7XG5cbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gaXNPYmplY3QoeCkge1xuICAgICAgICAgICAgICAgIHJldHVybiB0eXBlb2YgeCA9PT0gXCJvYmplY3RcIiAmJiB4ICE9PSBudWxsO1xuICAgICAgICAgICAgfTtcbiAgICAgICAgfSwge31dLCAxMjogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHtcbiAgICAgICAgICAgIHZhciBuYXRpdmVJc0FycmF5ID0gQXJyYXkuaXNBcnJheTtcbiAgICAgICAgICAgIHZhciB0b1N0cmluZyA9IE9iamVjdC5wcm90b3R5cGUudG9TdHJpbmc7XG5cbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gbmF0aXZlSXNBcnJheSB8fCBpc0FycmF5O1xuXG4gICAgICAgICAgICBmdW5jdGlvbiBpc0FycmF5KG9iaikge1xuICAgICAgICAgICAgICAgIHJldHVybiB0b1N0cmluZy5jYWxsKG9iaikgPT09IFwiW29iamVjdCBBcnJheV1cIjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSwge31dLCAxMzogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHtcbiAgICAgICAgICAgIHZhciBwYXRjaCA9IHJlcXVpcmUoXCIuL3Zkb20vcGF0Y2guanNcIik7XG5cbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gcGF0Y2g7XG4gICAgICAgIH0sIHsgXCIuL3Zkb20vcGF0Y2guanNcIjogMTggfV0sIDE0OiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge1xuICAgICAgICAgICAgdmFyIGlzT2JqZWN0ID0gcmVxdWlyZShcImlzLW9iamVjdFwiKTtcbiAgICAgICAgICAgIHZhciBpc0hvb2sgPSByZXF1aXJlKFwiLi4vdm5vZGUvaXMtdmhvb2suanNcIik7XG5cbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gYXBwbHlQcm9wZXJ0aWVzO1xuXG4gICAgICAgICAgICBmdW5jdGlvbiBhcHBseVByb3BlcnRpZXMobm9kZSwgcHJvcHMsIHByZXZpb3VzKSB7XG4gICAgICAgICAgICAgICAgZm9yICh2YXIgcHJvcE5hbWUgaW4gcHJvcHMpIHtcbiAgICAgICAgICAgICAgICAgICAgdmFyIHByb3BWYWx1ZSA9IHByb3BzW3Byb3BOYW1lXTtcblxuICAgICAgICAgICAgICAgICAgICBpZiAocHJvcFZhbHVlID09PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJlbW92ZVByb3BlcnR5KG5vZGUsIHByb3BOYW1lLCBwcm9wVmFsdWUsIHByZXZpb3VzKTtcbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIGlmIChpc0hvb2socHJvcFZhbHVlKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgcmVtb3ZlUHJvcGVydHkobm9kZSwgcHJvcE5hbWUsIHByb3BWYWx1ZSwgcHJldmlvdXMpO1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHByb3BWYWx1ZS5ob29rKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcHJvcFZhbHVlLmhvb2sobm9kZSwgcHJvcE5hbWUsIHByZXZpb3VzID8gcHJldmlvdXNbcHJvcE5hbWVdIDogdW5kZWZpbmVkKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChpc09iamVjdChwcm9wVmFsdWUpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcGF0Y2hPYmplY3Qobm9kZSwgcHJvcHMsIHByZXZpb3VzLCBwcm9wTmFtZSwgcHJvcFZhbHVlKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgbm9kZVtwcm9wTmFtZV0gPSBwcm9wVmFsdWU7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIHJlbW92ZVByb3BlcnR5KG5vZGUsIHByb3BOYW1lLCBwcm9wVmFsdWUsIHByZXZpb3VzKSB7XG4gICAgICAgICAgICAgICAgaWYgKHByZXZpb3VzKSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciBwcmV2aW91c1ZhbHVlID0gcHJldmlvdXNbcHJvcE5hbWVdO1xuXG4gICAgICAgICAgICAgICAgICAgIGlmICghaXNIb29rKHByZXZpb3VzVmFsdWUpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAocHJvcE5hbWUgPT09IFwiYXR0cmlidXRlc1wiKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgZm9yICh2YXIgYXR0ck5hbWUgaW4gcHJldmlvdXNWYWx1ZSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBub2RlLnJlbW92ZUF0dHJpYnV0ZShhdHRyTmFtZSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIGlmIChwcm9wTmFtZSA9PT0gXCJzdHlsZVwiKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgZm9yICh2YXIgaSBpbiBwcmV2aW91c1ZhbHVlKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG5vZGUuc3R5bGVbaV0gPSBcIlwiO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAodHlwZW9mIHByZXZpb3VzVmFsdWUgPT09IFwic3RyaW5nXCIpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBub2RlW3Byb3BOYW1lXSA9IFwiXCI7XG4gICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIG5vZGVbcHJvcE5hbWVdID0gbnVsbDtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIGlmIChwcmV2aW91c1ZhbHVlLnVuaG9vaykge1xuICAgICAgICAgICAgICAgICAgICAgICAgcHJldmlvdXNWYWx1ZS51bmhvb2sobm9kZSwgcHJvcE5hbWUsIHByb3BWYWx1ZSk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIHBhdGNoT2JqZWN0KG5vZGUsIHByb3BzLCBwcmV2aW91cywgcHJvcE5hbWUsIHByb3BWYWx1ZSkge1xuICAgICAgICAgICAgICAgIHZhciBwcmV2aW91c1ZhbHVlID0gcHJldmlvdXMgPyBwcmV2aW91c1twcm9wTmFtZV0gOiB1bmRlZmluZWQ7XG5cbiAgICAgICAgICAgICAgICAvLyBTZXQgYXR0cmlidXRlc1xuICAgICAgICAgICAgICAgIGlmIChwcm9wTmFtZSA9PT0gXCJhdHRyaWJ1dGVzXCIpIHtcbiAgICAgICAgICAgICAgICAgICAgZm9yICh2YXIgYXR0ck5hbWUgaW4gcHJvcFZhbHVlKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICB2YXIgYXR0clZhbHVlID0gcHJvcFZhbHVlW2F0dHJOYW1lXTtcblxuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGF0dHJWYWx1ZSA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgbm9kZS5yZW1vdmVBdHRyaWJ1dGUoYXR0ck5hbWUpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBub2RlLnNldEF0dHJpYnV0ZShhdHRyTmFtZSwgYXR0clZhbHVlKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICBpZiAocHJldmlvdXNWYWx1ZSAmJiBpc09iamVjdChwcmV2aW91c1ZhbHVlKSAmJiBnZXRQcm90b3R5cGUocHJldmlvdXNWYWx1ZSkgIT09IGdldFByb3RvdHlwZShwcm9wVmFsdWUpKSB7XG4gICAgICAgICAgICAgICAgICAgIG5vZGVbcHJvcE5hbWVdID0gcHJvcFZhbHVlO1xuICAgICAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgaWYgKCFpc09iamVjdChub2RlW3Byb3BOYW1lXSkpIHtcbiAgICAgICAgICAgICAgICAgICAgbm9kZVtwcm9wTmFtZV0gPSB7fTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICB2YXIgcmVwbGFjZXIgPSBwcm9wTmFtZSA9PT0gXCJzdHlsZVwiID8gXCJcIiA6IHVuZGVmaW5lZDtcblxuICAgICAgICAgICAgICAgIGZvciAodmFyIGsgaW4gcHJvcFZhbHVlKSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciB2YWx1ZSA9IHByb3BWYWx1ZVtrXTtcbiAgICAgICAgICAgICAgICAgICAgbm9kZVtwcm9wTmFtZV1ba10gPSB2YWx1ZSA9PT0gdW5kZWZpbmVkID8gcmVwbGFjZXIgOiB2YWx1ZTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIGdldFByb3RvdHlwZSh2YWx1ZSkge1xuICAgICAgICAgICAgICAgIGlmIChPYmplY3QuZ2V0UHJvdG90eXBlT2YpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIE9iamVjdC5nZXRQcm90b3R5cGVPZih2YWx1ZSk7XG4gICAgICAgICAgICAgICAgfSBlbHNlIGlmICh2YWx1ZS5fX3Byb3RvX18pIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHZhbHVlLl9fcHJvdG9fXztcbiAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKHZhbHVlLmNvbnN0cnVjdG9yKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiB2YWx1ZS5jb25zdHJ1Y3Rvci5wcm90b3R5cGU7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9LCB7IFwiLi4vdm5vZGUvaXMtdmhvb2suanNcIjogMjYsIFwiaXMtb2JqZWN0XCI6IDExIH1dLCAxNTogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHtcbiAgICAgICAgICAgIHZhciBkb2N1bWVudCA9IHJlcXVpcmUoXCJnbG9iYWwvZG9jdW1lbnRcIik7XG5cbiAgICAgICAgICAgIHZhciBhcHBseVByb3BlcnRpZXMgPSByZXF1aXJlKFwiLi9hcHBseS1wcm9wZXJ0aWVzXCIpO1xuXG4gICAgICAgICAgICB2YXIgaXNWTm9kZSA9IHJlcXVpcmUoXCIuLi92bm9kZS9pcy12bm9kZS5qc1wiKTtcbiAgICAgICAgICAgIHZhciBpc1ZUZXh0ID0gcmVxdWlyZShcIi4uL3Zub2RlL2lzLXZ0ZXh0LmpzXCIpO1xuICAgICAgICAgICAgdmFyIGlzV2lkZ2V0ID0gcmVxdWlyZShcIi4uL3Zub2RlL2lzLXdpZGdldC5qc1wiKTtcbiAgICAgICAgICAgIHZhciBoYW5kbGVUaHVuayA9IHJlcXVpcmUoXCIuLi92bm9kZS9oYW5kbGUtdGh1bmsuanNcIik7XG5cbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gY3JlYXRlRWxlbWVudDtcblxuICAgICAgICAgICAgZnVuY3Rpb24gY3JlYXRlRWxlbWVudCh2bm9kZSwgb3B0cykge1xuICAgICAgICAgICAgICAgIHZhciBkb2MgPSBvcHRzID8gb3B0cy5kb2N1bWVudCB8fCBkb2N1bWVudCA6IGRvY3VtZW50O1xuICAgICAgICAgICAgICAgIHZhciB3YXJuID0gb3B0cyA/IG9wdHMud2FybiA6IG51bGw7XG5cbiAgICAgICAgICAgICAgICB2bm9kZSA9IGhhbmRsZVRodW5rKHZub2RlKS5hO1xuXG4gICAgICAgICAgICAgICAgaWYgKGlzV2lkZ2V0KHZub2RlKSkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gdm5vZGUuaW5pdCgpO1xuICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoaXNWVGV4dCh2bm9kZSkpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGRvYy5jcmVhdGVUZXh0Tm9kZSh2bm9kZS50ZXh0KTtcbiAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKCFpc1ZOb2RlKHZub2RlKSkge1xuICAgICAgICAgICAgICAgICAgICBpZiAod2Fybikge1xuICAgICAgICAgICAgICAgICAgICAgICAgd2FybihcIkl0ZW0gaXMgbm90IGEgdmFsaWQgdmlydHVhbCBkb20gbm9kZVwiLCB2bm9kZSk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIG51bGw7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgdmFyIG5vZGUgPSB2bm9kZS5uYW1lc3BhY2UgPT09IG51bGwgPyBkb2MuY3JlYXRlRWxlbWVudCh2bm9kZS50YWdOYW1lKSA6IGRvYy5jcmVhdGVFbGVtZW50TlModm5vZGUubmFtZXNwYWNlLCB2bm9kZS50YWdOYW1lKTtcblxuICAgICAgICAgICAgICAgIHZhciBwcm9wcyA9IHZub2RlLnByb3BlcnRpZXM7XG4gICAgICAgICAgICAgICAgYXBwbHlQcm9wZXJ0aWVzKG5vZGUsIHByb3BzKTtcblxuICAgICAgICAgICAgICAgIHZhciBjaGlsZHJlbiA9IHZub2RlLmNoaWxkcmVuO1xuXG4gICAgICAgICAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCBjaGlsZHJlbi5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgICAgICAgICB2YXIgY2hpbGROb2RlID0gY3JlYXRlRWxlbWVudChjaGlsZHJlbltpXSwgb3B0cyk7XG4gICAgICAgICAgICAgICAgICAgIGlmIChjaGlsZE5vZGUpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIG5vZGUuYXBwZW5kQ2hpbGQoY2hpbGROb2RlKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHJldHVybiBub2RlO1xuICAgICAgICAgICAgfVxuICAgICAgICB9LCB7IFwiLi4vdm5vZGUvaGFuZGxlLXRodW5rLmpzXCI6IDI0LCBcIi4uL3Zub2RlL2lzLXZub2RlLmpzXCI6IDI3LCBcIi4uL3Zub2RlL2lzLXZ0ZXh0LmpzXCI6IDI4LCBcIi4uL3Zub2RlL2lzLXdpZGdldC5qc1wiOiAyOSwgXCIuL2FwcGx5LXByb3BlcnRpZXNcIjogMTQsIFwiZ2xvYmFsL2RvY3VtZW50XCI6IDEwIH1dLCAxNjogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHtcbiAgICAgICAgICAgIC8vIE1hcHMgYSB2aXJ0dWFsIERPTSB0cmVlIG9udG8gYSByZWFsIERPTSB0cmVlIGluIGFuIGVmZmljaWVudCBtYW5uZXIuXG4gICAgICAgICAgICAvLyBXZSBkb24ndCB3YW50IHRvIHJlYWQgYWxsIG9mIHRoZSBET00gbm9kZXMgaW4gdGhlIHRyZWUgc28gd2UgdXNlXG4gICAgICAgICAgICAvLyB0aGUgaW4tb3JkZXIgdHJlZSBpbmRleGluZyB0byBlbGltaW5hdGUgcmVjdXJzaW9uIGRvd24gY2VydGFpbiBicmFuY2hlcy5cbiAgICAgICAgICAgIC8vIFdlIG9ubHkgcmVjdXJzZSBpbnRvIGEgRE9NIG5vZGUgaWYgd2Uga25vdyB0aGF0IGl0IGNvbnRhaW5zIGEgY2hpbGQgb2ZcbiAgICAgICAgICAgIC8vIGludGVyZXN0LlxuXG4gICAgICAgICAgICB2YXIgbm9DaGlsZCA9IHt9O1xuXG4gICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IGRvbUluZGV4O1xuXG4gICAgICAgICAgICBmdW5jdGlvbiBkb21JbmRleChyb290Tm9kZSwgdHJlZSwgaW5kaWNlcywgbm9kZXMpIHtcbiAgICAgICAgICAgICAgICBpZiAoIWluZGljZXMgfHwgaW5kaWNlcy5sZW5ndGggPT09IDApIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHt9O1xuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIGluZGljZXMuc29ydChhc2NlbmRpbmcpO1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gcmVjdXJzZShyb290Tm9kZSwgdHJlZSwgaW5kaWNlcywgbm9kZXMsIDApO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZnVuY3Rpb24gcmVjdXJzZShyb290Tm9kZSwgdHJlZSwgaW5kaWNlcywgbm9kZXMsIHJvb3RJbmRleCkge1xuICAgICAgICAgICAgICAgIG5vZGVzID0gbm9kZXMgfHwge307XG5cbiAgICAgICAgICAgICAgICBpZiAocm9vdE5vZGUpIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKGluZGV4SW5SYW5nZShpbmRpY2VzLCByb290SW5kZXgsIHJvb3RJbmRleCkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIG5vZGVzW3Jvb3RJbmRleF0gPSByb290Tm9kZTtcbiAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgIHZhciB2Q2hpbGRyZW4gPSB0cmVlLmNoaWxkcmVuO1xuXG4gICAgICAgICAgICAgICAgICAgIGlmICh2Q2hpbGRyZW4pIHtcblxuICAgICAgICAgICAgICAgICAgICAgICAgdmFyIGNoaWxkTm9kZXMgPSByb290Tm9kZS5jaGlsZE5vZGVzO1xuXG4gICAgICAgICAgICAgICAgICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IHRyZWUuY2hpbGRyZW4ubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICByb290SW5kZXggKz0gMTtcblxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZhciB2Q2hpbGQgPSB2Q2hpbGRyZW5baV0gfHwgbm9DaGlsZDtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB2YXIgbmV4dEluZGV4ID0gcm9vdEluZGV4ICsgKHZDaGlsZC5jb3VudCB8fCAwKTtcblxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIHNraXAgcmVjdXJzaW9uIGRvd24gdGhlIHRyZWUgaWYgdGhlcmUgYXJlIG5vIG5vZGVzIGRvd24gaGVyZVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChpbmRleEluUmFuZ2UoaW5kaWNlcywgcm9vdEluZGV4LCBuZXh0SW5kZXgpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlY3Vyc2UoY2hpbGROb2Rlc1tpXSwgdkNoaWxkLCBpbmRpY2VzLCBub2Rlcywgcm9vdEluZGV4KTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICByb290SW5kZXggPSBuZXh0SW5kZXg7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICByZXR1cm4gbm9kZXM7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIC8vIEJpbmFyeSBzZWFyY2ggZm9yIGFuIGluZGV4IGluIHRoZSBpbnRlcnZhbCBbbGVmdCwgcmlnaHRdXG4gICAgICAgICAgICBmdW5jdGlvbiBpbmRleEluUmFuZ2UoaW5kaWNlcywgbGVmdCwgcmlnaHQpIHtcbiAgICAgICAgICAgICAgICBpZiAoaW5kaWNlcy5sZW5ndGggPT09IDApIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHZhciBtaW5JbmRleCA9IDA7XG4gICAgICAgICAgICAgICAgdmFyIG1heEluZGV4ID0gaW5kaWNlcy5sZW5ndGggLSAxO1xuICAgICAgICAgICAgICAgIHZhciBjdXJyZW50SW5kZXg7XG4gICAgICAgICAgICAgICAgdmFyIGN1cnJlbnRJdGVtO1xuXG4gICAgICAgICAgICAgICAgd2hpbGUgKG1pbkluZGV4IDw9IG1heEluZGV4KSB7XG4gICAgICAgICAgICAgICAgICAgIGN1cnJlbnRJbmRleCA9IChtYXhJbmRleCArIG1pbkluZGV4KSAvIDIgPj4gMDtcbiAgICAgICAgICAgICAgICAgICAgY3VycmVudEl0ZW0gPSBpbmRpY2VzW2N1cnJlbnRJbmRleF07XG5cbiAgICAgICAgICAgICAgICAgICAgaWYgKG1pbkluZGV4ID09PSBtYXhJbmRleCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGN1cnJlbnRJdGVtID49IGxlZnQgJiYgY3VycmVudEl0ZW0gPD0gcmlnaHQ7XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoY3VycmVudEl0ZW0gPCBsZWZ0KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBtaW5JbmRleCA9IGN1cnJlbnRJbmRleCArIDE7XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoY3VycmVudEl0ZW0gPiByaWdodCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgbWF4SW5kZXggPSBjdXJyZW50SW5kZXggLSAxO1xuICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIGFzY2VuZGluZyhhLCBiKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGEgPiBiID8gMSA6IC0xO1xuICAgICAgICAgICAgfVxuICAgICAgICB9LCB7fV0sIDE3OiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge1xuICAgICAgICAgICAgdmFyIGFwcGx5UHJvcGVydGllcyA9IHJlcXVpcmUoXCIuL2FwcGx5LXByb3BlcnRpZXNcIik7XG5cbiAgICAgICAgICAgIHZhciBpc1dpZGdldCA9IHJlcXVpcmUoXCIuLi92bm9kZS9pcy13aWRnZXQuanNcIik7XG4gICAgICAgICAgICB2YXIgVlBhdGNoID0gcmVxdWlyZShcIi4uL3Zub2RlL3ZwYXRjaC5qc1wiKTtcblxuICAgICAgICAgICAgdmFyIHVwZGF0ZVdpZGdldCA9IHJlcXVpcmUoXCIuL3VwZGF0ZS13aWRnZXRcIik7XG5cbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gYXBwbHlQYXRjaDtcblxuICAgICAgICAgICAgZnVuY3Rpb24gYXBwbHlQYXRjaCh2cGF0Y2gsIGRvbU5vZGUsIHJlbmRlck9wdGlvbnMpIHtcbiAgICAgICAgICAgICAgICB2YXIgdHlwZSA9IHZwYXRjaC50eXBlO1xuICAgICAgICAgICAgICAgIHZhciB2Tm9kZSA9IHZwYXRjaC52Tm9kZTtcbiAgICAgICAgICAgICAgICB2YXIgcGF0Y2ggPSB2cGF0Y2gucGF0Y2g7XG5cbiAgICAgICAgICAgICAgICBzd2l0Y2ggKHR5cGUpIHtcbiAgICAgICAgICAgICAgICAgICAgY2FzZSBWUGF0Y2guUkVNT1ZFOlxuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHJlbW92ZU5vZGUoZG9tTm9kZSwgdk5vZGUpO1xuICAgICAgICAgICAgICAgICAgICBjYXNlIFZQYXRjaC5JTlNFUlQ6XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gaW5zZXJ0Tm9kZShkb21Ob2RlLCBwYXRjaCwgcmVuZGVyT3B0aW9ucyk7XG4gICAgICAgICAgICAgICAgICAgIGNhc2UgVlBhdGNoLlZURVhUOlxuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHN0cmluZ1BhdGNoKGRvbU5vZGUsIHZOb2RlLCBwYXRjaCwgcmVuZGVyT3B0aW9ucyk7XG4gICAgICAgICAgICAgICAgICAgIGNhc2UgVlBhdGNoLldJREdFVDpcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiB3aWRnZXRQYXRjaChkb21Ob2RlLCB2Tm9kZSwgcGF0Y2gsIHJlbmRlck9wdGlvbnMpO1xuICAgICAgICAgICAgICAgICAgICBjYXNlIFZQYXRjaC5WTk9ERTpcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiB2Tm9kZVBhdGNoKGRvbU5vZGUsIHZOb2RlLCBwYXRjaCwgcmVuZGVyT3B0aW9ucyk7XG4gICAgICAgICAgICAgICAgICAgIGNhc2UgVlBhdGNoLk9SREVSOlxuICAgICAgICAgICAgICAgICAgICAgICAgcmVvcmRlckNoaWxkcmVuKGRvbU5vZGUsIHBhdGNoKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBkb21Ob2RlO1xuICAgICAgICAgICAgICAgICAgICBjYXNlIFZQYXRjaC5QUk9QUzpcbiAgICAgICAgICAgICAgICAgICAgICAgIGFwcGx5UHJvcGVydGllcyhkb21Ob2RlLCBwYXRjaCwgdk5vZGUucHJvcGVydGllcyk7XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gZG9tTm9kZTtcbiAgICAgICAgICAgICAgICAgICAgY2FzZSBWUGF0Y2guVEhVTks6XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gcmVwbGFjZVJvb3QoZG9tTm9kZSwgcmVuZGVyT3B0aW9ucy5wYXRjaChkb21Ob2RlLCBwYXRjaCwgcmVuZGVyT3B0aW9ucykpO1xuICAgICAgICAgICAgICAgICAgICBkZWZhdWx0OlxuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGRvbU5vZGU7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBmdW5jdGlvbiByZW1vdmVOb2RlKGRvbU5vZGUsIHZOb2RlKSB7XG4gICAgICAgICAgICAgICAgdmFyIHBhcmVudE5vZGUgPSBkb21Ob2RlLnBhcmVudE5vZGU7XG5cbiAgICAgICAgICAgICAgICBpZiAocGFyZW50Tm9kZSkge1xuICAgICAgICAgICAgICAgICAgICBwYXJlbnROb2RlLnJlbW92ZUNoaWxkKGRvbU5vZGUpO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIGRlc3Ryb3lXaWRnZXQoZG9tTm9kZSwgdk5vZGUpO1xuXG4gICAgICAgICAgICAgICAgcmV0dXJuIG51bGw7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIGluc2VydE5vZGUocGFyZW50Tm9kZSwgdk5vZGUsIHJlbmRlck9wdGlvbnMpIHtcbiAgICAgICAgICAgICAgICB2YXIgbmV3Tm9kZSA9IHJlbmRlck9wdGlvbnMucmVuZGVyKHZOb2RlLCByZW5kZXJPcHRpb25zKTtcblxuICAgICAgICAgICAgICAgIGlmIChwYXJlbnROb2RlKSB7XG4gICAgICAgICAgICAgICAgICAgIHBhcmVudE5vZGUuYXBwZW5kQ2hpbGQobmV3Tm9kZSk7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgcmV0dXJuIHBhcmVudE5vZGU7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIHN0cmluZ1BhdGNoKGRvbU5vZGUsIGxlZnRWTm9kZSwgdlRleHQsIHJlbmRlck9wdGlvbnMpIHtcbiAgICAgICAgICAgICAgICB2YXIgbmV3Tm9kZTtcblxuICAgICAgICAgICAgICAgIGlmIChkb21Ob2RlLm5vZGVUeXBlID09PSAzKSB7XG4gICAgICAgICAgICAgICAgICAgIGRvbU5vZGUucmVwbGFjZURhdGEoMCwgZG9tTm9kZS5sZW5ndGgsIHZUZXh0LnRleHQpO1xuICAgICAgICAgICAgICAgICAgICBuZXdOb2RlID0gZG9tTm9kZTtcbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICB2YXIgcGFyZW50Tm9kZSA9IGRvbU5vZGUucGFyZW50Tm9kZTtcbiAgICAgICAgICAgICAgICAgICAgbmV3Tm9kZSA9IHJlbmRlck9wdGlvbnMucmVuZGVyKHZUZXh0LCByZW5kZXJPcHRpb25zKTtcblxuICAgICAgICAgICAgICAgICAgICBpZiAocGFyZW50Tm9kZSAmJiBuZXdOb2RlICE9PSBkb21Ob2RlKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBwYXJlbnROb2RlLnJlcGxhY2VDaGlsZChuZXdOb2RlLCBkb21Ob2RlKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHJldHVybiBuZXdOb2RlO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBmdW5jdGlvbiB3aWRnZXRQYXRjaChkb21Ob2RlLCBsZWZ0Vk5vZGUsIHdpZGdldCwgcmVuZGVyT3B0aW9ucykge1xuICAgICAgICAgICAgICAgIHZhciB1cGRhdGluZyA9IHVwZGF0ZVdpZGdldChsZWZ0Vk5vZGUsIHdpZGdldCk7XG4gICAgICAgICAgICAgICAgdmFyIG5ld05vZGU7XG5cbiAgICAgICAgICAgICAgICBpZiAodXBkYXRpbmcpIHtcbiAgICAgICAgICAgICAgICAgICAgbmV3Tm9kZSA9IHdpZGdldC51cGRhdGUobGVmdFZOb2RlLCBkb21Ob2RlKSB8fCBkb21Ob2RlO1xuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIG5ld05vZGUgPSByZW5kZXJPcHRpb25zLnJlbmRlcih3aWRnZXQsIHJlbmRlck9wdGlvbnMpO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHZhciBwYXJlbnROb2RlID0gZG9tTm9kZS5wYXJlbnROb2RlO1xuXG4gICAgICAgICAgICAgICAgaWYgKHBhcmVudE5vZGUgJiYgbmV3Tm9kZSAhPT0gZG9tTm9kZSkge1xuICAgICAgICAgICAgICAgICAgICBwYXJlbnROb2RlLnJlcGxhY2VDaGlsZChuZXdOb2RlLCBkb21Ob2RlKTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICBpZiAoIXVwZGF0aW5nKSB7XG4gICAgICAgICAgICAgICAgICAgIGRlc3Ryb3lXaWRnZXQoZG9tTm9kZSwgbGVmdFZOb2RlKTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICByZXR1cm4gbmV3Tm9kZTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZnVuY3Rpb24gdk5vZGVQYXRjaChkb21Ob2RlLCBsZWZ0Vk5vZGUsIHZOb2RlLCByZW5kZXJPcHRpb25zKSB7XG4gICAgICAgICAgICAgICAgdmFyIHBhcmVudE5vZGUgPSBkb21Ob2RlLnBhcmVudE5vZGU7XG4gICAgICAgICAgICAgICAgdmFyIG5ld05vZGUgPSByZW5kZXJPcHRpb25zLnJlbmRlcih2Tm9kZSwgcmVuZGVyT3B0aW9ucyk7XG5cbiAgICAgICAgICAgICAgICBpZiAocGFyZW50Tm9kZSAmJiBuZXdOb2RlICE9PSBkb21Ob2RlKSB7XG4gICAgICAgICAgICAgICAgICAgIHBhcmVudE5vZGUucmVwbGFjZUNoaWxkKG5ld05vZGUsIGRvbU5vZGUpO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHJldHVybiBuZXdOb2RlO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBmdW5jdGlvbiBkZXN0cm95V2lkZ2V0KGRvbU5vZGUsIHcpIHtcbiAgICAgICAgICAgICAgICBpZiAodHlwZW9mIHcuZGVzdHJveSA9PT0gXCJmdW5jdGlvblwiICYmIGlzV2lkZ2V0KHcpKSB7XG4gICAgICAgICAgICAgICAgICAgIHcuZGVzdHJveShkb21Ob2RlKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIHJlb3JkZXJDaGlsZHJlbihkb21Ob2RlLCBtb3Zlcykge1xuICAgICAgICAgICAgICAgIHZhciBjaGlsZE5vZGVzID0gZG9tTm9kZS5jaGlsZE5vZGVzO1xuICAgICAgICAgICAgICAgIHZhciBrZXlNYXAgPSB7fTtcbiAgICAgICAgICAgICAgICB2YXIgbm9kZTtcbiAgICAgICAgICAgICAgICB2YXIgcmVtb3ZlO1xuICAgICAgICAgICAgICAgIHZhciBpbnNlcnQ7XG5cbiAgICAgICAgICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IG1vdmVzLnJlbW92ZXMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgICAgICAgICAgcmVtb3ZlID0gbW92ZXMucmVtb3Zlc1tpXTtcbiAgICAgICAgICAgICAgICAgICAgbm9kZSA9IGNoaWxkTm9kZXNbcmVtb3ZlLmZyb21dO1xuICAgICAgICAgICAgICAgICAgICBpZiAocmVtb3ZlLmtleSkge1xuICAgICAgICAgICAgICAgICAgICAgICAga2V5TWFwW3JlbW92ZS5rZXldID0gbm9kZTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICBkb21Ob2RlLnJlbW92ZUNoaWxkKG5vZGUpO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHZhciBsZW5ndGggPSBjaGlsZE5vZGVzLmxlbmd0aDtcbiAgICAgICAgICAgICAgICBmb3IgKHZhciBqID0gMDsgaiA8IG1vdmVzLmluc2VydHMubGVuZ3RoOyBqKyspIHtcbiAgICAgICAgICAgICAgICAgICAgaW5zZXJ0ID0gbW92ZXMuaW5zZXJ0c1tqXTtcbiAgICAgICAgICAgICAgICAgICAgbm9kZSA9IGtleU1hcFtpbnNlcnQua2V5XTtcbiAgICAgICAgICAgICAgICAgICAgLy8gdGhpcyBpcyB0aGUgd2VpcmRlc3QgYnVnIGkndmUgZXZlciBzZWVuIGluIHdlYmtpdFxuICAgICAgICAgICAgICAgICAgICBkb21Ob2RlLmluc2VydEJlZm9yZShub2RlLCBpbnNlcnQudG8gPj0gbGVuZ3RoKysgPyBudWxsIDogY2hpbGROb2Rlc1tpbnNlcnQudG9dKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIHJlcGxhY2VSb290KG9sZFJvb3QsIG5ld1Jvb3QpIHtcbiAgICAgICAgICAgICAgICBpZiAob2xkUm9vdCAmJiBuZXdSb290ICYmIG9sZFJvb3QgIT09IG5ld1Jvb3QgJiYgb2xkUm9vdC5wYXJlbnROb2RlKSB7XG4gICAgICAgICAgICAgICAgICAgIG9sZFJvb3QucGFyZW50Tm9kZS5yZXBsYWNlQ2hpbGQobmV3Um9vdCwgb2xkUm9vdCk7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgcmV0dXJuIG5ld1Jvb3Q7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0sIHsgXCIuLi92bm9kZS9pcy13aWRnZXQuanNcIjogMjksIFwiLi4vdm5vZGUvdnBhdGNoLmpzXCI6IDMyLCBcIi4vYXBwbHktcHJvcGVydGllc1wiOiAxNCwgXCIuL3VwZGF0ZS13aWRnZXRcIjogMTkgfV0sIDE4OiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge1xuICAgICAgICAgICAgdmFyIGRvY3VtZW50ID0gcmVxdWlyZShcImdsb2JhbC9kb2N1bWVudFwiKTtcbiAgICAgICAgICAgIHZhciBpc0FycmF5ID0gcmVxdWlyZShcIngtaXMtYXJyYXlcIik7XG5cbiAgICAgICAgICAgIHZhciByZW5kZXIgPSByZXF1aXJlKFwiLi9jcmVhdGUtZWxlbWVudFwiKTtcbiAgICAgICAgICAgIHZhciBkb21JbmRleCA9IHJlcXVpcmUoXCIuL2RvbS1pbmRleFwiKTtcbiAgICAgICAgICAgIHZhciBwYXRjaE9wID0gcmVxdWlyZShcIi4vcGF0Y2gtb3BcIik7XG4gICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IHBhdGNoO1xuXG4gICAgICAgICAgICBmdW5jdGlvbiBwYXRjaChyb290Tm9kZSwgcGF0Y2hlcywgcmVuZGVyT3B0aW9ucykge1xuICAgICAgICAgICAgICAgIHJlbmRlck9wdGlvbnMgPSByZW5kZXJPcHRpb25zIHx8IHt9O1xuICAgICAgICAgICAgICAgIHJlbmRlck9wdGlvbnMucGF0Y2ggPSByZW5kZXJPcHRpb25zLnBhdGNoICYmIHJlbmRlck9wdGlvbnMucGF0Y2ggIT09IHBhdGNoID8gcmVuZGVyT3B0aW9ucy5wYXRjaCA6IHBhdGNoUmVjdXJzaXZlO1xuICAgICAgICAgICAgICAgIHJlbmRlck9wdGlvbnMucmVuZGVyID0gcmVuZGVyT3B0aW9ucy5yZW5kZXIgfHwgcmVuZGVyO1xuXG4gICAgICAgICAgICAgICAgcmV0dXJuIHJlbmRlck9wdGlvbnMucGF0Y2gocm9vdE5vZGUsIHBhdGNoZXMsIHJlbmRlck9wdGlvbnMpO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBmdW5jdGlvbiBwYXRjaFJlY3Vyc2l2ZShyb290Tm9kZSwgcGF0Y2hlcywgcmVuZGVyT3B0aW9ucykge1xuICAgICAgICAgICAgICAgIHZhciBpbmRpY2VzID0gcGF0Y2hJbmRpY2VzKHBhdGNoZXMpO1xuXG4gICAgICAgICAgICAgICAgaWYgKGluZGljZXMubGVuZ3RoID09PSAwKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiByb290Tm9kZTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICB2YXIgaW5kZXggPSBkb21JbmRleChyb290Tm9kZSwgcGF0Y2hlcy5hLCBpbmRpY2VzKTtcbiAgICAgICAgICAgICAgICB2YXIgb3duZXJEb2N1bWVudCA9IHJvb3ROb2RlLm93bmVyRG9jdW1lbnQ7XG5cbiAgICAgICAgICAgICAgICBpZiAoIXJlbmRlck9wdGlvbnMuZG9jdW1lbnQgJiYgb3duZXJEb2N1bWVudCAhPT0gZG9jdW1lbnQpIHtcbiAgICAgICAgICAgICAgICAgICAgcmVuZGVyT3B0aW9ucy5kb2N1bWVudCA9IG93bmVyRG9jdW1lbnQ7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCBpbmRpY2VzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciBub2RlSW5kZXggPSBpbmRpY2VzW2ldO1xuICAgICAgICAgICAgICAgICAgICByb290Tm9kZSA9IGFwcGx5UGF0Y2gocm9vdE5vZGUsIGluZGV4W25vZGVJbmRleF0sIHBhdGNoZXNbbm9kZUluZGV4XSwgcmVuZGVyT3B0aW9ucyk7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgcmV0dXJuIHJvb3ROb2RlO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBmdW5jdGlvbiBhcHBseVBhdGNoKHJvb3ROb2RlLCBkb21Ob2RlLCBwYXRjaExpc3QsIHJlbmRlck9wdGlvbnMpIHtcbiAgICAgICAgICAgICAgICBpZiAoIWRvbU5vZGUpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHJvb3ROb2RlO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHZhciBuZXdOb2RlO1xuXG4gICAgICAgICAgICAgICAgaWYgKGlzQXJyYXkocGF0Y2hMaXN0KSkge1xuICAgICAgICAgICAgICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IHBhdGNoTGlzdC5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgICAgICAgICAgICAgbmV3Tm9kZSA9IHBhdGNoT3AocGF0Y2hMaXN0W2ldLCBkb21Ob2RlLCByZW5kZXJPcHRpb25zKTtcblxuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGRvbU5vZGUgPT09IHJvb3ROb2RlKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcm9vdE5vZGUgPSBuZXdOb2RlO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgbmV3Tm9kZSA9IHBhdGNoT3AocGF0Y2hMaXN0LCBkb21Ob2RlLCByZW5kZXJPcHRpb25zKTtcblxuICAgICAgICAgICAgICAgICAgICBpZiAoZG9tTm9kZSA9PT0gcm9vdE5vZGUpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJvb3ROb2RlID0gbmV3Tm9kZTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHJldHVybiByb290Tm9kZTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZnVuY3Rpb24gcGF0Y2hJbmRpY2VzKHBhdGNoZXMpIHtcbiAgICAgICAgICAgICAgICB2YXIgaW5kaWNlcyA9IFtdO1xuXG4gICAgICAgICAgICAgICAgZm9yICh2YXIga2V5IGluIHBhdGNoZXMpIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKGtleSAhPT0gXCJhXCIpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGluZGljZXMucHVzaChOdW1iZXIoa2V5KSk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICByZXR1cm4gaW5kaWNlcztcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSwgeyBcIi4vY3JlYXRlLWVsZW1lbnRcIjogMTUsIFwiLi9kb20taW5kZXhcIjogMTYsIFwiLi9wYXRjaC1vcFwiOiAxNywgXCJnbG9iYWwvZG9jdW1lbnRcIjogMTAsIFwieC1pcy1hcnJheVwiOiAxMiB9XSwgMTk6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICB2YXIgaXNXaWRnZXQgPSByZXF1aXJlKFwiLi4vdm5vZGUvaXMtd2lkZ2V0LmpzXCIpO1xuXG4gICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IHVwZGF0ZVdpZGdldDtcblxuICAgICAgICAgICAgZnVuY3Rpb24gdXBkYXRlV2lkZ2V0KGEsIGIpIHtcbiAgICAgICAgICAgICAgICBpZiAoaXNXaWRnZXQoYSkgJiYgaXNXaWRnZXQoYikpIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKFwibmFtZVwiIGluIGEgJiYgXCJuYW1lXCIgaW4gYikge1xuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGEuaWQgPT09IGIuaWQ7XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gYS5pbml0ID09PSBiLmluaXQ7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0sIHsgXCIuLi92bm9kZS9pcy13aWRnZXQuanNcIjogMjkgfV0sIDIwOiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge1xuICAgICAgICAgICAgXCJ1c2Ugc3RyaWN0XCI7XG5cbiAgICAgICAgICAgIHZhciBFdlN0b3JlID0gcmVxdWlyZShcImV2LXN0b3JlXCIpO1xuXG4gICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IEV2SG9vaztcblxuICAgICAgICAgICAgZnVuY3Rpb24gRXZIb29rKHZhbHVlKSB7XG4gICAgICAgICAgICAgICAgaWYgKCEodGhpcyBpbnN0YW5jZW9mIEV2SG9vaykpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIG5ldyBFdkhvb2sodmFsdWUpO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHRoaXMudmFsdWUgPSB2YWx1ZTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgRXZIb29rLnByb3RvdHlwZS5ob29rID0gZnVuY3Rpb24gKG5vZGUsIHByb3BlcnR5TmFtZSkge1xuICAgICAgICAgICAgICAgIHZhciBlcyA9IEV2U3RvcmUobm9kZSk7XG4gICAgICAgICAgICAgICAgdmFyIHByb3BOYW1lID0gcHJvcGVydHlOYW1lLnN1YnN0cigzKTtcblxuICAgICAgICAgICAgICAgIGVzW3Byb3BOYW1lXSA9IHRoaXMudmFsdWU7XG4gICAgICAgICAgICB9O1xuXG4gICAgICAgICAgICBFdkhvb2sucHJvdG90eXBlLnVuaG9vayA9IGZ1bmN0aW9uIChub2RlLCBwcm9wZXJ0eU5hbWUpIHtcbiAgICAgICAgICAgICAgICB2YXIgZXMgPSBFdlN0b3JlKG5vZGUpO1xuICAgICAgICAgICAgICAgIHZhciBwcm9wTmFtZSA9IHByb3BlcnR5TmFtZS5zdWJzdHIoMyk7XG5cbiAgICAgICAgICAgICAgICBlc1twcm9wTmFtZV0gPSB1bmRlZmluZWQ7XG4gICAgICAgICAgICB9O1xuICAgICAgICB9LCB7IFwiZXYtc3RvcmVcIjogNyB9XSwgMjE6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICBcInVzZSBzdHJpY3RcIjtcblxuICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBTb2Z0U2V0SG9vaztcblxuICAgICAgICAgICAgZnVuY3Rpb24gU29mdFNldEhvb2sodmFsdWUpIHtcbiAgICAgICAgICAgICAgICBpZiAoISh0aGlzIGluc3RhbmNlb2YgU29mdFNldEhvb2spKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBuZXcgU29mdFNldEhvb2sodmFsdWUpO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHRoaXMudmFsdWUgPSB2YWx1ZTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgU29mdFNldEhvb2sucHJvdG90eXBlLmhvb2sgPSBmdW5jdGlvbiAobm9kZSwgcHJvcGVydHlOYW1lKSB7XG4gICAgICAgICAgICAgICAgaWYgKG5vZGVbcHJvcGVydHlOYW1lXSAhPT0gdGhpcy52YWx1ZSkge1xuICAgICAgICAgICAgICAgICAgICBub2RlW3Byb3BlcnR5TmFtZV0gPSB0aGlzLnZhbHVlO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH07XG4gICAgICAgIH0sIHt9XSwgMjI6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICBcInVzZSBzdHJpY3RcIjtcblxuICAgICAgICAgICAgdmFyIGlzQXJyYXkgPSByZXF1aXJlKFwieC1pcy1hcnJheVwiKTtcblxuICAgICAgICAgICAgdmFyIFZOb2RlID0gcmVxdWlyZShcIi4uL3Zub2RlL3Zub2RlLmpzXCIpO1xuICAgICAgICAgICAgdmFyIFZUZXh0ID0gcmVxdWlyZShcIi4uL3Zub2RlL3Z0ZXh0LmpzXCIpO1xuICAgICAgICAgICAgdmFyIGlzVk5vZGUgPSByZXF1aXJlKFwiLi4vdm5vZGUvaXMtdm5vZGVcIik7XG4gICAgICAgICAgICB2YXIgaXNWVGV4dCA9IHJlcXVpcmUoXCIuLi92bm9kZS9pcy12dGV4dFwiKTtcbiAgICAgICAgICAgIHZhciBpc1dpZGdldCA9IHJlcXVpcmUoXCIuLi92bm9kZS9pcy13aWRnZXRcIik7XG4gICAgICAgICAgICB2YXIgaXNIb29rID0gcmVxdWlyZShcIi4uL3Zub2RlL2lzLXZob29rXCIpO1xuICAgICAgICAgICAgdmFyIGlzVlRodW5rID0gcmVxdWlyZShcIi4uL3Zub2RlL2lzLXRodW5rXCIpO1xuXG4gICAgICAgICAgICB2YXIgcGFyc2VUYWcgPSByZXF1aXJlKFwiLi9wYXJzZS10YWcuanNcIik7XG4gICAgICAgICAgICB2YXIgc29mdFNldEhvb2sgPSByZXF1aXJlKFwiLi9ob29rcy9zb2Z0LXNldC1ob29rLmpzXCIpO1xuICAgICAgICAgICAgdmFyIGV2SG9vayA9IHJlcXVpcmUoXCIuL2hvb2tzL2V2LWhvb2suanNcIik7XG5cbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gaDtcblxuICAgICAgICAgICAgZnVuY3Rpb24gaCh0YWdOYW1lLCBwcm9wZXJ0aWVzLCBjaGlsZHJlbikge1xuICAgICAgICAgICAgICAgIHZhciBjaGlsZE5vZGVzID0gW107XG4gICAgICAgICAgICAgICAgdmFyIHRhZywgcHJvcHMsIGtleSwgbmFtZXNwYWNlO1xuXG4gICAgICAgICAgICAgICAgaWYgKCFjaGlsZHJlbiAmJiBpc0NoaWxkcmVuKHByb3BlcnRpZXMpKSB7XG4gICAgICAgICAgICAgICAgICAgIGNoaWxkcmVuID0gcHJvcGVydGllcztcbiAgICAgICAgICAgICAgICAgICAgcHJvcHMgPSB7fTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICBwcm9wcyA9IHByb3BzIHx8IHByb3BlcnRpZXMgfHwge307XG4gICAgICAgICAgICAgICAgdGFnID0gcGFyc2VUYWcodGFnTmFtZSwgcHJvcHMpO1xuXG4gICAgICAgICAgICAgICAgLy8gc3VwcG9ydCBrZXlzXG4gICAgICAgICAgICAgICAgaWYgKHByb3BzLmhhc093blByb3BlcnR5KFwia2V5XCIpKSB7XG4gICAgICAgICAgICAgICAgICAgIGtleSA9IHByb3BzLmtleTtcbiAgICAgICAgICAgICAgICAgICAgcHJvcHMua2V5ID0gdW5kZWZpbmVkO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIC8vIHN1cHBvcnQgbmFtZXNwYWNlXG4gICAgICAgICAgICAgICAgaWYgKHByb3BzLmhhc093blByb3BlcnR5KFwibmFtZXNwYWNlXCIpKSB7XG4gICAgICAgICAgICAgICAgICAgIG5hbWVzcGFjZSA9IHByb3BzLm5hbWVzcGFjZTtcbiAgICAgICAgICAgICAgICAgICAgcHJvcHMubmFtZXNwYWNlID0gdW5kZWZpbmVkO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIC8vIGZpeCBjdXJzb3IgYnVnXG4gICAgICAgICAgICAgICAgaWYgKHRhZyA9PT0gXCJJTlBVVFwiICYmICFuYW1lc3BhY2UgJiYgcHJvcHMuaGFzT3duUHJvcGVydHkoXCJ2YWx1ZVwiKSAmJiBwcm9wcy52YWx1ZSAhPT0gdW5kZWZpbmVkICYmICFpc0hvb2socHJvcHMudmFsdWUpKSB7XG4gICAgICAgICAgICAgICAgICAgIHByb3BzLnZhbHVlID0gc29mdFNldEhvb2socHJvcHMudmFsdWUpO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHRyYW5zZm9ybVByb3BlcnRpZXMocHJvcHMpO1xuXG4gICAgICAgICAgICAgICAgaWYgKGNoaWxkcmVuICE9PSB1bmRlZmluZWQgJiYgY2hpbGRyZW4gIT09IG51bGwpIHtcbiAgICAgICAgICAgICAgICAgICAgYWRkQ2hpbGQoY2hpbGRyZW4sIGNoaWxkTm9kZXMsIHRhZywgcHJvcHMpO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHJldHVybiBuZXcgVk5vZGUodGFnLCBwcm9wcywgY2hpbGROb2Rlcywga2V5LCBuYW1lc3BhY2UpO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBmdW5jdGlvbiBhZGRDaGlsZChjLCBjaGlsZE5vZGVzLCB0YWcsIHByb3BzKSB7XG4gICAgICAgICAgICAgICAgaWYgKHR5cGVvZiBjID09PSBcInN0cmluZ1wiKSB7XG4gICAgICAgICAgICAgICAgICAgIGNoaWxkTm9kZXMucHVzaChuZXcgVlRleHQoYykpO1xuICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAodHlwZW9mIGMgPT09IFwibnVtYmVyXCIpIHtcbiAgICAgICAgICAgICAgICAgICAgY2hpbGROb2Rlcy5wdXNoKG5ldyBWVGV4dChTdHJpbmcoYykpKTtcbiAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKGlzQ2hpbGQoYykpIHtcbiAgICAgICAgICAgICAgICAgICAgY2hpbGROb2Rlcy5wdXNoKGMpO1xuICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoaXNBcnJheShjKSkge1xuICAgICAgICAgICAgICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IGMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGFkZENoaWxkKGNbaV0sIGNoaWxkTm9kZXMsIHRhZywgcHJvcHMpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfSBlbHNlIGlmIChjID09PSBudWxsIHx8IGMgPT09IHVuZGVmaW5lZCkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgdGhyb3cgVW5leHBlY3RlZFZpcnR1YWxFbGVtZW50KHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGZvcmVpZ25PYmplY3Q6IGMsXG4gICAgICAgICAgICAgICAgICAgICAgICBwYXJlbnRWbm9kZToge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRhZ05hbWU6IHRhZyxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBwcm9wZXJ0aWVzOiBwcm9wc1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIHRyYW5zZm9ybVByb3BlcnRpZXMocHJvcHMpIHtcbiAgICAgICAgICAgICAgICBmb3IgKHZhciBwcm9wTmFtZSBpbiBwcm9wcykge1xuICAgICAgICAgICAgICAgICAgICBpZiAocHJvcHMuaGFzT3duUHJvcGVydHkocHJvcE5hbWUpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICB2YXIgdmFsdWUgPSBwcm9wc1twcm9wTmFtZV07XG5cbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChpc0hvb2sodmFsdWUpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgY29udGludWU7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChwcm9wTmFtZS5zdWJzdHIoMCwgMykgPT09IFwiZXYtXCIpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBhZGQgZXYtZm9vIHN1cHBvcnRcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBwcm9wc1twcm9wTmFtZV0gPSBldkhvb2sodmFsdWUpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBmdW5jdGlvbiBpc0NoaWxkKHgpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gaXNWTm9kZSh4KSB8fCBpc1ZUZXh0KHgpIHx8IGlzV2lkZ2V0KHgpIHx8IGlzVlRodW5rKHgpO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBmdW5jdGlvbiBpc0NoaWxkcmVuKHgpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gdHlwZW9mIHggPT09IFwic3RyaW5nXCIgfHwgaXNBcnJheSh4KSB8fCBpc0NoaWxkKHgpO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBmdW5jdGlvbiBVbmV4cGVjdGVkVmlydHVhbEVsZW1lbnQoZGF0YSkge1xuICAgICAgICAgICAgICAgIHZhciBlcnIgPSBuZXcgRXJyb3IoKTtcblxuICAgICAgICAgICAgICAgIGVyci50eXBlID0gXCJ2aXJ0dWFsLWh5cGVyc2NyaXB0LnVuZXhwZWN0ZWQudmlydHVhbC1lbGVtZW50XCI7XG4gICAgICAgICAgICAgICAgZXJyLm1lc3NhZ2UgPSBcIlVuZXhwZWN0ZWQgdmlydHVhbCBjaGlsZCBwYXNzZWQgdG8gaCgpLlxcblwiICsgXCJFeHBlY3RlZCBhIFZOb2RlIC8gVnRodW5rIC8gVldpZGdldCAvIHN0cmluZyBidXQ6XFxuXCIgKyBcImdvdDpcXG5cIiArIGVycm9yU3RyaW5nKGRhdGEuZm9yZWlnbk9iamVjdCkgKyBcIi5cXG5cIiArIFwiVGhlIHBhcmVudCB2bm9kZSBpczpcXG5cIiArIGVycm9yU3RyaW5nKGRhdGEucGFyZW50Vm5vZGUpO1xuICAgICAgICAgICAgICAgIFwiXFxuXCIgKyBcIlN1Z2dlc3RlZCBmaXg6IGNoYW5nZSB5b3VyIGBoKC4uLiwgWyAuLi4gXSlgIGNhbGxzaXRlLlwiO1xuICAgICAgICAgICAgICAgIGVyci5mb3JlaWduT2JqZWN0ID0gZGF0YS5mb3JlaWduT2JqZWN0O1xuICAgICAgICAgICAgICAgIGVyci5wYXJlbnRWbm9kZSA9IGRhdGEucGFyZW50Vm5vZGU7XG5cbiAgICAgICAgICAgICAgICByZXR1cm4gZXJyO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBmdW5jdGlvbiBlcnJvclN0cmluZyhvYmopIHtcbiAgICAgICAgICAgICAgICB0cnkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gSlNPTi5zdHJpbmdpZnkob2JqLCBudWxsLCBcIiAgICBcIik7XG4gICAgICAgICAgICAgICAgfSBjYXRjaCAoZSkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gU3RyaW5nKG9iaik7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9LCB7IFwiLi4vdm5vZGUvaXMtdGh1bmtcIjogMjUsIFwiLi4vdm5vZGUvaXMtdmhvb2tcIjogMjYsIFwiLi4vdm5vZGUvaXMtdm5vZGVcIjogMjcsIFwiLi4vdm5vZGUvaXMtdnRleHRcIjogMjgsIFwiLi4vdm5vZGUvaXMtd2lkZ2V0XCI6IDI5LCBcIi4uL3Zub2RlL3Zub2RlLmpzXCI6IDMxLCBcIi4uL3Zub2RlL3Z0ZXh0LmpzXCI6IDMzLCBcIi4vaG9va3MvZXYtaG9vay5qc1wiOiAyMCwgXCIuL2hvb2tzL3NvZnQtc2V0LWhvb2suanNcIjogMjEsIFwiLi9wYXJzZS10YWcuanNcIjogMjMsIFwieC1pcy1hcnJheVwiOiAxMiB9XSwgMjM6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICBcInVzZSBzdHJpY3RcIjtcblxuICAgICAgICAgICAgdmFyIHNwbGl0ID0gcmVxdWlyZShcImJyb3dzZXItc3BsaXRcIik7XG5cbiAgICAgICAgICAgIHZhciBjbGFzc0lkU3BsaXQgPSAvKFtcXC4jXT9bYS16QS1aMC05XFx1MDA3Ri1cXHVGRkZGXzotXSspLztcbiAgICAgICAgICAgIHZhciBub3RDbGFzc0lkID0gL15cXC58Iy87XG5cbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gcGFyc2VUYWc7XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIHBhcnNlVGFnKHRhZywgcHJvcHMpIHtcbiAgICAgICAgICAgICAgICBpZiAoIXRhZykge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gXCJESVZcIjtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICB2YXIgbm9JZCA9ICFwcm9wcy5oYXNPd25Qcm9wZXJ0eShcImlkXCIpO1xuXG4gICAgICAgICAgICAgICAgdmFyIHRhZ1BhcnRzID0gc3BsaXQodGFnLCBjbGFzc0lkU3BsaXQpO1xuICAgICAgICAgICAgICAgIHZhciB0YWdOYW1lID0gbnVsbDtcblxuICAgICAgICAgICAgICAgIGlmIChub3RDbGFzc0lkLnRlc3QodGFnUGFydHNbMV0pKSB7XG4gICAgICAgICAgICAgICAgICAgIHRhZ05hbWUgPSBcIkRJVlwiO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHZhciBjbGFzc2VzLCBwYXJ0LCB0eXBlLCBpO1xuXG4gICAgICAgICAgICAgICAgZm9yIChpID0gMDsgaSA8IHRhZ1BhcnRzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICAgICAgICAgIHBhcnQgPSB0YWdQYXJ0c1tpXTtcblxuICAgICAgICAgICAgICAgICAgICBpZiAoIXBhcnQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnRpbnVlO1xuICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgdHlwZSA9IHBhcnQuY2hhckF0KDApO1xuXG4gICAgICAgICAgICAgICAgICAgIGlmICghdGFnTmFtZSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgdGFnTmFtZSA9IHBhcnQ7XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAodHlwZSA9PT0gXCIuXCIpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGNsYXNzZXMgPSBjbGFzc2VzIHx8IFtdO1xuICAgICAgICAgICAgICAgICAgICAgICAgY2xhc3Nlcy5wdXNoKHBhcnQuc3Vic3RyaW5nKDEsIHBhcnQubGVuZ3RoKSk7XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAodHlwZSA9PT0gXCIjXCIgJiYgbm9JZCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgcHJvcHMuaWQgPSBwYXJ0LnN1YnN0cmluZygxLCBwYXJ0Lmxlbmd0aCk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICBpZiAoY2xhc3Nlcykge1xuICAgICAgICAgICAgICAgICAgICBpZiAocHJvcHMuY2xhc3NOYW1lKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBjbGFzc2VzLnB1c2gocHJvcHMuY2xhc3NOYW1lKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgIHByb3BzLmNsYXNzTmFtZSA9IGNsYXNzZXMuam9pbihcIiBcIik7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgcmV0dXJuIHByb3BzLm5hbWVzcGFjZSA/IHRhZ05hbWUgOiB0YWdOYW1lLnRvVXBwZXJDYXNlKCk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0sIHsgXCJicm93c2VyLXNwbGl0XCI6IDUgfV0sIDI0OiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge1xuICAgICAgICAgICAgdmFyIGlzVk5vZGUgPSByZXF1aXJlKFwiLi9pcy12bm9kZVwiKTtcbiAgICAgICAgICAgIHZhciBpc1ZUZXh0ID0gcmVxdWlyZShcIi4vaXMtdnRleHRcIik7XG4gICAgICAgICAgICB2YXIgaXNXaWRnZXQgPSByZXF1aXJlKFwiLi9pcy13aWRnZXRcIik7XG4gICAgICAgICAgICB2YXIgaXNUaHVuayA9IHJlcXVpcmUoXCIuL2lzLXRodW5rXCIpO1xuXG4gICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IGhhbmRsZVRodW5rO1xuXG4gICAgICAgICAgICBmdW5jdGlvbiBoYW5kbGVUaHVuayhhLCBiKSB7XG4gICAgICAgICAgICAgICAgdmFyIHJlbmRlcmVkQSA9IGE7XG4gICAgICAgICAgICAgICAgdmFyIHJlbmRlcmVkQiA9IGI7XG5cbiAgICAgICAgICAgICAgICBpZiAoaXNUaHVuayhiKSkge1xuICAgICAgICAgICAgICAgICAgICByZW5kZXJlZEIgPSByZW5kZXJUaHVuayhiLCBhKTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICBpZiAoaXNUaHVuayhhKSkge1xuICAgICAgICAgICAgICAgICAgICByZW5kZXJlZEEgPSByZW5kZXJUaHVuayhhLCBudWxsKTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgICAgICAgICBhOiByZW5kZXJlZEEsXG4gICAgICAgICAgICAgICAgICAgIGI6IHJlbmRlcmVkQlxuICAgICAgICAgICAgICAgIH07XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIHJlbmRlclRodW5rKHRodW5rLCBwcmV2aW91cykge1xuICAgICAgICAgICAgICAgIHZhciByZW5kZXJlZFRodW5rID0gdGh1bmsudm5vZGU7XG5cbiAgICAgICAgICAgICAgICBpZiAoIXJlbmRlcmVkVGh1bmspIHtcbiAgICAgICAgICAgICAgICAgICAgcmVuZGVyZWRUaHVuayA9IHRodW5rLnZub2RlID0gdGh1bmsucmVuZGVyKHByZXZpb3VzKTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICBpZiAoIShpc1ZOb2RlKHJlbmRlcmVkVGh1bmspIHx8IGlzVlRleHQocmVuZGVyZWRUaHVuaykgfHwgaXNXaWRnZXQocmVuZGVyZWRUaHVuaykpKSB7XG4gICAgICAgICAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcihcInRodW5rIGRpZCBub3QgcmV0dXJuIGEgdmFsaWQgbm9kZVwiKTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICByZXR1cm4gcmVuZGVyZWRUaHVuaztcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSwgeyBcIi4vaXMtdGh1bmtcIjogMjUsIFwiLi9pcy12bm9kZVwiOiAyNywgXCIuL2lzLXZ0ZXh0XCI6IDI4LCBcIi4vaXMtd2lkZ2V0XCI6IDI5IH1dLCAyNTogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHtcbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gaXNUaHVuaztcblxuICAgICAgICAgICAgZnVuY3Rpb24gaXNUaHVuayh0KSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHQgJiYgdC50eXBlID09PSBcIlRodW5rXCI7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0sIHt9XSwgMjY6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IGlzSG9vaztcblxuICAgICAgICAgICAgZnVuY3Rpb24gaXNIb29rKGhvb2spIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gaG9vayAmJiAodHlwZW9mIGhvb2suaG9vayA9PT0gXCJmdW5jdGlvblwiICYmICFob29rLmhhc093blByb3BlcnR5KFwiaG9va1wiKSB8fCB0eXBlb2YgaG9vay51bmhvb2sgPT09IFwiZnVuY3Rpb25cIiAmJiAhaG9vay5oYXNPd25Qcm9wZXJ0eShcInVuaG9va1wiKSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0sIHt9XSwgMjc6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICB2YXIgdmVyc2lvbiA9IHJlcXVpcmUoXCIuL3ZlcnNpb25cIik7XG5cbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gaXNWaXJ0dWFsTm9kZTtcblxuICAgICAgICAgICAgZnVuY3Rpb24gaXNWaXJ0dWFsTm9kZSh4KSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHggJiYgeC50eXBlID09PSBcIlZpcnR1YWxOb2RlXCIgJiYgeC52ZXJzaW9uID09PSB2ZXJzaW9uO1xuICAgICAgICAgICAgfVxuICAgICAgICB9LCB7IFwiLi92ZXJzaW9uXCI6IDMwIH1dLCAyODogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHtcbiAgICAgICAgICAgIHZhciB2ZXJzaW9uID0gcmVxdWlyZShcIi4vdmVyc2lvblwiKTtcblxuICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBpc1ZpcnR1YWxUZXh0O1xuXG4gICAgICAgICAgICBmdW5jdGlvbiBpc1ZpcnR1YWxUZXh0KHgpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4geCAmJiB4LnR5cGUgPT09IFwiVmlydHVhbFRleHRcIiAmJiB4LnZlcnNpb24gPT09IHZlcnNpb247XG4gICAgICAgICAgICB9XG4gICAgICAgIH0sIHsgXCIuL3ZlcnNpb25cIjogMzAgfV0sIDI5OiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge1xuICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBpc1dpZGdldDtcblxuICAgICAgICAgICAgZnVuY3Rpb24gaXNXaWRnZXQodykge1xuICAgICAgICAgICAgICAgIHJldHVybiB3ICYmIHcudHlwZSA9PT0gXCJXaWRnZXRcIjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSwge31dLCAzMDogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHtcbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gXCIyXCI7XG4gICAgICAgIH0sIHt9XSwgMzE6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICB2YXIgdmVyc2lvbiA9IHJlcXVpcmUoXCIuL3ZlcnNpb25cIik7XG4gICAgICAgICAgICB2YXIgaXNWTm9kZSA9IHJlcXVpcmUoXCIuL2lzLXZub2RlXCIpO1xuICAgICAgICAgICAgdmFyIGlzV2lkZ2V0ID0gcmVxdWlyZShcIi4vaXMtd2lkZ2V0XCIpO1xuICAgICAgICAgICAgdmFyIGlzVGh1bmsgPSByZXF1aXJlKFwiLi9pcy10aHVua1wiKTtcbiAgICAgICAgICAgIHZhciBpc1ZIb29rID0gcmVxdWlyZShcIi4vaXMtdmhvb2tcIik7XG5cbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gVmlydHVhbE5vZGU7XG5cbiAgICAgICAgICAgIHZhciBub1Byb3BlcnRpZXMgPSB7fTtcbiAgICAgICAgICAgIHZhciBub0NoaWxkcmVuID0gW107XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIFZpcnR1YWxOb2RlKHRhZ05hbWUsIHByb3BlcnRpZXMsIGNoaWxkcmVuLCBrZXksIG5hbWVzcGFjZSkge1xuICAgICAgICAgICAgICAgIHRoaXMudGFnTmFtZSA9IHRhZ05hbWU7XG4gICAgICAgICAgICAgICAgdGhpcy5wcm9wZXJ0aWVzID0gcHJvcGVydGllcyB8fCBub1Byb3BlcnRpZXM7XG4gICAgICAgICAgICAgICAgdGhpcy5jaGlsZHJlbiA9IGNoaWxkcmVuIHx8IG5vQ2hpbGRyZW47XG4gICAgICAgICAgICAgICAgdGhpcy5rZXkgPSBrZXkgIT0gbnVsbCA/IFN0cmluZyhrZXkpIDogdW5kZWZpbmVkO1xuICAgICAgICAgICAgICAgIHRoaXMubmFtZXNwYWNlID0gdHlwZW9mIG5hbWVzcGFjZSA9PT0gXCJzdHJpbmdcIiA/IG5hbWVzcGFjZSA6IG51bGw7XG5cbiAgICAgICAgICAgICAgICB2YXIgY291bnQgPSBjaGlsZHJlbiAmJiBjaGlsZHJlbi5sZW5ndGggfHwgMDtcbiAgICAgICAgICAgICAgICB2YXIgZGVzY2VuZGFudHMgPSAwO1xuICAgICAgICAgICAgICAgIHZhciBoYXNXaWRnZXRzID0gZmFsc2U7XG4gICAgICAgICAgICAgICAgdmFyIGhhc1RodW5rcyA9IGZhbHNlO1xuICAgICAgICAgICAgICAgIHZhciBkZXNjZW5kYW50SG9va3MgPSBmYWxzZTtcbiAgICAgICAgICAgICAgICB2YXIgaG9va3M7XG5cbiAgICAgICAgICAgICAgICBmb3IgKHZhciBwcm9wTmFtZSBpbiBwcm9wZXJ0aWVzKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmIChwcm9wZXJ0aWVzLmhhc093blByb3BlcnR5KHByb3BOYW1lKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgdmFyIHByb3BlcnR5ID0gcHJvcGVydGllc1twcm9wTmFtZV07XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoaXNWSG9vayhwcm9wZXJ0eSkgJiYgcHJvcGVydHkudW5ob29rKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKCFob29rcykge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBob29rcyA9IHt9O1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGhvb2tzW3Byb3BOYW1lXSA9IHByb3BlcnR5O1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCBjb3VudDsgaSsrKSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciBjaGlsZCA9IGNoaWxkcmVuW2ldO1xuICAgICAgICAgICAgICAgICAgICBpZiAoaXNWTm9kZShjaGlsZCkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGRlc2NlbmRhbnRzICs9IGNoaWxkLmNvdW50IHx8IDA7XG5cbiAgICAgICAgICAgICAgICAgICAgICAgIGlmICghaGFzV2lkZ2V0cyAmJiBjaGlsZC5oYXNXaWRnZXRzKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaGFzV2lkZ2V0cyA9IHRydWU7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgICAgIGlmICghaGFzVGh1bmtzICYmIGNoaWxkLmhhc1RodW5rcykge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGhhc1RodW5rcyA9IHRydWU7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgICAgIGlmICghZGVzY2VuZGFudEhvb2tzICYmIChjaGlsZC5ob29rcyB8fCBjaGlsZC5kZXNjZW5kYW50SG9va3MpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgZGVzY2VuZGFudEhvb2tzID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIGlmICghaGFzV2lkZ2V0cyAmJiBpc1dpZGdldChjaGlsZCkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmICh0eXBlb2YgY2hpbGQuZGVzdHJveSA9PT0gXCJmdW5jdGlvblwiKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaGFzV2lkZ2V0cyA9IHRydWU7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoIWhhc1RodW5rcyAmJiBpc1RodW5rKGNoaWxkKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgaGFzVGh1bmtzID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHRoaXMuY291bnQgPSBjb3VudCArIGRlc2NlbmRhbnRzO1xuICAgICAgICAgICAgICAgIHRoaXMuaGFzV2lkZ2V0cyA9IGhhc1dpZGdldHM7XG4gICAgICAgICAgICAgICAgdGhpcy5oYXNUaHVua3MgPSBoYXNUaHVua3M7XG4gICAgICAgICAgICAgICAgdGhpcy5ob29rcyA9IGhvb2tzO1xuICAgICAgICAgICAgICAgIHRoaXMuZGVzY2VuZGFudEhvb2tzID0gZGVzY2VuZGFudEhvb2tzO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBWaXJ0dWFsTm9kZS5wcm90b3R5cGUudmVyc2lvbiA9IHZlcnNpb247XG4gICAgICAgICAgICBWaXJ0dWFsTm9kZS5wcm90b3R5cGUudHlwZSA9IFwiVmlydHVhbE5vZGVcIjtcbiAgICAgICAgfSwgeyBcIi4vaXMtdGh1bmtcIjogMjUsIFwiLi9pcy12aG9va1wiOiAyNiwgXCIuL2lzLXZub2RlXCI6IDI3LCBcIi4vaXMtd2lkZ2V0XCI6IDI5LCBcIi4vdmVyc2lvblwiOiAzMCB9XSwgMzI6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICB2YXIgdmVyc2lvbiA9IHJlcXVpcmUoXCIuL3ZlcnNpb25cIik7XG5cbiAgICAgICAgICAgIFZpcnR1YWxQYXRjaC5OT05FID0gMDtcbiAgICAgICAgICAgIFZpcnR1YWxQYXRjaC5WVEVYVCA9IDE7XG4gICAgICAgICAgICBWaXJ0dWFsUGF0Y2guVk5PREUgPSAyO1xuICAgICAgICAgICAgVmlydHVhbFBhdGNoLldJREdFVCA9IDM7XG4gICAgICAgICAgICBWaXJ0dWFsUGF0Y2guUFJPUFMgPSA0O1xuICAgICAgICAgICAgVmlydHVhbFBhdGNoLk9SREVSID0gNTtcbiAgICAgICAgICAgIFZpcnR1YWxQYXRjaC5JTlNFUlQgPSA2O1xuICAgICAgICAgICAgVmlydHVhbFBhdGNoLlJFTU9WRSA9IDc7XG4gICAgICAgICAgICBWaXJ0dWFsUGF0Y2guVEhVTksgPSA4O1xuXG4gICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IFZpcnR1YWxQYXRjaDtcblxuICAgICAgICAgICAgZnVuY3Rpb24gVmlydHVhbFBhdGNoKHR5cGUsIHZOb2RlLCBwYXRjaCkge1xuICAgICAgICAgICAgICAgIHRoaXMudHlwZSA9IE51bWJlcih0eXBlKTtcbiAgICAgICAgICAgICAgICB0aGlzLnZOb2RlID0gdk5vZGU7XG4gICAgICAgICAgICAgICAgdGhpcy5wYXRjaCA9IHBhdGNoO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBWaXJ0dWFsUGF0Y2gucHJvdG90eXBlLnZlcnNpb24gPSB2ZXJzaW9uO1xuICAgICAgICAgICAgVmlydHVhbFBhdGNoLnByb3RvdHlwZS50eXBlID0gXCJWaXJ0dWFsUGF0Y2hcIjtcbiAgICAgICAgfSwgeyBcIi4vdmVyc2lvblwiOiAzMCB9XSwgMzM6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICB2YXIgdmVyc2lvbiA9IHJlcXVpcmUoXCIuL3ZlcnNpb25cIik7XG5cbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gVmlydHVhbFRleHQ7XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIFZpcnR1YWxUZXh0KHRleHQpIHtcbiAgICAgICAgICAgICAgICB0aGlzLnRleHQgPSBTdHJpbmcodGV4dCk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIFZpcnR1YWxUZXh0LnByb3RvdHlwZS52ZXJzaW9uID0gdmVyc2lvbjtcbiAgICAgICAgICAgIFZpcnR1YWxUZXh0LnByb3RvdHlwZS50eXBlID0gXCJWaXJ0dWFsVGV4dFwiO1xuICAgICAgICB9LCB7IFwiLi92ZXJzaW9uXCI6IDMwIH1dLCAzNDogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHtcbiAgICAgICAgICAgIHZhciBpc09iamVjdCA9IHJlcXVpcmUoXCJpcy1vYmplY3RcIik7XG4gICAgICAgICAgICB2YXIgaXNIb29rID0gcmVxdWlyZShcIi4uL3Zub2RlL2lzLXZob29rXCIpO1xuXG4gICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IGRpZmZQcm9wcztcblxuICAgICAgICAgICAgZnVuY3Rpb24gZGlmZlByb3BzKGEsIGIpIHtcbiAgICAgICAgICAgICAgICB2YXIgZGlmZjtcblxuICAgICAgICAgICAgICAgIGZvciAodmFyIGFLZXkgaW4gYSkge1xuICAgICAgICAgICAgICAgICAgICBpZiAoIShhS2V5IGluIGIpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBkaWZmID0gZGlmZiB8fCB7fTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGRpZmZbYUtleV0gPSB1bmRlZmluZWQ7XG4gICAgICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgICAgICB2YXIgYVZhbHVlID0gYVthS2V5XTtcbiAgICAgICAgICAgICAgICAgICAgdmFyIGJWYWx1ZSA9IGJbYUtleV07XG5cbiAgICAgICAgICAgICAgICAgICAgaWYgKGFWYWx1ZSA9PT0gYlZhbHVlKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBjb250aW51ZTtcbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIGlmIChpc09iamVjdChhVmFsdWUpICYmIGlzT2JqZWN0KGJWYWx1ZSkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChnZXRQcm90b3R5cGUoYlZhbHVlKSAhPT0gZ2V0UHJvdG90eXBlKGFWYWx1ZSkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBkaWZmID0gZGlmZiB8fCB7fTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBkaWZmW2FLZXldID0gYlZhbHVlO1xuICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIGlmIChpc0hvb2soYlZhbHVlKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRpZmYgPSBkaWZmIHx8IHt9O1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRpZmZbYUtleV0gPSBiVmFsdWU7XG4gICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZhciBvYmplY3REaWZmID0gZGlmZlByb3BzKGFWYWx1ZSwgYlZhbHVlKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAob2JqZWN0RGlmZikge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBkaWZmID0gZGlmZiB8fCB7fTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZGlmZlthS2V5XSA9IG9iamVjdERpZmY7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgZGlmZiA9IGRpZmYgfHwge307XG4gICAgICAgICAgICAgICAgICAgICAgICBkaWZmW2FLZXldID0gYlZhbHVlO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgZm9yICh2YXIgYktleSBpbiBiKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmICghKGJLZXkgaW4gYSkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGRpZmYgPSBkaWZmIHx8IHt9O1xuICAgICAgICAgICAgICAgICAgICAgICAgZGlmZltiS2V5XSA9IGJbYktleV07XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICByZXR1cm4gZGlmZjtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZnVuY3Rpb24gZ2V0UHJvdG90eXBlKHZhbHVlKSB7XG4gICAgICAgICAgICAgICAgaWYgKE9iamVjdC5nZXRQcm90b3R5cGVPZikge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gT2JqZWN0LmdldFByb3RvdHlwZU9mKHZhbHVlKTtcbiAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKHZhbHVlLl9fcHJvdG9fXykge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gdmFsdWUuX19wcm90b19fO1xuICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAodmFsdWUuY29uc3RydWN0b3IpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHZhbHVlLmNvbnN0cnVjdG9yLnByb3RvdHlwZTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH0sIHsgXCIuLi92bm9kZS9pcy12aG9va1wiOiAyNiwgXCJpcy1vYmplY3RcIjogMTEgfV0sIDM1OiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge1xuICAgICAgICAgICAgdmFyIGlzQXJyYXkgPSByZXF1aXJlKFwieC1pcy1hcnJheVwiKTtcblxuICAgICAgICAgICAgdmFyIFZQYXRjaCA9IHJlcXVpcmUoXCIuLi92bm9kZS92cGF0Y2hcIik7XG4gICAgICAgICAgICB2YXIgaXNWTm9kZSA9IHJlcXVpcmUoXCIuLi92bm9kZS9pcy12bm9kZVwiKTtcbiAgICAgICAgICAgIHZhciBpc1ZUZXh0ID0gcmVxdWlyZShcIi4uL3Zub2RlL2lzLXZ0ZXh0XCIpO1xuICAgICAgICAgICAgdmFyIGlzV2lkZ2V0ID0gcmVxdWlyZShcIi4uL3Zub2RlL2lzLXdpZGdldFwiKTtcbiAgICAgICAgICAgIHZhciBpc1RodW5rID0gcmVxdWlyZShcIi4uL3Zub2RlL2lzLXRodW5rXCIpO1xuICAgICAgICAgICAgdmFyIGhhbmRsZVRodW5rID0gcmVxdWlyZShcIi4uL3Zub2RlL2hhbmRsZS10aHVua1wiKTtcblxuICAgICAgICAgICAgdmFyIGRpZmZQcm9wcyA9IHJlcXVpcmUoXCIuL2RpZmYtcHJvcHNcIik7XG5cbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gZGlmZjtcblxuICAgICAgICAgICAgZnVuY3Rpb24gZGlmZihhLCBiKSB7XG4gICAgICAgICAgICAgICAgdmFyIHBhdGNoID0geyBhOiBhIH07XG4gICAgICAgICAgICAgICAgd2FsayhhLCBiLCBwYXRjaCwgMCk7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHBhdGNoO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBmdW5jdGlvbiB3YWxrKGEsIGIsIHBhdGNoLCBpbmRleCkge1xuICAgICAgICAgICAgICAgIGlmIChhID09PSBiKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICB2YXIgYXBwbHkgPSBwYXRjaFtpbmRleF07XG4gICAgICAgICAgICAgICAgdmFyIGFwcGx5Q2xlYXIgPSBmYWxzZTtcblxuICAgICAgICAgICAgICAgIGlmIChpc1RodW5rKGEpIHx8IGlzVGh1bmsoYikpIHtcbiAgICAgICAgICAgICAgICAgICAgdGh1bmtzKGEsIGIsIHBhdGNoLCBpbmRleCk7XG4gICAgICAgICAgICAgICAgfSBlbHNlIGlmIChiID09IG51bGwpIHtcblxuICAgICAgICAgICAgICAgICAgICAvLyBJZiBhIGlzIGEgd2lkZ2V0IHdlIHdpbGwgYWRkIGEgcmVtb3ZlIHBhdGNoIGZvciBpdFxuICAgICAgICAgICAgICAgICAgICAvLyBPdGhlcndpc2UgYW55IGNoaWxkIHdpZGdldHMvaG9va3MgbXVzdCBiZSBkZXN0cm95ZWQuXG4gICAgICAgICAgICAgICAgICAgIC8vIFRoaXMgcHJldmVudHMgYWRkaW5nIHR3byByZW1vdmUgcGF0Y2hlcyBmb3IgYSB3aWRnZXQuXG4gICAgICAgICAgICAgICAgICAgIGlmICghaXNXaWRnZXQoYSkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGNsZWFyU3RhdGUoYSwgcGF0Y2gsIGluZGV4KTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGFwcGx5ID0gcGF0Y2hbaW5kZXhdO1xuICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgYXBwbHkgPSBhcHBlbmRQYXRjaChhcHBseSwgbmV3IFZQYXRjaChWUGF0Y2guUkVNT1ZFLCBhLCBiKSk7XG4gICAgICAgICAgICAgICAgfSBlbHNlIGlmIChpc1ZOb2RlKGIpKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmIChpc1ZOb2RlKGEpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoYS50YWdOYW1lID09PSBiLnRhZ05hbWUgJiYgYS5uYW1lc3BhY2UgPT09IGIubmFtZXNwYWNlICYmIGEua2V5ID09PSBiLmtleSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZhciBwcm9wc1BhdGNoID0gZGlmZlByb3BzKGEucHJvcGVydGllcywgYi5wcm9wZXJ0aWVzKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAocHJvcHNQYXRjaCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBhcHBseSA9IGFwcGVuZFBhdGNoKGFwcGx5LCBuZXcgVlBhdGNoKFZQYXRjaC5QUk9QUywgYSwgcHJvcHNQYXRjaCkpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBhcHBseSA9IGRpZmZDaGlsZHJlbihhLCBiLCBwYXRjaCwgYXBwbHksIGluZGV4KTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgYXBwbHkgPSBhcHBlbmRQYXRjaChhcHBseSwgbmV3IFZQYXRjaChWUGF0Y2guVk5PREUsIGEsIGIpKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBhcHBseUNsZWFyID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGFwcGx5ID0gYXBwZW5kUGF0Y2goYXBwbHksIG5ldyBWUGF0Y2goVlBhdGNoLlZOT0RFLCBhLCBiKSk7XG4gICAgICAgICAgICAgICAgICAgICAgICBhcHBseUNsZWFyID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoaXNWVGV4dChiKSkge1xuICAgICAgICAgICAgICAgICAgICBpZiAoIWlzVlRleHQoYSkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGFwcGx5ID0gYXBwZW5kUGF0Y2goYXBwbHksIG5ldyBWUGF0Y2goVlBhdGNoLlZURVhULCBhLCBiKSk7XG4gICAgICAgICAgICAgICAgICAgICAgICBhcHBseUNsZWFyID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIGlmIChhLnRleHQgIT09IGIudGV4dCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgYXBwbHkgPSBhcHBlbmRQYXRjaChhcHBseSwgbmV3IFZQYXRjaChWUGF0Y2guVlRFWFQsIGEsIGIpKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoaXNXaWRnZXQoYikpIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKCFpc1dpZGdldChhKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgYXBwbHlDbGVhciA9IHRydWU7XG4gICAgICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgICAgICBhcHBseSA9IGFwcGVuZFBhdGNoKGFwcGx5LCBuZXcgVlBhdGNoKFZQYXRjaC5XSURHRVQsIGEsIGIpKTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICBpZiAoYXBwbHkpIHtcbiAgICAgICAgICAgICAgICAgICAgcGF0Y2hbaW5kZXhdID0gYXBwbHk7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgaWYgKGFwcGx5Q2xlYXIpIHtcbiAgICAgICAgICAgICAgICAgICAgY2xlYXJTdGF0ZShhLCBwYXRjaCwgaW5kZXgpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZnVuY3Rpb24gZGlmZkNoaWxkcmVuKGEsIGIsIHBhdGNoLCBhcHBseSwgaW5kZXgpIHtcbiAgICAgICAgICAgICAgICB2YXIgYUNoaWxkcmVuID0gYS5jaGlsZHJlbjtcbiAgICAgICAgICAgICAgICB2YXIgb3JkZXJlZFNldCA9IHJlb3JkZXIoYUNoaWxkcmVuLCBiLmNoaWxkcmVuKTtcbiAgICAgICAgICAgICAgICB2YXIgYkNoaWxkcmVuID0gb3JkZXJlZFNldC5jaGlsZHJlbjtcblxuICAgICAgICAgICAgICAgIHZhciBhTGVuID0gYUNoaWxkcmVuLmxlbmd0aDtcbiAgICAgICAgICAgICAgICB2YXIgYkxlbiA9IGJDaGlsZHJlbi5sZW5ndGg7XG4gICAgICAgICAgICAgICAgdmFyIGxlbiA9IGFMZW4gPiBiTGVuID8gYUxlbiA6IGJMZW47XG5cbiAgICAgICAgICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IGxlbjsgaSsrKSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciBsZWZ0Tm9kZSA9IGFDaGlsZHJlbltpXTtcbiAgICAgICAgICAgICAgICAgICAgdmFyIHJpZ2h0Tm9kZSA9IGJDaGlsZHJlbltpXTtcbiAgICAgICAgICAgICAgICAgICAgaW5kZXggKz0gMTtcblxuICAgICAgICAgICAgICAgICAgICBpZiAoIWxlZnROb2RlKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAocmlnaHROb2RlKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gRXhjZXNzIG5vZGVzIGluIGIgbmVlZCB0byBiZSBhZGRlZFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGFwcGx5ID0gYXBwZW5kUGF0Y2goYXBwbHksIG5ldyBWUGF0Y2goVlBhdGNoLklOU0VSVCwgbnVsbCwgcmlnaHROb2RlKSk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICB3YWxrKGxlZnROb2RlLCByaWdodE5vZGUsIHBhdGNoLCBpbmRleCk7XG4gICAgICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgICAgICBpZiAoaXNWTm9kZShsZWZ0Tm9kZSkgJiYgbGVmdE5vZGUuY291bnQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGluZGV4ICs9IGxlZnROb2RlLmNvdW50O1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgaWYgKG9yZGVyZWRTZXQubW92ZXMpIHtcbiAgICAgICAgICAgICAgICAgICAgLy8gUmVvcmRlciBub2RlcyBsYXN0XG4gICAgICAgICAgICAgICAgICAgIGFwcGx5ID0gYXBwZW5kUGF0Y2goYXBwbHksIG5ldyBWUGF0Y2goVlBhdGNoLk9SREVSLCBhLCBvcmRlcmVkU2V0Lm1vdmVzKSk7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgcmV0dXJuIGFwcGx5O1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBmdW5jdGlvbiBjbGVhclN0YXRlKHZOb2RlLCBwYXRjaCwgaW5kZXgpIHtcbiAgICAgICAgICAgICAgICAvLyBUT0RPOiBNYWtlIHRoaXMgYSBzaW5nbGUgd2Fsaywgbm90IHR3b1xuICAgICAgICAgICAgICAgIHVuaG9vayh2Tm9kZSwgcGF0Y2gsIGluZGV4KTtcbiAgICAgICAgICAgICAgICBkZXN0cm95V2lkZ2V0cyh2Tm9kZSwgcGF0Y2gsIGluZGV4KTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgLy8gUGF0Y2ggcmVjb3JkcyBmb3IgYWxsIGRlc3Ryb3llZCB3aWRnZXRzIG11c3QgYmUgYWRkZWQgYmVjYXVzZSB3ZSBuZWVkXG4gICAgICAgICAgICAvLyBhIERPTSBub2RlIHJlZmVyZW5jZSBmb3IgdGhlIGRlc3Ryb3kgZnVuY3Rpb25cbiAgICAgICAgICAgIGZ1bmN0aW9uIGRlc3Ryb3lXaWRnZXRzKHZOb2RlLCBwYXRjaCwgaW5kZXgpIHtcbiAgICAgICAgICAgICAgICBpZiAoaXNXaWRnZXQodk5vZGUpKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmICh0eXBlb2Ygdk5vZGUuZGVzdHJveSA9PT0gXCJmdW5jdGlvblwiKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBwYXRjaFtpbmRleF0gPSBhcHBlbmRQYXRjaChwYXRjaFtpbmRleF0sIG5ldyBWUGF0Y2goVlBhdGNoLlJFTU9WRSwgdk5vZGUsIG51bGwpKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoaXNWTm9kZSh2Tm9kZSkgJiYgKHZOb2RlLmhhc1dpZGdldHMgfHwgdk5vZGUuaGFzVGh1bmtzKSkge1xuICAgICAgICAgICAgICAgICAgICB2YXIgY2hpbGRyZW4gPSB2Tm9kZS5jaGlsZHJlbjtcbiAgICAgICAgICAgICAgICAgICAgdmFyIGxlbiA9IGNoaWxkcmVuLmxlbmd0aDtcbiAgICAgICAgICAgICAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCBsZW47IGkrKykge1xuICAgICAgICAgICAgICAgICAgICAgICAgdmFyIGNoaWxkID0gY2hpbGRyZW5baV07XG4gICAgICAgICAgICAgICAgICAgICAgICBpbmRleCArPSAxO1xuXG4gICAgICAgICAgICAgICAgICAgICAgICBkZXN0cm95V2lkZ2V0cyhjaGlsZCwgcGF0Y2gsIGluZGV4KTtcblxuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGlzVk5vZGUoY2hpbGQpICYmIGNoaWxkLmNvdW50KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaW5kZXggKz0gY2hpbGQuY291bnQ7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKGlzVGh1bmsodk5vZGUpKSB7XG4gICAgICAgICAgICAgICAgICAgIHRodW5rcyh2Tm9kZSwgbnVsbCwgcGF0Y2gsIGluZGV4KTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIC8vIENyZWF0ZSBhIHN1Yi1wYXRjaCBmb3IgdGh1bmtzXG4gICAgICAgICAgICBmdW5jdGlvbiB0aHVua3MoYSwgYiwgcGF0Y2gsIGluZGV4KSB7XG4gICAgICAgICAgICAgICAgdmFyIG5vZGVzID0gaGFuZGxlVGh1bmsoYSwgYik7XG4gICAgICAgICAgICAgICAgdmFyIHRodW5rUGF0Y2ggPSBkaWZmKG5vZGVzLmEsIG5vZGVzLmIpO1xuICAgICAgICAgICAgICAgIGlmIChoYXNQYXRjaGVzKHRodW5rUGF0Y2gpKSB7XG4gICAgICAgICAgICAgICAgICAgIHBhdGNoW2luZGV4XSA9IG5ldyBWUGF0Y2goVlBhdGNoLlRIVU5LLCBudWxsLCB0aHVua1BhdGNoKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIGhhc1BhdGNoZXMocGF0Y2gpIHtcbiAgICAgICAgICAgICAgICBmb3IgKHZhciBpbmRleCBpbiBwYXRjaCkge1xuICAgICAgICAgICAgICAgICAgICBpZiAoaW5kZXggIT09IFwiYVwiKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgLy8gRXhlY3V0ZSBob29rcyB3aGVuIHR3byBub2RlcyBhcmUgaWRlbnRpY2FsXG4gICAgICAgICAgICBmdW5jdGlvbiB1bmhvb2sodk5vZGUsIHBhdGNoLCBpbmRleCkge1xuICAgICAgICAgICAgICAgIGlmIChpc1ZOb2RlKHZOb2RlKSkge1xuICAgICAgICAgICAgICAgICAgICBpZiAodk5vZGUuaG9va3MpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHBhdGNoW2luZGV4XSA9IGFwcGVuZFBhdGNoKHBhdGNoW2luZGV4XSwgbmV3IFZQYXRjaChWUGF0Y2guUFJPUFMsIHZOb2RlLCB1bmRlZmluZWRLZXlzKHZOb2RlLmhvb2tzKSkpO1xuICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgaWYgKHZOb2RlLmRlc2NlbmRhbnRIb29rcyB8fCB2Tm9kZS5oYXNUaHVua3MpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHZhciBjaGlsZHJlbiA9IHZOb2RlLmNoaWxkcmVuO1xuICAgICAgICAgICAgICAgICAgICAgICAgdmFyIGxlbiA9IGNoaWxkcmVuLmxlbmd0aDtcbiAgICAgICAgICAgICAgICAgICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgbGVuOyBpKyspIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB2YXIgY2hpbGQgPSBjaGlsZHJlbltpXTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpbmRleCArPSAxO1xuXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdW5ob29rKGNoaWxkLCBwYXRjaCwgaW5kZXgpO1xuXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGlzVk5vZGUoY2hpbGQpICYmIGNoaWxkLmNvdW50KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGluZGV4ICs9IGNoaWxkLmNvdW50O1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoaXNUaHVuayh2Tm9kZSkpIHtcbiAgICAgICAgICAgICAgICAgICAgdGh1bmtzKHZOb2RlLCBudWxsLCBwYXRjaCwgaW5kZXgpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZnVuY3Rpb24gdW5kZWZpbmVkS2V5cyhvYmopIHtcbiAgICAgICAgICAgICAgICB2YXIgcmVzdWx0ID0ge307XG5cbiAgICAgICAgICAgICAgICBmb3IgKHZhciBrZXkgaW4gb2JqKSB7XG4gICAgICAgICAgICAgICAgICAgIHJlc3VsdFtrZXldID0gdW5kZWZpbmVkO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHJldHVybiByZXN1bHQ7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIC8vIExpc3QgZGlmZiwgbmFpdmUgbGVmdCB0byByaWdodCByZW9yZGVyaW5nXG4gICAgICAgICAgICBmdW5jdGlvbiByZW9yZGVyKGFDaGlsZHJlbiwgYkNoaWxkcmVuKSB7XG4gICAgICAgICAgICAgICAgLy8gTyhNKSB0aW1lLCBPKE0pIG1lbW9yeVxuICAgICAgICAgICAgICAgIHZhciBiQ2hpbGRJbmRleCA9IGtleUluZGV4KGJDaGlsZHJlbik7XG4gICAgICAgICAgICAgICAgdmFyIGJLZXlzID0gYkNoaWxkSW5kZXgua2V5cztcbiAgICAgICAgICAgICAgICB2YXIgYkZyZWUgPSBiQ2hpbGRJbmRleC5mcmVlO1xuXG4gICAgICAgICAgICAgICAgaWYgKGJGcmVlLmxlbmd0aCA9PT0gYkNoaWxkcmVuLmxlbmd0aCkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgICAgICAgICAgICAgY2hpbGRyZW46IGJDaGlsZHJlbixcbiAgICAgICAgICAgICAgICAgICAgICAgIG1vdmVzOiBudWxsXG4gICAgICAgICAgICAgICAgICAgIH07XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgLy8gTyhOKSB0aW1lLCBPKE4pIG1lbW9yeVxuICAgICAgICAgICAgICAgIHZhciBhQ2hpbGRJbmRleCA9IGtleUluZGV4KGFDaGlsZHJlbik7XG4gICAgICAgICAgICAgICAgdmFyIGFLZXlzID0gYUNoaWxkSW5kZXgua2V5cztcbiAgICAgICAgICAgICAgICB2YXIgYUZyZWUgPSBhQ2hpbGRJbmRleC5mcmVlO1xuXG4gICAgICAgICAgICAgICAgaWYgKGFGcmVlLmxlbmd0aCA9PT0gYUNoaWxkcmVuLmxlbmd0aCkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgICAgICAgICAgICAgY2hpbGRyZW46IGJDaGlsZHJlbixcbiAgICAgICAgICAgICAgICAgICAgICAgIG1vdmVzOiBudWxsXG4gICAgICAgICAgICAgICAgICAgIH07XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgLy8gTyhNQVgoTiwgTSkpIG1lbW9yeVxuICAgICAgICAgICAgICAgIHZhciBuZXdDaGlsZHJlbiA9IFtdO1xuXG4gICAgICAgICAgICAgICAgdmFyIGZyZWVJbmRleCA9IDA7XG4gICAgICAgICAgICAgICAgdmFyIGZyZWVDb3VudCA9IGJGcmVlLmxlbmd0aDtcbiAgICAgICAgICAgICAgICB2YXIgZGVsZXRlZEl0ZW1zID0gMDtcblxuICAgICAgICAgICAgICAgIC8vIEl0ZXJhdGUgdGhyb3VnaCBhIGFuZCBtYXRjaCBhIG5vZGUgaW4gYlxuICAgICAgICAgICAgICAgIC8vIE8oTikgdGltZSxcbiAgICAgICAgICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IGFDaGlsZHJlbi5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgICAgICAgICB2YXIgYUl0ZW0gPSBhQ2hpbGRyZW5baV07XG4gICAgICAgICAgICAgICAgICAgIHZhciBpdGVtSW5kZXg7XG5cbiAgICAgICAgICAgICAgICAgICAgaWYgKGFJdGVtLmtleSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGJLZXlzLmhhc093blByb3BlcnR5KGFJdGVtLmtleSkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBNYXRjaCB1cCB0aGUgb2xkIGtleXNcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpdGVtSW5kZXggPSBiS2V5c1thSXRlbS5rZXldO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIG5ld0NoaWxkcmVuLnB1c2goYkNoaWxkcmVuW2l0ZW1JbmRleF0pO1xuICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBSZW1vdmUgb2xkIGtleWVkIGl0ZW1zXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaXRlbUluZGV4ID0gaSAtIGRlbGV0ZWRJdGVtcysrO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIG5ld0NoaWxkcmVuLnB1c2gobnVsbCk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAvLyBNYXRjaCB0aGUgaXRlbSBpbiBhIHdpdGggdGhlIG5leHQgZnJlZSBpdGVtIGluIGJcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChmcmVlSW5kZXggPCBmcmVlQ291bnQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpdGVtSW5kZXggPSBiRnJlZVtmcmVlSW5kZXgrK107XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgbmV3Q2hpbGRyZW4ucHVzaChiQ2hpbGRyZW5baXRlbUluZGV4XSk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIFRoZXJlIGFyZSBubyBmcmVlIGl0ZW1zIGluIGIgdG8gbWF0Y2ggd2l0aFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIHRoZSBmcmVlIGl0ZW1zIGluIGEsIHNvIHRoZSBleHRyYSBmcmVlIG5vZGVzXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gYXJlIGRlbGV0ZWQuXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaXRlbUluZGV4ID0gaSAtIGRlbGV0ZWRJdGVtcysrO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIG5ld0NoaWxkcmVuLnB1c2gobnVsbCk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICB2YXIgbGFzdEZyZWVJbmRleCA9IGZyZWVJbmRleCA+PSBiRnJlZS5sZW5ndGggPyBiQ2hpbGRyZW4ubGVuZ3RoIDogYkZyZWVbZnJlZUluZGV4XTtcblxuICAgICAgICAgICAgICAgIC8vIEl0ZXJhdGUgdGhyb3VnaCBiIGFuZCBhcHBlbmQgYW55IG5ldyBrZXlzXG4gICAgICAgICAgICAgICAgLy8gTyhNKSB0aW1lXG4gICAgICAgICAgICAgICAgZm9yICh2YXIgaiA9IDA7IGogPCBiQ2hpbGRyZW4ubGVuZ3RoOyBqKyspIHtcbiAgICAgICAgICAgICAgICAgICAgdmFyIG5ld0l0ZW0gPSBiQ2hpbGRyZW5bal07XG5cbiAgICAgICAgICAgICAgICAgICAgaWYgKG5ld0l0ZW0ua2V5KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoIWFLZXlzLmhhc093blByb3BlcnR5KG5ld0l0ZW0ua2V5KSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIEFkZCBhbnkgbmV3IGtleWVkIGl0ZW1zXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gV2UgYXJlIGFkZGluZyBuZXcgaXRlbXMgdG8gdGhlIGVuZCBhbmQgdGhlbiBzb3J0aW5nIHRoZW1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBpbiBwbGFjZS4gSW4gZnV0dXJlIHdlIHNob3VsZCBpbnNlcnQgbmV3IGl0ZW1zIGluIHBsYWNlLlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIG5ld0NoaWxkcmVuLnB1c2gobmV3SXRlbSk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoaiA+PSBsYXN0RnJlZUluZGV4KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAvLyBBZGQgYW55IGxlZnRvdmVyIG5vbi1rZXllZCBpdGVtc1xuICAgICAgICAgICAgICAgICAgICAgICAgbmV3Q2hpbGRyZW4ucHVzaChuZXdJdGVtKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHZhciBzaW11bGF0ZSA9IG5ld0NoaWxkcmVuLnNsaWNlKCk7XG4gICAgICAgICAgICAgICAgdmFyIHNpbXVsYXRlSW5kZXggPSAwO1xuICAgICAgICAgICAgICAgIHZhciByZW1vdmVzID0gW107XG4gICAgICAgICAgICAgICAgdmFyIGluc2VydHMgPSBbXTtcbiAgICAgICAgICAgICAgICB2YXIgc2ltdWxhdGVJdGVtO1xuXG4gICAgICAgICAgICAgICAgZm9yICh2YXIgayA9IDA7IGsgPCBiQ2hpbGRyZW4ubGVuZ3RoOykge1xuICAgICAgICAgICAgICAgICAgICB2YXIgd2FudGVkSXRlbSA9IGJDaGlsZHJlbltrXTtcbiAgICAgICAgICAgICAgICAgICAgc2ltdWxhdGVJdGVtID0gc2ltdWxhdGVbc2ltdWxhdGVJbmRleF07XG5cbiAgICAgICAgICAgICAgICAgICAgLy8gcmVtb3ZlIGl0ZW1zXG4gICAgICAgICAgICAgICAgICAgIHdoaWxlIChzaW11bGF0ZUl0ZW0gPT09IG51bGwgJiYgc2ltdWxhdGUubGVuZ3RoKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICByZW1vdmVzLnB1c2gocmVtb3ZlKHNpbXVsYXRlLCBzaW11bGF0ZUluZGV4LCBudWxsKSk7XG4gICAgICAgICAgICAgICAgICAgICAgICBzaW11bGF0ZUl0ZW0gPSBzaW11bGF0ZVtzaW11bGF0ZUluZGV4XTtcbiAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgIGlmICghc2ltdWxhdGVJdGVtIHx8IHNpbXVsYXRlSXRlbS5rZXkgIT09IHdhbnRlZEl0ZW0ua2V5KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAvLyBpZiB3ZSBuZWVkIGEga2V5IGluIHRoaXMgcG9zaXRpb24uLi5cbiAgICAgICAgICAgICAgICAgICAgICAgIGlmICh3YW50ZWRJdGVtLmtleSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChzaW11bGF0ZUl0ZW0gJiYgc2ltdWxhdGVJdGVtLmtleSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBpZiBhbiBpbnNlcnQgZG9lc24ndCBwdXQgdGhpcyBrZXkgaW4gcGxhY2UsIGl0IG5lZWRzIHRvIG1vdmVcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGJLZXlzW3NpbXVsYXRlSXRlbS5rZXldICE9PSBrICsgMSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmVtb3Zlcy5wdXNoKHJlbW92ZShzaW11bGF0ZSwgc2ltdWxhdGVJbmRleCwgc2ltdWxhdGVJdGVtLmtleSkpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc2ltdWxhdGVJdGVtID0gc2ltdWxhdGVbc2ltdWxhdGVJbmRleF07XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBpZiB0aGUgcmVtb3ZlIGRpZG4ndCBwdXQgdGhlIHdhbnRlZCBpdGVtIGluIHBsYWNlLCB3ZSBuZWVkIHRvIGluc2VydCBpdFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKCFzaW11bGF0ZUl0ZW0gfHwgc2ltdWxhdGVJdGVtLmtleSAhPT0gd2FudGVkSXRlbS5rZXkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpbnNlcnRzLnB1c2goeyBrZXk6IHdhbnRlZEl0ZW0ua2V5LCB0bzogayB9KTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIGl0ZW1zIGFyZSBtYXRjaGluZywgc28gc2tpcCBhaGVhZFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc2ltdWxhdGVJbmRleCsrO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaW5zZXJ0cy5wdXNoKHsga2V5OiB3YW50ZWRJdGVtLmtleSwgdG86IGsgfSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpbnNlcnRzLnB1c2goeyBrZXk6IHdhbnRlZEl0ZW0ua2V5LCB0bzogayB9KTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaysrO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgLy8gYSBrZXkgaW4gc2ltdWxhdGUgaGFzIG5vIG1hdGNoaW5nIHdhbnRlZCBrZXksIHJlbW92ZSBpdFxuICAgICAgICAgICAgICAgICAgICAgICAgZWxzZSBpZiAoc2ltdWxhdGVJdGVtICYmIHNpbXVsYXRlSXRlbS5rZXkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICByZW1vdmVzLnB1c2gocmVtb3ZlKHNpbXVsYXRlLCBzaW11bGF0ZUluZGV4LCBzaW11bGF0ZUl0ZW0ua2V5KSk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBzaW11bGF0ZUluZGV4Kys7XG4gICAgICAgICAgICAgICAgICAgICAgICBrKys7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAvLyByZW1vdmUgYWxsIHRoZSByZW1haW5pbmcgbm9kZXMgZnJvbSBzaW11bGF0ZVxuICAgICAgICAgICAgICAgIHdoaWxlIChzaW11bGF0ZUluZGV4IDwgc2ltdWxhdGUubGVuZ3RoKSB7XG4gICAgICAgICAgICAgICAgICAgIHNpbXVsYXRlSXRlbSA9IHNpbXVsYXRlW3NpbXVsYXRlSW5kZXhdO1xuICAgICAgICAgICAgICAgICAgICByZW1vdmVzLnB1c2gocmVtb3ZlKHNpbXVsYXRlLCBzaW11bGF0ZUluZGV4LCBzaW11bGF0ZUl0ZW0gJiYgc2ltdWxhdGVJdGVtLmtleSkpO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIC8vIElmIHRoZSBvbmx5IG1vdmVzIHdlIGhhdmUgYXJlIGRlbGV0ZXMgdGhlbiB3ZSBjYW4ganVzdFxuICAgICAgICAgICAgICAgIC8vIGxldCB0aGUgZGVsZXRlIHBhdGNoIHJlbW92ZSB0aGVzZSBpdGVtcy5cbiAgICAgICAgICAgICAgICBpZiAocmVtb3Zlcy5sZW5ndGggPT09IGRlbGV0ZWRJdGVtcyAmJiAhaW5zZXJ0cy5sZW5ndGgpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGNoaWxkcmVuOiBuZXdDaGlsZHJlbixcbiAgICAgICAgICAgICAgICAgICAgICAgIG1vdmVzOiBudWxsXG4gICAgICAgICAgICAgICAgICAgIH07XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgICAgICAgICAgY2hpbGRyZW46IG5ld0NoaWxkcmVuLFxuICAgICAgICAgICAgICAgICAgICBtb3Zlczoge1xuICAgICAgICAgICAgICAgICAgICAgICAgcmVtb3ZlczogcmVtb3ZlcyxcbiAgICAgICAgICAgICAgICAgICAgICAgIGluc2VydHM6IGluc2VydHNcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH07XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIHJlbW92ZShhcnIsIGluZGV4LCBrZXkpIHtcbiAgICAgICAgICAgICAgICBhcnIuc3BsaWNlKGluZGV4LCAxKTtcblxuICAgICAgICAgICAgICAgIHJldHVybiB7XG4gICAgICAgICAgICAgICAgICAgIGZyb206IGluZGV4LFxuICAgICAgICAgICAgICAgICAgICBrZXk6IGtleVxuICAgICAgICAgICAgICAgIH07XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIGtleUluZGV4KGNoaWxkcmVuKSB7XG4gICAgICAgICAgICAgICAgdmFyIGtleXMgPSB7fTtcbiAgICAgICAgICAgICAgICB2YXIgZnJlZSA9IFtdO1xuICAgICAgICAgICAgICAgIHZhciBsZW5ndGggPSBjaGlsZHJlbi5sZW5ndGg7XG5cbiAgICAgICAgICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IGxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciBjaGlsZCA9IGNoaWxkcmVuW2ldO1xuXG4gICAgICAgICAgICAgICAgICAgIGlmIChjaGlsZC5rZXkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGtleXNbY2hpbGQua2V5XSA9IGk7XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBmcmVlLnB1c2goaSk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgICAgICAgICBrZXlzOiBrZXlzLCAvLyBBIGhhc2ggb2Yga2V5IG5hbWUgdG8gaW5kZXhcbiAgICAgICAgICAgICAgICAgICAgZnJlZTogZnJlZSAvLyBBbiBhcnJheSBvZiB1bmtleWVkIGl0ZW0gaW5kaWNlc1xuICAgICAgICAgICAgICAgIH07XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIGFwcGVuZFBhdGNoKGFwcGx5LCBwYXRjaCkge1xuICAgICAgICAgICAgICAgIGlmIChhcHBseSkge1xuICAgICAgICAgICAgICAgICAgICBpZiAoaXNBcnJheShhcHBseSkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGFwcGx5LnB1c2gocGF0Y2gpO1xuICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgYXBwbHkgPSBbYXBwbHksIHBhdGNoXTtcbiAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBhcHBseTtcbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gcGF0Y2g7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9LCB7IFwiLi4vdm5vZGUvaGFuZGxlLXRodW5rXCI6IDI0LCBcIi4uL3Zub2RlL2lzLXRodW5rXCI6IDI1LCBcIi4uL3Zub2RlL2lzLXZub2RlXCI6IDI3LCBcIi4uL3Zub2RlL2lzLXZ0ZXh0XCI6IDI4LCBcIi4uL3Zub2RlL2lzLXdpZGdldFwiOiAyOSwgXCIuLi92bm9kZS92cGF0Y2hcIjogMzIsIFwiLi9kaWZmLXByb3BzXCI6IDM0LCBcIngtaXMtYXJyYXlcIjogMTIgfV0gfSwge30sIFs0XSkoNCk7XG59KTtcblxuY29uc3QgQ29yZSA9IEM7XG5cbmV4cG9ydCB7IENvcmUsIEVudW0sIFZpcnR1YWxET00gfTsiXSwiZmlsZSI6IkVsaXhpci5qcyIsInNvdXJjZVJvb3QiOiIvc291cmNlLyJ9 \ No newline at end of file diff --git a/src/javascript/lib/core/functions.js b/src/javascript/lib/core/functions.js index abe03fb0..fea6ab41 100644 --- a/src/javascript/lib/core/functions.js +++ b/src/javascript/lib/core/functions.js @@ -1,4 +1,4 @@ -import { PID, Tuple, Integer, Float } from './primitives'; +import { Tuple } from './primitives'; import BitString from './bit_string'; import Patterns from './patterns'; diff --git a/src/javascript/tests/bit_string.spec.js b/src/javascript/tests/bit_string.spec.js index f64d9c67..30a05f44 100644 --- a/src/javascript/tests/bit_string.spec.js +++ b/src/javascript/tests/bit_string.spec.js @@ -1,5 +1,4 @@ var BitString = require('../lib/core').BitString; -var SpecialForms = require('../lib/core').SpecialForms; var Patterns = require('../lib/core').Patterns; var expect = require('chai').expect; @@ -11,19 +10,19 @@ describe('BitString', function(){ describe('creation', function(){ it('create properly', function(){ - let bs = SpecialForms.bitstring(BitString.integer(1)); + let bs = new BitString(BitString.integer(1)); expect(is_match(bs.value, [1])).to.equal(true); - bs = SpecialForms.bitstring(BitString.binary("foo")); + bs = new BitString(BitString.binary("foo")); expect(is_match(bs.value, [102, 111, 111])).to.equal(true); - bs = SpecialForms.bitstring(BitString.integer(0), BitString.binary("foo")); + bs = new BitString(BitString.integer(0), BitString.binary("foo")); expect(is_match(bs.value, [0, 102, 111, 111])).to.equal(true); - bs = SpecialForms.bitstring(BitString.float(3.14)); + bs = new BitString(BitString.float(3.14)); expect(is_match(bs.value, [64, 9, 30, 184, 81, 235, 133, 31])).to.equal(true); - bs = SpecialForms.bitstring(BitString.signed(BitString.integer(-100))); + bs = new BitString(BitString.signed(BitString.integer(-100))); expect(is_match(bs.value, [156])).to.equal(true); }); }); diff --git a/src/javascript/tests/case.spec.js b/src/javascript/tests/case.spec.js index 366ce313..6224157a 100644 --- a/src/javascript/tests/case.spec.js +++ b/src/javascript/tests/case.spec.js @@ -1,5 +1,6 @@ var Patterns = require("../lib/core/patterns"); var Enum = require('../lib/enum'); +var Tuple = require('../lib/core').Tuple; var SpecialForms = require('../lib/core').SpecialForms; var expect = require('chai').expect; @@ -9,7 +10,7 @@ describe('case', () => { it('case', () => { let clauses = [ Patterns.make_case( - [SpecialForms.tuple(Symbol.for("selector"), Patterns.variable(), Patterns.variable())], + [new Tuple(Symbol.for("selector"), Patterns.variable(), Patterns.variable())], function(i, value){ return value; }, function(i){ return Kernel.is_integer(i); } ), diff --git a/src/javascript/tests/special_forms.spec.js b/src/javascript/tests/special_forms.spec.js index 8d628e7b..f4dc1434 100644 --- a/src/javascript/tests/special_forms.spec.js +++ b/src/javascript/tests/special_forms.spec.js @@ -5,7 +5,7 @@ describe('SpecialForms', function(){ describe('map_update', function(){ it('creates new object', function(){ - const foo = SpecialForms.map({foo: "bar", fizz: "buzz"}); + const foo = Object.freeze({foo: "bar", fizz: "buzz"}); const bar = SpecialForms.map_update(foo, {baz: "bar", fizz: "fizzbuzz"}); expect(foo instanceof Object).to.equal(bar instanceof Object); From a012dc6238b47540ee49152d9c8a562e04431dad Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Tue, 5 Jan 2016 22:07:35 -0600 Subject: [PATCH 117/860] More refactoring. Added support for multi alias/require/imports --- lib/elixir_script.ex | 30 ++++++++++++--------------- lib/elixir_script/translator.ex | 36 +++++++++++++++++++++++++++++++++ 2 files changed, 49 insertions(+), 17 deletions(-) diff --git a/lib/elixir_script.ex b/lib/elixir_script.ex index 472ef8e8..51787a09 100644 --- a/lib/elixir_script.ex +++ b/lib/elixir_script.ex @@ -2,6 +2,7 @@ defmodule ElixirScript do alias ESTree.Tools.Builder alias ESTree.Tools.Generator alias ElixirScript.Translator.Utils + alias ElixirScript.Translator.ModuleCollector @moduledoc """ Translates Elixir into JavaScript. @@ -39,6 +40,8 @@ defmodule ElixirScript do |> Code.string_to_quoted! end) + @js_core_path "/Elixir.js" + @doc """ Compiles the given Elixir code string """ @@ -61,7 +64,8 @@ defmodule ElixirScript do libs = @libs |> updated_quoted - build_environment(libs ++ [updated_quoted(quoted)]) + ModuleCollector.process_modules(libs ++ [updated_quoted(quoted)]) + create_code(compiler_opts) end @@ -81,7 +85,8 @@ defmodule ElixirScript do |> Path.wildcard |> Enum.map(&file_to_quoted/1) - build_environment(libs ++ code) + + ModuleCollector.process_modules(libs ++ code) create_code(compiler_opts) end @@ -104,11 +109,6 @@ defmodule ElixirScript do |> updated_quoted end - defp build_environment(code_list) do - code_list - |> ElixirScript.Translator.ModuleCollector.process_modules - end - defp updated_quoted(quoted) do Macro.prewalk(quoted, fn ({name, context, parms}) -> @@ -168,14 +168,14 @@ defmodule ElixirScript do to the specified location """ def copy_standard_libs_to_destination(destination) do - File.cp!(operating_path <> "/Elixir.js", destination <> "/Elixir.js") + File.cp!(operating_path <> @js_core_path, destination <> @js_core_path) end @doc """ Returns the standard lib js code """ def standard_libs() do - File.read!(operating_path <> "/Elixir.js") + File.read!(operating_path <> @js_core_path) end defp convert_to_code(js_ast) do @@ -186,20 +186,16 @@ defmodule ElixirScript do defp process_module(module) do file_path = Utils.name_to_js_file_name(module.name) <> ".js" - { file_path, ESTree.Tools.Builder.program(module.body) } + { file_path, Builder.program(module.body) } end @doc false def javascript_ast_to_code({path, js_ast}) do - js_code = javascript_ast_to_code(js_ast) - {path, js_code} - end - - @doc false - def javascript_ast_to_code(js_ast) do - js_ast + js_code = js_ast |> prepare_js_ast |> Generator.generate + + {path, js_code} end defp prepare_js_ast(js_ast) do diff --git a/lib/elixir_script/translator.ex b/lib/elixir_script/translator.ex index e3ade1ce..35b89f47 100644 --- a/lib/elixir_script/translator.ex +++ b/lib/elixir_script/translator.ex @@ -304,6 +304,18 @@ defmodule ElixirScript.Translator do { Quote.make_quote(opts, expr, env), env } end + defp do_translate({:import, _, [{{:., _, [{:__aliases__, _, head_import_name}, :{}]}, _, tail_imports }]}, env) do + env = Enum.reduce(tail_imports, env, fn({:__aliases__, context, name}, acc) -> + full_module_name = { :__aliases__, context, head_import_name ++ name } + + module_name = Utils.quoted_to_name(full_module_name) + ElixirScript.Translator.Env.add_import(acc, module_name) + end) + + { %ElixirScript.Translator.Group{}, env } + end + + defp do_translate({:import, _, [{:__aliases__, _, _} = module_name]}, env) do env = ElixirScript.Translator.Env.add_import(env, module_name) { %ElixirScript.Translator.Group{}, env } @@ -317,6 +329,19 @@ defmodule ElixirScript.Translator do { %ElixirScript.Translator.Group{}, env } end + defp do_translate({:alias, _, [{{:., _, [{:__aliases__, _, head_alias_name}, :{}]}, _, tail_aliases }]}, env) do + env = Enum.reduce(tail_aliases, env, fn({:__aliases__, context, name}, acc) -> + full_module_name = { :__aliases__, context, head_alias_name ++ name } + + module_name = Utils.quoted_to_name(full_module_name) + alias_name = Utils.quoted_to_name({:__aliases__, [], [List.last(name)] }) + + ElixirScript.Translator.Env.add_alias(acc, module_name, alias_name) + end) + + { %ElixirScript.Translator.Group{}, env } + end + defp do_translate({:alias, _, [{:__aliases__, _, _} = module_name] }, env) do {_, _, name} = module_name name = [List.last(name)] @@ -336,6 +361,17 @@ defmodule ElixirScript.Translator do { %ElixirScript.Translator.Group{}, env } end + defp do_translate({:require, _, [{{:., _, [{:__aliases__, _, head_require_name}, :{}]}, _, tail_requires }]}, env) do + env = Enum.reduce(tail_requires, env, fn({:__aliases__, context, name}, acc) -> + full_module_name = { :__aliases__, context, head_require_name ++ name } + + module_name = Utils.quoted_to_name(full_module_name) + ElixirScript.Translator.Env.add_require(acc, module_name) + end) + + { %ElixirScript.Translator.Group{}, env } + end + defp do_translate({:require, _, [{:__aliases__, _, _} = module_name] }, env) do module_name = Utils.quoted_to_name(module_name) env = ElixirScript.Translator.Env.add_require(env, module_name) From 84f764e1bb931efc5d5fbfbc29ec8e8ca768d83a Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Sun, 10 Jan 2016 20:21:44 -0600 Subject: [PATCH 118/860] Added enumerable protocol. Updated changelog --- CHANGELOG.md | 1 + lib/elixir_script/prelude/enumerable.ex | 5 +++++ 2 files changed, 6 insertions(+) create mode 100644 lib/elixir_script/prelude/enumerable.ex diff --git a/CHANGELOG.md b/CHANGELOG.md index 134a13e6..983af435 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,7 @@ * `__ENV__` and `__CALLER__` are now supported * Began writing some of the standard libraries in Elixir instead of JavaScript * Added `JS.import/1` + * Added support for multi alias/require/imports statements * Breaking * `compile`, `compile_path`, and `compile_quoted` opts parameter now expects a map diff --git a/lib/elixir_script/prelude/enumerable.ex b/lib/elixir_script/prelude/enumerable.ex new file mode 100644 index 00000000..ab04c59b --- /dev/null +++ b/lib/elixir_script/prelude/enumerable.ex @@ -0,0 +1,5 @@ +defprotocol ElixirScript.Enumerable do + def reduce(enumerable, acc, fun) + def member?(enumerable, element) + def count(enumerable) +end From 2a61c9f3415182655ec2b9f83e068af541205d80 Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Wed, 13 Jan 2016 14:56:10 -0600 Subject: [PATCH 119/860] Updated translator to translated external resource attribute used in html module --- lib/elixir_script/cli.ex | 7 ++++--- lib/elixir_script/prelude/html.ex | 1 + lib/elixir_script/prelude/tuple.ex | 8 ++++---- lib/elixir_script/translator.ex | 6 +++++- lib/elixir_script/translator/for.ex | 2 +- 5 files changed, 15 insertions(+), 9 deletions(-) diff --git a/lib/elixir_script/cli.ex b/lib/elixir_script/cli.ex index 400469aa..be69456a 100644 --- a/lib/elixir_script/cli.ex +++ b/lib/elixir_script/cli.ex @@ -72,11 +72,12 @@ defmodule ElixirScript.CLI do case options[:output] do nil -> - Enum.each(compile_output, + Enum.map(compile_output, fn - ({_path, code})-> IO.write(code) - (code)-> IO.write(code) + ({_path, code})-> code + (code)-> code end) + |> IO.write output_path -> Enum.each(compile_output, fn(x) -> write_to_file(x, output_path) diff --git a/lib/elixir_script/prelude/html.ex b/lib/elixir_script/prelude/html.ex index e2f3f35d..4a5610d2 100644 --- a/lib/elixir_script/prelude/html.ex +++ b/lib/elixir_script/prelude/html.ex @@ -24,6 +24,7 @@ defmodule ElixirScript.Html do """ @external_resource tags_path = Path.join([__DIR__, "tags.txt"]) + @tags (for line <- File.stream!(tags_path, [], :line) do line |> String.strip |> String.to_atom end) diff --git a/lib/elixir_script/prelude/tuple.ex b/lib/elixir_script/prelude/tuple.ex index e0896ad7..d5f98b00 100644 --- a/lib/elixir_script/prelude/tuple.ex +++ b/lib/elixir_script/prelude/tuple.ex @@ -36,10 +36,10 @@ defmodule ElixirScript.Tuple do end def delete_at(tuple, index) do - JS.new(Elixir.Core.Tuple, delete_at(tuple, index, 0, [])) + JS.new(Elixir.Core.Tuple, do_delete_at(tuple, index, 0, [])) end - defp delete_at(tuple, index, current_index, list) do + defp do_delete_at(tuple, index, current_index, list) do if current_index == length(tuple) do list else @@ -50,12 +50,12 @@ defmodule ElixirScript.Tuple do list ++ [tuple.get(current_index)] end - delete_at(tuple, index, current_index + 1, list) + do_delete_at(tuple, index, current_index + 1, list) end end def append(tuple, value) do - #JS.new(Elixir.Core.Tuple, to_list(tuple) ++ [value]) + JS.new(Elixir.Core.Tuple, to_list(tuple) ++ [value]) end end diff --git a/lib/elixir_script/translator.ex b/lib/elixir_script/translator.ex index 35b89f47..51c77e14 100644 --- a/lib/elixir_script/translator.ex +++ b/lib/elixir_script/translator.ex @@ -139,10 +139,14 @@ defmodule ElixirScript.Translator do end defp do_translate({:@, _, [{name, _, _}]}, env) - when name in [:doc, :moduledoc, :type, :typep, :spec, :opaque, :callback, :macrocallback] do + when name in [:doc, :moduledoc, :type, :typep, :spec, :opaque, :callback, :macrocallback, :after_compile, :before_compile, :behaviour, :compile, :file, :on_definition, :on_load, :dialyzer, :vsn] do { %ElixirScript.Translator.Group{}, env } end + defp do_translate({:@, _, [{:external_resource, _, [param]}]}, env) do + translate(param, env) + end + defp do_translate({:@, _, [{name, _, [value]}]}, env) do name = Utils.filter_name(name) { Module.make_attribute(name, value, env), env } diff --git a/lib/elixir_script/translator/for.ex b/lib/elixir_script/translator/for.ex index 40d0d24a..b6fecb64 100644 --- a/lib/elixir_script/translator/for.ex +++ b/lib/elixir_script/translator/for.ex @@ -28,7 +28,7 @@ defmodule ElixirScript.Translator.For do defp handle_args(generators, env) do Enum.reduce(generators, %{collections: [], args: [], filter: nil, fun: nil, into: nil}, fn - ({:<-, [], [identifier, enum]}, state) -> + ({:<-, _, [identifier, enum]}, state) -> { patterns, params, env } = PatternMatching.process_match([identifier], env) list = Primitive.make_list_no_translate([hd(patterns), Translator.translate!(enum, env)]) From 75fff10023c93261acd3cb6af7ad69600b767420 Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Wed, 13 Jan 2016 15:13:30 -0600 Subject: [PATCH 120/860] Removed prelude files with unsupported features from transpilation --- lib/elixir_script.ex | 14 ++++++++++---- lib/elixir_script/translator.ex | 6 +----- 2 files changed, 11 insertions(+), 9 deletions(-) diff --git a/lib/elixir_script.ex b/lib/elixir_script.ex index 51787a09..fb06d2d4 100644 --- a/lib/elixir_script.ex +++ b/lib/elixir_script.ex @@ -33,12 +33,18 @@ defmodule ElixirScript do end end + # These are full of macros and would not transpile to anything significant + @modules_to_not_read ["v_dom.ex", "html.ex"] + @external_resource libs_path = Path.join([__DIR__, "elixir_script", "prelude", "**", "*.ex"]) - @libs (for path <- Path.wildcard(libs_path) do - path - |> File.read! - |> Code.string_to_quoted! + @libs Enum.filter(Path.wildcard(libs_path), fn(path) -> + !String.contains?(path, @modules_to_not_read) end) + |> Enum.map(fn(path) -> + path + |> File.read! + |> Code.string_to_quoted! + end) @js_core_path "/Elixir.js" diff --git a/lib/elixir_script/translator.ex b/lib/elixir_script/translator.ex index 51c77e14..56b3ae7c 100644 --- a/lib/elixir_script/translator.ex +++ b/lib/elixir_script/translator.ex @@ -139,14 +139,10 @@ defmodule ElixirScript.Translator do end defp do_translate({:@, _, [{name, _, _}]}, env) - when name in [:doc, :moduledoc, :type, :typep, :spec, :opaque, :callback, :macrocallback, :after_compile, :before_compile, :behaviour, :compile, :file, :on_definition, :on_load, :dialyzer, :vsn] do + when name in [:doc, :moduledoc, :type, :typep, :spec, :opaque, :callback, :macrocallback, :after_compile, :before_compile, :behaviour, :compile, :file, :on_definition, :on_load, :dialyzer, :vsn, :external_resource] do { %ElixirScript.Translator.Group{}, env } end - defp do_translate({:@, _, [{:external_resource, _, [param]}]}, env) do - translate(param, env) - end - defp do_translate({:@, _, [{name, _, [value]}]}, env) do name = Utils.filter_name(name) { Module.make_attribute(name, value, env), env } From dda91147f77ebc14cb7a44aeffbd6315687442cc Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Thu, 14 Jan 2016 21:08:47 -0600 Subject: [PATCH 121/860] Added file delimiters for standard output --- lib/elixir_script/cli.ex | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/lib/elixir_script/cli.ex b/lib/elixir_script/cli.ex index be69456a..d2eb0b57 100644 --- a/lib/elixir_script/cli.ex +++ b/lib/elixir_script/cli.ex @@ -59,7 +59,7 @@ defmodule ElixirScript.CLI do def do_process(input, options) do compile_opts = %{ root: options[:root], - include_path: options[:output] != nil, + include_path: true, stdlib_path: Keyword.get(options, :stdlib_path, "Elixir") } @@ -74,9 +74,9 @@ defmodule ElixirScript.CLI do nil -> Enum.map(compile_output, fn - ({_path, code})-> code - (code)-> code + ({path, code})-> "//#{path}:ENDFILENAME\n" <> code end) + |> Enum.join("//:ENDFILE\n") |> IO.write output_path -> Enum.each(compile_output, fn(x) -> From 1773cc50782131df833f8db2934d6102b9c92e5e Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Fri, 15 Jan 2016 18:28:51 -0600 Subject: [PATCH 122/860] Modules now use export default declarations. Fixes #138 --- CHANGELOG.md | 1 + lib/elixir_script/translator/import.ex | 2 +- lib/elixir_script/translator/module.ex | 2 +- priv/Elixir.js | 5142 ++++++++++++------------ src/javascript/elixir.js | 12 +- src/javascript/lib/core.js | 2 +- src/javascript/lib/enum.js | 2 +- test/elixir_script_test.exs | 34 +- test/translator/bug_test.exs | 4 +- test/translator/defmodule_test.exs | 74 +- test/translator/function_test.exs | 20 +- test/translator/protocol_test.exs | 2 +- test/translator/struct_test.exs | 28 +- 13 files changed, 2666 insertions(+), 2659 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 983af435..4e0d45de 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,7 @@ * Began writing some of the standard libraries in Elixir instead of JavaScript * Added `JS.import/1` * Added support for multi alias/require/imports statements + * exports are now default exports * Breaking * `compile`, `compile_path`, and `compile_quoted` opts parameter now expects a map diff --git a/lib/elixir_script/translator/import.ex b/lib/elixir_script/translator/import.ex index f0e24bcc..18f24580 100644 --- a/lib/elixir_script/translator/import.ex +++ b/lib/elixir_script/translator/import.ex @@ -14,7 +14,7 @@ defmodule ElixirScript.Translator.Import do defp do_make_import(import_name, file_name) do root = ElixirScript.Translator.State.get().compiler_opts.root - import_specifier = JS.import_namespace_specifier( + import_specifier = JS.import_default_specifier( JS.identifier(import_name) ) diff --git a/lib/elixir_script/translator/module.ex b/lib/elixir_script/translator/module.ex index 0be24ff5..c49313ab 100644 --- a/lib/elixir_script/translator/module.ex +++ b/lib/elixir_script/translator/module.ex @@ -50,7 +50,7 @@ defmodule ElixirScript.Translator.Module do exported_functions = Enum.map(exported_functions, fn({_key, value}) -> value end) private_functions = Enum.map(private_functions, fn({_key, value}) -> value end) - default = JS.export_named_declaration(exported_object) + default = JS.export_default_declaration(exported_object) result = %{ name: Utils.quoted_to_name({:__aliases__, [], module }), diff --git a/priv/Elixir.js b/priv/Elixir.js index 5e0e0c26..02168c36 100644 --- a/priv/Elixir.js +++ b/priv/Elixir.js @@ -1,3159 +1,3161 @@ -/* @flow */ - -class Mailbox { - - constructor() { - this.messages = []; - } - - deliver(message) { - this.messages.push(message); - return message; - } - - get() { - return this.messages; - } - - isEmpty() { - return this.messages.length === 0; - } - - removeAt(index) { - this.messages.splice(index, 1); - } -} - -var States = { - NORMAL: Symbol.for("normal"), - KILL: Symbol.for("kill"), - SUSPEND: Symbol.for("suspend"), - CONTINUE: Symbol.for("continue"), - RECEIVE: Symbol.for("receive"), - SEND: Symbol.for("send"), - SLEEPING: Symbol.for("sleeping"), - RUNNING: Symbol.for("running"), - SUSPENDED: Symbol.for("suspended"), - STOPPED: Symbol.for("stopped"), - SLEEP: Symbol.for("sleep"), - EXIT: Symbol.for("exit"), - NOMATCH: Symbol.for("no_match") -}; - -class Process { - - constructor(pid, mailbox) { - this.pid = pid; - this.mailbox = mailbox; - this.status = States.STOPPED; - this.dict = {}; - } -} - -class Tuple { - - constructor(...args) { - this.values = Object.freeze(args); - this.length = this.values.length; - } - - get(index) { - return this.values[index]; - } - - count() { - return this.values.length; - } - - [Symbol.iterator]() { - return this.values[Symbol.iterator](); - } - - toString() { - var i, - s = ""; - for (i = 0; i < this.values.length; i++) { - if (s !== "") { - s += ", "; - } - s += this.values[i].toString(); - } - - return "{" + s + "}"; - } - -} - -let process_counter = -1; +let VirtualDOM = (function (e) { + return e(); +})(function () { + var define, module, exports; + return (function e(t, n, r) { + function s(o, u) { + if (!n[o]) { + if (!t[o]) { + var a = typeof require == "function" && require; + if (!u && a) return a(o, !0); + if (i) return i(o, !0); + var f = new Error("Cannot find module '" + o + "'"); + throw (f.code = "MODULE_NOT_FOUND", f); + } + var l = n[o] = { + exports: {} + }; + t[o][0].call(l.exports, function (e) { + var n = t[o][1][e]; + return s(n ? n : e); + }, l, l.exports, e, t, n, r); + } + return n[o].exports; + } + var i = typeof require == "function" && require; + for (var o = 0; o < r.length; o++) s(r[o]); + return s; + })({ + 1: [function (require, module, exports) { -class PID { - constructor() { - process_counter = process_counter + 1; - this.id = process_counter; - } + var createElement = require("./vdom/create-element.js"); - toString() { - return "PID#<0." + this.id + ".0>"; - } -} + module.exports = createElement; + }, { "./vdom/create-element.js": 15 }], 2: [function (require, module, exports) { + var diff = require("./vtree/diff.js"); -class Integer {} -class Float {} + module.exports = diff; + }, { "./vtree/diff.js": 35 }], 3: [function (require, module, exports) { + var h = require("./virtual-hyperscript/index.js"); -class ProcessSystem { + module.exports = h; + }, { "./virtual-hyperscript/index.js": 22 }], 4: [function (require, module, exports) { + var diff = require("./diff.js"); + var patch = require("./patch.js"); + var h = require("./h.js"); + var create = require("./create-element.js"); + var VNode = require("./vnode/vnode.js"); + var VText = require("./vnode/vtext.js"); - constructor() { - this.pids = new Map(); - this.mailboxes = new Map(); - this.names = new Map(); - this.links = new Map(); + module.exports = { + diff: diff, + patch: patch, + h: h, + create: create, + VNode: VNode, + VText: VText + }; + }, { "./create-element.js": 1, "./diff.js": 2, "./h.js": 3, "./patch.js": 13, "./vnode/vnode.js": 31, "./vnode/vtext.js": 33 }], 5: [function (require, module, exports) { + /*! + * Cross-Browser Split 1.1.1 + * Copyright 2007-2012 Steven Levithan + * Available under the MIT License + * ECMAScript compliant, uniform cross-browser split method + */ - this.current_process = null; - this.suspended = new Map(); + /** + * Splits a string into an array of strings using a regex or string separator. Matches of the + * separator are not included in the result array. However, if `separator` is a regex that contains + * capturing groups, backreferences are spliced into the result each time `separator` is matched. + * Fixes browser bugs compared to the native `String.prototype.split` and can be used reliably + * cross-browser. + * @param {String} str String to split. + * @param {RegExp|String} separator Regex or string to use for separating the string. + * @param {Number} [limit] Maximum number of items to include in the result array. + * @returns {Array} Array of substrings. + * @example + * + * // Basic use + * split('a b c d', ' '); + * // -> ['a', 'b', 'c', 'd'] + * + * // With limit + * split('a b c d', ' ', 2); + * // -> ['a', 'b'] + * + * // Backreferences in result array + * split('..word1 word2..', /([a-z]+)(\d+)/i); + * // -> ['..', 'word', '1', ' ', 'word', '2', '..'] + */ + module.exports = (function split(undef) { - this.main_process_pid = this.spawn(); - this.set_current(this.main_process_pid); - } + var nativeSplit = String.prototype.split, + compliantExecNpcg = /()??/.exec("")[1] === undef, - spawn() { - return this.add_proc(false).pid; - } + // NPCG: nonparticipating capturing group + self; - spawn_link() { - return this.add_proc(true).pid; - } + self = function (str, separator, limit) { + // If `separator` is not a regex, use `nativeSplit` + if (Object.prototype.toString.call(separator) !== "[object RegExp]") { + return nativeSplit.call(str, separator, limit); + } + var output = [], + flags = (separator.ignoreCase ? "i" : "") + (separator.multiline ? "m" : "") + (separator.extended ? "x" : "") + (separator.sticky ? "y" : ""), - link(pid) { - this.links.get(this.pid()).add(pid); - this.links.get(pid).add(this.pid()); - } + // Firefox 3+ + lastLastIndex = 0, - unlink(pid) { - this.links.get(this.pid()).delete(pid); - this.links.get(pid).delete(this.pid()); - } + // Make `global` and avoid `lastIndex` issues by working with a copy + separator = new RegExp(separator.source, flags + "g"), + separator2, + match, + lastIndex, + lastLength; + str += ""; // Type-convert + if (!compliantExecNpcg) { + // Doesn't need flags gy, but they don't hurt + separator2 = new RegExp("^" + separator.source + "$(?!\\s)", flags); + } + /* Values for `limit`, per the spec: + * If undefined: 4294967295 // Math.pow(2, 32) - 1 + * If 0, Infinity, or NaN: 0 + * If positive number: limit = Math.floor(limit); if (limit > 4294967295) limit -= 4294967296; + * If negative number: 4294967296 - Math.floor(Math.abs(limit)) + * If other: Type-convert, then use the above rules + */ + limit = limit === undef ? -1 >>> 0 : // Math.pow(2, 32) - 1 + limit >>> 0; // ToUint32(limit) + while (match = separator.exec(str)) { + // `separator.lastIndex` is not reliable cross-browser + lastIndex = match.index + match[0].length; + if (lastIndex > lastLastIndex) { + output.push(str.slice(lastLastIndex, match.index)); + // Fix browsers whose `exec` methods don't consistently return `undefined` for + // nonparticipating capturing groups + if (!compliantExecNpcg && match.length > 1) { + match[0].replace(separator2, function () { + for (var i = 1; i < arguments.length - 2; i++) { + if (arguments[i] === undef) { + match[i] = undef; + } + } + }); + } + if (match.length > 1 && match.index < str.length) { + Array.prototype.push.apply(output, match.slice(1)); + } + lastLength = match[0].length; + lastLastIndex = lastIndex; + if (output.length >= limit) { + break; + } + } + if (separator.lastIndex === match.index) { + separator.lastIndex++; // Avoid an infinite loop + } + } + if (lastLastIndex === str.length) { + if (lastLength || !separator.test("")) { + output.push(""); + } + } else { + output.push(str.slice(lastLastIndex)); + } + return output.length > limit ? output.slice(0, limit) : output; + }; - set_current(id) { - let pid = this.pidof(id); - if (pid !== null) { - this.current_process = this.pids.get(pid); - this.current_process.status = States.RUNNING; - } - } + return self; + })(); + }, {}], 6: [function (require, module, exports) {}, {}], 7: [function (require, module, exports) { + "use strict"; - add_proc(linked) { - let newpid = new PID(); - let mailbox = new Mailbox(); - let newproc = new Process(newpid, mailbox); + var OneVersionConstraint = require("individual/one-version"); - this.pids.set(newpid, newproc); - this.mailboxes.set(newpid, mailbox); - this.links.set(newpid, new Set()); + var MY_VERSION = "7"; + OneVersionConstraint("ev-store", MY_VERSION); - if (linked) { - this.link(newpid); - } + var hashKey = "__EV_STORE_KEY@" + MY_VERSION; - return newproc; - } + module.exports = EvStore; - remove_proc(pid) { - this.pids.delete(pid); - this.unregister(pid); + function EvStore(elem) { + var hash = elem[hashKey]; - if (this.links.has(pid)) { - for (let linkpid of this.links.get(pid)) { - this.links.get(linkpid).delete(pid); - } + if (!hash) { + hash = elem[hashKey] = {}; + } - this.links.delete(pid); - } - } + return hash; + } + }, { "individual/one-version": 9 }], 8: [function (require, module, exports) { + (function (global) { + "use strict"; - exit(id) { - let pid = this.pidof(id); - this.remove_proc(id); - } + /*global window, global*/ - register(name, pid) { - if (!this.names.has(name)) { - this.names.set(name, pid); - return name; - } else { - throw new Error("Name is already registered to another process"); - } - } + var root = typeof window !== "undefined" ? window : typeof global !== "undefined" ? global : {}; - registered(name) { - return this.names.has(name) ? this.names.get(name) : null; - } + module.exports = Individual; - unregister(pid) { - for (let name of this.names.keys()) { - if (this.names.has(name) && this.names.get(name) === pid) { - this.names.delete(name); - } - } - } + function Individual(key, value) { + if (key in root) { + return root[key]; + } - pid() { - return this.current_process.pid; - } + root[key] = value; - pidof(id) { - if (id instanceof PID) { - return this.pids.has(id) ? id : null; - } else if (id instanceof Process) { - return id.pid; - } else { - let pid = this.registered(id); - if (pid === null) throw "Process name not registered: " + id + " (" + typeof id + ")"; - return pid; - } - } + return value; + } + }).call(this, typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}); + }, {}], 9: [function (require, module, exports) { + "use strict"; - put(id, key, value) { - let pid = this.pidof(id); - let process = this.pids.get(pid); - process.dict[key] = value; - } + var Individual = require("./index.js"); - get(id, key) { - let pid = this.pidof(id); - let process = this.pids.get(pid); + module.exports = OneVersion; - if (key != null) { - return process.dict[key]; - } else { - return process.dict; - } - } + function OneVersion(moduleName, version, defaultValue) { + var key = "__INDIVIDUAL_ONE_VERSION_" + moduleName; + var enforceKey = key + "_ENFORCE_SINGLETON"; - get_keys(id) { - let pid = this.pidof(id); - let process = this.pids.get(pid); + var versionValue = Individual(enforceKey, version); - return Object.keys(process.dict); - } + if (versionValue !== version) { + throw new Error("Can only have one copy of " + moduleName + ".\n" + "You already have version " + versionValue + " installed.\n" + "This means you cannot install version " + version); + } - erase(id, key) { - let pid = this.pidof(id); - let process = this.pids.get(pid); + return Individual(key, defaultValue); + } + }, { "./index.js": 8 }], 10: [function (require, module, exports) { + (function (global) { + var topLevel = typeof global !== "undefined" ? global : typeof window !== "undefined" ? window : {}; + var minDoc = require("min-document"); - if (key != null) { - delete process.dict[key]; - } else { - process.dict = {}; - } - } -} + if (typeof document !== "undefined") { + module.exports = document; + } else { + var doccy = topLevel["__GLOBAL_DOCUMENT_CACHE@4"]; -class BitString { - constructor(...args) { - this.raw_value = function () { - return Object.freeze(args); - }; + if (!doccy) { + doccy = topLevel["__GLOBAL_DOCUMENT_CACHE@4"] = minDoc; + } - this.value = Object.freeze(this.process(args)); - } + module.exports = doccy; + } + }).call(this, typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}); + }, { "min-document": 6 }], 11: [function (require, module, exports) { + "use strict"; - get(index) { - return this.value[index]; - } + module.exports = function isObject(x) { + return typeof x === "object" && x !== null; + }; + }, {}], 12: [function (require, module, exports) { + var nativeIsArray = Array.isArray; + var toString = Object.prototype.toString; - count() { - return this.value.length; - } + module.exports = nativeIsArray || isArray; - [Symbol.iterator]() { - return this.value[Symbol.iterator](); - } + function isArray(obj) { + return toString.call(obj) === "[object Array]"; + } + }, {}], 13: [function (require, module, exports) { + var patch = require("./vdom/patch.js"); - toString() { - var i, - s = ""; - for (i = 0; i < this.count(); i++) { - if (s !== "") { - s += ", "; - } - s += this[i].toString(); - } + module.exports = patch; + }, { "./vdom/patch.js": 18 }], 14: [function (require, module, exports) { + var isObject = require("is-object"); + var isHook = require("../vnode/is-vhook.js"); - return "<<" + s + ">>"; - } + module.exports = applyProperties; - process() { - let processed_values = []; + function applyProperties(node, props, previous) { + for (var propName in props) { + var propValue = props[propName]; - var i; - for (i = 0; i < this.raw_value().length; i++) { - let processed_value = this["process_" + this.raw_value()[i].type](this.raw_value()[i]); + if (propValue === undefined) { + removeProperty(node, propName, propValue, previous); + } else if (isHook(propValue)) { + removeProperty(node, propName, propValue, previous); + if (propValue.hook) { + propValue.hook(node, propName, previous ? previous[propName] : undefined); + } + } else { + if (isObject(propValue)) { + patchObject(node, props, previous, propName, propValue); + } else { + node[propName] = propValue; + } + } + } + } - for (let attr of this.raw_value()[i].attributes) { - processed_value = this["process_" + attr](processed_value); - } + function removeProperty(node, propName, propValue, previous) { + if (previous) { + var previousValue = previous[propName]; - processed_values = processed_values.concat(processed_value); - } + if (!isHook(previousValue)) { + if (propName === "attributes") { + for (var attrName in previousValue) { + node.removeAttribute(attrName); + } + } else if (propName === "style") { + for (var i in previousValue) { + node.style[i] = ""; + } + } else if (typeof previousValue === "string") { + node[propName] = ""; + } else { + node[propName] = null; + } + } else if (previousValue.unhook) { + previousValue.unhook(node, propName, propValue); + } + } + } - return processed_values; - } + function patchObject(node, props, previous, propName, propValue) { + var previousValue = previous ? previous[propName] : undefined; - process_integer(value) { - return value.value; - } + // Set attributes + if (propName === "attributes") { + for (var attrName in propValue) { + var attrValue = propValue[attrName]; - process_float(value) { - if (value.size === 64) { - return BitString.float64ToBytes(value.value); - } else if (value.size === 32) { - return BitString.float32ToBytes(value.value); - } + if (attrValue === undefined) { + node.removeAttribute(attrName); + } else { + node.setAttribute(attrName, attrValue); + } + } - throw new Error("Invalid size for float"); - } + return; + } - process_bitstring(value) { - return value.value.value; - } + if (previousValue && isObject(previousValue) && getPrototype(previousValue) !== getPrototype(propValue)) { + node[propName] = propValue; + return; + } - process_binary(value) { - return BitString.toUTF8Array(value.value); - } + if (!isObject(node[propName])) { + node[propName] = {}; + } - process_utf8(value) { - return BitString.toUTF8Array(value.value); - } + var replacer = propName === "style" ? "" : undefined; - process_utf16(value) { - return BitString.toUTF16Array(value.value); - } + for (var k in propValue) { + var value = propValue[k]; + node[propName][k] = value === undefined ? replacer : value; + } + } - process_utf32(value) { - return BitString.toUTF32Array(value.value); - } + function getPrototype(value) { + if (Object.getPrototypeOf) { + return Object.getPrototypeOf(value); + } else if (value.__proto__) { + return value.__proto__; + } else if (value.constructor) { + return value.constructor.prototype; + } + } + }, { "../vnode/is-vhook.js": 26, "is-object": 11 }], 15: [function (require, module, exports) { + var document = require("global/document"); - process_signed(value) { - return new Uint8Array([value])[0]; - } + var applyProperties = require("./apply-properties"); - process_unsigned(value) { - return value; - } + var isVNode = require("../vnode/is-vnode.js"); + var isVText = require("../vnode/is-vtext.js"); + var isWidget = require("../vnode/is-widget.js"); + var handleThunk = require("../vnode/handle-thunk.js"); - process_native(value) { - return value; - } + module.exports = createElement; - process_big(value) { - return value; - } + function createElement(vnode, opts) { + var doc = opts ? opts.document || document : document; + var warn = opts ? opts.warn : null; - process_little(value) { - return value.reverse(); - } + vnode = handleThunk(vnode).a; - process_size(value) { - return value; - } + if (isWidget(vnode)) { + return vnode.init(); + } else if (isVText(vnode)) { + return doc.createTextNode(vnode.text); + } else if (!isVNode(vnode)) { + if (warn) { + warn("Item is not a valid virtual dom node", vnode); + } + return null; + } - process_unit(value) { - return value; - } + var node = vnode.namespace === null ? doc.createElement(vnode.tagName) : doc.createElementNS(vnode.namespace, vnode.tagName); - static integer(value) { - return BitString.wrap(value, { "type": "integer", "unit": 1, "size": 8 }); - } + var props = vnode.properties; + applyProperties(node, props); - static float(value) { - return BitString.wrap(value, { "type": "float", "unit": 1, "size": 64 }); - } + var children = vnode.children; - static bitstring(value) { - return BitString.wrap(value, { "type": "bitstring", "unit": 1, "size": value.length }); - } + for (var i = 0; i < children.length; i++) { + var childNode = createElement(children[i], opts); + if (childNode) { + node.appendChild(childNode); + } + } - static bits(value) { - return BitString.bitstring(value); - } + return node; + } + }, { "../vnode/handle-thunk.js": 24, "../vnode/is-vnode.js": 27, "../vnode/is-vtext.js": 28, "../vnode/is-widget.js": 29, "./apply-properties": 14, "global/document": 10 }], 16: [function (require, module, exports) { + // Maps a virtual DOM tree onto a real DOM tree in an efficient manner. + // We don't want to read all of the DOM nodes in the tree so we use + // the in-order tree indexing to eliminate recursion down certain branches. + // We only recurse into a DOM node if we know that it contains a child of + // interest. - static binary(value) { - return BitString.wrap(value, { "type": "binary", "unit": 8, "size": value.length }); - } + var noChild = {}; - static bytes(value) { - return BitString.binary(value); - } + module.exports = domIndex; - static utf8(value) { - return BitString.wrap(value, { "type": "utf8" }); - } + function domIndex(rootNode, tree, indices, nodes) { + if (!indices || indices.length === 0) { + return {}; + } else { + indices.sort(ascending); + return recurse(rootNode, tree, indices, nodes, 0); + } + } - static utf16(value) { - return BitString.wrap(value, { "type": "utf16" }); - } + function recurse(rootNode, tree, indices, nodes, rootIndex) { + nodes = nodes || {}; - static utf32(value) { - return BitString.wrap(value, { "type": "utf32" }); - } + if (rootNode) { + if (indexInRange(indices, rootIndex, rootIndex)) { + nodes[rootIndex] = rootNode; + } - static signed(value) { - return BitString.wrap(value, {}, "signed"); - } + var vChildren = tree.children; - static unsigned(value) { - return BitString.wrap(value, {}, "unsigned"); - } + if (vChildren) { - static native(value) { - return BitString.wrap(value, {}, "native"); - } + var childNodes = rootNode.childNodes; - static big(value) { - return BitString.wrap(value, {}, "big"); - } + for (var i = 0; i < tree.children.length; i++) { + rootIndex += 1; - static little(value) { - return BitString.wrap(value, {}, "little"); - } + var vChild = vChildren[i] || noChild; + var nextIndex = rootIndex + (vChild.count || 0); - static size(value, count) { - return BitString.wrap(value, { "size": count }); - } + // skip recursion down the tree if there are no nodes down here + if (indexInRange(indices, rootIndex, nextIndex)) { + recurse(childNodes[i], vChild, indices, nodes, rootIndex); + } - static unit(value, count) { - return BitString.wrap(value, { "unit": count }); - } + rootIndex = nextIndex; + } + } + } - static wrap(value, opt, new_attribute = null) { - let the_value = value; + return nodes; + } - if (!(value instanceof Object)) { - the_value = { "value": value, "attributes": [] }; - } + // Binary search for an index in the interval [left, right] + function indexInRange(indices, left, right) { + if (indices.length === 0) { + return false; + } - the_value = Object.assign(the_value, opt); + var minIndex = 0; + var maxIndex = indices.length - 1; + var currentIndex; + var currentItem; - if (new_attribute) { - the_value.attributes.push(new_attribute); - } + while (minIndex <= maxIndex) { + currentIndex = (maxIndex + minIndex) / 2 >> 0; + currentItem = indices[currentIndex]; + + if (minIndex === maxIndex) { + return currentItem >= left && currentItem <= right; + } else if (currentItem < left) { + minIndex = currentIndex + 1; + } else if (currentItem > right) { + maxIndex = currentIndex - 1; + } else { + return true; + } + } - return the_value; - } + return false; + } - static toUTF8Array(str) { - var utf8 = []; - for (var i = 0; i < str.length; i++) { - var charcode = str.charCodeAt(i); - if (charcode < 128) { - utf8.push(charcode); - } else if (charcode < 2048) { - utf8.push(192 | charcode >> 6, 128 | charcode & 63); - } else if (charcode < 55296 || charcode >= 57344) { - utf8.push(224 | charcode >> 12, 128 | charcode >> 6 & 63, 128 | charcode & 63); - } - // surrogate pair - else { - i++; - // UTF-16 encodes 0x10000-0x10FFFF by - // subtracting 0x10000 and splitting the - // 20 bits of 0x0-0xFFFFF into two halves - charcode = 65536 + ((charcode & 1023) << 10 | str.charCodeAt(i) & 1023); - utf8.push(240 | charcode >> 18, 128 | charcode >> 12 & 63, 128 | charcode >> 6 & 63, 128 | charcode & 63); - } - } - return utf8; - } + function ascending(a, b) { + return a > b ? 1 : -1; + } + }, {}], 17: [function (require, module, exports) { + var applyProperties = require("./apply-properties"); - static toUTF16Array(str) { - var utf16 = []; - for (var i = 0; i < str.length; i++) { - var codePoint = str.codePointAt(i); + var isWidget = require("../vnode/is-widget.js"); + var VPatch = require("../vnode/vpatch.js"); - if (codePoint <= 255) { - utf16.push(0); - utf16.push(codePoint); - } else { - utf16.push(codePoint >> 8 & 255); - utf16.push(codePoint & 255); - } - } - return utf16; - } + var updateWidget = require("./update-widget"); - static toUTF32Array(str) { - var utf32 = []; - for (var i = 0; i < str.length; i++) { - var codePoint = str.codePointAt(i); + module.exports = applyPatch; - if (codePoint <= 255) { - utf32.push(0); - utf32.push(0); - utf32.push(0); - utf32.push(codePoint); - } else { - utf32.push(0); - utf32.push(0); - utf32.push(codePoint >> 8 & 255); - utf32.push(codePoint & 255); - } - } - return utf32; - } + function applyPatch(vpatch, domNode, renderOptions) { + var type = vpatch.type; + var vNode = vpatch.vNode; + var patch = vpatch.patch; - //http://stackoverflow.com/questions/2003493/javascript-float-from-to-bits - static float32ToBytes(f) { - var bytes = []; + switch (type) { + case VPatch.REMOVE: + return removeNode(domNode, vNode); + case VPatch.INSERT: + return insertNode(domNode, patch, renderOptions); + case VPatch.VTEXT: + return stringPatch(domNode, vNode, patch, renderOptions); + case VPatch.WIDGET: + return widgetPatch(domNode, vNode, patch, renderOptions); + case VPatch.VNODE: + return vNodePatch(domNode, vNode, patch, renderOptions); + case VPatch.ORDER: + reorderChildren(domNode, patch); + return domNode; + case VPatch.PROPS: + applyProperties(domNode, patch, vNode.properties); + return domNode; + case VPatch.THUNK: + return replaceRoot(domNode, renderOptions.patch(domNode, patch, renderOptions)); + default: + return domNode; + } + } - var buf = new ArrayBuffer(4); - new Float32Array(buf)[0] = f; + function removeNode(domNode, vNode) { + var parentNode = domNode.parentNode; - let intVersion = new Uint32Array(buf)[0]; + if (parentNode) { + parentNode.removeChild(domNode); + } - bytes.push(intVersion >> 24 & 255); - bytes.push(intVersion >> 16 & 255); - bytes.push(intVersion >> 8 & 255); - bytes.push(intVersion & 255); + destroyWidget(domNode, vNode); - return bytes; - } + return null; + } - static float64ToBytes(f) { - var bytes = []; + function insertNode(parentNode, vNode, renderOptions) { + var newNode = renderOptions.render(vNode, renderOptions); - var buf = new ArrayBuffer(8); - new Float64Array(buf)[0] = f; + if (parentNode) { + parentNode.appendChild(newNode); + } - var intVersion1 = new Uint32Array(buf)[0]; - var intVersion2 = new Uint32Array(buf)[1]; + return parentNode; + } - bytes.push(intVersion2 >> 24 & 255); - bytes.push(intVersion2 >> 16 & 255); - bytes.push(intVersion2 >> 8 & 255); - bytes.push(intVersion2 & 255); + function stringPatch(domNode, leftVNode, vText, renderOptions) { + var newNode; - bytes.push(intVersion1 >> 24 & 255); - bytes.push(intVersion1 >> 16 & 255); - bytes.push(intVersion1 >> 8 & 255); - bytes.push(intVersion1 & 255); + if (domNode.nodeType === 3) { + domNode.replaceData(0, domNode.length, vText.text); + newNode = domNode; + } else { + var parentNode = domNode.parentNode; + newNode = renderOptions.render(vText, renderOptions); - return bytes; - } -} + if (parentNode && newNode !== domNode) { + parentNode.replaceChild(newNode, domNode); + } + } -/* @flow */ + return newNode; + } -class Variable { + function widgetPatch(domNode, leftVNode, widget, renderOptions) { + var updating = updateWidget(leftVNode, widget); + var newNode; - constructor(name = null) { - this.name = name; - } -} + if (updating) { + newNode = widget.update(leftVNode, domNode) || domNode; + } else { + newNode = renderOptions.render(widget, renderOptions); + } -class Wildcard { - constructor() {} -} + var parentNode = domNode.parentNode; -class StartsWith { + if (parentNode && newNode !== domNode) { + parentNode.replaceChild(newNode, domNode); + } - constructor(prefix) { - this.prefix = prefix; - } -} + if (!updating) { + destroyWidget(domNode, leftVNode); + } -class Capture { + return newNode; + } - constructor(value) { - this.value = value; - } -} + function vNodePatch(domNode, leftVNode, vNode, renderOptions) { + var parentNode = domNode.parentNode; + var newNode = renderOptions.render(vNode, renderOptions); -class HeadTail { - constructor() {} -} + if (parentNode && newNode !== domNode) { + parentNode.replaceChild(newNode, domNode); + } -class Type { + return newNode; + } - constructor(type, objPattern = {}) { - this.type = type; - this.objPattern = objPattern; - } -} + function destroyWidget(domNode, w) { + if (typeof w.destroy === "function" && isWidget(w)) { + w.destroy(domNode); + } + } -class Bound { + function reorderChildren(domNode, moves) { + var childNodes = domNode.childNodes; + var keyMap = {}; + var node; + var remove; + var insert; - constructor(value) { - this.value = value; - } -} + for (var i = 0; i < moves.removes.length; i++) { + remove = moves.removes[i]; + node = childNodes[remove.from]; + if (remove.key) { + keyMap[remove.key] = node; + } + domNode.removeChild(node); + } -function variable(name = null) { - return new Variable(name); -} + var length = childNodes.length; + for (var j = 0; j < moves.inserts.length; j++) { + insert = moves.inserts[j]; + node = keyMap[insert.key]; + // this is the weirdest bug i've ever seen in webkit + domNode.insertBefore(node, insert.to >= length++ ? null : childNodes[insert.to]); + } + } -function wildcard() { - return new Wildcard(); -} + function replaceRoot(oldRoot, newRoot) { + if (oldRoot && newRoot && oldRoot !== newRoot && oldRoot.parentNode) { + oldRoot.parentNode.replaceChild(newRoot, oldRoot); + } -function startsWith(prefix) { - return new StartsWith(prefix); -} + return newRoot; + } + }, { "../vnode/is-widget.js": 29, "../vnode/vpatch.js": 32, "./apply-properties": 14, "./update-widget": 19 }], 18: [function (require, module, exports) { + var document = require("global/document"); + var isArray = require("x-is-array"); -function capture(value) { - return new Capture(value); -} + var render = require("./create-element"); + var domIndex = require("./dom-index"); + var patchOp = require("./patch-op"); + module.exports = patch; -function headTail() { - return new HeadTail(); -} + function patch(rootNode, patches, renderOptions) { + renderOptions = renderOptions || {}; + renderOptions.patch = renderOptions.patch && renderOptions.patch !== patch ? renderOptions.patch : patchRecursive; + renderOptions.render = renderOptions.render || render; -function type(type, objPattern = {}) { - return new Type(type, objPattern); -} + return renderOptions.patch(rootNode, patches, renderOptions); + } -function bound(value) { - return new Bound(value); -} + function patchRecursive(rootNode, patches, renderOptions) { + var indices = patchIndices(patches); -function is_number(value) { - return typeof value === 'number'; -} + if (indices.length === 0) { + return rootNode; + } -function is_string(value) { - return typeof value === 'string'; -} + var index = domIndex(rootNode, patches.a, indices); + var ownerDocument = rootNode.ownerDocument; -function is_boolean(value) { - return typeof value === 'boolean'; -} + if (!renderOptions.document && ownerDocument !== document) { + renderOptions.document = ownerDocument; + } -function is_symbol(value) { - return typeof value === 'symbol'; -} + for (var i = 0; i < indices.length; i++) { + var nodeIndex = indices[i]; + rootNode = applyPatch(rootNode, index[nodeIndex], patches[nodeIndex], renderOptions); + } -function is_null(value) { - return value === null; -} + return rootNode; + } -function is_undefined(value) { - return typeof value === 'undefined'; -} + function applyPatch(rootNode, domNode, patchList, renderOptions) { + if (!domNode) { + return rootNode; + } -function is_function(value) { - return Object.prototype.toString.call(value) == '[object Function]'; -} + var newNode; -function is_variable(value) { - return value instanceof Variable; -} + if (isArray(patchList)) { + for (var i = 0; i < patchList.length; i++) { + newNode = patchOp(patchList[i], domNode, renderOptions); -function is_wildcard(value) { - return value instanceof Wildcard; -} + if (domNode === rootNode) { + rootNode = newNode; + } + } + } else { + newNode = patchOp(patchList, domNode, renderOptions); -function is_headTail(value) { - return value instanceof HeadTail; -} + if (domNode === rootNode) { + rootNode = newNode; + } + } -function is_capture(value) { - return value instanceof Capture; -} + return rootNode; + } -function is_type(value) { - return value instanceof Type; -} + function patchIndices(patches) { + var indices = []; -function is_startsWith(value) { - return value instanceof StartsWith; -} + for (var key in patches) { + if (key !== "a") { + indices.push(Number(key)); + } + } -function is_bound(value) { - return value instanceof Bound; -} + return indices; + } + }, { "./create-element": 15, "./dom-index": 16, "./patch-op": 17, "global/document": 10, "x-is-array": 12 }], 19: [function (require, module, exports) { + var isWidget = require("../vnode/is-widget.js"); -function is_object(value) { - return typeof value === 'object'; -} + module.exports = updateWidget; -function is_array(value) { - return Array.isArray(value); -} + function updateWidget(a, b) { + if (isWidget(a) && isWidget(b)) { + if ("name" in a && "name" in b) { + return a.id === b.id; + } else { + return a.init === b.init; + } + } -var Checks = { - is_number, - is_string, - is_boolean, - is_symbol, - is_null, - is_undefined, - is_function, - is_variable, - is_wildcard, - is_headTail, - is_capture, - is_type, - is_startsWith, - is_bound, - is_object, - is_array -}; + return false; + } + }, { "../vnode/is-widget.js": 29 }], 20: [function (require, module, exports) { + "use strict"; -function resolveSymbol(pattern) { - return function (value) { - return Checks.is_symbol(value) && value === pattern; - }; -} + var EvStore = require("ev-store"); -function resolveString(pattern) { - return function (value) { - return Checks.is_string(value) && value === pattern; - }; -} + module.exports = EvHook; -function resolveNumber(pattern) { - return function (value) { - return Checks.is_number(value) && value === pattern; - }; -} + function EvHook(value) { + if (!(this instanceof EvHook)) { + return new EvHook(value); + } -function resolveBoolean(pattern) { - return function (value) { - return Checks.is_boolean(value) && value === pattern; - }; -} + this.value = value; + } -function resolveFunction(pattern) { - return function (value) { - return Checks.is_function(value) && value === pattern; - }; -} + EvHook.prototype.hook = function (node, propertyName) { + var es = EvStore(node); + var propName = propertyName.substr(3); -function resolveNull(pattern) { - return function (value) { - return Checks.is_null(value); - }; -} + es[propName] = this.value; + }; -function resolveBound(pattern) { - return function (value, args) { - if (typeof value === typeof pattern.value && value === pattern.value) { - args.push(value); - return true; - } + EvHook.prototype.unhook = function (node, propertyName) { + var es = EvStore(node); + var propName = propertyName.substr(3); - return false; - }; -} + es[propName] = undefined; + }; + }, { "ev-store": 7 }], 21: [function (require, module, exports) { + "use strict"; -function resolveWildcard() { - return function () { - return true; - }; -} + module.exports = SoftSetHook; -function resolveVariable() { - return function (value, args) { - args.push(value); - return true; - }; -} + function SoftSetHook(value) { + if (!(this instanceof SoftSetHook)) { + return new SoftSetHook(value); + } -function resolveHeadTail() { - return function (value, args) { - if (!Checks.is_array(value) || value.length < 2) { - return false; - } + this.value = value; + } - const head = value[0]; - const tail = value.slice(1); + SoftSetHook.prototype.hook = function (node, propertyName) { + if (node[propertyName] !== this.value) { + node[propertyName] = this.value; + } + }; + }, {}], 22: [function (require, module, exports) { + "use strict"; - args.push(head); - args.push(tail); + var isArray = require("x-is-array"); + + var VNode = require("../vnode/vnode.js"); + var VText = require("../vnode/vtext.js"); + var isVNode = require("../vnode/is-vnode"); + var isVText = require("../vnode/is-vtext"); + var isWidget = require("../vnode/is-widget"); + var isHook = require("../vnode/is-vhook"); + var isVThunk = require("../vnode/is-thunk"); - return true; - }; -} + var parseTag = require("./parse-tag.js"); + var softSetHook = require("./hooks/soft-set-hook.js"); + var evHook = require("./hooks/ev-hook.js"); -function resolveCapture(pattern) { - const matches = buildMatch(pattern.value); + module.exports = h; - return function (value, args) { - if (matches(value, args)) { - args.push(value); - return true; - } + function h(tagName, properties, children) { + var childNodes = []; + var tag, props, key, namespace; - return false; - }; -} + if (!children && isChildren(properties)) { + children = properties; + props = {}; + } -function resolveStartsWith(pattern) { - const prefix = pattern.prefix; + props = props || properties || {}; + tag = parseTag(tagName, props); - return function (value, args) { - if (Checks.is_string(value) && value.startsWith(prefix)) { - args.push(value.substring(prefix.length)); - return true; - } + // support keys + if (props.hasOwnProperty("key")) { + key = props.key; + props.key = undefined; + } - return false; - }; -} + // support namespace + if (props.hasOwnProperty("namespace")) { + namespace = props.namespace; + props.namespace = undefined; + } -function resolveType(pattern) { - return function (value, args) { - if (value instanceof pattern.type) { - const matches = buildMatch(pattern.objPattern); - return matches(value, args) && args.push(value) > 0; - } + // fix cursor bug + if (tag === "INPUT" && !namespace && props.hasOwnProperty("value") && props.value !== undefined && !isHook(props.value)) { + props.value = softSetHook(props.value); + } - return false; - }; -} + transformProperties(props); -function resolveArray(pattern) { - const matches = pattern.map(x => buildMatch(x)); + if (children !== undefined && children !== null) { + addChild(children, childNodes, tag, props); + } - return function (value, args) { - if (!Checks.is_array(value) || value.length != pattern.length) { - return false; - } + return new VNode(tag, props, childNodes, key, namespace); + } - return value.every(function (v, i) { - return matches[i](value[i], args); - }); - }; -} + function addChild(c, childNodes, tag, props) { + if (typeof c === "string") { + childNodes.push(new VText(c)); + } else if (typeof c === "number") { + childNodes.push(new VText(String(c))); + } else if (isChild(c)) { + childNodes.push(c); + } else if (isArray(c)) { + for (var i = 0; i < c.length; i++) { + addChild(c[i], childNodes, tag, props); + } + } else if (c === null || c === undefined) { + return; + } else { + throw UnexpectedVirtualElement({ + foreignObject: c, + parentVnode: { + tagName: tag, + properties: props + } + }); + } + } -function resolveObject(pattern) { - let matches = {}; + function transformProperties(props) { + for (var propName in props) { + if (props.hasOwnProperty(propName)) { + var value = props[propName]; - for (let key of Object.keys(pattern).concat(Object.getOwnPropertySymbols(pattern))) { - matches[key] = buildMatch(pattern[key]); - } + if (isHook(value)) { + continue; + } - return function (value, args) { - if (!Checks.is_object(value) || pattern.length > value.length) { - return false; - } + if (propName.substr(0, 3) === "ev-") { + // add ev-foo support + props[propName] = evHook(value); + } + } + } + } - for (let key of Object.keys(pattern).concat(Object.getOwnPropertySymbols(pattern))) { - if (!(key in value) || !matches[key](value[key], args)) { - return false; - } - } + function isChild(x) { + return isVNode(x) || isVText(x) || isWidget(x) || isVThunk(x); + } - return true; - }; -} + function isChildren(x) { + return typeof x === "string" || isArray(x) || isChild(x); + } -function resolveNoMatch() { - return function () { - return false; - }; -} + function UnexpectedVirtualElement(data) { + var err = new Error(); -var Resolvers = { - resolveBound, - resolveWildcard, - resolveVariable, - resolveHeadTail, - resolveCapture, - resolveStartsWith, - resolveType, - resolveArray, - resolveObject, - resolveNoMatch, - resolveSymbol, - resolveString, - resolveNumber, - resolveBoolean, - resolveFunction, - resolveNull -}; + err.type = "virtual-hyperscript.unexpected.virtual-element"; + err.message = "Unexpected virtual child passed to h().\n" + "Expected a VNode / Vthunk / VWidget / string but:\n" + "got:\n" + errorString(data.foreignObject) + ".\n" + "The parent vnode is:\n" + errorString(data.parentVnode); + "\n" + "Suggested fix: change your `h(..., [ ... ])` callsite."; + err.foreignObject = data.foreignObject; + err.parentVnode = data.parentVnode; -function buildMatch(pattern) { + return err; + } - if (Checks.is_variable(pattern)) { - return Resolvers.resolveVariable(pattern); - } + function errorString(obj) { + try { + return JSON.stringify(obj, null, " "); + } catch (e) { + return String(obj); + } + } + }, { "../vnode/is-thunk": 25, "../vnode/is-vhook": 26, "../vnode/is-vnode": 27, "../vnode/is-vtext": 28, "../vnode/is-widget": 29, "../vnode/vnode.js": 31, "../vnode/vtext.js": 33, "./hooks/ev-hook.js": 20, "./hooks/soft-set-hook.js": 21, "./parse-tag.js": 23, "x-is-array": 12 }], 23: [function (require, module, exports) { + "use strict"; - if (Checks.is_wildcard(pattern)) { - return Resolvers.resolveWildcard(pattern); - } + var split = require("browser-split"); - if (Checks.is_undefined(pattern)) { - return Resolvers.resolveWildcard(pattern); - } + var classIdSplit = /([\.#]?[a-zA-Z0-9\u007F-\uFFFF_:-]+)/; + var notClassId = /^\.|#/; - if (Checks.is_headTail(pattern)) { - return Resolvers.resolveHeadTail(pattern); - } + module.exports = parseTag; - if (Checks.is_startsWith(pattern)) { - return Resolvers.resolveStartsWith(pattern); - } + function parseTag(tag, props) { + if (!tag) { + return "DIV"; + } - if (Checks.is_capture(pattern)) { - return Resolvers.resolveCapture(pattern); - } + var noId = !props.hasOwnProperty("id"); - if (Checks.is_bound(pattern)) { - return Resolvers.resolveBound(pattern); - } + var tagParts = split(tag, classIdSplit); + var tagName = null; - if (Checks.is_type(pattern)) { - return Resolvers.resolveType(pattern); - } + if (notClassId.test(tagParts[1])) { + tagName = "DIV"; + } - if (Checks.is_array(pattern)) { - return Resolvers.resolveArray(pattern); - } + var classes, part, type, i; - if (Checks.is_number(pattern)) { - return Resolvers.resolveNumber(pattern); - } + for (i = 0; i < tagParts.length; i++) { + part = tagParts[i]; - if (Checks.is_string(pattern)) { - return Resolvers.resolveString(pattern); - } + if (!part) { + continue; + } - if (Checks.is_boolean(pattern)) { - return Resolvers.resolveBoolean(pattern); - } + type = part.charAt(0); - if (Checks.is_symbol(pattern)) { - return Resolvers.resolveSymbol(pattern); - } + if (!tagName) { + tagName = part; + } else if (type === ".") { + classes = classes || []; + classes.push(part.substring(1, part.length)); + } else if (type === "#" && noId) { + props.id = part.substring(1, part.length); + } + } - if (Checks.is_null(pattern)) { - return Resolvers.resolveNull(pattern); - } + if (classes) { + if (props.className) { + classes.push(props.className); + } - if (Checks.is_object(pattern)) { - return Resolvers.resolveObject(pattern); - } + props.className = classes.join(" "); + } - return Resolvers.resolveNoMatch(); -} + return props.namespace ? tagName : tagName.toUpperCase(); + } + }, { "browser-split": 5 }], 24: [function (require, module, exports) { + var isVNode = require("./is-vnode"); + var isVText = require("./is-vtext"); + var isWidget = require("./is-widget"); + var isThunk = require("./is-thunk"); -class MatchError extends Error { - constructor(arg) { - super(); + module.exports = handleThunk; - if (typeof arg === 'symbol') { - this.message = 'No match for: ' + arg.toString(); - } else if (Array.isArray(arg)) { - let mappedValues = arg.map(x => x.toString()); - this.message = 'No match for: ' + mappedValues; - } else { - this.message = 'No match for: ' + arg; - } + function handleThunk(a, b) { + var renderedA = a; + var renderedB = b; - this.stack = new Error().stack; - this.name = this.constructor.name; - } -} + if (isThunk(b)) { + renderedB = renderThunk(b, a); + } -class Case { + if (isThunk(a)) { + renderedA = renderThunk(a, null); + } - constructor(pattern, fn, guard = () => true) { - this.pattern = buildMatch(pattern); - this.fn = fn; - this.guard = guard; - } -} + return { + a: renderedA, + b: renderedB + }; + } -function make_case(pattern, fn, guard = () => true) { - return new Case(pattern, fn, guard); -} + function renderThunk(thunk, previous) { + var renderedThunk = thunk.vnode; -function defmatch(...cases) { - return function (...args) { - for (let processedCase of cases) { - let result = []; - if (processedCase.pattern(args, result) && processedCase.guard.apply(this, result)) { - return processedCase.fn.apply(this, result); - } - } + if (!renderedThunk) { + renderedThunk = thunk.vnode = thunk.render(previous); + } - throw new MatchError(args); - }; -} + if (!(isVNode(renderedThunk) || isVText(renderedThunk) || isWidget(renderedThunk))) { + throw new Error("thunk did not return a valid node"); + } -function match(pattern, expr, guard = () => true) { - let result = []; - let processedPattern = buildMatch(pattern); - if (processedPattern(expr, result) && guard.apply(this, result)) { - return result; - } else { - throw new MatchError(expr); - } -} + return renderedThunk; + } + }, { "./is-thunk": 25, "./is-vnode": 27, "./is-vtext": 28, "./is-widget": 29 }], 25: [function (require, module, exports) { + module.exports = isThunk; -function match_no_throw(pattern, expr, guard = () => true) { - try { - return match(pattern, expr, guard); - } catch (e) { - if (e instanceof MatchError) { - return null; - } + function isThunk(t) { + return t && t.type === "Thunk"; + } + }, {}], 26: [function (require, module, exports) { + module.exports = isHook; - throw e; - } -} + function isHook(hook) { + return hook && (typeof hook.hook === "function" && !hook.hasOwnProperty("hook") || typeof hook.unhook === "function" && !hook.hasOwnProperty("unhook")); + } + }, {}], 27: [function (require, module, exports) { + var version = require("./version"); -var Patterns = { - defmatch, match, MatchError, match_no_throw, - variable, wildcard, startsWith, - capture, headTail, type, bound, Case, make_case -}; + module.exports = isVirtualNode; -function call_property(item, property) { - let prop = null; + function isVirtualNode(x) { + return x && x.type === "VirtualNode" && x.version === version; + } + }, { "./version": 30 }], 28: [function (require, module, exports) { + var version = require("./version"); - if (property in item) { - prop = property; - } else if (Symbol.for(property) in item) { - prop = Symbol.for(property); - } else { - throw new Error(`Property ${ property } not found in ${ item }`); - } + module.exports = isVirtualText; - if (item[prop] instanceof Function) { - return item[prop](); - } else { - return item[prop]; - } -} + function isVirtualText(x) { + return x && x.type === "VirtualText" && x.version === version; + } + }, { "./version": 30 }], 29: [function (require, module, exports) { + module.exports = isWidget; -function apply(...args) { - if (args.length === 2) { - args[0].apply(null, args.slice(1)); - } else { - args[0][args[1]].apply(null, args.slice(2)); - } -} + function isWidget(w) { + return w && w.type === "Widget"; + } + }, {}], 30: [function (require, module, exports) { + module.exports = "2"; + }, {}], 31: [function (require, module, exports) { + var version = require("./version"); + var isVNode = require("./is-vnode"); + var isWidget = require("./is-widget"); + var isThunk = require("./is-thunk"); + var isVHook = require("./is-vhook"); -function contains(left, right) { - for (let x of right) { - if (Patterns.match_no_throw(left, x) != null) { - return true; - } - } + module.exports = VirtualNode; - return false; -} + var noProperties = {}; + var noChildren = []; -function get_global() { - if (typeof self !== 'undefined') { - return self; - } else if (typeof window !== 'undefined') { - return window; - } else if (typeof global !== 'undefined') { - return global; - } + function VirtualNode(tagName, properties, children, key, namespace) { + this.tagName = tagName; + this.properties = properties || noProperties; + this.children = children || noChildren; + this.key = key != null ? String(key) : undefined; + this.namespace = typeof namespace === "string" ? namespace : null; - throw new Error('No global state found'); -} + var count = children && children.length || 0; + var descendants = 0; + var hasWidgets = false; + var hasThunks = false; + var descendantHooks = false; + var hooks; -function defstruct(defaults) { - return class { - constructor(update = {}) { - let the_values = Object.assign(defaults, update); - Object.assign(this, the_values); - } + for (var propName in properties) { + if (properties.hasOwnProperty(propName)) { + var property = properties[propName]; + if (isVHook(property) && property.unhook) { + if (!hooks) { + hooks = {}; + } - static create(updates = {}) { - let x = new this(updates); - return Object.freeze(x); - } - }; -} + hooks[propName] = property; + } + } + } -function defexception(defaults) { - return class extends Error { - constructor(update = {}) { - let message = update.message || ''; - super(message); + for (var i = 0; i < count; i++) { + var child = children[i]; + if (isVNode(child)) { + descendants += child.count || 0; - let the_values = Object.assign(defaults, update); - Object.assign(this, the_values); + if (!hasWidgets && child.hasWidgets) { + hasWidgets = true; + } - this.name = this.constructor.name; - this.message = message; - this[SpecialForms.atom('__exception__')] = true; - Error.captureStackTrace(this, this.constructor.name); - } + if (!hasThunks && child.hasThunks) { + hasThunks = true; + } - static create(updates = {}) { - let x = new this(updates); - return Object.freeze(x); - } - }; -} + if (!descendantHooks && (child.hooks || child.descendantHooks)) { + descendantHooks = true; + } + } else if (!hasWidgets && isWidget(child)) { + if (typeof child.destroy === "function") { + hasWidgets = true; + } + } else if (!hasThunks && isThunk(child)) { + hasThunks = true; + } + } + + this.count = count + descendants; + this.hasWidgets = hasWidgets; + this.hasThunks = hasThunks; + this.hooks = hooks; + this.descendantHooks = descendantHooks; + } -function defprotocol(spec) { - return new Protocol(spec); -} + VirtualNode.prototype.version = version; + VirtualNode.prototype.type = "VirtualNode"; + }, { "./is-thunk": 25, "./is-vhook": 26, "./is-vnode": 27, "./is-widget": 29, "./version": 30 }], 32: [function (require, module, exports) { + var version = require("./version"); -function defimpl(protocol, type, impl) { - protocol.implementation(type, impl); -} + VirtualPatch.NONE = 0; + VirtualPatch.VTEXT = 1; + VirtualPatch.VNODE = 2; + VirtualPatch.WIDGET = 3; + VirtualPatch.PROPS = 4; + VirtualPatch.ORDER = 5; + VirtualPatch.INSERT = 6; + VirtualPatch.REMOVE = 7; + VirtualPatch.THUNK = 8; -function get_object_keys(obj) { - return Object.keys(obj).concat(Object.getOwnPropertySymbols(obj)); -} + module.exports = VirtualPatch; -function is_valid_character(codepoint) { - try { - return String.fromCodePoint(codepoint) != null; - } catch (e) { - return false; - } -} + function VirtualPatch(type, vNode, patch) { + this.type = Number(type); + this.vNode = vNode; + this.patch = patch; + } -//https://developer.mozilla.org/en-US/docs/Web/API/WindowBase64/Base64_encoding_and_decoding#Solution_2_%E2%80%93_rewrite_the_DOMs_atob()_and_btoa()_using_JavaScript's_TypedArrays_and_UTF-8 -function b64EncodeUnicode(str) { - return btoa(encodeURIComponent(str).replace(/%([0-9A-F]{2})/g, function (match, p1) { - return String.fromCharCode('0x' + p1); - })); -} + VirtualPatch.prototype.version = version; + VirtualPatch.prototype.type = "VirtualPatch"; + }, { "./version": 30 }], 33: [function (require, module, exports) { + var version = require("./version"); -function delete_property_from_map(map, property) { - let new_map = Object.assign(Object.create(map.constructor.prototype), map); - delete new_map[property]; + module.exports = VirtualText; - return Object.freeze(new_map); -} + function VirtualText(text) { + this.text = String(text); + } -function class_to_obj(map) { - let new_map = Object.assign({}, map); - return Object.freeze(new_map); -} + VirtualText.prototype.version = version; + VirtualText.prototype.type = "VirtualText"; + }, { "./version": 30 }], 34: [function (require, module, exports) { + var isObject = require("is-object"); + var isHook = require("../vnode/is-vhook"); -function add_property_to_map(map, property, value) { - let new_map = Object.assign({}, map); - new_map[property] = value; - return Object.freeze(new_map); -} + module.exports = diffProps; -function bnot(expr) { - return ~expr; -} + function diffProps(a, b) { + var diff; -function band(left, right) { - return left & right; -} + for (var aKey in a) { + if (!(aKey in b)) { + diff = diff || {}; + diff[aKey] = undefined; + } -function bor(left, right) { - return left | right; -} + var aValue = a[aKey]; + var bValue = b[aKey]; -function bsl(left, right) { - return left << right; -} + if (aValue === bValue) { + continue; + } else if (isObject(aValue) && isObject(bValue)) { + if (getPrototype(bValue) !== getPrototype(aValue)) { + diff = diff || {}; + diff[aKey] = bValue; + } else if (isHook(bValue)) { + diff = diff || {}; + diff[aKey] = bValue; + } else { + var objectDiff = diffProps(aValue, bValue); + if (objectDiff) { + diff = diff || {}; + diff[aKey] = objectDiff; + } + } + } else { + diff = diff || {}; + diff[aKey] = bValue; + } + } -function bsr(left, right) { - return left >> right; -} + for (var bKey in b) { + if (!(bKey in a)) { + diff = diff || {}; + diff[bKey] = b[bKey]; + } + } -function bxor(left, right) { - return left ^ right; -} + return diff; + } -function zip(list_of_lists) { - if (list_of_lists.length === 0) { - return Object.freeze([]); - } + function getPrototype(value) { + if (Object.getPrototypeOf) { + return Object.getPrototypeOf(value); + } else if (value.__proto__) { + return value.__proto__; + } else if (value.constructor) { + return value.constructor.prototype; + } + } + }, { "../vnode/is-vhook": 26, "is-object": 11 }], 35: [function (require, module, exports) { + var isArray = require("x-is-array"); - let new_value = []; - let smallest_length = list_of_lists[0]; + var VPatch = require("../vnode/vpatch"); + var isVNode = require("../vnode/is-vnode"); + var isVText = require("../vnode/is-vtext"); + var isWidget = require("../vnode/is-widget"); + var isThunk = require("../vnode/is-thunk"); + var handleThunk = require("../vnode/handle-thunk"); - for (let x of list_of_lists) { - if (x.length < smallest_length) { - smallest_length = x.length; - } - } + var diffProps = require("./diff-props"); - for (let i = 0; i < smallest_length; i++) { - let current_value = []; - for (let j = 0; j < list_of_lists.length; j++) { - current_value.push(list_of_lists[j][i]); - } + module.exports = diff; - new_value.push(new Tuple(...current_value)); - } + function diff(a, b) { + var patch = { a: a }; + walk(a, b, patch, 0); + return patch; + } - return Object.freeze(new_value); -} + function walk(a, b, patch, index) { + if (a === b) { + return; + } -function can_decode64(data) { - try { - atob(data); - return true; - } catch (e) { - return false; - } -} + var apply = patch[index]; + var applyClear = false; -var Functions = { - call_property, - apply, - contains, - get_global, - defstruct, - defexception, - defprotocol, - defimpl, - get_object_keys, - is_valid_character, - b64EncodeUnicode, - delete_property_from_map, - add_property_to_map, - class_to_obj, - can_decode64, - bnot, - band, - bor, - bsl, - bsr, - bxor, - zip -}; + if (isThunk(a) || isThunk(b)) { + thunks(a, b, patch, index); + } else if (b == null) { -function _case(condition, clauses) { - return Patterns.defmatch(...clauses)(condition); -} + // If a is a widget we will add a remove patch for it + // Otherwise any child widgets/hooks must be destroyed. + // This prevents adding two remove patches for a widget. + if (!isWidget(a)) { + clearState(a, patch, index); + apply = patch[index]; + } -function cond(clauses) { - for (let clause of clauses) { - if (clause[0]) { - return clause[1](); - } - } + apply = appendPatch(apply, new VPatch(VPatch.REMOVE, a, b)); + } else if (isVNode(b)) { + if (isVNode(a)) { + if (a.tagName === b.tagName && a.namespace === b.namespace && a.key === b.key) { + var propsPatch = diffProps(a.properties, b.properties); + if (propsPatch) { + apply = appendPatch(apply, new VPatch(VPatch.PROPS, a, propsPatch)); + } + apply = diffChildren(a, b, patch, apply, index); + } else { + apply = appendPatch(apply, new VPatch(VPatch.VNODE, a, b)); + applyClear = true; + } + } else { + apply = appendPatch(apply, new VPatch(VPatch.VNODE, a, b)); + applyClear = true; + } + } else if (isVText(b)) { + if (!isVText(a)) { + apply = appendPatch(apply, new VPatch(VPatch.VTEXT, a, b)); + applyClear = true; + } else if (a.text !== b.text) { + apply = appendPatch(apply, new VPatch(VPatch.VTEXT, a, b)); + } + } else if (isWidget(b)) { + if (!isWidget(a)) { + applyClear = true; + } - throw new Error(); -} + apply = appendPatch(apply, new VPatch(VPatch.WIDGET, a, b)); + } -function map_update(map, values) { - return Object.freeze(Object.assign(Object.create(map.constructor.prototype), map, values)); -} + if (apply) { + patch[index] = apply; + } -function _for(collections, fun, filter = () => true, into = [], previousValues = []) { - let pattern = collections[0][0]; - let collection = collections[0][1]; + if (applyClear) { + clearState(a, patch, index); + } + } - if (collections.length === 1) { + function diffChildren(a, b, patch, apply, index) { + var aChildren = a.children; + var orderedSet = reorder(aChildren, b.children); + var bChildren = orderedSet.children; - for (let elem of collection) { - let r = Patterns.match_no_throw(pattern, elem); - let args = previousValues.concat(r); + var aLen = aChildren.length; + var bLen = bChildren.length; + var len = aLen > bLen ? aLen : bLen; - if (r && filter.apply(this, args)) { - into = into.concat([fun.apply(this, args)]); - } - } + for (var i = 0; i < len; i++) { + var leftNode = aChildren[i]; + var rightNode = bChildren[i]; + index += 1; - return into; - } else { - let _into = []; + if (!leftNode) { + if (rightNode) { + // Excess nodes in b need to be added + apply = appendPatch(apply, new VPatch(VPatch.INSERT, null, rightNode)); + } + } else { + walk(leftNode, rightNode, patch, index); + } - for (let elem of collection) { - let r = Patterns.match_no_throw(pattern, elem); - if (r) { - _into = into.concat(this._for(collections.slice(1), fun, filter, _into, previousValues.concat(r))); - } - } + if (isVNode(leftNode) && leftNode.count) { + index += leftNode.count; + } + } - return _into; - } -} + if (orderedSet.moves) { + // Reorder nodes last + apply = appendPatch(apply, new VPatch(VPatch.ORDER, a, orderedSet.moves)); + } -function _try(do_fun, rescue_function, catch_fun, else_function, after_function) { - let result = null; + return apply; + } - try { - result = do_fun(); - } catch (e) { - let ex_result = null; + function clearState(vNode, patch, index) { + // TODO: Make this a single walk, not two + unhook(vNode, patch, index); + destroyWidgets(vNode, patch, index); + } - if (rescue_function) { - try { - ex_result = rescue_function(e); - return ex_result; - } catch (ex) { - if (ex instanceof Patterns.MatchError) { - throw ex; - } - } - } + // Patch records for all destroyed widgets must be added because we need + // a DOM node reference for the destroy function + function destroyWidgets(vNode, patch, index) { + if (isWidget(vNode)) { + if (typeof vNode.destroy === "function") { + patch[index] = appendPatch(patch[index], new VPatch(VPatch.REMOVE, vNode, null)); + } + } else if (isVNode(vNode) && (vNode.hasWidgets || vNode.hasThunks)) { + var children = vNode.children; + var len = children.length; + for (var i = 0; i < len; i++) { + var child = children[i]; + index += 1; - if (catch_fun) { - try { - ex_result = catch_fun(e); - return ex_result; - } catch (ex) { - if (ex instanceof Patterns.MatchError) { - throw ex; - } - } - } + destroyWidgets(child, patch, index); - throw e; - } finally { - if (after_function) { - after_function(); - } - } + if (isVNode(child) && child.count) { + index += child.count; + } + } + } else if (isThunk(vNode)) { + thunks(vNode, null, patch, index); + } + } - if (else_function) { - try { - return else_function(result); - } catch (ex) { - if (ex instanceof Patterns.MatchError) { - throw new Error('No Match Found in Else'); - } + // Create a sub-patch for thunks + function thunks(a, b, patch, index) { + var nodes = handleThunk(a, b); + var thunkPatch = diff(nodes.a, nodes.b); + if (hasPatches(thunkPatch)) { + patch[index] = new VPatch(VPatch.THUNK, null, thunkPatch); + } + } - throw ex; - } - } else { - return result; - } -} + function hasPatches(patch) { + for (var index in patch) { + if (index !== "a") { + return true; + } + } -var special_forms = { - _case, - cond, - map_update, - _for, - _try -}; + return false; + } -Functions.get_global().processes = Functions.get_global().processes || new ProcessSystem(); + // Execute hooks when two nodes are identical + function unhook(vNode, patch, index) { + if (isVNode(vNode)) { + if (vNode.hooks) { + patch[index] = appendPatch(patch[index], new VPatch(VPatch.PROPS, vNode, undefinedKeys(vNode.hooks))); + } + if (vNode.descendantHooks || vNode.hasThunks) { + var children = vNode.children; + var len = children.length; + for (var i = 0; i < len; i++) { + var child = children[i]; + index += 1; + unhook(child, patch, index); -var C = Object.freeze({ - ProcessSystem: ProcessSystem, - Tuple: Tuple, - PID: PID, - BitString: BitString, - Patterns: Patterns, - Integer: Integer, - Float: Float, - Functions: Functions, - SpecialForms: special_forms -}); + if (isVNode(child) && child.count) { + index += child.count; + } + } + } + } else if (isThunk(vNode)) { + thunks(vNode, null, patch, index); + } + } -let Enum = { + function undefinedKeys(obj) { + var result = {}; - all__qmark__: function (collection, fun = x => x) { - for (let elem of collection) { - if (!fun(elem)) { - return false; - } - } + for (var key in obj) { + result[key] = undefined; + } - return true; - }, + return result; + } - any__qmark__: function (collection, fun = x => x) { - for (let elem of collection) { - if (fun(elem)) { - return true; - } - } + // List diff, naive left to right reordering + function reorder(aChildren, bChildren) { + // O(M) time, O(M) memory + var bChildIndex = keyIndex(bChildren); + var bKeys = bChildIndex.keys; + var bFree = bChildIndex.free; - return false; - }, + if (bFree.length === bChildren.length) { + return { + children: bChildren, + moves: null + }; + } - at: function (collection, n, the_default = null) { - if (n > this.count(collection) || n < 0) { - return the_default; - } + // O(N) time, O(N) memory + var aChildIndex = keyIndex(aChildren); + var aKeys = aChildIndex.keys; + var aFree = aChildIndex.free; - return collection[n]; - }, + if (aFree.length === aChildren.length) { + return { + children: bChildren, + moves: null + }; + } - concat: function (...enumables) { - return enumables[0].concat(enumables[1]); - }, + // O(MAX(N, M)) memory + var newChildren = []; - count: function (collection, fun = null) { - if (fun == null) { - return collection.length; - } else { - return collection.filter(fun).length; - } - }, + var freeIndex = 0; + var freeCount = bFree.length; + var deletedItems = 0; + + // Iterate through a and match a node in b + // O(N) time, + for (var i = 0; i < aChildren.length; i++) { + var aItem = aChildren[i]; + var itemIndex; - drop: function (collection, count) { - return collection.slice(count); - }, + if (aItem.key) { + if (bKeys.hasOwnProperty(aItem.key)) { + // Match up the old keys + itemIndex = bKeys[aItem.key]; + newChildren.push(bChildren[itemIndex]); + } else { + // Remove old keyed items + itemIndex = i - deletedItems++; + newChildren.push(null); + } + } else { + // Match the item in a with the next free item in b + if (freeIndex < freeCount) { + itemIndex = bFree[freeIndex++]; + newChildren.push(bChildren[itemIndex]); + } else { + // There are no free items in b to match with + // the free items in a, so the extra free nodes + // are deleted. + itemIndex = i - deletedItems++; + newChildren.push(null); + } + } + } - drop_while: function (collection, fun) { - let count = 0; + var lastFreeIndex = freeIndex >= bFree.length ? bChildren.length : bFree[freeIndex]; - for (let elem of collection) { - if (fun(elem)) { - count = count + 1; - } else { - break; - } - } + // Iterate through b and append any new keys + // O(M) time + for (var j = 0; j < bChildren.length; j++) { + var newItem = bChildren[j]; - return collection.slice(count); - }, + if (newItem.key) { + if (!aKeys.hasOwnProperty(newItem.key)) { + // Add any new keyed items + // We are adding new items to the end and then sorting them + // in place. In future we should insert new items in place. + newChildren.push(newItem); + } + } else if (j >= lastFreeIndex) { + // Add any leftover non-keyed items + newChildren.push(newItem); + } + } - each: function (collection, fun) { - for (let elem of collection) { - fun(elem); - } - }, + var simulate = newChildren.slice(); + var simulateIndex = 0; + var removes = []; + var inserts = []; + var simulateItem; - empty__qmark__: function (collection) { - return collection.length === 0; - }, + for (var k = 0; k < bChildren.length;) { + var wantedItem = bChildren[k]; + simulateItem = simulate[simulateIndex]; - fetch: function (collection, n) { - if (Array.isArray(collection)) { - if (n < this.count(collection) && n >= 0) { - return new Tuple(Symbol.for("ok"), collection[n]); - } else { - return Symbol.for("error"); - } - } + // remove items + while (simulateItem === null && simulate.length) { + removes.push(remove(simulate, simulateIndex, null)); + simulateItem = simulate[simulateIndex]; + } - throw new Error("collection is not an Enumerable"); - }, + if (!simulateItem || simulateItem.key !== wantedItem.key) { + // if we need a key in this position... + if (wantedItem.key) { + if (simulateItem && simulateItem.key) { + // if an insert doesn't put this key in place, it needs to move + if (bKeys[simulateItem.key] !== k + 1) { + removes.push(remove(simulate, simulateIndex, simulateItem.key)); + simulateItem = simulate[simulateIndex]; + // if the remove didn't put the wanted item in place, we need to insert it + if (!simulateItem || simulateItem.key !== wantedItem.key) { + inserts.push({ key: wantedItem.key, to: k }); + } + // items are matching, so skip ahead + else { + simulateIndex++; + } + } else { + inserts.push({ key: wantedItem.key, to: k }); + } + } else { + inserts.push({ key: wantedItem.key, to: k }); + } + k++; + } + // a key in simulate has no matching wanted key, remove it + else if (simulateItem && simulateItem.key) { + removes.push(remove(simulate, simulateIndex, simulateItem.key)); + } + } else { + simulateIndex++; + k++; + } + } - fetch__emark__: function (collection, n) { - if (Array.isArray(collection)) { - if (n < this.count(collection) && n >= 0) { - return collection[n]; - } else { - throw new Error("out of bounds error"); - } - } + // remove all the remaining nodes from simulate + while (simulateIndex < simulate.length) { + simulateItem = simulate[simulateIndex]; + removes.push(remove(simulate, simulateIndex, simulateItem && simulateItem.key)); + } - throw new Error("collection is not an Enumerable"); - }, + // If the only moves we have are deletes then we can just + // let the delete patch remove these items. + if (removes.length === deletedItems && !inserts.length) { + return { + children: newChildren, + moves: null + }; + } - filter: function (collection, fun) { - let result = []; + return { + children: newChildren, + moves: { + removes: removes, + inserts: inserts + } + }; + } - for (let elem of collection) { - if (fun(elem)) { - result.push(elem); - } - } + function remove(arr, index, key) { + arr.splice(index, 1); - return result; - }, + return { + from: index, + key: key + }; + } - filter_map: function (collection, filter, mapper) { - return Enum.map(Enum.filter(collection, filter), mapper); - }, + function keyIndex(children) { + var keys = {}; + var free = []; + var length = children.length; - find: function (collection, if_none = null, fun) { - for (let elem of collection) { - if (fun(elem)) { - return elem; - } - } + for (var i = 0; i < length; i++) { + var child = children[i]; - return if_none; - }, + if (child.key) { + keys[child.key] = i; + } else { + free.push(i); + } + } - into: function (collection, list) { - return list.concat(collection); - }, + return { + keys: keys, // A hash of key name to index + free: free // An array of unkeyed item indices + }; + } - map: function (collection, fun) { - let result = []; + function appendPatch(apply, patch) { + if (apply) { + if (isArray(apply)) { + apply.push(patch); + } else { + apply = [apply, patch]; + } - for (let elem of collection) { - result.push(fun(elem)); - } + return apply; + } else { + return patch; + } + } + }, { "../vnode/handle-thunk": 24, "../vnode/is-thunk": 25, "../vnode/is-vnode": 27, "../vnode/is-vtext": 28, "../vnode/is-widget": 29, "../vnode/vpatch": 32, "./diff-props": 34, "x-is-array": 12 }] }, {}, [4])(4); +}); - return result; - }, +/* @flow */ - map_reduce: function (collection, acc, fun) { - let mapped = Object.freeze([]); - let the_acc = acc; +class Mailbox { - for (var i = 0; i < this.count(collection); i++) { - let tuple = fun(collection[i], the_acc); + constructor() { + this.messages = []; + } - the_acc = tuple.get(1); - mapped = Object.freeze(mapped.concat([tuple.get(0)])); - } + deliver(message) { + this.messages.push(message); + return message; + } - return new Tuple(mapped, the_acc); - }, + get() { + return this.messages; + } - member__qmark__: function (collection, value) { - return collection.includes(value); - }, + isEmpty() { + return this.messages.length === 0; + } - reduce: function (collection, acc, fun) { - let the_acc = acc; + removeAt(index) { + this.messages.splice(index, 1); + } +} - for (var i = 0; i < this.count(collection); i++) { - let tuple = fun(collection[i], the_acc); +var States = { + NORMAL: Symbol.for("normal"), + KILL: Symbol.for("kill"), + SUSPEND: Symbol.for("suspend"), + CONTINUE: Symbol.for("continue"), + RECEIVE: Symbol.for("receive"), + SEND: Symbol.for("send"), + SLEEPING: Symbol.for("sleeping"), + RUNNING: Symbol.for("running"), + SUSPENDED: Symbol.for("suspended"), + STOPPED: Symbol.for("stopped"), + SLEEP: Symbol.for("sleep"), + EXIT: Symbol.for("exit"), + NOMATCH: Symbol.for("no_match") +}; - the_acc = tuple.get(1); - } +class Process { - return the_acc; - }, + constructor(pid, mailbox) { + this.pid = pid; + this.mailbox = mailbox; + this.status = States.STOPPED; + this.dict = {}; + } +} - take: function (collection, count) { - return collection.slice(0, count); - }, +class Tuple { - take_every: function (collection, nth) { - let result = []; - let index = 0; + constructor(...args) { + this.values = Object.freeze(args); + this.length = this.values.length; + } - for (let elem of collection) { - if (index % nth === 0) { - result.push(elem); - } - } + get(index) { + return this.values[index]; + } - return Object.freeze(result); - }, + count() { + return this.values.length; + } - take_while: function (collection, fun) { - let count = 0; + [Symbol.iterator]() { + return this.values[Symbol.iterator](); + } - for (let elem of collection) { - if (fun(elem)) { - count = count + 1; - } else { - break; + toString() { + var i, + s = ""; + for (i = 0; i < this.values.length; i++) { + if (s !== "") { + s += ", "; } + s += this.values[i].toString(); } - return collection.slice(0, count); - }, - - to_list: function (collection) { - return collection; + return "{" + s + "}"; } -}; - -let VirtualDOM = (function (e) { - return e(); -})(function () { - var define, module, exports; - return (function e(t, n, r) { - function s(o, u) { - if (!n[o]) { - if (!t[o]) { - var a = typeof require == "function" && require; - if (!u && a) return a(o, !0); - if (i) return i(o, !0); - var f = new Error("Cannot find module '" + o + "'"); - throw (f.code = "MODULE_NOT_FOUND", f); - } - var l = n[o] = { - exports: {} - }; - t[o][0].call(l.exports, function (e) { - var n = t[o][1][e]; - return s(n ? n : e); - }, l, l.exports, e, t, n, r); - } - return n[o].exports; - } - var i = typeof require == "function" && require; - for (var o = 0; o < r.length; o++) s(r[o]); - return s; - })({ - 1: [function (require, module, exports) { - - var createElement = require("./vdom/create-element.js"); - module.exports = createElement; - }, { "./vdom/create-element.js": 15 }], 2: [function (require, module, exports) { - var diff = require("./vtree/diff.js"); +} - module.exports = diff; - }, { "./vtree/diff.js": 35 }], 3: [function (require, module, exports) { - var h = require("./virtual-hyperscript/index.js"); +let process_counter = -1; - module.exports = h; - }, { "./virtual-hyperscript/index.js": 22 }], 4: [function (require, module, exports) { - var diff = require("./diff.js"); - var patch = require("./patch.js"); - var h = require("./h.js"); - var create = require("./create-element.js"); - var VNode = require("./vnode/vnode.js"); - var VText = require("./vnode/vtext.js"); +class PID { + constructor() { + process_counter = process_counter + 1; + this.id = process_counter; + } - module.exports = { - diff: diff, - patch: patch, - h: h, - create: create, - VNode: VNode, - VText: VText - }; - }, { "./create-element.js": 1, "./diff.js": 2, "./h.js": 3, "./patch.js": 13, "./vnode/vnode.js": 31, "./vnode/vtext.js": 33 }], 5: [function (require, module, exports) { - /*! - * Cross-Browser Split 1.1.1 - * Copyright 2007-2012 Steven Levithan - * Available under the MIT License - * ECMAScript compliant, uniform cross-browser split method - */ + toString() { + return "PID#<0." + this.id + ".0>"; + } +} - /** - * Splits a string into an array of strings using a regex or string separator. Matches of the - * separator are not included in the result array. However, if `separator` is a regex that contains - * capturing groups, backreferences are spliced into the result each time `separator` is matched. - * Fixes browser bugs compared to the native `String.prototype.split` and can be used reliably - * cross-browser. - * @param {String} str String to split. - * @param {RegExp|String} separator Regex or string to use for separating the string. - * @param {Number} [limit] Maximum number of items to include in the result array. - * @returns {Array} Array of substrings. - * @example - * - * // Basic use - * split('a b c d', ' '); - * // -> ['a', 'b', 'c', 'd'] - * - * // With limit - * split('a b c d', ' ', 2); - * // -> ['a', 'b'] - * - * // Backreferences in result array - * split('..word1 word2..', /([a-z]+)(\d+)/i); - * // -> ['..', 'word', '1', ' ', 'word', '2', '..'] - */ - module.exports = (function split(undef) { +class Integer {} +class Float {} - var nativeSplit = String.prototype.split, - compliantExecNpcg = /()??/.exec("")[1] === undef, +class ProcessSystem { - // NPCG: nonparticipating capturing group - self; + constructor() { + this.pids = new Map(); + this.mailboxes = new Map(); + this.names = new Map(); + this.links = new Map(); - self = function (str, separator, limit) { - // If `separator` is not a regex, use `nativeSplit` - if (Object.prototype.toString.call(separator) !== "[object RegExp]") { - return nativeSplit.call(str, separator, limit); - } - var output = [], - flags = (separator.ignoreCase ? "i" : "") + (separator.multiline ? "m" : "") + (separator.extended ? "x" : "") + (separator.sticky ? "y" : ""), + this.current_process = null; + this.suspended = new Map(); - // Firefox 3+ - lastLastIndex = 0, + this.main_process_pid = this.spawn(); + this.set_current(this.main_process_pid); + } - // Make `global` and avoid `lastIndex` issues by working with a copy - separator = new RegExp(separator.source, flags + "g"), - separator2, - match, - lastIndex, - lastLength; - str += ""; // Type-convert - if (!compliantExecNpcg) { - // Doesn't need flags gy, but they don't hurt - separator2 = new RegExp("^" + separator.source + "$(?!\\s)", flags); - } - /* Values for `limit`, per the spec: - * If undefined: 4294967295 // Math.pow(2, 32) - 1 - * If 0, Infinity, or NaN: 0 - * If positive number: limit = Math.floor(limit); if (limit > 4294967295) limit -= 4294967296; - * If negative number: 4294967296 - Math.floor(Math.abs(limit)) - * If other: Type-convert, then use the above rules - */ - limit = limit === undef ? -1 >>> 0 : // Math.pow(2, 32) - 1 - limit >>> 0; // ToUint32(limit) - while (match = separator.exec(str)) { - // `separator.lastIndex` is not reliable cross-browser - lastIndex = match.index + match[0].length; - if (lastIndex > lastLastIndex) { - output.push(str.slice(lastLastIndex, match.index)); - // Fix browsers whose `exec` methods don't consistently return `undefined` for - // nonparticipating capturing groups - if (!compliantExecNpcg && match.length > 1) { - match[0].replace(separator2, function () { - for (var i = 1; i < arguments.length - 2; i++) { - if (arguments[i] === undef) { - match[i] = undef; - } - } - }); - } - if (match.length > 1 && match.index < str.length) { - Array.prototype.push.apply(output, match.slice(1)); - } - lastLength = match[0].length; - lastLastIndex = lastIndex; - if (output.length >= limit) { - break; - } - } - if (separator.lastIndex === match.index) { - separator.lastIndex++; // Avoid an infinite loop - } - } - if (lastLastIndex === str.length) { - if (lastLength || !separator.test("")) { - output.push(""); - } - } else { - output.push(str.slice(lastLastIndex)); - } - return output.length > limit ? output.slice(0, limit) : output; - }; + spawn() { + return this.add_proc(false).pid; + } - return self; - })(); - }, {}], 6: [function (require, module, exports) {}, {}], 7: [function (require, module, exports) { - "use strict"; + spawn_link() { + return this.add_proc(true).pid; + } - var OneVersionConstraint = require("individual/one-version"); + link(pid) { + this.links.get(this.pid()).add(pid); + this.links.get(pid).add(this.pid()); + } - var MY_VERSION = "7"; - OneVersionConstraint("ev-store", MY_VERSION); + unlink(pid) { + this.links.get(this.pid()).delete(pid); + this.links.get(pid).delete(this.pid()); + } - var hashKey = "__EV_STORE_KEY@" + MY_VERSION; + set_current(id) { + let pid = this.pidof(id); + if (pid !== null) { + this.current_process = this.pids.get(pid); + this.current_process.status = States.RUNNING; + } + } - module.exports = EvStore; + add_proc(linked) { + let newpid = new PID(); + let mailbox = new Mailbox(); + let newproc = new Process(newpid, mailbox); - function EvStore(elem) { - var hash = elem[hashKey]; + this.pids.set(newpid, newproc); + this.mailboxes.set(newpid, mailbox); + this.links.set(newpid, new Set()); - if (!hash) { - hash = elem[hashKey] = {}; - } + if (linked) { + this.link(newpid); + } - return hash; - } - }, { "individual/one-version": 9 }], 8: [function (require, module, exports) { - (function (global) { - "use strict"; + return newproc; + } - /*global window, global*/ + remove_proc(pid) { + this.pids.delete(pid); + this.unregister(pid); - var root = typeof window !== "undefined" ? window : typeof global !== "undefined" ? global : {}; + if (this.links.has(pid)) { + for (let linkpid of this.links.get(pid)) { + this.links.get(linkpid).delete(pid); + } - module.exports = Individual; + this.links.delete(pid); + } + } - function Individual(key, value) { - if (key in root) { - return root[key]; - } + exit(id) { + let pid = this.pidof(id); + this.remove_proc(id); + } - root[key] = value; + register(name, pid) { + if (!this.names.has(name)) { + this.names.set(name, pid); + return name; + } else { + throw new Error("Name is already registered to another process"); + } + } - return value; - } - }).call(this, typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}); - }, {}], 9: [function (require, module, exports) { - "use strict"; + registered(name) { + return this.names.has(name) ? this.names.get(name) : null; + } - var Individual = require("./index.js"); + unregister(pid) { + for (let name of this.names.keys()) { + if (this.names.has(name) && this.names.get(name) === pid) { + this.names.delete(name); + } + } + } - module.exports = OneVersion; + pid() { + return this.current_process.pid; + } - function OneVersion(moduleName, version, defaultValue) { - var key = "__INDIVIDUAL_ONE_VERSION_" + moduleName; - var enforceKey = key + "_ENFORCE_SINGLETON"; + pidof(id) { + if (id instanceof PID) { + return this.pids.has(id) ? id : null; + } else if (id instanceof Process) { + return id.pid; + } else { + let pid = this.registered(id); + if (pid === null) throw "Process name not registered: " + id + " (" + typeof id + ")"; + return pid; + } + } - var versionValue = Individual(enforceKey, version); + put(id, key, value) { + let pid = this.pidof(id); + let process = this.pids.get(pid); + process.dict[key] = value; + } - if (versionValue !== version) { - throw new Error("Can only have one copy of " + moduleName + ".\n" + "You already have version " + versionValue + " installed.\n" + "This means you cannot install version " + version); - } + get(id, key) { + let pid = this.pidof(id); + let process = this.pids.get(pid); - return Individual(key, defaultValue); - } - }, { "./index.js": 8 }], 10: [function (require, module, exports) { - (function (global) { - var topLevel = typeof global !== "undefined" ? global : typeof window !== "undefined" ? window : {}; - var minDoc = require("min-document"); + if (key != null) { + return process.dict[key]; + } else { + return process.dict; + } + } - if (typeof document !== "undefined") { - module.exports = document; - } else { - var doccy = topLevel["__GLOBAL_DOCUMENT_CACHE@4"]; + get_keys(id) { + let pid = this.pidof(id); + let process = this.pids.get(pid); - if (!doccy) { - doccy = topLevel["__GLOBAL_DOCUMENT_CACHE@4"] = minDoc; - } + return Object.keys(process.dict); + } - module.exports = doccy; - } - }).call(this, typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}); - }, { "min-document": 6 }], 11: [function (require, module, exports) { - "use strict"; + erase(id, key) { + let pid = this.pidof(id); + let process = this.pids.get(pid); - module.exports = function isObject(x) { - return typeof x === "object" && x !== null; - }; - }, {}], 12: [function (require, module, exports) { - var nativeIsArray = Array.isArray; - var toString = Object.prototype.toString; + if (key != null) { + delete process.dict[key]; + } else { + process.dict = {}; + } + } +} - module.exports = nativeIsArray || isArray; +class BitString { + constructor(...args) { + this.raw_value = function () { + return Object.freeze(args); + }; - function isArray(obj) { - return toString.call(obj) === "[object Array]"; - } - }, {}], 13: [function (require, module, exports) { - var patch = require("./vdom/patch.js"); + this.value = Object.freeze(this.process(args)); + } - module.exports = patch; - }, { "./vdom/patch.js": 18 }], 14: [function (require, module, exports) { - var isObject = require("is-object"); - var isHook = require("../vnode/is-vhook.js"); + get(index) { + return this.value[index]; + } - module.exports = applyProperties; + count() { + return this.value.length; + } - function applyProperties(node, props, previous) { - for (var propName in props) { - var propValue = props[propName]; + [Symbol.iterator]() { + return this.value[Symbol.iterator](); + } - if (propValue === undefined) { - removeProperty(node, propName, propValue, previous); - } else if (isHook(propValue)) { - removeProperty(node, propName, propValue, previous); - if (propValue.hook) { - propValue.hook(node, propName, previous ? previous[propName] : undefined); - } - } else { - if (isObject(propValue)) { - patchObject(node, props, previous, propName, propValue); - } else { - node[propName] = propValue; - } - } - } - } + toString() { + var i, + s = ""; + for (i = 0; i < this.count(); i++) { + if (s !== "") { + s += ", "; + } + s += this[i].toString(); + } + + return "<<" + s + ">>"; + } + + process() { + let processed_values = []; + + var i; + for (i = 0; i < this.raw_value().length; i++) { + let processed_value = this["process_" + this.raw_value()[i].type](this.raw_value()[i]); + + for (let attr of this.raw_value()[i].attributes) { + processed_value = this["process_" + attr](processed_value); + } + + processed_values = processed_values.concat(processed_value); + } + + return processed_values; + } + + process_integer(value) { + return value.value; + } + + process_float(value) { + if (value.size === 64) { + return BitString.float64ToBytes(value.value); + } else if (value.size === 32) { + return BitString.float32ToBytes(value.value); + } - function removeProperty(node, propName, propValue, previous) { - if (previous) { - var previousValue = previous[propName]; + throw new Error("Invalid size for float"); + } - if (!isHook(previousValue)) { - if (propName === "attributes") { - for (var attrName in previousValue) { - node.removeAttribute(attrName); - } - } else if (propName === "style") { - for (var i in previousValue) { - node.style[i] = ""; - } - } else if (typeof previousValue === "string") { - node[propName] = ""; - } else { - node[propName] = null; - } - } else if (previousValue.unhook) { - previousValue.unhook(node, propName, propValue); - } - } - } + process_bitstring(value) { + return value.value.value; + } - function patchObject(node, props, previous, propName, propValue) { - var previousValue = previous ? previous[propName] : undefined; + process_binary(value) { + return BitString.toUTF8Array(value.value); + } - // Set attributes - if (propName === "attributes") { - for (var attrName in propValue) { - var attrValue = propValue[attrName]; + process_utf8(value) { + return BitString.toUTF8Array(value.value); + } - if (attrValue === undefined) { - node.removeAttribute(attrName); - } else { - node.setAttribute(attrName, attrValue); - } - } + process_utf16(value) { + return BitString.toUTF16Array(value.value); + } - return; - } + process_utf32(value) { + return BitString.toUTF32Array(value.value); + } - if (previousValue && isObject(previousValue) && getPrototype(previousValue) !== getPrototype(propValue)) { - node[propName] = propValue; - return; - } + process_signed(value) { + return new Uint8Array([value])[0]; + } - if (!isObject(node[propName])) { - node[propName] = {}; - } + process_unsigned(value) { + return value; + } - var replacer = propName === "style" ? "" : undefined; + process_native(value) { + return value; + } - for (var k in propValue) { - var value = propValue[k]; - node[propName][k] = value === undefined ? replacer : value; - } - } + process_big(value) { + return value; + } - function getPrototype(value) { - if (Object.getPrototypeOf) { - return Object.getPrototypeOf(value); - } else if (value.__proto__) { - return value.__proto__; - } else if (value.constructor) { - return value.constructor.prototype; - } - } - }, { "../vnode/is-vhook.js": 26, "is-object": 11 }], 15: [function (require, module, exports) { - var document = require("global/document"); + process_little(value) { + return value.reverse(); + } - var applyProperties = require("./apply-properties"); + process_size(value) { + return value; + } - var isVNode = require("../vnode/is-vnode.js"); - var isVText = require("../vnode/is-vtext.js"); - var isWidget = require("../vnode/is-widget.js"); - var handleThunk = require("../vnode/handle-thunk.js"); + process_unit(value) { + return value; + } - module.exports = createElement; + static integer(value) { + return BitString.wrap(value, { "type": "integer", "unit": 1, "size": 8 }); + } - function createElement(vnode, opts) { - var doc = opts ? opts.document || document : document; - var warn = opts ? opts.warn : null; + static float(value) { + return BitString.wrap(value, { "type": "float", "unit": 1, "size": 64 }); + } - vnode = handleThunk(vnode).a; + static bitstring(value) { + return BitString.wrap(value, { "type": "bitstring", "unit": 1, "size": value.length }); + } - if (isWidget(vnode)) { - return vnode.init(); - } else if (isVText(vnode)) { - return doc.createTextNode(vnode.text); - } else if (!isVNode(vnode)) { - if (warn) { - warn("Item is not a valid virtual dom node", vnode); - } - return null; - } + static bits(value) { + return BitString.bitstring(value); + } - var node = vnode.namespace === null ? doc.createElement(vnode.tagName) : doc.createElementNS(vnode.namespace, vnode.tagName); + static binary(value) { + return BitString.wrap(value, { "type": "binary", "unit": 8, "size": value.length }); + } - var props = vnode.properties; - applyProperties(node, props); + static bytes(value) { + return BitString.binary(value); + } - var children = vnode.children; + static utf8(value) { + return BitString.wrap(value, { "type": "utf8" }); + } - for (var i = 0; i < children.length; i++) { - var childNode = createElement(children[i], opts); - if (childNode) { - node.appendChild(childNode); - } - } + static utf16(value) { + return BitString.wrap(value, { "type": "utf16" }); + } - return node; - } - }, { "../vnode/handle-thunk.js": 24, "../vnode/is-vnode.js": 27, "../vnode/is-vtext.js": 28, "../vnode/is-widget.js": 29, "./apply-properties": 14, "global/document": 10 }], 16: [function (require, module, exports) { - // Maps a virtual DOM tree onto a real DOM tree in an efficient manner. - // We don't want to read all of the DOM nodes in the tree so we use - // the in-order tree indexing to eliminate recursion down certain branches. - // We only recurse into a DOM node if we know that it contains a child of - // interest. + static utf32(value) { + return BitString.wrap(value, { "type": "utf32" }); + } - var noChild = {}; + static signed(value) { + return BitString.wrap(value, {}, "signed"); + } - module.exports = domIndex; + static unsigned(value) { + return BitString.wrap(value, {}, "unsigned"); + } - function domIndex(rootNode, tree, indices, nodes) { - if (!indices || indices.length === 0) { - return {}; - } else { - indices.sort(ascending); - return recurse(rootNode, tree, indices, nodes, 0); - } - } + static native(value) { + return BitString.wrap(value, {}, "native"); + } - function recurse(rootNode, tree, indices, nodes, rootIndex) { - nodes = nodes || {}; + static big(value) { + return BitString.wrap(value, {}, "big"); + } - if (rootNode) { - if (indexInRange(indices, rootIndex, rootIndex)) { - nodes[rootIndex] = rootNode; - } + static little(value) { + return BitString.wrap(value, {}, "little"); + } - var vChildren = tree.children; + static size(value, count) { + return BitString.wrap(value, { "size": count }); + } - if (vChildren) { + static unit(value, count) { + return BitString.wrap(value, { "unit": count }); + } - var childNodes = rootNode.childNodes; + static wrap(value, opt, new_attribute = null) { + let the_value = value; - for (var i = 0; i < tree.children.length; i++) { - rootIndex += 1; + if (!(value instanceof Object)) { + the_value = { "value": value, "attributes": [] }; + } - var vChild = vChildren[i] || noChild; - var nextIndex = rootIndex + (vChild.count || 0); + the_value = Object.assign(the_value, opt); - // skip recursion down the tree if there are no nodes down here - if (indexInRange(indices, rootIndex, nextIndex)) { - recurse(childNodes[i], vChild, indices, nodes, rootIndex); - } + if (new_attribute) { + the_value.attributes.push(new_attribute); + } + + return the_value; + } + + static toUTF8Array(str) { + var utf8 = []; + for (var i = 0; i < str.length; i++) { + var charcode = str.charCodeAt(i); + if (charcode < 128) { + utf8.push(charcode); + } else if (charcode < 2048) { + utf8.push(192 | charcode >> 6, 128 | charcode & 63); + } else if (charcode < 55296 || charcode >= 57344) { + utf8.push(224 | charcode >> 12, 128 | charcode >> 6 & 63, 128 | charcode & 63); + } + // surrogate pair + else { + i++; + // UTF-16 encodes 0x10000-0x10FFFF by + // subtracting 0x10000 and splitting the + // 20 bits of 0x0-0xFFFFF into two halves + charcode = 65536 + ((charcode & 1023) << 10 | str.charCodeAt(i) & 1023); + utf8.push(240 | charcode >> 18, 128 | charcode >> 12 & 63, 128 | charcode >> 6 & 63, 128 | charcode & 63); + } + } + return utf8; + } + + static toUTF16Array(str) { + var utf16 = []; + for (var i = 0; i < str.length; i++) { + var codePoint = str.codePointAt(i); + + if (codePoint <= 255) { + utf16.push(0); + utf16.push(codePoint); + } else { + utf16.push(codePoint >> 8 & 255); + utf16.push(codePoint & 255); + } + } + return utf16; + } - rootIndex = nextIndex; - } - } - } + static toUTF32Array(str) { + var utf32 = []; + for (var i = 0; i < str.length; i++) { + var codePoint = str.codePointAt(i); - return nodes; - } + if (codePoint <= 255) { + utf32.push(0); + utf32.push(0); + utf32.push(0); + utf32.push(codePoint); + } else { + utf32.push(0); + utf32.push(0); + utf32.push(codePoint >> 8 & 255); + utf32.push(codePoint & 255); + } + } + return utf32; + } - // Binary search for an index in the interval [left, right] - function indexInRange(indices, left, right) { - if (indices.length === 0) { - return false; - } + //http://stackoverflow.com/questions/2003493/javascript-float-from-to-bits + static float32ToBytes(f) { + var bytes = []; - var minIndex = 0; - var maxIndex = indices.length - 1; - var currentIndex; - var currentItem; + var buf = new ArrayBuffer(4); + new Float32Array(buf)[0] = f; - while (minIndex <= maxIndex) { - currentIndex = (maxIndex + minIndex) / 2 >> 0; - currentItem = indices[currentIndex]; + let intVersion = new Uint32Array(buf)[0]; - if (minIndex === maxIndex) { - return currentItem >= left && currentItem <= right; - } else if (currentItem < left) { - minIndex = currentIndex + 1; - } else if (currentItem > right) { - maxIndex = currentIndex - 1; - } else { - return true; - } - } + bytes.push(intVersion >> 24 & 255); + bytes.push(intVersion >> 16 & 255); + bytes.push(intVersion >> 8 & 255); + bytes.push(intVersion & 255); - return false; - } + return bytes; + } - function ascending(a, b) { - return a > b ? 1 : -1; - } - }, {}], 17: [function (require, module, exports) { - var applyProperties = require("./apply-properties"); + static float64ToBytes(f) { + var bytes = []; - var isWidget = require("../vnode/is-widget.js"); - var VPatch = require("../vnode/vpatch.js"); + var buf = new ArrayBuffer(8); + new Float64Array(buf)[0] = f; - var updateWidget = require("./update-widget"); + var intVersion1 = new Uint32Array(buf)[0]; + var intVersion2 = new Uint32Array(buf)[1]; - module.exports = applyPatch; + bytes.push(intVersion2 >> 24 & 255); + bytes.push(intVersion2 >> 16 & 255); + bytes.push(intVersion2 >> 8 & 255); + bytes.push(intVersion2 & 255); - function applyPatch(vpatch, domNode, renderOptions) { - var type = vpatch.type; - var vNode = vpatch.vNode; - var patch = vpatch.patch; + bytes.push(intVersion1 >> 24 & 255); + bytes.push(intVersion1 >> 16 & 255); + bytes.push(intVersion1 >> 8 & 255); + bytes.push(intVersion1 & 255); - switch (type) { - case VPatch.REMOVE: - return removeNode(domNode, vNode); - case VPatch.INSERT: - return insertNode(domNode, patch, renderOptions); - case VPatch.VTEXT: - return stringPatch(domNode, vNode, patch, renderOptions); - case VPatch.WIDGET: - return widgetPatch(domNode, vNode, patch, renderOptions); - case VPatch.VNODE: - return vNodePatch(domNode, vNode, patch, renderOptions); - case VPatch.ORDER: - reorderChildren(domNode, patch); - return domNode; - case VPatch.PROPS: - applyProperties(domNode, patch, vNode.properties); - return domNode; - case VPatch.THUNK: - return replaceRoot(domNode, renderOptions.patch(domNode, patch, renderOptions)); - default: - return domNode; - } - } + return bytes; + } +} - function removeNode(domNode, vNode) { - var parentNode = domNode.parentNode; +/* @flow */ - if (parentNode) { - parentNode.removeChild(domNode); - } +class Variable { - destroyWidget(domNode, vNode); + constructor(name = null) { + this.name = name; + } +} - return null; - } +class Wildcard { + constructor() {} +} - function insertNode(parentNode, vNode, renderOptions) { - var newNode = renderOptions.render(vNode, renderOptions); +class StartsWith { - if (parentNode) { - parentNode.appendChild(newNode); - } + constructor(prefix) { + this.prefix = prefix; + } +} - return parentNode; - } +class Capture { - function stringPatch(domNode, leftVNode, vText, renderOptions) { - var newNode; + constructor(value) { + this.value = value; + } +} - if (domNode.nodeType === 3) { - domNode.replaceData(0, domNode.length, vText.text); - newNode = domNode; - } else { - var parentNode = domNode.parentNode; - newNode = renderOptions.render(vText, renderOptions); +class HeadTail { + constructor() {} +} - if (parentNode && newNode !== domNode) { - parentNode.replaceChild(newNode, domNode); - } - } +class Type { - return newNode; - } + constructor(type, objPattern = {}) { + this.type = type; + this.objPattern = objPattern; + } +} - function widgetPatch(domNode, leftVNode, widget, renderOptions) { - var updating = updateWidget(leftVNode, widget); - var newNode; +class Bound { - if (updating) { - newNode = widget.update(leftVNode, domNode) || domNode; - } else { - newNode = renderOptions.render(widget, renderOptions); - } + constructor(value) { + this.value = value; + } +} - var parentNode = domNode.parentNode; +function variable(name = null) { + return new Variable(name); +} - if (parentNode && newNode !== domNode) { - parentNode.replaceChild(newNode, domNode); - } +function wildcard() { + return new Wildcard(); +} - if (!updating) { - destroyWidget(domNode, leftVNode); - } +function startsWith(prefix) { + return new StartsWith(prefix); +} - return newNode; - } +function capture(value) { + return new Capture(value); +} - function vNodePatch(domNode, leftVNode, vNode, renderOptions) { - var parentNode = domNode.parentNode; - var newNode = renderOptions.render(vNode, renderOptions); +function headTail() { + return new HeadTail(); +} - if (parentNode && newNode !== domNode) { - parentNode.replaceChild(newNode, domNode); - } +function type(type, objPattern = {}) { + return new Type(type, objPattern); +} - return newNode; - } +function bound(value) { + return new Bound(value); +} - function destroyWidget(domNode, w) { - if (typeof w.destroy === "function" && isWidget(w)) { - w.destroy(domNode); - } - } +function is_number(value) { + return typeof value === 'number'; +} - function reorderChildren(domNode, moves) { - var childNodes = domNode.childNodes; - var keyMap = {}; - var node; - var remove; - var insert; +function is_string(value) { + return typeof value === 'string'; +} - for (var i = 0; i < moves.removes.length; i++) { - remove = moves.removes[i]; - node = childNodes[remove.from]; - if (remove.key) { - keyMap[remove.key] = node; - } - domNode.removeChild(node); - } +function is_boolean(value) { + return typeof value === 'boolean'; +} - var length = childNodes.length; - for (var j = 0; j < moves.inserts.length; j++) { - insert = moves.inserts[j]; - node = keyMap[insert.key]; - // this is the weirdest bug i've ever seen in webkit - domNode.insertBefore(node, insert.to >= length++ ? null : childNodes[insert.to]); - } - } +function is_symbol(value) { + return typeof value === 'symbol'; +} - function replaceRoot(oldRoot, newRoot) { - if (oldRoot && newRoot && oldRoot !== newRoot && oldRoot.parentNode) { - oldRoot.parentNode.replaceChild(newRoot, oldRoot); - } +function is_null(value) { + return value === null; +} - return newRoot; - } - }, { "../vnode/is-widget.js": 29, "../vnode/vpatch.js": 32, "./apply-properties": 14, "./update-widget": 19 }], 18: [function (require, module, exports) { - var document = require("global/document"); - var isArray = require("x-is-array"); +function is_undefined(value) { + return typeof value === 'undefined'; +} - var render = require("./create-element"); - var domIndex = require("./dom-index"); - var patchOp = require("./patch-op"); - module.exports = patch; +function is_function(value) { + return Object.prototype.toString.call(value) == '[object Function]'; +} - function patch(rootNode, patches, renderOptions) { - renderOptions = renderOptions || {}; - renderOptions.patch = renderOptions.patch && renderOptions.patch !== patch ? renderOptions.patch : patchRecursive; - renderOptions.render = renderOptions.render || render; +function is_variable(value) { + return value instanceof Variable; +} - return renderOptions.patch(rootNode, patches, renderOptions); - } +function is_wildcard(value) { + return value instanceof Wildcard; +} - function patchRecursive(rootNode, patches, renderOptions) { - var indices = patchIndices(patches); +function is_headTail(value) { + return value instanceof HeadTail; +} - if (indices.length === 0) { - return rootNode; - } +function is_capture(value) { + return value instanceof Capture; +} - var index = domIndex(rootNode, patches.a, indices); - var ownerDocument = rootNode.ownerDocument; +function is_type(value) { + return value instanceof Type; +} - if (!renderOptions.document && ownerDocument !== document) { - renderOptions.document = ownerDocument; - } +function is_startsWith(value) { + return value instanceof StartsWith; +} - for (var i = 0; i < indices.length; i++) { - var nodeIndex = indices[i]; - rootNode = applyPatch(rootNode, index[nodeIndex], patches[nodeIndex], renderOptions); - } +function is_bound(value) { + return value instanceof Bound; +} - return rootNode; - } +function is_object(value) { + return typeof value === 'object'; +} - function applyPatch(rootNode, domNode, patchList, renderOptions) { - if (!domNode) { - return rootNode; - } +function is_array(value) { + return Array.isArray(value); +} - var newNode; +var Checks = { + is_number, + is_string, + is_boolean, + is_symbol, + is_null, + is_undefined, + is_function, + is_variable, + is_wildcard, + is_headTail, + is_capture, + is_type, + is_startsWith, + is_bound, + is_object, + is_array +}; - if (isArray(patchList)) { - for (var i = 0; i < patchList.length; i++) { - newNode = patchOp(patchList[i], domNode, renderOptions); +function resolveSymbol(pattern) { + return function (value) { + return Checks.is_symbol(value) && value === pattern; + }; +} - if (domNode === rootNode) { - rootNode = newNode; - } - } - } else { - newNode = patchOp(patchList, domNode, renderOptions); +function resolveString(pattern) { + return function (value) { + return Checks.is_string(value) && value === pattern; + }; +} - if (domNode === rootNode) { - rootNode = newNode; - } - } +function resolveNumber(pattern) { + return function (value) { + return Checks.is_number(value) && value === pattern; + }; +} - return rootNode; - } +function resolveBoolean(pattern) { + return function (value) { + return Checks.is_boolean(value) && value === pattern; + }; +} - function patchIndices(patches) { - var indices = []; +function resolveFunction(pattern) { + return function (value) { + return Checks.is_function(value) && value === pattern; + }; +} - for (var key in patches) { - if (key !== "a") { - indices.push(Number(key)); - } - } +function resolveNull(pattern) { + return function (value) { + return Checks.is_null(value); + }; +} - return indices; - } - }, { "./create-element": 15, "./dom-index": 16, "./patch-op": 17, "global/document": 10, "x-is-array": 12 }], 19: [function (require, module, exports) { - var isWidget = require("../vnode/is-widget.js"); +function resolveBound(pattern) { + return function (value, args) { + if (typeof value === typeof pattern.value && value === pattern.value) { + args.push(value); + return true; + } - module.exports = updateWidget; + return false; + }; +} - function updateWidget(a, b) { - if (isWidget(a) && isWidget(b)) { - if ("name" in a && "name" in b) { - return a.id === b.id; - } else { - return a.init === b.init; - } - } +function resolveWildcard() { + return function () { + return true; + }; +} - return false; - } - }, { "../vnode/is-widget.js": 29 }], 20: [function (require, module, exports) { - "use strict"; +function resolveVariable() { + return function (value, args) { + args.push(value); + return true; + }; +} - var EvStore = require("ev-store"); +function resolveHeadTail() { + return function (value, args) { + if (!Checks.is_array(value) || value.length < 2) { + return false; + } - module.exports = EvHook; + const head = value[0]; + const tail = value.slice(1); - function EvHook(value) { - if (!(this instanceof EvHook)) { - return new EvHook(value); - } + args.push(head); + args.push(tail); - this.value = value; - } + return true; + }; +} - EvHook.prototype.hook = function (node, propertyName) { - var es = EvStore(node); - var propName = propertyName.substr(3); +function resolveCapture(pattern) { + const matches = buildMatch(pattern.value); - es[propName] = this.value; - }; + return function (value, args) { + if (matches(value, args)) { + args.push(value); + return true; + } - EvHook.prototype.unhook = function (node, propertyName) { - var es = EvStore(node); - var propName = propertyName.substr(3); + return false; + }; +} - es[propName] = undefined; - }; - }, { "ev-store": 7 }], 21: [function (require, module, exports) { - "use strict"; +function resolveStartsWith(pattern) { + const prefix = pattern.prefix; - module.exports = SoftSetHook; + return function (value, args) { + if (Checks.is_string(value) && value.startsWith(prefix)) { + args.push(value.substring(prefix.length)); + return true; + } + + return false; + }; +} + +function resolveType(pattern) { + return function (value, args) { + if (value instanceof pattern.type) { + const matches = buildMatch(pattern.objPattern); + return matches(value, args) && args.push(value) > 0; + } - function SoftSetHook(value) { - if (!(this instanceof SoftSetHook)) { - return new SoftSetHook(value); - } + return false; + }; +} - this.value = value; - } +function resolveArray(pattern) { + const matches = pattern.map(x => buildMatch(x)); - SoftSetHook.prototype.hook = function (node, propertyName) { - if (node[propertyName] !== this.value) { - node[propertyName] = this.value; - } - }; - }, {}], 22: [function (require, module, exports) { - "use strict"; + return function (value, args) { + if (!Checks.is_array(value) || value.length != pattern.length) { + return false; + } - var isArray = require("x-is-array"); + return value.every(function (v, i) { + return matches[i](value[i], args); + }); + }; +} - var VNode = require("../vnode/vnode.js"); - var VText = require("../vnode/vtext.js"); - var isVNode = require("../vnode/is-vnode"); - var isVText = require("../vnode/is-vtext"); - var isWidget = require("../vnode/is-widget"); - var isHook = require("../vnode/is-vhook"); - var isVThunk = require("../vnode/is-thunk"); +function resolveObject(pattern) { + let matches = {}; - var parseTag = require("./parse-tag.js"); - var softSetHook = require("./hooks/soft-set-hook.js"); - var evHook = require("./hooks/ev-hook.js"); + for (let key of Object.keys(pattern).concat(Object.getOwnPropertySymbols(pattern))) { + matches[key] = buildMatch(pattern[key]); + } - module.exports = h; + return function (value, args) { + if (!Checks.is_object(value) || pattern.length > value.length) { + return false; + } - function h(tagName, properties, children) { - var childNodes = []; - var tag, props, key, namespace; + for (let key of Object.keys(pattern).concat(Object.getOwnPropertySymbols(pattern))) { + if (!(key in value) || !matches[key](value[key], args)) { + return false; + } + } - if (!children && isChildren(properties)) { - children = properties; - props = {}; - } + return true; + }; +} - props = props || properties || {}; - tag = parseTag(tagName, props); +function resolveNoMatch() { + return function () { + return false; + }; +} - // support keys - if (props.hasOwnProperty("key")) { - key = props.key; - props.key = undefined; - } +var Resolvers = { + resolveBound, + resolveWildcard, + resolveVariable, + resolveHeadTail, + resolveCapture, + resolveStartsWith, + resolveType, + resolveArray, + resolveObject, + resolveNoMatch, + resolveSymbol, + resolveString, + resolveNumber, + resolveBoolean, + resolveFunction, + resolveNull +}; - // support namespace - if (props.hasOwnProperty("namespace")) { - namespace = props.namespace; - props.namespace = undefined; - } +function buildMatch(pattern) { - // fix cursor bug - if (tag === "INPUT" && !namespace && props.hasOwnProperty("value") && props.value !== undefined && !isHook(props.value)) { - props.value = softSetHook(props.value); - } + if (Checks.is_variable(pattern)) { + return Resolvers.resolveVariable(pattern); + } - transformProperties(props); + if (Checks.is_wildcard(pattern)) { + return Resolvers.resolveWildcard(pattern); + } - if (children !== undefined && children !== null) { - addChild(children, childNodes, tag, props); - } + if (Checks.is_undefined(pattern)) { + return Resolvers.resolveWildcard(pattern); + } - return new VNode(tag, props, childNodes, key, namespace); - } + if (Checks.is_headTail(pattern)) { + return Resolvers.resolveHeadTail(pattern); + } - function addChild(c, childNodes, tag, props) { - if (typeof c === "string") { - childNodes.push(new VText(c)); - } else if (typeof c === "number") { - childNodes.push(new VText(String(c))); - } else if (isChild(c)) { - childNodes.push(c); - } else if (isArray(c)) { - for (var i = 0; i < c.length; i++) { - addChild(c[i], childNodes, tag, props); - } - } else if (c === null || c === undefined) { - return; - } else { - throw UnexpectedVirtualElement({ - foreignObject: c, - parentVnode: { - tagName: tag, - properties: props - } - }); - } - } + if (Checks.is_startsWith(pattern)) { + return Resolvers.resolveStartsWith(pattern); + } - function transformProperties(props) { - for (var propName in props) { - if (props.hasOwnProperty(propName)) { - var value = props[propName]; + if (Checks.is_capture(pattern)) { + return Resolvers.resolveCapture(pattern); + } - if (isHook(value)) { - continue; - } + if (Checks.is_bound(pattern)) { + return Resolvers.resolveBound(pattern); + } - if (propName.substr(0, 3) === "ev-") { - // add ev-foo support - props[propName] = evHook(value); - } - } - } - } + if (Checks.is_type(pattern)) { + return Resolvers.resolveType(pattern); + } - function isChild(x) { - return isVNode(x) || isVText(x) || isWidget(x) || isVThunk(x); - } + if (Checks.is_array(pattern)) { + return Resolvers.resolveArray(pattern); + } - function isChildren(x) { - return typeof x === "string" || isArray(x) || isChild(x); - } + if (Checks.is_number(pattern)) { + return Resolvers.resolveNumber(pattern); + } - function UnexpectedVirtualElement(data) { - var err = new Error(); + if (Checks.is_string(pattern)) { + return Resolvers.resolveString(pattern); + } - err.type = "virtual-hyperscript.unexpected.virtual-element"; - err.message = "Unexpected virtual child passed to h().\n" + "Expected a VNode / Vthunk / VWidget / string but:\n" + "got:\n" + errorString(data.foreignObject) + ".\n" + "The parent vnode is:\n" + errorString(data.parentVnode); - "\n" + "Suggested fix: change your `h(..., [ ... ])` callsite."; - err.foreignObject = data.foreignObject; - err.parentVnode = data.parentVnode; + if (Checks.is_boolean(pattern)) { + return Resolvers.resolveBoolean(pattern); + } - return err; - } + if (Checks.is_symbol(pattern)) { + return Resolvers.resolveSymbol(pattern); + } - function errorString(obj) { - try { - return JSON.stringify(obj, null, " "); - } catch (e) { - return String(obj); - } - } - }, { "../vnode/is-thunk": 25, "../vnode/is-vhook": 26, "../vnode/is-vnode": 27, "../vnode/is-vtext": 28, "../vnode/is-widget": 29, "../vnode/vnode.js": 31, "../vnode/vtext.js": 33, "./hooks/ev-hook.js": 20, "./hooks/soft-set-hook.js": 21, "./parse-tag.js": 23, "x-is-array": 12 }], 23: [function (require, module, exports) { - "use strict"; + if (Checks.is_null(pattern)) { + return Resolvers.resolveNull(pattern); + } - var split = require("browser-split"); + if (Checks.is_object(pattern)) { + return Resolvers.resolveObject(pattern); + } - var classIdSplit = /([\.#]?[a-zA-Z0-9\u007F-\uFFFF_:-]+)/; - var notClassId = /^\.|#/; + return Resolvers.resolveNoMatch(); +} - module.exports = parseTag; +class MatchError extends Error { + constructor(arg) { + super(); - function parseTag(tag, props) { - if (!tag) { - return "DIV"; - } + if (typeof arg === 'symbol') { + this.message = 'No match for: ' + arg.toString(); + } else if (Array.isArray(arg)) { + let mappedValues = arg.map(x => x.toString()); + this.message = 'No match for: ' + mappedValues; + } else { + this.message = 'No match for: ' + arg; + } - var noId = !props.hasOwnProperty("id"); + this.stack = new Error().stack; + this.name = this.constructor.name; + } +} - var tagParts = split(tag, classIdSplit); - var tagName = null; +class Case { - if (notClassId.test(tagParts[1])) { - tagName = "DIV"; - } + constructor(pattern, fn, guard = () => true) { + this.pattern = buildMatch(pattern); + this.fn = fn; + this.guard = guard; + } +} - var classes, part, type, i; +function make_case(pattern, fn, guard = () => true) { + return new Case(pattern, fn, guard); +} - for (i = 0; i < tagParts.length; i++) { - part = tagParts[i]; +function defmatch(...cases) { + return function (...args) { + for (let processedCase of cases) { + let result = []; + if (processedCase.pattern(args, result) && processedCase.guard.apply(this, result)) { + return processedCase.fn.apply(this, result); + } + } - if (!part) { - continue; - } + throw new MatchError(args); + }; +} - type = part.charAt(0); +function match(pattern, expr, guard = () => true) { + let result = []; + let processedPattern = buildMatch(pattern); + if (processedPattern(expr, result) && guard.apply(this, result)) { + return result; + } else { + throw new MatchError(expr); + } +} - if (!tagName) { - tagName = part; - } else if (type === ".") { - classes = classes || []; - classes.push(part.substring(1, part.length)); - } else if (type === "#" && noId) { - props.id = part.substring(1, part.length); - } - } +function match_no_throw(pattern, expr, guard = () => true) { + try { + return match(pattern, expr, guard); + } catch (e) { + if (e instanceof MatchError) { + return null; + } - if (classes) { - if (props.className) { - classes.push(props.className); - } + throw e; + } +} - props.className = classes.join(" "); - } +var Patterns = { + defmatch, match, MatchError, match_no_throw, + variable, wildcard, startsWith, + capture, headTail, type, bound, Case, make_case +}; - return props.namespace ? tagName : tagName.toUpperCase(); - } - }, { "browser-split": 5 }], 24: [function (require, module, exports) { - var isVNode = require("./is-vnode"); - var isVText = require("./is-vtext"); - var isWidget = require("./is-widget"); - var isThunk = require("./is-thunk"); +function call_property(item, property) { + let prop = null; - module.exports = handleThunk; + if (property in item) { + prop = property; + } else if (Symbol.for(property) in item) { + prop = Symbol.for(property); + } else { + throw new Error(`Property ${ property } not found in ${ item }`); + } - function handleThunk(a, b) { - var renderedA = a; - var renderedB = b; + if (item[prop] instanceof Function) { + return item[prop](); + } else { + return item[prop]; + } +} - if (isThunk(b)) { - renderedB = renderThunk(b, a); - } +function apply(...args) { + if (args.length === 2) { + args[0].apply(null, args.slice(1)); + } else { + args[0][args[1]].apply(null, args.slice(2)); + } +} - if (isThunk(a)) { - renderedA = renderThunk(a, null); - } +function contains(left, right) { + for (let x of right) { + if (Patterns.match_no_throw(left, x) != null) { + return true; + } + } - return { - a: renderedA, - b: renderedB - }; - } + return false; +} - function renderThunk(thunk, previous) { - var renderedThunk = thunk.vnode; +function get_global() { + if (typeof self !== 'undefined') { + return self; + } else if (typeof window !== 'undefined') { + return window; + } else if (typeof global !== 'undefined') { + return global; + } - if (!renderedThunk) { - renderedThunk = thunk.vnode = thunk.render(previous); - } + throw new Error('No global state found'); +} - if (!(isVNode(renderedThunk) || isVText(renderedThunk) || isWidget(renderedThunk))) { - throw new Error("thunk did not return a valid node"); - } +function defstruct(defaults) { + return class { + constructor(update = {}) { + let the_values = Object.assign(defaults, update); + Object.assign(this, the_values); + } - return renderedThunk; - } - }, { "./is-thunk": 25, "./is-vnode": 27, "./is-vtext": 28, "./is-widget": 29 }], 25: [function (require, module, exports) { - module.exports = isThunk; + static create(updates = {}) { + let x = new this(updates); + return Object.freeze(x); + } + }; +} - function isThunk(t) { - return t && t.type === "Thunk"; - } - }, {}], 26: [function (require, module, exports) { - module.exports = isHook; +function defexception(defaults) { + return class extends Error { + constructor(update = {}) { + let message = update.message || ''; + super(message); - function isHook(hook) { - return hook && (typeof hook.hook === "function" && !hook.hasOwnProperty("hook") || typeof hook.unhook === "function" && !hook.hasOwnProperty("unhook")); - } - }, {}], 27: [function (require, module, exports) { - var version = require("./version"); + let the_values = Object.assign(defaults, update); + Object.assign(this, the_values); - module.exports = isVirtualNode; + this.name = this.constructor.name; + this.message = message; + this[SpecialForms.atom('__exception__')] = true; + Error.captureStackTrace(this, this.constructor.name); + } - function isVirtualNode(x) { - return x && x.type === "VirtualNode" && x.version === version; - } - }, { "./version": 30 }], 28: [function (require, module, exports) { - var version = require("./version"); + static create(updates = {}) { + let x = new this(updates); + return Object.freeze(x); + } + }; +} - module.exports = isVirtualText; +function defprotocol(spec) { + return new Protocol(spec); +} - function isVirtualText(x) { - return x && x.type === "VirtualText" && x.version === version; - } - }, { "./version": 30 }], 29: [function (require, module, exports) { - module.exports = isWidget; +function defimpl(protocol, type, impl) { + protocol.implementation(type, impl); +} - function isWidget(w) { - return w && w.type === "Widget"; - } - }, {}], 30: [function (require, module, exports) { - module.exports = "2"; - }, {}], 31: [function (require, module, exports) { - var version = require("./version"); - var isVNode = require("./is-vnode"); - var isWidget = require("./is-widget"); - var isThunk = require("./is-thunk"); - var isVHook = require("./is-vhook"); +function get_object_keys(obj) { + return Object.keys(obj).concat(Object.getOwnPropertySymbols(obj)); +} - module.exports = VirtualNode; +function is_valid_character(codepoint) { + try { + return String.fromCodePoint(codepoint) != null; + } catch (e) { + return false; + } +} - var noProperties = {}; - var noChildren = []; +//https://developer.mozilla.org/en-US/docs/Web/API/WindowBase64/Base64_encoding_and_decoding#Solution_2_%E2%80%93_rewrite_the_DOMs_atob()_and_btoa()_using_JavaScript's_TypedArrays_and_UTF-8 +function b64EncodeUnicode(str) { + return btoa(encodeURIComponent(str).replace(/%([0-9A-F]{2})/g, function (match, p1) { + return String.fromCharCode('0x' + p1); + })); +} - function VirtualNode(tagName, properties, children, key, namespace) { - this.tagName = tagName; - this.properties = properties || noProperties; - this.children = children || noChildren; - this.key = key != null ? String(key) : undefined; - this.namespace = typeof namespace === "string" ? namespace : null; +function delete_property_from_map(map, property) { + let new_map = Object.assign(Object.create(map.constructor.prototype), map); + delete new_map[property]; - var count = children && children.length || 0; - var descendants = 0; - var hasWidgets = false; - var hasThunks = false; - var descendantHooks = false; - var hooks; + return Object.freeze(new_map); +} - for (var propName in properties) { - if (properties.hasOwnProperty(propName)) { - var property = properties[propName]; - if (isVHook(property) && property.unhook) { - if (!hooks) { - hooks = {}; - } +function class_to_obj(map) { + let new_map = Object.assign({}, map); + return Object.freeze(new_map); +} - hooks[propName] = property; - } - } - } +function add_property_to_map(map, property, value) { + let new_map = Object.assign({}, map); + new_map[property] = value; + return Object.freeze(new_map); +} - for (var i = 0; i < count; i++) { - var child = children[i]; - if (isVNode(child)) { - descendants += child.count || 0; +function bnot(expr) { + return ~expr; +} - if (!hasWidgets && child.hasWidgets) { - hasWidgets = true; - } +function band(left, right) { + return left & right; +} - if (!hasThunks && child.hasThunks) { - hasThunks = true; - } +function bor(left, right) { + return left | right; +} - if (!descendantHooks && (child.hooks || child.descendantHooks)) { - descendantHooks = true; - } - } else if (!hasWidgets && isWidget(child)) { - if (typeof child.destroy === "function") { - hasWidgets = true; - } - } else if (!hasThunks && isThunk(child)) { - hasThunks = true; - } - } +function bsl(left, right) { + return left << right; +} - this.count = count + descendants; - this.hasWidgets = hasWidgets; - this.hasThunks = hasThunks; - this.hooks = hooks; - this.descendantHooks = descendantHooks; - } +function bsr(left, right) { + return left >> right; +} - VirtualNode.prototype.version = version; - VirtualNode.prototype.type = "VirtualNode"; - }, { "./is-thunk": 25, "./is-vhook": 26, "./is-vnode": 27, "./is-widget": 29, "./version": 30 }], 32: [function (require, module, exports) { - var version = require("./version"); +function bxor(left, right) { + return left ^ right; +} - VirtualPatch.NONE = 0; - VirtualPatch.VTEXT = 1; - VirtualPatch.VNODE = 2; - VirtualPatch.WIDGET = 3; - VirtualPatch.PROPS = 4; - VirtualPatch.ORDER = 5; - VirtualPatch.INSERT = 6; - VirtualPatch.REMOVE = 7; - VirtualPatch.THUNK = 8; +function zip(list_of_lists) { + if (list_of_lists.length === 0) { + return Object.freeze([]); + } - module.exports = VirtualPatch; + let new_value = []; + let smallest_length = list_of_lists[0]; - function VirtualPatch(type, vNode, patch) { - this.type = Number(type); - this.vNode = vNode; - this.patch = patch; - } + for (let x of list_of_lists) { + if (x.length < smallest_length) { + smallest_length = x.length; + } + } - VirtualPatch.prototype.version = version; - VirtualPatch.prototype.type = "VirtualPatch"; - }, { "./version": 30 }], 33: [function (require, module, exports) { - var version = require("./version"); + for (let i = 0; i < smallest_length; i++) { + let current_value = []; + for (let j = 0; j < list_of_lists.length; j++) { + current_value.push(list_of_lists[j][i]); + } - module.exports = VirtualText; + new_value.push(new Tuple(...current_value)); + } - function VirtualText(text) { - this.text = String(text); - } + return Object.freeze(new_value); +} - VirtualText.prototype.version = version; - VirtualText.prototype.type = "VirtualText"; - }, { "./version": 30 }], 34: [function (require, module, exports) { - var isObject = require("is-object"); - var isHook = require("../vnode/is-vhook"); +function can_decode64(data) { + try { + atob(data); + return true; + } catch (e) { + return false; + } +} - module.exports = diffProps; +var Functions = { + call_property, + apply, + contains, + get_global, + defstruct, + defexception, + defprotocol, + defimpl, + get_object_keys, + is_valid_character, + b64EncodeUnicode, + delete_property_from_map, + add_property_to_map, + class_to_obj, + can_decode64, + bnot, + band, + bor, + bsl, + bsr, + bxor, + zip +}; - function diffProps(a, b) { - var diff; +function _case(condition, clauses) { + return Patterns.defmatch(...clauses)(condition); +} - for (var aKey in a) { - if (!(aKey in b)) { - diff = diff || {}; - diff[aKey] = undefined; - } +function cond(clauses) { + for (let clause of clauses) { + if (clause[0]) { + return clause[1](); + } + } - var aValue = a[aKey]; - var bValue = b[aKey]; + throw new Error(); +} - if (aValue === bValue) { - continue; - } else if (isObject(aValue) && isObject(bValue)) { - if (getPrototype(bValue) !== getPrototype(aValue)) { - diff = diff || {}; - diff[aKey] = bValue; - } else if (isHook(bValue)) { - diff = diff || {}; - diff[aKey] = bValue; - } else { - var objectDiff = diffProps(aValue, bValue); - if (objectDiff) { - diff = diff || {}; - diff[aKey] = objectDiff; - } - } - } else { - diff = diff || {}; - diff[aKey] = bValue; - } - } +function map_update(map, values) { + return Object.freeze(Object.assign(Object.create(map.constructor.prototype), map, values)); +} - for (var bKey in b) { - if (!(bKey in a)) { - diff = diff || {}; - diff[bKey] = b[bKey]; - } - } +function _for(collections, fun, filter = () => true, into = [], previousValues = []) { + let pattern = collections[0][0]; + let collection = collections[0][1]; - return diff; - } + if (collections.length === 1) { - function getPrototype(value) { - if (Object.getPrototypeOf) { - return Object.getPrototypeOf(value); - } else if (value.__proto__) { - return value.__proto__; - } else if (value.constructor) { - return value.constructor.prototype; - } - } - }, { "../vnode/is-vhook": 26, "is-object": 11 }], 35: [function (require, module, exports) { - var isArray = require("x-is-array"); + for (let elem of collection) { + let r = Patterns.match_no_throw(pattern, elem); + let args = previousValues.concat(r); - var VPatch = require("../vnode/vpatch"); - var isVNode = require("../vnode/is-vnode"); - var isVText = require("../vnode/is-vtext"); - var isWidget = require("../vnode/is-widget"); - var isThunk = require("../vnode/is-thunk"); - var handleThunk = require("../vnode/handle-thunk"); + if (r && filter.apply(this, args)) { + into = into.concat([fun.apply(this, args)]); + } + } - var diffProps = require("./diff-props"); + return into; + } else { + let _into = []; - module.exports = diff; + for (let elem of collection) { + let r = Patterns.match_no_throw(pattern, elem); + if (r) { + _into = into.concat(this._for(collections.slice(1), fun, filter, _into, previousValues.concat(r))); + } + } - function diff(a, b) { - var patch = { a: a }; - walk(a, b, patch, 0); - return patch; - } + return _into; + } +} - function walk(a, b, patch, index) { - if (a === b) { - return; - } +function _try(do_fun, rescue_function, catch_fun, else_function, after_function) { + let result = null; - var apply = patch[index]; - var applyClear = false; + try { + result = do_fun(); + } catch (e) { + let ex_result = null; - if (isThunk(a) || isThunk(b)) { - thunks(a, b, patch, index); - } else if (b == null) { + if (rescue_function) { + try { + ex_result = rescue_function(e); + return ex_result; + } catch (ex) { + if (ex instanceof Patterns.MatchError) { + throw ex; + } + } + } + + if (catch_fun) { + try { + ex_result = catch_fun(e); + return ex_result; + } catch (ex) { + if (ex instanceof Patterns.MatchError) { + throw ex; + } + } + } - // If a is a widget we will add a remove patch for it - // Otherwise any child widgets/hooks must be destroyed. - // This prevents adding two remove patches for a widget. - if (!isWidget(a)) { - clearState(a, patch, index); - apply = patch[index]; - } + throw e; + } finally { + if (after_function) { + after_function(); + } + } - apply = appendPatch(apply, new VPatch(VPatch.REMOVE, a, b)); - } else if (isVNode(b)) { - if (isVNode(a)) { - if (a.tagName === b.tagName && a.namespace === b.namespace && a.key === b.key) { - var propsPatch = diffProps(a.properties, b.properties); - if (propsPatch) { - apply = appendPatch(apply, new VPatch(VPatch.PROPS, a, propsPatch)); - } - apply = diffChildren(a, b, patch, apply, index); - } else { - apply = appendPatch(apply, new VPatch(VPatch.VNODE, a, b)); - applyClear = true; - } - } else { - apply = appendPatch(apply, new VPatch(VPatch.VNODE, a, b)); - applyClear = true; - } - } else if (isVText(b)) { - if (!isVText(a)) { - apply = appendPatch(apply, new VPatch(VPatch.VTEXT, a, b)); - applyClear = true; - } else if (a.text !== b.text) { - apply = appendPatch(apply, new VPatch(VPatch.VTEXT, a, b)); - } - } else if (isWidget(b)) { - if (!isWidget(a)) { - applyClear = true; - } + if (else_function) { + try { + return else_function(result); + } catch (ex) { + if (ex instanceof Patterns.MatchError) { + throw new Error('No Match Found in Else'); + } - apply = appendPatch(apply, new VPatch(VPatch.WIDGET, a, b)); - } + throw ex; + } + } else { + return result; + } +} - if (apply) { - patch[index] = apply; - } +var SpecialForms$1 = { + _case, + cond, + map_update, + _for, + _try +}; - if (applyClear) { - clearState(a, patch, index); - } - } +Functions.get_global().processes = Functions.get_global().processes || new ProcessSystem(); - function diffChildren(a, b, patch, apply, index) { - var aChildren = a.children; - var orderedSet = reorder(aChildren, b.children); - var bChildren = orderedSet.children; +var Core = { + ProcessSystem, + Tuple, + PID, + BitString, + Patterns, + Integer, + Float, + Functions, + SpecialForms: SpecialForms$1 +}; - var aLen = aChildren.length; - var bLen = bChildren.length; - var len = aLen > bLen ? aLen : bLen; +let Enum = { - for (var i = 0; i < len; i++) { - var leftNode = aChildren[i]; - var rightNode = bChildren[i]; - index += 1; + all__qmark__: function (collection, fun = x => x) { + for (let elem of collection) { + if (!fun(elem)) { + return false; + } + } - if (!leftNode) { - if (rightNode) { - // Excess nodes in b need to be added - apply = appendPatch(apply, new VPatch(VPatch.INSERT, null, rightNode)); - } - } else { - walk(leftNode, rightNode, patch, index); - } + return true; + }, - if (isVNode(leftNode) && leftNode.count) { - index += leftNode.count; - } - } + any__qmark__: function (collection, fun = x => x) { + for (let elem of collection) { + if (fun(elem)) { + return true; + } + } - if (orderedSet.moves) { - // Reorder nodes last - apply = appendPatch(apply, new VPatch(VPatch.ORDER, a, orderedSet.moves)); - } + return false; + }, - return apply; - } + at: function (collection, n, the_default = null) { + if (n > this.count(collection) || n < 0) { + return the_default; + } - function clearState(vNode, patch, index) { - // TODO: Make this a single walk, not two - unhook(vNode, patch, index); - destroyWidgets(vNode, patch, index); - } + return collection[n]; + }, - // Patch records for all destroyed widgets must be added because we need - // a DOM node reference for the destroy function - function destroyWidgets(vNode, patch, index) { - if (isWidget(vNode)) { - if (typeof vNode.destroy === "function") { - patch[index] = appendPatch(patch[index], new VPatch(VPatch.REMOVE, vNode, null)); - } - } else if (isVNode(vNode) && (vNode.hasWidgets || vNode.hasThunks)) { - var children = vNode.children; - var len = children.length; - for (var i = 0; i < len; i++) { - var child = children[i]; - index += 1; + concat: function (...enumables) { + return enumables[0].concat(enumables[1]); + }, - destroyWidgets(child, patch, index); + count: function (collection, fun = null) { + if (fun == null) { + return collection.length; + } else { + return collection.filter(fun).length; + } + }, - if (isVNode(child) && child.count) { - index += child.count; - } - } - } else if (isThunk(vNode)) { - thunks(vNode, null, patch, index); - } - } + drop: function (collection, count) { + return collection.slice(count); + }, - // Create a sub-patch for thunks - function thunks(a, b, patch, index) { - var nodes = handleThunk(a, b); - var thunkPatch = diff(nodes.a, nodes.b); - if (hasPatches(thunkPatch)) { - patch[index] = new VPatch(VPatch.THUNK, null, thunkPatch); - } - } + drop_while: function (collection, fun) { + let count = 0; - function hasPatches(patch) { - for (var index in patch) { - if (index !== "a") { - return true; - } - } + for (let elem of collection) { + if (fun(elem)) { + count = count + 1; + } else { + break; + } + } - return false; - } + return collection.slice(count); + }, - // Execute hooks when two nodes are identical - function unhook(vNode, patch, index) { - if (isVNode(vNode)) { - if (vNode.hooks) { - patch[index] = appendPatch(patch[index], new VPatch(VPatch.PROPS, vNode, undefinedKeys(vNode.hooks))); - } + each: function (collection, fun) { + for (let elem of collection) { + fun(elem); + } + }, - if (vNode.descendantHooks || vNode.hasThunks) { - var children = vNode.children; - var len = children.length; - for (var i = 0; i < len; i++) { - var child = children[i]; - index += 1; + empty__qmark__: function (collection) { + return collection.length === 0; + }, - unhook(child, patch, index); + fetch: function (collection, n) { + if (Array.isArray(collection)) { + if (n < this.count(collection) && n >= 0) { + return new Core.Tuple(Symbol.for("ok"), collection[n]); + } else { + return Symbol.for("error"); + } + } - if (isVNode(child) && child.count) { - index += child.count; - } - } - } - } else if (isThunk(vNode)) { - thunks(vNode, null, patch, index); - } - } + throw new Error("collection is not an Enumerable"); + }, - function undefinedKeys(obj) { - var result = {}; + fetch__emark__: function (collection, n) { + if (Array.isArray(collection)) { + if (n < this.count(collection) && n >= 0) { + return collection[n]; + } else { + throw new Error("out of bounds error"); + } + } - for (var key in obj) { - result[key] = undefined; - } + throw new Error("collection is not an Enumerable"); + }, - return result; - } + filter: function (collection, fun) { + let result = []; - // List diff, naive left to right reordering - function reorder(aChildren, bChildren) { - // O(M) time, O(M) memory - var bChildIndex = keyIndex(bChildren); - var bKeys = bChildIndex.keys; - var bFree = bChildIndex.free; + for (let elem of collection) { + if (fun(elem)) { + result.push(elem); + } + } - if (bFree.length === bChildren.length) { - return { - children: bChildren, - moves: null - }; - } + return result; + }, - // O(N) time, O(N) memory - var aChildIndex = keyIndex(aChildren); - var aKeys = aChildIndex.keys; - var aFree = aChildIndex.free; + filter_map: function (collection, filter, mapper) { + return Enum.map(Enum.filter(collection, filter), mapper); + }, - if (aFree.length === aChildren.length) { - return { - children: bChildren, - moves: null - }; - } + find: function (collection, if_none = null, fun) { + for (let elem of collection) { + if (fun(elem)) { + return elem; + } + } - // O(MAX(N, M)) memory - var newChildren = []; + return if_none; + }, - var freeIndex = 0; - var freeCount = bFree.length; - var deletedItems = 0; + into: function (collection, list) { + return list.concat(collection); + }, - // Iterate through a and match a node in b - // O(N) time, - for (var i = 0; i < aChildren.length; i++) { - var aItem = aChildren[i]; - var itemIndex; + map: function (collection, fun) { + let result = []; - if (aItem.key) { - if (bKeys.hasOwnProperty(aItem.key)) { - // Match up the old keys - itemIndex = bKeys[aItem.key]; - newChildren.push(bChildren[itemIndex]); - } else { - // Remove old keyed items - itemIndex = i - deletedItems++; - newChildren.push(null); - } - } else { - // Match the item in a with the next free item in b - if (freeIndex < freeCount) { - itemIndex = bFree[freeIndex++]; - newChildren.push(bChildren[itemIndex]); - } else { - // There are no free items in b to match with - // the free items in a, so the extra free nodes - // are deleted. - itemIndex = i - deletedItems++; - newChildren.push(null); - } - } - } + for (let elem of collection) { + result.push(fun(elem)); + } - var lastFreeIndex = freeIndex >= bFree.length ? bChildren.length : bFree[freeIndex]; + return result; + }, - // Iterate through b and append any new keys - // O(M) time - for (var j = 0; j < bChildren.length; j++) { - var newItem = bChildren[j]; + map_reduce: function (collection, acc, fun) { + let mapped = Object.freeze([]); + let the_acc = acc; - if (newItem.key) { - if (!aKeys.hasOwnProperty(newItem.key)) { - // Add any new keyed items - // We are adding new items to the end and then sorting them - // in place. In future we should insert new items in place. - newChildren.push(newItem); - } - } else if (j >= lastFreeIndex) { - // Add any leftover non-keyed items - newChildren.push(newItem); - } - } + for (var i = 0; i < this.count(collection); i++) { + let tuple = fun(collection[i], the_acc); - var simulate = newChildren.slice(); - var simulateIndex = 0; - var removes = []; - var inserts = []; - var simulateItem; + the_acc = tuple.get(1); + mapped = Object.freeze(mapped.concat([tuple.get(0)])); + } - for (var k = 0; k < bChildren.length;) { - var wantedItem = bChildren[k]; - simulateItem = simulate[simulateIndex]; + return new Core.Tuple(mapped, the_acc); + }, - // remove items - while (simulateItem === null && simulate.length) { - removes.push(remove(simulate, simulateIndex, null)); - simulateItem = simulate[simulateIndex]; - } + member__qmark__: function (collection, value) { + return collection.includes(value); + }, - if (!simulateItem || simulateItem.key !== wantedItem.key) { - // if we need a key in this position... - if (wantedItem.key) { - if (simulateItem && simulateItem.key) { - // if an insert doesn't put this key in place, it needs to move - if (bKeys[simulateItem.key] !== k + 1) { - removes.push(remove(simulate, simulateIndex, simulateItem.key)); - simulateItem = simulate[simulateIndex]; - // if the remove didn't put the wanted item in place, we need to insert it - if (!simulateItem || simulateItem.key !== wantedItem.key) { - inserts.push({ key: wantedItem.key, to: k }); - } - // items are matching, so skip ahead - else { - simulateIndex++; - } - } else { - inserts.push({ key: wantedItem.key, to: k }); - } - } else { - inserts.push({ key: wantedItem.key, to: k }); - } - k++; - } - // a key in simulate has no matching wanted key, remove it - else if (simulateItem && simulateItem.key) { - removes.push(remove(simulate, simulateIndex, simulateItem.key)); - } - } else { - simulateIndex++; - k++; - } - } + reduce: function (collection, acc, fun) { + let the_acc = acc; - // remove all the remaining nodes from simulate - while (simulateIndex < simulate.length) { - simulateItem = simulate[simulateIndex]; - removes.push(remove(simulate, simulateIndex, simulateItem && simulateItem.key)); - } + for (var i = 0; i < this.count(collection); i++) { + let tuple = fun(collection[i], the_acc); - // If the only moves we have are deletes then we can just - // let the delete patch remove these items. - if (removes.length === deletedItems && !inserts.length) { - return { - children: newChildren, - moves: null - }; - } + the_acc = tuple.get(1); + } - return { - children: newChildren, - moves: { - removes: removes, - inserts: inserts - } - }; - } + return the_acc; + }, - function remove(arr, index, key) { - arr.splice(index, 1); + take: function (collection, count) { + return collection.slice(0, count); + }, - return { - from: index, - key: key - }; - } + take_every: function (collection, nth) { + let result = []; + let index = 0; - function keyIndex(children) { - var keys = {}; - var free = []; - var length = children.length; + for (let elem of collection) { + if (index % nth === 0) { + result.push(elem); + } + } - for (var i = 0; i < length; i++) { - var child = children[i]; + return Object.freeze(result); + }, - if (child.key) { - keys[child.key] = i; - } else { - free.push(i); - } - } + take_while: function (collection, fun) { + let count = 0; - return { - keys: keys, // A hash of key name to index - free: free // An array of unkeyed item indices - }; - } + for (let elem of collection) { + if (fun(elem)) { + count = count + 1; + } else { + break; + } + } - function appendPatch(apply, patch) { - if (apply) { - if (isArray(apply)) { - apply.push(patch); - } else { - apply = [apply, patch]; - } + return collection.slice(0, count); + }, - return apply; - } else { - return patch; - } - } - }, { "../vnode/handle-thunk": 24, "../vnode/is-thunk": 25, "../vnode/is-vnode": 27, "../vnode/is-vtext": 28, "../vnode/is-widget": 29, "../vnode/vpatch": 32, "./diff-props": 34, "x-is-array": 12 }] }, {}, [4])(4); -}); + to_list: function (collection) { + return collection; + } +}; -const Core = C; +var Elixir = { + Core, + Enum, + VirtualDOM +}; -export { Core, Enum, VirtualDOM }; -//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiIiwic291cmNlcyI6WyJFbGl4aXIuanMiXSwic291cmNlc0NvbnRlbnQiOlsiLyogQGZsb3cgKi9cblxuY2xhc3MgTWFpbGJveCB7XG5cbiAgY29uc3RydWN0b3IoKSB7XG4gICAgdGhpcy5tZXNzYWdlcyA9IFtdO1xuICB9XG5cbiAgZGVsaXZlcihtZXNzYWdlKSB7XG4gICAgdGhpcy5tZXNzYWdlcy5wdXNoKG1lc3NhZ2UpO1xuICAgIHJldHVybiBtZXNzYWdlO1xuICB9XG5cbiAgZ2V0KCkge1xuICAgIHJldHVybiB0aGlzLm1lc3NhZ2VzO1xuICB9XG5cbiAgaXNFbXB0eSgpIHtcbiAgICByZXR1cm4gdGhpcy5tZXNzYWdlcy5sZW5ndGggPT09IDA7XG4gIH1cblxuICByZW1vdmVBdChpbmRleCkge1xuICAgIHRoaXMubWVzc2FnZXMuc3BsaWNlKGluZGV4LCAxKTtcbiAgfVxufVxuXG52YXIgU3RhdGVzID0ge1xuICBOT1JNQUw6IFN5bWJvbC5mb3IoXCJub3JtYWxcIiksXG4gIEtJTEw6IFN5bWJvbC5mb3IoXCJraWxsXCIpLFxuICBTVVNQRU5EOiBTeW1ib2wuZm9yKFwic3VzcGVuZFwiKSxcbiAgQ09OVElOVUU6IFN5bWJvbC5mb3IoXCJjb250aW51ZVwiKSxcbiAgUkVDRUlWRTogU3ltYm9sLmZvcihcInJlY2VpdmVcIiksXG4gIFNFTkQ6IFN5bWJvbC5mb3IoXCJzZW5kXCIpLFxuICBTTEVFUElORzogU3ltYm9sLmZvcihcInNsZWVwaW5nXCIpLFxuICBSVU5OSU5HOiBTeW1ib2wuZm9yKFwicnVubmluZ1wiKSxcbiAgU1VTUEVOREVEOiBTeW1ib2wuZm9yKFwic3VzcGVuZGVkXCIpLFxuICBTVE9QUEVEOiBTeW1ib2wuZm9yKFwic3RvcHBlZFwiKSxcbiAgU0xFRVA6IFN5bWJvbC5mb3IoXCJzbGVlcFwiKSxcbiAgRVhJVDogU3ltYm9sLmZvcihcImV4aXRcIiksXG4gIE5PTUFUQ0g6IFN5bWJvbC5mb3IoXCJub19tYXRjaFwiKVxufTtcblxuY2xhc3MgUHJvY2VzcyB7XG5cbiAgY29uc3RydWN0b3IocGlkLCBtYWlsYm94KSB7XG4gICAgdGhpcy5waWQgPSBwaWQ7XG4gICAgdGhpcy5tYWlsYm94ID0gbWFpbGJveDtcbiAgICB0aGlzLnN0YXR1cyA9IFN0YXRlcy5TVE9QUEVEO1xuICAgIHRoaXMuZGljdCA9IHt9O1xuICB9XG59XG5cbmNsYXNzIFR1cGxlIHtcblxuICBjb25zdHJ1Y3RvciguLi5hcmdzKSB7XG4gICAgdGhpcy52YWx1ZXMgPSBPYmplY3QuZnJlZXplKGFyZ3MpO1xuICAgIHRoaXMubGVuZ3RoID0gdGhpcy52YWx1ZXMubGVuZ3RoO1xuICB9XG5cbiAgZ2V0KGluZGV4KSB7XG4gICAgcmV0dXJuIHRoaXMudmFsdWVzW2luZGV4XTtcbiAgfVxuXG4gIGNvdW50KCkge1xuICAgIHJldHVybiB0aGlzLnZhbHVlcy5sZW5ndGg7XG4gIH1cblxuICBbU3ltYm9sLml0ZXJhdG9yXSgpIHtcbiAgICByZXR1cm4gdGhpcy52YWx1ZXNbU3ltYm9sLml0ZXJhdG9yXSgpO1xuICB9XG5cbiAgdG9TdHJpbmcoKSB7XG4gICAgdmFyIGksXG4gICAgICAgIHMgPSBcIlwiO1xuICAgIGZvciAoaSA9IDA7IGkgPCB0aGlzLnZhbHVlcy5sZW5ndGg7IGkrKykge1xuICAgICAgaWYgKHMgIT09IFwiXCIpIHtcbiAgICAgICAgcyArPSBcIiwgXCI7XG4gICAgICB9XG4gICAgICBzICs9IHRoaXMudmFsdWVzW2ldLnRvU3RyaW5nKCk7XG4gICAgfVxuXG4gICAgcmV0dXJuIFwie1wiICsgcyArIFwifVwiO1xuICB9XG5cbn1cblxubGV0IHByb2Nlc3NfY291bnRlciA9IC0xO1xuXG5jbGFzcyBQSUQge1xuICBjb25zdHJ1Y3RvcigpIHtcbiAgICBwcm9jZXNzX2NvdW50ZXIgPSBwcm9jZXNzX2NvdW50ZXIgKyAxO1xuICAgIHRoaXMuaWQgPSBwcm9jZXNzX2NvdW50ZXI7XG4gIH1cblxuICB0b1N0cmluZygpIHtcbiAgICByZXR1cm4gXCJQSUQjPDAuXCIgKyB0aGlzLmlkICsgXCIuMD5cIjtcbiAgfVxufVxuXG5jbGFzcyBJbnRlZ2VyIHt9XG5jbGFzcyBGbG9hdCB7fVxuXG5jbGFzcyBQcm9jZXNzU3lzdGVtIHtcblxuICBjb25zdHJ1Y3RvcigpIHtcbiAgICB0aGlzLnBpZHMgPSBuZXcgTWFwKCk7XG4gICAgdGhpcy5tYWlsYm94ZXMgPSBuZXcgTWFwKCk7XG4gICAgdGhpcy5uYW1lcyA9IG5ldyBNYXAoKTtcbiAgICB0aGlzLmxpbmtzID0gbmV3IE1hcCgpO1xuXG4gICAgdGhpcy5jdXJyZW50X3Byb2Nlc3MgPSBudWxsO1xuICAgIHRoaXMuc3VzcGVuZGVkID0gbmV3IE1hcCgpO1xuXG4gICAgdGhpcy5tYWluX3Byb2Nlc3NfcGlkID0gdGhpcy5zcGF3bigpO1xuICAgIHRoaXMuc2V0X2N1cnJlbnQodGhpcy5tYWluX3Byb2Nlc3NfcGlkKTtcbiAgfVxuXG4gIHNwYXduKCkge1xuICAgIHJldHVybiB0aGlzLmFkZF9wcm9jKGZhbHNlKS5waWQ7XG4gIH1cblxuICBzcGF3bl9saW5rKCkge1xuICAgIHJldHVybiB0aGlzLmFkZF9wcm9jKHRydWUpLnBpZDtcbiAgfVxuXG4gIGxpbmsocGlkKSB7XG4gICAgdGhpcy5saW5rcy5nZXQodGhpcy5waWQoKSkuYWRkKHBpZCk7XG4gICAgdGhpcy5saW5rcy5nZXQocGlkKS5hZGQodGhpcy5waWQoKSk7XG4gIH1cblxuICB1bmxpbmsocGlkKSB7XG4gICAgdGhpcy5saW5rcy5nZXQodGhpcy5waWQoKSkuZGVsZXRlKHBpZCk7XG4gICAgdGhpcy5saW5rcy5nZXQocGlkKS5kZWxldGUodGhpcy5waWQoKSk7XG4gIH1cblxuICBzZXRfY3VycmVudChpZCkge1xuICAgIGxldCBwaWQgPSB0aGlzLnBpZG9mKGlkKTtcbiAgICBpZiAocGlkICE9PSBudWxsKSB7XG4gICAgICB0aGlzLmN1cnJlbnRfcHJvY2VzcyA9IHRoaXMucGlkcy5nZXQocGlkKTtcbiAgICAgIHRoaXMuY3VycmVudF9wcm9jZXNzLnN0YXR1cyA9IFN0YXRlcy5SVU5OSU5HO1xuICAgIH1cbiAgfVxuXG4gIGFkZF9wcm9jKGxpbmtlZCkge1xuICAgIGxldCBuZXdwaWQgPSBuZXcgUElEKCk7XG4gICAgbGV0IG1haWxib3ggPSBuZXcgTWFpbGJveCgpO1xuICAgIGxldCBuZXdwcm9jID0gbmV3IFByb2Nlc3MobmV3cGlkLCBtYWlsYm94KTtcblxuICAgIHRoaXMucGlkcy5zZXQobmV3cGlkLCBuZXdwcm9jKTtcbiAgICB0aGlzLm1haWxib3hlcy5zZXQobmV3cGlkLCBtYWlsYm94KTtcbiAgICB0aGlzLmxpbmtzLnNldChuZXdwaWQsIG5ldyBTZXQoKSk7XG5cbiAgICBpZiAobGlua2VkKSB7XG4gICAgICB0aGlzLmxpbmsobmV3cGlkKTtcbiAgICB9XG5cbiAgICByZXR1cm4gbmV3cHJvYztcbiAgfVxuXG4gIHJlbW92ZV9wcm9jKHBpZCkge1xuICAgIHRoaXMucGlkcy5kZWxldGUocGlkKTtcbiAgICB0aGlzLnVucmVnaXN0ZXIocGlkKTtcblxuICAgIGlmICh0aGlzLmxpbmtzLmhhcyhwaWQpKSB7XG4gICAgICBmb3IgKGxldCBsaW5rcGlkIG9mIHRoaXMubGlua3MuZ2V0KHBpZCkpIHtcbiAgICAgICAgdGhpcy5saW5rcy5nZXQobGlua3BpZCkuZGVsZXRlKHBpZCk7XG4gICAgICB9XG5cbiAgICAgIHRoaXMubGlua3MuZGVsZXRlKHBpZCk7XG4gICAgfVxuICB9XG5cbiAgZXhpdChpZCkge1xuICAgIGxldCBwaWQgPSB0aGlzLnBpZG9mKGlkKTtcbiAgICB0aGlzLnJlbW92ZV9wcm9jKGlkKTtcbiAgfVxuXG4gIHJlZ2lzdGVyKG5hbWUsIHBpZCkge1xuICAgIGlmICghdGhpcy5uYW1lcy5oYXMobmFtZSkpIHtcbiAgICAgIHRoaXMubmFtZXMuc2V0KG5hbWUsIHBpZCk7XG4gICAgICByZXR1cm4gbmFtZTtcbiAgICB9IGVsc2Uge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKFwiTmFtZSBpcyBhbHJlYWR5IHJlZ2lzdGVyZWQgdG8gYW5vdGhlciBwcm9jZXNzXCIpO1xuICAgIH1cbiAgfVxuXG4gIHJlZ2lzdGVyZWQobmFtZSkge1xuICAgIHJldHVybiB0aGlzLm5hbWVzLmhhcyhuYW1lKSA/IHRoaXMubmFtZXMuZ2V0KG5hbWUpIDogbnVsbDtcbiAgfVxuXG4gIHVucmVnaXN0ZXIocGlkKSB7XG4gICAgZm9yIChsZXQgbmFtZSBvZiB0aGlzLm5hbWVzLmtleXMoKSkge1xuICAgICAgaWYgKHRoaXMubmFtZXMuaGFzKG5hbWUpICYmIHRoaXMubmFtZXMuZ2V0KG5hbWUpID09PSBwaWQpIHtcbiAgICAgICAgdGhpcy5uYW1lcy5kZWxldGUobmFtZSk7XG4gICAgICB9XG4gICAgfVxuICB9XG5cbiAgcGlkKCkge1xuICAgIHJldHVybiB0aGlzLmN1cnJlbnRfcHJvY2Vzcy5waWQ7XG4gIH1cblxuICBwaWRvZihpZCkge1xuICAgIGlmIChpZCBpbnN0YW5jZW9mIFBJRCkge1xuICAgICAgcmV0dXJuIHRoaXMucGlkcy5oYXMoaWQpID8gaWQgOiBudWxsO1xuICAgIH0gZWxzZSBpZiAoaWQgaW5zdGFuY2VvZiBQcm9jZXNzKSB7XG4gICAgICByZXR1cm4gaWQucGlkO1xuICAgIH0gZWxzZSB7XG4gICAgICBsZXQgcGlkID0gdGhpcy5yZWdpc3RlcmVkKGlkKTtcbiAgICAgIGlmIChwaWQgPT09IG51bGwpIHRocm93IFwiUHJvY2VzcyBuYW1lIG5vdCByZWdpc3RlcmVkOiBcIiArIGlkICsgXCIgKFwiICsgdHlwZW9mIGlkICsgXCIpXCI7XG4gICAgICByZXR1cm4gcGlkO1xuICAgIH1cbiAgfVxuXG4gIHB1dChpZCwga2V5LCB2YWx1ZSkge1xuICAgIGxldCBwaWQgPSB0aGlzLnBpZG9mKGlkKTtcbiAgICBsZXQgcHJvY2VzcyA9IHRoaXMucGlkcy5nZXQocGlkKTtcbiAgICBwcm9jZXNzLmRpY3Rba2V5XSA9IHZhbHVlO1xuICB9XG5cbiAgZ2V0KGlkLCBrZXkpIHtcbiAgICBsZXQgcGlkID0gdGhpcy5waWRvZihpZCk7XG4gICAgbGV0IHByb2Nlc3MgPSB0aGlzLnBpZHMuZ2V0KHBpZCk7XG5cbiAgICBpZiAoa2V5ICE9IG51bGwpIHtcbiAgICAgIHJldHVybiBwcm9jZXNzLmRpY3Rba2V5XTtcbiAgICB9IGVsc2Uge1xuICAgICAgcmV0dXJuIHByb2Nlc3MuZGljdDtcbiAgICB9XG4gIH1cblxuICBnZXRfa2V5cyhpZCkge1xuICAgIGxldCBwaWQgPSB0aGlzLnBpZG9mKGlkKTtcbiAgICBsZXQgcHJvY2VzcyA9IHRoaXMucGlkcy5nZXQocGlkKTtcblxuICAgIHJldHVybiBPYmplY3Qua2V5cyhwcm9jZXNzLmRpY3QpO1xuICB9XG5cbiAgZXJhc2UoaWQsIGtleSkge1xuICAgIGxldCBwaWQgPSB0aGlzLnBpZG9mKGlkKTtcbiAgICBsZXQgcHJvY2VzcyA9IHRoaXMucGlkcy5nZXQocGlkKTtcblxuICAgIGlmIChrZXkgIT0gbnVsbCkge1xuICAgICAgZGVsZXRlIHByb2Nlc3MuZGljdFtrZXldO1xuICAgIH0gZWxzZSB7XG4gICAgICBwcm9jZXNzLmRpY3QgPSB7fTtcbiAgICB9XG4gIH1cbn1cblxuY2xhc3MgQml0U3RyaW5nIHtcbiAgY29uc3RydWN0b3IoLi4uYXJncykge1xuICAgIHRoaXMucmF3X3ZhbHVlID0gZnVuY3Rpb24gKCkge1xuICAgICAgcmV0dXJuIE9iamVjdC5mcmVlemUoYXJncyk7XG4gICAgfTtcblxuICAgIHRoaXMudmFsdWUgPSBPYmplY3QuZnJlZXplKHRoaXMucHJvY2VzcyhhcmdzKSk7XG4gIH1cblxuICBnZXQoaW5kZXgpIHtcbiAgICByZXR1cm4gdGhpcy52YWx1ZVtpbmRleF07XG4gIH1cblxuICBjb3VudCgpIHtcbiAgICByZXR1cm4gdGhpcy52YWx1ZS5sZW5ndGg7XG4gIH1cblxuICBbU3ltYm9sLml0ZXJhdG9yXSgpIHtcbiAgICByZXR1cm4gdGhpcy52YWx1ZVtTeW1ib2wuaXRlcmF0b3JdKCk7XG4gIH1cblxuICB0b1N0cmluZygpIHtcbiAgICB2YXIgaSxcbiAgICAgICAgcyA9IFwiXCI7XG4gICAgZm9yIChpID0gMDsgaSA8IHRoaXMuY291bnQoKTsgaSsrKSB7XG4gICAgICBpZiAocyAhPT0gXCJcIikge1xuICAgICAgICBzICs9IFwiLCBcIjtcbiAgICAgIH1cbiAgICAgIHMgKz0gdGhpc1tpXS50b1N0cmluZygpO1xuICAgIH1cblxuICAgIHJldHVybiBcIjw8XCIgKyBzICsgXCI+PlwiO1xuICB9XG5cbiAgcHJvY2VzcygpIHtcbiAgICBsZXQgcHJvY2Vzc2VkX3ZhbHVlcyA9IFtdO1xuXG4gICAgdmFyIGk7XG4gICAgZm9yIChpID0gMDsgaSA8IHRoaXMucmF3X3ZhbHVlKCkubGVuZ3RoOyBpKyspIHtcbiAgICAgIGxldCBwcm9jZXNzZWRfdmFsdWUgPSB0aGlzW1wicHJvY2Vzc19cIiArIHRoaXMucmF3X3ZhbHVlKClbaV0udHlwZV0odGhpcy5yYXdfdmFsdWUoKVtpXSk7XG5cbiAgICAgIGZvciAobGV0IGF0dHIgb2YgdGhpcy5yYXdfdmFsdWUoKVtpXS5hdHRyaWJ1dGVzKSB7XG4gICAgICAgIHByb2Nlc3NlZF92YWx1ZSA9IHRoaXNbXCJwcm9jZXNzX1wiICsgYXR0cl0ocHJvY2Vzc2VkX3ZhbHVlKTtcbiAgICAgIH1cblxuICAgICAgcHJvY2Vzc2VkX3ZhbHVlcyA9IHByb2Nlc3NlZF92YWx1ZXMuY29uY2F0KHByb2Nlc3NlZF92YWx1ZSk7XG4gICAgfVxuXG4gICAgcmV0dXJuIHByb2Nlc3NlZF92YWx1ZXM7XG4gIH1cblxuICBwcm9jZXNzX2ludGVnZXIodmFsdWUpIHtcbiAgICByZXR1cm4gdmFsdWUudmFsdWU7XG4gIH1cblxuICBwcm9jZXNzX2Zsb2F0KHZhbHVlKSB7XG4gICAgaWYgKHZhbHVlLnNpemUgPT09IDY0KSB7XG4gICAgICByZXR1cm4gQml0U3RyaW5nLmZsb2F0NjRUb0J5dGVzKHZhbHVlLnZhbHVlKTtcbiAgICB9IGVsc2UgaWYgKHZhbHVlLnNpemUgPT09IDMyKSB7XG4gICAgICByZXR1cm4gQml0U3RyaW5nLmZsb2F0MzJUb0J5dGVzKHZhbHVlLnZhbHVlKTtcbiAgICB9XG5cbiAgICB0aHJvdyBuZXcgRXJyb3IoXCJJbnZhbGlkIHNpemUgZm9yIGZsb2F0XCIpO1xuICB9XG5cbiAgcHJvY2Vzc19iaXRzdHJpbmcodmFsdWUpIHtcbiAgICByZXR1cm4gdmFsdWUudmFsdWUudmFsdWU7XG4gIH1cblxuICBwcm9jZXNzX2JpbmFyeSh2YWx1ZSkge1xuICAgIHJldHVybiBCaXRTdHJpbmcudG9VVEY4QXJyYXkodmFsdWUudmFsdWUpO1xuICB9XG5cbiAgcHJvY2Vzc191dGY4KHZhbHVlKSB7XG4gICAgcmV0dXJuIEJpdFN0cmluZy50b1VURjhBcnJheSh2YWx1ZS52YWx1ZSk7XG4gIH1cblxuICBwcm9jZXNzX3V0ZjE2KHZhbHVlKSB7XG4gICAgcmV0dXJuIEJpdFN0cmluZy50b1VURjE2QXJyYXkodmFsdWUudmFsdWUpO1xuICB9XG5cbiAgcHJvY2Vzc191dGYzMih2YWx1ZSkge1xuICAgIHJldHVybiBCaXRTdHJpbmcudG9VVEYzMkFycmF5KHZhbHVlLnZhbHVlKTtcbiAgfVxuXG4gIHByb2Nlc3Nfc2lnbmVkKHZhbHVlKSB7XG4gICAgcmV0dXJuIG5ldyBVaW50OEFycmF5KFt2YWx1ZV0pWzBdO1xuICB9XG5cbiAgcHJvY2Vzc191bnNpZ25lZCh2YWx1ZSkge1xuICAgIHJldHVybiB2YWx1ZTtcbiAgfVxuXG4gIHByb2Nlc3NfbmF0aXZlKHZhbHVlKSB7XG4gICAgcmV0dXJuIHZhbHVlO1xuICB9XG5cbiAgcHJvY2Vzc19iaWcodmFsdWUpIHtcbiAgICByZXR1cm4gdmFsdWU7XG4gIH1cblxuICBwcm9jZXNzX2xpdHRsZSh2YWx1ZSkge1xuICAgIHJldHVybiB2YWx1ZS5yZXZlcnNlKCk7XG4gIH1cblxuICBwcm9jZXNzX3NpemUodmFsdWUpIHtcbiAgICByZXR1cm4gdmFsdWU7XG4gIH1cblxuICBwcm9jZXNzX3VuaXQodmFsdWUpIHtcbiAgICByZXR1cm4gdmFsdWU7XG4gIH1cblxuICBzdGF0aWMgaW50ZWdlcih2YWx1ZSkge1xuICAgIHJldHVybiBCaXRTdHJpbmcud3JhcCh2YWx1ZSwgeyBcInR5cGVcIjogXCJpbnRlZ2VyXCIsIFwidW5pdFwiOiAxLCBcInNpemVcIjogOCB9KTtcbiAgfVxuXG4gIHN0YXRpYyBmbG9hdCh2YWx1ZSkge1xuICAgIHJldHVybiBCaXRTdHJpbmcud3JhcCh2YWx1ZSwgeyBcInR5cGVcIjogXCJmbG9hdFwiLCBcInVuaXRcIjogMSwgXCJzaXplXCI6IDY0IH0pO1xuICB9XG5cbiAgc3RhdGljIGJpdHN0cmluZyh2YWx1ZSkge1xuICAgIHJldHVybiBCaXRTdHJpbmcud3JhcCh2YWx1ZSwgeyBcInR5cGVcIjogXCJiaXRzdHJpbmdcIiwgXCJ1bml0XCI6IDEsIFwic2l6ZVwiOiB2YWx1ZS5sZW5ndGggfSk7XG4gIH1cblxuICBzdGF0aWMgYml0cyh2YWx1ZSkge1xuICAgIHJldHVybiBCaXRTdHJpbmcuYml0c3RyaW5nKHZhbHVlKTtcbiAgfVxuXG4gIHN0YXRpYyBiaW5hcnkodmFsdWUpIHtcbiAgICByZXR1cm4gQml0U3RyaW5nLndyYXAodmFsdWUsIHsgXCJ0eXBlXCI6IFwiYmluYXJ5XCIsIFwidW5pdFwiOiA4LCBcInNpemVcIjogdmFsdWUubGVuZ3RoIH0pO1xuICB9XG5cbiAgc3RhdGljIGJ5dGVzKHZhbHVlKSB7XG4gICAgcmV0dXJuIEJpdFN0cmluZy5iaW5hcnkodmFsdWUpO1xuICB9XG5cbiAgc3RhdGljIHV0ZjgodmFsdWUpIHtcbiAgICByZXR1cm4gQml0U3RyaW5nLndyYXAodmFsdWUsIHsgXCJ0eXBlXCI6IFwidXRmOFwiIH0pO1xuICB9XG5cbiAgc3RhdGljIHV0ZjE2KHZhbHVlKSB7XG4gICAgcmV0dXJuIEJpdFN0cmluZy53cmFwKHZhbHVlLCB7IFwidHlwZVwiOiBcInV0ZjE2XCIgfSk7XG4gIH1cblxuICBzdGF0aWMgdXRmMzIodmFsdWUpIHtcbiAgICByZXR1cm4gQml0U3RyaW5nLndyYXAodmFsdWUsIHsgXCJ0eXBlXCI6IFwidXRmMzJcIiB9KTtcbiAgfVxuXG4gIHN0YXRpYyBzaWduZWQodmFsdWUpIHtcbiAgICByZXR1cm4gQml0U3RyaW5nLndyYXAodmFsdWUsIHt9LCBcInNpZ25lZFwiKTtcbiAgfVxuXG4gIHN0YXRpYyB1bnNpZ25lZCh2YWx1ZSkge1xuICAgIHJldHVybiBCaXRTdHJpbmcud3JhcCh2YWx1ZSwge30sIFwidW5zaWduZWRcIik7XG4gIH1cblxuICBzdGF0aWMgbmF0aXZlKHZhbHVlKSB7XG4gICAgcmV0dXJuIEJpdFN0cmluZy53cmFwKHZhbHVlLCB7fSwgXCJuYXRpdmVcIik7XG4gIH1cblxuICBzdGF0aWMgYmlnKHZhbHVlKSB7XG4gICAgcmV0dXJuIEJpdFN0cmluZy53cmFwKHZhbHVlLCB7fSwgXCJiaWdcIik7XG4gIH1cblxuICBzdGF0aWMgbGl0dGxlKHZhbHVlKSB7XG4gICAgcmV0dXJuIEJpdFN0cmluZy53cmFwKHZhbHVlLCB7fSwgXCJsaXR0bGVcIik7XG4gIH1cblxuICBzdGF0aWMgc2l6ZSh2YWx1ZSwgY291bnQpIHtcbiAgICByZXR1cm4gQml0U3RyaW5nLndyYXAodmFsdWUsIHsgXCJzaXplXCI6IGNvdW50IH0pO1xuICB9XG5cbiAgc3RhdGljIHVuaXQodmFsdWUsIGNvdW50KSB7XG4gICAgcmV0dXJuIEJpdFN0cmluZy53cmFwKHZhbHVlLCB7IFwidW5pdFwiOiBjb3VudCB9KTtcbiAgfVxuXG4gIHN0YXRpYyB3cmFwKHZhbHVlLCBvcHQsIG5ld19hdHRyaWJ1dGUgPSBudWxsKSB7XG4gICAgbGV0IHRoZV92YWx1ZSA9IHZhbHVlO1xuXG4gICAgaWYgKCEodmFsdWUgaW5zdGFuY2VvZiBPYmplY3QpKSB7XG4gICAgICB0aGVfdmFsdWUgPSB7IFwidmFsdWVcIjogdmFsdWUsIFwiYXR0cmlidXRlc1wiOiBbXSB9O1xuICAgIH1cblxuICAgIHRoZV92YWx1ZSA9IE9iamVjdC5hc3NpZ24odGhlX3ZhbHVlLCBvcHQpO1xuXG4gICAgaWYgKG5ld19hdHRyaWJ1dGUpIHtcbiAgICAgIHRoZV92YWx1ZS5hdHRyaWJ1dGVzLnB1c2gobmV3X2F0dHJpYnV0ZSk7XG4gICAgfVxuXG4gICAgcmV0dXJuIHRoZV92YWx1ZTtcbiAgfVxuXG4gIHN0YXRpYyB0b1VURjhBcnJheShzdHIpIHtcbiAgICB2YXIgdXRmOCA9IFtdO1xuICAgIGZvciAodmFyIGkgPSAwOyBpIDwgc3RyLmxlbmd0aDsgaSsrKSB7XG4gICAgICB2YXIgY2hhcmNvZGUgPSBzdHIuY2hhckNvZGVBdChpKTtcbiAgICAgIGlmIChjaGFyY29kZSA8IDEyOCkge1xuICAgICAgICB1dGY4LnB1c2goY2hhcmNvZGUpO1xuICAgICAgfSBlbHNlIGlmIChjaGFyY29kZSA8IDIwNDgpIHtcbiAgICAgICAgdXRmOC5wdXNoKDE5MiB8IGNoYXJjb2RlID4+IDYsIDEyOCB8IGNoYXJjb2RlICYgNjMpO1xuICAgICAgfSBlbHNlIGlmIChjaGFyY29kZSA8IDU1Mjk2IHx8IGNoYXJjb2RlID49IDU3MzQ0KSB7XG4gICAgICAgIHV0ZjgucHVzaCgyMjQgfCBjaGFyY29kZSA+PiAxMiwgMTI4IHwgY2hhcmNvZGUgPj4gNiAmIDYzLCAxMjggfCBjaGFyY29kZSAmIDYzKTtcbiAgICAgIH1cbiAgICAgIC8vIHN1cnJvZ2F0ZSBwYWlyXG4gICAgICBlbHNlIHtcbiAgICAgICAgaSsrO1xuICAgICAgICAvLyBVVEYtMTYgZW5jb2RlcyAweDEwMDAwLTB4MTBGRkZGIGJ5XG4gICAgICAgIC8vIHN1YnRyYWN0aW5nIDB4MTAwMDAgYW5kIHNwbGl0dGluZyB0aGVcbiAgICAgICAgLy8gMjAgYml0cyBvZiAweDAtMHhGRkZGRiBpbnRvIHR3byBoYWx2ZXNcbiAgICAgICAgY2hhcmNvZGUgPSA2NTUzNiArICgoY2hhcmNvZGUgJiAxMDIzKSA8PCAxMCB8IHN0ci5jaGFyQ29kZUF0KGkpICYgMTAyMyk7XG4gICAgICAgIHV0ZjgucHVzaCgyNDAgfCBjaGFyY29kZSA+PiAxOCwgMTI4IHwgY2hhcmNvZGUgPj4gMTIgJiA2MywgMTI4IHwgY2hhcmNvZGUgPj4gNiAmIDYzLCAxMjggfCBjaGFyY29kZSAmIDYzKTtcbiAgICAgIH1cbiAgICB9XG4gICAgcmV0dXJuIHV0Zjg7XG4gIH1cblxuICBzdGF0aWMgdG9VVEYxNkFycmF5KHN0cikge1xuICAgIHZhciB1dGYxNiA9IFtdO1xuICAgIGZvciAodmFyIGkgPSAwOyBpIDwgc3RyLmxlbmd0aDsgaSsrKSB7XG4gICAgICB2YXIgY29kZVBvaW50ID0gc3RyLmNvZGVQb2ludEF0KGkpO1xuXG4gICAgICBpZiAoY29kZVBvaW50IDw9IDI1NSkge1xuICAgICAgICB1dGYxNi5wdXNoKDApO1xuICAgICAgICB1dGYxNi5wdXNoKGNvZGVQb2ludCk7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICB1dGYxNi5wdXNoKGNvZGVQb2ludCA+PiA4ICYgMjU1KTtcbiAgICAgICAgdXRmMTYucHVzaChjb2RlUG9pbnQgJiAyNTUpO1xuICAgICAgfVxuICAgIH1cbiAgICByZXR1cm4gdXRmMTY7XG4gIH1cblxuICBzdGF0aWMgdG9VVEYzMkFycmF5KHN0cikge1xuICAgIHZhciB1dGYzMiA9IFtdO1xuICAgIGZvciAodmFyIGkgPSAwOyBpIDwgc3RyLmxlbmd0aDsgaSsrKSB7XG4gICAgICB2YXIgY29kZVBvaW50ID0gc3RyLmNvZGVQb2ludEF0KGkpO1xuXG4gICAgICBpZiAoY29kZVBvaW50IDw9IDI1NSkge1xuICAgICAgICB1dGYzMi5wdXNoKDApO1xuICAgICAgICB1dGYzMi5wdXNoKDApO1xuICAgICAgICB1dGYzMi5wdXNoKDApO1xuICAgICAgICB1dGYzMi5wdXNoKGNvZGVQb2ludCk7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICB1dGYzMi5wdXNoKDApO1xuICAgICAgICB1dGYzMi5wdXNoKDApO1xuICAgICAgICB1dGYzMi5wdXNoKGNvZGVQb2ludCA+PiA4ICYgMjU1KTtcbiAgICAgICAgdXRmMzIucHVzaChjb2RlUG9pbnQgJiAyNTUpO1xuICAgICAgfVxuICAgIH1cbiAgICByZXR1cm4gdXRmMzI7XG4gIH1cblxuICAvL2h0dHA6Ly9zdGFja292ZXJmbG93LmNvbS9xdWVzdGlvbnMvMjAwMzQ5My9qYXZhc2NyaXB0LWZsb2F0LWZyb20tdG8tYml0c1xuICBzdGF0aWMgZmxvYXQzMlRvQnl0ZXMoZikge1xuICAgIHZhciBieXRlcyA9IFtdO1xuXG4gICAgdmFyIGJ1ZiA9IG5ldyBBcnJheUJ1ZmZlcig0KTtcbiAgICBuZXcgRmxvYXQzMkFycmF5KGJ1ZilbMF0gPSBmO1xuXG4gICAgbGV0IGludFZlcnNpb24gPSBuZXcgVWludDMyQXJyYXkoYnVmKVswXTtcblxuICAgIGJ5dGVzLnB1c2goaW50VmVyc2lvbiA+PiAyNCAmIDI1NSk7XG4gICAgYnl0ZXMucHVzaChpbnRWZXJzaW9uID4+IDE2ICYgMjU1KTtcbiAgICBieXRlcy5wdXNoKGludFZlcnNpb24gPj4gOCAmIDI1NSk7XG4gICAgYnl0ZXMucHVzaChpbnRWZXJzaW9uICYgMjU1KTtcblxuICAgIHJldHVybiBieXRlcztcbiAgfVxuXG4gIHN0YXRpYyBmbG9hdDY0VG9CeXRlcyhmKSB7XG4gICAgdmFyIGJ5dGVzID0gW107XG5cbiAgICB2YXIgYnVmID0gbmV3IEFycmF5QnVmZmVyKDgpO1xuICAgIG5ldyBGbG9hdDY0QXJyYXkoYnVmKVswXSA9IGY7XG5cbiAgICB2YXIgaW50VmVyc2lvbjEgPSBuZXcgVWludDMyQXJyYXkoYnVmKVswXTtcbiAgICB2YXIgaW50VmVyc2lvbjIgPSBuZXcgVWludDMyQXJyYXkoYnVmKVsxXTtcblxuICAgIGJ5dGVzLnB1c2goaW50VmVyc2lvbjIgPj4gMjQgJiAyNTUpO1xuICAgIGJ5dGVzLnB1c2goaW50VmVyc2lvbjIgPj4gMTYgJiAyNTUpO1xuICAgIGJ5dGVzLnB1c2goaW50VmVyc2lvbjIgPj4gOCAmIDI1NSk7XG4gICAgYnl0ZXMucHVzaChpbnRWZXJzaW9uMiAmIDI1NSk7XG5cbiAgICBieXRlcy5wdXNoKGludFZlcnNpb24xID4+IDI0ICYgMjU1KTtcbiAgICBieXRlcy5wdXNoKGludFZlcnNpb24xID4+IDE2ICYgMjU1KTtcbiAgICBieXRlcy5wdXNoKGludFZlcnNpb24xID4+IDggJiAyNTUpO1xuICAgIGJ5dGVzLnB1c2goaW50VmVyc2lvbjEgJiAyNTUpO1xuXG4gICAgcmV0dXJuIGJ5dGVzO1xuICB9XG59XG5cbi8qIEBmbG93ICovXG5cbmNsYXNzIFZhcmlhYmxlIHtcblxuICBjb25zdHJ1Y3RvcihuYW1lID0gbnVsbCkge1xuICAgIHRoaXMubmFtZSA9IG5hbWU7XG4gIH1cbn1cblxuY2xhc3MgV2lsZGNhcmQge1xuICBjb25zdHJ1Y3RvcigpIHt9XG59XG5cbmNsYXNzIFN0YXJ0c1dpdGgge1xuXG4gIGNvbnN0cnVjdG9yKHByZWZpeCkge1xuICAgIHRoaXMucHJlZml4ID0gcHJlZml4O1xuICB9XG59XG5cbmNsYXNzIENhcHR1cmUge1xuXG4gIGNvbnN0cnVjdG9yKHZhbHVlKSB7XG4gICAgdGhpcy52YWx1ZSA9IHZhbHVlO1xuICB9XG59XG5cbmNsYXNzIEhlYWRUYWlsIHtcbiAgY29uc3RydWN0b3IoKSB7fVxufVxuXG5jbGFzcyBUeXBlIHtcblxuICBjb25zdHJ1Y3Rvcih0eXBlLCBvYmpQYXR0ZXJuID0ge30pIHtcbiAgICB0aGlzLnR5cGUgPSB0eXBlO1xuICAgIHRoaXMub2JqUGF0dGVybiA9IG9ialBhdHRlcm47XG4gIH1cbn1cblxuY2xhc3MgQm91bmQge1xuXG4gIGNvbnN0cnVjdG9yKHZhbHVlKSB7XG4gICAgdGhpcy52YWx1ZSA9IHZhbHVlO1xuICB9XG59XG5cbmZ1bmN0aW9uIHZhcmlhYmxlKG5hbWUgPSBudWxsKSB7XG4gIHJldHVybiBuZXcgVmFyaWFibGUobmFtZSk7XG59XG5cbmZ1bmN0aW9uIHdpbGRjYXJkKCkge1xuICByZXR1cm4gbmV3IFdpbGRjYXJkKCk7XG59XG5cbmZ1bmN0aW9uIHN0YXJ0c1dpdGgocHJlZml4KSB7XG4gIHJldHVybiBuZXcgU3RhcnRzV2l0aChwcmVmaXgpO1xufVxuXG5mdW5jdGlvbiBjYXB0dXJlKHZhbHVlKSB7XG4gIHJldHVybiBuZXcgQ2FwdHVyZSh2YWx1ZSk7XG59XG5cbmZ1bmN0aW9uIGhlYWRUYWlsKCkge1xuICByZXR1cm4gbmV3IEhlYWRUYWlsKCk7XG59XG5cbmZ1bmN0aW9uIHR5cGUodHlwZSwgb2JqUGF0dGVybiA9IHt9KSB7XG4gIHJldHVybiBuZXcgVHlwZSh0eXBlLCBvYmpQYXR0ZXJuKTtcbn1cblxuZnVuY3Rpb24gYm91bmQodmFsdWUpIHtcbiAgcmV0dXJuIG5ldyBCb3VuZCh2YWx1ZSk7XG59XG5cbmZ1bmN0aW9uIGlzX251bWJlcih2YWx1ZSkge1xuICByZXR1cm4gdHlwZW9mIHZhbHVlID09PSAnbnVtYmVyJztcbn1cblxuZnVuY3Rpb24gaXNfc3RyaW5nKHZhbHVlKSB7XG4gIHJldHVybiB0eXBlb2YgdmFsdWUgPT09ICdzdHJpbmcnO1xufVxuXG5mdW5jdGlvbiBpc19ib29sZWFuKHZhbHVlKSB7XG4gIHJldHVybiB0eXBlb2YgdmFsdWUgPT09ICdib29sZWFuJztcbn1cblxuZnVuY3Rpb24gaXNfc3ltYm9sKHZhbHVlKSB7XG4gIHJldHVybiB0eXBlb2YgdmFsdWUgPT09ICdzeW1ib2wnO1xufVxuXG5mdW5jdGlvbiBpc19udWxsKHZhbHVlKSB7XG4gIHJldHVybiB2YWx1ZSA9PT0gbnVsbDtcbn1cblxuZnVuY3Rpb24gaXNfdW5kZWZpbmVkKHZhbHVlKSB7XG4gIHJldHVybiB0eXBlb2YgdmFsdWUgPT09ICd1bmRlZmluZWQnO1xufVxuXG5mdW5jdGlvbiBpc19mdW5jdGlvbih2YWx1ZSkge1xuICByZXR1cm4gT2JqZWN0LnByb3RvdHlwZS50b1N0cmluZy5jYWxsKHZhbHVlKSA9PSAnW29iamVjdCBGdW5jdGlvbl0nO1xufVxuXG5mdW5jdGlvbiBpc192YXJpYWJsZSh2YWx1ZSkge1xuICByZXR1cm4gdmFsdWUgaW5zdGFuY2VvZiBWYXJpYWJsZTtcbn1cblxuZnVuY3Rpb24gaXNfd2lsZGNhcmQodmFsdWUpIHtcbiAgcmV0dXJuIHZhbHVlIGluc3RhbmNlb2YgV2lsZGNhcmQ7XG59XG5cbmZ1bmN0aW9uIGlzX2hlYWRUYWlsKHZhbHVlKSB7XG4gIHJldHVybiB2YWx1ZSBpbnN0YW5jZW9mIEhlYWRUYWlsO1xufVxuXG5mdW5jdGlvbiBpc19jYXB0dXJlKHZhbHVlKSB7XG4gIHJldHVybiB2YWx1ZSBpbnN0YW5jZW9mIENhcHR1cmU7XG59XG5cbmZ1bmN0aW9uIGlzX3R5cGUodmFsdWUpIHtcbiAgcmV0dXJuIHZhbHVlIGluc3RhbmNlb2YgVHlwZTtcbn1cblxuZnVuY3Rpb24gaXNfc3RhcnRzV2l0aCh2YWx1ZSkge1xuICByZXR1cm4gdmFsdWUgaW5zdGFuY2VvZiBTdGFydHNXaXRoO1xufVxuXG5mdW5jdGlvbiBpc19ib3VuZCh2YWx1ZSkge1xuICByZXR1cm4gdmFsdWUgaW5zdGFuY2VvZiBCb3VuZDtcbn1cblxuZnVuY3Rpb24gaXNfb2JqZWN0KHZhbHVlKSB7XG4gIHJldHVybiB0eXBlb2YgdmFsdWUgPT09ICdvYmplY3QnO1xufVxuXG5mdW5jdGlvbiBpc19hcnJheSh2YWx1ZSkge1xuICByZXR1cm4gQXJyYXkuaXNBcnJheSh2YWx1ZSk7XG59XG5cbnZhciBDaGVja3MgPSB7XG4gIGlzX251bWJlcixcbiAgaXNfc3RyaW5nLFxuICBpc19ib29sZWFuLFxuICBpc19zeW1ib2wsXG4gIGlzX251bGwsXG4gIGlzX3VuZGVmaW5lZCxcbiAgaXNfZnVuY3Rpb24sXG4gIGlzX3ZhcmlhYmxlLFxuICBpc193aWxkY2FyZCxcbiAgaXNfaGVhZFRhaWwsXG4gIGlzX2NhcHR1cmUsXG4gIGlzX3R5cGUsXG4gIGlzX3N0YXJ0c1dpdGgsXG4gIGlzX2JvdW5kLFxuICBpc19vYmplY3QsXG4gIGlzX2FycmF5XG59O1xuXG5mdW5jdGlvbiByZXNvbHZlU3ltYm9sKHBhdHRlcm4pIHtcbiAgcmV0dXJuIGZ1bmN0aW9uICh2YWx1ZSkge1xuICAgIHJldHVybiBDaGVja3MuaXNfc3ltYm9sKHZhbHVlKSAmJiB2YWx1ZSA9PT0gcGF0dGVybjtcbiAgfTtcbn1cblxuZnVuY3Rpb24gcmVzb2x2ZVN0cmluZyhwYXR0ZXJuKSB7XG4gIHJldHVybiBmdW5jdGlvbiAodmFsdWUpIHtcbiAgICByZXR1cm4gQ2hlY2tzLmlzX3N0cmluZyh2YWx1ZSkgJiYgdmFsdWUgPT09IHBhdHRlcm47XG4gIH07XG59XG5cbmZ1bmN0aW9uIHJlc29sdmVOdW1iZXIocGF0dGVybikge1xuICByZXR1cm4gZnVuY3Rpb24gKHZhbHVlKSB7XG4gICAgcmV0dXJuIENoZWNrcy5pc19udW1iZXIodmFsdWUpICYmIHZhbHVlID09PSBwYXR0ZXJuO1xuICB9O1xufVxuXG5mdW5jdGlvbiByZXNvbHZlQm9vbGVhbihwYXR0ZXJuKSB7XG4gIHJldHVybiBmdW5jdGlvbiAodmFsdWUpIHtcbiAgICByZXR1cm4gQ2hlY2tzLmlzX2Jvb2xlYW4odmFsdWUpICYmIHZhbHVlID09PSBwYXR0ZXJuO1xuICB9O1xufVxuXG5mdW5jdGlvbiByZXNvbHZlRnVuY3Rpb24ocGF0dGVybikge1xuICByZXR1cm4gZnVuY3Rpb24gKHZhbHVlKSB7XG4gICAgcmV0dXJuIENoZWNrcy5pc19mdW5jdGlvbih2YWx1ZSkgJiYgdmFsdWUgPT09IHBhdHRlcm47XG4gIH07XG59XG5cbmZ1bmN0aW9uIHJlc29sdmVOdWxsKHBhdHRlcm4pIHtcbiAgcmV0dXJuIGZ1bmN0aW9uICh2YWx1ZSkge1xuICAgIHJldHVybiBDaGVja3MuaXNfbnVsbCh2YWx1ZSk7XG4gIH07XG59XG5cbmZ1bmN0aW9uIHJlc29sdmVCb3VuZChwYXR0ZXJuKSB7XG4gIHJldHVybiBmdW5jdGlvbiAodmFsdWUsIGFyZ3MpIHtcbiAgICBpZiAodHlwZW9mIHZhbHVlID09PSB0eXBlb2YgcGF0dGVybi52YWx1ZSAmJiB2YWx1ZSA9PT0gcGF0dGVybi52YWx1ZSkge1xuICAgICAgYXJncy5wdXNoKHZhbHVlKTtcbiAgICAgIHJldHVybiB0cnVlO1xuICAgIH1cblxuICAgIHJldHVybiBmYWxzZTtcbiAgfTtcbn1cblxuZnVuY3Rpb24gcmVzb2x2ZVdpbGRjYXJkKCkge1xuICByZXR1cm4gZnVuY3Rpb24gKCkge1xuICAgIHJldHVybiB0cnVlO1xuICB9O1xufVxuXG5mdW5jdGlvbiByZXNvbHZlVmFyaWFibGUoKSB7XG4gIHJldHVybiBmdW5jdGlvbiAodmFsdWUsIGFyZ3MpIHtcbiAgICBhcmdzLnB1c2godmFsdWUpO1xuICAgIHJldHVybiB0cnVlO1xuICB9O1xufVxuXG5mdW5jdGlvbiByZXNvbHZlSGVhZFRhaWwoKSB7XG4gIHJldHVybiBmdW5jdGlvbiAodmFsdWUsIGFyZ3MpIHtcbiAgICBpZiAoIUNoZWNrcy5pc19hcnJheSh2YWx1ZSkgfHwgdmFsdWUubGVuZ3RoIDwgMikge1xuICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH1cblxuICAgIGNvbnN0IGhlYWQgPSB2YWx1ZVswXTtcbiAgICBjb25zdCB0YWlsID0gdmFsdWUuc2xpY2UoMSk7XG5cbiAgICBhcmdzLnB1c2goaGVhZCk7XG4gICAgYXJncy5wdXNoKHRhaWwpO1xuXG4gICAgcmV0dXJuIHRydWU7XG4gIH07XG59XG5cbmZ1bmN0aW9uIHJlc29sdmVDYXB0dXJlKHBhdHRlcm4pIHtcbiAgY29uc3QgbWF0Y2hlcyA9IGJ1aWxkTWF0Y2gocGF0dGVybi52YWx1ZSk7XG5cbiAgcmV0dXJuIGZ1bmN0aW9uICh2YWx1ZSwgYXJncykge1xuICAgIGlmIChtYXRjaGVzKHZhbHVlLCBhcmdzKSkge1xuICAgICAgYXJncy5wdXNoKHZhbHVlKTtcbiAgICAgIHJldHVybiB0cnVlO1xuICAgIH1cblxuICAgIHJldHVybiBmYWxzZTtcbiAgfTtcbn1cblxuZnVuY3Rpb24gcmVzb2x2ZVN0YXJ0c1dpdGgocGF0dGVybikge1xuICBjb25zdCBwcmVmaXggPSBwYXR0ZXJuLnByZWZpeDtcblxuICByZXR1cm4gZnVuY3Rpb24gKHZhbHVlLCBhcmdzKSB7XG4gICAgaWYgKENoZWNrcy5pc19zdHJpbmcodmFsdWUpICYmIHZhbHVlLnN0YXJ0c1dpdGgocHJlZml4KSkge1xuICAgICAgYXJncy5wdXNoKHZhbHVlLnN1YnN0cmluZyhwcmVmaXgubGVuZ3RoKSk7XG4gICAgICByZXR1cm4gdHJ1ZTtcbiAgICB9XG5cbiAgICByZXR1cm4gZmFsc2U7XG4gIH07XG59XG5cbmZ1bmN0aW9uIHJlc29sdmVUeXBlKHBhdHRlcm4pIHtcbiAgcmV0dXJuIGZ1bmN0aW9uICh2YWx1ZSwgYXJncykge1xuICAgIGlmICh2YWx1ZSBpbnN0YW5jZW9mIHBhdHRlcm4udHlwZSkge1xuICAgICAgY29uc3QgbWF0Y2hlcyA9IGJ1aWxkTWF0Y2gocGF0dGVybi5vYmpQYXR0ZXJuKTtcbiAgICAgIHJldHVybiBtYXRjaGVzKHZhbHVlLCBhcmdzKSAmJiBhcmdzLnB1c2godmFsdWUpID4gMDtcbiAgICB9XG5cbiAgICByZXR1cm4gZmFsc2U7XG4gIH07XG59XG5cbmZ1bmN0aW9uIHJlc29sdmVBcnJheShwYXR0ZXJuKSB7XG4gIGNvbnN0IG1hdGNoZXMgPSBwYXR0ZXJuLm1hcCh4ID0+IGJ1aWxkTWF0Y2goeCkpO1xuXG4gIHJldHVybiBmdW5jdGlvbiAodmFsdWUsIGFyZ3MpIHtcbiAgICBpZiAoIUNoZWNrcy5pc19hcnJheSh2YWx1ZSkgfHwgdmFsdWUubGVuZ3RoICE9IHBhdHRlcm4ubGVuZ3RoKSB7XG4gICAgICByZXR1cm4gZmFsc2U7XG4gICAgfVxuXG4gICAgcmV0dXJuIHZhbHVlLmV2ZXJ5KGZ1bmN0aW9uICh2LCBpKSB7XG4gICAgICByZXR1cm4gbWF0Y2hlc1tpXSh2YWx1ZVtpXSwgYXJncyk7XG4gICAgfSk7XG4gIH07XG59XG5cbmZ1bmN0aW9uIHJlc29sdmVPYmplY3QocGF0dGVybikge1xuICBsZXQgbWF0Y2hlcyA9IHt9O1xuXG4gIGZvciAobGV0IGtleSBvZiBPYmplY3Qua2V5cyhwYXR0ZXJuKS5jb25jYXQoT2JqZWN0LmdldE93blByb3BlcnR5U3ltYm9scyhwYXR0ZXJuKSkpIHtcbiAgICBtYXRjaGVzW2tleV0gPSBidWlsZE1hdGNoKHBhdHRlcm5ba2V5XSk7XG4gIH1cblxuICByZXR1cm4gZnVuY3Rpb24gKHZhbHVlLCBhcmdzKSB7XG4gICAgaWYgKCFDaGVja3MuaXNfb2JqZWN0KHZhbHVlKSB8fCBwYXR0ZXJuLmxlbmd0aCA+IHZhbHVlLmxlbmd0aCkge1xuICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH1cblxuICAgIGZvciAobGV0IGtleSBvZiBPYmplY3Qua2V5cyhwYXR0ZXJuKS5jb25jYXQoT2JqZWN0LmdldE93blByb3BlcnR5U3ltYm9scyhwYXR0ZXJuKSkpIHtcbiAgICAgIGlmICghKGtleSBpbiB2YWx1ZSkgfHwgIW1hdGNoZXNba2V5XSh2YWx1ZVtrZXldLCBhcmdzKSkge1xuICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICB9XG4gICAgfVxuXG4gICAgcmV0dXJuIHRydWU7XG4gIH07XG59XG5cbmZ1bmN0aW9uIHJlc29sdmVOb01hdGNoKCkge1xuICByZXR1cm4gZnVuY3Rpb24gKCkge1xuICAgIHJldHVybiBmYWxzZTtcbiAgfTtcbn1cblxudmFyIFJlc29sdmVycyA9IHtcbiAgcmVzb2x2ZUJvdW5kLFxuICByZXNvbHZlV2lsZGNhcmQsXG4gIHJlc29sdmVWYXJpYWJsZSxcbiAgcmVzb2x2ZUhlYWRUYWlsLFxuICByZXNvbHZlQ2FwdHVyZSxcbiAgcmVzb2x2ZVN0YXJ0c1dpdGgsXG4gIHJlc29sdmVUeXBlLFxuICByZXNvbHZlQXJyYXksXG4gIHJlc29sdmVPYmplY3QsXG4gIHJlc29sdmVOb01hdGNoLFxuICByZXNvbHZlU3ltYm9sLFxuICByZXNvbHZlU3RyaW5nLFxuICByZXNvbHZlTnVtYmVyLFxuICByZXNvbHZlQm9vbGVhbixcbiAgcmVzb2x2ZUZ1bmN0aW9uLFxuICByZXNvbHZlTnVsbFxufTtcblxuZnVuY3Rpb24gYnVpbGRNYXRjaChwYXR0ZXJuKSB7XG5cbiAgaWYgKENoZWNrcy5pc192YXJpYWJsZShwYXR0ZXJuKSkge1xuICAgIHJldHVybiBSZXNvbHZlcnMucmVzb2x2ZVZhcmlhYmxlKHBhdHRlcm4pO1xuICB9XG5cbiAgaWYgKENoZWNrcy5pc193aWxkY2FyZChwYXR0ZXJuKSkge1xuICAgIHJldHVybiBSZXNvbHZlcnMucmVzb2x2ZVdpbGRjYXJkKHBhdHRlcm4pO1xuICB9XG5cbiAgaWYgKENoZWNrcy5pc191bmRlZmluZWQocGF0dGVybikpIHtcbiAgICByZXR1cm4gUmVzb2x2ZXJzLnJlc29sdmVXaWxkY2FyZChwYXR0ZXJuKTtcbiAgfVxuXG4gIGlmIChDaGVja3MuaXNfaGVhZFRhaWwocGF0dGVybikpIHtcbiAgICByZXR1cm4gUmVzb2x2ZXJzLnJlc29sdmVIZWFkVGFpbChwYXR0ZXJuKTtcbiAgfVxuXG4gIGlmIChDaGVja3MuaXNfc3RhcnRzV2l0aChwYXR0ZXJuKSkge1xuICAgIHJldHVybiBSZXNvbHZlcnMucmVzb2x2ZVN0YXJ0c1dpdGgocGF0dGVybik7XG4gIH1cblxuICBpZiAoQ2hlY2tzLmlzX2NhcHR1cmUocGF0dGVybikpIHtcbiAgICByZXR1cm4gUmVzb2x2ZXJzLnJlc29sdmVDYXB0dXJlKHBhdHRlcm4pO1xuICB9XG5cbiAgaWYgKENoZWNrcy5pc19ib3VuZChwYXR0ZXJuKSkge1xuICAgIHJldHVybiBSZXNvbHZlcnMucmVzb2x2ZUJvdW5kKHBhdHRlcm4pO1xuICB9XG5cbiAgaWYgKENoZWNrcy5pc190eXBlKHBhdHRlcm4pKSB7XG4gICAgcmV0dXJuIFJlc29sdmVycy5yZXNvbHZlVHlwZShwYXR0ZXJuKTtcbiAgfVxuXG4gIGlmIChDaGVja3MuaXNfYXJyYXkocGF0dGVybikpIHtcbiAgICByZXR1cm4gUmVzb2x2ZXJzLnJlc29sdmVBcnJheShwYXR0ZXJuKTtcbiAgfVxuXG4gIGlmIChDaGVja3MuaXNfbnVtYmVyKHBhdHRlcm4pKSB7XG4gICAgcmV0dXJuIFJlc29sdmVycy5yZXNvbHZlTnVtYmVyKHBhdHRlcm4pO1xuICB9XG5cbiAgaWYgKENoZWNrcy5pc19zdHJpbmcocGF0dGVybikpIHtcbiAgICByZXR1cm4gUmVzb2x2ZXJzLnJlc29sdmVTdHJpbmcocGF0dGVybik7XG4gIH1cblxuICBpZiAoQ2hlY2tzLmlzX2Jvb2xlYW4ocGF0dGVybikpIHtcbiAgICByZXR1cm4gUmVzb2x2ZXJzLnJlc29sdmVCb29sZWFuKHBhdHRlcm4pO1xuICB9XG5cbiAgaWYgKENoZWNrcy5pc19zeW1ib2wocGF0dGVybikpIHtcbiAgICByZXR1cm4gUmVzb2x2ZXJzLnJlc29sdmVTeW1ib2wocGF0dGVybik7XG4gIH1cblxuICBpZiAoQ2hlY2tzLmlzX251bGwocGF0dGVybikpIHtcbiAgICByZXR1cm4gUmVzb2x2ZXJzLnJlc29sdmVOdWxsKHBhdHRlcm4pO1xuICB9XG5cbiAgaWYgKENoZWNrcy5pc19vYmplY3QocGF0dGVybikpIHtcbiAgICByZXR1cm4gUmVzb2x2ZXJzLnJlc29sdmVPYmplY3QocGF0dGVybik7XG4gIH1cblxuICByZXR1cm4gUmVzb2x2ZXJzLnJlc29sdmVOb01hdGNoKCk7XG59XG5cbmNsYXNzIE1hdGNoRXJyb3IgZXh0ZW5kcyBFcnJvciB7XG4gIGNvbnN0cnVjdG9yKGFyZykge1xuICAgIHN1cGVyKCk7XG5cbiAgICBpZiAodHlwZW9mIGFyZyA9PT0gJ3N5bWJvbCcpIHtcbiAgICAgIHRoaXMubWVzc2FnZSA9ICdObyBtYXRjaCBmb3I6ICcgKyBhcmcudG9TdHJpbmcoKTtcbiAgICB9IGVsc2UgaWYgKEFycmF5LmlzQXJyYXkoYXJnKSkge1xuICAgICAgbGV0IG1hcHBlZFZhbHVlcyA9IGFyZy5tYXAoeCA9PiB4LnRvU3RyaW5nKCkpO1xuICAgICAgdGhpcy5tZXNzYWdlID0gJ05vIG1hdGNoIGZvcjogJyArIG1hcHBlZFZhbHVlcztcbiAgICB9IGVsc2Uge1xuICAgICAgdGhpcy5tZXNzYWdlID0gJ05vIG1hdGNoIGZvcjogJyArIGFyZztcbiAgICB9XG5cbiAgICB0aGlzLnN0YWNrID0gbmV3IEVycm9yKCkuc3RhY2s7XG4gICAgdGhpcy5uYW1lID0gdGhpcy5jb25zdHJ1Y3Rvci5uYW1lO1xuICB9XG59XG5cbmNsYXNzIENhc2Uge1xuXG4gIGNvbnN0cnVjdG9yKHBhdHRlcm4sIGZuLCBndWFyZCA9ICgpID0+IHRydWUpIHtcbiAgICB0aGlzLnBhdHRlcm4gPSBidWlsZE1hdGNoKHBhdHRlcm4pO1xuICAgIHRoaXMuZm4gPSBmbjtcbiAgICB0aGlzLmd1YXJkID0gZ3VhcmQ7XG4gIH1cbn1cblxuZnVuY3Rpb24gbWFrZV9jYXNlKHBhdHRlcm4sIGZuLCBndWFyZCA9ICgpID0+IHRydWUpIHtcbiAgcmV0dXJuIG5ldyBDYXNlKHBhdHRlcm4sIGZuLCBndWFyZCk7XG59XG5cbmZ1bmN0aW9uIGRlZm1hdGNoKC4uLmNhc2VzKSB7XG4gIHJldHVybiBmdW5jdGlvbiAoLi4uYXJncykge1xuICAgIGZvciAobGV0IHByb2Nlc3NlZENhc2Ugb2YgY2FzZXMpIHtcbiAgICAgIGxldCByZXN1bHQgPSBbXTtcbiAgICAgIGlmIChwcm9jZXNzZWRDYXNlLnBhdHRlcm4oYXJncywgcmVzdWx0KSAmJiBwcm9jZXNzZWRDYXNlLmd1YXJkLmFwcGx5KHRoaXMsIHJlc3VsdCkpIHtcbiAgICAgICAgcmV0dXJuIHByb2Nlc3NlZENhc2UuZm4uYXBwbHkodGhpcywgcmVzdWx0KTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICB0aHJvdyBuZXcgTWF0Y2hFcnJvcihhcmdzKTtcbiAgfTtcbn1cblxuZnVuY3Rpb24gbWF0Y2gocGF0dGVybiwgZXhwciwgZ3VhcmQgPSAoKSA9PiB0cnVlKSB7XG4gIGxldCByZXN1bHQgPSBbXTtcbiAgbGV0IHByb2Nlc3NlZFBhdHRlcm4gPSBidWlsZE1hdGNoKHBhdHRlcm4pO1xuICBpZiAocHJvY2Vzc2VkUGF0dGVybihleHByLCByZXN1bHQpICYmIGd1YXJkLmFwcGx5KHRoaXMsIHJlc3VsdCkpIHtcbiAgICByZXR1cm4gcmVzdWx0O1xuICB9IGVsc2Uge1xuICAgIHRocm93IG5ldyBNYXRjaEVycm9yKGV4cHIpO1xuICB9XG59XG5cbmZ1bmN0aW9uIG1hdGNoX25vX3Rocm93KHBhdHRlcm4sIGV4cHIsIGd1YXJkID0gKCkgPT4gdHJ1ZSkge1xuICB0cnkge1xuICAgIHJldHVybiBtYXRjaChwYXR0ZXJuLCBleHByLCBndWFyZCk7XG4gIH0gY2F0Y2ggKGUpIHtcbiAgICBpZiAoZSBpbnN0YW5jZW9mIE1hdGNoRXJyb3IpIHtcbiAgICAgIHJldHVybiBudWxsO1xuICAgIH1cblxuICAgIHRocm93IGU7XG4gIH1cbn1cblxudmFyIFBhdHRlcm5zID0ge1xuICBkZWZtYXRjaCwgbWF0Y2gsIE1hdGNoRXJyb3IsIG1hdGNoX25vX3Rocm93LFxuICB2YXJpYWJsZSwgd2lsZGNhcmQsIHN0YXJ0c1dpdGgsXG4gIGNhcHR1cmUsIGhlYWRUYWlsLCB0eXBlLCBib3VuZCwgQ2FzZSwgbWFrZV9jYXNlXG59O1xuXG5mdW5jdGlvbiBjYWxsX3Byb3BlcnR5KGl0ZW0sIHByb3BlcnR5KSB7XG4gIGxldCBwcm9wID0gbnVsbDtcblxuICBpZiAocHJvcGVydHkgaW4gaXRlbSkge1xuICAgIHByb3AgPSBwcm9wZXJ0eTtcbiAgfSBlbHNlIGlmIChTeW1ib2wuZm9yKHByb3BlcnR5KSBpbiBpdGVtKSB7XG4gICAgcHJvcCA9IFN5bWJvbC5mb3IocHJvcGVydHkpO1xuICB9IGVsc2Uge1xuICAgIHRocm93IG5ldyBFcnJvcihgUHJvcGVydHkgJHsgcHJvcGVydHkgfSBub3QgZm91bmQgaW4gJHsgaXRlbSB9YCk7XG4gIH1cblxuICBpZiAoaXRlbVtwcm9wXSBpbnN0YW5jZW9mIEZ1bmN0aW9uKSB7XG4gICAgcmV0dXJuIGl0ZW1bcHJvcF0oKTtcbiAgfSBlbHNlIHtcbiAgICByZXR1cm4gaXRlbVtwcm9wXTtcbiAgfVxufVxuXG5mdW5jdGlvbiBhcHBseSguLi5hcmdzKSB7XG4gIGlmIChhcmdzLmxlbmd0aCA9PT0gMikge1xuICAgIGFyZ3NbMF0uYXBwbHkobnVsbCwgYXJncy5zbGljZSgxKSk7XG4gIH0gZWxzZSB7XG4gICAgYXJnc1swXVthcmdzWzFdXS5hcHBseShudWxsLCBhcmdzLnNsaWNlKDIpKTtcbiAgfVxufVxuXG5mdW5jdGlvbiBjb250YWlucyhsZWZ0LCByaWdodCkge1xuICBmb3IgKGxldCB4IG9mIHJpZ2h0KSB7XG4gICAgaWYgKFBhdHRlcm5zLm1hdGNoX25vX3Rocm93KGxlZnQsIHgpICE9IG51bGwpIHtcbiAgICAgIHJldHVybiB0cnVlO1xuICAgIH1cbiAgfVxuXG4gIHJldHVybiBmYWxzZTtcbn1cblxuZnVuY3Rpb24gZ2V0X2dsb2JhbCgpIHtcbiAgaWYgKHR5cGVvZiBzZWxmICE9PSAndW5kZWZpbmVkJykge1xuICAgIHJldHVybiBzZWxmO1xuICB9IGVsc2UgaWYgKHR5cGVvZiB3aW5kb3cgIT09ICd1bmRlZmluZWQnKSB7XG4gICAgcmV0dXJuIHdpbmRvdztcbiAgfSBlbHNlIGlmICh0eXBlb2YgZ2xvYmFsICE9PSAndW5kZWZpbmVkJykge1xuICAgIHJldHVybiBnbG9iYWw7XG4gIH1cblxuICB0aHJvdyBuZXcgRXJyb3IoJ05vIGdsb2JhbCBzdGF0ZSBmb3VuZCcpO1xufVxuXG5mdW5jdGlvbiBkZWZzdHJ1Y3QoZGVmYXVsdHMpIHtcbiAgcmV0dXJuIGNsYXNzIHtcbiAgICBjb25zdHJ1Y3Rvcih1cGRhdGUgPSB7fSkge1xuICAgICAgbGV0IHRoZV92YWx1ZXMgPSBPYmplY3QuYXNzaWduKGRlZmF1bHRzLCB1cGRhdGUpO1xuICAgICAgT2JqZWN0LmFzc2lnbih0aGlzLCB0aGVfdmFsdWVzKTtcbiAgICB9XG5cbiAgICBzdGF0aWMgY3JlYXRlKHVwZGF0ZXMgPSB7fSkge1xuICAgICAgbGV0IHggPSBuZXcgdGhpcyh1cGRhdGVzKTtcbiAgICAgIHJldHVybiBPYmplY3QuZnJlZXplKHgpO1xuICAgIH1cbiAgfTtcbn1cblxuZnVuY3Rpb24gZGVmZXhjZXB0aW9uKGRlZmF1bHRzKSB7XG4gIHJldHVybiBjbGFzcyBleHRlbmRzIEVycm9yIHtcbiAgICBjb25zdHJ1Y3Rvcih1cGRhdGUgPSB7fSkge1xuICAgICAgbGV0IG1lc3NhZ2UgPSB1cGRhdGUubWVzc2FnZSB8fCAnJztcbiAgICAgIHN1cGVyKG1lc3NhZ2UpO1xuXG4gICAgICBsZXQgdGhlX3ZhbHVlcyA9IE9iamVjdC5hc3NpZ24oZGVmYXVsdHMsIHVwZGF0ZSk7XG4gICAgICBPYmplY3QuYXNzaWduKHRoaXMsIHRoZV92YWx1ZXMpO1xuXG4gICAgICB0aGlzLm5hbWUgPSB0aGlzLmNvbnN0cnVjdG9yLm5hbWU7XG4gICAgICB0aGlzLm1lc3NhZ2UgPSBtZXNzYWdlO1xuICAgICAgdGhpc1tTcGVjaWFsRm9ybXMuYXRvbSgnX19leGNlcHRpb25fXycpXSA9IHRydWU7XG4gICAgICBFcnJvci5jYXB0dXJlU3RhY2tUcmFjZSh0aGlzLCB0aGlzLmNvbnN0cnVjdG9yLm5hbWUpO1xuICAgIH1cblxuICAgIHN0YXRpYyBjcmVhdGUodXBkYXRlcyA9IHt9KSB7XG4gICAgICBsZXQgeCA9IG5ldyB0aGlzKHVwZGF0ZXMpO1xuICAgICAgcmV0dXJuIE9iamVjdC5mcmVlemUoeCk7XG4gICAgfVxuICB9O1xufVxuXG5mdW5jdGlvbiBkZWZwcm90b2NvbChzcGVjKSB7XG4gIHJldHVybiBuZXcgUHJvdG9jb2woc3BlYyk7XG59XG5cbmZ1bmN0aW9uIGRlZmltcGwocHJvdG9jb2wsIHR5cGUsIGltcGwpIHtcbiAgcHJvdG9jb2wuaW1wbGVtZW50YXRpb24odHlwZSwgaW1wbCk7XG59XG5cbmZ1bmN0aW9uIGdldF9vYmplY3Rfa2V5cyhvYmopIHtcbiAgcmV0dXJuIE9iamVjdC5rZXlzKG9iaikuY29uY2F0KE9iamVjdC5nZXRPd25Qcm9wZXJ0eVN5bWJvbHMob2JqKSk7XG59XG5cbmZ1bmN0aW9uIGlzX3ZhbGlkX2NoYXJhY3Rlcihjb2RlcG9pbnQpIHtcbiAgdHJ5IHtcbiAgICByZXR1cm4gU3RyaW5nLmZyb21Db2RlUG9pbnQoY29kZXBvaW50KSAhPSBudWxsO1xuICB9IGNhdGNoIChlKSB7XG4gICAgcmV0dXJuIGZhbHNlO1xuICB9XG59XG5cbi8vaHR0cHM6Ly9kZXZlbG9wZXIubW96aWxsYS5vcmcvZW4tVVMvZG9jcy9XZWIvQVBJL1dpbmRvd0Jhc2U2NC9CYXNlNjRfZW5jb2RpbmdfYW5kX2RlY29kaW5nI1NvbHV0aW9uXzJfJUUyJTgwJTkzX3Jld3JpdGVfdGhlX0RPTXNfYXRvYigpX2FuZF9idG9hKClfdXNpbmdfSmF2YVNjcmlwdCdzX1R5cGVkQXJyYXlzX2FuZF9VVEYtOFxuZnVuY3Rpb24gYjY0RW5jb2RlVW5pY29kZShzdHIpIHtcbiAgcmV0dXJuIGJ0b2EoZW5jb2RlVVJJQ29tcG9uZW50KHN0cikucmVwbGFjZSgvJShbMC05QS1GXXsyfSkvZywgZnVuY3Rpb24gKG1hdGNoLCBwMSkge1xuICAgIHJldHVybiBTdHJpbmcuZnJvbUNoYXJDb2RlKCcweCcgKyBwMSk7XG4gIH0pKTtcbn1cblxuZnVuY3Rpb24gZGVsZXRlX3Byb3BlcnR5X2Zyb21fbWFwKG1hcCwgcHJvcGVydHkpIHtcbiAgbGV0IG5ld19tYXAgPSBPYmplY3QuYXNzaWduKE9iamVjdC5jcmVhdGUobWFwLmNvbnN0cnVjdG9yLnByb3RvdHlwZSksIG1hcCk7XG4gIGRlbGV0ZSBuZXdfbWFwW3Byb3BlcnR5XTtcblxuICByZXR1cm4gT2JqZWN0LmZyZWV6ZShuZXdfbWFwKTtcbn1cblxuZnVuY3Rpb24gY2xhc3NfdG9fb2JqKG1hcCkge1xuICBsZXQgbmV3X21hcCA9IE9iamVjdC5hc3NpZ24oe30sIG1hcCk7XG4gIHJldHVybiBPYmplY3QuZnJlZXplKG5ld19tYXApO1xufVxuXG5mdW5jdGlvbiBhZGRfcHJvcGVydHlfdG9fbWFwKG1hcCwgcHJvcGVydHksIHZhbHVlKSB7XG4gIGxldCBuZXdfbWFwID0gT2JqZWN0LmFzc2lnbih7fSwgbWFwKTtcbiAgbmV3X21hcFtwcm9wZXJ0eV0gPSB2YWx1ZTtcbiAgcmV0dXJuIE9iamVjdC5mcmVlemUobmV3X21hcCk7XG59XG5cbmZ1bmN0aW9uIGJub3QoZXhwcikge1xuICByZXR1cm4gfmV4cHI7XG59XG5cbmZ1bmN0aW9uIGJhbmQobGVmdCwgcmlnaHQpIHtcbiAgcmV0dXJuIGxlZnQgJiByaWdodDtcbn1cblxuZnVuY3Rpb24gYm9yKGxlZnQsIHJpZ2h0KSB7XG4gIHJldHVybiBsZWZ0IHwgcmlnaHQ7XG59XG5cbmZ1bmN0aW9uIGJzbChsZWZ0LCByaWdodCkge1xuICByZXR1cm4gbGVmdCA8PCByaWdodDtcbn1cblxuZnVuY3Rpb24gYnNyKGxlZnQsIHJpZ2h0KSB7XG4gIHJldHVybiBsZWZ0ID4+IHJpZ2h0O1xufVxuXG5mdW5jdGlvbiBieG9yKGxlZnQsIHJpZ2h0KSB7XG4gIHJldHVybiBsZWZ0IF4gcmlnaHQ7XG59XG5cbmZ1bmN0aW9uIHppcChsaXN0X29mX2xpc3RzKSB7XG4gIGlmIChsaXN0X29mX2xpc3RzLmxlbmd0aCA9PT0gMCkge1xuICAgIHJldHVybiBPYmplY3QuZnJlZXplKFtdKTtcbiAgfVxuXG4gIGxldCBuZXdfdmFsdWUgPSBbXTtcbiAgbGV0IHNtYWxsZXN0X2xlbmd0aCA9IGxpc3Rfb2ZfbGlzdHNbMF07XG5cbiAgZm9yIChsZXQgeCBvZiBsaXN0X29mX2xpc3RzKSB7XG4gICAgaWYgKHgubGVuZ3RoIDwgc21hbGxlc3RfbGVuZ3RoKSB7XG4gICAgICBzbWFsbGVzdF9sZW5ndGggPSB4Lmxlbmd0aDtcbiAgICB9XG4gIH1cblxuICBmb3IgKGxldCBpID0gMDsgaSA8IHNtYWxsZXN0X2xlbmd0aDsgaSsrKSB7XG4gICAgbGV0IGN1cnJlbnRfdmFsdWUgPSBbXTtcbiAgICBmb3IgKGxldCBqID0gMDsgaiA8IGxpc3Rfb2ZfbGlzdHMubGVuZ3RoOyBqKyspIHtcbiAgICAgIGN1cnJlbnRfdmFsdWUucHVzaChsaXN0X29mX2xpc3RzW2pdW2ldKTtcbiAgICB9XG5cbiAgICBuZXdfdmFsdWUucHVzaChuZXcgVHVwbGUoLi4uY3VycmVudF92YWx1ZSkpO1xuICB9XG5cbiAgcmV0dXJuIE9iamVjdC5mcmVlemUobmV3X3ZhbHVlKTtcbn1cblxuZnVuY3Rpb24gY2FuX2RlY29kZTY0KGRhdGEpIHtcbiAgdHJ5IHtcbiAgICBhdG9iKGRhdGEpO1xuICAgIHJldHVybiB0cnVlO1xuICB9IGNhdGNoIChlKSB7XG4gICAgcmV0dXJuIGZhbHNlO1xuICB9XG59XG5cbnZhciBGdW5jdGlvbnMgPSB7XG4gIGNhbGxfcHJvcGVydHksXG4gIGFwcGx5LFxuICBjb250YWlucyxcbiAgZ2V0X2dsb2JhbCxcbiAgZGVmc3RydWN0LFxuICBkZWZleGNlcHRpb24sXG4gIGRlZnByb3RvY29sLFxuICBkZWZpbXBsLFxuICBnZXRfb2JqZWN0X2tleXMsXG4gIGlzX3ZhbGlkX2NoYXJhY3RlcixcbiAgYjY0RW5jb2RlVW5pY29kZSxcbiAgZGVsZXRlX3Byb3BlcnR5X2Zyb21fbWFwLFxuICBhZGRfcHJvcGVydHlfdG9fbWFwLFxuICBjbGFzc190b19vYmosXG4gIGNhbl9kZWNvZGU2NCxcbiAgYm5vdCxcbiAgYmFuZCxcbiAgYm9yLFxuICBic2wsXG4gIGJzcixcbiAgYnhvcixcbiAgemlwXG59O1xuXG5mdW5jdGlvbiBfY2FzZShjb25kaXRpb24sIGNsYXVzZXMpIHtcbiAgcmV0dXJuIFBhdHRlcm5zLmRlZm1hdGNoKC4uLmNsYXVzZXMpKGNvbmRpdGlvbik7XG59XG5cbmZ1bmN0aW9uIGNvbmQoY2xhdXNlcykge1xuICBmb3IgKGxldCBjbGF1c2Ugb2YgY2xhdXNlcykge1xuICAgIGlmIChjbGF1c2VbMF0pIHtcbiAgICAgIHJldHVybiBjbGF1c2VbMV0oKTtcbiAgICB9XG4gIH1cblxuICB0aHJvdyBuZXcgRXJyb3IoKTtcbn1cblxuZnVuY3Rpb24gbWFwX3VwZGF0ZShtYXAsIHZhbHVlcykge1xuICByZXR1cm4gT2JqZWN0LmZyZWV6ZShPYmplY3QuYXNzaWduKE9iamVjdC5jcmVhdGUobWFwLmNvbnN0cnVjdG9yLnByb3RvdHlwZSksIG1hcCwgdmFsdWVzKSk7XG59XG5cbmZ1bmN0aW9uIF9mb3IoY29sbGVjdGlvbnMsIGZ1biwgZmlsdGVyID0gKCkgPT4gdHJ1ZSwgaW50byA9IFtdLCBwcmV2aW91c1ZhbHVlcyA9IFtdKSB7XG4gIGxldCBwYXR0ZXJuID0gY29sbGVjdGlvbnNbMF1bMF07XG4gIGxldCBjb2xsZWN0aW9uID0gY29sbGVjdGlvbnNbMF1bMV07XG5cbiAgaWYgKGNvbGxlY3Rpb25zLmxlbmd0aCA9PT0gMSkge1xuXG4gICAgZm9yIChsZXQgZWxlbSBvZiBjb2xsZWN0aW9uKSB7XG4gICAgICBsZXQgciA9IFBhdHRlcm5zLm1hdGNoX25vX3Rocm93KHBhdHRlcm4sIGVsZW0pO1xuICAgICAgbGV0IGFyZ3MgPSBwcmV2aW91c1ZhbHVlcy5jb25jYXQocik7XG5cbiAgICAgIGlmIChyICYmIGZpbHRlci5hcHBseSh0aGlzLCBhcmdzKSkge1xuICAgICAgICBpbnRvID0gaW50by5jb25jYXQoW2Z1bi5hcHBseSh0aGlzLCBhcmdzKV0pO1xuICAgICAgfVxuICAgIH1cblxuICAgIHJldHVybiBpbnRvO1xuICB9IGVsc2Uge1xuICAgIGxldCBfaW50byA9IFtdO1xuXG4gICAgZm9yIChsZXQgZWxlbSBvZiBjb2xsZWN0aW9uKSB7XG4gICAgICBsZXQgciA9IFBhdHRlcm5zLm1hdGNoX25vX3Rocm93KHBhdHRlcm4sIGVsZW0pO1xuICAgICAgaWYgKHIpIHtcbiAgICAgICAgX2ludG8gPSBpbnRvLmNvbmNhdCh0aGlzLl9mb3IoY29sbGVjdGlvbnMuc2xpY2UoMSksIGZ1biwgZmlsdGVyLCBfaW50bywgcHJldmlvdXNWYWx1ZXMuY29uY2F0KHIpKSk7XG4gICAgICB9XG4gICAgfVxuXG4gICAgcmV0dXJuIF9pbnRvO1xuICB9XG59XG5cbmZ1bmN0aW9uIF90cnkoZG9fZnVuLCByZXNjdWVfZnVuY3Rpb24sIGNhdGNoX2Z1biwgZWxzZV9mdW5jdGlvbiwgYWZ0ZXJfZnVuY3Rpb24pIHtcbiAgbGV0IHJlc3VsdCA9IG51bGw7XG5cbiAgdHJ5IHtcbiAgICByZXN1bHQgPSBkb19mdW4oKTtcbiAgfSBjYXRjaCAoZSkge1xuICAgIGxldCBleF9yZXN1bHQgPSBudWxsO1xuXG4gICAgaWYgKHJlc2N1ZV9mdW5jdGlvbikge1xuICAgICAgdHJ5IHtcbiAgICAgICAgZXhfcmVzdWx0ID0gcmVzY3VlX2Z1bmN0aW9uKGUpO1xuICAgICAgICByZXR1cm4gZXhfcmVzdWx0O1xuICAgICAgfSBjYXRjaCAoZXgpIHtcbiAgICAgICAgaWYgKGV4IGluc3RhbmNlb2YgUGF0dGVybnMuTWF0Y2hFcnJvcikge1xuICAgICAgICAgIHRocm93IGV4O1xuICAgICAgICB9XG4gICAgICB9XG4gICAgfVxuXG4gICAgaWYgKGNhdGNoX2Z1bikge1xuICAgICAgdHJ5IHtcbiAgICAgICAgZXhfcmVzdWx0ID0gY2F0Y2hfZnVuKGUpO1xuICAgICAgICByZXR1cm4gZXhfcmVzdWx0O1xuICAgICAgfSBjYXRjaCAoZXgpIHtcbiAgICAgICAgaWYgKGV4IGluc3RhbmNlb2YgUGF0dGVybnMuTWF0Y2hFcnJvcikge1xuICAgICAgICAgIHRocm93IGV4O1xuICAgICAgICB9XG4gICAgICB9XG4gICAgfVxuXG4gICAgdGhyb3cgZTtcbiAgfSBmaW5hbGx5IHtcbiAgICBpZiAoYWZ0ZXJfZnVuY3Rpb24pIHtcbiAgICAgIGFmdGVyX2Z1bmN0aW9uKCk7XG4gICAgfVxuICB9XG5cbiAgaWYgKGVsc2VfZnVuY3Rpb24pIHtcbiAgICB0cnkge1xuICAgICAgcmV0dXJuIGVsc2VfZnVuY3Rpb24ocmVzdWx0KTtcbiAgICB9IGNhdGNoIChleCkge1xuICAgICAgaWYgKGV4IGluc3RhbmNlb2YgUGF0dGVybnMuTWF0Y2hFcnJvcikge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ05vIE1hdGNoIEZvdW5kIGluIEVsc2UnKTtcbiAgICAgIH1cblxuICAgICAgdGhyb3cgZXg7XG4gICAgfVxuICB9IGVsc2Uge1xuICAgIHJldHVybiByZXN1bHQ7XG4gIH1cbn1cblxudmFyIHNwZWNpYWxfZm9ybXMgPSB7XG4gIF9jYXNlLFxuICBjb25kLFxuICBtYXBfdXBkYXRlLFxuICBfZm9yLFxuICBfdHJ5XG59O1xuXG5GdW5jdGlvbnMuZ2V0X2dsb2JhbCgpLnByb2Nlc3NlcyA9IEZ1bmN0aW9ucy5nZXRfZ2xvYmFsKCkucHJvY2Vzc2VzIHx8IG5ldyBQcm9jZXNzU3lzdGVtKCk7XG5cblxuXG52YXIgQyA9IE9iamVjdC5mcmVlemUoe1xuXHRQcm9jZXNzU3lzdGVtOiBQcm9jZXNzU3lzdGVtLFxuXHRUdXBsZTogVHVwbGUsXG5cdFBJRDogUElELFxuXHRCaXRTdHJpbmc6IEJpdFN0cmluZyxcblx0UGF0dGVybnM6IFBhdHRlcm5zLFxuXHRJbnRlZ2VyOiBJbnRlZ2VyLFxuXHRGbG9hdDogRmxvYXQsXG5cdEZ1bmN0aW9uczogRnVuY3Rpb25zLFxuXHRTcGVjaWFsRm9ybXM6IHNwZWNpYWxfZm9ybXNcbn0pO1xuXG5sZXQgRW51bSA9IHtcblxuICBhbGxfX3FtYXJrX186IGZ1bmN0aW9uIChjb2xsZWN0aW9uLCBmdW4gPSB4ID0+IHgpIHtcbiAgICBmb3IgKGxldCBlbGVtIG9mIGNvbGxlY3Rpb24pIHtcbiAgICAgIGlmICghZnVuKGVsZW0pKSB7XG4gICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICByZXR1cm4gdHJ1ZTtcbiAgfSxcblxuICBhbnlfX3FtYXJrX186IGZ1bmN0aW9uIChjb2xsZWN0aW9uLCBmdW4gPSB4ID0+IHgpIHtcbiAgICBmb3IgKGxldCBlbGVtIG9mIGNvbGxlY3Rpb24pIHtcbiAgICAgIGlmIChmdW4oZWxlbSkpIHtcbiAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICB9XG4gICAgfVxuXG4gICAgcmV0dXJuIGZhbHNlO1xuICB9LFxuXG4gIGF0OiBmdW5jdGlvbiAoY29sbGVjdGlvbiwgbiwgdGhlX2RlZmF1bHQgPSBudWxsKSB7XG4gICAgaWYgKG4gPiB0aGlzLmNvdW50KGNvbGxlY3Rpb24pIHx8IG4gPCAwKSB7XG4gICAgICByZXR1cm4gdGhlX2RlZmF1bHQ7XG4gICAgfVxuXG4gICAgcmV0dXJuIGNvbGxlY3Rpb25bbl07XG4gIH0sXG5cbiAgY29uY2F0OiBmdW5jdGlvbiAoLi4uZW51bWFibGVzKSB7XG4gICAgcmV0dXJuIGVudW1hYmxlc1swXS5jb25jYXQoZW51bWFibGVzWzFdKTtcbiAgfSxcblxuICBjb3VudDogZnVuY3Rpb24gKGNvbGxlY3Rpb24sIGZ1biA9IG51bGwpIHtcbiAgICBpZiAoZnVuID09IG51bGwpIHtcbiAgICAgIHJldHVybiBjb2xsZWN0aW9uLmxlbmd0aDtcbiAgICB9IGVsc2Uge1xuICAgICAgcmV0dXJuIGNvbGxlY3Rpb24uZmlsdGVyKGZ1bikubGVuZ3RoO1xuICAgIH1cbiAgfSxcblxuICBkcm9wOiBmdW5jdGlvbiAoY29sbGVjdGlvbiwgY291bnQpIHtcbiAgICByZXR1cm4gY29sbGVjdGlvbi5zbGljZShjb3VudCk7XG4gIH0sXG5cbiAgZHJvcF93aGlsZTogZnVuY3Rpb24gKGNvbGxlY3Rpb24sIGZ1bikge1xuICAgIGxldCBjb3VudCA9IDA7XG5cbiAgICBmb3IgKGxldCBlbGVtIG9mIGNvbGxlY3Rpb24pIHtcbiAgICAgIGlmIChmdW4oZWxlbSkpIHtcbiAgICAgICAgY291bnQgPSBjb3VudCArIDE7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBicmVhaztcbiAgICAgIH1cbiAgICB9XG5cbiAgICByZXR1cm4gY29sbGVjdGlvbi5zbGljZShjb3VudCk7XG4gIH0sXG5cbiAgZWFjaDogZnVuY3Rpb24gKGNvbGxlY3Rpb24sIGZ1bikge1xuICAgIGZvciAobGV0IGVsZW0gb2YgY29sbGVjdGlvbikge1xuICAgICAgZnVuKGVsZW0pO1xuICAgIH1cbiAgfSxcblxuICBlbXB0eV9fcW1hcmtfXzogZnVuY3Rpb24gKGNvbGxlY3Rpb24pIHtcbiAgICByZXR1cm4gY29sbGVjdGlvbi5sZW5ndGggPT09IDA7XG4gIH0sXG5cbiAgZmV0Y2g6IGZ1bmN0aW9uIChjb2xsZWN0aW9uLCBuKSB7XG4gICAgaWYgKEFycmF5LmlzQXJyYXkoY29sbGVjdGlvbikpIHtcbiAgICAgIGlmIChuIDwgdGhpcy5jb3VudChjb2xsZWN0aW9uKSAmJiBuID49IDApIHtcbiAgICAgICAgcmV0dXJuIG5ldyBUdXBsZShTeW1ib2wuZm9yKFwib2tcIiksIGNvbGxlY3Rpb25bbl0pO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgcmV0dXJuIFN5bWJvbC5mb3IoXCJlcnJvclwiKTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICB0aHJvdyBuZXcgRXJyb3IoXCJjb2xsZWN0aW9uIGlzIG5vdCBhbiBFbnVtZXJhYmxlXCIpO1xuICB9LFxuXG4gIGZldGNoX19lbWFya19fOiBmdW5jdGlvbiAoY29sbGVjdGlvbiwgbikge1xuICAgIGlmIChBcnJheS5pc0FycmF5KGNvbGxlY3Rpb24pKSB7XG4gICAgICBpZiAobiA8IHRoaXMuY291bnQoY29sbGVjdGlvbikgJiYgbiA+PSAwKSB7XG4gICAgICAgIHJldHVybiBjb2xsZWN0aW9uW25dO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKFwib3V0IG9mIGJvdW5kcyBlcnJvclwiKTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICB0aHJvdyBuZXcgRXJyb3IoXCJjb2xsZWN0aW9uIGlzIG5vdCBhbiBFbnVtZXJhYmxlXCIpO1xuICB9LFxuXG4gIGZpbHRlcjogZnVuY3Rpb24gKGNvbGxlY3Rpb24sIGZ1bikge1xuICAgIGxldCByZXN1bHQgPSBbXTtcblxuICAgIGZvciAobGV0IGVsZW0gb2YgY29sbGVjdGlvbikge1xuICAgICAgaWYgKGZ1bihlbGVtKSkge1xuICAgICAgICByZXN1bHQucHVzaChlbGVtKTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICByZXR1cm4gcmVzdWx0O1xuICB9LFxuXG4gIGZpbHRlcl9tYXA6IGZ1bmN0aW9uIChjb2xsZWN0aW9uLCBmaWx0ZXIsIG1hcHBlcikge1xuICAgIHJldHVybiBFbnVtLm1hcChFbnVtLmZpbHRlcihjb2xsZWN0aW9uLCBmaWx0ZXIpLCBtYXBwZXIpO1xuICB9LFxuXG4gIGZpbmQ6IGZ1bmN0aW9uIChjb2xsZWN0aW9uLCBpZl9ub25lID0gbnVsbCwgZnVuKSB7XG4gICAgZm9yIChsZXQgZWxlbSBvZiBjb2xsZWN0aW9uKSB7XG4gICAgICBpZiAoZnVuKGVsZW0pKSB7XG4gICAgICAgIHJldHVybiBlbGVtO1xuICAgICAgfVxuICAgIH1cblxuICAgIHJldHVybiBpZl9ub25lO1xuICB9LFxuXG4gIGludG86IGZ1bmN0aW9uIChjb2xsZWN0aW9uLCBsaXN0KSB7XG4gICAgcmV0dXJuIGxpc3QuY29uY2F0KGNvbGxlY3Rpb24pO1xuICB9LFxuXG4gIG1hcDogZnVuY3Rpb24gKGNvbGxlY3Rpb24sIGZ1bikge1xuICAgIGxldCByZXN1bHQgPSBbXTtcblxuICAgIGZvciAobGV0IGVsZW0gb2YgY29sbGVjdGlvbikge1xuICAgICAgcmVzdWx0LnB1c2goZnVuKGVsZW0pKTtcbiAgICB9XG5cbiAgICByZXR1cm4gcmVzdWx0O1xuICB9LFxuXG4gIG1hcF9yZWR1Y2U6IGZ1bmN0aW9uIChjb2xsZWN0aW9uLCBhY2MsIGZ1bikge1xuICAgIGxldCBtYXBwZWQgPSBPYmplY3QuZnJlZXplKFtdKTtcbiAgICBsZXQgdGhlX2FjYyA9IGFjYztcblxuICAgIGZvciAodmFyIGkgPSAwOyBpIDwgdGhpcy5jb3VudChjb2xsZWN0aW9uKTsgaSsrKSB7XG4gICAgICBsZXQgdHVwbGUgPSBmdW4oY29sbGVjdGlvbltpXSwgdGhlX2FjYyk7XG5cbiAgICAgIHRoZV9hY2MgPSB0dXBsZS5nZXQoMSk7XG4gICAgICBtYXBwZWQgPSBPYmplY3QuZnJlZXplKG1hcHBlZC5jb25jYXQoW3R1cGxlLmdldCgwKV0pKTtcbiAgICB9XG5cbiAgICByZXR1cm4gbmV3IFR1cGxlKG1hcHBlZCwgdGhlX2FjYyk7XG4gIH0sXG5cbiAgbWVtYmVyX19xbWFya19fOiBmdW5jdGlvbiAoY29sbGVjdGlvbiwgdmFsdWUpIHtcbiAgICByZXR1cm4gY29sbGVjdGlvbi5pbmNsdWRlcyh2YWx1ZSk7XG4gIH0sXG5cbiAgcmVkdWNlOiBmdW5jdGlvbiAoY29sbGVjdGlvbiwgYWNjLCBmdW4pIHtcbiAgICBsZXQgdGhlX2FjYyA9IGFjYztcblxuICAgIGZvciAodmFyIGkgPSAwOyBpIDwgdGhpcy5jb3VudChjb2xsZWN0aW9uKTsgaSsrKSB7XG4gICAgICBsZXQgdHVwbGUgPSBmdW4oY29sbGVjdGlvbltpXSwgdGhlX2FjYyk7XG5cbiAgICAgIHRoZV9hY2MgPSB0dXBsZS5nZXQoMSk7XG4gICAgfVxuXG4gICAgcmV0dXJuIHRoZV9hY2M7XG4gIH0sXG5cbiAgdGFrZTogZnVuY3Rpb24gKGNvbGxlY3Rpb24sIGNvdW50KSB7XG4gICAgcmV0dXJuIGNvbGxlY3Rpb24uc2xpY2UoMCwgY291bnQpO1xuICB9LFxuXG4gIHRha2VfZXZlcnk6IGZ1bmN0aW9uIChjb2xsZWN0aW9uLCBudGgpIHtcbiAgICBsZXQgcmVzdWx0ID0gW107XG4gICAgbGV0IGluZGV4ID0gMDtcblxuICAgIGZvciAobGV0IGVsZW0gb2YgY29sbGVjdGlvbikge1xuICAgICAgaWYgKGluZGV4ICUgbnRoID09PSAwKSB7XG4gICAgICAgIHJlc3VsdC5wdXNoKGVsZW0pO1xuICAgICAgfVxuICAgIH1cblxuICAgIHJldHVybiBPYmplY3QuZnJlZXplKHJlc3VsdCk7XG4gIH0sXG5cbiAgdGFrZV93aGlsZTogZnVuY3Rpb24gKGNvbGxlY3Rpb24sIGZ1bikge1xuICAgIGxldCBjb3VudCA9IDA7XG5cbiAgICBmb3IgKGxldCBlbGVtIG9mIGNvbGxlY3Rpb24pIHtcbiAgICAgIGlmIChmdW4oZWxlbSkpIHtcbiAgICAgICAgY291bnQgPSBjb3VudCArIDE7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBicmVhaztcbiAgICAgIH1cbiAgICB9XG5cbiAgICByZXR1cm4gY29sbGVjdGlvbi5zbGljZSgwLCBjb3VudCk7XG4gIH0sXG5cbiAgdG9fbGlzdDogZnVuY3Rpb24gKGNvbGxlY3Rpb24pIHtcbiAgICByZXR1cm4gY29sbGVjdGlvbjtcbiAgfVxufTtcblxubGV0IFZpcnR1YWxET00gPSAoZnVuY3Rpb24gKGUpIHtcbiAgICByZXR1cm4gZSgpO1xufSkoZnVuY3Rpb24gKCkge1xuICAgIHZhciBkZWZpbmUsIG1vZHVsZSwgZXhwb3J0cztcbiAgICByZXR1cm4gKGZ1bmN0aW9uIGUodCwgbiwgcikge1xuICAgICAgICBmdW5jdGlvbiBzKG8sIHUpIHtcbiAgICAgICAgICAgIGlmICghbltvXSkge1xuICAgICAgICAgICAgICAgIGlmICghdFtvXSkge1xuICAgICAgICAgICAgICAgICAgICB2YXIgYSA9IHR5cGVvZiByZXF1aXJlID09IFwiZnVuY3Rpb25cIiAmJiByZXF1aXJlO1xuICAgICAgICAgICAgICAgICAgICBpZiAoIXUgJiYgYSkgcmV0dXJuIGEobywgITApO1xuICAgICAgICAgICAgICAgICAgICBpZiAoaSkgcmV0dXJuIGkobywgITApO1xuICAgICAgICAgICAgICAgICAgICB2YXIgZiA9IG5ldyBFcnJvcihcIkNhbm5vdCBmaW5kIG1vZHVsZSAnXCIgKyBvICsgXCInXCIpO1xuICAgICAgICAgICAgICAgICAgICB0aHJvdyAoZi5jb2RlID0gXCJNT0RVTEVfTk9UX0ZPVU5EXCIsIGYpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB2YXIgbCA9IG5bb10gPSB7XG4gICAgICAgICAgICAgICAgICAgIGV4cG9ydHM6IHt9XG4gICAgICAgICAgICAgICAgfTtcbiAgICAgICAgICAgICAgICB0W29dWzBdLmNhbGwobC5leHBvcnRzLCBmdW5jdGlvbiAoZSkge1xuICAgICAgICAgICAgICAgICAgICB2YXIgbiA9IHRbb11bMV1bZV07XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBzKG4gPyBuIDogZSk7XG4gICAgICAgICAgICAgICAgfSwgbCwgbC5leHBvcnRzLCBlLCB0LCBuLCByKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJldHVybiBuW29dLmV4cG9ydHM7XG4gICAgICAgIH1cbiAgICAgICAgdmFyIGkgPSB0eXBlb2YgcmVxdWlyZSA9PSBcImZ1bmN0aW9uXCIgJiYgcmVxdWlyZTtcbiAgICAgICAgZm9yICh2YXIgbyA9IDA7IG8gPCByLmxlbmd0aDsgbysrKSBzKHJbb10pO1xuICAgICAgICByZXR1cm4gcztcbiAgICB9KSh7XG4gICAgICAgIDE6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG5cbiAgICAgICAgICAgIHZhciBjcmVhdGVFbGVtZW50ID0gcmVxdWlyZShcIi4vdmRvbS9jcmVhdGUtZWxlbWVudC5qc1wiKTtcblxuICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBjcmVhdGVFbGVtZW50O1xuICAgICAgICB9LCB7IFwiLi92ZG9tL2NyZWF0ZS1lbGVtZW50LmpzXCI6IDE1IH1dLCAyOiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge1xuICAgICAgICAgICAgdmFyIGRpZmYgPSByZXF1aXJlKFwiLi92dHJlZS9kaWZmLmpzXCIpO1xuXG4gICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IGRpZmY7XG4gICAgICAgIH0sIHsgXCIuL3Z0cmVlL2RpZmYuanNcIjogMzUgfV0sIDM6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICB2YXIgaCA9IHJlcXVpcmUoXCIuL3ZpcnR1YWwtaHlwZXJzY3JpcHQvaW5kZXguanNcIik7XG5cbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gaDtcbiAgICAgICAgfSwgeyBcIi4vdmlydHVhbC1oeXBlcnNjcmlwdC9pbmRleC5qc1wiOiAyMiB9XSwgNDogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHtcbiAgICAgICAgICAgIHZhciBkaWZmID0gcmVxdWlyZShcIi4vZGlmZi5qc1wiKTtcbiAgICAgICAgICAgIHZhciBwYXRjaCA9IHJlcXVpcmUoXCIuL3BhdGNoLmpzXCIpO1xuICAgICAgICAgICAgdmFyIGggPSByZXF1aXJlKFwiLi9oLmpzXCIpO1xuICAgICAgICAgICAgdmFyIGNyZWF0ZSA9IHJlcXVpcmUoXCIuL2NyZWF0ZS1lbGVtZW50LmpzXCIpO1xuICAgICAgICAgICAgdmFyIFZOb2RlID0gcmVxdWlyZShcIi4vdm5vZGUvdm5vZGUuanNcIik7XG4gICAgICAgICAgICB2YXIgVlRleHQgPSByZXF1aXJlKFwiLi92bm9kZS92dGV4dC5qc1wiKTtcblxuICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSB7XG4gICAgICAgICAgICAgICAgZGlmZjogZGlmZixcbiAgICAgICAgICAgICAgICBwYXRjaDogcGF0Y2gsXG4gICAgICAgICAgICAgICAgaDogaCxcbiAgICAgICAgICAgICAgICBjcmVhdGU6IGNyZWF0ZSxcbiAgICAgICAgICAgICAgICBWTm9kZTogVk5vZGUsXG4gICAgICAgICAgICAgICAgVlRleHQ6IFZUZXh0XG4gICAgICAgICAgICB9O1xuICAgICAgICB9LCB7IFwiLi9jcmVhdGUtZWxlbWVudC5qc1wiOiAxLCBcIi4vZGlmZi5qc1wiOiAyLCBcIi4vaC5qc1wiOiAzLCBcIi4vcGF0Y2guanNcIjogMTMsIFwiLi92bm9kZS92bm9kZS5qc1wiOiAzMSwgXCIuL3Zub2RlL3Z0ZXh0LmpzXCI6IDMzIH1dLCA1OiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge1xuICAgICAgICAgICAgLyohXG4gICAgICAgICAgICAgKiBDcm9zcy1Ccm93c2VyIFNwbGl0IDEuMS4xXG4gICAgICAgICAgICAgKiBDb3B5cmlnaHQgMjAwNy0yMDEyIFN0ZXZlbiBMZXZpdGhhbiA8c3RldmVubGV2aXRoYW4uY29tPlxuICAgICAgICAgICAgICogQXZhaWxhYmxlIHVuZGVyIHRoZSBNSVQgTGljZW5zZVxuICAgICAgICAgICAgICogRUNNQVNjcmlwdCBjb21wbGlhbnQsIHVuaWZvcm0gY3Jvc3MtYnJvd3NlciBzcGxpdCBtZXRob2RcbiAgICAgICAgICAgICAqL1xuXG4gICAgICAgICAgICAvKipcbiAgICAgICAgICAgICAqIFNwbGl0cyBhIHN0cmluZyBpbnRvIGFuIGFycmF5IG9mIHN0cmluZ3MgdXNpbmcgYSByZWdleCBvciBzdHJpbmcgc2VwYXJhdG9yLiBNYXRjaGVzIG9mIHRoZVxuICAgICAgICAgICAgICogc2VwYXJhdG9yIGFyZSBub3QgaW5jbHVkZWQgaW4gdGhlIHJlc3VsdCBhcnJheS4gSG93ZXZlciwgaWYgYHNlcGFyYXRvcmAgaXMgYSByZWdleCB0aGF0IGNvbnRhaW5zXG4gICAgICAgICAgICAgKiBjYXB0dXJpbmcgZ3JvdXBzLCBiYWNrcmVmZXJlbmNlcyBhcmUgc3BsaWNlZCBpbnRvIHRoZSByZXN1bHQgZWFjaCB0aW1lIGBzZXBhcmF0b3JgIGlzIG1hdGNoZWQuXG4gICAgICAgICAgICAgKiBGaXhlcyBicm93c2VyIGJ1Z3MgY29tcGFyZWQgdG8gdGhlIG5hdGl2ZSBgU3RyaW5nLnByb3RvdHlwZS5zcGxpdGAgYW5kIGNhbiBiZSB1c2VkIHJlbGlhYmx5XG4gICAgICAgICAgICAgKiBjcm9zcy1icm93c2VyLlxuICAgICAgICAgICAgICogQHBhcmFtIHtTdHJpbmd9IHN0ciBTdHJpbmcgdG8gc3BsaXQuXG4gICAgICAgICAgICAgKiBAcGFyYW0ge1JlZ0V4cHxTdHJpbmd9IHNlcGFyYXRvciBSZWdleCBvciBzdHJpbmcgdG8gdXNlIGZvciBzZXBhcmF0aW5nIHRoZSBzdHJpbmcuXG4gICAgICAgICAgICAgKiBAcGFyYW0ge051bWJlcn0gW2xpbWl0XSBNYXhpbXVtIG51bWJlciBvZiBpdGVtcyB0byBpbmNsdWRlIGluIHRoZSByZXN1bHQgYXJyYXkuXG4gICAgICAgICAgICAgKiBAcmV0dXJucyB7QXJyYXl9IEFycmF5IG9mIHN1YnN0cmluZ3MuXG4gICAgICAgICAgICAgKiBAZXhhbXBsZVxuICAgICAgICAgICAgICpcbiAgICAgICAgICAgICAqIC8vIEJhc2ljIHVzZVxuICAgICAgICAgICAgICogc3BsaXQoJ2EgYiBjIGQnLCAnICcpO1xuICAgICAgICAgICAgICogLy8gLT4gWydhJywgJ2InLCAnYycsICdkJ11cbiAgICAgICAgICAgICAqXG4gICAgICAgICAgICAgKiAvLyBXaXRoIGxpbWl0XG4gICAgICAgICAgICAgKiBzcGxpdCgnYSBiIGMgZCcsICcgJywgMik7XG4gICAgICAgICAgICAgKiAvLyAtPiBbJ2EnLCAnYiddXG4gICAgICAgICAgICAgKlxuICAgICAgICAgICAgICogLy8gQmFja3JlZmVyZW5jZXMgaW4gcmVzdWx0IGFycmF5XG4gICAgICAgICAgICAgKiBzcGxpdCgnLi53b3JkMSB3b3JkMi4uJywgLyhbYS16XSspKFxcZCspL2kpO1xuICAgICAgICAgICAgICogLy8gLT4gWycuLicsICd3b3JkJywgJzEnLCAnICcsICd3b3JkJywgJzInLCAnLi4nXVxuICAgICAgICAgICAgICovXG4gICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IChmdW5jdGlvbiBzcGxpdCh1bmRlZikge1xuXG4gICAgICAgICAgICAgICAgdmFyIG5hdGl2ZVNwbGl0ID0gU3RyaW5nLnByb3RvdHlwZS5zcGxpdCxcbiAgICAgICAgICAgICAgICAgICAgY29tcGxpYW50RXhlY05wY2cgPSAvKCk/Py8uZXhlYyhcIlwiKVsxXSA9PT0gdW5kZWYsXG5cbiAgICAgICAgICAgICAgICAvLyBOUENHOiBub25wYXJ0aWNpcGF0aW5nIGNhcHR1cmluZyBncm91cFxuICAgICAgICAgICAgICAgIHNlbGY7XG5cbiAgICAgICAgICAgICAgICBzZWxmID0gZnVuY3Rpb24gKHN0ciwgc2VwYXJhdG9yLCBsaW1pdCkge1xuICAgICAgICAgICAgICAgICAgICAvLyBJZiBgc2VwYXJhdG9yYCBpcyBub3QgYSByZWdleCwgdXNlIGBuYXRpdmVTcGxpdGBcbiAgICAgICAgICAgICAgICAgICAgaWYgKE9iamVjdC5wcm90b3R5cGUudG9TdHJpbmcuY2FsbChzZXBhcmF0b3IpICE9PSBcIltvYmplY3QgUmVnRXhwXVwiKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gbmF0aXZlU3BsaXQuY2FsbChzdHIsIHNlcGFyYXRvciwgbGltaXQpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIHZhciBvdXRwdXQgPSBbXSxcbiAgICAgICAgICAgICAgICAgICAgICAgIGZsYWdzID0gKHNlcGFyYXRvci5pZ25vcmVDYXNlID8gXCJpXCIgOiBcIlwiKSArIChzZXBhcmF0b3IubXVsdGlsaW5lID8gXCJtXCIgOiBcIlwiKSArIChzZXBhcmF0b3IuZXh0ZW5kZWQgPyBcInhcIiA6IFwiXCIpICsgKHNlcGFyYXRvci5zdGlja3kgPyBcInlcIiA6IFwiXCIpLFxuXG4gICAgICAgICAgICAgICAgICAgIC8vIEZpcmVmb3ggMytcbiAgICAgICAgICAgICAgICAgICAgbGFzdExhc3RJbmRleCA9IDAsXG5cbiAgICAgICAgICAgICAgICAgICAgLy8gTWFrZSBgZ2xvYmFsYCBhbmQgYXZvaWQgYGxhc3RJbmRleGAgaXNzdWVzIGJ5IHdvcmtpbmcgd2l0aCBhIGNvcHlcbiAgICAgICAgICAgICAgICAgICAgc2VwYXJhdG9yID0gbmV3IFJlZ0V4cChzZXBhcmF0b3Iuc291cmNlLCBmbGFncyArIFwiZ1wiKSxcbiAgICAgICAgICAgICAgICAgICAgICAgIHNlcGFyYXRvcjIsXG4gICAgICAgICAgICAgICAgICAgICAgICBtYXRjaCxcbiAgICAgICAgICAgICAgICAgICAgICAgIGxhc3RJbmRleCxcbiAgICAgICAgICAgICAgICAgICAgICAgIGxhc3RMZW5ndGg7XG4gICAgICAgICAgICAgICAgICAgIHN0ciArPSBcIlwiOyAvLyBUeXBlLWNvbnZlcnRcbiAgICAgICAgICAgICAgICAgICAgaWYgKCFjb21wbGlhbnRFeGVjTnBjZykge1xuICAgICAgICAgICAgICAgICAgICAgICAgLy8gRG9lc24ndCBuZWVkIGZsYWdzIGd5LCBidXQgdGhleSBkb24ndCBodXJ0XG4gICAgICAgICAgICAgICAgICAgICAgICBzZXBhcmF0b3IyID0gbmV3IFJlZ0V4cChcIl5cIiArIHNlcGFyYXRvci5zb3VyY2UgKyBcIiQoPyFcXFxccylcIiwgZmxhZ3MpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIC8qIFZhbHVlcyBmb3IgYGxpbWl0YCwgcGVyIHRoZSBzcGVjOlxuICAgICAgICAgICAgICAgICAgICAgKiBJZiB1bmRlZmluZWQ6IDQyOTQ5NjcyOTUgLy8gTWF0aC5wb3coMiwgMzIpIC0gMVxuICAgICAgICAgICAgICAgICAgICAgKiBJZiAwLCBJbmZpbml0eSwgb3IgTmFOOiAwXG4gICAgICAgICAgICAgICAgICAgICAqIElmIHBvc2l0aXZlIG51bWJlcjogbGltaXQgPSBNYXRoLmZsb29yKGxpbWl0KTsgaWYgKGxpbWl0ID4gNDI5NDk2NzI5NSkgbGltaXQgLT0gNDI5NDk2NzI5NjtcbiAgICAgICAgICAgICAgICAgICAgICogSWYgbmVnYXRpdmUgbnVtYmVyOiA0Mjk0OTY3Mjk2IC0gTWF0aC5mbG9vcihNYXRoLmFicyhsaW1pdCkpXG4gICAgICAgICAgICAgICAgICAgICAqIElmIG90aGVyOiBUeXBlLWNvbnZlcnQsIHRoZW4gdXNlIHRoZSBhYm92ZSBydWxlc1xuICAgICAgICAgICAgICAgICAgICAgKi9cbiAgICAgICAgICAgICAgICAgICAgbGltaXQgPSBsaW1pdCA9PT0gdW5kZWYgPyAtMSA+Pj4gMCA6IC8vIE1hdGgucG93KDIsIDMyKSAtIDFcbiAgICAgICAgICAgICAgICAgICAgbGltaXQgPj4+IDA7IC8vIFRvVWludDMyKGxpbWl0KVxuICAgICAgICAgICAgICAgICAgICB3aGlsZSAobWF0Y2ggPSBzZXBhcmF0b3IuZXhlYyhzdHIpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAvLyBgc2VwYXJhdG9yLmxhc3RJbmRleGAgaXMgbm90IHJlbGlhYmxlIGNyb3NzLWJyb3dzZXJcbiAgICAgICAgICAgICAgICAgICAgICAgIGxhc3RJbmRleCA9IG1hdGNoLmluZGV4ICsgbWF0Y2hbMF0ubGVuZ3RoO1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGxhc3RJbmRleCA+IGxhc3RMYXN0SW5kZXgpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBvdXRwdXQucHVzaChzdHIuc2xpY2UobGFzdExhc3RJbmRleCwgbWF0Y2guaW5kZXgpKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBGaXggYnJvd3NlcnMgd2hvc2UgYGV4ZWNgIG1ldGhvZHMgZG9uJ3QgY29uc2lzdGVudGx5IHJldHVybiBgdW5kZWZpbmVkYCBmb3JcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBub25wYXJ0aWNpcGF0aW5nIGNhcHR1cmluZyBncm91cHNcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoIWNvbXBsaWFudEV4ZWNOcGNnICYmIG1hdGNoLmxlbmd0aCA+IDEpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbWF0Y2hbMF0ucmVwbGFjZShzZXBhcmF0b3IyLCBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBmb3IgKHZhciBpID0gMTsgaSA8IGFyZ3VtZW50cy5sZW5ndGggLSAyOyBpKyspIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoYXJndW1lbnRzW2ldID09PSB1bmRlZikge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBtYXRjaFtpXSA9IHVuZGVmO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChtYXRjaC5sZW5ndGggPiAxICYmIG1hdGNoLmluZGV4IDwgc3RyLmxlbmd0aCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBBcnJheS5wcm90b3R5cGUucHVzaC5hcHBseShvdXRwdXQsIG1hdGNoLnNsaWNlKDEpKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgbGFzdExlbmd0aCA9IG1hdGNoWzBdLmxlbmd0aDtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBsYXN0TGFzdEluZGV4ID0gbGFzdEluZGV4O1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChvdXRwdXQubGVuZ3RoID49IGxpbWl0KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChzZXBhcmF0b3IubGFzdEluZGV4ID09PSBtYXRjaC5pbmRleCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNlcGFyYXRvci5sYXN0SW5kZXgrKzsgLy8gQXZvaWQgYW4gaW5maW5pdGUgbG9vcFxuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIGlmIChsYXN0TGFzdEluZGV4ID09PSBzdHIubGVuZ3RoKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAobGFzdExlbmd0aCB8fCAhc2VwYXJhdG9yLnRlc3QoXCJcIikpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBvdXRwdXQucHVzaChcIlwiKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIG91dHB1dC5wdXNoKHN0ci5zbGljZShsYXN0TGFzdEluZGV4KSk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIG91dHB1dC5sZW5ndGggPiBsaW1pdCA/IG91dHB1dC5zbGljZSgwLCBsaW1pdCkgOiBvdXRwdXQ7XG4gICAgICAgICAgICAgICAgfTtcblxuICAgICAgICAgICAgICAgIHJldHVybiBzZWxmO1xuICAgICAgICAgICAgfSkoKTtcbiAgICAgICAgfSwge31dLCA2OiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge30sIHt9XSwgNzogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHtcbiAgICAgICAgICAgIFwidXNlIHN0cmljdFwiO1xuXG4gICAgICAgICAgICB2YXIgT25lVmVyc2lvbkNvbnN0cmFpbnQgPSByZXF1aXJlKFwiaW5kaXZpZHVhbC9vbmUtdmVyc2lvblwiKTtcblxuICAgICAgICAgICAgdmFyIE1ZX1ZFUlNJT04gPSBcIjdcIjtcbiAgICAgICAgICAgIE9uZVZlcnNpb25Db25zdHJhaW50KFwiZXYtc3RvcmVcIiwgTVlfVkVSU0lPTik7XG5cbiAgICAgICAgICAgIHZhciBoYXNoS2V5ID0gXCJfX0VWX1NUT1JFX0tFWUBcIiArIE1ZX1ZFUlNJT047XG5cbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gRXZTdG9yZTtcblxuICAgICAgICAgICAgZnVuY3Rpb24gRXZTdG9yZShlbGVtKSB7XG4gICAgICAgICAgICAgICAgdmFyIGhhc2ggPSBlbGVtW2hhc2hLZXldO1xuXG4gICAgICAgICAgICAgICAgaWYgKCFoYXNoKSB7XG4gICAgICAgICAgICAgICAgICAgIGhhc2ggPSBlbGVtW2hhc2hLZXldID0ge307XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgcmV0dXJuIGhhc2g7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0sIHsgXCJpbmRpdmlkdWFsL29uZS12ZXJzaW9uXCI6IDkgfV0sIDg6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICAoZnVuY3Rpb24gKGdsb2JhbCkge1xuICAgICAgICAgICAgICAgIFwidXNlIHN0cmljdFwiO1xuXG4gICAgICAgICAgICAgICAgLypnbG9iYWwgd2luZG93LCBnbG9iYWwqL1xuXG4gICAgICAgICAgICAgICAgdmFyIHJvb3QgPSB0eXBlb2Ygd2luZG93ICE9PSBcInVuZGVmaW5lZFwiID8gd2luZG93IDogdHlwZW9mIGdsb2JhbCAhPT0gXCJ1bmRlZmluZWRcIiA/IGdsb2JhbCA6IHt9O1xuXG4gICAgICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBJbmRpdmlkdWFsO1xuXG4gICAgICAgICAgICAgICAgZnVuY3Rpb24gSW5kaXZpZHVhbChrZXksIHZhbHVlKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmIChrZXkgaW4gcm9vdCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHJvb3Rba2V5XTtcbiAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgIHJvb3Rba2V5XSA9IHZhbHVlO1xuXG4gICAgICAgICAgICAgICAgICAgIHJldHVybiB2YWx1ZTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9KS5jYWxsKHRoaXMsIHR5cGVvZiBnbG9iYWwgIT09IFwidW5kZWZpbmVkXCIgPyBnbG9iYWwgOiB0eXBlb2Ygc2VsZiAhPT0gXCJ1bmRlZmluZWRcIiA/IHNlbGYgOiB0eXBlb2Ygd2luZG93ICE9PSBcInVuZGVmaW5lZFwiID8gd2luZG93IDoge30pO1xuICAgICAgICB9LCB7fV0sIDk6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICBcInVzZSBzdHJpY3RcIjtcblxuICAgICAgICAgICAgdmFyIEluZGl2aWR1YWwgPSByZXF1aXJlKFwiLi9pbmRleC5qc1wiKTtcblxuICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBPbmVWZXJzaW9uO1xuXG4gICAgICAgICAgICBmdW5jdGlvbiBPbmVWZXJzaW9uKG1vZHVsZU5hbWUsIHZlcnNpb24sIGRlZmF1bHRWYWx1ZSkge1xuICAgICAgICAgICAgICAgIHZhciBrZXkgPSBcIl9fSU5ESVZJRFVBTF9PTkVfVkVSU0lPTl9cIiArIG1vZHVsZU5hbWU7XG4gICAgICAgICAgICAgICAgdmFyIGVuZm9yY2VLZXkgPSBrZXkgKyBcIl9FTkZPUkNFX1NJTkdMRVRPTlwiO1xuXG4gICAgICAgICAgICAgICAgdmFyIHZlcnNpb25WYWx1ZSA9IEluZGl2aWR1YWwoZW5mb3JjZUtleSwgdmVyc2lvbik7XG5cbiAgICAgICAgICAgICAgICBpZiAodmVyc2lvblZhbHVlICE9PSB2ZXJzaW9uKSB7XG4gICAgICAgICAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcihcIkNhbiBvbmx5IGhhdmUgb25lIGNvcHkgb2YgXCIgKyBtb2R1bGVOYW1lICsgXCIuXFxuXCIgKyBcIllvdSBhbHJlYWR5IGhhdmUgdmVyc2lvbiBcIiArIHZlcnNpb25WYWx1ZSArIFwiIGluc3RhbGxlZC5cXG5cIiArIFwiVGhpcyBtZWFucyB5b3UgY2Fubm90IGluc3RhbGwgdmVyc2lvbiBcIiArIHZlcnNpb24pO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHJldHVybiBJbmRpdmlkdWFsKGtleSwgZGVmYXVsdFZhbHVlKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSwgeyBcIi4vaW5kZXguanNcIjogOCB9XSwgMTA6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICAoZnVuY3Rpb24gKGdsb2JhbCkge1xuICAgICAgICAgICAgICAgIHZhciB0b3BMZXZlbCA9IHR5cGVvZiBnbG9iYWwgIT09IFwidW5kZWZpbmVkXCIgPyBnbG9iYWwgOiB0eXBlb2Ygd2luZG93ICE9PSBcInVuZGVmaW5lZFwiID8gd2luZG93IDoge307XG4gICAgICAgICAgICAgICAgdmFyIG1pbkRvYyA9IHJlcXVpcmUoXCJtaW4tZG9jdW1lbnRcIik7XG5cbiAgICAgICAgICAgICAgICBpZiAodHlwZW9mIGRvY3VtZW50ICE9PSBcInVuZGVmaW5lZFwiKSB7XG4gICAgICAgICAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gZG9jdW1lbnQ7XG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgdmFyIGRvY2N5ID0gdG9wTGV2ZWxbXCJfX0dMT0JBTF9ET0NVTUVOVF9DQUNIRUA0XCJdO1xuXG4gICAgICAgICAgICAgICAgICAgIGlmICghZG9jY3kpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGRvY2N5ID0gdG9wTGV2ZWxbXCJfX0dMT0JBTF9ET0NVTUVOVF9DQUNIRUA0XCJdID0gbWluRG9jO1xuICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBkb2NjeTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9KS5jYWxsKHRoaXMsIHR5cGVvZiBnbG9iYWwgIT09IFwidW5kZWZpbmVkXCIgPyBnbG9iYWwgOiB0eXBlb2Ygc2VsZiAhPT0gXCJ1bmRlZmluZWRcIiA/IHNlbGYgOiB0eXBlb2Ygd2luZG93ICE9PSBcInVuZGVmaW5lZFwiID8gd2luZG93IDoge30pO1xuICAgICAgICB9LCB7IFwibWluLWRvY3VtZW50XCI6IDYgfV0sIDExOiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge1xuICAgICAgICAgICAgXCJ1c2Ugc3RyaWN0XCI7XG5cbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gaXNPYmplY3QoeCkge1xuICAgICAgICAgICAgICAgIHJldHVybiB0eXBlb2YgeCA9PT0gXCJvYmplY3RcIiAmJiB4ICE9PSBudWxsO1xuICAgICAgICAgICAgfTtcbiAgICAgICAgfSwge31dLCAxMjogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHtcbiAgICAgICAgICAgIHZhciBuYXRpdmVJc0FycmF5ID0gQXJyYXkuaXNBcnJheTtcbiAgICAgICAgICAgIHZhciB0b1N0cmluZyA9IE9iamVjdC5wcm90b3R5cGUudG9TdHJpbmc7XG5cbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gbmF0aXZlSXNBcnJheSB8fCBpc0FycmF5O1xuXG4gICAgICAgICAgICBmdW5jdGlvbiBpc0FycmF5KG9iaikge1xuICAgICAgICAgICAgICAgIHJldHVybiB0b1N0cmluZy5jYWxsKG9iaikgPT09IFwiW29iamVjdCBBcnJheV1cIjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSwge31dLCAxMzogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHtcbiAgICAgICAgICAgIHZhciBwYXRjaCA9IHJlcXVpcmUoXCIuL3Zkb20vcGF0Y2guanNcIik7XG5cbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gcGF0Y2g7XG4gICAgICAgIH0sIHsgXCIuL3Zkb20vcGF0Y2guanNcIjogMTggfV0sIDE0OiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge1xuICAgICAgICAgICAgdmFyIGlzT2JqZWN0ID0gcmVxdWlyZShcImlzLW9iamVjdFwiKTtcbiAgICAgICAgICAgIHZhciBpc0hvb2sgPSByZXF1aXJlKFwiLi4vdm5vZGUvaXMtdmhvb2suanNcIik7XG5cbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gYXBwbHlQcm9wZXJ0aWVzO1xuXG4gICAgICAgICAgICBmdW5jdGlvbiBhcHBseVByb3BlcnRpZXMobm9kZSwgcHJvcHMsIHByZXZpb3VzKSB7XG4gICAgICAgICAgICAgICAgZm9yICh2YXIgcHJvcE5hbWUgaW4gcHJvcHMpIHtcbiAgICAgICAgICAgICAgICAgICAgdmFyIHByb3BWYWx1ZSA9IHByb3BzW3Byb3BOYW1lXTtcblxuICAgICAgICAgICAgICAgICAgICBpZiAocHJvcFZhbHVlID09PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJlbW92ZVByb3BlcnR5KG5vZGUsIHByb3BOYW1lLCBwcm9wVmFsdWUsIHByZXZpb3VzKTtcbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIGlmIChpc0hvb2socHJvcFZhbHVlKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgcmVtb3ZlUHJvcGVydHkobm9kZSwgcHJvcE5hbWUsIHByb3BWYWx1ZSwgcHJldmlvdXMpO1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHByb3BWYWx1ZS5ob29rKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcHJvcFZhbHVlLmhvb2sobm9kZSwgcHJvcE5hbWUsIHByZXZpb3VzID8gcHJldmlvdXNbcHJvcE5hbWVdIDogdW5kZWZpbmVkKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChpc09iamVjdChwcm9wVmFsdWUpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcGF0Y2hPYmplY3Qobm9kZSwgcHJvcHMsIHByZXZpb3VzLCBwcm9wTmFtZSwgcHJvcFZhbHVlKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgbm9kZVtwcm9wTmFtZV0gPSBwcm9wVmFsdWU7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIHJlbW92ZVByb3BlcnR5KG5vZGUsIHByb3BOYW1lLCBwcm9wVmFsdWUsIHByZXZpb3VzKSB7XG4gICAgICAgICAgICAgICAgaWYgKHByZXZpb3VzKSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciBwcmV2aW91c1ZhbHVlID0gcHJldmlvdXNbcHJvcE5hbWVdO1xuXG4gICAgICAgICAgICAgICAgICAgIGlmICghaXNIb29rKHByZXZpb3VzVmFsdWUpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAocHJvcE5hbWUgPT09IFwiYXR0cmlidXRlc1wiKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgZm9yICh2YXIgYXR0ck5hbWUgaW4gcHJldmlvdXNWYWx1ZSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBub2RlLnJlbW92ZUF0dHJpYnV0ZShhdHRyTmFtZSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIGlmIChwcm9wTmFtZSA9PT0gXCJzdHlsZVwiKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgZm9yICh2YXIgaSBpbiBwcmV2aW91c1ZhbHVlKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG5vZGUuc3R5bGVbaV0gPSBcIlwiO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAodHlwZW9mIHByZXZpb3VzVmFsdWUgPT09IFwic3RyaW5nXCIpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBub2RlW3Byb3BOYW1lXSA9IFwiXCI7XG4gICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIG5vZGVbcHJvcE5hbWVdID0gbnVsbDtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIGlmIChwcmV2aW91c1ZhbHVlLnVuaG9vaykge1xuICAgICAgICAgICAgICAgICAgICAgICAgcHJldmlvdXNWYWx1ZS51bmhvb2sobm9kZSwgcHJvcE5hbWUsIHByb3BWYWx1ZSk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIHBhdGNoT2JqZWN0KG5vZGUsIHByb3BzLCBwcmV2aW91cywgcHJvcE5hbWUsIHByb3BWYWx1ZSkge1xuICAgICAgICAgICAgICAgIHZhciBwcmV2aW91c1ZhbHVlID0gcHJldmlvdXMgPyBwcmV2aW91c1twcm9wTmFtZV0gOiB1bmRlZmluZWQ7XG5cbiAgICAgICAgICAgICAgICAvLyBTZXQgYXR0cmlidXRlc1xuICAgICAgICAgICAgICAgIGlmIChwcm9wTmFtZSA9PT0gXCJhdHRyaWJ1dGVzXCIpIHtcbiAgICAgICAgICAgICAgICAgICAgZm9yICh2YXIgYXR0ck5hbWUgaW4gcHJvcFZhbHVlKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICB2YXIgYXR0clZhbHVlID0gcHJvcFZhbHVlW2F0dHJOYW1lXTtcblxuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGF0dHJWYWx1ZSA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgbm9kZS5yZW1vdmVBdHRyaWJ1dGUoYXR0ck5hbWUpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBub2RlLnNldEF0dHJpYnV0ZShhdHRyTmFtZSwgYXR0clZhbHVlKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICBpZiAocHJldmlvdXNWYWx1ZSAmJiBpc09iamVjdChwcmV2aW91c1ZhbHVlKSAmJiBnZXRQcm90b3R5cGUocHJldmlvdXNWYWx1ZSkgIT09IGdldFByb3RvdHlwZShwcm9wVmFsdWUpKSB7XG4gICAgICAgICAgICAgICAgICAgIG5vZGVbcHJvcE5hbWVdID0gcHJvcFZhbHVlO1xuICAgICAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgaWYgKCFpc09iamVjdChub2RlW3Byb3BOYW1lXSkpIHtcbiAgICAgICAgICAgICAgICAgICAgbm9kZVtwcm9wTmFtZV0gPSB7fTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICB2YXIgcmVwbGFjZXIgPSBwcm9wTmFtZSA9PT0gXCJzdHlsZVwiID8gXCJcIiA6IHVuZGVmaW5lZDtcblxuICAgICAgICAgICAgICAgIGZvciAodmFyIGsgaW4gcHJvcFZhbHVlKSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciB2YWx1ZSA9IHByb3BWYWx1ZVtrXTtcbiAgICAgICAgICAgICAgICAgICAgbm9kZVtwcm9wTmFtZV1ba10gPSB2YWx1ZSA9PT0gdW5kZWZpbmVkID8gcmVwbGFjZXIgOiB2YWx1ZTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIGdldFByb3RvdHlwZSh2YWx1ZSkge1xuICAgICAgICAgICAgICAgIGlmIChPYmplY3QuZ2V0UHJvdG90eXBlT2YpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIE9iamVjdC5nZXRQcm90b3R5cGVPZih2YWx1ZSk7XG4gICAgICAgICAgICAgICAgfSBlbHNlIGlmICh2YWx1ZS5fX3Byb3RvX18pIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHZhbHVlLl9fcHJvdG9fXztcbiAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKHZhbHVlLmNvbnN0cnVjdG9yKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiB2YWx1ZS5jb25zdHJ1Y3Rvci5wcm90b3R5cGU7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9LCB7IFwiLi4vdm5vZGUvaXMtdmhvb2suanNcIjogMjYsIFwiaXMtb2JqZWN0XCI6IDExIH1dLCAxNTogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHtcbiAgICAgICAgICAgIHZhciBkb2N1bWVudCA9IHJlcXVpcmUoXCJnbG9iYWwvZG9jdW1lbnRcIik7XG5cbiAgICAgICAgICAgIHZhciBhcHBseVByb3BlcnRpZXMgPSByZXF1aXJlKFwiLi9hcHBseS1wcm9wZXJ0aWVzXCIpO1xuXG4gICAgICAgICAgICB2YXIgaXNWTm9kZSA9IHJlcXVpcmUoXCIuLi92bm9kZS9pcy12bm9kZS5qc1wiKTtcbiAgICAgICAgICAgIHZhciBpc1ZUZXh0ID0gcmVxdWlyZShcIi4uL3Zub2RlL2lzLXZ0ZXh0LmpzXCIpO1xuICAgICAgICAgICAgdmFyIGlzV2lkZ2V0ID0gcmVxdWlyZShcIi4uL3Zub2RlL2lzLXdpZGdldC5qc1wiKTtcbiAgICAgICAgICAgIHZhciBoYW5kbGVUaHVuayA9IHJlcXVpcmUoXCIuLi92bm9kZS9oYW5kbGUtdGh1bmsuanNcIik7XG5cbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gY3JlYXRlRWxlbWVudDtcblxuICAgICAgICAgICAgZnVuY3Rpb24gY3JlYXRlRWxlbWVudCh2bm9kZSwgb3B0cykge1xuICAgICAgICAgICAgICAgIHZhciBkb2MgPSBvcHRzID8gb3B0cy5kb2N1bWVudCB8fCBkb2N1bWVudCA6IGRvY3VtZW50O1xuICAgICAgICAgICAgICAgIHZhciB3YXJuID0gb3B0cyA/IG9wdHMud2FybiA6IG51bGw7XG5cbiAgICAgICAgICAgICAgICB2bm9kZSA9IGhhbmRsZVRodW5rKHZub2RlKS5hO1xuXG4gICAgICAgICAgICAgICAgaWYgKGlzV2lkZ2V0KHZub2RlKSkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gdm5vZGUuaW5pdCgpO1xuICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoaXNWVGV4dCh2bm9kZSkpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGRvYy5jcmVhdGVUZXh0Tm9kZSh2bm9kZS50ZXh0KTtcbiAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKCFpc1ZOb2RlKHZub2RlKSkge1xuICAgICAgICAgICAgICAgICAgICBpZiAod2Fybikge1xuICAgICAgICAgICAgICAgICAgICAgICAgd2FybihcIkl0ZW0gaXMgbm90IGEgdmFsaWQgdmlydHVhbCBkb20gbm9kZVwiLCB2bm9kZSk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIG51bGw7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgdmFyIG5vZGUgPSB2bm9kZS5uYW1lc3BhY2UgPT09IG51bGwgPyBkb2MuY3JlYXRlRWxlbWVudCh2bm9kZS50YWdOYW1lKSA6IGRvYy5jcmVhdGVFbGVtZW50TlModm5vZGUubmFtZXNwYWNlLCB2bm9kZS50YWdOYW1lKTtcblxuICAgICAgICAgICAgICAgIHZhciBwcm9wcyA9IHZub2RlLnByb3BlcnRpZXM7XG4gICAgICAgICAgICAgICAgYXBwbHlQcm9wZXJ0aWVzKG5vZGUsIHByb3BzKTtcblxuICAgICAgICAgICAgICAgIHZhciBjaGlsZHJlbiA9IHZub2RlLmNoaWxkcmVuO1xuXG4gICAgICAgICAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCBjaGlsZHJlbi5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgICAgICAgICB2YXIgY2hpbGROb2RlID0gY3JlYXRlRWxlbWVudChjaGlsZHJlbltpXSwgb3B0cyk7XG4gICAgICAgICAgICAgICAgICAgIGlmIChjaGlsZE5vZGUpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIG5vZGUuYXBwZW5kQ2hpbGQoY2hpbGROb2RlKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHJldHVybiBub2RlO1xuICAgICAgICAgICAgfVxuICAgICAgICB9LCB7IFwiLi4vdm5vZGUvaGFuZGxlLXRodW5rLmpzXCI6IDI0LCBcIi4uL3Zub2RlL2lzLXZub2RlLmpzXCI6IDI3LCBcIi4uL3Zub2RlL2lzLXZ0ZXh0LmpzXCI6IDI4LCBcIi4uL3Zub2RlL2lzLXdpZGdldC5qc1wiOiAyOSwgXCIuL2FwcGx5LXByb3BlcnRpZXNcIjogMTQsIFwiZ2xvYmFsL2RvY3VtZW50XCI6IDEwIH1dLCAxNjogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHtcbiAgICAgICAgICAgIC8vIE1hcHMgYSB2aXJ0dWFsIERPTSB0cmVlIG9udG8gYSByZWFsIERPTSB0cmVlIGluIGFuIGVmZmljaWVudCBtYW5uZXIuXG4gICAgICAgICAgICAvLyBXZSBkb24ndCB3YW50IHRvIHJlYWQgYWxsIG9mIHRoZSBET00gbm9kZXMgaW4gdGhlIHRyZWUgc28gd2UgdXNlXG4gICAgICAgICAgICAvLyB0aGUgaW4tb3JkZXIgdHJlZSBpbmRleGluZyB0byBlbGltaW5hdGUgcmVjdXJzaW9uIGRvd24gY2VydGFpbiBicmFuY2hlcy5cbiAgICAgICAgICAgIC8vIFdlIG9ubHkgcmVjdXJzZSBpbnRvIGEgRE9NIG5vZGUgaWYgd2Uga25vdyB0aGF0IGl0IGNvbnRhaW5zIGEgY2hpbGQgb2ZcbiAgICAgICAgICAgIC8vIGludGVyZXN0LlxuXG4gICAgICAgICAgICB2YXIgbm9DaGlsZCA9IHt9O1xuXG4gICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IGRvbUluZGV4O1xuXG4gICAgICAgICAgICBmdW5jdGlvbiBkb21JbmRleChyb290Tm9kZSwgdHJlZSwgaW5kaWNlcywgbm9kZXMpIHtcbiAgICAgICAgICAgICAgICBpZiAoIWluZGljZXMgfHwgaW5kaWNlcy5sZW5ndGggPT09IDApIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHt9O1xuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIGluZGljZXMuc29ydChhc2NlbmRpbmcpO1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gcmVjdXJzZShyb290Tm9kZSwgdHJlZSwgaW5kaWNlcywgbm9kZXMsIDApO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZnVuY3Rpb24gcmVjdXJzZShyb290Tm9kZSwgdHJlZSwgaW5kaWNlcywgbm9kZXMsIHJvb3RJbmRleCkge1xuICAgICAgICAgICAgICAgIG5vZGVzID0gbm9kZXMgfHwge307XG5cbiAgICAgICAgICAgICAgICBpZiAocm9vdE5vZGUpIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKGluZGV4SW5SYW5nZShpbmRpY2VzLCByb290SW5kZXgsIHJvb3RJbmRleCkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIG5vZGVzW3Jvb3RJbmRleF0gPSByb290Tm9kZTtcbiAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgIHZhciB2Q2hpbGRyZW4gPSB0cmVlLmNoaWxkcmVuO1xuXG4gICAgICAgICAgICAgICAgICAgIGlmICh2Q2hpbGRyZW4pIHtcblxuICAgICAgICAgICAgICAgICAgICAgICAgdmFyIGNoaWxkTm9kZXMgPSByb290Tm9kZS5jaGlsZE5vZGVzO1xuXG4gICAgICAgICAgICAgICAgICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IHRyZWUuY2hpbGRyZW4ubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICByb290SW5kZXggKz0gMTtcblxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZhciB2Q2hpbGQgPSB2Q2hpbGRyZW5baV0gfHwgbm9DaGlsZDtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB2YXIgbmV4dEluZGV4ID0gcm9vdEluZGV4ICsgKHZDaGlsZC5jb3VudCB8fCAwKTtcblxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIHNraXAgcmVjdXJzaW9uIGRvd24gdGhlIHRyZWUgaWYgdGhlcmUgYXJlIG5vIG5vZGVzIGRvd24gaGVyZVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChpbmRleEluUmFuZ2UoaW5kaWNlcywgcm9vdEluZGV4LCBuZXh0SW5kZXgpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlY3Vyc2UoY2hpbGROb2Rlc1tpXSwgdkNoaWxkLCBpbmRpY2VzLCBub2Rlcywgcm9vdEluZGV4KTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICByb290SW5kZXggPSBuZXh0SW5kZXg7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICByZXR1cm4gbm9kZXM7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIC8vIEJpbmFyeSBzZWFyY2ggZm9yIGFuIGluZGV4IGluIHRoZSBpbnRlcnZhbCBbbGVmdCwgcmlnaHRdXG4gICAgICAgICAgICBmdW5jdGlvbiBpbmRleEluUmFuZ2UoaW5kaWNlcywgbGVmdCwgcmlnaHQpIHtcbiAgICAgICAgICAgICAgICBpZiAoaW5kaWNlcy5sZW5ndGggPT09IDApIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHZhciBtaW5JbmRleCA9IDA7XG4gICAgICAgICAgICAgICAgdmFyIG1heEluZGV4ID0gaW5kaWNlcy5sZW5ndGggLSAxO1xuICAgICAgICAgICAgICAgIHZhciBjdXJyZW50SW5kZXg7XG4gICAgICAgICAgICAgICAgdmFyIGN1cnJlbnRJdGVtO1xuXG4gICAgICAgICAgICAgICAgd2hpbGUgKG1pbkluZGV4IDw9IG1heEluZGV4KSB7XG4gICAgICAgICAgICAgICAgICAgIGN1cnJlbnRJbmRleCA9IChtYXhJbmRleCArIG1pbkluZGV4KSAvIDIgPj4gMDtcbiAgICAgICAgICAgICAgICAgICAgY3VycmVudEl0ZW0gPSBpbmRpY2VzW2N1cnJlbnRJbmRleF07XG5cbiAgICAgICAgICAgICAgICAgICAgaWYgKG1pbkluZGV4ID09PSBtYXhJbmRleCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGN1cnJlbnRJdGVtID49IGxlZnQgJiYgY3VycmVudEl0ZW0gPD0gcmlnaHQ7XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoY3VycmVudEl0ZW0gPCBsZWZ0KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBtaW5JbmRleCA9IGN1cnJlbnRJbmRleCArIDE7XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoY3VycmVudEl0ZW0gPiByaWdodCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgbWF4SW5kZXggPSBjdXJyZW50SW5kZXggLSAxO1xuICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIGFzY2VuZGluZyhhLCBiKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGEgPiBiID8gMSA6IC0xO1xuICAgICAgICAgICAgfVxuICAgICAgICB9LCB7fV0sIDE3OiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge1xuICAgICAgICAgICAgdmFyIGFwcGx5UHJvcGVydGllcyA9IHJlcXVpcmUoXCIuL2FwcGx5LXByb3BlcnRpZXNcIik7XG5cbiAgICAgICAgICAgIHZhciBpc1dpZGdldCA9IHJlcXVpcmUoXCIuLi92bm9kZS9pcy13aWRnZXQuanNcIik7XG4gICAgICAgICAgICB2YXIgVlBhdGNoID0gcmVxdWlyZShcIi4uL3Zub2RlL3ZwYXRjaC5qc1wiKTtcblxuICAgICAgICAgICAgdmFyIHVwZGF0ZVdpZGdldCA9IHJlcXVpcmUoXCIuL3VwZGF0ZS13aWRnZXRcIik7XG5cbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gYXBwbHlQYXRjaDtcblxuICAgICAgICAgICAgZnVuY3Rpb24gYXBwbHlQYXRjaCh2cGF0Y2gsIGRvbU5vZGUsIHJlbmRlck9wdGlvbnMpIHtcbiAgICAgICAgICAgICAgICB2YXIgdHlwZSA9IHZwYXRjaC50eXBlO1xuICAgICAgICAgICAgICAgIHZhciB2Tm9kZSA9IHZwYXRjaC52Tm9kZTtcbiAgICAgICAgICAgICAgICB2YXIgcGF0Y2ggPSB2cGF0Y2gucGF0Y2g7XG5cbiAgICAgICAgICAgICAgICBzd2l0Y2ggKHR5cGUpIHtcbiAgICAgICAgICAgICAgICAgICAgY2FzZSBWUGF0Y2guUkVNT1ZFOlxuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHJlbW92ZU5vZGUoZG9tTm9kZSwgdk5vZGUpO1xuICAgICAgICAgICAgICAgICAgICBjYXNlIFZQYXRjaC5JTlNFUlQ6XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gaW5zZXJ0Tm9kZShkb21Ob2RlLCBwYXRjaCwgcmVuZGVyT3B0aW9ucyk7XG4gICAgICAgICAgICAgICAgICAgIGNhc2UgVlBhdGNoLlZURVhUOlxuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHN0cmluZ1BhdGNoKGRvbU5vZGUsIHZOb2RlLCBwYXRjaCwgcmVuZGVyT3B0aW9ucyk7XG4gICAgICAgICAgICAgICAgICAgIGNhc2UgVlBhdGNoLldJREdFVDpcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiB3aWRnZXRQYXRjaChkb21Ob2RlLCB2Tm9kZSwgcGF0Y2gsIHJlbmRlck9wdGlvbnMpO1xuICAgICAgICAgICAgICAgICAgICBjYXNlIFZQYXRjaC5WTk9ERTpcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiB2Tm9kZVBhdGNoKGRvbU5vZGUsIHZOb2RlLCBwYXRjaCwgcmVuZGVyT3B0aW9ucyk7XG4gICAgICAgICAgICAgICAgICAgIGNhc2UgVlBhdGNoLk9SREVSOlxuICAgICAgICAgICAgICAgICAgICAgICAgcmVvcmRlckNoaWxkcmVuKGRvbU5vZGUsIHBhdGNoKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBkb21Ob2RlO1xuICAgICAgICAgICAgICAgICAgICBjYXNlIFZQYXRjaC5QUk9QUzpcbiAgICAgICAgICAgICAgICAgICAgICAgIGFwcGx5UHJvcGVydGllcyhkb21Ob2RlLCBwYXRjaCwgdk5vZGUucHJvcGVydGllcyk7XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gZG9tTm9kZTtcbiAgICAgICAgICAgICAgICAgICAgY2FzZSBWUGF0Y2guVEhVTks6XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gcmVwbGFjZVJvb3QoZG9tTm9kZSwgcmVuZGVyT3B0aW9ucy5wYXRjaChkb21Ob2RlLCBwYXRjaCwgcmVuZGVyT3B0aW9ucykpO1xuICAgICAgICAgICAgICAgICAgICBkZWZhdWx0OlxuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGRvbU5vZGU7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBmdW5jdGlvbiByZW1vdmVOb2RlKGRvbU5vZGUsIHZOb2RlKSB7XG4gICAgICAgICAgICAgICAgdmFyIHBhcmVudE5vZGUgPSBkb21Ob2RlLnBhcmVudE5vZGU7XG5cbiAgICAgICAgICAgICAgICBpZiAocGFyZW50Tm9kZSkge1xuICAgICAgICAgICAgICAgICAgICBwYXJlbnROb2RlLnJlbW92ZUNoaWxkKGRvbU5vZGUpO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIGRlc3Ryb3lXaWRnZXQoZG9tTm9kZSwgdk5vZGUpO1xuXG4gICAgICAgICAgICAgICAgcmV0dXJuIG51bGw7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIGluc2VydE5vZGUocGFyZW50Tm9kZSwgdk5vZGUsIHJlbmRlck9wdGlvbnMpIHtcbiAgICAgICAgICAgICAgICB2YXIgbmV3Tm9kZSA9IHJlbmRlck9wdGlvbnMucmVuZGVyKHZOb2RlLCByZW5kZXJPcHRpb25zKTtcblxuICAgICAgICAgICAgICAgIGlmIChwYXJlbnROb2RlKSB7XG4gICAgICAgICAgICAgICAgICAgIHBhcmVudE5vZGUuYXBwZW5kQ2hpbGQobmV3Tm9kZSk7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgcmV0dXJuIHBhcmVudE5vZGU7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIHN0cmluZ1BhdGNoKGRvbU5vZGUsIGxlZnRWTm9kZSwgdlRleHQsIHJlbmRlck9wdGlvbnMpIHtcbiAgICAgICAgICAgICAgICB2YXIgbmV3Tm9kZTtcblxuICAgICAgICAgICAgICAgIGlmIChkb21Ob2RlLm5vZGVUeXBlID09PSAzKSB7XG4gICAgICAgICAgICAgICAgICAgIGRvbU5vZGUucmVwbGFjZURhdGEoMCwgZG9tTm9kZS5sZW5ndGgsIHZUZXh0LnRleHQpO1xuICAgICAgICAgICAgICAgICAgICBuZXdOb2RlID0gZG9tTm9kZTtcbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICB2YXIgcGFyZW50Tm9kZSA9IGRvbU5vZGUucGFyZW50Tm9kZTtcbiAgICAgICAgICAgICAgICAgICAgbmV3Tm9kZSA9IHJlbmRlck9wdGlvbnMucmVuZGVyKHZUZXh0LCByZW5kZXJPcHRpb25zKTtcblxuICAgICAgICAgICAgICAgICAgICBpZiAocGFyZW50Tm9kZSAmJiBuZXdOb2RlICE9PSBkb21Ob2RlKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBwYXJlbnROb2RlLnJlcGxhY2VDaGlsZChuZXdOb2RlLCBkb21Ob2RlKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHJldHVybiBuZXdOb2RlO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBmdW5jdGlvbiB3aWRnZXRQYXRjaChkb21Ob2RlLCBsZWZ0Vk5vZGUsIHdpZGdldCwgcmVuZGVyT3B0aW9ucykge1xuICAgICAgICAgICAgICAgIHZhciB1cGRhdGluZyA9IHVwZGF0ZVdpZGdldChsZWZ0Vk5vZGUsIHdpZGdldCk7XG4gICAgICAgICAgICAgICAgdmFyIG5ld05vZGU7XG5cbiAgICAgICAgICAgICAgICBpZiAodXBkYXRpbmcpIHtcbiAgICAgICAgICAgICAgICAgICAgbmV3Tm9kZSA9IHdpZGdldC51cGRhdGUobGVmdFZOb2RlLCBkb21Ob2RlKSB8fCBkb21Ob2RlO1xuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIG5ld05vZGUgPSByZW5kZXJPcHRpb25zLnJlbmRlcih3aWRnZXQsIHJlbmRlck9wdGlvbnMpO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHZhciBwYXJlbnROb2RlID0gZG9tTm9kZS5wYXJlbnROb2RlO1xuXG4gICAgICAgICAgICAgICAgaWYgKHBhcmVudE5vZGUgJiYgbmV3Tm9kZSAhPT0gZG9tTm9kZSkge1xuICAgICAgICAgICAgICAgICAgICBwYXJlbnROb2RlLnJlcGxhY2VDaGlsZChuZXdOb2RlLCBkb21Ob2RlKTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICBpZiAoIXVwZGF0aW5nKSB7XG4gICAgICAgICAgICAgICAgICAgIGRlc3Ryb3lXaWRnZXQoZG9tTm9kZSwgbGVmdFZOb2RlKTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICByZXR1cm4gbmV3Tm9kZTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZnVuY3Rpb24gdk5vZGVQYXRjaChkb21Ob2RlLCBsZWZ0Vk5vZGUsIHZOb2RlLCByZW5kZXJPcHRpb25zKSB7XG4gICAgICAgICAgICAgICAgdmFyIHBhcmVudE5vZGUgPSBkb21Ob2RlLnBhcmVudE5vZGU7XG4gICAgICAgICAgICAgICAgdmFyIG5ld05vZGUgPSByZW5kZXJPcHRpb25zLnJlbmRlcih2Tm9kZSwgcmVuZGVyT3B0aW9ucyk7XG5cbiAgICAgICAgICAgICAgICBpZiAocGFyZW50Tm9kZSAmJiBuZXdOb2RlICE9PSBkb21Ob2RlKSB7XG4gICAgICAgICAgICAgICAgICAgIHBhcmVudE5vZGUucmVwbGFjZUNoaWxkKG5ld05vZGUsIGRvbU5vZGUpO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHJldHVybiBuZXdOb2RlO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBmdW5jdGlvbiBkZXN0cm95V2lkZ2V0KGRvbU5vZGUsIHcpIHtcbiAgICAgICAgICAgICAgICBpZiAodHlwZW9mIHcuZGVzdHJveSA9PT0gXCJmdW5jdGlvblwiICYmIGlzV2lkZ2V0KHcpKSB7XG4gICAgICAgICAgICAgICAgICAgIHcuZGVzdHJveShkb21Ob2RlKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIHJlb3JkZXJDaGlsZHJlbihkb21Ob2RlLCBtb3Zlcykge1xuICAgICAgICAgICAgICAgIHZhciBjaGlsZE5vZGVzID0gZG9tTm9kZS5jaGlsZE5vZGVzO1xuICAgICAgICAgICAgICAgIHZhciBrZXlNYXAgPSB7fTtcbiAgICAgICAgICAgICAgICB2YXIgbm9kZTtcbiAgICAgICAgICAgICAgICB2YXIgcmVtb3ZlO1xuICAgICAgICAgICAgICAgIHZhciBpbnNlcnQ7XG5cbiAgICAgICAgICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IG1vdmVzLnJlbW92ZXMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgICAgICAgICAgcmVtb3ZlID0gbW92ZXMucmVtb3Zlc1tpXTtcbiAgICAgICAgICAgICAgICAgICAgbm9kZSA9IGNoaWxkTm9kZXNbcmVtb3ZlLmZyb21dO1xuICAgICAgICAgICAgICAgICAgICBpZiAocmVtb3ZlLmtleSkge1xuICAgICAgICAgICAgICAgICAgICAgICAga2V5TWFwW3JlbW92ZS5rZXldID0gbm9kZTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICBkb21Ob2RlLnJlbW92ZUNoaWxkKG5vZGUpO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHZhciBsZW5ndGggPSBjaGlsZE5vZGVzLmxlbmd0aDtcbiAgICAgICAgICAgICAgICBmb3IgKHZhciBqID0gMDsgaiA8IG1vdmVzLmluc2VydHMubGVuZ3RoOyBqKyspIHtcbiAgICAgICAgICAgICAgICAgICAgaW5zZXJ0ID0gbW92ZXMuaW5zZXJ0c1tqXTtcbiAgICAgICAgICAgICAgICAgICAgbm9kZSA9IGtleU1hcFtpbnNlcnQua2V5XTtcbiAgICAgICAgICAgICAgICAgICAgLy8gdGhpcyBpcyB0aGUgd2VpcmRlc3QgYnVnIGkndmUgZXZlciBzZWVuIGluIHdlYmtpdFxuICAgICAgICAgICAgICAgICAgICBkb21Ob2RlLmluc2VydEJlZm9yZShub2RlLCBpbnNlcnQudG8gPj0gbGVuZ3RoKysgPyBudWxsIDogY2hpbGROb2Rlc1tpbnNlcnQudG9dKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIHJlcGxhY2VSb290KG9sZFJvb3QsIG5ld1Jvb3QpIHtcbiAgICAgICAgICAgICAgICBpZiAob2xkUm9vdCAmJiBuZXdSb290ICYmIG9sZFJvb3QgIT09IG5ld1Jvb3QgJiYgb2xkUm9vdC5wYXJlbnROb2RlKSB7XG4gICAgICAgICAgICAgICAgICAgIG9sZFJvb3QucGFyZW50Tm9kZS5yZXBsYWNlQ2hpbGQobmV3Um9vdCwgb2xkUm9vdCk7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgcmV0dXJuIG5ld1Jvb3Q7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0sIHsgXCIuLi92bm9kZS9pcy13aWRnZXQuanNcIjogMjksIFwiLi4vdm5vZGUvdnBhdGNoLmpzXCI6IDMyLCBcIi4vYXBwbHktcHJvcGVydGllc1wiOiAxNCwgXCIuL3VwZGF0ZS13aWRnZXRcIjogMTkgfV0sIDE4OiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge1xuICAgICAgICAgICAgdmFyIGRvY3VtZW50ID0gcmVxdWlyZShcImdsb2JhbC9kb2N1bWVudFwiKTtcbiAgICAgICAgICAgIHZhciBpc0FycmF5ID0gcmVxdWlyZShcIngtaXMtYXJyYXlcIik7XG5cbiAgICAgICAgICAgIHZhciByZW5kZXIgPSByZXF1aXJlKFwiLi9jcmVhdGUtZWxlbWVudFwiKTtcbiAgICAgICAgICAgIHZhciBkb21JbmRleCA9IHJlcXVpcmUoXCIuL2RvbS1pbmRleFwiKTtcbiAgICAgICAgICAgIHZhciBwYXRjaE9wID0gcmVxdWlyZShcIi4vcGF0Y2gtb3BcIik7XG4gICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IHBhdGNoO1xuXG4gICAgICAgICAgICBmdW5jdGlvbiBwYXRjaChyb290Tm9kZSwgcGF0Y2hlcywgcmVuZGVyT3B0aW9ucykge1xuICAgICAgICAgICAgICAgIHJlbmRlck9wdGlvbnMgPSByZW5kZXJPcHRpb25zIHx8IHt9O1xuICAgICAgICAgICAgICAgIHJlbmRlck9wdGlvbnMucGF0Y2ggPSByZW5kZXJPcHRpb25zLnBhdGNoICYmIHJlbmRlck9wdGlvbnMucGF0Y2ggIT09IHBhdGNoID8gcmVuZGVyT3B0aW9ucy5wYXRjaCA6IHBhdGNoUmVjdXJzaXZlO1xuICAgICAgICAgICAgICAgIHJlbmRlck9wdGlvbnMucmVuZGVyID0gcmVuZGVyT3B0aW9ucy5yZW5kZXIgfHwgcmVuZGVyO1xuXG4gICAgICAgICAgICAgICAgcmV0dXJuIHJlbmRlck9wdGlvbnMucGF0Y2gocm9vdE5vZGUsIHBhdGNoZXMsIHJlbmRlck9wdGlvbnMpO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBmdW5jdGlvbiBwYXRjaFJlY3Vyc2l2ZShyb290Tm9kZSwgcGF0Y2hlcywgcmVuZGVyT3B0aW9ucykge1xuICAgICAgICAgICAgICAgIHZhciBpbmRpY2VzID0gcGF0Y2hJbmRpY2VzKHBhdGNoZXMpO1xuXG4gICAgICAgICAgICAgICAgaWYgKGluZGljZXMubGVuZ3RoID09PSAwKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiByb290Tm9kZTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICB2YXIgaW5kZXggPSBkb21JbmRleChyb290Tm9kZSwgcGF0Y2hlcy5hLCBpbmRpY2VzKTtcbiAgICAgICAgICAgICAgICB2YXIgb3duZXJEb2N1bWVudCA9IHJvb3ROb2RlLm93bmVyRG9jdW1lbnQ7XG5cbiAgICAgICAgICAgICAgICBpZiAoIXJlbmRlck9wdGlvbnMuZG9jdW1lbnQgJiYgb3duZXJEb2N1bWVudCAhPT0gZG9jdW1lbnQpIHtcbiAgICAgICAgICAgICAgICAgICAgcmVuZGVyT3B0aW9ucy5kb2N1bWVudCA9IG93bmVyRG9jdW1lbnQ7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCBpbmRpY2VzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciBub2RlSW5kZXggPSBpbmRpY2VzW2ldO1xuICAgICAgICAgICAgICAgICAgICByb290Tm9kZSA9IGFwcGx5UGF0Y2gocm9vdE5vZGUsIGluZGV4W25vZGVJbmRleF0sIHBhdGNoZXNbbm9kZUluZGV4XSwgcmVuZGVyT3B0aW9ucyk7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgcmV0dXJuIHJvb3ROb2RlO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBmdW5jdGlvbiBhcHBseVBhdGNoKHJvb3ROb2RlLCBkb21Ob2RlLCBwYXRjaExpc3QsIHJlbmRlck9wdGlvbnMpIHtcbiAgICAgICAgICAgICAgICBpZiAoIWRvbU5vZGUpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHJvb3ROb2RlO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHZhciBuZXdOb2RlO1xuXG4gICAgICAgICAgICAgICAgaWYgKGlzQXJyYXkocGF0Y2hMaXN0KSkge1xuICAgICAgICAgICAgICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IHBhdGNoTGlzdC5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgICAgICAgICAgICAgbmV3Tm9kZSA9IHBhdGNoT3AocGF0Y2hMaXN0W2ldLCBkb21Ob2RlLCByZW5kZXJPcHRpb25zKTtcblxuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGRvbU5vZGUgPT09IHJvb3ROb2RlKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcm9vdE5vZGUgPSBuZXdOb2RlO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgbmV3Tm9kZSA9IHBhdGNoT3AocGF0Y2hMaXN0LCBkb21Ob2RlLCByZW5kZXJPcHRpb25zKTtcblxuICAgICAgICAgICAgICAgICAgICBpZiAoZG9tTm9kZSA9PT0gcm9vdE5vZGUpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJvb3ROb2RlID0gbmV3Tm9kZTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHJldHVybiByb290Tm9kZTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZnVuY3Rpb24gcGF0Y2hJbmRpY2VzKHBhdGNoZXMpIHtcbiAgICAgICAgICAgICAgICB2YXIgaW5kaWNlcyA9IFtdO1xuXG4gICAgICAgICAgICAgICAgZm9yICh2YXIga2V5IGluIHBhdGNoZXMpIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKGtleSAhPT0gXCJhXCIpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGluZGljZXMucHVzaChOdW1iZXIoa2V5KSk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICByZXR1cm4gaW5kaWNlcztcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSwgeyBcIi4vY3JlYXRlLWVsZW1lbnRcIjogMTUsIFwiLi9kb20taW5kZXhcIjogMTYsIFwiLi9wYXRjaC1vcFwiOiAxNywgXCJnbG9iYWwvZG9jdW1lbnRcIjogMTAsIFwieC1pcy1hcnJheVwiOiAxMiB9XSwgMTk6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICB2YXIgaXNXaWRnZXQgPSByZXF1aXJlKFwiLi4vdm5vZGUvaXMtd2lkZ2V0LmpzXCIpO1xuXG4gICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IHVwZGF0ZVdpZGdldDtcblxuICAgICAgICAgICAgZnVuY3Rpb24gdXBkYXRlV2lkZ2V0KGEsIGIpIHtcbiAgICAgICAgICAgICAgICBpZiAoaXNXaWRnZXQoYSkgJiYgaXNXaWRnZXQoYikpIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKFwibmFtZVwiIGluIGEgJiYgXCJuYW1lXCIgaW4gYikge1xuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGEuaWQgPT09IGIuaWQ7XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gYS5pbml0ID09PSBiLmluaXQ7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0sIHsgXCIuLi92bm9kZS9pcy13aWRnZXQuanNcIjogMjkgfV0sIDIwOiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge1xuICAgICAgICAgICAgXCJ1c2Ugc3RyaWN0XCI7XG5cbiAgICAgICAgICAgIHZhciBFdlN0b3JlID0gcmVxdWlyZShcImV2LXN0b3JlXCIpO1xuXG4gICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IEV2SG9vaztcblxuICAgICAgICAgICAgZnVuY3Rpb24gRXZIb29rKHZhbHVlKSB7XG4gICAgICAgICAgICAgICAgaWYgKCEodGhpcyBpbnN0YW5jZW9mIEV2SG9vaykpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIG5ldyBFdkhvb2sodmFsdWUpO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHRoaXMudmFsdWUgPSB2YWx1ZTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgRXZIb29rLnByb3RvdHlwZS5ob29rID0gZnVuY3Rpb24gKG5vZGUsIHByb3BlcnR5TmFtZSkge1xuICAgICAgICAgICAgICAgIHZhciBlcyA9IEV2U3RvcmUobm9kZSk7XG4gICAgICAgICAgICAgICAgdmFyIHByb3BOYW1lID0gcHJvcGVydHlOYW1lLnN1YnN0cigzKTtcblxuICAgICAgICAgICAgICAgIGVzW3Byb3BOYW1lXSA9IHRoaXMudmFsdWU7XG4gICAgICAgICAgICB9O1xuXG4gICAgICAgICAgICBFdkhvb2sucHJvdG90eXBlLnVuaG9vayA9IGZ1bmN0aW9uIChub2RlLCBwcm9wZXJ0eU5hbWUpIHtcbiAgICAgICAgICAgICAgICB2YXIgZXMgPSBFdlN0b3JlKG5vZGUpO1xuICAgICAgICAgICAgICAgIHZhciBwcm9wTmFtZSA9IHByb3BlcnR5TmFtZS5zdWJzdHIoMyk7XG5cbiAgICAgICAgICAgICAgICBlc1twcm9wTmFtZV0gPSB1bmRlZmluZWQ7XG4gICAgICAgICAgICB9O1xuICAgICAgICB9LCB7IFwiZXYtc3RvcmVcIjogNyB9XSwgMjE6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICBcInVzZSBzdHJpY3RcIjtcblxuICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBTb2Z0U2V0SG9vaztcblxuICAgICAgICAgICAgZnVuY3Rpb24gU29mdFNldEhvb2sodmFsdWUpIHtcbiAgICAgICAgICAgICAgICBpZiAoISh0aGlzIGluc3RhbmNlb2YgU29mdFNldEhvb2spKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBuZXcgU29mdFNldEhvb2sodmFsdWUpO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHRoaXMudmFsdWUgPSB2YWx1ZTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgU29mdFNldEhvb2sucHJvdG90eXBlLmhvb2sgPSBmdW5jdGlvbiAobm9kZSwgcHJvcGVydHlOYW1lKSB7XG4gICAgICAgICAgICAgICAgaWYgKG5vZGVbcHJvcGVydHlOYW1lXSAhPT0gdGhpcy52YWx1ZSkge1xuICAgICAgICAgICAgICAgICAgICBub2RlW3Byb3BlcnR5TmFtZV0gPSB0aGlzLnZhbHVlO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH07XG4gICAgICAgIH0sIHt9XSwgMjI6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICBcInVzZSBzdHJpY3RcIjtcblxuICAgICAgICAgICAgdmFyIGlzQXJyYXkgPSByZXF1aXJlKFwieC1pcy1hcnJheVwiKTtcblxuICAgICAgICAgICAgdmFyIFZOb2RlID0gcmVxdWlyZShcIi4uL3Zub2RlL3Zub2RlLmpzXCIpO1xuICAgICAgICAgICAgdmFyIFZUZXh0ID0gcmVxdWlyZShcIi4uL3Zub2RlL3Z0ZXh0LmpzXCIpO1xuICAgICAgICAgICAgdmFyIGlzVk5vZGUgPSByZXF1aXJlKFwiLi4vdm5vZGUvaXMtdm5vZGVcIik7XG4gICAgICAgICAgICB2YXIgaXNWVGV4dCA9IHJlcXVpcmUoXCIuLi92bm9kZS9pcy12dGV4dFwiKTtcbiAgICAgICAgICAgIHZhciBpc1dpZGdldCA9IHJlcXVpcmUoXCIuLi92bm9kZS9pcy13aWRnZXRcIik7XG4gICAgICAgICAgICB2YXIgaXNIb29rID0gcmVxdWlyZShcIi4uL3Zub2RlL2lzLXZob29rXCIpO1xuICAgICAgICAgICAgdmFyIGlzVlRodW5rID0gcmVxdWlyZShcIi4uL3Zub2RlL2lzLXRodW5rXCIpO1xuXG4gICAgICAgICAgICB2YXIgcGFyc2VUYWcgPSByZXF1aXJlKFwiLi9wYXJzZS10YWcuanNcIik7XG4gICAgICAgICAgICB2YXIgc29mdFNldEhvb2sgPSByZXF1aXJlKFwiLi9ob29rcy9zb2Z0LXNldC1ob29rLmpzXCIpO1xuICAgICAgICAgICAgdmFyIGV2SG9vayA9IHJlcXVpcmUoXCIuL2hvb2tzL2V2LWhvb2suanNcIik7XG5cbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gaDtcblxuICAgICAgICAgICAgZnVuY3Rpb24gaCh0YWdOYW1lLCBwcm9wZXJ0aWVzLCBjaGlsZHJlbikge1xuICAgICAgICAgICAgICAgIHZhciBjaGlsZE5vZGVzID0gW107XG4gICAgICAgICAgICAgICAgdmFyIHRhZywgcHJvcHMsIGtleSwgbmFtZXNwYWNlO1xuXG4gICAgICAgICAgICAgICAgaWYgKCFjaGlsZHJlbiAmJiBpc0NoaWxkcmVuKHByb3BlcnRpZXMpKSB7XG4gICAgICAgICAgICAgICAgICAgIGNoaWxkcmVuID0gcHJvcGVydGllcztcbiAgICAgICAgICAgICAgICAgICAgcHJvcHMgPSB7fTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICBwcm9wcyA9IHByb3BzIHx8IHByb3BlcnRpZXMgfHwge307XG4gICAgICAgICAgICAgICAgdGFnID0gcGFyc2VUYWcodGFnTmFtZSwgcHJvcHMpO1xuXG4gICAgICAgICAgICAgICAgLy8gc3VwcG9ydCBrZXlzXG4gICAgICAgICAgICAgICAgaWYgKHByb3BzLmhhc093blByb3BlcnR5KFwia2V5XCIpKSB7XG4gICAgICAgICAgICAgICAgICAgIGtleSA9IHByb3BzLmtleTtcbiAgICAgICAgICAgICAgICAgICAgcHJvcHMua2V5ID0gdW5kZWZpbmVkO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIC8vIHN1cHBvcnQgbmFtZXNwYWNlXG4gICAgICAgICAgICAgICAgaWYgKHByb3BzLmhhc093blByb3BlcnR5KFwibmFtZXNwYWNlXCIpKSB7XG4gICAgICAgICAgICAgICAgICAgIG5hbWVzcGFjZSA9IHByb3BzLm5hbWVzcGFjZTtcbiAgICAgICAgICAgICAgICAgICAgcHJvcHMubmFtZXNwYWNlID0gdW5kZWZpbmVkO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIC8vIGZpeCBjdXJzb3IgYnVnXG4gICAgICAgICAgICAgICAgaWYgKHRhZyA9PT0gXCJJTlBVVFwiICYmICFuYW1lc3BhY2UgJiYgcHJvcHMuaGFzT3duUHJvcGVydHkoXCJ2YWx1ZVwiKSAmJiBwcm9wcy52YWx1ZSAhPT0gdW5kZWZpbmVkICYmICFpc0hvb2socHJvcHMudmFsdWUpKSB7XG4gICAgICAgICAgICAgICAgICAgIHByb3BzLnZhbHVlID0gc29mdFNldEhvb2socHJvcHMudmFsdWUpO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHRyYW5zZm9ybVByb3BlcnRpZXMocHJvcHMpO1xuXG4gICAgICAgICAgICAgICAgaWYgKGNoaWxkcmVuICE9PSB1bmRlZmluZWQgJiYgY2hpbGRyZW4gIT09IG51bGwpIHtcbiAgICAgICAgICAgICAgICAgICAgYWRkQ2hpbGQoY2hpbGRyZW4sIGNoaWxkTm9kZXMsIHRhZywgcHJvcHMpO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHJldHVybiBuZXcgVk5vZGUodGFnLCBwcm9wcywgY2hpbGROb2Rlcywga2V5LCBuYW1lc3BhY2UpO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBmdW5jdGlvbiBhZGRDaGlsZChjLCBjaGlsZE5vZGVzLCB0YWcsIHByb3BzKSB7XG4gICAgICAgICAgICAgICAgaWYgKHR5cGVvZiBjID09PSBcInN0cmluZ1wiKSB7XG4gICAgICAgICAgICAgICAgICAgIGNoaWxkTm9kZXMucHVzaChuZXcgVlRleHQoYykpO1xuICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAodHlwZW9mIGMgPT09IFwibnVtYmVyXCIpIHtcbiAgICAgICAgICAgICAgICAgICAgY2hpbGROb2Rlcy5wdXNoKG5ldyBWVGV4dChTdHJpbmcoYykpKTtcbiAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKGlzQ2hpbGQoYykpIHtcbiAgICAgICAgICAgICAgICAgICAgY2hpbGROb2Rlcy5wdXNoKGMpO1xuICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoaXNBcnJheShjKSkge1xuICAgICAgICAgICAgICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IGMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGFkZENoaWxkKGNbaV0sIGNoaWxkTm9kZXMsIHRhZywgcHJvcHMpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfSBlbHNlIGlmIChjID09PSBudWxsIHx8IGMgPT09IHVuZGVmaW5lZCkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgdGhyb3cgVW5leHBlY3RlZFZpcnR1YWxFbGVtZW50KHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGZvcmVpZ25PYmplY3Q6IGMsXG4gICAgICAgICAgICAgICAgICAgICAgICBwYXJlbnRWbm9kZToge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRhZ05hbWU6IHRhZyxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBwcm9wZXJ0aWVzOiBwcm9wc1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIHRyYW5zZm9ybVByb3BlcnRpZXMocHJvcHMpIHtcbiAgICAgICAgICAgICAgICBmb3IgKHZhciBwcm9wTmFtZSBpbiBwcm9wcykge1xuICAgICAgICAgICAgICAgICAgICBpZiAocHJvcHMuaGFzT3duUHJvcGVydHkocHJvcE5hbWUpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICB2YXIgdmFsdWUgPSBwcm9wc1twcm9wTmFtZV07XG5cbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChpc0hvb2sodmFsdWUpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgY29udGludWU7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChwcm9wTmFtZS5zdWJzdHIoMCwgMykgPT09IFwiZXYtXCIpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBhZGQgZXYtZm9vIHN1cHBvcnRcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBwcm9wc1twcm9wTmFtZV0gPSBldkhvb2sodmFsdWUpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBmdW5jdGlvbiBpc0NoaWxkKHgpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gaXNWTm9kZSh4KSB8fCBpc1ZUZXh0KHgpIHx8IGlzV2lkZ2V0KHgpIHx8IGlzVlRodW5rKHgpO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBmdW5jdGlvbiBpc0NoaWxkcmVuKHgpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gdHlwZW9mIHggPT09IFwic3RyaW5nXCIgfHwgaXNBcnJheSh4KSB8fCBpc0NoaWxkKHgpO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBmdW5jdGlvbiBVbmV4cGVjdGVkVmlydHVhbEVsZW1lbnQoZGF0YSkge1xuICAgICAgICAgICAgICAgIHZhciBlcnIgPSBuZXcgRXJyb3IoKTtcblxuICAgICAgICAgICAgICAgIGVyci50eXBlID0gXCJ2aXJ0dWFsLWh5cGVyc2NyaXB0LnVuZXhwZWN0ZWQudmlydHVhbC1lbGVtZW50XCI7XG4gICAgICAgICAgICAgICAgZXJyLm1lc3NhZ2UgPSBcIlVuZXhwZWN0ZWQgdmlydHVhbCBjaGlsZCBwYXNzZWQgdG8gaCgpLlxcblwiICsgXCJFeHBlY3RlZCBhIFZOb2RlIC8gVnRodW5rIC8gVldpZGdldCAvIHN0cmluZyBidXQ6XFxuXCIgKyBcImdvdDpcXG5cIiArIGVycm9yU3RyaW5nKGRhdGEuZm9yZWlnbk9iamVjdCkgKyBcIi5cXG5cIiArIFwiVGhlIHBhcmVudCB2bm9kZSBpczpcXG5cIiArIGVycm9yU3RyaW5nKGRhdGEucGFyZW50Vm5vZGUpO1xuICAgICAgICAgICAgICAgIFwiXFxuXCIgKyBcIlN1Z2dlc3RlZCBmaXg6IGNoYW5nZSB5b3VyIGBoKC4uLiwgWyAuLi4gXSlgIGNhbGxzaXRlLlwiO1xuICAgICAgICAgICAgICAgIGVyci5mb3JlaWduT2JqZWN0ID0gZGF0YS5mb3JlaWduT2JqZWN0O1xuICAgICAgICAgICAgICAgIGVyci5wYXJlbnRWbm9kZSA9IGRhdGEucGFyZW50Vm5vZGU7XG5cbiAgICAgICAgICAgICAgICByZXR1cm4gZXJyO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBmdW5jdGlvbiBlcnJvclN0cmluZyhvYmopIHtcbiAgICAgICAgICAgICAgICB0cnkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gSlNPTi5zdHJpbmdpZnkob2JqLCBudWxsLCBcIiAgICBcIik7XG4gICAgICAgICAgICAgICAgfSBjYXRjaCAoZSkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gU3RyaW5nKG9iaik7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9LCB7IFwiLi4vdm5vZGUvaXMtdGh1bmtcIjogMjUsIFwiLi4vdm5vZGUvaXMtdmhvb2tcIjogMjYsIFwiLi4vdm5vZGUvaXMtdm5vZGVcIjogMjcsIFwiLi4vdm5vZGUvaXMtdnRleHRcIjogMjgsIFwiLi4vdm5vZGUvaXMtd2lkZ2V0XCI6IDI5LCBcIi4uL3Zub2RlL3Zub2RlLmpzXCI6IDMxLCBcIi4uL3Zub2RlL3Z0ZXh0LmpzXCI6IDMzLCBcIi4vaG9va3MvZXYtaG9vay5qc1wiOiAyMCwgXCIuL2hvb2tzL3NvZnQtc2V0LWhvb2suanNcIjogMjEsIFwiLi9wYXJzZS10YWcuanNcIjogMjMsIFwieC1pcy1hcnJheVwiOiAxMiB9XSwgMjM6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICBcInVzZSBzdHJpY3RcIjtcblxuICAgICAgICAgICAgdmFyIHNwbGl0ID0gcmVxdWlyZShcImJyb3dzZXItc3BsaXRcIik7XG5cbiAgICAgICAgICAgIHZhciBjbGFzc0lkU3BsaXQgPSAvKFtcXC4jXT9bYS16QS1aMC05XFx1MDA3Ri1cXHVGRkZGXzotXSspLztcbiAgICAgICAgICAgIHZhciBub3RDbGFzc0lkID0gL15cXC58Iy87XG5cbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gcGFyc2VUYWc7XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIHBhcnNlVGFnKHRhZywgcHJvcHMpIHtcbiAgICAgICAgICAgICAgICBpZiAoIXRhZykge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gXCJESVZcIjtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICB2YXIgbm9JZCA9ICFwcm9wcy5oYXNPd25Qcm9wZXJ0eShcImlkXCIpO1xuXG4gICAgICAgICAgICAgICAgdmFyIHRhZ1BhcnRzID0gc3BsaXQodGFnLCBjbGFzc0lkU3BsaXQpO1xuICAgICAgICAgICAgICAgIHZhciB0YWdOYW1lID0gbnVsbDtcblxuICAgICAgICAgICAgICAgIGlmIChub3RDbGFzc0lkLnRlc3QodGFnUGFydHNbMV0pKSB7XG4gICAgICAgICAgICAgICAgICAgIHRhZ05hbWUgPSBcIkRJVlwiO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHZhciBjbGFzc2VzLCBwYXJ0LCB0eXBlLCBpO1xuXG4gICAgICAgICAgICAgICAgZm9yIChpID0gMDsgaSA8IHRhZ1BhcnRzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICAgICAgICAgIHBhcnQgPSB0YWdQYXJ0c1tpXTtcblxuICAgICAgICAgICAgICAgICAgICBpZiAoIXBhcnQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnRpbnVlO1xuICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgdHlwZSA9IHBhcnQuY2hhckF0KDApO1xuXG4gICAgICAgICAgICAgICAgICAgIGlmICghdGFnTmFtZSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgdGFnTmFtZSA9IHBhcnQ7XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAodHlwZSA9PT0gXCIuXCIpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGNsYXNzZXMgPSBjbGFzc2VzIHx8IFtdO1xuICAgICAgICAgICAgICAgICAgICAgICAgY2xhc3Nlcy5wdXNoKHBhcnQuc3Vic3RyaW5nKDEsIHBhcnQubGVuZ3RoKSk7XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAodHlwZSA9PT0gXCIjXCIgJiYgbm9JZCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgcHJvcHMuaWQgPSBwYXJ0LnN1YnN0cmluZygxLCBwYXJ0Lmxlbmd0aCk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICBpZiAoY2xhc3Nlcykge1xuICAgICAgICAgICAgICAgICAgICBpZiAocHJvcHMuY2xhc3NOYW1lKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBjbGFzc2VzLnB1c2gocHJvcHMuY2xhc3NOYW1lKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgIHByb3BzLmNsYXNzTmFtZSA9IGNsYXNzZXMuam9pbihcIiBcIik7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgcmV0dXJuIHByb3BzLm5hbWVzcGFjZSA/IHRhZ05hbWUgOiB0YWdOYW1lLnRvVXBwZXJDYXNlKCk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0sIHsgXCJicm93c2VyLXNwbGl0XCI6IDUgfV0sIDI0OiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge1xuICAgICAgICAgICAgdmFyIGlzVk5vZGUgPSByZXF1aXJlKFwiLi9pcy12bm9kZVwiKTtcbiAgICAgICAgICAgIHZhciBpc1ZUZXh0ID0gcmVxdWlyZShcIi4vaXMtdnRleHRcIik7XG4gICAgICAgICAgICB2YXIgaXNXaWRnZXQgPSByZXF1aXJlKFwiLi9pcy13aWRnZXRcIik7XG4gICAgICAgICAgICB2YXIgaXNUaHVuayA9IHJlcXVpcmUoXCIuL2lzLXRodW5rXCIpO1xuXG4gICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IGhhbmRsZVRodW5rO1xuXG4gICAgICAgICAgICBmdW5jdGlvbiBoYW5kbGVUaHVuayhhLCBiKSB7XG4gICAgICAgICAgICAgICAgdmFyIHJlbmRlcmVkQSA9IGE7XG4gICAgICAgICAgICAgICAgdmFyIHJlbmRlcmVkQiA9IGI7XG5cbiAgICAgICAgICAgICAgICBpZiAoaXNUaHVuayhiKSkge1xuICAgICAgICAgICAgICAgICAgICByZW5kZXJlZEIgPSByZW5kZXJUaHVuayhiLCBhKTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICBpZiAoaXNUaHVuayhhKSkge1xuICAgICAgICAgICAgICAgICAgICByZW5kZXJlZEEgPSByZW5kZXJUaHVuayhhLCBudWxsKTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgICAgICAgICBhOiByZW5kZXJlZEEsXG4gICAgICAgICAgICAgICAgICAgIGI6IHJlbmRlcmVkQlxuICAgICAgICAgICAgICAgIH07XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIHJlbmRlclRodW5rKHRodW5rLCBwcmV2aW91cykge1xuICAgICAgICAgICAgICAgIHZhciByZW5kZXJlZFRodW5rID0gdGh1bmsudm5vZGU7XG5cbiAgICAgICAgICAgICAgICBpZiAoIXJlbmRlcmVkVGh1bmspIHtcbiAgICAgICAgICAgICAgICAgICAgcmVuZGVyZWRUaHVuayA9IHRodW5rLnZub2RlID0gdGh1bmsucmVuZGVyKHByZXZpb3VzKTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICBpZiAoIShpc1ZOb2RlKHJlbmRlcmVkVGh1bmspIHx8IGlzVlRleHQocmVuZGVyZWRUaHVuaykgfHwgaXNXaWRnZXQocmVuZGVyZWRUaHVuaykpKSB7XG4gICAgICAgICAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcihcInRodW5rIGRpZCBub3QgcmV0dXJuIGEgdmFsaWQgbm9kZVwiKTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICByZXR1cm4gcmVuZGVyZWRUaHVuaztcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSwgeyBcIi4vaXMtdGh1bmtcIjogMjUsIFwiLi9pcy12bm9kZVwiOiAyNywgXCIuL2lzLXZ0ZXh0XCI6IDI4LCBcIi4vaXMtd2lkZ2V0XCI6IDI5IH1dLCAyNTogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHtcbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gaXNUaHVuaztcblxuICAgICAgICAgICAgZnVuY3Rpb24gaXNUaHVuayh0KSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHQgJiYgdC50eXBlID09PSBcIlRodW5rXCI7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0sIHt9XSwgMjY6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IGlzSG9vaztcblxuICAgICAgICAgICAgZnVuY3Rpb24gaXNIb29rKGhvb2spIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gaG9vayAmJiAodHlwZW9mIGhvb2suaG9vayA9PT0gXCJmdW5jdGlvblwiICYmICFob29rLmhhc093blByb3BlcnR5KFwiaG9va1wiKSB8fCB0eXBlb2YgaG9vay51bmhvb2sgPT09IFwiZnVuY3Rpb25cIiAmJiAhaG9vay5oYXNPd25Qcm9wZXJ0eShcInVuaG9va1wiKSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0sIHt9XSwgMjc6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICB2YXIgdmVyc2lvbiA9IHJlcXVpcmUoXCIuL3ZlcnNpb25cIik7XG5cbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gaXNWaXJ0dWFsTm9kZTtcblxuICAgICAgICAgICAgZnVuY3Rpb24gaXNWaXJ0dWFsTm9kZSh4KSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHggJiYgeC50eXBlID09PSBcIlZpcnR1YWxOb2RlXCIgJiYgeC52ZXJzaW9uID09PSB2ZXJzaW9uO1xuICAgICAgICAgICAgfVxuICAgICAgICB9LCB7IFwiLi92ZXJzaW9uXCI6IDMwIH1dLCAyODogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHtcbiAgICAgICAgICAgIHZhciB2ZXJzaW9uID0gcmVxdWlyZShcIi4vdmVyc2lvblwiKTtcblxuICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBpc1ZpcnR1YWxUZXh0O1xuXG4gICAgICAgICAgICBmdW5jdGlvbiBpc1ZpcnR1YWxUZXh0KHgpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4geCAmJiB4LnR5cGUgPT09IFwiVmlydHVhbFRleHRcIiAmJiB4LnZlcnNpb24gPT09IHZlcnNpb247XG4gICAgICAgICAgICB9XG4gICAgICAgIH0sIHsgXCIuL3ZlcnNpb25cIjogMzAgfV0sIDI5OiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge1xuICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBpc1dpZGdldDtcblxuICAgICAgICAgICAgZnVuY3Rpb24gaXNXaWRnZXQodykge1xuICAgICAgICAgICAgICAgIHJldHVybiB3ICYmIHcudHlwZSA9PT0gXCJXaWRnZXRcIjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSwge31dLCAzMDogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHtcbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gXCIyXCI7XG4gICAgICAgIH0sIHt9XSwgMzE6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICB2YXIgdmVyc2lvbiA9IHJlcXVpcmUoXCIuL3ZlcnNpb25cIik7XG4gICAgICAgICAgICB2YXIgaXNWTm9kZSA9IHJlcXVpcmUoXCIuL2lzLXZub2RlXCIpO1xuICAgICAgICAgICAgdmFyIGlzV2lkZ2V0ID0gcmVxdWlyZShcIi4vaXMtd2lkZ2V0XCIpO1xuICAgICAgICAgICAgdmFyIGlzVGh1bmsgPSByZXF1aXJlKFwiLi9pcy10aHVua1wiKTtcbiAgICAgICAgICAgIHZhciBpc1ZIb29rID0gcmVxdWlyZShcIi4vaXMtdmhvb2tcIik7XG5cbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gVmlydHVhbE5vZGU7XG5cbiAgICAgICAgICAgIHZhciBub1Byb3BlcnRpZXMgPSB7fTtcbiAgICAgICAgICAgIHZhciBub0NoaWxkcmVuID0gW107XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIFZpcnR1YWxOb2RlKHRhZ05hbWUsIHByb3BlcnRpZXMsIGNoaWxkcmVuLCBrZXksIG5hbWVzcGFjZSkge1xuICAgICAgICAgICAgICAgIHRoaXMudGFnTmFtZSA9IHRhZ05hbWU7XG4gICAgICAgICAgICAgICAgdGhpcy5wcm9wZXJ0aWVzID0gcHJvcGVydGllcyB8fCBub1Byb3BlcnRpZXM7XG4gICAgICAgICAgICAgICAgdGhpcy5jaGlsZHJlbiA9IGNoaWxkcmVuIHx8IG5vQ2hpbGRyZW47XG4gICAgICAgICAgICAgICAgdGhpcy5rZXkgPSBrZXkgIT0gbnVsbCA/IFN0cmluZyhrZXkpIDogdW5kZWZpbmVkO1xuICAgICAgICAgICAgICAgIHRoaXMubmFtZXNwYWNlID0gdHlwZW9mIG5hbWVzcGFjZSA9PT0gXCJzdHJpbmdcIiA/IG5hbWVzcGFjZSA6IG51bGw7XG5cbiAgICAgICAgICAgICAgICB2YXIgY291bnQgPSBjaGlsZHJlbiAmJiBjaGlsZHJlbi5sZW5ndGggfHwgMDtcbiAgICAgICAgICAgICAgICB2YXIgZGVzY2VuZGFudHMgPSAwO1xuICAgICAgICAgICAgICAgIHZhciBoYXNXaWRnZXRzID0gZmFsc2U7XG4gICAgICAgICAgICAgICAgdmFyIGhhc1RodW5rcyA9IGZhbHNlO1xuICAgICAgICAgICAgICAgIHZhciBkZXNjZW5kYW50SG9va3MgPSBmYWxzZTtcbiAgICAgICAgICAgICAgICB2YXIgaG9va3M7XG5cbiAgICAgICAgICAgICAgICBmb3IgKHZhciBwcm9wTmFtZSBpbiBwcm9wZXJ0aWVzKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmIChwcm9wZXJ0aWVzLmhhc093blByb3BlcnR5KHByb3BOYW1lKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgdmFyIHByb3BlcnR5ID0gcHJvcGVydGllc1twcm9wTmFtZV07XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoaXNWSG9vayhwcm9wZXJ0eSkgJiYgcHJvcGVydHkudW5ob29rKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKCFob29rcykge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBob29rcyA9IHt9O1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGhvb2tzW3Byb3BOYW1lXSA9IHByb3BlcnR5O1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCBjb3VudDsgaSsrKSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciBjaGlsZCA9IGNoaWxkcmVuW2ldO1xuICAgICAgICAgICAgICAgICAgICBpZiAoaXNWTm9kZShjaGlsZCkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGRlc2NlbmRhbnRzICs9IGNoaWxkLmNvdW50IHx8IDA7XG5cbiAgICAgICAgICAgICAgICAgICAgICAgIGlmICghaGFzV2lkZ2V0cyAmJiBjaGlsZC5oYXNXaWRnZXRzKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaGFzV2lkZ2V0cyA9IHRydWU7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgICAgIGlmICghaGFzVGh1bmtzICYmIGNoaWxkLmhhc1RodW5rcykge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGhhc1RodW5rcyA9IHRydWU7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgICAgIGlmICghZGVzY2VuZGFudEhvb2tzICYmIChjaGlsZC5ob29rcyB8fCBjaGlsZC5kZXNjZW5kYW50SG9va3MpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgZGVzY2VuZGFudEhvb2tzID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIGlmICghaGFzV2lkZ2V0cyAmJiBpc1dpZGdldChjaGlsZCkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmICh0eXBlb2YgY2hpbGQuZGVzdHJveSA9PT0gXCJmdW5jdGlvblwiKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaGFzV2lkZ2V0cyA9IHRydWU7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoIWhhc1RodW5rcyAmJiBpc1RodW5rKGNoaWxkKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgaGFzVGh1bmtzID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHRoaXMuY291bnQgPSBjb3VudCArIGRlc2NlbmRhbnRzO1xuICAgICAgICAgICAgICAgIHRoaXMuaGFzV2lkZ2V0cyA9IGhhc1dpZGdldHM7XG4gICAgICAgICAgICAgICAgdGhpcy5oYXNUaHVua3MgPSBoYXNUaHVua3M7XG4gICAgICAgICAgICAgICAgdGhpcy5ob29rcyA9IGhvb2tzO1xuICAgICAgICAgICAgICAgIHRoaXMuZGVzY2VuZGFudEhvb2tzID0gZGVzY2VuZGFudEhvb2tzO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBWaXJ0dWFsTm9kZS5wcm90b3R5cGUudmVyc2lvbiA9IHZlcnNpb247XG4gICAgICAgICAgICBWaXJ0dWFsTm9kZS5wcm90b3R5cGUudHlwZSA9IFwiVmlydHVhbE5vZGVcIjtcbiAgICAgICAgfSwgeyBcIi4vaXMtdGh1bmtcIjogMjUsIFwiLi9pcy12aG9va1wiOiAyNiwgXCIuL2lzLXZub2RlXCI6IDI3LCBcIi4vaXMtd2lkZ2V0XCI6IDI5LCBcIi4vdmVyc2lvblwiOiAzMCB9XSwgMzI6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICB2YXIgdmVyc2lvbiA9IHJlcXVpcmUoXCIuL3ZlcnNpb25cIik7XG5cbiAgICAgICAgICAgIFZpcnR1YWxQYXRjaC5OT05FID0gMDtcbiAgICAgICAgICAgIFZpcnR1YWxQYXRjaC5WVEVYVCA9IDE7XG4gICAgICAgICAgICBWaXJ0dWFsUGF0Y2guVk5PREUgPSAyO1xuICAgICAgICAgICAgVmlydHVhbFBhdGNoLldJREdFVCA9IDM7XG4gICAgICAgICAgICBWaXJ0dWFsUGF0Y2guUFJPUFMgPSA0O1xuICAgICAgICAgICAgVmlydHVhbFBhdGNoLk9SREVSID0gNTtcbiAgICAgICAgICAgIFZpcnR1YWxQYXRjaC5JTlNFUlQgPSA2O1xuICAgICAgICAgICAgVmlydHVhbFBhdGNoLlJFTU9WRSA9IDc7XG4gICAgICAgICAgICBWaXJ0dWFsUGF0Y2guVEhVTksgPSA4O1xuXG4gICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IFZpcnR1YWxQYXRjaDtcblxuICAgICAgICAgICAgZnVuY3Rpb24gVmlydHVhbFBhdGNoKHR5cGUsIHZOb2RlLCBwYXRjaCkge1xuICAgICAgICAgICAgICAgIHRoaXMudHlwZSA9IE51bWJlcih0eXBlKTtcbiAgICAgICAgICAgICAgICB0aGlzLnZOb2RlID0gdk5vZGU7XG4gICAgICAgICAgICAgICAgdGhpcy5wYXRjaCA9IHBhdGNoO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBWaXJ0dWFsUGF0Y2gucHJvdG90eXBlLnZlcnNpb24gPSB2ZXJzaW9uO1xuICAgICAgICAgICAgVmlydHVhbFBhdGNoLnByb3RvdHlwZS50eXBlID0gXCJWaXJ0dWFsUGF0Y2hcIjtcbiAgICAgICAgfSwgeyBcIi4vdmVyc2lvblwiOiAzMCB9XSwgMzM6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICB2YXIgdmVyc2lvbiA9IHJlcXVpcmUoXCIuL3ZlcnNpb25cIik7XG5cbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gVmlydHVhbFRleHQ7XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIFZpcnR1YWxUZXh0KHRleHQpIHtcbiAgICAgICAgICAgICAgICB0aGlzLnRleHQgPSBTdHJpbmcodGV4dCk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIFZpcnR1YWxUZXh0LnByb3RvdHlwZS52ZXJzaW9uID0gdmVyc2lvbjtcbiAgICAgICAgICAgIFZpcnR1YWxUZXh0LnByb3RvdHlwZS50eXBlID0gXCJWaXJ0dWFsVGV4dFwiO1xuICAgICAgICB9LCB7IFwiLi92ZXJzaW9uXCI6IDMwIH1dLCAzNDogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHtcbiAgICAgICAgICAgIHZhciBpc09iamVjdCA9IHJlcXVpcmUoXCJpcy1vYmplY3RcIik7XG4gICAgICAgICAgICB2YXIgaXNIb29rID0gcmVxdWlyZShcIi4uL3Zub2RlL2lzLXZob29rXCIpO1xuXG4gICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IGRpZmZQcm9wcztcblxuICAgICAgICAgICAgZnVuY3Rpb24gZGlmZlByb3BzKGEsIGIpIHtcbiAgICAgICAgICAgICAgICB2YXIgZGlmZjtcblxuICAgICAgICAgICAgICAgIGZvciAodmFyIGFLZXkgaW4gYSkge1xuICAgICAgICAgICAgICAgICAgICBpZiAoIShhS2V5IGluIGIpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBkaWZmID0gZGlmZiB8fCB7fTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGRpZmZbYUtleV0gPSB1bmRlZmluZWQ7XG4gICAgICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgICAgICB2YXIgYVZhbHVlID0gYVthS2V5XTtcbiAgICAgICAgICAgICAgICAgICAgdmFyIGJWYWx1ZSA9IGJbYUtleV07XG5cbiAgICAgICAgICAgICAgICAgICAgaWYgKGFWYWx1ZSA9PT0gYlZhbHVlKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBjb250aW51ZTtcbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIGlmIChpc09iamVjdChhVmFsdWUpICYmIGlzT2JqZWN0KGJWYWx1ZSkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChnZXRQcm90b3R5cGUoYlZhbHVlKSAhPT0gZ2V0UHJvdG90eXBlKGFWYWx1ZSkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBkaWZmID0gZGlmZiB8fCB7fTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBkaWZmW2FLZXldID0gYlZhbHVlO1xuICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIGlmIChpc0hvb2soYlZhbHVlKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRpZmYgPSBkaWZmIHx8IHt9O1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRpZmZbYUtleV0gPSBiVmFsdWU7XG4gICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZhciBvYmplY3REaWZmID0gZGlmZlByb3BzKGFWYWx1ZSwgYlZhbHVlKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAob2JqZWN0RGlmZikge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBkaWZmID0gZGlmZiB8fCB7fTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZGlmZlthS2V5XSA9IG9iamVjdERpZmY7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgZGlmZiA9IGRpZmYgfHwge307XG4gICAgICAgICAgICAgICAgICAgICAgICBkaWZmW2FLZXldID0gYlZhbHVlO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgZm9yICh2YXIgYktleSBpbiBiKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmICghKGJLZXkgaW4gYSkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGRpZmYgPSBkaWZmIHx8IHt9O1xuICAgICAgICAgICAgICAgICAgICAgICAgZGlmZltiS2V5XSA9IGJbYktleV07XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICByZXR1cm4gZGlmZjtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZnVuY3Rpb24gZ2V0UHJvdG90eXBlKHZhbHVlKSB7XG4gICAgICAgICAgICAgICAgaWYgKE9iamVjdC5nZXRQcm90b3R5cGVPZikge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gT2JqZWN0LmdldFByb3RvdHlwZU9mKHZhbHVlKTtcbiAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKHZhbHVlLl9fcHJvdG9fXykge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gdmFsdWUuX19wcm90b19fO1xuICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAodmFsdWUuY29uc3RydWN0b3IpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHZhbHVlLmNvbnN0cnVjdG9yLnByb3RvdHlwZTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH0sIHsgXCIuLi92bm9kZS9pcy12aG9va1wiOiAyNiwgXCJpcy1vYmplY3RcIjogMTEgfV0sIDM1OiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge1xuICAgICAgICAgICAgdmFyIGlzQXJyYXkgPSByZXF1aXJlKFwieC1pcy1hcnJheVwiKTtcblxuICAgICAgICAgICAgdmFyIFZQYXRjaCA9IHJlcXVpcmUoXCIuLi92bm9kZS92cGF0Y2hcIik7XG4gICAgICAgICAgICB2YXIgaXNWTm9kZSA9IHJlcXVpcmUoXCIuLi92bm9kZS9pcy12bm9kZVwiKTtcbiAgICAgICAgICAgIHZhciBpc1ZUZXh0ID0gcmVxdWlyZShcIi4uL3Zub2RlL2lzLXZ0ZXh0XCIpO1xuICAgICAgICAgICAgdmFyIGlzV2lkZ2V0ID0gcmVxdWlyZShcIi4uL3Zub2RlL2lzLXdpZGdldFwiKTtcbiAgICAgICAgICAgIHZhciBpc1RodW5rID0gcmVxdWlyZShcIi4uL3Zub2RlL2lzLXRodW5rXCIpO1xuICAgICAgICAgICAgdmFyIGhhbmRsZVRodW5rID0gcmVxdWlyZShcIi4uL3Zub2RlL2hhbmRsZS10aHVua1wiKTtcblxuICAgICAgICAgICAgdmFyIGRpZmZQcm9wcyA9IHJlcXVpcmUoXCIuL2RpZmYtcHJvcHNcIik7XG5cbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gZGlmZjtcblxuICAgICAgICAgICAgZnVuY3Rpb24gZGlmZihhLCBiKSB7XG4gICAgICAgICAgICAgICAgdmFyIHBhdGNoID0geyBhOiBhIH07XG4gICAgICAgICAgICAgICAgd2FsayhhLCBiLCBwYXRjaCwgMCk7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHBhdGNoO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBmdW5jdGlvbiB3YWxrKGEsIGIsIHBhdGNoLCBpbmRleCkge1xuICAgICAgICAgICAgICAgIGlmIChhID09PSBiKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICB2YXIgYXBwbHkgPSBwYXRjaFtpbmRleF07XG4gICAgICAgICAgICAgICAgdmFyIGFwcGx5Q2xlYXIgPSBmYWxzZTtcblxuICAgICAgICAgICAgICAgIGlmIChpc1RodW5rKGEpIHx8IGlzVGh1bmsoYikpIHtcbiAgICAgICAgICAgICAgICAgICAgdGh1bmtzKGEsIGIsIHBhdGNoLCBpbmRleCk7XG4gICAgICAgICAgICAgICAgfSBlbHNlIGlmIChiID09IG51bGwpIHtcblxuICAgICAgICAgICAgICAgICAgICAvLyBJZiBhIGlzIGEgd2lkZ2V0IHdlIHdpbGwgYWRkIGEgcmVtb3ZlIHBhdGNoIGZvciBpdFxuICAgICAgICAgICAgICAgICAgICAvLyBPdGhlcndpc2UgYW55IGNoaWxkIHdpZGdldHMvaG9va3MgbXVzdCBiZSBkZXN0cm95ZWQuXG4gICAgICAgICAgICAgICAgICAgIC8vIFRoaXMgcHJldmVudHMgYWRkaW5nIHR3byByZW1vdmUgcGF0Y2hlcyBmb3IgYSB3aWRnZXQuXG4gICAgICAgICAgICAgICAgICAgIGlmICghaXNXaWRnZXQoYSkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGNsZWFyU3RhdGUoYSwgcGF0Y2gsIGluZGV4KTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGFwcGx5ID0gcGF0Y2hbaW5kZXhdO1xuICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgYXBwbHkgPSBhcHBlbmRQYXRjaChhcHBseSwgbmV3IFZQYXRjaChWUGF0Y2guUkVNT1ZFLCBhLCBiKSk7XG4gICAgICAgICAgICAgICAgfSBlbHNlIGlmIChpc1ZOb2RlKGIpKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmIChpc1ZOb2RlKGEpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoYS50YWdOYW1lID09PSBiLnRhZ05hbWUgJiYgYS5uYW1lc3BhY2UgPT09IGIubmFtZXNwYWNlICYmIGEua2V5ID09PSBiLmtleSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZhciBwcm9wc1BhdGNoID0gZGlmZlByb3BzKGEucHJvcGVydGllcywgYi5wcm9wZXJ0aWVzKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAocHJvcHNQYXRjaCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBhcHBseSA9IGFwcGVuZFBhdGNoKGFwcGx5LCBuZXcgVlBhdGNoKFZQYXRjaC5QUk9QUywgYSwgcHJvcHNQYXRjaCkpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBhcHBseSA9IGRpZmZDaGlsZHJlbihhLCBiLCBwYXRjaCwgYXBwbHksIGluZGV4KTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgYXBwbHkgPSBhcHBlbmRQYXRjaChhcHBseSwgbmV3IFZQYXRjaChWUGF0Y2guVk5PREUsIGEsIGIpKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBhcHBseUNsZWFyID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGFwcGx5ID0gYXBwZW5kUGF0Y2goYXBwbHksIG5ldyBWUGF0Y2goVlBhdGNoLlZOT0RFLCBhLCBiKSk7XG4gICAgICAgICAgICAgICAgICAgICAgICBhcHBseUNsZWFyID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoaXNWVGV4dChiKSkge1xuICAgICAgICAgICAgICAgICAgICBpZiAoIWlzVlRleHQoYSkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGFwcGx5ID0gYXBwZW5kUGF0Y2goYXBwbHksIG5ldyBWUGF0Y2goVlBhdGNoLlZURVhULCBhLCBiKSk7XG4gICAgICAgICAgICAgICAgICAgICAgICBhcHBseUNsZWFyID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIGlmIChhLnRleHQgIT09IGIudGV4dCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgYXBwbHkgPSBhcHBlbmRQYXRjaChhcHBseSwgbmV3IFZQYXRjaChWUGF0Y2guVlRFWFQsIGEsIGIpKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoaXNXaWRnZXQoYikpIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKCFpc1dpZGdldChhKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgYXBwbHlDbGVhciA9IHRydWU7XG4gICAgICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgICAgICBhcHBseSA9IGFwcGVuZFBhdGNoKGFwcGx5LCBuZXcgVlBhdGNoKFZQYXRjaC5XSURHRVQsIGEsIGIpKTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICBpZiAoYXBwbHkpIHtcbiAgICAgICAgICAgICAgICAgICAgcGF0Y2hbaW5kZXhdID0gYXBwbHk7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgaWYgKGFwcGx5Q2xlYXIpIHtcbiAgICAgICAgICAgICAgICAgICAgY2xlYXJTdGF0ZShhLCBwYXRjaCwgaW5kZXgpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZnVuY3Rpb24gZGlmZkNoaWxkcmVuKGEsIGIsIHBhdGNoLCBhcHBseSwgaW5kZXgpIHtcbiAgICAgICAgICAgICAgICB2YXIgYUNoaWxkcmVuID0gYS5jaGlsZHJlbjtcbiAgICAgICAgICAgICAgICB2YXIgb3JkZXJlZFNldCA9IHJlb3JkZXIoYUNoaWxkcmVuLCBiLmNoaWxkcmVuKTtcbiAgICAgICAgICAgICAgICB2YXIgYkNoaWxkcmVuID0gb3JkZXJlZFNldC5jaGlsZHJlbjtcblxuICAgICAgICAgICAgICAgIHZhciBhTGVuID0gYUNoaWxkcmVuLmxlbmd0aDtcbiAgICAgICAgICAgICAgICB2YXIgYkxlbiA9IGJDaGlsZHJlbi5sZW5ndGg7XG4gICAgICAgICAgICAgICAgdmFyIGxlbiA9IGFMZW4gPiBiTGVuID8gYUxlbiA6IGJMZW47XG5cbiAgICAgICAgICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IGxlbjsgaSsrKSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciBsZWZ0Tm9kZSA9IGFDaGlsZHJlbltpXTtcbiAgICAgICAgICAgICAgICAgICAgdmFyIHJpZ2h0Tm9kZSA9IGJDaGlsZHJlbltpXTtcbiAgICAgICAgICAgICAgICAgICAgaW5kZXggKz0gMTtcblxuICAgICAgICAgICAgICAgICAgICBpZiAoIWxlZnROb2RlKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAocmlnaHROb2RlKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gRXhjZXNzIG5vZGVzIGluIGIgbmVlZCB0byBiZSBhZGRlZFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGFwcGx5ID0gYXBwZW5kUGF0Y2goYXBwbHksIG5ldyBWUGF0Y2goVlBhdGNoLklOU0VSVCwgbnVsbCwgcmlnaHROb2RlKSk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICB3YWxrKGxlZnROb2RlLCByaWdodE5vZGUsIHBhdGNoLCBpbmRleCk7XG4gICAgICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgICAgICBpZiAoaXNWTm9kZShsZWZ0Tm9kZSkgJiYgbGVmdE5vZGUuY291bnQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGluZGV4ICs9IGxlZnROb2RlLmNvdW50O1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgaWYgKG9yZGVyZWRTZXQubW92ZXMpIHtcbiAgICAgICAgICAgICAgICAgICAgLy8gUmVvcmRlciBub2RlcyBsYXN0XG4gICAgICAgICAgICAgICAgICAgIGFwcGx5ID0gYXBwZW5kUGF0Y2goYXBwbHksIG5ldyBWUGF0Y2goVlBhdGNoLk9SREVSLCBhLCBvcmRlcmVkU2V0Lm1vdmVzKSk7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgcmV0dXJuIGFwcGx5O1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBmdW5jdGlvbiBjbGVhclN0YXRlKHZOb2RlLCBwYXRjaCwgaW5kZXgpIHtcbiAgICAgICAgICAgICAgICAvLyBUT0RPOiBNYWtlIHRoaXMgYSBzaW5nbGUgd2Fsaywgbm90IHR3b1xuICAgICAgICAgICAgICAgIHVuaG9vayh2Tm9kZSwgcGF0Y2gsIGluZGV4KTtcbiAgICAgICAgICAgICAgICBkZXN0cm95V2lkZ2V0cyh2Tm9kZSwgcGF0Y2gsIGluZGV4KTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgLy8gUGF0Y2ggcmVjb3JkcyBmb3IgYWxsIGRlc3Ryb3llZCB3aWRnZXRzIG11c3QgYmUgYWRkZWQgYmVjYXVzZSB3ZSBuZWVkXG4gICAgICAgICAgICAvLyBhIERPTSBub2RlIHJlZmVyZW5jZSBmb3IgdGhlIGRlc3Ryb3kgZnVuY3Rpb25cbiAgICAgICAgICAgIGZ1bmN0aW9uIGRlc3Ryb3lXaWRnZXRzKHZOb2RlLCBwYXRjaCwgaW5kZXgpIHtcbiAgICAgICAgICAgICAgICBpZiAoaXNXaWRnZXQodk5vZGUpKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmICh0eXBlb2Ygdk5vZGUuZGVzdHJveSA9PT0gXCJmdW5jdGlvblwiKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBwYXRjaFtpbmRleF0gPSBhcHBlbmRQYXRjaChwYXRjaFtpbmRleF0sIG5ldyBWUGF0Y2goVlBhdGNoLlJFTU9WRSwgdk5vZGUsIG51bGwpKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoaXNWTm9kZSh2Tm9kZSkgJiYgKHZOb2RlLmhhc1dpZGdldHMgfHwgdk5vZGUuaGFzVGh1bmtzKSkge1xuICAgICAgICAgICAgICAgICAgICB2YXIgY2hpbGRyZW4gPSB2Tm9kZS5jaGlsZHJlbjtcbiAgICAgICAgICAgICAgICAgICAgdmFyIGxlbiA9IGNoaWxkcmVuLmxlbmd0aDtcbiAgICAgICAgICAgICAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCBsZW47IGkrKykge1xuICAgICAgICAgICAgICAgICAgICAgICAgdmFyIGNoaWxkID0gY2hpbGRyZW5baV07XG4gICAgICAgICAgICAgICAgICAgICAgICBpbmRleCArPSAxO1xuXG4gICAgICAgICAgICAgICAgICAgICAgICBkZXN0cm95V2lkZ2V0cyhjaGlsZCwgcGF0Y2gsIGluZGV4KTtcblxuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGlzVk5vZGUoY2hpbGQpICYmIGNoaWxkLmNvdW50KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaW5kZXggKz0gY2hpbGQuY291bnQ7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKGlzVGh1bmsodk5vZGUpKSB7XG4gICAgICAgICAgICAgICAgICAgIHRodW5rcyh2Tm9kZSwgbnVsbCwgcGF0Y2gsIGluZGV4KTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIC8vIENyZWF0ZSBhIHN1Yi1wYXRjaCBmb3IgdGh1bmtzXG4gICAgICAgICAgICBmdW5jdGlvbiB0aHVua3MoYSwgYiwgcGF0Y2gsIGluZGV4KSB7XG4gICAgICAgICAgICAgICAgdmFyIG5vZGVzID0gaGFuZGxlVGh1bmsoYSwgYik7XG4gICAgICAgICAgICAgICAgdmFyIHRodW5rUGF0Y2ggPSBkaWZmKG5vZGVzLmEsIG5vZGVzLmIpO1xuICAgICAgICAgICAgICAgIGlmIChoYXNQYXRjaGVzKHRodW5rUGF0Y2gpKSB7XG4gICAgICAgICAgICAgICAgICAgIHBhdGNoW2luZGV4XSA9IG5ldyBWUGF0Y2goVlBhdGNoLlRIVU5LLCBudWxsLCB0aHVua1BhdGNoKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIGhhc1BhdGNoZXMocGF0Y2gpIHtcbiAgICAgICAgICAgICAgICBmb3IgKHZhciBpbmRleCBpbiBwYXRjaCkge1xuICAgICAgICAgICAgICAgICAgICBpZiAoaW5kZXggIT09IFwiYVwiKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgLy8gRXhlY3V0ZSBob29rcyB3aGVuIHR3byBub2RlcyBhcmUgaWRlbnRpY2FsXG4gICAgICAgICAgICBmdW5jdGlvbiB1bmhvb2sodk5vZGUsIHBhdGNoLCBpbmRleCkge1xuICAgICAgICAgICAgICAgIGlmIChpc1ZOb2RlKHZOb2RlKSkge1xuICAgICAgICAgICAgICAgICAgICBpZiAodk5vZGUuaG9va3MpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHBhdGNoW2luZGV4XSA9IGFwcGVuZFBhdGNoKHBhdGNoW2luZGV4XSwgbmV3IFZQYXRjaChWUGF0Y2guUFJPUFMsIHZOb2RlLCB1bmRlZmluZWRLZXlzKHZOb2RlLmhvb2tzKSkpO1xuICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgaWYgKHZOb2RlLmRlc2NlbmRhbnRIb29rcyB8fCB2Tm9kZS5oYXNUaHVua3MpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHZhciBjaGlsZHJlbiA9IHZOb2RlLmNoaWxkcmVuO1xuICAgICAgICAgICAgICAgICAgICAgICAgdmFyIGxlbiA9IGNoaWxkcmVuLmxlbmd0aDtcbiAgICAgICAgICAgICAgICAgICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgbGVuOyBpKyspIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB2YXIgY2hpbGQgPSBjaGlsZHJlbltpXTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpbmRleCArPSAxO1xuXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdW5ob29rKGNoaWxkLCBwYXRjaCwgaW5kZXgpO1xuXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGlzVk5vZGUoY2hpbGQpICYmIGNoaWxkLmNvdW50KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGluZGV4ICs9IGNoaWxkLmNvdW50O1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoaXNUaHVuayh2Tm9kZSkpIHtcbiAgICAgICAgICAgICAgICAgICAgdGh1bmtzKHZOb2RlLCBudWxsLCBwYXRjaCwgaW5kZXgpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZnVuY3Rpb24gdW5kZWZpbmVkS2V5cyhvYmopIHtcbiAgICAgICAgICAgICAgICB2YXIgcmVzdWx0ID0ge307XG5cbiAgICAgICAgICAgICAgICBmb3IgKHZhciBrZXkgaW4gb2JqKSB7XG4gICAgICAgICAgICAgICAgICAgIHJlc3VsdFtrZXldID0gdW5kZWZpbmVkO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHJldHVybiByZXN1bHQ7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIC8vIExpc3QgZGlmZiwgbmFpdmUgbGVmdCB0byByaWdodCByZW9yZGVyaW5nXG4gICAgICAgICAgICBmdW5jdGlvbiByZW9yZGVyKGFDaGlsZHJlbiwgYkNoaWxkcmVuKSB7XG4gICAgICAgICAgICAgICAgLy8gTyhNKSB0aW1lLCBPKE0pIG1lbW9yeVxuICAgICAgICAgICAgICAgIHZhciBiQ2hpbGRJbmRleCA9IGtleUluZGV4KGJDaGlsZHJlbik7XG4gICAgICAgICAgICAgICAgdmFyIGJLZXlzID0gYkNoaWxkSW5kZXgua2V5cztcbiAgICAgICAgICAgICAgICB2YXIgYkZyZWUgPSBiQ2hpbGRJbmRleC5mcmVlO1xuXG4gICAgICAgICAgICAgICAgaWYgKGJGcmVlLmxlbmd0aCA9PT0gYkNoaWxkcmVuLmxlbmd0aCkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgICAgICAgICAgICAgY2hpbGRyZW46IGJDaGlsZHJlbixcbiAgICAgICAgICAgICAgICAgICAgICAgIG1vdmVzOiBudWxsXG4gICAgICAgICAgICAgICAgICAgIH07XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgLy8gTyhOKSB0aW1lLCBPKE4pIG1lbW9yeVxuICAgICAgICAgICAgICAgIHZhciBhQ2hpbGRJbmRleCA9IGtleUluZGV4KGFDaGlsZHJlbik7XG4gICAgICAgICAgICAgICAgdmFyIGFLZXlzID0gYUNoaWxkSW5kZXgua2V5cztcbiAgICAgICAgICAgICAgICB2YXIgYUZyZWUgPSBhQ2hpbGRJbmRleC5mcmVlO1xuXG4gICAgICAgICAgICAgICAgaWYgKGFGcmVlLmxlbmd0aCA9PT0gYUNoaWxkcmVuLmxlbmd0aCkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgICAgICAgICAgICAgY2hpbGRyZW46IGJDaGlsZHJlbixcbiAgICAgICAgICAgICAgICAgICAgICAgIG1vdmVzOiBudWxsXG4gICAgICAgICAgICAgICAgICAgIH07XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgLy8gTyhNQVgoTiwgTSkpIG1lbW9yeVxuICAgICAgICAgICAgICAgIHZhciBuZXdDaGlsZHJlbiA9IFtdO1xuXG4gICAgICAgICAgICAgICAgdmFyIGZyZWVJbmRleCA9IDA7XG4gICAgICAgICAgICAgICAgdmFyIGZyZWVDb3VudCA9IGJGcmVlLmxlbmd0aDtcbiAgICAgICAgICAgICAgICB2YXIgZGVsZXRlZEl0ZW1zID0gMDtcblxuICAgICAgICAgICAgICAgIC8vIEl0ZXJhdGUgdGhyb3VnaCBhIGFuZCBtYXRjaCBhIG5vZGUgaW4gYlxuICAgICAgICAgICAgICAgIC8vIE8oTikgdGltZSxcbiAgICAgICAgICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IGFDaGlsZHJlbi5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgICAgICAgICB2YXIgYUl0ZW0gPSBhQ2hpbGRyZW5baV07XG4gICAgICAgICAgICAgICAgICAgIHZhciBpdGVtSW5kZXg7XG5cbiAgICAgICAgICAgICAgICAgICAgaWYgKGFJdGVtLmtleSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGJLZXlzLmhhc093blByb3BlcnR5KGFJdGVtLmtleSkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBNYXRjaCB1cCB0aGUgb2xkIGtleXNcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpdGVtSW5kZXggPSBiS2V5c1thSXRlbS5rZXldO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIG5ld0NoaWxkcmVuLnB1c2goYkNoaWxkcmVuW2l0ZW1JbmRleF0pO1xuICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBSZW1vdmUgb2xkIGtleWVkIGl0ZW1zXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaXRlbUluZGV4ID0gaSAtIGRlbGV0ZWRJdGVtcysrO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIG5ld0NoaWxkcmVuLnB1c2gobnVsbCk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAvLyBNYXRjaCB0aGUgaXRlbSBpbiBhIHdpdGggdGhlIG5leHQgZnJlZSBpdGVtIGluIGJcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChmcmVlSW5kZXggPCBmcmVlQ291bnQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpdGVtSW5kZXggPSBiRnJlZVtmcmVlSW5kZXgrK107XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgbmV3Q2hpbGRyZW4ucHVzaChiQ2hpbGRyZW5baXRlbUluZGV4XSk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIFRoZXJlIGFyZSBubyBmcmVlIGl0ZW1zIGluIGIgdG8gbWF0Y2ggd2l0aFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIHRoZSBmcmVlIGl0ZW1zIGluIGEsIHNvIHRoZSBleHRyYSBmcmVlIG5vZGVzXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gYXJlIGRlbGV0ZWQuXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaXRlbUluZGV4ID0gaSAtIGRlbGV0ZWRJdGVtcysrO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIG5ld0NoaWxkcmVuLnB1c2gobnVsbCk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICB2YXIgbGFzdEZyZWVJbmRleCA9IGZyZWVJbmRleCA+PSBiRnJlZS5sZW5ndGggPyBiQ2hpbGRyZW4ubGVuZ3RoIDogYkZyZWVbZnJlZUluZGV4XTtcblxuICAgICAgICAgICAgICAgIC8vIEl0ZXJhdGUgdGhyb3VnaCBiIGFuZCBhcHBlbmQgYW55IG5ldyBrZXlzXG4gICAgICAgICAgICAgICAgLy8gTyhNKSB0aW1lXG4gICAgICAgICAgICAgICAgZm9yICh2YXIgaiA9IDA7IGogPCBiQ2hpbGRyZW4ubGVuZ3RoOyBqKyspIHtcbiAgICAgICAgICAgICAgICAgICAgdmFyIG5ld0l0ZW0gPSBiQ2hpbGRyZW5bal07XG5cbiAgICAgICAgICAgICAgICAgICAgaWYgKG5ld0l0ZW0ua2V5KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoIWFLZXlzLmhhc093blByb3BlcnR5KG5ld0l0ZW0ua2V5KSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIEFkZCBhbnkgbmV3IGtleWVkIGl0ZW1zXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gV2UgYXJlIGFkZGluZyBuZXcgaXRlbXMgdG8gdGhlIGVuZCBhbmQgdGhlbiBzb3J0aW5nIHRoZW1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBpbiBwbGFjZS4gSW4gZnV0dXJlIHdlIHNob3VsZCBpbnNlcnQgbmV3IGl0ZW1zIGluIHBsYWNlLlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIG5ld0NoaWxkcmVuLnB1c2gobmV3SXRlbSk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoaiA+PSBsYXN0RnJlZUluZGV4KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAvLyBBZGQgYW55IGxlZnRvdmVyIG5vbi1rZXllZCBpdGVtc1xuICAgICAgICAgICAgICAgICAgICAgICAgbmV3Q2hpbGRyZW4ucHVzaChuZXdJdGVtKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHZhciBzaW11bGF0ZSA9IG5ld0NoaWxkcmVuLnNsaWNlKCk7XG4gICAgICAgICAgICAgICAgdmFyIHNpbXVsYXRlSW5kZXggPSAwO1xuICAgICAgICAgICAgICAgIHZhciByZW1vdmVzID0gW107XG4gICAgICAgICAgICAgICAgdmFyIGluc2VydHMgPSBbXTtcbiAgICAgICAgICAgICAgICB2YXIgc2ltdWxhdGVJdGVtO1xuXG4gICAgICAgICAgICAgICAgZm9yICh2YXIgayA9IDA7IGsgPCBiQ2hpbGRyZW4ubGVuZ3RoOykge1xuICAgICAgICAgICAgICAgICAgICB2YXIgd2FudGVkSXRlbSA9IGJDaGlsZHJlbltrXTtcbiAgICAgICAgICAgICAgICAgICAgc2ltdWxhdGVJdGVtID0gc2ltdWxhdGVbc2ltdWxhdGVJbmRleF07XG5cbiAgICAgICAgICAgICAgICAgICAgLy8gcmVtb3ZlIGl0ZW1zXG4gICAgICAgICAgICAgICAgICAgIHdoaWxlIChzaW11bGF0ZUl0ZW0gPT09IG51bGwgJiYgc2ltdWxhdGUubGVuZ3RoKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICByZW1vdmVzLnB1c2gocmVtb3ZlKHNpbXVsYXRlLCBzaW11bGF0ZUluZGV4LCBudWxsKSk7XG4gICAgICAgICAgICAgICAgICAgICAgICBzaW11bGF0ZUl0ZW0gPSBzaW11bGF0ZVtzaW11bGF0ZUluZGV4XTtcbiAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgIGlmICghc2ltdWxhdGVJdGVtIHx8IHNpbXVsYXRlSXRlbS5rZXkgIT09IHdhbnRlZEl0ZW0ua2V5KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAvLyBpZiB3ZSBuZWVkIGEga2V5IGluIHRoaXMgcG9zaXRpb24uLi5cbiAgICAgICAgICAgICAgICAgICAgICAgIGlmICh3YW50ZWRJdGVtLmtleSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChzaW11bGF0ZUl0ZW0gJiYgc2ltdWxhdGVJdGVtLmtleSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBpZiBhbiBpbnNlcnQgZG9lc24ndCBwdXQgdGhpcyBrZXkgaW4gcGxhY2UsIGl0IG5lZWRzIHRvIG1vdmVcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGJLZXlzW3NpbXVsYXRlSXRlbS5rZXldICE9PSBrICsgMSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmVtb3Zlcy5wdXNoKHJlbW92ZShzaW11bGF0ZSwgc2ltdWxhdGVJbmRleCwgc2ltdWxhdGVJdGVtLmtleSkpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc2ltdWxhdGVJdGVtID0gc2ltdWxhdGVbc2ltdWxhdGVJbmRleF07XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBpZiB0aGUgcmVtb3ZlIGRpZG4ndCBwdXQgdGhlIHdhbnRlZCBpdGVtIGluIHBsYWNlLCB3ZSBuZWVkIHRvIGluc2VydCBpdFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKCFzaW11bGF0ZUl0ZW0gfHwgc2ltdWxhdGVJdGVtLmtleSAhPT0gd2FudGVkSXRlbS5rZXkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpbnNlcnRzLnB1c2goeyBrZXk6IHdhbnRlZEl0ZW0ua2V5LCB0bzogayB9KTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIGl0ZW1zIGFyZSBtYXRjaGluZywgc28gc2tpcCBhaGVhZFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc2ltdWxhdGVJbmRleCsrO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaW5zZXJ0cy5wdXNoKHsga2V5OiB3YW50ZWRJdGVtLmtleSwgdG86IGsgfSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpbnNlcnRzLnB1c2goeyBrZXk6IHdhbnRlZEl0ZW0ua2V5LCB0bzogayB9KTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaysrO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgLy8gYSBrZXkgaW4gc2ltdWxhdGUgaGFzIG5vIG1hdGNoaW5nIHdhbnRlZCBrZXksIHJlbW92ZSBpdFxuICAgICAgICAgICAgICAgICAgICAgICAgZWxzZSBpZiAoc2ltdWxhdGVJdGVtICYmIHNpbXVsYXRlSXRlbS5rZXkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICByZW1vdmVzLnB1c2gocmVtb3ZlKHNpbXVsYXRlLCBzaW11bGF0ZUluZGV4LCBzaW11bGF0ZUl0ZW0ua2V5KSk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBzaW11bGF0ZUluZGV4Kys7XG4gICAgICAgICAgICAgICAgICAgICAgICBrKys7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAvLyByZW1vdmUgYWxsIHRoZSByZW1haW5pbmcgbm9kZXMgZnJvbSBzaW11bGF0ZVxuICAgICAgICAgICAgICAgIHdoaWxlIChzaW11bGF0ZUluZGV4IDwgc2ltdWxhdGUubGVuZ3RoKSB7XG4gICAgICAgICAgICAgICAgICAgIHNpbXVsYXRlSXRlbSA9IHNpbXVsYXRlW3NpbXVsYXRlSW5kZXhdO1xuICAgICAgICAgICAgICAgICAgICByZW1vdmVzLnB1c2gocmVtb3ZlKHNpbXVsYXRlLCBzaW11bGF0ZUluZGV4LCBzaW11bGF0ZUl0ZW0gJiYgc2ltdWxhdGVJdGVtLmtleSkpO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIC8vIElmIHRoZSBvbmx5IG1vdmVzIHdlIGhhdmUgYXJlIGRlbGV0ZXMgdGhlbiB3ZSBjYW4ganVzdFxuICAgICAgICAgICAgICAgIC8vIGxldCB0aGUgZGVsZXRlIHBhdGNoIHJlbW92ZSB0aGVzZSBpdGVtcy5cbiAgICAgICAgICAgICAgICBpZiAocmVtb3Zlcy5sZW5ndGggPT09IGRlbGV0ZWRJdGVtcyAmJiAhaW5zZXJ0cy5sZW5ndGgpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGNoaWxkcmVuOiBuZXdDaGlsZHJlbixcbiAgICAgICAgICAgICAgICAgICAgICAgIG1vdmVzOiBudWxsXG4gICAgICAgICAgICAgICAgICAgIH07XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgICAgICAgICAgY2hpbGRyZW46IG5ld0NoaWxkcmVuLFxuICAgICAgICAgICAgICAgICAgICBtb3Zlczoge1xuICAgICAgICAgICAgICAgICAgICAgICAgcmVtb3ZlczogcmVtb3ZlcyxcbiAgICAgICAgICAgICAgICAgICAgICAgIGluc2VydHM6IGluc2VydHNcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH07XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIHJlbW92ZShhcnIsIGluZGV4LCBrZXkpIHtcbiAgICAgICAgICAgICAgICBhcnIuc3BsaWNlKGluZGV4LCAxKTtcblxuICAgICAgICAgICAgICAgIHJldHVybiB7XG4gICAgICAgICAgICAgICAgICAgIGZyb206IGluZGV4LFxuICAgICAgICAgICAgICAgICAgICBrZXk6IGtleVxuICAgICAgICAgICAgICAgIH07XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIGtleUluZGV4KGNoaWxkcmVuKSB7XG4gICAgICAgICAgICAgICAgdmFyIGtleXMgPSB7fTtcbiAgICAgICAgICAgICAgICB2YXIgZnJlZSA9IFtdO1xuICAgICAgICAgICAgICAgIHZhciBsZW5ndGggPSBjaGlsZHJlbi5sZW5ndGg7XG5cbiAgICAgICAgICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IGxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciBjaGlsZCA9IGNoaWxkcmVuW2ldO1xuXG4gICAgICAgICAgICAgICAgICAgIGlmIChjaGlsZC5rZXkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGtleXNbY2hpbGQua2V5XSA9IGk7XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBmcmVlLnB1c2goaSk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgICAgICAgICBrZXlzOiBrZXlzLCAvLyBBIGhhc2ggb2Yga2V5IG5hbWUgdG8gaW5kZXhcbiAgICAgICAgICAgICAgICAgICAgZnJlZTogZnJlZSAvLyBBbiBhcnJheSBvZiB1bmtleWVkIGl0ZW0gaW5kaWNlc1xuICAgICAgICAgICAgICAgIH07XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIGFwcGVuZFBhdGNoKGFwcGx5LCBwYXRjaCkge1xuICAgICAgICAgICAgICAgIGlmIChhcHBseSkge1xuICAgICAgICAgICAgICAgICAgICBpZiAoaXNBcnJheShhcHBseSkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGFwcGx5LnB1c2gocGF0Y2gpO1xuICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgYXBwbHkgPSBbYXBwbHksIHBhdGNoXTtcbiAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBhcHBseTtcbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gcGF0Y2g7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9LCB7IFwiLi4vdm5vZGUvaGFuZGxlLXRodW5rXCI6IDI0LCBcIi4uL3Zub2RlL2lzLXRodW5rXCI6IDI1LCBcIi4uL3Zub2RlL2lzLXZub2RlXCI6IDI3LCBcIi4uL3Zub2RlL2lzLXZ0ZXh0XCI6IDI4LCBcIi4uL3Zub2RlL2lzLXdpZGdldFwiOiAyOSwgXCIuLi92bm9kZS92cGF0Y2hcIjogMzIsIFwiLi9kaWZmLXByb3BzXCI6IDM0LCBcIngtaXMtYXJyYXlcIjogMTIgfV0gfSwge30sIFs0XSkoNCk7XG59KTtcblxuY29uc3QgQ29yZSA9IEM7XG5cbmV4cG9ydCB7IENvcmUsIEVudW0sIFZpcnR1YWxET00gfTsiXSwiZmlsZSI6IkVsaXhpci5qcyIsInNvdXJjZVJvb3QiOiIvc291cmNlLyJ9 \ No newline at end of file +export default Elixir; +//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiIiwic291cmNlcyI6WyJFbGl4aXIuanMiXSwic291cmNlc0NvbnRlbnQiOlsibGV0IFZpcnR1YWxET00gPSAoZnVuY3Rpb24gKGUpIHtcbiAgICByZXR1cm4gZSgpO1xufSkoZnVuY3Rpb24gKCkge1xuICAgIHZhciBkZWZpbmUsIG1vZHVsZSwgZXhwb3J0cztcbiAgICByZXR1cm4gKGZ1bmN0aW9uIGUodCwgbiwgcikge1xuICAgICAgICBmdW5jdGlvbiBzKG8sIHUpIHtcbiAgICAgICAgICAgIGlmICghbltvXSkge1xuICAgICAgICAgICAgICAgIGlmICghdFtvXSkge1xuICAgICAgICAgICAgICAgICAgICB2YXIgYSA9IHR5cGVvZiByZXF1aXJlID09IFwiZnVuY3Rpb25cIiAmJiByZXF1aXJlO1xuICAgICAgICAgICAgICAgICAgICBpZiAoIXUgJiYgYSkgcmV0dXJuIGEobywgITApO1xuICAgICAgICAgICAgICAgICAgICBpZiAoaSkgcmV0dXJuIGkobywgITApO1xuICAgICAgICAgICAgICAgICAgICB2YXIgZiA9IG5ldyBFcnJvcihcIkNhbm5vdCBmaW5kIG1vZHVsZSAnXCIgKyBvICsgXCInXCIpO1xuICAgICAgICAgICAgICAgICAgICB0aHJvdyAoZi5jb2RlID0gXCJNT0RVTEVfTk9UX0ZPVU5EXCIsIGYpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB2YXIgbCA9IG5bb10gPSB7XG4gICAgICAgICAgICAgICAgICAgIGV4cG9ydHM6IHt9XG4gICAgICAgICAgICAgICAgfTtcbiAgICAgICAgICAgICAgICB0W29dWzBdLmNhbGwobC5leHBvcnRzLCBmdW5jdGlvbiAoZSkge1xuICAgICAgICAgICAgICAgICAgICB2YXIgbiA9IHRbb11bMV1bZV07XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBzKG4gPyBuIDogZSk7XG4gICAgICAgICAgICAgICAgfSwgbCwgbC5leHBvcnRzLCBlLCB0LCBuLCByKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJldHVybiBuW29dLmV4cG9ydHM7XG4gICAgICAgIH1cbiAgICAgICAgdmFyIGkgPSB0eXBlb2YgcmVxdWlyZSA9PSBcImZ1bmN0aW9uXCIgJiYgcmVxdWlyZTtcbiAgICAgICAgZm9yICh2YXIgbyA9IDA7IG8gPCByLmxlbmd0aDsgbysrKSBzKHJbb10pO1xuICAgICAgICByZXR1cm4gcztcbiAgICB9KSh7XG4gICAgICAgIDE6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG5cbiAgICAgICAgICAgIHZhciBjcmVhdGVFbGVtZW50ID0gcmVxdWlyZShcIi4vdmRvbS9jcmVhdGUtZWxlbWVudC5qc1wiKTtcblxuICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBjcmVhdGVFbGVtZW50O1xuICAgICAgICB9LCB7IFwiLi92ZG9tL2NyZWF0ZS1lbGVtZW50LmpzXCI6IDE1IH1dLCAyOiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge1xuICAgICAgICAgICAgdmFyIGRpZmYgPSByZXF1aXJlKFwiLi92dHJlZS9kaWZmLmpzXCIpO1xuXG4gICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IGRpZmY7XG4gICAgICAgIH0sIHsgXCIuL3Z0cmVlL2RpZmYuanNcIjogMzUgfV0sIDM6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICB2YXIgaCA9IHJlcXVpcmUoXCIuL3ZpcnR1YWwtaHlwZXJzY3JpcHQvaW5kZXguanNcIik7XG5cbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gaDtcbiAgICAgICAgfSwgeyBcIi4vdmlydHVhbC1oeXBlcnNjcmlwdC9pbmRleC5qc1wiOiAyMiB9XSwgNDogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHtcbiAgICAgICAgICAgIHZhciBkaWZmID0gcmVxdWlyZShcIi4vZGlmZi5qc1wiKTtcbiAgICAgICAgICAgIHZhciBwYXRjaCA9IHJlcXVpcmUoXCIuL3BhdGNoLmpzXCIpO1xuICAgICAgICAgICAgdmFyIGggPSByZXF1aXJlKFwiLi9oLmpzXCIpO1xuICAgICAgICAgICAgdmFyIGNyZWF0ZSA9IHJlcXVpcmUoXCIuL2NyZWF0ZS1lbGVtZW50LmpzXCIpO1xuICAgICAgICAgICAgdmFyIFZOb2RlID0gcmVxdWlyZShcIi4vdm5vZGUvdm5vZGUuanNcIik7XG4gICAgICAgICAgICB2YXIgVlRleHQgPSByZXF1aXJlKFwiLi92bm9kZS92dGV4dC5qc1wiKTtcblxuICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSB7XG4gICAgICAgICAgICAgICAgZGlmZjogZGlmZixcbiAgICAgICAgICAgICAgICBwYXRjaDogcGF0Y2gsXG4gICAgICAgICAgICAgICAgaDogaCxcbiAgICAgICAgICAgICAgICBjcmVhdGU6IGNyZWF0ZSxcbiAgICAgICAgICAgICAgICBWTm9kZTogVk5vZGUsXG4gICAgICAgICAgICAgICAgVlRleHQ6IFZUZXh0XG4gICAgICAgICAgICB9O1xuICAgICAgICB9LCB7IFwiLi9jcmVhdGUtZWxlbWVudC5qc1wiOiAxLCBcIi4vZGlmZi5qc1wiOiAyLCBcIi4vaC5qc1wiOiAzLCBcIi4vcGF0Y2guanNcIjogMTMsIFwiLi92bm9kZS92bm9kZS5qc1wiOiAzMSwgXCIuL3Zub2RlL3Z0ZXh0LmpzXCI6IDMzIH1dLCA1OiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge1xuICAgICAgICAgICAgLyohXG4gICAgICAgICAgICAgKiBDcm9zcy1Ccm93c2VyIFNwbGl0IDEuMS4xXG4gICAgICAgICAgICAgKiBDb3B5cmlnaHQgMjAwNy0yMDEyIFN0ZXZlbiBMZXZpdGhhbiA8c3RldmVubGV2aXRoYW4uY29tPlxuICAgICAgICAgICAgICogQXZhaWxhYmxlIHVuZGVyIHRoZSBNSVQgTGljZW5zZVxuICAgICAgICAgICAgICogRUNNQVNjcmlwdCBjb21wbGlhbnQsIHVuaWZvcm0gY3Jvc3MtYnJvd3NlciBzcGxpdCBtZXRob2RcbiAgICAgICAgICAgICAqL1xuXG4gICAgICAgICAgICAvKipcbiAgICAgICAgICAgICAqIFNwbGl0cyBhIHN0cmluZyBpbnRvIGFuIGFycmF5IG9mIHN0cmluZ3MgdXNpbmcgYSByZWdleCBvciBzdHJpbmcgc2VwYXJhdG9yLiBNYXRjaGVzIG9mIHRoZVxuICAgICAgICAgICAgICogc2VwYXJhdG9yIGFyZSBub3QgaW5jbHVkZWQgaW4gdGhlIHJlc3VsdCBhcnJheS4gSG93ZXZlciwgaWYgYHNlcGFyYXRvcmAgaXMgYSByZWdleCB0aGF0IGNvbnRhaW5zXG4gICAgICAgICAgICAgKiBjYXB0dXJpbmcgZ3JvdXBzLCBiYWNrcmVmZXJlbmNlcyBhcmUgc3BsaWNlZCBpbnRvIHRoZSByZXN1bHQgZWFjaCB0aW1lIGBzZXBhcmF0b3JgIGlzIG1hdGNoZWQuXG4gICAgICAgICAgICAgKiBGaXhlcyBicm93c2VyIGJ1Z3MgY29tcGFyZWQgdG8gdGhlIG5hdGl2ZSBgU3RyaW5nLnByb3RvdHlwZS5zcGxpdGAgYW5kIGNhbiBiZSB1c2VkIHJlbGlhYmx5XG4gICAgICAgICAgICAgKiBjcm9zcy1icm93c2VyLlxuICAgICAgICAgICAgICogQHBhcmFtIHtTdHJpbmd9IHN0ciBTdHJpbmcgdG8gc3BsaXQuXG4gICAgICAgICAgICAgKiBAcGFyYW0ge1JlZ0V4cHxTdHJpbmd9IHNlcGFyYXRvciBSZWdleCBvciBzdHJpbmcgdG8gdXNlIGZvciBzZXBhcmF0aW5nIHRoZSBzdHJpbmcuXG4gICAgICAgICAgICAgKiBAcGFyYW0ge051bWJlcn0gW2xpbWl0XSBNYXhpbXVtIG51bWJlciBvZiBpdGVtcyB0byBpbmNsdWRlIGluIHRoZSByZXN1bHQgYXJyYXkuXG4gICAgICAgICAgICAgKiBAcmV0dXJucyB7QXJyYXl9IEFycmF5IG9mIHN1YnN0cmluZ3MuXG4gICAgICAgICAgICAgKiBAZXhhbXBsZVxuICAgICAgICAgICAgICpcbiAgICAgICAgICAgICAqIC8vIEJhc2ljIHVzZVxuICAgICAgICAgICAgICogc3BsaXQoJ2EgYiBjIGQnLCAnICcpO1xuICAgICAgICAgICAgICogLy8gLT4gWydhJywgJ2InLCAnYycsICdkJ11cbiAgICAgICAgICAgICAqXG4gICAgICAgICAgICAgKiAvLyBXaXRoIGxpbWl0XG4gICAgICAgICAgICAgKiBzcGxpdCgnYSBiIGMgZCcsICcgJywgMik7XG4gICAgICAgICAgICAgKiAvLyAtPiBbJ2EnLCAnYiddXG4gICAgICAgICAgICAgKlxuICAgICAgICAgICAgICogLy8gQmFja3JlZmVyZW5jZXMgaW4gcmVzdWx0IGFycmF5XG4gICAgICAgICAgICAgKiBzcGxpdCgnLi53b3JkMSB3b3JkMi4uJywgLyhbYS16XSspKFxcZCspL2kpO1xuICAgICAgICAgICAgICogLy8gLT4gWycuLicsICd3b3JkJywgJzEnLCAnICcsICd3b3JkJywgJzInLCAnLi4nXVxuICAgICAgICAgICAgICovXG4gICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IChmdW5jdGlvbiBzcGxpdCh1bmRlZikge1xuXG4gICAgICAgICAgICAgICAgdmFyIG5hdGl2ZVNwbGl0ID0gU3RyaW5nLnByb3RvdHlwZS5zcGxpdCxcbiAgICAgICAgICAgICAgICAgICAgY29tcGxpYW50RXhlY05wY2cgPSAvKCk/Py8uZXhlYyhcIlwiKVsxXSA9PT0gdW5kZWYsXG5cbiAgICAgICAgICAgICAgICAvLyBOUENHOiBub25wYXJ0aWNpcGF0aW5nIGNhcHR1cmluZyBncm91cFxuICAgICAgICAgICAgICAgIHNlbGY7XG5cbiAgICAgICAgICAgICAgICBzZWxmID0gZnVuY3Rpb24gKHN0ciwgc2VwYXJhdG9yLCBsaW1pdCkge1xuICAgICAgICAgICAgICAgICAgICAvLyBJZiBgc2VwYXJhdG9yYCBpcyBub3QgYSByZWdleCwgdXNlIGBuYXRpdmVTcGxpdGBcbiAgICAgICAgICAgICAgICAgICAgaWYgKE9iamVjdC5wcm90b3R5cGUudG9TdHJpbmcuY2FsbChzZXBhcmF0b3IpICE9PSBcIltvYmplY3QgUmVnRXhwXVwiKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gbmF0aXZlU3BsaXQuY2FsbChzdHIsIHNlcGFyYXRvciwgbGltaXQpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIHZhciBvdXRwdXQgPSBbXSxcbiAgICAgICAgICAgICAgICAgICAgICAgIGZsYWdzID0gKHNlcGFyYXRvci5pZ25vcmVDYXNlID8gXCJpXCIgOiBcIlwiKSArIChzZXBhcmF0b3IubXVsdGlsaW5lID8gXCJtXCIgOiBcIlwiKSArIChzZXBhcmF0b3IuZXh0ZW5kZWQgPyBcInhcIiA6IFwiXCIpICsgKHNlcGFyYXRvci5zdGlja3kgPyBcInlcIiA6IFwiXCIpLFxuXG4gICAgICAgICAgICAgICAgICAgIC8vIEZpcmVmb3ggMytcbiAgICAgICAgICAgICAgICAgICAgbGFzdExhc3RJbmRleCA9IDAsXG5cbiAgICAgICAgICAgICAgICAgICAgLy8gTWFrZSBgZ2xvYmFsYCBhbmQgYXZvaWQgYGxhc3RJbmRleGAgaXNzdWVzIGJ5IHdvcmtpbmcgd2l0aCBhIGNvcHlcbiAgICAgICAgICAgICAgICAgICAgc2VwYXJhdG9yID0gbmV3IFJlZ0V4cChzZXBhcmF0b3Iuc291cmNlLCBmbGFncyArIFwiZ1wiKSxcbiAgICAgICAgICAgICAgICAgICAgICAgIHNlcGFyYXRvcjIsXG4gICAgICAgICAgICAgICAgICAgICAgICBtYXRjaCxcbiAgICAgICAgICAgICAgICAgICAgICAgIGxhc3RJbmRleCxcbiAgICAgICAgICAgICAgICAgICAgICAgIGxhc3RMZW5ndGg7XG4gICAgICAgICAgICAgICAgICAgIHN0ciArPSBcIlwiOyAvLyBUeXBlLWNvbnZlcnRcbiAgICAgICAgICAgICAgICAgICAgaWYgKCFjb21wbGlhbnRFeGVjTnBjZykge1xuICAgICAgICAgICAgICAgICAgICAgICAgLy8gRG9lc24ndCBuZWVkIGZsYWdzIGd5LCBidXQgdGhleSBkb24ndCBodXJ0XG4gICAgICAgICAgICAgICAgICAgICAgICBzZXBhcmF0b3IyID0gbmV3IFJlZ0V4cChcIl5cIiArIHNlcGFyYXRvci5zb3VyY2UgKyBcIiQoPyFcXFxccylcIiwgZmxhZ3MpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIC8qIFZhbHVlcyBmb3IgYGxpbWl0YCwgcGVyIHRoZSBzcGVjOlxuICAgICAgICAgICAgICAgICAgICAgKiBJZiB1bmRlZmluZWQ6IDQyOTQ5NjcyOTUgLy8gTWF0aC5wb3coMiwgMzIpIC0gMVxuICAgICAgICAgICAgICAgICAgICAgKiBJZiAwLCBJbmZpbml0eSwgb3IgTmFOOiAwXG4gICAgICAgICAgICAgICAgICAgICAqIElmIHBvc2l0aXZlIG51bWJlcjogbGltaXQgPSBNYXRoLmZsb29yKGxpbWl0KTsgaWYgKGxpbWl0ID4gNDI5NDk2NzI5NSkgbGltaXQgLT0gNDI5NDk2NzI5NjtcbiAgICAgICAgICAgICAgICAgICAgICogSWYgbmVnYXRpdmUgbnVtYmVyOiA0Mjk0OTY3Mjk2IC0gTWF0aC5mbG9vcihNYXRoLmFicyhsaW1pdCkpXG4gICAgICAgICAgICAgICAgICAgICAqIElmIG90aGVyOiBUeXBlLWNvbnZlcnQsIHRoZW4gdXNlIHRoZSBhYm92ZSBydWxlc1xuICAgICAgICAgICAgICAgICAgICAgKi9cbiAgICAgICAgICAgICAgICAgICAgbGltaXQgPSBsaW1pdCA9PT0gdW5kZWYgPyAtMSA+Pj4gMCA6IC8vIE1hdGgucG93KDIsIDMyKSAtIDFcbiAgICAgICAgICAgICAgICAgICAgbGltaXQgPj4+IDA7IC8vIFRvVWludDMyKGxpbWl0KVxuICAgICAgICAgICAgICAgICAgICB3aGlsZSAobWF0Y2ggPSBzZXBhcmF0b3IuZXhlYyhzdHIpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAvLyBgc2VwYXJhdG9yLmxhc3RJbmRleGAgaXMgbm90IHJlbGlhYmxlIGNyb3NzLWJyb3dzZXJcbiAgICAgICAgICAgICAgICAgICAgICAgIGxhc3RJbmRleCA9IG1hdGNoLmluZGV4ICsgbWF0Y2hbMF0ubGVuZ3RoO1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGxhc3RJbmRleCA+IGxhc3RMYXN0SW5kZXgpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBvdXRwdXQucHVzaChzdHIuc2xpY2UobGFzdExhc3RJbmRleCwgbWF0Y2guaW5kZXgpKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBGaXggYnJvd3NlcnMgd2hvc2UgYGV4ZWNgIG1ldGhvZHMgZG9uJ3QgY29uc2lzdGVudGx5IHJldHVybiBgdW5kZWZpbmVkYCBmb3JcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBub25wYXJ0aWNpcGF0aW5nIGNhcHR1cmluZyBncm91cHNcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoIWNvbXBsaWFudEV4ZWNOcGNnICYmIG1hdGNoLmxlbmd0aCA+IDEpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbWF0Y2hbMF0ucmVwbGFjZShzZXBhcmF0b3IyLCBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBmb3IgKHZhciBpID0gMTsgaSA8IGFyZ3VtZW50cy5sZW5ndGggLSAyOyBpKyspIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoYXJndW1lbnRzW2ldID09PSB1bmRlZikge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBtYXRjaFtpXSA9IHVuZGVmO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChtYXRjaC5sZW5ndGggPiAxICYmIG1hdGNoLmluZGV4IDwgc3RyLmxlbmd0aCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBBcnJheS5wcm90b3R5cGUucHVzaC5hcHBseShvdXRwdXQsIG1hdGNoLnNsaWNlKDEpKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgbGFzdExlbmd0aCA9IG1hdGNoWzBdLmxlbmd0aDtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBsYXN0TGFzdEluZGV4ID0gbGFzdEluZGV4O1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChvdXRwdXQubGVuZ3RoID49IGxpbWl0KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChzZXBhcmF0b3IubGFzdEluZGV4ID09PSBtYXRjaC5pbmRleCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNlcGFyYXRvci5sYXN0SW5kZXgrKzsgLy8gQXZvaWQgYW4gaW5maW5pdGUgbG9vcFxuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIGlmIChsYXN0TGFzdEluZGV4ID09PSBzdHIubGVuZ3RoKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAobGFzdExlbmd0aCB8fCAhc2VwYXJhdG9yLnRlc3QoXCJcIikpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBvdXRwdXQucHVzaChcIlwiKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIG91dHB1dC5wdXNoKHN0ci5zbGljZShsYXN0TGFzdEluZGV4KSk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIG91dHB1dC5sZW5ndGggPiBsaW1pdCA/IG91dHB1dC5zbGljZSgwLCBsaW1pdCkgOiBvdXRwdXQ7XG4gICAgICAgICAgICAgICAgfTtcblxuICAgICAgICAgICAgICAgIHJldHVybiBzZWxmO1xuICAgICAgICAgICAgfSkoKTtcbiAgICAgICAgfSwge31dLCA2OiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge30sIHt9XSwgNzogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHtcbiAgICAgICAgICAgIFwidXNlIHN0cmljdFwiO1xuXG4gICAgICAgICAgICB2YXIgT25lVmVyc2lvbkNvbnN0cmFpbnQgPSByZXF1aXJlKFwiaW5kaXZpZHVhbC9vbmUtdmVyc2lvblwiKTtcblxuICAgICAgICAgICAgdmFyIE1ZX1ZFUlNJT04gPSBcIjdcIjtcbiAgICAgICAgICAgIE9uZVZlcnNpb25Db25zdHJhaW50KFwiZXYtc3RvcmVcIiwgTVlfVkVSU0lPTik7XG5cbiAgICAgICAgICAgIHZhciBoYXNoS2V5ID0gXCJfX0VWX1NUT1JFX0tFWUBcIiArIE1ZX1ZFUlNJT047XG5cbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gRXZTdG9yZTtcblxuICAgICAgICAgICAgZnVuY3Rpb24gRXZTdG9yZShlbGVtKSB7XG4gICAgICAgICAgICAgICAgdmFyIGhhc2ggPSBlbGVtW2hhc2hLZXldO1xuXG4gICAgICAgICAgICAgICAgaWYgKCFoYXNoKSB7XG4gICAgICAgICAgICAgICAgICAgIGhhc2ggPSBlbGVtW2hhc2hLZXldID0ge307XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgcmV0dXJuIGhhc2g7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0sIHsgXCJpbmRpdmlkdWFsL29uZS12ZXJzaW9uXCI6IDkgfV0sIDg6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICAoZnVuY3Rpb24gKGdsb2JhbCkge1xuICAgICAgICAgICAgICAgIFwidXNlIHN0cmljdFwiO1xuXG4gICAgICAgICAgICAgICAgLypnbG9iYWwgd2luZG93LCBnbG9iYWwqL1xuXG4gICAgICAgICAgICAgICAgdmFyIHJvb3QgPSB0eXBlb2Ygd2luZG93ICE9PSBcInVuZGVmaW5lZFwiID8gd2luZG93IDogdHlwZW9mIGdsb2JhbCAhPT0gXCJ1bmRlZmluZWRcIiA/IGdsb2JhbCA6IHt9O1xuXG4gICAgICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBJbmRpdmlkdWFsO1xuXG4gICAgICAgICAgICAgICAgZnVuY3Rpb24gSW5kaXZpZHVhbChrZXksIHZhbHVlKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmIChrZXkgaW4gcm9vdCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHJvb3Rba2V5XTtcbiAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgIHJvb3Rba2V5XSA9IHZhbHVlO1xuXG4gICAgICAgICAgICAgICAgICAgIHJldHVybiB2YWx1ZTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9KS5jYWxsKHRoaXMsIHR5cGVvZiBnbG9iYWwgIT09IFwidW5kZWZpbmVkXCIgPyBnbG9iYWwgOiB0eXBlb2Ygc2VsZiAhPT0gXCJ1bmRlZmluZWRcIiA/IHNlbGYgOiB0eXBlb2Ygd2luZG93ICE9PSBcInVuZGVmaW5lZFwiID8gd2luZG93IDoge30pO1xuICAgICAgICB9LCB7fV0sIDk6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICBcInVzZSBzdHJpY3RcIjtcblxuICAgICAgICAgICAgdmFyIEluZGl2aWR1YWwgPSByZXF1aXJlKFwiLi9pbmRleC5qc1wiKTtcblxuICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBPbmVWZXJzaW9uO1xuXG4gICAgICAgICAgICBmdW5jdGlvbiBPbmVWZXJzaW9uKG1vZHVsZU5hbWUsIHZlcnNpb24sIGRlZmF1bHRWYWx1ZSkge1xuICAgICAgICAgICAgICAgIHZhciBrZXkgPSBcIl9fSU5ESVZJRFVBTF9PTkVfVkVSU0lPTl9cIiArIG1vZHVsZU5hbWU7XG4gICAgICAgICAgICAgICAgdmFyIGVuZm9yY2VLZXkgPSBrZXkgKyBcIl9FTkZPUkNFX1NJTkdMRVRPTlwiO1xuXG4gICAgICAgICAgICAgICAgdmFyIHZlcnNpb25WYWx1ZSA9IEluZGl2aWR1YWwoZW5mb3JjZUtleSwgdmVyc2lvbik7XG5cbiAgICAgICAgICAgICAgICBpZiAodmVyc2lvblZhbHVlICE9PSB2ZXJzaW9uKSB7XG4gICAgICAgICAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcihcIkNhbiBvbmx5IGhhdmUgb25lIGNvcHkgb2YgXCIgKyBtb2R1bGVOYW1lICsgXCIuXFxuXCIgKyBcIllvdSBhbHJlYWR5IGhhdmUgdmVyc2lvbiBcIiArIHZlcnNpb25WYWx1ZSArIFwiIGluc3RhbGxlZC5cXG5cIiArIFwiVGhpcyBtZWFucyB5b3UgY2Fubm90IGluc3RhbGwgdmVyc2lvbiBcIiArIHZlcnNpb24pO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHJldHVybiBJbmRpdmlkdWFsKGtleSwgZGVmYXVsdFZhbHVlKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSwgeyBcIi4vaW5kZXguanNcIjogOCB9XSwgMTA6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICAoZnVuY3Rpb24gKGdsb2JhbCkge1xuICAgICAgICAgICAgICAgIHZhciB0b3BMZXZlbCA9IHR5cGVvZiBnbG9iYWwgIT09IFwidW5kZWZpbmVkXCIgPyBnbG9iYWwgOiB0eXBlb2Ygd2luZG93ICE9PSBcInVuZGVmaW5lZFwiID8gd2luZG93IDoge307XG4gICAgICAgICAgICAgICAgdmFyIG1pbkRvYyA9IHJlcXVpcmUoXCJtaW4tZG9jdW1lbnRcIik7XG5cbiAgICAgICAgICAgICAgICBpZiAodHlwZW9mIGRvY3VtZW50ICE9PSBcInVuZGVmaW5lZFwiKSB7XG4gICAgICAgICAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gZG9jdW1lbnQ7XG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgdmFyIGRvY2N5ID0gdG9wTGV2ZWxbXCJfX0dMT0JBTF9ET0NVTUVOVF9DQUNIRUA0XCJdO1xuXG4gICAgICAgICAgICAgICAgICAgIGlmICghZG9jY3kpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGRvY2N5ID0gdG9wTGV2ZWxbXCJfX0dMT0JBTF9ET0NVTUVOVF9DQUNIRUA0XCJdID0gbWluRG9jO1xuICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBkb2NjeTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9KS5jYWxsKHRoaXMsIHR5cGVvZiBnbG9iYWwgIT09IFwidW5kZWZpbmVkXCIgPyBnbG9iYWwgOiB0eXBlb2Ygc2VsZiAhPT0gXCJ1bmRlZmluZWRcIiA/IHNlbGYgOiB0eXBlb2Ygd2luZG93ICE9PSBcInVuZGVmaW5lZFwiID8gd2luZG93IDoge30pO1xuICAgICAgICB9LCB7IFwibWluLWRvY3VtZW50XCI6IDYgfV0sIDExOiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge1xuICAgICAgICAgICAgXCJ1c2Ugc3RyaWN0XCI7XG5cbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gaXNPYmplY3QoeCkge1xuICAgICAgICAgICAgICAgIHJldHVybiB0eXBlb2YgeCA9PT0gXCJvYmplY3RcIiAmJiB4ICE9PSBudWxsO1xuICAgICAgICAgICAgfTtcbiAgICAgICAgfSwge31dLCAxMjogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHtcbiAgICAgICAgICAgIHZhciBuYXRpdmVJc0FycmF5ID0gQXJyYXkuaXNBcnJheTtcbiAgICAgICAgICAgIHZhciB0b1N0cmluZyA9IE9iamVjdC5wcm90b3R5cGUudG9TdHJpbmc7XG5cbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gbmF0aXZlSXNBcnJheSB8fCBpc0FycmF5O1xuXG4gICAgICAgICAgICBmdW5jdGlvbiBpc0FycmF5KG9iaikge1xuICAgICAgICAgICAgICAgIHJldHVybiB0b1N0cmluZy5jYWxsKG9iaikgPT09IFwiW29iamVjdCBBcnJheV1cIjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSwge31dLCAxMzogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHtcbiAgICAgICAgICAgIHZhciBwYXRjaCA9IHJlcXVpcmUoXCIuL3Zkb20vcGF0Y2guanNcIik7XG5cbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gcGF0Y2g7XG4gICAgICAgIH0sIHsgXCIuL3Zkb20vcGF0Y2guanNcIjogMTggfV0sIDE0OiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge1xuICAgICAgICAgICAgdmFyIGlzT2JqZWN0ID0gcmVxdWlyZShcImlzLW9iamVjdFwiKTtcbiAgICAgICAgICAgIHZhciBpc0hvb2sgPSByZXF1aXJlKFwiLi4vdm5vZGUvaXMtdmhvb2suanNcIik7XG5cbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gYXBwbHlQcm9wZXJ0aWVzO1xuXG4gICAgICAgICAgICBmdW5jdGlvbiBhcHBseVByb3BlcnRpZXMobm9kZSwgcHJvcHMsIHByZXZpb3VzKSB7XG4gICAgICAgICAgICAgICAgZm9yICh2YXIgcHJvcE5hbWUgaW4gcHJvcHMpIHtcbiAgICAgICAgICAgICAgICAgICAgdmFyIHByb3BWYWx1ZSA9IHByb3BzW3Byb3BOYW1lXTtcblxuICAgICAgICAgICAgICAgICAgICBpZiAocHJvcFZhbHVlID09PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJlbW92ZVByb3BlcnR5KG5vZGUsIHByb3BOYW1lLCBwcm9wVmFsdWUsIHByZXZpb3VzKTtcbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIGlmIChpc0hvb2socHJvcFZhbHVlKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgcmVtb3ZlUHJvcGVydHkobm9kZSwgcHJvcE5hbWUsIHByb3BWYWx1ZSwgcHJldmlvdXMpO1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHByb3BWYWx1ZS5ob29rKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcHJvcFZhbHVlLmhvb2sobm9kZSwgcHJvcE5hbWUsIHByZXZpb3VzID8gcHJldmlvdXNbcHJvcE5hbWVdIDogdW5kZWZpbmVkKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChpc09iamVjdChwcm9wVmFsdWUpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcGF0Y2hPYmplY3Qobm9kZSwgcHJvcHMsIHByZXZpb3VzLCBwcm9wTmFtZSwgcHJvcFZhbHVlKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgbm9kZVtwcm9wTmFtZV0gPSBwcm9wVmFsdWU7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIHJlbW92ZVByb3BlcnR5KG5vZGUsIHByb3BOYW1lLCBwcm9wVmFsdWUsIHByZXZpb3VzKSB7XG4gICAgICAgICAgICAgICAgaWYgKHByZXZpb3VzKSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciBwcmV2aW91c1ZhbHVlID0gcHJldmlvdXNbcHJvcE5hbWVdO1xuXG4gICAgICAgICAgICAgICAgICAgIGlmICghaXNIb29rKHByZXZpb3VzVmFsdWUpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAocHJvcE5hbWUgPT09IFwiYXR0cmlidXRlc1wiKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgZm9yICh2YXIgYXR0ck5hbWUgaW4gcHJldmlvdXNWYWx1ZSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBub2RlLnJlbW92ZUF0dHJpYnV0ZShhdHRyTmFtZSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIGlmIChwcm9wTmFtZSA9PT0gXCJzdHlsZVwiKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgZm9yICh2YXIgaSBpbiBwcmV2aW91c1ZhbHVlKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG5vZGUuc3R5bGVbaV0gPSBcIlwiO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAodHlwZW9mIHByZXZpb3VzVmFsdWUgPT09IFwic3RyaW5nXCIpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBub2RlW3Byb3BOYW1lXSA9IFwiXCI7XG4gICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIG5vZGVbcHJvcE5hbWVdID0gbnVsbDtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIGlmIChwcmV2aW91c1ZhbHVlLnVuaG9vaykge1xuICAgICAgICAgICAgICAgICAgICAgICAgcHJldmlvdXNWYWx1ZS51bmhvb2sobm9kZSwgcHJvcE5hbWUsIHByb3BWYWx1ZSk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIHBhdGNoT2JqZWN0KG5vZGUsIHByb3BzLCBwcmV2aW91cywgcHJvcE5hbWUsIHByb3BWYWx1ZSkge1xuICAgICAgICAgICAgICAgIHZhciBwcmV2aW91c1ZhbHVlID0gcHJldmlvdXMgPyBwcmV2aW91c1twcm9wTmFtZV0gOiB1bmRlZmluZWQ7XG5cbiAgICAgICAgICAgICAgICAvLyBTZXQgYXR0cmlidXRlc1xuICAgICAgICAgICAgICAgIGlmIChwcm9wTmFtZSA9PT0gXCJhdHRyaWJ1dGVzXCIpIHtcbiAgICAgICAgICAgICAgICAgICAgZm9yICh2YXIgYXR0ck5hbWUgaW4gcHJvcFZhbHVlKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICB2YXIgYXR0clZhbHVlID0gcHJvcFZhbHVlW2F0dHJOYW1lXTtcblxuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGF0dHJWYWx1ZSA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgbm9kZS5yZW1vdmVBdHRyaWJ1dGUoYXR0ck5hbWUpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBub2RlLnNldEF0dHJpYnV0ZShhdHRyTmFtZSwgYXR0clZhbHVlKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICBpZiAocHJldmlvdXNWYWx1ZSAmJiBpc09iamVjdChwcmV2aW91c1ZhbHVlKSAmJiBnZXRQcm90b3R5cGUocHJldmlvdXNWYWx1ZSkgIT09IGdldFByb3RvdHlwZShwcm9wVmFsdWUpKSB7XG4gICAgICAgICAgICAgICAgICAgIG5vZGVbcHJvcE5hbWVdID0gcHJvcFZhbHVlO1xuICAgICAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgaWYgKCFpc09iamVjdChub2RlW3Byb3BOYW1lXSkpIHtcbiAgICAgICAgICAgICAgICAgICAgbm9kZVtwcm9wTmFtZV0gPSB7fTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICB2YXIgcmVwbGFjZXIgPSBwcm9wTmFtZSA9PT0gXCJzdHlsZVwiID8gXCJcIiA6IHVuZGVmaW5lZDtcblxuICAgICAgICAgICAgICAgIGZvciAodmFyIGsgaW4gcHJvcFZhbHVlKSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciB2YWx1ZSA9IHByb3BWYWx1ZVtrXTtcbiAgICAgICAgICAgICAgICAgICAgbm9kZVtwcm9wTmFtZV1ba10gPSB2YWx1ZSA9PT0gdW5kZWZpbmVkID8gcmVwbGFjZXIgOiB2YWx1ZTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIGdldFByb3RvdHlwZSh2YWx1ZSkge1xuICAgICAgICAgICAgICAgIGlmIChPYmplY3QuZ2V0UHJvdG90eXBlT2YpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIE9iamVjdC5nZXRQcm90b3R5cGVPZih2YWx1ZSk7XG4gICAgICAgICAgICAgICAgfSBlbHNlIGlmICh2YWx1ZS5fX3Byb3RvX18pIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHZhbHVlLl9fcHJvdG9fXztcbiAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKHZhbHVlLmNvbnN0cnVjdG9yKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiB2YWx1ZS5jb25zdHJ1Y3Rvci5wcm90b3R5cGU7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9LCB7IFwiLi4vdm5vZGUvaXMtdmhvb2suanNcIjogMjYsIFwiaXMtb2JqZWN0XCI6IDExIH1dLCAxNTogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHtcbiAgICAgICAgICAgIHZhciBkb2N1bWVudCA9IHJlcXVpcmUoXCJnbG9iYWwvZG9jdW1lbnRcIik7XG5cbiAgICAgICAgICAgIHZhciBhcHBseVByb3BlcnRpZXMgPSByZXF1aXJlKFwiLi9hcHBseS1wcm9wZXJ0aWVzXCIpO1xuXG4gICAgICAgICAgICB2YXIgaXNWTm9kZSA9IHJlcXVpcmUoXCIuLi92bm9kZS9pcy12bm9kZS5qc1wiKTtcbiAgICAgICAgICAgIHZhciBpc1ZUZXh0ID0gcmVxdWlyZShcIi4uL3Zub2RlL2lzLXZ0ZXh0LmpzXCIpO1xuICAgICAgICAgICAgdmFyIGlzV2lkZ2V0ID0gcmVxdWlyZShcIi4uL3Zub2RlL2lzLXdpZGdldC5qc1wiKTtcbiAgICAgICAgICAgIHZhciBoYW5kbGVUaHVuayA9IHJlcXVpcmUoXCIuLi92bm9kZS9oYW5kbGUtdGh1bmsuanNcIik7XG5cbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gY3JlYXRlRWxlbWVudDtcblxuICAgICAgICAgICAgZnVuY3Rpb24gY3JlYXRlRWxlbWVudCh2bm9kZSwgb3B0cykge1xuICAgICAgICAgICAgICAgIHZhciBkb2MgPSBvcHRzID8gb3B0cy5kb2N1bWVudCB8fCBkb2N1bWVudCA6IGRvY3VtZW50O1xuICAgICAgICAgICAgICAgIHZhciB3YXJuID0gb3B0cyA/IG9wdHMud2FybiA6IG51bGw7XG5cbiAgICAgICAgICAgICAgICB2bm9kZSA9IGhhbmRsZVRodW5rKHZub2RlKS5hO1xuXG4gICAgICAgICAgICAgICAgaWYgKGlzV2lkZ2V0KHZub2RlKSkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gdm5vZGUuaW5pdCgpO1xuICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoaXNWVGV4dCh2bm9kZSkpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGRvYy5jcmVhdGVUZXh0Tm9kZSh2bm9kZS50ZXh0KTtcbiAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKCFpc1ZOb2RlKHZub2RlKSkge1xuICAgICAgICAgICAgICAgICAgICBpZiAod2Fybikge1xuICAgICAgICAgICAgICAgICAgICAgICAgd2FybihcIkl0ZW0gaXMgbm90IGEgdmFsaWQgdmlydHVhbCBkb20gbm9kZVwiLCB2bm9kZSk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIG51bGw7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgdmFyIG5vZGUgPSB2bm9kZS5uYW1lc3BhY2UgPT09IG51bGwgPyBkb2MuY3JlYXRlRWxlbWVudCh2bm9kZS50YWdOYW1lKSA6IGRvYy5jcmVhdGVFbGVtZW50TlModm5vZGUubmFtZXNwYWNlLCB2bm9kZS50YWdOYW1lKTtcblxuICAgICAgICAgICAgICAgIHZhciBwcm9wcyA9IHZub2RlLnByb3BlcnRpZXM7XG4gICAgICAgICAgICAgICAgYXBwbHlQcm9wZXJ0aWVzKG5vZGUsIHByb3BzKTtcblxuICAgICAgICAgICAgICAgIHZhciBjaGlsZHJlbiA9IHZub2RlLmNoaWxkcmVuO1xuXG4gICAgICAgICAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCBjaGlsZHJlbi5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgICAgICAgICB2YXIgY2hpbGROb2RlID0gY3JlYXRlRWxlbWVudChjaGlsZHJlbltpXSwgb3B0cyk7XG4gICAgICAgICAgICAgICAgICAgIGlmIChjaGlsZE5vZGUpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIG5vZGUuYXBwZW5kQ2hpbGQoY2hpbGROb2RlKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHJldHVybiBub2RlO1xuICAgICAgICAgICAgfVxuICAgICAgICB9LCB7IFwiLi4vdm5vZGUvaGFuZGxlLXRodW5rLmpzXCI6IDI0LCBcIi4uL3Zub2RlL2lzLXZub2RlLmpzXCI6IDI3LCBcIi4uL3Zub2RlL2lzLXZ0ZXh0LmpzXCI6IDI4LCBcIi4uL3Zub2RlL2lzLXdpZGdldC5qc1wiOiAyOSwgXCIuL2FwcGx5LXByb3BlcnRpZXNcIjogMTQsIFwiZ2xvYmFsL2RvY3VtZW50XCI6IDEwIH1dLCAxNjogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHtcbiAgICAgICAgICAgIC8vIE1hcHMgYSB2aXJ0dWFsIERPTSB0cmVlIG9udG8gYSByZWFsIERPTSB0cmVlIGluIGFuIGVmZmljaWVudCBtYW5uZXIuXG4gICAgICAgICAgICAvLyBXZSBkb24ndCB3YW50IHRvIHJlYWQgYWxsIG9mIHRoZSBET00gbm9kZXMgaW4gdGhlIHRyZWUgc28gd2UgdXNlXG4gICAgICAgICAgICAvLyB0aGUgaW4tb3JkZXIgdHJlZSBpbmRleGluZyB0byBlbGltaW5hdGUgcmVjdXJzaW9uIGRvd24gY2VydGFpbiBicmFuY2hlcy5cbiAgICAgICAgICAgIC8vIFdlIG9ubHkgcmVjdXJzZSBpbnRvIGEgRE9NIG5vZGUgaWYgd2Uga25vdyB0aGF0IGl0IGNvbnRhaW5zIGEgY2hpbGQgb2ZcbiAgICAgICAgICAgIC8vIGludGVyZXN0LlxuXG4gICAgICAgICAgICB2YXIgbm9DaGlsZCA9IHt9O1xuXG4gICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IGRvbUluZGV4O1xuXG4gICAgICAgICAgICBmdW5jdGlvbiBkb21JbmRleChyb290Tm9kZSwgdHJlZSwgaW5kaWNlcywgbm9kZXMpIHtcbiAgICAgICAgICAgICAgICBpZiAoIWluZGljZXMgfHwgaW5kaWNlcy5sZW5ndGggPT09IDApIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHt9O1xuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIGluZGljZXMuc29ydChhc2NlbmRpbmcpO1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gcmVjdXJzZShyb290Tm9kZSwgdHJlZSwgaW5kaWNlcywgbm9kZXMsIDApO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZnVuY3Rpb24gcmVjdXJzZShyb290Tm9kZSwgdHJlZSwgaW5kaWNlcywgbm9kZXMsIHJvb3RJbmRleCkge1xuICAgICAgICAgICAgICAgIG5vZGVzID0gbm9kZXMgfHwge307XG5cbiAgICAgICAgICAgICAgICBpZiAocm9vdE5vZGUpIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKGluZGV4SW5SYW5nZShpbmRpY2VzLCByb290SW5kZXgsIHJvb3RJbmRleCkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIG5vZGVzW3Jvb3RJbmRleF0gPSByb290Tm9kZTtcbiAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgIHZhciB2Q2hpbGRyZW4gPSB0cmVlLmNoaWxkcmVuO1xuXG4gICAgICAgICAgICAgICAgICAgIGlmICh2Q2hpbGRyZW4pIHtcblxuICAgICAgICAgICAgICAgICAgICAgICAgdmFyIGNoaWxkTm9kZXMgPSByb290Tm9kZS5jaGlsZE5vZGVzO1xuXG4gICAgICAgICAgICAgICAgICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IHRyZWUuY2hpbGRyZW4ubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICByb290SW5kZXggKz0gMTtcblxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZhciB2Q2hpbGQgPSB2Q2hpbGRyZW5baV0gfHwgbm9DaGlsZDtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB2YXIgbmV4dEluZGV4ID0gcm9vdEluZGV4ICsgKHZDaGlsZC5jb3VudCB8fCAwKTtcblxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIHNraXAgcmVjdXJzaW9uIGRvd24gdGhlIHRyZWUgaWYgdGhlcmUgYXJlIG5vIG5vZGVzIGRvd24gaGVyZVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChpbmRleEluUmFuZ2UoaW5kaWNlcywgcm9vdEluZGV4LCBuZXh0SW5kZXgpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlY3Vyc2UoY2hpbGROb2Rlc1tpXSwgdkNoaWxkLCBpbmRpY2VzLCBub2Rlcywgcm9vdEluZGV4KTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICByb290SW5kZXggPSBuZXh0SW5kZXg7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICByZXR1cm4gbm9kZXM7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIC8vIEJpbmFyeSBzZWFyY2ggZm9yIGFuIGluZGV4IGluIHRoZSBpbnRlcnZhbCBbbGVmdCwgcmlnaHRdXG4gICAgICAgICAgICBmdW5jdGlvbiBpbmRleEluUmFuZ2UoaW5kaWNlcywgbGVmdCwgcmlnaHQpIHtcbiAgICAgICAgICAgICAgICBpZiAoaW5kaWNlcy5sZW5ndGggPT09IDApIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHZhciBtaW5JbmRleCA9IDA7XG4gICAgICAgICAgICAgICAgdmFyIG1heEluZGV4ID0gaW5kaWNlcy5sZW5ndGggLSAxO1xuICAgICAgICAgICAgICAgIHZhciBjdXJyZW50SW5kZXg7XG4gICAgICAgICAgICAgICAgdmFyIGN1cnJlbnRJdGVtO1xuXG4gICAgICAgICAgICAgICAgd2hpbGUgKG1pbkluZGV4IDw9IG1heEluZGV4KSB7XG4gICAgICAgICAgICAgICAgICAgIGN1cnJlbnRJbmRleCA9IChtYXhJbmRleCArIG1pbkluZGV4KSAvIDIgPj4gMDtcbiAgICAgICAgICAgICAgICAgICAgY3VycmVudEl0ZW0gPSBpbmRpY2VzW2N1cnJlbnRJbmRleF07XG5cbiAgICAgICAgICAgICAgICAgICAgaWYgKG1pbkluZGV4ID09PSBtYXhJbmRleCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGN1cnJlbnRJdGVtID49IGxlZnQgJiYgY3VycmVudEl0ZW0gPD0gcmlnaHQ7XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoY3VycmVudEl0ZW0gPCBsZWZ0KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBtaW5JbmRleCA9IGN1cnJlbnRJbmRleCArIDE7XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoY3VycmVudEl0ZW0gPiByaWdodCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgbWF4SW5kZXggPSBjdXJyZW50SW5kZXggLSAxO1xuICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIGFzY2VuZGluZyhhLCBiKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGEgPiBiID8gMSA6IC0xO1xuICAgICAgICAgICAgfVxuICAgICAgICB9LCB7fV0sIDE3OiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge1xuICAgICAgICAgICAgdmFyIGFwcGx5UHJvcGVydGllcyA9IHJlcXVpcmUoXCIuL2FwcGx5LXByb3BlcnRpZXNcIik7XG5cbiAgICAgICAgICAgIHZhciBpc1dpZGdldCA9IHJlcXVpcmUoXCIuLi92bm9kZS9pcy13aWRnZXQuanNcIik7XG4gICAgICAgICAgICB2YXIgVlBhdGNoID0gcmVxdWlyZShcIi4uL3Zub2RlL3ZwYXRjaC5qc1wiKTtcblxuICAgICAgICAgICAgdmFyIHVwZGF0ZVdpZGdldCA9IHJlcXVpcmUoXCIuL3VwZGF0ZS13aWRnZXRcIik7XG5cbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gYXBwbHlQYXRjaDtcblxuICAgICAgICAgICAgZnVuY3Rpb24gYXBwbHlQYXRjaCh2cGF0Y2gsIGRvbU5vZGUsIHJlbmRlck9wdGlvbnMpIHtcbiAgICAgICAgICAgICAgICB2YXIgdHlwZSA9IHZwYXRjaC50eXBlO1xuICAgICAgICAgICAgICAgIHZhciB2Tm9kZSA9IHZwYXRjaC52Tm9kZTtcbiAgICAgICAgICAgICAgICB2YXIgcGF0Y2ggPSB2cGF0Y2gucGF0Y2g7XG5cbiAgICAgICAgICAgICAgICBzd2l0Y2ggKHR5cGUpIHtcbiAgICAgICAgICAgICAgICAgICAgY2FzZSBWUGF0Y2guUkVNT1ZFOlxuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHJlbW92ZU5vZGUoZG9tTm9kZSwgdk5vZGUpO1xuICAgICAgICAgICAgICAgICAgICBjYXNlIFZQYXRjaC5JTlNFUlQ6XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gaW5zZXJ0Tm9kZShkb21Ob2RlLCBwYXRjaCwgcmVuZGVyT3B0aW9ucyk7XG4gICAgICAgICAgICAgICAgICAgIGNhc2UgVlBhdGNoLlZURVhUOlxuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHN0cmluZ1BhdGNoKGRvbU5vZGUsIHZOb2RlLCBwYXRjaCwgcmVuZGVyT3B0aW9ucyk7XG4gICAgICAgICAgICAgICAgICAgIGNhc2UgVlBhdGNoLldJREdFVDpcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiB3aWRnZXRQYXRjaChkb21Ob2RlLCB2Tm9kZSwgcGF0Y2gsIHJlbmRlck9wdGlvbnMpO1xuICAgICAgICAgICAgICAgICAgICBjYXNlIFZQYXRjaC5WTk9ERTpcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiB2Tm9kZVBhdGNoKGRvbU5vZGUsIHZOb2RlLCBwYXRjaCwgcmVuZGVyT3B0aW9ucyk7XG4gICAgICAgICAgICAgICAgICAgIGNhc2UgVlBhdGNoLk9SREVSOlxuICAgICAgICAgICAgICAgICAgICAgICAgcmVvcmRlckNoaWxkcmVuKGRvbU5vZGUsIHBhdGNoKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBkb21Ob2RlO1xuICAgICAgICAgICAgICAgICAgICBjYXNlIFZQYXRjaC5QUk9QUzpcbiAgICAgICAgICAgICAgICAgICAgICAgIGFwcGx5UHJvcGVydGllcyhkb21Ob2RlLCBwYXRjaCwgdk5vZGUucHJvcGVydGllcyk7XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gZG9tTm9kZTtcbiAgICAgICAgICAgICAgICAgICAgY2FzZSBWUGF0Y2guVEhVTks6XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gcmVwbGFjZVJvb3QoZG9tTm9kZSwgcmVuZGVyT3B0aW9ucy5wYXRjaChkb21Ob2RlLCBwYXRjaCwgcmVuZGVyT3B0aW9ucykpO1xuICAgICAgICAgICAgICAgICAgICBkZWZhdWx0OlxuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGRvbU5vZGU7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBmdW5jdGlvbiByZW1vdmVOb2RlKGRvbU5vZGUsIHZOb2RlKSB7XG4gICAgICAgICAgICAgICAgdmFyIHBhcmVudE5vZGUgPSBkb21Ob2RlLnBhcmVudE5vZGU7XG5cbiAgICAgICAgICAgICAgICBpZiAocGFyZW50Tm9kZSkge1xuICAgICAgICAgICAgICAgICAgICBwYXJlbnROb2RlLnJlbW92ZUNoaWxkKGRvbU5vZGUpO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIGRlc3Ryb3lXaWRnZXQoZG9tTm9kZSwgdk5vZGUpO1xuXG4gICAgICAgICAgICAgICAgcmV0dXJuIG51bGw7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIGluc2VydE5vZGUocGFyZW50Tm9kZSwgdk5vZGUsIHJlbmRlck9wdGlvbnMpIHtcbiAgICAgICAgICAgICAgICB2YXIgbmV3Tm9kZSA9IHJlbmRlck9wdGlvbnMucmVuZGVyKHZOb2RlLCByZW5kZXJPcHRpb25zKTtcblxuICAgICAgICAgICAgICAgIGlmIChwYXJlbnROb2RlKSB7XG4gICAgICAgICAgICAgICAgICAgIHBhcmVudE5vZGUuYXBwZW5kQ2hpbGQobmV3Tm9kZSk7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgcmV0dXJuIHBhcmVudE5vZGU7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIHN0cmluZ1BhdGNoKGRvbU5vZGUsIGxlZnRWTm9kZSwgdlRleHQsIHJlbmRlck9wdGlvbnMpIHtcbiAgICAgICAgICAgICAgICB2YXIgbmV3Tm9kZTtcblxuICAgICAgICAgICAgICAgIGlmIChkb21Ob2RlLm5vZGVUeXBlID09PSAzKSB7XG4gICAgICAgICAgICAgICAgICAgIGRvbU5vZGUucmVwbGFjZURhdGEoMCwgZG9tTm9kZS5sZW5ndGgsIHZUZXh0LnRleHQpO1xuICAgICAgICAgICAgICAgICAgICBuZXdOb2RlID0gZG9tTm9kZTtcbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICB2YXIgcGFyZW50Tm9kZSA9IGRvbU5vZGUucGFyZW50Tm9kZTtcbiAgICAgICAgICAgICAgICAgICAgbmV3Tm9kZSA9IHJlbmRlck9wdGlvbnMucmVuZGVyKHZUZXh0LCByZW5kZXJPcHRpb25zKTtcblxuICAgICAgICAgICAgICAgICAgICBpZiAocGFyZW50Tm9kZSAmJiBuZXdOb2RlICE9PSBkb21Ob2RlKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBwYXJlbnROb2RlLnJlcGxhY2VDaGlsZChuZXdOb2RlLCBkb21Ob2RlKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHJldHVybiBuZXdOb2RlO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBmdW5jdGlvbiB3aWRnZXRQYXRjaChkb21Ob2RlLCBsZWZ0Vk5vZGUsIHdpZGdldCwgcmVuZGVyT3B0aW9ucykge1xuICAgICAgICAgICAgICAgIHZhciB1cGRhdGluZyA9IHVwZGF0ZVdpZGdldChsZWZ0Vk5vZGUsIHdpZGdldCk7XG4gICAgICAgICAgICAgICAgdmFyIG5ld05vZGU7XG5cbiAgICAgICAgICAgICAgICBpZiAodXBkYXRpbmcpIHtcbiAgICAgICAgICAgICAgICAgICAgbmV3Tm9kZSA9IHdpZGdldC51cGRhdGUobGVmdFZOb2RlLCBkb21Ob2RlKSB8fCBkb21Ob2RlO1xuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIG5ld05vZGUgPSByZW5kZXJPcHRpb25zLnJlbmRlcih3aWRnZXQsIHJlbmRlck9wdGlvbnMpO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHZhciBwYXJlbnROb2RlID0gZG9tTm9kZS5wYXJlbnROb2RlO1xuXG4gICAgICAgICAgICAgICAgaWYgKHBhcmVudE5vZGUgJiYgbmV3Tm9kZSAhPT0gZG9tTm9kZSkge1xuICAgICAgICAgICAgICAgICAgICBwYXJlbnROb2RlLnJlcGxhY2VDaGlsZChuZXdOb2RlLCBkb21Ob2RlKTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICBpZiAoIXVwZGF0aW5nKSB7XG4gICAgICAgICAgICAgICAgICAgIGRlc3Ryb3lXaWRnZXQoZG9tTm9kZSwgbGVmdFZOb2RlKTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICByZXR1cm4gbmV3Tm9kZTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZnVuY3Rpb24gdk5vZGVQYXRjaChkb21Ob2RlLCBsZWZ0Vk5vZGUsIHZOb2RlLCByZW5kZXJPcHRpb25zKSB7XG4gICAgICAgICAgICAgICAgdmFyIHBhcmVudE5vZGUgPSBkb21Ob2RlLnBhcmVudE5vZGU7XG4gICAgICAgICAgICAgICAgdmFyIG5ld05vZGUgPSByZW5kZXJPcHRpb25zLnJlbmRlcih2Tm9kZSwgcmVuZGVyT3B0aW9ucyk7XG5cbiAgICAgICAgICAgICAgICBpZiAocGFyZW50Tm9kZSAmJiBuZXdOb2RlICE9PSBkb21Ob2RlKSB7XG4gICAgICAgICAgICAgICAgICAgIHBhcmVudE5vZGUucmVwbGFjZUNoaWxkKG5ld05vZGUsIGRvbU5vZGUpO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHJldHVybiBuZXdOb2RlO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBmdW5jdGlvbiBkZXN0cm95V2lkZ2V0KGRvbU5vZGUsIHcpIHtcbiAgICAgICAgICAgICAgICBpZiAodHlwZW9mIHcuZGVzdHJveSA9PT0gXCJmdW5jdGlvblwiICYmIGlzV2lkZ2V0KHcpKSB7XG4gICAgICAgICAgICAgICAgICAgIHcuZGVzdHJveShkb21Ob2RlKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIHJlb3JkZXJDaGlsZHJlbihkb21Ob2RlLCBtb3Zlcykge1xuICAgICAgICAgICAgICAgIHZhciBjaGlsZE5vZGVzID0gZG9tTm9kZS5jaGlsZE5vZGVzO1xuICAgICAgICAgICAgICAgIHZhciBrZXlNYXAgPSB7fTtcbiAgICAgICAgICAgICAgICB2YXIgbm9kZTtcbiAgICAgICAgICAgICAgICB2YXIgcmVtb3ZlO1xuICAgICAgICAgICAgICAgIHZhciBpbnNlcnQ7XG5cbiAgICAgICAgICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IG1vdmVzLnJlbW92ZXMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgICAgICAgICAgcmVtb3ZlID0gbW92ZXMucmVtb3Zlc1tpXTtcbiAgICAgICAgICAgICAgICAgICAgbm9kZSA9IGNoaWxkTm9kZXNbcmVtb3ZlLmZyb21dO1xuICAgICAgICAgICAgICAgICAgICBpZiAocmVtb3ZlLmtleSkge1xuICAgICAgICAgICAgICAgICAgICAgICAga2V5TWFwW3JlbW92ZS5rZXldID0gbm9kZTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICBkb21Ob2RlLnJlbW92ZUNoaWxkKG5vZGUpO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHZhciBsZW5ndGggPSBjaGlsZE5vZGVzLmxlbmd0aDtcbiAgICAgICAgICAgICAgICBmb3IgKHZhciBqID0gMDsgaiA8IG1vdmVzLmluc2VydHMubGVuZ3RoOyBqKyspIHtcbiAgICAgICAgICAgICAgICAgICAgaW5zZXJ0ID0gbW92ZXMuaW5zZXJ0c1tqXTtcbiAgICAgICAgICAgICAgICAgICAgbm9kZSA9IGtleU1hcFtpbnNlcnQua2V5XTtcbiAgICAgICAgICAgICAgICAgICAgLy8gdGhpcyBpcyB0aGUgd2VpcmRlc3QgYnVnIGkndmUgZXZlciBzZWVuIGluIHdlYmtpdFxuICAgICAgICAgICAgICAgICAgICBkb21Ob2RlLmluc2VydEJlZm9yZShub2RlLCBpbnNlcnQudG8gPj0gbGVuZ3RoKysgPyBudWxsIDogY2hpbGROb2Rlc1tpbnNlcnQudG9dKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIHJlcGxhY2VSb290KG9sZFJvb3QsIG5ld1Jvb3QpIHtcbiAgICAgICAgICAgICAgICBpZiAob2xkUm9vdCAmJiBuZXdSb290ICYmIG9sZFJvb3QgIT09IG5ld1Jvb3QgJiYgb2xkUm9vdC5wYXJlbnROb2RlKSB7XG4gICAgICAgICAgICAgICAgICAgIG9sZFJvb3QucGFyZW50Tm9kZS5yZXBsYWNlQ2hpbGQobmV3Um9vdCwgb2xkUm9vdCk7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgcmV0dXJuIG5ld1Jvb3Q7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0sIHsgXCIuLi92bm9kZS9pcy13aWRnZXQuanNcIjogMjksIFwiLi4vdm5vZGUvdnBhdGNoLmpzXCI6IDMyLCBcIi4vYXBwbHktcHJvcGVydGllc1wiOiAxNCwgXCIuL3VwZGF0ZS13aWRnZXRcIjogMTkgfV0sIDE4OiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge1xuICAgICAgICAgICAgdmFyIGRvY3VtZW50ID0gcmVxdWlyZShcImdsb2JhbC9kb2N1bWVudFwiKTtcbiAgICAgICAgICAgIHZhciBpc0FycmF5ID0gcmVxdWlyZShcIngtaXMtYXJyYXlcIik7XG5cbiAgICAgICAgICAgIHZhciByZW5kZXIgPSByZXF1aXJlKFwiLi9jcmVhdGUtZWxlbWVudFwiKTtcbiAgICAgICAgICAgIHZhciBkb21JbmRleCA9IHJlcXVpcmUoXCIuL2RvbS1pbmRleFwiKTtcbiAgICAgICAgICAgIHZhciBwYXRjaE9wID0gcmVxdWlyZShcIi4vcGF0Y2gtb3BcIik7XG4gICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IHBhdGNoO1xuXG4gICAgICAgICAgICBmdW5jdGlvbiBwYXRjaChyb290Tm9kZSwgcGF0Y2hlcywgcmVuZGVyT3B0aW9ucykge1xuICAgICAgICAgICAgICAgIHJlbmRlck9wdGlvbnMgPSByZW5kZXJPcHRpb25zIHx8IHt9O1xuICAgICAgICAgICAgICAgIHJlbmRlck9wdGlvbnMucGF0Y2ggPSByZW5kZXJPcHRpb25zLnBhdGNoICYmIHJlbmRlck9wdGlvbnMucGF0Y2ggIT09IHBhdGNoID8gcmVuZGVyT3B0aW9ucy5wYXRjaCA6IHBhdGNoUmVjdXJzaXZlO1xuICAgICAgICAgICAgICAgIHJlbmRlck9wdGlvbnMucmVuZGVyID0gcmVuZGVyT3B0aW9ucy5yZW5kZXIgfHwgcmVuZGVyO1xuXG4gICAgICAgICAgICAgICAgcmV0dXJuIHJlbmRlck9wdGlvbnMucGF0Y2gocm9vdE5vZGUsIHBhdGNoZXMsIHJlbmRlck9wdGlvbnMpO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBmdW5jdGlvbiBwYXRjaFJlY3Vyc2l2ZShyb290Tm9kZSwgcGF0Y2hlcywgcmVuZGVyT3B0aW9ucykge1xuICAgICAgICAgICAgICAgIHZhciBpbmRpY2VzID0gcGF0Y2hJbmRpY2VzKHBhdGNoZXMpO1xuXG4gICAgICAgICAgICAgICAgaWYgKGluZGljZXMubGVuZ3RoID09PSAwKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiByb290Tm9kZTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICB2YXIgaW5kZXggPSBkb21JbmRleChyb290Tm9kZSwgcGF0Y2hlcy5hLCBpbmRpY2VzKTtcbiAgICAgICAgICAgICAgICB2YXIgb3duZXJEb2N1bWVudCA9IHJvb3ROb2RlLm93bmVyRG9jdW1lbnQ7XG5cbiAgICAgICAgICAgICAgICBpZiAoIXJlbmRlck9wdGlvbnMuZG9jdW1lbnQgJiYgb3duZXJEb2N1bWVudCAhPT0gZG9jdW1lbnQpIHtcbiAgICAgICAgICAgICAgICAgICAgcmVuZGVyT3B0aW9ucy5kb2N1bWVudCA9IG93bmVyRG9jdW1lbnQ7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCBpbmRpY2VzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciBub2RlSW5kZXggPSBpbmRpY2VzW2ldO1xuICAgICAgICAgICAgICAgICAgICByb290Tm9kZSA9IGFwcGx5UGF0Y2gocm9vdE5vZGUsIGluZGV4W25vZGVJbmRleF0sIHBhdGNoZXNbbm9kZUluZGV4XSwgcmVuZGVyT3B0aW9ucyk7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgcmV0dXJuIHJvb3ROb2RlO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBmdW5jdGlvbiBhcHBseVBhdGNoKHJvb3ROb2RlLCBkb21Ob2RlLCBwYXRjaExpc3QsIHJlbmRlck9wdGlvbnMpIHtcbiAgICAgICAgICAgICAgICBpZiAoIWRvbU5vZGUpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHJvb3ROb2RlO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHZhciBuZXdOb2RlO1xuXG4gICAgICAgICAgICAgICAgaWYgKGlzQXJyYXkocGF0Y2hMaXN0KSkge1xuICAgICAgICAgICAgICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IHBhdGNoTGlzdC5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgICAgICAgICAgICAgbmV3Tm9kZSA9IHBhdGNoT3AocGF0Y2hMaXN0W2ldLCBkb21Ob2RlLCByZW5kZXJPcHRpb25zKTtcblxuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGRvbU5vZGUgPT09IHJvb3ROb2RlKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcm9vdE5vZGUgPSBuZXdOb2RlO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgbmV3Tm9kZSA9IHBhdGNoT3AocGF0Y2hMaXN0LCBkb21Ob2RlLCByZW5kZXJPcHRpb25zKTtcblxuICAgICAgICAgICAgICAgICAgICBpZiAoZG9tTm9kZSA9PT0gcm9vdE5vZGUpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJvb3ROb2RlID0gbmV3Tm9kZTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHJldHVybiByb290Tm9kZTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZnVuY3Rpb24gcGF0Y2hJbmRpY2VzKHBhdGNoZXMpIHtcbiAgICAgICAgICAgICAgICB2YXIgaW5kaWNlcyA9IFtdO1xuXG4gICAgICAgICAgICAgICAgZm9yICh2YXIga2V5IGluIHBhdGNoZXMpIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKGtleSAhPT0gXCJhXCIpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGluZGljZXMucHVzaChOdW1iZXIoa2V5KSk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICByZXR1cm4gaW5kaWNlcztcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSwgeyBcIi4vY3JlYXRlLWVsZW1lbnRcIjogMTUsIFwiLi9kb20taW5kZXhcIjogMTYsIFwiLi9wYXRjaC1vcFwiOiAxNywgXCJnbG9iYWwvZG9jdW1lbnRcIjogMTAsIFwieC1pcy1hcnJheVwiOiAxMiB9XSwgMTk6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICB2YXIgaXNXaWRnZXQgPSByZXF1aXJlKFwiLi4vdm5vZGUvaXMtd2lkZ2V0LmpzXCIpO1xuXG4gICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IHVwZGF0ZVdpZGdldDtcblxuICAgICAgICAgICAgZnVuY3Rpb24gdXBkYXRlV2lkZ2V0KGEsIGIpIHtcbiAgICAgICAgICAgICAgICBpZiAoaXNXaWRnZXQoYSkgJiYgaXNXaWRnZXQoYikpIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKFwibmFtZVwiIGluIGEgJiYgXCJuYW1lXCIgaW4gYikge1xuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGEuaWQgPT09IGIuaWQ7XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gYS5pbml0ID09PSBiLmluaXQ7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0sIHsgXCIuLi92bm9kZS9pcy13aWRnZXQuanNcIjogMjkgfV0sIDIwOiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge1xuICAgICAgICAgICAgXCJ1c2Ugc3RyaWN0XCI7XG5cbiAgICAgICAgICAgIHZhciBFdlN0b3JlID0gcmVxdWlyZShcImV2LXN0b3JlXCIpO1xuXG4gICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IEV2SG9vaztcblxuICAgICAgICAgICAgZnVuY3Rpb24gRXZIb29rKHZhbHVlKSB7XG4gICAgICAgICAgICAgICAgaWYgKCEodGhpcyBpbnN0YW5jZW9mIEV2SG9vaykpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIG5ldyBFdkhvb2sodmFsdWUpO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHRoaXMudmFsdWUgPSB2YWx1ZTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgRXZIb29rLnByb3RvdHlwZS5ob29rID0gZnVuY3Rpb24gKG5vZGUsIHByb3BlcnR5TmFtZSkge1xuICAgICAgICAgICAgICAgIHZhciBlcyA9IEV2U3RvcmUobm9kZSk7XG4gICAgICAgICAgICAgICAgdmFyIHByb3BOYW1lID0gcHJvcGVydHlOYW1lLnN1YnN0cigzKTtcblxuICAgICAgICAgICAgICAgIGVzW3Byb3BOYW1lXSA9IHRoaXMudmFsdWU7XG4gICAgICAgICAgICB9O1xuXG4gICAgICAgICAgICBFdkhvb2sucHJvdG90eXBlLnVuaG9vayA9IGZ1bmN0aW9uIChub2RlLCBwcm9wZXJ0eU5hbWUpIHtcbiAgICAgICAgICAgICAgICB2YXIgZXMgPSBFdlN0b3JlKG5vZGUpO1xuICAgICAgICAgICAgICAgIHZhciBwcm9wTmFtZSA9IHByb3BlcnR5TmFtZS5zdWJzdHIoMyk7XG5cbiAgICAgICAgICAgICAgICBlc1twcm9wTmFtZV0gPSB1bmRlZmluZWQ7XG4gICAgICAgICAgICB9O1xuICAgICAgICB9LCB7IFwiZXYtc3RvcmVcIjogNyB9XSwgMjE6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICBcInVzZSBzdHJpY3RcIjtcblxuICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBTb2Z0U2V0SG9vaztcblxuICAgICAgICAgICAgZnVuY3Rpb24gU29mdFNldEhvb2sodmFsdWUpIHtcbiAgICAgICAgICAgICAgICBpZiAoISh0aGlzIGluc3RhbmNlb2YgU29mdFNldEhvb2spKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBuZXcgU29mdFNldEhvb2sodmFsdWUpO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHRoaXMudmFsdWUgPSB2YWx1ZTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgU29mdFNldEhvb2sucHJvdG90eXBlLmhvb2sgPSBmdW5jdGlvbiAobm9kZSwgcHJvcGVydHlOYW1lKSB7XG4gICAgICAgICAgICAgICAgaWYgKG5vZGVbcHJvcGVydHlOYW1lXSAhPT0gdGhpcy52YWx1ZSkge1xuICAgICAgICAgICAgICAgICAgICBub2RlW3Byb3BlcnR5TmFtZV0gPSB0aGlzLnZhbHVlO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH07XG4gICAgICAgIH0sIHt9XSwgMjI6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICBcInVzZSBzdHJpY3RcIjtcblxuICAgICAgICAgICAgdmFyIGlzQXJyYXkgPSByZXF1aXJlKFwieC1pcy1hcnJheVwiKTtcblxuICAgICAgICAgICAgdmFyIFZOb2RlID0gcmVxdWlyZShcIi4uL3Zub2RlL3Zub2RlLmpzXCIpO1xuICAgICAgICAgICAgdmFyIFZUZXh0ID0gcmVxdWlyZShcIi4uL3Zub2RlL3Z0ZXh0LmpzXCIpO1xuICAgICAgICAgICAgdmFyIGlzVk5vZGUgPSByZXF1aXJlKFwiLi4vdm5vZGUvaXMtdm5vZGVcIik7XG4gICAgICAgICAgICB2YXIgaXNWVGV4dCA9IHJlcXVpcmUoXCIuLi92bm9kZS9pcy12dGV4dFwiKTtcbiAgICAgICAgICAgIHZhciBpc1dpZGdldCA9IHJlcXVpcmUoXCIuLi92bm9kZS9pcy13aWRnZXRcIik7XG4gICAgICAgICAgICB2YXIgaXNIb29rID0gcmVxdWlyZShcIi4uL3Zub2RlL2lzLXZob29rXCIpO1xuICAgICAgICAgICAgdmFyIGlzVlRodW5rID0gcmVxdWlyZShcIi4uL3Zub2RlL2lzLXRodW5rXCIpO1xuXG4gICAgICAgICAgICB2YXIgcGFyc2VUYWcgPSByZXF1aXJlKFwiLi9wYXJzZS10YWcuanNcIik7XG4gICAgICAgICAgICB2YXIgc29mdFNldEhvb2sgPSByZXF1aXJlKFwiLi9ob29rcy9zb2Z0LXNldC1ob29rLmpzXCIpO1xuICAgICAgICAgICAgdmFyIGV2SG9vayA9IHJlcXVpcmUoXCIuL2hvb2tzL2V2LWhvb2suanNcIik7XG5cbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gaDtcblxuICAgICAgICAgICAgZnVuY3Rpb24gaCh0YWdOYW1lLCBwcm9wZXJ0aWVzLCBjaGlsZHJlbikge1xuICAgICAgICAgICAgICAgIHZhciBjaGlsZE5vZGVzID0gW107XG4gICAgICAgICAgICAgICAgdmFyIHRhZywgcHJvcHMsIGtleSwgbmFtZXNwYWNlO1xuXG4gICAgICAgICAgICAgICAgaWYgKCFjaGlsZHJlbiAmJiBpc0NoaWxkcmVuKHByb3BlcnRpZXMpKSB7XG4gICAgICAgICAgICAgICAgICAgIGNoaWxkcmVuID0gcHJvcGVydGllcztcbiAgICAgICAgICAgICAgICAgICAgcHJvcHMgPSB7fTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICBwcm9wcyA9IHByb3BzIHx8IHByb3BlcnRpZXMgfHwge307XG4gICAgICAgICAgICAgICAgdGFnID0gcGFyc2VUYWcodGFnTmFtZSwgcHJvcHMpO1xuXG4gICAgICAgICAgICAgICAgLy8gc3VwcG9ydCBrZXlzXG4gICAgICAgICAgICAgICAgaWYgKHByb3BzLmhhc093blByb3BlcnR5KFwia2V5XCIpKSB7XG4gICAgICAgICAgICAgICAgICAgIGtleSA9IHByb3BzLmtleTtcbiAgICAgICAgICAgICAgICAgICAgcHJvcHMua2V5ID0gdW5kZWZpbmVkO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIC8vIHN1cHBvcnQgbmFtZXNwYWNlXG4gICAgICAgICAgICAgICAgaWYgKHByb3BzLmhhc093blByb3BlcnR5KFwibmFtZXNwYWNlXCIpKSB7XG4gICAgICAgICAgICAgICAgICAgIG5hbWVzcGFjZSA9IHByb3BzLm5hbWVzcGFjZTtcbiAgICAgICAgICAgICAgICAgICAgcHJvcHMubmFtZXNwYWNlID0gdW5kZWZpbmVkO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIC8vIGZpeCBjdXJzb3IgYnVnXG4gICAgICAgICAgICAgICAgaWYgKHRhZyA9PT0gXCJJTlBVVFwiICYmICFuYW1lc3BhY2UgJiYgcHJvcHMuaGFzT3duUHJvcGVydHkoXCJ2YWx1ZVwiKSAmJiBwcm9wcy52YWx1ZSAhPT0gdW5kZWZpbmVkICYmICFpc0hvb2socHJvcHMudmFsdWUpKSB7XG4gICAgICAgICAgICAgICAgICAgIHByb3BzLnZhbHVlID0gc29mdFNldEhvb2socHJvcHMudmFsdWUpO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHRyYW5zZm9ybVByb3BlcnRpZXMocHJvcHMpO1xuXG4gICAgICAgICAgICAgICAgaWYgKGNoaWxkcmVuICE9PSB1bmRlZmluZWQgJiYgY2hpbGRyZW4gIT09IG51bGwpIHtcbiAgICAgICAgICAgICAgICAgICAgYWRkQ2hpbGQoY2hpbGRyZW4sIGNoaWxkTm9kZXMsIHRhZywgcHJvcHMpO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHJldHVybiBuZXcgVk5vZGUodGFnLCBwcm9wcywgY2hpbGROb2Rlcywga2V5LCBuYW1lc3BhY2UpO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBmdW5jdGlvbiBhZGRDaGlsZChjLCBjaGlsZE5vZGVzLCB0YWcsIHByb3BzKSB7XG4gICAgICAgICAgICAgICAgaWYgKHR5cGVvZiBjID09PSBcInN0cmluZ1wiKSB7XG4gICAgICAgICAgICAgICAgICAgIGNoaWxkTm9kZXMucHVzaChuZXcgVlRleHQoYykpO1xuICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAodHlwZW9mIGMgPT09IFwibnVtYmVyXCIpIHtcbiAgICAgICAgICAgICAgICAgICAgY2hpbGROb2Rlcy5wdXNoKG5ldyBWVGV4dChTdHJpbmcoYykpKTtcbiAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKGlzQ2hpbGQoYykpIHtcbiAgICAgICAgICAgICAgICAgICAgY2hpbGROb2Rlcy5wdXNoKGMpO1xuICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoaXNBcnJheShjKSkge1xuICAgICAgICAgICAgICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IGMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGFkZENoaWxkKGNbaV0sIGNoaWxkTm9kZXMsIHRhZywgcHJvcHMpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfSBlbHNlIGlmIChjID09PSBudWxsIHx8IGMgPT09IHVuZGVmaW5lZCkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgdGhyb3cgVW5leHBlY3RlZFZpcnR1YWxFbGVtZW50KHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGZvcmVpZ25PYmplY3Q6IGMsXG4gICAgICAgICAgICAgICAgICAgICAgICBwYXJlbnRWbm9kZToge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRhZ05hbWU6IHRhZyxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBwcm9wZXJ0aWVzOiBwcm9wc1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIHRyYW5zZm9ybVByb3BlcnRpZXMocHJvcHMpIHtcbiAgICAgICAgICAgICAgICBmb3IgKHZhciBwcm9wTmFtZSBpbiBwcm9wcykge1xuICAgICAgICAgICAgICAgICAgICBpZiAocHJvcHMuaGFzT3duUHJvcGVydHkocHJvcE5hbWUpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICB2YXIgdmFsdWUgPSBwcm9wc1twcm9wTmFtZV07XG5cbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChpc0hvb2sodmFsdWUpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgY29udGludWU7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChwcm9wTmFtZS5zdWJzdHIoMCwgMykgPT09IFwiZXYtXCIpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBhZGQgZXYtZm9vIHN1cHBvcnRcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBwcm9wc1twcm9wTmFtZV0gPSBldkhvb2sodmFsdWUpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBmdW5jdGlvbiBpc0NoaWxkKHgpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gaXNWTm9kZSh4KSB8fCBpc1ZUZXh0KHgpIHx8IGlzV2lkZ2V0KHgpIHx8IGlzVlRodW5rKHgpO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBmdW5jdGlvbiBpc0NoaWxkcmVuKHgpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gdHlwZW9mIHggPT09IFwic3RyaW5nXCIgfHwgaXNBcnJheSh4KSB8fCBpc0NoaWxkKHgpO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBmdW5jdGlvbiBVbmV4cGVjdGVkVmlydHVhbEVsZW1lbnQoZGF0YSkge1xuICAgICAgICAgICAgICAgIHZhciBlcnIgPSBuZXcgRXJyb3IoKTtcblxuICAgICAgICAgICAgICAgIGVyci50eXBlID0gXCJ2aXJ0dWFsLWh5cGVyc2NyaXB0LnVuZXhwZWN0ZWQudmlydHVhbC1lbGVtZW50XCI7XG4gICAgICAgICAgICAgICAgZXJyLm1lc3NhZ2UgPSBcIlVuZXhwZWN0ZWQgdmlydHVhbCBjaGlsZCBwYXNzZWQgdG8gaCgpLlxcblwiICsgXCJFeHBlY3RlZCBhIFZOb2RlIC8gVnRodW5rIC8gVldpZGdldCAvIHN0cmluZyBidXQ6XFxuXCIgKyBcImdvdDpcXG5cIiArIGVycm9yU3RyaW5nKGRhdGEuZm9yZWlnbk9iamVjdCkgKyBcIi5cXG5cIiArIFwiVGhlIHBhcmVudCB2bm9kZSBpczpcXG5cIiArIGVycm9yU3RyaW5nKGRhdGEucGFyZW50Vm5vZGUpO1xuICAgICAgICAgICAgICAgIFwiXFxuXCIgKyBcIlN1Z2dlc3RlZCBmaXg6IGNoYW5nZSB5b3VyIGBoKC4uLiwgWyAuLi4gXSlgIGNhbGxzaXRlLlwiO1xuICAgICAgICAgICAgICAgIGVyci5mb3JlaWduT2JqZWN0ID0gZGF0YS5mb3JlaWduT2JqZWN0O1xuICAgICAgICAgICAgICAgIGVyci5wYXJlbnRWbm9kZSA9IGRhdGEucGFyZW50Vm5vZGU7XG5cbiAgICAgICAgICAgICAgICByZXR1cm4gZXJyO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBmdW5jdGlvbiBlcnJvclN0cmluZyhvYmopIHtcbiAgICAgICAgICAgICAgICB0cnkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gSlNPTi5zdHJpbmdpZnkob2JqLCBudWxsLCBcIiAgICBcIik7XG4gICAgICAgICAgICAgICAgfSBjYXRjaCAoZSkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gU3RyaW5nKG9iaik7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9LCB7IFwiLi4vdm5vZGUvaXMtdGh1bmtcIjogMjUsIFwiLi4vdm5vZGUvaXMtdmhvb2tcIjogMjYsIFwiLi4vdm5vZGUvaXMtdm5vZGVcIjogMjcsIFwiLi4vdm5vZGUvaXMtdnRleHRcIjogMjgsIFwiLi4vdm5vZGUvaXMtd2lkZ2V0XCI6IDI5LCBcIi4uL3Zub2RlL3Zub2RlLmpzXCI6IDMxLCBcIi4uL3Zub2RlL3Z0ZXh0LmpzXCI6IDMzLCBcIi4vaG9va3MvZXYtaG9vay5qc1wiOiAyMCwgXCIuL2hvb2tzL3NvZnQtc2V0LWhvb2suanNcIjogMjEsIFwiLi9wYXJzZS10YWcuanNcIjogMjMsIFwieC1pcy1hcnJheVwiOiAxMiB9XSwgMjM6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICBcInVzZSBzdHJpY3RcIjtcblxuICAgICAgICAgICAgdmFyIHNwbGl0ID0gcmVxdWlyZShcImJyb3dzZXItc3BsaXRcIik7XG5cbiAgICAgICAgICAgIHZhciBjbGFzc0lkU3BsaXQgPSAvKFtcXC4jXT9bYS16QS1aMC05XFx1MDA3Ri1cXHVGRkZGXzotXSspLztcbiAgICAgICAgICAgIHZhciBub3RDbGFzc0lkID0gL15cXC58Iy87XG5cbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gcGFyc2VUYWc7XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIHBhcnNlVGFnKHRhZywgcHJvcHMpIHtcbiAgICAgICAgICAgICAgICBpZiAoIXRhZykge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gXCJESVZcIjtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICB2YXIgbm9JZCA9ICFwcm9wcy5oYXNPd25Qcm9wZXJ0eShcImlkXCIpO1xuXG4gICAgICAgICAgICAgICAgdmFyIHRhZ1BhcnRzID0gc3BsaXQodGFnLCBjbGFzc0lkU3BsaXQpO1xuICAgICAgICAgICAgICAgIHZhciB0YWdOYW1lID0gbnVsbDtcblxuICAgICAgICAgICAgICAgIGlmIChub3RDbGFzc0lkLnRlc3QodGFnUGFydHNbMV0pKSB7XG4gICAgICAgICAgICAgICAgICAgIHRhZ05hbWUgPSBcIkRJVlwiO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHZhciBjbGFzc2VzLCBwYXJ0LCB0eXBlLCBpO1xuXG4gICAgICAgICAgICAgICAgZm9yIChpID0gMDsgaSA8IHRhZ1BhcnRzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICAgICAgICAgIHBhcnQgPSB0YWdQYXJ0c1tpXTtcblxuICAgICAgICAgICAgICAgICAgICBpZiAoIXBhcnQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnRpbnVlO1xuICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgdHlwZSA9IHBhcnQuY2hhckF0KDApO1xuXG4gICAgICAgICAgICAgICAgICAgIGlmICghdGFnTmFtZSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgdGFnTmFtZSA9IHBhcnQ7XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAodHlwZSA9PT0gXCIuXCIpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGNsYXNzZXMgPSBjbGFzc2VzIHx8IFtdO1xuICAgICAgICAgICAgICAgICAgICAgICAgY2xhc3Nlcy5wdXNoKHBhcnQuc3Vic3RyaW5nKDEsIHBhcnQubGVuZ3RoKSk7XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAodHlwZSA9PT0gXCIjXCIgJiYgbm9JZCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgcHJvcHMuaWQgPSBwYXJ0LnN1YnN0cmluZygxLCBwYXJ0Lmxlbmd0aCk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICBpZiAoY2xhc3Nlcykge1xuICAgICAgICAgICAgICAgICAgICBpZiAocHJvcHMuY2xhc3NOYW1lKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBjbGFzc2VzLnB1c2gocHJvcHMuY2xhc3NOYW1lKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgIHByb3BzLmNsYXNzTmFtZSA9IGNsYXNzZXMuam9pbihcIiBcIik7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgcmV0dXJuIHByb3BzLm5hbWVzcGFjZSA/IHRhZ05hbWUgOiB0YWdOYW1lLnRvVXBwZXJDYXNlKCk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0sIHsgXCJicm93c2VyLXNwbGl0XCI6IDUgfV0sIDI0OiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge1xuICAgICAgICAgICAgdmFyIGlzVk5vZGUgPSByZXF1aXJlKFwiLi9pcy12bm9kZVwiKTtcbiAgICAgICAgICAgIHZhciBpc1ZUZXh0ID0gcmVxdWlyZShcIi4vaXMtdnRleHRcIik7XG4gICAgICAgICAgICB2YXIgaXNXaWRnZXQgPSByZXF1aXJlKFwiLi9pcy13aWRnZXRcIik7XG4gICAgICAgICAgICB2YXIgaXNUaHVuayA9IHJlcXVpcmUoXCIuL2lzLXRodW5rXCIpO1xuXG4gICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IGhhbmRsZVRodW5rO1xuXG4gICAgICAgICAgICBmdW5jdGlvbiBoYW5kbGVUaHVuayhhLCBiKSB7XG4gICAgICAgICAgICAgICAgdmFyIHJlbmRlcmVkQSA9IGE7XG4gICAgICAgICAgICAgICAgdmFyIHJlbmRlcmVkQiA9IGI7XG5cbiAgICAgICAgICAgICAgICBpZiAoaXNUaHVuayhiKSkge1xuICAgICAgICAgICAgICAgICAgICByZW5kZXJlZEIgPSByZW5kZXJUaHVuayhiLCBhKTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICBpZiAoaXNUaHVuayhhKSkge1xuICAgICAgICAgICAgICAgICAgICByZW5kZXJlZEEgPSByZW5kZXJUaHVuayhhLCBudWxsKTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgICAgICAgICBhOiByZW5kZXJlZEEsXG4gICAgICAgICAgICAgICAgICAgIGI6IHJlbmRlcmVkQlxuICAgICAgICAgICAgICAgIH07XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIHJlbmRlclRodW5rKHRodW5rLCBwcmV2aW91cykge1xuICAgICAgICAgICAgICAgIHZhciByZW5kZXJlZFRodW5rID0gdGh1bmsudm5vZGU7XG5cbiAgICAgICAgICAgICAgICBpZiAoIXJlbmRlcmVkVGh1bmspIHtcbiAgICAgICAgICAgICAgICAgICAgcmVuZGVyZWRUaHVuayA9IHRodW5rLnZub2RlID0gdGh1bmsucmVuZGVyKHByZXZpb3VzKTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICBpZiAoIShpc1ZOb2RlKHJlbmRlcmVkVGh1bmspIHx8IGlzVlRleHQocmVuZGVyZWRUaHVuaykgfHwgaXNXaWRnZXQocmVuZGVyZWRUaHVuaykpKSB7XG4gICAgICAgICAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcihcInRodW5rIGRpZCBub3QgcmV0dXJuIGEgdmFsaWQgbm9kZVwiKTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICByZXR1cm4gcmVuZGVyZWRUaHVuaztcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSwgeyBcIi4vaXMtdGh1bmtcIjogMjUsIFwiLi9pcy12bm9kZVwiOiAyNywgXCIuL2lzLXZ0ZXh0XCI6IDI4LCBcIi4vaXMtd2lkZ2V0XCI6IDI5IH1dLCAyNTogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHtcbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gaXNUaHVuaztcblxuICAgICAgICAgICAgZnVuY3Rpb24gaXNUaHVuayh0KSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHQgJiYgdC50eXBlID09PSBcIlRodW5rXCI7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0sIHt9XSwgMjY6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IGlzSG9vaztcblxuICAgICAgICAgICAgZnVuY3Rpb24gaXNIb29rKGhvb2spIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gaG9vayAmJiAodHlwZW9mIGhvb2suaG9vayA9PT0gXCJmdW5jdGlvblwiICYmICFob29rLmhhc093blByb3BlcnR5KFwiaG9va1wiKSB8fCB0eXBlb2YgaG9vay51bmhvb2sgPT09IFwiZnVuY3Rpb25cIiAmJiAhaG9vay5oYXNPd25Qcm9wZXJ0eShcInVuaG9va1wiKSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0sIHt9XSwgMjc6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICB2YXIgdmVyc2lvbiA9IHJlcXVpcmUoXCIuL3ZlcnNpb25cIik7XG5cbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gaXNWaXJ0dWFsTm9kZTtcblxuICAgICAgICAgICAgZnVuY3Rpb24gaXNWaXJ0dWFsTm9kZSh4KSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHggJiYgeC50eXBlID09PSBcIlZpcnR1YWxOb2RlXCIgJiYgeC52ZXJzaW9uID09PSB2ZXJzaW9uO1xuICAgICAgICAgICAgfVxuICAgICAgICB9LCB7IFwiLi92ZXJzaW9uXCI6IDMwIH1dLCAyODogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHtcbiAgICAgICAgICAgIHZhciB2ZXJzaW9uID0gcmVxdWlyZShcIi4vdmVyc2lvblwiKTtcblxuICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBpc1ZpcnR1YWxUZXh0O1xuXG4gICAgICAgICAgICBmdW5jdGlvbiBpc1ZpcnR1YWxUZXh0KHgpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4geCAmJiB4LnR5cGUgPT09IFwiVmlydHVhbFRleHRcIiAmJiB4LnZlcnNpb24gPT09IHZlcnNpb247XG4gICAgICAgICAgICB9XG4gICAgICAgIH0sIHsgXCIuL3ZlcnNpb25cIjogMzAgfV0sIDI5OiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge1xuICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBpc1dpZGdldDtcblxuICAgICAgICAgICAgZnVuY3Rpb24gaXNXaWRnZXQodykge1xuICAgICAgICAgICAgICAgIHJldHVybiB3ICYmIHcudHlwZSA9PT0gXCJXaWRnZXRcIjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSwge31dLCAzMDogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHtcbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gXCIyXCI7XG4gICAgICAgIH0sIHt9XSwgMzE6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICB2YXIgdmVyc2lvbiA9IHJlcXVpcmUoXCIuL3ZlcnNpb25cIik7XG4gICAgICAgICAgICB2YXIgaXNWTm9kZSA9IHJlcXVpcmUoXCIuL2lzLXZub2RlXCIpO1xuICAgICAgICAgICAgdmFyIGlzV2lkZ2V0ID0gcmVxdWlyZShcIi4vaXMtd2lkZ2V0XCIpO1xuICAgICAgICAgICAgdmFyIGlzVGh1bmsgPSByZXF1aXJlKFwiLi9pcy10aHVua1wiKTtcbiAgICAgICAgICAgIHZhciBpc1ZIb29rID0gcmVxdWlyZShcIi4vaXMtdmhvb2tcIik7XG5cbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gVmlydHVhbE5vZGU7XG5cbiAgICAgICAgICAgIHZhciBub1Byb3BlcnRpZXMgPSB7fTtcbiAgICAgICAgICAgIHZhciBub0NoaWxkcmVuID0gW107XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIFZpcnR1YWxOb2RlKHRhZ05hbWUsIHByb3BlcnRpZXMsIGNoaWxkcmVuLCBrZXksIG5hbWVzcGFjZSkge1xuICAgICAgICAgICAgICAgIHRoaXMudGFnTmFtZSA9IHRhZ05hbWU7XG4gICAgICAgICAgICAgICAgdGhpcy5wcm9wZXJ0aWVzID0gcHJvcGVydGllcyB8fCBub1Byb3BlcnRpZXM7XG4gICAgICAgICAgICAgICAgdGhpcy5jaGlsZHJlbiA9IGNoaWxkcmVuIHx8IG5vQ2hpbGRyZW47XG4gICAgICAgICAgICAgICAgdGhpcy5rZXkgPSBrZXkgIT0gbnVsbCA/IFN0cmluZyhrZXkpIDogdW5kZWZpbmVkO1xuICAgICAgICAgICAgICAgIHRoaXMubmFtZXNwYWNlID0gdHlwZW9mIG5hbWVzcGFjZSA9PT0gXCJzdHJpbmdcIiA/IG5hbWVzcGFjZSA6IG51bGw7XG5cbiAgICAgICAgICAgICAgICB2YXIgY291bnQgPSBjaGlsZHJlbiAmJiBjaGlsZHJlbi5sZW5ndGggfHwgMDtcbiAgICAgICAgICAgICAgICB2YXIgZGVzY2VuZGFudHMgPSAwO1xuICAgICAgICAgICAgICAgIHZhciBoYXNXaWRnZXRzID0gZmFsc2U7XG4gICAgICAgICAgICAgICAgdmFyIGhhc1RodW5rcyA9IGZhbHNlO1xuICAgICAgICAgICAgICAgIHZhciBkZXNjZW5kYW50SG9va3MgPSBmYWxzZTtcbiAgICAgICAgICAgICAgICB2YXIgaG9va3M7XG5cbiAgICAgICAgICAgICAgICBmb3IgKHZhciBwcm9wTmFtZSBpbiBwcm9wZXJ0aWVzKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmIChwcm9wZXJ0aWVzLmhhc093blByb3BlcnR5KHByb3BOYW1lKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgdmFyIHByb3BlcnR5ID0gcHJvcGVydGllc1twcm9wTmFtZV07XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoaXNWSG9vayhwcm9wZXJ0eSkgJiYgcHJvcGVydHkudW5ob29rKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKCFob29rcykge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBob29rcyA9IHt9O1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGhvb2tzW3Byb3BOYW1lXSA9IHByb3BlcnR5O1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCBjb3VudDsgaSsrKSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciBjaGlsZCA9IGNoaWxkcmVuW2ldO1xuICAgICAgICAgICAgICAgICAgICBpZiAoaXNWTm9kZShjaGlsZCkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGRlc2NlbmRhbnRzICs9IGNoaWxkLmNvdW50IHx8IDA7XG5cbiAgICAgICAgICAgICAgICAgICAgICAgIGlmICghaGFzV2lkZ2V0cyAmJiBjaGlsZC5oYXNXaWRnZXRzKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaGFzV2lkZ2V0cyA9IHRydWU7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgICAgIGlmICghaGFzVGh1bmtzICYmIGNoaWxkLmhhc1RodW5rcykge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGhhc1RodW5rcyA9IHRydWU7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgICAgIGlmICghZGVzY2VuZGFudEhvb2tzICYmIChjaGlsZC5ob29rcyB8fCBjaGlsZC5kZXNjZW5kYW50SG9va3MpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgZGVzY2VuZGFudEhvb2tzID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIGlmICghaGFzV2lkZ2V0cyAmJiBpc1dpZGdldChjaGlsZCkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmICh0eXBlb2YgY2hpbGQuZGVzdHJveSA9PT0gXCJmdW5jdGlvblwiKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaGFzV2lkZ2V0cyA9IHRydWU7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoIWhhc1RodW5rcyAmJiBpc1RodW5rKGNoaWxkKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgaGFzVGh1bmtzID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHRoaXMuY291bnQgPSBjb3VudCArIGRlc2NlbmRhbnRzO1xuICAgICAgICAgICAgICAgIHRoaXMuaGFzV2lkZ2V0cyA9IGhhc1dpZGdldHM7XG4gICAgICAgICAgICAgICAgdGhpcy5oYXNUaHVua3MgPSBoYXNUaHVua3M7XG4gICAgICAgICAgICAgICAgdGhpcy5ob29rcyA9IGhvb2tzO1xuICAgICAgICAgICAgICAgIHRoaXMuZGVzY2VuZGFudEhvb2tzID0gZGVzY2VuZGFudEhvb2tzO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBWaXJ0dWFsTm9kZS5wcm90b3R5cGUudmVyc2lvbiA9IHZlcnNpb247XG4gICAgICAgICAgICBWaXJ0dWFsTm9kZS5wcm90b3R5cGUudHlwZSA9IFwiVmlydHVhbE5vZGVcIjtcbiAgICAgICAgfSwgeyBcIi4vaXMtdGh1bmtcIjogMjUsIFwiLi9pcy12aG9va1wiOiAyNiwgXCIuL2lzLXZub2RlXCI6IDI3LCBcIi4vaXMtd2lkZ2V0XCI6IDI5LCBcIi4vdmVyc2lvblwiOiAzMCB9XSwgMzI6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICB2YXIgdmVyc2lvbiA9IHJlcXVpcmUoXCIuL3ZlcnNpb25cIik7XG5cbiAgICAgICAgICAgIFZpcnR1YWxQYXRjaC5OT05FID0gMDtcbiAgICAgICAgICAgIFZpcnR1YWxQYXRjaC5WVEVYVCA9IDE7XG4gICAgICAgICAgICBWaXJ0dWFsUGF0Y2guVk5PREUgPSAyO1xuICAgICAgICAgICAgVmlydHVhbFBhdGNoLldJREdFVCA9IDM7XG4gICAgICAgICAgICBWaXJ0dWFsUGF0Y2guUFJPUFMgPSA0O1xuICAgICAgICAgICAgVmlydHVhbFBhdGNoLk9SREVSID0gNTtcbiAgICAgICAgICAgIFZpcnR1YWxQYXRjaC5JTlNFUlQgPSA2O1xuICAgICAgICAgICAgVmlydHVhbFBhdGNoLlJFTU9WRSA9IDc7XG4gICAgICAgICAgICBWaXJ0dWFsUGF0Y2guVEhVTksgPSA4O1xuXG4gICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IFZpcnR1YWxQYXRjaDtcblxuICAgICAgICAgICAgZnVuY3Rpb24gVmlydHVhbFBhdGNoKHR5cGUsIHZOb2RlLCBwYXRjaCkge1xuICAgICAgICAgICAgICAgIHRoaXMudHlwZSA9IE51bWJlcih0eXBlKTtcbiAgICAgICAgICAgICAgICB0aGlzLnZOb2RlID0gdk5vZGU7XG4gICAgICAgICAgICAgICAgdGhpcy5wYXRjaCA9IHBhdGNoO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBWaXJ0dWFsUGF0Y2gucHJvdG90eXBlLnZlcnNpb24gPSB2ZXJzaW9uO1xuICAgICAgICAgICAgVmlydHVhbFBhdGNoLnByb3RvdHlwZS50eXBlID0gXCJWaXJ0dWFsUGF0Y2hcIjtcbiAgICAgICAgfSwgeyBcIi4vdmVyc2lvblwiOiAzMCB9XSwgMzM6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICB2YXIgdmVyc2lvbiA9IHJlcXVpcmUoXCIuL3ZlcnNpb25cIik7XG5cbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gVmlydHVhbFRleHQ7XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIFZpcnR1YWxUZXh0KHRleHQpIHtcbiAgICAgICAgICAgICAgICB0aGlzLnRleHQgPSBTdHJpbmcodGV4dCk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIFZpcnR1YWxUZXh0LnByb3RvdHlwZS52ZXJzaW9uID0gdmVyc2lvbjtcbiAgICAgICAgICAgIFZpcnR1YWxUZXh0LnByb3RvdHlwZS50eXBlID0gXCJWaXJ0dWFsVGV4dFwiO1xuICAgICAgICB9LCB7IFwiLi92ZXJzaW9uXCI6IDMwIH1dLCAzNDogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHtcbiAgICAgICAgICAgIHZhciBpc09iamVjdCA9IHJlcXVpcmUoXCJpcy1vYmplY3RcIik7XG4gICAgICAgICAgICB2YXIgaXNIb29rID0gcmVxdWlyZShcIi4uL3Zub2RlL2lzLXZob29rXCIpO1xuXG4gICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IGRpZmZQcm9wcztcblxuICAgICAgICAgICAgZnVuY3Rpb24gZGlmZlByb3BzKGEsIGIpIHtcbiAgICAgICAgICAgICAgICB2YXIgZGlmZjtcblxuICAgICAgICAgICAgICAgIGZvciAodmFyIGFLZXkgaW4gYSkge1xuICAgICAgICAgICAgICAgICAgICBpZiAoIShhS2V5IGluIGIpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBkaWZmID0gZGlmZiB8fCB7fTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGRpZmZbYUtleV0gPSB1bmRlZmluZWQ7XG4gICAgICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgICAgICB2YXIgYVZhbHVlID0gYVthS2V5XTtcbiAgICAgICAgICAgICAgICAgICAgdmFyIGJWYWx1ZSA9IGJbYUtleV07XG5cbiAgICAgICAgICAgICAgICAgICAgaWYgKGFWYWx1ZSA9PT0gYlZhbHVlKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBjb250aW51ZTtcbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIGlmIChpc09iamVjdChhVmFsdWUpICYmIGlzT2JqZWN0KGJWYWx1ZSkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChnZXRQcm90b3R5cGUoYlZhbHVlKSAhPT0gZ2V0UHJvdG90eXBlKGFWYWx1ZSkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBkaWZmID0gZGlmZiB8fCB7fTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBkaWZmW2FLZXldID0gYlZhbHVlO1xuICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIGlmIChpc0hvb2soYlZhbHVlKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRpZmYgPSBkaWZmIHx8IHt9O1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRpZmZbYUtleV0gPSBiVmFsdWU7XG4gICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZhciBvYmplY3REaWZmID0gZGlmZlByb3BzKGFWYWx1ZSwgYlZhbHVlKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAob2JqZWN0RGlmZikge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBkaWZmID0gZGlmZiB8fCB7fTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZGlmZlthS2V5XSA9IG9iamVjdERpZmY7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgZGlmZiA9IGRpZmYgfHwge307XG4gICAgICAgICAgICAgICAgICAgICAgICBkaWZmW2FLZXldID0gYlZhbHVlO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgZm9yICh2YXIgYktleSBpbiBiKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmICghKGJLZXkgaW4gYSkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGRpZmYgPSBkaWZmIHx8IHt9O1xuICAgICAgICAgICAgICAgICAgICAgICAgZGlmZltiS2V5XSA9IGJbYktleV07XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICByZXR1cm4gZGlmZjtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZnVuY3Rpb24gZ2V0UHJvdG90eXBlKHZhbHVlKSB7XG4gICAgICAgICAgICAgICAgaWYgKE9iamVjdC5nZXRQcm90b3R5cGVPZikge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gT2JqZWN0LmdldFByb3RvdHlwZU9mKHZhbHVlKTtcbiAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKHZhbHVlLl9fcHJvdG9fXykge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gdmFsdWUuX19wcm90b19fO1xuICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAodmFsdWUuY29uc3RydWN0b3IpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHZhbHVlLmNvbnN0cnVjdG9yLnByb3RvdHlwZTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH0sIHsgXCIuLi92bm9kZS9pcy12aG9va1wiOiAyNiwgXCJpcy1vYmplY3RcIjogMTEgfV0sIDM1OiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge1xuICAgICAgICAgICAgdmFyIGlzQXJyYXkgPSByZXF1aXJlKFwieC1pcy1hcnJheVwiKTtcblxuICAgICAgICAgICAgdmFyIFZQYXRjaCA9IHJlcXVpcmUoXCIuLi92bm9kZS92cGF0Y2hcIik7XG4gICAgICAgICAgICB2YXIgaXNWTm9kZSA9IHJlcXVpcmUoXCIuLi92bm9kZS9pcy12bm9kZVwiKTtcbiAgICAgICAgICAgIHZhciBpc1ZUZXh0ID0gcmVxdWlyZShcIi4uL3Zub2RlL2lzLXZ0ZXh0XCIpO1xuICAgICAgICAgICAgdmFyIGlzV2lkZ2V0ID0gcmVxdWlyZShcIi4uL3Zub2RlL2lzLXdpZGdldFwiKTtcbiAgICAgICAgICAgIHZhciBpc1RodW5rID0gcmVxdWlyZShcIi4uL3Zub2RlL2lzLXRodW5rXCIpO1xuICAgICAgICAgICAgdmFyIGhhbmRsZVRodW5rID0gcmVxdWlyZShcIi4uL3Zub2RlL2hhbmRsZS10aHVua1wiKTtcblxuICAgICAgICAgICAgdmFyIGRpZmZQcm9wcyA9IHJlcXVpcmUoXCIuL2RpZmYtcHJvcHNcIik7XG5cbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gZGlmZjtcblxuICAgICAgICAgICAgZnVuY3Rpb24gZGlmZihhLCBiKSB7XG4gICAgICAgICAgICAgICAgdmFyIHBhdGNoID0geyBhOiBhIH07XG4gICAgICAgICAgICAgICAgd2FsayhhLCBiLCBwYXRjaCwgMCk7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHBhdGNoO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBmdW5jdGlvbiB3YWxrKGEsIGIsIHBhdGNoLCBpbmRleCkge1xuICAgICAgICAgICAgICAgIGlmIChhID09PSBiKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICB2YXIgYXBwbHkgPSBwYXRjaFtpbmRleF07XG4gICAgICAgICAgICAgICAgdmFyIGFwcGx5Q2xlYXIgPSBmYWxzZTtcblxuICAgICAgICAgICAgICAgIGlmIChpc1RodW5rKGEpIHx8IGlzVGh1bmsoYikpIHtcbiAgICAgICAgICAgICAgICAgICAgdGh1bmtzKGEsIGIsIHBhdGNoLCBpbmRleCk7XG4gICAgICAgICAgICAgICAgfSBlbHNlIGlmIChiID09IG51bGwpIHtcblxuICAgICAgICAgICAgICAgICAgICAvLyBJZiBhIGlzIGEgd2lkZ2V0IHdlIHdpbGwgYWRkIGEgcmVtb3ZlIHBhdGNoIGZvciBpdFxuICAgICAgICAgICAgICAgICAgICAvLyBPdGhlcndpc2UgYW55IGNoaWxkIHdpZGdldHMvaG9va3MgbXVzdCBiZSBkZXN0cm95ZWQuXG4gICAgICAgICAgICAgICAgICAgIC8vIFRoaXMgcHJldmVudHMgYWRkaW5nIHR3byByZW1vdmUgcGF0Y2hlcyBmb3IgYSB3aWRnZXQuXG4gICAgICAgICAgICAgICAgICAgIGlmICghaXNXaWRnZXQoYSkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGNsZWFyU3RhdGUoYSwgcGF0Y2gsIGluZGV4KTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGFwcGx5ID0gcGF0Y2hbaW5kZXhdO1xuICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgYXBwbHkgPSBhcHBlbmRQYXRjaChhcHBseSwgbmV3IFZQYXRjaChWUGF0Y2guUkVNT1ZFLCBhLCBiKSk7XG4gICAgICAgICAgICAgICAgfSBlbHNlIGlmIChpc1ZOb2RlKGIpKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmIChpc1ZOb2RlKGEpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoYS50YWdOYW1lID09PSBiLnRhZ05hbWUgJiYgYS5uYW1lc3BhY2UgPT09IGIubmFtZXNwYWNlICYmIGEua2V5ID09PSBiLmtleSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZhciBwcm9wc1BhdGNoID0gZGlmZlByb3BzKGEucHJvcGVydGllcywgYi5wcm9wZXJ0aWVzKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAocHJvcHNQYXRjaCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBhcHBseSA9IGFwcGVuZFBhdGNoKGFwcGx5LCBuZXcgVlBhdGNoKFZQYXRjaC5QUk9QUywgYSwgcHJvcHNQYXRjaCkpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBhcHBseSA9IGRpZmZDaGlsZHJlbihhLCBiLCBwYXRjaCwgYXBwbHksIGluZGV4KTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgYXBwbHkgPSBhcHBlbmRQYXRjaChhcHBseSwgbmV3IFZQYXRjaChWUGF0Y2guVk5PREUsIGEsIGIpKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBhcHBseUNsZWFyID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGFwcGx5ID0gYXBwZW5kUGF0Y2goYXBwbHksIG5ldyBWUGF0Y2goVlBhdGNoLlZOT0RFLCBhLCBiKSk7XG4gICAgICAgICAgICAgICAgICAgICAgICBhcHBseUNsZWFyID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoaXNWVGV4dChiKSkge1xuICAgICAgICAgICAgICAgICAgICBpZiAoIWlzVlRleHQoYSkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGFwcGx5ID0gYXBwZW5kUGF0Y2goYXBwbHksIG5ldyBWUGF0Y2goVlBhdGNoLlZURVhULCBhLCBiKSk7XG4gICAgICAgICAgICAgICAgICAgICAgICBhcHBseUNsZWFyID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIGlmIChhLnRleHQgIT09IGIudGV4dCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgYXBwbHkgPSBhcHBlbmRQYXRjaChhcHBseSwgbmV3IFZQYXRjaChWUGF0Y2guVlRFWFQsIGEsIGIpKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoaXNXaWRnZXQoYikpIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKCFpc1dpZGdldChhKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgYXBwbHlDbGVhciA9IHRydWU7XG4gICAgICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgICAgICBhcHBseSA9IGFwcGVuZFBhdGNoKGFwcGx5LCBuZXcgVlBhdGNoKFZQYXRjaC5XSURHRVQsIGEsIGIpKTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICBpZiAoYXBwbHkpIHtcbiAgICAgICAgICAgICAgICAgICAgcGF0Y2hbaW5kZXhdID0gYXBwbHk7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgaWYgKGFwcGx5Q2xlYXIpIHtcbiAgICAgICAgICAgICAgICAgICAgY2xlYXJTdGF0ZShhLCBwYXRjaCwgaW5kZXgpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZnVuY3Rpb24gZGlmZkNoaWxkcmVuKGEsIGIsIHBhdGNoLCBhcHBseSwgaW5kZXgpIHtcbiAgICAgICAgICAgICAgICB2YXIgYUNoaWxkcmVuID0gYS5jaGlsZHJlbjtcbiAgICAgICAgICAgICAgICB2YXIgb3JkZXJlZFNldCA9IHJlb3JkZXIoYUNoaWxkcmVuLCBiLmNoaWxkcmVuKTtcbiAgICAgICAgICAgICAgICB2YXIgYkNoaWxkcmVuID0gb3JkZXJlZFNldC5jaGlsZHJlbjtcblxuICAgICAgICAgICAgICAgIHZhciBhTGVuID0gYUNoaWxkcmVuLmxlbmd0aDtcbiAgICAgICAgICAgICAgICB2YXIgYkxlbiA9IGJDaGlsZHJlbi5sZW5ndGg7XG4gICAgICAgICAgICAgICAgdmFyIGxlbiA9IGFMZW4gPiBiTGVuID8gYUxlbiA6IGJMZW47XG5cbiAgICAgICAgICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IGxlbjsgaSsrKSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciBsZWZ0Tm9kZSA9IGFDaGlsZHJlbltpXTtcbiAgICAgICAgICAgICAgICAgICAgdmFyIHJpZ2h0Tm9kZSA9IGJDaGlsZHJlbltpXTtcbiAgICAgICAgICAgICAgICAgICAgaW5kZXggKz0gMTtcblxuICAgICAgICAgICAgICAgICAgICBpZiAoIWxlZnROb2RlKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAocmlnaHROb2RlKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gRXhjZXNzIG5vZGVzIGluIGIgbmVlZCB0byBiZSBhZGRlZFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGFwcGx5ID0gYXBwZW5kUGF0Y2goYXBwbHksIG5ldyBWUGF0Y2goVlBhdGNoLklOU0VSVCwgbnVsbCwgcmlnaHROb2RlKSk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICB3YWxrKGxlZnROb2RlLCByaWdodE5vZGUsIHBhdGNoLCBpbmRleCk7XG4gICAgICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgICAgICBpZiAoaXNWTm9kZShsZWZ0Tm9kZSkgJiYgbGVmdE5vZGUuY291bnQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGluZGV4ICs9IGxlZnROb2RlLmNvdW50O1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgaWYgKG9yZGVyZWRTZXQubW92ZXMpIHtcbiAgICAgICAgICAgICAgICAgICAgLy8gUmVvcmRlciBub2RlcyBsYXN0XG4gICAgICAgICAgICAgICAgICAgIGFwcGx5ID0gYXBwZW5kUGF0Y2goYXBwbHksIG5ldyBWUGF0Y2goVlBhdGNoLk9SREVSLCBhLCBvcmRlcmVkU2V0Lm1vdmVzKSk7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgcmV0dXJuIGFwcGx5O1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBmdW5jdGlvbiBjbGVhclN0YXRlKHZOb2RlLCBwYXRjaCwgaW5kZXgpIHtcbiAgICAgICAgICAgICAgICAvLyBUT0RPOiBNYWtlIHRoaXMgYSBzaW5nbGUgd2Fsaywgbm90IHR3b1xuICAgICAgICAgICAgICAgIHVuaG9vayh2Tm9kZSwgcGF0Y2gsIGluZGV4KTtcbiAgICAgICAgICAgICAgICBkZXN0cm95V2lkZ2V0cyh2Tm9kZSwgcGF0Y2gsIGluZGV4KTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgLy8gUGF0Y2ggcmVjb3JkcyBmb3IgYWxsIGRlc3Ryb3llZCB3aWRnZXRzIG11c3QgYmUgYWRkZWQgYmVjYXVzZSB3ZSBuZWVkXG4gICAgICAgICAgICAvLyBhIERPTSBub2RlIHJlZmVyZW5jZSBmb3IgdGhlIGRlc3Ryb3kgZnVuY3Rpb25cbiAgICAgICAgICAgIGZ1bmN0aW9uIGRlc3Ryb3lXaWRnZXRzKHZOb2RlLCBwYXRjaCwgaW5kZXgpIHtcbiAgICAgICAgICAgICAgICBpZiAoaXNXaWRnZXQodk5vZGUpKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmICh0eXBlb2Ygdk5vZGUuZGVzdHJveSA9PT0gXCJmdW5jdGlvblwiKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBwYXRjaFtpbmRleF0gPSBhcHBlbmRQYXRjaChwYXRjaFtpbmRleF0sIG5ldyBWUGF0Y2goVlBhdGNoLlJFTU9WRSwgdk5vZGUsIG51bGwpKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoaXNWTm9kZSh2Tm9kZSkgJiYgKHZOb2RlLmhhc1dpZGdldHMgfHwgdk5vZGUuaGFzVGh1bmtzKSkge1xuICAgICAgICAgICAgICAgICAgICB2YXIgY2hpbGRyZW4gPSB2Tm9kZS5jaGlsZHJlbjtcbiAgICAgICAgICAgICAgICAgICAgdmFyIGxlbiA9IGNoaWxkcmVuLmxlbmd0aDtcbiAgICAgICAgICAgICAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCBsZW47IGkrKykge1xuICAgICAgICAgICAgICAgICAgICAgICAgdmFyIGNoaWxkID0gY2hpbGRyZW5baV07XG4gICAgICAgICAgICAgICAgICAgICAgICBpbmRleCArPSAxO1xuXG4gICAgICAgICAgICAgICAgICAgICAgICBkZXN0cm95V2lkZ2V0cyhjaGlsZCwgcGF0Y2gsIGluZGV4KTtcblxuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGlzVk5vZGUoY2hpbGQpICYmIGNoaWxkLmNvdW50KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaW5kZXggKz0gY2hpbGQuY291bnQ7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKGlzVGh1bmsodk5vZGUpKSB7XG4gICAgICAgICAgICAgICAgICAgIHRodW5rcyh2Tm9kZSwgbnVsbCwgcGF0Y2gsIGluZGV4KTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIC8vIENyZWF0ZSBhIHN1Yi1wYXRjaCBmb3IgdGh1bmtzXG4gICAgICAgICAgICBmdW5jdGlvbiB0aHVua3MoYSwgYiwgcGF0Y2gsIGluZGV4KSB7XG4gICAgICAgICAgICAgICAgdmFyIG5vZGVzID0gaGFuZGxlVGh1bmsoYSwgYik7XG4gICAgICAgICAgICAgICAgdmFyIHRodW5rUGF0Y2ggPSBkaWZmKG5vZGVzLmEsIG5vZGVzLmIpO1xuICAgICAgICAgICAgICAgIGlmIChoYXNQYXRjaGVzKHRodW5rUGF0Y2gpKSB7XG4gICAgICAgICAgICAgICAgICAgIHBhdGNoW2luZGV4XSA9IG5ldyBWUGF0Y2goVlBhdGNoLlRIVU5LLCBudWxsLCB0aHVua1BhdGNoKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIGhhc1BhdGNoZXMocGF0Y2gpIHtcbiAgICAgICAgICAgICAgICBmb3IgKHZhciBpbmRleCBpbiBwYXRjaCkge1xuICAgICAgICAgICAgICAgICAgICBpZiAoaW5kZXggIT09IFwiYVwiKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgLy8gRXhlY3V0ZSBob29rcyB3aGVuIHR3byBub2RlcyBhcmUgaWRlbnRpY2FsXG4gICAgICAgICAgICBmdW5jdGlvbiB1bmhvb2sodk5vZGUsIHBhdGNoLCBpbmRleCkge1xuICAgICAgICAgICAgICAgIGlmIChpc1ZOb2RlKHZOb2RlKSkge1xuICAgICAgICAgICAgICAgICAgICBpZiAodk5vZGUuaG9va3MpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHBhdGNoW2luZGV4XSA9IGFwcGVuZFBhdGNoKHBhdGNoW2luZGV4XSwgbmV3IFZQYXRjaChWUGF0Y2guUFJPUFMsIHZOb2RlLCB1bmRlZmluZWRLZXlzKHZOb2RlLmhvb2tzKSkpO1xuICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgaWYgKHZOb2RlLmRlc2NlbmRhbnRIb29rcyB8fCB2Tm9kZS5oYXNUaHVua3MpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHZhciBjaGlsZHJlbiA9IHZOb2RlLmNoaWxkcmVuO1xuICAgICAgICAgICAgICAgICAgICAgICAgdmFyIGxlbiA9IGNoaWxkcmVuLmxlbmd0aDtcbiAgICAgICAgICAgICAgICAgICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgbGVuOyBpKyspIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB2YXIgY2hpbGQgPSBjaGlsZHJlbltpXTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpbmRleCArPSAxO1xuXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdW5ob29rKGNoaWxkLCBwYXRjaCwgaW5kZXgpO1xuXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGlzVk5vZGUoY2hpbGQpICYmIGNoaWxkLmNvdW50KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGluZGV4ICs9IGNoaWxkLmNvdW50O1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoaXNUaHVuayh2Tm9kZSkpIHtcbiAgICAgICAgICAgICAgICAgICAgdGh1bmtzKHZOb2RlLCBudWxsLCBwYXRjaCwgaW5kZXgpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZnVuY3Rpb24gdW5kZWZpbmVkS2V5cyhvYmopIHtcbiAgICAgICAgICAgICAgICB2YXIgcmVzdWx0ID0ge307XG5cbiAgICAgICAgICAgICAgICBmb3IgKHZhciBrZXkgaW4gb2JqKSB7XG4gICAgICAgICAgICAgICAgICAgIHJlc3VsdFtrZXldID0gdW5kZWZpbmVkO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHJldHVybiByZXN1bHQ7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIC8vIExpc3QgZGlmZiwgbmFpdmUgbGVmdCB0byByaWdodCByZW9yZGVyaW5nXG4gICAgICAgICAgICBmdW5jdGlvbiByZW9yZGVyKGFDaGlsZHJlbiwgYkNoaWxkcmVuKSB7XG4gICAgICAgICAgICAgICAgLy8gTyhNKSB0aW1lLCBPKE0pIG1lbW9yeVxuICAgICAgICAgICAgICAgIHZhciBiQ2hpbGRJbmRleCA9IGtleUluZGV4KGJDaGlsZHJlbik7XG4gICAgICAgICAgICAgICAgdmFyIGJLZXlzID0gYkNoaWxkSW5kZXgua2V5cztcbiAgICAgICAgICAgICAgICB2YXIgYkZyZWUgPSBiQ2hpbGRJbmRleC5mcmVlO1xuXG4gICAgICAgICAgICAgICAgaWYgKGJGcmVlLmxlbmd0aCA9PT0gYkNoaWxkcmVuLmxlbmd0aCkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgICAgICAgICAgICAgY2hpbGRyZW46IGJDaGlsZHJlbixcbiAgICAgICAgICAgICAgICAgICAgICAgIG1vdmVzOiBudWxsXG4gICAgICAgICAgICAgICAgICAgIH07XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgLy8gTyhOKSB0aW1lLCBPKE4pIG1lbW9yeVxuICAgICAgICAgICAgICAgIHZhciBhQ2hpbGRJbmRleCA9IGtleUluZGV4KGFDaGlsZHJlbik7XG4gICAgICAgICAgICAgICAgdmFyIGFLZXlzID0gYUNoaWxkSW5kZXgua2V5cztcbiAgICAgICAgICAgICAgICB2YXIgYUZyZWUgPSBhQ2hpbGRJbmRleC5mcmVlO1xuXG4gICAgICAgICAgICAgICAgaWYgKGFGcmVlLmxlbmd0aCA9PT0gYUNoaWxkcmVuLmxlbmd0aCkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgICAgICAgICAgICAgY2hpbGRyZW46IGJDaGlsZHJlbixcbiAgICAgICAgICAgICAgICAgICAgICAgIG1vdmVzOiBudWxsXG4gICAgICAgICAgICAgICAgICAgIH07XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgLy8gTyhNQVgoTiwgTSkpIG1lbW9yeVxuICAgICAgICAgICAgICAgIHZhciBuZXdDaGlsZHJlbiA9IFtdO1xuXG4gICAgICAgICAgICAgICAgdmFyIGZyZWVJbmRleCA9IDA7XG4gICAgICAgICAgICAgICAgdmFyIGZyZWVDb3VudCA9IGJGcmVlLmxlbmd0aDtcbiAgICAgICAgICAgICAgICB2YXIgZGVsZXRlZEl0ZW1zID0gMDtcblxuICAgICAgICAgICAgICAgIC8vIEl0ZXJhdGUgdGhyb3VnaCBhIGFuZCBtYXRjaCBhIG5vZGUgaW4gYlxuICAgICAgICAgICAgICAgIC8vIE8oTikgdGltZSxcbiAgICAgICAgICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IGFDaGlsZHJlbi5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgICAgICAgICB2YXIgYUl0ZW0gPSBhQ2hpbGRyZW5baV07XG4gICAgICAgICAgICAgICAgICAgIHZhciBpdGVtSW5kZXg7XG5cbiAgICAgICAgICAgICAgICAgICAgaWYgKGFJdGVtLmtleSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGJLZXlzLmhhc093blByb3BlcnR5KGFJdGVtLmtleSkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBNYXRjaCB1cCB0aGUgb2xkIGtleXNcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpdGVtSW5kZXggPSBiS2V5c1thSXRlbS5rZXldO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIG5ld0NoaWxkcmVuLnB1c2goYkNoaWxkcmVuW2l0ZW1JbmRleF0pO1xuICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBSZW1vdmUgb2xkIGtleWVkIGl0ZW1zXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaXRlbUluZGV4ID0gaSAtIGRlbGV0ZWRJdGVtcysrO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIG5ld0NoaWxkcmVuLnB1c2gobnVsbCk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAvLyBNYXRjaCB0aGUgaXRlbSBpbiBhIHdpdGggdGhlIG5leHQgZnJlZSBpdGVtIGluIGJcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChmcmVlSW5kZXggPCBmcmVlQ291bnQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpdGVtSW5kZXggPSBiRnJlZVtmcmVlSW5kZXgrK107XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgbmV3Q2hpbGRyZW4ucHVzaChiQ2hpbGRyZW5baXRlbUluZGV4XSk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIFRoZXJlIGFyZSBubyBmcmVlIGl0ZW1zIGluIGIgdG8gbWF0Y2ggd2l0aFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIHRoZSBmcmVlIGl0ZW1zIGluIGEsIHNvIHRoZSBleHRyYSBmcmVlIG5vZGVzXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gYXJlIGRlbGV0ZWQuXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaXRlbUluZGV4ID0gaSAtIGRlbGV0ZWRJdGVtcysrO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIG5ld0NoaWxkcmVuLnB1c2gobnVsbCk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICB2YXIgbGFzdEZyZWVJbmRleCA9IGZyZWVJbmRleCA+PSBiRnJlZS5sZW5ndGggPyBiQ2hpbGRyZW4ubGVuZ3RoIDogYkZyZWVbZnJlZUluZGV4XTtcblxuICAgICAgICAgICAgICAgIC8vIEl0ZXJhdGUgdGhyb3VnaCBiIGFuZCBhcHBlbmQgYW55IG5ldyBrZXlzXG4gICAgICAgICAgICAgICAgLy8gTyhNKSB0aW1lXG4gICAgICAgICAgICAgICAgZm9yICh2YXIgaiA9IDA7IGogPCBiQ2hpbGRyZW4ubGVuZ3RoOyBqKyspIHtcbiAgICAgICAgICAgICAgICAgICAgdmFyIG5ld0l0ZW0gPSBiQ2hpbGRyZW5bal07XG5cbiAgICAgICAgICAgICAgICAgICAgaWYgKG5ld0l0ZW0ua2V5KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoIWFLZXlzLmhhc093blByb3BlcnR5KG5ld0l0ZW0ua2V5KSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIEFkZCBhbnkgbmV3IGtleWVkIGl0ZW1zXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gV2UgYXJlIGFkZGluZyBuZXcgaXRlbXMgdG8gdGhlIGVuZCBhbmQgdGhlbiBzb3J0aW5nIHRoZW1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBpbiBwbGFjZS4gSW4gZnV0dXJlIHdlIHNob3VsZCBpbnNlcnQgbmV3IGl0ZW1zIGluIHBsYWNlLlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIG5ld0NoaWxkcmVuLnB1c2gobmV3SXRlbSk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoaiA+PSBsYXN0RnJlZUluZGV4KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAvLyBBZGQgYW55IGxlZnRvdmVyIG5vbi1rZXllZCBpdGVtc1xuICAgICAgICAgICAgICAgICAgICAgICAgbmV3Q2hpbGRyZW4ucHVzaChuZXdJdGVtKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHZhciBzaW11bGF0ZSA9IG5ld0NoaWxkcmVuLnNsaWNlKCk7XG4gICAgICAgICAgICAgICAgdmFyIHNpbXVsYXRlSW5kZXggPSAwO1xuICAgICAgICAgICAgICAgIHZhciByZW1vdmVzID0gW107XG4gICAgICAgICAgICAgICAgdmFyIGluc2VydHMgPSBbXTtcbiAgICAgICAgICAgICAgICB2YXIgc2ltdWxhdGVJdGVtO1xuXG4gICAgICAgICAgICAgICAgZm9yICh2YXIgayA9IDA7IGsgPCBiQ2hpbGRyZW4ubGVuZ3RoOykge1xuICAgICAgICAgICAgICAgICAgICB2YXIgd2FudGVkSXRlbSA9IGJDaGlsZHJlbltrXTtcbiAgICAgICAgICAgICAgICAgICAgc2ltdWxhdGVJdGVtID0gc2ltdWxhdGVbc2ltdWxhdGVJbmRleF07XG5cbiAgICAgICAgICAgICAgICAgICAgLy8gcmVtb3ZlIGl0ZW1zXG4gICAgICAgICAgICAgICAgICAgIHdoaWxlIChzaW11bGF0ZUl0ZW0gPT09IG51bGwgJiYgc2ltdWxhdGUubGVuZ3RoKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICByZW1vdmVzLnB1c2gocmVtb3ZlKHNpbXVsYXRlLCBzaW11bGF0ZUluZGV4LCBudWxsKSk7XG4gICAgICAgICAgICAgICAgICAgICAgICBzaW11bGF0ZUl0ZW0gPSBzaW11bGF0ZVtzaW11bGF0ZUluZGV4XTtcbiAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgIGlmICghc2ltdWxhdGVJdGVtIHx8IHNpbXVsYXRlSXRlbS5rZXkgIT09IHdhbnRlZEl0ZW0ua2V5KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAvLyBpZiB3ZSBuZWVkIGEga2V5IGluIHRoaXMgcG9zaXRpb24uLi5cbiAgICAgICAgICAgICAgICAgICAgICAgIGlmICh3YW50ZWRJdGVtLmtleSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChzaW11bGF0ZUl0ZW0gJiYgc2ltdWxhdGVJdGVtLmtleSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBpZiBhbiBpbnNlcnQgZG9lc24ndCBwdXQgdGhpcyBrZXkgaW4gcGxhY2UsIGl0IG5lZWRzIHRvIG1vdmVcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGJLZXlzW3NpbXVsYXRlSXRlbS5rZXldICE9PSBrICsgMSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmVtb3Zlcy5wdXNoKHJlbW92ZShzaW11bGF0ZSwgc2ltdWxhdGVJbmRleCwgc2ltdWxhdGVJdGVtLmtleSkpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc2ltdWxhdGVJdGVtID0gc2ltdWxhdGVbc2ltdWxhdGVJbmRleF07XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBpZiB0aGUgcmVtb3ZlIGRpZG4ndCBwdXQgdGhlIHdhbnRlZCBpdGVtIGluIHBsYWNlLCB3ZSBuZWVkIHRvIGluc2VydCBpdFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKCFzaW11bGF0ZUl0ZW0gfHwgc2ltdWxhdGVJdGVtLmtleSAhPT0gd2FudGVkSXRlbS5rZXkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpbnNlcnRzLnB1c2goeyBrZXk6IHdhbnRlZEl0ZW0ua2V5LCB0bzogayB9KTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIGl0ZW1zIGFyZSBtYXRjaGluZywgc28gc2tpcCBhaGVhZFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc2ltdWxhdGVJbmRleCsrO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaW5zZXJ0cy5wdXNoKHsga2V5OiB3YW50ZWRJdGVtLmtleSwgdG86IGsgfSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpbnNlcnRzLnB1c2goeyBrZXk6IHdhbnRlZEl0ZW0ua2V5LCB0bzogayB9KTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaysrO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgLy8gYSBrZXkgaW4gc2ltdWxhdGUgaGFzIG5vIG1hdGNoaW5nIHdhbnRlZCBrZXksIHJlbW92ZSBpdFxuICAgICAgICAgICAgICAgICAgICAgICAgZWxzZSBpZiAoc2ltdWxhdGVJdGVtICYmIHNpbXVsYXRlSXRlbS5rZXkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICByZW1vdmVzLnB1c2gocmVtb3ZlKHNpbXVsYXRlLCBzaW11bGF0ZUluZGV4LCBzaW11bGF0ZUl0ZW0ua2V5KSk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBzaW11bGF0ZUluZGV4Kys7XG4gICAgICAgICAgICAgICAgICAgICAgICBrKys7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAvLyByZW1vdmUgYWxsIHRoZSByZW1haW5pbmcgbm9kZXMgZnJvbSBzaW11bGF0ZVxuICAgICAgICAgICAgICAgIHdoaWxlIChzaW11bGF0ZUluZGV4IDwgc2ltdWxhdGUubGVuZ3RoKSB7XG4gICAgICAgICAgICAgICAgICAgIHNpbXVsYXRlSXRlbSA9IHNpbXVsYXRlW3NpbXVsYXRlSW5kZXhdO1xuICAgICAgICAgICAgICAgICAgICByZW1vdmVzLnB1c2gocmVtb3ZlKHNpbXVsYXRlLCBzaW11bGF0ZUluZGV4LCBzaW11bGF0ZUl0ZW0gJiYgc2ltdWxhdGVJdGVtLmtleSkpO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIC8vIElmIHRoZSBvbmx5IG1vdmVzIHdlIGhhdmUgYXJlIGRlbGV0ZXMgdGhlbiB3ZSBjYW4ganVzdFxuICAgICAgICAgICAgICAgIC8vIGxldCB0aGUgZGVsZXRlIHBhdGNoIHJlbW92ZSB0aGVzZSBpdGVtcy5cbiAgICAgICAgICAgICAgICBpZiAocmVtb3Zlcy5sZW5ndGggPT09IGRlbGV0ZWRJdGVtcyAmJiAhaW5zZXJ0cy5sZW5ndGgpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGNoaWxkcmVuOiBuZXdDaGlsZHJlbixcbiAgICAgICAgICAgICAgICAgICAgICAgIG1vdmVzOiBudWxsXG4gICAgICAgICAgICAgICAgICAgIH07XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgICAgICAgICAgY2hpbGRyZW46IG5ld0NoaWxkcmVuLFxuICAgICAgICAgICAgICAgICAgICBtb3Zlczoge1xuICAgICAgICAgICAgICAgICAgICAgICAgcmVtb3ZlczogcmVtb3ZlcyxcbiAgICAgICAgICAgICAgICAgICAgICAgIGluc2VydHM6IGluc2VydHNcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH07XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIHJlbW92ZShhcnIsIGluZGV4LCBrZXkpIHtcbiAgICAgICAgICAgICAgICBhcnIuc3BsaWNlKGluZGV4LCAxKTtcblxuICAgICAgICAgICAgICAgIHJldHVybiB7XG4gICAgICAgICAgICAgICAgICAgIGZyb206IGluZGV4LFxuICAgICAgICAgICAgICAgICAgICBrZXk6IGtleVxuICAgICAgICAgICAgICAgIH07XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIGtleUluZGV4KGNoaWxkcmVuKSB7XG4gICAgICAgICAgICAgICAgdmFyIGtleXMgPSB7fTtcbiAgICAgICAgICAgICAgICB2YXIgZnJlZSA9IFtdO1xuICAgICAgICAgICAgICAgIHZhciBsZW5ndGggPSBjaGlsZHJlbi5sZW5ndGg7XG5cbiAgICAgICAgICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IGxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciBjaGlsZCA9IGNoaWxkcmVuW2ldO1xuXG4gICAgICAgICAgICAgICAgICAgIGlmIChjaGlsZC5rZXkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGtleXNbY2hpbGQua2V5XSA9IGk7XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBmcmVlLnB1c2goaSk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgICAgICAgICBrZXlzOiBrZXlzLCAvLyBBIGhhc2ggb2Yga2V5IG5hbWUgdG8gaW5kZXhcbiAgICAgICAgICAgICAgICAgICAgZnJlZTogZnJlZSAvLyBBbiBhcnJheSBvZiB1bmtleWVkIGl0ZW0gaW5kaWNlc1xuICAgICAgICAgICAgICAgIH07XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIGFwcGVuZFBhdGNoKGFwcGx5LCBwYXRjaCkge1xuICAgICAgICAgICAgICAgIGlmIChhcHBseSkge1xuICAgICAgICAgICAgICAgICAgICBpZiAoaXNBcnJheShhcHBseSkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGFwcGx5LnB1c2gocGF0Y2gpO1xuICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgYXBwbHkgPSBbYXBwbHksIHBhdGNoXTtcbiAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBhcHBseTtcbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gcGF0Y2g7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9LCB7IFwiLi4vdm5vZGUvaGFuZGxlLXRodW5rXCI6IDI0LCBcIi4uL3Zub2RlL2lzLXRodW5rXCI6IDI1LCBcIi4uL3Zub2RlL2lzLXZub2RlXCI6IDI3LCBcIi4uL3Zub2RlL2lzLXZ0ZXh0XCI6IDI4LCBcIi4uL3Zub2RlL2lzLXdpZGdldFwiOiAyOSwgXCIuLi92bm9kZS92cGF0Y2hcIjogMzIsIFwiLi9kaWZmLXByb3BzXCI6IDM0LCBcIngtaXMtYXJyYXlcIjogMTIgfV0gfSwge30sIFs0XSkoNCk7XG59KTtcblxuLyogQGZsb3cgKi9cblxuY2xhc3MgTWFpbGJveCB7XG5cbiAgY29uc3RydWN0b3IoKSB7XG4gICAgdGhpcy5tZXNzYWdlcyA9IFtdO1xuICB9XG5cbiAgZGVsaXZlcihtZXNzYWdlKSB7XG4gICAgdGhpcy5tZXNzYWdlcy5wdXNoKG1lc3NhZ2UpO1xuICAgIHJldHVybiBtZXNzYWdlO1xuICB9XG5cbiAgZ2V0KCkge1xuICAgIHJldHVybiB0aGlzLm1lc3NhZ2VzO1xuICB9XG5cbiAgaXNFbXB0eSgpIHtcbiAgICByZXR1cm4gdGhpcy5tZXNzYWdlcy5sZW5ndGggPT09IDA7XG4gIH1cblxuICByZW1vdmVBdChpbmRleCkge1xuICAgIHRoaXMubWVzc2FnZXMuc3BsaWNlKGluZGV4LCAxKTtcbiAgfVxufVxuXG52YXIgU3RhdGVzID0ge1xuICBOT1JNQUw6IFN5bWJvbC5mb3IoXCJub3JtYWxcIiksXG4gIEtJTEw6IFN5bWJvbC5mb3IoXCJraWxsXCIpLFxuICBTVVNQRU5EOiBTeW1ib2wuZm9yKFwic3VzcGVuZFwiKSxcbiAgQ09OVElOVUU6IFN5bWJvbC5mb3IoXCJjb250aW51ZVwiKSxcbiAgUkVDRUlWRTogU3ltYm9sLmZvcihcInJlY2VpdmVcIiksXG4gIFNFTkQ6IFN5bWJvbC5mb3IoXCJzZW5kXCIpLFxuICBTTEVFUElORzogU3ltYm9sLmZvcihcInNsZWVwaW5nXCIpLFxuICBSVU5OSU5HOiBTeW1ib2wuZm9yKFwicnVubmluZ1wiKSxcbiAgU1VTUEVOREVEOiBTeW1ib2wuZm9yKFwic3VzcGVuZGVkXCIpLFxuICBTVE9QUEVEOiBTeW1ib2wuZm9yKFwic3RvcHBlZFwiKSxcbiAgU0xFRVA6IFN5bWJvbC5mb3IoXCJzbGVlcFwiKSxcbiAgRVhJVDogU3ltYm9sLmZvcihcImV4aXRcIiksXG4gIE5PTUFUQ0g6IFN5bWJvbC5mb3IoXCJub19tYXRjaFwiKVxufTtcblxuY2xhc3MgUHJvY2VzcyB7XG5cbiAgY29uc3RydWN0b3IocGlkLCBtYWlsYm94KSB7XG4gICAgdGhpcy5waWQgPSBwaWQ7XG4gICAgdGhpcy5tYWlsYm94ID0gbWFpbGJveDtcbiAgICB0aGlzLnN0YXR1cyA9IFN0YXRlcy5TVE9QUEVEO1xuICAgIHRoaXMuZGljdCA9IHt9O1xuICB9XG59XG5cbmNsYXNzIFR1cGxlIHtcblxuICBjb25zdHJ1Y3RvciguLi5hcmdzKSB7XG4gICAgdGhpcy52YWx1ZXMgPSBPYmplY3QuZnJlZXplKGFyZ3MpO1xuICAgIHRoaXMubGVuZ3RoID0gdGhpcy52YWx1ZXMubGVuZ3RoO1xuICB9XG5cbiAgZ2V0KGluZGV4KSB7XG4gICAgcmV0dXJuIHRoaXMudmFsdWVzW2luZGV4XTtcbiAgfVxuXG4gIGNvdW50KCkge1xuICAgIHJldHVybiB0aGlzLnZhbHVlcy5sZW5ndGg7XG4gIH1cblxuICBbU3ltYm9sLml0ZXJhdG9yXSgpIHtcbiAgICByZXR1cm4gdGhpcy52YWx1ZXNbU3ltYm9sLml0ZXJhdG9yXSgpO1xuICB9XG5cbiAgdG9TdHJpbmcoKSB7XG4gICAgdmFyIGksXG4gICAgICAgIHMgPSBcIlwiO1xuICAgIGZvciAoaSA9IDA7IGkgPCB0aGlzLnZhbHVlcy5sZW5ndGg7IGkrKykge1xuICAgICAgaWYgKHMgIT09IFwiXCIpIHtcbiAgICAgICAgcyArPSBcIiwgXCI7XG4gICAgICB9XG4gICAgICBzICs9IHRoaXMudmFsdWVzW2ldLnRvU3RyaW5nKCk7XG4gICAgfVxuXG4gICAgcmV0dXJuIFwie1wiICsgcyArIFwifVwiO1xuICB9XG5cbn1cblxubGV0IHByb2Nlc3NfY291bnRlciA9IC0xO1xuXG5jbGFzcyBQSUQge1xuICBjb25zdHJ1Y3RvcigpIHtcbiAgICBwcm9jZXNzX2NvdW50ZXIgPSBwcm9jZXNzX2NvdW50ZXIgKyAxO1xuICAgIHRoaXMuaWQgPSBwcm9jZXNzX2NvdW50ZXI7XG4gIH1cblxuICB0b1N0cmluZygpIHtcbiAgICByZXR1cm4gXCJQSUQjPDAuXCIgKyB0aGlzLmlkICsgXCIuMD5cIjtcbiAgfVxufVxuXG5jbGFzcyBJbnRlZ2VyIHt9XG5jbGFzcyBGbG9hdCB7fVxuXG5jbGFzcyBQcm9jZXNzU3lzdGVtIHtcblxuICBjb25zdHJ1Y3RvcigpIHtcbiAgICB0aGlzLnBpZHMgPSBuZXcgTWFwKCk7XG4gICAgdGhpcy5tYWlsYm94ZXMgPSBuZXcgTWFwKCk7XG4gICAgdGhpcy5uYW1lcyA9IG5ldyBNYXAoKTtcbiAgICB0aGlzLmxpbmtzID0gbmV3IE1hcCgpO1xuXG4gICAgdGhpcy5jdXJyZW50X3Byb2Nlc3MgPSBudWxsO1xuICAgIHRoaXMuc3VzcGVuZGVkID0gbmV3IE1hcCgpO1xuXG4gICAgdGhpcy5tYWluX3Byb2Nlc3NfcGlkID0gdGhpcy5zcGF3bigpO1xuICAgIHRoaXMuc2V0X2N1cnJlbnQodGhpcy5tYWluX3Byb2Nlc3NfcGlkKTtcbiAgfVxuXG4gIHNwYXduKCkge1xuICAgIHJldHVybiB0aGlzLmFkZF9wcm9jKGZhbHNlKS5waWQ7XG4gIH1cblxuICBzcGF3bl9saW5rKCkge1xuICAgIHJldHVybiB0aGlzLmFkZF9wcm9jKHRydWUpLnBpZDtcbiAgfVxuXG4gIGxpbmsocGlkKSB7XG4gICAgdGhpcy5saW5rcy5nZXQodGhpcy5waWQoKSkuYWRkKHBpZCk7XG4gICAgdGhpcy5saW5rcy5nZXQocGlkKS5hZGQodGhpcy5waWQoKSk7XG4gIH1cblxuICB1bmxpbmsocGlkKSB7XG4gICAgdGhpcy5saW5rcy5nZXQodGhpcy5waWQoKSkuZGVsZXRlKHBpZCk7XG4gICAgdGhpcy5saW5rcy5nZXQocGlkKS5kZWxldGUodGhpcy5waWQoKSk7XG4gIH1cblxuICBzZXRfY3VycmVudChpZCkge1xuICAgIGxldCBwaWQgPSB0aGlzLnBpZG9mKGlkKTtcbiAgICBpZiAocGlkICE9PSBudWxsKSB7XG4gICAgICB0aGlzLmN1cnJlbnRfcHJvY2VzcyA9IHRoaXMucGlkcy5nZXQocGlkKTtcbiAgICAgIHRoaXMuY3VycmVudF9wcm9jZXNzLnN0YXR1cyA9IFN0YXRlcy5SVU5OSU5HO1xuICAgIH1cbiAgfVxuXG4gIGFkZF9wcm9jKGxpbmtlZCkge1xuICAgIGxldCBuZXdwaWQgPSBuZXcgUElEKCk7XG4gICAgbGV0IG1haWxib3ggPSBuZXcgTWFpbGJveCgpO1xuICAgIGxldCBuZXdwcm9jID0gbmV3IFByb2Nlc3MobmV3cGlkLCBtYWlsYm94KTtcblxuICAgIHRoaXMucGlkcy5zZXQobmV3cGlkLCBuZXdwcm9jKTtcbiAgICB0aGlzLm1haWxib3hlcy5zZXQobmV3cGlkLCBtYWlsYm94KTtcbiAgICB0aGlzLmxpbmtzLnNldChuZXdwaWQsIG5ldyBTZXQoKSk7XG5cbiAgICBpZiAobGlua2VkKSB7XG4gICAgICB0aGlzLmxpbmsobmV3cGlkKTtcbiAgICB9XG5cbiAgICByZXR1cm4gbmV3cHJvYztcbiAgfVxuXG4gIHJlbW92ZV9wcm9jKHBpZCkge1xuICAgIHRoaXMucGlkcy5kZWxldGUocGlkKTtcbiAgICB0aGlzLnVucmVnaXN0ZXIocGlkKTtcblxuICAgIGlmICh0aGlzLmxpbmtzLmhhcyhwaWQpKSB7XG4gICAgICBmb3IgKGxldCBsaW5rcGlkIG9mIHRoaXMubGlua3MuZ2V0KHBpZCkpIHtcbiAgICAgICAgdGhpcy5saW5rcy5nZXQobGlua3BpZCkuZGVsZXRlKHBpZCk7XG4gICAgICB9XG5cbiAgICAgIHRoaXMubGlua3MuZGVsZXRlKHBpZCk7XG4gICAgfVxuICB9XG5cbiAgZXhpdChpZCkge1xuICAgIGxldCBwaWQgPSB0aGlzLnBpZG9mKGlkKTtcbiAgICB0aGlzLnJlbW92ZV9wcm9jKGlkKTtcbiAgfVxuXG4gIHJlZ2lzdGVyKG5hbWUsIHBpZCkge1xuICAgIGlmICghdGhpcy5uYW1lcy5oYXMobmFtZSkpIHtcbiAgICAgIHRoaXMubmFtZXMuc2V0KG5hbWUsIHBpZCk7XG4gICAgICByZXR1cm4gbmFtZTtcbiAgICB9IGVsc2Uge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKFwiTmFtZSBpcyBhbHJlYWR5IHJlZ2lzdGVyZWQgdG8gYW5vdGhlciBwcm9jZXNzXCIpO1xuICAgIH1cbiAgfVxuXG4gIHJlZ2lzdGVyZWQobmFtZSkge1xuICAgIHJldHVybiB0aGlzLm5hbWVzLmhhcyhuYW1lKSA/IHRoaXMubmFtZXMuZ2V0KG5hbWUpIDogbnVsbDtcbiAgfVxuXG4gIHVucmVnaXN0ZXIocGlkKSB7XG4gICAgZm9yIChsZXQgbmFtZSBvZiB0aGlzLm5hbWVzLmtleXMoKSkge1xuICAgICAgaWYgKHRoaXMubmFtZXMuaGFzKG5hbWUpICYmIHRoaXMubmFtZXMuZ2V0KG5hbWUpID09PSBwaWQpIHtcbiAgICAgICAgdGhpcy5uYW1lcy5kZWxldGUobmFtZSk7XG4gICAgICB9XG4gICAgfVxuICB9XG5cbiAgcGlkKCkge1xuICAgIHJldHVybiB0aGlzLmN1cnJlbnRfcHJvY2Vzcy5waWQ7XG4gIH1cblxuICBwaWRvZihpZCkge1xuICAgIGlmIChpZCBpbnN0YW5jZW9mIFBJRCkge1xuICAgICAgcmV0dXJuIHRoaXMucGlkcy5oYXMoaWQpID8gaWQgOiBudWxsO1xuICAgIH0gZWxzZSBpZiAoaWQgaW5zdGFuY2VvZiBQcm9jZXNzKSB7XG4gICAgICByZXR1cm4gaWQucGlkO1xuICAgIH0gZWxzZSB7XG4gICAgICBsZXQgcGlkID0gdGhpcy5yZWdpc3RlcmVkKGlkKTtcbiAgICAgIGlmIChwaWQgPT09IG51bGwpIHRocm93IFwiUHJvY2VzcyBuYW1lIG5vdCByZWdpc3RlcmVkOiBcIiArIGlkICsgXCIgKFwiICsgdHlwZW9mIGlkICsgXCIpXCI7XG4gICAgICByZXR1cm4gcGlkO1xuICAgIH1cbiAgfVxuXG4gIHB1dChpZCwga2V5LCB2YWx1ZSkge1xuICAgIGxldCBwaWQgPSB0aGlzLnBpZG9mKGlkKTtcbiAgICBsZXQgcHJvY2VzcyA9IHRoaXMucGlkcy5nZXQocGlkKTtcbiAgICBwcm9jZXNzLmRpY3Rba2V5XSA9IHZhbHVlO1xuICB9XG5cbiAgZ2V0KGlkLCBrZXkpIHtcbiAgICBsZXQgcGlkID0gdGhpcy5waWRvZihpZCk7XG4gICAgbGV0IHByb2Nlc3MgPSB0aGlzLnBpZHMuZ2V0KHBpZCk7XG5cbiAgICBpZiAoa2V5ICE9IG51bGwpIHtcbiAgICAgIHJldHVybiBwcm9jZXNzLmRpY3Rba2V5XTtcbiAgICB9IGVsc2Uge1xuICAgICAgcmV0dXJuIHByb2Nlc3MuZGljdDtcbiAgICB9XG4gIH1cblxuICBnZXRfa2V5cyhpZCkge1xuICAgIGxldCBwaWQgPSB0aGlzLnBpZG9mKGlkKTtcbiAgICBsZXQgcHJvY2VzcyA9IHRoaXMucGlkcy5nZXQocGlkKTtcblxuICAgIHJldHVybiBPYmplY3Qua2V5cyhwcm9jZXNzLmRpY3QpO1xuICB9XG5cbiAgZXJhc2UoaWQsIGtleSkge1xuICAgIGxldCBwaWQgPSB0aGlzLnBpZG9mKGlkKTtcbiAgICBsZXQgcHJvY2VzcyA9IHRoaXMucGlkcy5nZXQocGlkKTtcblxuICAgIGlmIChrZXkgIT0gbnVsbCkge1xuICAgICAgZGVsZXRlIHByb2Nlc3MuZGljdFtrZXldO1xuICAgIH0gZWxzZSB7XG4gICAgICBwcm9jZXNzLmRpY3QgPSB7fTtcbiAgICB9XG4gIH1cbn1cblxuY2xhc3MgQml0U3RyaW5nIHtcbiAgY29uc3RydWN0b3IoLi4uYXJncykge1xuICAgIHRoaXMucmF3X3ZhbHVlID0gZnVuY3Rpb24gKCkge1xuICAgICAgcmV0dXJuIE9iamVjdC5mcmVlemUoYXJncyk7XG4gICAgfTtcblxuICAgIHRoaXMudmFsdWUgPSBPYmplY3QuZnJlZXplKHRoaXMucHJvY2VzcyhhcmdzKSk7XG4gIH1cblxuICBnZXQoaW5kZXgpIHtcbiAgICByZXR1cm4gdGhpcy52YWx1ZVtpbmRleF07XG4gIH1cblxuICBjb3VudCgpIHtcbiAgICByZXR1cm4gdGhpcy52YWx1ZS5sZW5ndGg7XG4gIH1cblxuICBbU3ltYm9sLml0ZXJhdG9yXSgpIHtcbiAgICByZXR1cm4gdGhpcy52YWx1ZVtTeW1ib2wuaXRlcmF0b3JdKCk7XG4gIH1cblxuICB0b1N0cmluZygpIHtcbiAgICB2YXIgaSxcbiAgICAgICAgcyA9IFwiXCI7XG4gICAgZm9yIChpID0gMDsgaSA8IHRoaXMuY291bnQoKTsgaSsrKSB7XG4gICAgICBpZiAocyAhPT0gXCJcIikge1xuICAgICAgICBzICs9IFwiLCBcIjtcbiAgICAgIH1cbiAgICAgIHMgKz0gdGhpc1tpXS50b1N0cmluZygpO1xuICAgIH1cblxuICAgIHJldHVybiBcIjw8XCIgKyBzICsgXCI+PlwiO1xuICB9XG5cbiAgcHJvY2VzcygpIHtcbiAgICBsZXQgcHJvY2Vzc2VkX3ZhbHVlcyA9IFtdO1xuXG4gICAgdmFyIGk7XG4gICAgZm9yIChpID0gMDsgaSA8IHRoaXMucmF3X3ZhbHVlKCkubGVuZ3RoOyBpKyspIHtcbiAgICAgIGxldCBwcm9jZXNzZWRfdmFsdWUgPSB0aGlzW1wicHJvY2Vzc19cIiArIHRoaXMucmF3X3ZhbHVlKClbaV0udHlwZV0odGhpcy5yYXdfdmFsdWUoKVtpXSk7XG5cbiAgICAgIGZvciAobGV0IGF0dHIgb2YgdGhpcy5yYXdfdmFsdWUoKVtpXS5hdHRyaWJ1dGVzKSB7XG4gICAgICAgIHByb2Nlc3NlZF92YWx1ZSA9IHRoaXNbXCJwcm9jZXNzX1wiICsgYXR0cl0ocHJvY2Vzc2VkX3ZhbHVlKTtcbiAgICAgIH1cblxuICAgICAgcHJvY2Vzc2VkX3ZhbHVlcyA9IHByb2Nlc3NlZF92YWx1ZXMuY29uY2F0KHByb2Nlc3NlZF92YWx1ZSk7XG4gICAgfVxuXG4gICAgcmV0dXJuIHByb2Nlc3NlZF92YWx1ZXM7XG4gIH1cblxuICBwcm9jZXNzX2ludGVnZXIodmFsdWUpIHtcbiAgICByZXR1cm4gdmFsdWUudmFsdWU7XG4gIH1cblxuICBwcm9jZXNzX2Zsb2F0KHZhbHVlKSB7XG4gICAgaWYgKHZhbHVlLnNpemUgPT09IDY0KSB7XG4gICAgICByZXR1cm4gQml0U3RyaW5nLmZsb2F0NjRUb0J5dGVzKHZhbHVlLnZhbHVlKTtcbiAgICB9IGVsc2UgaWYgKHZhbHVlLnNpemUgPT09IDMyKSB7XG4gICAgICByZXR1cm4gQml0U3RyaW5nLmZsb2F0MzJUb0J5dGVzKHZhbHVlLnZhbHVlKTtcbiAgICB9XG5cbiAgICB0aHJvdyBuZXcgRXJyb3IoXCJJbnZhbGlkIHNpemUgZm9yIGZsb2F0XCIpO1xuICB9XG5cbiAgcHJvY2Vzc19iaXRzdHJpbmcodmFsdWUpIHtcbiAgICByZXR1cm4gdmFsdWUudmFsdWUudmFsdWU7XG4gIH1cblxuICBwcm9jZXNzX2JpbmFyeSh2YWx1ZSkge1xuICAgIHJldHVybiBCaXRTdHJpbmcudG9VVEY4QXJyYXkodmFsdWUudmFsdWUpO1xuICB9XG5cbiAgcHJvY2Vzc191dGY4KHZhbHVlKSB7XG4gICAgcmV0dXJuIEJpdFN0cmluZy50b1VURjhBcnJheSh2YWx1ZS52YWx1ZSk7XG4gIH1cblxuICBwcm9jZXNzX3V0ZjE2KHZhbHVlKSB7XG4gICAgcmV0dXJuIEJpdFN0cmluZy50b1VURjE2QXJyYXkodmFsdWUudmFsdWUpO1xuICB9XG5cbiAgcHJvY2Vzc191dGYzMih2YWx1ZSkge1xuICAgIHJldHVybiBCaXRTdHJpbmcudG9VVEYzMkFycmF5KHZhbHVlLnZhbHVlKTtcbiAgfVxuXG4gIHByb2Nlc3Nfc2lnbmVkKHZhbHVlKSB7XG4gICAgcmV0dXJuIG5ldyBVaW50OEFycmF5KFt2YWx1ZV0pWzBdO1xuICB9XG5cbiAgcHJvY2Vzc191bnNpZ25lZCh2YWx1ZSkge1xuICAgIHJldHVybiB2YWx1ZTtcbiAgfVxuXG4gIHByb2Nlc3NfbmF0aXZlKHZhbHVlKSB7XG4gICAgcmV0dXJuIHZhbHVlO1xuICB9XG5cbiAgcHJvY2Vzc19iaWcodmFsdWUpIHtcbiAgICByZXR1cm4gdmFsdWU7XG4gIH1cblxuICBwcm9jZXNzX2xpdHRsZSh2YWx1ZSkge1xuICAgIHJldHVybiB2YWx1ZS5yZXZlcnNlKCk7XG4gIH1cblxuICBwcm9jZXNzX3NpemUodmFsdWUpIHtcbiAgICByZXR1cm4gdmFsdWU7XG4gIH1cblxuICBwcm9jZXNzX3VuaXQodmFsdWUpIHtcbiAgICByZXR1cm4gdmFsdWU7XG4gIH1cblxuICBzdGF0aWMgaW50ZWdlcih2YWx1ZSkge1xuICAgIHJldHVybiBCaXRTdHJpbmcud3JhcCh2YWx1ZSwgeyBcInR5cGVcIjogXCJpbnRlZ2VyXCIsIFwidW5pdFwiOiAxLCBcInNpemVcIjogOCB9KTtcbiAgfVxuXG4gIHN0YXRpYyBmbG9hdCh2YWx1ZSkge1xuICAgIHJldHVybiBCaXRTdHJpbmcud3JhcCh2YWx1ZSwgeyBcInR5cGVcIjogXCJmbG9hdFwiLCBcInVuaXRcIjogMSwgXCJzaXplXCI6IDY0IH0pO1xuICB9XG5cbiAgc3RhdGljIGJpdHN0cmluZyh2YWx1ZSkge1xuICAgIHJldHVybiBCaXRTdHJpbmcud3JhcCh2YWx1ZSwgeyBcInR5cGVcIjogXCJiaXRzdHJpbmdcIiwgXCJ1bml0XCI6IDEsIFwic2l6ZVwiOiB2YWx1ZS5sZW5ndGggfSk7XG4gIH1cblxuICBzdGF0aWMgYml0cyh2YWx1ZSkge1xuICAgIHJldHVybiBCaXRTdHJpbmcuYml0c3RyaW5nKHZhbHVlKTtcbiAgfVxuXG4gIHN0YXRpYyBiaW5hcnkodmFsdWUpIHtcbiAgICByZXR1cm4gQml0U3RyaW5nLndyYXAodmFsdWUsIHsgXCJ0eXBlXCI6IFwiYmluYXJ5XCIsIFwidW5pdFwiOiA4LCBcInNpemVcIjogdmFsdWUubGVuZ3RoIH0pO1xuICB9XG5cbiAgc3RhdGljIGJ5dGVzKHZhbHVlKSB7XG4gICAgcmV0dXJuIEJpdFN0cmluZy5iaW5hcnkodmFsdWUpO1xuICB9XG5cbiAgc3RhdGljIHV0ZjgodmFsdWUpIHtcbiAgICByZXR1cm4gQml0U3RyaW5nLndyYXAodmFsdWUsIHsgXCJ0eXBlXCI6IFwidXRmOFwiIH0pO1xuICB9XG5cbiAgc3RhdGljIHV0ZjE2KHZhbHVlKSB7XG4gICAgcmV0dXJuIEJpdFN0cmluZy53cmFwKHZhbHVlLCB7IFwidHlwZVwiOiBcInV0ZjE2XCIgfSk7XG4gIH1cblxuICBzdGF0aWMgdXRmMzIodmFsdWUpIHtcbiAgICByZXR1cm4gQml0U3RyaW5nLndyYXAodmFsdWUsIHsgXCJ0eXBlXCI6IFwidXRmMzJcIiB9KTtcbiAgfVxuXG4gIHN0YXRpYyBzaWduZWQodmFsdWUpIHtcbiAgICByZXR1cm4gQml0U3RyaW5nLndyYXAodmFsdWUsIHt9LCBcInNpZ25lZFwiKTtcbiAgfVxuXG4gIHN0YXRpYyB1bnNpZ25lZCh2YWx1ZSkge1xuICAgIHJldHVybiBCaXRTdHJpbmcud3JhcCh2YWx1ZSwge30sIFwidW5zaWduZWRcIik7XG4gIH1cblxuICBzdGF0aWMgbmF0aXZlKHZhbHVlKSB7XG4gICAgcmV0dXJuIEJpdFN0cmluZy53cmFwKHZhbHVlLCB7fSwgXCJuYXRpdmVcIik7XG4gIH1cblxuICBzdGF0aWMgYmlnKHZhbHVlKSB7XG4gICAgcmV0dXJuIEJpdFN0cmluZy53cmFwKHZhbHVlLCB7fSwgXCJiaWdcIik7XG4gIH1cblxuICBzdGF0aWMgbGl0dGxlKHZhbHVlKSB7XG4gICAgcmV0dXJuIEJpdFN0cmluZy53cmFwKHZhbHVlLCB7fSwgXCJsaXR0bGVcIik7XG4gIH1cblxuICBzdGF0aWMgc2l6ZSh2YWx1ZSwgY291bnQpIHtcbiAgICByZXR1cm4gQml0U3RyaW5nLndyYXAodmFsdWUsIHsgXCJzaXplXCI6IGNvdW50IH0pO1xuICB9XG5cbiAgc3RhdGljIHVuaXQodmFsdWUsIGNvdW50KSB7XG4gICAgcmV0dXJuIEJpdFN0cmluZy53cmFwKHZhbHVlLCB7IFwidW5pdFwiOiBjb3VudCB9KTtcbiAgfVxuXG4gIHN0YXRpYyB3cmFwKHZhbHVlLCBvcHQsIG5ld19hdHRyaWJ1dGUgPSBudWxsKSB7XG4gICAgbGV0IHRoZV92YWx1ZSA9IHZhbHVlO1xuXG4gICAgaWYgKCEodmFsdWUgaW5zdGFuY2VvZiBPYmplY3QpKSB7XG4gICAgICB0aGVfdmFsdWUgPSB7IFwidmFsdWVcIjogdmFsdWUsIFwiYXR0cmlidXRlc1wiOiBbXSB9O1xuICAgIH1cblxuICAgIHRoZV92YWx1ZSA9IE9iamVjdC5hc3NpZ24odGhlX3ZhbHVlLCBvcHQpO1xuXG4gICAgaWYgKG5ld19hdHRyaWJ1dGUpIHtcbiAgICAgIHRoZV92YWx1ZS5hdHRyaWJ1dGVzLnB1c2gobmV3X2F0dHJpYnV0ZSk7XG4gICAgfVxuXG4gICAgcmV0dXJuIHRoZV92YWx1ZTtcbiAgfVxuXG4gIHN0YXRpYyB0b1VURjhBcnJheShzdHIpIHtcbiAgICB2YXIgdXRmOCA9IFtdO1xuICAgIGZvciAodmFyIGkgPSAwOyBpIDwgc3RyLmxlbmd0aDsgaSsrKSB7XG4gICAgICB2YXIgY2hhcmNvZGUgPSBzdHIuY2hhckNvZGVBdChpKTtcbiAgICAgIGlmIChjaGFyY29kZSA8IDEyOCkge1xuICAgICAgICB1dGY4LnB1c2goY2hhcmNvZGUpO1xuICAgICAgfSBlbHNlIGlmIChjaGFyY29kZSA8IDIwNDgpIHtcbiAgICAgICAgdXRmOC5wdXNoKDE5MiB8IGNoYXJjb2RlID4+IDYsIDEyOCB8IGNoYXJjb2RlICYgNjMpO1xuICAgICAgfSBlbHNlIGlmIChjaGFyY29kZSA8IDU1Mjk2IHx8IGNoYXJjb2RlID49IDU3MzQ0KSB7XG4gICAgICAgIHV0ZjgucHVzaCgyMjQgfCBjaGFyY29kZSA+PiAxMiwgMTI4IHwgY2hhcmNvZGUgPj4gNiAmIDYzLCAxMjggfCBjaGFyY29kZSAmIDYzKTtcbiAgICAgIH1cbiAgICAgIC8vIHN1cnJvZ2F0ZSBwYWlyXG4gICAgICBlbHNlIHtcbiAgICAgICAgaSsrO1xuICAgICAgICAvLyBVVEYtMTYgZW5jb2RlcyAweDEwMDAwLTB4MTBGRkZGIGJ5XG4gICAgICAgIC8vIHN1YnRyYWN0aW5nIDB4MTAwMDAgYW5kIHNwbGl0dGluZyB0aGVcbiAgICAgICAgLy8gMjAgYml0cyBvZiAweDAtMHhGRkZGRiBpbnRvIHR3byBoYWx2ZXNcbiAgICAgICAgY2hhcmNvZGUgPSA2NTUzNiArICgoY2hhcmNvZGUgJiAxMDIzKSA8PCAxMCB8IHN0ci5jaGFyQ29kZUF0KGkpICYgMTAyMyk7XG4gICAgICAgIHV0ZjgucHVzaCgyNDAgfCBjaGFyY29kZSA+PiAxOCwgMTI4IHwgY2hhcmNvZGUgPj4gMTIgJiA2MywgMTI4IHwgY2hhcmNvZGUgPj4gNiAmIDYzLCAxMjggfCBjaGFyY29kZSAmIDYzKTtcbiAgICAgIH1cbiAgICB9XG4gICAgcmV0dXJuIHV0Zjg7XG4gIH1cblxuICBzdGF0aWMgdG9VVEYxNkFycmF5KHN0cikge1xuICAgIHZhciB1dGYxNiA9IFtdO1xuICAgIGZvciAodmFyIGkgPSAwOyBpIDwgc3RyLmxlbmd0aDsgaSsrKSB7XG4gICAgICB2YXIgY29kZVBvaW50ID0gc3RyLmNvZGVQb2ludEF0KGkpO1xuXG4gICAgICBpZiAoY29kZVBvaW50IDw9IDI1NSkge1xuICAgICAgICB1dGYxNi5wdXNoKDApO1xuICAgICAgICB1dGYxNi5wdXNoKGNvZGVQb2ludCk7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICB1dGYxNi5wdXNoKGNvZGVQb2ludCA+PiA4ICYgMjU1KTtcbiAgICAgICAgdXRmMTYucHVzaChjb2RlUG9pbnQgJiAyNTUpO1xuICAgICAgfVxuICAgIH1cbiAgICByZXR1cm4gdXRmMTY7XG4gIH1cblxuICBzdGF0aWMgdG9VVEYzMkFycmF5KHN0cikge1xuICAgIHZhciB1dGYzMiA9IFtdO1xuICAgIGZvciAodmFyIGkgPSAwOyBpIDwgc3RyLmxlbmd0aDsgaSsrKSB7XG4gICAgICB2YXIgY29kZVBvaW50ID0gc3RyLmNvZGVQb2ludEF0KGkpO1xuXG4gICAgICBpZiAoY29kZVBvaW50IDw9IDI1NSkge1xuICAgICAgICB1dGYzMi5wdXNoKDApO1xuICAgICAgICB1dGYzMi5wdXNoKDApO1xuICAgICAgICB1dGYzMi5wdXNoKDApO1xuICAgICAgICB1dGYzMi5wdXNoKGNvZGVQb2ludCk7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICB1dGYzMi5wdXNoKDApO1xuICAgICAgICB1dGYzMi5wdXNoKDApO1xuICAgICAgICB1dGYzMi5wdXNoKGNvZGVQb2ludCA+PiA4ICYgMjU1KTtcbiAgICAgICAgdXRmMzIucHVzaChjb2RlUG9pbnQgJiAyNTUpO1xuICAgICAgfVxuICAgIH1cbiAgICByZXR1cm4gdXRmMzI7XG4gIH1cblxuICAvL2h0dHA6Ly9zdGFja292ZXJmbG93LmNvbS9xdWVzdGlvbnMvMjAwMzQ5My9qYXZhc2NyaXB0LWZsb2F0LWZyb20tdG8tYml0c1xuICBzdGF0aWMgZmxvYXQzMlRvQnl0ZXMoZikge1xuICAgIHZhciBieXRlcyA9IFtdO1xuXG4gICAgdmFyIGJ1ZiA9IG5ldyBBcnJheUJ1ZmZlcig0KTtcbiAgICBuZXcgRmxvYXQzMkFycmF5KGJ1ZilbMF0gPSBmO1xuXG4gICAgbGV0IGludFZlcnNpb24gPSBuZXcgVWludDMyQXJyYXkoYnVmKVswXTtcblxuICAgIGJ5dGVzLnB1c2goaW50VmVyc2lvbiA+PiAyNCAmIDI1NSk7XG4gICAgYnl0ZXMucHVzaChpbnRWZXJzaW9uID4+IDE2ICYgMjU1KTtcbiAgICBieXRlcy5wdXNoKGludFZlcnNpb24gPj4gOCAmIDI1NSk7XG4gICAgYnl0ZXMucHVzaChpbnRWZXJzaW9uICYgMjU1KTtcblxuICAgIHJldHVybiBieXRlcztcbiAgfVxuXG4gIHN0YXRpYyBmbG9hdDY0VG9CeXRlcyhmKSB7XG4gICAgdmFyIGJ5dGVzID0gW107XG5cbiAgICB2YXIgYnVmID0gbmV3IEFycmF5QnVmZmVyKDgpO1xuICAgIG5ldyBGbG9hdDY0QXJyYXkoYnVmKVswXSA9IGY7XG5cbiAgICB2YXIgaW50VmVyc2lvbjEgPSBuZXcgVWludDMyQXJyYXkoYnVmKVswXTtcbiAgICB2YXIgaW50VmVyc2lvbjIgPSBuZXcgVWludDMyQXJyYXkoYnVmKVsxXTtcblxuICAgIGJ5dGVzLnB1c2goaW50VmVyc2lvbjIgPj4gMjQgJiAyNTUpO1xuICAgIGJ5dGVzLnB1c2goaW50VmVyc2lvbjIgPj4gMTYgJiAyNTUpO1xuICAgIGJ5dGVzLnB1c2goaW50VmVyc2lvbjIgPj4gOCAmIDI1NSk7XG4gICAgYnl0ZXMucHVzaChpbnRWZXJzaW9uMiAmIDI1NSk7XG5cbiAgICBieXRlcy5wdXNoKGludFZlcnNpb24xID4+IDI0ICYgMjU1KTtcbiAgICBieXRlcy5wdXNoKGludFZlcnNpb24xID4+IDE2ICYgMjU1KTtcbiAgICBieXRlcy5wdXNoKGludFZlcnNpb24xID4+IDggJiAyNTUpO1xuICAgIGJ5dGVzLnB1c2goaW50VmVyc2lvbjEgJiAyNTUpO1xuXG4gICAgcmV0dXJuIGJ5dGVzO1xuICB9XG59XG5cbi8qIEBmbG93ICovXG5cbmNsYXNzIFZhcmlhYmxlIHtcblxuICBjb25zdHJ1Y3RvcihuYW1lID0gbnVsbCkge1xuICAgIHRoaXMubmFtZSA9IG5hbWU7XG4gIH1cbn1cblxuY2xhc3MgV2lsZGNhcmQge1xuICBjb25zdHJ1Y3RvcigpIHt9XG59XG5cbmNsYXNzIFN0YXJ0c1dpdGgge1xuXG4gIGNvbnN0cnVjdG9yKHByZWZpeCkge1xuICAgIHRoaXMucHJlZml4ID0gcHJlZml4O1xuICB9XG59XG5cbmNsYXNzIENhcHR1cmUge1xuXG4gIGNvbnN0cnVjdG9yKHZhbHVlKSB7XG4gICAgdGhpcy52YWx1ZSA9IHZhbHVlO1xuICB9XG59XG5cbmNsYXNzIEhlYWRUYWlsIHtcbiAgY29uc3RydWN0b3IoKSB7fVxufVxuXG5jbGFzcyBUeXBlIHtcblxuICBjb25zdHJ1Y3Rvcih0eXBlLCBvYmpQYXR0ZXJuID0ge30pIHtcbiAgICB0aGlzLnR5cGUgPSB0eXBlO1xuICAgIHRoaXMub2JqUGF0dGVybiA9IG9ialBhdHRlcm47XG4gIH1cbn1cblxuY2xhc3MgQm91bmQge1xuXG4gIGNvbnN0cnVjdG9yKHZhbHVlKSB7XG4gICAgdGhpcy52YWx1ZSA9IHZhbHVlO1xuICB9XG59XG5cbmZ1bmN0aW9uIHZhcmlhYmxlKG5hbWUgPSBudWxsKSB7XG4gIHJldHVybiBuZXcgVmFyaWFibGUobmFtZSk7XG59XG5cbmZ1bmN0aW9uIHdpbGRjYXJkKCkge1xuICByZXR1cm4gbmV3IFdpbGRjYXJkKCk7XG59XG5cbmZ1bmN0aW9uIHN0YXJ0c1dpdGgocHJlZml4KSB7XG4gIHJldHVybiBuZXcgU3RhcnRzV2l0aChwcmVmaXgpO1xufVxuXG5mdW5jdGlvbiBjYXB0dXJlKHZhbHVlKSB7XG4gIHJldHVybiBuZXcgQ2FwdHVyZSh2YWx1ZSk7XG59XG5cbmZ1bmN0aW9uIGhlYWRUYWlsKCkge1xuICByZXR1cm4gbmV3IEhlYWRUYWlsKCk7XG59XG5cbmZ1bmN0aW9uIHR5cGUodHlwZSwgb2JqUGF0dGVybiA9IHt9KSB7XG4gIHJldHVybiBuZXcgVHlwZSh0eXBlLCBvYmpQYXR0ZXJuKTtcbn1cblxuZnVuY3Rpb24gYm91bmQodmFsdWUpIHtcbiAgcmV0dXJuIG5ldyBCb3VuZCh2YWx1ZSk7XG59XG5cbmZ1bmN0aW9uIGlzX251bWJlcih2YWx1ZSkge1xuICByZXR1cm4gdHlwZW9mIHZhbHVlID09PSAnbnVtYmVyJztcbn1cblxuZnVuY3Rpb24gaXNfc3RyaW5nKHZhbHVlKSB7XG4gIHJldHVybiB0eXBlb2YgdmFsdWUgPT09ICdzdHJpbmcnO1xufVxuXG5mdW5jdGlvbiBpc19ib29sZWFuKHZhbHVlKSB7XG4gIHJldHVybiB0eXBlb2YgdmFsdWUgPT09ICdib29sZWFuJztcbn1cblxuZnVuY3Rpb24gaXNfc3ltYm9sKHZhbHVlKSB7XG4gIHJldHVybiB0eXBlb2YgdmFsdWUgPT09ICdzeW1ib2wnO1xufVxuXG5mdW5jdGlvbiBpc19udWxsKHZhbHVlKSB7XG4gIHJldHVybiB2YWx1ZSA9PT0gbnVsbDtcbn1cblxuZnVuY3Rpb24gaXNfdW5kZWZpbmVkKHZhbHVlKSB7XG4gIHJldHVybiB0eXBlb2YgdmFsdWUgPT09ICd1bmRlZmluZWQnO1xufVxuXG5mdW5jdGlvbiBpc19mdW5jdGlvbih2YWx1ZSkge1xuICByZXR1cm4gT2JqZWN0LnByb3RvdHlwZS50b1N0cmluZy5jYWxsKHZhbHVlKSA9PSAnW29iamVjdCBGdW5jdGlvbl0nO1xufVxuXG5mdW5jdGlvbiBpc192YXJpYWJsZSh2YWx1ZSkge1xuICByZXR1cm4gdmFsdWUgaW5zdGFuY2VvZiBWYXJpYWJsZTtcbn1cblxuZnVuY3Rpb24gaXNfd2lsZGNhcmQodmFsdWUpIHtcbiAgcmV0dXJuIHZhbHVlIGluc3RhbmNlb2YgV2lsZGNhcmQ7XG59XG5cbmZ1bmN0aW9uIGlzX2hlYWRUYWlsKHZhbHVlKSB7XG4gIHJldHVybiB2YWx1ZSBpbnN0YW5jZW9mIEhlYWRUYWlsO1xufVxuXG5mdW5jdGlvbiBpc19jYXB0dXJlKHZhbHVlKSB7XG4gIHJldHVybiB2YWx1ZSBpbnN0YW5jZW9mIENhcHR1cmU7XG59XG5cbmZ1bmN0aW9uIGlzX3R5cGUodmFsdWUpIHtcbiAgcmV0dXJuIHZhbHVlIGluc3RhbmNlb2YgVHlwZTtcbn1cblxuZnVuY3Rpb24gaXNfc3RhcnRzV2l0aCh2YWx1ZSkge1xuICByZXR1cm4gdmFsdWUgaW5zdGFuY2VvZiBTdGFydHNXaXRoO1xufVxuXG5mdW5jdGlvbiBpc19ib3VuZCh2YWx1ZSkge1xuICByZXR1cm4gdmFsdWUgaW5zdGFuY2VvZiBCb3VuZDtcbn1cblxuZnVuY3Rpb24gaXNfb2JqZWN0KHZhbHVlKSB7XG4gIHJldHVybiB0eXBlb2YgdmFsdWUgPT09ICdvYmplY3QnO1xufVxuXG5mdW5jdGlvbiBpc19hcnJheSh2YWx1ZSkge1xuICByZXR1cm4gQXJyYXkuaXNBcnJheSh2YWx1ZSk7XG59XG5cbnZhciBDaGVja3MgPSB7XG4gIGlzX251bWJlcixcbiAgaXNfc3RyaW5nLFxuICBpc19ib29sZWFuLFxuICBpc19zeW1ib2wsXG4gIGlzX251bGwsXG4gIGlzX3VuZGVmaW5lZCxcbiAgaXNfZnVuY3Rpb24sXG4gIGlzX3ZhcmlhYmxlLFxuICBpc193aWxkY2FyZCxcbiAgaXNfaGVhZFRhaWwsXG4gIGlzX2NhcHR1cmUsXG4gIGlzX3R5cGUsXG4gIGlzX3N0YXJ0c1dpdGgsXG4gIGlzX2JvdW5kLFxuICBpc19vYmplY3QsXG4gIGlzX2FycmF5XG59O1xuXG5mdW5jdGlvbiByZXNvbHZlU3ltYm9sKHBhdHRlcm4pIHtcbiAgcmV0dXJuIGZ1bmN0aW9uICh2YWx1ZSkge1xuICAgIHJldHVybiBDaGVja3MuaXNfc3ltYm9sKHZhbHVlKSAmJiB2YWx1ZSA9PT0gcGF0dGVybjtcbiAgfTtcbn1cblxuZnVuY3Rpb24gcmVzb2x2ZVN0cmluZyhwYXR0ZXJuKSB7XG4gIHJldHVybiBmdW5jdGlvbiAodmFsdWUpIHtcbiAgICByZXR1cm4gQ2hlY2tzLmlzX3N0cmluZyh2YWx1ZSkgJiYgdmFsdWUgPT09IHBhdHRlcm47XG4gIH07XG59XG5cbmZ1bmN0aW9uIHJlc29sdmVOdW1iZXIocGF0dGVybikge1xuICByZXR1cm4gZnVuY3Rpb24gKHZhbHVlKSB7XG4gICAgcmV0dXJuIENoZWNrcy5pc19udW1iZXIodmFsdWUpICYmIHZhbHVlID09PSBwYXR0ZXJuO1xuICB9O1xufVxuXG5mdW5jdGlvbiByZXNvbHZlQm9vbGVhbihwYXR0ZXJuKSB7XG4gIHJldHVybiBmdW5jdGlvbiAodmFsdWUpIHtcbiAgICByZXR1cm4gQ2hlY2tzLmlzX2Jvb2xlYW4odmFsdWUpICYmIHZhbHVlID09PSBwYXR0ZXJuO1xuICB9O1xufVxuXG5mdW5jdGlvbiByZXNvbHZlRnVuY3Rpb24ocGF0dGVybikge1xuICByZXR1cm4gZnVuY3Rpb24gKHZhbHVlKSB7XG4gICAgcmV0dXJuIENoZWNrcy5pc19mdW5jdGlvbih2YWx1ZSkgJiYgdmFsdWUgPT09IHBhdHRlcm47XG4gIH07XG59XG5cbmZ1bmN0aW9uIHJlc29sdmVOdWxsKHBhdHRlcm4pIHtcbiAgcmV0dXJuIGZ1bmN0aW9uICh2YWx1ZSkge1xuICAgIHJldHVybiBDaGVja3MuaXNfbnVsbCh2YWx1ZSk7XG4gIH07XG59XG5cbmZ1bmN0aW9uIHJlc29sdmVCb3VuZChwYXR0ZXJuKSB7XG4gIHJldHVybiBmdW5jdGlvbiAodmFsdWUsIGFyZ3MpIHtcbiAgICBpZiAodHlwZW9mIHZhbHVlID09PSB0eXBlb2YgcGF0dGVybi52YWx1ZSAmJiB2YWx1ZSA9PT0gcGF0dGVybi52YWx1ZSkge1xuICAgICAgYXJncy5wdXNoKHZhbHVlKTtcbiAgICAgIHJldHVybiB0cnVlO1xuICAgIH1cblxuICAgIHJldHVybiBmYWxzZTtcbiAgfTtcbn1cblxuZnVuY3Rpb24gcmVzb2x2ZVdpbGRjYXJkKCkge1xuICByZXR1cm4gZnVuY3Rpb24gKCkge1xuICAgIHJldHVybiB0cnVlO1xuICB9O1xufVxuXG5mdW5jdGlvbiByZXNvbHZlVmFyaWFibGUoKSB7XG4gIHJldHVybiBmdW5jdGlvbiAodmFsdWUsIGFyZ3MpIHtcbiAgICBhcmdzLnB1c2godmFsdWUpO1xuICAgIHJldHVybiB0cnVlO1xuICB9O1xufVxuXG5mdW5jdGlvbiByZXNvbHZlSGVhZFRhaWwoKSB7XG4gIHJldHVybiBmdW5jdGlvbiAodmFsdWUsIGFyZ3MpIHtcbiAgICBpZiAoIUNoZWNrcy5pc19hcnJheSh2YWx1ZSkgfHwgdmFsdWUubGVuZ3RoIDwgMikge1xuICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH1cblxuICAgIGNvbnN0IGhlYWQgPSB2YWx1ZVswXTtcbiAgICBjb25zdCB0YWlsID0gdmFsdWUuc2xpY2UoMSk7XG5cbiAgICBhcmdzLnB1c2goaGVhZCk7XG4gICAgYXJncy5wdXNoKHRhaWwpO1xuXG4gICAgcmV0dXJuIHRydWU7XG4gIH07XG59XG5cbmZ1bmN0aW9uIHJlc29sdmVDYXB0dXJlKHBhdHRlcm4pIHtcbiAgY29uc3QgbWF0Y2hlcyA9IGJ1aWxkTWF0Y2gocGF0dGVybi52YWx1ZSk7XG5cbiAgcmV0dXJuIGZ1bmN0aW9uICh2YWx1ZSwgYXJncykge1xuICAgIGlmIChtYXRjaGVzKHZhbHVlLCBhcmdzKSkge1xuICAgICAgYXJncy5wdXNoKHZhbHVlKTtcbiAgICAgIHJldHVybiB0cnVlO1xuICAgIH1cblxuICAgIHJldHVybiBmYWxzZTtcbiAgfTtcbn1cblxuZnVuY3Rpb24gcmVzb2x2ZVN0YXJ0c1dpdGgocGF0dGVybikge1xuICBjb25zdCBwcmVmaXggPSBwYXR0ZXJuLnByZWZpeDtcblxuICByZXR1cm4gZnVuY3Rpb24gKHZhbHVlLCBhcmdzKSB7XG4gICAgaWYgKENoZWNrcy5pc19zdHJpbmcodmFsdWUpICYmIHZhbHVlLnN0YXJ0c1dpdGgocHJlZml4KSkge1xuICAgICAgYXJncy5wdXNoKHZhbHVlLnN1YnN0cmluZyhwcmVmaXgubGVuZ3RoKSk7XG4gICAgICByZXR1cm4gdHJ1ZTtcbiAgICB9XG5cbiAgICByZXR1cm4gZmFsc2U7XG4gIH07XG59XG5cbmZ1bmN0aW9uIHJlc29sdmVUeXBlKHBhdHRlcm4pIHtcbiAgcmV0dXJuIGZ1bmN0aW9uICh2YWx1ZSwgYXJncykge1xuICAgIGlmICh2YWx1ZSBpbnN0YW5jZW9mIHBhdHRlcm4udHlwZSkge1xuICAgICAgY29uc3QgbWF0Y2hlcyA9IGJ1aWxkTWF0Y2gocGF0dGVybi5vYmpQYXR0ZXJuKTtcbiAgICAgIHJldHVybiBtYXRjaGVzKHZhbHVlLCBhcmdzKSAmJiBhcmdzLnB1c2godmFsdWUpID4gMDtcbiAgICB9XG5cbiAgICByZXR1cm4gZmFsc2U7XG4gIH07XG59XG5cbmZ1bmN0aW9uIHJlc29sdmVBcnJheShwYXR0ZXJuKSB7XG4gIGNvbnN0IG1hdGNoZXMgPSBwYXR0ZXJuLm1hcCh4ID0+IGJ1aWxkTWF0Y2goeCkpO1xuXG4gIHJldHVybiBmdW5jdGlvbiAodmFsdWUsIGFyZ3MpIHtcbiAgICBpZiAoIUNoZWNrcy5pc19hcnJheSh2YWx1ZSkgfHwgdmFsdWUubGVuZ3RoICE9IHBhdHRlcm4ubGVuZ3RoKSB7XG4gICAgICByZXR1cm4gZmFsc2U7XG4gICAgfVxuXG4gICAgcmV0dXJuIHZhbHVlLmV2ZXJ5KGZ1bmN0aW9uICh2LCBpKSB7XG4gICAgICByZXR1cm4gbWF0Y2hlc1tpXSh2YWx1ZVtpXSwgYXJncyk7XG4gICAgfSk7XG4gIH07XG59XG5cbmZ1bmN0aW9uIHJlc29sdmVPYmplY3QocGF0dGVybikge1xuICBsZXQgbWF0Y2hlcyA9IHt9O1xuXG4gIGZvciAobGV0IGtleSBvZiBPYmplY3Qua2V5cyhwYXR0ZXJuKS5jb25jYXQoT2JqZWN0LmdldE93blByb3BlcnR5U3ltYm9scyhwYXR0ZXJuKSkpIHtcbiAgICBtYXRjaGVzW2tleV0gPSBidWlsZE1hdGNoKHBhdHRlcm5ba2V5XSk7XG4gIH1cblxuICByZXR1cm4gZnVuY3Rpb24gKHZhbHVlLCBhcmdzKSB7XG4gICAgaWYgKCFDaGVja3MuaXNfb2JqZWN0KHZhbHVlKSB8fCBwYXR0ZXJuLmxlbmd0aCA+IHZhbHVlLmxlbmd0aCkge1xuICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH1cblxuICAgIGZvciAobGV0IGtleSBvZiBPYmplY3Qua2V5cyhwYXR0ZXJuKS5jb25jYXQoT2JqZWN0LmdldE93blByb3BlcnR5U3ltYm9scyhwYXR0ZXJuKSkpIHtcbiAgICAgIGlmICghKGtleSBpbiB2YWx1ZSkgfHwgIW1hdGNoZXNba2V5XSh2YWx1ZVtrZXldLCBhcmdzKSkge1xuICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICB9XG4gICAgfVxuXG4gICAgcmV0dXJuIHRydWU7XG4gIH07XG59XG5cbmZ1bmN0aW9uIHJlc29sdmVOb01hdGNoKCkge1xuICByZXR1cm4gZnVuY3Rpb24gKCkge1xuICAgIHJldHVybiBmYWxzZTtcbiAgfTtcbn1cblxudmFyIFJlc29sdmVycyA9IHtcbiAgcmVzb2x2ZUJvdW5kLFxuICByZXNvbHZlV2lsZGNhcmQsXG4gIHJlc29sdmVWYXJpYWJsZSxcbiAgcmVzb2x2ZUhlYWRUYWlsLFxuICByZXNvbHZlQ2FwdHVyZSxcbiAgcmVzb2x2ZVN0YXJ0c1dpdGgsXG4gIHJlc29sdmVUeXBlLFxuICByZXNvbHZlQXJyYXksXG4gIHJlc29sdmVPYmplY3QsXG4gIHJlc29sdmVOb01hdGNoLFxuICByZXNvbHZlU3ltYm9sLFxuICByZXNvbHZlU3RyaW5nLFxuICByZXNvbHZlTnVtYmVyLFxuICByZXNvbHZlQm9vbGVhbixcbiAgcmVzb2x2ZUZ1bmN0aW9uLFxuICByZXNvbHZlTnVsbFxufTtcblxuZnVuY3Rpb24gYnVpbGRNYXRjaChwYXR0ZXJuKSB7XG5cbiAgaWYgKENoZWNrcy5pc192YXJpYWJsZShwYXR0ZXJuKSkge1xuICAgIHJldHVybiBSZXNvbHZlcnMucmVzb2x2ZVZhcmlhYmxlKHBhdHRlcm4pO1xuICB9XG5cbiAgaWYgKENoZWNrcy5pc193aWxkY2FyZChwYXR0ZXJuKSkge1xuICAgIHJldHVybiBSZXNvbHZlcnMucmVzb2x2ZVdpbGRjYXJkKHBhdHRlcm4pO1xuICB9XG5cbiAgaWYgKENoZWNrcy5pc191bmRlZmluZWQocGF0dGVybikpIHtcbiAgICByZXR1cm4gUmVzb2x2ZXJzLnJlc29sdmVXaWxkY2FyZChwYXR0ZXJuKTtcbiAgfVxuXG4gIGlmIChDaGVja3MuaXNfaGVhZFRhaWwocGF0dGVybikpIHtcbiAgICByZXR1cm4gUmVzb2x2ZXJzLnJlc29sdmVIZWFkVGFpbChwYXR0ZXJuKTtcbiAgfVxuXG4gIGlmIChDaGVja3MuaXNfc3RhcnRzV2l0aChwYXR0ZXJuKSkge1xuICAgIHJldHVybiBSZXNvbHZlcnMucmVzb2x2ZVN0YXJ0c1dpdGgocGF0dGVybik7XG4gIH1cblxuICBpZiAoQ2hlY2tzLmlzX2NhcHR1cmUocGF0dGVybikpIHtcbiAgICByZXR1cm4gUmVzb2x2ZXJzLnJlc29sdmVDYXB0dXJlKHBhdHRlcm4pO1xuICB9XG5cbiAgaWYgKENoZWNrcy5pc19ib3VuZChwYXR0ZXJuKSkge1xuICAgIHJldHVybiBSZXNvbHZlcnMucmVzb2x2ZUJvdW5kKHBhdHRlcm4pO1xuICB9XG5cbiAgaWYgKENoZWNrcy5pc190eXBlKHBhdHRlcm4pKSB7XG4gICAgcmV0dXJuIFJlc29sdmVycy5yZXNvbHZlVHlwZShwYXR0ZXJuKTtcbiAgfVxuXG4gIGlmIChDaGVja3MuaXNfYXJyYXkocGF0dGVybikpIHtcbiAgICByZXR1cm4gUmVzb2x2ZXJzLnJlc29sdmVBcnJheShwYXR0ZXJuKTtcbiAgfVxuXG4gIGlmIChDaGVja3MuaXNfbnVtYmVyKHBhdHRlcm4pKSB7XG4gICAgcmV0dXJuIFJlc29sdmVycy5yZXNvbHZlTnVtYmVyKHBhdHRlcm4pO1xuICB9XG5cbiAgaWYgKENoZWNrcy5pc19zdHJpbmcocGF0dGVybikpIHtcbiAgICByZXR1cm4gUmVzb2x2ZXJzLnJlc29sdmVTdHJpbmcocGF0dGVybik7XG4gIH1cblxuICBpZiAoQ2hlY2tzLmlzX2Jvb2xlYW4ocGF0dGVybikpIHtcbiAgICByZXR1cm4gUmVzb2x2ZXJzLnJlc29sdmVCb29sZWFuKHBhdHRlcm4pO1xuICB9XG5cbiAgaWYgKENoZWNrcy5pc19zeW1ib2wocGF0dGVybikpIHtcbiAgICByZXR1cm4gUmVzb2x2ZXJzLnJlc29sdmVTeW1ib2wocGF0dGVybik7XG4gIH1cblxuICBpZiAoQ2hlY2tzLmlzX251bGwocGF0dGVybikpIHtcbiAgICByZXR1cm4gUmVzb2x2ZXJzLnJlc29sdmVOdWxsKHBhdHRlcm4pO1xuICB9XG5cbiAgaWYgKENoZWNrcy5pc19vYmplY3QocGF0dGVybikpIHtcbiAgICByZXR1cm4gUmVzb2x2ZXJzLnJlc29sdmVPYmplY3QocGF0dGVybik7XG4gIH1cblxuICByZXR1cm4gUmVzb2x2ZXJzLnJlc29sdmVOb01hdGNoKCk7XG59XG5cbmNsYXNzIE1hdGNoRXJyb3IgZXh0ZW5kcyBFcnJvciB7XG4gIGNvbnN0cnVjdG9yKGFyZykge1xuICAgIHN1cGVyKCk7XG5cbiAgICBpZiAodHlwZW9mIGFyZyA9PT0gJ3N5bWJvbCcpIHtcbiAgICAgIHRoaXMubWVzc2FnZSA9ICdObyBtYXRjaCBmb3I6ICcgKyBhcmcudG9TdHJpbmcoKTtcbiAgICB9IGVsc2UgaWYgKEFycmF5LmlzQXJyYXkoYXJnKSkge1xuICAgICAgbGV0IG1hcHBlZFZhbHVlcyA9IGFyZy5tYXAoeCA9PiB4LnRvU3RyaW5nKCkpO1xuICAgICAgdGhpcy5tZXNzYWdlID0gJ05vIG1hdGNoIGZvcjogJyArIG1hcHBlZFZhbHVlcztcbiAgICB9IGVsc2Uge1xuICAgICAgdGhpcy5tZXNzYWdlID0gJ05vIG1hdGNoIGZvcjogJyArIGFyZztcbiAgICB9XG5cbiAgICB0aGlzLnN0YWNrID0gbmV3IEVycm9yKCkuc3RhY2s7XG4gICAgdGhpcy5uYW1lID0gdGhpcy5jb25zdHJ1Y3Rvci5uYW1lO1xuICB9XG59XG5cbmNsYXNzIENhc2Uge1xuXG4gIGNvbnN0cnVjdG9yKHBhdHRlcm4sIGZuLCBndWFyZCA9ICgpID0+IHRydWUpIHtcbiAgICB0aGlzLnBhdHRlcm4gPSBidWlsZE1hdGNoKHBhdHRlcm4pO1xuICAgIHRoaXMuZm4gPSBmbjtcbiAgICB0aGlzLmd1YXJkID0gZ3VhcmQ7XG4gIH1cbn1cblxuZnVuY3Rpb24gbWFrZV9jYXNlKHBhdHRlcm4sIGZuLCBndWFyZCA9ICgpID0+IHRydWUpIHtcbiAgcmV0dXJuIG5ldyBDYXNlKHBhdHRlcm4sIGZuLCBndWFyZCk7XG59XG5cbmZ1bmN0aW9uIGRlZm1hdGNoKC4uLmNhc2VzKSB7XG4gIHJldHVybiBmdW5jdGlvbiAoLi4uYXJncykge1xuICAgIGZvciAobGV0IHByb2Nlc3NlZENhc2Ugb2YgY2FzZXMpIHtcbiAgICAgIGxldCByZXN1bHQgPSBbXTtcbiAgICAgIGlmIChwcm9jZXNzZWRDYXNlLnBhdHRlcm4oYXJncywgcmVzdWx0KSAmJiBwcm9jZXNzZWRDYXNlLmd1YXJkLmFwcGx5KHRoaXMsIHJlc3VsdCkpIHtcbiAgICAgICAgcmV0dXJuIHByb2Nlc3NlZENhc2UuZm4uYXBwbHkodGhpcywgcmVzdWx0KTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICB0aHJvdyBuZXcgTWF0Y2hFcnJvcihhcmdzKTtcbiAgfTtcbn1cblxuZnVuY3Rpb24gbWF0Y2gocGF0dGVybiwgZXhwciwgZ3VhcmQgPSAoKSA9PiB0cnVlKSB7XG4gIGxldCByZXN1bHQgPSBbXTtcbiAgbGV0IHByb2Nlc3NlZFBhdHRlcm4gPSBidWlsZE1hdGNoKHBhdHRlcm4pO1xuICBpZiAocHJvY2Vzc2VkUGF0dGVybihleHByLCByZXN1bHQpICYmIGd1YXJkLmFwcGx5KHRoaXMsIHJlc3VsdCkpIHtcbiAgICByZXR1cm4gcmVzdWx0O1xuICB9IGVsc2Uge1xuICAgIHRocm93IG5ldyBNYXRjaEVycm9yKGV4cHIpO1xuICB9XG59XG5cbmZ1bmN0aW9uIG1hdGNoX25vX3Rocm93KHBhdHRlcm4sIGV4cHIsIGd1YXJkID0gKCkgPT4gdHJ1ZSkge1xuICB0cnkge1xuICAgIHJldHVybiBtYXRjaChwYXR0ZXJuLCBleHByLCBndWFyZCk7XG4gIH0gY2F0Y2ggKGUpIHtcbiAgICBpZiAoZSBpbnN0YW5jZW9mIE1hdGNoRXJyb3IpIHtcbiAgICAgIHJldHVybiBudWxsO1xuICAgIH1cblxuICAgIHRocm93IGU7XG4gIH1cbn1cblxudmFyIFBhdHRlcm5zID0ge1xuICBkZWZtYXRjaCwgbWF0Y2gsIE1hdGNoRXJyb3IsIG1hdGNoX25vX3Rocm93LFxuICB2YXJpYWJsZSwgd2lsZGNhcmQsIHN0YXJ0c1dpdGgsXG4gIGNhcHR1cmUsIGhlYWRUYWlsLCB0eXBlLCBib3VuZCwgQ2FzZSwgbWFrZV9jYXNlXG59O1xuXG5mdW5jdGlvbiBjYWxsX3Byb3BlcnR5KGl0ZW0sIHByb3BlcnR5KSB7XG4gIGxldCBwcm9wID0gbnVsbDtcblxuICBpZiAocHJvcGVydHkgaW4gaXRlbSkge1xuICAgIHByb3AgPSBwcm9wZXJ0eTtcbiAgfSBlbHNlIGlmIChTeW1ib2wuZm9yKHByb3BlcnR5KSBpbiBpdGVtKSB7XG4gICAgcHJvcCA9IFN5bWJvbC5mb3IocHJvcGVydHkpO1xuICB9IGVsc2Uge1xuICAgIHRocm93IG5ldyBFcnJvcihgUHJvcGVydHkgJHsgcHJvcGVydHkgfSBub3QgZm91bmQgaW4gJHsgaXRlbSB9YCk7XG4gIH1cblxuICBpZiAoaXRlbVtwcm9wXSBpbnN0YW5jZW9mIEZ1bmN0aW9uKSB7XG4gICAgcmV0dXJuIGl0ZW1bcHJvcF0oKTtcbiAgfSBlbHNlIHtcbiAgICByZXR1cm4gaXRlbVtwcm9wXTtcbiAgfVxufVxuXG5mdW5jdGlvbiBhcHBseSguLi5hcmdzKSB7XG4gIGlmIChhcmdzLmxlbmd0aCA9PT0gMikge1xuICAgIGFyZ3NbMF0uYXBwbHkobnVsbCwgYXJncy5zbGljZSgxKSk7XG4gIH0gZWxzZSB7XG4gICAgYXJnc1swXVthcmdzWzFdXS5hcHBseShudWxsLCBhcmdzLnNsaWNlKDIpKTtcbiAgfVxufVxuXG5mdW5jdGlvbiBjb250YWlucyhsZWZ0LCByaWdodCkge1xuICBmb3IgKGxldCB4IG9mIHJpZ2h0KSB7XG4gICAgaWYgKFBhdHRlcm5zLm1hdGNoX25vX3Rocm93KGxlZnQsIHgpICE9IG51bGwpIHtcbiAgICAgIHJldHVybiB0cnVlO1xuICAgIH1cbiAgfVxuXG4gIHJldHVybiBmYWxzZTtcbn1cblxuZnVuY3Rpb24gZ2V0X2dsb2JhbCgpIHtcbiAgaWYgKHR5cGVvZiBzZWxmICE9PSAndW5kZWZpbmVkJykge1xuICAgIHJldHVybiBzZWxmO1xuICB9IGVsc2UgaWYgKHR5cGVvZiB3aW5kb3cgIT09ICd1bmRlZmluZWQnKSB7XG4gICAgcmV0dXJuIHdpbmRvdztcbiAgfSBlbHNlIGlmICh0eXBlb2YgZ2xvYmFsICE9PSAndW5kZWZpbmVkJykge1xuICAgIHJldHVybiBnbG9iYWw7XG4gIH1cblxuICB0aHJvdyBuZXcgRXJyb3IoJ05vIGdsb2JhbCBzdGF0ZSBmb3VuZCcpO1xufVxuXG5mdW5jdGlvbiBkZWZzdHJ1Y3QoZGVmYXVsdHMpIHtcbiAgcmV0dXJuIGNsYXNzIHtcbiAgICBjb25zdHJ1Y3Rvcih1cGRhdGUgPSB7fSkge1xuICAgICAgbGV0IHRoZV92YWx1ZXMgPSBPYmplY3QuYXNzaWduKGRlZmF1bHRzLCB1cGRhdGUpO1xuICAgICAgT2JqZWN0LmFzc2lnbih0aGlzLCB0aGVfdmFsdWVzKTtcbiAgICB9XG5cbiAgICBzdGF0aWMgY3JlYXRlKHVwZGF0ZXMgPSB7fSkge1xuICAgICAgbGV0IHggPSBuZXcgdGhpcyh1cGRhdGVzKTtcbiAgICAgIHJldHVybiBPYmplY3QuZnJlZXplKHgpO1xuICAgIH1cbiAgfTtcbn1cblxuZnVuY3Rpb24gZGVmZXhjZXB0aW9uKGRlZmF1bHRzKSB7XG4gIHJldHVybiBjbGFzcyBleHRlbmRzIEVycm9yIHtcbiAgICBjb25zdHJ1Y3Rvcih1cGRhdGUgPSB7fSkge1xuICAgICAgbGV0IG1lc3NhZ2UgPSB1cGRhdGUubWVzc2FnZSB8fCAnJztcbiAgICAgIHN1cGVyKG1lc3NhZ2UpO1xuXG4gICAgICBsZXQgdGhlX3ZhbHVlcyA9IE9iamVjdC5hc3NpZ24oZGVmYXVsdHMsIHVwZGF0ZSk7XG4gICAgICBPYmplY3QuYXNzaWduKHRoaXMsIHRoZV92YWx1ZXMpO1xuXG4gICAgICB0aGlzLm5hbWUgPSB0aGlzLmNvbnN0cnVjdG9yLm5hbWU7XG4gICAgICB0aGlzLm1lc3NhZ2UgPSBtZXNzYWdlO1xuICAgICAgdGhpc1tTcGVjaWFsRm9ybXMuYXRvbSgnX19leGNlcHRpb25fXycpXSA9IHRydWU7XG4gICAgICBFcnJvci5jYXB0dXJlU3RhY2tUcmFjZSh0aGlzLCB0aGlzLmNvbnN0cnVjdG9yLm5hbWUpO1xuICAgIH1cblxuICAgIHN0YXRpYyBjcmVhdGUodXBkYXRlcyA9IHt9KSB7XG4gICAgICBsZXQgeCA9IG5ldyB0aGlzKHVwZGF0ZXMpO1xuICAgICAgcmV0dXJuIE9iamVjdC5mcmVlemUoeCk7XG4gICAgfVxuICB9O1xufVxuXG5mdW5jdGlvbiBkZWZwcm90b2NvbChzcGVjKSB7XG4gIHJldHVybiBuZXcgUHJvdG9jb2woc3BlYyk7XG59XG5cbmZ1bmN0aW9uIGRlZmltcGwocHJvdG9jb2wsIHR5cGUsIGltcGwpIHtcbiAgcHJvdG9jb2wuaW1wbGVtZW50YXRpb24odHlwZSwgaW1wbCk7XG59XG5cbmZ1bmN0aW9uIGdldF9vYmplY3Rfa2V5cyhvYmopIHtcbiAgcmV0dXJuIE9iamVjdC5rZXlzKG9iaikuY29uY2F0KE9iamVjdC5nZXRPd25Qcm9wZXJ0eVN5bWJvbHMob2JqKSk7XG59XG5cbmZ1bmN0aW9uIGlzX3ZhbGlkX2NoYXJhY3Rlcihjb2RlcG9pbnQpIHtcbiAgdHJ5IHtcbiAgICByZXR1cm4gU3RyaW5nLmZyb21Db2RlUG9pbnQoY29kZXBvaW50KSAhPSBudWxsO1xuICB9IGNhdGNoIChlKSB7XG4gICAgcmV0dXJuIGZhbHNlO1xuICB9XG59XG5cbi8vaHR0cHM6Ly9kZXZlbG9wZXIubW96aWxsYS5vcmcvZW4tVVMvZG9jcy9XZWIvQVBJL1dpbmRvd0Jhc2U2NC9CYXNlNjRfZW5jb2RpbmdfYW5kX2RlY29kaW5nI1NvbHV0aW9uXzJfJUUyJTgwJTkzX3Jld3JpdGVfdGhlX0RPTXNfYXRvYigpX2FuZF9idG9hKClfdXNpbmdfSmF2YVNjcmlwdCdzX1R5cGVkQXJyYXlzX2FuZF9VVEYtOFxuZnVuY3Rpb24gYjY0RW5jb2RlVW5pY29kZShzdHIpIHtcbiAgcmV0dXJuIGJ0b2EoZW5jb2RlVVJJQ29tcG9uZW50KHN0cikucmVwbGFjZSgvJShbMC05QS1GXXsyfSkvZywgZnVuY3Rpb24gKG1hdGNoLCBwMSkge1xuICAgIHJldHVybiBTdHJpbmcuZnJvbUNoYXJDb2RlKCcweCcgKyBwMSk7XG4gIH0pKTtcbn1cblxuZnVuY3Rpb24gZGVsZXRlX3Byb3BlcnR5X2Zyb21fbWFwKG1hcCwgcHJvcGVydHkpIHtcbiAgbGV0IG5ld19tYXAgPSBPYmplY3QuYXNzaWduKE9iamVjdC5jcmVhdGUobWFwLmNvbnN0cnVjdG9yLnByb3RvdHlwZSksIG1hcCk7XG4gIGRlbGV0ZSBuZXdfbWFwW3Byb3BlcnR5XTtcblxuICByZXR1cm4gT2JqZWN0LmZyZWV6ZShuZXdfbWFwKTtcbn1cblxuZnVuY3Rpb24gY2xhc3NfdG9fb2JqKG1hcCkge1xuICBsZXQgbmV3X21hcCA9IE9iamVjdC5hc3NpZ24oe30sIG1hcCk7XG4gIHJldHVybiBPYmplY3QuZnJlZXplKG5ld19tYXApO1xufVxuXG5mdW5jdGlvbiBhZGRfcHJvcGVydHlfdG9fbWFwKG1hcCwgcHJvcGVydHksIHZhbHVlKSB7XG4gIGxldCBuZXdfbWFwID0gT2JqZWN0LmFzc2lnbih7fSwgbWFwKTtcbiAgbmV3X21hcFtwcm9wZXJ0eV0gPSB2YWx1ZTtcbiAgcmV0dXJuIE9iamVjdC5mcmVlemUobmV3X21hcCk7XG59XG5cbmZ1bmN0aW9uIGJub3QoZXhwcikge1xuICByZXR1cm4gfmV4cHI7XG59XG5cbmZ1bmN0aW9uIGJhbmQobGVmdCwgcmlnaHQpIHtcbiAgcmV0dXJuIGxlZnQgJiByaWdodDtcbn1cblxuZnVuY3Rpb24gYm9yKGxlZnQsIHJpZ2h0KSB7XG4gIHJldHVybiBsZWZ0IHwgcmlnaHQ7XG59XG5cbmZ1bmN0aW9uIGJzbChsZWZ0LCByaWdodCkge1xuICByZXR1cm4gbGVmdCA8PCByaWdodDtcbn1cblxuZnVuY3Rpb24gYnNyKGxlZnQsIHJpZ2h0KSB7XG4gIHJldHVybiBsZWZ0ID4+IHJpZ2h0O1xufVxuXG5mdW5jdGlvbiBieG9yKGxlZnQsIHJpZ2h0KSB7XG4gIHJldHVybiBsZWZ0IF4gcmlnaHQ7XG59XG5cbmZ1bmN0aW9uIHppcChsaXN0X29mX2xpc3RzKSB7XG4gIGlmIChsaXN0X29mX2xpc3RzLmxlbmd0aCA9PT0gMCkge1xuICAgIHJldHVybiBPYmplY3QuZnJlZXplKFtdKTtcbiAgfVxuXG4gIGxldCBuZXdfdmFsdWUgPSBbXTtcbiAgbGV0IHNtYWxsZXN0X2xlbmd0aCA9IGxpc3Rfb2ZfbGlzdHNbMF07XG5cbiAgZm9yIChsZXQgeCBvZiBsaXN0X29mX2xpc3RzKSB7XG4gICAgaWYgKHgubGVuZ3RoIDwgc21hbGxlc3RfbGVuZ3RoKSB7XG4gICAgICBzbWFsbGVzdF9sZW5ndGggPSB4Lmxlbmd0aDtcbiAgICB9XG4gIH1cblxuICBmb3IgKGxldCBpID0gMDsgaSA8IHNtYWxsZXN0X2xlbmd0aDsgaSsrKSB7XG4gICAgbGV0IGN1cnJlbnRfdmFsdWUgPSBbXTtcbiAgICBmb3IgKGxldCBqID0gMDsgaiA8IGxpc3Rfb2ZfbGlzdHMubGVuZ3RoOyBqKyspIHtcbiAgICAgIGN1cnJlbnRfdmFsdWUucHVzaChsaXN0X29mX2xpc3RzW2pdW2ldKTtcbiAgICB9XG5cbiAgICBuZXdfdmFsdWUucHVzaChuZXcgVHVwbGUoLi4uY3VycmVudF92YWx1ZSkpO1xuICB9XG5cbiAgcmV0dXJuIE9iamVjdC5mcmVlemUobmV3X3ZhbHVlKTtcbn1cblxuZnVuY3Rpb24gY2FuX2RlY29kZTY0KGRhdGEpIHtcbiAgdHJ5IHtcbiAgICBhdG9iKGRhdGEpO1xuICAgIHJldHVybiB0cnVlO1xuICB9IGNhdGNoIChlKSB7XG4gICAgcmV0dXJuIGZhbHNlO1xuICB9XG59XG5cbnZhciBGdW5jdGlvbnMgPSB7XG4gIGNhbGxfcHJvcGVydHksXG4gIGFwcGx5LFxuICBjb250YWlucyxcbiAgZ2V0X2dsb2JhbCxcbiAgZGVmc3RydWN0LFxuICBkZWZleGNlcHRpb24sXG4gIGRlZnByb3RvY29sLFxuICBkZWZpbXBsLFxuICBnZXRfb2JqZWN0X2tleXMsXG4gIGlzX3ZhbGlkX2NoYXJhY3RlcixcbiAgYjY0RW5jb2RlVW5pY29kZSxcbiAgZGVsZXRlX3Byb3BlcnR5X2Zyb21fbWFwLFxuICBhZGRfcHJvcGVydHlfdG9fbWFwLFxuICBjbGFzc190b19vYmosXG4gIGNhbl9kZWNvZGU2NCxcbiAgYm5vdCxcbiAgYmFuZCxcbiAgYm9yLFxuICBic2wsXG4gIGJzcixcbiAgYnhvcixcbiAgemlwXG59O1xuXG5mdW5jdGlvbiBfY2FzZShjb25kaXRpb24sIGNsYXVzZXMpIHtcbiAgcmV0dXJuIFBhdHRlcm5zLmRlZm1hdGNoKC4uLmNsYXVzZXMpKGNvbmRpdGlvbik7XG59XG5cbmZ1bmN0aW9uIGNvbmQoY2xhdXNlcykge1xuICBmb3IgKGxldCBjbGF1c2Ugb2YgY2xhdXNlcykge1xuICAgIGlmIChjbGF1c2VbMF0pIHtcbiAgICAgIHJldHVybiBjbGF1c2VbMV0oKTtcbiAgICB9XG4gIH1cblxuICB0aHJvdyBuZXcgRXJyb3IoKTtcbn1cblxuZnVuY3Rpb24gbWFwX3VwZGF0ZShtYXAsIHZhbHVlcykge1xuICByZXR1cm4gT2JqZWN0LmZyZWV6ZShPYmplY3QuYXNzaWduKE9iamVjdC5jcmVhdGUobWFwLmNvbnN0cnVjdG9yLnByb3RvdHlwZSksIG1hcCwgdmFsdWVzKSk7XG59XG5cbmZ1bmN0aW9uIF9mb3IoY29sbGVjdGlvbnMsIGZ1biwgZmlsdGVyID0gKCkgPT4gdHJ1ZSwgaW50byA9IFtdLCBwcmV2aW91c1ZhbHVlcyA9IFtdKSB7XG4gIGxldCBwYXR0ZXJuID0gY29sbGVjdGlvbnNbMF1bMF07XG4gIGxldCBjb2xsZWN0aW9uID0gY29sbGVjdGlvbnNbMF1bMV07XG5cbiAgaWYgKGNvbGxlY3Rpb25zLmxlbmd0aCA9PT0gMSkge1xuXG4gICAgZm9yIChsZXQgZWxlbSBvZiBjb2xsZWN0aW9uKSB7XG4gICAgICBsZXQgciA9IFBhdHRlcm5zLm1hdGNoX25vX3Rocm93KHBhdHRlcm4sIGVsZW0pO1xuICAgICAgbGV0IGFyZ3MgPSBwcmV2aW91c1ZhbHVlcy5jb25jYXQocik7XG5cbiAgICAgIGlmIChyICYmIGZpbHRlci5hcHBseSh0aGlzLCBhcmdzKSkge1xuICAgICAgICBpbnRvID0gaW50by5jb25jYXQoW2Z1bi5hcHBseSh0aGlzLCBhcmdzKV0pO1xuICAgICAgfVxuICAgIH1cblxuICAgIHJldHVybiBpbnRvO1xuICB9IGVsc2Uge1xuICAgIGxldCBfaW50byA9IFtdO1xuXG4gICAgZm9yIChsZXQgZWxlbSBvZiBjb2xsZWN0aW9uKSB7XG4gICAgICBsZXQgciA9IFBhdHRlcm5zLm1hdGNoX25vX3Rocm93KHBhdHRlcm4sIGVsZW0pO1xuICAgICAgaWYgKHIpIHtcbiAgICAgICAgX2ludG8gPSBpbnRvLmNvbmNhdCh0aGlzLl9mb3IoY29sbGVjdGlvbnMuc2xpY2UoMSksIGZ1biwgZmlsdGVyLCBfaW50bywgcHJldmlvdXNWYWx1ZXMuY29uY2F0KHIpKSk7XG4gICAgICB9XG4gICAgfVxuXG4gICAgcmV0dXJuIF9pbnRvO1xuICB9XG59XG5cbmZ1bmN0aW9uIF90cnkoZG9fZnVuLCByZXNjdWVfZnVuY3Rpb24sIGNhdGNoX2Z1biwgZWxzZV9mdW5jdGlvbiwgYWZ0ZXJfZnVuY3Rpb24pIHtcbiAgbGV0IHJlc3VsdCA9IG51bGw7XG5cbiAgdHJ5IHtcbiAgICByZXN1bHQgPSBkb19mdW4oKTtcbiAgfSBjYXRjaCAoZSkge1xuICAgIGxldCBleF9yZXN1bHQgPSBudWxsO1xuXG4gICAgaWYgKHJlc2N1ZV9mdW5jdGlvbikge1xuICAgICAgdHJ5IHtcbiAgICAgICAgZXhfcmVzdWx0ID0gcmVzY3VlX2Z1bmN0aW9uKGUpO1xuICAgICAgICByZXR1cm4gZXhfcmVzdWx0O1xuICAgICAgfSBjYXRjaCAoZXgpIHtcbiAgICAgICAgaWYgKGV4IGluc3RhbmNlb2YgUGF0dGVybnMuTWF0Y2hFcnJvcikge1xuICAgICAgICAgIHRocm93IGV4O1xuICAgICAgICB9XG4gICAgICB9XG4gICAgfVxuXG4gICAgaWYgKGNhdGNoX2Z1bikge1xuICAgICAgdHJ5IHtcbiAgICAgICAgZXhfcmVzdWx0ID0gY2F0Y2hfZnVuKGUpO1xuICAgICAgICByZXR1cm4gZXhfcmVzdWx0O1xuICAgICAgfSBjYXRjaCAoZXgpIHtcbiAgICAgICAgaWYgKGV4IGluc3RhbmNlb2YgUGF0dGVybnMuTWF0Y2hFcnJvcikge1xuICAgICAgICAgIHRocm93IGV4O1xuICAgICAgICB9XG4gICAgICB9XG4gICAgfVxuXG4gICAgdGhyb3cgZTtcbiAgfSBmaW5hbGx5IHtcbiAgICBpZiAoYWZ0ZXJfZnVuY3Rpb24pIHtcbiAgICAgIGFmdGVyX2Z1bmN0aW9uKCk7XG4gICAgfVxuICB9XG5cbiAgaWYgKGVsc2VfZnVuY3Rpb24pIHtcbiAgICB0cnkge1xuICAgICAgcmV0dXJuIGVsc2VfZnVuY3Rpb24ocmVzdWx0KTtcbiAgICB9IGNhdGNoIChleCkge1xuICAgICAgaWYgKGV4IGluc3RhbmNlb2YgUGF0dGVybnMuTWF0Y2hFcnJvcikge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ05vIE1hdGNoIEZvdW5kIGluIEVsc2UnKTtcbiAgICAgIH1cblxuICAgICAgdGhyb3cgZXg7XG4gICAgfVxuICB9IGVsc2Uge1xuICAgIHJldHVybiByZXN1bHQ7XG4gIH1cbn1cblxudmFyIFNwZWNpYWxGb3JtcyQxID0ge1xuICBfY2FzZSxcbiAgY29uZCxcbiAgbWFwX3VwZGF0ZSxcbiAgX2ZvcixcbiAgX3RyeVxufTtcblxuRnVuY3Rpb25zLmdldF9nbG9iYWwoKS5wcm9jZXNzZXMgPSBGdW5jdGlvbnMuZ2V0X2dsb2JhbCgpLnByb2Nlc3NlcyB8fCBuZXcgUHJvY2Vzc1N5c3RlbSgpO1xuXG52YXIgQ29yZSA9IHtcbiAgUHJvY2Vzc1N5c3RlbSxcbiAgVHVwbGUsXG4gIFBJRCxcbiAgQml0U3RyaW5nLFxuICBQYXR0ZXJucyxcbiAgSW50ZWdlcixcbiAgRmxvYXQsXG4gIEZ1bmN0aW9ucyxcbiAgU3BlY2lhbEZvcm1zOiBTcGVjaWFsRm9ybXMkMVxufTtcblxubGV0IEVudW0gPSB7XG5cbiAgYWxsX19xbWFya19fOiBmdW5jdGlvbiAoY29sbGVjdGlvbiwgZnVuID0geCA9PiB4KSB7XG4gICAgZm9yIChsZXQgZWxlbSBvZiBjb2xsZWN0aW9uKSB7XG4gICAgICBpZiAoIWZ1bihlbGVtKSkge1xuICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICB9XG4gICAgfVxuXG4gICAgcmV0dXJuIHRydWU7XG4gIH0sXG5cbiAgYW55X19xbWFya19fOiBmdW5jdGlvbiAoY29sbGVjdGlvbiwgZnVuID0geCA9PiB4KSB7XG4gICAgZm9yIChsZXQgZWxlbSBvZiBjb2xsZWN0aW9uKSB7XG4gICAgICBpZiAoZnVuKGVsZW0pKSB7XG4gICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgfVxuICAgIH1cblxuICAgIHJldHVybiBmYWxzZTtcbiAgfSxcblxuICBhdDogZnVuY3Rpb24gKGNvbGxlY3Rpb24sIG4sIHRoZV9kZWZhdWx0ID0gbnVsbCkge1xuICAgIGlmIChuID4gdGhpcy5jb3VudChjb2xsZWN0aW9uKSB8fCBuIDwgMCkge1xuICAgICAgcmV0dXJuIHRoZV9kZWZhdWx0O1xuICAgIH1cblxuICAgIHJldHVybiBjb2xsZWN0aW9uW25dO1xuICB9LFxuXG4gIGNvbmNhdDogZnVuY3Rpb24gKC4uLmVudW1hYmxlcykge1xuICAgIHJldHVybiBlbnVtYWJsZXNbMF0uY29uY2F0KGVudW1hYmxlc1sxXSk7XG4gIH0sXG5cbiAgY291bnQ6IGZ1bmN0aW9uIChjb2xsZWN0aW9uLCBmdW4gPSBudWxsKSB7XG4gICAgaWYgKGZ1biA9PSBudWxsKSB7XG4gICAgICByZXR1cm4gY29sbGVjdGlvbi5sZW5ndGg7XG4gICAgfSBlbHNlIHtcbiAgICAgIHJldHVybiBjb2xsZWN0aW9uLmZpbHRlcihmdW4pLmxlbmd0aDtcbiAgICB9XG4gIH0sXG5cbiAgZHJvcDogZnVuY3Rpb24gKGNvbGxlY3Rpb24sIGNvdW50KSB7XG4gICAgcmV0dXJuIGNvbGxlY3Rpb24uc2xpY2UoY291bnQpO1xuICB9LFxuXG4gIGRyb3Bfd2hpbGU6IGZ1bmN0aW9uIChjb2xsZWN0aW9uLCBmdW4pIHtcbiAgICBsZXQgY291bnQgPSAwO1xuXG4gICAgZm9yIChsZXQgZWxlbSBvZiBjb2xsZWN0aW9uKSB7XG4gICAgICBpZiAoZnVuKGVsZW0pKSB7XG4gICAgICAgIGNvdW50ID0gY291bnQgKyAxO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgYnJlYWs7XG4gICAgICB9XG4gICAgfVxuXG4gICAgcmV0dXJuIGNvbGxlY3Rpb24uc2xpY2UoY291bnQpO1xuICB9LFxuXG4gIGVhY2g6IGZ1bmN0aW9uIChjb2xsZWN0aW9uLCBmdW4pIHtcbiAgICBmb3IgKGxldCBlbGVtIG9mIGNvbGxlY3Rpb24pIHtcbiAgICAgIGZ1bihlbGVtKTtcbiAgICB9XG4gIH0sXG5cbiAgZW1wdHlfX3FtYXJrX186IGZ1bmN0aW9uIChjb2xsZWN0aW9uKSB7XG4gICAgcmV0dXJuIGNvbGxlY3Rpb24ubGVuZ3RoID09PSAwO1xuICB9LFxuXG4gIGZldGNoOiBmdW5jdGlvbiAoY29sbGVjdGlvbiwgbikge1xuICAgIGlmIChBcnJheS5pc0FycmF5KGNvbGxlY3Rpb24pKSB7XG4gICAgICBpZiAobiA8IHRoaXMuY291bnQoY29sbGVjdGlvbikgJiYgbiA+PSAwKSB7XG4gICAgICAgIHJldHVybiBuZXcgQ29yZS5UdXBsZShTeW1ib2wuZm9yKFwib2tcIiksIGNvbGxlY3Rpb25bbl0pO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgcmV0dXJuIFN5bWJvbC5mb3IoXCJlcnJvclwiKTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICB0aHJvdyBuZXcgRXJyb3IoXCJjb2xsZWN0aW9uIGlzIG5vdCBhbiBFbnVtZXJhYmxlXCIpO1xuICB9LFxuXG4gIGZldGNoX19lbWFya19fOiBmdW5jdGlvbiAoY29sbGVjdGlvbiwgbikge1xuICAgIGlmIChBcnJheS5pc0FycmF5KGNvbGxlY3Rpb24pKSB7XG4gICAgICBpZiAobiA8IHRoaXMuY291bnQoY29sbGVjdGlvbikgJiYgbiA+PSAwKSB7XG4gICAgICAgIHJldHVybiBjb2xsZWN0aW9uW25dO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKFwib3V0IG9mIGJvdW5kcyBlcnJvclwiKTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICB0aHJvdyBuZXcgRXJyb3IoXCJjb2xsZWN0aW9uIGlzIG5vdCBhbiBFbnVtZXJhYmxlXCIpO1xuICB9LFxuXG4gIGZpbHRlcjogZnVuY3Rpb24gKGNvbGxlY3Rpb24sIGZ1bikge1xuICAgIGxldCByZXN1bHQgPSBbXTtcblxuICAgIGZvciAobGV0IGVsZW0gb2YgY29sbGVjdGlvbikge1xuICAgICAgaWYgKGZ1bihlbGVtKSkge1xuICAgICAgICByZXN1bHQucHVzaChlbGVtKTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICByZXR1cm4gcmVzdWx0O1xuICB9LFxuXG4gIGZpbHRlcl9tYXA6IGZ1bmN0aW9uIChjb2xsZWN0aW9uLCBmaWx0ZXIsIG1hcHBlcikge1xuICAgIHJldHVybiBFbnVtLm1hcChFbnVtLmZpbHRlcihjb2xsZWN0aW9uLCBmaWx0ZXIpLCBtYXBwZXIpO1xuICB9LFxuXG4gIGZpbmQ6IGZ1bmN0aW9uIChjb2xsZWN0aW9uLCBpZl9ub25lID0gbnVsbCwgZnVuKSB7XG4gICAgZm9yIChsZXQgZWxlbSBvZiBjb2xsZWN0aW9uKSB7XG4gICAgICBpZiAoZnVuKGVsZW0pKSB7XG4gICAgICAgIHJldHVybiBlbGVtO1xuICAgICAgfVxuICAgIH1cblxuICAgIHJldHVybiBpZl9ub25lO1xuICB9LFxuXG4gIGludG86IGZ1bmN0aW9uIChjb2xsZWN0aW9uLCBsaXN0KSB7XG4gICAgcmV0dXJuIGxpc3QuY29uY2F0KGNvbGxlY3Rpb24pO1xuICB9LFxuXG4gIG1hcDogZnVuY3Rpb24gKGNvbGxlY3Rpb24sIGZ1bikge1xuICAgIGxldCByZXN1bHQgPSBbXTtcblxuICAgIGZvciAobGV0IGVsZW0gb2YgY29sbGVjdGlvbikge1xuICAgICAgcmVzdWx0LnB1c2goZnVuKGVsZW0pKTtcbiAgICB9XG5cbiAgICByZXR1cm4gcmVzdWx0O1xuICB9LFxuXG4gIG1hcF9yZWR1Y2U6IGZ1bmN0aW9uIChjb2xsZWN0aW9uLCBhY2MsIGZ1bikge1xuICAgIGxldCBtYXBwZWQgPSBPYmplY3QuZnJlZXplKFtdKTtcbiAgICBsZXQgdGhlX2FjYyA9IGFjYztcblxuICAgIGZvciAodmFyIGkgPSAwOyBpIDwgdGhpcy5jb3VudChjb2xsZWN0aW9uKTsgaSsrKSB7XG4gICAgICBsZXQgdHVwbGUgPSBmdW4oY29sbGVjdGlvbltpXSwgdGhlX2FjYyk7XG5cbiAgICAgIHRoZV9hY2MgPSB0dXBsZS5nZXQoMSk7XG4gICAgICBtYXBwZWQgPSBPYmplY3QuZnJlZXplKG1hcHBlZC5jb25jYXQoW3R1cGxlLmdldCgwKV0pKTtcbiAgICB9XG5cbiAgICByZXR1cm4gbmV3IENvcmUuVHVwbGUobWFwcGVkLCB0aGVfYWNjKTtcbiAgfSxcblxuICBtZW1iZXJfX3FtYXJrX186IGZ1bmN0aW9uIChjb2xsZWN0aW9uLCB2YWx1ZSkge1xuICAgIHJldHVybiBjb2xsZWN0aW9uLmluY2x1ZGVzKHZhbHVlKTtcbiAgfSxcblxuICByZWR1Y2U6IGZ1bmN0aW9uIChjb2xsZWN0aW9uLCBhY2MsIGZ1bikge1xuICAgIGxldCB0aGVfYWNjID0gYWNjO1xuXG4gICAgZm9yICh2YXIgaSA9IDA7IGkgPCB0aGlzLmNvdW50KGNvbGxlY3Rpb24pOyBpKyspIHtcbiAgICAgIGxldCB0dXBsZSA9IGZ1bihjb2xsZWN0aW9uW2ldLCB0aGVfYWNjKTtcblxuICAgICAgdGhlX2FjYyA9IHR1cGxlLmdldCgxKTtcbiAgICB9XG5cbiAgICByZXR1cm4gdGhlX2FjYztcbiAgfSxcblxuICB0YWtlOiBmdW5jdGlvbiAoY29sbGVjdGlvbiwgY291bnQpIHtcbiAgICByZXR1cm4gY29sbGVjdGlvbi5zbGljZSgwLCBjb3VudCk7XG4gIH0sXG5cbiAgdGFrZV9ldmVyeTogZnVuY3Rpb24gKGNvbGxlY3Rpb24sIG50aCkge1xuICAgIGxldCByZXN1bHQgPSBbXTtcbiAgICBsZXQgaW5kZXggPSAwO1xuXG4gICAgZm9yIChsZXQgZWxlbSBvZiBjb2xsZWN0aW9uKSB7XG4gICAgICBpZiAoaW5kZXggJSBudGggPT09IDApIHtcbiAgICAgICAgcmVzdWx0LnB1c2goZWxlbSk7XG4gICAgICB9XG4gICAgfVxuXG4gICAgcmV0dXJuIE9iamVjdC5mcmVlemUocmVzdWx0KTtcbiAgfSxcblxuICB0YWtlX3doaWxlOiBmdW5jdGlvbiAoY29sbGVjdGlvbiwgZnVuKSB7XG4gICAgbGV0IGNvdW50ID0gMDtcblxuICAgIGZvciAobGV0IGVsZW0gb2YgY29sbGVjdGlvbikge1xuICAgICAgaWYgKGZ1bihlbGVtKSkge1xuICAgICAgICBjb3VudCA9IGNvdW50ICsgMTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIGJyZWFrO1xuICAgICAgfVxuICAgIH1cblxuICAgIHJldHVybiBjb2xsZWN0aW9uLnNsaWNlKDAsIGNvdW50KTtcbiAgfSxcblxuICB0b19saXN0OiBmdW5jdGlvbiAoY29sbGVjdGlvbikge1xuICAgIHJldHVybiBjb2xsZWN0aW9uO1xuICB9XG59O1xuXG52YXIgRWxpeGlyID0ge1xuICBDb3JlLFxuICBFbnVtLFxuICBWaXJ0dWFsRE9NXG59O1xuXG5leHBvcnQgZGVmYXVsdCBFbGl4aXI7Il0sImZpbGUiOiJFbGl4aXIuanMiLCJzb3VyY2VSb290IjoiL3NvdXJjZS8ifQ== \ No newline at end of file diff --git a/src/javascript/elixir.js b/src/javascript/elixir.js index c6ba77ac..9dc23da5 100644 --- a/src/javascript/elixir.js +++ b/src/javascript/elixir.js @@ -1,5 +1,9 @@ -import * as C from './lib/core'; +import Core from './lib/core'; +import Enum from './lib/enum'; +import VirtualDOM from './lib/virtual-dom'; -export const Core = C; -export { default as Enum } from './lib/enum'; -export { default as VirtualDOM } from './lib/virtual-dom'; +export default { + Core, + Enum, + VirtualDOM +} diff --git a/src/javascript/lib/core.js b/src/javascript/lib/core.js index 5aadd909..f55eca1f 100644 --- a/src/javascript/lib/core.js +++ b/src/javascript/lib/core.js @@ -7,7 +7,7 @@ import SpecialForms from './core/special_forms'; Functions.get_global().processes = Functions.get_global().processes || new ProcessSystem(); -export { +export default { ProcessSystem, Tuple, PID, diff --git a/src/javascript/lib/enum.js b/src/javascript/lib/enum.js index 1e9dbfdd..13916e50 100644 --- a/src/javascript/lib/enum.js +++ b/src/javascript/lib/enum.js @@ -1,4 +1,4 @@ -import * as Core from './core'; +import Core from './core'; let Enum = { diff --git a/test/elixir_script_test.exs b/test/elixir_script_test.exs index 88d9f63c..1c2d8f61 100644 --- a/test/elixir_script_test.exs +++ b/test/elixir_script_test.exs @@ -42,9 +42,9 @@ defmodule ElixirScript.Test do """) assert_js_matches """ - import * as Elixir from './Elixir'; - import * as Elixir$ElixirScript$Kernel from './Elixir.ElixirScript.Kernel'; - import * as Elixir$ElixirScript$String$Chars from './Elixir.ElixirScript.String.Chars'; + import Elixir from './Elixir'; + import Elixir$ElixirScript$Kernel from './Elixir.ElixirScript.Kernel'; + import Elixir$ElixirScript$String$Chars from './Elixir.ElixirScript.String.Chars'; const something_else = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([],function() { return Elixir$ElixirScript$String$Chars.to_string(10); })); @@ -52,7 +52,7 @@ defmodule ElixirScript.Test do return ul; })); const ul = JQuery('#todo-list'); - export { + export default { something }; """, hd(js_code) @@ -76,25 +76,25 @@ defmodule ElixirScript.Test do """, %{ env: make_custom_env }) assert_js_matches """ - import * as Elixir from './Elixir'; - import * as Elixir$ElixirScript$Kernel from './Elixir.ElixirScript.Kernel'; - import * as Elixir$Animals$Elephant from './Elixir.Animals.Elephant'; + import Elixir from './Elixir'; + import Elixir$ElixirScript$Kernel from './Elixir.ElixirScript.Kernel'; + import Elixir$Animals$Elephant from './Elixir.Animals.Elephant'; const something = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([],function() { return Elixir$Animals$Elephant.Elixir$Animals$Elephant.create(Object.freeze({})); })); - export { + export default { something }; """, hd(js_code) assert_js_matches """ - import * as Elixir from './Elixir'; - import * as Elixir$ElixirScript$Kernel from './Elixir.ElixirScript.Kernel'; + import Elixir from './Elixir'; + import Elixir$ElixirScript$Kernel from './Elixir.ElixirScript.Kernel'; const Elixir$Animals$Elephant = Elixir.Core.Functions.defstruct({ [Symbol.for('__struct__')]: Symbol.for('Elixir.Animals.Elephant'), [Symbol.for('trunk')]: true }); - export { + export default { Elixir$Animals$Elephant }; """, Enum.fetch!(js_code, 1) @@ -115,15 +115,15 @@ defmodule ElixirScript.Test do """, %{ env: make_custom_env }) assert_js_matches """ - import * as Elixir from './Elixir'; - import * as Elixir$ElixirScript$Kernel from './Elixir.ElixirScript.Kernel'; + import Elixir from './Elixir'; + import Elixir$ElixirScript$Kernel from './Elixir.ElixirScript.Kernel'; const something_else = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([],function() { return 1 * 1; })); const sandwich = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([],function() { return null; })); - export { + export default { sandwich }; """, hd(js_code) @@ -168,15 +168,15 @@ defmodule ElixirScript.Test do """, %{ env: make_custom_env, stdlib_path: "elixirscript"} ) assert_js_matches """ - import * as Elixir from './elixirscript'; - import * as Elixir$ElixirScript$Kernel from './Elixir.ElixirScript.Kernel'; + import Elixir from './elixirscript'; + import Elixir$ElixirScript$Kernel from './Elixir.ElixirScript.Kernel'; const something_else = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([],function() { return 1 * 1; })); const sandwich = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([],function() { return null; })); - export { + export default { sandwich }; """, hd(js_code) diff --git a/test/translator/bug_test.exs b/test/translator/bug_test.exs index e6dbb769..92adfba7 100644 --- a/test/translator/bug_test.exs +++ b/test/translator/bug_test.exs @@ -47,9 +47,9 @@ defmodule ElixirScript.Translator.Bug.Test do js_code = """ import JQuery from 'jquery'; - import * as Elixir$ElixirScript$Kernel from './Elixir.ElixirScript.Kernel'; + import Elixir$ElixirScript$Kernel from './Elixir.ElixirScript.Kernel'; JQuery(Elixir.Core.Functions.call_property(e,'target')); - export {}; + export default {}; """ assert_translation(ex_ast, js_code) diff --git a/test/translator/defmodule_test.exs b/test/translator/defmodule_test.exs index e032dd1f..df4f343d 100644 --- a/test/translator/defmodule_test.exs +++ b/test/translator/defmodule_test.exs @@ -9,8 +9,8 @@ defmodule ElixirScript.Translator.Defmodule.Test do end js_code = """ - import * as Elixir$ElixirScript$Kernel from './Elixir.ElixirScript.Kernel'; - export {}; + import Elixir$ElixirScript$Kernel from './Elixir.ElixirScript.Kernel'; + export default {}; """ assert_translation(ex_ast, js_code) @@ -32,7 +32,7 @@ defmodule ElixirScript.Translator.Defmodule.Test do js_code = """ - import * as Elixir$ElixirScript$Kernel from './Elixir.ElixirScript.Kernel'; + import Elixir$ElixirScript$Kernel from './Elixir.ElixirScript.Kernel'; const something_else = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([],function() { return null; })); @@ -40,7 +40,7 @@ defmodule ElixirScript.Translator.Defmodule.Test do return ul; })); const ul = JQuery('#todo-list'); - export { + export default { something }; """ @@ -67,8 +67,8 @@ defmodule ElixirScript.Translator.Defmodule.Test do end js_code = """ - import * as Elixir$ElixirScript$Kernel from './Elixir.ElixirScript.Kernel'; - import * as Elixir$Animals$Elephant from './Elixir.Animals.Elephant'; + import Elixir$ElixirScript$Kernel from './Elixir.ElixirScript.Kernel'; + import Elixir$Animals$Elephant from './Elixir.Animals.Elephant'; const something_else = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([],function() { return null; })); @@ -77,16 +77,16 @@ defmodule ElixirScript.Translator.Defmodule.Test do return Elixir$Animals$Elephant.Elixir$Animals$Elephant.create(Object.freeze({})); })); - export { + export default { something }; - import * as Elixir$ElixirScript$Kernel from './Elixir.ElixirScript.Kernel'; + import Elixir$ElixirScript$Kernel from './Elixir.ElixirScript.Kernel'; const Elixir$Animals$Elephant = Elixir.Core.Functions.defstruct({ [Symbol.for('__struct__')]: Symbol.for('Elixir.Animals.Elephant'), [Symbol.for('trunk')]: true }); - export { + export default { Elixir$Animals$Elephant }; """ @@ -119,8 +119,8 @@ defmodule ElixirScript.Translator.Defmodule.Test do end js_code = """ - import * as Elixir$ElixirScript$Kernel from './Elixir.ElixirScript.Kernel'; - import * as Elixir$Animals$Elephant from './Elixir.Animals.Elephant'; + import Elixir$ElixirScript$Kernel from './Elixir.ElixirScript.Kernel'; + import Elixir$Animals$Elephant from './Elixir.Animals.Elephant'; const something_else = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([],function() { return null; })); @@ -128,27 +128,27 @@ defmodule ElixirScript.Translator.Defmodule.Test do return Elixir$Animals$Elephant.Elixir$Animals$Elephant.create(Object.freeze({})); })); - export { + export default { something }; - import * as Elixir$ElixirScript$Kernel from './Elixir.ElixirScript.Kernel'; - import * as Elixir$Animals$Elephant$Bear from './Elixir.Animals.Elephant.Bear'; + import Elixir$ElixirScript$Kernel from './Elixir.ElixirScript.Kernel'; + import Elixir$Animals$Elephant$Bear from './Elixir.Animals.Elephant.Bear'; const Elixir$Animals$Elephant = Elixir.Core.Functions.defstruct({ [Symbol.for('__struct__')]: Symbol.for('Elixir.Animals.Elephant'), [Symbol.for('trunk')]: true }); - export { + export default { Elixir$Animals$Elephant }; - import * as Elixir$ElixirScript$Kernel from './Elixir.ElixirScript.Kernel'; + import Elixir$ElixirScript$Kernel from './Elixir.ElixirScript.Kernel'; const Elixir$Animals$Elephant$Bear = Elixir.Core.Functions.defstruct({ [Symbol.for('__struct__')]: Symbol.for('Elixir.Animals.Elephant.Bear'), [Symbol.for('trunk')]: true }); - export { + export default { Elixir$Animals$Elephant$Bear }; """ @@ -168,14 +168,14 @@ defmodule ElixirScript.Translator.Defmodule.Test do end js_code = """ - import * as Elixir$ElixirScript$Kernel from './Elixir.ElixirScript.Kernel'; - import * as Elixir$Lions$Tigers from './Elixir.Lions.Tigers'; + import Elixir$ElixirScript$Kernel from './Elixir.ElixirScript.Kernel'; + import Elixir$Lions$Tigers from './Elixir.Lions.Tigers'; Elixir.Core.Functions.call_property(Elixir$Lions$Tigers,'oh_my'); - export {}; + export default {}; - import * as Elixir$ElixirScript$Kernel from './Elixir.ElixirScript.Kernel'; + import Elixir$ElixirScript$Kernel from './Elixir.ElixirScript.Kernel'; Elixir.Core.Functions.call_property(Lions.Tigers.Bears,'oh_my'); - export {}; + export default {}; """ assert_translation(ex_ast, js_code) @@ -198,17 +198,17 @@ defmodule ElixirScript.Translator.Defmodule.Test do end js_code = """ - import * as Elixir$ElixirScript$Kernel from './Elixir.ElixirScript.Kernel'; - import * as Elixir$Lions$Tigers from './Elixir.Lions.Tigers'; + import Elixir$ElixirScript$Kernel from './Elixir.ElixirScript.Kernel'; + import Elixir$Lions$Tigers from './Elixir.Lions.Tigers'; Elixir.Core.Functions.call_property(Elixir$Lions$Tigers,'oh_my'); - export {}; + export default {}; - import * as Elixir$ElixirScript$Kernel from './Elixir.ElixirScript.Kernel'; + import Elixir$ElixirScript$Kernel from './Elixir.ElixirScript.Kernel'; const oh_my = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([],function() { return null; })); Elixir.Core.Functions.call_property(Lions.Tigers.Bears,'oh_my'); - export { + export default { oh_my }; """ @@ -234,12 +234,12 @@ defmodule ElixirScript.Translator.Defmodule.Test do end js_code = """ - import * as Elixir$ElixirScript$Kernel from './Elixir.ElixirScript.Kernel'; - import * as Elixir$Lions$Tigers from './Elixir.Lions.Tigers'; + import Elixir$ElixirScript$Kernel from './Elixir.ElixirScript.Kernel'; + import Elixir$Lions$Tigers from './Elixir.Lions.Tigers'; Elixir$Lions$Tigers.oh_my(); - export {}; + export default {}; - import * as Elixir$ElixirScript$Kernel from './Elixir.ElixirScript.Kernel'; + import Elixir$ElixirScript$Kernel from './Elixir.ElixirScript.Kernel'; const oh_my2 = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([],function() { return null; })); @@ -248,7 +248,7 @@ defmodule ElixirScript.Translator.Defmodule.Test do return null; })); - export { + export default { oh_my2, oh_my }; """ @@ -274,12 +274,12 @@ defmodule ElixirScript.Translator.Defmodule.Test do end js_code = """ - import * as Elixir$ElixirScript$Kernel from './Elixir.ElixirScript.Kernel'; - import * as Elixir$Lions$Tigers from './Elixir.Lions.Tigers'; + import Elixir$ElixirScript$Kernel from './Elixir.ElixirScript.Kernel'; + import Elixir$Lions$Tigers from './Elixir.Lions.Tigers'; Elixir$Lions$Tigers.oh_my2(); - export {}; + export default {}; - import * as Elixir$ElixirScript$Kernel from './Elixir.ElixirScript.Kernel'; + import Elixir$ElixirScript$Kernel from './Elixir.ElixirScript.Kernel'; const oh_my2 = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([],function() { return null; })); @@ -288,7 +288,7 @@ defmodule ElixirScript.Translator.Defmodule.Test do return null; })); - export { + export default { oh_my2, oh_my }; diff --git a/test/translator/function_test.exs b/test/translator/function_test.exs index 56fcdee7..e0b8f1e4 100644 --- a/test/translator/function_test.exs +++ b/test/translator/function_test.exs @@ -239,7 +239,7 @@ defmodule ElixirScript.Translator.Function.Test do end js_code = """ - import * as Elixir$ElixirScript$Kernel from './Elixir.ElixirScript.Kernel'; + import Elixir$ElixirScript$Kernel from './Elixir.ElixirScript.Kernel'; const example = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([],function() { return null; }),Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable()],function(oneArg) { @@ -251,7 +251,7 @@ defmodule ElixirScript.Translator.Function.Test do }),Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable(), Elixir.Core.Patterns.variable(), Elixir.Core.Patterns.variable(), Elixir.Core.Patterns.variable()],function(oneArg,twoArg,redArg,blueArg) { return null; })); - export {}; + export default {}; """ assert_translation(ex_ast, js_code) @@ -276,7 +276,7 @@ defmodule ElixirScript.Translator.Function.Test do end js_code = """ - import * as Elixir$ElixirScript$Kernel from './Elixir.ElixirScript.Kernel'; + import Elixir$ElixirScript$Kernel from './Elixir.ElixirScript.Kernel'; const example = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([],function() { return null; }),Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable()],function(oneArg) { @@ -288,7 +288,7 @@ defmodule ElixirScript.Translator.Function.Test do }),Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable(), Elixir.Core.Patterns.variable(), Elixir.Core.Patterns.variable(), Elixir.Core.Patterns.variable()],function(oneArg,twoArg,redArg,blueArg) { return null; })); - export { + export default { example }; """ @@ -303,11 +303,11 @@ defmodule ElixirScript.Translator.Function.Test do end js_code = """ - import * as Elixir$ElixirScript$Kernel from './Elixir.ElixirScript.Kernel'; + import Elixir$ElixirScript$Kernel from './Elixir.ElixirScript.Kernel'; const example = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable()],function(oneArg) { return null; })); - export { + export default { example }; """ @@ -421,7 +421,7 @@ defmodule ElixirScript.Translator.Function.Test do end js_code = """ - import * as Elixir$ElixirScript$Kernel from './Elixir.ElixirScript.Kernel'; + import Elixir$ElixirScript$Kernel from './Elixir.ElixirScript.Kernel'; const something = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable()],function(one) { return null; },function(one) { @@ -431,7 +431,7 @@ defmodule ElixirScript.Translator.Function.Test do },function(one) { return Elixir$ElixirScript$Kernel.is_number(one) || Elixir$ElixirScript$Kernel.is_atom(one); })); - export { + export default { something }; """ @@ -652,7 +652,7 @@ defmodule ElixirScript.Translator.Function.Test do js_code = """ - import * as Elixir$ElixirScript$Kernel from './Elixir.ElixirScript.Kernel'; + import Elixir$ElixirScript$Kernel from './Elixir.ElixirScript.Kernel'; const something = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([1],function() { return null; }),Elixir.Core.Patterns.make_case([2],function() { @@ -664,7 +664,7 @@ defmodule ElixirScript.Translator.Function.Test do }),Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable()],function(one) { return null; })); - export { + export default { something }; """ diff --git a/test/translator/protocol_test.exs b/test/translator/protocol_test.exs index 1f2df19a..8d13db99 100644 --- a/test/translator/protocol_test.exs +++ b/test/translator/protocol_test.exs @@ -25,7 +25,7 @@ defmodule ElixirScript.Translator.Protocol.Test do end js_code = """ - import * as Elixir$ElixirScript$Kernel from './Elixir.ElixirScript.Kernel'; + import Elixir$ElixirScript$Kernel from './Elixir.ElixirScript.Kernel'; const Elixir$Blank = Elixir.Core.Functions.defprotocol({ blank__qmark__: Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable()],function(data) { return null; diff --git a/test/translator/struct_test.exs b/test/translator/struct_test.exs index 5a798af3..3b92b57c 100644 --- a/test/translator/struct_test.exs +++ b/test/translator/struct_test.exs @@ -10,14 +10,14 @@ defmodule ElixirScript.Translator.Struct.Test do end js_code = """ - import * as Elixir$ElixirScript$Kernel from './Elixir.ElixirScript.Kernel'; + import Elixir$ElixirScript$Kernel from './Elixir.ElixirScript.Kernel'; const Elixir$User = Elixir.Core.Functions.defstruct({ [Symbol.for('__struct__')]: Symbol.for('Elixir.User'), [Symbol.for('name')]: 'john', [Symbol.for('age')]: 27 }); - export { + export default { Elixir$User }; """ @@ -34,13 +34,13 @@ defmodule ElixirScript.Translator.Struct.Test do end js_code = """ - import * as Elixir$ElixirScript$Kernel from './Elixir.ElixirScript.Kernel'; + import Elixir$ElixirScript$Kernel from './Elixir.ElixirScript.Kernel'; const Elixir$User = Elixir.Core.Functions.defstruct({ [Symbol.for('__struct__')]: Symbol.for('Elixir.User'), [Symbol.for('name')]: null, [Symbol.for('age')]: null }); - export { + export default { Elixir$User }; """ @@ -61,14 +61,14 @@ defmodule ElixirScript.Translator.Struct.Test do js_code = """ let [user] = Elixir.Core.Patterns.match(Elixir.Core.Patterns.variable(), Elixir$User.Elixir$User.create(Object.freeze({}))); - import * as Elixir$ElixirScript$Kernel from './Elixir.ElixirScript.Kernel'; + import Elixir$ElixirScript$Kernel from './Elixir.ElixirScript.Kernel'; const Elixir$User = Elixir.Core.Functions.defstruct({ [Symbol.for('__struct__')]: Symbol.for('Elixir.User'), [Symbol.for('name')]: null, [Symbol.for('age')]: null }); - export { + export default { Elixir$User }; """ @@ -88,13 +88,13 @@ defmodule ElixirScript.Translator.Struct.Test do [Symbol.for('name')]: 'John' }))); - import * as Elixir$ElixirScript$Kernel from './Elixir.ElixirScript.Kernel'; + import Elixir$ElixirScript$Kernel from './Elixir.ElixirScript.Kernel'; const Elixir$User = Elixir.Core.Functions.defstruct({ [Symbol.for('__struct__')]: Symbol.for('Elixir.User'), [Symbol.for('name')]: null, [Symbol.for('age')]: null }); - export { + export default { Elixir$User }; """ @@ -137,13 +137,13 @@ defmodule ElixirScript.Translator.Struct.Test do end js_code = """ - import * as Elixir$ElixirScript$Kernel from './Elixir.ElixirScript.Kernel'; + import Elixir$ElixirScript$Kernel from './Elixir.ElixirScript.Kernel'; const Elixir$MyAppError = Elixir.Core.Functions.defexception({ [Symbol.for('__struct__')]: Symbol.for('Elixir.MyAppError'), [Symbol.for('__exception__')]: true, [Symbol.for('message')]: 'This is a message' }); - export { + export default { Elixir$MyAppError }; """ @@ -157,14 +157,14 @@ defmodule ElixirScript.Translator.Struct.Test do end js_code = """ - import * as Elixir$ElixirScript$Kernel from './Elixir.ElixirScript.Kernel'; + import Elixir$ElixirScript$Kernel from './Elixir.ElixirScript.Kernel'; const Elixir$MyAppError = Elixir.Core.Functions.defexception({ [Symbol.for('__struct__')]: Symbol.for('Elixir.MyAppError'), [Symbol.for('__exception__')]: true, [Symbol.for('message')]: null }); - export { + export default { Elixir$MyAppError }; """ @@ -187,14 +187,14 @@ defmodule ElixirScript.Translator.Struct.Test do [Symbol.for('message')]: 'did not get what was expected' })); -import * as Elixir$ElixirScript$Kernel from './Elixir.ElixirScript.Kernel'; +import Elixir$ElixirScript$Kernel from './Elixir.ElixirScript.Kernel'; const Elixir$MyAppError = Elixir.Core.Functions.defexception({ [Symbol.for('__struct__')]: Symbol.for('Elixir.MyAppError'), [Symbol.for('__exception__')]: true, [Symbol.for('message')]: null }); - export { + export default { Elixir$MyAppError }; """ From f2c3481eee7204833fc9c70ba8a9f44bfe4eb792 Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Fri, 15 Jan 2016 18:32:56 -0600 Subject: [PATCH 123/860] Updated CHANGELOG --- CHANGELOG.md | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 4e0d45de..0b66ef1d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,7 +6,11 @@ * Began writing some of the standard libraries in Elixir instead of JavaScript * Added `JS.import/1` * Added support for multi alias/require/imports statements - * exports are now default exports + * Exports are now default exports + * When output is sent to standard out, there are now markers to specify where + each module begins as well as what the file name would be. + For the end of a file, `//:ENDFILE` is used. For the file name, `//:ENDFILENAME` + is used where `` is the name of the file * Breaking * `compile`, `compile_path`, and `compile_quoted` opts parameter now expects a map From 7b2fbfebf331f9aa461ac69c7d5055150e2afd04 Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Sun, 17 Jan 2016 11:33:20 -0600 Subject: [PATCH 124/860] Updated rollup. Removed unused devDependencies in package.json --- gulpfile.js | 2 -- package.json | 4 +--- 2 files changed, 1 insertion(+), 5 deletions(-) diff --git a/gulpfile.js b/gulpfile.js index b202f56d..4ad53938 100644 --- a/gulpfile.js +++ b/gulpfile.js @@ -1,9 +1,7 @@ var gulp = require('gulp'); var mocha = require('gulp-mocha'); -var concat = require('gulp-concat'); var babel = require('gulp-babel'); var eslint = require('gulp-eslint'); -var rollup = require('gulp-rollup'); var sourcemaps = require('gulp-sourcemaps'); require("babel/polyfill"); diff --git a/package.json b/package.json index 14a90415..92a5ece4 100644 --- a/package.json +++ b/package.json @@ -23,12 +23,10 @@ "chai": "^2.2.0", "gulp": "^3.8.11", "gulp-babel": "^5.1.0", - "gulp-concat": "^2.5.2", "gulp-eslint": "^0.13.2", "gulp-mocha": "^2.1.3", - "gulp-rollup": "^1.0.1", "gulp-sourcemaps": "^1.5.2", "mocha": "^2.3.3", - "rollup": "^0.21.1" + "rollup": "^0.24.1" } } From c908484ae4bf2515373020a224d422a96bb3ce09 Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Tue, 19 Jan 2016 18:35:21 -0600 Subject: [PATCH 125/860] Updated protocol output. Add protocol import to core.functions --- lib/elixir_script.ex | 47 ++++++++++----- lib/elixir_script/prelude/module.ex | 2 +- .../translator/module_collector.ex | 20 +++++-- lib/elixir_script/translator/protocol.ex | 37 ++++-------- lib/elixir_script/translator/state.ex | 17 ++++-- priv/Elixir.js | 59 +++++++++++++++++-- src/javascript/lib/core/functions.js | 1 + test/translator/protocol_test.exs | 4 +- 8 files changed, 126 insertions(+), 61 deletions(-) diff --git a/lib/elixir_script.ex b/lib/elixir_script.ex index fb06d2d4..73a14e8c 100644 --- a/lib/elixir_script.ex +++ b/lib/elixir_script.ex @@ -72,7 +72,11 @@ defmodule ElixirScript do ModuleCollector.process_modules(libs ++ [updated_quoted(quoted)]) - create_code(compiler_opts) + code = create_code(compiler_opts) + + ElixirScript.Translator.State.stop + + code end @doc """ @@ -94,7 +98,11 @@ defmodule ElixirScript do ModuleCollector.process_modules(libs ++ code) - create_code(compiler_opts) + code = create_code(compiler_opts) + + ElixirScript.Translator.State.stop + + code end defp build_compiler_options(opts) do @@ -135,10 +143,11 @@ defmodule ElixirScript do defp create_code(compiler_opts) do + parent = self + state = ElixirScript.Translator.State.get - standard_lib_modules = state.std_lib_map - |> Map.values + standard_lib_modules = Map.values(state.std_lib_map) result = Map.values(state.modules) @@ -146,27 +155,35 @@ defmodule ElixirScript do compiler_opts.import_standard_libs == false && ast.name in standard_lib_modules end) |> Enum.map(fn ast -> + spawn_link fn -> env = ElixirScript.Translator.Env.module_env(ast.name, Utils.name_to_js_file_name(ast.name) <> ".js") - case ast.type do + module = case ast.type do :module -> ElixirScript.Translator.Module.make_module(ast.name, ast.body, env) :protocol -> ElixirScript.Translator.Protocol.consolidate(ast, env) end - |> convert_to_code() - end) - ElixirScript.Translator.State.stop + { path, code } = convert_to_code(module) + + result = case compiler_opts.include_path do + true -> + { path, code } + false -> + code + end + + send parent, { self, result } + end + end) + |> Enum.map(fn pid -> + receive do + {^pid, result} -> result + end + end) result - |> Enum.map(fn({path, code}) -> - if(compiler_opts.include_path) do - { path, code } - else - code - end - end) end @doc """ diff --git a/lib/elixir_script/prelude/module.ex b/lib/elixir_script/prelude/module.ex index dc32959a..b35564df 100644 --- a/lib/elixir_script/prelude/module.ex +++ b/lib/elixir_script/prelude/module.ex @@ -5,6 +5,6 @@ defmodule ElixirScript.Module do functions: Keyword.new, private_functions: Keyword.new, macros: Keyword.new, private_macros: Keyword.new, body: nil, js_imports: [], module_refs: [], type: :module, - spec: nil, impls: HashDict.new + impls: HashDict.new end diff --git a/lib/elixir_script/translator/module_collector.ex b/lib/elixir_script/translator/module_collector.ex index 912f09e7..93aded66 100644 --- a/lib/elixir_script/translator/module_collector.ex +++ b/lib/elixir_script/translator/module_collector.ex @@ -35,12 +35,14 @@ defmodule ElixirScript.Translator.ModuleCollector do end) end - def do_process_modules({:defprotocol, _, [{:__aliases__, _, _} = the_alias, [do: {:__block__, context, spec}]]}) do - ElixirScript.Translator.State.add_protocol(Utils.quoted_to_name(the_alias), {:__block__, context, spec}) + def do_process_modules({:defprotocol, _, [{:__aliases__, _, _} = the_alias, [do: {:__block__, _, _} = block]]}) do + %{def: functions, defp: _, defmacro: _, defmacrop: _ } = get_functions_from_module(block) + ElixirScript.Translator.State.add_protocol(Utils.quoted_to_name(the_alias), functions) end def do_process_modules({:defprotocol, _, [{:__aliases__, _, _} = the_alias, [do: spec]]}) do - ElixirScript.Translator.State.add_protocol(Utils.quoted_to_name(the_alias), {:__block__, [], [spec]}) + %{def: functions, defp: _, defmacro: _, defmacrop: _ } = get_functions_from_module({:__block__, [], [spec]}) + ElixirScript.Translator.State.add_protocol(Utils.quoted_to_name(the_alias), functions) end def do_process_modules({:defimpl, _, [ {:__aliases__, _, _} = the_alias, [for: type], [do: {:__block__, context, spec}] ]}) do @@ -175,8 +177,16 @@ defmodule ElixirScript.Translator.ModuleCollector do add_function_to_map(state, type, name, arity) - _, state -> - state + ({type, _, [{name, _, params}]}, state) when is_atom(params) and type in [:def, :defp] -> + arity = 0 + add_function_to_map(state, type, name, arity) + + ({type, _, [{name, _, params}]}, state) when type in [:def, :defp] -> + arity = length(params) + add_function_to_map(state, type, name, arity) + + _, state -> + state end) end diff --git a/lib/elixir_script/translator/protocol.ex b/lib/elixir_script/translator/protocol.ex index 4262f63e..5dfefe20 100644 --- a/lib/elixir_script/translator/protocol.ex +++ b/lib/elixir_script/translator/protocol.ex @@ -12,10 +12,10 @@ defmodule ElixirScript.Translator.Protocol do """ def consolidate(protocol, env) do name = protocol.name - spec = protocol.spec + functions = protocol.functions impls = protocol.impls |> Dict.to_list - {spec_imports, spec_body, spec} = define_spec(name, spec, env) + {spec_imports, spec_body, spec} = define_spec(name, functions, env) {impl_imports, impl_body, impls} = define_impls(name, impls, env) body = spec_body ++ impl_body @@ -24,18 +24,15 @@ defmodule ElixirScript.Translator.Protocol do create_module(name, spec, impls, imports, body, env) end - defp define_spec(name, spec, env) do - { body, functions } = extract_function_from_spec(spec) - { body, env } = Module.translate_body(body, env) - { exported_functions, _ } = process_functions(functions, env) - + defp define_spec(name, functions, env) do + { body, _ } = Module.translate_body( {:__block__, [], [] }, env) module_refs = ElixirScript.Translator.State.get_module_references(name) - {imports, body} = Module.extract_imports_from_body(body) - imports = imports ++ Module.make_std_lib_import() ++ Module.make_imports(module_refs) - object = Enum.map(exported_functions, fn({key, value}) -> + + object = process_spec_functions(functions) + |> Enum.map(fn({key, value}) -> Map.make_property(JS.identifier(Utils.filter_name(key)), value) end) |> JS.object_expression @@ -118,22 +115,10 @@ defmodule ElixirScript.Translator.Protocol do } end - defp extract_function_from_spec({:__block__, meta, body_list}) do - { body_list, functions } = Enum.map_reduce(body_list, - %{exported: HashDict.new(), private: HashDict.new()}, fn - ({:def, _, [{name, _, _}]} = function, state) -> - { - nil, - %{ state | exported: HashDict.put(state.exported, name, HashDict.get(state.exported, name, []) ++ [function]) } - } - (x, state) -> - { x, state } - end) - - body_list = Enum.filter(body_list, fn(x) -> !is_nil(x) end) - body = {:__block__, meta, body_list} - - { body, functions } + defp process_spec_functions(functions) do + Enum.map(Keyword.keys(functions), fn(function_name) -> + {function_name, JS.function_expression([], [], JS.block_statement([]))} + end) end defp process_functions(%{ exported: exported, private: private }, env) do diff --git a/lib/elixir_script/translator/state.ex b/lib/elixir_script/translator/state.ex index 0daf0d29..33f79959 100644 --- a/lib/elixir_script/translator/state.ex +++ b/lib/elixir_script/translator/state.ex @@ -46,14 +46,14 @@ defmodule ElixirScript.Translator.State do end) end - def add_protocol(name, spec) do + def add_protocol(name, functions) do Agent.update(__MODULE__, fn state -> proto = do_get_module(state, name) if proto == nil do - proto = %ElixirScript.Module{ name: name, spec: spec, impls: HashDict.new, type: :protocol } + proto = %ElixirScript.Module{ name: name, functions: functions, impls: HashDict.new, type: :protocol } else - proto = %{proto | spec: spec, type: :protocol } + proto = %{proto | functions: functions, type: :protocol } end %{ state | modules: Map.put(state.modules, name, proto) } @@ -71,7 +71,7 @@ defmodule ElixirScript.Translator.State do proto = do_get_module(state, protocol) if proto == nil do - proto = %ElixirScript.Module{ name: protocol, spec: nil, impls: HashDict.new, type: :protocol } + proto = %ElixirScript.Module{ name: protocol, impls: HashDict.new, type: :protocol } end proto = %{ proto | impls: Dict.put(proto.impls, type, impl), type: :protocol } @@ -85,7 +85,12 @@ defmodule ElixirScript.Translator.State do end def get_module_name(module_name) do - case Map.get(build_standard_lib_map, module_name) do + get_module_name(module_name, get) + end + + def get_module_name(module_name, state) do + std_lib_map = state.std_lib_map + case Map.get(std_lib_map, module_name) do nil -> module_name actual_module_name -> @@ -109,7 +114,7 @@ defmodule ElixirScript.Translator.State do end defp do_get_module(state, name) do - Map.get(state.modules, get_module_name(name)) + Map.get(state.modules, get_module_name(name, state)) end def add_module_reference(module_name, module_ref) do diff --git a/priv/Elixir.js b/priv/Elixir.js index 02168c36..3f4aa734 100644 --- a/priv/Elixir.js +++ b/priv/Elixir.js @@ -2616,6 +2616,55 @@ var Patterns = { capture, headTail, type, bound, Case, make_case }; +//https://github.com/airportyh/protomorphism +class Protocol { + constructor(spec) { + this.registry = new Map(); + this.fallback = null; + + for (let funName in spec) { + this[funName] = createFun(funName).bind(this); + } + + function createFun(funName) { + + return function (...args) { + let thing = args[0]; + let fun = null; + + if (Number.isInteger(thing) && this.hasImplementation(Integer)) { + fun = this.registry.get(Core.Integer)[funName]; + } else if (typeof thing === "number" && !Number.isInteger(thing) && this.hasImplementation(Float)) { + fun = this.registry.get(Core.Float)[funName]; + } else if (this.hasImplementation(thing)) { + fun = this.registry.get(thing.constructor)[funName]; + } else if (this.fallback) { + fun = this.fallback[funName]; + } + + if (fun != null) { + let retval = fun.apply(this, args); + return retval; + } + + throw new Error("No implementation found for " + thing); + }; + } + } + + implementation(type, implementation) { + if (type === null) { + this.fallback = implementation; + } else { + this.registry.set(type, implementation); + } + } + + hasImplementation(thing) { + return this.registry.has(thing.constructor); + } +} + function call_property(item, property) { let prop = null; @@ -2939,7 +2988,7 @@ var SpecialForms$1 = { Functions.get_global().processes = Functions.get_global().processes || new ProcessSystem(); -var Core = { +var Core$1 = { ProcessSystem, Tuple, PID, @@ -3024,7 +3073,7 @@ let Enum = { fetch: function (collection, n) { if (Array.isArray(collection)) { if (n < this.count(collection) && n >= 0) { - return new Core.Tuple(Symbol.for("ok"), collection[n]); + return new Core$1.Tuple(Symbol.for("ok"), collection[n]); } else { return Symbol.for("error"); } @@ -3096,7 +3145,7 @@ let Enum = { mapped = Object.freeze(mapped.concat([tuple.get(0)])); } - return new Core.Tuple(mapped, the_acc); + return new Core$1.Tuple(mapped, the_acc); }, member__qmark__: function (collection, value) { @@ -3152,10 +3201,10 @@ let Enum = { }; var Elixir = { - Core, + Core: Core$1, Enum, VirtualDOM }; export default Elixir; -//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiIiwic291cmNlcyI6WyJFbGl4aXIuanMiXSwic291cmNlc0NvbnRlbnQiOlsibGV0IFZpcnR1YWxET00gPSAoZnVuY3Rpb24gKGUpIHtcbiAgICByZXR1cm4gZSgpO1xufSkoZnVuY3Rpb24gKCkge1xuICAgIHZhciBkZWZpbmUsIG1vZHVsZSwgZXhwb3J0cztcbiAgICByZXR1cm4gKGZ1bmN0aW9uIGUodCwgbiwgcikge1xuICAgICAgICBmdW5jdGlvbiBzKG8sIHUpIHtcbiAgICAgICAgICAgIGlmICghbltvXSkge1xuICAgICAgICAgICAgICAgIGlmICghdFtvXSkge1xuICAgICAgICAgICAgICAgICAgICB2YXIgYSA9IHR5cGVvZiByZXF1aXJlID09IFwiZnVuY3Rpb25cIiAmJiByZXF1aXJlO1xuICAgICAgICAgICAgICAgICAgICBpZiAoIXUgJiYgYSkgcmV0dXJuIGEobywgITApO1xuICAgICAgICAgICAgICAgICAgICBpZiAoaSkgcmV0dXJuIGkobywgITApO1xuICAgICAgICAgICAgICAgICAgICB2YXIgZiA9IG5ldyBFcnJvcihcIkNhbm5vdCBmaW5kIG1vZHVsZSAnXCIgKyBvICsgXCInXCIpO1xuICAgICAgICAgICAgICAgICAgICB0aHJvdyAoZi5jb2RlID0gXCJNT0RVTEVfTk9UX0ZPVU5EXCIsIGYpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB2YXIgbCA9IG5bb10gPSB7XG4gICAgICAgICAgICAgICAgICAgIGV4cG9ydHM6IHt9XG4gICAgICAgICAgICAgICAgfTtcbiAgICAgICAgICAgICAgICB0W29dWzBdLmNhbGwobC5leHBvcnRzLCBmdW5jdGlvbiAoZSkge1xuICAgICAgICAgICAgICAgICAgICB2YXIgbiA9IHRbb11bMV1bZV07XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBzKG4gPyBuIDogZSk7XG4gICAgICAgICAgICAgICAgfSwgbCwgbC5leHBvcnRzLCBlLCB0LCBuLCByKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJldHVybiBuW29dLmV4cG9ydHM7XG4gICAgICAgIH1cbiAgICAgICAgdmFyIGkgPSB0eXBlb2YgcmVxdWlyZSA9PSBcImZ1bmN0aW9uXCIgJiYgcmVxdWlyZTtcbiAgICAgICAgZm9yICh2YXIgbyA9IDA7IG8gPCByLmxlbmd0aDsgbysrKSBzKHJbb10pO1xuICAgICAgICByZXR1cm4gcztcbiAgICB9KSh7XG4gICAgICAgIDE6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG5cbiAgICAgICAgICAgIHZhciBjcmVhdGVFbGVtZW50ID0gcmVxdWlyZShcIi4vdmRvbS9jcmVhdGUtZWxlbWVudC5qc1wiKTtcblxuICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBjcmVhdGVFbGVtZW50O1xuICAgICAgICB9LCB7IFwiLi92ZG9tL2NyZWF0ZS1lbGVtZW50LmpzXCI6IDE1IH1dLCAyOiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge1xuICAgICAgICAgICAgdmFyIGRpZmYgPSByZXF1aXJlKFwiLi92dHJlZS9kaWZmLmpzXCIpO1xuXG4gICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IGRpZmY7XG4gICAgICAgIH0sIHsgXCIuL3Z0cmVlL2RpZmYuanNcIjogMzUgfV0sIDM6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICB2YXIgaCA9IHJlcXVpcmUoXCIuL3ZpcnR1YWwtaHlwZXJzY3JpcHQvaW5kZXguanNcIik7XG5cbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gaDtcbiAgICAgICAgfSwgeyBcIi4vdmlydHVhbC1oeXBlcnNjcmlwdC9pbmRleC5qc1wiOiAyMiB9XSwgNDogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHtcbiAgICAgICAgICAgIHZhciBkaWZmID0gcmVxdWlyZShcIi4vZGlmZi5qc1wiKTtcbiAgICAgICAgICAgIHZhciBwYXRjaCA9IHJlcXVpcmUoXCIuL3BhdGNoLmpzXCIpO1xuICAgICAgICAgICAgdmFyIGggPSByZXF1aXJlKFwiLi9oLmpzXCIpO1xuICAgICAgICAgICAgdmFyIGNyZWF0ZSA9IHJlcXVpcmUoXCIuL2NyZWF0ZS1lbGVtZW50LmpzXCIpO1xuICAgICAgICAgICAgdmFyIFZOb2RlID0gcmVxdWlyZShcIi4vdm5vZGUvdm5vZGUuanNcIik7XG4gICAgICAgICAgICB2YXIgVlRleHQgPSByZXF1aXJlKFwiLi92bm9kZS92dGV4dC5qc1wiKTtcblxuICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSB7XG4gICAgICAgICAgICAgICAgZGlmZjogZGlmZixcbiAgICAgICAgICAgICAgICBwYXRjaDogcGF0Y2gsXG4gICAgICAgICAgICAgICAgaDogaCxcbiAgICAgICAgICAgICAgICBjcmVhdGU6IGNyZWF0ZSxcbiAgICAgICAgICAgICAgICBWTm9kZTogVk5vZGUsXG4gICAgICAgICAgICAgICAgVlRleHQ6IFZUZXh0XG4gICAgICAgICAgICB9O1xuICAgICAgICB9LCB7IFwiLi9jcmVhdGUtZWxlbWVudC5qc1wiOiAxLCBcIi4vZGlmZi5qc1wiOiAyLCBcIi4vaC5qc1wiOiAzLCBcIi4vcGF0Y2guanNcIjogMTMsIFwiLi92bm9kZS92bm9kZS5qc1wiOiAzMSwgXCIuL3Zub2RlL3Z0ZXh0LmpzXCI6IDMzIH1dLCA1OiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge1xuICAgICAgICAgICAgLyohXG4gICAgICAgICAgICAgKiBDcm9zcy1Ccm93c2VyIFNwbGl0IDEuMS4xXG4gICAgICAgICAgICAgKiBDb3B5cmlnaHQgMjAwNy0yMDEyIFN0ZXZlbiBMZXZpdGhhbiA8c3RldmVubGV2aXRoYW4uY29tPlxuICAgICAgICAgICAgICogQXZhaWxhYmxlIHVuZGVyIHRoZSBNSVQgTGljZW5zZVxuICAgICAgICAgICAgICogRUNNQVNjcmlwdCBjb21wbGlhbnQsIHVuaWZvcm0gY3Jvc3MtYnJvd3NlciBzcGxpdCBtZXRob2RcbiAgICAgICAgICAgICAqL1xuXG4gICAgICAgICAgICAvKipcbiAgICAgICAgICAgICAqIFNwbGl0cyBhIHN0cmluZyBpbnRvIGFuIGFycmF5IG9mIHN0cmluZ3MgdXNpbmcgYSByZWdleCBvciBzdHJpbmcgc2VwYXJhdG9yLiBNYXRjaGVzIG9mIHRoZVxuICAgICAgICAgICAgICogc2VwYXJhdG9yIGFyZSBub3QgaW5jbHVkZWQgaW4gdGhlIHJlc3VsdCBhcnJheS4gSG93ZXZlciwgaWYgYHNlcGFyYXRvcmAgaXMgYSByZWdleCB0aGF0IGNvbnRhaW5zXG4gICAgICAgICAgICAgKiBjYXB0dXJpbmcgZ3JvdXBzLCBiYWNrcmVmZXJlbmNlcyBhcmUgc3BsaWNlZCBpbnRvIHRoZSByZXN1bHQgZWFjaCB0aW1lIGBzZXBhcmF0b3JgIGlzIG1hdGNoZWQuXG4gICAgICAgICAgICAgKiBGaXhlcyBicm93c2VyIGJ1Z3MgY29tcGFyZWQgdG8gdGhlIG5hdGl2ZSBgU3RyaW5nLnByb3RvdHlwZS5zcGxpdGAgYW5kIGNhbiBiZSB1c2VkIHJlbGlhYmx5XG4gICAgICAgICAgICAgKiBjcm9zcy1icm93c2VyLlxuICAgICAgICAgICAgICogQHBhcmFtIHtTdHJpbmd9IHN0ciBTdHJpbmcgdG8gc3BsaXQuXG4gICAgICAgICAgICAgKiBAcGFyYW0ge1JlZ0V4cHxTdHJpbmd9IHNlcGFyYXRvciBSZWdleCBvciBzdHJpbmcgdG8gdXNlIGZvciBzZXBhcmF0aW5nIHRoZSBzdHJpbmcuXG4gICAgICAgICAgICAgKiBAcGFyYW0ge051bWJlcn0gW2xpbWl0XSBNYXhpbXVtIG51bWJlciBvZiBpdGVtcyB0byBpbmNsdWRlIGluIHRoZSByZXN1bHQgYXJyYXkuXG4gICAgICAgICAgICAgKiBAcmV0dXJucyB7QXJyYXl9IEFycmF5IG9mIHN1YnN0cmluZ3MuXG4gICAgICAgICAgICAgKiBAZXhhbXBsZVxuICAgICAgICAgICAgICpcbiAgICAgICAgICAgICAqIC8vIEJhc2ljIHVzZVxuICAgICAgICAgICAgICogc3BsaXQoJ2EgYiBjIGQnLCAnICcpO1xuICAgICAgICAgICAgICogLy8gLT4gWydhJywgJ2InLCAnYycsICdkJ11cbiAgICAgICAgICAgICAqXG4gICAgICAgICAgICAgKiAvLyBXaXRoIGxpbWl0XG4gICAgICAgICAgICAgKiBzcGxpdCgnYSBiIGMgZCcsICcgJywgMik7XG4gICAgICAgICAgICAgKiAvLyAtPiBbJ2EnLCAnYiddXG4gICAgICAgICAgICAgKlxuICAgICAgICAgICAgICogLy8gQmFja3JlZmVyZW5jZXMgaW4gcmVzdWx0IGFycmF5XG4gICAgICAgICAgICAgKiBzcGxpdCgnLi53b3JkMSB3b3JkMi4uJywgLyhbYS16XSspKFxcZCspL2kpO1xuICAgICAgICAgICAgICogLy8gLT4gWycuLicsICd3b3JkJywgJzEnLCAnICcsICd3b3JkJywgJzInLCAnLi4nXVxuICAgICAgICAgICAgICovXG4gICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IChmdW5jdGlvbiBzcGxpdCh1bmRlZikge1xuXG4gICAgICAgICAgICAgICAgdmFyIG5hdGl2ZVNwbGl0ID0gU3RyaW5nLnByb3RvdHlwZS5zcGxpdCxcbiAgICAgICAgICAgICAgICAgICAgY29tcGxpYW50RXhlY05wY2cgPSAvKCk/Py8uZXhlYyhcIlwiKVsxXSA9PT0gdW5kZWYsXG5cbiAgICAgICAgICAgICAgICAvLyBOUENHOiBub25wYXJ0aWNpcGF0aW5nIGNhcHR1cmluZyBncm91cFxuICAgICAgICAgICAgICAgIHNlbGY7XG5cbiAgICAgICAgICAgICAgICBzZWxmID0gZnVuY3Rpb24gKHN0ciwgc2VwYXJhdG9yLCBsaW1pdCkge1xuICAgICAgICAgICAgICAgICAgICAvLyBJZiBgc2VwYXJhdG9yYCBpcyBub3QgYSByZWdleCwgdXNlIGBuYXRpdmVTcGxpdGBcbiAgICAgICAgICAgICAgICAgICAgaWYgKE9iamVjdC5wcm90b3R5cGUudG9TdHJpbmcuY2FsbChzZXBhcmF0b3IpICE9PSBcIltvYmplY3QgUmVnRXhwXVwiKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gbmF0aXZlU3BsaXQuY2FsbChzdHIsIHNlcGFyYXRvciwgbGltaXQpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIHZhciBvdXRwdXQgPSBbXSxcbiAgICAgICAgICAgICAgICAgICAgICAgIGZsYWdzID0gKHNlcGFyYXRvci5pZ25vcmVDYXNlID8gXCJpXCIgOiBcIlwiKSArIChzZXBhcmF0b3IubXVsdGlsaW5lID8gXCJtXCIgOiBcIlwiKSArIChzZXBhcmF0b3IuZXh0ZW5kZWQgPyBcInhcIiA6IFwiXCIpICsgKHNlcGFyYXRvci5zdGlja3kgPyBcInlcIiA6IFwiXCIpLFxuXG4gICAgICAgICAgICAgICAgICAgIC8vIEZpcmVmb3ggMytcbiAgICAgICAgICAgICAgICAgICAgbGFzdExhc3RJbmRleCA9IDAsXG5cbiAgICAgICAgICAgICAgICAgICAgLy8gTWFrZSBgZ2xvYmFsYCBhbmQgYXZvaWQgYGxhc3RJbmRleGAgaXNzdWVzIGJ5IHdvcmtpbmcgd2l0aCBhIGNvcHlcbiAgICAgICAgICAgICAgICAgICAgc2VwYXJhdG9yID0gbmV3IFJlZ0V4cChzZXBhcmF0b3Iuc291cmNlLCBmbGFncyArIFwiZ1wiKSxcbiAgICAgICAgICAgICAgICAgICAgICAgIHNlcGFyYXRvcjIsXG4gICAgICAgICAgICAgICAgICAgICAgICBtYXRjaCxcbiAgICAgICAgICAgICAgICAgICAgICAgIGxhc3RJbmRleCxcbiAgICAgICAgICAgICAgICAgICAgICAgIGxhc3RMZW5ndGg7XG4gICAgICAgICAgICAgICAgICAgIHN0ciArPSBcIlwiOyAvLyBUeXBlLWNvbnZlcnRcbiAgICAgICAgICAgICAgICAgICAgaWYgKCFjb21wbGlhbnRFeGVjTnBjZykge1xuICAgICAgICAgICAgICAgICAgICAgICAgLy8gRG9lc24ndCBuZWVkIGZsYWdzIGd5LCBidXQgdGhleSBkb24ndCBodXJ0XG4gICAgICAgICAgICAgICAgICAgICAgICBzZXBhcmF0b3IyID0gbmV3IFJlZ0V4cChcIl5cIiArIHNlcGFyYXRvci5zb3VyY2UgKyBcIiQoPyFcXFxccylcIiwgZmxhZ3MpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIC8qIFZhbHVlcyBmb3IgYGxpbWl0YCwgcGVyIHRoZSBzcGVjOlxuICAgICAgICAgICAgICAgICAgICAgKiBJZiB1bmRlZmluZWQ6IDQyOTQ5NjcyOTUgLy8gTWF0aC5wb3coMiwgMzIpIC0gMVxuICAgICAgICAgICAgICAgICAgICAgKiBJZiAwLCBJbmZpbml0eSwgb3IgTmFOOiAwXG4gICAgICAgICAgICAgICAgICAgICAqIElmIHBvc2l0aXZlIG51bWJlcjogbGltaXQgPSBNYXRoLmZsb29yKGxpbWl0KTsgaWYgKGxpbWl0ID4gNDI5NDk2NzI5NSkgbGltaXQgLT0gNDI5NDk2NzI5NjtcbiAgICAgICAgICAgICAgICAgICAgICogSWYgbmVnYXRpdmUgbnVtYmVyOiA0Mjk0OTY3Mjk2IC0gTWF0aC5mbG9vcihNYXRoLmFicyhsaW1pdCkpXG4gICAgICAgICAgICAgICAgICAgICAqIElmIG90aGVyOiBUeXBlLWNvbnZlcnQsIHRoZW4gdXNlIHRoZSBhYm92ZSBydWxlc1xuICAgICAgICAgICAgICAgICAgICAgKi9cbiAgICAgICAgICAgICAgICAgICAgbGltaXQgPSBsaW1pdCA9PT0gdW5kZWYgPyAtMSA+Pj4gMCA6IC8vIE1hdGgucG93KDIsIDMyKSAtIDFcbiAgICAgICAgICAgICAgICAgICAgbGltaXQgPj4+IDA7IC8vIFRvVWludDMyKGxpbWl0KVxuICAgICAgICAgICAgICAgICAgICB3aGlsZSAobWF0Y2ggPSBzZXBhcmF0b3IuZXhlYyhzdHIpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAvLyBgc2VwYXJhdG9yLmxhc3RJbmRleGAgaXMgbm90IHJlbGlhYmxlIGNyb3NzLWJyb3dzZXJcbiAgICAgICAgICAgICAgICAgICAgICAgIGxhc3RJbmRleCA9IG1hdGNoLmluZGV4ICsgbWF0Y2hbMF0ubGVuZ3RoO1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGxhc3RJbmRleCA+IGxhc3RMYXN0SW5kZXgpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBvdXRwdXQucHVzaChzdHIuc2xpY2UobGFzdExhc3RJbmRleCwgbWF0Y2guaW5kZXgpKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBGaXggYnJvd3NlcnMgd2hvc2UgYGV4ZWNgIG1ldGhvZHMgZG9uJ3QgY29uc2lzdGVudGx5IHJldHVybiBgdW5kZWZpbmVkYCBmb3JcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBub25wYXJ0aWNpcGF0aW5nIGNhcHR1cmluZyBncm91cHNcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoIWNvbXBsaWFudEV4ZWNOcGNnICYmIG1hdGNoLmxlbmd0aCA+IDEpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbWF0Y2hbMF0ucmVwbGFjZShzZXBhcmF0b3IyLCBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBmb3IgKHZhciBpID0gMTsgaSA8IGFyZ3VtZW50cy5sZW5ndGggLSAyOyBpKyspIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoYXJndW1lbnRzW2ldID09PSB1bmRlZikge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBtYXRjaFtpXSA9IHVuZGVmO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChtYXRjaC5sZW5ndGggPiAxICYmIG1hdGNoLmluZGV4IDwgc3RyLmxlbmd0aCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBBcnJheS5wcm90b3R5cGUucHVzaC5hcHBseShvdXRwdXQsIG1hdGNoLnNsaWNlKDEpKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgbGFzdExlbmd0aCA9IG1hdGNoWzBdLmxlbmd0aDtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBsYXN0TGFzdEluZGV4ID0gbGFzdEluZGV4O1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChvdXRwdXQubGVuZ3RoID49IGxpbWl0KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChzZXBhcmF0b3IubGFzdEluZGV4ID09PSBtYXRjaC5pbmRleCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNlcGFyYXRvci5sYXN0SW5kZXgrKzsgLy8gQXZvaWQgYW4gaW5maW5pdGUgbG9vcFxuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIGlmIChsYXN0TGFzdEluZGV4ID09PSBzdHIubGVuZ3RoKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAobGFzdExlbmd0aCB8fCAhc2VwYXJhdG9yLnRlc3QoXCJcIikpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBvdXRwdXQucHVzaChcIlwiKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIG91dHB1dC5wdXNoKHN0ci5zbGljZShsYXN0TGFzdEluZGV4KSk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIG91dHB1dC5sZW5ndGggPiBsaW1pdCA/IG91dHB1dC5zbGljZSgwLCBsaW1pdCkgOiBvdXRwdXQ7XG4gICAgICAgICAgICAgICAgfTtcblxuICAgICAgICAgICAgICAgIHJldHVybiBzZWxmO1xuICAgICAgICAgICAgfSkoKTtcbiAgICAgICAgfSwge31dLCA2OiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge30sIHt9XSwgNzogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHtcbiAgICAgICAgICAgIFwidXNlIHN0cmljdFwiO1xuXG4gICAgICAgICAgICB2YXIgT25lVmVyc2lvbkNvbnN0cmFpbnQgPSByZXF1aXJlKFwiaW5kaXZpZHVhbC9vbmUtdmVyc2lvblwiKTtcblxuICAgICAgICAgICAgdmFyIE1ZX1ZFUlNJT04gPSBcIjdcIjtcbiAgICAgICAgICAgIE9uZVZlcnNpb25Db25zdHJhaW50KFwiZXYtc3RvcmVcIiwgTVlfVkVSU0lPTik7XG5cbiAgICAgICAgICAgIHZhciBoYXNoS2V5ID0gXCJfX0VWX1NUT1JFX0tFWUBcIiArIE1ZX1ZFUlNJT047XG5cbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gRXZTdG9yZTtcblxuICAgICAgICAgICAgZnVuY3Rpb24gRXZTdG9yZShlbGVtKSB7XG4gICAgICAgICAgICAgICAgdmFyIGhhc2ggPSBlbGVtW2hhc2hLZXldO1xuXG4gICAgICAgICAgICAgICAgaWYgKCFoYXNoKSB7XG4gICAgICAgICAgICAgICAgICAgIGhhc2ggPSBlbGVtW2hhc2hLZXldID0ge307XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgcmV0dXJuIGhhc2g7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0sIHsgXCJpbmRpdmlkdWFsL29uZS12ZXJzaW9uXCI6IDkgfV0sIDg6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICAoZnVuY3Rpb24gKGdsb2JhbCkge1xuICAgICAgICAgICAgICAgIFwidXNlIHN0cmljdFwiO1xuXG4gICAgICAgICAgICAgICAgLypnbG9iYWwgd2luZG93LCBnbG9iYWwqL1xuXG4gICAgICAgICAgICAgICAgdmFyIHJvb3QgPSB0eXBlb2Ygd2luZG93ICE9PSBcInVuZGVmaW5lZFwiID8gd2luZG93IDogdHlwZW9mIGdsb2JhbCAhPT0gXCJ1bmRlZmluZWRcIiA/IGdsb2JhbCA6IHt9O1xuXG4gICAgICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBJbmRpdmlkdWFsO1xuXG4gICAgICAgICAgICAgICAgZnVuY3Rpb24gSW5kaXZpZHVhbChrZXksIHZhbHVlKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmIChrZXkgaW4gcm9vdCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHJvb3Rba2V5XTtcbiAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgIHJvb3Rba2V5XSA9IHZhbHVlO1xuXG4gICAgICAgICAgICAgICAgICAgIHJldHVybiB2YWx1ZTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9KS5jYWxsKHRoaXMsIHR5cGVvZiBnbG9iYWwgIT09IFwidW5kZWZpbmVkXCIgPyBnbG9iYWwgOiB0eXBlb2Ygc2VsZiAhPT0gXCJ1bmRlZmluZWRcIiA/IHNlbGYgOiB0eXBlb2Ygd2luZG93ICE9PSBcInVuZGVmaW5lZFwiID8gd2luZG93IDoge30pO1xuICAgICAgICB9LCB7fV0sIDk6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICBcInVzZSBzdHJpY3RcIjtcblxuICAgICAgICAgICAgdmFyIEluZGl2aWR1YWwgPSByZXF1aXJlKFwiLi9pbmRleC5qc1wiKTtcblxuICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBPbmVWZXJzaW9uO1xuXG4gICAgICAgICAgICBmdW5jdGlvbiBPbmVWZXJzaW9uKG1vZHVsZU5hbWUsIHZlcnNpb24sIGRlZmF1bHRWYWx1ZSkge1xuICAgICAgICAgICAgICAgIHZhciBrZXkgPSBcIl9fSU5ESVZJRFVBTF9PTkVfVkVSU0lPTl9cIiArIG1vZHVsZU5hbWU7XG4gICAgICAgICAgICAgICAgdmFyIGVuZm9yY2VLZXkgPSBrZXkgKyBcIl9FTkZPUkNFX1NJTkdMRVRPTlwiO1xuXG4gICAgICAgICAgICAgICAgdmFyIHZlcnNpb25WYWx1ZSA9IEluZGl2aWR1YWwoZW5mb3JjZUtleSwgdmVyc2lvbik7XG5cbiAgICAgICAgICAgICAgICBpZiAodmVyc2lvblZhbHVlICE9PSB2ZXJzaW9uKSB7XG4gICAgICAgICAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcihcIkNhbiBvbmx5IGhhdmUgb25lIGNvcHkgb2YgXCIgKyBtb2R1bGVOYW1lICsgXCIuXFxuXCIgKyBcIllvdSBhbHJlYWR5IGhhdmUgdmVyc2lvbiBcIiArIHZlcnNpb25WYWx1ZSArIFwiIGluc3RhbGxlZC5cXG5cIiArIFwiVGhpcyBtZWFucyB5b3UgY2Fubm90IGluc3RhbGwgdmVyc2lvbiBcIiArIHZlcnNpb24pO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHJldHVybiBJbmRpdmlkdWFsKGtleSwgZGVmYXVsdFZhbHVlKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSwgeyBcIi4vaW5kZXguanNcIjogOCB9XSwgMTA6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICAoZnVuY3Rpb24gKGdsb2JhbCkge1xuICAgICAgICAgICAgICAgIHZhciB0b3BMZXZlbCA9IHR5cGVvZiBnbG9iYWwgIT09IFwidW5kZWZpbmVkXCIgPyBnbG9iYWwgOiB0eXBlb2Ygd2luZG93ICE9PSBcInVuZGVmaW5lZFwiID8gd2luZG93IDoge307XG4gICAgICAgICAgICAgICAgdmFyIG1pbkRvYyA9IHJlcXVpcmUoXCJtaW4tZG9jdW1lbnRcIik7XG5cbiAgICAgICAgICAgICAgICBpZiAodHlwZW9mIGRvY3VtZW50ICE9PSBcInVuZGVmaW5lZFwiKSB7XG4gICAgICAgICAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gZG9jdW1lbnQ7XG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgdmFyIGRvY2N5ID0gdG9wTGV2ZWxbXCJfX0dMT0JBTF9ET0NVTUVOVF9DQUNIRUA0XCJdO1xuXG4gICAgICAgICAgICAgICAgICAgIGlmICghZG9jY3kpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGRvY2N5ID0gdG9wTGV2ZWxbXCJfX0dMT0JBTF9ET0NVTUVOVF9DQUNIRUA0XCJdID0gbWluRG9jO1xuICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBkb2NjeTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9KS5jYWxsKHRoaXMsIHR5cGVvZiBnbG9iYWwgIT09IFwidW5kZWZpbmVkXCIgPyBnbG9iYWwgOiB0eXBlb2Ygc2VsZiAhPT0gXCJ1bmRlZmluZWRcIiA/IHNlbGYgOiB0eXBlb2Ygd2luZG93ICE9PSBcInVuZGVmaW5lZFwiID8gd2luZG93IDoge30pO1xuICAgICAgICB9LCB7IFwibWluLWRvY3VtZW50XCI6IDYgfV0sIDExOiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge1xuICAgICAgICAgICAgXCJ1c2Ugc3RyaWN0XCI7XG5cbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gaXNPYmplY3QoeCkge1xuICAgICAgICAgICAgICAgIHJldHVybiB0eXBlb2YgeCA9PT0gXCJvYmplY3RcIiAmJiB4ICE9PSBudWxsO1xuICAgICAgICAgICAgfTtcbiAgICAgICAgfSwge31dLCAxMjogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHtcbiAgICAgICAgICAgIHZhciBuYXRpdmVJc0FycmF5ID0gQXJyYXkuaXNBcnJheTtcbiAgICAgICAgICAgIHZhciB0b1N0cmluZyA9IE9iamVjdC5wcm90b3R5cGUudG9TdHJpbmc7XG5cbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gbmF0aXZlSXNBcnJheSB8fCBpc0FycmF5O1xuXG4gICAgICAgICAgICBmdW5jdGlvbiBpc0FycmF5KG9iaikge1xuICAgICAgICAgICAgICAgIHJldHVybiB0b1N0cmluZy5jYWxsKG9iaikgPT09IFwiW29iamVjdCBBcnJheV1cIjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSwge31dLCAxMzogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHtcbiAgICAgICAgICAgIHZhciBwYXRjaCA9IHJlcXVpcmUoXCIuL3Zkb20vcGF0Y2guanNcIik7XG5cbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gcGF0Y2g7XG4gICAgICAgIH0sIHsgXCIuL3Zkb20vcGF0Y2guanNcIjogMTggfV0sIDE0OiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge1xuICAgICAgICAgICAgdmFyIGlzT2JqZWN0ID0gcmVxdWlyZShcImlzLW9iamVjdFwiKTtcbiAgICAgICAgICAgIHZhciBpc0hvb2sgPSByZXF1aXJlKFwiLi4vdm5vZGUvaXMtdmhvb2suanNcIik7XG5cbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gYXBwbHlQcm9wZXJ0aWVzO1xuXG4gICAgICAgICAgICBmdW5jdGlvbiBhcHBseVByb3BlcnRpZXMobm9kZSwgcHJvcHMsIHByZXZpb3VzKSB7XG4gICAgICAgICAgICAgICAgZm9yICh2YXIgcHJvcE5hbWUgaW4gcHJvcHMpIHtcbiAgICAgICAgICAgICAgICAgICAgdmFyIHByb3BWYWx1ZSA9IHByb3BzW3Byb3BOYW1lXTtcblxuICAgICAgICAgICAgICAgICAgICBpZiAocHJvcFZhbHVlID09PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJlbW92ZVByb3BlcnR5KG5vZGUsIHByb3BOYW1lLCBwcm9wVmFsdWUsIHByZXZpb3VzKTtcbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIGlmIChpc0hvb2socHJvcFZhbHVlKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgcmVtb3ZlUHJvcGVydHkobm9kZSwgcHJvcE5hbWUsIHByb3BWYWx1ZSwgcHJldmlvdXMpO1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHByb3BWYWx1ZS5ob29rKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcHJvcFZhbHVlLmhvb2sobm9kZSwgcHJvcE5hbWUsIHByZXZpb3VzID8gcHJldmlvdXNbcHJvcE5hbWVdIDogdW5kZWZpbmVkKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChpc09iamVjdChwcm9wVmFsdWUpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcGF0Y2hPYmplY3Qobm9kZSwgcHJvcHMsIHByZXZpb3VzLCBwcm9wTmFtZSwgcHJvcFZhbHVlKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgbm9kZVtwcm9wTmFtZV0gPSBwcm9wVmFsdWU7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIHJlbW92ZVByb3BlcnR5KG5vZGUsIHByb3BOYW1lLCBwcm9wVmFsdWUsIHByZXZpb3VzKSB7XG4gICAgICAgICAgICAgICAgaWYgKHByZXZpb3VzKSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciBwcmV2aW91c1ZhbHVlID0gcHJldmlvdXNbcHJvcE5hbWVdO1xuXG4gICAgICAgICAgICAgICAgICAgIGlmICghaXNIb29rKHByZXZpb3VzVmFsdWUpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAocHJvcE5hbWUgPT09IFwiYXR0cmlidXRlc1wiKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgZm9yICh2YXIgYXR0ck5hbWUgaW4gcHJldmlvdXNWYWx1ZSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBub2RlLnJlbW92ZUF0dHJpYnV0ZShhdHRyTmFtZSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIGlmIChwcm9wTmFtZSA9PT0gXCJzdHlsZVwiKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgZm9yICh2YXIgaSBpbiBwcmV2aW91c1ZhbHVlKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG5vZGUuc3R5bGVbaV0gPSBcIlwiO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAodHlwZW9mIHByZXZpb3VzVmFsdWUgPT09IFwic3RyaW5nXCIpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBub2RlW3Byb3BOYW1lXSA9IFwiXCI7XG4gICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIG5vZGVbcHJvcE5hbWVdID0gbnVsbDtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIGlmIChwcmV2aW91c1ZhbHVlLnVuaG9vaykge1xuICAgICAgICAgICAgICAgICAgICAgICAgcHJldmlvdXNWYWx1ZS51bmhvb2sobm9kZSwgcHJvcE5hbWUsIHByb3BWYWx1ZSk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIHBhdGNoT2JqZWN0KG5vZGUsIHByb3BzLCBwcmV2aW91cywgcHJvcE5hbWUsIHByb3BWYWx1ZSkge1xuICAgICAgICAgICAgICAgIHZhciBwcmV2aW91c1ZhbHVlID0gcHJldmlvdXMgPyBwcmV2aW91c1twcm9wTmFtZV0gOiB1bmRlZmluZWQ7XG5cbiAgICAgICAgICAgICAgICAvLyBTZXQgYXR0cmlidXRlc1xuICAgICAgICAgICAgICAgIGlmIChwcm9wTmFtZSA9PT0gXCJhdHRyaWJ1dGVzXCIpIHtcbiAgICAgICAgICAgICAgICAgICAgZm9yICh2YXIgYXR0ck5hbWUgaW4gcHJvcFZhbHVlKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICB2YXIgYXR0clZhbHVlID0gcHJvcFZhbHVlW2F0dHJOYW1lXTtcblxuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGF0dHJWYWx1ZSA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgbm9kZS5yZW1vdmVBdHRyaWJ1dGUoYXR0ck5hbWUpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBub2RlLnNldEF0dHJpYnV0ZShhdHRyTmFtZSwgYXR0clZhbHVlKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICBpZiAocHJldmlvdXNWYWx1ZSAmJiBpc09iamVjdChwcmV2aW91c1ZhbHVlKSAmJiBnZXRQcm90b3R5cGUocHJldmlvdXNWYWx1ZSkgIT09IGdldFByb3RvdHlwZShwcm9wVmFsdWUpKSB7XG4gICAgICAgICAgICAgICAgICAgIG5vZGVbcHJvcE5hbWVdID0gcHJvcFZhbHVlO1xuICAgICAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgaWYgKCFpc09iamVjdChub2RlW3Byb3BOYW1lXSkpIHtcbiAgICAgICAgICAgICAgICAgICAgbm9kZVtwcm9wTmFtZV0gPSB7fTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICB2YXIgcmVwbGFjZXIgPSBwcm9wTmFtZSA9PT0gXCJzdHlsZVwiID8gXCJcIiA6IHVuZGVmaW5lZDtcblxuICAgICAgICAgICAgICAgIGZvciAodmFyIGsgaW4gcHJvcFZhbHVlKSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciB2YWx1ZSA9IHByb3BWYWx1ZVtrXTtcbiAgICAgICAgICAgICAgICAgICAgbm9kZVtwcm9wTmFtZV1ba10gPSB2YWx1ZSA9PT0gdW5kZWZpbmVkID8gcmVwbGFjZXIgOiB2YWx1ZTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIGdldFByb3RvdHlwZSh2YWx1ZSkge1xuICAgICAgICAgICAgICAgIGlmIChPYmplY3QuZ2V0UHJvdG90eXBlT2YpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIE9iamVjdC5nZXRQcm90b3R5cGVPZih2YWx1ZSk7XG4gICAgICAgICAgICAgICAgfSBlbHNlIGlmICh2YWx1ZS5fX3Byb3RvX18pIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHZhbHVlLl9fcHJvdG9fXztcbiAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKHZhbHVlLmNvbnN0cnVjdG9yKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiB2YWx1ZS5jb25zdHJ1Y3Rvci5wcm90b3R5cGU7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9LCB7IFwiLi4vdm5vZGUvaXMtdmhvb2suanNcIjogMjYsIFwiaXMtb2JqZWN0XCI6IDExIH1dLCAxNTogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHtcbiAgICAgICAgICAgIHZhciBkb2N1bWVudCA9IHJlcXVpcmUoXCJnbG9iYWwvZG9jdW1lbnRcIik7XG5cbiAgICAgICAgICAgIHZhciBhcHBseVByb3BlcnRpZXMgPSByZXF1aXJlKFwiLi9hcHBseS1wcm9wZXJ0aWVzXCIpO1xuXG4gICAgICAgICAgICB2YXIgaXNWTm9kZSA9IHJlcXVpcmUoXCIuLi92bm9kZS9pcy12bm9kZS5qc1wiKTtcbiAgICAgICAgICAgIHZhciBpc1ZUZXh0ID0gcmVxdWlyZShcIi4uL3Zub2RlL2lzLXZ0ZXh0LmpzXCIpO1xuICAgICAgICAgICAgdmFyIGlzV2lkZ2V0ID0gcmVxdWlyZShcIi4uL3Zub2RlL2lzLXdpZGdldC5qc1wiKTtcbiAgICAgICAgICAgIHZhciBoYW5kbGVUaHVuayA9IHJlcXVpcmUoXCIuLi92bm9kZS9oYW5kbGUtdGh1bmsuanNcIik7XG5cbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gY3JlYXRlRWxlbWVudDtcblxuICAgICAgICAgICAgZnVuY3Rpb24gY3JlYXRlRWxlbWVudCh2bm9kZSwgb3B0cykge1xuICAgICAgICAgICAgICAgIHZhciBkb2MgPSBvcHRzID8gb3B0cy5kb2N1bWVudCB8fCBkb2N1bWVudCA6IGRvY3VtZW50O1xuICAgICAgICAgICAgICAgIHZhciB3YXJuID0gb3B0cyA/IG9wdHMud2FybiA6IG51bGw7XG5cbiAgICAgICAgICAgICAgICB2bm9kZSA9IGhhbmRsZVRodW5rKHZub2RlKS5hO1xuXG4gICAgICAgICAgICAgICAgaWYgKGlzV2lkZ2V0KHZub2RlKSkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gdm5vZGUuaW5pdCgpO1xuICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoaXNWVGV4dCh2bm9kZSkpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGRvYy5jcmVhdGVUZXh0Tm9kZSh2bm9kZS50ZXh0KTtcbiAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKCFpc1ZOb2RlKHZub2RlKSkge1xuICAgICAgICAgICAgICAgICAgICBpZiAod2Fybikge1xuICAgICAgICAgICAgICAgICAgICAgICAgd2FybihcIkl0ZW0gaXMgbm90IGEgdmFsaWQgdmlydHVhbCBkb20gbm9kZVwiLCB2bm9kZSk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIG51bGw7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgdmFyIG5vZGUgPSB2bm9kZS5uYW1lc3BhY2UgPT09IG51bGwgPyBkb2MuY3JlYXRlRWxlbWVudCh2bm9kZS50YWdOYW1lKSA6IGRvYy5jcmVhdGVFbGVtZW50TlModm5vZGUubmFtZXNwYWNlLCB2bm9kZS50YWdOYW1lKTtcblxuICAgICAgICAgICAgICAgIHZhciBwcm9wcyA9IHZub2RlLnByb3BlcnRpZXM7XG4gICAgICAgICAgICAgICAgYXBwbHlQcm9wZXJ0aWVzKG5vZGUsIHByb3BzKTtcblxuICAgICAgICAgICAgICAgIHZhciBjaGlsZHJlbiA9IHZub2RlLmNoaWxkcmVuO1xuXG4gICAgICAgICAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCBjaGlsZHJlbi5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgICAgICAgICB2YXIgY2hpbGROb2RlID0gY3JlYXRlRWxlbWVudChjaGlsZHJlbltpXSwgb3B0cyk7XG4gICAgICAgICAgICAgICAgICAgIGlmIChjaGlsZE5vZGUpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIG5vZGUuYXBwZW5kQ2hpbGQoY2hpbGROb2RlKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHJldHVybiBub2RlO1xuICAgICAgICAgICAgfVxuICAgICAgICB9LCB7IFwiLi4vdm5vZGUvaGFuZGxlLXRodW5rLmpzXCI6IDI0LCBcIi4uL3Zub2RlL2lzLXZub2RlLmpzXCI6IDI3LCBcIi4uL3Zub2RlL2lzLXZ0ZXh0LmpzXCI6IDI4LCBcIi4uL3Zub2RlL2lzLXdpZGdldC5qc1wiOiAyOSwgXCIuL2FwcGx5LXByb3BlcnRpZXNcIjogMTQsIFwiZ2xvYmFsL2RvY3VtZW50XCI6IDEwIH1dLCAxNjogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHtcbiAgICAgICAgICAgIC8vIE1hcHMgYSB2aXJ0dWFsIERPTSB0cmVlIG9udG8gYSByZWFsIERPTSB0cmVlIGluIGFuIGVmZmljaWVudCBtYW5uZXIuXG4gICAgICAgICAgICAvLyBXZSBkb24ndCB3YW50IHRvIHJlYWQgYWxsIG9mIHRoZSBET00gbm9kZXMgaW4gdGhlIHRyZWUgc28gd2UgdXNlXG4gICAgICAgICAgICAvLyB0aGUgaW4tb3JkZXIgdHJlZSBpbmRleGluZyB0byBlbGltaW5hdGUgcmVjdXJzaW9uIGRvd24gY2VydGFpbiBicmFuY2hlcy5cbiAgICAgICAgICAgIC8vIFdlIG9ubHkgcmVjdXJzZSBpbnRvIGEgRE9NIG5vZGUgaWYgd2Uga25vdyB0aGF0IGl0IGNvbnRhaW5zIGEgY2hpbGQgb2ZcbiAgICAgICAgICAgIC8vIGludGVyZXN0LlxuXG4gICAgICAgICAgICB2YXIgbm9DaGlsZCA9IHt9O1xuXG4gICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IGRvbUluZGV4O1xuXG4gICAgICAgICAgICBmdW5jdGlvbiBkb21JbmRleChyb290Tm9kZSwgdHJlZSwgaW5kaWNlcywgbm9kZXMpIHtcbiAgICAgICAgICAgICAgICBpZiAoIWluZGljZXMgfHwgaW5kaWNlcy5sZW5ndGggPT09IDApIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHt9O1xuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIGluZGljZXMuc29ydChhc2NlbmRpbmcpO1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gcmVjdXJzZShyb290Tm9kZSwgdHJlZSwgaW5kaWNlcywgbm9kZXMsIDApO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZnVuY3Rpb24gcmVjdXJzZShyb290Tm9kZSwgdHJlZSwgaW5kaWNlcywgbm9kZXMsIHJvb3RJbmRleCkge1xuICAgICAgICAgICAgICAgIG5vZGVzID0gbm9kZXMgfHwge307XG5cbiAgICAgICAgICAgICAgICBpZiAocm9vdE5vZGUpIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKGluZGV4SW5SYW5nZShpbmRpY2VzLCByb290SW5kZXgsIHJvb3RJbmRleCkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIG5vZGVzW3Jvb3RJbmRleF0gPSByb290Tm9kZTtcbiAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgIHZhciB2Q2hpbGRyZW4gPSB0cmVlLmNoaWxkcmVuO1xuXG4gICAgICAgICAgICAgICAgICAgIGlmICh2Q2hpbGRyZW4pIHtcblxuICAgICAgICAgICAgICAgICAgICAgICAgdmFyIGNoaWxkTm9kZXMgPSByb290Tm9kZS5jaGlsZE5vZGVzO1xuXG4gICAgICAgICAgICAgICAgICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IHRyZWUuY2hpbGRyZW4ubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICByb290SW5kZXggKz0gMTtcblxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZhciB2Q2hpbGQgPSB2Q2hpbGRyZW5baV0gfHwgbm9DaGlsZDtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB2YXIgbmV4dEluZGV4ID0gcm9vdEluZGV4ICsgKHZDaGlsZC5jb3VudCB8fCAwKTtcblxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIHNraXAgcmVjdXJzaW9uIGRvd24gdGhlIHRyZWUgaWYgdGhlcmUgYXJlIG5vIG5vZGVzIGRvd24gaGVyZVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChpbmRleEluUmFuZ2UoaW5kaWNlcywgcm9vdEluZGV4LCBuZXh0SW5kZXgpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlY3Vyc2UoY2hpbGROb2Rlc1tpXSwgdkNoaWxkLCBpbmRpY2VzLCBub2Rlcywgcm9vdEluZGV4KTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICByb290SW5kZXggPSBuZXh0SW5kZXg7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICByZXR1cm4gbm9kZXM7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIC8vIEJpbmFyeSBzZWFyY2ggZm9yIGFuIGluZGV4IGluIHRoZSBpbnRlcnZhbCBbbGVmdCwgcmlnaHRdXG4gICAgICAgICAgICBmdW5jdGlvbiBpbmRleEluUmFuZ2UoaW5kaWNlcywgbGVmdCwgcmlnaHQpIHtcbiAgICAgICAgICAgICAgICBpZiAoaW5kaWNlcy5sZW5ndGggPT09IDApIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHZhciBtaW5JbmRleCA9IDA7XG4gICAgICAgICAgICAgICAgdmFyIG1heEluZGV4ID0gaW5kaWNlcy5sZW5ndGggLSAxO1xuICAgICAgICAgICAgICAgIHZhciBjdXJyZW50SW5kZXg7XG4gICAgICAgICAgICAgICAgdmFyIGN1cnJlbnRJdGVtO1xuXG4gICAgICAgICAgICAgICAgd2hpbGUgKG1pbkluZGV4IDw9IG1heEluZGV4KSB7XG4gICAgICAgICAgICAgICAgICAgIGN1cnJlbnRJbmRleCA9IChtYXhJbmRleCArIG1pbkluZGV4KSAvIDIgPj4gMDtcbiAgICAgICAgICAgICAgICAgICAgY3VycmVudEl0ZW0gPSBpbmRpY2VzW2N1cnJlbnRJbmRleF07XG5cbiAgICAgICAgICAgICAgICAgICAgaWYgKG1pbkluZGV4ID09PSBtYXhJbmRleCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGN1cnJlbnRJdGVtID49IGxlZnQgJiYgY3VycmVudEl0ZW0gPD0gcmlnaHQ7XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoY3VycmVudEl0ZW0gPCBsZWZ0KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBtaW5JbmRleCA9IGN1cnJlbnRJbmRleCArIDE7XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoY3VycmVudEl0ZW0gPiByaWdodCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgbWF4SW5kZXggPSBjdXJyZW50SW5kZXggLSAxO1xuICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIGFzY2VuZGluZyhhLCBiKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGEgPiBiID8gMSA6IC0xO1xuICAgICAgICAgICAgfVxuICAgICAgICB9LCB7fV0sIDE3OiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge1xuICAgICAgICAgICAgdmFyIGFwcGx5UHJvcGVydGllcyA9IHJlcXVpcmUoXCIuL2FwcGx5LXByb3BlcnRpZXNcIik7XG5cbiAgICAgICAgICAgIHZhciBpc1dpZGdldCA9IHJlcXVpcmUoXCIuLi92bm9kZS9pcy13aWRnZXQuanNcIik7XG4gICAgICAgICAgICB2YXIgVlBhdGNoID0gcmVxdWlyZShcIi4uL3Zub2RlL3ZwYXRjaC5qc1wiKTtcblxuICAgICAgICAgICAgdmFyIHVwZGF0ZVdpZGdldCA9IHJlcXVpcmUoXCIuL3VwZGF0ZS13aWRnZXRcIik7XG5cbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gYXBwbHlQYXRjaDtcblxuICAgICAgICAgICAgZnVuY3Rpb24gYXBwbHlQYXRjaCh2cGF0Y2gsIGRvbU5vZGUsIHJlbmRlck9wdGlvbnMpIHtcbiAgICAgICAgICAgICAgICB2YXIgdHlwZSA9IHZwYXRjaC50eXBlO1xuICAgICAgICAgICAgICAgIHZhciB2Tm9kZSA9IHZwYXRjaC52Tm9kZTtcbiAgICAgICAgICAgICAgICB2YXIgcGF0Y2ggPSB2cGF0Y2gucGF0Y2g7XG5cbiAgICAgICAgICAgICAgICBzd2l0Y2ggKHR5cGUpIHtcbiAgICAgICAgICAgICAgICAgICAgY2FzZSBWUGF0Y2guUkVNT1ZFOlxuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHJlbW92ZU5vZGUoZG9tTm9kZSwgdk5vZGUpO1xuICAgICAgICAgICAgICAgICAgICBjYXNlIFZQYXRjaC5JTlNFUlQ6XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gaW5zZXJ0Tm9kZShkb21Ob2RlLCBwYXRjaCwgcmVuZGVyT3B0aW9ucyk7XG4gICAgICAgICAgICAgICAgICAgIGNhc2UgVlBhdGNoLlZURVhUOlxuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHN0cmluZ1BhdGNoKGRvbU5vZGUsIHZOb2RlLCBwYXRjaCwgcmVuZGVyT3B0aW9ucyk7XG4gICAgICAgICAgICAgICAgICAgIGNhc2UgVlBhdGNoLldJREdFVDpcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiB3aWRnZXRQYXRjaChkb21Ob2RlLCB2Tm9kZSwgcGF0Y2gsIHJlbmRlck9wdGlvbnMpO1xuICAgICAgICAgICAgICAgICAgICBjYXNlIFZQYXRjaC5WTk9ERTpcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiB2Tm9kZVBhdGNoKGRvbU5vZGUsIHZOb2RlLCBwYXRjaCwgcmVuZGVyT3B0aW9ucyk7XG4gICAgICAgICAgICAgICAgICAgIGNhc2UgVlBhdGNoLk9SREVSOlxuICAgICAgICAgICAgICAgICAgICAgICAgcmVvcmRlckNoaWxkcmVuKGRvbU5vZGUsIHBhdGNoKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBkb21Ob2RlO1xuICAgICAgICAgICAgICAgICAgICBjYXNlIFZQYXRjaC5QUk9QUzpcbiAgICAgICAgICAgICAgICAgICAgICAgIGFwcGx5UHJvcGVydGllcyhkb21Ob2RlLCBwYXRjaCwgdk5vZGUucHJvcGVydGllcyk7XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gZG9tTm9kZTtcbiAgICAgICAgICAgICAgICAgICAgY2FzZSBWUGF0Y2guVEhVTks6XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gcmVwbGFjZVJvb3QoZG9tTm9kZSwgcmVuZGVyT3B0aW9ucy5wYXRjaChkb21Ob2RlLCBwYXRjaCwgcmVuZGVyT3B0aW9ucykpO1xuICAgICAgICAgICAgICAgICAgICBkZWZhdWx0OlxuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGRvbU5vZGU7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBmdW5jdGlvbiByZW1vdmVOb2RlKGRvbU5vZGUsIHZOb2RlKSB7XG4gICAgICAgICAgICAgICAgdmFyIHBhcmVudE5vZGUgPSBkb21Ob2RlLnBhcmVudE5vZGU7XG5cbiAgICAgICAgICAgICAgICBpZiAocGFyZW50Tm9kZSkge1xuICAgICAgICAgICAgICAgICAgICBwYXJlbnROb2RlLnJlbW92ZUNoaWxkKGRvbU5vZGUpO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIGRlc3Ryb3lXaWRnZXQoZG9tTm9kZSwgdk5vZGUpO1xuXG4gICAgICAgICAgICAgICAgcmV0dXJuIG51bGw7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIGluc2VydE5vZGUocGFyZW50Tm9kZSwgdk5vZGUsIHJlbmRlck9wdGlvbnMpIHtcbiAgICAgICAgICAgICAgICB2YXIgbmV3Tm9kZSA9IHJlbmRlck9wdGlvbnMucmVuZGVyKHZOb2RlLCByZW5kZXJPcHRpb25zKTtcblxuICAgICAgICAgICAgICAgIGlmIChwYXJlbnROb2RlKSB7XG4gICAgICAgICAgICAgICAgICAgIHBhcmVudE5vZGUuYXBwZW5kQ2hpbGQobmV3Tm9kZSk7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgcmV0dXJuIHBhcmVudE5vZGU7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIHN0cmluZ1BhdGNoKGRvbU5vZGUsIGxlZnRWTm9kZSwgdlRleHQsIHJlbmRlck9wdGlvbnMpIHtcbiAgICAgICAgICAgICAgICB2YXIgbmV3Tm9kZTtcblxuICAgICAgICAgICAgICAgIGlmIChkb21Ob2RlLm5vZGVUeXBlID09PSAzKSB7XG4gICAgICAgICAgICAgICAgICAgIGRvbU5vZGUucmVwbGFjZURhdGEoMCwgZG9tTm9kZS5sZW5ndGgsIHZUZXh0LnRleHQpO1xuICAgICAgICAgICAgICAgICAgICBuZXdOb2RlID0gZG9tTm9kZTtcbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICB2YXIgcGFyZW50Tm9kZSA9IGRvbU5vZGUucGFyZW50Tm9kZTtcbiAgICAgICAgICAgICAgICAgICAgbmV3Tm9kZSA9IHJlbmRlck9wdGlvbnMucmVuZGVyKHZUZXh0LCByZW5kZXJPcHRpb25zKTtcblxuICAgICAgICAgICAgICAgICAgICBpZiAocGFyZW50Tm9kZSAmJiBuZXdOb2RlICE9PSBkb21Ob2RlKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBwYXJlbnROb2RlLnJlcGxhY2VDaGlsZChuZXdOb2RlLCBkb21Ob2RlKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHJldHVybiBuZXdOb2RlO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBmdW5jdGlvbiB3aWRnZXRQYXRjaChkb21Ob2RlLCBsZWZ0Vk5vZGUsIHdpZGdldCwgcmVuZGVyT3B0aW9ucykge1xuICAgICAgICAgICAgICAgIHZhciB1cGRhdGluZyA9IHVwZGF0ZVdpZGdldChsZWZ0Vk5vZGUsIHdpZGdldCk7XG4gICAgICAgICAgICAgICAgdmFyIG5ld05vZGU7XG5cbiAgICAgICAgICAgICAgICBpZiAodXBkYXRpbmcpIHtcbiAgICAgICAgICAgICAgICAgICAgbmV3Tm9kZSA9IHdpZGdldC51cGRhdGUobGVmdFZOb2RlLCBkb21Ob2RlKSB8fCBkb21Ob2RlO1xuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIG5ld05vZGUgPSByZW5kZXJPcHRpb25zLnJlbmRlcih3aWRnZXQsIHJlbmRlck9wdGlvbnMpO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHZhciBwYXJlbnROb2RlID0gZG9tTm9kZS5wYXJlbnROb2RlO1xuXG4gICAgICAgICAgICAgICAgaWYgKHBhcmVudE5vZGUgJiYgbmV3Tm9kZSAhPT0gZG9tTm9kZSkge1xuICAgICAgICAgICAgICAgICAgICBwYXJlbnROb2RlLnJlcGxhY2VDaGlsZChuZXdOb2RlLCBkb21Ob2RlKTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICBpZiAoIXVwZGF0aW5nKSB7XG4gICAgICAgICAgICAgICAgICAgIGRlc3Ryb3lXaWRnZXQoZG9tTm9kZSwgbGVmdFZOb2RlKTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICByZXR1cm4gbmV3Tm9kZTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZnVuY3Rpb24gdk5vZGVQYXRjaChkb21Ob2RlLCBsZWZ0Vk5vZGUsIHZOb2RlLCByZW5kZXJPcHRpb25zKSB7XG4gICAgICAgICAgICAgICAgdmFyIHBhcmVudE5vZGUgPSBkb21Ob2RlLnBhcmVudE5vZGU7XG4gICAgICAgICAgICAgICAgdmFyIG5ld05vZGUgPSByZW5kZXJPcHRpb25zLnJlbmRlcih2Tm9kZSwgcmVuZGVyT3B0aW9ucyk7XG5cbiAgICAgICAgICAgICAgICBpZiAocGFyZW50Tm9kZSAmJiBuZXdOb2RlICE9PSBkb21Ob2RlKSB7XG4gICAgICAgICAgICAgICAgICAgIHBhcmVudE5vZGUucmVwbGFjZUNoaWxkKG5ld05vZGUsIGRvbU5vZGUpO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHJldHVybiBuZXdOb2RlO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBmdW5jdGlvbiBkZXN0cm95V2lkZ2V0KGRvbU5vZGUsIHcpIHtcbiAgICAgICAgICAgICAgICBpZiAodHlwZW9mIHcuZGVzdHJveSA9PT0gXCJmdW5jdGlvblwiICYmIGlzV2lkZ2V0KHcpKSB7XG4gICAgICAgICAgICAgICAgICAgIHcuZGVzdHJveShkb21Ob2RlKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIHJlb3JkZXJDaGlsZHJlbihkb21Ob2RlLCBtb3Zlcykge1xuICAgICAgICAgICAgICAgIHZhciBjaGlsZE5vZGVzID0gZG9tTm9kZS5jaGlsZE5vZGVzO1xuICAgICAgICAgICAgICAgIHZhciBrZXlNYXAgPSB7fTtcbiAgICAgICAgICAgICAgICB2YXIgbm9kZTtcbiAgICAgICAgICAgICAgICB2YXIgcmVtb3ZlO1xuICAgICAgICAgICAgICAgIHZhciBpbnNlcnQ7XG5cbiAgICAgICAgICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IG1vdmVzLnJlbW92ZXMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgICAgICAgICAgcmVtb3ZlID0gbW92ZXMucmVtb3Zlc1tpXTtcbiAgICAgICAgICAgICAgICAgICAgbm9kZSA9IGNoaWxkTm9kZXNbcmVtb3ZlLmZyb21dO1xuICAgICAgICAgICAgICAgICAgICBpZiAocmVtb3ZlLmtleSkge1xuICAgICAgICAgICAgICAgICAgICAgICAga2V5TWFwW3JlbW92ZS5rZXldID0gbm9kZTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICBkb21Ob2RlLnJlbW92ZUNoaWxkKG5vZGUpO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHZhciBsZW5ndGggPSBjaGlsZE5vZGVzLmxlbmd0aDtcbiAgICAgICAgICAgICAgICBmb3IgKHZhciBqID0gMDsgaiA8IG1vdmVzLmluc2VydHMubGVuZ3RoOyBqKyspIHtcbiAgICAgICAgICAgICAgICAgICAgaW5zZXJ0ID0gbW92ZXMuaW5zZXJ0c1tqXTtcbiAgICAgICAgICAgICAgICAgICAgbm9kZSA9IGtleU1hcFtpbnNlcnQua2V5XTtcbiAgICAgICAgICAgICAgICAgICAgLy8gdGhpcyBpcyB0aGUgd2VpcmRlc3QgYnVnIGkndmUgZXZlciBzZWVuIGluIHdlYmtpdFxuICAgICAgICAgICAgICAgICAgICBkb21Ob2RlLmluc2VydEJlZm9yZShub2RlLCBpbnNlcnQudG8gPj0gbGVuZ3RoKysgPyBudWxsIDogY2hpbGROb2Rlc1tpbnNlcnQudG9dKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIHJlcGxhY2VSb290KG9sZFJvb3QsIG5ld1Jvb3QpIHtcbiAgICAgICAgICAgICAgICBpZiAob2xkUm9vdCAmJiBuZXdSb290ICYmIG9sZFJvb3QgIT09IG5ld1Jvb3QgJiYgb2xkUm9vdC5wYXJlbnROb2RlKSB7XG4gICAgICAgICAgICAgICAgICAgIG9sZFJvb3QucGFyZW50Tm9kZS5yZXBsYWNlQ2hpbGQobmV3Um9vdCwgb2xkUm9vdCk7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgcmV0dXJuIG5ld1Jvb3Q7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0sIHsgXCIuLi92bm9kZS9pcy13aWRnZXQuanNcIjogMjksIFwiLi4vdm5vZGUvdnBhdGNoLmpzXCI6IDMyLCBcIi4vYXBwbHktcHJvcGVydGllc1wiOiAxNCwgXCIuL3VwZGF0ZS13aWRnZXRcIjogMTkgfV0sIDE4OiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge1xuICAgICAgICAgICAgdmFyIGRvY3VtZW50ID0gcmVxdWlyZShcImdsb2JhbC9kb2N1bWVudFwiKTtcbiAgICAgICAgICAgIHZhciBpc0FycmF5ID0gcmVxdWlyZShcIngtaXMtYXJyYXlcIik7XG5cbiAgICAgICAgICAgIHZhciByZW5kZXIgPSByZXF1aXJlKFwiLi9jcmVhdGUtZWxlbWVudFwiKTtcbiAgICAgICAgICAgIHZhciBkb21JbmRleCA9IHJlcXVpcmUoXCIuL2RvbS1pbmRleFwiKTtcbiAgICAgICAgICAgIHZhciBwYXRjaE9wID0gcmVxdWlyZShcIi4vcGF0Y2gtb3BcIik7XG4gICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IHBhdGNoO1xuXG4gICAgICAgICAgICBmdW5jdGlvbiBwYXRjaChyb290Tm9kZSwgcGF0Y2hlcywgcmVuZGVyT3B0aW9ucykge1xuICAgICAgICAgICAgICAgIHJlbmRlck9wdGlvbnMgPSByZW5kZXJPcHRpb25zIHx8IHt9O1xuICAgICAgICAgICAgICAgIHJlbmRlck9wdGlvbnMucGF0Y2ggPSByZW5kZXJPcHRpb25zLnBhdGNoICYmIHJlbmRlck9wdGlvbnMucGF0Y2ggIT09IHBhdGNoID8gcmVuZGVyT3B0aW9ucy5wYXRjaCA6IHBhdGNoUmVjdXJzaXZlO1xuICAgICAgICAgICAgICAgIHJlbmRlck9wdGlvbnMucmVuZGVyID0gcmVuZGVyT3B0aW9ucy5yZW5kZXIgfHwgcmVuZGVyO1xuXG4gICAgICAgICAgICAgICAgcmV0dXJuIHJlbmRlck9wdGlvbnMucGF0Y2gocm9vdE5vZGUsIHBhdGNoZXMsIHJlbmRlck9wdGlvbnMpO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBmdW5jdGlvbiBwYXRjaFJlY3Vyc2l2ZShyb290Tm9kZSwgcGF0Y2hlcywgcmVuZGVyT3B0aW9ucykge1xuICAgICAgICAgICAgICAgIHZhciBpbmRpY2VzID0gcGF0Y2hJbmRpY2VzKHBhdGNoZXMpO1xuXG4gICAgICAgICAgICAgICAgaWYgKGluZGljZXMubGVuZ3RoID09PSAwKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiByb290Tm9kZTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICB2YXIgaW5kZXggPSBkb21JbmRleChyb290Tm9kZSwgcGF0Y2hlcy5hLCBpbmRpY2VzKTtcbiAgICAgICAgICAgICAgICB2YXIgb3duZXJEb2N1bWVudCA9IHJvb3ROb2RlLm93bmVyRG9jdW1lbnQ7XG5cbiAgICAgICAgICAgICAgICBpZiAoIXJlbmRlck9wdGlvbnMuZG9jdW1lbnQgJiYgb3duZXJEb2N1bWVudCAhPT0gZG9jdW1lbnQpIHtcbiAgICAgICAgICAgICAgICAgICAgcmVuZGVyT3B0aW9ucy5kb2N1bWVudCA9IG93bmVyRG9jdW1lbnQ7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCBpbmRpY2VzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciBub2RlSW5kZXggPSBpbmRpY2VzW2ldO1xuICAgICAgICAgICAgICAgICAgICByb290Tm9kZSA9IGFwcGx5UGF0Y2gocm9vdE5vZGUsIGluZGV4W25vZGVJbmRleF0sIHBhdGNoZXNbbm9kZUluZGV4XSwgcmVuZGVyT3B0aW9ucyk7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgcmV0dXJuIHJvb3ROb2RlO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBmdW5jdGlvbiBhcHBseVBhdGNoKHJvb3ROb2RlLCBkb21Ob2RlLCBwYXRjaExpc3QsIHJlbmRlck9wdGlvbnMpIHtcbiAgICAgICAgICAgICAgICBpZiAoIWRvbU5vZGUpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHJvb3ROb2RlO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHZhciBuZXdOb2RlO1xuXG4gICAgICAgICAgICAgICAgaWYgKGlzQXJyYXkocGF0Y2hMaXN0KSkge1xuICAgICAgICAgICAgICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IHBhdGNoTGlzdC5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgICAgICAgICAgICAgbmV3Tm9kZSA9IHBhdGNoT3AocGF0Y2hMaXN0W2ldLCBkb21Ob2RlLCByZW5kZXJPcHRpb25zKTtcblxuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGRvbU5vZGUgPT09IHJvb3ROb2RlKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcm9vdE5vZGUgPSBuZXdOb2RlO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgbmV3Tm9kZSA9IHBhdGNoT3AocGF0Y2hMaXN0LCBkb21Ob2RlLCByZW5kZXJPcHRpb25zKTtcblxuICAgICAgICAgICAgICAgICAgICBpZiAoZG9tTm9kZSA9PT0gcm9vdE5vZGUpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJvb3ROb2RlID0gbmV3Tm9kZTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHJldHVybiByb290Tm9kZTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZnVuY3Rpb24gcGF0Y2hJbmRpY2VzKHBhdGNoZXMpIHtcbiAgICAgICAgICAgICAgICB2YXIgaW5kaWNlcyA9IFtdO1xuXG4gICAgICAgICAgICAgICAgZm9yICh2YXIga2V5IGluIHBhdGNoZXMpIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKGtleSAhPT0gXCJhXCIpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGluZGljZXMucHVzaChOdW1iZXIoa2V5KSk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICByZXR1cm4gaW5kaWNlcztcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSwgeyBcIi4vY3JlYXRlLWVsZW1lbnRcIjogMTUsIFwiLi9kb20taW5kZXhcIjogMTYsIFwiLi9wYXRjaC1vcFwiOiAxNywgXCJnbG9iYWwvZG9jdW1lbnRcIjogMTAsIFwieC1pcy1hcnJheVwiOiAxMiB9XSwgMTk6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICB2YXIgaXNXaWRnZXQgPSByZXF1aXJlKFwiLi4vdm5vZGUvaXMtd2lkZ2V0LmpzXCIpO1xuXG4gICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IHVwZGF0ZVdpZGdldDtcblxuICAgICAgICAgICAgZnVuY3Rpb24gdXBkYXRlV2lkZ2V0KGEsIGIpIHtcbiAgICAgICAgICAgICAgICBpZiAoaXNXaWRnZXQoYSkgJiYgaXNXaWRnZXQoYikpIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKFwibmFtZVwiIGluIGEgJiYgXCJuYW1lXCIgaW4gYikge1xuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGEuaWQgPT09IGIuaWQ7XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gYS5pbml0ID09PSBiLmluaXQ7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0sIHsgXCIuLi92bm9kZS9pcy13aWRnZXQuanNcIjogMjkgfV0sIDIwOiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge1xuICAgICAgICAgICAgXCJ1c2Ugc3RyaWN0XCI7XG5cbiAgICAgICAgICAgIHZhciBFdlN0b3JlID0gcmVxdWlyZShcImV2LXN0b3JlXCIpO1xuXG4gICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IEV2SG9vaztcblxuICAgICAgICAgICAgZnVuY3Rpb24gRXZIb29rKHZhbHVlKSB7XG4gICAgICAgICAgICAgICAgaWYgKCEodGhpcyBpbnN0YW5jZW9mIEV2SG9vaykpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIG5ldyBFdkhvb2sodmFsdWUpO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHRoaXMudmFsdWUgPSB2YWx1ZTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgRXZIb29rLnByb3RvdHlwZS5ob29rID0gZnVuY3Rpb24gKG5vZGUsIHByb3BlcnR5TmFtZSkge1xuICAgICAgICAgICAgICAgIHZhciBlcyA9IEV2U3RvcmUobm9kZSk7XG4gICAgICAgICAgICAgICAgdmFyIHByb3BOYW1lID0gcHJvcGVydHlOYW1lLnN1YnN0cigzKTtcblxuICAgICAgICAgICAgICAgIGVzW3Byb3BOYW1lXSA9IHRoaXMudmFsdWU7XG4gICAgICAgICAgICB9O1xuXG4gICAgICAgICAgICBFdkhvb2sucHJvdG90eXBlLnVuaG9vayA9IGZ1bmN0aW9uIChub2RlLCBwcm9wZXJ0eU5hbWUpIHtcbiAgICAgICAgICAgICAgICB2YXIgZXMgPSBFdlN0b3JlKG5vZGUpO1xuICAgICAgICAgICAgICAgIHZhciBwcm9wTmFtZSA9IHByb3BlcnR5TmFtZS5zdWJzdHIoMyk7XG5cbiAgICAgICAgICAgICAgICBlc1twcm9wTmFtZV0gPSB1bmRlZmluZWQ7XG4gICAgICAgICAgICB9O1xuICAgICAgICB9LCB7IFwiZXYtc3RvcmVcIjogNyB9XSwgMjE6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICBcInVzZSBzdHJpY3RcIjtcblxuICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBTb2Z0U2V0SG9vaztcblxuICAgICAgICAgICAgZnVuY3Rpb24gU29mdFNldEhvb2sodmFsdWUpIHtcbiAgICAgICAgICAgICAgICBpZiAoISh0aGlzIGluc3RhbmNlb2YgU29mdFNldEhvb2spKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBuZXcgU29mdFNldEhvb2sodmFsdWUpO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHRoaXMudmFsdWUgPSB2YWx1ZTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgU29mdFNldEhvb2sucHJvdG90eXBlLmhvb2sgPSBmdW5jdGlvbiAobm9kZSwgcHJvcGVydHlOYW1lKSB7XG4gICAgICAgICAgICAgICAgaWYgKG5vZGVbcHJvcGVydHlOYW1lXSAhPT0gdGhpcy52YWx1ZSkge1xuICAgICAgICAgICAgICAgICAgICBub2RlW3Byb3BlcnR5TmFtZV0gPSB0aGlzLnZhbHVlO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH07XG4gICAgICAgIH0sIHt9XSwgMjI6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICBcInVzZSBzdHJpY3RcIjtcblxuICAgICAgICAgICAgdmFyIGlzQXJyYXkgPSByZXF1aXJlKFwieC1pcy1hcnJheVwiKTtcblxuICAgICAgICAgICAgdmFyIFZOb2RlID0gcmVxdWlyZShcIi4uL3Zub2RlL3Zub2RlLmpzXCIpO1xuICAgICAgICAgICAgdmFyIFZUZXh0ID0gcmVxdWlyZShcIi4uL3Zub2RlL3Z0ZXh0LmpzXCIpO1xuICAgICAgICAgICAgdmFyIGlzVk5vZGUgPSByZXF1aXJlKFwiLi4vdm5vZGUvaXMtdm5vZGVcIik7XG4gICAgICAgICAgICB2YXIgaXNWVGV4dCA9IHJlcXVpcmUoXCIuLi92bm9kZS9pcy12dGV4dFwiKTtcbiAgICAgICAgICAgIHZhciBpc1dpZGdldCA9IHJlcXVpcmUoXCIuLi92bm9kZS9pcy13aWRnZXRcIik7XG4gICAgICAgICAgICB2YXIgaXNIb29rID0gcmVxdWlyZShcIi4uL3Zub2RlL2lzLXZob29rXCIpO1xuICAgICAgICAgICAgdmFyIGlzVlRodW5rID0gcmVxdWlyZShcIi4uL3Zub2RlL2lzLXRodW5rXCIpO1xuXG4gICAgICAgICAgICB2YXIgcGFyc2VUYWcgPSByZXF1aXJlKFwiLi9wYXJzZS10YWcuanNcIik7XG4gICAgICAgICAgICB2YXIgc29mdFNldEhvb2sgPSByZXF1aXJlKFwiLi9ob29rcy9zb2Z0LXNldC1ob29rLmpzXCIpO1xuICAgICAgICAgICAgdmFyIGV2SG9vayA9IHJlcXVpcmUoXCIuL2hvb2tzL2V2LWhvb2suanNcIik7XG5cbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gaDtcblxuICAgICAgICAgICAgZnVuY3Rpb24gaCh0YWdOYW1lLCBwcm9wZXJ0aWVzLCBjaGlsZHJlbikge1xuICAgICAgICAgICAgICAgIHZhciBjaGlsZE5vZGVzID0gW107XG4gICAgICAgICAgICAgICAgdmFyIHRhZywgcHJvcHMsIGtleSwgbmFtZXNwYWNlO1xuXG4gICAgICAgICAgICAgICAgaWYgKCFjaGlsZHJlbiAmJiBpc0NoaWxkcmVuKHByb3BlcnRpZXMpKSB7XG4gICAgICAgICAgICAgICAgICAgIGNoaWxkcmVuID0gcHJvcGVydGllcztcbiAgICAgICAgICAgICAgICAgICAgcHJvcHMgPSB7fTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICBwcm9wcyA9IHByb3BzIHx8IHByb3BlcnRpZXMgfHwge307XG4gICAgICAgICAgICAgICAgdGFnID0gcGFyc2VUYWcodGFnTmFtZSwgcHJvcHMpO1xuXG4gICAgICAgICAgICAgICAgLy8gc3VwcG9ydCBrZXlzXG4gICAgICAgICAgICAgICAgaWYgKHByb3BzLmhhc093blByb3BlcnR5KFwia2V5XCIpKSB7XG4gICAgICAgICAgICAgICAgICAgIGtleSA9IHByb3BzLmtleTtcbiAgICAgICAgICAgICAgICAgICAgcHJvcHMua2V5ID0gdW5kZWZpbmVkO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIC8vIHN1cHBvcnQgbmFtZXNwYWNlXG4gICAgICAgICAgICAgICAgaWYgKHByb3BzLmhhc093blByb3BlcnR5KFwibmFtZXNwYWNlXCIpKSB7XG4gICAgICAgICAgICAgICAgICAgIG5hbWVzcGFjZSA9IHByb3BzLm5hbWVzcGFjZTtcbiAgICAgICAgICAgICAgICAgICAgcHJvcHMubmFtZXNwYWNlID0gdW5kZWZpbmVkO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIC8vIGZpeCBjdXJzb3IgYnVnXG4gICAgICAgICAgICAgICAgaWYgKHRhZyA9PT0gXCJJTlBVVFwiICYmICFuYW1lc3BhY2UgJiYgcHJvcHMuaGFzT3duUHJvcGVydHkoXCJ2YWx1ZVwiKSAmJiBwcm9wcy52YWx1ZSAhPT0gdW5kZWZpbmVkICYmICFpc0hvb2socHJvcHMudmFsdWUpKSB7XG4gICAgICAgICAgICAgICAgICAgIHByb3BzLnZhbHVlID0gc29mdFNldEhvb2socHJvcHMudmFsdWUpO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHRyYW5zZm9ybVByb3BlcnRpZXMocHJvcHMpO1xuXG4gICAgICAgICAgICAgICAgaWYgKGNoaWxkcmVuICE9PSB1bmRlZmluZWQgJiYgY2hpbGRyZW4gIT09IG51bGwpIHtcbiAgICAgICAgICAgICAgICAgICAgYWRkQ2hpbGQoY2hpbGRyZW4sIGNoaWxkTm9kZXMsIHRhZywgcHJvcHMpO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHJldHVybiBuZXcgVk5vZGUodGFnLCBwcm9wcywgY2hpbGROb2Rlcywga2V5LCBuYW1lc3BhY2UpO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBmdW5jdGlvbiBhZGRDaGlsZChjLCBjaGlsZE5vZGVzLCB0YWcsIHByb3BzKSB7XG4gICAgICAgICAgICAgICAgaWYgKHR5cGVvZiBjID09PSBcInN0cmluZ1wiKSB7XG4gICAgICAgICAgICAgICAgICAgIGNoaWxkTm9kZXMucHVzaChuZXcgVlRleHQoYykpO1xuICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAodHlwZW9mIGMgPT09IFwibnVtYmVyXCIpIHtcbiAgICAgICAgICAgICAgICAgICAgY2hpbGROb2Rlcy5wdXNoKG5ldyBWVGV4dChTdHJpbmcoYykpKTtcbiAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKGlzQ2hpbGQoYykpIHtcbiAgICAgICAgICAgICAgICAgICAgY2hpbGROb2Rlcy5wdXNoKGMpO1xuICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoaXNBcnJheShjKSkge1xuICAgICAgICAgICAgICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IGMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGFkZENoaWxkKGNbaV0sIGNoaWxkTm9kZXMsIHRhZywgcHJvcHMpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfSBlbHNlIGlmIChjID09PSBudWxsIHx8IGMgPT09IHVuZGVmaW5lZCkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgdGhyb3cgVW5leHBlY3RlZFZpcnR1YWxFbGVtZW50KHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGZvcmVpZ25PYmplY3Q6IGMsXG4gICAgICAgICAgICAgICAgICAgICAgICBwYXJlbnRWbm9kZToge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRhZ05hbWU6IHRhZyxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBwcm9wZXJ0aWVzOiBwcm9wc1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIHRyYW5zZm9ybVByb3BlcnRpZXMocHJvcHMpIHtcbiAgICAgICAgICAgICAgICBmb3IgKHZhciBwcm9wTmFtZSBpbiBwcm9wcykge1xuICAgICAgICAgICAgICAgICAgICBpZiAocHJvcHMuaGFzT3duUHJvcGVydHkocHJvcE5hbWUpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICB2YXIgdmFsdWUgPSBwcm9wc1twcm9wTmFtZV07XG5cbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChpc0hvb2sodmFsdWUpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgY29udGludWU7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChwcm9wTmFtZS5zdWJzdHIoMCwgMykgPT09IFwiZXYtXCIpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBhZGQgZXYtZm9vIHN1cHBvcnRcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBwcm9wc1twcm9wTmFtZV0gPSBldkhvb2sodmFsdWUpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBmdW5jdGlvbiBpc0NoaWxkKHgpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gaXNWTm9kZSh4KSB8fCBpc1ZUZXh0KHgpIHx8IGlzV2lkZ2V0KHgpIHx8IGlzVlRodW5rKHgpO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBmdW5jdGlvbiBpc0NoaWxkcmVuKHgpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gdHlwZW9mIHggPT09IFwic3RyaW5nXCIgfHwgaXNBcnJheSh4KSB8fCBpc0NoaWxkKHgpO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBmdW5jdGlvbiBVbmV4cGVjdGVkVmlydHVhbEVsZW1lbnQoZGF0YSkge1xuICAgICAgICAgICAgICAgIHZhciBlcnIgPSBuZXcgRXJyb3IoKTtcblxuICAgICAgICAgICAgICAgIGVyci50eXBlID0gXCJ2aXJ0dWFsLWh5cGVyc2NyaXB0LnVuZXhwZWN0ZWQudmlydHVhbC1lbGVtZW50XCI7XG4gICAgICAgICAgICAgICAgZXJyLm1lc3NhZ2UgPSBcIlVuZXhwZWN0ZWQgdmlydHVhbCBjaGlsZCBwYXNzZWQgdG8gaCgpLlxcblwiICsgXCJFeHBlY3RlZCBhIFZOb2RlIC8gVnRodW5rIC8gVldpZGdldCAvIHN0cmluZyBidXQ6XFxuXCIgKyBcImdvdDpcXG5cIiArIGVycm9yU3RyaW5nKGRhdGEuZm9yZWlnbk9iamVjdCkgKyBcIi5cXG5cIiArIFwiVGhlIHBhcmVudCB2bm9kZSBpczpcXG5cIiArIGVycm9yU3RyaW5nKGRhdGEucGFyZW50Vm5vZGUpO1xuICAgICAgICAgICAgICAgIFwiXFxuXCIgKyBcIlN1Z2dlc3RlZCBmaXg6IGNoYW5nZSB5b3VyIGBoKC4uLiwgWyAuLi4gXSlgIGNhbGxzaXRlLlwiO1xuICAgICAgICAgICAgICAgIGVyci5mb3JlaWduT2JqZWN0ID0gZGF0YS5mb3JlaWduT2JqZWN0O1xuICAgICAgICAgICAgICAgIGVyci5wYXJlbnRWbm9kZSA9IGRhdGEucGFyZW50Vm5vZGU7XG5cbiAgICAgICAgICAgICAgICByZXR1cm4gZXJyO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBmdW5jdGlvbiBlcnJvclN0cmluZyhvYmopIHtcbiAgICAgICAgICAgICAgICB0cnkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gSlNPTi5zdHJpbmdpZnkob2JqLCBudWxsLCBcIiAgICBcIik7XG4gICAgICAgICAgICAgICAgfSBjYXRjaCAoZSkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gU3RyaW5nKG9iaik7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9LCB7IFwiLi4vdm5vZGUvaXMtdGh1bmtcIjogMjUsIFwiLi4vdm5vZGUvaXMtdmhvb2tcIjogMjYsIFwiLi4vdm5vZGUvaXMtdm5vZGVcIjogMjcsIFwiLi4vdm5vZGUvaXMtdnRleHRcIjogMjgsIFwiLi4vdm5vZGUvaXMtd2lkZ2V0XCI6IDI5LCBcIi4uL3Zub2RlL3Zub2RlLmpzXCI6IDMxLCBcIi4uL3Zub2RlL3Z0ZXh0LmpzXCI6IDMzLCBcIi4vaG9va3MvZXYtaG9vay5qc1wiOiAyMCwgXCIuL2hvb2tzL3NvZnQtc2V0LWhvb2suanNcIjogMjEsIFwiLi9wYXJzZS10YWcuanNcIjogMjMsIFwieC1pcy1hcnJheVwiOiAxMiB9XSwgMjM6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICBcInVzZSBzdHJpY3RcIjtcblxuICAgICAgICAgICAgdmFyIHNwbGl0ID0gcmVxdWlyZShcImJyb3dzZXItc3BsaXRcIik7XG5cbiAgICAgICAgICAgIHZhciBjbGFzc0lkU3BsaXQgPSAvKFtcXC4jXT9bYS16QS1aMC05XFx1MDA3Ri1cXHVGRkZGXzotXSspLztcbiAgICAgICAgICAgIHZhciBub3RDbGFzc0lkID0gL15cXC58Iy87XG5cbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gcGFyc2VUYWc7XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIHBhcnNlVGFnKHRhZywgcHJvcHMpIHtcbiAgICAgICAgICAgICAgICBpZiAoIXRhZykge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gXCJESVZcIjtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICB2YXIgbm9JZCA9ICFwcm9wcy5oYXNPd25Qcm9wZXJ0eShcImlkXCIpO1xuXG4gICAgICAgICAgICAgICAgdmFyIHRhZ1BhcnRzID0gc3BsaXQodGFnLCBjbGFzc0lkU3BsaXQpO1xuICAgICAgICAgICAgICAgIHZhciB0YWdOYW1lID0gbnVsbDtcblxuICAgICAgICAgICAgICAgIGlmIChub3RDbGFzc0lkLnRlc3QodGFnUGFydHNbMV0pKSB7XG4gICAgICAgICAgICAgICAgICAgIHRhZ05hbWUgPSBcIkRJVlwiO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHZhciBjbGFzc2VzLCBwYXJ0LCB0eXBlLCBpO1xuXG4gICAgICAgICAgICAgICAgZm9yIChpID0gMDsgaSA8IHRhZ1BhcnRzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICAgICAgICAgIHBhcnQgPSB0YWdQYXJ0c1tpXTtcblxuICAgICAgICAgICAgICAgICAgICBpZiAoIXBhcnQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnRpbnVlO1xuICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgdHlwZSA9IHBhcnQuY2hhckF0KDApO1xuXG4gICAgICAgICAgICAgICAgICAgIGlmICghdGFnTmFtZSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgdGFnTmFtZSA9IHBhcnQ7XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAodHlwZSA9PT0gXCIuXCIpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGNsYXNzZXMgPSBjbGFzc2VzIHx8IFtdO1xuICAgICAgICAgICAgICAgICAgICAgICAgY2xhc3Nlcy5wdXNoKHBhcnQuc3Vic3RyaW5nKDEsIHBhcnQubGVuZ3RoKSk7XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAodHlwZSA9PT0gXCIjXCIgJiYgbm9JZCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgcHJvcHMuaWQgPSBwYXJ0LnN1YnN0cmluZygxLCBwYXJ0Lmxlbmd0aCk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICBpZiAoY2xhc3Nlcykge1xuICAgICAgICAgICAgICAgICAgICBpZiAocHJvcHMuY2xhc3NOYW1lKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBjbGFzc2VzLnB1c2gocHJvcHMuY2xhc3NOYW1lKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgIHByb3BzLmNsYXNzTmFtZSA9IGNsYXNzZXMuam9pbihcIiBcIik7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgcmV0dXJuIHByb3BzLm5hbWVzcGFjZSA/IHRhZ05hbWUgOiB0YWdOYW1lLnRvVXBwZXJDYXNlKCk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0sIHsgXCJicm93c2VyLXNwbGl0XCI6IDUgfV0sIDI0OiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge1xuICAgICAgICAgICAgdmFyIGlzVk5vZGUgPSByZXF1aXJlKFwiLi9pcy12bm9kZVwiKTtcbiAgICAgICAgICAgIHZhciBpc1ZUZXh0ID0gcmVxdWlyZShcIi4vaXMtdnRleHRcIik7XG4gICAgICAgICAgICB2YXIgaXNXaWRnZXQgPSByZXF1aXJlKFwiLi9pcy13aWRnZXRcIik7XG4gICAgICAgICAgICB2YXIgaXNUaHVuayA9IHJlcXVpcmUoXCIuL2lzLXRodW5rXCIpO1xuXG4gICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IGhhbmRsZVRodW5rO1xuXG4gICAgICAgICAgICBmdW5jdGlvbiBoYW5kbGVUaHVuayhhLCBiKSB7XG4gICAgICAgICAgICAgICAgdmFyIHJlbmRlcmVkQSA9IGE7XG4gICAgICAgICAgICAgICAgdmFyIHJlbmRlcmVkQiA9IGI7XG5cbiAgICAgICAgICAgICAgICBpZiAoaXNUaHVuayhiKSkge1xuICAgICAgICAgICAgICAgICAgICByZW5kZXJlZEIgPSByZW5kZXJUaHVuayhiLCBhKTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICBpZiAoaXNUaHVuayhhKSkge1xuICAgICAgICAgICAgICAgICAgICByZW5kZXJlZEEgPSByZW5kZXJUaHVuayhhLCBudWxsKTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgICAgICAgICBhOiByZW5kZXJlZEEsXG4gICAgICAgICAgICAgICAgICAgIGI6IHJlbmRlcmVkQlxuICAgICAgICAgICAgICAgIH07XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIHJlbmRlclRodW5rKHRodW5rLCBwcmV2aW91cykge1xuICAgICAgICAgICAgICAgIHZhciByZW5kZXJlZFRodW5rID0gdGh1bmsudm5vZGU7XG5cbiAgICAgICAgICAgICAgICBpZiAoIXJlbmRlcmVkVGh1bmspIHtcbiAgICAgICAgICAgICAgICAgICAgcmVuZGVyZWRUaHVuayA9IHRodW5rLnZub2RlID0gdGh1bmsucmVuZGVyKHByZXZpb3VzKTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICBpZiAoIShpc1ZOb2RlKHJlbmRlcmVkVGh1bmspIHx8IGlzVlRleHQocmVuZGVyZWRUaHVuaykgfHwgaXNXaWRnZXQocmVuZGVyZWRUaHVuaykpKSB7XG4gICAgICAgICAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcihcInRodW5rIGRpZCBub3QgcmV0dXJuIGEgdmFsaWQgbm9kZVwiKTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICByZXR1cm4gcmVuZGVyZWRUaHVuaztcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSwgeyBcIi4vaXMtdGh1bmtcIjogMjUsIFwiLi9pcy12bm9kZVwiOiAyNywgXCIuL2lzLXZ0ZXh0XCI6IDI4LCBcIi4vaXMtd2lkZ2V0XCI6IDI5IH1dLCAyNTogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHtcbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gaXNUaHVuaztcblxuICAgICAgICAgICAgZnVuY3Rpb24gaXNUaHVuayh0KSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHQgJiYgdC50eXBlID09PSBcIlRodW5rXCI7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0sIHt9XSwgMjY6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IGlzSG9vaztcblxuICAgICAgICAgICAgZnVuY3Rpb24gaXNIb29rKGhvb2spIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gaG9vayAmJiAodHlwZW9mIGhvb2suaG9vayA9PT0gXCJmdW5jdGlvblwiICYmICFob29rLmhhc093blByb3BlcnR5KFwiaG9va1wiKSB8fCB0eXBlb2YgaG9vay51bmhvb2sgPT09IFwiZnVuY3Rpb25cIiAmJiAhaG9vay5oYXNPd25Qcm9wZXJ0eShcInVuaG9va1wiKSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0sIHt9XSwgMjc6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICB2YXIgdmVyc2lvbiA9IHJlcXVpcmUoXCIuL3ZlcnNpb25cIik7XG5cbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gaXNWaXJ0dWFsTm9kZTtcblxuICAgICAgICAgICAgZnVuY3Rpb24gaXNWaXJ0dWFsTm9kZSh4KSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHggJiYgeC50eXBlID09PSBcIlZpcnR1YWxOb2RlXCIgJiYgeC52ZXJzaW9uID09PSB2ZXJzaW9uO1xuICAgICAgICAgICAgfVxuICAgICAgICB9LCB7IFwiLi92ZXJzaW9uXCI6IDMwIH1dLCAyODogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHtcbiAgICAgICAgICAgIHZhciB2ZXJzaW9uID0gcmVxdWlyZShcIi4vdmVyc2lvblwiKTtcblxuICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBpc1ZpcnR1YWxUZXh0O1xuXG4gICAgICAgICAgICBmdW5jdGlvbiBpc1ZpcnR1YWxUZXh0KHgpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4geCAmJiB4LnR5cGUgPT09IFwiVmlydHVhbFRleHRcIiAmJiB4LnZlcnNpb24gPT09IHZlcnNpb247XG4gICAgICAgICAgICB9XG4gICAgICAgIH0sIHsgXCIuL3ZlcnNpb25cIjogMzAgfV0sIDI5OiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge1xuICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBpc1dpZGdldDtcblxuICAgICAgICAgICAgZnVuY3Rpb24gaXNXaWRnZXQodykge1xuICAgICAgICAgICAgICAgIHJldHVybiB3ICYmIHcudHlwZSA9PT0gXCJXaWRnZXRcIjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSwge31dLCAzMDogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHtcbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gXCIyXCI7XG4gICAgICAgIH0sIHt9XSwgMzE6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICB2YXIgdmVyc2lvbiA9IHJlcXVpcmUoXCIuL3ZlcnNpb25cIik7XG4gICAgICAgICAgICB2YXIgaXNWTm9kZSA9IHJlcXVpcmUoXCIuL2lzLXZub2RlXCIpO1xuICAgICAgICAgICAgdmFyIGlzV2lkZ2V0ID0gcmVxdWlyZShcIi4vaXMtd2lkZ2V0XCIpO1xuICAgICAgICAgICAgdmFyIGlzVGh1bmsgPSByZXF1aXJlKFwiLi9pcy10aHVua1wiKTtcbiAgICAgICAgICAgIHZhciBpc1ZIb29rID0gcmVxdWlyZShcIi4vaXMtdmhvb2tcIik7XG5cbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gVmlydHVhbE5vZGU7XG5cbiAgICAgICAgICAgIHZhciBub1Byb3BlcnRpZXMgPSB7fTtcbiAgICAgICAgICAgIHZhciBub0NoaWxkcmVuID0gW107XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIFZpcnR1YWxOb2RlKHRhZ05hbWUsIHByb3BlcnRpZXMsIGNoaWxkcmVuLCBrZXksIG5hbWVzcGFjZSkge1xuICAgICAgICAgICAgICAgIHRoaXMudGFnTmFtZSA9IHRhZ05hbWU7XG4gICAgICAgICAgICAgICAgdGhpcy5wcm9wZXJ0aWVzID0gcHJvcGVydGllcyB8fCBub1Byb3BlcnRpZXM7XG4gICAgICAgICAgICAgICAgdGhpcy5jaGlsZHJlbiA9IGNoaWxkcmVuIHx8IG5vQ2hpbGRyZW47XG4gICAgICAgICAgICAgICAgdGhpcy5rZXkgPSBrZXkgIT0gbnVsbCA/IFN0cmluZyhrZXkpIDogdW5kZWZpbmVkO1xuICAgICAgICAgICAgICAgIHRoaXMubmFtZXNwYWNlID0gdHlwZW9mIG5hbWVzcGFjZSA9PT0gXCJzdHJpbmdcIiA/IG5hbWVzcGFjZSA6IG51bGw7XG5cbiAgICAgICAgICAgICAgICB2YXIgY291bnQgPSBjaGlsZHJlbiAmJiBjaGlsZHJlbi5sZW5ndGggfHwgMDtcbiAgICAgICAgICAgICAgICB2YXIgZGVzY2VuZGFudHMgPSAwO1xuICAgICAgICAgICAgICAgIHZhciBoYXNXaWRnZXRzID0gZmFsc2U7XG4gICAgICAgICAgICAgICAgdmFyIGhhc1RodW5rcyA9IGZhbHNlO1xuICAgICAgICAgICAgICAgIHZhciBkZXNjZW5kYW50SG9va3MgPSBmYWxzZTtcbiAgICAgICAgICAgICAgICB2YXIgaG9va3M7XG5cbiAgICAgICAgICAgICAgICBmb3IgKHZhciBwcm9wTmFtZSBpbiBwcm9wZXJ0aWVzKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmIChwcm9wZXJ0aWVzLmhhc093blByb3BlcnR5KHByb3BOYW1lKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgdmFyIHByb3BlcnR5ID0gcHJvcGVydGllc1twcm9wTmFtZV07XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoaXNWSG9vayhwcm9wZXJ0eSkgJiYgcHJvcGVydHkudW5ob29rKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKCFob29rcykge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBob29rcyA9IHt9O1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGhvb2tzW3Byb3BOYW1lXSA9IHByb3BlcnR5O1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCBjb3VudDsgaSsrKSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciBjaGlsZCA9IGNoaWxkcmVuW2ldO1xuICAgICAgICAgICAgICAgICAgICBpZiAoaXNWTm9kZShjaGlsZCkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGRlc2NlbmRhbnRzICs9IGNoaWxkLmNvdW50IHx8IDA7XG5cbiAgICAgICAgICAgICAgICAgICAgICAgIGlmICghaGFzV2lkZ2V0cyAmJiBjaGlsZC5oYXNXaWRnZXRzKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaGFzV2lkZ2V0cyA9IHRydWU7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgICAgIGlmICghaGFzVGh1bmtzICYmIGNoaWxkLmhhc1RodW5rcykge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGhhc1RodW5rcyA9IHRydWU7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgICAgIGlmICghZGVzY2VuZGFudEhvb2tzICYmIChjaGlsZC5ob29rcyB8fCBjaGlsZC5kZXNjZW5kYW50SG9va3MpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgZGVzY2VuZGFudEhvb2tzID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIGlmICghaGFzV2lkZ2V0cyAmJiBpc1dpZGdldChjaGlsZCkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmICh0eXBlb2YgY2hpbGQuZGVzdHJveSA9PT0gXCJmdW5jdGlvblwiKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaGFzV2lkZ2V0cyA9IHRydWU7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoIWhhc1RodW5rcyAmJiBpc1RodW5rKGNoaWxkKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgaGFzVGh1bmtzID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHRoaXMuY291bnQgPSBjb3VudCArIGRlc2NlbmRhbnRzO1xuICAgICAgICAgICAgICAgIHRoaXMuaGFzV2lkZ2V0cyA9IGhhc1dpZGdldHM7XG4gICAgICAgICAgICAgICAgdGhpcy5oYXNUaHVua3MgPSBoYXNUaHVua3M7XG4gICAgICAgICAgICAgICAgdGhpcy5ob29rcyA9IGhvb2tzO1xuICAgICAgICAgICAgICAgIHRoaXMuZGVzY2VuZGFudEhvb2tzID0gZGVzY2VuZGFudEhvb2tzO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBWaXJ0dWFsTm9kZS5wcm90b3R5cGUudmVyc2lvbiA9IHZlcnNpb247XG4gICAgICAgICAgICBWaXJ0dWFsTm9kZS5wcm90b3R5cGUudHlwZSA9IFwiVmlydHVhbE5vZGVcIjtcbiAgICAgICAgfSwgeyBcIi4vaXMtdGh1bmtcIjogMjUsIFwiLi9pcy12aG9va1wiOiAyNiwgXCIuL2lzLXZub2RlXCI6IDI3LCBcIi4vaXMtd2lkZ2V0XCI6IDI5LCBcIi4vdmVyc2lvblwiOiAzMCB9XSwgMzI6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICB2YXIgdmVyc2lvbiA9IHJlcXVpcmUoXCIuL3ZlcnNpb25cIik7XG5cbiAgICAgICAgICAgIFZpcnR1YWxQYXRjaC5OT05FID0gMDtcbiAgICAgICAgICAgIFZpcnR1YWxQYXRjaC5WVEVYVCA9IDE7XG4gICAgICAgICAgICBWaXJ0dWFsUGF0Y2guVk5PREUgPSAyO1xuICAgICAgICAgICAgVmlydHVhbFBhdGNoLldJREdFVCA9IDM7XG4gICAgICAgICAgICBWaXJ0dWFsUGF0Y2guUFJPUFMgPSA0O1xuICAgICAgICAgICAgVmlydHVhbFBhdGNoLk9SREVSID0gNTtcbiAgICAgICAgICAgIFZpcnR1YWxQYXRjaC5JTlNFUlQgPSA2O1xuICAgICAgICAgICAgVmlydHVhbFBhdGNoLlJFTU9WRSA9IDc7XG4gICAgICAgICAgICBWaXJ0dWFsUGF0Y2guVEhVTksgPSA4O1xuXG4gICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IFZpcnR1YWxQYXRjaDtcblxuICAgICAgICAgICAgZnVuY3Rpb24gVmlydHVhbFBhdGNoKHR5cGUsIHZOb2RlLCBwYXRjaCkge1xuICAgICAgICAgICAgICAgIHRoaXMudHlwZSA9IE51bWJlcih0eXBlKTtcbiAgICAgICAgICAgICAgICB0aGlzLnZOb2RlID0gdk5vZGU7XG4gICAgICAgICAgICAgICAgdGhpcy5wYXRjaCA9IHBhdGNoO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBWaXJ0dWFsUGF0Y2gucHJvdG90eXBlLnZlcnNpb24gPSB2ZXJzaW9uO1xuICAgICAgICAgICAgVmlydHVhbFBhdGNoLnByb3RvdHlwZS50eXBlID0gXCJWaXJ0dWFsUGF0Y2hcIjtcbiAgICAgICAgfSwgeyBcIi4vdmVyc2lvblwiOiAzMCB9XSwgMzM6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICB2YXIgdmVyc2lvbiA9IHJlcXVpcmUoXCIuL3ZlcnNpb25cIik7XG5cbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gVmlydHVhbFRleHQ7XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIFZpcnR1YWxUZXh0KHRleHQpIHtcbiAgICAgICAgICAgICAgICB0aGlzLnRleHQgPSBTdHJpbmcodGV4dCk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIFZpcnR1YWxUZXh0LnByb3RvdHlwZS52ZXJzaW9uID0gdmVyc2lvbjtcbiAgICAgICAgICAgIFZpcnR1YWxUZXh0LnByb3RvdHlwZS50eXBlID0gXCJWaXJ0dWFsVGV4dFwiO1xuICAgICAgICB9LCB7IFwiLi92ZXJzaW9uXCI6IDMwIH1dLCAzNDogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHtcbiAgICAgICAgICAgIHZhciBpc09iamVjdCA9IHJlcXVpcmUoXCJpcy1vYmplY3RcIik7XG4gICAgICAgICAgICB2YXIgaXNIb29rID0gcmVxdWlyZShcIi4uL3Zub2RlL2lzLXZob29rXCIpO1xuXG4gICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IGRpZmZQcm9wcztcblxuICAgICAgICAgICAgZnVuY3Rpb24gZGlmZlByb3BzKGEsIGIpIHtcbiAgICAgICAgICAgICAgICB2YXIgZGlmZjtcblxuICAgICAgICAgICAgICAgIGZvciAodmFyIGFLZXkgaW4gYSkge1xuICAgICAgICAgICAgICAgICAgICBpZiAoIShhS2V5IGluIGIpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBkaWZmID0gZGlmZiB8fCB7fTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGRpZmZbYUtleV0gPSB1bmRlZmluZWQ7XG4gICAgICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgICAgICB2YXIgYVZhbHVlID0gYVthS2V5XTtcbiAgICAgICAgICAgICAgICAgICAgdmFyIGJWYWx1ZSA9IGJbYUtleV07XG5cbiAgICAgICAgICAgICAgICAgICAgaWYgKGFWYWx1ZSA9PT0gYlZhbHVlKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBjb250aW51ZTtcbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIGlmIChpc09iamVjdChhVmFsdWUpICYmIGlzT2JqZWN0KGJWYWx1ZSkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChnZXRQcm90b3R5cGUoYlZhbHVlKSAhPT0gZ2V0UHJvdG90eXBlKGFWYWx1ZSkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBkaWZmID0gZGlmZiB8fCB7fTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBkaWZmW2FLZXldID0gYlZhbHVlO1xuICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIGlmIChpc0hvb2soYlZhbHVlKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRpZmYgPSBkaWZmIHx8IHt9O1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRpZmZbYUtleV0gPSBiVmFsdWU7XG4gICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZhciBvYmplY3REaWZmID0gZGlmZlByb3BzKGFWYWx1ZSwgYlZhbHVlKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAob2JqZWN0RGlmZikge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBkaWZmID0gZGlmZiB8fCB7fTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZGlmZlthS2V5XSA9IG9iamVjdERpZmY7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgZGlmZiA9IGRpZmYgfHwge307XG4gICAgICAgICAgICAgICAgICAgICAgICBkaWZmW2FLZXldID0gYlZhbHVlO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgZm9yICh2YXIgYktleSBpbiBiKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmICghKGJLZXkgaW4gYSkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGRpZmYgPSBkaWZmIHx8IHt9O1xuICAgICAgICAgICAgICAgICAgICAgICAgZGlmZltiS2V5XSA9IGJbYktleV07XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICByZXR1cm4gZGlmZjtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZnVuY3Rpb24gZ2V0UHJvdG90eXBlKHZhbHVlKSB7XG4gICAgICAgICAgICAgICAgaWYgKE9iamVjdC5nZXRQcm90b3R5cGVPZikge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gT2JqZWN0LmdldFByb3RvdHlwZU9mKHZhbHVlKTtcbiAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKHZhbHVlLl9fcHJvdG9fXykge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gdmFsdWUuX19wcm90b19fO1xuICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAodmFsdWUuY29uc3RydWN0b3IpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHZhbHVlLmNvbnN0cnVjdG9yLnByb3RvdHlwZTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH0sIHsgXCIuLi92bm9kZS9pcy12aG9va1wiOiAyNiwgXCJpcy1vYmplY3RcIjogMTEgfV0sIDM1OiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge1xuICAgICAgICAgICAgdmFyIGlzQXJyYXkgPSByZXF1aXJlKFwieC1pcy1hcnJheVwiKTtcblxuICAgICAgICAgICAgdmFyIFZQYXRjaCA9IHJlcXVpcmUoXCIuLi92bm9kZS92cGF0Y2hcIik7XG4gICAgICAgICAgICB2YXIgaXNWTm9kZSA9IHJlcXVpcmUoXCIuLi92bm9kZS9pcy12bm9kZVwiKTtcbiAgICAgICAgICAgIHZhciBpc1ZUZXh0ID0gcmVxdWlyZShcIi4uL3Zub2RlL2lzLXZ0ZXh0XCIpO1xuICAgICAgICAgICAgdmFyIGlzV2lkZ2V0ID0gcmVxdWlyZShcIi4uL3Zub2RlL2lzLXdpZGdldFwiKTtcbiAgICAgICAgICAgIHZhciBpc1RodW5rID0gcmVxdWlyZShcIi4uL3Zub2RlL2lzLXRodW5rXCIpO1xuICAgICAgICAgICAgdmFyIGhhbmRsZVRodW5rID0gcmVxdWlyZShcIi4uL3Zub2RlL2hhbmRsZS10aHVua1wiKTtcblxuICAgICAgICAgICAgdmFyIGRpZmZQcm9wcyA9IHJlcXVpcmUoXCIuL2RpZmYtcHJvcHNcIik7XG5cbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gZGlmZjtcblxuICAgICAgICAgICAgZnVuY3Rpb24gZGlmZihhLCBiKSB7XG4gICAgICAgICAgICAgICAgdmFyIHBhdGNoID0geyBhOiBhIH07XG4gICAgICAgICAgICAgICAgd2FsayhhLCBiLCBwYXRjaCwgMCk7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHBhdGNoO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBmdW5jdGlvbiB3YWxrKGEsIGIsIHBhdGNoLCBpbmRleCkge1xuICAgICAgICAgICAgICAgIGlmIChhID09PSBiKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICB2YXIgYXBwbHkgPSBwYXRjaFtpbmRleF07XG4gICAgICAgICAgICAgICAgdmFyIGFwcGx5Q2xlYXIgPSBmYWxzZTtcblxuICAgICAgICAgICAgICAgIGlmIChpc1RodW5rKGEpIHx8IGlzVGh1bmsoYikpIHtcbiAgICAgICAgICAgICAgICAgICAgdGh1bmtzKGEsIGIsIHBhdGNoLCBpbmRleCk7XG4gICAgICAgICAgICAgICAgfSBlbHNlIGlmIChiID09IG51bGwpIHtcblxuICAgICAgICAgICAgICAgICAgICAvLyBJZiBhIGlzIGEgd2lkZ2V0IHdlIHdpbGwgYWRkIGEgcmVtb3ZlIHBhdGNoIGZvciBpdFxuICAgICAgICAgICAgICAgICAgICAvLyBPdGhlcndpc2UgYW55IGNoaWxkIHdpZGdldHMvaG9va3MgbXVzdCBiZSBkZXN0cm95ZWQuXG4gICAgICAgICAgICAgICAgICAgIC8vIFRoaXMgcHJldmVudHMgYWRkaW5nIHR3byByZW1vdmUgcGF0Y2hlcyBmb3IgYSB3aWRnZXQuXG4gICAgICAgICAgICAgICAgICAgIGlmICghaXNXaWRnZXQoYSkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGNsZWFyU3RhdGUoYSwgcGF0Y2gsIGluZGV4KTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGFwcGx5ID0gcGF0Y2hbaW5kZXhdO1xuICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgYXBwbHkgPSBhcHBlbmRQYXRjaChhcHBseSwgbmV3IFZQYXRjaChWUGF0Y2guUkVNT1ZFLCBhLCBiKSk7XG4gICAgICAgICAgICAgICAgfSBlbHNlIGlmIChpc1ZOb2RlKGIpKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmIChpc1ZOb2RlKGEpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoYS50YWdOYW1lID09PSBiLnRhZ05hbWUgJiYgYS5uYW1lc3BhY2UgPT09IGIubmFtZXNwYWNlICYmIGEua2V5ID09PSBiLmtleSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZhciBwcm9wc1BhdGNoID0gZGlmZlByb3BzKGEucHJvcGVydGllcywgYi5wcm9wZXJ0aWVzKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAocHJvcHNQYXRjaCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBhcHBseSA9IGFwcGVuZFBhdGNoKGFwcGx5LCBuZXcgVlBhdGNoKFZQYXRjaC5QUk9QUywgYSwgcHJvcHNQYXRjaCkpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBhcHBseSA9IGRpZmZDaGlsZHJlbihhLCBiLCBwYXRjaCwgYXBwbHksIGluZGV4KTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgYXBwbHkgPSBhcHBlbmRQYXRjaChhcHBseSwgbmV3IFZQYXRjaChWUGF0Y2guVk5PREUsIGEsIGIpKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBhcHBseUNsZWFyID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGFwcGx5ID0gYXBwZW5kUGF0Y2goYXBwbHksIG5ldyBWUGF0Y2goVlBhdGNoLlZOT0RFLCBhLCBiKSk7XG4gICAgICAgICAgICAgICAgICAgICAgICBhcHBseUNsZWFyID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoaXNWVGV4dChiKSkge1xuICAgICAgICAgICAgICAgICAgICBpZiAoIWlzVlRleHQoYSkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGFwcGx5ID0gYXBwZW5kUGF0Y2goYXBwbHksIG5ldyBWUGF0Y2goVlBhdGNoLlZURVhULCBhLCBiKSk7XG4gICAgICAgICAgICAgICAgICAgICAgICBhcHBseUNsZWFyID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIGlmIChhLnRleHQgIT09IGIudGV4dCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgYXBwbHkgPSBhcHBlbmRQYXRjaChhcHBseSwgbmV3IFZQYXRjaChWUGF0Y2guVlRFWFQsIGEsIGIpKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoaXNXaWRnZXQoYikpIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKCFpc1dpZGdldChhKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgYXBwbHlDbGVhciA9IHRydWU7XG4gICAgICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgICAgICBhcHBseSA9IGFwcGVuZFBhdGNoKGFwcGx5LCBuZXcgVlBhdGNoKFZQYXRjaC5XSURHRVQsIGEsIGIpKTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICBpZiAoYXBwbHkpIHtcbiAgICAgICAgICAgICAgICAgICAgcGF0Y2hbaW5kZXhdID0gYXBwbHk7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgaWYgKGFwcGx5Q2xlYXIpIHtcbiAgICAgICAgICAgICAgICAgICAgY2xlYXJTdGF0ZShhLCBwYXRjaCwgaW5kZXgpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZnVuY3Rpb24gZGlmZkNoaWxkcmVuKGEsIGIsIHBhdGNoLCBhcHBseSwgaW5kZXgpIHtcbiAgICAgICAgICAgICAgICB2YXIgYUNoaWxkcmVuID0gYS5jaGlsZHJlbjtcbiAgICAgICAgICAgICAgICB2YXIgb3JkZXJlZFNldCA9IHJlb3JkZXIoYUNoaWxkcmVuLCBiLmNoaWxkcmVuKTtcbiAgICAgICAgICAgICAgICB2YXIgYkNoaWxkcmVuID0gb3JkZXJlZFNldC5jaGlsZHJlbjtcblxuICAgICAgICAgICAgICAgIHZhciBhTGVuID0gYUNoaWxkcmVuLmxlbmd0aDtcbiAgICAgICAgICAgICAgICB2YXIgYkxlbiA9IGJDaGlsZHJlbi5sZW5ndGg7XG4gICAgICAgICAgICAgICAgdmFyIGxlbiA9IGFMZW4gPiBiTGVuID8gYUxlbiA6IGJMZW47XG5cbiAgICAgICAgICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IGxlbjsgaSsrKSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciBsZWZ0Tm9kZSA9IGFDaGlsZHJlbltpXTtcbiAgICAgICAgICAgICAgICAgICAgdmFyIHJpZ2h0Tm9kZSA9IGJDaGlsZHJlbltpXTtcbiAgICAgICAgICAgICAgICAgICAgaW5kZXggKz0gMTtcblxuICAgICAgICAgICAgICAgICAgICBpZiAoIWxlZnROb2RlKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAocmlnaHROb2RlKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gRXhjZXNzIG5vZGVzIGluIGIgbmVlZCB0byBiZSBhZGRlZFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGFwcGx5ID0gYXBwZW5kUGF0Y2goYXBwbHksIG5ldyBWUGF0Y2goVlBhdGNoLklOU0VSVCwgbnVsbCwgcmlnaHROb2RlKSk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICB3YWxrKGxlZnROb2RlLCByaWdodE5vZGUsIHBhdGNoLCBpbmRleCk7XG4gICAgICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgICAgICBpZiAoaXNWTm9kZShsZWZ0Tm9kZSkgJiYgbGVmdE5vZGUuY291bnQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGluZGV4ICs9IGxlZnROb2RlLmNvdW50O1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgaWYgKG9yZGVyZWRTZXQubW92ZXMpIHtcbiAgICAgICAgICAgICAgICAgICAgLy8gUmVvcmRlciBub2RlcyBsYXN0XG4gICAgICAgICAgICAgICAgICAgIGFwcGx5ID0gYXBwZW5kUGF0Y2goYXBwbHksIG5ldyBWUGF0Y2goVlBhdGNoLk9SREVSLCBhLCBvcmRlcmVkU2V0Lm1vdmVzKSk7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgcmV0dXJuIGFwcGx5O1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBmdW5jdGlvbiBjbGVhclN0YXRlKHZOb2RlLCBwYXRjaCwgaW5kZXgpIHtcbiAgICAgICAgICAgICAgICAvLyBUT0RPOiBNYWtlIHRoaXMgYSBzaW5nbGUgd2Fsaywgbm90IHR3b1xuICAgICAgICAgICAgICAgIHVuaG9vayh2Tm9kZSwgcGF0Y2gsIGluZGV4KTtcbiAgICAgICAgICAgICAgICBkZXN0cm95V2lkZ2V0cyh2Tm9kZSwgcGF0Y2gsIGluZGV4KTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgLy8gUGF0Y2ggcmVjb3JkcyBmb3IgYWxsIGRlc3Ryb3llZCB3aWRnZXRzIG11c3QgYmUgYWRkZWQgYmVjYXVzZSB3ZSBuZWVkXG4gICAgICAgICAgICAvLyBhIERPTSBub2RlIHJlZmVyZW5jZSBmb3IgdGhlIGRlc3Ryb3kgZnVuY3Rpb25cbiAgICAgICAgICAgIGZ1bmN0aW9uIGRlc3Ryb3lXaWRnZXRzKHZOb2RlLCBwYXRjaCwgaW5kZXgpIHtcbiAgICAgICAgICAgICAgICBpZiAoaXNXaWRnZXQodk5vZGUpKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmICh0eXBlb2Ygdk5vZGUuZGVzdHJveSA9PT0gXCJmdW5jdGlvblwiKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBwYXRjaFtpbmRleF0gPSBhcHBlbmRQYXRjaChwYXRjaFtpbmRleF0sIG5ldyBWUGF0Y2goVlBhdGNoLlJFTU9WRSwgdk5vZGUsIG51bGwpKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoaXNWTm9kZSh2Tm9kZSkgJiYgKHZOb2RlLmhhc1dpZGdldHMgfHwgdk5vZGUuaGFzVGh1bmtzKSkge1xuICAgICAgICAgICAgICAgICAgICB2YXIgY2hpbGRyZW4gPSB2Tm9kZS5jaGlsZHJlbjtcbiAgICAgICAgICAgICAgICAgICAgdmFyIGxlbiA9IGNoaWxkcmVuLmxlbmd0aDtcbiAgICAgICAgICAgICAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCBsZW47IGkrKykge1xuICAgICAgICAgICAgICAgICAgICAgICAgdmFyIGNoaWxkID0gY2hpbGRyZW5baV07XG4gICAgICAgICAgICAgICAgICAgICAgICBpbmRleCArPSAxO1xuXG4gICAgICAgICAgICAgICAgICAgICAgICBkZXN0cm95V2lkZ2V0cyhjaGlsZCwgcGF0Y2gsIGluZGV4KTtcblxuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGlzVk5vZGUoY2hpbGQpICYmIGNoaWxkLmNvdW50KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaW5kZXggKz0gY2hpbGQuY291bnQ7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKGlzVGh1bmsodk5vZGUpKSB7XG4gICAgICAgICAgICAgICAgICAgIHRodW5rcyh2Tm9kZSwgbnVsbCwgcGF0Y2gsIGluZGV4KTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIC8vIENyZWF0ZSBhIHN1Yi1wYXRjaCBmb3IgdGh1bmtzXG4gICAgICAgICAgICBmdW5jdGlvbiB0aHVua3MoYSwgYiwgcGF0Y2gsIGluZGV4KSB7XG4gICAgICAgICAgICAgICAgdmFyIG5vZGVzID0gaGFuZGxlVGh1bmsoYSwgYik7XG4gICAgICAgICAgICAgICAgdmFyIHRodW5rUGF0Y2ggPSBkaWZmKG5vZGVzLmEsIG5vZGVzLmIpO1xuICAgICAgICAgICAgICAgIGlmIChoYXNQYXRjaGVzKHRodW5rUGF0Y2gpKSB7XG4gICAgICAgICAgICAgICAgICAgIHBhdGNoW2luZGV4XSA9IG5ldyBWUGF0Y2goVlBhdGNoLlRIVU5LLCBudWxsLCB0aHVua1BhdGNoKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIGhhc1BhdGNoZXMocGF0Y2gpIHtcbiAgICAgICAgICAgICAgICBmb3IgKHZhciBpbmRleCBpbiBwYXRjaCkge1xuICAgICAgICAgICAgICAgICAgICBpZiAoaW5kZXggIT09IFwiYVwiKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgLy8gRXhlY3V0ZSBob29rcyB3aGVuIHR3byBub2RlcyBhcmUgaWRlbnRpY2FsXG4gICAgICAgICAgICBmdW5jdGlvbiB1bmhvb2sodk5vZGUsIHBhdGNoLCBpbmRleCkge1xuICAgICAgICAgICAgICAgIGlmIChpc1ZOb2RlKHZOb2RlKSkge1xuICAgICAgICAgICAgICAgICAgICBpZiAodk5vZGUuaG9va3MpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHBhdGNoW2luZGV4XSA9IGFwcGVuZFBhdGNoKHBhdGNoW2luZGV4XSwgbmV3IFZQYXRjaChWUGF0Y2guUFJPUFMsIHZOb2RlLCB1bmRlZmluZWRLZXlzKHZOb2RlLmhvb2tzKSkpO1xuICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgaWYgKHZOb2RlLmRlc2NlbmRhbnRIb29rcyB8fCB2Tm9kZS5oYXNUaHVua3MpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHZhciBjaGlsZHJlbiA9IHZOb2RlLmNoaWxkcmVuO1xuICAgICAgICAgICAgICAgICAgICAgICAgdmFyIGxlbiA9IGNoaWxkcmVuLmxlbmd0aDtcbiAgICAgICAgICAgICAgICAgICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgbGVuOyBpKyspIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB2YXIgY2hpbGQgPSBjaGlsZHJlbltpXTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpbmRleCArPSAxO1xuXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdW5ob29rKGNoaWxkLCBwYXRjaCwgaW5kZXgpO1xuXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGlzVk5vZGUoY2hpbGQpICYmIGNoaWxkLmNvdW50KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGluZGV4ICs9IGNoaWxkLmNvdW50O1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoaXNUaHVuayh2Tm9kZSkpIHtcbiAgICAgICAgICAgICAgICAgICAgdGh1bmtzKHZOb2RlLCBudWxsLCBwYXRjaCwgaW5kZXgpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZnVuY3Rpb24gdW5kZWZpbmVkS2V5cyhvYmopIHtcbiAgICAgICAgICAgICAgICB2YXIgcmVzdWx0ID0ge307XG5cbiAgICAgICAgICAgICAgICBmb3IgKHZhciBrZXkgaW4gb2JqKSB7XG4gICAgICAgICAgICAgICAgICAgIHJlc3VsdFtrZXldID0gdW5kZWZpbmVkO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHJldHVybiByZXN1bHQ7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIC8vIExpc3QgZGlmZiwgbmFpdmUgbGVmdCB0byByaWdodCByZW9yZGVyaW5nXG4gICAgICAgICAgICBmdW5jdGlvbiByZW9yZGVyKGFDaGlsZHJlbiwgYkNoaWxkcmVuKSB7XG4gICAgICAgICAgICAgICAgLy8gTyhNKSB0aW1lLCBPKE0pIG1lbW9yeVxuICAgICAgICAgICAgICAgIHZhciBiQ2hpbGRJbmRleCA9IGtleUluZGV4KGJDaGlsZHJlbik7XG4gICAgICAgICAgICAgICAgdmFyIGJLZXlzID0gYkNoaWxkSW5kZXgua2V5cztcbiAgICAgICAgICAgICAgICB2YXIgYkZyZWUgPSBiQ2hpbGRJbmRleC5mcmVlO1xuXG4gICAgICAgICAgICAgICAgaWYgKGJGcmVlLmxlbmd0aCA9PT0gYkNoaWxkcmVuLmxlbmd0aCkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgICAgICAgICAgICAgY2hpbGRyZW46IGJDaGlsZHJlbixcbiAgICAgICAgICAgICAgICAgICAgICAgIG1vdmVzOiBudWxsXG4gICAgICAgICAgICAgICAgICAgIH07XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgLy8gTyhOKSB0aW1lLCBPKE4pIG1lbW9yeVxuICAgICAgICAgICAgICAgIHZhciBhQ2hpbGRJbmRleCA9IGtleUluZGV4KGFDaGlsZHJlbik7XG4gICAgICAgICAgICAgICAgdmFyIGFLZXlzID0gYUNoaWxkSW5kZXgua2V5cztcbiAgICAgICAgICAgICAgICB2YXIgYUZyZWUgPSBhQ2hpbGRJbmRleC5mcmVlO1xuXG4gICAgICAgICAgICAgICAgaWYgKGFGcmVlLmxlbmd0aCA9PT0gYUNoaWxkcmVuLmxlbmd0aCkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgICAgICAgICAgICAgY2hpbGRyZW46IGJDaGlsZHJlbixcbiAgICAgICAgICAgICAgICAgICAgICAgIG1vdmVzOiBudWxsXG4gICAgICAgICAgICAgICAgICAgIH07XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgLy8gTyhNQVgoTiwgTSkpIG1lbW9yeVxuICAgICAgICAgICAgICAgIHZhciBuZXdDaGlsZHJlbiA9IFtdO1xuXG4gICAgICAgICAgICAgICAgdmFyIGZyZWVJbmRleCA9IDA7XG4gICAgICAgICAgICAgICAgdmFyIGZyZWVDb3VudCA9IGJGcmVlLmxlbmd0aDtcbiAgICAgICAgICAgICAgICB2YXIgZGVsZXRlZEl0ZW1zID0gMDtcblxuICAgICAgICAgICAgICAgIC8vIEl0ZXJhdGUgdGhyb3VnaCBhIGFuZCBtYXRjaCBhIG5vZGUgaW4gYlxuICAgICAgICAgICAgICAgIC8vIE8oTikgdGltZSxcbiAgICAgICAgICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IGFDaGlsZHJlbi5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgICAgICAgICB2YXIgYUl0ZW0gPSBhQ2hpbGRyZW5baV07XG4gICAgICAgICAgICAgICAgICAgIHZhciBpdGVtSW5kZXg7XG5cbiAgICAgICAgICAgICAgICAgICAgaWYgKGFJdGVtLmtleSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGJLZXlzLmhhc093blByb3BlcnR5KGFJdGVtLmtleSkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBNYXRjaCB1cCB0aGUgb2xkIGtleXNcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpdGVtSW5kZXggPSBiS2V5c1thSXRlbS5rZXldO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIG5ld0NoaWxkcmVuLnB1c2goYkNoaWxkcmVuW2l0ZW1JbmRleF0pO1xuICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBSZW1vdmUgb2xkIGtleWVkIGl0ZW1zXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaXRlbUluZGV4ID0gaSAtIGRlbGV0ZWRJdGVtcysrO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIG5ld0NoaWxkcmVuLnB1c2gobnVsbCk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAvLyBNYXRjaCB0aGUgaXRlbSBpbiBhIHdpdGggdGhlIG5leHQgZnJlZSBpdGVtIGluIGJcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChmcmVlSW5kZXggPCBmcmVlQ291bnQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpdGVtSW5kZXggPSBiRnJlZVtmcmVlSW5kZXgrK107XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgbmV3Q2hpbGRyZW4ucHVzaChiQ2hpbGRyZW5baXRlbUluZGV4XSk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIFRoZXJlIGFyZSBubyBmcmVlIGl0ZW1zIGluIGIgdG8gbWF0Y2ggd2l0aFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIHRoZSBmcmVlIGl0ZW1zIGluIGEsIHNvIHRoZSBleHRyYSBmcmVlIG5vZGVzXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gYXJlIGRlbGV0ZWQuXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaXRlbUluZGV4ID0gaSAtIGRlbGV0ZWRJdGVtcysrO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIG5ld0NoaWxkcmVuLnB1c2gobnVsbCk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICB2YXIgbGFzdEZyZWVJbmRleCA9IGZyZWVJbmRleCA+PSBiRnJlZS5sZW5ndGggPyBiQ2hpbGRyZW4ubGVuZ3RoIDogYkZyZWVbZnJlZUluZGV4XTtcblxuICAgICAgICAgICAgICAgIC8vIEl0ZXJhdGUgdGhyb3VnaCBiIGFuZCBhcHBlbmQgYW55IG5ldyBrZXlzXG4gICAgICAgICAgICAgICAgLy8gTyhNKSB0aW1lXG4gICAgICAgICAgICAgICAgZm9yICh2YXIgaiA9IDA7IGogPCBiQ2hpbGRyZW4ubGVuZ3RoOyBqKyspIHtcbiAgICAgICAgICAgICAgICAgICAgdmFyIG5ld0l0ZW0gPSBiQ2hpbGRyZW5bal07XG5cbiAgICAgICAgICAgICAgICAgICAgaWYgKG5ld0l0ZW0ua2V5KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoIWFLZXlzLmhhc093blByb3BlcnR5KG5ld0l0ZW0ua2V5KSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIEFkZCBhbnkgbmV3IGtleWVkIGl0ZW1zXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gV2UgYXJlIGFkZGluZyBuZXcgaXRlbXMgdG8gdGhlIGVuZCBhbmQgdGhlbiBzb3J0aW5nIHRoZW1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBpbiBwbGFjZS4gSW4gZnV0dXJlIHdlIHNob3VsZCBpbnNlcnQgbmV3IGl0ZW1zIGluIHBsYWNlLlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIG5ld0NoaWxkcmVuLnB1c2gobmV3SXRlbSk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoaiA+PSBsYXN0RnJlZUluZGV4KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAvLyBBZGQgYW55IGxlZnRvdmVyIG5vbi1rZXllZCBpdGVtc1xuICAgICAgICAgICAgICAgICAgICAgICAgbmV3Q2hpbGRyZW4ucHVzaChuZXdJdGVtKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHZhciBzaW11bGF0ZSA9IG5ld0NoaWxkcmVuLnNsaWNlKCk7XG4gICAgICAgICAgICAgICAgdmFyIHNpbXVsYXRlSW5kZXggPSAwO1xuICAgICAgICAgICAgICAgIHZhciByZW1vdmVzID0gW107XG4gICAgICAgICAgICAgICAgdmFyIGluc2VydHMgPSBbXTtcbiAgICAgICAgICAgICAgICB2YXIgc2ltdWxhdGVJdGVtO1xuXG4gICAgICAgICAgICAgICAgZm9yICh2YXIgayA9IDA7IGsgPCBiQ2hpbGRyZW4ubGVuZ3RoOykge1xuICAgICAgICAgICAgICAgICAgICB2YXIgd2FudGVkSXRlbSA9IGJDaGlsZHJlbltrXTtcbiAgICAgICAgICAgICAgICAgICAgc2ltdWxhdGVJdGVtID0gc2ltdWxhdGVbc2ltdWxhdGVJbmRleF07XG5cbiAgICAgICAgICAgICAgICAgICAgLy8gcmVtb3ZlIGl0ZW1zXG4gICAgICAgICAgICAgICAgICAgIHdoaWxlIChzaW11bGF0ZUl0ZW0gPT09IG51bGwgJiYgc2ltdWxhdGUubGVuZ3RoKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICByZW1vdmVzLnB1c2gocmVtb3ZlKHNpbXVsYXRlLCBzaW11bGF0ZUluZGV4LCBudWxsKSk7XG4gICAgICAgICAgICAgICAgICAgICAgICBzaW11bGF0ZUl0ZW0gPSBzaW11bGF0ZVtzaW11bGF0ZUluZGV4XTtcbiAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgIGlmICghc2ltdWxhdGVJdGVtIHx8IHNpbXVsYXRlSXRlbS5rZXkgIT09IHdhbnRlZEl0ZW0ua2V5KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAvLyBpZiB3ZSBuZWVkIGEga2V5IGluIHRoaXMgcG9zaXRpb24uLi5cbiAgICAgICAgICAgICAgICAgICAgICAgIGlmICh3YW50ZWRJdGVtLmtleSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChzaW11bGF0ZUl0ZW0gJiYgc2ltdWxhdGVJdGVtLmtleSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBpZiBhbiBpbnNlcnQgZG9lc24ndCBwdXQgdGhpcyBrZXkgaW4gcGxhY2UsIGl0IG5lZWRzIHRvIG1vdmVcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGJLZXlzW3NpbXVsYXRlSXRlbS5rZXldICE9PSBrICsgMSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmVtb3Zlcy5wdXNoKHJlbW92ZShzaW11bGF0ZSwgc2ltdWxhdGVJbmRleCwgc2ltdWxhdGVJdGVtLmtleSkpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc2ltdWxhdGVJdGVtID0gc2ltdWxhdGVbc2ltdWxhdGVJbmRleF07XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBpZiB0aGUgcmVtb3ZlIGRpZG4ndCBwdXQgdGhlIHdhbnRlZCBpdGVtIGluIHBsYWNlLCB3ZSBuZWVkIHRvIGluc2VydCBpdFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKCFzaW11bGF0ZUl0ZW0gfHwgc2ltdWxhdGVJdGVtLmtleSAhPT0gd2FudGVkSXRlbS5rZXkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpbnNlcnRzLnB1c2goeyBrZXk6IHdhbnRlZEl0ZW0ua2V5LCB0bzogayB9KTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIGl0ZW1zIGFyZSBtYXRjaGluZywgc28gc2tpcCBhaGVhZFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc2ltdWxhdGVJbmRleCsrO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaW5zZXJ0cy5wdXNoKHsga2V5OiB3YW50ZWRJdGVtLmtleSwgdG86IGsgfSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpbnNlcnRzLnB1c2goeyBrZXk6IHdhbnRlZEl0ZW0ua2V5LCB0bzogayB9KTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaysrO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgLy8gYSBrZXkgaW4gc2ltdWxhdGUgaGFzIG5vIG1hdGNoaW5nIHdhbnRlZCBrZXksIHJlbW92ZSBpdFxuICAgICAgICAgICAgICAgICAgICAgICAgZWxzZSBpZiAoc2ltdWxhdGVJdGVtICYmIHNpbXVsYXRlSXRlbS5rZXkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICByZW1vdmVzLnB1c2gocmVtb3ZlKHNpbXVsYXRlLCBzaW11bGF0ZUluZGV4LCBzaW11bGF0ZUl0ZW0ua2V5KSk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBzaW11bGF0ZUluZGV4Kys7XG4gICAgICAgICAgICAgICAgICAgICAgICBrKys7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAvLyByZW1vdmUgYWxsIHRoZSByZW1haW5pbmcgbm9kZXMgZnJvbSBzaW11bGF0ZVxuICAgICAgICAgICAgICAgIHdoaWxlIChzaW11bGF0ZUluZGV4IDwgc2ltdWxhdGUubGVuZ3RoKSB7XG4gICAgICAgICAgICAgICAgICAgIHNpbXVsYXRlSXRlbSA9IHNpbXVsYXRlW3NpbXVsYXRlSW5kZXhdO1xuICAgICAgICAgICAgICAgICAgICByZW1vdmVzLnB1c2gocmVtb3ZlKHNpbXVsYXRlLCBzaW11bGF0ZUluZGV4LCBzaW11bGF0ZUl0ZW0gJiYgc2ltdWxhdGVJdGVtLmtleSkpO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIC8vIElmIHRoZSBvbmx5IG1vdmVzIHdlIGhhdmUgYXJlIGRlbGV0ZXMgdGhlbiB3ZSBjYW4ganVzdFxuICAgICAgICAgICAgICAgIC8vIGxldCB0aGUgZGVsZXRlIHBhdGNoIHJlbW92ZSB0aGVzZSBpdGVtcy5cbiAgICAgICAgICAgICAgICBpZiAocmVtb3Zlcy5sZW5ndGggPT09IGRlbGV0ZWRJdGVtcyAmJiAhaW5zZXJ0cy5sZW5ndGgpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGNoaWxkcmVuOiBuZXdDaGlsZHJlbixcbiAgICAgICAgICAgICAgICAgICAgICAgIG1vdmVzOiBudWxsXG4gICAgICAgICAgICAgICAgICAgIH07XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgICAgICAgICAgY2hpbGRyZW46IG5ld0NoaWxkcmVuLFxuICAgICAgICAgICAgICAgICAgICBtb3Zlczoge1xuICAgICAgICAgICAgICAgICAgICAgICAgcmVtb3ZlczogcmVtb3ZlcyxcbiAgICAgICAgICAgICAgICAgICAgICAgIGluc2VydHM6IGluc2VydHNcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH07XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIHJlbW92ZShhcnIsIGluZGV4LCBrZXkpIHtcbiAgICAgICAgICAgICAgICBhcnIuc3BsaWNlKGluZGV4LCAxKTtcblxuICAgICAgICAgICAgICAgIHJldHVybiB7XG4gICAgICAgICAgICAgICAgICAgIGZyb206IGluZGV4LFxuICAgICAgICAgICAgICAgICAgICBrZXk6IGtleVxuICAgICAgICAgICAgICAgIH07XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIGtleUluZGV4KGNoaWxkcmVuKSB7XG4gICAgICAgICAgICAgICAgdmFyIGtleXMgPSB7fTtcbiAgICAgICAgICAgICAgICB2YXIgZnJlZSA9IFtdO1xuICAgICAgICAgICAgICAgIHZhciBsZW5ndGggPSBjaGlsZHJlbi5sZW5ndGg7XG5cbiAgICAgICAgICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IGxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciBjaGlsZCA9IGNoaWxkcmVuW2ldO1xuXG4gICAgICAgICAgICAgICAgICAgIGlmIChjaGlsZC5rZXkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGtleXNbY2hpbGQua2V5XSA9IGk7XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBmcmVlLnB1c2goaSk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgICAgICAgICBrZXlzOiBrZXlzLCAvLyBBIGhhc2ggb2Yga2V5IG5hbWUgdG8gaW5kZXhcbiAgICAgICAgICAgICAgICAgICAgZnJlZTogZnJlZSAvLyBBbiBhcnJheSBvZiB1bmtleWVkIGl0ZW0gaW5kaWNlc1xuICAgICAgICAgICAgICAgIH07XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIGFwcGVuZFBhdGNoKGFwcGx5LCBwYXRjaCkge1xuICAgICAgICAgICAgICAgIGlmIChhcHBseSkge1xuICAgICAgICAgICAgICAgICAgICBpZiAoaXNBcnJheShhcHBseSkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGFwcGx5LnB1c2gocGF0Y2gpO1xuICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgYXBwbHkgPSBbYXBwbHksIHBhdGNoXTtcbiAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBhcHBseTtcbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gcGF0Y2g7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9LCB7IFwiLi4vdm5vZGUvaGFuZGxlLXRodW5rXCI6IDI0LCBcIi4uL3Zub2RlL2lzLXRodW5rXCI6IDI1LCBcIi4uL3Zub2RlL2lzLXZub2RlXCI6IDI3LCBcIi4uL3Zub2RlL2lzLXZ0ZXh0XCI6IDI4LCBcIi4uL3Zub2RlL2lzLXdpZGdldFwiOiAyOSwgXCIuLi92bm9kZS92cGF0Y2hcIjogMzIsIFwiLi9kaWZmLXByb3BzXCI6IDM0LCBcIngtaXMtYXJyYXlcIjogMTIgfV0gfSwge30sIFs0XSkoNCk7XG59KTtcblxuLyogQGZsb3cgKi9cblxuY2xhc3MgTWFpbGJveCB7XG5cbiAgY29uc3RydWN0b3IoKSB7XG4gICAgdGhpcy5tZXNzYWdlcyA9IFtdO1xuICB9XG5cbiAgZGVsaXZlcihtZXNzYWdlKSB7XG4gICAgdGhpcy5tZXNzYWdlcy5wdXNoKG1lc3NhZ2UpO1xuICAgIHJldHVybiBtZXNzYWdlO1xuICB9XG5cbiAgZ2V0KCkge1xuICAgIHJldHVybiB0aGlzLm1lc3NhZ2VzO1xuICB9XG5cbiAgaXNFbXB0eSgpIHtcbiAgICByZXR1cm4gdGhpcy5tZXNzYWdlcy5sZW5ndGggPT09IDA7XG4gIH1cblxuICByZW1vdmVBdChpbmRleCkge1xuICAgIHRoaXMubWVzc2FnZXMuc3BsaWNlKGluZGV4LCAxKTtcbiAgfVxufVxuXG52YXIgU3RhdGVzID0ge1xuICBOT1JNQUw6IFN5bWJvbC5mb3IoXCJub3JtYWxcIiksXG4gIEtJTEw6IFN5bWJvbC5mb3IoXCJraWxsXCIpLFxuICBTVVNQRU5EOiBTeW1ib2wuZm9yKFwic3VzcGVuZFwiKSxcbiAgQ09OVElOVUU6IFN5bWJvbC5mb3IoXCJjb250aW51ZVwiKSxcbiAgUkVDRUlWRTogU3ltYm9sLmZvcihcInJlY2VpdmVcIiksXG4gIFNFTkQ6IFN5bWJvbC5mb3IoXCJzZW5kXCIpLFxuICBTTEVFUElORzogU3ltYm9sLmZvcihcInNsZWVwaW5nXCIpLFxuICBSVU5OSU5HOiBTeW1ib2wuZm9yKFwicnVubmluZ1wiKSxcbiAgU1VTUEVOREVEOiBTeW1ib2wuZm9yKFwic3VzcGVuZGVkXCIpLFxuICBTVE9QUEVEOiBTeW1ib2wuZm9yKFwic3RvcHBlZFwiKSxcbiAgU0xFRVA6IFN5bWJvbC5mb3IoXCJzbGVlcFwiKSxcbiAgRVhJVDogU3ltYm9sLmZvcihcImV4aXRcIiksXG4gIE5PTUFUQ0g6IFN5bWJvbC5mb3IoXCJub19tYXRjaFwiKVxufTtcblxuY2xhc3MgUHJvY2VzcyB7XG5cbiAgY29uc3RydWN0b3IocGlkLCBtYWlsYm94KSB7XG4gICAgdGhpcy5waWQgPSBwaWQ7XG4gICAgdGhpcy5tYWlsYm94ID0gbWFpbGJveDtcbiAgICB0aGlzLnN0YXR1cyA9IFN0YXRlcy5TVE9QUEVEO1xuICAgIHRoaXMuZGljdCA9IHt9O1xuICB9XG59XG5cbmNsYXNzIFR1cGxlIHtcblxuICBjb25zdHJ1Y3RvciguLi5hcmdzKSB7XG4gICAgdGhpcy52YWx1ZXMgPSBPYmplY3QuZnJlZXplKGFyZ3MpO1xuICAgIHRoaXMubGVuZ3RoID0gdGhpcy52YWx1ZXMubGVuZ3RoO1xuICB9XG5cbiAgZ2V0KGluZGV4KSB7XG4gICAgcmV0dXJuIHRoaXMudmFsdWVzW2luZGV4XTtcbiAgfVxuXG4gIGNvdW50KCkge1xuICAgIHJldHVybiB0aGlzLnZhbHVlcy5sZW5ndGg7XG4gIH1cblxuICBbU3ltYm9sLml0ZXJhdG9yXSgpIHtcbiAgICByZXR1cm4gdGhpcy52YWx1ZXNbU3ltYm9sLml0ZXJhdG9yXSgpO1xuICB9XG5cbiAgdG9TdHJpbmcoKSB7XG4gICAgdmFyIGksXG4gICAgICAgIHMgPSBcIlwiO1xuICAgIGZvciAoaSA9IDA7IGkgPCB0aGlzLnZhbHVlcy5sZW5ndGg7IGkrKykge1xuICAgICAgaWYgKHMgIT09IFwiXCIpIHtcbiAgICAgICAgcyArPSBcIiwgXCI7XG4gICAgICB9XG4gICAgICBzICs9IHRoaXMudmFsdWVzW2ldLnRvU3RyaW5nKCk7XG4gICAgfVxuXG4gICAgcmV0dXJuIFwie1wiICsgcyArIFwifVwiO1xuICB9XG5cbn1cblxubGV0IHByb2Nlc3NfY291bnRlciA9IC0xO1xuXG5jbGFzcyBQSUQge1xuICBjb25zdHJ1Y3RvcigpIHtcbiAgICBwcm9jZXNzX2NvdW50ZXIgPSBwcm9jZXNzX2NvdW50ZXIgKyAxO1xuICAgIHRoaXMuaWQgPSBwcm9jZXNzX2NvdW50ZXI7XG4gIH1cblxuICB0b1N0cmluZygpIHtcbiAgICByZXR1cm4gXCJQSUQjPDAuXCIgKyB0aGlzLmlkICsgXCIuMD5cIjtcbiAgfVxufVxuXG5jbGFzcyBJbnRlZ2VyIHt9XG5jbGFzcyBGbG9hdCB7fVxuXG5jbGFzcyBQcm9jZXNzU3lzdGVtIHtcblxuICBjb25zdHJ1Y3RvcigpIHtcbiAgICB0aGlzLnBpZHMgPSBuZXcgTWFwKCk7XG4gICAgdGhpcy5tYWlsYm94ZXMgPSBuZXcgTWFwKCk7XG4gICAgdGhpcy5uYW1lcyA9IG5ldyBNYXAoKTtcbiAgICB0aGlzLmxpbmtzID0gbmV3IE1hcCgpO1xuXG4gICAgdGhpcy5jdXJyZW50X3Byb2Nlc3MgPSBudWxsO1xuICAgIHRoaXMuc3VzcGVuZGVkID0gbmV3IE1hcCgpO1xuXG4gICAgdGhpcy5tYWluX3Byb2Nlc3NfcGlkID0gdGhpcy5zcGF3bigpO1xuICAgIHRoaXMuc2V0X2N1cnJlbnQodGhpcy5tYWluX3Byb2Nlc3NfcGlkKTtcbiAgfVxuXG4gIHNwYXduKCkge1xuICAgIHJldHVybiB0aGlzLmFkZF9wcm9jKGZhbHNlKS5waWQ7XG4gIH1cblxuICBzcGF3bl9saW5rKCkge1xuICAgIHJldHVybiB0aGlzLmFkZF9wcm9jKHRydWUpLnBpZDtcbiAgfVxuXG4gIGxpbmsocGlkKSB7XG4gICAgdGhpcy5saW5rcy5nZXQodGhpcy5waWQoKSkuYWRkKHBpZCk7XG4gICAgdGhpcy5saW5rcy5nZXQocGlkKS5hZGQodGhpcy5waWQoKSk7XG4gIH1cblxuICB1bmxpbmsocGlkKSB7XG4gICAgdGhpcy5saW5rcy5nZXQodGhpcy5waWQoKSkuZGVsZXRlKHBpZCk7XG4gICAgdGhpcy5saW5rcy5nZXQocGlkKS5kZWxldGUodGhpcy5waWQoKSk7XG4gIH1cblxuICBzZXRfY3VycmVudChpZCkge1xuICAgIGxldCBwaWQgPSB0aGlzLnBpZG9mKGlkKTtcbiAgICBpZiAocGlkICE9PSBudWxsKSB7XG4gICAgICB0aGlzLmN1cnJlbnRfcHJvY2VzcyA9IHRoaXMucGlkcy5nZXQocGlkKTtcbiAgICAgIHRoaXMuY3VycmVudF9wcm9jZXNzLnN0YXR1cyA9IFN0YXRlcy5SVU5OSU5HO1xuICAgIH1cbiAgfVxuXG4gIGFkZF9wcm9jKGxpbmtlZCkge1xuICAgIGxldCBuZXdwaWQgPSBuZXcgUElEKCk7XG4gICAgbGV0IG1haWxib3ggPSBuZXcgTWFpbGJveCgpO1xuICAgIGxldCBuZXdwcm9jID0gbmV3IFByb2Nlc3MobmV3cGlkLCBtYWlsYm94KTtcblxuICAgIHRoaXMucGlkcy5zZXQobmV3cGlkLCBuZXdwcm9jKTtcbiAgICB0aGlzLm1haWxib3hlcy5zZXQobmV3cGlkLCBtYWlsYm94KTtcbiAgICB0aGlzLmxpbmtzLnNldChuZXdwaWQsIG5ldyBTZXQoKSk7XG5cbiAgICBpZiAobGlua2VkKSB7XG4gICAgICB0aGlzLmxpbmsobmV3cGlkKTtcbiAgICB9XG5cbiAgICByZXR1cm4gbmV3cHJvYztcbiAgfVxuXG4gIHJlbW92ZV9wcm9jKHBpZCkge1xuICAgIHRoaXMucGlkcy5kZWxldGUocGlkKTtcbiAgICB0aGlzLnVucmVnaXN0ZXIocGlkKTtcblxuICAgIGlmICh0aGlzLmxpbmtzLmhhcyhwaWQpKSB7XG4gICAgICBmb3IgKGxldCBsaW5rcGlkIG9mIHRoaXMubGlua3MuZ2V0KHBpZCkpIHtcbiAgICAgICAgdGhpcy5saW5rcy5nZXQobGlua3BpZCkuZGVsZXRlKHBpZCk7XG4gICAgICB9XG5cbiAgICAgIHRoaXMubGlua3MuZGVsZXRlKHBpZCk7XG4gICAgfVxuICB9XG5cbiAgZXhpdChpZCkge1xuICAgIGxldCBwaWQgPSB0aGlzLnBpZG9mKGlkKTtcbiAgICB0aGlzLnJlbW92ZV9wcm9jKGlkKTtcbiAgfVxuXG4gIHJlZ2lzdGVyKG5hbWUsIHBpZCkge1xuICAgIGlmICghdGhpcy5uYW1lcy5oYXMobmFtZSkpIHtcbiAgICAgIHRoaXMubmFtZXMuc2V0KG5hbWUsIHBpZCk7XG4gICAgICByZXR1cm4gbmFtZTtcbiAgICB9IGVsc2Uge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKFwiTmFtZSBpcyBhbHJlYWR5IHJlZ2lzdGVyZWQgdG8gYW5vdGhlciBwcm9jZXNzXCIpO1xuICAgIH1cbiAgfVxuXG4gIHJlZ2lzdGVyZWQobmFtZSkge1xuICAgIHJldHVybiB0aGlzLm5hbWVzLmhhcyhuYW1lKSA/IHRoaXMubmFtZXMuZ2V0KG5hbWUpIDogbnVsbDtcbiAgfVxuXG4gIHVucmVnaXN0ZXIocGlkKSB7XG4gICAgZm9yIChsZXQgbmFtZSBvZiB0aGlzLm5hbWVzLmtleXMoKSkge1xuICAgICAgaWYgKHRoaXMubmFtZXMuaGFzKG5hbWUpICYmIHRoaXMubmFtZXMuZ2V0KG5hbWUpID09PSBwaWQpIHtcbiAgICAgICAgdGhpcy5uYW1lcy5kZWxldGUobmFtZSk7XG4gICAgICB9XG4gICAgfVxuICB9XG5cbiAgcGlkKCkge1xuICAgIHJldHVybiB0aGlzLmN1cnJlbnRfcHJvY2Vzcy5waWQ7XG4gIH1cblxuICBwaWRvZihpZCkge1xuICAgIGlmIChpZCBpbnN0YW5jZW9mIFBJRCkge1xuICAgICAgcmV0dXJuIHRoaXMucGlkcy5oYXMoaWQpID8gaWQgOiBudWxsO1xuICAgIH0gZWxzZSBpZiAoaWQgaW5zdGFuY2VvZiBQcm9jZXNzKSB7XG4gICAgICByZXR1cm4gaWQucGlkO1xuICAgIH0gZWxzZSB7XG4gICAgICBsZXQgcGlkID0gdGhpcy5yZWdpc3RlcmVkKGlkKTtcbiAgICAgIGlmIChwaWQgPT09IG51bGwpIHRocm93IFwiUHJvY2VzcyBuYW1lIG5vdCByZWdpc3RlcmVkOiBcIiArIGlkICsgXCIgKFwiICsgdHlwZW9mIGlkICsgXCIpXCI7XG4gICAgICByZXR1cm4gcGlkO1xuICAgIH1cbiAgfVxuXG4gIHB1dChpZCwga2V5LCB2YWx1ZSkge1xuICAgIGxldCBwaWQgPSB0aGlzLnBpZG9mKGlkKTtcbiAgICBsZXQgcHJvY2VzcyA9IHRoaXMucGlkcy5nZXQocGlkKTtcbiAgICBwcm9jZXNzLmRpY3Rba2V5XSA9IHZhbHVlO1xuICB9XG5cbiAgZ2V0KGlkLCBrZXkpIHtcbiAgICBsZXQgcGlkID0gdGhpcy5waWRvZihpZCk7XG4gICAgbGV0IHByb2Nlc3MgPSB0aGlzLnBpZHMuZ2V0KHBpZCk7XG5cbiAgICBpZiAoa2V5ICE9IG51bGwpIHtcbiAgICAgIHJldHVybiBwcm9jZXNzLmRpY3Rba2V5XTtcbiAgICB9IGVsc2Uge1xuICAgICAgcmV0dXJuIHByb2Nlc3MuZGljdDtcbiAgICB9XG4gIH1cblxuICBnZXRfa2V5cyhpZCkge1xuICAgIGxldCBwaWQgPSB0aGlzLnBpZG9mKGlkKTtcbiAgICBsZXQgcHJvY2VzcyA9IHRoaXMucGlkcy5nZXQocGlkKTtcblxuICAgIHJldHVybiBPYmplY3Qua2V5cyhwcm9jZXNzLmRpY3QpO1xuICB9XG5cbiAgZXJhc2UoaWQsIGtleSkge1xuICAgIGxldCBwaWQgPSB0aGlzLnBpZG9mKGlkKTtcbiAgICBsZXQgcHJvY2VzcyA9IHRoaXMucGlkcy5nZXQocGlkKTtcblxuICAgIGlmIChrZXkgIT0gbnVsbCkge1xuICAgICAgZGVsZXRlIHByb2Nlc3MuZGljdFtrZXldO1xuICAgIH0gZWxzZSB7XG4gICAgICBwcm9jZXNzLmRpY3QgPSB7fTtcbiAgICB9XG4gIH1cbn1cblxuY2xhc3MgQml0U3RyaW5nIHtcbiAgY29uc3RydWN0b3IoLi4uYXJncykge1xuICAgIHRoaXMucmF3X3ZhbHVlID0gZnVuY3Rpb24gKCkge1xuICAgICAgcmV0dXJuIE9iamVjdC5mcmVlemUoYXJncyk7XG4gICAgfTtcblxuICAgIHRoaXMudmFsdWUgPSBPYmplY3QuZnJlZXplKHRoaXMucHJvY2VzcyhhcmdzKSk7XG4gIH1cblxuICBnZXQoaW5kZXgpIHtcbiAgICByZXR1cm4gdGhpcy52YWx1ZVtpbmRleF07XG4gIH1cblxuICBjb3VudCgpIHtcbiAgICByZXR1cm4gdGhpcy52YWx1ZS5sZW5ndGg7XG4gIH1cblxuICBbU3ltYm9sLml0ZXJhdG9yXSgpIHtcbiAgICByZXR1cm4gdGhpcy52YWx1ZVtTeW1ib2wuaXRlcmF0b3JdKCk7XG4gIH1cblxuICB0b1N0cmluZygpIHtcbiAgICB2YXIgaSxcbiAgICAgICAgcyA9IFwiXCI7XG4gICAgZm9yIChpID0gMDsgaSA8IHRoaXMuY291bnQoKTsgaSsrKSB7XG4gICAgICBpZiAocyAhPT0gXCJcIikge1xuICAgICAgICBzICs9IFwiLCBcIjtcbiAgICAgIH1cbiAgICAgIHMgKz0gdGhpc1tpXS50b1N0cmluZygpO1xuICAgIH1cblxuICAgIHJldHVybiBcIjw8XCIgKyBzICsgXCI+PlwiO1xuICB9XG5cbiAgcHJvY2VzcygpIHtcbiAgICBsZXQgcHJvY2Vzc2VkX3ZhbHVlcyA9IFtdO1xuXG4gICAgdmFyIGk7XG4gICAgZm9yIChpID0gMDsgaSA8IHRoaXMucmF3X3ZhbHVlKCkubGVuZ3RoOyBpKyspIHtcbiAgICAgIGxldCBwcm9jZXNzZWRfdmFsdWUgPSB0aGlzW1wicHJvY2Vzc19cIiArIHRoaXMucmF3X3ZhbHVlKClbaV0udHlwZV0odGhpcy5yYXdfdmFsdWUoKVtpXSk7XG5cbiAgICAgIGZvciAobGV0IGF0dHIgb2YgdGhpcy5yYXdfdmFsdWUoKVtpXS5hdHRyaWJ1dGVzKSB7XG4gICAgICAgIHByb2Nlc3NlZF92YWx1ZSA9IHRoaXNbXCJwcm9jZXNzX1wiICsgYXR0cl0ocHJvY2Vzc2VkX3ZhbHVlKTtcbiAgICAgIH1cblxuICAgICAgcHJvY2Vzc2VkX3ZhbHVlcyA9IHByb2Nlc3NlZF92YWx1ZXMuY29uY2F0KHByb2Nlc3NlZF92YWx1ZSk7XG4gICAgfVxuXG4gICAgcmV0dXJuIHByb2Nlc3NlZF92YWx1ZXM7XG4gIH1cblxuICBwcm9jZXNzX2ludGVnZXIodmFsdWUpIHtcbiAgICByZXR1cm4gdmFsdWUudmFsdWU7XG4gIH1cblxuICBwcm9jZXNzX2Zsb2F0KHZhbHVlKSB7XG4gICAgaWYgKHZhbHVlLnNpemUgPT09IDY0KSB7XG4gICAgICByZXR1cm4gQml0U3RyaW5nLmZsb2F0NjRUb0J5dGVzKHZhbHVlLnZhbHVlKTtcbiAgICB9IGVsc2UgaWYgKHZhbHVlLnNpemUgPT09IDMyKSB7XG4gICAgICByZXR1cm4gQml0U3RyaW5nLmZsb2F0MzJUb0J5dGVzKHZhbHVlLnZhbHVlKTtcbiAgICB9XG5cbiAgICB0aHJvdyBuZXcgRXJyb3IoXCJJbnZhbGlkIHNpemUgZm9yIGZsb2F0XCIpO1xuICB9XG5cbiAgcHJvY2Vzc19iaXRzdHJpbmcodmFsdWUpIHtcbiAgICByZXR1cm4gdmFsdWUudmFsdWUudmFsdWU7XG4gIH1cblxuICBwcm9jZXNzX2JpbmFyeSh2YWx1ZSkge1xuICAgIHJldHVybiBCaXRTdHJpbmcudG9VVEY4QXJyYXkodmFsdWUudmFsdWUpO1xuICB9XG5cbiAgcHJvY2Vzc191dGY4KHZhbHVlKSB7XG4gICAgcmV0dXJuIEJpdFN0cmluZy50b1VURjhBcnJheSh2YWx1ZS52YWx1ZSk7XG4gIH1cblxuICBwcm9jZXNzX3V0ZjE2KHZhbHVlKSB7XG4gICAgcmV0dXJuIEJpdFN0cmluZy50b1VURjE2QXJyYXkodmFsdWUudmFsdWUpO1xuICB9XG5cbiAgcHJvY2Vzc191dGYzMih2YWx1ZSkge1xuICAgIHJldHVybiBCaXRTdHJpbmcudG9VVEYzMkFycmF5KHZhbHVlLnZhbHVlKTtcbiAgfVxuXG4gIHByb2Nlc3Nfc2lnbmVkKHZhbHVlKSB7XG4gICAgcmV0dXJuIG5ldyBVaW50OEFycmF5KFt2YWx1ZV0pWzBdO1xuICB9XG5cbiAgcHJvY2Vzc191bnNpZ25lZCh2YWx1ZSkge1xuICAgIHJldHVybiB2YWx1ZTtcbiAgfVxuXG4gIHByb2Nlc3NfbmF0aXZlKHZhbHVlKSB7XG4gICAgcmV0dXJuIHZhbHVlO1xuICB9XG5cbiAgcHJvY2Vzc19iaWcodmFsdWUpIHtcbiAgICByZXR1cm4gdmFsdWU7XG4gIH1cblxuICBwcm9jZXNzX2xpdHRsZSh2YWx1ZSkge1xuICAgIHJldHVybiB2YWx1ZS5yZXZlcnNlKCk7XG4gIH1cblxuICBwcm9jZXNzX3NpemUodmFsdWUpIHtcbiAgICByZXR1cm4gdmFsdWU7XG4gIH1cblxuICBwcm9jZXNzX3VuaXQodmFsdWUpIHtcbiAgICByZXR1cm4gdmFsdWU7XG4gIH1cblxuICBzdGF0aWMgaW50ZWdlcih2YWx1ZSkge1xuICAgIHJldHVybiBCaXRTdHJpbmcud3JhcCh2YWx1ZSwgeyBcInR5cGVcIjogXCJpbnRlZ2VyXCIsIFwidW5pdFwiOiAxLCBcInNpemVcIjogOCB9KTtcbiAgfVxuXG4gIHN0YXRpYyBmbG9hdCh2YWx1ZSkge1xuICAgIHJldHVybiBCaXRTdHJpbmcud3JhcCh2YWx1ZSwgeyBcInR5cGVcIjogXCJmbG9hdFwiLCBcInVuaXRcIjogMSwgXCJzaXplXCI6IDY0IH0pO1xuICB9XG5cbiAgc3RhdGljIGJpdHN0cmluZyh2YWx1ZSkge1xuICAgIHJldHVybiBCaXRTdHJpbmcud3JhcCh2YWx1ZSwgeyBcInR5cGVcIjogXCJiaXRzdHJpbmdcIiwgXCJ1bml0XCI6IDEsIFwic2l6ZVwiOiB2YWx1ZS5sZW5ndGggfSk7XG4gIH1cblxuICBzdGF0aWMgYml0cyh2YWx1ZSkge1xuICAgIHJldHVybiBCaXRTdHJpbmcuYml0c3RyaW5nKHZhbHVlKTtcbiAgfVxuXG4gIHN0YXRpYyBiaW5hcnkodmFsdWUpIHtcbiAgICByZXR1cm4gQml0U3RyaW5nLndyYXAodmFsdWUsIHsgXCJ0eXBlXCI6IFwiYmluYXJ5XCIsIFwidW5pdFwiOiA4LCBcInNpemVcIjogdmFsdWUubGVuZ3RoIH0pO1xuICB9XG5cbiAgc3RhdGljIGJ5dGVzKHZhbHVlKSB7XG4gICAgcmV0dXJuIEJpdFN0cmluZy5iaW5hcnkodmFsdWUpO1xuICB9XG5cbiAgc3RhdGljIHV0ZjgodmFsdWUpIHtcbiAgICByZXR1cm4gQml0U3RyaW5nLndyYXAodmFsdWUsIHsgXCJ0eXBlXCI6IFwidXRmOFwiIH0pO1xuICB9XG5cbiAgc3RhdGljIHV0ZjE2KHZhbHVlKSB7XG4gICAgcmV0dXJuIEJpdFN0cmluZy53cmFwKHZhbHVlLCB7IFwidHlwZVwiOiBcInV0ZjE2XCIgfSk7XG4gIH1cblxuICBzdGF0aWMgdXRmMzIodmFsdWUpIHtcbiAgICByZXR1cm4gQml0U3RyaW5nLndyYXAodmFsdWUsIHsgXCJ0eXBlXCI6IFwidXRmMzJcIiB9KTtcbiAgfVxuXG4gIHN0YXRpYyBzaWduZWQodmFsdWUpIHtcbiAgICByZXR1cm4gQml0U3RyaW5nLndyYXAodmFsdWUsIHt9LCBcInNpZ25lZFwiKTtcbiAgfVxuXG4gIHN0YXRpYyB1bnNpZ25lZCh2YWx1ZSkge1xuICAgIHJldHVybiBCaXRTdHJpbmcud3JhcCh2YWx1ZSwge30sIFwidW5zaWduZWRcIik7XG4gIH1cblxuICBzdGF0aWMgbmF0aXZlKHZhbHVlKSB7XG4gICAgcmV0dXJuIEJpdFN0cmluZy53cmFwKHZhbHVlLCB7fSwgXCJuYXRpdmVcIik7XG4gIH1cblxuICBzdGF0aWMgYmlnKHZhbHVlKSB7XG4gICAgcmV0dXJuIEJpdFN0cmluZy53cmFwKHZhbHVlLCB7fSwgXCJiaWdcIik7XG4gIH1cblxuICBzdGF0aWMgbGl0dGxlKHZhbHVlKSB7XG4gICAgcmV0dXJuIEJpdFN0cmluZy53cmFwKHZhbHVlLCB7fSwgXCJsaXR0bGVcIik7XG4gIH1cblxuICBzdGF0aWMgc2l6ZSh2YWx1ZSwgY291bnQpIHtcbiAgICByZXR1cm4gQml0U3RyaW5nLndyYXAodmFsdWUsIHsgXCJzaXplXCI6IGNvdW50IH0pO1xuICB9XG5cbiAgc3RhdGljIHVuaXQodmFsdWUsIGNvdW50KSB7XG4gICAgcmV0dXJuIEJpdFN0cmluZy53cmFwKHZhbHVlLCB7IFwidW5pdFwiOiBjb3VudCB9KTtcbiAgfVxuXG4gIHN0YXRpYyB3cmFwKHZhbHVlLCBvcHQsIG5ld19hdHRyaWJ1dGUgPSBudWxsKSB7XG4gICAgbGV0IHRoZV92YWx1ZSA9IHZhbHVlO1xuXG4gICAgaWYgKCEodmFsdWUgaW5zdGFuY2VvZiBPYmplY3QpKSB7XG4gICAgICB0aGVfdmFsdWUgPSB7IFwidmFsdWVcIjogdmFsdWUsIFwiYXR0cmlidXRlc1wiOiBbXSB9O1xuICAgIH1cblxuICAgIHRoZV92YWx1ZSA9IE9iamVjdC5hc3NpZ24odGhlX3ZhbHVlLCBvcHQpO1xuXG4gICAgaWYgKG5ld19hdHRyaWJ1dGUpIHtcbiAgICAgIHRoZV92YWx1ZS5hdHRyaWJ1dGVzLnB1c2gobmV3X2F0dHJpYnV0ZSk7XG4gICAgfVxuXG4gICAgcmV0dXJuIHRoZV92YWx1ZTtcbiAgfVxuXG4gIHN0YXRpYyB0b1VURjhBcnJheShzdHIpIHtcbiAgICB2YXIgdXRmOCA9IFtdO1xuICAgIGZvciAodmFyIGkgPSAwOyBpIDwgc3RyLmxlbmd0aDsgaSsrKSB7XG4gICAgICB2YXIgY2hhcmNvZGUgPSBzdHIuY2hhckNvZGVBdChpKTtcbiAgICAgIGlmIChjaGFyY29kZSA8IDEyOCkge1xuICAgICAgICB1dGY4LnB1c2goY2hhcmNvZGUpO1xuICAgICAgfSBlbHNlIGlmIChjaGFyY29kZSA8IDIwNDgpIHtcbiAgICAgICAgdXRmOC5wdXNoKDE5MiB8IGNoYXJjb2RlID4+IDYsIDEyOCB8IGNoYXJjb2RlICYgNjMpO1xuICAgICAgfSBlbHNlIGlmIChjaGFyY29kZSA8IDU1Mjk2IHx8IGNoYXJjb2RlID49IDU3MzQ0KSB7XG4gICAgICAgIHV0ZjgucHVzaCgyMjQgfCBjaGFyY29kZSA+PiAxMiwgMTI4IHwgY2hhcmNvZGUgPj4gNiAmIDYzLCAxMjggfCBjaGFyY29kZSAmIDYzKTtcbiAgICAgIH1cbiAgICAgIC8vIHN1cnJvZ2F0ZSBwYWlyXG4gICAgICBlbHNlIHtcbiAgICAgICAgaSsrO1xuICAgICAgICAvLyBVVEYtMTYgZW5jb2RlcyAweDEwMDAwLTB4MTBGRkZGIGJ5XG4gICAgICAgIC8vIHN1YnRyYWN0aW5nIDB4MTAwMDAgYW5kIHNwbGl0dGluZyB0aGVcbiAgICAgICAgLy8gMjAgYml0cyBvZiAweDAtMHhGRkZGRiBpbnRvIHR3byBoYWx2ZXNcbiAgICAgICAgY2hhcmNvZGUgPSA2NTUzNiArICgoY2hhcmNvZGUgJiAxMDIzKSA8PCAxMCB8IHN0ci5jaGFyQ29kZUF0KGkpICYgMTAyMyk7XG4gICAgICAgIHV0ZjgucHVzaCgyNDAgfCBjaGFyY29kZSA+PiAxOCwgMTI4IHwgY2hhcmNvZGUgPj4gMTIgJiA2MywgMTI4IHwgY2hhcmNvZGUgPj4gNiAmIDYzLCAxMjggfCBjaGFyY29kZSAmIDYzKTtcbiAgICAgIH1cbiAgICB9XG4gICAgcmV0dXJuIHV0Zjg7XG4gIH1cblxuICBzdGF0aWMgdG9VVEYxNkFycmF5KHN0cikge1xuICAgIHZhciB1dGYxNiA9IFtdO1xuICAgIGZvciAodmFyIGkgPSAwOyBpIDwgc3RyLmxlbmd0aDsgaSsrKSB7XG4gICAgICB2YXIgY29kZVBvaW50ID0gc3RyLmNvZGVQb2ludEF0KGkpO1xuXG4gICAgICBpZiAoY29kZVBvaW50IDw9IDI1NSkge1xuICAgICAgICB1dGYxNi5wdXNoKDApO1xuICAgICAgICB1dGYxNi5wdXNoKGNvZGVQb2ludCk7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICB1dGYxNi5wdXNoKGNvZGVQb2ludCA+PiA4ICYgMjU1KTtcbiAgICAgICAgdXRmMTYucHVzaChjb2RlUG9pbnQgJiAyNTUpO1xuICAgICAgfVxuICAgIH1cbiAgICByZXR1cm4gdXRmMTY7XG4gIH1cblxuICBzdGF0aWMgdG9VVEYzMkFycmF5KHN0cikge1xuICAgIHZhciB1dGYzMiA9IFtdO1xuICAgIGZvciAodmFyIGkgPSAwOyBpIDwgc3RyLmxlbmd0aDsgaSsrKSB7XG4gICAgICB2YXIgY29kZVBvaW50ID0gc3RyLmNvZGVQb2ludEF0KGkpO1xuXG4gICAgICBpZiAoY29kZVBvaW50IDw9IDI1NSkge1xuICAgICAgICB1dGYzMi5wdXNoKDApO1xuICAgICAgICB1dGYzMi5wdXNoKDApO1xuICAgICAgICB1dGYzMi5wdXNoKDApO1xuICAgICAgICB1dGYzMi5wdXNoKGNvZGVQb2ludCk7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICB1dGYzMi5wdXNoKDApO1xuICAgICAgICB1dGYzMi5wdXNoKDApO1xuICAgICAgICB1dGYzMi5wdXNoKGNvZGVQb2ludCA+PiA4ICYgMjU1KTtcbiAgICAgICAgdXRmMzIucHVzaChjb2RlUG9pbnQgJiAyNTUpO1xuICAgICAgfVxuICAgIH1cbiAgICByZXR1cm4gdXRmMzI7XG4gIH1cblxuICAvL2h0dHA6Ly9zdGFja292ZXJmbG93LmNvbS9xdWVzdGlvbnMvMjAwMzQ5My9qYXZhc2NyaXB0LWZsb2F0LWZyb20tdG8tYml0c1xuICBzdGF0aWMgZmxvYXQzMlRvQnl0ZXMoZikge1xuICAgIHZhciBieXRlcyA9IFtdO1xuXG4gICAgdmFyIGJ1ZiA9IG5ldyBBcnJheUJ1ZmZlcig0KTtcbiAgICBuZXcgRmxvYXQzMkFycmF5KGJ1ZilbMF0gPSBmO1xuXG4gICAgbGV0IGludFZlcnNpb24gPSBuZXcgVWludDMyQXJyYXkoYnVmKVswXTtcblxuICAgIGJ5dGVzLnB1c2goaW50VmVyc2lvbiA+PiAyNCAmIDI1NSk7XG4gICAgYnl0ZXMucHVzaChpbnRWZXJzaW9uID4+IDE2ICYgMjU1KTtcbiAgICBieXRlcy5wdXNoKGludFZlcnNpb24gPj4gOCAmIDI1NSk7XG4gICAgYnl0ZXMucHVzaChpbnRWZXJzaW9uICYgMjU1KTtcblxuICAgIHJldHVybiBieXRlcztcbiAgfVxuXG4gIHN0YXRpYyBmbG9hdDY0VG9CeXRlcyhmKSB7XG4gICAgdmFyIGJ5dGVzID0gW107XG5cbiAgICB2YXIgYnVmID0gbmV3IEFycmF5QnVmZmVyKDgpO1xuICAgIG5ldyBGbG9hdDY0QXJyYXkoYnVmKVswXSA9IGY7XG5cbiAgICB2YXIgaW50VmVyc2lvbjEgPSBuZXcgVWludDMyQXJyYXkoYnVmKVswXTtcbiAgICB2YXIgaW50VmVyc2lvbjIgPSBuZXcgVWludDMyQXJyYXkoYnVmKVsxXTtcblxuICAgIGJ5dGVzLnB1c2goaW50VmVyc2lvbjIgPj4gMjQgJiAyNTUpO1xuICAgIGJ5dGVzLnB1c2goaW50VmVyc2lvbjIgPj4gMTYgJiAyNTUpO1xuICAgIGJ5dGVzLnB1c2goaW50VmVyc2lvbjIgPj4gOCAmIDI1NSk7XG4gICAgYnl0ZXMucHVzaChpbnRWZXJzaW9uMiAmIDI1NSk7XG5cbiAgICBieXRlcy5wdXNoKGludFZlcnNpb24xID4+IDI0ICYgMjU1KTtcbiAgICBieXRlcy5wdXNoKGludFZlcnNpb24xID4+IDE2ICYgMjU1KTtcbiAgICBieXRlcy5wdXNoKGludFZlcnNpb24xID4+IDggJiAyNTUpO1xuICAgIGJ5dGVzLnB1c2goaW50VmVyc2lvbjEgJiAyNTUpO1xuXG4gICAgcmV0dXJuIGJ5dGVzO1xuICB9XG59XG5cbi8qIEBmbG93ICovXG5cbmNsYXNzIFZhcmlhYmxlIHtcblxuICBjb25zdHJ1Y3RvcihuYW1lID0gbnVsbCkge1xuICAgIHRoaXMubmFtZSA9IG5hbWU7XG4gIH1cbn1cblxuY2xhc3MgV2lsZGNhcmQge1xuICBjb25zdHJ1Y3RvcigpIHt9XG59XG5cbmNsYXNzIFN0YXJ0c1dpdGgge1xuXG4gIGNvbnN0cnVjdG9yKHByZWZpeCkge1xuICAgIHRoaXMucHJlZml4ID0gcHJlZml4O1xuICB9XG59XG5cbmNsYXNzIENhcHR1cmUge1xuXG4gIGNvbnN0cnVjdG9yKHZhbHVlKSB7XG4gICAgdGhpcy52YWx1ZSA9IHZhbHVlO1xuICB9XG59XG5cbmNsYXNzIEhlYWRUYWlsIHtcbiAgY29uc3RydWN0b3IoKSB7fVxufVxuXG5jbGFzcyBUeXBlIHtcblxuICBjb25zdHJ1Y3Rvcih0eXBlLCBvYmpQYXR0ZXJuID0ge30pIHtcbiAgICB0aGlzLnR5cGUgPSB0eXBlO1xuICAgIHRoaXMub2JqUGF0dGVybiA9IG9ialBhdHRlcm47XG4gIH1cbn1cblxuY2xhc3MgQm91bmQge1xuXG4gIGNvbnN0cnVjdG9yKHZhbHVlKSB7XG4gICAgdGhpcy52YWx1ZSA9IHZhbHVlO1xuICB9XG59XG5cbmZ1bmN0aW9uIHZhcmlhYmxlKG5hbWUgPSBudWxsKSB7XG4gIHJldHVybiBuZXcgVmFyaWFibGUobmFtZSk7XG59XG5cbmZ1bmN0aW9uIHdpbGRjYXJkKCkge1xuICByZXR1cm4gbmV3IFdpbGRjYXJkKCk7XG59XG5cbmZ1bmN0aW9uIHN0YXJ0c1dpdGgocHJlZml4KSB7XG4gIHJldHVybiBuZXcgU3RhcnRzV2l0aChwcmVmaXgpO1xufVxuXG5mdW5jdGlvbiBjYXB0dXJlKHZhbHVlKSB7XG4gIHJldHVybiBuZXcgQ2FwdHVyZSh2YWx1ZSk7XG59XG5cbmZ1bmN0aW9uIGhlYWRUYWlsKCkge1xuICByZXR1cm4gbmV3IEhlYWRUYWlsKCk7XG59XG5cbmZ1bmN0aW9uIHR5cGUodHlwZSwgb2JqUGF0dGVybiA9IHt9KSB7XG4gIHJldHVybiBuZXcgVHlwZSh0eXBlLCBvYmpQYXR0ZXJuKTtcbn1cblxuZnVuY3Rpb24gYm91bmQodmFsdWUpIHtcbiAgcmV0dXJuIG5ldyBCb3VuZCh2YWx1ZSk7XG59XG5cbmZ1bmN0aW9uIGlzX251bWJlcih2YWx1ZSkge1xuICByZXR1cm4gdHlwZW9mIHZhbHVlID09PSAnbnVtYmVyJztcbn1cblxuZnVuY3Rpb24gaXNfc3RyaW5nKHZhbHVlKSB7XG4gIHJldHVybiB0eXBlb2YgdmFsdWUgPT09ICdzdHJpbmcnO1xufVxuXG5mdW5jdGlvbiBpc19ib29sZWFuKHZhbHVlKSB7XG4gIHJldHVybiB0eXBlb2YgdmFsdWUgPT09ICdib29sZWFuJztcbn1cblxuZnVuY3Rpb24gaXNfc3ltYm9sKHZhbHVlKSB7XG4gIHJldHVybiB0eXBlb2YgdmFsdWUgPT09ICdzeW1ib2wnO1xufVxuXG5mdW5jdGlvbiBpc19udWxsKHZhbHVlKSB7XG4gIHJldHVybiB2YWx1ZSA9PT0gbnVsbDtcbn1cblxuZnVuY3Rpb24gaXNfdW5kZWZpbmVkKHZhbHVlKSB7XG4gIHJldHVybiB0eXBlb2YgdmFsdWUgPT09ICd1bmRlZmluZWQnO1xufVxuXG5mdW5jdGlvbiBpc19mdW5jdGlvbih2YWx1ZSkge1xuICByZXR1cm4gT2JqZWN0LnByb3RvdHlwZS50b1N0cmluZy5jYWxsKHZhbHVlKSA9PSAnW29iamVjdCBGdW5jdGlvbl0nO1xufVxuXG5mdW5jdGlvbiBpc192YXJpYWJsZSh2YWx1ZSkge1xuICByZXR1cm4gdmFsdWUgaW5zdGFuY2VvZiBWYXJpYWJsZTtcbn1cblxuZnVuY3Rpb24gaXNfd2lsZGNhcmQodmFsdWUpIHtcbiAgcmV0dXJuIHZhbHVlIGluc3RhbmNlb2YgV2lsZGNhcmQ7XG59XG5cbmZ1bmN0aW9uIGlzX2hlYWRUYWlsKHZhbHVlKSB7XG4gIHJldHVybiB2YWx1ZSBpbnN0YW5jZW9mIEhlYWRUYWlsO1xufVxuXG5mdW5jdGlvbiBpc19jYXB0dXJlKHZhbHVlKSB7XG4gIHJldHVybiB2YWx1ZSBpbnN0YW5jZW9mIENhcHR1cmU7XG59XG5cbmZ1bmN0aW9uIGlzX3R5cGUodmFsdWUpIHtcbiAgcmV0dXJuIHZhbHVlIGluc3RhbmNlb2YgVHlwZTtcbn1cblxuZnVuY3Rpb24gaXNfc3RhcnRzV2l0aCh2YWx1ZSkge1xuICByZXR1cm4gdmFsdWUgaW5zdGFuY2VvZiBTdGFydHNXaXRoO1xufVxuXG5mdW5jdGlvbiBpc19ib3VuZCh2YWx1ZSkge1xuICByZXR1cm4gdmFsdWUgaW5zdGFuY2VvZiBCb3VuZDtcbn1cblxuZnVuY3Rpb24gaXNfb2JqZWN0KHZhbHVlKSB7XG4gIHJldHVybiB0eXBlb2YgdmFsdWUgPT09ICdvYmplY3QnO1xufVxuXG5mdW5jdGlvbiBpc19hcnJheSh2YWx1ZSkge1xuICByZXR1cm4gQXJyYXkuaXNBcnJheSh2YWx1ZSk7XG59XG5cbnZhciBDaGVja3MgPSB7XG4gIGlzX251bWJlcixcbiAgaXNfc3RyaW5nLFxuICBpc19ib29sZWFuLFxuICBpc19zeW1ib2wsXG4gIGlzX251bGwsXG4gIGlzX3VuZGVmaW5lZCxcbiAgaXNfZnVuY3Rpb24sXG4gIGlzX3ZhcmlhYmxlLFxuICBpc193aWxkY2FyZCxcbiAgaXNfaGVhZFRhaWwsXG4gIGlzX2NhcHR1cmUsXG4gIGlzX3R5cGUsXG4gIGlzX3N0YXJ0c1dpdGgsXG4gIGlzX2JvdW5kLFxuICBpc19vYmplY3QsXG4gIGlzX2FycmF5XG59O1xuXG5mdW5jdGlvbiByZXNvbHZlU3ltYm9sKHBhdHRlcm4pIHtcbiAgcmV0dXJuIGZ1bmN0aW9uICh2YWx1ZSkge1xuICAgIHJldHVybiBDaGVja3MuaXNfc3ltYm9sKHZhbHVlKSAmJiB2YWx1ZSA9PT0gcGF0dGVybjtcbiAgfTtcbn1cblxuZnVuY3Rpb24gcmVzb2x2ZVN0cmluZyhwYXR0ZXJuKSB7XG4gIHJldHVybiBmdW5jdGlvbiAodmFsdWUpIHtcbiAgICByZXR1cm4gQ2hlY2tzLmlzX3N0cmluZyh2YWx1ZSkgJiYgdmFsdWUgPT09IHBhdHRlcm47XG4gIH07XG59XG5cbmZ1bmN0aW9uIHJlc29sdmVOdW1iZXIocGF0dGVybikge1xuICByZXR1cm4gZnVuY3Rpb24gKHZhbHVlKSB7XG4gICAgcmV0dXJuIENoZWNrcy5pc19udW1iZXIodmFsdWUpICYmIHZhbHVlID09PSBwYXR0ZXJuO1xuICB9O1xufVxuXG5mdW5jdGlvbiByZXNvbHZlQm9vbGVhbihwYXR0ZXJuKSB7XG4gIHJldHVybiBmdW5jdGlvbiAodmFsdWUpIHtcbiAgICByZXR1cm4gQ2hlY2tzLmlzX2Jvb2xlYW4odmFsdWUpICYmIHZhbHVlID09PSBwYXR0ZXJuO1xuICB9O1xufVxuXG5mdW5jdGlvbiByZXNvbHZlRnVuY3Rpb24ocGF0dGVybikge1xuICByZXR1cm4gZnVuY3Rpb24gKHZhbHVlKSB7XG4gICAgcmV0dXJuIENoZWNrcy5pc19mdW5jdGlvbih2YWx1ZSkgJiYgdmFsdWUgPT09IHBhdHRlcm47XG4gIH07XG59XG5cbmZ1bmN0aW9uIHJlc29sdmVOdWxsKHBhdHRlcm4pIHtcbiAgcmV0dXJuIGZ1bmN0aW9uICh2YWx1ZSkge1xuICAgIHJldHVybiBDaGVja3MuaXNfbnVsbCh2YWx1ZSk7XG4gIH07XG59XG5cbmZ1bmN0aW9uIHJlc29sdmVCb3VuZChwYXR0ZXJuKSB7XG4gIHJldHVybiBmdW5jdGlvbiAodmFsdWUsIGFyZ3MpIHtcbiAgICBpZiAodHlwZW9mIHZhbHVlID09PSB0eXBlb2YgcGF0dGVybi52YWx1ZSAmJiB2YWx1ZSA9PT0gcGF0dGVybi52YWx1ZSkge1xuICAgICAgYXJncy5wdXNoKHZhbHVlKTtcbiAgICAgIHJldHVybiB0cnVlO1xuICAgIH1cblxuICAgIHJldHVybiBmYWxzZTtcbiAgfTtcbn1cblxuZnVuY3Rpb24gcmVzb2x2ZVdpbGRjYXJkKCkge1xuICByZXR1cm4gZnVuY3Rpb24gKCkge1xuICAgIHJldHVybiB0cnVlO1xuICB9O1xufVxuXG5mdW5jdGlvbiByZXNvbHZlVmFyaWFibGUoKSB7XG4gIHJldHVybiBmdW5jdGlvbiAodmFsdWUsIGFyZ3MpIHtcbiAgICBhcmdzLnB1c2godmFsdWUpO1xuICAgIHJldHVybiB0cnVlO1xuICB9O1xufVxuXG5mdW5jdGlvbiByZXNvbHZlSGVhZFRhaWwoKSB7XG4gIHJldHVybiBmdW5jdGlvbiAodmFsdWUsIGFyZ3MpIHtcbiAgICBpZiAoIUNoZWNrcy5pc19hcnJheSh2YWx1ZSkgfHwgdmFsdWUubGVuZ3RoIDwgMikge1xuICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH1cblxuICAgIGNvbnN0IGhlYWQgPSB2YWx1ZVswXTtcbiAgICBjb25zdCB0YWlsID0gdmFsdWUuc2xpY2UoMSk7XG5cbiAgICBhcmdzLnB1c2goaGVhZCk7XG4gICAgYXJncy5wdXNoKHRhaWwpO1xuXG4gICAgcmV0dXJuIHRydWU7XG4gIH07XG59XG5cbmZ1bmN0aW9uIHJlc29sdmVDYXB0dXJlKHBhdHRlcm4pIHtcbiAgY29uc3QgbWF0Y2hlcyA9IGJ1aWxkTWF0Y2gocGF0dGVybi52YWx1ZSk7XG5cbiAgcmV0dXJuIGZ1bmN0aW9uICh2YWx1ZSwgYXJncykge1xuICAgIGlmIChtYXRjaGVzKHZhbHVlLCBhcmdzKSkge1xuICAgICAgYXJncy5wdXNoKHZhbHVlKTtcbiAgICAgIHJldHVybiB0cnVlO1xuICAgIH1cblxuICAgIHJldHVybiBmYWxzZTtcbiAgfTtcbn1cblxuZnVuY3Rpb24gcmVzb2x2ZVN0YXJ0c1dpdGgocGF0dGVybikge1xuICBjb25zdCBwcmVmaXggPSBwYXR0ZXJuLnByZWZpeDtcblxuICByZXR1cm4gZnVuY3Rpb24gKHZhbHVlLCBhcmdzKSB7XG4gICAgaWYgKENoZWNrcy5pc19zdHJpbmcodmFsdWUpICYmIHZhbHVlLnN0YXJ0c1dpdGgocHJlZml4KSkge1xuICAgICAgYXJncy5wdXNoKHZhbHVlLnN1YnN0cmluZyhwcmVmaXgubGVuZ3RoKSk7XG4gICAgICByZXR1cm4gdHJ1ZTtcbiAgICB9XG5cbiAgICByZXR1cm4gZmFsc2U7XG4gIH07XG59XG5cbmZ1bmN0aW9uIHJlc29sdmVUeXBlKHBhdHRlcm4pIHtcbiAgcmV0dXJuIGZ1bmN0aW9uICh2YWx1ZSwgYXJncykge1xuICAgIGlmICh2YWx1ZSBpbnN0YW5jZW9mIHBhdHRlcm4udHlwZSkge1xuICAgICAgY29uc3QgbWF0Y2hlcyA9IGJ1aWxkTWF0Y2gocGF0dGVybi5vYmpQYXR0ZXJuKTtcbiAgICAgIHJldHVybiBtYXRjaGVzKHZhbHVlLCBhcmdzKSAmJiBhcmdzLnB1c2godmFsdWUpID4gMDtcbiAgICB9XG5cbiAgICByZXR1cm4gZmFsc2U7XG4gIH07XG59XG5cbmZ1bmN0aW9uIHJlc29sdmVBcnJheShwYXR0ZXJuKSB7XG4gIGNvbnN0IG1hdGNoZXMgPSBwYXR0ZXJuLm1hcCh4ID0+IGJ1aWxkTWF0Y2goeCkpO1xuXG4gIHJldHVybiBmdW5jdGlvbiAodmFsdWUsIGFyZ3MpIHtcbiAgICBpZiAoIUNoZWNrcy5pc19hcnJheSh2YWx1ZSkgfHwgdmFsdWUubGVuZ3RoICE9IHBhdHRlcm4ubGVuZ3RoKSB7XG4gICAgICByZXR1cm4gZmFsc2U7XG4gICAgfVxuXG4gICAgcmV0dXJuIHZhbHVlLmV2ZXJ5KGZ1bmN0aW9uICh2LCBpKSB7XG4gICAgICByZXR1cm4gbWF0Y2hlc1tpXSh2YWx1ZVtpXSwgYXJncyk7XG4gICAgfSk7XG4gIH07XG59XG5cbmZ1bmN0aW9uIHJlc29sdmVPYmplY3QocGF0dGVybikge1xuICBsZXQgbWF0Y2hlcyA9IHt9O1xuXG4gIGZvciAobGV0IGtleSBvZiBPYmplY3Qua2V5cyhwYXR0ZXJuKS5jb25jYXQoT2JqZWN0LmdldE93blByb3BlcnR5U3ltYm9scyhwYXR0ZXJuKSkpIHtcbiAgICBtYXRjaGVzW2tleV0gPSBidWlsZE1hdGNoKHBhdHRlcm5ba2V5XSk7XG4gIH1cblxuICByZXR1cm4gZnVuY3Rpb24gKHZhbHVlLCBhcmdzKSB7XG4gICAgaWYgKCFDaGVja3MuaXNfb2JqZWN0KHZhbHVlKSB8fCBwYXR0ZXJuLmxlbmd0aCA+IHZhbHVlLmxlbmd0aCkge1xuICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH1cblxuICAgIGZvciAobGV0IGtleSBvZiBPYmplY3Qua2V5cyhwYXR0ZXJuKS5jb25jYXQoT2JqZWN0LmdldE93blByb3BlcnR5U3ltYm9scyhwYXR0ZXJuKSkpIHtcbiAgICAgIGlmICghKGtleSBpbiB2YWx1ZSkgfHwgIW1hdGNoZXNba2V5XSh2YWx1ZVtrZXldLCBhcmdzKSkge1xuICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICB9XG4gICAgfVxuXG4gICAgcmV0dXJuIHRydWU7XG4gIH07XG59XG5cbmZ1bmN0aW9uIHJlc29sdmVOb01hdGNoKCkge1xuICByZXR1cm4gZnVuY3Rpb24gKCkge1xuICAgIHJldHVybiBmYWxzZTtcbiAgfTtcbn1cblxudmFyIFJlc29sdmVycyA9IHtcbiAgcmVzb2x2ZUJvdW5kLFxuICByZXNvbHZlV2lsZGNhcmQsXG4gIHJlc29sdmVWYXJpYWJsZSxcbiAgcmVzb2x2ZUhlYWRUYWlsLFxuICByZXNvbHZlQ2FwdHVyZSxcbiAgcmVzb2x2ZVN0YXJ0c1dpdGgsXG4gIHJlc29sdmVUeXBlLFxuICByZXNvbHZlQXJyYXksXG4gIHJlc29sdmVPYmplY3QsXG4gIHJlc29sdmVOb01hdGNoLFxuICByZXNvbHZlU3ltYm9sLFxuICByZXNvbHZlU3RyaW5nLFxuICByZXNvbHZlTnVtYmVyLFxuICByZXNvbHZlQm9vbGVhbixcbiAgcmVzb2x2ZUZ1bmN0aW9uLFxuICByZXNvbHZlTnVsbFxufTtcblxuZnVuY3Rpb24gYnVpbGRNYXRjaChwYXR0ZXJuKSB7XG5cbiAgaWYgKENoZWNrcy5pc192YXJpYWJsZShwYXR0ZXJuKSkge1xuICAgIHJldHVybiBSZXNvbHZlcnMucmVzb2x2ZVZhcmlhYmxlKHBhdHRlcm4pO1xuICB9XG5cbiAgaWYgKENoZWNrcy5pc193aWxkY2FyZChwYXR0ZXJuKSkge1xuICAgIHJldHVybiBSZXNvbHZlcnMucmVzb2x2ZVdpbGRjYXJkKHBhdHRlcm4pO1xuICB9XG5cbiAgaWYgKENoZWNrcy5pc191bmRlZmluZWQocGF0dGVybikpIHtcbiAgICByZXR1cm4gUmVzb2x2ZXJzLnJlc29sdmVXaWxkY2FyZChwYXR0ZXJuKTtcbiAgfVxuXG4gIGlmIChDaGVja3MuaXNfaGVhZFRhaWwocGF0dGVybikpIHtcbiAgICByZXR1cm4gUmVzb2x2ZXJzLnJlc29sdmVIZWFkVGFpbChwYXR0ZXJuKTtcbiAgfVxuXG4gIGlmIChDaGVja3MuaXNfc3RhcnRzV2l0aChwYXR0ZXJuKSkge1xuICAgIHJldHVybiBSZXNvbHZlcnMucmVzb2x2ZVN0YXJ0c1dpdGgocGF0dGVybik7XG4gIH1cblxuICBpZiAoQ2hlY2tzLmlzX2NhcHR1cmUocGF0dGVybikpIHtcbiAgICByZXR1cm4gUmVzb2x2ZXJzLnJlc29sdmVDYXB0dXJlKHBhdHRlcm4pO1xuICB9XG5cbiAgaWYgKENoZWNrcy5pc19ib3VuZChwYXR0ZXJuKSkge1xuICAgIHJldHVybiBSZXNvbHZlcnMucmVzb2x2ZUJvdW5kKHBhdHRlcm4pO1xuICB9XG5cbiAgaWYgKENoZWNrcy5pc190eXBlKHBhdHRlcm4pKSB7XG4gICAgcmV0dXJuIFJlc29sdmVycy5yZXNvbHZlVHlwZShwYXR0ZXJuKTtcbiAgfVxuXG4gIGlmIChDaGVja3MuaXNfYXJyYXkocGF0dGVybikpIHtcbiAgICByZXR1cm4gUmVzb2x2ZXJzLnJlc29sdmVBcnJheShwYXR0ZXJuKTtcbiAgfVxuXG4gIGlmIChDaGVja3MuaXNfbnVtYmVyKHBhdHRlcm4pKSB7XG4gICAgcmV0dXJuIFJlc29sdmVycy5yZXNvbHZlTnVtYmVyKHBhdHRlcm4pO1xuICB9XG5cbiAgaWYgKENoZWNrcy5pc19zdHJpbmcocGF0dGVybikpIHtcbiAgICByZXR1cm4gUmVzb2x2ZXJzLnJlc29sdmVTdHJpbmcocGF0dGVybik7XG4gIH1cblxuICBpZiAoQ2hlY2tzLmlzX2Jvb2xlYW4ocGF0dGVybikpIHtcbiAgICByZXR1cm4gUmVzb2x2ZXJzLnJlc29sdmVCb29sZWFuKHBhdHRlcm4pO1xuICB9XG5cbiAgaWYgKENoZWNrcy5pc19zeW1ib2wocGF0dGVybikpIHtcbiAgICByZXR1cm4gUmVzb2x2ZXJzLnJlc29sdmVTeW1ib2wocGF0dGVybik7XG4gIH1cblxuICBpZiAoQ2hlY2tzLmlzX251bGwocGF0dGVybikpIHtcbiAgICByZXR1cm4gUmVzb2x2ZXJzLnJlc29sdmVOdWxsKHBhdHRlcm4pO1xuICB9XG5cbiAgaWYgKENoZWNrcy5pc19vYmplY3QocGF0dGVybikpIHtcbiAgICByZXR1cm4gUmVzb2x2ZXJzLnJlc29sdmVPYmplY3QocGF0dGVybik7XG4gIH1cblxuICByZXR1cm4gUmVzb2x2ZXJzLnJlc29sdmVOb01hdGNoKCk7XG59XG5cbmNsYXNzIE1hdGNoRXJyb3IgZXh0ZW5kcyBFcnJvciB7XG4gIGNvbnN0cnVjdG9yKGFyZykge1xuICAgIHN1cGVyKCk7XG5cbiAgICBpZiAodHlwZW9mIGFyZyA9PT0gJ3N5bWJvbCcpIHtcbiAgICAgIHRoaXMubWVzc2FnZSA9ICdObyBtYXRjaCBmb3I6ICcgKyBhcmcudG9TdHJpbmcoKTtcbiAgICB9IGVsc2UgaWYgKEFycmF5LmlzQXJyYXkoYXJnKSkge1xuICAgICAgbGV0IG1hcHBlZFZhbHVlcyA9IGFyZy5tYXAoeCA9PiB4LnRvU3RyaW5nKCkpO1xuICAgICAgdGhpcy5tZXNzYWdlID0gJ05vIG1hdGNoIGZvcjogJyArIG1hcHBlZFZhbHVlcztcbiAgICB9IGVsc2Uge1xuICAgICAgdGhpcy5tZXNzYWdlID0gJ05vIG1hdGNoIGZvcjogJyArIGFyZztcbiAgICB9XG5cbiAgICB0aGlzLnN0YWNrID0gbmV3IEVycm9yKCkuc3RhY2s7XG4gICAgdGhpcy5uYW1lID0gdGhpcy5jb25zdHJ1Y3Rvci5uYW1lO1xuICB9XG59XG5cbmNsYXNzIENhc2Uge1xuXG4gIGNvbnN0cnVjdG9yKHBhdHRlcm4sIGZuLCBndWFyZCA9ICgpID0+IHRydWUpIHtcbiAgICB0aGlzLnBhdHRlcm4gPSBidWlsZE1hdGNoKHBhdHRlcm4pO1xuICAgIHRoaXMuZm4gPSBmbjtcbiAgICB0aGlzLmd1YXJkID0gZ3VhcmQ7XG4gIH1cbn1cblxuZnVuY3Rpb24gbWFrZV9jYXNlKHBhdHRlcm4sIGZuLCBndWFyZCA9ICgpID0+IHRydWUpIHtcbiAgcmV0dXJuIG5ldyBDYXNlKHBhdHRlcm4sIGZuLCBndWFyZCk7XG59XG5cbmZ1bmN0aW9uIGRlZm1hdGNoKC4uLmNhc2VzKSB7XG4gIHJldHVybiBmdW5jdGlvbiAoLi4uYXJncykge1xuICAgIGZvciAobGV0IHByb2Nlc3NlZENhc2Ugb2YgY2FzZXMpIHtcbiAgICAgIGxldCByZXN1bHQgPSBbXTtcbiAgICAgIGlmIChwcm9jZXNzZWRDYXNlLnBhdHRlcm4oYXJncywgcmVzdWx0KSAmJiBwcm9jZXNzZWRDYXNlLmd1YXJkLmFwcGx5KHRoaXMsIHJlc3VsdCkpIHtcbiAgICAgICAgcmV0dXJuIHByb2Nlc3NlZENhc2UuZm4uYXBwbHkodGhpcywgcmVzdWx0KTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICB0aHJvdyBuZXcgTWF0Y2hFcnJvcihhcmdzKTtcbiAgfTtcbn1cblxuZnVuY3Rpb24gbWF0Y2gocGF0dGVybiwgZXhwciwgZ3VhcmQgPSAoKSA9PiB0cnVlKSB7XG4gIGxldCByZXN1bHQgPSBbXTtcbiAgbGV0IHByb2Nlc3NlZFBhdHRlcm4gPSBidWlsZE1hdGNoKHBhdHRlcm4pO1xuICBpZiAocHJvY2Vzc2VkUGF0dGVybihleHByLCByZXN1bHQpICYmIGd1YXJkLmFwcGx5KHRoaXMsIHJlc3VsdCkpIHtcbiAgICByZXR1cm4gcmVzdWx0O1xuICB9IGVsc2Uge1xuICAgIHRocm93IG5ldyBNYXRjaEVycm9yKGV4cHIpO1xuICB9XG59XG5cbmZ1bmN0aW9uIG1hdGNoX25vX3Rocm93KHBhdHRlcm4sIGV4cHIsIGd1YXJkID0gKCkgPT4gdHJ1ZSkge1xuICB0cnkge1xuICAgIHJldHVybiBtYXRjaChwYXR0ZXJuLCBleHByLCBndWFyZCk7XG4gIH0gY2F0Y2ggKGUpIHtcbiAgICBpZiAoZSBpbnN0YW5jZW9mIE1hdGNoRXJyb3IpIHtcbiAgICAgIHJldHVybiBudWxsO1xuICAgIH1cblxuICAgIHRocm93IGU7XG4gIH1cbn1cblxudmFyIFBhdHRlcm5zID0ge1xuICBkZWZtYXRjaCwgbWF0Y2gsIE1hdGNoRXJyb3IsIG1hdGNoX25vX3Rocm93LFxuICB2YXJpYWJsZSwgd2lsZGNhcmQsIHN0YXJ0c1dpdGgsXG4gIGNhcHR1cmUsIGhlYWRUYWlsLCB0eXBlLCBib3VuZCwgQ2FzZSwgbWFrZV9jYXNlXG59O1xuXG5mdW5jdGlvbiBjYWxsX3Byb3BlcnR5KGl0ZW0sIHByb3BlcnR5KSB7XG4gIGxldCBwcm9wID0gbnVsbDtcblxuICBpZiAocHJvcGVydHkgaW4gaXRlbSkge1xuICAgIHByb3AgPSBwcm9wZXJ0eTtcbiAgfSBlbHNlIGlmIChTeW1ib2wuZm9yKHByb3BlcnR5KSBpbiBpdGVtKSB7XG4gICAgcHJvcCA9IFN5bWJvbC5mb3IocHJvcGVydHkpO1xuICB9IGVsc2Uge1xuICAgIHRocm93IG5ldyBFcnJvcihgUHJvcGVydHkgJHsgcHJvcGVydHkgfSBub3QgZm91bmQgaW4gJHsgaXRlbSB9YCk7XG4gIH1cblxuICBpZiAoaXRlbVtwcm9wXSBpbnN0YW5jZW9mIEZ1bmN0aW9uKSB7XG4gICAgcmV0dXJuIGl0ZW1bcHJvcF0oKTtcbiAgfSBlbHNlIHtcbiAgICByZXR1cm4gaXRlbVtwcm9wXTtcbiAgfVxufVxuXG5mdW5jdGlvbiBhcHBseSguLi5hcmdzKSB7XG4gIGlmIChhcmdzLmxlbmd0aCA9PT0gMikge1xuICAgIGFyZ3NbMF0uYXBwbHkobnVsbCwgYXJncy5zbGljZSgxKSk7XG4gIH0gZWxzZSB7XG4gICAgYXJnc1swXVthcmdzWzFdXS5hcHBseShudWxsLCBhcmdzLnNsaWNlKDIpKTtcbiAgfVxufVxuXG5mdW5jdGlvbiBjb250YWlucyhsZWZ0LCByaWdodCkge1xuICBmb3IgKGxldCB4IG9mIHJpZ2h0KSB7XG4gICAgaWYgKFBhdHRlcm5zLm1hdGNoX25vX3Rocm93KGxlZnQsIHgpICE9IG51bGwpIHtcbiAgICAgIHJldHVybiB0cnVlO1xuICAgIH1cbiAgfVxuXG4gIHJldHVybiBmYWxzZTtcbn1cblxuZnVuY3Rpb24gZ2V0X2dsb2JhbCgpIHtcbiAgaWYgKHR5cGVvZiBzZWxmICE9PSAndW5kZWZpbmVkJykge1xuICAgIHJldHVybiBzZWxmO1xuICB9IGVsc2UgaWYgKHR5cGVvZiB3aW5kb3cgIT09ICd1bmRlZmluZWQnKSB7XG4gICAgcmV0dXJuIHdpbmRvdztcbiAgfSBlbHNlIGlmICh0eXBlb2YgZ2xvYmFsICE9PSAndW5kZWZpbmVkJykge1xuICAgIHJldHVybiBnbG9iYWw7XG4gIH1cblxuICB0aHJvdyBuZXcgRXJyb3IoJ05vIGdsb2JhbCBzdGF0ZSBmb3VuZCcpO1xufVxuXG5mdW5jdGlvbiBkZWZzdHJ1Y3QoZGVmYXVsdHMpIHtcbiAgcmV0dXJuIGNsYXNzIHtcbiAgICBjb25zdHJ1Y3Rvcih1cGRhdGUgPSB7fSkge1xuICAgICAgbGV0IHRoZV92YWx1ZXMgPSBPYmplY3QuYXNzaWduKGRlZmF1bHRzLCB1cGRhdGUpO1xuICAgICAgT2JqZWN0LmFzc2lnbih0aGlzLCB0aGVfdmFsdWVzKTtcbiAgICB9XG5cbiAgICBzdGF0aWMgY3JlYXRlKHVwZGF0ZXMgPSB7fSkge1xuICAgICAgbGV0IHggPSBuZXcgdGhpcyh1cGRhdGVzKTtcbiAgICAgIHJldHVybiBPYmplY3QuZnJlZXplKHgpO1xuICAgIH1cbiAgfTtcbn1cblxuZnVuY3Rpb24gZGVmZXhjZXB0aW9uKGRlZmF1bHRzKSB7XG4gIHJldHVybiBjbGFzcyBleHRlbmRzIEVycm9yIHtcbiAgICBjb25zdHJ1Y3Rvcih1cGRhdGUgPSB7fSkge1xuICAgICAgbGV0IG1lc3NhZ2UgPSB1cGRhdGUubWVzc2FnZSB8fCAnJztcbiAgICAgIHN1cGVyKG1lc3NhZ2UpO1xuXG4gICAgICBsZXQgdGhlX3ZhbHVlcyA9IE9iamVjdC5hc3NpZ24oZGVmYXVsdHMsIHVwZGF0ZSk7XG4gICAgICBPYmplY3QuYXNzaWduKHRoaXMsIHRoZV92YWx1ZXMpO1xuXG4gICAgICB0aGlzLm5hbWUgPSB0aGlzLmNvbnN0cnVjdG9yLm5hbWU7XG4gICAgICB0aGlzLm1lc3NhZ2UgPSBtZXNzYWdlO1xuICAgICAgdGhpc1tTcGVjaWFsRm9ybXMuYXRvbSgnX19leGNlcHRpb25fXycpXSA9IHRydWU7XG4gICAgICBFcnJvci5jYXB0dXJlU3RhY2tUcmFjZSh0aGlzLCB0aGlzLmNvbnN0cnVjdG9yLm5hbWUpO1xuICAgIH1cblxuICAgIHN0YXRpYyBjcmVhdGUodXBkYXRlcyA9IHt9KSB7XG4gICAgICBsZXQgeCA9IG5ldyB0aGlzKHVwZGF0ZXMpO1xuICAgICAgcmV0dXJuIE9iamVjdC5mcmVlemUoeCk7XG4gICAgfVxuICB9O1xufVxuXG5mdW5jdGlvbiBkZWZwcm90b2NvbChzcGVjKSB7XG4gIHJldHVybiBuZXcgUHJvdG9jb2woc3BlYyk7XG59XG5cbmZ1bmN0aW9uIGRlZmltcGwocHJvdG9jb2wsIHR5cGUsIGltcGwpIHtcbiAgcHJvdG9jb2wuaW1wbGVtZW50YXRpb24odHlwZSwgaW1wbCk7XG59XG5cbmZ1bmN0aW9uIGdldF9vYmplY3Rfa2V5cyhvYmopIHtcbiAgcmV0dXJuIE9iamVjdC5rZXlzKG9iaikuY29uY2F0KE9iamVjdC5nZXRPd25Qcm9wZXJ0eVN5bWJvbHMob2JqKSk7XG59XG5cbmZ1bmN0aW9uIGlzX3ZhbGlkX2NoYXJhY3Rlcihjb2RlcG9pbnQpIHtcbiAgdHJ5IHtcbiAgICByZXR1cm4gU3RyaW5nLmZyb21Db2RlUG9pbnQoY29kZXBvaW50KSAhPSBudWxsO1xuICB9IGNhdGNoIChlKSB7XG4gICAgcmV0dXJuIGZhbHNlO1xuICB9XG59XG5cbi8vaHR0cHM6Ly9kZXZlbG9wZXIubW96aWxsYS5vcmcvZW4tVVMvZG9jcy9XZWIvQVBJL1dpbmRvd0Jhc2U2NC9CYXNlNjRfZW5jb2RpbmdfYW5kX2RlY29kaW5nI1NvbHV0aW9uXzJfJUUyJTgwJTkzX3Jld3JpdGVfdGhlX0RPTXNfYXRvYigpX2FuZF9idG9hKClfdXNpbmdfSmF2YVNjcmlwdCdzX1R5cGVkQXJyYXlzX2FuZF9VVEYtOFxuZnVuY3Rpb24gYjY0RW5jb2RlVW5pY29kZShzdHIpIHtcbiAgcmV0dXJuIGJ0b2EoZW5jb2RlVVJJQ29tcG9uZW50KHN0cikucmVwbGFjZSgvJShbMC05QS1GXXsyfSkvZywgZnVuY3Rpb24gKG1hdGNoLCBwMSkge1xuICAgIHJldHVybiBTdHJpbmcuZnJvbUNoYXJDb2RlKCcweCcgKyBwMSk7XG4gIH0pKTtcbn1cblxuZnVuY3Rpb24gZGVsZXRlX3Byb3BlcnR5X2Zyb21fbWFwKG1hcCwgcHJvcGVydHkpIHtcbiAgbGV0IG5ld19tYXAgPSBPYmplY3QuYXNzaWduKE9iamVjdC5jcmVhdGUobWFwLmNvbnN0cnVjdG9yLnByb3RvdHlwZSksIG1hcCk7XG4gIGRlbGV0ZSBuZXdfbWFwW3Byb3BlcnR5XTtcblxuICByZXR1cm4gT2JqZWN0LmZyZWV6ZShuZXdfbWFwKTtcbn1cblxuZnVuY3Rpb24gY2xhc3NfdG9fb2JqKG1hcCkge1xuICBsZXQgbmV3X21hcCA9IE9iamVjdC5hc3NpZ24oe30sIG1hcCk7XG4gIHJldHVybiBPYmplY3QuZnJlZXplKG5ld19tYXApO1xufVxuXG5mdW5jdGlvbiBhZGRfcHJvcGVydHlfdG9fbWFwKG1hcCwgcHJvcGVydHksIHZhbHVlKSB7XG4gIGxldCBuZXdfbWFwID0gT2JqZWN0LmFzc2lnbih7fSwgbWFwKTtcbiAgbmV3X21hcFtwcm9wZXJ0eV0gPSB2YWx1ZTtcbiAgcmV0dXJuIE9iamVjdC5mcmVlemUobmV3X21hcCk7XG59XG5cbmZ1bmN0aW9uIGJub3QoZXhwcikge1xuICByZXR1cm4gfmV4cHI7XG59XG5cbmZ1bmN0aW9uIGJhbmQobGVmdCwgcmlnaHQpIHtcbiAgcmV0dXJuIGxlZnQgJiByaWdodDtcbn1cblxuZnVuY3Rpb24gYm9yKGxlZnQsIHJpZ2h0KSB7XG4gIHJldHVybiBsZWZ0IHwgcmlnaHQ7XG59XG5cbmZ1bmN0aW9uIGJzbChsZWZ0LCByaWdodCkge1xuICByZXR1cm4gbGVmdCA8PCByaWdodDtcbn1cblxuZnVuY3Rpb24gYnNyKGxlZnQsIHJpZ2h0KSB7XG4gIHJldHVybiBsZWZ0ID4+IHJpZ2h0O1xufVxuXG5mdW5jdGlvbiBieG9yKGxlZnQsIHJpZ2h0KSB7XG4gIHJldHVybiBsZWZ0IF4gcmlnaHQ7XG59XG5cbmZ1bmN0aW9uIHppcChsaXN0X29mX2xpc3RzKSB7XG4gIGlmIChsaXN0X29mX2xpc3RzLmxlbmd0aCA9PT0gMCkge1xuICAgIHJldHVybiBPYmplY3QuZnJlZXplKFtdKTtcbiAgfVxuXG4gIGxldCBuZXdfdmFsdWUgPSBbXTtcbiAgbGV0IHNtYWxsZXN0X2xlbmd0aCA9IGxpc3Rfb2ZfbGlzdHNbMF07XG5cbiAgZm9yIChsZXQgeCBvZiBsaXN0X29mX2xpc3RzKSB7XG4gICAgaWYgKHgubGVuZ3RoIDwgc21hbGxlc3RfbGVuZ3RoKSB7XG4gICAgICBzbWFsbGVzdF9sZW5ndGggPSB4Lmxlbmd0aDtcbiAgICB9XG4gIH1cblxuICBmb3IgKGxldCBpID0gMDsgaSA8IHNtYWxsZXN0X2xlbmd0aDsgaSsrKSB7XG4gICAgbGV0IGN1cnJlbnRfdmFsdWUgPSBbXTtcbiAgICBmb3IgKGxldCBqID0gMDsgaiA8IGxpc3Rfb2ZfbGlzdHMubGVuZ3RoOyBqKyspIHtcbiAgICAgIGN1cnJlbnRfdmFsdWUucHVzaChsaXN0X29mX2xpc3RzW2pdW2ldKTtcbiAgICB9XG5cbiAgICBuZXdfdmFsdWUucHVzaChuZXcgVHVwbGUoLi4uY3VycmVudF92YWx1ZSkpO1xuICB9XG5cbiAgcmV0dXJuIE9iamVjdC5mcmVlemUobmV3X3ZhbHVlKTtcbn1cblxuZnVuY3Rpb24gY2FuX2RlY29kZTY0KGRhdGEpIHtcbiAgdHJ5IHtcbiAgICBhdG9iKGRhdGEpO1xuICAgIHJldHVybiB0cnVlO1xuICB9IGNhdGNoIChlKSB7XG4gICAgcmV0dXJuIGZhbHNlO1xuICB9XG59XG5cbnZhciBGdW5jdGlvbnMgPSB7XG4gIGNhbGxfcHJvcGVydHksXG4gIGFwcGx5LFxuICBjb250YWlucyxcbiAgZ2V0X2dsb2JhbCxcbiAgZGVmc3RydWN0LFxuICBkZWZleGNlcHRpb24sXG4gIGRlZnByb3RvY29sLFxuICBkZWZpbXBsLFxuICBnZXRfb2JqZWN0X2tleXMsXG4gIGlzX3ZhbGlkX2NoYXJhY3RlcixcbiAgYjY0RW5jb2RlVW5pY29kZSxcbiAgZGVsZXRlX3Byb3BlcnR5X2Zyb21fbWFwLFxuICBhZGRfcHJvcGVydHlfdG9fbWFwLFxuICBjbGFzc190b19vYmosXG4gIGNhbl9kZWNvZGU2NCxcbiAgYm5vdCxcbiAgYmFuZCxcbiAgYm9yLFxuICBic2wsXG4gIGJzcixcbiAgYnhvcixcbiAgemlwXG59O1xuXG5mdW5jdGlvbiBfY2FzZShjb25kaXRpb24sIGNsYXVzZXMpIHtcbiAgcmV0dXJuIFBhdHRlcm5zLmRlZm1hdGNoKC4uLmNsYXVzZXMpKGNvbmRpdGlvbik7XG59XG5cbmZ1bmN0aW9uIGNvbmQoY2xhdXNlcykge1xuICBmb3IgKGxldCBjbGF1c2Ugb2YgY2xhdXNlcykge1xuICAgIGlmIChjbGF1c2VbMF0pIHtcbiAgICAgIHJldHVybiBjbGF1c2VbMV0oKTtcbiAgICB9XG4gIH1cblxuICB0aHJvdyBuZXcgRXJyb3IoKTtcbn1cblxuZnVuY3Rpb24gbWFwX3VwZGF0ZShtYXAsIHZhbHVlcykge1xuICByZXR1cm4gT2JqZWN0LmZyZWV6ZShPYmplY3QuYXNzaWduKE9iamVjdC5jcmVhdGUobWFwLmNvbnN0cnVjdG9yLnByb3RvdHlwZSksIG1hcCwgdmFsdWVzKSk7XG59XG5cbmZ1bmN0aW9uIF9mb3IoY29sbGVjdGlvbnMsIGZ1biwgZmlsdGVyID0gKCkgPT4gdHJ1ZSwgaW50byA9IFtdLCBwcmV2aW91c1ZhbHVlcyA9IFtdKSB7XG4gIGxldCBwYXR0ZXJuID0gY29sbGVjdGlvbnNbMF1bMF07XG4gIGxldCBjb2xsZWN0aW9uID0gY29sbGVjdGlvbnNbMF1bMV07XG5cbiAgaWYgKGNvbGxlY3Rpb25zLmxlbmd0aCA9PT0gMSkge1xuXG4gICAgZm9yIChsZXQgZWxlbSBvZiBjb2xsZWN0aW9uKSB7XG4gICAgICBsZXQgciA9IFBhdHRlcm5zLm1hdGNoX25vX3Rocm93KHBhdHRlcm4sIGVsZW0pO1xuICAgICAgbGV0IGFyZ3MgPSBwcmV2aW91c1ZhbHVlcy5jb25jYXQocik7XG5cbiAgICAgIGlmIChyICYmIGZpbHRlci5hcHBseSh0aGlzLCBhcmdzKSkge1xuICAgICAgICBpbnRvID0gaW50by5jb25jYXQoW2Z1bi5hcHBseSh0aGlzLCBhcmdzKV0pO1xuICAgICAgfVxuICAgIH1cblxuICAgIHJldHVybiBpbnRvO1xuICB9IGVsc2Uge1xuICAgIGxldCBfaW50byA9IFtdO1xuXG4gICAgZm9yIChsZXQgZWxlbSBvZiBjb2xsZWN0aW9uKSB7XG4gICAgICBsZXQgciA9IFBhdHRlcm5zLm1hdGNoX25vX3Rocm93KHBhdHRlcm4sIGVsZW0pO1xuICAgICAgaWYgKHIpIHtcbiAgICAgICAgX2ludG8gPSBpbnRvLmNvbmNhdCh0aGlzLl9mb3IoY29sbGVjdGlvbnMuc2xpY2UoMSksIGZ1biwgZmlsdGVyLCBfaW50bywgcHJldmlvdXNWYWx1ZXMuY29uY2F0KHIpKSk7XG4gICAgICB9XG4gICAgfVxuXG4gICAgcmV0dXJuIF9pbnRvO1xuICB9XG59XG5cbmZ1bmN0aW9uIF90cnkoZG9fZnVuLCByZXNjdWVfZnVuY3Rpb24sIGNhdGNoX2Z1biwgZWxzZV9mdW5jdGlvbiwgYWZ0ZXJfZnVuY3Rpb24pIHtcbiAgbGV0IHJlc3VsdCA9IG51bGw7XG5cbiAgdHJ5IHtcbiAgICByZXN1bHQgPSBkb19mdW4oKTtcbiAgfSBjYXRjaCAoZSkge1xuICAgIGxldCBleF9yZXN1bHQgPSBudWxsO1xuXG4gICAgaWYgKHJlc2N1ZV9mdW5jdGlvbikge1xuICAgICAgdHJ5IHtcbiAgICAgICAgZXhfcmVzdWx0ID0gcmVzY3VlX2Z1bmN0aW9uKGUpO1xuICAgICAgICByZXR1cm4gZXhfcmVzdWx0O1xuICAgICAgfSBjYXRjaCAoZXgpIHtcbiAgICAgICAgaWYgKGV4IGluc3RhbmNlb2YgUGF0dGVybnMuTWF0Y2hFcnJvcikge1xuICAgICAgICAgIHRocm93IGV4O1xuICAgICAgICB9XG4gICAgICB9XG4gICAgfVxuXG4gICAgaWYgKGNhdGNoX2Z1bikge1xuICAgICAgdHJ5IHtcbiAgICAgICAgZXhfcmVzdWx0ID0gY2F0Y2hfZnVuKGUpO1xuICAgICAgICByZXR1cm4gZXhfcmVzdWx0O1xuICAgICAgfSBjYXRjaCAoZXgpIHtcbiAgICAgICAgaWYgKGV4IGluc3RhbmNlb2YgUGF0dGVybnMuTWF0Y2hFcnJvcikge1xuICAgICAgICAgIHRocm93IGV4O1xuICAgICAgICB9XG4gICAgICB9XG4gICAgfVxuXG4gICAgdGhyb3cgZTtcbiAgfSBmaW5hbGx5IHtcbiAgICBpZiAoYWZ0ZXJfZnVuY3Rpb24pIHtcbiAgICAgIGFmdGVyX2Z1bmN0aW9uKCk7XG4gICAgfVxuICB9XG5cbiAgaWYgKGVsc2VfZnVuY3Rpb24pIHtcbiAgICB0cnkge1xuICAgICAgcmV0dXJuIGVsc2VfZnVuY3Rpb24ocmVzdWx0KTtcbiAgICB9IGNhdGNoIChleCkge1xuICAgICAgaWYgKGV4IGluc3RhbmNlb2YgUGF0dGVybnMuTWF0Y2hFcnJvcikge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ05vIE1hdGNoIEZvdW5kIGluIEVsc2UnKTtcbiAgICAgIH1cblxuICAgICAgdGhyb3cgZXg7XG4gICAgfVxuICB9IGVsc2Uge1xuICAgIHJldHVybiByZXN1bHQ7XG4gIH1cbn1cblxudmFyIFNwZWNpYWxGb3JtcyQxID0ge1xuICBfY2FzZSxcbiAgY29uZCxcbiAgbWFwX3VwZGF0ZSxcbiAgX2ZvcixcbiAgX3RyeVxufTtcblxuRnVuY3Rpb25zLmdldF9nbG9iYWwoKS5wcm9jZXNzZXMgPSBGdW5jdGlvbnMuZ2V0X2dsb2JhbCgpLnByb2Nlc3NlcyB8fCBuZXcgUHJvY2Vzc1N5c3RlbSgpO1xuXG52YXIgQ29yZSA9IHtcbiAgUHJvY2Vzc1N5c3RlbSxcbiAgVHVwbGUsXG4gIFBJRCxcbiAgQml0U3RyaW5nLFxuICBQYXR0ZXJucyxcbiAgSW50ZWdlcixcbiAgRmxvYXQsXG4gIEZ1bmN0aW9ucyxcbiAgU3BlY2lhbEZvcm1zOiBTcGVjaWFsRm9ybXMkMVxufTtcblxubGV0IEVudW0gPSB7XG5cbiAgYWxsX19xbWFya19fOiBmdW5jdGlvbiAoY29sbGVjdGlvbiwgZnVuID0geCA9PiB4KSB7XG4gICAgZm9yIChsZXQgZWxlbSBvZiBjb2xsZWN0aW9uKSB7XG4gICAgICBpZiAoIWZ1bihlbGVtKSkge1xuICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICB9XG4gICAgfVxuXG4gICAgcmV0dXJuIHRydWU7XG4gIH0sXG5cbiAgYW55X19xbWFya19fOiBmdW5jdGlvbiAoY29sbGVjdGlvbiwgZnVuID0geCA9PiB4KSB7XG4gICAgZm9yIChsZXQgZWxlbSBvZiBjb2xsZWN0aW9uKSB7XG4gICAgICBpZiAoZnVuKGVsZW0pKSB7XG4gICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgfVxuICAgIH1cblxuICAgIHJldHVybiBmYWxzZTtcbiAgfSxcblxuICBhdDogZnVuY3Rpb24gKGNvbGxlY3Rpb24sIG4sIHRoZV9kZWZhdWx0ID0gbnVsbCkge1xuICAgIGlmIChuID4gdGhpcy5jb3VudChjb2xsZWN0aW9uKSB8fCBuIDwgMCkge1xuICAgICAgcmV0dXJuIHRoZV9kZWZhdWx0O1xuICAgIH1cblxuICAgIHJldHVybiBjb2xsZWN0aW9uW25dO1xuICB9LFxuXG4gIGNvbmNhdDogZnVuY3Rpb24gKC4uLmVudW1hYmxlcykge1xuICAgIHJldHVybiBlbnVtYWJsZXNbMF0uY29uY2F0KGVudW1hYmxlc1sxXSk7XG4gIH0sXG5cbiAgY291bnQ6IGZ1bmN0aW9uIChjb2xsZWN0aW9uLCBmdW4gPSBudWxsKSB7XG4gICAgaWYgKGZ1biA9PSBudWxsKSB7XG4gICAgICByZXR1cm4gY29sbGVjdGlvbi5sZW5ndGg7XG4gICAgfSBlbHNlIHtcbiAgICAgIHJldHVybiBjb2xsZWN0aW9uLmZpbHRlcihmdW4pLmxlbmd0aDtcbiAgICB9XG4gIH0sXG5cbiAgZHJvcDogZnVuY3Rpb24gKGNvbGxlY3Rpb24sIGNvdW50KSB7XG4gICAgcmV0dXJuIGNvbGxlY3Rpb24uc2xpY2UoY291bnQpO1xuICB9LFxuXG4gIGRyb3Bfd2hpbGU6IGZ1bmN0aW9uIChjb2xsZWN0aW9uLCBmdW4pIHtcbiAgICBsZXQgY291bnQgPSAwO1xuXG4gICAgZm9yIChsZXQgZWxlbSBvZiBjb2xsZWN0aW9uKSB7XG4gICAgICBpZiAoZnVuKGVsZW0pKSB7XG4gICAgICAgIGNvdW50ID0gY291bnQgKyAxO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgYnJlYWs7XG4gICAgICB9XG4gICAgfVxuXG4gICAgcmV0dXJuIGNvbGxlY3Rpb24uc2xpY2UoY291bnQpO1xuICB9LFxuXG4gIGVhY2g6IGZ1bmN0aW9uIChjb2xsZWN0aW9uLCBmdW4pIHtcbiAgICBmb3IgKGxldCBlbGVtIG9mIGNvbGxlY3Rpb24pIHtcbiAgICAgIGZ1bihlbGVtKTtcbiAgICB9XG4gIH0sXG5cbiAgZW1wdHlfX3FtYXJrX186IGZ1bmN0aW9uIChjb2xsZWN0aW9uKSB7XG4gICAgcmV0dXJuIGNvbGxlY3Rpb24ubGVuZ3RoID09PSAwO1xuICB9LFxuXG4gIGZldGNoOiBmdW5jdGlvbiAoY29sbGVjdGlvbiwgbikge1xuICAgIGlmIChBcnJheS5pc0FycmF5KGNvbGxlY3Rpb24pKSB7XG4gICAgICBpZiAobiA8IHRoaXMuY291bnQoY29sbGVjdGlvbikgJiYgbiA+PSAwKSB7XG4gICAgICAgIHJldHVybiBuZXcgQ29yZS5UdXBsZShTeW1ib2wuZm9yKFwib2tcIiksIGNvbGxlY3Rpb25bbl0pO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgcmV0dXJuIFN5bWJvbC5mb3IoXCJlcnJvclwiKTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICB0aHJvdyBuZXcgRXJyb3IoXCJjb2xsZWN0aW9uIGlzIG5vdCBhbiBFbnVtZXJhYmxlXCIpO1xuICB9LFxuXG4gIGZldGNoX19lbWFya19fOiBmdW5jdGlvbiAoY29sbGVjdGlvbiwgbikge1xuICAgIGlmIChBcnJheS5pc0FycmF5KGNvbGxlY3Rpb24pKSB7XG4gICAgICBpZiAobiA8IHRoaXMuY291bnQoY29sbGVjdGlvbikgJiYgbiA+PSAwKSB7XG4gICAgICAgIHJldHVybiBjb2xsZWN0aW9uW25dO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKFwib3V0IG9mIGJvdW5kcyBlcnJvclwiKTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICB0aHJvdyBuZXcgRXJyb3IoXCJjb2xsZWN0aW9uIGlzIG5vdCBhbiBFbnVtZXJhYmxlXCIpO1xuICB9LFxuXG4gIGZpbHRlcjogZnVuY3Rpb24gKGNvbGxlY3Rpb24sIGZ1bikge1xuICAgIGxldCByZXN1bHQgPSBbXTtcblxuICAgIGZvciAobGV0IGVsZW0gb2YgY29sbGVjdGlvbikge1xuICAgICAgaWYgKGZ1bihlbGVtKSkge1xuICAgICAgICByZXN1bHQucHVzaChlbGVtKTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICByZXR1cm4gcmVzdWx0O1xuICB9LFxuXG4gIGZpbHRlcl9tYXA6IGZ1bmN0aW9uIChjb2xsZWN0aW9uLCBmaWx0ZXIsIG1hcHBlcikge1xuICAgIHJldHVybiBFbnVtLm1hcChFbnVtLmZpbHRlcihjb2xsZWN0aW9uLCBmaWx0ZXIpLCBtYXBwZXIpO1xuICB9LFxuXG4gIGZpbmQ6IGZ1bmN0aW9uIChjb2xsZWN0aW9uLCBpZl9ub25lID0gbnVsbCwgZnVuKSB7XG4gICAgZm9yIChsZXQgZWxlbSBvZiBjb2xsZWN0aW9uKSB7XG4gICAgICBpZiAoZnVuKGVsZW0pKSB7XG4gICAgICAgIHJldHVybiBlbGVtO1xuICAgICAgfVxuICAgIH1cblxuICAgIHJldHVybiBpZl9ub25lO1xuICB9LFxuXG4gIGludG86IGZ1bmN0aW9uIChjb2xsZWN0aW9uLCBsaXN0KSB7XG4gICAgcmV0dXJuIGxpc3QuY29uY2F0KGNvbGxlY3Rpb24pO1xuICB9LFxuXG4gIG1hcDogZnVuY3Rpb24gKGNvbGxlY3Rpb24sIGZ1bikge1xuICAgIGxldCByZXN1bHQgPSBbXTtcblxuICAgIGZvciAobGV0IGVsZW0gb2YgY29sbGVjdGlvbikge1xuICAgICAgcmVzdWx0LnB1c2goZnVuKGVsZW0pKTtcbiAgICB9XG5cbiAgICByZXR1cm4gcmVzdWx0O1xuICB9LFxuXG4gIG1hcF9yZWR1Y2U6IGZ1bmN0aW9uIChjb2xsZWN0aW9uLCBhY2MsIGZ1bikge1xuICAgIGxldCBtYXBwZWQgPSBPYmplY3QuZnJlZXplKFtdKTtcbiAgICBsZXQgdGhlX2FjYyA9IGFjYztcblxuICAgIGZvciAodmFyIGkgPSAwOyBpIDwgdGhpcy5jb3VudChjb2xsZWN0aW9uKTsgaSsrKSB7XG4gICAgICBsZXQgdHVwbGUgPSBmdW4oY29sbGVjdGlvbltpXSwgdGhlX2FjYyk7XG5cbiAgICAgIHRoZV9hY2MgPSB0dXBsZS5nZXQoMSk7XG4gICAgICBtYXBwZWQgPSBPYmplY3QuZnJlZXplKG1hcHBlZC5jb25jYXQoW3R1cGxlLmdldCgwKV0pKTtcbiAgICB9XG5cbiAgICByZXR1cm4gbmV3IENvcmUuVHVwbGUobWFwcGVkLCB0aGVfYWNjKTtcbiAgfSxcblxuICBtZW1iZXJfX3FtYXJrX186IGZ1bmN0aW9uIChjb2xsZWN0aW9uLCB2YWx1ZSkge1xuICAgIHJldHVybiBjb2xsZWN0aW9uLmluY2x1ZGVzKHZhbHVlKTtcbiAgfSxcblxuICByZWR1Y2U6IGZ1bmN0aW9uIChjb2xsZWN0aW9uLCBhY2MsIGZ1bikge1xuICAgIGxldCB0aGVfYWNjID0gYWNjO1xuXG4gICAgZm9yICh2YXIgaSA9IDA7IGkgPCB0aGlzLmNvdW50KGNvbGxlY3Rpb24pOyBpKyspIHtcbiAgICAgIGxldCB0dXBsZSA9IGZ1bihjb2xsZWN0aW9uW2ldLCB0aGVfYWNjKTtcblxuICAgICAgdGhlX2FjYyA9IHR1cGxlLmdldCgxKTtcbiAgICB9XG5cbiAgICByZXR1cm4gdGhlX2FjYztcbiAgfSxcblxuICB0YWtlOiBmdW5jdGlvbiAoY29sbGVjdGlvbiwgY291bnQpIHtcbiAgICByZXR1cm4gY29sbGVjdGlvbi5zbGljZSgwLCBjb3VudCk7XG4gIH0sXG5cbiAgdGFrZV9ldmVyeTogZnVuY3Rpb24gKGNvbGxlY3Rpb24sIG50aCkge1xuICAgIGxldCByZXN1bHQgPSBbXTtcbiAgICBsZXQgaW5kZXggPSAwO1xuXG4gICAgZm9yIChsZXQgZWxlbSBvZiBjb2xsZWN0aW9uKSB7XG4gICAgICBpZiAoaW5kZXggJSBudGggPT09IDApIHtcbiAgICAgICAgcmVzdWx0LnB1c2goZWxlbSk7XG4gICAgICB9XG4gICAgfVxuXG4gICAgcmV0dXJuIE9iamVjdC5mcmVlemUocmVzdWx0KTtcbiAgfSxcblxuICB0YWtlX3doaWxlOiBmdW5jdGlvbiAoY29sbGVjdGlvbiwgZnVuKSB7XG4gICAgbGV0IGNvdW50ID0gMDtcblxuICAgIGZvciAobGV0IGVsZW0gb2YgY29sbGVjdGlvbikge1xuICAgICAgaWYgKGZ1bihlbGVtKSkge1xuICAgICAgICBjb3VudCA9IGNvdW50ICsgMTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIGJyZWFrO1xuICAgICAgfVxuICAgIH1cblxuICAgIHJldHVybiBjb2xsZWN0aW9uLnNsaWNlKDAsIGNvdW50KTtcbiAgfSxcblxuICB0b19saXN0OiBmdW5jdGlvbiAoY29sbGVjdGlvbikge1xuICAgIHJldHVybiBjb2xsZWN0aW9uO1xuICB9XG59O1xuXG52YXIgRWxpeGlyID0ge1xuICBDb3JlLFxuICBFbnVtLFxuICBWaXJ0dWFsRE9NXG59O1xuXG5leHBvcnQgZGVmYXVsdCBFbGl4aXI7Il0sImZpbGUiOiJFbGl4aXIuanMiLCJzb3VyY2VSb290IjoiL3NvdXJjZS8ifQ== \ No newline at end of file +//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiIiwic291cmNlcyI6WyJFbGl4aXIuanMiXSwic291cmNlc0NvbnRlbnQiOlsibGV0IFZpcnR1YWxET00gPSAoZnVuY3Rpb24gKGUpIHtcbiAgICByZXR1cm4gZSgpO1xufSkoZnVuY3Rpb24gKCkge1xuICAgIHZhciBkZWZpbmUsIG1vZHVsZSwgZXhwb3J0cztcbiAgICByZXR1cm4gKGZ1bmN0aW9uIGUodCwgbiwgcikge1xuICAgICAgICBmdW5jdGlvbiBzKG8sIHUpIHtcbiAgICAgICAgICAgIGlmICghbltvXSkge1xuICAgICAgICAgICAgICAgIGlmICghdFtvXSkge1xuICAgICAgICAgICAgICAgICAgICB2YXIgYSA9IHR5cGVvZiByZXF1aXJlID09IFwiZnVuY3Rpb25cIiAmJiByZXF1aXJlO1xuICAgICAgICAgICAgICAgICAgICBpZiAoIXUgJiYgYSkgcmV0dXJuIGEobywgITApO1xuICAgICAgICAgICAgICAgICAgICBpZiAoaSkgcmV0dXJuIGkobywgITApO1xuICAgICAgICAgICAgICAgICAgICB2YXIgZiA9IG5ldyBFcnJvcihcIkNhbm5vdCBmaW5kIG1vZHVsZSAnXCIgKyBvICsgXCInXCIpO1xuICAgICAgICAgICAgICAgICAgICB0aHJvdyAoZi5jb2RlID0gXCJNT0RVTEVfTk9UX0ZPVU5EXCIsIGYpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB2YXIgbCA9IG5bb10gPSB7XG4gICAgICAgICAgICAgICAgICAgIGV4cG9ydHM6IHt9XG4gICAgICAgICAgICAgICAgfTtcbiAgICAgICAgICAgICAgICB0W29dWzBdLmNhbGwobC5leHBvcnRzLCBmdW5jdGlvbiAoZSkge1xuICAgICAgICAgICAgICAgICAgICB2YXIgbiA9IHRbb11bMV1bZV07XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBzKG4gPyBuIDogZSk7XG4gICAgICAgICAgICAgICAgfSwgbCwgbC5leHBvcnRzLCBlLCB0LCBuLCByKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJldHVybiBuW29dLmV4cG9ydHM7XG4gICAgICAgIH1cbiAgICAgICAgdmFyIGkgPSB0eXBlb2YgcmVxdWlyZSA9PSBcImZ1bmN0aW9uXCIgJiYgcmVxdWlyZTtcbiAgICAgICAgZm9yICh2YXIgbyA9IDA7IG8gPCByLmxlbmd0aDsgbysrKSBzKHJbb10pO1xuICAgICAgICByZXR1cm4gcztcbiAgICB9KSh7XG4gICAgICAgIDE6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG5cbiAgICAgICAgICAgIHZhciBjcmVhdGVFbGVtZW50ID0gcmVxdWlyZShcIi4vdmRvbS9jcmVhdGUtZWxlbWVudC5qc1wiKTtcblxuICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBjcmVhdGVFbGVtZW50O1xuICAgICAgICB9LCB7IFwiLi92ZG9tL2NyZWF0ZS1lbGVtZW50LmpzXCI6IDE1IH1dLCAyOiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge1xuICAgICAgICAgICAgdmFyIGRpZmYgPSByZXF1aXJlKFwiLi92dHJlZS9kaWZmLmpzXCIpO1xuXG4gICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IGRpZmY7XG4gICAgICAgIH0sIHsgXCIuL3Z0cmVlL2RpZmYuanNcIjogMzUgfV0sIDM6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICB2YXIgaCA9IHJlcXVpcmUoXCIuL3ZpcnR1YWwtaHlwZXJzY3JpcHQvaW5kZXguanNcIik7XG5cbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gaDtcbiAgICAgICAgfSwgeyBcIi4vdmlydHVhbC1oeXBlcnNjcmlwdC9pbmRleC5qc1wiOiAyMiB9XSwgNDogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHtcbiAgICAgICAgICAgIHZhciBkaWZmID0gcmVxdWlyZShcIi4vZGlmZi5qc1wiKTtcbiAgICAgICAgICAgIHZhciBwYXRjaCA9IHJlcXVpcmUoXCIuL3BhdGNoLmpzXCIpO1xuICAgICAgICAgICAgdmFyIGggPSByZXF1aXJlKFwiLi9oLmpzXCIpO1xuICAgICAgICAgICAgdmFyIGNyZWF0ZSA9IHJlcXVpcmUoXCIuL2NyZWF0ZS1lbGVtZW50LmpzXCIpO1xuICAgICAgICAgICAgdmFyIFZOb2RlID0gcmVxdWlyZShcIi4vdm5vZGUvdm5vZGUuanNcIik7XG4gICAgICAgICAgICB2YXIgVlRleHQgPSByZXF1aXJlKFwiLi92bm9kZS92dGV4dC5qc1wiKTtcblxuICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSB7XG4gICAgICAgICAgICAgICAgZGlmZjogZGlmZixcbiAgICAgICAgICAgICAgICBwYXRjaDogcGF0Y2gsXG4gICAgICAgICAgICAgICAgaDogaCxcbiAgICAgICAgICAgICAgICBjcmVhdGU6IGNyZWF0ZSxcbiAgICAgICAgICAgICAgICBWTm9kZTogVk5vZGUsXG4gICAgICAgICAgICAgICAgVlRleHQ6IFZUZXh0XG4gICAgICAgICAgICB9O1xuICAgICAgICB9LCB7IFwiLi9jcmVhdGUtZWxlbWVudC5qc1wiOiAxLCBcIi4vZGlmZi5qc1wiOiAyLCBcIi4vaC5qc1wiOiAzLCBcIi4vcGF0Y2guanNcIjogMTMsIFwiLi92bm9kZS92bm9kZS5qc1wiOiAzMSwgXCIuL3Zub2RlL3Z0ZXh0LmpzXCI6IDMzIH1dLCA1OiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge1xuICAgICAgICAgICAgLyohXG4gICAgICAgICAgICAgKiBDcm9zcy1Ccm93c2VyIFNwbGl0IDEuMS4xXG4gICAgICAgICAgICAgKiBDb3B5cmlnaHQgMjAwNy0yMDEyIFN0ZXZlbiBMZXZpdGhhbiA8c3RldmVubGV2aXRoYW4uY29tPlxuICAgICAgICAgICAgICogQXZhaWxhYmxlIHVuZGVyIHRoZSBNSVQgTGljZW5zZVxuICAgICAgICAgICAgICogRUNNQVNjcmlwdCBjb21wbGlhbnQsIHVuaWZvcm0gY3Jvc3MtYnJvd3NlciBzcGxpdCBtZXRob2RcbiAgICAgICAgICAgICAqL1xuXG4gICAgICAgICAgICAvKipcbiAgICAgICAgICAgICAqIFNwbGl0cyBhIHN0cmluZyBpbnRvIGFuIGFycmF5IG9mIHN0cmluZ3MgdXNpbmcgYSByZWdleCBvciBzdHJpbmcgc2VwYXJhdG9yLiBNYXRjaGVzIG9mIHRoZVxuICAgICAgICAgICAgICogc2VwYXJhdG9yIGFyZSBub3QgaW5jbHVkZWQgaW4gdGhlIHJlc3VsdCBhcnJheS4gSG93ZXZlciwgaWYgYHNlcGFyYXRvcmAgaXMgYSByZWdleCB0aGF0IGNvbnRhaW5zXG4gICAgICAgICAgICAgKiBjYXB0dXJpbmcgZ3JvdXBzLCBiYWNrcmVmZXJlbmNlcyBhcmUgc3BsaWNlZCBpbnRvIHRoZSByZXN1bHQgZWFjaCB0aW1lIGBzZXBhcmF0b3JgIGlzIG1hdGNoZWQuXG4gICAgICAgICAgICAgKiBGaXhlcyBicm93c2VyIGJ1Z3MgY29tcGFyZWQgdG8gdGhlIG5hdGl2ZSBgU3RyaW5nLnByb3RvdHlwZS5zcGxpdGAgYW5kIGNhbiBiZSB1c2VkIHJlbGlhYmx5XG4gICAgICAgICAgICAgKiBjcm9zcy1icm93c2VyLlxuICAgICAgICAgICAgICogQHBhcmFtIHtTdHJpbmd9IHN0ciBTdHJpbmcgdG8gc3BsaXQuXG4gICAgICAgICAgICAgKiBAcGFyYW0ge1JlZ0V4cHxTdHJpbmd9IHNlcGFyYXRvciBSZWdleCBvciBzdHJpbmcgdG8gdXNlIGZvciBzZXBhcmF0aW5nIHRoZSBzdHJpbmcuXG4gICAgICAgICAgICAgKiBAcGFyYW0ge051bWJlcn0gW2xpbWl0XSBNYXhpbXVtIG51bWJlciBvZiBpdGVtcyB0byBpbmNsdWRlIGluIHRoZSByZXN1bHQgYXJyYXkuXG4gICAgICAgICAgICAgKiBAcmV0dXJucyB7QXJyYXl9IEFycmF5IG9mIHN1YnN0cmluZ3MuXG4gICAgICAgICAgICAgKiBAZXhhbXBsZVxuICAgICAgICAgICAgICpcbiAgICAgICAgICAgICAqIC8vIEJhc2ljIHVzZVxuICAgICAgICAgICAgICogc3BsaXQoJ2EgYiBjIGQnLCAnICcpO1xuICAgICAgICAgICAgICogLy8gLT4gWydhJywgJ2InLCAnYycsICdkJ11cbiAgICAgICAgICAgICAqXG4gICAgICAgICAgICAgKiAvLyBXaXRoIGxpbWl0XG4gICAgICAgICAgICAgKiBzcGxpdCgnYSBiIGMgZCcsICcgJywgMik7XG4gICAgICAgICAgICAgKiAvLyAtPiBbJ2EnLCAnYiddXG4gICAgICAgICAgICAgKlxuICAgICAgICAgICAgICogLy8gQmFja3JlZmVyZW5jZXMgaW4gcmVzdWx0IGFycmF5XG4gICAgICAgICAgICAgKiBzcGxpdCgnLi53b3JkMSB3b3JkMi4uJywgLyhbYS16XSspKFxcZCspL2kpO1xuICAgICAgICAgICAgICogLy8gLT4gWycuLicsICd3b3JkJywgJzEnLCAnICcsICd3b3JkJywgJzInLCAnLi4nXVxuICAgICAgICAgICAgICovXG4gICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IChmdW5jdGlvbiBzcGxpdCh1bmRlZikge1xuXG4gICAgICAgICAgICAgICAgdmFyIG5hdGl2ZVNwbGl0ID0gU3RyaW5nLnByb3RvdHlwZS5zcGxpdCxcbiAgICAgICAgICAgICAgICAgICAgY29tcGxpYW50RXhlY05wY2cgPSAvKCk/Py8uZXhlYyhcIlwiKVsxXSA9PT0gdW5kZWYsXG5cbiAgICAgICAgICAgICAgICAvLyBOUENHOiBub25wYXJ0aWNpcGF0aW5nIGNhcHR1cmluZyBncm91cFxuICAgICAgICAgICAgICAgIHNlbGY7XG5cbiAgICAgICAgICAgICAgICBzZWxmID0gZnVuY3Rpb24gKHN0ciwgc2VwYXJhdG9yLCBsaW1pdCkge1xuICAgICAgICAgICAgICAgICAgICAvLyBJZiBgc2VwYXJhdG9yYCBpcyBub3QgYSByZWdleCwgdXNlIGBuYXRpdmVTcGxpdGBcbiAgICAgICAgICAgICAgICAgICAgaWYgKE9iamVjdC5wcm90b3R5cGUudG9TdHJpbmcuY2FsbChzZXBhcmF0b3IpICE9PSBcIltvYmplY3QgUmVnRXhwXVwiKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gbmF0aXZlU3BsaXQuY2FsbChzdHIsIHNlcGFyYXRvciwgbGltaXQpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIHZhciBvdXRwdXQgPSBbXSxcbiAgICAgICAgICAgICAgICAgICAgICAgIGZsYWdzID0gKHNlcGFyYXRvci5pZ25vcmVDYXNlID8gXCJpXCIgOiBcIlwiKSArIChzZXBhcmF0b3IubXVsdGlsaW5lID8gXCJtXCIgOiBcIlwiKSArIChzZXBhcmF0b3IuZXh0ZW5kZWQgPyBcInhcIiA6IFwiXCIpICsgKHNlcGFyYXRvci5zdGlja3kgPyBcInlcIiA6IFwiXCIpLFxuXG4gICAgICAgICAgICAgICAgICAgIC8vIEZpcmVmb3ggMytcbiAgICAgICAgICAgICAgICAgICAgbGFzdExhc3RJbmRleCA9IDAsXG5cbiAgICAgICAgICAgICAgICAgICAgLy8gTWFrZSBgZ2xvYmFsYCBhbmQgYXZvaWQgYGxhc3RJbmRleGAgaXNzdWVzIGJ5IHdvcmtpbmcgd2l0aCBhIGNvcHlcbiAgICAgICAgICAgICAgICAgICAgc2VwYXJhdG9yID0gbmV3IFJlZ0V4cChzZXBhcmF0b3Iuc291cmNlLCBmbGFncyArIFwiZ1wiKSxcbiAgICAgICAgICAgICAgICAgICAgICAgIHNlcGFyYXRvcjIsXG4gICAgICAgICAgICAgICAgICAgICAgICBtYXRjaCxcbiAgICAgICAgICAgICAgICAgICAgICAgIGxhc3RJbmRleCxcbiAgICAgICAgICAgICAgICAgICAgICAgIGxhc3RMZW5ndGg7XG4gICAgICAgICAgICAgICAgICAgIHN0ciArPSBcIlwiOyAvLyBUeXBlLWNvbnZlcnRcbiAgICAgICAgICAgICAgICAgICAgaWYgKCFjb21wbGlhbnRFeGVjTnBjZykge1xuICAgICAgICAgICAgICAgICAgICAgICAgLy8gRG9lc24ndCBuZWVkIGZsYWdzIGd5LCBidXQgdGhleSBkb24ndCBodXJ0XG4gICAgICAgICAgICAgICAgICAgICAgICBzZXBhcmF0b3IyID0gbmV3IFJlZ0V4cChcIl5cIiArIHNlcGFyYXRvci5zb3VyY2UgKyBcIiQoPyFcXFxccylcIiwgZmxhZ3MpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIC8qIFZhbHVlcyBmb3IgYGxpbWl0YCwgcGVyIHRoZSBzcGVjOlxuICAgICAgICAgICAgICAgICAgICAgKiBJZiB1bmRlZmluZWQ6IDQyOTQ5NjcyOTUgLy8gTWF0aC5wb3coMiwgMzIpIC0gMVxuICAgICAgICAgICAgICAgICAgICAgKiBJZiAwLCBJbmZpbml0eSwgb3IgTmFOOiAwXG4gICAgICAgICAgICAgICAgICAgICAqIElmIHBvc2l0aXZlIG51bWJlcjogbGltaXQgPSBNYXRoLmZsb29yKGxpbWl0KTsgaWYgKGxpbWl0ID4gNDI5NDk2NzI5NSkgbGltaXQgLT0gNDI5NDk2NzI5NjtcbiAgICAgICAgICAgICAgICAgICAgICogSWYgbmVnYXRpdmUgbnVtYmVyOiA0Mjk0OTY3Mjk2IC0gTWF0aC5mbG9vcihNYXRoLmFicyhsaW1pdCkpXG4gICAgICAgICAgICAgICAgICAgICAqIElmIG90aGVyOiBUeXBlLWNvbnZlcnQsIHRoZW4gdXNlIHRoZSBhYm92ZSBydWxlc1xuICAgICAgICAgICAgICAgICAgICAgKi9cbiAgICAgICAgICAgICAgICAgICAgbGltaXQgPSBsaW1pdCA9PT0gdW5kZWYgPyAtMSA+Pj4gMCA6IC8vIE1hdGgucG93KDIsIDMyKSAtIDFcbiAgICAgICAgICAgICAgICAgICAgbGltaXQgPj4+IDA7IC8vIFRvVWludDMyKGxpbWl0KVxuICAgICAgICAgICAgICAgICAgICB3aGlsZSAobWF0Y2ggPSBzZXBhcmF0b3IuZXhlYyhzdHIpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAvLyBgc2VwYXJhdG9yLmxhc3RJbmRleGAgaXMgbm90IHJlbGlhYmxlIGNyb3NzLWJyb3dzZXJcbiAgICAgICAgICAgICAgICAgICAgICAgIGxhc3RJbmRleCA9IG1hdGNoLmluZGV4ICsgbWF0Y2hbMF0ubGVuZ3RoO1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGxhc3RJbmRleCA+IGxhc3RMYXN0SW5kZXgpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBvdXRwdXQucHVzaChzdHIuc2xpY2UobGFzdExhc3RJbmRleCwgbWF0Y2guaW5kZXgpKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBGaXggYnJvd3NlcnMgd2hvc2UgYGV4ZWNgIG1ldGhvZHMgZG9uJ3QgY29uc2lzdGVudGx5IHJldHVybiBgdW5kZWZpbmVkYCBmb3JcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBub25wYXJ0aWNpcGF0aW5nIGNhcHR1cmluZyBncm91cHNcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoIWNvbXBsaWFudEV4ZWNOcGNnICYmIG1hdGNoLmxlbmd0aCA+IDEpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbWF0Y2hbMF0ucmVwbGFjZShzZXBhcmF0b3IyLCBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBmb3IgKHZhciBpID0gMTsgaSA8IGFyZ3VtZW50cy5sZW5ndGggLSAyOyBpKyspIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoYXJndW1lbnRzW2ldID09PSB1bmRlZikge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBtYXRjaFtpXSA9IHVuZGVmO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChtYXRjaC5sZW5ndGggPiAxICYmIG1hdGNoLmluZGV4IDwgc3RyLmxlbmd0aCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBBcnJheS5wcm90b3R5cGUucHVzaC5hcHBseShvdXRwdXQsIG1hdGNoLnNsaWNlKDEpKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgbGFzdExlbmd0aCA9IG1hdGNoWzBdLmxlbmd0aDtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBsYXN0TGFzdEluZGV4ID0gbGFzdEluZGV4O1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChvdXRwdXQubGVuZ3RoID49IGxpbWl0KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChzZXBhcmF0b3IubGFzdEluZGV4ID09PSBtYXRjaC5pbmRleCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNlcGFyYXRvci5sYXN0SW5kZXgrKzsgLy8gQXZvaWQgYW4gaW5maW5pdGUgbG9vcFxuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIGlmIChsYXN0TGFzdEluZGV4ID09PSBzdHIubGVuZ3RoKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAobGFzdExlbmd0aCB8fCAhc2VwYXJhdG9yLnRlc3QoXCJcIikpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBvdXRwdXQucHVzaChcIlwiKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIG91dHB1dC5wdXNoKHN0ci5zbGljZShsYXN0TGFzdEluZGV4KSk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIG91dHB1dC5sZW5ndGggPiBsaW1pdCA/IG91dHB1dC5zbGljZSgwLCBsaW1pdCkgOiBvdXRwdXQ7XG4gICAgICAgICAgICAgICAgfTtcblxuICAgICAgICAgICAgICAgIHJldHVybiBzZWxmO1xuICAgICAgICAgICAgfSkoKTtcbiAgICAgICAgfSwge31dLCA2OiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge30sIHt9XSwgNzogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHtcbiAgICAgICAgICAgIFwidXNlIHN0cmljdFwiO1xuXG4gICAgICAgICAgICB2YXIgT25lVmVyc2lvbkNvbnN0cmFpbnQgPSByZXF1aXJlKFwiaW5kaXZpZHVhbC9vbmUtdmVyc2lvblwiKTtcblxuICAgICAgICAgICAgdmFyIE1ZX1ZFUlNJT04gPSBcIjdcIjtcbiAgICAgICAgICAgIE9uZVZlcnNpb25Db25zdHJhaW50KFwiZXYtc3RvcmVcIiwgTVlfVkVSU0lPTik7XG5cbiAgICAgICAgICAgIHZhciBoYXNoS2V5ID0gXCJfX0VWX1NUT1JFX0tFWUBcIiArIE1ZX1ZFUlNJT047XG5cbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gRXZTdG9yZTtcblxuICAgICAgICAgICAgZnVuY3Rpb24gRXZTdG9yZShlbGVtKSB7XG4gICAgICAgICAgICAgICAgdmFyIGhhc2ggPSBlbGVtW2hhc2hLZXldO1xuXG4gICAgICAgICAgICAgICAgaWYgKCFoYXNoKSB7XG4gICAgICAgICAgICAgICAgICAgIGhhc2ggPSBlbGVtW2hhc2hLZXldID0ge307XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgcmV0dXJuIGhhc2g7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0sIHsgXCJpbmRpdmlkdWFsL29uZS12ZXJzaW9uXCI6IDkgfV0sIDg6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICAoZnVuY3Rpb24gKGdsb2JhbCkge1xuICAgICAgICAgICAgICAgIFwidXNlIHN0cmljdFwiO1xuXG4gICAgICAgICAgICAgICAgLypnbG9iYWwgd2luZG93LCBnbG9iYWwqL1xuXG4gICAgICAgICAgICAgICAgdmFyIHJvb3QgPSB0eXBlb2Ygd2luZG93ICE9PSBcInVuZGVmaW5lZFwiID8gd2luZG93IDogdHlwZW9mIGdsb2JhbCAhPT0gXCJ1bmRlZmluZWRcIiA/IGdsb2JhbCA6IHt9O1xuXG4gICAgICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBJbmRpdmlkdWFsO1xuXG4gICAgICAgICAgICAgICAgZnVuY3Rpb24gSW5kaXZpZHVhbChrZXksIHZhbHVlKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmIChrZXkgaW4gcm9vdCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHJvb3Rba2V5XTtcbiAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgIHJvb3Rba2V5XSA9IHZhbHVlO1xuXG4gICAgICAgICAgICAgICAgICAgIHJldHVybiB2YWx1ZTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9KS5jYWxsKHRoaXMsIHR5cGVvZiBnbG9iYWwgIT09IFwidW5kZWZpbmVkXCIgPyBnbG9iYWwgOiB0eXBlb2Ygc2VsZiAhPT0gXCJ1bmRlZmluZWRcIiA/IHNlbGYgOiB0eXBlb2Ygd2luZG93ICE9PSBcInVuZGVmaW5lZFwiID8gd2luZG93IDoge30pO1xuICAgICAgICB9LCB7fV0sIDk6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICBcInVzZSBzdHJpY3RcIjtcblxuICAgICAgICAgICAgdmFyIEluZGl2aWR1YWwgPSByZXF1aXJlKFwiLi9pbmRleC5qc1wiKTtcblxuICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBPbmVWZXJzaW9uO1xuXG4gICAgICAgICAgICBmdW5jdGlvbiBPbmVWZXJzaW9uKG1vZHVsZU5hbWUsIHZlcnNpb24sIGRlZmF1bHRWYWx1ZSkge1xuICAgICAgICAgICAgICAgIHZhciBrZXkgPSBcIl9fSU5ESVZJRFVBTF9PTkVfVkVSU0lPTl9cIiArIG1vZHVsZU5hbWU7XG4gICAgICAgICAgICAgICAgdmFyIGVuZm9yY2VLZXkgPSBrZXkgKyBcIl9FTkZPUkNFX1NJTkdMRVRPTlwiO1xuXG4gICAgICAgICAgICAgICAgdmFyIHZlcnNpb25WYWx1ZSA9IEluZGl2aWR1YWwoZW5mb3JjZUtleSwgdmVyc2lvbik7XG5cbiAgICAgICAgICAgICAgICBpZiAodmVyc2lvblZhbHVlICE9PSB2ZXJzaW9uKSB7XG4gICAgICAgICAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcihcIkNhbiBvbmx5IGhhdmUgb25lIGNvcHkgb2YgXCIgKyBtb2R1bGVOYW1lICsgXCIuXFxuXCIgKyBcIllvdSBhbHJlYWR5IGhhdmUgdmVyc2lvbiBcIiArIHZlcnNpb25WYWx1ZSArIFwiIGluc3RhbGxlZC5cXG5cIiArIFwiVGhpcyBtZWFucyB5b3UgY2Fubm90IGluc3RhbGwgdmVyc2lvbiBcIiArIHZlcnNpb24pO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHJldHVybiBJbmRpdmlkdWFsKGtleSwgZGVmYXVsdFZhbHVlKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSwgeyBcIi4vaW5kZXguanNcIjogOCB9XSwgMTA6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICAoZnVuY3Rpb24gKGdsb2JhbCkge1xuICAgICAgICAgICAgICAgIHZhciB0b3BMZXZlbCA9IHR5cGVvZiBnbG9iYWwgIT09IFwidW5kZWZpbmVkXCIgPyBnbG9iYWwgOiB0eXBlb2Ygd2luZG93ICE9PSBcInVuZGVmaW5lZFwiID8gd2luZG93IDoge307XG4gICAgICAgICAgICAgICAgdmFyIG1pbkRvYyA9IHJlcXVpcmUoXCJtaW4tZG9jdW1lbnRcIik7XG5cbiAgICAgICAgICAgICAgICBpZiAodHlwZW9mIGRvY3VtZW50ICE9PSBcInVuZGVmaW5lZFwiKSB7XG4gICAgICAgICAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gZG9jdW1lbnQ7XG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgdmFyIGRvY2N5ID0gdG9wTGV2ZWxbXCJfX0dMT0JBTF9ET0NVTUVOVF9DQUNIRUA0XCJdO1xuXG4gICAgICAgICAgICAgICAgICAgIGlmICghZG9jY3kpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGRvY2N5ID0gdG9wTGV2ZWxbXCJfX0dMT0JBTF9ET0NVTUVOVF9DQUNIRUA0XCJdID0gbWluRG9jO1xuICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBkb2NjeTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9KS5jYWxsKHRoaXMsIHR5cGVvZiBnbG9iYWwgIT09IFwidW5kZWZpbmVkXCIgPyBnbG9iYWwgOiB0eXBlb2Ygc2VsZiAhPT0gXCJ1bmRlZmluZWRcIiA/IHNlbGYgOiB0eXBlb2Ygd2luZG93ICE9PSBcInVuZGVmaW5lZFwiID8gd2luZG93IDoge30pO1xuICAgICAgICB9LCB7IFwibWluLWRvY3VtZW50XCI6IDYgfV0sIDExOiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge1xuICAgICAgICAgICAgXCJ1c2Ugc3RyaWN0XCI7XG5cbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gaXNPYmplY3QoeCkge1xuICAgICAgICAgICAgICAgIHJldHVybiB0eXBlb2YgeCA9PT0gXCJvYmplY3RcIiAmJiB4ICE9PSBudWxsO1xuICAgICAgICAgICAgfTtcbiAgICAgICAgfSwge31dLCAxMjogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHtcbiAgICAgICAgICAgIHZhciBuYXRpdmVJc0FycmF5ID0gQXJyYXkuaXNBcnJheTtcbiAgICAgICAgICAgIHZhciB0b1N0cmluZyA9IE9iamVjdC5wcm90b3R5cGUudG9TdHJpbmc7XG5cbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gbmF0aXZlSXNBcnJheSB8fCBpc0FycmF5O1xuXG4gICAgICAgICAgICBmdW5jdGlvbiBpc0FycmF5KG9iaikge1xuICAgICAgICAgICAgICAgIHJldHVybiB0b1N0cmluZy5jYWxsKG9iaikgPT09IFwiW29iamVjdCBBcnJheV1cIjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSwge31dLCAxMzogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHtcbiAgICAgICAgICAgIHZhciBwYXRjaCA9IHJlcXVpcmUoXCIuL3Zkb20vcGF0Y2guanNcIik7XG5cbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gcGF0Y2g7XG4gICAgICAgIH0sIHsgXCIuL3Zkb20vcGF0Y2guanNcIjogMTggfV0sIDE0OiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge1xuICAgICAgICAgICAgdmFyIGlzT2JqZWN0ID0gcmVxdWlyZShcImlzLW9iamVjdFwiKTtcbiAgICAgICAgICAgIHZhciBpc0hvb2sgPSByZXF1aXJlKFwiLi4vdm5vZGUvaXMtdmhvb2suanNcIik7XG5cbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gYXBwbHlQcm9wZXJ0aWVzO1xuXG4gICAgICAgICAgICBmdW5jdGlvbiBhcHBseVByb3BlcnRpZXMobm9kZSwgcHJvcHMsIHByZXZpb3VzKSB7XG4gICAgICAgICAgICAgICAgZm9yICh2YXIgcHJvcE5hbWUgaW4gcHJvcHMpIHtcbiAgICAgICAgICAgICAgICAgICAgdmFyIHByb3BWYWx1ZSA9IHByb3BzW3Byb3BOYW1lXTtcblxuICAgICAgICAgICAgICAgICAgICBpZiAocHJvcFZhbHVlID09PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJlbW92ZVByb3BlcnR5KG5vZGUsIHByb3BOYW1lLCBwcm9wVmFsdWUsIHByZXZpb3VzKTtcbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIGlmIChpc0hvb2socHJvcFZhbHVlKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgcmVtb3ZlUHJvcGVydHkobm9kZSwgcHJvcE5hbWUsIHByb3BWYWx1ZSwgcHJldmlvdXMpO1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHByb3BWYWx1ZS5ob29rKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcHJvcFZhbHVlLmhvb2sobm9kZSwgcHJvcE5hbWUsIHByZXZpb3VzID8gcHJldmlvdXNbcHJvcE5hbWVdIDogdW5kZWZpbmVkKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChpc09iamVjdChwcm9wVmFsdWUpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcGF0Y2hPYmplY3Qobm9kZSwgcHJvcHMsIHByZXZpb3VzLCBwcm9wTmFtZSwgcHJvcFZhbHVlKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgbm9kZVtwcm9wTmFtZV0gPSBwcm9wVmFsdWU7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIHJlbW92ZVByb3BlcnR5KG5vZGUsIHByb3BOYW1lLCBwcm9wVmFsdWUsIHByZXZpb3VzKSB7XG4gICAgICAgICAgICAgICAgaWYgKHByZXZpb3VzKSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciBwcmV2aW91c1ZhbHVlID0gcHJldmlvdXNbcHJvcE5hbWVdO1xuXG4gICAgICAgICAgICAgICAgICAgIGlmICghaXNIb29rKHByZXZpb3VzVmFsdWUpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAocHJvcE5hbWUgPT09IFwiYXR0cmlidXRlc1wiKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgZm9yICh2YXIgYXR0ck5hbWUgaW4gcHJldmlvdXNWYWx1ZSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBub2RlLnJlbW92ZUF0dHJpYnV0ZShhdHRyTmFtZSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIGlmIChwcm9wTmFtZSA9PT0gXCJzdHlsZVwiKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgZm9yICh2YXIgaSBpbiBwcmV2aW91c1ZhbHVlKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG5vZGUuc3R5bGVbaV0gPSBcIlwiO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAodHlwZW9mIHByZXZpb3VzVmFsdWUgPT09IFwic3RyaW5nXCIpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBub2RlW3Byb3BOYW1lXSA9IFwiXCI7XG4gICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIG5vZGVbcHJvcE5hbWVdID0gbnVsbDtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIGlmIChwcmV2aW91c1ZhbHVlLnVuaG9vaykge1xuICAgICAgICAgICAgICAgICAgICAgICAgcHJldmlvdXNWYWx1ZS51bmhvb2sobm9kZSwgcHJvcE5hbWUsIHByb3BWYWx1ZSk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIHBhdGNoT2JqZWN0KG5vZGUsIHByb3BzLCBwcmV2aW91cywgcHJvcE5hbWUsIHByb3BWYWx1ZSkge1xuICAgICAgICAgICAgICAgIHZhciBwcmV2aW91c1ZhbHVlID0gcHJldmlvdXMgPyBwcmV2aW91c1twcm9wTmFtZV0gOiB1bmRlZmluZWQ7XG5cbiAgICAgICAgICAgICAgICAvLyBTZXQgYXR0cmlidXRlc1xuICAgICAgICAgICAgICAgIGlmIChwcm9wTmFtZSA9PT0gXCJhdHRyaWJ1dGVzXCIpIHtcbiAgICAgICAgICAgICAgICAgICAgZm9yICh2YXIgYXR0ck5hbWUgaW4gcHJvcFZhbHVlKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICB2YXIgYXR0clZhbHVlID0gcHJvcFZhbHVlW2F0dHJOYW1lXTtcblxuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGF0dHJWYWx1ZSA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgbm9kZS5yZW1vdmVBdHRyaWJ1dGUoYXR0ck5hbWUpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBub2RlLnNldEF0dHJpYnV0ZShhdHRyTmFtZSwgYXR0clZhbHVlKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICBpZiAocHJldmlvdXNWYWx1ZSAmJiBpc09iamVjdChwcmV2aW91c1ZhbHVlKSAmJiBnZXRQcm90b3R5cGUocHJldmlvdXNWYWx1ZSkgIT09IGdldFByb3RvdHlwZShwcm9wVmFsdWUpKSB7XG4gICAgICAgICAgICAgICAgICAgIG5vZGVbcHJvcE5hbWVdID0gcHJvcFZhbHVlO1xuICAgICAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgaWYgKCFpc09iamVjdChub2RlW3Byb3BOYW1lXSkpIHtcbiAgICAgICAgICAgICAgICAgICAgbm9kZVtwcm9wTmFtZV0gPSB7fTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICB2YXIgcmVwbGFjZXIgPSBwcm9wTmFtZSA9PT0gXCJzdHlsZVwiID8gXCJcIiA6IHVuZGVmaW5lZDtcblxuICAgICAgICAgICAgICAgIGZvciAodmFyIGsgaW4gcHJvcFZhbHVlKSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciB2YWx1ZSA9IHByb3BWYWx1ZVtrXTtcbiAgICAgICAgICAgICAgICAgICAgbm9kZVtwcm9wTmFtZV1ba10gPSB2YWx1ZSA9PT0gdW5kZWZpbmVkID8gcmVwbGFjZXIgOiB2YWx1ZTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIGdldFByb3RvdHlwZSh2YWx1ZSkge1xuICAgICAgICAgICAgICAgIGlmIChPYmplY3QuZ2V0UHJvdG90eXBlT2YpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIE9iamVjdC5nZXRQcm90b3R5cGVPZih2YWx1ZSk7XG4gICAgICAgICAgICAgICAgfSBlbHNlIGlmICh2YWx1ZS5fX3Byb3RvX18pIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHZhbHVlLl9fcHJvdG9fXztcbiAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKHZhbHVlLmNvbnN0cnVjdG9yKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiB2YWx1ZS5jb25zdHJ1Y3Rvci5wcm90b3R5cGU7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9LCB7IFwiLi4vdm5vZGUvaXMtdmhvb2suanNcIjogMjYsIFwiaXMtb2JqZWN0XCI6IDExIH1dLCAxNTogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHtcbiAgICAgICAgICAgIHZhciBkb2N1bWVudCA9IHJlcXVpcmUoXCJnbG9iYWwvZG9jdW1lbnRcIik7XG5cbiAgICAgICAgICAgIHZhciBhcHBseVByb3BlcnRpZXMgPSByZXF1aXJlKFwiLi9hcHBseS1wcm9wZXJ0aWVzXCIpO1xuXG4gICAgICAgICAgICB2YXIgaXNWTm9kZSA9IHJlcXVpcmUoXCIuLi92bm9kZS9pcy12bm9kZS5qc1wiKTtcbiAgICAgICAgICAgIHZhciBpc1ZUZXh0ID0gcmVxdWlyZShcIi4uL3Zub2RlL2lzLXZ0ZXh0LmpzXCIpO1xuICAgICAgICAgICAgdmFyIGlzV2lkZ2V0ID0gcmVxdWlyZShcIi4uL3Zub2RlL2lzLXdpZGdldC5qc1wiKTtcbiAgICAgICAgICAgIHZhciBoYW5kbGVUaHVuayA9IHJlcXVpcmUoXCIuLi92bm9kZS9oYW5kbGUtdGh1bmsuanNcIik7XG5cbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gY3JlYXRlRWxlbWVudDtcblxuICAgICAgICAgICAgZnVuY3Rpb24gY3JlYXRlRWxlbWVudCh2bm9kZSwgb3B0cykge1xuICAgICAgICAgICAgICAgIHZhciBkb2MgPSBvcHRzID8gb3B0cy5kb2N1bWVudCB8fCBkb2N1bWVudCA6IGRvY3VtZW50O1xuICAgICAgICAgICAgICAgIHZhciB3YXJuID0gb3B0cyA/IG9wdHMud2FybiA6IG51bGw7XG5cbiAgICAgICAgICAgICAgICB2bm9kZSA9IGhhbmRsZVRodW5rKHZub2RlKS5hO1xuXG4gICAgICAgICAgICAgICAgaWYgKGlzV2lkZ2V0KHZub2RlKSkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gdm5vZGUuaW5pdCgpO1xuICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoaXNWVGV4dCh2bm9kZSkpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGRvYy5jcmVhdGVUZXh0Tm9kZSh2bm9kZS50ZXh0KTtcbiAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKCFpc1ZOb2RlKHZub2RlKSkge1xuICAgICAgICAgICAgICAgICAgICBpZiAod2Fybikge1xuICAgICAgICAgICAgICAgICAgICAgICAgd2FybihcIkl0ZW0gaXMgbm90IGEgdmFsaWQgdmlydHVhbCBkb20gbm9kZVwiLCB2bm9kZSk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIG51bGw7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgdmFyIG5vZGUgPSB2bm9kZS5uYW1lc3BhY2UgPT09IG51bGwgPyBkb2MuY3JlYXRlRWxlbWVudCh2bm9kZS50YWdOYW1lKSA6IGRvYy5jcmVhdGVFbGVtZW50TlModm5vZGUubmFtZXNwYWNlLCB2bm9kZS50YWdOYW1lKTtcblxuICAgICAgICAgICAgICAgIHZhciBwcm9wcyA9IHZub2RlLnByb3BlcnRpZXM7XG4gICAgICAgICAgICAgICAgYXBwbHlQcm9wZXJ0aWVzKG5vZGUsIHByb3BzKTtcblxuICAgICAgICAgICAgICAgIHZhciBjaGlsZHJlbiA9IHZub2RlLmNoaWxkcmVuO1xuXG4gICAgICAgICAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCBjaGlsZHJlbi5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgICAgICAgICB2YXIgY2hpbGROb2RlID0gY3JlYXRlRWxlbWVudChjaGlsZHJlbltpXSwgb3B0cyk7XG4gICAgICAgICAgICAgICAgICAgIGlmIChjaGlsZE5vZGUpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIG5vZGUuYXBwZW5kQ2hpbGQoY2hpbGROb2RlKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHJldHVybiBub2RlO1xuICAgICAgICAgICAgfVxuICAgICAgICB9LCB7IFwiLi4vdm5vZGUvaGFuZGxlLXRodW5rLmpzXCI6IDI0LCBcIi4uL3Zub2RlL2lzLXZub2RlLmpzXCI6IDI3LCBcIi4uL3Zub2RlL2lzLXZ0ZXh0LmpzXCI6IDI4LCBcIi4uL3Zub2RlL2lzLXdpZGdldC5qc1wiOiAyOSwgXCIuL2FwcGx5LXByb3BlcnRpZXNcIjogMTQsIFwiZ2xvYmFsL2RvY3VtZW50XCI6IDEwIH1dLCAxNjogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHtcbiAgICAgICAgICAgIC8vIE1hcHMgYSB2aXJ0dWFsIERPTSB0cmVlIG9udG8gYSByZWFsIERPTSB0cmVlIGluIGFuIGVmZmljaWVudCBtYW5uZXIuXG4gICAgICAgICAgICAvLyBXZSBkb24ndCB3YW50IHRvIHJlYWQgYWxsIG9mIHRoZSBET00gbm9kZXMgaW4gdGhlIHRyZWUgc28gd2UgdXNlXG4gICAgICAgICAgICAvLyB0aGUgaW4tb3JkZXIgdHJlZSBpbmRleGluZyB0byBlbGltaW5hdGUgcmVjdXJzaW9uIGRvd24gY2VydGFpbiBicmFuY2hlcy5cbiAgICAgICAgICAgIC8vIFdlIG9ubHkgcmVjdXJzZSBpbnRvIGEgRE9NIG5vZGUgaWYgd2Uga25vdyB0aGF0IGl0IGNvbnRhaW5zIGEgY2hpbGQgb2ZcbiAgICAgICAgICAgIC8vIGludGVyZXN0LlxuXG4gICAgICAgICAgICB2YXIgbm9DaGlsZCA9IHt9O1xuXG4gICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IGRvbUluZGV4O1xuXG4gICAgICAgICAgICBmdW5jdGlvbiBkb21JbmRleChyb290Tm9kZSwgdHJlZSwgaW5kaWNlcywgbm9kZXMpIHtcbiAgICAgICAgICAgICAgICBpZiAoIWluZGljZXMgfHwgaW5kaWNlcy5sZW5ndGggPT09IDApIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHt9O1xuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIGluZGljZXMuc29ydChhc2NlbmRpbmcpO1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gcmVjdXJzZShyb290Tm9kZSwgdHJlZSwgaW5kaWNlcywgbm9kZXMsIDApO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZnVuY3Rpb24gcmVjdXJzZShyb290Tm9kZSwgdHJlZSwgaW5kaWNlcywgbm9kZXMsIHJvb3RJbmRleCkge1xuICAgICAgICAgICAgICAgIG5vZGVzID0gbm9kZXMgfHwge307XG5cbiAgICAgICAgICAgICAgICBpZiAocm9vdE5vZGUpIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKGluZGV4SW5SYW5nZShpbmRpY2VzLCByb290SW5kZXgsIHJvb3RJbmRleCkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIG5vZGVzW3Jvb3RJbmRleF0gPSByb290Tm9kZTtcbiAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgIHZhciB2Q2hpbGRyZW4gPSB0cmVlLmNoaWxkcmVuO1xuXG4gICAgICAgICAgICAgICAgICAgIGlmICh2Q2hpbGRyZW4pIHtcblxuICAgICAgICAgICAgICAgICAgICAgICAgdmFyIGNoaWxkTm9kZXMgPSByb290Tm9kZS5jaGlsZE5vZGVzO1xuXG4gICAgICAgICAgICAgICAgICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IHRyZWUuY2hpbGRyZW4ubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICByb290SW5kZXggKz0gMTtcblxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZhciB2Q2hpbGQgPSB2Q2hpbGRyZW5baV0gfHwgbm9DaGlsZDtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB2YXIgbmV4dEluZGV4ID0gcm9vdEluZGV4ICsgKHZDaGlsZC5jb3VudCB8fCAwKTtcblxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIHNraXAgcmVjdXJzaW9uIGRvd24gdGhlIHRyZWUgaWYgdGhlcmUgYXJlIG5vIG5vZGVzIGRvd24gaGVyZVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChpbmRleEluUmFuZ2UoaW5kaWNlcywgcm9vdEluZGV4LCBuZXh0SW5kZXgpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlY3Vyc2UoY2hpbGROb2Rlc1tpXSwgdkNoaWxkLCBpbmRpY2VzLCBub2Rlcywgcm9vdEluZGV4KTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICByb290SW5kZXggPSBuZXh0SW5kZXg7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICByZXR1cm4gbm9kZXM7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIC8vIEJpbmFyeSBzZWFyY2ggZm9yIGFuIGluZGV4IGluIHRoZSBpbnRlcnZhbCBbbGVmdCwgcmlnaHRdXG4gICAgICAgICAgICBmdW5jdGlvbiBpbmRleEluUmFuZ2UoaW5kaWNlcywgbGVmdCwgcmlnaHQpIHtcbiAgICAgICAgICAgICAgICBpZiAoaW5kaWNlcy5sZW5ndGggPT09IDApIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHZhciBtaW5JbmRleCA9IDA7XG4gICAgICAgICAgICAgICAgdmFyIG1heEluZGV4ID0gaW5kaWNlcy5sZW5ndGggLSAxO1xuICAgICAgICAgICAgICAgIHZhciBjdXJyZW50SW5kZXg7XG4gICAgICAgICAgICAgICAgdmFyIGN1cnJlbnRJdGVtO1xuXG4gICAgICAgICAgICAgICAgd2hpbGUgKG1pbkluZGV4IDw9IG1heEluZGV4KSB7XG4gICAgICAgICAgICAgICAgICAgIGN1cnJlbnRJbmRleCA9IChtYXhJbmRleCArIG1pbkluZGV4KSAvIDIgPj4gMDtcbiAgICAgICAgICAgICAgICAgICAgY3VycmVudEl0ZW0gPSBpbmRpY2VzW2N1cnJlbnRJbmRleF07XG5cbiAgICAgICAgICAgICAgICAgICAgaWYgKG1pbkluZGV4ID09PSBtYXhJbmRleCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGN1cnJlbnRJdGVtID49IGxlZnQgJiYgY3VycmVudEl0ZW0gPD0gcmlnaHQ7XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoY3VycmVudEl0ZW0gPCBsZWZ0KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBtaW5JbmRleCA9IGN1cnJlbnRJbmRleCArIDE7XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoY3VycmVudEl0ZW0gPiByaWdodCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgbWF4SW5kZXggPSBjdXJyZW50SW5kZXggLSAxO1xuICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIGFzY2VuZGluZyhhLCBiKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGEgPiBiID8gMSA6IC0xO1xuICAgICAgICAgICAgfVxuICAgICAgICB9LCB7fV0sIDE3OiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge1xuICAgICAgICAgICAgdmFyIGFwcGx5UHJvcGVydGllcyA9IHJlcXVpcmUoXCIuL2FwcGx5LXByb3BlcnRpZXNcIik7XG5cbiAgICAgICAgICAgIHZhciBpc1dpZGdldCA9IHJlcXVpcmUoXCIuLi92bm9kZS9pcy13aWRnZXQuanNcIik7XG4gICAgICAgICAgICB2YXIgVlBhdGNoID0gcmVxdWlyZShcIi4uL3Zub2RlL3ZwYXRjaC5qc1wiKTtcblxuICAgICAgICAgICAgdmFyIHVwZGF0ZVdpZGdldCA9IHJlcXVpcmUoXCIuL3VwZGF0ZS13aWRnZXRcIik7XG5cbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gYXBwbHlQYXRjaDtcblxuICAgICAgICAgICAgZnVuY3Rpb24gYXBwbHlQYXRjaCh2cGF0Y2gsIGRvbU5vZGUsIHJlbmRlck9wdGlvbnMpIHtcbiAgICAgICAgICAgICAgICB2YXIgdHlwZSA9IHZwYXRjaC50eXBlO1xuICAgICAgICAgICAgICAgIHZhciB2Tm9kZSA9IHZwYXRjaC52Tm9kZTtcbiAgICAgICAgICAgICAgICB2YXIgcGF0Y2ggPSB2cGF0Y2gucGF0Y2g7XG5cbiAgICAgICAgICAgICAgICBzd2l0Y2ggKHR5cGUpIHtcbiAgICAgICAgICAgICAgICAgICAgY2FzZSBWUGF0Y2guUkVNT1ZFOlxuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHJlbW92ZU5vZGUoZG9tTm9kZSwgdk5vZGUpO1xuICAgICAgICAgICAgICAgICAgICBjYXNlIFZQYXRjaC5JTlNFUlQ6XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gaW5zZXJ0Tm9kZShkb21Ob2RlLCBwYXRjaCwgcmVuZGVyT3B0aW9ucyk7XG4gICAgICAgICAgICAgICAgICAgIGNhc2UgVlBhdGNoLlZURVhUOlxuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHN0cmluZ1BhdGNoKGRvbU5vZGUsIHZOb2RlLCBwYXRjaCwgcmVuZGVyT3B0aW9ucyk7XG4gICAgICAgICAgICAgICAgICAgIGNhc2UgVlBhdGNoLldJREdFVDpcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiB3aWRnZXRQYXRjaChkb21Ob2RlLCB2Tm9kZSwgcGF0Y2gsIHJlbmRlck9wdGlvbnMpO1xuICAgICAgICAgICAgICAgICAgICBjYXNlIFZQYXRjaC5WTk9ERTpcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiB2Tm9kZVBhdGNoKGRvbU5vZGUsIHZOb2RlLCBwYXRjaCwgcmVuZGVyT3B0aW9ucyk7XG4gICAgICAgICAgICAgICAgICAgIGNhc2UgVlBhdGNoLk9SREVSOlxuICAgICAgICAgICAgICAgICAgICAgICAgcmVvcmRlckNoaWxkcmVuKGRvbU5vZGUsIHBhdGNoKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBkb21Ob2RlO1xuICAgICAgICAgICAgICAgICAgICBjYXNlIFZQYXRjaC5QUk9QUzpcbiAgICAgICAgICAgICAgICAgICAgICAgIGFwcGx5UHJvcGVydGllcyhkb21Ob2RlLCBwYXRjaCwgdk5vZGUucHJvcGVydGllcyk7XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gZG9tTm9kZTtcbiAgICAgICAgICAgICAgICAgICAgY2FzZSBWUGF0Y2guVEhVTks6XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gcmVwbGFjZVJvb3QoZG9tTm9kZSwgcmVuZGVyT3B0aW9ucy5wYXRjaChkb21Ob2RlLCBwYXRjaCwgcmVuZGVyT3B0aW9ucykpO1xuICAgICAgICAgICAgICAgICAgICBkZWZhdWx0OlxuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGRvbU5vZGU7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBmdW5jdGlvbiByZW1vdmVOb2RlKGRvbU5vZGUsIHZOb2RlKSB7XG4gICAgICAgICAgICAgICAgdmFyIHBhcmVudE5vZGUgPSBkb21Ob2RlLnBhcmVudE5vZGU7XG5cbiAgICAgICAgICAgICAgICBpZiAocGFyZW50Tm9kZSkge1xuICAgICAgICAgICAgICAgICAgICBwYXJlbnROb2RlLnJlbW92ZUNoaWxkKGRvbU5vZGUpO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIGRlc3Ryb3lXaWRnZXQoZG9tTm9kZSwgdk5vZGUpO1xuXG4gICAgICAgICAgICAgICAgcmV0dXJuIG51bGw7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIGluc2VydE5vZGUocGFyZW50Tm9kZSwgdk5vZGUsIHJlbmRlck9wdGlvbnMpIHtcbiAgICAgICAgICAgICAgICB2YXIgbmV3Tm9kZSA9IHJlbmRlck9wdGlvbnMucmVuZGVyKHZOb2RlLCByZW5kZXJPcHRpb25zKTtcblxuICAgICAgICAgICAgICAgIGlmIChwYXJlbnROb2RlKSB7XG4gICAgICAgICAgICAgICAgICAgIHBhcmVudE5vZGUuYXBwZW5kQ2hpbGQobmV3Tm9kZSk7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgcmV0dXJuIHBhcmVudE5vZGU7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIHN0cmluZ1BhdGNoKGRvbU5vZGUsIGxlZnRWTm9kZSwgdlRleHQsIHJlbmRlck9wdGlvbnMpIHtcbiAgICAgICAgICAgICAgICB2YXIgbmV3Tm9kZTtcblxuICAgICAgICAgICAgICAgIGlmIChkb21Ob2RlLm5vZGVUeXBlID09PSAzKSB7XG4gICAgICAgICAgICAgICAgICAgIGRvbU5vZGUucmVwbGFjZURhdGEoMCwgZG9tTm9kZS5sZW5ndGgsIHZUZXh0LnRleHQpO1xuICAgICAgICAgICAgICAgICAgICBuZXdOb2RlID0gZG9tTm9kZTtcbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICB2YXIgcGFyZW50Tm9kZSA9IGRvbU5vZGUucGFyZW50Tm9kZTtcbiAgICAgICAgICAgICAgICAgICAgbmV3Tm9kZSA9IHJlbmRlck9wdGlvbnMucmVuZGVyKHZUZXh0LCByZW5kZXJPcHRpb25zKTtcblxuICAgICAgICAgICAgICAgICAgICBpZiAocGFyZW50Tm9kZSAmJiBuZXdOb2RlICE9PSBkb21Ob2RlKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBwYXJlbnROb2RlLnJlcGxhY2VDaGlsZChuZXdOb2RlLCBkb21Ob2RlKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHJldHVybiBuZXdOb2RlO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBmdW5jdGlvbiB3aWRnZXRQYXRjaChkb21Ob2RlLCBsZWZ0Vk5vZGUsIHdpZGdldCwgcmVuZGVyT3B0aW9ucykge1xuICAgICAgICAgICAgICAgIHZhciB1cGRhdGluZyA9IHVwZGF0ZVdpZGdldChsZWZ0Vk5vZGUsIHdpZGdldCk7XG4gICAgICAgICAgICAgICAgdmFyIG5ld05vZGU7XG5cbiAgICAgICAgICAgICAgICBpZiAodXBkYXRpbmcpIHtcbiAgICAgICAgICAgICAgICAgICAgbmV3Tm9kZSA9IHdpZGdldC51cGRhdGUobGVmdFZOb2RlLCBkb21Ob2RlKSB8fCBkb21Ob2RlO1xuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIG5ld05vZGUgPSByZW5kZXJPcHRpb25zLnJlbmRlcih3aWRnZXQsIHJlbmRlck9wdGlvbnMpO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHZhciBwYXJlbnROb2RlID0gZG9tTm9kZS5wYXJlbnROb2RlO1xuXG4gICAgICAgICAgICAgICAgaWYgKHBhcmVudE5vZGUgJiYgbmV3Tm9kZSAhPT0gZG9tTm9kZSkge1xuICAgICAgICAgICAgICAgICAgICBwYXJlbnROb2RlLnJlcGxhY2VDaGlsZChuZXdOb2RlLCBkb21Ob2RlKTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICBpZiAoIXVwZGF0aW5nKSB7XG4gICAgICAgICAgICAgICAgICAgIGRlc3Ryb3lXaWRnZXQoZG9tTm9kZSwgbGVmdFZOb2RlKTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICByZXR1cm4gbmV3Tm9kZTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZnVuY3Rpb24gdk5vZGVQYXRjaChkb21Ob2RlLCBsZWZ0Vk5vZGUsIHZOb2RlLCByZW5kZXJPcHRpb25zKSB7XG4gICAgICAgICAgICAgICAgdmFyIHBhcmVudE5vZGUgPSBkb21Ob2RlLnBhcmVudE5vZGU7XG4gICAgICAgICAgICAgICAgdmFyIG5ld05vZGUgPSByZW5kZXJPcHRpb25zLnJlbmRlcih2Tm9kZSwgcmVuZGVyT3B0aW9ucyk7XG5cbiAgICAgICAgICAgICAgICBpZiAocGFyZW50Tm9kZSAmJiBuZXdOb2RlICE9PSBkb21Ob2RlKSB7XG4gICAgICAgICAgICAgICAgICAgIHBhcmVudE5vZGUucmVwbGFjZUNoaWxkKG5ld05vZGUsIGRvbU5vZGUpO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHJldHVybiBuZXdOb2RlO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBmdW5jdGlvbiBkZXN0cm95V2lkZ2V0KGRvbU5vZGUsIHcpIHtcbiAgICAgICAgICAgICAgICBpZiAodHlwZW9mIHcuZGVzdHJveSA9PT0gXCJmdW5jdGlvblwiICYmIGlzV2lkZ2V0KHcpKSB7XG4gICAgICAgICAgICAgICAgICAgIHcuZGVzdHJveShkb21Ob2RlKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIHJlb3JkZXJDaGlsZHJlbihkb21Ob2RlLCBtb3Zlcykge1xuICAgICAgICAgICAgICAgIHZhciBjaGlsZE5vZGVzID0gZG9tTm9kZS5jaGlsZE5vZGVzO1xuICAgICAgICAgICAgICAgIHZhciBrZXlNYXAgPSB7fTtcbiAgICAgICAgICAgICAgICB2YXIgbm9kZTtcbiAgICAgICAgICAgICAgICB2YXIgcmVtb3ZlO1xuICAgICAgICAgICAgICAgIHZhciBpbnNlcnQ7XG5cbiAgICAgICAgICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IG1vdmVzLnJlbW92ZXMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgICAgICAgICAgcmVtb3ZlID0gbW92ZXMucmVtb3Zlc1tpXTtcbiAgICAgICAgICAgICAgICAgICAgbm9kZSA9IGNoaWxkTm9kZXNbcmVtb3ZlLmZyb21dO1xuICAgICAgICAgICAgICAgICAgICBpZiAocmVtb3ZlLmtleSkge1xuICAgICAgICAgICAgICAgICAgICAgICAga2V5TWFwW3JlbW92ZS5rZXldID0gbm9kZTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICBkb21Ob2RlLnJlbW92ZUNoaWxkKG5vZGUpO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHZhciBsZW5ndGggPSBjaGlsZE5vZGVzLmxlbmd0aDtcbiAgICAgICAgICAgICAgICBmb3IgKHZhciBqID0gMDsgaiA8IG1vdmVzLmluc2VydHMubGVuZ3RoOyBqKyspIHtcbiAgICAgICAgICAgICAgICAgICAgaW5zZXJ0ID0gbW92ZXMuaW5zZXJ0c1tqXTtcbiAgICAgICAgICAgICAgICAgICAgbm9kZSA9IGtleU1hcFtpbnNlcnQua2V5XTtcbiAgICAgICAgICAgICAgICAgICAgLy8gdGhpcyBpcyB0aGUgd2VpcmRlc3QgYnVnIGkndmUgZXZlciBzZWVuIGluIHdlYmtpdFxuICAgICAgICAgICAgICAgICAgICBkb21Ob2RlLmluc2VydEJlZm9yZShub2RlLCBpbnNlcnQudG8gPj0gbGVuZ3RoKysgPyBudWxsIDogY2hpbGROb2Rlc1tpbnNlcnQudG9dKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIHJlcGxhY2VSb290KG9sZFJvb3QsIG5ld1Jvb3QpIHtcbiAgICAgICAgICAgICAgICBpZiAob2xkUm9vdCAmJiBuZXdSb290ICYmIG9sZFJvb3QgIT09IG5ld1Jvb3QgJiYgb2xkUm9vdC5wYXJlbnROb2RlKSB7XG4gICAgICAgICAgICAgICAgICAgIG9sZFJvb3QucGFyZW50Tm9kZS5yZXBsYWNlQ2hpbGQobmV3Um9vdCwgb2xkUm9vdCk7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgcmV0dXJuIG5ld1Jvb3Q7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0sIHsgXCIuLi92bm9kZS9pcy13aWRnZXQuanNcIjogMjksIFwiLi4vdm5vZGUvdnBhdGNoLmpzXCI6IDMyLCBcIi4vYXBwbHktcHJvcGVydGllc1wiOiAxNCwgXCIuL3VwZGF0ZS13aWRnZXRcIjogMTkgfV0sIDE4OiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge1xuICAgICAgICAgICAgdmFyIGRvY3VtZW50ID0gcmVxdWlyZShcImdsb2JhbC9kb2N1bWVudFwiKTtcbiAgICAgICAgICAgIHZhciBpc0FycmF5ID0gcmVxdWlyZShcIngtaXMtYXJyYXlcIik7XG5cbiAgICAgICAgICAgIHZhciByZW5kZXIgPSByZXF1aXJlKFwiLi9jcmVhdGUtZWxlbWVudFwiKTtcbiAgICAgICAgICAgIHZhciBkb21JbmRleCA9IHJlcXVpcmUoXCIuL2RvbS1pbmRleFwiKTtcbiAgICAgICAgICAgIHZhciBwYXRjaE9wID0gcmVxdWlyZShcIi4vcGF0Y2gtb3BcIik7XG4gICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IHBhdGNoO1xuXG4gICAgICAgICAgICBmdW5jdGlvbiBwYXRjaChyb290Tm9kZSwgcGF0Y2hlcywgcmVuZGVyT3B0aW9ucykge1xuICAgICAgICAgICAgICAgIHJlbmRlck9wdGlvbnMgPSByZW5kZXJPcHRpb25zIHx8IHt9O1xuICAgICAgICAgICAgICAgIHJlbmRlck9wdGlvbnMucGF0Y2ggPSByZW5kZXJPcHRpb25zLnBhdGNoICYmIHJlbmRlck9wdGlvbnMucGF0Y2ggIT09IHBhdGNoID8gcmVuZGVyT3B0aW9ucy5wYXRjaCA6IHBhdGNoUmVjdXJzaXZlO1xuICAgICAgICAgICAgICAgIHJlbmRlck9wdGlvbnMucmVuZGVyID0gcmVuZGVyT3B0aW9ucy5yZW5kZXIgfHwgcmVuZGVyO1xuXG4gICAgICAgICAgICAgICAgcmV0dXJuIHJlbmRlck9wdGlvbnMucGF0Y2gocm9vdE5vZGUsIHBhdGNoZXMsIHJlbmRlck9wdGlvbnMpO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBmdW5jdGlvbiBwYXRjaFJlY3Vyc2l2ZShyb290Tm9kZSwgcGF0Y2hlcywgcmVuZGVyT3B0aW9ucykge1xuICAgICAgICAgICAgICAgIHZhciBpbmRpY2VzID0gcGF0Y2hJbmRpY2VzKHBhdGNoZXMpO1xuXG4gICAgICAgICAgICAgICAgaWYgKGluZGljZXMubGVuZ3RoID09PSAwKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiByb290Tm9kZTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICB2YXIgaW5kZXggPSBkb21JbmRleChyb290Tm9kZSwgcGF0Y2hlcy5hLCBpbmRpY2VzKTtcbiAgICAgICAgICAgICAgICB2YXIgb3duZXJEb2N1bWVudCA9IHJvb3ROb2RlLm93bmVyRG9jdW1lbnQ7XG5cbiAgICAgICAgICAgICAgICBpZiAoIXJlbmRlck9wdGlvbnMuZG9jdW1lbnQgJiYgb3duZXJEb2N1bWVudCAhPT0gZG9jdW1lbnQpIHtcbiAgICAgICAgICAgICAgICAgICAgcmVuZGVyT3B0aW9ucy5kb2N1bWVudCA9IG93bmVyRG9jdW1lbnQ7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCBpbmRpY2VzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciBub2RlSW5kZXggPSBpbmRpY2VzW2ldO1xuICAgICAgICAgICAgICAgICAgICByb290Tm9kZSA9IGFwcGx5UGF0Y2gocm9vdE5vZGUsIGluZGV4W25vZGVJbmRleF0sIHBhdGNoZXNbbm9kZUluZGV4XSwgcmVuZGVyT3B0aW9ucyk7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgcmV0dXJuIHJvb3ROb2RlO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBmdW5jdGlvbiBhcHBseVBhdGNoKHJvb3ROb2RlLCBkb21Ob2RlLCBwYXRjaExpc3QsIHJlbmRlck9wdGlvbnMpIHtcbiAgICAgICAgICAgICAgICBpZiAoIWRvbU5vZGUpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHJvb3ROb2RlO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHZhciBuZXdOb2RlO1xuXG4gICAgICAgICAgICAgICAgaWYgKGlzQXJyYXkocGF0Y2hMaXN0KSkge1xuICAgICAgICAgICAgICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IHBhdGNoTGlzdC5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgICAgICAgICAgICAgbmV3Tm9kZSA9IHBhdGNoT3AocGF0Y2hMaXN0W2ldLCBkb21Ob2RlLCByZW5kZXJPcHRpb25zKTtcblxuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGRvbU5vZGUgPT09IHJvb3ROb2RlKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcm9vdE5vZGUgPSBuZXdOb2RlO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgbmV3Tm9kZSA9IHBhdGNoT3AocGF0Y2hMaXN0LCBkb21Ob2RlLCByZW5kZXJPcHRpb25zKTtcblxuICAgICAgICAgICAgICAgICAgICBpZiAoZG9tTm9kZSA9PT0gcm9vdE5vZGUpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJvb3ROb2RlID0gbmV3Tm9kZTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHJldHVybiByb290Tm9kZTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZnVuY3Rpb24gcGF0Y2hJbmRpY2VzKHBhdGNoZXMpIHtcbiAgICAgICAgICAgICAgICB2YXIgaW5kaWNlcyA9IFtdO1xuXG4gICAgICAgICAgICAgICAgZm9yICh2YXIga2V5IGluIHBhdGNoZXMpIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKGtleSAhPT0gXCJhXCIpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGluZGljZXMucHVzaChOdW1iZXIoa2V5KSk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICByZXR1cm4gaW5kaWNlcztcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSwgeyBcIi4vY3JlYXRlLWVsZW1lbnRcIjogMTUsIFwiLi9kb20taW5kZXhcIjogMTYsIFwiLi9wYXRjaC1vcFwiOiAxNywgXCJnbG9iYWwvZG9jdW1lbnRcIjogMTAsIFwieC1pcy1hcnJheVwiOiAxMiB9XSwgMTk6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICB2YXIgaXNXaWRnZXQgPSByZXF1aXJlKFwiLi4vdm5vZGUvaXMtd2lkZ2V0LmpzXCIpO1xuXG4gICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IHVwZGF0ZVdpZGdldDtcblxuICAgICAgICAgICAgZnVuY3Rpb24gdXBkYXRlV2lkZ2V0KGEsIGIpIHtcbiAgICAgICAgICAgICAgICBpZiAoaXNXaWRnZXQoYSkgJiYgaXNXaWRnZXQoYikpIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKFwibmFtZVwiIGluIGEgJiYgXCJuYW1lXCIgaW4gYikge1xuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGEuaWQgPT09IGIuaWQ7XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gYS5pbml0ID09PSBiLmluaXQ7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0sIHsgXCIuLi92bm9kZS9pcy13aWRnZXQuanNcIjogMjkgfV0sIDIwOiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge1xuICAgICAgICAgICAgXCJ1c2Ugc3RyaWN0XCI7XG5cbiAgICAgICAgICAgIHZhciBFdlN0b3JlID0gcmVxdWlyZShcImV2LXN0b3JlXCIpO1xuXG4gICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IEV2SG9vaztcblxuICAgICAgICAgICAgZnVuY3Rpb24gRXZIb29rKHZhbHVlKSB7XG4gICAgICAgICAgICAgICAgaWYgKCEodGhpcyBpbnN0YW5jZW9mIEV2SG9vaykpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIG5ldyBFdkhvb2sodmFsdWUpO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHRoaXMudmFsdWUgPSB2YWx1ZTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgRXZIb29rLnByb3RvdHlwZS5ob29rID0gZnVuY3Rpb24gKG5vZGUsIHByb3BlcnR5TmFtZSkge1xuICAgICAgICAgICAgICAgIHZhciBlcyA9IEV2U3RvcmUobm9kZSk7XG4gICAgICAgICAgICAgICAgdmFyIHByb3BOYW1lID0gcHJvcGVydHlOYW1lLnN1YnN0cigzKTtcblxuICAgICAgICAgICAgICAgIGVzW3Byb3BOYW1lXSA9IHRoaXMudmFsdWU7XG4gICAgICAgICAgICB9O1xuXG4gICAgICAgICAgICBFdkhvb2sucHJvdG90eXBlLnVuaG9vayA9IGZ1bmN0aW9uIChub2RlLCBwcm9wZXJ0eU5hbWUpIHtcbiAgICAgICAgICAgICAgICB2YXIgZXMgPSBFdlN0b3JlKG5vZGUpO1xuICAgICAgICAgICAgICAgIHZhciBwcm9wTmFtZSA9IHByb3BlcnR5TmFtZS5zdWJzdHIoMyk7XG5cbiAgICAgICAgICAgICAgICBlc1twcm9wTmFtZV0gPSB1bmRlZmluZWQ7XG4gICAgICAgICAgICB9O1xuICAgICAgICB9LCB7IFwiZXYtc3RvcmVcIjogNyB9XSwgMjE6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICBcInVzZSBzdHJpY3RcIjtcblxuICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBTb2Z0U2V0SG9vaztcblxuICAgICAgICAgICAgZnVuY3Rpb24gU29mdFNldEhvb2sodmFsdWUpIHtcbiAgICAgICAgICAgICAgICBpZiAoISh0aGlzIGluc3RhbmNlb2YgU29mdFNldEhvb2spKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBuZXcgU29mdFNldEhvb2sodmFsdWUpO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHRoaXMudmFsdWUgPSB2YWx1ZTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgU29mdFNldEhvb2sucHJvdG90eXBlLmhvb2sgPSBmdW5jdGlvbiAobm9kZSwgcHJvcGVydHlOYW1lKSB7XG4gICAgICAgICAgICAgICAgaWYgKG5vZGVbcHJvcGVydHlOYW1lXSAhPT0gdGhpcy52YWx1ZSkge1xuICAgICAgICAgICAgICAgICAgICBub2RlW3Byb3BlcnR5TmFtZV0gPSB0aGlzLnZhbHVlO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH07XG4gICAgICAgIH0sIHt9XSwgMjI6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICBcInVzZSBzdHJpY3RcIjtcblxuICAgICAgICAgICAgdmFyIGlzQXJyYXkgPSByZXF1aXJlKFwieC1pcy1hcnJheVwiKTtcblxuICAgICAgICAgICAgdmFyIFZOb2RlID0gcmVxdWlyZShcIi4uL3Zub2RlL3Zub2RlLmpzXCIpO1xuICAgICAgICAgICAgdmFyIFZUZXh0ID0gcmVxdWlyZShcIi4uL3Zub2RlL3Z0ZXh0LmpzXCIpO1xuICAgICAgICAgICAgdmFyIGlzVk5vZGUgPSByZXF1aXJlKFwiLi4vdm5vZGUvaXMtdm5vZGVcIik7XG4gICAgICAgICAgICB2YXIgaXNWVGV4dCA9IHJlcXVpcmUoXCIuLi92bm9kZS9pcy12dGV4dFwiKTtcbiAgICAgICAgICAgIHZhciBpc1dpZGdldCA9IHJlcXVpcmUoXCIuLi92bm9kZS9pcy13aWRnZXRcIik7XG4gICAgICAgICAgICB2YXIgaXNIb29rID0gcmVxdWlyZShcIi4uL3Zub2RlL2lzLXZob29rXCIpO1xuICAgICAgICAgICAgdmFyIGlzVlRodW5rID0gcmVxdWlyZShcIi4uL3Zub2RlL2lzLXRodW5rXCIpO1xuXG4gICAgICAgICAgICB2YXIgcGFyc2VUYWcgPSByZXF1aXJlKFwiLi9wYXJzZS10YWcuanNcIik7XG4gICAgICAgICAgICB2YXIgc29mdFNldEhvb2sgPSByZXF1aXJlKFwiLi9ob29rcy9zb2Z0LXNldC1ob29rLmpzXCIpO1xuICAgICAgICAgICAgdmFyIGV2SG9vayA9IHJlcXVpcmUoXCIuL2hvb2tzL2V2LWhvb2suanNcIik7XG5cbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gaDtcblxuICAgICAgICAgICAgZnVuY3Rpb24gaCh0YWdOYW1lLCBwcm9wZXJ0aWVzLCBjaGlsZHJlbikge1xuICAgICAgICAgICAgICAgIHZhciBjaGlsZE5vZGVzID0gW107XG4gICAgICAgICAgICAgICAgdmFyIHRhZywgcHJvcHMsIGtleSwgbmFtZXNwYWNlO1xuXG4gICAgICAgICAgICAgICAgaWYgKCFjaGlsZHJlbiAmJiBpc0NoaWxkcmVuKHByb3BlcnRpZXMpKSB7XG4gICAgICAgICAgICAgICAgICAgIGNoaWxkcmVuID0gcHJvcGVydGllcztcbiAgICAgICAgICAgICAgICAgICAgcHJvcHMgPSB7fTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICBwcm9wcyA9IHByb3BzIHx8IHByb3BlcnRpZXMgfHwge307XG4gICAgICAgICAgICAgICAgdGFnID0gcGFyc2VUYWcodGFnTmFtZSwgcHJvcHMpO1xuXG4gICAgICAgICAgICAgICAgLy8gc3VwcG9ydCBrZXlzXG4gICAgICAgICAgICAgICAgaWYgKHByb3BzLmhhc093blByb3BlcnR5KFwia2V5XCIpKSB7XG4gICAgICAgICAgICAgICAgICAgIGtleSA9IHByb3BzLmtleTtcbiAgICAgICAgICAgICAgICAgICAgcHJvcHMua2V5ID0gdW5kZWZpbmVkO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIC8vIHN1cHBvcnQgbmFtZXNwYWNlXG4gICAgICAgICAgICAgICAgaWYgKHByb3BzLmhhc093blByb3BlcnR5KFwibmFtZXNwYWNlXCIpKSB7XG4gICAgICAgICAgICAgICAgICAgIG5hbWVzcGFjZSA9IHByb3BzLm5hbWVzcGFjZTtcbiAgICAgICAgICAgICAgICAgICAgcHJvcHMubmFtZXNwYWNlID0gdW5kZWZpbmVkO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIC8vIGZpeCBjdXJzb3IgYnVnXG4gICAgICAgICAgICAgICAgaWYgKHRhZyA9PT0gXCJJTlBVVFwiICYmICFuYW1lc3BhY2UgJiYgcHJvcHMuaGFzT3duUHJvcGVydHkoXCJ2YWx1ZVwiKSAmJiBwcm9wcy52YWx1ZSAhPT0gdW5kZWZpbmVkICYmICFpc0hvb2socHJvcHMudmFsdWUpKSB7XG4gICAgICAgICAgICAgICAgICAgIHByb3BzLnZhbHVlID0gc29mdFNldEhvb2socHJvcHMudmFsdWUpO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHRyYW5zZm9ybVByb3BlcnRpZXMocHJvcHMpO1xuXG4gICAgICAgICAgICAgICAgaWYgKGNoaWxkcmVuICE9PSB1bmRlZmluZWQgJiYgY2hpbGRyZW4gIT09IG51bGwpIHtcbiAgICAgICAgICAgICAgICAgICAgYWRkQ2hpbGQoY2hpbGRyZW4sIGNoaWxkTm9kZXMsIHRhZywgcHJvcHMpO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHJldHVybiBuZXcgVk5vZGUodGFnLCBwcm9wcywgY2hpbGROb2Rlcywga2V5LCBuYW1lc3BhY2UpO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBmdW5jdGlvbiBhZGRDaGlsZChjLCBjaGlsZE5vZGVzLCB0YWcsIHByb3BzKSB7XG4gICAgICAgICAgICAgICAgaWYgKHR5cGVvZiBjID09PSBcInN0cmluZ1wiKSB7XG4gICAgICAgICAgICAgICAgICAgIGNoaWxkTm9kZXMucHVzaChuZXcgVlRleHQoYykpO1xuICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAodHlwZW9mIGMgPT09IFwibnVtYmVyXCIpIHtcbiAgICAgICAgICAgICAgICAgICAgY2hpbGROb2Rlcy5wdXNoKG5ldyBWVGV4dChTdHJpbmcoYykpKTtcbiAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKGlzQ2hpbGQoYykpIHtcbiAgICAgICAgICAgICAgICAgICAgY2hpbGROb2Rlcy5wdXNoKGMpO1xuICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoaXNBcnJheShjKSkge1xuICAgICAgICAgICAgICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IGMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGFkZENoaWxkKGNbaV0sIGNoaWxkTm9kZXMsIHRhZywgcHJvcHMpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfSBlbHNlIGlmIChjID09PSBudWxsIHx8IGMgPT09IHVuZGVmaW5lZCkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgdGhyb3cgVW5leHBlY3RlZFZpcnR1YWxFbGVtZW50KHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGZvcmVpZ25PYmplY3Q6IGMsXG4gICAgICAgICAgICAgICAgICAgICAgICBwYXJlbnRWbm9kZToge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRhZ05hbWU6IHRhZyxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBwcm9wZXJ0aWVzOiBwcm9wc1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIHRyYW5zZm9ybVByb3BlcnRpZXMocHJvcHMpIHtcbiAgICAgICAgICAgICAgICBmb3IgKHZhciBwcm9wTmFtZSBpbiBwcm9wcykge1xuICAgICAgICAgICAgICAgICAgICBpZiAocHJvcHMuaGFzT3duUHJvcGVydHkocHJvcE5hbWUpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICB2YXIgdmFsdWUgPSBwcm9wc1twcm9wTmFtZV07XG5cbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChpc0hvb2sodmFsdWUpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgY29udGludWU7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChwcm9wTmFtZS5zdWJzdHIoMCwgMykgPT09IFwiZXYtXCIpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBhZGQgZXYtZm9vIHN1cHBvcnRcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBwcm9wc1twcm9wTmFtZV0gPSBldkhvb2sodmFsdWUpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBmdW5jdGlvbiBpc0NoaWxkKHgpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gaXNWTm9kZSh4KSB8fCBpc1ZUZXh0KHgpIHx8IGlzV2lkZ2V0KHgpIHx8IGlzVlRodW5rKHgpO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBmdW5jdGlvbiBpc0NoaWxkcmVuKHgpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gdHlwZW9mIHggPT09IFwic3RyaW5nXCIgfHwgaXNBcnJheSh4KSB8fCBpc0NoaWxkKHgpO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBmdW5jdGlvbiBVbmV4cGVjdGVkVmlydHVhbEVsZW1lbnQoZGF0YSkge1xuICAgICAgICAgICAgICAgIHZhciBlcnIgPSBuZXcgRXJyb3IoKTtcblxuICAgICAgICAgICAgICAgIGVyci50eXBlID0gXCJ2aXJ0dWFsLWh5cGVyc2NyaXB0LnVuZXhwZWN0ZWQudmlydHVhbC1lbGVtZW50XCI7XG4gICAgICAgICAgICAgICAgZXJyLm1lc3NhZ2UgPSBcIlVuZXhwZWN0ZWQgdmlydHVhbCBjaGlsZCBwYXNzZWQgdG8gaCgpLlxcblwiICsgXCJFeHBlY3RlZCBhIFZOb2RlIC8gVnRodW5rIC8gVldpZGdldCAvIHN0cmluZyBidXQ6XFxuXCIgKyBcImdvdDpcXG5cIiArIGVycm9yU3RyaW5nKGRhdGEuZm9yZWlnbk9iamVjdCkgKyBcIi5cXG5cIiArIFwiVGhlIHBhcmVudCB2bm9kZSBpczpcXG5cIiArIGVycm9yU3RyaW5nKGRhdGEucGFyZW50Vm5vZGUpO1xuICAgICAgICAgICAgICAgIFwiXFxuXCIgKyBcIlN1Z2dlc3RlZCBmaXg6IGNoYW5nZSB5b3VyIGBoKC4uLiwgWyAuLi4gXSlgIGNhbGxzaXRlLlwiO1xuICAgICAgICAgICAgICAgIGVyci5mb3JlaWduT2JqZWN0ID0gZGF0YS5mb3JlaWduT2JqZWN0O1xuICAgICAgICAgICAgICAgIGVyci5wYXJlbnRWbm9kZSA9IGRhdGEucGFyZW50Vm5vZGU7XG5cbiAgICAgICAgICAgICAgICByZXR1cm4gZXJyO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBmdW5jdGlvbiBlcnJvclN0cmluZyhvYmopIHtcbiAgICAgICAgICAgICAgICB0cnkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gSlNPTi5zdHJpbmdpZnkob2JqLCBudWxsLCBcIiAgICBcIik7XG4gICAgICAgICAgICAgICAgfSBjYXRjaCAoZSkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gU3RyaW5nKG9iaik7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9LCB7IFwiLi4vdm5vZGUvaXMtdGh1bmtcIjogMjUsIFwiLi4vdm5vZGUvaXMtdmhvb2tcIjogMjYsIFwiLi4vdm5vZGUvaXMtdm5vZGVcIjogMjcsIFwiLi4vdm5vZGUvaXMtdnRleHRcIjogMjgsIFwiLi4vdm5vZGUvaXMtd2lkZ2V0XCI6IDI5LCBcIi4uL3Zub2RlL3Zub2RlLmpzXCI6IDMxLCBcIi4uL3Zub2RlL3Z0ZXh0LmpzXCI6IDMzLCBcIi4vaG9va3MvZXYtaG9vay5qc1wiOiAyMCwgXCIuL2hvb2tzL3NvZnQtc2V0LWhvb2suanNcIjogMjEsIFwiLi9wYXJzZS10YWcuanNcIjogMjMsIFwieC1pcy1hcnJheVwiOiAxMiB9XSwgMjM6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICBcInVzZSBzdHJpY3RcIjtcblxuICAgICAgICAgICAgdmFyIHNwbGl0ID0gcmVxdWlyZShcImJyb3dzZXItc3BsaXRcIik7XG5cbiAgICAgICAgICAgIHZhciBjbGFzc0lkU3BsaXQgPSAvKFtcXC4jXT9bYS16QS1aMC05XFx1MDA3Ri1cXHVGRkZGXzotXSspLztcbiAgICAgICAgICAgIHZhciBub3RDbGFzc0lkID0gL15cXC58Iy87XG5cbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gcGFyc2VUYWc7XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIHBhcnNlVGFnKHRhZywgcHJvcHMpIHtcbiAgICAgICAgICAgICAgICBpZiAoIXRhZykge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gXCJESVZcIjtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICB2YXIgbm9JZCA9ICFwcm9wcy5oYXNPd25Qcm9wZXJ0eShcImlkXCIpO1xuXG4gICAgICAgICAgICAgICAgdmFyIHRhZ1BhcnRzID0gc3BsaXQodGFnLCBjbGFzc0lkU3BsaXQpO1xuICAgICAgICAgICAgICAgIHZhciB0YWdOYW1lID0gbnVsbDtcblxuICAgICAgICAgICAgICAgIGlmIChub3RDbGFzc0lkLnRlc3QodGFnUGFydHNbMV0pKSB7XG4gICAgICAgICAgICAgICAgICAgIHRhZ05hbWUgPSBcIkRJVlwiO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHZhciBjbGFzc2VzLCBwYXJ0LCB0eXBlLCBpO1xuXG4gICAgICAgICAgICAgICAgZm9yIChpID0gMDsgaSA8IHRhZ1BhcnRzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICAgICAgICAgIHBhcnQgPSB0YWdQYXJ0c1tpXTtcblxuICAgICAgICAgICAgICAgICAgICBpZiAoIXBhcnQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnRpbnVlO1xuICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgdHlwZSA9IHBhcnQuY2hhckF0KDApO1xuXG4gICAgICAgICAgICAgICAgICAgIGlmICghdGFnTmFtZSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgdGFnTmFtZSA9IHBhcnQ7XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAodHlwZSA9PT0gXCIuXCIpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGNsYXNzZXMgPSBjbGFzc2VzIHx8IFtdO1xuICAgICAgICAgICAgICAgICAgICAgICAgY2xhc3Nlcy5wdXNoKHBhcnQuc3Vic3RyaW5nKDEsIHBhcnQubGVuZ3RoKSk7XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAodHlwZSA9PT0gXCIjXCIgJiYgbm9JZCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgcHJvcHMuaWQgPSBwYXJ0LnN1YnN0cmluZygxLCBwYXJ0Lmxlbmd0aCk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICBpZiAoY2xhc3Nlcykge1xuICAgICAgICAgICAgICAgICAgICBpZiAocHJvcHMuY2xhc3NOYW1lKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBjbGFzc2VzLnB1c2gocHJvcHMuY2xhc3NOYW1lKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgIHByb3BzLmNsYXNzTmFtZSA9IGNsYXNzZXMuam9pbihcIiBcIik7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgcmV0dXJuIHByb3BzLm5hbWVzcGFjZSA/IHRhZ05hbWUgOiB0YWdOYW1lLnRvVXBwZXJDYXNlKCk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0sIHsgXCJicm93c2VyLXNwbGl0XCI6IDUgfV0sIDI0OiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge1xuICAgICAgICAgICAgdmFyIGlzVk5vZGUgPSByZXF1aXJlKFwiLi9pcy12bm9kZVwiKTtcbiAgICAgICAgICAgIHZhciBpc1ZUZXh0ID0gcmVxdWlyZShcIi4vaXMtdnRleHRcIik7XG4gICAgICAgICAgICB2YXIgaXNXaWRnZXQgPSByZXF1aXJlKFwiLi9pcy13aWRnZXRcIik7XG4gICAgICAgICAgICB2YXIgaXNUaHVuayA9IHJlcXVpcmUoXCIuL2lzLXRodW5rXCIpO1xuXG4gICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IGhhbmRsZVRodW5rO1xuXG4gICAgICAgICAgICBmdW5jdGlvbiBoYW5kbGVUaHVuayhhLCBiKSB7XG4gICAgICAgICAgICAgICAgdmFyIHJlbmRlcmVkQSA9IGE7XG4gICAgICAgICAgICAgICAgdmFyIHJlbmRlcmVkQiA9IGI7XG5cbiAgICAgICAgICAgICAgICBpZiAoaXNUaHVuayhiKSkge1xuICAgICAgICAgICAgICAgICAgICByZW5kZXJlZEIgPSByZW5kZXJUaHVuayhiLCBhKTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICBpZiAoaXNUaHVuayhhKSkge1xuICAgICAgICAgICAgICAgICAgICByZW5kZXJlZEEgPSByZW5kZXJUaHVuayhhLCBudWxsKTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgICAgICAgICBhOiByZW5kZXJlZEEsXG4gICAgICAgICAgICAgICAgICAgIGI6IHJlbmRlcmVkQlxuICAgICAgICAgICAgICAgIH07XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIHJlbmRlclRodW5rKHRodW5rLCBwcmV2aW91cykge1xuICAgICAgICAgICAgICAgIHZhciByZW5kZXJlZFRodW5rID0gdGh1bmsudm5vZGU7XG5cbiAgICAgICAgICAgICAgICBpZiAoIXJlbmRlcmVkVGh1bmspIHtcbiAgICAgICAgICAgICAgICAgICAgcmVuZGVyZWRUaHVuayA9IHRodW5rLnZub2RlID0gdGh1bmsucmVuZGVyKHByZXZpb3VzKTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICBpZiAoIShpc1ZOb2RlKHJlbmRlcmVkVGh1bmspIHx8IGlzVlRleHQocmVuZGVyZWRUaHVuaykgfHwgaXNXaWRnZXQocmVuZGVyZWRUaHVuaykpKSB7XG4gICAgICAgICAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcihcInRodW5rIGRpZCBub3QgcmV0dXJuIGEgdmFsaWQgbm9kZVwiKTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICByZXR1cm4gcmVuZGVyZWRUaHVuaztcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSwgeyBcIi4vaXMtdGh1bmtcIjogMjUsIFwiLi9pcy12bm9kZVwiOiAyNywgXCIuL2lzLXZ0ZXh0XCI6IDI4LCBcIi4vaXMtd2lkZ2V0XCI6IDI5IH1dLCAyNTogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHtcbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gaXNUaHVuaztcblxuICAgICAgICAgICAgZnVuY3Rpb24gaXNUaHVuayh0KSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHQgJiYgdC50eXBlID09PSBcIlRodW5rXCI7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0sIHt9XSwgMjY6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IGlzSG9vaztcblxuICAgICAgICAgICAgZnVuY3Rpb24gaXNIb29rKGhvb2spIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gaG9vayAmJiAodHlwZW9mIGhvb2suaG9vayA9PT0gXCJmdW5jdGlvblwiICYmICFob29rLmhhc093blByb3BlcnR5KFwiaG9va1wiKSB8fCB0eXBlb2YgaG9vay51bmhvb2sgPT09IFwiZnVuY3Rpb25cIiAmJiAhaG9vay5oYXNPd25Qcm9wZXJ0eShcInVuaG9va1wiKSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0sIHt9XSwgMjc6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICB2YXIgdmVyc2lvbiA9IHJlcXVpcmUoXCIuL3ZlcnNpb25cIik7XG5cbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gaXNWaXJ0dWFsTm9kZTtcblxuICAgICAgICAgICAgZnVuY3Rpb24gaXNWaXJ0dWFsTm9kZSh4KSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHggJiYgeC50eXBlID09PSBcIlZpcnR1YWxOb2RlXCIgJiYgeC52ZXJzaW9uID09PSB2ZXJzaW9uO1xuICAgICAgICAgICAgfVxuICAgICAgICB9LCB7IFwiLi92ZXJzaW9uXCI6IDMwIH1dLCAyODogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHtcbiAgICAgICAgICAgIHZhciB2ZXJzaW9uID0gcmVxdWlyZShcIi4vdmVyc2lvblwiKTtcblxuICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBpc1ZpcnR1YWxUZXh0O1xuXG4gICAgICAgICAgICBmdW5jdGlvbiBpc1ZpcnR1YWxUZXh0KHgpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4geCAmJiB4LnR5cGUgPT09IFwiVmlydHVhbFRleHRcIiAmJiB4LnZlcnNpb24gPT09IHZlcnNpb247XG4gICAgICAgICAgICB9XG4gICAgICAgIH0sIHsgXCIuL3ZlcnNpb25cIjogMzAgfV0sIDI5OiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge1xuICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBpc1dpZGdldDtcblxuICAgICAgICAgICAgZnVuY3Rpb24gaXNXaWRnZXQodykge1xuICAgICAgICAgICAgICAgIHJldHVybiB3ICYmIHcudHlwZSA9PT0gXCJXaWRnZXRcIjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSwge31dLCAzMDogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHtcbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gXCIyXCI7XG4gICAgICAgIH0sIHt9XSwgMzE6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICB2YXIgdmVyc2lvbiA9IHJlcXVpcmUoXCIuL3ZlcnNpb25cIik7XG4gICAgICAgICAgICB2YXIgaXNWTm9kZSA9IHJlcXVpcmUoXCIuL2lzLXZub2RlXCIpO1xuICAgICAgICAgICAgdmFyIGlzV2lkZ2V0ID0gcmVxdWlyZShcIi4vaXMtd2lkZ2V0XCIpO1xuICAgICAgICAgICAgdmFyIGlzVGh1bmsgPSByZXF1aXJlKFwiLi9pcy10aHVua1wiKTtcbiAgICAgICAgICAgIHZhciBpc1ZIb29rID0gcmVxdWlyZShcIi4vaXMtdmhvb2tcIik7XG5cbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gVmlydHVhbE5vZGU7XG5cbiAgICAgICAgICAgIHZhciBub1Byb3BlcnRpZXMgPSB7fTtcbiAgICAgICAgICAgIHZhciBub0NoaWxkcmVuID0gW107XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIFZpcnR1YWxOb2RlKHRhZ05hbWUsIHByb3BlcnRpZXMsIGNoaWxkcmVuLCBrZXksIG5hbWVzcGFjZSkge1xuICAgICAgICAgICAgICAgIHRoaXMudGFnTmFtZSA9IHRhZ05hbWU7XG4gICAgICAgICAgICAgICAgdGhpcy5wcm9wZXJ0aWVzID0gcHJvcGVydGllcyB8fCBub1Byb3BlcnRpZXM7XG4gICAgICAgICAgICAgICAgdGhpcy5jaGlsZHJlbiA9IGNoaWxkcmVuIHx8IG5vQ2hpbGRyZW47XG4gICAgICAgICAgICAgICAgdGhpcy5rZXkgPSBrZXkgIT0gbnVsbCA/IFN0cmluZyhrZXkpIDogdW5kZWZpbmVkO1xuICAgICAgICAgICAgICAgIHRoaXMubmFtZXNwYWNlID0gdHlwZW9mIG5hbWVzcGFjZSA9PT0gXCJzdHJpbmdcIiA/IG5hbWVzcGFjZSA6IG51bGw7XG5cbiAgICAgICAgICAgICAgICB2YXIgY291bnQgPSBjaGlsZHJlbiAmJiBjaGlsZHJlbi5sZW5ndGggfHwgMDtcbiAgICAgICAgICAgICAgICB2YXIgZGVzY2VuZGFudHMgPSAwO1xuICAgICAgICAgICAgICAgIHZhciBoYXNXaWRnZXRzID0gZmFsc2U7XG4gICAgICAgICAgICAgICAgdmFyIGhhc1RodW5rcyA9IGZhbHNlO1xuICAgICAgICAgICAgICAgIHZhciBkZXNjZW5kYW50SG9va3MgPSBmYWxzZTtcbiAgICAgICAgICAgICAgICB2YXIgaG9va3M7XG5cbiAgICAgICAgICAgICAgICBmb3IgKHZhciBwcm9wTmFtZSBpbiBwcm9wZXJ0aWVzKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmIChwcm9wZXJ0aWVzLmhhc093blByb3BlcnR5KHByb3BOYW1lKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgdmFyIHByb3BlcnR5ID0gcHJvcGVydGllc1twcm9wTmFtZV07XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoaXNWSG9vayhwcm9wZXJ0eSkgJiYgcHJvcGVydHkudW5ob29rKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKCFob29rcykge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBob29rcyA9IHt9O1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGhvb2tzW3Byb3BOYW1lXSA9IHByb3BlcnR5O1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCBjb3VudDsgaSsrKSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciBjaGlsZCA9IGNoaWxkcmVuW2ldO1xuICAgICAgICAgICAgICAgICAgICBpZiAoaXNWTm9kZShjaGlsZCkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGRlc2NlbmRhbnRzICs9IGNoaWxkLmNvdW50IHx8IDA7XG5cbiAgICAgICAgICAgICAgICAgICAgICAgIGlmICghaGFzV2lkZ2V0cyAmJiBjaGlsZC5oYXNXaWRnZXRzKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaGFzV2lkZ2V0cyA9IHRydWU7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgICAgIGlmICghaGFzVGh1bmtzICYmIGNoaWxkLmhhc1RodW5rcykge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGhhc1RodW5rcyA9IHRydWU7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgICAgIGlmICghZGVzY2VuZGFudEhvb2tzICYmIChjaGlsZC5ob29rcyB8fCBjaGlsZC5kZXNjZW5kYW50SG9va3MpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgZGVzY2VuZGFudEhvb2tzID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIGlmICghaGFzV2lkZ2V0cyAmJiBpc1dpZGdldChjaGlsZCkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmICh0eXBlb2YgY2hpbGQuZGVzdHJveSA9PT0gXCJmdW5jdGlvblwiKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaGFzV2lkZ2V0cyA9IHRydWU7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoIWhhc1RodW5rcyAmJiBpc1RodW5rKGNoaWxkKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgaGFzVGh1bmtzID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHRoaXMuY291bnQgPSBjb3VudCArIGRlc2NlbmRhbnRzO1xuICAgICAgICAgICAgICAgIHRoaXMuaGFzV2lkZ2V0cyA9IGhhc1dpZGdldHM7XG4gICAgICAgICAgICAgICAgdGhpcy5oYXNUaHVua3MgPSBoYXNUaHVua3M7XG4gICAgICAgICAgICAgICAgdGhpcy5ob29rcyA9IGhvb2tzO1xuICAgICAgICAgICAgICAgIHRoaXMuZGVzY2VuZGFudEhvb2tzID0gZGVzY2VuZGFudEhvb2tzO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBWaXJ0dWFsTm9kZS5wcm90b3R5cGUudmVyc2lvbiA9IHZlcnNpb247XG4gICAgICAgICAgICBWaXJ0dWFsTm9kZS5wcm90b3R5cGUudHlwZSA9IFwiVmlydHVhbE5vZGVcIjtcbiAgICAgICAgfSwgeyBcIi4vaXMtdGh1bmtcIjogMjUsIFwiLi9pcy12aG9va1wiOiAyNiwgXCIuL2lzLXZub2RlXCI6IDI3LCBcIi4vaXMtd2lkZ2V0XCI6IDI5LCBcIi4vdmVyc2lvblwiOiAzMCB9XSwgMzI6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICB2YXIgdmVyc2lvbiA9IHJlcXVpcmUoXCIuL3ZlcnNpb25cIik7XG5cbiAgICAgICAgICAgIFZpcnR1YWxQYXRjaC5OT05FID0gMDtcbiAgICAgICAgICAgIFZpcnR1YWxQYXRjaC5WVEVYVCA9IDE7XG4gICAgICAgICAgICBWaXJ0dWFsUGF0Y2guVk5PREUgPSAyO1xuICAgICAgICAgICAgVmlydHVhbFBhdGNoLldJREdFVCA9IDM7XG4gICAgICAgICAgICBWaXJ0dWFsUGF0Y2guUFJPUFMgPSA0O1xuICAgICAgICAgICAgVmlydHVhbFBhdGNoLk9SREVSID0gNTtcbiAgICAgICAgICAgIFZpcnR1YWxQYXRjaC5JTlNFUlQgPSA2O1xuICAgICAgICAgICAgVmlydHVhbFBhdGNoLlJFTU9WRSA9IDc7XG4gICAgICAgICAgICBWaXJ0dWFsUGF0Y2guVEhVTksgPSA4O1xuXG4gICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IFZpcnR1YWxQYXRjaDtcblxuICAgICAgICAgICAgZnVuY3Rpb24gVmlydHVhbFBhdGNoKHR5cGUsIHZOb2RlLCBwYXRjaCkge1xuICAgICAgICAgICAgICAgIHRoaXMudHlwZSA9IE51bWJlcih0eXBlKTtcbiAgICAgICAgICAgICAgICB0aGlzLnZOb2RlID0gdk5vZGU7XG4gICAgICAgICAgICAgICAgdGhpcy5wYXRjaCA9IHBhdGNoO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBWaXJ0dWFsUGF0Y2gucHJvdG90eXBlLnZlcnNpb24gPSB2ZXJzaW9uO1xuICAgICAgICAgICAgVmlydHVhbFBhdGNoLnByb3RvdHlwZS50eXBlID0gXCJWaXJ0dWFsUGF0Y2hcIjtcbiAgICAgICAgfSwgeyBcIi4vdmVyc2lvblwiOiAzMCB9XSwgMzM6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICB2YXIgdmVyc2lvbiA9IHJlcXVpcmUoXCIuL3ZlcnNpb25cIik7XG5cbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gVmlydHVhbFRleHQ7XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIFZpcnR1YWxUZXh0KHRleHQpIHtcbiAgICAgICAgICAgICAgICB0aGlzLnRleHQgPSBTdHJpbmcodGV4dCk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIFZpcnR1YWxUZXh0LnByb3RvdHlwZS52ZXJzaW9uID0gdmVyc2lvbjtcbiAgICAgICAgICAgIFZpcnR1YWxUZXh0LnByb3RvdHlwZS50eXBlID0gXCJWaXJ0dWFsVGV4dFwiO1xuICAgICAgICB9LCB7IFwiLi92ZXJzaW9uXCI6IDMwIH1dLCAzNDogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHtcbiAgICAgICAgICAgIHZhciBpc09iamVjdCA9IHJlcXVpcmUoXCJpcy1vYmplY3RcIik7XG4gICAgICAgICAgICB2YXIgaXNIb29rID0gcmVxdWlyZShcIi4uL3Zub2RlL2lzLXZob29rXCIpO1xuXG4gICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IGRpZmZQcm9wcztcblxuICAgICAgICAgICAgZnVuY3Rpb24gZGlmZlByb3BzKGEsIGIpIHtcbiAgICAgICAgICAgICAgICB2YXIgZGlmZjtcblxuICAgICAgICAgICAgICAgIGZvciAodmFyIGFLZXkgaW4gYSkge1xuICAgICAgICAgICAgICAgICAgICBpZiAoIShhS2V5IGluIGIpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBkaWZmID0gZGlmZiB8fCB7fTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGRpZmZbYUtleV0gPSB1bmRlZmluZWQ7XG4gICAgICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgICAgICB2YXIgYVZhbHVlID0gYVthS2V5XTtcbiAgICAgICAgICAgICAgICAgICAgdmFyIGJWYWx1ZSA9IGJbYUtleV07XG5cbiAgICAgICAgICAgICAgICAgICAgaWYgKGFWYWx1ZSA9PT0gYlZhbHVlKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBjb250aW51ZTtcbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIGlmIChpc09iamVjdChhVmFsdWUpICYmIGlzT2JqZWN0KGJWYWx1ZSkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChnZXRQcm90b3R5cGUoYlZhbHVlKSAhPT0gZ2V0UHJvdG90eXBlKGFWYWx1ZSkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBkaWZmID0gZGlmZiB8fCB7fTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBkaWZmW2FLZXldID0gYlZhbHVlO1xuICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIGlmIChpc0hvb2soYlZhbHVlKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRpZmYgPSBkaWZmIHx8IHt9O1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRpZmZbYUtleV0gPSBiVmFsdWU7XG4gICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZhciBvYmplY3REaWZmID0gZGlmZlByb3BzKGFWYWx1ZSwgYlZhbHVlKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAob2JqZWN0RGlmZikge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBkaWZmID0gZGlmZiB8fCB7fTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZGlmZlthS2V5XSA9IG9iamVjdERpZmY7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgZGlmZiA9IGRpZmYgfHwge307XG4gICAgICAgICAgICAgICAgICAgICAgICBkaWZmW2FLZXldID0gYlZhbHVlO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgZm9yICh2YXIgYktleSBpbiBiKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmICghKGJLZXkgaW4gYSkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGRpZmYgPSBkaWZmIHx8IHt9O1xuICAgICAgICAgICAgICAgICAgICAgICAgZGlmZltiS2V5XSA9IGJbYktleV07XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICByZXR1cm4gZGlmZjtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZnVuY3Rpb24gZ2V0UHJvdG90eXBlKHZhbHVlKSB7XG4gICAgICAgICAgICAgICAgaWYgKE9iamVjdC5nZXRQcm90b3R5cGVPZikge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gT2JqZWN0LmdldFByb3RvdHlwZU9mKHZhbHVlKTtcbiAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKHZhbHVlLl9fcHJvdG9fXykge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gdmFsdWUuX19wcm90b19fO1xuICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAodmFsdWUuY29uc3RydWN0b3IpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHZhbHVlLmNvbnN0cnVjdG9yLnByb3RvdHlwZTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH0sIHsgXCIuLi92bm9kZS9pcy12aG9va1wiOiAyNiwgXCJpcy1vYmplY3RcIjogMTEgfV0sIDM1OiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge1xuICAgICAgICAgICAgdmFyIGlzQXJyYXkgPSByZXF1aXJlKFwieC1pcy1hcnJheVwiKTtcblxuICAgICAgICAgICAgdmFyIFZQYXRjaCA9IHJlcXVpcmUoXCIuLi92bm9kZS92cGF0Y2hcIik7XG4gICAgICAgICAgICB2YXIgaXNWTm9kZSA9IHJlcXVpcmUoXCIuLi92bm9kZS9pcy12bm9kZVwiKTtcbiAgICAgICAgICAgIHZhciBpc1ZUZXh0ID0gcmVxdWlyZShcIi4uL3Zub2RlL2lzLXZ0ZXh0XCIpO1xuICAgICAgICAgICAgdmFyIGlzV2lkZ2V0ID0gcmVxdWlyZShcIi4uL3Zub2RlL2lzLXdpZGdldFwiKTtcbiAgICAgICAgICAgIHZhciBpc1RodW5rID0gcmVxdWlyZShcIi4uL3Zub2RlL2lzLXRodW5rXCIpO1xuICAgICAgICAgICAgdmFyIGhhbmRsZVRodW5rID0gcmVxdWlyZShcIi4uL3Zub2RlL2hhbmRsZS10aHVua1wiKTtcblxuICAgICAgICAgICAgdmFyIGRpZmZQcm9wcyA9IHJlcXVpcmUoXCIuL2RpZmYtcHJvcHNcIik7XG5cbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gZGlmZjtcblxuICAgICAgICAgICAgZnVuY3Rpb24gZGlmZihhLCBiKSB7XG4gICAgICAgICAgICAgICAgdmFyIHBhdGNoID0geyBhOiBhIH07XG4gICAgICAgICAgICAgICAgd2FsayhhLCBiLCBwYXRjaCwgMCk7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHBhdGNoO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBmdW5jdGlvbiB3YWxrKGEsIGIsIHBhdGNoLCBpbmRleCkge1xuICAgICAgICAgICAgICAgIGlmIChhID09PSBiKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICB2YXIgYXBwbHkgPSBwYXRjaFtpbmRleF07XG4gICAgICAgICAgICAgICAgdmFyIGFwcGx5Q2xlYXIgPSBmYWxzZTtcblxuICAgICAgICAgICAgICAgIGlmIChpc1RodW5rKGEpIHx8IGlzVGh1bmsoYikpIHtcbiAgICAgICAgICAgICAgICAgICAgdGh1bmtzKGEsIGIsIHBhdGNoLCBpbmRleCk7XG4gICAgICAgICAgICAgICAgfSBlbHNlIGlmIChiID09IG51bGwpIHtcblxuICAgICAgICAgICAgICAgICAgICAvLyBJZiBhIGlzIGEgd2lkZ2V0IHdlIHdpbGwgYWRkIGEgcmVtb3ZlIHBhdGNoIGZvciBpdFxuICAgICAgICAgICAgICAgICAgICAvLyBPdGhlcndpc2UgYW55IGNoaWxkIHdpZGdldHMvaG9va3MgbXVzdCBiZSBkZXN0cm95ZWQuXG4gICAgICAgICAgICAgICAgICAgIC8vIFRoaXMgcHJldmVudHMgYWRkaW5nIHR3byByZW1vdmUgcGF0Y2hlcyBmb3IgYSB3aWRnZXQuXG4gICAgICAgICAgICAgICAgICAgIGlmICghaXNXaWRnZXQoYSkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGNsZWFyU3RhdGUoYSwgcGF0Y2gsIGluZGV4KTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGFwcGx5ID0gcGF0Y2hbaW5kZXhdO1xuICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgYXBwbHkgPSBhcHBlbmRQYXRjaChhcHBseSwgbmV3IFZQYXRjaChWUGF0Y2guUkVNT1ZFLCBhLCBiKSk7XG4gICAgICAgICAgICAgICAgfSBlbHNlIGlmIChpc1ZOb2RlKGIpKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmIChpc1ZOb2RlKGEpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoYS50YWdOYW1lID09PSBiLnRhZ05hbWUgJiYgYS5uYW1lc3BhY2UgPT09IGIubmFtZXNwYWNlICYmIGEua2V5ID09PSBiLmtleSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZhciBwcm9wc1BhdGNoID0gZGlmZlByb3BzKGEucHJvcGVydGllcywgYi5wcm9wZXJ0aWVzKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAocHJvcHNQYXRjaCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBhcHBseSA9IGFwcGVuZFBhdGNoKGFwcGx5LCBuZXcgVlBhdGNoKFZQYXRjaC5QUk9QUywgYSwgcHJvcHNQYXRjaCkpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBhcHBseSA9IGRpZmZDaGlsZHJlbihhLCBiLCBwYXRjaCwgYXBwbHksIGluZGV4KTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgYXBwbHkgPSBhcHBlbmRQYXRjaChhcHBseSwgbmV3IFZQYXRjaChWUGF0Y2guVk5PREUsIGEsIGIpKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBhcHBseUNsZWFyID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGFwcGx5ID0gYXBwZW5kUGF0Y2goYXBwbHksIG5ldyBWUGF0Y2goVlBhdGNoLlZOT0RFLCBhLCBiKSk7XG4gICAgICAgICAgICAgICAgICAgICAgICBhcHBseUNsZWFyID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoaXNWVGV4dChiKSkge1xuICAgICAgICAgICAgICAgICAgICBpZiAoIWlzVlRleHQoYSkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGFwcGx5ID0gYXBwZW5kUGF0Y2goYXBwbHksIG5ldyBWUGF0Y2goVlBhdGNoLlZURVhULCBhLCBiKSk7XG4gICAgICAgICAgICAgICAgICAgICAgICBhcHBseUNsZWFyID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIGlmIChhLnRleHQgIT09IGIudGV4dCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgYXBwbHkgPSBhcHBlbmRQYXRjaChhcHBseSwgbmV3IFZQYXRjaChWUGF0Y2guVlRFWFQsIGEsIGIpKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoaXNXaWRnZXQoYikpIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKCFpc1dpZGdldChhKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgYXBwbHlDbGVhciA9IHRydWU7XG4gICAgICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgICAgICBhcHBseSA9IGFwcGVuZFBhdGNoKGFwcGx5LCBuZXcgVlBhdGNoKFZQYXRjaC5XSURHRVQsIGEsIGIpKTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICBpZiAoYXBwbHkpIHtcbiAgICAgICAgICAgICAgICAgICAgcGF0Y2hbaW5kZXhdID0gYXBwbHk7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgaWYgKGFwcGx5Q2xlYXIpIHtcbiAgICAgICAgICAgICAgICAgICAgY2xlYXJTdGF0ZShhLCBwYXRjaCwgaW5kZXgpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZnVuY3Rpb24gZGlmZkNoaWxkcmVuKGEsIGIsIHBhdGNoLCBhcHBseSwgaW5kZXgpIHtcbiAgICAgICAgICAgICAgICB2YXIgYUNoaWxkcmVuID0gYS5jaGlsZHJlbjtcbiAgICAgICAgICAgICAgICB2YXIgb3JkZXJlZFNldCA9IHJlb3JkZXIoYUNoaWxkcmVuLCBiLmNoaWxkcmVuKTtcbiAgICAgICAgICAgICAgICB2YXIgYkNoaWxkcmVuID0gb3JkZXJlZFNldC5jaGlsZHJlbjtcblxuICAgICAgICAgICAgICAgIHZhciBhTGVuID0gYUNoaWxkcmVuLmxlbmd0aDtcbiAgICAgICAgICAgICAgICB2YXIgYkxlbiA9IGJDaGlsZHJlbi5sZW5ndGg7XG4gICAgICAgICAgICAgICAgdmFyIGxlbiA9IGFMZW4gPiBiTGVuID8gYUxlbiA6IGJMZW47XG5cbiAgICAgICAgICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IGxlbjsgaSsrKSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciBsZWZ0Tm9kZSA9IGFDaGlsZHJlbltpXTtcbiAgICAgICAgICAgICAgICAgICAgdmFyIHJpZ2h0Tm9kZSA9IGJDaGlsZHJlbltpXTtcbiAgICAgICAgICAgICAgICAgICAgaW5kZXggKz0gMTtcblxuICAgICAgICAgICAgICAgICAgICBpZiAoIWxlZnROb2RlKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAocmlnaHROb2RlKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gRXhjZXNzIG5vZGVzIGluIGIgbmVlZCB0byBiZSBhZGRlZFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGFwcGx5ID0gYXBwZW5kUGF0Y2goYXBwbHksIG5ldyBWUGF0Y2goVlBhdGNoLklOU0VSVCwgbnVsbCwgcmlnaHROb2RlKSk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICB3YWxrKGxlZnROb2RlLCByaWdodE5vZGUsIHBhdGNoLCBpbmRleCk7XG4gICAgICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgICAgICBpZiAoaXNWTm9kZShsZWZ0Tm9kZSkgJiYgbGVmdE5vZGUuY291bnQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGluZGV4ICs9IGxlZnROb2RlLmNvdW50O1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgaWYgKG9yZGVyZWRTZXQubW92ZXMpIHtcbiAgICAgICAgICAgICAgICAgICAgLy8gUmVvcmRlciBub2RlcyBsYXN0XG4gICAgICAgICAgICAgICAgICAgIGFwcGx5ID0gYXBwZW5kUGF0Y2goYXBwbHksIG5ldyBWUGF0Y2goVlBhdGNoLk9SREVSLCBhLCBvcmRlcmVkU2V0Lm1vdmVzKSk7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgcmV0dXJuIGFwcGx5O1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBmdW5jdGlvbiBjbGVhclN0YXRlKHZOb2RlLCBwYXRjaCwgaW5kZXgpIHtcbiAgICAgICAgICAgICAgICAvLyBUT0RPOiBNYWtlIHRoaXMgYSBzaW5nbGUgd2Fsaywgbm90IHR3b1xuICAgICAgICAgICAgICAgIHVuaG9vayh2Tm9kZSwgcGF0Y2gsIGluZGV4KTtcbiAgICAgICAgICAgICAgICBkZXN0cm95V2lkZ2V0cyh2Tm9kZSwgcGF0Y2gsIGluZGV4KTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgLy8gUGF0Y2ggcmVjb3JkcyBmb3IgYWxsIGRlc3Ryb3llZCB3aWRnZXRzIG11c3QgYmUgYWRkZWQgYmVjYXVzZSB3ZSBuZWVkXG4gICAgICAgICAgICAvLyBhIERPTSBub2RlIHJlZmVyZW5jZSBmb3IgdGhlIGRlc3Ryb3kgZnVuY3Rpb25cbiAgICAgICAgICAgIGZ1bmN0aW9uIGRlc3Ryb3lXaWRnZXRzKHZOb2RlLCBwYXRjaCwgaW5kZXgpIHtcbiAgICAgICAgICAgICAgICBpZiAoaXNXaWRnZXQodk5vZGUpKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmICh0eXBlb2Ygdk5vZGUuZGVzdHJveSA9PT0gXCJmdW5jdGlvblwiKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBwYXRjaFtpbmRleF0gPSBhcHBlbmRQYXRjaChwYXRjaFtpbmRleF0sIG5ldyBWUGF0Y2goVlBhdGNoLlJFTU9WRSwgdk5vZGUsIG51bGwpKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoaXNWTm9kZSh2Tm9kZSkgJiYgKHZOb2RlLmhhc1dpZGdldHMgfHwgdk5vZGUuaGFzVGh1bmtzKSkge1xuICAgICAgICAgICAgICAgICAgICB2YXIgY2hpbGRyZW4gPSB2Tm9kZS5jaGlsZHJlbjtcbiAgICAgICAgICAgICAgICAgICAgdmFyIGxlbiA9IGNoaWxkcmVuLmxlbmd0aDtcbiAgICAgICAgICAgICAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCBsZW47IGkrKykge1xuICAgICAgICAgICAgICAgICAgICAgICAgdmFyIGNoaWxkID0gY2hpbGRyZW5baV07XG4gICAgICAgICAgICAgICAgICAgICAgICBpbmRleCArPSAxO1xuXG4gICAgICAgICAgICAgICAgICAgICAgICBkZXN0cm95V2lkZ2V0cyhjaGlsZCwgcGF0Y2gsIGluZGV4KTtcblxuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGlzVk5vZGUoY2hpbGQpICYmIGNoaWxkLmNvdW50KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaW5kZXggKz0gY2hpbGQuY291bnQ7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKGlzVGh1bmsodk5vZGUpKSB7XG4gICAgICAgICAgICAgICAgICAgIHRodW5rcyh2Tm9kZSwgbnVsbCwgcGF0Y2gsIGluZGV4KTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIC8vIENyZWF0ZSBhIHN1Yi1wYXRjaCBmb3IgdGh1bmtzXG4gICAgICAgICAgICBmdW5jdGlvbiB0aHVua3MoYSwgYiwgcGF0Y2gsIGluZGV4KSB7XG4gICAgICAgICAgICAgICAgdmFyIG5vZGVzID0gaGFuZGxlVGh1bmsoYSwgYik7XG4gICAgICAgICAgICAgICAgdmFyIHRodW5rUGF0Y2ggPSBkaWZmKG5vZGVzLmEsIG5vZGVzLmIpO1xuICAgICAgICAgICAgICAgIGlmIChoYXNQYXRjaGVzKHRodW5rUGF0Y2gpKSB7XG4gICAgICAgICAgICAgICAgICAgIHBhdGNoW2luZGV4XSA9IG5ldyBWUGF0Y2goVlBhdGNoLlRIVU5LLCBudWxsLCB0aHVua1BhdGNoKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIGhhc1BhdGNoZXMocGF0Y2gpIHtcbiAgICAgICAgICAgICAgICBmb3IgKHZhciBpbmRleCBpbiBwYXRjaCkge1xuICAgICAgICAgICAgICAgICAgICBpZiAoaW5kZXggIT09IFwiYVwiKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgLy8gRXhlY3V0ZSBob29rcyB3aGVuIHR3byBub2RlcyBhcmUgaWRlbnRpY2FsXG4gICAgICAgICAgICBmdW5jdGlvbiB1bmhvb2sodk5vZGUsIHBhdGNoLCBpbmRleCkge1xuICAgICAgICAgICAgICAgIGlmIChpc1ZOb2RlKHZOb2RlKSkge1xuICAgICAgICAgICAgICAgICAgICBpZiAodk5vZGUuaG9va3MpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHBhdGNoW2luZGV4XSA9IGFwcGVuZFBhdGNoKHBhdGNoW2luZGV4XSwgbmV3IFZQYXRjaChWUGF0Y2guUFJPUFMsIHZOb2RlLCB1bmRlZmluZWRLZXlzKHZOb2RlLmhvb2tzKSkpO1xuICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgaWYgKHZOb2RlLmRlc2NlbmRhbnRIb29rcyB8fCB2Tm9kZS5oYXNUaHVua3MpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHZhciBjaGlsZHJlbiA9IHZOb2RlLmNoaWxkcmVuO1xuICAgICAgICAgICAgICAgICAgICAgICAgdmFyIGxlbiA9IGNoaWxkcmVuLmxlbmd0aDtcbiAgICAgICAgICAgICAgICAgICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgbGVuOyBpKyspIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB2YXIgY2hpbGQgPSBjaGlsZHJlbltpXTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpbmRleCArPSAxO1xuXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdW5ob29rKGNoaWxkLCBwYXRjaCwgaW5kZXgpO1xuXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGlzVk5vZGUoY2hpbGQpICYmIGNoaWxkLmNvdW50KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGluZGV4ICs9IGNoaWxkLmNvdW50O1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoaXNUaHVuayh2Tm9kZSkpIHtcbiAgICAgICAgICAgICAgICAgICAgdGh1bmtzKHZOb2RlLCBudWxsLCBwYXRjaCwgaW5kZXgpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZnVuY3Rpb24gdW5kZWZpbmVkS2V5cyhvYmopIHtcbiAgICAgICAgICAgICAgICB2YXIgcmVzdWx0ID0ge307XG5cbiAgICAgICAgICAgICAgICBmb3IgKHZhciBrZXkgaW4gb2JqKSB7XG4gICAgICAgICAgICAgICAgICAgIHJlc3VsdFtrZXldID0gdW5kZWZpbmVkO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHJldHVybiByZXN1bHQ7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIC8vIExpc3QgZGlmZiwgbmFpdmUgbGVmdCB0byByaWdodCByZW9yZGVyaW5nXG4gICAgICAgICAgICBmdW5jdGlvbiByZW9yZGVyKGFDaGlsZHJlbiwgYkNoaWxkcmVuKSB7XG4gICAgICAgICAgICAgICAgLy8gTyhNKSB0aW1lLCBPKE0pIG1lbW9yeVxuICAgICAgICAgICAgICAgIHZhciBiQ2hpbGRJbmRleCA9IGtleUluZGV4KGJDaGlsZHJlbik7XG4gICAgICAgICAgICAgICAgdmFyIGJLZXlzID0gYkNoaWxkSW5kZXgua2V5cztcbiAgICAgICAgICAgICAgICB2YXIgYkZyZWUgPSBiQ2hpbGRJbmRleC5mcmVlO1xuXG4gICAgICAgICAgICAgICAgaWYgKGJGcmVlLmxlbmd0aCA9PT0gYkNoaWxkcmVuLmxlbmd0aCkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgICAgICAgICAgICAgY2hpbGRyZW46IGJDaGlsZHJlbixcbiAgICAgICAgICAgICAgICAgICAgICAgIG1vdmVzOiBudWxsXG4gICAgICAgICAgICAgICAgICAgIH07XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgLy8gTyhOKSB0aW1lLCBPKE4pIG1lbW9yeVxuICAgICAgICAgICAgICAgIHZhciBhQ2hpbGRJbmRleCA9IGtleUluZGV4KGFDaGlsZHJlbik7XG4gICAgICAgICAgICAgICAgdmFyIGFLZXlzID0gYUNoaWxkSW5kZXgua2V5cztcbiAgICAgICAgICAgICAgICB2YXIgYUZyZWUgPSBhQ2hpbGRJbmRleC5mcmVlO1xuXG4gICAgICAgICAgICAgICAgaWYgKGFGcmVlLmxlbmd0aCA9PT0gYUNoaWxkcmVuLmxlbmd0aCkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgICAgICAgICAgICAgY2hpbGRyZW46IGJDaGlsZHJlbixcbiAgICAgICAgICAgICAgICAgICAgICAgIG1vdmVzOiBudWxsXG4gICAgICAgICAgICAgICAgICAgIH07XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgLy8gTyhNQVgoTiwgTSkpIG1lbW9yeVxuICAgICAgICAgICAgICAgIHZhciBuZXdDaGlsZHJlbiA9IFtdO1xuXG4gICAgICAgICAgICAgICAgdmFyIGZyZWVJbmRleCA9IDA7XG4gICAgICAgICAgICAgICAgdmFyIGZyZWVDb3VudCA9IGJGcmVlLmxlbmd0aDtcbiAgICAgICAgICAgICAgICB2YXIgZGVsZXRlZEl0ZW1zID0gMDtcblxuICAgICAgICAgICAgICAgIC8vIEl0ZXJhdGUgdGhyb3VnaCBhIGFuZCBtYXRjaCBhIG5vZGUgaW4gYlxuICAgICAgICAgICAgICAgIC8vIE8oTikgdGltZSxcbiAgICAgICAgICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IGFDaGlsZHJlbi5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgICAgICAgICB2YXIgYUl0ZW0gPSBhQ2hpbGRyZW5baV07XG4gICAgICAgICAgICAgICAgICAgIHZhciBpdGVtSW5kZXg7XG5cbiAgICAgICAgICAgICAgICAgICAgaWYgKGFJdGVtLmtleSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGJLZXlzLmhhc093blByb3BlcnR5KGFJdGVtLmtleSkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBNYXRjaCB1cCB0aGUgb2xkIGtleXNcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpdGVtSW5kZXggPSBiS2V5c1thSXRlbS5rZXldO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIG5ld0NoaWxkcmVuLnB1c2goYkNoaWxkcmVuW2l0ZW1JbmRleF0pO1xuICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBSZW1vdmUgb2xkIGtleWVkIGl0ZW1zXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaXRlbUluZGV4ID0gaSAtIGRlbGV0ZWRJdGVtcysrO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIG5ld0NoaWxkcmVuLnB1c2gobnVsbCk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAvLyBNYXRjaCB0aGUgaXRlbSBpbiBhIHdpdGggdGhlIG5leHQgZnJlZSBpdGVtIGluIGJcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChmcmVlSW5kZXggPCBmcmVlQ291bnQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpdGVtSW5kZXggPSBiRnJlZVtmcmVlSW5kZXgrK107XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgbmV3Q2hpbGRyZW4ucHVzaChiQ2hpbGRyZW5baXRlbUluZGV4XSk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIFRoZXJlIGFyZSBubyBmcmVlIGl0ZW1zIGluIGIgdG8gbWF0Y2ggd2l0aFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIHRoZSBmcmVlIGl0ZW1zIGluIGEsIHNvIHRoZSBleHRyYSBmcmVlIG5vZGVzXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gYXJlIGRlbGV0ZWQuXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaXRlbUluZGV4ID0gaSAtIGRlbGV0ZWRJdGVtcysrO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIG5ld0NoaWxkcmVuLnB1c2gobnVsbCk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICB2YXIgbGFzdEZyZWVJbmRleCA9IGZyZWVJbmRleCA+PSBiRnJlZS5sZW5ndGggPyBiQ2hpbGRyZW4ubGVuZ3RoIDogYkZyZWVbZnJlZUluZGV4XTtcblxuICAgICAgICAgICAgICAgIC8vIEl0ZXJhdGUgdGhyb3VnaCBiIGFuZCBhcHBlbmQgYW55IG5ldyBrZXlzXG4gICAgICAgICAgICAgICAgLy8gTyhNKSB0aW1lXG4gICAgICAgICAgICAgICAgZm9yICh2YXIgaiA9IDA7IGogPCBiQ2hpbGRyZW4ubGVuZ3RoOyBqKyspIHtcbiAgICAgICAgICAgICAgICAgICAgdmFyIG5ld0l0ZW0gPSBiQ2hpbGRyZW5bal07XG5cbiAgICAgICAgICAgICAgICAgICAgaWYgKG5ld0l0ZW0ua2V5KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoIWFLZXlzLmhhc093blByb3BlcnR5KG5ld0l0ZW0ua2V5KSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIEFkZCBhbnkgbmV3IGtleWVkIGl0ZW1zXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gV2UgYXJlIGFkZGluZyBuZXcgaXRlbXMgdG8gdGhlIGVuZCBhbmQgdGhlbiBzb3J0aW5nIHRoZW1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBpbiBwbGFjZS4gSW4gZnV0dXJlIHdlIHNob3VsZCBpbnNlcnQgbmV3IGl0ZW1zIGluIHBsYWNlLlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIG5ld0NoaWxkcmVuLnB1c2gobmV3SXRlbSk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoaiA+PSBsYXN0RnJlZUluZGV4KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAvLyBBZGQgYW55IGxlZnRvdmVyIG5vbi1rZXllZCBpdGVtc1xuICAgICAgICAgICAgICAgICAgICAgICAgbmV3Q2hpbGRyZW4ucHVzaChuZXdJdGVtKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHZhciBzaW11bGF0ZSA9IG5ld0NoaWxkcmVuLnNsaWNlKCk7XG4gICAgICAgICAgICAgICAgdmFyIHNpbXVsYXRlSW5kZXggPSAwO1xuICAgICAgICAgICAgICAgIHZhciByZW1vdmVzID0gW107XG4gICAgICAgICAgICAgICAgdmFyIGluc2VydHMgPSBbXTtcbiAgICAgICAgICAgICAgICB2YXIgc2ltdWxhdGVJdGVtO1xuXG4gICAgICAgICAgICAgICAgZm9yICh2YXIgayA9IDA7IGsgPCBiQ2hpbGRyZW4ubGVuZ3RoOykge1xuICAgICAgICAgICAgICAgICAgICB2YXIgd2FudGVkSXRlbSA9IGJDaGlsZHJlbltrXTtcbiAgICAgICAgICAgICAgICAgICAgc2ltdWxhdGVJdGVtID0gc2ltdWxhdGVbc2ltdWxhdGVJbmRleF07XG5cbiAgICAgICAgICAgICAgICAgICAgLy8gcmVtb3ZlIGl0ZW1zXG4gICAgICAgICAgICAgICAgICAgIHdoaWxlIChzaW11bGF0ZUl0ZW0gPT09IG51bGwgJiYgc2ltdWxhdGUubGVuZ3RoKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICByZW1vdmVzLnB1c2gocmVtb3ZlKHNpbXVsYXRlLCBzaW11bGF0ZUluZGV4LCBudWxsKSk7XG4gICAgICAgICAgICAgICAgICAgICAgICBzaW11bGF0ZUl0ZW0gPSBzaW11bGF0ZVtzaW11bGF0ZUluZGV4XTtcbiAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgIGlmICghc2ltdWxhdGVJdGVtIHx8IHNpbXVsYXRlSXRlbS5rZXkgIT09IHdhbnRlZEl0ZW0ua2V5KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAvLyBpZiB3ZSBuZWVkIGEga2V5IGluIHRoaXMgcG9zaXRpb24uLi5cbiAgICAgICAgICAgICAgICAgICAgICAgIGlmICh3YW50ZWRJdGVtLmtleSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChzaW11bGF0ZUl0ZW0gJiYgc2ltdWxhdGVJdGVtLmtleSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBpZiBhbiBpbnNlcnQgZG9lc24ndCBwdXQgdGhpcyBrZXkgaW4gcGxhY2UsIGl0IG5lZWRzIHRvIG1vdmVcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGJLZXlzW3NpbXVsYXRlSXRlbS5rZXldICE9PSBrICsgMSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmVtb3Zlcy5wdXNoKHJlbW92ZShzaW11bGF0ZSwgc2ltdWxhdGVJbmRleCwgc2ltdWxhdGVJdGVtLmtleSkpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc2ltdWxhdGVJdGVtID0gc2ltdWxhdGVbc2ltdWxhdGVJbmRleF07XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBpZiB0aGUgcmVtb3ZlIGRpZG4ndCBwdXQgdGhlIHdhbnRlZCBpdGVtIGluIHBsYWNlLCB3ZSBuZWVkIHRvIGluc2VydCBpdFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKCFzaW11bGF0ZUl0ZW0gfHwgc2ltdWxhdGVJdGVtLmtleSAhPT0gd2FudGVkSXRlbS5rZXkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpbnNlcnRzLnB1c2goeyBrZXk6IHdhbnRlZEl0ZW0ua2V5LCB0bzogayB9KTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIGl0ZW1zIGFyZSBtYXRjaGluZywgc28gc2tpcCBhaGVhZFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc2ltdWxhdGVJbmRleCsrO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaW5zZXJ0cy5wdXNoKHsga2V5OiB3YW50ZWRJdGVtLmtleSwgdG86IGsgfSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpbnNlcnRzLnB1c2goeyBrZXk6IHdhbnRlZEl0ZW0ua2V5LCB0bzogayB9KTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaysrO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgLy8gYSBrZXkgaW4gc2ltdWxhdGUgaGFzIG5vIG1hdGNoaW5nIHdhbnRlZCBrZXksIHJlbW92ZSBpdFxuICAgICAgICAgICAgICAgICAgICAgICAgZWxzZSBpZiAoc2ltdWxhdGVJdGVtICYmIHNpbXVsYXRlSXRlbS5rZXkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICByZW1vdmVzLnB1c2gocmVtb3ZlKHNpbXVsYXRlLCBzaW11bGF0ZUluZGV4LCBzaW11bGF0ZUl0ZW0ua2V5KSk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBzaW11bGF0ZUluZGV4Kys7XG4gICAgICAgICAgICAgICAgICAgICAgICBrKys7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAvLyByZW1vdmUgYWxsIHRoZSByZW1haW5pbmcgbm9kZXMgZnJvbSBzaW11bGF0ZVxuICAgICAgICAgICAgICAgIHdoaWxlIChzaW11bGF0ZUluZGV4IDwgc2ltdWxhdGUubGVuZ3RoKSB7XG4gICAgICAgICAgICAgICAgICAgIHNpbXVsYXRlSXRlbSA9IHNpbXVsYXRlW3NpbXVsYXRlSW5kZXhdO1xuICAgICAgICAgICAgICAgICAgICByZW1vdmVzLnB1c2gocmVtb3ZlKHNpbXVsYXRlLCBzaW11bGF0ZUluZGV4LCBzaW11bGF0ZUl0ZW0gJiYgc2ltdWxhdGVJdGVtLmtleSkpO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIC8vIElmIHRoZSBvbmx5IG1vdmVzIHdlIGhhdmUgYXJlIGRlbGV0ZXMgdGhlbiB3ZSBjYW4ganVzdFxuICAgICAgICAgICAgICAgIC8vIGxldCB0aGUgZGVsZXRlIHBhdGNoIHJlbW92ZSB0aGVzZSBpdGVtcy5cbiAgICAgICAgICAgICAgICBpZiAocmVtb3Zlcy5sZW5ndGggPT09IGRlbGV0ZWRJdGVtcyAmJiAhaW5zZXJ0cy5sZW5ndGgpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGNoaWxkcmVuOiBuZXdDaGlsZHJlbixcbiAgICAgICAgICAgICAgICAgICAgICAgIG1vdmVzOiBudWxsXG4gICAgICAgICAgICAgICAgICAgIH07XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgICAgICAgICAgY2hpbGRyZW46IG5ld0NoaWxkcmVuLFxuICAgICAgICAgICAgICAgICAgICBtb3Zlczoge1xuICAgICAgICAgICAgICAgICAgICAgICAgcmVtb3ZlczogcmVtb3ZlcyxcbiAgICAgICAgICAgICAgICAgICAgICAgIGluc2VydHM6IGluc2VydHNcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH07XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIHJlbW92ZShhcnIsIGluZGV4LCBrZXkpIHtcbiAgICAgICAgICAgICAgICBhcnIuc3BsaWNlKGluZGV4LCAxKTtcblxuICAgICAgICAgICAgICAgIHJldHVybiB7XG4gICAgICAgICAgICAgICAgICAgIGZyb206IGluZGV4LFxuICAgICAgICAgICAgICAgICAgICBrZXk6IGtleVxuICAgICAgICAgICAgICAgIH07XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIGtleUluZGV4KGNoaWxkcmVuKSB7XG4gICAgICAgICAgICAgICAgdmFyIGtleXMgPSB7fTtcbiAgICAgICAgICAgICAgICB2YXIgZnJlZSA9IFtdO1xuICAgICAgICAgICAgICAgIHZhciBsZW5ndGggPSBjaGlsZHJlbi5sZW5ndGg7XG5cbiAgICAgICAgICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IGxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciBjaGlsZCA9IGNoaWxkcmVuW2ldO1xuXG4gICAgICAgICAgICAgICAgICAgIGlmIChjaGlsZC5rZXkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGtleXNbY2hpbGQua2V5XSA9IGk7XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBmcmVlLnB1c2goaSk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgICAgICAgICBrZXlzOiBrZXlzLCAvLyBBIGhhc2ggb2Yga2V5IG5hbWUgdG8gaW5kZXhcbiAgICAgICAgICAgICAgICAgICAgZnJlZTogZnJlZSAvLyBBbiBhcnJheSBvZiB1bmtleWVkIGl0ZW0gaW5kaWNlc1xuICAgICAgICAgICAgICAgIH07XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIGFwcGVuZFBhdGNoKGFwcGx5LCBwYXRjaCkge1xuICAgICAgICAgICAgICAgIGlmIChhcHBseSkge1xuICAgICAgICAgICAgICAgICAgICBpZiAoaXNBcnJheShhcHBseSkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGFwcGx5LnB1c2gocGF0Y2gpO1xuICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgYXBwbHkgPSBbYXBwbHksIHBhdGNoXTtcbiAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBhcHBseTtcbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gcGF0Y2g7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9LCB7IFwiLi4vdm5vZGUvaGFuZGxlLXRodW5rXCI6IDI0LCBcIi4uL3Zub2RlL2lzLXRodW5rXCI6IDI1LCBcIi4uL3Zub2RlL2lzLXZub2RlXCI6IDI3LCBcIi4uL3Zub2RlL2lzLXZ0ZXh0XCI6IDI4LCBcIi4uL3Zub2RlL2lzLXdpZGdldFwiOiAyOSwgXCIuLi92bm9kZS92cGF0Y2hcIjogMzIsIFwiLi9kaWZmLXByb3BzXCI6IDM0LCBcIngtaXMtYXJyYXlcIjogMTIgfV0gfSwge30sIFs0XSkoNCk7XG59KTtcblxuLyogQGZsb3cgKi9cblxuY2xhc3MgTWFpbGJveCB7XG5cbiAgY29uc3RydWN0b3IoKSB7XG4gICAgdGhpcy5tZXNzYWdlcyA9IFtdO1xuICB9XG5cbiAgZGVsaXZlcihtZXNzYWdlKSB7XG4gICAgdGhpcy5tZXNzYWdlcy5wdXNoKG1lc3NhZ2UpO1xuICAgIHJldHVybiBtZXNzYWdlO1xuICB9XG5cbiAgZ2V0KCkge1xuICAgIHJldHVybiB0aGlzLm1lc3NhZ2VzO1xuICB9XG5cbiAgaXNFbXB0eSgpIHtcbiAgICByZXR1cm4gdGhpcy5tZXNzYWdlcy5sZW5ndGggPT09IDA7XG4gIH1cblxuICByZW1vdmVBdChpbmRleCkge1xuICAgIHRoaXMubWVzc2FnZXMuc3BsaWNlKGluZGV4LCAxKTtcbiAgfVxufVxuXG52YXIgU3RhdGVzID0ge1xuICBOT1JNQUw6IFN5bWJvbC5mb3IoXCJub3JtYWxcIiksXG4gIEtJTEw6IFN5bWJvbC5mb3IoXCJraWxsXCIpLFxuICBTVVNQRU5EOiBTeW1ib2wuZm9yKFwic3VzcGVuZFwiKSxcbiAgQ09OVElOVUU6IFN5bWJvbC5mb3IoXCJjb250aW51ZVwiKSxcbiAgUkVDRUlWRTogU3ltYm9sLmZvcihcInJlY2VpdmVcIiksXG4gIFNFTkQ6IFN5bWJvbC5mb3IoXCJzZW5kXCIpLFxuICBTTEVFUElORzogU3ltYm9sLmZvcihcInNsZWVwaW5nXCIpLFxuICBSVU5OSU5HOiBTeW1ib2wuZm9yKFwicnVubmluZ1wiKSxcbiAgU1VTUEVOREVEOiBTeW1ib2wuZm9yKFwic3VzcGVuZGVkXCIpLFxuICBTVE9QUEVEOiBTeW1ib2wuZm9yKFwic3RvcHBlZFwiKSxcbiAgU0xFRVA6IFN5bWJvbC5mb3IoXCJzbGVlcFwiKSxcbiAgRVhJVDogU3ltYm9sLmZvcihcImV4aXRcIiksXG4gIE5PTUFUQ0g6IFN5bWJvbC5mb3IoXCJub19tYXRjaFwiKVxufTtcblxuY2xhc3MgUHJvY2VzcyB7XG5cbiAgY29uc3RydWN0b3IocGlkLCBtYWlsYm94KSB7XG4gICAgdGhpcy5waWQgPSBwaWQ7XG4gICAgdGhpcy5tYWlsYm94ID0gbWFpbGJveDtcbiAgICB0aGlzLnN0YXR1cyA9IFN0YXRlcy5TVE9QUEVEO1xuICAgIHRoaXMuZGljdCA9IHt9O1xuICB9XG59XG5cbmNsYXNzIFR1cGxlIHtcblxuICBjb25zdHJ1Y3RvciguLi5hcmdzKSB7XG4gICAgdGhpcy52YWx1ZXMgPSBPYmplY3QuZnJlZXplKGFyZ3MpO1xuICAgIHRoaXMubGVuZ3RoID0gdGhpcy52YWx1ZXMubGVuZ3RoO1xuICB9XG5cbiAgZ2V0KGluZGV4KSB7XG4gICAgcmV0dXJuIHRoaXMudmFsdWVzW2luZGV4XTtcbiAgfVxuXG4gIGNvdW50KCkge1xuICAgIHJldHVybiB0aGlzLnZhbHVlcy5sZW5ndGg7XG4gIH1cblxuICBbU3ltYm9sLml0ZXJhdG9yXSgpIHtcbiAgICByZXR1cm4gdGhpcy52YWx1ZXNbU3ltYm9sLml0ZXJhdG9yXSgpO1xuICB9XG5cbiAgdG9TdHJpbmcoKSB7XG4gICAgdmFyIGksXG4gICAgICAgIHMgPSBcIlwiO1xuICAgIGZvciAoaSA9IDA7IGkgPCB0aGlzLnZhbHVlcy5sZW5ndGg7IGkrKykge1xuICAgICAgaWYgKHMgIT09IFwiXCIpIHtcbiAgICAgICAgcyArPSBcIiwgXCI7XG4gICAgICB9XG4gICAgICBzICs9IHRoaXMudmFsdWVzW2ldLnRvU3RyaW5nKCk7XG4gICAgfVxuXG4gICAgcmV0dXJuIFwie1wiICsgcyArIFwifVwiO1xuICB9XG5cbn1cblxubGV0IHByb2Nlc3NfY291bnRlciA9IC0xO1xuXG5jbGFzcyBQSUQge1xuICBjb25zdHJ1Y3RvcigpIHtcbiAgICBwcm9jZXNzX2NvdW50ZXIgPSBwcm9jZXNzX2NvdW50ZXIgKyAxO1xuICAgIHRoaXMuaWQgPSBwcm9jZXNzX2NvdW50ZXI7XG4gIH1cblxuICB0b1N0cmluZygpIHtcbiAgICByZXR1cm4gXCJQSUQjPDAuXCIgKyB0aGlzLmlkICsgXCIuMD5cIjtcbiAgfVxufVxuXG5jbGFzcyBJbnRlZ2VyIHt9XG5jbGFzcyBGbG9hdCB7fVxuXG5jbGFzcyBQcm9jZXNzU3lzdGVtIHtcblxuICBjb25zdHJ1Y3RvcigpIHtcbiAgICB0aGlzLnBpZHMgPSBuZXcgTWFwKCk7XG4gICAgdGhpcy5tYWlsYm94ZXMgPSBuZXcgTWFwKCk7XG4gICAgdGhpcy5uYW1lcyA9IG5ldyBNYXAoKTtcbiAgICB0aGlzLmxpbmtzID0gbmV3IE1hcCgpO1xuXG4gICAgdGhpcy5jdXJyZW50X3Byb2Nlc3MgPSBudWxsO1xuICAgIHRoaXMuc3VzcGVuZGVkID0gbmV3IE1hcCgpO1xuXG4gICAgdGhpcy5tYWluX3Byb2Nlc3NfcGlkID0gdGhpcy5zcGF3bigpO1xuICAgIHRoaXMuc2V0X2N1cnJlbnQodGhpcy5tYWluX3Byb2Nlc3NfcGlkKTtcbiAgfVxuXG4gIHNwYXduKCkge1xuICAgIHJldHVybiB0aGlzLmFkZF9wcm9jKGZhbHNlKS5waWQ7XG4gIH1cblxuICBzcGF3bl9saW5rKCkge1xuICAgIHJldHVybiB0aGlzLmFkZF9wcm9jKHRydWUpLnBpZDtcbiAgfVxuXG4gIGxpbmsocGlkKSB7XG4gICAgdGhpcy5saW5rcy5nZXQodGhpcy5waWQoKSkuYWRkKHBpZCk7XG4gICAgdGhpcy5saW5rcy5nZXQocGlkKS5hZGQodGhpcy5waWQoKSk7XG4gIH1cblxuICB1bmxpbmsocGlkKSB7XG4gICAgdGhpcy5saW5rcy5nZXQodGhpcy5waWQoKSkuZGVsZXRlKHBpZCk7XG4gICAgdGhpcy5saW5rcy5nZXQocGlkKS5kZWxldGUodGhpcy5waWQoKSk7XG4gIH1cblxuICBzZXRfY3VycmVudChpZCkge1xuICAgIGxldCBwaWQgPSB0aGlzLnBpZG9mKGlkKTtcbiAgICBpZiAocGlkICE9PSBudWxsKSB7XG4gICAgICB0aGlzLmN1cnJlbnRfcHJvY2VzcyA9IHRoaXMucGlkcy5nZXQocGlkKTtcbiAgICAgIHRoaXMuY3VycmVudF9wcm9jZXNzLnN0YXR1cyA9IFN0YXRlcy5SVU5OSU5HO1xuICAgIH1cbiAgfVxuXG4gIGFkZF9wcm9jKGxpbmtlZCkge1xuICAgIGxldCBuZXdwaWQgPSBuZXcgUElEKCk7XG4gICAgbGV0IG1haWxib3ggPSBuZXcgTWFpbGJveCgpO1xuICAgIGxldCBuZXdwcm9jID0gbmV3IFByb2Nlc3MobmV3cGlkLCBtYWlsYm94KTtcblxuICAgIHRoaXMucGlkcy5zZXQobmV3cGlkLCBuZXdwcm9jKTtcbiAgICB0aGlzLm1haWxib3hlcy5zZXQobmV3cGlkLCBtYWlsYm94KTtcbiAgICB0aGlzLmxpbmtzLnNldChuZXdwaWQsIG5ldyBTZXQoKSk7XG5cbiAgICBpZiAobGlua2VkKSB7XG4gICAgICB0aGlzLmxpbmsobmV3cGlkKTtcbiAgICB9XG5cbiAgICByZXR1cm4gbmV3cHJvYztcbiAgfVxuXG4gIHJlbW92ZV9wcm9jKHBpZCkge1xuICAgIHRoaXMucGlkcy5kZWxldGUocGlkKTtcbiAgICB0aGlzLnVucmVnaXN0ZXIocGlkKTtcblxuICAgIGlmICh0aGlzLmxpbmtzLmhhcyhwaWQpKSB7XG4gICAgICBmb3IgKGxldCBsaW5rcGlkIG9mIHRoaXMubGlua3MuZ2V0KHBpZCkpIHtcbiAgICAgICAgdGhpcy5saW5rcy5nZXQobGlua3BpZCkuZGVsZXRlKHBpZCk7XG4gICAgICB9XG5cbiAgICAgIHRoaXMubGlua3MuZGVsZXRlKHBpZCk7XG4gICAgfVxuICB9XG5cbiAgZXhpdChpZCkge1xuICAgIGxldCBwaWQgPSB0aGlzLnBpZG9mKGlkKTtcbiAgICB0aGlzLnJlbW92ZV9wcm9jKGlkKTtcbiAgfVxuXG4gIHJlZ2lzdGVyKG5hbWUsIHBpZCkge1xuICAgIGlmICghdGhpcy5uYW1lcy5oYXMobmFtZSkpIHtcbiAgICAgIHRoaXMubmFtZXMuc2V0KG5hbWUsIHBpZCk7XG4gICAgICByZXR1cm4gbmFtZTtcbiAgICB9IGVsc2Uge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKFwiTmFtZSBpcyBhbHJlYWR5IHJlZ2lzdGVyZWQgdG8gYW5vdGhlciBwcm9jZXNzXCIpO1xuICAgIH1cbiAgfVxuXG4gIHJlZ2lzdGVyZWQobmFtZSkge1xuICAgIHJldHVybiB0aGlzLm5hbWVzLmhhcyhuYW1lKSA/IHRoaXMubmFtZXMuZ2V0KG5hbWUpIDogbnVsbDtcbiAgfVxuXG4gIHVucmVnaXN0ZXIocGlkKSB7XG4gICAgZm9yIChsZXQgbmFtZSBvZiB0aGlzLm5hbWVzLmtleXMoKSkge1xuICAgICAgaWYgKHRoaXMubmFtZXMuaGFzKG5hbWUpICYmIHRoaXMubmFtZXMuZ2V0KG5hbWUpID09PSBwaWQpIHtcbiAgICAgICAgdGhpcy5uYW1lcy5kZWxldGUobmFtZSk7XG4gICAgICB9XG4gICAgfVxuICB9XG5cbiAgcGlkKCkge1xuICAgIHJldHVybiB0aGlzLmN1cnJlbnRfcHJvY2Vzcy5waWQ7XG4gIH1cblxuICBwaWRvZihpZCkge1xuICAgIGlmIChpZCBpbnN0YW5jZW9mIFBJRCkge1xuICAgICAgcmV0dXJuIHRoaXMucGlkcy5oYXMoaWQpID8gaWQgOiBudWxsO1xuICAgIH0gZWxzZSBpZiAoaWQgaW5zdGFuY2VvZiBQcm9jZXNzKSB7XG4gICAgICByZXR1cm4gaWQucGlkO1xuICAgIH0gZWxzZSB7XG4gICAgICBsZXQgcGlkID0gdGhpcy5yZWdpc3RlcmVkKGlkKTtcbiAgICAgIGlmIChwaWQgPT09IG51bGwpIHRocm93IFwiUHJvY2VzcyBuYW1lIG5vdCByZWdpc3RlcmVkOiBcIiArIGlkICsgXCIgKFwiICsgdHlwZW9mIGlkICsgXCIpXCI7XG4gICAgICByZXR1cm4gcGlkO1xuICAgIH1cbiAgfVxuXG4gIHB1dChpZCwga2V5LCB2YWx1ZSkge1xuICAgIGxldCBwaWQgPSB0aGlzLnBpZG9mKGlkKTtcbiAgICBsZXQgcHJvY2VzcyA9IHRoaXMucGlkcy5nZXQocGlkKTtcbiAgICBwcm9jZXNzLmRpY3Rba2V5XSA9IHZhbHVlO1xuICB9XG5cbiAgZ2V0KGlkLCBrZXkpIHtcbiAgICBsZXQgcGlkID0gdGhpcy5waWRvZihpZCk7XG4gICAgbGV0IHByb2Nlc3MgPSB0aGlzLnBpZHMuZ2V0KHBpZCk7XG5cbiAgICBpZiAoa2V5ICE9IG51bGwpIHtcbiAgICAgIHJldHVybiBwcm9jZXNzLmRpY3Rba2V5XTtcbiAgICB9IGVsc2Uge1xuICAgICAgcmV0dXJuIHByb2Nlc3MuZGljdDtcbiAgICB9XG4gIH1cblxuICBnZXRfa2V5cyhpZCkge1xuICAgIGxldCBwaWQgPSB0aGlzLnBpZG9mKGlkKTtcbiAgICBsZXQgcHJvY2VzcyA9IHRoaXMucGlkcy5nZXQocGlkKTtcblxuICAgIHJldHVybiBPYmplY3Qua2V5cyhwcm9jZXNzLmRpY3QpO1xuICB9XG5cbiAgZXJhc2UoaWQsIGtleSkge1xuICAgIGxldCBwaWQgPSB0aGlzLnBpZG9mKGlkKTtcbiAgICBsZXQgcHJvY2VzcyA9IHRoaXMucGlkcy5nZXQocGlkKTtcblxuICAgIGlmIChrZXkgIT0gbnVsbCkge1xuICAgICAgZGVsZXRlIHByb2Nlc3MuZGljdFtrZXldO1xuICAgIH0gZWxzZSB7XG4gICAgICBwcm9jZXNzLmRpY3QgPSB7fTtcbiAgICB9XG4gIH1cbn1cblxuY2xhc3MgQml0U3RyaW5nIHtcbiAgY29uc3RydWN0b3IoLi4uYXJncykge1xuICAgIHRoaXMucmF3X3ZhbHVlID0gZnVuY3Rpb24gKCkge1xuICAgICAgcmV0dXJuIE9iamVjdC5mcmVlemUoYXJncyk7XG4gICAgfTtcblxuICAgIHRoaXMudmFsdWUgPSBPYmplY3QuZnJlZXplKHRoaXMucHJvY2VzcyhhcmdzKSk7XG4gIH1cblxuICBnZXQoaW5kZXgpIHtcbiAgICByZXR1cm4gdGhpcy52YWx1ZVtpbmRleF07XG4gIH1cblxuICBjb3VudCgpIHtcbiAgICByZXR1cm4gdGhpcy52YWx1ZS5sZW5ndGg7XG4gIH1cblxuICBbU3ltYm9sLml0ZXJhdG9yXSgpIHtcbiAgICByZXR1cm4gdGhpcy52YWx1ZVtTeW1ib2wuaXRlcmF0b3JdKCk7XG4gIH1cblxuICB0b1N0cmluZygpIHtcbiAgICB2YXIgaSxcbiAgICAgICAgcyA9IFwiXCI7XG4gICAgZm9yIChpID0gMDsgaSA8IHRoaXMuY291bnQoKTsgaSsrKSB7XG4gICAgICBpZiAocyAhPT0gXCJcIikge1xuICAgICAgICBzICs9IFwiLCBcIjtcbiAgICAgIH1cbiAgICAgIHMgKz0gdGhpc1tpXS50b1N0cmluZygpO1xuICAgIH1cblxuICAgIHJldHVybiBcIjw8XCIgKyBzICsgXCI+PlwiO1xuICB9XG5cbiAgcHJvY2VzcygpIHtcbiAgICBsZXQgcHJvY2Vzc2VkX3ZhbHVlcyA9IFtdO1xuXG4gICAgdmFyIGk7XG4gICAgZm9yIChpID0gMDsgaSA8IHRoaXMucmF3X3ZhbHVlKCkubGVuZ3RoOyBpKyspIHtcbiAgICAgIGxldCBwcm9jZXNzZWRfdmFsdWUgPSB0aGlzW1wicHJvY2Vzc19cIiArIHRoaXMucmF3X3ZhbHVlKClbaV0udHlwZV0odGhpcy5yYXdfdmFsdWUoKVtpXSk7XG5cbiAgICAgIGZvciAobGV0IGF0dHIgb2YgdGhpcy5yYXdfdmFsdWUoKVtpXS5hdHRyaWJ1dGVzKSB7XG4gICAgICAgIHByb2Nlc3NlZF92YWx1ZSA9IHRoaXNbXCJwcm9jZXNzX1wiICsgYXR0cl0ocHJvY2Vzc2VkX3ZhbHVlKTtcbiAgICAgIH1cblxuICAgICAgcHJvY2Vzc2VkX3ZhbHVlcyA9IHByb2Nlc3NlZF92YWx1ZXMuY29uY2F0KHByb2Nlc3NlZF92YWx1ZSk7XG4gICAgfVxuXG4gICAgcmV0dXJuIHByb2Nlc3NlZF92YWx1ZXM7XG4gIH1cblxuICBwcm9jZXNzX2ludGVnZXIodmFsdWUpIHtcbiAgICByZXR1cm4gdmFsdWUudmFsdWU7XG4gIH1cblxuICBwcm9jZXNzX2Zsb2F0KHZhbHVlKSB7XG4gICAgaWYgKHZhbHVlLnNpemUgPT09IDY0KSB7XG4gICAgICByZXR1cm4gQml0U3RyaW5nLmZsb2F0NjRUb0J5dGVzKHZhbHVlLnZhbHVlKTtcbiAgICB9IGVsc2UgaWYgKHZhbHVlLnNpemUgPT09IDMyKSB7XG4gICAgICByZXR1cm4gQml0U3RyaW5nLmZsb2F0MzJUb0J5dGVzKHZhbHVlLnZhbHVlKTtcbiAgICB9XG5cbiAgICB0aHJvdyBuZXcgRXJyb3IoXCJJbnZhbGlkIHNpemUgZm9yIGZsb2F0XCIpO1xuICB9XG5cbiAgcHJvY2Vzc19iaXRzdHJpbmcodmFsdWUpIHtcbiAgICByZXR1cm4gdmFsdWUudmFsdWUudmFsdWU7XG4gIH1cblxuICBwcm9jZXNzX2JpbmFyeSh2YWx1ZSkge1xuICAgIHJldHVybiBCaXRTdHJpbmcudG9VVEY4QXJyYXkodmFsdWUudmFsdWUpO1xuICB9XG5cbiAgcHJvY2Vzc191dGY4KHZhbHVlKSB7XG4gICAgcmV0dXJuIEJpdFN0cmluZy50b1VURjhBcnJheSh2YWx1ZS52YWx1ZSk7XG4gIH1cblxuICBwcm9jZXNzX3V0ZjE2KHZhbHVlKSB7XG4gICAgcmV0dXJuIEJpdFN0cmluZy50b1VURjE2QXJyYXkodmFsdWUudmFsdWUpO1xuICB9XG5cbiAgcHJvY2Vzc191dGYzMih2YWx1ZSkge1xuICAgIHJldHVybiBCaXRTdHJpbmcudG9VVEYzMkFycmF5KHZhbHVlLnZhbHVlKTtcbiAgfVxuXG4gIHByb2Nlc3Nfc2lnbmVkKHZhbHVlKSB7XG4gICAgcmV0dXJuIG5ldyBVaW50OEFycmF5KFt2YWx1ZV0pWzBdO1xuICB9XG5cbiAgcHJvY2Vzc191bnNpZ25lZCh2YWx1ZSkge1xuICAgIHJldHVybiB2YWx1ZTtcbiAgfVxuXG4gIHByb2Nlc3NfbmF0aXZlKHZhbHVlKSB7XG4gICAgcmV0dXJuIHZhbHVlO1xuICB9XG5cbiAgcHJvY2Vzc19iaWcodmFsdWUpIHtcbiAgICByZXR1cm4gdmFsdWU7XG4gIH1cblxuICBwcm9jZXNzX2xpdHRsZSh2YWx1ZSkge1xuICAgIHJldHVybiB2YWx1ZS5yZXZlcnNlKCk7XG4gIH1cblxuICBwcm9jZXNzX3NpemUodmFsdWUpIHtcbiAgICByZXR1cm4gdmFsdWU7XG4gIH1cblxuICBwcm9jZXNzX3VuaXQodmFsdWUpIHtcbiAgICByZXR1cm4gdmFsdWU7XG4gIH1cblxuICBzdGF0aWMgaW50ZWdlcih2YWx1ZSkge1xuICAgIHJldHVybiBCaXRTdHJpbmcud3JhcCh2YWx1ZSwgeyBcInR5cGVcIjogXCJpbnRlZ2VyXCIsIFwidW5pdFwiOiAxLCBcInNpemVcIjogOCB9KTtcbiAgfVxuXG4gIHN0YXRpYyBmbG9hdCh2YWx1ZSkge1xuICAgIHJldHVybiBCaXRTdHJpbmcud3JhcCh2YWx1ZSwgeyBcInR5cGVcIjogXCJmbG9hdFwiLCBcInVuaXRcIjogMSwgXCJzaXplXCI6IDY0IH0pO1xuICB9XG5cbiAgc3RhdGljIGJpdHN0cmluZyh2YWx1ZSkge1xuICAgIHJldHVybiBCaXRTdHJpbmcud3JhcCh2YWx1ZSwgeyBcInR5cGVcIjogXCJiaXRzdHJpbmdcIiwgXCJ1bml0XCI6IDEsIFwic2l6ZVwiOiB2YWx1ZS5sZW5ndGggfSk7XG4gIH1cblxuICBzdGF0aWMgYml0cyh2YWx1ZSkge1xuICAgIHJldHVybiBCaXRTdHJpbmcuYml0c3RyaW5nKHZhbHVlKTtcbiAgfVxuXG4gIHN0YXRpYyBiaW5hcnkodmFsdWUpIHtcbiAgICByZXR1cm4gQml0U3RyaW5nLndyYXAodmFsdWUsIHsgXCJ0eXBlXCI6IFwiYmluYXJ5XCIsIFwidW5pdFwiOiA4LCBcInNpemVcIjogdmFsdWUubGVuZ3RoIH0pO1xuICB9XG5cbiAgc3RhdGljIGJ5dGVzKHZhbHVlKSB7XG4gICAgcmV0dXJuIEJpdFN0cmluZy5iaW5hcnkodmFsdWUpO1xuICB9XG5cbiAgc3RhdGljIHV0ZjgodmFsdWUpIHtcbiAgICByZXR1cm4gQml0U3RyaW5nLndyYXAodmFsdWUsIHsgXCJ0eXBlXCI6IFwidXRmOFwiIH0pO1xuICB9XG5cbiAgc3RhdGljIHV0ZjE2KHZhbHVlKSB7XG4gICAgcmV0dXJuIEJpdFN0cmluZy53cmFwKHZhbHVlLCB7IFwidHlwZVwiOiBcInV0ZjE2XCIgfSk7XG4gIH1cblxuICBzdGF0aWMgdXRmMzIodmFsdWUpIHtcbiAgICByZXR1cm4gQml0U3RyaW5nLndyYXAodmFsdWUsIHsgXCJ0eXBlXCI6IFwidXRmMzJcIiB9KTtcbiAgfVxuXG4gIHN0YXRpYyBzaWduZWQodmFsdWUpIHtcbiAgICByZXR1cm4gQml0U3RyaW5nLndyYXAodmFsdWUsIHt9LCBcInNpZ25lZFwiKTtcbiAgfVxuXG4gIHN0YXRpYyB1bnNpZ25lZCh2YWx1ZSkge1xuICAgIHJldHVybiBCaXRTdHJpbmcud3JhcCh2YWx1ZSwge30sIFwidW5zaWduZWRcIik7XG4gIH1cblxuICBzdGF0aWMgbmF0aXZlKHZhbHVlKSB7XG4gICAgcmV0dXJuIEJpdFN0cmluZy53cmFwKHZhbHVlLCB7fSwgXCJuYXRpdmVcIik7XG4gIH1cblxuICBzdGF0aWMgYmlnKHZhbHVlKSB7XG4gICAgcmV0dXJuIEJpdFN0cmluZy53cmFwKHZhbHVlLCB7fSwgXCJiaWdcIik7XG4gIH1cblxuICBzdGF0aWMgbGl0dGxlKHZhbHVlKSB7XG4gICAgcmV0dXJuIEJpdFN0cmluZy53cmFwKHZhbHVlLCB7fSwgXCJsaXR0bGVcIik7XG4gIH1cblxuICBzdGF0aWMgc2l6ZSh2YWx1ZSwgY291bnQpIHtcbiAgICByZXR1cm4gQml0U3RyaW5nLndyYXAodmFsdWUsIHsgXCJzaXplXCI6IGNvdW50IH0pO1xuICB9XG5cbiAgc3RhdGljIHVuaXQodmFsdWUsIGNvdW50KSB7XG4gICAgcmV0dXJuIEJpdFN0cmluZy53cmFwKHZhbHVlLCB7IFwidW5pdFwiOiBjb3VudCB9KTtcbiAgfVxuXG4gIHN0YXRpYyB3cmFwKHZhbHVlLCBvcHQsIG5ld19hdHRyaWJ1dGUgPSBudWxsKSB7XG4gICAgbGV0IHRoZV92YWx1ZSA9IHZhbHVlO1xuXG4gICAgaWYgKCEodmFsdWUgaW5zdGFuY2VvZiBPYmplY3QpKSB7XG4gICAgICB0aGVfdmFsdWUgPSB7IFwidmFsdWVcIjogdmFsdWUsIFwiYXR0cmlidXRlc1wiOiBbXSB9O1xuICAgIH1cblxuICAgIHRoZV92YWx1ZSA9IE9iamVjdC5hc3NpZ24odGhlX3ZhbHVlLCBvcHQpO1xuXG4gICAgaWYgKG5ld19hdHRyaWJ1dGUpIHtcbiAgICAgIHRoZV92YWx1ZS5hdHRyaWJ1dGVzLnB1c2gobmV3X2F0dHJpYnV0ZSk7XG4gICAgfVxuXG4gICAgcmV0dXJuIHRoZV92YWx1ZTtcbiAgfVxuXG4gIHN0YXRpYyB0b1VURjhBcnJheShzdHIpIHtcbiAgICB2YXIgdXRmOCA9IFtdO1xuICAgIGZvciAodmFyIGkgPSAwOyBpIDwgc3RyLmxlbmd0aDsgaSsrKSB7XG4gICAgICB2YXIgY2hhcmNvZGUgPSBzdHIuY2hhckNvZGVBdChpKTtcbiAgICAgIGlmIChjaGFyY29kZSA8IDEyOCkge1xuICAgICAgICB1dGY4LnB1c2goY2hhcmNvZGUpO1xuICAgICAgfSBlbHNlIGlmIChjaGFyY29kZSA8IDIwNDgpIHtcbiAgICAgICAgdXRmOC5wdXNoKDE5MiB8IGNoYXJjb2RlID4+IDYsIDEyOCB8IGNoYXJjb2RlICYgNjMpO1xuICAgICAgfSBlbHNlIGlmIChjaGFyY29kZSA8IDU1Mjk2IHx8IGNoYXJjb2RlID49IDU3MzQ0KSB7XG4gICAgICAgIHV0ZjgucHVzaCgyMjQgfCBjaGFyY29kZSA+PiAxMiwgMTI4IHwgY2hhcmNvZGUgPj4gNiAmIDYzLCAxMjggfCBjaGFyY29kZSAmIDYzKTtcbiAgICAgIH1cbiAgICAgIC8vIHN1cnJvZ2F0ZSBwYWlyXG4gICAgICBlbHNlIHtcbiAgICAgICAgaSsrO1xuICAgICAgICAvLyBVVEYtMTYgZW5jb2RlcyAweDEwMDAwLTB4MTBGRkZGIGJ5XG4gICAgICAgIC8vIHN1YnRyYWN0aW5nIDB4MTAwMDAgYW5kIHNwbGl0dGluZyB0aGVcbiAgICAgICAgLy8gMjAgYml0cyBvZiAweDAtMHhGRkZGRiBpbnRvIHR3byBoYWx2ZXNcbiAgICAgICAgY2hhcmNvZGUgPSA2NTUzNiArICgoY2hhcmNvZGUgJiAxMDIzKSA8PCAxMCB8IHN0ci5jaGFyQ29kZUF0KGkpICYgMTAyMyk7XG4gICAgICAgIHV0ZjgucHVzaCgyNDAgfCBjaGFyY29kZSA+PiAxOCwgMTI4IHwgY2hhcmNvZGUgPj4gMTIgJiA2MywgMTI4IHwgY2hhcmNvZGUgPj4gNiAmIDYzLCAxMjggfCBjaGFyY29kZSAmIDYzKTtcbiAgICAgIH1cbiAgICB9XG4gICAgcmV0dXJuIHV0Zjg7XG4gIH1cblxuICBzdGF0aWMgdG9VVEYxNkFycmF5KHN0cikge1xuICAgIHZhciB1dGYxNiA9IFtdO1xuICAgIGZvciAodmFyIGkgPSAwOyBpIDwgc3RyLmxlbmd0aDsgaSsrKSB7XG4gICAgICB2YXIgY29kZVBvaW50ID0gc3RyLmNvZGVQb2ludEF0KGkpO1xuXG4gICAgICBpZiAoY29kZVBvaW50IDw9IDI1NSkge1xuICAgICAgICB1dGYxNi5wdXNoKDApO1xuICAgICAgICB1dGYxNi5wdXNoKGNvZGVQb2ludCk7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICB1dGYxNi5wdXNoKGNvZGVQb2ludCA+PiA4ICYgMjU1KTtcbiAgICAgICAgdXRmMTYucHVzaChjb2RlUG9pbnQgJiAyNTUpO1xuICAgICAgfVxuICAgIH1cbiAgICByZXR1cm4gdXRmMTY7XG4gIH1cblxuICBzdGF0aWMgdG9VVEYzMkFycmF5KHN0cikge1xuICAgIHZhciB1dGYzMiA9IFtdO1xuICAgIGZvciAodmFyIGkgPSAwOyBpIDwgc3RyLmxlbmd0aDsgaSsrKSB7XG4gICAgICB2YXIgY29kZVBvaW50ID0gc3RyLmNvZGVQb2ludEF0KGkpO1xuXG4gICAgICBpZiAoY29kZVBvaW50IDw9IDI1NSkge1xuICAgICAgICB1dGYzMi5wdXNoKDApO1xuICAgICAgICB1dGYzMi5wdXNoKDApO1xuICAgICAgICB1dGYzMi5wdXNoKDApO1xuICAgICAgICB1dGYzMi5wdXNoKGNvZGVQb2ludCk7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICB1dGYzMi5wdXNoKDApO1xuICAgICAgICB1dGYzMi5wdXNoKDApO1xuICAgICAgICB1dGYzMi5wdXNoKGNvZGVQb2ludCA+PiA4ICYgMjU1KTtcbiAgICAgICAgdXRmMzIucHVzaChjb2RlUG9pbnQgJiAyNTUpO1xuICAgICAgfVxuICAgIH1cbiAgICByZXR1cm4gdXRmMzI7XG4gIH1cblxuICAvL2h0dHA6Ly9zdGFja292ZXJmbG93LmNvbS9xdWVzdGlvbnMvMjAwMzQ5My9qYXZhc2NyaXB0LWZsb2F0LWZyb20tdG8tYml0c1xuICBzdGF0aWMgZmxvYXQzMlRvQnl0ZXMoZikge1xuICAgIHZhciBieXRlcyA9IFtdO1xuXG4gICAgdmFyIGJ1ZiA9IG5ldyBBcnJheUJ1ZmZlcig0KTtcbiAgICBuZXcgRmxvYXQzMkFycmF5KGJ1ZilbMF0gPSBmO1xuXG4gICAgbGV0IGludFZlcnNpb24gPSBuZXcgVWludDMyQXJyYXkoYnVmKVswXTtcblxuICAgIGJ5dGVzLnB1c2goaW50VmVyc2lvbiA+PiAyNCAmIDI1NSk7XG4gICAgYnl0ZXMucHVzaChpbnRWZXJzaW9uID4+IDE2ICYgMjU1KTtcbiAgICBieXRlcy5wdXNoKGludFZlcnNpb24gPj4gOCAmIDI1NSk7XG4gICAgYnl0ZXMucHVzaChpbnRWZXJzaW9uICYgMjU1KTtcblxuICAgIHJldHVybiBieXRlcztcbiAgfVxuXG4gIHN0YXRpYyBmbG9hdDY0VG9CeXRlcyhmKSB7XG4gICAgdmFyIGJ5dGVzID0gW107XG5cbiAgICB2YXIgYnVmID0gbmV3IEFycmF5QnVmZmVyKDgpO1xuICAgIG5ldyBGbG9hdDY0QXJyYXkoYnVmKVswXSA9IGY7XG5cbiAgICB2YXIgaW50VmVyc2lvbjEgPSBuZXcgVWludDMyQXJyYXkoYnVmKVswXTtcbiAgICB2YXIgaW50VmVyc2lvbjIgPSBuZXcgVWludDMyQXJyYXkoYnVmKVsxXTtcblxuICAgIGJ5dGVzLnB1c2goaW50VmVyc2lvbjIgPj4gMjQgJiAyNTUpO1xuICAgIGJ5dGVzLnB1c2goaW50VmVyc2lvbjIgPj4gMTYgJiAyNTUpO1xuICAgIGJ5dGVzLnB1c2goaW50VmVyc2lvbjIgPj4gOCAmIDI1NSk7XG4gICAgYnl0ZXMucHVzaChpbnRWZXJzaW9uMiAmIDI1NSk7XG5cbiAgICBieXRlcy5wdXNoKGludFZlcnNpb24xID4+IDI0ICYgMjU1KTtcbiAgICBieXRlcy5wdXNoKGludFZlcnNpb24xID4+IDE2ICYgMjU1KTtcbiAgICBieXRlcy5wdXNoKGludFZlcnNpb24xID4+IDggJiAyNTUpO1xuICAgIGJ5dGVzLnB1c2goaW50VmVyc2lvbjEgJiAyNTUpO1xuXG4gICAgcmV0dXJuIGJ5dGVzO1xuICB9XG59XG5cbi8qIEBmbG93ICovXG5cbmNsYXNzIFZhcmlhYmxlIHtcblxuICBjb25zdHJ1Y3RvcihuYW1lID0gbnVsbCkge1xuICAgIHRoaXMubmFtZSA9IG5hbWU7XG4gIH1cbn1cblxuY2xhc3MgV2lsZGNhcmQge1xuICBjb25zdHJ1Y3RvcigpIHt9XG59XG5cbmNsYXNzIFN0YXJ0c1dpdGgge1xuXG4gIGNvbnN0cnVjdG9yKHByZWZpeCkge1xuICAgIHRoaXMucHJlZml4ID0gcHJlZml4O1xuICB9XG59XG5cbmNsYXNzIENhcHR1cmUge1xuXG4gIGNvbnN0cnVjdG9yKHZhbHVlKSB7XG4gICAgdGhpcy52YWx1ZSA9IHZhbHVlO1xuICB9XG59XG5cbmNsYXNzIEhlYWRUYWlsIHtcbiAgY29uc3RydWN0b3IoKSB7fVxufVxuXG5jbGFzcyBUeXBlIHtcblxuICBjb25zdHJ1Y3Rvcih0eXBlLCBvYmpQYXR0ZXJuID0ge30pIHtcbiAgICB0aGlzLnR5cGUgPSB0eXBlO1xuICAgIHRoaXMub2JqUGF0dGVybiA9IG9ialBhdHRlcm47XG4gIH1cbn1cblxuY2xhc3MgQm91bmQge1xuXG4gIGNvbnN0cnVjdG9yKHZhbHVlKSB7XG4gICAgdGhpcy52YWx1ZSA9IHZhbHVlO1xuICB9XG59XG5cbmZ1bmN0aW9uIHZhcmlhYmxlKG5hbWUgPSBudWxsKSB7XG4gIHJldHVybiBuZXcgVmFyaWFibGUobmFtZSk7XG59XG5cbmZ1bmN0aW9uIHdpbGRjYXJkKCkge1xuICByZXR1cm4gbmV3IFdpbGRjYXJkKCk7XG59XG5cbmZ1bmN0aW9uIHN0YXJ0c1dpdGgocHJlZml4KSB7XG4gIHJldHVybiBuZXcgU3RhcnRzV2l0aChwcmVmaXgpO1xufVxuXG5mdW5jdGlvbiBjYXB0dXJlKHZhbHVlKSB7XG4gIHJldHVybiBuZXcgQ2FwdHVyZSh2YWx1ZSk7XG59XG5cbmZ1bmN0aW9uIGhlYWRUYWlsKCkge1xuICByZXR1cm4gbmV3IEhlYWRUYWlsKCk7XG59XG5cbmZ1bmN0aW9uIHR5cGUodHlwZSwgb2JqUGF0dGVybiA9IHt9KSB7XG4gIHJldHVybiBuZXcgVHlwZSh0eXBlLCBvYmpQYXR0ZXJuKTtcbn1cblxuZnVuY3Rpb24gYm91bmQodmFsdWUpIHtcbiAgcmV0dXJuIG5ldyBCb3VuZCh2YWx1ZSk7XG59XG5cbmZ1bmN0aW9uIGlzX251bWJlcih2YWx1ZSkge1xuICByZXR1cm4gdHlwZW9mIHZhbHVlID09PSAnbnVtYmVyJztcbn1cblxuZnVuY3Rpb24gaXNfc3RyaW5nKHZhbHVlKSB7XG4gIHJldHVybiB0eXBlb2YgdmFsdWUgPT09ICdzdHJpbmcnO1xufVxuXG5mdW5jdGlvbiBpc19ib29sZWFuKHZhbHVlKSB7XG4gIHJldHVybiB0eXBlb2YgdmFsdWUgPT09ICdib29sZWFuJztcbn1cblxuZnVuY3Rpb24gaXNfc3ltYm9sKHZhbHVlKSB7XG4gIHJldHVybiB0eXBlb2YgdmFsdWUgPT09ICdzeW1ib2wnO1xufVxuXG5mdW5jdGlvbiBpc19udWxsKHZhbHVlKSB7XG4gIHJldHVybiB2YWx1ZSA9PT0gbnVsbDtcbn1cblxuZnVuY3Rpb24gaXNfdW5kZWZpbmVkKHZhbHVlKSB7XG4gIHJldHVybiB0eXBlb2YgdmFsdWUgPT09ICd1bmRlZmluZWQnO1xufVxuXG5mdW5jdGlvbiBpc19mdW5jdGlvbih2YWx1ZSkge1xuICByZXR1cm4gT2JqZWN0LnByb3RvdHlwZS50b1N0cmluZy5jYWxsKHZhbHVlKSA9PSAnW29iamVjdCBGdW5jdGlvbl0nO1xufVxuXG5mdW5jdGlvbiBpc192YXJpYWJsZSh2YWx1ZSkge1xuICByZXR1cm4gdmFsdWUgaW5zdGFuY2VvZiBWYXJpYWJsZTtcbn1cblxuZnVuY3Rpb24gaXNfd2lsZGNhcmQodmFsdWUpIHtcbiAgcmV0dXJuIHZhbHVlIGluc3RhbmNlb2YgV2lsZGNhcmQ7XG59XG5cbmZ1bmN0aW9uIGlzX2hlYWRUYWlsKHZhbHVlKSB7XG4gIHJldHVybiB2YWx1ZSBpbnN0YW5jZW9mIEhlYWRUYWlsO1xufVxuXG5mdW5jdGlvbiBpc19jYXB0dXJlKHZhbHVlKSB7XG4gIHJldHVybiB2YWx1ZSBpbnN0YW5jZW9mIENhcHR1cmU7XG59XG5cbmZ1bmN0aW9uIGlzX3R5cGUodmFsdWUpIHtcbiAgcmV0dXJuIHZhbHVlIGluc3RhbmNlb2YgVHlwZTtcbn1cblxuZnVuY3Rpb24gaXNfc3RhcnRzV2l0aCh2YWx1ZSkge1xuICByZXR1cm4gdmFsdWUgaW5zdGFuY2VvZiBTdGFydHNXaXRoO1xufVxuXG5mdW5jdGlvbiBpc19ib3VuZCh2YWx1ZSkge1xuICByZXR1cm4gdmFsdWUgaW5zdGFuY2VvZiBCb3VuZDtcbn1cblxuZnVuY3Rpb24gaXNfb2JqZWN0KHZhbHVlKSB7XG4gIHJldHVybiB0eXBlb2YgdmFsdWUgPT09ICdvYmplY3QnO1xufVxuXG5mdW5jdGlvbiBpc19hcnJheSh2YWx1ZSkge1xuICByZXR1cm4gQXJyYXkuaXNBcnJheSh2YWx1ZSk7XG59XG5cbnZhciBDaGVja3MgPSB7XG4gIGlzX251bWJlcixcbiAgaXNfc3RyaW5nLFxuICBpc19ib29sZWFuLFxuICBpc19zeW1ib2wsXG4gIGlzX251bGwsXG4gIGlzX3VuZGVmaW5lZCxcbiAgaXNfZnVuY3Rpb24sXG4gIGlzX3ZhcmlhYmxlLFxuICBpc193aWxkY2FyZCxcbiAgaXNfaGVhZFRhaWwsXG4gIGlzX2NhcHR1cmUsXG4gIGlzX3R5cGUsXG4gIGlzX3N0YXJ0c1dpdGgsXG4gIGlzX2JvdW5kLFxuICBpc19vYmplY3QsXG4gIGlzX2FycmF5XG59O1xuXG5mdW5jdGlvbiByZXNvbHZlU3ltYm9sKHBhdHRlcm4pIHtcbiAgcmV0dXJuIGZ1bmN0aW9uICh2YWx1ZSkge1xuICAgIHJldHVybiBDaGVja3MuaXNfc3ltYm9sKHZhbHVlKSAmJiB2YWx1ZSA9PT0gcGF0dGVybjtcbiAgfTtcbn1cblxuZnVuY3Rpb24gcmVzb2x2ZVN0cmluZyhwYXR0ZXJuKSB7XG4gIHJldHVybiBmdW5jdGlvbiAodmFsdWUpIHtcbiAgICByZXR1cm4gQ2hlY2tzLmlzX3N0cmluZyh2YWx1ZSkgJiYgdmFsdWUgPT09IHBhdHRlcm47XG4gIH07XG59XG5cbmZ1bmN0aW9uIHJlc29sdmVOdW1iZXIocGF0dGVybikge1xuICByZXR1cm4gZnVuY3Rpb24gKHZhbHVlKSB7XG4gICAgcmV0dXJuIENoZWNrcy5pc19udW1iZXIodmFsdWUpICYmIHZhbHVlID09PSBwYXR0ZXJuO1xuICB9O1xufVxuXG5mdW5jdGlvbiByZXNvbHZlQm9vbGVhbihwYXR0ZXJuKSB7XG4gIHJldHVybiBmdW5jdGlvbiAodmFsdWUpIHtcbiAgICByZXR1cm4gQ2hlY2tzLmlzX2Jvb2xlYW4odmFsdWUpICYmIHZhbHVlID09PSBwYXR0ZXJuO1xuICB9O1xufVxuXG5mdW5jdGlvbiByZXNvbHZlRnVuY3Rpb24ocGF0dGVybikge1xuICByZXR1cm4gZnVuY3Rpb24gKHZhbHVlKSB7XG4gICAgcmV0dXJuIENoZWNrcy5pc19mdW5jdGlvbih2YWx1ZSkgJiYgdmFsdWUgPT09IHBhdHRlcm47XG4gIH07XG59XG5cbmZ1bmN0aW9uIHJlc29sdmVOdWxsKHBhdHRlcm4pIHtcbiAgcmV0dXJuIGZ1bmN0aW9uICh2YWx1ZSkge1xuICAgIHJldHVybiBDaGVja3MuaXNfbnVsbCh2YWx1ZSk7XG4gIH07XG59XG5cbmZ1bmN0aW9uIHJlc29sdmVCb3VuZChwYXR0ZXJuKSB7XG4gIHJldHVybiBmdW5jdGlvbiAodmFsdWUsIGFyZ3MpIHtcbiAgICBpZiAodHlwZW9mIHZhbHVlID09PSB0eXBlb2YgcGF0dGVybi52YWx1ZSAmJiB2YWx1ZSA9PT0gcGF0dGVybi52YWx1ZSkge1xuICAgICAgYXJncy5wdXNoKHZhbHVlKTtcbiAgICAgIHJldHVybiB0cnVlO1xuICAgIH1cblxuICAgIHJldHVybiBmYWxzZTtcbiAgfTtcbn1cblxuZnVuY3Rpb24gcmVzb2x2ZVdpbGRjYXJkKCkge1xuICByZXR1cm4gZnVuY3Rpb24gKCkge1xuICAgIHJldHVybiB0cnVlO1xuICB9O1xufVxuXG5mdW5jdGlvbiByZXNvbHZlVmFyaWFibGUoKSB7XG4gIHJldHVybiBmdW5jdGlvbiAodmFsdWUsIGFyZ3MpIHtcbiAgICBhcmdzLnB1c2godmFsdWUpO1xuICAgIHJldHVybiB0cnVlO1xuICB9O1xufVxuXG5mdW5jdGlvbiByZXNvbHZlSGVhZFRhaWwoKSB7XG4gIHJldHVybiBmdW5jdGlvbiAodmFsdWUsIGFyZ3MpIHtcbiAgICBpZiAoIUNoZWNrcy5pc19hcnJheSh2YWx1ZSkgfHwgdmFsdWUubGVuZ3RoIDwgMikge1xuICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH1cblxuICAgIGNvbnN0IGhlYWQgPSB2YWx1ZVswXTtcbiAgICBjb25zdCB0YWlsID0gdmFsdWUuc2xpY2UoMSk7XG5cbiAgICBhcmdzLnB1c2goaGVhZCk7XG4gICAgYXJncy5wdXNoKHRhaWwpO1xuXG4gICAgcmV0dXJuIHRydWU7XG4gIH07XG59XG5cbmZ1bmN0aW9uIHJlc29sdmVDYXB0dXJlKHBhdHRlcm4pIHtcbiAgY29uc3QgbWF0Y2hlcyA9IGJ1aWxkTWF0Y2gocGF0dGVybi52YWx1ZSk7XG5cbiAgcmV0dXJuIGZ1bmN0aW9uICh2YWx1ZSwgYXJncykge1xuICAgIGlmIChtYXRjaGVzKHZhbHVlLCBhcmdzKSkge1xuICAgICAgYXJncy5wdXNoKHZhbHVlKTtcbiAgICAgIHJldHVybiB0cnVlO1xuICAgIH1cblxuICAgIHJldHVybiBmYWxzZTtcbiAgfTtcbn1cblxuZnVuY3Rpb24gcmVzb2x2ZVN0YXJ0c1dpdGgocGF0dGVybikge1xuICBjb25zdCBwcmVmaXggPSBwYXR0ZXJuLnByZWZpeDtcblxuICByZXR1cm4gZnVuY3Rpb24gKHZhbHVlLCBhcmdzKSB7XG4gICAgaWYgKENoZWNrcy5pc19zdHJpbmcodmFsdWUpICYmIHZhbHVlLnN0YXJ0c1dpdGgocHJlZml4KSkge1xuICAgICAgYXJncy5wdXNoKHZhbHVlLnN1YnN0cmluZyhwcmVmaXgubGVuZ3RoKSk7XG4gICAgICByZXR1cm4gdHJ1ZTtcbiAgICB9XG5cbiAgICByZXR1cm4gZmFsc2U7XG4gIH07XG59XG5cbmZ1bmN0aW9uIHJlc29sdmVUeXBlKHBhdHRlcm4pIHtcbiAgcmV0dXJuIGZ1bmN0aW9uICh2YWx1ZSwgYXJncykge1xuICAgIGlmICh2YWx1ZSBpbnN0YW5jZW9mIHBhdHRlcm4udHlwZSkge1xuICAgICAgY29uc3QgbWF0Y2hlcyA9IGJ1aWxkTWF0Y2gocGF0dGVybi5vYmpQYXR0ZXJuKTtcbiAgICAgIHJldHVybiBtYXRjaGVzKHZhbHVlLCBhcmdzKSAmJiBhcmdzLnB1c2godmFsdWUpID4gMDtcbiAgICB9XG5cbiAgICByZXR1cm4gZmFsc2U7XG4gIH07XG59XG5cbmZ1bmN0aW9uIHJlc29sdmVBcnJheShwYXR0ZXJuKSB7XG4gIGNvbnN0IG1hdGNoZXMgPSBwYXR0ZXJuLm1hcCh4ID0+IGJ1aWxkTWF0Y2goeCkpO1xuXG4gIHJldHVybiBmdW5jdGlvbiAodmFsdWUsIGFyZ3MpIHtcbiAgICBpZiAoIUNoZWNrcy5pc19hcnJheSh2YWx1ZSkgfHwgdmFsdWUubGVuZ3RoICE9IHBhdHRlcm4ubGVuZ3RoKSB7XG4gICAgICByZXR1cm4gZmFsc2U7XG4gICAgfVxuXG4gICAgcmV0dXJuIHZhbHVlLmV2ZXJ5KGZ1bmN0aW9uICh2LCBpKSB7XG4gICAgICByZXR1cm4gbWF0Y2hlc1tpXSh2YWx1ZVtpXSwgYXJncyk7XG4gICAgfSk7XG4gIH07XG59XG5cbmZ1bmN0aW9uIHJlc29sdmVPYmplY3QocGF0dGVybikge1xuICBsZXQgbWF0Y2hlcyA9IHt9O1xuXG4gIGZvciAobGV0IGtleSBvZiBPYmplY3Qua2V5cyhwYXR0ZXJuKS5jb25jYXQoT2JqZWN0LmdldE93blByb3BlcnR5U3ltYm9scyhwYXR0ZXJuKSkpIHtcbiAgICBtYXRjaGVzW2tleV0gPSBidWlsZE1hdGNoKHBhdHRlcm5ba2V5XSk7XG4gIH1cblxuICByZXR1cm4gZnVuY3Rpb24gKHZhbHVlLCBhcmdzKSB7XG4gICAgaWYgKCFDaGVja3MuaXNfb2JqZWN0KHZhbHVlKSB8fCBwYXR0ZXJuLmxlbmd0aCA+IHZhbHVlLmxlbmd0aCkge1xuICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH1cblxuICAgIGZvciAobGV0IGtleSBvZiBPYmplY3Qua2V5cyhwYXR0ZXJuKS5jb25jYXQoT2JqZWN0LmdldE93blByb3BlcnR5U3ltYm9scyhwYXR0ZXJuKSkpIHtcbiAgICAgIGlmICghKGtleSBpbiB2YWx1ZSkgfHwgIW1hdGNoZXNba2V5XSh2YWx1ZVtrZXldLCBhcmdzKSkge1xuICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICB9XG4gICAgfVxuXG4gICAgcmV0dXJuIHRydWU7XG4gIH07XG59XG5cbmZ1bmN0aW9uIHJlc29sdmVOb01hdGNoKCkge1xuICByZXR1cm4gZnVuY3Rpb24gKCkge1xuICAgIHJldHVybiBmYWxzZTtcbiAgfTtcbn1cblxudmFyIFJlc29sdmVycyA9IHtcbiAgcmVzb2x2ZUJvdW5kLFxuICByZXNvbHZlV2lsZGNhcmQsXG4gIHJlc29sdmVWYXJpYWJsZSxcbiAgcmVzb2x2ZUhlYWRUYWlsLFxuICByZXNvbHZlQ2FwdHVyZSxcbiAgcmVzb2x2ZVN0YXJ0c1dpdGgsXG4gIHJlc29sdmVUeXBlLFxuICByZXNvbHZlQXJyYXksXG4gIHJlc29sdmVPYmplY3QsXG4gIHJlc29sdmVOb01hdGNoLFxuICByZXNvbHZlU3ltYm9sLFxuICByZXNvbHZlU3RyaW5nLFxuICByZXNvbHZlTnVtYmVyLFxuICByZXNvbHZlQm9vbGVhbixcbiAgcmVzb2x2ZUZ1bmN0aW9uLFxuICByZXNvbHZlTnVsbFxufTtcblxuZnVuY3Rpb24gYnVpbGRNYXRjaChwYXR0ZXJuKSB7XG5cbiAgaWYgKENoZWNrcy5pc192YXJpYWJsZShwYXR0ZXJuKSkge1xuICAgIHJldHVybiBSZXNvbHZlcnMucmVzb2x2ZVZhcmlhYmxlKHBhdHRlcm4pO1xuICB9XG5cbiAgaWYgKENoZWNrcy5pc193aWxkY2FyZChwYXR0ZXJuKSkge1xuICAgIHJldHVybiBSZXNvbHZlcnMucmVzb2x2ZVdpbGRjYXJkKHBhdHRlcm4pO1xuICB9XG5cbiAgaWYgKENoZWNrcy5pc191bmRlZmluZWQocGF0dGVybikpIHtcbiAgICByZXR1cm4gUmVzb2x2ZXJzLnJlc29sdmVXaWxkY2FyZChwYXR0ZXJuKTtcbiAgfVxuXG4gIGlmIChDaGVja3MuaXNfaGVhZFRhaWwocGF0dGVybikpIHtcbiAgICByZXR1cm4gUmVzb2x2ZXJzLnJlc29sdmVIZWFkVGFpbChwYXR0ZXJuKTtcbiAgfVxuXG4gIGlmIChDaGVja3MuaXNfc3RhcnRzV2l0aChwYXR0ZXJuKSkge1xuICAgIHJldHVybiBSZXNvbHZlcnMucmVzb2x2ZVN0YXJ0c1dpdGgocGF0dGVybik7XG4gIH1cblxuICBpZiAoQ2hlY2tzLmlzX2NhcHR1cmUocGF0dGVybikpIHtcbiAgICByZXR1cm4gUmVzb2x2ZXJzLnJlc29sdmVDYXB0dXJlKHBhdHRlcm4pO1xuICB9XG5cbiAgaWYgKENoZWNrcy5pc19ib3VuZChwYXR0ZXJuKSkge1xuICAgIHJldHVybiBSZXNvbHZlcnMucmVzb2x2ZUJvdW5kKHBhdHRlcm4pO1xuICB9XG5cbiAgaWYgKENoZWNrcy5pc190eXBlKHBhdHRlcm4pKSB7XG4gICAgcmV0dXJuIFJlc29sdmVycy5yZXNvbHZlVHlwZShwYXR0ZXJuKTtcbiAgfVxuXG4gIGlmIChDaGVja3MuaXNfYXJyYXkocGF0dGVybikpIHtcbiAgICByZXR1cm4gUmVzb2x2ZXJzLnJlc29sdmVBcnJheShwYXR0ZXJuKTtcbiAgfVxuXG4gIGlmIChDaGVja3MuaXNfbnVtYmVyKHBhdHRlcm4pKSB7XG4gICAgcmV0dXJuIFJlc29sdmVycy5yZXNvbHZlTnVtYmVyKHBhdHRlcm4pO1xuICB9XG5cbiAgaWYgKENoZWNrcy5pc19zdHJpbmcocGF0dGVybikpIHtcbiAgICByZXR1cm4gUmVzb2x2ZXJzLnJlc29sdmVTdHJpbmcocGF0dGVybik7XG4gIH1cblxuICBpZiAoQ2hlY2tzLmlzX2Jvb2xlYW4ocGF0dGVybikpIHtcbiAgICByZXR1cm4gUmVzb2x2ZXJzLnJlc29sdmVCb29sZWFuKHBhdHRlcm4pO1xuICB9XG5cbiAgaWYgKENoZWNrcy5pc19zeW1ib2wocGF0dGVybikpIHtcbiAgICByZXR1cm4gUmVzb2x2ZXJzLnJlc29sdmVTeW1ib2wocGF0dGVybik7XG4gIH1cblxuICBpZiAoQ2hlY2tzLmlzX251bGwocGF0dGVybikpIHtcbiAgICByZXR1cm4gUmVzb2x2ZXJzLnJlc29sdmVOdWxsKHBhdHRlcm4pO1xuICB9XG5cbiAgaWYgKENoZWNrcy5pc19vYmplY3QocGF0dGVybikpIHtcbiAgICByZXR1cm4gUmVzb2x2ZXJzLnJlc29sdmVPYmplY3QocGF0dGVybik7XG4gIH1cblxuICByZXR1cm4gUmVzb2x2ZXJzLnJlc29sdmVOb01hdGNoKCk7XG59XG5cbmNsYXNzIE1hdGNoRXJyb3IgZXh0ZW5kcyBFcnJvciB7XG4gIGNvbnN0cnVjdG9yKGFyZykge1xuICAgIHN1cGVyKCk7XG5cbiAgICBpZiAodHlwZW9mIGFyZyA9PT0gJ3N5bWJvbCcpIHtcbiAgICAgIHRoaXMubWVzc2FnZSA9ICdObyBtYXRjaCBmb3I6ICcgKyBhcmcudG9TdHJpbmcoKTtcbiAgICB9IGVsc2UgaWYgKEFycmF5LmlzQXJyYXkoYXJnKSkge1xuICAgICAgbGV0IG1hcHBlZFZhbHVlcyA9IGFyZy5tYXAoeCA9PiB4LnRvU3RyaW5nKCkpO1xuICAgICAgdGhpcy5tZXNzYWdlID0gJ05vIG1hdGNoIGZvcjogJyArIG1hcHBlZFZhbHVlcztcbiAgICB9IGVsc2Uge1xuICAgICAgdGhpcy5tZXNzYWdlID0gJ05vIG1hdGNoIGZvcjogJyArIGFyZztcbiAgICB9XG5cbiAgICB0aGlzLnN0YWNrID0gbmV3IEVycm9yKCkuc3RhY2s7XG4gICAgdGhpcy5uYW1lID0gdGhpcy5jb25zdHJ1Y3Rvci5uYW1lO1xuICB9XG59XG5cbmNsYXNzIENhc2Uge1xuXG4gIGNvbnN0cnVjdG9yKHBhdHRlcm4sIGZuLCBndWFyZCA9ICgpID0+IHRydWUpIHtcbiAgICB0aGlzLnBhdHRlcm4gPSBidWlsZE1hdGNoKHBhdHRlcm4pO1xuICAgIHRoaXMuZm4gPSBmbjtcbiAgICB0aGlzLmd1YXJkID0gZ3VhcmQ7XG4gIH1cbn1cblxuZnVuY3Rpb24gbWFrZV9jYXNlKHBhdHRlcm4sIGZuLCBndWFyZCA9ICgpID0+IHRydWUpIHtcbiAgcmV0dXJuIG5ldyBDYXNlKHBhdHRlcm4sIGZuLCBndWFyZCk7XG59XG5cbmZ1bmN0aW9uIGRlZm1hdGNoKC4uLmNhc2VzKSB7XG4gIHJldHVybiBmdW5jdGlvbiAoLi4uYXJncykge1xuICAgIGZvciAobGV0IHByb2Nlc3NlZENhc2Ugb2YgY2FzZXMpIHtcbiAgICAgIGxldCByZXN1bHQgPSBbXTtcbiAgICAgIGlmIChwcm9jZXNzZWRDYXNlLnBhdHRlcm4oYXJncywgcmVzdWx0KSAmJiBwcm9jZXNzZWRDYXNlLmd1YXJkLmFwcGx5KHRoaXMsIHJlc3VsdCkpIHtcbiAgICAgICAgcmV0dXJuIHByb2Nlc3NlZENhc2UuZm4uYXBwbHkodGhpcywgcmVzdWx0KTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICB0aHJvdyBuZXcgTWF0Y2hFcnJvcihhcmdzKTtcbiAgfTtcbn1cblxuZnVuY3Rpb24gbWF0Y2gocGF0dGVybiwgZXhwciwgZ3VhcmQgPSAoKSA9PiB0cnVlKSB7XG4gIGxldCByZXN1bHQgPSBbXTtcbiAgbGV0IHByb2Nlc3NlZFBhdHRlcm4gPSBidWlsZE1hdGNoKHBhdHRlcm4pO1xuICBpZiAocHJvY2Vzc2VkUGF0dGVybihleHByLCByZXN1bHQpICYmIGd1YXJkLmFwcGx5KHRoaXMsIHJlc3VsdCkpIHtcbiAgICByZXR1cm4gcmVzdWx0O1xuICB9IGVsc2Uge1xuICAgIHRocm93IG5ldyBNYXRjaEVycm9yKGV4cHIpO1xuICB9XG59XG5cbmZ1bmN0aW9uIG1hdGNoX25vX3Rocm93KHBhdHRlcm4sIGV4cHIsIGd1YXJkID0gKCkgPT4gdHJ1ZSkge1xuICB0cnkge1xuICAgIHJldHVybiBtYXRjaChwYXR0ZXJuLCBleHByLCBndWFyZCk7XG4gIH0gY2F0Y2ggKGUpIHtcbiAgICBpZiAoZSBpbnN0YW5jZW9mIE1hdGNoRXJyb3IpIHtcbiAgICAgIHJldHVybiBudWxsO1xuICAgIH1cblxuICAgIHRocm93IGU7XG4gIH1cbn1cblxudmFyIFBhdHRlcm5zID0ge1xuICBkZWZtYXRjaCwgbWF0Y2gsIE1hdGNoRXJyb3IsIG1hdGNoX25vX3Rocm93LFxuICB2YXJpYWJsZSwgd2lsZGNhcmQsIHN0YXJ0c1dpdGgsXG4gIGNhcHR1cmUsIGhlYWRUYWlsLCB0eXBlLCBib3VuZCwgQ2FzZSwgbWFrZV9jYXNlXG59O1xuXG4vL2h0dHBzOi8vZ2l0aHViLmNvbS9haXJwb3J0eWgvcHJvdG9tb3JwaGlzbVxuY2xhc3MgUHJvdG9jb2wge1xuICBjb25zdHJ1Y3RvcihzcGVjKSB7XG4gICAgdGhpcy5yZWdpc3RyeSA9IG5ldyBNYXAoKTtcbiAgICB0aGlzLmZhbGxiYWNrID0gbnVsbDtcblxuICAgIGZvciAobGV0IGZ1bk5hbWUgaW4gc3BlYykge1xuICAgICAgdGhpc1tmdW5OYW1lXSA9IGNyZWF0ZUZ1bihmdW5OYW1lKS5iaW5kKHRoaXMpO1xuICAgIH1cblxuICAgIGZ1bmN0aW9uIGNyZWF0ZUZ1bihmdW5OYW1lKSB7XG5cbiAgICAgIHJldHVybiBmdW5jdGlvbiAoLi4uYXJncykge1xuICAgICAgICBsZXQgdGhpbmcgPSBhcmdzWzBdO1xuICAgICAgICBsZXQgZnVuID0gbnVsbDtcblxuICAgICAgICBpZiAoTnVtYmVyLmlzSW50ZWdlcih0aGluZykgJiYgdGhpcy5oYXNJbXBsZW1lbnRhdGlvbihJbnRlZ2VyKSkge1xuICAgICAgICAgIGZ1biA9IHRoaXMucmVnaXN0cnkuZ2V0KENvcmUuSW50ZWdlcilbZnVuTmFtZV07XG4gICAgICAgIH0gZWxzZSBpZiAodHlwZW9mIHRoaW5nID09PSBcIm51bWJlclwiICYmICFOdW1iZXIuaXNJbnRlZ2VyKHRoaW5nKSAmJiB0aGlzLmhhc0ltcGxlbWVudGF0aW9uKEZsb2F0KSkge1xuICAgICAgICAgIGZ1biA9IHRoaXMucmVnaXN0cnkuZ2V0KENvcmUuRmxvYXQpW2Z1bk5hbWVdO1xuICAgICAgICB9IGVsc2UgaWYgKHRoaXMuaGFzSW1wbGVtZW50YXRpb24odGhpbmcpKSB7XG4gICAgICAgICAgZnVuID0gdGhpcy5yZWdpc3RyeS5nZXQodGhpbmcuY29uc3RydWN0b3IpW2Z1bk5hbWVdO1xuICAgICAgICB9IGVsc2UgaWYgKHRoaXMuZmFsbGJhY2spIHtcbiAgICAgICAgICBmdW4gPSB0aGlzLmZhbGxiYWNrW2Z1bk5hbWVdO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKGZ1biAhPSBudWxsKSB7XG4gICAgICAgICAgbGV0IHJldHZhbCA9IGZ1bi5hcHBseSh0aGlzLCBhcmdzKTtcbiAgICAgICAgICByZXR1cm4gcmV0dmFsO1xuICAgICAgICB9XG5cbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKFwiTm8gaW1wbGVtZW50YXRpb24gZm91bmQgZm9yIFwiICsgdGhpbmcpO1xuICAgICAgfTtcbiAgICB9XG4gIH1cblxuICBpbXBsZW1lbnRhdGlvbih0eXBlLCBpbXBsZW1lbnRhdGlvbikge1xuICAgIGlmICh0eXBlID09PSBudWxsKSB7XG4gICAgICB0aGlzLmZhbGxiYWNrID0gaW1wbGVtZW50YXRpb247XG4gICAgfSBlbHNlIHtcbiAgICAgIHRoaXMucmVnaXN0cnkuc2V0KHR5cGUsIGltcGxlbWVudGF0aW9uKTtcbiAgICB9XG4gIH1cblxuICBoYXNJbXBsZW1lbnRhdGlvbih0aGluZykge1xuICAgIHJldHVybiB0aGlzLnJlZ2lzdHJ5Lmhhcyh0aGluZy5jb25zdHJ1Y3Rvcik7XG4gIH1cbn1cblxuZnVuY3Rpb24gY2FsbF9wcm9wZXJ0eShpdGVtLCBwcm9wZXJ0eSkge1xuICBsZXQgcHJvcCA9IG51bGw7XG5cbiAgaWYgKHByb3BlcnR5IGluIGl0ZW0pIHtcbiAgICBwcm9wID0gcHJvcGVydHk7XG4gIH0gZWxzZSBpZiAoU3ltYm9sLmZvcihwcm9wZXJ0eSkgaW4gaXRlbSkge1xuICAgIHByb3AgPSBTeW1ib2wuZm9yKHByb3BlcnR5KTtcbiAgfSBlbHNlIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoYFByb3BlcnR5ICR7IHByb3BlcnR5IH0gbm90IGZvdW5kIGluICR7IGl0ZW0gfWApO1xuICB9XG5cbiAgaWYgKGl0ZW1bcHJvcF0gaW5zdGFuY2VvZiBGdW5jdGlvbikge1xuICAgIHJldHVybiBpdGVtW3Byb3BdKCk7XG4gIH0gZWxzZSB7XG4gICAgcmV0dXJuIGl0ZW1bcHJvcF07XG4gIH1cbn1cblxuZnVuY3Rpb24gYXBwbHkoLi4uYXJncykge1xuICBpZiAoYXJncy5sZW5ndGggPT09IDIpIHtcbiAgICBhcmdzWzBdLmFwcGx5KG51bGwsIGFyZ3Muc2xpY2UoMSkpO1xuICB9IGVsc2Uge1xuICAgIGFyZ3NbMF1bYXJnc1sxXV0uYXBwbHkobnVsbCwgYXJncy5zbGljZSgyKSk7XG4gIH1cbn1cblxuZnVuY3Rpb24gY29udGFpbnMobGVmdCwgcmlnaHQpIHtcbiAgZm9yIChsZXQgeCBvZiByaWdodCkge1xuICAgIGlmIChQYXR0ZXJucy5tYXRjaF9ub190aHJvdyhsZWZ0LCB4KSAhPSBudWxsKSB7XG4gICAgICByZXR1cm4gdHJ1ZTtcbiAgICB9XG4gIH1cblxuICByZXR1cm4gZmFsc2U7XG59XG5cbmZ1bmN0aW9uIGdldF9nbG9iYWwoKSB7XG4gIGlmICh0eXBlb2Ygc2VsZiAhPT0gJ3VuZGVmaW5lZCcpIHtcbiAgICByZXR1cm4gc2VsZjtcbiAgfSBlbHNlIGlmICh0eXBlb2Ygd2luZG93ICE9PSAndW5kZWZpbmVkJykge1xuICAgIHJldHVybiB3aW5kb3c7XG4gIH0gZWxzZSBpZiAodHlwZW9mIGdsb2JhbCAhPT0gJ3VuZGVmaW5lZCcpIHtcbiAgICByZXR1cm4gZ2xvYmFsO1xuICB9XG5cbiAgdGhyb3cgbmV3IEVycm9yKCdObyBnbG9iYWwgc3RhdGUgZm91bmQnKTtcbn1cblxuZnVuY3Rpb24gZGVmc3RydWN0KGRlZmF1bHRzKSB7XG4gIHJldHVybiBjbGFzcyB7XG4gICAgY29uc3RydWN0b3IodXBkYXRlID0ge30pIHtcbiAgICAgIGxldCB0aGVfdmFsdWVzID0gT2JqZWN0LmFzc2lnbihkZWZhdWx0cywgdXBkYXRlKTtcbiAgICAgIE9iamVjdC5hc3NpZ24odGhpcywgdGhlX3ZhbHVlcyk7XG4gICAgfVxuXG4gICAgc3RhdGljIGNyZWF0ZSh1cGRhdGVzID0ge30pIHtcbiAgICAgIGxldCB4ID0gbmV3IHRoaXModXBkYXRlcyk7XG4gICAgICByZXR1cm4gT2JqZWN0LmZyZWV6ZSh4KTtcbiAgICB9XG4gIH07XG59XG5cbmZ1bmN0aW9uIGRlZmV4Y2VwdGlvbihkZWZhdWx0cykge1xuICByZXR1cm4gY2xhc3MgZXh0ZW5kcyBFcnJvciB7XG4gICAgY29uc3RydWN0b3IodXBkYXRlID0ge30pIHtcbiAgICAgIGxldCBtZXNzYWdlID0gdXBkYXRlLm1lc3NhZ2UgfHwgJyc7XG4gICAgICBzdXBlcihtZXNzYWdlKTtcblxuICAgICAgbGV0IHRoZV92YWx1ZXMgPSBPYmplY3QuYXNzaWduKGRlZmF1bHRzLCB1cGRhdGUpO1xuICAgICAgT2JqZWN0LmFzc2lnbih0aGlzLCB0aGVfdmFsdWVzKTtcblxuICAgICAgdGhpcy5uYW1lID0gdGhpcy5jb25zdHJ1Y3Rvci5uYW1lO1xuICAgICAgdGhpcy5tZXNzYWdlID0gbWVzc2FnZTtcbiAgICAgIHRoaXNbU3BlY2lhbEZvcm1zLmF0b20oJ19fZXhjZXB0aW9uX18nKV0gPSB0cnVlO1xuICAgICAgRXJyb3IuY2FwdHVyZVN0YWNrVHJhY2UodGhpcywgdGhpcy5jb25zdHJ1Y3Rvci5uYW1lKTtcbiAgICB9XG5cbiAgICBzdGF0aWMgY3JlYXRlKHVwZGF0ZXMgPSB7fSkge1xuICAgICAgbGV0IHggPSBuZXcgdGhpcyh1cGRhdGVzKTtcbiAgICAgIHJldHVybiBPYmplY3QuZnJlZXplKHgpO1xuICAgIH1cbiAgfTtcbn1cblxuZnVuY3Rpb24gZGVmcHJvdG9jb2woc3BlYykge1xuICByZXR1cm4gbmV3IFByb3RvY29sKHNwZWMpO1xufVxuXG5mdW5jdGlvbiBkZWZpbXBsKHByb3RvY29sLCB0eXBlLCBpbXBsKSB7XG4gIHByb3RvY29sLmltcGxlbWVudGF0aW9uKHR5cGUsIGltcGwpO1xufVxuXG5mdW5jdGlvbiBnZXRfb2JqZWN0X2tleXMob2JqKSB7XG4gIHJldHVybiBPYmplY3Qua2V5cyhvYmopLmNvbmNhdChPYmplY3QuZ2V0T3duUHJvcGVydHlTeW1ib2xzKG9iaikpO1xufVxuXG5mdW5jdGlvbiBpc192YWxpZF9jaGFyYWN0ZXIoY29kZXBvaW50KSB7XG4gIHRyeSB7XG4gICAgcmV0dXJuIFN0cmluZy5mcm9tQ29kZVBvaW50KGNvZGVwb2ludCkgIT0gbnVsbDtcbiAgfSBjYXRjaCAoZSkge1xuICAgIHJldHVybiBmYWxzZTtcbiAgfVxufVxuXG4vL2h0dHBzOi8vZGV2ZWxvcGVyLm1vemlsbGEub3JnL2VuLVVTL2RvY3MvV2ViL0FQSS9XaW5kb3dCYXNlNjQvQmFzZTY0X2VuY29kaW5nX2FuZF9kZWNvZGluZyNTb2x1dGlvbl8yXyVFMiU4MCU5M19yZXdyaXRlX3RoZV9ET01zX2F0b2IoKV9hbmRfYnRvYSgpX3VzaW5nX0phdmFTY3JpcHQnc19UeXBlZEFycmF5c19hbmRfVVRGLThcbmZ1bmN0aW9uIGI2NEVuY29kZVVuaWNvZGUoc3RyKSB7XG4gIHJldHVybiBidG9hKGVuY29kZVVSSUNvbXBvbmVudChzdHIpLnJlcGxhY2UoLyUoWzAtOUEtRl17Mn0pL2csIGZ1bmN0aW9uIChtYXRjaCwgcDEpIHtcbiAgICByZXR1cm4gU3RyaW5nLmZyb21DaGFyQ29kZSgnMHgnICsgcDEpO1xuICB9KSk7XG59XG5cbmZ1bmN0aW9uIGRlbGV0ZV9wcm9wZXJ0eV9mcm9tX21hcChtYXAsIHByb3BlcnR5KSB7XG4gIGxldCBuZXdfbWFwID0gT2JqZWN0LmFzc2lnbihPYmplY3QuY3JlYXRlKG1hcC5jb25zdHJ1Y3Rvci5wcm90b3R5cGUpLCBtYXApO1xuICBkZWxldGUgbmV3X21hcFtwcm9wZXJ0eV07XG5cbiAgcmV0dXJuIE9iamVjdC5mcmVlemUobmV3X21hcCk7XG59XG5cbmZ1bmN0aW9uIGNsYXNzX3RvX29iaihtYXApIHtcbiAgbGV0IG5ld19tYXAgPSBPYmplY3QuYXNzaWduKHt9LCBtYXApO1xuICByZXR1cm4gT2JqZWN0LmZyZWV6ZShuZXdfbWFwKTtcbn1cblxuZnVuY3Rpb24gYWRkX3Byb3BlcnR5X3RvX21hcChtYXAsIHByb3BlcnR5LCB2YWx1ZSkge1xuICBsZXQgbmV3X21hcCA9IE9iamVjdC5hc3NpZ24oe30sIG1hcCk7XG4gIG5ld19tYXBbcHJvcGVydHldID0gdmFsdWU7XG4gIHJldHVybiBPYmplY3QuZnJlZXplKG5ld19tYXApO1xufVxuXG5mdW5jdGlvbiBibm90KGV4cHIpIHtcbiAgcmV0dXJuIH5leHByO1xufVxuXG5mdW5jdGlvbiBiYW5kKGxlZnQsIHJpZ2h0KSB7XG4gIHJldHVybiBsZWZ0ICYgcmlnaHQ7XG59XG5cbmZ1bmN0aW9uIGJvcihsZWZ0LCByaWdodCkge1xuICByZXR1cm4gbGVmdCB8IHJpZ2h0O1xufVxuXG5mdW5jdGlvbiBic2wobGVmdCwgcmlnaHQpIHtcbiAgcmV0dXJuIGxlZnQgPDwgcmlnaHQ7XG59XG5cbmZ1bmN0aW9uIGJzcihsZWZ0LCByaWdodCkge1xuICByZXR1cm4gbGVmdCA+PiByaWdodDtcbn1cblxuZnVuY3Rpb24gYnhvcihsZWZ0LCByaWdodCkge1xuICByZXR1cm4gbGVmdCBeIHJpZ2h0O1xufVxuXG5mdW5jdGlvbiB6aXAobGlzdF9vZl9saXN0cykge1xuICBpZiAobGlzdF9vZl9saXN0cy5sZW5ndGggPT09IDApIHtcbiAgICByZXR1cm4gT2JqZWN0LmZyZWV6ZShbXSk7XG4gIH1cblxuICBsZXQgbmV3X3ZhbHVlID0gW107XG4gIGxldCBzbWFsbGVzdF9sZW5ndGggPSBsaXN0X29mX2xpc3RzWzBdO1xuXG4gIGZvciAobGV0IHggb2YgbGlzdF9vZl9saXN0cykge1xuICAgIGlmICh4Lmxlbmd0aCA8IHNtYWxsZXN0X2xlbmd0aCkge1xuICAgICAgc21hbGxlc3RfbGVuZ3RoID0geC5sZW5ndGg7XG4gICAgfVxuICB9XG5cbiAgZm9yIChsZXQgaSA9IDA7IGkgPCBzbWFsbGVzdF9sZW5ndGg7IGkrKykge1xuICAgIGxldCBjdXJyZW50X3ZhbHVlID0gW107XG4gICAgZm9yIChsZXQgaiA9IDA7IGogPCBsaXN0X29mX2xpc3RzLmxlbmd0aDsgaisrKSB7XG4gICAgICBjdXJyZW50X3ZhbHVlLnB1c2gobGlzdF9vZl9saXN0c1tqXVtpXSk7XG4gICAgfVxuXG4gICAgbmV3X3ZhbHVlLnB1c2gobmV3IFR1cGxlKC4uLmN1cnJlbnRfdmFsdWUpKTtcbiAgfVxuXG4gIHJldHVybiBPYmplY3QuZnJlZXplKG5ld192YWx1ZSk7XG59XG5cbmZ1bmN0aW9uIGNhbl9kZWNvZGU2NChkYXRhKSB7XG4gIHRyeSB7XG4gICAgYXRvYihkYXRhKTtcbiAgICByZXR1cm4gdHJ1ZTtcbiAgfSBjYXRjaCAoZSkge1xuICAgIHJldHVybiBmYWxzZTtcbiAgfVxufVxuXG52YXIgRnVuY3Rpb25zID0ge1xuICBjYWxsX3Byb3BlcnR5LFxuICBhcHBseSxcbiAgY29udGFpbnMsXG4gIGdldF9nbG9iYWwsXG4gIGRlZnN0cnVjdCxcbiAgZGVmZXhjZXB0aW9uLFxuICBkZWZwcm90b2NvbCxcbiAgZGVmaW1wbCxcbiAgZ2V0X29iamVjdF9rZXlzLFxuICBpc192YWxpZF9jaGFyYWN0ZXIsXG4gIGI2NEVuY29kZVVuaWNvZGUsXG4gIGRlbGV0ZV9wcm9wZXJ0eV9mcm9tX21hcCxcbiAgYWRkX3Byb3BlcnR5X3RvX21hcCxcbiAgY2xhc3NfdG9fb2JqLFxuICBjYW5fZGVjb2RlNjQsXG4gIGJub3QsXG4gIGJhbmQsXG4gIGJvcixcbiAgYnNsLFxuICBic3IsXG4gIGJ4b3IsXG4gIHppcFxufTtcblxuZnVuY3Rpb24gX2Nhc2UoY29uZGl0aW9uLCBjbGF1c2VzKSB7XG4gIHJldHVybiBQYXR0ZXJucy5kZWZtYXRjaCguLi5jbGF1c2VzKShjb25kaXRpb24pO1xufVxuXG5mdW5jdGlvbiBjb25kKGNsYXVzZXMpIHtcbiAgZm9yIChsZXQgY2xhdXNlIG9mIGNsYXVzZXMpIHtcbiAgICBpZiAoY2xhdXNlWzBdKSB7XG4gICAgICByZXR1cm4gY2xhdXNlWzFdKCk7XG4gICAgfVxuICB9XG5cbiAgdGhyb3cgbmV3IEVycm9yKCk7XG59XG5cbmZ1bmN0aW9uIG1hcF91cGRhdGUobWFwLCB2YWx1ZXMpIHtcbiAgcmV0dXJuIE9iamVjdC5mcmVlemUoT2JqZWN0LmFzc2lnbihPYmplY3QuY3JlYXRlKG1hcC5jb25zdHJ1Y3Rvci5wcm90b3R5cGUpLCBtYXAsIHZhbHVlcykpO1xufVxuXG5mdW5jdGlvbiBfZm9yKGNvbGxlY3Rpb25zLCBmdW4sIGZpbHRlciA9ICgpID0+IHRydWUsIGludG8gPSBbXSwgcHJldmlvdXNWYWx1ZXMgPSBbXSkge1xuICBsZXQgcGF0dGVybiA9IGNvbGxlY3Rpb25zWzBdWzBdO1xuICBsZXQgY29sbGVjdGlvbiA9IGNvbGxlY3Rpb25zWzBdWzFdO1xuXG4gIGlmIChjb2xsZWN0aW9ucy5sZW5ndGggPT09IDEpIHtcblxuICAgIGZvciAobGV0IGVsZW0gb2YgY29sbGVjdGlvbikge1xuICAgICAgbGV0IHIgPSBQYXR0ZXJucy5tYXRjaF9ub190aHJvdyhwYXR0ZXJuLCBlbGVtKTtcbiAgICAgIGxldCBhcmdzID0gcHJldmlvdXNWYWx1ZXMuY29uY2F0KHIpO1xuXG4gICAgICBpZiAociAmJiBmaWx0ZXIuYXBwbHkodGhpcywgYXJncykpIHtcbiAgICAgICAgaW50byA9IGludG8uY29uY2F0KFtmdW4uYXBwbHkodGhpcywgYXJncyldKTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICByZXR1cm4gaW50bztcbiAgfSBlbHNlIHtcbiAgICBsZXQgX2ludG8gPSBbXTtcblxuICAgIGZvciAobGV0IGVsZW0gb2YgY29sbGVjdGlvbikge1xuICAgICAgbGV0IHIgPSBQYXR0ZXJucy5tYXRjaF9ub190aHJvdyhwYXR0ZXJuLCBlbGVtKTtcbiAgICAgIGlmIChyKSB7XG4gICAgICAgIF9pbnRvID0gaW50by5jb25jYXQodGhpcy5fZm9yKGNvbGxlY3Rpb25zLnNsaWNlKDEpLCBmdW4sIGZpbHRlciwgX2ludG8sIHByZXZpb3VzVmFsdWVzLmNvbmNhdChyKSkpO1xuICAgICAgfVxuICAgIH1cblxuICAgIHJldHVybiBfaW50bztcbiAgfVxufVxuXG5mdW5jdGlvbiBfdHJ5KGRvX2Z1biwgcmVzY3VlX2Z1bmN0aW9uLCBjYXRjaF9mdW4sIGVsc2VfZnVuY3Rpb24sIGFmdGVyX2Z1bmN0aW9uKSB7XG4gIGxldCByZXN1bHQgPSBudWxsO1xuXG4gIHRyeSB7XG4gICAgcmVzdWx0ID0gZG9fZnVuKCk7XG4gIH0gY2F0Y2ggKGUpIHtcbiAgICBsZXQgZXhfcmVzdWx0ID0gbnVsbDtcblxuICAgIGlmIChyZXNjdWVfZnVuY3Rpb24pIHtcbiAgICAgIHRyeSB7XG4gICAgICAgIGV4X3Jlc3VsdCA9IHJlc2N1ZV9mdW5jdGlvbihlKTtcbiAgICAgICAgcmV0dXJuIGV4X3Jlc3VsdDtcbiAgICAgIH0gY2F0Y2ggKGV4KSB7XG4gICAgICAgIGlmIChleCBpbnN0YW5jZW9mIFBhdHRlcm5zLk1hdGNoRXJyb3IpIHtcbiAgICAgICAgICB0aHJvdyBleDtcbiAgICAgICAgfVxuICAgICAgfVxuICAgIH1cblxuICAgIGlmIChjYXRjaF9mdW4pIHtcbiAgICAgIHRyeSB7XG4gICAgICAgIGV4X3Jlc3VsdCA9IGNhdGNoX2Z1bihlKTtcbiAgICAgICAgcmV0dXJuIGV4X3Jlc3VsdDtcbiAgICAgIH0gY2F0Y2ggKGV4KSB7XG4gICAgICAgIGlmIChleCBpbnN0YW5jZW9mIFBhdHRlcm5zLk1hdGNoRXJyb3IpIHtcbiAgICAgICAgICB0aHJvdyBleDtcbiAgICAgICAgfVxuICAgICAgfVxuICAgIH1cblxuICAgIHRocm93IGU7XG4gIH0gZmluYWxseSB7XG4gICAgaWYgKGFmdGVyX2Z1bmN0aW9uKSB7XG4gICAgICBhZnRlcl9mdW5jdGlvbigpO1xuICAgIH1cbiAgfVxuXG4gIGlmIChlbHNlX2Z1bmN0aW9uKSB7XG4gICAgdHJ5IHtcbiAgICAgIHJldHVybiBlbHNlX2Z1bmN0aW9uKHJlc3VsdCk7XG4gICAgfSBjYXRjaCAoZXgpIHtcbiAgICAgIGlmIChleCBpbnN0YW5jZW9mIFBhdHRlcm5zLk1hdGNoRXJyb3IpIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdObyBNYXRjaCBGb3VuZCBpbiBFbHNlJyk7XG4gICAgICB9XG5cbiAgICAgIHRocm93IGV4O1xuICAgIH1cbiAgfSBlbHNlIHtcbiAgICByZXR1cm4gcmVzdWx0O1xuICB9XG59XG5cbnZhciBTcGVjaWFsRm9ybXMkMSA9IHtcbiAgX2Nhc2UsXG4gIGNvbmQsXG4gIG1hcF91cGRhdGUsXG4gIF9mb3IsXG4gIF90cnlcbn07XG5cbkZ1bmN0aW9ucy5nZXRfZ2xvYmFsKCkucHJvY2Vzc2VzID0gRnVuY3Rpb25zLmdldF9nbG9iYWwoKS5wcm9jZXNzZXMgfHwgbmV3IFByb2Nlc3NTeXN0ZW0oKTtcblxudmFyIENvcmUkMSA9IHtcbiAgUHJvY2Vzc1N5c3RlbSxcbiAgVHVwbGUsXG4gIFBJRCxcbiAgQml0U3RyaW5nLFxuICBQYXR0ZXJucyxcbiAgSW50ZWdlcixcbiAgRmxvYXQsXG4gIEZ1bmN0aW9ucyxcbiAgU3BlY2lhbEZvcm1zOiBTcGVjaWFsRm9ybXMkMVxufTtcblxubGV0IEVudW0gPSB7XG5cbiAgYWxsX19xbWFya19fOiBmdW5jdGlvbiAoY29sbGVjdGlvbiwgZnVuID0geCA9PiB4KSB7XG4gICAgZm9yIChsZXQgZWxlbSBvZiBjb2xsZWN0aW9uKSB7XG4gICAgICBpZiAoIWZ1bihlbGVtKSkge1xuICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICB9XG4gICAgfVxuXG4gICAgcmV0dXJuIHRydWU7XG4gIH0sXG5cbiAgYW55X19xbWFya19fOiBmdW5jdGlvbiAoY29sbGVjdGlvbiwgZnVuID0geCA9PiB4KSB7XG4gICAgZm9yIChsZXQgZWxlbSBvZiBjb2xsZWN0aW9uKSB7XG4gICAgICBpZiAoZnVuKGVsZW0pKSB7XG4gICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgfVxuICAgIH1cblxuICAgIHJldHVybiBmYWxzZTtcbiAgfSxcblxuICBhdDogZnVuY3Rpb24gKGNvbGxlY3Rpb24sIG4sIHRoZV9kZWZhdWx0ID0gbnVsbCkge1xuICAgIGlmIChuID4gdGhpcy5jb3VudChjb2xsZWN0aW9uKSB8fCBuIDwgMCkge1xuICAgICAgcmV0dXJuIHRoZV9kZWZhdWx0O1xuICAgIH1cblxuICAgIHJldHVybiBjb2xsZWN0aW9uW25dO1xuICB9LFxuXG4gIGNvbmNhdDogZnVuY3Rpb24gKC4uLmVudW1hYmxlcykge1xuICAgIHJldHVybiBlbnVtYWJsZXNbMF0uY29uY2F0KGVudW1hYmxlc1sxXSk7XG4gIH0sXG5cbiAgY291bnQ6IGZ1bmN0aW9uIChjb2xsZWN0aW9uLCBmdW4gPSBudWxsKSB7XG4gICAgaWYgKGZ1biA9PSBudWxsKSB7XG4gICAgICByZXR1cm4gY29sbGVjdGlvbi5sZW5ndGg7XG4gICAgfSBlbHNlIHtcbiAgICAgIHJldHVybiBjb2xsZWN0aW9uLmZpbHRlcihmdW4pLmxlbmd0aDtcbiAgICB9XG4gIH0sXG5cbiAgZHJvcDogZnVuY3Rpb24gKGNvbGxlY3Rpb24sIGNvdW50KSB7XG4gICAgcmV0dXJuIGNvbGxlY3Rpb24uc2xpY2UoY291bnQpO1xuICB9LFxuXG4gIGRyb3Bfd2hpbGU6IGZ1bmN0aW9uIChjb2xsZWN0aW9uLCBmdW4pIHtcbiAgICBsZXQgY291bnQgPSAwO1xuXG4gICAgZm9yIChsZXQgZWxlbSBvZiBjb2xsZWN0aW9uKSB7XG4gICAgICBpZiAoZnVuKGVsZW0pKSB7XG4gICAgICAgIGNvdW50ID0gY291bnQgKyAxO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgYnJlYWs7XG4gICAgICB9XG4gICAgfVxuXG4gICAgcmV0dXJuIGNvbGxlY3Rpb24uc2xpY2UoY291bnQpO1xuICB9LFxuXG4gIGVhY2g6IGZ1bmN0aW9uIChjb2xsZWN0aW9uLCBmdW4pIHtcbiAgICBmb3IgKGxldCBlbGVtIG9mIGNvbGxlY3Rpb24pIHtcbiAgICAgIGZ1bihlbGVtKTtcbiAgICB9XG4gIH0sXG5cbiAgZW1wdHlfX3FtYXJrX186IGZ1bmN0aW9uIChjb2xsZWN0aW9uKSB7XG4gICAgcmV0dXJuIGNvbGxlY3Rpb24ubGVuZ3RoID09PSAwO1xuICB9LFxuXG4gIGZldGNoOiBmdW5jdGlvbiAoY29sbGVjdGlvbiwgbikge1xuICAgIGlmIChBcnJheS5pc0FycmF5KGNvbGxlY3Rpb24pKSB7XG4gICAgICBpZiAobiA8IHRoaXMuY291bnQoY29sbGVjdGlvbikgJiYgbiA+PSAwKSB7XG4gICAgICAgIHJldHVybiBuZXcgQ29yZSQxLlR1cGxlKFN5bWJvbC5mb3IoXCJva1wiKSwgY29sbGVjdGlvbltuXSk7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICByZXR1cm4gU3ltYm9sLmZvcihcImVycm9yXCIpO1xuICAgICAgfVxuICAgIH1cblxuICAgIHRocm93IG5ldyBFcnJvcihcImNvbGxlY3Rpb24gaXMgbm90IGFuIEVudW1lcmFibGVcIik7XG4gIH0sXG5cbiAgZmV0Y2hfX2VtYXJrX186IGZ1bmN0aW9uIChjb2xsZWN0aW9uLCBuKSB7XG4gICAgaWYgKEFycmF5LmlzQXJyYXkoY29sbGVjdGlvbikpIHtcbiAgICAgIGlmIChuIDwgdGhpcy5jb3VudChjb2xsZWN0aW9uKSAmJiBuID49IDApIHtcbiAgICAgICAgcmV0dXJuIGNvbGxlY3Rpb25bbl07XG4gICAgICB9IGVsc2Uge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoXCJvdXQgb2YgYm91bmRzIGVycm9yXCIpO1xuICAgICAgfVxuICAgIH1cblxuICAgIHRocm93IG5ldyBFcnJvcihcImNvbGxlY3Rpb24gaXMgbm90IGFuIEVudW1lcmFibGVcIik7XG4gIH0sXG5cbiAgZmlsdGVyOiBmdW5jdGlvbiAoY29sbGVjdGlvbiwgZnVuKSB7XG4gICAgbGV0IHJlc3VsdCA9IFtdO1xuXG4gICAgZm9yIChsZXQgZWxlbSBvZiBjb2xsZWN0aW9uKSB7XG4gICAgICBpZiAoZnVuKGVsZW0pKSB7XG4gICAgICAgIHJlc3VsdC5wdXNoKGVsZW0pO1xuICAgICAgfVxuICAgIH1cblxuICAgIHJldHVybiByZXN1bHQ7XG4gIH0sXG5cbiAgZmlsdGVyX21hcDogZnVuY3Rpb24gKGNvbGxlY3Rpb24sIGZpbHRlciwgbWFwcGVyKSB7XG4gICAgcmV0dXJuIEVudW0ubWFwKEVudW0uZmlsdGVyKGNvbGxlY3Rpb24sIGZpbHRlciksIG1hcHBlcik7XG4gIH0sXG5cbiAgZmluZDogZnVuY3Rpb24gKGNvbGxlY3Rpb24sIGlmX25vbmUgPSBudWxsLCBmdW4pIHtcbiAgICBmb3IgKGxldCBlbGVtIG9mIGNvbGxlY3Rpb24pIHtcbiAgICAgIGlmIChmdW4oZWxlbSkpIHtcbiAgICAgICAgcmV0dXJuIGVsZW07XG4gICAgICB9XG4gICAgfVxuXG4gICAgcmV0dXJuIGlmX25vbmU7XG4gIH0sXG5cbiAgaW50bzogZnVuY3Rpb24gKGNvbGxlY3Rpb24sIGxpc3QpIHtcbiAgICByZXR1cm4gbGlzdC5jb25jYXQoY29sbGVjdGlvbik7XG4gIH0sXG5cbiAgbWFwOiBmdW5jdGlvbiAoY29sbGVjdGlvbiwgZnVuKSB7XG4gICAgbGV0IHJlc3VsdCA9IFtdO1xuXG4gICAgZm9yIChsZXQgZWxlbSBvZiBjb2xsZWN0aW9uKSB7XG4gICAgICByZXN1bHQucHVzaChmdW4oZWxlbSkpO1xuICAgIH1cblxuICAgIHJldHVybiByZXN1bHQ7XG4gIH0sXG5cbiAgbWFwX3JlZHVjZTogZnVuY3Rpb24gKGNvbGxlY3Rpb24sIGFjYywgZnVuKSB7XG4gICAgbGV0IG1hcHBlZCA9IE9iamVjdC5mcmVlemUoW10pO1xuICAgIGxldCB0aGVfYWNjID0gYWNjO1xuXG4gICAgZm9yICh2YXIgaSA9IDA7IGkgPCB0aGlzLmNvdW50KGNvbGxlY3Rpb24pOyBpKyspIHtcbiAgICAgIGxldCB0dXBsZSA9IGZ1bihjb2xsZWN0aW9uW2ldLCB0aGVfYWNjKTtcblxuICAgICAgdGhlX2FjYyA9IHR1cGxlLmdldCgxKTtcbiAgICAgIG1hcHBlZCA9IE9iamVjdC5mcmVlemUobWFwcGVkLmNvbmNhdChbdHVwbGUuZ2V0KDApXSkpO1xuICAgIH1cblxuICAgIHJldHVybiBuZXcgQ29yZSQxLlR1cGxlKG1hcHBlZCwgdGhlX2FjYyk7XG4gIH0sXG5cbiAgbWVtYmVyX19xbWFya19fOiBmdW5jdGlvbiAoY29sbGVjdGlvbiwgdmFsdWUpIHtcbiAgICByZXR1cm4gY29sbGVjdGlvbi5pbmNsdWRlcyh2YWx1ZSk7XG4gIH0sXG5cbiAgcmVkdWNlOiBmdW5jdGlvbiAoY29sbGVjdGlvbiwgYWNjLCBmdW4pIHtcbiAgICBsZXQgdGhlX2FjYyA9IGFjYztcblxuICAgIGZvciAodmFyIGkgPSAwOyBpIDwgdGhpcy5jb3VudChjb2xsZWN0aW9uKTsgaSsrKSB7XG4gICAgICBsZXQgdHVwbGUgPSBmdW4oY29sbGVjdGlvbltpXSwgdGhlX2FjYyk7XG5cbiAgICAgIHRoZV9hY2MgPSB0dXBsZS5nZXQoMSk7XG4gICAgfVxuXG4gICAgcmV0dXJuIHRoZV9hY2M7XG4gIH0sXG5cbiAgdGFrZTogZnVuY3Rpb24gKGNvbGxlY3Rpb24sIGNvdW50KSB7XG4gICAgcmV0dXJuIGNvbGxlY3Rpb24uc2xpY2UoMCwgY291bnQpO1xuICB9LFxuXG4gIHRha2VfZXZlcnk6IGZ1bmN0aW9uIChjb2xsZWN0aW9uLCBudGgpIHtcbiAgICBsZXQgcmVzdWx0ID0gW107XG4gICAgbGV0IGluZGV4ID0gMDtcblxuICAgIGZvciAobGV0IGVsZW0gb2YgY29sbGVjdGlvbikge1xuICAgICAgaWYgKGluZGV4ICUgbnRoID09PSAwKSB7XG4gICAgICAgIHJlc3VsdC5wdXNoKGVsZW0pO1xuICAgICAgfVxuICAgIH1cblxuICAgIHJldHVybiBPYmplY3QuZnJlZXplKHJlc3VsdCk7XG4gIH0sXG5cbiAgdGFrZV93aGlsZTogZnVuY3Rpb24gKGNvbGxlY3Rpb24sIGZ1bikge1xuICAgIGxldCBjb3VudCA9IDA7XG5cbiAgICBmb3IgKGxldCBlbGVtIG9mIGNvbGxlY3Rpb24pIHtcbiAgICAgIGlmIChmdW4oZWxlbSkpIHtcbiAgICAgICAgY291bnQgPSBjb3VudCArIDE7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBicmVhaztcbiAgICAgIH1cbiAgICB9XG5cbiAgICByZXR1cm4gY29sbGVjdGlvbi5zbGljZSgwLCBjb3VudCk7XG4gIH0sXG5cbiAgdG9fbGlzdDogZnVuY3Rpb24gKGNvbGxlY3Rpb24pIHtcbiAgICByZXR1cm4gY29sbGVjdGlvbjtcbiAgfVxufTtcblxudmFyIEVsaXhpciA9IHtcbiAgQ29yZTogQ29yZSQxLFxuICBFbnVtLFxuICBWaXJ0dWFsRE9NXG59O1xuXG5leHBvcnQgZGVmYXVsdCBFbGl4aXI7Il0sImZpbGUiOiJFbGl4aXIuanMiLCJzb3VyY2VSb290IjoiL3NvdXJjZS8ifQ== \ No newline at end of file diff --git a/src/javascript/lib/core/functions.js b/src/javascript/lib/core/functions.js index fea6ab41..500ab6e6 100644 --- a/src/javascript/lib/core/functions.js +++ b/src/javascript/lib/core/functions.js @@ -1,6 +1,7 @@ import { Tuple } from './primitives'; import BitString from './bit_string'; import Patterns from './patterns'; +import Protocol from './protocol'; function call_property(item, property){ let prop = null; diff --git a/test/translator/protocol_test.exs b/test/translator/protocol_test.exs index 8d13db99..9e059915 100644 --- a/test/translator/protocol_test.exs +++ b/test/translator/protocol_test.exs @@ -27,9 +27,7 @@ defmodule ElixirScript.Translator.Protocol.Test do js_code = """ import Elixir$ElixirScript$Kernel from './Elixir.ElixirScript.Kernel'; const Elixir$Blank = Elixir.Core.Functions.defprotocol({ - blank__qmark__: Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable()],function(data) { - return null; - })) + blank__qmark__: function(){} }); Elixir.Core.Functions.defimpl(Elixir$Blank, Array,{ blank__qmark__: Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Object.freeze([])],function() { From bd9cb14678dcf838f428f4779fe230cf1952a3a4 Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Thu, 21 Jan 2016 18:22:24 -0600 Subject: [PATCH 126/860] Refactoring and added some comments --- lib/elixir_script.ex | 43 +++++++++++---------------- lib/elixir_script/cli.ex | 1 + lib/elixir_script/translator/state.ex | 8 +++++ 3 files changed, 26 insertions(+), 26 deletions(-) diff --git a/lib/elixir_script.ex b/lib/elixir_script.ex index 73a14e8c..9828e86a 100644 --- a/lib/elixir_script.ex +++ b/lib/elixir_script.ex @@ -33,6 +33,10 @@ defmodule ElixirScript do end end + + # At compile time, gathers the files containing the standard lib modules, + # converts them to their quoted forms and keeps them in @libs for use when compiling. + # These are full of macros and would not transpile to anything significant @modules_to_not_read ["v_dom.ex", "html.ex"] @@ -63,20 +67,7 @@ defmodule ElixirScript do """ @spec compile_quoted(Macro.t, Map.t) :: [binary | {binary, binary}] def compile_quoted(quoted, opts \\ %{}) do - - compiler_opts = build_compiler_options(opts) - ElixirScript.Translator.State.start_link(compiler_opts) - - libs = @libs - |> updated_quoted - - ModuleCollector.process_modules(libs ++ [updated_quoted(quoted)]) - - code = create_code(compiler_opts) - - ElixirScript.Translator.State.stop - - code + do_compile(opts, [quoted]) end @doc """ @@ -84,19 +75,20 @@ defmodule ElixirScript do """ @spec compile_path(binary, Map.t) :: [binary | {binary, binary}] def compile_path(path, opts \\ %{}) do - - compiler_opts = build_compiler_options(opts) - ElixirScript.Translator.State.start_link(compiler_opts) - - libs = @libs - |> updated_quoted - code = path |> Path.wildcard |> Enum.map(&file_to_quoted/1) + do_compile(opts, code) + end + + defp do_compile(opts, quoted_code_list) do + compiler_opts = build_compiler_options(opts) + libs = update_quoted(@libs) + + ElixirScript.Translator.State.start_link(compiler_opts) - ModuleCollector.process_modules(libs ++ code) + ModuleCollector.process_modules(libs ++ Enum.map(quoted_code_list, &update_quoted(&1))) code = create_code(compiler_opts) @@ -120,10 +112,9 @@ defmodule ElixirScript do file |> File.read! |> Code.string_to_quoted! - |> updated_quoted end - defp updated_quoted(quoted) do + defp update_quoted(quoted) do Macro.prewalk(quoted, fn ({name, context, parms}) -> if context[:import] == Kernel do @@ -136,6 +127,7 @@ defmodule ElixirScript do end) end + @doc false def custom_env() do __using__([]) __ENV__ @@ -212,8 +204,7 @@ defmodule ElixirScript do { file_path, Builder.program(module.body) } end - @doc false - def javascript_ast_to_code({path, js_ast}) do + defp javascript_ast_to_code({path, js_ast}) do js_code = js_ast |> prepare_js_ast |> Generator.generate diff --git a/lib/elixir_script/cli.ex b/lib/elixir_script/cli.ex index d2eb0b57..994ec567 100644 --- a/lib/elixir_script/cli.ex +++ b/lib/elixir_script/cli.ex @@ -78,6 +78,7 @@ defmodule ElixirScript.CLI do end) |> Enum.join("//:ENDFILE\n") |> IO.write + output_path -> Enum.each(compile_output, fn(x) -> write_to_file(x, output_path) diff --git a/lib/elixir_script/translator/state.ex b/lib/elixir_script/translator/state.ex index 33f79959..db4c8bdd 100644 --- a/lib/elixir_script/translator/state.ex +++ b/lib/elixir_script/translator/state.ex @@ -2,6 +2,14 @@ defmodule ElixirScript.Translator.State do @moduledoc false alias ElixirScript.Translator.Utils + @doc """ + This agent holds references to the compiler options, a map all of the modules, and + a map of modules that define the standard library. + + The modules map has the module's name a the key and a ElixirScript.Module struct as the value. + The module struct contains properties to access the function and macro names/arities + + """ def start_link(compiler_opts \\ []) do Agent.start_link(fn -> %{ compiler_opts: compiler_opts, modules: Map.new, std_lib_map: build_standard_lib_map() } From addb9dcb3c70733a9cca1ac4d03b985fc8c93275 Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Fri, 22 Jan 2016 17:45:06 -0600 Subject: [PATCH 127/860] Refactoring of State module --- lib/elixir_script/translator/state.ex | 55 ++++++++++++++------------- 1 file changed, 29 insertions(+), 26 deletions(-) diff --git a/lib/elixir_script/translator/state.ex b/lib/elixir_script/translator/state.ex index db4c8bdd..a4439630 100644 --- a/lib/elixir_script/translator/state.ex +++ b/lib/elixir_script/translator/state.ex @@ -1,15 +1,14 @@ +# This agent holds references to the compiler options, a map all of the modules, and +# a map of modules that define the standard library. +# +# The modules map has the module's name a the key and a ElixirScript.Module struct as the value. +# +# The std_lib_map holds a mapping of the Elixir standard lib module to the +# version implemented here in ElixirScript. defmodule ElixirScript.Translator.State do @moduledoc false alias ElixirScript.Translator.Utils - @doc """ - This agent holds references to the compiler options, a map all of the modules, and - a map of modules that define the standard library. - - The modules map has the module's name a the key and a ElixirScript.Module struct as the value. - The module struct contains properties to access the function and macro names/arities - - """ def start_link(compiler_opts \\ []) do Agent.start_link(fn -> %{ compiler_opts: compiler_opts, modules: Map.new, std_lib_map: build_standard_lib_map() } @@ -56,7 +55,7 @@ defmodule ElixirScript.Translator.State do def add_protocol(name, functions) do Agent.update(__MODULE__, fn state -> - proto = do_get_module(state, name) + proto = Map.get(state.modules, do_get_module_name(name, state)) if proto == nil do proto = %ElixirScript.Module{ name: name, functions: functions, impls: HashDict.new, type: :protocol } @@ -76,7 +75,7 @@ defmodule ElixirScript.Translator.State do def add_protocol_impl(protocol, type, impl) do Agent.update(__MODULE__, fn state -> - proto = do_get_module(state, protocol) + proto = Map.get(state.modules, do_get_module_name(protocol, state)) if proto == nil do proto = %ElixirScript.Module{ name: protocol, impls: HashDict.new, type: :protocol } @@ -93,10 +92,12 @@ defmodule ElixirScript.Translator.State do end def get_module_name(module_name) do - get_module_name(module_name, get) + Agent.get(__MODULE__, fn(state) -> + do_get_module_name(module_name, state) + end) end - def get_module_name(module_name, state) do + defp do_get_module_name(module_name, state) do std_lib_map = state.std_lib_map case Map.get(std_lib_map, module_name) do nil -> @@ -107,31 +108,33 @@ defmodule ElixirScript.Translator.State do end def get_module(module) when is_atom(module) do - state = Agent.get(__MODULE__, &(&1)) - do_get_module(state, module) + do_get_module(module) end def get_module({:__aliases__, _, _} = name) do - state = Agent.get(__MODULE__, &(&1)) - do_get_module(state, Utils.quoted_to_name(name)) + do_get_module(name) end def get_module(module_name_list) when is_list(module_name_list) do - state = Agent.get(__MODULE__, &(&1)) - do_get_module(state, Utils.quoted_to_name({:__aliases__, [], module_name_list})) + do_get_module(Utils.quoted_to_name({:__aliases__, [], module_name_list})) end - defp do_get_module(state, name) do - Map.get(state.modules, get_module_name(name, state)) + defp do_get_module(name) do + Agent.get(__MODULE__, fn(state) -> + Map.get(state.modules, do_get_module_name(name, state)) + end) end def add_module_reference(module_name, module_ref) do - module = get_module(module_name) - - if module do - module = %{ module | module_refs: Enum.uniq(module.module_refs ++ [module_ref]) } - add_module(module) - end + Agent.update(__MODULE__, fn(state) -> + case Map.get(state.modules, do_get_module_name(module_name, state)) do + nil -> + state + module -> + module = %{ module | module_refs: Enum.uniq(module.module_refs ++ [module_ref]) } + %{ state | modules: Map.put(state.modules, module.name, module) } + end + end) end def get_module_references(module_name) do From 24e1c79f09e98f7a5b3d90fb9437183a9d7c85ab Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Fri, 22 Jan 2016 17:53:21 -0600 Subject: [PATCH 128/860] Updated CHANGELOG. Updated doc on JS.global --- CHANGELOG.md | 8 ++++---- lib/elixir_script/prelude/js.ex | 4 ++-- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 0b66ef1d..8d37facc 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,12 +1,12 @@ # v0.15.0-dev * Enhancements - * Now tracking environment scopes * `alias`, `require`, and `import` now work inside lexical scopes * `__ENV__` and `__CALLER__` are now supported - * Began writing some of the standard libraries in Elixir instead of JavaScript - * Added `JS.import/1` + * Some of the standard library originally written in JavaScript has been rewritten + in Elixir + * Added `JS.import/1`, `JS.typeof/1`,`JS.instanceof/1`, and JS.global/1 * Added support for multi alias/require/imports statements - * Exports are now default exports + * Generated JavaScript export statements are now default exports * When output is sent to standard out, there are now markers to specify where each module begins as well as what the file name would be. For the end of a file, `//:ENDFILE` is used. For the file name, `//:ENDFILENAME` diff --git a/lib/elixir_script/prelude/js.ex b/lib/elixir_script/prelude/js.ex index b961542e..b8257975 100644 --- a/lib/elixir_script/prelude/js.ex +++ b/lib/elixir_script/prelude/js.ex @@ -71,9 +71,9 @@ defmodule ElixirScript.JS do @doc """ - Returns a reference to the global object. + Returns a reference to the global JavaScript object. - In browsers this would be Window or WindowProxy. + In browsers this would be window or self. In node this would be the global object. """ def global() do From c95c72170f3b56469968cf92f80f0d2ea3cc6f04 Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Sat, 23 Jan 2016 17:22:37 -0600 Subject: [PATCH 129/860] Updated docs --- FAQ.md | 12 +----------- GettingStarted.md | 22 ++++++++++++++-------- 2 files changed, 15 insertions(+), 19 deletions(-) diff --git a/FAQ.md b/FAQ.md index dc1c7056..606ae41d 100644 --- a/FAQ.md +++ b/FAQ.md @@ -1,13 +1,5 @@ # FAQ -## Q. Why the `exjs` file extension instead of `ex` or `exs`? - -### A. Because you may reference JavaScript code in your ElixirScript modules that the Elixir compiler may not know about. - -For instance, if you are writing an ElixirScript module that references JQuery or React. Since the Elixir compiler won't know about the existence of these, you may end up with some compiler errors. The main purpose is to sort of hide it from the Elixir compiler. You can feed normal `.ex` files to the ElixirScript compiler and it can turn them into JavaScript however. - -In the future, the added file extension may not be needed as much as ElixirScript continues to support more of the Elixir standard library. An eventual goal would be to use standard `.ex` files in both Elixir and ElixirScript, while leaving `exjs` files strictly for JavaScript related code. - # Q. How much is implemented? ### A. Most of Kernel.SpecialForms as well as some modules in the Standard Library @@ -89,7 +81,7 @@ The compiler to this point has been focused on translating Kernel.SpecialForms a ### A. Yes, but don't expect it to be pretty or idiomatic. Also it is not production ready. -You **can** use ElixirScript on your front ends and have it work and interoperate with JavaScript modules. The problem is since most of the standard library is incomplete, it will not feel the same. It will feel like some basterdized hybrid of Elixir and JavaScript. That is not the goal of the project. The end goal is to have it look and feel like Elixir code with the added availability of JavaScript modules. +You **can** use ElixirScript on your front ends and have it work and interoperate with JavaScript modules. The problem is since most of the standard library is incomplete, it will not feel the same. It will feel like some weird hybrid of Elixir and JavaScript. That is not the goal of the project. The end goal is to have it look and feel like Elixir code with the added availability of JavaScript modules. ## Q. Can I use pattern matching? @@ -100,14 +92,12 @@ You **can** use ElixirScript on your front ends and have it work and interoperat ### A. No, but follow [this issue](https://github.com/bryanjos/elixirscript/issues/99). Any ideas or contributions are appreciated. - ## Q. Will it be able to do the things that Elm can? ### A. Maybe, but in an idiomatic fashion. One of my demos is an example of using a design similar to redux to accomplish the things that redux does only using the Elixir standard library. Redux is influenced by Elm. The goal is to eventually allow for designs that can be Elm influenced if that is the desire. Similar to the same way the José saya to bring the spirit of projects from other languages to Elixir and not always just a straight port. If processes are added, I believe it will be easier to do those things in an idiomatic Elixir way. - ## Q. What about OTP? ### A. Maybe. diff --git a/GettingStarted.md b/GettingStarted.md index 066e3934..6490122c 100644 --- a/GettingStarted.md +++ b/GettingStarted.md @@ -97,7 +97,7 @@ The intent of this guide is to get you started with ElixirScript. It will give y The first step is getting the dependency. In your mix.exs file for your elixir project, add elixir_script to your deps. ```elixir - {:elixir_script, "~> 0.13"} + {:elixir_script, "~> 0.14"} ``` * Step 2: Now download the dep @@ -121,7 +121,7 @@ The intent of this guide is to get you started with ElixirScript. It will give y The first step is getting the dependency. In your mix.exs file for your elixir project, add elixir_script to your deps. ```elixir - {:elixir_script, "~> 0.12"} + {:elixir_script, "~> 0.14"} ``` * Step 2: Now download the dep @@ -187,27 +187,33 @@ JS.import A, "a" #translates to "import {default as A} from 'a'" JS.import [A, B, C], "a" #translates to "import {A, B, C} from 'a'" ``` + +#### ElixirScript-Brunch + +There is an Brunch plugin, [ElixirScript-Brunch](https://www.npmjs.com/package/elixirscript-brunch). +There are instructions there on how to use it with Phoenix. + #### Gulp -I am a gulp user and I use elixirscript with gulp. Here is a snippet of how I my gulpfile looks +There is no gulp plugin just yet, but below is an example of how to make a gulp +task that will work with it. ```javascript var gulp = require('gulp'); var exec = require('child_process').exec; var babel = require('gulp-babel'); - //Calls out to the escript and places the output in src/js + //Calls out to the elixirscript compiler and places the output in src/js gulp.task('build-exjs', function(cb) { - exec('/usr/local/elixirscript/bin/elixirscript "' + exjsSrc + '" -o ' + "src/js", function (err, stdout, stderr) { + exec('elixirscript "' + exjsSrc + '" -o ' + "src/js", function (err, stdout, stderr) { cb(err); }); }); + // A task to turn the es6 output from build-exjs to es5 gulp.task('build-js', ['build-exjs'], function() { return gulp.src(jsSrc) - .pipe(babel({modules: 'system'})) + .pipe(babel()) .pipe(gulp.dest(jsDest)); }); ``` - -This is also the setup I use when using ElixirScript with Phoenix. If you are a brunch user, there is n [ElixirScript brunch plugin](https://www.npmjs.com/package/elixirscript-brunch) From a9c60c945446437e071b95e4496bd557e2c0f642 Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Sat, 23 Jan 2016 17:35:47 -0600 Subject: [PATCH 130/860] Updated cli help message --- lib/elixir_script/cli.ex | 2 +- lib/mix/tasks/elixirscript.ex | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/lib/elixir_script/cli.ex b/lib/elixir_script/cli.ex index 994ec567..9789b19f 100644 --- a/lib/elixir_script/cli.ex +++ b/lib/elixir_script/cli.ex @@ -37,7 +37,7 @@ defmodule ElixirScript.CLI do -o --output [path] places output at the given path -ex --elixir read input as elixir code string -r --root [path] root import path for all exported modules - -st --stdlib outputs the standard lib js file + -st --stdlib outputs the elixirscript core JavaScript file -stp --stdlib_path es6 import path to the elixirscript standard lib only used with the [output] option. When used, Elixir.js is not exported -h --help this message diff --git a/lib/mix/tasks/elixirscript.ex b/lib/mix/tasks/elixirscript.ex index 34e4cb5d..f787d17a 100644 --- a/lib/mix/tasks/elixirscript.ex +++ b/lib/mix/tasks/elixirscript.ex @@ -8,8 +8,8 @@ defmodule Mix.Tasks.Elixirscript do -o --output [path] places output at the given path -ex --elixir read input as elixir code string -r --root [path] root import path for all exported modules - -st --stdlib outputs the standard lib js file - -stp --stdlib_path es6 import path to the elixirscript standard lib + -st --stdlib outputs the elixirscript core JavaScript file + -stp --stdlib_path es6 import path to the elixirscript core JavaScript file only used with the [output] option. When used, elixir.js is not exported -h --help this message """ From 1185723f7fbc3b54330b090bfc2227081a988bfc Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Sun, 24 Jan 2016 11:24:07 -0600 Subject: [PATCH 131/860] Renamed stdlib compiler option to core and stdlib_path option to core_path. Fixed bug when getting module from the ast version of its name --- CHANGELOG.md | 2 ++ lib/elixir_script.ex | 12 ++++++------ lib/elixir_script/cli.ex | 20 ++++++++++---------- lib/elixir_script/translator/bitstring.ex | 1 - lib/elixir_script/translator/module.ex | 2 +- lib/elixir_script/translator/state.ex | 2 +- lib/mix/tasks/elixirscript.ex | 4 ++-- test/elixir_script_test.exs | 2 +- 8 files changed, 23 insertions(+), 22 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 8d37facc..41f9ceec 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -14,6 +14,8 @@ * Breaking * `compile`, `compile_path`, and `compile_quoted` opts parameter now expects a map + * The `stdlib` compiler option is now `core`. The `stdlib_path` compiler options is now + `core_path` # v0.14.1 * Enhancements diff --git a/lib/elixir_script.ex b/lib/elixir_script.ex index 9828e86a..c7d30e61 100644 --- a/lib/elixir_script.ex +++ b/lib/elixir_script.ex @@ -19,7 +19,7 @@ defmodule ElixirScript do or a tuple of the file name and the JavaScript code * `:root` - a binary path prepended to the path of the standard lib imports if needed * `:env` - a Macro.env struct to use. This is most useful when using macros. Make sure that the - * `:stdlib_path` - The es6 import path used to import the elixirscript standard lib. + * `:core_path` - The es6 import path used to import the elixirscript core. When using this option, the Elixir.js file is not exported """ @@ -103,7 +103,7 @@ defmodule ElixirScript do |> Map.put(:root, nil) |> Map.put(:env, custom_env) |> Map.put(:import_standard_libs, true) - |> Map.put(:stdlib_path, "Elixir") + |> Map.put(:core_path, "Elixir") Map.merge(default_options, opts) end @@ -179,17 +179,17 @@ defmodule ElixirScript do end @doc """ - Copies the javascript that makes up the ElixirScript standard libs + Copies the javascript that makes up the ElixirScript core to the specified location """ - def copy_standard_libs_to_destination(destination) do + def copy_core_to_destination(destination) do File.cp!(operating_path <> @js_core_path, destination <> @js_core_path) end @doc """ - Returns the standard lib js code + Returns the elixirscript core js code """ - def standard_libs() do + def elixirscript_core() do File.read!(operating_path <> @js_core_path) end diff --git a/lib/elixir_script/cli.ex b/lib/elixir_script/cli.ex index 9789b19f..40548fb4 100644 --- a/lib/elixir_script/cli.ex +++ b/lib/elixir_script/cli.ex @@ -3,11 +3,11 @@ defmodule ElixirScript.CLI do @switches [ output: :binary, elixir: :boolean, root: :binary, - help: :boolean, stdlib: :boolean, stdlib_path: :binary + help: :boolean, core: :boolean, core_path: :binary ] @aliases [ - o: :output, ex: :elixir, h: :help, r: :root, st: :stdlib, stp: :stdlib_path + o: :output, ex: :elixir, h: :help, r: :root ] def main(argv) do @@ -21,7 +21,7 @@ defmodule ElixirScript.CLI do case parse do { [help: true] , _ , _ } -> :help - { [stdlib: true] , _ , _ } -> :stdlib + { [core: true] , _ , _ } -> :core { options , [input], _ } -> { input, options } _ -> :help end @@ -37,15 +37,15 @@ defmodule ElixirScript.CLI do -o --output [path] places output at the given path -ex --elixir read input as elixir code string -r --root [path] root import path for all exported modules - -st --stdlib outputs the elixirscript core JavaScript file - -stp --stdlib_path es6 import path to the elixirscript standard lib + --core outputs the elixirscript core JavaScript file + --core_path es6 import path to the elixirscript standard lib only used with the [output] option. When used, Elixir.js is not exported -h --help this message """ end - def process(:stdlib) do - IO.write(ElixirScript.standard_libs) + def process(:core) do + IO.write(ElixirScript.elixirscript_core) end def process({ input, options }) do @@ -60,7 +60,7 @@ defmodule ElixirScript.CLI do compile_opts = %{ root: options[:root], include_path: true, - stdlib_path: Keyword.get(options, :stdlib_path, "Elixir") + core_path: Keyword.get(options, :core_path, "Elixir") } compile_output = case options[:elixir] do @@ -84,8 +84,8 @@ defmodule ElixirScript.CLI do write_to_file(x, output_path) end) - if options[:stdlib_path] == nil do - ElixirScript.copy_standard_libs_to_destination(output_path) + if options[:core_path] == nil do + ElixirScript.copy_core_to_destination(output_path) end end end diff --git a/lib/elixir_script/translator/bitstring.ex b/lib/elixir_script/translator/bitstring.ex index 19ea4ded..7e21cac3 100644 --- a/lib/elixir_script/translator/bitstring.ex +++ b/lib/elixir_script/translator/bitstring.ex @@ -2,7 +2,6 @@ defmodule ElixirScript.Translator.Bitstring do @moduledoc false alias ESTree.Tools.Builder, as: JS alias ElixirScript.Translator - alias ElixirScript.Translator.Primitive def make_bitstring(elements, env) do diff --git a/lib/elixir_script/translator/module.ex b/lib/elixir_script/translator/module.ex index c49313ab..480f21ef 100644 --- a/lib/elixir_script/translator/module.ex +++ b/lib/elixir_script/translator/module.ex @@ -175,7 +175,7 @@ defmodule ElixirScript.Translator.Module do compiler_opts = ElixirScript.Translator.State.get().compiler_opts case compiler_opts.import_standard_libs do true -> - [ElixirScript.Translator.Import.create_standard_lib_imports(compiler_opts.stdlib_path)] + [ElixirScript.Translator.Import.create_standard_lib_imports(compiler_opts.core_path)] false -> [] end diff --git a/lib/elixir_script/translator/state.ex b/lib/elixir_script/translator/state.ex index a4439630..2bed20e2 100644 --- a/lib/elixir_script/translator/state.ex +++ b/lib/elixir_script/translator/state.ex @@ -112,7 +112,7 @@ defmodule ElixirScript.Translator.State do end def get_module({:__aliases__, _, _} = name) do - do_get_module(name) + do_get_module(Utils.quoted_to_name(name)) end def get_module(module_name_list) when is_list(module_name_list) do diff --git a/lib/mix/tasks/elixirscript.ex b/lib/mix/tasks/elixirscript.ex index f787d17a..65eca9f9 100644 --- a/lib/mix/tasks/elixirscript.ex +++ b/lib/mix/tasks/elixirscript.ex @@ -8,8 +8,8 @@ defmodule Mix.Tasks.Elixirscript do -o --output [path] places output at the given path -ex --elixir read input as elixir code string -r --root [path] root import path for all exported modules - -st --stdlib outputs the elixirscript core JavaScript file - -stp --stdlib_path es6 import path to the elixirscript core JavaScript file + --core outputs the elixirscript core JavaScript file + --core_path es6 import path to the elixirscript standard lib only used with the [output] option. When used, elixir.js is not exported -h --help this message """ diff --git a/test/elixir_script_test.exs b/test/elixir_script_test.exs index 1c2d8f61..181b71f4 100644 --- a/test/elixir_script_test.exs +++ b/test/elixir_script_test.exs @@ -165,7 +165,7 @@ defmodule ElixirScript.Test do end end - """, %{ env: make_custom_env, stdlib_path: "elixirscript"} ) + """, %{ env: make_custom_env, core_path: "elixirscript"} ) assert_js_matches """ import Elixir from './elixirscript'; From 96c8fbd1e4e85de53889d8f1eb07640e9c0c1269 Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Sun, 24 Jan 2016 11:25:27 -0600 Subject: [PATCH 132/860] Fixed misspelling of Phoenix --- README.md | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/README.md b/README.md index e656cd9a..8de410e1 100644 --- a/README.md +++ b/README.md @@ -48,11 +48,10 @@ Please check the [CONTRIBUTING.md](CONTRIBUTING.md) ### Example projects -* [phoenix_chat_example](https://github.com/bryanjos/phoenix_chat_example) The Pheonix Chat App using ElixirScript. +* [phoenix_chat_example](https://github.com/bryanjos/phoenix_chat_example) The Phoenix Chat App using ElixirScript. * [MobileElixir](https://github.com/bryanjos/MobileElixir) Using ElixirScript with React Native * [color_bar_spike](https://github.com/bryanjos/color_bar_spike) A canvas drawing example using ElixirScript, React and a Redux-like design #### Using with Brunch There is a plugin for using ElixirScript in your Brunch project [here](https://www.npmjs.com/package/elixirscript-brunch) - From f10f7a98db6737a6af0f17ca96426b4089ea8ebb Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Sun, 24 Jan 2016 11:56:28 -0600 Subject: [PATCH 133/860] Updated changelog --- CHANGELOG.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 41f9ceec..f0789316 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,8 +3,8 @@ * `alias`, `require`, and `import` now work inside lexical scopes * `__ENV__` and `__CALLER__` are now supported * Some of the standard library originally written in JavaScript has been rewritten - in Elixir - * Added `JS.import/1`, `JS.typeof/1`,`JS.instanceof/1`, and JS.global/1 + in Elixir. + * Added `JS.import/1`, `JS.typeof/1`,`JS.instanceof/1`, and `JS.global/1` * Added support for multi alias/require/imports statements * Generated JavaScript export statements are now default exports * When output is sent to standard out, there are now markers to specify where From 16ce117996bd7f65e7080759c1147d53c025f105 Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Mon, 25 Jan 2016 17:20:49 -0600 Subject: [PATCH 134/860] Removed -dev from version --- CHANGELOG.md | 2 +- mix.exs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index f0789316..fbe9eda8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,4 +1,4 @@ -# v0.15.0-dev +# v0.15.0 * Enhancements * `alias`, `require`, and `import` now work inside lexical scopes * `__ENV__` and `__CALLER__` are now supported diff --git a/mix.exs b/mix.exs index 9e5ac309..8bd99567 100644 --- a/mix.exs +++ b/mix.exs @@ -4,7 +4,7 @@ defmodule ElixirScript.Mixfile do def project do [ app: :elixir_script, - version: "0.15.0-dev", + version: "0.15.0", elixir: "~> 1.0", escript: escript_config, deps: deps, From 4a058e66b9cb6f15ada5b5b7b16336f30b37d34a Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Wed, 27 Jan 2016 19:38:15 -0600 Subject: [PATCH 135/860] Added rewriter module with erlang function calls from kernel module --- lib/elixir_script/prelude/js.ex | 6 + lib/elixir_script/translator/js.ex | 5 + lib/elixir_script/translator/rewriter.ex | 302 +++++++++++++++++++++++ src/javascript/lib/core/bit_string.js | 7 +- src/javascript/lib/core/functions.js | 91 ++++++- src/javascript/lib/core/primitives.js | 6 + 6 files changed, 407 insertions(+), 10 deletions(-) create mode 100644 lib/elixir_script/translator/rewriter.ex diff --git a/lib/elixir_script/prelude/js.ex b/lib/elixir_script/prelude/js.ex index b8257975..4b7603fd 100644 --- a/lib/elixir_script/prelude/js.ex +++ b/lib/elixir_script/prelude/js.ex @@ -69,6 +69,12 @@ defmodule ElixirScript.JS do defmacro instanceof(value, type) do end + @doc """ + Throws the term given + """ + defmacro throw(term) do + end + @doc """ Returns a reference to the global JavaScript object. diff --git a/lib/elixir_script/translator/js.ex b/lib/elixir_script/translator/js.ex index bcde40a7..c6216b9c 100644 --- a/lib/elixir_script/translator/js.ex +++ b/lib/elixir_script/translator/js.ex @@ -26,6 +26,11 @@ defmodule ElixirScript.Translator.JS do ) end + defp do_translate({:throw, _, [term]}, env) do + Builder.throw_statement( + Translator.translate!(term, env) + ) + end defp do_translate({:new, _, [module_name, params]}, env) when not is_list(params) do Builder.new_expression( diff --git a/lib/elixir_script/translator/rewriter.ex b/lib/elixir_script/translator/rewriter.ex new file mode 100644 index 00000000..9b4e90cb --- /dev/null +++ b/lib/elixir_script/translator/rewriter.ex @@ -0,0 +1,302 @@ +defmodule ElixirScript.Translator.Rewriter do + + + def rewrite({{:., _, [:erlang, :abs]}, _, [number]}) do + quote do: Math.abs(unquote(number)) + end + + def rewrite({{:., _, [:erlang, :apply]}, _, [fun, args]}) do + quote do: unquote(fun).apply(nil, unquote(args)) + end + + def rewrite({{:., _, [:erlang, :apply]}, _, [module, fun, args]}) do + quote do: unquote(module).unquote(fun).apply(nil, unquote(args)) + end + + def rewrite({{:., _, [:erlang, :binary_part]}, _, [binary, start, length]})do + quote do: unquote(binary).substring(unquote(start), unquote(length)) + end + + def rewrite({{:., _, [:erlang, :bit_size]}, _, [bitstring]})do + quote do: unquote(bitstring).bit_size + end + + def rewrite({{:., _, [:erlang, :byte_size]}, _, [bitstring]})do + quote do: unquote(bitstring).byte_size + end + + def rewrite({{:., _, [:erlang, :div]}, _, [left, right]}) do + quote do: unquote(left) / unquote(right) + end + + def rewrite({{:., _, [:erlang, :exit]}, _, [reason]}) do + # TODO: implement exit + quote do: nil + end + + def rewrite({{:., _, [:erlang, :hd]}, _, [list]}) do + quote do: unquote(list)[0] + end + + def rewrite({{:., _, [:erlang, :is_atom]}, _, [term]}) do + quote do: JS.typeof(unquote(term)) === "symbol" + end + + def rewrite({{:., _, [:erlang, :is_binary]}, _, [term]}) do + quote do: JS.typeof(unquote(term)) === "string" + end + + def rewrite({{:., _, [:erlang, :is_bitstring]}, _, [term]}) do + quote do: is_binary(unquote(term)) || JS.instanceof(unquote(term), Elixir.Core.BitString) + end + + def rewrite({{:., _, [:erlang, :is_boolean]}, _, [term]}) do + quote do: JS.typeof(unquote(term)) === "boolean" || JS.instanceof(unquote(term), Boolean) + end + + def rewrite({{:., _, [:erlang, :is_float]}, _, [term]}) do + quote do: (JS.typeof(unquote(term)) === "number" || JS.instanceof(unquote(term, Number))) && !Number.isInteger(unquote(term)) + end + + def rewrite({{:., _, [:erlang, :is_function]}, _, [term]}) do + quote do: JS.typeof(unquote(term)) === "function" || JS.instanceof(unquote(term), Function) + end + + def rewrite({{:., _, [:erlang, :is_function]}, _, [term, _]}) do + quote do: JS.typeof(unquote(term)) === "function" || JS.instanceof(unquote(term), Function) + end + + def rewrite({{:., _, [:erlang, :is_integer]}, _, [term]}) do + quote do: Number.isInteger(unquote(term)) + end + + def rewrite({{:., _, [:erlang, :is_list]}, _, [term]}) do + quote do: Array.isArray(unquote(term)) + end + + def rewrite({{:., _, [:erlang, :is_number]}, _, [term]}) do + quote do: JS.typeof(unquote(term)) === "number" || JS.instanceof(unquote(term), Number) + end + + def rewrite({{:., _, [:erlang, :is_pid]}, _, [term]}) do + quote do: JS.instanceof(unquote(term), Elixir.Core.PID) + end + + def rewrite({{:., _, [:erlang, :is_port]}, _, [_term]}) do + #TODO implement is_port + quote do: false + end + + def rewrite({{:., _, [:erlang, :is_reference]}, _, [_term]}) do + #TODO implement is_reference + quote do: false + end + + def rewrite({{:., _, [:erlang, :is_tuple]}, _, [term]}) do + quote do: JS.instanceof(unquote(term), Elixir.Core.Tuple) + end + + def rewrite({{:., _, [:erlang, :is_map]}, _, [term]}) do + quote do: JS.typeof(unquote(term)) === "object" || JS.instanceof(unquote(term), Object) + end + + def rewrite({{:., _, [:erlang, :length]}, _, [list]}) do + quote do: unquote(list).length + end + + def rewrite({{:., _, [:erlang, :make_ref]}, _, []}) do + #TODO: implement make_ref + quote do: nil + end + + def rewrite({{:., _, [:erlang, :map_size]}, _, [map]}) do + quote do: Object.keys(unquote(map)).length + end + + def rewrite({{:., _, [:erlang, :max]}, _, [first, second]}) do + quote do: Math.max(unquote(first), unquote(second)) + end + + def rewrite({{:., _, [:erlang, :min]}, _, [first, second]}) do + quote do: Math.min(unquote(first), unquote(second)) + end + + def rewrite({{:., _, [:erlang, :node]}, _, []}) do + quote do: :nonode@nohost + end + + def rewrite({{:., _, [:erlang, :node]}, _, [_]}) do + quote do: :nonode@nohost + end + + def rewrite({{:., _, [:erlang, :rem]}, _, [first, second]}) do + {:%, [], [first, second]} + end + + def rewrite({{:., _, [:erlang, :round]}, _, [number]}) do + quote do: Math.round(unquote(number)) + end + + def rewrite({{:., _, [:erlang, :send]}, _, [dest, msg]}) do + #TODO implement send + quote do: unquote(msg) + end + + def rewrite({{:., _, [:erlang, :self]}, _, []}) do + #TODO: implement self + quote do: nil + end + + def rewrite({{:., _, [:erlang, :spawn]}, _, [_fun]}) do + #TODO: implement spawn + quote do: nil + end + + def rewrite({{:., _, [:erlang, :spawn]}, _, [_module, _fun, _args]}) do + #TODO: implement spawn + quote do: nil + end + + def rewrite({{:., _, [:erlang, :spawn_link]}, _, [_fun]}) do + #TODO: implement spawn_link + quote do: nil + end + + def rewrite({{:., _, [:erlang, :spawn_link]}, _, [_module, _fun, _args]}) do + #TODO: implement spawn_link + quote do: nil + end + + def rewrite({{:., _, [:erlang, :spawn_monitor]}, _, [_fun]}) do + #TODO: implement spawn_monitor + quote do: nil + end + + def rewrite({{:., _, [:erlang, :spawn_monitor]}, _, [_module, _fun, _args]}) do + #TODO: implement spawn_monitor + quote do: nil + end + + def rewrite({{:., _, [:erlang, :spawn_monitor]}, _, [_module, _fun, _args]}) do + #TODO: implement spawn_monitor + quote do: nil + end + + def rewrite({{:., _, [:erlang, :throw]}, _, [term]}) do + quote do: JS.throw(unquote(term)) + end + + def rewrite({{:., _, [:erlang, :tl]}, _, [list]}) do + quote do: unquote(list).splice(1) + end + + def rewrite({{:., _, [:erlang, :trunc]}, _, [number]}) do + quote do: Math.floor(unquote(number)) + end + + def rewrite({{:., _, [:erlang, :tuple_size]}, _, [tuple]}) do + quote do: unquote(tuple).length + end + + def rewrite({{:., _, [:erlang, operator]}, _, [left, right]}) when operator in [:+, :-, :*, :/, :<, :>, :>=, :==] do + {operator, [], [left, right]} + end + + def rewrite({{:., _, [:erlang, operator]}, _, [value]}) when operator in [:+, :-] do + {operator, [], [value]} + end + + def rewrite({{:., _, [:erlang, :++]}, _, [left, right]}) do + quote do: unquote(left).concat(unquote(right)) + end + + def rewrite({{:., _, [:erlang, :--]}, _, [list, element]}) do + quote do: unquote(list).slice(unquote(list).indexOf(unquote(element)) + 1) + end + + def rewrite({{:., _, [:erlang, :not]}, _, [value]}) do + {:!, [], [value]} + end + + def rewrite({{:., _, [:erlang, :"=<"]}, _, [left, right]}) do + {:<=, [], [left, right]} + end + + def rewrite({{:., _, [:erlang, :"/="]}, _, [left, right]}) do + {:!=, [], [left, right]} + end + + def rewrite({{:., _, [:erlang, :"=:="]}, _, [left, right]}) do + {:===, [], [left, right]} + end + + def rewrite({{:., _, [:erlang, :"=/="]}, _, [left, right]}) do + {:!==, [], [left, right]} + end + + def rewrite({{:., _, [:erlang, :element]}, _, [index, tuple]}) do + quote do: unquote(tuple).get(unquote(index) - 1) + end + + def rewrite({{:., _, [:erlang, :setelement]}, _, [index, tuple, value]}) do + quote do: unquote(tuple).put_elem(unquote(index) - 1, unquote(value)) + end + + def rewrite({{:., _, [:erlang, :orelse]}, _, [left, right]}) do + {:||, [], [left, right]} + end + + def rewrite({{:., _, [:erlang, :andalso]}, _, [left, right]}) do + {:&&, [], [left, right]} + end + + def rewrite({{:., _, [:erlang, :error]}, _, [error]}) do + quote do: JS.throw(unquote(error)) + end + + def rewrite({{:., _, [:erlang, :raise]}, _, [_class, reason, _stacktrace]}) do + quote do: JS.throw(unquote(reason)) + end + + def rewrite({{:., _, [:lists, :map]}, _, [fun, list]}) do + quote do: unquote(list).map(unquote(fun)) + end + + def rewrite({{:., _, [:lists, :member]}, _, [elem, list]}) do + quote do: unquote(list).indexOf(unquote(elem)) > -1 + end + + def rewrite({{:., _, [:lists, :foldl]}, _, [fun, acc, list]}) do + quote do: Elixir.Core.Functions.foldl(unquote(fun), unquote(acc), unquote(list)) + end + + def rewrite({{:., _, [:lists, :foldr]}, _, [fun, acc, list]}) do + quote do: Elixir.Core.Functions.foldr(unquote(fun), unquote(acc), unquote(list)) + end + + def rewrite({{:., _, [:lists, :keydelete]}, _, [key, n, list]}) do + quote do: Elixir.Core.Functions.keydelete(unquote(key), unquote(n), unquote(list)) + end + + def rewrite({{:., _, [:lists, :keystore]}, _, [key, n, list, newtuple]}) do + quote do: Elixir.Core.Functions.keymember(unquote(key), unquote(n), unquote(list), unquote(newtuple)) + end + + def rewrite({{:., _, [:lists, :reverse]}, _, [list]}) do + quote do: Elixir.Core.Functions.reverse(unquote(list)) + end + + def rewrite({{:., _, [:maps, :is_key]}, _, [key, map]}) do + quote do: unquote(key) in Elixir.Core.Functions.get_object_keys(unquote(map)) + end + + def rewrite({{:., _, [:maps, :put]}, _, [key, value, map]}) do + quote do: Elixir.Core.Functions.add_property_to_map(unquote(map), unquote(key), unquote(value)) + end + + def rewrite({{:., _, [:maps, :update]}, _, [key, value, map]}) do + quote do: Elixir.Core.Functions.update_map(unquote(map), unquote(key), unquote(value)) + end + + +end diff --git a/src/javascript/lib/core/bit_string.js b/src/javascript/lib/core/bit_string.js index 16e7d268..ac01f377 100644 --- a/src/javascript/lib/core/bit_string.js +++ b/src/javascript/lib/core/bit_string.js @@ -5,6 +5,9 @@ class BitString { }; this.value = Object.freeze(this.process(args)); + this.length = this.value.length; + this.bit_size = this.raw_value.reduce((prev, current) => prev + current.size); + this.byte_size = (this.bit_size / 8) + (this.bit_size % 8 > 0 ? 1 : 0); } get(index){ @@ -119,7 +122,7 @@ class BitString { } static bitstring(value){ - return BitString.wrap(value, { 'type': 'bitstring', 'unit': 1, 'size': value.length }); + return BitString.wrap(value, { 'type': 'bitstring', 'unit': 1, 'size': value.bit_size }); } static bits(value){ @@ -127,7 +130,7 @@ class BitString { } static binary(value){ - return BitString.wrap(value, { 'type': 'binary', 'unit': 8, 'size': value.length}); + return BitString.wrap(value, { 'type': 'binary', 'unit': 8, 'size': value.length }); } static bytes(value){ diff --git a/src/javascript/lib/core/functions.js b/src/javascript/lib/core/functions.js index 500ab6e6..71b6ea56 100644 --- a/src/javascript/lib/core/functions.js +++ b/src/javascript/lib/core/functions.js @@ -7,7 +7,7 @@ function call_property(item, property){ let prop = null; if(property in item){ - prop = property + prop = property; }else if(Symbol.for(property) in item){ prop = Symbol.for(property); }else{ @@ -62,7 +62,7 @@ function defstruct(defaults){ let x = new this(updates); return Object.freeze(x); } - } + }; } @@ -85,7 +85,7 @@ function defexception(defaults){ let x = new this(updates); return Object.freeze(x); } - } + }; } function defprotocol(spec){ @@ -97,7 +97,7 @@ function defimpl(protocol, type, impl){ } function get_object_keys(obj){ - return Object.keys(obj).concat(Object.getOwnPropertySymbols(obj)) + return Object.keys(obj).concat(Object.getOwnPropertySymbols(obj)); } function is_valid_character(codepoint){ @@ -116,14 +116,14 @@ function b64EncodeUnicode(str) { } function delete_property_from_map(map, property){ - let new_map = Object.assign(Object.create(map.constructor.prototype), map) - delete new_map[property] + let new_map = Object.assign(Object.create(map.constructor.prototype), map); + delete new_map[property]; return Object.freeze(new_map); } function class_to_obj(map){ - let new_map = Object.assign({}, map) + let new_map = Object.assign({}, map); return Object.freeze(new_map); } @@ -133,6 +133,15 @@ function add_property_to_map(map, property, value){ return Object.freeze(new_map); } + +function update_map(map, property, value){ + if(property in get_object_keys(map)){ + return add_property_to_map(map, property, value); + } + + throw "map does not have key"; +} + function bnot(expr){ return ~expr; } @@ -192,6 +201,65 @@ function can_decode64(data) { } } +function remove_from_list(list, element){ + let found = false; + + return list.filter((elem) => { + if(!found && elem === element){ + found = true; + return false; + } + + return true; + }); +} + +function foldl(fun, acc, list){ + let acc1 = acc; + + for(const el of list){ + acc1 = fun(el, acc1); + } + + return acc1; +} + + +function foldr(fun, acc, list){ + let acc1 = acc; + + for(let i = list.length - 1; i >= 0; i--){ + acc1 = fun(list[i], acc1); + } + + return acc1; +} + +function keydelete(key, n, tuplelist){ + + for(let i = tuplelist.length - 1; i >= 0; i--){ + if(tuplelist[i].get(n) === key){ + return tuplelist.concat([]).splice(i, 1); + } + } + + return tuplelist; +} + +function keystore(key, n, list, newtuple){ + for(let i = list.length - 1; i >= 0; i--){ + if(list[i].get(n) === key){ + return list.concat([]).splice(i, 1, newtuple); + } + } + + return list; +} + +function reverse(list){ + return list.concat([]).reverse(); +} + export default { call_property, apply, @@ -214,5 +282,12 @@ export default { bsl, bsr, bxor, - zip + zip, + foldl, + foldr, + remove_from_list, + keydelete, + keystore, + reverse, + update_map }; diff --git a/src/javascript/lib/core/primitives.js b/src/javascript/lib/core/primitives.js index 2521eb63..239759ef 100644 --- a/src/javascript/lib/core/primitives.js +++ b/src/javascript/lib/core/primitives.js @@ -29,6 +29,12 @@ class Tuple { return "{" + s + "}"; } + put_elem(index, elem){ + let new_values = this.values.concat([]); + new_values.splice(index, 0, elem); + return new Tuple(...new_values); + } + } From c1c253f56bde927ec8c5cef82d2679ee9b45ab5a Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Sat, 30 Jan 2016 17:19:24 -0600 Subject: [PATCH 136/860] Update GettingStarted.md --- GettingStarted.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/GettingStarted.md b/GettingStarted.md index 6490122c..698cec52 100644 --- a/GettingStarted.md +++ b/GettingStarted.md @@ -97,7 +97,7 @@ The intent of this guide is to get you started with ElixirScript. It will give y The first step is getting the dependency. In your mix.exs file for your elixir project, add elixir_script to your deps. ```elixir - {:elixir_script, "~> 0.14"} + {:elixir_script, "~> 0.15"} ``` * Step 2: Now download the dep @@ -121,7 +121,7 @@ The intent of this guide is to get you started with ElixirScript. It will give y The first step is getting the dependency. In your mix.exs file for your elixir project, add elixir_script to your deps. ```elixir - {:elixir_script, "~> 0.14"} + {:elixir_script, "~> 0.15"} ``` * Step 2: Now download the dep From 6fedcd6d8d3001126ede91875bc775584d1a57a4 Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Sat, 30 Jan 2016 17:20:05 -0600 Subject: [PATCH 137/860] Update GettingStarted.md --- GettingStarted.md | 38 +++++++++++++++++++------------------- 1 file changed, 19 insertions(+), 19 deletions(-) diff --git a/GettingStarted.md b/GettingStarted.md index 698cec52..83547ef7 100644 --- a/GettingStarted.md +++ b/GettingStarted.md @@ -198,22 +198,22 @@ There are instructions there on how to use it with Phoenix. There is no gulp plugin just yet, but below is an example of how to make a gulp task that will work with it. - ```javascript - var gulp = require('gulp'); - var exec = require('child_process').exec; - var babel = require('gulp-babel'); - - //Calls out to the elixirscript compiler and places the output in src/js - gulp.task('build-exjs', function(cb) { - exec('elixirscript "' + exjsSrc + '" -o ' + "src/js", function (err, stdout, stderr) { - cb(err); - }); - }); - - // A task to turn the es6 output from build-exjs to es5 - gulp.task('build-js', ['build-exjs'], function() { - return gulp.src(jsSrc) - .pipe(babel()) - .pipe(gulp.dest(jsDest)); - }); - ``` + ```javascript + var gulp = require('gulp'); + var exec = require('child_process').exec; + var babel = require('gulp-babel'); + + //Calls out to the elixirscript compiler and places the output in src/js + gulp.task('build-exjs', function(cb) { + exec('elixirscript "' + exjsSrc + '" -o ' + "src/js", function (err, stdout, stderr) { + cb(err); + }); + }); + + // A task to turn the es6 output from build-exjs to es5 + gulp.task('build-js', ['build-exjs'], function() { + return gulp.src(jsSrc) + .pipe(babel()) + .pipe(gulp.dest(jsDest)); + }); + ``` From 5ffbfd9b49917f1fa697b2d7da49c4c9b5c0fbb3 Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Sat, 30 Jan 2016 17:20:29 -0600 Subject: [PATCH 138/860] Update GettingStarted.md --- GettingStarted.md | 38 +++++++++++++++++++------------------- 1 file changed, 19 insertions(+), 19 deletions(-) diff --git a/GettingStarted.md b/GettingStarted.md index 83547ef7..751116f1 100644 --- a/GettingStarted.md +++ b/GettingStarted.md @@ -198,22 +198,22 @@ There are instructions there on how to use it with Phoenix. There is no gulp plugin just yet, but below is an example of how to make a gulp task that will work with it. - ```javascript - var gulp = require('gulp'); - var exec = require('child_process').exec; - var babel = require('gulp-babel'); - - //Calls out to the elixirscript compiler and places the output in src/js - gulp.task('build-exjs', function(cb) { - exec('elixirscript "' + exjsSrc + '" -o ' + "src/js", function (err, stdout, stderr) { - cb(err); - }); - }); - - // A task to turn the es6 output from build-exjs to es5 - gulp.task('build-js', ['build-exjs'], function() { - return gulp.src(jsSrc) - .pipe(babel()) - .pipe(gulp.dest(jsDest)); - }); - ``` +```javascript +var gulp = require('gulp'); +var exec = require('child_process').exec; +var babel = require('gulp-babel'); + +//Calls out to the elixirscript compiler and places the output in src/js +gulp.task('build-exjs', function(cb) { + exec('elixirscript "' + exjsSrc + '" -o ' + "src/js", function (err, stdout, stderr) { + cb(err); + }); +}); + +// A task to turn the es6 output from build-exjs to es5 +gulp.task('build-js', ['build-exjs'], function() { + return gulp.src(jsSrc) + .pipe(babel()) + .pipe(gulp.dest(jsDest)); +}); +``` From fa9683e998155d3d2aecfa413216cc6176d2f725 Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Thu, 4 Feb 2016 23:57:56 -0600 Subject: [PATCH 139/860] Fixed bug where defstruct with a list of atoms failed --- CHANGELOG.md | 2 + lib/elixir_script.ex | 4 +- lib/elixir_script/translator.ex | 6 ++ lib/elixir_script/translator/env.ex | 3 +- lib/elixir_script/translator/rewriter.ex | 56 ++++++++++++-- lib/elixir_script/translator/state.ex | 4 + lib/elixir_script/translator/struct.ex | 16 ++-- mix.exs | 4 +- mix.lock | 8 +- priv/Elixir.js | 97 +++++++++++++++++++++++- src/javascript/elixir.js | 2 +- src/javascript/lib/core/functions.js | 11 ++- test/translator/struct_test.exs | 2 +- 13 files changed, 189 insertions(+), 26 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index fbe9eda8..28192d1c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,5 @@ +# v0.16.0-dev + # v0.15.0 * Enhancements * `alias`, `require`, and `import` now work inside lexical scopes diff --git a/lib/elixir_script.ex b/lib/elixir_script.ex index c7d30e61..d518e8cf 100644 --- a/lib/elixir_script.ex +++ b/lib/elixir_script.ex @@ -42,7 +42,7 @@ defmodule ElixirScript do @external_resource libs_path = Path.join([__DIR__, "elixir_script", "prelude", "**", "*.ex"]) @libs Enum.filter(Path.wildcard(libs_path), fn(path) -> - !String.contains?(path, @modules_to_not_read) + !String.contains?(path, @modules_to_not_read) end) |> Enum.map(fn(path) -> path @@ -147,7 +147,7 @@ defmodule ElixirScript do compiler_opts.import_standard_libs == false && ast.name in standard_lib_modules end) |> Enum.map(fn ast -> - spawn_link fn -> + spawn_link fn -> env = ElixirScript.Translator.Env.module_env(ast.name, Utils.name_to_js_file_name(ast.name) <> ".js") module = case ast.type do diff --git a/lib/elixir_script/translator.ex b/lib/elixir_script/translator.ex index 56b3ae7c..7740862f 100644 --- a/lib/elixir_script/translator.ex +++ b/lib/elixir_script/translator.ex @@ -21,6 +21,7 @@ defmodule ElixirScript.Translator do alias ElixirScript.Translator.Utils alias ElixirScript.Translator.JS, as: JSLib alias ESTree.Tools.Builder, as: JS + alias ElixirScript.Translator.Rewriter @@ -185,6 +186,11 @@ defmodule ElixirScript.Translator do end end + defp do_translate({{:., _, [erlang_module, _]}, _, _} = erlang_function_call, env) when erlang_module in [:erlang, :maps, :lists] do + Rewriter.rewrite(erlang_function_call) + |> translate(env) + end + defp do_translate({{:., _, [Access, :get]}, _, [target, property]}, env) do { Map.make_get_property(target, property, env), env } end diff --git a/lib/elixir_script/translator/env.ex b/lib/elixir_script/translator/env.ex index dce9b7af..e27719cc 100644 --- a/lib/elixir_script/translator/env.ex +++ b/lib/elixir_script/translator/env.ex @@ -83,7 +83,8 @@ defmodule ElixirScript.Translator.Env do end defp get_module(env, module_name) do - module = ElixirScript.Translator.State.get_module(module_name) + module = get_module_name(env, module_name) |> + ElixirScript.Translator.State.get_module unless module do raise "Module #{module_name} not found" diff --git a/lib/elixir_script/translator/rewriter.ex b/lib/elixir_script/translator/rewriter.ex index 9b4e90cb..6f9ed6b5 100644 --- a/lib/elixir_script/translator/rewriter.ex +++ b/lib/elixir_script/translator/rewriter.ex @@ -1,5 +1,13 @@ defmodule ElixirScript.Translator.Rewriter do + # :erlang, :lists, :maps, :beam_lib, :binary, :calendar, :digraph, + # :epp, :erl_lint, :erl_internal, :erl_expand_records, :erl_eval, + # :ets, :filename, :gen_event, :gen_server, :io, :io_lib, :math, + # :ordsets, :proc_lib, :rand, :re, :sets, :supervisor,:sys, :timer, + # :unicode, :os, :application, :code, :gen_tcp, :error_logger, :gen, + # :file + # http://erlang.org/doc/applications.html + def rewrite({{:., _, [:erlang, :abs]}, _, [number]}) do quote do: Math.abs(unquote(number)) @@ -55,7 +63,7 @@ defmodule ElixirScript.Translator.Rewriter do end def rewrite({{:., _, [:erlang, :is_float]}, _, [term]}) do - quote do: (JS.typeof(unquote(term)) === "number" || JS.instanceof(unquote(term, Number))) && !Number.isInteger(unquote(term)) + quote do: (JS.typeof(unquote(term)) === "number" || JS.instanceof(unquote(term), Number)) && !Number.isInteger(unquote(term)) end def rewrite({{:., _, [:erlang, :is_function]}, _, [term]}) do @@ -177,11 +185,6 @@ defmodule ElixirScript.Translator.Rewriter do quote do: nil end - def rewrite({{:., _, [:erlang, :spawn_monitor]}, _, [_module, _fun, _args]}) do - #TODO: implement spawn_monitor - quote do: nil - end - def rewrite({{:., _, [:erlang, :throw]}, _, [term]}) do quote do: JS.throw(unquote(term)) end @@ -258,6 +261,43 @@ defmodule ElixirScript.Translator.Rewriter do quote do: JS.throw(unquote(reason)) end + def rewrite({{:., _, [:erlang, :atom_to_binary]}, _, [atom, _]}) do + quote do: Symbol.keyFor(unquote(atom)) + end + + def rewrite({{:., _, [:erlang, :atom_to_list]}, _, [atom]}) do + quote do: to_string(unquote(atom)).split("") + end + + def rewrite({{:., _, [:erlang, :bnot]}, _, [expr]}) do + {:"~", [], [expr]} + end + + def rewrite({{:., _, [:erlang, :band]}, _, [left, right]}) do + {:&, [], [left, right]} + end + + def rewrite({{:., _, [:erlang, :bor]}, _, [left, right]}) do + {:|, [], [left, right]} + end + + def rewrite({{:., _, [:erlang, :bxor]}, _, [left, right]}) do + {:^, [], [left, right]} + end + + def rewrite({{:., _, [:erlang, :bsl]}, _, [left, right]}) do + {:"<<", [], [left, right]} + end + + def rewrite({{:., _, [:erlang, :bsr]}, _, [left, right]}) do + {:">>", [], [left, right]} + end + + def rewrite({{:., _, [:erlang, :function_exported]}, _, [_, _, _]}) do + quote do: true + end + + def rewrite({{:., _, [:lists, :map]}, _, [fun, list]}) do quote do: unquote(list).map(unquote(fun)) end @@ -298,5 +338,9 @@ defmodule ElixirScript.Translator.Rewriter do quote do: Elixir.Core.Functions.update_map(unquote(map), unquote(key), unquote(value)) end + def rewrite({{:., _, [:maps, :find]}, _, [key, map]}) do + quote do: Elixir.Core.Functions.maps_find(unquote(key), unquote(map)) + end + end diff --git a/lib/elixir_script/translator/state.ex b/lib/elixir_script/translator/state.ex index 2bed20e2..ccd4a635 100644 --- a/lib/elixir_script/translator/state.ex +++ b/lib/elixir_script/translator/state.ex @@ -91,6 +91,10 @@ defmodule ElixirScript.Translator.State do Agent.get(__MODULE__, &(&1)) end + def get_module_name({:__aliases__, _, _} = name) do + get_module_name(Utils.quoted_to_name(name)) + end + def get_module_name(module_name) do Agent.get(__MODULE__, fn(state) -> do_get_module_name(module_name, state) diff --git a/lib/elixir_script/translator/struct.ex b/lib/elixir_script/translator/struct.ex index b41b6783..e575653f 100644 --- a/lib/elixir_script/translator/struct.ex +++ b/lib/elixir_script/translator/struct.ex @@ -36,11 +36,17 @@ defmodule ElixirScript.Translator.Struct do def make_defstruct(attributes, env) when length(attributes) == 1 do attributes = Enum.flat_map(attributes, fn(x) -> x end) - defaults = Enum.map(attributes, fn({x, y}) -> - Map.make_property( - Translator.translate!(x, env), - Translator.translate!(y, env) - ) + defaults = Enum.map(attributes, fn + ({x, y}) -> + Map.make_property( + Translator.translate!(x, env), + Translator.translate!(y, env) + ) + (attribute) -> + Map.make_property( + Translator.translate!(attribute, env), + Translator.translate!(nil, env) + ) end) |> JS.object_expression diff --git a/mix.exs b/mix.exs index 8bd99567..3bbfc4fd 100644 --- a/mix.exs +++ b/mix.exs @@ -4,7 +4,7 @@ defmodule ElixirScript.Mixfile do def project do [ app: :elixir_script, - version: "0.15.0", + version: "0.16.0-dev", elixir: "~> 1.0", escript: escript_config, deps: deps, @@ -28,7 +28,7 @@ defmodule ElixirScript.Mixfile do defp deps do [ - {:estree, "~> 2.0"}, + {:estree, "~> 2.2"}, {:earmark, "~> 0.2", only: :dev }, {:ex_doc, "~> 0.11", only: :dev }, {:excoveralls, "~> 0.4", only: :test}, diff --git a/mix.lock b/mix.lock index 74ef82f2..4c01630a 100644 --- a/mix.lock +++ b/mix.lock @@ -3,10 +3,10 @@ "certifi": {:hex, :certifi, "0.3.0"}, "credo": {:hex, :credo, "0.2.5"}, "dogma": {:hex, :dogma, "0.0.7"}, - "earmark": {:hex, :earmark, "0.2.0"}, - "estree": {:hex, :estree, "2.1.2"}, - "ex_doc": {:hex, :ex_doc, "0.11.3"}, - "excoveralls": {:hex, :excoveralls, "0.4.3"}, + "earmark": {:hex, :earmark, "0.2.1"}, + "estree": {:hex, :estree, "2.2.0"}, + "ex_doc": {:hex, :ex_doc, "0.11.4"}, + "excoveralls": {:hex, :excoveralls, "0.4.5"}, "exjsx": {:hex, :exjsx, "3.2.0"}, "hackney": {:hex, :hackney, "1.4.8"}, "idna": {:hex, :idna, "1.0.3"}, diff --git a/priv/Elixir.js b/priv/Elixir.js index 3f4aa734..b15eaf4b 100644 --- a/priv/Elixir.js +++ b/priv/Elixir.js @@ -1689,6 +1689,12 @@ class Tuple { return "{" + s + "}"; } + put_elem(index, elem) { + let new_values = this.values.concat([]); + new_values.splice(index, 0, elem); + return new Tuple(...new_values); + } + } let process_counter = -1; @@ -1862,6 +1868,9 @@ class BitString { }; this.value = Object.freeze(this.process(args)); + this.length = this.value.length; + this.bit_size = this.raw_value.reduce((prev, current) => prev + current.size); + this.byte_size = this.bit_size / 8 + (this.bit_size % 8 > 0 ? 1 : 0); } get(index) { @@ -1977,7 +1986,7 @@ class BitString { } static bitstring(value) { - return BitString.wrap(value, { "type": "bitstring", "unit": 1, "size": value.length }); + return BitString.wrap(value, { "type": "bitstring", "unit": 1, "size": value.bit_size }); } static bits(value) { @@ -2794,6 +2803,14 @@ function add_property_to_map(map, property, value) { return Object.freeze(new_map); } +function update_map(map, property, value) { + if (property in get_object_keys(map)) { + return add_property_to_map(map, property, value); + } + + throw 'map does not have key'; +} + function bnot(expr) { return ~expr; } @@ -2853,6 +2870,72 @@ function can_decode64(data) { } } +function remove_from_list(list, element) { + let found = false; + + return list.filter(elem => { + if (!found && elem === element) { + found = true; + return false; + } + + return true; + }); +} + +function foldl(fun, acc, list) { + let acc1 = acc; + + for (const el of list) { + acc1 = fun(el, acc1); + } + + return acc1; +} + +function foldr(fun, acc, list) { + let acc1 = acc; + + for (let i = list.length - 1; i >= 0; i--) { + acc1 = fun(list[i], acc1); + } + + return acc1; +} + +function keydelete(key, n, tuplelist) { + + for (let i = tuplelist.length - 1; i >= 0; i--) { + if (tuplelist[i].get(n) === key) { + return tuplelist.concat([]).splice(i, 1); + } + } + + return tuplelist; +} + +function keystore(key, n, list, newtuple) { + for (let i = list.length - 1; i >= 0; i--) { + if (list[i].get(n) === key) { + return list.concat([]).splice(i, 1, newtuple); + } + } + + return list; +} + +function reverse(list) { + return list.concat([]).reverse(); +} + +function maps_find(key, map) { + if (key in get_object_keys(map)) { + return new Tuple(Symbol.for('ok'), map[key]); + } else { + return Symbol.for('error'); + } +} + var Functions = { call_property, apply, @@ -2875,7 +2958,15 @@ var Functions = { bsl, bsr, bxor, - zip + zip, + foldl, + foldr, + remove_from_list, + keydelete, + keystore, + reverse, + update_map, + maps_find }; function _case(condition, clauses) { @@ -3207,4 +3298,4 @@ var Elixir = { }; export default Elixir; -//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiIiwic291cmNlcyI6WyJFbGl4aXIuanMiXSwic291cmNlc0NvbnRlbnQiOlsibGV0IFZpcnR1YWxET00gPSAoZnVuY3Rpb24gKGUpIHtcbiAgICByZXR1cm4gZSgpO1xufSkoZnVuY3Rpb24gKCkge1xuICAgIHZhciBkZWZpbmUsIG1vZHVsZSwgZXhwb3J0cztcbiAgICByZXR1cm4gKGZ1bmN0aW9uIGUodCwgbiwgcikge1xuICAgICAgICBmdW5jdGlvbiBzKG8sIHUpIHtcbiAgICAgICAgICAgIGlmICghbltvXSkge1xuICAgICAgICAgICAgICAgIGlmICghdFtvXSkge1xuICAgICAgICAgICAgICAgICAgICB2YXIgYSA9IHR5cGVvZiByZXF1aXJlID09IFwiZnVuY3Rpb25cIiAmJiByZXF1aXJlO1xuICAgICAgICAgICAgICAgICAgICBpZiAoIXUgJiYgYSkgcmV0dXJuIGEobywgITApO1xuICAgICAgICAgICAgICAgICAgICBpZiAoaSkgcmV0dXJuIGkobywgITApO1xuICAgICAgICAgICAgICAgICAgICB2YXIgZiA9IG5ldyBFcnJvcihcIkNhbm5vdCBmaW5kIG1vZHVsZSAnXCIgKyBvICsgXCInXCIpO1xuICAgICAgICAgICAgICAgICAgICB0aHJvdyAoZi5jb2RlID0gXCJNT0RVTEVfTk9UX0ZPVU5EXCIsIGYpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB2YXIgbCA9IG5bb10gPSB7XG4gICAgICAgICAgICAgICAgICAgIGV4cG9ydHM6IHt9XG4gICAgICAgICAgICAgICAgfTtcbiAgICAgICAgICAgICAgICB0W29dWzBdLmNhbGwobC5leHBvcnRzLCBmdW5jdGlvbiAoZSkge1xuICAgICAgICAgICAgICAgICAgICB2YXIgbiA9IHRbb11bMV1bZV07XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBzKG4gPyBuIDogZSk7XG4gICAgICAgICAgICAgICAgfSwgbCwgbC5leHBvcnRzLCBlLCB0LCBuLCByKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJldHVybiBuW29dLmV4cG9ydHM7XG4gICAgICAgIH1cbiAgICAgICAgdmFyIGkgPSB0eXBlb2YgcmVxdWlyZSA9PSBcImZ1bmN0aW9uXCIgJiYgcmVxdWlyZTtcbiAgICAgICAgZm9yICh2YXIgbyA9IDA7IG8gPCByLmxlbmd0aDsgbysrKSBzKHJbb10pO1xuICAgICAgICByZXR1cm4gcztcbiAgICB9KSh7XG4gICAgICAgIDE6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG5cbiAgICAgICAgICAgIHZhciBjcmVhdGVFbGVtZW50ID0gcmVxdWlyZShcIi4vdmRvbS9jcmVhdGUtZWxlbWVudC5qc1wiKTtcblxuICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBjcmVhdGVFbGVtZW50O1xuICAgICAgICB9LCB7IFwiLi92ZG9tL2NyZWF0ZS1lbGVtZW50LmpzXCI6IDE1IH1dLCAyOiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge1xuICAgICAgICAgICAgdmFyIGRpZmYgPSByZXF1aXJlKFwiLi92dHJlZS9kaWZmLmpzXCIpO1xuXG4gICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IGRpZmY7XG4gICAgICAgIH0sIHsgXCIuL3Z0cmVlL2RpZmYuanNcIjogMzUgfV0sIDM6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICB2YXIgaCA9IHJlcXVpcmUoXCIuL3ZpcnR1YWwtaHlwZXJzY3JpcHQvaW5kZXguanNcIik7XG5cbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gaDtcbiAgICAgICAgfSwgeyBcIi4vdmlydHVhbC1oeXBlcnNjcmlwdC9pbmRleC5qc1wiOiAyMiB9XSwgNDogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHtcbiAgICAgICAgICAgIHZhciBkaWZmID0gcmVxdWlyZShcIi4vZGlmZi5qc1wiKTtcbiAgICAgICAgICAgIHZhciBwYXRjaCA9IHJlcXVpcmUoXCIuL3BhdGNoLmpzXCIpO1xuICAgICAgICAgICAgdmFyIGggPSByZXF1aXJlKFwiLi9oLmpzXCIpO1xuICAgICAgICAgICAgdmFyIGNyZWF0ZSA9IHJlcXVpcmUoXCIuL2NyZWF0ZS1lbGVtZW50LmpzXCIpO1xuICAgICAgICAgICAgdmFyIFZOb2RlID0gcmVxdWlyZShcIi4vdm5vZGUvdm5vZGUuanNcIik7XG4gICAgICAgICAgICB2YXIgVlRleHQgPSByZXF1aXJlKFwiLi92bm9kZS92dGV4dC5qc1wiKTtcblxuICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSB7XG4gICAgICAgICAgICAgICAgZGlmZjogZGlmZixcbiAgICAgICAgICAgICAgICBwYXRjaDogcGF0Y2gsXG4gICAgICAgICAgICAgICAgaDogaCxcbiAgICAgICAgICAgICAgICBjcmVhdGU6IGNyZWF0ZSxcbiAgICAgICAgICAgICAgICBWTm9kZTogVk5vZGUsXG4gICAgICAgICAgICAgICAgVlRleHQ6IFZUZXh0XG4gICAgICAgICAgICB9O1xuICAgICAgICB9LCB7IFwiLi9jcmVhdGUtZWxlbWVudC5qc1wiOiAxLCBcIi4vZGlmZi5qc1wiOiAyLCBcIi4vaC5qc1wiOiAzLCBcIi4vcGF0Y2guanNcIjogMTMsIFwiLi92bm9kZS92bm9kZS5qc1wiOiAzMSwgXCIuL3Zub2RlL3Z0ZXh0LmpzXCI6IDMzIH1dLCA1OiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge1xuICAgICAgICAgICAgLyohXG4gICAgICAgICAgICAgKiBDcm9zcy1Ccm93c2VyIFNwbGl0IDEuMS4xXG4gICAgICAgICAgICAgKiBDb3B5cmlnaHQgMjAwNy0yMDEyIFN0ZXZlbiBMZXZpdGhhbiA8c3RldmVubGV2aXRoYW4uY29tPlxuICAgICAgICAgICAgICogQXZhaWxhYmxlIHVuZGVyIHRoZSBNSVQgTGljZW5zZVxuICAgICAgICAgICAgICogRUNNQVNjcmlwdCBjb21wbGlhbnQsIHVuaWZvcm0gY3Jvc3MtYnJvd3NlciBzcGxpdCBtZXRob2RcbiAgICAgICAgICAgICAqL1xuXG4gICAgICAgICAgICAvKipcbiAgICAgICAgICAgICAqIFNwbGl0cyBhIHN0cmluZyBpbnRvIGFuIGFycmF5IG9mIHN0cmluZ3MgdXNpbmcgYSByZWdleCBvciBzdHJpbmcgc2VwYXJhdG9yLiBNYXRjaGVzIG9mIHRoZVxuICAgICAgICAgICAgICogc2VwYXJhdG9yIGFyZSBub3QgaW5jbHVkZWQgaW4gdGhlIHJlc3VsdCBhcnJheS4gSG93ZXZlciwgaWYgYHNlcGFyYXRvcmAgaXMgYSByZWdleCB0aGF0IGNvbnRhaW5zXG4gICAgICAgICAgICAgKiBjYXB0dXJpbmcgZ3JvdXBzLCBiYWNrcmVmZXJlbmNlcyBhcmUgc3BsaWNlZCBpbnRvIHRoZSByZXN1bHQgZWFjaCB0aW1lIGBzZXBhcmF0b3JgIGlzIG1hdGNoZWQuXG4gICAgICAgICAgICAgKiBGaXhlcyBicm93c2VyIGJ1Z3MgY29tcGFyZWQgdG8gdGhlIG5hdGl2ZSBgU3RyaW5nLnByb3RvdHlwZS5zcGxpdGAgYW5kIGNhbiBiZSB1c2VkIHJlbGlhYmx5XG4gICAgICAgICAgICAgKiBjcm9zcy1icm93c2VyLlxuICAgICAgICAgICAgICogQHBhcmFtIHtTdHJpbmd9IHN0ciBTdHJpbmcgdG8gc3BsaXQuXG4gICAgICAgICAgICAgKiBAcGFyYW0ge1JlZ0V4cHxTdHJpbmd9IHNlcGFyYXRvciBSZWdleCBvciBzdHJpbmcgdG8gdXNlIGZvciBzZXBhcmF0aW5nIHRoZSBzdHJpbmcuXG4gICAgICAgICAgICAgKiBAcGFyYW0ge051bWJlcn0gW2xpbWl0XSBNYXhpbXVtIG51bWJlciBvZiBpdGVtcyB0byBpbmNsdWRlIGluIHRoZSByZXN1bHQgYXJyYXkuXG4gICAgICAgICAgICAgKiBAcmV0dXJucyB7QXJyYXl9IEFycmF5IG9mIHN1YnN0cmluZ3MuXG4gICAgICAgICAgICAgKiBAZXhhbXBsZVxuICAgICAgICAgICAgICpcbiAgICAgICAgICAgICAqIC8vIEJhc2ljIHVzZVxuICAgICAgICAgICAgICogc3BsaXQoJ2EgYiBjIGQnLCAnICcpO1xuICAgICAgICAgICAgICogLy8gLT4gWydhJywgJ2InLCAnYycsICdkJ11cbiAgICAgICAgICAgICAqXG4gICAgICAgICAgICAgKiAvLyBXaXRoIGxpbWl0XG4gICAgICAgICAgICAgKiBzcGxpdCgnYSBiIGMgZCcsICcgJywgMik7XG4gICAgICAgICAgICAgKiAvLyAtPiBbJ2EnLCAnYiddXG4gICAgICAgICAgICAgKlxuICAgICAgICAgICAgICogLy8gQmFja3JlZmVyZW5jZXMgaW4gcmVzdWx0IGFycmF5XG4gICAgICAgICAgICAgKiBzcGxpdCgnLi53b3JkMSB3b3JkMi4uJywgLyhbYS16XSspKFxcZCspL2kpO1xuICAgICAgICAgICAgICogLy8gLT4gWycuLicsICd3b3JkJywgJzEnLCAnICcsICd3b3JkJywgJzInLCAnLi4nXVxuICAgICAgICAgICAgICovXG4gICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IChmdW5jdGlvbiBzcGxpdCh1bmRlZikge1xuXG4gICAgICAgICAgICAgICAgdmFyIG5hdGl2ZVNwbGl0ID0gU3RyaW5nLnByb3RvdHlwZS5zcGxpdCxcbiAgICAgICAgICAgICAgICAgICAgY29tcGxpYW50RXhlY05wY2cgPSAvKCk/Py8uZXhlYyhcIlwiKVsxXSA9PT0gdW5kZWYsXG5cbiAgICAgICAgICAgICAgICAvLyBOUENHOiBub25wYXJ0aWNpcGF0aW5nIGNhcHR1cmluZyBncm91cFxuICAgICAgICAgICAgICAgIHNlbGY7XG5cbiAgICAgICAgICAgICAgICBzZWxmID0gZnVuY3Rpb24gKHN0ciwgc2VwYXJhdG9yLCBsaW1pdCkge1xuICAgICAgICAgICAgICAgICAgICAvLyBJZiBgc2VwYXJhdG9yYCBpcyBub3QgYSByZWdleCwgdXNlIGBuYXRpdmVTcGxpdGBcbiAgICAgICAgICAgICAgICAgICAgaWYgKE9iamVjdC5wcm90b3R5cGUudG9TdHJpbmcuY2FsbChzZXBhcmF0b3IpICE9PSBcIltvYmplY3QgUmVnRXhwXVwiKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gbmF0aXZlU3BsaXQuY2FsbChzdHIsIHNlcGFyYXRvciwgbGltaXQpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIHZhciBvdXRwdXQgPSBbXSxcbiAgICAgICAgICAgICAgICAgICAgICAgIGZsYWdzID0gKHNlcGFyYXRvci5pZ25vcmVDYXNlID8gXCJpXCIgOiBcIlwiKSArIChzZXBhcmF0b3IubXVsdGlsaW5lID8gXCJtXCIgOiBcIlwiKSArIChzZXBhcmF0b3IuZXh0ZW5kZWQgPyBcInhcIiA6IFwiXCIpICsgKHNlcGFyYXRvci5zdGlja3kgPyBcInlcIiA6IFwiXCIpLFxuXG4gICAgICAgICAgICAgICAgICAgIC8vIEZpcmVmb3ggMytcbiAgICAgICAgICAgICAgICAgICAgbGFzdExhc3RJbmRleCA9IDAsXG5cbiAgICAgICAgICAgICAgICAgICAgLy8gTWFrZSBgZ2xvYmFsYCBhbmQgYXZvaWQgYGxhc3RJbmRleGAgaXNzdWVzIGJ5IHdvcmtpbmcgd2l0aCBhIGNvcHlcbiAgICAgICAgICAgICAgICAgICAgc2VwYXJhdG9yID0gbmV3IFJlZ0V4cChzZXBhcmF0b3Iuc291cmNlLCBmbGFncyArIFwiZ1wiKSxcbiAgICAgICAgICAgICAgICAgICAgICAgIHNlcGFyYXRvcjIsXG4gICAgICAgICAgICAgICAgICAgICAgICBtYXRjaCxcbiAgICAgICAgICAgICAgICAgICAgICAgIGxhc3RJbmRleCxcbiAgICAgICAgICAgICAgICAgICAgICAgIGxhc3RMZW5ndGg7XG4gICAgICAgICAgICAgICAgICAgIHN0ciArPSBcIlwiOyAvLyBUeXBlLWNvbnZlcnRcbiAgICAgICAgICAgICAgICAgICAgaWYgKCFjb21wbGlhbnRFeGVjTnBjZykge1xuICAgICAgICAgICAgICAgICAgICAgICAgLy8gRG9lc24ndCBuZWVkIGZsYWdzIGd5LCBidXQgdGhleSBkb24ndCBodXJ0XG4gICAgICAgICAgICAgICAgICAgICAgICBzZXBhcmF0b3IyID0gbmV3IFJlZ0V4cChcIl5cIiArIHNlcGFyYXRvci5zb3VyY2UgKyBcIiQoPyFcXFxccylcIiwgZmxhZ3MpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIC8qIFZhbHVlcyBmb3IgYGxpbWl0YCwgcGVyIHRoZSBzcGVjOlxuICAgICAgICAgICAgICAgICAgICAgKiBJZiB1bmRlZmluZWQ6IDQyOTQ5NjcyOTUgLy8gTWF0aC5wb3coMiwgMzIpIC0gMVxuICAgICAgICAgICAgICAgICAgICAgKiBJZiAwLCBJbmZpbml0eSwgb3IgTmFOOiAwXG4gICAgICAgICAgICAgICAgICAgICAqIElmIHBvc2l0aXZlIG51bWJlcjogbGltaXQgPSBNYXRoLmZsb29yKGxpbWl0KTsgaWYgKGxpbWl0ID4gNDI5NDk2NzI5NSkgbGltaXQgLT0gNDI5NDk2NzI5NjtcbiAgICAgICAgICAgICAgICAgICAgICogSWYgbmVnYXRpdmUgbnVtYmVyOiA0Mjk0OTY3Mjk2IC0gTWF0aC5mbG9vcihNYXRoLmFicyhsaW1pdCkpXG4gICAgICAgICAgICAgICAgICAgICAqIElmIG90aGVyOiBUeXBlLWNvbnZlcnQsIHRoZW4gdXNlIHRoZSBhYm92ZSBydWxlc1xuICAgICAgICAgICAgICAgICAgICAgKi9cbiAgICAgICAgICAgICAgICAgICAgbGltaXQgPSBsaW1pdCA9PT0gdW5kZWYgPyAtMSA+Pj4gMCA6IC8vIE1hdGgucG93KDIsIDMyKSAtIDFcbiAgICAgICAgICAgICAgICAgICAgbGltaXQgPj4+IDA7IC8vIFRvVWludDMyKGxpbWl0KVxuICAgICAgICAgICAgICAgICAgICB3aGlsZSAobWF0Y2ggPSBzZXBhcmF0b3IuZXhlYyhzdHIpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAvLyBgc2VwYXJhdG9yLmxhc3RJbmRleGAgaXMgbm90IHJlbGlhYmxlIGNyb3NzLWJyb3dzZXJcbiAgICAgICAgICAgICAgICAgICAgICAgIGxhc3RJbmRleCA9IG1hdGNoLmluZGV4ICsgbWF0Y2hbMF0ubGVuZ3RoO1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGxhc3RJbmRleCA+IGxhc3RMYXN0SW5kZXgpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBvdXRwdXQucHVzaChzdHIuc2xpY2UobGFzdExhc3RJbmRleCwgbWF0Y2guaW5kZXgpKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBGaXggYnJvd3NlcnMgd2hvc2UgYGV4ZWNgIG1ldGhvZHMgZG9uJ3QgY29uc2lzdGVudGx5IHJldHVybiBgdW5kZWZpbmVkYCBmb3JcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBub25wYXJ0aWNpcGF0aW5nIGNhcHR1cmluZyBncm91cHNcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoIWNvbXBsaWFudEV4ZWNOcGNnICYmIG1hdGNoLmxlbmd0aCA+IDEpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbWF0Y2hbMF0ucmVwbGFjZShzZXBhcmF0b3IyLCBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBmb3IgKHZhciBpID0gMTsgaSA8IGFyZ3VtZW50cy5sZW5ndGggLSAyOyBpKyspIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoYXJndW1lbnRzW2ldID09PSB1bmRlZikge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBtYXRjaFtpXSA9IHVuZGVmO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChtYXRjaC5sZW5ndGggPiAxICYmIG1hdGNoLmluZGV4IDwgc3RyLmxlbmd0aCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBBcnJheS5wcm90b3R5cGUucHVzaC5hcHBseShvdXRwdXQsIG1hdGNoLnNsaWNlKDEpKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgbGFzdExlbmd0aCA9IG1hdGNoWzBdLmxlbmd0aDtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBsYXN0TGFzdEluZGV4ID0gbGFzdEluZGV4O1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChvdXRwdXQubGVuZ3RoID49IGxpbWl0KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChzZXBhcmF0b3IubGFzdEluZGV4ID09PSBtYXRjaC5pbmRleCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNlcGFyYXRvci5sYXN0SW5kZXgrKzsgLy8gQXZvaWQgYW4gaW5maW5pdGUgbG9vcFxuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIGlmIChsYXN0TGFzdEluZGV4ID09PSBzdHIubGVuZ3RoKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAobGFzdExlbmd0aCB8fCAhc2VwYXJhdG9yLnRlc3QoXCJcIikpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBvdXRwdXQucHVzaChcIlwiKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIG91dHB1dC5wdXNoKHN0ci5zbGljZShsYXN0TGFzdEluZGV4KSk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIG91dHB1dC5sZW5ndGggPiBsaW1pdCA/IG91dHB1dC5zbGljZSgwLCBsaW1pdCkgOiBvdXRwdXQ7XG4gICAgICAgICAgICAgICAgfTtcblxuICAgICAgICAgICAgICAgIHJldHVybiBzZWxmO1xuICAgICAgICAgICAgfSkoKTtcbiAgICAgICAgfSwge31dLCA2OiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge30sIHt9XSwgNzogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHtcbiAgICAgICAgICAgIFwidXNlIHN0cmljdFwiO1xuXG4gICAgICAgICAgICB2YXIgT25lVmVyc2lvbkNvbnN0cmFpbnQgPSByZXF1aXJlKFwiaW5kaXZpZHVhbC9vbmUtdmVyc2lvblwiKTtcblxuICAgICAgICAgICAgdmFyIE1ZX1ZFUlNJT04gPSBcIjdcIjtcbiAgICAgICAgICAgIE9uZVZlcnNpb25Db25zdHJhaW50KFwiZXYtc3RvcmVcIiwgTVlfVkVSU0lPTik7XG5cbiAgICAgICAgICAgIHZhciBoYXNoS2V5ID0gXCJfX0VWX1NUT1JFX0tFWUBcIiArIE1ZX1ZFUlNJT047XG5cbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gRXZTdG9yZTtcblxuICAgICAgICAgICAgZnVuY3Rpb24gRXZTdG9yZShlbGVtKSB7XG4gICAgICAgICAgICAgICAgdmFyIGhhc2ggPSBlbGVtW2hhc2hLZXldO1xuXG4gICAgICAgICAgICAgICAgaWYgKCFoYXNoKSB7XG4gICAgICAgICAgICAgICAgICAgIGhhc2ggPSBlbGVtW2hhc2hLZXldID0ge307XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgcmV0dXJuIGhhc2g7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0sIHsgXCJpbmRpdmlkdWFsL29uZS12ZXJzaW9uXCI6IDkgfV0sIDg6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICAoZnVuY3Rpb24gKGdsb2JhbCkge1xuICAgICAgICAgICAgICAgIFwidXNlIHN0cmljdFwiO1xuXG4gICAgICAgICAgICAgICAgLypnbG9iYWwgd2luZG93LCBnbG9iYWwqL1xuXG4gICAgICAgICAgICAgICAgdmFyIHJvb3QgPSB0eXBlb2Ygd2luZG93ICE9PSBcInVuZGVmaW5lZFwiID8gd2luZG93IDogdHlwZW9mIGdsb2JhbCAhPT0gXCJ1bmRlZmluZWRcIiA/IGdsb2JhbCA6IHt9O1xuXG4gICAgICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBJbmRpdmlkdWFsO1xuXG4gICAgICAgICAgICAgICAgZnVuY3Rpb24gSW5kaXZpZHVhbChrZXksIHZhbHVlKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmIChrZXkgaW4gcm9vdCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHJvb3Rba2V5XTtcbiAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgIHJvb3Rba2V5XSA9IHZhbHVlO1xuXG4gICAgICAgICAgICAgICAgICAgIHJldHVybiB2YWx1ZTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9KS5jYWxsKHRoaXMsIHR5cGVvZiBnbG9iYWwgIT09IFwidW5kZWZpbmVkXCIgPyBnbG9iYWwgOiB0eXBlb2Ygc2VsZiAhPT0gXCJ1bmRlZmluZWRcIiA/IHNlbGYgOiB0eXBlb2Ygd2luZG93ICE9PSBcInVuZGVmaW5lZFwiID8gd2luZG93IDoge30pO1xuICAgICAgICB9LCB7fV0sIDk6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICBcInVzZSBzdHJpY3RcIjtcblxuICAgICAgICAgICAgdmFyIEluZGl2aWR1YWwgPSByZXF1aXJlKFwiLi9pbmRleC5qc1wiKTtcblxuICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBPbmVWZXJzaW9uO1xuXG4gICAgICAgICAgICBmdW5jdGlvbiBPbmVWZXJzaW9uKG1vZHVsZU5hbWUsIHZlcnNpb24sIGRlZmF1bHRWYWx1ZSkge1xuICAgICAgICAgICAgICAgIHZhciBrZXkgPSBcIl9fSU5ESVZJRFVBTF9PTkVfVkVSU0lPTl9cIiArIG1vZHVsZU5hbWU7XG4gICAgICAgICAgICAgICAgdmFyIGVuZm9yY2VLZXkgPSBrZXkgKyBcIl9FTkZPUkNFX1NJTkdMRVRPTlwiO1xuXG4gICAgICAgICAgICAgICAgdmFyIHZlcnNpb25WYWx1ZSA9IEluZGl2aWR1YWwoZW5mb3JjZUtleSwgdmVyc2lvbik7XG5cbiAgICAgICAgICAgICAgICBpZiAodmVyc2lvblZhbHVlICE9PSB2ZXJzaW9uKSB7XG4gICAgICAgICAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcihcIkNhbiBvbmx5IGhhdmUgb25lIGNvcHkgb2YgXCIgKyBtb2R1bGVOYW1lICsgXCIuXFxuXCIgKyBcIllvdSBhbHJlYWR5IGhhdmUgdmVyc2lvbiBcIiArIHZlcnNpb25WYWx1ZSArIFwiIGluc3RhbGxlZC5cXG5cIiArIFwiVGhpcyBtZWFucyB5b3UgY2Fubm90IGluc3RhbGwgdmVyc2lvbiBcIiArIHZlcnNpb24pO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHJldHVybiBJbmRpdmlkdWFsKGtleSwgZGVmYXVsdFZhbHVlKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSwgeyBcIi4vaW5kZXguanNcIjogOCB9XSwgMTA6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICAoZnVuY3Rpb24gKGdsb2JhbCkge1xuICAgICAgICAgICAgICAgIHZhciB0b3BMZXZlbCA9IHR5cGVvZiBnbG9iYWwgIT09IFwidW5kZWZpbmVkXCIgPyBnbG9iYWwgOiB0eXBlb2Ygd2luZG93ICE9PSBcInVuZGVmaW5lZFwiID8gd2luZG93IDoge307XG4gICAgICAgICAgICAgICAgdmFyIG1pbkRvYyA9IHJlcXVpcmUoXCJtaW4tZG9jdW1lbnRcIik7XG5cbiAgICAgICAgICAgICAgICBpZiAodHlwZW9mIGRvY3VtZW50ICE9PSBcInVuZGVmaW5lZFwiKSB7XG4gICAgICAgICAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gZG9jdW1lbnQ7XG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgdmFyIGRvY2N5ID0gdG9wTGV2ZWxbXCJfX0dMT0JBTF9ET0NVTUVOVF9DQUNIRUA0XCJdO1xuXG4gICAgICAgICAgICAgICAgICAgIGlmICghZG9jY3kpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGRvY2N5ID0gdG9wTGV2ZWxbXCJfX0dMT0JBTF9ET0NVTUVOVF9DQUNIRUA0XCJdID0gbWluRG9jO1xuICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBkb2NjeTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9KS5jYWxsKHRoaXMsIHR5cGVvZiBnbG9iYWwgIT09IFwidW5kZWZpbmVkXCIgPyBnbG9iYWwgOiB0eXBlb2Ygc2VsZiAhPT0gXCJ1bmRlZmluZWRcIiA/IHNlbGYgOiB0eXBlb2Ygd2luZG93ICE9PSBcInVuZGVmaW5lZFwiID8gd2luZG93IDoge30pO1xuICAgICAgICB9LCB7IFwibWluLWRvY3VtZW50XCI6IDYgfV0sIDExOiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge1xuICAgICAgICAgICAgXCJ1c2Ugc3RyaWN0XCI7XG5cbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gaXNPYmplY3QoeCkge1xuICAgICAgICAgICAgICAgIHJldHVybiB0eXBlb2YgeCA9PT0gXCJvYmplY3RcIiAmJiB4ICE9PSBudWxsO1xuICAgICAgICAgICAgfTtcbiAgICAgICAgfSwge31dLCAxMjogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHtcbiAgICAgICAgICAgIHZhciBuYXRpdmVJc0FycmF5ID0gQXJyYXkuaXNBcnJheTtcbiAgICAgICAgICAgIHZhciB0b1N0cmluZyA9IE9iamVjdC5wcm90b3R5cGUudG9TdHJpbmc7XG5cbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gbmF0aXZlSXNBcnJheSB8fCBpc0FycmF5O1xuXG4gICAgICAgICAgICBmdW5jdGlvbiBpc0FycmF5KG9iaikge1xuICAgICAgICAgICAgICAgIHJldHVybiB0b1N0cmluZy5jYWxsKG9iaikgPT09IFwiW29iamVjdCBBcnJheV1cIjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSwge31dLCAxMzogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHtcbiAgICAgICAgICAgIHZhciBwYXRjaCA9IHJlcXVpcmUoXCIuL3Zkb20vcGF0Y2guanNcIik7XG5cbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gcGF0Y2g7XG4gICAgICAgIH0sIHsgXCIuL3Zkb20vcGF0Y2guanNcIjogMTggfV0sIDE0OiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge1xuICAgICAgICAgICAgdmFyIGlzT2JqZWN0ID0gcmVxdWlyZShcImlzLW9iamVjdFwiKTtcbiAgICAgICAgICAgIHZhciBpc0hvb2sgPSByZXF1aXJlKFwiLi4vdm5vZGUvaXMtdmhvb2suanNcIik7XG5cbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gYXBwbHlQcm9wZXJ0aWVzO1xuXG4gICAgICAgICAgICBmdW5jdGlvbiBhcHBseVByb3BlcnRpZXMobm9kZSwgcHJvcHMsIHByZXZpb3VzKSB7XG4gICAgICAgICAgICAgICAgZm9yICh2YXIgcHJvcE5hbWUgaW4gcHJvcHMpIHtcbiAgICAgICAgICAgICAgICAgICAgdmFyIHByb3BWYWx1ZSA9IHByb3BzW3Byb3BOYW1lXTtcblxuICAgICAgICAgICAgICAgICAgICBpZiAocHJvcFZhbHVlID09PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJlbW92ZVByb3BlcnR5KG5vZGUsIHByb3BOYW1lLCBwcm9wVmFsdWUsIHByZXZpb3VzKTtcbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIGlmIChpc0hvb2socHJvcFZhbHVlKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgcmVtb3ZlUHJvcGVydHkobm9kZSwgcHJvcE5hbWUsIHByb3BWYWx1ZSwgcHJldmlvdXMpO1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHByb3BWYWx1ZS5ob29rKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcHJvcFZhbHVlLmhvb2sobm9kZSwgcHJvcE5hbWUsIHByZXZpb3VzID8gcHJldmlvdXNbcHJvcE5hbWVdIDogdW5kZWZpbmVkKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChpc09iamVjdChwcm9wVmFsdWUpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcGF0Y2hPYmplY3Qobm9kZSwgcHJvcHMsIHByZXZpb3VzLCBwcm9wTmFtZSwgcHJvcFZhbHVlKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgbm9kZVtwcm9wTmFtZV0gPSBwcm9wVmFsdWU7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIHJlbW92ZVByb3BlcnR5KG5vZGUsIHByb3BOYW1lLCBwcm9wVmFsdWUsIHByZXZpb3VzKSB7XG4gICAgICAgICAgICAgICAgaWYgKHByZXZpb3VzKSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciBwcmV2aW91c1ZhbHVlID0gcHJldmlvdXNbcHJvcE5hbWVdO1xuXG4gICAgICAgICAgICAgICAgICAgIGlmICghaXNIb29rKHByZXZpb3VzVmFsdWUpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAocHJvcE5hbWUgPT09IFwiYXR0cmlidXRlc1wiKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgZm9yICh2YXIgYXR0ck5hbWUgaW4gcHJldmlvdXNWYWx1ZSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBub2RlLnJlbW92ZUF0dHJpYnV0ZShhdHRyTmFtZSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIGlmIChwcm9wTmFtZSA9PT0gXCJzdHlsZVwiKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgZm9yICh2YXIgaSBpbiBwcmV2aW91c1ZhbHVlKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG5vZGUuc3R5bGVbaV0gPSBcIlwiO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAodHlwZW9mIHByZXZpb3VzVmFsdWUgPT09IFwic3RyaW5nXCIpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBub2RlW3Byb3BOYW1lXSA9IFwiXCI7XG4gICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIG5vZGVbcHJvcE5hbWVdID0gbnVsbDtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIGlmIChwcmV2aW91c1ZhbHVlLnVuaG9vaykge1xuICAgICAgICAgICAgICAgICAgICAgICAgcHJldmlvdXNWYWx1ZS51bmhvb2sobm9kZSwgcHJvcE5hbWUsIHByb3BWYWx1ZSk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIHBhdGNoT2JqZWN0KG5vZGUsIHByb3BzLCBwcmV2aW91cywgcHJvcE5hbWUsIHByb3BWYWx1ZSkge1xuICAgICAgICAgICAgICAgIHZhciBwcmV2aW91c1ZhbHVlID0gcHJldmlvdXMgPyBwcmV2aW91c1twcm9wTmFtZV0gOiB1bmRlZmluZWQ7XG5cbiAgICAgICAgICAgICAgICAvLyBTZXQgYXR0cmlidXRlc1xuICAgICAgICAgICAgICAgIGlmIChwcm9wTmFtZSA9PT0gXCJhdHRyaWJ1dGVzXCIpIHtcbiAgICAgICAgICAgICAgICAgICAgZm9yICh2YXIgYXR0ck5hbWUgaW4gcHJvcFZhbHVlKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICB2YXIgYXR0clZhbHVlID0gcHJvcFZhbHVlW2F0dHJOYW1lXTtcblxuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGF0dHJWYWx1ZSA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgbm9kZS5yZW1vdmVBdHRyaWJ1dGUoYXR0ck5hbWUpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBub2RlLnNldEF0dHJpYnV0ZShhdHRyTmFtZSwgYXR0clZhbHVlKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICBpZiAocHJldmlvdXNWYWx1ZSAmJiBpc09iamVjdChwcmV2aW91c1ZhbHVlKSAmJiBnZXRQcm90b3R5cGUocHJldmlvdXNWYWx1ZSkgIT09IGdldFByb3RvdHlwZShwcm9wVmFsdWUpKSB7XG4gICAgICAgICAgICAgICAgICAgIG5vZGVbcHJvcE5hbWVdID0gcHJvcFZhbHVlO1xuICAgICAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgaWYgKCFpc09iamVjdChub2RlW3Byb3BOYW1lXSkpIHtcbiAgICAgICAgICAgICAgICAgICAgbm9kZVtwcm9wTmFtZV0gPSB7fTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICB2YXIgcmVwbGFjZXIgPSBwcm9wTmFtZSA9PT0gXCJzdHlsZVwiID8gXCJcIiA6IHVuZGVmaW5lZDtcblxuICAgICAgICAgICAgICAgIGZvciAodmFyIGsgaW4gcHJvcFZhbHVlKSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciB2YWx1ZSA9IHByb3BWYWx1ZVtrXTtcbiAgICAgICAgICAgICAgICAgICAgbm9kZVtwcm9wTmFtZV1ba10gPSB2YWx1ZSA9PT0gdW5kZWZpbmVkID8gcmVwbGFjZXIgOiB2YWx1ZTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIGdldFByb3RvdHlwZSh2YWx1ZSkge1xuICAgICAgICAgICAgICAgIGlmIChPYmplY3QuZ2V0UHJvdG90eXBlT2YpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIE9iamVjdC5nZXRQcm90b3R5cGVPZih2YWx1ZSk7XG4gICAgICAgICAgICAgICAgfSBlbHNlIGlmICh2YWx1ZS5fX3Byb3RvX18pIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHZhbHVlLl9fcHJvdG9fXztcbiAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKHZhbHVlLmNvbnN0cnVjdG9yKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiB2YWx1ZS5jb25zdHJ1Y3Rvci5wcm90b3R5cGU7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9LCB7IFwiLi4vdm5vZGUvaXMtdmhvb2suanNcIjogMjYsIFwiaXMtb2JqZWN0XCI6IDExIH1dLCAxNTogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHtcbiAgICAgICAgICAgIHZhciBkb2N1bWVudCA9IHJlcXVpcmUoXCJnbG9iYWwvZG9jdW1lbnRcIik7XG5cbiAgICAgICAgICAgIHZhciBhcHBseVByb3BlcnRpZXMgPSByZXF1aXJlKFwiLi9hcHBseS1wcm9wZXJ0aWVzXCIpO1xuXG4gICAgICAgICAgICB2YXIgaXNWTm9kZSA9IHJlcXVpcmUoXCIuLi92bm9kZS9pcy12bm9kZS5qc1wiKTtcbiAgICAgICAgICAgIHZhciBpc1ZUZXh0ID0gcmVxdWlyZShcIi4uL3Zub2RlL2lzLXZ0ZXh0LmpzXCIpO1xuICAgICAgICAgICAgdmFyIGlzV2lkZ2V0ID0gcmVxdWlyZShcIi4uL3Zub2RlL2lzLXdpZGdldC5qc1wiKTtcbiAgICAgICAgICAgIHZhciBoYW5kbGVUaHVuayA9IHJlcXVpcmUoXCIuLi92bm9kZS9oYW5kbGUtdGh1bmsuanNcIik7XG5cbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gY3JlYXRlRWxlbWVudDtcblxuICAgICAgICAgICAgZnVuY3Rpb24gY3JlYXRlRWxlbWVudCh2bm9kZSwgb3B0cykge1xuICAgICAgICAgICAgICAgIHZhciBkb2MgPSBvcHRzID8gb3B0cy5kb2N1bWVudCB8fCBkb2N1bWVudCA6IGRvY3VtZW50O1xuICAgICAgICAgICAgICAgIHZhciB3YXJuID0gb3B0cyA/IG9wdHMud2FybiA6IG51bGw7XG5cbiAgICAgICAgICAgICAgICB2bm9kZSA9IGhhbmRsZVRodW5rKHZub2RlKS5hO1xuXG4gICAgICAgICAgICAgICAgaWYgKGlzV2lkZ2V0KHZub2RlKSkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gdm5vZGUuaW5pdCgpO1xuICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoaXNWVGV4dCh2bm9kZSkpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGRvYy5jcmVhdGVUZXh0Tm9kZSh2bm9kZS50ZXh0KTtcbiAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKCFpc1ZOb2RlKHZub2RlKSkge1xuICAgICAgICAgICAgICAgICAgICBpZiAod2Fybikge1xuICAgICAgICAgICAgICAgICAgICAgICAgd2FybihcIkl0ZW0gaXMgbm90IGEgdmFsaWQgdmlydHVhbCBkb20gbm9kZVwiLCB2bm9kZSk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIG51bGw7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgdmFyIG5vZGUgPSB2bm9kZS5uYW1lc3BhY2UgPT09IG51bGwgPyBkb2MuY3JlYXRlRWxlbWVudCh2bm9kZS50YWdOYW1lKSA6IGRvYy5jcmVhdGVFbGVtZW50TlModm5vZGUubmFtZXNwYWNlLCB2bm9kZS50YWdOYW1lKTtcblxuICAgICAgICAgICAgICAgIHZhciBwcm9wcyA9IHZub2RlLnByb3BlcnRpZXM7XG4gICAgICAgICAgICAgICAgYXBwbHlQcm9wZXJ0aWVzKG5vZGUsIHByb3BzKTtcblxuICAgICAgICAgICAgICAgIHZhciBjaGlsZHJlbiA9IHZub2RlLmNoaWxkcmVuO1xuXG4gICAgICAgICAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCBjaGlsZHJlbi5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgICAgICAgICB2YXIgY2hpbGROb2RlID0gY3JlYXRlRWxlbWVudChjaGlsZHJlbltpXSwgb3B0cyk7XG4gICAgICAgICAgICAgICAgICAgIGlmIChjaGlsZE5vZGUpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIG5vZGUuYXBwZW5kQ2hpbGQoY2hpbGROb2RlKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHJldHVybiBub2RlO1xuICAgICAgICAgICAgfVxuICAgICAgICB9LCB7IFwiLi4vdm5vZGUvaGFuZGxlLXRodW5rLmpzXCI6IDI0LCBcIi4uL3Zub2RlL2lzLXZub2RlLmpzXCI6IDI3LCBcIi4uL3Zub2RlL2lzLXZ0ZXh0LmpzXCI6IDI4LCBcIi4uL3Zub2RlL2lzLXdpZGdldC5qc1wiOiAyOSwgXCIuL2FwcGx5LXByb3BlcnRpZXNcIjogMTQsIFwiZ2xvYmFsL2RvY3VtZW50XCI6IDEwIH1dLCAxNjogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHtcbiAgICAgICAgICAgIC8vIE1hcHMgYSB2aXJ0dWFsIERPTSB0cmVlIG9udG8gYSByZWFsIERPTSB0cmVlIGluIGFuIGVmZmljaWVudCBtYW5uZXIuXG4gICAgICAgICAgICAvLyBXZSBkb24ndCB3YW50IHRvIHJlYWQgYWxsIG9mIHRoZSBET00gbm9kZXMgaW4gdGhlIHRyZWUgc28gd2UgdXNlXG4gICAgICAgICAgICAvLyB0aGUgaW4tb3JkZXIgdHJlZSBpbmRleGluZyB0byBlbGltaW5hdGUgcmVjdXJzaW9uIGRvd24gY2VydGFpbiBicmFuY2hlcy5cbiAgICAgICAgICAgIC8vIFdlIG9ubHkgcmVjdXJzZSBpbnRvIGEgRE9NIG5vZGUgaWYgd2Uga25vdyB0aGF0IGl0IGNvbnRhaW5zIGEgY2hpbGQgb2ZcbiAgICAgICAgICAgIC8vIGludGVyZXN0LlxuXG4gICAgICAgICAgICB2YXIgbm9DaGlsZCA9IHt9O1xuXG4gICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IGRvbUluZGV4O1xuXG4gICAgICAgICAgICBmdW5jdGlvbiBkb21JbmRleChyb290Tm9kZSwgdHJlZSwgaW5kaWNlcywgbm9kZXMpIHtcbiAgICAgICAgICAgICAgICBpZiAoIWluZGljZXMgfHwgaW5kaWNlcy5sZW5ndGggPT09IDApIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHt9O1xuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIGluZGljZXMuc29ydChhc2NlbmRpbmcpO1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gcmVjdXJzZShyb290Tm9kZSwgdHJlZSwgaW5kaWNlcywgbm9kZXMsIDApO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZnVuY3Rpb24gcmVjdXJzZShyb290Tm9kZSwgdHJlZSwgaW5kaWNlcywgbm9kZXMsIHJvb3RJbmRleCkge1xuICAgICAgICAgICAgICAgIG5vZGVzID0gbm9kZXMgfHwge307XG5cbiAgICAgICAgICAgICAgICBpZiAocm9vdE5vZGUpIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKGluZGV4SW5SYW5nZShpbmRpY2VzLCByb290SW5kZXgsIHJvb3RJbmRleCkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIG5vZGVzW3Jvb3RJbmRleF0gPSByb290Tm9kZTtcbiAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgIHZhciB2Q2hpbGRyZW4gPSB0cmVlLmNoaWxkcmVuO1xuXG4gICAgICAgICAgICAgICAgICAgIGlmICh2Q2hpbGRyZW4pIHtcblxuICAgICAgICAgICAgICAgICAgICAgICAgdmFyIGNoaWxkTm9kZXMgPSByb290Tm9kZS5jaGlsZE5vZGVzO1xuXG4gICAgICAgICAgICAgICAgICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IHRyZWUuY2hpbGRyZW4ubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICByb290SW5kZXggKz0gMTtcblxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZhciB2Q2hpbGQgPSB2Q2hpbGRyZW5baV0gfHwgbm9DaGlsZDtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB2YXIgbmV4dEluZGV4ID0gcm9vdEluZGV4ICsgKHZDaGlsZC5jb3VudCB8fCAwKTtcblxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIHNraXAgcmVjdXJzaW9uIGRvd24gdGhlIHRyZWUgaWYgdGhlcmUgYXJlIG5vIG5vZGVzIGRvd24gaGVyZVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChpbmRleEluUmFuZ2UoaW5kaWNlcywgcm9vdEluZGV4LCBuZXh0SW5kZXgpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlY3Vyc2UoY2hpbGROb2Rlc1tpXSwgdkNoaWxkLCBpbmRpY2VzLCBub2Rlcywgcm9vdEluZGV4KTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICByb290SW5kZXggPSBuZXh0SW5kZXg7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICByZXR1cm4gbm9kZXM7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIC8vIEJpbmFyeSBzZWFyY2ggZm9yIGFuIGluZGV4IGluIHRoZSBpbnRlcnZhbCBbbGVmdCwgcmlnaHRdXG4gICAgICAgICAgICBmdW5jdGlvbiBpbmRleEluUmFuZ2UoaW5kaWNlcywgbGVmdCwgcmlnaHQpIHtcbiAgICAgICAgICAgICAgICBpZiAoaW5kaWNlcy5sZW5ndGggPT09IDApIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHZhciBtaW5JbmRleCA9IDA7XG4gICAgICAgICAgICAgICAgdmFyIG1heEluZGV4ID0gaW5kaWNlcy5sZW5ndGggLSAxO1xuICAgICAgICAgICAgICAgIHZhciBjdXJyZW50SW5kZXg7XG4gICAgICAgICAgICAgICAgdmFyIGN1cnJlbnRJdGVtO1xuXG4gICAgICAgICAgICAgICAgd2hpbGUgKG1pbkluZGV4IDw9IG1heEluZGV4KSB7XG4gICAgICAgICAgICAgICAgICAgIGN1cnJlbnRJbmRleCA9IChtYXhJbmRleCArIG1pbkluZGV4KSAvIDIgPj4gMDtcbiAgICAgICAgICAgICAgICAgICAgY3VycmVudEl0ZW0gPSBpbmRpY2VzW2N1cnJlbnRJbmRleF07XG5cbiAgICAgICAgICAgICAgICAgICAgaWYgKG1pbkluZGV4ID09PSBtYXhJbmRleCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGN1cnJlbnRJdGVtID49IGxlZnQgJiYgY3VycmVudEl0ZW0gPD0gcmlnaHQ7XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoY3VycmVudEl0ZW0gPCBsZWZ0KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBtaW5JbmRleCA9IGN1cnJlbnRJbmRleCArIDE7XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoY3VycmVudEl0ZW0gPiByaWdodCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgbWF4SW5kZXggPSBjdXJyZW50SW5kZXggLSAxO1xuICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIGFzY2VuZGluZyhhLCBiKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGEgPiBiID8gMSA6IC0xO1xuICAgICAgICAgICAgfVxuICAgICAgICB9LCB7fV0sIDE3OiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge1xuICAgICAgICAgICAgdmFyIGFwcGx5UHJvcGVydGllcyA9IHJlcXVpcmUoXCIuL2FwcGx5LXByb3BlcnRpZXNcIik7XG5cbiAgICAgICAgICAgIHZhciBpc1dpZGdldCA9IHJlcXVpcmUoXCIuLi92bm9kZS9pcy13aWRnZXQuanNcIik7XG4gICAgICAgICAgICB2YXIgVlBhdGNoID0gcmVxdWlyZShcIi4uL3Zub2RlL3ZwYXRjaC5qc1wiKTtcblxuICAgICAgICAgICAgdmFyIHVwZGF0ZVdpZGdldCA9IHJlcXVpcmUoXCIuL3VwZGF0ZS13aWRnZXRcIik7XG5cbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gYXBwbHlQYXRjaDtcblxuICAgICAgICAgICAgZnVuY3Rpb24gYXBwbHlQYXRjaCh2cGF0Y2gsIGRvbU5vZGUsIHJlbmRlck9wdGlvbnMpIHtcbiAgICAgICAgICAgICAgICB2YXIgdHlwZSA9IHZwYXRjaC50eXBlO1xuICAgICAgICAgICAgICAgIHZhciB2Tm9kZSA9IHZwYXRjaC52Tm9kZTtcbiAgICAgICAgICAgICAgICB2YXIgcGF0Y2ggPSB2cGF0Y2gucGF0Y2g7XG5cbiAgICAgICAgICAgICAgICBzd2l0Y2ggKHR5cGUpIHtcbiAgICAgICAgICAgICAgICAgICAgY2FzZSBWUGF0Y2guUkVNT1ZFOlxuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHJlbW92ZU5vZGUoZG9tTm9kZSwgdk5vZGUpO1xuICAgICAgICAgICAgICAgICAgICBjYXNlIFZQYXRjaC5JTlNFUlQ6XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gaW5zZXJ0Tm9kZShkb21Ob2RlLCBwYXRjaCwgcmVuZGVyT3B0aW9ucyk7XG4gICAgICAgICAgICAgICAgICAgIGNhc2UgVlBhdGNoLlZURVhUOlxuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHN0cmluZ1BhdGNoKGRvbU5vZGUsIHZOb2RlLCBwYXRjaCwgcmVuZGVyT3B0aW9ucyk7XG4gICAgICAgICAgICAgICAgICAgIGNhc2UgVlBhdGNoLldJREdFVDpcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiB3aWRnZXRQYXRjaChkb21Ob2RlLCB2Tm9kZSwgcGF0Y2gsIHJlbmRlck9wdGlvbnMpO1xuICAgICAgICAgICAgICAgICAgICBjYXNlIFZQYXRjaC5WTk9ERTpcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiB2Tm9kZVBhdGNoKGRvbU5vZGUsIHZOb2RlLCBwYXRjaCwgcmVuZGVyT3B0aW9ucyk7XG4gICAgICAgICAgICAgICAgICAgIGNhc2UgVlBhdGNoLk9SREVSOlxuICAgICAgICAgICAgICAgICAgICAgICAgcmVvcmRlckNoaWxkcmVuKGRvbU5vZGUsIHBhdGNoKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBkb21Ob2RlO1xuICAgICAgICAgICAgICAgICAgICBjYXNlIFZQYXRjaC5QUk9QUzpcbiAgICAgICAgICAgICAgICAgICAgICAgIGFwcGx5UHJvcGVydGllcyhkb21Ob2RlLCBwYXRjaCwgdk5vZGUucHJvcGVydGllcyk7XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gZG9tTm9kZTtcbiAgICAgICAgICAgICAgICAgICAgY2FzZSBWUGF0Y2guVEhVTks6XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gcmVwbGFjZVJvb3QoZG9tTm9kZSwgcmVuZGVyT3B0aW9ucy5wYXRjaChkb21Ob2RlLCBwYXRjaCwgcmVuZGVyT3B0aW9ucykpO1xuICAgICAgICAgICAgICAgICAgICBkZWZhdWx0OlxuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGRvbU5vZGU7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBmdW5jdGlvbiByZW1vdmVOb2RlKGRvbU5vZGUsIHZOb2RlKSB7XG4gICAgICAgICAgICAgICAgdmFyIHBhcmVudE5vZGUgPSBkb21Ob2RlLnBhcmVudE5vZGU7XG5cbiAgICAgICAgICAgICAgICBpZiAocGFyZW50Tm9kZSkge1xuICAgICAgICAgICAgICAgICAgICBwYXJlbnROb2RlLnJlbW92ZUNoaWxkKGRvbU5vZGUpO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIGRlc3Ryb3lXaWRnZXQoZG9tTm9kZSwgdk5vZGUpO1xuXG4gICAgICAgICAgICAgICAgcmV0dXJuIG51bGw7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIGluc2VydE5vZGUocGFyZW50Tm9kZSwgdk5vZGUsIHJlbmRlck9wdGlvbnMpIHtcbiAgICAgICAgICAgICAgICB2YXIgbmV3Tm9kZSA9IHJlbmRlck9wdGlvbnMucmVuZGVyKHZOb2RlLCByZW5kZXJPcHRpb25zKTtcblxuICAgICAgICAgICAgICAgIGlmIChwYXJlbnROb2RlKSB7XG4gICAgICAgICAgICAgICAgICAgIHBhcmVudE5vZGUuYXBwZW5kQ2hpbGQobmV3Tm9kZSk7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgcmV0dXJuIHBhcmVudE5vZGU7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIHN0cmluZ1BhdGNoKGRvbU5vZGUsIGxlZnRWTm9kZSwgdlRleHQsIHJlbmRlck9wdGlvbnMpIHtcbiAgICAgICAgICAgICAgICB2YXIgbmV3Tm9kZTtcblxuICAgICAgICAgICAgICAgIGlmIChkb21Ob2RlLm5vZGVUeXBlID09PSAzKSB7XG4gICAgICAgICAgICAgICAgICAgIGRvbU5vZGUucmVwbGFjZURhdGEoMCwgZG9tTm9kZS5sZW5ndGgsIHZUZXh0LnRleHQpO1xuICAgICAgICAgICAgICAgICAgICBuZXdOb2RlID0gZG9tTm9kZTtcbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICB2YXIgcGFyZW50Tm9kZSA9IGRvbU5vZGUucGFyZW50Tm9kZTtcbiAgICAgICAgICAgICAgICAgICAgbmV3Tm9kZSA9IHJlbmRlck9wdGlvbnMucmVuZGVyKHZUZXh0LCByZW5kZXJPcHRpb25zKTtcblxuICAgICAgICAgICAgICAgICAgICBpZiAocGFyZW50Tm9kZSAmJiBuZXdOb2RlICE9PSBkb21Ob2RlKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBwYXJlbnROb2RlLnJlcGxhY2VDaGlsZChuZXdOb2RlLCBkb21Ob2RlKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHJldHVybiBuZXdOb2RlO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBmdW5jdGlvbiB3aWRnZXRQYXRjaChkb21Ob2RlLCBsZWZ0Vk5vZGUsIHdpZGdldCwgcmVuZGVyT3B0aW9ucykge1xuICAgICAgICAgICAgICAgIHZhciB1cGRhdGluZyA9IHVwZGF0ZVdpZGdldChsZWZ0Vk5vZGUsIHdpZGdldCk7XG4gICAgICAgICAgICAgICAgdmFyIG5ld05vZGU7XG5cbiAgICAgICAgICAgICAgICBpZiAodXBkYXRpbmcpIHtcbiAgICAgICAgICAgICAgICAgICAgbmV3Tm9kZSA9IHdpZGdldC51cGRhdGUobGVmdFZOb2RlLCBkb21Ob2RlKSB8fCBkb21Ob2RlO1xuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIG5ld05vZGUgPSByZW5kZXJPcHRpb25zLnJlbmRlcih3aWRnZXQsIHJlbmRlck9wdGlvbnMpO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHZhciBwYXJlbnROb2RlID0gZG9tTm9kZS5wYXJlbnROb2RlO1xuXG4gICAgICAgICAgICAgICAgaWYgKHBhcmVudE5vZGUgJiYgbmV3Tm9kZSAhPT0gZG9tTm9kZSkge1xuICAgICAgICAgICAgICAgICAgICBwYXJlbnROb2RlLnJlcGxhY2VDaGlsZChuZXdOb2RlLCBkb21Ob2RlKTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICBpZiAoIXVwZGF0aW5nKSB7XG4gICAgICAgICAgICAgICAgICAgIGRlc3Ryb3lXaWRnZXQoZG9tTm9kZSwgbGVmdFZOb2RlKTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICByZXR1cm4gbmV3Tm9kZTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZnVuY3Rpb24gdk5vZGVQYXRjaChkb21Ob2RlLCBsZWZ0Vk5vZGUsIHZOb2RlLCByZW5kZXJPcHRpb25zKSB7XG4gICAgICAgICAgICAgICAgdmFyIHBhcmVudE5vZGUgPSBkb21Ob2RlLnBhcmVudE5vZGU7XG4gICAgICAgICAgICAgICAgdmFyIG5ld05vZGUgPSByZW5kZXJPcHRpb25zLnJlbmRlcih2Tm9kZSwgcmVuZGVyT3B0aW9ucyk7XG5cbiAgICAgICAgICAgICAgICBpZiAocGFyZW50Tm9kZSAmJiBuZXdOb2RlICE9PSBkb21Ob2RlKSB7XG4gICAgICAgICAgICAgICAgICAgIHBhcmVudE5vZGUucmVwbGFjZUNoaWxkKG5ld05vZGUsIGRvbU5vZGUpO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHJldHVybiBuZXdOb2RlO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBmdW5jdGlvbiBkZXN0cm95V2lkZ2V0KGRvbU5vZGUsIHcpIHtcbiAgICAgICAgICAgICAgICBpZiAodHlwZW9mIHcuZGVzdHJveSA9PT0gXCJmdW5jdGlvblwiICYmIGlzV2lkZ2V0KHcpKSB7XG4gICAgICAgICAgICAgICAgICAgIHcuZGVzdHJveShkb21Ob2RlKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIHJlb3JkZXJDaGlsZHJlbihkb21Ob2RlLCBtb3Zlcykge1xuICAgICAgICAgICAgICAgIHZhciBjaGlsZE5vZGVzID0gZG9tTm9kZS5jaGlsZE5vZGVzO1xuICAgICAgICAgICAgICAgIHZhciBrZXlNYXAgPSB7fTtcbiAgICAgICAgICAgICAgICB2YXIgbm9kZTtcbiAgICAgICAgICAgICAgICB2YXIgcmVtb3ZlO1xuICAgICAgICAgICAgICAgIHZhciBpbnNlcnQ7XG5cbiAgICAgICAgICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IG1vdmVzLnJlbW92ZXMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgICAgICAgICAgcmVtb3ZlID0gbW92ZXMucmVtb3Zlc1tpXTtcbiAgICAgICAgICAgICAgICAgICAgbm9kZSA9IGNoaWxkTm9kZXNbcmVtb3ZlLmZyb21dO1xuICAgICAgICAgICAgICAgICAgICBpZiAocmVtb3ZlLmtleSkge1xuICAgICAgICAgICAgICAgICAgICAgICAga2V5TWFwW3JlbW92ZS5rZXldID0gbm9kZTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICBkb21Ob2RlLnJlbW92ZUNoaWxkKG5vZGUpO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHZhciBsZW5ndGggPSBjaGlsZE5vZGVzLmxlbmd0aDtcbiAgICAgICAgICAgICAgICBmb3IgKHZhciBqID0gMDsgaiA8IG1vdmVzLmluc2VydHMubGVuZ3RoOyBqKyspIHtcbiAgICAgICAgICAgICAgICAgICAgaW5zZXJ0ID0gbW92ZXMuaW5zZXJ0c1tqXTtcbiAgICAgICAgICAgICAgICAgICAgbm9kZSA9IGtleU1hcFtpbnNlcnQua2V5XTtcbiAgICAgICAgICAgICAgICAgICAgLy8gdGhpcyBpcyB0aGUgd2VpcmRlc3QgYnVnIGkndmUgZXZlciBzZWVuIGluIHdlYmtpdFxuICAgICAgICAgICAgICAgICAgICBkb21Ob2RlLmluc2VydEJlZm9yZShub2RlLCBpbnNlcnQudG8gPj0gbGVuZ3RoKysgPyBudWxsIDogY2hpbGROb2Rlc1tpbnNlcnQudG9dKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIHJlcGxhY2VSb290KG9sZFJvb3QsIG5ld1Jvb3QpIHtcbiAgICAgICAgICAgICAgICBpZiAob2xkUm9vdCAmJiBuZXdSb290ICYmIG9sZFJvb3QgIT09IG5ld1Jvb3QgJiYgb2xkUm9vdC5wYXJlbnROb2RlKSB7XG4gICAgICAgICAgICAgICAgICAgIG9sZFJvb3QucGFyZW50Tm9kZS5yZXBsYWNlQ2hpbGQobmV3Um9vdCwgb2xkUm9vdCk7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgcmV0dXJuIG5ld1Jvb3Q7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0sIHsgXCIuLi92bm9kZS9pcy13aWRnZXQuanNcIjogMjksIFwiLi4vdm5vZGUvdnBhdGNoLmpzXCI6IDMyLCBcIi4vYXBwbHktcHJvcGVydGllc1wiOiAxNCwgXCIuL3VwZGF0ZS13aWRnZXRcIjogMTkgfV0sIDE4OiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge1xuICAgICAgICAgICAgdmFyIGRvY3VtZW50ID0gcmVxdWlyZShcImdsb2JhbC9kb2N1bWVudFwiKTtcbiAgICAgICAgICAgIHZhciBpc0FycmF5ID0gcmVxdWlyZShcIngtaXMtYXJyYXlcIik7XG5cbiAgICAgICAgICAgIHZhciByZW5kZXIgPSByZXF1aXJlKFwiLi9jcmVhdGUtZWxlbWVudFwiKTtcbiAgICAgICAgICAgIHZhciBkb21JbmRleCA9IHJlcXVpcmUoXCIuL2RvbS1pbmRleFwiKTtcbiAgICAgICAgICAgIHZhciBwYXRjaE9wID0gcmVxdWlyZShcIi4vcGF0Y2gtb3BcIik7XG4gICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IHBhdGNoO1xuXG4gICAgICAgICAgICBmdW5jdGlvbiBwYXRjaChyb290Tm9kZSwgcGF0Y2hlcywgcmVuZGVyT3B0aW9ucykge1xuICAgICAgICAgICAgICAgIHJlbmRlck9wdGlvbnMgPSByZW5kZXJPcHRpb25zIHx8IHt9O1xuICAgICAgICAgICAgICAgIHJlbmRlck9wdGlvbnMucGF0Y2ggPSByZW5kZXJPcHRpb25zLnBhdGNoICYmIHJlbmRlck9wdGlvbnMucGF0Y2ggIT09IHBhdGNoID8gcmVuZGVyT3B0aW9ucy5wYXRjaCA6IHBhdGNoUmVjdXJzaXZlO1xuICAgICAgICAgICAgICAgIHJlbmRlck9wdGlvbnMucmVuZGVyID0gcmVuZGVyT3B0aW9ucy5yZW5kZXIgfHwgcmVuZGVyO1xuXG4gICAgICAgICAgICAgICAgcmV0dXJuIHJlbmRlck9wdGlvbnMucGF0Y2gocm9vdE5vZGUsIHBhdGNoZXMsIHJlbmRlck9wdGlvbnMpO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBmdW5jdGlvbiBwYXRjaFJlY3Vyc2l2ZShyb290Tm9kZSwgcGF0Y2hlcywgcmVuZGVyT3B0aW9ucykge1xuICAgICAgICAgICAgICAgIHZhciBpbmRpY2VzID0gcGF0Y2hJbmRpY2VzKHBhdGNoZXMpO1xuXG4gICAgICAgICAgICAgICAgaWYgKGluZGljZXMubGVuZ3RoID09PSAwKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiByb290Tm9kZTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICB2YXIgaW5kZXggPSBkb21JbmRleChyb290Tm9kZSwgcGF0Y2hlcy5hLCBpbmRpY2VzKTtcbiAgICAgICAgICAgICAgICB2YXIgb3duZXJEb2N1bWVudCA9IHJvb3ROb2RlLm93bmVyRG9jdW1lbnQ7XG5cbiAgICAgICAgICAgICAgICBpZiAoIXJlbmRlck9wdGlvbnMuZG9jdW1lbnQgJiYgb3duZXJEb2N1bWVudCAhPT0gZG9jdW1lbnQpIHtcbiAgICAgICAgICAgICAgICAgICAgcmVuZGVyT3B0aW9ucy5kb2N1bWVudCA9IG93bmVyRG9jdW1lbnQ7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCBpbmRpY2VzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciBub2RlSW5kZXggPSBpbmRpY2VzW2ldO1xuICAgICAgICAgICAgICAgICAgICByb290Tm9kZSA9IGFwcGx5UGF0Y2gocm9vdE5vZGUsIGluZGV4W25vZGVJbmRleF0sIHBhdGNoZXNbbm9kZUluZGV4XSwgcmVuZGVyT3B0aW9ucyk7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgcmV0dXJuIHJvb3ROb2RlO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBmdW5jdGlvbiBhcHBseVBhdGNoKHJvb3ROb2RlLCBkb21Ob2RlLCBwYXRjaExpc3QsIHJlbmRlck9wdGlvbnMpIHtcbiAgICAgICAgICAgICAgICBpZiAoIWRvbU5vZGUpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHJvb3ROb2RlO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHZhciBuZXdOb2RlO1xuXG4gICAgICAgICAgICAgICAgaWYgKGlzQXJyYXkocGF0Y2hMaXN0KSkge1xuICAgICAgICAgICAgICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IHBhdGNoTGlzdC5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgICAgICAgICAgICAgbmV3Tm9kZSA9IHBhdGNoT3AocGF0Y2hMaXN0W2ldLCBkb21Ob2RlLCByZW5kZXJPcHRpb25zKTtcblxuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGRvbU5vZGUgPT09IHJvb3ROb2RlKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcm9vdE5vZGUgPSBuZXdOb2RlO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgbmV3Tm9kZSA9IHBhdGNoT3AocGF0Y2hMaXN0LCBkb21Ob2RlLCByZW5kZXJPcHRpb25zKTtcblxuICAgICAgICAgICAgICAgICAgICBpZiAoZG9tTm9kZSA9PT0gcm9vdE5vZGUpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJvb3ROb2RlID0gbmV3Tm9kZTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHJldHVybiByb290Tm9kZTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZnVuY3Rpb24gcGF0Y2hJbmRpY2VzKHBhdGNoZXMpIHtcbiAgICAgICAgICAgICAgICB2YXIgaW5kaWNlcyA9IFtdO1xuXG4gICAgICAgICAgICAgICAgZm9yICh2YXIga2V5IGluIHBhdGNoZXMpIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKGtleSAhPT0gXCJhXCIpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGluZGljZXMucHVzaChOdW1iZXIoa2V5KSk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICByZXR1cm4gaW5kaWNlcztcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSwgeyBcIi4vY3JlYXRlLWVsZW1lbnRcIjogMTUsIFwiLi9kb20taW5kZXhcIjogMTYsIFwiLi9wYXRjaC1vcFwiOiAxNywgXCJnbG9iYWwvZG9jdW1lbnRcIjogMTAsIFwieC1pcy1hcnJheVwiOiAxMiB9XSwgMTk6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICB2YXIgaXNXaWRnZXQgPSByZXF1aXJlKFwiLi4vdm5vZGUvaXMtd2lkZ2V0LmpzXCIpO1xuXG4gICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IHVwZGF0ZVdpZGdldDtcblxuICAgICAgICAgICAgZnVuY3Rpb24gdXBkYXRlV2lkZ2V0KGEsIGIpIHtcbiAgICAgICAgICAgICAgICBpZiAoaXNXaWRnZXQoYSkgJiYgaXNXaWRnZXQoYikpIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKFwibmFtZVwiIGluIGEgJiYgXCJuYW1lXCIgaW4gYikge1xuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGEuaWQgPT09IGIuaWQ7XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gYS5pbml0ID09PSBiLmluaXQ7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0sIHsgXCIuLi92bm9kZS9pcy13aWRnZXQuanNcIjogMjkgfV0sIDIwOiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge1xuICAgICAgICAgICAgXCJ1c2Ugc3RyaWN0XCI7XG5cbiAgICAgICAgICAgIHZhciBFdlN0b3JlID0gcmVxdWlyZShcImV2LXN0b3JlXCIpO1xuXG4gICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IEV2SG9vaztcblxuICAgICAgICAgICAgZnVuY3Rpb24gRXZIb29rKHZhbHVlKSB7XG4gICAgICAgICAgICAgICAgaWYgKCEodGhpcyBpbnN0YW5jZW9mIEV2SG9vaykpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIG5ldyBFdkhvb2sodmFsdWUpO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHRoaXMudmFsdWUgPSB2YWx1ZTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgRXZIb29rLnByb3RvdHlwZS5ob29rID0gZnVuY3Rpb24gKG5vZGUsIHByb3BlcnR5TmFtZSkge1xuICAgICAgICAgICAgICAgIHZhciBlcyA9IEV2U3RvcmUobm9kZSk7XG4gICAgICAgICAgICAgICAgdmFyIHByb3BOYW1lID0gcHJvcGVydHlOYW1lLnN1YnN0cigzKTtcblxuICAgICAgICAgICAgICAgIGVzW3Byb3BOYW1lXSA9IHRoaXMudmFsdWU7XG4gICAgICAgICAgICB9O1xuXG4gICAgICAgICAgICBFdkhvb2sucHJvdG90eXBlLnVuaG9vayA9IGZ1bmN0aW9uIChub2RlLCBwcm9wZXJ0eU5hbWUpIHtcbiAgICAgICAgICAgICAgICB2YXIgZXMgPSBFdlN0b3JlKG5vZGUpO1xuICAgICAgICAgICAgICAgIHZhciBwcm9wTmFtZSA9IHByb3BlcnR5TmFtZS5zdWJzdHIoMyk7XG5cbiAgICAgICAgICAgICAgICBlc1twcm9wTmFtZV0gPSB1bmRlZmluZWQ7XG4gICAgICAgICAgICB9O1xuICAgICAgICB9LCB7IFwiZXYtc3RvcmVcIjogNyB9XSwgMjE6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICBcInVzZSBzdHJpY3RcIjtcblxuICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBTb2Z0U2V0SG9vaztcblxuICAgICAgICAgICAgZnVuY3Rpb24gU29mdFNldEhvb2sodmFsdWUpIHtcbiAgICAgICAgICAgICAgICBpZiAoISh0aGlzIGluc3RhbmNlb2YgU29mdFNldEhvb2spKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBuZXcgU29mdFNldEhvb2sodmFsdWUpO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHRoaXMudmFsdWUgPSB2YWx1ZTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgU29mdFNldEhvb2sucHJvdG90eXBlLmhvb2sgPSBmdW5jdGlvbiAobm9kZSwgcHJvcGVydHlOYW1lKSB7XG4gICAgICAgICAgICAgICAgaWYgKG5vZGVbcHJvcGVydHlOYW1lXSAhPT0gdGhpcy52YWx1ZSkge1xuICAgICAgICAgICAgICAgICAgICBub2RlW3Byb3BlcnR5TmFtZV0gPSB0aGlzLnZhbHVlO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH07XG4gICAgICAgIH0sIHt9XSwgMjI6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICBcInVzZSBzdHJpY3RcIjtcblxuICAgICAgICAgICAgdmFyIGlzQXJyYXkgPSByZXF1aXJlKFwieC1pcy1hcnJheVwiKTtcblxuICAgICAgICAgICAgdmFyIFZOb2RlID0gcmVxdWlyZShcIi4uL3Zub2RlL3Zub2RlLmpzXCIpO1xuICAgICAgICAgICAgdmFyIFZUZXh0ID0gcmVxdWlyZShcIi4uL3Zub2RlL3Z0ZXh0LmpzXCIpO1xuICAgICAgICAgICAgdmFyIGlzVk5vZGUgPSByZXF1aXJlKFwiLi4vdm5vZGUvaXMtdm5vZGVcIik7XG4gICAgICAgICAgICB2YXIgaXNWVGV4dCA9IHJlcXVpcmUoXCIuLi92bm9kZS9pcy12dGV4dFwiKTtcbiAgICAgICAgICAgIHZhciBpc1dpZGdldCA9IHJlcXVpcmUoXCIuLi92bm9kZS9pcy13aWRnZXRcIik7XG4gICAgICAgICAgICB2YXIgaXNIb29rID0gcmVxdWlyZShcIi4uL3Zub2RlL2lzLXZob29rXCIpO1xuICAgICAgICAgICAgdmFyIGlzVlRodW5rID0gcmVxdWlyZShcIi4uL3Zub2RlL2lzLXRodW5rXCIpO1xuXG4gICAgICAgICAgICB2YXIgcGFyc2VUYWcgPSByZXF1aXJlKFwiLi9wYXJzZS10YWcuanNcIik7XG4gICAgICAgICAgICB2YXIgc29mdFNldEhvb2sgPSByZXF1aXJlKFwiLi9ob29rcy9zb2Z0LXNldC1ob29rLmpzXCIpO1xuICAgICAgICAgICAgdmFyIGV2SG9vayA9IHJlcXVpcmUoXCIuL2hvb2tzL2V2LWhvb2suanNcIik7XG5cbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gaDtcblxuICAgICAgICAgICAgZnVuY3Rpb24gaCh0YWdOYW1lLCBwcm9wZXJ0aWVzLCBjaGlsZHJlbikge1xuICAgICAgICAgICAgICAgIHZhciBjaGlsZE5vZGVzID0gW107XG4gICAgICAgICAgICAgICAgdmFyIHRhZywgcHJvcHMsIGtleSwgbmFtZXNwYWNlO1xuXG4gICAgICAgICAgICAgICAgaWYgKCFjaGlsZHJlbiAmJiBpc0NoaWxkcmVuKHByb3BlcnRpZXMpKSB7XG4gICAgICAgICAgICAgICAgICAgIGNoaWxkcmVuID0gcHJvcGVydGllcztcbiAgICAgICAgICAgICAgICAgICAgcHJvcHMgPSB7fTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICBwcm9wcyA9IHByb3BzIHx8IHByb3BlcnRpZXMgfHwge307XG4gICAgICAgICAgICAgICAgdGFnID0gcGFyc2VUYWcodGFnTmFtZSwgcHJvcHMpO1xuXG4gICAgICAgICAgICAgICAgLy8gc3VwcG9ydCBrZXlzXG4gICAgICAgICAgICAgICAgaWYgKHByb3BzLmhhc093blByb3BlcnR5KFwia2V5XCIpKSB7XG4gICAgICAgICAgICAgICAgICAgIGtleSA9IHByb3BzLmtleTtcbiAgICAgICAgICAgICAgICAgICAgcHJvcHMua2V5ID0gdW5kZWZpbmVkO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIC8vIHN1cHBvcnQgbmFtZXNwYWNlXG4gICAgICAgICAgICAgICAgaWYgKHByb3BzLmhhc093blByb3BlcnR5KFwibmFtZXNwYWNlXCIpKSB7XG4gICAgICAgICAgICAgICAgICAgIG5hbWVzcGFjZSA9IHByb3BzLm5hbWVzcGFjZTtcbiAgICAgICAgICAgICAgICAgICAgcHJvcHMubmFtZXNwYWNlID0gdW5kZWZpbmVkO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIC8vIGZpeCBjdXJzb3IgYnVnXG4gICAgICAgICAgICAgICAgaWYgKHRhZyA9PT0gXCJJTlBVVFwiICYmICFuYW1lc3BhY2UgJiYgcHJvcHMuaGFzT3duUHJvcGVydHkoXCJ2YWx1ZVwiKSAmJiBwcm9wcy52YWx1ZSAhPT0gdW5kZWZpbmVkICYmICFpc0hvb2socHJvcHMudmFsdWUpKSB7XG4gICAgICAgICAgICAgICAgICAgIHByb3BzLnZhbHVlID0gc29mdFNldEhvb2socHJvcHMudmFsdWUpO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHRyYW5zZm9ybVByb3BlcnRpZXMocHJvcHMpO1xuXG4gICAgICAgICAgICAgICAgaWYgKGNoaWxkcmVuICE9PSB1bmRlZmluZWQgJiYgY2hpbGRyZW4gIT09IG51bGwpIHtcbiAgICAgICAgICAgICAgICAgICAgYWRkQ2hpbGQoY2hpbGRyZW4sIGNoaWxkTm9kZXMsIHRhZywgcHJvcHMpO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHJldHVybiBuZXcgVk5vZGUodGFnLCBwcm9wcywgY2hpbGROb2Rlcywga2V5LCBuYW1lc3BhY2UpO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBmdW5jdGlvbiBhZGRDaGlsZChjLCBjaGlsZE5vZGVzLCB0YWcsIHByb3BzKSB7XG4gICAgICAgICAgICAgICAgaWYgKHR5cGVvZiBjID09PSBcInN0cmluZ1wiKSB7XG4gICAgICAgICAgICAgICAgICAgIGNoaWxkTm9kZXMucHVzaChuZXcgVlRleHQoYykpO1xuICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAodHlwZW9mIGMgPT09IFwibnVtYmVyXCIpIHtcbiAgICAgICAgICAgICAgICAgICAgY2hpbGROb2Rlcy5wdXNoKG5ldyBWVGV4dChTdHJpbmcoYykpKTtcbiAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKGlzQ2hpbGQoYykpIHtcbiAgICAgICAgICAgICAgICAgICAgY2hpbGROb2Rlcy5wdXNoKGMpO1xuICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoaXNBcnJheShjKSkge1xuICAgICAgICAgICAgICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IGMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGFkZENoaWxkKGNbaV0sIGNoaWxkTm9kZXMsIHRhZywgcHJvcHMpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfSBlbHNlIGlmIChjID09PSBudWxsIHx8IGMgPT09IHVuZGVmaW5lZCkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgdGhyb3cgVW5leHBlY3RlZFZpcnR1YWxFbGVtZW50KHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGZvcmVpZ25PYmplY3Q6IGMsXG4gICAgICAgICAgICAgICAgICAgICAgICBwYXJlbnRWbm9kZToge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRhZ05hbWU6IHRhZyxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBwcm9wZXJ0aWVzOiBwcm9wc1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIHRyYW5zZm9ybVByb3BlcnRpZXMocHJvcHMpIHtcbiAgICAgICAgICAgICAgICBmb3IgKHZhciBwcm9wTmFtZSBpbiBwcm9wcykge1xuICAgICAgICAgICAgICAgICAgICBpZiAocHJvcHMuaGFzT3duUHJvcGVydHkocHJvcE5hbWUpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICB2YXIgdmFsdWUgPSBwcm9wc1twcm9wTmFtZV07XG5cbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChpc0hvb2sodmFsdWUpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgY29udGludWU7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChwcm9wTmFtZS5zdWJzdHIoMCwgMykgPT09IFwiZXYtXCIpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBhZGQgZXYtZm9vIHN1cHBvcnRcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBwcm9wc1twcm9wTmFtZV0gPSBldkhvb2sodmFsdWUpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBmdW5jdGlvbiBpc0NoaWxkKHgpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gaXNWTm9kZSh4KSB8fCBpc1ZUZXh0KHgpIHx8IGlzV2lkZ2V0KHgpIHx8IGlzVlRodW5rKHgpO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBmdW5jdGlvbiBpc0NoaWxkcmVuKHgpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gdHlwZW9mIHggPT09IFwic3RyaW5nXCIgfHwgaXNBcnJheSh4KSB8fCBpc0NoaWxkKHgpO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBmdW5jdGlvbiBVbmV4cGVjdGVkVmlydHVhbEVsZW1lbnQoZGF0YSkge1xuICAgICAgICAgICAgICAgIHZhciBlcnIgPSBuZXcgRXJyb3IoKTtcblxuICAgICAgICAgICAgICAgIGVyci50eXBlID0gXCJ2aXJ0dWFsLWh5cGVyc2NyaXB0LnVuZXhwZWN0ZWQudmlydHVhbC1lbGVtZW50XCI7XG4gICAgICAgICAgICAgICAgZXJyLm1lc3NhZ2UgPSBcIlVuZXhwZWN0ZWQgdmlydHVhbCBjaGlsZCBwYXNzZWQgdG8gaCgpLlxcblwiICsgXCJFeHBlY3RlZCBhIFZOb2RlIC8gVnRodW5rIC8gVldpZGdldCAvIHN0cmluZyBidXQ6XFxuXCIgKyBcImdvdDpcXG5cIiArIGVycm9yU3RyaW5nKGRhdGEuZm9yZWlnbk9iamVjdCkgKyBcIi5cXG5cIiArIFwiVGhlIHBhcmVudCB2bm9kZSBpczpcXG5cIiArIGVycm9yU3RyaW5nKGRhdGEucGFyZW50Vm5vZGUpO1xuICAgICAgICAgICAgICAgIFwiXFxuXCIgKyBcIlN1Z2dlc3RlZCBmaXg6IGNoYW5nZSB5b3VyIGBoKC4uLiwgWyAuLi4gXSlgIGNhbGxzaXRlLlwiO1xuICAgICAgICAgICAgICAgIGVyci5mb3JlaWduT2JqZWN0ID0gZGF0YS5mb3JlaWduT2JqZWN0O1xuICAgICAgICAgICAgICAgIGVyci5wYXJlbnRWbm9kZSA9IGRhdGEucGFyZW50Vm5vZGU7XG5cbiAgICAgICAgICAgICAgICByZXR1cm4gZXJyO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBmdW5jdGlvbiBlcnJvclN0cmluZyhvYmopIHtcbiAgICAgICAgICAgICAgICB0cnkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gSlNPTi5zdHJpbmdpZnkob2JqLCBudWxsLCBcIiAgICBcIik7XG4gICAgICAgICAgICAgICAgfSBjYXRjaCAoZSkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gU3RyaW5nKG9iaik7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9LCB7IFwiLi4vdm5vZGUvaXMtdGh1bmtcIjogMjUsIFwiLi4vdm5vZGUvaXMtdmhvb2tcIjogMjYsIFwiLi4vdm5vZGUvaXMtdm5vZGVcIjogMjcsIFwiLi4vdm5vZGUvaXMtdnRleHRcIjogMjgsIFwiLi4vdm5vZGUvaXMtd2lkZ2V0XCI6IDI5LCBcIi4uL3Zub2RlL3Zub2RlLmpzXCI6IDMxLCBcIi4uL3Zub2RlL3Z0ZXh0LmpzXCI6IDMzLCBcIi4vaG9va3MvZXYtaG9vay5qc1wiOiAyMCwgXCIuL2hvb2tzL3NvZnQtc2V0LWhvb2suanNcIjogMjEsIFwiLi9wYXJzZS10YWcuanNcIjogMjMsIFwieC1pcy1hcnJheVwiOiAxMiB9XSwgMjM6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICBcInVzZSBzdHJpY3RcIjtcblxuICAgICAgICAgICAgdmFyIHNwbGl0ID0gcmVxdWlyZShcImJyb3dzZXItc3BsaXRcIik7XG5cbiAgICAgICAgICAgIHZhciBjbGFzc0lkU3BsaXQgPSAvKFtcXC4jXT9bYS16QS1aMC05XFx1MDA3Ri1cXHVGRkZGXzotXSspLztcbiAgICAgICAgICAgIHZhciBub3RDbGFzc0lkID0gL15cXC58Iy87XG5cbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gcGFyc2VUYWc7XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIHBhcnNlVGFnKHRhZywgcHJvcHMpIHtcbiAgICAgICAgICAgICAgICBpZiAoIXRhZykge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gXCJESVZcIjtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICB2YXIgbm9JZCA9ICFwcm9wcy5oYXNPd25Qcm9wZXJ0eShcImlkXCIpO1xuXG4gICAgICAgICAgICAgICAgdmFyIHRhZ1BhcnRzID0gc3BsaXQodGFnLCBjbGFzc0lkU3BsaXQpO1xuICAgICAgICAgICAgICAgIHZhciB0YWdOYW1lID0gbnVsbDtcblxuICAgICAgICAgICAgICAgIGlmIChub3RDbGFzc0lkLnRlc3QodGFnUGFydHNbMV0pKSB7XG4gICAgICAgICAgICAgICAgICAgIHRhZ05hbWUgPSBcIkRJVlwiO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHZhciBjbGFzc2VzLCBwYXJ0LCB0eXBlLCBpO1xuXG4gICAgICAgICAgICAgICAgZm9yIChpID0gMDsgaSA8IHRhZ1BhcnRzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICAgICAgICAgIHBhcnQgPSB0YWdQYXJ0c1tpXTtcblxuICAgICAgICAgICAgICAgICAgICBpZiAoIXBhcnQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnRpbnVlO1xuICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgdHlwZSA9IHBhcnQuY2hhckF0KDApO1xuXG4gICAgICAgICAgICAgICAgICAgIGlmICghdGFnTmFtZSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgdGFnTmFtZSA9IHBhcnQ7XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAodHlwZSA9PT0gXCIuXCIpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGNsYXNzZXMgPSBjbGFzc2VzIHx8IFtdO1xuICAgICAgICAgICAgICAgICAgICAgICAgY2xhc3Nlcy5wdXNoKHBhcnQuc3Vic3RyaW5nKDEsIHBhcnQubGVuZ3RoKSk7XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAodHlwZSA9PT0gXCIjXCIgJiYgbm9JZCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgcHJvcHMuaWQgPSBwYXJ0LnN1YnN0cmluZygxLCBwYXJ0Lmxlbmd0aCk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICBpZiAoY2xhc3Nlcykge1xuICAgICAgICAgICAgICAgICAgICBpZiAocHJvcHMuY2xhc3NOYW1lKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBjbGFzc2VzLnB1c2gocHJvcHMuY2xhc3NOYW1lKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgIHByb3BzLmNsYXNzTmFtZSA9IGNsYXNzZXMuam9pbihcIiBcIik7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgcmV0dXJuIHByb3BzLm5hbWVzcGFjZSA/IHRhZ05hbWUgOiB0YWdOYW1lLnRvVXBwZXJDYXNlKCk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0sIHsgXCJicm93c2VyLXNwbGl0XCI6IDUgfV0sIDI0OiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge1xuICAgICAgICAgICAgdmFyIGlzVk5vZGUgPSByZXF1aXJlKFwiLi9pcy12bm9kZVwiKTtcbiAgICAgICAgICAgIHZhciBpc1ZUZXh0ID0gcmVxdWlyZShcIi4vaXMtdnRleHRcIik7XG4gICAgICAgICAgICB2YXIgaXNXaWRnZXQgPSByZXF1aXJlKFwiLi9pcy13aWRnZXRcIik7XG4gICAgICAgICAgICB2YXIgaXNUaHVuayA9IHJlcXVpcmUoXCIuL2lzLXRodW5rXCIpO1xuXG4gICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IGhhbmRsZVRodW5rO1xuXG4gICAgICAgICAgICBmdW5jdGlvbiBoYW5kbGVUaHVuayhhLCBiKSB7XG4gICAgICAgICAgICAgICAgdmFyIHJlbmRlcmVkQSA9IGE7XG4gICAgICAgICAgICAgICAgdmFyIHJlbmRlcmVkQiA9IGI7XG5cbiAgICAgICAgICAgICAgICBpZiAoaXNUaHVuayhiKSkge1xuICAgICAgICAgICAgICAgICAgICByZW5kZXJlZEIgPSByZW5kZXJUaHVuayhiLCBhKTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICBpZiAoaXNUaHVuayhhKSkge1xuICAgICAgICAgICAgICAgICAgICByZW5kZXJlZEEgPSByZW5kZXJUaHVuayhhLCBudWxsKTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgICAgICAgICBhOiByZW5kZXJlZEEsXG4gICAgICAgICAgICAgICAgICAgIGI6IHJlbmRlcmVkQlxuICAgICAgICAgICAgICAgIH07XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIHJlbmRlclRodW5rKHRodW5rLCBwcmV2aW91cykge1xuICAgICAgICAgICAgICAgIHZhciByZW5kZXJlZFRodW5rID0gdGh1bmsudm5vZGU7XG5cbiAgICAgICAgICAgICAgICBpZiAoIXJlbmRlcmVkVGh1bmspIHtcbiAgICAgICAgICAgICAgICAgICAgcmVuZGVyZWRUaHVuayA9IHRodW5rLnZub2RlID0gdGh1bmsucmVuZGVyKHByZXZpb3VzKTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICBpZiAoIShpc1ZOb2RlKHJlbmRlcmVkVGh1bmspIHx8IGlzVlRleHQocmVuZGVyZWRUaHVuaykgfHwgaXNXaWRnZXQocmVuZGVyZWRUaHVuaykpKSB7XG4gICAgICAgICAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcihcInRodW5rIGRpZCBub3QgcmV0dXJuIGEgdmFsaWQgbm9kZVwiKTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICByZXR1cm4gcmVuZGVyZWRUaHVuaztcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSwgeyBcIi4vaXMtdGh1bmtcIjogMjUsIFwiLi9pcy12bm9kZVwiOiAyNywgXCIuL2lzLXZ0ZXh0XCI6IDI4LCBcIi4vaXMtd2lkZ2V0XCI6IDI5IH1dLCAyNTogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHtcbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gaXNUaHVuaztcblxuICAgICAgICAgICAgZnVuY3Rpb24gaXNUaHVuayh0KSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHQgJiYgdC50eXBlID09PSBcIlRodW5rXCI7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0sIHt9XSwgMjY6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IGlzSG9vaztcblxuICAgICAgICAgICAgZnVuY3Rpb24gaXNIb29rKGhvb2spIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gaG9vayAmJiAodHlwZW9mIGhvb2suaG9vayA9PT0gXCJmdW5jdGlvblwiICYmICFob29rLmhhc093blByb3BlcnR5KFwiaG9va1wiKSB8fCB0eXBlb2YgaG9vay51bmhvb2sgPT09IFwiZnVuY3Rpb25cIiAmJiAhaG9vay5oYXNPd25Qcm9wZXJ0eShcInVuaG9va1wiKSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0sIHt9XSwgMjc6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICB2YXIgdmVyc2lvbiA9IHJlcXVpcmUoXCIuL3ZlcnNpb25cIik7XG5cbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gaXNWaXJ0dWFsTm9kZTtcblxuICAgICAgICAgICAgZnVuY3Rpb24gaXNWaXJ0dWFsTm9kZSh4KSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHggJiYgeC50eXBlID09PSBcIlZpcnR1YWxOb2RlXCIgJiYgeC52ZXJzaW9uID09PSB2ZXJzaW9uO1xuICAgICAgICAgICAgfVxuICAgICAgICB9LCB7IFwiLi92ZXJzaW9uXCI6IDMwIH1dLCAyODogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHtcbiAgICAgICAgICAgIHZhciB2ZXJzaW9uID0gcmVxdWlyZShcIi4vdmVyc2lvblwiKTtcblxuICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBpc1ZpcnR1YWxUZXh0O1xuXG4gICAgICAgICAgICBmdW5jdGlvbiBpc1ZpcnR1YWxUZXh0KHgpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4geCAmJiB4LnR5cGUgPT09IFwiVmlydHVhbFRleHRcIiAmJiB4LnZlcnNpb24gPT09IHZlcnNpb247XG4gICAgICAgICAgICB9XG4gICAgICAgIH0sIHsgXCIuL3ZlcnNpb25cIjogMzAgfV0sIDI5OiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge1xuICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBpc1dpZGdldDtcblxuICAgICAgICAgICAgZnVuY3Rpb24gaXNXaWRnZXQodykge1xuICAgICAgICAgICAgICAgIHJldHVybiB3ICYmIHcudHlwZSA9PT0gXCJXaWRnZXRcIjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSwge31dLCAzMDogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHtcbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gXCIyXCI7XG4gICAgICAgIH0sIHt9XSwgMzE6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICB2YXIgdmVyc2lvbiA9IHJlcXVpcmUoXCIuL3ZlcnNpb25cIik7XG4gICAgICAgICAgICB2YXIgaXNWTm9kZSA9IHJlcXVpcmUoXCIuL2lzLXZub2RlXCIpO1xuICAgICAgICAgICAgdmFyIGlzV2lkZ2V0ID0gcmVxdWlyZShcIi4vaXMtd2lkZ2V0XCIpO1xuICAgICAgICAgICAgdmFyIGlzVGh1bmsgPSByZXF1aXJlKFwiLi9pcy10aHVua1wiKTtcbiAgICAgICAgICAgIHZhciBpc1ZIb29rID0gcmVxdWlyZShcIi4vaXMtdmhvb2tcIik7XG5cbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gVmlydHVhbE5vZGU7XG5cbiAgICAgICAgICAgIHZhciBub1Byb3BlcnRpZXMgPSB7fTtcbiAgICAgICAgICAgIHZhciBub0NoaWxkcmVuID0gW107XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIFZpcnR1YWxOb2RlKHRhZ05hbWUsIHByb3BlcnRpZXMsIGNoaWxkcmVuLCBrZXksIG5hbWVzcGFjZSkge1xuICAgICAgICAgICAgICAgIHRoaXMudGFnTmFtZSA9IHRhZ05hbWU7XG4gICAgICAgICAgICAgICAgdGhpcy5wcm9wZXJ0aWVzID0gcHJvcGVydGllcyB8fCBub1Byb3BlcnRpZXM7XG4gICAgICAgICAgICAgICAgdGhpcy5jaGlsZHJlbiA9IGNoaWxkcmVuIHx8IG5vQ2hpbGRyZW47XG4gICAgICAgICAgICAgICAgdGhpcy5rZXkgPSBrZXkgIT0gbnVsbCA/IFN0cmluZyhrZXkpIDogdW5kZWZpbmVkO1xuICAgICAgICAgICAgICAgIHRoaXMubmFtZXNwYWNlID0gdHlwZW9mIG5hbWVzcGFjZSA9PT0gXCJzdHJpbmdcIiA/IG5hbWVzcGFjZSA6IG51bGw7XG5cbiAgICAgICAgICAgICAgICB2YXIgY291bnQgPSBjaGlsZHJlbiAmJiBjaGlsZHJlbi5sZW5ndGggfHwgMDtcbiAgICAgICAgICAgICAgICB2YXIgZGVzY2VuZGFudHMgPSAwO1xuICAgICAgICAgICAgICAgIHZhciBoYXNXaWRnZXRzID0gZmFsc2U7XG4gICAgICAgICAgICAgICAgdmFyIGhhc1RodW5rcyA9IGZhbHNlO1xuICAgICAgICAgICAgICAgIHZhciBkZXNjZW5kYW50SG9va3MgPSBmYWxzZTtcbiAgICAgICAgICAgICAgICB2YXIgaG9va3M7XG5cbiAgICAgICAgICAgICAgICBmb3IgKHZhciBwcm9wTmFtZSBpbiBwcm9wZXJ0aWVzKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmIChwcm9wZXJ0aWVzLmhhc093blByb3BlcnR5KHByb3BOYW1lKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgdmFyIHByb3BlcnR5ID0gcHJvcGVydGllc1twcm9wTmFtZV07XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoaXNWSG9vayhwcm9wZXJ0eSkgJiYgcHJvcGVydHkudW5ob29rKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKCFob29rcykge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBob29rcyA9IHt9O1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGhvb2tzW3Byb3BOYW1lXSA9IHByb3BlcnR5O1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCBjb3VudDsgaSsrKSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciBjaGlsZCA9IGNoaWxkcmVuW2ldO1xuICAgICAgICAgICAgICAgICAgICBpZiAoaXNWTm9kZShjaGlsZCkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGRlc2NlbmRhbnRzICs9IGNoaWxkLmNvdW50IHx8IDA7XG5cbiAgICAgICAgICAgICAgICAgICAgICAgIGlmICghaGFzV2lkZ2V0cyAmJiBjaGlsZC5oYXNXaWRnZXRzKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaGFzV2lkZ2V0cyA9IHRydWU7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgICAgIGlmICghaGFzVGh1bmtzICYmIGNoaWxkLmhhc1RodW5rcykge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGhhc1RodW5rcyA9IHRydWU7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgICAgIGlmICghZGVzY2VuZGFudEhvb2tzICYmIChjaGlsZC5ob29rcyB8fCBjaGlsZC5kZXNjZW5kYW50SG9va3MpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgZGVzY2VuZGFudEhvb2tzID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIGlmICghaGFzV2lkZ2V0cyAmJiBpc1dpZGdldChjaGlsZCkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmICh0eXBlb2YgY2hpbGQuZGVzdHJveSA9PT0gXCJmdW5jdGlvblwiKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaGFzV2lkZ2V0cyA9IHRydWU7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoIWhhc1RodW5rcyAmJiBpc1RodW5rKGNoaWxkKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgaGFzVGh1bmtzID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHRoaXMuY291bnQgPSBjb3VudCArIGRlc2NlbmRhbnRzO1xuICAgICAgICAgICAgICAgIHRoaXMuaGFzV2lkZ2V0cyA9IGhhc1dpZGdldHM7XG4gICAgICAgICAgICAgICAgdGhpcy5oYXNUaHVua3MgPSBoYXNUaHVua3M7XG4gICAgICAgICAgICAgICAgdGhpcy5ob29rcyA9IGhvb2tzO1xuICAgICAgICAgICAgICAgIHRoaXMuZGVzY2VuZGFudEhvb2tzID0gZGVzY2VuZGFudEhvb2tzO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBWaXJ0dWFsTm9kZS5wcm90b3R5cGUudmVyc2lvbiA9IHZlcnNpb247XG4gICAgICAgICAgICBWaXJ0dWFsTm9kZS5wcm90b3R5cGUudHlwZSA9IFwiVmlydHVhbE5vZGVcIjtcbiAgICAgICAgfSwgeyBcIi4vaXMtdGh1bmtcIjogMjUsIFwiLi9pcy12aG9va1wiOiAyNiwgXCIuL2lzLXZub2RlXCI6IDI3LCBcIi4vaXMtd2lkZ2V0XCI6IDI5LCBcIi4vdmVyc2lvblwiOiAzMCB9XSwgMzI6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICB2YXIgdmVyc2lvbiA9IHJlcXVpcmUoXCIuL3ZlcnNpb25cIik7XG5cbiAgICAgICAgICAgIFZpcnR1YWxQYXRjaC5OT05FID0gMDtcbiAgICAgICAgICAgIFZpcnR1YWxQYXRjaC5WVEVYVCA9IDE7XG4gICAgICAgICAgICBWaXJ0dWFsUGF0Y2guVk5PREUgPSAyO1xuICAgICAgICAgICAgVmlydHVhbFBhdGNoLldJREdFVCA9IDM7XG4gICAgICAgICAgICBWaXJ0dWFsUGF0Y2guUFJPUFMgPSA0O1xuICAgICAgICAgICAgVmlydHVhbFBhdGNoLk9SREVSID0gNTtcbiAgICAgICAgICAgIFZpcnR1YWxQYXRjaC5JTlNFUlQgPSA2O1xuICAgICAgICAgICAgVmlydHVhbFBhdGNoLlJFTU9WRSA9IDc7XG4gICAgICAgICAgICBWaXJ0dWFsUGF0Y2guVEhVTksgPSA4O1xuXG4gICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IFZpcnR1YWxQYXRjaDtcblxuICAgICAgICAgICAgZnVuY3Rpb24gVmlydHVhbFBhdGNoKHR5cGUsIHZOb2RlLCBwYXRjaCkge1xuICAgICAgICAgICAgICAgIHRoaXMudHlwZSA9IE51bWJlcih0eXBlKTtcbiAgICAgICAgICAgICAgICB0aGlzLnZOb2RlID0gdk5vZGU7XG4gICAgICAgICAgICAgICAgdGhpcy5wYXRjaCA9IHBhdGNoO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBWaXJ0dWFsUGF0Y2gucHJvdG90eXBlLnZlcnNpb24gPSB2ZXJzaW9uO1xuICAgICAgICAgICAgVmlydHVhbFBhdGNoLnByb3RvdHlwZS50eXBlID0gXCJWaXJ0dWFsUGF0Y2hcIjtcbiAgICAgICAgfSwgeyBcIi4vdmVyc2lvblwiOiAzMCB9XSwgMzM6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICB2YXIgdmVyc2lvbiA9IHJlcXVpcmUoXCIuL3ZlcnNpb25cIik7XG5cbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gVmlydHVhbFRleHQ7XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIFZpcnR1YWxUZXh0KHRleHQpIHtcbiAgICAgICAgICAgICAgICB0aGlzLnRleHQgPSBTdHJpbmcodGV4dCk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIFZpcnR1YWxUZXh0LnByb3RvdHlwZS52ZXJzaW9uID0gdmVyc2lvbjtcbiAgICAgICAgICAgIFZpcnR1YWxUZXh0LnByb3RvdHlwZS50eXBlID0gXCJWaXJ0dWFsVGV4dFwiO1xuICAgICAgICB9LCB7IFwiLi92ZXJzaW9uXCI6IDMwIH1dLCAzNDogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHtcbiAgICAgICAgICAgIHZhciBpc09iamVjdCA9IHJlcXVpcmUoXCJpcy1vYmplY3RcIik7XG4gICAgICAgICAgICB2YXIgaXNIb29rID0gcmVxdWlyZShcIi4uL3Zub2RlL2lzLXZob29rXCIpO1xuXG4gICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IGRpZmZQcm9wcztcblxuICAgICAgICAgICAgZnVuY3Rpb24gZGlmZlByb3BzKGEsIGIpIHtcbiAgICAgICAgICAgICAgICB2YXIgZGlmZjtcblxuICAgICAgICAgICAgICAgIGZvciAodmFyIGFLZXkgaW4gYSkge1xuICAgICAgICAgICAgICAgICAgICBpZiAoIShhS2V5IGluIGIpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBkaWZmID0gZGlmZiB8fCB7fTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGRpZmZbYUtleV0gPSB1bmRlZmluZWQ7XG4gICAgICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgICAgICB2YXIgYVZhbHVlID0gYVthS2V5XTtcbiAgICAgICAgICAgICAgICAgICAgdmFyIGJWYWx1ZSA9IGJbYUtleV07XG5cbiAgICAgICAgICAgICAgICAgICAgaWYgKGFWYWx1ZSA9PT0gYlZhbHVlKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBjb250aW51ZTtcbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIGlmIChpc09iamVjdChhVmFsdWUpICYmIGlzT2JqZWN0KGJWYWx1ZSkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChnZXRQcm90b3R5cGUoYlZhbHVlKSAhPT0gZ2V0UHJvdG90eXBlKGFWYWx1ZSkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBkaWZmID0gZGlmZiB8fCB7fTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBkaWZmW2FLZXldID0gYlZhbHVlO1xuICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIGlmIChpc0hvb2soYlZhbHVlKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRpZmYgPSBkaWZmIHx8IHt9O1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRpZmZbYUtleV0gPSBiVmFsdWU7XG4gICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZhciBvYmplY3REaWZmID0gZGlmZlByb3BzKGFWYWx1ZSwgYlZhbHVlKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAob2JqZWN0RGlmZikge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBkaWZmID0gZGlmZiB8fCB7fTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZGlmZlthS2V5XSA9IG9iamVjdERpZmY7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgZGlmZiA9IGRpZmYgfHwge307XG4gICAgICAgICAgICAgICAgICAgICAgICBkaWZmW2FLZXldID0gYlZhbHVlO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgZm9yICh2YXIgYktleSBpbiBiKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmICghKGJLZXkgaW4gYSkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGRpZmYgPSBkaWZmIHx8IHt9O1xuICAgICAgICAgICAgICAgICAgICAgICAgZGlmZltiS2V5XSA9IGJbYktleV07XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICByZXR1cm4gZGlmZjtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZnVuY3Rpb24gZ2V0UHJvdG90eXBlKHZhbHVlKSB7XG4gICAgICAgICAgICAgICAgaWYgKE9iamVjdC5nZXRQcm90b3R5cGVPZikge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gT2JqZWN0LmdldFByb3RvdHlwZU9mKHZhbHVlKTtcbiAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKHZhbHVlLl9fcHJvdG9fXykge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gdmFsdWUuX19wcm90b19fO1xuICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAodmFsdWUuY29uc3RydWN0b3IpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHZhbHVlLmNvbnN0cnVjdG9yLnByb3RvdHlwZTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH0sIHsgXCIuLi92bm9kZS9pcy12aG9va1wiOiAyNiwgXCJpcy1vYmplY3RcIjogMTEgfV0sIDM1OiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge1xuICAgICAgICAgICAgdmFyIGlzQXJyYXkgPSByZXF1aXJlKFwieC1pcy1hcnJheVwiKTtcblxuICAgICAgICAgICAgdmFyIFZQYXRjaCA9IHJlcXVpcmUoXCIuLi92bm9kZS92cGF0Y2hcIik7XG4gICAgICAgICAgICB2YXIgaXNWTm9kZSA9IHJlcXVpcmUoXCIuLi92bm9kZS9pcy12bm9kZVwiKTtcbiAgICAgICAgICAgIHZhciBpc1ZUZXh0ID0gcmVxdWlyZShcIi4uL3Zub2RlL2lzLXZ0ZXh0XCIpO1xuICAgICAgICAgICAgdmFyIGlzV2lkZ2V0ID0gcmVxdWlyZShcIi4uL3Zub2RlL2lzLXdpZGdldFwiKTtcbiAgICAgICAgICAgIHZhciBpc1RodW5rID0gcmVxdWlyZShcIi4uL3Zub2RlL2lzLXRodW5rXCIpO1xuICAgICAgICAgICAgdmFyIGhhbmRsZVRodW5rID0gcmVxdWlyZShcIi4uL3Zub2RlL2hhbmRsZS10aHVua1wiKTtcblxuICAgICAgICAgICAgdmFyIGRpZmZQcm9wcyA9IHJlcXVpcmUoXCIuL2RpZmYtcHJvcHNcIik7XG5cbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gZGlmZjtcblxuICAgICAgICAgICAgZnVuY3Rpb24gZGlmZihhLCBiKSB7XG4gICAgICAgICAgICAgICAgdmFyIHBhdGNoID0geyBhOiBhIH07XG4gICAgICAgICAgICAgICAgd2FsayhhLCBiLCBwYXRjaCwgMCk7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHBhdGNoO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBmdW5jdGlvbiB3YWxrKGEsIGIsIHBhdGNoLCBpbmRleCkge1xuICAgICAgICAgICAgICAgIGlmIChhID09PSBiKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICB2YXIgYXBwbHkgPSBwYXRjaFtpbmRleF07XG4gICAgICAgICAgICAgICAgdmFyIGFwcGx5Q2xlYXIgPSBmYWxzZTtcblxuICAgICAgICAgICAgICAgIGlmIChpc1RodW5rKGEpIHx8IGlzVGh1bmsoYikpIHtcbiAgICAgICAgICAgICAgICAgICAgdGh1bmtzKGEsIGIsIHBhdGNoLCBpbmRleCk7XG4gICAgICAgICAgICAgICAgfSBlbHNlIGlmIChiID09IG51bGwpIHtcblxuICAgICAgICAgICAgICAgICAgICAvLyBJZiBhIGlzIGEgd2lkZ2V0IHdlIHdpbGwgYWRkIGEgcmVtb3ZlIHBhdGNoIGZvciBpdFxuICAgICAgICAgICAgICAgICAgICAvLyBPdGhlcndpc2UgYW55IGNoaWxkIHdpZGdldHMvaG9va3MgbXVzdCBiZSBkZXN0cm95ZWQuXG4gICAgICAgICAgICAgICAgICAgIC8vIFRoaXMgcHJldmVudHMgYWRkaW5nIHR3byByZW1vdmUgcGF0Y2hlcyBmb3IgYSB3aWRnZXQuXG4gICAgICAgICAgICAgICAgICAgIGlmICghaXNXaWRnZXQoYSkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGNsZWFyU3RhdGUoYSwgcGF0Y2gsIGluZGV4KTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGFwcGx5ID0gcGF0Y2hbaW5kZXhdO1xuICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgYXBwbHkgPSBhcHBlbmRQYXRjaChhcHBseSwgbmV3IFZQYXRjaChWUGF0Y2guUkVNT1ZFLCBhLCBiKSk7XG4gICAgICAgICAgICAgICAgfSBlbHNlIGlmIChpc1ZOb2RlKGIpKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmIChpc1ZOb2RlKGEpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoYS50YWdOYW1lID09PSBiLnRhZ05hbWUgJiYgYS5uYW1lc3BhY2UgPT09IGIubmFtZXNwYWNlICYmIGEua2V5ID09PSBiLmtleSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZhciBwcm9wc1BhdGNoID0gZGlmZlByb3BzKGEucHJvcGVydGllcywgYi5wcm9wZXJ0aWVzKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAocHJvcHNQYXRjaCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBhcHBseSA9IGFwcGVuZFBhdGNoKGFwcGx5LCBuZXcgVlBhdGNoKFZQYXRjaC5QUk9QUywgYSwgcHJvcHNQYXRjaCkpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBhcHBseSA9IGRpZmZDaGlsZHJlbihhLCBiLCBwYXRjaCwgYXBwbHksIGluZGV4KTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgYXBwbHkgPSBhcHBlbmRQYXRjaChhcHBseSwgbmV3IFZQYXRjaChWUGF0Y2guVk5PREUsIGEsIGIpKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBhcHBseUNsZWFyID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGFwcGx5ID0gYXBwZW5kUGF0Y2goYXBwbHksIG5ldyBWUGF0Y2goVlBhdGNoLlZOT0RFLCBhLCBiKSk7XG4gICAgICAgICAgICAgICAgICAgICAgICBhcHBseUNsZWFyID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoaXNWVGV4dChiKSkge1xuICAgICAgICAgICAgICAgICAgICBpZiAoIWlzVlRleHQoYSkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGFwcGx5ID0gYXBwZW5kUGF0Y2goYXBwbHksIG5ldyBWUGF0Y2goVlBhdGNoLlZURVhULCBhLCBiKSk7XG4gICAgICAgICAgICAgICAgICAgICAgICBhcHBseUNsZWFyID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIGlmIChhLnRleHQgIT09IGIudGV4dCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgYXBwbHkgPSBhcHBlbmRQYXRjaChhcHBseSwgbmV3IFZQYXRjaChWUGF0Y2guVlRFWFQsIGEsIGIpKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoaXNXaWRnZXQoYikpIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKCFpc1dpZGdldChhKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgYXBwbHlDbGVhciA9IHRydWU7XG4gICAgICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgICAgICBhcHBseSA9IGFwcGVuZFBhdGNoKGFwcGx5LCBuZXcgVlBhdGNoKFZQYXRjaC5XSURHRVQsIGEsIGIpKTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICBpZiAoYXBwbHkpIHtcbiAgICAgICAgICAgICAgICAgICAgcGF0Y2hbaW5kZXhdID0gYXBwbHk7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgaWYgKGFwcGx5Q2xlYXIpIHtcbiAgICAgICAgICAgICAgICAgICAgY2xlYXJTdGF0ZShhLCBwYXRjaCwgaW5kZXgpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZnVuY3Rpb24gZGlmZkNoaWxkcmVuKGEsIGIsIHBhdGNoLCBhcHBseSwgaW5kZXgpIHtcbiAgICAgICAgICAgICAgICB2YXIgYUNoaWxkcmVuID0gYS5jaGlsZHJlbjtcbiAgICAgICAgICAgICAgICB2YXIgb3JkZXJlZFNldCA9IHJlb3JkZXIoYUNoaWxkcmVuLCBiLmNoaWxkcmVuKTtcbiAgICAgICAgICAgICAgICB2YXIgYkNoaWxkcmVuID0gb3JkZXJlZFNldC5jaGlsZHJlbjtcblxuICAgICAgICAgICAgICAgIHZhciBhTGVuID0gYUNoaWxkcmVuLmxlbmd0aDtcbiAgICAgICAgICAgICAgICB2YXIgYkxlbiA9IGJDaGlsZHJlbi5sZW5ndGg7XG4gICAgICAgICAgICAgICAgdmFyIGxlbiA9IGFMZW4gPiBiTGVuID8gYUxlbiA6IGJMZW47XG5cbiAgICAgICAgICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IGxlbjsgaSsrKSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciBsZWZ0Tm9kZSA9IGFDaGlsZHJlbltpXTtcbiAgICAgICAgICAgICAgICAgICAgdmFyIHJpZ2h0Tm9kZSA9IGJDaGlsZHJlbltpXTtcbiAgICAgICAgICAgICAgICAgICAgaW5kZXggKz0gMTtcblxuICAgICAgICAgICAgICAgICAgICBpZiAoIWxlZnROb2RlKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAocmlnaHROb2RlKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gRXhjZXNzIG5vZGVzIGluIGIgbmVlZCB0byBiZSBhZGRlZFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGFwcGx5ID0gYXBwZW5kUGF0Y2goYXBwbHksIG5ldyBWUGF0Y2goVlBhdGNoLklOU0VSVCwgbnVsbCwgcmlnaHROb2RlKSk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICB3YWxrKGxlZnROb2RlLCByaWdodE5vZGUsIHBhdGNoLCBpbmRleCk7XG4gICAgICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgICAgICBpZiAoaXNWTm9kZShsZWZ0Tm9kZSkgJiYgbGVmdE5vZGUuY291bnQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGluZGV4ICs9IGxlZnROb2RlLmNvdW50O1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgaWYgKG9yZGVyZWRTZXQubW92ZXMpIHtcbiAgICAgICAgICAgICAgICAgICAgLy8gUmVvcmRlciBub2RlcyBsYXN0XG4gICAgICAgICAgICAgICAgICAgIGFwcGx5ID0gYXBwZW5kUGF0Y2goYXBwbHksIG5ldyBWUGF0Y2goVlBhdGNoLk9SREVSLCBhLCBvcmRlcmVkU2V0Lm1vdmVzKSk7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgcmV0dXJuIGFwcGx5O1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBmdW5jdGlvbiBjbGVhclN0YXRlKHZOb2RlLCBwYXRjaCwgaW5kZXgpIHtcbiAgICAgICAgICAgICAgICAvLyBUT0RPOiBNYWtlIHRoaXMgYSBzaW5nbGUgd2Fsaywgbm90IHR3b1xuICAgICAgICAgICAgICAgIHVuaG9vayh2Tm9kZSwgcGF0Y2gsIGluZGV4KTtcbiAgICAgICAgICAgICAgICBkZXN0cm95V2lkZ2V0cyh2Tm9kZSwgcGF0Y2gsIGluZGV4KTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgLy8gUGF0Y2ggcmVjb3JkcyBmb3IgYWxsIGRlc3Ryb3llZCB3aWRnZXRzIG11c3QgYmUgYWRkZWQgYmVjYXVzZSB3ZSBuZWVkXG4gICAgICAgICAgICAvLyBhIERPTSBub2RlIHJlZmVyZW5jZSBmb3IgdGhlIGRlc3Ryb3kgZnVuY3Rpb25cbiAgICAgICAgICAgIGZ1bmN0aW9uIGRlc3Ryb3lXaWRnZXRzKHZOb2RlLCBwYXRjaCwgaW5kZXgpIHtcbiAgICAgICAgICAgICAgICBpZiAoaXNXaWRnZXQodk5vZGUpKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmICh0eXBlb2Ygdk5vZGUuZGVzdHJveSA9PT0gXCJmdW5jdGlvblwiKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBwYXRjaFtpbmRleF0gPSBhcHBlbmRQYXRjaChwYXRjaFtpbmRleF0sIG5ldyBWUGF0Y2goVlBhdGNoLlJFTU9WRSwgdk5vZGUsIG51bGwpKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoaXNWTm9kZSh2Tm9kZSkgJiYgKHZOb2RlLmhhc1dpZGdldHMgfHwgdk5vZGUuaGFzVGh1bmtzKSkge1xuICAgICAgICAgICAgICAgICAgICB2YXIgY2hpbGRyZW4gPSB2Tm9kZS5jaGlsZHJlbjtcbiAgICAgICAgICAgICAgICAgICAgdmFyIGxlbiA9IGNoaWxkcmVuLmxlbmd0aDtcbiAgICAgICAgICAgICAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCBsZW47IGkrKykge1xuICAgICAgICAgICAgICAgICAgICAgICAgdmFyIGNoaWxkID0gY2hpbGRyZW5baV07XG4gICAgICAgICAgICAgICAgICAgICAgICBpbmRleCArPSAxO1xuXG4gICAgICAgICAgICAgICAgICAgICAgICBkZXN0cm95V2lkZ2V0cyhjaGlsZCwgcGF0Y2gsIGluZGV4KTtcblxuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGlzVk5vZGUoY2hpbGQpICYmIGNoaWxkLmNvdW50KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaW5kZXggKz0gY2hpbGQuY291bnQ7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKGlzVGh1bmsodk5vZGUpKSB7XG4gICAgICAgICAgICAgICAgICAgIHRodW5rcyh2Tm9kZSwgbnVsbCwgcGF0Y2gsIGluZGV4KTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIC8vIENyZWF0ZSBhIHN1Yi1wYXRjaCBmb3IgdGh1bmtzXG4gICAgICAgICAgICBmdW5jdGlvbiB0aHVua3MoYSwgYiwgcGF0Y2gsIGluZGV4KSB7XG4gICAgICAgICAgICAgICAgdmFyIG5vZGVzID0gaGFuZGxlVGh1bmsoYSwgYik7XG4gICAgICAgICAgICAgICAgdmFyIHRodW5rUGF0Y2ggPSBkaWZmKG5vZGVzLmEsIG5vZGVzLmIpO1xuICAgICAgICAgICAgICAgIGlmIChoYXNQYXRjaGVzKHRodW5rUGF0Y2gpKSB7XG4gICAgICAgICAgICAgICAgICAgIHBhdGNoW2luZGV4XSA9IG5ldyBWUGF0Y2goVlBhdGNoLlRIVU5LLCBudWxsLCB0aHVua1BhdGNoKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIGhhc1BhdGNoZXMocGF0Y2gpIHtcbiAgICAgICAgICAgICAgICBmb3IgKHZhciBpbmRleCBpbiBwYXRjaCkge1xuICAgICAgICAgICAgICAgICAgICBpZiAoaW5kZXggIT09IFwiYVwiKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgLy8gRXhlY3V0ZSBob29rcyB3aGVuIHR3byBub2RlcyBhcmUgaWRlbnRpY2FsXG4gICAgICAgICAgICBmdW5jdGlvbiB1bmhvb2sodk5vZGUsIHBhdGNoLCBpbmRleCkge1xuICAgICAgICAgICAgICAgIGlmIChpc1ZOb2RlKHZOb2RlKSkge1xuICAgICAgICAgICAgICAgICAgICBpZiAodk5vZGUuaG9va3MpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHBhdGNoW2luZGV4XSA9IGFwcGVuZFBhdGNoKHBhdGNoW2luZGV4XSwgbmV3IFZQYXRjaChWUGF0Y2guUFJPUFMsIHZOb2RlLCB1bmRlZmluZWRLZXlzKHZOb2RlLmhvb2tzKSkpO1xuICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgaWYgKHZOb2RlLmRlc2NlbmRhbnRIb29rcyB8fCB2Tm9kZS5oYXNUaHVua3MpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHZhciBjaGlsZHJlbiA9IHZOb2RlLmNoaWxkcmVuO1xuICAgICAgICAgICAgICAgICAgICAgICAgdmFyIGxlbiA9IGNoaWxkcmVuLmxlbmd0aDtcbiAgICAgICAgICAgICAgICAgICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgbGVuOyBpKyspIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB2YXIgY2hpbGQgPSBjaGlsZHJlbltpXTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpbmRleCArPSAxO1xuXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdW5ob29rKGNoaWxkLCBwYXRjaCwgaW5kZXgpO1xuXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGlzVk5vZGUoY2hpbGQpICYmIGNoaWxkLmNvdW50KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGluZGV4ICs9IGNoaWxkLmNvdW50O1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoaXNUaHVuayh2Tm9kZSkpIHtcbiAgICAgICAgICAgICAgICAgICAgdGh1bmtzKHZOb2RlLCBudWxsLCBwYXRjaCwgaW5kZXgpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZnVuY3Rpb24gdW5kZWZpbmVkS2V5cyhvYmopIHtcbiAgICAgICAgICAgICAgICB2YXIgcmVzdWx0ID0ge307XG5cbiAgICAgICAgICAgICAgICBmb3IgKHZhciBrZXkgaW4gb2JqKSB7XG4gICAgICAgICAgICAgICAgICAgIHJlc3VsdFtrZXldID0gdW5kZWZpbmVkO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHJldHVybiByZXN1bHQ7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIC8vIExpc3QgZGlmZiwgbmFpdmUgbGVmdCB0byByaWdodCByZW9yZGVyaW5nXG4gICAgICAgICAgICBmdW5jdGlvbiByZW9yZGVyKGFDaGlsZHJlbiwgYkNoaWxkcmVuKSB7XG4gICAgICAgICAgICAgICAgLy8gTyhNKSB0aW1lLCBPKE0pIG1lbW9yeVxuICAgICAgICAgICAgICAgIHZhciBiQ2hpbGRJbmRleCA9IGtleUluZGV4KGJDaGlsZHJlbik7XG4gICAgICAgICAgICAgICAgdmFyIGJLZXlzID0gYkNoaWxkSW5kZXgua2V5cztcbiAgICAgICAgICAgICAgICB2YXIgYkZyZWUgPSBiQ2hpbGRJbmRleC5mcmVlO1xuXG4gICAgICAgICAgICAgICAgaWYgKGJGcmVlLmxlbmd0aCA9PT0gYkNoaWxkcmVuLmxlbmd0aCkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgICAgICAgICAgICAgY2hpbGRyZW46IGJDaGlsZHJlbixcbiAgICAgICAgICAgICAgICAgICAgICAgIG1vdmVzOiBudWxsXG4gICAgICAgICAgICAgICAgICAgIH07XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgLy8gTyhOKSB0aW1lLCBPKE4pIG1lbW9yeVxuICAgICAgICAgICAgICAgIHZhciBhQ2hpbGRJbmRleCA9IGtleUluZGV4KGFDaGlsZHJlbik7XG4gICAgICAgICAgICAgICAgdmFyIGFLZXlzID0gYUNoaWxkSW5kZXgua2V5cztcbiAgICAgICAgICAgICAgICB2YXIgYUZyZWUgPSBhQ2hpbGRJbmRleC5mcmVlO1xuXG4gICAgICAgICAgICAgICAgaWYgKGFGcmVlLmxlbmd0aCA9PT0gYUNoaWxkcmVuLmxlbmd0aCkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgICAgICAgICAgICAgY2hpbGRyZW46IGJDaGlsZHJlbixcbiAgICAgICAgICAgICAgICAgICAgICAgIG1vdmVzOiBudWxsXG4gICAgICAgICAgICAgICAgICAgIH07XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgLy8gTyhNQVgoTiwgTSkpIG1lbW9yeVxuICAgICAgICAgICAgICAgIHZhciBuZXdDaGlsZHJlbiA9IFtdO1xuXG4gICAgICAgICAgICAgICAgdmFyIGZyZWVJbmRleCA9IDA7XG4gICAgICAgICAgICAgICAgdmFyIGZyZWVDb3VudCA9IGJGcmVlLmxlbmd0aDtcbiAgICAgICAgICAgICAgICB2YXIgZGVsZXRlZEl0ZW1zID0gMDtcblxuICAgICAgICAgICAgICAgIC8vIEl0ZXJhdGUgdGhyb3VnaCBhIGFuZCBtYXRjaCBhIG5vZGUgaW4gYlxuICAgICAgICAgICAgICAgIC8vIE8oTikgdGltZSxcbiAgICAgICAgICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IGFDaGlsZHJlbi5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgICAgICAgICB2YXIgYUl0ZW0gPSBhQ2hpbGRyZW5baV07XG4gICAgICAgICAgICAgICAgICAgIHZhciBpdGVtSW5kZXg7XG5cbiAgICAgICAgICAgICAgICAgICAgaWYgKGFJdGVtLmtleSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGJLZXlzLmhhc093blByb3BlcnR5KGFJdGVtLmtleSkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBNYXRjaCB1cCB0aGUgb2xkIGtleXNcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpdGVtSW5kZXggPSBiS2V5c1thSXRlbS5rZXldO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIG5ld0NoaWxkcmVuLnB1c2goYkNoaWxkcmVuW2l0ZW1JbmRleF0pO1xuICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBSZW1vdmUgb2xkIGtleWVkIGl0ZW1zXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaXRlbUluZGV4ID0gaSAtIGRlbGV0ZWRJdGVtcysrO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIG5ld0NoaWxkcmVuLnB1c2gobnVsbCk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAvLyBNYXRjaCB0aGUgaXRlbSBpbiBhIHdpdGggdGhlIG5leHQgZnJlZSBpdGVtIGluIGJcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChmcmVlSW5kZXggPCBmcmVlQ291bnQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpdGVtSW5kZXggPSBiRnJlZVtmcmVlSW5kZXgrK107XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgbmV3Q2hpbGRyZW4ucHVzaChiQ2hpbGRyZW5baXRlbUluZGV4XSk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIFRoZXJlIGFyZSBubyBmcmVlIGl0ZW1zIGluIGIgdG8gbWF0Y2ggd2l0aFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIHRoZSBmcmVlIGl0ZW1zIGluIGEsIHNvIHRoZSBleHRyYSBmcmVlIG5vZGVzXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gYXJlIGRlbGV0ZWQuXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaXRlbUluZGV4ID0gaSAtIGRlbGV0ZWRJdGVtcysrO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIG5ld0NoaWxkcmVuLnB1c2gobnVsbCk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICB2YXIgbGFzdEZyZWVJbmRleCA9IGZyZWVJbmRleCA+PSBiRnJlZS5sZW5ndGggPyBiQ2hpbGRyZW4ubGVuZ3RoIDogYkZyZWVbZnJlZUluZGV4XTtcblxuICAgICAgICAgICAgICAgIC8vIEl0ZXJhdGUgdGhyb3VnaCBiIGFuZCBhcHBlbmQgYW55IG5ldyBrZXlzXG4gICAgICAgICAgICAgICAgLy8gTyhNKSB0aW1lXG4gICAgICAgICAgICAgICAgZm9yICh2YXIgaiA9IDA7IGogPCBiQ2hpbGRyZW4ubGVuZ3RoOyBqKyspIHtcbiAgICAgICAgICAgICAgICAgICAgdmFyIG5ld0l0ZW0gPSBiQ2hpbGRyZW5bal07XG5cbiAgICAgICAgICAgICAgICAgICAgaWYgKG5ld0l0ZW0ua2V5KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoIWFLZXlzLmhhc093blByb3BlcnR5KG5ld0l0ZW0ua2V5KSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIEFkZCBhbnkgbmV3IGtleWVkIGl0ZW1zXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gV2UgYXJlIGFkZGluZyBuZXcgaXRlbXMgdG8gdGhlIGVuZCBhbmQgdGhlbiBzb3J0aW5nIHRoZW1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBpbiBwbGFjZS4gSW4gZnV0dXJlIHdlIHNob3VsZCBpbnNlcnQgbmV3IGl0ZW1zIGluIHBsYWNlLlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIG5ld0NoaWxkcmVuLnB1c2gobmV3SXRlbSk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoaiA+PSBsYXN0RnJlZUluZGV4KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAvLyBBZGQgYW55IGxlZnRvdmVyIG5vbi1rZXllZCBpdGVtc1xuICAgICAgICAgICAgICAgICAgICAgICAgbmV3Q2hpbGRyZW4ucHVzaChuZXdJdGVtKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHZhciBzaW11bGF0ZSA9IG5ld0NoaWxkcmVuLnNsaWNlKCk7XG4gICAgICAgICAgICAgICAgdmFyIHNpbXVsYXRlSW5kZXggPSAwO1xuICAgICAgICAgICAgICAgIHZhciByZW1vdmVzID0gW107XG4gICAgICAgICAgICAgICAgdmFyIGluc2VydHMgPSBbXTtcbiAgICAgICAgICAgICAgICB2YXIgc2ltdWxhdGVJdGVtO1xuXG4gICAgICAgICAgICAgICAgZm9yICh2YXIgayA9IDA7IGsgPCBiQ2hpbGRyZW4ubGVuZ3RoOykge1xuICAgICAgICAgICAgICAgICAgICB2YXIgd2FudGVkSXRlbSA9IGJDaGlsZHJlbltrXTtcbiAgICAgICAgICAgICAgICAgICAgc2ltdWxhdGVJdGVtID0gc2ltdWxhdGVbc2ltdWxhdGVJbmRleF07XG5cbiAgICAgICAgICAgICAgICAgICAgLy8gcmVtb3ZlIGl0ZW1zXG4gICAgICAgICAgICAgICAgICAgIHdoaWxlIChzaW11bGF0ZUl0ZW0gPT09IG51bGwgJiYgc2ltdWxhdGUubGVuZ3RoKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICByZW1vdmVzLnB1c2gocmVtb3ZlKHNpbXVsYXRlLCBzaW11bGF0ZUluZGV4LCBudWxsKSk7XG4gICAgICAgICAgICAgICAgICAgICAgICBzaW11bGF0ZUl0ZW0gPSBzaW11bGF0ZVtzaW11bGF0ZUluZGV4XTtcbiAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgIGlmICghc2ltdWxhdGVJdGVtIHx8IHNpbXVsYXRlSXRlbS5rZXkgIT09IHdhbnRlZEl0ZW0ua2V5KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAvLyBpZiB3ZSBuZWVkIGEga2V5IGluIHRoaXMgcG9zaXRpb24uLi5cbiAgICAgICAgICAgICAgICAgICAgICAgIGlmICh3YW50ZWRJdGVtLmtleSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChzaW11bGF0ZUl0ZW0gJiYgc2ltdWxhdGVJdGVtLmtleSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBpZiBhbiBpbnNlcnQgZG9lc24ndCBwdXQgdGhpcyBrZXkgaW4gcGxhY2UsIGl0IG5lZWRzIHRvIG1vdmVcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGJLZXlzW3NpbXVsYXRlSXRlbS5rZXldICE9PSBrICsgMSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmVtb3Zlcy5wdXNoKHJlbW92ZShzaW11bGF0ZSwgc2ltdWxhdGVJbmRleCwgc2ltdWxhdGVJdGVtLmtleSkpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc2ltdWxhdGVJdGVtID0gc2ltdWxhdGVbc2ltdWxhdGVJbmRleF07XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBpZiB0aGUgcmVtb3ZlIGRpZG4ndCBwdXQgdGhlIHdhbnRlZCBpdGVtIGluIHBsYWNlLCB3ZSBuZWVkIHRvIGluc2VydCBpdFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKCFzaW11bGF0ZUl0ZW0gfHwgc2ltdWxhdGVJdGVtLmtleSAhPT0gd2FudGVkSXRlbS5rZXkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpbnNlcnRzLnB1c2goeyBrZXk6IHdhbnRlZEl0ZW0ua2V5LCB0bzogayB9KTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIGl0ZW1zIGFyZSBtYXRjaGluZywgc28gc2tpcCBhaGVhZFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc2ltdWxhdGVJbmRleCsrO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaW5zZXJ0cy5wdXNoKHsga2V5OiB3YW50ZWRJdGVtLmtleSwgdG86IGsgfSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpbnNlcnRzLnB1c2goeyBrZXk6IHdhbnRlZEl0ZW0ua2V5LCB0bzogayB9KTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaysrO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgLy8gYSBrZXkgaW4gc2ltdWxhdGUgaGFzIG5vIG1hdGNoaW5nIHdhbnRlZCBrZXksIHJlbW92ZSBpdFxuICAgICAgICAgICAgICAgICAgICAgICAgZWxzZSBpZiAoc2ltdWxhdGVJdGVtICYmIHNpbXVsYXRlSXRlbS5rZXkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICByZW1vdmVzLnB1c2gocmVtb3ZlKHNpbXVsYXRlLCBzaW11bGF0ZUluZGV4LCBzaW11bGF0ZUl0ZW0ua2V5KSk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBzaW11bGF0ZUluZGV4Kys7XG4gICAgICAgICAgICAgICAgICAgICAgICBrKys7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAvLyByZW1vdmUgYWxsIHRoZSByZW1haW5pbmcgbm9kZXMgZnJvbSBzaW11bGF0ZVxuICAgICAgICAgICAgICAgIHdoaWxlIChzaW11bGF0ZUluZGV4IDwgc2ltdWxhdGUubGVuZ3RoKSB7XG4gICAgICAgICAgICAgICAgICAgIHNpbXVsYXRlSXRlbSA9IHNpbXVsYXRlW3NpbXVsYXRlSW5kZXhdO1xuICAgICAgICAgICAgICAgICAgICByZW1vdmVzLnB1c2gocmVtb3ZlKHNpbXVsYXRlLCBzaW11bGF0ZUluZGV4LCBzaW11bGF0ZUl0ZW0gJiYgc2ltdWxhdGVJdGVtLmtleSkpO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIC8vIElmIHRoZSBvbmx5IG1vdmVzIHdlIGhhdmUgYXJlIGRlbGV0ZXMgdGhlbiB3ZSBjYW4ganVzdFxuICAgICAgICAgICAgICAgIC8vIGxldCB0aGUgZGVsZXRlIHBhdGNoIHJlbW92ZSB0aGVzZSBpdGVtcy5cbiAgICAgICAgICAgICAgICBpZiAocmVtb3Zlcy5sZW5ndGggPT09IGRlbGV0ZWRJdGVtcyAmJiAhaW5zZXJ0cy5sZW5ndGgpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGNoaWxkcmVuOiBuZXdDaGlsZHJlbixcbiAgICAgICAgICAgICAgICAgICAgICAgIG1vdmVzOiBudWxsXG4gICAgICAgICAgICAgICAgICAgIH07XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgICAgICAgICAgY2hpbGRyZW46IG5ld0NoaWxkcmVuLFxuICAgICAgICAgICAgICAgICAgICBtb3Zlczoge1xuICAgICAgICAgICAgICAgICAgICAgICAgcmVtb3ZlczogcmVtb3ZlcyxcbiAgICAgICAgICAgICAgICAgICAgICAgIGluc2VydHM6IGluc2VydHNcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH07XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIHJlbW92ZShhcnIsIGluZGV4LCBrZXkpIHtcbiAgICAgICAgICAgICAgICBhcnIuc3BsaWNlKGluZGV4LCAxKTtcblxuICAgICAgICAgICAgICAgIHJldHVybiB7XG4gICAgICAgICAgICAgICAgICAgIGZyb206IGluZGV4LFxuICAgICAgICAgICAgICAgICAgICBrZXk6IGtleVxuICAgICAgICAgICAgICAgIH07XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIGtleUluZGV4KGNoaWxkcmVuKSB7XG4gICAgICAgICAgICAgICAgdmFyIGtleXMgPSB7fTtcbiAgICAgICAgICAgICAgICB2YXIgZnJlZSA9IFtdO1xuICAgICAgICAgICAgICAgIHZhciBsZW5ndGggPSBjaGlsZHJlbi5sZW5ndGg7XG5cbiAgICAgICAgICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IGxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciBjaGlsZCA9IGNoaWxkcmVuW2ldO1xuXG4gICAgICAgICAgICAgICAgICAgIGlmIChjaGlsZC5rZXkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGtleXNbY2hpbGQua2V5XSA9IGk7XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBmcmVlLnB1c2goaSk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgICAgICAgICBrZXlzOiBrZXlzLCAvLyBBIGhhc2ggb2Yga2V5IG5hbWUgdG8gaW5kZXhcbiAgICAgICAgICAgICAgICAgICAgZnJlZTogZnJlZSAvLyBBbiBhcnJheSBvZiB1bmtleWVkIGl0ZW0gaW5kaWNlc1xuICAgICAgICAgICAgICAgIH07XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIGFwcGVuZFBhdGNoKGFwcGx5LCBwYXRjaCkge1xuICAgICAgICAgICAgICAgIGlmIChhcHBseSkge1xuICAgICAgICAgICAgICAgICAgICBpZiAoaXNBcnJheShhcHBseSkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGFwcGx5LnB1c2gocGF0Y2gpO1xuICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgYXBwbHkgPSBbYXBwbHksIHBhdGNoXTtcbiAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBhcHBseTtcbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gcGF0Y2g7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9LCB7IFwiLi4vdm5vZGUvaGFuZGxlLXRodW5rXCI6IDI0LCBcIi4uL3Zub2RlL2lzLXRodW5rXCI6IDI1LCBcIi4uL3Zub2RlL2lzLXZub2RlXCI6IDI3LCBcIi4uL3Zub2RlL2lzLXZ0ZXh0XCI6IDI4LCBcIi4uL3Zub2RlL2lzLXdpZGdldFwiOiAyOSwgXCIuLi92bm9kZS92cGF0Y2hcIjogMzIsIFwiLi9kaWZmLXByb3BzXCI6IDM0LCBcIngtaXMtYXJyYXlcIjogMTIgfV0gfSwge30sIFs0XSkoNCk7XG59KTtcblxuLyogQGZsb3cgKi9cblxuY2xhc3MgTWFpbGJveCB7XG5cbiAgY29uc3RydWN0b3IoKSB7XG4gICAgdGhpcy5tZXNzYWdlcyA9IFtdO1xuICB9XG5cbiAgZGVsaXZlcihtZXNzYWdlKSB7XG4gICAgdGhpcy5tZXNzYWdlcy5wdXNoKG1lc3NhZ2UpO1xuICAgIHJldHVybiBtZXNzYWdlO1xuICB9XG5cbiAgZ2V0KCkge1xuICAgIHJldHVybiB0aGlzLm1lc3NhZ2VzO1xuICB9XG5cbiAgaXNFbXB0eSgpIHtcbiAgICByZXR1cm4gdGhpcy5tZXNzYWdlcy5sZW5ndGggPT09IDA7XG4gIH1cblxuICByZW1vdmVBdChpbmRleCkge1xuICAgIHRoaXMubWVzc2FnZXMuc3BsaWNlKGluZGV4LCAxKTtcbiAgfVxufVxuXG52YXIgU3RhdGVzID0ge1xuICBOT1JNQUw6IFN5bWJvbC5mb3IoXCJub3JtYWxcIiksXG4gIEtJTEw6IFN5bWJvbC5mb3IoXCJraWxsXCIpLFxuICBTVVNQRU5EOiBTeW1ib2wuZm9yKFwic3VzcGVuZFwiKSxcbiAgQ09OVElOVUU6IFN5bWJvbC5mb3IoXCJjb250aW51ZVwiKSxcbiAgUkVDRUlWRTogU3ltYm9sLmZvcihcInJlY2VpdmVcIiksXG4gIFNFTkQ6IFN5bWJvbC5mb3IoXCJzZW5kXCIpLFxuICBTTEVFUElORzogU3ltYm9sLmZvcihcInNsZWVwaW5nXCIpLFxuICBSVU5OSU5HOiBTeW1ib2wuZm9yKFwicnVubmluZ1wiKSxcbiAgU1VTUEVOREVEOiBTeW1ib2wuZm9yKFwic3VzcGVuZGVkXCIpLFxuICBTVE9QUEVEOiBTeW1ib2wuZm9yKFwic3RvcHBlZFwiKSxcbiAgU0xFRVA6IFN5bWJvbC5mb3IoXCJzbGVlcFwiKSxcbiAgRVhJVDogU3ltYm9sLmZvcihcImV4aXRcIiksXG4gIE5PTUFUQ0g6IFN5bWJvbC5mb3IoXCJub19tYXRjaFwiKVxufTtcblxuY2xhc3MgUHJvY2VzcyB7XG5cbiAgY29uc3RydWN0b3IocGlkLCBtYWlsYm94KSB7XG4gICAgdGhpcy5waWQgPSBwaWQ7XG4gICAgdGhpcy5tYWlsYm94ID0gbWFpbGJveDtcbiAgICB0aGlzLnN0YXR1cyA9IFN0YXRlcy5TVE9QUEVEO1xuICAgIHRoaXMuZGljdCA9IHt9O1xuICB9XG59XG5cbmNsYXNzIFR1cGxlIHtcblxuICBjb25zdHJ1Y3RvciguLi5hcmdzKSB7XG4gICAgdGhpcy52YWx1ZXMgPSBPYmplY3QuZnJlZXplKGFyZ3MpO1xuICAgIHRoaXMubGVuZ3RoID0gdGhpcy52YWx1ZXMubGVuZ3RoO1xuICB9XG5cbiAgZ2V0KGluZGV4KSB7XG4gICAgcmV0dXJuIHRoaXMudmFsdWVzW2luZGV4XTtcbiAgfVxuXG4gIGNvdW50KCkge1xuICAgIHJldHVybiB0aGlzLnZhbHVlcy5sZW5ndGg7XG4gIH1cblxuICBbU3ltYm9sLml0ZXJhdG9yXSgpIHtcbiAgICByZXR1cm4gdGhpcy52YWx1ZXNbU3ltYm9sLml0ZXJhdG9yXSgpO1xuICB9XG5cbiAgdG9TdHJpbmcoKSB7XG4gICAgdmFyIGksXG4gICAgICAgIHMgPSBcIlwiO1xuICAgIGZvciAoaSA9IDA7IGkgPCB0aGlzLnZhbHVlcy5sZW5ndGg7IGkrKykge1xuICAgICAgaWYgKHMgIT09IFwiXCIpIHtcbiAgICAgICAgcyArPSBcIiwgXCI7XG4gICAgICB9XG4gICAgICBzICs9IHRoaXMudmFsdWVzW2ldLnRvU3RyaW5nKCk7XG4gICAgfVxuXG4gICAgcmV0dXJuIFwie1wiICsgcyArIFwifVwiO1xuICB9XG5cbn1cblxubGV0IHByb2Nlc3NfY291bnRlciA9IC0xO1xuXG5jbGFzcyBQSUQge1xuICBjb25zdHJ1Y3RvcigpIHtcbiAgICBwcm9jZXNzX2NvdW50ZXIgPSBwcm9jZXNzX2NvdW50ZXIgKyAxO1xuICAgIHRoaXMuaWQgPSBwcm9jZXNzX2NvdW50ZXI7XG4gIH1cblxuICB0b1N0cmluZygpIHtcbiAgICByZXR1cm4gXCJQSUQjPDAuXCIgKyB0aGlzLmlkICsgXCIuMD5cIjtcbiAgfVxufVxuXG5jbGFzcyBJbnRlZ2VyIHt9XG5jbGFzcyBGbG9hdCB7fVxuXG5jbGFzcyBQcm9jZXNzU3lzdGVtIHtcblxuICBjb25zdHJ1Y3RvcigpIHtcbiAgICB0aGlzLnBpZHMgPSBuZXcgTWFwKCk7XG4gICAgdGhpcy5tYWlsYm94ZXMgPSBuZXcgTWFwKCk7XG4gICAgdGhpcy5uYW1lcyA9IG5ldyBNYXAoKTtcbiAgICB0aGlzLmxpbmtzID0gbmV3IE1hcCgpO1xuXG4gICAgdGhpcy5jdXJyZW50X3Byb2Nlc3MgPSBudWxsO1xuICAgIHRoaXMuc3VzcGVuZGVkID0gbmV3IE1hcCgpO1xuXG4gICAgdGhpcy5tYWluX3Byb2Nlc3NfcGlkID0gdGhpcy5zcGF3bigpO1xuICAgIHRoaXMuc2V0X2N1cnJlbnQodGhpcy5tYWluX3Byb2Nlc3NfcGlkKTtcbiAgfVxuXG4gIHNwYXduKCkge1xuICAgIHJldHVybiB0aGlzLmFkZF9wcm9jKGZhbHNlKS5waWQ7XG4gIH1cblxuICBzcGF3bl9saW5rKCkge1xuICAgIHJldHVybiB0aGlzLmFkZF9wcm9jKHRydWUpLnBpZDtcbiAgfVxuXG4gIGxpbmsocGlkKSB7XG4gICAgdGhpcy5saW5rcy5nZXQodGhpcy5waWQoKSkuYWRkKHBpZCk7XG4gICAgdGhpcy5saW5rcy5nZXQocGlkKS5hZGQodGhpcy5waWQoKSk7XG4gIH1cblxuICB1bmxpbmsocGlkKSB7XG4gICAgdGhpcy5saW5rcy5nZXQodGhpcy5waWQoKSkuZGVsZXRlKHBpZCk7XG4gICAgdGhpcy5saW5rcy5nZXQocGlkKS5kZWxldGUodGhpcy5waWQoKSk7XG4gIH1cblxuICBzZXRfY3VycmVudChpZCkge1xuICAgIGxldCBwaWQgPSB0aGlzLnBpZG9mKGlkKTtcbiAgICBpZiAocGlkICE9PSBudWxsKSB7XG4gICAgICB0aGlzLmN1cnJlbnRfcHJvY2VzcyA9IHRoaXMucGlkcy5nZXQocGlkKTtcbiAgICAgIHRoaXMuY3VycmVudF9wcm9jZXNzLnN0YXR1cyA9IFN0YXRlcy5SVU5OSU5HO1xuICAgIH1cbiAgfVxuXG4gIGFkZF9wcm9jKGxpbmtlZCkge1xuICAgIGxldCBuZXdwaWQgPSBuZXcgUElEKCk7XG4gICAgbGV0IG1haWxib3ggPSBuZXcgTWFpbGJveCgpO1xuICAgIGxldCBuZXdwcm9jID0gbmV3IFByb2Nlc3MobmV3cGlkLCBtYWlsYm94KTtcblxuICAgIHRoaXMucGlkcy5zZXQobmV3cGlkLCBuZXdwcm9jKTtcbiAgICB0aGlzLm1haWxib3hlcy5zZXQobmV3cGlkLCBtYWlsYm94KTtcbiAgICB0aGlzLmxpbmtzLnNldChuZXdwaWQsIG5ldyBTZXQoKSk7XG5cbiAgICBpZiAobGlua2VkKSB7XG4gICAgICB0aGlzLmxpbmsobmV3cGlkKTtcbiAgICB9XG5cbiAgICByZXR1cm4gbmV3cHJvYztcbiAgfVxuXG4gIHJlbW92ZV9wcm9jKHBpZCkge1xuICAgIHRoaXMucGlkcy5kZWxldGUocGlkKTtcbiAgICB0aGlzLnVucmVnaXN0ZXIocGlkKTtcblxuICAgIGlmICh0aGlzLmxpbmtzLmhhcyhwaWQpKSB7XG4gICAgICBmb3IgKGxldCBsaW5rcGlkIG9mIHRoaXMubGlua3MuZ2V0KHBpZCkpIHtcbiAgICAgICAgdGhpcy5saW5rcy5nZXQobGlua3BpZCkuZGVsZXRlKHBpZCk7XG4gICAgICB9XG5cbiAgICAgIHRoaXMubGlua3MuZGVsZXRlKHBpZCk7XG4gICAgfVxuICB9XG5cbiAgZXhpdChpZCkge1xuICAgIGxldCBwaWQgPSB0aGlzLnBpZG9mKGlkKTtcbiAgICB0aGlzLnJlbW92ZV9wcm9jKGlkKTtcbiAgfVxuXG4gIHJlZ2lzdGVyKG5hbWUsIHBpZCkge1xuICAgIGlmICghdGhpcy5uYW1lcy5oYXMobmFtZSkpIHtcbiAgICAgIHRoaXMubmFtZXMuc2V0KG5hbWUsIHBpZCk7XG4gICAgICByZXR1cm4gbmFtZTtcbiAgICB9IGVsc2Uge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKFwiTmFtZSBpcyBhbHJlYWR5IHJlZ2lzdGVyZWQgdG8gYW5vdGhlciBwcm9jZXNzXCIpO1xuICAgIH1cbiAgfVxuXG4gIHJlZ2lzdGVyZWQobmFtZSkge1xuICAgIHJldHVybiB0aGlzLm5hbWVzLmhhcyhuYW1lKSA/IHRoaXMubmFtZXMuZ2V0KG5hbWUpIDogbnVsbDtcbiAgfVxuXG4gIHVucmVnaXN0ZXIocGlkKSB7XG4gICAgZm9yIChsZXQgbmFtZSBvZiB0aGlzLm5hbWVzLmtleXMoKSkge1xuICAgICAgaWYgKHRoaXMubmFtZXMuaGFzKG5hbWUpICYmIHRoaXMubmFtZXMuZ2V0KG5hbWUpID09PSBwaWQpIHtcbiAgICAgICAgdGhpcy5uYW1lcy5kZWxldGUobmFtZSk7XG4gICAgICB9XG4gICAgfVxuICB9XG5cbiAgcGlkKCkge1xuICAgIHJldHVybiB0aGlzLmN1cnJlbnRfcHJvY2Vzcy5waWQ7XG4gIH1cblxuICBwaWRvZihpZCkge1xuICAgIGlmIChpZCBpbnN0YW5jZW9mIFBJRCkge1xuICAgICAgcmV0dXJuIHRoaXMucGlkcy5oYXMoaWQpID8gaWQgOiBudWxsO1xuICAgIH0gZWxzZSBpZiAoaWQgaW5zdGFuY2VvZiBQcm9jZXNzKSB7XG4gICAgICByZXR1cm4gaWQucGlkO1xuICAgIH0gZWxzZSB7XG4gICAgICBsZXQgcGlkID0gdGhpcy5yZWdpc3RlcmVkKGlkKTtcbiAgICAgIGlmIChwaWQgPT09IG51bGwpIHRocm93IFwiUHJvY2VzcyBuYW1lIG5vdCByZWdpc3RlcmVkOiBcIiArIGlkICsgXCIgKFwiICsgdHlwZW9mIGlkICsgXCIpXCI7XG4gICAgICByZXR1cm4gcGlkO1xuICAgIH1cbiAgfVxuXG4gIHB1dChpZCwga2V5LCB2YWx1ZSkge1xuICAgIGxldCBwaWQgPSB0aGlzLnBpZG9mKGlkKTtcbiAgICBsZXQgcHJvY2VzcyA9IHRoaXMucGlkcy5nZXQocGlkKTtcbiAgICBwcm9jZXNzLmRpY3Rba2V5XSA9IHZhbHVlO1xuICB9XG5cbiAgZ2V0KGlkLCBrZXkpIHtcbiAgICBsZXQgcGlkID0gdGhpcy5waWRvZihpZCk7XG4gICAgbGV0IHByb2Nlc3MgPSB0aGlzLnBpZHMuZ2V0KHBpZCk7XG5cbiAgICBpZiAoa2V5ICE9IG51bGwpIHtcbiAgICAgIHJldHVybiBwcm9jZXNzLmRpY3Rba2V5XTtcbiAgICB9IGVsc2Uge1xuICAgICAgcmV0dXJuIHByb2Nlc3MuZGljdDtcbiAgICB9XG4gIH1cblxuICBnZXRfa2V5cyhpZCkge1xuICAgIGxldCBwaWQgPSB0aGlzLnBpZG9mKGlkKTtcbiAgICBsZXQgcHJvY2VzcyA9IHRoaXMucGlkcy5nZXQocGlkKTtcblxuICAgIHJldHVybiBPYmplY3Qua2V5cyhwcm9jZXNzLmRpY3QpO1xuICB9XG5cbiAgZXJhc2UoaWQsIGtleSkge1xuICAgIGxldCBwaWQgPSB0aGlzLnBpZG9mKGlkKTtcbiAgICBsZXQgcHJvY2VzcyA9IHRoaXMucGlkcy5nZXQocGlkKTtcblxuICAgIGlmIChrZXkgIT0gbnVsbCkge1xuICAgICAgZGVsZXRlIHByb2Nlc3MuZGljdFtrZXldO1xuICAgIH0gZWxzZSB7XG4gICAgICBwcm9jZXNzLmRpY3QgPSB7fTtcbiAgICB9XG4gIH1cbn1cblxuY2xhc3MgQml0U3RyaW5nIHtcbiAgY29uc3RydWN0b3IoLi4uYXJncykge1xuICAgIHRoaXMucmF3X3ZhbHVlID0gZnVuY3Rpb24gKCkge1xuICAgICAgcmV0dXJuIE9iamVjdC5mcmVlemUoYXJncyk7XG4gICAgfTtcblxuICAgIHRoaXMudmFsdWUgPSBPYmplY3QuZnJlZXplKHRoaXMucHJvY2VzcyhhcmdzKSk7XG4gIH1cblxuICBnZXQoaW5kZXgpIHtcbiAgICByZXR1cm4gdGhpcy52YWx1ZVtpbmRleF07XG4gIH1cblxuICBjb3VudCgpIHtcbiAgICByZXR1cm4gdGhpcy52YWx1ZS5sZW5ndGg7XG4gIH1cblxuICBbU3ltYm9sLml0ZXJhdG9yXSgpIHtcbiAgICByZXR1cm4gdGhpcy52YWx1ZVtTeW1ib2wuaXRlcmF0b3JdKCk7XG4gIH1cblxuICB0b1N0cmluZygpIHtcbiAgICB2YXIgaSxcbiAgICAgICAgcyA9IFwiXCI7XG4gICAgZm9yIChpID0gMDsgaSA8IHRoaXMuY291bnQoKTsgaSsrKSB7XG4gICAgICBpZiAocyAhPT0gXCJcIikge1xuICAgICAgICBzICs9IFwiLCBcIjtcbiAgICAgIH1cbiAgICAgIHMgKz0gdGhpc1tpXS50b1N0cmluZygpO1xuICAgIH1cblxuICAgIHJldHVybiBcIjw8XCIgKyBzICsgXCI+PlwiO1xuICB9XG5cbiAgcHJvY2VzcygpIHtcbiAgICBsZXQgcHJvY2Vzc2VkX3ZhbHVlcyA9IFtdO1xuXG4gICAgdmFyIGk7XG4gICAgZm9yIChpID0gMDsgaSA8IHRoaXMucmF3X3ZhbHVlKCkubGVuZ3RoOyBpKyspIHtcbiAgICAgIGxldCBwcm9jZXNzZWRfdmFsdWUgPSB0aGlzW1wicHJvY2Vzc19cIiArIHRoaXMucmF3X3ZhbHVlKClbaV0udHlwZV0odGhpcy5yYXdfdmFsdWUoKVtpXSk7XG5cbiAgICAgIGZvciAobGV0IGF0dHIgb2YgdGhpcy5yYXdfdmFsdWUoKVtpXS5hdHRyaWJ1dGVzKSB7XG4gICAgICAgIHByb2Nlc3NlZF92YWx1ZSA9IHRoaXNbXCJwcm9jZXNzX1wiICsgYXR0cl0ocHJvY2Vzc2VkX3ZhbHVlKTtcbiAgICAgIH1cblxuICAgICAgcHJvY2Vzc2VkX3ZhbHVlcyA9IHByb2Nlc3NlZF92YWx1ZXMuY29uY2F0KHByb2Nlc3NlZF92YWx1ZSk7XG4gICAgfVxuXG4gICAgcmV0dXJuIHByb2Nlc3NlZF92YWx1ZXM7XG4gIH1cblxuICBwcm9jZXNzX2ludGVnZXIodmFsdWUpIHtcbiAgICByZXR1cm4gdmFsdWUudmFsdWU7XG4gIH1cblxuICBwcm9jZXNzX2Zsb2F0KHZhbHVlKSB7XG4gICAgaWYgKHZhbHVlLnNpemUgPT09IDY0KSB7XG4gICAgICByZXR1cm4gQml0U3RyaW5nLmZsb2F0NjRUb0J5dGVzKHZhbHVlLnZhbHVlKTtcbiAgICB9IGVsc2UgaWYgKHZhbHVlLnNpemUgPT09IDMyKSB7XG4gICAgICByZXR1cm4gQml0U3RyaW5nLmZsb2F0MzJUb0J5dGVzKHZhbHVlLnZhbHVlKTtcbiAgICB9XG5cbiAgICB0aHJvdyBuZXcgRXJyb3IoXCJJbnZhbGlkIHNpemUgZm9yIGZsb2F0XCIpO1xuICB9XG5cbiAgcHJvY2Vzc19iaXRzdHJpbmcodmFsdWUpIHtcbiAgICByZXR1cm4gdmFsdWUudmFsdWUudmFsdWU7XG4gIH1cblxuICBwcm9jZXNzX2JpbmFyeSh2YWx1ZSkge1xuICAgIHJldHVybiBCaXRTdHJpbmcudG9VVEY4QXJyYXkodmFsdWUudmFsdWUpO1xuICB9XG5cbiAgcHJvY2Vzc191dGY4KHZhbHVlKSB7XG4gICAgcmV0dXJuIEJpdFN0cmluZy50b1VURjhBcnJheSh2YWx1ZS52YWx1ZSk7XG4gIH1cblxuICBwcm9jZXNzX3V0ZjE2KHZhbHVlKSB7XG4gICAgcmV0dXJuIEJpdFN0cmluZy50b1VURjE2QXJyYXkodmFsdWUudmFsdWUpO1xuICB9XG5cbiAgcHJvY2Vzc191dGYzMih2YWx1ZSkge1xuICAgIHJldHVybiBCaXRTdHJpbmcudG9VVEYzMkFycmF5KHZhbHVlLnZhbHVlKTtcbiAgfVxuXG4gIHByb2Nlc3Nfc2lnbmVkKHZhbHVlKSB7XG4gICAgcmV0dXJuIG5ldyBVaW50OEFycmF5KFt2YWx1ZV0pWzBdO1xuICB9XG5cbiAgcHJvY2Vzc191bnNpZ25lZCh2YWx1ZSkge1xuICAgIHJldHVybiB2YWx1ZTtcbiAgfVxuXG4gIHByb2Nlc3NfbmF0aXZlKHZhbHVlKSB7XG4gICAgcmV0dXJuIHZhbHVlO1xuICB9XG5cbiAgcHJvY2Vzc19iaWcodmFsdWUpIHtcbiAgICByZXR1cm4gdmFsdWU7XG4gIH1cblxuICBwcm9jZXNzX2xpdHRsZSh2YWx1ZSkge1xuICAgIHJldHVybiB2YWx1ZS5yZXZlcnNlKCk7XG4gIH1cblxuICBwcm9jZXNzX3NpemUodmFsdWUpIHtcbiAgICByZXR1cm4gdmFsdWU7XG4gIH1cblxuICBwcm9jZXNzX3VuaXQodmFsdWUpIHtcbiAgICByZXR1cm4gdmFsdWU7XG4gIH1cblxuICBzdGF0aWMgaW50ZWdlcih2YWx1ZSkge1xuICAgIHJldHVybiBCaXRTdHJpbmcud3JhcCh2YWx1ZSwgeyBcInR5cGVcIjogXCJpbnRlZ2VyXCIsIFwidW5pdFwiOiAxLCBcInNpemVcIjogOCB9KTtcbiAgfVxuXG4gIHN0YXRpYyBmbG9hdCh2YWx1ZSkge1xuICAgIHJldHVybiBCaXRTdHJpbmcud3JhcCh2YWx1ZSwgeyBcInR5cGVcIjogXCJmbG9hdFwiLCBcInVuaXRcIjogMSwgXCJzaXplXCI6IDY0IH0pO1xuICB9XG5cbiAgc3RhdGljIGJpdHN0cmluZyh2YWx1ZSkge1xuICAgIHJldHVybiBCaXRTdHJpbmcud3JhcCh2YWx1ZSwgeyBcInR5cGVcIjogXCJiaXRzdHJpbmdcIiwgXCJ1bml0XCI6IDEsIFwic2l6ZVwiOiB2YWx1ZS5sZW5ndGggfSk7XG4gIH1cblxuICBzdGF0aWMgYml0cyh2YWx1ZSkge1xuICAgIHJldHVybiBCaXRTdHJpbmcuYml0c3RyaW5nKHZhbHVlKTtcbiAgfVxuXG4gIHN0YXRpYyBiaW5hcnkodmFsdWUpIHtcbiAgICByZXR1cm4gQml0U3RyaW5nLndyYXAodmFsdWUsIHsgXCJ0eXBlXCI6IFwiYmluYXJ5XCIsIFwidW5pdFwiOiA4LCBcInNpemVcIjogdmFsdWUubGVuZ3RoIH0pO1xuICB9XG5cbiAgc3RhdGljIGJ5dGVzKHZhbHVlKSB7XG4gICAgcmV0dXJuIEJpdFN0cmluZy5iaW5hcnkodmFsdWUpO1xuICB9XG5cbiAgc3RhdGljIHV0ZjgodmFsdWUpIHtcbiAgICByZXR1cm4gQml0U3RyaW5nLndyYXAodmFsdWUsIHsgXCJ0eXBlXCI6IFwidXRmOFwiIH0pO1xuICB9XG5cbiAgc3RhdGljIHV0ZjE2KHZhbHVlKSB7XG4gICAgcmV0dXJuIEJpdFN0cmluZy53cmFwKHZhbHVlLCB7IFwidHlwZVwiOiBcInV0ZjE2XCIgfSk7XG4gIH1cblxuICBzdGF0aWMgdXRmMzIodmFsdWUpIHtcbiAgICByZXR1cm4gQml0U3RyaW5nLndyYXAodmFsdWUsIHsgXCJ0eXBlXCI6IFwidXRmMzJcIiB9KTtcbiAgfVxuXG4gIHN0YXRpYyBzaWduZWQodmFsdWUpIHtcbiAgICByZXR1cm4gQml0U3RyaW5nLndyYXAodmFsdWUsIHt9LCBcInNpZ25lZFwiKTtcbiAgfVxuXG4gIHN0YXRpYyB1bnNpZ25lZCh2YWx1ZSkge1xuICAgIHJldHVybiBCaXRTdHJpbmcud3JhcCh2YWx1ZSwge30sIFwidW5zaWduZWRcIik7XG4gIH1cblxuICBzdGF0aWMgbmF0aXZlKHZhbHVlKSB7XG4gICAgcmV0dXJuIEJpdFN0cmluZy53cmFwKHZhbHVlLCB7fSwgXCJuYXRpdmVcIik7XG4gIH1cblxuICBzdGF0aWMgYmlnKHZhbHVlKSB7XG4gICAgcmV0dXJuIEJpdFN0cmluZy53cmFwKHZhbHVlLCB7fSwgXCJiaWdcIik7XG4gIH1cblxuICBzdGF0aWMgbGl0dGxlKHZhbHVlKSB7XG4gICAgcmV0dXJuIEJpdFN0cmluZy53cmFwKHZhbHVlLCB7fSwgXCJsaXR0bGVcIik7XG4gIH1cblxuICBzdGF0aWMgc2l6ZSh2YWx1ZSwgY291bnQpIHtcbiAgICByZXR1cm4gQml0U3RyaW5nLndyYXAodmFsdWUsIHsgXCJzaXplXCI6IGNvdW50IH0pO1xuICB9XG5cbiAgc3RhdGljIHVuaXQodmFsdWUsIGNvdW50KSB7XG4gICAgcmV0dXJuIEJpdFN0cmluZy53cmFwKHZhbHVlLCB7IFwidW5pdFwiOiBjb3VudCB9KTtcbiAgfVxuXG4gIHN0YXRpYyB3cmFwKHZhbHVlLCBvcHQsIG5ld19hdHRyaWJ1dGUgPSBudWxsKSB7XG4gICAgbGV0IHRoZV92YWx1ZSA9IHZhbHVlO1xuXG4gICAgaWYgKCEodmFsdWUgaW5zdGFuY2VvZiBPYmplY3QpKSB7XG4gICAgICB0aGVfdmFsdWUgPSB7IFwidmFsdWVcIjogdmFsdWUsIFwiYXR0cmlidXRlc1wiOiBbXSB9O1xuICAgIH1cblxuICAgIHRoZV92YWx1ZSA9IE9iamVjdC5hc3NpZ24odGhlX3ZhbHVlLCBvcHQpO1xuXG4gICAgaWYgKG5ld19hdHRyaWJ1dGUpIHtcbiAgICAgIHRoZV92YWx1ZS5hdHRyaWJ1dGVzLnB1c2gobmV3X2F0dHJpYnV0ZSk7XG4gICAgfVxuXG4gICAgcmV0dXJuIHRoZV92YWx1ZTtcbiAgfVxuXG4gIHN0YXRpYyB0b1VURjhBcnJheShzdHIpIHtcbiAgICB2YXIgdXRmOCA9IFtdO1xuICAgIGZvciAodmFyIGkgPSAwOyBpIDwgc3RyLmxlbmd0aDsgaSsrKSB7XG4gICAgICB2YXIgY2hhcmNvZGUgPSBzdHIuY2hhckNvZGVBdChpKTtcbiAgICAgIGlmIChjaGFyY29kZSA8IDEyOCkge1xuICAgICAgICB1dGY4LnB1c2goY2hhcmNvZGUpO1xuICAgICAgfSBlbHNlIGlmIChjaGFyY29kZSA8IDIwNDgpIHtcbiAgICAgICAgdXRmOC5wdXNoKDE5MiB8IGNoYXJjb2RlID4+IDYsIDEyOCB8IGNoYXJjb2RlICYgNjMpO1xuICAgICAgfSBlbHNlIGlmIChjaGFyY29kZSA8IDU1Mjk2IHx8IGNoYXJjb2RlID49IDU3MzQ0KSB7XG4gICAgICAgIHV0ZjgucHVzaCgyMjQgfCBjaGFyY29kZSA+PiAxMiwgMTI4IHwgY2hhcmNvZGUgPj4gNiAmIDYzLCAxMjggfCBjaGFyY29kZSAmIDYzKTtcbiAgICAgIH1cbiAgICAgIC8vIHN1cnJvZ2F0ZSBwYWlyXG4gICAgICBlbHNlIHtcbiAgICAgICAgaSsrO1xuICAgICAgICAvLyBVVEYtMTYgZW5jb2RlcyAweDEwMDAwLTB4MTBGRkZGIGJ5XG4gICAgICAgIC8vIHN1YnRyYWN0aW5nIDB4MTAwMDAgYW5kIHNwbGl0dGluZyB0aGVcbiAgICAgICAgLy8gMjAgYml0cyBvZiAweDAtMHhGRkZGRiBpbnRvIHR3byBoYWx2ZXNcbiAgICAgICAgY2hhcmNvZGUgPSA2NTUzNiArICgoY2hhcmNvZGUgJiAxMDIzKSA8PCAxMCB8IHN0ci5jaGFyQ29kZUF0KGkpICYgMTAyMyk7XG4gICAgICAgIHV0ZjgucHVzaCgyNDAgfCBjaGFyY29kZSA+PiAxOCwgMTI4IHwgY2hhcmNvZGUgPj4gMTIgJiA2MywgMTI4IHwgY2hhcmNvZGUgPj4gNiAmIDYzLCAxMjggfCBjaGFyY29kZSAmIDYzKTtcbiAgICAgIH1cbiAgICB9XG4gICAgcmV0dXJuIHV0Zjg7XG4gIH1cblxuICBzdGF0aWMgdG9VVEYxNkFycmF5KHN0cikge1xuICAgIHZhciB1dGYxNiA9IFtdO1xuICAgIGZvciAodmFyIGkgPSAwOyBpIDwgc3RyLmxlbmd0aDsgaSsrKSB7XG4gICAgICB2YXIgY29kZVBvaW50ID0gc3RyLmNvZGVQb2ludEF0KGkpO1xuXG4gICAgICBpZiAoY29kZVBvaW50IDw9IDI1NSkge1xuICAgICAgICB1dGYxNi5wdXNoKDApO1xuICAgICAgICB1dGYxNi5wdXNoKGNvZGVQb2ludCk7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICB1dGYxNi5wdXNoKGNvZGVQb2ludCA+PiA4ICYgMjU1KTtcbiAgICAgICAgdXRmMTYucHVzaChjb2RlUG9pbnQgJiAyNTUpO1xuICAgICAgfVxuICAgIH1cbiAgICByZXR1cm4gdXRmMTY7XG4gIH1cblxuICBzdGF0aWMgdG9VVEYzMkFycmF5KHN0cikge1xuICAgIHZhciB1dGYzMiA9IFtdO1xuICAgIGZvciAodmFyIGkgPSAwOyBpIDwgc3RyLmxlbmd0aDsgaSsrKSB7XG4gICAgICB2YXIgY29kZVBvaW50ID0gc3RyLmNvZGVQb2ludEF0KGkpO1xuXG4gICAgICBpZiAoY29kZVBvaW50IDw9IDI1NSkge1xuICAgICAgICB1dGYzMi5wdXNoKDApO1xuICAgICAgICB1dGYzMi5wdXNoKDApO1xuICAgICAgICB1dGYzMi5wdXNoKDApO1xuICAgICAgICB1dGYzMi5wdXNoKGNvZGVQb2ludCk7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICB1dGYzMi5wdXNoKDApO1xuICAgICAgICB1dGYzMi5wdXNoKDApO1xuICAgICAgICB1dGYzMi5wdXNoKGNvZGVQb2ludCA+PiA4ICYgMjU1KTtcbiAgICAgICAgdXRmMzIucHVzaChjb2RlUG9pbnQgJiAyNTUpO1xuICAgICAgfVxuICAgIH1cbiAgICByZXR1cm4gdXRmMzI7XG4gIH1cblxuICAvL2h0dHA6Ly9zdGFja292ZXJmbG93LmNvbS9xdWVzdGlvbnMvMjAwMzQ5My9qYXZhc2NyaXB0LWZsb2F0LWZyb20tdG8tYml0c1xuICBzdGF0aWMgZmxvYXQzMlRvQnl0ZXMoZikge1xuICAgIHZhciBieXRlcyA9IFtdO1xuXG4gICAgdmFyIGJ1ZiA9IG5ldyBBcnJheUJ1ZmZlcig0KTtcbiAgICBuZXcgRmxvYXQzMkFycmF5KGJ1ZilbMF0gPSBmO1xuXG4gICAgbGV0IGludFZlcnNpb24gPSBuZXcgVWludDMyQXJyYXkoYnVmKVswXTtcblxuICAgIGJ5dGVzLnB1c2goaW50VmVyc2lvbiA+PiAyNCAmIDI1NSk7XG4gICAgYnl0ZXMucHVzaChpbnRWZXJzaW9uID4+IDE2ICYgMjU1KTtcbiAgICBieXRlcy5wdXNoKGludFZlcnNpb24gPj4gOCAmIDI1NSk7XG4gICAgYnl0ZXMucHVzaChpbnRWZXJzaW9uICYgMjU1KTtcblxuICAgIHJldHVybiBieXRlcztcbiAgfVxuXG4gIHN0YXRpYyBmbG9hdDY0VG9CeXRlcyhmKSB7XG4gICAgdmFyIGJ5dGVzID0gW107XG5cbiAgICB2YXIgYnVmID0gbmV3IEFycmF5QnVmZmVyKDgpO1xuICAgIG5ldyBGbG9hdDY0QXJyYXkoYnVmKVswXSA9IGY7XG5cbiAgICB2YXIgaW50VmVyc2lvbjEgPSBuZXcgVWludDMyQXJyYXkoYnVmKVswXTtcbiAgICB2YXIgaW50VmVyc2lvbjIgPSBuZXcgVWludDMyQXJyYXkoYnVmKVsxXTtcblxuICAgIGJ5dGVzLnB1c2goaW50VmVyc2lvbjIgPj4gMjQgJiAyNTUpO1xuICAgIGJ5dGVzLnB1c2goaW50VmVyc2lvbjIgPj4gMTYgJiAyNTUpO1xuICAgIGJ5dGVzLnB1c2goaW50VmVyc2lvbjIgPj4gOCAmIDI1NSk7XG4gICAgYnl0ZXMucHVzaChpbnRWZXJzaW9uMiAmIDI1NSk7XG5cbiAgICBieXRlcy5wdXNoKGludFZlcnNpb24xID4+IDI0ICYgMjU1KTtcbiAgICBieXRlcy5wdXNoKGludFZlcnNpb24xID4+IDE2ICYgMjU1KTtcbiAgICBieXRlcy5wdXNoKGludFZlcnNpb24xID4+IDggJiAyNTUpO1xuICAgIGJ5dGVzLnB1c2goaW50VmVyc2lvbjEgJiAyNTUpO1xuXG4gICAgcmV0dXJuIGJ5dGVzO1xuICB9XG59XG5cbi8qIEBmbG93ICovXG5cbmNsYXNzIFZhcmlhYmxlIHtcblxuICBjb25zdHJ1Y3RvcihuYW1lID0gbnVsbCkge1xuICAgIHRoaXMubmFtZSA9IG5hbWU7XG4gIH1cbn1cblxuY2xhc3MgV2lsZGNhcmQge1xuICBjb25zdHJ1Y3RvcigpIHt9XG59XG5cbmNsYXNzIFN0YXJ0c1dpdGgge1xuXG4gIGNvbnN0cnVjdG9yKHByZWZpeCkge1xuICAgIHRoaXMucHJlZml4ID0gcHJlZml4O1xuICB9XG59XG5cbmNsYXNzIENhcHR1cmUge1xuXG4gIGNvbnN0cnVjdG9yKHZhbHVlKSB7XG4gICAgdGhpcy52YWx1ZSA9IHZhbHVlO1xuICB9XG59XG5cbmNsYXNzIEhlYWRUYWlsIHtcbiAgY29uc3RydWN0b3IoKSB7fVxufVxuXG5jbGFzcyBUeXBlIHtcblxuICBjb25zdHJ1Y3Rvcih0eXBlLCBvYmpQYXR0ZXJuID0ge30pIHtcbiAgICB0aGlzLnR5cGUgPSB0eXBlO1xuICAgIHRoaXMub2JqUGF0dGVybiA9IG9ialBhdHRlcm47XG4gIH1cbn1cblxuY2xhc3MgQm91bmQge1xuXG4gIGNvbnN0cnVjdG9yKHZhbHVlKSB7XG4gICAgdGhpcy52YWx1ZSA9IHZhbHVlO1xuICB9XG59XG5cbmZ1bmN0aW9uIHZhcmlhYmxlKG5hbWUgPSBudWxsKSB7XG4gIHJldHVybiBuZXcgVmFyaWFibGUobmFtZSk7XG59XG5cbmZ1bmN0aW9uIHdpbGRjYXJkKCkge1xuICByZXR1cm4gbmV3IFdpbGRjYXJkKCk7XG59XG5cbmZ1bmN0aW9uIHN0YXJ0c1dpdGgocHJlZml4KSB7XG4gIHJldHVybiBuZXcgU3RhcnRzV2l0aChwcmVmaXgpO1xufVxuXG5mdW5jdGlvbiBjYXB0dXJlKHZhbHVlKSB7XG4gIHJldHVybiBuZXcgQ2FwdHVyZSh2YWx1ZSk7XG59XG5cbmZ1bmN0aW9uIGhlYWRUYWlsKCkge1xuICByZXR1cm4gbmV3IEhlYWRUYWlsKCk7XG59XG5cbmZ1bmN0aW9uIHR5cGUodHlwZSwgb2JqUGF0dGVybiA9IHt9KSB7XG4gIHJldHVybiBuZXcgVHlwZSh0eXBlLCBvYmpQYXR0ZXJuKTtcbn1cblxuZnVuY3Rpb24gYm91bmQodmFsdWUpIHtcbiAgcmV0dXJuIG5ldyBCb3VuZCh2YWx1ZSk7XG59XG5cbmZ1bmN0aW9uIGlzX251bWJlcih2YWx1ZSkge1xuICByZXR1cm4gdHlwZW9mIHZhbHVlID09PSAnbnVtYmVyJztcbn1cblxuZnVuY3Rpb24gaXNfc3RyaW5nKHZhbHVlKSB7XG4gIHJldHVybiB0eXBlb2YgdmFsdWUgPT09ICdzdHJpbmcnO1xufVxuXG5mdW5jdGlvbiBpc19ib29sZWFuKHZhbHVlKSB7XG4gIHJldHVybiB0eXBlb2YgdmFsdWUgPT09ICdib29sZWFuJztcbn1cblxuZnVuY3Rpb24gaXNfc3ltYm9sKHZhbHVlKSB7XG4gIHJldHVybiB0eXBlb2YgdmFsdWUgPT09ICdzeW1ib2wnO1xufVxuXG5mdW5jdGlvbiBpc19udWxsKHZhbHVlKSB7XG4gIHJldHVybiB2YWx1ZSA9PT0gbnVsbDtcbn1cblxuZnVuY3Rpb24gaXNfdW5kZWZpbmVkKHZhbHVlKSB7XG4gIHJldHVybiB0eXBlb2YgdmFsdWUgPT09ICd1bmRlZmluZWQnO1xufVxuXG5mdW5jdGlvbiBpc19mdW5jdGlvbih2YWx1ZSkge1xuICByZXR1cm4gT2JqZWN0LnByb3RvdHlwZS50b1N0cmluZy5jYWxsKHZhbHVlKSA9PSAnW29iamVjdCBGdW5jdGlvbl0nO1xufVxuXG5mdW5jdGlvbiBpc192YXJpYWJsZSh2YWx1ZSkge1xuICByZXR1cm4gdmFsdWUgaW5zdGFuY2VvZiBWYXJpYWJsZTtcbn1cblxuZnVuY3Rpb24gaXNfd2lsZGNhcmQodmFsdWUpIHtcbiAgcmV0dXJuIHZhbHVlIGluc3RhbmNlb2YgV2lsZGNhcmQ7XG59XG5cbmZ1bmN0aW9uIGlzX2hlYWRUYWlsKHZhbHVlKSB7XG4gIHJldHVybiB2YWx1ZSBpbnN0YW5jZW9mIEhlYWRUYWlsO1xufVxuXG5mdW5jdGlvbiBpc19jYXB0dXJlKHZhbHVlKSB7XG4gIHJldHVybiB2YWx1ZSBpbnN0YW5jZW9mIENhcHR1cmU7XG59XG5cbmZ1bmN0aW9uIGlzX3R5cGUodmFsdWUpIHtcbiAgcmV0dXJuIHZhbHVlIGluc3RhbmNlb2YgVHlwZTtcbn1cblxuZnVuY3Rpb24gaXNfc3RhcnRzV2l0aCh2YWx1ZSkge1xuICByZXR1cm4gdmFsdWUgaW5zdGFuY2VvZiBTdGFydHNXaXRoO1xufVxuXG5mdW5jdGlvbiBpc19ib3VuZCh2YWx1ZSkge1xuICByZXR1cm4gdmFsdWUgaW5zdGFuY2VvZiBCb3VuZDtcbn1cblxuZnVuY3Rpb24gaXNfb2JqZWN0KHZhbHVlKSB7XG4gIHJldHVybiB0eXBlb2YgdmFsdWUgPT09ICdvYmplY3QnO1xufVxuXG5mdW5jdGlvbiBpc19hcnJheSh2YWx1ZSkge1xuICByZXR1cm4gQXJyYXkuaXNBcnJheSh2YWx1ZSk7XG59XG5cbnZhciBDaGVja3MgPSB7XG4gIGlzX251bWJlcixcbiAgaXNfc3RyaW5nLFxuICBpc19ib29sZWFuLFxuICBpc19zeW1ib2wsXG4gIGlzX251bGwsXG4gIGlzX3VuZGVmaW5lZCxcbiAgaXNfZnVuY3Rpb24sXG4gIGlzX3ZhcmlhYmxlLFxuICBpc193aWxkY2FyZCxcbiAgaXNfaGVhZFRhaWwsXG4gIGlzX2NhcHR1cmUsXG4gIGlzX3R5cGUsXG4gIGlzX3N0YXJ0c1dpdGgsXG4gIGlzX2JvdW5kLFxuICBpc19vYmplY3QsXG4gIGlzX2FycmF5XG59O1xuXG5mdW5jdGlvbiByZXNvbHZlU3ltYm9sKHBhdHRlcm4pIHtcbiAgcmV0dXJuIGZ1bmN0aW9uICh2YWx1ZSkge1xuICAgIHJldHVybiBDaGVja3MuaXNfc3ltYm9sKHZhbHVlKSAmJiB2YWx1ZSA9PT0gcGF0dGVybjtcbiAgfTtcbn1cblxuZnVuY3Rpb24gcmVzb2x2ZVN0cmluZyhwYXR0ZXJuKSB7XG4gIHJldHVybiBmdW5jdGlvbiAodmFsdWUpIHtcbiAgICByZXR1cm4gQ2hlY2tzLmlzX3N0cmluZyh2YWx1ZSkgJiYgdmFsdWUgPT09IHBhdHRlcm47XG4gIH07XG59XG5cbmZ1bmN0aW9uIHJlc29sdmVOdW1iZXIocGF0dGVybikge1xuICByZXR1cm4gZnVuY3Rpb24gKHZhbHVlKSB7XG4gICAgcmV0dXJuIENoZWNrcy5pc19udW1iZXIodmFsdWUpICYmIHZhbHVlID09PSBwYXR0ZXJuO1xuICB9O1xufVxuXG5mdW5jdGlvbiByZXNvbHZlQm9vbGVhbihwYXR0ZXJuKSB7XG4gIHJldHVybiBmdW5jdGlvbiAodmFsdWUpIHtcbiAgICByZXR1cm4gQ2hlY2tzLmlzX2Jvb2xlYW4odmFsdWUpICYmIHZhbHVlID09PSBwYXR0ZXJuO1xuICB9O1xufVxuXG5mdW5jdGlvbiByZXNvbHZlRnVuY3Rpb24ocGF0dGVybikge1xuICByZXR1cm4gZnVuY3Rpb24gKHZhbHVlKSB7XG4gICAgcmV0dXJuIENoZWNrcy5pc19mdW5jdGlvbih2YWx1ZSkgJiYgdmFsdWUgPT09IHBhdHRlcm47XG4gIH07XG59XG5cbmZ1bmN0aW9uIHJlc29sdmVOdWxsKHBhdHRlcm4pIHtcbiAgcmV0dXJuIGZ1bmN0aW9uICh2YWx1ZSkge1xuICAgIHJldHVybiBDaGVja3MuaXNfbnVsbCh2YWx1ZSk7XG4gIH07XG59XG5cbmZ1bmN0aW9uIHJlc29sdmVCb3VuZChwYXR0ZXJuKSB7XG4gIHJldHVybiBmdW5jdGlvbiAodmFsdWUsIGFyZ3MpIHtcbiAgICBpZiAodHlwZW9mIHZhbHVlID09PSB0eXBlb2YgcGF0dGVybi52YWx1ZSAmJiB2YWx1ZSA9PT0gcGF0dGVybi52YWx1ZSkge1xuICAgICAgYXJncy5wdXNoKHZhbHVlKTtcbiAgICAgIHJldHVybiB0cnVlO1xuICAgIH1cblxuICAgIHJldHVybiBmYWxzZTtcbiAgfTtcbn1cblxuZnVuY3Rpb24gcmVzb2x2ZVdpbGRjYXJkKCkge1xuICByZXR1cm4gZnVuY3Rpb24gKCkge1xuICAgIHJldHVybiB0cnVlO1xuICB9O1xufVxuXG5mdW5jdGlvbiByZXNvbHZlVmFyaWFibGUoKSB7XG4gIHJldHVybiBmdW5jdGlvbiAodmFsdWUsIGFyZ3MpIHtcbiAgICBhcmdzLnB1c2godmFsdWUpO1xuICAgIHJldHVybiB0cnVlO1xuICB9O1xufVxuXG5mdW5jdGlvbiByZXNvbHZlSGVhZFRhaWwoKSB7XG4gIHJldHVybiBmdW5jdGlvbiAodmFsdWUsIGFyZ3MpIHtcbiAgICBpZiAoIUNoZWNrcy5pc19hcnJheSh2YWx1ZSkgfHwgdmFsdWUubGVuZ3RoIDwgMikge1xuICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH1cblxuICAgIGNvbnN0IGhlYWQgPSB2YWx1ZVswXTtcbiAgICBjb25zdCB0YWlsID0gdmFsdWUuc2xpY2UoMSk7XG5cbiAgICBhcmdzLnB1c2goaGVhZCk7XG4gICAgYXJncy5wdXNoKHRhaWwpO1xuXG4gICAgcmV0dXJuIHRydWU7XG4gIH07XG59XG5cbmZ1bmN0aW9uIHJlc29sdmVDYXB0dXJlKHBhdHRlcm4pIHtcbiAgY29uc3QgbWF0Y2hlcyA9IGJ1aWxkTWF0Y2gocGF0dGVybi52YWx1ZSk7XG5cbiAgcmV0dXJuIGZ1bmN0aW9uICh2YWx1ZSwgYXJncykge1xuICAgIGlmIChtYXRjaGVzKHZhbHVlLCBhcmdzKSkge1xuICAgICAgYXJncy5wdXNoKHZhbHVlKTtcbiAgICAgIHJldHVybiB0cnVlO1xuICAgIH1cblxuICAgIHJldHVybiBmYWxzZTtcbiAgfTtcbn1cblxuZnVuY3Rpb24gcmVzb2x2ZVN0YXJ0c1dpdGgocGF0dGVybikge1xuICBjb25zdCBwcmVmaXggPSBwYXR0ZXJuLnByZWZpeDtcblxuICByZXR1cm4gZnVuY3Rpb24gKHZhbHVlLCBhcmdzKSB7XG4gICAgaWYgKENoZWNrcy5pc19zdHJpbmcodmFsdWUpICYmIHZhbHVlLnN0YXJ0c1dpdGgocHJlZml4KSkge1xuICAgICAgYXJncy5wdXNoKHZhbHVlLnN1YnN0cmluZyhwcmVmaXgubGVuZ3RoKSk7XG4gICAgICByZXR1cm4gdHJ1ZTtcbiAgICB9XG5cbiAgICByZXR1cm4gZmFsc2U7XG4gIH07XG59XG5cbmZ1bmN0aW9uIHJlc29sdmVUeXBlKHBhdHRlcm4pIHtcbiAgcmV0dXJuIGZ1bmN0aW9uICh2YWx1ZSwgYXJncykge1xuICAgIGlmICh2YWx1ZSBpbnN0YW5jZW9mIHBhdHRlcm4udHlwZSkge1xuICAgICAgY29uc3QgbWF0Y2hlcyA9IGJ1aWxkTWF0Y2gocGF0dGVybi5vYmpQYXR0ZXJuKTtcbiAgICAgIHJldHVybiBtYXRjaGVzKHZhbHVlLCBhcmdzKSAmJiBhcmdzLnB1c2godmFsdWUpID4gMDtcbiAgICB9XG5cbiAgICByZXR1cm4gZmFsc2U7XG4gIH07XG59XG5cbmZ1bmN0aW9uIHJlc29sdmVBcnJheShwYXR0ZXJuKSB7XG4gIGNvbnN0IG1hdGNoZXMgPSBwYXR0ZXJuLm1hcCh4ID0+IGJ1aWxkTWF0Y2goeCkpO1xuXG4gIHJldHVybiBmdW5jdGlvbiAodmFsdWUsIGFyZ3MpIHtcbiAgICBpZiAoIUNoZWNrcy5pc19hcnJheSh2YWx1ZSkgfHwgdmFsdWUubGVuZ3RoICE9IHBhdHRlcm4ubGVuZ3RoKSB7XG4gICAgICByZXR1cm4gZmFsc2U7XG4gICAgfVxuXG4gICAgcmV0dXJuIHZhbHVlLmV2ZXJ5KGZ1bmN0aW9uICh2LCBpKSB7XG4gICAgICByZXR1cm4gbWF0Y2hlc1tpXSh2YWx1ZVtpXSwgYXJncyk7XG4gICAgfSk7XG4gIH07XG59XG5cbmZ1bmN0aW9uIHJlc29sdmVPYmplY3QocGF0dGVybikge1xuICBsZXQgbWF0Y2hlcyA9IHt9O1xuXG4gIGZvciAobGV0IGtleSBvZiBPYmplY3Qua2V5cyhwYXR0ZXJuKS5jb25jYXQoT2JqZWN0LmdldE93blByb3BlcnR5U3ltYm9scyhwYXR0ZXJuKSkpIHtcbiAgICBtYXRjaGVzW2tleV0gPSBidWlsZE1hdGNoKHBhdHRlcm5ba2V5XSk7XG4gIH1cblxuICByZXR1cm4gZnVuY3Rpb24gKHZhbHVlLCBhcmdzKSB7XG4gICAgaWYgKCFDaGVja3MuaXNfb2JqZWN0KHZhbHVlKSB8fCBwYXR0ZXJuLmxlbmd0aCA+IHZhbHVlLmxlbmd0aCkge1xuICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH1cblxuICAgIGZvciAobGV0IGtleSBvZiBPYmplY3Qua2V5cyhwYXR0ZXJuKS5jb25jYXQoT2JqZWN0LmdldE93blByb3BlcnR5U3ltYm9scyhwYXR0ZXJuKSkpIHtcbiAgICAgIGlmICghKGtleSBpbiB2YWx1ZSkgfHwgIW1hdGNoZXNba2V5XSh2YWx1ZVtrZXldLCBhcmdzKSkge1xuICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICB9XG4gICAgfVxuXG4gICAgcmV0dXJuIHRydWU7XG4gIH07XG59XG5cbmZ1bmN0aW9uIHJlc29sdmVOb01hdGNoKCkge1xuICByZXR1cm4gZnVuY3Rpb24gKCkge1xuICAgIHJldHVybiBmYWxzZTtcbiAgfTtcbn1cblxudmFyIFJlc29sdmVycyA9IHtcbiAgcmVzb2x2ZUJvdW5kLFxuICByZXNvbHZlV2lsZGNhcmQsXG4gIHJlc29sdmVWYXJpYWJsZSxcbiAgcmVzb2x2ZUhlYWRUYWlsLFxuICByZXNvbHZlQ2FwdHVyZSxcbiAgcmVzb2x2ZVN0YXJ0c1dpdGgsXG4gIHJlc29sdmVUeXBlLFxuICByZXNvbHZlQXJyYXksXG4gIHJlc29sdmVPYmplY3QsXG4gIHJlc29sdmVOb01hdGNoLFxuICByZXNvbHZlU3ltYm9sLFxuICByZXNvbHZlU3RyaW5nLFxuICByZXNvbHZlTnVtYmVyLFxuICByZXNvbHZlQm9vbGVhbixcbiAgcmVzb2x2ZUZ1bmN0aW9uLFxuICByZXNvbHZlTnVsbFxufTtcblxuZnVuY3Rpb24gYnVpbGRNYXRjaChwYXR0ZXJuKSB7XG5cbiAgaWYgKENoZWNrcy5pc192YXJpYWJsZShwYXR0ZXJuKSkge1xuICAgIHJldHVybiBSZXNvbHZlcnMucmVzb2x2ZVZhcmlhYmxlKHBhdHRlcm4pO1xuICB9XG5cbiAgaWYgKENoZWNrcy5pc193aWxkY2FyZChwYXR0ZXJuKSkge1xuICAgIHJldHVybiBSZXNvbHZlcnMucmVzb2x2ZVdpbGRjYXJkKHBhdHRlcm4pO1xuICB9XG5cbiAgaWYgKENoZWNrcy5pc191bmRlZmluZWQocGF0dGVybikpIHtcbiAgICByZXR1cm4gUmVzb2x2ZXJzLnJlc29sdmVXaWxkY2FyZChwYXR0ZXJuKTtcbiAgfVxuXG4gIGlmIChDaGVja3MuaXNfaGVhZFRhaWwocGF0dGVybikpIHtcbiAgICByZXR1cm4gUmVzb2x2ZXJzLnJlc29sdmVIZWFkVGFpbChwYXR0ZXJuKTtcbiAgfVxuXG4gIGlmIChDaGVja3MuaXNfc3RhcnRzV2l0aChwYXR0ZXJuKSkge1xuICAgIHJldHVybiBSZXNvbHZlcnMucmVzb2x2ZVN0YXJ0c1dpdGgocGF0dGVybik7XG4gIH1cblxuICBpZiAoQ2hlY2tzLmlzX2NhcHR1cmUocGF0dGVybikpIHtcbiAgICByZXR1cm4gUmVzb2x2ZXJzLnJlc29sdmVDYXB0dXJlKHBhdHRlcm4pO1xuICB9XG5cbiAgaWYgKENoZWNrcy5pc19ib3VuZChwYXR0ZXJuKSkge1xuICAgIHJldHVybiBSZXNvbHZlcnMucmVzb2x2ZUJvdW5kKHBhdHRlcm4pO1xuICB9XG5cbiAgaWYgKENoZWNrcy5pc190eXBlKHBhdHRlcm4pKSB7XG4gICAgcmV0dXJuIFJlc29sdmVycy5yZXNvbHZlVHlwZShwYXR0ZXJuKTtcbiAgfVxuXG4gIGlmIChDaGVja3MuaXNfYXJyYXkocGF0dGVybikpIHtcbiAgICByZXR1cm4gUmVzb2x2ZXJzLnJlc29sdmVBcnJheShwYXR0ZXJuKTtcbiAgfVxuXG4gIGlmIChDaGVja3MuaXNfbnVtYmVyKHBhdHRlcm4pKSB7XG4gICAgcmV0dXJuIFJlc29sdmVycy5yZXNvbHZlTnVtYmVyKHBhdHRlcm4pO1xuICB9XG5cbiAgaWYgKENoZWNrcy5pc19zdHJpbmcocGF0dGVybikpIHtcbiAgICByZXR1cm4gUmVzb2x2ZXJzLnJlc29sdmVTdHJpbmcocGF0dGVybik7XG4gIH1cblxuICBpZiAoQ2hlY2tzLmlzX2Jvb2xlYW4ocGF0dGVybikpIHtcbiAgICByZXR1cm4gUmVzb2x2ZXJzLnJlc29sdmVCb29sZWFuKHBhdHRlcm4pO1xuICB9XG5cbiAgaWYgKENoZWNrcy5pc19zeW1ib2wocGF0dGVybikpIHtcbiAgICByZXR1cm4gUmVzb2x2ZXJzLnJlc29sdmVTeW1ib2wocGF0dGVybik7XG4gIH1cblxuICBpZiAoQ2hlY2tzLmlzX251bGwocGF0dGVybikpIHtcbiAgICByZXR1cm4gUmVzb2x2ZXJzLnJlc29sdmVOdWxsKHBhdHRlcm4pO1xuICB9XG5cbiAgaWYgKENoZWNrcy5pc19vYmplY3QocGF0dGVybikpIHtcbiAgICByZXR1cm4gUmVzb2x2ZXJzLnJlc29sdmVPYmplY3QocGF0dGVybik7XG4gIH1cblxuICByZXR1cm4gUmVzb2x2ZXJzLnJlc29sdmVOb01hdGNoKCk7XG59XG5cbmNsYXNzIE1hdGNoRXJyb3IgZXh0ZW5kcyBFcnJvciB7XG4gIGNvbnN0cnVjdG9yKGFyZykge1xuICAgIHN1cGVyKCk7XG5cbiAgICBpZiAodHlwZW9mIGFyZyA9PT0gJ3N5bWJvbCcpIHtcbiAgICAgIHRoaXMubWVzc2FnZSA9ICdObyBtYXRjaCBmb3I6ICcgKyBhcmcudG9TdHJpbmcoKTtcbiAgICB9IGVsc2UgaWYgKEFycmF5LmlzQXJyYXkoYXJnKSkge1xuICAgICAgbGV0IG1hcHBlZFZhbHVlcyA9IGFyZy5tYXAoeCA9PiB4LnRvU3RyaW5nKCkpO1xuICAgICAgdGhpcy5tZXNzYWdlID0gJ05vIG1hdGNoIGZvcjogJyArIG1hcHBlZFZhbHVlcztcbiAgICB9IGVsc2Uge1xuICAgICAgdGhpcy5tZXNzYWdlID0gJ05vIG1hdGNoIGZvcjogJyArIGFyZztcbiAgICB9XG5cbiAgICB0aGlzLnN0YWNrID0gbmV3IEVycm9yKCkuc3RhY2s7XG4gICAgdGhpcy5uYW1lID0gdGhpcy5jb25zdHJ1Y3Rvci5uYW1lO1xuICB9XG59XG5cbmNsYXNzIENhc2Uge1xuXG4gIGNvbnN0cnVjdG9yKHBhdHRlcm4sIGZuLCBndWFyZCA9ICgpID0+IHRydWUpIHtcbiAgICB0aGlzLnBhdHRlcm4gPSBidWlsZE1hdGNoKHBhdHRlcm4pO1xuICAgIHRoaXMuZm4gPSBmbjtcbiAgICB0aGlzLmd1YXJkID0gZ3VhcmQ7XG4gIH1cbn1cblxuZnVuY3Rpb24gbWFrZV9jYXNlKHBhdHRlcm4sIGZuLCBndWFyZCA9ICgpID0+IHRydWUpIHtcbiAgcmV0dXJuIG5ldyBDYXNlKHBhdHRlcm4sIGZuLCBndWFyZCk7XG59XG5cbmZ1bmN0aW9uIGRlZm1hdGNoKC4uLmNhc2VzKSB7XG4gIHJldHVybiBmdW5jdGlvbiAoLi4uYXJncykge1xuICAgIGZvciAobGV0IHByb2Nlc3NlZENhc2Ugb2YgY2FzZXMpIHtcbiAgICAgIGxldCByZXN1bHQgPSBbXTtcbiAgICAgIGlmIChwcm9jZXNzZWRDYXNlLnBhdHRlcm4oYXJncywgcmVzdWx0KSAmJiBwcm9jZXNzZWRDYXNlLmd1YXJkLmFwcGx5KHRoaXMsIHJlc3VsdCkpIHtcbiAgICAgICAgcmV0dXJuIHByb2Nlc3NlZENhc2UuZm4uYXBwbHkodGhpcywgcmVzdWx0KTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICB0aHJvdyBuZXcgTWF0Y2hFcnJvcihhcmdzKTtcbiAgfTtcbn1cblxuZnVuY3Rpb24gbWF0Y2gocGF0dGVybiwgZXhwciwgZ3VhcmQgPSAoKSA9PiB0cnVlKSB7XG4gIGxldCByZXN1bHQgPSBbXTtcbiAgbGV0IHByb2Nlc3NlZFBhdHRlcm4gPSBidWlsZE1hdGNoKHBhdHRlcm4pO1xuICBpZiAocHJvY2Vzc2VkUGF0dGVybihleHByLCByZXN1bHQpICYmIGd1YXJkLmFwcGx5KHRoaXMsIHJlc3VsdCkpIHtcbiAgICByZXR1cm4gcmVzdWx0O1xuICB9IGVsc2Uge1xuICAgIHRocm93IG5ldyBNYXRjaEVycm9yKGV4cHIpO1xuICB9XG59XG5cbmZ1bmN0aW9uIG1hdGNoX25vX3Rocm93KHBhdHRlcm4sIGV4cHIsIGd1YXJkID0gKCkgPT4gdHJ1ZSkge1xuICB0cnkge1xuICAgIHJldHVybiBtYXRjaChwYXR0ZXJuLCBleHByLCBndWFyZCk7XG4gIH0gY2F0Y2ggKGUpIHtcbiAgICBpZiAoZSBpbnN0YW5jZW9mIE1hdGNoRXJyb3IpIHtcbiAgICAgIHJldHVybiBudWxsO1xuICAgIH1cblxuICAgIHRocm93IGU7XG4gIH1cbn1cblxudmFyIFBhdHRlcm5zID0ge1xuICBkZWZtYXRjaCwgbWF0Y2gsIE1hdGNoRXJyb3IsIG1hdGNoX25vX3Rocm93LFxuICB2YXJpYWJsZSwgd2lsZGNhcmQsIHN0YXJ0c1dpdGgsXG4gIGNhcHR1cmUsIGhlYWRUYWlsLCB0eXBlLCBib3VuZCwgQ2FzZSwgbWFrZV9jYXNlXG59O1xuXG4vL2h0dHBzOi8vZ2l0aHViLmNvbS9haXJwb3J0eWgvcHJvdG9tb3JwaGlzbVxuY2xhc3MgUHJvdG9jb2wge1xuICBjb25zdHJ1Y3RvcihzcGVjKSB7XG4gICAgdGhpcy5yZWdpc3RyeSA9IG5ldyBNYXAoKTtcbiAgICB0aGlzLmZhbGxiYWNrID0gbnVsbDtcblxuICAgIGZvciAobGV0IGZ1bk5hbWUgaW4gc3BlYykge1xuICAgICAgdGhpc1tmdW5OYW1lXSA9IGNyZWF0ZUZ1bihmdW5OYW1lKS5iaW5kKHRoaXMpO1xuICAgIH1cblxuICAgIGZ1bmN0aW9uIGNyZWF0ZUZ1bihmdW5OYW1lKSB7XG5cbiAgICAgIHJldHVybiBmdW5jdGlvbiAoLi4uYXJncykge1xuICAgICAgICBsZXQgdGhpbmcgPSBhcmdzWzBdO1xuICAgICAgICBsZXQgZnVuID0gbnVsbDtcblxuICAgICAgICBpZiAoTnVtYmVyLmlzSW50ZWdlcih0aGluZykgJiYgdGhpcy5oYXNJbXBsZW1lbnRhdGlvbihJbnRlZ2VyKSkge1xuICAgICAgICAgIGZ1biA9IHRoaXMucmVnaXN0cnkuZ2V0KENvcmUuSW50ZWdlcilbZnVuTmFtZV07XG4gICAgICAgIH0gZWxzZSBpZiAodHlwZW9mIHRoaW5nID09PSBcIm51bWJlclwiICYmICFOdW1iZXIuaXNJbnRlZ2VyKHRoaW5nKSAmJiB0aGlzLmhhc0ltcGxlbWVudGF0aW9uKEZsb2F0KSkge1xuICAgICAgICAgIGZ1biA9IHRoaXMucmVnaXN0cnkuZ2V0KENvcmUuRmxvYXQpW2Z1bk5hbWVdO1xuICAgICAgICB9IGVsc2UgaWYgKHRoaXMuaGFzSW1wbGVtZW50YXRpb24odGhpbmcpKSB7XG4gICAgICAgICAgZnVuID0gdGhpcy5yZWdpc3RyeS5nZXQodGhpbmcuY29uc3RydWN0b3IpW2Z1bk5hbWVdO1xuICAgICAgICB9IGVsc2UgaWYgKHRoaXMuZmFsbGJhY2spIHtcbiAgICAgICAgICBmdW4gPSB0aGlzLmZhbGxiYWNrW2Z1bk5hbWVdO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKGZ1biAhPSBudWxsKSB7XG4gICAgICAgICAgbGV0IHJldHZhbCA9IGZ1bi5hcHBseSh0aGlzLCBhcmdzKTtcbiAgICAgICAgICByZXR1cm4gcmV0dmFsO1xuICAgICAgICB9XG5cbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKFwiTm8gaW1wbGVtZW50YXRpb24gZm91bmQgZm9yIFwiICsgdGhpbmcpO1xuICAgICAgfTtcbiAgICB9XG4gIH1cblxuICBpbXBsZW1lbnRhdGlvbih0eXBlLCBpbXBsZW1lbnRhdGlvbikge1xuICAgIGlmICh0eXBlID09PSBudWxsKSB7XG4gICAgICB0aGlzLmZhbGxiYWNrID0gaW1wbGVtZW50YXRpb247XG4gICAgfSBlbHNlIHtcbiAgICAgIHRoaXMucmVnaXN0cnkuc2V0KHR5cGUsIGltcGxlbWVudGF0aW9uKTtcbiAgICB9XG4gIH1cblxuICBoYXNJbXBsZW1lbnRhdGlvbih0aGluZykge1xuICAgIHJldHVybiB0aGlzLnJlZ2lzdHJ5Lmhhcyh0aGluZy5jb25zdHJ1Y3Rvcik7XG4gIH1cbn1cblxuZnVuY3Rpb24gY2FsbF9wcm9wZXJ0eShpdGVtLCBwcm9wZXJ0eSkge1xuICBsZXQgcHJvcCA9IG51bGw7XG5cbiAgaWYgKHByb3BlcnR5IGluIGl0ZW0pIHtcbiAgICBwcm9wID0gcHJvcGVydHk7XG4gIH0gZWxzZSBpZiAoU3ltYm9sLmZvcihwcm9wZXJ0eSkgaW4gaXRlbSkge1xuICAgIHByb3AgPSBTeW1ib2wuZm9yKHByb3BlcnR5KTtcbiAgfSBlbHNlIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoYFByb3BlcnR5ICR7IHByb3BlcnR5IH0gbm90IGZvdW5kIGluICR7IGl0ZW0gfWApO1xuICB9XG5cbiAgaWYgKGl0ZW1bcHJvcF0gaW5zdGFuY2VvZiBGdW5jdGlvbikge1xuICAgIHJldHVybiBpdGVtW3Byb3BdKCk7XG4gIH0gZWxzZSB7XG4gICAgcmV0dXJuIGl0ZW1bcHJvcF07XG4gIH1cbn1cblxuZnVuY3Rpb24gYXBwbHkoLi4uYXJncykge1xuICBpZiAoYXJncy5sZW5ndGggPT09IDIpIHtcbiAgICBhcmdzWzBdLmFwcGx5KG51bGwsIGFyZ3Muc2xpY2UoMSkpO1xuICB9IGVsc2Uge1xuICAgIGFyZ3NbMF1bYXJnc1sxXV0uYXBwbHkobnVsbCwgYXJncy5zbGljZSgyKSk7XG4gIH1cbn1cblxuZnVuY3Rpb24gY29udGFpbnMobGVmdCwgcmlnaHQpIHtcbiAgZm9yIChsZXQgeCBvZiByaWdodCkge1xuICAgIGlmIChQYXR0ZXJucy5tYXRjaF9ub190aHJvdyhsZWZ0LCB4KSAhPSBudWxsKSB7XG4gICAgICByZXR1cm4gdHJ1ZTtcbiAgICB9XG4gIH1cblxuICByZXR1cm4gZmFsc2U7XG59XG5cbmZ1bmN0aW9uIGdldF9nbG9iYWwoKSB7XG4gIGlmICh0eXBlb2Ygc2VsZiAhPT0gJ3VuZGVmaW5lZCcpIHtcbiAgICByZXR1cm4gc2VsZjtcbiAgfSBlbHNlIGlmICh0eXBlb2Ygd2luZG93ICE9PSAndW5kZWZpbmVkJykge1xuICAgIHJldHVybiB3aW5kb3c7XG4gIH0gZWxzZSBpZiAodHlwZW9mIGdsb2JhbCAhPT0gJ3VuZGVmaW5lZCcpIHtcbiAgICByZXR1cm4gZ2xvYmFsO1xuICB9XG5cbiAgdGhyb3cgbmV3IEVycm9yKCdObyBnbG9iYWwgc3RhdGUgZm91bmQnKTtcbn1cblxuZnVuY3Rpb24gZGVmc3RydWN0KGRlZmF1bHRzKSB7XG4gIHJldHVybiBjbGFzcyB7XG4gICAgY29uc3RydWN0b3IodXBkYXRlID0ge30pIHtcbiAgICAgIGxldCB0aGVfdmFsdWVzID0gT2JqZWN0LmFzc2lnbihkZWZhdWx0cywgdXBkYXRlKTtcbiAgICAgIE9iamVjdC5hc3NpZ24odGhpcywgdGhlX3ZhbHVlcyk7XG4gICAgfVxuXG4gICAgc3RhdGljIGNyZWF0ZSh1cGRhdGVzID0ge30pIHtcbiAgICAgIGxldCB4ID0gbmV3IHRoaXModXBkYXRlcyk7XG4gICAgICByZXR1cm4gT2JqZWN0LmZyZWV6ZSh4KTtcbiAgICB9XG4gIH07XG59XG5cbmZ1bmN0aW9uIGRlZmV4Y2VwdGlvbihkZWZhdWx0cykge1xuICByZXR1cm4gY2xhc3MgZXh0ZW5kcyBFcnJvciB7XG4gICAgY29uc3RydWN0b3IodXBkYXRlID0ge30pIHtcbiAgICAgIGxldCBtZXNzYWdlID0gdXBkYXRlLm1lc3NhZ2UgfHwgJyc7XG4gICAgICBzdXBlcihtZXNzYWdlKTtcblxuICAgICAgbGV0IHRoZV92YWx1ZXMgPSBPYmplY3QuYXNzaWduKGRlZmF1bHRzLCB1cGRhdGUpO1xuICAgICAgT2JqZWN0LmFzc2lnbih0aGlzLCB0aGVfdmFsdWVzKTtcblxuICAgICAgdGhpcy5uYW1lID0gdGhpcy5jb25zdHJ1Y3Rvci5uYW1lO1xuICAgICAgdGhpcy5tZXNzYWdlID0gbWVzc2FnZTtcbiAgICAgIHRoaXNbU3BlY2lhbEZvcm1zLmF0b20oJ19fZXhjZXB0aW9uX18nKV0gPSB0cnVlO1xuICAgICAgRXJyb3IuY2FwdHVyZVN0YWNrVHJhY2UodGhpcywgdGhpcy5jb25zdHJ1Y3Rvci5uYW1lKTtcbiAgICB9XG5cbiAgICBzdGF0aWMgY3JlYXRlKHVwZGF0ZXMgPSB7fSkge1xuICAgICAgbGV0IHggPSBuZXcgdGhpcyh1cGRhdGVzKTtcbiAgICAgIHJldHVybiBPYmplY3QuZnJlZXplKHgpO1xuICAgIH1cbiAgfTtcbn1cblxuZnVuY3Rpb24gZGVmcHJvdG9jb2woc3BlYykge1xuICByZXR1cm4gbmV3IFByb3RvY29sKHNwZWMpO1xufVxuXG5mdW5jdGlvbiBkZWZpbXBsKHByb3RvY29sLCB0eXBlLCBpbXBsKSB7XG4gIHByb3RvY29sLmltcGxlbWVudGF0aW9uKHR5cGUsIGltcGwpO1xufVxuXG5mdW5jdGlvbiBnZXRfb2JqZWN0X2tleXMob2JqKSB7XG4gIHJldHVybiBPYmplY3Qua2V5cyhvYmopLmNvbmNhdChPYmplY3QuZ2V0T3duUHJvcGVydHlTeW1ib2xzKG9iaikpO1xufVxuXG5mdW5jdGlvbiBpc192YWxpZF9jaGFyYWN0ZXIoY29kZXBvaW50KSB7XG4gIHRyeSB7XG4gICAgcmV0dXJuIFN0cmluZy5mcm9tQ29kZVBvaW50KGNvZGVwb2ludCkgIT0gbnVsbDtcbiAgfSBjYXRjaCAoZSkge1xuICAgIHJldHVybiBmYWxzZTtcbiAgfVxufVxuXG4vL2h0dHBzOi8vZGV2ZWxvcGVyLm1vemlsbGEub3JnL2VuLVVTL2RvY3MvV2ViL0FQSS9XaW5kb3dCYXNlNjQvQmFzZTY0X2VuY29kaW5nX2FuZF9kZWNvZGluZyNTb2x1dGlvbl8yXyVFMiU4MCU5M19yZXdyaXRlX3RoZV9ET01zX2F0b2IoKV9hbmRfYnRvYSgpX3VzaW5nX0phdmFTY3JpcHQnc19UeXBlZEFycmF5c19hbmRfVVRGLThcbmZ1bmN0aW9uIGI2NEVuY29kZVVuaWNvZGUoc3RyKSB7XG4gIHJldHVybiBidG9hKGVuY29kZVVSSUNvbXBvbmVudChzdHIpLnJlcGxhY2UoLyUoWzAtOUEtRl17Mn0pL2csIGZ1bmN0aW9uIChtYXRjaCwgcDEpIHtcbiAgICByZXR1cm4gU3RyaW5nLmZyb21DaGFyQ29kZSgnMHgnICsgcDEpO1xuICB9KSk7XG59XG5cbmZ1bmN0aW9uIGRlbGV0ZV9wcm9wZXJ0eV9mcm9tX21hcChtYXAsIHByb3BlcnR5KSB7XG4gIGxldCBuZXdfbWFwID0gT2JqZWN0LmFzc2lnbihPYmplY3QuY3JlYXRlKG1hcC5jb25zdHJ1Y3Rvci5wcm90b3R5cGUpLCBtYXApO1xuICBkZWxldGUgbmV3X21hcFtwcm9wZXJ0eV07XG5cbiAgcmV0dXJuIE9iamVjdC5mcmVlemUobmV3X21hcCk7XG59XG5cbmZ1bmN0aW9uIGNsYXNzX3RvX29iaihtYXApIHtcbiAgbGV0IG5ld19tYXAgPSBPYmplY3QuYXNzaWduKHt9LCBtYXApO1xuICByZXR1cm4gT2JqZWN0LmZyZWV6ZShuZXdfbWFwKTtcbn1cblxuZnVuY3Rpb24gYWRkX3Byb3BlcnR5X3RvX21hcChtYXAsIHByb3BlcnR5LCB2YWx1ZSkge1xuICBsZXQgbmV3X21hcCA9IE9iamVjdC5hc3NpZ24oe30sIG1hcCk7XG4gIG5ld19tYXBbcHJvcGVydHldID0gdmFsdWU7XG4gIHJldHVybiBPYmplY3QuZnJlZXplKG5ld19tYXApO1xufVxuXG5mdW5jdGlvbiBibm90KGV4cHIpIHtcbiAgcmV0dXJuIH5leHByO1xufVxuXG5mdW5jdGlvbiBiYW5kKGxlZnQsIHJpZ2h0KSB7XG4gIHJldHVybiBsZWZ0ICYgcmlnaHQ7XG59XG5cbmZ1bmN0aW9uIGJvcihsZWZ0LCByaWdodCkge1xuICByZXR1cm4gbGVmdCB8IHJpZ2h0O1xufVxuXG5mdW5jdGlvbiBic2wobGVmdCwgcmlnaHQpIHtcbiAgcmV0dXJuIGxlZnQgPDwgcmlnaHQ7XG59XG5cbmZ1bmN0aW9uIGJzcihsZWZ0LCByaWdodCkge1xuICByZXR1cm4gbGVmdCA+PiByaWdodDtcbn1cblxuZnVuY3Rpb24gYnhvcihsZWZ0LCByaWdodCkge1xuICByZXR1cm4gbGVmdCBeIHJpZ2h0O1xufVxuXG5mdW5jdGlvbiB6aXAobGlzdF9vZl9saXN0cykge1xuICBpZiAobGlzdF9vZl9saXN0cy5sZW5ndGggPT09IDApIHtcbiAgICByZXR1cm4gT2JqZWN0LmZyZWV6ZShbXSk7XG4gIH1cblxuICBsZXQgbmV3X3ZhbHVlID0gW107XG4gIGxldCBzbWFsbGVzdF9sZW5ndGggPSBsaXN0X29mX2xpc3RzWzBdO1xuXG4gIGZvciAobGV0IHggb2YgbGlzdF9vZl9saXN0cykge1xuICAgIGlmICh4Lmxlbmd0aCA8IHNtYWxsZXN0X2xlbmd0aCkge1xuICAgICAgc21hbGxlc3RfbGVuZ3RoID0geC5sZW5ndGg7XG4gICAgfVxuICB9XG5cbiAgZm9yIChsZXQgaSA9IDA7IGkgPCBzbWFsbGVzdF9sZW5ndGg7IGkrKykge1xuICAgIGxldCBjdXJyZW50X3ZhbHVlID0gW107XG4gICAgZm9yIChsZXQgaiA9IDA7IGogPCBsaXN0X29mX2xpc3RzLmxlbmd0aDsgaisrKSB7XG4gICAgICBjdXJyZW50X3ZhbHVlLnB1c2gobGlzdF9vZl9saXN0c1tqXVtpXSk7XG4gICAgfVxuXG4gICAgbmV3X3ZhbHVlLnB1c2gobmV3IFR1cGxlKC4uLmN1cnJlbnRfdmFsdWUpKTtcbiAgfVxuXG4gIHJldHVybiBPYmplY3QuZnJlZXplKG5ld192YWx1ZSk7XG59XG5cbmZ1bmN0aW9uIGNhbl9kZWNvZGU2NChkYXRhKSB7XG4gIHRyeSB7XG4gICAgYXRvYihkYXRhKTtcbiAgICByZXR1cm4gdHJ1ZTtcbiAgfSBjYXRjaCAoZSkge1xuICAgIHJldHVybiBmYWxzZTtcbiAgfVxufVxuXG52YXIgRnVuY3Rpb25zID0ge1xuICBjYWxsX3Byb3BlcnR5LFxuICBhcHBseSxcbiAgY29udGFpbnMsXG4gIGdldF9nbG9iYWwsXG4gIGRlZnN0cnVjdCxcbiAgZGVmZXhjZXB0aW9uLFxuICBkZWZwcm90b2NvbCxcbiAgZGVmaW1wbCxcbiAgZ2V0X29iamVjdF9rZXlzLFxuICBpc192YWxpZF9jaGFyYWN0ZXIsXG4gIGI2NEVuY29kZVVuaWNvZGUsXG4gIGRlbGV0ZV9wcm9wZXJ0eV9mcm9tX21hcCxcbiAgYWRkX3Byb3BlcnR5X3RvX21hcCxcbiAgY2xhc3NfdG9fb2JqLFxuICBjYW5fZGVjb2RlNjQsXG4gIGJub3QsXG4gIGJhbmQsXG4gIGJvcixcbiAgYnNsLFxuICBic3IsXG4gIGJ4b3IsXG4gIHppcFxufTtcblxuZnVuY3Rpb24gX2Nhc2UoY29uZGl0aW9uLCBjbGF1c2VzKSB7XG4gIHJldHVybiBQYXR0ZXJucy5kZWZtYXRjaCguLi5jbGF1c2VzKShjb25kaXRpb24pO1xufVxuXG5mdW5jdGlvbiBjb25kKGNsYXVzZXMpIHtcbiAgZm9yIChsZXQgY2xhdXNlIG9mIGNsYXVzZXMpIHtcbiAgICBpZiAoY2xhdXNlWzBdKSB7XG4gICAgICByZXR1cm4gY2xhdXNlWzFdKCk7XG4gICAgfVxuICB9XG5cbiAgdGhyb3cgbmV3IEVycm9yKCk7XG59XG5cbmZ1bmN0aW9uIG1hcF91cGRhdGUobWFwLCB2YWx1ZXMpIHtcbiAgcmV0dXJuIE9iamVjdC5mcmVlemUoT2JqZWN0LmFzc2lnbihPYmplY3QuY3JlYXRlKG1hcC5jb25zdHJ1Y3Rvci5wcm90b3R5cGUpLCBtYXAsIHZhbHVlcykpO1xufVxuXG5mdW5jdGlvbiBfZm9yKGNvbGxlY3Rpb25zLCBmdW4sIGZpbHRlciA9ICgpID0+IHRydWUsIGludG8gPSBbXSwgcHJldmlvdXNWYWx1ZXMgPSBbXSkge1xuICBsZXQgcGF0dGVybiA9IGNvbGxlY3Rpb25zWzBdWzBdO1xuICBsZXQgY29sbGVjdGlvbiA9IGNvbGxlY3Rpb25zWzBdWzFdO1xuXG4gIGlmIChjb2xsZWN0aW9ucy5sZW5ndGggPT09IDEpIHtcblxuICAgIGZvciAobGV0IGVsZW0gb2YgY29sbGVjdGlvbikge1xuICAgICAgbGV0IHIgPSBQYXR0ZXJucy5tYXRjaF9ub190aHJvdyhwYXR0ZXJuLCBlbGVtKTtcbiAgICAgIGxldCBhcmdzID0gcHJldmlvdXNWYWx1ZXMuY29uY2F0KHIpO1xuXG4gICAgICBpZiAociAmJiBmaWx0ZXIuYXBwbHkodGhpcywgYXJncykpIHtcbiAgICAgICAgaW50byA9IGludG8uY29uY2F0KFtmdW4uYXBwbHkodGhpcywgYXJncyldKTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICByZXR1cm4gaW50bztcbiAgfSBlbHNlIHtcbiAgICBsZXQgX2ludG8gPSBbXTtcblxuICAgIGZvciAobGV0IGVsZW0gb2YgY29sbGVjdGlvbikge1xuICAgICAgbGV0IHIgPSBQYXR0ZXJucy5tYXRjaF9ub190aHJvdyhwYXR0ZXJuLCBlbGVtKTtcbiAgICAgIGlmIChyKSB7XG4gICAgICAgIF9pbnRvID0gaW50by5jb25jYXQodGhpcy5fZm9yKGNvbGxlY3Rpb25zLnNsaWNlKDEpLCBmdW4sIGZpbHRlciwgX2ludG8sIHByZXZpb3VzVmFsdWVzLmNvbmNhdChyKSkpO1xuICAgICAgfVxuICAgIH1cblxuICAgIHJldHVybiBfaW50bztcbiAgfVxufVxuXG5mdW5jdGlvbiBfdHJ5KGRvX2Z1biwgcmVzY3VlX2Z1bmN0aW9uLCBjYXRjaF9mdW4sIGVsc2VfZnVuY3Rpb24sIGFmdGVyX2Z1bmN0aW9uKSB7XG4gIGxldCByZXN1bHQgPSBudWxsO1xuXG4gIHRyeSB7XG4gICAgcmVzdWx0ID0gZG9fZnVuKCk7XG4gIH0gY2F0Y2ggKGUpIHtcbiAgICBsZXQgZXhfcmVzdWx0ID0gbnVsbDtcblxuICAgIGlmIChyZXNjdWVfZnVuY3Rpb24pIHtcbiAgICAgIHRyeSB7XG4gICAgICAgIGV4X3Jlc3VsdCA9IHJlc2N1ZV9mdW5jdGlvbihlKTtcbiAgICAgICAgcmV0dXJuIGV4X3Jlc3VsdDtcbiAgICAgIH0gY2F0Y2ggKGV4KSB7XG4gICAgICAgIGlmIChleCBpbnN0YW5jZW9mIFBhdHRlcm5zLk1hdGNoRXJyb3IpIHtcbiAgICAgICAgICB0aHJvdyBleDtcbiAgICAgICAgfVxuICAgICAgfVxuICAgIH1cblxuICAgIGlmIChjYXRjaF9mdW4pIHtcbiAgICAgIHRyeSB7XG4gICAgICAgIGV4X3Jlc3VsdCA9IGNhdGNoX2Z1bihlKTtcbiAgICAgICAgcmV0dXJuIGV4X3Jlc3VsdDtcbiAgICAgIH0gY2F0Y2ggKGV4KSB7XG4gICAgICAgIGlmIChleCBpbnN0YW5jZW9mIFBhdHRlcm5zLk1hdGNoRXJyb3IpIHtcbiAgICAgICAgICB0aHJvdyBleDtcbiAgICAgICAgfVxuICAgICAgfVxuICAgIH1cblxuICAgIHRocm93IGU7XG4gIH0gZmluYWxseSB7XG4gICAgaWYgKGFmdGVyX2Z1bmN0aW9uKSB7XG4gICAgICBhZnRlcl9mdW5jdGlvbigpO1xuICAgIH1cbiAgfVxuXG4gIGlmIChlbHNlX2Z1bmN0aW9uKSB7XG4gICAgdHJ5IHtcbiAgICAgIHJldHVybiBlbHNlX2Z1bmN0aW9uKHJlc3VsdCk7XG4gICAgfSBjYXRjaCAoZXgpIHtcbiAgICAgIGlmIChleCBpbnN0YW5jZW9mIFBhdHRlcm5zLk1hdGNoRXJyb3IpIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdObyBNYXRjaCBGb3VuZCBpbiBFbHNlJyk7XG4gICAgICB9XG5cbiAgICAgIHRocm93IGV4O1xuICAgIH1cbiAgfSBlbHNlIHtcbiAgICByZXR1cm4gcmVzdWx0O1xuICB9XG59XG5cbnZhciBTcGVjaWFsRm9ybXMkMSA9IHtcbiAgX2Nhc2UsXG4gIGNvbmQsXG4gIG1hcF91cGRhdGUsXG4gIF9mb3IsXG4gIF90cnlcbn07XG5cbkZ1bmN0aW9ucy5nZXRfZ2xvYmFsKCkucHJvY2Vzc2VzID0gRnVuY3Rpb25zLmdldF9nbG9iYWwoKS5wcm9jZXNzZXMgfHwgbmV3IFByb2Nlc3NTeXN0ZW0oKTtcblxudmFyIENvcmUkMSA9IHtcbiAgUHJvY2Vzc1N5c3RlbSxcbiAgVHVwbGUsXG4gIFBJRCxcbiAgQml0U3RyaW5nLFxuICBQYXR0ZXJucyxcbiAgSW50ZWdlcixcbiAgRmxvYXQsXG4gIEZ1bmN0aW9ucyxcbiAgU3BlY2lhbEZvcm1zOiBTcGVjaWFsRm9ybXMkMVxufTtcblxubGV0IEVudW0gPSB7XG5cbiAgYWxsX19xbWFya19fOiBmdW5jdGlvbiAoY29sbGVjdGlvbiwgZnVuID0geCA9PiB4KSB7XG4gICAgZm9yIChsZXQgZWxlbSBvZiBjb2xsZWN0aW9uKSB7XG4gICAgICBpZiAoIWZ1bihlbGVtKSkge1xuICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICB9XG4gICAgfVxuXG4gICAgcmV0dXJuIHRydWU7XG4gIH0sXG5cbiAgYW55X19xbWFya19fOiBmdW5jdGlvbiAoY29sbGVjdGlvbiwgZnVuID0geCA9PiB4KSB7XG4gICAgZm9yIChsZXQgZWxlbSBvZiBjb2xsZWN0aW9uKSB7XG4gICAgICBpZiAoZnVuKGVsZW0pKSB7XG4gICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgfVxuICAgIH1cblxuICAgIHJldHVybiBmYWxzZTtcbiAgfSxcblxuICBhdDogZnVuY3Rpb24gKGNvbGxlY3Rpb24sIG4sIHRoZV9kZWZhdWx0ID0gbnVsbCkge1xuICAgIGlmIChuID4gdGhpcy5jb3VudChjb2xsZWN0aW9uKSB8fCBuIDwgMCkge1xuICAgICAgcmV0dXJuIHRoZV9kZWZhdWx0O1xuICAgIH1cblxuICAgIHJldHVybiBjb2xsZWN0aW9uW25dO1xuICB9LFxuXG4gIGNvbmNhdDogZnVuY3Rpb24gKC4uLmVudW1hYmxlcykge1xuICAgIHJldHVybiBlbnVtYWJsZXNbMF0uY29uY2F0KGVudW1hYmxlc1sxXSk7XG4gIH0sXG5cbiAgY291bnQ6IGZ1bmN0aW9uIChjb2xsZWN0aW9uLCBmdW4gPSBudWxsKSB7XG4gICAgaWYgKGZ1biA9PSBudWxsKSB7XG4gICAgICByZXR1cm4gY29sbGVjdGlvbi5sZW5ndGg7XG4gICAgfSBlbHNlIHtcbiAgICAgIHJldHVybiBjb2xsZWN0aW9uLmZpbHRlcihmdW4pLmxlbmd0aDtcbiAgICB9XG4gIH0sXG5cbiAgZHJvcDogZnVuY3Rpb24gKGNvbGxlY3Rpb24sIGNvdW50KSB7XG4gICAgcmV0dXJuIGNvbGxlY3Rpb24uc2xpY2UoY291bnQpO1xuICB9LFxuXG4gIGRyb3Bfd2hpbGU6IGZ1bmN0aW9uIChjb2xsZWN0aW9uLCBmdW4pIHtcbiAgICBsZXQgY291bnQgPSAwO1xuXG4gICAgZm9yIChsZXQgZWxlbSBvZiBjb2xsZWN0aW9uKSB7XG4gICAgICBpZiAoZnVuKGVsZW0pKSB7XG4gICAgICAgIGNvdW50ID0gY291bnQgKyAxO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgYnJlYWs7XG4gICAgICB9XG4gICAgfVxuXG4gICAgcmV0dXJuIGNvbGxlY3Rpb24uc2xpY2UoY291bnQpO1xuICB9LFxuXG4gIGVhY2g6IGZ1bmN0aW9uIChjb2xsZWN0aW9uLCBmdW4pIHtcbiAgICBmb3IgKGxldCBlbGVtIG9mIGNvbGxlY3Rpb24pIHtcbiAgICAgIGZ1bihlbGVtKTtcbiAgICB9XG4gIH0sXG5cbiAgZW1wdHlfX3FtYXJrX186IGZ1bmN0aW9uIChjb2xsZWN0aW9uKSB7XG4gICAgcmV0dXJuIGNvbGxlY3Rpb24ubGVuZ3RoID09PSAwO1xuICB9LFxuXG4gIGZldGNoOiBmdW5jdGlvbiAoY29sbGVjdGlvbiwgbikge1xuICAgIGlmIChBcnJheS5pc0FycmF5KGNvbGxlY3Rpb24pKSB7XG4gICAgICBpZiAobiA8IHRoaXMuY291bnQoY29sbGVjdGlvbikgJiYgbiA+PSAwKSB7XG4gICAgICAgIHJldHVybiBuZXcgQ29yZSQxLlR1cGxlKFN5bWJvbC5mb3IoXCJva1wiKSwgY29sbGVjdGlvbltuXSk7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICByZXR1cm4gU3ltYm9sLmZvcihcImVycm9yXCIpO1xuICAgICAgfVxuICAgIH1cblxuICAgIHRocm93IG5ldyBFcnJvcihcImNvbGxlY3Rpb24gaXMgbm90IGFuIEVudW1lcmFibGVcIik7XG4gIH0sXG5cbiAgZmV0Y2hfX2VtYXJrX186IGZ1bmN0aW9uIChjb2xsZWN0aW9uLCBuKSB7XG4gICAgaWYgKEFycmF5LmlzQXJyYXkoY29sbGVjdGlvbikpIHtcbiAgICAgIGlmIChuIDwgdGhpcy5jb3VudChjb2xsZWN0aW9uKSAmJiBuID49IDApIHtcbiAgICAgICAgcmV0dXJuIGNvbGxlY3Rpb25bbl07XG4gICAgICB9IGVsc2Uge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoXCJvdXQgb2YgYm91bmRzIGVycm9yXCIpO1xuICAgICAgfVxuICAgIH1cblxuICAgIHRocm93IG5ldyBFcnJvcihcImNvbGxlY3Rpb24gaXMgbm90IGFuIEVudW1lcmFibGVcIik7XG4gIH0sXG5cbiAgZmlsdGVyOiBmdW5jdGlvbiAoY29sbGVjdGlvbiwgZnVuKSB7XG4gICAgbGV0IHJlc3VsdCA9IFtdO1xuXG4gICAgZm9yIChsZXQgZWxlbSBvZiBjb2xsZWN0aW9uKSB7XG4gICAgICBpZiAoZnVuKGVsZW0pKSB7XG4gICAgICAgIHJlc3VsdC5wdXNoKGVsZW0pO1xuICAgICAgfVxuICAgIH1cblxuICAgIHJldHVybiByZXN1bHQ7XG4gIH0sXG5cbiAgZmlsdGVyX21hcDogZnVuY3Rpb24gKGNvbGxlY3Rpb24sIGZpbHRlciwgbWFwcGVyKSB7XG4gICAgcmV0dXJuIEVudW0ubWFwKEVudW0uZmlsdGVyKGNvbGxlY3Rpb24sIGZpbHRlciksIG1hcHBlcik7XG4gIH0sXG5cbiAgZmluZDogZnVuY3Rpb24gKGNvbGxlY3Rpb24sIGlmX25vbmUgPSBudWxsLCBmdW4pIHtcbiAgICBmb3IgKGxldCBlbGVtIG9mIGNvbGxlY3Rpb24pIHtcbiAgICAgIGlmIChmdW4oZWxlbSkpIHtcbiAgICAgICAgcmV0dXJuIGVsZW07XG4gICAgICB9XG4gICAgfVxuXG4gICAgcmV0dXJuIGlmX25vbmU7XG4gIH0sXG5cbiAgaW50bzogZnVuY3Rpb24gKGNvbGxlY3Rpb24sIGxpc3QpIHtcbiAgICByZXR1cm4gbGlzdC5jb25jYXQoY29sbGVjdGlvbik7XG4gIH0sXG5cbiAgbWFwOiBmdW5jdGlvbiAoY29sbGVjdGlvbiwgZnVuKSB7XG4gICAgbGV0IHJlc3VsdCA9IFtdO1xuXG4gICAgZm9yIChsZXQgZWxlbSBvZiBjb2xsZWN0aW9uKSB7XG4gICAgICByZXN1bHQucHVzaChmdW4oZWxlbSkpO1xuICAgIH1cblxuICAgIHJldHVybiByZXN1bHQ7XG4gIH0sXG5cbiAgbWFwX3JlZHVjZTogZnVuY3Rpb24gKGNvbGxlY3Rpb24sIGFjYywgZnVuKSB7XG4gICAgbGV0IG1hcHBlZCA9IE9iamVjdC5mcmVlemUoW10pO1xuICAgIGxldCB0aGVfYWNjID0gYWNjO1xuXG4gICAgZm9yICh2YXIgaSA9IDA7IGkgPCB0aGlzLmNvdW50KGNvbGxlY3Rpb24pOyBpKyspIHtcbiAgICAgIGxldCB0dXBsZSA9IGZ1bihjb2xsZWN0aW9uW2ldLCB0aGVfYWNjKTtcblxuICAgICAgdGhlX2FjYyA9IHR1cGxlLmdldCgxKTtcbiAgICAgIG1hcHBlZCA9IE9iamVjdC5mcmVlemUobWFwcGVkLmNvbmNhdChbdHVwbGUuZ2V0KDApXSkpO1xuICAgIH1cblxuICAgIHJldHVybiBuZXcgQ29yZSQxLlR1cGxlKG1hcHBlZCwgdGhlX2FjYyk7XG4gIH0sXG5cbiAgbWVtYmVyX19xbWFya19fOiBmdW5jdGlvbiAoY29sbGVjdGlvbiwgdmFsdWUpIHtcbiAgICByZXR1cm4gY29sbGVjdGlvbi5pbmNsdWRlcyh2YWx1ZSk7XG4gIH0sXG5cbiAgcmVkdWNlOiBmdW5jdGlvbiAoY29sbGVjdGlvbiwgYWNjLCBmdW4pIHtcbiAgICBsZXQgdGhlX2FjYyA9IGFjYztcblxuICAgIGZvciAodmFyIGkgPSAwOyBpIDwgdGhpcy5jb3VudChjb2xsZWN0aW9uKTsgaSsrKSB7XG4gICAgICBsZXQgdHVwbGUgPSBmdW4oY29sbGVjdGlvbltpXSwgdGhlX2FjYyk7XG5cbiAgICAgIHRoZV9hY2MgPSB0dXBsZS5nZXQoMSk7XG4gICAgfVxuXG4gICAgcmV0dXJuIHRoZV9hY2M7XG4gIH0sXG5cbiAgdGFrZTogZnVuY3Rpb24gKGNvbGxlY3Rpb24sIGNvdW50KSB7XG4gICAgcmV0dXJuIGNvbGxlY3Rpb24uc2xpY2UoMCwgY291bnQpO1xuICB9LFxuXG4gIHRha2VfZXZlcnk6IGZ1bmN0aW9uIChjb2xsZWN0aW9uLCBudGgpIHtcbiAgICBsZXQgcmVzdWx0ID0gW107XG4gICAgbGV0IGluZGV4ID0gMDtcblxuICAgIGZvciAobGV0IGVsZW0gb2YgY29sbGVjdGlvbikge1xuICAgICAgaWYgKGluZGV4ICUgbnRoID09PSAwKSB7XG4gICAgICAgIHJlc3VsdC5wdXNoKGVsZW0pO1xuICAgICAgfVxuICAgIH1cblxuICAgIHJldHVybiBPYmplY3QuZnJlZXplKHJlc3VsdCk7XG4gIH0sXG5cbiAgdGFrZV93aGlsZTogZnVuY3Rpb24gKGNvbGxlY3Rpb24sIGZ1bikge1xuICAgIGxldCBjb3VudCA9IDA7XG5cbiAgICBmb3IgKGxldCBlbGVtIG9mIGNvbGxlY3Rpb24pIHtcbiAgICAgIGlmIChmdW4oZWxlbSkpIHtcbiAgICAgICAgY291bnQgPSBjb3VudCArIDE7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBicmVhaztcbiAgICAgIH1cbiAgICB9XG5cbiAgICByZXR1cm4gY29sbGVjdGlvbi5zbGljZSgwLCBjb3VudCk7XG4gIH0sXG5cbiAgdG9fbGlzdDogZnVuY3Rpb24gKGNvbGxlY3Rpb24pIHtcbiAgICByZXR1cm4gY29sbGVjdGlvbjtcbiAgfVxufTtcblxudmFyIEVsaXhpciA9IHtcbiAgQ29yZTogQ29yZSQxLFxuICBFbnVtLFxuICBWaXJ0dWFsRE9NXG59O1xuXG5leHBvcnQgZGVmYXVsdCBFbGl4aXI7Il0sImZpbGUiOiJFbGl4aXIuanMiLCJzb3VyY2VSb290IjoiL3NvdXJjZS8ifQ== \ No newline at end of file +//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiIiwic291cmNlcyI6WyJFbGl4aXIuanMiXSwic291cmNlc0NvbnRlbnQiOlsibGV0IFZpcnR1YWxET00gPSAoZnVuY3Rpb24gKGUpIHtcbiAgICByZXR1cm4gZSgpO1xufSkoZnVuY3Rpb24gKCkge1xuICAgIHZhciBkZWZpbmUsIG1vZHVsZSwgZXhwb3J0cztcbiAgICByZXR1cm4gKGZ1bmN0aW9uIGUodCwgbiwgcikge1xuICAgICAgICBmdW5jdGlvbiBzKG8sIHUpIHtcbiAgICAgICAgICAgIGlmICghbltvXSkge1xuICAgICAgICAgICAgICAgIGlmICghdFtvXSkge1xuICAgICAgICAgICAgICAgICAgICB2YXIgYSA9IHR5cGVvZiByZXF1aXJlID09IFwiZnVuY3Rpb25cIiAmJiByZXF1aXJlO1xuICAgICAgICAgICAgICAgICAgICBpZiAoIXUgJiYgYSkgcmV0dXJuIGEobywgITApO1xuICAgICAgICAgICAgICAgICAgICBpZiAoaSkgcmV0dXJuIGkobywgITApO1xuICAgICAgICAgICAgICAgICAgICB2YXIgZiA9IG5ldyBFcnJvcihcIkNhbm5vdCBmaW5kIG1vZHVsZSAnXCIgKyBvICsgXCInXCIpO1xuICAgICAgICAgICAgICAgICAgICB0aHJvdyAoZi5jb2RlID0gXCJNT0RVTEVfTk9UX0ZPVU5EXCIsIGYpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB2YXIgbCA9IG5bb10gPSB7XG4gICAgICAgICAgICAgICAgICAgIGV4cG9ydHM6IHt9XG4gICAgICAgICAgICAgICAgfTtcbiAgICAgICAgICAgICAgICB0W29dWzBdLmNhbGwobC5leHBvcnRzLCBmdW5jdGlvbiAoZSkge1xuICAgICAgICAgICAgICAgICAgICB2YXIgbiA9IHRbb11bMV1bZV07XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBzKG4gPyBuIDogZSk7XG4gICAgICAgICAgICAgICAgfSwgbCwgbC5leHBvcnRzLCBlLCB0LCBuLCByKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJldHVybiBuW29dLmV4cG9ydHM7XG4gICAgICAgIH1cbiAgICAgICAgdmFyIGkgPSB0eXBlb2YgcmVxdWlyZSA9PSBcImZ1bmN0aW9uXCIgJiYgcmVxdWlyZTtcbiAgICAgICAgZm9yICh2YXIgbyA9IDA7IG8gPCByLmxlbmd0aDsgbysrKSBzKHJbb10pO1xuICAgICAgICByZXR1cm4gcztcbiAgICB9KSh7XG4gICAgICAgIDE6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG5cbiAgICAgICAgICAgIHZhciBjcmVhdGVFbGVtZW50ID0gcmVxdWlyZShcIi4vdmRvbS9jcmVhdGUtZWxlbWVudC5qc1wiKTtcblxuICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBjcmVhdGVFbGVtZW50O1xuICAgICAgICB9LCB7IFwiLi92ZG9tL2NyZWF0ZS1lbGVtZW50LmpzXCI6IDE1IH1dLCAyOiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge1xuICAgICAgICAgICAgdmFyIGRpZmYgPSByZXF1aXJlKFwiLi92dHJlZS9kaWZmLmpzXCIpO1xuXG4gICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IGRpZmY7XG4gICAgICAgIH0sIHsgXCIuL3Z0cmVlL2RpZmYuanNcIjogMzUgfV0sIDM6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICB2YXIgaCA9IHJlcXVpcmUoXCIuL3ZpcnR1YWwtaHlwZXJzY3JpcHQvaW5kZXguanNcIik7XG5cbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gaDtcbiAgICAgICAgfSwgeyBcIi4vdmlydHVhbC1oeXBlcnNjcmlwdC9pbmRleC5qc1wiOiAyMiB9XSwgNDogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHtcbiAgICAgICAgICAgIHZhciBkaWZmID0gcmVxdWlyZShcIi4vZGlmZi5qc1wiKTtcbiAgICAgICAgICAgIHZhciBwYXRjaCA9IHJlcXVpcmUoXCIuL3BhdGNoLmpzXCIpO1xuICAgICAgICAgICAgdmFyIGggPSByZXF1aXJlKFwiLi9oLmpzXCIpO1xuICAgICAgICAgICAgdmFyIGNyZWF0ZSA9IHJlcXVpcmUoXCIuL2NyZWF0ZS1lbGVtZW50LmpzXCIpO1xuICAgICAgICAgICAgdmFyIFZOb2RlID0gcmVxdWlyZShcIi4vdm5vZGUvdm5vZGUuanNcIik7XG4gICAgICAgICAgICB2YXIgVlRleHQgPSByZXF1aXJlKFwiLi92bm9kZS92dGV4dC5qc1wiKTtcblxuICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSB7XG4gICAgICAgICAgICAgICAgZGlmZjogZGlmZixcbiAgICAgICAgICAgICAgICBwYXRjaDogcGF0Y2gsXG4gICAgICAgICAgICAgICAgaDogaCxcbiAgICAgICAgICAgICAgICBjcmVhdGU6IGNyZWF0ZSxcbiAgICAgICAgICAgICAgICBWTm9kZTogVk5vZGUsXG4gICAgICAgICAgICAgICAgVlRleHQ6IFZUZXh0XG4gICAgICAgICAgICB9O1xuICAgICAgICB9LCB7IFwiLi9jcmVhdGUtZWxlbWVudC5qc1wiOiAxLCBcIi4vZGlmZi5qc1wiOiAyLCBcIi4vaC5qc1wiOiAzLCBcIi4vcGF0Y2guanNcIjogMTMsIFwiLi92bm9kZS92bm9kZS5qc1wiOiAzMSwgXCIuL3Zub2RlL3Z0ZXh0LmpzXCI6IDMzIH1dLCA1OiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge1xuICAgICAgICAgICAgLyohXG4gICAgICAgICAgICAgKiBDcm9zcy1Ccm93c2VyIFNwbGl0IDEuMS4xXG4gICAgICAgICAgICAgKiBDb3B5cmlnaHQgMjAwNy0yMDEyIFN0ZXZlbiBMZXZpdGhhbiA8c3RldmVubGV2aXRoYW4uY29tPlxuICAgICAgICAgICAgICogQXZhaWxhYmxlIHVuZGVyIHRoZSBNSVQgTGljZW5zZVxuICAgICAgICAgICAgICogRUNNQVNjcmlwdCBjb21wbGlhbnQsIHVuaWZvcm0gY3Jvc3MtYnJvd3NlciBzcGxpdCBtZXRob2RcbiAgICAgICAgICAgICAqL1xuXG4gICAgICAgICAgICAvKipcbiAgICAgICAgICAgICAqIFNwbGl0cyBhIHN0cmluZyBpbnRvIGFuIGFycmF5IG9mIHN0cmluZ3MgdXNpbmcgYSByZWdleCBvciBzdHJpbmcgc2VwYXJhdG9yLiBNYXRjaGVzIG9mIHRoZVxuICAgICAgICAgICAgICogc2VwYXJhdG9yIGFyZSBub3QgaW5jbHVkZWQgaW4gdGhlIHJlc3VsdCBhcnJheS4gSG93ZXZlciwgaWYgYHNlcGFyYXRvcmAgaXMgYSByZWdleCB0aGF0IGNvbnRhaW5zXG4gICAgICAgICAgICAgKiBjYXB0dXJpbmcgZ3JvdXBzLCBiYWNrcmVmZXJlbmNlcyBhcmUgc3BsaWNlZCBpbnRvIHRoZSByZXN1bHQgZWFjaCB0aW1lIGBzZXBhcmF0b3JgIGlzIG1hdGNoZWQuXG4gICAgICAgICAgICAgKiBGaXhlcyBicm93c2VyIGJ1Z3MgY29tcGFyZWQgdG8gdGhlIG5hdGl2ZSBgU3RyaW5nLnByb3RvdHlwZS5zcGxpdGAgYW5kIGNhbiBiZSB1c2VkIHJlbGlhYmx5XG4gICAgICAgICAgICAgKiBjcm9zcy1icm93c2VyLlxuICAgICAgICAgICAgICogQHBhcmFtIHtTdHJpbmd9IHN0ciBTdHJpbmcgdG8gc3BsaXQuXG4gICAgICAgICAgICAgKiBAcGFyYW0ge1JlZ0V4cHxTdHJpbmd9IHNlcGFyYXRvciBSZWdleCBvciBzdHJpbmcgdG8gdXNlIGZvciBzZXBhcmF0aW5nIHRoZSBzdHJpbmcuXG4gICAgICAgICAgICAgKiBAcGFyYW0ge051bWJlcn0gW2xpbWl0XSBNYXhpbXVtIG51bWJlciBvZiBpdGVtcyB0byBpbmNsdWRlIGluIHRoZSByZXN1bHQgYXJyYXkuXG4gICAgICAgICAgICAgKiBAcmV0dXJucyB7QXJyYXl9IEFycmF5IG9mIHN1YnN0cmluZ3MuXG4gICAgICAgICAgICAgKiBAZXhhbXBsZVxuICAgICAgICAgICAgICpcbiAgICAgICAgICAgICAqIC8vIEJhc2ljIHVzZVxuICAgICAgICAgICAgICogc3BsaXQoJ2EgYiBjIGQnLCAnICcpO1xuICAgICAgICAgICAgICogLy8gLT4gWydhJywgJ2InLCAnYycsICdkJ11cbiAgICAgICAgICAgICAqXG4gICAgICAgICAgICAgKiAvLyBXaXRoIGxpbWl0XG4gICAgICAgICAgICAgKiBzcGxpdCgnYSBiIGMgZCcsICcgJywgMik7XG4gICAgICAgICAgICAgKiAvLyAtPiBbJ2EnLCAnYiddXG4gICAgICAgICAgICAgKlxuICAgICAgICAgICAgICogLy8gQmFja3JlZmVyZW5jZXMgaW4gcmVzdWx0IGFycmF5XG4gICAgICAgICAgICAgKiBzcGxpdCgnLi53b3JkMSB3b3JkMi4uJywgLyhbYS16XSspKFxcZCspL2kpO1xuICAgICAgICAgICAgICogLy8gLT4gWycuLicsICd3b3JkJywgJzEnLCAnICcsICd3b3JkJywgJzInLCAnLi4nXVxuICAgICAgICAgICAgICovXG4gICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IChmdW5jdGlvbiBzcGxpdCh1bmRlZikge1xuXG4gICAgICAgICAgICAgICAgdmFyIG5hdGl2ZVNwbGl0ID0gU3RyaW5nLnByb3RvdHlwZS5zcGxpdCxcbiAgICAgICAgICAgICAgICAgICAgY29tcGxpYW50RXhlY05wY2cgPSAvKCk/Py8uZXhlYyhcIlwiKVsxXSA9PT0gdW5kZWYsXG5cbiAgICAgICAgICAgICAgICAvLyBOUENHOiBub25wYXJ0aWNpcGF0aW5nIGNhcHR1cmluZyBncm91cFxuICAgICAgICAgICAgICAgIHNlbGY7XG5cbiAgICAgICAgICAgICAgICBzZWxmID0gZnVuY3Rpb24gKHN0ciwgc2VwYXJhdG9yLCBsaW1pdCkge1xuICAgICAgICAgICAgICAgICAgICAvLyBJZiBgc2VwYXJhdG9yYCBpcyBub3QgYSByZWdleCwgdXNlIGBuYXRpdmVTcGxpdGBcbiAgICAgICAgICAgICAgICAgICAgaWYgKE9iamVjdC5wcm90b3R5cGUudG9TdHJpbmcuY2FsbChzZXBhcmF0b3IpICE9PSBcIltvYmplY3QgUmVnRXhwXVwiKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gbmF0aXZlU3BsaXQuY2FsbChzdHIsIHNlcGFyYXRvciwgbGltaXQpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIHZhciBvdXRwdXQgPSBbXSxcbiAgICAgICAgICAgICAgICAgICAgICAgIGZsYWdzID0gKHNlcGFyYXRvci5pZ25vcmVDYXNlID8gXCJpXCIgOiBcIlwiKSArIChzZXBhcmF0b3IubXVsdGlsaW5lID8gXCJtXCIgOiBcIlwiKSArIChzZXBhcmF0b3IuZXh0ZW5kZWQgPyBcInhcIiA6IFwiXCIpICsgKHNlcGFyYXRvci5zdGlja3kgPyBcInlcIiA6IFwiXCIpLFxuXG4gICAgICAgICAgICAgICAgICAgIC8vIEZpcmVmb3ggMytcbiAgICAgICAgICAgICAgICAgICAgbGFzdExhc3RJbmRleCA9IDAsXG5cbiAgICAgICAgICAgICAgICAgICAgLy8gTWFrZSBgZ2xvYmFsYCBhbmQgYXZvaWQgYGxhc3RJbmRleGAgaXNzdWVzIGJ5IHdvcmtpbmcgd2l0aCBhIGNvcHlcbiAgICAgICAgICAgICAgICAgICAgc2VwYXJhdG9yID0gbmV3IFJlZ0V4cChzZXBhcmF0b3Iuc291cmNlLCBmbGFncyArIFwiZ1wiKSxcbiAgICAgICAgICAgICAgICAgICAgICAgIHNlcGFyYXRvcjIsXG4gICAgICAgICAgICAgICAgICAgICAgICBtYXRjaCxcbiAgICAgICAgICAgICAgICAgICAgICAgIGxhc3RJbmRleCxcbiAgICAgICAgICAgICAgICAgICAgICAgIGxhc3RMZW5ndGg7XG4gICAgICAgICAgICAgICAgICAgIHN0ciArPSBcIlwiOyAvLyBUeXBlLWNvbnZlcnRcbiAgICAgICAgICAgICAgICAgICAgaWYgKCFjb21wbGlhbnRFeGVjTnBjZykge1xuICAgICAgICAgICAgICAgICAgICAgICAgLy8gRG9lc24ndCBuZWVkIGZsYWdzIGd5LCBidXQgdGhleSBkb24ndCBodXJ0XG4gICAgICAgICAgICAgICAgICAgICAgICBzZXBhcmF0b3IyID0gbmV3IFJlZ0V4cChcIl5cIiArIHNlcGFyYXRvci5zb3VyY2UgKyBcIiQoPyFcXFxccylcIiwgZmxhZ3MpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIC8qIFZhbHVlcyBmb3IgYGxpbWl0YCwgcGVyIHRoZSBzcGVjOlxuICAgICAgICAgICAgICAgICAgICAgKiBJZiB1bmRlZmluZWQ6IDQyOTQ5NjcyOTUgLy8gTWF0aC5wb3coMiwgMzIpIC0gMVxuICAgICAgICAgICAgICAgICAgICAgKiBJZiAwLCBJbmZpbml0eSwgb3IgTmFOOiAwXG4gICAgICAgICAgICAgICAgICAgICAqIElmIHBvc2l0aXZlIG51bWJlcjogbGltaXQgPSBNYXRoLmZsb29yKGxpbWl0KTsgaWYgKGxpbWl0ID4gNDI5NDk2NzI5NSkgbGltaXQgLT0gNDI5NDk2NzI5NjtcbiAgICAgICAgICAgICAgICAgICAgICogSWYgbmVnYXRpdmUgbnVtYmVyOiA0Mjk0OTY3Mjk2IC0gTWF0aC5mbG9vcihNYXRoLmFicyhsaW1pdCkpXG4gICAgICAgICAgICAgICAgICAgICAqIElmIG90aGVyOiBUeXBlLWNvbnZlcnQsIHRoZW4gdXNlIHRoZSBhYm92ZSBydWxlc1xuICAgICAgICAgICAgICAgICAgICAgKi9cbiAgICAgICAgICAgICAgICAgICAgbGltaXQgPSBsaW1pdCA9PT0gdW5kZWYgPyAtMSA+Pj4gMCA6IC8vIE1hdGgucG93KDIsIDMyKSAtIDFcbiAgICAgICAgICAgICAgICAgICAgbGltaXQgPj4+IDA7IC8vIFRvVWludDMyKGxpbWl0KVxuICAgICAgICAgICAgICAgICAgICB3aGlsZSAobWF0Y2ggPSBzZXBhcmF0b3IuZXhlYyhzdHIpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAvLyBgc2VwYXJhdG9yLmxhc3RJbmRleGAgaXMgbm90IHJlbGlhYmxlIGNyb3NzLWJyb3dzZXJcbiAgICAgICAgICAgICAgICAgICAgICAgIGxhc3RJbmRleCA9IG1hdGNoLmluZGV4ICsgbWF0Y2hbMF0ubGVuZ3RoO1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGxhc3RJbmRleCA+IGxhc3RMYXN0SW5kZXgpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBvdXRwdXQucHVzaChzdHIuc2xpY2UobGFzdExhc3RJbmRleCwgbWF0Y2guaW5kZXgpKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBGaXggYnJvd3NlcnMgd2hvc2UgYGV4ZWNgIG1ldGhvZHMgZG9uJ3QgY29uc2lzdGVudGx5IHJldHVybiBgdW5kZWZpbmVkYCBmb3JcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBub25wYXJ0aWNpcGF0aW5nIGNhcHR1cmluZyBncm91cHNcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoIWNvbXBsaWFudEV4ZWNOcGNnICYmIG1hdGNoLmxlbmd0aCA+IDEpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbWF0Y2hbMF0ucmVwbGFjZShzZXBhcmF0b3IyLCBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBmb3IgKHZhciBpID0gMTsgaSA8IGFyZ3VtZW50cy5sZW5ndGggLSAyOyBpKyspIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoYXJndW1lbnRzW2ldID09PSB1bmRlZikge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBtYXRjaFtpXSA9IHVuZGVmO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChtYXRjaC5sZW5ndGggPiAxICYmIG1hdGNoLmluZGV4IDwgc3RyLmxlbmd0aCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBBcnJheS5wcm90b3R5cGUucHVzaC5hcHBseShvdXRwdXQsIG1hdGNoLnNsaWNlKDEpKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgbGFzdExlbmd0aCA9IG1hdGNoWzBdLmxlbmd0aDtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBsYXN0TGFzdEluZGV4ID0gbGFzdEluZGV4O1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChvdXRwdXQubGVuZ3RoID49IGxpbWl0KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChzZXBhcmF0b3IubGFzdEluZGV4ID09PSBtYXRjaC5pbmRleCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNlcGFyYXRvci5sYXN0SW5kZXgrKzsgLy8gQXZvaWQgYW4gaW5maW5pdGUgbG9vcFxuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIGlmIChsYXN0TGFzdEluZGV4ID09PSBzdHIubGVuZ3RoKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAobGFzdExlbmd0aCB8fCAhc2VwYXJhdG9yLnRlc3QoXCJcIikpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBvdXRwdXQucHVzaChcIlwiKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIG91dHB1dC5wdXNoKHN0ci5zbGljZShsYXN0TGFzdEluZGV4KSk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIG91dHB1dC5sZW5ndGggPiBsaW1pdCA/IG91dHB1dC5zbGljZSgwLCBsaW1pdCkgOiBvdXRwdXQ7XG4gICAgICAgICAgICAgICAgfTtcblxuICAgICAgICAgICAgICAgIHJldHVybiBzZWxmO1xuICAgICAgICAgICAgfSkoKTtcbiAgICAgICAgfSwge31dLCA2OiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge30sIHt9XSwgNzogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHtcbiAgICAgICAgICAgIFwidXNlIHN0cmljdFwiO1xuXG4gICAgICAgICAgICB2YXIgT25lVmVyc2lvbkNvbnN0cmFpbnQgPSByZXF1aXJlKFwiaW5kaXZpZHVhbC9vbmUtdmVyc2lvblwiKTtcblxuICAgICAgICAgICAgdmFyIE1ZX1ZFUlNJT04gPSBcIjdcIjtcbiAgICAgICAgICAgIE9uZVZlcnNpb25Db25zdHJhaW50KFwiZXYtc3RvcmVcIiwgTVlfVkVSU0lPTik7XG5cbiAgICAgICAgICAgIHZhciBoYXNoS2V5ID0gXCJfX0VWX1NUT1JFX0tFWUBcIiArIE1ZX1ZFUlNJT047XG5cbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gRXZTdG9yZTtcblxuICAgICAgICAgICAgZnVuY3Rpb24gRXZTdG9yZShlbGVtKSB7XG4gICAgICAgICAgICAgICAgdmFyIGhhc2ggPSBlbGVtW2hhc2hLZXldO1xuXG4gICAgICAgICAgICAgICAgaWYgKCFoYXNoKSB7XG4gICAgICAgICAgICAgICAgICAgIGhhc2ggPSBlbGVtW2hhc2hLZXldID0ge307XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgcmV0dXJuIGhhc2g7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0sIHsgXCJpbmRpdmlkdWFsL29uZS12ZXJzaW9uXCI6IDkgfV0sIDg6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICAoZnVuY3Rpb24gKGdsb2JhbCkge1xuICAgICAgICAgICAgICAgIFwidXNlIHN0cmljdFwiO1xuXG4gICAgICAgICAgICAgICAgLypnbG9iYWwgd2luZG93LCBnbG9iYWwqL1xuXG4gICAgICAgICAgICAgICAgdmFyIHJvb3QgPSB0eXBlb2Ygd2luZG93ICE9PSBcInVuZGVmaW5lZFwiID8gd2luZG93IDogdHlwZW9mIGdsb2JhbCAhPT0gXCJ1bmRlZmluZWRcIiA/IGdsb2JhbCA6IHt9O1xuXG4gICAgICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBJbmRpdmlkdWFsO1xuXG4gICAgICAgICAgICAgICAgZnVuY3Rpb24gSW5kaXZpZHVhbChrZXksIHZhbHVlKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmIChrZXkgaW4gcm9vdCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHJvb3Rba2V5XTtcbiAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgIHJvb3Rba2V5XSA9IHZhbHVlO1xuXG4gICAgICAgICAgICAgICAgICAgIHJldHVybiB2YWx1ZTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9KS5jYWxsKHRoaXMsIHR5cGVvZiBnbG9iYWwgIT09IFwidW5kZWZpbmVkXCIgPyBnbG9iYWwgOiB0eXBlb2Ygc2VsZiAhPT0gXCJ1bmRlZmluZWRcIiA/IHNlbGYgOiB0eXBlb2Ygd2luZG93ICE9PSBcInVuZGVmaW5lZFwiID8gd2luZG93IDoge30pO1xuICAgICAgICB9LCB7fV0sIDk6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICBcInVzZSBzdHJpY3RcIjtcblxuICAgICAgICAgICAgdmFyIEluZGl2aWR1YWwgPSByZXF1aXJlKFwiLi9pbmRleC5qc1wiKTtcblxuICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBPbmVWZXJzaW9uO1xuXG4gICAgICAgICAgICBmdW5jdGlvbiBPbmVWZXJzaW9uKG1vZHVsZU5hbWUsIHZlcnNpb24sIGRlZmF1bHRWYWx1ZSkge1xuICAgICAgICAgICAgICAgIHZhciBrZXkgPSBcIl9fSU5ESVZJRFVBTF9PTkVfVkVSU0lPTl9cIiArIG1vZHVsZU5hbWU7XG4gICAgICAgICAgICAgICAgdmFyIGVuZm9yY2VLZXkgPSBrZXkgKyBcIl9FTkZPUkNFX1NJTkdMRVRPTlwiO1xuXG4gICAgICAgICAgICAgICAgdmFyIHZlcnNpb25WYWx1ZSA9IEluZGl2aWR1YWwoZW5mb3JjZUtleSwgdmVyc2lvbik7XG5cbiAgICAgICAgICAgICAgICBpZiAodmVyc2lvblZhbHVlICE9PSB2ZXJzaW9uKSB7XG4gICAgICAgICAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcihcIkNhbiBvbmx5IGhhdmUgb25lIGNvcHkgb2YgXCIgKyBtb2R1bGVOYW1lICsgXCIuXFxuXCIgKyBcIllvdSBhbHJlYWR5IGhhdmUgdmVyc2lvbiBcIiArIHZlcnNpb25WYWx1ZSArIFwiIGluc3RhbGxlZC5cXG5cIiArIFwiVGhpcyBtZWFucyB5b3UgY2Fubm90IGluc3RhbGwgdmVyc2lvbiBcIiArIHZlcnNpb24pO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHJldHVybiBJbmRpdmlkdWFsKGtleSwgZGVmYXVsdFZhbHVlKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSwgeyBcIi4vaW5kZXguanNcIjogOCB9XSwgMTA6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICAoZnVuY3Rpb24gKGdsb2JhbCkge1xuICAgICAgICAgICAgICAgIHZhciB0b3BMZXZlbCA9IHR5cGVvZiBnbG9iYWwgIT09IFwidW5kZWZpbmVkXCIgPyBnbG9iYWwgOiB0eXBlb2Ygd2luZG93ICE9PSBcInVuZGVmaW5lZFwiID8gd2luZG93IDoge307XG4gICAgICAgICAgICAgICAgdmFyIG1pbkRvYyA9IHJlcXVpcmUoXCJtaW4tZG9jdW1lbnRcIik7XG5cbiAgICAgICAgICAgICAgICBpZiAodHlwZW9mIGRvY3VtZW50ICE9PSBcInVuZGVmaW5lZFwiKSB7XG4gICAgICAgICAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gZG9jdW1lbnQ7XG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgdmFyIGRvY2N5ID0gdG9wTGV2ZWxbXCJfX0dMT0JBTF9ET0NVTUVOVF9DQUNIRUA0XCJdO1xuXG4gICAgICAgICAgICAgICAgICAgIGlmICghZG9jY3kpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGRvY2N5ID0gdG9wTGV2ZWxbXCJfX0dMT0JBTF9ET0NVTUVOVF9DQUNIRUA0XCJdID0gbWluRG9jO1xuICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBkb2NjeTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9KS5jYWxsKHRoaXMsIHR5cGVvZiBnbG9iYWwgIT09IFwidW5kZWZpbmVkXCIgPyBnbG9iYWwgOiB0eXBlb2Ygc2VsZiAhPT0gXCJ1bmRlZmluZWRcIiA/IHNlbGYgOiB0eXBlb2Ygd2luZG93ICE9PSBcInVuZGVmaW5lZFwiID8gd2luZG93IDoge30pO1xuICAgICAgICB9LCB7IFwibWluLWRvY3VtZW50XCI6IDYgfV0sIDExOiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge1xuICAgICAgICAgICAgXCJ1c2Ugc3RyaWN0XCI7XG5cbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gaXNPYmplY3QoeCkge1xuICAgICAgICAgICAgICAgIHJldHVybiB0eXBlb2YgeCA9PT0gXCJvYmplY3RcIiAmJiB4ICE9PSBudWxsO1xuICAgICAgICAgICAgfTtcbiAgICAgICAgfSwge31dLCAxMjogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHtcbiAgICAgICAgICAgIHZhciBuYXRpdmVJc0FycmF5ID0gQXJyYXkuaXNBcnJheTtcbiAgICAgICAgICAgIHZhciB0b1N0cmluZyA9IE9iamVjdC5wcm90b3R5cGUudG9TdHJpbmc7XG5cbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gbmF0aXZlSXNBcnJheSB8fCBpc0FycmF5O1xuXG4gICAgICAgICAgICBmdW5jdGlvbiBpc0FycmF5KG9iaikge1xuICAgICAgICAgICAgICAgIHJldHVybiB0b1N0cmluZy5jYWxsKG9iaikgPT09IFwiW29iamVjdCBBcnJheV1cIjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSwge31dLCAxMzogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHtcbiAgICAgICAgICAgIHZhciBwYXRjaCA9IHJlcXVpcmUoXCIuL3Zkb20vcGF0Y2guanNcIik7XG5cbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gcGF0Y2g7XG4gICAgICAgIH0sIHsgXCIuL3Zkb20vcGF0Y2guanNcIjogMTggfV0sIDE0OiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge1xuICAgICAgICAgICAgdmFyIGlzT2JqZWN0ID0gcmVxdWlyZShcImlzLW9iamVjdFwiKTtcbiAgICAgICAgICAgIHZhciBpc0hvb2sgPSByZXF1aXJlKFwiLi4vdm5vZGUvaXMtdmhvb2suanNcIik7XG5cbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gYXBwbHlQcm9wZXJ0aWVzO1xuXG4gICAgICAgICAgICBmdW5jdGlvbiBhcHBseVByb3BlcnRpZXMobm9kZSwgcHJvcHMsIHByZXZpb3VzKSB7XG4gICAgICAgICAgICAgICAgZm9yICh2YXIgcHJvcE5hbWUgaW4gcHJvcHMpIHtcbiAgICAgICAgICAgICAgICAgICAgdmFyIHByb3BWYWx1ZSA9IHByb3BzW3Byb3BOYW1lXTtcblxuICAgICAgICAgICAgICAgICAgICBpZiAocHJvcFZhbHVlID09PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJlbW92ZVByb3BlcnR5KG5vZGUsIHByb3BOYW1lLCBwcm9wVmFsdWUsIHByZXZpb3VzKTtcbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIGlmIChpc0hvb2socHJvcFZhbHVlKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgcmVtb3ZlUHJvcGVydHkobm9kZSwgcHJvcE5hbWUsIHByb3BWYWx1ZSwgcHJldmlvdXMpO1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHByb3BWYWx1ZS5ob29rKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcHJvcFZhbHVlLmhvb2sobm9kZSwgcHJvcE5hbWUsIHByZXZpb3VzID8gcHJldmlvdXNbcHJvcE5hbWVdIDogdW5kZWZpbmVkKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChpc09iamVjdChwcm9wVmFsdWUpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcGF0Y2hPYmplY3Qobm9kZSwgcHJvcHMsIHByZXZpb3VzLCBwcm9wTmFtZSwgcHJvcFZhbHVlKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgbm9kZVtwcm9wTmFtZV0gPSBwcm9wVmFsdWU7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIHJlbW92ZVByb3BlcnR5KG5vZGUsIHByb3BOYW1lLCBwcm9wVmFsdWUsIHByZXZpb3VzKSB7XG4gICAgICAgICAgICAgICAgaWYgKHByZXZpb3VzKSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciBwcmV2aW91c1ZhbHVlID0gcHJldmlvdXNbcHJvcE5hbWVdO1xuXG4gICAgICAgICAgICAgICAgICAgIGlmICghaXNIb29rKHByZXZpb3VzVmFsdWUpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAocHJvcE5hbWUgPT09IFwiYXR0cmlidXRlc1wiKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgZm9yICh2YXIgYXR0ck5hbWUgaW4gcHJldmlvdXNWYWx1ZSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBub2RlLnJlbW92ZUF0dHJpYnV0ZShhdHRyTmFtZSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIGlmIChwcm9wTmFtZSA9PT0gXCJzdHlsZVwiKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgZm9yICh2YXIgaSBpbiBwcmV2aW91c1ZhbHVlKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG5vZGUuc3R5bGVbaV0gPSBcIlwiO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAodHlwZW9mIHByZXZpb3VzVmFsdWUgPT09IFwic3RyaW5nXCIpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBub2RlW3Byb3BOYW1lXSA9IFwiXCI7XG4gICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIG5vZGVbcHJvcE5hbWVdID0gbnVsbDtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIGlmIChwcmV2aW91c1ZhbHVlLnVuaG9vaykge1xuICAgICAgICAgICAgICAgICAgICAgICAgcHJldmlvdXNWYWx1ZS51bmhvb2sobm9kZSwgcHJvcE5hbWUsIHByb3BWYWx1ZSk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIHBhdGNoT2JqZWN0KG5vZGUsIHByb3BzLCBwcmV2aW91cywgcHJvcE5hbWUsIHByb3BWYWx1ZSkge1xuICAgICAgICAgICAgICAgIHZhciBwcmV2aW91c1ZhbHVlID0gcHJldmlvdXMgPyBwcmV2aW91c1twcm9wTmFtZV0gOiB1bmRlZmluZWQ7XG5cbiAgICAgICAgICAgICAgICAvLyBTZXQgYXR0cmlidXRlc1xuICAgICAgICAgICAgICAgIGlmIChwcm9wTmFtZSA9PT0gXCJhdHRyaWJ1dGVzXCIpIHtcbiAgICAgICAgICAgICAgICAgICAgZm9yICh2YXIgYXR0ck5hbWUgaW4gcHJvcFZhbHVlKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICB2YXIgYXR0clZhbHVlID0gcHJvcFZhbHVlW2F0dHJOYW1lXTtcblxuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGF0dHJWYWx1ZSA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgbm9kZS5yZW1vdmVBdHRyaWJ1dGUoYXR0ck5hbWUpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBub2RlLnNldEF0dHJpYnV0ZShhdHRyTmFtZSwgYXR0clZhbHVlKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICBpZiAocHJldmlvdXNWYWx1ZSAmJiBpc09iamVjdChwcmV2aW91c1ZhbHVlKSAmJiBnZXRQcm90b3R5cGUocHJldmlvdXNWYWx1ZSkgIT09IGdldFByb3RvdHlwZShwcm9wVmFsdWUpKSB7XG4gICAgICAgICAgICAgICAgICAgIG5vZGVbcHJvcE5hbWVdID0gcHJvcFZhbHVlO1xuICAgICAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgaWYgKCFpc09iamVjdChub2RlW3Byb3BOYW1lXSkpIHtcbiAgICAgICAgICAgICAgICAgICAgbm9kZVtwcm9wTmFtZV0gPSB7fTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICB2YXIgcmVwbGFjZXIgPSBwcm9wTmFtZSA9PT0gXCJzdHlsZVwiID8gXCJcIiA6IHVuZGVmaW5lZDtcblxuICAgICAgICAgICAgICAgIGZvciAodmFyIGsgaW4gcHJvcFZhbHVlKSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciB2YWx1ZSA9IHByb3BWYWx1ZVtrXTtcbiAgICAgICAgICAgICAgICAgICAgbm9kZVtwcm9wTmFtZV1ba10gPSB2YWx1ZSA9PT0gdW5kZWZpbmVkID8gcmVwbGFjZXIgOiB2YWx1ZTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIGdldFByb3RvdHlwZSh2YWx1ZSkge1xuICAgICAgICAgICAgICAgIGlmIChPYmplY3QuZ2V0UHJvdG90eXBlT2YpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIE9iamVjdC5nZXRQcm90b3R5cGVPZih2YWx1ZSk7XG4gICAgICAgICAgICAgICAgfSBlbHNlIGlmICh2YWx1ZS5fX3Byb3RvX18pIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHZhbHVlLl9fcHJvdG9fXztcbiAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKHZhbHVlLmNvbnN0cnVjdG9yKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiB2YWx1ZS5jb25zdHJ1Y3Rvci5wcm90b3R5cGU7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9LCB7IFwiLi4vdm5vZGUvaXMtdmhvb2suanNcIjogMjYsIFwiaXMtb2JqZWN0XCI6IDExIH1dLCAxNTogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHtcbiAgICAgICAgICAgIHZhciBkb2N1bWVudCA9IHJlcXVpcmUoXCJnbG9iYWwvZG9jdW1lbnRcIik7XG5cbiAgICAgICAgICAgIHZhciBhcHBseVByb3BlcnRpZXMgPSByZXF1aXJlKFwiLi9hcHBseS1wcm9wZXJ0aWVzXCIpO1xuXG4gICAgICAgICAgICB2YXIgaXNWTm9kZSA9IHJlcXVpcmUoXCIuLi92bm9kZS9pcy12bm9kZS5qc1wiKTtcbiAgICAgICAgICAgIHZhciBpc1ZUZXh0ID0gcmVxdWlyZShcIi4uL3Zub2RlL2lzLXZ0ZXh0LmpzXCIpO1xuICAgICAgICAgICAgdmFyIGlzV2lkZ2V0ID0gcmVxdWlyZShcIi4uL3Zub2RlL2lzLXdpZGdldC5qc1wiKTtcbiAgICAgICAgICAgIHZhciBoYW5kbGVUaHVuayA9IHJlcXVpcmUoXCIuLi92bm9kZS9oYW5kbGUtdGh1bmsuanNcIik7XG5cbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gY3JlYXRlRWxlbWVudDtcblxuICAgICAgICAgICAgZnVuY3Rpb24gY3JlYXRlRWxlbWVudCh2bm9kZSwgb3B0cykge1xuICAgICAgICAgICAgICAgIHZhciBkb2MgPSBvcHRzID8gb3B0cy5kb2N1bWVudCB8fCBkb2N1bWVudCA6IGRvY3VtZW50O1xuICAgICAgICAgICAgICAgIHZhciB3YXJuID0gb3B0cyA/IG9wdHMud2FybiA6IG51bGw7XG5cbiAgICAgICAgICAgICAgICB2bm9kZSA9IGhhbmRsZVRodW5rKHZub2RlKS5hO1xuXG4gICAgICAgICAgICAgICAgaWYgKGlzV2lkZ2V0KHZub2RlKSkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gdm5vZGUuaW5pdCgpO1xuICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoaXNWVGV4dCh2bm9kZSkpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGRvYy5jcmVhdGVUZXh0Tm9kZSh2bm9kZS50ZXh0KTtcbiAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKCFpc1ZOb2RlKHZub2RlKSkge1xuICAgICAgICAgICAgICAgICAgICBpZiAod2Fybikge1xuICAgICAgICAgICAgICAgICAgICAgICAgd2FybihcIkl0ZW0gaXMgbm90IGEgdmFsaWQgdmlydHVhbCBkb20gbm9kZVwiLCB2bm9kZSk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIG51bGw7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgdmFyIG5vZGUgPSB2bm9kZS5uYW1lc3BhY2UgPT09IG51bGwgPyBkb2MuY3JlYXRlRWxlbWVudCh2bm9kZS50YWdOYW1lKSA6IGRvYy5jcmVhdGVFbGVtZW50TlModm5vZGUubmFtZXNwYWNlLCB2bm9kZS50YWdOYW1lKTtcblxuICAgICAgICAgICAgICAgIHZhciBwcm9wcyA9IHZub2RlLnByb3BlcnRpZXM7XG4gICAgICAgICAgICAgICAgYXBwbHlQcm9wZXJ0aWVzKG5vZGUsIHByb3BzKTtcblxuICAgICAgICAgICAgICAgIHZhciBjaGlsZHJlbiA9IHZub2RlLmNoaWxkcmVuO1xuXG4gICAgICAgICAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCBjaGlsZHJlbi5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgICAgICAgICB2YXIgY2hpbGROb2RlID0gY3JlYXRlRWxlbWVudChjaGlsZHJlbltpXSwgb3B0cyk7XG4gICAgICAgICAgICAgICAgICAgIGlmIChjaGlsZE5vZGUpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIG5vZGUuYXBwZW5kQ2hpbGQoY2hpbGROb2RlKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHJldHVybiBub2RlO1xuICAgICAgICAgICAgfVxuICAgICAgICB9LCB7IFwiLi4vdm5vZGUvaGFuZGxlLXRodW5rLmpzXCI6IDI0LCBcIi4uL3Zub2RlL2lzLXZub2RlLmpzXCI6IDI3LCBcIi4uL3Zub2RlL2lzLXZ0ZXh0LmpzXCI6IDI4LCBcIi4uL3Zub2RlL2lzLXdpZGdldC5qc1wiOiAyOSwgXCIuL2FwcGx5LXByb3BlcnRpZXNcIjogMTQsIFwiZ2xvYmFsL2RvY3VtZW50XCI6IDEwIH1dLCAxNjogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHtcbiAgICAgICAgICAgIC8vIE1hcHMgYSB2aXJ0dWFsIERPTSB0cmVlIG9udG8gYSByZWFsIERPTSB0cmVlIGluIGFuIGVmZmljaWVudCBtYW5uZXIuXG4gICAgICAgICAgICAvLyBXZSBkb24ndCB3YW50IHRvIHJlYWQgYWxsIG9mIHRoZSBET00gbm9kZXMgaW4gdGhlIHRyZWUgc28gd2UgdXNlXG4gICAgICAgICAgICAvLyB0aGUgaW4tb3JkZXIgdHJlZSBpbmRleGluZyB0byBlbGltaW5hdGUgcmVjdXJzaW9uIGRvd24gY2VydGFpbiBicmFuY2hlcy5cbiAgICAgICAgICAgIC8vIFdlIG9ubHkgcmVjdXJzZSBpbnRvIGEgRE9NIG5vZGUgaWYgd2Uga25vdyB0aGF0IGl0IGNvbnRhaW5zIGEgY2hpbGQgb2ZcbiAgICAgICAgICAgIC8vIGludGVyZXN0LlxuXG4gICAgICAgICAgICB2YXIgbm9DaGlsZCA9IHt9O1xuXG4gICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IGRvbUluZGV4O1xuXG4gICAgICAgICAgICBmdW5jdGlvbiBkb21JbmRleChyb290Tm9kZSwgdHJlZSwgaW5kaWNlcywgbm9kZXMpIHtcbiAgICAgICAgICAgICAgICBpZiAoIWluZGljZXMgfHwgaW5kaWNlcy5sZW5ndGggPT09IDApIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHt9O1xuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIGluZGljZXMuc29ydChhc2NlbmRpbmcpO1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gcmVjdXJzZShyb290Tm9kZSwgdHJlZSwgaW5kaWNlcywgbm9kZXMsIDApO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZnVuY3Rpb24gcmVjdXJzZShyb290Tm9kZSwgdHJlZSwgaW5kaWNlcywgbm9kZXMsIHJvb3RJbmRleCkge1xuICAgICAgICAgICAgICAgIG5vZGVzID0gbm9kZXMgfHwge307XG5cbiAgICAgICAgICAgICAgICBpZiAocm9vdE5vZGUpIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKGluZGV4SW5SYW5nZShpbmRpY2VzLCByb290SW5kZXgsIHJvb3RJbmRleCkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIG5vZGVzW3Jvb3RJbmRleF0gPSByb290Tm9kZTtcbiAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgIHZhciB2Q2hpbGRyZW4gPSB0cmVlLmNoaWxkcmVuO1xuXG4gICAgICAgICAgICAgICAgICAgIGlmICh2Q2hpbGRyZW4pIHtcblxuICAgICAgICAgICAgICAgICAgICAgICAgdmFyIGNoaWxkTm9kZXMgPSByb290Tm9kZS5jaGlsZE5vZGVzO1xuXG4gICAgICAgICAgICAgICAgICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IHRyZWUuY2hpbGRyZW4ubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICByb290SW5kZXggKz0gMTtcblxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZhciB2Q2hpbGQgPSB2Q2hpbGRyZW5baV0gfHwgbm9DaGlsZDtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB2YXIgbmV4dEluZGV4ID0gcm9vdEluZGV4ICsgKHZDaGlsZC5jb3VudCB8fCAwKTtcblxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIHNraXAgcmVjdXJzaW9uIGRvd24gdGhlIHRyZWUgaWYgdGhlcmUgYXJlIG5vIG5vZGVzIGRvd24gaGVyZVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChpbmRleEluUmFuZ2UoaW5kaWNlcywgcm9vdEluZGV4LCBuZXh0SW5kZXgpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlY3Vyc2UoY2hpbGROb2Rlc1tpXSwgdkNoaWxkLCBpbmRpY2VzLCBub2Rlcywgcm9vdEluZGV4KTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICByb290SW5kZXggPSBuZXh0SW5kZXg7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICByZXR1cm4gbm9kZXM7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIC8vIEJpbmFyeSBzZWFyY2ggZm9yIGFuIGluZGV4IGluIHRoZSBpbnRlcnZhbCBbbGVmdCwgcmlnaHRdXG4gICAgICAgICAgICBmdW5jdGlvbiBpbmRleEluUmFuZ2UoaW5kaWNlcywgbGVmdCwgcmlnaHQpIHtcbiAgICAgICAgICAgICAgICBpZiAoaW5kaWNlcy5sZW5ndGggPT09IDApIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHZhciBtaW5JbmRleCA9IDA7XG4gICAgICAgICAgICAgICAgdmFyIG1heEluZGV4ID0gaW5kaWNlcy5sZW5ndGggLSAxO1xuICAgICAgICAgICAgICAgIHZhciBjdXJyZW50SW5kZXg7XG4gICAgICAgICAgICAgICAgdmFyIGN1cnJlbnRJdGVtO1xuXG4gICAgICAgICAgICAgICAgd2hpbGUgKG1pbkluZGV4IDw9IG1heEluZGV4KSB7XG4gICAgICAgICAgICAgICAgICAgIGN1cnJlbnRJbmRleCA9IChtYXhJbmRleCArIG1pbkluZGV4KSAvIDIgPj4gMDtcbiAgICAgICAgICAgICAgICAgICAgY3VycmVudEl0ZW0gPSBpbmRpY2VzW2N1cnJlbnRJbmRleF07XG5cbiAgICAgICAgICAgICAgICAgICAgaWYgKG1pbkluZGV4ID09PSBtYXhJbmRleCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGN1cnJlbnRJdGVtID49IGxlZnQgJiYgY3VycmVudEl0ZW0gPD0gcmlnaHQ7XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoY3VycmVudEl0ZW0gPCBsZWZ0KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBtaW5JbmRleCA9IGN1cnJlbnRJbmRleCArIDE7XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoY3VycmVudEl0ZW0gPiByaWdodCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgbWF4SW5kZXggPSBjdXJyZW50SW5kZXggLSAxO1xuICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIGFzY2VuZGluZyhhLCBiKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGEgPiBiID8gMSA6IC0xO1xuICAgICAgICAgICAgfVxuICAgICAgICB9LCB7fV0sIDE3OiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge1xuICAgICAgICAgICAgdmFyIGFwcGx5UHJvcGVydGllcyA9IHJlcXVpcmUoXCIuL2FwcGx5LXByb3BlcnRpZXNcIik7XG5cbiAgICAgICAgICAgIHZhciBpc1dpZGdldCA9IHJlcXVpcmUoXCIuLi92bm9kZS9pcy13aWRnZXQuanNcIik7XG4gICAgICAgICAgICB2YXIgVlBhdGNoID0gcmVxdWlyZShcIi4uL3Zub2RlL3ZwYXRjaC5qc1wiKTtcblxuICAgICAgICAgICAgdmFyIHVwZGF0ZVdpZGdldCA9IHJlcXVpcmUoXCIuL3VwZGF0ZS13aWRnZXRcIik7XG5cbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gYXBwbHlQYXRjaDtcblxuICAgICAgICAgICAgZnVuY3Rpb24gYXBwbHlQYXRjaCh2cGF0Y2gsIGRvbU5vZGUsIHJlbmRlck9wdGlvbnMpIHtcbiAgICAgICAgICAgICAgICB2YXIgdHlwZSA9IHZwYXRjaC50eXBlO1xuICAgICAgICAgICAgICAgIHZhciB2Tm9kZSA9IHZwYXRjaC52Tm9kZTtcbiAgICAgICAgICAgICAgICB2YXIgcGF0Y2ggPSB2cGF0Y2gucGF0Y2g7XG5cbiAgICAgICAgICAgICAgICBzd2l0Y2ggKHR5cGUpIHtcbiAgICAgICAgICAgICAgICAgICAgY2FzZSBWUGF0Y2guUkVNT1ZFOlxuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHJlbW92ZU5vZGUoZG9tTm9kZSwgdk5vZGUpO1xuICAgICAgICAgICAgICAgICAgICBjYXNlIFZQYXRjaC5JTlNFUlQ6XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gaW5zZXJ0Tm9kZShkb21Ob2RlLCBwYXRjaCwgcmVuZGVyT3B0aW9ucyk7XG4gICAgICAgICAgICAgICAgICAgIGNhc2UgVlBhdGNoLlZURVhUOlxuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHN0cmluZ1BhdGNoKGRvbU5vZGUsIHZOb2RlLCBwYXRjaCwgcmVuZGVyT3B0aW9ucyk7XG4gICAgICAgICAgICAgICAgICAgIGNhc2UgVlBhdGNoLldJREdFVDpcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiB3aWRnZXRQYXRjaChkb21Ob2RlLCB2Tm9kZSwgcGF0Y2gsIHJlbmRlck9wdGlvbnMpO1xuICAgICAgICAgICAgICAgICAgICBjYXNlIFZQYXRjaC5WTk9ERTpcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiB2Tm9kZVBhdGNoKGRvbU5vZGUsIHZOb2RlLCBwYXRjaCwgcmVuZGVyT3B0aW9ucyk7XG4gICAgICAgICAgICAgICAgICAgIGNhc2UgVlBhdGNoLk9SREVSOlxuICAgICAgICAgICAgICAgICAgICAgICAgcmVvcmRlckNoaWxkcmVuKGRvbU5vZGUsIHBhdGNoKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBkb21Ob2RlO1xuICAgICAgICAgICAgICAgICAgICBjYXNlIFZQYXRjaC5QUk9QUzpcbiAgICAgICAgICAgICAgICAgICAgICAgIGFwcGx5UHJvcGVydGllcyhkb21Ob2RlLCBwYXRjaCwgdk5vZGUucHJvcGVydGllcyk7XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gZG9tTm9kZTtcbiAgICAgICAgICAgICAgICAgICAgY2FzZSBWUGF0Y2guVEhVTks6XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gcmVwbGFjZVJvb3QoZG9tTm9kZSwgcmVuZGVyT3B0aW9ucy5wYXRjaChkb21Ob2RlLCBwYXRjaCwgcmVuZGVyT3B0aW9ucykpO1xuICAgICAgICAgICAgICAgICAgICBkZWZhdWx0OlxuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGRvbU5vZGU7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBmdW5jdGlvbiByZW1vdmVOb2RlKGRvbU5vZGUsIHZOb2RlKSB7XG4gICAgICAgICAgICAgICAgdmFyIHBhcmVudE5vZGUgPSBkb21Ob2RlLnBhcmVudE5vZGU7XG5cbiAgICAgICAgICAgICAgICBpZiAocGFyZW50Tm9kZSkge1xuICAgICAgICAgICAgICAgICAgICBwYXJlbnROb2RlLnJlbW92ZUNoaWxkKGRvbU5vZGUpO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIGRlc3Ryb3lXaWRnZXQoZG9tTm9kZSwgdk5vZGUpO1xuXG4gICAgICAgICAgICAgICAgcmV0dXJuIG51bGw7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIGluc2VydE5vZGUocGFyZW50Tm9kZSwgdk5vZGUsIHJlbmRlck9wdGlvbnMpIHtcbiAgICAgICAgICAgICAgICB2YXIgbmV3Tm9kZSA9IHJlbmRlck9wdGlvbnMucmVuZGVyKHZOb2RlLCByZW5kZXJPcHRpb25zKTtcblxuICAgICAgICAgICAgICAgIGlmIChwYXJlbnROb2RlKSB7XG4gICAgICAgICAgICAgICAgICAgIHBhcmVudE5vZGUuYXBwZW5kQ2hpbGQobmV3Tm9kZSk7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgcmV0dXJuIHBhcmVudE5vZGU7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIHN0cmluZ1BhdGNoKGRvbU5vZGUsIGxlZnRWTm9kZSwgdlRleHQsIHJlbmRlck9wdGlvbnMpIHtcbiAgICAgICAgICAgICAgICB2YXIgbmV3Tm9kZTtcblxuICAgICAgICAgICAgICAgIGlmIChkb21Ob2RlLm5vZGVUeXBlID09PSAzKSB7XG4gICAgICAgICAgICAgICAgICAgIGRvbU5vZGUucmVwbGFjZURhdGEoMCwgZG9tTm9kZS5sZW5ndGgsIHZUZXh0LnRleHQpO1xuICAgICAgICAgICAgICAgICAgICBuZXdOb2RlID0gZG9tTm9kZTtcbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICB2YXIgcGFyZW50Tm9kZSA9IGRvbU5vZGUucGFyZW50Tm9kZTtcbiAgICAgICAgICAgICAgICAgICAgbmV3Tm9kZSA9IHJlbmRlck9wdGlvbnMucmVuZGVyKHZUZXh0LCByZW5kZXJPcHRpb25zKTtcblxuICAgICAgICAgICAgICAgICAgICBpZiAocGFyZW50Tm9kZSAmJiBuZXdOb2RlICE9PSBkb21Ob2RlKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBwYXJlbnROb2RlLnJlcGxhY2VDaGlsZChuZXdOb2RlLCBkb21Ob2RlKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHJldHVybiBuZXdOb2RlO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBmdW5jdGlvbiB3aWRnZXRQYXRjaChkb21Ob2RlLCBsZWZ0Vk5vZGUsIHdpZGdldCwgcmVuZGVyT3B0aW9ucykge1xuICAgICAgICAgICAgICAgIHZhciB1cGRhdGluZyA9IHVwZGF0ZVdpZGdldChsZWZ0Vk5vZGUsIHdpZGdldCk7XG4gICAgICAgICAgICAgICAgdmFyIG5ld05vZGU7XG5cbiAgICAgICAgICAgICAgICBpZiAodXBkYXRpbmcpIHtcbiAgICAgICAgICAgICAgICAgICAgbmV3Tm9kZSA9IHdpZGdldC51cGRhdGUobGVmdFZOb2RlLCBkb21Ob2RlKSB8fCBkb21Ob2RlO1xuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIG5ld05vZGUgPSByZW5kZXJPcHRpb25zLnJlbmRlcih3aWRnZXQsIHJlbmRlck9wdGlvbnMpO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHZhciBwYXJlbnROb2RlID0gZG9tTm9kZS5wYXJlbnROb2RlO1xuXG4gICAgICAgICAgICAgICAgaWYgKHBhcmVudE5vZGUgJiYgbmV3Tm9kZSAhPT0gZG9tTm9kZSkge1xuICAgICAgICAgICAgICAgICAgICBwYXJlbnROb2RlLnJlcGxhY2VDaGlsZChuZXdOb2RlLCBkb21Ob2RlKTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICBpZiAoIXVwZGF0aW5nKSB7XG4gICAgICAgICAgICAgICAgICAgIGRlc3Ryb3lXaWRnZXQoZG9tTm9kZSwgbGVmdFZOb2RlKTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICByZXR1cm4gbmV3Tm9kZTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZnVuY3Rpb24gdk5vZGVQYXRjaChkb21Ob2RlLCBsZWZ0Vk5vZGUsIHZOb2RlLCByZW5kZXJPcHRpb25zKSB7XG4gICAgICAgICAgICAgICAgdmFyIHBhcmVudE5vZGUgPSBkb21Ob2RlLnBhcmVudE5vZGU7XG4gICAgICAgICAgICAgICAgdmFyIG5ld05vZGUgPSByZW5kZXJPcHRpb25zLnJlbmRlcih2Tm9kZSwgcmVuZGVyT3B0aW9ucyk7XG5cbiAgICAgICAgICAgICAgICBpZiAocGFyZW50Tm9kZSAmJiBuZXdOb2RlICE9PSBkb21Ob2RlKSB7XG4gICAgICAgICAgICAgICAgICAgIHBhcmVudE5vZGUucmVwbGFjZUNoaWxkKG5ld05vZGUsIGRvbU5vZGUpO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHJldHVybiBuZXdOb2RlO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBmdW5jdGlvbiBkZXN0cm95V2lkZ2V0KGRvbU5vZGUsIHcpIHtcbiAgICAgICAgICAgICAgICBpZiAodHlwZW9mIHcuZGVzdHJveSA9PT0gXCJmdW5jdGlvblwiICYmIGlzV2lkZ2V0KHcpKSB7XG4gICAgICAgICAgICAgICAgICAgIHcuZGVzdHJveShkb21Ob2RlKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIHJlb3JkZXJDaGlsZHJlbihkb21Ob2RlLCBtb3Zlcykge1xuICAgICAgICAgICAgICAgIHZhciBjaGlsZE5vZGVzID0gZG9tTm9kZS5jaGlsZE5vZGVzO1xuICAgICAgICAgICAgICAgIHZhciBrZXlNYXAgPSB7fTtcbiAgICAgICAgICAgICAgICB2YXIgbm9kZTtcbiAgICAgICAgICAgICAgICB2YXIgcmVtb3ZlO1xuICAgICAgICAgICAgICAgIHZhciBpbnNlcnQ7XG5cbiAgICAgICAgICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IG1vdmVzLnJlbW92ZXMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgICAgICAgICAgcmVtb3ZlID0gbW92ZXMucmVtb3Zlc1tpXTtcbiAgICAgICAgICAgICAgICAgICAgbm9kZSA9IGNoaWxkTm9kZXNbcmVtb3ZlLmZyb21dO1xuICAgICAgICAgICAgICAgICAgICBpZiAocmVtb3ZlLmtleSkge1xuICAgICAgICAgICAgICAgICAgICAgICAga2V5TWFwW3JlbW92ZS5rZXldID0gbm9kZTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICBkb21Ob2RlLnJlbW92ZUNoaWxkKG5vZGUpO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHZhciBsZW5ndGggPSBjaGlsZE5vZGVzLmxlbmd0aDtcbiAgICAgICAgICAgICAgICBmb3IgKHZhciBqID0gMDsgaiA8IG1vdmVzLmluc2VydHMubGVuZ3RoOyBqKyspIHtcbiAgICAgICAgICAgICAgICAgICAgaW5zZXJ0ID0gbW92ZXMuaW5zZXJ0c1tqXTtcbiAgICAgICAgICAgICAgICAgICAgbm9kZSA9IGtleU1hcFtpbnNlcnQua2V5XTtcbiAgICAgICAgICAgICAgICAgICAgLy8gdGhpcyBpcyB0aGUgd2VpcmRlc3QgYnVnIGkndmUgZXZlciBzZWVuIGluIHdlYmtpdFxuICAgICAgICAgICAgICAgICAgICBkb21Ob2RlLmluc2VydEJlZm9yZShub2RlLCBpbnNlcnQudG8gPj0gbGVuZ3RoKysgPyBudWxsIDogY2hpbGROb2Rlc1tpbnNlcnQudG9dKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIHJlcGxhY2VSb290KG9sZFJvb3QsIG5ld1Jvb3QpIHtcbiAgICAgICAgICAgICAgICBpZiAob2xkUm9vdCAmJiBuZXdSb290ICYmIG9sZFJvb3QgIT09IG5ld1Jvb3QgJiYgb2xkUm9vdC5wYXJlbnROb2RlKSB7XG4gICAgICAgICAgICAgICAgICAgIG9sZFJvb3QucGFyZW50Tm9kZS5yZXBsYWNlQ2hpbGQobmV3Um9vdCwgb2xkUm9vdCk7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgcmV0dXJuIG5ld1Jvb3Q7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0sIHsgXCIuLi92bm9kZS9pcy13aWRnZXQuanNcIjogMjksIFwiLi4vdm5vZGUvdnBhdGNoLmpzXCI6IDMyLCBcIi4vYXBwbHktcHJvcGVydGllc1wiOiAxNCwgXCIuL3VwZGF0ZS13aWRnZXRcIjogMTkgfV0sIDE4OiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge1xuICAgICAgICAgICAgdmFyIGRvY3VtZW50ID0gcmVxdWlyZShcImdsb2JhbC9kb2N1bWVudFwiKTtcbiAgICAgICAgICAgIHZhciBpc0FycmF5ID0gcmVxdWlyZShcIngtaXMtYXJyYXlcIik7XG5cbiAgICAgICAgICAgIHZhciByZW5kZXIgPSByZXF1aXJlKFwiLi9jcmVhdGUtZWxlbWVudFwiKTtcbiAgICAgICAgICAgIHZhciBkb21JbmRleCA9IHJlcXVpcmUoXCIuL2RvbS1pbmRleFwiKTtcbiAgICAgICAgICAgIHZhciBwYXRjaE9wID0gcmVxdWlyZShcIi4vcGF0Y2gtb3BcIik7XG4gICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IHBhdGNoO1xuXG4gICAgICAgICAgICBmdW5jdGlvbiBwYXRjaChyb290Tm9kZSwgcGF0Y2hlcywgcmVuZGVyT3B0aW9ucykge1xuICAgICAgICAgICAgICAgIHJlbmRlck9wdGlvbnMgPSByZW5kZXJPcHRpb25zIHx8IHt9O1xuICAgICAgICAgICAgICAgIHJlbmRlck9wdGlvbnMucGF0Y2ggPSByZW5kZXJPcHRpb25zLnBhdGNoICYmIHJlbmRlck9wdGlvbnMucGF0Y2ggIT09IHBhdGNoID8gcmVuZGVyT3B0aW9ucy5wYXRjaCA6IHBhdGNoUmVjdXJzaXZlO1xuICAgICAgICAgICAgICAgIHJlbmRlck9wdGlvbnMucmVuZGVyID0gcmVuZGVyT3B0aW9ucy5yZW5kZXIgfHwgcmVuZGVyO1xuXG4gICAgICAgICAgICAgICAgcmV0dXJuIHJlbmRlck9wdGlvbnMucGF0Y2gocm9vdE5vZGUsIHBhdGNoZXMsIHJlbmRlck9wdGlvbnMpO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBmdW5jdGlvbiBwYXRjaFJlY3Vyc2l2ZShyb290Tm9kZSwgcGF0Y2hlcywgcmVuZGVyT3B0aW9ucykge1xuICAgICAgICAgICAgICAgIHZhciBpbmRpY2VzID0gcGF0Y2hJbmRpY2VzKHBhdGNoZXMpO1xuXG4gICAgICAgICAgICAgICAgaWYgKGluZGljZXMubGVuZ3RoID09PSAwKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiByb290Tm9kZTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICB2YXIgaW5kZXggPSBkb21JbmRleChyb290Tm9kZSwgcGF0Y2hlcy5hLCBpbmRpY2VzKTtcbiAgICAgICAgICAgICAgICB2YXIgb3duZXJEb2N1bWVudCA9IHJvb3ROb2RlLm93bmVyRG9jdW1lbnQ7XG5cbiAgICAgICAgICAgICAgICBpZiAoIXJlbmRlck9wdGlvbnMuZG9jdW1lbnQgJiYgb3duZXJEb2N1bWVudCAhPT0gZG9jdW1lbnQpIHtcbiAgICAgICAgICAgICAgICAgICAgcmVuZGVyT3B0aW9ucy5kb2N1bWVudCA9IG93bmVyRG9jdW1lbnQ7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCBpbmRpY2VzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciBub2RlSW5kZXggPSBpbmRpY2VzW2ldO1xuICAgICAgICAgICAgICAgICAgICByb290Tm9kZSA9IGFwcGx5UGF0Y2gocm9vdE5vZGUsIGluZGV4W25vZGVJbmRleF0sIHBhdGNoZXNbbm9kZUluZGV4XSwgcmVuZGVyT3B0aW9ucyk7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgcmV0dXJuIHJvb3ROb2RlO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBmdW5jdGlvbiBhcHBseVBhdGNoKHJvb3ROb2RlLCBkb21Ob2RlLCBwYXRjaExpc3QsIHJlbmRlck9wdGlvbnMpIHtcbiAgICAgICAgICAgICAgICBpZiAoIWRvbU5vZGUpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHJvb3ROb2RlO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHZhciBuZXdOb2RlO1xuXG4gICAgICAgICAgICAgICAgaWYgKGlzQXJyYXkocGF0Y2hMaXN0KSkge1xuICAgICAgICAgICAgICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IHBhdGNoTGlzdC5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgICAgICAgICAgICAgbmV3Tm9kZSA9IHBhdGNoT3AocGF0Y2hMaXN0W2ldLCBkb21Ob2RlLCByZW5kZXJPcHRpb25zKTtcblxuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGRvbU5vZGUgPT09IHJvb3ROb2RlKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcm9vdE5vZGUgPSBuZXdOb2RlO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgbmV3Tm9kZSA9IHBhdGNoT3AocGF0Y2hMaXN0LCBkb21Ob2RlLCByZW5kZXJPcHRpb25zKTtcblxuICAgICAgICAgICAgICAgICAgICBpZiAoZG9tTm9kZSA9PT0gcm9vdE5vZGUpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJvb3ROb2RlID0gbmV3Tm9kZTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHJldHVybiByb290Tm9kZTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZnVuY3Rpb24gcGF0Y2hJbmRpY2VzKHBhdGNoZXMpIHtcbiAgICAgICAgICAgICAgICB2YXIgaW5kaWNlcyA9IFtdO1xuXG4gICAgICAgICAgICAgICAgZm9yICh2YXIga2V5IGluIHBhdGNoZXMpIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKGtleSAhPT0gXCJhXCIpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGluZGljZXMucHVzaChOdW1iZXIoa2V5KSk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICByZXR1cm4gaW5kaWNlcztcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSwgeyBcIi4vY3JlYXRlLWVsZW1lbnRcIjogMTUsIFwiLi9kb20taW5kZXhcIjogMTYsIFwiLi9wYXRjaC1vcFwiOiAxNywgXCJnbG9iYWwvZG9jdW1lbnRcIjogMTAsIFwieC1pcy1hcnJheVwiOiAxMiB9XSwgMTk6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICB2YXIgaXNXaWRnZXQgPSByZXF1aXJlKFwiLi4vdm5vZGUvaXMtd2lkZ2V0LmpzXCIpO1xuXG4gICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IHVwZGF0ZVdpZGdldDtcblxuICAgICAgICAgICAgZnVuY3Rpb24gdXBkYXRlV2lkZ2V0KGEsIGIpIHtcbiAgICAgICAgICAgICAgICBpZiAoaXNXaWRnZXQoYSkgJiYgaXNXaWRnZXQoYikpIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKFwibmFtZVwiIGluIGEgJiYgXCJuYW1lXCIgaW4gYikge1xuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGEuaWQgPT09IGIuaWQ7XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gYS5pbml0ID09PSBiLmluaXQ7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0sIHsgXCIuLi92bm9kZS9pcy13aWRnZXQuanNcIjogMjkgfV0sIDIwOiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge1xuICAgICAgICAgICAgXCJ1c2Ugc3RyaWN0XCI7XG5cbiAgICAgICAgICAgIHZhciBFdlN0b3JlID0gcmVxdWlyZShcImV2LXN0b3JlXCIpO1xuXG4gICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IEV2SG9vaztcblxuICAgICAgICAgICAgZnVuY3Rpb24gRXZIb29rKHZhbHVlKSB7XG4gICAgICAgICAgICAgICAgaWYgKCEodGhpcyBpbnN0YW5jZW9mIEV2SG9vaykpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIG5ldyBFdkhvb2sodmFsdWUpO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHRoaXMudmFsdWUgPSB2YWx1ZTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgRXZIb29rLnByb3RvdHlwZS5ob29rID0gZnVuY3Rpb24gKG5vZGUsIHByb3BlcnR5TmFtZSkge1xuICAgICAgICAgICAgICAgIHZhciBlcyA9IEV2U3RvcmUobm9kZSk7XG4gICAgICAgICAgICAgICAgdmFyIHByb3BOYW1lID0gcHJvcGVydHlOYW1lLnN1YnN0cigzKTtcblxuICAgICAgICAgICAgICAgIGVzW3Byb3BOYW1lXSA9IHRoaXMudmFsdWU7XG4gICAgICAgICAgICB9O1xuXG4gICAgICAgICAgICBFdkhvb2sucHJvdG90eXBlLnVuaG9vayA9IGZ1bmN0aW9uIChub2RlLCBwcm9wZXJ0eU5hbWUpIHtcbiAgICAgICAgICAgICAgICB2YXIgZXMgPSBFdlN0b3JlKG5vZGUpO1xuICAgICAgICAgICAgICAgIHZhciBwcm9wTmFtZSA9IHByb3BlcnR5TmFtZS5zdWJzdHIoMyk7XG5cbiAgICAgICAgICAgICAgICBlc1twcm9wTmFtZV0gPSB1bmRlZmluZWQ7XG4gICAgICAgICAgICB9O1xuICAgICAgICB9LCB7IFwiZXYtc3RvcmVcIjogNyB9XSwgMjE6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICBcInVzZSBzdHJpY3RcIjtcblxuICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBTb2Z0U2V0SG9vaztcblxuICAgICAgICAgICAgZnVuY3Rpb24gU29mdFNldEhvb2sodmFsdWUpIHtcbiAgICAgICAgICAgICAgICBpZiAoISh0aGlzIGluc3RhbmNlb2YgU29mdFNldEhvb2spKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBuZXcgU29mdFNldEhvb2sodmFsdWUpO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHRoaXMudmFsdWUgPSB2YWx1ZTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgU29mdFNldEhvb2sucHJvdG90eXBlLmhvb2sgPSBmdW5jdGlvbiAobm9kZSwgcHJvcGVydHlOYW1lKSB7XG4gICAgICAgICAgICAgICAgaWYgKG5vZGVbcHJvcGVydHlOYW1lXSAhPT0gdGhpcy52YWx1ZSkge1xuICAgICAgICAgICAgICAgICAgICBub2RlW3Byb3BlcnR5TmFtZV0gPSB0aGlzLnZhbHVlO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH07XG4gICAgICAgIH0sIHt9XSwgMjI6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICBcInVzZSBzdHJpY3RcIjtcblxuICAgICAgICAgICAgdmFyIGlzQXJyYXkgPSByZXF1aXJlKFwieC1pcy1hcnJheVwiKTtcblxuICAgICAgICAgICAgdmFyIFZOb2RlID0gcmVxdWlyZShcIi4uL3Zub2RlL3Zub2RlLmpzXCIpO1xuICAgICAgICAgICAgdmFyIFZUZXh0ID0gcmVxdWlyZShcIi4uL3Zub2RlL3Z0ZXh0LmpzXCIpO1xuICAgICAgICAgICAgdmFyIGlzVk5vZGUgPSByZXF1aXJlKFwiLi4vdm5vZGUvaXMtdm5vZGVcIik7XG4gICAgICAgICAgICB2YXIgaXNWVGV4dCA9IHJlcXVpcmUoXCIuLi92bm9kZS9pcy12dGV4dFwiKTtcbiAgICAgICAgICAgIHZhciBpc1dpZGdldCA9IHJlcXVpcmUoXCIuLi92bm9kZS9pcy13aWRnZXRcIik7XG4gICAgICAgICAgICB2YXIgaXNIb29rID0gcmVxdWlyZShcIi4uL3Zub2RlL2lzLXZob29rXCIpO1xuICAgICAgICAgICAgdmFyIGlzVlRodW5rID0gcmVxdWlyZShcIi4uL3Zub2RlL2lzLXRodW5rXCIpO1xuXG4gICAgICAgICAgICB2YXIgcGFyc2VUYWcgPSByZXF1aXJlKFwiLi9wYXJzZS10YWcuanNcIik7XG4gICAgICAgICAgICB2YXIgc29mdFNldEhvb2sgPSByZXF1aXJlKFwiLi9ob29rcy9zb2Z0LXNldC1ob29rLmpzXCIpO1xuICAgICAgICAgICAgdmFyIGV2SG9vayA9IHJlcXVpcmUoXCIuL2hvb2tzL2V2LWhvb2suanNcIik7XG5cbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gaDtcblxuICAgICAgICAgICAgZnVuY3Rpb24gaCh0YWdOYW1lLCBwcm9wZXJ0aWVzLCBjaGlsZHJlbikge1xuICAgICAgICAgICAgICAgIHZhciBjaGlsZE5vZGVzID0gW107XG4gICAgICAgICAgICAgICAgdmFyIHRhZywgcHJvcHMsIGtleSwgbmFtZXNwYWNlO1xuXG4gICAgICAgICAgICAgICAgaWYgKCFjaGlsZHJlbiAmJiBpc0NoaWxkcmVuKHByb3BlcnRpZXMpKSB7XG4gICAgICAgICAgICAgICAgICAgIGNoaWxkcmVuID0gcHJvcGVydGllcztcbiAgICAgICAgICAgICAgICAgICAgcHJvcHMgPSB7fTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICBwcm9wcyA9IHByb3BzIHx8IHByb3BlcnRpZXMgfHwge307XG4gICAgICAgICAgICAgICAgdGFnID0gcGFyc2VUYWcodGFnTmFtZSwgcHJvcHMpO1xuXG4gICAgICAgICAgICAgICAgLy8gc3VwcG9ydCBrZXlzXG4gICAgICAgICAgICAgICAgaWYgKHByb3BzLmhhc093blByb3BlcnR5KFwia2V5XCIpKSB7XG4gICAgICAgICAgICAgICAgICAgIGtleSA9IHByb3BzLmtleTtcbiAgICAgICAgICAgICAgICAgICAgcHJvcHMua2V5ID0gdW5kZWZpbmVkO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIC8vIHN1cHBvcnQgbmFtZXNwYWNlXG4gICAgICAgICAgICAgICAgaWYgKHByb3BzLmhhc093blByb3BlcnR5KFwibmFtZXNwYWNlXCIpKSB7XG4gICAgICAgICAgICAgICAgICAgIG5hbWVzcGFjZSA9IHByb3BzLm5hbWVzcGFjZTtcbiAgICAgICAgICAgICAgICAgICAgcHJvcHMubmFtZXNwYWNlID0gdW5kZWZpbmVkO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIC8vIGZpeCBjdXJzb3IgYnVnXG4gICAgICAgICAgICAgICAgaWYgKHRhZyA9PT0gXCJJTlBVVFwiICYmICFuYW1lc3BhY2UgJiYgcHJvcHMuaGFzT3duUHJvcGVydHkoXCJ2YWx1ZVwiKSAmJiBwcm9wcy52YWx1ZSAhPT0gdW5kZWZpbmVkICYmICFpc0hvb2socHJvcHMudmFsdWUpKSB7XG4gICAgICAgICAgICAgICAgICAgIHByb3BzLnZhbHVlID0gc29mdFNldEhvb2socHJvcHMudmFsdWUpO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHRyYW5zZm9ybVByb3BlcnRpZXMocHJvcHMpO1xuXG4gICAgICAgICAgICAgICAgaWYgKGNoaWxkcmVuICE9PSB1bmRlZmluZWQgJiYgY2hpbGRyZW4gIT09IG51bGwpIHtcbiAgICAgICAgICAgICAgICAgICAgYWRkQ2hpbGQoY2hpbGRyZW4sIGNoaWxkTm9kZXMsIHRhZywgcHJvcHMpO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHJldHVybiBuZXcgVk5vZGUodGFnLCBwcm9wcywgY2hpbGROb2Rlcywga2V5LCBuYW1lc3BhY2UpO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBmdW5jdGlvbiBhZGRDaGlsZChjLCBjaGlsZE5vZGVzLCB0YWcsIHByb3BzKSB7XG4gICAgICAgICAgICAgICAgaWYgKHR5cGVvZiBjID09PSBcInN0cmluZ1wiKSB7XG4gICAgICAgICAgICAgICAgICAgIGNoaWxkTm9kZXMucHVzaChuZXcgVlRleHQoYykpO1xuICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAodHlwZW9mIGMgPT09IFwibnVtYmVyXCIpIHtcbiAgICAgICAgICAgICAgICAgICAgY2hpbGROb2Rlcy5wdXNoKG5ldyBWVGV4dChTdHJpbmcoYykpKTtcbiAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKGlzQ2hpbGQoYykpIHtcbiAgICAgICAgICAgICAgICAgICAgY2hpbGROb2Rlcy5wdXNoKGMpO1xuICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoaXNBcnJheShjKSkge1xuICAgICAgICAgICAgICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IGMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGFkZENoaWxkKGNbaV0sIGNoaWxkTm9kZXMsIHRhZywgcHJvcHMpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfSBlbHNlIGlmIChjID09PSBudWxsIHx8IGMgPT09IHVuZGVmaW5lZCkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgdGhyb3cgVW5leHBlY3RlZFZpcnR1YWxFbGVtZW50KHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGZvcmVpZ25PYmplY3Q6IGMsXG4gICAgICAgICAgICAgICAgICAgICAgICBwYXJlbnRWbm9kZToge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRhZ05hbWU6IHRhZyxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBwcm9wZXJ0aWVzOiBwcm9wc1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIHRyYW5zZm9ybVByb3BlcnRpZXMocHJvcHMpIHtcbiAgICAgICAgICAgICAgICBmb3IgKHZhciBwcm9wTmFtZSBpbiBwcm9wcykge1xuICAgICAgICAgICAgICAgICAgICBpZiAocHJvcHMuaGFzT3duUHJvcGVydHkocHJvcE5hbWUpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICB2YXIgdmFsdWUgPSBwcm9wc1twcm9wTmFtZV07XG5cbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChpc0hvb2sodmFsdWUpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgY29udGludWU7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChwcm9wTmFtZS5zdWJzdHIoMCwgMykgPT09IFwiZXYtXCIpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBhZGQgZXYtZm9vIHN1cHBvcnRcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBwcm9wc1twcm9wTmFtZV0gPSBldkhvb2sodmFsdWUpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBmdW5jdGlvbiBpc0NoaWxkKHgpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gaXNWTm9kZSh4KSB8fCBpc1ZUZXh0KHgpIHx8IGlzV2lkZ2V0KHgpIHx8IGlzVlRodW5rKHgpO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBmdW5jdGlvbiBpc0NoaWxkcmVuKHgpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gdHlwZW9mIHggPT09IFwic3RyaW5nXCIgfHwgaXNBcnJheSh4KSB8fCBpc0NoaWxkKHgpO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBmdW5jdGlvbiBVbmV4cGVjdGVkVmlydHVhbEVsZW1lbnQoZGF0YSkge1xuICAgICAgICAgICAgICAgIHZhciBlcnIgPSBuZXcgRXJyb3IoKTtcblxuICAgICAgICAgICAgICAgIGVyci50eXBlID0gXCJ2aXJ0dWFsLWh5cGVyc2NyaXB0LnVuZXhwZWN0ZWQudmlydHVhbC1lbGVtZW50XCI7XG4gICAgICAgICAgICAgICAgZXJyLm1lc3NhZ2UgPSBcIlVuZXhwZWN0ZWQgdmlydHVhbCBjaGlsZCBwYXNzZWQgdG8gaCgpLlxcblwiICsgXCJFeHBlY3RlZCBhIFZOb2RlIC8gVnRodW5rIC8gVldpZGdldCAvIHN0cmluZyBidXQ6XFxuXCIgKyBcImdvdDpcXG5cIiArIGVycm9yU3RyaW5nKGRhdGEuZm9yZWlnbk9iamVjdCkgKyBcIi5cXG5cIiArIFwiVGhlIHBhcmVudCB2bm9kZSBpczpcXG5cIiArIGVycm9yU3RyaW5nKGRhdGEucGFyZW50Vm5vZGUpO1xuICAgICAgICAgICAgICAgIFwiXFxuXCIgKyBcIlN1Z2dlc3RlZCBmaXg6IGNoYW5nZSB5b3VyIGBoKC4uLiwgWyAuLi4gXSlgIGNhbGxzaXRlLlwiO1xuICAgICAgICAgICAgICAgIGVyci5mb3JlaWduT2JqZWN0ID0gZGF0YS5mb3JlaWduT2JqZWN0O1xuICAgICAgICAgICAgICAgIGVyci5wYXJlbnRWbm9kZSA9IGRhdGEucGFyZW50Vm5vZGU7XG5cbiAgICAgICAgICAgICAgICByZXR1cm4gZXJyO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBmdW5jdGlvbiBlcnJvclN0cmluZyhvYmopIHtcbiAgICAgICAgICAgICAgICB0cnkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gSlNPTi5zdHJpbmdpZnkob2JqLCBudWxsLCBcIiAgICBcIik7XG4gICAgICAgICAgICAgICAgfSBjYXRjaCAoZSkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gU3RyaW5nKG9iaik7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9LCB7IFwiLi4vdm5vZGUvaXMtdGh1bmtcIjogMjUsIFwiLi4vdm5vZGUvaXMtdmhvb2tcIjogMjYsIFwiLi4vdm5vZGUvaXMtdm5vZGVcIjogMjcsIFwiLi4vdm5vZGUvaXMtdnRleHRcIjogMjgsIFwiLi4vdm5vZGUvaXMtd2lkZ2V0XCI6IDI5LCBcIi4uL3Zub2RlL3Zub2RlLmpzXCI6IDMxLCBcIi4uL3Zub2RlL3Z0ZXh0LmpzXCI6IDMzLCBcIi4vaG9va3MvZXYtaG9vay5qc1wiOiAyMCwgXCIuL2hvb2tzL3NvZnQtc2V0LWhvb2suanNcIjogMjEsIFwiLi9wYXJzZS10YWcuanNcIjogMjMsIFwieC1pcy1hcnJheVwiOiAxMiB9XSwgMjM6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICBcInVzZSBzdHJpY3RcIjtcblxuICAgICAgICAgICAgdmFyIHNwbGl0ID0gcmVxdWlyZShcImJyb3dzZXItc3BsaXRcIik7XG5cbiAgICAgICAgICAgIHZhciBjbGFzc0lkU3BsaXQgPSAvKFtcXC4jXT9bYS16QS1aMC05XFx1MDA3Ri1cXHVGRkZGXzotXSspLztcbiAgICAgICAgICAgIHZhciBub3RDbGFzc0lkID0gL15cXC58Iy87XG5cbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gcGFyc2VUYWc7XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIHBhcnNlVGFnKHRhZywgcHJvcHMpIHtcbiAgICAgICAgICAgICAgICBpZiAoIXRhZykge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gXCJESVZcIjtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICB2YXIgbm9JZCA9ICFwcm9wcy5oYXNPd25Qcm9wZXJ0eShcImlkXCIpO1xuXG4gICAgICAgICAgICAgICAgdmFyIHRhZ1BhcnRzID0gc3BsaXQodGFnLCBjbGFzc0lkU3BsaXQpO1xuICAgICAgICAgICAgICAgIHZhciB0YWdOYW1lID0gbnVsbDtcblxuICAgICAgICAgICAgICAgIGlmIChub3RDbGFzc0lkLnRlc3QodGFnUGFydHNbMV0pKSB7XG4gICAgICAgICAgICAgICAgICAgIHRhZ05hbWUgPSBcIkRJVlwiO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHZhciBjbGFzc2VzLCBwYXJ0LCB0eXBlLCBpO1xuXG4gICAgICAgICAgICAgICAgZm9yIChpID0gMDsgaSA8IHRhZ1BhcnRzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICAgICAgICAgIHBhcnQgPSB0YWdQYXJ0c1tpXTtcblxuICAgICAgICAgICAgICAgICAgICBpZiAoIXBhcnQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnRpbnVlO1xuICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgdHlwZSA9IHBhcnQuY2hhckF0KDApO1xuXG4gICAgICAgICAgICAgICAgICAgIGlmICghdGFnTmFtZSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgdGFnTmFtZSA9IHBhcnQ7XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAodHlwZSA9PT0gXCIuXCIpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGNsYXNzZXMgPSBjbGFzc2VzIHx8IFtdO1xuICAgICAgICAgICAgICAgICAgICAgICAgY2xhc3Nlcy5wdXNoKHBhcnQuc3Vic3RyaW5nKDEsIHBhcnQubGVuZ3RoKSk7XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAodHlwZSA9PT0gXCIjXCIgJiYgbm9JZCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgcHJvcHMuaWQgPSBwYXJ0LnN1YnN0cmluZygxLCBwYXJ0Lmxlbmd0aCk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICBpZiAoY2xhc3Nlcykge1xuICAgICAgICAgICAgICAgICAgICBpZiAocHJvcHMuY2xhc3NOYW1lKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBjbGFzc2VzLnB1c2gocHJvcHMuY2xhc3NOYW1lKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgIHByb3BzLmNsYXNzTmFtZSA9IGNsYXNzZXMuam9pbihcIiBcIik7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgcmV0dXJuIHByb3BzLm5hbWVzcGFjZSA/IHRhZ05hbWUgOiB0YWdOYW1lLnRvVXBwZXJDYXNlKCk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0sIHsgXCJicm93c2VyLXNwbGl0XCI6IDUgfV0sIDI0OiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge1xuICAgICAgICAgICAgdmFyIGlzVk5vZGUgPSByZXF1aXJlKFwiLi9pcy12bm9kZVwiKTtcbiAgICAgICAgICAgIHZhciBpc1ZUZXh0ID0gcmVxdWlyZShcIi4vaXMtdnRleHRcIik7XG4gICAgICAgICAgICB2YXIgaXNXaWRnZXQgPSByZXF1aXJlKFwiLi9pcy13aWRnZXRcIik7XG4gICAgICAgICAgICB2YXIgaXNUaHVuayA9IHJlcXVpcmUoXCIuL2lzLXRodW5rXCIpO1xuXG4gICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IGhhbmRsZVRodW5rO1xuXG4gICAgICAgICAgICBmdW5jdGlvbiBoYW5kbGVUaHVuayhhLCBiKSB7XG4gICAgICAgICAgICAgICAgdmFyIHJlbmRlcmVkQSA9IGE7XG4gICAgICAgICAgICAgICAgdmFyIHJlbmRlcmVkQiA9IGI7XG5cbiAgICAgICAgICAgICAgICBpZiAoaXNUaHVuayhiKSkge1xuICAgICAgICAgICAgICAgICAgICByZW5kZXJlZEIgPSByZW5kZXJUaHVuayhiLCBhKTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICBpZiAoaXNUaHVuayhhKSkge1xuICAgICAgICAgICAgICAgICAgICByZW5kZXJlZEEgPSByZW5kZXJUaHVuayhhLCBudWxsKTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgICAgICAgICBhOiByZW5kZXJlZEEsXG4gICAgICAgICAgICAgICAgICAgIGI6IHJlbmRlcmVkQlxuICAgICAgICAgICAgICAgIH07XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIHJlbmRlclRodW5rKHRodW5rLCBwcmV2aW91cykge1xuICAgICAgICAgICAgICAgIHZhciByZW5kZXJlZFRodW5rID0gdGh1bmsudm5vZGU7XG5cbiAgICAgICAgICAgICAgICBpZiAoIXJlbmRlcmVkVGh1bmspIHtcbiAgICAgICAgICAgICAgICAgICAgcmVuZGVyZWRUaHVuayA9IHRodW5rLnZub2RlID0gdGh1bmsucmVuZGVyKHByZXZpb3VzKTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICBpZiAoIShpc1ZOb2RlKHJlbmRlcmVkVGh1bmspIHx8IGlzVlRleHQocmVuZGVyZWRUaHVuaykgfHwgaXNXaWRnZXQocmVuZGVyZWRUaHVuaykpKSB7XG4gICAgICAgICAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcihcInRodW5rIGRpZCBub3QgcmV0dXJuIGEgdmFsaWQgbm9kZVwiKTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICByZXR1cm4gcmVuZGVyZWRUaHVuaztcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSwgeyBcIi4vaXMtdGh1bmtcIjogMjUsIFwiLi9pcy12bm9kZVwiOiAyNywgXCIuL2lzLXZ0ZXh0XCI6IDI4LCBcIi4vaXMtd2lkZ2V0XCI6IDI5IH1dLCAyNTogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHtcbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gaXNUaHVuaztcblxuICAgICAgICAgICAgZnVuY3Rpb24gaXNUaHVuayh0KSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHQgJiYgdC50eXBlID09PSBcIlRodW5rXCI7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0sIHt9XSwgMjY6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IGlzSG9vaztcblxuICAgICAgICAgICAgZnVuY3Rpb24gaXNIb29rKGhvb2spIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gaG9vayAmJiAodHlwZW9mIGhvb2suaG9vayA9PT0gXCJmdW5jdGlvblwiICYmICFob29rLmhhc093blByb3BlcnR5KFwiaG9va1wiKSB8fCB0eXBlb2YgaG9vay51bmhvb2sgPT09IFwiZnVuY3Rpb25cIiAmJiAhaG9vay5oYXNPd25Qcm9wZXJ0eShcInVuaG9va1wiKSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0sIHt9XSwgMjc6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICB2YXIgdmVyc2lvbiA9IHJlcXVpcmUoXCIuL3ZlcnNpb25cIik7XG5cbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gaXNWaXJ0dWFsTm9kZTtcblxuICAgICAgICAgICAgZnVuY3Rpb24gaXNWaXJ0dWFsTm9kZSh4KSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHggJiYgeC50eXBlID09PSBcIlZpcnR1YWxOb2RlXCIgJiYgeC52ZXJzaW9uID09PSB2ZXJzaW9uO1xuICAgICAgICAgICAgfVxuICAgICAgICB9LCB7IFwiLi92ZXJzaW9uXCI6IDMwIH1dLCAyODogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHtcbiAgICAgICAgICAgIHZhciB2ZXJzaW9uID0gcmVxdWlyZShcIi4vdmVyc2lvblwiKTtcblxuICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBpc1ZpcnR1YWxUZXh0O1xuXG4gICAgICAgICAgICBmdW5jdGlvbiBpc1ZpcnR1YWxUZXh0KHgpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4geCAmJiB4LnR5cGUgPT09IFwiVmlydHVhbFRleHRcIiAmJiB4LnZlcnNpb24gPT09IHZlcnNpb247XG4gICAgICAgICAgICB9XG4gICAgICAgIH0sIHsgXCIuL3ZlcnNpb25cIjogMzAgfV0sIDI5OiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge1xuICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBpc1dpZGdldDtcblxuICAgICAgICAgICAgZnVuY3Rpb24gaXNXaWRnZXQodykge1xuICAgICAgICAgICAgICAgIHJldHVybiB3ICYmIHcudHlwZSA9PT0gXCJXaWRnZXRcIjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSwge31dLCAzMDogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHtcbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gXCIyXCI7XG4gICAgICAgIH0sIHt9XSwgMzE6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICB2YXIgdmVyc2lvbiA9IHJlcXVpcmUoXCIuL3ZlcnNpb25cIik7XG4gICAgICAgICAgICB2YXIgaXNWTm9kZSA9IHJlcXVpcmUoXCIuL2lzLXZub2RlXCIpO1xuICAgICAgICAgICAgdmFyIGlzV2lkZ2V0ID0gcmVxdWlyZShcIi4vaXMtd2lkZ2V0XCIpO1xuICAgICAgICAgICAgdmFyIGlzVGh1bmsgPSByZXF1aXJlKFwiLi9pcy10aHVua1wiKTtcbiAgICAgICAgICAgIHZhciBpc1ZIb29rID0gcmVxdWlyZShcIi4vaXMtdmhvb2tcIik7XG5cbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gVmlydHVhbE5vZGU7XG5cbiAgICAgICAgICAgIHZhciBub1Byb3BlcnRpZXMgPSB7fTtcbiAgICAgICAgICAgIHZhciBub0NoaWxkcmVuID0gW107XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIFZpcnR1YWxOb2RlKHRhZ05hbWUsIHByb3BlcnRpZXMsIGNoaWxkcmVuLCBrZXksIG5hbWVzcGFjZSkge1xuICAgICAgICAgICAgICAgIHRoaXMudGFnTmFtZSA9IHRhZ05hbWU7XG4gICAgICAgICAgICAgICAgdGhpcy5wcm9wZXJ0aWVzID0gcHJvcGVydGllcyB8fCBub1Byb3BlcnRpZXM7XG4gICAgICAgICAgICAgICAgdGhpcy5jaGlsZHJlbiA9IGNoaWxkcmVuIHx8IG5vQ2hpbGRyZW47XG4gICAgICAgICAgICAgICAgdGhpcy5rZXkgPSBrZXkgIT0gbnVsbCA/IFN0cmluZyhrZXkpIDogdW5kZWZpbmVkO1xuICAgICAgICAgICAgICAgIHRoaXMubmFtZXNwYWNlID0gdHlwZW9mIG5hbWVzcGFjZSA9PT0gXCJzdHJpbmdcIiA/IG5hbWVzcGFjZSA6IG51bGw7XG5cbiAgICAgICAgICAgICAgICB2YXIgY291bnQgPSBjaGlsZHJlbiAmJiBjaGlsZHJlbi5sZW5ndGggfHwgMDtcbiAgICAgICAgICAgICAgICB2YXIgZGVzY2VuZGFudHMgPSAwO1xuICAgICAgICAgICAgICAgIHZhciBoYXNXaWRnZXRzID0gZmFsc2U7XG4gICAgICAgICAgICAgICAgdmFyIGhhc1RodW5rcyA9IGZhbHNlO1xuICAgICAgICAgICAgICAgIHZhciBkZXNjZW5kYW50SG9va3MgPSBmYWxzZTtcbiAgICAgICAgICAgICAgICB2YXIgaG9va3M7XG5cbiAgICAgICAgICAgICAgICBmb3IgKHZhciBwcm9wTmFtZSBpbiBwcm9wZXJ0aWVzKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmIChwcm9wZXJ0aWVzLmhhc093blByb3BlcnR5KHByb3BOYW1lKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgdmFyIHByb3BlcnR5ID0gcHJvcGVydGllc1twcm9wTmFtZV07XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoaXNWSG9vayhwcm9wZXJ0eSkgJiYgcHJvcGVydHkudW5ob29rKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKCFob29rcykge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBob29rcyA9IHt9O1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGhvb2tzW3Byb3BOYW1lXSA9IHByb3BlcnR5O1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCBjb3VudDsgaSsrKSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciBjaGlsZCA9IGNoaWxkcmVuW2ldO1xuICAgICAgICAgICAgICAgICAgICBpZiAoaXNWTm9kZShjaGlsZCkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGRlc2NlbmRhbnRzICs9IGNoaWxkLmNvdW50IHx8IDA7XG5cbiAgICAgICAgICAgICAgICAgICAgICAgIGlmICghaGFzV2lkZ2V0cyAmJiBjaGlsZC5oYXNXaWRnZXRzKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaGFzV2lkZ2V0cyA9IHRydWU7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgICAgIGlmICghaGFzVGh1bmtzICYmIGNoaWxkLmhhc1RodW5rcykge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGhhc1RodW5rcyA9IHRydWU7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgICAgIGlmICghZGVzY2VuZGFudEhvb2tzICYmIChjaGlsZC5ob29rcyB8fCBjaGlsZC5kZXNjZW5kYW50SG9va3MpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgZGVzY2VuZGFudEhvb2tzID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIGlmICghaGFzV2lkZ2V0cyAmJiBpc1dpZGdldChjaGlsZCkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmICh0eXBlb2YgY2hpbGQuZGVzdHJveSA9PT0gXCJmdW5jdGlvblwiKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaGFzV2lkZ2V0cyA9IHRydWU7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoIWhhc1RodW5rcyAmJiBpc1RodW5rKGNoaWxkKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgaGFzVGh1bmtzID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHRoaXMuY291bnQgPSBjb3VudCArIGRlc2NlbmRhbnRzO1xuICAgICAgICAgICAgICAgIHRoaXMuaGFzV2lkZ2V0cyA9IGhhc1dpZGdldHM7XG4gICAgICAgICAgICAgICAgdGhpcy5oYXNUaHVua3MgPSBoYXNUaHVua3M7XG4gICAgICAgICAgICAgICAgdGhpcy5ob29rcyA9IGhvb2tzO1xuICAgICAgICAgICAgICAgIHRoaXMuZGVzY2VuZGFudEhvb2tzID0gZGVzY2VuZGFudEhvb2tzO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBWaXJ0dWFsTm9kZS5wcm90b3R5cGUudmVyc2lvbiA9IHZlcnNpb247XG4gICAgICAgICAgICBWaXJ0dWFsTm9kZS5wcm90b3R5cGUudHlwZSA9IFwiVmlydHVhbE5vZGVcIjtcbiAgICAgICAgfSwgeyBcIi4vaXMtdGh1bmtcIjogMjUsIFwiLi9pcy12aG9va1wiOiAyNiwgXCIuL2lzLXZub2RlXCI6IDI3LCBcIi4vaXMtd2lkZ2V0XCI6IDI5LCBcIi4vdmVyc2lvblwiOiAzMCB9XSwgMzI6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICB2YXIgdmVyc2lvbiA9IHJlcXVpcmUoXCIuL3ZlcnNpb25cIik7XG5cbiAgICAgICAgICAgIFZpcnR1YWxQYXRjaC5OT05FID0gMDtcbiAgICAgICAgICAgIFZpcnR1YWxQYXRjaC5WVEVYVCA9IDE7XG4gICAgICAgICAgICBWaXJ0dWFsUGF0Y2guVk5PREUgPSAyO1xuICAgICAgICAgICAgVmlydHVhbFBhdGNoLldJREdFVCA9IDM7XG4gICAgICAgICAgICBWaXJ0dWFsUGF0Y2guUFJPUFMgPSA0O1xuICAgICAgICAgICAgVmlydHVhbFBhdGNoLk9SREVSID0gNTtcbiAgICAgICAgICAgIFZpcnR1YWxQYXRjaC5JTlNFUlQgPSA2O1xuICAgICAgICAgICAgVmlydHVhbFBhdGNoLlJFTU9WRSA9IDc7XG4gICAgICAgICAgICBWaXJ0dWFsUGF0Y2guVEhVTksgPSA4O1xuXG4gICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IFZpcnR1YWxQYXRjaDtcblxuICAgICAgICAgICAgZnVuY3Rpb24gVmlydHVhbFBhdGNoKHR5cGUsIHZOb2RlLCBwYXRjaCkge1xuICAgICAgICAgICAgICAgIHRoaXMudHlwZSA9IE51bWJlcih0eXBlKTtcbiAgICAgICAgICAgICAgICB0aGlzLnZOb2RlID0gdk5vZGU7XG4gICAgICAgICAgICAgICAgdGhpcy5wYXRjaCA9IHBhdGNoO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBWaXJ0dWFsUGF0Y2gucHJvdG90eXBlLnZlcnNpb24gPSB2ZXJzaW9uO1xuICAgICAgICAgICAgVmlydHVhbFBhdGNoLnByb3RvdHlwZS50eXBlID0gXCJWaXJ0dWFsUGF0Y2hcIjtcbiAgICAgICAgfSwgeyBcIi4vdmVyc2lvblwiOiAzMCB9XSwgMzM6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICB2YXIgdmVyc2lvbiA9IHJlcXVpcmUoXCIuL3ZlcnNpb25cIik7XG5cbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gVmlydHVhbFRleHQ7XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIFZpcnR1YWxUZXh0KHRleHQpIHtcbiAgICAgICAgICAgICAgICB0aGlzLnRleHQgPSBTdHJpbmcodGV4dCk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIFZpcnR1YWxUZXh0LnByb3RvdHlwZS52ZXJzaW9uID0gdmVyc2lvbjtcbiAgICAgICAgICAgIFZpcnR1YWxUZXh0LnByb3RvdHlwZS50eXBlID0gXCJWaXJ0dWFsVGV4dFwiO1xuICAgICAgICB9LCB7IFwiLi92ZXJzaW9uXCI6IDMwIH1dLCAzNDogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHtcbiAgICAgICAgICAgIHZhciBpc09iamVjdCA9IHJlcXVpcmUoXCJpcy1vYmplY3RcIik7XG4gICAgICAgICAgICB2YXIgaXNIb29rID0gcmVxdWlyZShcIi4uL3Zub2RlL2lzLXZob29rXCIpO1xuXG4gICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IGRpZmZQcm9wcztcblxuICAgICAgICAgICAgZnVuY3Rpb24gZGlmZlByb3BzKGEsIGIpIHtcbiAgICAgICAgICAgICAgICB2YXIgZGlmZjtcblxuICAgICAgICAgICAgICAgIGZvciAodmFyIGFLZXkgaW4gYSkge1xuICAgICAgICAgICAgICAgICAgICBpZiAoIShhS2V5IGluIGIpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBkaWZmID0gZGlmZiB8fCB7fTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGRpZmZbYUtleV0gPSB1bmRlZmluZWQ7XG4gICAgICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgICAgICB2YXIgYVZhbHVlID0gYVthS2V5XTtcbiAgICAgICAgICAgICAgICAgICAgdmFyIGJWYWx1ZSA9IGJbYUtleV07XG5cbiAgICAgICAgICAgICAgICAgICAgaWYgKGFWYWx1ZSA9PT0gYlZhbHVlKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBjb250aW51ZTtcbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIGlmIChpc09iamVjdChhVmFsdWUpICYmIGlzT2JqZWN0KGJWYWx1ZSkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChnZXRQcm90b3R5cGUoYlZhbHVlKSAhPT0gZ2V0UHJvdG90eXBlKGFWYWx1ZSkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBkaWZmID0gZGlmZiB8fCB7fTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBkaWZmW2FLZXldID0gYlZhbHVlO1xuICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIGlmIChpc0hvb2soYlZhbHVlKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRpZmYgPSBkaWZmIHx8IHt9O1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRpZmZbYUtleV0gPSBiVmFsdWU7XG4gICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZhciBvYmplY3REaWZmID0gZGlmZlByb3BzKGFWYWx1ZSwgYlZhbHVlKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAob2JqZWN0RGlmZikge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBkaWZmID0gZGlmZiB8fCB7fTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZGlmZlthS2V5XSA9IG9iamVjdERpZmY7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgZGlmZiA9IGRpZmYgfHwge307XG4gICAgICAgICAgICAgICAgICAgICAgICBkaWZmW2FLZXldID0gYlZhbHVlO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgZm9yICh2YXIgYktleSBpbiBiKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmICghKGJLZXkgaW4gYSkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGRpZmYgPSBkaWZmIHx8IHt9O1xuICAgICAgICAgICAgICAgICAgICAgICAgZGlmZltiS2V5XSA9IGJbYktleV07XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICByZXR1cm4gZGlmZjtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZnVuY3Rpb24gZ2V0UHJvdG90eXBlKHZhbHVlKSB7XG4gICAgICAgICAgICAgICAgaWYgKE9iamVjdC5nZXRQcm90b3R5cGVPZikge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gT2JqZWN0LmdldFByb3RvdHlwZU9mKHZhbHVlKTtcbiAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKHZhbHVlLl9fcHJvdG9fXykge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gdmFsdWUuX19wcm90b19fO1xuICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAodmFsdWUuY29uc3RydWN0b3IpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHZhbHVlLmNvbnN0cnVjdG9yLnByb3RvdHlwZTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH0sIHsgXCIuLi92bm9kZS9pcy12aG9va1wiOiAyNiwgXCJpcy1vYmplY3RcIjogMTEgfV0sIDM1OiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge1xuICAgICAgICAgICAgdmFyIGlzQXJyYXkgPSByZXF1aXJlKFwieC1pcy1hcnJheVwiKTtcblxuICAgICAgICAgICAgdmFyIFZQYXRjaCA9IHJlcXVpcmUoXCIuLi92bm9kZS92cGF0Y2hcIik7XG4gICAgICAgICAgICB2YXIgaXNWTm9kZSA9IHJlcXVpcmUoXCIuLi92bm9kZS9pcy12bm9kZVwiKTtcbiAgICAgICAgICAgIHZhciBpc1ZUZXh0ID0gcmVxdWlyZShcIi4uL3Zub2RlL2lzLXZ0ZXh0XCIpO1xuICAgICAgICAgICAgdmFyIGlzV2lkZ2V0ID0gcmVxdWlyZShcIi4uL3Zub2RlL2lzLXdpZGdldFwiKTtcbiAgICAgICAgICAgIHZhciBpc1RodW5rID0gcmVxdWlyZShcIi4uL3Zub2RlL2lzLXRodW5rXCIpO1xuICAgICAgICAgICAgdmFyIGhhbmRsZVRodW5rID0gcmVxdWlyZShcIi4uL3Zub2RlL2hhbmRsZS10aHVua1wiKTtcblxuICAgICAgICAgICAgdmFyIGRpZmZQcm9wcyA9IHJlcXVpcmUoXCIuL2RpZmYtcHJvcHNcIik7XG5cbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gZGlmZjtcblxuICAgICAgICAgICAgZnVuY3Rpb24gZGlmZihhLCBiKSB7XG4gICAgICAgICAgICAgICAgdmFyIHBhdGNoID0geyBhOiBhIH07XG4gICAgICAgICAgICAgICAgd2FsayhhLCBiLCBwYXRjaCwgMCk7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHBhdGNoO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBmdW5jdGlvbiB3YWxrKGEsIGIsIHBhdGNoLCBpbmRleCkge1xuICAgICAgICAgICAgICAgIGlmIChhID09PSBiKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICB2YXIgYXBwbHkgPSBwYXRjaFtpbmRleF07XG4gICAgICAgICAgICAgICAgdmFyIGFwcGx5Q2xlYXIgPSBmYWxzZTtcblxuICAgICAgICAgICAgICAgIGlmIChpc1RodW5rKGEpIHx8IGlzVGh1bmsoYikpIHtcbiAgICAgICAgICAgICAgICAgICAgdGh1bmtzKGEsIGIsIHBhdGNoLCBpbmRleCk7XG4gICAgICAgICAgICAgICAgfSBlbHNlIGlmIChiID09IG51bGwpIHtcblxuICAgICAgICAgICAgICAgICAgICAvLyBJZiBhIGlzIGEgd2lkZ2V0IHdlIHdpbGwgYWRkIGEgcmVtb3ZlIHBhdGNoIGZvciBpdFxuICAgICAgICAgICAgICAgICAgICAvLyBPdGhlcndpc2UgYW55IGNoaWxkIHdpZGdldHMvaG9va3MgbXVzdCBiZSBkZXN0cm95ZWQuXG4gICAgICAgICAgICAgICAgICAgIC8vIFRoaXMgcHJldmVudHMgYWRkaW5nIHR3byByZW1vdmUgcGF0Y2hlcyBmb3IgYSB3aWRnZXQuXG4gICAgICAgICAgICAgICAgICAgIGlmICghaXNXaWRnZXQoYSkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGNsZWFyU3RhdGUoYSwgcGF0Y2gsIGluZGV4KTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGFwcGx5ID0gcGF0Y2hbaW5kZXhdO1xuICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgYXBwbHkgPSBhcHBlbmRQYXRjaChhcHBseSwgbmV3IFZQYXRjaChWUGF0Y2guUkVNT1ZFLCBhLCBiKSk7XG4gICAgICAgICAgICAgICAgfSBlbHNlIGlmIChpc1ZOb2RlKGIpKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmIChpc1ZOb2RlKGEpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoYS50YWdOYW1lID09PSBiLnRhZ05hbWUgJiYgYS5uYW1lc3BhY2UgPT09IGIubmFtZXNwYWNlICYmIGEua2V5ID09PSBiLmtleSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZhciBwcm9wc1BhdGNoID0gZGlmZlByb3BzKGEucHJvcGVydGllcywgYi5wcm9wZXJ0aWVzKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAocHJvcHNQYXRjaCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBhcHBseSA9IGFwcGVuZFBhdGNoKGFwcGx5LCBuZXcgVlBhdGNoKFZQYXRjaC5QUk9QUywgYSwgcHJvcHNQYXRjaCkpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBhcHBseSA9IGRpZmZDaGlsZHJlbihhLCBiLCBwYXRjaCwgYXBwbHksIGluZGV4KTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgYXBwbHkgPSBhcHBlbmRQYXRjaChhcHBseSwgbmV3IFZQYXRjaChWUGF0Y2guVk5PREUsIGEsIGIpKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBhcHBseUNsZWFyID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGFwcGx5ID0gYXBwZW5kUGF0Y2goYXBwbHksIG5ldyBWUGF0Y2goVlBhdGNoLlZOT0RFLCBhLCBiKSk7XG4gICAgICAgICAgICAgICAgICAgICAgICBhcHBseUNsZWFyID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoaXNWVGV4dChiKSkge1xuICAgICAgICAgICAgICAgICAgICBpZiAoIWlzVlRleHQoYSkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGFwcGx5ID0gYXBwZW5kUGF0Y2goYXBwbHksIG5ldyBWUGF0Y2goVlBhdGNoLlZURVhULCBhLCBiKSk7XG4gICAgICAgICAgICAgICAgICAgICAgICBhcHBseUNsZWFyID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIGlmIChhLnRleHQgIT09IGIudGV4dCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgYXBwbHkgPSBhcHBlbmRQYXRjaChhcHBseSwgbmV3IFZQYXRjaChWUGF0Y2guVlRFWFQsIGEsIGIpKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoaXNXaWRnZXQoYikpIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKCFpc1dpZGdldChhKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgYXBwbHlDbGVhciA9IHRydWU7XG4gICAgICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgICAgICBhcHBseSA9IGFwcGVuZFBhdGNoKGFwcGx5LCBuZXcgVlBhdGNoKFZQYXRjaC5XSURHRVQsIGEsIGIpKTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICBpZiAoYXBwbHkpIHtcbiAgICAgICAgICAgICAgICAgICAgcGF0Y2hbaW5kZXhdID0gYXBwbHk7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgaWYgKGFwcGx5Q2xlYXIpIHtcbiAgICAgICAgICAgICAgICAgICAgY2xlYXJTdGF0ZShhLCBwYXRjaCwgaW5kZXgpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZnVuY3Rpb24gZGlmZkNoaWxkcmVuKGEsIGIsIHBhdGNoLCBhcHBseSwgaW5kZXgpIHtcbiAgICAgICAgICAgICAgICB2YXIgYUNoaWxkcmVuID0gYS5jaGlsZHJlbjtcbiAgICAgICAgICAgICAgICB2YXIgb3JkZXJlZFNldCA9IHJlb3JkZXIoYUNoaWxkcmVuLCBiLmNoaWxkcmVuKTtcbiAgICAgICAgICAgICAgICB2YXIgYkNoaWxkcmVuID0gb3JkZXJlZFNldC5jaGlsZHJlbjtcblxuICAgICAgICAgICAgICAgIHZhciBhTGVuID0gYUNoaWxkcmVuLmxlbmd0aDtcbiAgICAgICAgICAgICAgICB2YXIgYkxlbiA9IGJDaGlsZHJlbi5sZW5ndGg7XG4gICAgICAgICAgICAgICAgdmFyIGxlbiA9IGFMZW4gPiBiTGVuID8gYUxlbiA6IGJMZW47XG5cbiAgICAgICAgICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IGxlbjsgaSsrKSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciBsZWZ0Tm9kZSA9IGFDaGlsZHJlbltpXTtcbiAgICAgICAgICAgICAgICAgICAgdmFyIHJpZ2h0Tm9kZSA9IGJDaGlsZHJlbltpXTtcbiAgICAgICAgICAgICAgICAgICAgaW5kZXggKz0gMTtcblxuICAgICAgICAgICAgICAgICAgICBpZiAoIWxlZnROb2RlKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAocmlnaHROb2RlKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gRXhjZXNzIG5vZGVzIGluIGIgbmVlZCB0byBiZSBhZGRlZFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGFwcGx5ID0gYXBwZW5kUGF0Y2goYXBwbHksIG5ldyBWUGF0Y2goVlBhdGNoLklOU0VSVCwgbnVsbCwgcmlnaHROb2RlKSk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICB3YWxrKGxlZnROb2RlLCByaWdodE5vZGUsIHBhdGNoLCBpbmRleCk7XG4gICAgICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgICAgICBpZiAoaXNWTm9kZShsZWZ0Tm9kZSkgJiYgbGVmdE5vZGUuY291bnQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGluZGV4ICs9IGxlZnROb2RlLmNvdW50O1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgaWYgKG9yZGVyZWRTZXQubW92ZXMpIHtcbiAgICAgICAgICAgICAgICAgICAgLy8gUmVvcmRlciBub2RlcyBsYXN0XG4gICAgICAgICAgICAgICAgICAgIGFwcGx5ID0gYXBwZW5kUGF0Y2goYXBwbHksIG5ldyBWUGF0Y2goVlBhdGNoLk9SREVSLCBhLCBvcmRlcmVkU2V0Lm1vdmVzKSk7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgcmV0dXJuIGFwcGx5O1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBmdW5jdGlvbiBjbGVhclN0YXRlKHZOb2RlLCBwYXRjaCwgaW5kZXgpIHtcbiAgICAgICAgICAgICAgICAvLyBUT0RPOiBNYWtlIHRoaXMgYSBzaW5nbGUgd2Fsaywgbm90IHR3b1xuICAgICAgICAgICAgICAgIHVuaG9vayh2Tm9kZSwgcGF0Y2gsIGluZGV4KTtcbiAgICAgICAgICAgICAgICBkZXN0cm95V2lkZ2V0cyh2Tm9kZSwgcGF0Y2gsIGluZGV4KTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgLy8gUGF0Y2ggcmVjb3JkcyBmb3IgYWxsIGRlc3Ryb3llZCB3aWRnZXRzIG11c3QgYmUgYWRkZWQgYmVjYXVzZSB3ZSBuZWVkXG4gICAgICAgICAgICAvLyBhIERPTSBub2RlIHJlZmVyZW5jZSBmb3IgdGhlIGRlc3Ryb3kgZnVuY3Rpb25cbiAgICAgICAgICAgIGZ1bmN0aW9uIGRlc3Ryb3lXaWRnZXRzKHZOb2RlLCBwYXRjaCwgaW5kZXgpIHtcbiAgICAgICAgICAgICAgICBpZiAoaXNXaWRnZXQodk5vZGUpKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmICh0eXBlb2Ygdk5vZGUuZGVzdHJveSA9PT0gXCJmdW5jdGlvblwiKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBwYXRjaFtpbmRleF0gPSBhcHBlbmRQYXRjaChwYXRjaFtpbmRleF0sIG5ldyBWUGF0Y2goVlBhdGNoLlJFTU9WRSwgdk5vZGUsIG51bGwpKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoaXNWTm9kZSh2Tm9kZSkgJiYgKHZOb2RlLmhhc1dpZGdldHMgfHwgdk5vZGUuaGFzVGh1bmtzKSkge1xuICAgICAgICAgICAgICAgICAgICB2YXIgY2hpbGRyZW4gPSB2Tm9kZS5jaGlsZHJlbjtcbiAgICAgICAgICAgICAgICAgICAgdmFyIGxlbiA9IGNoaWxkcmVuLmxlbmd0aDtcbiAgICAgICAgICAgICAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCBsZW47IGkrKykge1xuICAgICAgICAgICAgICAgICAgICAgICAgdmFyIGNoaWxkID0gY2hpbGRyZW5baV07XG4gICAgICAgICAgICAgICAgICAgICAgICBpbmRleCArPSAxO1xuXG4gICAgICAgICAgICAgICAgICAgICAgICBkZXN0cm95V2lkZ2V0cyhjaGlsZCwgcGF0Y2gsIGluZGV4KTtcblxuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGlzVk5vZGUoY2hpbGQpICYmIGNoaWxkLmNvdW50KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaW5kZXggKz0gY2hpbGQuY291bnQ7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKGlzVGh1bmsodk5vZGUpKSB7XG4gICAgICAgICAgICAgICAgICAgIHRodW5rcyh2Tm9kZSwgbnVsbCwgcGF0Y2gsIGluZGV4KTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIC8vIENyZWF0ZSBhIHN1Yi1wYXRjaCBmb3IgdGh1bmtzXG4gICAgICAgICAgICBmdW5jdGlvbiB0aHVua3MoYSwgYiwgcGF0Y2gsIGluZGV4KSB7XG4gICAgICAgICAgICAgICAgdmFyIG5vZGVzID0gaGFuZGxlVGh1bmsoYSwgYik7XG4gICAgICAgICAgICAgICAgdmFyIHRodW5rUGF0Y2ggPSBkaWZmKG5vZGVzLmEsIG5vZGVzLmIpO1xuICAgICAgICAgICAgICAgIGlmIChoYXNQYXRjaGVzKHRodW5rUGF0Y2gpKSB7XG4gICAgICAgICAgICAgICAgICAgIHBhdGNoW2luZGV4XSA9IG5ldyBWUGF0Y2goVlBhdGNoLlRIVU5LLCBudWxsLCB0aHVua1BhdGNoKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIGhhc1BhdGNoZXMocGF0Y2gpIHtcbiAgICAgICAgICAgICAgICBmb3IgKHZhciBpbmRleCBpbiBwYXRjaCkge1xuICAgICAgICAgICAgICAgICAgICBpZiAoaW5kZXggIT09IFwiYVwiKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgLy8gRXhlY3V0ZSBob29rcyB3aGVuIHR3byBub2RlcyBhcmUgaWRlbnRpY2FsXG4gICAgICAgICAgICBmdW5jdGlvbiB1bmhvb2sodk5vZGUsIHBhdGNoLCBpbmRleCkge1xuICAgICAgICAgICAgICAgIGlmIChpc1ZOb2RlKHZOb2RlKSkge1xuICAgICAgICAgICAgICAgICAgICBpZiAodk5vZGUuaG9va3MpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHBhdGNoW2luZGV4XSA9IGFwcGVuZFBhdGNoKHBhdGNoW2luZGV4XSwgbmV3IFZQYXRjaChWUGF0Y2guUFJPUFMsIHZOb2RlLCB1bmRlZmluZWRLZXlzKHZOb2RlLmhvb2tzKSkpO1xuICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgaWYgKHZOb2RlLmRlc2NlbmRhbnRIb29rcyB8fCB2Tm9kZS5oYXNUaHVua3MpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHZhciBjaGlsZHJlbiA9IHZOb2RlLmNoaWxkcmVuO1xuICAgICAgICAgICAgICAgICAgICAgICAgdmFyIGxlbiA9IGNoaWxkcmVuLmxlbmd0aDtcbiAgICAgICAgICAgICAgICAgICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgbGVuOyBpKyspIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB2YXIgY2hpbGQgPSBjaGlsZHJlbltpXTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpbmRleCArPSAxO1xuXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdW5ob29rKGNoaWxkLCBwYXRjaCwgaW5kZXgpO1xuXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGlzVk5vZGUoY2hpbGQpICYmIGNoaWxkLmNvdW50KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGluZGV4ICs9IGNoaWxkLmNvdW50O1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoaXNUaHVuayh2Tm9kZSkpIHtcbiAgICAgICAgICAgICAgICAgICAgdGh1bmtzKHZOb2RlLCBudWxsLCBwYXRjaCwgaW5kZXgpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZnVuY3Rpb24gdW5kZWZpbmVkS2V5cyhvYmopIHtcbiAgICAgICAgICAgICAgICB2YXIgcmVzdWx0ID0ge307XG5cbiAgICAgICAgICAgICAgICBmb3IgKHZhciBrZXkgaW4gb2JqKSB7XG4gICAgICAgICAgICAgICAgICAgIHJlc3VsdFtrZXldID0gdW5kZWZpbmVkO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHJldHVybiByZXN1bHQ7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIC8vIExpc3QgZGlmZiwgbmFpdmUgbGVmdCB0byByaWdodCByZW9yZGVyaW5nXG4gICAgICAgICAgICBmdW5jdGlvbiByZW9yZGVyKGFDaGlsZHJlbiwgYkNoaWxkcmVuKSB7XG4gICAgICAgICAgICAgICAgLy8gTyhNKSB0aW1lLCBPKE0pIG1lbW9yeVxuICAgICAgICAgICAgICAgIHZhciBiQ2hpbGRJbmRleCA9IGtleUluZGV4KGJDaGlsZHJlbik7XG4gICAgICAgICAgICAgICAgdmFyIGJLZXlzID0gYkNoaWxkSW5kZXgua2V5cztcbiAgICAgICAgICAgICAgICB2YXIgYkZyZWUgPSBiQ2hpbGRJbmRleC5mcmVlO1xuXG4gICAgICAgICAgICAgICAgaWYgKGJGcmVlLmxlbmd0aCA9PT0gYkNoaWxkcmVuLmxlbmd0aCkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgICAgICAgICAgICAgY2hpbGRyZW46IGJDaGlsZHJlbixcbiAgICAgICAgICAgICAgICAgICAgICAgIG1vdmVzOiBudWxsXG4gICAgICAgICAgICAgICAgICAgIH07XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgLy8gTyhOKSB0aW1lLCBPKE4pIG1lbW9yeVxuICAgICAgICAgICAgICAgIHZhciBhQ2hpbGRJbmRleCA9IGtleUluZGV4KGFDaGlsZHJlbik7XG4gICAgICAgICAgICAgICAgdmFyIGFLZXlzID0gYUNoaWxkSW5kZXgua2V5cztcbiAgICAgICAgICAgICAgICB2YXIgYUZyZWUgPSBhQ2hpbGRJbmRleC5mcmVlO1xuXG4gICAgICAgICAgICAgICAgaWYgKGFGcmVlLmxlbmd0aCA9PT0gYUNoaWxkcmVuLmxlbmd0aCkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgICAgICAgICAgICAgY2hpbGRyZW46IGJDaGlsZHJlbixcbiAgICAgICAgICAgICAgICAgICAgICAgIG1vdmVzOiBudWxsXG4gICAgICAgICAgICAgICAgICAgIH07XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgLy8gTyhNQVgoTiwgTSkpIG1lbW9yeVxuICAgICAgICAgICAgICAgIHZhciBuZXdDaGlsZHJlbiA9IFtdO1xuXG4gICAgICAgICAgICAgICAgdmFyIGZyZWVJbmRleCA9IDA7XG4gICAgICAgICAgICAgICAgdmFyIGZyZWVDb3VudCA9IGJGcmVlLmxlbmd0aDtcbiAgICAgICAgICAgICAgICB2YXIgZGVsZXRlZEl0ZW1zID0gMDtcblxuICAgICAgICAgICAgICAgIC8vIEl0ZXJhdGUgdGhyb3VnaCBhIGFuZCBtYXRjaCBhIG5vZGUgaW4gYlxuICAgICAgICAgICAgICAgIC8vIE8oTikgdGltZSxcbiAgICAgICAgICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IGFDaGlsZHJlbi5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgICAgICAgICB2YXIgYUl0ZW0gPSBhQ2hpbGRyZW5baV07XG4gICAgICAgICAgICAgICAgICAgIHZhciBpdGVtSW5kZXg7XG5cbiAgICAgICAgICAgICAgICAgICAgaWYgKGFJdGVtLmtleSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGJLZXlzLmhhc093blByb3BlcnR5KGFJdGVtLmtleSkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBNYXRjaCB1cCB0aGUgb2xkIGtleXNcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpdGVtSW5kZXggPSBiS2V5c1thSXRlbS5rZXldO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIG5ld0NoaWxkcmVuLnB1c2goYkNoaWxkcmVuW2l0ZW1JbmRleF0pO1xuICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBSZW1vdmUgb2xkIGtleWVkIGl0ZW1zXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaXRlbUluZGV4ID0gaSAtIGRlbGV0ZWRJdGVtcysrO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIG5ld0NoaWxkcmVuLnB1c2gobnVsbCk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAvLyBNYXRjaCB0aGUgaXRlbSBpbiBhIHdpdGggdGhlIG5leHQgZnJlZSBpdGVtIGluIGJcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChmcmVlSW5kZXggPCBmcmVlQ291bnQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpdGVtSW5kZXggPSBiRnJlZVtmcmVlSW5kZXgrK107XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgbmV3Q2hpbGRyZW4ucHVzaChiQ2hpbGRyZW5baXRlbUluZGV4XSk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIFRoZXJlIGFyZSBubyBmcmVlIGl0ZW1zIGluIGIgdG8gbWF0Y2ggd2l0aFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIHRoZSBmcmVlIGl0ZW1zIGluIGEsIHNvIHRoZSBleHRyYSBmcmVlIG5vZGVzXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gYXJlIGRlbGV0ZWQuXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaXRlbUluZGV4ID0gaSAtIGRlbGV0ZWRJdGVtcysrO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIG5ld0NoaWxkcmVuLnB1c2gobnVsbCk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICB2YXIgbGFzdEZyZWVJbmRleCA9IGZyZWVJbmRleCA+PSBiRnJlZS5sZW5ndGggPyBiQ2hpbGRyZW4ubGVuZ3RoIDogYkZyZWVbZnJlZUluZGV4XTtcblxuICAgICAgICAgICAgICAgIC8vIEl0ZXJhdGUgdGhyb3VnaCBiIGFuZCBhcHBlbmQgYW55IG5ldyBrZXlzXG4gICAgICAgICAgICAgICAgLy8gTyhNKSB0aW1lXG4gICAgICAgICAgICAgICAgZm9yICh2YXIgaiA9IDA7IGogPCBiQ2hpbGRyZW4ubGVuZ3RoOyBqKyspIHtcbiAgICAgICAgICAgICAgICAgICAgdmFyIG5ld0l0ZW0gPSBiQ2hpbGRyZW5bal07XG5cbiAgICAgICAgICAgICAgICAgICAgaWYgKG5ld0l0ZW0ua2V5KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoIWFLZXlzLmhhc093blByb3BlcnR5KG5ld0l0ZW0ua2V5KSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIEFkZCBhbnkgbmV3IGtleWVkIGl0ZW1zXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gV2UgYXJlIGFkZGluZyBuZXcgaXRlbXMgdG8gdGhlIGVuZCBhbmQgdGhlbiBzb3J0aW5nIHRoZW1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBpbiBwbGFjZS4gSW4gZnV0dXJlIHdlIHNob3VsZCBpbnNlcnQgbmV3IGl0ZW1zIGluIHBsYWNlLlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIG5ld0NoaWxkcmVuLnB1c2gobmV3SXRlbSk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoaiA+PSBsYXN0RnJlZUluZGV4KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAvLyBBZGQgYW55IGxlZnRvdmVyIG5vbi1rZXllZCBpdGVtc1xuICAgICAgICAgICAgICAgICAgICAgICAgbmV3Q2hpbGRyZW4ucHVzaChuZXdJdGVtKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHZhciBzaW11bGF0ZSA9IG5ld0NoaWxkcmVuLnNsaWNlKCk7XG4gICAgICAgICAgICAgICAgdmFyIHNpbXVsYXRlSW5kZXggPSAwO1xuICAgICAgICAgICAgICAgIHZhciByZW1vdmVzID0gW107XG4gICAgICAgICAgICAgICAgdmFyIGluc2VydHMgPSBbXTtcbiAgICAgICAgICAgICAgICB2YXIgc2ltdWxhdGVJdGVtO1xuXG4gICAgICAgICAgICAgICAgZm9yICh2YXIgayA9IDA7IGsgPCBiQ2hpbGRyZW4ubGVuZ3RoOykge1xuICAgICAgICAgICAgICAgICAgICB2YXIgd2FudGVkSXRlbSA9IGJDaGlsZHJlbltrXTtcbiAgICAgICAgICAgICAgICAgICAgc2ltdWxhdGVJdGVtID0gc2ltdWxhdGVbc2ltdWxhdGVJbmRleF07XG5cbiAgICAgICAgICAgICAgICAgICAgLy8gcmVtb3ZlIGl0ZW1zXG4gICAgICAgICAgICAgICAgICAgIHdoaWxlIChzaW11bGF0ZUl0ZW0gPT09IG51bGwgJiYgc2ltdWxhdGUubGVuZ3RoKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICByZW1vdmVzLnB1c2gocmVtb3ZlKHNpbXVsYXRlLCBzaW11bGF0ZUluZGV4LCBudWxsKSk7XG4gICAgICAgICAgICAgICAgICAgICAgICBzaW11bGF0ZUl0ZW0gPSBzaW11bGF0ZVtzaW11bGF0ZUluZGV4XTtcbiAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgIGlmICghc2ltdWxhdGVJdGVtIHx8IHNpbXVsYXRlSXRlbS5rZXkgIT09IHdhbnRlZEl0ZW0ua2V5KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAvLyBpZiB3ZSBuZWVkIGEga2V5IGluIHRoaXMgcG9zaXRpb24uLi5cbiAgICAgICAgICAgICAgICAgICAgICAgIGlmICh3YW50ZWRJdGVtLmtleSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChzaW11bGF0ZUl0ZW0gJiYgc2ltdWxhdGVJdGVtLmtleSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBpZiBhbiBpbnNlcnQgZG9lc24ndCBwdXQgdGhpcyBrZXkgaW4gcGxhY2UsIGl0IG5lZWRzIHRvIG1vdmVcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGJLZXlzW3NpbXVsYXRlSXRlbS5rZXldICE9PSBrICsgMSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmVtb3Zlcy5wdXNoKHJlbW92ZShzaW11bGF0ZSwgc2ltdWxhdGVJbmRleCwgc2ltdWxhdGVJdGVtLmtleSkpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc2ltdWxhdGVJdGVtID0gc2ltdWxhdGVbc2ltdWxhdGVJbmRleF07XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBpZiB0aGUgcmVtb3ZlIGRpZG4ndCBwdXQgdGhlIHdhbnRlZCBpdGVtIGluIHBsYWNlLCB3ZSBuZWVkIHRvIGluc2VydCBpdFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKCFzaW11bGF0ZUl0ZW0gfHwgc2ltdWxhdGVJdGVtLmtleSAhPT0gd2FudGVkSXRlbS5rZXkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpbnNlcnRzLnB1c2goeyBrZXk6IHdhbnRlZEl0ZW0ua2V5LCB0bzogayB9KTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIGl0ZW1zIGFyZSBtYXRjaGluZywgc28gc2tpcCBhaGVhZFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc2ltdWxhdGVJbmRleCsrO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaW5zZXJ0cy5wdXNoKHsga2V5OiB3YW50ZWRJdGVtLmtleSwgdG86IGsgfSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpbnNlcnRzLnB1c2goeyBrZXk6IHdhbnRlZEl0ZW0ua2V5LCB0bzogayB9KTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaysrO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgLy8gYSBrZXkgaW4gc2ltdWxhdGUgaGFzIG5vIG1hdGNoaW5nIHdhbnRlZCBrZXksIHJlbW92ZSBpdFxuICAgICAgICAgICAgICAgICAgICAgICAgZWxzZSBpZiAoc2ltdWxhdGVJdGVtICYmIHNpbXVsYXRlSXRlbS5rZXkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICByZW1vdmVzLnB1c2gocmVtb3ZlKHNpbXVsYXRlLCBzaW11bGF0ZUluZGV4LCBzaW11bGF0ZUl0ZW0ua2V5KSk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBzaW11bGF0ZUluZGV4Kys7XG4gICAgICAgICAgICAgICAgICAgICAgICBrKys7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAvLyByZW1vdmUgYWxsIHRoZSByZW1haW5pbmcgbm9kZXMgZnJvbSBzaW11bGF0ZVxuICAgICAgICAgICAgICAgIHdoaWxlIChzaW11bGF0ZUluZGV4IDwgc2ltdWxhdGUubGVuZ3RoKSB7XG4gICAgICAgICAgICAgICAgICAgIHNpbXVsYXRlSXRlbSA9IHNpbXVsYXRlW3NpbXVsYXRlSW5kZXhdO1xuICAgICAgICAgICAgICAgICAgICByZW1vdmVzLnB1c2gocmVtb3ZlKHNpbXVsYXRlLCBzaW11bGF0ZUluZGV4LCBzaW11bGF0ZUl0ZW0gJiYgc2ltdWxhdGVJdGVtLmtleSkpO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIC8vIElmIHRoZSBvbmx5IG1vdmVzIHdlIGhhdmUgYXJlIGRlbGV0ZXMgdGhlbiB3ZSBjYW4ganVzdFxuICAgICAgICAgICAgICAgIC8vIGxldCB0aGUgZGVsZXRlIHBhdGNoIHJlbW92ZSB0aGVzZSBpdGVtcy5cbiAgICAgICAgICAgICAgICBpZiAocmVtb3Zlcy5sZW5ndGggPT09IGRlbGV0ZWRJdGVtcyAmJiAhaW5zZXJ0cy5sZW5ndGgpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGNoaWxkcmVuOiBuZXdDaGlsZHJlbixcbiAgICAgICAgICAgICAgICAgICAgICAgIG1vdmVzOiBudWxsXG4gICAgICAgICAgICAgICAgICAgIH07XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgICAgICAgICAgY2hpbGRyZW46IG5ld0NoaWxkcmVuLFxuICAgICAgICAgICAgICAgICAgICBtb3Zlczoge1xuICAgICAgICAgICAgICAgICAgICAgICAgcmVtb3ZlczogcmVtb3ZlcyxcbiAgICAgICAgICAgICAgICAgICAgICAgIGluc2VydHM6IGluc2VydHNcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH07XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIHJlbW92ZShhcnIsIGluZGV4LCBrZXkpIHtcbiAgICAgICAgICAgICAgICBhcnIuc3BsaWNlKGluZGV4LCAxKTtcblxuICAgICAgICAgICAgICAgIHJldHVybiB7XG4gICAgICAgICAgICAgICAgICAgIGZyb206IGluZGV4LFxuICAgICAgICAgICAgICAgICAgICBrZXk6IGtleVxuICAgICAgICAgICAgICAgIH07XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIGtleUluZGV4KGNoaWxkcmVuKSB7XG4gICAgICAgICAgICAgICAgdmFyIGtleXMgPSB7fTtcbiAgICAgICAgICAgICAgICB2YXIgZnJlZSA9IFtdO1xuICAgICAgICAgICAgICAgIHZhciBsZW5ndGggPSBjaGlsZHJlbi5sZW5ndGg7XG5cbiAgICAgICAgICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IGxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciBjaGlsZCA9IGNoaWxkcmVuW2ldO1xuXG4gICAgICAgICAgICAgICAgICAgIGlmIChjaGlsZC5rZXkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGtleXNbY2hpbGQua2V5XSA9IGk7XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBmcmVlLnB1c2goaSk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgICAgICAgICBrZXlzOiBrZXlzLCAvLyBBIGhhc2ggb2Yga2V5IG5hbWUgdG8gaW5kZXhcbiAgICAgICAgICAgICAgICAgICAgZnJlZTogZnJlZSAvLyBBbiBhcnJheSBvZiB1bmtleWVkIGl0ZW0gaW5kaWNlc1xuICAgICAgICAgICAgICAgIH07XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIGFwcGVuZFBhdGNoKGFwcGx5LCBwYXRjaCkge1xuICAgICAgICAgICAgICAgIGlmIChhcHBseSkge1xuICAgICAgICAgICAgICAgICAgICBpZiAoaXNBcnJheShhcHBseSkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGFwcGx5LnB1c2gocGF0Y2gpO1xuICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgYXBwbHkgPSBbYXBwbHksIHBhdGNoXTtcbiAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBhcHBseTtcbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gcGF0Y2g7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9LCB7IFwiLi4vdm5vZGUvaGFuZGxlLXRodW5rXCI6IDI0LCBcIi4uL3Zub2RlL2lzLXRodW5rXCI6IDI1LCBcIi4uL3Zub2RlL2lzLXZub2RlXCI6IDI3LCBcIi4uL3Zub2RlL2lzLXZ0ZXh0XCI6IDI4LCBcIi4uL3Zub2RlL2lzLXdpZGdldFwiOiAyOSwgXCIuLi92bm9kZS92cGF0Y2hcIjogMzIsIFwiLi9kaWZmLXByb3BzXCI6IDM0LCBcIngtaXMtYXJyYXlcIjogMTIgfV0gfSwge30sIFs0XSkoNCk7XG59KTtcblxuLyogQGZsb3cgKi9cblxuY2xhc3MgTWFpbGJveCB7XG5cbiAgY29uc3RydWN0b3IoKSB7XG4gICAgdGhpcy5tZXNzYWdlcyA9IFtdO1xuICB9XG5cbiAgZGVsaXZlcihtZXNzYWdlKSB7XG4gICAgdGhpcy5tZXNzYWdlcy5wdXNoKG1lc3NhZ2UpO1xuICAgIHJldHVybiBtZXNzYWdlO1xuICB9XG5cbiAgZ2V0KCkge1xuICAgIHJldHVybiB0aGlzLm1lc3NhZ2VzO1xuICB9XG5cbiAgaXNFbXB0eSgpIHtcbiAgICByZXR1cm4gdGhpcy5tZXNzYWdlcy5sZW5ndGggPT09IDA7XG4gIH1cblxuICByZW1vdmVBdChpbmRleCkge1xuICAgIHRoaXMubWVzc2FnZXMuc3BsaWNlKGluZGV4LCAxKTtcbiAgfVxufVxuXG52YXIgU3RhdGVzID0ge1xuICBOT1JNQUw6IFN5bWJvbC5mb3IoXCJub3JtYWxcIiksXG4gIEtJTEw6IFN5bWJvbC5mb3IoXCJraWxsXCIpLFxuICBTVVNQRU5EOiBTeW1ib2wuZm9yKFwic3VzcGVuZFwiKSxcbiAgQ09OVElOVUU6IFN5bWJvbC5mb3IoXCJjb250aW51ZVwiKSxcbiAgUkVDRUlWRTogU3ltYm9sLmZvcihcInJlY2VpdmVcIiksXG4gIFNFTkQ6IFN5bWJvbC5mb3IoXCJzZW5kXCIpLFxuICBTTEVFUElORzogU3ltYm9sLmZvcihcInNsZWVwaW5nXCIpLFxuICBSVU5OSU5HOiBTeW1ib2wuZm9yKFwicnVubmluZ1wiKSxcbiAgU1VTUEVOREVEOiBTeW1ib2wuZm9yKFwic3VzcGVuZGVkXCIpLFxuICBTVE9QUEVEOiBTeW1ib2wuZm9yKFwic3RvcHBlZFwiKSxcbiAgU0xFRVA6IFN5bWJvbC5mb3IoXCJzbGVlcFwiKSxcbiAgRVhJVDogU3ltYm9sLmZvcihcImV4aXRcIiksXG4gIE5PTUFUQ0g6IFN5bWJvbC5mb3IoXCJub19tYXRjaFwiKVxufTtcblxuY2xhc3MgUHJvY2VzcyB7XG5cbiAgY29uc3RydWN0b3IocGlkLCBtYWlsYm94KSB7XG4gICAgdGhpcy5waWQgPSBwaWQ7XG4gICAgdGhpcy5tYWlsYm94ID0gbWFpbGJveDtcbiAgICB0aGlzLnN0YXR1cyA9IFN0YXRlcy5TVE9QUEVEO1xuICAgIHRoaXMuZGljdCA9IHt9O1xuICB9XG59XG5cbmNsYXNzIFR1cGxlIHtcblxuICBjb25zdHJ1Y3RvciguLi5hcmdzKSB7XG4gICAgdGhpcy52YWx1ZXMgPSBPYmplY3QuZnJlZXplKGFyZ3MpO1xuICAgIHRoaXMubGVuZ3RoID0gdGhpcy52YWx1ZXMubGVuZ3RoO1xuICB9XG5cbiAgZ2V0KGluZGV4KSB7XG4gICAgcmV0dXJuIHRoaXMudmFsdWVzW2luZGV4XTtcbiAgfVxuXG4gIGNvdW50KCkge1xuICAgIHJldHVybiB0aGlzLnZhbHVlcy5sZW5ndGg7XG4gIH1cblxuICBbU3ltYm9sLml0ZXJhdG9yXSgpIHtcbiAgICByZXR1cm4gdGhpcy52YWx1ZXNbU3ltYm9sLml0ZXJhdG9yXSgpO1xuICB9XG5cbiAgdG9TdHJpbmcoKSB7XG4gICAgdmFyIGksXG4gICAgICAgIHMgPSBcIlwiO1xuICAgIGZvciAoaSA9IDA7IGkgPCB0aGlzLnZhbHVlcy5sZW5ndGg7IGkrKykge1xuICAgICAgaWYgKHMgIT09IFwiXCIpIHtcbiAgICAgICAgcyArPSBcIiwgXCI7XG4gICAgICB9XG4gICAgICBzICs9IHRoaXMudmFsdWVzW2ldLnRvU3RyaW5nKCk7XG4gICAgfVxuXG4gICAgcmV0dXJuIFwie1wiICsgcyArIFwifVwiO1xuICB9XG5cbiAgcHV0X2VsZW0oaW5kZXgsIGVsZW0pIHtcbiAgICBsZXQgbmV3X3ZhbHVlcyA9IHRoaXMudmFsdWVzLmNvbmNhdChbXSk7XG4gICAgbmV3X3ZhbHVlcy5zcGxpY2UoaW5kZXgsIDAsIGVsZW0pO1xuICAgIHJldHVybiBuZXcgVHVwbGUoLi4ubmV3X3ZhbHVlcyk7XG4gIH1cblxufVxuXG5sZXQgcHJvY2Vzc19jb3VudGVyID0gLTE7XG5cbmNsYXNzIFBJRCB7XG4gIGNvbnN0cnVjdG9yKCkge1xuICAgIHByb2Nlc3NfY291bnRlciA9IHByb2Nlc3NfY291bnRlciArIDE7XG4gICAgdGhpcy5pZCA9IHByb2Nlc3NfY291bnRlcjtcbiAgfVxuXG4gIHRvU3RyaW5nKCkge1xuICAgIHJldHVybiBcIlBJRCM8MC5cIiArIHRoaXMuaWQgKyBcIi4wPlwiO1xuICB9XG59XG5cbmNsYXNzIEludGVnZXIge31cbmNsYXNzIEZsb2F0IHt9XG5cbmNsYXNzIFByb2Nlc3NTeXN0ZW0ge1xuXG4gIGNvbnN0cnVjdG9yKCkge1xuICAgIHRoaXMucGlkcyA9IG5ldyBNYXAoKTtcbiAgICB0aGlzLm1haWxib3hlcyA9IG5ldyBNYXAoKTtcbiAgICB0aGlzLm5hbWVzID0gbmV3IE1hcCgpO1xuICAgIHRoaXMubGlua3MgPSBuZXcgTWFwKCk7XG5cbiAgICB0aGlzLmN1cnJlbnRfcHJvY2VzcyA9IG51bGw7XG4gICAgdGhpcy5zdXNwZW5kZWQgPSBuZXcgTWFwKCk7XG5cbiAgICB0aGlzLm1haW5fcHJvY2Vzc19waWQgPSB0aGlzLnNwYXduKCk7XG4gICAgdGhpcy5zZXRfY3VycmVudCh0aGlzLm1haW5fcHJvY2Vzc19waWQpO1xuICB9XG5cbiAgc3Bhd24oKSB7XG4gICAgcmV0dXJuIHRoaXMuYWRkX3Byb2MoZmFsc2UpLnBpZDtcbiAgfVxuXG4gIHNwYXduX2xpbmsoKSB7XG4gICAgcmV0dXJuIHRoaXMuYWRkX3Byb2ModHJ1ZSkucGlkO1xuICB9XG5cbiAgbGluayhwaWQpIHtcbiAgICB0aGlzLmxpbmtzLmdldCh0aGlzLnBpZCgpKS5hZGQocGlkKTtcbiAgICB0aGlzLmxpbmtzLmdldChwaWQpLmFkZCh0aGlzLnBpZCgpKTtcbiAgfVxuXG4gIHVubGluayhwaWQpIHtcbiAgICB0aGlzLmxpbmtzLmdldCh0aGlzLnBpZCgpKS5kZWxldGUocGlkKTtcbiAgICB0aGlzLmxpbmtzLmdldChwaWQpLmRlbGV0ZSh0aGlzLnBpZCgpKTtcbiAgfVxuXG4gIHNldF9jdXJyZW50KGlkKSB7XG4gICAgbGV0IHBpZCA9IHRoaXMucGlkb2YoaWQpO1xuICAgIGlmIChwaWQgIT09IG51bGwpIHtcbiAgICAgIHRoaXMuY3VycmVudF9wcm9jZXNzID0gdGhpcy5waWRzLmdldChwaWQpO1xuICAgICAgdGhpcy5jdXJyZW50X3Byb2Nlc3Muc3RhdHVzID0gU3RhdGVzLlJVTk5JTkc7XG4gICAgfVxuICB9XG5cbiAgYWRkX3Byb2MobGlua2VkKSB7XG4gICAgbGV0IG5ld3BpZCA9IG5ldyBQSUQoKTtcbiAgICBsZXQgbWFpbGJveCA9IG5ldyBNYWlsYm94KCk7XG4gICAgbGV0IG5ld3Byb2MgPSBuZXcgUHJvY2VzcyhuZXdwaWQsIG1haWxib3gpO1xuXG4gICAgdGhpcy5waWRzLnNldChuZXdwaWQsIG5ld3Byb2MpO1xuICAgIHRoaXMubWFpbGJveGVzLnNldChuZXdwaWQsIG1haWxib3gpO1xuICAgIHRoaXMubGlua3Muc2V0KG5ld3BpZCwgbmV3IFNldCgpKTtcblxuICAgIGlmIChsaW5rZWQpIHtcbiAgICAgIHRoaXMubGluayhuZXdwaWQpO1xuICAgIH1cblxuICAgIHJldHVybiBuZXdwcm9jO1xuICB9XG5cbiAgcmVtb3ZlX3Byb2MocGlkKSB7XG4gICAgdGhpcy5waWRzLmRlbGV0ZShwaWQpO1xuICAgIHRoaXMudW5yZWdpc3RlcihwaWQpO1xuXG4gICAgaWYgKHRoaXMubGlua3MuaGFzKHBpZCkpIHtcbiAgICAgIGZvciAobGV0IGxpbmtwaWQgb2YgdGhpcy5saW5rcy5nZXQocGlkKSkge1xuICAgICAgICB0aGlzLmxpbmtzLmdldChsaW5rcGlkKS5kZWxldGUocGlkKTtcbiAgICAgIH1cblxuICAgICAgdGhpcy5saW5rcy5kZWxldGUocGlkKTtcbiAgICB9XG4gIH1cblxuICBleGl0KGlkKSB7XG4gICAgbGV0IHBpZCA9IHRoaXMucGlkb2YoaWQpO1xuICAgIHRoaXMucmVtb3ZlX3Byb2MoaWQpO1xuICB9XG5cbiAgcmVnaXN0ZXIobmFtZSwgcGlkKSB7XG4gICAgaWYgKCF0aGlzLm5hbWVzLmhhcyhuYW1lKSkge1xuICAgICAgdGhpcy5uYW1lcy5zZXQobmFtZSwgcGlkKTtcbiAgICAgIHJldHVybiBuYW1lO1xuICAgIH0gZWxzZSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoXCJOYW1lIGlzIGFscmVhZHkgcmVnaXN0ZXJlZCB0byBhbm90aGVyIHByb2Nlc3NcIik7XG4gICAgfVxuICB9XG5cbiAgcmVnaXN0ZXJlZChuYW1lKSB7XG4gICAgcmV0dXJuIHRoaXMubmFtZXMuaGFzKG5hbWUpID8gdGhpcy5uYW1lcy5nZXQobmFtZSkgOiBudWxsO1xuICB9XG5cbiAgdW5yZWdpc3RlcihwaWQpIHtcbiAgICBmb3IgKGxldCBuYW1lIG9mIHRoaXMubmFtZXMua2V5cygpKSB7XG4gICAgICBpZiAodGhpcy5uYW1lcy5oYXMobmFtZSkgJiYgdGhpcy5uYW1lcy5nZXQobmFtZSkgPT09IHBpZCkge1xuICAgICAgICB0aGlzLm5hbWVzLmRlbGV0ZShuYW1lKTtcbiAgICAgIH1cbiAgICB9XG4gIH1cblxuICBwaWQoKSB7XG4gICAgcmV0dXJuIHRoaXMuY3VycmVudF9wcm9jZXNzLnBpZDtcbiAgfVxuXG4gIHBpZG9mKGlkKSB7XG4gICAgaWYgKGlkIGluc3RhbmNlb2YgUElEKSB7XG4gICAgICByZXR1cm4gdGhpcy5waWRzLmhhcyhpZCkgPyBpZCA6IG51bGw7XG4gICAgfSBlbHNlIGlmIChpZCBpbnN0YW5jZW9mIFByb2Nlc3MpIHtcbiAgICAgIHJldHVybiBpZC5waWQ7XG4gICAgfSBlbHNlIHtcbiAgICAgIGxldCBwaWQgPSB0aGlzLnJlZ2lzdGVyZWQoaWQpO1xuICAgICAgaWYgKHBpZCA9PT0gbnVsbCkgdGhyb3cgXCJQcm9jZXNzIG5hbWUgbm90IHJlZ2lzdGVyZWQ6IFwiICsgaWQgKyBcIiAoXCIgKyB0eXBlb2YgaWQgKyBcIilcIjtcbiAgICAgIHJldHVybiBwaWQ7XG4gICAgfVxuICB9XG5cbiAgcHV0KGlkLCBrZXksIHZhbHVlKSB7XG4gICAgbGV0IHBpZCA9IHRoaXMucGlkb2YoaWQpO1xuICAgIGxldCBwcm9jZXNzID0gdGhpcy5waWRzLmdldChwaWQpO1xuICAgIHByb2Nlc3MuZGljdFtrZXldID0gdmFsdWU7XG4gIH1cblxuICBnZXQoaWQsIGtleSkge1xuICAgIGxldCBwaWQgPSB0aGlzLnBpZG9mKGlkKTtcbiAgICBsZXQgcHJvY2VzcyA9IHRoaXMucGlkcy5nZXQocGlkKTtcblxuICAgIGlmIChrZXkgIT0gbnVsbCkge1xuICAgICAgcmV0dXJuIHByb2Nlc3MuZGljdFtrZXldO1xuICAgIH0gZWxzZSB7XG4gICAgICByZXR1cm4gcHJvY2Vzcy5kaWN0O1xuICAgIH1cbiAgfVxuXG4gIGdldF9rZXlzKGlkKSB7XG4gICAgbGV0IHBpZCA9IHRoaXMucGlkb2YoaWQpO1xuICAgIGxldCBwcm9jZXNzID0gdGhpcy5waWRzLmdldChwaWQpO1xuXG4gICAgcmV0dXJuIE9iamVjdC5rZXlzKHByb2Nlc3MuZGljdCk7XG4gIH1cblxuICBlcmFzZShpZCwga2V5KSB7XG4gICAgbGV0IHBpZCA9IHRoaXMucGlkb2YoaWQpO1xuICAgIGxldCBwcm9jZXNzID0gdGhpcy5waWRzLmdldChwaWQpO1xuXG4gICAgaWYgKGtleSAhPSBudWxsKSB7XG4gICAgICBkZWxldGUgcHJvY2Vzcy5kaWN0W2tleV07XG4gICAgfSBlbHNlIHtcbiAgICAgIHByb2Nlc3MuZGljdCA9IHt9O1xuICAgIH1cbiAgfVxufVxuXG5jbGFzcyBCaXRTdHJpbmcge1xuICBjb25zdHJ1Y3RvciguLi5hcmdzKSB7XG4gICAgdGhpcy5yYXdfdmFsdWUgPSBmdW5jdGlvbiAoKSB7XG4gICAgICByZXR1cm4gT2JqZWN0LmZyZWV6ZShhcmdzKTtcbiAgICB9O1xuXG4gICAgdGhpcy52YWx1ZSA9IE9iamVjdC5mcmVlemUodGhpcy5wcm9jZXNzKGFyZ3MpKTtcbiAgICB0aGlzLmxlbmd0aCA9IHRoaXMudmFsdWUubGVuZ3RoO1xuICAgIHRoaXMuYml0X3NpemUgPSB0aGlzLnJhd192YWx1ZS5yZWR1Y2UoKHByZXYsIGN1cnJlbnQpID0+IHByZXYgKyBjdXJyZW50LnNpemUpO1xuICAgIHRoaXMuYnl0ZV9zaXplID0gdGhpcy5iaXRfc2l6ZSAvIDggKyAodGhpcy5iaXRfc2l6ZSAlIDggPiAwID8gMSA6IDApO1xuICB9XG5cbiAgZ2V0KGluZGV4KSB7XG4gICAgcmV0dXJuIHRoaXMudmFsdWVbaW5kZXhdO1xuICB9XG5cbiAgY291bnQoKSB7XG4gICAgcmV0dXJuIHRoaXMudmFsdWUubGVuZ3RoO1xuICB9XG5cbiAgW1N5bWJvbC5pdGVyYXRvcl0oKSB7XG4gICAgcmV0dXJuIHRoaXMudmFsdWVbU3ltYm9sLml0ZXJhdG9yXSgpO1xuICB9XG5cbiAgdG9TdHJpbmcoKSB7XG4gICAgdmFyIGksXG4gICAgICAgIHMgPSBcIlwiO1xuICAgIGZvciAoaSA9IDA7IGkgPCB0aGlzLmNvdW50KCk7IGkrKykge1xuICAgICAgaWYgKHMgIT09IFwiXCIpIHtcbiAgICAgICAgcyArPSBcIiwgXCI7XG4gICAgICB9XG4gICAgICBzICs9IHRoaXNbaV0udG9TdHJpbmcoKTtcbiAgICB9XG5cbiAgICByZXR1cm4gXCI8PFwiICsgcyArIFwiPj5cIjtcbiAgfVxuXG4gIHByb2Nlc3MoKSB7XG4gICAgbGV0IHByb2Nlc3NlZF92YWx1ZXMgPSBbXTtcblxuICAgIHZhciBpO1xuICAgIGZvciAoaSA9IDA7IGkgPCB0aGlzLnJhd192YWx1ZSgpLmxlbmd0aDsgaSsrKSB7XG4gICAgICBsZXQgcHJvY2Vzc2VkX3ZhbHVlID0gdGhpc1tcInByb2Nlc3NfXCIgKyB0aGlzLnJhd192YWx1ZSgpW2ldLnR5cGVdKHRoaXMucmF3X3ZhbHVlKClbaV0pO1xuXG4gICAgICBmb3IgKGxldCBhdHRyIG9mIHRoaXMucmF3X3ZhbHVlKClbaV0uYXR0cmlidXRlcykge1xuICAgICAgICBwcm9jZXNzZWRfdmFsdWUgPSB0aGlzW1wicHJvY2Vzc19cIiArIGF0dHJdKHByb2Nlc3NlZF92YWx1ZSk7XG4gICAgICB9XG5cbiAgICAgIHByb2Nlc3NlZF92YWx1ZXMgPSBwcm9jZXNzZWRfdmFsdWVzLmNvbmNhdChwcm9jZXNzZWRfdmFsdWUpO1xuICAgIH1cblxuICAgIHJldHVybiBwcm9jZXNzZWRfdmFsdWVzO1xuICB9XG5cbiAgcHJvY2Vzc19pbnRlZ2VyKHZhbHVlKSB7XG4gICAgcmV0dXJuIHZhbHVlLnZhbHVlO1xuICB9XG5cbiAgcHJvY2Vzc19mbG9hdCh2YWx1ZSkge1xuICAgIGlmICh2YWx1ZS5zaXplID09PSA2NCkge1xuICAgICAgcmV0dXJuIEJpdFN0cmluZy5mbG9hdDY0VG9CeXRlcyh2YWx1ZS52YWx1ZSk7XG4gICAgfSBlbHNlIGlmICh2YWx1ZS5zaXplID09PSAzMikge1xuICAgICAgcmV0dXJuIEJpdFN0cmluZy5mbG9hdDMyVG9CeXRlcyh2YWx1ZS52YWx1ZSk7XG4gICAgfVxuXG4gICAgdGhyb3cgbmV3IEVycm9yKFwiSW52YWxpZCBzaXplIGZvciBmbG9hdFwiKTtcbiAgfVxuXG4gIHByb2Nlc3NfYml0c3RyaW5nKHZhbHVlKSB7XG4gICAgcmV0dXJuIHZhbHVlLnZhbHVlLnZhbHVlO1xuICB9XG5cbiAgcHJvY2Vzc19iaW5hcnkodmFsdWUpIHtcbiAgICByZXR1cm4gQml0U3RyaW5nLnRvVVRGOEFycmF5KHZhbHVlLnZhbHVlKTtcbiAgfVxuXG4gIHByb2Nlc3NfdXRmOCh2YWx1ZSkge1xuICAgIHJldHVybiBCaXRTdHJpbmcudG9VVEY4QXJyYXkodmFsdWUudmFsdWUpO1xuICB9XG5cbiAgcHJvY2Vzc191dGYxNih2YWx1ZSkge1xuICAgIHJldHVybiBCaXRTdHJpbmcudG9VVEYxNkFycmF5KHZhbHVlLnZhbHVlKTtcbiAgfVxuXG4gIHByb2Nlc3NfdXRmMzIodmFsdWUpIHtcbiAgICByZXR1cm4gQml0U3RyaW5nLnRvVVRGMzJBcnJheSh2YWx1ZS52YWx1ZSk7XG4gIH1cblxuICBwcm9jZXNzX3NpZ25lZCh2YWx1ZSkge1xuICAgIHJldHVybiBuZXcgVWludDhBcnJheShbdmFsdWVdKVswXTtcbiAgfVxuXG4gIHByb2Nlc3NfdW5zaWduZWQodmFsdWUpIHtcbiAgICByZXR1cm4gdmFsdWU7XG4gIH1cblxuICBwcm9jZXNzX25hdGl2ZSh2YWx1ZSkge1xuICAgIHJldHVybiB2YWx1ZTtcbiAgfVxuXG4gIHByb2Nlc3NfYmlnKHZhbHVlKSB7XG4gICAgcmV0dXJuIHZhbHVlO1xuICB9XG5cbiAgcHJvY2Vzc19saXR0bGUodmFsdWUpIHtcbiAgICByZXR1cm4gdmFsdWUucmV2ZXJzZSgpO1xuICB9XG5cbiAgcHJvY2Vzc19zaXplKHZhbHVlKSB7XG4gICAgcmV0dXJuIHZhbHVlO1xuICB9XG5cbiAgcHJvY2Vzc191bml0KHZhbHVlKSB7XG4gICAgcmV0dXJuIHZhbHVlO1xuICB9XG5cbiAgc3RhdGljIGludGVnZXIodmFsdWUpIHtcbiAgICByZXR1cm4gQml0U3RyaW5nLndyYXAodmFsdWUsIHsgXCJ0eXBlXCI6IFwiaW50ZWdlclwiLCBcInVuaXRcIjogMSwgXCJzaXplXCI6IDggfSk7XG4gIH1cblxuICBzdGF0aWMgZmxvYXQodmFsdWUpIHtcbiAgICByZXR1cm4gQml0U3RyaW5nLndyYXAodmFsdWUsIHsgXCJ0eXBlXCI6IFwiZmxvYXRcIiwgXCJ1bml0XCI6IDEsIFwic2l6ZVwiOiA2NCB9KTtcbiAgfVxuXG4gIHN0YXRpYyBiaXRzdHJpbmcodmFsdWUpIHtcbiAgICByZXR1cm4gQml0U3RyaW5nLndyYXAodmFsdWUsIHsgXCJ0eXBlXCI6IFwiYml0c3RyaW5nXCIsIFwidW5pdFwiOiAxLCBcInNpemVcIjogdmFsdWUuYml0X3NpemUgfSk7XG4gIH1cblxuICBzdGF0aWMgYml0cyh2YWx1ZSkge1xuICAgIHJldHVybiBCaXRTdHJpbmcuYml0c3RyaW5nKHZhbHVlKTtcbiAgfVxuXG4gIHN0YXRpYyBiaW5hcnkodmFsdWUpIHtcbiAgICByZXR1cm4gQml0U3RyaW5nLndyYXAodmFsdWUsIHsgXCJ0eXBlXCI6IFwiYmluYXJ5XCIsIFwidW5pdFwiOiA4LCBcInNpemVcIjogdmFsdWUubGVuZ3RoIH0pO1xuICB9XG5cbiAgc3RhdGljIGJ5dGVzKHZhbHVlKSB7XG4gICAgcmV0dXJuIEJpdFN0cmluZy5iaW5hcnkodmFsdWUpO1xuICB9XG5cbiAgc3RhdGljIHV0ZjgodmFsdWUpIHtcbiAgICByZXR1cm4gQml0U3RyaW5nLndyYXAodmFsdWUsIHsgXCJ0eXBlXCI6IFwidXRmOFwiIH0pO1xuICB9XG5cbiAgc3RhdGljIHV0ZjE2KHZhbHVlKSB7XG4gICAgcmV0dXJuIEJpdFN0cmluZy53cmFwKHZhbHVlLCB7IFwidHlwZVwiOiBcInV0ZjE2XCIgfSk7XG4gIH1cblxuICBzdGF0aWMgdXRmMzIodmFsdWUpIHtcbiAgICByZXR1cm4gQml0U3RyaW5nLndyYXAodmFsdWUsIHsgXCJ0eXBlXCI6IFwidXRmMzJcIiB9KTtcbiAgfVxuXG4gIHN0YXRpYyBzaWduZWQodmFsdWUpIHtcbiAgICByZXR1cm4gQml0U3RyaW5nLndyYXAodmFsdWUsIHt9LCBcInNpZ25lZFwiKTtcbiAgfVxuXG4gIHN0YXRpYyB1bnNpZ25lZCh2YWx1ZSkge1xuICAgIHJldHVybiBCaXRTdHJpbmcud3JhcCh2YWx1ZSwge30sIFwidW5zaWduZWRcIik7XG4gIH1cblxuICBzdGF0aWMgbmF0aXZlKHZhbHVlKSB7XG4gICAgcmV0dXJuIEJpdFN0cmluZy53cmFwKHZhbHVlLCB7fSwgXCJuYXRpdmVcIik7XG4gIH1cblxuICBzdGF0aWMgYmlnKHZhbHVlKSB7XG4gICAgcmV0dXJuIEJpdFN0cmluZy53cmFwKHZhbHVlLCB7fSwgXCJiaWdcIik7XG4gIH1cblxuICBzdGF0aWMgbGl0dGxlKHZhbHVlKSB7XG4gICAgcmV0dXJuIEJpdFN0cmluZy53cmFwKHZhbHVlLCB7fSwgXCJsaXR0bGVcIik7XG4gIH1cblxuICBzdGF0aWMgc2l6ZSh2YWx1ZSwgY291bnQpIHtcbiAgICByZXR1cm4gQml0U3RyaW5nLndyYXAodmFsdWUsIHsgXCJzaXplXCI6IGNvdW50IH0pO1xuICB9XG5cbiAgc3RhdGljIHVuaXQodmFsdWUsIGNvdW50KSB7XG4gICAgcmV0dXJuIEJpdFN0cmluZy53cmFwKHZhbHVlLCB7IFwidW5pdFwiOiBjb3VudCB9KTtcbiAgfVxuXG4gIHN0YXRpYyB3cmFwKHZhbHVlLCBvcHQsIG5ld19hdHRyaWJ1dGUgPSBudWxsKSB7XG4gICAgbGV0IHRoZV92YWx1ZSA9IHZhbHVlO1xuXG4gICAgaWYgKCEodmFsdWUgaW5zdGFuY2VvZiBPYmplY3QpKSB7XG4gICAgICB0aGVfdmFsdWUgPSB7IFwidmFsdWVcIjogdmFsdWUsIFwiYXR0cmlidXRlc1wiOiBbXSB9O1xuICAgIH1cblxuICAgIHRoZV92YWx1ZSA9IE9iamVjdC5hc3NpZ24odGhlX3ZhbHVlLCBvcHQpO1xuXG4gICAgaWYgKG5ld19hdHRyaWJ1dGUpIHtcbiAgICAgIHRoZV92YWx1ZS5hdHRyaWJ1dGVzLnB1c2gobmV3X2F0dHJpYnV0ZSk7XG4gICAgfVxuXG4gICAgcmV0dXJuIHRoZV92YWx1ZTtcbiAgfVxuXG4gIHN0YXRpYyB0b1VURjhBcnJheShzdHIpIHtcbiAgICB2YXIgdXRmOCA9IFtdO1xuICAgIGZvciAodmFyIGkgPSAwOyBpIDwgc3RyLmxlbmd0aDsgaSsrKSB7XG4gICAgICB2YXIgY2hhcmNvZGUgPSBzdHIuY2hhckNvZGVBdChpKTtcbiAgICAgIGlmIChjaGFyY29kZSA8IDEyOCkge1xuICAgICAgICB1dGY4LnB1c2goY2hhcmNvZGUpO1xuICAgICAgfSBlbHNlIGlmIChjaGFyY29kZSA8IDIwNDgpIHtcbiAgICAgICAgdXRmOC5wdXNoKDE5MiB8IGNoYXJjb2RlID4+IDYsIDEyOCB8IGNoYXJjb2RlICYgNjMpO1xuICAgICAgfSBlbHNlIGlmIChjaGFyY29kZSA8IDU1Mjk2IHx8IGNoYXJjb2RlID49IDU3MzQ0KSB7XG4gICAgICAgIHV0ZjgucHVzaCgyMjQgfCBjaGFyY29kZSA+PiAxMiwgMTI4IHwgY2hhcmNvZGUgPj4gNiAmIDYzLCAxMjggfCBjaGFyY29kZSAmIDYzKTtcbiAgICAgIH1cbiAgICAgIC8vIHN1cnJvZ2F0ZSBwYWlyXG4gICAgICBlbHNlIHtcbiAgICAgICAgaSsrO1xuICAgICAgICAvLyBVVEYtMTYgZW5jb2RlcyAweDEwMDAwLTB4MTBGRkZGIGJ5XG4gICAgICAgIC8vIHN1YnRyYWN0aW5nIDB4MTAwMDAgYW5kIHNwbGl0dGluZyB0aGVcbiAgICAgICAgLy8gMjAgYml0cyBvZiAweDAtMHhGRkZGRiBpbnRvIHR3byBoYWx2ZXNcbiAgICAgICAgY2hhcmNvZGUgPSA2NTUzNiArICgoY2hhcmNvZGUgJiAxMDIzKSA8PCAxMCB8IHN0ci5jaGFyQ29kZUF0KGkpICYgMTAyMyk7XG4gICAgICAgIHV0ZjgucHVzaCgyNDAgfCBjaGFyY29kZSA+PiAxOCwgMTI4IHwgY2hhcmNvZGUgPj4gMTIgJiA2MywgMTI4IHwgY2hhcmNvZGUgPj4gNiAmIDYzLCAxMjggfCBjaGFyY29kZSAmIDYzKTtcbiAgICAgIH1cbiAgICB9XG4gICAgcmV0dXJuIHV0Zjg7XG4gIH1cblxuICBzdGF0aWMgdG9VVEYxNkFycmF5KHN0cikge1xuICAgIHZhciB1dGYxNiA9IFtdO1xuICAgIGZvciAodmFyIGkgPSAwOyBpIDwgc3RyLmxlbmd0aDsgaSsrKSB7XG4gICAgICB2YXIgY29kZVBvaW50ID0gc3RyLmNvZGVQb2ludEF0KGkpO1xuXG4gICAgICBpZiAoY29kZVBvaW50IDw9IDI1NSkge1xuICAgICAgICB1dGYxNi5wdXNoKDApO1xuICAgICAgICB1dGYxNi5wdXNoKGNvZGVQb2ludCk7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICB1dGYxNi5wdXNoKGNvZGVQb2ludCA+PiA4ICYgMjU1KTtcbiAgICAgICAgdXRmMTYucHVzaChjb2RlUG9pbnQgJiAyNTUpO1xuICAgICAgfVxuICAgIH1cbiAgICByZXR1cm4gdXRmMTY7XG4gIH1cblxuICBzdGF0aWMgdG9VVEYzMkFycmF5KHN0cikge1xuICAgIHZhciB1dGYzMiA9IFtdO1xuICAgIGZvciAodmFyIGkgPSAwOyBpIDwgc3RyLmxlbmd0aDsgaSsrKSB7XG4gICAgICB2YXIgY29kZVBvaW50ID0gc3RyLmNvZGVQb2ludEF0KGkpO1xuXG4gICAgICBpZiAoY29kZVBvaW50IDw9IDI1NSkge1xuICAgICAgICB1dGYzMi5wdXNoKDApO1xuICAgICAgICB1dGYzMi5wdXNoKDApO1xuICAgICAgICB1dGYzMi5wdXNoKDApO1xuICAgICAgICB1dGYzMi5wdXNoKGNvZGVQb2ludCk7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICB1dGYzMi5wdXNoKDApO1xuICAgICAgICB1dGYzMi5wdXNoKDApO1xuICAgICAgICB1dGYzMi5wdXNoKGNvZGVQb2ludCA+PiA4ICYgMjU1KTtcbiAgICAgICAgdXRmMzIucHVzaChjb2RlUG9pbnQgJiAyNTUpO1xuICAgICAgfVxuICAgIH1cbiAgICByZXR1cm4gdXRmMzI7XG4gIH1cblxuICAvL2h0dHA6Ly9zdGFja292ZXJmbG93LmNvbS9xdWVzdGlvbnMvMjAwMzQ5My9qYXZhc2NyaXB0LWZsb2F0LWZyb20tdG8tYml0c1xuICBzdGF0aWMgZmxvYXQzMlRvQnl0ZXMoZikge1xuICAgIHZhciBieXRlcyA9IFtdO1xuXG4gICAgdmFyIGJ1ZiA9IG5ldyBBcnJheUJ1ZmZlcig0KTtcbiAgICBuZXcgRmxvYXQzMkFycmF5KGJ1ZilbMF0gPSBmO1xuXG4gICAgbGV0IGludFZlcnNpb24gPSBuZXcgVWludDMyQXJyYXkoYnVmKVswXTtcblxuICAgIGJ5dGVzLnB1c2goaW50VmVyc2lvbiA+PiAyNCAmIDI1NSk7XG4gICAgYnl0ZXMucHVzaChpbnRWZXJzaW9uID4+IDE2ICYgMjU1KTtcbiAgICBieXRlcy5wdXNoKGludFZlcnNpb24gPj4gOCAmIDI1NSk7XG4gICAgYnl0ZXMucHVzaChpbnRWZXJzaW9uICYgMjU1KTtcblxuICAgIHJldHVybiBieXRlcztcbiAgfVxuXG4gIHN0YXRpYyBmbG9hdDY0VG9CeXRlcyhmKSB7XG4gICAgdmFyIGJ5dGVzID0gW107XG5cbiAgICB2YXIgYnVmID0gbmV3IEFycmF5QnVmZmVyKDgpO1xuICAgIG5ldyBGbG9hdDY0QXJyYXkoYnVmKVswXSA9IGY7XG5cbiAgICB2YXIgaW50VmVyc2lvbjEgPSBuZXcgVWludDMyQXJyYXkoYnVmKVswXTtcbiAgICB2YXIgaW50VmVyc2lvbjIgPSBuZXcgVWludDMyQXJyYXkoYnVmKVsxXTtcblxuICAgIGJ5dGVzLnB1c2goaW50VmVyc2lvbjIgPj4gMjQgJiAyNTUpO1xuICAgIGJ5dGVzLnB1c2goaW50VmVyc2lvbjIgPj4gMTYgJiAyNTUpO1xuICAgIGJ5dGVzLnB1c2goaW50VmVyc2lvbjIgPj4gOCAmIDI1NSk7XG4gICAgYnl0ZXMucHVzaChpbnRWZXJzaW9uMiAmIDI1NSk7XG5cbiAgICBieXRlcy5wdXNoKGludFZlcnNpb24xID4+IDI0ICYgMjU1KTtcbiAgICBieXRlcy5wdXNoKGludFZlcnNpb24xID4+IDE2ICYgMjU1KTtcbiAgICBieXRlcy5wdXNoKGludFZlcnNpb24xID4+IDggJiAyNTUpO1xuICAgIGJ5dGVzLnB1c2goaW50VmVyc2lvbjEgJiAyNTUpO1xuXG4gICAgcmV0dXJuIGJ5dGVzO1xuICB9XG59XG5cbi8qIEBmbG93ICovXG5cbmNsYXNzIFZhcmlhYmxlIHtcblxuICBjb25zdHJ1Y3RvcihuYW1lID0gbnVsbCkge1xuICAgIHRoaXMubmFtZSA9IG5hbWU7XG4gIH1cbn1cblxuY2xhc3MgV2lsZGNhcmQge1xuICBjb25zdHJ1Y3RvcigpIHt9XG59XG5cbmNsYXNzIFN0YXJ0c1dpdGgge1xuXG4gIGNvbnN0cnVjdG9yKHByZWZpeCkge1xuICAgIHRoaXMucHJlZml4ID0gcHJlZml4O1xuICB9XG59XG5cbmNsYXNzIENhcHR1cmUge1xuXG4gIGNvbnN0cnVjdG9yKHZhbHVlKSB7XG4gICAgdGhpcy52YWx1ZSA9IHZhbHVlO1xuICB9XG59XG5cbmNsYXNzIEhlYWRUYWlsIHtcbiAgY29uc3RydWN0b3IoKSB7fVxufVxuXG5jbGFzcyBUeXBlIHtcblxuICBjb25zdHJ1Y3Rvcih0eXBlLCBvYmpQYXR0ZXJuID0ge30pIHtcbiAgICB0aGlzLnR5cGUgPSB0eXBlO1xuICAgIHRoaXMub2JqUGF0dGVybiA9IG9ialBhdHRlcm47XG4gIH1cbn1cblxuY2xhc3MgQm91bmQge1xuXG4gIGNvbnN0cnVjdG9yKHZhbHVlKSB7XG4gICAgdGhpcy52YWx1ZSA9IHZhbHVlO1xuICB9XG59XG5cbmZ1bmN0aW9uIHZhcmlhYmxlKG5hbWUgPSBudWxsKSB7XG4gIHJldHVybiBuZXcgVmFyaWFibGUobmFtZSk7XG59XG5cbmZ1bmN0aW9uIHdpbGRjYXJkKCkge1xuICByZXR1cm4gbmV3IFdpbGRjYXJkKCk7XG59XG5cbmZ1bmN0aW9uIHN0YXJ0c1dpdGgocHJlZml4KSB7XG4gIHJldHVybiBuZXcgU3RhcnRzV2l0aChwcmVmaXgpO1xufVxuXG5mdW5jdGlvbiBjYXB0dXJlKHZhbHVlKSB7XG4gIHJldHVybiBuZXcgQ2FwdHVyZSh2YWx1ZSk7XG59XG5cbmZ1bmN0aW9uIGhlYWRUYWlsKCkge1xuICByZXR1cm4gbmV3IEhlYWRUYWlsKCk7XG59XG5cbmZ1bmN0aW9uIHR5cGUodHlwZSwgb2JqUGF0dGVybiA9IHt9KSB7XG4gIHJldHVybiBuZXcgVHlwZSh0eXBlLCBvYmpQYXR0ZXJuKTtcbn1cblxuZnVuY3Rpb24gYm91bmQodmFsdWUpIHtcbiAgcmV0dXJuIG5ldyBCb3VuZCh2YWx1ZSk7XG59XG5cbmZ1bmN0aW9uIGlzX251bWJlcih2YWx1ZSkge1xuICByZXR1cm4gdHlwZW9mIHZhbHVlID09PSAnbnVtYmVyJztcbn1cblxuZnVuY3Rpb24gaXNfc3RyaW5nKHZhbHVlKSB7XG4gIHJldHVybiB0eXBlb2YgdmFsdWUgPT09ICdzdHJpbmcnO1xufVxuXG5mdW5jdGlvbiBpc19ib29sZWFuKHZhbHVlKSB7XG4gIHJldHVybiB0eXBlb2YgdmFsdWUgPT09ICdib29sZWFuJztcbn1cblxuZnVuY3Rpb24gaXNfc3ltYm9sKHZhbHVlKSB7XG4gIHJldHVybiB0eXBlb2YgdmFsdWUgPT09ICdzeW1ib2wnO1xufVxuXG5mdW5jdGlvbiBpc19udWxsKHZhbHVlKSB7XG4gIHJldHVybiB2YWx1ZSA9PT0gbnVsbDtcbn1cblxuZnVuY3Rpb24gaXNfdW5kZWZpbmVkKHZhbHVlKSB7XG4gIHJldHVybiB0eXBlb2YgdmFsdWUgPT09ICd1bmRlZmluZWQnO1xufVxuXG5mdW5jdGlvbiBpc19mdW5jdGlvbih2YWx1ZSkge1xuICByZXR1cm4gT2JqZWN0LnByb3RvdHlwZS50b1N0cmluZy5jYWxsKHZhbHVlKSA9PSAnW29iamVjdCBGdW5jdGlvbl0nO1xufVxuXG5mdW5jdGlvbiBpc192YXJpYWJsZSh2YWx1ZSkge1xuICByZXR1cm4gdmFsdWUgaW5zdGFuY2VvZiBWYXJpYWJsZTtcbn1cblxuZnVuY3Rpb24gaXNfd2lsZGNhcmQodmFsdWUpIHtcbiAgcmV0dXJuIHZhbHVlIGluc3RhbmNlb2YgV2lsZGNhcmQ7XG59XG5cbmZ1bmN0aW9uIGlzX2hlYWRUYWlsKHZhbHVlKSB7XG4gIHJldHVybiB2YWx1ZSBpbnN0YW5jZW9mIEhlYWRUYWlsO1xufVxuXG5mdW5jdGlvbiBpc19jYXB0dXJlKHZhbHVlKSB7XG4gIHJldHVybiB2YWx1ZSBpbnN0YW5jZW9mIENhcHR1cmU7XG59XG5cbmZ1bmN0aW9uIGlzX3R5cGUodmFsdWUpIHtcbiAgcmV0dXJuIHZhbHVlIGluc3RhbmNlb2YgVHlwZTtcbn1cblxuZnVuY3Rpb24gaXNfc3RhcnRzV2l0aCh2YWx1ZSkge1xuICByZXR1cm4gdmFsdWUgaW5zdGFuY2VvZiBTdGFydHNXaXRoO1xufVxuXG5mdW5jdGlvbiBpc19ib3VuZCh2YWx1ZSkge1xuICByZXR1cm4gdmFsdWUgaW5zdGFuY2VvZiBCb3VuZDtcbn1cblxuZnVuY3Rpb24gaXNfb2JqZWN0KHZhbHVlKSB7XG4gIHJldHVybiB0eXBlb2YgdmFsdWUgPT09ICdvYmplY3QnO1xufVxuXG5mdW5jdGlvbiBpc19hcnJheSh2YWx1ZSkge1xuICByZXR1cm4gQXJyYXkuaXNBcnJheSh2YWx1ZSk7XG59XG5cbnZhciBDaGVja3MgPSB7XG4gIGlzX251bWJlcixcbiAgaXNfc3RyaW5nLFxuICBpc19ib29sZWFuLFxuICBpc19zeW1ib2wsXG4gIGlzX251bGwsXG4gIGlzX3VuZGVmaW5lZCxcbiAgaXNfZnVuY3Rpb24sXG4gIGlzX3ZhcmlhYmxlLFxuICBpc193aWxkY2FyZCxcbiAgaXNfaGVhZFRhaWwsXG4gIGlzX2NhcHR1cmUsXG4gIGlzX3R5cGUsXG4gIGlzX3N0YXJ0c1dpdGgsXG4gIGlzX2JvdW5kLFxuICBpc19vYmplY3QsXG4gIGlzX2FycmF5XG59O1xuXG5mdW5jdGlvbiByZXNvbHZlU3ltYm9sKHBhdHRlcm4pIHtcbiAgcmV0dXJuIGZ1bmN0aW9uICh2YWx1ZSkge1xuICAgIHJldHVybiBDaGVja3MuaXNfc3ltYm9sKHZhbHVlKSAmJiB2YWx1ZSA9PT0gcGF0dGVybjtcbiAgfTtcbn1cblxuZnVuY3Rpb24gcmVzb2x2ZVN0cmluZyhwYXR0ZXJuKSB7XG4gIHJldHVybiBmdW5jdGlvbiAodmFsdWUpIHtcbiAgICByZXR1cm4gQ2hlY2tzLmlzX3N0cmluZyh2YWx1ZSkgJiYgdmFsdWUgPT09IHBhdHRlcm47XG4gIH07XG59XG5cbmZ1bmN0aW9uIHJlc29sdmVOdW1iZXIocGF0dGVybikge1xuICByZXR1cm4gZnVuY3Rpb24gKHZhbHVlKSB7XG4gICAgcmV0dXJuIENoZWNrcy5pc19udW1iZXIodmFsdWUpICYmIHZhbHVlID09PSBwYXR0ZXJuO1xuICB9O1xufVxuXG5mdW5jdGlvbiByZXNvbHZlQm9vbGVhbihwYXR0ZXJuKSB7XG4gIHJldHVybiBmdW5jdGlvbiAodmFsdWUpIHtcbiAgICByZXR1cm4gQ2hlY2tzLmlzX2Jvb2xlYW4odmFsdWUpICYmIHZhbHVlID09PSBwYXR0ZXJuO1xuICB9O1xufVxuXG5mdW5jdGlvbiByZXNvbHZlRnVuY3Rpb24ocGF0dGVybikge1xuICByZXR1cm4gZnVuY3Rpb24gKHZhbHVlKSB7XG4gICAgcmV0dXJuIENoZWNrcy5pc19mdW5jdGlvbih2YWx1ZSkgJiYgdmFsdWUgPT09IHBhdHRlcm47XG4gIH07XG59XG5cbmZ1bmN0aW9uIHJlc29sdmVOdWxsKHBhdHRlcm4pIHtcbiAgcmV0dXJuIGZ1bmN0aW9uICh2YWx1ZSkge1xuICAgIHJldHVybiBDaGVja3MuaXNfbnVsbCh2YWx1ZSk7XG4gIH07XG59XG5cbmZ1bmN0aW9uIHJlc29sdmVCb3VuZChwYXR0ZXJuKSB7XG4gIHJldHVybiBmdW5jdGlvbiAodmFsdWUsIGFyZ3MpIHtcbiAgICBpZiAodHlwZW9mIHZhbHVlID09PSB0eXBlb2YgcGF0dGVybi52YWx1ZSAmJiB2YWx1ZSA9PT0gcGF0dGVybi52YWx1ZSkge1xuICAgICAgYXJncy5wdXNoKHZhbHVlKTtcbiAgICAgIHJldHVybiB0cnVlO1xuICAgIH1cblxuICAgIHJldHVybiBmYWxzZTtcbiAgfTtcbn1cblxuZnVuY3Rpb24gcmVzb2x2ZVdpbGRjYXJkKCkge1xuICByZXR1cm4gZnVuY3Rpb24gKCkge1xuICAgIHJldHVybiB0cnVlO1xuICB9O1xufVxuXG5mdW5jdGlvbiByZXNvbHZlVmFyaWFibGUoKSB7XG4gIHJldHVybiBmdW5jdGlvbiAodmFsdWUsIGFyZ3MpIHtcbiAgICBhcmdzLnB1c2godmFsdWUpO1xuICAgIHJldHVybiB0cnVlO1xuICB9O1xufVxuXG5mdW5jdGlvbiByZXNvbHZlSGVhZFRhaWwoKSB7XG4gIHJldHVybiBmdW5jdGlvbiAodmFsdWUsIGFyZ3MpIHtcbiAgICBpZiAoIUNoZWNrcy5pc19hcnJheSh2YWx1ZSkgfHwgdmFsdWUubGVuZ3RoIDwgMikge1xuICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH1cblxuICAgIGNvbnN0IGhlYWQgPSB2YWx1ZVswXTtcbiAgICBjb25zdCB0YWlsID0gdmFsdWUuc2xpY2UoMSk7XG5cbiAgICBhcmdzLnB1c2goaGVhZCk7XG4gICAgYXJncy5wdXNoKHRhaWwpO1xuXG4gICAgcmV0dXJuIHRydWU7XG4gIH07XG59XG5cbmZ1bmN0aW9uIHJlc29sdmVDYXB0dXJlKHBhdHRlcm4pIHtcbiAgY29uc3QgbWF0Y2hlcyA9IGJ1aWxkTWF0Y2gocGF0dGVybi52YWx1ZSk7XG5cbiAgcmV0dXJuIGZ1bmN0aW9uICh2YWx1ZSwgYXJncykge1xuICAgIGlmIChtYXRjaGVzKHZhbHVlLCBhcmdzKSkge1xuICAgICAgYXJncy5wdXNoKHZhbHVlKTtcbiAgICAgIHJldHVybiB0cnVlO1xuICAgIH1cblxuICAgIHJldHVybiBmYWxzZTtcbiAgfTtcbn1cblxuZnVuY3Rpb24gcmVzb2x2ZVN0YXJ0c1dpdGgocGF0dGVybikge1xuICBjb25zdCBwcmVmaXggPSBwYXR0ZXJuLnByZWZpeDtcblxuICByZXR1cm4gZnVuY3Rpb24gKHZhbHVlLCBhcmdzKSB7XG4gICAgaWYgKENoZWNrcy5pc19zdHJpbmcodmFsdWUpICYmIHZhbHVlLnN0YXJ0c1dpdGgocHJlZml4KSkge1xuICAgICAgYXJncy5wdXNoKHZhbHVlLnN1YnN0cmluZyhwcmVmaXgubGVuZ3RoKSk7XG4gICAgICByZXR1cm4gdHJ1ZTtcbiAgICB9XG5cbiAgICByZXR1cm4gZmFsc2U7XG4gIH07XG59XG5cbmZ1bmN0aW9uIHJlc29sdmVUeXBlKHBhdHRlcm4pIHtcbiAgcmV0dXJuIGZ1bmN0aW9uICh2YWx1ZSwgYXJncykge1xuICAgIGlmICh2YWx1ZSBpbnN0YW5jZW9mIHBhdHRlcm4udHlwZSkge1xuICAgICAgY29uc3QgbWF0Y2hlcyA9IGJ1aWxkTWF0Y2gocGF0dGVybi5vYmpQYXR0ZXJuKTtcbiAgICAgIHJldHVybiBtYXRjaGVzKHZhbHVlLCBhcmdzKSAmJiBhcmdzLnB1c2godmFsdWUpID4gMDtcbiAgICB9XG5cbiAgICByZXR1cm4gZmFsc2U7XG4gIH07XG59XG5cbmZ1bmN0aW9uIHJlc29sdmVBcnJheShwYXR0ZXJuKSB7XG4gIGNvbnN0IG1hdGNoZXMgPSBwYXR0ZXJuLm1hcCh4ID0+IGJ1aWxkTWF0Y2goeCkpO1xuXG4gIHJldHVybiBmdW5jdGlvbiAodmFsdWUsIGFyZ3MpIHtcbiAgICBpZiAoIUNoZWNrcy5pc19hcnJheSh2YWx1ZSkgfHwgdmFsdWUubGVuZ3RoICE9IHBhdHRlcm4ubGVuZ3RoKSB7XG4gICAgICByZXR1cm4gZmFsc2U7XG4gICAgfVxuXG4gICAgcmV0dXJuIHZhbHVlLmV2ZXJ5KGZ1bmN0aW9uICh2LCBpKSB7XG4gICAgICByZXR1cm4gbWF0Y2hlc1tpXSh2YWx1ZVtpXSwgYXJncyk7XG4gICAgfSk7XG4gIH07XG59XG5cbmZ1bmN0aW9uIHJlc29sdmVPYmplY3QocGF0dGVybikge1xuICBsZXQgbWF0Y2hlcyA9IHt9O1xuXG4gIGZvciAobGV0IGtleSBvZiBPYmplY3Qua2V5cyhwYXR0ZXJuKS5jb25jYXQoT2JqZWN0LmdldE93blByb3BlcnR5U3ltYm9scyhwYXR0ZXJuKSkpIHtcbiAgICBtYXRjaGVzW2tleV0gPSBidWlsZE1hdGNoKHBhdHRlcm5ba2V5XSk7XG4gIH1cblxuICByZXR1cm4gZnVuY3Rpb24gKHZhbHVlLCBhcmdzKSB7XG4gICAgaWYgKCFDaGVja3MuaXNfb2JqZWN0KHZhbHVlKSB8fCBwYXR0ZXJuLmxlbmd0aCA+IHZhbHVlLmxlbmd0aCkge1xuICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH1cblxuICAgIGZvciAobGV0IGtleSBvZiBPYmplY3Qua2V5cyhwYXR0ZXJuKS5jb25jYXQoT2JqZWN0LmdldE93blByb3BlcnR5U3ltYm9scyhwYXR0ZXJuKSkpIHtcbiAgICAgIGlmICghKGtleSBpbiB2YWx1ZSkgfHwgIW1hdGNoZXNba2V5XSh2YWx1ZVtrZXldLCBhcmdzKSkge1xuICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICB9XG4gICAgfVxuXG4gICAgcmV0dXJuIHRydWU7XG4gIH07XG59XG5cbmZ1bmN0aW9uIHJlc29sdmVOb01hdGNoKCkge1xuICByZXR1cm4gZnVuY3Rpb24gKCkge1xuICAgIHJldHVybiBmYWxzZTtcbiAgfTtcbn1cblxudmFyIFJlc29sdmVycyA9IHtcbiAgcmVzb2x2ZUJvdW5kLFxuICByZXNvbHZlV2lsZGNhcmQsXG4gIHJlc29sdmVWYXJpYWJsZSxcbiAgcmVzb2x2ZUhlYWRUYWlsLFxuICByZXNvbHZlQ2FwdHVyZSxcbiAgcmVzb2x2ZVN0YXJ0c1dpdGgsXG4gIHJlc29sdmVUeXBlLFxuICByZXNvbHZlQXJyYXksXG4gIHJlc29sdmVPYmplY3QsXG4gIHJlc29sdmVOb01hdGNoLFxuICByZXNvbHZlU3ltYm9sLFxuICByZXNvbHZlU3RyaW5nLFxuICByZXNvbHZlTnVtYmVyLFxuICByZXNvbHZlQm9vbGVhbixcbiAgcmVzb2x2ZUZ1bmN0aW9uLFxuICByZXNvbHZlTnVsbFxufTtcblxuZnVuY3Rpb24gYnVpbGRNYXRjaChwYXR0ZXJuKSB7XG5cbiAgaWYgKENoZWNrcy5pc192YXJpYWJsZShwYXR0ZXJuKSkge1xuICAgIHJldHVybiBSZXNvbHZlcnMucmVzb2x2ZVZhcmlhYmxlKHBhdHRlcm4pO1xuICB9XG5cbiAgaWYgKENoZWNrcy5pc193aWxkY2FyZChwYXR0ZXJuKSkge1xuICAgIHJldHVybiBSZXNvbHZlcnMucmVzb2x2ZVdpbGRjYXJkKHBhdHRlcm4pO1xuICB9XG5cbiAgaWYgKENoZWNrcy5pc191bmRlZmluZWQocGF0dGVybikpIHtcbiAgICByZXR1cm4gUmVzb2x2ZXJzLnJlc29sdmVXaWxkY2FyZChwYXR0ZXJuKTtcbiAgfVxuXG4gIGlmIChDaGVja3MuaXNfaGVhZFRhaWwocGF0dGVybikpIHtcbiAgICByZXR1cm4gUmVzb2x2ZXJzLnJlc29sdmVIZWFkVGFpbChwYXR0ZXJuKTtcbiAgfVxuXG4gIGlmIChDaGVja3MuaXNfc3RhcnRzV2l0aChwYXR0ZXJuKSkge1xuICAgIHJldHVybiBSZXNvbHZlcnMucmVzb2x2ZVN0YXJ0c1dpdGgocGF0dGVybik7XG4gIH1cblxuICBpZiAoQ2hlY2tzLmlzX2NhcHR1cmUocGF0dGVybikpIHtcbiAgICByZXR1cm4gUmVzb2x2ZXJzLnJlc29sdmVDYXB0dXJlKHBhdHRlcm4pO1xuICB9XG5cbiAgaWYgKENoZWNrcy5pc19ib3VuZChwYXR0ZXJuKSkge1xuICAgIHJldHVybiBSZXNvbHZlcnMucmVzb2x2ZUJvdW5kKHBhdHRlcm4pO1xuICB9XG5cbiAgaWYgKENoZWNrcy5pc190eXBlKHBhdHRlcm4pKSB7XG4gICAgcmV0dXJuIFJlc29sdmVycy5yZXNvbHZlVHlwZShwYXR0ZXJuKTtcbiAgfVxuXG4gIGlmIChDaGVja3MuaXNfYXJyYXkocGF0dGVybikpIHtcbiAgICByZXR1cm4gUmVzb2x2ZXJzLnJlc29sdmVBcnJheShwYXR0ZXJuKTtcbiAgfVxuXG4gIGlmIChDaGVja3MuaXNfbnVtYmVyKHBhdHRlcm4pKSB7XG4gICAgcmV0dXJuIFJlc29sdmVycy5yZXNvbHZlTnVtYmVyKHBhdHRlcm4pO1xuICB9XG5cbiAgaWYgKENoZWNrcy5pc19zdHJpbmcocGF0dGVybikpIHtcbiAgICByZXR1cm4gUmVzb2x2ZXJzLnJlc29sdmVTdHJpbmcocGF0dGVybik7XG4gIH1cblxuICBpZiAoQ2hlY2tzLmlzX2Jvb2xlYW4ocGF0dGVybikpIHtcbiAgICByZXR1cm4gUmVzb2x2ZXJzLnJlc29sdmVCb29sZWFuKHBhdHRlcm4pO1xuICB9XG5cbiAgaWYgKENoZWNrcy5pc19zeW1ib2wocGF0dGVybikpIHtcbiAgICByZXR1cm4gUmVzb2x2ZXJzLnJlc29sdmVTeW1ib2wocGF0dGVybik7XG4gIH1cblxuICBpZiAoQ2hlY2tzLmlzX251bGwocGF0dGVybikpIHtcbiAgICByZXR1cm4gUmVzb2x2ZXJzLnJlc29sdmVOdWxsKHBhdHRlcm4pO1xuICB9XG5cbiAgaWYgKENoZWNrcy5pc19vYmplY3QocGF0dGVybikpIHtcbiAgICByZXR1cm4gUmVzb2x2ZXJzLnJlc29sdmVPYmplY3QocGF0dGVybik7XG4gIH1cblxuICByZXR1cm4gUmVzb2x2ZXJzLnJlc29sdmVOb01hdGNoKCk7XG59XG5cbmNsYXNzIE1hdGNoRXJyb3IgZXh0ZW5kcyBFcnJvciB7XG4gIGNvbnN0cnVjdG9yKGFyZykge1xuICAgIHN1cGVyKCk7XG5cbiAgICBpZiAodHlwZW9mIGFyZyA9PT0gJ3N5bWJvbCcpIHtcbiAgICAgIHRoaXMubWVzc2FnZSA9ICdObyBtYXRjaCBmb3I6ICcgKyBhcmcudG9TdHJpbmcoKTtcbiAgICB9IGVsc2UgaWYgKEFycmF5LmlzQXJyYXkoYXJnKSkge1xuICAgICAgbGV0IG1hcHBlZFZhbHVlcyA9IGFyZy5tYXAoeCA9PiB4LnRvU3RyaW5nKCkpO1xuICAgICAgdGhpcy5tZXNzYWdlID0gJ05vIG1hdGNoIGZvcjogJyArIG1hcHBlZFZhbHVlcztcbiAgICB9IGVsc2Uge1xuICAgICAgdGhpcy5tZXNzYWdlID0gJ05vIG1hdGNoIGZvcjogJyArIGFyZztcbiAgICB9XG5cbiAgICB0aGlzLnN0YWNrID0gbmV3IEVycm9yKCkuc3RhY2s7XG4gICAgdGhpcy5uYW1lID0gdGhpcy5jb25zdHJ1Y3Rvci5uYW1lO1xuICB9XG59XG5cbmNsYXNzIENhc2Uge1xuXG4gIGNvbnN0cnVjdG9yKHBhdHRlcm4sIGZuLCBndWFyZCA9ICgpID0+IHRydWUpIHtcbiAgICB0aGlzLnBhdHRlcm4gPSBidWlsZE1hdGNoKHBhdHRlcm4pO1xuICAgIHRoaXMuZm4gPSBmbjtcbiAgICB0aGlzLmd1YXJkID0gZ3VhcmQ7XG4gIH1cbn1cblxuZnVuY3Rpb24gbWFrZV9jYXNlKHBhdHRlcm4sIGZuLCBndWFyZCA9ICgpID0+IHRydWUpIHtcbiAgcmV0dXJuIG5ldyBDYXNlKHBhdHRlcm4sIGZuLCBndWFyZCk7XG59XG5cbmZ1bmN0aW9uIGRlZm1hdGNoKC4uLmNhc2VzKSB7XG4gIHJldHVybiBmdW5jdGlvbiAoLi4uYXJncykge1xuICAgIGZvciAobGV0IHByb2Nlc3NlZENhc2Ugb2YgY2FzZXMpIHtcbiAgICAgIGxldCByZXN1bHQgPSBbXTtcbiAgICAgIGlmIChwcm9jZXNzZWRDYXNlLnBhdHRlcm4oYXJncywgcmVzdWx0KSAmJiBwcm9jZXNzZWRDYXNlLmd1YXJkLmFwcGx5KHRoaXMsIHJlc3VsdCkpIHtcbiAgICAgICAgcmV0dXJuIHByb2Nlc3NlZENhc2UuZm4uYXBwbHkodGhpcywgcmVzdWx0KTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICB0aHJvdyBuZXcgTWF0Y2hFcnJvcihhcmdzKTtcbiAgfTtcbn1cblxuZnVuY3Rpb24gbWF0Y2gocGF0dGVybiwgZXhwciwgZ3VhcmQgPSAoKSA9PiB0cnVlKSB7XG4gIGxldCByZXN1bHQgPSBbXTtcbiAgbGV0IHByb2Nlc3NlZFBhdHRlcm4gPSBidWlsZE1hdGNoKHBhdHRlcm4pO1xuICBpZiAocHJvY2Vzc2VkUGF0dGVybihleHByLCByZXN1bHQpICYmIGd1YXJkLmFwcGx5KHRoaXMsIHJlc3VsdCkpIHtcbiAgICByZXR1cm4gcmVzdWx0O1xuICB9IGVsc2Uge1xuICAgIHRocm93IG5ldyBNYXRjaEVycm9yKGV4cHIpO1xuICB9XG59XG5cbmZ1bmN0aW9uIG1hdGNoX25vX3Rocm93KHBhdHRlcm4sIGV4cHIsIGd1YXJkID0gKCkgPT4gdHJ1ZSkge1xuICB0cnkge1xuICAgIHJldHVybiBtYXRjaChwYXR0ZXJuLCBleHByLCBndWFyZCk7XG4gIH0gY2F0Y2ggKGUpIHtcbiAgICBpZiAoZSBpbnN0YW5jZW9mIE1hdGNoRXJyb3IpIHtcbiAgICAgIHJldHVybiBudWxsO1xuICAgIH1cblxuICAgIHRocm93IGU7XG4gIH1cbn1cblxudmFyIFBhdHRlcm5zID0ge1xuICBkZWZtYXRjaCwgbWF0Y2gsIE1hdGNoRXJyb3IsIG1hdGNoX25vX3Rocm93LFxuICB2YXJpYWJsZSwgd2lsZGNhcmQsIHN0YXJ0c1dpdGgsXG4gIGNhcHR1cmUsIGhlYWRUYWlsLCB0eXBlLCBib3VuZCwgQ2FzZSwgbWFrZV9jYXNlXG59O1xuXG4vL2h0dHBzOi8vZ2l0aHViLmNvbS9haXJwb3J0eWgvcHJvdG9tb3JwaGlzbVxuY2xhc3MgUHJvdG9jb2wge1xuICBjb25zdHJ1Y3RvcihzcGVjKSB7XG4gICAgdGhpcy5yZWdpc3RyeSA9IG5ldyBNYXAoKTtcbiAgICB0aGlzLmZhbGxiYWNrID0gbnVsbDtcblxuICAgIGZvciAobGV0IGZ1bk5hbWUgaW4gc3BlYykge1xuICAgICAgdGhpc1tmdW5OYW1lXSA9IGNyZWF0ZUZ1bihmdW5OYW1lKS5iaW5kKHRoaXMpO1xuICAgIH1cblxuICAgIGZ1bmN0aW9uIGNyZWF0ZUZ1bihmdW5OYW1lKSB7XG5cbiAgICAgIHJldHVybiBmdW5jdGlvbiAoLi4uYXJncykge1xuICAgICAgICBsZXQgdGhpbmcgPSBhcmdzWzBdO1xuICAgICAgICBsZXQgZnVuID0gbnVsbDtcblxuICAgICAgICBpZiAoTnVtYmVyLmlzSW50ZWdlcih0aGluZykgJiYgdGhpcy5oYXNJbXBsZW1lbnRhdGlvbihJbnRlZ2VyKSkge1xuICAgICAgICAgIGZ1biA9IHRoaXMucmVnaXN0cnkuZ2V0KENvcmUuSW50ZWdlcilbZnVuTmFtZV07XG4gICAgICAgIH0gZWxzZSBpZiAodHlwZW9mIHRoaW5nID09PSBcIm51bWJlclwiICYmICFOdW1iZXIuaXNJbnRlZ2VyKHRoaW5nKSAmJiB0aGlzLmhhc0ltcGxlbWVudGF0aW9uKEZsb2F0KSkge1xuICAgICAgICAgIGZ1biA9IHRoaXMucmVnaXN0cnkuZ2V0KENvcmUuRmxvYXQpW2Z1bk5hbWVdO1xuICAgICAgICB9IGVsc2UgaWYgKHRoaXMuaGFzSW1wbGVtZW50YXRpb24odGhpbmcpKSB7XG4gICAgICAgICAgZnVuID0gdGhpcy5yZWdpc3RyeS5nZXQodGhpbmcuY29uc3RydWN0b3IpW2Z1bk5hbWVdO1xuICAgICAgICB9IGVsc2UgaWYgKHRoaXMuZmFsbGJhY2spIHtcbiAgICAgICAgICBmdW4gPSB0aGlzLmZhbGxiYWNrW2Z1bk5hbWVdO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKGZ1biAhPSBudWxsKSB7XG4gICAgICAgICAgbGV0IHJldHZhbCA9IGZ1bi5hcHBseSh0aGlzLCBhcmdzKTtcbiAgICAgICAgICByZXR1cm4gcmV0dmFsO1xuICAgICAgICB9XG5cbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKFwiTm8gaW1wbGVtZW50YXRpb24gZm91bmQgZm9yIFwiICsgdGhpbmcpO1xuICAgICAgfTtcbiAgICB9XG4gIH1cblxuICBpbXBsZW1lbnRhdGlvbih0eXBlLCBpbXBsZW1lbnRhdGlvbikge1xuICAgIGlmICh0eXBlID09PSBudWxsKSB7XG4gICAgICB0aGlzLmZhbGxiYWNrID0gaW1wbGVtZW50YXRpb247XG4gICAgfSBlbHNlIHtcbiAgICAgIHRoaXMucmVnaXN0cnkuc2V0KHR5cGUsIGltcGxlbWVudGF0aW9uKTtcbiAgICB9XG4gIH1cblxuICBoYXNJbXBsZW1lbnRhdGlvbih0aGluZykge1xuICAgIHJldHVybiB0aGlzLnJlZ2lzdHJ5Lmhhcyh0aGluZy5jb25zdHJ1Y3Rvcik7XG4gIH1cbn1cblxuZnVuY3Rpb24gY2FsbF9wcm9wZXJ0eShpdGVtLCBwcm9wZXJ0eSkge1xuICBsZXQgcHJvcCA9IG51bGw7XG5cbiAgaWYgKHByb3BlcnR5IGluIGl0ZW0pIHtcbiAgICBwcm9wID0gcHJvcGVydHk7XG4gIH0gZWxzZSBpZiAoU3ltYm9sLmZvcihwcm9wZXJ0eSkgaW4gaXRlbSkge1xuICAgIHByb3AgPSBTeW1ib2wuZm9yKHByb3BlcnR5KTtcbiAgfSBlbHNlIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoYFByb3BlcnR5ICR7IHByb3BlcnR5IH0gbm90IGZvdW5kIGluICR7IGl0ZW0gfWApO1xuICB9XG5cbiAgaWYgKGl0ZW1bcHJvcF0gaW5zdGFuY2VvZiBGdW5jdGlvbikge1xuICAgIHJldHVybiBpdGVtW3Byb3BdKCk7XG4gIH0gZWxzZSB7XG4gICAgcmV0dXJuIGl0ZW1bcHJvcF07XG4gIH1cbn1cblxuZnVuY3Rpb24gYXBwbHkoLi4uYXJncykge1xuICBpZiAoYXJncy5sZW5ndGggPT09IDIpIHtcbiAgICBhcmdzWzBdLmFwcGx5KG51bGwsIGFyZ3Muc2xpY2UoMSkpO1xuICB9IGVsc2Uge1xuICAgIGFyZ3NbMF1bYXJnc1sxXV0uYXBwbHkobnVsbCwgYXJncy5zbGljZSgyKSk7XG4gIH1cbn1cblxuZnVuY3Rpb24gY29udGFpbnMobGVmdCwgcmlnaHQpIHtcbiAgZm9yIChsZXQgeCBvZiByaWdodCkge1xuICAgIGlmIChQYXR0ZXJucy5tYXRjaF9ub190aHJvdyhsZWZ0LCB4KSAhPSBudWxsKSB7XG4gICAgICByZXR1cm4gdHJ1ZTtcbiAgICB9XG4gIH1cblxuICByZXR1cm4gZmFsc2U7XG59XG5cbmZ1bmN0aW9uIGdldF9nbG9iYWwoKSB7XG4gIGlmICh0eXBlb2Ygc2VsZiAhPT0gJ3VuZGVmaW5lZCcpIHtcbiAgICByZXR1cm4gc2VsZjtcbiAgfSBlbHNlIGlmICh0eXBlb2Ygd2luZG93ICE9PSAndW5kZWZpbmVkJykge1xuICAgIHJldHVybiB3aW5kb3c7XG4gIH0gZWxzZSBpZiAodHlwZW9mIGdsb2JhbCAhPT0gJ3VuZGVmaW5lZCcpIHtcbiAgICByZXR1cm4gZ2xvYmFsO1xuICB9XG5cbiAgdGhyb3cgbmV3IEVycm9yKCdObyBnbG9iYWwgc3RhdGUgZm91bmQnKTtcbn1cblxuZnVuY3Rpb24gZGVmc3RydWN0KGRlZmF1bHRzKSB7XG4gIHJldHVybiBjbGFzcyB7XG4gICAgY29uc3RydWN0b3IodXBkYXRlID0ge30pIHtcbiAgICAgIGxldCB0aGVfdmFsdWVzID0gT2JqZWN0LmFzc2lnbihkZWZhdWx0cywgdXBkYXRlKTtcbiAgICAgIE9iamVjdC5hc3NpZ24odGhpcywgdGhlX3ZhbHVlcyk7XG4gICAgfVxuXG4gICAgc3RhdGljIGNyZWF0ZSh1cGRhdGVzID0ge30pIHtcbiAgICAgIGxldCB4ID0gbmV3IHRoaXModXBkYXRlcyk7XG4gICAgICByZXR1cm4gT2JqZWN0LmZyZWV6ZSh4KTtcbiAgICB9XG4gIH07XG59XG5cbmZ1bmN0aW9uIGRlZmV4Y2VwdGlvbihkZWZhdWx0cykge1xuICByZXR1cm4gY2xhc3MgZXh0ZW5kcyBFcnJvciB7XG4gICAgY29uc3RydWN0b3IodXBkYXRlID0ge30pIHtcbiAgICAgIGxldCBtZXNzYWdlID0gdXBkYXRlLm1lc3NhZ2UgfHwgJyc7XG4gICAgICBzdXBlcihtZXNzYWdlKTtcblxuICAgICAgbGV0IHRoZV92YWx1ZXMgPSBPYmplY3QuYXNzaWduKGRlZmF1bHRzLCB1cGRhdGUpO1xuICAgICAgT2JqZWN0LmFzc2lnbih0aGlzLCB0aGVfdmFsdWVzKTtcblxuICAgICAgdGhpcy5uYW1lID0gdGhpcy5jb25zdHJ1Y3Rvci5uYW1lO1xuICAgICAgdGhpcy5tZXNzYWdlID0gbWVzc2FnZTtcbiAgICAgIHRoaXNbU3BlY2lhbEZvcm1zLmF0b20oJ19fZXhjZXB0aW9uX18nKV0gPSB0cnVlO1xuICAgICAgRXJyb3IuY2FwdHVyZVN0YWNrVHJhY2UodGhpcywgdGhpcy5jb25zdHJ1Y3Rvci5uYW1lKTtcbiAgICB9XG5cbiAgICBzdGF0aWMgY3JlYXRlKHVwZGF0ZXMgPSB7fSkge1xuICAgICAgbGV0IHggPSBuZXcgdGhpcyh1cGRhdGVzKTtcbiAgICAgIHJldHVybiBPYmplY3QuZnJlZXplKHgpO1xuICAgIH1cbiAgfTtcbn1cblxuZnVuY3Rpb24gZGVmcHJvdG9jb2woc3BlYykge1xuICByZXR1cm4gbmV3IFByb3RvY29sKHNwZWMpO1xufVxuXG5mdW5jdGlvbiBkZWZpbXBsKHByb3RvY29sLCB0eXBlLCBpbXBsKSB7XG4gIHByb3RvY29sLmltcGxlbWVudGF0aW9uKHR5cGUsIGltcGwpO1xufVxuXG5mdW5jdGlvbiBnZXRfb2JqZWN0X2tleXMob2JqKSB7XG4gIHJldHVybiBPYmplY3Qua2V5cyhvYmopLmNvbmNhdChPYmplY3QuZ2V0T3duUHJvcGVydHlTeW1ib2xzKG9iaikpO1xufVxuXG5mdW5jdGlvbiBpc192YWxpZF9jaGFyYWN0ZXIoY29kZXBvaW50KSB7XG4gIHRyeSB7XG4gICAgcmV0dXJuIFN0cmluZy5mcm9tQ29kZVBvaW50KGNvZGVwb2ludCkgIT0gbnVsbDtcbiAgfSBjYXRjaCAoZSkge1xuICAgIHJldHVybiBmYWxzZTtcbiAgfVxufVxuXG4vL2h0dHBzOi8vZGV2ZWxvcGVyLm1vemlsbGEub3JnL2VuLVVTL2RvY3MvV2ViL0FQSS9XaW5kb3dCYXNlNjQvQmFzZTY0X2VuY29kaW5nX2FuZF9kZWNvZGluZyNTb2x1dGlvbl8yXyVFMiU4MCU5M19yZXdyaXRlX3RoZV9ET01zX2F0b2IoKV9hbmRfYnRvYSgpX3VzaW5nX0phdmFTY3JpcHQnc19UeXBlZEFycmF5c19hbmRfVVRGLThcbmZ1bmN0aW9uIGI2NEVuY29kZVVuaWNvZGUoc3RyKSB7XG4gIHJldHVybiBidG9hKGVuY29kZVVSSUNvbXBvbmVudChzdHIpLnJlcGxhY2UoLyUoWzAtOUEtRl17Mn0pL2csIGZ1bmN0aW9uIChtYXRjaCwgcDEpIHtcbiAgICByZXR1cm4gU3RyaW5nLmZyb21DaGFyQ29kZSgnMHgnICsgcDEpO1xuICB9KSk7XG59XG5cbmZ1bmN0aW9uIGRlbGV0ZV9wcm9wZXJ0eV9mcm9tX21hcChtYXAsIHByb3BlcnR5KSB7XG4gIGxldCBuZXdfbWFwID0gT2JqZWN0LmFzc2lnbihPYmplY3QuY3JlYXRlKG1hcC5jb25zdHJ1Y3Rvci5wcm90b3R5cGUpLCBtYXApO1xuICBkZWxldGUgbmV3X21hcFtwcm9wZXJ0eV07XG5cbiAgcmV0dXJuIE9iamVjdC5mcmVlemUobmV3X21hcCk7XG59XG5cbmZ1bmN0aW9uIGNsYXNzX3RvX29iaihtYXApIHtcbiAgbGV0IG5ld19tYXAgPSBPYmplY3QuYXNzaWduKHt9LCBtYXApO1xuICByZXR1cm4gT2JqZWN0LmZyZWV6ZShuZXdfbWFwKTtcbn1cblxuZnVuY3Rpb24gYWRkX3Byb3BlcnR5X3RvX21hcChtYXAsIHByb3BlcnR5LCB2YWx1ZSkge1xuICBsZXQgbmV3X21hcCA9IE9iamVjdC5hc3NpZ24oe30sIG1hcCk7XG4gIG5ld19tYXBbcHJvcGVydHldID0gdmFsdWU7XG4gIHJldHVybiBPYmplY3QuZnJlZXplKG5ld19tYXApO1xufVxuXG5mdW5jdGlvbiB1cGRhdGVfbWFwKG1hcCwgcHJvcGVydHksIHZhbHVlKSB7XG4gIGlmIChwcm9wZXJ0eSBpbiBnZXRfb2JqZWN0X2tleXMobWFwKSkge1xuICAgIHJldHVybiBhZGRfcHJvcGVydHlfdG9fbWFwKG1hcCwgcHJvcGVydHksIHZhbHVlKTtcbiAgfVxuXG4gIHRocm93ICdtYXAgZG9lcyBub3QgaGF2ZSBrZXknO1xufVxuXG5mdW5jdGlvbiBibm90KGV4cHIpIHtcbiAgcmV0dXJuIH5leHByO1xufVxuXG5mdW5jdGlvbiBiYW5kKGxlZnQsIHJpZ2h0KSB7XG4gIHJldHVybiBsZWZ0ICYgcmlnaHQ7XG59XG5cbmZ1bmN0aW9uIGJvcihsZWZ0LCByaWdodCkge1xuICByZXR1cm4gbGVmdCB8IHJpZ2h0O1xufVxuXG5mdW5jdGlvbiBic2wobGVmdCwgcmlnaHQpIHtcbiAgcmV0dXJuIGxlZnQgPDwgcmlnaHQ7XG59XG5cbmZ1bmN0aW9uIGJzcihsZWZ0LCByaWdodCkge1xuICByZXR1cm4gbGVmdCA+PiByaWdodDtcbn1cblxuZnVuY3Rpb24gYnhvcihsZWZ0LCByaWdodCkge1xuICByZXR1cm4gbGVmdCBeIHJpZ2h0O1xufVxuXG5mdW5jdGlvbiB6aXAobGlzdF9vZl9saXN0cykge1xuICBpZiAobGlzdF9vZl9saXN0cy5sZW5ndGggPT09IDApIHtcbiAgICByZXR1cm4gT2JqZWN0LmZyZWV6ZShbXSk7XG4gIH1cblxuICBsZXQgbmV3X3ZhbHVlID0gW107XG4gIGxldCBzbWFsbGVzdF9sZW5ndGggPSBsaXN0X29mX2xpc3RzWzBdO1xuXG4gIGZvciAobGV0IHggb2YgbGlzdF9vZl9saXN0cykge1xuICAgIGlmICh4Lmxlbmd0aCA8IHNtYWxsZXN0X2xlbmd0aCkge1xuICAgICAgc21hbGxlc3RfbGVuZ3RoID0geC5sZW5ndGg7XG4gICAgfVxuICB9XG5cbiAgZm9yIChsZXQgaSA9IDA7IGkgPCBzbWFsbGVzdF9sZW5ndGg7IGkrKykge1xuICAgIGxldCBjdXJyZW50X3ZhbHVlID0gW107XG4gICAgZm9yIChsZXQgaiA9IDA7IGogPCBsaXN0X29mX2xpc3RzLmxlbmd0aDsgaisrKSB7XG4gICAgICBjdXJyZW50X3ZhbHVlLnB1c2gobGlzdF9vZl9saXN0c1tqXVtpXSk7XG4gICAgfVxuXG4gICAgbmV3X3ZhbHVlLnB1c2gobmV3IFR1cGxlKC4uLmN1cnJlbnRfdmFsdWUpKTtcbiAgfVxuXG4gIHJldHVybiBPYmplY3QuZnJlZXplKG5ld192YWx1ZSk7XG59XG5cbmZ1bmN0aW9uIGNhbl9kZWNvZGU2NChkYXRhKSB7XG4gIHRyeSB7XG4gICAgYXRvYihkYXRhKTtcbiAgICByZXR1cm4gdHJ1ZTtcbiAgfSBjYXRjaCAoZSkge1xuICAgIHJldHVybiBmYWxzZTtcbiAgfVxufVxuXG5mdW5jdGlvbiByZW1vdmVfZnJvbV9saXN0KGxpc3QsIGVsZW1lbnQpIHtcbiAgbGV0IGZvdW5kID0gZmFsc2U7XG5cbiAgcmV0dXJuIGxpc3QuZmlsdGVyKGVsZW0gPT4ge1xuICAgIGlmICghZm91bmQgJiYgZWxlbSA9PT0gZWxlbWVudCkge1xuICAgICAgZm91bmQgPSB0cnVlO1xuICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH1cblxuICAgIHJldHVybiB0cnVlO1xuICB9KTtcbn1cblxuZnVuY3Rpb24gZm9sZGwoZnVuLCBhY2MsIGxpc3QpIHtcbiAgbGV0IGFjYzEgPSBhY2M7XG5cbiAgZm9yIChjb25zdCBlbCBvZiBsaXN0KSB7XG4gICAgYWNjMSA9IGZ1bihlbCwgYWNjMSk7XG4gIH1cblxuICByZXR1cm4gYWNjMTtcbn1cblxuZnVuY3Rpb24gZm9sZHIoZnVuLCBhY2MsIGxpc3QpIHtcbiAgbGV0IGFjYzEgPSBhY2M7XG5cbiAgZm9yIChsZXQgaSA9IGxpc3QubGVuZ3RoIC0gMTsgaSA+PSAwOyBpLS0pIHtcbiAgICBhY2MxID0gZnVuKGxpc3RbaV0sIGFjYzEpO1xuICB9XG5cbiAgcmV0dXJuIGFjYzE7XG59XG5cbmZ1bmN0aW9uIGtleWRlbGV0ZShrZXksIG4sIHR1cGxlbGlzdCkge1xuXG4gIGZvciAobGV0IGkgPSB0dXBsZWxpc3QubGVuZ3RoIC0gMTsgaSA+PSAwOyBpLS0pIHtcbiAgICBpZiAodHVwbGVsaXN0W2ldLmdldChuKSA9PT0ga2V5KSB7XG4gICAgICByZXR1cm4gdHVwbGVsaXN0LmNvbmNhdChbXSkuc3BsaWNlKGksIDEpO1xuICAgIH1cbiAgfVxuXG4gIHJldHVybiB0dXBsZWxpc3Q7XG59XG5cbmZ1bmN0aW9uIGtleXN0b3JlKGtleSwgbiwgbGlzdCwgbmV3dHVwbGUpIHtcbiAgZm9yIChsZXQgaSA9IGxpc3QubGVuZ3RoIC0gMTsgaSA+PSAwOyBpLS0pIHtcbiAgICBpZiAobGlzdFtpXS5nZXQobikgPT09IGtleSkge1xuICAgICAgcmV0dXJuIGxpc3QuY29uY2F0KFtdKS5zcGxpY2UoaSwgMSwgbmV3dHVwbGUpO1xuICAgIH1cbiAgfVxuXG4gIHJldHVybiBsaXN0O1xufVxuXG5mdW5jdGlvbiByZXZlcnNlKGxpc3QpIHtcbiAgcmV0dXJuIGxpc3QuY29uY2F0KFtdKS5yZXZlcnNlKCk7XG59XG5cbmZ1bmN0aW9uIG1hcHNfZmluZChrZXksIG1hcCkge1xuICBpZiAoa2V5IGluIGdldF9vYmplY3Rfa2V5cyhtYXApKSB7XG4gICAgcmV0dXJuIG5ldyBUdXBsZShTeW1ib2wuZm9yKCdvaycpLCBtYXBba2V5XSk7XG4gIH0gZWxzZSB7XG4gICAgcmV0dXJuIFN5bWJvbC5mb3IoJ2Vycm9yJyk7XG4gIH1cbn1cblxudmFyIEZ1bmN0aW9ucyA9IHtcbiAgY2FsbF9wcm9wZXJ0eSxcbiAgYXBwbHksXG4gIGNvbnRhaW5zLFxuICBnZXRfZ2xvYmFsLFxuICBkZWZzdHJ1Y3QsXG4gIGRlZmV4Y2VwdGlvbixcbiAgZGVmcHJvdG9jb2wsXG4gIGRlZmltcGwsXG4gIGdldF9vYmplY3Rfa2V5cyxcbiAgaXNfdmFsaWRfY2hhcmFjdGVyLFxuICBiNjRFbmNvZGVVbmljb2RlLFxuICBkZWxldGVfcHJvcGVydHlfZnJvbV9tYXAsXG4gIGFkZF9wcm9wZXJ0eV90b19tYXAsXG4gIGNsYXNzX3RvX29iaixcbiAgY2FuX2RlY29kZTY0LFxuICBibm90LFxuICBiYW5kLFxuICBib3IsXG4gIGJzbCxcbiAgYnNyLFxuICBieG9yLFxuICB6aXAsXG4gIGZvbGRsLFxuICBmb2xkcixcbiAgcmVtb3ZlX2Zyb21fbGlzdCxcbiAga2V5ZGVsZXRlLFxuICBrZXlzdG9yZSxcbiAgcmV2ZXJzZSxcbiAgdXBkYXRlX21hcCxcbiAgbWFwc19maW5kXG59O1xuXG5mdW5jdGlvbiBfY2FzZShjb25kaXRpb24sIGNsYXVzZXMpIHtcbiAgcmV0dXJuIFBhdHRlcm5zLmRlZm1hdGNoKC4uLmNsYXVzZXMpKGNvbmRpdGlvbik7XG59XG5cbmZ1bmN0aW9uIGNvbmQoY2xhdXNlcykge1xuICBmb3IgKGxldCBjbGF1c2Ugb2YgY2xhdXNlcykge1xuICAgIGlmIChjbGF1c2VbMF0pIHtcbiAgICAgIHJldHVybiBjbGF1c2VbMV0oKTtcbiAgICB9XG4gIH1cblxuICB0aHJvdyBuZXcgRXJyb3IoKTtcbn1cblxuZnVuY3Rpb24gbWFwX3VwZGF0ZShtYXAsIHZhbHVlcykge1xuICByZXR1cm4gT2JqZWN0LmZyZWV6ZShPYmplY3QuYXNzaWduKE9iamVjdC5jcmVhdGUobWFwLmNvbnN0cnVjdG9yLnByb3RvdHlwZSksIG1hcCwgdmFsdWVzKSk7XG59XG5cbmZ1bmN0aW9uIF9mb3IoY29sbGVjdGlvbnMsIGZ1biwgZmlsdGVyID0gKCkgPT4gdHJ1ZSwgaW50byA9IFtdLCBwcmV2aW91c1ZhbHVlcyA9IFtdKSB7XG4gIGxldCBwYXR0ZXJuID0gY29sbGVjdGlvbnNbMF1bMF07XG4gIGxldCBjb2xsZWN0aW9uID0gY29sbGVjdGlvbnNbMF1bMV07XG5cbiAgaWYgKGNvbGxlY3Rpb25zLmxlbmd0aCA9PT0gMSkge1xuXG4gICAgZm9yIChsZXQgZWxlbSBvZiBjb2xsZWN0aW9uKSB7XG4gICAgICBsZXQgciA9IFBhdHRlcm5zLm1hdGNoX25vX3Rocm93KHBhdHRlcm4sIGVsZW0pO1xuICAgICAgbGV0IGFyZ3MgPSBwcmV2aW91c1ZhbHVlcy5jb25jYXQocik7XG5cbiAgICAgIGlmIChyICYmIGZpbHRlci5hcHBseSh0aGlzLCBhcmdzKSkge1xuICAgICAgICBpbnRvID0gaW50by5jb25jYXQoW2Z1bi5hcHBseSh0aGlzLCBhcmdzKV0pO1xuICAgICAgfVxuICAgIH1cblxuICAgIHJldHVybiBpbnRvO1xuICB9IGVsc2Uge1xuICAgIGxldCBfaW50byA9IFtdO1xuXG4gICAgZm9yIChsZXQgZWxlbSBvZiBjb2xsZWN0aW9uKSB7XG4gICAgICBsZXQgciA9IFBhdHRlcm5zLm1hdGNoX25vX3Rocm93KHBhdHRlcm4sIGVsZW0pO1xuICAgICAgaWYgKHIpIHtcbiAgICAgICAgX2ludG8gPSBpbnRvLmNvbmNhdCh0aGlzLl9mb3IoY29sbGVjdGlvbnMuc2xpY2UoMSksIGZ1biwgZmlsdGVyLCBfaW50bywgcHJldmlvdXNWYWx1ZXMuY29uY2F0KHIpKSk7XG4gICAgICB9XG4gICAgfVxuXG4gICAgcmV0dXJuIF9pbnRvO1xuICB9XG59XG5cbmZ1bmN0aW9uIF90cnkoZG9fZnVuLCByZXNjdWVfZnVuY3Rpb24sIGNhdGNoX2Z1biwgZWxzZV9mdW5jdGlvbiwgYWZ0ZXJfZnVuY3Rpb24pIHtcbiAgbGV0IHJlc3VsdCA9IG51bGw7XG5cbiAgdHJ5IHtcbiAgICByZXN1bHQgPSBkb19mdW4oKTtcbiAgfSBjYXRjaCAoZSkge1xuICAgIGxldCBleF9yZXN1bHQgPSBudWxsO1xuXG4gICAgaWYgKHJlc2N1ZV9mdW5jdGlvbikge1xuICAgICAgdHJ5IHtcbiAgICAgICAgZXhfcmVzdWx0ID0gcmVzY3VlX2Z1bmN0aW9uKGUpO1xuICAgICAgICByZXR1cm4gZXhfcmVzdWx0O1xuICAgICAgfSBjYXRjaCAoZXgpIHtcbiAgICAgICAgaWYgKGV4IGluc3RhbmNlb2YgUGF0dGVybnMuTWF0Y2hFcnJvcikge1xuICAgICAgICAgIHRocm93IGV4O1xuICAgICAgICB9XG4gICAgICB9XG4gICAgfVxuXG4gICAgaWYgKGNhdGNoX2Z1bikge1xuICAgICAgdHJ5IHtcbiAgICAgICAgZXhfcmVzdWx0ID0gY2F0Y2hfZnVuKGUpO1xuICAgICAgICByZXR1cm4gZXhfcmVzdWx0O1xuICAgICAgfSBjYXRjaCAoZXgpIHtcbiAgICAgICAgaWYgKGV4IGluc3RhbmNlb2YgUGF0dGVybnMuTWF0Y2hFcnJvcikge1xuICAgICAgICAgIHRocm93IGV4O1xuICAgICAgICB9XG4gICAgICB9XG4gICAgfVxuXG4gICAgdGhyb3cgZTtcbiAgfSBmaW5hbGx5IHtcbiAgICBpZiAoYWZ0ZXJfZnVuY3Rpb24pIHtcbiAgICAgIGFmdGVyX2Z1bmN0aW9uKCk7XG4gICAgfVxuICB9XG5cbiAgaWYgKGVsc2VfZnVuY3Rpb24pIHtcbiAgICB0cnkge1xuICAgICAgcmV0dXJuIGVsc2VfZnVuY3Rpb24ocmVzdWx0KTtcbiAgICB9IGNhdGNoIChleCkge1xuICAgICAgaWYgKGV4IGluc3RhbmNlb2YgUGF0dGVybnMuTWF0Y2hFcnJvcikge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ05vIE1hdGNoIEZvdW5kIGluIEVsc2UnKTtcbiAgICAgIH1cblxuICAgICAgdGhyb3cgZXg7XG4gICAgfVxuICB9IGVsc2Uge1xuICAgIHJldHVybiByZXN1bHQ7XG4gIH1cbn1cblxudmFyIFNwZWNpYWxGb3JtcyQxID0ge1xuICBfY2FzZSxcbiAgY29uZCxcbiAgbWFwX3VwZGF0ZSxcbiAgX2ZvcixcbiAgX3RyeVxufTtcblxuRnVuY3Rpb25zLmdldF9nbG9iYWwoKS5wcm9jZXNzZXMgPSBGdW5jdGlvbnMuZ2V0X2dsb2JhbCgpLnByb2Nlc3NlcyB8fCBuZXcgUHJvY2Vzc1N5c3RlbSgpO1xuXG52YXIgQ29yZSQxID0ge1xuICBQcm9jZXNzU3lzdGVtLFxuICBUdXBsZSxcbiAgUElELFxuICBCaXRTdHJpbmcsXG4gIFBhdHRlcm5zLFxuICBJbnRlZ2VyLFxuICBGbG9hdCxcbiAgRnVuY3Rpb25zLFxuICBTcGVjaWFsRm9ybXM6IFNwZWNpYWxGb3JtcyQxXG59O1xuXG5sZXQgRW51bSA9IHtcblxuICBhbGxfX3FtYXJrX186IGZ1bmN0aW9uIChjb2xsZWN0aW9uLCBmdW4gPSB4ID0+IHgpIHtcbiAgICBmb3IgKGxldCBlbGVtIG9mIGNvbGxlY3Rpb24pIHtcbiAgICAgIGlmICghZnVuKGVsZW0pKSB7XG4gICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICByZXR1cm4gdHJ1ZTtcbiAgfSxcblxuICBhbnlfX3FtYXJrX186IGZ1bmN0aW9uIChjb2xsZWN0aW9uLCBmdW4gPSB4ID0+IHgpIHtcbiAgICBmb3IgKGxldCBlbGVtIG9mIGNvbGxlY3Rpb24pIHtcbiAgICAgIGlmIChmdW4oZWxlbSkpIHtcbiAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICB9XG4gICAgfVxuXG4gICAgcmV0dXJuIGZhbHNlO1xuICB9LFxuXG4gIGF0OiBmdW5jdGlvbiAoY29sbGVjdGlvbiwgbiwgdGhlX2RlZmF1bHQgPSBudWxsKSB7XG4gICAgaWYgKG4gPiB0aGlzLmNvdW50KGNvbGxlY3Rpb24pIHx8IG4gPCAwKSB7XG4gICAgICByZXR1cm4gdGhlX2RlZmF1bHQ7XG4gICAgfVxuXG4gICAgcmV0dXJuIGNvbGxlY3Rpb25bbl07XG4gIH0sXG5cbiAgY29uY2F0OiBmdW5jdGlvbiAoLi4uZW51bWFibGVzKSB7XG4gICAgcmV0dXJuIGVudW1hYmxlc1swXS5jb25jYXQoZW51bWFibGVzWzFdKTtcbiAgfSxcblxuICBjb3VudDogZnVuY3Rpb24gKGNvbGxlY3Rpb24sIGZ1biA9IG51bGwpIHtcbiAgICBpZiAoZnVuID09IG51bGwpIHtcbiAgICAgIHJldHVybiBjb2xsZWN0aW9uLmxlbmd0aDtcbiAgICB9IGVsc2Uge1xuICAgICAgcmV0dXJuIGNvbGxlY3Rpb24uZmlsdGVyKGZ1bikubGVuZ3RoO1xuICAgIH1cbiAgfSxcblxuICBkcm9wOiBmdW5jdGlvbiAoY29sbGVjdGlvbiwgY291bnQpIHtcbiAgICByZXR1cm4gY29sbGVjdGlvbi5zbGljZShjb3VudCk7XG4gIH0sXG5cbiAgZHJvcF93aGlsZTogZnVuY3Rpb24gKGNvbGxlY3Rpb24sIGZ1bikge1xuICAgIGxldCBjb3VudCA9IDA7XG5cbiAgICBmb3IgKGxldCBlbGVtIG9mIGNvbGxlY3Rpb24pIHtcbiAgICAgIGlmIChmdW4oZWxlbSkpIHtcbiAgICAgICAgY291bnQgPSBjb3VudCArIDE7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBicmVhaztcbiAgICAgIH1cbiAgICB9XG5cbiAgICByZXR1cm4gY29sbGVjdGlvbi5zbGljZShjb3VudCk7XG4gIH0sXG5cbiAgZWFjaDogZnVuY3Rpb24gKGNvbGxlY3Rpb24sIGZ1bikge1xuICAgIGZvciAobGV0IGVsZW0gb2YgY29sbGVjdGlvbikge1xuICAgICAgZnVuKGVsZW0pO1xuICAgIH1cbiAgfSxcblxuICBlbXB0eV9fcW1hcmtfXzogZnVuY3Rpb24gKGNvbGxlY3Rpb24pIHtcbiAgICByZXR1cm4gY29sbGVjdGlvbi5sZW5ndGggPT09IDA7XG4gIH0sXG5cbiAgZmV0Y2g6IGZ1bmN0aW9uIChjb2xsZWN0aW9uLCBuKSB7XG4gICAgaWYgKEFycmF5LmlzQXJyYXkoY29sbGVjdGlvbikpIHtcbiAgICAgIGlmIChuIDwgdGhpcy5jb3VudChjb2xsZWN0aW9uKSAmJiBuID49IDApIHtcbiAgICAgICAgcmV0dXJuIG5ldyBDb3JlJDEuVHVwbGUoU3ltYm9sLmZvcihcIm9rXCIpLCBjb2xsZWN0aW9uW25dKTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHJldHVybiBTeW1ib2wuZm9yKFwiZXJyb3JcIik7XG4gICAgICB9XG4gICAgfVxuXG4gICAgdGhyb3cgbmV3IEVycm9yKFwiY29sbGVjdGlvbiBpcyBub3QgYW4gRW51bWVyYWJsZVwiKTtcbiAgfSxcblxuICBmZXRjaF9fZW1hcmtfXzogZnVuY3Rpb24gKGNvbGxlY3Rpb24sIG4pIHtcbiAgICBpZiAoQXJyYXkuaXNBcnJheShjb2xsZWN0aW9uKSkge1xuICAgICAgaWYgKG4gPCB0aGlzLmNvdW50KGNvbGxlY3Rpb24pICYmIG4gPj0gMCkge1xuICAgICAgICByZXR1cm4gY29sbGVjdGlvbltuXTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcihcIm91dCBvZiBib3VuZHMgZXJyb3JcIik7XG4gICAgICB9XG4gICAgfVxuXG4gICAgdGhyb3cgbmV3IEVycm9yKFwiY29sbGVjdGlvbiBpcyBub3QgYW4gRW51bWVyYWJsZVwiKTtcbiAgfSxcblxuICBmaWx0ZXI6IGZ1bmN0aW9uIChjb2xsZWN0aW9uLCBmdW4pIHtcbiAgICBsZXQgcmVzdWx0ID0gW107XG5cbiAgICBmb3IgKGxldCBlbGVtIG9mIGNvbGxlY3Rpb24pIHtcbiAgICAgIGlmIChmdW4oZWxlbSkpIHtcbiAgICAgICAgcmVzdWx0LnB1c2goZWxlbSk7XG4gICAgICB9XG4gICAgfVxuXG4gICAgcmV0dXJuIHJlc3VsdDtcbiAgfSxcblxuICBmaWx0ZXJfbWFwOiBmdW5jdGlvbiAoY29sbGVjdGlvbiwgZmlsdGVyLCBtYXBwZXIpIHtcbiAgICByZXR1cm4gRW51bS5tYXAoRW51bS5maWx0ZXIoY29sbGVjdGlvbiwgZmlsdGVyKSwgbWFwcGVyKTtcbiAgfSxcblxuICBmaW5kOiBmdW5jdGlvbiAoY29sbGVjdGlvbiwgaWZfbm9uZSA9IG51bGwsIGZ1bikge1xuICAgIGZvciAobGV0IGVsZW0gb2YgY29sbGVjdGlvbikge1xuICAgICAgaWYgKGZ1bihlbGVtKSkge1xuICAgICAgICByZXR1cm4gZWxlbTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICByZXR1cm4gaWZfbm9uZTtcbiAgfSxcblxuICBpbnRvOiBmdW5jdGlvbiAoY29sbGVjdGlvbiwgbGlzdCkge1xuICAgIHJldHVybiBsaXN0LmNvbmNhdChjb2xsZWN0aW9uKTtcbiAgfSxcblxuICBtYXA6IGZ1bmN0aW9uIChjb2xsZWN0aW9uLCBmdW4pIHtcbiAgICBsZXQgcmVzdWx0ID0gW107XG5cbiAgICBmb3IgKGxldCBlbGVtIG9mIGNvbGxlY3Rpb24pIHtcbiAgICAgIHJlc3VsdC5wdXNoKGZ1bihlbGVtKSk7XG4gICAgfVxuXG4gICAgcmV0dXJuIHJlc3VsdDtcbiAgfSxcblxuICBtYXBfcmVkdWNlOiBmdW5jdGlvbiAoY29sbGVjdGlvbiwgYWNjLCBmdW4pIHtcbiAgICBsZXQgbWFwcGVkID0gT2JqZWN0LmZyZWV6ZShbXSk7XG4gICAgbGV0IHRoZV9hY2MgPSBhY2M7XG5cbiAgICBmb3IgKHZhciBpID0gMDsgaSA8IHRoaXMuY291bnQoY29sbGVjdGlvbik7IGkrKykge1xuICAgICAgbGV0IHR1cGxlID0gZnVuKGNvbGxlY3Rpb25baV0sIHRoZV9hY2MpO1xuXG4gICAgICB0aGVfYWNjID0gdHVwbGUuZ2V0KDEpO1xuICAgICAgbWFwcGVkID0gT2JqZWN0LmZyZWV6ZShtYXBwZWQuY29uY2F0KFt0dXBsZS5nZXQoMCldKSk7XG4gICAgfVxuXG4gICAgcmV0dXJuIG5ldyBDb3JlJDEuVHVwbGUobWFwcGVkLCB0aGVfYWNjKTtcbiAgfSxcblxuICBtZW1iZXJfX3FtYXJrX186IGZ1bmN0aW9uIChjb2xsZWN0aW9uLCB2YWx1ZSkge1xuICAgIHJldHVybiBjb2xsZWN0aW9uLmluY2x1ZGVzKHZhbHVlKTtcbiAgfSxcblxuICByZWR1Y2U6IGZ1bmN0aW9uIChjb2xsZWN0aW9uLCBhY2MsIGZ1bikge1xuICAgIGxldCB0aGVfYWNjID0gYWNjO1xuXG4gICAgZm9yICh2YXIgaSA9IDA7IGkgPCB0aGlzLmNvdW50KGNvbGxlY3Rpb24pOyBpKyspIHtcbiAgICAgIGxldCB0dXBsZSA9IGZ1bihjb2xsZWN0aW9uW2ldLCB0aGVfYWNjKTtcblxuICAgICAgdGhlX2FjYyA9IHR1cGxlLmdldCgxKTtcbiAgICB9XG5cbiAgICByZXR1cm4gdGhlX2FjYztcbiAgfSxcblxuICB0YWtlOiBmdW5jdGlvbiAoY29sbGVjdGlvbiwgY291bnQpIHtcbiAgICByZXR1cm4gY29sbGVjdGlvbi5zbGljZSgwLCBjb3VudCk7XG4gIH0sXG5cbiAgdGFrZV9ldmVyeTogZnVuY3Rpb24gKGNvbGxlY3Rpb24sIG50aCkge1xuICAgIGxldCByZXN1bHQgPSBbXTtcbiAgICBsZXQgaW5kZXggPSAwO1xuXG4gICAgZm9yIChsZXQgZWxlbSBvZiBjb2xsZWN0aW9uKSB7XG4gICAgICBpZiAoaW5kZXggJSBudGggPT09IDApIHtcbiAgICAgICAgcmVzdWx0LnB1c2goZWxlbSk7XG4gICAgICB9XG4gICAgfVxuXG4gICAgcmV0dXJuIE9iamVjdC5mcmVlemUocmVzdWx0KTtcbiAgfSxcblxuICB0YWtlX3doaWxlOiBmdW5jdGlvbiAoY29sbGVjdGlvbiwgZnVuKSB7XG4gICAgbGV0IGNvdW50ID0gMDtcblxuICAgIGZvciAobGV0IGVsZW0gb2YgY29sbGVjdGlvbikge1xuICAgICAgaWYgKGZ1bihlbGVtKSkge1xuICAgICAgICBjb3VudCA9IGNvdW50ICsgMTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIGJyZWFrO1xuICAgICAgfVxuICAgIH1cblxuICAgIHJldHVybiBjb2xsZWN0aW9uLnNsaWNlKDAsIGNvdW50KTtcbiAgfSxcblxuICB0b19saXN0OiBmdW5jdGlvbiAoY29sbGVjdGlvbikge1xuICAgIHJldHVybiBjb2xsZWN0aW9uO1xuICB9XG59O1xuXG52YXIgRWxpeGlyID0ge1xuICBDb3JlOiBDb3JlJDEsXG4gIEVudW0sXG4gIFZpcnR1YWxET01cbn07XG5cbmV4cG9ydCBkZWZhdWx0IEVsaXhpcjsiXSwiZmlsZSI6IkVsaXhpci5qcyIsInNvdXJjZVJvb3QiOiIvc291cmNlLyJ9 \ No newline at end of file diff --git a/src/javascript/elixir.js b/src/javascript/elixir.js index 9dc23da5..8495d9b1 100644 --- a/src/javascript/elixir.js +++ b/src/javascript/elixir.js @@ -6,4 +6,4 @@ export default { Core, Enum, VirtualDOM -} +}; diff --git a/src/javascript/lib/core/functions.js b/src/javascript/lib/core/functions.js index 71b6ea56..a18871cd 100644 --- a/src/javascript/lib/core/functions.js +++ b/src/javascript/lib/core/functions.js @@ -260,6 +260,14 @@ function reverse(list){ return list.concat([]).reverse(); } +function maps_find(key, map){ + if(key in get_object_keys(map)){ + return new Tuple(Symbol.for("ok"), map[key]); + }else{ + return Symbol.for("error"); + } +} + export default { call_property, apply, @@ -289,5 +297,6 @@ export default { keydelete, keystore, reverse, - update_map + update_map, + maps_find }; diff --git a/test/translator/struct_test.exs b/test/translator/struct_test.exs index 3b92b57c..f92a84d8 100644 --- a/test/translator/struct_test.exs +++ b/test/translator/struct_test.exs @@ -29,7 +29,7 @@ defmodule ElixirScript.Translator.Struct.Test do ex_ast = quote do defmodule User do - defstruct :name, :age + defstruct [:name, :age] end end From 1db68cf42e66ee8637f8b6d4c178d40b79e7e535 Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Tue, 9 Feb 2016 09:29:43 -0600 Subject: [PATCH 140/860] Fixed error message when a module cannot be found --- lib/elixir_script.ex | 5 ++-- lib/elixir_script/translator/env.ex | 28 +++++++++++++------ .../translator/module_collector.ex | 3 +- 3 files changed, 22 insertions(+), 14 deletions(-) diff --git a/lib/elixir_script.ex b/lib/elixir_script.ex index d518e8cf..24752039 100644 --- a/lib/elixir_script.ex +++ b/lib/elixir_script.ex @@ -75,9 +75,8 @@ defmodule ElixirScript do """ @spec compile_path(binary, Map.t) :: [binary | {binary, binary}] def compile_path(path, opts \\ %{}) do - code = path - |> Path.wildcard - |> Enum.map(&file_to_quoted/1) + path = Path.wildcard(path) + code = Enum.map(path, &file_to_quoted/1) do_compile(opts, code) end diff --git a/lib/elixir_script/translator/env.ex b/lib/elixir_script/translator/env.ex index e27719cc..41c8bbc0 100644 --- a/lib/elixir_script/translator/env.ex +++ b/lib/elixir_script/translator/env.ex @@ -87,6 +87,17 @@ defmodule ElixirScript.Translator.Env do ElixirScript.Translator.State.get_module unless module do + module_name = case module_name do + {:__aliases__, _, _} -> + ElixirScript.Translator.Utils.quoted_to_name(module_name) + |> Atom.to_string + |> String.split(".") + |> tl + |> Enum.join(".") + _ -> + module_name + end + raise "Module #{module_name} not found" end @@ -97,7 +108,6 @@ defmodule ElixirScript.Translator.Env do def add_import(env, module_name) do module = get_module(env, module_name) - %{ env | requires: Enum.uniq(env.requires ++ [module.name]), functions: env.functions ++ [{ module.name, module.functions }], macros: env.macros ++ [{ module.name, module.macros }] } @@ -107,7 +117,7 @@ defmodule ElixirScript.Translator.Env do module = get_module(env, module_name) %{ env | functions: List.keydelete(env.functions, module_name, 0) ++ [{ module.name, module.functions }], - macros: List.keydelete(env.macros, module_name, 0), + macros: List.keydelete(env.macros, module.name, 0), requires: Enum.uniq(env.requires ++ [module.name]) } end @@ -115,7 +125,7 @@ defmodule ElixirScript.Translator.Env do module = get_module(env, module_name) %{ env | macros: List.keydelete(env.macros, module_name, 0) ++ [{ module.name, module.macros }], - functions: List.keydelete(env.functions, module_name, 0), + functions: List.keydelete(env.functions, module.name, 0), requires: Enum.uniq(env.requires ++ [module.name]) } end @@ -130,22 +140,22 @@ defmodule ElixirScript.Translator.Env do end) %{ env | requires: Enum.uniq(env.requires ++ [module.name]), - functions: List.keydelete(env.functions, module_name, 0) ++ [{ module.name, functions }], - macros: List.keydelete(env.macros, module_name, 0) ++ [{ module.name, macros }] } + functions: List.keydelete(env.functions, module.name, 0) ++ [{ module.name, functions }], + macros: List.keydelete(env.macros, module.name, 0) ++ [{ module.name, macros }] } end def add_import(env, module_name, [except: except]) do module = get_module(env, module_name) - {_, current_functions } = List.keyfind(env.functions, module_name, 0, { module_name, module.functions }) - {_, current_macros } = List.keyfind(env.macros, module_name, 0, { module_name, module.macros }) + {_, current_functions } = List.keyfind(env.functions, module.name, 0, { module.name, module.functions }) + {_, current_macros } = List.keyfind(env.macros, module.name, 0, { module.name, module.macros }) macros = Enum.filter(current_macros, fn(mac) -> not(mac in except) end) functions = Enum.filter(current_functions, fn(func) -> not(func in except) end) %{ env | requires: env.requires ++ [module.name], - functions: List.keydelete(env.functions, module_name, 0) ++ [{ module.name, functions }], - macros: List.keydelete(env.macros, module_name, 0) ++ [{ module.name, macros }] } + functions: List.keydelete(env.functions, module.name, 0) ++ [{ module.name, functions }], + macros: List.keydelete(env.macros, module.name, 0) ++ [{ module.name, macros }] } end def add_alias(env, module_name, alias_name) do diff --git a/lib/elixir_script/translator/module_collector.ex b/lib/elixir_script/translator/module_collector.ex index 93aded66..05707805 100644 --- a/lib/elixir_script/translator/module_collector.ex +++ b/lib/elixir_script/translator/module_collector.ex @@ -103,7 +103,6 @@ defmodule ElixirScript.Translator.ModuleCollector do inner_module_body = make_inner_module_aliases( name ++ inner_module_name, inner_module_body) inner_alias = add_module_to_state(name, inner_module_name, inner_module_body) - [ inner_alias ] _ -> x @@ -126,7 +125,7 @@ defmodule ElixirScript.Translator.ModuleCollector do %{def: functions, defp: private_functions, defmacro: macros, defmacrop: private_macros } = get_functions_from_module(inner_module_body) js_imports = get_js_imports_from_module(inner_module_body) - inner_alias = {:alias, [], [{:__aliases__, [alias: false], name ++ inner_module_name}]} + inner_alias = { :alias, [], [{:__aliases__, [alias: false], name ++ inner_module_name}] } module_name = Utils.quoted_to_name({:__aliases__, [], tl(name) ++ inner_module_name}) State.delete_module_by_name(module_name) From 6e3adfe9647fe783a70fca1b92f75cee56d8d464 Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Tue, 9 Feb 2016 11:17:09 -0600 Subject: [PATCH 141/860] Reworked module collector to allow for adding aliases to inner modules --- lib/elixir_script/translator/env.ex | 3 +- .../translator/module_collector.ex | 65 ++++++++++++------- lib/elixir_script/translator/state.ex | 4 ++ test/translator/defmodule_test.exs | 33 ++++++++++ 4 files changed, 82 insertions(+), 23 deletions(-) diff --git a/lib/elixir_script/translator/env.ex b/lib/elixir_script/translator/env.ex index dce9b7af..e27719cc 100644 --- a/lib/elixir_script/translator/env.ex +++ b/lib/elixir_script/translator/env.ex @@ -83,7 +83,8 @@ defmodule ElixirScript.Translator.Env do end defp get_module(env, module_name) do - module = ElixirScript.Translator.State.get_module(module_name) + module = get_module_name(env, module_name) |> + ElixirScript.Translator.State.get_module unless module do raise "Module #{module_name} not found" diff --git a/lib/elixir_script/translator/module_collector.ex b/lib/elixir_script/translator/module_collector.ex index 93aded66..779ba9de 100644 --- a/lib/elixir_script/translator/module_collector.ex +++ b/lib/elixir_script/translator/module_collector.ex @@ -61,12 +61,8 @@ defmodule ElixirScript.Translator.ModuleCollector do ast end - def do_process_modules({:defmodule, _, [{:__aliases__, _, name}, [do: body]]} = ast) do - body = make_inner_module_aliases(name, body) - - make_module(body, name) - |> State.add_module - + def do_process_modules({:defmodule, _, [{:__aliases__, _, _}, [do: _]]} = ast) do + do_module_processing(ast) ast end @@ -74,6 +70,39 @@ defmodule ElixirScript.Translator.ModuleCollector do ast end + defp do_module_processing({:defmodule, _, [{:__aliases__, _, name}, [do: body]]}) do + { body, inner_modules } = make_inner_module_aliases(name, body) + + aliases = Enum.map(inner_modules, fn + ({:defmodule, _, [{:__aliases__, _, inner_module_name}, [do: inner_module_body]]}) -> + { :alias, [], [{:__aliases__, [alias: false], name ++ inner_module_name}, [as: {:__aliases__, [alias: false], inner_module_name }] ] } + end) + + Enum.each(inner_modules, fn + ({:defmodule, context1, [{:__aliases__, context2, inner_module_name}, [do: inner_module_body]]}) -> + + module_name = Utils.quoted_to_name({:__aliases__, [], tl(name) ++ inner_module_name}) + State.delete_module_by_name(module_name) + + this_module_aliases = aliases -- [{ :alias, [], [{:__aliases__, [alias: false], name ++ inner_module_name}, [as: {:__aliases__, [alias: false], inner_module_name }] ] }] + + {:defmodule, context1, [{:__aliases__, context2, name ++ inner_module_name}, [do: add_aliases_to_body(inner_module_body, this_module_aliases)]]} + |> do_module_processing + end) + + module = make_module(add_aliases_to_body(body, aliases), name) + State.add_module(module) + end + + defp add_aliases_to_body(body, aliases) do + case body do + { :__block__, context, body } -> + { :__block__, context, aliases ++ List.wrap(body) } + _ -> + { :__block__, [], aliases ++ List.wrap(body) } + end + end + defp make_module(body, name) do body = case body do {:__block__, _, _ } -> @@ -94,31 +123,23 @@ defmodule ElixirScript.Translator.ModuleCollector do defp make_inner_module_aliases(name, body) do case body do nil -> - { :__block__, [], [] } + { { :__block__, [], [] }, [] } {:__block__, context, list2 } -> - list2 = Enum.map(list2, fn(x) -> + { list2, inner_modules } = Enum.partition(list2, fn(x) -> case x do {:defmodule, _, [{:__aliases__, _, inner_module_name}, [do: inner_module_body]]} -> - inner_module_body = make_inner_module_aliases( name ++ inner_module_name, inner_module_body) - inner_alias = add_module_to_state(name, inner_module_name, inner_module_body) - - - [ inner_alias ] + false _ -> - x + true end end) - |> List.flatten - {:__block__, context, list2} - {:defmodule, _, [{:__aliases__, context, inner_module_name}, [do: inner_module_body]]} -> - inner_module_body = make_inner_module_aliases(name ++ inner_module_name, inner_module_body) - inner_alias = add_module_to_state(name, inner_module_name, inner_module_body) - - {:__block__, context, [ inner_alias ] } + { {:__block__, context, list2}, inner_modules } + {:defmodule, _, [{:__aliases__, context, inner_module_name}, [do: inner_module_body]]} = mod -> + { {:__block__, context, [] }, [mod] } _ -> - body + { body, [] } end end diff --git a/lib/elixir_script/translator/state.ex b/lib/elixir_script/translator/state.ex index 2bed20e2..ccd4a635 100644 --- a/lib/elixir_script/translator/state.ex +++ b/lib/elixir_script/translator/state.ex @@ -91,6 +91,10 @@ defmodule ElixirScript.Translator.State do Agent.get(__MODULE__, &(&1)) end + def get_module_name({:__aliases__, _, _} = name) do + get_module_name(Utils.quoted_to_name(name)) + end + def get_module_name(module_name) do Agent.get(__MODULE__, fn(state) -> do_get_module_name(module_name, state) diff --git a/test/translator/defmodule_test.exs b/test/translator/defmodule_test.exs index df4f343d..e41627f6 100644 --- a/test/translator/defmodule_test.exs +++ b/test/translator/defmodule_test.exs @@ -296,4 +296,37 @@ defmodule ElixirScript.Translator.Defmodule.Test do assert_translation(ex_ast, js_code) end + + + test "translate inner module has another inner module alias" do + ex_ast = quote do + defmodule Version do + defmodule Parser do + import Parser.DSL + end + + defmodule Parser.DSL do + + end + end + end + + js_code = """ + import Elixir$ElixirScript$Kernel from './Elixir.ElixirScript.Kernel'; + import Elixir$Version$Parser from './Elixir.Version.Parser'; + import Elixir$Version$Parser$DSL from './Elixir.Version.Parser.DSL'; + export default {}; + + import Elixir$ElixirScript$Kernel from './Elixir.ElixirScript.Kernel'; + import Elixir$Version$Parser$DSL from './Elixir.Version.Parser.DSL'; + export default {}; + + import Elixir$ElixirScript$Kernel from './Elixir.ElixirScript.Kernel'; + import Elixir$Version$Parser from './Elixir.Version.Parser'; + export default {}; + """ + + assert_translation(ex_ast, js_code) + end + end From 847d14cb1e2d48ae197605bcfd76459d916afe00 Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Tue, 9 Feb 2016 11:33:59 -0600 Subject: [PATCH 142/860] Fixed bug with defstruct failing when a list of atoms is given --- lib/elixir_script/translator/struct.ex | 16 +++++++++++----- test/translator/struct_test.exs | 2 +- 2 files changed, 12 insertions(+), 6 deletions(-) diff --git a/lib/elixir_script/translator/struct.ex b/lib/elixir_script/translator/struct.ex index b41b6783..e575653f 100644 --- a/lib/elixir_script/translator/struct.ex +++ b/lib/elixir_script/translator/struct.ex @@ -36,11 +36,17 @@ defmodule ElixirScript.Translator.Struct do def make_defstruct(attributes, env) when length(attributes) == 1 do attributes = Enum.flat_map(attributes, fn(x) -> x end) - defaults = Enum.map(attributes, fn({x, y}) -> - Map.make_property( - Translator.translate!(x, env), - Translator.translate!(y, env) - ) + defaults = Enum.map(attributes, fn + ({x, y}) -> + Map.make_property( + Translator.translate!(x, env), + Translator.translate!(y, env) + ) + (attribute) -> + Map.make_property( + Translator.translate!(attribute, env), + Translator.translate!(nil, env) + ) end) |> JS.object_expression diff --git a/test/translator/struct_test.exs b/test/translator/struct_test.exs index 3b92b57c..f92a84d8 100644 --- a/test/translator/struct_test.exs +++ b/test/translator/struct_test.exs @@ -29,7 +29,7 @@ defmodule ElixirScript.Translator.Struct.Test do ex_ast = quote do defmodule User do - defstruct :name, :age + defstruct [:name, :age] end end From 6bf134cac647e1f35c5f3648652145bdfeda1f67 Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Tue, 9 Feb 2016 12:00:16 -0600 Subject: [PATCH 143/860] Added more rewriter function heads --- .gitignore | 1 + lib/elixir_script/translator/rewriter.ex | 19 +++++++++++++++++++ src/javascript/lib/core/primitives.js | 15 +++++++++++++-- test/elixir_script_test.exs | 1 - 4 files changed, 33 insertions(+), 3 deletions(-) diff --git a/.gitignore b/.gitignore index 072bdaa1..dceb01a1 100644 --- a/.gitignore +++ b/.gitignore @@ -17,3 +17,4 @@ fprof.trace index.js /doc /bench/snapshots +.tern-port diff --git a/lib/elixir_script/translator/rewriter.ex b/lib/elixir_script/translator/rewriter.ex index 6f9ed6b5..df901768 100644 --- a/lib/elixir_script/translator/rewriter.ex +++ b/lib/elixir_script/translator/rewriter.ex @@ -297,6 +297,25 @@ defmodule ElixirScript.Translator.Rewriter do quote do: true end + def rewrite({{:., _, [:erlang, :make_tuple]}, _, [size, data]}) do + quote do: JS.new(Elixir.Core.Tuple, List.duplicate(unquote(size), unquote(data))) + end + + def rewrite({{:., _, [:erlang, :insert_element]}, _, [index, tuple, term]}) do + quote do: unquote(tuple).put_elem(unquote(index) - 1, unquote(term)) + end + + def rewrite({{:., _, [:erlang, :tuple_to_list]}, _, [tuple]}) do + quote do: unquote(tuple).values + end + + def rewrite({{:., _, [:erlang, :append_element]}, _, [tuple, value]}) do + quote do: unquote(tuple).put_elem(unquote(tuple).length, unquote(value)) + end + + def rewrite({{:., _, [:erlang, :delete_element]}, _, [index, tuple]}) do + quote do: unquote(tuple).remove_elem(unquote(index)) + end def rewrite({{:., _, [:lists, :map]}, _, [fun, list]}) do quote do: unquote(list).map(unquote(fun)) diff --git a/src/javascript/lib/core/primitives.js b/src/javascript/lib/core/primitives.js index 239759ef..d483ec8a 100644 --- a/src/javascript/lib/core/primitives.js +++ b/src/javascript/lib/core/primitives.js @@ -30,9 +30,20 @@ class Tuple { } put_elem(index, elem){ - let new_values = this.values.concat([]); - new_values.splice(index, 0, elem); + if(index === this.length){ + let new_values = this.values.concat([elem]); return new Tuple(...new_values); + } + + let new_values = this.values.concat([]); + new_values.splice(index, 0, elem); + return new Tuple(...new_values); + } + + remove_elem(index){ + let new_values = this.values.concat([]); + new_values.splice(index, 1); + return new Tuple(...new_values); } } diff --git a/test/elixir_script_test.exs b/test/elixir_script_test.exs index 181b71f4..ef0f5990 100644 --- a/test/elixir_script_test.exs +++ b/test/elixir_script_test.exs @@ -181,5 +181,4 @@ defmodule ElixirScript.Test do }; """, hd(js_code) end - end From e76c71ce64c05f3567a53d9542aea94b7b817817 Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Mon, 15 Feb 2016 11:35:18 -0600 Subject: [PATCH 144/860] Added more erlang replacement functions --- .gitignore | 1 + lib/elixir_script/translator.ex | 8 ++ lib/elixir_script/translator/module.ex | 4 +- lib/elixir_script/translator/rewriter.ex | 88 +++++++++++++++++- src/javascript/lib/core/functions.js | 111 ++++++++++++++++++++++- test/translator/kernel_test.exs | 14 +++ 6 files changed, 220 insertions(+), 6 deletions(-) diff --git a/.gitignore b/.gitignore index dceb01a1..363c47e8 100644 --- a/.gitignore +++ b/.gitignore @@ -18,3 +18,4 @@ index.js /doc /bench/snapshots .tern-port +test/std_lib_compile_test.exs diff --git a/lib/elixir_script/translator.ex b/lib/elixir_script/translator.ex index 7740862f..d3cfe9ff 100644 --- a/lib/elixir_script/translator.ex +++ b/lib/elixir_script/translator.ex @@ -469,6 +469,14 @@ defmodule ElixirScript.Translator do translate(quoted, env) end + defp do_translate({:raise, _, [alias_info, {:<<>>, _, _} = message]}, env) do + js_ast = JS.throw_statement( + Struct.new_struct(alias_info, {:%{}, [], [message: message] }, env) + ) + + { js_ast, env } + end + defp do_translate({:raise, _, [alias_info, attributes]}, env) do js_ast = JS.throw_statement( Struct.new_struct(alias_info, {:%{}, [], attributes }, env) diff --git a/lib/elixir_script/translator/module.ex b/lib/elixir_script/translator/module.ex index 480f21ef..66d3109b 100644 --- a/lib/elixir_script/translator/module.ex +++ b/lib/elixir_script/translator/module.ex @@ -55,7 +55,9 @@ defmodule ElixirScript.Translator.Module do result = %{ name: Utils.quoted_to_name({:__aliases__, [], module }), body: imports ++ structs ++ private_functions ++ exported_functions ++ body ++ [default] - } + } + + IO.inspect(result.body) result end diff --git a/lib/elixir_script/translator/rewriter.ex b/lib/elixir_script/translator/rewriter.ex index df901768..9a17481b 100644 --- a/lib/elixir_script/translator/rewriter.ex +++ b/lib/elixir_script/translator/rewriter.ex @@ -333,18 +333,104 @@ defmodule ElixirScript.Translator.Rewriter do quote do: Elixir.Core.Functions.foldr(unquote(fun), unquote(acc), unquote(list)) end + def rewrite({{:., _, [:lists, :keymember]}, _, [key, n, list]}) do + quote do: Elixir.Core.Functions.keymember(unquote(key), unquote(n), unquote(list)) + end + def rewrite({{:., _, [:lists, :keydelete]}, _, [key, n, list]}) do quote do: Elixir.Core.Functions.keydelete(unquote(key), unquote(n), unquote(list)) end def rewrite({{:., _, [:lists, :keystore]}, _, [key, n, list, newtuple]}) do - quote do: Elixir.Core.Functions.keymember(unquote(key), unquote(n), unquote(list), unquote(newtuple)) + quote do: Elixir.Core.Functions.keystore(unquote(key), unquote(n), unquote(list), unquote(newtuple)) + end + + def rewrite({{:., _, [:lists, :keytake]}, _, [key, n, list]}) do + quote do: Elixir.Core.Functions.keystore(unquote(key), unquote(n), unquote(list)) + end + + def rewrite({{:., _, [:lists, :keyfind]}, _, [key, n, list]}) do + quote do: Elixir.Core.Functions.keyfind(unquote(key), unquote(n), unquote(list)) + end + + def rewrite({{:., _, [:lists, :keyreplace]}, _, [key, n, list, newtuple]}) do + quote do: Elixir.Core.Functions.keyreplace(unquote(key), unquote(n), unquote(list), unquote(newtuple)) + end + + def rewrite({{:., _, [:lists, :keysort]}, _, [n, tuplelist]}) do + #TODO: implement keysort + quote do: unquote(tuplelist) end def rewrite({{:., _, [:lists, :reverse]}, _, [list]}) do quote do: Elixir.Core.Functions.reverse(unquote(list)) end + def rewrite({{:., _, [:lists, :reverse]}, _, [list, tail]}) do + quote do: Elixir.Core.Functions.reverse(unquote(list)) ++ unquote(tail) + end + + def rewrite({{:., _, [:lists, :flatten]}, _, [list]}) do + quote do: Elixir.Core.Functions.flatten(unquote(list)) + end + + def rewrite({{:., _, [:lists, :flatten]}, _, [list, tail]}) do + quote do: Elixir.Core.Functions.flatten(unquote(list), unquote(tail)) + end + + def rewrite({{:., _, [:lists, :delete]}, _, [elem, list]}) do + quote do: Elixir.Core.Functions.remove_from_list(unquote(list), unquote(elem)) + end + + def rewrite({{:., _, [:lists, :duplicate]}, _, [n, elem]}) do + quote do: Elixir.Core.Functions.duplicate(unquote(n), unquote(elem)) + end + + def rewrite({{:., _, [:lists, :mapfoldl]}, _, [fun, acc, list]}) do + quote do: Elixir.Core.Functions.mapfoldl(unquote(fun), unquote(acc), unquote(list)) + end + + def rewrite({{:., _, [:lists, :sort]}, _, [list]}) do + quote do: unquote(list).sort() + end + + #TODO: Implement sort + def rewrite({{:., _, [:lists, :sort]}, _, [_fun, list]}) do + quote do: unquote(list) + end + + def rewrite({{:., _, [:lists, :filter]}, _, [pred, list]}) do + quote do: unquote(list).filter(unquote(pred)) + end + + def rewrite({{:., _, [:lists, :filtermap]}, _, [fun, list]}) do + quote do: Elixir.Core.Functions.filtermap(unquote(fun), unquote(list)) + end + + def rewrite({{:., _, [:erlang, :list_to_atom]}, _, [char_list]}) do + quote do: Symbol.for(unquote(char_list)) + end + + def rewrite({{:., _, [:erlang, :list_to_existing_atom]}, _, [char_list]}) do + quote do: Symbol.for(unquote(char_list)) + end + + def rewrite({{:., _, [:erlang, :list_to_tuple]}, _, [list]}) do + quote do: JS.new(Elixir.Core.Tuple, unquote(list)) + end + + def rewrite({{:., _, [:erlang, :list_to_float]}, _, [list]}) do + quote do: parseFloat(unquote(list)) + end + + def rewrite({{:., _, [:erlang, :list_to_integer]}, _, [list]}) do + quote do: parseInt(unquote(list)) + end + + def rewrite({{:., _, [:erlang, :list_to_integer]}, _, [list, base]}) do + quote do: parseInt(unquote(list), unquote(base)) + end + def rewrite({{:., _, [:maps, :is_key]}, _, [key, map]}) do quote do: unquote(key) in Elixir.Core.Functions.get_object_keys(unquote(map)) end diff --git a/src/javascript/lib/core/functions.js b/src/javascript/lib/core/functions.js index a18871cd..9bcfa1e4 100644 --- a/src/javascript/lib/core/functions.js +++ b/src/javascript/lib/core/functions.js @@ -235,6 +235,17 @@ function foldr(fun, acc, list){ return acc1; } +function keyfind(key, n, tuplelist){ + + for(let i = tuplelist.length - 1; i >= 0; i--){ + if(tuplelist[i].get(n) === key){ + return tuplelist[i]; + } + } + + return false; +} + function keydelete(key, n, tuplelist){ for(let i = tuplelist.length - 1; i >= 0; i--){ @@ -253,9 +264,41 @@ function keystore(key, n, list, newtuple){ } } - return list; + return list.concat([]).push(newtuple); +} + +function keymember(key, n, list){ + for(let i = list.length - 1; i >= 0; i--){ + if(list[i].get(n) === key){ + return true; + } + } + + return false; +} + +function keytake(key, n, list){ + if(!keymember(key, n, list)){ + return false; + } + + let tuple = keyfind(key, n, list); + + return new Tuple(tuple.get(n), tuple, keydelete(key, n, list)); +} + +function keyreplace(key, n, list, newtuple){ + + for(let i = tuplelist.length - 1; i >= 0; i--){ + if(tuplelist[i].get(n) === key){ + return tuplelist.concat([]).splice(i, 1, newtuple); + } + } + + return tuplelist; } + function reverse(list){ return list.concat([]).reverse(); } @@ -268,6 +311,59 @@ function maps_find(key, map){ } } +function flatten(list, tail = []) { + let new_list = []; + + for(let e of list){ + if(isArray(e)){ + new_list = new_list.concat(flatten(e)); + }else{ + new_list.push(e); + } + } + + return Object.freeze(new_list.concat(tail)); +} + +function duplicate(n, elem){ + let list = []; + + for(let i = 0; i < n; i++){ + list.push(elem); + } + + return Object.freeze(list); +} + +function mapfoldl(fun, acc, list){ + let newlist = []; + + for(let x of list){ + let tup = fun(x, acc); + newlist.push(tup.get(0)); + acc = tup.get(1); + } + + + return new Tuple(Object.freeze(newlist), acc); +} + +function filtermap(fun, list){ + let newlist = []; + + for(x of list){ + let result = fun(x); + + if(result === true){ + newlist.push(x); + }else if(result instanceof Tuple){ + newlist.push(result.get(1)); + } + } + + return Object.freeze(newlist); +} + export default { call_property, apply, @@ -296,7 +392,14 @@ export default { remove_from_list, keydelete, keystore, - reverse, - update_map, - maps_find + keyfind, + keytake, + keyreplace, + reverse, + update_map, + maps_find, + flatten, + duplicate, + mapfoldl, + filtermap }; diff --git a/test/translator/kernel_test.exs b/test/translator/kernel_test.exs index 32afa525..4c7b21aa 100644 --- a/test/translator/kernel_test.exs +++ b/test/translator/kernel_test.exs @@ -2,6 +2,20 @@ defmodule ElixirScript.Translator.Kernel.Test do use ExUnit.Case import ElixirScript.TestHelper + test "raise" do + ex_ast = quote do + raise ArgumentError, "cannot convert list to string. The list must contain only integers, strings or nested such lists; got: #{inspect list}" + end + + js_code = """ + throw ArgumentError.create(Object.freeze({ + [Symbol.for('message')]: 'cannot convert list to string. The list must contain only integers, strings or nested such lists; got: ' + Elixir$ElixirScript$String$Chars.to_string(inspect(list)) + })); + """ + + assert_translation(ex_ast, js_code) + end + test "max" do ex_ast = quote do max(1, 2) From 165ece672aca617dc2af33422b19df799552fc89 Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Mon, 15 Feb 2016 14:44:45 -0600 Subject: [PATCH 145/860] Fixed bug with headTail pattern matching preventing more advanced matches --- lib/elixir_script/translator/module.ex | 2 -- lib/elixir_script/translator/pattern_matching.ex | 10 +++++++--- src/javascript/lib/core/bit_string.js | 2 +- src/javascript/lib/core/patterns/resolvers.js | 12 +++++++----- src/javascript/lib/core/patterns/types.js | 11 ++++++++--- src/javascript/tests/patterns/defmatch.spec.js | 2 +- 6 files changed, 24 insertions(+), 15 deletions(-) diff --git a/lib/elixir_script/translator/module.ex b/lib/elixir_script/translator/module.ex index 66d3109b..96cff913 100644 --- a/lib/elixir_script/translator/module.ex +++ b/lib/elixir_script/translator/module.ex @@ -57,8 +57,6 @@ defmodule ElixirScript.Translator.Module do body: imports ++ structs ++ private_functions ++ exported_functions ++ body ++ [default] } - IO.inspect(result.body) - result end diff --git a/lib/elixir_script/translator/pattern_matching.ex b/lib/elixir_script/translator/pattern_matching.ex index 4d8c55c5..0c77b40e 100644 --- a/lib/elixir_script/translator/pattern_matching.ex +++ b/lib/elixir_script/translator/pattern_matching.ex @@ -65,10 +65,10 @@ defmodule ElixirScript.Translator.PatternMatching do ) end - def head_tail() do + def head_tail(headParameter, tailParameter) do JS.call_expression( @head_tail, - [] + [headParameter, tailParameter] ) end @@ -138,7 +138,11 @@ defmodule ElixirScript.Translator.PatternMatching do end defp do_build_match([{:|, _, [head, tail]}], env) do - { [head_tail()], [Translator.translate!(head, env), Translator.translate!(tail, env)] } + { head_patterns, head_params } = do_build_match(head, env) + { tail_patterns, tail_params } = do_build_match(tail, env) + params = head_params ++ tail_params + + { [head_tail(hd(head_patterns), hd(tail_patterns))], params } end defp do_build_match({:<>, _, [prefix, value]}, env) do diff --git a/src/javascript/lib/core/bit_string.js b/src/javascript/lib/core/bit_string.js index ac01f377..b548015f 100644 --- a/src/javascript/lib/core/bit_string.js +++ b/src/javascript/lib/core/bit_string.js @@ -6,7 +6,7 @@ class BitString { this.value = Object.freeze(this.process(args)); this.length = this.value.length; - this.bit_size = this.raw_value.reduce((prev, current) => prev + current.size); + this.bit_size = this.raw_value().reduce((prev, current) => prev + current.size); this.byte_size = (this.bit_size / 8) + (this.bit_size % 8 > 0 ? 1 : 0); } diff --git a/src/javascript/lib/core/patterns/resolvers.js b/src/javascript/lib/core/patterns/resolvers.js index ea21d51d..fbd05dc4 100644 --- a/src/javascript/lib/core/patterns/resolvers.js +++ b/src/javascript/lib/core/patterns/resolvers.js @@ -64,7 +64,10 @@ function resolveVariable(): Function { }; } -function resolveHeadTail(): Function { +function resolveHeadTail(pattern: Types.HeadTail): Function { + const headMatches = buildMatch(pattern.head); + const tailMatches = buildMatch(pattern.tail); + return function(value: any, args: Array): boolean { if(!Checks.is_array(value) || value.length < 2){ return false; @@ -73,10 +76,9 @@ function resolveHeadTail(): Function { const head = value[0]; const tail = value.slice(1); - args.push(head); - args.push(tail); - - return true; + if(headMatches(head, args) && tailMatches(tail, args)){ + return true; + } }; } diff --git a/src/javascript/lib/core/patterns/types.js b/src/javascript/lib/core/patterns/types.js index dbd004a2..05362fdf 100644 --- a/src/javascript/lib/core/patterns/types.js +++ b/src/javascript/lib/core/patterns/types.js @@ -29,7 +29,12 @@ export class Capture { } export class HeadTail { - constructor() { + head: any; + tail: any; + + constructor(head: any = null, tail: any = null) { + this.head = head; + this.tail = tail; } } @@ -67,8 +72,8 @@ export function capture(value: any): Capture { return new Capture(value); } -export function headTail(): HeadTail { - return new HeadTail(); +export function headTail(head: any = null, tail: any = null): HeadTail { + return new HeadTail(head, tail); } export function type(type: any, objPattern: Object = {}): Type { diff --git a/src/javascript/tests/patterns/defmatch.spec.js b/src/javascript/tests/patterns/defmatch.spec.js index fcc74c85..5cdc0d5d 100644 --- a/src/javascript/tests/patterns/defmatch.spec.js +++ b/src/javascript/tests/patterns/defmatch.spec.js @@ -123,7 +123,7 @@ describe('defmatch', () => { let fn = Patterns.defmatch( Patterns.make_case( - [Patterns.headTail()], + [Patterns.headTail($, $)], (head, tail) => tail ) ); From f5abddd7fab6b217b1e8b1124be4a99676e8eef6 Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Mon, 15 Feb 2016 18:47:33 -0600 Subject: [PATCH 146/860] Added more erlang functions. Fixed more translations found from compiling stdlib --- lib/elixir_script/translator.ex | 8 +-- lib/elixir_script/translator/bitstring.ex | 5 ++ .../translator/module_collector.ex | 4 ++ lib/elixir_script/translator/rewriter.ex | 67 +++++++++++++++++++ src/javascript/lib/core/functions.js | 23 ++++++- test/translator/assignment_test.exs | 4 +- test/translator/function_test.exs | 6 +- test/translator/kernel_test.exs | 16 ++++- 8 files changed, 122 insertions(+), 11 deletions(-) diff --git a/lib/elixir_script/translator.ex b/lib/elixir_script/translator.ex index d3cfe9ff..bd770f8d 100644 --- a/lib/elixir_script/translator.ex +++ b/lib/elixir_script/translator.ex @@ -469,17 +469,17 @@ defmodule ElixirScript.Translator do translate(quoted, env) end - defp do_translate({:raise, _, [alias_info, {:<<>>, _, _} = message]}, env) do + defp do_translate({:raise, _, [alias_info, attributes]}, env) when is_list(attributes) do js_ast = JS.throw_statement( - Struct.new_struct(alias_info, {:%{}, [], [message: message] }, env) + Struct.new_struct(alias_info, {:%{}, [], attributes }, env) ) { js_ast, env } end - defp do_translate({:raise, _, [alias_info, attributes]}, env) do + defp do_translate({:raise, _, [alias_info, message]}, env) do js_ast = JS.throw_statement( - Struct.new_struct(alias_info, {:%{}, [], attributes }, env) + Struct.new_struct(alias_info, {:%{}, [], [message: message] }, env) ) { js_ast, env } diff --git a/lib/elixir_script/translator/bitstring.ex b/lib/elixir_script/translator/bitstring.ex index 7e21cac3..57d373dc 100644 --- a/lib/elixir_script/translator/bitstring.ex +++ b/lib/elixir_script/translator/bitstring.ex @@ -53,6 +53,11 @@ defmodule ElixirScript.Translator.Bitstring do do_make_bitstring_element({:size, Translator.translate!(element, env), [Translator.translate!(size, env)]}) end + defp make_bitstring_element(element, env) do + do_make_bitstring_element({:binary, Translator.translate!(element, env)}) + end + + defp handle_type_adjectives({:-, _, types}, ast, env) do Enum.reduce(types, ast, fn(type, current_ast) -> case type do diff --git a/lib/elixir_script/translator/module_collector.ex b/lib/elixir_script/translator/module_collector.ex index 95eccf28..64512882 100644 --- a/lib/elixir_script/translator/module_collector.ex +++ b/lib/elixir_script/translator/module_collector.ex @@ -193,6 +193,10 @@ defmodule ElixirScript.Translator.ModuleCollector do add_function_to_map(state, type, name, arity) + ({type, _, [{name, _, nil}, [do: _body]]}, state) when type in [:defmacro, :defmacrop] -> + add_function_to_map(state, type, name, 0) + + ({type, _, [{name, _, params}, [do: _body]]}, state) when type in [:defmacro, :defmacrop] -> arity = length(params) diff --git a/lib/elixir_script/translator/rewriter.ex b/lib/elixir_script/translator/rewriter.ex index 9a17481b..38d1aa47 100644 --- a/lib/elixir_script/translator/rewriter.ex +++ b/lib/elixir_script/translator/rewriter.ex @@ -407,6 +407,18 @@ defmodule ElixirScript.Translator.Rewriter do quote do: Elixir.Core.Functions.filtermap(unquote(fun), unquote(list)) end + def rewrite({{:., _, [:lists, :concat]}, _, [things]}) do + quote do: unquote(things).join("") + end + + def rewrite({{:., _, [:erlang, :binary_to_atom]}, _, [binary, _]}) do + quote do: Symbol.for(unquote(binary)) + end + + def rewrite({{:., _, [:erlang, :binary_to_existing_atom]}, _, [binary, _]}) do + quote do: Symbol.for(unquote(binary)) + end + def rewrite({{:., _, [:erlang, :list_to_atom]}, _, [char_list]}) do quote do: Symbol.for(unquote(char_list)) end @@ -431,6 +443,50 @@ defmodule ElixirScript.Translator.Rewriter do quote do: parseInt(unquote(list), unquote(base)) end + def rewrite({{:., _, [:erlang, :integer_to_binary]}, _, [integer]}) do + quote do: unquote(integer).toString() + end + + def rewrite({{:., _, [:erlang, :integer_to_binary]}, _, [integer, base]}) do + quote do: unquote(integer).toString(unquote(base)) + end + + def rewrite({{:., _, [:erlang, :integer_to_list]}, _, [integer]}) do + quote do: unquote(integer).toString() + end + + def rewrite({{:., _, [:erlang, :integer_to_list]}, _, [integer, base]}) do + quote do: unquote(integer).toString(unquote(base)) + end + + def rewrite({{:., _, [:erlang, :float_to_binary]}, _, [float]}) do + quote do: unquote(float).toString() + end + + def rewrite({{:., _, [:erlang, :float_to_binary]}, _, [float, base]}) do + quote do: unquote(float).toString(unquote(base)) + end + + def rewrite({{:., _, [:erlang, :float_to_list]}, _, [float]}) do + quote do: unquote(float).toString() + end + + def rewrite({{:., _, [:erlang, :float_to_list]}, _, [float, base]}) do + quote do: unquote(float).toString(unquote(base)) + end + + def rewrite({{:., _, [:erlang, :binary_to_float]}, _, [binary]}) do + quote do: parseFloat(unquote(binary)) + end + + def rewrite({{:., _, [:erlang, :binary_to_integer]}, _, [binary]}) do + quote do: parseInt(unquote(binary)) + end + + def rewrite({{:., _, [:erlang, :binary_to_integer]}, _, [binary, base]}) do + quote do: parseInt(unquote(binary), unquote(base)) + end + def rewrite({{:., _, [:maps, :is_key]}, _, [key, map]}) do quote do: unquote(key) in Elixir.Core.Functions.get_object_keys(unquote(map)) end @@ -447,5 +503,16 @@ defmodule ElixirScript.Translator.Rewriter do quote do: Elixir.Core.Functions.maps_find(unquote(key), unquote(map)) end + def rewrite({{:., _, [:maps, :remove]}, _, [key, map]}) do + quote do: Elixir.Core.Functions.delete_property_from_map(unquote(map), unquote(key)) + end + + def rewrite({{:., _, [:maps, :fold]}, _, [fun, init, map]}) do + quote do: Elixir.Core.Functions.maps_fold(unquote(fun), unquote(init), unquote(map)) + end + + def rewrite({{:., _, [:maps, :from_list]}, _, [list]}) do + quote do: Elixir.Core.Functions.maps_fold(unquote(list)) + end end diff --git a/src/javascript/lib/core/functions.js b/src/javascript/lib/core/functions.js index 9bcfa1e4..69f66a7f 100644 --- a/src/javascript/lib/core/functions.js +++ b/src/javascript/lib/core/functions.js @@ -364,6 +364,26 @@ function filtermap(fun, list){ return Object.freeze(newlist); } +function maps_fold(fun, acc, map){ + let acc1 = acc; + + for(let k of get_object_keys(map)){ + acc1 = fun(k, map[k], acc1); + } + + return acc1; +} + +function maps_from_list(list){ + let m = {}; + + for(x of list){ + m[x.get(0)] = x.get(1); + } + + return Object.freeze(m); +} + export default { call_property, apply, @@ -401,5 +421,6 @@ export default { flatten, duplicate, mapfoldl, - filtermap + filtermap, + maps_fold }; diff --git a/test/translator/assignment_test.exs b/test/translator/assignment_test.exs index a58f808a..c03f1b7f 100644 --- a/test/translator/assignment_test.exs +++ b/test/translator/assignment_test.exs @@ -71,8 +71,8 @@ defmodule ElixirScript.Translator.Assignment.Test do test "translate head/tail assignment" do ex_ast = quote do: [a | b] = [1, 2, 3, 4] js_code = """ - let [a,b] = Elixir.Core.Patterns.match(Elixir.Core.Patterns.headTail(),Object.freeze([1, 2, 3, 4])); - let _ref = Object.freeze([a, b]); + let [a,b] = Elixir.Core.Patterns.match(Elixir.Core.Patterns.headTail(Elixir.Core.Patterns.variable(),Elixir.Core.Patterns.variable()),Object.freeze([1, 2, 3, 4])); + let _ref = Object.freeze([a, b]); """ assert_translation(ex_ast, js_code) diff --git a/test/translator/function_test.exs b/test/translator/function_test.exs index e0b8f1e4..baa0d82b 100644 --- a/test/translator/function_test.exs +++ b/test/translator/function_test.exs @@ -463,9 +463,9 @@ defmodule ElixirScript.Translator.Function.Test do js_code = """ - const something = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.headTail()],function(apple,fruits) { - return null; - })); + const something = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.headTail(Elixir.Core.Patterns.variable(),Elixir.Core.Patterns.variable())],function(apple,fruits) { + return null; + })); """ assert_translation(ex_ast, js_code) diff --git a/test/translator/kernel_test.exs b/test/translator/kernel_test.exs index 4c7b21aa..533cf51b 100644 --- a/test/translator/kernel_test.exs +++ b/test/translator/kernel_test.exs @@ -2,7 +2,7 @@ defmodule ElixirScript.Translator.Kernel.Test do use ExUnit.Case import ElixirScript.TestHelper - test "raise" do + test "raise with bitstring" do ex_ast = quote do raise ArgumentError, "cannot convert list to string. The list must contain only integers, strings or nested such lists; got: #{inspect list}" end @@ -16,6 +16,20 @@ defmodule ElixirScript.Translator.Kernel.Test do assert_translation(ex_ast, js_code) end + test "raise with string" do + ex_ast = quote do + raise ArgumentError, "cannot convert list to string. The list must contain only integers, strings or nested such lists; got" + end + + js_code = """ + throw ArgumentError.create(Object.freeze({ + [Symbol.for('message')]: 'cannot convert list to string. The list must contain only integers, strings or nested such lists; got' + })); + """ + + assert_translation(ex_ast, js_code) + end + test "max" do ex_ast = quote do max(1, 2) From f684eed565c32ce16983c0ad8fc863cfa8cec369 Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Fri, 19 Feb 2016 12:41:55 -0600 Subject: [PATCH 147/860] Fixed bugs in html module and removed catch from list of js keywords --- lib/elixir_script/prelude/html.ex | 4 +- lib/elixir_script/translator.ex | 15 +- lib/elixir_script/translator/utils.ex | 1 - priv/Elixir.js | 165 ++++++++++++++++-- src/javascript/lib/core/protocol.js | 4 +- .../tests/patterns/defmatch.spec.js | 3 - 6 files changed, 164 insertions(+), 28 deletions(-) diff --git a/lib/elixir_script/prelude/html.ex b/lib/elixir_script/prelude/html.ex index 4a5610d2..a476c134 100644 --- a/lib/elixir_script/prelude/html.ex +++ b/lib/elixir_script/prelude/html.ex @@ -38,7 +38,7 @@ defmodule ElixirScript.Html do { inner, attributes } = do_tag(inner, attrs) quote do - Elixir.VirtualDOM.h(unquote(tag), unquote(attributes), unquote_splicing(inner)) + Elixir.VirtualDOM.h(unquote(tag), unquote(attributes), unquote(inner)) end end @@ -49,7 +49,7 @@ defmodule ElixirScript.Html do { inner, attributes } = do_tag(inner, attributes) quote do - Elixir.VirtualDOM.h(unquote(tag), unquote(attributes), unquote_splicing(inner)) + Elixir.VirtualDOM.h(unquote(tag), unquote(attributes), unquote(inner)) end end end diff --git a/lib/elixir_script/translator.ex b/lib/elixir_script/translator.ex index bd770f8d..8608ea21 100644 --- a/lib/elixir_script/translator.ex +++ b/lib/elixir_script/translator.ex @@ -23,7 +23,18 @@ defmodule ElixirScript.Translator do alias ESTree.Tools.Builder, as: JS alias ElixirScript.Translator.Rewriter - + @erlang_modules [ + :erlang, + :maps, + :lists, + :gen, + :elixir_errors, + :supervisor, + :application, + :code, + :elixir_utils, + :file + ] @doc """ Translates the given Elixir AST to JavaScript AST. The given `env` is a `ElixirScript.Macro.Env` @@ -186,7 +197,7 @@ defmodule ElixirScript.Translator do end end - defp do_translate({{:., _, [erlang_module, _]}, _, _} = erlang_function_call, env) when erlang_module in [:erlang, :maps, :lists] do + defp do_translate({{:., _, [erlang_module, _]}, _, _} = erlang_function_call, env) when erlang_module in @erlang_modules do Rewriter.rewrite(erlang_function_call) |> translate(env) end diff --git a/lib/elixir_script/translator/utils.ex b/lib/elixir_script/translator/utils.ex index 4a443d0a..96020d66 100644 --- a/lib/elixir_script/translator/utils.ex +++ b/lib/elixir_script/translator/utils.ex @@ -7,7 +7,6 @@ defmodule ElixirScript.Translator.Utils do :break, :case, :class, - :catch, :const, :continue, :debugger, diff --git a/priv/Elixir.js b/priv/Elixir.js index b15eaf4b..905299bb 100644 --- a/priv/Elixir.js +++ b/priv/Elixir.js @@ -1690,11 +1690,22 @@ class Tuple { } put_elem(index, elem) { + if (index === this.length) { + let new_values = this.values.concat([elem]); + return new Tuple(...new_values); + } + let new_values = this.values.concat([]); new_values.splice(index, 0, elem); return new Tuple(...new_values); } + remove_elem(index) { + let new_values = this.values.concat([]); + new_values.splice(index, 1); + return new Tuple(...new_values); + } + } let process_counter = -1; @@ -1869,7 +1880,7 @@ class BitString { this.value = Object.freeze(this.process(args)); this.length = this.value.length; - this.bit_size = this.raw_value.reduce((prev, current) => prev + current.size); + this.bit_size = this.raw_value().reduce((prev, current) => prev + current.size); this.byte_size = this.bit_size / 8 + (this.bit_size % 8 > 0 ? 1 : 0); } @@ -2185,7 +2196,11 @@ class Capture { } class HeadTail { - constructor() {} + + constructor(head = null, tail = null) { + this.head = head; + this.tail = tail; + } } class Type { @@ -2219,8 +2234,8 @@ function capture(value) { return new Capture(value); } -function headTail() { - return new HeadTail(); +function headTail(head = null, tail = null) { + return new HeadTail(head, tail); } function type(type, objPattern = {}) { @@ -2374,7 +2389,10 @@ function resolveVariable() { }; } -function resolveHeadTail() { +function resolveHeadTail(pattern) { + const headMatches = buildMatch(pattern.head); + const tailMatches = buildMatch(pattern.tail); + return function (value, args) { if (!Checks.is_array(value) || value.length < 2) { return false; @@ -2383,10 +2401,9 @@ function resolveHeadTail() { const head = value[0]; const tail = value.slice(1); - args.push(head); - args.push(tail); - - return true; + if (headMatches(head, args) && tailMatches(tail, args)) { + return true; + } }; } @@ -2642,9 +2659,9 @@ class Protocol { let fun = null; if (Number.isInteger(thing) && this.hasImplementation(Integer)) { - fun = this.registry.get(Core.Integer)[funName]; + fun = this.registry.get(Integer)[funName]; } else if (typeof thing === "number" && !Number.isInteger(thing) && this.hasImplementation(Float)) { - fun = this.registry.get(Core.Float)[funName]; + fun = this.registry.get(Float)[funName]; } else if (this.hasImplementation(thing)) { fun = this.registry.get(thing.constructor)[funName]; } else if (this.fallback) { @@ -2903,6 +2920,17 @@ function foldr(fun, acc, list) { return acc1; } +function keyfind(key, n, tuplelist) { + + for (let i = tuplelist.length - 1; i >= 0; i--) { + if (tuplelist[i].get(n) === key) { + return tuplelist[i]; + } + } + + return false; +} + function keydelete(key, n, tuplelist) { for (let i = tuplelist.length - 1; i >= 0; i--) { @@ -2921,7 +2949,38 @@ function keystore(key, n, list, newtuple) { } } - return list; + return list.concat([]).push(newtuple); +} + +function keymember(key, n, list) { + for (let i = list.length - 1; i >= 0; i--) { + if (list[i].get(n) === key) { + return true; + } + } + + return false; +} + +function keytake(key, n, list) { + if (!keymember(key, n, list)) { + return false; + } + + let tuple = keyfind(key, n, list); + + return new Tuple(tuple.get(n), tuple, keydelete(key, n, list)); +} + +function keyreplace(key, n, list, newtuple) { + + for (let i = tuplelist.length - 1; i >= 0; i--) { + if (tuplelist[i].get(n) === key) { + return tuplelist.concat([]).splice(i, 1, newtuple); + } + } + + return tuplelist; } function reverse(list) { @@ -2936,6 +2995,68 @@ function maps_find(key, map) { } } +function flatten(list, tail = []) { + let new_list = []; + + for (let e of list) { + if (isArray(e)) { + new_list = new_list.concat(flatten(e)); + } else { + new_list.push(e); + } + } + + return Object.freeze(new_list.concat(tail)); +} + +function duplicate(n, elem) { + let list = []; + + for (let i = 0; i < n; i++) { + list.push(elem); + } + + return Object.freeze(list); +} + +function mapfoldl(fun, acc, list) { + let newlist = []; + + for (let x of list) { + let tup = fun(x, acc); + newlist.push(tup.get(0)); + acc = tup.get(1); + } + + return new Tuple(Object.freeze(newlist), acc); +} + +function filtermap(fun, list) { + let newlist = []; + + for (x of list) { + let result = fun(x); + + if (result === true) { + newlist.push(x); + } else if (result instanceof Tuple) { + newlist.push(result.get(1)); + } + } + + return Object.freeze(newlist); +} + +function maps_fold(fun, acc, map) { + let acc1 = acc; + + for (let k of get_object_keys(map)) { + acc1 = fun(k, map[k], acc1); + } + + return acc1; +} + var Functions = { call_property, apply, @@ -2964,9 +3085,17 @@ var Functions = { remove_from_list, keydelete, keystore, + keyfind, + keytake, + keyreplace, reverse, update_map, - maps_find + maps_find, + flatten, + duplicate, + mapfoldl, + filtermap, + maps_fold }; function _case(condition, clauses) { @@ -3079,7 +3208,7 @@ var SpecialForms$1 = { Functions.get_global().processes = Functions.get_global().processes || new ProcessSystem(); -var Core$1 = { +var Core = { ProcessSystem, Tuple, PID, @@ -3164,7 +3293,7 @@ let Enum = { fetch: function (collection, n) { if (Array.isArray(collection)) { if (n < this.count(collection) && n >= 0) { - return new Core$1.Tuple(Symbol.for("ok"), collection[n]); + return new Core.Tuple(Symbol.for("ok"), collection[n]); } else { return Symbol.for("error"); } @@ -3236,7 +3365,7 @@ let Enum = { mapped = Object.freeze(mapped.concat([tuple.get(0)])); } - return new Core$1.Tuple(mapped, the_acc); + return new Core.Tuple(mapped, the_acc); }, member__qmark__: function (collection, value) { @@ -3292,10 +3421,10 @@ let Enum = { }; var Elixir = { - Core: Core$1, + Core, Enum, VirtualDOM }; export default Elixir; -//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiIiwic291cmNlcyI6WyJFbGl4aXIuanMiXSwic291cmNlc0NvbnRlbnQiOlsibGV0IFZpcnR1YWxET00gPSAoZnVuY3Rpb24gKGUpIHtcbiAgICByZXR1cm4gZSgpO1xufSkoZnVuY3Rpb24gKCkge1xuICAgIHZhciBkZWZpbmUsIG1vZHVsZSwgZXhwb3J0cztcbiAgICByZXR1cm4gKGZ1bmN0aW9uIGUodCwgbiwgcikge1xuICAgICAgICBmdW5jdGlvbiBzKG8sIHUpIHtcbiAgICAgICAgICAgIGlmICghbltvXSkge1xuICAgICAgICAgICAgICAgIGlmICghdFtvXSkge1xuICAgICAgICAgICAgICAgICAgICB2YXIgYSA9IHR5cGVvZiByZXF1aXJlID09IFwiZnVuY3Rpb25cIiAmJiByZXF1aXJlO1xuICAgICAgICAgICAgICAgICAgICBpZiAoIXUgJiYgYSkgcmV0dXJuIGEobywgITApO1xuICAgICAgICAgICAgICAgICAgICBpZiAoaSkgcmV0dXJuIGkobywgITApO1xuICAgICAgICAgICAgICAgICAgICB2YXIgZiA9IG5ldyBFcnJvcihcIkNhbm5vdCBmaW5kIG1vZHVsZSAnXCIgKyBvICsgXCInXCIpO1xuICAgICAgICAgICAgICAgICAgICB0aHJvdyAoZi5jb2RlID0gXCJNT0RVTEVfTk9UX0ZPVU5EXCIsIGYpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB2YXIgbCA9IG5bb10gPSB7XG4gICAgICAgICAgICAgICAgICAgIGV4cG9ydHM6IHt9XG4gICAgICAgICAgICAgICAgfTtcbiAgICAgICAgICAgICAgICB0W29dWzBdLmNhbGwobC5leHBvcnRzLCBmdW5jdGlvbiAoZSkge1xuICAgICAgICAgICAgICAgICAgICB2YXIgbiA9IHRbb11bMV1bZV07XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBzKG4gPyBuIDogZSk7XG4gICAgICAgICAgICAgICAgfSwgbCwgbC5leHBvcnRzLCBlLCB0LCBuLCByKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJldHVybiBuW29dLmV4cG9ydHM7XG4gICAgICAgIH1cbiAgICAgICAgdmFyIGkgPSB0eXBlb2YgcmVxdWlyZSA9PSBcImZ1bmN0aW9uXCIgJiYgcmVxdWlyZTtcbiAgICAgICAgZm9yICh2YXIgbyA9IDA7IG8gPCByLmxlbmd0aDsgbysrKSBzKHJbb10pO1xuICAgICAgICByZXR1cm4gcztcbiAgICB9KSh7XG4gICAgICAgIDE6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG5cbiAgICAgICAgICAgIHZhciBjcmVhdGVFbGVtZW50ID0gcmVxdWlyZShcIi4vdmRvbS9jcmVhdGUtZWxlbWVudC5qc1wiKTtcblxuICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBjcmVhdGVFbGVtZW50O1xuICAgICAgICB9LCB7IFwiLi92ZG9tL2NyZWF0ZS1lbGVtZW50LmpzXCI6IDE1IH1dLCAyOiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge1xuICAgICAgICAgICAgdmFyIGRpZmYgPSByZXF1aXJlKFwiLi92dHJlZS9kaWZmLmpzXCIpO1xuXG4gICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IGRpZmY7XG4gICAgICAgIH0sIHsgXCIuL3Z0cmVlL2RpZmYuanNcIjogMzUgfV0sIDM6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICB2YXIgaCA9IHJlcXVpcmUoXCIuL3ZpcnR1YWwtaHlwZXJzY3JpcHQvaW5kZXguanNcIik7XG5cbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gaDtcbiAgICAgICAgfSwgeyBcIi4vdmlydHVhbC1oeXBlcnNjcmlwdC9pbmRleC5qc1wiOiAyMiB9XSwgNDogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHtcbiAgICAgICAgICAgIHZhciBkaWZmID0gcmVxdWlyZShcIi4vZGlmZi5qc1wiKTtcbiAgICAgICAgICAgIHZhciBwYXRjaCA9IHJlcXVpcmUoXCIuL3BhdGNoLmpzXCIpO1xuICAgICAgICAgICAgdmFyIGggPSByZXF1aXJlKFwiLi9oLmpzXCIpO1xuICAgICAgICAgICAgdmFyIGNyZWF0ZSA9IHJlcXVpcmUoXCIuL2NyZWF0ZS1lbGVtZW50LmpzXCIpO1xuICAgICAgICAgICAgdmFyIFZOb2RlID0gcmVxdWlyZShcIi4vdm5vZGUvdm5vZGUuanNcIik7XG4gICAgICAgICAgICB2YXIgVlRleHQgPSByZXF1aXJlKFwiLi92bm9kZS92dGV4dC5qc1wiKTtcblxuICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSB7XG4gICAgICAgICAgICAgICAgZGlmZjogZGlmZixcbiAgICAgICAgICAgICAgICBwYXRjaDogcGF0Y2gsXG4gICAgICAgICAgICAgICAgaDogaCxcbiAgICAgICAgICAgICAgICBjcmVhdGU6IGNyZWF0ZSxcbiAgICAgICAgICAgICAgICBWTm9kZTogVk5vZGUsXG4gICAgICAgICAgICAgICAgVlRleHQ6IFZUZXh0XG4gICAgICAgICAgICB9O1xuICAgICAgICB9LCB7IFwiLi9jcmVhdGUtZWxlbWVudC5qc1wiOiAxLCBcIi4vZGlmZi5qc1wiOiAyLCBcIi4vaC5qc1wiOiAzLCBcIi4vcGF0Y2guanNcIjogMTMsIFwiLi92bm9kZS92bm9kZS5qc1wiOiAzMSwgXCIuL3Zub2RlL3Z0ZXh0LmpzXCI6IDMzIH1dLCA1OiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge1xuICAgICAgICAgICAgLyohXG4gICAgICAgICAgICAgKiBDcm9zcy1Ccm93c2VyIFNwbGl0IDEuMS4xXG4gICAgICAgICAgICAgKiBDb3B5cmlnaHQgMjAwNy0yMDEyIFN0ZXZlbiBMZXZpdGhhbiA8c3RldmVubGV2aXRoYW4uY29tPlxuICAgICAgICAgICAgICogQXZhaWxhYmxlIHVuZGVyIHRoZSBNSVQgTGljZW5zZVxuICAgICAgICAgICAgICogRUNNQVNjcmlwdCBjb21wbGlhbnQsIHVuaWZvcm0gY3Jvc3MtYnJvd3NlciBzcGxpdCBtZXRob2RcbiAgICAgICAgICAgICAqL1xuXG4gICAgICAgICAgICAvKipcbiAgICAgICAgICAgICAqIFNwbGl0cyBhIHN0cmluZyBpbnRvIGFuIGFycmF5IG9mIHN0cmluZ3MgdXNpbmcgYSByZWdleCBvciBzdHJpbmcgc2VwYXJhdG9yLiBNYXRjaGVzIG9mIHRoZVxuICAgICAgICAgICAgICogc2VwYXJhdG9yIGFyZSBub3QgaW5jbHVkZWQgaW4gdGhlIHJlc3VsdCBhcnJheS4gSG93ZXZlciwgaWYgYHNlcGFyYXRvcmAgaXMgYSByZWdleCB0aGF0IGNvbnRhaW5zXG4gICAgICAgICAgICAgKiBjYXB0dXJpbmcgZ3JvdXBzLCBiYWNrcmVmZXJlbmNlcyBhcmUgc3BsaWNlZCBpbnRvIHRoZSByZXN1bHQgZWFjaCB0aW1lIGBzZXBhcmF0b3JgIGlzIG1hdGNoZWQuXG4gICAgICAgICAgICAgKiBGaXhlcyBicm93c2VyIGJ1Z3MgY29tcGFyZWQgdG8gdGhlIG5hdGl2ZSBgU3RyaW5nLnByb3RvdHlwZS5zcGxpdGAgYW5kIGNhbiBiZSB1c2VkIHJlbGlhYmx5XG4gICAgICAgICAgICAgKiBjcm9zcy1icm93c2VyLlxuICAgICAgICAgICAgICogQHBhcmFtIHtTdHJpbmd9IHN0ciBTdHJpbmcgdG8gc3BsaXQuXG4gICAgICAgICAgICAgKiBAcGFyYW0ge1JlZ0V4cHxTdHJpbmd9IHNlcGFyYXRvciBSZWdleCBvciBzdHJpbmcgdG8gdXNlIGZvciBzZXBhcmF0aW5nIHRoZSBzdHJpbmcuXG4gICAgICAgICAgICAgKiBAcGFyYW0ge051bWJlcn0gW2xpbWl0XSBNYXhpbXVtIG51bWJlciBvZiBpdGVtcyB0byBpbmNsdWRlIGluIHRoZSByZXN1bHQgYXJyYXkuXG4gICAgICAgICAgICAgKiBAcmV0dXJucyB7QXJyYXl9IEFycmF5IG9mIHN1YnN0cmluZ3MuXG4gICAgICAgICAgICAgKiBAZXhhbXBsZVxuICAgICAgICAgICAgICpcbiAgICAgICAgICAgICAqIC8vIEJhc2ljIHVzZVxuICAgICAgICAgICAgICogc3BsaXQoJ2EgYiBjIGQnLCAnICcpO1xuICAgICAgICAgICAgICogLy8gLT4gWydhJywgJ2InLCAnYycsICdkJ11cbiAgICAgICAgICAgICAqXG4gICAgICAgICAgICAgKiAvLyBXaXRoIGxpbWl0XG4gICAgICAgICAgICAgKiBzcGxpdCgnYSBiIGMgZCcsICcgJywgMik7XG4gICAgICAgICAgICAgKiAvLyAtPiBbJ2EnLCAnYiddXG4gICAgICAgICAgICAgKlxuICAgICAgICAgICAgICogLy8gQmFja3JlZmVyZW5jZXMgaW4gcmVzdWx0IGFycmF5XG4gICAgICAgICAgICAgKiBzcGxpdCgnLi53b3JkMSB3b3JkMi4uJywgLyhbYS16XSspKFxcZCspL2kpO1xuICAgICAgICAgICAgICogLy8gLT4gWycuLicsICd3b3JkJywgJzEnLCAnICcsICd3b3JkJywgJzInLCAnLi4nXVxuICAgICAgICAgICAgICovXG4gICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IChmdW5jdGlvbiBzcGxpdCh1bmRlZikge1xuXG4gICAgICAgICAgICAgICAgdmFyIG5hdGl2ZVNwbGl0ID0gU3RyaW5nLnByb3RvdHlwZS5zcGxpdCxcbiAgICAgICAgICAgICAgICAgICAgY29tcGxpYW50RXhlY05wY2cgPSAvKCk/Py8uZXhlYyhcIlwiKVsxXSA9PT0gdW5kZWYsXG5cbiAgICAgICAgICAgICAgICAvLyBOUENHOiBub25wYXJ0aWNpcGF0aW5nIGNhcHR1cmluZyBncm91cFxuICAgICAgICAgICAgICAgIHNlbGY7XG5cbiAgICAgICAgICAgICAgICBzZWxmID0gZnVuY3Rpb24gKHN0ciwgc2VwYXJhdG9yLCBsaW1pdCkge1xuICAgICAgICAgICAgICAgICAgICAvLyBJZiBgc2VwYXJhdG9yYCBpcyBub3QgYSByZWdleCwgdXNlIGBuYXRpdmVTcGxpdGBcbiAgICAgICAgICAgICAgICAgICAgaWYgKE9iamVjdC5wcm90b3R5cGUudG9TdHJpbmcuY2FsbChzZXBhcmF0b3IpICE9PSBcIltvYmplY3QgUmVnRXhwXVwiKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gbmF0aXZlU3BsaXQuY2FsbChzdHIsIHNlcGFyYXRvciwgbGltaXQpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIHZhciBvdXRwdXQgPSBbXSxcbiAgICAgICAgICAgICAgICAgICAgICAgIGZsYWdzID0gKHNlcGFyYXRvci5pZ25vcmVDYXNlID8gXCJpXCIgOiBcIlwiKSArIChzZXBhcmF0b3IubXVsdGlsaW5lID8gXCJtXCIgOiBcIlwiKSArIChzZXBhcmF0b3IuZXh0ZW5kZWQgPyBcInhcIiA6IFwiXCIpICsgKHNlcGFyYXRvci5zdGlja3kgPyBcInlcIiA6IFwiXCIpLFxuXG4gICAgICAgICAgICAgICAgICAgIC8vIEZpcmVmb3ggMytcbiAgICAgICAgICAgICAgICAgICAgbGFzdExhc3RJbmRleCA9IDAsXG5cbiAgICAgICAgICAgICAgICAgICAgLy8gTWFrZSBgZ2xvYmFsYCBhbmQgYXZvaWQgYGxhc3RJbmRleGAgaXNzdWVzIGJ5IHdvcmtpbmcgd2l0aCBhIGNvcHlcbiAgICAgICAgICAgICAgICAgICAgc2VwYXJhdG9yID0gbmV3IFJlZ0V4cChzZXBhcmF0b3Iuc291cmNlLCBmbGFncyArIFwiZ1wiKSxcbiAgICAgICAgICAgICAgICAgICAgICAgIHNlcGFyYXRvcjIsXG4gICAgICAgICAgICAgICAgICAgICAgICBtYXRjaCxcbiAgICAgICAgICAgICAgICAgICAgICAgIGxhc3RJbmRleCxcbiAgICAgICAgICAgICAgICAgICAgICAgIGxhc3RMZW5ndGg7XG4gICAgICAgICAgICAgICAgICAgIHN0ciArPSBcIlwiOyAvLyBUeXBlLWNvbnZlcnRcbiAgICAgICAgICAgICAgICAgICAgaWYgKCFjb21wbGlhbnRFeGVjTnBjZykge1xuICAgICAgICAgICAgICAgICAgICAgICAgLy8gRG9lc24ndCBuZWVkIGZsYWdzIGd5LCBidXQgdGhleSBkb24ndCBodXJ0XG4gICAgICAgICAgICAgICAgICAgICAgICBzZXBhcmF0b3IyID0gbmV3IFJlZ0V4cChcIl5cIiArIHNlcGFyYXRvci5zb3VyY2UgKyBcIiQoPyFcXFxccylcIiwgZmxhZ3MpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIC8qIFZhbHVlcyBmb3IgYGxpbWl0YCwgcGVyIHRoZSBzcGVjOlxuICAgICAgICAgICAgICAgICAgICAgKiBJZiB1bmRlZmluZWQ6IDQyOTQ5NjcyOTUgLy8gTWF0aC5wb3coMiwgMzIpIC0gMVxuICAgICAgICAgICAgICAgICAgICAgKiBJZiAwLCBJbmZpbml0eSwgb3IgTmFOOiAwXG4gICAgICAgICAgICAgICAgICAgICAqIElmIHBvc2l0aXZlIG51bWJlcjogbGltaXQgPSBNYXRoLmZsb29yKGxpbWl0KTsgaWYgKGxpbWl0ID4gNDI5NDk2NzI5NSkgbGltaXQgLT0gNDI5NDk2NzI5NjtcbiAgICAgICAgICAgICAgICAgICAgICogSWYgbmVnYXRpdmUgbnVtYmVyOiA0Mjk0OTY3Mjk2IC0gTWF0aC5mbG9vcihNYXRoLmFicyhsaW1pdCkpXG4gICAgICAgICAgICAgICAgICAgICAqIElmIG90aGVyOiBUeXBlLWNvbnZlcnQsIHRoZW4gdXNlIHRoZSBhYm92ZSBydWxlc1xuICAgICAgICAgICAgICAgICAgICAgKi9cbiAgICAgICAgICAgICAgICAgICAgbGltaXQgPSBsaW1pdCA9PT0gdW5kZWYgPyAtMSA+Pj4gMCA6IC8vIE1hdGgucG93KDIsIDMyKSAtIDFcbiAgICAgICAgICAgICAgICAgICAgbGltaXQgPj4+IDA7IC8vIFRvVWludDMyKGxpbWl0KVxuICAgICAgICAgICAgICAgICAgICB3aGlsZSAobWF0Y2ggPSBzZXBhcmF0b3IuZXhlYyhzdHIpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAvLyBgc2VwYXJhdG9yLmxhc3RJbmRleGAgaXMgbm90IHJlbGlhYmxlIGNyb3NzLWJyb3dzZXJcbiAgICAgICAgICAgICAgICAgICAgICAgIGxhc3RJbmRleCA9IG1hdGNoLmluZGV4ICsgbWF0Y2hbMF0ubGVuZ3RoO1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGxhc3RJbmRleCA+IGxhc3RMYXN0SW5kZXgpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBvdXRwdXQucHVzaChzdHIuc2xpY2UobGFzdExhc3RJbmRleCwgbWF0Y2guaW5kZXgpKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBGaXggYnJvd3NlcnMgd2hvc2UgYGV4ZWNgIG1ldGhvZHMgZG9uJ3QgY29uc2lzdGVudGx5IHJldHVybiBgdW5kZWZpbmVkYCBmb3JcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBub25wYXJ0aWNpcGF0aW5nIGNhcHR1cmluZyBncm91cHNcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoIWNvbXBsaWFudEV4ZWNOcGNnICYmIG1hdGNoLmxlbmd0aCA+IDEpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbWF0Y2hbMF0ucmVwbGFjZShzZXBhcmF0b3IyLCBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBmb3IgKHZhciBpID0gMTsgaSA8IGFyZ3VtZW50cy5sZW5ndGggLSAyOyBpKyspIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoYXJndW1lbnRzW2ldID09PSB1bmRlZikge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBtYXRjaFtpXSA9IHVuZGVmO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChtYXRjaC5sZW5ndGggPiAxICYmIG1hdGNoLmluZGV4IDwgc3RyLmxlbmd0aCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBBcnJheS5wcm90b3R5cGUucHVzaC5hcHBseShvdXRwdXQsIG1hdGNoLnNsaWNlKDEpKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgbGFzdExlbmd0aCA9IG1hdGNoWzBdLmxlbmd0aDtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBsYXN0TGFzdEluZGV4ID0gbGFzdEluZGV4O1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChvdXRwdXQubGVuZ3RoID49IGxpbWl0KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChzZXBhcmF0b3IubGFzdEluZGV4ID09PSBtYXRjaC5pbmRleCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNlcGFyYXRvci5sYXN0SW5kZXgrKzsgLy8gQXZvaWQgYW4gaW5maW5pdGUgbG9vcFxuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIGlmIChsYXN0TGFzdEluZGV4ID09PSBzdHIubGVuZ3RoKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAobGFzdExlbmd0aCB8fCAhc2VwYXJhdG9yLnRlc3QoXCJcIikpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBvdXRwdXQucHVzaChcIlwiKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIG91dHB1dC5wdXNoKHN0ci5zbGljZShsYXN0TGFzdEluZGV4KSk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIG91dHB1dC5sZW5ndGggPiBsaW1pdCA/IG91dHB1dC5zbGljZSgwLCBsaW1pdCkgOiBvdXRwdXQ7XG4gICAgICAgICAgICAgICAgfTtcblxuICAgICAgICAgICAgICAgIHJldHVybiBzZWxmO1xuICAgICAgICAgICAgfSkoKTtcbiAgICAgICAgfSwge31dLCA2OiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge30sIHt9XSwgNzogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHtcbiAgICAgICAgICAgIFwidXNlIHN0cmljdFwiO1xuXG4gICAgICAgICAgICB2YXIgT25lVmVyc2lvbkNvbnN0cmFpbnQgPSByZXF1aXJlKFwiaW5kaXZpZHVhbC9vbmUtdmVyc2lvblwiKTtcblxuICAgICAgICAgICAgdmFyIE1ZX1ZFUlNJT04gPSBcIjdcIjtcbiAgICAgICAgICAgIE9uZVZlcnNpb25Db25zdHJhaW50KFwiZXYtc3RvcmVcIiwgTVlfVkVSU0lPTik7XG5cbiAgICAgICAgICAgIHZhciBoYXNoS2V5ID0gXCJfX0VWX1NUT1JFX0tFWUBcIiArIE1ZX1ZFUlNJT047XG5cbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gRXZTdG9yZTtcblxuICAgICAgICAgICAgZnVuY3Rpb24gRXZTdG9yZShlbGVtKSB7XG4gICAgICAgICAgICAgICAgdmFyIGhhc2ggPSBlbGVtW2hhc2hLZXldO1xuXG4gICAgICAgICAgICAgICAgaWYgKCFoYXNoKSB7XG4gICAgICAgICAgICAgICAgICAgIGhhc2ggPSBlbGVtW2hhc2hLZXldID0ge307XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgcmV0dXJuIGhhc2g7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0sIHsgXCJpbmRpdmlkdWFsL29uZS12ZXJzaW9uXCI6IDkgfV0sIDg6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICAoZnVuY3Rpb24gKGdsb2JhbCkge1xuICAgICAgICAgICAgICAgIFwidXNlIHN0cmljdFwiO1xuXG4gICAgICAgICAgICAgICAgLypnbG9iYWwgd2luZG93LCBnbG9iYWwqL1xuXG4gICAgICAgICAgICAgICAgdmFyIHJvb3QgPSB0eXBlb2Ygd2luZG93ICE9PSBcInVuZGVmaW5lZFwiID8gd2luZG93IDogdHlwZW9mIGdsb2JhbCAhPT0gXCJ1bmRlZmluZWRcIiA/IGdsb2JhbCA6IHt9O1xuXG4gICAgICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBJbmRpdmlkdWFsO1xuXG4gICAgICAgICAgICAgICAgZnVuY3Rpb24gSW5kaXZpZHVhbChrZXksIHZhbHVlKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmIChrZXkgaW4gcm9vdCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHJvb3Rba2V5XTtcbiAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgIHJvb3Rba2V5XSA9IHZhbHVlO1xuXG4gICAgICAgICAgICAgICAgICAgIHJldHVybiB2YWx1ZTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9KS5jYWxsKHRoaXMsIHR5cGVvZiBnbG9iYWwgIT09IFwidW5kZWZpbmVkXCIgPyBnbG9iYWwgOiB0eXBlb2Ygc2VsZiAhPT0gXCJ1bmRlZmluZWRcIiA/IHNlbGYgOiB0eXBlb2Ygd2luZG93ICE9PSBcInVuZGVmaW5lZFwiID8gd2luZG93IDoge30pO1xuICAgICAgICB9LCB7fV0sIDk6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICBcInVzZSBzdHJpY3RcIjtcblxuICAgICAgICAgICAgdmFyIEluZGl2aWR1YWwgPSByZXF1aXJlKFwiLi9pbmRleC5qc1wiKTtcblxuICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBPbmVWZXJzaW9uO1xuXG4gICAgICAgICAgICBmdW5jdGlvbiBPbmVWZXJzaW9uKG1vZHVsZU5hbWUsIHZlcnNpb24sIGRlZmF1bHRWYWx1ZSkge1xuICAgICAgICAgICAgICAgIHZhciBrZXkgPSBcIl9fSU5ESVZJRFVBTF9PTkVfVkVSU0lPTl9cIiArIG1vZHVsZU5hbWU7XG4gICAgICAgICAgICAgICAgdmFyIGVuZm9yY2VLZXkgPSBrZXkgKyBcIl9FTkZPUkNFX1NJTkdMRVRPTlwiO1xuXG4gICAgICAgICAgICAgICAgdmFyIHZlcnNpb25WYWx1ZSA9IEluZGl2aWR1YWwoZW5mb3JjZUtleSwgdmVyc2lvbik7XG5cbiAgICAgICAgICAgICAgICBpZiAodmVyc2lvblZhbHVlICE9PSB2ZXJzaW9uKSB7XG4gICAgICAgICAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcihcIkNhbiBvbmx5IGhhdmUgb25lIGNvcHkgb2YgXCIgKyBtb2R1bGVOYW1lICsgXCIuXFxuXCIgKyBcIllvdSBhbHJlYWR5IGhhdmUgdmVyc2lvbiBcIiArIHZlcnNpb25WYWx1ZSArIFwiIGluc3RhbGxlZC5cXG5cIiArIFwiVGhpcyBtZWFucyB5b3UgY2Fubm90IGluc3RhbGwgdmVyc2lvbiBcIiArIHZlcnNpb24pO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHJldHVybiBJbmRpdmlkdWFsKGtleSwgZGVmYXVsdFZhbHVlKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSwgeyBcIi4vaW5kZXguanNcIjogOCB9XSwgMTA6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICAoZnVuY3Rpb24gKGdsb2JhbCkge1xuICAgICAgICAgICAgICAgIHZhciB0b3BMZXZlbCA9IHR5cGVvZiBnbG9iYWwgIT09IFwidW5kZWZpbmVkXCIgPyBnbG9iYWwgOiB0eXBlb2Ygd2luZG93ICE9PSBcInVuZGVmaW5lZFwiID8gd2luZG93IDoge307XG4gICAgICAgICAgICAgICAgdmFyIG1pbkRvYyA9IHJlcXVpcmUoXCJtaW4tZG9jdW1lbnRcIik7XG5cbiAgICAgICAgICAgICAgICBpZiAodHlwZW9mIGRvY3VtZW50ICE9PSBcInVuZGVmaW5lZFwiKSB7XG4gICAgICAgICAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gZG9jdW1lbnQ7XG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgdmFyIGRvY2N5ID0gdG9wTGV2ZWxbXCJfX0dMT0JBTF9ET0NVTUVOVF9DQUNIRUA0XCJdO1xuXG4gICAgICAgICAgICAgICAgICAgIGlmICghZG9jY3kpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGRvY2N5ID0gdG9wTGV2ZWxbXCJfX0dMT0JBTF9ET0NVTUVOVF9DQUNIRUA0XCJdID0gbWluRG9jO1xuICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBkb2NjeTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9KS5jYWxsKHRoaXMsIHR5cGVvZiBnbG9iYWwgIT09IFwidW5kZWZpbmVkXCIgPyBnbG9iYWwgOiB0eXBlb2Ygc2VsZiAhPT0gXCJ1bmRlZmluZWRcIiA/IHNlbGYgOiB0eXBlb2Ygd2luZG93ICE9PSBcInVuZGVmaW5lZFwiID8gd2luZG93IDoge30pO1xuICAgICAgICB9LCB7IFwibWluLWRvY3VtZW50XCI6IDYgfV0sIDExOiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge1xuICAgICAgICAgICAgXCJ1c2Ugc3RyaWN0XCI7XG5cbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gaXNPYmplY3QoeCkge1xuICAgICAgICAgICAgICAgIHJldHVybiB0eXBlb2YgeCA9PT0gXCJvYmplY3RcIiAmJiB4ICE9PSBudWxsO1xuICAgICAgICAgICAgfTtcbiAgICAgICAgfSwge31dLCAxMjogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHtcbiAgICAgICAgICAgIHZhciBuYXRpdmVJc0FycmF5ID0gQXJyYXkuaXNBcnJheTtcbiAgICAgICAgICAgIHZhciB0b1N0cmluZyA9IE9iamVjdC5wcm90b3R5cGUudG9TdHJpbmc7XG5cbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gbmF0aXZlSXNBcnJheSB8fCBpc0FycmF5O1xuXG4gICAgICAgICAgICBmdW5jdGlvbiBpc0FycmF5KG9iaikge1xuICAgICAgICAgICAgICAgIHJldHVybiB0b1N0cmluZy5jYWxsKG9iaikgPT09IFwiW29iamVjdCBBcnJheV1cIjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSwge31dLCAxMzogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHtcbiAgICAgICAgICAgIHZhciBwYXRjaCA9IHJlcXVpcmUoXCIuL3Zkb20vcGF0Y2guanNcIik7XG5cbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gcGF0Y2g7XG4gICAgICAgIH0sIHsgXCIuL3Zkb20vcGF0Y2guanNcIjogMTggfV0sIDE0OiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge1xuICAgICAgICAgICAgdmFyIGlzT2JqZWN0ID0gcmVxdWlyZShcImlzLW9iamVjdFwiKTtcbiAgICAgICAgICAgIHZhciBpc0hvb2sgPSByZXF1aXJlKFwiLi4vdm5vZGUvaXMtdmhvb2suanNcIik7XG5cbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gYXBwbHlQcm9wZXJ0aWVzO1xuXG4gICAgICAgICAgICBmdW5jdGlvbiBhcHBseVByb3BlcnRpZXMobm9kZSwgcHJvcHMsIHByZXZpb3VzKSB7XG4gICAgICAgICAgICAgICAgZm9yICh2YXIgcHJvcE5hbWUgaW4gcHJvcHMpIHtcbiAgICAgICAgICAgICAgICAgICAgdmFyIHByb3BWYWx1ZSA9IHByb3BzW3Byb3BOYW1lXTtcblxuICAgICAgICAgICAgICAgICAgICBpZiAocHJvcFZhbHVlID09PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJlbW92ZVByb3BlcnR5KG5vZGUsIHByb3BOYW1lLCBwcm9wVmFsdWUsIHByZXZpb3VzKTtcbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIGlmIChpc0hvb2socHJvcFZhbHVlKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgcmVtb3ZlUHJvcGVydHkobm9kZSwgcHJvcE5hbWUsIHByb3BWYWx1ZSwgcHJldmlvdXMpO1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHByb3BWYWx1ZS5ob29rKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcHJvcFZhbHVlLmhvb2sobm9kZSwgcHJvcE5hbWUsIHByZXZpb3VzID8gcHJldmlvdXNbcHJvcE5hbWVdIDogdW5kZWZpbmVkKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChpc09iamVjdChwcm9wVmFsdWUpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcGF0Y2hPYmplY3Qobm9kZSwgcHJvcHMsIHByZXZpb3VzLCBwcm9wTmFtZSwgcHJvcFZhbHVlKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgbm9kZVtwcm9wTmFtZV0gPSBwcm9wVmFsdWU7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIHJlbW92ZVByb3BlcnR5KG5vZGUsIHByb3BOYW1lLCBwcm9wVmFsdWUsIHByZXZpb3VzKSB7XG4gICAgICAgICAgICAgICAgaWYgKHByZXZpb3VzKSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciBwcmV2aW91c1ZhbHVlID0gcHJldmlvdXNbcHJvcE5hbWVdO1xuXG4gICAgICAgICAgICAgICAgICAgIGlmICghaXNIb29rKHByZXZpb3VzVmFsdWUpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAocHJvcE5hbWUgPT09IFwiYXR0cmlidXRlc1wiKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgZm9yICh2YXIgYXR0ck5hbWUgaW4gcHJldmlvdXNWYWx1ZSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBub2RlLnJlbW92ZUF0dHJpYnV0ZShhdHRyTmFtZSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIGlmIChwcm9wTmFtZSA9PT0gXCJzdHlsZVwiKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgZm9yICh2YXIgaSBpbiBwcmV2aW91c1ZhbHVlKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG5vZGUuc3R5bGVbaV0gPSBcIlwiO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAodHlwZW9mIHByZXZpb3VzVmFsdWUgPT09IFwic3RyaW5nXCIpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBub2RlW3Byb3BOYW1lXSA9IFwiXCI7XG4gICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIG5vZGVbcHJvcE5hbWVdID0gbnVsbDtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIGlmIChwcmV2aW91c1ZhbHVlLnVuaG9vaykge1xuICAgICAgICAgICAgICAgICAgICAgICAgcHJldmlvdXNWYWx1ZS51bmhvb2sobm9kZSwgcHJvcE5hbWUsIHByb3BWYWx1ZSk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIHBhdGNoT2JqZWN0KG5vZGUsIHByb3BzLCBwcmV2aW91cywgcHJvcE5hbWUsIHByb3BWYWx1ZSkge1xuICAgICAgICAgICAgICAgIHZhciBwcmV2aW91c1ZhbHVlID0gcHJldmlvdXMgPyBwcmV2aW91c1twcm9wTmFtZV0gOiB1bmRlZmluZWQ7XG5cbiAgICAgICAgICAgICAgICAvLyBTZXQgYXR0cmlidXRlc1xuICAgICAgICAgICAgICAgIGlmIChwcm9wTmFtZSA9PT0gXCJhdHRyaWJ1dGVzXCIpIHtcbiAgICAgICAgICAgICAgICAgICAgZm9yICh2YXIgYXR0ck5hbWUgaW4gcHJvcFZhbHVlKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICB2YXIgYXR0clZhbHVlID0gcHJvcFZhbHVlW2F0dHJOYW1lXTtcblxuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGF0dHJWYWx1ZSA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgbm9kZS5yZW1vdmVBdHRyaWJ1dGUoYXR0ck5hbWUpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBub2RlLnNldEF0dHJpYnV0ZShhdHRyTmFtZSwgYXR0clZhbHVlKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICBpZiAocHJldmlvdXNWYWx1ZSAmJiBpc09iamVjdChwcmV2aW91c1ZhbHVlKSAmJiBnZXRQcm90b3R5cGUocHJldmlvdXNWYWx1ZSkgIT09IGdldFByb3RvdHlwZShwcm9wVmFsdWUpKSB7XG4gICAgICAgICAgICAgICAgICAgIG5vZGVbcHJvcE5hbWVdID0gcHJvcFZhbHVlO1xuICAgICAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgaWYgKCFpc09iamVjdChub2RlW3Byb3BOYW1lXSkpIHtcbiAgICAgICAgICAgICAgICAgICAgbm9kZVtwcm9wTmFtZV0gPSB7fTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICB2YXIgcmVwbGFjZXIgPSBwcm9wTmFtZSA9PT0gXCJzdHlsZVwiID8gXCJcIiA6IHVuZGVmaW5lZDtcblxuICAgICAgICAgICAgICAgIGZvciAodmFyIGsgaW4gcHJvcFZhbHVlKSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciB2YWx1ZSA9IHByb3BWYWx1ZVtrXTtcbiAgICAgICAgICAgICAgICAgICAgbm9kZVtwcm9wTmFtZV1ba10gPSB2YWx1ZSA9PT0gdW5kZWZpbmVkID8gcmVwbGFjZXIgOiB2YWx1ZTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIGdldFByb3RvdHlwZSh2YWx1ZSkge1xuICAgICAgICAgICAgICAgIGlmIChPYmplY3QuZ2V0UHJvdG90eXBlT2YpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIE9iamVjdC5nZXRQcm90b3R5cGVPZih2YWx1ZSk7XG4gICAgICAgICAgICAgICAgfSBlbHNlIGlmICh2YWx1ZS5fX3Byb3RvX18pIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHZhbHVlLl9fcHJvdG9fXztcbiAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKHZhbHVlLmNvbnN0cnVjdG9yKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiB2YWx1ZS5jb25zdHJ1Y3Rvci5wcm90b3R5cGU7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9LCB7IFwiLi4vdm5vZGUvaXMtdmhvb2suanNcIjogMjYsIFwiaXMtb2JqZWN0XCI6IDExIH1dLCAxNTogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHtcbiAgICAgICAgICAgIHZhciBkb2N1bWVudCA9IHJlcXVpcmUoXCJnbG9iYWwvZG9jdW1lbnRcIik7XG5cbiAgICAgICAgICAgIHZhciBhcHBseVByb3BlcnRpZXMgPSByZXF1aXJlKFwiLi9hcHBseS1wcm9wZXJ0aWVzXCIpO1xuXG4gICAgICAgICAgICB2YXIgaXNWTm9kZSA9IHJlcXVpcmUoXCIuLi92bm9kZS9pcy12bm9kZS5qc1wiKTtcbiAgICAgICAgICAgIHZhciBpc1ZUZXh0ID0gcmVxdWlyZShcIi4uL3Zub2RlL2lzLXZ0ZXh0LmpzXCIpO1xuICAgICAgICAgICAgdmFyIGlzV2lkZ2V0ID0gcmVxdWlyZShcIi4uL3Zub2RlL2lzLXdpZGdldC5qc1wiKTtcbiAgICAgICAgICAgIHZhciBoYW5kbGVUaHVuayA9IHJlcXVpcmUoXCIuLi92bm9kZS9oYW5kbGUtdGh1bmsuanNcIik7XG5cbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gY3JlYXRlRWxlbWVudDtcblxuICAgICAgICAgICAgZnVuY3Rpb24gY3JlYXRlRWxlbWVudCh2bm9kZSwgb3B0cykge1xuICAgICAgICAgICAgICAgIHZhciBkb2MgPSBvcHRzID8gb3B0cy5kb2N1bWVudCB8fCBkb2N1bWVudCA6IGRvY3VtZW50O1xuICAgICAgICAgICAgICAgIHZhciB3YXJuID0gb3B0cyA/IG9wdHMud2FybiA6IG51bGw7XG5cbiAgICAgICAgICAgICAgICB2bm9kZSA9IGhhbmRsZVRodW5rKHZub2RlKS5hO1xuXG4gICAgICAgICAgICAgICAgaWYgKGlzV2lkZ2V0KHZub2RlKSkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gdm5vZGUuaW5pdCgpO1xuICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoaXNWVGV4dCh2bm9kZSkpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGRvYy5jcmVhdGVUZXh0Tm9kZSh2bm9kZS50ZXh0KTtcbiAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKCFpc1ZOb2RlKHZub2RlKSkge1xuICAgICAgICAgICAgICAgICAgICBpZiAod2Fybikge1xuICAgICAgICAgICAgICAgICAgICAgICAgd2FybihcIkl0ZW0gaXMgbm90IGEgdmFsaWQgdmlydHVhbCBkb20gbm9kZVwiLCB2bm9kZSk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIG51bGw7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgdmFyIG5vZGUgPSB2bm9kZS5uYW1lc3BhY2UgPT09IG51bGwgPyBkb2MuY3JlYXRlRWxlbWVudCh2bm9kZS50YWdOYW1lKSA6IGRvYy5jcmVhdGVFbGVtZW50TlModm5vZGUubmFtZXNwYWNlLCB2bm9kZS50YWdOYW1lKTtcblxuICAgICAgICAgICAgICAgIHZhciBwcm9wcyA9IHZub2RlLnByb3BlcnRpZXM7XG4gICAgICAgICAgICAgICAgYXBwbHlQcm9wZXJ0aWVzKG5vZGUsIHByb3BzKTtcblxuICAgICAgICAgICAgICAgIHZhciBjaGlsZHJlbiA9IHZub2RlLmNoaWxkcmVuO1xuXG4gICAgICAgICAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCBjaGlsZHJlbi5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgICAgICAgICB2YXIgY2hpbGROb2RlID0gY3JlYXRlRWxlbWVudChjaGlsZHJlbltpXSwgb3B0cyk7XG4gICAgICAgICAgICAgICAgICAgIGlmIChjaGlsZE5vZGUpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIG5vZGUuYXBwZW5kQ2hpbGQoY2hpbGROb2RlKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHJldHVybiBub2RlO1xuICAgICAgICAgICAgfVxuICAgICAgICB9LCB7IFwiLi4vdm5vZGUvaGFuZGxlLXRodW5rLmpzXCI6IDI0LCBcIi4uL3Zub2RlL2lzLXZub2RlLmpzXCI6IDI3LCBcIi4uL3Zub2RlL2lzLXZ0ZXh0LmpzXCI6IDI4LCBcIi4uL3Zub2RlL2lzLXdpZGdldC5qc1wiOiAyOSwgXCIuL2FwcGx5LXByb3BlcnRpZXNcIjogMTQsIFwiZ2xvYmFsL2RvY3VtZW50XCI6IDEwIH1dLCAxNjogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHtcbiAgICAgICAgICAgIC8vIE1hcHMgYSB2aXJ0dWFsIERPTSB0cmVlIG9udG8gYSByZWFsIERPTSB0cmVlIGluIGFuIGVmZmljaWVudCBtYW5uZXIuXG4gICAgICAgICAgICAvLyBXZSBkb24ndCB3YW50IHRvIHJlYWQgYWxsIG9mIHRoZSBET00gbm9kZXMgaW4gdGhlIHRyZWUgc28gd2UgdXNlXG4gICAgICAgICAgICAvLyB0aGUgaW4tb3JkZXIgdHJlZSBpbmRleGluZyB0byBlbGltaW5hdGUgcmVjdXJzaW9uIGRvd24gY2VydGFpbiBicmFuY2hlcy5cbiAgICAgICAgICAgIC8vIFdlIG9ubHkgcmVjdXJzZSBpbnRvIGEgRE9NIG5vZGUgaWYgd2Uga25vdyB0aGF0IGl0IGNvbnRhaW5zIGEgY2hpbGQgb2ZcbiAgICAgICAgICAgIC8vIGludGVyZXN0LlxuXG4gICAgICAgICAgICB2YXIgbm9DaGlsZCA9IHt9O1xuXG4gICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IGRvbUluZGV4O1xuXG4gICAgICAgICAgICBmdW5jdGlvbiBkb21JbmRleChyb290Tm9kZSwgdHJlZSwgaW5kaWNlcywgbm9kZXMpIHtcbiAgICAgICAgICAgICAgICBpZiAoIWluZGljZXMgfHwgaW5kaWNlcy5sZW5ndGggPT09IDApIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHt9O1xuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIGluZGljZXMuc29ydChhc2NlbmRpbmcpO1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gcmVjdXJzZShyb290Tm9kZSwgdHJlZSwgaW5kaWNlcywgbm9kZXMsIDApO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZnVuY3Rpb24gcmVjdXJzZShyb290Tm9kZSwgdHJlZSwgaW5kaWNlcywgbm9kZXMsIHJvb3RJbmRleCkge1xuICAgICAgICAgICAgICAgIG5vZGVzID0gbm9kZXMgfHwge307XG5cbiAgICAgICAgICAgICAgICBpZiAocm9vdE5vZGUpIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKGluZGV4SW5SYW5nZShpbmRpY2VzLCByb290SW5kZXgsIHJvb3RJbmRleCkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIG5vZGVzW3Jvb3RJbmRleF0gPSByb290Tm9kZTtcbiAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgIHZhciB2Q2hpbGRyZW4gPSB0cmVlLmNoaWxkcmVuO1xuXG4gICAgICAgICAgICAgICAgICAgIGlmICh2Q2hpbGRyZW4pIHtcblxuICAgICAgICAgICAgICAgICAgICAgICAgdmFyIGNoaWxkTm9kZXMgPSByb290Tm9kZS5jaGlsZE5vZGVzO1xuXG4gICAgICAgICAgICAgICAgICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IHRyZWUuY2hpbGRyZW4ubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICByb290SW5kZXggKz0gMTtcblxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZhciB2Q2hpbGQgPSB2Q2hpbGRyZW5baV0gfHwgbm9DaGlsZDtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB2YXIgbmV4dEluZGV4ID0gcm9vdEluZGV4ICsgKHZDaGlsZC5jb3VudCB8fCAwKTtcblxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIHNraXAgcmVjdXJzaW9uIGRvd24gdGhlIHRyZWUgaWYgdGhlcmUgYXJlIG5vIG5vZGVzIGRvd24gaGVyZVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChpbmRleEluUmFuZ2UoaW5kaWNlcywgcm9vdEluZGV4LCBuZXh0SW5kZXgpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlY3Vyc2UoY2hpbGROb2Rlc1tpXSwgdkNoaWxkLCBpbmRpY2VzLCBub2Rlcywgcm9vdEluZGV4KTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICByb290SW5kZXggPSBuZXh0SW5kZXg7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICByZXR1cm4gbm9kZXM7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIC8vIEJpbmFyeSBzZWFyY2ggZm9yIGFuIGluZGV4IGluIHRoZSBpbnRlcnZhbCBbbGVmdCwgcmlnaHRdXG4gICAgICAgICAgICBmdW5jdGlvbiBpbmRleEluUmFuZ2UoaW5kaWNlcywgbGVmdCwgcmlnaHQpIHtcbiAgICAgICAgICAgICAgICBpZiAoaW5kaWNlcy5sZW5ndGggPT09IDApIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHZhciBtaW5JbmRleCA9IDA7XG4gICAgICAgICAgICAgICAgdmFyIG1heEluZGV4ID0gaW5kaWNlcy5sZW5ndGggLSAxO1xuICAgICAgICAgICAgICAgIHZhciBjdXJyZW50SW5kZXg7XG4gICAgICAgICAgICAgICAgdmFyIGN1cnJlbnRJdGVtO1xuXG4gICAgICAgICAgICAgICAgd2hpbGUgKG1pbkluZGV4IDw9IG1heEluZGV4KSB7XG4gICAgICAgICAgICAgICAgICAgIGN1cnJlbnRJbmRleCA9IChtYXhJbmRleCArIG1pbkluZGV4KSAvIDIgPj4gMDtcbiAgICAgICAgICAgICAgICAgICAgY3VycmVudEl0ZW0gPSBpbmRpY2VzW2N1cnJlbnRJbmRleF07XG5cbiAgICAgICAgICAgICAgICAgICAgaWYgKG1pbkluZGV4ID09PSBtYXhJbmRleCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGN1cnJlbnRJdGVtID49IGxlZnQgJiYgY3VycmVudEl0ZW0gPD0gcmlnaHQ7XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoY3VycmVudEl0ZW0gPCBsZWZ0KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBtaW5JbmRleCA9IGN1cnJlbnRJbmRleCArIDE7XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoY3VycmVudEl0ZW0gPiByaWdodCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgbWF4SW5kZXggPSBjdXJyZW50SW5kZXggLSAxO1xuICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIGFzY2VuZGluZyhhLCBiKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGEgPiBiID8gMSA6IC0xO1xuICAgICAgICAgICAgfVxuICAgICAgICB9LCB7fV0sIDE3OiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge1xuICAgICAgICAgICAgdmFyIGFwcGx5UHJvcGVydGllcyA9IHJlcXVpcmUoXCIuL2FwcGx5LXByb3BlcnRpZXNcIik7XG5cbiAgICAgICAgICAgIHZhciBpc1dpZGdldCA9IHJlcXVpcmUoXCIuLi92bm9kZS9pcy13aWRnZXQuanNcIik7XG4gICAgICAgICAgICB2YXIgVlBhdGNoID0gcmVxdWlyZShcIi4uL3Zub2RlL3ZwYXRjaC5qc1wiKTtcblxuICAgICAgICAgICAgdmFyIHVwZGF0ZVdpZGdldCA9IHJlcXVpcmUoXCIuL3VwZGF0ZS13aWRnZXRcIik7XG5cbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gYXBwbHlQYXRjaDtcblxuICAgICAgICAgICAgZnVuY3Rpb24gYXBwbHlQYXRjaCh2cGF0Y2gsIGRvbU5vZGUsIHJlbmRlck9wdGlvbnMpIHtcbiAgICAgICAgICAgICAgICB2YXIgdHlwZSA9IHZwYXRjaC50eXBlO1xuICAgICAgICAgICAgICAgIHZhciB2Tm9kZSA9IHZwYXRjaC52Tm9kZTtcbiAgICAgICAgICAgICAgICB2YXIgcGF0Y2ggPSB2cGF0Y2gucGF0Y2g7XG5cbiAgICAgICAgICAgICAgICBzd2l0Y2ggKHR5cGUpIHtcbiAgICAgICAgICAgICAgICAgICAgY2FzZSBWUGF0Y2guUkVNT1ZFOlxuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHJlbW92ZU5vZGUoZG9tTm9kZSwgdk5vZGUpO1xuICAgICAgICAgICAgICAgICAgICBjYXNlIFZQYXRjaC5JTlNFUlQ6XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gaW5zZXJ0Tm9kZShkb21Ob2RlLCBwYXRjaCwgcmVuZGVyT3B0aW9ucyk7XG4gICAgICAgICAgICAgICAgICAgIGNhc2UgVlBhdGNoLlZURVhUOlxuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHN0cmluZ1BhdGNoKGRvbU5vZGUsIHZOb2RlLCBwYXRjaCwgcmVuZGVyT3B0aW9ucyk7XG4gICAgICAgICAgICAgICAgICAgIGNhc2UgVlBhdGNoLldJREdFVDpcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiB3aWRnZXRQYXRjaChkb21Ob2RlLCB2Tm9kZSwgcGF0Y2gsIHJlbmRlck9wdGlvbnMpO1xuICAgICAgICAgICAgICAgICAgICBjYXNlIFZQYXRjaC5WTk9ERTpcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiB2Tm9kZVBhdGNoKGRvbU5vZGUsIHZOb2RlLCBwYXRjaCwgcmVuZGVyT3B0aW9ucyk7XG4gICAgICAgICAgICAgICAgICAgIGNhc2UgVlBhdGNoLk9SREVSOlxuICAgICAgICAgICAgICAgICAgICAgICAgcmVvcmRlckNoaWxkcmVuKGRvbU5vZGUsIHBhdGNoKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBkb21Ob2RlO1xuICAgICAgICAgICAgICAgICAgICBjYXNlIFZQYXRjaC5QUk9QUzpcbiAgICAgICAgICAgICAgICAgICAgICAgIGFwcGx5UHJvcGVydGllcyhkb21Ob2RlLCBwYXRjaCwgdk5vZGUucHJvcGVydGllcyk7XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gZG9tTm9kZTtcbiAgICAgICAgICAgICAgICAgICAgY2FzZSBWUGF0Y2guVEhVTks6XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gcmVwbGFjZVJvb3QoZG9tTm9kZSwgcmVuZGVyT3B0aW9ucy5wYXRjaChkb21Ob2RlLCBwYXRjaCwgcmVuZGVyT3B0aW9ucykpO1xuICAgICAgICAgICAgICAgICAgICBkZWZhdWx0OlxuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGRvbU5vZGU7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBmdW5jdGlvbiByZW1vdmVOb2RlKGRvbU5vZGUsIHZOb2RlKSB7XG4gICAgICAgICAgICAgICAgdmFyIHBhcmVudE5vZGUgPSBkb21Ob2RlLnBhcmVudE5vZGU7XG5cbiAgICAgICAgICAgICAgICBpZiAocGFyZW50Tm9kZSkge1xuICAgICAgICAgICAgICAgICAgICBwYXJlbnROb2RlLnJlbW92ZUNoaWxkKGRvbU5vZGUpO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIGRlc3Ryb3lXaWRnZXQoZG9tTm9kZSwgdk5vZGUpO1xuXG4gICAgICAgICAgICAgICAgcmV0dXJuIG51bGw7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIGluc2VydE5vZGUocGFyZW50Tm9kZSwgdk5vZGUsIHJlbmRlck9wdGlvbnMpIHtcbiAgICAgICAgICAgICAgICB2YXIgbmV3Tm9kZSA9IHJlbmRlck9wdGlvbnMucmVuZGVyKHZOb2RlLCByZW5kZXJPcHRpb25zKTtcblxuICAgICAgICAgICAgICAgIGlmIChwYXJlbnROb2RlKSB7XG4gICAgICAgICAgICAgICAgICAgIHBhcmVudE5vZGUuYXBwZW5kQ2hpbGQobmV3Tm9kZSk7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgcmV0dXJuIHBhcmVudE5vZGU7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIHN0cmluZ1BhdGNoKGRvbU5vZGUsIGxlZnRWTm9kZSwgdlRleHQsIHJlbmRlck9wdGlvbnMpIHtcbiAgICAgICAgICAgICAgICB2YXIgbmV3Tm9kZTtcblxuICAgICAgICAgICAgICAgIGlmIChkb21Ob2RlLm5vZGVUeXBlID09PSAzKSB7XG4gICAgICAgICAgICAgICAgICAgIGRvbU5vZGUucmVwbGFjZURhdGEoMCwgZG9tTm9kZS5sZW5ndGgsIHZUZXh0LnRleHQpO1xuICAgICAgICAgICAgICAgICAgICBuZXdOb2RlID0gZG9tTm9kZTtcbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICB2YXIgcGFyZW50Tm9kZSA9IGRvbU5vZGUucGFyZW50Tm9kZTtcbiAgICAgICAgICAgICAgICAgICAgbmV3Tm9kZSA9IHJlbmRlck9wdGlvbnMucmVuZGVyKHZUZXh0LCByZW5kZXJPcHRpb25zKTtcblxuICAgICAgICAgICAgICAgICAgICBpZiAocGFyZW50Tm9kZSAmJiBuZXdOb2RlICE9PSBkb21Ob2RlKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBwYXJlbnROb2RlLnJlcGxhY2VDaGlsZChuZXdOb2RlLCBkb21Ob2RlKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHJldHVybiBuZXdOb2RlO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBmdW5jdGlvbiB3aWRnZXRQYXRjaChkb21Ob2RlLCBsZWZ0Vk5vZGUsIHdpZGdldCwgcmVuZGVyT3B0aW9ucykge1xuICAgICAgICAgICAgICAgIHZhciB1cGRhdGluZyA9IHVwZGF0ZVdpZGdldChsZWZ0Vk5vZGUsIHdpZGdldCk7XG4gICAgICAgICAgICAgICAgdmFyIG5ld05vZGU7XG5cbiAgICAgICAgICAgICAgICBpZiAodXBkYXRpbmcpIHtcbiAgICAgICAgICAgICAgICAgICAgbmV3Tm9kZSA9IHdpZGdldC51cGRhdGUobGVmdFZOb2RlLCBkb21Ob2RlKSB8fCBkb21Ob2RlO1xuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIG5ld05vZGUgPSByZW5kZXJPcHRpb25zLnJlbmRlcih3aWRnZXQsIHJlbmRlck9wdGlvbnMpO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHZhciBwYXJlbnROb2RlID0gZG9tTm9kZS5wYXJlbnROb2RlO1xuXG4gICAgICAgICAgICAgICAgaWYgKHBhcmVudE5vZGUgJiYgbmV3Tm9kZSAhPT0gZG9tTm9kZSkge1xuICAgICAgICAgICAgICAgICAgICBwYXJlbnROb2RlLnJlcGxhY2VDaGlsZChuZXdOb2RlLCBkb21Ob2RlKTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICBpZiAoIXVwZGF0aW5nKSB7XG4gICAgICAgICAgICAgICAgICAgIGRlc3Ryb3lXaWRnZXQoZG9tTm9kZSwgbGVmdFZOb2RlKTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICByZXR1cm4gbmV3Tm9kZTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZnVuY3Rpb24gdk5vZGVQYXRjaChkb21Ob2RlLCBsZWZ0Vk5vZGUsIHZOb2RlLCByZW5kZXJPcHRpb25zKSB7XG4gICAgICAgICAgICAgICAgdmFyIHBhcmVudE5vZGUgPSBkb21Ob2RlLnBhcmVudE5vZGU7XG4gICAgICAgICAgICAgICAgdmFyIG5ld05vZGUgPSByZW5kZXJPcHRpb25zLnJlbmRlcih2Tm9kZSwgcmVuZGVyT3B0aW9ucyk7XG5cbiAgICAgICAgICAgICAgICBpZiAocGFyZW50Tm9kZSAmJiBuZXdOb2RlICE9PSBkb21Ob2RlKSB7XG4gICAgICAgICAgICAgICAgICAgIHBhcmVudE5vZGUucmVwbGFjZUNoaWxkKG5ld05vZGUsIGRvbU5vZGUpO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHJldHVybiBuZXdOb2RlO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBmdW5jdGlvbiBkZXN0cm95V2lkZ2V0KGRvbU5vZGUsIHcpIHtcbiAgICAgICAgICAgICAgICBpZiAodHlwZW9mIHcuZGVzdHJveSA9PT0gXCJmdW5jdGlvblwiICYmIGlzV2lkZ2V0KHcpKSB7XG4gICAgICAgICAgICAgICAgICAgIHcuZGVzdHJveShkb21Ob2RlKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIHJlb3JkZXJDaGlsZHJlbihkb21Ob2RlLCBtb3Zlcykge1xuICAgICAgICAgICAgICAgIHZhciBjaGlsZE5vZGVzID0gZG9tTm9kZS5jaGlsZE5vZGVzO1xuICAgICAgICAgICAgICAgIHZhciBrZXlNYXAgPSB7fTtcbiAgICAgICAgICAgICAgICB2YXIgbm9kZTtcbiAgICAgICAgICAgICAgICB2YXIgcmVtb3ZlO1xuICAgICAgICAgICAgICAgIHZhciBpbnNlcnQ7XG5cbiAgICAgICAgICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IG1vdmVzLnJlbW92ZXMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgICAgICAgICAgcmVtb3ZlID0gbW92ZXMucmVtb3Zlc1tpXTtcbiAgICAgICAgICAgICAgICAgICAgbm9kZSA9IGNoaWxkTm9kZXNbcmVtb3ZlLmZyb21dO1xuICAgICAgICAgICAgICAgICAgICBpZiAocmVtb3ZlLmtleSkge1xuICAgICAgICAgICAgICAgICAgICAgICAga2V5TWFwW3JlbW92ZS5rZXldID0gbm9kZTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICBkb21Ob2RlLnJlbW92ZUNoaWxkKG5vZGUpO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHZhciBsZW5ndGggPSBjaGlsZE5vZGVzLmxlbmd0aDtcbiAgICAgICAgICAgICAgICBmb3IgKHZhciBqID0gMDsgaiA8IG1vdmVzLmluc2VydHMubGVuZ3RoOyBqKyspIHtcbiAgICAgICAgICAgICAgICAgICAgaW5zZXJ0ID0gbW92ZXMuaW5zZXJ0c1tqXTtcbiAgICAgICAgICAgICAgICAgICAgbm9kZSA9IGtleU1hcFtpbnNlcnQua2V5XTtcbiAgICAgICAgICAgICAgICAgICAgLy8gdGhpcyBpcyB0aGUgd2VpcmRlc3QgYnVnIGkndmUgZXZlciBzZWVuIGluIHdlYmtpdFxuICAgICAgICAgICAgICAgICAgICBkb21Ob2RlLmluc2VydEJlZm9yZShub2RlLCBpbnNlcnQudG8gPj0gbGVuZ3RoKysgPyBudWxsIDogY2hpbGROb2Rlc1tpbnNlcnQudG9dKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIHJlcGxhY2VSb290KG9sZFJvb3QsIG5ld1Jvb3QpIHtcbiAgICAgICAgICAgICAgICBpZiAob2xkUm9vdCAmJiBuZXdSb290ICYmIG9sZFJvb3QgIT09IG5ld1Jvb3QgJiYgb2xkUm9vdC5wYXJlbnROb2RlKSB7XG4gICAgICAgICAgICAgICAgICAgIG9sZFJvb3QucGFyZW50Tm9kZS5yZXBsYWNlQ2hpbGQobmV3Um9vdCwgb2xkUm9vdCk7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgcmV0dXJuIG5ld1Jvb3Q7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0sIHsgXCIuLi92bm9kZS9pcy13aWRnZXQuanNcIjogMjksIFwiLi4vdm5vZGUvdnBhdGNoLmpzXCI6IDMyLCBcIi4vYXBwbHktcHJvcGVydGllc1wiOiAxNCwgXCIuL3VwZGF0ZS13aWRnZXRcIjogMTkgfV0sIDE4OiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge1xuICAgICAgICAgICAgdmFyIGRvY3VtZW50ID0gcmVxdWlyZShcImdsb2JhbC9kb2N1bWVudFwiKTtcbiAgICAgICAgICAgIHZhciBpc0FycmF5ID0gcmVxdWlyZShcIngtaXMtYXJyYXlcIik7XG5cbiAgICAgICAgICAgIHZhciByZW5kZXIgPSByZXF1aXJlKFwiLi9jcmVhdGUtZWxlbWVudFwiKTtcbiAgICAgICAgICAgIHZhciBkb21JbmRleCA9IHJlcXVpcmUoXCIuL2RvbS1pbmRleFwiKTtcbiAgICAgICAgICAgIHZhciBwYXRjaE9wID0gcmVxdWlyZShcIi4vcGF0Y2gtb3BcIik7XG4gICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IHBhdGNoO1xuXG4gICAgICAgICAgICBmdW5jdGlvbiBwYXRjaChyb290Tm9kZSwgcGF0Y2hlcywgcmVuZGVyT3B0aW9ucykge1xuICAgICAgICAgICAgICAgIHJlbmRlck9wdGlvbnMgPSByZW5kZXJPcHRpb25zIHx8IHt9O1xuICAgICAgICAgICAgICAgIHJlbmRlck9wdGlvbnMucGF0Y2ggPSByZW5kZXJPcHRpb25zLnBhdGNoICYmIHJlbmRlck9wdGlvbnMucGF0Y2ggIT09IHBhdGNoID8gcmVuZGVyT3B0aW9ucy5wYXRjaCA6IHBhdGNoUmVjdXJzaXZlO1xuICAgICAgICAgICAgICAgIHJlbmRlck9wdGlvbnMucmVuZGVyID0gcmVuZGVyT3B0aW9ucy5yZW5kZXIgfHwgcmVuZGVyO1xuXG4gICAgICAgICAgICAgICAgcmV0dXJuIHJlbmRlck9wdGlvbnMucGF0Y2gocm9vdE5vZGUsIHBhdGNoZXMsIHJlbmRlck9wdGlvbnMpO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBmdW5jdGlvbiBwYXRjaFJlY3Vyc2l2ZShyb290Tm9kZSwgcGF0Y2hlcywgcmVuZGVyT3B0aW9ucykge1xuICAgICAgICAgICAgICAgIHZhciBpbmRpY2VzID0gcGF0Y2hJbmRpY2VzKHBhdGNoZXMpO1xuXG4gICAgICAgICAgICAgICAgaWYgKGluZGljZXMubGVuZ3RoID09PSAwKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiByb290Tm9kZTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICB2YXIgaW5kZXggPSBkb21JbmRleChyb290Tm9kZSwgcGF0Y2hlcy5hLCBpbmRpY2VzKTtcbiAgICAgICAgICAgICAgICB2YXIgb3duZXJEb2N1bWVudCA9IHJvb3ROb2RlLm93bmVyRG9jdW1lbnQ7XG5cbiAgICAgICAgICAgICAgICBpZiAoIXJlbmRlck9wdGlvbnMuZG9jdW1lbnQgJiYgb3duZXJEb2N1bWVudCAhPT0gZG9jdW1lbnQpIHtcbiAgICAgICAgICAgICAgICAgICAgcmVuZGVyT3B0aW9ucy5kb2N1bWVudCA9IG93bmVyRG9jdW1lbnQ7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCBpbmRpY2VzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciBub2RlSW5kZXggPSBpbmRpY2VzW2ldO1xuICAgICAgICAgICAgICAgICAgICByb290Tm9kZSA9IGFwcGx5UGF0Y2gocm9vdE5vZGUsIGluZGV4W25vZGVJbmRleF0sIHBhdGNoZXNbbm9kZUluZGV4XSwgcmVuZGVyT3B0aW9ucyk7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgcmV0dXJuIHJvb3ROb2RlO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBmdW5jdGlvbiBhcHBseVBhdGNoKHJvb3ROb2RlLCBkb21Ob2RlLCBwYXRjaExpc3QsIHJlbmRlck9wdGlvbnMpIHtcbiAgICAgICAgICAgICAgICBpZiAoIWRvbU5vZGUpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHJvb3ROb2RlO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHZhciBuZXdOb2RlO1xuXG4gICAgICAgICAgICAgICAgaWYgKGlzQXJyYXkocGF0Y2hMaXN0KSkge1xuICAgICAgICAgICAgICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IHBhdGNoTGlzdC5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgICAgICAgICAgICAgbmV3Tm9kZSA9IHBhdGNoT3AocGF0Y2hMaXN0W2ldLCBkb21Ob2RlLCByZW5kZXJPcHRpb25zKTtcblxuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGRvbU5vZGUgPT09IHJvb3ROb2RlKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcm9vdE5vZGUgPSBuZXdOb2RlO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgbmV3Tm9kZSA9IHBhdGNoT3AocGF0Y2hMaXN0LCBkb21Ob2RlLCByZW5kZXJPcHRpb25zKTtcblxuICAgICAgICAgICAgICAgICAgICBpZiAoZG9tTm9kZSA9PT0gcm9vdE5vZGUpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJvb3ROb2RlID0gbmV3Tm9kZTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHJldHVybiByb290Tm9kZTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZnVuY3Rpb24gcGF0Y2hJbmRpY2VzKHBhdGNoZXMpIHtcbiAgICAgICAgICAgICAgICB2YXIgaW5kaWNlcyA9IFtdO1xuXG4gICAgICAgICAgICAgICAgZm9yICh2YXIga2V5IGluIHBhdGNoZXMpIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKGtleSAhPT0gXCJhXCIpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGluZGljZXMucHVzaChOdW1iZXIoa2V5KSk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICByZXR1cm4gaW5kaWNlcztcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSwgeyBcIi4vY3JlYXRlLWVsZW1lbnRcIjogMTUsIFwiLi9kb20taW5kZXhcIjogMTYsIFwiLi9wYXRjaC1vcFwiOiAxNywgXCJnbG9iYWwvZG9jdW1lbnRcIjogMTAsIFwieC1pcy1hcnJheVwiOiAxMiB9XSwgMTk6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICB2YXIgaXNXaWRnZXQgPSByZXF1aXJlKFwiLi4vdm5vZGUvaXMtd2lkZ2V0LmpzXCIpO1xuXG4gICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IHVwZGF0ZVdpZGdldDtcblxuICAgICAgICAgICAgZnVuY3Rpb24gdXBkYXRlV2lkZ2V0KGEsIGIpIHtcbiAgICAgICAgICAgICAgICBpZiAoaXNXaWRnZXQoYSkgJiYgaXNXaWRnZXQoYikpIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKFwibmFtZVwiIGluIGEgJiYgXCJuYW1lXCIgaW4gYikge1xuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGEuaWQgPT09IGIuaWQ7XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gYS5pbml0ID09PSBiLmluaXQ7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0sIHsgXCIuLi92bm9kZS9pcy13aWRnZXQuanNcIjogMjkgfV0sIDIwOiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge1xuICAgICAgICAgICAgXCJ1c2Ugc3RyaWN0XCI7XG5cbiAgICAgICAgICAgIHZhciBFdlN0b3JlID0gcmVxdWlyZShcImV2LXN0b3JlXCIpO1xuXG4gICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IEV2SG9vaztcblxuICAgICAgICAgICAgZnVuY3Rpb24gRXZIb29rKHZhbHVlKSB7XG4gICAgICAgICAgICAgICAgaWYgKCEodGhpcyBpbnN0YW5jZW9mIEV2SG9vaykpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIG5ldyBFdkhvb2sodmFsdWUpO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHRoaXMudmFsdWUgPSB2YWx1ZTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgRXZIb29rLnByb3RvdHlwZS5ob29rID0gZnVuY3Rpb24gKG5vZGUsIHByb3BlcnR5TmFtZSkge1xuICAgICAgICAgICAgICAgIHZhciBlcyA9IEV2U3RvcmUobm9kZSk7XG4gICAgICAgICAgICAgICAgdmFyIHByb3BOYW1lID0gcHJvcGVydHlOYW1lLnN1YnN0cigzKTtcblxuICAgICAgICAgICAgICAgIGVzW3Byb3BOYW1lXSA9IHRoaXMudmFsdWU7XG4gICAgICAgICAgICB9O1xuXG4gICAgICAgICAgICBFdkhvb2sucHJvdG90eXBlLnVuaG9vayA9IGZ1bmN0aW9uIChub2RlLCBwcm9wZXJ0eU5hbWUpIHtcbiAgICAgICAgICAgICAgICB2YXIgZXMgPSBFdlN0b3JlKG5vZGUpO1xuICAgICAgICAgICAgICAgIHZhciBwcm9wTmFtZSA9IHByb3BlcnR5TmFtZS5zdWJzdHIoMyk7XG5cbiAgICAgICAgICAgICAgICBlc1twcm9wTmFtZV0gPSB1bmRlZmluZWQ7XG4gICAgICAgICAgICB9O1xuICAgICAgICB9LCB7IFwiZXYtc3RvcmVcIjogNyB9XSwgMjE6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICBcInVzZSBzdHJpY3RcIjtcblxuICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBTb2Z0U2V0SG9vaztcblxuICAgICAgICAgICAgZnVuY3Rpb24gU29mdFNldEhvb2sodmFsdWUpIHtcbiAgICAgICAgICAgICAgICBpZiAoISh0aGlzIGluc3RhbmNlb2YgU29mdFNldEhvb2spKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBuZXcgU29mdFNldEhvb2sodmFsdWUpO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHRoaXMudmFsdWUgPSB2YWx1ZTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgU29mdFNldEhvb2sucHJvdG90eXBlLmhvb2sgPSBmdW5jdGlvbiAobm9kZSwgcHJvcGVydHlOYW1lKSB7XG4gICAgICAgICAgICAgICAgaWYgKG5vZGVbcHJvcGVydHlOYW1lXSAhPT0gdGhpcy52YWx1ZSkge1xuICAgICAgICAgICAgICAgICAgICBub2RlW3Byb3BlcnR5TmFtZV0gPSB0aGlzLnZhbHVlO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH07XG4gICAgICAgIH0sIHt9XSwgMjI6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICBcInVzZSBzdHJpY3RcIjtcblxuICAgICAgICAgICAgdmFyIGlzQXJyYXkgPSByZXF1aXJlKFwieC1pcy1hcnJheVwiKTtcblxuICAgICAgICAgICAgdmFyIFZOb2RlID0gcmVxdWlyZShcIi4uL3Zub2RlL3Zub2RlLmpzXCIpO1xuICAgICAgICAgICAgdmFyIFZUZXh0ID0gcmVxdWlyZShcIi4uL3Zub2RlL3Z0ZXh0LmpzXCIpO1xuICAgICAgICAgICAgdmFyIGlzVk5vZGUgPSByZXF1aXJlKFwiLi4vdm5vZGUvaXMtdm5vZGVcIik7XG4gICAgICAgICAgICB2YXIgaXNWVGV4dCA9IHJlcXVpcmUoXCIuLi92bm9kZS9pcy12dGV4dFwiKTtcbiAgICAgICAgICAgIHZhciBpc1dpZGdldCA9IHJlcXVpcmUoXCIuLi92bm9kZS9pcy13aWRnZXRcIik7XG4gICAgICAgICAgICB2YXIgaXNIb29rID0gcmVxdWlyZShcIi4uL3Zub2RlL2lzLXZob29rXCIpO1xuICAgICAgICAgICAgdmFyIGlzVlRodW5rID0gcmVxdWlyZShcIi4uL3Zub2RlL2lzLXRodW5rXCIpO1xuXG4gICAgICAgICAgICB2YXIgcGFyc2VUYWcgPSByZXF1aXJlKFwiLi9wYXJzZS10YWcuanNcIik7XG4gICAgICAgICAgICB2YXIgc29mdFNldEhvb2sgPSByZXF1aXJlKFwiLi9ob29rcy9zb2Z0LXNldC1ob29rLmpzXCIpO1xuICAgICAgICAgICAgdmFyIGV2SG9vayA9IHJlcXVpcmUoXCIuL2hvb2tzL2V2LWhvb2suanNcIik7XG5cbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gaDtcblxuICAgICAgICAgICAgZnVuY3Rpb24gaCh0YWdOYW1lLCBwcm9wZXJ0aWVzLCBjaGlsZHJlbikge1xuICAgICAgICAgICAgICAgIHZhciBjaGlsZE5vZGVzID0gW107XG4gICAgICAgICAgICAgICAgdmFyIHRhZywgcHJvcHMsIGtleSwgbmFtZXNwYWNlO1xuXG4gICAgICAgICAgICAgICAgaWYgKCFjaGlsZHJlbiAmJiBpc0NoaWxkcmVuKHByb3BlcnRpZXMpKSB7XG4gICAgICAgICAgICAgICAgICAgIGNoaWxkcmVuID0gcHJvcGVydGllcztcbiAgICAgICAgICAgICAgICAgICAgcHJvcHMgPSB7fTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICBwcm9wcyA9IHByb3BzIHx8IHByb3BlcnRpZXMgfHwge307XG4gICAgICAgICAgICAgICAgdGFnID0gcGFyc2VUYWcodGFnTmFtZSwgcHJvcHMpO1xuXG4gICAgICAgICAgICAgICAgLy8gc3VwcG9ydCBrZXlzXG4gICAgICAgICAgICAgICAgaWYgKHByb3BzLmhhc093blByb3BlcnR5KFwia2V5XCIpKSB7XG4gICAgICAgICAgICAgICAgICAgIGtleSA9IHByb3BzLmtleTtcbiAgICAgICAgICAgICAgICAgICAgcHJvcHMua2V5ID0gdW5kZWZpbmVkO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIC8vIHN1cHBvcnQgbmFtZXNwYWNlXG4gICAgICAgICAgICAgICAgaWYgKHByb3BzLmhhc093blByb3BlcnR5KFwibmFtZXNwYWNlXCIpKSB7XG4gICAgICAgICAgICAgICAgICAgIG5hbWVzcGFjZSA9IHByb3BzLm5hbWVzcGFjZTtcbiAgICAgICAgICAgICAgICAgICAgcHJvcHMubmFtZXNwYWNlID0gdW5kZWZpbmVkO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIC8vIGZpeCBjdXJzb3IgYnVnXG4gICAgICAgICAgICAgICAgaWYgKHRhZyA9PT0gXCJJTlBVVFwiICYmICFuYW1lc3BhY2UgJiYgcHJvcHMuaGFzT3duUHJvcGVydHkoXCJ2YWx1ZVwiKSAmJiBwcm9wcy52YWx1ZSAhPT0gdW5kZWZpbmVkICYmICFpc0hvb2socHJvcHMudmFsdWUpKSB7XG4gICAgICAgICAgICAgICAgICAgIHByb3BzLnZhbHVlID0gc29mdFNldEhvb2socHJvcHMudmFsdWUpO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHRyYW5zZm9ybVByb3BlcnRpZXMocHJvcHMpO1xuXG4gICAgICAgICAgICAgICAgaWYgKGNoaWxkcmVuICE9PSB1bmRlZmluZWQgJiYgY2hpbGRyZW4gIT09IG51bGwpIHtcbiAgICAgICAgICAgICAgICAgICAgYWRkQ2hpbGQoY2hpbGRyZW4sIGNoaWxkTm9kZXMsIHRhZywgcHJvcHMpO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHJldHVybiBuZXcgVk5vZGUodGFnLCBwcm9wcywgY2hpbGROb2Rlcywga2V5LCBuYW1lc3BhY2UpO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBmdW5jdGlvbiBhZGRDaGlsZChjLCBjaGlsZE5vZGVzLCB0YWcsIHByb3BzKSB7XG4gICAgICAgICAgICAgICAgaWYgKHR5cGVvZiBjID09PSBcInN0cmluZ1wiKSB7XG4gICAgICAgICAgICAgICAgICAgIGNoaWxkTm9kZXMucHVzaChuZXcgVlRleHQoYykpO1xuICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAodHlwZW9mIGMgPT09IFwibnVtYmVyXCIpIHtcbiAgICAgICAgICAgICAgICAgICAgY2hpbGROb2Rlcy5wdXNoKG5ldyBWVGV4dChTdHJpbmcoYykpKTtcbiAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKGlzQ2hpbGQoYykpIHtcbiAgICAgICAgICAgICAgICAgICAgY2hpbGROb2Rlcy5wdXNoKGMpO1xuICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoaXNBcnJheShjKSkge1xuICAgICAgICAgICAgICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IGMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGFkZENoaWxkKGNbaV0sIGNoaWxkTm9kZXMsIHRhZywgcHJvcHMpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfSBlbHNlIGlmIChjID09PSBudWxsIHx8IGMgPT09IHVuZGVmaW5lZCkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgdGhyb3cgVW5leHBlY3RlZFZpcnR1YWxFbGVtZW50KHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGZvcmVpZ25PYmplY3Q6IGMsXG4gICAgICAgICAgICAgICAgICAgICAgICBwYXJlbnRWbm9kZToge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRhZ05hbWU6IHRhZyxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBwcm9wZXJ0aWVzOiBwcm9wc1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIHRyYW5zZm9ybVByb3BlcnRpZXMocHJvcHMpIHtcbiAgICAgICAgICAgICAgICBmb3IgKHZhciBwcm9wTmFtZSBpbiBwcm9wcykge1xuICAgICAgICAgICAgICAgICAgICBpZiAocHJvcHMuaGFzT3duUHJvcGVydHkocHJvcE5hbWUpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICB2YXIgdmFsdWUgPSBwcm9wc1twcm9wTmFtZV07XG5cbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChpc0hvb2sodmFsdWUpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgY29udGludWU7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChwcm9wTmFtZS5zdWJzdHIoMCwgMykgPT09IFwiZXYtXCIpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBhZGQgZXYtZm9vIHN1cHBvcnRcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBwcm9wc1twcm9wTmFtZV0gPSBldkhvb2sodmFsdWUpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBmdW5jdGlvbiBpc0NoaWxkKHgpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gaXNWTm9kZSh4KSB8fCBpc1ZUZXh0KHgpIHx8IGlzV2lkZ2V0KHgpIHx8IGlzVlRodW5rKHgpO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBmdW5jdGlvbiBpc0NoaWxkcmVuKHgpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gdHlwZW9mIHggPT09IFwic3RyaW5nXCIgfHwgaXNBcnJheSh4KSB8fCBpc0NoaWxkKHgpO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBmdW5jdGlvbiBVbmV4cGVjdGVkVmlydHVhbEVsZW1lbnQoZGF0YSkge1xuICAgICAgICAgICAgICAgIHZhciBlcnIgPSBuZXcgRXJyb3IoKTtcblxuICAgICAgICAgICAgICAgIGVyci50eXBlID0gXCJ2aXJ0dWFsLWh5cGVyc2NyaXB0LnVuZXhwZWN0ZWQudmlydHVhbC1lbGVtZW50XCI7XG4gICAgICAgICAgICAgICAgZXJyLm1lc3NhZ2UgPSBcIlVuZXhwZWN0ZWQgdmlydHVhbCBjaGlsZCBwYXNzZWQgdG8gaCgpLlxcblwiICsgXCJFeHBlY3RlZCBhIFZOb2RlIC8gVnRodW5rIC8gVldpZGdldCAvIHN0cmluZyBidXQ6XFxuXCIgKyBcImdvdDpcXG5cIiArIGVycm9yU3RyaW5nKGRhdGEuZm9yZWlnbk9iamVjdCkgKyBcIi5cXG5cIiArIFwiVGhlIHBhcmVudCB2bm9kZSBpczpcXG5cIiArIGVycm9yU3RyaW5nKGRhdGEucGFyZW50Vm5vZGUpO1xuICAgICAgICAgICAgICAgIFwiXFxuXCIgKyBcIlN1Z2dlc3RlZCBmaXg6IGNoYW5nZSB5b3VyIGBoKC4uLiwgWyAuLi4gXSlgIGNhbGxzaXRlLlwiO1xuICAgICAgICAgICAgICAgIGVyci5mb3JlaWduT2JqZWN0ID0gZGF0YS5mb3JlaWduT2JqZWN0O1xuICAgICAgICAgICAgICAgIGVyci5wYXJlbnRWbm9kZSA9IGRhdGEucGFyZW50Vm5vZGU7XG5cbiAgICAgICAgICAgICAgICByZXR1cm4gZXJyO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBmdW5jdGlvbiBlcnJvclN0cmluZyhvYmopIHtcbiAgICAgICAgICAgICAgICB0cnkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gSlNPTi5zdHJpbmdpZnkob2JqLCBudWxsLCBcIiAgICBcIik7XG4gICAgICAgICAgICAgICAgfSBjYXRjaCAoZSkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gU3RyaW5nKG9iaik7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9LCB7IFwiLi4vdm5vZGUvaXMtdGh1bmtcIjogMjUsIFwiLi4vdm5vZGUvaXMtdmhvb2tcIjogMjYsIFwiLi4vdm5vZGUvaXMtdm5vZGVcIjogMjcsIFwiLi4vdm5vZGUvaXMtdnRleHRcIjogMjgsIFwiLi4vdm5vZGUvaXMtd2lkZ2V0XCI6IDI5LCBcIi4uL3Zub2RlL3Zub2RlLmpzXCI6IDMxLCBcIi4uL3Zub2RlL3Z0ZXh0LmpzXCI6IDMzLCBcIi4vaG9va3MvZXYtaG9vay5qc1wiOiAyMCwgXCIuL2hvb2tzL3NvZnQtc2V0LWhvb2suanNcIjogMjEsIFwiLi9wYXJzZS10YWcuanNcIjogMjMsIFwieC1pcy1hcnJheVwiOiAxMiB9XSwgMjM6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICBcInVzZSBzdHJpY3RcIjtcblxuICAgICAgICAgICAgdmFyIHNwbGl0ID0gcmVxdWlyZShcImJyb3dzZXItc3BsaXRcIik7XG5cbiAgICAgICAgICAgIHZhciBjbGFzc0lkU3BsaXQgPSAvKFtcXC4jXT9bYS16QS1aMC05XFx1MDA3Ri1cXHVGRkZGXzotXSspLztcbiAgICAgICAgICAgIHZhciBub3RDbGFzc0lkID0gL15cXC58Iy87XG5cbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gcGFyc2VUYWc7XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIHBhcnNlVGFnKHRhZywgcHJvcHMpIHtcbiAgICAgICAgICAgICAgICBpZiAoIXRhZykge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gXCJESVZcIjtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICB2YXIgbm9JZCA9ICFwcm9wcy5oYXNPd25Qcm9wZXJ0eShcImlkXCIpO1xuXG4gICAgICAgICAgICAgICAgdmFyIHRhZ1BhcnRzID0gc3BsaXQodGFnLCBjbGFzc0lkU3BsaXQpO1xuICAgICAgICAgICAgICAgIHZhciB0YWdOYW1lID0gbnVsbDtcblxuICAgICAgICAgICAgICAgIGlmIChub3RDbGFzc0lkLnRlc3QodGFnUGFydHNbMV0pKSB7XG4gICAgICAgICAgICAgICAgICAgIHRhZ05hbWUgPSBcIkRJVlwiO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHZhciBjbGFzc2VzLCBwYXJ0LCB0eXBlLCBpO1xuXG4gICAgICAgICAgICAgICAgZm9yIChpID0gMDsgaSA8IHRhZ1BhcnRzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICAgICAgICAgIHBhcnQgPSB0YWdQYXJ0c1tpXTtcblxuICAgICAgICAgICAgICAgICAgICBpZiAoIXBhcnQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnRpbnVlO1xuICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgdHlwZSA9IHBhcnQuY2hhckF0KDApO1xuXG4gICAgICAgICAgICAgICAgICAgIGlmICghdGFnTmFtZSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgdGFnTmFtZSA9IHBhcnQ7XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAodHlwZSA9PT0gXCIuXCIpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGNsYXNzZXMgPSBjbGFzc2VzIHx8IFtdO1xuICAgICAgICAgICAgICAgICAgICAgICAgY2xhc3Nlcy5wdXNoKHBhcnQuc3Vic3RyaW5nKDEsIHBhcnQubGVuZ3RoKSk7XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAodHlwZSA9PT0gXCIjXCIgJiYgbm9JZCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgcHJvcHMuaWQgPSBwYXJ0LnN1YnN0cmluZygxLCBwYXJ0Lmxlbmd0aCk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICBpZiAoY2xhc3Nlcykge1xuICAgICAgICAgICAgICAgICAgICBpZiAocHJvcHMuY2xhc3NOYW1lKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBjbGFzc2VzLnB1c2gocHJvcHMuY2xhc3NOYW1lKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgIHByb3BzLmNsYXNzTmFtZSA9IGNsYXNzZXMuam9pbihcIiBcIik7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgcmV0dXJuIHByb3BzLm5hbWVzcGFjZSA/IHRhZ05hbWUgOiB0YWdOYW1lLnRvVXBwZXJDYXNlKCk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0sIHsgXCJicm93c2VyLXNwbGl0XCI6IDUgfV0sIDI0OiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge1xuICAgICAgICAgICAgdmFyIGlzVk5vZGUgPSByZXF1aXJlKFwiLi9pcy12bm9kZVwiKTtcbiAgICAgICAgICAgIHZhciBpc1ZUZXh0ID0gcmVxdWlyZShcIi4vaXMtdnRleHRcIik7XG4gICAgICAgICAgICB2YXIgaXNXaWRnZXQgPSByZXF1aXJlKFwiLi9pcy13aWRnZXRcIik7XG4gICAgICAgICAgICB2YXIgaXNUaHVuayA9IHJlcXVpcmUoXCIuL2lzLXRodW5rXCIpO1xuXG4gICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IGhhbmRsZVRodW5rO1xuXG4gICAgICAgICAgICBmdW5jdGlvbiBoYW5kbGVUaHVuayhhLCBiKSB7XG4gICAgICAgICAgICAgICAgdmFyIHJlbmRlcmVkQSA9IGE7XG4gICAgICAgICAgICAgICAgdmFyIHJlbmRlcmVkQiA9IGI7XG5cbiAgICAgICAgICAgICAgICBpZiAoaXNUaHVuayhiKSkge1xuICAgICAgICAgICAgICAgICAgICByZW5kZXJlZEIgPSByZW5kZXJUaHVuayhiLCBhKTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICBpZiAoaXNUaHVuayhhKSkge1xuICAgICAgICAgICAgICAgICAgICByZW5kZXJlZEEgPSByZW5kZXJUaHVuayhhLCBudWxsKTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgICAgICAgICBhOiByZW5kZXJlZEEsXG4gICAgICAgICAgICAgICAgICAgIGI6IHJlbmRlcmVkQlxuICAgICAgICAgICAgICAgIH07XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIHJlbmRlclRodW5rKHRodW5rLCBwcmV2aW91cykge1xuICAgICAgICAgICAgICAgIHZhciByZW5kZXJlZFRodW5rID0gdGh1bmsudm5vZGU7XG5cbiAgICAgICAgICAgICAgICBpZiAoIXJlbmRlcmVkVGh1bmspIHtcbiAgICAgICAgICAgICAgICAgICAgcmVuZGVyZWRUaHVuayA9IHRodW5rLnZub2RlID0gdGh1bmsucmVuZGVyKHByZXZpb3VzKTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICBpZiAoIShpc1ZOb2RlKHJlbmRlcmVkVGh1bmspIHx8IGlzVlRleHQocmVuZGVyZWRUaHVuaykgfHwgaXNXaWRnZXQocmVuZGVyZWRUaHVuaykpKSB7XG4gICAgICAgICAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcihcInRodW5rIGRpZCBub3QgcmV0dXJuIGEgdmFsaWQgbm9kZVwiKTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICByZXR1cm4gcmVuZGVyZWRUaHVuaztcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSwgeyBcIi4vaXMtdGh1bmtcIjogMjUsIFwiLi9pcy12bm9kZVwiOiAyNywgXCIuL2lzLXZ0ZXh0XCI6IDI4LCBcIi4vaXMtd2lkZ2V0XCI6IDI5IH1dLCAyNTogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHtcbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gaXNUaHVuaztcblxuICAgICAgICAgICAgZnVuY3Rpb24gaXNUaHVuayh0KSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHQgJiYgdC50eXBlID09PSBcIlRodW5rXCI7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0sIHt9XSwgMjY6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IGlzSG9vaztcblxuICAgICAgICAgICAgZnVuY3Rpb24gaXNIb29rKGhvb2spIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gaG9vayAmJiAodHlwZW9mIGhvb2suaG9vayA9PT0gXCJmdW5jdGlvblwiICYmICFob29rLmhhc093blByb3BlcnR5KFwiaG9va1wiKSB8fCB0eXBlb2YgaG9vay51bmhvb2sgPT09IFwiZnVuY3Rpb25cIiAmJiAhaG9vay5oYXNPd25Qcm9wZXJ0eShcInVuaG9va1wiKSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0sIHt9XSwgMjc6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICB2YXIgdmVyc2lvbiA9IHJlcXVpcmUoXCIuL3ZlcnNpb25cIik7XG5cbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gaXNWaXJ0dWFsTm9kZTtcblxuICAgICAgICAgICAgZnVuY3Rpb24gaXNWaXJ0dWFsTm9kZSh4KSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHggJiYgeC50eXBlID09PSBcIlZpcnR1YWxOb2RlXCIgJiYgeC52ZXJzaW9uID09PSB2ZXJzaW9uO1xuICAgICAgICAgICAgfVxuICAgICAgICB9LCB7IFwiLi92ZXJzaW9uXCI6IDMwIH1dLCAyODogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHtcbiAgICAgICAgICAgIHZhciB2ZXJzaW9uID0gcmVxdWlyZShcIi4vdmVyc2lvblwiKTtcblxuICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBpc1ZpcnR1YWxUZXh0O1xuXG4gICAgICAgICAgICBmdW5jdGlvbiBpc1ZpcnR1YWxUZXh0KHgpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4geCAmJiB4LnR5cGUgPT09IFwiVmlydHVhbFRleHRcIiAmJiB4LnZlcnNpb24gPT09IHZlcnNpb247XG4gICAgICAgICAgICB9XG4gICAgICAgIH0sIHsgXCIuL3ZlcnNpb25cIjogMzAgfV0sIDI5OiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge1xuICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBpc1dpZGdldDtcblxuICAgICAgICAgICAgZnVuY3Rpb24gaXNXaWRnZXQodykge1xuICAgICAgICAgICAgICAgIHJldHVybiB3ICYmIHcudHlwZSA9PT0gXCJXaWRnZXRcIjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSwge31dLCAzMDogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHtcbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gXCIyXCI7XG4gICAgICAgIH0sIHt9XSwgMzE6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICB2YXIgdmVyc2lvbiA9IHJlcXVpcmUoXCIuL3ZlcnNpb25cIik7XG4gICAgICAgICAgICB2YXIgaXNWTm9kZSA9IHJlcXVpcmUoXCIuL2lzLXZub2RlXCIpO1xuICAgICAgICAgICAgdmFyIGlzV2lkZ2V0ID0gcmVxdWlyZShcIi4vaXMtd2lkZ2V0XCIpO1xuICAgICAgICAgICAgdmFyIGlzVGh1bmsgPSByZXF1aXJlKFwiLi9pcy10aHVua1wiKTtcbiAgICAgICAgICAgIHZhciBpc1ZIb29rID0gcmVxdWlyZShcIi4vaXMtdmhvb2tcIik7XG5cbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gVmlydHVhbE5vZGU7XG5cbiAgICAgICAgICAgIHZhciBub1Byb3BlcnRpZXMgPSB7fTtcbiAgICAgICAgICAgIHZhciBub0NoaWxkcmVuID0gW107XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIFZpcnR1YWxOb2RlKHRhZ05hbWUsIHByb3BlcnRpZXMsIGNoaWxkcmVuLCBrZXksIG5hbWVzcGFjZSkge1xuICAgICAgICAgICAgICAgIHRoaXMudGFnTmFtZSA9IHRhZ05hbWU7XG4gICAgICAgICAgICAgICAgdGhpcy5wcm9wZXJ0aWVzID0gcHJvcGVydGllcyB8fCBub1Byb3BlcnRpZXM7XG4gICAgICAgICAgICAgICAgdGhpcy5jaGlsZHJlbiA9IGNoaWxkcmVuIHx8IG5vQ2hpbGRyZW47XG4gICAgICAgICAgICAgICAgdGhpcy5rZXkgPSBrZXkgIT0gbnVsbCA/IFN0cmluZyhrZXkpIDogdW5kZWZpbmVkO1xuICAgICAgICAgICAgICAgIHRoaXMubmFtZXNwYWNlID0gdHlwZW9mIG5hbWVzcGFjZSA9PT0gXCJzdHJpbmdcIiA/IG5hbWVzcGFjZSA6IG51bGw7XG5cbiAgICAgICAgICAgICAgICB2YXIgY291bnQgPSBjaGlsZHJlbiAmJiBjaGlsZHJlbi5sZW5ndGggfHwgMDtcbiAgICAgICAgICAgICAgICB2YXIgZGVzY2VuZGFudHMgPSAwO1xuICAgICAgICAgICAgICAgIHZhciBoYXNXaWRnZXRzID0gZmFsc2U7XG4gICAgICAgICAgICAgICAgdmFyIGhhc1RodW5rcyA9IGZhbHNlO1xuICAgICAgICAgICAgICAgIHZhciBkZXNjZW5kYW50SG9va3MgPSBmYWxzZTtcbiAgICAgICAgICAgICAgICB2YXIgaG9va3M7XG5cbiAgICAgICAgICAgICAgICBmb3IgKHZhciBwcm9wTmFtZSBpbiBwcm9wZXJ0aWVzKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmIChwcm9wZXJ0aWVzLmhhc093blByb3BlcnR5KHByb3BOYW1lKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgdmFyIHByb3BlcnR5ID0gcHJvcGVydGllc1twcm9wTmFtZV07XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoaXNWSG9vayhwcm9wZXJ0eSkgJiYgcHJvcGVydHkudW5ob29rKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKCFob29rcykge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBob29rcyA9IHt9O1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGhvb2tzW3Byb3BOYW1lXSA9IHByb3BlcnR5O1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCBjb3VudDsgaSsrKSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciBjaGlsZCA9IGNoaWxkcmVuW2ldO1xuICAgICAgICAgICAgICAgICAgICBpZiAoaXNWTm9kZShjaGlsZCkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGRlc2NlbmRhbnRzICs9IGNoaWxkLmNvdW50IHx8IDA7XG5cbiAgICAgICAgICAgICAgICAgICAgICAgIGlmICghaGFzV2lkZ2V0cyAmJiBjaGlsZC5oYXNXaWRnZXRzKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaGFzV2lkZ2V0cyA9IHRydWU7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgICAgIGlmICghaGFzVGh1bmtzICYmIGNoaWxkLmhhc1RodW5rcykge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGhhc1RodW5rcyA9IHRydWU7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgICAgIGlmICghZGVzY2VuZGFudEhvb2tzICYmIChjaGlsZC5ob29rcyB8fCBjaGlsZC5kZXNjZW5kYW50SG9va3MpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgZGVzY2VuZGFudEhvb2tzID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIGlmICghaGFzV2lkZ2V0cyAmJiBpc1dpZGdldChjaGlsZCkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmICh0eXBlb2YgY2hpbGQuZGVzdHJveSA9PT0gXCJmdW5jdGlvblwiKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaGFzV2lkZ2V0cyA9IHRydWU7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoIWhhc1RodW5rcyAmJiBpc1RodW5rKGNoaWxkKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgaGFzVGh1bmtzID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHRoaXMuY291bnQgPSBjb3VudCArIGRlc2NlbmRhbnRzO1xuICAgICAgICAgICAgICAgIHRoaXMuaGFzV2lkZ2V0cyA9IGhhc1dpZGdldHM7XG4gICAgICAgICAgICAgICAgdGhpcy5oYXNUaHVua3MgPSBoYXNUaHVua3M7XG4gICAgICAgICAgICAgICAgdGhpcy5ob29rcyA9IGhvb2tzO1xuICAgICAgICAgICAgICAgIHRoaXMuZGVzY2VuZGFudEhvb2tzID0gZGVzY2VuZGFudEhvb2tzO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBWaXJ0dWFsTm9kZS5wcm90b3R5cGUudmVyc2lvbiA9IHZlcnNpb247XG4gICAgICAgICAgICBWaXJ0dWFsTm9kZS5wcm90b3R5cGUudHlwZSA9IFwiVmlydHVhbE5vZGVcIjtcbiAgICAgICAgfSwgeyBcIi4vaXMtdGh1bmtcIjogMjUsIFwiLi9pcy12aG9va1wiOiAyNiwgXCIuL2lzLXZub2RlXCI6IDI3LCBcIi4vaXMtd2lkZ2V0XCI6IDI5LCBcIi4vdmVyc2lvblwiOiAzMCB9XSwgMzI6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICB2YXIgdmVyc2lvbiA9IHJlcXVpcmUoXCIuL3ZlcnNpb25cIik7XG5cbiAgICAgICAgICAgIFZpcnR1YWxQYXRjaC5OT05FID0gMDtcbiAgICAgICAgICAgIFZpcnR1YWxQYXRjaC5WVEVYVCA9IDE7XG4gICAgICAgICAgICBWaXJ0dWFsUGF0Y2guVk5PREUgPSAyO1xuICAgICAgICAgICAgVmlydHVhbFBhdGNoLldJREdFVCA9IDM7XG4gICAgICAgICAgICBWaXJ0dWFsUGF0Y2guUFJPUFMgPSA0O1xuICAgICAgICAgICAgVmlydHVhbFBhdGNoLk9SREVSID0gNTtcbiAgICAgICAgICAgIFZpcnR1YWxQYXRjaC5JTlNFUlQgPSA2O1xuICAgICAgICAgICAgVmlydHVhbFBhdGNoLlJFTU9WRSA9IDc7XG4gICAgICAgICAgICBWaXJ0dWFsUGF0Y2guVEhVTksgPSA4O1xuXG4gICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IFZpcnR1YWxQYXRjaDtcblxuICAgICAgICAgICAgZnVuY3Rpb24gVmlydHVhbFBhdGNoKHR5cGUsIHZOb2RlLCBwYXRjaCkge1xuICAgICAgICAgICAgICAgIHRoaXMudHlwZSA9IE51bWJlcih0eXBlKTtcbiAgICAgICAgICAgICAgICB0aGlzLnZOb2RlID0gdk5vZGU7XG4gICAgICAgICAgICAgICAgdGhpcy5wYXRjaCA9IHBhdGNoO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBWaXJ0dWFsUGF0Y2gucHJvdG90eXBlLnZlcnNpb24gPSB2ZXJzaW9uO1xuICAgICAgICAgICAgVmlydHVhbFBhdGNoLnByb3RvdHlwZS50eXBlID0gXCJWaXJ0dWFsUGF0Y2hcIjtcbiAgICAgICAgfSwgeyBcIi4vdmVyc2lvblwiOiAzMCB9XSwgMzM6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICB2YXIgdmVyc2lvbiA9IHJlcXVpcmUoXCIuL3ZlcnNpb25cIik7XG5cbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gVmlydHVhbFRleHQ7XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIFZpcnR1YWxUZXh0KHRleHQpIHtcbiAgICAgICAgICAgICAgICB0aGlzLnRleHQgPSBTdHJpbmcodGV4dCk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIFZpcnR1YWxUZXh0LnByb3RvdHlwZS52ZXJzaW9uID0gdmVyc2lvbjtcbiAgICAgICAgICAgIFZpcnR1YWxUZXh0LnByb3RvdHlwZS50eXBlID0gXCJWaXJ0dWFsVGV4dFwiO1xuICAgICAgICB9LCB7IFwiLi92ZXJzaW9uXCI6IDMwIH1dLCAzNDogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHtcbiAgICAgICAgICAgIHZhciBpc09iamVjdCA9IHJlcXVpcmUoXCJpcy1vYmplY3RcIik7XG4gICAgICAgICAgICB2YXIgaXNIb29rID0gcmVxdWlyZShcIi4uL3Zub2RlL2lzLXZob29rXCIpO1xuXG4gICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IGRpZmZQcm9wcztcblxuICAgICAgICAgICAgZnVuY3Rpb24gZGlmZlByb3BzKGEsIGIpIHtcbiAgICAgICAgICAgICAgICB2YXIgZGlmZjtcblxuICAgICAgICAgICAgICAgIGZvciAodmFyIGFLZXkgaW4gYSkge1xuICAgICAgICAgICAgICAgICAgICBpZiAoIShhS2V5IGluIGIpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBkaWZmID0gZGlmZiB8fCB7fTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGRpZmZbYUtleV0gPSB1bmRlZmluZWQ7XG4gICAgICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgICAgICB2YXIgYVZhbHVlID0gYVthS2V5XTtcbiAgICAgICAgICAgICAgICAgICAgdmFyIGJWYWx1ZSA9IGJbYUtleV07XG5cbiAgICAgICAgICAgICAgICAgICAgaWYgKGFWYWx1ZSA9PT0gYlZhbHVlKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBjb250aW51ZTtcbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIGlmIChpc09iamVjdChhVmFsdWUpICYmIGlzT2JqZWN0KGJWYWx1ZSkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChnZXRQcm90b3R5cGUoYlZhbHVlKSAhPT0gZ2V0UHJvdG90eXBlKGFWYWx1ZSkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBkaWZmID0gZGlmZiB8fCB7fTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBkaWZmW2FLZXldID0gYlZhbHVlO1xuICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIGlmIChpc0hvb2soYlZhbHVlKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRpZmYgPSBkaWZmIHx8IHt9O1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRpZmZbYUtleV0gPSBiVmFsdWU7XG4gICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZhciBvYmplY3REaWZmID0gZGlmZlByb3BzKGFWYWx1ZSwgYlZhbHVlKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAob2JqZWN0RGlmZikge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBkaWZmID0gZGlmZiB8fCB7fTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZGlmZlthS2V5XSA9IG9iamVjdERpZmY7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgZGlmZiA9IGRpZmYgfHwge307XG4gICAgICAgICAgICAgICAgICAgICAgICBkaWZmW2FLZXldID0gYlZhbHVlO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgZm9yICh2YXIgYktleSBpbiBiKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmICghKGJLZXkgaW4gYSkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGRpZmYgPSBkaWZmIHx8IHt9O1xuICAgICAgICAgICAgICAgICAgICAgICAgZGlmZltiS2V5XSA9IGJbYktleV07XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICByZXR1cm4gZGlmZjtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZnVuY3Rpb24gZ2V0UHJvdG90eXBlKHZhbHVlKSB7XG4gICAgICAgICAgICAgICAgaWYgKE9iamVjdC5nZXRQcm90b3R5cGVPZikge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gT2JqZWN0LmdldFByb3RvdHlwZU9mKHZhbHVlKTtcbiAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKHZhbHVlLl9fcHJvdG9fXykge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gdmFsdWUuX19wcm90b19fO1xuICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAodmFsdWUuY29uc3RydWN0b3IpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHZhbHVlLmNvbnN0cnVjdG9yLnByb3RvdHlwZTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH0sIHsgXCIuLi92bm9kZS9pcy12aG9va1wiOiAyNiwgXCJpcy1vYmplY3RcIjogMTEgfV0sIDM1OiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge1xuICAgICAgICAgICAgdmFyIGlzQXJyYXkgPSByZXF1aXJlKFwieC1pcy1hcnJheVwiKTtcblxuICAgICAgICAgICAgdmFyIFZQYXRjaCA9IHJlcXVpcmUoXCIuLi92bm9kZS92cGF0Y2hcIik7XG4gICAgICAgICAgICB2YXIgaXNWTm9kZSA9IHJlcXVpcmUoXCIuLi92bm9kZS9pcy12bm9kZVwiKTtcbiAgICAgICAgICAgIHZhciBpc1ZUZXh0ID0gcmVxdWlyZShcIi4uL3Zub2RlL2lzLXZ0ZXh0XCIpO1xuICAgICAgICAgICAgdmFyIGlzV2lkZ2V0ID0gcmVxdWlyZShcIi4uL3Zub2RlL2lzLXdpZGdldFwiKTtcbiAgICAgICAgICAgIHZhciBpc1RodW5rID0gcmVxdWlyZShcIi4uL3Zub2RlL2lzLXRodW5rXCIpO1xuICAgICAgICAgICAgdmFyIGhhbmRsZVRodW5rID0gcmVxdWlyZShcIi4uL3Zub2RlL2hhbmRsZS10aHVua1wiKTtcblxuICAgICAgICAgICAgdmFyIGRpZmZQcm9wcyA9IHJlcXVpcmUoXCIuL2RpZmYtcHJvcHNcIik7XG5cbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gZGlmZjtcblxuICAgICAgICAgICAgZnVuY3Rpb24gZGlmZihhLCBiKSB7XG4gICAgICAgICAgICAgICAgdmFyIHBhdGNoID0geyBhOiBhIH07XG4gICAgICAgICAgICAgICAgd2FsayhhLCBiLCBwYXRjaCwgMCk7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHBhdGNoO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBmdW5jdGlvbiB3YWxrKGEsIGIsIHBhdGNoLCBpbmRleCkge1xuICAgICAgICAgICAgICAgIGlmIChhID09PSBiKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICB2YXIgYXBwbHkgPSBwYXRjaFtpbmRleF07XG4gICAgICAgICAgICAgICAgdmFyIGFwcGx5Q2xlYXIgPSBmYWxzZTtcblxuICAgICAgICAgICAgICAgIGlmIChpc1RodW5rKGEpIHx8IGlzVGh1bmsoYikpIHtcbiAgICAgICAgICAgICAgICAgICAgdGh1bmtzKGEsIGIsIHBhdGNoLCBpbmRleCk7XG4gICAgICAgICAgICAgICAgfSBlbHNlIGlmIChiID09IG51bGwpIHtcblxuICAgICAgICAgICAgICAgICAgICAvLyBJZiBhIGlzIGEgd2lkZ2V0IHdlIHdpbGwgYWRkIGEgcmVtb3ZlIHBhdGNoIGZvciBpdFxuICAgICAgICAgICAgICAgICAgICAvLyBPdGhlcndpc2UgYW55IGNoaWxkIHdpZGdldHMvaG9va3MgbXVzdCBiZSBkZXN0cm95ZWQuXG4gICAgICAgICAgICAgICAgICAgIC8vIFRoaXMgcHJldmVudHMgYWRkaW5nIHR3byByZW1vdmUgcGF0Y2hlcyBmb3IgYSB3aWRnZXQuXG4gICAgICAgICAgICAgICAgICAgIGlmICghaXNXaWRnZXQoYSkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGNsZWFyU3RhdGUoYSwgcGF0Y2gsIGluZGV4KTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGFwcGx5ID0gcGF0Y2hbaW5kZXhdO1xuICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgYXBwbHkgPSBhcHBlbmRQYXRjaChhcHBseSwgbmV3IFZQYXRjaChWUGF0Y2guUkVNT1ZFLCBhLCBiKSk7XG4gICAgICAgICAgICAgICAgfSBlbHNlIGlmIChpc1ZOb2RlKGIpKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmIChpc1ZOb2RlKGEpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoYS50YWdOYW1lID09PSBiLnRhZ05hbWUgJiYgYS5uYW1lc3BhY2UgPT09IGIubmFtZXNwYWNlICYmIGEua2V5ID09PSBiLmtleSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZhciBwcm9wc1BhdGNoID0gZGlmZlByb3BzKGEucHJvcGVydGllcywgYi5wcm9wZXJ0aWVzKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAocHJvcHNQYXRjaCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBhcHBseSA9IGFwcGVuZFBhdGNoKGFwcGx5LCBuZXcgVlBhdGNoKFZQYXRjaC5QUk9QUywgYSwgcHJvcHNQYXRjaCkpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBhcHBseSA9IGRpZmZDaGlsZHJlbihhLCBiLCBwYXRjaCwgYXBwbHksIGluZGV4KTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgYXBwbHkgPSBhcHBlbmRQYXRjaChhcHBseSwgbmV3IFZQYXRjaChWUGF0Y2guVk5PREUsIGEsIGIpKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBhcHBseUNsZWFyID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGFwcGx5ID0gYXBwZW5kUGF0Y2goYXBwbHksIG5ldyBWUGF0Y2goVlBhdGNoLlZOT0RFLCBhLCBiKSk7XG4gICAgICAgICAgICAgICAgICAgICAgICBhcHBseUNsZWFyID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoaXNWVGV4dChiKSkge1xuICAgICAgICAgICAgICAgICAgICBpZiAoIWlzVlRleHQoYSkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGFwcGx5ID0gYXBwZW5kUGF0Y2goYXBwbHksIG5ldyBWUGF0Y2goVlBhdGNoLlZURVhULCBhLCBiKSk7XG4gICAgICAgICAgICAgICAgICAgICAgICBhcHBseUNsZWFyID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIGlmIChhLnRleHQgIT09IGIudGV4dCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgYXBwbHkgPSBhcHBlbmRQYXRjaChhcHBseSwgbmV3IFZQYXRjaChWUGF0Y2guVlRFWFQsIGEsIGIpKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoaXNXaWRnZXQoYikpIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKCFpc1dpZGdldChhKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgYXBwbHlDbGVhciA9IHRydWU7XG4gICAgICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgICAgICBhcHBseSA9IGFwcGVuZFBhdGNoKGFwcGx5LCBuZXcgVlBhdGNoKFZQYXRjaC5XSURHRVQsIGEsIGIpKTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICBpZiAoYXBwbHkpIHtcbiAgICAgICAgICAgICAgICAgICAgcGF0Y2hbaW5kZXhdID0gYXBwbHk7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgaWYgKGFwcGx5Q2xlYXIpIHtcbiAgICAgICAgICAgICAgICAgICAgY2xlYXJTdGF0ZShhLCBwYXRjaCwgaW5kZXgpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZnVuY3Rpb24gZGlmZkNoaWxkcmVuKGEsIGIsIHBhdGNoLCBhcHBseSwgaW5kZXgpIHtcbiAgICAgICAgICAgICAgICB2YXIgYUNoaWxkcmVuID0gYS5jaGlsZHJlbjtcbiAgICAgICAgICAgICAgICB2YXIgb3JkZXJlZFNldCA9IHJlb3JkZXIoYUNoaWxkcmVuLCBiLmNoaWxkcmVuKTtcbiAgICAgICAgICAgICAgICB2YXIgYkNoaWxkcmVuID0gb3JkZXJlZFNldC5jaGlsZHJlbjtcblxuICAgICAgICAgICAgICAgIHZhciBhTGVuID0gYUNoaWxkcmVuLmxlbmd0aDtcbiAgICAgICAgICAgICAgICB2YXIgYkxlbiA9IGJDaGlsZHJlbi5sZW5ndGg7XG4gICAgICAgICAgICAgICAgdmFyIGxlbiA9IGFMZW4gPiBiTGVuID8gYUxlbiA6IGJMZW47XG5cbiAgICAgICAgICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IGxlbjsgaSsrKSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciBsZWZ0Tm9kZSA9IGFDaGlsZHJlbltpXTtcbiAgICAgICAgICAgICAgICAgICAgdmFyIHJpZ2h0Tm9kZSA9IGJDaGlsZHJlbltpXTtcbiAgICAgICAgICAgICAgICAgICAgaW5kZXggKz0gMTtcblxuICAgICAgICAgICAgICAgICAgICBpZiAoIWxlZnROb2RlKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAocmlnaHROb2RlKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gRXhjZXNzIG5vZGVzIGluIGIgbmVlZCB0byBiZSBhZGRlZFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGFwcGx5ID0gYXBwZW5kUGF0Y2goYXBwbHksIG5ldyBWUGF0Y2goVlBhdGNoLklOU0VSVCwgbnVsbCwgcmlnaHROb2RlKSk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICB3YWxrKGxlZnROb2RlLCByaWdodE5vZGUsIHBhdGNoLCBpbmRleCk7XG4gICAgICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgICAgICBpZiAoaXNWTm9kZShsZWZ0Tm9kZSkgJiYgbGVmdE5vZGUuY291bnQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGluZGV4ICs9IGxlZnROb2RlLmNvdW50O1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgaWYgKG9yZGVyZWRTZXQubW92ZXMpIHtcbiAgICAgICAgICAgICAgICAgICAgLy8gUmVvcmRlciBub2RlcyBsYXN0XG4gICAgICAgICAgICAgICAgICAgIGFwcGx5ID0gYXBwZW5kUGF0Y2goYXBwbHksIG5ldyBWUGF0Y2goVlBhdGNoLk9SREVSLCBhLCBvcmRlcmVkU2V0Lm1vdmVzKSk7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgcmV0dXJuIGFwcGx5O1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBmdW5jdGlvbiBjbGVhclN0YXRlKHZOb2RlLCBwYXRjaCwgaW5kZXgpIHtcbiAgICAgICAgICAgICAgICAvLyBUT0RPOiBNYWtlIHRoaXMgYSBzaW5nbGUgd2Fsaywgbm90IHR3b1xuICAgICAgICAgICAgICAgIHVuaG9vayh2Tm9kZSwgcGF0Y2gsIGluZGV4KTtcbiAgICAgICAgICAgICAgICBkZXN0cm95V2lkZ2V0cyh2Tm9kZSwgcGF0Y2gsIGluZGV4KTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgLy8gUGF0Y2ggcmVjb3JkcyBmb3IgYWxsIGRlc3Ryb3llZCB3aWRnZXRzIG11c3QgYmUgYWRkZWQgYmVjYXVzZSB3ZSBuZWVkXG4gICAgICAgICAgICAvLyBhIERPTSBub2RlIHJlZmVyZW5jZSBmb3IgdGhlIGRlc3Ryb3kgZnVuY3Rpb25cbiAgICAgICAgICAgIGZ1bmN0aW9uIGRlc3Ryb3lXaWRnZXRzKHZOb2RlLCBwYXRjaCwgaW5kZXgpIHtcbiAgICAgICAgICAgICAgICBpZiAoaXNXaWRnZXQodk5vZGUpKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmICh0eXBlb2Ygdk5vZGUuZGVzdHJveSA9PT0gXCJmdW5jdGlvblwiKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBwYXRjaFtpbmRleF0gPSBhcHBlbmRQYXRjaChwYXRjaFtpbmRleF0sIG5ldyBWUGF0Y2goVlBhdGNoLlJFTU9WRSwgdk5vZGUsIG51bGwpKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoaXNWTm9kZSh2Tm9kZSkgJiYgKHZOb2RlLmhhc1dpZGdldHMgfHwgdk5vZGUuaGFzVGh1bmtzKSkge1xuICAgICAgICAgICAgICAgICAgICB2YXIgY2hpbGRyZW4gPSB2Tm9kZS5jaGlsZHJlbjtcbiAgICAgICAgICAgICAgICAgICAgdmFyIGxlbiA9IGNoaWxkcmVuLmxlbmd0aDtcbiAgICAgICAgICAgICAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCBsZW47IGkrKykge1xuICAgICAgICAgICAgICAgICAgICAgICAgdmFyIGNoaWxkID0gY2hpbGRyZW5baV07XG4gICAgICAgICAgICAgICAgICAgICAgICBpbmRleCArPSAxO1xuXG4gICAgICAgICAgICAgICAgICAgICAgICBkZXN0cm95V2lkZ2V0cyhjaGlsZCwgcGF0Y2gsIGluZGV4KTtcblxuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGlzVk5vZGUoY2hpbGQpICYmIGNoaWxkLmNvdW50KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaW5kZXggKz0gY2hpbGQuY291bnQ7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKGlzVGh1bmsodk5vZGUpKSB7XG4gICAgICAgICAgICAgICAgICAgIHRodW5rcyh2Tm9kZSwgbnVsbCwgcGF0Y2gsIGluZGV4KTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIC8vIENyZWF0ZSBhIHN1Yi1wYXRjaCBmb3IgdGh1bmtzXG4gICAgICAgICAgICBmdW5jdGlvbiB0aHVua3MoYSwgYiwgcGF0Y2gsIGluZGV4KSB7XG4gICAgICAgICAgICAgICAgdmFyIG5vZGVzID0gaGFuZGxlVGh1bmsoYSwgYik7XG4gICAgICAgICAgICAgICAgdmFyIHRodW5rUGF0Y2ggPSBkaWZmKG5vZGVzLmEsIG5vZGVzLmIpO1xuICAgICAgICAgICAgICAgIGlmIChoYXNQYXRjaGVzKHRodW5rUGF0Y2gpKSB7XG4gICAgICAgICAgICAgICAgICAgIHBhdGNoW2luZGV4XSA9IG5ldyBWUGF0Y2goVlBhdGNoLlRIVU5LLCBudWxsLCB0aHVua1BhdGNoKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIGhhc1BhdGNoZXMocGF0Y2gpIHtcbiAgICAgICAgICAgICAgICBmb3IgKHZhciBpbmRleCBpbiBwYXRjaCkge1xuICAgICAgICAgICAgICAgICAgICBpZiAoaW5kZXggIT09IFwiYVwiKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgLy8gRXhlY3V0ZSBob29rcyB3aGVuIHR3byBub2RlcyBhcmUgaWRlbnRpY2FsXG4gICAgICAgICAgICBmdW5jdGlvbiB1bmhvb2sodk5vZGUsIHBhdGNoLCBpbmRleCkge1xuICAgICAgICAgICAgICAgIGlmIChpc1ZOb2RlKHZOb2RlKSkge1xuICAgICAgICAgICAgICAgICAgICBpZiAodk5vZGUuaG9va3MpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHBhdGNoW2luZGV4XSA9IGFwcGVuZFBhdGNoKHBhdGNoW2luZGV4XSwgbmV3IFZQYXRjaChWUGF0Y2guUFJPUFMsIHZOb2RlLCB1bmRlZmluZWRLZXlzKHZOb2RlLmhvb2tzKSkpO1xuICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgaWYgKHZOb2RlLmRlc2NlbmRhbnRIb29rcyB8fCB2Tm9kZS5oYXNUaHVua3MpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHZhciBjaGlsZHJlbiA9IHZOb2RlLmNoaWxkcmVuO1xuICAgICAgICAgICAgICAgICAgICAgICAgdmFyIGxlbiA9IGNoaWxkcmVuLmxlbmd0aDtcbiAgICAgICAgICAgICAgICAgICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgbGVuOyBpKyspIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB2YXIgY2hpbGQgPSBjaGlsZHJlbltpXTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpbmRleCArPSAxO1xuXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdW5ob29rKGNoaWxkLCBwYXRjaCwgaW5kZXgpO1xuXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGlzVk5vZGUoY2hpbGQpICYmIGNoaWxkLmNvdW50KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGluZGV4ICs9IGNoaWxkLmNvdW50O1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoaXNUaHVuayh2Tm9kZSkpIHtcbiAgICAgICAgICAgICAgICAgICAgdGh1bmtzKHZOb2RlLCBudWxsLCBwYXRjaCwgaW5kZXgpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZnVuY3Rpb24gdW5kZWZpbmVkS2V5cyhvYmopIHtcbiAgICAgICAgICAgICAgICB2YXIgcmVzdWx0ID0ge307XG5cbiAgICAgICAgICAgICAgICBmb3IgKHZhciBrZXkgaW4gb2JqKSB7XG4gICAgICAgICAgICAgICAgICAgIHJlc3VsdFtrZXldID0gdW5kZWZpbmVkO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHJldHVybiByZXN1bHQ7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIC8vIExpc3QgZGlmZiwgbmFpdmUgbGVmdCB0byByaWdodCByZW9yZGVyaW5nXG4gICAgICAgICAgICBmdW5jdGlvbiByZW9yZGVyKGFDaGlsZHJlbiwgYkNoaWxkcmVuKSB7XG4gICAgICAgICAgICAgICAgLy8gTyhNKSB0aW1lLCBPKE0pIG1lbW9yeVxuICAgICAgICAgICAgICAgIHZhciBiQ2hpbGRJbmRleCA9IGtleUluZGV4KGJDaGlsZHJlbik7XG4gICAgICAgICAgICAgICAgdmFyIGJLZXlzID0gYkNoaWxkSW5kZXgua2V5cztcbiAgICAgICAgICAgICAgICB2YXIgYkZyZWUgPSBiQ2hpbGRJbmRleC5mcmVlO1xuXG4gICAgICAgICAgICAgICAgaWYgKGJGcmVlLmxlbmd0aCA9PT0gYkNoaWxkcmVuLmxlbmd0aCkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgICAgICAgICAgICAgY2hpbGRyZW46IGJDaGlsZHJlbixcbiAgICAgICAgICAgICAgICAgICAgICAgIG1vdmVzOiBudWxsXG4gICAgICAgICAgICAgICAgICAgIH07XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgLy8gTyhOKSB0aW1lLCBPKE4pIG1lbW9yeVxuICAgICAgICAgICAgICAgIHZhciBhQ2hpbGRJbmRleCA9IGtleUluZGV4KGFDaGlsZHJlbik7XG4gICAgICAgICAgICAgICAgdmFyIGFLZXlzID0gYUNoaWxkSW5kZXgua2V5cztcbiAgICAgICAgICAgICAgICB2YXIgYUZyZWUgPSBhQ2hpbGRJbmRleC5mcmVlO1xuXG4gICAgICAgICAgICAgICAgaWYgKGFGcmVlLmxlbmd0aCA9PT0gYUNoaWxkcmVuLmxlbmd0aCkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgICAgICAgICAgICAgY2hpbGRyZW46IGJDaGlsZHJlbixcbiAgICAgICAgICAgICAgICAgICAgICAgIG1vdmVzOiBudWxsXG4gICAgICAgICAgICAgICAgICAgIH07XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgLy8gTyhNQVgoTiwgTSkpIG1lbW9yeVxuICAgICAgICAgICAgICAgIHZhciBuZXdDaGlsZHJlbiA9IFtdO1xuXG4gICAgICAgICAgICAgICAgdmFyIGZyZWVJbmRleCA9IDA7XG4gICAgICAgICAgICAgICAgdmFyIGZyZWVDb3VudCA9IGJGcmVlLmxlbmd0aDtcbiAgICAgICAgICAgICAgICB2YXIgZGVsZXRlZEl0ZW1zID0gMDtcblxuICAgICAgICAgICAgICAgIC8vIEl0ZXJhdGUgdGhyb3VnaCBhIGFuZCBtYXRjaCBhIG5vZGUgaW4gYlxuICAgICAgICAgICAgICAgIC8vIE8oTikgdGltZSxcbiAgICAgICAgICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IGFDaGlsZHJlbi5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgICAgICAgICB2YXIgYUl0ZW0gPSBhQ2hpbGRyZW5baV07XG4gICAgICAgICAgICAgICAgICAgIHZhciBpdGVtSW5kZXg7XG5cbiAgICAgICAgICAgICAgICAgICAgaWYgKGFJdGVtLmtleSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGJLZXlzLmhhc093blByb3BlcnR5KGFJdGVtLmtleSkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBNYXRjaCB1cCB0aGUgb2xkIGtleXNcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpdGVtSW5kZXggPSBiS2V5c1thSXRlbS5rZXldO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIG5ld0NoaWxkcmVuLnB1c2goYkNoaWxkcmVuW2l0ZW1JbmRleF0pO1xuICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBSZW1vdmUgb2xkIGtleWVkIGl0ZW1zXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaXRlbUluZGV4ID0gaSAtIGRlbGV0ZWRJdGVtcysrO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIG5ld0NoaWxkcmVuLnB1c2gobnVsbCk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAvLyBNYXRjaCB0aGUgaXRlbSBpbiBhIHdpdGggdGhlIG5leHQgZnJlZSBpdGVtIGluIGJcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChmcmVlSW5kZXggPCBmcmVlQ291bnQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpdGVtSW5kZXggPSBiRnJlZVtmcmVlSW5kZXgrK107XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgbmV3Q2hpbGRyZW4ucHVzaChiQ2hpbGRyZW5baXRlbUluZGV4XSk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIFRoZXJlIGFyZSBubyBmcmVlIGl0ZW1zIGluIGIgdG8gbWF0Y2ggd2l0aFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIHRoZSBmcmVlIGl0ZW1zIGluIGEsIHNvIHRoZSBleHRyYSBmcmVlIG5vZGVzXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gYXJlIGRlbGV0ZWQuXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaXRlbUluZGV4ID0gaSAtIGRlbGV0ZWRJdGVtcysrO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIG5ld0NoaWxkcmVuLnB1c2gobnVsbCk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICB2YXIgbGFzdEZyZWVJbmRleCA9IGZyZWVJbmRleCA+PSBiRnJlZS5sZW5ndGggPyBiQ2hpbGRyZW4ubGVuZ3RoIDogYkZyZWVbZnJlZUluZGV4XTtcblxuICAgICAgICAgICAgICAgIC8vIEl0ZXJhdGUgdGhyb3VnaCBiIGFuZCBhcHBlbmQgYW55IG5ldyBrZXlzXG4gICAgICAgICAgICAgICAgLy8gTyhNKSB0aW1lXG4gICAgICAgICAgICAgICAgZm9yICh2YXIgaiA9IDA7IGogPCBiQ2hpbGRyZW4ubGVuZ3RoOyBqKyspIHtcbiAgICAgICAgICAgICAgICAgICAgdmFyIG5ld0l0ZW0gPSBiQ2hpbGRyZW5bal07XG5cbiAgICAgICAgICAgICAgICAgICAgaWYgKG5ld0l0ZW0ua2V5KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoIWFLZXlzLmhhc093blByb3BlcnR5KG5ld0l0ZW0ua2V5KSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIEFkZCBhbnkgbmV3IGtleWVkIGl0ZW1zXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gV2UgYXJlIGFkZGluZyBuZXcgaXRlbXMgdG8gdGhlIGVuZCBhbmQgdGhlbiBzb3J0aW5nIHRoZW1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBpbiBwbGFjZS4gSW4gZnV0dXJlIHdlIHNob3VsZCBpbnNlcnQgbmV3IGl0ZW1zIGluIHBsYWNlLlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIG5ld0NoaWxkcmVuLnB1c2gobmV3SXRlbSk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoaiA+PSBsYXN0RnJlZUluZGV4KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAvLyBBZGQgYW55IGxlZnRvdmVyIG5vbi1rZXllZCBpdGVtc1xuICAgICAgICAgICAgICAgICAgICAgICAgbmV3Q2hpbGRyZW4ucHVzaChuZXdJdGVtKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHZhciBzaW11bGF0ZSA9IG5ld0NoaWxkcmVuLnNsaWNlKCk7XG4gICAgICAgICAgICAgICAgdmFyIHNpbXVsYXRlSW5kZXggPSAwO1xuICAgICAgICAgICAgICAgIHZhciByZW1vdmVzID0gW107XG4gICAgICAgICAgICAgICAgdmFyIGluc2VydHMgPSBbXTtcbiAgICAgICAgICAgICAgICB2YXIgc2ltdWxhdGVJdGVtO1xuXG4gICAgICAgICAgICAgICAgZm9yICh2YXIgayA9IDA7IGsgPCBiQ2hpbGRyZW4ubGVuZ3RoOykge1xuICAgICAgICAgICAgICAgICAgICB2YXIgd2FudGVkSXRlbSA9IGJDaGlsZHJlbltrXTtcbiAgICAgICAgICAgICAgICAgICAgc2ltdWxhdGVJdGVtID0gc2ltdWxhdGVbc2ltdWxhdGVJbmRleF07XG5cbiAgICAgICAgICAgICAgICAgICAgLy8gcmVtb3ZlIGl0ZW1zXG4gICAgICAgICAgICAgICAgICAgIHdoaWxlIChzaW11bGF0ZUl0ZW0gPT09IG51bGwgJiYgc2ltdWxhdGUubGVuZ3RoKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICByZW1vdmVzLnB1c2gocmVtb3ZlKHNpbXVsYXRlLCBzaW11bGF0ZUluZGV4LCBudWxsKSk7XG4gICAgICAgICAgICAgICAgICAgICAgICBzaW11bGF0ZUl0ZW0gPSBzaW11bGF0ZVtzaW11bGF0ZUluZGV4XTtcbiAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgIGlmICghc2ltdWxhdGVJdGVtIHx8IHNpbXVsYXRlSXRlbS5rZXkgIT09IHdhbnRlZEl0ZW0ua2V5KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAvLyBpZiB3ZSBuZWVkIGEga2V5IGluIHRoaXMgcG9zaXRpb24uLi5cbiAgICAgICAgICAgICAgICAgICAgICAgIGlmICh3YW50ZWRJdGVtLmtleSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChzaW11bGF0ZUl0ZW0gJiYgc2ltdWxhdGVJdGVtLmtleSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBpZiBhbiBpbnNlcnQgZG9lc24ndCBwdXQgdGhpcyBrZXkgaW4gcGxhY2UsIGl0IG5lZWRzIHRvIG1vdmVcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGJLZXlzW3NpbXVsYXRlSXRlbS5rZXldICE9PSBrICsgMSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmVtb3Zlcy5wdXNoKHJlbW92ZShzaW11bGF0ZSwgc2ltdWxhdGVJbmRleCwgc2ltdWxhdGVJdGVtLmtleSkpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc2ltdWxhdGVJdGVtID0gc2ltdWxhdGVbc2ltdWxhdGVJbmRleF07XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBpZiB0aGUgcmVtb3ZlIGRpZG4ndCBwdXQgdGhlIHdhbnRlZCBpdGVtIGluIHBsYWNlLCB3ZSBuZWVkIHRvIGluc2VydCBpdFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKCFzaW11bGF0ZUl0ZW0gfHwgc2ltdWxhdGVJdGVtLmtleSAhPT0gd2FudGVkSXRlbS5rZXkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpbnNlcnRzLnB1c2goeyBrZXk6IHdhbnRlZEl0ZW0ua2V5LCB0bzogayB9KTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIGl0ZW1zIGFyZSBtYXRjaGluZywgc28gc2tpcCBhaGVhZFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc2ltdWxhdGVJbmRleCsrO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaW5zZXJ0cy5wdXNoKHsga2V5OiB3YW50ZWRJdGVtLmtleSwgdG86IGsgfSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpbnNlcnRzLnB1c2goeyBrZXk6IHdhbnRlZEl0ZW0ua2V5LCB0bzogayB9KTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaysrO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgLy8gYSBrZXkgaW4gc2ltdWxhdGUgaGFzIG5vIG1hdGNoaW5nIHdhbnRlZCBrZXksIHJlbW92ZSBpdFxuICAgICAgICAgICAgICAgICAgICAgICAgZWxzZSBpZiAoc2ltdWxhdGVJdGVtICYmIHNpbXVsYXRlSXRlbS5rZXkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICByZW1vdmVzLnB1c2gocmVtb3ZlKHNpbXVsYXRlLCBzaW11bGF0ZUluZGV4LCBzaW11bGF0ZUl0ZW0ua2V5KSk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBzaW11bGF0ZUluZGV4Kys7XG4gICAgICAgICAgICAgICAgICAgICAgICBrKys7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAvLyByZW1vdmUgYWxsIHRoZSByZW1haW5pbmcgbm9kZXMgZnJvbSBzaW11bGF0ZVxuICAgICAgICAgICAgICAgIHdoaWxlIChzaW11bGF0ZUluZGV4IDwgc2ltdWxhdGUubGVuZ3RoKSB7XG4gICAgICAgICAgICAgICAgICAgIHNpbXVsYXRlSXRlbSA9IHNpbXVsYXRlW3NpbXVsYXRlSW5kZXhdO1xuICAgICAgICAgICAgICAgICAgICByZW1vdmVzLnB1c2gocmVtb3ZlKHNpbXVsYXRlLCBzaW11bGF0ZUluZGV4LCBzaW11bGF0ZUl0ZW0gJiYgc2ltdWxhdGVJdGVtLmtleSkpO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIC8vIElmIHRoZSBvbmx5IG1vdmVzIHdlIGhhdmUgYXJlIGRlbGV0ZXMgdGhlbiB3ZSBjYW4ganVzdFxuICAgICAgICAgICAgICAgIC8vIGxldCB0aGUgZGVsZXRlIHBhdGNoIHJlbW92ZSB0aGVzZSBpdGVtcy5cbiAgICAgICAgICAgICAgICBpZiAocmVtb3Zlcy5sZW5ndGggPT09IGRlbGV0ZWRJdGVtcyAmJiAhaW5zZXJ0cy5sZW5ndGgpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGNoaWxkcmVuOiBuZXdDaGlsZHJlbixcbiAgICAgICAgICAgICAgICAgICAgICAgIG1vdmVzOiBudWxsXG4gICAgICAgICAgICAgICAgICAgIH07XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgICAgICAgICAgY2hpbGRyZW46IG5ld0NoaWxkcmVuLFxuICAgICAgICAgICAgICAgICAgICBtb3Zlczoge1xuICAgICAgICAgICAgICAgICAgICAgICAgcmVtb3ZlczogcmVtb3ZlcyxcbiAgICAgICAgICAgICAgICAgICAgICAgIGluc2VydHM6IGluc2VydHNcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH07XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIHJlbW92ZShhcnIsIGluZGV4LCBrZXkpIHtcbiAgICAgICAgICAgICAgICBhcnIuc3BsaWNlKGluZGV4LCAxKTtcblxuICAgICAgICAgICAgICAgIHJldHVybiB7XG4gICAgICAgICAgICAgICAgICAgIGZyb206IGluZGV4LFxuICAgICAgICAgICAgICAgICAgICBrZXk6IGtleVxuICAgICAgICAgICAgICAgIH07XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIGtleUluZGV4KGNoaWxkcmVuKSB7XG4gICAgICAgICAgICAgICAgdmFyIGtleXMgPSB7fTtcbiAgICAgICAgICAgICAgICB2YXIgZnJlZSA9IFtdO1xuICAgICAgICAgICAgICAgIHZhciBsZW5ndGggPSBjaGlsZHJlbi5sZW5ndGg7XG5cbiAgICAgICAgICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IGxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciBjaGlsZCA9IGNoaWxkcmVuW2ldO1xuXG4gICAgICAgICAgICAgICAgICAgIGlmIChjaGlsZC5rZXkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGtleXNbY2hpbGQua2V5XSA9IGk7XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBmcmVlLnB1c2goaSk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgICAgICAgICBrZXlzOiBrZXlzLCAvLyBBIGhhc2ggb2Yga2V5IG5hbWUgdG8gaW5kZXhcbiAgICAgICAgICAgICAgICAgICAgZnJlZTogZnJlZSAvLyBBbiBhcnJheSBvZiB1bmtleWVkIGl0ZW0gaW5kaWNlc1xuICAgICAgICAgICAgICAgIH07XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIGFwcGVuZFBhdGNoKGFwcGx5LCBwYXRjaCkge1xuICAgICAgICAgICAgICAgIGlmIChhcHBseSkge1xuICAgICAgICAgICAgICAgICAgICBpZiAoaXNBcnJheShhcHBseSkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGFwcGx5LnB1c2gocGF0Y2gpO1xuICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgYXBwbHkgPSBbYXBwbHksIHBhdGNoXTtcbiAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBhcHBseTtcbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gcGF0Y2g7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9LCB7IFwiLi4vdm5vZGUvaGFuZGxlLXRodW5rXCI6IDI0LCBcIi4uL3Zub2RlL2lzLXRodW5rXCI6IDI1LCBcIi4uL3Zub2RlL2lzLXZub2RlXCI6IDI3LCBcIi4uL3Zub2RlL2lzLXZ0ZXh0XCI6IDI4LCBcIi4uL3Zub2RlL2lzLXdpZGdldFwiOiAyOSwgXCIuLi92bm9kZS92cGF0Y2hcIjogMzIsIFwiLi9kaWZmLXByb3BzXCI6IDM0LCBcIngtaXMtYXJyYXlcIjogMTIgfV0gfSwge30sIFs0XSkoNCk7XG59KTtcblxuLyogQGZsb3cgKi9cblxuY2xhc3MgTWFpbGJveCB7XG5cbiAgY29uc3RydWN0b3IoKSB7XG4gICAgdGhpcy5tZXNzYWdlcyA9IFtdO1xuICB9XG5cbiAgZGVsaXZlcihtZXNzYWdlKSB7XG4gICAgdGhpcy5tZXNzYWdlcy5wdXNoKG1lc3NhZ2UpO1xuICAgIHJldHVybiBtZXNzYWdlO1xuICB9XG5cbiAgZ2V0KCkge1xuICAgIHJldHVybiB0aGlzLm1lc3NhZ2VzO1xuICB9XG5cbiAgaXNFbXB0eSgpIHtcbiAgICByZXR1cm4gdGhpcy5tZXNzYWdlcy5sZW5ndGggPT09IDA7XG4gIH1cblxuICByZW1vdmVBdChpbmRleCkge1xuICAgIHRoaXMubWVzc2FnZXMuc3BsaWNlKGluZGV4LCAxKTtcbiAgfVxufVxuXG52YXIgU3RhdGVzID0ge1xuICBOT1JNQUw6IFN5bWJvbC5mb3IoXCJub3JtYWxcIiksXG4gIEtJTEw6IFN5bWJvbC5mb3IoXCJraWxsXCIpLFxuICBTVVNQRU5EOiBTeW1ib2wuZm9yKFwic3VzcGVuZFwiKSxcbiAgQ09OVElOVUU6IFN5bWJvbC5mb3IoXCJjb250aW51ZVwiKSxcbiAgUkVDRUlWRTogU3ltYm9sLmZvcihcInJlY2VpdmVcIiksXG4gIFNFTkQ6IFN5bWJvbC5mb3IoXCJzZW5kXCIpLFxuICBTTEVFUElORzogU3ltYm9sLmZvcihcInNsZWVwaW5nXCIpLFxuICBSVU5OSU5HOiBTeW1ib2wuZm9yKFwicnVubmluZ1wiKSxcbiAgU1VTUEVOREVEOiBTeW1ib2wuZm9yKFwic3VzcGVuZGVkXCIpLFxuICBTVE9QUEVEOiBTeW1ib2wuZm9yKFwic3RvcHBlZFwiKSxcbiAgU0xFRVA6IFN5bWJvbC5mb3IoXCJzbGVlcFwiKSxcbiAgRVhJVDogU3ltYm9sLmZvcihcImV4aXRcIiksXG4gIE5PTUFUQ0g6IFN5bWJvbC5mb3IoXCJub19tYXRjaFwiKVxufTtcblxuY2xhc3MgUHJvY2VzcyB7XG5cbiAgY29uc3RydWN0b3IocGlkLCBtYWlsYm94KSB7XG4gICAgdGhpcy5waWQgPSBwaWQ7XG4gICAgdGhpcy5tYWlsYm94ID0gbWFpbGJveDtcbiAgICB0aGlzLnN0YXR1cyA9IFN0YXRlcy5TVE9QUEVEO1xuICAgIHRoaXMuZGljdCA9IHt9O1xuICB9XG59XG5cbmNsYXNzIFR1cGxlIHtcblxuICBjb25zdHJ1Y3RvciguLi5hcmdzKSB7XG4gICAgdGhpcy52YWx1ZXMgPSBPYmplY3QuZnJlZXplKGFyZ3MpO1xuICAgIHRoaXMubGVuZ3RoID0gdGhpcy52YWx1ZXMubGVuZ3RoO1xuICB9XG5cbiAgZ2V0KGluZGV4KSB7XG4gICAgcmV0dXJuIHRoaXMudmFsdWVzW2luZGV4XTtcbiAgfVxuXG4gIGNvdW50KCkge1xuICAgIHJldHVybiB0aGlzLnZhbHVlcy5sZW5ndGg7XG4gIH1cblxuICBbU3ltYm9sLml0ZXJhdG9yXSgpIHtcbiAgICByZXR1cm4gdGhpcy52YWx1ZXNbU3ltYm9sLml0ZXJhdG9yXSgpO1xuICB9XG5cbiAgdG9TdHJpbmcoKSB7XG4gICAgdmFyIGksXG4gICAgICAgIHMgPSBcIlwiO1xuICAgIGZvciAoaSA9IDA7IGkgPCB0aGlzLnZhbHVlcy5sZW5ndGg7IGkrKykge1xuICAgICAgaWYgKHMgIT09IFwiXCIpIHtcbiAgICAgICAgcyArPSBcIiwgXCI7XG4gICAgICB9XG4gICAgICBzICs9IHRoaXMudmFsdWVzW2ldLnRvU3RyaW5nKCk7XG4gICAgfVxuXG4gICAgcmV0dXJuIFwie1wiICsgcyArIFwifVwiO1xuICB9XG5cbiAgcHV0X2VsZW0oaW5kZXgsIGVsZW0pIHtcbiAgICBsZXQgbmV3X3ZhbHVlcyA9IHRoaXMudmFsdWVzLmNvbmNhdChbXSk7XG4gICAgbmV3X3ZhbHVlcy5zcGxpY2UoaW5kZXgsIDAsIGVsZW0pO1xuICAgIHJldHVybiBuZXcgVHVwbGUoLi4ubmV3X3ZhbHVlcyk7XG4gIH1cblxufVxuXG5sZXQgcHJvY2Vzc19jb3VudGVyID0gLTE7XG5cbmNsYXNzIFBJRCB7XG4gIGNvbnN0cnVjdG9yKCkge1xuICAgIHByb2Nlc3NfY291bnRlciA9IHByb2Nlc3NfY291bnRlciArIDE7XG4gICAgdGhpcy5pZCA9IHByb2Nlc3NfY291bnRlcjtcbiAgfVxuXG4gIHRvU3RyaW5nKCkge1xuICAgIHJldHVybiBcIlBJRCM8MC5cIiArIHRoaXMuaWQgKyBcIi4wPlwiO1xuICB9XG59XG5cbmNsYXNzIEludGVnZXIge31cbmNsYXNzIEZsb2F0IHt9XG5cbmNsYXNzIFByb2Nlc3NTeXN0ZW0ge1xuXG4gIGNvbnN0cnVjdG9yKCkge1xuICAgIHRoaXMucGlkcyA9IG5ldyBNYXAoKTtcbiAgICB0aGlzLm1haWxib3hlcyA9IG5ldyBNYXAoKTtcbiAgICB0aGlzLm5hbWVzID0gbmV3IE1hcCgpO1xuICAgIHRoaXMubGlua3MgPSBuZXcgTWFwKCk7XG5cbiAgICB0aGlzLmN1cnJlbnRfcHJvY2VzcyA9IG51bGw7XG4gICAgdGhpcy5zdXNwZW5kZWQgPSBuZXcgTWFwKCk7XG5cbiAgICB0aGlzLm1haW5fcHJvY2Vzc19waWQgPSB0aGlzLnNwYXduKCk7XG4gICAgdGhpcy5zZXRfY3VycmVudCh0aGlzLm1haW5fcHJvY2Vzc19waWQpO1xuICB9XG5cbiAgc3Bhd24oKSB7XG4gICAgcmV0dXJuIHRoaXMuYWRkX3Byb2MoZmFsc2UpLnBpZDtcbiAgfVxuXG4gIHNwYXduX2xpbmsoKSB7XG4gICAgcmV0dXJuIHRoaXMuYWRkX3Byb2ModHJ1ZSkucGlkO1xuICB9XG5cbiAgbGluayhwaWQpIHtcbiAgICB0aGlzLmxpbmtzLmdldCh0aGlzLnBpZCgpKS5hZGQocGlkKTtcbiAgICB0aGlzLmxpbmtzLmdldChwaWQpLmFkZCh0aGlzLnBpZCgpKTtcbiAgfVxuXG4gIHVubGluayhwaWQpIHtcbiAgICB0aGlzLmxpbmtzLmdldCh0aGlzLnBpZCgpKS5kZWxldGUocGlkKTtcbiAgICB0aGlzLmxpbmtzLmdldChwaWQpLmRlbGV0ZSh0aGlzLnBpZCgpKTtcbiAgfVxuXG4gIHNldF9jdXJyZW50KGlkKSB7XG4gICAgbGV0IHBpZCA9IHRoaXMucGlkb2YoaWQpO1xuICAgIGlmIChwaWQgIT09IG51bGwpIHtcbiAgICAgIHRoaXMuY3VycmVudF9wcm9jZXNzID0gdGhpcy5waWRzLmdldChwaWQpO1xuICAgICAgdGhpcy5jdXJyZW50X3Byb2Nlc3Muc3RhdHVzID0gU3RhdGVzLlJVTk5JTkc7XG4gICAgfVxuICB9XG5cbiAgYWRkX3Byb2MobGlua2VkKSB7XG4gICAgbGV0IG5ld3BpZCA9IG5ldyBQSUQoKTtcbiAgICBsZXQgbWFpbGJveCA9IG5ldyBNYWlsYm94KCk7XG4gICAgbGV0IG5ld3Byb2MgPSBuZXcgUHJvY2VzcyhuZXdwaWQsIG1haWxib3gpO1xuXG4gICAgdGhpcy5waWRzLnNldChuZXdwaWQsIG5ld3Byb2MpO1xuICAgIHRoaXMubWFpbGJveGVzLnNldChuZXdwaWQsIG1haWxib3gpO1xuICAgIHRoaXMubGlua3Muc2V0KG5ld3BpZCwgbmV3IFNldCgpKTtcblxuICAgIGlmIChsaW5rZWQpIHtcbiAgICAgIHRoaXMubGluayhuZXdwaWQpO1xuICAgIH1cblxuICAgIHJldHVybiBuZXdwcm9jO1xuICB9XG5cbiAgcmVtb3ZlX3Byb2MocGlkKSB7XG4gICAgdGhpcy5waWRzLmRlbGV0ZShwaWQpO1xuICAgIHRoaXMudW5yZWdpc3RlcihwaWQpO1xuXG4gICAgaWYgKHRoaXMubGlua3MuaGFzKHBpZCkpIHtcbiAgICAgIGZvciAobGV0IGxpbmtwaWQgb2YgdGhpcy5saW5rcy5nZXQocGlkKSkge1xuICAgICAgICB0aGlzLmxpbmtzLmdldChsaW5rcGlkKS5kZWxldGUocGlkKTtcbiAgICAgIH1cblxuICAgICAgdGhpcy5saW5rcy5kZWxldGUocGlkKTtcbiAgICB9XG4gIH1cblxuICBleGl0KGlkKSB7XG4gICAgbGV0IHBpZCA9IHRoaXMucGlkb2YoaWQpO1xuICAgIHRoaXMucmVtb3ZlX3Byb2MoaWQpO1xuICB9XG5cbiAgcmVnaXN0ZXIobmFtZSwgcGlkKSB7XG4gICAgaWYgKCF0aGlzLm5hbWVzLmhhcyhuYW1lKSkge1xuICAgICAgdGhpcy5uYW1lcy5zZXQobmFtZSwgcGlkKTtcbiAgICAgIHJldHVybiBuYW1lO1xuICAgIH0gZWxzZSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoXCJOYW1lIGlzIGFscmVhZHkgcmVnaXN0ZXJlZCB0byBhbm90aGVyIHByb2Nlc3NcIik7XG4gICAgfVxuICB9XG5cbiAgcmVnaXN0ZXJlZChuYW1lKSB7XG4gICAgcmV0dXJuIHRoaXMubmFtZXMuaGFzKG5hbWUpID8gdGhpcy5uYW1lcy5nZXQobmFtZSkgOiBudWxsO1xuICB9XG5cbiAgdW5yZWdpc3RlcihwaWQpIHtcbiAgICBmb3IgKGxldCBuYW1lIG9mIHRoaXMubmFtZXMua2V5cygpKSB7XG4gICAgICBpZiAodGhpcy5uYW1lcy5oYXMobmFtZSkgJiYgdGhpcy5uYW1lcy5nZXQobmFtZSkgPT09IHBpZCkge1xuICAgICAgICB0aGlzLm5hbWVzLmRlbGV0ZShuYW1lKTtcbiAgICAgIH1cbiAgICB9XG4gIH1cblxuICBwaWQoKSB7XG4gICAgcmV0dXJuIHRoaXMuY3VycmVudF9wcm9jZXNzLnBpZDtcbiAgfVxuXG4gIHBpZG9mKGlkKSB7XG4gICAgaWYgKGlkIGluc3RhbmNlb2YgUElEKSB7XG4gICAgICByZXR1cm4gdGhpcy5waWRzLmhhcyhpZCkgPyBpZCA6IG51bGw7XG4gICAgfSBlbHNlIGlmIChpZCBpbnN0YW5jZW9mIFByb2Nlc3MpIHtcbiAgICAgIHJldHVybiBpZC5waWQ7XG4gICAgfSBlbHNlIHtcbiAgICAgIGxldCBwaWQgPSB0aGlzLnJlZ2lzdGVyZWQoaWQpO1xuICAgICAgaWYgKHBpZCA9PT0gbnVsbCkgdGhyb3cgXCJQcm9jZXNzIG5hbWUgbm90IHJlZ2lzdGVyZWQ6IFwiICsgaWQgKyBcIiAoXCIgKyB0eXBlb2YgaWQgKyBcIilcIjtcbiAgICAgIHJldHVybiBwaWQ7XG4gICAgfVxuICB9XG5cbiAgcHV0KGlkLCBrZXksIHZhbHVlKSB7XG4gICAgbGV0IHBpZCA9IHRoaXMucGlkb2YoaWQpO1xuICAgIGxldCBwcm9jZXNzID0gdGhpcy5waWRzLmdldChwaWQpO1xuICAgIHByb2Nlc3MuZGljdFtrZXldID0gdmFsdWU7XG4gIH1cblxuICBnZXQoaWQsIGtleSkge1xuICAgIGxldCBwaWQgPSB0aGlzLnBpZG9mKGlkKTtcbiAgICBsZXQgcHJvY2VzcyA9IHRoaXMucGlkcy5nZXQocGlkKTtcblxuICAgIGlmIChrZXkgIT0gbnVsbCkge1xuICAgICAgcmV0dXJuIHByb2Nlc3MuZGljdFtrZXldO1xuICAgIH0gZWxzZSB7XG4gICAgICByZXR1cm4gcHJvY2Vzcy5kaWN0O1xuICAgIH1cbiAgfVxuXG4gIGdldF9rZXlzKGlkKSB7XG4gICAgbGV0IHBpZCA9IHRoaXMucGlkb2YoaWQpO1xuICAgIGxldCBwcm9jZXNzID0gdGhpcy5waWRzLmdldChwaWQpO1xuXG4gICAgcmV0dXJuIE9iamVjdC5rZXlzKHByb2Nlc3MuZGljdCk7XG4gIH1cblxuICBlcmFzZShpZCwga2V5KSB7XG4gICAgbGV0IHBpZCA9IHRoaXMucGlkb2YoaWQpO1xuICAgIGxldCBwcm9jZXNzID0gdGhpcy5waWRzLmdldChwaWQpO1xuXG4gICAgaWYgKGtleSAhPSBudWxsKSB7XG4gICAgICBkZWxldGUgcHJvY2Vzcy5kaWN0W2tleV07XG4gICAgfSBlbHNlIHtcbiAgICAgIHByb2Nlc3MuZGljdCA9IHt9O1xuICAgIH1cbiAgfVxufVxuXG5jbGFzcyBCaXRTdHJpbmcge1xuICBjb25zdHJ1Y3RvciguLi5hcmdzKSB7XG4gICAgdGhpcy5yYXdfdmFsdWUgPSBmdW5jdGlvbiAoKSB7XG4gICAgICByZXR1cm4gT2JqZWN0LmZyZWV6ZShhcmdzKTtcbiAgICB9O1xuXG4gICAgdGhpcy52YWx1ZSA9IE9iamVjdC5mcmVlemUodGhpcy5wcm9jZXNzKGFyZ3MpKTtcbiAgICB0aGlzLmxlbmd0aCA9IHRoaXMudmFsdWUubGVuZ3RoO1xuICAgIHRoaXMuYml0X3NpemUgPSB0aGlzLnJhd192YWx1ZS5yZWR1Y2UoKHByZXYsIGN1cnJlbnQpID0+IHByZXYgKyBjdXJyZW50LnNpemUpO1xuICAgIHRoaXMuYnl0ZV9zaXplID0gdGhpcy5iaXRfc2l6ZSAvIDggKyAodGhpcy5iaXRfc2l6ZSAlIDggPiAwID8gMSA6IDApO1xuICB9XG5cbiAgZ2V0KGluZGV4KSB7XG4gICAgcmV0dXJuIHRoaXMudmFsdWVbaW5kZXhdO1xuICB9XG5cbiAgY291bnQoKSB7XG4gICAgcmV0dXJuIHRoaXMudmFsdWUubGVuZ3RoO1xuICB9XG5cbiAgW1N5bWJvbC5pdGVyYXRvcl0oKSB7XG4gICAgcmV0dXJuIHRoaXMudmFsdWVbU3ltYm9sLml0ZXJhdG9yXSgpO1xuICB9XG5cbiAgdG9TdHJpbmcoKSB7XG4gICAgdmFyIGksXG4gICAgICAgIHMgPSBcIlwiO1xuICAgIGZvciAoaSA9IDA7IGkgPCB0aGlzLmNvdW50KCk7IGkrKykge1xuICAgICAgaWYgKHMgIT09IFwiXCIpIHtcbiAgICAgICAgcyArPSBcIiwgXCI7XG4gICAgICB9XG4gICAgICBzICs9IHRoaXNbaV0udG9TdHJpbmcoKTtcbiAgICB9XG5cbiAgICByZXR1cm4gXCI8PFwiICsgcyArIFwiPj5cIjtcbiAgfVxuXG4gIHByb2Nlc3MoKSB7XG4gICAgbGV0IHByb2Nlc3NlZF92YWx1ZXMgPSBbXTtcblxuICAgIHZhciBpO1xuICAgIGZvciAoaSA9IDA7IGkgPCB0aGlzLnJhd192YWx1ZSgpLmxlbmd0aDsgaSsrKSB7XG4gICAgICBsZXQgcHJvY2Vzc2VkX3ZhbHVlID0gdGhpc1tcInByb2Nlc3NfXCIgKyB0aGlzLnJhd192YWx1ZSgpW2ldLnR5cGVdKHRoaXMucmF3X3ZhbHVlKClbaV0pO1xuXG4gICAgICBmb3IgKGxldCBhdHRyIG9mIHRoaXMucmF3X3ZhbHVlKClbaV0uYXR0cmlidXRlcykge1xuICAgICAgICBwcm9jZXNzZWRfdmFsdWUgPSB0aGlzW1wicHJvY2Vzc19cIiArIGF0dHJdKHByb2Nlc3NlZF92YWx1ZSk7XG4gICAgICB9XG5cbiAgICAgIHByb2Nlc3NlZF92YWx1ZXMgPSBwcm9jZXNzZWRfdmFsdWVzLmNvbmNhdChwcm9jZXNzZWRfdmFsdWUpO1xuICAgIH1cblxuICAgIHJldHVybiBwcm9jZXNzZWRfdmFsdWVzO1xuICB9XG5cbiAgcHJvY2Vzc19pbnRlZ2VyKHZhbHVlKSB7XG4gICAgcmV0dXJuIHZhbHVlLnZhbHVlO1xuICB9XG5cbiAgcHJvY2Vzc19mbG9hdCh2YWx1ZSkge1xuICAgIGlmICh2YWx1ZS5zaXplID09PSA2NCkge1xuICAgICAgcmV0dXJuIEJpdFN0cmluZy5mbG9hdDY0VG9CeXRlcyh2YWx1ZS52YWx1ZSk7XG4gICAgfSBlbHNlIGlmICh2YWx1ZS5zaXplID09PSAzMikge1xuICAgICAgcmV0dXJuIEJpdFN0cmluZy5mbG9hdDMyVG9CeXRlcyh2YWx1ZS52YWx1ZSk7XG4gICAgfVxuXG4gICAgdGhyb3cgbmV3IEVycm9yKFwiSW52YWxpZCBzaXplIGZvciBmbG9hdFwiKTtcbiAgfVxuXG4gIHByb2Nlc3NfYml0c3RyaW5nKHZhbHVlKSB7XG4gICAgcmV0dXJuIHZhbHVlLnZhbHVlLnZhbHVlO1xuICB9XG5cbiAgcHJvY2Vzc19iaW5hcnkodmFsdWUpIHtcbiAgICByZXR1cm4gQml0U3RyaW5nLnRvVVRGOEFycmF5KHZhbHVlLnZhbHVlKTtcbiAgfVxuXG4gIHByb2Nlc3NfdXRmOCh2YWx1ZSkge1xuICAgIHJldHVybiBCaXRTdHJpbmcudG9VVEY4QXJyYXkodmFsdWUudmFsdWUpO1xuICB9XG5cbiAgcHJvY2Vzc191dGYxNih2YWx1ZSkge1xuICAgIHJldHVybiBCaXRTdHJpbmcudG9VVEYxNkFycmF5KHZhbHVlLnZhbHVlKTtcbiAgfVxuXG4gIHByb2Nlc3NfdXRmMzIodmFsdWUpIHtcbiAgICByZXR1cm4gQml0U3RyaW5nLnRvVVRGMzJBcnJheSh2YWx1ZS52YWx1ZSk7XG4gIH1cblxuICBwcm9jZXNzX3NpZ25lZCh2YWx1ZSkge1xuICAgIHJldHVybiBuZXcgVWludDhBcnJheShbdmFsdWVdKVswXTtcbiAgfVxuXG4gIHByb2Nlc3NfdW5zaWduZWQodmFsdWUpIHtcbiAgICByZXR1cm4gdmFsdWU7XG4gIH1cblxuICBwcm9jZXNzX25hdGl2ZSh2YWx1ZSkge1xuICAgIHJldHVybiB2YWx1ZTtcbiAgfVxuXG4gIHByb2Nlc3NfYmlnKHZhbHVlKSB7XG4gICAgcmV0dXJuIHZhbHVlO1xuICB9XG5cbiAgcHJvY2Vzc19saXR0bGUodmFsdWUpIHtcbiAgICByZXR1cm4gdmFsdWUucmV2ZXJzZSgpO1xuICB9XG5cbiAgcHJvY2Vzc19zaXplKHZhbHVlKSB7XG4gICAgcmV0dXJuIHZhbHVlO1xuICB9XG5cbiAgcHJvY2Vzc191bml0KHZhbHVlKSB7XG4gICAgcmV0dXJuIHZhbHVlO1xuICB9XG5cbiAgc3RhdGljIGludGVnZXIodmFsdWUpIHtcbiAgICByZXR1cm4gQml0U3RyaW5nLndyYXAodmFsdWUsIHsgXCJ0eXBlXCI6IFwiaW50ZWdlclwiLCBcInVuaXRcIjogMSwgXCJzaXplXCI6IDggfSk7XG4gIH1cblxuICBzdGF0aWMgZmxvYXQodmFsdWUpIHtcbiAgICByZXR1cm4gQml0U3RyaW5nLndyYXAodmFsdWUsIHsgXCJ0eXBlXCI6IFwiZmxvYXRcIiwgXCJ1bml0XCI6IDEsIFwic2l6ZVwiOiA2NCB9KTtcbiAgfVxuXG4gIHN0YXRpYyBiaXRzdHJpbmcodmFsdWUpIHtcbiAgICByZXR1cm4gQml0U3RyaW5nLndyYXAodmFsdWUsIHsgXCJ0eXBlXCI6IFwiYml0c3RyaW5nXCIsIFwidW5pdFwiOiAxLCBcInNpemVcIjogdmFsdWUuYml0X3NpemUgfSk7XG4gIH1cblxuICBzdGF0aWMgYml0cyh2YWx1ZSkge1xuICAgIHJldHVybiBCaXRTdHJpbmcuYml0c3RyaW5nKHZhbHVlKTtcbiAgfVxuXG4gIHN0YXRpYyBiaW5hcnkodmFsdWUpIHtcbiAgICByZXR1cm4gQml0U3RyaW5nLndyYXAodmFsdWUsIHsgXCJ0eXBlXCI6IFwiYmluYXJ5XCIsIFwidW5pdFwiOiA4LCBcInNpemVcIjogdmFsdWUubGVuZ3RoIH0pO1xuICB9XG5cbiAgc3RhdGljIGJ5dGVzKHZhbHVlKSB7XG4gICAgcmV0dXJuIEJpdFN0cmluZy5iaW5hcnkodmFsdWUpO1xuICB9XG5cbiAgc3RhdGljIHV0ZjgodmFsdWUpIHtcbiAgICByZXR1cm4gQml0U3RyaW5nLndyYXAodmFsdWUsIHsgXCJ0eXBlXCI6IFwidXRmOFwiIH0pO1xuICB9XG5cbiAgc3RhdGljIHV0ZjE2KHZhbHVlKSB7XG4gICAgcmV0dXJuIEJpdFN0cmluZy53cmFwKHZhbHVlLCB7IFwidHlwZVwiOiBcInV0ZjE2XCIgfSk7XG4gIH1cblxuICBzdGF0aWMgdXRmMzIodmFsdWUpIHtcbiAgICByZXR1cm4gQml0U3RyaW5nLndyYXAodmFsdWUsIHsgXCJ0eXBlXCI6IFwidXRmMzJcIiB9KTtcbiAgfVxuXG4gIHN0YXRpYyBzaWduZWQodmFsdWUpIHtcbiAgICByZXR1cm4gQml0U3RyaW5nLndyYXAodmFsdWUsIHt9LCBcInNpZ25lZFwiKTtcbiAgfVxuXG4gIHN0YXRpYyB1bnNpZ25lZCh2YWx1ZSkge1xuICAgIHJldHVybiBCaXRTdHJpbmcud3JhcCh2YWx1ZSwge30sIFwidW5zaWduZWRcIik7XG4gIH1cblxuICBzdGF0aWMgbmF0aXZlKHZhbHVlKSB7XG4gICAgcmV0dXJuIEJpdFN0cmluZy53cmFwKHZhbHVlLCB7fSwgXCJuYXRpdmVcIik7XG4gIH1cblxuICBzdGF0aWMgYmlnKHZhbHVlKSB7XG4gICAgcmV0dXJuIEJpdFN0cmluZy53cmFwKHZhbHVlLCB7fSwgXCJiaWdcIik7XG4gIH1cblxuICBzdGF0aWMgbGl0dGxlKHZhbHVlKSB7XG4gICAgcmV0dXJuIEJpdFN0cmluZy53cmFwKHZhbHVlLCB7fSwgXCJsaXR0bGVcIik7XG4gIH1cblxuICBzdGF0aWMgc2l6ZSh2YWx1ZSwgY291bnQpIHtcbiAgICByZXR1cm4gQml0U3RyaW5nLndyYXAodmFsdWUsIHsgXCJzaXplXCI6IGNvdW50IH0pO1xuICB9XG5cbiAgc3RhdGljIHVuaXQodmFsdWUsIGNvdW50KSB7XG4gICAgcmV0dXJuIEJpdFN0cmluZy53cmFwKHZhbHVlLCB7IFwidW5pdFwiOiBjb3VudCB9KTtcbiAgfVxuXG4gIHN0YXRpYyB3cmFwKHZhbHVlLCBvcHQsIG5ld19hdHRyaWJ1dGUgPSBudWxsKSB7XG4gICAgbGV0IHRoZV92YWx1ZSA9IHZhbHVlO1xuXG4gICAgaWYgKCEodmFsdWUgaW5zdGFuY2VvZiBPYmplY3QpKSB7XG4gICAgICB0aGVfdmFsdWUgPSB7IFwidmFsdWVcIjogdmFsdWUsIFwiYXR0cmlidXRlc1wiOiBbXSB9O1xuICAgIH1cblxuICAgIHRoZV92YWx1ZSA9IE9iamVjdC5hc3NpZ24odGhlX3ZhbHVlLCBvcHQpO1xuXG4gICAgaWYgKG5ld19hdHRyaWJ1dGUpIHtcbiAgICAgIHRoZV92YWx1ZS5hdHRyaWJ1dGVzLnB1c2gobmV3X2F0dHJpYnV0ZSk7XG4gICAgfVxuXG4gICAgcmV0dXJuIHRoZV92YWx1ZTtcbiAgfVxuXG4gIHN0YXRpYyB0b1VURjhBcnJheShzdHIpIHtcbiAgICB2YXIgdXRmOCA9IFtdO1xuICAgIGZvciAodmFyIGkgPSAwOyBpIDwgc3RyLmxlbmd0aDsgaSsrKSB7XG4gICAgICB2YXIgY2hhcmNvZGUgPSBzdHIuY2hhckNvZGVBdChpKTtcbiAgICAgIGlmIChjaGFyY29kZSA8IDEyOCkge1xuICAgICAgICB1dGY4LnB1c2goY2hhcmNvZGUpO1xuICAgICAgfSBlbHNlIGlmIChjaGFyY29kZSA8IDIwNDgpIHtcbiAgICAgICAgdXRmOC5wdXNoKDE5MiB8IGNoYXJjb2RlID4+IDYsIDEyOCB8IGNoYXJjb2RlICYgNjMpO1xuICAgICAgfSBlbHNlIGlmIChjaGFyY29kZSA8IDU1Mjk2IHx8IGNoYXJjb2RlID49IDU3MzQ0KSB7XG4gICAgICAgIHV0ZjgucHVzaCgyMjQgfCBjaGFyY29kZSA+PiAxMiwgMTI4IHwgY2hhcmNvZGUgPj4gNiAmIDYzLCAxMjggfCBjaGFyY29kZSAmIDYzKTtcbiAgICAgIH1cbiAgICAgIC8vIHN1cnJvZ2F0ZSBwYWlyXG4gICAgICBlbHNlIHtcbiAgICAgICAgaSsrO1xuICAgICAgICAvLyBVVEYtMTYgZW5jb2RlcyAweDEwMDAwLTB4MTBGRkZGIGJ5XG4gICAgICAgIC8vIHN1YnRyYWN0aW5nIDB4MTAwMDAgYW5kIHNwbGl0dGluZyB0aGVcbiAgICAgICAgLy8gMjAgYml0cyBvZiAweDAtMHhGRkZGRiBpbnRvIHR3byBoYWx2ZXNcbiAgICAgICAgY2hhcmNvZGUgPSA2NTUzNiArICgoY2hhcmNvZGUgJiAxMDIzKSA8PCAxMCB8IHN0ci5jaGFyQ29kZUF0KGkpICYgMTAyMyk7XG4gICAgICAgIHV0ZjgucHVzaCgyNDAgfCBjaGFyY29kZSA+PiAxOCwgMTI4IHwgY2hhcmNvZGUgPj4gMTIgJiA2MywgMTI4IHwgY2hhcmNvZGUgPj4gNiAmIDYzLCAxMjggfCBjaGFyY29kZSAmIDYzKTtcbiAgICAgIH1cbiAgICB9XG4gICAgcmV0dXJuIHV0Zjg7XG4gIH1cblxuICBzdGF0aWMgdG9VVEYxNkFycmF5KHN0cikge1xuICAgIHZhciB1dGYxNiA9IFtdO1xuICAgIGZvciAodmFyIGkgPSAwOyBpIDwgc3RyLmxlbmd0aDsgaSsrKSB7XG4gICAgICB2YXIgY29kZVBvaW50ID0gc3RyLmNvZGVQb2ludEF0KGkpO1xuXG4gICAgICBpZiAoY29kZVBvaW50IDw9IDI1NSkge1xuICAgICAgICB1dGYxNi5wdXNoKDApO1xuICAgICAgICB1dGYxNi5wdXNoKGNvZGVQb2ludCk7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICB1dGYxNi5wdXNoKGNvZGVQb2ludCA+PiA4ICYgMjU1KTtcbiAgICAgICAgdXRmMTYucHVzaChjb2RlUG9pbnQgJiAyNTUpO1xuICAgICAgfVxuICAgIH1cbiAgICByZXR1cm4gdXRmMTY7XG4gIH1cblxuICBzdGF0aWMgdG9VVEYzMkFycmF5KHN0cikge1xuICAgIHZhciB1dGYzMiA9IFtdO1xuICAgIGZvciAodmFyIGkgPSAwOyBpIDwgc3RyLmxlbmd0aDsgaSsrKSB7XG4gICAgICB2YXIgY29kZVBvaW50ID0gc3RyLmNvZGVQb2ludEF0KGkpO1xuXG4gICAgICBpZiAoY29kZVBvaW50IDw9IDI1NSkge1xuICAgICAgICB1dGYzMi5wdXNoKDApO1xuICAgICAgICB1dGYzMi5wdXNoKDApO1xuICAgICAgICB1dGYzMi5wdXNoKDApO1xuICAgICAgICB1dGYzMi5wdXNoKGNvZGVQb2ludCk7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICB1dGYzMi5wdXNoKDApO1xuICAgICAgICB1dGYzMi5wdXNoKDApO1xuICAgICAgICB1dGYzMi5wdXNoKGNvZGVQb2ludCA+PiA4ICYgMjU1KTtcbiAgICAgICAgdXRmMzIucHVzaChjb2RlUG9pbnQgJiAyNTUpO1xuICAgICAgfVxuICAgIH1cbiAgICByZXR1cm4gdXRmMzI7XG4gIH1cblxuICAvL2h0dHA6Ly9zdGFja292ZXJmbG93LmNvbS9xdWVzdGlvbnMvMjAwMzQ5My9qYXZhc2NyaXB0LWZsb2F0LWZyb20tdG8tYml0c1xuICBzdGF0aWMgZmxvYXQzMlRvQnl0ZXMoZikge1xuICAgIHZhciBieXRlcyA9IFtdO1xuXG4gICAgdmFyIGJ1ZiA9IG5ldyBBcnJheUJ1ZmZlcig0KTtcbiAgICBuZXcgRmxvYXQzMkFycmF5KGJ1ZilbMF0gPSBmO1xuXG4gICAgbGV0IGludFZlcnNpb24gPSBuZXcgVWludDMyQXJyYXkoYnVmKVswXTtcblxuICAgIGJ5dGVzLnB1c2goaW50VmVyc2lvbiA+PiAyNCAmIDI1NSk7XG4gICAgYnl0ZXMucHVzaChpbnRWZXJzaW9uID4+IDE2ICYgMjU1KTtcbiAgICBieXRlcy5wdXNoKGludFZlcnNpb24gPj4gOCAmIDI1NSk7XG4gICAgYnl0ZXMucHVzaChpbnRWZXJzaW9uICYgMjU1KTtcblxuICAgIHJldHVybiBieXRlcztcbiAgfVxuXG4gIHN0YXRpYyBmbG9hdDY0VG9CeXRlcyhmKSB7XG4gICAgdmFyIGJ5dGVzID0gW107XG5cbiAgICB2YXIgYnVmID0gbmV3IEFycmF5QnVmZmVyKDgpO1xuICAgIG5ldyBGbG9hdDY0QXJyYXkoYnVmKVswXSA9IGY7XG5cbiAgICB2YXIgaW50VmVyc2lvbjEgPSBuZXcgVWludDMyQXJyYXkoYnVmKVswXTtcbiAgICB2YXIgaW50VmVyc2lvbjIgPSBuZXcgVWludDMyQXJyYXkoYnVmKVsxXTtcblxuICAgIGJ5dGVzLnB1c2goaW50VmVyc2lvbjIgPj4gMjQgJiAyNTUpO1xuICAgIGJ5dGVzLnB1c2goaW50VmVyc2lvbjIgPj4gMTYgJiAyNTUpO1xuICAgIGJ5dGVzLnB1c2goaW50VmVyc2lvbjIgPj4gOCAmIDI1NSk7XG4gICAgYnl0ZXMucHVzaChpbnRWZXJzaW9uMiAmIDI1NSk7XG5cbiAgICBieXRlcy5wdXNoKGludFZlcnNpb24xID4+IDI0ICYgMjU1KTtcbiAgICBieXRlcy5wdXNoKGludFZlcnNpb24xID4+IDE2ICYgMjU1KTtcbiAgICBieXRlcy5wdXNoKGludFZlcnNpb24xID4+IDggJiAyNTUpO1xuICAgIGJ5dGVzLnB1c2goaW50VmVyc2lvbjEgJiAyNTUpO1xuXG4gICAgcmV0dXJuIGJ5dGVzO1xuICB9XG59XG5cbi8qIEBmbG93ICovXG5cbmNsYXNzIFZhcmlhYmxlIHtcblxuICBjb25zdHJ1Y3RvcihuYW1lID0gbnVsbCkge1xuICAgIHRoaXMubmFtZSA9IG5hbWU7XG4gIH1cbn1cblxuY2xhc3MgV2lsZGNhcmQge1xuICBjb25zdHJ1Y3RvcigpIHt9XG59XG5cbmNsYXNzIFN0YXJ0c1dpdGgge1xuXG4gIGNvbnN0cnVjdG9yKHByZWZpeCkge1xuICAgIHRoaXMucHJlZml4ID0gcHJlZml4O1xuICB9XG59XG5cbmNsYXNzIENhcHR1cmUge1xuXG4gIGNvbnN0cnVjdG9yKHZhbHVlKSB7XG4gICAgdGhpcy52YWx1ZSA9IHZhbHVlO1xuICB9XG59XG5cbmNsYXNzIEhlYWRUYWlsIHtcbiAgY29uc3RydWN0b3IoKSB7fVxufVxuXG5jbGFzcyBUeXBlIHtcblxuICBjb25zdHJ1Y3Rvcih0eXBlLCBvYmpQYXR0ZXJuID0ge30pIHtcbiAgICB0aGlzLnR5cGUgPSB0eXBlO1xuICAgIHRoaXMub2JqUGF0dGVybiA9IG9ialBhdHRlcm47XG4gIH1cbn1cblxuY2xhc3MgQm91bmQge1xuXG4gIGNvbnN0cnVjdG9yKHZhbHVlKSB7XG4gICAgdGhpcy52YWx1ZSA9IHZhbHVlO1xuICB9XG59XG5cbmZ1bmN0aW9uIHZhcmlhYmxlKG5hbWUgPSBudWxsKSB7XG4gIHJldHVybiBuZXcgVmFyaWFibGUobmFtZSk7XG59XG5cbmZ1bmN0aW9uIHdpbGRjYXJkKCkge1xuICByZXR1cm4gbmV3IFdpbGRjYXJkKCk7XG59XG5cbmZ1bmN0aW9uIHN0YXJ0c1dpdGgocHJlZml4KSB7XG4gIHJldHVybiBuZXcgU3RhcnRzV2l0aChwcmVmaXgpO1xufVxuXG5mdW5jdGlvbiBjYXB0dXJlKHZhbHVlKSB7XG4gIHJldHVybiBuZXcgQ2FwdHVyZSh2YWx1ZSk7XG59XG5cbmZ1bmN0aW9uIGhlYWRUYWlsKCkge1xuICByZXR1cm4gbmV3IEhlYWRUYWlsKCk7XG59XG5cbmZ1bmN0aW9uIHR5cGUodHlwZSwgb2JqUGF0dGVybiA9IHt9KSB7XG4gIHJldHVybiBuZXcgVHlwZSh0eXBlLCBvYmpQYXR0ZXJuKTtcbn1cblxuZnVuY3Rpb24gYm91bmQodmFsdWUpIHtcbiAgcmV0dXJuIG5ldyBCb3VuZCh2YWx1ZSk7XG59XG5cbmZ1bmN0aW9uIGlzX251bWJlcih2YWx1ZSkge1xuICByZXR1cm4gdHlwZW9mIHZhbHVlID09PSAnbnVtYmVyJztcbn1cblxuZnVuY3Rpb24gaXNfc3RyaW5nKHZhbHVlKSB7XG4gIHJldHVybiB0eXBlb2YgdmFsdWUgPT09ICdzdHJpbmcnO1xufVxuXG5mdW5jdGlvbiBpc19ib29sZWFuKHZhbHVlKSB7XG4gIHJldHVybiB0eXBlb2YgdmFsdWUgPT09ICdib29sZWFuJztcbn1cblxuZnVuY3Rpb24gaXNfc3ltYm9sKHZhbHVlKSB7XG4gIHJldHVybiB0eXBlb2YgdmFsdWUgPT09ICdzeW1ib2wnO1xufVxuXG5mdW5jdGlvbiBpc19udWxsKHZhbHVlKSB7XG4gIHJldHVybiB2YWx1ZSA9PT0gbnVsbDtcbn1cblxuZnVuY3Rpb24gaXNfdW5kZWZpbmVkKHZhbHVlKSB7XG4gIHJldHVybiB0eXBlb2YgdmFsdWUgPT09ICd1bmRlZmluZWQnO1xufVxuXG5mdW5jdGlvbiBpc19mdW5jdGlvbih2YWx1ZSkge1xuICByZXR1cm4gT2JqZWN0LnByb3RvdHlwZS50b1N0cmluZy5jYWxsKHZhbHVlKSA9PSAnW29iamVjdCBGdW5jdGlvbl0nO1xufVxuXG5mdW5jdGlvbiBpc192YXJpYWJsZSh2YWx1ZSkge1xuICByZXR1cm4gdmFsdWUgaW5zdGFuY2VvZiBWYXJpYWJsZTtcbn1cblxuZnVuY3Rpb24gaXNfd2lsZGNhcmQodmFsdWUpIHtcbiAgcmV0dXJuIHZhbHVlIGluc3RhbmNlb2YgV2lsZGNhcmQ7XG59XG5cbmZ1bmN0aW9uIGlzX2hlYWRUYWlsKHZhbHVlKSB7XG4gIHJldHVybiB2YWx1ZSBpbnN0YW5jZW9mIEhlYWRUYWlsO1xufVxuXG5mdW5jdGlvbiBpc19jYXB0dXJlKHZhbHVlKSB7XG4gIHJldHVybiB2YWx1ZSBpbnN0YW5jZW9mIENhcHR1cmU7XG59XG5cbmZ1bmN0aW9uIGlzX3R5cGUodmFsdWUpIHtcbiAgcmV0dXJuIHZhbHVlIGluc3RhbmNlb2YgVHlwZTtcbn1cblxuZnVuY3Rpb24gaXNfc3RhcnRzV2l0aCh2YWx1ZSkge1xuICByZXR1cm4gdmFsdWUgaW5zdGFuY2VvZiBTdGFydHNXaXRoO1xufVxuXG5mdW5jdGlvbiBpc19ib3VuZCh2YWx1ZSkge1xuICByZXR1cm4gdmFsdWUgaW5zdGFuY2VvZiBCb3VuZDtcbn1cblxuZnVuY3Rpb24gaXNfb2JqZWN0KHZhbHVlKSB7XG4gIHJldHVybiB0eXBlb2YgdmFsdWUgPT09ICdvYmplY3QnO1xufVxuXG5mdW5jdGlvbiBpc19hcnJheSh2YWx1ZSkge1xuICByZXR1cm4gQXJyYXkuaXNBcnJheSh2YWx1ZSk7XG59XG5cbnZhciBDaGVja3MgPSB7XG4gIGlzX251bWJlcixcbiAgaXNfc3RyaW5nLFxuICBpc19ib29sZWFuLFxuICBpc19zeW1ib2wsXG4gIGlzX251bGwsXG4gIGlzX3VuZGVmaW5lZCxcbiAgaXNfZnVuY3Rpb24sXG4gIGlzX3ZhcmlhYmxlLFxuICBpc193aWxkY2FyZCxcbiAgaXNfaGVhZFRhaWwsXG4gIGlzX2NhcHR1cmUsXG4gIGlzX3R5cGUsXG4gIGlzX3N0YXJ0c1dpdGgsXG4gIGlzX2JvdW5kLFxuICBpc19vYmplY3QsXG4gIGlzX2FycmF5XG59O1xuXG5mdW5jdGlvbiByZXNvbHZlU3ltYm9sKHBhdHRlcm4pIHtcbiAgcmV0dXJuIGZ1bmN0aW9uICh2YWx1ZSkge1xuICAgIHJldHVybiBDaGVja3MuaXNfc3ltYm9sKHZhbHVlKSAmJiB2YWx1ZSA9PT0gcGF0dGVybjtcbiAgfTtcbn1cblxuZnVuY3Rpb24gcmVzb2x2ZVN0cmluZyhwYXR0ZXJuKSB7XG4gIHJldHVybiBmdW5jdGlvbiAodmFsdWUpIHtcbiAgICByZXR1cm4gQ2hlY2tzLmlzX3N0cmluZyh2YWx1ZSkgJiYgdmFsdWUgPT09IHBhdHRlcm47XG4gIH07XG59XG5cbmZ1bmN0aW9uIHJlc29sdmVOdW1iZXIocGF0dGVybikge1xuICByZXR1cm4gZnVuY3Rpb24gKHZhbHVlKSB7XG4gICAgcmV0dXJuIENoZWNrcy5pc19udW1iZXIodmFsdWUpICYmIHZhbHVlID09PSBwYXR0ZXJuO1xuICB9O1xufVxuXG5mdW5jdGlvbiByZXNvbHZlQm9vbGVhbihwYXR0ZXJuKSB7XG4gIHJldHVybiBmdW5jdGlvbiAodmFsdWUpIHtcbiAgICByZXR1cm4gQ2hlY2tzLmlzX2Jvb2xlYW4odmFsdWUpICYmIHZhbHVlID09PSBwYXR0ZXJuO1xuICB9O1xufVxuXG5mdW5jdGlvbiByZXNvbHZlRnVuY3Rpb24ocGF0dGVybikge1xuICByZXR1cm4gZnVuY3Rpb24gKHZhbHVlKSB7XG4gICAgcmV0dXJuIENoZWNrcy5pc19mdW5jdGlvbih2YWx1ZSkgJiYgdmFsdWUgPT09IHBhdHRlcm47XG4gIH07XG59XG5cbmZ1bmN0aW9uIHJlc29sdmVOdWxsKHBhdHRlcm4pIHtcbiAgcmV0dXJuIGZ1bmN0aW9uICh2YWx1ZSkge1xuICAgIHJldHVybiBDaGVja3MuaXNfbnVsbCh2YWx1ZSk7XG4gIH07XG59XG5cbmZ1bmN0aW9uIHJlc29sdmVCb3VuZChwYXR0ZXJuKSB7XG4gIHJldHVybiBmdW5jdGlvbiAodmFsdWUsIGFyZ3MpIHtcbiAgICBpZiAodHlwZW9mIHZhbHVlID09PSB0eXBlb2YgcGF0dGVybi52YWx1ZSAmJiB2YWx1ZSA9PT0gcGF0dGVybi52YWx1ZSkge1xuICAgICAgYXJncy5wdXNoKHZhbHVlKTtcbiAgICAgIHJldHVybiB0cnVlO1xuICAgIH1cblxuICAgIHJldHVybiBmYWxzZTtcbiAgfTtcbn1cblxuZnVuY3Rpb24gcmVzb2x2ZVdpbGRjYXJkKCkge1xuICByZXR1cm4gZnVuY3Rpb24gKCkge1xuICAgIHJldHVybiB0cnVlO1xuICB9O1xufVxuXG5mdW5jdGlvbiByZXNvbHZlVmFyaWFibGUoKSB7XG4gIHJldHVybiBmdW5jdGlvbiAodmFsdWUsIGFyZ3MpIHtcbiAgICBhcmdzLnB1c2godmFsdWUpO1xuICAgIHJldHVybiB0cnVlO1xuICB9O1xufVxuXG5mdW5jdGlvbiByZXNvbHZlSGVhZFRhaWwoKSB7XG4gIHJldHVybiBmdW5jdGlvbiAodmFsdWUsIGFyZ3MpIHtcbiAgICBpZiAoIUNoZWNrcy5pc19hcnJheSh2YWx1ZSkgfHwgdmFsdWUubGVuZ3RoIDwgMikge1xuICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH1cblxuICAgIGNvbnN0IGhlYWQgPSB2YWx1ZVswXTtcbiAgICBjb25zdCB0YWlsID0gdmFsdWUuc2xpY2UoMSk7XG5cbiAgICBhcmdzLnB1c2goaGVhZCk7XG4gICAgYXJncy5wdXNoKHRhaWwpO1xuXG4gICAgcmV0dXJuIHRydWU7XG4gIH07XG59XG5cbmZ1bmN0aW9uIHJlc29sdmVDYXB0dXJlKHBhdHRlcm4pIHtcbiAgY29uc3QgbWF0Y2hlcyA9IGJ1aWxkTWF0Y2gocGF0dGVybi52YWx1ZSk7XG5cbiAgcmV0dXJuIGZ1bmN0aW9uICh2YWx1ZSwgYXJncykge1xuICAgIGlmIChtYXRjaGVzKHZhbHVlLCBhcmdzKSkge1xuICAgICAgYXJncy5wdXNoKHZhbHVlKTtcbiAgICAgIHJldHVybiB0cnVlO1xuICAgIH1cblxuICAgIHJldHVybiBmYWxzZTtcbiAgfTtcbn1cblxuZnVuY3Rpb24gcmVzb2x2ZVN0YXJ0c1dpdGgocGF0dGVybikge1xuICBjb25zdCBwcmVmaXggPSBwYXR0ZXJuLnByZWZpeDtcblxuICByZXR1cm4gZnVuY3Rpb24gKHZhbHVlLCBhcmdzKSB7XG4gICAgaWYgKENoZWNrcy5pc19zdHJpbmcodmFsdWUpICYmIHZhbHVlLnN0YXJ0c1dpdGgocHJlZml4KSkge1xuICAgICAgYXJncy5wdXNoKHZhbHVlLnN1YnN0cmluZyhwcmVmaXgubGVuZ3RoKSk7XG4gICAgICByZXR1cm4gdHJ1ZTtcbiAgICB9XG5cbiAgICByZXR1cm4gZmFsc2U7XG4gIH07XG59XG5cbmZ1bmN0aW9uIHJlc29sdmVUeXBlKHBhdHRlcm4pIHtcbiAgcmV0dXJuIGZ1bmN0aW9uICh2YWx1ZSwgYXJncykge1xuICAgIGlmICh2YWx1ZSBpbnN0YW5jZW9mIHBhdHRlcm4udHlwZSkge1xuICAgICAgY29uc3QgbWF0Y2hlcyA9IGJ1aWxkTWF0Y2gocGF0dGVybi5vYmpQYXR0ZXJuKTtcbiAgICAgIHJldHVybiBtYXRjaGVzKHZhbHVlLCBhcmdzKSAmJiBhcmdzLnB1c2godmFsdWUpID4gMDtcbiAgICB9XG5cbiAgICByZXR1cm4gZmFsc2U7XG4gIH07XG59XG5cbmZ1bmN0aW9uIHJlc29sdmVBcnJheShwYXR0ZXJuKSB7XG4gIGNvbnN0IG1hdGNoZXMgPSBwYXR0ZXJuLm1hcCh4ID0+IGJ1aWxkTWF0Y2goeCkpO1xuXG4gIHJldHVybiBmdW5jdGlvbiAodmFsdWUsIGFyZ3MpIHtcbiAgICBpZiAoIUNoZWNrcy5pc19hcnJheSh2YWx1ZSkgfHwgdmFsdWUubGVuZ3RoICE9IHBhdHRlcm4ubGVuZ3RoKSB7XG4gICAgICByZXR1cm4gZmFsc2U7XG4gICAgfVxuXG4gICAgcmV0dXJuIHZhbHVlLmV2ZXJ5KGZ1bmN0aW9uICh2LCBpKSB7XG4gICAgICByZXR1cm4gbWF0Y2hlc1tpXSh2YWx1ZVtpXSwgYXJncyk7XG4gICAgfSk7XG4gIH07XG59XG5cbmZ1bmN0aW9uIHJlc29sdmVPYmplY3QocGF0dGVybikge1xuICBsZXQgbWF0Y2hlcyA9IHt9O1xuXG4gIGZvciAobGV0IGtleSBvZiBPYmplY3Qua2V5cyhwYXR0ZXJuKS5jb25jYXQoT2JqZWN0LmdldE93blByb3BlcnR5U3ltYm9scyhwYXR0ZXJuKSkpIHtcbiAgICBtYXRjaGVzW2tleV0gPSBidWlsZE1hdGNoKHBhdHRlcm5ba2V5XSk7XG4gIH1cblxuICByZXR1cm4gZnVuY3Rpb24gKHZhbHVlLCBhcmdzKSB7XG4gICAgaWYgKCFDaGVja3MuaXNfb2JqZWN0KHZhbHVlKSB8fCBwYXR0ZXJuLmxlbmd0aCA+IHZhbHVlLmxlbmd0aCkge1xuICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH1cblxuICAgIGZvciAobGV0IGtleSBvZiBPYmplY3Qua2V5cyhwYXR0ZXJuKS5jb25jYXQoT2JqZWN0LmdldE93blByb3BlcnR5U3ltYm9scyhwYXR0ZXJuKSkpIHtcbiAgICAgIGlmICghKGtleSBpbiB2YWx1ZSkgfHwgIW1hdGNoZXNba2V5XSh2YWx1ZVtrZXldLCBhcmdzKSkge1xuICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICB9XG4gICAgfVxuXG4gICAgcmV0dXJuIHRydWU7XG4gIH07XG59XG5cbmZ1bmN0aW9uIHJlc29sdmVOb01hdGNoKCkge1xuICByZXR1cm4gZnVuY3Rpb24gKCkge1xuICAgIHJldHVybiBmYWxzZTtcbiAgfTtcbn1cblxudmFyIFJlc29sdmVycyA9IHtcbiAgcmVzb2x2ZUJvdW5kLFxuICByZXNvbHZlV2lsZGNhcmQsXG4gIHJlc29sdmVWYXJpYWJsZSxcbiAgcmVzb2x2ZUhlYWRUYWlsLFxuICByZXNvbHZlQ2FwdHVyZSxcbiAgcmVzb2x2ZVN0YXJ0c1dpdGgsXG4gIHJlc29sdmVUeXBlLFxuICByZXNvbHZlQXJyYXksXG4gIHJlc29sdmVPYmplY3QsXG4gIHJlc29sdmVOb01hdGNoLFxuICByZXNvbHZlU3ltYm9sLFxuICByZXNvbHZlU3RyaW5nLFxuICByZXNvbHZlTnVtYmVyLFxuICByZXNvbHZlQm9vbGVhbixcbiAgcmVzb2x2ZUZ1bmN0aW9uLFxuICByZXNvbHZlTnVsbFxufTtcblxuZnVuY3Rpb24gYnVpbGRNYXRjaChwYXR0ZXJuKSB7XG5cbiAgaWYgKENoZWNrcy5pc192YXJpYWJsZShwYXR0ZXJuKSkge1xuICAgIHJldHVybiBSZXNvbHZlcnMucmVzb2x2ZVZhcmlhYmxlKHBhdHRlcm4pO1xuICB9XG5cbiAgaWYgKENoZWNrcy5pc193aWxkY2FyZChwYXR0ZXJuKSkge1xuICAgIHJldHVybiBSZXNvbHZlcnMucmVzb2x2ZVdpbGRjYXJkKHBhdHRlcm4pO1xuICB9XG5cbiAgaWYgKENoZWNrcy5pc191bmRlZmluZWQocGF0dGVybikpIHtcbiAgICByZXR1cm4gUmVzb2x2ZXJzLnJlc29sdmVXaWxkY2FyZChwYXR0ZXJuKTtcbiAgfVxuXG4gIGlmIChDaGVja3MuaXNfaGVhZFRhaWwocGF0dGVybikpIHtcbiAgICByZXR1cm4gUmVzb2x2ZXJzLnJlc29sdmVIZWFkVGFpbChwYXR0ZXJuKTtcbiAgfVxuXG4gIGlmIChDaGVja3MuaXNfc3RhcnRzV2l0aChwYXR0ZXJuKSkge1xuICAgIHJldHVybiBSZXNvbHZlcnMucmVzb2x2ZVN0YXJ0c1dpdGgocGF0dGVybik7XG4gIH1cblxuICBpZiAoQ2hlY2tzLmlzX2NhcHR1cmUocGF0dGVybikpIHtcbiAgICByZXR1cm4gUmVzb2x2ZXJzLnJlc29sdmVDYXB0dXJlKHBhdHRlcm4pO1xuICB9XG5cbiAgaWYgKENoZWNrcy5pc19ib3VuZChwYXR0ZXJuKSkge1xuICAgIHJldHVybiBSZXNvbHZlcnMucmVzb2x2ZUJvdW5kKHBhdHRlcm4pO1xuICB9XG5cbiAgaWYgKENoZWNrcy5pc190eXBlKHBhdHRlcm4pKSB7XG4gICAgcmV0dXJuIFJlc29sdmVycy5yZXNvbHZlVHlwZShwYXR0ZXJuKTtcbiAgfVxuXG4gIGlmIChDaGVja3MuaXNfYXJyYXkocGF0dGVybikpIHtcbiAgICByZXR1cm4gUmVzb2x2ZXJzLnJlc29sdmVBcnJheShwYXR0ZXJuKTtcbiAgfVxuXG4gIGlmIChDaGVja3MuaXNfbnVtYmVyKHBhdHRlcm4pKSB7XG4gICAgcmV0dXJuIFJlc29sdmVycy5yZXNvbHZlTnVtYmVyKHBhdHRlcm4pO1xuICB9XG5cbiAgaWYgKENoZWNrcy5pc19zdHJpbmcocGF0dGVybikpIHtcbiAgICByZXR1cm4gUmVzb2x2ZXJzLnJlc29sdmVTdHJpbmcocGF0dGVybik7XG4gIH1cblxuICBpZiAoQ2hlY2tzLmlzX2Jvb2xlYW4ocGF0dGVybikpIHtcbiAgICByZXR1cm4gUmVzb2x2ZXJzLnJlc29sdmVCb29sZWFuKHBhdHRlcm4pO1xuICB9XG5cbiAgaWYgKENoZWNrcy5pc19zeW1ib2wocGF0dGVybikpIHtcbiAgICByZXR1cm4gUmVzb2x2ZXJzLnJlc29sdmVTeW1ib2wocGF0dGVybik7XG4gIH1cblxuICBpZiAoQ2hlY2tzLmlzX251bGwocGF0dGVybikpIHtcbiAgICByZXR1cm4gUmVzb2x2ZXJzLnJlc29sdmVOdWxsKHBhdHRlcm4pO1xuICB9XG5cbiAgaWYgKENoZWNrcy5pc19vYmplY3QocGF0dGVybikpIHtcbiAgICByZXR1cm4gUmVzb2x2ZXJzLnJlc29sdmVPYmplY3QocGF0dGVybik7XG4gIH1cblxuICByZXR1cm4gUmVzb2x2ZXJzLnJlc29sdmVOb01hdGNoKCk7XG59XG5cbmNsYXNzIE1hdGNoRXJyb3IgZXh0ZW5kcyBFcnJvciB7XG4gIGNvbnN0cnVjdG9yKGFyZykge1xuICAgIHN1cGVyKCk7XG5cbiAgICBpZiAodHlwZW9mIGFyZyA9PT0gJ3N5bWJvbCcpIHtcbiAgICAgIHRoaXMubWVzc2FnZSA9ICdObyBtYXRjaCBmb3I6ICcgKyBhcmcudG9TdHJpbmcoKTtcbiAgICB9IGVsc2UgaWYgKEFycmF5LmlzQXJyYXkoYXJnKSkge1xuICAgICAgbGV0IG1hcHBlZFZhbHVlcyA9IGFyZy5tYXAoeCA9PiB4LnRvU3RyaW5nKCkpO1xuICAgICAgdGhpcy5tZXNzYWdlID0gJ05vIG1hdGNoIGZvcjogJyArIG1hcHBlZFZhbHVlcztcbiAgICB9IGVsc2Uge1xuICAgICAgdGhpcy5tZXNzYWdlID0gJ05vIG1hdGNoIGZvcjogJyArIGFyZztcbiAgICB9XG5cbiAgICB0aGlzLnN0YWNrID0gbmV3IEVycm9yKCkuc3RhY2s7XG4gICAgdGhpcy5uYW1lID0gdGhpcy5jb25zdHJ1Y3Rvci5uYW1lO1xuICB9XG59XG5cbmNsYXNzIENhc2Uge1xuXG4gIGNvbnN0cnVjdG9yKHBhdHRlcm4sIGZuLCBndWFyZCA9ICgpID0+IHRydWUpIHtcbiAgICB0aGlzLnBhdHRlcm4gPSBidWlsZE1hdGNoKHBhdHRlcm4pO1xuICAgIHRoaXMuZm4gPSBmbjtcbiAgICB0aGlzLmd1YXJkID0gZ3VhcmQ7XG4gIH1cbn1cblxuZnVuY3Rpb24gbWFrZV9jYXNlKHBhdHRlcm4sIGZuLCBndWFyZCA9ICgpID0+IHRydWUpIHtcbiAgcmV0dXJuIG5ldyBDYXNlKHBhdHRlcm4sIGZuLCBndWFyZCk7XG59XG5cbmZ1bmN0aW9uIGRlZm1hdGNoKC4uLmNhc2VzKSB7XG4gIHJldHVybiBmdW5jdGlvbiAoLi4uYXJncykge1xuICAgIGZvciAobGV0IHByb2Nlc3NlZENhc2Ugb2YgY2FzZXMpIHtcbiAgICAgIGxldCByZXN1bHQgPSBbXTtcbiAgICAgIGlmIChwcm9jZXNzZWRDYXNlLnBhdHRlcm4oYXJncywgcmVzdWx0KSAmJiBwcm9jZXNzZWRDYXNlLmd1YXJkLmFwcGx5KHRoaXMsIHJlc3VsdCkpIHtcbiAgICAgICAgcmV0dXJuIHByb2Nlc3NlZENhc2UuZm4uYXBwbHkodGhpcywgcmVzdWx0KTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICB0aHJvdyBuZXcgTWF0Y2hFcnJvcihhcmdzKTtcbiAgfTtcbn1cblxuZnVuY3Rpb24gbWF0Y2gocGF0dGVybiwgZXhwciwgZ3VhcmQgPSAoKSA9PiB0cnVlKSB7XG4gIGxldCByZXN1bHQgPSBbXTtcbiAgbGV0IHByb2Nlc3NlZFBhdHRlcm4gPSBidWlsZE1hdGNoKHBhdHRlcm4pO1xuICBpZiAocHJvY2Vzc2VkUGF0dGVybihleHByLCByZXN1bHQpICYmIGd1YXJkLmFwcGx5KHRoaXMsIHJlc3VsdCkpIHtcbiAgICByZXR1cm4gcmVzdWx0O1xuICB9IGVsc2Uge1xuICAgIHRocm93IG5ldyBNYXRjaEVycm9yKGV4cHIpO1xuICB9XG59XG5cbmZ1bmN0aW9uIG1hdGNoX25vX3Rocm93KHBhdHRlcm4sIGV4cHIsIGd1YXJkID0gKCkgPT4gdHJ1ZSkge1xuICB0cnkge1xuICAgIHJldHVybiBtYXRjaChwYXR0ZXJuLCBleHByLCBndWFyZCk7XG4gIH0gY2F0Y2ggKGUpIHtcbiAgICBpZiAoZSBpbnN0YW5jZW9mIE1hdGNoRXJyb3IpIHtcbiAgICAgIHJldHVybiBudWxsO1xuICAgIH1cblxuICAgIHRocm93IGU7XG4gIH1cbn1cblxudmFyIFBhdHRlcm5zID0ge1xuICBkZWZtYXRjaCwgbWF0Y2gsIE1hdGNoRXJyb3IsIG1hdGNoX25vX3Rocm93LFxuICB2YXJpYWJsZSwgd2lsZGNhcmQsIHN0YXJ0c1dpdGgsXG4gIGNhcHR1cmUsIGhlYWRUYWlsLCB0eXBlLCBib3VuZCwgQ2FzZSwgbWFrZV9jYXNlXG59O1xuXG4vL2h0dHBzOi8vZ2l0aHViLmNvbS9haXJwb3J0eWgvcHJvdG9tb3JwaGlzbVxuY2xhc3MgUHJvdG9jb2wge1xuICBjb25zdHJ1Y3RvcihzcGVjKSB7XG4gICAgdGhpcy5yZWdpc3RyeSA9IG5ldyBNYXAoKTtcbiAgICB0aGlzLmZhbGxiYWNrID0gbnVsbDtcblxuICAgIGZvciAobGV0IGZ1bk5hbWUgaW4gc3BlYykge1xuICAgICAgdGhpc1tmdW5OYW1lXSA9IGNyZWF0ZUZ1bihmdW5OYW1lKS5iaW5kKHRoaXMpO1xuICAgIH1cblxuICAgIGZ1bmN0aW9uIGNyZWF0ZUZ1bihmdW5OYW1lKSB7XG5cbiAgICAgIHJldHVybiBmdW5jdGlvbiAoLi4uYXJncykge1xuICAgICAgICBsZXQgdGhpbmcgPSBhcmdzWzBdO1xuICAgICAgICBsZXQgZnVuID0gbnVsbDtcblxuICAgICAgICBpZiAoTnVtYmVyLmlzSW50ZWdlcih0aGluZykgJiYgdGhpcy5oYXNJbXBsZW1lbnRhdGlvbihJbnRlZ2VyKSkge1xuICAgICAgICAgIGZ1biA9IHRoaXMucmVnaXN0cnkuZ2V0KENvcmUuSW50ZWdlcilbZnVuTmFtZV07XG4gICAgICAgIH0gZWxzZSBpZiAodHlwZW9mIHRoaW5nID09PSBcIm51bWJlclwiICYmICFOdW1iZXIuaXNJbnRlZ2VyKHRoaW5nKSAmJiB0aGlzLmhhc0ltcGxlbWVudGF0aW9uKEZsb2F0KSkge1xuICAgICAgICAgIGZ1biA9IHRoaXMucmVnaXN0cnkuZ2V0KENvcmUuRmxvYXQpW2Z1bk5hbWVdO1xuICAgICAgICB9IGVsc2UgaWYgKHRoaXMuaGFzSW1wbGVtZW50YXRpb24odGhpbmcpKSB7XG4gICAgICAgICAgZnVuID0gdGhpcy5yZWdpc3RyeS5nZXQodGhpbmcuY29uc3RydWN0b3IpW2Z1bk5hbWVdO1xuICAgICAgICB9IGVsc2UgaWYgKHRoaXMuZmFsbGJhY2spIHtcbiAgICAgICAgICBmdW4gPSB0aGlzLmZhbGxiYWNrW2Z1bk5hbWVdO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKGZ1biAhPSBudWxsKSB7XG4gICAgICAgICAgbGV0IHJldHZhbCA9IGZ1bi5hcHBseSh0aGlzLCBhcmdzKTtcbiAgICAgICAgICByZXR1cm4gcmV0dmFsO1xuICAgICAgICB9XG5cbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKFwiTm8gaW1wbGVtZW50YXRpb24gZm91bmQgZm9yIFwiICsgdGhpbmcpO1xuICAgICAgfTtcbiAgICB9XG4gIH1cblxuICBpbXBsZW1lbnRhdGlvbih0eXBlLCBpbXBsZW1lbnRhdGlvbikge1xuICAgIGlmICh0eXBlID09PSBudWxsKSB7XG4gICAgICB0aGlzLmZhbGxiYWNrID0gaW1wbGVtZW50YXRpb247XG4gICAgfSBlbHNlIHtcbiAgICAgIHRoaXMucmVnaXN0cnkuc2V0KHR5cGUsIGltcGxlbWVudGF0aW9uKTtcbiAgICB9XG4gIH1cblxuICBoYXNJbXBsZW1lbnRhdGlvbih0aGluZykge1xuICAgIHJldHVybiB0aGlzLnJlZ2lzdHJ5Lmhhcyh0aGluZy5jb25zdHJ1Y3Rvcik7XG4gIH1cbn1cblxuZnVuY3Rpb24gY2FsbF9wcm9wZXJ0eShpdGVtLCBwcm9wZXJ0eSkge1xuICBsZXQgcHJvcCA9IG51bGw7XG5cbiAgaWYgKHByb3BlcnR5IGluIGl0ZW0pIHtcbiAgICBwcm9wID0gcHJvcGVydHk7XG4gIH0gZWxzZSBpZiAoU3ltYm9sLmZvcihwcm9wZXJ0eSkgaW4gaXRlbSkge1xuICAgIHByb3AgPSBTeW1ib2wuZm9yKHByb3BlcnR5KTtcbiAgfSBlbHNlIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoYFByb3BlcnR5ICR7IHByb3BlcnR5IH0gbm90IGZvdW5kIGluICR7IGl0ZW0gfWApO1xuICB9XG5cbiAgaWYgKGl0ZW1bcHJvcF0gaW5zdGFuY2VvZiBGdW5jdGlvbikge1xuICAgIHJldHVybiBpdGVtW3Byb3BdKCk7XG4gIH0gZWxzZSB7XG4gICAgcmV0dXJuIGl0ZW1bcHJvcF07XG4gIH1cbn1cblxuZnVuY3Rpb24gYXBwbHkoLi4uYXJncykge1xuICBpZiAoYXJncy5sZW5ndGggPT09IDIpIHtcbiAgICBhcmdzWzBdLmFwcGx5KG51bGwsIGFyZ3Muc2xpY2UoMSkpO1xuICB9IGVsc2Uge1xuICAgIGFyZ3NbMF1bYXJnc1sxXV0uYXBwbHkobnVsbCwgYXJncy5zbGljZSgyKSk7XG4gIH1cbn1cblxuZnVuY3Rpb24gY29udGFpbnMobGVmdCwgcmlnaHQpIHtcbiAgZm9yIChsZXQgeCBvZiByaWdodCkge1xuICAgIGlmIChQYXR0ZXJucy5tYXRjaF9ub190aHJvdyhsZWZ0LCB4KSAhPSBudWxsKSB7XG4gICAgICByZXR1cm4gdHJ1ZTtcbiAgICB9XG4gIH1cblxuICByZXR1cm4gZmFsc2U7XG59XG5cbmZ1bmN0aW9uIGdldF9nbG9iYWwoKSB7XG4gIGlmICh0eXBlb2Ygc2VsZiAhPT0gJ3VuZGVmaW5lZCcpIHtcbiAgICByZXR1cm4gc2VsZjtcbiAgfSBlbHNlIGlmICh0eXBlb2Ygd2luZG93ICE9PSAndW5kZWZpbmVkJykge1xuICAgIHJldHVybiB3aW5kb3c7XG4gIH0gZWxzZSBpZiAodHlwZW9mIGdsb2JhbCAhPT0gJ3VuZGVmaW5lZCcpIHtcbiAgICByZXR1cm4gZ2xvYmFsO1xuICB9XG5cbiAgdGhyb3cgbmV3IEVycm9yKCdObyBnbG9iYWwgc3RhdGUgZm91bmQnKTtcbn1cblxuZnVuY3Rpb24gZGVmc3RydWN0KGRlZmF1bHRzKSB7XG4gIHJldHVybiBjbGFzcyB7XG4gICAgY29uc3RydWN0b3IodXBkYXRlID0ge30pIHtcbiAgICAgIGxldCB0aGVfdmFsdWVzID0gT2JqZWN0LmFzc2lnbihkZWZhdWx0cywgdXBkYXRlKTtcbiAgICAgIE9iamVjdC5hc3NpZ24odGhpcywgdGhlX3ZhbHVlcyk7XG4gICAgfVxuXG4gICAgc3RhdGljIGNyZWF0ZSh1cGRhdGVzID0ge30pIHtcbiAgICAgIGxldCB4ID0gbmV3IHRoaXModXBkYXRlcyk7XG4gICAgICByZXR1cm4gT2JqZWN0LmZyZWV6ZSh4KTtcbiAgICB9XG4gIH07XG59XG5cbmZ1bmN0aW9uIGRlZmV4Y2VwdGlvbihkZWZhdWx0cykge1xuICByZXR1cm4gY2xhc3MgZXh0ZW5kcyBFcnJvciB7XG4gICAgY29uc3RydWN0b3IodXBkYXRlID0ge30pIHtcbiAgICAgIGxldCBtZXNzYWdlID0gdXBkYXRlLm1lc3NhZ2UgfHwgJyc7XG4gICAgICBzdXBlcihtZXNzYWdlKTtcblxuICAgICAgbGV0IHRoZV92YWx1ZXMgPSBPYmplY3QuYXNzaWduKGRlZmF1bHRzLCB1cGRhdGUpO1xuICAgICAgT2JqZWN0LmFzc2lnbih0aGlzLCB0aGVfdmFsdWVzKTtcblxuICAgICAgdGhpcy5uYW1lID0gdGhpcy5jb25zdHJ1Y3Rvci5uYW1lO1xuICAgICAgdGhpcy5tZXNzYWdlID0gbWVzc2FnZTtcbiAgICAgIHRoaXNbU3BlY2lhbEZvcm1zLmF0b20oJ19fZXhjZXB0aW9uX18nKV0gPSB0cnVlO1xuICAgICAgRXJyb3IuY2FwdHVyZVN0YWNrVHJhY2UodGhpcywgdGhpcy5jb25zdHJ1Y3Rvci5uYW1lKTtcbiAgICB9XG5cbiAgICBzdGF0aWMgY3JlYXRlKHVwZGF0ZXMgPSB7fSkge1xuICAgICAgbGV0IHggPSBuZXcgdGhpcyh1cGRhdGVzKTtcbiAgICAgIHJldHVybiBPYmplY3QuZnJlZXplKHgpO1xuICAgIH1cbiAgfTtcbn1cblxuZnVuY3Rpb24gZGVmcHJvdG9jb2woc3BlYykge1xuICByZXR1cm4gbmV3IFByb3RvY29sKHNwZWMpO1xufVxuXG5mdW5jdGlvbiBkZWZpbXBsKHByb3RvY29sLCB0eXBlLCBpbXBsKSB7XG4gIHByb3RvY29sLmltcGxlbWVudGF0aW9uKHR5cGUsIGltcGwpO1xufVxuXG5mdW5jdGlvbiBnZXRfb2JqZWN0X2tleXMob2JqKSB7XG4gIHJldHVybiBPYmplY3Qua2V5cyhvYmopLmNvbmNhdChPYmplY3QuZ2V0T3duUHJvcGVydHlTeW1ib2xzKG9iaikpO1xufVxuXG5mdW5jdGlvbiBpc192YWxpZF9jaGFyYWN0ZXIoY29kZXBvaW50KSB7XG4gIHRyeSB7XG4gICAgcmV0dXJuIFN0cmluZy5mcm9tQ29kZVBvaW50KGNvZGVwb2ludCkgIT0gbnVsbDtcbiAgfSBjYXRjaCAoZSkge1xuICAgIHJldHVybiBmYWxzZTtcbiAgfVxufVxuXG4vL2h0dHBzOi8vZGV2ZWxvcGVyLm1vemlsbGEub3JnL2VuLVVTL2RvY3MvV2ViL0FQSS9XaW5kb3dCYXNlNjQvQmFzZTY0X2VuY29kaW5nX2FuZF9kZWNvZGluZyNTb2x1dGlvbl8yXyVFMiU4MCU5M19yZXdyaXRlX3RoZV9ET01zX2F0b2IoKV9hbmRfYnRvYSgpX3VzaW5nX0phdmFTY3JpcHQnc19UeXBlZEFycmF5c19hbmRfVVRGLThcbmZ1bmN0aW9uIGI2NEVuY29kZVVuaWNvZGUoc3RyKSB7XG4gIHJldHVybiBidG9hKGVuY29kZVVSSUNvbXBvbmVudChzdHIpLnJlcGxhY2UoLyUoWzAtOUEtRl17Mn0pL2csIGZ1bmN0aW9uIChtYXRjaCwgcDEpIHtcbiAgICByZXR1cm4gU3RyaW5nLmZyb21DaGFyQ29kZSgnMHgnICsgcDEpO1xuICB9KSk7XG59XG5cbmZ1bmN0aW9uIGRlbGV0ZV9wcm9wZXJ0eV9mcm9tX21hcChtYXAsIHByb3BlcnR5KSB7XG4gIGxldCBuZXdfbWFwID0gT2JqZWN0LmFzc2lnbihPYmplY3QuY3JlYXRlKG1hcC5jb25zdHJ1Y3Rvci5wcm90b3R5cGUpLCBtYXApO1xuICBkZWxldGUgbmV3X21hcFtwcm9wZXJ0eV07XG5cbiAgcmV0dXJuIE9iamVjdC5mcmVlemUobmV3X21hcCk7XG59XG5cbmZ1bmN0aW9uIGNsYXNzX3RvX29iaihtYXApIHtcbiAgbGV0IG5ld19tYXAgPSBPYmplY3QuYXNzaWduKHt9LCBtYXApO1xuICByZXR1cm4gT2JqZWN0LmZyZWV6ZShuZXdfbWFwKTtcbn1cblxuZnVuY3Rpb24gYWRkX3Byb3BlcnR5X3RvX21hcChtYXAsIHByb3BlcnR5LCB2YWx1ZSkge1xuICBsZXQgbmV3X21hcCA9IE9iamVjdC5hc3NpZ24oe30sIG1hcCk7XG4gIG5ld19tYXBbcHJvcGVydHldID0gdmFsdWU7XG4gIHJldHVybiBPYmplY3QuZnJlZXplKG5ld19tYXApO1xufVxuXG5mdW5jdGlvbiB1cGRhdGVfbWFwKG1hcCwgcHJvcGVydHksIHZhbHVlKSB7XG4gIGlmIChwcm9wZXJ0eSBpbiBnZXRfb2JqZWN0X2tleXMobWFwKSkge1xuICAgIHJldHVybiBhZGRfcHJvcGVydHlfdG9fbWFwKG1hcCwgcHJvcGVydHksIHZhbHVlKTtcbiAgfVxuXG4gIHRocm93ICdtYXAgZG9lcyBub3QgaGF2ZSBrZXknO1xufVxuXG5mdW5jdGlvbiBibm90KGV4cHIpIHtcbiAgcmV0dXJuIH5leHByO1xufVxuXG5mdW5jdGlvbiBiYW5kKGxlZnQsIHJpZ2h0KSB7XG4gIHJldHVybiBsZWZ0ICYgcmlnaHQ7XG59XG5cbmZ1bmN0aW9uIGJvcihsZWZ0LCByaWdodCkge1xuICByZXR1cm4gbGVmdCB8IHJpZ2h0O1xufVxuXG5mdW5jdGlvbiBic2wobGVmdCwgcmlnaHQpIHtcbiAgcmV0dXJuIGxlZnQgPDwgcmlnaHQ7XG59XG5cbmZ1bmN0aW9uIGJzcihsZWZ0LCByaWdodCkge1xuICByZXR1cm4gbGVmdCA+PiByaWdodDtcbn1cblxuZnVuY3Rpb24gYnhvcihsZWZ0LCByaWdodCkge1xuICByZXR1cm4gbGVmdCBeIHJpZ2h0O1xufVxuXG5mdW5jdGlvbiB6aXAobGlzdF9vZl9saXN0cykge1xuICBpZiAobGlzdF9vZl9saXN0cy5sZW5ndGggPT09IDApIHtcbiAgICByZXR1cm4gT2JqZWN0LmZyZWV6ZShbXSk7XG4gIH1cblxuICBsZXQgbmV3X3ZhbHVlID0gW107XG4gIGxldCBzbWFsbGVzdF9sZW5ndGggPSBsaXN0X29mX2xpc3RzWzBdO1xuXG4gIGZvciAobGV0IHggb2YgbGlzdF9vZl9saXN0cykge1xuICAgIGlmICh4Lmxlbmd0aCA8IHNtYWxsZXN0X2xlbmd0aCkge1xuICAgICAgc21hbGxlc3RfbGVuZ3RoID0geC5sZW5ndGg7XG4gICAgfVxuICB9XG5cbiAgZm9yIChsZXQgaSA9IDA7IGkgPCBzbWFsbGVzdF9sZW5ndGg7IGkrKykge1xuICAgIGxldCBjdXJyZW50X3ZhbHVlID0gW107XG4gICAgZm9yIChsZXQgaiA9IDA7IGogPCBsaXN0X29mX2xpc3RzLmxlbmd0aDsgaisrKSB7XG4gICAgICBjdXJyZW50X3ZhbHVlLnB1c2gobGlzdF9vZl9saXN0c1tqXVtpXSk7XG4gICAgfVxuXG4gICAgbmV3X3ZhbHVlLnB1c2gobmV3IFR1cGxlKC4uLmN1cnJlbnRfdmFsdWUpKTtcbiAgfVxuXG4gIHJldHVybiBPYmplY3QuZnJlZXplKG5ld192YWx1ZSk7XG59XG5cbmZ1bmN0aW9uIGNhbl9kZWNvZGU2NChkYXRhKSB7XG4gIHRyeSB7XG4gICAgYXRvYihkYXRhKTtcbiAgICByZXR1cm4gdHJ1ZTtcbiAgfSBjYXRjaCAoZSkge1xuICAgIHJldHVybiBmYWxzZTtcbiAgfVxufVxuXG5mdW5jdGlvbiByZW1vdmVfZnJvbV9saXN0KGxpc3QsIGVsZW1lbnQpIHtcbiAgbGV0IGZvdW5kID0gZmFsc2U7XG5cbiAgcmV0dXJuIGxpc3QuZmlsdGVyKGVsZW0gPT4ge1xuICAgIGlmICghZm91bmQgJiYgZWxlbSA9PT0gZWxlbWVudCkge1xuICAgICAgZm91bmQgPSB0cnVlO1xuICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH1cblxuICAgIHJldHVybiB0cnVlO1xuICB9KTtcbn1cblxuZnVuY3Rpb24gZm9sZGwoZnVuLCBhY2MsIGxpc3QpIHtcbiAgbGV0IGFjYzEgPSBhY2M7XG5cbiAgZm9yIChjb25zdCBlbCBvZiBsaXN0KSB7XG4gICAgYWNjMSA9IGZ1bihlbCwgYWNjMSk7XG4gIH1cblxuICByZXR1cm4gYWNjMTtcbn1cblxuZnVuY3Rpb24gZm9sZHIoZnVuLCBhY2MsIGxpc3QpIHtcbiAgbGV0IGFjYzEgPSBhY2M7XG5cbiAgZm9yIChsZXQgaSA9IGxpc3QubGVuZ3RoIC0gMTsgaSA+PSAwOyBpLS0pIHtcbiAgICBhY2MxID0gZnVuKGxpc3RbaV0sIGFjYzEpO1xuICB9XG5cbiAgcmV0dXJuIGFjYzE7XG59XG5cbmZ1bmN0aW9uIGtleWRlbGV0ZShrZXksIG4sIHR1cGxlbGlzdCkge1xuXG4gIGZvciAobGV0IGkgPSB0dXBsZWxpc3QubGVuZ3RoIC0gMTsgaSA+PSAwOyBpLS0pIHtcbiAgICBpZiAodHVwbGVsaXN0W2ldLmdldChuKSA9PT0ga2V5KSB7XG4gICAgICByZXR1cm4gdHVwbGVsaXN0LmNvbmNhdChbXSkuc3BsaWNlKGksIDEpO1xuICAgIH1cbiAgfVxuXG4gIHJldHVybiB0dXBsZWxpc3Q7XG59XG5cbmZ1bmN0aW9uIGtleXN0b3JlKGtleSwgbiwgbGlzdCwgbmV3dHVwbGUpIHtcbiAgZm9yIChsZXQgaSA9IGxpc3QubGVuZ3RoIC0gMTsgaSA+PSAwOyBpLS0pIHtcbiAgICBpZiAobGlzdFtpXS5nZXQobikgPT09IGtleSkge1xuICAgICAgcmV0dXJuIGxpc3QuY29uY2F0KFtdKS5zcGxpY2UoaSwgMSwgbmV3dHVwbGUpO1xuICAgIH1cbiAgfVxuXG4gIHJldHVybiBsaXN0O1xufVxuXG5mdW5jdGlvbiByZXZlcnNlKGxpc3QpIHtcbiAgcmV0dXJuIGxpc3QuY29uY2F0KFtdKS5yZXZlcnNlKCk7XG59XG5cbmZ1bmN0aW9uIG1hcHNfZmluZChrZXksIG1hcCkge1xuICBpZiAoa2V5IGluIGdldF9vYmplY3Rfa2V5cyhtYXApKSB7XG4gICAgcmV0dXJuIG5ldyBUdXBsZShTeW1ib2wuZm9yKCdvaycpLCBtYXBba2V5XSk7XG4gIH0gZWxzZSB7XG4gICAgcmV0dXJuIFN5bWJvbC5mb3IoJ2Vycm9yJyk7XG4gIH1cbn1cblxudmFyIEZ1bmN0aW9ucyA9IHtcbiAgY2FsbF9wcm9wZXJ0eSxcbiAgYXBwbHksXG4gIGNvbnRhaW5zLFxuICBnZXRfZ2xvYmFsLFxuICBkZWZzdHJ1Y3QsXG4gIGRlZmV4Y2VwdGlvbixcbiAgZGVmcHJvdG9jb2wsXG4gIGRlZmltcGwsXG4gIGdldF9vYmplY3Rfa2V5cyxcbiAgaXNfdmFsaWRfY2hhcmFjdGVyLFxuICBiNjRFbmNvZGVVbmljb2RlLFxuICBkZWxldGVfcHJvcGVydHlfZnJvbV9tYXAsXG4gIGFkZF9wcm9wZXJ0eV90b19tYXAsXG4gIGNsYXNzX3RvX29iaixcbiAgY2FuX2RlY29kZTY0LFxuICBibm90LFxuICBiYW5kLFxuICBib3IsXG4gIGJzbCxcbiAgYnNyLFxuICBieG9yLFxuICB6aXAsXG4gIGZvbGRsLFxuICBmb2xkcixcbiAgcmVtb3ZlX2Zyb21fbGlzdCxcbiAga2V5ZGVsZXRlLFxuICBrZXlzdG9yZSxcbiAgcmV2ZXJzZSxcbiAgdXBkYXRlX21hcCxcbiAgbWFwc19maW5kXG59O1xuXG5mdW5jdGlvbiBfY2FzZShjb25kaXRpb24sIGNsYXVzZXMpIHtcbiAgcmV0dXJuIFBhdHRlcm5zLmRlZm1hdGNoKC4uLmNsYXVzZXMpKGNvbmRpdGlvbik7XG59XG5cbmZ1bmN0aW9uIGNvbmQoY2xhdXNlcykge1xuICBmb3IgKGxldCBjbGF1c2Ugb2YgY2xhdXNlcykge1xuICAgIGlmIChjbGF1c2VbMF0pIHtcbiAgICAgIHJldHVybiBjbGF1c2VbMV0oKTtcbiAgICB9XG4gIH1cblxuICB0aHJvdyBuZXcgRXJyb3IoKTtcbn1cblxuZnVuY3Rpb24gbWFwX3VwZGF0ZShtYXAsIHZhbHVlcykge1xuICByZXR1cm4gT2JqZWN0LmZyZWV6ZShPYmplY3QuYXNzaWduKE9iamVjdC5jcmVhdGUobWFwLmNvbnN0cnVjdG9yLnByb3RvdHlwZSksIG1hcCwgdmFsdWVzKSk7XG59XG5cbmZ1bmN0aW9uIF9mb3IoY29sbGVjdGlvbnMsIGZ1biwgZmlsdGVyID0gKCkgPT4gdHJ1ZSwgaW50byA9IFtdLCBwcmV2aW91c1ZhbHVlcyA9IFtdKSB7XG4gIGxldCBwYXR0ZXJuID0gY29sbGVjdGlvbnNbMF1bMF07XG4gIGxldCBjb2xsZWN0aW9uID0gY29sbGVjdGlvbnNbMF1bMV07XG5cbiAgaWYgKGNvbGxlY3Rpb25zLmxlbmd0aCA9PT0gMSkge1xuXG4gICAgZm9yIChsZXQgZWxlbSBvZiBjb2xsZWN0aW9uKSB7XG4gICAgICBsZXQgciA9IFBhdHRlcm5zLm1hdGNoX25vX3Rocm93KHBhdHRlcm4sIGVsZW0pO1xuICAgICAgbGV0IGFyZ3MgPSBwcmV2aW91c1ZhbHVlcy5jb25jYXQocik7XG5cbiAgICAgIGlmIChyICYmIGZpbHRlci5hcHBseSh0aGlzLCBhcmdzKSkge1xuICAgICAgICBpbnRvID0gaW50by5jb25jYXQoW2Z1bi5hcHBseSh0aGlzLCBhcmdzKV0pO1xuICAgICAgfVxuICAgIH1cblxuICAgIHJldHVybiBpbnRvO1xuICB9IGVsc2Uge1xuICAgIGxldCBfaW50byA9IFtdO1xuXG4gICAgZm9yIChsZXQgZWxlbSBvZiBjb2xsZWN0aW9uKSB7XG4gICAgICBsZXQgciA9IFBhdHRlcm5zLm1hdGNoX25vX3Rocm93KHBhdHRlcm4sIGVsZW0pO1xuICAgICAgaWYgKHIpIHtcbiAgICAgICAgX2ludG8gPSBpbnRvLmNvbmNhdCh0aGlzLl9mb3IoY29sbGVjdGlvbnMuc2xpY2UoMSksIGZ1biwgZmlsdGVyLCBfaW50bywgcHJldmlvdXNWYWx1ZXMuY29uY2F0KHIpKSk7XG4gICAgICB9XG4gICAgfVxuXG4gICAgcmV0dXJuIF9pbnRvO1xuICB9XG59XG5cbmZ1bmN0aW9uIF90cnkoZG9fZnVuLCByZXNjdWVfZnVuY3Rpb24sIGNhdGNoX2Z1biwgZWxzZV9mdW5jdGlvbiwgYWZ0ZXJfZnVuY3Rpb24pIHtcbiAgbGV0IHJlc3VsdCA9IG51bGw7XG5cbiAgdHJ5IHtcbiAgICByZXN1bHQgPSBkb19mdW4oKTtcbiAgfSBjYXRjaCAoZSkge1xuICAgIGxldCBleF9yZXN1bHQgPSBudWxsO1xuXG4gICAgaWYgKHJlc2N1ZV9mdW5jdGlvbikge1xuICAgICAgdHJ5IHtcbiAgICAgICAgZXhfcmVzdWx0ID0gcmVzY3VlX2Z1bmN0aW9uKGUpO1xuICAgICAgICByZXR1cm4gZXhfcmVzdWx0O1xuICAgICAgfSBjYXRjaCAoZXgpIHtcbiAgICAgICAgaWYgKGV4IGluc3RhbmNlb2YgUGF0dGVybnMuTWF0Y2hFcnJvcikge1xuICAgICAgICAgIHRocm93IGV4O1xuICAgICAgICB9XG4gICAgICB9XG4gICAgfVxuXG4gICAgaWYgKGNhdGNoX2Z1bikge1xuICAgICAgdHJ5IHtcbiAgICAgICAgZXhfcmVzdWx0ID0gY2F0Y2hfZnVuKGUpO1xuICAgICAgICByZXR1cm4gZXhfcmVzdWx0O1xuICAgICAgfSBjYXRjaCAoZXgpIHtcbiAgICAgICAgaWYgKGV4IGluc3RhbmNlb2YgUGF0dGVybnMuTWF0Y2hFcnJvcikge1xuICAgICAgICAgIHRocm93IGV4O1xuICAgICAgICB9XG4gICAgICB9XG4gICAgfVxuXG4gICAgdGhyb3cgZTtcbiAgfSBmaW5hbGx5IHtcbiAgICBpZiAoYWZ0ZXJfZnVuY3Rpb24pIHtcbiAgICAgIGFmdGVyX2Z1bmN0aW9uKCk7XG4gICAgfVxuICB9XG5cbiAgaWYgKGVsc2VfZnVuY3Rpb24pIHtcbiAgICB0cnkge1xuICAgICAgcmV0dXJuIGVsc2VfZnVuY3Rpb24ocmVzdWx0KTtcbiAgICB9IGNhdGNoIChleCkge1xuICAgICAgaWYgKGV4IGluc3RhbmNlb2YgUGF0dGVybnMuTWF0Y2hFcnJvcikge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ05vIE1hdGNoIEZvdW5kIGluIEVsc2UnKTtcbiAgICAgIH1cblxuICAgICAgdGhyb3cgZXg7XG4gICAgfVxuICB9IGVsc2Uge1xuICAgIHJldHVybiByZXN1bHQ7XG4gIH1cbn1cblxudmFyIFNwZWNpYWxGb3JtcyQxID0ge1xuICBfY2FzZSxcbiAgY29uZCxcbiAgbWFwX3VwZGF0ZSxcbiAgX2ZvcixcbiAgX3RyeVxufTtcblxuRnVuY3Rpb25zLmdldF9nbG9iYWwoKS5wcm9jZXNzZXMgPSBGdW5jdGlvbnMuZ2V0X2dsb2JhbCgpLnByb2Nlc3NlcyB8fCBuZXcgUHJvY2Vzc1N5c3RlbSgpO1xuXG52YXIgQ29yZSQxID0ge1xuICBQcm9jZXNzU3lzdGVtLFxuICBUdXBsZSxcbiAgUElELFxuICBCaXRTdHJpbmcsXG4gIFBhdHRlcm5zLFxuICBJbnRlZ2VyLFxuICBGbG9hdCxcbiAgRnVuY3Rpb25zLFxuICBTcGVjaWFsRm9ybXM6IFNwZWNpYWxGb3JtcyQxXG59O1xuXG5sZXQgRW51bSA9IHtcblxuICBhbGxfX3FtYXJrX186IGZ1bmN0aW9uIChjb2xsZWN0aW9uLCBmdW4gPSB4ID0+IHgpIHtcbiAgICBmb3IgKGxldCBlbGVtIG9mIGNvbGxlY3Rpb24pIHtcbiAgICAgIGlmICghZnVuKGVsZW0pKSB7XG4gICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICByZXR1cm4gdHJ1ZTtcbiAgfSxcblxuICBhbnlfX3FtYXJrX186IGZ1bmN0aW9uIChjb2xsZWN0aW9uLCBmdW4gPSB4ID0+IHgpIHtcbiAgICBmb3IgKGxldCBlbGVtIG9mIGNvbGxlY3Rpb24pIHtcbiAgICAgIGlmIChmdW4oZWxlbSkpIHtcbiAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICB9XG4gICAgfVxuXG4gICAgcmV0dXJuIGZhbHNlO1xuICB9LFxuXG4gIGF0OiBmdW5jdGlvbiAoY29sbGVjdGlvbiwgbiwgdGhlX2RlZmF1bHQgPSBudWxsKSB7XG4gICAgaWYgKG4gPiB0aGlzLmNvdW50KGNvbGxlY3Rpb24pIHx8IG4gPCAwKSB7XG4gICAgICByZXR1cm4gdGhlX2RlZmF1bHQ7XG4gICAgfVxuXG4gICAgcmV0dXJuIGNvbGxlY3Rpb25bbl07XG4gIH0sXG5cbiAgY29uY2F0OiBmdW5jdGlvbiAoLi4uZW51bWFibGVzKSB7XG4gICAgcmV0dXJuIGVudW1hYmxlc1swXS5jb25jYXQoZW51bWFibGVzWzFdKTtcbiAgfSxcblxuICBjb3VudDogZnVuY3Rpb24gKGNvbGxlY3Rpb24sIGZ1biA9IG51bGwpIHtcbiAgICBpZiAoZnVuID09IG51bGwpIHtcbiAgICAgIHJldHVybiBjb2xsZWN0aW9uLmxlbmd0aDtcbiAgICB9IGVsc2Uge1xuICAgICAgcmV0dXJuIGNvbGxlY3Rpb24uZmlsdGVyKGZ1bikubGVuZ3RoO1xuICAgIH1cbiAgfSxcblxuICBkcm9wOiBmdW5jdGlvbiAoY29sbGVjdGlvbiwgY291bnQpIHtcbiAgICByZXR1cm4gY29sbGVjdGlvbi5zbGljZShjb3VudCk7XG4gIH0sXG5cbiAgZHJvcF93aGlsZTogZnVuY3Rpb24gKGNvbGxlY3Rpb24sIGZ1bikge1xuICAgIGxldCBjb3VudCA9IDA7XG5cbiAgICBmb3IgKGxldCBlbGVtIG9mIGNvbGxlY3Rpb24pIHtcbiAgICAgIGlmIChmdW4oZWxlbSkpIHtcbiAgICAgICAgY291bnQgPSBjb3VudCArIDE7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBicmVhaztcbiAgICAgIH1cbiAgICB9XG5cbiAgICByZXR1cm4gY29sbGVjdGlvbi5zbGljZShjb3VudCk7XG4gIH0sXG5cbiAgZWFjaDogZnVuY3Rpb24gKGNvbGxlY3Rpb24sIGZ1bikge1xuICAgIGZvciAobGV0IGVsZW0gb2YgY29sbGVjdGlvbikge1xuICAgICAgZnVuKGVsZW0pO1xuICAgIH1cbiAgfSxcblxuICBlbXB0eV9fcW1hcmtfXzogZnVuY3Rpb24gKGNvbGxlY3Rpb24pIHtcbiAgICByZXR1cm4gY29sbGVjdGlvbi5sZW5ndGggPT09IDA7XG4gIH0sXG5cbiAgZmV0Y2g6IGZ1bmN0aW9uIChjb2xsZWN0aW9uLCBuKSB7XG4gICAgaWYgKEFycmF5LmlzQXJyYXkoY29sbGVjdGlvbikpIHtcbiAgICAgIGlmIChuIDwgdGhpcy5jb3VudChjb2xsZWN0aW9uKSAmJiBuID49IDApIHtcbiAgICAgICAgcmV0dXJuIG5ldyBDb3JlJDEuVHVwbGUoU3ltYm9sLmZvcihcIm9rXCIpLCBjb2xsZWN0aW9uW25dKTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHJldHVybiBTeW1ib2wuZm9yKFwiZXJyb3JcIik7XG4gICAgICB9XG4gICAgfVxuXG4gICAgdGhyb3cgbmV3IEVycm9yKFwiY29sbGVjdGlvbiBpcyBub3QgYW4gRW51bWVyYWJsZVwiKTtcbiAgfSxcblxuICBmZXRjaF9fZW1hcmtfXzogZnVuY3Rpb24gKGNvbGxlY3Rpb24sIG4pIHtcbiAgICBpZiAoQXJyYXkuaXNBcnJheShjb2xsZWN0aW9uKSkge1xuICAgICAgaWYgKG4gPCB0aGlzLmNvdW50KGNvbGxlY3Rpb24pICYmIG4gPj0gMCkge1xuICAgICAgICByZXR1cm4gY29sbGVjdGlvbltuXTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcihcIm91dCBvZiBib3VuZHMgZXJyb3JcIik7XG4gICAgICB9XG4gICAgfVxuXG4gICAgdGhyb3cgbmV3IEVycm9yKFwiY29sbGVjdGlvbiBpcyBub3QgYW4gRW51bWVyYWJsZVwiKTtcbiAgfSxcblxuICBmaWx0ZXI6IGZ1bmN0aW9uIChjb2xsZWN0aW9uLCBmdW4pIHtcbiAgICBsZXQgcmVzdWx0ID0gW107XG5cbiAgICBmb3IgKGxldCBlbGVtIG9mIGNvbGxlY3Rpb24pIHtcbiAgICAgIGlmIChmdW4oZWxlbSkpIHtcbiAgICAgICAgcmVzdWx0LnB1c2goZWxlbSk7XG4gICAgICB9XG4gICAgfVxuXG4gICAgcmV0dXJuIHJlc3VsdDtcbiAgfSxcblxuICBmaWx0ZXJfbWFwOiBmdW5jdGlvbiAoY29sbGVjdGlvbiwgZmlsdGVyLCBtYXBwZXIpIHtcbiAgICByZXR1cm4gRW51bS5tYXAoRW51bS5maWx0ZXIoY29sbGVjdGlvbiwgZmlsdGVyKSwgbWFwcGVyKTtcbiAgfSxcblxuICBmaW5kOiBmdW5jdGlvbiAoY29sbGVjdGlvbiwgaWZfbm9uZSA9IG51bGwsIGZ1bikge1xuICAgIGZvciAobGV0IGVsZW0gb2YgY29sbGVjdGlvbikge1xuICAgICAgaWYgKGZ1bihlbGVtKSkge1xuICAgICAgICByZXR1cm4gZWxlbTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICByZXR1cm4gaWZfbm9uZTtcbiAgfSxcblxuICBpbnRvOiBmdW5jdGlvbiAoY29sbGVjdGlvbiwgbGlzdCkge1xuICAgIHJldHVybiBsaXN0LmNvbmNhdChjb2xsZWN0aW9uKTtcbiAgfSxcblxuICBtYXA6IGZ1bmN0aW9uIChjb2xsZWN0aW9uLCBmdW4pIHtcbiAgICBsZXQgcmVzdWx0ID0gW107XG5cbiAgICBmb3IgKGxldCBlbGVtIG9mIGNvbGxlY3Rpb24pIHtcbiAgICAgIHJlc3VsdC5wdXNoKGZ1bihlbGVtKSk7XG4gICAgfVxuXG4gICAgcmV0dXJuIHJlc3VsdDtcbiAgfSxcblxuICBtYXBfcmVkdWNlOiBmdW5jdGlvbiAoY29sbGVjdGlvbiwgYWNjLCBmdW4pIHtcbiAgICBsZXQgbWFwcGVkID0gT2JqZWN0LmZyZWV6ZShbXSk7XG4gICAgbGV0IHRoZV9hY2MgPSBhY2M7XG5cbiAgICBmb3IgKHZhciBpID0gMDsgaSA8IHRoaXMuY291bnQoY29sbGVjdGlvbik7IGkrKykge1xuICAgICAgbGV0IHR1cGxlID0gZnVuKGNvbGxlY3Rpb25baV0sIHRoZV9hY2MpO1xuXG4gICAgICB0aGVfYWNjID0gdHVwbGUuZ2V0KDEpO1xuICAgICAgbWFwcGVkID0gT2JqZWN0LmZyZWV6ZShtYXBwZWQuY29uY2F0KFt0dXBsZS5nZXQoMCldKSk7XG4gICAgfVxuXG4gICAgcmV0dXJuIG5ldyBDb3JlJDEuVHVwbGUobWFwcGVkLCB0aGVfYWNjKTtcbiAgfSxcblxuICBtZW1iZXJfX3FtYXJrX186IGZ1bmN0aW9uIChjb2xsZWN0aW9uLCB2YWx1ZSkge1xuICAgIHJldHVybiBjb2xsZWN0aW9uLmluY2x1ZGVzKHZhbHVlKTtcbiAgfSxcblxuICByZWR1Y2U6IGZ1bmN0aW9uIChjb2xsZWN0aW9uLCBhY2MsIGZ1bikge1xuICAgIGxldCB0aGVfYWNjID0gYWNjO1xuXG4gICAgZm9yICh2YXIgaSA9IDA7IGkgPCB0aGlzLmNvdW50KGNvbGxlY3Rpb24pOyBpKyspIHtcbiAgICAgIGxldCB0dXBsZSA9IGZ1bihjb2xsZWN0aW9uW2ldLCB0aGVfYWNjKTtcblxuICAgICAgdGhlX2FjYyA9IHR1cGxlLmdldCgxKTtcbiAgICB9XG5cbiAgICByZXR1cm4gdGhlX2FjYztcbiAgfSxcblxuICB0YWtlOiBmdW5jdGlvbiAoY29sbGVjdGlvbiwgY291bnQpIHtcbiAgICByZXR1cm4gY29sbGVjdGlvbi5zbGljZSgwLCBjb3VudCk7XG4gIH0sXG5cbiAgdGFrZV9ldmVyeTogZnVuY3Rpb24gKGNvbGxlY3Rpb24sIG50aCkge1xuICAgIGxldCByZXN1bHQgPSBbXTtcbiAgICBsZXQgaW5kZXggPSAwO1xuXG4gICAgZm9yIChsZXQgZWxlbSBvZiBjb2xsZWN0aW9uKSB7XG4gICAgICBpZiAoaW5kZXggJSBudGggPT09IDApIHtcbiAgICAgICAgcmVzdWx0LnB1c2goZWxlbSk7XG4gICAgICB9XG4gICAgfVxuXG4gICAgcmV0dXJuIE9iamVjdC5mcmVlemUocmVzdWx0KTtcbiAgfSxcblxuICB0YWtlX3doaWxlOiBmdW5jdGlvbiAoY29sbGVjdGlvbiwgZnVuKSB7XG4gICAgbGV0IGNvdW50ID0gMDtcblxuICAgIGZvciAobGV0IGVsZW0gb2YgY29sbGVjdGlvbikge1xuICAgICAgaWYgKGZ1bihlbGVtKSkge1xuICAgICAgICBjb3VudCA9IGNvdW50ICsgMTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIGJyZWFrO1xuICAgICAgfVxuICAgIH1cblxuICAgIHJldHVybiBjb2xsZWN0aW9uLnNsaWNlKDAsIGNvdW50KTtcbiAgfSxcblxuICB0b19saXN0OiBmdW5jdGlvbiAoY29sbGVjdGlvbikge1xuICAgIHJldHVybiBjb2xsZWN0aW9uO1xuICB9XG59O1xuXG52YXIgRWxpeGlyID0ge1xuICBDb3JlOiBDb3JlJDEsXG4gIEVudW0sXG4gIFZpcnR1YWxET01cbn07XG5cbmV4cG9ydCBkZWZhdWx0IEVsaXhpcjsiXSwiZmlsZSI6IkVsaXhpci5qcyIsInNvdXJjZVJvb3QiOiIvc291cmNlLyJ9 \ No newline at end of file +//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiIiwic291cmNlcyI6WyJFbGl4aXIuanMiXSwic291cmNlc0NvbnRlbnQiOlsibGV0IFZpcnR1YWxET00gPSAoZnVuY3Rpb24gKGUpIHtcbiAgICByZXR1cm4gZSgpO1xufSkoZnVuY3Rpb24gKCkge1xuICAgIHZhciBkZWZpbmUsIG1vZHVsZSwgZXhwb3J0cztcbiAgICByZXR1cm4gKGZ1bmN0aW9uIGUodCwgbiwgcikge1xuICAgICAgICBmdW5jdGlvbiBzKG8sIHUpIHtcbiAgICAgICAgICAgIGlmICghbltvXSkge1xuICAgICAgICAgICAgICAgIGlmICghdFtvXSkge1xuICAgICAgICAgICAgICAgICAgICB2YXIgYSA9IHR5cGVvZiByZXF1aXJlID09IFwiZnVuY3Rpb25cIiAmJiByZXF1aXJlO1xuICAgICAgICAgICAgICAgICAgICBpZiAoIXUgJiYgYSkgcmV0dXJuIGEobywgITApO1xuICAgICAgICAgICAgICAgICAgICBpZiAoaSkgcmV0dXJuIGkobywgITApO1xuICAgICAgICAgICAgICAgICAgICB2YXIgZiA9IG5ldyBFcnJvcihcIkNhbm5vdCBmaW5kIG1vZHVsZSAnXCIgKyBvICsgXCInXCIpO1xuICAgICAgICAgICAgICAgICAgICB0aHJvdyAoZi5jb2RlID0gXCJNT0RVTEVfTk9UX0ZPVU5EXCIsIGYpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB2YXIgbCA9IG5bb10gPSB7XG4gICAgICAgICAgICAgICAgICAgIGV4cG9ydHM6IHt9XG4gICAgICAgICAgICAgICAgfTtcbiAgICAgICAgICAgICAgICB0W29dWzBdLmNhbGwobC5leHBvcnRzLCBmdW5jdGlvbiAoZSkge1xuICAgICAgICAgICAgICAgICAgICB2YXIgbiA9IHRbb11bMV1bZV07XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBzKG4gPyBuIDogZSk7XG4gICAgICAgICAgICAgICAgfSwgbCwgbC5leHBvcnRzLCBlLCB0LCBuLCByKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJldHVybiBuW29dLmV4cG9ydHM7XG4gICAgICAgIH1cbiAgICAgICAgdmFyIGkgPSB0eXBlb2YgcmVxdWlyZSA9PSBcImZ1bmN0aW9uXCIgJiYgcmVxdWlyZTtcbiAgICAgICAgZm9yICh2YXIgbyA9IDA7IG8gPCByLmxlbmd0aDsgbysrKSBzKHJbb10pO1xuICAgICAgICByZXR1cm4gcztcbiAgICB9KSh7XG4gICAgICAgIDE6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG5cbiAgICAgICAgICAgIHZhciBjcmVhdGVFbGVtZW50ID0gcmVxdWlyZShcIi4vdmRvbS9jcmVhdGUtZWxlbWVudC5qc1wiKTtcblxuICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBjcmVhdGVFbGVtZW50O1xuICAgICAgICB9LCB7IFwiLi92ZG9tL2NyZWF0ZS1lbGVtZW50LmpzXCI6IDE1IH1dLCAyOiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge1xuICAgICAgICAgICAgdmFyIGRpZmYgPSByZXF1aXJlKFwiLi92dHJlZS9kaWZmLmpzXCIpO1xuXG4gICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IGRpZmY7XG4gICAgICAgIH0sIHsgXCIuL3Z0cmVlL2RpZmYuanNcIjogMzUgfV0sIDM6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICB2YXIgaCA9IHJlcXVpcmUoXCIuL3ZpcnR1YWwtaHlwZXJzY3JpcHQvaW5kZXguanNcIik7XG5cbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gaDtcbiAgICAgICAgfSwgeyBcIi4vdmlydHVhbC1oeXBlcnNjcmlwdC9pbmRleC5qc1wiOiAyMiB9XSwgNDogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHtcbiAgICAgICAgICAgIHZhciBkaWZmID0gcmVxdWlyZShcIi4vZGlmZi5qc1wiKTtcbiAgICAgICAgICAgIHZhciBwYXRjaCA9IHJlcXVpcmUoXCIuL3BhdGNoLmpzXCIpO1xuICAgICAgICAgICAgdmFyIGggPSByZXF1aXJlKFwiLi9oLmpzXCIpO1xuICAgICAgICAgICAgdmFyIGNyZWF0ZSA9IHJlcXVpcmUoXCIuL2NyZWF0ZS1lbGVtZW50LmpzXCIpO1xuICAgICAgICAgICAgdmFyIFZOb2RlID0gcmVxdWlyZShcIi4vdm5vZGUvdm5vZGUuanNcIik7XG4gICAgICAgICAgICB2YXIgVlRleHQgPSByZXF1aXJlKFwiLi92bm9kZS92dGV4dC5qc1wiKTtcblxuICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSB7XG4gICAgICAgICAgICAgICAgZGlmZjogZGlmZixcbiAgICAgICAgICAgICAgICBwYXRjaDogcGF0Y2gsXG4gICAgICAgICAgICAgICAgaDogaCxcbiAgICAgICAgICAgICAgICBjcmVhdGU6IGNyZWF0ZSxcbiAgICAgICAgICAgICAgICBWTm9kZTogVk5vZGUsXG4gICAgICAgICAgICAgICAgVlRleHQ6IFZUZXh0XG4gICAgICAgICAgICB9O1xuICAgICAgICB9LCB7IFwiLi9jcmVhdGUtZWxlbWVudC5qc1wiOiAxLCBcIi4vZGlmZi5qc1wiOiAyLCBcIi4vaC5qc1wiOiAzLCBcIi4vcGF0Y2guanNcIjogMTMsIFwiLi92bm9kZS92bm9kZS5qc1wiOiAzMSwgXCIuL3Zub2RlL3Z0ZXh0LmpzXCI6IDMzIH1dLCA1OiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge1xuICAgICAgICAgICAgLyohXG4gICAgICAgICAgICAgKiBDcm9zcy1Ccm93c2VyIFNwbGl0IDEuMS4xXG4gICAgICAgICAgICAgKiBDb3B5cmlnaHQgMjAwNy0yMDEyIFN0ZXZlbiBMZXZpdGhhbiA8c3RldmVubGV2aXRoYW4uY29tPlxuICAgICAgICAgICAgICogQXZhaWxhYmxlIHVuZGVyIHRoZSBNSVQgTGljZW5zZVxuICAgICAgICAgICAgICogRUNNQVNjcmlwdCBjb21wbGlhbnQsIHVuaWZvcm0gY3Jvc3MtYnJvd3NlciBzcGxpdCBtZXRob2RcbiAgICAgICAgICAgICAqL1xuXG4gICAgICAgICAgICAvKipcbiAgICAgICAgICAgICAqIFNwbGl0cyBhIHN0cmluZyBpbnRvIGFuIGFycmF5IG9mIHN0cmluZ3MgdXNpbmcgYSByZWdleCBvciBzdHJpbmcgc2VwYXJhdG9yLiBNYXRjaGVzIG9mIHRoZVxuICAgICAgICAgICAgICogc2VwYXJhdG9yIGFyZSBub3QgaW5jbHVkZWQgaW4gdGhlIHJlc3VsdCBhcnJheS4gSG93ZXZlciwgaWYgYHNlcGFyYXRvcmAgaXMgYSByZWdleCB0aGF0IGNvbnRhaW5zXG4gICAgICAgICAgICAgKiBjYXB0dXJpbmcgZ3JvdXBzLCBiYWNrcmVmZXJlbmNlcyBhcmUgc3BsaWNlZCBpbnRvIHRoZSByZXN1bHQgZWFjaCB0aW1lIGBzZXBhcmF0b3JgIGlzIG1hdGNoZWQuXG4gICAgICAgICAgICAgKiBGaXhlcyBicm93c2VyIGJ1Z3MgY29tcGFyZWQgdG8gdGhlIG5hdGl2ZSBgU3RyaW5nLnByb3RvdHlwZS5zcGxpdGAgYW5kIGNhbiBiZSB1c2VkIHJlbGlhYmx5XG4gICAgICAgICAgICAgKiBjcm9zcy1icm93c2VyLlxuICAgICAgICAgICAgICogQHBhcmFtIHtTdHJpbmd9IHN0ciBTdHJpbmcgdG8gc3BsaXQuXG4gICAgICAgICAgICAgKiBAcGFyYW0ge1JlZ0V4cHxTdHJpbmd9IHNlcGFyYXRvciBSZWdleCBvciBzdHJpbmcgdG8gdXNlIGZvciBzZXBhcmF0aW5nIHRoZSBzdHJpbmcuXG4gICAgICAgICAgICAgKiBAcGFyYW0ge051bWJlcn0gW2xpbWl0XSBNYXhpbXVtIG51bWJlciBvZiBpdGVtcyB0byBpbmNsdWRlIGluIHRoZSByZXN1bHQgYXJyYXkuXG4gICAgICAgICAgICAgKiBAcmV0dXJucyB7QXJyYXl9IEFycmF5IG9mIHN1YnN0cmluZ3MuXG4gICAgICAgICAgICAgKiBAZXhhbXBsZVxuICAgICAgICAgICAgICpcbiAgICAgICAgICAgICAqIC8vIEJhc2ljIHVzZVxuICAgICAgICAgICAgICogc3BsaXQoJ2EgYiBjIGQnLCAnICcpO1xuICAgICAgICAgICAgICogLy8gLT4gWydhJywgJ2InLCAnYycsICdkJ11cbiAgICAgICAgICAgICAqXG4gICAgICAgICAgICAgKiAvLyBXaXRoIGxpbWl0XG4gICAgICAgICAgICAgKiBzcGxpdCgnYSBiIGMgZCcsICcgJywgMik7XG4gICAgICAgICAgICAgKiAvLyAtPiBbJ2EnLCAnYiddXG4gICAgICAgICAgICAgKlxuICAgICAgICAgICAgICogLy8gQmFja3JlZmVyZW5jZXMgaW4gcmVzdWx0IGFycmF5XG4gICAgICAgICAgICAgKiBzcGxpdCgnLi53b3JkMSB3b3JkMi4uJywgLyhbYS16XSspKFxcZCspL2kpO1xuICAgICAgICAgICAgICogLy8gLT4gWycuLicsICd3b3JkJywgJzEnLCAnICcsICd3b3JkJywgJzInLCAnLi4nXVxuICAgICAgICAgICAgICovXG4gICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IChmdW5jdGlvbiBzcGxpdCh1bmRlZikge1xuXG4gICAgICAgICAgICAgICAgdmFyIG5hdGl2ZVNwbGl0ID0gU3RyaW5nLnByb3RvdHlwZS5zcGxpdCxcbiAgICAgICAgICAgICAgICAgICAgY29tcGxpYW50RXhlY05wY2cgPSAvKCk/Py8uZXhlYyhcIlwiKVsxXSA9PT0gdW5kZWYsXG5cbiAgICAgICAgICAgICAgICAvLyBOUENHOiBub25wYXJ0aWNpcGF0aW5nIGNhcHR1cmluZyBncm91cFxuICAgICAgICAgICAgICAgIHNlbGY7XG5cbiAgICAgICAgICAgICAgICBzZWxmID0gZnVuY3Rpb24gKHN0ciwgc2VwYXJhdG9yLCBsaW1pdCkge1xuICAgICAgICAgICAgICAgICAgICAvLyBJZiBgc2VwYXJhdG9yYCBpcyBub3QgYSByZWdleCwgdXNlIGBuYXRpdmVTcGxpdGBcbiAgICAgICAgICAgICAgICAgICAgaWYgKE9iamVjdC5wcm90b3R5cGUudG9TdHJpbmcuY2FsbChzZXBhcmF0b3IpICE9PSBcIltvYmplY3QgUmVnRXhwXVwiKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gbmF0aXZlU3BsaXQuY2FsbChzdHIsIHNlcGFyYXRvciwgbGltaXQpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIHZhciBvdXRwdXQgPSBbXSxcbiAgICAgICAgICAgICAgICAgICAgICAgIGZsYWdzID0gKHNlcGFyYXRvci5pZ25vcmVDYXNlID8gXCJpXCIgOiBcIlwiKSArIChzZXBhcmF0b3IubXVsdGlsaW5lID8gXCJtXCIgOiBcIlwiKSArIChzZXBhcmF0b3IuZXh0ZW5kZWQgPyBcInhcIiA6IFwiXCIpICsgKHNlcGFyYXRvci5zdGlja3kgPyBcInlcIiA6IFwiXCIpLFxuXG4gICAgICAgICAgICAgICAgICAgIC8vIEZpcmVmb3ggMytcbiAgICAgICAgICAgICAgICAgICAgbGFzdExhc3RJbmRleCA9IDAsXG5cbiAgICAgICAgICAgICAgICAgICAgLy8gTWFrZSBgZ2xvYmFsYCBhbmQgYXZvaWQgYGxhc3RJbmRleGAgaXNzdWVzIGJ5IHdvcmtpbmcgd2l0aCBhIGNvcHlcbiAgICAgICAgICAgICAgICAgICAgc2VwYXJhdG9yID0gbmV3IFJlZ0V4cChzZXBhcmF0b3Iuc291cmNlLCBmbGFncyArIFwiZ1wiKSxcbiAgICAgICAgICAgICAgICAgICAgICAgIHNlcGFyYXRvcjIsXG4gICAgICAgICAgICAgICAgICAgICAgICBtYXRjaCxcbiAgICAgICAgICAgICAgICAgICAgICAgIGxhc3RJbmRleCxcbiAgICAgICAgICAgICAgICAgICAgICAgIGxhc3RMZW5ndGg7XG4gICAgICAgICAgICAgICAgICAgIHN0ciArPSBcIlwiOyAvLyBUeXBlLWNvbnZlcnRcbiAgICAgICAgICAgICAgICAgICAgaWYgKCFjb21wbGlhbnRFeGVjTnBjZykge1xuICAgICAgICAgICAgICAgICAgICAgICAgLy8gRG9lc24ndCBuZWVkIGZsYWdzIGd5LCBidXQgdGhleSBkb24ndCBodXJ0XG4gICAgICAgICAgICAgICAgICAgICAgICBzZXBhcmF0b3IyID0gbmV3IFJlZ0V4cChcIl5cIiArIHNlcGFyYXRvci5zb3VyY2UgKyBcIiQoPyFcXFxccylcIiwgZmxhZ3MpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIC8qIFZhbHVlcyBmb3IgYGxpbWl0YCwgcGVyIHRoZSBzcGVjOlxuICAgICAgICAgICAgICAgICAgICAgKiBJZiB1bmRlZmluZWQ6IDQyOTQ5NjcyOTUgLy8gTWF0aC5wb3coMiwgMzIpIC0gMVxuICAgICAgICAgICAgICAgICAgICAgKiBJZiAwLCBJbmZpbml0eSwgb3IgTmFOOiAwXG4gICAgICAgICAgICAgICAgICAgICAqIElmIHBvc2l0aXZlIG51bWJlcjogbGltaXQgPSBNYXRoLmZsb29yKGxpbWl0KTsgaWYgKGxpbWl0ID4gNDI5NDk2NzI5NSkgbGltaXQgLT0gNDI5NDk2NzI5NjtcbiAgICAgICAgICAgICAgICAgICAgICogSWYgbmVnYXRpdmUgbnVtYmVyOiA0Mjk0OTY3Mjk2IC0gTWF0aC5mbG9vcihNYXRoLmFicyhsaW1pdCkpXG4gICAgICAgICAgICAgICAgICAgICAqIElmIG90aGVyOiBUeXBlLWNvbnZlcnQsIHRoZW4gdXNlIHRoZSBhYm92ZSBydWxlc1xuICAgICAgICAgICAgICAgICAgICAgKi9cbiAgICAgICAgICAgICAgICAgICAgbGltaXQgPSBsaW1pdCA9PT0gdW5kZWYgPyAtMSA+Pj4gMCA6IC8vIE1hdGgucG93KDIsIDMyKSAtIDFcbiAgICAgICAgICAgICAgICAgICAgbGltaXQgPj4+IDA7IC8vIFRvVWludDMyKGxpbWl0KVxuICAgICAgICAgICAgICAgICAgICB3aGlsZSAobWF0Y2ggPSBzZXBhcmF0b3IuZXhlYyhzdHIpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAvLyBgc2VwYXJhdG9yLmxhc3RJbmRleGAgaXMgbm90IHJlbGlhYmxlIGNyb3NzLWJyb3dzZXJcbiAgICAgICAgICAgICAgICAgICAgICAgIGxhc3RJbmRleCA9IG1hdGNoLmluZGV4ICsgbWF0Y2hbMF0ubGVuZ3RoO1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGxhc3RJbmRleCA+IGxhc3RMYXN0SW5kZXgpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBvdXRwdXQucHVzaChzdHIuc2xpY2UobGFzdExhc3RJbmRleCwgbWF0Y2guaW5kZXgpKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBGaXggYnJvd3NlcnMgd2hvc2UgYGV4ZWNgIG1ldGhvZHMgZG9uJ3QgY29uc2lzdGVudGx5IHJldHVybiBgdW5kZWZpbmVkYCBmb3JcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBub25wYXJ0aWNpcGF0aW5nIGNhcHR1cmluZyBncm91cHNcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoIWNvbXBsaWFudEV4ZWNOcGNnICYmIG1hdGNoLmxlbmd0aCA+IDEpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbWF0Y2hbMF0ucmVwbGFjZShzZXBhcmF0b3IyLCBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBmb3IgKHZhciBpID0gMTsgaSA8IGFyZ3VtZW50cy5sZW5ndGggLSAyOyBpKyspIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoYXJndW1lbnRzW2ldID09PSB1bmRlZikge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBtYXRjaFtpXSA9IHVuZGVmO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChtYXRjaC5sZW5ndGggPiAxICYmIG1hdGNoLmluZGV4IDwgc3RyLmxlbmd0aCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBBcnJheS5wcm90b3R5cGUucHVzaC5hcHBseShvdXRwdXQsIG1hdGNoLnNsaWNlKDEpKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgbGFzdExlbmd0aCA9IG1hdGNoWzBdLmxlbmd0aDtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBsYXN0TGFzdEluZGV4ID0gbGFzdEluZGV4O1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChvdXRwdXQubGVuZ3RoID49IGxpbWl0KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChzZXBhcmF0b3IubGFzdEluZGV4ID09PSBtYXRjaC5pbmRleCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNlcGFyYXRvci5sYXN0SW5kZXgrKzsgLy8gQXZvaWQgYW4gaW5maW5pdGUgbG9vcFxuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIGlmIChsYXN0TGFzdEluZGV4ID09PSBzdHIubGVuZ3RoKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAobGFzdExlbmd0aCB8fCAhc2VwYXJhdG9yLnRlc3QoXCJcIikpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBvdXRwdXQucHVzaChcIlwiKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIG91dHB1dC5wdXNoKHN0ci5zbGljZShsYXN0TGFzdEluZGV4KSk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIG91dHB1dC5sZW5ndGggPiBsaW1pdCA/IG91dHB1dC5zbGljZSgwLCBsaW1pdCkgOiBvdXRwdXQ7XG4gICAgICAgICAgICAgICAgfTtcblxuICAgICAgICAgICAgICAgIHJldHVybiBzZWxmO1xuICAgICAgICAgICAgfSkoKTtcbiAgICAgICAgfSwge31dLCA2OiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge30sIHt9XSwgNzogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHtcbiAgICAgICAgICAgIFwidXNlIHN0cmljdFwiO1xuXG4gICAgICAgICAgICB2YXIgT25lVmVyc2lvbkNvbnN0cmFpbnQgPSByZXF1aXJlKFwiaW5kaXZpZHVhbC9vbmUtdmVyc2lvblwiKTtcblxuICAgICAgICAgICAgdmFyIE1ZX1ZFUlNJT04gPSBcIjdcIjtcbiAgICAgICAgICAgIE9uZVZlcnNpb25Db25zdHJhaW50KFwiZXYtc3RvcmVcIiwgTVlfVkVSU0lPTik7XG5cbiAgICAgICAgICAgIHZhciBoYXNoS2V5ID0gXCJfX0VWX1NUT1JFX0tFWUBcIiArIE1ZX1ZFUlNJT047XG5cbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gRXZTdG9yZTtcblxuICAgICAgICAgICAgZnVuY3Rpb24gRXZTdG9yZShlbGVtKSB7XG4gICAgICAgICAgICAgICAgdmFyIGhhc2ggPSBlbGVtW2hhc2hLZXldO1xuXG4gICAgICAgICAgICAgICAgaWYgKCFoYXNoKSB7XG4gICAgICAgICAgICAgICAgICAgIGhhc2ggPSBlbGVtW2hhc2hLZXldID0ge307XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgcmV0dXJuIGhhc2g7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0sIHsgXCJpbmRpdmlkdWFsL29uZS12ZXJzaW9uXCI6IDkgfV0sIDg6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICAoZnVuY3Rpb24gKGdsb2JhbCkge1xuICAgICAgICAgICAgICAgIFwidXNlIHN0cmljdFwiO1xuXG4gICAgICAgICAgICAgICAgLypnbG9iYWwgd2luZG93LCBnbG9iYWwqL1xuXG4gICAgICAgICAgICAgICAgdmFyIHJvb3QgPSB0eXBlb2Ygd2luZG93ICE9PSBcInVuZGVmaW5lZFwiID8gd2luZG93IDogdHlwZW9mIGdsb2JhbCAhPT0gXCJ1bmRlZmluZWRcIiA/IGdsb2JhbCA6IHt9O1xuXG4gICAgICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBJbmRpdmlkdWFsO1xuXG4gICAgICAgICAgICAgICAgZnVuY3Rpb24gSW5kaXZpZHVhbChrZXksIHZhbHVlKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmIChrZXkgaW4gcm9vdCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHJvb3Rba2V5XTtcbiAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgIHJvb3Rba2V5XSA9IHZhbHVlO1xuXG4gICAgICAgICAgICAgICAgICAgIHJldHVybiB2YWx1ZTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9KS5jYWxsKHRoaXMsIHR5cGVvZiBnbG9iYWwgIT09IFwidW5kZWZpbmVkXCIgPyBnbG9iYWwgOiB0eXBlb2Ygc2VsZiAhPT0gXCJ1bmRlZmluZWRcIiA/IHNlbGYgOiB0eXBlb2Ygd2luZG93ICE9PSBcInVuZGVmaW5lZFwiID8gd2luZG93IDoge30pO1xuICAgICAgICB9LCB7fV0sIDk6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICBcInVzZSBzdHJpY3RcIjtcblxuICAgICAgICAgICAgdmFyIEluZGl2aWR1YWwgPSByZXF1aXJlKFwiLi9pbmRleC5qc1wiKTtcblxuICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBPbmVWZXJzaW9uO1xuXG4gICAgICAgICAgICBmdW5jdGlvbiBPbmVWZXJzaW9uKG1vZHVsZU5hbWUsIHZlcnNpb24sIGRlZmF1bHRWYWx1ZSkge1xuICAgICAgICAgICAgICAgIHZhciBrZXkgPSBcIl9fSU5ESVZJRFVBTF9PTkVfVkVSU0lPTl9cIiArIG1vZHVsZU5hbWU7XG4gICAgICAgICAgICAgICAgdmFyIGVuZm9yY2VLZXkgPSBrZXkgKyBcIl9FTkZPUkNFX1NJTkdMRVRPTlwiO1xuXG4gICAgICAgICAgICAgICAgdmFyIHZlcnNpb25WYWx1ZSA9IEluZGl2aWR1YWwoZW5mb3JjZUtleSwgdmVyc2lvbik7XG5cbiAgICAgICAgICAgICAgICBpZiAodmVyc2lvblZhbHVlICE9PSB2ZXJzaW9uKSB7XG4gICAgICAgICAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcihcIkNhbiBvbmx5IGhhdmUgb25lIGNvcHkgb2YgXCIgKyBtb2R1bGVOYW1lICsgXCIuXFxuXCIgKyBcIllvdSBhbHJlYWR5IGhhdmUgdmVyc2lvbiBcIiArIHZlcnNpb25WYWx1ZSArIFwiIGluc3RhbGxlZC5cXG5cIiArIFwiVGhpcyBtZWFucyB5b3UgY2Fubm90IGluc3RhbGwgdmVyc2lvbiBcIiArIHZlcnNpb24pO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHJldHVybiBJbmRpdmlkdWFsKGtleSwgZGVmYXVsdFZhbHVlKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSwgeyBcIi4vaW5kZXguanNcIjogOCB9XSwgMTA6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICAoZnVuY3Rpb24gKGdsb2JhbCkge1xuICAgICAgICAgICAgICAgIHZhciB0b3BMZXZlbCA9IHR5cGVvZiBnbG9iYWwgIT09IFwidW5kZWZpbmVkXCIgPyBnbG9iYWwgOiB0eXBlb2Ygd2luZG93ICE9PSBcInVuZGVmaW5lZFwiID8gd2luZG93IDoge307XG4gICAgICAgICAgICAgICAgdmFyIG1pbkRvYyA9IHJlcXVpcmUoXCJtaW4tZG9jdW1lbnRcIik7XG5cbiAgICAgICAgICAgICAgICBpZiAodHlwZW9mIGRvY3VtZW50ICE9PSBcInVuZGVmaW5lZFwiKSB7XG4gICAgICAgICAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gZG9jdW1lbnQ7XG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgdmFyIGRvY2N5ID0gdG9wTGV2ZWxbXCJfX0dMT0JBTF9ET0NVTUVOVF9DQUNIRUA0XCJdO1xuXG4gICAgICAgICAgICAgICAgICAgIGlmICghZG9jY3kpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGRvY2N5ID0gdG9wTGV2ZWxbXCJfX0dMT0JBTF9ET0NVTUVOVF9DQUNIRUA0XCJdID0gbWluRG9jO1xuICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBkb2NjeTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9KS5jYWxsKHRoaXMsIHR5cGVvZiBnbG9iYWwgIT09IFwidW5kZWZpbmVkXCIgPyBnbG9iYWwgOiB0eXBlb2Ygc2VsZiAhPT0gXCJ1bmRlZmluZWRcIiA/IHNlbGYgOiB0eXBlb2Ygd2luZG93ICE9PSBcInVuZGVmaW5lZFwiID8gd2luZG93IDoge30pO1xuICAgICAgICB9LCB7IFwibWluLWRvY3VtZW50XCI6IDYgfV0sIDExOiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge1xuICAgICAgICAgICAgXCJ1c2Ugc3RyaWN0XCI7XG5cbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gaXNPYmplY3QoeCkge1xuICAgICAgICAgICAgICAgIHJldHVybiB0eXBlb2YgeCA9PT0gXCJvYmplY3RcIiAmJiB4ICE9PSBudWxsO1xuICAgICAgICAgICAgfTtcbiAgICAgICAgfSwge31dLCAxMjogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHtcbiAgICAgICAgICAgIHZhciBuYXRpdmVJc0FycmF5ID0gQXJyYXkuaXNBcnJheTtcbiAgICAgICAgICAgIHZhciB0b1N0cmluZyA9IE9iamVjdC5wcm90b3R5cGUudG9TdHJpbmc7XG5cbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gbmF0aXZlSXNBcnJheSB8fCBpc0FycmF5O1xuXG4gICAgICAgICAgICBmdW5jdGlvbiBpc0FycmF5KG9iaikge1xuICAgICAgICAgICAgICAgIHJldHVybiB0b1N0cmluZy5jYWxsKG9iaikgPT09IFwiW29iamVjdCBBcnJheV1cIjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSwge31dLCAxMzogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHtcbiAgICAgICAgICAgIHZhciBwYXRjaCA9IHJlcXVpcmUoXCIuL3Zkb20vcGF0Y2guanNcIik7XG5cbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gcGF0Y2g7XG4gICAgICAgIH0sIHsgXCIuL3Zkb20vcGF0Y2guanNcIjogMTggfV0sIDE0OiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge1xuICAgICAgICAgICAgdmFyIGlzT2JqZWN0ID0gcmVxdWlyZShcImlzLW9iamVjdFwiKTtcbiAgICAgICAgICAgIHZhciBpc0hvb2sgPSByZXF1aXJlKFwiLi4vdm5vZGUvaXMtdmhvb2suanNcIik7XG5cbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gYXBwbHlQcm9wZXJ0aWVzO1xuXG4gICAgICAgICAgICBmdW5jdGlvbiBhcHBseVByb3BlcnRpZXMobm9kZSwgcHJvcHMsIHByZXZpb3VzKSB7XG4gICAgICAgICAgICAgICAgZm9yICh2YXIgcHJvcE5hbWUgaW4gcHJvcHMpIHtcbiAgICAgICAgICAgICAgICAgICAgdmFyIHByb3BWYWx1ZSA9IHByb3BzW3Byb3BOYW1lXTtcblxuICAgICAgICAgICAgICAgICAgICBpZiAocHJvcFZhbHVlID09PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJlbW92ZVByb3BlcnR5KG5vZGUsIHByb3BOYW1lLCBwcm9wVmFsdWUsIHByZXZpb3VzKTtcbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIGlmIChpc0hvb2socHJvcFZhbHVlKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgcmVtb3ZlUHJvcGVydHkobm9kZSwgcHJvcE5hbWUsIHByb3BWYWx1ZSwgcHJldmlvdXMpO1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHByb3BWYWx1ZS5ob29rKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcHJvcFZhbHVlLmhvb2sobm9kZSwgcHJvcE5hbWUsIHByZXZpb3VzID8gcHJldmlvdXNbcHJvcE5hbWVdIDogdW5kZWZpbmVkKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChpc09iamVjdChwcm9wVmFsdWUpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcGF0Y2hPYmplY3Qobm9kZSwgcHJvcHMsIHByZXZpb3VzLCBwcm9wTmFtZSwgcHJvcFZhbHVlKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgbm9kZVtwcm9wTmFtZV0gPSBwcm9wVmFsdWU7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIHJlbW92ZVByb3BlcnR5KG5vZGUsIHByb3BOYW1lLCBwcm9wVmFsdWUsIHByZXZpb3VzKSB7XG4gICAgICAgICAgICAgICAgaWYgKHByZXZpb3VzKSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciBwcmV2aW91c1ZhbHVlID0gcHJldmlvdXNbcHJvcE5hbWVdO1xuXG4gICAgICAgICAgICAgICAgICAgIGlmICghaXNIb29rKHByZXZpb3VzVmFsdWUpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAocHJvcE5hbWUgPT09IFwiYXR0cmlidXRlc1wiKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgZm9yICh2YXIgYXR0ck5hbWUgaW4gcHJldmlvdXNWYWx1ZSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBub2RlLnJlbW92ZUF0dHJpYnV0ZShhdHRyTmFtZSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIGlmIChwcm9wTmFtZSA9PT0gXCJzdHlsZVwiKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgZm9yICh2YXIgaSBpbiBwcmV2aW91c1ZhbHVlKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG5vZGUuc3R5bGVbaV0gPSBcIlwiO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAodHlwZW9mIHByZXZpb3VzVmFsdWUgPT09IFwic3RyaW5nXCIpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBub2RlW3Byb3BOYW1lXSA9IFwiXCI7XG4gICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIG5vZGVbcHJvcE5hbWVdID0gbnVsbDtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIGlmIChwcmV2aW91c1ZhbHVlLnVuaG9vaykge1xuICAgICAgICAgICAgICAgICAgICAgICAgcHJldmlvdXNWYWx1ZS51bmhvb2sobm9kZSwgcHJvcE5hbWUsIHByb3BWYWx1ZSk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIHBhdGNoT2JqZWN0KG5vZGUsIHByb3BzLCBwcmV2aW91cywgcHJvcE5hbWUsIHByb3BWYWx1ZSkge1xuICAgICAgICAgICAgICAgIHZhciBwcmV2aW91c1ZhbHVlID0gcHJldmlvdXMgPyBwcmV2aW91c1twcm9wTmFtZV0gOiB1bmRlZmluZWQ7XG5cbiAgICAgICAgICAgICAgICAvLyBTZXQgYXR0cmlidXRlc1xuICAgICAgICAgICAgICAgIGlmIChwcm9wTmFtZSA9PT0gXCJhdHRyaWJ1dGVzXCIpIHtcbiAgICAgICAgICAgICAgICAgICAgZm9yICh2YXIgYXR0ck5hbWUgaW4gcHJvcFZhbHVlKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICB2YXIgYXR0clZhbHVlID0gcHJvcFZhbHVlW2F0dHJOYW1lXTtcblxuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGF0dHJWYWx1ZSA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgbm9kZS5yZW1vdmVBdHRyaWJ1dGUoYXR0ck5hbWUpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBub2RlLnNldEF0dHJpYnV0ZShhdHRyTmFtZSwgYXR0clZhbHVlKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICBpZiAocHJldmlvdXNWYWx1ZSAmJiBpc09iamVjdChwcmV2aW91c1ZhbHVlKSAmJiBnZXRQcm90b3R5cGUocHJldmlvdXNWYWx1ZSkgIT09IGdldFByb3RvdHlwZShwcm9wVmFsdWUpKSB7XG4gICAgICAgICAgICAgICAgICAgIG5vZGVbcHJvcE5hbWVdID0gcHJvcFZhbHVlO1xuICAgICAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgaWYgKCFpc09iamVjdChub2RlW3Byb3BOYW1lXSkpIHtcbiAgICAgICAgICAgICAgICAgICAgbm9kZVtwcm9wTmFtZV0gPSB7fTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICB2YXIgcmVwbGFjZXIgPSBwcm9wTmFtZSA9PT0gXCJzdHlsZVwiID8gXCJcIiA6IHVuZGVmaW5lZDtcblxuICAgICAgICAgICAgICAgIGZvciAodmFyIGsgaW4gcHJvcFZhbHVlKSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciB2YWx1ZSA9IHByb3BWYWx1ZVtrXTtcbiAgICAgICAgICAgICAgICAgICAgbm9kZVtwcm9wTmFtZV1ba10gPSB2YWx1ZSA9PT0gdW5kZWZpbmVkID8gcmVwbGFjZXIgOiB2YWx1ZTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIGdldFByb3RvdHlwZSh2YWx1ZSkge1xuICAgICAgICAgICAgICAgIGlmIChPYmplY3QuZ2V0UHJvdG90eXBlT2YpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIE9iamVjdC5nZXRQcm90b3R5cGVPZih2YWx1ZSk7XG4gICAgICAgICAgICAgICAgfSBlbHNlIGlmICh2YWx1ZS5fX3Byb3RvX18pIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHZhbHVlLl9fcHJvdG9fXztcbiAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKHZhbHVlLmNvbnN0cnVjdG9yKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiB2YWx1ZS5jb25zdHJ1Y3Rvci5wcm90b3R5cGU7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9LCB7IFwiLi4vdm5vZGUvaXMtdmhvb2suanNcIjogMjYsIFwiaXMtb2JqZWN0XCI6IDExIH1dLCAxNTogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHtcbiAgICAgICAgICAgIHZhciBkb2N1bWVudCA9IHJlcXVpcmUoXCJnbG9iYWwvZG9jdW1lbnRcIik7XG5cbiAgICAgICAgICAgIHZhciBhcHBseVByb3BlcnRpZXMgPSByZXF1aXJlKFwiLi9hcHBseS1wcm9wZXJ0aWVzXCIpO1xuXG4gICAgICAgICAgICB2YXIgaXNWTm9kZSA9IHJlcXVpcmUoXCIuLi92bm9kZS9pcy12bm9kZS5qc1wiKTtcbiAgICAgICAgICAgIHZhciBpc1ZUZXh0ID0gcmVxdWlyZShcIi4uL3Zub2RlL2lzLXZ0ZXh0LmpzXCIpO1xuICAgICAgICAgICAgdmFyIGlzV2lkZ2V0ID0gcmVxdWlyZShcIi4uL3Zub2RlL2lzLXdpZGdldC5qc1wiKTtcbiAgICAgICAgICAgIHZhciBoYW5kbGVUaHVuayA9IHJlcXVpcmUoXCIuLi92bm9kZS9oYW5kbGUtdGh1bmsuanNcIik7XG5cbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gY3JlYXRlRWxlbWVudDtcblxuICAgICAgICAgICAgZnVuY3Rpb24gY3JlYXRlRWxlbWVudCh2bm9kZSwgb3B0cykge1xuICAgICAgICAgICAgICAgIHZhciBkb2MgPSBvcHRzID8gb3B0cy5kb2N1bWVudCB8fCBkb2N1bWVudCA6IGRvY3VtZW50O1xuICAgICAgICAgICAgICAgIHZhciB3YXJuID0gb3B0cyA/IG9wdHMud2FybiA6IG51bGw7XG5cbiAgICAgICAgICAgICAgICB2bm9kZSA9IGhhbmRsZVRodW5rKHZub2RlKS5hO1xuXG4gICAgICAgICAgICAgICAgaWYgKGlzV2lkZ2V0KHZub2RlKSkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gdm5vZGUuaW5pdCgpO1xuICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoaXNWVGV4dCh2bm9kZSkpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGRvYy5jcmVhdGVUZXh0Tm9kZSh2bm9kZS50ZXh0KTtcbiAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKCFpc1ZOb2RlKHZub2RlKSkge1xuICAgICAgICAgICAgICAgICAgICBpZiAod2Fybikge1xuICAgICAgICAgICAgICAgICAgICAgICAgd2FybihcIkl0ZW0gaXMgbm90IGEgdmFsaWQgdmlydHVhbCBkb20gbm9kZVwiLCB2bm9kZSk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIG51bGw7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgdmFyIG5vZGUgPSB2bm9kZS5uYW1lc3BhY2UgPT09IG51bGwgPyBkb2MuY3JlYXRlRWxlbWVudCh2bm9kZS50YWdOYW1lKSA6IGRvYy5jcmVhdGVFbGVtZW50TlModm5vZGUubmFtZXNwYWNlLCB2bm9kZS50YWdOYW1lKTtcblxuICAgICAgICAgICAgICAgIHZhciBwcm9wcyA9IHZub2RlLnByb3BlcnRpZXM7XG4gICAgICAgICAgICAgICAgYXBwbHlQcm9wZXJ0aWVzKG5vZGUsIHByb3BzKTtcblxuICAgICAgICAgICAgICAgIHZhciBjaGlsZHJlbiA9IHZub2RlLmNoaWxkcmVuO1xuXG4gICAgICAgICAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCBjaGlsZHJlbi5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgICAgICAgICB2YXIgY2hpbGROb2RlID0gY3JlYXRlRWxlbWVudChjaGlsZHJlbltpXSwgb3B0cyk7XG4gICAgICAgICAgICAgICAgICAgIGlmIChjaGlsZE5vZGUpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIG5vZGUuYXBwZW5kQ2hpbGQoY2hpbGROb2RlKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHJldHVybiBub2RlO1xuICAgICAgICAgICAgfVxuICAgICAgICB9LCB7IFwiLi4vdm5vZGUvaGFuZGxlLXRodW5rLmpzXCI6IDI0LCBcIi4uL3Zub2RlL2lzLXZub2RlLmpzXCI6IDI3LCBcIi4uL3Zub2RlL2lzLXZ0ZXh0LmpzXCI6IDI4LCBcIi4uL3Zub2RlL2lzLXdpZGdldC5qc1wiOiAyOSwgXCIuL2FwcGx5LXByb3BlcnRpZXNcIjogMTQsIFwiZ2xvYmFsL2RvY3VtZW50XCI6IDEwIH1dLCAxNjogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHtcbiAgICAgICAgICAgIC8vIE1hcHMgYSB2aXJ0dWFsIERPTSB0cmVlIG9udG8gYSByZWFsIERPTSB0cmVlIGluIGFuIGVmZmljaWVudCBtYW5uZXIuXG4gICAgICAgICAgICAvLyBXZSBkb24ndCB3YW50IHRvIHJlYWQgYWxsIG9mIHRoZSBET00gbm9kZXMgaW4gdGhlIHRyZWUgc28gd2UgdXNlXG4gICAgICAgICAgICAvLyB0aGUgaW4tb3JkZXIgdHJlZSBpbmRleGluZyB0byBlbGltaW5hdGUgcmVjdXJzaW9uIGRvd24gY2VydGFpbiBicmFuY2hlcy5cbiAgICAgICAgICAgIC8vIFdlIG9ubHkgcmVjdXJzZSBpbnRvIGEgRE9NIG5vZGUgaWYgd2Uga25vdyB0aGF0IGl0IGNvbnRhaW5zIGEgY2hpbGQgb2ZcbiAgICAgICAgICAgIC8vIGludGVyZXN0LlxuXG4gICAgICAgICAgICB2YXIgbm9DaGlsZCA9IHt9O1xuXG4gICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IGRvbUluZGV4O1xuXG4gICAgICAgICAgICBmdW5jdGlvbiBkb21JbmRleChyb290Tm9kZSwgdHJlZSwgaW5kaWNlcywgbm9kZXMpIHtcbiAgICAgICAgICAgICAgICBpZiAoIWluZGljZXMgfHwgaW5kaWNlcy5sZW5ndGggPT09IDApIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHt9O1xuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIGluZGljZXMuc29ydChhc2NlbmRpbmcpO1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gcmVjdXJzZShyb290Tm9kZSwgdHJlZSwgaW5kaWNlcywgbm9kZXMsIDApO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZnVuY3Rpb24gcmVjdXJzZShyb290Tm9kZSwgdHJlZSwgaW5kaWNlcywgbm9kZXMsIHJvb3RJbmRleCkge1xuICAgICAgICAgICAgICAgIG5vZGVzID0gbm9kZXMgfHwge307XG5cbiAgICAgICAgICAgICAgICBpZiAocm9vdE5vZGUpIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKGluZGV4SW5SYW5nZShpbmRpY2VzLCByb290SW5kZXgsIHJvb3RJbmRleCkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIG5vZGVzW3Jvb3RJbmRleF0gPSByb290Tm9kZTtcbiAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgIHZhciB2Q2hpbGRyZW4gPSB0cmVlLmNoaWxkcmVuO1xuXG4gICAgICAgICAgICAgICAgICAgIGlmICh2Q2hpbGRyZW4pIHtcblxuICAgICAgICAgICAgICAgICAgICAgICAgdmFyIGNoaWxkTm9kZXMgPSByb290Tm9kZS5jaGlsZE5vZGVzO1xuXG4gICAgICAgICAgICAgICAgICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IHRyZWUuY2hpbGRyZW4ubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICByb290SW5kZXggKz0gMTtcblxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZhciB2Q2hpbGQgPSB2Q2hpbGRyZW5baV0gfHwgbm9DaGlsZDtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB2YXIgbmV4dEluZGV4ID0gcm9vdEluZGV4ICsgKHZDaGlsZC5jb3VudCB8fCAwKTtcblxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIHNraXAgcmVjdXJzaW9uIGRvd24gdGhlIHRyZWUgaWYgdGhlcmUgYXJlIG5vIG5vZGVzIGRvd24gaGVyZVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChpbmRleEluUmFuZ2UoaW5kaWNlcywgcm9vdEluZGV4LCBuZXh0SW5kZXgpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlY3Vyc2UoY2hpbGROb2Rlc1tpXSwgdkNoaWxkLCBpbmRpY2VzLCBub2Rlcywgcm9vdEluZGV4KTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICByb290SW5kZXggPSBuZXh0SW5kZXg7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICByZXR1cm4gbm9kZXM7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIC8vIEJpbmFyeSBzZWFyY2ggZm9yIGFuIGluZGV4IGluIHRoZSBpbnRlcnZhbCBbbGVmdCwgcmlnaHRdXG4gICAgICAgICAgICBmdW5jdGlvbiBpbmRleEluUmFuZ2UoaW5kaWNlcywgbGVmdCwgcmlnaHQpIHtcbiAgICAgICAgICAgICAgICBpZiAoaW5kaWNlcy5sZW5ndGggPT09IDApIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHZhciBtaW5JbmRleCA9IDA7XG4gICAgICAgICAgICAgICAgdmFyIG1heEluZGV4ID0gaW5kaWNlcy5sZW5ndGggLSAxO1xuICAgICAgICAgICAgICAgIHZhciBjdXJyZW50SW5kZXg7XG4gICAgICAgICAgICAgICAgdmFyIGN1cnJlbnRJdGVtO1xuXG4gICAgICAgICAgICAgICAgd2hpbGUgKG1pbkluZGV4IDw9IG1heEluZGV4KSB7XG4gICAgICAgICAgICAgICAgICAgIGN1cnJlbnRJbmRleCA9IChtYXhJbmRleCArIG1pbkluZGV4KSAvIDIgPj4gMDtcbiAgICAgICAgICAgICAgICAgICAgY3VycmVudEl0ZW0gPSBpbmRpY2VzW2N1cnJlbnRJbmRleF07XG5cbiAgICAgICAgICAgICAgICAgICAgaWYgKG1pbkluZGV4ID09PSBtYXhJbmRleCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGN1cnJlbnRJdGVtID49IGxlZnQgJiYgY3VycmVudEl0ZW0gPD0gcmlnaHQ7XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoY3VycmVudEl0ZW0gPCBsZWZ0KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBtaW5JbmRleCA9IGN1cnJlbnRJbmRleCArIDE7XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoY3VycmVudEl0ZW0gPiByaWdodCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgbWF4SW5kZXggPSBjdXJyZW50SW5kZXggLSAxO1xuICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIGFzY2VuZGluZyhhLCBiKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGEgPiBiID8gMSA6IC0xO1xuICAgICAgICAgICAgfVxuICAgICAgICB9LCB7fV0sIDE3OiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge1xuICAgICAgICAgICAgdmFyIGFwcGx5UHJvcGVydGllcyA9IHJlcXVpcmUoXCIuL2FwcGx5LXByb3BlcnRpZXNcIik7XG5cbiAgICAgICAgICAgIHZhciBpc1dpZGdldCA9IHJlcXVpcmUoXCIuLi92bm9kZS9pcy13aWRnZXQuanNcIik7XG4gICAgICAgICAgICB2YXIgVlBhdGNoID0gcmVxdWlyZShcIi4uL3Zub2RlL3ZwYXRjaC5qc1wiKTtcblxuICAgICAgICAgICAgdmFyIHVwZGF0ZVdpZGdldCA9IHJlcXVpcmUoXCIuL3VwZGF0ZS13aWRnZXRcIik7XG5cbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gYXBwbHlQYXRjaDtcblxuICAgICAgICAgICAgZnVuY3Rpb24gYXBwbHlQYXRjaCh2cGF0Y2gsIGRvbU5vZGUsIHJlbmRlck9wdGlvbnMpIHtcbiAgICAgICAgICAgICAgICB2YXIgdHlwZSA9IHZwYXRjaC50eXBlO1xuICAgICAgICAgICAgICAgIHZhciB2Tm9kZSA9IHZwYXRjaC52Tm9kZTtcbiAgICAgICAgICAgICAgICB2YXIgcGF0Y2ggPSB2cGF0Y2gucGF0Y2g7XG5cbiAgICAgICAgICAgICAgICBzd2l0Y2ggKHR5cGUpIHtcbiAgICAgICAgICAgICAgICAgICAgY2FzZSBWUGF0Y2guUkVNT1ZFOlxuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHJlbW92ZU5vZGUoZG9tTm9kZSwgdk5vZGUpO1xuICAgICAgICAgICAgICAgICAgICBjYXNlIFZQYXRjaC5JTlNFUlQ6XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gaW5zZXJ0Tm9kZShkb21Ob2RlLCBwYXRjaCwgcmVuZGVyT3B0aW9ucyk7XG4gICAgICAgICAgICAgICAgICAgIGNhc2UgVlBhdGNoLlZURVhUOlxuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHN0cmluZ1BhdGNoKGRvbU5vZGUsIHZOb2RlLCBwYXRjaCwgcmVuZGVyT3B0aW9ucyk7XG4gICAgICAgICAgICAgICAgICAgIGNhc2UgVlBhdGNoLldJREdFVDpcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiB3aWRnZXRQYXRjaChkb21Ob2RlLCB2Tm9kZSwgcGF0Y2gsIHJlbmRlck9wdGlvbnMpO1xuICAgICAgICAgICAgICAgICAgICBjYXNlIFZQYXRjaC5WTk9ERTpcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiB2Tm9kZVBhdGNoKGRvbU5vZGUsIHZOb2RlLCBwYXRjaCwgcmVuZGVyT3B0aW9ucyk7XG4gICAgICAgICAgICAgICAgICAgIGNhc2UgVlBhdGNoLk9SREVSOlxuICAgICAgICAgICAgICAgICAgICAgICAgcmVvcmRlckNoaWxkcmVuKGRvbU5vZGUsIHBhdGNoKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBkb21Ob2RlO1xuICAgICAgICAgICAgICAgICAgICBjYXNlIFZQYXRjaC5QUk9QUzpcbiAgICAgICAgICAgICAgICAgICAgICAgIGFwcGx5UHJvcGVydGllcyhkb21Ob2RlLCBwYXRjaCwgdk5vZGUucHJvcGVydGllcyk7XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gZG9tTm9kZTtcbiAgICAgICAgICAgICAgICAgICAgY2FzZSBWUGF0Y2guVEhVTks6XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gcmVwbGFjZVJvb3QoZG9tTm9kZSwgcmVuZGVyT3B0aW9ucy5wYXRjaChkb21Ob2RlLCBwYXRjaCwgcmVuZGVyT3B0aW9ucykpO1xuICAgICAgICAgICAgICAgICAgICBkZWZhdWx0OlxuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGRvbU5vZGU7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBmdW5jdGlvbiByZW1vdmVOb2RlKGRvbU5vZGUsIHZOb2RlKSB7XG4gICAgICAgICAgICAgICAgdmFyIHBhcmVudE5vZGUgPSBkb21Ob2RlLnBhcmVudE5vZGU7XG5cbiAgICAgICAgICAgICAgICBpZiAocGFyZW50Tm9kZSkge1xuICAgICAgICAgICAgICAgICAgICBwYXJlbnROb2RlLnJlbW92ZUNoaWxkKGRvbU5vZGUpO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIGRlc3Ryb3lXaWRnZXQoZG9tTm9kZSwgdk5vZGUpO1xuXG4gICAgICAgICAgICAgICAgcmV0dXJuIG51bGw7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIGluc2VydE5vZGUocGFyZW50Tm9kZSwgdk5vZGUsIHJlbmRlck9wdGlvbnMpIHtcbiAgICAgICAgICAgICAgICB2YXIgbmV3Tm9kZSA9IHJlbmRlck9wdGlvbnMucmVuZGVyKHZOb2RlLCByZW5kZXJPcHRpb25zKTtcblxuICAgICAgICAgICAgICAgIGlmIChwYXJlbnROb2RlKSB7XG4gICAgICAgICAgICAgICAgICAgIHBhcmVudE5vZGUuYXBwZW5kQ2hpbGQobmV3Tm9kZSk7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgcmV0dXJuIHBhcmVudE5vZGU7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIHN0cmluZ1BhdGNoKGRvbU5vZGUsIGxlZnRWTm9kZSwgdlRleHQsIHJlbmRlck9wdGlvbnMpIHtcbiAgICAgICAgICAgICAgICB2YXIgbmV3Tm9kZTtcblxuICAgICAgICAgICAgICAgIGlmIChkb21Ob2RlLm5vZGVUeXBlID09PSAzKSB7XG4gICAgICAgICAgICAgICAgICAgIGRvbU5vZGUucmVwbGFjZURhdGEoMCwgZG9tTm9kZS5sZW5ndGgsIHZUZXh0LnRleHQpO1xuICAgICAgICAgICAgICAgICAgICBuZXdOb2RlID0gZG9tTm9kZTtcbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICB2YXIgcGFyZW50Tm9kZSA9IGRvbU5vZGUucGFyZW50Tm9kZTtcbiAgICAgICAgICAgICAgICAgICAgbmV3Tm9kZSA9IHJlbmRlck9wdGlvbnMucmVuZGVyKHZUZXh0LCByZW5kZXJPcHRpb25zKTtcblxuICAgICAgICAgICAgICAgICAgICBpZiAocGFyZW50Tm9kZSAmJiBuZXdOb2RlICE9PSBkb21Ob2RlKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBwYXJlbnROb2RlLnJlcGxhY2VDaGlsZChuZXdOb2RlLCBkb21Ob2RlKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHJldHVybiBuZXdOb2RlO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBmdW5jdGlvbiB3aWRnZXRQYXRjaChkb21Ob2RlLCBsZWZ0Vk5vZGUsIHdpZGdldCwgcmVuZGVyT3B0aW9ucykge1xuICAgICAgICAgICAgICAgIHZhciB1cGRhdGluZyA9IHVwZGF0ZVdpZGdldChsZWZ0Vk5vZGUsIHdpZGdldCk7XG4gICAgICAgICAgICAgICAgdmFyIG5ld05vZGU7XG5cbiAgICAgICAgICAgICAgICBpZiAodXBkYXRpbmcpIHtcbiAgICAgICAgICAgICAgICAgICAgbmV3Tm9kZSA9IHdpZGdldC51cGRhdGUobGVmdFZOb2RlLCBkb21Ob2RlKSB8fCBkb21Ob2RlO1xuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIG5ld05vZGUgPSByZW5kZXJPcHRpb25zLnJlbmRlcih3aWRnZXQsIHJlbmRlck9wdGlvbnMpO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHZhciBwYXJlbnROb2RlID0gZG9tTm9kZS5wYXJlbnROb2RlO1xuXG4gICAgICAgICAgICAgICAgaWYgKHBhcmVudE5vZGUgJiYgbmV3Tm9kZSAhPT0gZG9tTm9kZSkge1xuICAgICAgICAgICAgICAgICAgICBwYXJlbnROb2RlLnJlcGxhY2VDaGlsZChuZXdOb2RlLCBkb21Ob2RlKTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICBpZiAoIXVwZGF0aW5nKSB7XG4gICAgICAgICAgICAgICAgICAgIGRlc3Ryb3lXaWRnZXQoZG9tTm9kZSwgbGVmdFZOb2RlKTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICByZXR1cm4gbmV3Tm9kZTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZnVuY3Rpb24gdk5vZGVQYXRjaChkb21Ob2RlLCBsZWZ0Vk5vZGUsIHZOb2RlLCByZW5kZXJPcHRpb25zKSB7XG4gICAgICAgICAgICAgICAgdmFyIHBhcmVudE5vZGUgPSBkb21Ob2RlLnBhcmVudE5vZGU7XG4gICAgICAgICAgICAgICAgdmFyIG5ld05vZGUgPSByZW5kZXJPcHRpb25zLnJlbmRlcih2Tm9kZSwgcmVuZGVyT3B0aW9ucyk7XG5cbiAgICAgICAgICAgICAgICBpZiAocGFyZW50Tm9kZSAmJiBuZXdOb2RlICE9PSBkb21Ob2RlKSB7XG4gICAgICAgICAgICAgICAgICAgIHBhcmVudE5vZGUucmVwbGFjZUNoaWxkKG5ld05vZGUsIGRvbU5vZGUpO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHJldHVybiBuZXdOb2RlO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBmdW5jdGlvbiBkZXN0cm95V2lkZ2V0KGRvbU5vZGUsIHcpIHtcbiAgICAgICAgICAgICAgICBpZiAodHlwZW9mIHcuZGVzdHJveSA9PT0gXCJmdW5jdGlvblwiICYmIGlzV2lkZ2V0KHcpKSB7XG4gICAgICAgICAgICAgICAgICAgIHcuZGVzdHJveShkb21Ob2RlKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIHJlb3JkZXJDaGlsZHJlbihkb21Ob2RlLCBtb3Zlcykge1xuICAgICAgICAgICAgICAgIHZhciBjaGlsZE5vZGVzID0gZG9tTm9kZS5jaGlsZE5vZGVzO1xuICAgICAgICAgICAgICAgIHZhciBrZXlNYXAgPSB7fTtcbiAgICAgICAgICAgICAgICB2YXIgbm9kZTtcbiAgICAgICAgICAgICAgICB2YXIgcmVtb3ZlO1xuICAgICAgICAgICAgICAgIHZhciBpbnNlcnQ7XG5cbiAgICAgICAgICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IG1vdmVzLnJlbW92ZXMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgICAgICAgICAgcmVtb3ZlID0gbW92ZXMucmVtb3Zlc1tpXTtcbiAgICAgICAgICAgICAgICAgICAgbm9kZSA9IGNoaWxkTm9kZXNbcmVtb3ZlLmZyb21dO1xuICAgICAgICAgICAgICAgICAgICBpZiAocmVtb3ZlLmtleSkge1xuICAgICAgICAgICAgICAgICAgICAgICAga2V5TWFwW3JlbW92ZS5rZXldID0gbm9kZTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICBkb21Ob2RlLnJlbW92ZUNoaWxkKG5vZGUpO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHZhciBsZW5ndGggPSBjaGlsZE5vZGVzLmxlbmd0aDtcbiAgICAgICAgICAgICAgICBmb3IgKHZhciBqID0gMDsgaiA8IG1vdmVzLmluc2VydHMubGVuZ3RoOyBqKyspIHtcbiAgICAgICAgICAgICAgICAgICAgaW5zZXJ0ID0gbW92ZXMuaW5zZXJ0c1tqXTtcbiAgICAgICAgICAgICAgICAgICAgbm9kZSA9IGtleU1hcFtpbnNlcnQua2V5XTtcbiAgICAgICAgICAgICAgICAgICAgLy8gdGhpcyBpcyB0aGUgd2VpcmRlc3QgYnVnIGkndmUgZXZlciBzZWVuIGluIHdlYmtpdFxuICAgICAgICAgICAgICAgICAgICBkb21Ob2RlLmluc2VydEJlZm9yZShub2RlLCBpbnNlcnQudG8gPj0gbGVuZ3RoKysgPyBudWxsIDogY2hpbGROb2Rlc1tpbnNlcnQudG9dKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIHJlcGxhY2VSb290KG9sZFJvb3QsIG5ld1Jvb3QpIHtcbiAgICAgICAgICAgICAgICBpZiAob2xkUm9vdCAmJiBuZXdSb290ICYmIG9sZFJvb3QgIT09IG5ld1Jvb3QgJiYgb2xkUm9vdC5wYXJlbnROb2RlKSB7XG4gICAgICAgICAgICAgICAgICAgIG9sZFJvb3QucGFyZW50Tm9kZS5yZXBsYWNlQ2hpbGQobmV3Um9vdCwgb2xkUm9vdCk7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgcmV0dXJuIG5ld1Jvb3Q7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0sIHsgXCIuLi92bm9kZS9pcy13aWRnZXQuanNcIjogMjksIFwiLi4vdm5vZGUvdnBhdGNoLmpzXCI6IDMyLCBcIi4vYXBwbHktcHJvcGVydGllc1wiOiAxNCwgXCIuL3VwZGF0ZS13aWRnZXRcIjogMTkgfV0sIDE4OiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge1xuICAgICAgICAgICAgdmFyIGRvY3VtZW50ID0gcmVxdWlyZShcImdsb2JhbC9kb2N1bWVudFwiKTtcbiAgICAgICAgICAgIHZhciBpc0FycmF5ID0gcmVxdWlyZShcIngtaXMtYXJyYXlcIik7XG5cbiAgICAgICAgICAgIHZhciByZW5kZXIgPSByZXF1aXJlKFwiLi9jcmVhdGUtZWxlbWVudFwiKTtcbiAgICAgICAgICAgIHZhciBkb21JbmRleCA9IHJlcXVpcmUoXCIuL2RvbS1pbmRleFwiKTtcbiAgICAgICAgICAgIHZhciBwYXRjaE9wID0gcmVxdWlyZShcIi4vcGF0Y2gtb3BcIik7XG4gICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IHBhdGNoO1xuXG4gICAgICAgICAgICBmdW5jdGlvbiBwYXRjaChyb290Tm9kZSwgcGF0Y2hlcywgcmVuZGVyT3B0aW9ucykge1xuICAgICAgICAgICAgICAgIHJlbmRlck9wdGlvbnMgPSByZW5kZXJPcHRpb25zIHx8IHt9O1xuICAgICAgICAgICAgICAgIHJlbmRlck9wdGlvbnMucGF0Y2ggPSByZW5kZXJPcHRpb25zLnBhdGNoICYmIHJlbmRlck9wdGlvbnMucGF0Y2ggIT09IHBhdGNoID8gcmVuZGVyT3B0aW9ucy5wYXRjaCA6IHBhdGNoUmVjdXJzaXZlO1xuICAgICAgICAgICAgICAgIHJlbmRlck9wdGlvbnMucmVuZGVyID0gcmVuZGVyT3B0aW9ucy5yZW5kZXIgfHwgcmVuZGVyO1xuXG4gICAgICAgICAgICAgICAgcmV0dXJuIHJlbmRlck9wdGlvbnMucGF0Y2gocm9vdE5vZGUsIHBhdGNoZXMsIHJlbmRlck9wdGlvbnMpO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBmdW5jdGlvbiBwYXRjaFJlY3Vyc2l2ZShyb290Tm9kZSwgcGF0Y2hlcywgcmVuZGVyT3B0aW9ucykge1xuICAgICAgICAgICAgICAgIHZhciBpbmRpY2VzID0gcGF0Y2hJbmRpY2VzKHBhdGNoZXMpO1xuXG4gICAgICAgICAgICAgICAgaWYgKGluZGljZXMubGVuZ3RoID09PSAwKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiByb290Tm9kZTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICB2YXIgaW5kZXggPSBkb21JbmRleChyb290Tm9kZSwgcGF0Y2hlcy5hLCBpbmRpY2VzKTtcbiAgICAgICAgICAgICAgICB2YXIgb3duZXJEb2N1bWVudCA9IHJvb3ROb2RlLm93bmVyRG9jdW1lbnQ7XG5cbiAgICAgICAgICAgICAgICBpZiAoIXJlbmRlck9wdGlvbnMuZG9jdW1lbnQgJiYgb3duZXJEb2N1bWVudCAhPT0gZG9jdW1lbnQpIHtcbiAgICAgICAgICAgICAgICAgICAgcmVuZGVyT3B0aW9ucy5kb2N1bWVudCA9IG93bmVyRG9jdW1lbnQ7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCBpbmRpY2VzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciBub2RlSW5kZXggPSBpbmRpY2VzW2ldO1xuICAgICAgICAgICAgICAgICAgICByb290Tm9kZSA9IGFwcGx5UGF0Y2gocm9vdE5vZGUsIGluZGV4W25vZGVJbmRleF0sIHBhdGNoZXNbbm9kZUluZGV4XSwgcmVuZGVyT3B0aW9ucyk7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgcmV0dXJuIHJvb3ROb2RlO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBmdW5jdGlvbiBhcHBseVBhdGNoKHJvb3ROb2RlLCBkb21Ob2RlLCBwYXRjaExpc3QsIHJlbmRlck9wdGlvbnMpIHtcbiAgICAgICAgICAgICAgICBpZiAoIWRvbU5vZGUpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHJvb3ROb2RlO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHZhciBuZXdOb2RlO1xuXG4gICAgICAgICAgICAgICAgaWYgKGlzQXJyYXkocGF0Y2hMaXN0KSkge1xuICAgICAgICAgICAgICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IHBhdGNoTGlzdC5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgICAgICAgICAgICAgbmV3Tm9kZSA9IHBhdGNoT3AocGF0Y2hMaXN0W2ldLCBkb21Ob2RlLCByZW5kZXJPcHRpb25zKTtcblxuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGRvbU5vZGUgPT09IHJvb3ROb2RlKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcm9vdE5vZGUgPSBuZXdOb2RlO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgbmV3Tm9kZSA9IHBhdGNoT3AocGF0Y2hMaXN0LCBkb21Ob2RlLCByZW5kZXJPcHRpb25zKTtcblxuICAgICAgICAgICAgICAgICAgICBpZiAoZG9tTm9kZSA9PT0gcm9vdE5vZGUpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJvb3ROb2RlID0gbmV3Tm9kZTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHJldHVybiByb290Tm9kZTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZnVuY3Rpb24gcGF0Y2hJbmRpY2VzKHBhdGNoZXMpIHtcbiAgICAgICAgICAgICAgICB2YXIgaW5kaWNlcyA9IFtdO1xuXG4gICAgICAgICAgICAgICAgZm9yICh2YXIga2V5IGluIHBhdGNoZXMpIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKGtleSAhPT0gXCJhXCIpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGluZGljZXMucHVzaChOdW1iZXIoa2V5KSk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICByZXR1cm4gaW5kaWNlcztcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSwgeyBcIi4vY3JlYXRlLWVsZW1lbnRcIjogMTUsIFwiLi9kb20taW5kZXhcIjogMTYsIFwiLi9wYXRjaC1vcFwiOiAxNywgXCJnbG9iYWwvZG9jdW1lbnRcIjogMTAsIFwieC1pcy1hcnJheVwiOiAxMiB9XSwgMTk6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICB2YXIgaXNXaWRnZXQgPSByZXF1aXJlKFwiLi4vdm5vZGUvaXMtd2lkZ2V0LmpzXCIpO1xuXG4gICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IHVwZGF0ZVdpZGdldDtcblxuICAgICAgICAgICAgZnVuY3Rpb24gdXBkYXRlV2lkZ2V0KGEsIGIpIHtcbiAgICAgICAgICAgICAgICBpZiAoaXNXaWRnZXQoYSkgJiYgaXNXaWRnZXQoYikpIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKFwibmFtZVwiIGluIGEgJiYgXCJuYW1lXCIgaW4gYikge1xuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGEuaWQgPT09IGIuaWQ7XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gYS5pbml0ID09PSBiLmluaXQ7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0sIHsgXCIuLi92bm9kZS9pcy13aWRnZXQuanNcIjogMjkgfV0sIDIwOiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge1xuICAgICAgICAgICAgXCJ1c2Ugc3RyaWN0XCI7XG5cbiAgICAgICAgICAgIHZhciBFdlN0b3JlID0gcmVxdWlyZShcImV2LXN0b3JlXCIpO1xuXG4gICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IEV2SG9vaztcblxuICAgICAgICAgICAgZnVuY3Rpb24gRXZIb29rKHZhbHVlKSB7XG4gICAgICAgICAgICAgICAgaWYgKCEodGhpcyBpbnN0YW5jZW9mIEV2SG9vaykpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIG5ldyBFdkhvb2sodmFsdWUpO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHRoaXMudmFsdWUgPSB2YWx1ZTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgRXZIb29rLnByb3RvdHlwZS5ob29rID0gZnVuY3Rpb24gKG5vZGUsIHByb3BlcnR5TmFtZSkge1xuICAgICAgICAgICAgICAgIHZhciBlcyA9IEV2U3RvcmUobm9kZSk7XG4gICAgICAgICAgICAgICAgdmFyIHByb3BOYW1lID0gcHJvcGVydHlOYW1lLnN1YnN0cigzKTtcblxuICAgICAgICAgICAgICAgIGVzW3Byb3BOYW1lXSA9IHRoaXMudmFsdWU7XG4gICAgICAgICAgICB9O1xuXG4gICAgICAgICAgICBFdkhvb2sucHJvdG90eXBlLnVuaG9vayA9IGZ1bmN0aW9uIChub2RlLCBwcm9wZXJ0eU5hbWUpIHtcbiAgICAgICAgICAgICAgICB2YXIgZXMgPSBFdlN0b3JlKG5vZGUpO1xuICAgICAgICAgICAgICAgIHZhciBwcm9wTmFtZSA9IHByb3BlcnR5TmFtZS5zdWJzdHIoMyk7XG5cbiAgICAgICAgICAgICAgICBlc1twcm9wTmFtZV0gPSB1bmRlZmluZWQ7XG4gICAgICAgICAgICB9O1xuICAgICAgICB9LCB7IFwiZXYtc3RvcmVcIjogNyB9XSwgMjE6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICBcInVzZSBzdHJpY3RcIjtcblxuICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBTb2Z0U2V0SG9vaztcblxuICAgICAgICAgICAgZnVuY3Rpb24gU29mdFNldEhvb2sodmFsdWUpIHtcbiAgICAgICAgICAgICAgICBpZiAoISh0aGlzIGluc3RhbmNlb2YgU29mdFNldEhvb2spKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBuZXcgU29mdFNldEhvb2sodmFsdWUpO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHRoaXMudmFsdWUgPSB2YWx1ZTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgU29mdFNldEhvb2sucHJvdG90eXBlLmhvb2sgPSBmdW5jdGlvbiAobm9kZSwgcHJvcGVydHlOYW1lKSB7XG4gICAgICAgICAgICAgICAgaWYgKG5vZGVbcHJvcGVydHlOYW1lXSAhPT0gdGhpcy52YWx1ZSkge1xuICAgICAgICAgICAgICAgICAgICBub2RlW3Byb3BlcnR5TmFtZV0gPSB0aGlzLnZhbHVlO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH07XG4gICAgICAgIH0sIHt9XSwgMjI6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICBcInVzZSBzdHJpY3RcIjtcblxuICAgICAgICAgICAgdmFyIGlzQXJyYXkgPSByZXF1aXJlKFwieC1pcy1hcnJheVwiKTtcblxuICAgICAgICAgICAgdmFyIFZOb2RlID0gcmVxdWlyZShcIi4uL3Zub2RlL3Zub2RlLmpzXCIpO1xuICAgICAgICAgICAgdmFyIFZUZXh0ID0gcmVxdWlyZShcIi4uL3Zub2RlL3Z0ZXh0LmpzXCIpO1xuICAgICAgICAgICAgdmFyIGlzVk5vZGUgPSByZXF1aXJlKFwiLi4vdm5vZGUvaXMtdm5vZGVcIik7XG4gICAgICAgICAgICB2YXIgaXNWVGV4dCA9IHJlcXVpcmUoXCIuLi92bm9kZS9pcy12dGV4dFwiKTtcbiAgICAgICAgICAgIHZhciBpc1dpZGdldCA9IHJlcXVpcmUoXCIuLi92bm9kZS9pcy13aWRnZXRcIik7XG4gICAgICAgICAgICB2YXIgaXNIb29rID0gcmVxdWlyZShcIi4uL3Zub2RlL2lzLXZob29rXCIpO1xuICAgICAgICAgICAgdmFyIGlzVlRodW5rID0gcmVxdWlyZShcIi4uL3Zub2RlL2lzLXRodW5rXCIpO1xuXG4gICAgICAgICAgICB2YXIgcGFyc2VUYWcgPSByZXF1aXJlKFwiLi9wYXJzZS10YWcuanNcIik7XG4gICAgICAgICAgICB2YXIgc29mdFNldEhvb2sgPSByZXF1aXJlKFwiLi9ob29rcy9zb2Z0LXNldC1ob29rLmpzXCIpO1xuICAgICAgICAgICAgdmFyIGV2SG9vayA9IHJlcXVpcmUoXCIuL2hvb2tzL2V2LWhvb2suanNcIik7XG5cbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gaDtcblxuICAgICAgICAgICAgZnVuY3Rpb24gaCh0YWdOYW1lLCBwcm9wZXJ0aWVzLCBjaGlsZHJlbikge1xuICAgICAgICAgICAgICAgIHZhciBjaGlsZE5vZGVzID0gW107XG4gICAgICAgICAgICAgICAgdmFyIHRhZywgcHJvcHMsIGtleSwgbmFtZXNwYWNlO1xuXG4gICAgICAgICAgICAgICAgaWYgKCFjaGlsZHJlbiAmJiBpc0NoaWxkcmVuKHByb3BlcnRpZXMpKSB7XG4gICAgICAgICAgICAgICAgICAgIGNoaWxkcmVuID0gcHJvcGVydGllcztcbiAgICAgICAgICAgICAgICAgICAgcHJvcHMgPSB7fTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICBwcm9wcyA9IHByb3BzIHx8IHByb3BlcnRpZXMgfHwge307XG4gICAgICAgICAgICAgICAgdGFnID0gcGFyc2VUYWcodGFnTmFtZSwgcHJvcHMpO1xuXG4gICAgICAgICAgICAgICAgLy8gc3VwcG9ydCBrZXlzXG4gICAgICAgICAgICAgICAgaWYgKHByb3BzLmhhc093blByb3BlcnR5KFwia2V5XCIpKSB7XG4gICAgICAgICAgICAgICAgICAgIGtleSA9IHByb3BzLmtleTtcbiAgICAgICAgICAgICAgICAgICAgcHJvcHMua2V5ID0gdW5kZWZpbmVkO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIC8vIHN1cHBvcnQgbmFtZXNwYWNlXG4gICAgICAgICAgICAgICAgaWYgKHByb3BzLmhhc093blByb3BlcnR5KFwibmFtZXNwYWNlXCIpKSB7XG4gICAgICAgICAgICAgICAgICAgIG5hbWVzcGFjZSA9IHByb3BzLm5hbWVzcGFjZTtcbiAgICAgICAgICAgICAgICAgICAgcHJvcHMubmFtZXNwYWNlID0gdW5kZWZpbmVkO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIC8vIGZpeCBjdXJzb3IgYnVnXG4gICAgICAgICAgICAgICAgaWYgKHRhZyA9PT0gXCJJTlBVVFwiICYmICFuYW1lc3BhY2UgJiYgcHJvcHMuaGFzT3duUHJvcGVydHkoXCJ2YWx1ZVwiKSAmJiBwcm9wcy52YWx1ZSAhPT0gdW5kZWZpbmVkICYmICFpc0hvb2socHJvcHMudmFsdWUpKSB7XG4gICAgICAgICAgICAgICAgICAgIHByb3BzLnZhbHVlID0gc29mdFNldEhvb2socHJvcHMudmFsdWUpO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHRyYW5zZm9ybVByb3BlcnRpZXMocHJvcHMpO1xuXG4gICAgICAgICAgICAgICAgaWYgKGNoaWxkcmVuICE9PSB1bmRlZmluZWQgJiYgY2hpbGRyZW4gIT09IG51bGwpIHtcbiAgICAgICAgICAgICAgICAgICAgYWRkQ2hpbGQoY2hpbGRyZW4sIGNoaWxkTm9kZXMsIHRhZywgcHJvcHMpO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHJldHVybiBuZXcgVk5vZGUodGFnLCBwcm9wcywgY2hpbGROb2Rlcywga2V5LCBuYW1lc3BhY2UpO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBmdW5jdGlvbiBhZGRDaGlsZChjLCBjaGlsZE5vZGVzLCB0YWcsIHByb3BzKSB7XG4gICAgICAgICAgICAgICAgaWYgKHR5cGVvZiBjID09PSBcInN0cmluZ1wiKSB7XG4gICAgICAgICAgICAgICAgICAgIGNoaWxkTm9kZXMucHVzaChuZXcgVlRleHQoYykpO1xuICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAodHlwZW9mIGMgPT09IFwibnVtYmVyXCIpIHtcbiAgICAgICAgICAgICAgICAgICAgY2hpbGROb2Rlcy5wdXNoKG5ldyBWVGV4dChTdHJpbmcoYykpKTtcbiAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKGlzQ2hpbGQoYykpIHtcbiAgICAgICAgICAgICAgICAgICAgY2hpbGROb2Rlcy5wdXNoKGMpO1xuICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoaXNBcnJheShjKSkge1xuICAgICAgICAgICAgICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IGMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGFkZENoaWxkKGNbaV0sIGNoaWxkTm9kZXMsIHRhZywgcHJvcHMpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfSBlbHNlIGlmIChjID09PSBudWxsIHx8IGMgPT09IHVuZGVmaW5lZCkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgdGhyb3cgVW5leHBlY3RlZFZpcnR1YWxFbGVtZW50KHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGZvcmVpZ25PYmplY3Q6IGMsXG4gICAgICAgICAgICAgICAgICAgICAgICBwYXJlbnRWbm9kZToge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRhZ05hbWU6IHRhZyxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBwcm9wZXJ0aWVzOiBwcm9wc1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIHRyYW5zZm9ybVByb3BlcnRpZXMocHJvcHMpIHtcbiAgICAgICAgICAgICAgICBmb3IgKHZhciBwcm9wTmFtZSBpbiBwcm9wcykge1xuICAgICAgICAgICAgICAgICAgICBpZiAocHJvcHMuaGFzT3duUHJvcGVydHkocHJvcE5hbWUpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICB2YXIgdmFsdWUgPSBwcm9wc1twcm9wTmFtZV07XG5cbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChpc0hvb2sodmFsdWUpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgY29udGludWU7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChwcm9wTmFtZS5zdWJzdHIoMCwgMykgPT09IFwiZXYtXCIpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBhZGQgZXYtZm9vIHN1cHBvcnRcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBwcm9wc1twcm9wTmFtZV0gPSBldkhvb2sodmFsdWUpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBmdW5jdGlvbiBpc0NoaWxkKHgpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gaXNWTm9kZSh4KSB8fCBpc1ZUZXh0KHgpIHx8IGlzV2lkZ2V0KHgpIHx8IGlzVlRodW5rKHgpO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBmdW5jdGlvbiBpc0NoaWxkcmVuKHgpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gdHlwZW9mIHggPT09IFwic3RyaW5nXCIgfHwgaXNBcnJheSh4KSB8fCBpc0NoaWxkKHgpO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBmdW5jdGlvbiBVbmV4cGVjdGVkVmlydHVhbEVsZW1lbnQoZGF0YSkge1xuICAgICAgICAgICAgICAgIHZhciBlcnIgPSBuZXcgRXJyb3IoKTtcblxuICAgICAgICAgICAgICAgIGVyci50eXBlID0gXCJ2aXJ0dWFsLWh5cGVyc2NyaXB0LnVuZXhwZWN0ZWQudmlydHVhbC1lbGVtZW50XCI7XG4gICAgICAgICAgICAgICAgZXJyLm1lc3NhZ2UgPSBcIlVuZXhwZWN0ZWQgdmlydHVhbCBjaGlsZCBwYXNzZWQgdG8gaCgpLlxcblwiICsgXCJFeHBlY3RlZCBhIFZOb2RlIC8gVnRodW5rIC8gVldpZGdldCAvIHN0cmluZyBidXQ6XFxuXCIgKyBcImdvdDpcXG5cIiArIGVycm9yU3RyaW5nKGRhdGEuZm9yZWlnbk9iamVjdCkgKyBcIi5cXG5cIiArIFwiVGhlIHBhcmVudCB2bm9kZSBpczpcXG5cIiArIGVycm9yU3RyaW5nKGRhdGEucGFyZW50Vm5vZGUpO1xuICAgICAgICAgICAgICAgIFwiXFxuXCIgKyBcIlN1Z2dlc3RlZCBmaXg6IGNoYW5nZSB5b3VyIGBoKC4uLiwgWyAuLi4gXSlgIGNhbGxzaXRlLlwiO1xuICAgICAgICAgICAgICAgIGVyci5mb3JlaWduT2JqZWN0ID0gZGF0YS5mb3JlaWduT2JqZWN0O1xuICAgICAgICAgICAgICAgIGVyci5wYXJlbnRWbm9kZSA9IGRhdGEucGFyZW50Vm5vZGU7XG5cbiAgICAgICAgICAgICAgICByZXR1cm4gZXJyO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBmdW5jdGlvbiBlcnJvclN0cmluZyhvYmopIHtcbiAgICAgICAgICAgICAgICB0cnkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gSlNPTi5zdHJpbmdpZnkob2JqLCBudWxsLCBcIiAgICBcIik7XG4gICAgICAgICAgICAgICAgfSBjYXRjaCAoZSkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gU3RyaW5nKG9iaik7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9LCB7IFwiLi4vdm5vZGUvaXMtdGh1bmtcIjogMjUsIFwiLi4vdm5vZGUvaXMtdmhvb2tcIjogMjYsIFwiLi4vdm5vZGUvaXMtdm5vZGVcIjogMjcsIFwiLi4vdm5vZGUvaXMtdnRleHRcIjogMjgsIFwiLi4vdm5vZGUvaXMtd2lkZ2V0XCI6IDI5LCBcIi4uL3Zub2RlL3Zub2RlLmpzXCI6IDMxLCBcIi4uL3Zub2RlL3Z0ZXh0LmpzXCI6IDMzLCBcIi4vaG9va3MvZXYtaG9vay5qc1wiOiAyMCwgXCIuL2hvb2tzL3NvZnQtc2V0LWhvb2suanNcIjogMjEsIFwiLi9wYXJzZS10YWcuanNcIjogMjMsIFwieC1pcy1hcnJheVwiOiAxMiB9XSwgMjM6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICBcInVzZSBzdHJpY3RcIjtcblxuICAgICAgICAgICAgdmFyIHNwbGl0ID0gcmVxdWlyZShcImJyb3dzZXItc3BsaXRcIik7XG5cbiAgICAgICAgICAgIHZhciBjbGFzc0lkU3BsaXQgPSAvKFtcXC4jXT9bYS16QS1aMC05XFx1MDA3Ri1cXHVGRkZGXzotXSspLztcbiAgICAgICAgICAgIHZhciBub3RDbGFzc0lkID0gL15cXC58Iy87XG5cbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gcGFyc2VUYWc7XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIHBhcnNlVGFnKHRhZywgcHJvcHMpIHtcbiAgICAgICAgICAgICAgICBpZiAoIXRhZykge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gXCJESVZcIjtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICB2YXIgbm9JZCA9ICFwcm9wcy5oYXNPd25Qcm9wZXJ0eShcImlkXCIpO1xuXG4gICAgICAgICAgICAgICAgdmFyIHRhZ1BhcnRzID0gc3BsaXQodGFnLCBjbGFzc0lkU3BsaXQpO1xuICAgICAgICAgICAgICAgIHZhciB0YWdOYW1lID0gbnVsbDtcblxuICAgICAgICAgICAgICAgIGlmIChub3RDbGFzc0lkLnRlc3QodGFnUGFydHNbMV0pKSB7XG4gICAgICAgICAgICAgICAgICAgIHRhZ05hbWUgPSBcIkRJVlwiO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHZhciBjbGFzc2VzLCBwYXJ0LCB0eXBlLCBpO1xuXG4gICAgICAgICAgICAgICAgZm9yIChpID0gMDsgaSA8IHRhZ1BhcnRzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICAgICAgICAgIHBhcnQgPSB0YWdQYXJ0c1tpXTtcblxuICAgICAgICAgICAgICAgICAgICBpZiAoIXBhcnQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnRpbnVlO1xuICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgdHlwZSA9IHBhcnQuY2hhckF0KDApO1xuXG4gICAgICAgICAgICAgICAgICAgIGlmICghdGFnTmFtZSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgdGFnTmFtZSA9IHBhcnQ7XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAodHlwZSA9PT0gXCIuXCIpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGNsYXNzZXMgPSBjbGFzc2VzIHx8IFtdO1xuICAgICAgICAgICAgICAgICAgICAgICAgY2xhc3Nlcy5wdXNoKHBhcnQuc3Vic3RyaW5nKDEsIHBhcnQubGVuZ3RoKSk7XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAodHlwZSA9PT0gXCIjXCIgJiYgbm9JZCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgcHJvcHMuaWQgPSBwYXJ0LnN1YnN0cmluZygxLCBwYXJ0Lmxlbmd0aCk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICBpZiAoY2xhc3Nlcykge1xuICAgICAgICAgICAgICAgICAgICBpZiAocHJvcHMuY2xhc3NOYW1lKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBjbGFzc2VzLnB1c2gocHJvcHMuY2xhc3NOYW1lKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgIHByb3BzLmNsYXNzTmFtZSA9IGNsYXNzZXMuam9pbihcIiBcIik7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgcmV0dXJuIHByb3BzLm5hbWVzcGFjZSA/IHRhZ05hbWUgOiB0YWdOYW1lLnRvVXBwZXJDYXNlKCk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0sIHsgXCJicm93c2VyLXNwbGl0XCI6IDUgfV0sIDI0OiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge1xuICAgICAgICAgICAgdmFyIGlzVk5vZGUgPSByZXF1aXJlKFwiLi9pcy12bm9kZVwiKTtcbiAgICAgICAgICAgIHZhciBpc1ZUZXh0ID0gcmVxdWlyZShcIi4vaXMtdnRleHRcIik7XG4gICAgICAgICAgICB2YXIgaXNXaWRnZXQgPSByZXF1aXJlKFwiLi9pcy13aWRnZXRcIik7XG4gICAgICAgICAgICB2YXIgaXNUaHVuayA9IHJlcXVpcmUoXCIuL2lzLXRodW5rXCIpO1xuXG4gICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IGhhbmRsZVRodW5rO1xuXG4gICAgICAgICAgICBmdW5jdGlvbiBoYW5kbGVUaHVuayhhLCBiKSB7XG4gICAgICAgICAgICAgICAgdmFyIHJlbmRlcmVkQSA9IGE7XG4gICAgICAgICAgICAgICAgdmFyIHJlbmRlcmVkQiA9IGI7XG5cbiAgICAgICAgICAgICAgICBpZiAoaXNUaHVuayhiKSkge1xuICAgICAgICAgICAgICAgICAgICByZW5kZXJlZEIgPSByZW5kZXJUaHVuayhiLCBhKTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICBpZiAoaXNUaHVuayhhKSkge1xuICAgICAgICAgICAgICAgICAgICByZW5kZXJlZEEgPSByZW5kZXJUaHVuayhhLCBudWxsKTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgICAgICAgICBhOiByZW5kZXJlZEEsXG4gICAgICAgICAgICAgICAgICAgIGI6IHJlbmRlcmVkQlxuICAgICAgICAgICAgICAgIH07XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIHJlbmRlclRodW5rKHRodW5rLCBwcmV2aW91cykge1xuICAgICAgICAgICAgICAgIHZhciByZW5kZXJlZFRodW5rID0gdGh1bmsudm5vZGU7XG5cbiAgICAgICAgICAgICAgICBpZiAoIXJlbmRlcmVkVGh1bmspIHtcbiAgICAgICAgICAgICAgICAgICAgcmVuZGVyZWRUaHVuayA9IHRodW5rLnZub2RlID0gdGh1bmsucmVuZGVyKHByZXZpb3VzKTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICBpZiAoIShpc1ZOb2RlKHJlbmRlcmVkVGh1bmspIHx8IGlzVlRleHQocmVuZGVyZWRUaHVuaykgfHwgaXNXaWRnZXQocmVuZGVyZWRUaHVuaykpKSB7XG4gICAgICAgICAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcihcInRodW5rIGRpZCBub3QgcmV0dXJuIGEgdmFsaWQgbm9kZVwiKTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICByZXR1cm4gcmVuZGVyZWRUaHVuaztcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSwgeyBcIi4vaXMtdGh1bmtcIjogMjUsIFwiLi9pcy12bm9kZVwiOiAyNywgXCIuL2lzLXZ0ZXh0XCI6IDI4LCBcIi4vaXMtd2lkZ2V0XCI6IDI5IH1dLCAyNTogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHtcbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gaXNUaHVuaztcblxuICAgICAgICAgICAgZnVuY3Rpb24gaXNUaHVuayh0KSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHQgJiYgdC50eXBlID09PSBcIlRodW5rXCI7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0sIHt9XSwgMjY6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IGlzSG9vaztcblxuICAgICAgICAgICAgZnVuY3Rpb24gaXNIb29rKGhvb2spIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gaG9vayAmJiAodHlwZW9mIGhvb2suaG9vayA9PT0gXCJmdW5jdGlvblwiICYmICFob29rLmhhc093blByb3BlcnR5KFwiaG9va1wiKSB8fCB0eXBlb2YgaG9vay51bmhvb2sgPT09IFwiZnVuY3Rpb25cIiAmJiAhaG9vay5oYXNPd25Qcm9wZXJ0eShcInVuaG9va1wiKSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0sIHt9XSwgMjc6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICB2YXIgdmVyc2lvbiA9IHJlcXVpcmUoXCIuL3ZlcnNpb25cIik7XG5cbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gaXNWaXJ0dWFsTm9kZTtcblxuICAgICAgICAgICAgZnVuY3Rpb24gaXNWaXJ0dWFsTm9kZSh4KSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHggJiYgeC50eXBlID09PSBcIlZpcnR1YWxOb2RlXCIgJiYgeC52ZXJzaW9uID09PSB2ZXJzaW9uO1xuICAgICAgICAgICAgfVxuICAgICAgICB9LCB7IFwiLi92ZXJzaW9uXCI6IDMwIH1dLCAyODogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHtcbiAgICAgICAgICAgIHZhciB2ZXJzaW9uID0gcmVxdWlyZShcIi4vdmVyc2lvblwiKTtcblxuICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBpc1ZpcnR1YWxUZXh0O1xuXG4gICAgICAgICAgICBmdW5jdGlvbiBpc1ZpcnR1YWxUZXh0KHgpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4geCAmJiB4LnR5cGUgPT09IFwiVmlydHVhbFRleHRcIiAmJiB4LnZlcnNpb24gPT09IHZlcnNpb247XG4gICAgICAgICAgICB9XG4gICAgICAgIH0sIHsgXCIuL3ZlcnNpb25cIjogMzAgfV0sIDI5OiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge1xuICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBpc1dpZGdldDtcblxuICAgICAgICAgICAgZnVuY3Rpb24gaXNXaWRnZXQodykge1xuICAgICAgICAgICAgICAgIHJldHVybiB3ICYmIHcudHlwZSA9PT0gXCJXaWRnZXRcIjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSwge31dLCAzMDogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHtcbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gXCIyXCI7XG4gICAgICAgIH0sIHt9XSwgMzE6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICB2YXIgdmVyc2lvbiA9IHJlcXVpcmUoXCIuL3ZlcnNpb25cIik7XG4gICAgICAgICAgICB2YXIgaXNWTm9kZSA9IHJlcXVpcmUoXCIuL2lzLXZub2RlXCIpO1xuICAgICAgICAgICAgdmFyIGlzV2lkZ2V0ID0gcmVxdWlyZShcIi4vaXMtd2lkZ2V0XCIpO1xuICAgICAgICAgICAgdmFyIGlzVGh1bmsgPSByZXF1aXJlKFwiLi9pcy10aHVua1wiKTtcbiAgICAgICAgICAgIHZhciBpc1ZIb29rID0gcmVxdWlyZShcIi4vaXMtdmhvb2tcIik7XG5cbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gVmlydHVhbE5vZGU7XG5cbiAgICAgICAgICAgIHZhciBub1Byb3BlcnRpZXMgPSB7fTtcbiAgICAgICAgICAgIHZhciBub0NoaWxkcmVuID0gW107XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIFZpcnR1YWxOb2RlKHRhZ05hbWUsIHByb3BlcnRpZXMsIGNoaWxkcmVuLCBrZXksIG5hbWVzcGFjZSkge1xuICAgICAgICAgICAgICAgIHRoaXMudGFnTmFtZSA9IHRhZ05hbWU7XG4gICAgICAgICAgICAgICAgdGhpcy5wcm9wZXJ0aWVzID0gcHJvcGVydGllcyB8fCBub1Byb3BlcnRpZXM7XG4gICAgICAgICAgICAgICAgdGhpcy5jaGlsZHJlbiA9IGNoaWxkcmVuIHx8IG5vQ2hpbGRyZW47XG4gICAgICAgICAgICAgICAgdGhpcy5rZXkgPSBrZXkgIT0gbnVsbCA/IFN0cmluZyhrZXkpIDogdW5kZWZpbmVkO1xuICAgICAgICAgICAgICAgIHRoaXMubmFtZXNwYWNlID0gdHlwZW9mIG5hbWVzcGFjZSA9PT0gXCJzdHJpbmdcIiA/IG5hbWVzcGFjZSA6IG51bGw7XG5cbiAgICAgICAgICAgICAgICB2YXIgY291bnQgPSBjaGlsZHJlbiAmJiBjaGlsZHJlbi5sZW5ndGggfHwgMDtcbiAgICAgICAgICAgICAgICB2YXIgZGVzY2VuZGFudHMgPSAwO1xuICAgICAgICAgICAgICAgIHZhciBoYXNXaWRnZXRzID0gZmFsc2U7XG4gICAgICAgICAgICAgICAgdmFyIGhhc1RodW5rcyA9IGZhbHNlO1xuICAgICAgICAgICAgICAgIHZhciBkZXNjZW5kYW50SG9va3MgPSBmYWxzZTtcbiAgICAgICAgICAgICAgICB2YXIgaG9va3M7XG5cbiAgICAgICAgICAgICAgICBmb3IgKHZhciBwcm9wTmFtZSBpbiBwcm9wZXJ0aWVzKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmIChwcm9wZXJ0aWVzLmhhc093blByb3BlcnR5KHByb3BOYW1lKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgdmFyIHByb3BlcnR5ID0gcHJvcGVydGllc1twcm9wTmFtZV07XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoaXNWSG9vayhwcm9wZXJ0eSkgJiYgcHJvcGVydHkudW5ob29rKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKCFob29rcykge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBob29rcyA9IHt9O1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGhvb2tzW3Byb3BOYW1lXSA9IHByb3BlcnR5O1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCBjb3VudDsgaSsrKSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciBjaGlsZCA9IGNoaWxkcmVuW2ldO1xuICAgICAgICAgICAgICAgICAgICBpZiAoaXNWTm9kZShjaGlsZCkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGRlc2NlbmRhbnRzICs9IGNoaWxkLmNvdW50IHx8IDA7XG5cbiAgICAgICAgICAgICAgICAgICAgICAgIGlmICghaGFzV2lkZ2V0cyAmJiBjaGlsZC5oYXNXaWRnZXRzKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaGFzV2lkZ2V0cyA9IHRydWU7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgICAgIGlmICghaGFzVGh1bmtzICYmIGNoaWxkLmhhc1RodW5rcykge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGhhc1RodW5rcyA9IHRydWU7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgICAgIGlmICghZGVzY2VuZGFudEhvb2tzICYmIChjaGlsZC5ob29rcyB8fCBjaGlsZC5kZXNjZW5kYW50SG9va3MpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgZGVzY2VuZGFudEhvb2tzID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIGlmICghaGFzV2lkZ2V0cyAmJiBpc1dpZGdldChjaGlsZCkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmICh0eXBlb2YgY2hpbGQuZGVzdHJveSA9PT0gXCJmdW5jdGlvblwiKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaGFzV2lkZ2V0cyA9IHRydWU7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoIWhhc1RodW5rcyAmJiBpc1RodW5rKGNoaWxkKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgaGFzVGh1bmtzID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHRoaXMuY291bnQgPSBjb3VudCArIGRlc2NlbmRhbnRzO1xuICAgICAgICAgICAgICAgIHRoaXMuaGFzV2lkZ2V0cyA9IGhhc1dpZGdldHM7XG4gICAgICAgICAgICAgICAgdGhpcy5oYXNUaHVua3MgPSBoYXNUaHVua3M7XG4gICAgICAgICAgICAgICAgdGhpcy5ob29rcyA9IGhvb2tzO1xuICAgICAgICAgICAgICAgIHRoaXMuZGVzY2VuZGFudEhvb2tzID0gZGVzY2VuZGFudEhvb2tzO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBWaXJ0dWFsTm9kZS5wcm90b3R5cGUudmVyc2lvbiA9IHZlcnNpb247XG4gICAgICAgICAgICBWaXJ0dWFsTm9kZS5wcm90b3R5cGUudHlwZSA9IFwiVmlydHVhbE5vZGVcIjtcbiAgICAgICAgfSwgeyBcIi4vaXMtdGh1bmtcIjogMjUsIFwiLi9pcy12aG9va1wiOiAyNiwgXCIuL2lzLXZub2RlXCI6IDI3LCBcIi4vaXMtd2lkZ2V0XCI6IDI5LCBcIi4vdmVyc2lvblwiOiAzMCB9XSwgMzI6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICB2YXIgdmVyc2lvbiA9IHJlcXVpcmUoXCIuL3ZlcnNpb25cIik7XG5cbiAgICAgICAgICAgIFZpcnR1YWxQYXRjaC5OT05FID0gMDtcbiAgICAgICAgICAgIFZpcnR1YWxQYXRjaC5WVEVYVCA9IDE7XG4gICAgICAgICAgICBWaXJ0dWFsUGF0Y2guVk5PREUgPSAyO1xuICAgICAgICAgICAgVmlydHVhbFBhdGNoLldJREdFVCA9IDM7XG4gICAgICAgICAgICBWaXJ0dWFsUGF0Y2guUFJPUFMgPSA0O1xuICAgICAgICAgICAgVmlydHVhbFBhdGNoLk9SREVSID0gNTtcbiAgICAgICAgICAgIFZpcnR1YWxQYXRjaC5JTlNFUlQgPSA2O1xuICAgICAgICAgICAgVmlydHVhbFBhdGNoLlJFTU9WRSA9IDc7XG4gICAgICAgICAgICBWaXJ0dWFsUGF0Y2guVEhVTksgPSA4O1xuXG4gICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IFZpcnR1YWxQYXRjaDtcblxuICAgICAgICAgICAgZnVuY3Rpb24gVmlydHVhbFBhdGNoKHR5cGUsIHZOb2RlLCBwYXRjaCkge1xuICAgICAgICAgICAgICAgIHRoaXMudHlwZSA9IE51bWJlcih0eXBlKTtcbiAgICAgICAgICAgICAgICB0aGlzLnZOb2RlID0gdk5vZGU7XG4gICAgICAgICAgICAgICAgdGhpcy5wYXRjaCA9IHBhdGNoO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBWaXJ0dWFsUGF0Y2gucHJvdG90eXBlLnZlcnNpb24gPSB2ZXJzaW9uO1xuICAgICAgICAgICAgVmlydHVhbFBhdGNoLnByb3RvdHlwZS50eXBlID0gXCJWaXJ0dWFsUGF0Y2hcIjtcbiAgICAgICAgfSwgeyBcIi4vdmVyc2lvblwiOiAzMCB9XSwgMzM6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICB2YXIgdmVyc2lvbiA9IHJlcXVpcmUoXCIuL3ZlcnNpb25cIik7XG5cbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gVmlydHVhbFRleHQ7XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIFZpcnR1YWxUZXh0KHRleHQpIHtcbiAgICAgICAgICAgICAgICB0aGlzLnRleHQgPSBTdHJpbmcodGV4dCk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIFZpcnR1YWxUZXh0LnByb3RvdHlwZS52ZXJzaW9uID0gdmVyc2lvbjtcbiAgICAgICAgICAgIFZpcnR1YWxUZXh0LnByb3RvdHlwZS50eXBlID0gXCJWaXJ0dWFsVGV4dFwiO1xuICAgICAgICB9LCB7IFwiLi92ZXJzaW9uXCI6IDMwIH1dLCAzNDogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHtcbiAgICAgICAgICAgIHZhciBpc09iamVjdCA9IHJlcXVpcmUoXCJpcy1vYmplY3RcIik7XG4gICAgICAgICAgICB2YXIgaXNIb29rID0gcmVxdWlyZShcIi4uL3Zub2RlL2lzLXZob29rXCIpO1xuXG4gICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IGRpZmZQcm9wcztcblxuICAgICAgICAgICAgZnVuY3Rpb24gZGlmZlByb3BzKGEsIGIpIHtcbiAgICAgICAgICAgICAgICB2YXIgZGlmZjtcblxuICAgICAgICAgICAgICAgIGZvciAodmFyIGFLZXkgaW4gYSkge1xuICAgICAgICAgICAgICAgICAgICBpZiAoIShhS2V5IGluIGIpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBkaWZmID0gZGlmZiB8fCB7fTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGRpZmZbYUtleV0gPSB1bmRlZmluZWQ7XG4gICAgICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgICAgICB2YXIgYVZhbHVlID0gYVthS2V5XTtcbiAgICAgICAgICAgICAgICAgICAgdmFyIGJWYWx1ZSA9IGJbYUtleV07XG5cbiAgICAgICAgICAgICAgICAgICAgaWYgKGFWYWx1ZSA9PT0gYlZhbHVlKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBjb250aW51ZTtcbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIGlmIChpc09iamVjdChhVmFsdWUpICYmIGlzT2JqZWN0KGJWYWx1ZSkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChnZXRQcm90b3R5cGUoYlZhbHVlKSAhPT0gZ2V0UHJvdG90eXBlKGFWYWx1ZSkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBkaWZmID0gZGlmZiB8fCB7fTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBkaWZmW2FLZXldID0gYlZhbHVlO1xuICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIGlmIChpc0hvb2soYlZhbHVlKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRpZmYgPSBkaWZmIHx8IHt9O1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRpZmZbYUtleV0gPSBiVmFsdWU7XG4gICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZhciBvYmplY3REaWZmID0gZGlmZlByb3BzKGFWYWx1ZSwgYlZhbHVlKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAob2JqZWN0RGlmZikge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBkaWZmID0gZGlmZiB8fCB7fTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZGlmZlthS2V5XSA9IG9iamVjdERpZmY7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgZGlmZiA9IGRpZmYgfHwge307XG4gICAgICAgICAgICAgICAgICAgICAgICBkaWZmW2FLZXldID0gYlZhbHVlO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgZm9yICh2YXIgYktleSBpbiBiKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmICghKGJLZXkgaW4gYSkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGRpZmYgPSBkaWZmIHx8IHt9O1xuICAgICAgICAgICAgICAgICAgICAgICAgZGlmZltiS2V5XSA9IGJbYktleV07XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICByZXR1cm4gZGlmZjtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZnVuY3Rpb24gZ2V0UHJvdG90eXBlKHZhbHVlKSB7XG4gICAgICAgICAgICAgICAgaWYgKE9iamVjdC5nZXRQcm90b3R5cGVPZikge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gT2JqZWN0LmdldFByb3RvdHlwZU9mKHZhbHVlKTtcbiAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKHZhbHVlLl9fcHJvdG9fXykge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gdmFsdWUuX19wcm90b19fO1xuICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAodmFsdWUuY29uc3RydWN0b3IpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHZhbHVlLmNvbnN0cnVjdG9yLnByb3RvdHlwZTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH0sIHsgXCIuLi92bm9kZS9pcy12aG9va1wiOiAyNiwgXCJpcy1vYmplY3RcIjogMTEgfV0sIDM1OiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge1xuICAgICAgICAgICAgdmFyIGlzQXJyYXkgPSByZXF1aXJlKFwieC1pcy1hcnJheVwiKTtcblxuICAgICAgICAgICAgdmFyIFZQYXRjaCA9IHJlcXVpcmUoXCIuLi92bm9kZS92cGF0Y2hcIik7XG4gICAgICAgICAgICB2YXIgaXNWTm9kZSA9IHJlcXVpcmUoXCIuLi92bm9kZS9pcy12bm9kZVwiKTtcbiAgICAgICAgICAgIHZhciBpc1ZUZXh0ID0gcmVxdWlyZShcIi4uL3Zub2RlL2lzLXZ0ZXh0XCIpO1xuICAgICAgICAgICAgdmFyIGlzV2lkZ2V0ID0gcmVxdWlyZShcIi4uL3Zub2RlL2lzLXdpZGdldFwiKTtcbiAgICAgICAgICAgIHZhciBpc1RodW5rID0gcmVxdWlyZShcIi4uL3Zub2RlL2lzLXRodW5rXCIpO1xuICAgICAgICAgICAgdmFyIGhhbmRsZVRodW5rID0gcmVxdWlyZShcIi4uL3Zub2RlL2hhbmRsZS10aHVua1wiKTtcblxuICAgICAgICAgICAgdmFyIGRpZmZQcm9wcyA9IHJlcXVpcmUoXCIuL2RpZmYtcHJvcHNcIik7XG5cbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gZGlmZjtcblxuICAgICAgICAgICAgZnVuY3Rpb24gZGlmZihhLCBiKSB7XG4gICAgICAgICAgICAgICAgdmFyIHBhdGNoID0geyBhOiBhIH07XG4gICAgICAgICAgICAgICAgd2FsayhhLCBiLCBwYXRjaCwgMCk7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHBhdGNoO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBmdW5jdGlvbiB3YWxrKGEsIGIsIHBhdGNoLCBpbmRleCkge1xuICAgICAgICAgICAgICAgIGlmIChhID09PSBiKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICB2YXIgYXBwbHkgPSBwYXRjaFtpbmRleF07XG4gICAgICAgICAgICAgICAgdmFyIGFwcGx5Q2xlYXIgPSBmYWxzZTtcblxuICAgICAgICAgICAgICAgIGlmIChpc1RodW5rKGEpIHx8IGlzVGh1bmsoYikpIHtcbiAgICAgICAgICAgICAgICAgICAgdGh1bmtzKGEsIGIsIHBhdGNoLCBpbmRleCk7XG4gICAgICAgICAgICAgICAgfSBlbHNlIGlmIChiID09IG51bGwpIHtcblxuICAgICAgICAgICAgICAgICAgICAvLyBJZiBhIGlzIGEgd2lkZ2V0IHdlIHdpbGwgYWRkIGEgcmVtb3ZlIHBhdGNoIGZvciBpdFxuICAgICAgICAgICAgICAgICAgICAvLyBPdGhlcndpc2UgYW55IGNoaWxkIHdpZGdldHMvaG9va3MgbXVzdCBiZSBkZXN0cm95ZWQuXG4gICAgICAgICAgICAgICAgICAgIC8vIFRoaXMgcHJldmVudHMgYWRkaW5nIHR3byByZW1vdmUgcGF0Y2hlcyBmb3IgYSB3aWRnZXQuXG4gICAgICAgICAgICAgICAgICAgIGlmICghaXNXaWRnZXQoYSkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGNsZWFyU3RhdGUoYSwgcGF0Y2gsIGluZGV4KTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGFwcGx5ID0gcGF0Y2hbaW5kZXhdO1xuICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgYXBwbHkgPSBhcHBlbmRQYXRjaChhcHBseSwgbmV3IFZQYXRjaChWUGF0Y2guUkVNT1ZFLCBhLCBiKSk7XG4gICAgICAgICAgICAgICAgfSBlbHNlIGlmIChpc1ZOb2RlKGIpKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmIChpc1ZOb2RlKGEpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoYS50YWdOYW1lID09PSBiLnRhZ05hbWUgJiYgYS5uYW1lc3BhY2UgPT09IGIubmFtZXNwYWNlICYmIGEua2V5ID09PSBiLmtleSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZhciBwcm9wc1BhdGNoID0gZGlmZlByb3BzKGEucHJvcGVydGllcywgYi5wcm9wZXJ0aWVzKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAocHJvcHNQYXRjaCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBhcHBseSA9IGFwcGVuZFBhdGNoKGFwcGx5LCBuZXcgVlBhdGNoKFZQYXRjaC5QUk9QUywgYSwgcHJvcHNQYXRjaCkpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBhcHBseSA9IGRpZmZDaGlsZHJlbihhLCBiLCBwYXRjaCwgYXBwbHksIGluZGV4KTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgYXBwbHkgPSBhcHBlbmRQYXRjaChhcHBseSwgbmV3IFZQYXRjaChWUGF0Y2guVk5PREUsIGEsIGIpKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBhcHBseUNsZWFyID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGFwcGx5ID0gYXBwZW5kUGF0Y2goYXBwbHksIG5ldyBWUGF0Y2goVlBhdGNoLlZOT0RFLCBhLCBiKSk7XG4gICAgICAgICAgICAgICAgICAgICAgICBhcHBseUNsZWFyID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoaXNWVGV4dChiKSkge1xuICAgICAgICAgICAgICAgICAgICBpZiAoIWlzVlRleHQoYSkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGFwcGx5ID0gYXBwZW5kUGF0Y2goYXBwbHksIG5ldyBWUGF0Y2goVlBhdGNoLlZURVhULCBhLCBiKSk7XG4gICAgICAgICAgICAgICAgICAgICAgICBhcHBseUNsZWFyID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIGlmIChhLnRleHQgIT09IGIudGV4dCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgYXBwbHkgPSBhcHBlbmRQYXRjaChhcHBseSwgbmV3IFZQYXRjaChWUGF0Y2guVlRFWFQsIGEsIGIpKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoaXNXaWRnZXQoYikpIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKCFpc1dpZGdldChhKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgYXBwbHlDbGVhciA9IHRydWU7XG4gICAgICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgICAgICBhcHBseSA9IGFwcGVuZFBhdGNoKGFwcGx5LCBuZXcgVlBhdGNoKFZQYXRjaC5XSURHRVQsIGEsIGIpKTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICBpZiAoYXBwbHkpIHtcbiAgICAgICAgICAgICAgICAgICAgcGF0Y2hbaW5kZXhdID0gYXBwbHk7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgaWYgKGFwcGx5Q2xlYXIpIHtcbiAgICAgICAgICAgICAgICAgICAgY2xlYXJTdGF0ZShhLCBwYXRjaCwgaW5kZXgpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZnVuY3Rpb24gZGlmZkNoaWxkcmVuKGEsIGIsIHBhdGNoLCBhcHBseSwgaW5kZXgpIHtcbiAgICAgICAgICAgICAgICB2YXIgYUNoaWxkcmVuID0gYS5jaGlsZHJlbjtcbiAgICAgICAgICAgICAgICB2YXIgb3JkZXJlZFNldCA9IHJlb3JkZXIoYUNoaWxkcmVuLCBiLmNoaWxkcmVuKTtcbiAgICAgICAgICAgICAgICB2YXIgYkNoaWxkcmVuID0gb3JkZXJlZFNldC5jaGlsZHJlbjtcblxuICAgICAgICAgICAgICAgIHZhciBhTGVuID0gYUNoaWxkcmVuLmxlbmd0aDtcbiAgICAgICAgICAgICAgICB2YXIgYkxlbiA9IGJDaGlsZHJlbi5sZW5ndGg7XG4gICAgICAgICAgICAgICAgdmFyIGxlbiA9IGFMZW4gPiBiTGVuID8gYUxlbiA6IGJMZW47XG5cbiAgICAgICAgICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IGxlbjsgaSsrKSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciBsZWZ0Tm9kZSA9IGFDaGlsZHJlbltpXTtcbiAgICAgICAgICAgICAgICAgICAgdmFyIHJpZ2h0Tm9kZSA9IGJDaGlsZHJlbltpXTtcbiAgICAgICAgICAgICAgICAgICAgaW5kZXggKz0gMTtcblxuICAgICAgICAgICAgICAgICAgICBpZiAoIWxlZnROb2RlKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAocmlnaHROb2RlKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gRXhjZXNzIG5vZGVzIGluIGIgbmVlZCB0byBiZSBhZGRlZFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGFwcGx5ID0gYXBwZW5kUGF0Y2goYXBwbHksIG5ldyBWUGF0Y2goVlBhdGNoLklOU0VSVCwgbnVsbCwgcmlnaHROb2RlKSk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICB3YWxrKGxlZnROb2RlLCByaWdodE5vZGUsIHBhdGNoLCBpbmRleCk7XG4gICAgICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgICAgICBpZiAoaXNWTm9kZShsZWZ0Tm9kZSkgJiYgbGVmdE5vZGUuY291bnQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGluZGV4ICs9IGxlZnROb2RlLmNvdW50O1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgaWYgKG9yZGVyZWRTZXQubW92ZXMpIHtcbiAgICAgICAgICAgICAgICAgICAgLy8gUmVvcmRlciBub2RlcyBsYXN0XG4gICAgICAgICAgICAgICAgICAgIGFwcGx5ID0gYXBwZW5kUGF0Y2goYXBwbHksIG5ldyBWUGF0Y2goVlBhdGNoLk9SREVSLCBhLCBvcmRlcmVkU2V0Lm1vdmVzKSk7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgcmV0dXJuIGFwcGx5O1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBmdW5jdGlvbiBjbGVhclN0YXRlKHZOb2RlLCBwYXRjaCwgaW5kZXgpIHtcbiAgICAgICAgICAgICAgICAvLyBUT0RPOiBNYWtlIHRoaXMgYSBzaW5nbGUgd2Fsaywgbm90IHR3b1xuICAgICAgICAgICAgICAgIHVuaG9vayh2Tm9kZSwgcGF0Y2gsIGluZGV4KTtcbiAgICAgICAgICAgICAgICBkZXN0cm95V2lkZ2V0cyh2Tm9kZSwgcGF0Y2gsIGluZGV4KTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgLy8gUGF0Y2ggcmVjb3JkcyBmb3IgYWxsIGRlc3Ryb3llZCB3aWRnZXRzIG11c3QgYmUgYWRkZWQgYmVjYXVzZSB3ZSBuZWVkXG4gICAgICAgICAgICAvLyBhIERPTSBub2RlIHJlZmVyZW5jZSBmb3IgdGhlIGRlc3Ryb3kgZnVuY3Rpb25cbiAgICAgICAgICAgIGZ1bmN0aW9uIGRlc3Ryb3lXaWRnZXRzKHZOb2RlLCBwYXRjaCwgaW5kZXgpIHtcbiAgICAgICAgICAgICAgICBpZiAoaXNXaWRnZXQodk5vZGUpKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmICh0eXBlb2Ygdk5vZGUuZGVzdHJveSA9PT0gXCJmdW5jdGlvblwiKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBwYXRjaFtpbmRleF0gPSBhcHBlbmRQYXRjaChwYXRjaFtpbmRleF0sIG5ldyBWUGF0Y2goVlBhdGNoLlJFTU9WRSwgdk5vZGUsIG51bGwpKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoaXNWTm9kZSh2Tm9kZSkgJiYgKHZOb2RlLmhhc1dpZGdldHMgfHwgdk5vZGUuaGFzVGh1bmtzKSkge1xuICAgICAgICAgICAgICAgICAgICB2YXIgY2hpbGRyZW4gPSB2Tm9kZS5jaGlsZHJlbjtcbiAgICAgICAgICAgICAgICAgICAgdmFyIGxlbiA9IGNoaWxkcmVuLmxlbmd0aDtcbiAgICAgICAgICAgICAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCBsZW47IGkrKykge1xuICAgICAgICAgICAgICAgICAgICAgICAgdmFyIGNoaWxkID0gY2hpbGRyZW5baV07XG4gICAgICAgICAgICAgICAgICAgICAgICBpbmRleCArPSAxO1xuXG4gICAgICAgICAgICAgICAgICAgICAgICBkZXN0cm95V2lkZ2V0cyhjaGlsZCwgcGF0Y2gsIGluZGV4KTtcblxuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGlzVk5vZGUoY2hpbGQpICYmIGNoaWxkLmNvdW50KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaW5kZXggKz0gY2hpbGQuY291bnQ7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKGlzVGh1bmsodk5vZGUpKSB7XG4gICAgICAgICAgICAgICAgICAgIHRodW5rcyh2Tm9kZSwgbnVsbCwgcGF0Y2gsIGluZGV4KTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIC8vIENyZWF0ZSBhIHN1Yi1wYXRjaCBmb3IgdGh1bmtzXG4gICAgICAgICAgICBmdW5jdGlvbiB0aHVua3MoYSwgYiwgcGF0Y2gsIGluZGV4KSB7XG4gICAgICAgICAgICAgICAgdmFyIG5vZGVzID0gaGFuZGxlVGh1bmsoYSwgYik7XG4gICAgICAgICAgICAgICAgdmFyIHRodW5rUGF0Y2ggPSBkaWZmKG5vZGVzLmEsIG5vZGVzLmIpO1xuICAgICAgICAgICAgICAgIGlmIChoYXNQYXRjaGVzKHRodW5rUGF0Y2gpKSB7XG4gICAgICAgICAgICAgICAgICAgIHBhdGNoW2luZGV4XSA9IG5ldyBWUGF0Y2goVlBhdGNoLlRIVU5LLCBudWxsLCB0aHVua1BhdGNoKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIGhhc1BhdGNoZXMocGF0Y2gpIHtcbiAgICAgICAgICAgICAgICBmb3IgKHZhciBpbmRleCBpbiBwYXRjaCkge1xuICAgICAgICAgICAgICAgICAgICBpZiAoaW5kZXggIT09IFwiYVwiKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgLy8gRXhlY3V0ZSBob29rcyB3aGVuIHR3byBub2RlcyBhcmUgaWRlbnRpY2FsXG4gICAgICAgICAgICBmdW5jdGlvbiB1bmhvb2sodk5vZGUsIHBhdGNoLCBpbmRleCkge1xuICAgICAgICAgICAgICAgIGlmIChpc1ZOb2RlKHZOb2RlKSkge1xuICAgICAgICAgICAgICAgICAgICBpZiAodk5vZGUuaG9va3MpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHBhdGNoW2luZGV4XSA9IGFwcGVuZFBhdGNoKHBhdGNoW2luZGV4XSwgbmV3IFZQYXRjaChWUGF0Y2guUFJPUFMsIHZOb2RlLCB1bmRlZmluZWRLZXlzKHZOb2RlLmhvb2tzKSkpO1xuICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgaWYgKHZOb2RlLmRlc2NlbmRhbnRIb29rcyB8fCB2Tm9kZS5oYXNUaHVua3MpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHZhciBjaGlsZHJlbiA9IHZOb2RlLmNoaWxkcmVuO1xuICAgICAgICAgICAgICAgICAgICAgICAgdmFyIGxlbiA9IGNoaWxkcmVuLmxlbmd0aDtcbiAgICAgICAgICAgICAgICAgICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgbGVuOyBpKyspIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB2YXIgY2hpbGQgPSBjaGlsZHJlbltpXTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpbmRleCArPSAxO1xuXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdW5ob29rKGNoaWxkLCBwYXRjaCwgaW5kZXgpO1xuXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGlzVk5vZGUoY2hpbGQpICYmIGNoaWxkLmNvdW50KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGluZGV4ICs9IGNoaWxkLmNvdW50O1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoaXNUaHVuayh2Tm9kZSkpIHtcbiAgICAgICAgICAgICAgICAgICAgdGh1bmtzKHZOb2RlLCBudWxsLCBwYXRjaCwgaW5kZXgpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZnVuY3Rpb24gdW5kZWZpbmVkS2V5cyhvYmopIHtcbiAgICAgICAgICAgICAgICB2YXIgcmVzdWx0ID0ge307XG5cbiAgICAgICAgICAgICAgICBmb3IgKHZhciBrZXkgaW4gb2JqKSB7XG4gICAgICAgICAgICAgICAgICAgIHJlc3VsdFtrZXldID0gdW5kZWZpbmVkO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHJldHVybiByZXN1bHQ7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIC8vIExpc3QgZGlmZiwgbmFpdmUgbGVmdCB0byByaWdodCByZW9yZGVyaW5nXG4gICAgICAgICAgICBmdW5jdGlvbiByZW9yZGVyKGFDaGlsZHJlbiwgYkNoaWxkcmVuKSB7XG4gICAgICAgICAgICAgICAgLy8gTyhNKSB0aW1lLCBPKE0pIG1lbW9yeVxuICAgICAgICAgICAgICAgIHZhciBiQ2hpbGRJbmRleCA9IGtleUluZGV4KGJDaGlsZHJlbik7XG4gICAgICAgICAgICAgICAgdmFyIGJLZXlzID0gYkNoaWxkSW5kZXgua2V5cztcbiAgICAgICAgICAgICAgICB2YXIgYkZyZWUgPSBiQ2hpbGRJbmRleC5mcmVlO1xuXG4gICAgICAgICAgICAgICAgaWYgKGJGcmVlLmxlbmd0aCA9PT0gYkNoaWxkcmVuLmxlbmd0aCkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgICAgICAgICAgICAgY2hpbGRyZW46IGJDaGlsZHJlbixcbiAgICAgICAgICAgICAgICAgICAgICAgIG1vdmVzOiBudWxsXG4gICAgICAgICAgICAgICAgICAgIH07XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgLy8gTyhOKSB0aW1lLCBPKE4pIG1lbW9yeVxuICAgICAgICAgICAgICAgIHZhciBhQ2hpbGRJbmRleCA9IGtleUluZGV4KGFDaGlsZHJlbik7XG4gICAgICAgICAgICAgICAgdmFyIGFLZXlzID0gYUNoaWxkSW5kZXgua2V5cztcbiAgICAgICAgICAgICAgICB2YXIgYUZyZWUgPSBhQ2hpbGRJbmRleC5mcmVlO1xuXG4gICAgICAgICAgICAgICAgaWYgKGFGcmVlLmxlbmd0aCA9PT0gYUNoaWxkcmVuLmxlbmd0aCkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgICAgICAgICAgICAgY2hpbGRyZW46IGJDaGlsZHJlbixcbiAgICAgICAgICAgICAgICAgICAgICAgIG1vdmVzOiBudWxsXG4gICAgICAgICAgICAgICAgICAgIH07XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgLy8gTyhNQVgoTiwgTSkpIG1lbW9yeVxuICAgICAgICAgICAgICAgIHZhciBuZXdDaGlsZHJlbiA9IFtdO1xuXG4gICAgICAgICAgICAgICAgdmFyIGZyZWVJbmRleCA9IDA7XG4gICAgICAgICAgICAgICAgdmFyIGZyZWVDb3VudCA9IGJGcmVlLmxlbmd0aDtcbiAgICAgICAgICAgICAgICB2YXIgZGVsZXRlZEl0ZW1zID0gMDtcblxuICAgICAgICAgICAgICAgIC8vIEl0ZXJhdGUgdGhyb3VnaCBhIGFuZCBtYXRjaCBhIG5vZGUgaW4gYlxuICAgICAgICAgICAgICAgIC8vIE8oTikgdGltZSxcbiAgICAgICAgICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IGFDaGlsZHJlbi5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgICAgICAgICB2YXIgYUl0ZW0gPSBhQ2hpbGRyZW5baV07XG4gICAgICAgICAgICAgICAgICAgIHZhciBpdGVtSW5kZXg7XG5cbiAgICAgICAgICAgICAgICAgICAgaWYgKGFJdGVtLmtleSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGJLZXlzLmhhc093blByb3BlcnR5KGFJdGVtLmtleSkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBNYXRjaCB1cCB0aGUgb2xkIGtleXNcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpdGVtSW5kZXggPSBiS2V5c1thSXRlbS5rZXldO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIG5ld0NoaWxkcmVuLnB1c2goYkNoaWxkcmVuW2l0ZW1JbmRleF0pO1xuICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBSZW1vdmUgb2xkIGtleWVkIGl0ZW1zXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaXRlbUluZGV4ID0gaSAtIGRlbGV0ZWRJdGVtcysrO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIG5ld0NoaWxkcmVuLnB1c2gobnVsbCk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAvLyBNYXRjaCB0aGUgaXRlbSBpbiBhIHdpdGggdGhlIG5leHQgZnJlZSBpdGVtIGluIGJcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChmcmVlSW5kZXggPCBmcmVlQ291bnQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpdGVtSW5kZXggPSBiRnJlZVtmcmVlSW5kZXgrK107XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgbmV3Q2hpbGRyZW4ucHVzaChiQ2hpbGRyZW5baXRlbUluZGV4XSk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIFRoZXJlIGFyZSBubyBmcmVlIGl0ZW1zIGluIGIgdG8gbWF0Y2ggd2l0aFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIHRoZSBmcmVlIGl0ZW1zIGluIGEsIHNvIHRoZSBleHRyYSBmcmVlIG5vZGVzXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gYXJlIGRlbGV0ZWQuXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaXRlbUluZGV4ID0gaSAtIGRlbGV0ZWRJdGVtcysrO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIG5ld0NoaWxkcmVuLnB1c2gobnVsbCk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICB2YXIgbGFzdEZyZWVJbmRleCA9IGZyZWVJbmRleCA+PSBiRnJlZS5sZW5ndGggPyBiQ2hpbGRyZW4ubGVuZ3RoIDogYkZyZWVbZnJlZUluZGV4XTtcblxuICAgICAgICAgICAgICAgIC8vIEl0ZXJhdGUgdGhyb3VnaCBiIGFuZCBhcHBlbmQgYW55IG5ldyBrZXlzXG4gICAgICAgICAgICAgICAgLy8gTyhNKSB0aW1lXG4gICAgICAgICAgICAgICAgZm9yICh2YXIgaiA9IDA7IGogPCBiQ2hpbGRyZW4ubGVuZ3RoOyBqKyspIHtcbiAgICAgICAgICAgICAgICAgICAgdmFyIG5ld0l0ZW0gPSBiQ2hpbGRyZW5bal07XG5cbiAgICAgICAgICAgICAgICAgICAgaWYgKG5ld0l0ZW0ua2V5KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoIWFLZXlzLmhhc093blByb3BlcnR5KG5ld0l0ZW0ua2V5KSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIEFkZCBhbnkgbmV3IGtleWVkIGl0ZW1zXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gV2UgYXJlIGFkZGluZyBuZXcgaXRlbXMgdG8gdGhlIGVuZCBhbmQgdGhlbiBzb3J0aW5nIHRoZW1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBpbiBwbGFjZS4gSW4gZnV0dXJlIHdlIHNob3VsZCBpbnNlcnQgbmV3IGl0ZW1zIGluIHBsYWNlLlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIG5ld0NoaWxkcmVuLnB1c2gobmV3SXRlbSk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoaiA+PSBsYXN0RnJlZUluZGV4KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAvLyBBZGQgYW55IGxlZnRvdmVyIG5vbi1rZXllZCBpdGVtc1xuICAgICAgICAgICAgICAgICAgICAgICAgbmV3Q2hpbGRyZW4ucHVzaChuZXdJdGVtKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHZhciBzaW11bGF0ZSA9IG5ld0NoaWxkcmVuLnNsaWNlKCk7XG4gICAgICAgICAgICAgICAgdmFyIHNpbXVsYXRlSW5kZXggPSAwO1xuICAgICAgICAgICAgICAgIHZhciByZW1vdmVzID0gW107XG4gICAgICAgICAgICAgICAgdmFyIGluc2VydHMgPSBbXTtcbiAgICAgICAgICAgICAgICB2YXIgc2ltdWxhdGVJdGVtO1xuXG4gICAgICAgICAgICAgICAgZm9yICh2YXIgayA9IDA7IGsgPCBiQ2hpbGRyZW4ubGVuZ3RoOykge1xuICAgICAgICAgICAgICAgICAgICB2YXIgd2FudGVkSXRlbSA9IGJDaGlsZHJlbltrXTtcbiAgICAgICAgICAgICAgICAgICAgc2ltdWxhdGVJdGVtID0gc2ltdWxhdGVbc2ltdWxhdGVJbmRleF07XG5cbiAgICAgICAgICAgICAgICAgICAgLy8gcmVtb3ZlIGl0ZW1zXG4gICAgICAgICAgICAgICAgICAgIHdoaWxlIChzaW11bGF0ZUl0ZW0gPT09IG51bGwgJiYgc2ltdWxhdGUubGVuZ3RoKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICByZW1vdmVzLnB1c2gocmVtb3ZlKHNpbXVsYXRlLCBzaW11bGF0ZUluZGV4LCBudWxsKSk7XG4gICAgICAgICAgICAgICAgICAgICAgICBzaW11bGF0ZUl0ZW0gPSBzaW11bGF0ZVtzaW11bGF0ZUluZGV4XTtcbiAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgIGlmICghc2ltdWxhdGVJdGVtIHx8IHNpbXVsYXRlSXRlbS5rZXkgIT09IHdhbnRlZEl0ZW0ua2V5KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAvLyBpZiB3ZSBuZWVkIGEga2V5IGluIHRoaXMgcG9zaXRpb24uLi5cbiAgICAgICAgICAgICAgICAgICAgICAgIGlmICh3YW50ZWRJdGVtLmtleSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChzaW11bGF0ZUl0ZW0gJiYgc2ltdWxhdGVJdGVtLmtleSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBpZiBhbiBpbnNlcnQgZG9lc24ndCBwdXQgdGhpcyBrZXkgaW4gcGxhY2UsIGl0IG5lZWRzIHRvIG1vdmVcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGJLZXlzW3NpbXVsYXRlSXRlbS5rZXldICE9PSBrICsgMSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmVtb3Zlcy5wdXNoKHJlbW92ZShzaW11bGF0ZSwgc2ltdWxhdGVJbmRleCwgc2ltdWxhdGVJdGVtLmtleSkpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc2ltdWxhdGVJdGVtID0gc2ltdWxhdGVbc2ltdWxhdGVJbmRleF07XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBpZiB0aGUgcmVtb3ZlIGRpZG4ndCBwdXQgdGhlIHdhbnRlZCBpdGVtIGluIHBsYWNlLCB3ZSBuZWVkIHRvIGluc2VydCBpdFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKCFzaW11bGF0ZUl0ZW0gfHwgc2ltdWxhdGVJdGVtLmtleSAhPT0gd2FudGVkSXRlbS5rZXkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpbnNlcnRzLnB1c2goeyBrZXk6IHdhbnRlZEl0ZW0ua2V5LCB0bzogayB9KTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIGl0ZW1zIGFyZSBtYXRjaGluZywgc28gc2tpcCBhaGVhZFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc2ltdWxhdGVJbmRleCsrO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaW5zZXJ0cy5wdXNoKHsga2V5OiB3YW50ZWRJdGVtLmtleSwgdG86IGsgfSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpbnNlcnRzLnB1c2goeyBrZXk6IHdhbnRlZEl0ZW0ua2V5LCB0bzogayB9KTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaysrO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgLy8gYSBrZXkgaW4gc2ltdWxhdGUgaGFzIG5vIG1hdGNoaW5nIHdhbnRlZCBrZXksIHJlbW92ZSBpdFxuICAgICAgICAgICAgICAgICAgICAgICAgZWxzZSBpZiAoc2ltdWxhdGVJdGVtICYmIHNpbXVsYXRlSXRlbS5rZXkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICByZW1vdmVzLnB1c2gocmVtb3ZlKHNpbXVsYXRlLCBzaW11bGF0ZUluZGV4LCBzaW11bGF0ZUl0ZW0ua2V5KSk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBzaW11bGF0ZUluZGV4Kys7XG4gICAgICAgICAgICAgICAgICAgICAgICBrKys7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAvLyByZW1vdmUgYWxsIHRoZSByZW1haW5pbmcgbm9kZXMgZnJvbSBzaW11bGF0ZVxuICAgICAgICAgICAgICAgIHdoaWxlIChzaW11bGF0ZUluZGV4IDwgc2ltdWxhdGUubGVuZ3RoKSB7XG4gICAgICAgICAgICAgICAgICAgIHNpbXVsYXRlSXRlbSA9IHNpbXVsYXRlW3NpbXVsYXRlSW5kZXhdO1xuICAgICAgICAgICAgICAgICAgICByZW1vdmVzLnB1c2gocmVtb3ZlKHNpbXVsYXRlLCBzaW11bGF0ZUluZGV4LCBzaW11bGF0ZUl0ZW0gJiYgc2ltdWxhdGVJdGVtLmtleSkpO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIC8vIElmIHRoZSBvbmx5IG1vdmVzIHdlIGhhdmUgYXJlIGRlbGV0ZXMgdGhlbiB3ZSBjYW4ganVzdFxuICAgICAgICAgICAgICAgIC8vIGxldCB0aGUgZGVsZXRlIHBhdGNoIHJlbW92ZSB0aGVzZSBpdGVtcy5cbiAgICAgICAgICAgICAgICBpZiAocmVtb3Zlcy5sZW5ndGggPT09IGRlbGV0ZWRJdGVtcyAmJiAhaW5zZXJ0cy5sZW5ndGgpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGNoaWxkcmVuOiBuZXdDaGlsZHJlbixcbiAgICAgICAgICAgICAgICAgICAgICAgIG1vdmVzOiBudWxsXG4gICAgICAgICAgICAgICAgICAgIH07XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgICAgICAgICAgY2hpbGRyZW46IG5ld0NoaWxkcmVuLFxuICAgICAgICAgICAgICAgICAgICBtb3Zlczoge1xuICAgICAgICAgICAgICAgICAgICAgICAgcmVtb3ZlczogcmVtb3ZlcyxcbiAgICAgICAgICAgICAgICAgICAgICAgIGluc2VydHM6IGluc2VydHNcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH07XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIHJlbW92ZShhcnIsIGluZGV4LCBrZXkpIHtcbiAgICAgICAgICAgICAgICBhcnIuc3BsaWNlKGluZGV4LCAxKTtcblxuICAgICAgICAgICAgICAgIHJldHVybiB7XG4gICAgICAgICAgICAgICAgICAgIGZyb206IGluZGV4LFxuICAgICAgICAgICAgICAgICAgICBrZXk6IGtleVxuICAgICAgICAgICAgICAgIH07XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIGtleUluZGV4KGNoaWxkcmVuKSB7XG4gICAgICAgICAgICAgICAgdmFyIGtleXMgPSB7fTtcbiAgICAgICAgICAgICAgICB2YXIgZnJlZSA9IFtdO1xuICAgICAgICAgICAgICAgIHZhciBsZW5ndGggPSBjaGlsZHJlbi5sZW5ndGg7XG5cbiAgICAgICAgICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IGxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciBjaGlsZCA9IGNoaWxkcmVuW2ldO1xuXG4gICAgICAgICAgICAgICAgICAgIGlmIChjaGlsZC5rZXkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGtleXNbY2hpbGQua2V5XSA9IGk7XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBmcmVlLnB1c2goaSk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgICAgICAgICBrZXlzOiBrZXlzLCAvLyBBIGhhc2ggb2Yga2V5IG5hbWUgdG8gaW5kZXhcbiAgICAgICAgICAgICAgICAgICAgZnJlZTogZnJlZSAvLyBBbiBhcnJheSBvZiB1bmtleWVkIGl0ZW0gaW5kaWNlc1xuICAgICAgICAgICAgICAgIH07XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIGFwcGVuZFBhdGNoKGFwcGx5LCBwYXRjaCkge1xuICAgICAgICAgICAgICAgIGlmIChhcHBseSkge1xuICAgICAgICAgICAgICAgICAgICBpZiAoaXNBcnJheShhcHBseSkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGFwcGx5LnB1c2gocGF0Y2gpO1xuICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgYXBwbHkgPSBbYXBwbHksIHBhdGNoXTtcbiAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBhcHBseTtcbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gcGF0Y2g7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9LCB7IFwiLi4vdm5vZGUvaGFuZGxlLXRodW5rXCI6IDI0LCBcIi4uL3Zub2RlL2lzLXRodW5rXCI6IDI1LCBcIi4uL3Zub2RlL2lzLXZub2RlXCI6IDI3LCBcIi4uL3Zub2RlL2lzLXZ0ZXh0XCI6IDI4LCBcIi4uL3Zub2RlL2lzLXdpZGdldFwiOiAyOSwgXCIuLi92bm9kZS92cGF0Y2hcIjogMzIsIFwiLi9kaWZmLXByb3BzXCI6IDM0LCBcIngtaXMtYXJyYXlcIjogMTIgfV0gfSwge30sIFs0XSkoNCk7XG59KTtcblxuLyogQGZsb3cgKi9cblxuY2xhc3MgTWFpbGJveCB7XG5cbiAgY29uc3RydWN0b3IoKSB7XG4gICAgdGhpcy5tZXNzYWdlcyA9IFtdO1xuICB9XG5cbiAgZGVsaXZlcihtZXNzYWdlKSB7XG4gICAgdGhpcy5tZXNzYWdlcy5wdXNoKG1lc3NhZ2UpO1xuICAgIHJldHVybiBtZXNzYWdlO1xuICB9XG5cbiAgZ2V0KCkge1xuICAgIHJldHVybiB0aGlzLm1lc3NhZ2VzO1xuICB9XG5cbiAgaXNFbXB0eSgpIHtcbiAgICByZXR1cm4gdGhpcy5tZXNzYWdlcy5sZW5ndGggPT09IDA7XG4gIH1cblxuICByZW1vdmVBdChpbmRleCkge1xuICAgIHRoaXMubWVzc2FnZXMuc3BsaWNlKGluZGV4LCAxKTtcbiAgfVxufVxuXG52YXIgU3RhdGVzID0ge1xuICBOT1JNQUw6IFN5bWJvbC5mb3IoXCJub3JtYWxcIiksXG4gIEtJTEw6IFN5bWJvbC5mb3IoXCJraWxsXCIpLFxuICBTVVNQRU5EOiBTeW1ib2wuZm9yKFwic3VzcGVuZFwiKSxcbiAgQ09OVElOVUU6IFN5bWJvbC5mb3IoXCJjb250aW51ZVwiKSxcbiAgUkVDRUlWRTogU3ltYm9sLmZvcihcInJlY2VpdmVcIiksXG4gIFNFTkQ6IFN5bWJvbC5mb3IoXCJzZW5kXCIpLFxuICBTTEVFUElORzogU3ltYm9sLmZvcihcInNsZWVwaW5nXCIpLFxuICBSVU5OSU5HOiBTeW1ib2wuZm9yKFwicnVubmluZ1wiKSxcbiAgU1VTUEVOREVEOiBTeW1ib2wuZm9yKFwic3VzcGVuZGVkXCIpLFxuICBTVE9QUEVEOiBTeW1ib2wuZm9yKFwic3RvcHBlZFwiKSxcbiAgU0xFRVA6IFN5bWJvbC5mb3IoXCJzbGVlcFwiKSxcbiAgRVhJVDogU3ltYm9sLmZvcihcImV4aXRcIiksXG4gIE5PTUFUQ0g6IFN5bWJvbC5mb3IoXCJub19tYXRjaFwiKVxufTtcblxuY2xhc3MgUHJvY2VzcyB7XG5cbiAgY29uc3RydWN0b3IocGlkLCBtYWlsYm94KSB7XG4gICAgdGhpcy5waWQgPSBwaWQ7XG4gICAgdGhpcy5tYWlsYm94ID0gbWFpbGJveDtcbiAgICB0aGlzLnN0YXR1cyA9IFN0YXRlcy5TVE9QUEVEO1xuICAgIHRoaXMuZGljdCA9IHt9O1xuICB9XG59XG5cbmNsYXNzIFR1cGxlIHtcblxuICBjb25zdHJ1Y3RvciguLi5hcmdzKSB7XG4gICAgdGhpcy52YWx1ZXMgPSBPYmplY3QuZnJlZXplKGFyZ3MpO1xuICAgIHRoaXMubGVuZ3RoID0gdGhpcy52YWx1ZXMubGVuZ3RoO1xuICB9XG5cbiAgZ2V0KGluZGV4KSB7XG4gICAgcmV0dXJuIHRoaXMudmFsdWVzW2luZGV4XTtcbiAgfVxuXG4gIGNvdW50KCkge1xuICAgIHJldHVybiB0aGlzLnZhbHVlcy5sZW5ndGg7XG4gIH1cblxuICBbU3ltYm9sLml0ZXJhdG9yXSgpIHtcbiAgICByZXR1cm4gdGhpcy52YWx1ZXNbU3ltYm9sLml0ZXJhdG9yXSgpO1xuICB9XG5cbiAgdG9TdHJpbmcoKSB7XG4gICAgdmFyIGksXG4gICAgICAgIHMgPSBcIlwiO1xuICAgIGZvciAoaSA9IDA7IGkgPCB0aGlzLnZhbHVlcy5sZW5ndGg7IGkrKykge1xuICAgICAgaWYgKHMgIT09IFwiXCIpIHtcbiAgICAgICAgcyArPSBcIiwgXCI7XG4gICAgICB9XG4gICAgICBzICs9IHRoaXMudmFsdWVzW2ldLnRvU3RyaW5nKCk7XG4gICAgfVxuXG4gICAgcmV0dXJuIFwie1wiICsgcyArIFwifVwiO1xuICB9XG5cbiAgcHV0X2VsZW0oaW5kZXgsIGVsZW0pIHtcbiAgICBpZiAoaW5kZXggPT09IHRoaXMubGVuZ3RoKSB7XG4gICAgICBsZXQgbmV3X3ZhbHVlcyA9IHRoaXMudmFsdWVzLmNvbmNhdChbZWxlbV0pO1xuICAgICAgcmV0dXJuIG5ldyBUdXBsZSguLi5uZXdfdmFsdWVzKTtcbiAgICB9XG5cbiAgICBsZXQgbmV3X3ZhbHVlcyA9IHRoaXMudmFsdWVzLmNvbmNhdChbXSk7XG4gICAgbmV3X3ZhbHVlcy5zcGxpY2UoaW5kZXgsIDAsIGVsZW0pO1xuICAgIHJldHVybiBuZXcgVHVwbGUoLi4ubmV3X3ZhbHVlcyk7XG4gIH1cblxuICByZW1vdmVfZWxlbShpbmRleCkge1xuICAgIGxldCBuZXdfdmFsdWVzID0gdGhpcy52YWx1ZXMuY29uY2F0KFtdKTtcbiAgICBuZXdfdmFsdWVzLnNwbGljZShpbmRleCwgMSk7XG4gICAgcmV0dXJuIG5ldyBUdXBsZSguLi5uZXdfdmFsdWVzKTtcbiAgfVxuXG59XG5cbmxldCBwcm9jZXNzX2NvdW50ZXIgPSAtMTtcblxuY2xhc3MgUElEIHtcbiAgY29uc3RydWN0b3IoKSB7XG4gICAgcHJvY2Vzc19jb3VudGVyID0gcHJvY2Vzc19jb3VudGVyICsgMTtcbiAgICB0aGlzLmlkID0gcHJvY2Vzc19jb3VudGVyO1xuICB9XG5cbiAgdG9TdHJpbmcoKSB7XG4gICAgcmV0dXJuIFwiUElEIzwwLlwiICsgdGhpcy5pZCArIFwiLjA+XCI7XG4gIH1cbn1cblxuY2xhc3MgSW50ZWdlciB7fVxuY2xhc3MgRmxvYXQge31cblxuY2xhc3MgUHJvY2Vzc1N5c3RlbSB7XG5cbiAgY29uc3RydWN0b3IoKSB7XG4gICAgdGhpcy5waWRzID0gbmV3IE1hcCgpO1xuICAgIHRoaXMubWFpbGJveGVzID0gbmV3IE1hcCgpO1xuICAgIHRoaXMubmFtZXMgPSBuZXcgTWFwKCk7XG4gICAgdGhpcy5saW5rcyA9IG5ldyBNYXAoKTtcblxuICAgIHRoaXMuY3VycmVudF9wcm9jZXNzID0gbnVsbDtcbiAgICB0aGlzLnN1c3BlbmRlZCA9IG5ldyBNYXAoKTtcblxuICAgIHRoaXMubWFpbl9wcm9jZXNzX3BpZCA9IHRoaXMuc3Bhd24oKTtcbiAgICB0aGlzLnNldF9jdXJyZW50KHRoaXMubWFpbl9wcm9jZXNzX3BpZCk7XG4gIH1cblxuICBzcGF3bigpIHtcbiAgICByZXR1cm4gdGhpcy5hZGRfcHJvYyhmYWxzZSkucGlkO1xuICB9XG5cbiAgc3Bhd25fbGluaygpIHtcbiAgICByZXR1cm4gdGhpcy5hZGRfcHJvYyh0cnVlKS5waWQ7XG4gIH1cblxuICBsaW5rKHBpZCkge1xuICAgIHRoaXMubGlua3MuZ2V0KHRoaXMucGlkKCkpLmFkZChwaWQpO1xuICAgIHRoaXMubGlua3MuZ2V0KHBpZCkuYWRkKHRoaXMucGlkKCkpO1xuICB9XG5cbiAgdW5saW5rKHBpZCkge1xuICAgIHRoaXMubGlua3MuZ2V0KHRoaXMucGlkKCkpLmRlbGV0ZShwaWQpO1xuICAgIHRoaXMubGlua3MuZ2V0KHBpZCkuZGVsZXRlKHRoaXMucGlkKCkpO1xuICB9XG5cbiAgc2V0X2N1cnJlbnQoaWQpIHtcbiAgICBsZXQgcGlkID0gdGhpcy5waWRvZihpZCk7XG4gICAgaWYgKHBpZCAhPT0gbnVsbCkge1xuICAgICAgdGhpcy5jdXJyZW50X3Byb2Nlc3MgPSB0aGlzLnBpZHMuZ2V0KHBpZCk7XG4gICAgICB0aGlzLmN1cnJlbnRfcHJvY2Vzcy5zdGF0dXMgPSBTdGF0ZXMuUlVOTklORztcbiAgICB9XG4gIH1cblxuICBhZGRfcHJvYyhsaW5rZWQpIHtcbiAgICBsZXQgbmV3cGlkID0gbmV3IFBJRCgpO1xuICAgIGxldCBtYWlsYm94ID0gbmV3IE1haWxib3goKTtcbiAgICBsZXQgbmV3cHJvYyA9IG5ldyBQcm9jZXNzKG5ld3BpZCwgbWFpbGJveCk7XG5cbiAgICB0aGlzLnBpZHMuc2V0KG5ld3BpZCwgbmV3cHJvYyk7XG4gICAgdGhpcy5tYWlsYm94ZXMuc2V0KG5ld3BpZCwgbWFpbGJveCk7XG4gICAgdGhpcy5saW5rcy5zZXQobmV3cGlkLCBuZXcgU2V0KCkpO1xuXG4gICAgaWYgKGxpbmtlZCkge1xuICAgICAgdGhpcy5saW5rKG5ld3BpZCk7XG4gICAgfVxuXG4gICAgcmV0dXJuIG5ld3Byb2M7XG4gIH1cblxuICByZW1vdmVfcHJvYyhwaWQpIHtcbiAgICB0aGlzLnBpZHMuZGVsZXRlKHBpZCk7XG4gICAgdGhpcy51bnJlZ2lzdGVyKHBpZCk7XG5cbiAgICBpZiAodGhpcy5saW5rcy5oYXMocGlkKSkge1xuICAgICAgZm9yIChsZXQgbGlua3BpZCBvZiB0aGlzLmxpbmtzLmdldChwaWQpKSB7XG4gICAgICAgIHRoaXMubGlua3MuZ2V0KGxpbmtwaWQpLmRlbGV0ZShwaWQpO1xuICAgICAgfVxuXG4gICAgICB0aGlzLmxpbmtzLmRlbGV0ZShwaWQpO1xuICAgIH1cbiAgfVxuXG4gIGV4aXQoaWQpIHtcbiAgICBsZXQgcGlkID0gdGhpcy5waWRvZihpZCk7XG4gICAgdGhpcy5yZW1vdmVfcHJvYyhpZCk7XG4gIH1cblxuICByZWdpc3RlcihuYW1lLCBwaWQpIHtcbiAgICBpZiAoIXRoaXMubmFtZXMuaGFzKG5hbWUpKSB7XG4gICAgICB0aGlzLm5hbWVzLnNldChuYW1lLCBwaWQpO1xuICAgICAgcmV0dXJuIG5hbWU7XG4gICAgfSBlbHNlIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcihcIk5hbWUgaXMgYWxyZWFkeSByZWdpc3RlcmVkIHRvIGFub3RoZXIgcHJvY2Vzc1wiKTtcbiAgICB9XG4gIH1cblxuICByZWdpc3RlcmVkKG5hbWUpIHtcbiAgICByZXR1cm4gdGhpcy5uYW1lcy5oYXMobmFtZSkgPyB0aGlzLm5hbWVzLmdldChuYW1lKSA6IG51bGw7XG4gIH1cblxuICB1bnJlZ2lzdGVyKHBpZCkge1xuICAgIGZvciAobGV0IG5hbWUgb2YgdGhpcy5uYW1lcy5rZXlzKCkpIHtcbiAgICAgIGlmICh0aGlzLm5hbWVzLmhhcyhuYW1lKSAmJiB0aGlzLm5hbWVzLmdldChuYW1lKSA9PT0gcGlkKSB7XG4gICAgICAgIHRoaXMubmFtZXMuZGVsZXRlKG5hbWUpO1xuICAgICAgfVxuICAgIH1cbiAgfVxuXG4gIHBpZCgpIHtcbiAgICByZXR1cm4gdGhpcy5jdXJyZW50X3Byb2Nlc3MucGlkO1xuICB9XG5cbiAgcGlkb2YoaWQpIHtcbiAgICBpZiAoaWQgaW5zdGFuY2VvZiBQSUQpIHtcbiAgICAgIHJldHVybiB0aGlzLnBpZHMuaGFzKGlkKSA/IGlkIDogbnVsbDtcbiAgICB9IGVsc2UgaWYgKGlkIGluc3RhbmNlb2YgUHJvY2Vzcykge1xuICAgICAgcmV0dXJuIGlkLnBpZDtcbiAgICB9IGVsc2Uge1xuICAgICAgbGV0IHBpZCA9IHRoaXMucmVnaXN0ZXJlZChpZCk7XG4gICAgICBpZiAocGlkID09PSBudWxsKSB0aHJvdyBcIlByb2Nlc3MgbmFtZSBub3QgcmVnaXN0ZXJlZDogXCIgKyBpZCArIFwiIChcIiArIHR5cGVvZiBpZCArIFwiKVwiO1xuICAgICAgcmV0dXJuIHBpZDtcbiAgICB9XG4gIH1cblxuICBwdXQoaWQsIGtleSwgdmFsdWUpIHtcbiAgICBsZXQgcGlkID0gdGhpcy5waWRvZihpZCk7XG4gICAgbGV0IHByb2Nlc3MgPSB0aGlzLnBpZHMuZ2V0KHBpZCk7XG4gICAgcHJvY2Vzcy5kaWN0W2tleV0gPSB2YWx1ZTtcbiAgfVxuXG4gIGdldChpZCwga2V5KSB7XG4gICAgbGV0IHBpZCA9IHRoaXMucGlkb2YoaWQpO1xuICAgIGxldCBwcm9jZXNzID0gdGhpcy5waWRzLmdldChwaWQpO1xuXG4gICAgaWYgKGtleSAhPSBudWxsKSB7XG4gICAgICByZXR1cm4gcHJvY2Vzcy5kaWN0W2tleV07XG4gICAgfSBlbHNlIHtcbiAgICAgIHJldHVybiBwcm9jZXNzLmRpY3Q7XG4gICAgfVxuICB9XG5cbiAgZ2V0X2tleXMoaWQpIHtcbiAgICBsZXQgcGlkID0gdGhpcy5waWRvZihpZCk7XG4gICAgbGV0IHByb2Nlc3MgPSB0aGlzLnBpZHMuZ2V0KHBpZCk7XG5cbiAgICByZXR1cm4gT2JqZWN0LmtleXMocHJvY2Vzcy5kaWN0KTtcbiAgfVxuXG4gIGVyYXNlKGlkLCBrZXkpIHtcbiAgICBsZXQgcGlkID0gdGhpcy5waWRvZihpZCk7XG4gICAgbGV0IHByb2Nlc3MgPSB0aGlzLnBpZHMuZ2V0KHBpZCk7XG5cbiAgICBpZiAoa2V5ICE9IG51bGwpIHtcbiAgICAgIGRlbGV0ZSBwcm9jZXNzLmRpY3Rba2V5XTtcbiAgICB9IGVsc2Uge1xuICAgICAgcHJvY2Vzcy5kaWN0ID0ge307XG4gICAgfVxuICB9XG59XG5cbmNsYXNzIEJpdFN0cmluZyB7XG4gIGNvbnN0cnVjdG9yKC4uLmFyZ3MpIHtcbiAgICB0aGlzLnJhd192YWx1ZSA9IGZ1bmN0aW9uICgpIHtcbiAgICAgIHJldHVybiBPYmplY3QuZnJlZXplKGFyZ3MpO1xuICAgIH07XG5cbiAgICB0aGlzLnZhbHVlID0gT2JqZWN0LmZyZWV6ZSh0aGlzLnByb2Nlc3MoYXJncykpO1xuICAgIHRoaXMubGVuZ3RoID0gdGhpcy52YWx1ZS5sZW5ndGg7XG4gICAgdGhpcy5iaXRfc2l6ZSA9IHRoaXMucmF3X3ZhbHVlKCkucmVkdWNlKChwcmV2LCBjdXJyZW50KSA9PiBwcmV2ICsgY3VycmVudC5zaXplKTtcbiAgICB0aGlzLmJ5dGVfc2l6ZSA9IHRoaXMuYml0X3NpemUgLyA4ICsgKHRoaXMuYml0X3NpemUgJSA4ID4gMCA/IDEgOiAwKTtcbiAgfVxuXG4gIGdldChpbmRleCkge1xuICAgIHJldHVybiB0aGlzLnZhbHVlW2luZGV4XTtcbiAgfVxuXG4gIGNvdW50KCkge1xuICAgIHJldHVybiB0aGlzLnZhbHVlLmxlbmd0aDtcbiAgfVxuXG4gIFtTeW1ib2wuaXRlcmF0b3JdKCkge1xuICAgIHJldHVybiB0aGlzLnZhbHVlW1N5bWJvbC5pdGVyYXRvcl0oKTtcbiAgfVxuXG4gIHRvU3RyaW5nKCkge1xuICAgIHZhciBpLFxuICAgICAgICBzID0gXCJcIjtcbiAgICBmb3IgKGkgPSAwOyBpIDwgdGhpcy5jb3VudCgpOyBpKyspIHtcbiAgICAgIGlmIChzICE9PSBcIlwiKSB7XG4gICAgICAgIHMgKz0gXCIsIFwiO1xuICAgICAgfVxuICAgICAgcyArPSB0aGlzW2ldLnRvU3RyaW5nKCk7XG4gICAgfVxuXG4gICAgcmV0dXJuIFwiPDxcIiArIHMgKyBcIj4+XCI7XG4gIH1cblxuICBwcm9jZXNzKCkge1xuICAgIGxldCBwcm9jZXNzZWRfdmFsdWVzID0gW107XG5cbiAgICB2YXIgaTtcbiAgICBmb3IgKGkgPSAwOyBpIDwgdGhpcy5yYXdfdmFsdWUoKS5sZW5ndGg7IGkrKykge1xuICAgICAgbGV0IHByb2Nlc3NlZF92YWx1ZSA9IHRoaXNbXCJwcm9jZXNzX1wiICsgdGhpcy5yYXdfdmFsdWUoKVtpXS50eXBlXSh0aGlzLnJhd192YWx1ZSgpW2ldKTtcblxuICAgICAgZm9yIChsZXQgYXR0ciBvZiB0aGlzLnJhd192YWx1ZSgpW2ldLmF0dHJpYnV0ZXMpIHtcbiAgICAgICAgcHJvY2Vzc2VkX3ZhbHVlID0gdGhpc1tcInByb2Nlc3NfXCIgKyBhdHRyXShwcm9jZXNzZWRfdmFsdWUpO1xuICAgICAgfVxuXG4gICAgICBwcm9jZXNzZWRfdmFsdWVzID0gcHJvY2Vzc2VkX3ZhbHVlcy5jb25jYXQocHJvY2Vzc2VkX3ZhbHVlKTtcbiAgICB9XG5cbiAgICByZXR1cm4gcHJvY2Vzc2VkX3ZhbHVlcztcbiAgfVxuXG4gIHByb2Nlc3NfaW50ZWdlcih2YWx1ZSkge1xuICAgIHJldHVybiB2YWx1ZS52YWx1ZTtcbiAgfVxuXG4gIHByb2Nlc3NfZmxvYXQodmFsdWUpIHtcbiAgICBpZiAodmFsdWUuc2l6ZSA9PT0gNjQpIHtcbiAgICAgIHJldHVybiBCaXRTdHJpbmcuZmxvYXQ2NFRvQnl0ZXModmFsdWUudmFsdWUpO1xuICAgIH0gZWxzZSBpZiAodmFsdWUuc2l6ZSA9PT0gMzIpIHtcbiAgICAgIHJldHVybiBCaXRTdHJpbmcuZmxvYXQzMlRvQnl0ZXModmFsdWUudmFsdWUpO1xuICAgIH1cblxuICAgIHRocm93IG5ldyBFcnJvcihcIkludmFsaWQgc2l6ZSBmb3IgZmxvYXRcIik7XG4gIH1cblxuICBwcm9jZXNzX2JpdHN0cmluZyh2YWx1ZSkge1xuICAgIHJldHVybiB2YWx1ZS52YWx1ZS52YWx1ZTtcbiAgfVxuXG4gIHByb2Nlc3NfYmluYXJ5KHZhbHVlKSB7XG4gICAgcmV0dXJuIEJpdFN0cmluZy50b1VURjhBcnJheSh2YWx1ZS52YWx1ZSk7XG4gIH1cblxuICBwcm9jZXNzX3V0ZjgodmFsdWUpIHtcbiAgICByZXR1cm4gQml0U3RyaW5nLnRvVVRGOEFycmF5KHZhbHVlLnZhbHVlKTtcbiAgfVxuXG4gIHByb2Nlc3NfdXRmMTYodmFsdWUpIHtcbiAgICByZXR1cm4gQml0U3RyaW5nLnRvVVRGMTZBcnJheSh2YWx1ZS52YWx1ZSk7XG4gIH1cblxuICBwcm9jZXNzX3V0ZjMyKHZhbHVlKSB7XG4gICAgcmV0dXJuIEJpdFN0cmluZy50b1VURjMyQXJyYXkodmFsdWUudmFsdWUpO1xuICB9XG5cbiAgcHJvY2Vzc19zaWduZWQodmFsdWUpIHtcbiAgICByZXR1cm4gbmV3IFVpbnQ4QXJyYXkoW3ZhbHVlXSlbMF07XG4gIH1cblxuICBwcm9jZXNzX3Vuc2lnbmVkKHZhbHVlKSB7XG4gICAgcmV0dXJuIHZhbHVlO1xuICB9XG5cbiAgcHJvY2Vzc19uYXRpdmUodmFsdWUpIHtcbiAgICByZXR1cm4gdmFsdWU7XG4gIH1cblxuICBwcm9jZXNzX2JpZyh2YWx1ZSkge1xuICAgIHJldHVybiB2YWx1ZTtcbiAgfVxuXG4gIHByb2Nlc3NfbGl0dGxlKHZhbHVlKSB7XG4gICAgcmV0dXJuIHZhbHVlLnJldmVyc2UoKTtcbiAgfVxuXG4gIHByb2Nlc3Nfc2l6ZSh2YWx1ZSkge1xuICAgIHJldHVybiB2YWx1ZTtcbiAgfVxuXG4gIHByb2Nlc3NfdW5pdCh2YWx1ZSkge1xuICAgIHJldHVybiB2YWx1ZTtcbiAgfVxuXG4gIHN0YXRpYyBpbnRlZ2VyKHZhbHVlKSB7XG4gICAgcmV0dXJuIEJpdFN0cmluZy53cmFwKHZhbHVlLCB7IFwidHlwZVwiOiBcImludGVnZXJcIiwgXCJ1bml0XCI6IDEsIFwic2l6ZVwiOiA4IH0pO1xuICB9XG5cbiAgc3RhdGljIGZsb2F0KHZhbHVlKSB7XG4gICAgcmV0dXJuIEJpdFN0cmluZy53cmFwKHZhbHVlLCB7IFwidHlwZVwiOiBcImZsb2F0XCIsIFwidW5pdFwiOiAxLCBcInNpemVcIjogNjQgfSk7XG4gIH1cblxuICBzdGF0aWMgYml0c3RyaW5nKHZhbHVlKSB7XG4gICAgcmV0dXJuIEJpdFN0cmluZy53cmFwKHZhbHVlLCB7IFwidHlwZVwiOiBcImJpdHN0cmluZ1wiLCBcInVuaXRcIjogMSwgXCJzaXplXCI6IHZhbHVlLmJpdF9zaXplIH0pO1xuICB9XG5cbiAgc3RhdGljIGJpdHModmFsdWUpIHtcbiAgICByZXR1cm4gQml0U3RyaW5nLmJpdHN0cmluZyh2YWx1ZSk7XG4gIH1cblxuICBzdGF0aWMgYmluYXJ5KHZhbHVlKSB7XG4gICAgcmV0dXJuIEJpdFN0cmluZy53cmFwKHZhbHVlLCB7IFwidHlwZVwiOiBcImJpbmFyeVwiLCBcInVuaXRcIjogOCwgXCJzaXplXCI6IHZhbHVlLmxlbmd0aCB9KTtcbiAgfVxuXG4gIHN0YXRpYyBieXRlcyh2YWx1ZSkge1xuICAgIHJldHVybiBCaXRTdHJpbmcuYmluYXJ5KHZhbHVlKTtcbiAgfVxuXG4gIHN0YXRpYyB1dGY4KHZhbHVlKSB7XG4gICAgcmV0dXJuIEJpdFN0cmluZy53cmFwKHZhbHVlLCB7IFwidHlwZVwiOiBcInV0ZjhcIiB9KTtcbiAgfVxuXG4gIHN0YXRpYyB1dGYxNih2YWx1ZSkge1xuICAgIHJldHVybiBCaXRTdHJpbmcud3JhcCh2YWx1ZSwgeyBcInR5cGVcIjogXCJ1dGYxNlwiIH0pO1xuICB9XG5cbiAgc3RhdGljIHV0ZjMyKHZhbHVlKSB7XG4gICAgcmV0dXJuIEJpdFN0cmluZy53cmFwKHZhbHVlLCB7IFwidHlwZVwiOiBcInV0ZjMyXCIgfSk7XG4gIH1cblxuICBzdGF0aWMgc2lnbmVkKHZhbHVlKSB7XG4gICAgcmV0dXJuIEJpdFN0cmluZy53cmFwKHZhbHVlLCB7fSwgXCJzaWduZWRcIik7XG4gIH1cblxuICBzdGF0aWMgdW5zaWduZWQodmFsdWUpIHtcbiAgICByZXR1cm4gQml0U3RyaW5nLndyYXAodmFsdWUsIHt9LCBcInVuc2lnbmVkXCIpO1xuICB9XG5cbiAgc3RhdGljIG5hdGl2ZSh2YWx1ZSkge1xuICAgIHJldHVybiBCaXRTdHJpbmcud3JhcCh2YWx1ZSwge30sIFwibmF0aXZlXCIpO1xuICB9XG5cbiAgc3RhdGljIGJpZyh2YWx1ZSkge1xuICAgIHJldHVybiBCaXRTdHJpbmcud3JhcCh2YWx1ZSwge30sIFwiYmlnXCIpO1xuICB9XG5cbiAgc3RhdGljIGxpdHRsZSh2YWx1ZSkge1xuICAgIHJldHVybiBCaXRTdHJpbmcud3JhcCh2YWx1ZSwge30sIFwibGl0dGxlXCIpO1xuICB9XG5cbiAgc3RhdGljIHNpemUodmFsdWUsIGNvdW50KSB7XG4gICAgcmV0dXJuIEJpdFN0cmluZy53cmFwKHZhbHVlLCB7IFwic2l6ZVwiOiBjb3VudCB9KTtcbiAgfVxuXG4gIHN0YXRpYyB1bml0KHZhbHVlLCBjb3VudCkge1xuICAgIHJldHVybiBCaXRTdHJpbmcud3JhcCh2YWx1ZSwgeyBcInVuaXRcIjogY291bnQgfSk7XG4gIH1cblxuICBzdGF0aWMgd3JhcCh2YWx1ZSwgb3B0LCBuZXdfYXR0cmlidXRlID0gbnVsbCkge1xuICAgIGxldCB0aGVfdmFsdWUgPSB2YWx1ZTtcblxuICAgIGlmICghKHZhbHVlIGluc3RhbmNlb2YgT2JqZWN0KSkge1xuICAgICAgdGhlX3ZhbHVlID0geyBcInZhbHVlXCI6IHZhbHVlLCBcImF0dHJpYnV0ZXNcIjogW10gfTtcbiAgICB9XG5cbiAgICB0aGVfdmFsdWUgPSBPYmplY3QuYXNzaWduKHRoZV92YWx1ZSwgb3B0KTtcblxuICAgIGlmIChuZXdfYXR0cmlidXRlKSB7XG4gICAgICB0aGVfdmFsdWUuYXR0cmlidXRlcy5wdXNoKG5ld19hdHRyaWJ1dGUpO1xuICAgIH1cblxuICAgIHJldHVybiB0aGVfdmFsdWU7XG4gIH1cblxuICBzdGF0aWMgdG9VVEY4QXJyYXkoc3RyKSB7XG4gICAgdmFyIHV0ZjggPSBbXTtcbiAgICBmb3IgKHZhciBpID0gMDsgaSA8IHN0ci5sZW5ndGg7IGkrKykge1xuICAgICAgdmFyIGNoYXJjb2RlID0gc3RyLmNoYXJDb2RlQXQoaSk7XG4gICAgICBpZiAoY2hhcmNvZGUgPCAxMjgpIHtcbiAgICAgICAgdXRmOC5wdXNoKGNoYXJjb2RlKTtcbiAgICAgIH0gZWxzZSBpZiAoY2hhcmNvZGUgPCAyMDQ4KSB7XG4gICAgICAgIHV0ZjgucHVzaCgxOTIgfCBjaGFyY29kZSA+PiA2LCAxMjggfCBjaGFyY29kZSAmIDYzKTtcbiAgICAgIH0gZWxzZSBpZiAoY2hhcmNvZGUgPCA1NTI5NiB8fCBjaGFyY29kZSA+PSA1NzM0NCkge1xuICAgICAgICB1dGY4LnB1c2goMjI0IHwgY2hhcmNvZGUgPj4gMTIsIDEyOCB8IGNoYXJjb2RlID4+IDYgJiA2MywgMTI4IHwgY2hhcmNvZGUgJiA2Myk7XG4gICAgICB9XG4gICAgICAvLyBzdXJyb2dhdGUgcGFpclxuICAgICAgZWxzZSB7XG4gICAgICAgIGkrKztcbiAgICAgICAgLy8gVVRGLTE2IGVuY29kZXMgMHgxMDAwMC0weDEwRkZGRiBieVxuICAgICAgICAvLyBzdWJ0cmFjdGluZyAweDEwMDAwIGFuZCBzcGxpdHRpbmcgdGhlXG4gICAgICAgIC8vIDIwIGJpdHMgb2YgMHgwLTB4RkZGRkYgaW50byB0d28gaGFsdmVzXG4gICAgICAgIGNoYXJjb2RlID0gNjU1MzYgKyAoKGNoYXJjb2RlICYgMTAyMykgPDwgMTAgfCBzdHIuY2hhckNvZGVBdChpKSAmIDEwMjMpO1xuICAgICAgICB1dGY4LnB1c2goMjQwIHwgY2hhcmNvZGUgPj4gMTgsIDEyOCB8IGNoYXJjb2RlID4+IDEyICYgNjMsIDEyOCB8IGNoYXJjb2RlID4+IDYgJiA2MywgMTI4IHwgY2hhcmNvZGUgJiA2Myk7XG4gICAgICB9XG4gICAgfVxuICAgIHJldHVybiB1dGY4O1xuICB9XG5cbiAgc3RhdGljIHRvVVRGMTZBcnJheShzdHIpIHtcbiAgICB2YXIgdXRmMTYgPSBbXTtcbiAgICBmb3IgKHZhciBpID0gMDsgaSA8IHN0ci5sZW5ndGg7IGkrKykge1xuICAgICAgdmFyIGNvZGVQb2ludCA9IHN0ci5jb2RlUG9pbnRBdChpKTtcblxuICAgICAgaWYgKGNvZGVQb2ludCA8PSAyNTUpIHtcbiAgICAgICAgdXRmMTYucHVzaCgwKTtcbiAgICAgICAgdXRmMTYucHVzaChjb2RlUG9pbnQpO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgdXRmMTYucHVzaChjb2RlUG9pbnQgPj4gOCAmIDI1NSk7XG4gICAgICAgIHV0ZjE2LnB1c2goY29kZVBvaW50ICYgMjU1KTtcbiAgICAgIH1cbiAgICB9XG4gICAgcmV0dXJuIHV0ZjE2O1xuICB9XG5cbiAgc3RhdGljIHRvVVRGMzJBcnJheShzdHIpIHtcbiAgICB2YXIgdXRmMzIgPSBbXTtcbiAgICBmb3IgKHZhciBpID0gMDsgaSA8IHN0ci5sZW5ndGg7IGkrKykge1xuICAgICAgdmFyIGNvZGVQb2ludCA9IHN0ci5jb2RlUG9pbnRBdChpKTtcblxuICAgICAgaWYgKGNvZGVQb2ludCA8PSAyNTUpIHtcbiAgICAgICAgdXRmMzIucHVzaCgwKTtcbiAgICAgICAgdXRmMzIucHVzaCgwKTtcbiAgICAgICAgdXRmMzIucHVzaCgwKTtcbiAgICAgICAgdXRmMzIucHVzaChjb2RlUG9pbnQpO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgdXRmMzIucHVzaCgwKTtcbiAgICAgICAgdXRmMzIucHVzaCgwKTtcbiAgICAgICAgdXRmMzIucHVzaChjb2RlUG9pbnQgPj4gOCAmIDI1NSk7XG4gICAgICAgIHV0ZjMyLnB1c2goY29kZVBvaW50ICYgMjU1KTtcbiAgICAgIH1cbiAgICB9XG4gICAgcmV0dXJuIHV0ZjMyO1xuICB9XG5cbiAgLy9odHRwOi8vc3RhY2tvdmVyZmxvdy5jb20vcXVlc3Rpb25zLzIwMDM0OTMvamF2YXNjcmlwdC1mbG9hdC1mcm9tLXRvLWJpdHNcbiAgc3RhdGljIGZsb2F0MzJUb0J5dGVzKGYpIHtcbiAgICB2YXIgYnl0ZXMgPSBbXTtcblxuICAgIHZhciBidWYgPSBuZXcgQXJyYXlCdWZmZXIoNCk7XG4gICAgbmV3IEZsb2F0MzJBcnJheShidWYpWzBdID0gZjtcblxuICAgIGxldCBpbnRWZXJzaW9uID0gbmV3IFVpbnQzMkFycmF5KGJ1ZilbMF07XG5cbiAgICBieXRlcy5wdXNoKGludFZlcnNpb24gPj4gMjQgJiAyNTUpO1xuICAgIGJ5dGVzLnB1c2goaW50VmVyc2lvbiA+PiAxNiAmIDI1NSk7XG4gICAgYnl0ZXMucHVzaChpbnRWZXJzaW9uID4+IDggJiAyNTUpO1xuICAgIGJ5dGVzLnB1c2goaW50VmVyc2lvbiAmIDI1NSk7XG5cbiAgICByZXR1cm4gYnl0ZXM7XG4gIH1cblxuICBzdGF0aWMgZmxvYXQ2NFRvQnl0ZXMoZikge1xuICAgIHZhciBieXRlcyA9IFtdO1xuXG4gICAgdmFyIGJ1ZiA9IG5ldyBBcnJheUJ1ZmZlcig4KTtcbiAgICBuZXcgRmxvYXQ2NEFycmF5KGJ1ZilbMF0gPSBmO1xuXG4gICAgdmFyIGludFZlcnNpb24xID0gbmV3IFVpbnQzMkFycmF5KGJ1ZilbMF07XG4gICAgdmFyIGludFZlcnNpb24yID0gbmV3IFVpbnQzMkFycmF5KGJ1ZilbMV07XG5cbiAgICBieXRlcy5wdXNoKGludFZlcnNpb24yID4+IDI0ICYgMjU1KTtcbiAgICBieXRlcy5wdXNoKGludFZlcnNpb24yID4+IDE2ICYgMjU1KTtcbiAgICBieXRlcy5wdXNoKGludFZlcnNpb24yID4+IDggJiAyNTUpO1xuICAgIGJ5dGVzLnB1c2goaW50VmVyc2lvbjIgJiAyNTUpO1xuXG4gICAgYnl0ZXMucHVzaChpbnRWZXJzaW9uMSA+PiAyNCAmIDI1NSk7XG4gICAgYnl0ZXMucHVzaChpbnRWZXJzaW9uMSA+PiAxNiAmIDI1NSk7XG4gICAgYnl0ZXMucHVzaChpbnRWZXJzaW9uMSA+PiA4ICYgMjU1KTtcbiAgICBieXRlcy5wdXNoKGludFZlcnNpb24xICYgMjU1KTtcblxuICAgIHJldHVybiBieXRlcztcbiAgfVxufVxuXG4vKiBAZmxvdyAqL1xuXG5jbGFzcyBWYXJpYWJsZSB7XG5cbiAgY29uc3RydWN0b3IobmFtZSA9IG51bGwpIHtcbiAgICB0aGlzLm5hbWUgPSBuYW1lO1xuICB9XG59XG5cbmNsYXNzIFdpbGRjYXJkIHtcbiAgY29uc3RydWN0b3IoKSB7fVxufVxuXG5jbGFzcyBTdGFydHNXaXRoIHtcblxuICBjb25zdHJ1Y3RvcihwcmVmaXgpIHtcbiAgICB0aGlzLnByZWZpeCA9IHByZWZpeDtcbiAgfVxufVxuXG5jbGFzcyBDYXB0dXJlIHtcblxuICBjb25zdHJ1Y3Rvcih2YWx1ZSkge1xuICAgIHRoaXMudmFsdWUgPSB2YWx1ZTtcbiAgfVxufVxuXG5jbGFzcyBIZWFkVGFpbCB7XG5cbiAgY29uc3RydWN0b3IoaGVhZCA9IG51bGwsIHRhaWwgPSBudWxsKSB7XG4gICAgdGhpcy5oZWFkID0gaGVhZDtcbiAgICB0aGlzLnRhaWwgPSB0YWlsO1xuICB9XG59XG5cbmNsYXNzIFR5cGUge1xuXG4gIGNvbnN0cnVjdG9yKHR5cGUsIG9ialBhdHRlcm4gPSB7fSkge1xuICAgIHRoaXMudHlwZSA9IHR5cGU7XG4gICAgdGhpcy5vYmpQYXR0ZXJuID0gb2JqUGF0dGVybjtcbiAgfVxufVxuXG5jbGFzcyBCb3VuZCB7XG5cbiAgY29uc3RydWN0b3IodmFsdWUpIHtcbiAgICB0aGlzLnZhbHVlID0gdmFsdWU7XG4gIH1cbn1cblxuZnVuY3Rpb24gdmFyaWFibGUobmFtZSA9IG51bGwpIHtcbiAgcmV0dXJuIG5ldyBWYXJpYWJsZShuYW1lKTtcbn1cblxuZnVuY3Rpb24gd2lsZGNhcmQoKSB7XG4gIHJldHVybiBuZXcgV2lsZGNhcmQoKTtcbn1cblxuZnVuY3Rpb24gc3RhcnRzV2l0aChwcmVmaXgpIHtcbiAgcmV0dXJuIG5ldyBTdGFydHNXaXRoKHByZWZpeCk7XG59XG5cbmZ1bmN0aW9uIGNhcHR1cmUodmFsdWUpIHtcbiAgcmV0dXJuIG5ldyBDYXB0dXJlKHZhbHVlKTtcbn1cblxuZnVuY3Rpb24gaGVhZFRhaWwoaGVhZCA9IG51bGwsIHRhaWwgPSBudWxsKSB7XG4gIHJldHVybiBuZXcgSGVhZFRhaWwoaGVhZCwgdGFpbCk7XG59XG5cbmZ1bmN0aW9uIHR5cGUodHlwZSwgb2JqUGF0dGVybiA9IHt9KSB7XG4gIHJldHVybiBuZXcgVHlwZSh0eXBlLCBvYmpQYXR0ZXJuKTtcbn1cblxuZnVuY3Rpb24gYm91bmQodmFsdWUpIHtcbiAgcmV0dXJuIG5ldyBCb3VuZCh2YWx1ZSk7XG59XG5cbmZ1bmN0aW9uIGlzX251bWJlcih2YWx1ZSkge1xuICByZXR1cm4gdHlwZW9mIHZhbHVlID09PSAnbnVtYmVyJztcbn1cblxuZnVuY3Rpb24gaXNfc3RyaW5nKHZhbHVlKSB7XG4gIHJldHVybiB0eXBlb2YgdmFsdWUgPT09ICdzdHJpbmcnO1xufVxuXG5mdW5jdGlvbiBpc19ib29sZWFuKHZhbHVlKSB7XG4gIHJldHVybiB0eXBlb2YgdmFsdWUgPT09ICdib29sZWFuJztcbn1cblxuZnVuY3Rpb24gaXNfc3ltYm9sKHZhbHVlKSB7XG4gIHJldHVybiB0eXBlb2YgdmFsdWUgPT09ICdzeW1ib2wnO1xufVxuXG5mdW5jdGlvbiBpc19udWxsKHZhbHVlKSB7XG4gIHJldHVybiB2YWx1ZSA9PT0gbnVsbDtcbn1cblxuZnVuY3Rpb24gaXNfdW5kZWZpbmVkKHZhbHVlKSB7XG4gIHJldHVybiB0eXBlb2YgdmFsdWUgPT09ICd1bmRlZmluZWQnO1xufVxuXG5mdW5jdGlvbiBpc19mdW5jdGlvbih2YWx1ZSkge1xuICByZXR1cm4gT2JqZWN0LnByb3RvdHlwZS50b1N0cmluZy5jYWxsKHZhbHVlKSA9PSAnW29iamVjdCBGdW5jdGlvbl0nO1xufVxuXG5mdW5jdGlvbiBpc192YXJpYWJsZSh2YWx1ZSkge1xuICByZXR1cm4gdmFsdWUgaW5zdGFuY2VvZiBWYXJpYWJsZTtcbn1cblxuZnVuY3Rpb24gaXNfd2lsZGNhcmQodmFsdWUpIHtcbiAgcmV0dXJuIHZhbHVlIGluc3RhbmNlb2YgV2lsZGNhcmQ7XG59XG5cbmZ1bmN0aW9uIGlzX2hlYWRUYWlsKHZhbHVlKSB7XG4gIHJldHVybiB2YWx1ZSBpbnN0YW5jZW9mIEhlYWRUYWlsO1xufVxuXG5mdW5jdGlvbiBpc19jYXB0dXJlKHZhbHVlKSB7XG4gIHJldHVybiB2YWx1ZSBpbnN0YW5jZW9mIENhcHR1cmU7XG59XG5cbmZ1bmN0aW9uIGlzX3R5cGUodmFsdWUpIHtcbiAgcmV0dXJuIHZhbHVlIGluc3RhbmNlb2YgVHlwZTtcbn1cblxuZnVuY3Rpb24gaXNfc3RhcnRzV2l0aCh2YWx1ZSkge1xuICByZXR1cm4gdmFsdWUgaW5zdGFuY2VvZiBTdGFydHNXaXRoO1xufVxuXG5mdW5jdGlvbiBpc19ib3VuZCh2YWx1ZSkge1xuICByZXR1cm4gdmFsdWUgaW5zdGFuY2VvZiBCb3VuZDtcbn1cblxuZnVuY3Rpb24gaXNfb2JqZWN0KHZhbHVlKSB7XG4gIHJldHVybiB0eXBlb2YgdmFsdWUgPT09ICdvYmplY3QnO1xufVxuXG5mdW5jdGlvbiBpc19hcnJheSh2YWx1ZSkge1xuICByZXR1cm4gQXJyYXkuaXNBcnJheSh2YWx1ZSk7XG59XG5cbnZhciBDaGVja3MgPSB7XG4gIGlzX251bWJlcixcbiAgaXNfc3RyaW5nLFxuICBpc19ib29sZWFuLFxuICBpc19zeW1ib2wsXG4gIGlzX251bGwsXG4gIGlzX3VuZGVmaW5lZCxcbiAgaXNfZnVuY3Rpb24sXG4gIGlzX3ZhcmlhYmxlLFxuICBpc193aWxkY2FyZCxcbiAgaXNfaGVhZFRhaWwsXG4gIGlzX2NhcHR1cmUsXG4gIGlzX3R5cGUsXG4gIGlzX3N0YXJ0c1dpdGgsXG4gIGlzX2JvdW5kLFxuICBpc19vYmplY3QsXG4gIGlzX2FycmF5XG59O1xuXG5mdW5jdGlvbiByZXNvbHZlU3ltYm9sKHBhdHRlcm4pIHtcbiAgcmV0dXJuIGZ1bmN0aW9uICh2YWx1ZSkge1xuICAgIHJldHVybiBDaGVja3MuaXNfc3ltYm9sKHZhbHVlKSAmJiB2YWx1ZSA9PT0gcGF0dGVybjtcbiAgfTtcbn1cblxuZnVuY3Rpb24gcmVzb2x2ZVN0cmluZyhwYXR0ZXJuKSB7XG4gIHJldHVybiBmdW5jdGlvbiAodmFsdWUpIHtcbiAgICByZXR1cm4gQ2hlY2tzLmlzX3N0cmluZyh2YWx1ZSkgJiYgdmFsdWUgPT09IHBhdHRlcm47XG4gIH07XG59XG5cbmZ1bmN0aW9uIHJlc29sdmVOdW1iZXIocGF0dGVybikge1xuICByZXR1cm4gZnVuY3Rpb24gKHZhbHVlKSB7XG4gICAgcmV0dXJuIENoZWNrcy5pc19udW1iZXIodmFsdWUpICYmIHZhbHVlID09PSBwYXR0ZXJuO1xuICB9O1xufVxuXG5mdW5jdGlvbiByZXNvbHZlQm9vbGVhbihwYXR0ZXJuKSB7XG4gIHJldHVybiBmdW5jdGlvbiAodmFsdWUpIHtcbiAgICByZXR1cm4gQ2hlY2tzLmlzX2Jvb2xlYW4odmFsdWUpICYmIHZhbHVlID09PSBwYXR0ZXJuO1xuICB9O1xufVxuXG5mdW5jdGlvbiByZXNvbHZlRnVuY3Rpb24ocGF0dGVybikge1xuICByZXR1cm4gZnVuY3Rpb24gKHZhbHVlKSB7XG4gICAgcmV0dXJuIENoZWNrcy5pc19mdW5jdGlvbih2YWx1ZSkgJiYgdmFsdWUgPT09IHBhdHRlcm47XG4gIH07XG59XG5cbmZ1bmN0aW9uIHJlc29sdmVOdWxsKHBhdHRlcm4pIHtcbiAgcmV0dXJuIGZ1bmN0aW9uICh2YWx1ZSkge1xuICAgIHJldHVybiBDaGVja3MuaXNfbnVsbCh2YWx1ZSk7XG4gIH07XG59XG5cbmZ1bmN0aW9uIHJlc29sdmVCb3VuZChwYXR0ZXJuKSB7XG4gIHJldHVybiBmdW5jdGlvbiAodmFsdWUsIGFyZ3MpIHtcbiAgICBpZiAodHlwZW9mIHZhbHVlID09PSB0eXBlb2YgcGF0dGVybi52YWx1ZSAmJiB2YWx1ZSA9PT0gcGF0dGVybi52YWx1ZSkge1xuICAgICAgYXJncy5wdXNoKHZhbHVlKTtcbiAgICAgIHJldHVybiB0cnVlO1xuICAgIH1cblxuICAgIHJldHVybiBmYWxzZTtcbiAgfTtcbn1cblxuZnVuY3Rpb24gcmVzb2x2ZVdpbGRjYXJkKCkge1xuICByZXR1cm4gZnVuY3Rpb24gKCkge1xuICAgIHJldHVybiB0cnVlO1xuICB9O1xufVxuXG5mdW5jdGlvbiByZXNvbHZlVmFyaWFibGUoKSB7XG4gIHJldHVybiBmdW5jdGlvbiAodmFsdWUsIGFyZ3MpIHtcbiAgICBhcmdzLnB1c2godmFsdWUpO1xuICAgIHJldHVybiB0cnVlO1xuICB9O1xufVxuXG5mdW5jdGlvbiByZXNvbHZlSGVhZFRhaWwocGF0dGVybikge1xuICBjb25zdCBoZWFkTWF0Y2hlcyA9IGJ1aWxkTWF0Y2gocGF0dGVybi5oZWFkKTtcbiAgY29uc3QgdGFpbE1hdGNoZXMgPSBidWlsZE1hdGNoKHBhdHRlcm4udGFpbCk7XG5cbiAgcmV0dXJuIGZ1bmN0aW9uICh2YWx1ZSwgYXJncykge1xuICAgIGlmICghQ2hlY2tzLmlzX2FycmF5KHZhbHVlKSB8fCB2YWx1ZS5sZW5ndGggPCAyKSB7XG4gICAgICByZXR1cm4gZmFsc2U7XG4gICAgfVxuXG4gICAgY29uc3QgaGVhZCA9IHZhbHVlWzBdO1xuICAgIGNvbnN0IHRhaWwgPSB2YWx1ZS5zbGljZSgxKTtcblxuICAgIGlmIChoZWFkTWF0Y2hlcyhoZWFkLCBhcmdzKSAmJiB0YWlsTWF0Y2hlcyh0YWlsLCBhcmdzKSkge1xuICAgICAgcmV0dXJuIHRydWU7XG4gICAgfVxuICB9O1xufVxuXG5mdW5jdGlvbiByZXNvbHZlQ2FwdHVyZShwYXR0ZXJuKSB7XG4gIGNvbnN0IG1hdGNoZXMgPSBidWlsZE1hdGNoKHBhdHRlcm4udmFsdWUpO1xuXG4gIHJldHVybiBmdW5jdGlvbiAodmFsdWUsIGFyZ3MpIHtcbiAgICBpZiAobWF0Y2hlcyh2YWx1ZSwgYXJncykpIHtcbiAgICAgIGFyZ3MucHVzaCh2YWx1ZSk7XG4gICAgICByZXR1cm4gdHJ1ZTtcbiAgICB9XG5cbiAgICByZXR1cm4gZmFsc2U7XG4gIH07XG59XG5cbmZ1bmN0aW9uIHJlc29sdmVTdGFydHNXaXRoKHBhdHRlcm4pIHtcbiAgY29uc3QgcHJlZml4ID0gcGF0dGVybi5wcmVmaXg7XG5cbiAgcmV0dXJuIGZ1bmN0aW9uICh2YWx1ZSwgYXJncykge1xuICAgIGlmIChDaGVja3MuaXNfc3RyaW5nKHZhbHVlKSAmJiB2YWx1ZS5zdGFydHNXaXRoKHByZWZpeCkpIHtcbiAgICAgIGFyZ3MucHVzaCh2YWx1ZS5zdWJzdHJpbmcocHJlZml4Lmxlbmd0aCkpO1xuICAgICAgcmV0dXJuIHRydWU7XG4gICAgfVxuXG4gICAgcmV0dXJuIGZhbHNlO1xuICB9O1xufVxuXG5mdW5jdGlvbiByZXNvbHZlVHlwZShwYXR0ZXJuKSB7XG4gIHJldHVybiBmdW5jdGlvbiAodmFsdWUsIGFyZ3MpIHtcbiAgICBpZiAodmFsdWUgaW5zdGFuY2VvZiBwYXR0ZXJuLnR5cGUpIHtcbiAgICAgIGNvbnN0IG1hdGNoZXMgPSBidWlsZE1hdGNoKHBhdHRlcm4ub2JqUGF0dGVybik7XG4gICAgICByZXR1cm4gbWF0Y2hlcyh2YWx1ZSwgYXJncykgJiYgYXJncy5wdXNoKHZhbHVlKSA+IDA7XG4gICAgfVxuXG4gICAgcmV0dXJuIGZhbHNlO1xuICB9O1xufVxuXG5mdW5jdGlvbiByZXNvbHZlQXJyYXkocGF0dGVybikge1xuICBjb25zdCBtYXRjaGVzID0gcGF0dGVybi5tYXAoeCA9PiBidWlsZE1hdGNoKHgpKTtcblxuICByZXR1cm4gZnVuY3Rpb24gKHZhbHVlLCBhcmdzKSB7XG4gICAgaWYgKCFDaGVja3MuaXNfYXJyYXkodmFsdWUpIHx8IHZhbHVlLmxlbmd0aCAhPSBwYXR0ZXJuLmxlbmd0aCkge1xuICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH1cblxuICAgIHJldHVybiB2YWx1ZS5ldmVyeShmdW5jdGlvbiAodiwgaSkge1xuICAgICAgcmV0dXJuIG1hdGNoZXNbaV0odmFsdWVbaV0sIGFyZ3MpO1xuICAgIH0pO1xuICB9O1xufVxuXG5mdW5jdGlvbiByZXNvbHZlT2JqZWN0KHBhdHRlcm4pIHtcbiAgbGV0IG1hdGNoZXMgPSB7fTtcblxuICBmb3IgKGxldCBrZXkgb2YgT2JqZWN0LmtleXMocGF0dGVybikuY29uY2F0KE9iamVjdC5nZXRPd25Qcm9wZXJ0eVN5bWJvbHMocGF0dGVybikpKSB7XG4gICAgbWF0Y2hlc1trZXldID0gYnVpbGRNYXRjaChwYXR0ZXJuW2tleV0pO1xuICB9XG5cbiAgcmV0dXJuIGZ1bmN0aW9uICh2YWx1ZSwgYXJncykge1xuICAgIGlmICghQ2hlY2tzLmlzX29iamVjdCh2YWx1ZSkgfHwgcGF0dGVybi5sZW5ndGggPiB2YWx1ZS5sZW5ndGgpIHtcbiAgICAgIHJldHVybiBmYWxzZTtcbiAgICB9XG5cbiAgICBmb3IgKGxldCBrZXkgb2YgT2JqZWN0LmtleXMocGF0dGVybikuY29uY2F0KE9iamVjdC5nZXRPd25Qcm9wZXJ0eVN5bWJvbHMocGF0dGVybikpKSB7XG4gICAgICBpZiAoIShrZXkgaW4gdmFsdWUpIHx8ICFtYXRjaGVzW2tleV0odmFsdWVba2V5XSwgYXJncykpIHtcbiAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgfVxuICAgIH1cblxuICAgIHJldHVybiB0cnVlO1xuICB9O1xufVxuXG5mdW5jdGlvbiByZXNvbHZlTm9NYXRjaCgpIHtcbiAgcmV0dXJuIGZ1bmN0aW9uICgpIHtcbiAgICByZXR1cm4gZmFsc2U7XG4gIH07XG59XG5cbnZhciBSZXNvbHZlcnMgPSB7XG4gIHJlc29sdmVCb3VuZCxcbiAgcmVzb2x2ZVdpbGRjYXJkLFxuICByZXNvbHZlVmFyaWFibGUsXG4gIHJlc29sdmVIZWFkVGFpbCxcbiAgcmVzb2x2ZUNhcHR1cmUsXG4gIHJlc29sdmVTdGFydHNXaXRoLFxuICByZXNvbHZlVHlwZSxcbiAgcmVzb2x2ZUFycmF5LFxuICByZXNvbHZlT2JqZWN0LFxuICByZXNvbHZlTm9NYXRjaCxcbiAgcmVzb2x2ZVN5bWJvbCxcbiAgcmVzb2x2ZVN0cmluZyxcbiAgcmVzb2x2ZU51bWJlcixcbiAgcmVzb2x2ZUJvb2xlYW4sXG4gIHJlc29sdmVGdW5jdGlvbixcbiAgcmVzb2x2ZU51bGxcbn07XG5cbmZ1bmN0aW9uIGJ1aWxkTWF0Y2gocGF0dGVybikge1xuXG4gIGlmIChDaGVja3MuaXNfdmFyaWFibGUocGF0dGVybikpIHtcbiAgICByZXR1cm4gUmVzb2x2ZXJzLnJlc29sdmVWYXJpYWJsZShwYXR0ZXJuKTtcbiAgfVxuXG4gIGlmIChDaGVja3MuaXNfd2lsZGNhcmQocGF0dGVybikpIHtcbiAgICByZXR1cm4gUmVzb2x2ZXJzLnJlc29sdmVXaWxkY2FyZChwYXR0ZXJuKTtcbiAgfVxuXG4gIGlmIChDaGVja3MuaXNfdW5kZWZpbmVkKHBhdHRlcm4pKSB7XG4gICAgcmV0dXJuIFJlc29sdmVycy5yZXNvbHZlV2lsZGNhcmQocGF0dGVybik7XG4gIH1cblxuICBpZiAoQ2hlY2tzLmlzX2hlYWRUYWlsKHBhdHRlcm4pKSB7XG4gICAgcmV0dXJuIFJlc29sdmVycy5yZXNvbHZlSGVhZFRhaWwocGF0dGVybik7XG4gIH1cblxuICBpZiAoQ2hlY2tzLmlzX3N0YXJ0c1dpdGgocGF0dGVybikpIHtcbiAgICByZXR1cm4gUmVzb2x2ZXJzLnJlc29sdmVTdGFydHNXaXRoKHBhdHRlcm4pO1xuICB9XG5cbiAgaWYgKENoZWNrcy5pc19jYXB0dXJlKHBhdHRlcm4pKSB7XG4gICAgcmV0dXJuIFJlc29sdmVycy5yZXNvbHZlQ2FwdHVyZShwYXR0ZXJuKTtcbiAgfVxuXG4gIGlmIChDaGVja3MuaXNfYm91bmQocGF0dGVybikpIHtcbiAgICByZXR1cm4gUmVzb2x2ZXJzLnJlc29sdmVCb3VuZChwYXR0ZXJuKTtcbiAgfVxuXG4gIGlmIChDaGVja3MuaXNfdHlwZShwYXR0ZXJuKSkge1xuICAgIHJldHVybiBSZXNvbHZlcnMucmVzb2x2ZVR5cGUocGF0dGVybik7XG4gIH1cblxuICBpZiAoQ2hlY2tzLmlzX2FycmF5KHBhdHRlcm4pKSB7XG4gICAgcmV0dXJuIFJlc29sdmVycy5yZXNvbHZlQXJyYXkocGF0dGVybik7XG4gIH1cblxuICBpZiAoQ2hlY2tzLmlzX251bWJlcihwYXR0ZXJuKSkge1xuICAgIHJldHVybiBSZXNvbHZlcnMucmVzb2x2ZU51bWJlcihwYXR0ZXJuKTtcbiAgfVxuXG4gIGlmIChDaGVja3MuaXNfc3RyaW5nKHBhdHRlcm4pKSB7XG4gICAgcmV0dXJuIFJlc29sdmVycy5yZXNvbHZlU3RyaW5nKHBhdHRlcm4pO1xuICB9XG5cbiAgaWYgKENoZWNrcy5pc19ib29sZWFuKHBhdHRlcm4pKSB7XG4gICAgcmV0dXJuIFJlc29sdmVycy5yZXNvbHZlQm9vbGVhbihwYXR0ZXJuKTtcbiAgfVxuXG4gIGlmIChDaGVja3MuaXNfc3ltYm9sKHBhdHRlcm4pKSB7XG4gICAgcmV0dXJuIFJlc29sdmVycy5yZXNvbHZlU3ltYm9sKHBhdHRlcm4pO1xuICB9XG5cbiAgaWYgKENoZWNrcy5pc19udWxsKHBhdHRlcm4pKSB7XG4gICAgcmV0dXJuIFJlc29sdmVycy5yZXNvbHZlTnVsbChwYXR0ZXJuKTtcbiAgfVxuXG4gIGlmIChDaGVja3MuaXNfb2JqZWN0KHBhdHRlcm4pKSB7XG4gICAgcmV0dXJuIFJlc29sdmVycy5yZXNvbHZlT2JqZWN0KHBhdHRlcm4pO1xuICB9XG5cbiAgcmV0dXJuIFJlc29sdmVycy5yZXNvbHZlTm9NYXRjaCgpO1xufVxuXG5jbGFzcyBNYXRjaEVycm9yIGV4dGVuZHMgRXJyb3Ige1xuICBjb25zdHJ1Y3RvcihhcmcpIHtcbiAgICBzdXBlcigpO1xuXG4gICAgaWYgKHR5cGVvZiBhcmcgPT09ICdzeW1ib2wnKSB7XG4gICAgICB0aGlzLm1lc3NhZ2UgPSAnTm8gbWF0Y2ggZm9yOiAnICsgYXJnLnRvU3RyaW5nKCk7XG4gICAgfSBlbHNlIGlmIChBcnJheS5pc0FycmF5KGFyZykpIHtcbiAgICAgIGxldCBtYXBwZWRWYWx1ZXMgPSBhcmcubWFwKHggPT4geC50b1N0cmluZygpKTtcbiAgICAgIHRoaXMubWVzc2FnZSA9ICdObyBtYXRjaCBmb3I6ICcgKyBtYXBwZWRWYWx1ZXM7XG4gICAgfSBlbHNlIHtcbiAgICAgIHRoaXMubWVzc2FnZSA9ICdObyBtYXRjaCBmb3I6ICcgKyBhcmc7XG4gICAgfVxuXG4gICAgdGhpcy5zdGFjayA9IG5ldyBFcnJvcigpLnN0YWNrO1xuICAgIHRoaXMubmFtZSA9IHRoaXMuY29uc3RydWN0b3IubmFtZTtcbiAgfVxufVxuXG5jbGFzcyBDYXNlIHtcblxuICBjb25zdHJ1Y3RvcihwYXR0ZXJuLCBmbiwgZ3VhcmQgPSAoKSA9PiB0cnVlKSB7XG4gICAgdGhpcy5wYXR0ZXJuID0gYnVpbGRNYXRjaChwYXR0ZXJuKTtcbiAgICB0aGlzLmZuID0gZm47XG4gICAgdGhpcy5ndWFyZCA9IGd1YXJkO1xuICB9XG59XG5cbmZ1bmN0aW9uIG1ha2VfY2FzZShwYXR0ZXJuLCBmbiwgZ3VhcmQgPSAoKSA9PiB0cnVlKSB7XG4gIHJldHVybiBuZXcgQ2FzZShwYXR0ZXJuLCBmbiwgZ3VhcmQpO1xufVxuXG5mdW5jdGlvbiBkZWZtYXRjaCguLi5jYXNlcykge1xuICByZXR1cm4gZnVuY3Rpb24gKC4uLmFyZ3MpIHtcbiAgICBmb3IgKGxldCBwcm9jZXNzZWRDYXNlIG9mIGNhc2VzKSB7XG4gICAgICBsZXQgcmVzdWx0ID0gW107XG4gICAgICBpZiAocHJvY2Vzc2VkQ2FzZS5wYXR0ZXJuKGFyZ3MsIHJlc3VsdCkgJiYgcHJvY2Vzc2VkQ2FzZS5ndWFyZC5hcHBseSh0aGlzLCByZXN1bHQpKSB7XG4gICAgICAgIHJldHVybiBwcm9jZXNzZWRDYXNlLmZuLmFwcGx5KHRoaXMsIHJlc3VsdCk7XG4gICAgICB9XG4gICAgfVxuXG4gICAgdGhyb3cgbmV3IE1hdGNoRXJyb3IoYXJncyk7XG4gIH07XG59XG5cbmZ1bmN0aW9uIG1hdGNoKHBhdHRlcm4sIGV4cHIsIGd1YXJkID0gKCkgPT4gdHJ1ZSkge1xuICBsZXQgcmVzdWx0ID0gW107XG4gIGxldCBwcm9jZXNzZWRQYXR0ZXJuID0gYnVpbGRNYXRjaChwYXR0ZXJuKTtcbiAgaWYgKHByb2Nlc3NlZFBhdHRlcm4oZXhwciwgcmVzdWx0KSAmJiBndWFyZC5hcHBseSh0aGlzLCByZXN1bHQpKSB7XG4gICAgcmV0dXJuIHJlc3VsdDtcbiAgfSBlbHNlIHtcbiAgICB0aHJvdyBuZXcgTWF0Y2hFcnJvcihleHByKTtcbiAgfVxufVxuXG5mdW5jdGlvbiBtYXRjaF9ub190aHJvdyhwYXR0ZXJuLCBleHByLCBndWFyZCA9ICgpID0+IHRydWUpIHtcbiAgdHJ5IHtcbiAgICByZXR1cm4gbWF0Y2gocGF0dGVybiwgZXhwciwgZ3VhcmQpO1xuICB9IGNhdGNoIChlKSB7XG4gICAgaWYgKGUgaW5zdGFuY2VvZiBNYXRjaEVycm9yKSB7XG4gICAgICByZXR1cm4gbnVsbDtcbiAgICB9XG5cbiAgICB0aHJvdyBlO1xuICB9XG59XG5cbnZhciBQYXR0ZXJucyA9IHtcbiAgZGVmbWF0Y2gsIG1hdGNoLCBNYXRjaEVycm9yLCBtYXRjaF9ub190aHJvdyxcbiAgdmFyaWFibGUsIHdpbGRjYXJkLCBzdGFydHNXaXRoLFxuICBjYXB0dXJlLCBoZWFkVGFpbCwgdHlwZSwgYm91bmQsIENhc2UsIG1ha2VfY2FzZVxufTtcblxuLy9odHRwczovL2dpdGh1Yi5jb20vYWlycG9ydHloL3Byb3RvbW9ycGhpc21cbmNsYXNzIFByb3RvY29sIHtcbiAgY29uc3RydWN0b3Ioc3BlYykge1xuICAgIHRoaXMucmVnaXN0cnkgPSBuZXcgTWFwKCk7XG4gICAgdGhpcy5mYWxsYmFjayA9IG51bGw7XG5cbiAgICBmb3IgKGxldCBmdW5OYW1lIGluIHNwZWMpIHtcbiAgICAgIHRoaXNbZnVuTmFtZV0gPSBjcmVhdGVGdW4oZnVuTmFtZSkuYmluZCh0aGlzKTtcbiAgICB9XG5cbiAgICBmdW5jdGlvbiBjcmVhdGVGdW4oZnVuTmFtZSkge1xuXG4gICAgICByZXR1cm4gZnVuY3Rpb24gKC4uLmFyZ3MpIHtcbiAgICAgICAgbGV0IHRoaW5nID0gYXJnc1swXTtcbiAgICAgICAgbGV0IGZ1biA9IG51bGw7XG5cbiAgICAgICAgaWYgKE51bWJlci5pc0ludGVnZXIodGhpbmcpICYmIHRoaXMuaGFzSW1wbGVtZW50YXRpb24oSW50ZWdlcikpIHtcbiAgICAgICAgICBmdW4gPSB0aGlzLnJlZ2lzdHJ5LmdldChJbnRlZ2VyKVtmdW5OYW1lXTtcbiAgICAgICAgfSBlbHNlIGlmICh0eXBlb2YgdGhpbmcgPT09IFwibnVtYmVyXCIgJiYgIU51bWJlci5pc0ludGVnZXIodGhpbmcpICYmIHRoaXMuaGFzSW1wbGVtZW50YXRpb24oRmxvYXQpKSB7XG4gICAgICAgICAgZnVuID0gdGhpcy5yZWdpc3RyeS5nZXQoRmxvYXQpW2Z1bk5hbWVdO1xuICAgICAgICB9IGVsc2UgaWYgKHRoaXMuaGFzSW1wbGVtZW50YXRpb24odGhpbmcpKSB7XG4gICAgICAgICAgZnVuID0gdGhpcy5yZWdpc3RyeS5nZXQodGhpbmcuY29uc3RydWN0b3IpW2Z1bk5hbWVdO1xuICAgICAgICB9IGVsc2UgaWYgKHRoaXMuZmFsbGJhY2spIHtcbiAgICAgICAgICBmdW4gPSB0aGlzLmZhbGxiYWNrW2Z1bk5hbWVdO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKGZ1biAhPSBudWxsKSB7XG4gICAgICAgICAgbGV0IHJldHZhbCA9IGZ1bi5hcHBseSh0aGlzLCBhcmdzKTtcbiAgICAgICAgICByZXR1cm4gcmV0dmFsO1xuICAgICAgICB9XG5cbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKFwiTm8gaW1wbGVtZW50YXRpb24gZm91bmQgZm9yIFwiICsgdGhpbmcpO1xuICAgICAgfTtcbiAgICB9XG4gIH1cblxuICBpbXBsZW1lbnRhdGlvbih0eXBlLCBpbXBsZW1lbnRhdGlvbikge1xuICAgIGlmICh0eXBlID09PSBudWxsKSB7XG4gICAgICB0aGlzLmZhbGxiYWNrID0gaW1wbGVtZW50YXRpb247XG4gICAgfSBlbHNlIHtcbiAgICAgIHRoaXMucmVnaXN0cnkuc2V0KHR5cGUsIGltcGxlbWVudGF0aW9uKTtcbiAgICB9XG4gIH1cblxuICBoYXNJbXBsZW1lbnRhdGlvbih0aGluZykge1xuICAgIHJldHVybiB0aGlzLnJlZ2lzdHJ5Lmhhcyh0aGluZy5jb25zdHJ1Y3Rvcik7XG4gIH1cbn1cblxuZnVuY3Rpb24gY2FsbF9wcm9wZXJ0eShpdGVtLCBwcm9wZXJ0eSkge1xuICBsZXQgcHJvcCA9IG51bGw7XG5cbiAgaWYgKHByb3BlcnR5IGluIGl0ZW0pIHtcbiAgICBwcm9wID0gcHJvcGVydHk7XG4gIH0gZWxzZSBpZiAoU3ltYm9sLmZvcihwcm9wZXJ0eSkgaW4gaXRlbSkge1xuICAgIHByb3AgPSBTeW1ib2wuZm9yKHByb3BlcnR5KTtcbiAgfSBlbHNlIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoYFByb3BlcnR5ICR7IHByb3BlcnR5IH0gbm90IGZvdW5kIGluICR7IGl0ZW0gfWApO1xuICB9XG5cbiAgaWYgKGl0ZW1bcHJvcF0gaW5zdGFuY2VvZiBGdW5jdGlvbikge1xuICAgIHJldHVybiBpdGVtW3Byb3BdKCk7XG4gIH0gZWxzZSB7XG4gICAgcmV0dXJuIGl0ZW1bcHJvcF07XG4gIH1cbn1cblxuZnVuY3Rpb24gYXBwbHkoLi4uYXJncykge1xuICBpZiAoYXJncy5sZW5ndGggPT09IDIpIHtcbiAgICBhcmdzWzBdLmFwcGx5KG51bGwsIGFyZ3Muc2xpY2UoMSkpO1xuICB9IGVsc2Uge1xuICAgIGFyZ3NbMF1bYXJnc1sxXV0uYXBwbHkobnVsbCwgYXJncy5zbGljZSgyKSk7XG4gIH1cbn1cblxuZnVuY3Rpb24gY29udGFpbnMobGVmdCwgcmlnaHQpIHtcbiAgZm9yIChsZXQgeCBvZiByaWdodCkge1xuICAgIGlmIChQYXR0ZXJucy5tYXRjaF9ub190aHJvdyhsZWZ0LCB4KSAhPSBudWxsKSB7XG4gICAgICByZXR1cm4gdHJ1ZTtcbiAgICB9XG4gIH1cblxuICByZXR1cm4gZmFsc2U7XG59XG5cbmZ1bmN0aW9uIGdldF9nbG9iYWwoKSB7XG4gIGlmICh0eXBlb2Ygc2VsZiAhPT0gJ3VuZGVmaW5lZCcpIHtcbiAgICByZXR1cm4gc2VsZjtcbiAgfSBlbHNlIGlmICh0eXBlb2Ygd2luZG93ICE9PSAndW5kZWZpbmVkJykge1xuICAgIHJldHVybiB3aW5kb3c7XG4gIH0gZWxzZSBpZiAodHlwZW9mIGdsb2JhbCAhPT0gJ3VuZGVmaW5lZCcpIHtcbiAgICByZXR1cm4gZ2xvYmFsO1xuICB9XG5cbiAgdGhyb3cgbmV3IEVycm9yKCdObyBnbG9iYWwgc3RhdGUgZm91bmQnKTtcbn1cblxuZnVuY3Rpb24gZGVmc3RydWN0KGRlZmF1bHRzKSB7XG4gIHJldHVybiBjbGFzcyB7XG4gICAgY29uc3RydWN0b3IodXBkYXRlID0ge30pIHtcbiAgICAgIGxldCB0aGVfdmFsdWVzID0gT2JqZWN0LmFzc2lnbihkZWZhdWx0cywgdXBkYXRlKTtcbiAgICAgIE9iamVjdC5hc3NpZ24odGhpcywgdGhlX3ZhbHVlcyk7XG4gICAgfVxuXG4gICAgc3RhdGljIGNyZWF0ZSh1cGRhdGVzID0ge30pIHtcbiAgICAgIGxldCB4ID0gbmV3IHRoaXModXBkYXRlcyk7XG4gICAgICByZXR1cm4gT2JqZWN0LmZyZWV6ZSh4KTtcbiAgICB9XG4gIH07XG59XG5cbmZ1bmN0aW9uIGRlZmV4Y2VwdGlvbihkZWZhdWx0cykge1xuICByZXR1cm4gY2xhc3MgZXh0ZW5kcyBFcnJvciB7XG4gICAgY29uc3RydWN0b3IodXBkYXRlID0ge30pIHtcbiAgICAgIGxldCBtZXNzYWdlID0gdXBkYXRlLm1lc3NhZ2UgfHwgJyc7XG4gICAgICBzdXBlcihtZXNzYWdlKTtcblxuICAgICAgbGV0IHRoZV92YWx1ZXMgPSBPYmplY3QuYXNzaWduKGRlZmF1bHRzLCB1cGRhdGUpO1xuICAgICAgT2JqZWN0LmFzc2lnbih0aGlzLCB0aGVfdmFsdWVzKTtcblxuICAgICAgdGhpcy5uYW1lID0gdGhpcy5jb25zdHJ1Y3Rvci5uYW1lO1xuICAgICAgdGhpcy5tZXNzYWdlID0gbWVzc2FnZTtcbiAgICAgIHRoaXNbU3BlY2lhbEZvcm1zLmF0b20oJ19fZXhjZXB0aW9uX18nKV0gPSB0cnVlO1xuICAgICAgRXJyb3IuY2FwdHVyZVN0YWNrVHJhY2UodGhpcywgdGhpcy5jb25zdHJ1Y3Rvci5uYW1lKTtcbiAgICB9XG5cbiAgICBzdGF0aWMgY3JlYXRlKHVwZGF0ZXMgPSB7fSkge1xuICAgICAgbGV0IHggPSBuZXcgdGhpcyh1cGRhdGVzKTtcbiAgICAgIHJldHVybiBPYmplY3QuZnJlZXplKHgpO1xuICAgIH1cbiAgfTtcbn1cblxuZnVuY3Rpb24gZGVmcHJvdG9jb2woc3BlYykge1xuICByZXR1cm4gbmV3IFByb3RvY29sKHNwZWMpO1xufVxuXG5mdW5jdGlvbiBkZWZpbXBsKHByb3RvY29sLCB0eXBlLCBpbXBsKSB7XG4gIHByb3RvY29sLmltcGxlbWVudGF0aW9uKHR5cGUsIGltcGwpO1xufVxuXG5mdW5jdGlvbiBnZXRfb2JqZWN0X2tleXMob2JqKSB7XG4gIHJldHVybiBPYmplY3Qua2V5cyhvYmopLmNvbmNhdChPYmplY3QuZ2V0T3duUHJvcGVydHlTeW1ib2xzKG9iaikpO1xufVxuXG5mdW5jdGlvbiBpc192YWxpZF9jaGFyYWN0ZXIoY29kZXBvaW50KSB7XG4gIHRyeSB7XG4gICAgcmV0dXJuIFN0cmluZy5mcm9tQ29kZVBvaW50KGNvZGVwb2ludCkgIT0gbnVsbDtcbiAgfSBjYXRjaCAoZSkge1xuICAgIHJldHVybiBmYWxzZTtcbiAgfVxufVxuXG4vL2h0dHBzOi8vZGV2ZWxvcGVyLm1vemlsbGEub3JnL2VuLVVTL2RvY3MvV2ViL0FQSS9XaW5kb3dCYXNlNjQvQmFzZTY0X2VuY29kaW5nX2FuZF9kZWNvZGluZyNTb2x1dGlvbl8yXyVFMiU4MCU5M19yZXdyaXRlX3RoZV9ET01zX2F0b2IoKV9hbmRfYnRvYSgpX3VzaW5nX0phdmFTY3JpcHQnc19UeXBlZEFycmF5c19hbmRfVVRGLThcbmZ1bmN0aW9uIGI2NEVuY29kZVVuaWNvZGUoc3RyKSB7XG4gIHJldHVybiBidG9hKGVuY29kZVVSSUNvbXBvbmVudChzdHIpLnJlcGxhY2UoLyUoWzAtOUEtRl17Mn0pL2csIGZ1bmN0aW9uIChtYXRjaCwgcDEpIHtcbiAgICByZXR1cm4gU3RyaW5nLmZyb21DaGFyQ29kZSgnMHgnICsgcDEpO1xuICB9KSk7XG59XG5cbmZ1bmN0aW9uIGRlbGV0ZV9wcm9wZXJ0eV9mcm9tX21hcChtYXAsIHByb3BlcnR5KSB7XG4gIGxldCBuZXdfbWFwID0gT2JqZWN0LmFzc2lnbihPYmplY3QuY3JlYXRlKG1hcC5jb25zdHJ1Y3Rvci5wcm90b3R5cGUpLCBtYXApO1xuICBkZWxldGUgbmV3X21hcFtwcm9wZXJ0eV07XG5cbiAgcmV0dXJuIE9iamVjdC5mcmVlemUobmV3X21hcCk7XG59XG5cbmZ1bmN0aW9uIGNsYXNzX3RvX29iaihtYXApIHtcbiAgbGV0IG5ld19tYXAgPSBPYmplY3QuYXNzaWduKHt9LCBtYXApO1xuICByZXR1cm4gT2JqZWN0LmZyZWV6ZShuZXdfbWFwKTtcbn1cblxuZnVuY3Rpb24gYWRkX3Byb3BlcnR5X3RvX21hcChtYXAsIHByb3BlcnR5LCB2YWx1ZSkge1xuICBsZXQgbmV3X21hcCA9IE9iamVjdC5hc3NpZ24oe30sIG1hcCk7XG4gIG5ld19tYXBbcHJvcGVydHldID0gdmFsdWU7XG4gIHJldHVybiBPYmplY3QuZnJlZXplKG5ld19tYXApO1xufVxuXG5mdW5jdGlvbiB1cGRhdGVfbWFwKG1hcCwgcHJvcGVydHksIHZhbHVlKSB7XG4gIGlmIChwcm9wZXJ0eSBpbiBnZXRfb2JqZWN0X2tleXMobWFwKSkge1xuICAgIHJldHVybiBhZGRfcHJvcGVydHlfdG9fbWFwKG1hcCwgcHJvcGVydHksIHZhbHVlKTtcbiAgfVxuXG4gIHRocm93ICdtYXAgZG9lcyBub3QgaGF2ZSBrZXknO1xufVxuXG5mdW5jdGlvbiBibm90KGV4cHIpIHtcbiAgcmV0dXJuIH5leHByO1xufVxuXG5mdW5jdGlvbiBiYW5kKGxlZnQsIHJpZ2h0KSB7XG4gIHJldHVybiBsZWZ0ICYgcmlnaHQ7XG59XG5cbmZ1bmN0aW9uIGJvcihsZWZ0LCByaWdodCkge1xuICByZXR1cm4gbGVmdCB8IHJpZ2h0O1xufVxuXG5mdW5jdGlvbiBic2wobGVmdCwgcmlnaHQpIHtcbiAgcmV0dXJuIGxlZnQgPDwgcmlnaHQ7XG59XG5cbmZ1bmN0aW9uIGJzcihsZWZ0LCByaWdodCkge1xuICByZXR1cm4gbGVmdCA+PiByaWdodDtcbn1cblxuZnVuY3Rpb24gYnhvcihsZWZ0LCByaWdodCkge1xuICByZXR1cm4gbGVmdCBeIHJpZ2h0O1xufVxuXG5mdW5jdGlvbiB6aXAobGlzdF9vZl9saXN0cykge1xuICBpZiAobGlzdF9vZl9saXN0cy5sZW5ndGggPT09IDApIHtcbiAgICByZXR1cm4gT2JqZWN0LmZyZWV6ZShbXSk7XG4gIH1cblxuICBsZXQgbmV3X3ZhbHVlID0gW107XG4gIGxldCBzbWFsbGVzdF9sZW5ndGggPSBsaXN0X29mX2xpc3RzWzBdO1xuXG4gIGZvciAobGV0IHggb2YgbGlzdF9vZl9saXN0cykge1xuICAgIGlmICh4Lmxlbmd0aCA8IHNtYWxsZXN0X2xlbmd0aCkge1xuICAgICAgc21hbGxlc3RfbGVuZ3RoID0geC5sZW5ndGg7XG4gICAgfVxuICB9XG5cbiAgZm9yIChsZXQgaSA9IDA7IGkgPCBzbWFsbGVzdF9sZW5ndGg7IGkrKykge1xuICAgIGxldCBjdXJyZW50X3ZhbHVlID0gW107XG4gICAgZm9yIChsZXQgaiA9IDA7IGogPCBsaXN0X29mX2xpc3RzLmxlbmd0aDsgaisrKSB7XG4gICAgICBjdXJyZW50X3ZhbHVlLnB1c2gobGlzdF9vZl9saXN0c1tqXVtpXSk7XG4gICAgfVxuXG4gICAgbmV3X3ZhbHVlLnB1c2gobmV3IFR1cGxlKC4uLmN1cnJlbnRfdmFsdWUpKTtcbiAgfVxuXG4gIHJldHVybiBPYmplY3QuZnJlZXplKG5ld192YWx1ZSk7XG59XG5cbmZ1bmN0aW9uIGNhbl9kZWNvZGU2NChkYXRhKSB7XG4gIHRyeSB7XG4gICAgYXRvYihkYXRhKTtcbiAgICByZXR1cm4gdHJ1ZTtcbiAgfSBjYXRjaCAoZSkge1xuICAgIHJldHVybiBmYWxzZTtcbiAgfVxufVxuXG5mdW5jdGlvbiByZW1vdmVfZnJvbV9saXN0KGxpc3QsIGVsZW1lbnQpIHtcbiAgbGV0IGZvdW5kID0gZmFsc2U7XG5cbiAgcmV0dXJuIGxpc3QuZmlsdGVyKGVsZW0gPT4ge1xuICAgIGlmICghZm91bmQgJiYgZWxlbSA9PT0gZWxlbWVudCkge1xuICAgICAgZm91bmQgPSB0cnVlO1xuICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH1cblxuICAgIHJldHVybiB0cnVlO1xuICB9KTtcbn1cblxuZnVuY3Rpb24gZm9sZGwoZnVuLCBhY2MsIGxpc3QpIHtcbiAgbGV0IGFjYzEgPSBhY2M7XG5cbiAgZm9yIChjb25zdCBlbCBvZiBsaXN0KSB7XG4gICAgYWNjMSA9IGZ1bihlbCwgYWNjMSk7XG4gIH1cblxuICByZXR1cm4gYWNjMTtcbn1cblxuZnVuY3Rpb24gZm9sZHIoZnVuLCBhY2MsIGxpc3QpIHtcbiAgbGV0IGFjYzEgPSBhY2M7XG5cbiAgZm9yIChsZXQgaSA9IGxpc3QubGVuZ3RoIC0gMTsgaSA+PSAwOyBpLS0pIHtcbiAgICBhY2MxID0gZnVuKGxpc3RbaV0sIGFjYzEpO1xuICB9XG5cbiAgcmV0dXJuIGFjYzE7XG59XG5cbmZ1bmN0aW9uIGtleWZpbmQoa2V5LCBuLCB0dXBsZWxpc3QpIHtcblxuICBmb3IgKGxldCBpID0gdHVwbGVsaXN0Lmxlbmd0aCAtIDE7IGkgPj0gMDsgaS0tKSB7XG4gICAgaWYgKHR1cGxlbGlzdFtpXS5nZXQobikgPT09IGtleSkge1xuICAgICAgcmV0dXJuIHR1cGxlbGlzdFtpXTtcbiAgICB9XG4gIH1cblxuICByZXR1cm4gZmFsc2U7XG59XG5cbmZ1bmN0aW9uIGtleWRlbGV0ZShrZXksIG4sIHR1cGxlbGlzdCkge1xuXG4gIGZvciAobGV0IGkgPSB0dXBsZWxpc3QubGVuZ3RoIC0gMTsgaSA+PSAwOyBpLS0pIHtcbiAgICBpZiAodHVwbGVsaXN0W2ldLmdldChuKSA9PT0ga2V5KSB7XG4gICAgICByZXR1cm4gdHVwbGVsaXN0LmNvbmNhdChbXSkuc3BsaWNlKGksIDEpO1xuICAgIH1cbiAgfVxuXG4gIHJldHVybiB0dXBsZWxpc3Q7XG59XG5cbmZ1bmN0aW9uIGtleXN0b3JlKGtleSwgbiwgbGlzdCwgbmV3dHVwbGUpIHtcbiAgZm9yIChsZXQgaSA9IGxpc3QubGVuZ3RoIC0gMTsgaSA+PSAwOyBpLS0pIHtcbiAgICBpZiAobGlzdFtpXS5nZXQobikgPT09IGtleSkge1xuICAgICAgcmV0dXJuIGxpc3QuY29uY2F0KFtdKS5zcGxpY2UoaSwgMSwgbmV3dHVwbGUpO1xuICAgIH1cbiAgfVxuXG4gIHJldHVybiBsaXN0LmNvbmNhdChbXSkucHVzaChuZXd0dXBsZSk7XG59XG5cbmZ1bmN0aW9uIGtleW1lbWJlcihrZXksIG4sIGxpc3QpIHtcbiAgZm9yIChsZXQgaSA9IGxpc3QubGVuZ3RoIC0gMTsgaSA+PSAwOyBpLS0pIHtcbiAgICBpZiAobGlzdFtpXS5nZXQobikgPT09IGtleSkge1xuICAgICAgcmV0dXJuIHRydWU7XG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIGZhbHNlO1xufVxuXG5mdW5jdGlvbiBrZXl0YWtlKGtleSwgbiwgbGlzdCkge1xuICBpZiAoIWtleW1lbWJlcihrZXksIG4sIGxpc3QpKSB7XG4gICAgcmV0dXJuIGZhbHNlO1xuICB9XG5cbiAgbGV0IHR1cGxlID0ga2V5ZmluZChrZXksIG4sIGxpc3QpO1xuXG4gIHJldHVybiBuZXcgVHVwbGUodHVwbGUuZ2V0KG4pLCB0dXBsZSwga2V5ZGVsZXRlKGtleSwgbiwgbGlzdCkpO1xufVxuXG5mdW5jdGlvbiBrZXlyZXBsYWNlKGtleSwgbiwgbGlzdCwgbmV3dHVwbGUpIHtcblxuICBmb3IgKGxldCBpID0gdHVwbGVsaXN0Lmxlbmd0aCAtIDE7IGkgPj0gMDsgaS0tKSB7XG4gICAgaWYgKHR1cGxlbGlzdFtpXS5nZXQobikgPT09IGtleSkge1xuICAgICAgcmV0dXJuIHR1cGxlbGlzdC5jb25jYXQoW10pLnNwbGljZShpLCAxLCBuZXd0dXBsZSk7XG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIHR1cGxlbGlzdDtcbn1cblxuZnVuY3Rpb24gcmV2ZXJzZShsaXN0KSB7XG4gIHJldHVybiBsaXN0LmNvbmNhdChbXSkucmV2ZXJzZSgpO1xufVxuXG5mdW5jdGlvbiBtYXBzX2ZpbmQoa2V5LCBtYXApIHtcbiAgaWYgKGtleSBpbiBnZXRfb2JqZWN0X2tleXMobWFwKSkge1xuICAgIHJldHVybiBuZXcgVHVwbGUoU3ltYm9sLmZvcignb2snKSwgbWFwW2tleV0pO1xuICB9IGVsc2Uge1xuICAgIHJldHVybiBTeW1ib2wuZm9yKCdlcnJvcicpO1xuICB9XG59XG5cbmZ1bmN0aW9uIGZsYXR0ZW4obGlzdCwgdGFpbCA9IFtdKSB7XG4gIGxldCBuZXdfbGlzdCA9IFtdO1xuXG4gIGZvciAobGV0IGUgb2YgbGlzdCkge1xuICAgIGlmIChpc0FycmF5KGUpKSB7XG4gICAgICBuZXdfbGlzdCA9IG5ld19saXN0LmNvbmNhdChmbGF0dGVuKGUpKTtcbiAgICB9IGVsc2Uge1xuICAgICAgbmV3X2xpc3QucHVzaChlKTtcbiAgICB9XG4gIH1cblxuICByZXR1cm4gT2JqZWN0LmZyZWV6ZShuZXdfbGlzdC5jb25jYXQodGFpbCkpO1xufVxuXG5mdW5jdGlvbiBkdXBsaWNhdGUobiwgZWxlbSkge1xuICBsZXQgbGlzdCA9IFtdO1xuXG4gIGZvciAobGV0IGkgPSAwOyBpIDwgbjsgaSsrKSB7XG4gICAgbGlzdC5wdXNoKGVsZW0pO1xuICB9XG5cbiAgcmV0dXJuIE9iamVjdC5mcmVlemUobGlzdCk7XG59XG5cbmZ1bmN0aW9uIG1hcGZvbGRsKGZ1biwgYWNjLCBsaXN0KSB7XG4gIGxldCBuZXdsaXN0ID0gW107XG5cbiAgZm9yIChsZXQgeCBvZiBsaXN0KSB7XG4gICAgbGV0IHR1cCA9IGZ1bih4LCBhY2MpO1xuICAgIG5ld2xpc3QucHVzaCh0dXAuZ2V0KDApKTtcbiAgICBhY2MgPSB0dXAuZ2V0KDEpO1xuICB9XG5cbiAgcmV0dXJuIG5ldyBUdXBsZShPYmplY3QuZnJlZXplKG5ld2xpc3QpLCBhY2MpO1xufVxuXG5mdW5jdGlvbiBmaWx0ZXJtYXAoZnVuLCBsaXN0KSB7XG4gIGxldCBuZXdsaXN0ID0gW107XG5cbiAgZm9yICh4IG9mIGxpc3QpIHtcbiAgICBsZXQgcmVzdWx0ID0gZnVuKHgpO1xuXG4gICAgaWYgKHJlc3VsdCA9PT0gdHJ1ZSkge1xuICAgICAgbmV3bGlzdC5wdXNoKHgpO1xuICAgIH0gZWxzZSBpZiAocmVzdWx0IGluc3RhbmNlb2YgVHVwbGUpIHtcbiAgICAgIG5ld2xpc3QucHVzaChyZXN1bHQuZ2V0KDEpKTtcbiAgICB9XG4gIH1cblxuICByZXR1cm4gT2JqZWN0LmZyZWV6ZShuZXdsaXN0KTtcbn1cblxuZnVuY3Rpb24gbWFwc19mb2xkKGZ1biwgYWNjLCBtYXApIHtcbiAgbGV0IGFjYzEgPSBhY2M7XG5cbiAgZm9yIChsZXQgayBvZiBnZXRfb2JqZWN0X2tleXMobWFwKSkge1xuICAgIGFjYzEgPSBmdW4oaywgbWFwW2tdLCBhY2MxKTtcbiAgfVxuXG4gIHJldHVybiBhY2MxO1xufVxuXG52YXIgRnVuY3Rpb25zID0ge1xuICBjYWxsX3Byb3BlcnR5LFxuICBhcHBseSxcbiAgY29udGFpbnMsXG4gIGdldF9nbG9iYWwsXG4gIGRlZnN0cnVjdCxcbiAgZGVmZXhjZXB0aW9uLFxuICBkZWZwcm90b2NvbCxcbiAgZGVmaW1wbCxcbiAgZ2V0X29iamVjdF9rZXlzLFxuICBpc192YWxpZF9jaGFyYWN0ZXIsXG4gIGI2NEVuY29kZVVuaWNvZGUsXG4gIGRlbGV0ZV9wcm9wZXJ0eV9mcm9tX21hcCxcbiAgYWRkX3Byb3BlcnR5X3RvX21hcCxcbiAgY2xhc3NfdG9fb2JqLFxuICBjYW5fZGVjb2RlNjQsXG4gIGJub3QsXG4gIGJhbmQsXG4gIGJvcixcbiAgYnNsLFxuICBic3IsXG4gIGJ4b3IsXG4gIHppcCxcbiAgZm9sZGwsXG4gIGZvbGRyLFxuICByZW1vdmVfZnJvbV9saXN0LFxuICBrZXlkZWxldGUsXG4gIGtleXN0b3JlLFxuICBrZXlmaW5kLFxuICBrZXl0YWtlLFxuICBrZXlyZXBsYWNlLFxuICByZXZlcnNlLFxuICB1cGRhdGVfbWFwLFxuICBtYXBzX2ZpbmQsXG4gIGZsYXR0ZW4sXG4gIGR1cGxpY2F0ZSxcbiAgbWFwZm9sZGwsXG4gIGZpbHRlcm1hcCxcbiAgbWFwc19mb2xkXG59O1xuXG5mdW5jdGlvbiBfY2FzZShjb25kaXRpb24sIGNsYXVzZXMpIHtcbiAgcmV0dXJuIFBhdHRlcm5zLmRlZm1hdGNoKC4uLmNsYXVzZXMpKGNvbmRpdGlvbik7XG59XG5cbmZ1bmN0aW9uIGNvbmQoY2xhdXNlcykge1xuICBmb3IgKGxldCBjbGF1c2Ugb2YgY2xhdXNlcykge1xuICAgIGlmIChjbGF1c2VbMF0pIHtcbiAgICAgIHJldHVybiBjbGF1c2VbMV0oKTtcbiAgICB9XG4gIH1cblxuICB0aHJvdyBuZXcgRXJyb3IoKTtcbn1cblxuZnVuY3Rpb24gbWFwX3VwZGF0ZShtYXAsIHZhbHVlcykge1xuICByZXR1cm4gT2JqZWN0LmZyZWV6ZShPYmplY3QuYXNzaWduKE9iamVjdC5jcmVhdGUobWFwLmNvbnN0cnVjdG9yLnByb3RvdHlwZSksIG1hcCwgdmFsdWVzKSk7XG59XG5cbmZ1bmN0aW9uIF9mb3IoY29sbGVjdGlvbnMsIGZ1biwgZmlsdGVyID0gKCkgPT4gdHJ1ZSwgaW50byA9IFtdLCBwcmV2aW91c1ZhbHVlcyA9IFtdKSB7XG4gIGxldCBwYXR0ZXJuID0gY29sbGVjdGlvbnNbMF1bMF07XG4gIGxldCBjb2xsZWN0aW9uID0gY29sbGVjdGlvbnNbMF1bMV07XG5cbiAgaWYgKGNvbGxlY3Rpb25zLmxlbmd0aCA9PT0gMSkge1xuXG4gICAgZm9yIChsZXQgZWxlbSBvZiBjb2xsZWN0aW9uKSB7XG4gICAgICBsZXQgciA9IFBhdHRlcm5zLm1hdGNoX25vX3Rocm93KHBhdHRlcm4sIGVsZW0pO1xuICAgICAgbGV0IGFyZ3MgPSBwcmV2aW91c1ZhbHVlcy5jb25jYXQocik7XG5cbiAgICAgIGlmIChyICYmIGZpbHRlci5hcHBseSh0aGlzLCBhcmdzKSkge1xuICAgICAgICBpbnRvID0gaW50by5jb25jYXQoW2Z1bi5hcHBseSh0aGlzLCBhcmdzKV0pO1xuICAgICAgfVxuICAgIH1cblxuICAgIHJldHVybiBpbnRvO1xuICB9IGVsc2Uge1xuICAgIGxldCBfaW50byA9IFtdO1xuXG4gICAgZm9yIChsZXQgZWxlbSBvZiBjb2xsZWN0aW9uKSB7XG4gICAgICBsZXQgciA9IFBhdHRlcm5zLm1hdGNoX25vX3Rocm93KHBhdHRlcm4sIGVsZW0pO1xuICAgICAgaWYgKHIpIHtcbiAgICAgICAgX2ludG8gPSBpbnRvLmNvbmNhdCh0aGlzLl9mb3IoY29sbGVjdGlvbnMuc2xpY2UoMSksIGZ1biwgZmlsdGVyLCBfaW50bywgcHJldmlvdXNWYWx1ZXMuY29uY2F0KHIpKSk7XG4gICAgICB9XG4gICAgfVxuXG4gICAgcmV0dXJuIF9pbnRvO1xuICB9XG59XG5cbmZ1bmN0aW9uIF90cnkoZG9fZnVuLCByZXNjdWVfZnVuY3Rpb24sIGNhdGNoX2Z1biwgZWxzZV9mdW5jdGlvbiwgYWZ0ZXJfZnVuY3Rpb24pIHtcbiAgbGV0IHJlc3VsdCA9IG51bGw7XG5cbiAgdHJ5IHtcbiAgICByZXN1bHQgPSBkb19mdW4oKTtcbiAgfSBjYXRjaCAoZSkge1xuICAgIGxldCBleF9yZXN1bHQgPSBudWxsO1xuXG4gICAgaWYgKHJlc2N1ZV9mdW5jdGlvbikge1xuICAgICAgdHJ5IHtcbiAgICAgICAgZXhfcmVzdWx0ID0gcmVzY3VlX2Z1bmN0aW9uKGUpO1xuICAgICAgICByZXR1cm4gZXhfcmVzdWx0O1xuICAgICAgfSBjYXRjaCAoZXgpIHtcbiAgICAgICAgaWYgKGV4IGluc3RhbmNlb2YgUGF0dGVybnMuTWF0Y2hFcnJvcikge1xuICAgICAgICAgIHRocm93IGV4O1xuICAgICAgICB9XG4gICAgICB9XG4gICAgfVxuXG4gICAgaWYgKGNhdGNoX2Z1bikge1xuICAgICAgdHJ5IHtcbiAgICAgICAgZXhfcmVzdWx0ID0gY2F0Y2hfZnVuKGUpO1xuICAgICAgICByZXR1cm4gZXhfcmVzdWx0O1xuICAgICAgfSBjYXRjaCAoZXgpIHtcbiAgICAgICAgaWYgKGV4IGluc3RhbmNlb2YgUGF0dGVybnMuTWF0Y2hFcnJvcikge1xuICAgICAgICAgIHRocm93IGV4O1xuICAgICAgICB9XG4gICAgICB9XG4gICAgfVxuXG4gICAgdGhyb3cgZTtcbiAgfSBmaW5hbGx5IHtcbiAgICBpZiAoYWZ0ZXJfZnVuY3Rpb24pIHtcbiAgICAgIGFmdGVyX2Z1bmN0aW9uKCk7XG4gICAgfVxuICB9XG5cbiAgaWYgKGVsc2VfZnVuY3Rpb24pIHtcbiAgICB0cnkge1xuICAgICAgcmV0dXJuIGVsc2VfZnVuY3Rpb24ocmVzdWx0KTtcbiAgICB9IGNhdGNoIChleCkge1xuICAgICAgaWYgKGV4IGluc3RhbmNlb2YgUGF0dGVybnMuTWF0Y2hFcnJvcikge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ05vIE1hdGNoIEZvdW5kIGluIEVsc2UnKTtcbiAgICAgIH1cblxuICAgICAgdGhyb3cgZXg7XG4gICAgfVxuICB9IGVsc2Uge1xuICAgIHJldHVybiByZXN1bHQ7XG4gIH1cbn1cblxudmFyIFNwZWNpYWxGb3JtcyQxID0ge1xuICBfY2FzZSxcbiAgY29uZCxcbiAgbWFwX3VwZGF0ZSxcbiAgX2ZvcixcbiAgX3RyeVxufTtcblxuRnVuY3Rpb25zLmdldF9nbG9iYWwoKS5wcm9jZXNzZXMgPSBGdW5jdGlvbnMuZ2V0X2dsb2JhbCgpLnByb2Nlc3NlcyB8fCBuZXcgUHJvY2Vzc1N5c3RlbSgpO1xuXG52YXIgQ29yZSA9IHtcbiAgUHJvY2Vzc1N5c3RlbSxcbiAgVHVwbGUsXG4gIFBJRCxcbiAgQml0U3RyaW5nLFxuICBQYXR0ZXJucyxcbiAgSW50ZWdlcixcbiAgRmxvYXQsXG4gIEZ1bmN0aW9ucyxcbiAgU3BlY2lhbEZvcm1zOiBTcGVjaWFsRm9ybXMkMVxufTtcblxubGV0IEVudW0gPSB7XG5cbiAgYWxsX19xbWFya19fOiBmdW5jdGlvbiAoY29sbGVjdGlvbiwgZnVuID0geCA9PiB4KSB7XG4gICAgZm9yIChsZXQgZWxlbSBvZiBjb2xsZWN0aW9uKSB7XG4gICAgICBpZiAoIWZ1bihlbGVtKSkge1xuICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICB9XG4gICAgfVxuXG4gICAgcmV0dXJuIHRydWU7XG4gIH0sXG5cbiAgYW55X19xbWFya19fOiBmdW5jdGlvbiAoY29sbGVjdGlvbiwgZnVuID0geCA9PiB4KSB7XG4gICAgZm9yIChsZXQgZWxlbSBvZiBjb2xsZWN0aW9uKSB7XG4gICAgICBpZiAoZnVuKGVsZW0pKSB7XG4gICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgfVxuICAgIH1cblxuICAgIHJldHVybiBmYWxzZTtcbiAgfSxcblxuICBhdDogZnVuY3Rpb24gKGNvbGxlY3Rpb24sIG4sIHRoZV9kZWZhdWx0ID0gbnVsbCkge1xuICAgIGlmIChuID4gdGhpcy5jb3VudChjb2xsZWN0aW9uKSB8fCBuIDwgMCkge1xuICAgICAgcmV0dXJuIHRoZV9kZWZhdWx0O1xuICAgIH1cblxuICAgIHJldHVybiBjb2xsZWN0aW9uW25dO1xuICB9LFxuXG4gIGNvbmNhdDogZnVuY3Rpb24gKC4uLmVudW1hYmxlcykge1xuICAgIHJldHVybiBlbnVtYWJsZXNbMF0uY29uY2F0KGVudW1hYmxlc1sxXSk7XG4gIH0sXG5cbiAgY291bnQ6IGZ1bmN0aW9uIChjb2xsZWN0aW9uLCBmdW4gPSBudWxsKSB7XG4gICAgaWYgKGZ1biA9PSBudWxsKSB7XG4gICAgICByZXR1cm4gY29sbGVjdGlvbi5sZW5ndGg7XG4gICAgfSBlbHNlIHtcbiAgICAgIHJldHVybiBjb2xsZWN0aW9uLmZpbHRlcihmdW4pLmxlbmd0aDtcbiAgICB9XG4gIH0sXG5cbiAgZHJvcDogZnVuY3Rpb24gKGNvbGxlY3Rpb24sIGNvdW50KSB7XG4gICAgcmV0dXJuIGNvbGxlY3Rpb24uc2xpY2UoY291bnQpO1xuICB9LFxuXG4gIGRyb3Bfd2hpbGU6IGZ1bmN0aW9uIChjb2xsZWN0aW9uLCBmdW4pIHtcbiAgICBsZXQgY291bnQgPSAwO1xuXG4gICAgZm9yIChsZXQgZWxlbSBvZiBjb2xsZWN0aW9uKSB7XG4gICAgICBpZiAoZnVuKGVsZW0pKSB7XG4gICAgICAgIGNvdW50ID0gY291bnQgKyAxO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgYnJlYWs7XG4gICAgICB9XG4gICAgfVxuXG4gICAgcmV0dXJuIGNvbGxlY3Rpb24uc2xpY2UoY291bnQpO1xuICB9LFxuXG4gIGVhY2g6IGZ1bmN0aW9uIChjb2xsZWN0aW9uLCBmdW4pIHtcbiAgICBmb3IgKGxldCBlbGVtIG9mIGNvbGxlY3Rpb24pIHtcbiAgICAgIGZ1bihlbGVtKTtcbiAgICB9XG4gIH0sXG5cbiAgZW1wdHlfX3FtYXJrX186IGZ1bmN0aW9uIChjb2xsZWN0aW9uKSB7XG4gICAgcmV0dXJuIGNvbGxlY3Rpb24ubGVuZ3RoID09PSAwO1xuICB9LFxuXG4gIGZldGNoOiBmdW5jdGlvbiAoY29sbGVjdGlvbiwgbikge1xuICAgIGlmIChBcnJheS5pc0FycmF5KGNvbGxlY3Rpb24pKSB7XG4gICAgICBpZiAobiA8IHRoaXMuY291bnQoY29sbGVjdGlvbikgJiYgbiA+PSAwKSB7XG4gICAgICAgIHJldHVybiBuZXcgQ29yZS5UdXBsZShTeW1ib2wuZm9yKFwib2tcIiksIGNvbGxlY3Rpb25bbl0pO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgcmV0dXJuIFN5bWJvbC5mb3IoXCJlcnJvclwiKTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICB0aHJvdyBuZXcgRXJyb3IoXCJjb2xsZWN0aW9uIGlzIG5vdCBhbiBFbnVtZXJhYmxlXCIpO1xuICB9LFxuXG4gIGZldGNoX19lbWFya19fOiBmdW5jdGlvbiAoY29sbGVjdGlvbiwgbikge1xuICAgIGlmIChBcnJheS5pc0FycmF5KGNvbGxlY3Rpb24pKSB7XG4gICAgICBpZiAobiA8IHRoaXMuY291bnQoY29sbGVjdGlvbikgJiYgbiA+PSAwKSB7XG4gICAgICAgIHJldHVybiBjb2xsZWN0aW9uW25dO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKFwib3V0IG9mIGJvdW5kcyBlcnJvclwiKTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICB0aHJvdyBuZXcgRXJyb3IoXCJjb2xsZWN0aW9uIGlzIG5vdCBhbiBFbnVtZXJhYmxlXCIpO1xuICB9LFxuXG4gIGZpbHRlcjogZnVuY3Rpb24gKGNvbGxlY3Rpb24sIGZ1bikge1xuICAgIGxldCByZXN1bHQgPSBbXTtcblxuICAgIGZvciAobGV0IGVsZW0gb2YgY29sbGVjdGlvbikge1xuICAgICAgaWYgKGZ1bihlbGVtKSkge1xuICAgICAgICByZXN1bHQucHVzaChlbGVtKTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICByZXR1cm4gcmVzdWx0O1xuICB9LFxuXG4gIGZpbHRlcl9tYXA6IGZ1bmN0aW9uIChjb2xsZWN0aW9uLCBmaWx0ZXIsIG1hcHBlcikge1xuICAgIHJldHVybiBFbnVtLm1hcChFbnVtLmZpbHRlcihjb2xsZWN0aW9uLCBmaWx0ZXIpLCBtYXBwZXIpO1xuICB9LFxuXG4gIGZpbmQ6IGZ1bmN0aW9uIChjb2xsZWN0aW9uLCBpZl9ub25lID0gbnVsbCwgZnVuKSB7XG4gICAgZm9yIChsZXQgZWxlbSBvZiBjb2xsZWN0aW9uKSB7XG4gICAgICBpZiAoZnVuKGVsZW0pKSB7XG4gICAgICAgIHJldHVybiBlbGVtO1xuICAgICAgfVxuICAgIH1cblxuICAgIHJldHVybiBpZl9ub25lO1xuICB9LFxuXG4gIGludG86IGZ1bmN0aW9uIChjb2xsZWN0aW9uLCBsaXN0KSB7XG4gICAgcmV0dXJuIGxpc3QuY29uY2F0KGNvbGxlY3Rpb24pO1xuICB9LFxuXG4gIG1hcDogZnVuY3Rpb24gKGNvbGxlY3Rpb24sIGZ1bikge1xuICAgIGxldCByZXN1bHQgPSBbXTtcblxuICAgIGZvciAobGV0IGVsZW0gb2YgY29sbGVjdGlvbikge1xuICAgICAgcmVzdWx0LnB1c2goZnVuKGVsZW0pKTtcbiAgICB9XG5cbiAgICByZXR1cm4gcmVzdWx0O1xuICB9LFxuXG4gIG1hcF9yZWR1Y2U6IGZ1bmN0aW9uIChjb2xsZWN0aW9uLCBhY2MsIGZ1bikge1xuICAgIGxldCBtYXBwZWQgPSBPYmplY3QuZnJlZXplKFtdKTtcbiAgICBsZXQgdGhlX2FjYyA9IGFjYztcblxuICAgIGZvciAodmFyIGkgPSAwOyBpIDwgdGhpcy5jb3VudChjb2xsZWN0aW9uKTsgaSsrKSB7XG4gICAgICBsZXQgdHVwbGUgPSBmdW4oY29sbGVjdGlvbltpXSwgdGhlX2FjYyk7XG5cbiAgICAgIHRoZV9hY2MgPSB0dXBsZS5nZXQoMSk7XG4gICAgICBtYXBwZWQgPSBPYmplY3QuZnJlZXplKG1hcHBlZC5jb25jYXQoW3R1cGxlLmdldCgwKV0pKTtcbiAgICB9XG5cbiAgICByZXR1cm4gbmV3IENvcmUuVHVwbGUobWFwcGVkLCB0aGVfYWNjKTtcbiAgfSxcblxuICBtZW1iZXJfX3FtYXJrX186IGZ1bmN0aW9uIChjb2xsZWN0aW9uLCB2YWx1ZSkge1xuICAgIHJldHVybiBjb2xsZWN0aW9uLmluY2x1ZGVzKHZhbHVlKTtcbiAgfSxcblxuICByZWR1Y2U6IGZ1bmN0aW9uIChjb2xsZWN0aW9uLCBhY2MsIGZ1bikge1xuICAgIGxldCB0aGVfYWNjID0gYWNjO1xuXG4gICAgZm9yICh2YXIgaSA9IDA7IGkgPCB0aGlzLmNvdW50KGNvbGxlY3Rpb24pOyBpKyspIHtcbiAgICAgIGxldCB0dXBsZSA9IGZ1bihjb2xsZWN0aW9uW2ldLCB0aGVfYWNjKTtcblxuICAgICAgdGhlX2FjYyA9IHR1cGxlLmdldCgxKTtcbiAgICB9XG5cbiAgICByZXR1cm4gdGhlX2FjYztcbiAgfSxcblxuICB0YWtlOiBmdW5jdGlvbiAoY29sbGVjdGlvbiwgY291bnQpIHtcbiAgICByZXR1cm4gY29sbGVjdGlvbi5zbGljZSgwLCBjb3VudCk7XG4gIH0sXG5cbiAgdGFrZV9ldmVyeTogZnVuY3Rpb24gKGNvbGxlY3Rpb24sIG50aCkge1xuICAgIGxldCByZXN1bHQgPSBbXTtcbiAgICBsZXQgaW5kZXggPSAwO1xuXG4gICAgZm9yIChsZXQgZWxlbSBvZiBjb2xsZWN0aW9uKSB7XG4gICAgICBpZiAoaW5kZXggJSBudGggPT09IDApIHtcbiAgICAgICAgcmVzdWx0LnB1c2goZWxlbSk7XG4gICAgICB9XG4gICAgfVxuXG4gICAgcmV0dXJuIE9iamVjdC5mcmVlemUocmVzdWx0KTtcbiAgfSxcblxuICB0YWtlX3doaWxlOiBmdW5jdGlvbiAoY29sbGVjdGlvbiwgZnVuKSB7XG4gICAgbGV0IGNvdW50ID0gMDtcblxuICAgIGZvciAobGV0IGVsZW0gb2YgY29sbGVjdGlvbikge1xuICAgICAgaWYgKGZ1bihlbGVtKSkge1xuICAgICAgICBjb3VudCA9IGNvdW50ICsgMTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIGJyZWFrO1xuICAgICAgfVxuICAgIH1cblxuICAgIHJldHVybiBjb2xsZWN0aW9uLnNsaWNlKDAsIGNvdW50KTtcbiAgfSxcblxuICB0b19saXN0OiBmdW5jdGlvbiAoY29sbGVjdGlvbikge1xuICAgIHJldHVybiBjb2xsZWN0aW9uO1xuICB9XG59O1xuXG52YXIgRWxpeGlyID0ge1xuICBDb3JlLFxuICBFbnVtLFxuICBWaXJ0dWFsRE9NXG59O1xuXG5leHBvcnQgZGVmYXVsdCBFbGl4aXI7Il0sImZpbGUiOiJFbGl4aXIuanMiLCJzb3VyY2VSb290IjoiL3NvdXJjZS8ifQ== \ No newline at end of file diff --git a/src/javascript/lib/core/protocol.js b/src/javascript/lib/core/protocol.js index 06912855..cd96dbf0 100644 --- a/src/javascript/lib/core/protocol.js +++ b/src/javascript/lib/core/protocol.js @@ -17,9 +17,9 @@ class Protocol{ let fun = null; if(Number.isInteger(thing) && this.hasImplementation(Integer)){ - fun = this.registry.get(Core.Integer)[funName]; + fun = this.registry.get(Integer)[funName]; }else if(typeof thing === "number" && !Number.isInteger(thing) && this.hasImplementation(Float)){ - fun = this.registry.get(Core.Float)[funName]; + fun = this.registry.get(Float)[funName]; }else if(this.hasImplementation(thing)){ fun = this.registry.get(thing.constructor)[funName]; }else if(this.fallback){ diff --git a/src/javascript/tests/patterns/defmatch.spec.js b/src/javascript/tests/patterns/defmatch.spec.js index 5cdc0d5d..747774cf 100644 --- a/src/javascript/tests/patterns/defmatch.spec.js +++ b/src/javascript/tests/patterns/defmatch.spec.js @@ -143,7 +143,4 @@ describe('defmatch', () => { expect(fn(new Tuple(1, 2, 3))).to.equal(3); expect(fn.bind(fn, new Tuple(1, 2, 4))).to.throw("No match for: {1, 2, 4}"); }); - - - }); From 382d35fa33bddd417a604f6b99be1aa98427a9e3 Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Fri, 19 Feb 2016 14:23:55 -0600 Subject: [PATCH 148/860] Updated Changelog. Updated version to 0.15.1 --- CHANGELOG.md | 9 ++++++++- mix.exs | 2 +- 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 28192d1c..b7943c1f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,4 +1,11 @@ -# v0.16.0-dev +# v0.15.1 +* Bug fixes + * Fixed View module so that an element can have multiple elements within + * Removed `catch` as a javascript keyword to filter + * Fixed struct implementation so that lists of atoms for fields are compiled correctly + * Fixed head-tail pattern match to allow for more complicated scenarios + * Fixed ModuleCollector to properly alias inner modules + * Fixed raise translation to properly translate when string messages are given # v0.15.0 * Enhancements diff --git a/mix.exs b/mix.exs index 3bbfc4fd..ae7886a5 100644 --- a/mix.exs +++ b/mix.exs @@ -4,7 +4,7 @@ defmodule ElixirScript.Mixfile do def project do [ app: :elixir_script, - version: "0.16.0-dev", + version: "0.15.1", elixir: "~> 1.0", escript: escript_config, deps: deps, From 07b791c493f307cce7f054aec36c6bc028f60fc0 Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Sat, 20 Feb 2016 13:45:38 -0600 Subject: [PATCH 149/860] Fixed bugs in protocol and with call_property function. Added tests for call_property --- CHANGELOG.md | 5 +++++ mix.exs | 2 +- priv/Elixir.js | 24 ++++++++++++++++----- src/javascript/lib/core/functions.js | 20 ++++++++++++----- src/javascript/lib/core/protocol.js | 4 ++++ src/javascript/tests/core/functions.spec.js | 17 +++++++++++++++ 6 files changed, 61 insertions(+), 11 deletions(-) create mode 100644 src/javascript/tests/core/functions.spec.js diff --git a/CHANGELOG.md b/CHANGELOG.md index b7943c1f..68ca4ce2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,8 @@ +# v0.15.2-dev +* Bug fixes + * Fixed protocol implementations for Integer and Float which where not recognized + * Fixed calling properties on non-objects + # v0.15.1 * Bug fixes * Fixed View module so that an element can have multiple elements within diff --git a/mix.exs b/mix.exs index ae7886a5..d8d6659c 100644 --- a/mix.exs +++ b/mix.exs @@ -4,7 +4,7 @@ defmodule ElixirScript.Mixfile do def project do [ app: :elixir_script, - version: "0.15.1", + version: "0.15.2-dev", elixir: "~> 1.0", escript: escript_config, deps: deps, diff --git a/priv/Elixir.js b/priv/Elixir.js index 905299bb..43e1f9ae 100644 --- a/priv/Elixir.js +++ b/priv/Elixir.js @@ -2687,6 +2687,10 @@ class Protocol { } hasImplementation(thing) { + if (thing === Integer || thing === Float) { + return this.registry.has(thing); + } + return this.registry.has(thing.constructor); } } @@ -2694,11 +2698,21 @@ class Protocol { function call_property(item, property) { let prop = null; - if (property in item) { - prop = property; - } else if (Symbol.for(property) in item) { - prop = Symbol.for(property); + if (typeof item === 'number' || typeof item === 'symbol' || typeof item === 'boolean' || typeof item === 'string') { + if (item[property] !== undefined) { + prop = property; + } else if (item[Symbol.for(property)] !== undefined) { + prop = Symbol.for(property); + } } else { + if (property in item) { + prop = property; + } else if (Symbol.for(property) in item) { + prop = Symbol.for(property); + } + } + + if (prop === null) { throw new Error(`Property ${ property } not found in ${ item }`); } @@ -3427,4 +3441,4 @@ var Elixir = { }; export default Elixir; -//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiIiwic291cmNlcyI6WyJFbGl4aXIuanMiXSwic291cmNlc0NvbnRlbnQiOlsibGV0IFZpcnR1YWxET00gPSAoZnVuY3Rpb24gKGUpIHtcbiAgICByZXR1cm4gZSgpO1xufSkoZnVuY3Rpb24gKCkge1xuICAgIHZhciBkZWZpbmUsIG1vZHVsZSwgZXhwb3J0cztcbiAgICByZXR1cm4gKGZ1bmN0aW9uIGUodCwgbiwgcikge1xuICAgICAgICBmdW5jdGlvbiBzKG8sIHUpIHtcbiAgICAgICAgICAgIGlmICghbltvXSkge1xuICAgICAgICAgICAgICAgIGlmICghdFtvXSkge1xuICAgICAgICAgICAgICAgICAgICB2YXIgYSA9IHR5cGVvZiByZXF1aXJlID09IFwiZnVuY3Rpb25cIiAmJiByZXF1aXJlO1xuICAgICAgICAgICAgICAgICAgICBpZiAoIXUgJiYgYSkgcmV0dXJuIGEobywgITApO1xuICAgICAgICAgICAgICAgICAgICBpZiAoaSkgcmV0dXJuIGkobywgITApO1xuICAgICAgICAgICAgICAgICAgICB2YXIgZiA9IG5ldyBFcnJvcihcIkNhbm5vdCBmaW5kIG1vZHVsZSAnXCIgKyBvICsgXCInXCIpO1xuICAgICAgICAgICAgICAgICAgICB0aHJvdyAoZi5jb2RlID0gXCJNT0RVTEVfTk9UX0ZPVU5EXCIsIGYpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB2YXIgbCA9IG5bb10gPSB7XG4gICAgICAgICAgICAgICAgICAgIGV4cG9ydHM6IHt9XG4gICAgICAgICAgICAgICAgfTtcbiAgICAgICAgICAgICAgICB0W29dWzBdLmNhbGwobC5leHBvcnRzLCBmdW5jdGlvbiAoZSkge1xuICAgICAgICAgICAgICAgICAgICB2YXIgbiA9IHRbb11bMV1bZV07XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBzKG4gPyBuIDogZSk7XG4gICAgICAgICAgICAgICAgfSwgbCwgbC5leHBvcnRzLCBlLCB0LCBuLCByKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJldHVybiBuW29dLmV4cG9ydHM7XG4gICAgICAgIH1cbiAgICAgICAgdmFyIGkgPSB0eXBlb2YgcmVxdWlyZSA9PSBcImZ1bmN0aW9uXCIgJiYgcmVxdWlyZTtcbiAgICAgICAgZm9yICh2YXIgbyA9IDA7IG8gPCByLmxlbmd0aDsgbysrKSBzKHJbb10pO1xuICAgICAgICByZXR1cm4gcztcbiAgICB9KSh7XG4gICAgICAgIDE6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG5cbiAgICAgICAgICAgIHZhciBjcmVhdGVFbGVtZW50ID0gcmVxdWlyZShcIi4vdmRvbS9jcmVhdGUtZWxlbWVudC5qc1wiKTtcblxuICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBjcmVhdGVFbGVtZW50O1xuICAgICAgICB9LCB7IFwiLi92ZG9tL2NyZWF0ZS1lbGVtZW50LmpzXCI6IDE1IH1dLCAyOiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge1xuICAgICAgICAgICAgdmFyIGRpZmYgPSByZXF1aXJlKFwiLi92dHJlZS9kaWZmLmpzXCIpO1xuXG4gICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IGRpZmY7XG4gICAgICAgIH0sIHsgXCIuL3Z0cmVlL2RpZmYuanNcIjogMzUgfV0sIDM6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICB2YXIgaCA9IHJlcXVpcmUoXCIuL3ZpcnR1YWwtaHlwZXJzY3JpcHQvaW5kZXguanNcIik7XG5cbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gaDtcbiAgICAgICAgfSwgeyBcIi4vdmlydHVhbC1oeXBlcnNjcmlwdC9pbmRleC5qc1wiOiAyMiB9XSwgNDogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHtcbiAgICAgICAgICAgIHZhciBkaWZmID0gcmVxdWlyZShcIi4vZGlmZi5qc1wiKTtcbiAgICAgICAgICAgIHZhciBwYXRjaCA9IHJlcXVpcmUoXCIuL3BhdGNoLmpzXCIpO1xuICAgICAgICAgICAgdmFyIGggPSByZXF1aXJlKFwiLi9oLmpzXCIpO1xuICAgICAgICAgICAgdmFyIGNyZWF0ZSA9IHJlcXVpcmUoXCIuL2NyZWF0ZS1lbGVtZW50LmpzXCIpO1xuICAgICAgICAgICAgdmFyIFZOb2RlID0gcmVxdWlyZShcIi4vdm5vZGUvdm5vZGUuanNcIik7XG4gICAgICAgICAgICB2YXIgVlRleHQgPSByZXF1aXJlKFwiLi92bm9kZS92dGV4dC5qc1wiKTtcblxuICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSB7XG4gICAgICAgICAgICAgICAgZGlmZjogZGlmZixcbiAgICAgICAgICAgICAgICBwYXRjaDogcGF0Y2gsXG4gICAgICAgICAgICAgICAgaDogaCxcbiAgICAgICAgICAgICAgICBjcmVhdGU6IGNyZWF0ZSxcbiAgICAgICAgICAgICAgICBWTm9kZTogVk5vZGUsXG4gICAgICAgICAgICAgICAgVlRleHQ6IFZUZXh0XG4gICAgICAgICAgICB9O1xuICAgICAgICB9LCB7IFwiLi9jcmVhdGUtZWxlbWVudC5qc1wiOiAxLCBcIi4vZGlmZi5qc1wiOiAyLCBcIi4vaC5qc1wiOiAzLCBcIi4vcGF0Y2guanNcIjogMTMsIFwiLi92bm9kZS92bm9kZS5qc1wiOiAzMSwgXCIuL3Zub2RlL3Z0ZXh0LmpzXCI6IDMzIH1dLCA1OiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge1xuICAgICAgICAgICAgLyohXG4gICAgICAgICAgICAgKiBDcm9zcy1Ccm93c2VyIFNwbGl0IDEuMS4xXG4gICAgICAgICAgICAgKiBDb3B5cmlnaHQgMjAwNy0yMDEyIFN0ZXZlbiBMZXZpdGhhbiA8c3RldmVubGV2aXRoYW4uY29tPlxuICAgICAgICAgICAgICogQXZhaWxhYmxlIHVuZGVyIHRoZSBNSVQgTGljZW5zZVxuICAgICAgICAgICAgICogRUNNQVNjcmlwdCBjb21wbGlhbnQsIHVuaWZvcm0gY3Jvc3MtYnJvd3NlciBzcGxpdCBtZXRob2RcbiAgICAgICAgICAgICAqL1xuXG4gICAgICAgICAgICAvKipcbiAgICAgICAgICAgICAqIFNwbGl0cyBhIHN0cmluZyBpbnRvIGFuIGFycmF5IG9mIHN0cmluZ3MgdXNpbmcgYSByZWdleCBvciBzdHJpbmcgc2VwYXJhdG9yLiBNYXRjaGVzIG9mIHRoZVxuICAgICAgICAgICAgICogc2VwYXJhdG9yIGFyZSBub3QgaW5jbHVkZWQgaW4gdGhlIHJlc3VsdCBhcnJheS4gSG93ZXZlciwgaWYgYHNlcGFyYXRvcmAgaXMgYSByZWdleCB0aGF0IGNvbnRhaW5zXG4gICAgICAgICAgICAgKiBjYXB0dXJpbmcgZ3JvdXBzLCBiYWNrcmVmZXJlbmNlcyBhcmUgc3BsaWNlZCBpbnRvIHRoZSByZXN1bHQgZWFjaCB0aW1lIGBzZXBhcmF0b3JgIGlzIG1hdGNoZWQuXG4gICAgICAgICAgICAgKiBGaXhlcyBicm93c2VyIGJ1Z3MgY29tcGFyZWQgdG8gdGhlIG5hdGl2ZSBgU3RyaW5nLnByb3RvdHlwZS5zcGxpdGAgYW5kIGNhbiBiZSB1c2VkIHJlbGlhYmx5XG4gICAgICAgICAgICAgKiBjcm9zcy1icm93c2VyLlxuICAgICAgICAgICAgICogQHBhcmFtIHtTdHJpbmd9IHN0ciBTdHJpbmcgdG8gc3BsaXQuXG4gICAgICAgICAgICAgKiBAcGFyYW0ge1JlZ0V4cHxTdHJpbmd9IHNlcGFyYXRvciBSZWdleCBvciBzdHJpbmcgdG8gdXNlIGZvciBzZXBhcmF0aW5nIHRoZSBzdHJpbmcuXG4gICAgICAgICAgICAgKiBAcGFyYW0ge051bWJlcn0gW2xpbWl0XSBNYXhpbXVtIG51bWJlciBvZiBpdGVtcyB0byBpbmNsdWRlIGluIHRoZSByZXN1bHQgYXJyYXkuXG4gICAgICAgICAgICAgKiBAcmV0dXJucyB7QXJyYXl9IEFycmF5IG9mIHN1YnN0cmluZ3MuXG4gICAgICAgICAgICAgKiBAZXhhbXBsZVxuICAgICAgICAgICAgICpcbiAgICAgICAgICAgICAqIC8vIEJhc2ljIHVzZVxuICAgICAgICAgICAgICogc3BsaXQoJ2EgYiBjIGQnLCAnICcpO1xuICAgICAgICAgICAgICogLy8gLT4gWydhJywgJ2InLCAnYycsICdkJ11cbiAgICAgICAgICAgICAqXG4gICAgICAgICAgICAgKiAvLyBXaXRoIGxpbWl0XG4gICAgICAgICAgICAgKiBzcGxpdCgnYSBiIGMgZCcsICcgJywgMik7XG4gICAgICAgICAgICAgKiAvLyAtPiBbJ2EnLCAnYiddXG4gICAgICAgICAgICAgKlxuICAgICAgICAgICAgICogLy8gQmFja3JlZmVyZW5jZXMgaW4gcmVzdWx0IGFycmF5XG4gICAgICAgICAgICAgKiBzcGxpdCgnLi53b3JkMSB3b3JkMi4uJywgLyhbYS16XSspKFxcZCspL2kpO1xuICAgICAgICAgICAgICogLy8gLT4gWycuLicsICd3b3JkJywgJzEnLCAnICcsICd3b3JkJywgJzInLCAnLi4nXVxuICAgICAgICAgICAgICovXG4gICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IChmdW5jdGlvbiBzcGxpdCh1bmRlZikge1xuXG4gICAgICAgICAgICAgICAgdmFyIG5hdGl2ZVNwbGl0ID0gU3RyaW5nLnByb3RvdHlwZS5zcGxpdCxcbiAgICAgICAgICAgICAgICAgICAgY29tcGxpYW50RXhlY05wY2cgPSAvKCk/Py8uZXhlYyhcIlwiKVsxXSA9PT0gdW5kZWYsXG5cbiAgICAgICAgICAgICAgICAvLyBOUENHOiBub25wYXJ0aWNpcGF0aW5nIGNhcHR1cmluZyBncm91cFxuICAgICAgICAgICAgICAgIHNlbGY7XG5cbiAgICAgICAgICAgICAgICBzZWxmID0gZnVuY3Rpb24gKHN0ciwgc2VwYXJhdG9yLCBsaW1pdCkge1xuICAgICAgICAgICAgICAgICAgICAvLyBJZiBgc2VwYXJhdG9yYCBpcyBub3QgYSByZWdleCwgdXNlIGBuYXRpdmVTcGxpdGBcbiAgICAgICAgICAgICAgICAgICAgaWYgKE9iamVjdC5wcm90b3R5cGUudG9TdHJpbmcuY2FsbChzZXBhcmF0b3IpICE9PSBcIltvYmplY3QgUmVnRXhwXVwiKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gbmF0aXZlU3BsaXQuY2FsbChzdHIsIHNlcGFyYXRvciwgbGltaXQpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIHZhciBvdXRwdXQgPSBbXSxcbiAgICAgICAgICAgICAgICAgICAgICAgIGZsYWdzID0gKHNlcGFyYXRvci5pZ25vcmVDYXNlID8gXCJpXCIgOiBcIlwiKSArIChzZXBhcmF0b3IubXVsdGlsaW5lID8gXCJtXCIgOiBcIlwiKSArIChzZXBhcmF0b3IuZXh0ZW5kZWQgPyBcInhcIiA6IFwiXCIpICsgKHNlcGFyYXRvci5zdGlja3kgPyBcInlcIiA6IFwiXCIpLFxuXG4gICAgICAgICAgICAgICAgICAgIC8vIEZpcmVmb3ggMytcbiAgICAgICAgICAgICAgICAgICAgbGFzdExhc3RJbmRleCA9IDAsXG5cbiAgICAgICAgICAgICAgICAgICAgLy8gTWFrZSBgZ2xvYmFsYCBhbmQgYXZvaWQgYGxhc3RJbmRleGAgaXNzdWVzIGJ5IHdvcmtpbmcgd2l0aCBhIGNvcHlcbiAgICAgICAgICAgICAgICAgICAgc2VwYXJhdG9yID0gbmV3IFJlZ0V4cChzZXBhcmF0b3Iuc291cmNlLCBmbGFncyArIFwiZ1wiKSxcbiAgICAgICAgICAgICAgICAgICAgICAgIHNlcGFyYXRvcjIsXG4gICAgICAgICAgICAgICAgICAgICAgICBtYXRjaCxcbiAgICAgICAgICAgICAgICAgICAgICAgIGxhc3RJbmRleCxcbiAgICAgICAgICAgICAgICAgICAgICAgIGxhc3RMZW5ndGg7XG4gICAgICAgICAgICAgICAgICAgIHN0ciArPSBcIlwiOyAvLyBUeXBlLWNvbnZlcnRcbiAgICAgICAgICAgICAgICAgICAgaWYgKCFjb21wbGlhbnRFeGVjTnBjZykge1xuICAgICAgICAgICAgICAgICAgICAgICAgLy8gRG9lc24ndCBuZWVkIGZsYWdzIGd5LCBidXQgdGhleSBkb24ndCBodXJ0XG4gICAgICAgICAgICAgICAgICAgICAgICBzZXBhcmF0b3IyID0gbmV3IFJlZ0V4cChcIl5cIiArIHNlcGFyYXRvci5zb3VyY2UgKyBcIiQoPyFcXFxccylcIiwgZmxhZ3MpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIC8qIFZhbHVlcyBmb3IgYGxpbWl0YCwgcGVyIHRoZSBzcGVjOlxuICAgICAgICAgICAgICAgICAgICAgKiBJZiB1bmRlZmluZWQ6IDQyOTQ5NjcyOTUgLy8gTWF0aC5wb3coMiwgMzIpIC0gMVxuICAgICAgICAgICAgICAgICAgICAgKiBJZiAwLCBJbmZpbml0eSwgb3IgTmFOOiAwXG4gICAgICAgICAgICAgICAgICAgICAqIElmIHBvc2l0aXZlIG51bWJlcjogbGltaXQgPSBNYXRoLmZsb29yKGxpbWl0KTsgaWYgKGxpbWl0ID4gNDI5NDk2NzI5NSkgbGltaXQgLT0gNDI5NDk2NzI5NjtcbiAgICAgICAgICAgICAgICAgICAgICogSWYgbmVnYXRpdmUgbnVtYmVyOiA0Mjk0OTY3Mjk2IC0gTWF0aC5mbG9vcihNYXRoLmFicyhsaW1pdCkpXG4gICAgICAgICAgICAgICAgICAgICAqIElmIG90aGVyOiBUeXBlLWNvbnZlcnQsIHRoZW4gdXNlIHRoZSBhYm92ZSBydWxlc1xuICAgICAgICAgICAgICAgICAgICAgKi9cbiAgICAgICAgICAgICAgICAgICAgbGltaXQgPSBsaW1pdCA9PT0gdW5kZWYgPyAtMSA+Pj4gMCA6IC8vIE1hdGgucG93KDIsIDMyKSAtIDFcbiAgICAgICAgICAgICAgICAgICAgbGltaXQgPj4+IDA7IC8vIFRvVWludDMyKGxpbWl0KVxuICAgICAgICAgICAgICAgICAgICB3aGlsZSAobWF0Y2ggPSBzZXBhcmF0b3IuZXhlYyhzdHIpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAvLyBgc2VwYXJhdG9yLmxhc3RJbmRleGAgaXMgbm90IHJlbGlhYmxlIGNyb3NzLWJyb3dzZXJcbiAgICAgICAgICAgICAgICAgICAgICAgIGxhc3RJbmRleCA9IG1hdGNoLmluZGV4ICsgbWF0Y2hbMF0ubGVuZ3RoO1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGxhc3RJbmRleCA+IGxhc3RMYXN0SW5kZXgpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBvdXRwdXQucHVzaChzdHIuc2xpY2UobGFzdExhc3RJbmRleCwgbWF0Y2guaW5kZXgpKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBGaXggYnJvd3NlcnMgd2hvc2UgYGV4ZWNgIG1ldGhvZHMgZG9uJ3QgY29uc2lzdGVudGx5IHJldHVybiBgdW5kZWZpbmVkYCBmb3JcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBub25wYXJ0aWNpcGF0aW5nIGNhcHR1cmluZyBncm91cHNcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoIWNvbXBsaWFudEV4ZWNOcGNnICYmIG1hdGNoLmxlbmd0aCA+IDEpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbWF0Y2hbMF0ucmVwbGFjZShzZXBhcmF0b3IyLCBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBmb3IgKHZhciBpID0gMTsgaSA8IGFyZ3VtZW50cy5sZW5ndGggLSAyOyBpKyspIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoYXJndW1lbnRzW2ldID09PSB1bmRlZikge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBtYXRjaFtpXSA9IHVuZGVmO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChtYXRjaC5sZW5ndGggPiAxICYmIG1hdGNoLmluZGV4IDwgc3RyLmxlbmd0aCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBBcnJheS5wcm90b3R5cGUucHVzaC5hcHBseShvdXRwdXQsIG1hdGNoLnNsaWNlKDEpKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgbGFzdExlbmd0aCA9IG1hdGNoWzBdLmxlbmd0aDtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBsYXN0TGFzdEluZGV4ID0gbGFzdEluZGV4O1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChvdXRwdXQubGVuZ3RoID49IGxpbWl0KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChzZXBhcmF0b3IubGFzdEluZGV4ID09PSBtYXRjaC5pbmRleCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNlcGFyYXRvci5sYXN0SW5kZXgrKzsgLy8gQXZvaWQgYW4gaW5maW5pdGUgbG9vcFxuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIGlmIChsYXN0TGFzdEluZGV4ID09PSBzdHIubGVuZ3RoKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAobGFzdExlbmd0aCB8fCAhc2VwYXJhdG9yLnRlc3QoXCJcIikpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBvdXRwdXQucHVzaChcIlwiKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIG91dHB1dC5wdXNoKHN0ci5zbGljZShsYXN0TGFzdEluZGV4KSk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIG91dHB1dC5sZW5ndGggPiBsaW1pdCA/IG91dHB1dC5zbGljZSgwLCBsaW1pdCkgOiBvdXRwdXQ7XG4gICAgICAgICAgICAgICAgfTtcblxuICAgICAgICAgICAgICAgIHJldHVybiBzZWxmO1xuICAgICAgICAgICAgfSkoKTtcbiAgICAgICAgfSwge31dLCA2OiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge30sIHt9XSwgNzogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHtcbiAgICAgICAgICAgIFwidXNlIHN0cmljdFwiO1xuXG4gICAgICAgICAgICB2YXIgT25lVmVyc2lvbkNvbnN0cmFpbnQgPSByZXF1aXJlKFwiaW5kaXZpZHVhbC9vbmUtdmVyc2lvblwiKTtcblxuICAgICAgICAgICAgdmFyIE1ZX1ZFUlNJT04gPSBcIjdcIjtcbiAgICAgICAgICAgIE9uZVZlcnNpb25Db25zdHJhaW50KFwiZXYtc3RvcmVcIiwgTVlfVkVSU0lPTik7XG5cbiAgICAgICAgICAgIHZhciBoYXNoS2V5ID0gXCJfX0VWX1NUT1JFX0tFWUBcIiArIE1ZX1ZFUlNJT047XG5cbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gRXZTdG9yZTtcblxuICAgICAgICAgICAgZnVuY3Rpb24gRXZTdG9yZShlbGVtKSB7XG4gICAgICAgICAgICAgICAgdmFyIGhhc2ggPSBlbGVtW2hhc2hLZXldO1xuXG4gICAgICAgICAgICAgICAgaWYgKCFoYXNoKSB7XG4gICAgICAgICAgICAgICAgICAgIGhhc2ggPSBlbGVtW2hhc2hLZXldID0ge307XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgcmV0dXJuIGhhc2g7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0sIHsgXCJpbmRpdmlkdWFsL29uZS12ZXJzaW9uXCI6IDkgfV0sIDg6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICAoZnVuY3Rpb24gKGdsb2JhbCkge1xuICAgICAgICAgICAgICAgIFwidXNlIHN0cmljdFwiO1xuXG4gICAgICAgICAgICAgICAgLypnbG9iYWwgd2luZG93LCBnbG9iYWwqL1xuXG4gICAgICAgICAgICAgICAgdmFyIHJvb3QgPSB0eXBlb2Ygd2luZG93ICE9PSBcInVuZGVmaW5lZFwiID8gd2luZG93IDogdHlwZW9mIGdsb2JhbCAhPT0gXCJ1bmRlZmluZWRcIiA/IGdsb2JhbCA6IHt9O1xuXG4gICAgICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBJbmRpdmlkdWFsO1xuXG4gICAgICAgICAgICAgICAgZnVuY3Rpb24gSW5kaXZpZHVhbChrZXksIHZhbHVlKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmIChrZXkgaW4gcm9vdCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHJvb3Rba2V5XTtcbiAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgIHJvb3Rba2V5XSA9IHZhbHVlO1xuXG4gICAgICAgICAgICAgICAgICAgIHJldHVybiB2YWx1ZTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9KS5jYWxsKHRoaXMsIHR5cGVvZiBnbG9iYWwgIT09IFwidW5kZWZpbmVkXCIgPyBnbG9iYWwgOiB0eXBlb2Ygc2VsZiAhPT0gXCJ1bmRlZmluZWRcIiA/IHNlbGYgOiB0eXBlb2Ygd2luZG93ICE9PSBcInVuZGVmaW5lZFwiID8gd2luZG93IDoge30pO1xuICAgICAgICB9LCB7fV0sIDk6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICBcInVzZSBzdHJpY3RcIjtcblxuICAgICAgICAgICAgdmFyIEluZGl2aWR1YWwgPSByZXF1aXJlKFwiLi9pbmRleC5qc1wiKTtcblxuICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBPbmVWZXJzaW9uO1xuXG4gICAgICAgICAgICBmdW5jdGlvbiBPbmVWZXJzaW9uKG1vZHVsZU5hbWUsIHZlcnNpb24sIGRlZmF1bHRWYWx1ZSkge1xuICAgICAgICAgICAgICAgIHZhciBrZXkgPSBcIl9fSU5ESVZJRFVBTF9PTkVfVkVSU0lPTl9cIiArIG1vZHVsZU5hbWU7XG4gICAgICAgICAgICAgICAgdmFyIGVuZm9yY2VLZXkgPSBrZXkgKyBcIl9FTkZPUkNFX1NJTkdMRVRPTlwiO1xuXG4gICAgICAgICAgICAgICAgdmFyIHZlcnNpb25WYWx1ZSA9IEluZGl2aWR1YWwoZW5mb3JjZUtleSwgdmVyc2lvbik7XG5cbiAgICAgICAgICAgICAgICBpZiAodmVyc2lvblZhbHVlICE9PSB2ZXJzaW9uKSB7XG4gICAgICAgICAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcihcIkNhbiBvbmx5IGhhdmUgb25lIGNvcHkgb2YgXCIgKyBtb2R1bGVOYW1lICsgXCIuXFxuXCIgKyBcIllvdSBhbHJlYWR5IGhhdmUgdmVyc2lvbiBcIiArIHZlcnNpb25WYWx1ZSArIFwiIGluc3RhbGxlZC5cXG5cIiArIFwiVGhpcyBtZWFucyB5b3UgY2Fubm90IGluc3RhbGwgdmVyc2lvbiBcIiArIHZlcnNpb24pO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHJldHVybiBJbmRpdmlkdWFsKGtleSwgZGVmYXVsdFZhbHVlKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSwgeyBcIi4vaW5kZXguanNcIjogOCB9XSwgMTA6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICAoZnVuY3Rpb24gKGdsb2JhbCkge1xuICAgICAgICAgICAgICAgIHZhciB0b3BMZXZlbCA9IHR5cGVvZiBnbG9iYWwgIT09IFwidW5kZWZpbmVkXCIgPyBnbG9iYWwgOiB0eXBlb2Ygd2luZG93ICE9PSBcInVuZGVmaW5lZFwiID8gd2luZG93IDoge307XG4gICAgICAgICAgICAgICAgdmFyIG1pbkRvYyA9IHJlcXVpcmUoXCJtaW4tZG9jdW1lbnRcIik7XG5cbiAgICAgICAgICAgICAgICBpZiAodHlwZW9mIGRvY3VtZW50ICE9PSBcInVuZGVmaW5lZFwiKSB7XG4gICAgICAgICAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gZG9jdW1lbnQ7XG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgdmFyIGRvY2N5ID0gdG9wTGV2ZWxbXCJfX0dMT0JBTF9ET0NVTUVOVF9DQUNIRUA0XCJdO1xuXG4gICAgICAgICAgICAgICAgICAgIGlmICghZG9jY3kpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGRvY2N5ID0gdG9wTGV2ZWxbXCJfX0dMT0JBTF9ET0NVTUVOVF9DQUNIRUA0XCJdID0gbWluRG9jO1xuICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBkb2NjeTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9KS5jYWxsKHRoaXMsIHR5cGVvZiBnbG9iYWwgIT09IFwidW5kZWZpbmVkXCIgPyBnbG9iYWwgOiB0eXBlb2Ygc2VsZiAhPT0gXCJ1bmRlZmluZWRcIiA/IHNlbGYgOiB0eXBlb2Ygd2luZG93ICE9PSBcInVuZGVmaW5lZFwiID8gd2luZG93IDoge30pO1xuICAgICAgICB9LCB7IFwibWluLWRvY3VtZW50XCI6IDYgfV0sIDExOiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge1xuICAgICAgICAgICAgXCJ1c2Ugc3RyaWN0XCI7XG5cbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gaXNPYmplY3QoeCkge1xuICAgICAgICAgICAgICAgIHJldHVybiB0eXBlb2YgeCA9PT0gXCJvYmplY3RcIiAmJiB4ICE9PSBudWxsO1xuICAgICAgICAgICAgfTtcbiAgICAgICAgfSwge31dLCAxMjogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHtcbiAgICAgICAgICAgIHZhciBuYXRpdmVJc0FycmF5ID0gQXJyYXkuaXNBcnJheTtcbiAgICAgICAgICAgIHZhciB0b1N0cmluZyA9IE9iamVjdC5wcm90b3R5cGUudG9TdHJpbmc7XG5cbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gbmF0aXZlSXNBcnJheSB8fCBpc0FycmF5O1xuXG4gICAgICAgICAgICBmdW5jdGlvbiBpc0FycmF5KG9iaikge1xuICAgICAgICAgICAgICAgIHJldHVybiB0b1N0cmluZy5jYWxsKG9iaikgPT09IFwiW29iamVjdCBBcnJheV1cIjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSwge31dLCAxMzogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHtcbiAgICAgICAgICAgIHZhciBwYXRjaCA9IHJlcXVpcmUoXCIuL3Zkb20vcGF0Y2guanNcIik7XG5cbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gcGF0Y2g7XG4gICAgICAgIH0sIHsgXCIuL3Zkb20vcGF0Y2guanNcIjogMTggfV0sIDE0OiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge1xuICAgICAgICAgICAgdmFyIGlzT2JqZWN0ID0gcmVxdWlyZShcImlzLW9iamVjdFwiKTtcbiAgICAgICAgICAgIHZhciBpc0hvb2sgPSByZXF1aXJlKFwiLi4vdm5vZGUvaXMtdmhvb2suanNcIik7XG5cbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gYXBwbHlQcm9wZXJ0aWVzO1xuXG4gICAgICAgICAgICBmdW5jdGlvbiBhcHBseVByb3BlcnRpZXMobm9kZSwgcHJvcHMsIHByZXZpb3VzKSB7XG4gICAgICAgICAgICAgICAgZm9yICh2YXIgcHJvcE5hbWUgaW4gcHJvcHMpIHtcbiAgICAgICAgICAgICAgICAgICAgdmFyIHByb3BWYWx1ZSA9IHByb3BzW3Byb3BOYW1lXTtcblxuICAgICAgICAgICAgICAgICAgICBpZiAocHJvcFZhbHVlID09PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJlbW92ZVByb3BlcnR5KG5vZGUsIHByb3BOYW1lLCBwcm9wVmFsdWUsIHByZXZpb3VzKTtcbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIGlmIChpc0hvb2socHJvcFZhbHVlKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgcmVtb3ZlUHJvcGVydHkobm9kZSwgcHJvcE5hbWUsIHByb3BWYWx1ZSwgcHJldmlvdXMpO1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHByb3BWYWx1ZS5ob29rKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcHJvcFZhbHVlLmhvb2sobm9kZSwgcHJvcE5hbWUsIHByZXZpb3VzID8gcHJldmlvdXNbcHJvcE5hbWVdIDogdW5kZWZpbmVkKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChpc09iamVjdChwcm9wVmFsdWUpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcGF0Y2hPYmplY3Qobm9kZSwgcHJvcHMsIHByZXZpb3VzLCBwcm9wTmFtZSwgcHJvcFZhbHVlKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgbm9kZVtwcm9wTmFtZV0gPSBwcm9wVmFsdWU7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIHJlbW92ZVByb3BlcnR5KG5vZGUsIHByb3BOYW1lLCBwcm9wVmFsdWUsIHByZXZpb3VzKSB7XG4gICAgICAgICAgICAgICAgaWYgKHByZXZpb3VzKSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciBwcmV2aW91c1ZhbHVlID0gcHJldmlvdXNbcHJvcE5hbWVdO1xuXG4gICAgICAgICAgICAgICAgICAgIGlmICghaXNIb29rKHByZXZpb3VzVmFsdWUpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAocHJvcE5hbWUgPT09IFwiYXR0cmlidXRlc1wiKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgZm9yICh2YXIgYXR0ck5hbWUgaW4gcHJldmlvdXNWYWx1ZSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBub2RlLnJlbW92ZUF0dHJpYnV0ZShhdHRyTmFtZSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIGlmIChwcm9wTmFtZSA9PT0gXCJzdHlsZVwiKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgZm9yICh2YXIgaSBpbiBwcmV2aW91c1ZhbHVlKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG5vZGUuc3R5bGVbaV0gPSBcIlwiO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAodHlwZW9mIHByZXZpb3VzVmFsdWUgPT09IFwic3RyaW5nXCIpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBub2RlW3Byb3BOYW1lXSA9IFwiXCI7XG4gICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIG5vZGVbcHJvcE5hbWVdID0gbnVsbDtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIGlmIChwcmV2aW91c1ZhbHVlLnVuaG9vaykge1xuICAgICAgICAgICAgICAgICAgICAgICAgcHJldmlvdXNWYWx1ZS51bmhvb2sobm9kZSwgcHJvcE5hbWUsIHByb3BWYWx1ZSk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIHBhdGNoT2JqZWN0KG5vZGUsIHByb3BzLCBwcmV2aW91cywgcHJvcE5hbWUsIHByb3BWYWx1ZSkge1xuICAgICAgICAgICAgICAgIHZhciBwcmV2aW91c1ZhbHVlID0gcHJldmlvdXMgPyBwcmV2aW91c1twcm9wTmFtZV0gOiB1bmRlZmluZWQ7XG5cbiAgICAgICAgICAgICAgICAvLyBTZXQgYXR0cmlidXRlc1xuICAgICAgICAgICAgICAgIGlmIChwcm9wTmFtZSA9PT0gXCJhdHRyaWJ1dGVzXCIpIHtcbiAgICAgICAgICAgICAgICAgICAgZm9yICh2YXIgYXR0ck5hbWUgaW4gcHJvcFZhbHVlKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICB2YXIgYXR0clZhbHVlID0gcHJvcFZhbHVlW2F0dHJOYW1lXTtcblxuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGF0dHJWYWx1ZSA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgbm9kZS5yZW1vdmVBdHRyaWJ1dGUoYXR0ck5hbWUpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBub2RlLnNldEF0dHJpYnV0ZShhdHRyTmFtZSwgYXR0clZhbHVlKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICBpZiAocHJldmlvdXNWYWx1ZSAmJiBpc09iamVjdChwcmV2aW91c1ZhbHVlKSAmJiBnZXRQcm90b3R5cGUocHJldmlvdXNWYWx1ZSkgIT09IGdldFByb3RvdHlwZShwcm9wVmFsdWUpKSB7XG4gICAgICAgICAgICAgICAgICAgIG5vZGVbcHJvcE5hbWVdID0gcHJvcFZhbHVlO1xuICAgICAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgaWYgKCFpc09iamVjdChub2RlW3Byb3BOYW1lXSkpIHtcbiAgICAgICAgICAgICAgICAgICAgbm9kZVtwcm9wTmFtZV0gPSB7fTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICB2YXIgcmVwbGFjZXIgPSBwcm9wTmFtZSA9PT0gXCJzdHlsZVwiID8gXCJcIiA6IHVuZGVmaW5lZDtcblxuICAgICAgICAgICAgICAgIGZvciAodmFyIGsgaW4gcHJvcFZhbHVlKSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciB2YWx1ZSA9IHByb3BWYWx1ZVtrXTtcbiAgICAgICAgICAgICAgICAgICAgbm9kZVtwcm9wTmFtZV1ba10gPSB2YWx1ZSA9PT0gdW5kZWZpbmVkID8gcmVwbGFjZXIgOiB2YWx1ZTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIGdldFByb3RvdHlwZSh2YWx1ZSkge1xuICAgICAgICAgICAgICAgIGlmIChPYmplY3QuZ2V0UHJvdG90eXBlT2YpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIE9iamVjdC5nZXRQcm90b3R5cGVPZih2YWx1ZSk7XG4gICAgICAgICAgICAgICAgfSBlbHNlIGlmICh2YWx1ZS5fX3Byb3RvX18pIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHZhbHVlLl9fcHJvdG9fXztcbiAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKHZhbHVlLmNvbnN0cnVjdG9yKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiB2YWx1ZS5jb25zdHJ1Y3Rvci5wcm90b3R5cGU7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9LCB7IFwiLi4vdm5vZGUvaXMtdmhvb2suanNcIjogMjYsIFwiaXMtb2JqZWN0XCI6IDExIH1dLCAxNTogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHtcbiAgICAgICAgICAgIHZhciBkb2N1bWVudCA9IHJlcXVpcmUoXCJnbG9iYWwvZG9jdW1lbnRcIik7XG5cbiAgICAgICAgICAgIHZhciBhcHBseVByb3BlcnRpZXMgPSByZXF1aXJlKFwiLi9hcHBseS1wcm9wZXJ0aWVzXCIpO1xuXG4gICAgICAgICAgICB2YXIgaXNWTm9kZSA9IHJlcXVpcmUoXCIuLi92bm9kZS9pcy12bm9kZS5qc1wiKTtcbiAgICAgICAgICAgIHZhciBpc1ZUZXh0ID0gcmVxdWlyZShcIi4uL3Zub2RlL2lzLXZ0ZXh0LmpzXCIpO1xuICAgICAgICAgICAgdmFyIGlzV2lkZ2V0ID0gcmVxdWlyZShcIi4uL3Zub2RlL2lzLXdpZGdldC5qc1wiKTtcbiAgICAgICAgICAgIHZhciBoYW5kbGVUaHVuayA9IHJlcXVpcmUoXCIuLi92bm9kZS9oYW5kbGUtdGh1bmsuanNcIik7XG5cbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gY3JlYXRlRWxlbWVudDtcblxuICAgICAgICAgICAgZnVuY3Rpb24gY3JlYXRlRWxlbWVudCh2bm9kZSwgb3B0cykge1xuICAgICAgICAgICAgICAgIHZhciBkb2MgPSBvcHRzID8gb3B0cy5kb2N1bWVudCB8fCBkb2N1bWVudCA6IGRvY3VtZW50O1xuICAgICAgICAgICAgICAgIHZhciB3YXJuID0gb3B0cyA/IG9wdHMud2FybiA6IG51bGw7XG5cbiAgICAgICAgICAgICAgICB2bm9kZSA9IGhhbmRsZVRodW5rKHZub2RlKS5hO1xuXG4gICAgICAgICAgICAgICAgaWYgKGlzV2lkZ2V0KHZub2RlKSkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gdm5vZGUuaW5pdCgpO1xuICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoaXNWVGV4dCh2bm9kZSkpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGRvYy5jcmVhdGVUZXh0Tm9kZSh2bm9kZS50ZXh0KTtcbiAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKCFpc1ZOb2RlKHZub2RlKSkge1xuICAgICAgICAgICAgICAgICAgICBpZiAod2Fybikge1xuICAgICAgICAgICAgICAgICAgICAgICAgd2FybihcIkl0ZW0gaXMgbm90IGEgdmFsaWQgdmlydHVhbCBkb20gbm9kZVwiLCB2bm9kZSk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIG51bGw7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgdmFyIG5vZGUgPSB2bm9kZS5uYW1lc3BhY2UgPT09IG51bGwgPyBkb2MuY3JlYXRlRWxlbWVudCh2bm9kZS50YWdOYW1lKSA6IGRvYy5jcmVhdGVFbGVtZW50TlModm5vZGUubmFtZXNwYWNlLCB2bm9kZS50YWdOYW1lKTtcblxuICAgICAgICAgICAgICAgIHZhciBwcm9wcyA9IHZub2RlLnByb3BlcnRpZXM7XG4gICAgICAgICAgICAgICAgYXBwbHlQcm9wZXJ0aWVzKG5vZGUsIHByb3BzKTtcblxuICAgICAgICAgICAgICAgIHZhciBjaGlsZHJlbiA9IHZub2RlLmNoaWxkcmVuO1xuXG4gICAgICAgICAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCBjaGlsZHJlbi5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgICAgICAgICB2YXIgY2hpbGROb2RlID0gY3JlYXRlRWxlbWVudChjaGlsZHJlbltpXSwgb3B0cyk7XG4gICAgICAgICAgICAgICAgICAgIGlmIChjaGlsZE5vZGUpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIG5vZGUuYXBwZW5kQ2hpbGQoY2hpbGROb2RlKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHJldHVybiBub2RlO1xuICAgICAgICAgICAgfVxuICAgICAgICB9LCB7IFwiLi4vdm5vZGUvaGFuZGxlLXRodW5rLmpzXCI6IDI0LCBcIi4uL3Zub2RlL2lzLXZub2RlLmpzXCI6IDI3LCBcIi4uL3Zub2RlL2lzLXZ0ZXh0LmpzXCI6IDI4LCBcIi4uL3Zub2RlL2lzLXdpZGdldC5qc1wiOiAyOSwgXCIuL2FwcGx5LXByb3BlcnRpZXNcIjogMTQsIFwiZ2xvYmFsL2RvY3VtZW50XCI6IDEwIH1dLCAxNjogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHtcbiAgICAgICAgICAgIC8vIE1hcHMgYSB2aXJ0dWFsIERPTSB0cmVlIG9udG8gYSByZWFsIERPTSB0cmVlIGluIGFuIGVmZmljaWVudCBtYW5uZXIuXG4gICAgICAgICAgICAvLyBXZSBkb24ndCB3YW50IHRvIHJlYWQgYWxsIG9mIHRoZSBET00gbm9kZXMgaW4gdGhlIHRyZWUgc28gd2UgdXNlXG4gICAgICAgICAgICAvLyB0aGUgaW4tb3JkZXIgdHJlZSBpbmRleGluZyB0byBlbGltaW5hdGUgcmVjdXJzaW9uIGRvd24gY2VydGFpbiBicmFuY2hlcy5cbiAgICAgICAgICAgIC8vIFdlIG9ubHkgcmVjdXJzZSBpbnRvIGEgRE9NIG5vZGUgaWYgd2Uga25vdyB0aGF0IGl0IGNvbnRhaW5zIGEgY2hpbGQgb2ZcbiAgICAgICAgICAgIC8vIGludGVyZXN0LlxuXG4gICAgICAgICAgICB2YXIgbm9DaGlsZCA9IHt9O1xuXG4gICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IGRvbUluZGV4O1xuXG4gICAgICAgICAgICBmdW5jdGlvbiBkb21JbmRleChyb290Tm9kZSwgdHJlZSwgaW5kaWNlcywgbm9kZXMpIHtcbiAgICAgICAgICAgICAgICBpZiAoIWluZGljZXMgfHwgaW5kaWNlcy5sZW5ndGggPT09IDApIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHt9O1xuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIGluZGljZXMuc29ydChhc2NlbmRpbmcpO1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gcmVjdXJzZShyb290Tm9kZSwgdHJlZSwgaW5kaWNlcywgbm9kZXMsIDApO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZnVuY3Rpb24gcmVjdXJzZShyb290Tm9kZSwgdHJlZSwgaW5kaWNlcywgbm9kZXMsIHJvb3RJbmRleCkge1xuICAgICAgICAgICAgICAgIG5vZGVzID0gbm9kZXMgfHwge307XG5cbiAgICAgICAgICAgICAgICBpZiAocm9vdE5vZGUpIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKGluZGV4SW5SYW5nZShpbmRpY2VzLCByb290SW5kZXgsIHJvb3RJbmRleCkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIG5vZGVzW3Jvb3RJbmRleF0gPSByb290Tm9kZTtcbiAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgIHZhciB2Q2hpbGRyZW4gPSB0cmVlLmNoaWxkcmVuO1xuXG4gICAgICAgICAgICAgICAgICAgIGlmICh2Q2hpbGRyZW4pIHtcblxuICAgICAgICAgICAgICAgICAgICAgICAgdmFyIGNoaWxkTm9kZXMgPSByb290Tm9kZS5jaGlsZE5vZGVzO1xuXG4gICAgICAgICAgICAgICAgICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IHRyZWUuY2hpbGRyZW4ubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICByb290SW5kZXggKz0gMTtcblxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZhciB2Q2hpbGQgPSB2Q2hpbGRyZW5baV0gfHwgbm9DaGlsZDtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB2YXIgbmV4dEluZGV4ID0gcm9vdEluZGV4ICsgKHZDaGlsZC5jb3VudCB8fCAwKTtcblxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIHNraXAgcmVjdXJzaW9uIGRvd24gdGhlIHRyZWUgaWYgdGhlcmUgYXJlIG5vIG5vZGVzIGRvd24gaGVyZVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChpbmRleEluUmFuZ2UoaW5kaWNlcywgcm9vdEluZGV4LCBuZXh0SW5kZXgpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlY3Vyc2UoY2hpbGROb2Rlc1tpXSwgdkNoaWxkLCBpbmRpY2VzLCBub2Rlcywgcm9vdEluZGV4KTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICByb290SW5kZXggPSBuZXh0SW5kZXg7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICByZXR1cm4gbm9kZXM7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIC8vIEJpbmFyeSBzZWFyY2ggZm9yIGFuIGluZGV4IGluIHRoZSBpbnRlcnZhbCBbbGVmdCwgcmlnaHRdXG4gICAgICAgICAgICBmdW5jdGlvbiBpbmRleEluUmFuZ2UoaW5kaWNlcywgbGVmdCwgcmlnaHQpIHtcbiAgICAgICAgICAgICAgICBpZiAoaW5kaWNlcy5sZW5ndGggPT09IDApIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHZhciBtaW5JbmRleCA9IDA7XG4gICAgICAgICAgICAgICAgdmFyIG1heEluZGV4ID0gaW5kaWNlcy5sZW5ndGggLSAxO1xuICAgICAgICAgICAgICAgIHZhciBjdXJyZW50SW5kZXg7XG4gICAgICAgICAgICAgICAgdmFyIGN1cnJlbnRJdGVtO1xuXG4gICAgICAgICAgICAgICAgd2hpbGUgKG1pbkluZGV4IDw9IG1heEluZGV4KSB7XG4gICAgICAgICAgICAgICAgICAgIGN1cnJlbnRJbmRleCA9IChtYXhJbmRleCArIG1pbkluZGV4KSAvIDIgPj4gMDtcbiAgICAgICAgICAgICAgICAgICAgY3VycmVudEl0ZW0gPSBpbmRpY2VzW2N1cnJlbnRJbmRleF07XG5cbiAgICAgICAgICAgICAgICAgICAgaWYgKG1pbkluZGV4ID09PSBtYXhJbmRleCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGN1cnJlbnRJdGVtID49IGxlZnQgJiYgY3VycmVudEl0ZW0gPD0gcmlnaHQ7XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoY3VycmVudEl0ZW0gPCBsZWZ0KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBtaW5JbmRleCA9IGN1cnJlbnRJbmRleCArIDE7XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoY3VycmVudEl0ZW0gPiByaWdodCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgbWF4SW5kZXggPSBjdXJyZW50SW5kZXggLSAxO1xuICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIGFzY2VuZGluZyhhLCBiKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGEgPiBiID8gMSA6IC0xO1xuICAgICAgICAgICAgfVxuICAgICAgICB9LCB7fV0sIDE3OiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge1xuICAgICAgICAgICAgdmFyIGFwcGx5UHJvcGVydGllcyA9IHJlcXVpcmUoXCIuL2FwcGx5LXByb3BlcnRpZXNcIik7XG5cbiAgICAgICAgICAgIHZhciBpc1dpZGdldCA9IHJlcXVpcmUoXCIuLi92bm9kZS9pcy13aWRnZXQuanNcIik7XG4gICAgICAgICAgICB2YXIgVlBhdGNoID0gcmVxdWlyZShcIi4uL3Zub2RlL3ZwYXRjaC5qc1wiKTtcblxuICAgICAgICAgICAgdmFyIHVwZGF0ZVdpZGdldCA9IHJlcXVpcmUoXCIuL3VwZGF0ZS13aWRnZXRcIik7XG5cbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gYXBwbHlQYXRjaDtcblxuICAgICAgICAgICAgZnVuY3Rpb24gYXBwbHlQYXRjaCh2cGF0Y2gsIGRvbU5vZGUsIHJlbmRlck9wdGlvbnMpIHtcbiAgICAgICAgICAgICAgICB2YXIgdHlwZSA9IHZwYXRjaC50eXBlO1xuICAgICAgICAgICAgICAgIHZhciB2Tm9kZSA9IHZwYXRjaC52Tm9kZTtcbiAgICAgICAgICAgICAgICB2YXIgcGF0Y2ggPSB2cGF0Y2gucGF0Y2g7XG5cbiAgICAgICAgICAgICAgICBzd2l0Y2ggKHR5cGUpIHtcbiAgICAgICAgICAgICAgICAgICAgY2FzZSBWUGF0Y2guUkVNT1ZFOlxuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHJlbW92ZU5vZGUoZG9tTm9kZSwgdk5vZGUpO1xuICAgICAgICAgICAgICAgICAgICBjYXNlIFZQYXRjaC5JTlNFUlQ6XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gaW5zZXJ0Tm9kZShkb21Ob2RlLCBwYXRjaCwgcmVuZGVyT3B0aW9ucyk7XG4gICAgICAgICAgICAgICAgICAgIGNhc2UgVlBhdGNoLlZURVhUOlxuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHN0cmluZ1BhdGNoKGRvbU5vZGUsIHZOb2RlLCBwYXRjaCwgcmVuZGVyT3B0aW9ucyk7XG4gICAgICAgICAgICAgICAgICAgIGNhc2UgVlBhdGNoLldJREdFVDpcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiB3aWRnZXRQYXRjaChkb21Ob2RlLCB2Tm9kZSwgcGF0Y2gsIHJlbmRlck9wdGlvbnMpO1xuICAgICAgICAgICAgICAgICAgICBjYXNlIFZQYXRjaC5WTk9ERTpcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiB2Tm9kZVBhdGNoKGRvbU5vZGUsIHZOb2RlLCBwYXRjaCwgcmVuZGVyT3B0aW9ucyk7XG4gICAgICAgICAgICAgICAgICAgIGNhc2UgVlBhdGNoLk9SREVSOlxuICAgICAgICAgICAgICAgICAgICAgICAgcmVvcmRlckNoaWxkcmVuKGRvbU5vZGUsIHBhdGNoKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBkb21Ob2RlO1xuICAgICAgICAgICAgICAgICAgICBjYXNlIFZQYXRjaC5QUk9QUzpcbiAgICAgICAgICAgICAgICAgICAgICAgIGFwcGx5UHJvcGVydGllcyhkb21Ob2RlLCBwYXRjaCwgdk5vZGUucHJvcGVydGllcyk7XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gZG9tTm9kZTtcbiAgICAgICAgICAgICAgICAgICAgY2FzZSBWUGF0Y2guVEhVTks6XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gcmVwbGFjZVJvb3QoZG9tTm9kZSwgcmVuZGVyT3B0aW9ucy5wYXRjaChkb21Ob2RlLCBwYXRjaCwgcmVuZGVyT3B0aW9ucykpO1xuICAgICAgICAgICAgICAgICAgICBkZWZhdWx0OlxuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGRvbU5vZGU7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBmdW5jdGlvbiByZW1vdmVOb2RlKGRvbU5vZGUsIHZOb2RlKSB7XG4gICAgICAgICAgICAgICAgdmFyIHBhcmVudE5vZGUgPSBkb21Ob2RlLnBhcmVudE5vZGU7XG5cbiAgICAgICAgICAgICAgICBpZiAocGFyZW50Tm9kZSkge1xuICAgICAgICAgICAgICAgICAgICBwYXJlbnROb2RlLnJlbW92ZUNoaWxkKGRvbU5vZGUpO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIGRlc3Ryb3lXaWRnZXQoZG9tTm9kZSwgdk5vZGUpO1xuXG4gICAgICAgICAgICAgICAgcmV0dXJuIG51bGw7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIGluc2VydE5vZGUocGFyZW50Tm9kZSwgdk5vZGUsIHJlbmRlck9wdGlvbnMpIHtcbiAgICAgICAgICAgICAgICB2YXIgbmV3Tm9kZSA9IHJlbmRlck9wdGlvbnMucmVuZGVyKHZOb2RlLCByZW5kZXJPcHRpb25zKTtcblxuICAgICAgICAgICAgICAgIGlmIChwYXJlbnROb2RlKSB7XG4gICAgICAgICAgICAgICAgICAgIHBhcmVudE5vZGUuYXBwZW5kQ2hpbGQobmV3Tm9kZSk7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgcmV0dXJuIHBhcmVudE5vZGU7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIHN0cmluZ1BhdGNoKGRvbU5vZGUsIGxlZnRWTm9kZSwgdlRleHQsIHJlbmRlck9wdGlvbnMpIHtcbiAgICAgICAgICAgICAgICB2YXIgbmV3Tm9kZTtcblxuICAgICAgICAgICAgICAgIGlmIChkb21Ob2RlLm5vZGVUeXBlID09PSAzKSB7XG4gICAgICAgICAgICAgICAgICAgIGRvbU5vZGUucmVwbGFjZURhdGEoMCwgZG9tTm9kZS5sZW5ndGgsIHZUZXh0LnRleHQpO1xuICAgICAgICAgICAgICAgICAgICBuZXdOb2RlID0gZG9tTm9kZTtcbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICB2YXIgcGFyZW50Tm9kZSA9IGRvbU5vZGUucGFyZW50Tm9kZTtcbiAgICAgICAgICAgICAgICAgICAgbmV3Tm9kZSA9IHJlbmRlck9wdGlvbnMucmVuZGVyKHZUZXh0LCByZW5kZXJPcHRpb25zKTtcblxuICAgICAgICAgICAgICAgICAgICBpZiAocGFyZW50Tm9kZSAmJiBuZXdOb2RlICE9PSBkb21Ob2RlKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBwYXJlbnROb2RlLnJlcGxhY2VDaGlsZChuZXdOb2RlLCBkb21Ob2RlKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHJldHVybiBuZXdOb2RlO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBmdW5jdGlvbiB3aWRnZXRQYXRjaChkb21Ob2RlLCBsZWZ0Vk5vZGUsIHdpZGdldCwgcmVuZGVyT3B0aW9ucykge1xuICAgICAgICAgICAgICAgIHZhciB1cGRhdGluZyA9IHVwZGF0ZVdpZGdldChsZWZ0Vk5vZGUsIHdpZGdldCk7XG4gICAgICAgICAgICAgICAgdmFyIG5ld05vZGU7XG5cbiAgICAgICAgICAgICAgICBpZiAodXBkYXRpbmcpIHtcbiAgICAgICAgICAgICAgICAgICAgbmV3Tm9kZSA9IHdpZGdldC51cGRhdGUobGVmdFZOb2RlLCBkb21Ob2RlKSB8fCBkb21Ob2RlO1xuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIG5ld05vZGUgPSByZW5kZXJPcHRpb25zLnJlbmRlcih3aWRnZXQsIHJlbmRlck9wdGlvbnMpO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHZhciBwYXJlbnROb2RlID0gZG9tTm9kZS5wYXJlbnROb2RlO1xuXG4gICAgICAgICAgICAgICAgaWYgKHBhcmVudE5vZGUgJiYgbmV3Tm9kZSAhPT0gZG9tTm9kZSkge1xuICAgICAgICAgICAgICAgICAgICBwYXJlbnROb2RlLnJlcGxhY2VDaGlsZChuZXdOb2RlLCBkb21Ob2RlKTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICBpZiAoIXVwZGF0aW5nKSB7XG4gICAgICAgICAgICAgICAgICAgIGRlc3Ryb3lXaWRnZXQoZG9tTm9kZSwgbGVmdFZOb2RlKTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICByZXR1cm4gbmV3Tm9kZTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZnVuY3Rpb24gdk5vZGVQYXRjaChkb21Ob2RlLCBsZWZ0Vk5vZGUsIHZOb2RlLCByZW5kZXJPcHRpb25zKSB7XG4gICAgICAgICAgICAgICAgdmFyIHBhcmVudE5vZGUgPSBkb21Ob2RlLnBhcmVudE5vZGU7XG4gICAgICAgICAgICAgICAgdmFyIG5ld05vZGUgPSByZW5kZXJPcHRpb25zLnJlbmRlcih2Tm9kZSwgcmVuZGVyT3B0aW9ucyk7XG5cbiAgICAgICAgICAgICAgICBpZiAocGFyZW50Tm9kZSAmJiBuZXdOb2RlICE9PSBkb21Ob2RlKSB7XG4gICAgICAgICAgICAgICAgICAgIHBhcmVudE5vZGUucmVwbGFjZUNoaWxkKG5ld05vZGUsIGRvbU5vZGUpO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHJldHVybiBuZXdOb2RlO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBmdW5jdGlvbiBkZXN0cm95V2lkZ2V0KGRvbU5vZGUsIHcpIHtcbiAgICAgICAgICAgICAgICBpZiAodHlwZW9mIHcuZGVzdHJveSA9PT0gXCJmdW5jdGlvblwiICYmIGlzV2lkZ2V0KHcpKSB7XG4gICAgICAgICAgICAgICAgICAgIHcuZGVzdHJveShkb21Ob2RlKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIHJlb3JkZXJDaGlsZHJlbihkb21Ob2RlLCBtb3Zlcykge1xuICAgICAgICAgICAgICAgIHZhciBjaGlsZE5vZGVzID0gZG9tTm9kZS5jaGlsZE5vZGVzO1xuICAgICAgICAgICAgICAgIHZhciBrZXlNYXAgPSB7fTtcbiAgICAgICAgICAgICAgICB2YXIgbm9kZTtcbiAgICAgICAgICAgICAgICB2YXIgcmVtb3ZlO1xuICAgICAgICAgICAgICAgIHZhciBpbnNlcnQ7XG5cbiAgICAgICAgICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IG1vdmVzLnJlbW92ZXMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgICAgICAgICAgcmVtb3ZlID0gbW92ZXMucmVtb3Zlc1tpXTtcbiAgICAgICAgICAgICAgICAgICAgbm9kZSA9IGNoaWxkTm9kZXNbcmVtb3ZlLmZyb21dO1xuICAgICAgICAgICAgICAgICAgICBpZiAocmVtb3ZlLmtleSkge1xuICAgICAgICAgICAgICAgICAgICAgICAga2V5TWFwW3JlbW92ZS5rZXldID0gbm9kZTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICBkb21Ob2RlLnJlbW92ZUNoaWxkKG5vZGUpO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHZhciBsZW5ndGggPSBjaGlsZE5vZGVzLmxlbmd0aDtcbiAgICAgICAgICAgICAgICBmb3IgKHZhciBqID0gMDsgaiA8IG1vdmVzLmluc2VydHMubGVuZ3RoOyBqKyspIHtcbiAgICAgICAgICAgICAgICAgICAgaW5zZXJ0ID0gbW92ZXMuaW5zZXJ0c1tqXTtcbiAgICAgICAgICAgICAgICAgICAgbm9kZSA9IGtleU1hcFtpbnNlcnQua2V5XTtcbiAgICAgICAgICAgICAgICAgICAgLy8gdGhpcyBpcyB0aGUgd2VpcmRlc3QgYnVnIGkndmUgZXZlciBzZWVuIGluIHdlYmtpdFxuICAgICAgICAgICAgICAgICAgICBkb21Ob2RlLmluc2VydEJlZm9yZShub2RlLCBpbnNlcnQudG8gPj0gbGVuZ3RoKysgPyBudWxsIDogY2hpbGROb2Rlc1tpbnNlcnQudG9dKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIHJlcGxhY2VSb290KG9sZFJvb3QsIG5ld1Jvb3QpIHtcbiAgICAgICAgICAgICAgICBpZiAob2xkUm9vdCAmJiBuZXdSb290ICYmIG9sZFJvb3QgIT09IG5ld1Jvb3QgJiYgb2xkUm9vdC5wYXJlbnROb2RlKSB7XG4gICAgICAgICAgICAgICAgICAgIG9sZFJvb3QucGFyZW50Tm9kZS5yZXBsYWNlQ2hpbGQobmV3Um9vdCwgb2xkUm9vdCk7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgcmV0dXJuIG5ld1Jvb3Q7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0sIHsgXCIuLi92bm9kZS9pcy13aWRnZXQuanNcIjogMjksIFwiLi4vdm5vZGUvdnBhdGNoLmpzXCI6IDMyLCBcIi4vYXBwbHktcHJvcGVydGllc1wiOiAxNCwgXCIuL3VwZGF0ZS13aWRnZXRcIjogMTkgfV0sIDE4OiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge1xuICAgICAgICAgICAgdmFyIGRvY3VtZW50ID0gcmVxdWlyZShcImdsb2JhbC9kb2N1bWVudFwiKTtcbiAgICAgICAgICAgIHZhciBpc0FycmF5ID0gcmVxdWlyZShcIngtaXMtYXJyYXlcIik7XG5cbiAgICAgICAgICAgIHZhciByZW5kZXIgPSByZXF1aXJlKFwiLi9jcmVhdGUtZWxlbWVudFwiKTtcbiAgICAgICAgICAgIHZhciBkb21JbmRleCA9IHJlcXVpcmUoXCIuL2RvbS1pbmRleFwiKTtcbiAgICAgICAgICAgIHZhciBwYXRjaE9wID0gcmVxdWlyZShcIi4vcGF0Y2gtb3BcIik7XG4gICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IHBhdGNoO1xuXG4gICAgICAgICAgICBmdW5jdGlvbiBwYXRjaChyb290Tm9kZSwgcGF0Y2hlcywgcmVuZGVyT3B0aW9ucykge1xuICAgICAgICAgICAgICAgIHJlbmRlck9wdGlvbnMgPSByZW5kZXJPcHRpb25zIHx8IHt9O1xuICAgICAgICAgICAgICAgIHJlbmRlck9wdGlvbnMucGF0Y2ggPSByZW5kZXJPcHRpb25zLnBhdGNoICYmIHJlbmRlck9wdGlvbnMucGF0Y2ggIT09IHBhdGNoID8gcmVuZGVyT3B0aW9ucy5wYXRjaCA6IHBhdGNoUmVjdXJzaXZlO1xuICAgICAgICAgICAgICAgIHJlbmRlck9wdGlvbnMucmVuZGVyID0gcmVuZGVyT3B0aW9ucy5yZW5kZXIgfHwgcmVuZGVyO1xuXG4gICAgICAgICAgICAgICAgcmV0dXJuIHJlbmRlck9wdGlvbnMucGF0Y2gocm9vdE5vZGUsIHBhdGNoZXMsIHJlbmRlck9wdGlvbnMpO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBmdW5jdGlvbiBwYXRjaFJlY3Vyc2l2ZShyb290Tm9kZSwgcGF0Y2hlcywgcmVuZGVyT3B0aW9ucykge1xuICAgICAgICAgICAgICAgIHZhciBpbmRpY2VzID0gcGF0Y2hJbmRpY2VzKHBhdGNoZXMpO1xuXG4gICAgICAgICAgICAgICAgaWYgKGluZGljZXMubGVuZ3RoID09PSAwKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiByb290Tm9kZTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICB2YXIgaW5kZXggPSBkb21JbmRleChyb290Tm9kZSwgcGF0Y2hlcy5hLCBpbmRpY2VzKTtcbiAgICAgICAgICAgICAgICB2YXIgb3duZXJEb2N1bWVudCA9IHJvb3ROb2RlLm93bmVyRG9jdW1lbnQ7XG5cbiAgICAgICAgICAgICAgICBpZiAoIXJlbmRlck9wdGlvbnMuZG9jdW1lbnQgJiYgb3duZXJEb2N1bWVudCAhPT0gZG9jdW1lbnQpIHtcbiAgICAgICAgICAgICAgICAgICAgcmVuZGVyT3B0aW9ucy5kb2N1bWVudCA9IG93bmVyRG9jdW1lbnQ7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCBpbmRpY2VzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciBub2RlSW5kZXggPSBpbmRpY2VzW2ldO1xuICAgICAgICAgICAgICAgICAgICByb290Tm9kZSA9IGFwcGx5UGF0Y2gocm9vdE5vZGUsIGluZGV4W25vZGVJbmRleF0sIHBhdGNoZXNbbm9kZUluZGV4XSwgcmVuZGVyT3B0aW9ucyk7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgcmV0dXJuIHJvb3ROb2RlO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBmdW5jdGlvbiBhcHBseVBhdGNoKHJvb3ROb2RlLCBkb21Ob2RlLCBwYXRjaExpc3QsIHJlbmRlck9wdGlvbnMpIHtcbiAgICAgICAgICAgICAgICBpZiAoIWRvbU5vZGUpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHJvb3ROb2RlO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHZhciBuZXdOb2RlO1xuXG4gICAgICAgICAgICAgICAgaWYgKGlzQXJyYXkocGF0Y2hMaXN0KSkge1xuICAgICAgICAgICAgICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IHBhdGNoTGlzdC5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgICAgICAgICAgICAgbmV3Tm9kZSA9IHBhdGNoT3AocGF0Y2hMaXN0W2ldLCBkb21Ob2RlLCByZW5kZXJPcHRpb25zKTtcblxuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGRvbU5vZGUgPT09IHJvb3ROb2RlKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcm9vdE5vZGUgPSBuZXdOb2RlO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgbmV3Tm9kZSA9IHBhdGNoT3AocGF0Y2hMaXN0LCBkb21Ob2RlLCByZW5kZXJPcHRpb25zKTtcblxuICAgICAgICAgICAgICAgICAgICBpZiAoZG9tTm9kZSA9PT0gcm9vdE5vZGUpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJvb3ROb2RlID0gbmV3Tm9kZTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHJldHVybiByb290Tm9kZTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZnVuY3Rpb24gcGF0Y2hJbmRpY2VzKHBhdGNoZXMpIHtcbiAgICAgICAgICAgICAgICB2YXIgaW5kaWNlcyA9IFtdO1xuXG4gICAgICAgICAgICAgICAgZm9yICh2YXIga2V5IGluIHBhdGNoZXMpIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKGtleSAhPT0gXCJhXCIpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGluZGljZXMucHVzaChOdW1iZXIoa2V5KSk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICByZXR1cm4gaW5kaWNlcztcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSwgeyBcIi4vY3JlYXRlLWVsZW1lbnRcIjogMTUsIFwiLi9kb20taW5kZXhcIjogMTYsIFwiLi9wYXRjaC1vcFwiOiAxNywgXCJnbG9iYWwvZG9jdW1lbnRcIjogMTAsIFwieC1pcy1hcnJheVwiOiAxMiB9XSwgMTk6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICB2YXIgaXNXaWRnZXQgPSByZXF1aXJlKFwiLi4vdm5vZGUvaXMtd2lkZ2V0LmpzXCIpO1xuXG4gICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IHVwZGF0ZVdpZGdldDtcblxuICAgICAgICAgICAgZnVuY3Rpb24gdXBkYXRlV2lkZ2V0KGEsIGIpIHtcbiAgICAgICAgICAgICAgICBpZiAoaXNXaWRnZXQoYSkgJiYgaXNXaWRnZXQoYikpIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKFwibmFtZVwiIGluIGEgJiYgXCJuYW1lXCIgaW4gYikge1xuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGEuaWQgPT09IGIuaWQ7XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gYS5pbml0ID09PSBiLmluaXQ7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0sIHsgXCIuLi92bm9kZS9pcy13aWRnZXQuanNcIjogMjkgfV0sIDIwOiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge1xuICAgICAgICAgICAgXCJ1c2Ugc3RyaWN0XCI7XG5cbiAgICAgICAgICAgIHZhciBFdlN0b3JlID0gcmVxdWlyZShcImV2LXN0b3JlXCIpO1xuXG4gICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IEV2SG9vaztcblxuICAgICAgICAgICAgZnVuY3Rpb24gRXZIb29rKHZhbHVlKSB7XG4gICAgICAgICAgICAgICAgaWYgKCEodGhpcyBpbnN0YW5jZW9mIEV2SG9vaykpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIG5ldyBFdkhvb2sodmFsdWUpO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHRoaXMudmFsdWUgPSB2YWx1ZTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgRXZIb29rLnByb3RvdHlwZS5ob29rID0gZnVuY3Rpb24gKG5vZGUsIHByb3BlcnR5TmFtZSkge1xuICAgICAgICAgICAgICAgIHZhciBlcyA9IEV2U3RvcmUobm9kZSk7XG4gICAgICAgICAgICAgICAgdmFyIHByb3BOYW1lID0gcHJvcGVydHlOYW1lLnN1YnN0cigzKTtcblxuICAgICAgICAgICAgICAgIGVzW3Byb3BOYW1lXSA9IHRoaXMudmFsdWU7XG4gICAgICAgICAgICB9O1xuXG4gICAgICAgICAgICBFdkhvb2sucHJvdG90eXBlLnVuaG9vayA9IGZ1bmN0aW9uIChub2RlLCBwcm9wZXJ0eU5hbWUpIHtcbiAgICAgICAgICAgICAgICB2YXIgZXMgPSBFdlN0b3JlKG5vZGUpO1xuICAgICAgICAgICAgICAgIHZhciBwcm9wTmFtZSA9IHByb3BlcnR5TmFtZS5zdWJzdHIoMyk7XG5cbiAgICAgICAgICAgICAgICBlc1twcm9wTmFtZV0gPSB1bmRlZmluZWQ7XG4gICAgICAgICAgICB9O1xuICAgICAgICB9LCB7IFwiZXYtc3RvcmVcIjogNyB9XSwgMjE6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICBcInVzZSBzdHJpY3RcIjtcblxuICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBTb2Z0U2V0SG9vaztcblxuICAgICAgICAgICAgZnVuY3Rpb24gU29mdFNldEhvb2sodmFsdWUpIHtcbiAgICAgICAgICAgICAgICBpZiAoISh0aGlzIGluc3RhbmNlb2YgU29mdFNldEhvb2spKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBuZXcgU29mdFNldEhvb2sodmFsdWUpO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHRoaXMudmFsdWUgPSB2YWx1ZTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgU29mdFNldEhvb2sucHJvdG90eXBlLmhvb2sgPSBmdW5jdGlvbiAobm9kZSwgcHJvcGVydHlOYW1lKSB7XG4gICAgICAgICAgICAgICAgaWYgKG5vZGVbcHJvcGVydHlOYW1lXSAhPT0gdGhpcy52YWx1ZSkge1xuICAgICAgICAgICAgICAgICAgICBub2RlW3Byb3BlcnR5TmFtZV0gPSB0aGlzLnZhbHVlO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH07XG4gICAgICAgIH0sIHt9XSwgMjI6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICBcInVzZSBzdHJpY3RcIjtcblxuICAgICAgICAgICAgdmFyIGlzQXJyYXkgPSByZXF1aXJlKFwieC1pcy1hcnJheVwiKTtcblxuICAgICAgICAgICAgdmFyIFZOb2RlID0gcmVxdWlyZShcIi4uL3Zub2RlL3Zub2RlLmpzXCIpO1xuICAgICAgICAgICAgdmFyIFZUZXh0ID0gcmVxdWlyZShcIi4uL3Zub2RlL3Z0ZXh0LmpzXCIpO1xuICAgICAgICAgICAgdmFyIGlzVk5vZGUgPSByZXF1aXJlKFwiLi4vdm5vZGUvaXMtdm5vZGVcIik7XG4gICAgICAgICAgICB2YXIgaXNWVGV4dCA9IHJlcXVpcmUoXCIuLi92bm9kZS9pcy12dGV4dFwiKTtcbiAgICAgICAgICAgIHZhciBpc1dpZGdldCA9IHJlcXVpcmUoXCIuLi92bm9kZS9pcy13aWRnZXRcIik7XG4gICAgICAgICAgICB2YXIgaXNIb29rID0gcmVxdWlyZShcIi4uL3Zub2RlL2lzLXZob29rXCIpO1xuICAgICAgICAgICAgdmFyIGlzVlRodW5rID0gcmVxdWlyZShcIi4uL3Zub2RlL2lzLXRodW5rXCIpO1xuXG4gICAgICAgICAgICB2YXIgcGFyc2VUYWcgPSByZXF1aXJlKFwiLi9wYXJzZS10YWcuanNcIik7XG4gICAgICAgICAgICB2YXIgc29mdFNldEhvb2sgPSByZXF1aXJlKFwiLi9ob29rcy9zb2Z0LXNldC1ob29rLmpzXCIpO1xuICAgICAgICAgICAgdmFyIGV2SG9vayA9IHJlcXVpcmUoXCIuL2hvb2tzL2V2LWhvb2suanNcIik7XG5cbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gaDtcblxuICAgICAgICAgICAgZnVuY3Rpb24gaCh0YWdOYW1lLCBwcm9wZXJ0aWVzLCBjaGlsZHJlbikge1xuICAgICAgICAgICAgICAgIHZhciBjaGlsZE5vZGVzID0gW107XG4gICAgICAgICAgICAgICAgdmFyIHRhZywgcHJvcHMsIGtleSwgbmFtZXNwYWNlO1xuXG4gICAgICAgICAgICAgICAgaWYgKCFjaGlsZHJlbiAmJiBpc0NoaWxkcmVuKHByb3BlcnRpZXMpKSB7XG4gICAgICAgICAgICAgICAgICAgIGNoaWxkcmVuID0gcHJvcGVydGllcztcbiAgICAgICAgICAgICAgICAgICAgcHJvcHMgPSB7fTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICBwcm9wcyA9IHByb3BzIHx8IHByb3BlcnRpZXMgfHwge307XG4gICAgICAgICAgICAgICAgdGFnID0gcGFyc2VUYWcodGFnTmFtZSwgcHJvcHMpO1xuXG4gICAgICAgICAgICAgICAgLy8gc3VwcG9ydCBrZXlzXG4gICAgICAgICAgICAgICAgaWYgKHByb3BzLmhhc093blByb3BlcnR5KFwia2V5XCIpKSB7XG4gICAgICAgICAgICAgICAgICAgIGtleSA9IHByb3BzLmtleTtcbiAgICAgICAgICAgICAgICAgICAgcHJvcHMua2V5ID0gdW5kZWZpbmVkO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIC8vIHN1cHBvcnQgbmFtZXNwYWNlXG4gICAgICAgICAgICAgICAgaWYgKHByb3BzLmhhc093blByb3BlcnR5KFwibmFtZXNwYWNlXCIpKSB7XG4gICAgICAgICAgICAgICAgICAgIG5hbWVzcGFjZSA9IHByb3BzLm5hbWVzcGFjZTtcbiAgICAgICAgICAgICAgICAgICAgcHJvcHMubmFtZXNwYWNlID0gdW5kZWZpbmVkO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIC8vIGZpeCBjdXJzb3IgYnVnXG4gICAgICAgICAgICAgICAgaWYgKHRhZyA9PT0gXCJJTlBVVFwiICYmICFuYW1lc3BhY2UgJiYgcHJvcHMuaGFzT3duUHJvcGVydHkoXCJ2YWx1ZVwiKSAmJiBwcm9wcy52YWx1ZSAhPT0gdW5kZWZpbmVkICYmICFpc0hvb2socHJvcHMudmFsdWUpKSB7XG4gICAgICAgICAgICAgICAgICAgIHByb3BzLnZhbHVlID0gc29mdFNldEhvb2socHJvcHMudmFsdWUpO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHRyYW5zZm9ybVByb3BlcnRpZXMocHJvcHMpO1xuXG4gICAgICAgICAgICAgICAgaWYgKGNoaWxkcmVuICE9PSB1bmRlZmluZWQgJiYgY2hpbGRyZW4gIT09IG51bGwpIHtcbiAgICAgICAgICAgICAgICAgICAgYWRkQ2hpbGQoY2hpbGRyZW4sIGNoaWxkTm9kZXMsIHRhZywgcHJvcHMpO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHJldHVybiBuZXcgVk5vZGUodGFnLCBwcm9wcywgY2hpbGROb2Rlcywga2V5LCBuYW1lc3BhY2UpO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBmdW5jdGlvbiBhZGRDaGlsZChjLCBjaGlsZE5vZGVzLCB0YWcsIHByb3BzKSB7XG4gICAgICAgICAgICAgICAgaWYgKHR5cGVvZiBjID09PSBcInN0cmluZ1wiKSB7XG4gICAgICAgICAgICAgICAgICAgIGNoaWxkTm9kZXMucHVzaChuZXcgVlRleHQoYykpO1xuICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAodHlwZW9mIGMgPT09IFwibnVtYmVyXCIpIHtcbiAgICAgICAgICAgICAgICAgICAgY2hpbGROb2Rlcy5wdXNoKG5ldyBWVGV4dChTdHJpbmcoYykpKTtcbiAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKGlzQ2hpbGQoYykpIHtcbiAgICAgICAgICAgICAgICAgICAgY2hpbGROb2Rlcy5wdXNoKGMpO1xuICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoaXNBcnJheShjKSkge1xuICAgICAgICAgICAgICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IGMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGFkZENoaWxkKGNbaV0sIGNoaWxkTm9kZXMsIHRhZywgcHJvcHMpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfSBlbHNlIGlmIChjID09PSBudWxsIHx8IGMgPT09IHVuZGVmaW5lZCkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgdGhyb3cgVW5leHBlY3RlZFZpcnR1YWxFbGVtZW50KHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGZvcmVpZ25PYmplY3Q6IGMsXG4gICAgICAgICAgICAgICAgICAgICAgICBwYXJlbnRWbm9kZToge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRhZ05hbWU6IHRhZyxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBwcm9wZXJ0aWVzOiBwcm9wc1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIHRyYW5zZm9ybVByb3BlcnRpZXMocHJvcHMpIHtcbiAgICAgICAgICAgICAgICBmb3IgKHZhciBwcm9wTmFtZSBpbiBwcm9wcykge1xuICAgICAgICAgICAgICAgICAgICBpZiAocHJvcHMuaGFzT3duUHJvcGVydHkocHJvcE5hbWUpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICB2YXIgdmFsdWUgPSBwcm9wc1twcm9wTmFtZV07XG5cbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChpc0hvb2sodmFsdWUpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgY29udGludWU7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChwcm9wTmFtZS5zdWJzdHIoMCwgMykgPT09IFwiZXYtXCIpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBhZGQgZXYtZm9vIHN1cHBvcnRcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBwcm9wc1twcm9wTmFtZV0gPSBldkhvb2sodmFsdWUpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBmdW5jdGlvbiBpc0NoaWxkKHgpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gaXNWTm9kZSh4KSB8fCBpc1ZUZXh0KHgpIHx8IGlzV2lkZ2V0KHgpIHx8IGlzVlRodW5rKHgpO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBmdW5jdGlvbiBpc0NoaWxkcmVuKHgpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gdHlwZW9mIHggPT09IFwic3RyaW5nXCIgfHwgaXNBcnJheSh4KSB8fCBpc0NoaWxkKHgpO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBmdW5jdGlvbiBVbmV4cGVjdGVkVmlydHVhbEVsZW1lbnQoZGF0YSkge1xuICAgICAgICAgICAgICAgIHZhciBlcnIgPSBuZXcgRXJyb3IoKTtcblxuICAgICAgICAgICAgICAgIGVyci50eXBlID0gXCJ2aXJ0dWFsLWh5cGVyc2NyaXB0LnVuZXhwZWN0ZWQudmlydHVhbC1lbGVtZW50XCI7XG4gICAgICAgICAgICAgICAgZXJyLm1lc3NhZ2UgPSBcIlVuZXhwZWN0ZWQgdmlydHVhbCBjaGlsZCBwYXNzZWQgdG8gaCgpLlxcblwiICsgXCJFeHBlY3RlZCBhIFZOb2RlIC8gVnRodW5rIC8gVldpZGdldCAvIHN0cmluZyBidXQ6XFxuXCIgKyBcImdvdDpcXG5cIiArIGVycm9yU3RyaW5nKGRhdGEuZm9yZWlnbk9iamVjdCkgKyBcIi5cXG5cIiArIFwiVGhlIHBhcmVudCB2bm9kZSBpczpcXG5cIiArIGVycm9yU3RyaW5nKGRhdGEucGFyZW50Vm5vZGUpO1xuICAgICAgICAgICAgICAgIFwiXFxuXCIgKyBcIlN1Z2dlc3RlZCBmaXg6IGNoYW5nZSB5b3VyIGBoKC4uLiwgWyAuLi4gXSlgIGNhbGxzaXRlLlwiO1xuICAgICAgICAgICAgICAgIGVyci5mb3JlaWduT2JqZWN0ID0gZGF0YS5mb3JlaWduT2JqZWN0O1xuICAgICAgICAgICAgICAgIGVyci5wYXJlbnRWbm9kZSA9IGRhdGEucGFyZW50Vm5vZGU7XG5cbiAgICAgICAgICAgICAgICByZXR1cm4gZXJyO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBmdW5jdGlvbiBlcnJvclN0cmluZyhvYmopIHtcbiAgICAgICAgICAgICAgICB0cnkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gSlNPTi5zdHJpbmdpZnkob2JqLCBudWxsLCBcIiAgICBcIik7XG4gICAgICAgICAgICAgICAgfSBjYXRjaCAoZSkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gU3RyaW5nKG9iaik7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9LCB7IFwiLi4vdm5vZGUvaXMtdGh1bmtcIjogMjUsIFwiLi4vdm5vZGUvaXMtdmhvb2tcIjogMjYsIFwiLi4vdm5vZGUvaXMtdm5vZGVcIjogMjcsIFwiLi4vdm5vZGUvaXMtdnRleHRcIjogMjgsIFwiLi4vdm5vZGUvaXMtd2lkZ2V0XCI6IDI5LCBcIi4uL3Zub2RlL3Zub2RlLmpzXCI6IDMxLCBcIi4uL3Zub2RlL3Z0ZXh0LmpzXCI6IDMzLCBcIi4vaG9va3MvZXYtaG9vay5qc1wiOiAyMCwgXCIuL2hvb2tzL3NvZnQtc2V0LWhvb2suanNcIjogMjEsIFwiLi9wYXJzZS10YWcuanNcIjogMjMsIFwieC1pcy1hcnJheVwiOiAxMiB9XSwgMjM6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICBcInVzZSBzdHJpY3RcIjtcblxuICAgICAgICAgICAgdmFyIHNwbGl0ID0gcmVxdWlyZShcImJyb3dzZXItc3BsaXRcIik7XG5cbiAgICAgICAgICAgIHZhciBjbGFzc0lkU3BsaXQgPSAvKFtcXC4jXT9bYS16QS1aMC05XFx1MDA3Ri1cXHVGRkZGXzotXSspLztcbiAgICAgICAgICAgIHZhciBub3RDbGFzc0lkID0gL15cXC58Iy87XG5cbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gcGFyc2VUYWc7XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIHBhcnNlVGFnKHRhZywgcHJvcHMpIHtcbiAgICAgICAgICAgICAgICBpZiAoIXRhZykge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gXCJESVZcIjtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICB2YXIgbm9JZCA9ICFwcm9wcy5oYXNPd25Qcm9wZXJ0eShcImlkXCIpO1xuXG4gICAgICAgICAgICAgICAgdmFyIHRhZ1BhcnRzID0gc3BsaXQodGFnLCBjbGFzc0lkU3BsaXQpO1xuICAgICAgICAgICAgICAgIHZhciB0YWdOYW1lID0gbnVsbDtcblxuICAgICAgICAgICAgICAgIGlmIChub3RDbGFzc0lkLnRlc3QodGFnUGFydHNbMV0pKSB7XG4gICAgICAgICAgICAgICAgICAgIHRhZ05hbWUgPSBcIkRJVlwiO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHZhciBjbGFzc2VzLCBwYXJ0LCB0eXBlLCBpO1xuXG4gICAgICAgICAgICAgICAgZm9yIChpID0gMDsgaSA8IHRhZ1BhcnRzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICAgICAgICAgIHBhcnQgPSB0YWdQYXJ0c1tpXTtcblxuICAgICAgICAgICAgICAgICAgICBpZiAoIXBhcnQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnRpbnVlO1xuICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgdHlwZSA9IHBhcnQuY2hhckF0KDApO1xuXG4gICAgICAgICAgICAgICAgICAgIGlmICghdGFnTmFtZSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgdGFnTmFtZSA9IHBhcnQ7XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAodHlwZSA9PT0gXCIuXCIpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGNsYXNzZXMgPSBjbGFzc2VzIHx8IFtdO1xuICAgICAgICAgICAgICAgICAgICAgICAgY2xhc3Nlcy5wdXNoKHBhcnQuc3Vic3RyaW5nKDEsIHBhcnQubGVuZ3RoKSk7XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAodHlwZSA9PT0gXCIjXCIgJiYgbm9JZCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgcHJvcHMuaWQgPSBwYXJ0LnN1YnN0cmluZygxLCBwYXJ0Lmxlbmd0aCk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICBpZiAoY2xhc3Nlcykge1xuICAgICAgICAgICAgICAgICAgICBpZiAocHJvcHMuY2xhc3NOYW1lKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBjbGFzc2VzLnB1c2gocHJvcHMuY2xhc3NOYW1lKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgIHByb3BzLmNsYXNzTmFtZSA9IGNsYXNzZXMuam9pbihcIiBcIik7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgcmV0dXJuIHByb3BzLm5hbWVzcGFjZSA/IHRhZ05hbWUgOiB0YWdOYW1lLnRvVXBwZXJDYXNlKCk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0sIHsgXCJicm93c2VyLXNwbGl0XCI6IDUgfV0sIDI0OiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge1xuICAgICAgICAgICAgdmFyIGlzVk5vZGUgPSByZXF1aXJlKFwiLi9pcy12bm9kZVwiKTtcbiAgICAgICAgICAgIHZhciBpc1ZUZXh0ID0gcmVxdWlyZShcIi4vaXMtdnRleHRcIik7XG4gICAgICAgICAgICB2YXIgaXNXaWRnZXQgPSByZXF1aXJlKFwiLi9pcy13aWRnZXRcIik7XG4gICAgICAgICAgICB2YXIgaXNUaHVuayA9IHJlcXVpcmUoXCIuL2lzLXRodW5rXCIpO1xuXG4gICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IGhhbmRsZVRodW5rO1xuXG4gICAgICAgICAgICBmdW5jdGlvbiBoYW5kbGVUaHVuayhhLCBiKSB7XG4gICAgICAgICAgICAgICAgdmFyIHJlbmRlcmVkQSA9IGE7XG4gICAgICAgICAgICAgICAgdmFyIHJlbmRlcmVkQiA9IGI7XG5cbiAgICAgICAgICAgICAgICBpZiAoaXNUaHVuayhiKSkge1xuICAgICAgICAgICAgICAgICAgICByZW5kZXJlZEIgPSByZW5kZXJUaHVuayhiLCBhKTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICBpZiAoaXNUaHVuayhhKSkge1xuICAgICAgICAgICAgICAgICAgICByZW5kZXJlZEEgPSByZW5kZXJUaHVuayhhLCBudWxsKTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgICAgICAgICBhOiByZW5kZXJlZEEsXG4gICAgICAgICAgICAgICAgICAgIGI6IHJlbmRlcmVkQlxuICAgICAgICAgICAgICAgIH07XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIHJlbmRlclRodW5rKHRodW5rLCBwcmV2aW91cykge1xuICAgICAgICAgICAgICAgIHZhciByZW5kZXJlZFRodW5rID0gdGh1bmsudm5vZGU7XG5cbiAgICAgICAgICAgICAgICBpZiAoIXJlbmRlcmVkVGh1bmspIHtcbiAgICAgICAgICAgICAgICAgICAgcmVuZGVyZWRUaHVuayA9IHRodW5rLnZub2RlID0gdGh1bmsucmVuZGVyKHByZXZpb3VzKTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICBpZiAoIShpc1ZOb2RlKHJlbmRlcmVkVGh1bmspIHx8IGlzVlRleHQocmVuZGVyZWRUaHVuaykgfHwgaXNXaWRnZXQocmVuZGVyZWRUaHVuaykpKSB7XG4gICAgICAgICAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcihcInRodW5rIGRpZCBub3QgcmV0dXJuIGEgdmFsaWQgbm9kZVwiKTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICByZXR1cm4gcmVuZGVyZWRUaHVuaztcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSwgeyBcIi4vaXMtdGh1bmtcIjogMjUsIFwiLi9pcy12bm9kZVwiOiAyNywgXCIuL2lzLXZ0ZXh0XCI6IDI4LCBcIi4vaXMtd2lkZ2V0XCI6IDI5IH1dLCAyNTogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHtcbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gaXNUaHVuaztcblxuICAgICAgICAgICAgZnVuY3Rpb24gaXNUaHVuayh0KSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHQgJiYgdC50eXBlID09PSBcIlRodW5rXCI7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0sIHt9XSwgMjY6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IGlzSG9vaztcblxuICAgICAgICAgICAgZnVuY3Rpb24gaXNIb29rKGhvb2spIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gaG9vayAmJiAodHlwZW9mIGhvb2suaG9vayA9PT0gXCJmdW5jdGlvblwiICYmICFob29rLmhhc093blByb3BlcnR5KFwiaG9va1wiKSB8fCB0eXBlb2YgaG9vay51bmhvb2sgPT09IFwiZnVuY3Rpb25cIiAmJiAhaG9vay5oYXNPd25Qcm9wZXJ0eShcInVuaG9va1wiKSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0sIHt9XSwgMjc6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICB2YXIgdmVyc2lvbiA9IHJlcXVpcmUoXCIuL3ZlcnNpb25cIik7XG5cbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gaXNWaXJ0dWFsTm9kZTtcblxuICAgICAgICAgICAgZnVuY3Rpb24gaXNWaXJ0dWFsTm9kZSh4KSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHggJiYgeC50eXBlID09PSBcIlZpcnR1YWxOb2RlXCIgJiYgeC52ZXJzaW9uID09PSB2ZXJzaW9uO1xuICAgICAgICAgICAgfVxuICAgICAgICB9LCB7IFwiLi92ZXJzaW9uXCI6IDMwIH1dLCAyODogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHtcbiAgICAgICAgICAgIHZhciB2ZXJzaW9uID0gcmVxdWlyZShcIi4vdmVyc2lvblwiKTtcblxuICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBpc1ZpcnR1YWxUZXh0O1xuXG4gICAgICAgICAgICBmdW5jdGlvbiBpc1ZpcnR1YWxUZXh0KHgpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4geCAmJiB4LnR5cGUgPT09IFwiVmlydHVhbFRleHRcIiAmJiB4LnZlcnNpb24gPT09IHZlcnNpb247XG4gICAgICAgICAgICB9XG4gICAgICAgIH0sIHsgXCIuL3ZlcnNpb25cIjogMzAgfV0sIDI5OiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge1xuICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBpc1dpZGdldDtcblxuICAgICAgICAgICAgZnVuY3Rpb24gaXNXaWRnZXQodykge1xuICAgICAgICAgICAgICAgIHJldHVybiB3ICYmIHcudHlwZSA9PT0gXCJXaWRnZXRcIjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSwge31dLCAzMDogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHtcbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gXCIyXCI7XG4gICAgICAgIH0sIHt9XSwgMzE6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICB2YXIgdmVyc2lvbiA9IHJlcXVpcmUoXCIuL3ZlcnNpb25cIik7XG4gICAgICAgICAgICB2YXIgaXNWTm9kZSA9IHJlcXVpcmUoXCIuL2lzLXZub2RlXCIpO1xuICAgICAgICAgICAgdmFyIGlzV2lkZ2V0ID0gcmVxdWlyZShcIi4vaXMtd2lkZ2V0XCIpO1xuICAgICAgICAgICAgdmFyIGlzVGh1bmsgPSByZXF1aXJlKFwiLi9pcy10aHVua1wiKTtcbiAgICAgICAgICAgIHZhciBpc1ZIb29rID0gcmVxdWlyZShcIi4vaXMtdmhvb2tcIik7XG5cbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gVmlydHVhbE5vZGU7XG5cbiAgICAgICAgICAgIHZhciBub1Byb3BlcnRpZXMgPSB7fTtcbiAgICAgICAgICAgIHZhciBub0NoaWxkcmVuID0gW107XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIFZpcnR1YWxOb2RlKHRhZ05hbWUsIHByb3BlcnRpZXMsIGNoaWxkcmVuLCBrZXksIG5hbWVzcGFjZSkge1xuICAgICAgICAgICAgICAgIHRoaXMudGFnTmFtZSA9IHRhZ05hbWU7XG4gICAgICAgICAgICAgICAgdGhpcy5wcm9wZXJ0aWVzID0gcHJvcGVydGllcyB8fCBub1Byb3BlcnRpZXM7XG4gICAgICAgICAgICAgICAgdGhpcy5jaGlsZHJlbiA9IGNoaWxkcmVuIHx8IG5vQ2hpbGRyZW47XG4gICAgICAgICAgICAgICAgdGhpcy5rZXkgPSBrZXkgIT0gbnVsbCA/IFN0cmluZyhrZXkpIDogdW5kZWZpbmVkO1xuICAgICAgICAgICAgICAgIHRoaXMubmFtZXNwYWNlID0gdHlwZW9mIG5hbWVzcGFjZSA9PT0gXCJzdHJpbmdcIiA/IG5hbWVzcGFjZSA6IG51bGw7XG5cbiAgICAgICAgICAgICAgICB2YXIgY291bnQgPSBjaGlsZHJlbiAmJiBjaGlsZHJlbi5sZW5ndGggfHwgMDtcbiAgICAgICAgICAgICAgICB2YXIgZGVzY2VuZGFudHMgPSAwO1xuICAgICAgICAgICAgICAgIHZhciBoYXNXaWRnZXRzID0gZmFsc2U7XG4gICAgICAgICAgICAgICAgdmFyIGhhc1RodW5rcyA9IGZhbHNlO1xuICAgICAgICAgICAgICAgIHZhciBkZXNjZW5kYW50SG9va3MgPSBmYWxzZTtcbiAgICAgICAgICAgICAgICB2YXIgaG9va3M7XG5cbiAgICAgICAgICAgICAgICBmb3IgKHZhciBwcm9wTmFtZSBpbiBwcm9wZXJ0aWVzKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmIChwcm9wZXJ0aWVzLmhhc093blByb3BlcnR5KHByb3BOYW1lKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgdmFyIHByb3BlcnR5ID0gcHJvcGVydGllc1twcm9wTmFtZV07XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoaXNWSG9vayhwcm9wZXJ0eSkgJiYgcHJvcGVydHkudW5ob29rKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKCFob29rcykge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBob29rcyA9IHt9O1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGhvb2tzW3Byb3BOYW1lXSA9IHByb3BlcnR5O1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCBjb3VudDsgaSsrKSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciBjaGlsZCA9IGNoaWxkcmVuW2ldO1xuICAgICAgICAgICAgICAgICAgICBpZiAoaXNWTm9kZShjaGlsZCkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGRlc2NlbmRhbnRzICs9IGNoaWxkLmNvdW50IHx8IDA7XG5cbiAgICAgICAgICAgICAgICAgICAgICAgIGlmICghaGFzV2lkZ2V0cyAmJiBjaGlsZC5oYXNXaWRnZXRzKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaGFzV2lkZ2V0cyA9IHRydWU7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgICAgIGlmICghaGFzVGh1bmtzICYmIGNoaWxkLmhhc1RodW5rcykge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGhhc1RodW5rcyA9IHRydWU7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgICAgIGlmICghZGVzY2VuZGFudEhvb2tzICYmIChjaGlsZC5ob29rcyB8fCBjaGlsZC5kZXNjZW5kYW50SG9va3MpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgZGVzY2VuZGFudEhvb2tzID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIGlmICghaGFzV2lkZ2V0cyAmJiBpc1dpZGdldChjaGlsZCkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmICh0eXBlb2YgY2hpbGQuZGVzdHJveSA9PT0gXCJmdW5jdGlvblwiKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaGFzV2lkZ2V0cyA9IHRydWU7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoIWhhc1RodW5rcyAmJiBpc1RodW5rKGNoaWxkKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgaGFzVGh1bmtzID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHRoaXMuY291bnQgPSBjb3VudCArIGRlc2NlbmRhbnRzO1xuICAgICAgICAgICAgICAgIHRoaXMuaGFzV2lkZ2V0cyA9IGhhc1dpZGdldHM7XG4gICAgICAgICAgICAgICAgdGhpcy5oYXNUaHVua3MgPSBoYXNUaHVua3M7XG4gICAgICAgICAgICAgICAgdGhpcy5ob29rcyA9IGhvb2tzO1xuICAgICAgICAgICAgICAgIHRoaXMuZGVzY2VuZGFudEhvb2tzID0gZGVzY2VuZGFudEhvb2tzO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBWaXJ0dWFsTm9kZS5wcm90b3R5cGUudmVyc2lvbiA9IHZlcnNpb247XG4gICAgICAgICAgICBWaXJ0dWFsTm9kZS5wcm90b3R5cGUudHlwZSA9IFwiVmlydHVhbE5vZGVcIjtcbiAgICAgICAgfSwgeyBcIi4vaXMtdGh1bmtcIjogMjUsIFwiLi9pcy12aG9va1wiOiAyNiwgXCIuL2lzLXZub2RlXCI6IDI3LCBcIi4vaXMtd2lkZ2V0XCI6IDI5LCBcIi4vdmVyc2lvblwiOiAzMCB9XSwgMzI6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICB2YXIgdmVyc2lvbiA9IHJlcXVpcmUoXCIuL3ZlcnNpb25cIik7XG5cbiAgICAgICAgICAgIFZpcnR1YWxQYXRjaC5OT05FID0gMDtcbiAgICAgICAgICAgIFZpcnR1YWxQYXRjaC5WVEVYVCA9IDE7XG4gICAgICAgICAgICBWaXJ0dWFsUGF0Y2guVk5PREUgPSAyO1xuICAgICAgICAgICAgVmlydHVhbFBhdGNoLldJREdFVCA9IDM7XG4gICAgICAgICAgICBWaXJ0dWFsUGF0Y2guUFJPUFMgPSA0O1xuICAgICAgICAgICAgVmlydHVhbFBhdGNoLk9SREVSID0gNTtcbiAgICAgICAgICAgIFZpcnR1YWxQYXRjaC5JTlNFUlQgPSA2O1xuICAgICAgICAgICAgVmlydHVhbFBhdGNoLlJFTU9WRSA9IDc7XG4gICAgICAgICAgICBWaXJ0dWFsUGF0Y2guVEhVTksgPSA4O1xuXG4gICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IFZpcnR1YWxQYXRjaDtcblxuICAgICAgICAgICAgZnVuY3Rpb24gVmlydHVhbFBhdGNoKHR5cGUsIHZOb2RlLCBwYXRjaCkge1xuICAgICAgICAgICAgICAgIHRoaXMudHlwZSA9IE51bWJlcih0eXBlKTtcbiAgICAgICAgICAgICAgICB0aGlzLnZOb2RlID0gdk5vZGU7XG4gICAgICAgICAgICAgICAgdGhpcy5wYXRjaCA9IHBhdGNoO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBWaXJ0dWFsUGF0Y2gucHJvdG90eXBlLnZlcnNpb24gPSB2ZXJzaW9uO1xuICAgICAgICAgICAgVmlydHVhbFBhdGNoLnByb3RvdHlwZS50eXBlID0gXCJWaXJ0dWFsUGF0Y2hcIjtcbiAgICAgICAgfSwgeyBcIi4vdmVyc2lvblwiOiAzMCB9XSwgMzM6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICB2YXIgdmVyc2lvbiA9IHJlcXVpcmUoXCIuL3ZlcnNpb25cIik7XG5cbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gVmlydHVhbFRleHQ7XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIFZpcnR1YWxUZXh0KHRleHQpIHtcbiAgICAgICAgICAgICAgICB0aGlzLnRleHQgPSBTdHJpbmcodGV4dCk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIFZpcnR1YWxUZXh0LnByb3RvdHlwZS52ZXJzaW9uID0gdmVyc2lvbjtcbiAgICAgICAgICAgIFZpcnR1YWxUZXh0LnByb3RvdHlwZS50eXBlID0gXCJWaXJ0dWFsVGV4dFwiO1xuICAgICAgICB9LCB7IFwiLi92ZXJzaW9uXCI6IDMwIH1dLCAzNDogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHtcbiAgICAgICAgICAgIHZhciBpc09iamVjdCA9IHJlcXVpcmUoXCJpcy1vYmplY3RcIik7XG4gICAgICAgICAgICB2YXIgaXNIb29rID0gcmVxdWlyZShcIi4uL3Zub2RlL2lzLXZob29rXCIpO1xuXG4gICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IGRpZmZQcm9wcztcblxuICAgICAgICAgICAgZnVuY3Rpb24gZGlmZlByb3BzKGEsIGIpIHtcbiAgICAgICAgICAgICAgICB2YXIgZGlmZjtcblxuICAgICAgICAgICAgICAgIGZvciAodmFyIGFLZXkgaW4gYSkge1xuICAgICAgICAgICAgICAgICAgICBpZiAoIShhS2V5IGluIGIpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBkaWZmID0gZGlmZiB8fCB7fTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGRpZmZbYUtleV0gPSB1bmRlZmluZWQ7XG4gICAgICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgICAgICB2YXIgYVZhbHVlID0gYVthS2V5XTtcbiAgICAgICAgICAgICAgICAgICAgdmFyIGJWYWx1ZSA9IGJbYUtleV07XG5cbiAgICAgICAgICAgICAgICAgICAgaWYgKGFWYWx1ZSA9PT0gYlZhbHVlKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBjb250aW51ZTtcbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIGlmIChpc09iamVjdChhVmFsdWUpICYmIGlzT2JqZWN0KGJWYWx1ZSkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChnZXRQcm90b3R5cGUoYlZhbHVlKSAhPT0gZ2V0UHJvdG90eXBlKGFWYWx1ZSkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBkaWZmID0gZGlmZiB8fCB7fTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBkaWZmW2FLZXldID0gYlZhbHVlO1xuICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIGlmIChpc0hvb2soYlZhbHVlKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRpZmYgPSBkaWZmIHx8IHt9O1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRpZmZbYUtleV0gPSBiVmFsdWU7XG4gICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZhciBvYmplY3REaWZmID0gZGlmZlByb3BzKGFWYWx1ZSwgYlZhbHVlKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAob2JqZWN0RGlmZikge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBkaWZmID0gZGlmZiB8fCB7fTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZGlmZlthS2V5XSA9IG9iamVjdERpZmY7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgZGlmZiA9IGRpZmYgfHwge307XG4gICAgICAgICAgICAgICAgICAgICAgICBkaWZmW2FLZXldID0gYlZhbHVlO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgZm9yICh2YXIgYktleSBpbiBiKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmICghKGJLZXkgaW4gYSkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGRpZmYgPSBkaWZmIHx8IHt9O1xuICAgICAgICAgICAgICAgICAgICAgICAgZGlmZltiS2V5XSA9IGJbYktleV07XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICByZXR1cm4gZGlmZjtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZnVuY3Rpb24gZ2V0UHJvdG90eXBlKHZhbHVlKSB7XG4gICAgICAgICAgICAgICAgaWYgKE9iamVjdC5nZXRQcm90b3R5cGVPZikge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gT2JqZWN0LmdldFByb3RvdHlwZU9mKHZhbHVlKTtcbiAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKHZhbHVlLl9fcHJvdG9fXykge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gdmFsdWUuX19wcm90b19fO1xuICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAodmFsdWUuY29uc3RydWN0b3IpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHZhbHVlLmNvbnN0cnVjdG9yLnByb3RvdHlwZTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH0sIHsgXCIuLi92bm9kZS9pcy12aG9va1wiOiAyNiwgXCJpcy1vYmplY3RcIjogMTEgfV0sIDM1OiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge1xuICAgICAgICAgICAgdmFyIGlzQXJyYXkgPSByZXF1aXJlKFwieC1pcy1hcnJheVwiKTtcblxuICAgICAgICAgICAgdmFyIFZQYXRjaCA9IHJlcXVpcmUoXCIuLi92bm9kZS92cGF0Y2hcIik7XG4gICAgICAgICAgICB2YXIgaXNWTm9kZSA9IHJlcXVpcmUoXCIuLi92bm9kZS9pcy12bm9kZVwiKTtcbiAgICAgICAgICAgIHZhciBpc1ZUZXh0ID0gcmVxdWlyZShcIi4uL3Zub2RlL2lzLXZ0ZXh0XCIpO1xuICAgICAgICAgICAgdmFyIGlzV2lkZ2V0ID0gcmVxdWlyZShcIi4uL3Zub2RlL2lzLXdpZGdldFwiKTtcbiAgICAgICAgICAgIHZhciBpc1RodW5rID0gcmVxdWlyZShcIi4uL3Zub2RlL2lzLXRodW5rXCIpO1xuICAgICAgICAgICAgdmFyIGhhbmRsZVRodW5rID0gcmVxdWlyZShcIi4uL3Zub2RlL2hhbmRsZS10aHVua1wiKTtcblxuICAgICAgICAgICAgdmFyIGRpZmZQcm9wcyA9IHJlcXVpcmUoXCIuL2RpZmYtcHJvcHNcIik7XG5cbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gZGlmZjtcblxuICAgICAgICAgICAgZnVuY3Rpb24gZGlmZihhLCBiKSB7XG4gICAgICAgICAgICAgICAgdmFyIHBhdGNoID0geyBhOiBhIH07XG4gICAgICAgICAgICAgICAgd2FsayhhLCBiLCBwYXRjaCwgMCk7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHBhdGNoO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBmdW5jdGlvbiB3YWxrKGEsIGIsIHBhdGNoLCBpbmRleCkge1xuICAgICAgICAgICAgICAgIGlmIChhID09PSBiKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICB2YXIgYXBwbHkgPSBwYXRjaFtpbmRleF07XG4gICAgICAgICAgICAgICAgdmFyIGFwcGx5Q2xlYXIgPSBmYWxzZTtcblxuICAgICAgICAgICAgICAgIGlmIChpc1RodW5rKGEpIHx8IGlzVGh1bmsoYikpIHtcbiAgICAgICAgICAgICAgICAgICAgdGh1bmtzKGEsIGIsIHBhdGNoLCBpbmRleCk7XG4gICAgICAgICAgICAgICAgfSBlbHNlIGlmIChiID09IG51bGwpIHtcblxuICAgICAgICAgICAgICAgICAgICAvLyBJZiBhIGlzIGEgd2lkZ2V0IHdlIHdpbGwgYWRkIGEgcmVtb3ZlIHBhdGNoIGZvciBpdFxuICAgICAgICAgICAgICAgICAgICAvLyBPdGhlcndpc2UgYW55IGNoaWxkIHdpZGdldHMvaG9va3MgbXVzdCBiZSBkZXN0cm95ZWQuXG4gICAgICAgICAgICAgICAgICAgIC8vIFRoaXMgcHJldmVudHMgYWRkaW5nIHR3byByZW1vdmUgcGF0Y2hlcyBmb3IgYSB3aWRnZXQuXG4gICAgICAgICAgICAgICAgICAgIGlmICghaXNXaWRnZXQoYSkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGNsZWFyU3RhdGUoYSwgcGF0Y2gsIGluZGV4KTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGFwcGx5ID0gcGF0Y2hbaW5kZXhdO1xuICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgYXBwbHkgPSBhcHBlbmRQYXRjaChhcHBseSwgbmV3IFZQYXRjaChWUGF0Y2guUkVNT1ZFLCBhLCBiKSk7XG4gICAgICAgICAgICAgICAgfSBlbHNlIGlmIChpc1ZOb2RlKGIpKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmIChpc1ZOb2RlKGEpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoYS50YWdOYW1lID09PSBiLnRhZ05hbWUgJiYgYS5uYW1lc3BhY2UgPT09IGIubmFtZXNwYWNlICYmIGEua2V5ID09PSBiLmtleSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZhciBwcm9wc1BhdGNoID0gZGlmZlByb3BzKGEucHJvcGVydGllcywgYi5wcm9wZXJ0aWVzKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAocHJvcHNQYXRjaCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBhcHBseSA9IGFwcGVuZFBhdGNoKGFwcGx5LCBuZXcgVlBhdGNoKFZQYXRjaC5QUk9QUywgYSwgcHJvcHNQYXRjaCkpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBhcHBseSA9IGRpZmZDaGlsZHJlbihhLCBiLCBwYXRjaCwgYXBwbHksIGluZGV4KTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgYXBwbHkgPSBhcHBlbmRQYXRjaChhcHBseSwgbmV3IFZQYXRjaChWUGF0Y2guVk5PREUsIGEsIGIpKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBhcHBseUNsZWFyID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGFwcGx5ID0gYXBwZW5kUGF0Y2goYXBwbHksIG5ldyBWUGF0Y2goVlBhdGNoLlZOT0RFLCBhLCBiKSk7XG4gICAgICAgICAgICAgICAgICAgICAgICBhcHBseUNsZWFyID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoaXNWVGV4dChiKSkge1xuICAgICAgICAgICAgICAgICAgICBpZiAoIWlzVlRleHQoYSkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGFwcGx5ID0gYXBwZW5kUGF0Y2goYXBwbHksIG5ldyBWUGF0Y2goVlBhdGNoLlZURVhULCBhLCBiKSk7XG4gICAgICAgICAgICAgICAgICAgICAgICBhcHBseUNsZWFyID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIGlmIChhLnRleHQgIT09IGIudGV4dCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgYXBwbHkgPSBhcHBlbmRQYXRjaChhcHBseSwgbmV3IFZQYXRjaChWUGF0Y2guVlRFWFQsIGEsIGIpKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoaXNXaWRnZXQoYikpIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKCFpc1dpZGdldChhKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgYXBwbHlDbGVhciA9IHRydWU7XG4gICAgICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgICAgICBhcHBseSA9IGFwcGVuZFBhdGNoKGFwcGx5LCBuZXcgVlBhdGNoKFZQYXRjaC5XSURHRVQsIGEsIGIpKTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICBpZiAoYXBwbHkpIHtcbiAgICAgICAgICAgICAgICAgICAgcGF0Y2hbaW5kZXhdID0gYXBwbHk7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgaWYgKGFwcGx5Q2xlYXIpIHtcbiAgICAgICAgICAgICAgICAgICAgY2xlYXJTdGF0ZShhLCBwYXRjaCwgaW5kZXgpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZnVuY3Rpb24gZGlmZkNoaWxkcmVuKGEsIGIsIHBhdGNoLCBhcHBseSwgaW5kZXgpIHtcbiAgICAgICAgICAgICAgICB2YXIgYUNoaWxkcmVuID0gYS5jaGlsZHJlbjtcbiAgICAgICAgICAgICAgICB2YXIgb3JkZXJlZFNldCA9IHJlb3JkZXIoYUNoaWxkcmVuLCBiLmNoaWxkcmVuKTtcbiAgICAgICAgICAgICAgICB2YXIgYkNoaWxkcmVuID0gb3JkZXJlZFNldC5jaGlsZHJlbjtcblxuICAgICAgICAgICAgICAgIHZhciBhTGVuID0gYUNoaWxkcmVuLmxlbmd0aDtcbiAgICAgICAgICAgICAgICB2YXIgYkxlbiA9IGJDaGlsZHJlbi5sZW5ndGg7XG4gICAgICAgICAgICAgICAgdmFyIGxlbiA9IGFMZW4gPiBiTGVuID8gYUxlbiA6IGJMZW47XG5cbiAgICAgICAgICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IGxlbjsgaSsrKSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciBsZWZ0Tm9kZSA9IGFDaGlsZHJlbltpXTtcbiAgICAgICAgICAgICAgICAgICAgdmFyIHJpZ2h0Tm9kZSA9IGJDaGlsZHJlbltpXTtcbiAgICAgICAgICAgICAgICAgICAgaW5kZXggKz0gMTtcblxuICAgICAgICAgICAgICAgICAgICBpZiAoIWxlZnROb2RlKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAocmlnaHROb2RlKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gRXhjZXNzIG5vZGVzIGluIGIgbmVlZCB0byBiZSBhZGRlZFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGFwcGx5ID0gYXBwZW5kUGF0Y2goYXBwbHksIG5ldyBWUGF0Y2goVlBhdGNoLklOU0VSVCwgbnVsbCwgcmlnaHROb2RlKSk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICB3YWxrKGxlZnROb2RlLCByaWdodE5vZGUsIHBhdGNoLCBpbmRleCk7XG4gICAgICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgICAgICBpZiAoaXNWTm9kZShsZWZ0Tm9kZSkgJiYgbGVmdE5vZGUuY291bnQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGluZGV4ICs9IGxlZnROb2RlLmNvdW50O1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgaWYgKG9yZGVyZWRTZXQubW92ZXMpIHtcbiAgICAgICAgICAgICAgICAgICAgLy8gUmVvcmRlciBub2RlcyBsYXN0XG4gICAgICAgICAgICAgICAgICAgIGFwcGx5ID0gYXBwZW5kUGF0Y2goYXBwbHksIG5ldyBWUGF0Y2goVlBhdGNoLk9SREVSLCBhLCBvcmRlcmVkU2V0Lm1vdmVzKSk7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgcmV0dXJuIGFwcGx5O1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBmdW5jdGlvbiBjbGVhclN0YXRlKHZOb2RlLCBwYXRjaCwgaW5kZXgpIHtcbiAgICAgICAgICAgICAgICAvLyBUT0RPOiBNYWtlIHRoaXMgYSBzaW5nbGUgd2Fsaywgbm90IHR3b1xuICAgICAgICAgICAgICAgIHVuaG9vayh2Tm9kZSwgcGF0Y2gsIGluZGV4KTtcbiAgICAgICAgICAgICAgICBkZXN0cm95V2lkZ2V0cyh2Tm9kZSwgcGF0Y2gsIGluZGV4KTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgLy8gUGF0Y2ggcmVjb3JkcyBmb3IgYWxsIGRlc3Ryb3llZCB3aWRnZXRzIG11c3QgYmUgYWRkZWQgYmVjYXVzZSB3ZSBuZWVkXG4gICAgICAgICAgICAvLyBhIERPTSBub2RlIHJlZmVyZW5jZSBmb3IgdGhlIGRlc3Ryb3kgZnVuY3Rpb25cbiAgICAgICAgICAgIGZ1bmN0aW9uIGRlc3Ryb3lXaWRnZXRzKHZOb2RlLCBwYXRjaCwgaW5kZXgpIHtcbiAgICAgICAgICAgICAgICBpZiAoaXNXaWRnZXQodk5vZGUpKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmICh0eXBlb2Ygdk5vZGUuZGVzdHJveSA9PT0gXCJmdW5jdGlvblwiKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBwYXRjaFtpbmRleF0gPSBhcHBlbmRQYXRjaChwYXRjaFtpbmRleF0sIG5ldyBWUGF0Y2goVlBhdGNoLlJFTU9WRSwgdk5vZGUsIG51bGwpKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoaXNWTm9kZSh2Tm9kZSkgJiYgKHZOb2RlLmhhc1dpZGdldHMgfHwgdk5vZGUuaGFzVGh1bmtzKSkge1xuICAgICAgICAgICAgICAgICAgICB2YXIgY2hpbGRyZW4gPSB2Tm9kZS5jaGlsZHJlbjtcbiAgICAgICAgICAgICAgICAgICAgdmFyIGxlbiA9IGNoaWxkcmVuLmxlbmd0aDtcbiAgICAgICAgICAgICAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCBsZW47IGkrKykge1xuICAgICAgICAgICAgICAgICAgICAgICAgdmFyIGNoaWxkID0gY2hpbGRyZW5baV07XG4gICAgICAgICAgICAgICAgICAgICAgICBpbmRleCArPSAxO1xuXG4gICAgICAgICAgICAgICAgICAgICAgICBkZXN0cm95V2lkZ2V0cyhjaGlsZCwgcGF0Y2gsIGluZGV4KTtcblxuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGlzVk5vZGUoY2hpbGQpICYmIGNoaWxkLmNvdW50KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaW5kZXggKz0gY2hpbGQuY291bnQ7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKGlzVGh1bmsodk5vZGUpKSB7XG4gICAgICAgICAgICAgICAgICAgIHRodW5rcyh2Tm9kZSwgbnVsbCwgcGF0Y2gsIGluZGV4KTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIC8vIENyZWF0ZSBhIHN1Yi1wYXRjaCBmb3IgdGh1bmtzXG4gICAgICAgICAgICBmdW5jdGlvbiB0aHVua3MoYSwgYiwgcGF0Y2gsIGluZGV4KSB7XG4gICAgICAgICAgICAgICAgdmFyIG5vZGVzID0gaGFuZGxlVGh1bmsoYSwgYik7XG4gICAgICAgICAgICAgICAgdmFyIHRodW5rUGF0Y2ggPSBkaWZmKG5vZGVzLmEsIG5vZGVzLmIpO1xuICAgICAgICAgICAgICAgIGlmIChoYXNQYXRjaGVzKHRodW5rUGF0Y2gpKSB7XG4gICAgICAgICAgICAgICAgICAgIHBhdGNoW2luZGV4XSA9IG5ldyBWUGF0Y2goVlBhdGNoLlRIVU5LLCBudWxsLCB0aHVua1BhdGNoKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIGhhc1BhdGNoZXMocGF0Y2gpIHtcbiAgICAgICAgICAgICAgICBmb3IgKHZhciBpbmRleCBpbiBwYXRjaCkge1xuICAgICAgICAgICAgICAgICAgICBpZiAoaW5kZXggIT09IFwiYVwiKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgLy8gRXhlY3V0ZSBob29rcyB3aGVuIHR3byBub2RlcyBhcmUgaWRlbnRpY2FsXG4gICAgICAgICAgICBmdW5jdGlvbiB1bmhvb2sodk5vZGUsIHBhdGNoLCBpbmRleCkge1xuICAgICAgICAgICAgICAgIGlmIChpc1ZOb2RlKHZOb2RlKSkge1xuICAgICAgICAgICAgICAgICAgICBpZiAodk5vZGUuaG9va3MpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHBhdGNoW2luZGV4XSA9IGFwcGVuZFBhdGNoKHBhdGNoW2luZGV4XSwgbmV3IFZQYXRjaChWUGF0Y2guUFJPUFMsIHZOb2RlLCB1bmRlZmluZWRLZXlzKHZOb2RlLmhvb2tzKSkpO1xuICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgaWYgKHZOb2RlLmRlc2NlbmRhbnRIb29rcyB8fCB2Tm9kZS5oYXNUaHVua3MpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHZhciBjaGlsZHJlbiA9IHZOb2RlLmNoaWxkcmVuO1xuICAgICAgICAgICAgICAgICAgICAgICAgdmFyIGxlbiA9IGNoaWxkcmVuLmxlbmd0aDtcbiAgICAgICAgICAgICAgICAgICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgbGVuOyBpKyspIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB2YXIgY2hpbGQgPSBjaGlsZHJlbltpXTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpbmRleCArPSAxO1xuXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdW5ob29rKGNoaWxkLCBwYXRjaCwgaW5kZXgpO1xuXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGlzVk5vZGUoY2hpbGQpICYmIGNoaWxkLmNvdW50KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGluZGV4ICs9IGNoaWxkLmNvdW50O1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoaXNUaHVuayh2Tm9kZSkpIHtcbiAgICAgICAgICAgICAgICAgICAgdGh1bmtzKHZOb2RlLCBudWxsLCBwYXRjaCwgaW5kZXgpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZnVuY3Rpb24gdW5kZWZpbmVkS2V5cyhvYmopIHtcbiAgICAgICAgICAgICAgICB2YXIgcmVzdWx0ID0ge307XG5cbiAgICAgICAgICAgICAgICBmb3IgKHZhciBrZXkgaW4gb2JqKSB7XG4gICAgICAgICAgICAgICAgICAgIHJlc3VsdFtrZXldID0gdW5kZWZpbmVkO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHJldHVybiByZXN1bHQ7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIC8vIExpc3QgZGlmZiwgbmFpdmUgbGVmdCB0byByaWdodCByZW9yZGVyaW5nXG4gICAgICAgICAgICBmdW5jdGlvbiByZW9yZGVyKGFDaGlsZHJlbiwgYkNoaWxkcmVuKSB7XG4gICAgICAgICAgICAgICAgLy8gTyhNKSB0aW1lLCBPKE0pIG1lbW9yeVxuICAgICAgICAgICAgICAgIHZhciBiQ2hpbGRJbmRleCA9IGtleUluZGV4KGJDaGlsZHJlbik7XG4gICAgICAgICAgICAgICAgdmFyIGJLZXlzID0gYkNoaWxkSW5kZXgua2V5cztcbiAgICAgICAgICAgICAgICB2YXIgYkZyZWUgPSBiQ2hpbGRJbmRleC5mcmVlO1xuXG4gICAgICAgICAgICAgICAgaWYgKGJGcmVlLmxlbmd0aCA9PT0gYkNoaWxkcmVuLmxlbmd0aCkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgICAgICAgICAgICAgY2hpbGRyZW46IGJDaGlsZHJlbixcbiAgICAgICAgICAgICAgICAgICAgICAgIG1vdmVzOiBudWxsXG4gICAgICAgICAgICAgICAgICAgIH07XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgLy8gTyhOKSB0aW1lLCBPKE4pIG1lbW9yeVxuICAgICAgICAgICAgICAgIHZhciBhQ2hpbGRJbmRleCA9IGtleUluZGV4KGFDaGlsZHJlbik7XG4gICAgICAgICAgICAgICAgdmFyIGFLZXlzID0gYUNoaWxkSW5kZXgua2V5cztcbiAgICAgICAgICAgICAgICB2YXIgYUZyZWUgPSBhQ2hpbGRJbmRleC5mcmVlO1xuXG4gICAgICAgICAgICAgICAgaWYgKGFGcmVlLmxlbmd0aCA9PT0gYUNoaWxkcmVuLmxlbmd0aCkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgICAgICAgICAgICAgY2hpbGRyZW46IGJDaGlsZHJlbixcbiAgICAgICAgICAgICAgICAgICAgICAgIG1vdmVzOiBudWxsXG4gICAgICAgICAgICAgICAgICAgIH07XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgLy8gTyhNQVgoTiwgTSkpIG1lbW9yeVxuICAgICAgICAgICAgICAgIHZhciBuZXdDaGlsZHJlbiA9IFtdO1xuXG4gICAgICAgICAgICAgICAgdmFyIGZyZWVJbmRleCA9IDA7XG4gICAgICAgICAgICAgICAgdmFyIGZyZWVDb3VudCA9IGJGcmVlLmxlbmd0aDtcbiAgICAgICAgICAgICAgICB2YXIgZGVsZXRlZEl0ZW1zID0gMDtcblxuICAgICAgICAgICAgICAgIC8vIEl0ZXJhdGUgdGhyb3VnaCBhIGFuZCBtYXRjaCBhIG5vZGUgaW4gYlxuICAgICAgICAgICAgICAgIC8vIE8oTikgdGltZSxcbiAgICAgICAgICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IGFDaGlsZHJlbi5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgICAgICAgICB2YXIgYUl0ZW0gPSBhQ2hpbGRyZW5baV07XG4gICAgICAgICAgICAgICAgICAgIHZhciBpdGVtSW5kZXg7XG5cbiAgICAgICAgICAgICAgICAgICAgaWYgKGFJdGVtLmtleSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGJLZXlzLmhhc093blByb3BlcnR5KGFJdGVtLmtleSkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBNYXRjaCB1cCB0aGUgb2xkIGtleXNcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpdGVtSW5kZXggPSBiS2V5c1thSXRlbS5rZXldO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIG5ld0NoaWxkcmVuLnB1c2goYkNoaWxkcmVuW2l0ZW1JbmRleF0pO1xuICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBSZW1vdmUgb2xkIGtleWVkIGl0ZW1zXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaXRlbUluZGV4ID0gaSAtIGRlbGV0ZWRJdGVtcysrO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIG5ld0NoaWxkcmVuLnB1c2gobnVsbCk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAvLyBNYXRjaCB0aGUgaXRlbSBpbiBhIHdpdGggdGhlIG5leHQgZnJlZSBpdGVtIGluIGJcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChmcmVlSW5kZXggPCBmcmVlQ291bnQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpdGVtSW5kZXggPSBiRnJlZVtmcmVlSW5kZXgrK107XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgbmV3Q2hpbGRyZW4ucHVzaChiQ2hpbGRyZW5baXRlbUluZGV4XSk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIFRoZXJlIGFyZSBubyBmcmVlIGl0ZW1zIGluIGIgdG8gbWF0Y2ggd2l0aFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIHRoZSBmcmVlIGl0ZW1zIGluIGEsIHNvIHRoZSBleHRyYSBmcmVlIG5vZGVzXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gYXJlIGRlbGV0ZWQuXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaXRlbUluZGV4ID0gaSAtIGRlbGV0ZWRJdGVtcysrO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIG5ld0NoaWxkcmVuLnB1c2gobnVsbCk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICB2YXIgbGFzdEZyZWVJbmRleCA9IGZyZWVJbmRleCA+PSBiRnJlZS5sZW5ndGggPyBiQ2hpbGRyZW4ubGVuZ3RoIDogYkZyZWVbZnJlZUluZGV4XTtcblxuICAgICAgICAgICAgICAgIC8vIEl0ZXJhdGUgdGhyb3VnaCBiIGFuZCBhcHBlbmQgYW55IG5ldyBrZXlzXG4gICAgICAgICAgICAgICAgLy8gTyhNKSB0aW1lXG4gICAgICAgICAgICAgICAgZm9yICh2YXIgaiA9IDA7IGogPCBiQ2hpbGRyZW4ubGVuZ3RoOyBqKyspIHtcbiAgICAgICAgICAgICAgICAgICAgdmFyIG5ld0l0ZW0gPSBiQ2hpbGRyZW5bal07XG5cbiAgICAgICAgICAgICAgICAgICAgaWYgKG5ld0l0ZW0ua2V5KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoIWFLZXlzLmhhc093blByb3BlcnR5KG5ld0l0ZW0ua2V5KSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIEFkZCBhbnkgbmV3IGtleWVkIGl0ZW1zXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gV2UgYXJlIGFkZGluZyBuZXcgaXRlbXMgdG8gdGhlIGVuZCBhbmQgdGhlbiBzb3J0aW5nIHRoZW1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBpbiBwbGFjZS4gSW4gZnV0dXJlIHdlIHNob3VsZCBpbnNlcnQgbmV3IGl0ZW1zIGluIHBsYWNlLlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIG5ld0NoaWxkcmVuLnB1c2gobmV3SXRlbSk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoaiA+PSBsYXN0RnJlZUluZGV4KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAvLyBBZGQgYW55IGxlZnRvdmVyIG5vbi1rZXllZCBpdGVtc1xuICAgICAgICAgICAgICAgICAgICAgICAgbmV3Q2hpbGRyZW4ucHVzaChuZXdJdGVtKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHZhciBzaW11bGF0ZSA9IG5ld0NoaWxkcmVuLnNsaWNlKCk7XG4gICAgICAgICAgICAgICAgdmFyIHNpbXVsYXRlSW5kZXggPSAwO1xuICAgICAgICAgICAgICAgIHZhciByZW1vdmVzID0gW107XG4gICAgICAgICAgICAgICAgdmFyIGluc2VydHMgPSBbXTtcbiAgICAgICAgICAgICAgICB2YXIgc2ltdWxhdGVJdGVtO1xuXG4gICAgICAgICAgICAgICAgZm9yICh2YXIgayA9IDA7IGsgPCBiQ2hpbGRyZW4ubGVuZ3RoOykge1xuICAgICAgICAgICAgICAgICAgICB2YXIgd2FudGVkSXRlbSA9IGJDaGlsZHJlbltrXTtcbiAgICAgICAgICAgICAgICAgICAgc2ltdWxhdGVJdGVtID0gc2ltdWxhdGVbc2ltdWxhdGVJbmRleF07XG5cbiAgICAgICAgICAgICAgICAgICAgLy8gcmVtb3ZlIGl0ZW1zXG4gICAgICAgICAgICAgICAgICAgIHdoaWxlIChzaW11bGF0ZUl0ZW0gPT09IG51bGwgJiYgc2ltdWxhdGUubGVuZ3RoKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICByZW1vdmVzLnB1c2gocmVtb3ZlKHNpbXVsYXRlLCBzaW11bGF0ZUluZGV4LCBudWxsKSk7XG4gICAgICAgICAgICAgICAgICAgICAgICBzaW11bGF0ZUl0ZW0gPSBzaW11bGF0ZVtzaW11bGF0ZUluZGV4XTtcbiAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgIGlmICghc2ltdWxhdGVJdGVtIHx8IHNpbXVsYXRlSXRlbS5rZXkgIT09IHdhbnRlZEl0ZW0ua2V5KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAvLyBpZiB3ZSBuZWVkIGEga2V5IGluIHRoaXMgcG9zaXRpb24uLi5cbiAgICAgICAgICAgICAgICAgICAgICAgIGlmICh3YW50ZWRJdGVtLmtleSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChzaW11bGF0ZUl0ZW0gJiYgc2ltdWxhdGVJdGVtLmtleSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBpZiBhbiBpbnNlcnQgZG9lc24ndCBwdXQgdGhpcyBrZXkgaW4gcGxhY2UsIGl0IG5lZWRzIHRvIG1vdmVcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGJLZXlzW3NpbXVsYXRlSXRlbS5rZXldICE9PSBrICsgMSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmVtb3Zlcy5wdXNoKHJlbW92ZShzaW11bGF0ZSwgc2ltdWxhdGVJbmRleCwgc2ltdWxhdGVJdGVtLmtleSkpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc2ltdWxhdGVJdGVtID0gc2ltdWxhdGVbc2ltdWxhdGVJbmRleF07XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBpZiB0aGUgcmVtb3ZlIGRpZG4ndCBwdXQgdGhlIHdhbnRlZCBpdGVtIGluIHBsYWNlLCB3ZSBuZWVkIHRvIGluc2VydCBpdFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKCFzaW11bGF0ZUl0ZW0gfHwgc2ltdWxhdGVJdGVtLmtleSAhPT0gd2FudGVkSXRlbS5rZXkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpbnNlcnRzLnB1c2goeyBrZXk6IHdhbnRlZEl0ZW0ua2V5LCB0bzogayB9KTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIGl0ZW1zIGFyZSBtYXRjaGluZywgc28gc2tpcCBhaGVhZFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc2ltdWxhdGVJbmRleCsrO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaW5zZXJ0cy5wdXNoKHsga2V5OiB3YW50ZWRJdGVtLmtleSwgdG86IGsgfSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpbnNlcnRzLnB1c2goeyBrZXk6IHdhbnRlZEl0ZW0ua2V5LCB0bzogayB9KTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaysrO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgLy8gYSBrZXkgaW4gc2ltdWxhdGUgaGFzIG5vIG1hdGNoaW5nIHdhbnRlZCBrZXksIHJlbW92ZSBpdFxuICAgICAgICAgICAgICAgICAgICAgICAgZWxzZSBpZiAoc2ltdWxhdGVJdGVtICYmIHNpbXVsYXRlSXRlbS5rZXkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICByZW1vdmVzLnB1c2gocmVtb3ZlKHNpbXVsYXRlLCBzaW11bGF0ZUluZGV4LCBzaW11bGF0ZUl0ZW0ua2V5KSk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBzaW11bGF0ZUluZGV4Kys7XG4gICAgICAgICAgICAgICAgICAgICAgICBrKys7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAvLyByZW1vdmUgYWxsIHRoZSByZW1haW5pbmcgbm9kZXMgZnJvbSBzaW11bGF0ZVxuICAgICAgICAgICAgICAgIHdoaWxlIChzaW11bGF0ZUluZGV4IDwgc2ltdWxhdGUubGVuZ3RoKSB7XG4gICAgICAgICAgICAgICAgICAgIHNpbXVsYXRlSXRlbSA9IHNpbXVsYXRlW3NpbXVsYXRlSW5kZXhdO1xuICAgICAgICAgICAgICAgICAgICByZW1vdmVzLnB1c2gocmVtb3ZlKHNpbXVsYXRlLCBzaW11bGF0ZUluZGV4LCBzaW11bGF0ZUl0ZW0gJiYgc2ltdWxhdGVJdGVtLmtleSkpO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIC8vIElmIHRoZSBvbmx5IG1vdmVzIHdlIGhhdmUgYXJlIGRlbGV0ZXMgdGhlbiB3ZSBjYW4ganVzdFxuICAgICAgICAgICAgICAgIC8vIGxldCB0aGUgZGVsZXRlIHBhdGNoIHJlbW92ZSB0aGVzZSBpdGVtcy5cbiAgICAgICAgICAgICAgICBpZiAocmVtb3Zlcy5sZW5ndGggPT09IGRlbGV0ZWRJdGVtcyAmJiAhaW5zZXJ0cy5sZW5ndGgpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGNoaWxkcmVuOiBuZXdDaGlsZHJlbixcbiAgICAgICAgICAgICAgICAgICAgICAgIG1vdmVzOiBudWxsXG4gICAgICAgICAgICAgICAgICAgIH07XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgICAgICAgICAgY2hpbGRyZW46IG5ld0NoaWxkcmVuLFxuICAgICAgICAgICAgICAgICAgICBtb3Zlczoge1xuICAgICAgICAgICAgICAgICAgICAgICAgcmVtb3ZlczogcmVtb3ZlcyxcbiAgICAgICAgICAgICAgICAgICAgICAgIGluc2VydHM6IGluc2VydHNcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH07XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIHJlbW92ZShhcnIsIGluZGV4LCBrZXkpIHtcbiAgICAgICAgICAgICAgICBhcnIuc3BsaWNlKGluZGV4LCAxKTtcblxuICAgICAgICAgICAgICAgIHJldHVybiB7XG4gICAgICAgICAgICAgICAgICAgIGZyb206IGluZGV4LFxuICAgICAgICAgICAgICAgICAgICBrZXk6IGtleVxuICAgICAgICAgICAgICAgIH07XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIGtleUluZGV4KGNoaWxkcmVuKSB7XG4gICAgICAgICAgICAgICAgdmFyIGtleXMgPSB7fTtcbiAgICAgICAgICAgICAgICB2YXIgZnJlZSA9IFtdO1xuICAgICAgICAgICAgICAgIHZhciBsZW5ndGggPSBjaGlsZHJlbi5sZW5ndGg7XG5cbiAgICAgICAgICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IGxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciBjaGlsZCA9IGNoaWxkcmVuW2ldO1xuXG4gICAgICAgICAgICAgICAgICAgIGlmIChjaGlsZC5rZXkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGtleXNbY2hpbGQua2V5XSA9IGk7XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBmcmVlLnB1c2goaSk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgICAgICAgICBrZXlzOiBrZXlzLCAvLyBBIGhhc2ggb2Yga2V5IG5hbWUgdG8gaW5kZXhcbiAgICAgICAgICAgICAgICAgICAgZnJlZTogZnJlZSAvLyBBbiBhcnJheSBvZiB1bmtleWVkIGl0ZW0gaW5kaWNlc1xuICAgICAgICAgICAgICAgIH07XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIGFwcGVuZFBhdGNoKGFwcGx5LCBwYXRjaCkge1xuICAgICAgICAgICAgICAgIGlmIChhcHBseSkge1xuICAgICAgICAgICAgICAgICAgICBpZiAoaXNBcnJheShhcHBseSkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGFwcGx5LnB1c2gocGF0Y2gpO1xuICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgYXBwbHkgPSBbYXBwbHksIHBhdGNoXTtcbiAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBhcHBseTtcbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gcGF0Y2g7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9LCB7IFwiLi4vdm5vZGUvaGFuZGxlLXRodW5rXCI6IDI0LCBcIi4uL3Zub2RlL2lzLXRodW5rXCI6IDI1LCBcIi4uL3Zub2RlL2lzLXZub2RlXCI6IDI3LCBcIi4uL3Zub2RlL2lzLXZ0ZXh0XCI6IDI4LCBcIi4uL3Zub2RlL2lzLXdpZGdldFwiOiAyOSwgXCIuLi92bm9kZS92cGF0Y2hcIjogMzIsIFwiLi9kaWZmLXByb3BzXCI6IDM0LCBcIngtaXMtYXJyYXlcIjogMTIgfV0gfSwge30sIFs0XSkoNCk7XG59KTtcblxuLyogQGZsb3cgKi9cblxuY2xhc3MgTWFpbGJveCB7XG5cbiAgY29uc3RydWN0b3IoKSB7XG4gICAgdGhpcy5tZXNzYWdlcyA9IFtdO1xuICB9XG5cbiAgZGVsaXZlcihtZXNzYWdlKSB7XG4gICAgdGhpcy5tZXNzYWdlcy5wdXNoKG1lc3NhZ2UpO1xuICAgIHJldHVybiBtZXNzYWdlO1xuICB9XG5cbiAgZ2V0KCkge1xuICAgIHJldHVybiB0aGlzLm1lc3NhZ2VzO1xuICB9XG5cbiAgaXNFbXB0eSgpIHtcbiAgICByZXR1cm4gdGhpcy5tZXNzYWdlcy5sZW5ndGggPT09IDA7XG4gIH1cblxuICByZW1vdmVBdChpbmRleCkge1xuICAgIHRoaXMubWVzc2FnZXMuc3BsaWNlKGluZGV4LCAxKTtcbiAgfVxufVxuXG52YXIgU3RhdGVzID0ge1xuICBOT1JNQUw6IFN5bWJvbC5mb3IoXCJub3JtYWxcIiksXG4gIEtJTEw6IFN5bWJvbC5mb3IoXCJraWxsXCIpLFxuICBTVVNQRU5EOiBTeW1ib2wuZm9yKFwic3VzcGVuZFwiKSxcbiAgQ09OVElOVUU6IFN5bWJvbC5mb3IoXCJjb250aW51ZVwiKSxcbiAgUkVDRUlWRTogU3ltYm9sLmZvcihcInJlY2VpdmVcIiksXG4gIFNFTkQ6IFN5bWJvbC5mb3IoXCJzZW5kXCIpLFxuICBTTEVFUElORzogU3ltYm9sLmZvcihcInNsZWVwaW5nXCIpLFxuICBSVU5OSU5HOiBTeW1ib2wuZm9yKFwicnVubmluZ1wiKSxcbiAgU1VTUEVOREVEOiBTeW1ib2wuZm9yKFwic3VzcGVuZGVkXCIpLFxuICBTVE9QUEVEOiBTeW1ib2wuZm9yKFwic3RvcHBlZFwiKSxcbiAgU0xFRVA6IFN5bWJvbC5mb3IoXCJzbGVlcFwiKSxcbiAgRVhJVDogU3ltYm9sLmZvcihcImV4aXRcIiksXG4gIE5PTUFUQ0g6IFN5bWJvbC5mb3IoXCJub19tYXRjaFwiKVxufTtcblxuY2xhc3MgUHJvY2VzcyB7XG5cbiAgY29uc3RydWN0b3IocGlkLCBtYWlsYm94KSB7XG4gICAgdGhpcy5waWQgPSBwaWQ7XG4gICAgdGhpcy5tYWlsYm94ID0gbWFpbGJveDtcbiAgICB0aGlzLnN0YXR1cyA9IFN0YXRlcy5TVE9QUEVEO1xuICAgIHRoaXMuZGljdCA9IHt9O1xuICB9XG59XG5cbmNsYXNzIFR1cGxlIHtcblxuICBjb25zdHJ1Y3RvciguLi5hcmdzKSB7XG4gICAgdGhpcy52YWx1ZXMgPSBPYmplY3QuZnJlZXplKGFyZ3MpO1xuICAgIHRoaXMubGVuZ3RoID0gdGhpcy52YWx1ZXMubGVuZ3RoO1xuICB9XG5cbiAgZ2V0KGluZGV4KSB7XG4gICAgcmV0dXJuIHRoaXMudmFsdWVzW2luZGV4XTtcbiAgfVxuXG4gIGNvdW50KCkge1xuICAgIHJldHVybiB0aGlzLnZhbHVlcy5sZW5ndGg7XG4gIH1cblxuICBbU3ltYm9sLml0ZXJhdG9yXSgpIHtcbiAgICByZXR1cm4gdGhpcy52YWx1ZXNbU3ltYm9sLml0ZXJhdG9yXSgpO1xuICB9XG5cbiAgdG9TdHJpbmcoKSB7XG4gICAgdmFyIGksXG4gICAgICAgIHMgPSBcIlwiO1xuICAgIGZvciAoaSA9IDA7IGkgPCB0aGlzLnZhbHVlcy5sZW5ndGg7IGkrKykge1xuICAgICAgaWYgKHMgIT09IFwiXCIpIHtcbiAgICAgICAgcyArPSBcIiwgXCI7XG4gICAgICB9XG4gICAgICBzICs9IHRoaXMudmFsdWVzW2ldLnRvU3RyaW5nKCk7XG4gICAgfVxuXG4gICAgcmV0dXJuIFwie1wiICsgcyArIFwifVwiO1xuICB9XG5cbiAgcHV0X2VsZW0oaW5kZXgsIGVsZW0pIHtcbiAgICBpZiAoaW5kZXggPT09IHRoaXMubGVuZ3RoKSB7XG4gICAgICBsZXQgbmV3X3ZhbHVlcyA9IHRoaXMudmFsdWVzLmNvbmNhdChbZWxlbV0pO1xuICAgICAgcmV0dXJuIG5ldyBUdXBsZSguLi5uZXdfdmFsdWVzKTtcbiAgICB9XG5cbiAgICBsZXQgbmV3X3ZhbHVlcyA9IHRoaXMudmFsdWVzLmNvbmNhdChbXSk7XG4gICAgbmV3X3ZhbHVlcy5zcGxpY2UoaW5kZXgsIDAsIGVsZW0pO1xuICAgIHJldHVybiBuZXcgVHVwbGUoLi4ubmV3X3ZhbHVlcyk7XG4gIH1cblxuICByZW1vdmVfZWxlbShpbmRleCkge1xuICAgIGxldCBuZXdfdmFsdWVzID0gdGhpcy52YWx1ZXMuY29uY2F0KFtdKTtcbiAgICBuZXdfdmFsdWVzLnNwbGljZShpbmRleCwgMSk7XG4gICAgcmV0dXJuIG5ldyBUdXBsZSguLi5uZXdfdmFsdWVzKTtcbiAgfVxuXG59XG5cbmxldCBwcm9jZXNzX2NvdW50ZXIgPSAtMTtcblxuY2xhc3MgUElEIHtcbiAgY29uc3RydWN0b3IoKSB7XG4gICAgcHJvY2Vzc19jb3VudGVyID0gcHJvY2Vzc19jb3VudGVyICsgMTtcbiAgICB0aGlzLmlkID0gcHJvY2Vzc19jb3VudGVyO1xuICB9XG5cbiAgdG9TdHJpbmcoKSB7XG4gICAgcmV0dXJuIFwiUElEIzwwLlwiICsgdGhpcy5pZCArIFwiLjA+XCI7XG4gIH1cbn1cblxuY2xhc3MgSW50ZWdlciB7fVxuY2xhc3MgRmxvYXQge31cblxuY2xhc3MgUHJvY2Vzc1N5c3RlbSB7XG5cbiAgY29uc3RydWN0b3IoKSB7XG4gICAgdGhpcy5waWRzID0gbmV3IE1hcCgpO1xuICAgIHRoaXMubWFpbGJveGVzID0gbmV3IE1hcCgpO1xuICAgIHRoaXMubmFtZXMgPSBuZXcgTWFwKCk7XG4gICAgdGhpcy5saW5rcyA9IG5ldyBNYXAoKTtcblxuICAgIHRoaXMuY3VycmVudF9wcm9jZXNzID0gbnVsbDtcbiAgICB0aGlzLnN1c3BlbmRlZCA9IG5ldyBNYXAoKTtcblxuICAgIHRoaXMubWFpbl9wcm9jZXNzX3BpZCA9IHRoaXMuc3Bhd24oKTtcbiAgICB0aGlzLnNldF9jdXJyZW50KHRoaXMubWFpbl9wcm9jZXNzX3BpZCk7XG4gIH1cblxuICBzcGF3bigpIHtcbiAgICByZXR1cm4gdGhpcy5hZGRfcHJvYyhmYWxzZSkucGlkO1xuICB9XG5cbiAgc3Bhd25fbGluaygpIHtcbiAgICByZXR1cm4gdGhpcy5hZGRfcHJvYyh0cnVlKS5waWQ7XG4gIH1cblxuICBsaW5rKHBpZCkge1xuICAgIHRoaXMubGlua3MuZ2V0KHRoaXMucGlkKCkpLmFkZChwaWQpO1xuICAgIHRoaXMubGlua3MuZ2V0KHBpZCkuYWRkKHRoaXMucGlkKCkpO1xuICB9XG5cbiAgdW5saW5rKHBpZCkge1xuICAgIHRoaXMubGlua3MuZ2V0KHRoaXMucGlkKCkpLmRlbGV0ZShwaWQpO1xuICAgIHRoaXMubGlua3MuZ2V0KHBpZCkuZGVsZXRlKHRoaXMucGlkKCkpO1xuICB9XG5cbiAgc2V0X2N1cnJlbnQoaWQpIHtcbiAgICBsZXQgcGlkID0gdGhpcy5waWRvZihpZCk7XG4gICAgaWYgKHBpZCAhPT0gbnVsbCkge1xuICAgICAgdGhpcy5jdXJyZW50X3Byb2Nlc3MgPSB0aGlzLnBpZHMuZ2V0KHBpZCk7XG4gICAgICB0aGlzLmN1cnJlbnRfcHJvY2Vzcy5zdGF0dXMgPSBTdGF0ZXMuUlVOTklORztcbiAgICB9XG4gIH1cblxuICBhZGRfcHJvYyhsaW5rZWQpIHtcbiAgICBsZXQgbmV3cGlkID0gbmV3IFBJRCgpO1xuICAgIGxldCBtYWlsYm94ID0gbmV3IE1haWxib3goKTtcbiAgICBsZXQgbmV3cHJvYyA9IG5ldyBQcm9jZXNzKG5ld3BpZCwgbWFpbGJveCk7XG5cbiAgICB0aGlzLnBpZHMuc2V0KG5ld3BpZCwgbmV3cHJvYyk7XG4gICAgdGhpcy5tYWlsYm94ZXMuc2V0KG5ld3BpZCwgbWFpbGJveCk7XG4gICAgdGhpcy5saW5rcy5zZXQobmV3cGlkLCBuZXcgU2V0KCkpO1xuXG4gICAgaWYgKGxpbmtlZCkge1xuICAgICAgdGhpcy5saW5rKG5ld3BpZCk7XG4gICAgfVxuXG4gICAgcmV0dXJuIG5ld3Byb2M7XG4gIH1cblxuICByZW1vdmVfcHJvYyhwaWQpIHtcbiAgICB0aGlzLnBpZHMuZGVsZXRlKHBpZCk7XG4gICAgdGhpcy51bnJlZ2lzdGVyKHBpZCk7XG5cbiAgICBpZiAodGhpcy5saW5rcy5oYXMocGlkKSkge1xuICAgICAgZm9yIChsZXQgbGlua3BpZCBvZiB0aGlzLmxpbmtzLmdldChwaWQpKSB7XG4gICAgICAgIHRoaXMubGlua3MuZ2V0KGxpbmtwaWQpLmRlbGV0ZShwaWQpO1xuICAgICAgfVxuXG4gICAgICB0aGlzLmxpbmtzLmRlbGV0ZShwaWQpO1xuICAgIH1cbiAgfVxuXG4gIGV4aXQoaWQpIHtcbiAgICBsZXQgcGlkID0gdGhpcy5waWRvZihpZCk7XG4gICAgdGhpcy5yZW1vdmVfcHJvYyhpZCk7XG4gIH1cblxuICByZWdpc3RlcihuYW1lLCBwaWQpIHtcbiAgICBpZiAoIXRoaXMubmFtZXMuaGFzKG5hbWUpKSB7XG4gICAgICB0aGlzLm5hbWVzLnNldChuYW1lLCBwaWQpO1xuICAgICAgcmV0dXJuIG5hbWU7XG4gICAgfSBlbHNlIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcihcIk5hbWUgaXMgYWxyZWFkeSByZWdpc3RlcmVkIHRvIGFub3RoZXIgcHJvY2Vzc1wiKTtcbiAgICB9XG4gIH1cblxuICByZWdpc3RlcmVkKG5hbWUpIHtcbiAgICByZXR1cm4gdGhpcy5uYW1lcy5oYXMobmFtZSkgPyB0aGlzLm5hbWVzLmdldChuYW1lKSA6IG51bGw7XG4gIH1cblxuICB1bnJlZ2lzdGVyKHBpZCkge1xuICAgIGZvciAobGV0IG5hbWUgb2YgdGhpcy5uYW1lcy5rZXlzKCkpIHtcbiAgICAgIGlmICh0aGlzLm5hbWVzLmhhcyhuYW1lKSAmJiB0aGlzLm5hbWVzLmdldChuYW1lKSA9PT0gcGlkKSB7XG4gICAgICAgIHRoaXMubmFtZXMuZGVsZXRlKG5hbWUpO1xuICAgICAgfVxuICAgIH1cbiAgfVxuXG4gIHBpZCgpIHtcbiAgICByZXR1cm4gdGhpcy5jdXJyZW50X3Byb2Nlc3MucGlkO1xuICB9XG5cbiAgcGlkb2YoaWQpIHtcbiAgICBpZiAoaWQgaW5zdGFuY2VvZiBQSUQpIHtcbiAgICAgIHJldHVybiB0aGlzLnBpZHMuaGFzKGlkKSA/IGlkIDogbnVsbDtcbiAgICB9IGVsc2UgaWYgKGlkIGluc3RhbmNlb2YgUHJvY2Vzcykge1xuICAgICAgcmV0dXJuIGlkLnBpZDtcbiAgICB9IGVsc2Uge1xuICAgICAgbGV0IHBpZCA9IHRoaXMucmVnaXN0ZXJlZChpZCk7XG4gICAgICBpZiAocGlkID09PSBudWxsKSB0aHJvdyBcIlByb2Nlc3MgbmFtZSBub3QgcmVnaXN0ZXJlZDogXCIgKyBpZCArIFwiIChcIiArIHR5cGVvZiBpZCArIFwiKVwiO1xuICAgICAgcmV0dXJuIHBpZDtcbiAgICB9XG4gIH1cblxuICBwdXQoaWQsIGtleSwgdmFsdWUpIHtcbiAgICBsZXQgcGlkID0gdGhpcy5waWRvZihpZCk7XG4gICAgbGV0IHByb2Nlc3MgPSB0aGlzLnBpZHMuZ2V0KHBpZCk7XG4gICAgcHJvY2Vzcy5kaWN0W2tleV0gPSB2YWx1ZTtcbiAgfVxuXG4gIGdldChpZCwga2V5KSB7XG4gICAgbGV0IHBpZCA9IHRoaXMucGlkb2YoaWQpO1xuICAgIGxldCBwcm9jZXNzID0gdGhpcy5waWRzLmdldChwaWQpO1xuXG4gICAgaWYgKGtleSAhPSBudWxsKSB7XG4gICAgICByZXR1cm4gcHJvY2Vzcy5kaWN0W2tleV07XG4gICAgfSBlbHNlIHtcbiAgICAgIHJldHVybiBwcm9jZXNzLmRpY3Q7XG4gICAgfVxuICB9XG5cbiAgZ2V0X2tleXMoaWQpIHtcbiAgICBsZXQgcGlkID0gdGhpcy5waWRvZihpZCk7XG4gICAgbGV0IHByb2Nlc3MgPSB0aGlzLnBpZHMuZ2V0KHBpZCk7XG5cbiAgICByZXR1cm4gT2JqZWN0LmtleXMocHJvY2Vzcy5kaWN0KTtcbiAgfVxuXG4gIGVyYXNlKGlkLCBrZXkpIHtcbiAgICBsZXQgcGlkID0gdGhpcy5waWRvZihpZCk7XG4gICAgbGV0IHByb2Nlc3MgPSB0aGlzLnBpZHMuZ2V0KHBpZCk7XG5cbiAgICBpZiAoa2V5ICE9IG51bGwpIHtcbiAgICAgIGRlbGV0ZSBwcm9jZXNzLmRpY3Rba2V5XTtcbiAgICB9IGVsc2Uge1xuICAgICAgcHJvY2Vzcy5kaWN0ID0ge307XG4gICAgfVxuICB9XG59XG5cbmNsYXNzIEJpdFN0cmluZyB7XG4gIGNvbnN0cnVjdG9yKC4uLmFyZ3MpIHtcbiAgICB0aGlzLnJhd192YWx1ZSA9IGZ1bmN0aW9uICgpIHtcbiAgICAgIHJldHVybiBPYmplY3QuZnJlZXplKGFyZ3MpO1xuICAgIH07XG5cbiAgICB0aGlzLnZhbHVlID0gT2JqZWN0LmZyZWV6ZSh0aGlzLnByb2Nlc3MoYXJncykpO1xuICAgIHRoaXMubGVuZ3RoID0gdGhpcy52YWx1ZS5sZW5ndGg7XG4gICAgdGhpcy5iaXRfc2l6ZSA9IHRoaXMucmF3X3ZhbHVlKCkucmVkdWNlKChwcmV2LCBjdXJyZW50KSA9PiBwcmV2ICsgY3VycmVudC5zaXplKTtcbiAgICB0aGlzLmJ5dGVfc2l6ZSA9IHRoaXMuYml0X3NpemUgLyA4ICsgKHRoaXMuYml0X3NpemUgJSA4ID4gMCA/IDEgOiAwKTtcbiAgfVxuXG4gIGdldChpbmRleCkge1xuICAgIHJldHVybiB0aGlzLnZhbHVlW2luZGV4XTtcbiAgfVxuXG4gIGNvdW50KCkge1xuICAgIHJldHVybiB0aGlzLnZhbHVlLmxlbmd0aDtcbiAgfVxuXG4gIFtTeW1ib2wuaXRlcmF0b3JdKCkge1xuICAgIHJldHVybiB0aGlzLnZhbHVlW1N5bWJvbC5pdGVyYXRvcl0oKTtcbiAgfVxuXG4gIHRvU3RyaW5nKCkge1xuICAgIHZhciBpLFxuICAgICAgICBzID0gXCJcIjtcbiAgICBmb3IgKGkgPSAwOyBpIDwgdGhpcy5jb3VudCgpOyBpKyspIHtcbiAgICAgIGlmIChzICE9PSBcIlwiKSB7XG4gICAgICAgIHMgKz0gXCIsIFwiO1xuICAgICAgfVxuICAgICAgcyArPSB0aGlzW2ldLnRvU3RyaW5nKCk7XG4gICAgfVxuXG4gICAgcmV0dXJuIFwiPDxcIiArIHMgKyBcIj4+XCI7XG4gIH1cblxuICBwcm9jZXNzKCkge1xuICAgIGxldCBwcm9jZXNzZWRfdmFsdWVzID0gW107XG5cbiAgICB2YXIgaTtcbiAgICBmb3IgKGkgPSAwOyBpIDwgdGhpcy5yYXdfdmFsdWUoKS5sZW5ndGg7IGkrKykge1xuICAgICAgbGV0IHByb2Nlc3NlZF92YWx1ZSA9IHRoaXNbXCJwcm9jZXNzX1wiICsgdGhpcy5yYXdfdmFsdWUoKVtpXS50eXBlXSh0aGlzLnJhd192YWx1ZSgpW2ldKTtcblxuICAgICAgZm9yIChsZXQgYXR0ciBvZiB0aGlzLnJhd192YWx1ZSgpW2ldLmF0dHJpYnV0ZXMpIHtcbiAgICAgICAgcHJvY2Vzc2VkX3ZhbHVlID0gdGhpc1tcInByb2Nlc3NfXCIgKyBhdHRyXShwcm9jZXNzZWRfdmFsdWUpO1xuICAgICAgfVxuXG4gICAgICBwcm9jZXNzZWRfdmFsdWVzID0gcHJvY2Vzc2VkX3ZhbHVlcy5jb25jYXQocHJvY2Vzc2VkX3ZhbHVlKTtcbiAgICB9XG5cbiAgICByZXR1cm4gcHJvY2Vzc2VkX3ZhbHVlcztcbiAgfVxuXG4gIHByb2Nlc3NfaW50ZWdlcih2YWx1ZSkge1xuICAgIHJldHVybiB2YWx1ZS52YWx1ZTtcbiAgfVxuXG4gIHByb2Nlc3NfZmxvYXQodmFsdWUpIHtcbiAgICBpZiAodmFsdWUuc2l6ZSA9PT0gNjQpIHtcbiAgICAgIHJldHVybiBCaXRTdHJpbmcuZmxvYXQ2NFRvQnl0ZXModmFsdWUudmFsdWUpO1xuICAgIH0gZWxzZSBpZiAodmFsdWUuc2l6ZSA9PT0gMzIpIHtcbiAgICAgIHJldHVybiBCaXRTdHJpbmcuZmxvYXQzMlRvQnl0ZXModmFsdWUudmFsdWUpO1xuICAgIH1cblxuICAgIHRocm93IG5ldyBFcnJvcihcIkludmFsaWQgc2l6ZSBmb3IgZmxvYXRcIik7XG4gIH1cblxuICBwcm9jZXNzX2JpdHN0cmluZyh2YWx1ZSkge1xuICAgIHJldHVybiB2YWx1ZS52YWx1ZS52YWx1ZTtcbiAgfVxuXG4gIHByb2Nlc3NfYmluYXJ5KHZhbHVlKSB7XG4gICAgcmV0dXJuIEJpdFN0cmluZy50b1VURjhBcnJheSh2YWx1ZS52YWx1ZSk7XG4gIH1cblxuICBwcm9jZXNzX3V0ZjgodmFsdWUpIHtcbiAgICByZXR1cm4gQml0U3RyaW5nLnRvVVRGOEFycmF5KHZhbHVlLnZhbHVlKTtcbiAgfVxuXG4gIHByb2Nlc3NfdXRmMTYodmFsdWUpIHtcbiAgICByZXR1cm4gQml0U3RyaW5nLnRvVVRGMTZBcnJheSh2YWx1ZS52YWx1ZSk7XG4gIH1cblxuICBwcm9jZXNzX3V0ZjMyKHZhbHVlKSB7XG4gICAgcmV0dXJuIEJpdFN0cmluZy50b1VURjMyQXJyYXkodmFsdWUudmFsdWUpO1xuICB9XG5cbiAgcHJvY2Vzc19zaWduZWQodmFsdWUpIHtcbiAgICByZXR1cm4gbmV3IFVpbnQ4QXJyYXkoW3ZhbHVlXSlbMF07XG4gIH1cblxuICBwcm9jZXNzX3Vuc2lnbmVkKHZhbHVlKSB7XG4gICAgcmV0dXJuIHZhbHVlO1xuICB9XG5cbiAgcHJvY2Vzc19uYXRpdmUodmFsdWUpIHtcbiAgICByZXR1cm4gdmFsdWU7XG4gIH1cblxuICBwcm9jZXNzX2JpZyh2YWx1ZSkge1xuICAgIHJldHVybiB2YWx1ZTtcbiAgfVxuXG4gIHByb2Nlc3NfbGl0dGxlKHZhbHVlKSB7XG4gICAgcmV0dXJuIHZhbHVlLnJldmVyc2UoKTtcbiAgfVxuXG4gIHByb2Nlc3Nfc2l6ZSh2YWx1ZSkge1xuICAgIHJldHVybiB2YWx1ZTtcbiAgfVxuXG4gIHByb2Nlc3NfdW5pdCh2YWx1ZSkge1xuICAgIHJldHVybiB2YWx1ZTtcbiAgfVxuXG4gIHN0YXRpYyBpbnRlZ2VyKHZhbHVlKSB7XG4gICAgcmV0dXJuIEJpdFN0cmluZy53cmFwKHZhbHVlLCB7IFwidHlwZVwiOiBcImludGVnZXJcIiwgXCJ1bml0XCI6IDEsIFwic2l6ZVwiOiA4IH0pO1xuICB9XG5cbiAgc3RhdGljIGZsb2F0KHZhbHVlKSB7XG4gICAgcmV0dXJuIEJpdFN0cmluZy53cmFwKHZhbHVlLCB7IFwidHlwZVwiOiBcImZsb2F0XCIsIFwidW5pdFwiOiAxLCBcInNpemVcIjogNjQgfSk7XG4gIH1cblxuICBzdGF0aWMgYml0c3RyaW5nKHZhbHVlKSB7XG4gICAgcmV0dXJuIEJpdFN0cmluZy53cmFwKHZhbHVlLCB7IFwidHlwZVwiOiBcImJpdHN0cmluZ1wiLCBcInVuaXRcIjogMSwgXCJzaXplXCI6IHZhbHVlLmJpdF9zaXplIH0pO1xuICB9XG5cbiAgc3RhdGljIGJpdHModmFsdWUpIHtcbiAgICByZXR1cm4gQml0U3RyaW5nLmJpdHN0cmluZyh2YWx1ZSk7XG4gIH1cblxuICBzdGF0aWMgYmluYXJ5KHZhbHVlKSB7XG4gICAgcmV0dXJuIEJpdFN0cmluZy53cmFwKHZhbHVlLCB7IFwidHlwZVwiOiBcImJpbmFyeVwiLCBcInVuaXRcIjogOCwgXCJzaXplXCI6IHZhbHVlLmxlbmd0aCB9KTtcbiAgfVxuXG4gIHN0YXRpYyBieXRlcyh2YWx1ZSkge1xuICAgIHJldHVybiBCaXRTdHJpbmcuYmluYXJ5KHZhbHVlKTtcbiAgfVxuXG4gIHN0YXRpYyB1dGY4KHZhbHVlKSB7XG4gICAgcmV0dXJuIEJpdFN0cmluZy53cmFwKHZhbHVlLCB7IFwidHlwZVwiOiBcInV0ZjhcIiB9KTtcbiAgfVxuXG4gIHN0YXRpYyB1dGYxNih2YWx1ZSkge1xuICAgIHJldHVybiBCaXRTdHJpbmcud3JhcCh2YWx1ZSwgeyBcInR5cGVcIjogXCJ1dGYxNlwiIH0pO1xuICB9XG5cbiAgc3RhdGljIHV0ZjMyKHZhbHVlKSB7XG4gICAgcmV0dXJuIEJpdFN0cmluZy53cmFwKHZhbHVlLCB7IFwidHlwZVwiOiBcInV0ZjMyXCIgfSk7XG4gIH1cblxuICBzdGF0aWMgc2lnbmVkKHZhbHVlKSB7XG4gICAgcmV0dXJuIEJpdFN0cmluZy53cmFwKHZhbHVlLCB7fSwgXCJzaWduZWRcIik7XG4gIH1cblxuICBzdGF0aWMgdW5zaWduZWQodmFsdWUpIHtcbiAgICByZXR1cm4gQml0U3RyaW5nLndyYXAodmFsdWUsIHt9LCBcInVuc2lnbmVkXCIpO1xuICB9XG5cbiAgc3RhdGljIG5hdGl2ZSh2YWx1ZSkge1xuICAgIHJldHVybiBCaXRTdHJpbmcud3JhcCh2YWx1ZSwge30sIFwibmF0aXZlXCIpO1xuICB9XG5cbiAgc3RhdGljIGJpZyh2YWx1ZSkge1xuICAgIHJldHVybiBCaXRTdHJpbmcud3JhcCh2YWx1ZSwge30sIFwiYmlnXCIpO1xuICB9XG5cbiAgc3RhdGljIGxpdHRsZSh2YWx1ZSkge1xuICAgIHJldHVybiBCaXRTdHJpbmcud3JhcCh2YWx1ZSwge30sIFwibGl0dGxlXCIpO1xuICB9XG5cbiAgc3RhdGljIHNpemUodmFsdWUsIGNvdW50KSB7XG4gICAgcmV0dXJuIEJpdFN0cmluZy53cmFwKHZhbHVlLCB7IFwic2l6ZVwiOiBjb3VudCB9KTtcbiAgfVxuXG4gIHN0YXRpYyB1bml0KHZhbHVlLCBjb3VudCkge1xuICAgIHJldHVybiBCaXRTdHJpbmcud3JhcCh2YWx1ZSwgeyBcInVuaXRcIjogY291bnQgfSk7XG4gIH1cblxuICBzdGF0aWMgd3JhcCh2YWx1ZSwgb3B0LCBuZXdfYXR0cmlidXRlID0gbnVsbCkge1xuICAgIGxldCB0aGVfdmFsdWUgPSB2YWx1ZTtcblxuICAgIGlmICghKHZhbHVlIGluc3RhbmNlb2YgT2JqZWN0KSkge1xuICAgICAgdGhlX3ZhbHVlID0geyBcInZhbHVlXCI6IHZhbHVlLCBcImF0dHJpYnV0ZXNcIjogW10gfTtcbiAgICB9XG5cbiAgICB0aGVfdmFsdWUgPSBPYmplY3QuYXNzaWduKHRoZV92YWx1ZSwgb3B0KTtcblxuICAgIGlmIChuZXdfYXR0cmlidXRlKSB7XG4gICAgICB0aGVfdmFsdWUuYXR0cmlidXRlcy5wdXNoKG5ld19hdHRyaWJ1dGUpO1xuICAgIH1cblxuICAgIHJldHVybiB0aGVfdmFsdWU7XG4gIH1cblxuICBzdGF0aWMgdG9VVEY4QXJyYXkoc3RyKSB7XG4gICAgdmFyIHV0ZjggPSBbXTtcbiAgICBmb3IgKHZhciBpID0gMDsgaSA8IHN0ci5sZW5ndGg7IGkrKykge1xuICAgICAgdmFyIGNoYXJjb2RlID0gc3RyLmNoYXJDb2RlQXQoaSk7XG4gICAgICBpZiAoY2hhcmNvZGUgPCAxMjgpIHtcbiAgICAgICAgdXRmOC5wdXNoKGNoYXJjb2RlKTtcbiAgICAgIH0gZWxzZSBpZiAoY2hhcmNvZGUgPCAyMDQ4KSB7XG4gICAgICAgIHV0ZjgucHVzaCgxOTIgfCBjaGFyY29kZSA+PiA2LCAxMjggfCBjaGFyY29kZSAmIDYzKTtcbiAgICAgIH0gZWxzZSBpZiAoY2hhcmNvZGUgPCA1NTI5NiB8fCBjaGFyY29kZSA+PSA1NzM0NCkge1xuICAgICAgICB1dGY4LnB1c2goMjI0IHwgY2hhcmNvZGUgPj4gMTIsIDEyOCB8IGNoYXJjb2RlID4+IDYgJiA2MywgMTI4IHwgY2hhcmNvZGUgJiA2Myk7XG4gICAgICB9XG4gICAgICAvLyBzdXJyb2dhdGUgcGFpclxuICAgICAgZWxzZSB7XG4gICAgICAgIGkrKztcbiAgICAgICAgLy8gVVRGLTE2IGVuY29kZXMgMHgxMDAwMC0weDEwRkZGRiBieVxuICAgICAgICAvLyBzdWJ0cmFjdGluZyAweDEwMDAwIGFuZCBzcGxpdHRpbmcgdGhlXG4gICAgICAgIC8vIDIwIGJpdHMgb2YgMHgwLTB4RkZGRkYgaW50byB0d28gaGFsdmVzXG4gICAgICAgIGNoYXJjb2RlID0gNjU1MzYgKyAoKGNoYXJjb2RlICYgMTAyMykgPDwgMTAgfCBzdHIuY2hhckNvZGVBdChpKSAmIDEwMjMpO1xuICAgICAgICB1dGY4LnB1c2goMjQwIHwgY2hhcmNvZGUgPj4gMTgsIDEyOCB8IGNoYXJjb2RlID4+IDEyICYgNjMsIDEyOCB8IGNoYXJjb2RlID4+IDYgJiA2MywgMTI4IHwgY2hhcmNvZGUgJiA2Myk7XG4gICAgICB9XG4gICAgfVxuICAgIHJldHVybiB1dGY4O1xuICB9XG5cbiAgc3RhdGljIHRvVVRGMTZBcnJheShzdHIpIHtcbiAgICB2YXIgdXRmMTYgPSBbXTtcbiAgICBmb3IgKHZhciBpID0gMDsgaSA8IHN0ci5sZW5ndGg7IGkrKykge1xuICAgICAgdmFyIGNvZGVQb2ludCA9IHN0ci5jb2RlUG9pbnRBdChpKTtcblxuICAgICAgaWYgKGNvZGVQb2ludCA8PSAyNTUpIHtcbiAgICAgICAgdXRmMTYucHVzaCgwKTtcbiAgICAgICAgdXRmMTYucHVzaChjb2RlUG9pbnQpO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgdXRmMTYucHVzaChjb2RlUG9pbnQgPj4gOCAmIDI1NSk7XG4gICAgICAgIHV0ZjE2LnB1c2goY29kZVBvaW50ICYgMjU1KTtcbiAgICAgIH1cbiAgICB9XG4gICAgcmV0dXJuIHV0ZjE2O1xuICB9XG5cbiAgc3RhdGljIHRvVVRGMzJBcnJheShzdHIpIHtcbiAgICB2YXIgdXRmMzIgPSBbXTtcbiAgICBmb3IgKHZhciBpID0gMDsgaSA8IHN0ci5sZW5ndGg7IGkrKykge1xuICAgICAgdmFyIGNvZGVQb2ludCA9IHN0ci5jb2RlUG9pbnRBdChpKTtcblxuICAgICAgaWYgKGNvZGVQb2ludCA8PSAyNTUpIHtcbiAgICAgICAgdXRmMzIucHVzaCgwKTtcbiAgICAgICAgdXRmMzIucHVzaCgwKTtcbiAgICAgICAgdXRmMzIucHVzaCgwKTtcbiAgICAgICAgdXRmMzIucHVzaChjb2RlUG9pbnQpO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgdXRmMzIucHVzaCgwKTtcbiAgICAgICAgdXRmMzIucHVzaCgwKTtcbiAgICAgICAgdXRmMzIucHVzaChjb2RlUG9pbnQgPj4gOCAmIDI1NSk7XG4gICAgICAgIHV0ZjMyLnB1c2goY29kZVBvaW50ICYgMjU1KTtcbiAgICAgIH1cbiAgICB9XG4gICAgcmV0dXJuIHV0ZjMyO1xuICB9XG5cbiAgLy9odHRwOi8vc3RhY2tvdmVyZmxvdy5jb20vcXVlc3Rpb25zLzIwMDM0OTMvamF2YXNjcmlwdC1mbG9hdC1mcm9tLXRvLWJpdHNcbiAgc3RhdGljIGZsb2F0MzJUb0J5dGVzKGYpIHtcbiAgICB2YXIgYnl0ZXMgPSBbXTtcblxuICAgIHZhciBidWYgPSBuZXcgQXJyYXlCdWZmZXIoNCk7XG4gICAgbmV3IEZsb2F0MzJBcnJheShidWYpWzBdID0gZjtcblxuICAgIGxldCBpbnRWZXJzaW9uID0gbmV3IFVpbnQzMkFycmF5KGJ1ZilbMF07XG5cbiAgICBieXRlcy5wdXNoKGludFZlcnNpb24gPj4gMjQgJiAyNTUpO1xuICAgIGJ5dGVzLnB1c2goaW50VmVyc2lvbiA+PiAxNiAmIDI1NSk7XG4gICAgYnl0ZXMucHVzaChpbnRWZXJzaW9uID4+IDggJiAyNTUpO1xuICAgIGJ5dGVzLnB1c2goaW50VmVyc2lvbiAmIDI1NSk7XG5cbiAgICByZXR1cm4gYnl0ZXM7XG4gIH1cblxuICBzdGF0aWMgZmxvYXQ2NFRvQnl0ZXMoZikge1xuICAgIHZhciBieXRlcyA9IFtdO1xuXG4gICAgdmFyIGJ1ZiA9IG5ldyBBcnJheUJ1ZmZlcig4KTtcbiAgICBuZXcgRmxvYXQ2NEFycmF5KGJ1ZilbMF0gPSBmO1xuXG4gICAgdmFyIGludFZlcnNpb24xID0gbmV3IFVpbnQzMkFycmF5KGJ1ZilbMF07XG4gICAgdmFyIGludFZlcnNpb24yID0gbmV3IFVpbnQzMkFycmF5KGJ1ZilbMV07XG5cbiAgICBieXRlcy5wdXNoKGludFZlcnNpb24yID4+IDI0ICYgMjU1KTtcbiAgICBieXRlcy5wdXNoKGludFZlcnNpb24yID4+IDE2ICYgMjU1KTtcbiAgICBieXRlcy5wdXNoKGludFZlcnNpb24yID4+IDggJiAyNTUpO1xuICAgIGJ5dGVzLnB1c2goaW50VmVyc2lvbjIgJiAyNTUpO1xuXG4gICAgYnl0ZXMucHVzaChpbnRWZXJzaW9uMSA+PiAyNCAmIDI1NSk7XG4gICAgYnl0ZXMucHVzaChpbnRWZXJzaW9uMSA+PiAxNiAmIDI1NSk7XG4gICAgYnl0ZXMucHVzaChpbnRWZXJzaW9uMSA+PiA4ICYgMjU1KTtcbiAgICBieXRlcy5wdXNoKGludFZlcnNpb24xICYgMjU1KTtcblxuICAgIHJldHVybiBieXRlcztcbiAgfVxufVxuXG4vKiBAZmxvdyAqL1xuXG5jbGFzcyBWYXJpYWJsZSB7XG5cbiAgY29uc3RydWN0b3IobmFtZSA9IG51bGwpIHtcbiAgICB0aGlzLm5hbWUgPSBuYW1lO1xuICB9XG59XG5cbmNsYXNzIFdpbGRjYXJkIHtcbiAgY29uc3RydWN0b3IoKSB7fVxufVxuXG5jbGFzcyBTdGFydHNXaXRoIHtcblxuICBjb25zdHJ1Y3RvcihwcmVmaXgpIHtcbiAgICB0aGlzLnByZWZpeCA9IHByZWZpeDtcbiAgfVxufVxuXG5jbGFzcyBDYXB0dXJlIHtcblxuICBjb25zdHJ1Y3Rvcih2YWx1ZSkge1xuICAgIHRoaXMudmFsdWUgPSB2YWx1ZTtcbiAgfVxufVxuXG5jbGFzcyBIZWFkVGFpbCB7XG5cbiAgY29uc3RydWN0b3IoaGVhZCA9IG51bGwsIHRhaWwgPSBudWxsKSB7XG4gICAgdGhpcy5oZWFkID0gaGVhZDtcbiAgICB0aGlzLnRhaWwgPSB0YWlsO1xuICB9XG59XG5cbmNsYXNzIFR5cGUge1xuXG4gIGNvbnN0cnVjdG9yKHR5cGUsIG9ialBhdHRlcm4gPSB7fSkge1xuICAgIHRoaXMudHlwZSA9IHR5cGU7XG4gICAgdGhpcy5vYmpQYXR0ZXJuID0gb2JqUGF0dGVybjtcbiAgfVxufVxuXG5jbGFzcyBCb3VuZCB7XG5cbiAgY29uc3RydWN0b3IodmFsdWUpIHtcbiAgICB0aGlzLnZhbHVlID0gdmFsdWU7XG4gIH1cbn1cblxuZnVuY3Rpb24gdmFyaWFibGUobmFtZSA9IG51bGwpIHtcbiAgcmV0dXJuIG5ldyBWYXJpYWJsZShuYW1lKTtcbn1cblxuZnVuY3Rpb24gd2lsZGNhcmQoKSB7XG4gIHJldHVybiBuZXcgV2lsZGNhcmQoKTtcbn1cblxuZnVuY3Rpb24gc3RhcnRzV2l0aChwcmVmaXgpIHtcbiAgcmV0dXJuIG5ldyBTdGFydHNXaXRoKHByZWZpeCk7XG59XG5cbmZ1bmN0aW9uIGNhcHR1cmUodmFsdWUpIHtcbiAgcmV0dXJuIG5ldyBDYXB0dXJlKHZhbHVlKTtcbn1cblxuZnVuY3Rpb24gaGVhZFRhaWwoaGVhZCA9IG51bGwsIHRhaWwgPSBudWxsKSB7XG4gIHJldHVybiBuZXcgSGVhZFRhaWwoaGVhZCwgdGFpbCk7XG59XG5cbmZ1bmN0aW9uIHR5cGUodHlwZSwgb2JqUGF0dGVybiA9IHt9KSB7XG4gIHJldHVybiBuZXcgVHlwZSh0eXBlLCBvYmpQYXR0ZXJuKTtcbn1cblxuZnVuY3Rpb24gYm91bmQodmFsdWUpIHtcbiAgcmV0dXJuIG5ldyBCb3VuZCh2YWx1ZSk7XG59XG5cbmZ1bmN0aW9uIGlzX251bWJlcih2YWx1ZSkge1xuICByZXR1cm4gdHlwZW9mIHZhbHVlID09PSAnbnVtYmVyJztcbn1cblxuZnVuY3Rpb24gaXNfc3RyaW5nKHZhbHVlKSB7XG4gIHJldHVybiB0eXBlb2YgdmFsdWUgPT09ICdzdHJpbmcnO1xufVxuXG5mdW5jdGlvbiBpc19ib29sZWFuKHZhbHVlKSB7XG4gIHJldHVybiB0eXBlb2YgdmFsdWUgPT09ICdib29sZWFuJztcbn1cblxuZnVuY3Rpb24gaXNfc3ltYm9sKHZhbHVlKSB7XG4gIHJldHVybiB0eXBlb2YgdmFsdWUgPT09ICdzeW1ib2wnO1xufVxuXG5mdW5jdGlvbiBpc19udWxsKHZhbHVlKSB7XG4gIHJldHVybiB2YWx1ZSA9PT0gbnVsbDtcbn1cblxuZnVuY3Rpb24gaXNfdW5kZWZpbmVkKHZhbHVlKSB7XG4gIHJldHVybiB0eXBlb2YgdmFsdWUgPT09ICd1bmRlZmluZWQnO1xufVxuXG5mdW5jdGlvbiBpc19mdW5jdGlvbih2YWx1ZSkge1xuICByZXR1cm4gT2JqZWN0LnByb3RvdHlwZS50b1N0cmluZy5jYWxsKHZhbHVlKSA9PSAnW29iamVjdCBGdW5jdGlvbl0nO1xufVxuXG5mdW5jdGlvbiBpc192YXJpYWJsZSh2YWx1ZSkge1xuICByZXR1cm4gdmFsdWUgaW5zdGFuY2VvZiBWYXJpYWJsZTtcbn1cblxuZnVuY3Rpb24gaXNfd2lsZGNhcmQodmFsdWUpIHtcbiAgcmV0dXJuIHZhbHVlIGluc3RhbmNlb2YgV2lsZGNhcmQ7XG59XG5cbmZ1bmN0aW9uIGlzX2hlYWRUYWlsKHZhbHVlKSB7XG4gIHJldHVybiB2YWx1ZSBpbnN0YW5jZW9mIEhlYWRUYWlsO1xufVxuXG5mdW5jdGlvbiBpc19jYXB0dXJlKHZhbHVlKSB7XG4gIHJldHVybiB2YWx1ZSBpbnN0YW5jZW9mIENhcHR1cmU7XG59XG5cbmZ1bmN0aW9uIGlzX3R5cGUodmFsdWUpIHtcbiAgcmV0dXJuIHZhbHVlIGluc3RhbmNlb2YgVHlwZTtcbn1cblxuZnVuY3Rpb24gaXNfc3RhcnRzV2l0aCh2YWx1ZSkge1xuICByZXR1cm4gdmFsdWUgaW5zdGFuY2VvZiBTdGFydHNXaXRoO1xufVxuXG5mdW5jdGlvbiBpc19ib3VuZCh2YWx1ZSkge1xuICByZXR1cm4gdmFsdWUgaW5zdGFuY2VvZiBCb3VuZDtcbn1cblxuZnVuY3Rpb24gaXNfb2JqZWN0KHZhbHVlKSB7XG4gIHJldHVybiB0eXBlb2YgdmFsdWUgPT09ICdvYmplY3QnO1xufVxuXG5mdW5jdGlvbiBpc19hcnJheSh2YWx1ZSkge1xuICByZXR1cm4gQXJyYXkuaXNBcnJheSh2YWx1ZSk7XG59XG5cbnZhciBDaGVja3MgPSB7XG4gIGlzX251bWJlcixcbiAgaXNfc3RyaW5nLFxuICBpc19ib29sZWFuLFxuICBpc19zeW1ib2wsXG4gIGlzX251bGwsXG4gIGlzX3VuZGVmaW5lZCxcbiAgaXNfZnVuY3Rpb24sXG4gIGlzX3ZhcmlhYmxlLFxuICBpc193aWxkY2FyZCxcbiAgaXNfaGVhZFRhaWwsXG4gIGlzX2NhcHR1cmUsXG4gIGlzX3R5cGUsXG4gIGlzX3N0YXJ0c1dpdGgsXG4gIGlzX2JvdW5kLFxuICBpc19vYmplY3QsXG4gIGlzX2FycmF5XG59O1xuXG5mdW5jdGlvbiByZXNvbHZlU3ltYm9sKHBhdHRlcm4pIHtcbiAgcmV0dXJuIGZ1bmN0aW9uICh2YWx1ZSkge1xuICAgIHJldHVybiBDaGVja3MuaXNfc3ltYm9sKHZhbHVlKSAmJiB2YWx1ZSA9PT0gcGF0dGVybjtcbiAgfTtcbn1cblxuZnVuY3Rpb24gcmVzb2x2ZVN0cmluZyhwYXR0ZXJuKSB7XG4gIHJldHVybiBmdW5jdGlvbiAodmFsdWUpIHtcbiAgICByZXR1cm4gQ2hlY2tzLmlzX3N0cmluZyh2YWx1ZSkgJiYgdmFsdWUgPT09IHBhdHRlcm47XG4gIH07XG59XG5cbmZ1bmN0aW9uIHJlc29sdmVOdW1iZXIocGF0dGVybikge1xuICByZXR1cm4gZnVuY3Rpb24gKHZhbHVlKSB7XG4gICAgcmV0dXJuIENoZWNrcy5pc19udW1iZXIodmFsdWUpICYmIHZhbHVlID09PSBwYXR0ZXJuO1xuICB9O1xufVxuXG5mdW5jdGlvbiByZXNvbHZlQm9vbGVhbihwYXR0ZXJuKSB7XG4gIHJldHVybiBmdW5jdGlvbiAodmFsdWUpIHtcbiAgICByZXR1cm4gQ2hlY2tzLmlzX2Jvb2xlYW4odmFsdWUpICYmIHZhbHVlID09PSBwYXR0ZXJuO1xuICB9O1xufVxuXG5mdW5jdGlvbiByZXNvbHZlRnVuY3Rpb24ocGF0dGVybikge1xuICByZXR1cm4gZnVuY3Rpb24gKHZhbHVlKSB7XG4gICAgcmV0dXJuIENoZWNrcy5pc19mdW5jdGlvbih2YWx1ZSkgJiYgdmFsdWUgPT09IHBhdHRlcm47XG4gIH07XG59XG5cbmZ1bmN0aW9uIHJlc29sdmVOdWxsKHBhdHRlcm4pIHtcbiAgcmV0dXJuIGZ1bmN0aW9uICh2YWx1ZSkge1xuICAgIHJldHVybiBDaGVja3MuaXNfbnVsbCh2YWx1ZSk7XG4gIH07XG59XG5cbmZ1bmN0aW9uIHJlc29sdmVCb3VuZChwYXR0ZXJuKSB7XG4gIHJldHVybiBmdW5jdGlvbiAodmFsdWUsIGFyZ3MpIHtcbiAgICBpZiAodHlwZW9mIHZhbHVlID09PSB0eXBlb2YgcGF0dGVybi52YWx1ZSAmJiB2YWx1ZSA9PT0gcGF0dGVybi52YWx1ZSkge1xuICAgICAgYXJncy5wdXNoKHZhbHVlKTtcbiAgICAgIHJldHVybiB0cnVlO1xuICAgIH1cblxuICAgIHJldHVybiBmYWxzZTtcbiAgfTtcbn1cblxuZnVuY3Rpb24gcmVzb2x2ZVdpbGRjYXJkKCkge1xuICByZXR1cm4gZnVuY3Rpb24gKCkge1xuICAgIHJldHVybiB0cnVlO1xuICB9O1xufVxuXG5mdW5jdGlvbiByZXNvbHZlVmFyaWFibGUoKSB7XG4gIHJldHVybiBmdW5jdGlvbiAodmFsdWUsIGFyZ3MpIHtcbiAgICBhcmdzLnB1c2godmFsdWUpO1xuICAgIHJldHVybiB0cnVlO1xuICB9O1xufVxuXG5mdW5jdGlvbiByZXNvbHZlSGVhZFRhaWwocGF0dGVybikge1xuICBjb25zdCBoZWFkTWF0Y2hlcyA9IGJ1aWxkTWF0Y2gocGF0dGVybi5oZWFkKTtcbiAgY29uc3QgdGFpbE1hdGNoZXMgPSBidWlsZE1hdGNoKHBhdHRlcm4udGFpbCk7XG5cbiAgcmV0dXJuIGZ1bmN0aW9uICh2YWx1ZSwgYXJncykge1xuICAgIGlmICghQ2hlY2tzLmlzX2FycmF5KHZhbHVlKSB8fCB2YWx1ZS5sZW5ndGggPCAyKSB7XG4gICAgICByZXR1cm4gZmFsc2U7XG4gICAgfVxuXG4gICAgY29uc3QgaGVhZCA9IHZhbHVlWzBdO1xuICAgIGNvbnN0IHRhaWwgPSB2YWx1ZS5zbGljZSgxKTtcblxuICAgIGlmIChoZWFkTWF0Y2hlcyhoZWFkLCBhcmdzKSAmJiB0YWlsTWF0Y2hlcyh0YWlsLCBhcmdzKSkge1xuICAgICAgcmV0dXJuIHRydWU7XG4gICAgfVxuICB9O1xufVxuXG5mdW5jdGlvbiByZXNvbHZlQ2FwdHVyZShwYXR0ZXJuKSB7XG4gIGNvbnN0IG1hdGNoZXMgPSBidWlsZE1hdGNoKHBhdHRlcm4udmFsdWUpO1xuXG4gIHJldHVybiBmdW5jdGlvbiAodmFsdWUsIGFyZ3MpIHtcbiAgICBpZiAobWF0Y2hlcyh2YWx1ZSwgYXJncykpIHtcbiAgICAgIGFyZ3MucHVzaCh2YWx1ZSk7XG4gICAgICByZXR1cm4gdHJ1ZTtcbiAgICB9XG5cbiAgICByZXR1cm4gZmFsc2U7XG4gIH07XG59XG5cbmZ1bmN0aW9uIHJlc29sdmVTdGFydHNXaXRoKHBhdHRlcm4pIHtcbiAgY29uc3QgcHJlZml4ID0gcGF0dGVybi5wcmVmaXg7XG5cbiAgcmV0dXJuIGZ1bmN0aW9uICh2YWx1ZSwgYXJncykge1xuICAgIGlmIChDaGVja3MuaXNfc3RyaW5nKHZhbHVlKSAmJiB2YWx1ZS5zdGFydHNXaXRoKHByZWZpeCkpIHtcbiAgICAgIGFyZ3MucHVzaCh2YWx1ZS5zdWJzdHJpbmcocHJlZml4Lmxlbmd0aCkpO1xuICAgICAgcmV0dXJuIHRydWU7XG4gICAgfVxuXG4gICAgcmV0dXJuIGZhbHNlO1xuICB9O1xufVxuXG5mdW5jdGlvbiByZXNvbHZlVHlwZShwYXR0ZXJuKSB7XG4gIHJldHVybiBmdW5jdGlvbiAodmFsdWUsIGFyZ3MpIHtcbiAgICBpZiAodmFsdWUgaW5zdGFuY2VvZiBwYXR0ZXJuLnR5cGUpIHtcbiAgICAgIGNvbnN0IG1hdGNoZXMgPSBidWlsZE1hdGNoKHBhdHRlcm4ub2JqUGF0dGVybik7XG4gICAgICByZXR1cm4gbWF0Y2hlcyh2YWx1ZSwgYXJncykgJiYgYXJncy5wdXNoKHZhbHVlKSA+IDA7XG4gICAgfVxuXG4gICAgcmV0dXJuIGZhbHNlO1xuICB9O1xufVxuXG5mdW5jdGlvbiByZXNvbHZlQXJyYXkocGF0dGVybikge1xuICBjb25zdCBtYXRjaGVzID0gcGF0dGVybi5tYXAoeCA9PiBidWlsZE1hdGNoKHgpKTtcblxuICByZXR1cm4gZnVuY3Rpb24gKHZhbHVlLCBhcmdzKSB7XG4gICAgaWYgKCFDaGVja3MuaXNfYXJyYXkodmFsdWUpIHx8IHZhbHVlLmxlbmd0aCAhPSBwYXR0ZXJuLmxlbmd0aCkge1xuICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH1cblxuICAgIHJldHVybiB2YWx1ZS5ldmVyeShmdW5jdGlvbiAodiwgaSkge1xuICAgICAgcmV0dXJuIG1hdGNoZXNbaV0odmFsdWVbaV0sIGFyZ3MpO1xuICAgIH0pO1xuICB9O1xufVxuXG5mdW5jdGlvbiByZXNvbHZlT2JqZWN0KHBhdHRlcm4pIHtcbiAgbGV0IG1hdGNoZXMgPSB7fTtcblxuICBmb3IgKGxldCBrZXkgb2YgT2JqZWN0LmtleXMocGF0dGVybikuY29uY2F0KE9iamVjdC5nZXRPd25Qcm9wZXJ0eVN5bWJvbHMocGF0dGVybikpKSB7XG4gICAgbWF0Y2hlc1trZXldID0gYnVpbGRNYXRjaChwYXR0ZXJuW2tleV0pO1xuICB9XG5cbiAgcmV0dXJuIGZ1bmN0aW9uICh2YWx1ZSwgYXJncykge1xuICAgIGlmICghQ2hlY2tzLmlzX29iamVjdCh2YWx1ZSkgfHwgcGF0dGVybi5sZW5ndGggPiB2YWx1ZS5sZW5ndGgpIHtcbiAgICAgIHJldHVybiBmYWxzZTtcbiAgICB9XG5cbiAgICBmb3IgKGxldCBrZXkgb2YgT2JqZWN0LmtleXMocGF0dGVybikuY29uY2F0KE9iamVjdC5nZXRPd25Qcm9wZXJ0eVN5bWJvbHMocGF0dGVybikpKSB7XG4gICAgICBpZiAoIShrZXkgaW4gdmFsdWUpIHx8ICFtYXRjaGVzW2tleV0odmFsdWVba2V5XSwgYXJncykpIHtcbiAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgfVxuICAgIH1cblxuICAgIHJldHVybiB0cnVlO1xuICB9O1xufVxuXG5mdW5jdGlvbiByZXNvbHZlTm9NYXRjaCgpIHtcbiAgcmV0dXJuIGZ1bmN0aW9uICgpIHtcbiAgICByZXR1cm4gZmFsc2U7XG4gIH07XG59XG5cbnZhciBSZXNvbHZlcnMgPSB7XG4gIHJlc29sdmVCb3VuZCxcbiAgcmVzb2x2ZVdpbGRjYXJkLFxuICByZXNvbHZlVmFyaWFibGUsXG4gIHJlc29sdmVIZWFkVGFpbCxcbiAgcmVzb2x2ZUNhcHR1cmUsXG4gIHJlc29sdmVTdGFydHNXaXRoLFxuICByZXNvbHZlVHlwZSxcbiAgcmVzb2x2ZUFycmF5LFxuICByZXNvbHZlT2JqZWN0LFxuICByZXNvbHZlTm9NYXRjaCxcbiAgcmVzb2x2ZVN5bWJvbCxcbiAgcmVzb2x2ZVN0cmluZyxcbiAgcmVzb2x2ZU51bWJlcixcbiAgcmVzb2x2ZUJvb2xlYW4sXG4gIHJlc29sdmVGdW5jdGlvbixcbiAgcmVzb2x2ZU51bGxcbn07XG5cbmZ1bmN0aW9uIGJ1aWxkTWF0Y2gocGF0dGVybikge1xuXG4gIGlmIChDaGVja3MuaXNfdmFyaWFibGUocGF0dGVybikpIHtcbiAgICByZXR1cm4gUmVzb2x2ZXJzLnJlc29sdmVWYXJpYWJsZShwYXR0ZXJuKTtcbiAgfVxuXG4gIGlmIChDaGVja3MuaXNfd2lsZGNhcmQocGF0dGVybikpIHtcbiAgICByZXR1cm4gUmVzb2x2ZXJzLnJlc29sdmVXaWxkY2FyZChwYXR0ZXJuKTtcbiAgfVxuXG4gIGlmIChDaGVja3MuaXNfdW5kZWZpbmVkKHBhdHRlcm4pKSB7XG4gICAgcmV0dXJuIFJlc29sdmVycy5yZXNvbHZlV2lsZGNhcmQocGF0dGVybik7XG4gIH1cblxuICBpZiAoQ2hlY2tzLmlzX2hlYWRUYWlsKHBhdHRlcm4pKSB7XG4gICAgcmV0dXJuIFJlc29sdmVycy5yZXNvbHZlSGVhZFRhaWwocGF0dGVybik7XG4gIH1cblxuICBpZiAoQ2hlY2tzLmlzX3N0YXJ0c1dpdGgocGF0dGVybikpIHtcbiAgICByZXR1cm4gUmVzb2x2ZXJzLnJlc29sdmVTdGFydHNXaXRoKHBhdHRlcm4pO1xuICB9XG5cbiAgaWYgKENoZWNrcy5pc19jYXB0dXJlKHBhdHRlcm4pKSB7XG4gICAgcmV0dXJuIFJlc29sdmVycy5yZXNvbHZlQ2FwdHVyZShwYXR0ZXJuKTtcbiAgfVxuXG4gIGlmIChDaGVja3MuaXNfYm91bmQocGF0dGVybikpIHtcbiAgICByZXR1cm4gUmVzb2x2ZXJzLnJlc29sdmVCb3VuZChwYXR0ZXJuKTtcbiAgfVxuXG4gIGlmIChDaGVja3MuaXNfdHlwZShwYXR0ZXJuKSkge1xuICAgIHJldHVybiBSZXNvbHZlcnMucmVzb2x2ZVR5cGUocGF0dGVybik7XG4gIH1cblxuICBpZiAoQ2hlY2tzLmlzX2FycmF5KHBhdHRlcm4pKSB7XG4gICAgcmV0dXJuIFJlc29sdmVycy5yZXNvbHZlQXJyYXkocGF0dGVybik7XG4gIH1cblxuICBpZiAoQ2hlY2tzLmlzX251bWJlcihwYXR0ZXJuKSkge1xuICAgIHJldHVybiBSZXNvbHZlcnMucmVzb2x2ZU51bWJlcihwYXR0ZXJuKTtcbiAgfVxuXG4gIGlmIChDaGVja3MuaXNfc3RyaW5nKHBhdHRlcm4pKSB7XG4gICAgcmV0dXJuIFJlc29sdmVycy5yZXNvbHZlU3RyaW5nKHBhdHRlcm4pO1xuICB9XG5cbiAgaWYgKENoZWNrcy5pc19ib29sZWFuKHBhdHRlcm4pKSB7XG4gICAgcmV0dXJuIFJlc29sdmVycy5yZXNvbHZlQm9vbGVhbihwYXR0ZXJuKTtcbiAgfVxuXG4gIGlmIChDaGVja3MuaXNfc3ltYm9sKHBhdHRlcm4pKSB7XG4gICAgcmV0dXJuIFJlc29sdmVycy5yZXNvbHZlU3ltYm9sKHBhdHRlcm4pO1xuICB9XG5cbiAgaWYgKENoZWNrcy5pc19udWxsKHBhdHRlcm4pKSB7XG4gICAgcmV0dXJuIFJlc29sdmVycy5yZXNvbHZlTnVsbChwYXR0ZXJuKTtcbiAgfVxuXG4gIGlmIChDaGVja3MuaXNfb2JqZWN0KHBhdHRlcm4pKSB7XG4gICAgcmV0dXJuIFJlc29sdmVycy5yZXNvbHZlT2JqZWN0KHBhdHRlcm4pO1xuICB9XG5cbiAgcmV0dXJuIFJlc29sdmVycy5yZXNvbHZlTm9NYXRjaCgpO1xufVxuXG5jbGFzcyBNYXRjaEVycm9yIGV4dGVuZHMgRXJyb3Ige1xuICBjb25zdHJ1Y3RvcihhcmcpIHtcbiAgICBzdXBlcigpO1xuXG4gICAgaWYgKHR5cGVvZiBhcmcgPT09ICdzeW1ib2wnKSB7XG4gICAgICB0aGlzLm1lc3NhZ2UgPSAnTm8gbWF0Y2ggZm9yOiAnICsgYXJnLnRvU3RyaW5nKCk7XG4gICAgfSBlbHNlIGlmIChBcnJheS5pc0FycmF5KGFyZykpIHtcbiAgICAgIGxldCBtYXBwZWRWYWx1ZXMgPSBhcmcubWFwKHggPT4geC50b1N0cmluZygpKTtcbiAgICAgIHRoaXMubWVzc2FnZSA9ICdObyBtYXRjaCBmb3I6ICcgKyBtYXBwZWRWYWx1ZXM7XG4gICAgfSBlbHNlIHtcbiAgICAgIHRoaXMubWVzc2FnZSA9ICdObyBtYXRjaCBmb3I6ICcgKyBhcmc7XG4gICAgfVxuXG4gICAgdGhpcy5zdGFjayA9IG5ldyBFcnJvcigpLnN0YWNrO1xuICAgIHRoaXMubmFtZSA9IHRoaXMuY29uc3RydWN0b3IubmFtZTtcbiAgfVxufVxuXG5jbGFzcyBDYXNlIHtcblxuICBjb25zdHJ1Y3RvcihwYXR0ZXJuLCBmbiwgZ3VhcmQgPSAoKSA9PiB0cnVlKSB7XG4gICAgdGhpcy5wYXR0ZXJuID0gYnVpbGRNYXRjaChwYXR0ZXJuKTtcbiAgICB0aGlzLmZuID0gZm47XG4gICAgdGhpcy5ndWFyZCA9IGd1YXJkO1xuICB9XG59XG5cbmZ1bmN0aW9uIG1ha2VfY2FzZShwYXR0ZXJuLCBmbiwgZ3VhcmQgPSAoKSA9PiB0cnVlKSB7XG4gIHJldHVybiBuZXcgQ2FzZShwYXR0ZXJuLCBmbiwgZ3VhcmQpO1xufVxuXG5mdW5jdGlvbiBkZWZtYXRjaCguLi5jYXNlcykge1xuICByZXR1cm4gZnVuY3Rpb24gKC4uLmFyZ3MpIHtcbiAgICBmb3IgKGxldCBwcm9jZXNzZWRDYXNlIG9mIGNhc2VzKSB7XG4gICAgICBsZXQgcmVzdWx0ID0gW107XG4gICAgICBpZiAocHJvY2Vzc2VkQ2FzZS5wYXR0ZXJuKGFyZ3MsIHJlc3VsdCkgJiYgcHJvY2Vzc2VkQ2FzZS5ndWFyZC5hcHBseSh0aGlzLCByZXN1bHQpKSB7XG4gICAgICAgIHJldHVybiBwcm9jZXNzZWRDYXNlLmZuLmFwcGx5KHRoaXMsIHJlc3VsdCk7XG4gICAgICB9XG4gICAgfVxuXG4gICAgdGhyb3cgbmV3IE1hdGNoRXJyb3IoYXJncyk7XG4gIH07XG59XG5cbmZ1bmN0aW9uIG1hdGNoKHBhdHRlcm4sIGV4cHIsIGd1YXJkID0gKCkgPT4gdHJ1ZSkge1xuICBsZXQgcmVzdWx0ID0gW107XG4gIGxldCBwcm9jZXNzZWRQYXR0ZXJuID0gYnVpbGRNYXRjaChwYXR0ZXJuKTtcbiAgaWYgKHByb2Nlc3NlZFBhdHRlcm4oZXhwciwgcmVzdWx0KSAmJiBndWFyZC5hcHBseSh0aGlzLCByZXN1bHQpKSB7XG4gICAgcmV0dXJuIHJlc3VsdDtcbiAgfSBlbHNlIHtcbiAgICB0aHJvdyBuZXcgTWF0Y2hFcnJvcihleHByKTtcbiAgfVxufVxuXG5mdW5jdGlvbiBtYXRjaF9ub190aHJvdyhwYXR0ZXJuLCBleHByLCBndWFyZCA9ICgpID0+IHRydWUpIHtcbiAgdHJ5IHtcbiAgICByZXR1cm4gbWF0Y2gocGF0dGVybiwgZXhwciwgZ3VhcmQpO1xuICB9IGNhdGNoIChlKSB7XG4gICAgaWYgKGUgaW5zdGFuY2VvZiBNYXRjaEVycm9yKSB7XG4gICAgICByZXR1cm4gbnVsbDtcbiAgICB9XG5cbiAgICB0aHJvdyBlO1xuICB9XG59XG5cbnZhciBQYXR0ZXJucyA9IHtcbiAgZGVmbWF0Y2gsIG1hdGNoLCBNYXRjaEVycm9yLCBtYXRjaF9ub190aHJvdyxcbiAgdmFyaWFibGUsIHdpbGRjYXJkLCBzdGFydHNXaXRoLFxuICBjYXB0dXJlLCBoZWFkVGFpbCwgdHlwZSwgYm91bmQsIENhc2UsIG1ha2VfY2FzZVxufTtcblxuLy9odHRwczovL2dpdGh1Yi5jb20vYWlycG9ydHloL3Byb3RvbW9ycGhpc21cbmNsYXNzIFByb3RvY29sIHtcbiAgY29uc3RydWN0b3Ioc3BlYykge1xuICAgIHRoaXMucmVnaXN0cnkgPSBuZXcgTWFwKCk7XG4gICAgdGhpcy5mYWxsYmFjayA9IG51bGw7XG5cbiAgICBmb3IgKGxldCBmdW5OYW1lIGluIHNwZWMpIHtcbiAgICAgIHRoaXNbZnVuTmFtZV0gPSBjcmVhdGVGdW4oZnVuTmFtZSkuYmluZCh0aGlzKTtcbiAgICB9XG5cbiAgICBmdW5jdGlvbiBjcmVhdGVGdW4oZnVuTmFtZSkge1xuXG4gICAgICByZXR1cm4gZnVuY3Rpb24gKC4uLmFyZ3MpIHtcbiAgICAgICAgbGV0IHRoaW5nID0gYXJnc1swXTtcbiAgICAgICAgbGV0IGZ1biA9IG51bGw7XG5cbiAgICAgICAgaWYgKE51bWJlci5pc0ludGVnZXIodGhpbmcpICYmIHRoaXMuaGFzSW1wbGVtZW50YXRpb24oSW50ZWdlcikpIHtcbiAgICAgICAgICBmdW4gPSB0aGlzLnJlZ2lzdHJ5LmdldChJbnRlZ2VyKVtmdW5OYW1lXTtcbiAgICAgICAgfSBlbHNlIGlmICh0eXBlb2YgdGhpbmcgPT09IFwibnVtYmVyXCIgJiYgIU51bWJlci5pc0ludGVnZXIodGhpbmcpICYmIHRoaXMuaGFzSW1wbGVtZW50YXRpb24oRmxvYXQpKSB7XG4gICAgICAgICAgZnVuID0gdGhpcy5yZWdpc3RyeS5nZXQoRmxvYXQpW2Z1bk5hbWVdO1xuICAgICAgICB9IGVsc2UgaWYgKHRoaXMuaGFzSW1wbGVtZW50YXRpb24odGhpbmcpKSB7XG4gICAgICAgICAgZnVuID0gdGhpcy5yZWdpc3RyeS5nZXQodGhpbmcuY29uc3RydWN0b3IpW2Z1bk5hbWVdO1xuICAgICAgICB9IGVsc2UgaWYgKHRoaXMuZmFsbGJhY2spIHtcbiAgICAgICAgICBmdW4gPSB0aGlzLmZhbGxiYWNrW2Z1bk5hbWVdO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKGZ1biAhPSBudWxsKSB7XG4gICAgICAgICAgbGV0IHJldHZhbCA9IGZ1bi5hcHBseSh0aGlzLCBhcmdzKTtcbiAgICAgICAgICByZXR1cm4gcmV0dmFsO1xuICAgICAgICB9XG5cbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKFwiTm8gaW1wbGVtZW50YXRpb24gZm91bmQgZm9yIFwiICsgdGhpbmcpO1xuICAgICAgfTtcbiAgICB9XG4gIH1cblxuICBpbXBsZW1lbnRhdGlvbih0eXBlLCBpbXBsZW1lbnRhdGlvbikge1xuICAgIGlmICh0eXBlID09PSBudWxsKSB7XG4gICAgICB0aGlzLmZhbGxiYWNrID0gaW1wbGVtZW50YXRpb247XG4gICAgfSBlbHNlIHtcbiAgICAgIHRoaXMucmVnaXN0cnkuc2V0KHR5cGUsIGltcGxlbWVudGF0aW9uKTtcbiAgICB9XG4gIH1cblxuICBoYXNJbXBsZW1lbnRhdGlvbih0aGluZykge1xuICAgIHJldHVybiB0aGlzLnJlZ2lzdHJ5Lmhhcyh0aGluZy5jb25zdHJ1Y3Rvcik7XG4gIH1cbn1cblxuZnVuY3Rpb24gY2FsbF9wcm9wZXJ0eShpdGVtLCBwcm9wZXJ0eSkge1xuICBsZXQgcHJvcCA9IG51bGw7XG5cbiAgaWYgKHByb3BlcnR5IGluIGl0ZW0pIHtcbiAgICBwcm9wID0gcHJvcGVydHk7XG4gIH0gZWxzZSBpZiAoU3ltYm9sLmZvcihwcm9wZXJ0eSkgaW4gaXRlbSkge1xuICAgIHByb3AgPSBTeW1ib2wuZm9yKHByb3BlcnR5KTtcbiAgfSBlbHNlIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoYFByb3BlcnR5ICR7IHByb3BlcnR5IH0gbm90IGZvdW5kIGluICR7IGl0ZW0gfWApO1xuICB9XG5cbiAgaWYgKGl0ZW1bcHJvcF0gaW5zdGFuY2VvZiBGdW5jdGlvbikge1xuICAgIHJldHVybiBpdGVtW3Byb3BdKCk7XG4gIH0gZWxzZSB7XG4gICAgcmV0dXJuIGl0ZW1bcHJvcF07XG4gIH1cbn1cblxuZnVuY3Rpb24gYXBwbHkoLi4uYXJncykge1xuICBpZiAoYXJncy5sZW5ndGggPT09IDIpIHtcbiAgICBhcmdzWzBdLmFwcGx5KG51bGwsIGFyZ3Muc2xpY2UoMSkpO1xuICB9IGVsc2Uge1xuICAgIGFyZ3NbMF1bYXJnc1sxXV0uYXBwbHkobnVsbCwgYXJncy5zbGljZSgyKSk7XG4gIH1cbn1cblxuZnVuY3Rpb24gY29udGFpbnMobGVmdCwgcmlnaHQpIHtcbiAgZm9yIChsZXQgeCBvZiByaWdodCkge1xuICAgIGlmIChQYXR0ZXJucy5tYXRjaF9ub190aHJvdyhsZWZ0LCB4KSAhPSBudWxsKSB7XG4gICAgICByZXR1cm4gdHJ1ZTtcbiAgICB9XG4gIH1cblxuICByZXR1cm4gZmFsc2U7XG59XG5cbmZ1bmN0aW9uIGdldF9nbG9iYWwoKSB7XG4gIGlmICh0eXBlb2Ygc2VsZiAhPT0gJ3VuZGVmaW5lZCcpIHtcbiAgICByZXR1cm4gc2VsZjtcbiAgfSBlbHNlIGlmICh0eXBlb2Ygd2luZG93ICE9PSAndW5kZWZpbmVkJykge1xuICAgIHJldHVybiB3aW5kb3c7XG4gIH0gZWxzZSBpZiAodHlwZW9mIGdsb2JhbCAhPT0gJ3VuZGVmaW5lZCcpIHtcbiAgICByZXR1cm4gZ2xvYmFsO1xuICB9XG5cbiAgdGhyb3cgbmV3IEVycm9yKCdObyBnbG9iYWwgc3RhdGUgZm91bmQnKTtcbn1cblxuZnVuY3Rpb24gZGVmc3RydWN0KGRlZmF1bHRzKSB7XG4gIHJldHVybiBjbGFzcyB7XG4gICAgY29uc3RydWN0b3IodXBkYXRlID0ge30pIHtcbiAgICAgIGxldCB0aGVfdmFsdWVzID0gT2JqZWN0LmFzc2lnbihkZWZhdWx0cywgdXBkYXRlKTtcbiAgICAgIE9iamVjdC5hc3NpZ24odGhpcywgdGhlX3ZhbHVlcyk7XG4gICAgfVxuXG4gICAgc3RhdGljIGNyZWF0ZSh1cGRhdGVzID0ge30pIHtcbiAgICAgIGxldCB4ID0gbmV3IHRoaXModXBkYXRlcyk7XG4gICAgICByZXR1cm4gT2JqZWN0LmZyZWV6ZSh4KTtcbiAgICB9XG4gIH07XG59XG5cbmZ1bmN0aW9uIGRlZmV4Y2VwdGlvbihkZWZhdWx0cykge1xuICByZXR1cm4gY2xhc3MgZXh0ZW5kcyBFcnJvciB7XG4gICAgY29uc3RydWN0b3IodXBkYXRlID0ge30pIHtcbiAgICAgIGxldCBtZXNzYWdlID0gdXBkYXRlLm1lc3NhZ2UgfHwgJyc7XG4gICAgICBzdXBlcihtZXNzYWdlKTtcblxuICAgICAgbGV0IHRoZV92YWx1ZXMgPSBPYmplY3QuYXNzaWduKGRlZmF1bHRzLCB1cGRhdGUpO1xuICAgICAgT2JqZWN0LmFzc2lnbih0aGlzLCB0aGVfdmFsdWVzKTtcblxuICAgICAgdGhpcy5uYW1lID0gdGhpcy5jb25zdHJ1Y3Rvci5uYW1lO1xuICAgICAgdGhpcy5tZXNzYWdlID0gbWVzc2FnZTtcbiAgICAgIHRoaXNbU3BlY2lhbEZvcm1zLmF0b20oJ19fZXhjZXB0aW9uX18nKV0gPSB0cnVlO1xuICAgICAgRXJyb3IuY2FwdHVyZVN0YWNrVHJhY2UodGhpcywgdGhpcy5jb25zdHJ1Y3Rvci5uYW1lKTtcbiAgICB9XG5cbiAgICBzdGF0aWMgY3JlYXRlKHVwZGF0ZXMgPSB7fSkge1xuICAgICAgbGV0IHggPSBuZXcgdGhpcyh1cGRhdGVzKTtcbiAgICAgIHJldHVybiBPYmplY3QuZnJlZXplKHgpO1xuICAgIH1cbiAgfTtcbn1cblxuZnVuY3Rpb24gZGVmcHJvdG9jb2woc3BlYykge1xuICByZXR1cm4gbmV3IFByb3RvY29sKHNwZWMpO1xufVxuXG5mdW5jdGlvbiBkZWZpbXBsKHByb3RvY29sLCB0eXBlLCBpbXBsKSB7XG4gIHByb3RvY29sLmltcGxlbWVudGF0aW9uKHR5cGUsIGltcGwpO1xufVxuXG5mdW5jdGlvbiBnZXRfb2JqZWN0X2tleXMob2JqKSB7XG4gIHJldHVybiBPYmplY3Qua2V5cyhvYmopLmNvbmNhdChPYmplY3QuZ2V0T3duUHJvcGVydHlTeW1ib2xzKG9iaikpO1xufVxuXG5mdW5jdGlvbiBpc192YWxpZF9jaGFyYWN0ZXIoY29kZXBvaW50KSB7XG4gIHRyeSB7XG4gICAgcmV0dXJuIFN0cmluZy5mcm9tQ29kZVBvaW50KGNvZGVwb2ludCkgIT0gbnVsbDtcbiAgfSBjYXRjaCAoZSkge1xuICAgIHJldHVybiBmYWxzZTtcbiAgfVxufVxuXG4vL2h0dHBzOi8vZGV2ZWxvcGVyLm1vemlsbGEub3JnL2VuLVVTL2RvY3MvV2ViL0FQSS9XaW5kb3dCYXNlNjQvQmFzZTY0X2VuY29kaW5nX2FuZF9kZWNvZGluZyNTb2x1dGlvbl8yXyVFMiU4MCU5M19yZXdyaXRlX3RoZV9ET01zX2F0b2IoKV9hbmRfYnRvYSgpX3VzaW5nX0phdmFTY3JpcHQnc19UeXBlZEFycmF5c19hbmRfVVRGLThcbmZ1bmN0aW9uIGI2NEVuY29kZVVuaWNvZGUoc3RyKSB7XG4gIHJldHVybiBidG9hKGVuY29kZVVSSUNvbXBvbmVudChzdHIpLnJlcGxhY2UoLyUoWzAtOUEtRl17Mn0pL2csIGZ1bmN0aW9uIChtYXRjaCwgcDEpIHtcbiAgICByZXR1cm4gU3RyaW5nLmZyb21DaGFyQ29kZSgnMHgnICsgcDEpO1xuICB9KSk7XG59XG5cbmZ1bmN0aW9uIGRlbGV0ZV9wcm9wZXJ0eV9mcm9tX21hcChtYXAsIHByb3BlcnR5KSB7XG4gIGxldCBuZXdfbWFwID0gT2JqZWN0LmFzc2lnbihPYmplY3QuY3JlYXRlKG1hcC5jb25zdHJ1Y3Rvci5wcm90b3R5cGUpLCBtYXApO1xuICBkZWxldGUgbmV3X21hcFtwcm9wZXJ0eV07XG5cbiAgcmV0dXJuIE9iamVjdC5mcmVlemUobmV3X21hcCk7XG59XG5cbmZ1bmN0aW9uIGNsYXNzX3RvX29iaihtYXApIHtcbiAgbGV0IG5ld19tYXAgPSBPYmplY3QuYXNzaWduKHt9LCBtYXApO1xuICByZXR1cm4gT2JqZWN0LmZyZWV6ZShuZXdfbWFwKTtcbn1cblxuZnVuY3Rpb24gYWRkX3Byb3BlcnR5X3RvX21hcChtYXAsIHByb3BlcnR5LCB2YWx1ZSkge1xuICBsZXQgbmV3X21hcCA9IE9iamVjdC5hc3NpZ24oe30sIG1hcCk7XG4gIG5ld19tYXBbcHJvcGVydHldID0gdmFsdWU7XG4gIHJldHVybiBPYmplY3QuZnJlZXplKG5ld19tYXApO1xufVxuXG5mdW5jdGlvbiB1cGRhdGVfbWFwKG1hcCwgcHJvcGVydHksIHZhbHVlKSB7XG4gIGlmIChwcm9wZXJ0eSBpbiBnZXRfb2JqZWN0X2tleXMobWFwKSkge1xuICAgIHJldHVybiBhZGRfcHJvcGVydHlfdG9fbWFwKG1hcCwgcHJvcGVydHksIHZhbHVlKTtcbiAgfVxuXG4gIHRocm93ICdtYXAgZG9lcyBub3QgaGF2ZSBrZXknO1xufVxuXG5mdW5jdGlvbiBibm90KGV4cHIpIHtcbiAgcmV0dXJuIH5leHByO1xufVxuXG5mdW5jdGlvbiBiYW5kKGxlZnQsIHJpZ2h0KSB7XG4gIHJldHVybiBsZWZ0ICYgcmlnaHQ7XG59XG5cbmZ1bmN0aW9uIGJvcihsZWZ0LCByaWdodCkge1xuICByZXR1cm4gbGVmdCB8IHJpZ2h0O1xufVxuXG5mdW5jdGlvbiBic2wobGVmdCwgcmlnaHQpIHtcbiAgcmV0dXJuIGxlZnQgPDwgcmlnaHQ7XG59XG5cbmZ1bmN0aW9uIGJzcihsZWZ0LCByaWdodCkge1xuICByZXR1cm4gbGVmdCA+PiByaWdodDtcbn1cblxuZnVuY3Rpb24gYnhvcihsZWZ0LCByaWdodCkge1xuICByZXR1cm4gbGVmdCBeIHJpZ2h0O1xufVxuXG5mdW5jdGlvbiB6aXAobGlzdF9vZl9saXN0cykge1xuICBpZiAobGlzdF9vZl9saXN0cy5sZW5ndGggPT09IDApIHtcbiAgICByZXR1cm4gT2JqZWN0LmZyZWV6ZShbXSk7XG4gIH1cblxuICBsZXQgbmV3X3ZhbHVlID0gW107XG4gIGxldCBzbWFsbGVzdF9sZW5ndGggPSBsaXN0X29mX2xpc3RzWzBdO1xuXG4gIGZvciAobGV0IHggb2YgbGlzdF9vZl9saXN0cykge1xuICAgIGlmICh4Lmxlbmd0aCA8IHNtYWxsZXN0X2xlbmd0aCkge1xuICAgICAgc21hbGxlc3RfbGVuZ3RoID0geC5sZW5ndGg7XG4gICAgfVxuICB9XG5cbiAgZm9yIChsZXQgaSA9IDA7IGkgPCBzbWFsbGVzdF9sZW5ndGg7IGkrKykge1xuICAgIGxldCBjdXJyZW50X3ZhbHVlID0gW107XG4gICAgZm9yIChsZXQgaiA9IDA7IGogPCBsaXN0X29mX2xpc3RzLmxlbmd0aDsgaisrKSB7XG4gICAgICBjdXJyZW50X3ZhbHVlLnB1c2gobGlzdF9vZl9saXN0c1tqXVtpXSk7XG4gICAgfVxuXG4gICAgbmV3X3ZhbHVlLnB1c2gobmV3IFR1cGxlKC4uLmN1cnJlbnRfdmFsdWUpKTtcbiAgfVxuXG4gIHJldHVybiBPYmplY3QuZnJlZXplKG5ld192YWx1ZSk7XG59XG5cbmZ1bmN0aW9uIGNhbl9kZWNvZGU2NChkYXRhKSB7XG4gIHRyeSB7XG4gICAgYXRvYihkYXRhKTtcbiAgICByZXR1cm4gdHJ1ZTtcbiAgfSBjYXRjaCAoZSkge1xuICAgIHJldHVybiBmYWxzZTtcbiAgfVxufVxuXG5mdW5jdGlvbiByZW1vdmVfZnJvbV9saXN0KGxpc3QsIGVsZW1lbnQpIHtcbiAgbGV0IGZvdW5kID0gZmFsc2U7XG5cbiAgcmV0dXJuIGxpc3QuZmlsdGVyKGVsZW0gPT4ge1xuICAgIGlmICghZm91bmQgJiYgZWxlbSA9PT0gZWxlbWVudCkge1xuICAgICAgZm91bmQgPSB0cnVlO1xuICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH1cblxuICAgIHJldHVybiB0cnVlO1xuICB9KTtcbn1cblxuZnVuY3Rpb24gZm9sZGwoZnVuLCBhY2MsIGxpc3QpIHtcbiAgbGV0IGFjYzEgPSBhY2M7XG5cbiAgZm9yIChjb25zdCBlbCBvZiBsaXN0KSB7XG4gICAgYWNjMSA9IGZ1bihlbCwgYWNjMSk7XG4gIH1cblxuICByZXR1cm4gYWNjMTtcbn1cblxuZnVuY3Rpb24gZm9sZHIoZnVuLCBhY2MsIGxpc3QpIHtcbiAgbGV0IGFjYzEgPSBhY2M7XG5cbiAgZm9yIChsZXQgaSA9IGxpc3QubGVuZ3RoIC0gMTsgaSA+PSAwOyBpLS0pIHtcbiAgICBhY2MxID0gZnVuKGxpc3RbaV0sIGFjYzEpO1xuICB9XG5cbiAgcmV0dXJuIGFjYzE7XG59XG5cbmZ1bmN0aW9uIGtleWZpbmQoa2V5LCBuLCB0dXBsZWxpc3QpIHtcblxuICBmb3IgKGxldCBpID0gdHVwbGVsaXN0Lmxlbmd0aCAtIDE7IGkgPj0gMDsgaS0tKSB7XG4gICAgaWYgKHR1cGxlbGlzdFtpXS5nZXQobikgPT09IGtleSkge1xuICAgICAgcmV0dXJuIHR1cGxlbGlzdFtpXTtcbiAgICB9XG4gIH1cblxuICByZXR1cm4gZmFsc2U7XG59XG5cbmZ1bmN0aW9uIGtleWRlbGV0ZShrZXksIG4sIHR1cGxlbGlzdCkge1xuXG4gIGZvciAobGV0IGkgPSB0dXBsZWxpc3QubGVuZ3RoIC0gMTsgaSA+PSAwOyBpLS0pIHtcbiAgICBpZiAodHVwbGVsaXN0W2ldLmdldChuKSA9PT0ga2V5KSB7XG4gICAgICByZXR1cm4gdHVwbGVsaXN0LmNvbmNhdChbXSkuc3BsaWNlKGksIDEpO1xuICAgIH1cbiAgfVxuXG4gIHJldHVybiB0dXBsZWxpc3Q7XG59XG5cbmZ1bmN0aW9uIGtleXN0b3JlKGtleSwgbiwgbGlzdCwgbmV3dHVwbGUpIHtcbiAgZm9yIChsZXQgaSA9IGxpc3QubGVuZ3RoIC0gMTsgaSA+PSAwOyBpLS0pIHtcbiAgICBpZiAobGlzdFtpXS5nZXQobikgPT09IGtleSkge1xuICAgICAgcmV0dXJuIGxpc3QuY29uY2F0KFtdKS5zcGxpY2UoaSwgMSwgbmV3dHVwbGUpO1xuICAgIH1cbiAgfVxuXG4gIHJldHVybiBsaXN0LmNvbmNhdChbXSkucHVzaChuZXd0dXBsZSk7XG59XG5cbmZ1bmN0aW9uIGtleW1lbWJlcihrZXksIG4sIGxpc3QpIHtcbiAgZm9yIChsZXQgaSA9IGxpc3QubGVuZ3RoIC0gMTsgaSA+PSAwOyBpLS0pIHtcbiAgICBpZiAobGlzdFtpXS5nZXQobikgPT09IGtleSkge1xuICAgICAgcmV0dXJuIHRydWU7XG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIGZhbHNlO1xufVxuXG5mdW5jdGlvbiBrZXl0YWtlKGtleSwgbiwgbGlzdCkge1xuICBpZiAoIWtleW1lbWJlcihrZXksIG4sIGxpc3QpKSB7XG4gICAgcmV0dXJuIGZhbHNlO1xuICB9XG5cbiAgbGV0IHR1cGxlID0ga2V5ZmluZChrZXksIG4sIGxpc3QpO1xuXG4gIHJldHVybiBuZXcgVHVwbGUodHVwbGUuZ2V0KG4pLCB0dXBsZSwga2V5ZGVsZXRlKGtleSwgbiwgbGlzdCkpO1xufVxuXG5mdW5jdGlvbiBrZXlyZXBsYWNlKGtleSwgbiwgbGlzdCwgbmV3dHVwbGUpIHtcblxuICBmb3IgKGxldCBpID0gdHVwbGVsaXN0Lmxlbmd0aCAtIDE7IGkgPj0gMDsgaS0tKSB7XG4gICAgaWYgKHR1cGxlbGlzdFtpXS5nZXQobikgPT09IGtleSkge1xuICAgICAgcmV0dXJuIHR1cGxlbGlzdC5jb25jYXQoW10pLnNwbGljZShpLCAxLCBuZXd0dXBsZSk7XG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIHR1cGxlbGlzdDtcbn1cblxuZnVuY3Rpb24gcmV2ZXJzZShsaXN0KSB7XG4gIHJldHVybiBsaXN0LmNvbmNhdChbXSkucmV2ZXJzZSgpO1xufVxuXG5mdW5jdGlvbiBtYXBzX2ZpbmQoa2V5LCBtYXApIHtcbiAgaWYgKGtleSBpbiBnZXRfb2JqZWN0X2tleXMobWFwKSkge1xuICAgIHJldHVybiBuZXcgVHVwbGUoU3ltYm9sLmZvcignb2snKSwgbWFwW2tleV0pO1xuICB9IGVsc2Uge1xuICAgIHJldHVybiBTeW1ib2wuZm9yKCdlcnJvcicpO1xuICB9XG59XG5cbmZ1bmN0aW9uIGZsYXR0ZW4obGlzdCwgdGFpbCA9IFtdKSB7XG4gIGxldCBuZXdfbGlzdCA9IFtdO1xuXG4gIGZvciAobGV0IGUgb2YgbGlzdCkge1xuICAgIGlmIChpc0FycmF5KGUpKSB7XG4gICAgICBuZXdfbGlzdCA9IG5ld19saXN0LmNvbmNhdChmbGF0dGVuKGUpKTtcbiAgICB9IGVsc2Uge1xuICAgICAgbmV3X2xpc3QucHVzaChlKTtcbiAgICB9XG4gIH1cblxuICByZXR1cm4gT2JqZWN0LmZyZWV6ZShuZXdfbGlzdC5jb25jYXQodGFpbCkpO1xufVxuXG5mdW5jdGlvbiBkdXBsaWNhdGUobiwgZWxlbSkge1xuICBsZXQgbGlzdCA9IFtdO1xuXG4gIGZvciAobGV0IGkgPSAwOyBpIDwgbjsgaSsrKSB7XG4gICAgbGlzdC5wdXNoKGVsZW0pO1xuICB9XG5cbiAgcmV0dXJuIE9iamVjdC5mcmVlemUobGlzdCk7XG59XG5cbmZ1bmN0aW9uIG1hcGZvbGRsKGZ1biwgYWNjLCBsaXN0KSB7XG4gIGxldCBuZXdsaXN0ID0gW107XG5cbiAgZm9yIChsZXQgeCBvZiBsaXN0KSB7XG4gICAgbGV0IHR1cCA9IGZ1bih4LCBhY2MpO1xuICAgIG5ld2xpc3QucHVzaCh0dXAuZ2V0KDApKTtcbiAgICBhY2MgPSB0dXAuZ2V0KDEpO1xuICB9XG5cbiAgcmV0dXJuIG5ldyBUdXBsZShPYmplY3QuZnJlZXplKG5ld2xpc3QpLCBhY2MpO1xufVxuXG5mdW5jdGlvbiBmaWx0ZXJtYXAoZnVuLCBsaXN0KSB7XG4gIGxldCBuZXdsaXN0ID0gW107XG5cbiAgZm9yICh4IG9mIGxpc3QpIHtcbiAgICBsZXQgcmVzdWx0ID0gZnVuKHgpO1xuXG4gICAgaWYgKHJlc3VsdCA9PT0gdHJ1ZSkge1xuICAgICAgbmV3bGlzdC5wdXNoKHgpO1xuICAgIH0gZWxzZSBpZiAocmVzdWx0IGluc3RhbmNlb2YgVHVwbGUpIHtcbiAgICAgIG5ld2xpc3QucHVzaChyZXN1bHQuZ2V0KDEpKTtcbiAgICB9XG4gIH1cblxuICByZXR1cm4gT2JqZWN0LmZyZWV6ZShuZXdsaXN0KTtcbn1cblxuZnVuY3Rpb24gbWFwc19mb2xkKGZ1biwgYWNjLCBtYXApIHtcbiAgbGV0IGFjYzEgPSBhY2M7XG5cbiAgZm9yIChsZXQgayBvZiBnZXRfb2JqZWN0X2tleXMobWFwKSkge1xuICAgIGFjYzEgPSBmdW4oaywgbWFwW2tdLCBhY2MxKTtcbiAgfVxuXG4gIHJldHVybiBhY2MxO1xufVxuXG52YXIgRnVuY3Rpb25zID0ge1xuICBjYWxsX3Byb3BlcnR5LFxuICBhcHBseSxcbiAgY29udGFpbnMsXG4gIGdldF9nbG9iYWwsXG4gIGRlZnN0cnVjdCxcbiAgZGVmZXhjZXB0aW9uLFxuICBkZWZwcm90b2NvbCxcbiAgZGVmaW1wbCxcbiAgZ2V0X29iamVjdF9rZXlzLFxuICBpc192YWxpZF9jaGFyYWN0ZXIsXG4gIGI2NEVuY29kZVVuaWNvZGUsXG4gIGRlbGV0ZV9wcm9wZXJ0eV9mcm9tX21hcCxcbiAgYWRkX3Byb3BlcnR5X3RvX21hcCxcbiAgY2xhc3NfdG9fb2JqLFxuICBjYW5fZGVjb2RlNjQsXG4gIGJub3QsXG4gIGJhbmQsXG4gIGJvcixcbiAgYnNsLFxuICBic3IsXG4gIGJ4b3IsXG4gIHppcCxcbiAgZm9sZGwsXG4gIGZvbGRyLFxuICByZW1vdmVfZnJvbV9saXN0LFxuICBrZXlkZWxldGUsXG4gIGtleXN0b3JlLFxuICBrZXlmaW5kLFxuICBrZXl0YWtlLFxuICBrZXlyZXBsYWNlLFxuICByZXZlcnNlLFxuICB1cGRhdGVfbWFwLFxuICBtYXBzX2ZpbmQsXG4gIGZsYXR0ZW4sXG4gIGR1cGxpY2F0ZSxcbiAgbWFwZm9sZGwsXG4gIGZpbHRlcm1hcCxcbiAgbWFwc19mb2xkXG59O1xuXG5mdW5jdGlvbiBfY2FzZShjb25kaXRpb24sIGNsYXVzZXMpIHtcbiAgcmV0dXJuIFBhdHRlcm5zLmRlZm1hdGNoKC4uLmNsYXVzZXMpKGNvbmRpdGlvbik7XG59XG5cbmZ1bmN0aW9uIGNvbmQoY2xhdXNlcykge1xuICBmb3IgKGxldCBjbGF1c2Ugb2YgY2xhdXNlcykge1xuICAgIGlmIChjbGF1c2VbMF0pIHtcbiAgICAgIHJldHVybiBjbGF1c2VbMV0oKTtcbiAgICB9XG4gIH1cblxuICB0aHJvdyBuZXcgRXJyb3IoKTtcbn1cblxuZnVuY3Rpb24gbWFwX3VwZGF0ZShtYXAsIHZhbHVlcykge1xuICByZXR1cm4gT2JqZWN0LmZyZWV6ZShPYmplY3QuYXNzaWduKE9iamVjdC5jcmVhdGUobWFwLmNvbnN0cnVjdG9yLnByb3RvdHlwZSksIG1hcCwgdmFsdWVzKSk7XG59XG5cbmZ1bmN0aW9uIF9mb3IoY29sbGVjdGlvbnMsIGZ1biwgZmlsdGVyID0gKCkgPT4gdHJ1ZSwgaW50byA9IFtdLCBwcmV2aW91c1ZhbHVlcyA9IFtdKSB7XG4gIGxldCBwYXR0ZXJuID0gY29sbGVjdGlvbnNbMF1bMF07XG4gIGxldCBjb2xsZWN0aW9uID0gY29sbGVjdGlvbnNbMF1bMV07XG5cbiAgaWYgKGNvbGxlY3Rpb25zLmxlbmd0aCA9PT0gMSkge1xuXG4gICAgZm9yIChsZXQgZWxlbSBvZiBjb2xsZWN0aW9uKSB7XG4gICAgICBsZXQgciA9IFBhdHRlcm5zLm1hdGNoX25vX3Rocm93KHBhdHRlcm4sIGVsZW0pO1xuICAgICAgbGV0IGFyZ3MgPSBwcmV2aW91c1ZhbHVlcy5jb25jYXQocik7XG5cbiAgICAgIGlmIChyICYmIGZpbHRlci5hcHBseSh0aGlzLCBhcmdzKSkge1xuICAgICAgICBpbnRvID0gaW50by5jb25jYXQoW2Z1bi5hcHBseSh0aGlzLCBhcmdzKV0pO1xuICAgICAgfVxuICAgIH1cblxuICAgIHJldHVybiBpbnRvO1xuICB9IGVsc2Uge1xuICAgIGxldCBfaW50byA9IFtdO1xuXG4gICAgZm9yIChsZXQgZWxlbSBvZiBjb2xsZWN0aW9uKSB7XG4gICAgICBsZXQgciA9IFBhdHRlcm5zLm1hdGNoX25vX3Rocm93KHBhdHRlcm4sIGVsZW0pO1xuICAgICAgaWYgKHIpIHtcbiAgICAgICAgX2ludG8gPSBpbnRvLmNvbmNhdCh0aGlzLl9mb3IoY29sbGVjdGlvbnMuc2xpY2UoMSksIGZ1biwgZmlsdGVyLCBfaW50bywgcHJldmlvdXNWYWx1ZXMuY29uY2F0KHIpKSk7XG4gICAgICB9XG4gICAgfVxuXG4gICAgcmV0dXJuIF9pbnRvO1xuICB9XG59XG5cbmZ1bmN0aW9uIF90cnkoZG9fZnVuLCByZXNjdWVfZnVuY3Rpb24sIGNhdGNoX2Z1biwgZWxzZV9mdW5jdGlvbiwgYWZ0ZXJfZnVuY3Rpb24pIHtcbiAgbGV0IHJlc3VsdCA9IG51bGw7XG5cbiAgdHJ5IHtcbiAgICByZXN1bHQgPSBkb19mdW4oKTtcbiAgfSBjYXRjaCAoZSkge1xuICAgIGxldCBleF9yZXN1bHQgPSBudWxsO1xuXG4gICAgaWYgKHJlc2N1ZV9mdW5jdGlvbikge1xuICAgICAgdHJ5IHtcbiAgICAgICAgZXhfcmVzdWx0ID0gcmVzY3VlX2Z1bmN0aW9uKGUpO1xuICAgICAgICByZXR1cm4gZXhfcmVzdWx0O1xuICAgICAgfSBjYXRjaCAoZXgpIHtcbiAgICAgICAgaWYgKGV4IGluc3RhbmNlb2YgUGF0dGVybnMuTWF0Y2hFcnJvcikge1xuICAgICAgICAgIHRocm93IGV4O1xuICAgICAgICB9XG4gICAgICB9XG4gICAgfVxuXG4gICAgaWYgKGNhdGNoX2Z1bikge1xuICAgICAgdHJ5IHtcbiAgICAgICAgZXhfcmVzdWx0ID0gY2F0Y2hfZnVuKGUpO1xuICAgICAgICByZXR1cm4gZXhfcmVzdWx0O1xuICAgICAgfSBjYXRjaCAoZXgpIHtcbiAgICAgICAgaWYgKGV4IGluc3RhbmNlb2YgUGF0dGVybnMuTWF0Y2hFcnJvcikge1xuICAgICAgICAgIHRocm93IGV4O1xuICAgICAgICB9XG4gICAgICB9XG4gICAgfVxuXG4gICAgdGhyb3cgZTtcbiAgfSBmaW5hbGx5IHtcbiAgICBpZiAoYWZ0ZXJfZnVuY3Rpb24pIHtcbiAgICAgIGFmdGVyX2Z1bmN0aW9uKCk7XG4gICAgfVxuICB9XG5cbiAgaWYgKGVsc2VfZnVuY3Rpb24pIHtcbiAgICB0cnkge1xuICAgICAgcmV0dXJuIGVsc2VfZnVuY3Rpb24ocmVzdWx0KTtcbiAgICB9IGNhdGNoIChleCkge1xuICAgICAgaWYgKGV4IGluc3RhbmNlb2YgUGF0dGVybnMuTWF0Y2hFcnJvcikge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ05vIE1hdGNoIEZvdW5kIGluIEVsc2UnKTtcbiAgICAgIH1cblxuICAgICAgdGhyb3cgZXg7XG4gICAgfVxuICB9IGVsc2Uge1xuICAgIHJldHVybiByZXN1bHQ7XG4gIH1cbn1cblxudmFyIFNwZWNpYWxGb3JtcyQxID0ge1xuICBfY2FzZSxcbiAgY29uZCxcbiAgbWFwX3VwZGF0ZSxcbiAgX2ZvcixcbiAgX3RyeVxufTtcblxuRnVuY3Rpb25zLmdldF9nbG9iYWwoKS5wcm9jZXNzZXMgPSBGdW5jdGlvbnMuZ2V0X2dsb2JhbCgpLnByb2Nlc3NlcyB8fCBuZXcgUHJvY2Vzc1N5c3RlbSgpO1xuXG52YXIgQ29yZSA9IHtcbiAgUHJvY2Vzc1N5c3RlbSxcbiAgVHVwbGUsXG4gIFBJRCxcbiAgQml0U3RyaW5nLFxuICBQYXR0ZXJucyxcbiAgSW50ZWdlcixcbiAgRmxvYXQsXG4gIEZ1bmN0aW9ucyxcbiAgU3BlY2lhbEZvcm1zOiBTcGVjaWFsRm9ybXMkMVxufTtcblxubGV0IEVudW0gPSB7XG5cbiAgYWxsX19xbWFya19fOiBmdW5jdGlvbiAoY29sbGVjdGlvbiwgZnVuID0geCA9PiB4KSB7XG4gICAgZm9yIChsZXQgZWxlbSBvZiBjb2xsZWN0aW9uKSB7XG4gICAgICBpZiAoIWZ1bihlbGVtKSkge1xuICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICB9XG4gICAgfVxuXG4gICAgcmV0dXJuIHRydWU7XG4gIH0sXG5cbiAgYW55X19xbWFya19fOiBmdW5jdGlvbiAoY29sbGVjdGlvbiwgZnVuID0geCA9PiB4KSB7XG4gICAgZm9yIChsZXQgZWxlbSBvZiBjb2xsZWN0aW9uKSB7XG4gICAgICBpZiAoZnVuKGVsZW0pKSB7XG4gICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgfVxuICAgIH1cblxuICAgIHJldHVybiBmYWxzZTtcbiAgfSxcblxuICBhdDogZnVuY3Rpb24gKGNvbGxlY3Rpb24sIG4sIHRoZV9kZWZhdWx0ID0gbnVsbCkge1xuICAgIGlmIChuID4gdGhpcy5jb3VudChjb2xsZWN0aW9uKSB8fCBuIDwgMCkge1xuICAgICAgcmV0dXJuIHRoZV9kZWZhdWx0O1xuICAgIH1cblxuICAgIHJldHVybiBjb2xsZWN0aW9uW25dO1xuICB9LFxuXG4gIGNvbmNhdDogZnVuY3Rpb24gKC4uLmVudW1hYmxlcykge1xuICAgIHJldHVybiBlbnVtYWJsZXNbMF0uY29uY2F0KGVudW1hYmxlc1sxXSk7XG4gIH0sXG5cbiAgY291bnQ6IGZ1bmN0aW9uIChjb2xsZWN0aW9uLCBmdW4gPSBudWxsKSB7XG4gICAgaWYgKGZ1biA9PSBudWxsKSB7XG4gICAgICByZXR1cm4gY29sbGVjdGlvbi5sZW5ndGg7XG4gICAgfSBlbHNlIHtcbiAgICAgIHJldHVybiBjb2xsZWN0aW9uLmZpbHRlcihmdW4pLmxlbmd0aDtcbiAgICB9XG4gIH0sXG5cbiAgZHJvcDogZnVuY3Rpb24gKGNvbGxlY3Rpb24sIGNvdW50KSB7XG4gICAgcmV0dXJuIGNvbGxlY3Rpb24uc2xpY2UoY291bnQpO1xuICB9LFxuXG4gIGRyb3Bfd2hpbGU6IGZ1bmN0aW9uIChjb2xsZWN0aW9uLCBmdW4pIHtcbiAgICBsZXQgY291bnQgPSAwO1xuXG4gICAgZm9yIChsZXQgZWxlbSBvZiBjb2xsZWN0aW9uKSB7XG4gICAgICBpZiAoZnVuKGVsZW0pKSB7XG4gICAgICAgIGNvdW50ID0gY291bnQgKyAxO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgYnJlYWs7XG4gICAgICB9XG4gICAgfVxuXG4gICAgcmV0dXJuIGNvbGxlY3Rpb24uc2xpY2UoY291bnQpO1xuICB9LFxuXG4gIGVhY2g6IGZ1bmN0aW9uIChjb2xsZWN0aW9uLCBmdW4pIHtcbiAgICBmb3IgKGxldCBlbGVtIG9mIGNvbGxlY3Rpb24pIHtcbiAgICAgIGZ1bihlbGVtKTtcbiAgICB9XG4gIH0sXG5cbiAgZW1wdHlfX3FtYXJrX186IGZ1bmN0aW9uIChjb2xsZWN0aW9uKSB7XG4gICAgcmV0dXJuIGNvbGxlY3Rpb24ubGVuZ3RoID09PSAwO1xuICB9LFxuXG4gIGZldGNoOiBmdW5jdGlvbiAoY29sbGVjdGlvbiwgbikge1xuICAgIGlmIChBcnJheS5pc0FycmF5KGNvbGxlY3Rpb24pKSB7XG4gICAgICBpZiAobiA8IHRoaXMuY291bnQoY29sbGVjdGlvbikgJiYgbiA+PSAwKSB7XG4gICAgICAgIHJldHVybiBuZXcgQ29yZS5UdXBsZShTeW1ib2wuZm9yKFwib2tcIiksIGNvbGxlY3Rpb25bbl0pO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgcmV0dXJuIFN5bWJvbC5mb3IoXCJlcnJvclwiKTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICB0aHJvdyBuZXcgRXJyb3IoXCJjb2xsZWN0aW9uIGlzIG5vdCBhbiBFbnVtZXJhYmxlXCIpO1xuICB9LFxuXG4gIGZldGNoX19lbWFya19fOiBmdW5jdGlvbiAoY29sbGVjdGlvbiwgbikge1xuICAgIGlmIChBcnJheS5pc0FycmF5KGNvbGxlY3Rpb24pKSB7XG4gICAgICBpZiAobiA8IHRoaXMuY291bnQoY29sbGVjdGlvbikgJiYgbiA+PSAwKSB7XG4gICAgICAgIHJldHVybiBjb2xsZWN0aW9uW25dO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKFwib3V0IG9mIGJvdW5kcyBlcnJvclwiKTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICB0aHJvdyBuZXcgRXJyb3IoXCJjb2xsZWN0aW9uIGlzIG5vdCBhbiBFbnVtZXJhYmxlXCIpO1xuICB9LFxuXG4gIGZpbHRlcjogZnVuY3Rpb24gKGNvbGxlY3Rpb24sIGZ1bikge1xuICAgIGxldCByZXN1bHQgPSBbXTtcblxuICAgIGZvciAobGV0IGVsZW0gb2YgY29sbGVjdGlvbikge1xuICAgICAgaWYgKGZ1bihlbGVtKSkge1xuICAgICAgICByZXN1bHQucHVzaChlbGVtKTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICByZXR1cm4gcmVzdWx0O1xuICB9LFxuXG4gIGZpbHRlcl9tYXA6IGZ1bmN0aW9uIChjb2xsZWN0aW9uLCBmaWx0ZXIsIG1hcHBlcikge1xuICAgIHJldHVybiBFbnVtLm1hcChFbnVtLmZpbHRlcihjb2xsZWN0aW9uLCBmaWx0ZXIpLCBtYXBwZXIpO1xuICB9LFxuXG4gIGZpbmQ6IGZ1bmN0aW9uIChjb2xsZWN0aW9uLCBpZl9ub25lID0gbnVsbCwgZnVuKSB7XG4gICAgZm9yIChsZXQgZWxlbSBvZiBjb2xsZWN0aW9uKSB7XG4gICAgICBpZiAoZnVuKGVsZW0pKSB7XG4gICAgICAgIHJldHVybiBlbGVtO1xuICAgICAgfVxuICAgIH1cblxuICAgIHJldHVybiBpZl9ub25lO1xuICB9LFxuXG4gIGludG86IGZ1bmN0aW9uIChjb2xsZWN0aW9uLCBsaXN0KSB7XG4gICAgcmV0dXJuIGxpc3QuY29uY2F0KGNvbGxlY3Rpb24pO1xuICB9LFxuXG4gIG1hcDogZnVuY3Rpb24gKGNvbGxlY3Rpb24sIGZ1bikge1xuICAgIGxldCByZXN1bHQgPSBbXTtcblxuICAgIGZvciAobGV0IGVsZW0gb2YgY29sbGVjdGlvbikge1xuICAgICAgcmVzdWx0LnB1c2goZnVuKGVsZW0pKTtcbiAgICB9XG5cbiAgICByZXR1cm4gcmVzdWx0O1xuICB9LFxuXG4gIG1hcF9yZWR1Y2U6IGZ1bmN0aW9uIChjb2xsZWN0aW9uLCBhY2MsIGZ1bikge1xuICAgIGxldCBtYXBwZWQgPSBPYmplY3QuZnJlZXplKFtdKTtcbiAgICBsZXQgdGhlX2FjYyA9IGFjYztcblxuICAgIGZvciAodmFyIGkgPSAwOyBpIDwgdGhpcy5jb3VudChjb2xsZWN0aW9uKTsgaSsrKSB7XG4gICAgICBsZXQgdHVwbGUgPSBmdW4oY29sbGVjdGlvbltpXSwgdGhlX2FjYyk7XG5cbiAgICAgIHRoZV9hY2MgPSB0dXBsZS5nZXQoMSk7XG4gICAgICBtYXBwZWQgPSBPYmplY3QuZnJlZXplKG1hcHBlZC5jb25jYXQoW3R1cGxlLmdldCgwKV0pKTtcbiAgICB9XG5cbiAgICByZXR1cm4gbmV3IENvcmUuVHVwbGUobWFwcGVkLCB0aGVfYWNjKTtcbiAgfSxcblxuICBtZW1iZXJfX3FtYXJrX186IGZ1bmN0aW9uIChjb2xsZWN0aW9uLCB2YWx1ZSkge1xuICAgIHJldHVybiBjb2xsZWN0aW9uLmluY2x1ZGVzKHZhbHVlKTtcbiAgfSxcblxuICByZWR1Y2U6IGZ1bmN0aW9uIChjb2xsZWN0aW9uLCBhY2MsIGZ1bikge1xuICAgIGxldCB0aGVfYWNjID0gYWNjO1xuXG4gICAgZm9yICh2YXIgaSA9IDA7IGkgPCB0aGlzLmNvdW50KGNvbGxlY3Rpb24pOyBpKyspIHtcbiAgICAgIGxldCB0dXBsZSA9IGZ1bihjb2xsZWN0aW9uW2ldLCB0aGVfYWNjKTtcblxuICAgICAgdGhlX2FjYyA9IHR1cGxlLmdldCgxKTtcbiAgICB9XG5cbiAgICByZXR1cm4gdGhlX2FjYztcbiAgfSxcblxuICB0YWtlOiBmdW5jdGlvbiAoY29sbGVjdGlvbiwgY291bnQpIHtcbiAgICByZXR1cm4gY29sbGVjdGlvbi5zbGljZSgwLCBjb3VudCk7XG4gIH0sXG5cbiAgdGFrZV9ldmVyeTogZnVuY3Rpb24gKGNvbGxlY3Rpb24sIG50aCkge1xuICAgIGxldCByZXN1bHQgPSBbXTtcbiAgICBsZXQgaW5kZXggPSAwO1xuXG4gICAgZm9yIChsZXQgZWxlbSBvZiBjb2xsZWN0aW9uKSB7XG4gICAgICBpZiAoaW5kZXggJSBudGggPT09IDApIHtcbiAgICAgICAgcmVzdWx0LnB1c2goZWxlbSk7XG4gICAgICB9XG4gICAgfVxuXG4gICAgcmV0dXJuIE9iamVjdC5mcmVlemUocmVzdWx0KTtcbiAgfSxcblxuICB0YWtlX3doaWxlOiBmdW5jdGlvbiAoY29sbGVjdGlvbiwgZnVuKSB7XG4gICAgbGV0IGNvdW50ID0gMDtcblxuICAgIGZvciAobGV0IGVsZW0gb2YgY29sbGVjdGlvbikge1xuICAgICAgaWYgKGZ1bihlbGVtKSkge1xuICAgICAgICBjb3VudCA9IGNvdW50ICsgMTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIGJyZWFrO1xuICAgICAgfVxuICAgIH1cblxuICAgIHJldHVybiBjb2xsZWN0aW9uLnNsaWNlKDAsIGNvdW50KTtcbiAgfSxcblxuICB0b19saXN0OiBmdW5jdGlvbiAoY29sbGVjdGlvbikge1xuICAgIHJldHVybiBjb2xsZWN0aW9uO1xuICB9XG59O1xuXG52YXIgRWxpeGlyID0ge1xuICBDb3JlLFxuICBFbnVtLFxuICBWaXJ0dWFsRE9NXG59O1xuXG5leHBvcnQgZGVmYXVsdCBFbGl4aXI7Il0sImZpbGUiOiJFbGl4aXIuanMiLCJzb3VyY2VSb290IjoiL3NvdXJjZS8ifQ== \ No newline at end of file +//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiIiwic291cmNlcyI6WyJFbGl4aXIuanMiXSwic291cmNlc0NvbnRlbnQiOlsibGV0IFZpcnR1YWxET00gPSAoZnVuY3Rpb24gKGUpIHtcbiAgICByZXR1cm4gZSgpO1xufSkoZnVuY3Rpb24gKCkge1xuICAgIHZhciBkZWZpbmUsIG1vZHVsZSwgZXhwb3J0cztcbiAgICByZXR1cm4gKGZ1bmN0aW9uIGUodCwgbiwgcikge1xuICAgICAgICBmdW5jdGlvbiBzKG8sIHUpIHtcbiAgICAgICAgICAgIGlmICghbltvXSkge1xuICAgICAgICAgICAgICAgIGlmICghdFtvXSkge1xuICAgICAgICAgICAgICAgICAgICB2YXIgYSA9IHR5cGVvZiByZXF1aXJlID09IFwiZnVuY3Rpb25cIiAmJiByZXF1aXJlO1xuICAgICAgICAgICAgICAgICAgICBpZiAoIXUgJiYgYSkgcmV0dXJuIGEobywgITApO1xuICAgICAgICAgICAgICAgICAgICBpZiAoaSkgcmV0dXJuIGkobywgITApO1xuICAgICAgICAgICAgICAgICAgICB2YXIgZiA9IG5ldyBFcnJvcihcIkNhbm5vdCBmaW5kIG1vZHVsZSAnXCIgKyBvICsgXCInXCIpO1xuICAgICAgICAgICAgICAgICAgICB0aHJvdyAoZi5jb2RlID0gXCJNT0RVTEVfTk9UX0ZPVU5EXCIsIGYpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB2YXIgbCA9IG5bb10gPSB7XG4gICAgICAgICAgICAgICAgICAgIGV4cG9ydHM6IHt9XG4gICAgICAgICAgICAgICAgfTtcbiAgICAgICAgICAgICAgICB0W29dWzBdLmNhbGwobC5leHBvcnRzLCBmdW5jdGlvbiAoZSkge1xuICAgICAgICAgICAgICAgICAgICB2YXIgbiA9IHRbb11bMV1bZV07XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBzKG4gPyBuIDogZSk7XG4gICAgICAgICAgICAgICAgfSwgbCwgbC5leHBvcnRzLCBlLCB0LCBuLCByKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJldHVybiBuW29dLmV4cG9ydHM7XG4gICAgICAgIH1cbiAgICAgICAgdmFyIGkgPSB0eXBlb2YgcmVxdWlyZSA9PSBcImZ1bmN0aW9uXCIgJiYgcmVxdWlyZTtcbiAgICAgICAgZm9yICh2YXIgbyA9IDA7IG8gPCByLmxlbmd0aDsgbysrKSBzKHJbb10pO1xuICAgICAgICByZXR1cm4gcztcbiAgICB9KSh7XG4gICAgICAgIDE6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG5cbiAgICAgICAgICAgIHZhciBjcmVhdGVFbGVtZW50ID0gcmVxdWlyZShcIi4vdmRvbS9jcmVhdGUtZWxlbWVudC5qc1wiKTtcblxuICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBjcmVhdGVFbGVtZW50O1xuICAgICAgICB9LCB7IFwiLi92ZG9tL2NyZWF0ZS1lbGVtZW50LmpzXCI6IDE1IH1dLCAyOiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge1xuICAgICAgICAgICAgdmFyIGRpZmYgPSByZXF1aXJlKFwiLi92dHJlZS9kaWZmLmpzXCIpO1xuXG4gICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IGRpZmY7XG4gICAgICAgIH0sIHsgXCIuL3Z0cmVlL2RpZmYuanNcIjogMzUgfV0sIDM6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICB2YXIgaCA9IHJlcXVpcmUoXCIuL3ZpcnR1YWwtaHlwZXJzY3JpcHQvaW5kZXguanNcIik7XG5cbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gaDtcbiAgICAgICAgfSwgeyBcIi4vdmlydHVhbC1oeXBlcnNjcmlwdC9pbmRleC5qc1wiOiAyMiB9XSwgNDogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHtcbiAgICAgICAgICAgIHZhciBkaWZmID0gcmVxdWlyZShcIi4vZGlmZi5qc1wiKTtcbiAgICAgICAgICAgIHZhciBwYXRjaCA9IHJlcXVpcmUoXCIuL3BhdGNoLmpzXCIpO1xuICAgICAgICAgICAgdmFyIGggPSByZXF1aXJlKFwiLi9oLmpzXCIpO1xuICAgICAgICAgICAgdmFyIGNyZWF0ZSA9IHJlcXVpcmUoXCIuL2NyZWF0ZS1lbGVtZW50LmpzXCIpO1xuICAgICAgICAgICAgdmFyIFZOb2RlID0gcmVxdWlyZShcIi4vdm5vZGUvdm5vZGUuanNcIik7XG4gICAgICAgICAgICB2YXIgVlRleHQgPSByZXF1aXJlKFwiLi92bm9kZS92dGV4dC5qc1wiKTtcblxuICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSB7XG4gICAgICAgICAgICAgICAgZGlmZjogZGlmZixcbiAgICAgICAgICAgICAgICBwYXRjaDogcGF0Y2gsXG4gICAgICAgICAgICAgICAgaDogaCxcbiAgICAgICAgICAgICAgICBjcmVhdGU6IGNyZWF0ZSxcbiAgICAgICAgICAgICAgICBWTm9kZTogVk5vZGUsXG4gICAgICAgICAgICAgICAgVlRleHQ6IFZUZXh0XG4gICAgICAgICAgICB9O1xuICAgICAgICB9LCB7IFwiLi9jcmVhdGUtZWxlbWVudC5qc1wiOiAxLCBcIi4vZGlmZi5qc1wiOiAyLCBcIi4vaC5qc1wiOiAzLCBcIi4vcGF0Y2guanNcIjogMTMsIFwiLi92bm9kZS92bm9kZS5qc1wiOiAzMSwgXCIuL3Zub2RlL3Z0ZXh0LmpzXCI6IDMzIH1dLCA1OiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge1xuICAgICAgICAgICAgLyohXG4gICAgICAgICAgICAgKiBDcm9zcy1Ccm93c2VyIFNwbGl0IDEuMS4xXG4gICAgICAgICAgICAgKiBDb3B5cmlnaHQgMjAwNy0yMDEyIFN0ZXZlbiBMZXZpdGhhbiA8c3RldmVubGV2aXRoYW4uY29tPlxuICAgICAgICAgICAgICogQXZhaWxhYmxlIHVuZGVyIHRoZSBNSVQgTGljZW5zZVxuICAgICAgICAgICAgICogRUNNQVNjcmlwdCBjb21wbGlhbnQsIHVuaWZvcm0gY3Jvc3MtYnJvd3NlciBzcGxpdCBtZXRob2RcbiAgICAgICAgICAgICAqL1xuXG4gICAgICAgICAgICAvKipcbiAgICAgICAgICAgICAqIFNwbGl0cyBhIHN0cmluZyBpbnRvIGFuIGFycmF5IG9mIHN0cmluZ3MgdXNpbmcgYSByZWdleCBvciBzdHJpbmcgc2VwYXJhdG9yLiBNYXRjaGVzIG9mIHRoZVxuICAgICAgICAgICAgICogc2VwYXJhdG9yIGFyZSBub3QgaW5jbHVkZWQgaW4gdGhlIHJlc3VsdCBhcnJheS4gSG93ZXZlciwgaWYgYHNlcGFyYXRvcmAgaXMgYSByZWdleCB0aGF0IGNvbnRhaW5zXG4gICAgICAgICAgICAgKiBjYXB0dXJpbmcgZ3JvdXBzLCBiYWNrcmVmZXJlbmNlcyBhcmUgc3BsaWNlZCBpbnRvIHRoZSByZXN1bHQgZWFjaCB0aW1lIGBzZXBhcmF0b3JgIGlzIG1hdGNoZWQuXG4gICAgICAgICAgICAgKiBGaXhlcyBicm93c2VyIGJ1Z3MgY29tcGFyZWQgdG8gdGhlIG5hdGl2ZSBgU3RyaW5nLnByb3RvdHlwZS5zcGxpdGAgYW5kIGNhbiBiZSB1c2VkIHJlbGlhYmx5XG4gICAgICAgICAgICAgKiBjcm9zcy1icm93c2VyLlxuICAgICAgICAgICAgICogQHBhcmFtIHtTdHJpbmd9IHN0ciBTdHJpbmcgdG8gc3BsaXQuXG4gICAgICAgICAgICAgKiBAcGFyYW0ge1JlZ0V4cHxTdHJpbmd9IHNlcGFyYXRvciBSZWdleCBvciBzdHJpbmcgdG8gdXNlIGZvciBzZXBhcmF0aW5nIHRoZSBzdHJpbmcuXG4gICAgICAgICAgICAgKiBAcGFyYW0ge051bWJlcn0gW2xpbWl0XSBNYXhpbXVtIG51bWJlciBvZiBpdGVtcyB0byBpbmNsdWRlIGluIHRoZSByZXN1bHQgYXJyYXkuXG4gICAgICAgICAgICAgKiBAcmV0dXJucyB7QXJyYXl9IEFycmF5IG9mIHN1YnN0cmluZ3MuXG4gICAgICAgICAgICAgKiBAZXhhbXBsZVxuICAgICAgICAgICAgICpcbiAgICAgICAgICAgICAqIC8vIEJhc2ljIHVzZVxuICAgICAgICAgICAgICogc3BsaXQoJ2EgYiBjIGQnLCAnICcpO1xuICAgICAgICAgICAgICogLy8gLT4gWydhJywgJ2InLCAnYycsICdkJ11cbiAgICAgICAgICAgICAqXG4gICAgICAgICAgICAgKiAvLyBXaXRoIGxpbWl0XG4gICAgICAgICAgICAgKiBzcGxpdCgnYSBiIGMgZCcsICcgJywgMik7XG4gICAgICAgICAgICAgKiAvLyAtPiBbJ2EnLCAnYiddXG4gICAgICAgICAgICAgKlxuICAgICAgICAgICAgICogLy8gQmFja3JlZmVyZW5jZXMgaW4gcmVzdWx0IGFycmF5XG4gICAgICAgICAgICAgKiBzcGxpdCgnLi53b3JkMSB3b3JkMi4uJywgLyhbYS16XSspKFxcZCspL2kpO1xuICAgICAgICAgICAgICogLy8gLT4gWycuLicsICd3b3JkJywgJzEnLCAnICcsICd3b3JkJywgJzInLCAnLi4nXVxuICAgICAgICAgICAgICovXG4gICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IChmdW5jdGlvbiBzcGxpdCh1bmRlZikge1xuXG4gICAgICAgICAgICAgICAgdmFyIG5hdGl2ZVNwbGl0ID0gU3RyaW5nLnByb3RvdHlwZS5zcGxpdCxcbiAgICAgICAgICAgICAgICAgICAgY29tcGxpYW50RXhlY05wY2cgPSAvKCk/Py8uZXhlYyhcIlwiKVsxXSA9PT0gdW5kZWYsXG5cbiAgICAgICAgICAgICAgICAvLyBOUENHOiBub25wYXJ0aWNpcGF0aW5nIGNhcHR1cmluZyBncm91cFxuICAgICAgICAgICAgICAgIHNlbGY7XG5cbiAgICAgICAgICAgICAgICBzZWxmID0gZnVuY3Rpb24gKHN0ciwgc2VwYXJhdG9yLCBsaW1pdCkge1xuICAgICAgICAgICAgICAgICAgICAvLyBJZiBgc2VwYXJhdG9yYCBpcyBub3QgYSByZWdleCwgdXNlIGBuYXRpdmVTcGxpdGBcbiAgICAgICAgICAgICAgICAgICAgaWYgKE9iamVjdC5wcm90b3R5cGUudG9TdHJpbmcuY2FsbChzZXBhcmF0b3IpICE9PSBcIltvYmplY3QgUmVnRXhwXVwiKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gbmF0aXZlU3BsaXQuY2FsbChzdHIsIHNlcGFyYXRvciwgbGltaXQpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIHZhciBvdXRwdXQgPSBbXSxcbiAgICAgICAgICAgICAgICAgICAgICAgIGZsYWdzID0gKHNlcGFyYXRvci5pZ25vcmVDYXNlID8gXCJpXCIgOiBcIlwiKSArIChzZXBhcmF0b3IubXVsdGlsaW5lID8gXCJtXCIgOiBcIlwiKSArIChzZXBhcmF0b3IuZXh0ZW5kZWQgPyBcInhcIiA6IFwiXCIpICsgKHNlcGFyYXRvci5zdGlja3kgPyBcInlcIiA6IFwiXCIpLFxuXG4gICAgICAgICAgICAgICAgICAgIC8vIEZpcmVmb3ggMytcbiAgICAgICAgICAgICAgICAgICAgbGFzdExhc3RJbmRleCA9IDAsXG5cbiAgICAgICAgICAgICAgICAgICAgLy8gTWFrZSBgZ2xvYmFsYCBhbmQgYXZvaWQgYGxhc3RJbmRleGAgaXNzdWVzIGJ5IHdvcmtpbmcgd2l0aCBhIGNvcHlcbiAgICAgICAgICAgICAgICAgICAgc2VwYXJhdG9yID0gbmV3IFJlZ0V4cChzZXBhcmF0b3Iuc291cmNlLCBmbGFncyArIFwiZ1wiKSxcbiAgICAgICAgICAgICAgICAgICAgICAgIHNlcGFyYXRvcjIsXG4gICAgICAgICAgICAgICAgICAgICAgICBtYXRjaCxcbiAgICAgICAgICAgICAgICAgICAgICAgIGxhc3RJbmRleCxcbiAgICAgICAgICAgICAgICAgICAgICAgIGxhc3RMZW5ndGg7XG4gICAgICAgICAgICAgICAgICAgIHN0ciArPSBcIlwiOyAvLyBUeXBlLWNvbnZlcnRcbiAgICAgICAgICAgICAgICAgICAgaWYgKCFjb21wbGlhbnRFeGVjTnBjZykge1xuICAgICAgICAgICAgICAgICAgICAgICAgLy8gRG9lc24ndCBuZWVkIGZsYWdzIGd5LCBidXQgdGhleSBkb24ndCBodXJ0XG4gICAgICAgICAgICAgICAgICAgICAgICBzZXBhcmF0b3IyID0gbmV3IFJlZ0V4cChcIl5cIiArIHNlcGFyYXRvci5zb3VyY2UgKyBcIiQoPyFcXFxccylcIiwgZmxhZ3MpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIC8qIFZhbHVlcyBmb3IgYGxpbWl0YCwgcGVyIHRoZSBzcGVjOlxuICAgICAgICAgICAgICAgICAgICAgKiBJZiB1bmRlZmluZWQ6IDQyOTQ5NjcyOTUgLy8gTWF0aC5wb3coMiwgMzIpIC0gMVxuICAgICAgICAgICAgICAgICAgICAgKiBJZiAwLCBJbmZpbml0eSwgb3IgTmFOOiAwXG4gICAgICAgICAgICAgICAgICAgICAqIElmIHBvc2l0aXZlIG51bWJlcjogbGltaXQgPSBNYXRoLmZsb29yKGxpbWl0KTsgaWYgKGxpbWl0ID4gNDI5NDk2NzI5NSkgbGltaXQgLT0gNDI5NDk2NzI5NjtcbiAgICAgICAgICAgICAgICAgICAgICogSWYgbmVnYXRpdmUgbnVtYmVyOiA0Mjk0OTY3Mjk2IC0gTWF0aC5mbG9vcihNYXRoLmFicyhsaW1pdCkpXG4gICAgICAgICAgICAgICAgICAgICAqIElmIG90aGVyOiBUeXBlLWNvbnZlcnQsIHRoZW4gdXNlIHRoZSBhYm92ZSBydWxlc1xuICAgICAgICAgICAgICAgICAgICAgKi9cbiAgICAgICAgICAgICAgICAgICAgbGltaXQgPSBsaW1pdCA9PT0gdW5kZWYgPyAtMSA+Pj4gMCA6IC8vIE1hdGgucG93KDIsIDMyKSAtIDFcbiAgICAgICAgICAgICAgICAgICAgbGltaXQgPj4+IDA7IC8vIFRvVWludDMyKGxpbWl0KVxuICAgICAgICAgICAgICAgICAgICB3aGlsZSAobWF0Y2ggPSBzZXBhcmF0b3IuZXhlYyhzdHIpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAvLyBgc2VwYXJhdG9yLmxhc3RJbmRleGAgaXMgbm90IHJlbGlhYmxlIGNyb3NzLWJyb3dzZXJcbiAgICAgICAgICAgICAgICAgICAgICAgIGxhc3RJbmRleCA9IG1hdGNoLmluZGV4ICsgbWF0Y2hbMF0ubGVuZ3RoO1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGxhc3RJbmRleCA+IGxhc3RMYXN0SW5kZXgpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBvdXRwdXQucHVzaChzdHIuc2xpY2UobGFzdExhc3RJbmRleCwgbWF0Y2guaW5kZXgpKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBGaXggYnJvd3NlcnMgd2hvc2UgYGV4ZWNgIG1ldGhvZHMgZG9uJ3QgY29uc2lzdGVudGx5IHJldHVybiBgdW5kZWZpbmVkYCBmb3JcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBub25wYXJ0aWNpcGF0aW5nIGNhcHR1cmluZyBncm91cHNcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoIWNvbXBsaWFudEV4ZWNOcGNnICYmIG1hdGNoLmxlbmd0aCA+IDEpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbWF0Y2hbMF0ucmVwbGFjZShzZXBhcmF0b3IyLCBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBmb3IgKHZhciBpID0gMTsgaSA8IGFyZ3VtZW50cy5sZW5ndGggLSAyOyBpKyspIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoYXJndW1lbnRzW2ldID09PSB1bmRlZikge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBtYXRjaFtpXSA9IHVuZGVmO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChtYXRjaC5sZW5ndGggPiAxICYmIG1hdGNoLmluZGV4IDwgc3RyLmxlbmd0aCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBBcnJheS5wcm90b3R5cGUucHVzaC5hcHBseShvdXRwdXQsIG1hdGNoLnNsaWNlKDEpKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgbGFzdExlbmd0aCA9IG1hdGNoWzBdLmxlbmd0aDtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBsYXN0TGFzdEluZGV4ID0gbGFzdEluZGV4O1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChvdXRwdXQubGVuZ3RoID49IGxpbWl0KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChzZXBhcmF0b3IubGFzdEluZGV4ID09PSBtYXRjaC5pbmRleCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNlcGFyYXRvci5sYXN0SW5kZXgrKzsgLy8gQXZvaWQgYW4gaW5maW5pdGUgbG9vcFxuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIGlmIChsYXN0TGFzdEluZGV4ID09PSBzdHIubGVuZ3RoKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAobGFzdExlbmd0aCB8fCAhc2VwYXJhdG9yLnRlc3QoXCJcIikpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBvdXRwdXQucHVzaChcIlwiKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIG91dHB1dC5wdXNoKHN0ci5zbGljZShsYXN0TGFzdEluZGV4KSk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIG91dHB1dC5sZW5ndGggPiBsaW1pdCA/IG91dHB1dC5zbGljZSgwLCBsaW1pdCkgOiBvdXRwdXQ7XG4gICAgICAgICAgICAgICAgfTtcblxuICAgICAgICAgICAgICAgIHJldHVybiBzZWxmO1xuICAgICAgICAgICAgfSkoKTtcbiAgICAgICAgfSwge31dLCA2OiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge30sIHt9XSwgNzogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHtcbiAgICAgICAgICAgIFwidXNlIHN0cmljdFwiO1xuXG4gICAgICAgICAgICB2YXIgT25lVmVyc2lvbkNvbnN0cmFpbnQgPSByZXF1aXJlKFwiaW5kaXZpZHVhbC9vbmUtdmVyc2lvblwiKTtcblxuICAgICAgICAgICAgdmFyIE1ZX1ZFUlNJT04gPSBcIjdcIjtcbiAgICAgICAgICAgIE9uZVZlcnNpb25Db25zdHJhaW50KFwiZXYtc3RvcmVcIiwgTVlfVkVSU0lPTik7XG5cbiAgICAgICAgICAgIHZhciBoYXNoS2V5ID0gXCJfX0VWX1NUT1JFX0tFWUBcIiArIE1ZX1ZFUlNJT047XG5cbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gRXZTdG9yZTtcblxuICAgICAgICAgICAgZnVuY3Rpb24gRXZTdG9yZShlbGVtKSB7XG4gICAgICAgICAgICAgICAgdmFyIGhhc2ggPSBlbGVtW2hhc2hLZXldO1xuXG4gICAgICAgICAgICAgICAgaWYgKCFoYXNoKSB7XG4gICAgICAgICAgICAgICAgICAgIGhhc2ggPSBlbGVtW2hhc2hLZXldID0ge307XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgcmV0dXJuIGhhc2g7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0sIHsgXCJpbmRpdmlkdWFsL29uZS12ZXJzaW9uXCI6IDkgfV0sIDg6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICAoZnVuY3Rpb24gKGdsb2JhbCkge1xuICAgICAgICAgICAgICAgIFwidXNlIHN0cmljdFwiO1xuXG4gICAgICAgICAgICAgICAgLypnbG9iYWwgd2luZG93LCBnbG9iYWwqL1xuXG4gICAgICAgICAgICAgICAgdmFyIHJvb3QgPSB0eXBlb2Ygd2luZG93ICE9PSBcInVuZGVmaW5lZFwiID8gd2luZG93IDogdHlwZW9mIGdsb2JhbCAhPT0gXCJ1bmRlZmluZWRcIiA/IGdsb2JhbCA6IHt9O1xuXG4gICAgICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBJbmRpdmlkdWFsO1xuXG4gICAgICAgICAgICAgICAgZnVuY3Rpb24gSW5kaXZpZHVhbChrZXksIHZhbHVlKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmIChrZXkgaW4gcm9vdCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHJvb3Rba2V5XTtcbiAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgIHJvb3Rba2V5XSA9IHZhbHVlO1xuXG4gICAgICAgICAgICAgICAgICAgIHJldHVybiB2YWx1ZTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9KS5jYWxsKHRoaXMsIHR5cGVvZiBnbG9iYWwgIT09IFwidW5kZWZpbmVkXCIgPyBnbG9iYWwgOiB0eXBlb2Ygc2VsZiAhPT0gXCJ1bmRlZmluZWRcIiA/IHNlbGYgOiB0eXBlb2Ygd2luZG93ICE9PSBcInVuZGVmaW5lZFwiID8gd2luZG93IDoge30pO1xuICAgICAgICB9LCB7fV0sIDk6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICBcInVzZSBzdHJpY3RcIjtcblxuICAgICAgICAgICAgdmFyIEluZGl2aWR1YWwgPSByZXF1aXJlKFwiLi9pbmRleC5qc1wiKTtcblxuICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBPbmVWZXJzaW9uO1xuXG4gICAgICAgICAgICBmdW5jdGlvbiBPbmVWZXJzaW9uKG1vZHVsZU5hbWUsIHZlcnNpb24sIGRlZmF1bHRWYWx1ZSkge1xuICAgICAgICAgICAgICAgIHZhciBrZXkgPSBcIl9fSU5ESVZJRFVBTF9PTkVfVkVSU0lPTl9cIiArIG1vZHVsZU5hbWU7XG4gICAgICAgICAgICAgICAgdmFyIGVuZm9yY2VLZXkgPSBrZXkgKyBcIl9FTkZPUkNFX1NJTkdMRVRPTlwiO1xuXG4gICAgICAgICAgICAgICAgdmFyIHZlcnNpb25WYWx1ZSA9IEluZGl2aWR1YWwoZW5mb3JjZUtleSwgdmVyc2lvbik7XG5cbiAgICAgICAgICAgICAgICBpZiAodmVyc2lvblZhbHVlICE9PSB2ZXJzaW9uKSB7XG4gICAgICAgICAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcihcIkNhbiBvbmx5IGhhdmUgb25lIGNvcHkgb2YgXCIgKyBtb2R1bGVOYW1lICsgXCIuXFxuXCIgKyBcIllvdSBhbHJlYWR5IGhhdmUgdmVyc2lvbiBcIiArIHZlcnNpb25WYWx1ZSArIFwiIGluc3RhbGxlZC5cXG5cIiArIFwiVGhpcyBtZWFucyB5b3UgY2Fubm90IGluc3RhbGwgdmVyc2lvbiBcIiArIHZlcnNpb24pO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHJldHVybiBJbmRpdmlkdWFsKGtleSwgZGVmYXVsdFZhbHVlKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSwgeyBcIi4vaW5kZXguanNcIjogOCB9XSwgMTA6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICAoZnVuY3Rpb24gKGdsb2JhbCkge1xuICAgICAgICAgICAgICAgIHZhciB0b3BMZXZlbCA9IHR5cGVvZiBnbG9iYWwgIT09IFwidW5kZWZpbmVkXCIgPyBnbG9iYWwgOiB0eXBlb2Ygd2luZG93ICE9PSBcInVuZGVmaW5lZFwiID8gd2luZG93IDoge307XG4gICAgICAgICAgICAgICAgdmFyIG1pbkRvYyA9IHJlcXVpcmUoXCJtaW4tZG9jdW1lbnRcIik7XG5cbiAgICAgICAgICAgICAgICBpZiAodHlwZW9mIGRvY3VtZW50ICE9PSBcInVuZGVmaW5lZFwiKSB7XG4gICAgICAgICAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gZG9jdW1lbnQ7XG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgdmFyIGRvY2N5ID0gdG9wTGV2ZWxbXCJfX0dMT0JBTF9ET0NVTUVOVF9DQUNIRUA0XCJdO1xuXG4gICAgICAgICAgICAgICAgICAgIGlmICghZG9jY3kpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGRvY2N5ID0gdG9wTGV2ZWxbXCJfX0dMT0JBTF9ET0NVTUVOVF9DQUNIRUA0XCJdID0gbWluRG9jO1xuICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBkb2NjeTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9KS5jYWxsKHRoaXMsIHR5cGVvZiBnbG9iYWwgIT09IFwidW5kZWZpbmVkXCIgPyBnbG9iYWwgOiB0eXBlb2Ygc2VsZiAhPT0gXCJ1bmRlZmluZWRcIiA/IHNlbGYgOiB0eXBlb2Ygd2luZG93ICE9PSBcInVuZGVmaW5lZFwiID8gd2luZG93IDoge30pO1xuICAgICAgICB9LCB7IFwibWluLWRvY3VtZW50XCI6IDYgfV0sIDExOiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge1xuICAgICAgICAgICAgXCJ1c2Ugc3RyaWN0XCI7XG5cbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gaXNPYmplY3QoeCkge1xuICAgICAgICAgICAgICAgIHJldHVybiB0eXBlb2YgeCA9PT0gXCJvYmplY3RcIiAmJiB4ICE9PSBudWxsO1xuICAgICAgICAgICAgfTtcbiAgICAgICAgfSwge31dLCAxMjogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHtcbiAgICAgICAgICAgIHZhciBuYXRpdmVJc0FycmF5ID0gQXJyYXkuaXNBcnJheTtcbiAgICAgICAgICAgIHZhciB0b1N0cmluZyA9IE9iamVjdC5wcm90b3R5cGUudG9TdHJpbmc7XG5cbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gbmF0aXZlSXNBcnJheSB8fCBpc0FycmF5O1xuXG4gICAgICAgICAgICBmdW5jdGlvbiBpc0FycmF5KG9iaikge1xuICAgICAgICAgICAgICAgIHJldHVybiB0b1N0cmluZy5jYWxsKG9iaikgPT09IFwiW29iamVjdCBBcnJheV1cIjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSwge31dLCAxMzogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHtcbiAgICAgICAgICAgIHZhciBwYXRjaCA9IHJlcXVpcmUoXCIuL3Zkb20vcGF0Y2guanNcIik7XG5cbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gcGF0Y2g7XG4gICAgICAgIH0sIHsgXCIuL3Zkb20vcGF0Y2guanNcIjogMTggfV0sIDE0OiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge1xuICAgICAgICAgICAgdmFyIGlzT2JqZWN0ID0gcmVxdWlyZShcImlzLW9iamVjdFwiKTtcbiAgICAgICAgICAgIHZhciBpc0hvb2sgPSByZXF1aXJlKFwiLi4vdm5vZGUvaXMtdmhvb2suanNcIik7XG5cbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gYXBwbHlQcm9wZXJ0aWVzO1xuXG4gICAgICAgICAgICBmdW5jdGlvbiBhcHBseVByb3BlcnRpZXMobm9kZSwgcHJvcHMsIHByZXZpb3VzKSB7XG4gICAgICAgICAgICAgICAgZm9yICh2YXIgcHJvcE5hbWUgaW4gcHJvcHMpIHtcbiAgICAgICAgICAgICAgICAgICAgdmFyIHByb3BWYWx1ZSA9IHByb3BzW3Byb3BOYW1lXTtcblxuICAgICAgICAgICAgICAgICAgICBpZiAocHJvcFZhbHVlID09PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJlbW92ZVByb3BlcnR5KG5vZGUsIHByb3BOYW1lLCBwcm9wVmFsdWUsIHByZXZpb3VzKTtcbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIGlmIChpc0hvb2socHJvcFZhbHVlKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgcmVtb3ZlUHJvcGVydHkobm9kZSwgcHJvcE5hbWUsIHByb3BWYWx1ZSwgcHJldmlvdXMpO1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHByb3BWYWx1ZS5ob29rKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcHJvcFZhbHVlLmhvb2sobm9kZSwgcHJvcE5hbWUsIHByZXZpb3VzID8gcHJldmlvdXNbcHJvcE5hbWVdIDogdW5kZWZpbmVkKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChpc09iamVjdChwcm9wVmFsdWUpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcGF0Y2hPYmplY3Qobm9kZSwgcHJvcHMsIHByZXZpb3VzLCBwcm9wTmFtZSwgcHJvcFZhbHVlKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgbm9kZVtwcm9wTmFtZV0gPSBwcm9wVmFsdWU7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIHJlbW92ZVByb3BlcnR5KG5vZGUsIHByb3BOYW1lLCBwcm9wVmFsdWUsIHByZXZpb3VzKSB7XG4gICAgICAgICAgICAgICAgaWYgKHByZXZpb3VzKSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciBwcmV2aW91c1ZhbHVlID0gcHJldmlvdXNbcHJvcE5hbWVdO1xuXG4gICAgICAgICAgICAgICAgICAgIGlmICghaXNIb29rKHByZXZpb3VzVmFsdWUpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAocHJvcE5hbWUgPT09IFwiYXR0cmlidXRlc1wiKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgZm9yICh2YXIgYXR0ck5hbWUgaW4gcHJldmlvdXNWYWx1ZSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBub2RlLnJlbW92ZUF0dHJpYnV0ZShhdHRyTmFtZSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIGlmIChwcm9wTmFtZSA9PT0gXCJzdHlsZVwiKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgZm9yICh2YXIgaSBpbiBwcmV2aW91c1ZhbHVlKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG5vZGUuc3R5bGVbaV0gPSBcIlwiO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAodHlwZW9mIHByZXZpb3VzVmFsdWUgPT09IFwic3RyaW5nXCIpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBub2RlW3Byb3BOYW1lXSA9IFwiXCI7XG4gICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIG5vZGVbcHJvcE5hbWVdID0gbnVsbDtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIGlmIChwcmV2aW91c1ZhbHVlLnVuaG9vaykge1xuICAgICAgICAgICAgICAgICAgICAgICAgcHJldmlvdXNWYWx1ZS51bmhvb2sobm9kZSwgcHJvcE5hbWUsIHByb3BWYWx1ZSk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIHBhdGNoT2JqZWN0KG5vZGUsIHByb3BzLCBwcmV2aW91cywgcHJvcE5hbWUsIHByb3BWYWx1ZSkge1xuICAgICAgICAgICAgICAgIHZhciBwcmV2aW91c1ZhbHVlID0gcHJldmlvdXMgPyBwcmV2aW91c1twcm9wTmFtZV0gOiB1bmRlZmluZWQ7XG5cbiAgICAgICAgICAgICAgICAvLyBTZXQgYXR0cmlidXRlc1xuICAgICAgICAgICAgICAgIGlmIChwcm9wTmFtZSA9PT0gXCJhdHRyaWJ1dGVzXCIpIHtcbiAgICAgICAgICAgICAgICAgICAgZm9yICh2YXIgYXR0ck5hbWUgaW4gcHJvcFZhbHVlKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICB2YXIgYXR0clZhbHVlID0gcHJvcFZhbHVlW2F0dHJOYW1lXTtcblxuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGF0dHJWYWx1ZSA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgbm9kZS5yZW1vdmVBdHRyaWJ1dGUoYXR0ck5hbWUpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBub2RlLnNldEF0dHJpYnV0ZShhdHRyTmFtZSwgYXR0clZhbHVlKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICBpZiAocHJldmlvdXNWYWx1ZSAmJiBpc09iamVjdChwcmV2aW91c1ZhbHVlKSAmJiBnZXRQcm90b3R5cGUocHJldmlvdXNWYWx1ZSkgIT09IGdldFByb3RvdHlwZShwcm9wVmFsdWUpKSB7XG4gICAgICAgICAgICAgICAgICAgIG5vZGVbcHJvcE5hbWVdID0gcHJvcFZhbHVlO1xuICAgICAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgaWYgKCFpc09iamVjdChub2RlW3Byb3BOYW1lXSkpIHtcbiAgICAgICAgICAgICAgICAgICAgbm9kZVtwcm9wTmFtZV0gPSB7fTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICB2YXIgcmVwbGFjZXIgPSBwcm9wTmFtZSA9PT0gXCJzdHlsZVwiID8gXCJcIiA6IHVuZGVmaW5lZDtcblxuICAgICAgICAgICAgICAgIGZvciAodmFyIGsgaW4gcHJvcFZhbHVlKSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciB2YWx1ZSA9IHByb3BWYWx1ZVtrXTtcbiAgICAgICAgICAgICAgICAgICAgbm9kZVtwcm9wTmFtZV1ba10gPSB2YWx1ZSA9PT0gdW5kZWZpbmVkID8gcmVwbGFjZXIgOiB2YWx1ZTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIGdldFByb3RvdHlwZSh2YWx1ZSkge1xuICAgICAgICAgICAgICAgIGlmIChPYmplY3QuZ2V0UHJvdG90eXBlT2YpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIE9iamVjdC5nZXRQcm90b3R5cGVPZih2YWx1ZSk7XG4gICAgICAgICAgICAgICAgfSBlbHNlIGlmICh2YWx1ZS5fX3Byb3RvX18pIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHZhbHVlLl9fcHJvdG9fXztcbiAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKHZhbHVlLmNvbnN0cnVjdG9yKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiB2YWx1ZS5jb25zdHJ1Y3Rvci5wcm90b3R5cGU7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9LCB7IFwiLi4vdm5vZGUvaXMtdmhvb2suanNcIjogMjYsIFwiaXMtb2JqZWN0XCI6IDExIH1dLCAxNTogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHtcbiAgICAgICAgICAgIHZhciBkb2N1bWVudCA9IHJlcXVpcmUoXCJnbG9iYWwvZG9jdW1lbnRcIik7XG5cbiAgICAgICAgICAgIHZhciBhcHBseVByb3BlcnRpZXMgPSByZXF1aXJlKFwiLi9hcHBseS1wcm9wZXJ0aWVzXCIpO1xuXG4gICAgICAgICAgICB2YXIgaXNWTm9kZSA9IHJlcXVpcmUoXCIuLi92bm9kZS9pcy12bm9kZS5qc1wiKTtcbiAgICAgICAgICAgIHZhciBpc1ZUZXh0ID0gcmVxdWlyZShcIi4uL3Zub2RlL2lzLXZ0ZXh0LmpzXCIpO1xuICAgICAgICAgICAgdmFyIGlzV2lkZ2V0ID0gcmVxdWlyZShcIi4uL3Zub2RlL2lzLXdpZGdldC5qc1wiKTtcbiAgICAgICAgICAgIHZhciBoYW5kbGVUaHVuayA9IHJlcXVpcmUoXCIuLi92bm9kZS9oYW5kbGUtdGh1bmsuanNcIik7XG5cbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gY3JlYXRlRWxlbWVudDtcblxuICAgICAgICAgICAgZnVuY3Rpb24gY3JlYXRlRWxlbWVudCh2bm9kZSwgb3B0cykge1xuICAgICAgICAgICAgICAgIHZhciBkb2MgPSBvcHRzID8gb3B0cy5kb2N1bWVudCB8fCBkb2N1bWVudCA6IGRvY3VtZW50O1xuICAgICAgICAgICAgICAgIHZhciB3YXJuID0gb3B0cyA/IG9wdHMud2FybiA6IG51bGw7XG5cbiAgICAgICAgICAgICAgICB2bm9kZSA9IGhhbmRsZVRodW5rKHZub2RlKS5hO1xuXG4gICAgICAgICAgICAgICAgaWYgKGlzV2lkZ2V0KHZub2RlKSkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gdm5vZGUuaW5pdCgpO1xuICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoaXNWVGV4dCh2bm9kZSkpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGRvYy5jcmVhdGVUZXh0Tm9kZSh2bm9kZS50ZXh0KTtcbiAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKCFpc1ZOb2RlKHZub2RlKSkge1xuICAgICAgICAgICAgICAgICAgICBpZiAod2Fybikge1xuICAgICAgICAgICAgICAgICAgICAgICAgd2FybihcIkl0ZW0gaXMgbm90IGEgdmFsaWQgdmlydHVhbCBkb20gbm9kZVwiLCB2bm9kZSk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIG51bGw7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgdmFyIG5vZGUgPSB2bm9kZS5uYW1lc3BhY2UgPT09IG51bGwgPyBkb2MuY3JlYXRlRWxlbWVudCh2bm9kZS50YWdOYW1lKSA6IGRvYy5jcmVhdGVFbGVtZW50TlModm5vZGUubmFtZXNwYWNlLCB2bm9kZS50YWdOYW1lKTtcblxuICAgICAgICAgICAgICAgIHZhciBwcm9wcyA9IHZub2RlLnByb3BlcnRpZXM7XG4gICAgICAgICAgICAgICAgYXBwbHlQcm9wZXJ0aWVzKG5vZGUsIHByb3BzKTtcblxuICAgICAgICAgICAgICAgIHZhciBjaGlsZHJlbiA9IHZub2RlLmNoaWxkcmVuO1xuXG4gICAgICAgICAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCBjaGlsZHJlbi5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgICAgICAgICB2YXIgY2hpbGROb2RlID0gY3JlYXRlRWxlbWVudChjaGlsZHJlbltpXSwgb3B0cyk7XG4gICAgICAgICAgICAgICAgICAgIGlmIChjaGlsZE5vZGUpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIG5vZGUuYXBwZW5kQ2hpbGQoY2hpbGROb2RlKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHJldHVybiBub2RlO1xuICAgICAgICAgICAgfVxuICAgICAgICB9LCB7IFwiLi4vdm5vZGUvaGFuZGxlLXRodW5rLmpzXCI6IDI0LCBcIi4uL3Zub2RlL2lzLXZub2RlLmpzXCI6IDI3LCBcIi4uL3Zub2RlL2lzLXZ0ZXh0LmpzXCI6IDI4LCBcIi4uL3Zub2RlL2lzLXdpZGdldC5qc1wiOiAyOSwgXCIuL2FwcGx5LXByb3BlcnRpZXNcIjogMTQsIFwiZ2xvYmFsL2RvY3VtZW50XCI6IDEwIH1dLCAxNjogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHtcbiAgICAgICAgICAgIC8vIE1hcHMgYSB2aXJ0dWFsIERPTSB0cmVlIG9udG8gYSByZWFsIERPTSB0cmVlIGluIGFuIGVmZmljaWVudCBtYW5uZXIuXG4gICAgICAgICAgICAvLyBXZSBkb24ndCB3YW50IHRvIHJlYWQgYWxsIG9mIHRoZSBET00gbm9kZXMgaW4gdGhlIHRyZWUgc28gd2UgdXNlXG4gICAgICAgICAgICAvLyB0aGUgaW4tb3JkZXIgdHJlZSBpbmRleGluZyB0byBlbGltaW5hdGUgcmVjdXJzaW9uIGRvd24gY2VydGFpbiBicmFuY2hlcy5cbiAgICAgICAgICAgIC8vIFdlIG9ubHkgcmVjdXJzZSBpbnRvIGEgRE9NIG5vZGUgaWYgd2Uga25vdyB0aGF0IGl0IGNvbnRhaW5zIGEgY2hpbGQgb2ZcbiAgICAgICAgICAgIC8vIGludGVyZXN0LlxuXG4gICAgICAgICAgICB2YXIgbm9DaGlsZCA9IHt9O1xuXG4gICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IGRvbUluZGV4O1xuXG4gICAgICAgICAgICBmdW5jdGlvbiBkb21JbmRleChyb290Tm9kZSwgdHJlZSwgaW5kaWNlcywgbm9kZXMpIHtcbiAgICAgICAgICAgICAgICBpZiAoIWluZGljZXMgfHwgaW5kaWNlcy5sZW5ndGggPT09IDApIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHt9O1xuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIGluZGljZXMuc29ydChhc2NlbmRpbmcpO1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gcmVjdXJzZShyb290Tm9kZSwgdHJlZSwgaW5kaWNlcywgbm9kZXMsIDApO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZnVuY3Rpb24gcmVjdXJzZShyb290Tm9kZSwgdHJlZSwgaW5kaWNlcywgbm9kZXMsIHJvb3RJbmRleCkge1xuICAgICAgICAgICAgICAgIG5vZGVzID0gbm9kZXMgfHwge307XG5cbiAgICAgICAgICAgICAgICBpZiAocm9vdE5vZGUpIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKGluZGV4SW5SYW5nZShpbmRpY2VzLCByb290SW5kZXgsIHJvb3RJbmRleCkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIG5vZGVzW3Jvb3RJbmRleF0gPSByb290Tm9kZTtcbiAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgIHZhciB2Q2hpbGRyZW4gPSB0cmVlLmNoaWxkcmVuO1xuXG4gICAgICAgICAgICAgICAgICAgIGlmICh2Q2hpbGRyZW4pIHtcblxuICAgICAgICAgICAgICAgICAgICAgICAgdmFyIGNoaWxkTm9kZXMgPSByb290Tm9kZS5jaGlsZE5vZGVzO1xuXG4gICAgICAgICAgICAgICAgICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IHRyZWUuY2hpbGRyZW4ubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICByb290SW5kZXggKz0gMTtcblxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZhciB2Q2hpbGQgPSB2Q2hpbGRyZW5baV0gfHwgbm9DaGlsZDtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB2YXIgbmV4dEluZGV4ID0gcm9vdEluZGV4ICsgKHZDaGlsZC5jb3VudCB8fCAwKTtcblxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIHNraXAgcmVjdXJzaW9uIGRvd24gdGhlIHRyZWUgaWYgdGhlcmUgYXJlIG5vIG5vZGVzIGRvd24gaGVyZVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChpbmRleEluUmFuZ2UoaW5kaWNlcywgcm9vdEluZGV4LCBuZXh0SW5kZXgpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlY3Vyc2UoY2hpbGROb2Rlc1tpXSwgdkNoaWxkLCBpbmRpY2VzLCBub2Rlcywgcm9vdEluZGV4KTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICByb290SW5kZXggPSBuZXh0SW5kZXg7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICByZXR1cm4gbm9kZXM7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIC8vIEJpbmFyeSBzZWFyY2ggZm9yIGFuIGluZGV4IGluIHRoZSBpbnRlcnZhbCBbbGVmdCwgcmlnaHRdXG4gICAgICAgICAgICBmdW5jdGlvbiBpbmRleEluUmFuZ2UoaW5kaWNlcywgbGVmdCwgcmlnaHQpIHtcbiAgICAgICAgICAgICAgICBpZiAoaW5kaWNlcy5sZW5ndGggPT09IDApIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHZhciBtaW5JbmRleCA9IDA7XG4gICAgICAgICAgICAgICAgdmFyIG1heEluZGV4ID0gaW5kaWNlcy5sZW5ndGggLSAxO1xuICAgICAgICAgICAgICAgIHZhciBjdXJyZW50SW5kZXg7XG4gICAgICAgICAgICAgICAgdmFyIGN1cnJlbnRJdGVtO1xuXG4gICAgICAgICAgICAgICAgd2hpbGUgKG1pbkluZGV4IDw9IG1heEluZGV4KSB7XG4gICAgICAgICAgICAgICAgICAgIGN1cnJlbnRJbmRleCA9IChtYXhJbmRleCArIG1pbkluZGV4KSAvIDIgPj4gMDtcbiAgICAgICAgICAgICAgICAgICAgY3VycmVudEl0ZW0gPSBpbmRpY2VzW2N1cnJlbnRJbmRleF07XG5cbiAgICAgICAgICAgICAgICAgICAgaWYgKG1pbkluZGV4ID09PSBtYXhJbmRleCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGN1cnJlbnRJdGVtID49IGxlZnQgJiYgY3VycmVudEl0ZW0gPD0gcmlnaHQ7XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoY3VycmVudEl0ZW0gPCBsZWZ0KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBtaW5JbmRleCA9IGN1cnJlbnRJbmRleCArIDE7XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoY3VycmVudEl0ZW0gPiByaWdodCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgbWF4SW5kZXggPSBjdXJyZW50SW5kZXggLSAxO1xuICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIGFzY2VuZGluZyhhLCBiKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGEgPiBiID8gMSA6IC0xO1xuICAgICAgICAgICAgfVxuICAgICAgICB9LCB7fV0sIDE3OiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge1xuICAgICAgICAgICAgdmFyIGFwcGx5UHJvcGVydGllcyA9IHJlcXVpcmUoXCIuL2FwcGx5LXByb3BlcnRpZXNcIik7XG5cbiAgICAgICAgICAgIHZhciBpc1dpZGdldCA9IHJlcXVpcmUoXCIuLi92bm9kZS9pcy13aWRnZXQuanNcIik7XG4gICAgICAgICAgICB2YXIgVlBhdGNoID0gcmVxdWlyZShcIi4uL3Zub2RlL3ZwYXRjaC5qc1wiKTtcblxuICAgICAgICAgICAgdmFyIHVwZGF0ZVdpZGdldCA9IHJlcXVpcmUoXCIuL3VwZGF0ZS13aWRnZXRcIik7XG5cbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gYXBwbHlQYXRjaDtcblxuICAgICAgICAgICAgZnVuY3Rpb24gYXBwbHlQYXRjaCh2cGF0Y2gsIGRvbU5vZGUsIHJlbmRlck9wdGlvbnMpIHtcbiAgICAgICAgICAgICAgICB2YXIgdHlwZSA9IHZwYXRjaC50eXBlO1xuICAgICAgICAgICAgICAgIHZhciB2Tm9kZSA9IHZwYXRjaC52Tm9kZTtcbiAgICAgICAgICAgICAgICB2YXIgcGF0Y2ggPSB2cGF0Y2gucGF0Y2g7XG5cbiAgICAgICAgICAgICAgICBzd2l0Y2ggKHR5cGUpIHtcbiAgICAgICAgICAgICAgICAgICAgY2FzZSBWUGF0Y2guUkVNT1ZFOlxuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHJlbW92ZU5vZGUoZG9tTm9kZSwgdk5vZGUpO1xuICAgICAgICAgICAgICAgICAgICBjYXNlIFZQYXRjaC5JTlNFUlQ6XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gaW5zZXJ0Tm9kZShkb21Ob2RlLCBwYXRjaCwgcmVuZGVyT3B0aW9ucyk7XG4gICAgICAgICAgICAgICAgICAgIGNhc2UgVlBhdGNoLlZURVhUOlxuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHN0cmluZ1BhdGNoKGRvbU5vZGUsIHZOb2RlLCBwYXRjaCwgcmVuZGVyT3B0aW9ucyk7XG4gICAgICAgICAgICAgICAgICAgIGNhc2UgVlBhdGNoLldJREdFVDpcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiB3aWRnZXRQYXRjaChkb21Ob2RlLCB2Tm9kZSwgcGF0Y2gsIHJlbmRlck9wdGlvbnMpO1xuICAgICAgICAgICAgICAgICAgICBjYXNlIFZQYXRjaC5WTk9ERTpcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiB2Tm9kZVBhdGNoKGRvbU5vZGUsIHZOb2RlLCBwYXRjaCwgcmVuZGVyT3B0aW9ucyk7XG4gICAgICAgICAgICAgICAgICAgIGNhc2UgVlBhdGNoLk9SREVSOlxuICAgICAgICAgICAgICAgICAgICAgICAgcmVvcmRlckNoaWxkcmVuKGRvbU5vZGUsIHBhdGNoKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBkb21Ob2RlO1xuICAgICAgICAgICAgICAgICAgICBjYXNlIFZQYXRjaC5QUk9QUzpcbiAgICAgICAgICAgICAgICAgICAgICAgIGFwcGx5UHJvcGVydGllcyhkb21Ob2RlLCBwYXRjaCwgdk5vZGUucHJvcGVydGllcyk7XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gZG9tTm9kZTtcbiAgICAgICAgICAgICAgICAgICAgY2FzZSBWUGF0Y2guVEhVTks6XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gcmVwbGFjZVJvb3QoZG9tTm9kZSwgcmVuZGVyT3B0aW9ucy5wYXRjaChkb21Ob2RlLCBwYXRjaCwgcmVuZGVyT3B0aW9ucykpO1xuICAgICAgICAgICAgICAgICAgICBkZWZhdWx0OlxuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGRvbU5vZGU7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBmdW5jdGlvbiByZW1vdmVOb2RlKGRvbU5vZGUsIHZOb2RlKSB7XG4gICAgICAgICAgICAgICAgdmFyIHBhcmVudE5vZGUgPSBkb21Ob2RlLnBhcmVudE5vZGU7XG5cbiAgICAgICAgICAgICAgICBpZiAocGFyZW50Tm9kZSkge1xuICAgICAgICAgICAgICAgICAgICBwYXJlbnROb2RlLnJlbW92ZUNoaWxkKGRvbU5vZGUpO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIGRlc3Ryb3lXaWRnZXQoZG9tTm9kZSwgdk5vZGUpO1xuXG4gICAgICAgICAgICAgICAgcmV0dXJuIG51bGw7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIGluc2VydE5vZGUocGFyZW50Tm9kZSwgdk5vZGUsIHJlbmRlck9wdGlvbnMpIHtcbiAgICAgICAgICAgICAgICB2YXIgbmV3Tm9kZSA9IHJlbmRlck9wdGlvbnMucmVuZGVyKHZOb2RlLCByZW5kZXJPcHRpb25zKTtcblxuICAgICAgICAgICAgICAgIGlmIChwYXJlbnROb2RlKSB7XG4gICAgICAgICAgICAgICAgICAgIHBhcmVudE5vZGUuYXBwZW5kQ2hpbGQobmV3Tm9kZSk7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgcmV0dXJuIHBhcmVudE5vZGU7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIHN0cmluZ1BhdGNoKGRvbU5vZGUsIGxlZnRWTm9kZSwgdlRleHQsIHJlbmRlck9wdGlvbnMpIHtcbiAgICAgICAgICAgICAgICB2YXIgbmV3Tm9kZTtcblxuICAgICAgICAgICAgICAgIGlmIChkb21Ob2RlLm5vZGVUeXBlID09PSAzKSB7XG4gICAgICAgICAgICAgICAgICAgIGRvbU5vZGUucmVwbGFjZURhdGEoMCwgZG9tTm9kZS5sZW5ndGgsIHZUZXh0LnRleHQpO1xuICAgICAgICAgICAgICAgICAgICBuZXdOb2RlID0gZG9tTm9kZTtcbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICB2YXIgcGFyZW50Tm9kZSA9IGRvbU5vZGUucGFyZW50Tm9kZTtcbiAgICAgICAgICAgICAgICAgICAgbmV3Tm9kZSA9IHJlbmRlck9wdGlvbnMucmVuZGVyKHZUZXh0LCByZW5kZXJPcHRpb25zKTtcblxuICAgICAgICAgICAgICAgICAgICBpZiAocGFyZW50Tm9kZSAmJiBuZXdOb2RlICE9PSBkb21Ob2RlKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBwYXJlbnROb2RlLnJlcGxhY2VDaGlsZChuZXdOb2RlLCBkb21Ob2RlKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHJldHVybiBuZXdOb2RlO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBmdW5jdGlvbiB3aWRnZXRQYXRjaChkb21Ob2RlLCBsZWZ0Vk5vZGUsIHdpZGdldCwgcmVuZGVyT3B0aW9ucykge1xuICAgICAgICAgICAgICAgIHZhciB1cGRhdGluZyA9IHVwZGF0ZVdpZGdldChsZWZ0Vk5vZGUsIHdpZGdldCk7XG4gICAgICAgICAgICAgICAgdmFyIG5ld05vZGU7XG5cbiAgICAgICAgICAgICAgICBpZiAodXBkYXRpbmcpIHtcbiAgICAgICAgICAgICAgICAgICAgbmV3Tm9kZSA9IHdpZGdldC51cGRhdGUobGVmdFZOb2RlLCBkb21Ob2RlKSB8fCBkb21Ob2RlO1xuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIG5ld05vZGUgPSByZW5kZXJPcHRpb25zLnJlbmRlcih3aWRnZXQsIHJlbmRlck9wdGlvbnMpO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHZhciBwYXJlbnROb2RlID0gZG9tTm9kZS5wYXJlbnROb2RlO1xuXG4gICAgICAgICAgICAgICAgaWYgKHBhcmVudE5vZGUgJiYgbmV3Tm9kZSAhPT0gZG9tTm9kZSkge1xuICAgICAgICAgICAgICAgICAgICBwYXJlbnROb2RlLnJlcGxhY2VDaGlsZChuZXdOb2RlLCBkb21Ob2RlKTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICBpZiAoIXVwZGF0aW5nKSB7XG4gICAgICAgICAgICAgICAgICAgIGRlc3Ryb3lXaWRnZXQoZG9tTm9kZSwgbGVmdFZOb2RlKTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICByZXR1cm4gbmV3Tm9kZTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZnVuY3Rpb24gdk5vZGVQYXRjaChkb21Ob2RlLCBsZWZ0Vk5vZGUsIHZOb2RlLCByZW5kZXJPcHRpb25zKSB7XG4gICAgICAgICAgICAgICAgdmFyIHBhcmVudE5vZGUgPSBkb21Ob2RlLnBhcmVudE5vZGU7XG4gICAgICAgICAgICAgICAgdmFyIG5ld05vZGUgPSByZW5kZXJPcHRpb25zLnJlbmRlcih2Tm9kZSwgcmVuZGVyT3B0aW9ucyk7XG5cbiAgICAgICAgICAgICAgICBpZiAocGFyZW50Tm9kZSAmJiBuZXdOb2RlICE9PSBkb21Ob2RlKSB7XG4gICAgICAgICAgICAgICAgICAgIHBhcmVudE5vZGUucmVwbGFjZUNoaWxkKG5ld05vZGUsIGRvbU5vZGUpO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHJldHVybiBuZXdOb2RlO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBmdW5jdGlvbiBkZXN0cm95V2lkZ2V0KGRvbU5vZGUsIHcpIHtcbiAgICAgICAgICAgICAgICBpZiAodHlwZW9mIHcuZGVzdHJveSA9PT0gXCJmdW5jdGlvblwiICYmIGlzV2lkZ2V0KHcpKSB7XG4gICAgICAgICAgICAgICAgICAgIHcuZGVzdHJveShkb21Ob2RlKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIHJlb3JkZXJDaGlsZHJlbihkb21Ob2RlLCBtb3Zlcykge1xuICAgICAgICAgICAgICAgIHZhciBjaGlsZE5vZGVzID0gZG9tTm9kZS5jaGlsZE5vZGVzO1xuICAgICAgICAgICAgICAgIHZhciBrZXlNYXAgPSB7fTtcbiAgICAgICAgICAgICAgICB2YXIgbm9kZTtcbiAgICAgICAgICAgICAgICB2YXIgcmVtb3ZlO1xuICAgICAgICAgICAgICAgIHZhciBpbnNlcnQ7XG5cbiAgICAgICAgICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IG1vdmVzLnJlbW92ZXMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgICAgICAgICAgcmVtb3ZlID0gbW92ZXMucmVtb3Zlc1tpXTtcbiAgICAgICAgICAgICAgICAgICAgbm9kZSA9IGNoaWxkTm9kZXNbcmVtb3ZlLmZyb21dO1xuICAgICAgICAgICAgICAgICAgICBpZiAocmVtb3ZlLmtleSkge1xuICAgICAgICAgICAgICAgICAgICAgICAga2V5TWFwW3JlbW92ZS5rZXldID0gbm9kZTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICBkb21Ob2RlLnJlbW92ZUNoaWxkKG5vZGUpO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHZhciBsZW5ndGggPSBjaGlsZE5vZGVzLmxlbmd0aDtcbiAgICAgICAgICAgICAgICBmb3IgKHZhciBqID0gMDsgaiA8IG1vdmVzLmluc2VydHMubGVuZ3RoOyBqKyspIHtcbiAgICAgICAgICAgICAgICAgICAgaW5zZXJ0ID0gbW92ZXMuaW5zZXJ0c1tqXTtcbiAgICAgICAgICAgICAgICAgICAgbm9kZSA9IGtleU1hcFtpbnNlcnQua2V5XTtcbiAgICAgICAgICAgICAgICAgICAgLy8gdGhpcyBpcyB0aGUgd2VpcmRlc3QgYnVnIGkndmUgZXZlciBzZWVuIGluIHdlYmtpdFxuICAgICAgICAgICAgICAgICAgICBkb21Ob2RlLmluc2VydEJlZm9yZShub2RlLCBpbnNlcnQudG8gPj0gbGVuZ3RoKysgPyBudWxsIDogY2hpbGROb2Rlc1tpbnNlcnQudG9dKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIHJlcGxhY2VSb290KG9sZFJvb3QsIG5ld1Jvb3QpIHtcbiAgICAgICAgICAgICAgICBpZiAob2xkUm9vdCAmJiBuZXdSb290ICYmIG9sZFJvb3QgIT09IG5ld1Jvb3QgJiYgb2xkUm9vdC5wYXJlbnROb2RlKSB7XG4gICAgICAgICAgICAgICAgICAgIG9sZFJvb3QucGFyZW50Tm9kZS5yZXBsYWNlQ2hpbGQobmV3Um9vdCwgb2xkUm9vdCk7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgcmV0dXJuIG5ld1Jvb3Q7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0sIHsgXCIuLi92bm9kZS9pcy13aWRnZXQuanNcIjogMjksIFwiLi4vdm5vZGUvdnBhdGNoLmpzXCI6IDMyLCBcIi4vYXBwbHktcHJvcGVydGllc1wiOiAxNCwgXCIuL3VwZGF0ZS13aWRnZXRcIjogMTkgfV0sIDE4OiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge1xuICAgICAgICAgICAgdmFyIGRvY3VtZW50ID0gcmVxdWlyZShcImdsb2JhbC9kb2N1bWVudFwiKTtcbiAgICAgICAgICAgIHZhciBpc0FycmF5ID0gcmVxdWlyZShcIngtaXMtYXJyYXlcIik7XG5cbiAgICAgICAgICAgIHZhciByZW5kZXIgPSByZXF1aXJlKFwiLi9jcmVhdGUtZWxlbWVudFwiKTtcbiAgICAgICAgICAgIHZhciBkb21JbmRleCA9IHJlcXVpcmUoXCIuL2RvbS1pbmRleFwiKTtcbiAgICAgICAgICAgIHZhciBwYXRjaE9wID0gcmVxdWlyZShcIi4vcGF0Y2gtb3BcIik7XG4gICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IHBhdGNoO1xuXG4gICAgICAgICAgICBmdW5jdGlvbiBwYXRjaChyb290Tm9kZSwgcGF0Y2hlcywgcmVuZGVyT3B0aW9ucykge1xuICAgICAgICAgICAgICAgIHJlbmRlck9wdGlvbnMgPSByZW5kZXJPcHRpb25zIHx8IHt9O1xuICAgICAgICAgICAgICAgIHJlbmRlck9wdGlvbnMucGF0Y2ggPSByZW5kZXJPcHRpb25zLnBhdGNoICYmIHJlbmRlck9wdGlvbnMucGF0Y2ggIT09IHBhdGNoID8gcmVuZGVyT3B0aW9ucy5wYXRjaCA6IHBhdGNoUmVjdXJzaXZlO1xuICAgICAgICAgICAgICAgIHJlbmRlck9wdGlvbnMucmVuZGVyID0gcmVuZGVyT3B0aW9ucy5yZW5kZXIgfHwgcmVuZGVyO1xuXG4gICAgICAgICAgICAgICAgcmV0dXJuIHJlbmRlck9wdGlvbnMucGF0Y2gocm9vdE5vZGUsIHBhdGNoZXMsIHJlbmRlck9wdGlvbnMpO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBmdW5jdGlvbiBwYXRjaFJlY3Vyc2l2ZShyb290Tm9kZSwgcGF0Y2hlcywgcmVuZGVyT3B0aW9ucykge1xuICAgICAgICAgICAgICAgIHZhciBpbmRpY2VzID0gcGF0Y2hJbmRpY2VzKHBhdGNoZXMpO1xuXG4gICAgICAgICAgICAgICAgaWYgKGluZGljZXMubGVuZ3RoID09PSAwKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiByb290Tm9kZTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICB2YXIgaW5kZXggPSBkb21JbmRleChyb290Tm9kZSwgcGF0Y2hlcy5hLCBpbmRpY2VzKTtcbiAgICAgICAgICAgICAgICB2YXIgb3duZXJEb2N1bWVudCA9IHJvb3ROb2RlLm93bmVyRG9jdW1lbnQ7XG5cbiAgICAgICAgICAgICAgICBpZiAoIXJlbmRlck9wdGlvbnMuZG9jdW1lbnQgJiYgb3duZXJEb2N1bWVudCAhPT0gZG9jdW1lbnQpIHtcbiAgICAgICAgICAgICAgICAgICAgcmVuZGVyT3B0aW9ucy5kb2N1bWVudCA9IG93bmVyRG9jdW1lbnQ7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCBpbmRpY2VzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciBub2RlSW5kZXggPSBpbmRpY2VzW2ldO1xuICAgICAgICAgICAgICAgICAgICByb290Tm9kZSA9IGFwcGx5UGF0Y2gocm9vdE5vZGUsIGluZGV4W25vZGVJbmRleF0sIHBhdGNoZXNbbm9kZUluZGV4XSwgcmVuZGVyT3B0aW9ucyk7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgcmV0dXJuIHJvb3ROb2RlO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBmdW5jdGlvbiBhcHBseVBhdGNoKHJvb3ROb2RlLCBkb21Ob2RlLCBwYXRjaExpc3QsIHJlbmRlck9wdGlvbnMpIHtcbiAgICAgICAgICAgICAgICBpZiAoIWRvbU5vZGUpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHJvb3ROb2RlO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHZhciBuZXdOb2RlO1xuXG4gICAgICAgICAgICAgICAgaWYgKGlzQXJyYXkocGF0Y2hMaXN0KSkge1xuICAgICAgICAgICAgICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IHBhdGNoTGlzdC5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgICAgICAgICAgICAgbmV3Tm9kZSA9IHBhdGNoT3AocGF0Y2hMaXN0W2ldLCBkb21Ob2RlLCByZW5kZXJPcHRpb25zKTtcblxuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGRvbU5vZGUgPT09IHJvb3ROb2RlKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcm9vdE5vZGUgPSBuZXdOb2RlO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgbmV3Tm9kZSA9IHBhdGNoT3AocGF0Y2hMaXN0LCBkb21Ob2RlLCByZW5kZXJPcHRpb25zKTtcblxuICAgICAgICAgICAgICAgICAgICBpZiAoZG9tTm9kZSA9PT0gcm9vdE5vZGUpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJvb3ROb2RlID0gbmV3Tm9kZTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHJldHVybiByb290Tm9kZTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZnVuY3Rpb24gcGF0Y2hJbmRpY2VzKHBhdGNoZXMpIHtcbiAgICAgICAgICAgICAgICB2YXIgaW5kaWNlcyA9IFtdO1xuXG4gICAgICAgICAgICAgICAgZm9yICh2YXIga2V5IGluIHBhdGNoZXMpIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKGtleSAhPT0gXCJhXCIpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGluZGljZXMucHVzaChOdW1iZXIoa2V5KSk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICByZXR1cm4gaW5kaWNlcztcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSwgeyBcIi4vY3JlYXRlLWVsZW1lbnRcIjogMTUsIFwiLi9kb20taW5kZXhcIjogMTYsIFwiLi9wYXRjaC1vcFwiOiAxNywgXCJnbG9iYWwvZG9jdW1lbnRcIjogMTAsIFwieC1pcy1hcnJheVwiOiAxMiB9XSwgMTk6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICB2YXIgaXNXaWRnZXQgPSByZXF1aXJlKFwiLi4vdm5vZGUvaXMtd2lkZ2V0LmpzXCIpO1xuXG4gICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IHVwZGF0ZVdpZGdldDtcblxuICAgICAgICAgICAgZnVuY3Rpb24gdXBkYXRlV2lkZ2V0KGEsIGIpIHtcbiAgICAgICAgICAgICAgICBpZiAoaXNXaWRnZXQoYSkgJiYgaXNXaWRnZXQoYikpIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKFwibmFtZVwiIGluIGEgJiYgXCJuYW1lXCIgaW4gYikge1xuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGEuaWQgPT09IGIuaWQ7XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gYS5pbml0ID09PSBiLmluaXQ7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0sIHsgXCIuLi92bm9kZS9pcy13aWRnZXQuanNcIjogMjkgfV0sIDIwOiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge1xuICAgICAgICAgICAgXCJ1c2Ugc3RyaWN0XCI7XG5cbiAgICAgICAgICAgIHZhciBFdlN0b3JlID0gcmVxdWlyZShcImV2LXN0b3JlXCIpO1xuXG4gICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IEV2SG9vaztcblxuICAgICAgICAgICAgZnVuY3Rpb24gRXZIb29rKHZhbHVlKSB7XG4gICAgICAgICAgICAgICAgaWYgKCEodGhpcyBpbnN0YW5jZW9mIEV2SG9vaykpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIG5ldyBFdkhvb2sodmFsdWUpO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHRoaXMudmFsdWUgPSB2YWx1ZTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgRXZIb29rLnByb3RvdHlwZS5ob29rID0gZnVuY3Rpb24gKG5vZGUsIHByb3BlcnR5TmFtZSkge1xuICAgICAgICAgICAgICAgIHZhciBlcyA9IEV2U3RvcmUobm9kZSk7XG4gICAgICAgICAgICAgICAgdmFyIHByb3BOYW1lID0gcHJvcGVydHlOYW1lLnN1YnN0cigzKTtcblxuICAgICAgICAgICAgICAgIGVzW3Byb3BOYW1lXSA9IHRoaXMudmFsdWU7XG4gICAgICAgICAgICB9O1xuXG4gICAgICAgICAgICBFdkhvb2sucHJvdG90eXBlLnVuaG9vayA9IGZ1bmN0aW9uIChub2RlLCBwcm9wZXJ0eU5hbWUpIHtcbiAgICAgICAgICAgICAgICB2YXIgZXMgPSBFdlN0b3JlKG5vZGUpO1xuICAgICAgICAgICAgICAgIHZhciBwcm9wTmFtZSA9IHByb3BlcnR5TmFtZS5zdWJzdHIoMyk7XG5cbiAgICAgICAgICAgICAgICBlc1twcm9wTmFtZV0gPSB1bmRlZmluZWQ7XG4gICAgICAgICAgICB9O1xuICAgICAgICB9LCB7IFwiZXYtc3RvcmVcIjogNyB9XSwgMjE6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICBcInVzZSBzdHJpY3RcIjtcblxuICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBTb2Z0U2V0SG9vaztcblxuICAgICAgICAgICAgZnVuY3Rpb24gU29mdFNldEhvb2sodmFsdWUpIHtcbiAgICAgICAgICAgICAgICBpZiAoISh0aGlzIGluc3RhbmNlb2YgU29mdFNldEhvb2spKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBuZXcgU29mdFNldEhvb2sodmFsdWUpO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHRoaXMudmFsdWUgPSB2YWx1ZTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgU29mdFNldEhvb2sucHJvdG90eXBlLmhvb2sgPSBmdW5jdGlvbiAobm9kZSwgcHJvcGVydHlOYW1lKSB7XG4gICAgICAgICAgICAgICAgaWYgKG5vZGVbcHJvcGVydHlOYW1lXSAhPT0gdGhpcy52YWx1ZSkge1xuICAgICAgICAgICAgICAgICAgICBub2RlW3Byb3BlcnR5TmFtZV0gPSB0aGlzLnZhbHVlO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH07XG4gICAgICAgIH0sIHt9XSwgMjI6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICBcInVzZSBzdHJpY3RcIjtcblxuICAgICAgICAgICAgdmFyIGlzQXJyYXkgPSByZXF1aXJlKFwieC1pcy1hcnJheVwiKTtcblxuICAgICAgICAgICAgdmFyIFZOb2RlID0gcmVxdWlyZShcIi4uL3Zub2RlL3Zub2RlLmpzXCIpO1xuICAgICAgICAgICAgdmFyIFZUZXh0ID0gcmVxdWlyZShcIi4uL3Zub2RlL3Z0ZXh0LmpzXCIpO1xuICAgICAgICAgICAgdmFyIGlzVk5vZGUgPSByZXF1aXJlKFwiLi4vdm5vZGUvaXMtdm5vZGVcIik7XG4gICAgICAgICAgICB2YXIgaXNWVGV4dCA9IHJlcXVpcmUoXCIuLi92bm9kZS9pcy12dGV4dFwiKTtcbiAgICAgICAgICAgIHZhciBpc1dpZGdldCA9IHJlcXVpcmUoXCIuLi92bm9kZS9pcy13aWRnZXRcIik7XG4gICAgICAgICAgICB2YXIgaXNIb29rID0gcmVxdWlyZShcIi4uL3Zub2RlL2lzLXZob29rXCIpO1xuICAgICAgICAgICAgdmFyIGlzVlRodW5rID0gcmVxdWlyZShcIi4uL3Zub2RlL2lzLXRodW5rXCIpO1xuXG4gICAgICAgICAgICB2YXIgcGFyc2VUYWcgPSByZXF1aXJlKFwiLi9wYXJzZS10YWcuanNcIik7XG4gICAgICAgICAgICB2YXIgc29mdFNldEhvb2sgPSByZXF1aXJlKFwiLi9ob29rcy9zb2Z0LXNldC1ob29rLmpzXCIpO1xuICAgICAgICAgICAgdmFyIGV2SG9vayA9IHJlcXVpcmUoXCIuL2hvb2tzL2V2LWhvb2suanNcIik7XG5cbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gaDtcblxuICAgICAgICAgICAgZnVuY3Rpb24gaCh0YWdOYW1lLCBwcm9wZXJ0aWVzLCBjaGlsZHJlbikge1xuICAgICAgICAgICAgICAgIHZhciBjaGlsZE5vZGVzID0gW107XG4gICAgICAgICAgICAgICAgdmFyIHRhZywgcHJvcHMsIGtleSwgbmFtZXNwYWNlO1xuXG4gICAgICAgICAgICAgICAgaWYgKCFjaGlsZHJlbiAmJiBpc0NoaWxkcmVuKHByb3BlcnRpZXMpKSB7XG4gICAgICAgICAgICAgICAgICAgIGNoaWxkcmVuID0gcHJvcGVydGllcztcbiAgICAgICAgICAgICAgICAgICAgcHJvcHMgPSB7fTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICBwcm9wcyA9IHByb3BzIHx8IHByb3BlcnRpZXMgfHwge307XG4gICAgICAgICAgICAgICAgdGFnID0gcGFyc2VUYWcodGFnTmFtZSwgcHJvcHMpO1xuXG4gICAgICAgICAgICAgICAgLy8gc3VwcG9ydCBrZXlzXG4gICAgICAgICAgICAgICAgaWYgKHByb3BzLmhhc093blByb3BlcnR5KFwia2V5XCIpKSB7XG4gICAgICAgICAgICAgICAgICAgIGtleSA9IHByb3BzLmtleTtcbiAgICAgICAgICAgICAgICAgICAgcHJvcHMua2V5ID0gdW5kZWZpbmVkO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIC8vIHN1cHBvcnQgbmFtZXNwYWNlXG4gICAgICAgICAgICAgICAgaWYgKHByb3BzLmhhc093blByb3BlcnR5KFwibmFtZXNwYWNlXCIpKSB7XG4gICAgICAgICAgICAgICAgICAgIG5hbWVzcGFjZSA9IHByb3BzLm5hbWVzcGFjZTtcbiAgICAgICAgICAgICAgICAgICAgcHJvcHMubmFtZXNwYWNlID0gdW5kZWZpbmVkO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIC8vIGZpeCBjdXJzb3IgYnVnXG4gICAgICAgICAgICAgICAgaWYgKHRhZyA9PT0gXCJJTlBVVFwiICYmICFuYW1lc3BhY2UgJiYgcHJvcHMuaGFzT3duUHJvcGVydHkoXCJ2YWx1ZVwiKSAmJiBwcm9wcy52YWx1ZSAhPT0gdW5kZWZpbmVkICYmICFpc0hvb2socHJvcHMudmFsdWUpKSB7XG4gICAgICAgICAgICAgICAgICAgIHByb3BzLnZhbHVlID0gc29mdFNldEhvb2socHJvcHMudmFsdWUpO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHRyYW5zZm9ybVByb3BlcnRpZXMocHJvcHMpO1xuXG4gICAgICAgICAgICAgICAgaWYgKGNoaWxkcmVuICE9PSB1bmRlZmluZWQgJiYgY2hpbGRyZW4gIT09IG51bGwpIHtcbiAgICAgICAgICAgICAgICAgICAgYWRkQ2hpbGQoY2hpbGRyZW4sIGNoaWxkTm9kZXMsIHRhZywgcHJvcHMpO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHJldHVybiBuZXcgVk5vZGUodGFnLCBwcm9wcywgY2hpbGROb2Rlcywga2V5LCBuYW1lc3BhY2UpO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBmdW5jdGlvbiBhZGRDaGlsZChjLCBjaGlsZE5vZGVzLCB0YWcsIHByb3BzKSB7XG4gICAgICAgICAgICAgICAgaWYgKHR5cGVvZiBjID09PSBcInN0cmluZ1wiKSB7XG4gICAgICAgICAgICAgICAgICAgIGNoaWxkTm9kZXMucHVzaChuZXcgVlRleHQoYykpO1xuICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAodHlwZW9mIGMgPT09IFwibnVtYmVyXCIpIHtcbiAgICAgICAgICAgICAgICAgICAgY2hpbGROb2Rlcy5wdXNoKG5ldyBWVGV4dChTdHJpbmcoYykpKTtcbiAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKGlzQ2hpbGQoYykpIHtcbiAgICAgICAgICAgICAgICAgICAgY2hpbGROb2Rlcy5wdXNoKGMpO1xuICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoaXNBcnJheShjKSkge1xuICAgICAgICAgICAgICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IGMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGFkZENoaWxkKGNbaV0sIGNoaWxkTm9kZXMsIHRhZywgcHJvcHMpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfSBlbHNlIGlmIChjID09PSBudWxsIHx8IGMgPT09IHVuZGVmaW5lZCkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgdGhyb3cgVW5leHBlY3RlZFZpcnR1YWxFbGVtZW50KHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGZvcmVpZ25PYmplY3Q6IGMsXG4gICAgICAgICAgICAgICAgICAgICAgICBwYXJlbnRWbm9kZToge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRhZ05hbWU6IHRhZyxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBwcm9wZXJ0aWVzOiBwcm9wc1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIHRyYW5zZm9ybVByb3BlcnRpZXMocHJvcHMpIHtcbiAgICAgICAgICAgICAgICBmb3IgKHZhciBwcm9wTmFtZSBpbiBwcm9wcykge1xuICAgICAgICAgICAgICAgICAgICBpZiAocHJvcHMuaGFzT3duUHJvcGVydHkocHJvcE5hbWUpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICB2YXIgdmFsdWUgPSBwcm9wc1twcm9wTmFtZV07XG5cbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChpc0hvb2sodmFsdWUpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgY29udGludWU7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChwcm9wTmFtZS5zdWJzdHIoMCwgMykgPT09IFwiZXYtXCIpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBhZGQgZXYtZm9vIHN1cHBvcnRcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBwcm9wc1twcm9wTmFtZV0gPSBldkhvb2sodmFsdWUpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBmdW5jdGlvbiBpc0NoaWxkKHgpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gaXNWTm9kZSh4KSB8fCBpc1ZUZXh0KHgpIHx8IGlzV2lkZ2V0KHgpIHx8IGlzVlRodW5rKHgpO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBmdW5jdGlvbiBpc0NoaWxkcmVuKHgpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gdHlwZW9mIHggPT09IFwic3RyaW5nXCIgfHwgaXNBcnJheSh4KSB8fCBpc0NoaWxkKHgpO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBmdW5jdGlvbiBVbmV4cGVjdGVkVmlydHVhbEVsZW1lbnQoZGF0YSkge1xuICAgICAgICAgICAgICAgIHZhciBlcnIgPSBuZXcgRXJyb3IoKTtcblxuICAgICAgICAgICAgICAgIGVyci50eXBlID0gXCJ2aXJ0dWFsLWh5cGVyc2NyaXB0LnVuZXhwZWN0ZWQudmlydHVhbC1lbGVtZW50XCI7XG4gICAgICAgICAgICAgICAgZXJyLm1lc3NhZ2UgPSBcIlVuZXhwZWN0ZWQgdmlydHVhbCBjaGlsZCBwYXNzZWQgdG8gaCgpLlxcblwiICsgXCJFeHBlY3RlZCBhIFZOb2RlIC8gVnRodW5rIC8gVldpZGdldCAvIHN0cmluZyBidXQ6XFxuXCIgKyBcImdvdDpcXG5cIiArIGVycm9yU3RyaW5nKGRhdGEuZm9yZWlnbk9iamVjdCkgKyBcIi5cXG5cIiArIFwiVGhlIHBhcmVudCB2bm9kZSBpczpcXG5cIiArIGVycm9yU3RyaW5nKGRhdGEucGFyZW50Vm5vZGUpO1xuICAgICAgICAgICAgICAgIFwiXFxuXCIgKyBcIlN1Z2dlc3RlZCBmaXg6IGNoYW5nZSB5b3VyIGBoKC4uLiwgWyAuLi4gXSlgIGNhbGxzaXRlLlwiO1xuICAgICAgICAgICAgICAgIGVyci5mb3JlaWduT2JqZWN0ID0gZGF0YS5mb3JlaWduT2JqZWN0O1xuICAgICAgICAgICAgICAgIGVyci5wYXJlbnRWbm9kZSA9IGRhdGEucGFyZW50Vm5vZGU7XG5cbiAgICAgICAgICAgICAgICByZXR1cm4gZXJyO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBmdW5jdGlvbiBlcnJvclN0cmluZyhvYmopIHtcbiAgICAgICAgICAgICAgICB0cnkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gSlNPTi5zdHJpbmdpZnkob2JqLCBudWxsLCBcIiAgICBcIik7XG4gICAgICAgICAgICAgICAgfSBjYXRjaCAoZSkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gU3RyaW5nKG9iaik7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9LCB7IFwiLi4vdm5vZGUvaXMtdGh1bmtcIjogMjUsIFwiLi4vdm5vZGUvaXMtdmhvb2tcIjogMjYsIFwiLi4vdm5vZGUvaXMtdm5vZGVcIjogMjcsIFwiLi4vdm5vZGUvaXMtdnRleHRcIjogMjgsIFwiLi4vdm5vZGUvaXMtd2lkZ2V0XCI6IDI5LCBcIi4uL3Zub2RlL3Zub2RlLmpzXCI6IDMxLCBcIi4uL3Zub2RlL3Z0ZXh0LmpzXCI6IDMzLCBcIi4vaG9va3MvZXYtaG9vay5qc1wiOiAyMCwgXCIuL2hvb2tzL3NvZnQtc2V0LWhvb2suanNcIjogMjEsIFwiLi9wYXJzZS10YWcuanNcIjogMjMsIFwieC1pcy1hcnJheVwiOiAxMiB9XSwgMjM6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICBcInVzZSBzdHJpY3RcIjtcblxuICAgICAgICAgICAgdmFyIHNwbGl0ID0gcmVxdWlyZShcImJyb3dzZXItc3BsaXRcIik7XG5cbiAgICAgICAgICAgIHZhciBjbGFzc0lkU3BsaXQgPSAvKFtcXC4jXT9bYS16QS1aMC05XFx1MDA3Ri1cXHVGRkZGXzotXSspLztcbiAgICAgICAgICAgIHZhciBub3RDbGFzc0lkID0gL15cXC58Iy87XG5cbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gcGFyc2VUYWc7XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIHBhcnNlVGFnKHRhZywgcHJvcHMpIHtcbiAgICAgICAgICAgICAgICBpZiAoIXRhZykge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gXCJESVZcIjtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICB2YXIgbm9JZCA9ICFwcm9wcy5oYXNPd25Qcm9wZXJ0eShcImlkXCIpO1xuXG4gICAgICAgICAgICAgICAgdmFyIHRhZ1BhcnRzID0gc3BsaXQodGFnLCBjbGFzc0lkU3BsaXQpO1xuICAgICAgICAgICAgICAgIHZhciB0YWdOYW1lID0gbnVsbDtcblxuICAgICAgICAgICAgICAgIGlmIChub3RDbGFzc0lkLnRlc3QodGFnUGFydHNbMV0pKSB7XG4gICAgICAgICAgICAgICAgICAgIHRhZ05hbWUgPSBcIkRJVlwiO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHZhciBjbGFzc2VzLCBwYXJ0LCB0eXBlLCBpO1xuXG4gICAgICAgICAgICAgICAgZm9yIChpID0gMDsgaSA8IHRhZ1BhcnRzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICAgICAgICAgIHBhcnQgPSB0YWdQYXJ0c1tpXTtcblxuICAgICAgICAgICAgICAgICAgICBpZiAoIXBhcnQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnRpbnVlO1xuICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgdHlwZSA9IHBhcnQuY2hhckF0KDApO1xuXG4gICAgICAgICAgICAgICAgICAgIGlmICghdGFnTmFtZSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgdGFnTmFtZSA9IHBhcnQ7XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAodHlwZSA9PT0gXCIuXCIpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGNsYXNzZXMgPSBjbGFzc2VzIHx8IFtdO1xuICAgICAgICAgICAgICAgICAgICAgICAgY2xhc3Nlcy5wdXNoKHBhcnQuc3Vic3RyaW5nKDEsIHBhcnQubGVuZ3RoKSk7XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAodHlwZSA9PT0gXCIjXCIgJiYgbm9JZCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgcHJvcHMuaWQgPSBwYXJ0LnN1YnN0cmluZygxLCBwYXJ0Lmxlbmd0aCk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICBpZiAoY2xhc3Nlcykge1xuICAgICAgICAgICAgICAgICAgICBpZiAocHJvcHMuY2xhc3NOYW1lKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBjbGFzc2VzLnB1c2gocHJvcHMuY2xhc3NOYW1lKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgIHByb3BzLmNsYXNzTmFtZSA9IGNsYXNzZXMuam9pbihcIiBcIik7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgcmV0dXJuIHByb3BzLm5hbWVzcGFjZSA/IHRhZ05hbWUgOiB0YWdOYW1lLnRvVXBwZXJDYXNlKCk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0sIHsgXCJicm93c2VyLXNwbGl0XCI6IDUgfV0sIDI0OiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge1xuICAgICAgICAgICAgdmFyIGlzVk5vZGUgPSByZXF1aXJlKFwiLi9pcy12bm9kZVwiKTtcbiAgICAgICAgICAgIHZhciBpc1ZUZXh0ID0gcmVxdWlyZShcIi4vaXMtdnRleHRcIik7XG4gICAgICAgICAgICB2YXIgaXNXaWRnZXQgPSByZXF1aXJlKFwiLi9pcy13aWRnZXRcIik7XG4gICAgICAgICAgICB2YXIgaXNUaHVuayA9IHJlcXVpcmUoXCIuL2lzLXRodW5rXCIpO1xuXG4gICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IGhhbmRsZVRodW5rO1xuXG4gICAgICAgICAgICBmdW5jdGlvbiBoYW5kbGVUaHVuayhhLCBiKSB7XG4gICAgICAgICAgICAgICAgdmFyIHJlbmRlcmVkQSA9IGE7XG4gICAgICAgICAgICAgICAgdmFyIHJlbmRlcmVkQiA9IGI7XG5cbiAgICAgICAgICAgICAgICBpZiAoaXNUaHVuayhiKSkge1xuICAgICAgICAgICAgICAgICAgICByZW5kZXJlZEIgPSByZW5kZXJUaHVuayhiLCBhKTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICBpZiAoaXNUaHVuayhhKSkge1xuICAgICAgICAgICAgICAgICAgICByZW5kZXJlZEEgPSByZW5kZXJUaHVuayhhLCBudWxsKTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgICAgICAgICBhOiByZW5kZXJlZEEsXG4gICAgICAgICAgICAgICAgICAgIGI6IHJlbmRlcmVkQlxuICAgICAgICAgICAgICAgIH07XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIHJlbmRlclRodW5rKHRodW5rLCBwcmV2aW91cykge1xuICAgICAgICAgICAgICAgIHZhciByZW5kZXJlZFRodW5rID0gdGh1bmsudm5vZGU7XG5cbiAgICAgICAgICAgICAgICBpZiAoIXJlbmRlcmVkVGh1bmspIHtcbiAgICAgICAgICAgICAgICAgICAgcmVuZGVyZWRUaHVuayA9IHRodW5rLnZub2RlID0gdGh1bmsucmVuZGVyKHByZXZpb3VzKTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICBpZiAoIShpc1ZOb2RlKHJlbmRlcmVkVGh1bmspIHx8IGlzVlRleHQocmVuZGVyZWRUaHVuaykgfHwgaXNXaWRnZXQocmVuZGVyZWRUaHVuaykpKSB7XG4gICAgICAgICAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcihcInRodW5rIGRpZCBub3QgcmV0dXJuIGEgdmFsaWQgbm9kZVwiKTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICByZXR1cm4gcmVuZGVyZWRUaHVuaztcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSwgeyBcIi4vaXMtdGh1bmtcIjogMjUsIFwiLi9pcy12bm9kZVwiOiAyNywgXCIuL2lzLXZ0ZXh0XCI6IDI4LCBcIi4vaXMtd2lkZ2V0XCI6IDI5IH1dLCAyNTogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHtcbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gaXNUaHVuaztcblxuICAgICAgICAgICAgZnVuY3Rpb24gaXNUaHVuayh0KSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHQgJiYgdC50eXBlID09PSBcIlRodW5rXCI7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0sIHt9XSwgMjY6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IGlzSG9vaztcblxuICAgICAgICAgICAgZnVuY3Rpb24gaXNIb29rKGhvb2spIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gaG9vayAmJiAodHlwZW9mIGhvb2suaG9vayA9PT0gXCJmdW5jdGlvblwiICYmICFob29rLmhhc093blByb3BlcnR5KFwiaG9va1wiKSB8fCB0eXBlb2YgaG9vay51bmhvb2sgPT09IFwiZnVuY3Rpb25cIiAmJiAhaG9vay5oYXNPd25Qcm9wZXJ0eShcInVuaG9va1wiKSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0sIHt9XSwgMjc6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICB2YXIgdmVyc2lvbiA9IHJlcXVpcmUoXCIuL3ZlcnNpb25cIik7XG5cbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gaXNWaXJ0dWFsTm9kZTtcblxuICAgICAgICAgICAgZnVuY3Rpb24gaXNWaXJ0dWFsTm9kZSh4KSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHggJiYgeC50eXBlID09PSBcIlZpcnR1YWxOb2RlXCIgJiYgeC52ZXJzaW9uID09PSB2ZXJzaW9uO1xuICAgICAgICAgICAgfVxuICAgICAgICB9LCB7IFwiLi92ZXJzaW9uXCI6IDMwIH1dLCAyODogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHtcbiAgICAgICAgICAgIHZhciB2ZXJzaW9uID0gcmVxdWlyZShcIi4vdmVyc2lvblwiKTtcblxuICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBpc1ZpcnR1YWxUZXh0O1xuXG4gICAgICAgICAgICBmdW5jdGlvbiBpc1ZpcnR1YWxUZXh0KHgpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4geCAmJiB4LnR5cGUgPT09IFwiVmlydHVhbFRleHRcIiAmJiB4LnZlcnNpb24gPT09IHZlcnNpb247XG4gICAgICAgICAgICB9XG4gICAgICAgIH0sIHsgXCIuL3ZlcnNpb25cIjogMzAgfV0sIDI5OiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge1xuICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBpc1dpZGdldDtcblxuICAgICAgICAgICAgZnVuY3Rpb24gaXNXaWRnZXQodykge1xuICAgICAgICAgICAgICAgIHJldHVybiB3ICYmIHcudHlwZSA9PT0gXCJXaWRnZXRcIjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSwge31dLCAzMDogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHtcbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gXCIyXCI7XG4gICAgICAgIH0sIHt9XSwgMzE6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICB2YXIgdmVyc2lvbiA9IHJlcXVpcmUoXCIuL3ZlcnNpb25cIik7XG4gICAgICAgICAgICB2YXIgaXNWTm9kZSA9IHJlcXVpcmUoXCIuL2lzLXZub2RlXCIpO1xuICAgICAgICAgICAgdmFyIGlzV2lkZ2V0ID0gcmVxdWlyZShcIi4vaXMtd2lkZ2V0XCIpO1xuICAgICAgICAgICAgdmFyIGlzVGh1bmsgPSByZXF1aXJlKFwiLi9pcy10aHVua1wiKTtcbiAgICAgICAgICAgIHZhciBpc1ZIb29rID0gcmVxdWlyZShcIi4vaXMtdmhvb2tcIik7XG5cbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gVmlydHVhbE5vZGU7XG5cbiAgICAgICAgICAgIHZhciBub1Byb3BlcnRpZXMgPSB7fTtcbiAgICAgICAgICAgIHZhciBub0NoaWxkcmVuID0gW107XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIFZpcnR1YWxOb2RlKHRhZ05hbWUsIHByb3BlcnRpZXMsIGNoaWxkcmVuLCBrZXksIG5hbWVzcGFjZSkge1xuICAgICAgICAgICAgICAgIHRoaXMudGFnTmFtZSA9IHRhZ05hbWU7XG4gICAgICAgICAgICAgICAgdGhpcy5wcm9wZXJ0aWVzID0gcHJvcGVydGllcyB8fCBub1Byb3BlcnRpZXM7XG4gICAgICAgICAgICAgICAgdGhpcy5jaGlsZHJlbiA9IGNoaWxkcmVuIHx8IG5vQ2hpbGRyZW47XG4gICAgICAgICAgICAgICAgdGhpcy5rZXkgPSBrZXkgIT0gbnVsbCA/IFN0cmluZyhrZXkpIDogdW5kZWZpbmVkO1xuICAgICAgICAgICAgICAgIHRoaXMubmFtZXNwYWNlID0gdHlwZW9mIG5hbWVzcGFjZSA9PT0gXCJzdHJpbmdcIiA/IG5hbWVzcGFjZSA6IG51bGw7XG5cbiAgICAgICAgICAgICAgICB2YXIgY291bnQgPSBjaGlsZHJlbiAmJiBjaGlsZHJlbi5sZW5ndGggfHwgMDtcbiAgICAgICAgICAgICAgICB2YXIgZGVzY2VuZGFudHMgPSAwO1xuICAgICAgICAgICAgICAgIHZhciBoYXNXaWRnZXRzID0gZmFsc2U7XG4gICAgICAgICAgICAgICAgdmFyIGhhc1RodW5rcyA9IGZhbHNlO1xuICAgICAgICAgICAgICAgIHZhciBkZXNjZW5kYW50SG9va3MgPSBmYWxzZTtcbiAgICAgICAgICAgICAgICB2YXIgaG9va3M7XG5cbiAgICAgICAgICAgICAgICBmb3IgKHZhciBwcm9wTmFtZSBpbiBwcm9wZXJ0aWVzKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmIChwcm9wZXJ0aWVzLmhhc093blByb3BlcnR5KHByb3BOYW1lKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgdmFyIHByb3BlcnR5ID0gcHJvcGVydGllc1twcm9wTmFtZV07XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoaXNWSG9vayhwcm9wZXJ0eSkgJiYgcHJvcGVydHkudW5ob29rKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKCFob29rcykge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBob29rcyA9IHt9O1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGhvb2tzW3Byb3BOYW1lXSA9IHByb3BlcnR5O1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCBjb3VudDsgaSsrKSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciBjaGlsZCA9IGNoaWxkcmVuW2ldO1xuICAgICAgICAgICAgICAgICAgICBpZiAoaXNWTm9kZShjaGlsZCkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGRlc2NlbmRhbnRzICs9IGNoaWxkLmNvdW50IHx8IDA7XG5cbiAgICAgICAgICAgICAgICAgICAgICAgIGlmICghaGFzV2lkZ2V0cyAmJiBjaGlsZC5oYXNXaWRnZXRzKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaGFzV2lkZ2V0cyA9IHRydWU7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgICAgIGlmICghaGFzVGh1bmtzICYmIGNoaWxkLmhhc1RodW5rcykge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGhhc1RodW5rcyA9IHRydWU7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgICAgIGlmICghZGVzY2VuZGFudEhvb2tzICYmIChjaGlsZC5ob29rcyB8fCBjaGlsZC5kZXNjZW5kYW50SG9va3MpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgZGVzY2VuZGFudEhvb2tzID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIGlmICghaGFzV2lkZ2V0cyAmJiBpc1dpZGdldChjaGlsZCkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmICh0eXBlb2YgY2hpbGQuZGVzdHJveSA9PT0gXCJmdW5jdGlvblwiKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaGFzV2lkZ2V0cyA9IHRydWU7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoIWhhc1RodW5rcyAmJiBpc1RodW5rKGNoaWxkKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgaGFzVGh1bmtzID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHRoaXMuY291bnQgPSBjb3VudCArIGRlc2NlbmRhbnRzO1xuICAgICAgICAgICAgICAgIHRoaXMuaGFzV2lkZ2V0cyA9IGhhc1dpZGdldHM7XG4gICAgICAgICAgICAgICAgdGhpcy5oYXNUaHVua3MgPSBoYXNUaHVua3M7XG4gICAgICAgICAgICAgICAgdGhpcy5ob29rcyA9IGhvb2tzO1xuICAgICAgICAgICAgICAgIHRoaXMuZGVzY2VuZGFudEhvb2tzID0gZGVzY2VuZGFudEhvb2tzO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBWaXJ0dWFsTm9kZS5wcm90b3R5cGUudmVyc2lvbiA9IHZlcnNpb247XG4gICAgICAgICAgICBWaXJ0dWFsTm9kZS5wcm90b3R5cGUudHlwZSA9IFwiVmlydHVhbE5vZGVcIjtcbiAgICAgICAgfSwgeyBcIi4vaXMtdGh1bmtcIjogMjUsIFwiLi9pcy12aG9va1wiOiAyNiwgXCIuL2lzLXZub2RlXCI6IDI3LCBcIi4vaXMtd2lkZ2V0XCI6IDI5LCBcIi4vdmVyc2lvblwiOiAzMCB9XSwgMzI6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICB2YXIgdmVyc2lvbiA9IHJlcXVpcmUoXCIuL3ZlcnNpb25cIik7XG5cbiAgICAgICAgICAgIFZpcnR1YWxQYXRjaC5OT05FID0gMDtcbiAgICAgICAgICAgIFZpcnR1YWxQYXRjaC5WVEVYVCA9IDE7XG4gICAgICAgICAgICBWaXJ0dWFsUGF0Y2guVk5PREUgPSAyO1xuICAgICAgICAgICAgVmlydHVhbFBhdGNoLldJREdFVCA9IDM7XG4gICAgICAgICAgICBWaXJ0dWFsUGF0Y2guUFJPUFMgPSA0O1xuICAgICAgICAgICAgVmlydHVhbFBhdGNoLk9SREVSID0gNTtcbiAgICAgICAgICAgIFZpcnR1YWxQYXRjaC5JTlNFUlQgPSA2O1xuICAgICAgICAgICAgVmlydHVhbFBhdGNoLlJFTU9WRSA9IDc7XG4gICAgICAgICAgICBWaXJ0dWFsUGF0Y2guVEhVTksgPSA4O1xuXG4gICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IFZpcnR1YWxQYXRjaDtcblxuICAgICAgICAgICAgZnVuY3Rpb24gVmlydHVhbFBhdGNoKHR5cGUsIHZOb2RlLCBwYXRjaCkge1xuICAgICAgICAgICAgICAgIHRoaXMudHlwZSA9IE51bWJlcih0eXBlKTtcbiAgICAgICAgICAgICAgICB0aGlzLnZOb2RlID0gdk5vZGU7XG4gICAgICAgICAgICAgICAgdGhpcy5wYXRjaCA9IHBhdGNoO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBWaXJ0dWFsUGF0Y2gucHJvdG90eXBlLnZlcnNpb24gPSB2ZXJzaW9uO1xuICAgICAgICAgICAgVmlydHVhbFBhdGNoLnByb3RvdHlwZS50eXBlID0gXCJWaXJ0dWFsUGF0Y2hcIjtcbiAgICAgICAgfSwgeyBcIi4vdmVyc2lvblwiOiAzMCB9XSwgMzM6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICB2YXIgdmVyc2lvbiA9IHJlcXVpcmUoXCIuL3ZlcnNpb25cIik7XG5cbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gVmlydHVhbFRleHQ7XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIFZpcnR1YWxUZXh0KHRleHQpIHtcbiAgICAgICAgICAgICAgICB0aGlzLnRleHQgPSBTdHJpbmcodGV4dCk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIFZpcnR1YWxUZXh0LnByb3RvdHlwZS52ZXJzaW9uID0gdmVyc2lvbjtcbiAgICAgICAgICAgIFZpcnR1YWxUZXh0LnByb3RvdHlwZS50eXBlID0gXCJWaXJ0dWFsVGV4dFwiO1xuICAgICAgICB9LCB7IFwiLi92ZXJzaW9uXCI6IDMwIH1dLCAzNDogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHtcbiAgICAgICAgICAgIHZhciBpc09iamVjdCA9IHJlcXVpcmUoXCJpcy1vYmplY3RcIik7XG4gICAgICAgICAgICB2YXIgaXNIb29rID0gcmVxdWlyZShcIi4uL3Zub2RlL2lzLXZob29rXCIpO1xuXG4gICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IGRpZmZQcm9wcztcblxuICAgICAgICAgICAgZnVuY3Rpb24gZGlmZlByb3BzKGEsIGIpIHtcbiAgICAgICAgICAgICAgICB2YXIgZGlmZjtcblxuICAgICAgICAgICAgICAgIGZvciAodmFyIGFLZXkgaW4gYSkge1xuICAgICAgICAgICAgICAgICAgICBpZiAoIShhS2V5IGluIGIpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBkaWZmID0gZGlmZiB8fCB7fTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGRpZmZbYUtleV0gPSB1bmRlZmluZWQ7XG4gICAgICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgICAgICB2YXIgYVZhbHVlID0gYVthS2V5XTtcbiAgICAgICAgICAgICAgICAgICAgdmFyIGJWYWx1ZSA9IGJbYUtleV07XG5cbiAgICAgICAgICAgICAgICAgICAgaWYgKGFWYWx1ZSA9PT0gYlZhbHVlKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBjb250aW51ZTtcbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIGlmIChpc09iamVjdChhVmFsdWUpICYmIGlzT2JqZWN0KGJWYWx1ZSkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChnZXRQcm90b3R5cGUoYlZhbHVlKSAhPT0gZ2V0UHJvdG90eXBlKGFWYWx1ZSkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBkaWZmID0gZGlmZiB8fCB7fTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBkaWZmW2FLZXldID0gYlZhbHVlO1xuICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIGlmIChpc0hvb2soYlZhbHVlKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRpZmYgPSBkaWZmIHx8IHt9O1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRpZmZbYUtleV0gPSBiVmFsdWU7XG4gICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZhciBvYmplY3REaWZmID0gZGlmZlByb3BzKGFWYWx1ZSwgYlZhbHVlKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAob2JqZWN0RGlmZikge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBkaWZmID0gZGlmZiB8fCB7fTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZGlmZlthS2V5XSA9IG9iamVjdERpZmY7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgZGlmZiA9IGRpZmYgfHwge307XG4gICAgICAgICAgICAgICAgICAgICAgICBkaWZmW2FLZXldID0gYlZhbHVlO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgZm9yICh2YXIgYktleSBpbiBiKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmICghKGJLZXkgaW4gYSkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGRpZmYgPSBkaWZmIHx8IHt9O1xuICAgICAgICAgICAgICAgICAgICAgICAgZGlmZltiS2V5XSA9IGJbYktleV07XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICByZXR1cm4gZGlmZjtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZnVuY3Rpb24gZ2V0UHJvdG90eXBlKHZhbHVlKSB7XG4gICAgICAgICAgICAgICAgaWYgKE9iamVjdC5nZXRQcm90b3R5cGVPZikge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gT2JqZWN0LmdldFByb3RvdHlwZU9mKHZhbHVlKTtcbiAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKHZhbHVlLl9fcHJvdG9fXykge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gdmFsdWUuX19wcm90b19fO1xuICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAodmFsdWUuY29uc3RydWN0b3IpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHZhbHVlLmNvbnN0cnVjdG9yLnByb3RvdHlwZTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH0sIHsgXCIuLi92bm9kZS9pcy12aG9va1wiOiAyNiwgXCJpcy1vYmplY3RcIjogMTEgfV0sIDM1OiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge1xuICAgICAgICAgICAgdmFyIGlzQXJyYXkgPSByZXF1aXJlKFwieC1pcy1hcnJheVwiKTtcblxuICAgICAgICAgICAgdmFyIFZQYXRjaCA9IHJlcXVpcmUoXCIuLi92bm9kZS92cGF0Y2hcIik7XG4gICAgICAgICAgICB2YXIgaXNWTm9kZSA9IHJlcXVpcmUoXCIuLi92bm9kZS9pcy12bm9kZVwiKTtcbiAgICAgICAgICAgIHZhciBpc1ZUZXh0ID0gcmVxdWlyZShcIi4uL3Zub2RlL2lzLXZ0ZXh0XCIpO1xuICAgICAgICAgICAgdmFyIGlzV2lkZ2V0ID0gcmVxdWlyZShcIi4uL3Zub2RlL2lzLXdpZGdldFwiKTtcbiAgICAgICAgICAgIHZhciBpc1RodW5rID0gcmVxdWlyZShcIi4uL3Zub2RlL2lzLXRodW5rXCIpO1xuICAgICAgICAgICAgdmFyIGhhbmRsZVRodW5rID0gcmVxdWlyZShcIi4uL3Zub2RlL2hhbmRsZS10aHVua1wiKTtcblxuICAgICAgICAgICAgdmFyIGRpZmZQcm9wcyA9IHJlcXVpcmUoXCIuL2RpZmYtcHJvcHNcIik7XG5cbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gZGlmZjtcblxuICAgICAgICAgICAgZnVuY3Rpb24gZGlmZihhLCBiKSB7XG4gICAgICAgICAgICAgICAgdmFyIHBhdGNoID0geyBhOiBhIH07XG4gICAgICAgICAgICAgICAgd2FsayhhLCBiLCBwYXRjaCwgMCk7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHBhdGNoO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBmdW5jdGlvbiB3YWxrKGEsIGIsIHBhdGNoLCBpbmRleCkge1xuICAgICAgICAgICAgICAgIGlmIChhID09PSBiKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICB2YXIgYXBwbHkgPSBwYXRjaFtpbmRleF07XG4gICAgICAgICAgICAgICAgdmFyIGFwcGx5Q2xlYXIgPSBmYWxzZTtcblxuICAgICAgICAgICAgICAgIGlmIChpc1RodW5rKGEpIHx8IGlzVGh1bmsoYikpIHtcbiAgICAgICAgICAgICAgICAgICAgdGh1bmtzKGEsIGIsIHBhdGNoLCBpbmRleCk7XG4gICAgICAgICAgICAgICAgfSBlbHNlIGlmIChiID09IG51bGwpIHtcblxuICAgICAgICAgICAgICAgICAgICAvLyBJZiBhIGlzIGEgd2lkZ2V0IHdlIHdpbGwgYWRkIGEgcmVtb3ZlIHBhdGNoIGZvciBpdFxuICAgICAgICAgICAgICAgICAgICAvLyBPdGhlcndpc2UgYW55IGNoaWxkIHdpZGdldHMvaG9va3MgbXVzdCBiZSBkZXN0cm95ZWQuXG4gICAgICAgICAgICAgICAgICAgIC8vIFRoaXMgcHJldmVudHMgYWRkaW5nIHR3byByZW1vdmUgcGF0Y2hlcyBmb3IgYSB3aWRnZXQuXG4gICAgICAgICAgICAgICAgICAgIGlmICghaXNXaWRnZXQoYSkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGNsZWFyU3RhdGUoYSwgcGF0Y2gsIGluZGV4KTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGFwcGx5ID0gcGF0Y2hbaW5kZXhdO1xuICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgYXBwbHkgPSBhcHBlbmRQYXRjaChhcHBseSwgbmV3IFZQYXRjaChWUGF0Y2guUkVNT1ZFLCBhLCBiKSk7XG4gICAgICAgICAgICAgICAgfSBlbHNlIGlmIChpc1ZOb2RlKGIpKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmIChpc1ZOb2RlKGEpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoYS50YWdOYW1lID09PSBiLnRhZ05hbWUgJiYgYS5uYW1lc3BhY2UgPT09IGIubmFtZXNwYWNlICYmIGEua2V5ID09PSBiLmtleSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZhciBwcm9wc1BhdGNoID0gZGlmZlByb3BzKGEucHJvcGVydGllcywgYi5wcm9wZXJ0aWVzKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAocHJvcHNQYXRjaCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBhcHBseSA9IGFwcGVuZFBhdGNoKGFwcGx5LCBuZXcgVlBhdGNoKFZQYXRjaC5QUk9QUywgYSwgcHJvcHNQYXRjaCkpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBhcHBseSA9IGRpZmZDaGlsZHJlbihhLCBiLCBwYXRjaCwgYXBwbHksIGluZGV4KTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgYXBwbHkgPSBhcHBlbmRQYXRjaChhcHBseSwgbmV3IFZQYXRjaChWUGF0Y2guVk5PREUsIGEsIGIpKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBhcHBseUNsZWFyID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGFwcGx5ID0gYXBwZW5kUGF0Y2goYXBwbHksIG5ldyBWUGF0Y2goVlBhdGNoLlZOT0RFLCBhLCBiKSk7XG4gICAgICAgICAgICAgICAgICAgICAgICBhcHBseUNsZWFyID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoaXNWVGV4dChiKSkge1xuICAgICAgICAgICAgICAgICAgICBpZiAoIWlzVlRleHQoYSkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGFwcGx5ID0gYXBwZW5kUGF0Y2goYXBwbHksIG5ldyBWUGF0Y2goVlBhdGNoLlZURVhULCBhLCBiKSk7XG4gICAgICAgICAgICAgICAgICAgICAgICBhcHBseUNsZWFyID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIGlmIChhLnRleHQgIT09IGIudGV4dCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgYXBwbHkgPSBhcHBlbmRQYXRjaChhcHBseSwgbmV3IFZQYXRjaChWUGF0Y2guVlRFWFQsIGEsIGIpKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoaXNXaWRnZXQoYikpIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKCFpc1dpZGdldChhKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgYXBwbHlDbGVhciA9IHRydWU7XG4gICAgICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgICAgICBhcHBseSA9IGFwcGVuZFBhdGNoKGFwcGx5LCBuZXcgVlBhdGNoKFZQYXRjaC5XSURHRVQsIGEsIGIpKTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICBpZiAoYXBwbHkpIHtcbiAgICAgICAgICAgICAgICAgICAgcGF0Y2hbaW5kZXhdID0gYXBwbHk7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgaWYgKGFwcGx5Q2xlYXIpIHtcbiAgICAgICAgICAgICAgICAgICAgY2xlYXJTdGF0ZShhLCBwYXRjaCwgaW5kZXgpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZnVuY3Rpb24gZGlmZkNoaWxkcmVuKGEsIGIsIHBhdGNoLCBhcHBseSwgaW5kZXgpIHtcbiAgICAgICAgICAgICAgICB2YXIgYUNoaWxkcmVuID0gYS5jaGlsZHJlbjtcbiAgICAgICAgICAgICAgICB2YXIgb3JkZXJlZFNldCA9IHJlb3JkZXIoYUNoaWxkcmVuLCBiLmNoaWxkcmVuKTtcbiAgICAgICAgICAgICAgICB2YXIgYkNoaWxkcmVuID0gb3JkZXJlZFNldC5jaGlsZHJlbjtcblxuICAgICAgICAgICAgICAgIHZhciBhTGVuID0gYUNoaWxkcmVuLmxlbmd0aDtcbiAgICAgICAgICAgICAgICB2YXIgYkxlbiA9IGJDaGlsZHJlbi5sZW5ndGg7XG4gICAgICAgICAgICAgICAgdmFyIGxlbiA9IGFMZW4gPiBiTGVuID8gYUxlbiA6IGJMZW47XG5cbiAgICAgICAgICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IGxlbjsgaSsrKSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciBsZWZ0Tm9kZSA9IGFDaGlsZHJlbltpXTtcbiAgICAgICAgICAgICAgICAgICAgdmFyIHJpZ2h0Tm9kZSA9IGJDaGlsZHJlbltpXTtcbiAgICAgICAgICAgICAgICAgICAgaW5kZXggKz0gMTtcblxuICAgICAgICAgICAgICAgICAgICBpZiAoIWxlZnROb2RlKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAocmlnaHROb2RlKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gRXhjZXNzIG5vZGVzIGluIGIgbmVlZCB0byBiZSBhZGRlZFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGFwcGx5ID0gYXBwZW5kUGF0Y2goYXBwbHksIG5ldyBWUGF0Y2goVlBhdGNoLklOU0VSVCwgbnVsbCwgcmlnaHROb2RlKSk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICB3YWxrKGxlZnROb2RlLCByaWdodE5vZGUsIHBhdGNoLCBpbmRleCk7XG4gICAgICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgICAgICBpZiAoaXNWTm9kZShsZWZ0Tm9kZSkgJiYgbGVmdE5vZGUuY291bnQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGluZGV4ICs9IGxlZnROb2RlLmNvdW50O1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgaWYgKG9yZGVyZWRTZXQubW92ZXMpIHtcbiAgICAgICAgICAgICAgICAgICAgLy8gUmVvcmRlciBub2RlcyBsYXN0XG4gICAgICAgICAgICAgICAgICAgIGFwcGx5ID0gYXBwZW5kUGF0Y2goYXBwbHksIG5ldyBWUGF0Y2goVlBhdGNoLk9SREVSLCBhLCBvcmRlcmVkU2V0Lm1vdmVzKSk7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgcmV0dXJuIGFwcGx5O1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBmdW5jdGlvbiBjbGVhclN0YXRlKHZOb2RlLCBwYXRjaCwgaW5kZXgpIHtcbiAgICAgICAgICAgICAgICAvLyBUT0RPOiBNYWtlIHRoaXMgYSBzaW5nbGUgd2Fsaywgbm90IHR3b1xuICAgICAgICAgICAgICAgIHVuaG9vayh2Tm9kZSwgcGF0Y2gsIGluZGV4KTtcbiAgICAgICAgICAgICAgICBkZXN0cm95V2lkZ2V0cyh2Tm9kZSwgcGF0Y2gsIGluZGV4KTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgLy8gUGF0Y2ggcmVjb3JkcyBmb3IgYWxsIGRlc3Ryb3llZCB3aWRnZXRzIG11c3QgYmUgYWRkZWQgYmVjYXVzZSB3ZSBuZWVkXG4gICAgICAgICAgICAvLyBhIERPTSBub2RlIHJlZmVyZW5jZSBmb3IgdGhlIGRlc3Ryb3kgZnVuY3Rpb25cbiAgICAgICAgICAgIGZ1bmN0aW9uIGRlc3Ryb3lXaWRnZXRzKHZOb2RlLCBwYXRjaCwgaW5kZXgpIHtcbiAgICAgICAgICAgICAgICBpZiAoaXNXaWRnZXQodk5vZGUpKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmICh0eXBlb2Ygdk5vZGUuZGVzdHJveSA9PT0gXCJmdW5jdGlvblwiKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBwYXRjaFtpbmRleF0gPSBhcHBlbmRQYXRjaChwYXRjaFtpbmRleF0sIG5ldyBWUGF0Y2goVlBhdGNoLlJFTU9WRSwgdk5vZGUsIG51bGwpKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoaXNWTm9kZSh2Tm9kZSkgJiYgKHZOb2RlLmhhc1dpZGdldHMgfHwgdk5vZGUuaGFzVGh1bmtzKSkge1xuICAgICAgICAgICAgICAgICAgICB2YXIgY2hpbGRyZW4gPSB2Tm9kZS5jaGlsZHJlbjtcbiAgICAgICAgICAgICAgICAgICAgdmFyIGxlbiA9IGNoaWxkcmVuLmxlbmd0aDtcbiAgICAgICAgICAgICAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCBsZW47IGkrKykge1xuICAgICAgICAgICAgICAgICAgICAgICAgdmFyIGNoaWxkID0gY2hpbGRyZW5baV07XG4gICAgICAgICAgICAgICAgICAgICAgICBpbmRleCArPSAxO1xuXG4gICAgICAgICAgICAgICAgICAgICAgICBkZXN0cm95V2lkZ2V0cyhjaGlsZCwgcGF0Y2gsIGluZGV4KTtcblxuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGlzVk5vZGUoY2hpbGQpICYmIGNoaWxkLmNvdW50KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaW5kZXggKz0gY2hpbGQuY291bnQ7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKGlzVGh1bmsodk5vZGUpKSB7XG4gICAgICAgICAgICAgICAgICAgIHRodW5rcyh2Tm9kZSwgbnVsbCwgcGF0Y2gsIGluZGV4KTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIC8vIENyZWF0ZSBhIHN1Yi1wYXRjaCBmb3IgdGh1bmtzXG4gICAgICAgICAgICBmdW5jdGlvbiB0aHVua3MoYSwgYiwgcGF0Y2gsIGluZGV4KSB7XG4gICAgICAgICAgICAgICAgdmFyIG5vZGVzID0gaGFuZGxlVGh1bmsoYSwgYik7XG4gICAgICAgICAgICAgICAgdmFyIHRodW5rUGF0Y2ggPSBkaWZmKG5vZGVzLmEsIG5vZGVzLmIpO1xuICAgICAgICAgICAgICAgIGlmIChoYXNQYXRjaGVzKHRodW5rUGF0Y2gpKSB7XG4gICAgICAgICAgICAgICAgICAgIHBhdGNoW2luZGV4XSA9IG5ldyBWUGF0Y2goVlBhdGNoLlRIVU5LLCBudWxsLCB0aHVua1BhdGNoKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIGhhc1BhdGNoZXMocGF0Y2gpIHtcbiAgICAgICAgICAgICAgICBmb3IgKHZhciBpbmRleCBpbiBwYXRjaCkge1xuICAgICAgICAgICAgICAgICAgICBpZiAoaW5kZXggIT09IFwiYVwiKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgLy8gRXhlY3V0ZSBob29rcyB3aGVuIHR3byBub2RlcyBhcmUgaWRlbnRpY2FsXG4gICAgICAgICAgICBmdW5jdGlvbiB1bmhvb2sodk5vZGUsIHBhdGNoLCBpbmRleCkge1xuICAgICAgICAgICAgICAgIGlmIChpc1ZOb2RlKHZOb2RlKSkge1xuICAgICAgICAgICAgICAgICAgICBpZiAodk5vZGUuaG9va3MpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHBhdGNoW2luZGV4XSA9IGFwcGVuZFBhdGNoKHBhdGNoW2luZGV4XSwgbmV3IFZQYXRjaChWUGF0Y2guUFJPUFMsIHZOb2RlLCB1bmRlZmluZWRLZXlzKHZOb2RlLmhvb2tzKSkpO1xuICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgaWYgKHZOb2RlLmRlc2NlbmRhbnRIb29rcyB8fCB2Tm9kZS5oYXNUaHVua3MpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHZhciBjaGlsZHJlbiA9IHZOb2RlLmNoaWxkcmVuO1xuICAgICAgICAgICAgICAgICAgICAgICAgdmFyIGxlbiA9IGNoaWxkcmVuLmxlbmd0aDtcbiAgICAgICAgICAgICAgICAgICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgbGVuOyBpKyspIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB2YXIgY2hpbGQgPSBjaGlsZHJlbltpXTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpbmRleCArPSAxO1xuXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdW5ob29rKGNoaWxkLCBwYXRjaCwgaW5kZXgpO1xuXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGlzVk5vZGUoY2hpbGQpICYmIGNoaWxkLmNvdW50KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGluZGV4ICs9IGNoaWxkLmNvdW50O1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoaXNUaHVuayh2Tm9kZSkpIHtcbiAgICAgICAgICAgICAgICAgICAgdGh1bmtzKHZOb2RlLCBudWxsLCBwYXRjaCwgaW5kZXgpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZnVuY3Rpb24gdW5kZWZpbmVkS2V5cyhvYmopIHtcbiAgICAgICAgICAgICAgICB2YXIgcmVzdWx0ID0ge307XG5cbiAgICAgICAgICAgICAgICBmb3IgKHZhciBrZXkgaW4gb2JqKSB7XG4gICAgICAgICAgICAgICAgICAgIHJlc3VsdFtrZXldID0gdW5kZWZpbmVkO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHJldHVybiByZXN1bHQ7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIC8vIExpc3QgZGlmZiwgbmFpdmUgbGVmdCB0byByaWdodCByZW9yZGVyaW5nXG4gICAgICAgICAgICBmdW5jdGlvbiByZW9yZGVyKGFDaGlsZHJlbiwgYkNoaWxkcmVuKSB7XG4gICAgICAgICAgICAgICAgLy8gTyhNKSB0aW1lLCBPKE0pIG1lbW9yeVxuICAgICAgICAgICAgICAgIHZhciBiQ2hpbGRJbmRleCA9IGtleUluZGV4KGJDaGlsZHJlbik7XG4gICAgICAgICAgICAgICAgdmFyIGJLZXlzID0gYkNoaWxkSW5kZXgua2V5cztcbiAgICAgICAgICAgICAgICB2YXIgYkZyZWUgPSBiQ2hpbGRJbmRleC5mcmVlO1xuXG4gICAgICAgICAgICAgICAgaWYgKGJGcmVlLmxlbmd0aCA9PT0gYkNoaWxkcmVuLmxlbmd0aCkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgICAgICAgICAgICAgY2hpbGRyZW46IGJDaGlsZHJlbixcbiAgICAgICAgICAgICAgICAgICAgICAgIG1vdmVzOiBudWxsXG4gICAgICAgICAgICAgICAgICAgIH07XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgLy8gTyhOKSB0aW1lLCBPKE4pIG1lbW9yeVxuICAgICAgICAgICAgICAgIHZhciBhQ2hpbGRJbmRleCA9IGtleUluZGV4KGFDaGlsZHJlbik7XG4gICAgICAgICAgICAgICAgdmFyIGFLZXlzID0gYUNoaWxkSW5kZXgua2V5cztcbiAgICAgICAgICAgICAgICB2YXIgYUZyZWUgPSBhQ2hpbGRJbmRleC5mcmVlO1xuXG4gICAgICAgICAgICAgICAgaWYgKGFGcmVlLmxlbmd0aCA9PT0gYUNoaWxkcmVuLmxlbmd0aCkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgICAgICAgICAgICAgY2hpbGRyZW46IGJDaGlsZHJlbixcbiAgICAgICAgICAgICAgICAgICAgICAgIG1vdmVzOiBudWxsXG4gICAgICAgICAgICAgICAgICAgIH07XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgLy8gTyhNQVgoTiwgTSkpIG1lbW9yeVxuICAgICAgICAgICAgICAgIHZhciBuZXdDaGlsZHJlbiA9IFtdO1xuXG4gICAgICAgICAgICAgICAgdmFyIGZyZWVJbmRleCA9IDA7XG4gICAgICAgICAgICAgICAgdmFyIGZyZWVDb3VudCA9IGJGcmVlLmxlbmd0aDtcbiAgICAgICAgICAgICAgICB2YXIgZGVsZXRlZEl0ZW1zID0gMDtcblxuICAgICAgICAgICAgICAgIC8vIEl0ZXJhdGUgdGhyb3VnaCBhIGFuZCBtYXRjaCBhIG5vZGUgaW4gYlxuICAgICAgICAgICAgICAgIC8vIE8oTikgdGltZSxcbiAgICAgICAgICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IGFDaGlsZHJlbi5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgICAgICAgICB2YXIgYUl0ZW0gPSBhQ2hpbGRyZW5baV07XG4gICAgICAgICAgICAgICAgICAgIHZhciBpdGVtSW5kZXg7XG5cbiAgICAgICAgICAgICAgICAgICAgaWYgKGFJdGVtLmtleSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGJLZXlzLmhhc093blByb3BlcnR5KGFJdGVtLmtleSkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBNYXRjaCB1cCB0aGUgb2xkIGtleXNcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpdGVtSW5kZXggPSBiS2V5c1thSXRlbS5rZXldO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIG5ld0NoaWxkcmVuLnB1c2goYkNoaWxkcmVuW2l0ZW1JbmRleF0pO1xuICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBSZW1vdmUgb2xkIGtleWVkIGl0ZW1zXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaXRlbUluZGV4ID0gaSAtIGRlbGV0ZWRJdGVtcysrO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIG5ld0NoaWxkcmVuLnB1c2gobnVsbCk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAvLyBNYXRjaCB0aGUgaXRlbSBpbiBhIHdpdGggdGhlIG5leHQgZnJlZSBpdGVtIGluIGJcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChmcmVlSW5kZXggPCBmcmVlQ291bnQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpdGVtSW5kZXggPSBiRnJlZVtmcmVlSW5kZXgrK107XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgbmV3Q2hpbGRyZW4ucHVzaChiQ2hpbGRyZW5baXRlbUluZGV4XSk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIFRoZXJlIGFyZSBubyBmcmVlIGl0ZW1zIGluIGIgdG8gbWF0Y2ggd2l0aFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIHRoZSBmcmVlIGl0ZW1zIGluIGEsIHNvIHRoZSBleHRyYSBmcmVlIG5vZGVzXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gYXJlIGRlbGV0ZWQuXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaXRlbUluZGV4ID0gaSAtIGRlbGV0ZWRJdGVtcysrO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIG5ld0NoaWxkcmVuLnB1c2gobnVsbCk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICB2YXIgbGFzdEZyZWVJbmRleCA9IGZyZWVJbmRleCA+PSBiRnJlZS5sZW5ndGggPyBiQ2hpbGRyZW4ubGVuZ3RoIDogYkZyZWVbZnJlZUluZGV4XTtcblxuICAgICAgICAgICAgICAgIC8vIEl0ZXJhdGUgdGhyb3VnaCBiIGFuZCBhcHBlbmQgYW55IG5ldyBrZXlzXG4gICAgICAgICAgICAgICAgLy8gTyhNKSB0aW1lXG4gICAgICAgICAgICAgICAgZm9yICh2YXIgaiA9IDA7IGogPCBiQ2hpbGRyZW4ubGVuZ3RoOyBqKyspIHtcbiAgICAgICAgICAgICAgICAgICAgdmFyIG5ld0l0ZW0gPSBiQ2hpbGRyZW5bal07XG5cbiAgICAgICAgICAgICAgICAgICAgaWYgKG5ld0l0ZW0ua2V5KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoIWFLZXlzLmhhc093blByb3BlcnR5KG5ld0l0ZW0ua2V5KSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIEFkZCBhbnkgbmV3IGtleWVkIGl0ZW1zXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gV2UgYXJlIGFkZGluZyBuZXcgaXRlbXMgdG8gdGhlIGVuZCBhbmQgdGhlbiBzb3J0aW5nIHRoZW1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBpbiBwbGFjZS4gSW4gZnV0dXJlIHdlIHNob3VsZCBpbnNlcnQgbmV3IGl0ZW1zIGluIHBsYWNlLlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIG5ld0NoaWxkcmVuLnB1c2gobmV3SXRlbSk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoaiA+PSBsYXN0RnJlZUluZGV4KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAvLyBBZGQgYW55IGxlZnRvdmVyIG5vbi1rZXllZCBpdGVtc1xuICAgICAgICAgICAgICAgICAgICAgICAgbmV3Q2hpbGRyZW4ucHVzaChuZXdJdGVtKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHZhciBzaW11bGF0ZSA9IG5ld0NoaWxkcmVuLnNsaWNlKCk7XG4gICAgICAgICAgICAgICAgdmFyIHNpbXVsYXRlSW5kZXggPSAwO1xuICAgICAgICAgICAgICAgIHZhciByZW1vdmVzID0gW107XG4gICAgICAgICAgICAgICAgdmFyIGluc2VydHMgPSBbXTtcbiAgICAgICAgICAgICAgICB2YXIgc2ltdWxhdGVJdGVtO1xuXG4gICAgICAgICAgICAgICAgZm9yICh2YXIgayA9IDA7IGsgPCBiQ2hpbGRyZW4ubGVuZ3RoOykge1xuICAgICAgICAgICAgICAgICAgICB2YXIgd2FudGVkSXRlbSA9IGJDaGlsZHJlbltrXTtcbiAgICAgICAgICAgICAgICAgICAgc2ltdWxhdGVJdGVtID0gc2ltdWxhdGVbc2ltdWxhdGVJbmRleF07XG5cbiAgICAgICAgICAgICAgICAgICAgLy8gcmVtb3ZlIGl0ZW1zXG4gICAgICAgICAgICAgICAgICAgIHdoaWxlIChzaW11bGF0ZUl0ZW0gPT09IG51bGwgJiYgc2ltdWxhdGUubGVuZ3RoKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICByZW1vdmVzLnB1c2gocmVtb3ZlKHNpbXVsYXRlLCBzaW11bGF0ZUluZGV4LCBudWxsKSk7XG4gICAgICAgICAgICAgICAgICAgICAgICBzaW11bGF0ZUl0ZW0gPSBzaW11bGF0ZVtzaW11bGF0ZUluZGV4XTtcbiAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgIGlmICghc2ltdWxhdGVJdGVtIHx8IHNpbXVsYXRlSXRlbS5rZXkgIT09IHdhbnRlZEl0ZW0ua2V5KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAvLyBpZiB3ZSBuZWVkIGEga2V5IGluIHRoaXMgcG9zaXRpb24uLi5cbiAgICAgICAgICAgICAgICAgICAgICAgIGlmICh3YW50ZWRJdGVtLmtleSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChzaW11bGF0ZUl0ZW0gJiYgc2ltdWxhdGVJdGVtLmtleSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBpZiBhbiBpbnNlcnQgZG9lc24ndCBwdXQgdGhpcyBrZXkgaW4gcGxhY2UsIGl0IG5lZWRzIHRvIG1vdmVcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGJLZXlzW3NpbXVsYXRlSXRlbS5rZXldICE9PSBrICsgMSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmVtb3Zlcy5wdXNoKHJlbW92ZShzaW11bGF0ZSwgc2ltdWxhdGVJbmRleCwgc2ltdWxhdGVJdGVtLmtleSkpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc2ltdWxhdGVJdGVtID0gc2ltdWxhdGVbc2ltdWxhdGVJbmRleF07XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBpZiB0aGUgcmVtb3ZlIGRpZG4ndCBwdXQgdGhlIHdhbnRlZCBpdGVtIGluIHBsYWNlLCB3ZSBuZWVkIHRvIGluc2VydCBpdFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKCFzaW11bGF0ZUl0ZW0gfHwgc2ltdWxhdGVJdGVtLmtleSAhPT0gd2FudGVkSXRlbS5rZXkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpbnNlcnRzLnB1c2goeyBrZXk6IHdhbnRlZEl0ZW0ua2V5LCB0bzogayB9KTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIGl0ZW1zIGFyZSBtYXRjaGluZywgc28gc2tpcCBhaGVhZFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc2ltdWxhdGVJbmRleCsrO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaW5zZXJ0cy5wdXNoKHsga2V5OiB3YW50ZWRJdGVtLmtleSwgdG86IGsgfSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpbnNlcnRzLnB1c2goeyBrZXk6IHdhbnRlZEl0ZW0ua2V5LCB0bzogayB9KTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaysrO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgLy8gYSBrZXkgaW4gc2ltdWxhdGUgaGFzIG5vIG1hdGNoaW5nIHdhbnRlZCBrZXksIHJlbW92ZSBpdFxuICAgICAgICAgICAgICAgICAgICAgICAgZWxzZSBpZiAoc2ltdWxhdGVJdGVtICYmIHNpbXVsYXRlSXRlbS5rZXkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICByZW1vdmVzLnB1c2gocmVtb3ZlKHNpbXVsYXRlLCBzaW11bGF0ZUluZGV4LCBzaW11bGF0ZUl0ZW0ua2V5KSk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBzaW11bGF0ZUluZGV4Kys7XG4gICAgICAgICAgICAgICAgICAgICAgICBrKys7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAvLyByZW1vdmUgYWxsIHRoZSByZW1haW5pbmcgbm9kZXMgZnJvbSBzaW11bGF0ZVxuICAgICAgICAgICAgICAgIHdoaWxlIChzaW11bGF0ZUluZGV4IDwgc2ltdWxhdGUubGVuZ3RoKSB7XG4gICAgICAgICAgICAgICAgICAgIHNpbXVsYXRlSXRlbSA9IHNpbXVsYXRlW3NpbXVsYXRlSW5kZXhdO1xuICAgICAgICAgICAgICAgICAgICByZW1vdmVzLnB1c2gocmVtb3ZlKHNpbXVsYXRlLCBzaW11bGF0ZUluZGV4LCBzaW11bGF0ZUl0ZW0gJiYgc2ltdWxhdGVJdGVtLmtleSkpO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIC8vIElmIHRoZSBvbmx5IG1vdmVzIHdlIGhhdmUgYXJlIGRlbGV0ZXMgdGhlbiB3ZSBjYW4ganVzdFxuICAgICAgICAgICAgICAgIC8vIGxldCB0aGUgZGVsZXRlIHBhdGNoIHJlbW92ZSB0aGVzZSBpdGVtcy5cbiAgICAgICAgICAgICAgICBpZiAocmVtb3Zlcy5sZW5ndGggPT09IGRlbGV0ZWRJdGVtcyAmJiAhaW5zZXJ0cy5sZW5ndGgpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGNoaWxkcmVuOiBuZXdDaGlsZHJlbixcbiAgICAgICAgICAgICAgICAgICAgICAgIG1vdmVzOiBudWxsXG4gICAgICAgICAgICAgICAgICAgIH07XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgICAgICAgICAgY2hpbGRyZW46IG5ld0NoaWxkcmVuLFxuICAgICAgICAgICAgICAgICAgICBtb3Zlczoge1xuICAgICAgICAgICAgICAgICAgICAgICAgcmVtb3ZlczogcmVtb3ZlcyxcbiAgICAgICAgICAgICAgICAgICAgICAgIGluc2VydHM6IGluc2VydHNcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH07XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIHJlbW92ZShhcnIsIGluZGV4LCBrZXkpIHtcbiAgICAgICAgICAgICAgICBhcnIuc3BsaWNlKGluZGV4LCAxKTtcblxuICAgICAgICAgICAgICAgIHJldHVybiB7XG4gICAgICAgICAgICAgICAgICAgIGZyb206IGluZGV4LFxuICAgICAgICAgICAgICAgICAgICBrZXk6IGtleVxuICAgICAgICAgICAgICAgIH07XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIGtleUluZGV4KGNoaWxkcmVuKSB7XG4gICAgICAgICAgICAgICAgdmFyIGtleXMgPSB7fTtcbiAgICAgICAgICAgICAgICB2YXIgZnJlZSA9IFtdO1xuICAgICAgICAgICAgICAgIHZhciBsZW5ndGggPSBjaGlsZHJlbi5sZW5ndGg7XG5cbiAgICAgICAgICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IGxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciBjaGlsZCA9IGNoaWxkcmVuW2ldO1xuXG4gICAgICAgICAgICAgICAgICAgIGlmIChjaGlsZC5rZXkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGtleXNbY2hpbGQua2V5XSA9IGk7XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBmcmVlLnB1c2goaSk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgICAgICAgICBrZXlzOiBrZXlzLCAvLyBBIGhhc2ggb2Yga2V5IG5hbWUgdG8gaW5kZXhcbiAgICAgICAgICAgICAgICAgICAgZnJlZTogZnJlZSAvLyBBbiBhcnJheSBvZiB1bmtleWVkIGl0ZW0gaW5kaWNlc1xuICAgICAgICAgICAgICAgIH07XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIGFwcGVuZFBhdGNoKGFwcGx5LCBwYXRjaCkge1xuICAgICAgICAgICAgICAgIGlmIChhcHBseSkge1xuICAgICAgICAgICAgICAgICAgICBpZiAoaXNBcnJheShhcHBseSkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGFwcGx5LnB1c2gocGF0Y2gpO1xuICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgYXBwbHkgPSBbYXBwbHksIHBhdGNoXTtcbiAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBhcHBseTtcbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gcGF0Y2g7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9LCB7IFwiLi4vdm5vZGUvaGFuZGxlLXRodW5rXCI6IDI0LCBcIi4uL3Zub2RlL2lzLXRodW5rXCI6IDI1LCBcIi4uL3Zub2RlL2lzLXZub2RlXCI6IDI3LCBcIi4uL3Zub2RlL2lzLXZ0ZXh0XCI6IDI4LCBcIi4uL3Zub2RlL2lzLXdpZGdldFwiOiAyOSwgXCIuLi92bm9kZS92cGF0Y2hcIjogMzIsIFwiLi9kaWZmLXByb3BzXCI6IDM0LCBcIngtaXMtYXJyYXlcIjogMTIgfV0gfSwge30sIFs0XSkoNCk7XG59KTtcblxuLyogQGZsb3cgKi9cblxuY2xhc3MgTWFpbGJveCB7XG5cbiAgY29uc3RydWN0b3IoKSB7XG4gICAgdGhpcy5tZXNzYWdlcyA9IFtdO1xuICB9XG5cbiAgZGVsaXZlcihtZXNzYWdlKSB7XG4gICAgdGhpcy5tZXNzYWdlcy5wdXNoKG1lc3NhZ2UpO1xuICAgIHJldHVybiBtZXNzYWdlO1xuICB9XG5cbiAgZ2V0KCkge1xuICAgIHJldHVybiB0aGlzLm1lc3NhZ2VzO1xuICB9XG5cbiAgaXNFbXB0eSgpIHtcbiAgICByZXR1cm4gdGhpcy5tZXNzYWdlcy5sZW5ndGggPT09IDA7XG4gIH1cblxuICByZW1vdmVBdChpbmRleCkge1xuICAgIHRoaXMubWVzc2FnZXMuc3BsaWNlKGluZGV4LCAxKTtcbiAgfVxufVxuXG52YXIgU3RhdGVzID0ge1xuICBOT1JNQUw6IFN5bWJvbC5mb3IoXCJub3JtYWxcIiksXG4gIEtJTEw6IFN5bWJvbC5mb3IoXCJraWxsXCIpLFxuICBTVVNQRU5EOiBTeW1ib2wuZm9yKFwic3VzcGVuZFwiKSxcbiAgQ09OVElOVUU6IFN5bWJvbC5mb3IoXCJjb250aW51ZVwiKSxcbiAgUkVDRUlWRTogU3ltYm9sLmZvcihcInJlY2VpdmVcIiksXG4gIFNFTkQ6IFN5bWJvbC5mb3IoXCJzZW5kXCIpLFxuICBTTEVFUElORzogU3ltYm9sLmZvcihcInNsZWVwaW5nXCIpLFxuICBSVU5OSU5HOiBTeW1ib2wuZm9yKFwicnVubmluZ1wiKSxcbiAgU1VTUEVOREVEOiBTeW1ib2wuZm9yKFwic3VzcGVuZGVkXCIpLFxuICBTVE9QUEVEOiBTeW1ib2wuZm9yKFwic3RvcHBlZFwiKSxcbiAgU0xFRVA6IFN5bWJvbC5mb3IoXCJzbGVlcFwiKSxcbiAgRVhJVDogU3ltYm9sLmZvcihcImV4aXRcIiksXG4gIE5PTUFUQ0g6IFN5bWJvbC5mb3IoXCJub19tYXRjaFwiKVxufTtcblxuY2xhc3MgUHJvY2VzcyB7XG5cbiAgY29uc3RydWN0b3IocGlkLCBtYWlsYm94KSB7XG4gICAgdGhpcy5waWQgPSBwaWQ7XG4gICAgdGhpcy5tYWlsYm94ID0gbWFpbGJveDtcbiAgICB0aGlzLnN0YXR1cyA9IFN0YXRlcy5TVE9QUEVEO1xuICAgIHRoaXMuZGljdCA9IHt9O1xuICB9XG59XG5cbmNsYXNzIFR1cGxlIHtcblxuICBjb25zdHJ1Y3RvciguLi5hcmdzKSB7XG4gICAgdGhpcy52YWx1ZXMgPSBPYmplY3QuZnJlZXplKGFyZ3MpO1xuICAgIHRoaXMubGVuZ3RoID0gdGhpcy52YWx1ZXMubGVuZ3RoO1xuICB9XG5cbiAgZ2V0KGluZGV4KSB7XG4gICAgcmV0dXJuIHRoaXMudmFsdWVzW2luZGV4XTtcbiAgfVxuXG4gIGNvdW50KCkge1xuICAgIHJldHVybiB0aGlzLnZhbHVlcy5sZW5ndGg7XG4gIH1cblxuICBbU3ltYm9sLml0ZXJhdG9yXSgpIHtcbiAgICByZXR1cm4gdGhpcy52YWx1ZXNbU3ltYm9sLml0ZXJhdG9yXSgpO1xuICB9XG5cbiAgdG9TdHJpbmcoKSB7XG4gICAgdmFyIGksXG4gICAgICAgIHMgPSBcIlwiO1xuICAgIGZvciAoaSA9IDA7IGkgPCB0aGlzLnZhbHVlcy5sZW5ndGg7IGkrKykge1xuICAgICAgaWYgKHMgIT09IFwiXCIpIHtcbiAgICAgICAgcyArPSBcIiwgXCI7XG4gICAgICB9XG4gICAgICBzICs9IHRoaXMudmFsdWVzW2ldLnRvU3RyaW5nKCk7XG4gICAgfVxuXG4gICAgcmV0dXJuIFwie1wiICsgcyArIFwifVwiO1xuICB9XG5cbiAgcHV0X2VsZW0oaW5kZXgsIGVsZW0pIHtcbiAgICBpZiAoaW5kZXggPT09IHRoaXMubGVuZ3RoKSB7XG4gICAgICBsZXQgbmV3X3ZhbHVlcyA9IHRoaXMudmFsdWVzLmNvbmNhdChbZWxlbV0pO1xuICAgICAgcmV0dXJuIG5ldyBUdXBsZSguLi5uZXdfdmFsdWVzKTtcbiAgICB9XG5cbiAgICBsZXQgbmV3X3ZhbHVlcyA9IHRoaXMudmFsdWVzLmNvbmNhdChbXSk7XG4gICAgbmV3X3ZhbHVlcy5zcGxpY2UoaW5kZXgsIDAsIGVsZW0pO1xuICAgIHJldHVybiBuZXcgVHVwbGUoLi4ubmV3X3ZhbHVlcyk7XG4gIH1cblxuICByZW1vdmVfZWxlbShpbmRleCkge1xuICAgIGxldCBuZXdfdmFsdWVzID0gdGhpcy52YWx1ZXMuY29uY2F0KFtdKTtcbiAgICBuZXdfdmFsdWVzLnNwbGljZShpbmRleCwgMSk7XG4gICAgcmV0dXJuIG5ldyBUdXBsZSguLi5uZXdfdmFsdWVzKTtcbiAgfVxuXG59XG5cbmxldCBwcm9jZXNzX2NvdW50ZXIgPSAtMTtcblxuY2xhc3MgUElEIHtcbiAgY29uc3RydWN0b3IoKSB7XG4gICAgcHJvY2Vzc19jb3VudGVyID0gcHJvY2Vzc19jb3VudGVyICsgMTtcbiAgICB0aGlzLmlkID0gcHJvY2Vzc19jb3VudGVyO1xuICB9XG5cbiAgdG9TdHJpbmcoKSB7XG4gICAgcmV0dXJuIFwiUElEIzwwLlwiICsgdGhpcy5pZCArIFwiLjA+XCI7XG4gIH1cbn1cblxuY2xhc3MgSW50ZWdlciB7fVxuY2xhc3MgRmxvYXQge31cblxuY2xhc3MgUHJvY2Vzc1N5c3RlbSB7XG5cbiAgY29uc3RydWN0b3IoKSB7XG4gICAgdGhpcy5waWRzID0gbmV3IE1hcCgpO1xuICAgIHRoaXMubWFpbGJveGVzID0gbmV3IE1hcCgpO1xuICAgIHRoaXMubmFtZXMgPSBuZXcgTWFwKCk7XG4gICAgdGhpcy5saW5rcyA9IG5ldyBNYXAoKTtcblxuICAgIHRoaXMuY3VycmVudF9wcm9jZXNzID0gbnVsbDtcbiAgICB0aGlzLnN1c3BlbmRlZCA9IG5ldyBNYXAoKTtcblxuICAgIHRoaXMubWFpbl9wcm9jZXNzX3BpZCA9IHRoaXMuc3Bhd24oKTtcbiAgICB0aGlzLnNldF9jdXJyZW50KHRoaXMubWFpbl9wcm9jZXNzX3BpZCk7XG4gIH1cblxuICBzcGF3bigpIHtcbiAgICByZXR1cm4gdGhpcy5hZGRfcHJvYyhmYWxzZSkucGlkO1xuICB9XG5cbiAgc3Bhd25fbGluaygpIHtcbiAgICByZXR1cm4gdGhpcy5hZGRfcHJvYyh0cnVlKS5waWQ7XG4gIH1cblxuICBsaW5rKHBpZCkge1xuICAgIHRoaXMubGlua3MuZ2V0KHRoaXMucGlkKCkpLmFkZChwaWQpO1xuICAgIHRoaXMubGlua3MuZ2V0KHBpZCkuYWRkKHRoaXMucGlkKCkpO1xuICB9XG5cbiAgdW5saW5rKHBpZCkge1xuICAgIHRoaXMubGlua3MuZ2V0KHRoaXMucGlkKCkpLmRlbGV0ZShwaWQpO1xuICAgIHRoaXMubGlua3MuZ2V0KHBpZCkuZGVsZXRlKHRoaXMucGlkKCkpO1xuICB9XG5cbiAgc2V0X2N1cnJlbnQoaWQpIHtcbiAgICBsZXQgcGlkID0gdGhpcy5waWRvZihpZCk7XG4gICAgaWYgKHBpZCAhPT0gbnVsbCkge1xuICAgICAgdGhpcy5jdXJyZW50X3Byb2Nlc3MgPSB0aGlzLnBpZHMuZ2V0KHBpZCk7XG4gICAgICB0aGlzLmN1cnJlbnRfcHJvY2Vzcy5zdGF0dXMgPSBTdGF0ZXMuUlVOTklORztcbiAgICB9XG4gIH1cblxuICBhZGRfcHJvYyhsaW5rZWQpIHtcbiAgICBsZXQgbmV3cGlkID0gbmV3IFBJRCgpO1xuICAgIGxldCBtYWlsYm94ID0gbmV3IE1haWxib3goKTtcbiAgICBsZXQgbmV3cHJvYyA9IG5ldyBQcm9jZXNzKG5ld3BpZCwgbWFpbGJveCk7XG5cbiAgICB0aGlzLnBpZHMuc2V0KG5ld3BpZCwgbmV3cHJvYyk7XG4gICAgdGhpcy5tYWlsYm94ZXMuc2V0KG5ld3BpZCwgbWFpbGJveCk7XG4gICAgdGhpcy5saW5rcy5zZXQobmV3cGlkLCBuZXcgU2V0KCkpO1xuXG4gICAgaWYgKGxpbmtlZCkge1xuICAgICAgdGhpcy5saW5rKG5ld3BpZCk7XG4gICAgfVxuXG4gICAgcmV0dXJuIG5ld3Byb2M7XG4gIH1cblxuICByZW1vdmVfcHJvYyhwaWQpIHtcbiAgICB0aGlzLnBpZHMuZGVsZXRlKHBpZCk7XG4gICAgdGhpcy51bnJlZ2lzdGVyKHBpZCk7XG5cbiAgICBpZiAodGhpcy5saW5rcy5oYXMocGlkKSkge1xuICAgICAgZm9yIChsZXQgbGlua3BpZCBvZiB0aGlzLmxpbmtzLmdldChwaWQpKSB7XG4gICAgICAgIHRoaXMubGlua3MuZ2V0KGxpbmtwaWQpLmRlbGV0ZShwaWQpO1xuICAgICAgfVxuXG4gICAgICB0aGlzLmxpbmtzLmRlbGV0ZShwaWQpO1xuICAgIH1cbiAgfVxuXG4gIGV4aXQoaWQpIHtcbiAgICBsZXQgcGlkID0gdGhpcy5waWRvZihpZCk7XG4gICAgdGhpcy5yZW1vdmVfcHJvYyhpZCk7XG4gIH1cblxuICByZWdpc3RlcihuYW1lLCBwaWQpIHtcbiAgICBpZiAoIXRoaXMubmFtZXMuaGFzKG5hbWUpKSB7XG4gICAgICB0aGlzLm5hbWVzLnNldChuYW1lLCBwaWQpO1xuICAgICAgcmV0dXJuIG5hbWU7XG4gICAgfSBlbHNlIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcihcIk5hbWUgaXMgYWxyZWFkeSByZWdpc3RlcmVkIHRvIGFub3RoZXIgcHJvY2Vzc1wiKTtcbiAgICB9XG4gIH1cblxuICByZWdpc3RlcmVkKG5hbWUpIHtcbiAgICByZXR1cm4gdGhpcy5uYW1lcy5oYXMobmFtZSkgPyB0aGlzLm5hbWVzLmdldChuYW1lKSA6IG51bGw7XG4gIH1cblxuICB1bnJlZ2lzdGVyKHBpZCkge1xuICAgIGZvciAobGV0IG5hbWUgb2YgdGhpcy5uYW1lcy5rZXlzKCkpIHtcbiAgICAgIGlmICh0aGlzLm5hbWVzLmhhcyhuYW1lKSAmJiB0aGlzLm5hbWVzLmdldChuYW1lKSA9PT0gcGlkKSB7XG4gICAgICAgIHRoaXMubmFtZXMuZGVsZXRlKG5hbWUpO1xuICAgICAgfVxuICAgIH1cbiAgfVxuXG4gIHBpZCgpIHtcbiAgICByZXR1cm4gdGhpcy5jdXJyZW50X3Byb2Nlc3MucGlkO1xuICB9XG5cbiAgcGlkb2YoaWQpIHtcbiAgICBpZiAoaWQgaW5zdGFuY2VvZiBQSUQpIHtcbiAgICAgIHJldHVybiB0aGlzLnBpZHMuaGFzKGlkKSA/IGlkIDogbnVsbDtcbiAgICB9IGVsc2UgaWYgKGlkIGluc3RhbmNlb2YgUHJvY2Vzcykge1xuICAgICAgcmV0dXJuIGlkLnBpZDtcbiAgICB9IGVsc2Uge1xuICAgICAgbGV0IHBpZCA9IHRoaXMucmVnaXN0ZXJlZChpZCk7XG4gICAgICBpZiAocGlkID09PSBudWxsKSB0aHJvdyBcIlByb2Nlc3MgbmFtZSBub3QgcmVnaXN0ZXJlZDogXCIgKyBpZCArIFwiIChcIiArIHR5cGVvZiBpZCArIFwiKVwiO1xuICAgICAgcmV0dXJuIHBpZDtcbiAgICB9XG4gIH1cblxuICBwdXQoaWQsIGtleSwgdmFsdWUpIHtcbiAgICBsZXQgcGlkID0gdGhpcy5waWRvZihpZCk7XG4gICAgbGV0IHByb2Nlc3MgPSB0aGlzLnBpZHMuZ2V0KHBpZCk7XG4gICAgcHJvY2Vzcy5kaWN0W2tleV0gPSB2YWx1ZTtcbiAgfVxuXG4gIGdldChpZCwga2V5KSB7XG4gICAgbGV0IHBpZCA9IHRoaXMucGlkb2YoaWQpO1xuICAgIGxldCBwcm9jZXNzID0gdGhpcy5waWRzLmdldChwaWQpO1xuXG4gICAgaWYgKGtleSAhPSBudWxsKSB7XG4gICAgICByZXR1cm4gcHJvY2Vzcy5kaWN0W2tleV07XG4gICAgfSBlbHNlIHtcbiAgICAgIHJldHVybiBwcm9jZXNzLmRpY3Q7XG4gICAgfVxuICB9XG5cbiAgZ2V0X2tleXMoaWQpIHtcbiAgICBsZXQgcGlkID0gdGhpcy5waWRvZihpZCk7XG4gICAgbGV0IHByb2Nlc3MgPSB0aGlzLnBpZHMuZ2V0KHBpZCk7XG5cbiAgICByZXR1cm4gT2JqZWN0LmtleXMocHJvY2Vzcy5kaWN0KTtcbiAgfVxuXG4gIGVyYXNlKGlkLCBrZXkpIHtcbiAgICBsZXQgcGlkID0gdGhpcy5waWRvZihpZCk7XG4gICAgbGV0IHByb2Nlc3MgPSB0aGlzLnBpZHMuZ2V0KHBpZCk7XG5cbiAgICBpZiAoa2V5ICE9IG51bGwpIHtcbiAgICAgIGRlbGV0ZSBwcm9jZXNzLmRpY3Rba2V5XTtcbiAgICB9IGVsc2Uge1xuICAgICAgcHJvY2Vzcy5kaWN0ID0ge307XG4gICAgfVxuICB9XG59XG5cbmNsYXNzIEJpdFN0cmluZyB7XG4gIGNvbnN0cnVjdG9yKC4uLmFyZ3MpIHtcbiAgICB0aGlzLnJhd192YWx1ZSA9IGZ1bmN0aW9uICgpIHtcbiAgICAgIHJldHVybiBPYmplY3QuZnJlZXplKGFyZ3MpO1xuICAgIH07XG5cbiAgICB0aGlzLnZhbHVlID0gT2JqZWN0LmZyZWV6ZSh0aGlzLnByb2Nlc3MoYXJncykpO1xuICAgIHRoaXMubGVuZ3RoID0gdGhpcy52YWx1ZS5sZW5ndGg7XG4gICAgdGhpcy5iaXRfc2l6ZSA9IHRoaXMucmF3X3ZhbHVlKCkucmVkdWNlKChwcmV2LCBjdXJyZW50KSA9PiBwcmV2ICsgY3VycmVudC5zaXplKTtcbiAgICB0aGlzLmJ5dGVfc2l6ZSA9IHRoaXMuYml0X3NpemUgLyA4ICsgKHRoaXMuYml0X3NpemUgJSA4ID4gMCA/IDEgOiAwKTtcbiAgfVxuXG4gIGdldChpbmRleCkge1xuICAgIHJldHVybiB0aGlzLnZhbHVlW2luZGV4XTtcbiAgfVxuXG4gIGNvdW50KCkge1xuICAgIHJldHVybiB0aGlzLnZhbHVlLmxlbmd0aDtcbiAgfVxuXG4gIFtTeW1ib2wuaXRlcmF0b3JdKCkge1xuICAgIHJldHVybiB0aGlzLnZhbHVlW1N5bWJvbC5pdGVyYXRvcl0oKTtcbiAgfVxuXG4gIHRvU3RyaW5nKCkge1xuICAgIHZhciBpLFxuICAgICAgICBzID0gXCJcIjtcbiAgICBmb3IgKGkgPSAwOyBpIDwgdGhpcy5jb3VudCgpOyBpKyspIHtcbiAgICAgIGlmIChzICE9PSBcIlwiKSB7XG4gICAgICAgIHMgKz0gXCIsIFwiO1xuICAgICAgfVxuICAgICAgcyArPSB0aGlzW2ldLnRvU3RyaW5nKCk7XG4gICAgfVxuXG4gICAgcmV0dXJuIFwiPDxcIiArIHMgKyBcIj4+XCI7XG4gIH1cblxuICBwcm9jZXNzKCkge1xuICAgIGxldCBwcm9jZXNzZWRfdmFsdWVzID0gW107XG5cbiAgICB2YXIgaTtcbiAgICBmb3IgKGkgPSAwOyBpIDwgdGhpcy5yYXdfdmFsdWUoKS5sZW5ndGg7IGkrKykge1xuICAgICAgbGV0IHByb2Nlc3NlZF92YWx1ZSA9IHRoaXNbXCJwcm9jZXNzX1wiICsgdGhpcy5yYXdfdmFsdWUoKVtpXS50eXBlXSh0aGlzLnJhd192YWx1ZSgpW2ldKTtcblxuICAgICAgZm9yIChsZXQgYXR0ciBvZiB0aGlzLnJhd192YWx1ZSgpW2ldLmF0dHJpYnV0ZXMpIHtcbiAgICAgICAgcHJvY2Vzc2VkX3ZhbHVlID0gdGhpc1tcInByb2Nlc3NfXCIgKyBhdHRyXShwcm9jZXNzZWRfdmFsdWUpO1xuICAgICAgfVxuXG4gICAgICBwcm9jZXNzZWRfdmFsdWVzID0gcHJvY2Vzc2VkX3ZhbHVlcy5jb25jYXQocHJvY2Vzc2VkX3ZhbHVlKTtcbiAgICB9XG5cbiAgICByZXR1cm4gcHJvY2Vzc2VkX3ZhbHVlcztcbiAgfVxuXG4gIHByb2Nlc3NfaW50ZWdlcih2YWx1ZSkge1xuICAgIHJldHVybiB2YWx1ZS52YWx1ZTtcbiAgfVxuXG4gIHByb2Nlc3NfZmxvYXQodmFsdWUpIHtcbiAgICBpZiAodmFsdWUuc2l6ZSA9PT0gNjQpIHtcbiAgICAgIHJldHVybiBCaXRTdHJpbmcuZmxvYXQ2NFRvQnl0ZXModmFsdWUudmFsdWUpO1xuICAgIH0gZWxzZSBpZiAodmFsdWUuc2l6ZSA9PT0gMzIpIHtcbiAgICAgIHJldHVybiBCaXRTdHJpbmcuZmxvYXQzMlRvQnl0ZXModmFsdWUudmFsdWUpO1xuICAgIH1cblxuICAgIHRocm93IG5ldyBFcnJvcihcIkludmFsaWQgc2l6ZSBmb3IgZmxvYXRcIik7XG4gIH1cblxuICBwcm9jZXNzX2JpdHN0cmluZyh2YWx1ZSkge1xuICAgIHJldHVybiB2YWx1ZS52YWx1ZS52YWx1ZTtcbiAgfVxuXG4gIHByb2Nlc3NfYmluYXJ5KHZhbHVlKSB7XG4gICAgcmV0dXJuIEJpdFN0cmluZy50b1VURjhBcnJheSh2YWx1ZS52YWx1ZSk7XG4gIH1cblxuICBwcm9jZXNzX3V0ZjgodmFsdWUpIHtcbiAgICByZXR1cm4gQml0U3RyaW5nLnRvVVRGOEFycmF5KHZhbHVlLnZhbHVlKTtcbiAgfVxuXG4gIHByb2Nlc3NfdXRmMTYodmFsdWUpIHtcbiAgICByZXR1cm4gQml0U3RyaW5nLnRvVVRGMTZBcnJheSh2YWx1ZS52YWx1ZSk7XG4gIH1cblxuICBwcm9jZXNzX3V0ZjMyKHZhbHVlKSB7XG4gICAgcmV0dXJuIEJpdFN0cmluZy50b1VURjMyQXJyYXkodmFsdWUudmFsdWUpO1xuICB9XG5cbiAgcHJvY2Vzc19zaWduZWQodmFsdWUpIHtcbiAgICByZXR1cm4gbmV3IFVpbnQ4QXJyYXkoW3ZhbHVlXSlbMF07XG4gIH1cblxuICBwcm9jZXNzX3Vuc2lnbmVkKHZhbHVlKSB7XG4gICAgcmV0dXJuIHZhbHVlO1xuICB9XG5cbiAgcHJvY2Vzc19uYXRpdmUodmFsdWUpIHtcbiAgICByZXR1cm4gdmFsdWU7XG4gIH1cblxuICBwcm9jZXNzX2JpZyh2YWx1ZSkge1xuICAgIHJldHVybiB2YWx1ZTtcbiAgfVxuXG4gIHByb2Nlc3NfbGl0dGxlKHZhbHVlKSB7XG4gICAgcmV0dXJuIHZhbHVlLnJldmVyc2UoKTtcbiAgfVxuXG4gIHByb2Nlc3Nfc2l6ZSh2YWx1ZSkge1xuICAgIHJldHVybiB2YWx1ZTtcbiAgfVxuXG4gIHByb2Nlc3NfdW5pdCh2YWx1ZSkge1xuICAgIHJldHVybiB2YWx1ZTtcbiAgfVxuXG4gIHN0YXRpYyBpbnRlZ2VyKHZhbHVlKSB7XG4gICAgcmV0dXJuIEJpdFN0cmluZy53cmFwKHZhbHVlLCB7IFwidHlwZVwiOiBcImludGVnZXJcIiwgXCJ1bml0XCI6IDEsIFwic2l6ZVwiOiA4IH0pO1xuICB9XG5cbiAgc3RhdGljIGZsb2F0KHZhbHVlKSB7XG4gICAgcmV0dXJuIEJpdFN0cmluZy53cmFwKHZhbHVlLCB7IFwidHlwZVwiOiBcImZsb2F0XCIsIFwidW5pdFwiOiAxLCBcInNpemVcIjogNjQgfSk7XG4gIH1cblxuICBzdGF0aWMgYml0c3RyaW5nKHZhbHVlKSB7XG4gICAgcmV0dXJuIEJpdFN0cmluZy53cmFwKHZhbHVlLCB7IFwidHlwZVwiOiBcImJpdHN0cmluZ1wiLCBcInVuaXRcIjogMSwgXCJzaXplXCI6IHZhbHVlLmJpdF9zaXplIH0pO1xuICB9XG5cbiAgc3RhdGljIGJpdHModmFsdWUpIHtcbiAgICByZXR1cm4gQml0U3RyaW5nLmJpdHN0cmluZyh2YWx1ZSk7XG4gIH1cblxuICBzdGF0aWMgYmluYXJ5KHZhbHVlKSB7XG4gICAgcmV0dXJuIEJpdFN0cmluZy53cmFwKHZhbHVlLCB7IFwidHlwZVwiOiBcImJpbmFyeVwiLCBcInVuaXRcIjogOCwgXCJzaXplXCI6IHZhbHVlLmxlbmd0aCB9KTtcbiAgfVxuXG4gIHN0YXRpYyBieXRlcyh2YWx1ZSkge1xuICAgIHJldHVybiBCaXRTdHJpbmcuYmluYXJ5KHZhbHVlKTtcbiAgfVxuXG4gIHN0YXRpYyB1dGY4KHZhbHVlKSB7XG4gICAgcmV0dXJuIEJpdFN0cmluZy53cmFwKHZhbHVlLCB7IFwidHlwZVwiOiBcInV0ZjhcIiB9KTtcbiAgfVxuXG4gIHN0YXRpYyB1dGYxNih2YWx1ZSkge1xuICAgIHJldHVybiBCaXRTdHJpbmcud3JhcCh2YWx1ZSwgeyBcInR5cGVcIjogXCJ1dGYxNlwiIH0pO1xuICB9XG5cbiAgc3RhdGljIHV0ZjMyKHZhbHVlKSB7XG4gICAgcmV0dXJuIEJpdFN0cmluZy53cmFwKHZhbHVlLCB7IFwidHlwZVwiOiBcInV0ZjMyXCIgfSk7XG4gIH1cblxuICBzdGF0aWMgc2lnbmVkKHZhbHVlKSB7XG4gICAgcmV0dXJuIEJpdFN0cmluZy53cmFwKHZhbHVlLCB7fSwgXCJzaWduZWRcIik7XG4gIH1cblxuICBzdGF0aWMgdW5zaWduZWQodmFsdWUpIHtcbiAgICByZXR1cm4gQml0U3RyaW5nLndyYXAodmFsdWUsIHt9LCBcInVuc2lnbmVkXCIpO1xuICB9XG5cbiAgc3RhdGljIG5hdGl2ZSh2YWx1ZSkge1xuICAgIHJldHVybiBCaXRTdHJpbmcud3JhcCh2YWx1ZSwge30sIFwibmF0aXZlXCIpO1xuICB9XG5cbiAgc3RhdGljIGJpZyh2YWx1ZSkge1xuICAgIHJldHVybiBCaXRTdHJpbmcud3JhcCh2YWx1ZSwge30sIFwiYmlnXCIpO1xuICB9XG5cbiAgc3RhdGljIGxpdHRsZSh2YWx1ZSkge1xuICAgIHJldHVybiBCaXRTdHJpbmcud3JhcCh2YWx1ZSwge30sIFwibGl0dGxlXCIpO1xuICB9XG5cbiAgc3RhdGljIHNpemUodmFsdWUsIGNvdW50KSB7XG4gICAgcmV0dXJuIEJpdFN0cmluZy53cmFwKHZhbHVlLCB7IFwic2l6ZVwiOiBjb3VudCB9KTtcbiAgfVxuXG4gIHN0YXRpYyB1bml0KHZhbHVlLCBjb3VudCkge1xuICAgIHJldHVybiBCaXRTdHJpbmcud3JhcCh2YWx1ZSwgeyBcInVuaXRcIjogY291bnQgfSk7XG4gIH1cblxuICBzdGF0aWMgd3JhcCh2YWx1ZSwgb3B0LCBuZXdfYXR0cmlidXRlID0gbnVsbCkge1xuICAgIGxldCB0aGVfdmFsdWUgPSB2YWx1ZTtcblxuICAgIGlmICghKHZhbHVlIGluc3RhbmNlb2YgT2JqZWN0KSkge1xuICAgICAgdGhlX3ZhbHVlID0geyBcInZhbHVlXCI6IHZhbHVlLCBcImF0dHJpYnV0ZXNcIjogW10gfTtcbiAgICB9XG5cbiAgICB0aGVfdmFsdWUgPSBPYmplY3QuYXNzaWduKHRoZV92YWx1ZSwgb3B0KTtcblxuICAgIGlmIChuZXdfYXR0cmlidXRlKSB7XG4gICAgICB0aGVfdmFsdWUuYXR0cmlidXRlcy5wdXNoKG5ld19hdHRyaWJ1dGUpO1xuICAgIH1cblxuICAgIHJldHVybiB0aGVfdmFsdWU7XG4gIH1cblxuICBzdGF0aWMgdG9VVEY4QXJyYXkoc3RyKSB7XG4gICAgdmFyIHV0ZjggPSBbXTtcbiAgICBmb3IgKHZhciBpID0gMDsgaSA8IHN0ci5sZW5ndGg7IGkrKykge1xuICAgICAgdmFyIGNoYXJjb2RlID0gc3RyLmNoYXJDb2RlQXQoaSk7XG4gICAgICBpZiAoY2hhcmNvZGUgPCAxMjgpIHtcbiAgICAgICAgdXRmOC5wdXNoKGNoYXJjb2RlKTtcbiAgICAgIH0gZWxzZSBpZiAoY2hhcmNvZGUgPCAyMDQ4KSB7XG4gICAgICAgIHV0ZjgucHVzaCgxOTIgfCBjaGFyY29kZSA+PiA2LCAxMjggfCBjaGFyY29kZSAmIDYzKTtcbiAgICAgIH0gZWxzZSBpZiAoY2hhcmNvZGUgPCA1NTI5NiB8fCBjaGFyY29kZSA+PSA1NzM0NCkge1xuICAgICAgICB1dGY4LnB1c2goMjI0IHwgY2hhcmNvZGUgPj4gMTIsIDEyOCB8IGNoYXJjb2RlID4+IDYgJiA2MywgMTI4IHwgY2hhcmNvZGUgJiA2Myk7XG4gICAgICB9XG4gICAgICAvLyBzdXJyb2dhdGUgcGFpclxuICAgICAgZWxzZSB7XG4gICAgICAgIGkrKztcbiAgICAgICAgLy8gVVRGLTE2IGVuY29kZXMgMHgxMDAwMC0weDEwRkZGRiBieVxuICAgICAgICAvLyBzdWJ0cmFjdGluZyAweDEwMDAwIGFuZCBzcGxpdHRpbmcgdGhlXG4gICAgICAgIC8vIDIwIGJpdHMgb2YgMHgwLTB4RkZGRkYgaW50byB0d28gaGFsdmVzXG4gICAgICAgIGNoYXJjb2RlID0gNjU1MzYgKyAoKGNoYXJjb2RlICYgMTAyMykgPDwgMTAgfCBzdHIuY2hhckNvZGVBdChpKSAmIDEwMjMpO1xuICAgICAgICB1dGY4LnB1c2goMjQwIHwgY2hhcmNvZGUgPj4gMTgsIDEyOCB8IGNoYXJjb2RlID4+IDEyICYgNjMsIDEyOCB8IGNoYXJjb2RlID4+IDYgJiA2MywgMTI4IHwgY2hhcmNvZGUgJiA2Myk7XG4gICAgICB9XG4gICAgfVxuICAgIHJldHVybiB1dGY4O1xuICB9XG5cbiAgc3RhdGljIHRvVVRGMTZBcnJheShzdHIpIHtcbiAgICB2YXIgdXRmMTYgPSBbXTtcbiAgICBmb3IgKHZhciBpID0gMDsgaSA8IHN0ci5sZW5ndGg7IGkrKykge1xuICAgICAgdmFyIGNvZGVQb2ludCA9IHN0ci5jb2RlUG9pbnRBdChpKTtcblxuICAgICAgaWYgKGNvZGVQb2ludCA8PSAyNTUpIHtcbiAgICAgICAgdXRmMTYucHVzaCgwKTtcbiAgICAgICAgdXRmMTYucHVzaChjb2RlUG9pbnQpO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgdXRmMTYucHVzaChjb2RlUG9pbnQgPj4gOCAmIDI1NSk7XG4gICAgICAgIHV0ZjE2LnB1c2goY29kZVBvaW50ICYgMjU1KTtcbiAgICAgIH1cbiAgICB9XG4gICAgcmV0dXJuIHV0ZjE2O1xuICB9XG5cbiAgc3RhdGljIHRvVVRGMzJBcnJheShzdHIpIHtcbiAgICB2YXIgdXRmMzIgPSBbXTtcbiAgICBmb3IgKHZhciBpID0gMDsgaSA8IHN0ci5sZW5ndGg7IGkrKykge1xuICAgICAgdmFyIGNvZGVQb2ludCA9IHN0ci5jb2RlUG9pbnRBdChpKTtcblxuICAgICAgaWYgKGNvZGVQb2ludCA8PSAyNTUpIHtcbiAgICAgICAgdXRmMzIucHVzaCgwKTtcbiAgICAgICAgdXRmMzIucHVzaCgwKTtcbiAgICAgICAgdXRmMzIucHVzaCgwKTtcbiAgICAgICAgdXRmMzIucHVzaChjb2RlUG9pbnQpO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgdXRmMzIucHVzaCgwKTtcbiAgICAgICAgdXRmMzIucHVzaCgwKTtcbiAgICAgICAgdXRmMzIucHVzaChjb2RlUG9pbnQgPj4gOCAmIDI1NSk7XG4gICAgICAgIHV0ZjMyLnB1c2goY29kZVBvaW50ICYgMjU1KTtcbiAgICAgIH1cbiAgICB9XG4gICAgcmV0dXJuIHV0ZjMyO1xuICB9XG5cbiAgLy9odHRwOi8vc3RhY2tvdmVyZmxvdy5jb20vcXVlc3Rpb25zLzIwMDM0OTMvamF2YXNjcmlwdC1mbG9hdC1mcm9tLXRvLWJpdHNcbiAgc3RhdGljIGZsb2F0MzJUb0J5dGVzKGYpIHtcbiAgICB2YXIgYnl0ZXMgPSBbXTtcblxuICAgIHZhciBidWYgPSBuZXcgQXJyYXlCdWZmZXIoNCk7XG4gICAgbmV3IEZsb2F0MzJBcnJheShidWYpWzBdID0gZjtcblxuICAgIGxldCBpbnRWZXJzaW9uID0gbmV3IFVpbnQzMkFycmF5KGJ1ZilbMF07XG5cbiAgICBieXRlcy5wdXNoKGludFZlcnNpb24gPj4gMjQgJiAyNTUpO1xuICAgIGJ5dGVzLnB1c2goaW50VmVyc2lvbiA+PiAxNiAmIDI1NSk7XG4gICAgYnl0ZXMucHVzaChpbnRWZXJzaW9uID4+IDggJiAyNTUpO1xuICAgIGJ5dGVzLnB1c2goaW50VmVyc2lvbiAmIDI1NSk7XG5cbiAgICByZXR1cm4gYnl0ZXM7XG4gIH1cblxuICBzdGF0aWMgZmxvYXQ2NFRvQnl0ZXMoZikge1xuICAgIHZhciBieXRlcyA9IFtdO1xuXG4gICAgdmFyIGJ1ZiA9IG5ldyBBcnJheUJ1ZmZlcig4KTtcbiAgICBuZXcgRmxvYXQ2NEFycmF5KGJ1ZilbMF0gPSBmO1xuXG4gICAgdmFyIGludFZlcnNpb24xID0gbmV3IFVpbnQzMkFycmF5KGJ1ZilbMF07XG4gICAgdmFyIGludFZlcnNpb24yID0gbmV3IFVpbnQzMkFycmF5KGJ1ZilbMV07XG5cbiAgICBieXRlcy5wdXNoKGludFZlcnNpb24yID4+IDI0ICYgMjU1KTtcbiAgICBieXRlcy5wdXNoKGludFZlcnNpb24yID4+IDE2ICYgMjU1KTtcbiAgICBieXRlcy5wdXNoKGludFZlcnNpb24yID4+IDggJiAyNTUpO1xuICAgIGJ5dGVzLnB1c2goaW50VmVyc2lvbjIgJiAyNTUpO1xuXG4gICAgYnl0ZXMucHVzaChpbnRWZXJzaW9uMSA+PiAyNCAmIDI1NSk7XG4gICAgYnl0ZXMucHVzaChpbnRWZXJzaW9uMSA+PiAxNiAmIDI1NSk7XG4gICAgYnl0ZXMucHVzaChpbnRWZXJzaW9uMSA+PiA4ICYgMjU1KTtcbiAgICBieXRlcy5wdXNoKGludFZlcnNpb24xICYgMjU1KTtcblxuICAgIHJldHVybiBieXRlcztcbiAgfVxufVxuXG4vKiBAZmxvdyAqL1xuXG5jbGFzcyBWYXJpYWJsZSB7XG5cbiAgY29uc3RydWN0b3IobmFtZSA9IG51bGwpIHtcbiAgICB0aGlzLm5hbWUgPSBuYW1lO1xuICB9XG59XG5cbmNsYXNzIFdpbGRjYXJkIHtcbiAgY29uc3RydWN0b3IoKSB7fVxufVxuXG5jbGFzcyBTdGFydHNXaXRoIHtcblxuICBjb25zdHJ1Y3RvcihwcmVmaXgpIHtcbiAgICB0aGlzLnByZWZpeCA9IHByZWZpeDtcbiAgfVxufVxuXG5jbGFzcyBDYXB0dXJlIHtcblxuICBjb25zdHJ1Y3Rvcih2YWx1ZSkge1xuICAgIHRoaXMudmFsdWUgPSB2YWx1ZTtcbiAgfVxufVxuXG5jbGFzcyBIZWFkVGFpbCB7XG5cbiAgY29uc3RydWN0b3IoaGVhZCA9IG51bGwsIHRhaWwgPSBudWxsKSB7XG4gICAgdGhpcy5oZWFkID0gaGVhZDtcbiAgICB0aGlzLnRhaWwgPSB0YWlsO1xuICB9XG59XG5cbmNsYXNzIFR5cGUge1xuXG4gIGNvbnN0cnVjdG9yKHR5cGUsIG9ialBhdHRlcm4gPSB7fSkge1xuICAgIHRoaXMudHlwZSA9IHR5cGU7XG4gICAgdGhpcy5vYmpQYXR0ZXJuID0gb2JqUGF0dGVybjtcbiAgfVxufVxuXG5jbGFzcyBCb3VuZCB7XG5cbiAgY29uc3RydWN0b3IodmFsdWUpIHtcbiAgICB0aGlzLnZhbHVlID0gdmFsdWU7XG4gIH1cbn1cblxuZnVuY3Rpb24gdmFyaWFibGUobmFtZSA9IG51bGwpIHtcbiAgcmV0dXJuIG5ldyBWYXJpYWJsZShuYW1lKTtcbn1cblxuZnVuY3Rpb24gd2lsZGNhcmQoKSB7XG4gIHJldHVybiBuZXcgV2lsZGNhcmQoKTtcbn1cblxuZnVuY3Rpb24gc3RhcnRzV2l0aChwcmVmaXgpIHtcbiAgcmV0dXJuIG5ldyBTdGFydHNXaXRoKHByZWZpeCk7XG59XG5cbmZ1bmN0aW9uIGNhcHR1cmUodmFsdWUpIHtcbiAgcmV0dXJuIG5ldyBDYXB0dXJlKHZhbHVlKTtcbn1cblxuZnVuY3Rpb24gaGVhZFRhaWwoaGVhZCA9IG51bGwsIHRhaWwgPSBudWxsKSB7XG4gIHJldHVybiBuZXcgSGVhZFRhaWwoaGVhZCwgdGFpbCk7XG59XG5cbmZ1bmN0aW9uIHR5cGUodHlwZSwgb2JqUGF0dGVybiA9IHt9KSB7XG4gIHJldHVybiBuZXcgVHlwZSh0eXBlLCBvYmpQYXR0ZXJuKTtcbn1cblxuZnVuY3Rpb24gYm91bmQodmFsdWUpIHtcbiAgcmV0dXJuIG5ldyBCb3VuZCh2YWx1ZSk7XG59XG5cbmZ1bmN0aW9uIGlzX251bWJlcih2YWx1ZSkge1xuICByZXR1cm4gdHlwZW9mIHZhbHVlID09PSAnbnVtYmVyJztcbn1cblxuZnVuY3Rpb24gaXNfc3RyaW5nKHZhbHVlKSB7XG4gIHJldHVybiB0eXBlb2YgdmFsdWUgPT09ICdzdHJpbmcnO1xufVxuXG5mdW5jdGlvbiBpc19ib29sZWFuKHZhbHVlKSB7XG4gIHJldHVybiB0eXBlb2YgdmFsdWUgPT09ICdib29sZWFuJztcbn1cblxuZnVuY3Rpb24gaXNfc3ltYm9sKHZhbHVlKSB7XG4gIHJldHVybiB0eXBlb2YgdmFsdWUgPT09ICdzeW1ib2wnO1xufVxuXG5mdW5jdGlvbiBpc19udWxsKHZhbHVlKSB7XG4gIHJldHVybiB2YWx1ZSA9PT0gbnVsbDtcbn1cblxuZnVuY3Rpb24gaXNfdW5kZWZpbmVkKHZhbHVlKSB7XG4gIHJldHVybiB0eXBlb2YgdmFsdWUgPT09ICd1bmRlZmluZWQnO1xufVxuXG5mdW5jdGlvbiBpc19mdW5jdGlvbih2YWx1ZSkge1xuICByZXR1cm4gT2JqZWN0LnByb3RvdHlwZS50b1N0cmluZy5jYWxsKHZhbHVlKSA9PSAnW29iamVjdCBGdW5jdGlvbl0nO1xufVxuXG5mdW5jdGlvbiBpc192YXJpYWJsZSh2YWx1ZSkge1xuICByZXR1cm4gdmFsdWUgaW5zdGFuY2VvZiBWYXJpYWJsZTtcbn1cblxuZnVuY3Rpb24gaXNfd2lsZGNhcmQodmFsdWUpIHtcbiAgcmV0dXJuIHZhbHVlIGluc3RhbmNlb2YgV2lsZGNhcmQ7XG59XG5cbmZ1bmN0aW9uIGlzX2hlYWRUYWlsKHZhbHVlKSB7XG4gIHJldHVybiB2YWx1ZSBpbnN0YW5jZW9mIEhlYWRUYWlsO1xufVxuXG5mdW5jdGlvbiBpc19jYXB0dXJlKHZhbHVlKSB7XG4gIHJldHVybiB2YWx1ZSBpbnN0YW5jZW9mIENhcHR1cmU7XG59XG5cbmZ1bmN0aW9uIGlzX3R5cGUodmFsdWUpIHtcbiAgcmV0dXJuIHZhbHVlIGluc3RhbmNlb2YgVHlwZTtcbn1cblxuZnVuY3Rpb24gaXNfc3RhcnRzV2l0aCh2YWx1ZSkge1xuICByZXR1cm4gdmFsdWUgaW5zdGFuY2VvZiBTdGFydHNXaXRoO1xufVxuXG5mdW5jdGlvbiBpc19ib3VuZCh2YWx1ZSkge1xuICByZXR1cm4gdmFsdWUgaW5zdGFuY2VvZiBCb3VuZDtcbn1cblxuZnVuY3Rpb24gaXNfb2JqZWN0KHZhbHVlKSB7XG4gIHJldHVybiB0eXBlb2YgdmFsdWUgPT09ICdvYmplY3QnO1xufVxuXG5mdW5jdGlvbiBpc19hcnJheSh2YWx1ZSkge1xuICByZXR1cm4gQXJyYXkuaXNBcnJheSh2YWx1ZSk7XG59XG5cbnZhciBDaGVja3MgPSB7XG4gIGlzX251bWJlcixcbiAgaXNfc3RyaW5nLFxuICBpc19ib29sZWFuLFxuICBpc19zeW1ib2wsXG4gIGlzX251bGwsXG4gIGlzX3VuZGVmaW5lZCxcbiAgaXNfZnVuY3Rpb24sXG4gIGlzX3ZhcmlhYmxlLFxuICBpc193aWxkY2FyZCxcbiAgaXNfaGVhZFRhaWwsXG4gIGlzX2NhcHR1cmUsXG4gIGlzX3R5cGUsXG4gIGlzX3N0YXJ0c1dpdGgsXG4gIGlzX2JvdW5kLFxuICBpc19vYmplY3QsXG4gIGlzX2FycmF5XG59O1xuXG5mdW5jdGlvbiByZXNvbHZlU3ltYm9sKHBhdHRlcm4pIHtcbiAgcmV0dXJuIGZ1bmN0aW9uICh2YWx1ZSkge1xuICAgIHJldHVybiBDaGVja3MuaXNfc3ltYm9sKHZhbHVlKSAmJiB2YWx1ZSA9PT0gcGF0dGVybjtcbiAgfTtcbn1cblxuZnVuY3Rpb24gcmVzb2x2ZVN0cmluZyhwYXR0ZXJuKSB7XG4gIHJldHVybiBmdW5jdGlvbiAodmFsdWUpIHtcbiAgICByZXR1cm4gQ2hlY2tzLmlzX3N0cmluZyh2YWx1ZSkgJiYgdmFsdWUgPT09IHBhdHRlcm47XG4gIH07XG59XG5cbmZ1bmN0aW9uIHJlc29sdmVOdW1iZXIocGF0dGVybikge1xuICByZXR1cm4gZnVuY3Rpb24gKHZhbHVlKSB7XG4gICAgcmV0dXJuIENoZWNrcy5pc19udW1iZXIodmFsdWUpICYmIHZhbHVlID09PSBwYXR0ZXJuO1xuICB9O1xufVxuXG5mdW5jdGlvbiByZXNvbHZlQm9vbGVhbihwYXR0ZXJuKSB7XG4gIHJldHVybiBmdW5jdGlvbiAodmFsdWUpIHtcbiAgICByZXR1cm4gQ2hlY2tzLmlzX2Jvb2xlYW4odmFsdWUpICYmIHZhbHVlID09PSBwYXR0ZXJuO1xuICB9O1xufVxuXG5mdW5jdGlvbiByZXNvbHZlRnVuY3Rpb24ocGF0dGVybikge1xuICByZXR1cm4gZnVuY3Rpb24gKHZhbHVlKSB7XG4gICAgcmV0dXJuIENoZWNrcy5pc19mdW5jdGlvbih2YWx1ZSkgJiYgdmFsdWUgPT09IHBhdHRlcm47XG4gIH07XG59XG5cbmZ1bmN0aW9uIHJlc29sdmVOdWxsKHBhdHRlcm4pIHtcbiAgcmV0dXJuIGZ1bmN0aW9uICh2YWx1ZSkge1xuICAgIHJldHVybiBDaGVja3MuaXNfbnVsbCh2YWx1ZSk7XG4gIH07XG59XG5cbmZ1bmN0aW9uIHJlc29sdmVCb3VuZChwYXR0ZXJuKSB7XG4gIHJldHVybiBmdW5jdGlvbiAodmFsdWUsIGFyZ3MpIHtcbiAgICBpZiAodHlwZW9mIHZhbHVlID09PSB0eXBlb2YgcGF0dGVybi52YWx1ZSAmJiB2YWx1ZSA9PT0gcGF0dGVybi52YWx1ZSkge1xuICAgICAgYXJncy5wdXNoKHZhbHVlKTtcbiAgICAgIHJldHVybiB0cnVlO1xuICAgIH1cblxuICAgIHJldHVybiBmYWxzZTtcbiAgfTtcbn1cblxuZnVuY3Rpb24gcmVzb2x2ZVdpbGRjYXJkKCkge1xuICByZXR1cm4gZnVuY3Rpb24gKCkge1xuICAgIHJldHVybiB0cnVlO1xuICB9O1xufVxuXG5mdW5jdGlvbiByZXNvbHZlVmFyaWFibGUoKSB7XG4gIHJldHVybiBmdW5jdGlvbiAodmFsdWUsIGFyZ3MpIHtcbiAgICBhcmdzLnB1c2godmFsdWUpO1xuICAgIHJldHVybiB0cnVlO1xuICB9O1xufVxuXG5mdW5jdGlvbiByZXNvbHZlSGVhZFRhaWwocGF0dGVybikge1xuICBjb25zdCBoZWFkTWF0Y2hlcyA9IGJ1aWxkTWF0Y2gocGF0dGVybi5oZWFkKTtcbiAgY29uc3QgdGFpbE1hdGNoZXMgPSBidWlsZE1hdGNoKHBhdHRlcm4udGFpbCk7XG5cbiAgcmV0dXJuIGZ1bmN0aW9uICh2YWx1ZSwgYXJncykge1xuICAgIGlmICghQ2hlY2tzLmlzX2FycmF5KHZhbHVlKSB8fCB2YWx1ZS5sZW5ndGggPCAyKSB7XG4gICAgICByZXR1cm4gZmFsc2U7XG4gICAgfVxuXG4gICAgY29uc3QgaGVhZCA9IHZhbHVlWzBdO1xuICAgIGNvbnN0IHRhaWwgPSB2YWx1ZS5zbGljZSgxKTtcblxuICAgIGlmIChoZWFkTWF0Y2hlcyhoZWFkLCBhcmdzKSAmJiB0YWlsTWF0Y2hlcyh0YWlsLCBhcmdzKSkge1xuICAgICAgcmV0dXJuIHRydWU7XG4gICAgfVxuICB9O1xufVxuXG5mdW5jdGlvbiByZXNvbHZlQ2FwdHVyZShwYXR0ZXJuKSB7XG4gIGNvbnN0IG1hdGNoZXMgPSBidWlsZE1hdGNoKHBhdHRlcm4udmFsdWUpO1xuXG4gIHJldHVybiBmdW5jdGlvbiAodmFsdWUsIGFyZ3MpIHtcbiAgICBpZiAobWF0Y2hlcyh2YWx1ZSwgYXJncykpIHtcbiAgICAgIGFyZ3MucHVzaCh2YWx1ZSk7XG4gICAgICByZXR1cm4gdHJ1ZTtcbiAgICB9XG5cbiAgICByZXR1cm4gZmFsc2U7XG4gIH07XG59XG5cbmZ1bmN0aW9uIHJlc29sdmVTdGFydHNXaXRoKHBhdHRlcm4pIHtcbiAgY29uc3QgcHJlZml4ID0gcGF0dGVybi5wcmVmaXg7XG5cbiAgcmV0dXJuIGZ1bmN0aW9uICh2YWx1ZSwgYXJncykge1xuICAgIGlmIChDaGVja3MuaXNfc3RyaW5nKHZhbHVlKSAmJiB2YWx1ZS5zdGFydHNXaXRoKHByZWZpeCkpIHtcbiAgICAgIGFyZ3MucHVzaCh2YWx1ZS5zdWJzdHJpbmcocHJlZml4Lmxlbmd0aCkpO1xuICAgICAgcmV0dXJuIHRydWU7XG4gICAgfVxuXG4gICAgcmV0dXJuIGZhbHNlO1xuICB9O1xufVxuXG5mdW5jdGlvbiByZXNvbHZlVHlwZShwYXR0ZXJuKSB7XG4gIHJldHVybiBmdW5jdGlvbiAodmFsdWUsIGFyZ3MpIHtcbiAgICBpZiAodmFsdWUgaW5zdGFuY2VvZiBwYXR0ZXJuLnR5cGUpIHtcbiAgICAgIGNvbnN0IG1hdGNoZXMgPSBidWlsZE1hdGNoKHBhdHRlcm4ub2JqUGF0dGVybik7XG4gICAgICByZXR1cm4gbWF0Y2hlcyh2YWx1ZSwgYXJncykgJiYgYXJncy5wdXNoKHZhbHVlKSA+IDA7XG4gICAgfVxuXG4gICAgcmV0dXJuIGZhbHNlO1xuICB9O1xufVxuXG5mdW5jdGlvbiByZXNvbHZlQXJyYXkocGF0dGVybikge1xuICBjb25zdCBtYXRjaGVzID0gcGF0dGVybi5tYXAoeCA9PiBidWlsZE1hdGNoKHgpKTtcblxuICByZXR1cm4gZnVuY3Rpb24gKHZhbHVlLCBhcmdzKSB7XG4gICAgaWYgKCFDaGVja3MuaXNfYXJyYXkodmFsdWUpIHx8IHZhbHVlLmxlbmd0aCAhPSBwYXR0ZXJuLmxlbmd0aCkge1xuICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH1cblxuICAgIHJldHVybiB2YWx1ZS5ldmVyeShmdW5jdGlvbiAodiwgaSkge1xuICAgICAgcmV0dXJuIG1hdGNoZXNbaV0odmFsdWVbaV0sIGFyZ3MpO1xuICAgIH0pO1xuICB9O1xufVxuXG5mdW5jdGlvbiByZXNvbHZlT2JqZWN0KHBhdHRlcm4pIHtcbiAgbGV0IG1hdGNoZXMgPSB7fTtcblxuICBmb3IgKGxldCBrZXkgb2YgT2JqZWN0LmtleXMocGF0dGVybikuY29uY2F0KE9iamVjdC5nZXRPd25Qcm9wZXJ0eVN5bWJvbHMocGF0dGVybikpKSB7XG4gICAgbWF0Y2hlc1trZXldID0gYnVpbGRNYXRjaChwYXR0ZXJuW2tleV0pO1xuICB9XG5cbiAgcmV0dXJuIGZ1bmN0aW9uICh2YWx1ZSwgYXJncykge1xuICAgIGlmICghQ2hlY2tzLmlzX29iamVjdCh2YWx1ZSkgfHwgcGF0dGVybi5sZW5ndGggPiB2YWx1ZS5sZW5ndGgpIHtcbiAgICAgIHJldHVybiBmYWxzZTtcbiAgICB9XG5cbiAgICBmb3IgKGxldCBrZXkgb2YgT2JqZWN0LmtleXMocGF0dGVybikuY29uY2F0KE9iamVjdC5nZXRPd25Qcm9wZXJ0eVN5bWJvbHMocGF0dGVybikpKSB7XG4gICAgICBpZiAoIShrZXkgaW4gdmFsdWUpIHx8ICFtYXRjaGVzW2tleV0odmFsdWVba2V5XSwgYXJncykpIHtcbiAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgfVxuICAgIH1cblxuICAgIHJldHVybiB0cnVlO1xuICB9O1xufVxuXG5mdW5jdGlvbiByZXNvbHZlTm9NYXRjaCgpIHtcbiAgcmV0dXJuIGZ1bmN0aW9uICgpIHtcbiAgICByZXR1cm4gZmFsc2U7XG4gIH07XG59XG5cbnZhciBSZXNvbHZlcnMgPSB7XG4gIHJlc29sdmVCb3VuZCxcbiAgcmVzb2x2ZVdpbGRjYXJkLFxuICByZXNvbHZlVmFyaWFibGUsXG4gIHJlc29sdmVIZWFkVGFpbCxcbiAgcmVzb2x2ZUNhcHR1cmUsXG4gIHJlc29sdmVTdGFydHNXaXRoLFxuICByZXNvbHZlVHlwZSxcbiAgcmVzb2x2ZUFycmF5LFxuICByZXNvbHZlT2JqZWN0LFxuICByZXNvbHZlTm9NYXRjaCxcbiAgcmVzb2x2ZVN5bWJvbCxcbiAgcmVzb2x2ZVN0cmluZyxcbiAgcmVzb2x2ZU51bWJlcixcbiAgcmVzb2x2ZUJvb2xlYW4sXG4gIHJlc29sdmVGdW5jdGlvbixcbiAgcmVzb2x2ZU51bGxcbn07XG5cbmZ1bmN0aW9uIGJ1aWxkTWF0Y2gocGF0dGVybikge1xuXG4gIGlmIChDaGVja3MuaXNfdmFyaWFibGUocGF0dGVybikpIHtcbiAgICByZXR1cm4gUmVzb2x2ZXJzLnJlc29sdmVWYXJpYWJsZShwYXR0ZXJuKTtcbiAgfVxuXG4gIGlmIChDaGVja3MuaXNfd2lsZGNhcmQocGF0dGVybikpIHtcbiAgICByZXR1cm4gUmVzb2x2ZXJzLnJlc29sdmVXaWxkY2FyZChwYXR0ZXJuKTtcbiAgfVxuXG4gIGlmIChDaGVja3MuaXNfdW5kZWZpbmVkKHBhdHRlcm4pKSB7XG4gICAgcmV0dXJuIFJlc29sdmVycy5yZXNvbHZlV2lsZGNhcmQocGF0dGVybik7XG4gIH1cblxuICBpZiAoQ2hlY2tzLmlzX2hlYWRUYWlsKHBhdHRlcm4pKSB7XG4gICAgcmV0dXJuIFJlc29sdmVycy5yZXNvbHZlSGVhZFRhaWwocGF0dGVybik7XG4gIH1cblxuICBpZiAoQ2hlY2tzLmlzX3N0YXJ0c1dpdGgocGF0dGVybikpIHtcbiAgICByZXR1cm4gUmVzb2x2ZXJzLnJlc29sdmVTdGFydHNXaXRoKHBhdHRlcm4pO1xuICB9XG5cbiAgaWYgKENoZWNrcy5pc19jYXB0dXJlKHBhdHRlcm4pKSB7XG4gICAgcmV0dXJuIFJlc29sdmVycy5yZXNvbHZlQ2FwdHVyZShwYXR0ZXJuKTtcbiAgfVxuXG4gIGlmIChDaGVja3MuaXNfYm91bmQocGF0dGVybikpIHtcbiAgICByZXR1cm4gUmVzb2x2ZXJzLnJlc29sdmVCb3VuZChwYXR0ZXJuKTtcbiAgfVxuXG4gIGlmIChDaGVja3MuaXNfdHlwZShwYXR0ZXJuKSkge1xuICAgIHJldHVybiBSZXNvbHZlcnMucmVzb2x2ZVR5cGUocGF0dGVybik7XG4gIH1cblxuICBpZiAoQ2hlY2tzLmlzX2FycmF5KHBhdHRlcm4pKSB7XG4gICAgcmV0dXJuIFJlc29sdmVycy5yZXNvbHZlQXJyYXkocGF0dGVybik7XG4gIH1cblxuICBpZiAoQ2hlY2tzLmlzX251bWJlcihwYXR0ZXJuKSkge1xuICAgIHJldHVybiBSZXNvbHZlcnMucmVzb2x2ZU51bWJlcihwYXR0ZXJuKTtcbiAgfVxuXG4gIGlmIChDaGVja3MuaXNfc3RyaW5nKHBhdHRlcm4pKSB7XG4gICAgcmV0dXJuIFJlc29sdmVycy5yZXNvbHZlU3RyaW5nKHBhdHRlcm4pO1xuICB9XG5cbiAgaWYgKENoZWNrcy5pc19ib29sZWFuKHBhdHRlcm4pKSB7XG4gICAgcmV0dXJuIFJlc29sdmVycy5yZXNvbHZlQm9vbGVhbihwYXR0ZXJuKTtcbiAgfVxuXG4gIGlmIChDaGVja3MuaXNfc3ltYm9sKHBhdHRlcm4pKSB7XG4gICAgcmV0dXJuIFJlc29sdmVycy5yZXNvbHZlU3ltYm9sKHBhdHRlcm4pO1xuICB9XG5cbiAgaWYgKENoZWNrcy5pc19udWxsKHBhdHRlcm4pKSB7XG4gICAgcmV0dXJuIFJlc29sdmVycy5yZXNvbHZlTnVsbChwYXR0ZXJuKTtcbiAgfVxuXG4gIGlmIChDaGVja3MuaXNfb2JqZWN0KHBhdHRlcm4pKSB7XG4gICAgcmV0dXJuIFJlc29sdmVycy5yZXNvbHZlT2JqZWN0KHBhdHRlcm4pO1xuICB9XG5cbiAgcmV0dXJuIFJlc29sdmVycy5yZXNvbHZlTm9NYXRjaCgpO1xufVxuXG5jbGFzcyBNYXRjaEVycm9yIGV4dGVuZHMgRXJyb3Ige1xuICBjb25zdHJ1Y3RvcihhcmcpIHtcbiAgICBzdXBlcigpO1xuXG4gICAgaWYgKHR5cGVvZiBhcmcgPT09ICdzeW1ib2wnKSB7XG4gICAgICB0aGlzLm1lc3NhZ2UgPSAnTm8gbWF0Y2ggZm9yOiAnICsgYXJnLnRvU3RyaW5nKCk7XG4gICAgfSBlbHNlIGlmIChBcnJheS5pc0FycmF5KGFyZykpIHtcbiAgICAgIGxldCBtYXBwZWRWYWx1ZXMgPSBhcmcubWFwKHggPT4geC50b1N0cmluZygpKTtcbiAgICAgIHRoaXMubWVzc2FnZSA9ICdObyBtYXRjaCBmb3I6ICcgKyBtYXBwZWRWYWx1ZXM7XG4gICAgfSBlbHNlIHtcbiAgICAgIHRoaXMubWVzc2FnZSA9ICdObyBtYXRjaCBmb3I6ICcgKyBhcmc7XG4gICAgfVxuXG4gICAgdGhpcy5zdGFjayA9IG5ldyBFcnJvcigpLnN0YWNrO1xuICAgIHRoaXMubmFtZSA9IHRoaXMuY29uc3RydWN0b3IubmFtZTtcbiAgfVxufVxuXG5jbGFzcyBDYXNlIHtcblxuICBjb25zdHJ1Y3RvcihwYXR0ZXJuLCBmbiwgZ3VhcmQgPSAoKSA9PiB0cnVlKSB7XG4gICAgdGhpcy5wYXR0ZXJuID0gYnVpbGRNYXRjaChwYXR0ZXJuKTtcbiAgICB0aGlzLmZuID0gZm47XG4gICAgdGhpcy5ndWFyZCA9IGd1YXJkO1xuICB9XG59XG5cbmZ1bmN0aW9uIG1ha2VfY2FzZShwYXR0ZXJuLCBmbiwgZ3VhcmQgPSAoKSA9PiB0cnVlKSB7XG4gIHJldHVybiBuZXcgQ2FzZShwYXR0ZXJuLCBmbiwgZ3VhcmQpO1xufVxuXG5mdW5jdGlvbiBkZWZtYXRjaCguLi5jYXNlcykge1xuICByZXR1cm4gZnVuY3Rpb24gKC4uLmFyZ3MpIHtcbiAgICBmb3IgKGxldCBwcm9jZXNzZWRDYXNlIG9mIGNhc2VzKSB7XG4gICAgICBsZXQgcmVzdWx0ID0gW107XG4gICAgICBpZiAocHJvY2Vzc2VkQ2FzZS5wYXR0ZXJuKGFyZ3MsIHJlc3VsdCkgJiYgcHJvY2Vzc2VkQ2FzZS5ndWFyZC5hcHBseSh0aGlzLCByZXN1bHQpKSB7XG4gICAgICAgIHJldHVybiBwcm9jZXNzZWRDYXNlLmZuLmFwcGx5KHRoaXMsIHJlc3VsdCk7XG4gICAgICB9XG4gICAgfVxuXG4gICAgdGhyb3cgbmV3IE1hdGNoRXJyb3IoYXJncyk7XG4gIH07XG59XG5cbmZ1bmN0aW9uIG1hdGNoKHBhdHRlcm4sIGV4cHIsIGd1YXJkID0gKCkgPT4gdHJ1ZSkge1xuICBsZXQgcmVzdWx0ID0gW107XG4gIGxldCBwcm9jZXNzZWRQYXR0ZXJuID0gYnVpbGRNYXRjaChwYXR0ZXJuKTtcbiAgaWYgKHByb2Nlc3NlZFBhdHRlcm4oZXhwciwgcmVzdWx0KSAmJiBndWFyZC5hcHBseSh0aGlzLCByZXN1bHQpKSB7XG4gICAgcmV0dXJuIHJlc3VsdDtcbiAgfSBlbHNlIHtcbiAgICB0aHJvdyBuZXcgTWF0Y2hFcnJvcihleHByKTtcbiAgfVxufVxuXG5mdW5jdGlvbiBtYXRjaF9ub190aHJvdyhwYXR0ZXJuLCBleHByLCBndWFyZCA9ICgpID0+IHRydWUpIHtcbiAgdHJ5IHtcbiAgICByZXR1cm4gbWF0Y2gocGF0dGVybiwgZXhwciwgZ3VhcmQpO1xuICB9IGNhdGNoIChlKSB7XG4gICAgaWYgKGUgaW5zdGFuY2VvZiBNYXRjaEVycm9yKSB7XG4gICAgICByZXR1cm4gbnVsbDtcbiAgICB9XG5cbiAgICB0aHJvdyBlO1xuICB9XG59XG5cbnZhciBQYXR0ZXJucyA9IHtcbiAgZGVmbWF0Y2gsIG1hdGNoLCBNYXRjaEVycm9yLCBtYXRjaF9ub190aHJvdyxcbiAgdmFyaWFibGUsIHdpbGRjYXJkLCBzdGFydHNXaXRoLFxuICBjYXB0dXJlLCBoZWFkVGFpbCwgdHlwZSwgYm91bmQsIENhc2UsIG1ha2VfY2FzZVxufTtcblxuLy9odHRwczovL2dpdGh1Yi5jb20vYWlycG9ydHloL3Byb3RvbW9ycGhpc21cbmNsYXNzIFByb3RvY29sIHtcbiAgY29uc3RydWN0b3Ioc3BlYykge1xuICAgIHRoaXMucmVnaXN0cnkgPSBuZXcgTWFwKCk7XG4gICAgdGhpcy5mYWxsYmFjayA9IG51bGw7XG5cbiAgICBmb3IgKGxldCBmdW5OYW1lIGluIHNwZWMpIHtcbiAgICAgIHRoaXNbZnVuTmFtZV0gPSBjcmVhdGVGdW4oZnVuTmFtZSkuYmluZCh0aGlzKTtcbiAgICB9XG5cbiAgICBmdW5jdGlvbiBjcmVhdGVGdW4oZnVuTmFtZSkge1xuXG4gICAgICByZXR1cm4gZnVuY3Rpb24gKC4uLmFyZ3MpIHtcbiAgICAgICAgbGV0IHRoaW5nID0gYXJnc1swXTtcbiAgICAgICAgbGV0IGZ1biA9IG51bGw7XG5cbiAgICAgICAgaWYgKE51bWJlci5pc0ludGVnZXIodGhpbmcpICYmIHRoaXMuaGFzSW1wbGVtZW50YXRpb24oSW50ZWdlcikpIHtcbiAgICAgICAgICBmdW4gPSB0aGlzLnJlZ2lzdHJ5LmdldChJbnRlZ2VyKVtmdW5OYW1lXTtcbiAgICAgICAgfSBlbHNlIGlmICh0eXBlb2YgdGhpbmcgPT09IFwibnVtYmVyXCIgJiYgIU51bWJlci5pc0ludGVnZXIodGhpbmcpICYmIHRoaXMuaGFzSW1wbGVtZW50YXRpb24oRmxvYXQpKSB7XG4gICAgICAgICAgZnVuID0gdGhpcy5yZWdpc3RyeS5nZXQoRmxvYXQpW2Z1bk5hbWVdO1xuICAgICAgICB9IGVsc2UgaWYgKHRoaXMuaGFzSW1wbGVtZW50YXRpb24odGhpbmcpKSB7XG4gICAgICAgICAgZnVuID0gdGhpcy5yZWdpc3RyeS5nZXQodGhpbmcuY29uc3RydWN0b3IpW2Z1bk5hbWVdO1xuICAgICAgICB9IGVsc2UgaWYgKHRoaXMuZmFsbGJhY2spIHtcbiAgICAgICAgICBmdW4gPSB0aGlzLmZhbGxiYWNrW2Z1bk5hbWVdO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKGZ1biAhPSBudWxsKSB7XG4gICAgICAgICAgbGV0IHJldHZhbCA9IGZ1bi5hcHBseSh0aGlzLCBhcmdzKTtcbiAgICAgICAgICByZXR1cm4gcmV0dmFsO1xuICAgICAgICB9XG5cbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKFwiTm8gaW1wbGVtZW50YXRpb24gZm91bmQgZm9yIFwiICsgdGhpbmcpO1xuICAgICAgfTtcbiAgICB9XG4gIH1cblxuICBpbXBsZW1lbnRhdGlvbih0eXBlLCBpbXBsZW1lbnRhdGlvbikge1xuICAgIGlmICh0eXBlID09PSBudWxsKSB7XG4gICAgICB0aGlzLmZhbGxiYWNrID0gaW1wbGVtZW50YXRpb247XG4gICAgfSBlbHNlIHtcbiAgICAgIHRoaXMucmVnaXN0cnkuc2V0KHR5cGUsIGltcGxlbWVudGF0aW9uKTtcbiAgICB9XG4gIH1cblxuICBoYXNJbXBsZW1lbnRhdGlvbih0aGluZykge1xuICAgIGlmICh0aGluZyA9PT0gSW50ZWdlciB8fCB0aGluZyA9PT0gRmxvYXQpIHtcbiAgICAgIHJldHVybiB0aGlzLnJlZ2lzdHJ5Lmhhcyh0aGluZyk7XG4gICAgfVxuXG4gICAgcmV0dXJuIHRoaXMucmVnaXN0cnkuaGFzKHRoaW5nLmNvbnN0cnVjdG9yKTtcbiAgfVxufVxuXG5mdW5jdGlvbiBjYWxsX3Byb3BlcnR5KGl0ZW0sIHByb3BlcnR5KSB7XG4gIGxldCBwcm9wID0gbnVsbDtcblxuICBpZiAodHlwZW9mIGl0ZW0gPT09ICdudW1iZXInIHx8IHR5cGVvZiBpdGVtID09PSAnc3ltYm9sJyB8fCB0eXBlb2YgaXRlbSA9PT0gJ2Jvb2xlYW4nIHx8IHR5cGVvZiBpdGVtID09PSAnc3RyaW5nJykge1xuICAgIGlmIChpdGVtW3Byb3BlcnR5XSAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICBwcm9wID0gcHJvcGVydHk7XG4gICAgfSBlbHNlIGlmIChpdGVtW1N5bWJvbC5mb3IocHJvcGVydHkpXSAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICBwcm9wID0gU3ltYm9sLmZvcihwcm9wZXJ0eSk7XG4gICAgfVxuICB9IGVsc2Uge1xuICAgIGlmIChwcm9wZXJ0eSBpbiBpdGVtKSB7XG4gICAgICBwcm9wID0gcHJvcGVydHk7XG4gICAgfSBlbHNlIGlmIChTeW1ib2wuZm9yKHByb3BlcnR5KSBpbiBpdGVtKSB7XG4gICAgICBwcm9wID0gU3ltYm9sLmZvcihwcm9wZXJ0eSk7XG4gICAgfVxuICB9XG5cbiAgaWYgKHByb3AgPT09IG51bGwpIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoYFByb3BlcnR5ICR7IHByb3BlcnR5IH0gbm90IGZvdW5kIGluICR7IGl0ZW0gfWApO1xuICB9XG5cbiAgaWYgKGl0ZW1bcHJvcF0gaW5zdGFuY2VvZiBGdW5jdGlvbikge1xuICAgIHJldHVybiBpdGVtW3Byb3BdKCk7XG4gIH0gZWxzZSB7XG4gICAgcmV0dXJuIGl0ZW1bcHJvcF07XG4gIH1cbn1cblxuZnVuY3Rpb24gYXBwbHkoLi4uYXJncykge1xuICBpZiAoYXJncy5sZW5ndGggPT09IDIpIHtcbiAgICBhcmdzWzBdLmFwcGx5KG51bGwsIGFyZ3Muc2xpY2UoMSkpO1xuICB9IGVsc2Uge1xuICAgIGFyZ3NbMF1bYXJnc1sxXV0uYXBwbHkobnVsbCwgYXJncy5zbGljZSgyKSk7XG4gIH1cbn1cblxuZnVuY3Rpb24gY29udGFpbnMobGVmdCwgcmlnaHQpIHtcbiAgZm9yIChsZXQgeCBvZiByaWdodCkge1xuICAgIGlmIChQYXR0ZXJucy5tYXRjaF9ub190aHJvdyhsZWZ0LCB4KSAhPSBudWxsKSB7XG4gICAgICByZXR1cm4gdHJ1ZTtcbiAgICB9XG4gIH1cblxuICByZXR1cm4gZmFsc2U7XG59XG5cbmZ1bmN0aW9uIGdldF9nbG9iYWwoKSB7XG4gIGlmICh0eXBlb2Ygc2VsZiAhPT0gJ3VuZGVmaW5lZCcpIHtcbiAgICByZXR1cm4gc2VsZjtcbiAgfSBlbHNlIGlmICh0eXBlb2Ygd2luZG93ICE9PSAndW5kZWZpbmVkJykge1xuICAgIHJldHVybiB3aW5kb3c7XG4gIH0gZWxzZSBpZiAodHlwZW9mIGdsb2JhbCAhPT0gJ3VuZGVmaW5lZCcpIHtcbiAgICByZXR1cm4gZ2xvYmFsO1xuICB9XG5cbiAgdGhyb3cgbmV3IEVycm9yKCdObyBnbG9iYWwgc3RhdGUgZm91bmQnKTtcbn1cblxuZnVuY3Rpb24gZGVmc3RydWN0KGRlZmF1bHRzKSB7XG4gIHJldHVybiBjbGFzcyB7XG4gICAgY29uc3RydWN0b3IodXBkYXRlID0ge30pIHtcbiAgICAgIGxldCB0aGVfdmFsdWVzID0gT2JqZWN0LmFzc2lnbihkZWZhdWx0cywgdXBkYXRlKTtcbiAgICAgIE9iamVjdC5hc3NpZ24odGhpcywgdGhlX3ZhbHVlcyk7XG4gICAgfVxuXG4gICAgc3RhdGljIGNyZWF0ZSh1cGRhdGVzID0ge30pIHtcbiAgICAgIGxldCB4ID0gbmV3IHRoaXModXBkYXRlcyk7XG4gICAgICByZXR1cm4gT2JqZWN0LmZyZWV6ZSh4KTtcbiAgICB9XG4gIH07XG59XG5cbmZ1bmN0aW9uIGRlZmV4Y2VwdGlvbihkZWZhdWx0cykge1xuICByZXR1cm4gY2xhc3MgZXh0ZW5kcyBFcnJvciB7XG4gICAgY29uc3RydWN0b3IodXBkYXRlID0ge30pIHtcbiAgICAgIGxldCBtZXNzYWdlID0gdXBkYXRlLm1lc3NhZ2UgfHwgJyc7XG4gICAgICBzdXBlcihtZXNzYWdlKTtcblxuICAgICAgbGV0IHRoZV92YWx1ZXMgPSBPYmplY3QuYXNzaWduKGRlZmF1bHRzLCB1cGRhdGUpO1xuICAgICAgT2JqZWN0LmFzc2lnbih0aGlzLCB0aGVfdmFsdWVzKTtcblxuICAgICAgdGhpcy5uYW1lID0gdGhpcy5jb25zdHJ1Y3Rvci5uYW1lO1xuICAgICAgdGhpcy5tZXNzYWdlID0gbWVzc2FnZTtcbiAgICAgIHRoaXNbU3BlY2lhbEZvcm1zLmF0b20oJ19fZXhjZXB0aW9uX18nKV0gPSB0cnVlO1xuICAgICAgRXJyb3IuY2FwdHVyZVN0YWNrVHJhY2UodGhpcywgdGhpcy5jb25zdHJ1Y3Rvci5uYW1lKTtcbiAgICB9XG5cbiAgICBzdGF0aWMgY3JlYXRlKHVwZGF0ZXMgPSB7fSkge1xuICAgICAgbGV0IHggPSBuZXcgdGhpcyh1cGRhdGVzKTtcbiAgICAgIHJldHVybiBPYmplY3QuZnJlZXplKHgpO1xuICAgIH1cbiAgfTtcbn1cblxuZnVuY3Rpb24gZGVmcHJvdG9jb2woc3BlYykge1xuICByZXR1cm4gbmV3IFByb3RvY29sKHNwZWMpO1xufVxuXG5mdW5jdGlvbiBkZWZpbXBsKHByb3RvY29sLCB0eXBlLCBpbXBsKSB7XG4gIHByb3RvY29sLmltcGxlbWVudGF0aW9uKHR5cGUsIGltcGwpO1xufVxuXG5mdW5jdGlvbiBnZXRfb2JqZWN0X2tleXMob2JqKSB7XG4gIHJldHVybiBPYmplY3Qua2V5cyhvYmopLmNvbmNhdChPYmplY3QuZ2V0T3duUHJvcGVydHlTeW1ib2xzKG9iaikpO1xufVxuXG5mdW5jdGlvbiBpc192YWxpZF9jaGFyYWN0ZXIoY29kZXBvaW50KSB7XG4gIHRyeSB7XG4gICAgcmV0dXJuIFN0cmluZy5mcm9tQ29kZVBvaW50KGNvZGVwb2ludCkgIT0gbnVsbDtcbiAgfSBjYXRjaCAoZSkge1xuICAgIHJldHVybiBmYWxzZTtcbiAgfVxufVxuXG4vL2h0dHBzOi8vZGV2ZWxvcGVyLm1vemlsbGEub3JnL2VuLVVTL2RvY3MvV2ViL0FQSS9XaW5kb3dCYXNlNjQvQmFzZTY0X2VuY29kaW5nX2FuZF9kZWNvZGluZyNTb2x1dGlvbl8yXyVFMiU4MCU5M19yZXdyaXRlX3RoZV9ET01zX2F0b2IoKV9hbmRfYnRvYSgpX3VzaW5nX0phdmFTY3JpcHQnc19UeXBlZEFycmF5c19hbmRfVVRGLThcbmZ1bmN0aW9uIGI2NEVuY29kZVVuaWNvZGUoc3RyKSB7XG4gIHJldHVybiBidG9hKGVuY29kZVVSSUNvbXBvbmVudChzdHIpLnJlcGxhY2UoLyUoWzAtOUEtRl17Mn0pL2csIGZ1bmN0aW9uIChtYXRjaCwgcDEpIHtcbiAgICByZXR1cm4gU3RyaW5nLmZyb21DaGFyQ29kZSgnMHgnICsgcDEpO1xuICB9KSk7XG59XG5cbmZ1bmN0aW9uIGRlbGV0ZV9wcm9wZXJ0eV9mcm9tX21hcChtYXAsIHByb3BlcnR5KSB7XG4gIGxldCBuZXdfbWFwID0gT2JqZWN0LmFzc2lnbihPYmplY3QuY3JlYXRlKG1hcC5jb25zdHJ1Y3Rvci5wcm90b3R5cGUpLCBtYXApO1xuICBkZWxldGUgbmV3X21hcFtwcm9wZXJ0eV07XG5cbiAgcmV0dXJuIE9iamVjdC5mcmVlemUobmV3X21hcCk7XG59XG5cbmZ1bmN0aW9uIGNsYXNzX3RvX29iaihtYXApIHtcbiAgbGV0IG5ld19tYXAgPSBPYmplY3QuYXNzaWduKHt9LCBtYXApO1xuICByZXR1cm4gT2JqZWN0LmZyZWV6ZShuZXdfbWFwKTtcbn1cblxuZnVuY3Rpb24gYWRkX3Byb3BlcnR5X3RvX21hcChtYXAsIHByb3BlcnR5LCB2YWx1ZSkge1xuICBsZXQgbmV3X21hcCA9IE9iamVjdC5hc3NpZ24oe30sIG1hcCk7XG4gIG5ld19tYXBbcHJvcGVydHldID0gdmFsdWU7XG4gIHJldHVybiBPYmplY3QuZnJlZXplKG5ld19tYXApO1xufVxuXG5mdW5jdGlvbiB1cGRhdGVfbWFwKG1hcCwgcHJvcGVydHksIHZhbHVlKSB7XG4gIGlmIChwcm9wZXJ0eSBpbiBnZXRfb2JqZWN0X2tleXMobWFwKSkge1xuICAgIHJldHVybiBhZGRfcHJvcGVydHlfdG9fbWFwKG1hcCwgcHJvcGVydHksIHZhbHVlKTtcbiAgfVxuXG4gIHRocm93ICdtYXAgZG9lcyBub3QgaGF2ZSBrZXknO1xufVxuXG5mdW5jdGlvbiBibm90KGV4cHIpIHtcbiAgcmV0dXJuIH5leHByO1xufVxuXG5mdW5jdGlvbiBiYW5kKGxlZnQsIHJpZ2h0KSB7XG4gIHJldHVybiBsZWZ0ICYgcmlnaHQ7XG59XG5cbmZ1bmN0aW9uIGJvcihsZWZ0LCByaWdodCkge1xuICByZXR1cm4gbGVmdCB8IHJpZ2h0O1xufVxuXG5mdW5jdGlvbiBic2wobGVmdCwgcmlnaHQpIHtcbiAgcmV0dXJuIGxlZnQgPDwgcmlnaHQ7XG59XG5cbmZ1bmN0aW9uIGJzcihsZWZ0LCByaWdodCkge1xuICByZXR1cm4gbGVmdCA+PiByaWdodDtcbn1cblxuZnVuY3Rpb24gYnhvcihsZWZ0LCByaWdodCkge1xuICByZXR1cm4gbGVmdCBeIHJpZ2h0O1xufVxuXG5mdW5jdGlvbiB6aXAobGlzdF9vZl9saXN0cykge1xuICBpZiAobGlzdF9vZl9saXN0cy5sZW5ndGggPT09IDApIHtcbiAgICByZXR1cm4gT2JqZWN0LmZyZWV6ZShbXSk7XG4gIH1cblxuICBsZXQgbmV3X3ZhbHVlID0gW107XG4gIGxldCBzbWFsbGVzdF9sZW5ndGggPSBsaXN0X29mX2xpc3RzWzBdO1xuXG4gIGZvciAobGV0IHggb2YgbGlzdF9vZl9saXN0cykge1xuICAgIGlmICh4Lmxlbmd0aCA8IHNtYWxsZXN0X2xlbmd0aCkge1xuICAgICAgc21hbGxlc3RfbGVuZ3RoID0geC5sZW5ndGg7XG4gICAgfVxuICB9XG5cbiAgZm9yIChsZXQgaSA9IDA7IGkgPCBzbWFsbGVzdF9sZW5ndGg7IGkrKykge1xuICAgIGxldCBjdXJyZW50X3ZhbHVlID0gW107XG4gICAgZm9yIChsZXQgaiA9IDA7IGogPCBsaXN0X29mX2xpc3RzLmxlbmd0aDsgaisrKSB7XG4gICAgICBjdXJyZW50X3ZhbHVlLnB1c2gobGlzdF9vZl9saXN0c1tqXVtpXSk7XG4gICAgfVxuXG4gICAgbmV3X3ZhbHVlLnB1c2gobmV3IFR1cGxlKC4uLmN1cnJlbnRfdmFsdWUpKTtcbiAgfVxuXG4gIHJldHVybiBPYmplY3QuZnJlZXplKG5ld192YWx1ZSk7XG59XG5cbmZ1bmN0aW9uIGNhbl9kZWNvZGU2NChkYXRhKSB7XG4gIHRyeSB7XG4gICAgYXRvYihkYXRhKTtcbiAgICByZXR1cm4gdHJ1ZTtcbiAgfSBjYXRjaCAoZSkge1xuICAgIHJldHVybiBmYWxzZTtcbiAgfVxufVxuXG5mdW5jdGlvbiByZW1vdmVfZnJvbV9saXN0KGxpc3QsIGVsZW1lbnQpIHtcbiAgbGV0IGZvdW5kID0gZmFsc2U7XG5cbiAgcmV0dXJuIGxpc3QuZmlsdGVyKGVsZW0gPT4ge1xuICAgIGlmICghZm91bmQgJiYgZWxlbSA9PT0gZWxlbWVudCkge1xuICAgICAgZm91bmQgPSB0cnVlO1xuICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH1cblxuICAgIHJldHVybiB0cnVlO1xuICB9KTtcbn1cblxuZnVuY3Rpb24gZm9sZGwoZnVuLCBhY2MsIGxpc3QpIHtcbiAgbGV0IGFjYzEgPSBhY2M7XG5cbiAgZm9yIChjb25zdCBlbCBvZiBsaXN0KSB7XG4gICAgYWNjMSA9IGZ1bihlbCwgYWNjMSk7XG4gIH1cblxuICByZXR1cm4gYWNjMTtcbn1cblxuZnVuY3Rpb24gZm9sZHIoZnVuLCBhY2MsIGxpc3QpIHtcbiAgbGV0IGFjYzEgPSBhY2M7XG5cbiAgZm9yIChsZXQgaSA9IGxpc3QubGVuZ3RoIC0gMTsgaSA+PSAwOyBpLS0pIHtcbiAgICBhY2MxID0gZnVuKGxpc3RbaV0sIGFjYzEpO1xuICB9XG5cbiAgcmV0dXJuIGFjYzE7XG59XG5cbmZ1bmN0aW9uIGtleWZpbmQoa2V5LCBuLCB0dXBsZWxpc3QpIHtcblxuICBmb3IgKGxldCBpID0gdHVwbGVsaXN0Lmxlbmd0aCAtIDE7IGkgPj0gMDsgaS0tKSB7XG4gICAgaWYgKHR1cGxlbGlzdFtpXS5nZXQobikgPT09IGtleSkge1xuICAgICAgcmV0dXJuIHR1cGxlbGlzdFtpXTtcbiAgICB9XG4gIH1cblxuICByZXR1cm4gZmFsc2U7XG59XG5cbmZ1bmN0aW9uIGtleWRlbGV0ZShrZXksIG4sIHR1cGxlbGlzdCkge1xuXG4gIGZvciAobGV0IGkgPSB0dXBsZWxpc3QubGVuZ3RoIC0gMTsgaSA+PSAwOyBpLS0pIHtcbiAgICBpZiAodHVwbGVsaXN0W2ldLmdldChuKSA9PT0ga2V5KSB7XG4gICAgICByZXR1cm4gdHVwbGVsaXN0LmNvbmNhdChbXSkuc3BsaWNlKGksIDEpO1xuICAgIH1cbiAgfVxuXG4gIHJldHVybiB0dXBsZWxpc3Q7XG59XG5cbmZ1bmN0aW9uIGtleXN0b3JlKGtleSwgbiwgbGlzdCwgbmV3dHVwbGUpIHtcbiAgZm9yIChsZXQgaSA9IGxpc3QubGVuZ3RoIC0gMTsgaSA+PSAwOyBpLS0pIHtcbiAgICBpZiAobGlzdFtpXS5nZXQobikgPT09IGtleSkge1xuICAgICAgcmV0dXJuIGxpc3QuY29uY2F0KFtdKS5zcGxpY2UoaSwgMSwgbmV3dHVwbGUpO1xuICAgIH1cbiAgfVxuXG4gIHJldHVybiBsaXN0LmNvbmNhdChbXSkucHVzaChuZXd0dXBsZSk7XG59XG5cbmZ1bmN0aW9uIGtleW1lbWJlcihrZXksIG4sIGxpc3QpIHtcbiAgZm9yIChsZXQgaSA9IGxpc3QubGVuZ3RoIC0gMTsgaSA+PSAwOyBpLS0pIHtcbiAgICBpZiAobGlzdFtpXS5nZXQobikgPT09IGtleSkge1xuICAgICAgcmV0dXJuIHRydWU7XG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIGZhbHNlO1xufVxuXG5mdW5jdGlvbiBrZXl0YWtlKGtleSwgbiwgbGlzdCkge1xuICBpZiAoIWtleW1lbWJlcihrZXksIG4sIGxpc3QpKSB7XG4gICAgcmV0dXJuIGZhbHNlO1xuICB9XG5cbiAgbGV0IHR1cGxlID0ga2V5ZmluZChrZXksIG4sIGxpc3QpO1xuXG4gIHJldHVybiBuZXcgVHVwbGUodHVwbGUuZ2V0KG4pLCB0dXBsZSwga2V5ZGVsZXRlKGtleSwgbiwgbGlzdCkpO1xufVxuXG5mdW5jdGlvbiBrZXlyZXBsYWNlKGtleSwgbiwgbGlzdCwgbmV3dHVwbGUpIHtcblxuICBmb3IgKGxldCBpID0gdHVwbGVsaXN0Lmxlbmd0aCAtIDE7IGkgPj0gMDsgaS0tKSB7XG4gICAgaWYgKHR1cGxlbGlzdFtpXS5nZXQobikgPT09IGtleSkge1xuICAgICAgcmV0dXJuIHR1cGxlbGlzdC5jb25jYXQoW10pLnNwbGljZShpLCAxLCBuZXd0dXBsZSk7XG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIHR1cGxlbGlzdDtcbn1cblxuZnVuY3Rpb24gcmV2ZXJzZShsaXN0KSB7XG4gIHJldHVybiBsaXN0LmNvbmNhdChbXSkucmV2ZXJzZSgpO1xufVxuXG5mdW5jdGlvbiBtYXBzX2ZpbmQoa2V5LCBtYXApIHtcbiAgaWYgKGtleSBpbiBnZXRfb2JqZWN0X2tleXMobWFwKSkge1xuICAgIHJldHVybiBuZXcgVHVwbGUoU3ltYm9sLmZvcignb2snKSwgbWFwW2tleV0pO1xuICB9IGVsc2Uge1xuICAgIHJldHVybiBTeW1ib2wuZm9yKCdlcnJvcicpO1xuICB9XG59XG5cbmZ1bmN0aW9uIGZsYXR0ZW4obGlzdCwgdGFpbCA9IFtdKSB7XG4gIGxldCBuZXdfbGlzdCA9IFtdO1xuXG4gIGZvciAobGV0IGUgb2YgbGlzdCkge1xuICAgIGlmIChpc0FycmF5KGUpKSB7XG4gICAgICBuZXdfbGlzdCA9IG5ld19saXN0LmNvbmNhdChmbGF0dGVuKGUpKTtcbiAgICB9IGVsc2Uge1xuICAgICAgbmV3X2xpc3QucHVzaChlKTtcbiAgICB9XG4gIH1cblxuICByZXR1cm4gT2JqZWN0LmZyZWV6ZShuZXdfbGlzdC5jb25jYXQodGFpbCkpO1xufVxuXG5mdW5jdGlvbiBkdXBsaWNhdGUobiwgZWxlbSkge1xuICBsZXQgbGlzdCA9IFtdO1xuXG4gIGZvciAobGV0IGkgPSAwOyBpIDwgbjsgaSsrKSB7XG4gICAgbGlzdC5wdXNoKGVsZW0pO1xuICB9XG5cbiAgcmV0dXJuIE9iamVjdC5mcmVlemUobGlzdCk7XG59XG5cbmZ1bmN0aW9uIG1hcGZvbGRsKGZ1biwgYWNjLCBsaXN0KSB7XG4gIGxldCBuZXdsaXN0ID0gW107XG5cbiAgZm9yIChsZXQgeCBvZiBsaXN0KSB7XG4gICAgbGV0IHR1cCA9IGZ1bih4LCBhY2MpO1xuICAgIG5ld2xpc3QucHVzaCh0dXAuZ2V0KDApKTtcbiAgICBhY2MgPSB0dXAuZ2V0KDEpO1xuICB9XG5cbiAgcmV0dXJuIG5ldyBUdXBsZShPYmplY3QuZnJlZXplKG5ld2xpc3QpLCBhY2MpO1xufVxuXG5mdW5jdGlvbiBmaWx0ZXJtYXAoZnVuLCBsaXN0KSB7XG4gIGxldCBuZXdsaXN0ID0gW107XG5cbiAgZm9yICh4IG9mIGxpc3QpIHtcbiAgICBsZXQgcmVzdWx0ID0gZnVuKHgpO1xuXG4gICAgaWYgKHJlc3VsdCA9PT0gdHJ1ZSkge1xuICAgICAgbmV3bGlzdC5wdXNoKHgpO1xuICAgIH0gZWxzZSBpZiAocmVzdWx0IGluc3RhbmNlb2YgVHVwbGUpIHtcbiAgICAgIG5ld2xpc3QucHVzaChyZXN1bHQuZ2V0KDEpKTtcbiAgICB9XG4gIH1cblxuICByZXR1cm4gT2JqZWN0LmZyZWV6ZShuZXdsaXN0KTtcbn1cblxuZnVuY3Rpb24gbWFwc19mb2xkKGZ1biwgYWNjLCBtYXApIHtcbiAgbGV0IGFjYzEgPSBhY2M7XG5cbiAgZm9yIChsZXQgayBvZiBnZXRfb2JqZWN0X2tleXMobWFwKSkge1xuICAgIGFjYzEgPSBmdW4oaywgbWFwW2tdLCBhY2MxKTtcbiAgfVxuXG4gIHJldHVybiBhY2MxO1xufVxuXG52YXIgRnVuY3Rpb25zID0ge1xuICBjYWxsX3Byb3BlcnR5LFxuICBhcHBseSxcbiAgY29udGFpbnMsXG4gIGdldF9nbG9iYWwsXG4gIGRlZnN0cnVjdCxcbiAgZGVmZXhjZXB0aW9uLFxuICBkZWZwcm90b2NvbCxcbiAgZGVmaW1wbCxcbiAgZ2V0X29iamVjdF9rZXlzLFxuICBpc192YWxpZF9jaGFyYWN0ZXIsXG4gIGI2NEVuY29kZVVuaWNvZGUsXG4gIGRlbGV0ZV9wcm9wZXJ0eV9mcm9tX21hcCxcbiAgYWRkX3Byb3BlcnR5X3RvX21hcCxcbiAgY2xhc3NfdG9fb2JqLFxuICBjYW5fZGVjb2RlNjQsXG4gIGJub3QsXG4gIGJhbmQsXG4gIGJvcixcbiAgYnNsLFxuICBic3IsXG4gIGJ4b3IsXG4gIHppcCxcbiAgZm9sZGwsXG4gIGZvbGRyLFxuICByZW1vdmVfZnJvbV9saXN0LFxuICBrZXlkZWxldGUsXG4gIGtleXN0b3JlLFxuICBrZXlmaW5kLFxuICBrZXl0YWtlLFxuICBrZXlyZXBsYWNlLFxuICByZXZlcnNlLFxuICB1cGRhdGVfbWFwLFxuICBtYXBzX2ZpbmQsXG4gIGZsYXR0ZW4sXG4gIGR1cGxpY2F0ZSxcbiAgbWFwZm9sZGwsXG4gIGZpbHRlcm1hcCxcbiAgbWFwc19mb2xkXG59O1xuXG5mdW5jdGlvbiBfY2FzZShjb25kaXRpb24sIGNsYXVzZXMpIHtcbiAgcmV0dXJuIFBhdHRlcm5zLmRlZm1hdGNoKC4uLmNsYXVzZXMpKGNvbmRpdGlvbik7XG59XG5cbmZ1bmN0aW9uIGNvbmQoY2xhdXNlcykge1xuICBmb3IgKGxldCBjbGF1c2Ugb2YgY2xhdXNlcykge1xuICAgIGlmIChjbGF1c2VbMF0pIHtcbiAgICAgIHJldHVybiBjbGF1c2VbMV0oKTtcbiAgICB9XG4gIH1cblxuICB0aHJvdyBuZXcgRXJyb3IoKTtcbn1cblxuZnVuY3Rpb24gbWFwX3VwZGF0ZShtYXAsIHZhbHVlcykge1xuICByZXR1cm4gT2JqZWN0LmZyZWV6ZShPYmplY3QuYXNzaWduKE9iamVjdC5jcmVhdGUobWFwLmNvbnN0cnVjdG9yLnByb3RvdHlwZSksIG1hcCwgdmFsdWVzKSk7XG59XG5cbmZ1bmN0aW9uIF9mb3IoY29sbGVjdGlvbnMsIGZ1biwgZmlsdGVyID0gKCkgPT4gdHJ1ZSwgaW50byA9IFtdLCBwcmV2aW91c1ZhbHVlcyA9IFtdKSB7XG4gIGxldCBwYXR0ZXJuID0gY29sbGVjdGlvbnNbMF1bMF07XG4gIGxldCBjb2xsZWN0aW9uID0gY29sbGVjdGlvbnNbMF1bMV07XG5cbiAgaWYgKGNvbGxlY3Rpb25zLmxlbmd0aCA9PT0gMSkge1xuXG4gICAgZm9yIChsZXQgZWxlbSBvZiBjb2xsZWN0aW9uKSB7XG4gICAgICBsZXQgciA9IFBhdHRlcm5zLm1hdGNoX25vX3Rocm93KHBhdHRlcm4sIGVsZW0pO1xuICAgICAgbGV0IGFyZ3MgPSBwcmV2aW91c1ZhbHVlcy5jb25jYXQocik7XG5cbiAgICAgIGlmIChyICYmIGZpbHRlci5hcHBseSh0aGlzLCBhcmdzKSkge1xuICAgICAgICBpbnRvID0gaW50by5jb25jYXQoW2Z1bi5hcHBseSh0aGlzLCBhcmdzKV0pO1xuICAgICAgfVxuICAgIH1cblxuICAgIHJldHVybiBpbnRvO1xuICB9IGVsc2Uge1xuICAgIGxldCBfaW50byA9IFtdO1xuXG4gICAgZm9yIChsZXQgZWxlbSBvZiBjb2xsZWN0aW9uKSB7XG4gICAgICBsZXQgciA9IFBhdHRlcm5zLm1hdGNoX25vX3Rocm93KHBhdHRlcm4sIGVsZW0pO1xuICAgICAgaWYgKHIpIHtcbiAgICAgICAgX2ludG8gPSBpbnRvLmNvbmNhdCh0aGlzLl9mb3IoY29sbGVjdGlvbnMuc2xpY2UoMSksIGZ1biwgZmlsdGVyLCBfaW50bywgcHJldmlvdXNWYWx1ZXMuY29uY2F0KHIpKSk7XG4gICAgICB9XG4gICAgfVxuXG4gICAgcmV0dXJuIF9pbnRvO1xuICB9XG59XG5cbmZ1bmN0aW9uIF90cnkoZG9fZnVuLCByZXNjdWVfZnVuY3Rpb24sIGNhdGNoX2Z1biwgZWxzZV9mdW5jdGlvbiwgYWZ0ZXJfZnVuY3Rpb24pIHtcbiAgbGV0IHJlc3VsdCA9IG51bGw7XG5cbiAgdHJ5IHtcbiAgICByZXN1bHQgPSBkb19mdW4oKTtcbiAgfSBjYXRjaCAoZSkge1xuICAgIGxldCBleF9yZXN1bHQgPSBudWxsO1xuXG4gICAgaWYgKHJlc2N1ZV9mdW5jdGlvbikge1xuICAgICAgdHJ5IHtcbiAgICAgICAgZXhfcmVzdWx0ID0gcmVzY3VlX2Z1bmN0aW9uKGUpO1xuICAgICAgICByZXR1cm4gZXhfcmVzdWx0O1xuICAgICAgfSBjYXRjaCAoZXgpIHtcbiAgICAgICAgaWYgKGV4IGluc3RhbmNlb2YgUGF0dGVybnMuTWF0Y2hFcnJvcikge1xuICAgICAgICAgIHRocm93IGV4O1xuICAgICAgICB9XG4gICAgICB9XG4gICAgfVxuXG4gICAgaWYgKGNhdGNoX2Z1bikge1xuICAgICAgdHJ5IHtcbiAgICAgICAgZXhfcmVzdWx0ID0gY2F0Y2hfZnVuKGUpO1xuICAgICAgICByZXR1cm4gZXhfcmVzdWx0O1xuICAgICAgfSBjYXRjaCAoZXgpIHtcbiAgICAgICAgaWYgKGV4IGluc3RhbmNlb2YgUGF0dGVybnMuTWF0Y2hFcnJvcikge1xuICAgICAgICAgIHRocm93IGV4O1xuICAgICAgICB9XG4gICAgICB9XG4gICAgfVxuXG4gICAgdGhyb3cgZTtcbiAgfSBmaW5hbGx5IHtcbiAgICBpZiAoYWZ0ZXJfZnVuY3Rpb24pIHtcbiAgICAgIGFmdGVyX2Z1bmN0aW9uKCk7XG4gICAgfVxuICB9XG5cbiAgaWYgKGVsc2VfZnVuY3Rpb24pIHtcbiAgICB0cnkge1xuICAgICAgcmV0dXJuIGVsc2VfZnVuY3Rpb24ocmVzdWx0KTtcbiAgICB9IGNhdGNoIChleCkge1xuICAgICAgaWYgKGV4IGluc3RhbmNlb2YgUGF0dGVybnMuTWF0Y2hFcnJvcikge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ05vIE1hdGNoIEZvdW5kIGluIEVsc2UnKTtcbiAgICAgIH1cblxuICAgICAgdGhyb3cgZXg7XG4gICAgfVxuICB9IGVsc2Uge1xuICAgIHJldHVybiByZXN1bHQ7XG4gIH1cbn1cblxudmFyIFNwZWNpYWxGb3JtcyQxID0ge1xuICBfY2FzZSxcbiAgY29uZCxcbiAgbWFwX3VwZGF0ZSxcbiAgX2ZvcixcbiAgX3RyeVxufTtcblxuRnVuY3Rpb25zLmdldF9nbG9iYWwoKS5wcm9jZXNzZXMgPSBGdW5jdGlvbnMuZ2V0X2dsb2JhbCgpLnByb2Nlc3NlcyB8fCBuZXcgUHJvY2Vzc1N5c3RlbSgpO1xuXG52YXIgQ29yZSA9IHtcbiAgUHJvY2Vzc1N5c3RlbSxcbiAgVHVwbGUsXG4gIFBJRCxcbiAgQml0U3RyaW5nLFxuICBQYXR0ZXJucyxcbiAgSW50ZWdlcixcbiAgRmxvYXQsXG4gIEZ1bmN0aW9ucyxcbiAgU3BlY2lhbEZvcm1zOiBTcGVjaWFsRm9ybXMkMVxufTtcblxubGV0IEVudW0gPSB7XG5cbiAgYWxsX19xbWFya19fOiBmdW5jdGlvbiAoY29sbGVjdGlvbiwgZnVuID0geCA9PiB4KSB7XG4gICAgZm9yIChsZXQgZWxlbSBvZiBjb2xsZWN0aW9uKSB7XG4gICAgICBpZiAoIWZ1bihlbGVtKSkge1xuICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICB9XG4gICAgfVxuXG4gICAgcmV0dXJuIHRydWU7XG4gIH0sXG5cbiAgYW55X19xbWFya19fOiBmdW5jdGlvbiAoY29sbGVjdGlvbiwgZnVuID0geCA9PiB4KSB7XG4gICAgZm9yIChsZXQgZWxlbSBvZiBjb2xsZWN0aW9uKSB7XG4gICAgICBpZiAoZnVuKGVsZW0pKSB7XG4gICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgfVxuICAgIH1cblxuICAgIHJldHVybiBmYWxzZTtcbiAgfSxcblxuICBhdDogZnVuY3Rpb24gKGNvbGxlY3Rpb24sIG4sIHRoZV9kZWZhdWx0ID0gbnVsbCkge1xuICAgIGlmIChuID4gdGhpcy5jb3VudChjb2xsZWN0aW9uKSB8fCBuIDwgMCkge1xuICAgICAgcmV0dXJuIHRoZV9kZWZhdWx0O1xuICAgIH1cblxuICAgIHJldHVybiBjb2xsZWN0aW9uW25dO1xuICB9LFxuXG4gIGNvbmNhdDogZnVuY3Rpb24gKC4uLmVudW1hYmxlcykge1xuICAgIHJldHVybiBlbnVtYWJsZXNbMF0uY29uY2F0KGVudW1hYmxlc1sxXSk7XG4gIH0sXG5cbiAgY291bnQ6IGZ1bmN0aW9uIChjb2xsZWN0aW9uLCBmdW4gPSBudWxsKSB7XG4gICAgaWYgKGZ1biA9PSBudWxsKSB7XG4gICAgICByZXR1cm4gY29sbGVjdGlvbi5sZW5ndGg7XG4gICAgfSBlbHNlIHtcbiAgICAgIHJldHVybiBjb2xsZWN0aW9uLmZpbHRlcihmdW4pLmxlbmd0aDtcbiAgICB9XG4gIH0sXG5cbiAgZHJvcDogZnVuY3Rpb24gKGNvbGxlY3Rpb24sIGNvdW50KSB7XG4gICAgcmV0dXJuIGNvbGxlY3Rpb24uc2xpY2UoY291bnQpO1xuICB9LFxuXG4gIGRyb3Bfd2hpbGU6IGZ1bmN0aW9uIChjb2xsZWN0aW9uLCBmdW4pIHtcbiAgICBsZXQgY291bnQgPSAwO1xuXG4gICAgZm9yIChsZXQgZWxlbSBvZiBjb2xsZWN0aW9uKSB7XG4gICAgICBpZiAoZnVuKGVsZW0pKSB7XG4gICAgICAgIGNvdW50ID0gY291bnQgKyAxO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgYnJlYWs7XG4gICAgICB9XG4gICAgfVxuXG4gICAgcmV0dXJuIGNvbGxlY3Rpb24uc2xpY2UoY291bnQpO1xuICB9LFxuXG4gIGVhY2g6IGZ1bmN0aW9uIChjb2xsZWN0aW9uLCBmdW4pIHtcbiAgICBmb3IgKGxldCBlbGVtIG9mIGNvbGxlY3Rpb24pIHtcbiAgICAgIGZ1bihlbGVtKTtcbiAgICB9XG4gIH0sXG5cbiAgZW1wdHlfX3FtYXJrX186IGZ1bmN0aW9uIChjb2xsZWN0aW9uKSB7XG4gICAgcmV0dXJuIGNvbGxlY3Rpb24ubGVuZ3RoID09PSAwO1xuICB9LFxuXG4gIGZldGNoOiBmdW5jdGlvbiAoY29sbGVjdGlvbiwgbikge1xuICAgIGlmIChBcnJheS5pc0FycmF5KGNvbGxlY3Rpb24pKSB7XG4gICAgICBpZiAobiA8IHRoaXMuY291bnQoY29sbGVjdGlvbikgJiYgbiA+PSAwKSB7XG4gICAgICAgIHJldHVybiBuZXcgQ29yZS5UdXBsZShTeW1ib2wuZm9yKFwib2tcIiksIGNvbGxlY3Rpb25bbl0pO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgcmV0dXJuIFN5bWJvbC5mb3IoXCJlcnJvclwiKTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICB0aHJvdyBuZXcgRXJyb3IoXCJjb2xsZWN0aW9uIGlzIG5vdCBhbiBFbnVtZXJhYmxlXCIpO1xuICB9LFxuXG4gIGZldGNoX19lbWFya19fOiBmdW5jdGlvbiAoY29sbGVjdGlvbiwgbikge1xuICAgIGlmIChBcnJheS5pc0FycmF5KGNvbGxlY3Rpb24pKSB7XG4gICAgICBpZiAobiA8IHRoaXMuY291bnQoY29sbGVjdGlvbikgJiYgbiA+PSAwKSB7XG4gICAgICAgIHJldHVybiBjb2xsZWN0aW9uW25dO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKFwib3V0IG9mIGJvdW5kcyBlcnJvclwiKTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICB0aHJvdyBuZXcgRXJyb3IoXCJjb2xsZWN0aW9uIGlzIG5vdCBhbiBFbnVtZXJhYmxlXCIpO1xuICB9LFxuXG4gIGZpbHRlcjogZnVuY3Rpb24gKGNvbGxlY3Rpb24sIGZ1bikge1xuICAgIGxldCByZXN1bHQgPSBbXTtcblxuICAgIGZvciAobGV0IGVsZW0gb2YgY29sbGVjdGlvbikge1xuICAgICAgaWYgKGZ1bihlbGVtKSkge1xuICAgICAgICByZXN1bHQucHVzaChlbGVtKTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICByZXR1cm4gcmVzdWx0O1xuICB9LFxuXG4gIGZpbHRlcl9tYXA6IGZ1bmN0aW9uIChjb2xsZWN0aW9uLCBmaWx0ZXIsIG1hcHBlcikge1xuICAgIHJldHVybiBFbnVtLm1hcChFbnVtLmZpbHRlcihjb2xsZWN0aW9uLCBmaWx0ZXIpLCBtYXBwZXIpO1xuICB9LFxuXG4gIGZpbmQ6IGZ1bmN0aW9uIChjb2xsZWN0aW9uLCBpZl9ub25lID0gbnVsbCwgZnVuKSB7XG4gICAgZm9yIChsZXQgZWxlbSBvZiBjb2xsZWN0aW9uKSB7XG4gICAgICBpZiAoZnVuKGVsZW0pKSB7XG4gICAgICAgIHJldHVybiBlbGVtO1xuICAgICAgfVxuICAgIH1cblxuICAgIHJldHVybiBpZl9ub25lO1xuICB9LFxuXG4gIGludG86IGZ1bmN0aW9uIChjb2xsZWN0aW9uLCBsaXN0KSB7XG4gICAgcmV0dXJuIGxpc3QuY29uY2F0KGNvbGxlY3Rpb24pO1xuICB9LFxuXG4gIG1hcDogZnVuY3Rpb24gKGNvbGxlY3Rpb24sIGZ1bikge1xuICAgIGxldCByZXN1bHQgPSBbXTtcblxuICAgIGZvciAobGV0IGVsZW0gb2YgY29sbGVjdGlvbikge1xuICAgICAgcmVzdWx0LnB1c2goZnVuKGVsZW0pKTtcbiAgICB9XG5cbiAgICByZXR1cm4gcmVzdWx0O1xuICB9LFxuXG4gIG1hcF9yZWR1Y2U6IGZ1bmN0aW9uIChjb2xsZWN0aW9uLCBhY2MsIGZ1bikge1xuICAgIGxldCBtYXBwZWQgPSBPYmplY3QuZnJlZXplKFtdKTtcbiAgICBsZXQgdGhlX2FjYyA9IGFjYztcblxuICAgIGZvciAodmFyIGkgPSAwOyBpIDwgdGhpcy5jb3VudChjb2xsZWN0aW9uKTsgaSsrKSB7XG4gICAgICBsZXQgdHVwbGUgPSBmdW4oY29sbGVjdGlvbltpXSwgdGhlX2FjYyk7XG5cbiAgICAgIHRoZV9hY2MgPSB0dXBsZS5nZXQoMSk7XG4gICAgICBtYXBwZWQgPSBPYmplY3QuZnJlZXplKG1hcHBlZC5jb25jYXQoW3R1cGxlLmdldCgwKV0pKTtcbiAgICB9XG5cbiAgICByZXR1cm4gbmV3IENvcmUuVHVwbGUobWFwcGVkLCB0aGVfYWNjKTtcbiAgfSxcblxuICBtZW1iZXJfX3FtYXJrX186IGZ1bmN0aW9uIChjb2xsZWN0aW9uLCB2YWx1ZSkge1xuICAgIHJldHVybiBjb2xsZWN0aW9uLmluY2x1ZGVzKHZhbHVlKTtcbiAgfSxcblxuICByZWR1Y2U6IGZ1bmN0aW9uIChjb2xsZWN0aW9uLCBhY2MsIGZ1bikge1xuICAgIGxldCB0aGVfYWNjID0gYWNjO1xuXG4gICAgZm9yICh2YXIgaSA9IDA7IGkgPCB0aGlzLmNvdW50KGNvbGxlY3Rpb24pOyBpKyspIHtcbiAgICAgIGxldCB0dXBsZSA9IGZ1bihjb2xsZWN0aW9uW2ldLCB0aGVfYWNjKTtcblxuICAgICAgdGhlX2FjYyA9IHR1cGxlLmdldCgxKTtcbiAgICB9XG5cbiAgICByZXR1cm4gdGhlX2FjYztcbiAgfSxcblxuICB0YWtlOiBmdW5jdGlvbiAoY29sbGVjdGlvbiwgY291bnQpIHtcbiAgICByZXR1cm4gY29sbGVjdGlvbi5zbGljZSgwLCBjb3VudCk7XG4gIH0sXG5cbiAgdGFrZV9ldmVyeTogZnVuY3Rpb24gKGNvbGxlY3Rpb24sIG50aCkge1xuICAgIGxldCByZXN1bHQgPSBbXTtcbiAgICBsZXQgaW5kZXggPSAwO1xuXG4gICAgZm9yIChsZXQgZWxlbSBvZiBjb2xsZWN0aW9uKSB7XG4gICAgICBpZiAoaW5kZXggJSBudGggPT09IDApIHtcbiAgICAgICAgcmVzdWx0LnB1c2goZWxlbSk7XG4gICAgICB9XG4gICAgfVxuXG4gICAgcmV0dXJuIE9iamVjdC5mcmVlemUocmVzdWx0KTtcbiAgfSxcblxuICB0YWtlX3doaWxlOiBmdW5jdGlvbiAoY29sbGVjdGlvbiwgZnVuKSB7XG4gICAgbGV0IGNvdW50ID0gMDtcblxuICAgIGZvciAobGV0IGVsZW0gb2YgY29sbGVjdGlvbikge1xuICAgICAgaWYgKGZ1bihlbGVtKSkge1xuICAgICAgICBjb3VudCA9IGNvdW50ICsgMTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIGJyZWFrO1xuICAgICAgfVxuICAgIH1cblxuICAgIHJldHVybiBjb2xsZWN0aW9uLnNsaWNlKDAsIGNvdW50KTtcbiAgfSxcblxuICB0b19saXN0OiBmdW5jdGlvbiAoY29sbGVjdGlvbikge1xuICAgIHJldHVybiBjb2xsZWN0aW9uO1xuICB9XG59O1xuXG52YXIgRWxpeGlyID0ge1xuICBDb3JlLFxuICBFbnVtLFxuICBWaXJ0dWFsRE9NXG59O1xuXG5leHBvcnQgZGVmYXVsdCBFbGl4aXI7Il0sImZpbGUiOiJFbGl4aXIuanMiLCJzb3VyY2VSb290IjoiL3NvdXJjZS8ifQ== \ No newline at end of file diff --git a/src/javascript/lib/core/functions.js b/src/javascript/lib/core/functions.js index 69f66a7f..0cc6500d 100644 --- a/src/javascript/lib/core/functions.js +++ b/src/javascript/lib/core/functions.js @@ -6,12 +6,22 @@ import Protocol from './protocol'; function call_property(item, property){ let prop = null; - if(property in item){ + if(typeof item === "number" || typeof item === "symbol" || typeof item === "boolean" || typeof item === "string"){ + if(item[property] !== undefined){ prop = property; - }else if(Symbol.for(property) in item){ - prop = Symbol.for(property); - }else{ - throw new Error(`Property ${property} not found in ${item}`); + }else if(item[Symbol.for(property)] !== undefined){ + prop = Symbol.for(property); + } + } else { + if(property in item){ + prop = property; + }else if(Symbol.for(property) in item){ + prop = Symbol.for(property); + } + } + + if(prop === null){ + throw new Error(`Property ${ property } not found in ${ item }`); } if(item[prop] instanceof Function){ diff --git a/src/javascript/lib/core/protocol.js b/src/javascript/lib/core/protocol.js index cd96dbf0..79b5d7e2 100644 --- a/src/javascript/lib/core/protocol.js +++ b/src/javascript/lib/core/protocol.js @@ -45,6 +45,10 @@ class Protocol{ } hasImplementation(thing) { + if (thing === Integer || thing === Float){ + return this.registry.has(thing); + } + return this.registry.has(thing.constructor); } } diff --git a/src/javascript/tests/core/functions.spec.js b/src/javascript/tests/core/functions.spec.js new file mode 100644 index 00000000..9b110c20 --- /dev/null +++ b/src/javascript/tests/core/functions.spec.js @@ -0,0 +1,17 @@ +var Functions = require('../../lib/core').Functions; +var expect = require('chai').expect; + +describe('Functions', function(){ + + it('call_property', function(){ + expect(Functions.call_property(1, "toString")).to.equal("1"); + expect(Functions.call_property([], "toString")).to.equal(""); + expect(Functions.call_property([], "length")).to.equal(0); + expect(Functions.call_property("", "toString")).to.equal(""); + expect(Functions.call_property("", "length")).to.equal(0); + expect(Functions.call_property(Symbol("test"), "toString")).to.equal("Symbol(test)"); + expect(Functions.call_property({completed: false}, "completed")).to.equal(false); + expect(Functions.call_property({id: 0}, "id")).to.equal(0); + }); + +}); From 72ccef4fd79e293c8f7e08290a8f9e8f0e54dde2 Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Sat, 20 Feb 2016 15:15:25 -0600 Subject: [PATCH 150/860] Updated js tooling. --- .babelrc | 3 + .eslintrc | 32 +- .gitignore | 5 +- .travis.yml | 2 +- gulpfile.js | 59 +- mix.exs | 5 +- package.json | 28 +- priv/Elixir.js | 5545 ++++++++--------- src/javascript/lib/core/patterns/defmatch.js | 2 +- src/javascript/lib/core/special_forms.js | 2 +- src/javascript/tests/bit_string.spec.js | 11 +- src/javascript/tests/case.spec.js | 14 +- src/javascript/tests/cond.spec.js | 12 +- src/javascript/tests/core/functions.spec.js | 7 +- src/javascript/tests/for.spec.js | 12 +- .../tests/patterns/defmatch.spec.js | 9 +- src/javascript/tests/patterns/match.spec.js | 7 +- src/javascript/tests/special_forms.spec.js | 9 +- src/javascript/tests/try.spec.js | 14 +- 19 files changed, 2871 insertions(+), 2907 deletions(-) create mode 100644 .babelrc diff --git a/.babelrc b/.babelrc new file mode 100644 index 00000000..3a411289 --- /dev/null +++ b/.babelrc @@ -0,0 +1,3 @@ +{ + "presets": ["react", "es2015", "stage-0"], +} \ No newline at end of file diff --git a/.eslintrc b/.eslintrc index fbe1a0a5..3221dd47 100644 --- a/.eslintrc +++ b/.eslintrc @@ -1,15 +1,12 @@ { - "ecmaFeatures":{ - "modules": true - }, "rules": { "indent": [ 2, - 2 + 4 ], "quotes": [ - 0, - "double" + 2, + "single" ], "linebreak-style": [ 2, @@ -18,29 +15,12 @@ "semi": [ 2, "always" - ], - "no-var": true, - "camelcase": [ - 0, - { - "properties": "never" - } - ], - "no-underscore-dangle": false, - "new-cap": [ - 1, - { - "capIsNew": false - } - ], - "no-extend-native": [2, {"exceptions": ["Object", "String"]}], - "no-unused-vars": [2, {"vars": "all", "args": "none"}], - "space-infix-ops": [2, {"int32Hint": true}] + ] }, "env": { "es6": true, "browser": true, - "mocha": true, "node": true - } + }, + "extends": "eslint:recommended" } \ No newline at end of file diff --git a/.gitignore b/.gitignore index 363c47e8..e1cdbf56 100644 --- a/.gitignore +++ b/.gitignore @@ -5,10 +5,6 @@ erl_crash.dump ex2js elixirscript node_modules -src/javascript/build -src/javascript/test_build -src/javascript/dist -src/javascript/dist_build /dist deploy.sh .DS_Store @@ -19,3 +15,4 @@ index.js /bench/snapshots .tern-port test/std_lib_compile_test.exs +src/elixirscript diff --git a/.travis.yml b/.travis.yml index fb501c9b..21807e42 100644 --- a/.travis.yml +++ b/.travis.yml @@ -8,4 +8,4 @@ before_script: - npm install script: - mix test - - gulp test \ No newline at end of file + - npm test \ No newline at end of file diff --git a/gulpfile.js b/gulpfile.js index 4ad53938..8b68b656 100644 --- a/gulpfile.js +++ b/gulpfile.js @@ -1,60 +1,13 @@ var gulp = require('gulp'); -var mocha = require('gulp-mocha'); var babel = require('gulp-babel'); -var eslint = require('gulp-eslint'); var sourcemaps = require('gulp-sourcemaps'); -require("babel/polyfill"); - var path = './src/javascript'; -var stdLibPath = path + '/lib/**/*.js'; -var testPath = path + '/test_build/tests/**/*.spec.js'; -var libPath = path + '/lib'; - -gulp.task('test_build', function() { - return gulp.src([path + '/lib/**/*.js']) - .pipe(babel({sourceMap: false, modules:'common'})) - .pipe(gulp.dest(path + '/test_build/lib')); -}); - -gulp.task('test_build_tests', function() { - return gulp.src([path + '/tests/**/*.spec.js']) - .pipe(babel({sourceMap: false, modules:'common'})) - .pipe(gulp.dest(path + '/test_build/tests')); -}); - -gulp.task('test', ['test_build', 'test_build_tests'], function () { - return gulp.src(testPath, {read: false}) - .pipe(mocha({reporter: 'nyan'})); -}); -gulp.task('lint', function () { - return gulp.src([stdLibPath, testPath, '!' + path + '/build/**/*.js']) - .pipe(eslint()) - .pipe(eslint.format()) - .pipe(eslint.failOnError()); +gulp.task('build', function() { + return gulp.src([path + '/**/*.js', '!' + path + '/dist_build/**/*.js', '!' + path + '/tests/**/*.js']) + .pipe(sourcemaps.init()) + .pipe(babel({ presets: ["react", "stage-0"], babelrc: false })) + .pipe(sourcemaps.write()) + .pipe(gulp.dest('./src/elixirscript')); }); - -gulp.task('dist_build', function() { - return gulp.src([path + '/**/*.js', '!' + path + '/build/**/*.js', '!' + path + '/dist/**/*.js', '!' + path + '/dist_build/**/*.js', '!' + path + '/tests/**/*.js']) - .pipe(babel({whitelist: ['flow'], optional: ["minification.deadCodeElimination"]})) - .pipe(gulp.dest(path + '/dist_build')); -}); - -gulp.task('dist_add_source_map', function() { - return gulp.src(['./priv/Elixir.js']) - .pipe(sourcemaps.init()) - .pipe(sourcemaps.write()) - .pipe(gulp.dest('./priv')); -}); - -gulp.task('npm_build', function() { - npmDistPath = 'dist/npm' - gulp.src('./package.json').pipe(gulp.dest(npmDistPath)); - gulp.src('./elixirscript').pipe(gulp.dest(npmDistPath)); - return gulp.src([path + '/**/*.js', '!' + path + '/build/**/*.js', '!' + path + '/dist/**/*.js', '!' + path + '/dist_build/**/*.js', '!' + path + '/tests/**/*.js']) - .pipe(babel({sourceMap: false, modules:'common'})) - .pipe(gulp.dest(npmDistPath)); -}); - -gulp.task('default', ['lint', 'test']); diff --git a/mix.exs b/mix.exs index d8d6659c..a08ff024 100644 --- a/mix.exs +++ b/mix.exs @@ -76,10 +76,7 @@ defmodule ElixirScript.Mixfile do File.rm_rf(dist_folder) end - { _ , _ } = System.cmd("node", ["node_modules/gulp/bin/gulp.js", "dist_build"]) - { elixir_js, _ } = System.cmd("node", ["node_modules/rollup/bin/rollup", "./src/javascript/dist_build/Elixir.js"]) - File.write!("priv/Elixir.js", elixir_js) - { _ , _ } = System.cmd("node", ["node_modules/gulp/bin/gulp.js", "dist_add_source_map"]) + { _ , _ } = System.cmd("npm", ["run", "build"]) File.mkdir_p(folder_name <> "/bin") File.cp!("elixirscript", "#{folder_name}/bin/elixirscript") diff --git a/package.json b/package.json index 92a5ece4..dfc1c269 100644 --- a/package.json +++ b/package.json @@ -7,7 +7,10 @@ "elixirscript": "./elixirscript" }, "scripts": { - "test": "echo \"Error: no test specified\" && exit 1" + "lint": "eslint src/javascript/lib/**/*.js src/javascript/tests/**/*.js", + "build": "gulp build && rollup -m inline src/elixirscript/elixir.js -o priv/Elixir.js", + "clean": "rm -rf src/javascript/dist_build", + "test": "mocha src/javascript/tests --recursive --compilers js:babel-core/register" }, "repository": { "type": "git", @@ -17,16 +20,17 @@ "license": "MIT", "dependencies": {}, "devDependencies": { - "acorn": "^2.4.0", - "babel": "^5.8.23", - "babel-core": "^5.2.12", - "chai": "^2.2.0", - "gulp": "^3.8.11", - "gulp-babel": "^5.1.0", - "gulp-eslint": "^0.13.2", - "gulp-mocha": "^2.1.3", - "gulp-sourcemaps": "^1.5.2", - "mocha": "^2.3.3", - "rollup": "^0.24.1" + "babel": "^6.5.2", + "babel-core": "^6.5.2", + "babel-preset-es2015": "^6.5.0", + "babel-preset-react": "^6.5.0", + "babel-preset-stage-0": "^6.5.0", + "chai": "^3.5.0", + "eslint": "^2.2.0", + "gulp": "^3.9.1", + "gulp-babel": "^6.1.2", + "gulp-sourcemaps": "^1.6.0", + "mocha": "^2.4.5", + "rollup": "^0.25.4" } } diff --git a/priv/Elixir.js b/priv/Elixir.js index 43e1f9ae..dfe476f1 100644 --- a/priv/Elixir.js +++ b/priv/Elixir.js @@ -1,3444 +1,3441 @@ -let VirtualDOM = (function (e) { - return e(); -})(function () { - var define, module, exports; - return (function e(t, n, r) { - function s(o, u) { - if (!n[o]) { - if (!t[o]) { - var a = typeof require == "function" && require; - if (!u && a) return a(o, !0); - if (i) return i(o, !0); - var f = new Error("Cannot find module '" + o + "'"); - throw (f.code = "MODULE_NOT_FOUND", f); - } - var l = n[o] = { - exports: {} - }; - t[o][0].call(l.exports, function (e) { - var n = t[o][1][e]; - return s(n ? n : e); - }, l, l.exports, e, t, n, r); - } - return n[o].exports; - } - var i = typeof require == "function" && require; - for (var o = 0; o < r.length; o++) s(r[o]); - return s; - })({ - 1: [function (require, module, exports) { - - var createElement = require("./vdom/create-element.js"); - - module.exports = createElement; - }, { "./vdom/create-element.js": 15 }], 2: [function (require, module, exports) { - var diff = require("./vtree/diff.js"); - - module.exports = diff; - }, { "./vtree/diff.js": 35 }], 3: [function (require, module, exports) { - var h = require("./virtual-hyperscript/index.js"); - - module.exports = h; - }, { "./virtual-hyperscript/index.js": 22 }], 4: [function (require, module, exports) { - var diff = require("./diff.js"); - var patch = require("./patch.js"); - var h = require("./h.js"); - var create = require("./create-element.js"); - var VNode = require("./vnode/vnode.js"); - var VText = require("./vnode/vtext.js"); - - module.exports = { - diff: diff, - patch: patch, - h: h, - create: create, - VNode: VNode, - VText: VText - }; - }, { "./create-element.js": 1, "./diff.js": 2, "./h.js": 3, "./patch.js": 13, "./vnode/vnode.js": 31, "./vnode/vtext.js": 33 }], 5: [function (require, module, exports) { - /*! - * Cross-Browser Split 1.1.1 - * Copyright 2007-2012 Steven Levithan - * Available under the MIT License - * ECMAScript compliant, uniform cross-browser split method - */ - - /** - * Splits a string into an array of strings using a regex or string separator. Matches of the - * separator are not included in the result array. However, if `separator` is a regex that contains - * capturing groups, backreferences are spliced into the result each time `separator` is matched. - * Fixes browser bugs compared to the native `String.prototype.split` and can be used reliably - * cross-browser. - * @param {String} str String to split. - * @param {RegExp|String} separator Regex or string to use for separating the string. - * @param {Number} [limit] Maximum number of items to include in the result array. - * @returns {Array} Array of substrings. - * @example - * - * // Basic use - * split('a b c d', ' '); - * // -> ['a', 'b', 'c', 'd'] - * - * // With limit - * split('a b c d', ' ', 2); - * // -> ['a', 'b'] - * - * // Backreferences in result array - * split('..word1 word2..', /([a-z]+)(\d+)/i); - * // -> ['..', 'word', '1', ' ', 'word', '2', '..'] - */ - module.exports = (function split(undef) { - - var nativeSplit = String.prototype.split, - compliantExecNpcg = /()??/.exec("")[1] === undef, - - // NPCG: nonparticipating capturing group - self; - - self = function (str, separator, limit) { - // If `separator` is not a regex, use `nativeSplit` - if (Object.prototype.toString.call(separator) !== "[object RegExp]") { - return nativeSplit.call(str, separator, limit); - } - var output = [], - flags = (separator.ignoreCase ? "i" : "") + (separator.multiline ? "m" : "") + (separator.extended ? "x" : "") + (separator.sticky ? "y" : ""), - - // Firefox 3+ - lastLastIndex = 0, - - // Make `global` and avoid `lastIndex` issues by working with a copy - separator = new RegExp(separator.source, flags + "g"), - separator2, - match, - lastIndex, - lastLength; - str += ""; // Type-convert - if (!compliantExecNpcg) { - // Doesn't need flags gy, but they don't hurt - separator2 = new RegExp("^" + separator.source + "$(?!\\s)", flags); - } - /* Values for `limit`, per the spec: - * If undefined: 4294967295 // Math.pow(2, 32) - 1 - * If 0, Infinity, or NaN: 0 - * If positive number: limit = Math.floor(limit); if (limit > 4294967295) limit -= 4294967296; - * If negative number: 4294967296 - Math.floor(Math.abs(limit)) - * If other: Type-convert, then use the above rules - */ - limit = limit === undef ? -1 >>> 0 : // Math.pow(2, 32) - 1 - limit >>> 0; // ToUint32(limit) - while (match = separator.exec(str)) { - // `separator.lastIndex` is not reliable cross-browser - lastIndex = match.index + match[0].length; - if (lastIndex > lastLastIndex) { - output.push(str.slice(lastLastIndex, match.index)); - // Fix browsers whose `exec` methods don't consistently return `undefined` for - // nonparticipating capturing groups - if (!compliantExecNpcg && match.length > 1) { - match[0].replace(separator2, function () { - for (var i = 1; i < arguments.length - 2; i++) { - if (arguments[i] === undef) { - match[i] = undef; - } - } - }); - } - if (match.length > 1 && match.index < str.length) { - Array.prototype.push.apply(output, match.slice(1)); - } - lastLength = match[0].length; - lastLastIndex = lastIndex; - if (output.length >= limit) { - break; - } - } - if (separator.lastIndex === match.index) { - separator.lastIndex++; // Avoid an infinite loop - } - } - if (lastLastIndex === str.length) { - if (lastLength || !separator.test("")) { - output.push(""); - } - } else { - output.push(str.slice(lastLastIndex)); - } - return output.length > limit ? output.slice(0, limit) : output; - }; - - return self; - })(); - }, {}], 6: [function (require, module, exports) {}, {}], 7: [function (require, module, exports) { - "use strict"; - - var OneVersionConstraint = require("individual/one-version"); - - var MY_VERSION = "7"; - OneVersionConstraint("ev-store", MY_VERSION); - - var hashKey = "__EV_STORE_KEY@" + MY_VERSION; - - module.exports = EvStore; - - function EvStore(elem) { - var hash = elem[hashKey]; - - if (!hash) { - hash = elem[hashKey] = {}; - } - - return hash; - } - }, { "individual/one-version": 9 }], 8: [function (require, module, exports) { - (function (global) { - "use strict"; +class Mailbox { - /*global window, global*/ + constructor() { + this.messages = []; + } - var root = typeof window !== "undefined" ? window : typeof global !== "undefined" ? global : {}; + deliver(message) { + this.messages.push(message); + return message; + } - module.exports = Individual; + get() { + return this.messages; + } - function Individual(key, value) { - if (key in root) { - return root[key]; - } + isEmpty() { + return this.messages.length === 0; + } - root[key] = value; + removeAt(index) { + this.messages.splice(index, 1); + } +} - return value; - } - }).call(this, typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}); - }, {}], 9: [function (require, module, exports) { - "use strict"; +var States = { + NORMAL: Symbol.for("normal"), + KILL: Symbol.for("kill"), + SUSPEND: Symbol.for("suspend"), + CONTINUE: Symbol.for("continue"), + RECEIVE: Symbol.for("receive"), + SEND: Symbol.for("send"), + SLEEPING: Symbol.for("sleeping"), + RUNNING: Symbol.for("running"), + SUSPENDED: Symbol.for("suspended"), + STOPPED: Symbol.for("stopped"), + SLEEP: Symbol.for("sleep"), + EXIT: Symbol.for("exit"), + NOMATCH: Symbol.for("no_match") +}; - var Individual = require("./index.js"); +class Process { - module.exports = OneVersion; + constructor(pid, mailbox) { + this.pid = pid; + this.mailbox = mailbox; + this.status = States.STOPPED; + this.dict = {}; + } +} - function OneVersion(moduleName, version, defaultValue) { - var key = "__INDIVIDUAL_ONE_VERSION_" + moduleName; - var enforceKey = key + "_ENFORCE_SINGLETON"; +class Tuple { - var versionValue = Individual(enforceKey, version); + constructor(...args) { + this.values = Object.freeze(args); + this.length = this.values.length; + } - if (versionValue !== version) { - throw new Error("Can only have one copy of " + moduleName + ".\n" + "You already have version " + versionValue + " installed.\n" + "This means you cannot install version " + version); - } + get(index) { + return this.values[index]; + } - return Individual(key, defaultValue); - } - }, { "./index.js": 8 }], 10: [function (require, module, exports) { - (function (global) { - var topLevel = typeof global !== "undefined" ? global : typeof window !== "undefined" ? window : {}; - var minDoc = require("min-document"); + count() { + return this.values.length; + } - if (typeof document !== "undefined") { - module.exports = document; - } else { - var doccy = topLevel["__GLOBAL_DOCUMENT_CACHE@4"]; + [Symbol.iterator]() { + return this.values[Symbol.iterator](); + } - if (!doccy) { - doccy = topLevel["__GLOBAL_DOCUMENT_CACHE@4"] = minDoc; - } + toString() { + var i, + s = ""; + for (i = 0; i < this.values.length; i++) { + if (s !== "") { + s += ", "; + } + s += this.values[i].toString(); + } - module.exports = doccy; - } - }).call(this, typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}); - }, { "min-document": 6 }], 11: [function (require, module, exports) { - "use strict"; + return "{" + s + "}"; + } - module.exports = function isObject(x) { - return typeof x === "object" && x !== null; - }; - }, {}], 12: [function (require, module, exports) { - var nativeIsArray = Array.isArray; - var toString = Object.prototype.toString; + put_elem(index, elem) { + if (index === this.length) { + let new_values = this.values.concat([elem]); + return new Tuple(...new_values); + } - module.exports = nativeIsArray || isArray; + let new_values = this.values.concat([]); + new_values.splice(index, 0, elem); + return new Tuple(...new_values); + } - function isArray(obj) { - return toString.call(obj) === "[object Array]"; - } - }, {}], 13: [function (require, module, exports) { - var patch = require("./vdom/patch.js"); + remove_elem(index) { + let new_values = this.values.concat([]); + new_values.splice(index, 1); + return new Tuple(...new_values); + } - module.exports = patch; - }, { "./vdom/patch.js": 18 }], 14: [function (require, module, exports) { - var isObject = require("is-object"); - var isHook = require("../vnode/is-vhook.js"); +} - module.exports = applyProperties; +let process_counter = -1; - function applyProperties(node, props, previous) { - for (var propName in props) { - var propValue = props[propName]; +class PID { + constructor() { + process_counter = process_counter + 1; + this.id = process_counter; + } - if (propValue === undefined) { - removeProperty(node, propName, propValue, previous); - } else if (isHook(propValue)) { - removeProperty(node, propName, propValue, previous); - if (propValue.hook) { - propValue.hook(node, propName, previous ? previous[propName] : undefined); - } - } else { - if (isObject(propValue)) { - patchObject(node, props, previous, propName, propValue); - } else { - node[propName] = propValue; - } - } - } - } + toString() { + return "PID#<0." + this.id + ".0>"; + } +} - function removeProperty(node, propName, propValue, previous) { - if (previous) { - var previousValue = previous[propName]; +class Integer {} +class Float {} - if (!isHook(previousValue)) { - if (propName === "attributes") { - for (var attrName in previousValue) { - node.removeAttribute(attrName); - } - } else if (propName === "style") { - for (var i in previousValue) { - node.style[i] = ""; - } - } else if (typeof previousValue === "string") { - node[propName] = ""; - } else { - node[propName] = null; - } - } else if (previousValue.unhook) { - previousValue.unhook(node, propName, propValue); - } - } - } +class ProcessSystem { - function patchObject(node, props, previous, propName, propValue) { - var previousValue = previous ? previous[propName] : undefined; + constructor() { + this.pids = new Map(); + this.mailboxes = new Map(); + this.names = new Map(); + this.links = new Map(); - // Set attributes - if (propName === "attributes") { - for (var attrName in propValue) { - var attrValue = propValue[attrName]; + this.current_process = null; + this.suspended = new Map(); - if (attrValue === undefined) { - node.removeAttribute(attrName); - } else { - node.setAttribute(attrName, attrValue); - } - } + this.main_process_pid = this.spawn(); + this.set_current(this.main_process_pid); + } - return; - } + spawn() { + return this.add_proc(false).pid; + } - if (previousValue && isObject(previousValue) && getPrototype(previousValue) !== getPrototype(propValue)) { - node[propName] = propValue; - return; - } + spawn_link() { + return this.add_proc(true).pid; + } - if (!isObject(node[propName])) { - node[propName] = {}; - } + link(pid) { + this.links.get(this.pid()).add(pid); + this.links.get(pid).add(this.pid()); + } - var replacer = propName === "style" ? "" : undefined; + unlink(pid) { + this.links.get(this.pid()).delete(pid); + this.links.get(pid).delete(this.pid()); + } - for (var k in propValue) { - var value = propValue[k]; - node[propName][k] = value === undefined ? replacer : value; - } - } + set_current(id) { + let pid = this.pidof(id); + if (pid !== null) { + this.current_process = this.pids.get(pid); + this.current_process.status = States.RUNNING; + } + } - function getPrototype(value) { - if (Object.getPrototypeOf) { - return Object.getPrototypeOf(value); - } else if (value.__proto__) { - return value.__proto__; - } else if (value.constructor) { - return value.constructor.prototype; - } - } - }, { "../vnode/is-vhook.js": 26, "is-object": 11 }], 15: [function (require, module, exports) { - var document = require("global/document"); + add_proc(linked) { + let newpid = new PID(); + let mailbox = new Mailbox(); + let newproc = new Process(newpid, mailbox); - var applyProperties = require("./apply-properties"); + this.pids.set(newpid, newproc); + this.mailboxes.set(newpid, mailbox); + this.links.set(newpid, new Set()); - var isVNode = require("../vnode/is-vnode.js"); - var isVText = require("../vnode/is-vtext.js"); - var isWidget = require("../vnode/is-widget.js"); - var handleThunk = require("../vnode/handle-thunk.js"); + if (linked) { + this.link(newpid); + } - module.exports = createElement; + return newproc; + } - function createElement(vnode, opts) { - var doc = opts ? opts.document || document : document; - var warn = opts ? opts.warn : null; + remove_proc(pid) { + this.pids.delete(pid); + this.unregister(pid); - vnode = handleThunk(vnode).a; + if (this.links.has(pid)) { + for (let linkpid of this.links.get(pid)) { + this.links.get(linkpid).delete(pid); + } - if (isWidget(vnode)) { - return vnode.init(); - } else if (isVText(vnode)) { - return doc.createTextNode(vnode.text); - } else if (!isVNode(vnode)) { - if (warn) { - warn("Item is not a valid virtual dom node", vnode); - } - return null; - } + this.links.delete(pid); + } + } - var node = vnode.namespace === null ? doc.createElement(vnode.tagName) : doc.createElementNS(vnode.namespace, vnode.tagName); + exit(id) { + let pid = this.pidof(id); + this.remove_proc(id); + } - var props = vnode.properties; - applyProperties(node, props); + register(name, pid) { + if (!this.names.has(name)) { + this.names.set(name, pid); + return name; + } else { + throw new Error("Name is already registered to another process"); + } + } - var children = vnode.children; + registered(name) { + return this.names.has(name) ? this.names.get(name) : null; + } - for (var i = 0; i < children.length; i++) { - var childNode = createElement(children[i], opts); - if (childNode) { - node.appendChild(childNode); - } - } + unregister(pid) { + for (let name of this.names.keys()) { + if (this.names.has(name) && this.names.get(name) === pid) { + this.names.delete(name); + } + } + } - return node; - } - }, { "../vnode/handle-thunk.js": 24, "../vnode/is-vnode.js": 27, "../vnode/is-vtext.js": 28, "../vnode/is-widget.js": 29, "./apply-properties": 14, "global/document": 10 }], 16: [function (require, module, exports) { - // Maps a virtual DOM tree onto a real DOM tree in an efficient manner. - // We don't want to read all of the DOM nodes in the tree so we use - // the in-order tree indexing to eliminate recursion down certain branches. - // We only recurse into a DOM node if we know that it contains a child of - // interest. + pid() { + return this.current_process.pid; + } - var noChild = {}; + pidof(id) { + if (id instanceof PID) { + return this.pids.has(id) ? id : null; + } else if (id instanceof Process) { + return id.pid; + } else { + let pid = this.registered(id); + if (pid === null) throw "Process name not registered: " + id + " (" + typeof id + ")"; + return pid; + } + } - module.exports = domIndex; + put(id, key, value) { + let pid = this.pidof(id); + let process = this.pids.get(pid); + process.dict[key] = value; + } - function domIndex(rootNode, tree, indices, nodes) { - if (!indices || indices.length === 0) { - return {}; - } else { - indices.sort(ascending); - return recurse(rootNode, tree, indices, nodes, 0); - } - } + get(id, key) { + let pid = this.pidof(id); + let process = this.pids.get(pid); - function recurse(rootNode, tree, indices, nodes, rootIndex) { - nodes = nodes || {}; + if (key != null) { + return process.dict[key]; + } else { + return process.dict; + } + } - if (rootNode) { - if (indexInRange(indices, rootIndex, rootIndex)) { - nodes[rootIndex] = rootNode; - } + get_keys(id) { + let pid = this.pidof(id); + let process = this.pids.get(pid); - var vChildren = tree.children; + return Object.keys(process.dict); + } - if (vChildren) { + erase(id, key) { + let pid = this.pidof(id); + let process = this.pids.get(pid); - var childNodes = rootNode.childNodes; + if (key != null) { + delete process.dict[key]; + } else { + process.dict = {}; + } + } +} - for (var i = 0; i < tree.children.length; i++) { - rootIndex += 1; +class BitString { + constructor(...args) { + this.raw_value = function () { + return Object.freeze(args); + }; - var vChild = vChildren[i] || noChild; - var nextIndex = rootIndex + (vChild.count || 0); + this.value = Object.freeze(this.process(args)); + this.length = this.value.length; + this.bit_size = this.raw_value().reduce((prev, current) => prev + current.size); + this.byte_size = this.bit_size / 8 + (this.bit_size % 8 > 0 ? 1 : 0); + } - // skip recursion down the tree if there are no nodes down here - if (indexInRange(indices, rootIndex, nextIndex)) { - recurse(childNodes[i], vChild, indices, nodes, rootIndex); - } + get(index) { + return this.value[index]; + } - rootIndex = nextIndex; - } - } - } + count() { + return this.value.length; + } - return nodes; - } + [Symbol.iterator]() { + return this.value[Symbol.iterator](); + } - // Binary search for an index in the interval [left, right] - function indexInRange(indices, left, right) { - if (indices.length === 0) { - return false; - } + toString() { + var i, + s = ""; + for (i = 0; i < this.count(); i++) { + if (s !== "") { + s += ", "; + } + s += this[i].toString(); + } - var minIndex = 0; - var maxIndex = indices.length - 1; - var currentIndex; - var currentItem; + return "<<" + s + ">>"; + } - while (minIndex <= maxIndex) { - currentIndex = (maxIndex + minIndex) / 2 >> 0; - currentItem = indices[currentIndex]; + process() { + let processed_values = []; - if (minIndex === maxIndex) { - return currentItem >= left && currentItem <= right; - } else if (currentItem < left) { - minIndex = currentIndex + 1; - } else if (currentItem > right) { - maxIndex = currentIndex - 1; - } else { - return true; - } - } + var i; + for (i = 0; i < this.raw_value().length; i++) { + let processed_value = this['process_' + this.raw_value()[i].type](this.raw_value()[i]); - return false; - } + for (let attr of this.raw_value()[i].attributes) { + processed_value = this['process_' + attr](processed_value); + } - function ascending(a, b) { - return a > b ? 1 : -1; - } - }, {}], 17: [function (require, module, exports) { - var applyProperties = require("./apply-properties"); + processed_values = processed_values.concat(processed_value); + } - var isWidget = require("../vnode/is-widget.js"); - var VPatch = require("../vnode/vpatch.js"); + return processed_values; + } - var updateWidget = require("./update-widget"); + process_integer(value) { + return value.value; + } - module.exports = applyPatch; + process_float(value) { + if (value.size === 64) { + return BitString.float64ToBytes(value.value); + } else if (value.size === 32) { + return BitString.float32ToBytes(value.value); + } - function applyPatch(vpatch, domNode, renderOptions) { - var type = vpatch.type; - var vNode = vpatch.vNode; - var patch = vpatch.patch; + throw new Error('Invalid size for float'); + } - switch (type) { - case VPatch.REMOVE: - return removeNode(domNode, vNode); - case VPatch.INSERT: - return insertNode(domNode, patch, renderOptions); - case VPatch.VTEXT: - return stringPatch(domNode, vNode, patch, renderOptions); - case VPatch.WIDGET: - return widgetPatch(domNode, vNode, patch, renderOptions); - case VPatch.VNODE: - return vNodePatch(domNode, vNode, patch, renderOptions); - case VPatch.ORDER: - reorderChildren(domNode, patch); - return domNode; - case VPatch.PROPS: - applyProperties(domNode, patch, vNode.properties); - return domNode; - case VPatch.THUNK: - return replaceRoot(domNode, renderOptions.patch(domNode, patch, renderOptions)); - default: - return domNode; - } - } + process_bitstring(value) { + return value.value.value; + } - function removeNode(domNode, vNode) { - var parentNode = domNode.parentNode; + process_binary(value) { + return BitString.toUTF8Array(value.value); + } - if (parentNode) { - parentNode.removeChild(domNode); - } + process_utf8(value) { + return BitString.toUTF8Array(value.value); + } - destroyWidget(domNode, vNode); + process_utf16(value) { + return BitString.toUTF16Array(value.value); + } - return null; - } + process_utf32(value) { + return BitString.toUTF32Array(value.value); + } - function insertNode(parentNode, vNode, renderOptions) { - var newNode = renderOptions.render(vNode, renderOptions); + process_signed(value) { + return new Uint8Array([value])[0]; + } - if (parentNode) { - parentNode.appendChild(newNode); - } + process_unsigned(value) { + return value; + } - return parentNode; - } + process_native(value) { + return value; + } - function stringPatch(domNode, leftVNode, vText, renderOptions) { - var newNode; + process_big(value) { + return value; + } - if (domNode.nodeType === 3) { - domNode.replaceData(0, domNode.length, vText.text); - newNode = domNode; - } else { - var parentNode = domNode.parentNode; - newNode = renderOptions.render(vText, renderOptions); + process_little(value) { + return value.reverse(); + } - if (parentNode && newNode !== domNode) { - parentNode.replaceChild(newNode, domNode); - } - } + process_size(value) { + return value; + } - return newNode; - } + process_unit(value) { + return value; + } - function widgetPatch(domNode, leftVNode, widget, renderOptions) { - var updating = updateWidget(leftVNode, widget); - var newNode; + static integer(value) { + return BitString.wrap(value, { 'type': 'integer', 'unit': 1, 'size': 8 }); + } - if (updating) { - newNode = widget.update(leftVNode, domNode) || domNode; - } else { - newNode = renderOptions.render(widget, renderOptions); - } + static float(value) { + return BitString.wrap(value, { 'type': 'float', 'unit': 1, 'size': 64 }); + } - var parentNode = domNode.parentNode; + static bitstring(value) { + return BitString.wrap(value, { 'type': 'bitstring', 'unit': 1, 'size': value.bit_size }); + } - if (parentNode && newNode !== domNode) { - parentNode.replaceChild(newNode, domNode); - } + static bits(value) { + return BitString.bitstring(value); + } - if (!updating) { - destroyWidget(domNode, leftVNode); - } + static binary(value) { + return BitString.wrap(value, { 'type': 'binary', 'unit': 8, 'size': value.length }); + } - return newNode; - } + static bytes(value) { + return BitString.binary(value); + } - function vNodePatch(domNode, leftVNode, vNode, renderOptions) { - var parentNode = domNode.parentNode; - var newNode = renderOptions.render(vNode, renderOptions); + static utf8(value) { + return BitString.wrap(value, { 'type': 'utf8' }); + } - if (parentNode && newNode !== domNode) { - parentNode.replaceChild(newNode, domNode); - } + static utf16(value) { + return BitString.wrap(value, { 'type': 'utf16' }); + } - return newNode; - } + static utf32(value) { + return BitString.wrap(value, { 'type': 'utf32' }); + } - function destroyWidget(domNode, w) { - if (typeof w.destroy === "function" && isWidget(w)) { - w.destroy(domNode); - } - } + static signed(value) { + return BitString.wrap(value, {}, 'signed'); + } - function reorderChildren(domNode, moves) { - var childNodes = domNode.childNodes; - var keyMap = {}; - var node; - var remove; - var insert; + static unsigned(value) { + return BitString.wrap(value, {}, 'unsigned'); + } - for (var i = 0; i < moves.removes.length; i++) { - remove = moves.removes[i]; - node = childNodes[remove.from]; - if (remove.key) { - keyMap[remove.key] = node; - } - domNode.removeChild(node); - } + static native(value) { + return BitString.wrap(value, {}, 'native'); + } - var length = childNodes.length; - for (var j = 0; j < moves.inserts.length; j++) { - insert = moves.inserts[j]; - node = keyMap[insert.key]; - // this is the weirdest bug i've ever seen in webkit - domNode.insertBefore(node, insert.to >= length++ ? null : childNodes[insert.to]); - } - } + static big(value) { + return BitString.wrap(value, {}, 'big'); + } - function replaceRoot(oldRoot, newRoot) { - if (oldRoot && newRoot && oldRoot !== newRoot && oldRoot.parentNode) { - oldRoot.parentNode.replaceChild(newRoot, oldRoot); - } + static little(value) { + return BitString.wrap(value, {}, 'little'); + } - return newRoot; - } - }, { "../vnode/is-widget.js": 29, "../vnode/vpatch.js": 32, "./apply-properties": 14, "./update-widget": 19 }], 18: [function (require, module, exports) { - var document = require("global/document"); - var isArray = require("x-is-array"); + static size(value, count) { + return BitString.wrap(value, { 'size': count }); + } - var render = require("./create-element"); - var domIndex = require("./dom-index"); - var patchOp = require("./patch-op"); - module.exports = patch; + static unit(value, count) { + return BitString.wrap(value, { 'unit': count }); + } - function patch(rootNode, patches, renderOptions) { - renderOptions = renderOptions || {}; - renderOptions.patch = renderOptions.patch && renderOptions.patch !== patch ? renderOptions.patch : patchRecursive; - renderOptions.render = renderOptions.render || render; + static wrap(value, opt, new_attribute = null) { + let the_value = value; - return renderOptions.patch(rootNode, patches, renderOptions); - } + if (!(value instanceof Object)) { + the_value = { 'value': value, 'attributes': [] }; + } - function patchRecursive(rootNode, patches, renderOptions) { - var indices = patchIndices(patches); + the_value = Object.assign(the_value, opt); - if (indices.length === 0) { - return rootNode; - } + if (new_attribute) { + the_value.attributes.push(new_attribute); + } - var index = domIndex(rootNode, patches.a, indices); - var ownerDocument = rootNode.ownerDocument; + return the_value; + } - if (!renderOptions.document && ownerDocument !== document) { - renderOptions.document = ownerDocument; - } + static toUTF8Array(str) { + var utf8 = []; + for (var i = 0; i < str.length; i++) { + var charcode = str.charCodeAt(i); + if (charcode < 0x80) { + utf8.push(charcode); + } else if (charcode < 0x800) { + utf8.push(0xc0 | charcode >> 6, 0x80 | charcode & 0x3f); + } else if (charcode < 0xd800 || charcode >= 0xe000) { + utf8.push(0xe0 | charcode >> 12, 0x80 | charcode >> 6 & 0x3f, 0x80 | charcode & 0x3f); + } + // surrogate pair + else { + i++; + // UTF-16 encodes 0x10000-0x10FFFF by + // subtracting 0x10000 and splitting the + // 20 bits of 0x0-0xFFFFF into two halves + charcode = 0x10000 + ((charcode & 0x3ff) << 10 | str.charCodeAt(i) & 0x3ff); + utf8.push(0xf0 | charcode >> 18, 0x80 | charcode >> 12 & 0x3f, 0x80 | charcode >> 6 & 0x3f, 0x80 | charcode & 0x3f); + } + } + return utf8; + } - for (var i = 0; i < indices.length; i++) { - var nodeIndex = indices[i]; - rootNode = applyPatch(rootNode, index[nodeIndex], patches[nodeIndex], renderOptions); - } + static toUTF16Array(str) { + var utf16 = []; + for (var i = 0; i < str.length; i++) { + var codePoint = str.codePointAt(i); - return rootNode; - } + if (codePoint <= 255) { + utf16.push(0); + utf16.push(codePoint); + } else { + utf16.push(codePoint >> 8 & 0xFF); + utf16.push(codePoint & 0xFF); + } + } + return utf16; + } - function applyPatch(rootNode, domNode, patchList, renderOptions) { - if (!domNode) { - return rootNode; - } + static toUTF32Array(str) { + var utf32 = []; + for (var i = 0; i < str.length; i++) { + var codePoint = str.codePointAt(i); - var newNode; + if (codePoint <= 255) { + utf32.push(0); + utf32.push(0); + utf32.push(0); + utf32.push(codePoint); + } else { + utf32.push(0); + utf32.push(0); + utf32.push(codePoint >> 8 & 0xFF); + utf32.push(codePoint & 0xFF); + } + } + return utf32; + } - if (isArray(patchList)) { - for (var i = 0; i < patchList.length; i++) { - newNode = patchOp(patchList[i], domNode, renderOptions); + //http://stackoverflow.com/questions/2003493/javascript-float-from-to-bits + static float32ToBytes(f) { + var bytes = []; - if (domNode === rootNode) { - rootNode = newNode; - } - } - } else { - newNode = patchOp(patchList, domNode, renderOptions); + var buf = new ArrayBuffer(4); + new Float32Array(buf)[0] = f; + + let intVersion = new Uint32Array(buf)[0]; + + bytes.push(intVersion >> 24 & 0xFF); + bytes.push(intVersion >> 16 & 0xFF); + bytes.push(intVersion >> 8 & 0xFF); + bytes.push(intVersion & 0xFF); - if (domNode === rootNode) { - rootNode = newNode; - } - } + return bytes; + } - return rootNode; - } + static float64ToBytes(f) { + var bytes = []; - function patchIndices(patches) { - var indices = []; + var buf = new ArrayBuffer(8); + new Float64Array(buf)[0] = f; - for (var key in patches) { - if (key !== "a") { - indices.push(Number(key)); - } - } + var intVersion1 = new Uint32Array(buf)[0]; + var intVersion2 = new Uint32Array(buf)[1]; - return indices; - } - }, { "./create-element": 15, "./dom-index": 16, "./patch-op": 17, "global/document": 10, "x-is-array": 12 }], 19: [function (require, module, exports) { - var isWidget = require("../vnode/is-widget.js"); + bytes.push(intVersion2 >> 24 & 0xFF); + bytes.push(intVersion2 >> 16 & 0xFF); + bytes.push(intVersion2 >> 8 & 0xFF); + bytes.push(intVersion2 & 0xFF); - module.exports = updateWidget; + bytes.push(intVersion1 >> 24 & 0xFF); + bytes.push(intVersion1 >> 16 & 0xFF); + bytes.push(intVersion1 >> 8 & 0xFF); + bytes.push(intVersion1 & 0xFF); - function updateWidget(a, b) { - if (isWidget(a) && isWidget(b)) { - if ("name" in a && "name" in b) { - return a.id === b.id; - } else { - return a.init === b.init; - } - } + return bytes; + } +} - return false; - } - }, { "../vnode/is-widget.js": 29 }], 20: [function (require, module, exports) { - "use strict"; +class Variable { - var EvStore = require("ev-store"); + constructor(name = null) { + this.name = name; + } +} - module.exports = EvHook; +class Wildcard { + constructor() {} +} - function EvHook(value) { - if (!(this instanceof EvHook)) { - return new EvHook(value); - } +class StartsWith { - this.value = value; - } + constructor(prefix) { + this.prefix = prefix; + } +} - EvHook.prototype.hook = function (node, propertyName) { - var es = EvStore(node); - var propName = propertyName.substr(3); +class Capture { - es[propName] = this.value; - }; + constructor(value) { + this.value = value; + } +} - EvHook.prototype.unhook = function (node, propertyName) { - var es = EvStore(node); - var propName = propertyName.substr(3); +class HeadTail { - es[propName] = undefined; - }; - }, { "ev-store": 7 }], 21: [function (require, module, exports) { - "use strict"; + constructor(head = null, tail = null) { + this.head = head; + this.tail = tail; + } +} - module.exports = SoftSetHook; +class Type { - function SoftSetHook(value) { - if (!(this instanceof SoftSetHook)) { - return new SoftSetHook(value); - } + constructor(type, objPattern = {}) { + this.type = type; + this.objPattern = objPattern; + } +} - this.value = value; - } +class Bound { - SoftSetHook.prototype.hook = function (node, propertyName) { - if (node[propertyName] !== this.value) { - node[propertyName] = this.value; - } - }; - }, {}], 22: [function (require, module, exports) { - "use strict"; + constructor(value) { + this.value = value; + } +} - var isArray = require("x-is-array"); +function variable(name = null) { + return new Variable(name); +} - var VNode = require("../vnode/vnode.js"); - var VText = require("../vnode/vtext.js"); - var isVNode = require("../vnode/is-vnode"); - var isVText = require("../vnode/is-vtext"); - var isWidget = require("../vnode/is-widget"); - var isHook = require("../vnode/is-vhook"); - var isVThunk = require("../vnode/is-thunk"); +function wildcard() { + return new Wildcard(); +} - var parseTag = require("./parse-tag.js"); - var softSetHook = require("./hooks/soft-set-hook.js"); - var evHook = require("./hooks/ev-hook.js"); +function startsWith(prefix) { + return new StartsWith(prefix); +} - module.exports = h; +function capture(value) { + return new Capture(value); +} - function h(tagName, properties, children) { - var childNodes = []; - var tag, props, key, namespace; +function headTail(head = null, tail = null) { + return new HeadTail(head, tail); +} - if (!children && isChildren(properties)) { - children = properties; - props = {}; - } +function type(type, objPattern = {}) { + return new Type(type, objPattern); +} - props = props || properties || {}; - tag = parseTag(tagName, props); +function bound(value) { + return new Bound(value); +} - // support keys - if (props.hasOwnProperty("key")) { - key = props.key; - props.key = undefined; - } +function is_number(value) { + return typeof value === 'number'; +} - // support namespace - if (props.hasOwnProperty("namespace")) { - namespace = props.namespace; - props.namespace = undefined; - } +function is_string(value) { + return typeof value === 'string'; +} - // fix cursor bug - if (tag === "INPUT" && !namespace && props.hasOwnProperty("value") && props.value !== undefined && !isHook(props.value)) { - props.value = softSetHook(props.value); - } +function is_boolean(value) { + return typeof value === 'boolean'; +} - transformProperties(props); +function is_symbol(value) { + return typeof value === 'symbol'; +} - if (children !== undefined && children !== null) { - addChild(children, childNodes, tag, props); - } +function is_null(value) { + return value === null; +} - return new VNode(tag, props, childNodes, key, namespace); - } +function is_undefined(value) { + return typeof value === 'undefined'; +} - function addChild(c, childNodes, tag, props) { - if (typeof c === "string") { - childNodes.push(new VText(c)); - } else if (typeof c === "number") { - childNodes.push(new VText(String(c))); - } else if (isChild(c)) { - childNodes.push(c); - } else if (isArray(c)) { - for (var i = 0; i < c.length; i++) { - addChild(c[i], childNodes, tag, props); - } - } else if (c === null || c === undefined) { - return; - } else { - throw UnexpectedVirtualElement({ - foreignObject: c, - parentVnode: { - tagName: tag, - properties: props - } - }); - } - } +function is_function(value) { + return Object.prototype.toString.call(value) == '[object Function]'; +} - function transformProperties(props) { - for (var propName in props) { - if (props.hasOwnProperty(propName)) { - var value = props[propName]; +function is_variable(value) { + return value instanceof Variable; +} - if (isHook(value)) { - continue; - } +function is_wildcard(value) { + return value instanceof Wildcard; +} - if (propName.substr(0, 3) === "ev-") { - // add ev-foo support - props[propName] = evHook(value); - } - } - } - } +function is_headTail(value) { + return value instanceof HeadTail; +} - function isChild(x) { - return isVNode(x) || isVText(x) || isWidget(x) || isVThunk(x); - } +function is_capture(value) { + return value instanceof Capture; +} - function isChildren(x) { - return typeof x === "string" || isArray(x) || isChild(x); - } +function is_type(value) { + return value instanceof Type; +} - function UnexpectedVirtualElement(data) { - var err = new Error(); +function is_startsWith(value) { + return value instanceof StartsWith; +} - err.type = "virtual-hyperscript.unexpected.virtual-element"; - err.message = "Unexpected virtual child passed to h().\n" + "Expected a VNode / Vthunk / VWidget / string but:\n" + "got:\n" + errorString(data.foreignObject) + ".\n" + "The parent vnode is:\n" + errorString(data.parentVnode); - "\n" + "Suggested fix: change your `h(..., [ ... ])` callsite."; - err.foreignObject = data.foreignObject; - err.parentVnode = data.parentVnode; +function is_bound(value) { + return value instanceof Bound; +} - return err; - } +function is_object(value) { + return typeof value === 'object'; +} + +function is_array(value) { + return Array.isArray(value); +} - function errorString(obj) { - try { - return JSON.stringify(obj, null, " "); - } catch (e) { - return String(obj); - } - } - }, { "../vnode/is-thunk": 25, "../vnode/is-vhook": 26, "../vnode/is-vnode": 27, "../vnode/is-vtext": 28, "../vnode/is-widget": 29, "../vnode/vnode.js": 31, "../vnode/vtext.js": 33, "./hooks/ev-hook.js": 20, "./hooks/soft-set-hook.js": 21, "./parse-tag.js": 23, "x-is-array": 12 }], 23: [function (require, module, exports) { - "use strict"; +var Checks = { + is_number, + is_string, + is_boolean, + is_symbol, + is_null, + is_undefined, + is_function, + is_variable, + is_wildcard, + is_headTail, + is_capture, + is_type, + is_startsWith, + is_bound, + is_object, + is_array +}; - var split = require("browser-split"); +function resolveSymbol(pattern) { + return function (value) { + return Checks.is_symbol(value) && value === pattern; + }; +} - var classIdSplit = /([\.#]?[a-zA-Z0-9\u007F-\uFFFF_:-]+)/; - var notClassId = /^\.|#/; +function resolveString(pattern) { + return function (value) { + return Checks.is_string(value) && value === pattern; + }; +} - module.exports = parseTag; +function resolveNumber(pattern) { + return function (value) { + return Checks.is_number(value) && value === pattern; + }; +} - function parseTag(tag, props) { - if (!tag) { - return "DIV"; - } +function resolveBoolean(pattern) { + return function (value) { + return Checks.is_boolean(value) && value === pattern; + }; +} - var noId = !props.hasOwnProperty("id"); +function resolveFunction(pattern) { + return function (value) { + return Checks.is_function(value) && value === pattern; + }; +} - var tagParts = split(tag, classIdSplit); - var tagName = null; +function resolveNull(pattern) { + return function (value) { + return Checks.is_null(value); + }; +} - if (notClassId.test(tagParts[1])) { - tagName = "DIV"; - } +function resolveBound(pattern) { + return function (value, args) { + if (typeof value === typeof pattern.value && value === pattern.value) { + args.push(value); + return true; + } - var classes, part, type, i; + return false; + }; +} - for (i = 0; i < tagParts.length; i++) { - part = tagParts[i]; +function resolveWildcard() { + return function () { + return true; + }; +} - if (!part) { - continue; - } +function resolveVariable() { + return function (value, args) { + args.push(value); + return true; + }; +} - type = part.charAt(0); +function resolveHeadTail(pattern) { + const headMatches = buildMatch(pattern.head); + const tailMatches = buildMatch(pattern.tail); - if (!tagName) { - tagName = part; - } else if (type === ".") { - classes = classes || []; - classes.push(part.substring(1, part.length)); - } else if (type === "#" && noId) { - props.id = part.substring(1, part.length); - } - } + return function (value, args) { + if (!Checks.is_array(value) || value.length < 2) { + return false; + } - if (classes) { - if (props.className) { - classes.push(props.className); - } + const head = value[0]; + const tail = value.slice(1); - props.className = classes.join(" "); - } + if (headMatches(head, args) && tailMatches(tail, args)) { + return true; + } + }; +} - return props.namespace ? tagName : tagName.toUpperCase(); - } - }, { "browser-split": 5 }], 24: [function (require, module, exports) { - var isVNode = require("./is-vnode"); - var isVText = require("./is-vtext"); - var isWidget = require("./is-widget"); - var isThunk = require("./is-thunk"); +function resolveCapture(pattern) { + const matches = buildMatch(pattern.value); - module.exports = handleThunk; + return function (value, args) { + if (matches(value, args)) { + args.push(value); + return true; + } - function handleThunk(a, b) { - var renderedA = a; - var renderedB = b; + return false; + }; +} - if (isThunk(b)) { - renderedB = renderThunk(b, a); - } +function resolveStartsWith(pattern) { + const prefix = pattern.prefix; - if (isThunk(a)) { - renderedA = renderThunk(a, null); - } + return function (value, args) { + if (Checks.is_string(value) && value.startsWith(prefix)) { + args.push(value.substring(prefix.length)); + return true; + } - return { - a: renderedA, - b: renderedB - }; - } + return false; + }; +} - function renderThunk(thunk, previous) { - var renderedThunk = thunk.vnode; +function resolveType(pattern) { + return function (value, args) { + if (value instanceof pattern.type) { + const matches = buildMatch(pattern.objPattern); + return matches(value, args) && args.push(value) > 0; + } - if (!renderedThunk) { - renderedThunk = thunk.vnode = thunk.render(previous); - } + return false; + }; +} - if (!(isVNode(renderedThunk) || isVText(renderedThunk) || isWidget(renderedThunk))) { - throw new Error("thunk did not return a valid node"); - } +function resolveArray(pattern) { + const matches = pattern.map(x => buildMatch(x)); - return renderedThunk; - } - }, { "./is-thunk": 25, "./is-vnode": 27, "./is-vtext": 28, "./is-widget": 29 }], 25: [function (require, module, exports) { - module.exports = isThunk; + return function (value, args) { + if (!Checks.is_array(value) || value.length != pattern.length) { + return false; + } - function isThunk(t) { - return t && t.type === "Thunk"; - } - }, {}], 26: [function (require, module, exports) { - module.exports = isHook; + return value.every(function (v, i) { + return matches[i](value[i], args); + }); + }; +} - function isHook(hook) { - return hook && (typeof hook.hook === "function" && !hook.hasOwnProperty("hook") || typeof hook.unhook === "function" && !hook.hasOwnProperty("unhook")); - } - }, {}], 27: [function (require, module, exports) { - var version = require("./version"); +function resolveObject(pattern) { + let matches = {}; - module.exports = isVirtualNode; + for (let key of Object.keys(pattern).concat(Object.getOwnPropertySymbols(pattern))) { + matches[key] = buildMatch(pattern[key]); + } - function isVirtualNode(x) { - return x && x.type === "VirtualNode" && x.version === version; - } - }, { "./version": 30 }], 28: [function (require, module, exports) { - var version = require("./version"); + return function (value, args) { + if (!Checks.is_object(value) || pattern.length > value.length) { + return false; + } - module.exports = isVirtualText; + for (let key of Object.keys(pattern).concat(Object.getOwnPropertySymbols(pattern))) { + if (!(key in value) || !matches[key](value[key], args)) { + return false; + } + } - function isVirtualText(x) { - return x && x.type === "VirtualText" && x.version === version; - } - }, { "./version": 30 }], 29: [function (require, module, exports) { - module.exports = isWidget; + return true; + }; +} - function isWidget(w) { - return w && w.type === "Widget"; - } - }, {}], 30: [function (require, module, exports) { - module.exports = "2"; - }, {}], 31: [function (require, module, exports) { - var version = require("./version"); - var isVNode = require("./is-vnode"); - var isWidget = require("./is-widget"); - var isThunk = require("./is-thunk"); - var isVHook = require("./is-vhook"); +function resolveNoMatch() { + return function () { + return false; + }; +} + +var Resolvers = { + resolveBound, + resolveWildcard, + resolveVariable, + resolveHeadTail, + resolveCapture, + resolveStartsWith, + resolveType, + resolveArray, + resolveObject, + resolveNoMatch, + resolveSymbol, + resolveString, + resolveNumber, + resolveBoolean, + resolveFunction, + resolveNull +}; - module.exports = VirtualNode; +function buildMatch(pattern) { - var noProperties = {}; - var noChildren = []; + if (Checks.is_variable(pattern)) { + return Resolvers.resolveVariable(pattern); + } - function VirtualNode(tagName, properties, children, key, namespace) { - this.tagName = tagName; - this.properties = properties || noProperties; - this.children = children || noChildren; - this.key = key != null ? String(key) : undefined; - this.namespace = typeof namespace === "string" ? namespace : null; + if (Checks.is_wildcard(pattern)) { + return Resolvers.resolveWildcard(pattern); + } - var count = children && children.length || 0; - var descendants = 0; - var hasWidgets = false; - var hasThunks = false; - var descendantHooks = false; - var hooks; + if (Checks.is_undefined(pattern)) { + return Resolvers.resolveWildcard(pattern); + } - for (var propName in properties) { - if (properties.hasOwnProperty(propName)) { - var property = properties[propName]; - if (isVHook(property) && property.unhook) { - if (!hooks) { - hooks = {}; - } + if (Checks.is_headTail(pattern)) { + return Resolvers.resolveHeadTail(pattern); + } - hooks[propName] = property; - } - } - } + if (Checks.is_startsWith(pattern)) { + return Resolvers.resolveStartsWith(pattern); + } - for (var i = 0; i < count; i++) { - var child = children[i]; - if (isVNode(child)) { - descendants += child.count || 0; + if (Checks.is_capture(pattern)) { + return Resolvers.resolveCapture(pattern); + } - if (!hasWidgets && child.hasWidgets) { - hasWidgets = true; - } + if (Checks.is_bound(pattern)) { + return Resolvers.resolveBound(pattern); + } - if (!hasThunks && child.hasThunks) { - hasThunks = true; - } + if (Checks.is_type(pattern)) { + return Resolvers.resolveType(pattern); + } - if (!descendantHooks && (child.hooks || child.descendantHooks)) { - descendantHooks = true; - } - } else if (!hasWidgets && isWidget(child)) { - if (typeof child.destroy === "function") { - hasWidgets = true; - } - } else if (!hasThunks && isThunk(child)) { - hasThunks = true; - } - } + if (Checks.is_array(pattern)) { + return Resolvers.resolveArray(pattern); + } - this.count = count + descendants; - this.hasWidgets = hasWidgets; - this.hasThunks = hasThunks; - this.hooks = hooks; - this.descendantHooks = descendantHooks; - } + if (Checks.is_number(pattern)) { + return Resolvers.resolveNumber(pattern); + } - VirtualNode.prototype.version = version; - VirtualNode.prototype.type = "VirtualNode"; - }, { "./is-thunk": 25, "./is-vhook": 26, "./is-vnode": 27, "./is-widget": 29, "./version": 30 }], 32: [function (require, module, exports) { - var version = require("./version"); + if (Checks.is_string(pattern)) { + return Resolvers.resolveString(pattern); + } - VirtualPatch.NONE = 0; - VirtualPatch.VTEXT = 1; - VirtualPatch.VNODE = 2; - VirtualPatch.WIDGET = 3; - VirtualPatch.PROPS = 4; - VirtualPatch.ORDER = 5; - VirtualPatch.INSERT = 6; - VirtualPatch.REMOVE = 7; - VirtualPatch.THUNK = 8; + if (Checks.is_boolean(pattern)) { + return Resolvers.resolveBoolean(pattern); + } - module.exports = VirtualPatch; + if (Checks.is_symbol(pattern)) { + return Resolvers.resolveSymbol(pattern); + } - function VirtualPatch(type, vNode, patch) { - this.type = Number(type); - this.vNode = vNode; - this.patch = patch; - } + if (Checks.is_null(pattern)) { + return Resolvers.resolveNull(pattern); + } - VirtualPatch.prototype.version = version; - VirtualPatch.prototype.type = "VirtualPatch"; - }, { "./version": 30 }], 33: [function (require, module, exports) { - var version = require("./version"); + if (Checks.is_object(pattern)) { + return Resolvers.resolveObject(pattern); + } - module.exports = VirtualText; + return Resolvers.resolveNoMatch(); +} - function VirtualText(text) { - this.text = String(text); - } +class MatchError extends Error { + constructor(arg) { + super(); - VirtualText.prototype.version = version; - VirtualText.prototype.type = "VirtualText"; - }, { "./version": 30 }], 34: [function (require, module, exports) { - var isObject = require("is-object"); - var isHook = require("../vnode/is-vhook"); + if (typeof arg === 'symbol') { + this.message = 'No match for: ' + arg.toString(); + } else if (Array.isArray(arg)) { + let mappedValues = arg.map(x => x.toString()); + this.message = 'No match for: ' + mappedValues; + } else { + this.message = 'No match for: ' + arg; + } - module.exports = diffProps; + this.stack = new Error().stack; + this.name = this.constructor.name; + } +} - function diffProps(a, b) { - var diff; +class Case { - for (var aKey in a) { - if (!(aKey in b)) { - diff = diff || {}; - diff[aKey] = undefined; - } + constructor(pattern, fn, guard = () => true) { + this.pattern = buildMatch(pattern); + this.fn = fn; + this.guard = guard; + } +} - var aValue = a[aKey]; - var bValue = b[aKey]; +function make_case(pattern, fn, guard = () => true) { + return new Case(pattern, fn, guard); +} - if (aValue === bValue) { - continue; - } else if (isObject(aValue) && isObject(bValue)) { - if (getPrototype(bValue) !== getPrototype(aValue)) { - diff = diff || {}; - diff[aKey] = bValue; - } else if (isHook(bValue)) { - diff = diff || {}; - diff[aKey] = bValue; - } else { - var objectDiff = diffProps(aValue, bValue); - if (objectDiff) { - diff = diff || {}; - diff[aKey] = objectDiff; - } - } - } else { - diff = diff || {}; - diff[aKey] = bValue; - } - } +function defmatch(...cases) { + return function (...args) { + for (let processedCase of cases) { + let result = []; + if (processedCase.pattern(args, result) && processedCase.guard.apply(this, result)) { + return processedCase.fn.apply(this, result); + } + } - for (var bKey in b) { - if (!(bKey in a)) { - diff = diff || {}; - diff[bKey] = b[bKey]; - } - } + throw new MatchError(args); + }; +} - return diff; - } +function match(pattern, expr, guard = () => true) { + let result = []; + let processedPattern = buildMatch(pattern); + if (processedPattern(expr, result) && guard.apply(this, result)) { + return result; + } else { + throw new MatchError(expr); + } +} - function getPrototype(value) { - if (Object.getPrototypeOf) { - return Object.getPrototypeOf(value); - } else if (value.__proto__) { - return value.__proto__; - } else if (value.constructor) { - return value.constructor.prototype; - } - } - }, { "../vnode/is-vhook": 26, "is-object": 11 }], 35: [function (require, module, exports) { - var isArray = require("x-is-array"); +function match_no_throw(pattern, expr, guard = () => true) { + try { + return match(pattern, expr, guard); + } catch (e) { + if (e instanceof MatchError || e.message.startsWith('No match for:')) { + return null; + } - var VPatch = require("../vnode/vpatch"); - var isVNode = require("../vnode/is-vnode"); - var isVText = require("../vnode/is-vtext"); - var isWidget = require("../vnode/is-widget"); - var isThunk = require("../vnode/is-thunk"); - var handleThunk = require("../vnode/handle-thunk"); + throw e; + } +} - var diffProps = require("./diff-props"); +var Patterns = { + defmatch, match, MatchError, match_no_throw, + variable, wildcard, startsWith, + capture, headTail, type, bound, Case, make_case +}; - module.exports = diff; +//https://github.com/airportyh/protomorphism +class Protocol { + constructor(spec) { + this.registry = new Map(); + this.fallback = null; - function diff(a, b) { - var patch = { a: a }; - walk(a, b, patch, 0); - return patch; - } + for (let funName in spec) { + this[funName] = createFun(funName).bind(this); + } - function walk(a, b, patch, index) { - if (a === b) { - return; - } + function createFun(funName) { - var apply = patch[index]; - var applyClear = false; + return function (...args) { + let thing = args[0]; + let fun = null; - if (isThunk(a) || isThunk(b)) { - thunks(a, b, patch, index); - } else if (b == null) { + if (Number.isInteger(thing) && this.hasImplementation(Integer)) { + fun = this.registry.get(Integer)[funName]; + } else if (typeof thing === "number" && !Number.isInteger(thing) && this.hasImplementation(Float)) { + fun = this.registry.get(Float)[funName]; + } else if (this.hasImplementation(thing)) { + fun = this.registry.get(thing.constructor)[funName]; + } else if (this.fallback) { + fun = this.fallback[funName]; + } - // If a is a widget we will add a remove patch for it - // Otherwise any child widgets/hooks must be destroyed. - // This prevents adding two remove patches for a widget. - if (!isWidget(a)) { - clearState(a, patch, index); - apply = patch[index]; - } + if (fun != null) { + let retval = fun.apply(this, args); + return retval; + } - apply = appendPatch(apply, new VPatch(VPatch.REMOVE, a, b)); - } else if (isVNode(b)) { - if (isVNode(a)) { - if (a.tagName === b.tagName && a.namespace === b.namespace && a.key === b.key) { - var propsPatch = diffProps(a.properties, b.properties); - if (propsPatch) { - apply = appendPatch(apply, new VPatch(VPatch.PROPS, a, propsPatch)); - } - apply = diffChildren(a, b, patch, apply, index); - } else { - apply = appendPatch(apply, new VPatch(VPatch.VNODE, a, b)); - applyClear = true; - } - } else { - apply = appendPatch(apply, new VPatch(VPatch.VNODE, a, b)); - applyClear = true; - } - } else if (isVText(b)) { - if (!isVText(a)) { - apply = appendPatch(apply, new VPatch(VPatch.VTEXT, a, b)); - applyClear = true; - } else if (a.text !== b.text) { - apply = appendPatch(apply, new VPatch(VPatch.VTEXT, a, b)); - } - } else if (isWidget(b)) { - if (!isWidget(a)) { - applyClear = true; - } + throw new Error("No implementation found for " + thing); + }; + } + } - apply = appendPatch(apply, new VPatch(VPatch.WIDGET, a, b)); - } + implementation(type, implementation) { + if (type === null) { + this.fallback = implementation; + } else { + this.registry.set(type, implementation); + } + } - if (apply) { - patch[index] = apply; - } + hasImplementation(thing) { + if (thing === Integer || thing === Float) { + return this.registry.has(thing); + } - if (applyClear) { - clearState(a, patch, index); - } - } + return this.registry.has(thing.constructor); + } +} - function diffChildren(a, b, patch, apply, index) { - var aChildren = a.children; - var orderedSet = reorder(aChildren, b.children); - var bChildren = orderedSet.children; +function call_property(item, property) { + let prop = null; - var aLen = aChildren.length; - var bLen = bChildren.length; - var len = aLen > bLen ? aLen : bLen; + if (typeof item === "number" || typeof item === "symbol" || typeof item === "boolean" || typeof item === "string") { + if (item[property] !== undefined) { + prop = property; + } else if (item[Symbol.for(property)] !== undefined) { + prop = Symbol.for(property); + } + } else { + if (property in item) { + prop = property; + } else if (Symbol.for(property) in item) { + prop = Symbol.for(property); + } + } - for (var i = 0; i < len; i++) { - var leftNode = aChildren[i]; - var rightNode = bChildren[i]; - index += 1; + if (prop === null) { + throw new Error(`Property ${ property } not found in ${ item }`); + } - if (!leftNode) { - if (rightNode) { - // Excess nodes in b need to be added - apply = appendPatch(apply, new VPatch(VPatch.INSERT, null, rightNode)); - } - } else { - walk(leftNode, rightNode, patch, index); - } + if (item[prop] instanceof Function) { + return item[prop](); + } else { + return item[prop]; + } +} - if (isVNode(leftNode) && leftNode.count) { - index += leftNode.count; - } - } +function apply(...args) { + if (args.length === 2) { + args[0].apply(null, args.slice(1)); + } else { + args[0][args[1]].apply(null, args.slice(2)); + } +} - if (orderedSet.moves) { - // Reorder nodes last - apply = appendPatch(apply, new VPatch(VPatch.ORDER, a, orderedSet.moves)); - } +function contains(left, right) { + for (let x of right) { + if (Patterns.match_no_throw(left, x) != null) { + return true; + } + } - return apply; - } + return false; +} - function clearState(vNode, patch, index) { - // TODO: Make this a single walk, not two - unhook(vNode, patch, index); - destroyWidgets(vNode, patch, index); - } +function get_global() { + if (typeof self !== "undefined") { + return self; + } else if (typeof window !== "undefined") { + return window; + } else if (typeof global !== "undefined") { + return global; + } - // Patch records for all destroyed widgets must be added because we need - // a DOM node reference for the destroy function - function destroyWidgets(vNode, patch, index) { - if (isWidget(vNode)) { - if (typeof vNode.destroy === "function") { - patch[index] = appendPatch(patch[index], new VPatch(VPatch.REMOVE, vNode, null)); - } - } else if (isVNode(vNode) && (vNode.hasWidgets || vNode.hasThunks)) { - var children = vNode.children; - var len = children.length; - for (var i = 0; i < len; i++) { - var child = children[i]; - index += 1; + throw new Error("No global state found"); +} - destroyWidgets(child, patch, index); +function defstruct(defaults) { + return class { + constructor(update = {}) { + let the_values = Object.assign(defaults, update); + Object.assign(this, the_values); + } - if (isVNode(child) && child.count) { - index += child.count; - } - } - } else if (isThunk(vNode)) { - thunks(vNode, null, patch, index); - } - } + static create(updates = {}) { + let x = new this(updates); + return Object.freeze(x); + } + }; +} - // Create a sub-patch for thunks - function thunks(a, b, patch, index) { - var nodes = handleThunk(a, b); - var thunkPatch = diff(nodes.a, nodes.b); - if (hasPatches(thunkPatch)) { - patch[index] = new VPatch(VPatch.THUNK, null, thunkPatch); - } - } +function defexception(defaults) { + return class extends Error { + constructor(update = {}) { + let message = update.message || ""; + super(message); - function hasPatches(patch) { - for (var index in patch) { - if (index !== "a") { - return true; - } - } + let the_values = Object.assign(defaults, update); + Object.assign(this, the_values); - return false; - } + this.name = this.constructor.name; + this.message = message; + this[SpecialForms.atom("__exception__")] = true; + Error.captureStackTrace(this, this.constructor.name); + } - // Execute hooks when two nodes are identical - function unhook(vNode, patch, index) { - if (isVNode(vNode)) { - if (vNode.hooks) { - patch[index] = appendPatch(patch[index], new VPatch(VPatch.PROPS, vNode, undefinedKeys(vNode.hooks))); - } + static create(updates = {}) { + let x = new this(updates); + return Object.freeze(x); + } + }; +} - if (vNode.descendantHooks || vNode.hasThunks) { - var children = vNode.children; - var len = children.length; - for (var i = 0; i < len; i++) { - var child = children[i]; - index += 1; +function defprotocol(spec) { + return new Protocol(spec); +} - unhook(child, patch, index); +function defimpl(protocol, type, impl) { + protocol.implementation(type, impl); +} - if (isVNode(child) && child.count) { - index += child.count; - } - } - } - } else if (isThunk(vNode)) { - thunks(vNode, null, patch, index); - } - } +function get_object_keys(obj) { + return Object.keys(obj).concat(Object.getOwnPropertySymbols(obj)); +} - function undefinedKeys(obj) { - var result = {}; +function is_valid_character(codepoint) { + try { + return String.fromCodePoint(codepoint) != null; + } catch (e) { + return false; + } +} - for (var key in obj) { - result[key] = undefined; - } +//https://developer.mozilla.org/en-US/docs/Web/API/WindowBase64/Base64_encoding_and_decoding#Solution_2_%E2%80%93_rewrite_the_DOMs_atob()_and_btoa()_using_JavaScript's_TypedArrays_and_UTF-8 +function b64EncodeUnicode(str) { + return btoa(encodeURIComponent(str).replace(/%([0-9A-F]{2})/g, function (match, p1) { + return String.fromCharCode('0x' + p1); + })); +} - return result; - } +function delete_property_from_map(map, property) { + let new_map = Object.assign(Object.create(map.constructor.prototype), map); + delete new_map[property]; - // List diff, naive left to right reordering - function reorder(aChildren, bChildren) { - // O(M) time, O(M) memory - var bChildIndex = keyIndex(bChildren); - var bKeys = bChildIndex.keys; - var bFree = bChildIndex.free; + return Object.freeze(new_map); +} - if (bFree.length === bChildren.length) { - return { - children: bChildren, - moves: null - }; - } +function class_to_obj(map) { + let new_map = Object.assign({}, map); + return Object.freeze(new_map); +} - // O(N) time, O(N) memory - var aChildIndex = keyIndex(aChildren); - var aKeys = aChildIndex.keys; - var aFree = aChildIndex.free; +function add_property_to_map(map, property, value) { + let new_map = Object.assign({}, map); + new_map[property] = value; + return Object.freeze(new_map); +} - if (aFree.length === aChildren.length) { - return { - children: bChildren, - moves: null - }; - } +function update_map(map, property, value) { + if (property in get_object_keys(map)) { + return add_property_to_map(map, property, value); + } - // O(MAX(N, M)) memory - var newChildren = []; + throw "map does not have key"; +} - var freeIndex = 0; - var freeCount = bFree.length; - var deletedItems = 0; +function bnot(expr) { + return ~expr; +} - // Iterate through a and match a node in b - // O(N) time, - for (var i = 0; i < aChildren.length; i++) { - var aItem = aChildren[i]; - var itemIndex; +function band(left, right) { + return left & right; +} - if (aItem.key) { - if (bKeys.hasOwnProperty(aItem.key)) { - // Match up the old keys - itemIndex = bKeys[aItem.key]; - newChildren.push(bChildren[itemIndex]); - } else { - // Remove old keyed items - itemIndex = i - deletedItems++; - newChildren.push(null); - } - } else { - // Match the item in a with the next free item in b - if (freeIndex < freeCount) { - itemIndex = bFree[freeIndex++]; - newChildren.push(bChildren[itemIndex]); - } else { - // There are no free items in b to match with - // the free items in a, so the extra free nodes - // are deleted. - itemIndex = i - deletedItems++; - newChildren.push(null); - } - } - } +function bor(left, right) { + return left | right; +} - var lastFreeIndex = freeIndex >= bFree.length ? bChildren.length : bFree[freeIndex]; +function bsl(left, right) { + return left << right; +} - // Iterate through b and append any new keys - // O(M) time - for (var j = 0; j < bChildren.length; j++) { - var newItem = bChildren[j]; +function bsr(left, right) { + return left >> right; +} - if (newItem.key) { - if (!aKeys.hasOwnProperty(newItem.key)) { - // Add any new keyed items - // We are adding new items to the end and then sorting them - // in place. In future we should insert new items in place. - newChildren.push(newItem); - } - } else if (j >= lastFreeIndex) { - // Add any leftover non-keyed items - newChildren.push(newItem); - } - } +function bxor(left, right) { + return left ^ right; +} - var simulate = newChildren.slice(); - var simulateIndex = 0; - var removes = []; - var inserts = []; - var simulateItem; +function zip(list_of_lists) { + if (list_of_lists.length === 0) { + return Object.freeze([]); + } - for (var k = 0; k < bChildren.length;) { - var wantedItem = bChildren[k]; - simulateItem = simulate[simulateIndex]; + let new_value = []; + let smallest_length = list_of_lists[0]; - // remove items - while (simulateItem === null && simulate.length) { - removes.push(remove(simulate, simulateIndex, null)); - simulateItem = simulate[simulateIndex]; - } + for (let x of list_of_lists) { + if (x.length < smallest_length) { + smallest_length = x.length; + } + } - if (!simulateItem || simulateItem.key !== wantedItem.key) { - // if we need a key in this position... - if (wantedItem.key) { - if (simulateItem && simulateItem.key) { - // if an insert doesn't put this key in place, it needs to move - if (bKeys[simulateItem.key] !== k + 1) { - removes.push(remove(simulate, simulateIndex, simulateItem.key)); - simulateItem = simulate[simulateIndex]; - // if the remove didn't put the wanted item in place, we need to insert it - if (!simulateItem || simulateItem.key !== wantedItem.key) { - inserts.push({ key: wantedItem.key, to: k }); - } - // items are matching, so skip ahead - else { - simulateIndex++; - } - } else { - inserts.push({ key: wantedItem.key, to: k }); - } - } else { - inserts.push({ key: wantedItem.key, to: k }); - } - k++; - } - // a key in simulate has no matching wanted key, remove it - else if (simulateItem && simulateItem.key) { - removes.push(remove(simulate, simulateIndex, simulateItem.key)); - } - } else { - simulateIndex++; - k++; - } - } + for (let i = 0; i < smallest_length; i++) { + let current_value = []; + for (let j = 0; j < list_of_lists.length; j++) { + current_value.push(list_of_lists[j][i]); + } - // remove all the remaining nodes from simulate - while (simulateIndex < simulate.length) { - simulateItem = simulate[simulateIndex]; - removes.push(remove(simulate, simulateIndex, simulateItem && simulateItem.key)); - } + new_value.push(new Tuple(...current_value)); + } - // If the only moves we have are deletes then we can just - // let the delete patch remove these items. - if (removes.length === deletedItems && !inserts.length) { - return { - children: newChildren, - moves: null - }; - } + return Object.freeze(new_value); +} - return { - children: newChildren, - moves: { - removes: removes, - inserts: inserts - } - }; - } +function can_decode64(data) { + try { + atob(data); + return true; + } catch (e) { + return false; + } +} + +function remove_from_list(list, element) { + let found = false; + + return list.filter(elem => { + if (!found && elem === element) { + found = true; + return false; + } - function remove(arr, index, key) { - arr.splice(index, 1); + return true; + }); +} - return { - from: index, - key: key - }; - } +function foldl(fun, acc, list) { + let acc1 = acc; - function keyIndex(children) { - var keys = {}; - var free = []; - var length = children.length; + for (const el of list) { + acc1 = fun(el, acc1); + } - for (var i = 0; i < length; i++) { - var child = children[i]; + return acc1; +} - if (child.key) { - keys[child.key] = i; - } else { - free.push(i); - } - } +function foldr(fun, acc, list) { + let acc1 = acc; - return { - keys: keys, // A hash of key name to index - free: free // An array of unkeyed item indices - }; - } + for (let i = list.length - 1; i >= 0; i--) { + acc1 = fun(list[i], acc1); + } - function appendPatch(apply, patch) { - if (apply) { - if (isArray(apply)) { - apply.push(patch); - } else { - apply = [apply, patch]; - } + return acc1; +} - return apply; - } else { - return patch; - } - } - }, { "../vnode/handle-thunk": 24, "../vnode/is-thunk": 25, "../vnode/is-vnode": 27, "../vnode/is-vtext": 28, "../vnode/is-widget": 29, "../vnode/vpatch": 32, "./diff-props": 34, "x-is-array": 12 }] }, {}, [4])(4); -}); +function keyfind(key, n, tuplelist) { -/* @flow */ + for (let i = tuplelist.length - 1; i >= 0; i--) { + if (tuplelist[i].get(n) === key) { + return tuplelist[i]; + } + } -class Mailbox { + return false; +} - constructor() { - this.messages = []; - } +function keydelete(key, n, tuplelist) { - deliver(message) { - this.messages.push(message); - return message; + for (let i = tuplelist.length - 1; i >= 0; i--) { + if (tuplelist[i].get(n) === key) { + return tuplelist.concat([]).splice(i, 1); + } } - get() { - return this.messages; - } + return tuplelist; +} - isEmpty() { - return this.messages.length === 0; +function keystore(key, n, list, newtuple) { + for (let i = list.length - 1; i >= 0; i--) { + if (list[i].get(n) === key) { + return list.concat([]).splice(i, 1, newtuple); + } } - removeAt(index) { - this.messages.splice(index, 1); - } + return list.concat([]).push(newtuple); } -var States = { - NORMAL: Symbol.for("normal"), - KILL: Symbol.for("kill"), - SUSPEND: Symbol.for("suspend"), - CONTINUE: Symbol.for("continue"), - RECEIVE: Symbol.for("receive"), - SEND: Symbol.for("send"), - SLEEPING: Symbol.for("sleeping"), - RUNNING: Symbol.for("running"), - SUSPENDED: Symbol.for("suspended"), - STOPPED: Symbol.for("stopped"), - SLEEP: Symbol.for("sleep"), - EXIT: Symbol.for("exit"), - NOMATCH: Symbol.for("no_match") -}; +function keymember(key, n, list) { + for (let i = list.length - 1; i >= 0; i--) { + if (list[i].get(n) === key) { + return true; + } + } -class Process { + return false; +} - constructor(pid, mailbox) { - this.pid = pid; - this.mailbox = mailbox; - this.status = States.STOPPED; - this.dict = {}; +function keytake(key, n, list) { + if (!keymember(key, n, list)) { + return false; } + + let tuple = keyfind(key, n, list); + + return new Tuple(tuple.get(n), tuple, keydelete(key, n, list)); } -class Tuple { +function keyreplace(key, n, list, newtuple) { - constructor(...args) { - this.values = Object.freeze(args); - this.length = this.values.length; + for (let i = tuplelist.length - 1; i >= 0; i--) { + if (tuplelist[i].get(n) === key) { + return tuplelist.concat([]).splice(i, 1, newtuple); + } } - get(index) { - return this.values[index]; + return tuplelist; +} + +function reverse(list) { + return list.concat([]).reverse(); +} + +function maps_find(key, map) { + if (key in get_object_keys(map)) { + return new Tuple(Symbol.for("ok"), map[key]); + } else { + return Symbol.for("error"); } +} - count() { - return this.values.length; +function flatten(list, tail = []) { + let new_list = []; + + for (let e of list) { + if (isArray(e)) { + new_list = new_list.concat(flatten(e)); + } else { + new_list.push(e); + } } - [Symbol.iterator]() { - return this.values[Symbol.iterator](); + return Object.freeze(new_list.concat(tail)); +} + +function duplicate(n, elem) { + let list = []; + + for (let i = 0; i < n; i++) { + list.push(elem); } - toString() { - var i, - s = ""; - for (i = 0; i < this.values.length; i++) { - if (s !== "") { - s += ", "; - } - s += this.values[i].toString(); - } + return Object.freeze(list); +} - return "{" + s + "}"; +function mapfoldl(fun, acc, list) { + let newlist = []; + + for (let x of list) { + let tup = fun(x, acc); + newlist.push(tup.get(0)); + acc = tup.get(1); } - put_elem(index, elem) { - if (index === this.length) { - let new_values = this.values.concat([elem]); - return new Tuple(...new_values); - } + return new Tuple(Object.freeze(newlist), acc); +} - let new_values = this.values.concat([]); - new_values.splice(index, 0, elem); - return new Tuple(...new_values); +function filtermap(fun, list) { + let newlist = []; + + for (x of list) { + let result = fun(x); + + if (result === true) { + newlist.push(x); + } else if (result instanceof Tuple) { + newlist.push(result.get(1)); + } } - remove_elem(index) { - let new_values = this.values.concat([]); - new_values.splice(index, 1); - return new Tuple(...new_values); + return Object.freeze(newlist); +} + +function maps_fold(fun, acc, map) { + let acc1 = acc; + + for (let k of get_object_keys(map)) { + acc1 = fun(k, map[k], acc1); } + return acc1; +} + +var Functions = { + call_property, + apply, + contains, + get_global, + defstruct, + defexception, + defprotocol, + defimpl, + get_object_keys, + is_valid_character, + b64EncodeUnicode, + delete_property_from_map, + add_property_to_map, + class_to_obj, + can_decode64, + bnot, + band, + bor, + bsl, + bsr, + bxor, + zip, + foldl, + foldr, + remove_from_list, + keydelete, + keystore, + keyfind, + keytake, + keyreplace, + reverse, + update_map, + maps_find, + flatten, + duplicate, + mapfoldl, + filtermap, + maps_fold +}; + +function _case(condition, clauses) { + return Patterns.defmatch(...clauses)(condition); } -let process_counter = -1; - -class PID { - constructor() { - process_counter = process_counter + 1; - this.id = process_counter; +function cond(clauses) { + for (let clause of clauses) { + if (clause[0]) { + return clause[1](); + } } - toString() { - return "PID#<0." + this.id + ".0>"; - } + throw new Error(); } -class Integer {} -class Float {} - -class ProcessSystem { - - constructor() { - this.pids = new Map(); - this.mailboxes = new Map(); - this.names = new Map(); - this.links = new Map(); - - this.current_process = null; - this.suspended = new Map(); - - this.main_process_pid = this.spawn(); - this.set_current(this.main_process_pid); - } - - spawn() { - return this.add_proc(false).pid; - } +function map_update(map, values) { + return Object.freeze(Object.assign(Object.create(map.constructor.prototype), map, values)); +} - spawn_link() { - return this.add_proc(true).pid; - } +function _for(collections, fun, filter = () => true, into = [], previousValues = []) { + let pattern = collections[0][0]; + let collection = collections[0][1]; - link(pid) { - this.links.get(this.pid()).add(pid); - this.links.get(pid).add(this.pid()); - } + if (collections.length === 1) { - unlink(pid) { - this.links.get(this.pid()).delete(pid); - this.links.get(pid).delete(this.pid()); - } + for (let elem of collection) { + let r = Patterns.match_no_throw(pattern, elem); + let args = previousValues.concat(r); - set_current(id) { - let pid = this.pidof(id); - if (pid !== null) { - this.current_process = this.pids.get(pid); - this.current_process.status = States.RUNNING; + if (r && filter.apply(this, args)) { + into = into.concat([fun.apply(this, args)]); + } } - } - - add_proc(linked) { - let newpid = new PID(); - let mailbox = new Mailbox(); - let newproc = new Process(newpid, mailbox); - this.pids.set(newpid, newproc); - this.mailboxes.set(newpid, mailbox); - this.links.set(newpid, new Set()); + return into; + } else { + let _into = []; - if (linked) { - this.link(newpid); + for (let elem of collection) { + let r = Patterns.match_no_throw(pattern, elem); + if (r) { + _into = into.concat(this._for(collections.slice(1), fun, filter, _into, previousValues.concat(r))); + } } - return newproc; + return _into; } +} - remove_proc(pid) { - this.pids.delete(pid); - this.unregister(pid); +function _try(do_fun, rescue_function, catch_fun, else_function, after_function) { + let result = null; - if (this.links.has(pid)) { - for (let linkpid of this.links.get(pid)) { - this.links.get(linkpid).delete(pid); - } + try { + result = do_fun(); + } catch (e) { + let ex_result = null; - this.links.delete(pid); + if (rescue_function) { + try { + ex_result = rescue_function(e); + return ex_result; + } catch (ex) { + if (ex instanceof Patterns.MatchError) { + throw ex; + } + } } - } - - exit(id) { - let pid = this.pidof(id); - this.remove_proc(id); - } - register(name, pid) { - if (!this.names.has(name)) { - this.names.set(name, pid); - return name; - } else { - throw new Error("Name is already registered to another process"); + if (catch_fun) { + try { + ex_result = catch_fun(e); + return ex_result; + } catch (ex) { + if (ex instanceof Patterns.MatchError) { + throw ex; + } + } } - } - registered(name) { - return this.names.has(name) ? this.names.get(name) : null; + throw e; + } finally { + if (after_function) { + after_function(); + } } - unregister(pid) { - for (let name of this.names.keys()) { - if (this.names.has(name) && this.names.get(name) === pid) { - this.names.delete(name); + if (else_function) { + try { + return else_function(result); + } catch (ex) { + if (ex instanceof Patterns.MatchError) { + throw new Error("No Match Found in Else"); } + + throw ex; } + } else { + return result; } +} - pid() { - return this.current_process.pid; - } +var SpecialForms$1 = { + _case, + cond, + map_update, + _for, + _try +}; - pidof(id) { - if (id instanceof PID) { - return this.pids.has(id) ? id : null; - } else if (id instanceof Process) { - return id.pid; - } else { - let pid = this.registered(id); - if (pid === null) throw "Process name not registered: " + id + " (" + typeof id + ")"; - return pid; - } - } +Functions.get_global().processes = Functions.get_global().processes || new ProcessSystem(); - put(id, key, value) { - let pid = this.pidof(id); - let process = this.pids.get(pid); - process.dict[key] = value; - } +var Core = { + ProcessSystem, + Tuple, + PID, + BitString, + Patterns, + Integer, + Float, + Functions, + SpecialForms: SpecialForms$1 +}; - get(id, key) { - let pid = this.pidof(id); - let process = this.pids.get(pid); +let Enum = { - if (key != null) { - return process.dict[key]; - } else { - return process.dict; + all__qmark__: function (collection, fun = x => x) { + for (let elem of collection) { + if (!fun(elem)) { + return false; + } } - } - get_keys(id) { - let pid = this.pidof(id); - let process = this.pids.get(pid); + return true; + }, - return Object.keys(process.dict); - } + any__qmark__: function (collection, fun = x => x) { + for (let elem of collection) { + if (fun(elem)) { + return true; + } + } - erase(id, key) { - let pid = this.pidof(id); - let process = this.pids.get(pid); + return false; + }, - if (key != null) { - delete process.dict[key]; - } else { - process.dict = {}; + at: function (collection, n, the_default = null) { + if (n > this.count(collection) || n < 0) { + return the_default; } - } -} - -class BitString { - constructor(...args) { - this.raw_value = function () { - return Object.freeze(args); - }; - this.value = Object.freeze(this.process(args)); - this.length = this.value.length; - this.bit_size = this.raw_value().reduce((prev, current) => prev + current.size); - this.byte_size = this.bit_size / 8 + (this.bit_size % 8 > 0 ? 1 : 0); - } + return collection[n]; + }, - get(index) { - return this.value[index]; - } + concat: function (...enumables) { + return enumables[0].concat(enumables[1]); + }, - count() { - return this.value.length; - } + count: function (collection, fun = null) { + if (fun == null) { + return collection.length; + } else { + return collection.filter(fun).length; + } + }, - [Symbol.iterator]() { - return this.value[Symbol.iterator](); - } + drop: function (collection, count) { + return collection.slice(count); + }, - toString() { - var i, - s = ""; - for (i = 0; i < this.count(); i++) { - if (s !== "") { - s += ", "; + drop_while: function (collection, fun) { + let count = 0; + + for (let elem of collection) { + if (fun(elem)) { + count = count + 1; + } else { + break; } - s += this[i].toString(); } - return "<<" + s + ">>"; - } + return collection.slice(count); + }, - process() { - let processed_values = []; + each: function (collection, fun) { + for (let elem of collection) { + fun(elem); + } + }, - var i; - for (i = 0; i < this.raw_value().length; i++) { - let processed_value = this["process_" + this.raw_value()[i].type](this.raw_value()[i]); + empty__qmark__: function (collection) { + return collection.length === 0; + }, - for (let attr of this.raw_value()[i].attributes) { - processed_value = this["process_" + attr](processed_value); + fetch: function (collection, n) { + if (Array.isArray(collection)) { + if (n < this.count(collection) && n >= 0) { + return new Core.Tuple(Symbol.for("ok"), collection[n]); + } else { + return Symbol.for("error"); } - - processed_values = processed_values.concat(processed_value); } - return processed_values; - } - - process_integer(value) { - return value.value; - } + throw new Error("collection is not an Enumerable"); + }, - process_float(value) { - if (value.size === 64) { - return BitString.float64ToBytes(value.value); - } else if (value.size === 32) { - return BitString.float32ToBytes(value.value); + fetch__emark__: function (collection, n) { + if (Array.isArray(collection)) { + if (n < this.count(collection) && n >= 0) { + return collection[n]; + } else { + throw new Error("out of bounds error"); + } } - throw new Error("Invalid size for float"); - } - - process_bitstring(value) { - return value.value.value; - } + throw new Error("collection is not an Enumerable"); + }, - process_binary(value) { - return BitString.toUTF8Array(value.value); - } + filter: function (collection, fun) { + let result = []; - process_utf8(value) { - return BitString.toUTF8Array(value.value); - } + for (let elem of collection) { + if (fun(elem)) { + result.push(elem); + } + } - process_utf16(value) { - return BitString.toUTF16Array(value.value); - } + return result; + }, - process_utf32(value) { - return BitString.toUTF32Array(value.value); - } + filter_map: function (collection, filter, mapper) { + return Enum.map(Enum.filter(collection, filter), mapper); + }, - process_signed(value) { - return new Uint8Array([value])[0]; - } + find: function (collection, if_none = null, fun) { + for (let elem of collection) { + if (fun(elem)) { + return elem; + } + } - process_unsigned(value) { - return value; - } + return if_none; + }, - process_native(value) { - return value; - } + into: function (collection, list) { + return list.concat(collection); + }, - process_big(value) { - return value; - } + map: function (collection, fun) { + let result = []; - process_little(value) { - return value.reverse(); - } + for (let elem of collection) { + result.push(fun(elem)); + } - process_size(value) { - return value; - } + return result; + }, - process_unit(value) { - return value; - } + map_reduce: function (collection, acc, fun) { + let mapped = Object.freeze([]); + let the_acc = acc; - static integer(value) { - return BitString.wrap(value, { "type": "integer", "unit": 1, "size": 8 }); - } + for (var i = 0; i < this.count(collection); i++) { + let tuple = fun(collection[i], the_acc); - static float(value) { - return BitString.wrap(value, { "type": "float", "unit": 1, "size": 64 }); - } + the_acc = tuple.get(1); + mapped = Object.freeze(mapped.concat([tuple.get(0)])); + } - static bitstring(value) { - return BitString.wrap(value, { "type": "bitstring", "unit": 1, "size": value.bit_size }); - } + return new Core.Tuple(mapped, the_acc); + }, - static bits(value) { - return BitString.bitstring(value); - } + member__qmark__: function (collection, value) { + return collection.includes(value); + }, - static binary(value) { - return BitString.wrap(value, { "type": "binary", "unit": 8, "size": value.length }); - } + reduce: function (collection, acc, fun) { + let the_acc = acc; - static bytes(value) { - return BitString.binary(value); - } + for (var i = 0; i < this.count(collection); i++) { + let tuple = fun(collection[i], the_acc); - static utf8(value) { - return BitString.wrap(value, { "type": "utf8" }); - } + the_acc = tuple.get(1); + } - static utf16(value) { - return BitString.wrap(value, { "type": "utf16" }); - } + return the_acc; + }, - static utf32(value) { - return BitString.wrap(value, { "type": "utf32" }); - } + take: function (collection, count) { + return collection.slice(0, count); + }, - static signed(value) { - return BitString.wrap(value, {}, "signed"); - } + take_every: function (collection, nth) { + let result = []; + let index = 0; - static unsigned(value) { - return BitString.wrap(value, {}, "unsigned"); - } + for (let elem of collection) { + if (index % nth === 0) { + result.push(elem); + } + } - static native(value) { - return BitString.wrap(value, {}, "native"); - } + return Object.freeze(result); + }, - static big(value) { - return BitString.wrap(value, {}, "big"); - } + take_while: function (collection, fun) { + let count = 0; - static little(value) { - return BitString.wrap(value, {}, "little"); - } + for (let elem of collection) { + if (fun(elem)) { + count = count + 1; + } else { + break; + } + } - static size(value, count) { - return BitString.wrap(value, { "size": count }); - } + return collection.slice(0, count); + }, - static unit(value, count) { - return BitString.wrap(value, { "unit": count }); + to_list: function (collection) { + return collection; } +}; - static wrap(value, opt, new_attribute = null) { - let the_value = value; +let VirtualDOM = function (e) { + return e(); +}(function () { + var define, module, exports; + return function e(t, n, r) { + function s(o, u) { + if (!n[o]) { + if (!t[o]) { + var a = typeof require == "function" && require; + if (!u && a) return a(o, !0); + if (i) return i(o, !0); + var f = new Error("Cannot find module '" + o + "'"); + throw f.code = "MODULE_NOT_FOUND", f; + } + var l = n[o] = { + exports: {} + }; + t[o][0].call(l.exports, function (e) { + var n = t[o][1][e]; + return s(n ? n : e); + }, l, l.exports, e, t, n, r); + } + return n[o].exports; + } + var i = typeof require == "function" && require; + for (var o = 0; o < r.length; o++) s(r[o]); + return s; + }({ + 1: [function (require, module, exports) { - if (!(value instanceof Object)) { - the_value = { "value": value, "attributes": [] }; - } + var createElement = require("./vdom/create-element.js"); - the_value = Object.assign(the_value, opt); + module.exports = createElement; + }, { "./vdom/create-element.js": 15 }], 2: [function (require, module, exports) { + var diff = require("./vtree/diff.js"); - if (new_attribute) { - the_value.attributes.push(new_attribute); - } + module.exports = diff; + }, { "./vtree/diff.js": 35 }], 3: [function (require, module, exports) { + var h = require("./virtual-hyperscript/index.js"); - return the_value; - } + module.exports = h; + }, { "./virtual-hyperscript/index.js": 22 }], 4: [function (require, module, exports) { + var diff = require("./diff.js"); + var patch = require("./patch.js"); + var h = require("./h.js"); + var create = require("./create-element.js"); + var VNode = require('./vnode/vnode.js'); + var VText = require('./vnode/vtext.js'); - static toUTF8Array(str) { - var utf8 = []; - for (var i = 0; i < str.length; i++) { - var charcode = str.charCodeAt(i); - if (charcode < 128) { - utf8.push(charcode); - } else if (charcode < 2048) { - utf8.push(192 | charcode >> 6, 128 | charcode & 63); - } else if (charcode < 55296 || charcode >= 57344) { - utf8.push(224 | charcode >> 12, 128 | charcode >> 6 & 63, 128 | charcode & 63); - } - // surrogate pair - else { - i++; - // UTF-16 encodes 0x10000-0x10FFFF by - // subtracting 0x10000 and splitting the - // 20 bits of 0x0-0xFFFFF into two halves - charcode = 65536 + ((charcode & 1023) << 10 | str.charCodeAt(i) & 1023); - utf8.push(240 | charcode >> 18, 128 | charcode >> 12 & 63, 128 | charcode >> 6 & 63, 128 | charcode & 63); - } - } - return utf8; - } + module.exports = { + diff: diff, + patch: patch, + h: h, + create: create, + VNode: VNode, + VText: VText + }; + }, { "./create-element.js": 1, "./diff.js": 2, "./h.js": 3, "./patch.js": 13, "./vnode/vnode.js": 31, "./vnode/vtext.js": 33 }], 5: [function (require, module, exports) { + /*! + * Cross-Browser Split 1.1.1 + * Copyright 2007-2012 Steven Levithan + * Available under the MIT License + * ECMAScript compliant, uniform cross-browser split method + */ - static toUTF16Array(str) { - var utf16 = []; - for (var i = 0; i < str.length; i++) { - var codePoint = str.codePointAt(i); + /** + * Splits a string into an array of strings using a regex or string separator. Matches of the + * separator are not included in the result array. However, if `separator` is a regex that contains + * capturing groups, backreferences are spliced into the result each time `separator` is matched. + * Fixes browser bugs compared to the native `String.prototype.split` and can be used reliably + * cross-browser. + * @param {String} str String to split. + * @param {RegExp|String} separator Regex or string to use for separating the string. + * @param {Number} [limit] Maximum number of items to include in the result array. + * @returns {Array} Array of substrings. + * @example + * + * // Basic use + * split('a b c d', ' '); + * // -> ['a', 'b', 'c', 'd'] + * + * // With limit + * split('a b c d', ' ', 2); + * // -> ['a', 'b'] + * + * // Backreferences in result array + * split('..word1 word2..', /([a-z]+)(\d+)/i); + * // -> ['..', 'word', '1', ' ', 'word', '2', '..'] + */ + module.exports = function split(undef) { - if (codePoint <= 255) { - utf16.push(0); - utf16.push(codePoint); - } else { - utf16.push(codePoint >> 8 & 255); - utf16.push(codePoint & 255); - } - } - return utf16; - } + var nativeSplit = String.prototype.split, + compliantExecNpcg = /()??/.exec("")[1] === undef, - static toUTF32Array(str) { - var utf32 = []; - for (var i = 0; i < str.length; i++) { - var codePoint = str.codePointAt(i); + // NPCG: nonparticipating capturing group + self; - if (codePoint <= 255) { - utf32.push(0); - utf32.push(0); - utf32.push(0); - utf32.push(codePoint); - } else { - utf32.push(0); - utf32.push(0); - utf32.push(codePoint >> 8 & 255); - utf32.push(codePoint & 255); - } - } - return utf32; - } + self = function (str, separator, limit) { + // If `separator` is not a regex, use `nativeSplit` + if (Object.prototype.toString.call(separator) !== "[object RegExp]") { + return nativeSplit.call(str, separator, limit); + } + var output = [], + flags = (separator.ignoreCase ? "i" : "") + (separator.multiline ? "m" : "") + (separator.extended ? "x" : "") + ( // Proposed for ES6 + separator.sticky ? "y" : ""), - //http://stackoverflow.com/questions/2003493/javascript-float-from-to-bits - static float32ToBytes(f) { - var bytes = []; + // Firefox 3+ + lastLastIndex = 0, - var buf = new ArrayBuffer(4); - new Float32Array(buf)[0] = f; + // Make `global` and avoid `lastIndex` issues by working with a copy + separator = new RegExp(separator.source, flags + "g"), + separator2, + match, + lastIndex, + lastLength; + str += ""; // Type-convert + if (!compliantExecNpcg) { + // Doesn't need flags gy, but they don't hurt + separator2 = new RegExp("^" + separator.source + "$(?!\\s)", flags); + } + /* Values for `limit`, per the spec: + * If undefined: 4294967295 // Math.pow(2, 32) - 1 + * If 0, Infinity, or NaN: 0 + * If positive number: limit = Math.floor(limit); if (limit > 4294967295) limit -= 4294967296; + * If negative number: 4294967296 - Math.floor(Math.abs(limit)) + * If other: Type-convert, then use the above rules + */ + limit = limit === undef ? -1 >>> 0 : // Math.pow(2, 32) - 1 + limit >>> 0; // ToUint32(limit) + while (match = separator.exec(str)) { + // `separator.lastIndex` is not reliable cross-browser + lastIndex = match.index + match[0].length; + if (lastIndex > lastLastIndex) { + output.push(str.slice(lastLastIndex, match.index)); + // Fix browsers whose `exec` methods don't consistently return `undefined` for + // nonparticipating capturing groups + if (!compliantExecNpcg && match.length > 1) { + match[0].replace(separator2, function () { + for (var i = 1; i < arguments.length - 2; i++) { + if (arguments[i] === undef) { + match[i] = undef; + } + } + }); + } + if (match.length > 1 && match.index < str.length) { + Array.prototype.push.apply(output, match.slice(1)); + } + lastLength = match[0].length; + lastLastIndex = lastIndex; + if (output.length >= limit) { + break; + } + } + if (separator.lastIndex === match.index) { + separator.lastIndex++; // Avoid an infinite loop + } + } + if (lastLastIndex === str.length) { + if (lastLength || !separator.test("")) { + output.push(""); + } + } else { + output.push(str.slice(lastLastIndex)); + } + return output.length > limit ? output.slice(0, limit) : output; + }; - let intVersion = new Uint32Array(buf)[0]; + return self; + }(); + }, {}], 6: [function (require, module, exports) {}, {}], 7: [function (require, module, exports) { + 'use strict'; - bytes.push(intVersion >> 24 & 255); - bytes.push(intVersion >> 16 & 255); - bytes.push(intVersion >> 8 & 255); - bytes.push(intVersion & 255); + var OneVersionConstraint = require('individual/one-version'); - return bytes; - } + var MY_VERSION = '7'; + OneVersionConstraint('ev-store', MY_VERSION); - static float64ToBytes(f) { - var bytes = []; + var hashKey = '__EV_STORE_KEY@' + MY_VERSION; - var buf = new ArrayBuffer(8); - new Float64Array(buf)[0] = f; + module.exports = EvStore; - var intVersion1 = new Uint32Array(buf)[0]; - var intVersion2 = new Uint32Array(buf)[1]; + function EvStore(elem) { + var hash = elem[hashKey]; - bytes.push(intVersion2 >> 24 & 255); - bytes.push(intVersion2 >> 16 & 255); - bytes.push(intVersion2 >> 8 & 255); - bytes.push(intVersion2 & 255); + if (!hash) { + hash = elem[hashKey] = {}; + } - bytes.push(intVersion1 >> 24 & 255); - bytes.push(intVersion1 >> 16 & 255); - bytes.push(intVersion1 >> 8 & 255); - bytes.push(intVersion1 & 255); + return hash; + } + }, { "individual/one-version": 9 }], 8: [function (require, module, exports) { + (function (global) { + 'use strict'; - return bytes; - } -} + /*global window, global*/ -/* @flow */ + var root = typeof window !== 'undefined' ? window : typeof global !== 'undefined' ? global : {}; -class Variable { + module.exports = Individual; - constructor(name = null) { - this.name = name; - } -} + function Individual(key, value) { + if (key in root) { + return root[key]; + } -class Wildcard { - constructor() {} -} + root[key] = value; -class StartsWith { + return value; + } + }).call(this, typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}); + }, {}], 9: [function (require, module, exports) { + 'use strict'; - constructor(prefix) { - this.prefix = prefix; - } -} + var Individual = require('./index.js'); -class Capture { + module.exports = OneVersion; - constructor(value) { - this.value = value; - } -} + function OneVersion(moduleName, version, defaultValue) { + var key = '__INDIVIDUAL_ONE_VERSION_' + moduleName; + var enforceKey = key + '_ENFORCE_SINGLETON'; -class HeadTail { + var versionValue = Individual(enforceKey, version); - constructor(head = null, tail = null) { - this.head = head; - this.tail = tail; - } -} + if (versionValue !== version) { + throw new Error('Can only have one copy of ' + moduleName + '.\n' + 'You already have version ' + versionValue + ' installed.\n' + 'This means you cannot install version ' + version); + } -class Type { + return Individual(key, defaultValue); + } + }, { "./index.js": 8 }], 10: [function (require, module, exports) { + (function (global) { + var topLevel = typeof global !== 'undefined' ? global : typeof window !== 'undefined' ? window : {}; + var minDoc = require('min-document'); - constructor(type, objPattern = {}) { - this.type = type; - this.objPattern = objPattern; - } -} + if (typeof document !== 'undefined') { + module.exports = document; + } else { + var doccy = topLevel['__GLOBAL_DOCUMENT_CACHE@4']; -class Bound { + if (!doccy) { + doccy = topLevel['__GLOBAL_DOCUMENT_CACHE@4'] = minDoc; + } - constructor(value) { - this.value = value; - } -} + module.exports = doccy; + } + }).call(this, typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}); + }, { "min-document": 6 }], 11: [function (require, module, exports) { + "use strict"; -function variable(name = null) { - return new Variable(name); -} + module.exports = function isObject(x) { + return typeof x === "object" && x !== null; + }; + }, {}], 12: [function (require, module, exports) { + var nativeIsArray = Array.isArray; + var toString = Object.prototype.toString; -function wildcard() { - return new Wildcard(); -} + module.exports = nativeIsArray || isArray; -function startsWith(prefix) { - return new StartsWith(prefix); -} + function isArray(obj) { + return toString.call(obj) === "[object Array]"; + } + }, {}], 13: [function (require, module, exports) { + var patch = require("./vdom/patch.js"); -function capture(value) { - return new Capture(value); -} + module.exports = patch; + }, { "./vdom/patch.js": 18 }], 14: [function (require, module, exports) { + var isObject = require("is-object"); + var isHook = require("../vnode/is-vhook.js"); -function headTail(head = null, tail = null) { - return new HeadTail(head, tail); -} + module.exports = applyProperties; -function type(type, objPattern = {}) { - return new Type(type, objPattern); -} + function applyProperties(node, props, previous) { + for (var propName in props) { + var propValue = props[propName]; -function bound(value) { - return new Bound(value); -} + if (propValue === undefined) { + removeProperty(node, propName, propValue, previous); + } else if (isHook(propValue)) { + removeProperty(node, propName, propValue, previous); + if (propValue.hook) { + propValue.hook(node, propName, previous ? previous[propName] : undefined); + } + } else { + if (isObject(propValue)) { + patchObject(node, props, previous, propName, propValue); + } else { + node[propName] = propValue; + } + } + } + } -function is_number(value) { - return typeof value === 'number'; -} + function removeProperty(node, propName, propValue, previous) { + if (previous) { + var previousValue = previous[propName]; -function is_string(value) { - return typeof value === 'string'; -} + if (!isHook(previousValue)) { + if (propName === "attributes") { + for (var attrName in previousValue) { + node.removeAttribute(attrName); + } + } else if (propName === "style") { + for (var i in previousValue) { + node.style[i] = ""; + } + } else if (typeof previousValue === "string") { + node[propName] = ""; + } else { + node[propName] = null; + } + } else if (previousValue.unhook) { + previousValue.unhook(node, propName, propValue); + } + } + } -function is_boolean(value) { - return typeof value === 'boolean'; -} + function patchObject(node, props, previous, propName, propValue) { + var previousValue = previous ? previous[propName] : undefined; -function is_symbol(value) { - return typeof value === 'symbol'; -} + // Set attributes + if (propName === "attributes") { + for (var attrName in propValue) { + var attrValue = propValue[attrName]; -function is_null(value) { - return value === null; -} + if (attrValue === undefined) { + node.removeAttribute(attrName); + } else { + node.setAttribute(attrName, attrValue); + } + } -function is_undefined(value) { - return typeof value === 'undefined'; -} + return; + } -function is_function(value) { - return Object.prototype.toString.call(value) == '[object Function]'; -} + if (previousValue && isObject(previousValue) && getPrototype(previousValue) !== getPrototype(propValue)) { + node[propName] = propValue; + return; + } -function is_variable(value) { - return value instanceof Variable; -} + if (!isObject(node[propName])) { + node[propName] = {}; + } -function is_wildcard(value) { - return value instanceof Wildcard; -} + var replacer = propName === "style" ? "" : undefined; -function is_headTail(value) { - return value instanceof HeadTail; -} + for (var k in propValue) { + var value = propValue[k]; + node[propName][k] = value === undefined ? replacer : value; + } + } -function is_capture(value) { - return value instanceof Capture; -} + function getPrototype(value) { + if (Object.getPrototypeOf) { + return Object.getPrototypeOf(value); + } else if (value.__proto__) { + return value.__proto__; + } else if (value.constructor) { + return value.constructor.prototype; + } + } + }, { "../vnode/is-vhook.js": 26, "is-object": 11 }], 15: [function (require, module, exports) { + var document = require("global/document"); -function is_type(value) { - return value instanceof Type; -} + var applyProperties = require("./apply-properties"); -function is_startsWith(value) { - return value instanceof StartsWith; -} + var isVNode = require("../vnode/is-vnode.js"); + var isVText = require("../vnode/is-vtext.js"); + var isWidget = require("../vnode/is-widget.js"); + var handleThunk = require("../vnode/handle-thunk.js"); -function is_bound(value) { - return value instanceof Bound; -} + module.exports = createElement; -function is_object(value) { - return typeof value === 'object'; -} + function createElement(vnode, opts) { + var doc = opts ? opts.document || document : document; + var warn = opts ? opts.warn : null; -function is_array(value) { - return Array.isArray(value); -} + vnode = handleThunk(vnode).a; -var Checks = { - is_number, - is_string, - is_boolean, - is_symbol, - is_null, - is_undefined, - is_function, - is_variable, - is_wildcard, - is_headTail, - is_capture, - is_type, - is_startsWith, - is_bound, - is_object, - is_array -}; + if (isWidget(vnode)) { + return vnode.init(); + } else if (isVText(vnode)) { + return doc.createTextNode(vnode.text); + } else if (!isVNode(vnode)) { + if (warn) { + warn("Item is not a valid virtual dom node", vnode); + } + return null; + } -function resolveSymbol(pattern) { - return function (value) { - return Checks.is_symbol(value) && value === pattern; - }; -} + var node = vnode.namespace === null ? doc.createElement(vnode.tagName) : doc.createElementNS(vnode.namespace, vnode.tagName); -function resolveString(pattern) { - return function (value) { - return Checks.is_string(value) && value === pattern; - }; -} + var props = vnode.properties; + applyProperties(node, props); -function resolveNumber(pattern) { - return function (value) { - return Checks.is_number(value) && value === pattern; - }; -} + var children = vnode.children; -function resolveBoolean(pattern) { - return function (value) { - return Checks.is_boolean(value) && value === pattern; - }; -} + for (var i = 0; i < children.length; i++) { + var childNode = createElement(children[i], opts); + if (childNode) { + node.appendChild(childNode); + } + } + + return node; + } + }, { "../vnode/handle-thunk.js": 24, "../vnode/is-vnode.js": 27, "../vnode/is-vtext.js": 28, "../vnode/is-widget.js": 29, "./apply-properties": 14, "global/document": 10 }], 16: [function (require, module, exports) { + // Maps a virtual DOM tree onto a real DOM tree in an efficient manner. + // We don't want to read all of the DOM nodes in the tree so we use + // the in-order tree indexing to eliminate recursion down certain branches. + // We only recurse into a DOM node if we know that it contains a child of + // interest. + + var noChild = {}; -function resolveFunction(pattern) { - return function (value) { - return Checks.is_function(value) && value === pattern; - }; -} + module.exports = domIndex; -function resolveNull(pattern) { - return function (value) { - return Checks.is_null(value); - }; -} + function domIndex(rootNode, tree, indices, nodes) { + if (!indices || indices.length === 0) { + return {}; + } else { + indices.sort(ascending); + return recurse(rootNode, tree, indices, nodes, 0); + } + } -function resolveBound(pattern) { - return function (value, args) { - if (typeof value === typeof pattern.value && value === pattern.value) { - args.push(value); - return true; - } + function recurse(rootNode, tree, indices, nodes, rootIndex) { + nodes = nodes || {}; - return false; - }; -} + if (rootNode) { + if (indexInRange(indices, rootIndex, rootIndex)) { + nodes[rootIndex] = rootNode; + } -function resolveWildcard() { - return function () { - return true; - }; -} + var vChildren = tree.children; -function resolveVariable() { - return function (value, args) { - args.push(value); - return true; - }; -} + if (vChildren) { -function resolveHeadTail(pattern) { - const headMatches = buildMatch(pattern.head); - const tailMatches = buildMatch(pattern.tail); + var childNodes = rootNode.childNodes; - return function (value, args) { - if (!Checks.is_array(value) || value.length < 2) { - return false; - } + for (var i = 0; i < tree.children.length; i++) { + rootIndex += 1; - const head = value[0]; - const tail = value.slice(1); + var vChild = vChildren[i] || noChild; + var nextIndex = rootIndex + (vChild.count || 0); - if (headMatches(head, args) && tailMatches(tail, args)) { - return true; - } - }; -} + // skip recursion down the tree if there are no nodes down here + if (indexInRange(indices, rootIndex, nextIndex)) { + recurse(childNodes[i], vChild, indices, nodes, rootIndex); + } -function resolveCapture(pattern) { - const matches = buildMatch(pattern.value); + rootIndex = nextIndex; + } + } + } - return function (value, args) { - if (matches(value, args)) { - args.push(value); - return true; - } + return nodes; + } - return false; - }; -} + // Binary search for an index in the interval [left, right] + function indexInRange(indices, left, right) { + if (indices.length === 0) { + return false; + } -function resolveStartsWith(pattern) { - const prefix = pattern.prefix; + var minIndex = 0; + var maxIndex = indices.length - 1; + var currentIndex; + var currentItem; - return function (value, args) { - if (Checks.is_string(value) && value.startsWith(prefix)) { - args.push(value.substring(prefix.length)); - return true; - } + while (minIndex <= maxIndex) { + currentIndex = (maxIndex + minIndex) / 2 >> 0; + currentItem = indices[currentIndex]; - return false; - }; -} + if (minIndex === maxIndex) { + return currentItem >= left && currentItem <= right; + } else if (currentItem < left) { + minIndex = currentIndex + 1; + } else if (currentItem > right) { + maxIndex = currentIndex - 1; + } else { + return true; + } + } -function resolveType(pattern) { - return function (value, args) { - if (value instanceof pattern.type) { - const matches = buildMatch(pattern.objPattern); - return matches(value, args) && args.push(value) > 0; - } + return false; + } - return false; - }; -} + function ascending(a, b) { + return a > b ? 1 : -1; + } + }, {}], 17: [function (require, module, exports) { + var applyProperties = require("./apply-properties"); -function resolveArray(pattern) { - const matches = pattern.map(x => buildMatch(x)); + var isWidget = require("../vnode/is-widget.js"); + var VPatch = require("../vnode/vpatch.js"); - return function (value, args) { - if (!Checks.is_array(value) || value.length != pattern.length) { - return false; - } + var updateWidget = require("./update-widget"); - return value.every(function (v, i) { - return matches[i](value[i], args); - }); - }; -} + module.exports = applyPatch; -function resolveObject(pattern) { - let matches = {}; + function applyPatch(vpatch, domNode, renderOptions) { + var type = vpatch.type; + var vNode = vpatch.vNode; + var patch = vpatch.patch; - for (let key of Object.keys(pattern).concat(Object.getOwnPropertySymbols(pattern))) { - matches[key] = buildMatch(pattern[key]); - } + switch (type) { + case VPatch.REMOVE: + return removeNode(domNode, vNode); + case VPatch.INSERT: + return insertNode(domNode, patch, renderOptions); + case VPatch.VTEXT: + return stringPatch(domNode, vNode, patch, renderOptions); + case VPatch.WIDGET: + return widgetPatch(domNode, vNode, patch, renderOptions); + case VPatch.VNODE: + return vNodePatch(domNode, vNode, patch, renderOptions); + case VPatch.ORDER: + reorderChildren(domNode, patch); + return domNode; + case VPatch.PROPS: + applyProperties(domNode, patch, vNode.properties); + return domNode; + case VPatch.THUNK: + return replaceRoot(domNode, renderOptions.patch(domNode, patch, renderOptions)); + default: + return domNode; + } + } - return function (value, args) { - if (!Checks.is_object(value) || pattern.length > value.length) { - return false; - } + function removeNode(domNode, vNode) { + var parentNode = domNode.parentNode; - for (let key of Object.keys(pattern).concat(Object.getOwnPropertySymbols(pattern))) { - if (!(key in value) || !matches[key](value[key], args)) { - return false; - } - } + if (parentNode) { + parentNode.removeChild(domNode); + } - return true; - }; -} + destroyWidget(domNode, vNode); -function resolveNoMatch() { - return function () { - return false; - }; -} + return null; + } -var Resolvers = { - resolveBound, - resolveWildcard, - resolveVariable, - resolveHeadTail, - resolveCapture, - resolveStartsWith, - resolveType, - resolveArray, - resolveObject, - resolveNoMatch, - resolveSymbol, - resolveString, - resolveNumber, - resolveBoolean, - resolveFunction, - resolveNull -}; + function insertNode(parentNode, vNode, renderOptions) { + var newNode = renderOptions.render(vNode, renderOptions); -function buildMatch(pattern) { + if (parentNode) { + parentNode.appendChild(newNode); + } - if (Checks.is_variable(pattern)) { - return Resolvers.resolveVariable(pattern); - } + return parentNode; + } - if (Checks.is_wildcard(pattern)) { - return Resolvers.resolveWildcard(pattern); - } + function stringPatch(domNode, leftVNode, vText, renderOptions) { + var newNode; - if (Checks.is_undefined(pattern)) { - return Resolvers.resolveWildcard(pattern); - } + if (domNode.nodeType === 3) { + domNode.replaceData(0, domNode.length, vText.text); + newNode = domNode; + } else { + var parentNode = domNode.parentNode; + newNode = renderOptions.render(vText, renderOptions); - if (Checks.is_headTail(pattern)) { - return Resolvers.resolveHeadTail(pattern); - } + if (parentNode && newNode !== domNode) { + parentNode.replaceChild(newNode, domNode); + } + } - if (Checks.is_startsWith(pattern)) { - return Resolvers.resolveStartsWith(pattern); - } + return newNode; + } - if (Checks.is_capture(pattern)) { - return Resolvers.resolveCapture(pattern); - } + function widgetPatch(domNode, leftVNode, widget, renderOptions) { + var updating = updateWidget(leftVNode, widget); + var newNode; - if (Checks.is_bound(pattern)) { - return Resolvers.resolveBound(pattern); - } + if (updating) { + newNode = widget.update(leftVNode, domNode) || domNode; + } else { + newNode = renderOptions.render(widget, renderOptions); + } - if (Checks.is_type(pattern)) { - return Resolvers.resolveType(pattern); - } + var parentNode = domNode.parentNode; - if (Checks.is_array(pattern)) { - return Resolvers.resolveArray(pattern); - } + if (parentNode && newNode !== domNode) { + parentNode.replaceChild(newNode, domNode); + } - if (Checks.is_number(pattern)) { - return Resolvers.resolveNumber(pattern); - } + if (!updating) { + destroyWidget(domNode, leftVNode); + } - if (Checks.is_string(pattern)) { - return Resolvers.resolveString(pattern); - } + return newNode; + } - if (Checks.is_boolean(pattern)) { - return Resolvers.resolveBoolean(pattern); - } + function vNodePatch(domNode, leftVNode, vNode, renderOptions) { + var parentNode = domNode.parentNode; + var newNode = renderOptions.render(vNode, renderOptions); - if (Checks.is_symbol(pattern)) { - return Resolvers.resolveSymbol(pattern); - } + if (parentNode && newNode !== domNode) { + parentNode.replaceChild(newNode, domNode); + } - if (Checks.is_null(pattern)) { - return Resolvers.resolveNull(pattern); - } + return newNode; + } - if (Checks.is_object(pattern)) { - return Resolvers.resolveObject(pattern); - } + function destroyWidget(domNode, w) { + if (typeof w.destroy === "function" && isWidget(w)) { + w.destroy(domNode); + } + } - return Resolvers.resolveNoMatch(); -} + function reorderChildren(domNode, moves) { + var childNodes = domNode.childNodes; + var keyMap = {}; + var node; + var remove; + var insert; -class MatchError extends Error { - constructor(arg) { - super(); + for (var i = 0; i < moves.removes.length; i++) { + remove = moves.removes[i]; + node = childNodes[remove.from]; + if (remove.key) { + keyMap[remove.key] = node; + } + domNode.removeChild(node); + } - if (typeof arg === 'symbol') { - this.message = 'No match for: ' + arg.toString(); - } else if (Array.isArray(arg)) { - let mappedValues = arg.map(x => x.toString()); - this.message = 'No match for: ' + mappedValues; - } else { - this.message = 'No match for: ' + arg; - } + var length = childNodes.length; + for (var j = 0; j < moves.inserts.length; j++) { + insert = moves.inserts[j]; + node = keyMap[insert.key]; + // this is the weirdest bug i've ever seen in webkit + domNode.insertBefore(node, insert.to >= length++ ? null : childNodes[insert.to]); + } + } - this.stack = new Error().stack; - this.name = this.constructor.name; - } -} + function replaceRoot(oldRoot, newRoot) { + if (oldRoot && newRoot && oldRoot !== newRoot && oldRoot.parentNode) { + oldRoot.parentNode.replaceChild(newRoot, oldRoot); + } -class Case { + return newRoot; + } + }, { "../vnode/is-widget.js": 29, "../vnode/vpatch.js": 32, "./apply-properties": 14, "./update-widget": 19 }], 18: [function (require, module, exports) { + var document = require("global/document"); + var isArray = require("x-is-array"); - constructor(pattern, fn, guard = () => true) { - this.pattern = buildMatch(pattern); - this.fn = fn; - this.guard = guard; - } -} + var render = require("./create-element"); + var domIndex = require("./dom-index"); + var patchOp = require("./patch-op"); + module.exports = patch; -function make_case(pattern, fn, guard = () => true) { - return new Case(pattern, fn, guard); -} + function patch(rootNode, patches, renderOptions) { + renderOptions = renderOptions || {}; + renderOptions.patch = renderOptions.patch && renderOptions.patch !== patch ? renderOptions.patch : patchRecursive; + renderOptions.render = renderOptions.render || render; -function defmatch(...cases) { - return function (...args) { - for (let processedCase of cases) { - let result = []; - if (processedCase.pattern(args, result) && processedCase.guard.apply(this, result)) { - return processedCase.fn.apply(this, result); - } - } + return renderOptions.patch(rootNode, patches, renderOptions); + } - throw new MatchError(args); - }; -} + function patchRecursive(rootNode, patches, renderOptions) { + var indices = patchIndices(patches); -function match(pattern, expr, guard = () => true) { - let result = []; - let processedPattern = buildMatch(pattern); - if (processedPattern(expr, result) && guard.apply(this, result)) { - return result; - } else { - throw new MatchError(expr); - } -} + if (indices.length === 0) { + return rootNode; + } -function match_no_throw(pattern, expr, guard = () => true) { - try { - return match(pattern, expr, guard); - } catch (e) { - if (e instanceof MatchError) { - return null; - } + var index = domIndex(rootNode, patches.a, indices); + var ownerDocument = rootNode.ownerDocument; - throw e; - } -} + if (!renderOptions.document && ownerDocument !== document) { + renderOptions.document = ownerDocument; + } -var Patterns = { - defmatch, match, MatchError, match_no_throw, - variable, wildcard, startsWith, - capture, headTail, type, bound, Case, make_case -}; + for (var i = 0; i < indices.length; i++) { + var nodeIndex = indices[i]; + rootNode = applyPatch(rootNode, index[nodeIndex], patches[nodeIndex], renderOptions); + } -//https://github.com/airportyh/protomorphism -class Protocol { - constructor(spec) { - this.registry = new Map(); - this.fallback = null; + return rootNode; + } - for (let funName in spec) { - this[funName] = createFun(funName).bind(this); - } + function applyPatch(rootNode, domNode, patchList, renderOptions) { + if (!domNode) { + return rootNode; + } - function createFun(funName) { + var newNode; - return function (...args) { - let thing = args[0]; - let fun = null; + if (isArray(patchList)) { + for (var i = 0; i < patchList.length; i++) { + newNode = patchOp(patchList[i], domNode, renderOptions); - if (Number.isInteger(thing) && this.hasImplementation(Integer)) { - fun = this.registry.get(Integer)[funName]; - } else if (typeof thing === "number" && !Number.isInteger(thing) && this.hasImplementation(Float)) { - fun = this.registry.get(Float)[funName]; - } else if (this.hasImplementation(thing)) { - fun = this.registry.get(thing.constructor)[funName]; - } else if (this.fallback) { - fun = this.fallback[funName]; - } + if (domNode === rootNode) { + rootNode = newNode; + } + } + } else { + newNode = patchOp(patchList, domNode, renderOptions); - if (fun != null) { - let retval = fun.apply(this, args); - return retval; - } + if (domNode === rootNode) { + rootNode = newNode; + } + } - throw new Error("No implementation found for " + thing); - }; - } - } + return rootNode; + } - implementation(type, implementation) { - if (type === null) { - this.fallback = implementation; - } else { - this.registry.set(type, implementation); - } - } + function patchIndices(patches) { + var indices = []; - hasImplementation(thing) { - if (thing === Integer || thing === Float) { - return this.registry.has(thing); - } + for (var key in patches) { + if (key !== "a") { + indices.push(Number(key)); + } + } - return this.registry.has(thing.constructor); - } -} + return indices; + } + }, { "./create-element": 15, "./dom-index": 16, "./patch-op": 17, "global/document": 10, "x-is-array": 12 }], 19: [function (require, module, exports) { + var isWidget = require("../vnode/is-widget.js"); -function call_property(item, property) { - let prop = null; + module.exports = updateWidget; - if (typeof item === 'number' || typeof item === 'symbol' || typeof item === 'boolean' || typeof item === 'string') { - if (item[property] !== undefined) { - prop = property; - } else if (item[Symbol.for(property)] !== undefined) { - prop = Symbol.for(property); - } - } else { - if (property in item) { - prop = property; - } else if (Symbol.for(property) in item) { - prop = Symbol.for(property); - } - } + function updateWidget(a, b) { + if (isWidget(a) && isWidget(b)) { + if ("name" in a && "name" in b) { + return a.id === b.id; + } else { + return a.init === b.init; + } + } - if (prop === null) { - throw new Error(`Property ${ property } not found in ${ item }`); - } + return false; + } + }, { "../vnode/is-widget.js": 29 }], 20: [function (require, module, exports) { + 'use strict'; - if (item[prop] instanceof Function) { - return item[prop](); - } else { - return item[prop]; - } -} + var EvStore = require('ev-store'); -function apply(...args) { - if (args.length === 2) { - args[0].apply(null, args.slice(1)); - } else { - args[0][args[1]].apply(null, args.slice(2)); - } -} + module.exports = EvHook; -function contains(left, right) { - for (let x of right) { - if (Patterns.match_no_throw(left, x) != null) { - return true; - } - } + function EvHook(value) { + if (!(this instanceof EvHook)) { + return new EvHook(value); + } - return false; -} + this.value = value; + } -function get_global() { - if (typeof self !== 'undefined') { - return self; - } else if (typeof window !== 'undefined') { - return window; - } else if (typeof global !== 'undefined') { - return global; - } + EvHook.prototype.hook = function (node, propertyName) { + var es = EvStore(node); + var propName = propertyName.substr(3); - throw new Error('No global state found'); -} + es[propName] = this.value; + }; -function defstruct(defaults) { - return class { - constructor(update = {}) { - let the_values = Object.assign(defaults, update); - Object.assign(this, the_values); - } + EvHook.prototype.unhook = function (node, propertyName) { + var es = EvStore(node); + var propName = propertyName.substr(3); - static create(updates = {}) { - let x = new this(updates); - return Object.freeze(x); - } - }; -} + es[propName] = undefined; + }; + }, { "ev-store": 7 }], 21: [function (require, module, exports) { + 'use strict'; -function defexception(defaults) { - return class extends Error { - constructor(update = {}) { - let message = update.message || ''; - super(message); + module.exports = SoftSetHook; - let the_values = Object.assign(defaults, update); - Object.assign(this, the_values); + function SoftSetHook(value) { + if (!(this instanceof SoftSetHook)) { + return new SoftSetHook(value); + } - this.name = this.constructor.name; - this.message = message; - this[SpecialForms.atom('__exception__')] = true; - Error.captureStackTrace(this, this.constructor.name); - } + this.value = value; + } - static create(updates = {}) { - let x = new this(updates); - return Object.freeze(x); - } - }; -} + SoftSetHook.prototype.hook = function (node, propertyName) { + if (node[propertyName] !== this.value) { + node[propertyName] = this.value; + } + }; + }, {}], 22: [function (require, module, exports) { + 'use strict'; -function defprotocol(spec) { - return new Protocol(spec); -} + var isArray = require('x-is-array'); -function defimpl(protocol, type, impl) { - protocol.implementation(type, impl); -} + var VNode = require('../vnode/vnode.js'); + var VText = require('../vnode/vtext.js'); + var isVNode = require('../vnode/is-vnode'); + var isVText = require('../vnode/is-vtext'); + var isWidget = require('../vnode/is-widget'); + var isHook = require('../vnode/is-vhook'); + var isVThunk = require('../vnode/is-thunk'); -function get_object_keys(obj) { - return Object.keys(obj).concat(Object.getOwnPropertySymbols(obj)); -} + var parseTag = require('./parse-tag.js'); + var softSetHook = require('./hooks/soft-set-hook.js'); + var evHook = require('./hooks/ev-hook.js'); -function is_valid_character(codepoint) { - try { - return String.fromCodePoint(codepoint) != null; - } catch (e) { - return false; - } -} + module.exports = h; -//https://developer.mozilla.org/en-US/docs/Web/API/WindowBase64/Base64_encoding_and_decoding#Solution_2_%E2%80%93_rewrite_the_DOMs_atob()_and_btoa()_using_JavaScript's_TypedArrays_and_UTF-8 -function b64EncodeUnicode(str) { - return btoa(encodeURIComponent(str).replace(/%([0-9A-F]{2})/g, function (match, p1) { - return String.fromCharCode('0x' + p1); - })); -} + function h(tagName, properties, children) { + var childNodes = []; + var tag, props, key, namespace; -function delete_property_from_map(map, property) { - let new_map = Object.assign(Object.create(map.constructor.prototype), map); - delete new_map[property]; + if (!children && isChildren(properties)) { + children = properties; + props = {}; + } - return Object.freeze(new_map); -} + props = props || properties || {}; + tag = parseTag(tagName, props); -function class_to_obj(map) { - let new_map = Object.assign({}, map); - return Object.freeze(new_map); -} + // support keys + if (props.hasOwnProperty('key')) { + key = props.key; + props.key = undefined; + } -function add_property_to_map(map, property, value) { - let new_map = Object.assign({}, map); - new_map[property] = value; - return Object.freeze(new_map); -} + // support namespace + if (props.hasOwnProperty('namespace')) { + namespace = props.namespace; + props.namespace = undefined; + } -function update_map(map, property, value) { - if (property in get_object_keys(map)) { - return add_property_to_map(map, property, value); - } + // fix cursor bug + if (tag === 'INPUT' && !namespace && props.hasOwnProperty('value') && props.value !== undefined && !isHook(props.value)) { + props.value = softSetHook(props.value); + } - throw 'map does not have key'; -} + transformProperties(props); -function bnot(expr) { - return ~expr; -} + if (children !== undefined && children !== null) { + addChild(children, childNodes, tag, props); + } -function band(left, right) { - return left & right; -} + return new VNode(tag, props, childNodes, key, namespace); + } -function bor(left, right) { - return left | right; -} + function addChild(c, childNodes, tag, props) { + if (typeof c === 'string') { + childNodes.push(new VText(c)); + } else if (typeof c === 'number') { + childNodes.push(new VText(String(c))); + } else if (isChild(c)) { + childNodes.push(c); + } else if (isArray(c)) { + for (var i = 0; i < c.length; i++) { + addChild(c[i], childNodes, tag, props); + } + } else if (c === null || c === undefined) { + return; + } else { + throw UnexpectedVirtualElement({ + foreignObject: c, + parentVnode: { + tagName: tag, + properties: props + } + }); + } + } -function bsl(left, right) { - return left << right; -} + function transformProperties(props) { + for (var propName in props) { + if (props.hasOwnProperty(propName)) { + var value = props[propName]; -function bsr(left, right) { - return left >> right; -} + if (isHook(value)) { + continue; + } -function bxor(left, right) { - return left ^ right; -} + if (propName.substr(0, 3) === 'ev-') { + // add ev-foo support + props[propName] = evHook(value); + } + } + } + } -function zip(list_of_lists) { - if (list_of_lists.length === 0) { - return Object.freeze([]); - } + function isChild(x) { + return isVNode(x) || isVText(x) || isWidget(x) || isVThunk(x); + } - let new_value = []; - let smallest_length = list_of_lists[0]; + function isChildren(x) { + return typeof x === 'string' || isArray(x) || isChild(x); + } - for (let x of list_of_lists) { - if (x.length < smallest_length) { - smallest_length = x.length; - } - } + function UnexpectedVirtualElement(data) { + var err = new Error(); + + err.type = 'virtual-hyperscript.unexpected.virtual-element'; + err.message = 'Unexpected virtual child passed to h().\n' + 'Expected a VNode / Vthunk / VWidget / string but:\n' + 'got:\n' + errorString(data.foreignObject) + '.\n' + 'The parent vnode is:\n' + errorString(data.parentVnode); + '\n' + 'Suggested fix: change your `h(..., [ ... ])` callsite.'; + err.foreignObject = data.foreignObject; + err.parentVnode = data.parentVnode; - for (let i = 0; i < smallest_length; i++) { - let current_value = []; - for (let j = 0; j < list_of_lists.length; j++) { - current_value.push(list_of_lists[j][i]); - } + return err; + } - new_value.push(new Tuple(...current_value)); - } + function errorString(obj) { + try { + return JSON.stringify(obj, null, ' '); + } catch (e) { + return String(obj); + } + } + }, { "../vnode/is-thunk": 25, "../vnode/is-vhook": 26, "../vnode/is-vnode": 27, "../vnode/is-vtext": 28, "../vnode/is-widget": 29, "../vnode/vnode.js": 31, "../vnode/vtext.js": 33, "./hooks/ev-hook.js": 20, "./hooks/soft-set-hook.js": 21, "./parse-tag.js": 23, "x-is-array": 12 }], 23: [function (require, module, exports) { + 'use strict'; - return Object.freeze(new_value); -} + var split = require('browser-split'); -function can_decode64(data) { - try { - atob(data); - return true; - } catch (e) { - return false; - } -} + var classIdSplit = /([\.#]?[a-zA-Z0-9\u007F-\uFFFF_:-]+)/; + var notClassId = /^\.|#/; -function remove_from_list(list, element) { - let found = false; + module.exports = parseTag; - return list.filter(elem => { - if (!found && elem === element) { - found = true; - return false; - } + function parseTag(tag, props) { + if (!tag) { + return 'DIV'; + } - return true; - }); -} + var noId = !props.hasOwnProperty('id'); -function foldl(fun, acc, list) { - let acc1 = acc; + var tagParts = split(tag, classIdSplit); + var tagName = null; - for (const el of list) { - acc1 = fun(el, acc1); - } + if (notClassId.test(tagParts[1])) { + tagName = 'DIV'; + } - return acc1; -} + var classes, part, type, i; -function foldr(fun, acc, list) { - let acc1 = acc; + for (i = 0; i < tagParts.length; i++) { + part = tagParts[i]; - for (let i = list.length - 1; i >= 0; i--) { - acc1 = fun(list[i], acc1); - } + if (!part) { + continue; + } - return acc1; -} + type = part.charAt(0); -function keyfind(key, n, tuplelist) { + if (!tagName) { + tagName = part; + } else if (type === '.') { + classes = classes || []; + classes.push(part.substring(1, part.length)); + } else if (type === '#' && noId) { + props.id = part.substring(1, part.length); + } + } - for (let i = tuplelist.length - 1; i >= 0; i--) { - if (tuplelist[i].get(n) === key) { - return tuplelist[i]; - } - } + if (classes) { + if (props.className) { + classes.push(props.className); + } - return false; -} + props.className = classes.join(' '); + } -function keydelete(key, n, tuplelist) { + return props.namespace ? tagName : tagName.toUpperCase(); + } + }, { "browser-split": 5 }], 24: [function (require, module, exports) { + var isVNode = require("./is-vnode"); + var isVText = require("./is-vtext"); + var isWidget = require("./is-widget"); + var isThunk = require("./is-thunk"); - for (let i = tuplelist.length - 1; i >= 0; i--) { - if (tuplelist[i].get(n) === key) { - return tuplelist.concat([]).splice(i, 1); - } - } + module.exports = handleThunk; - return tuplelist; -} + function handleThunk(a, b) { + var renderedA = a; + var renderedB = b; -function keystore(key, n, list, newtuple) { - for (let i = list.length - 1; i >= 0; i--) { - if (list[i].get(n) === key) { - return list.concat([]).splice(i, 1, newtuple); - } - } + if (isThunk(b)) { + renderedB = renderThunk(b, a); + } - return list.concat([]).push(newtuple); -} + if (isThunk(a)) { + renderedA = renderThunk(a, null); + } -function keymember(key, n, list) { - for (let i = list.length - 1; i >= 0; i--) { - if (list[i].get(n) === key) { - return true; - } - } + return { + a: renderedA, + b: renderedB + }; + } - return false; -} + function renderThunk(thunk, previous) { + var renderedThunk = thunk.vnode; -function keytake(key, n, list) { - if (!keymember(key, n, list)) { - return false; - } + if (!renderedThunk) { + renderedThunk = thunk.vnode = thunk.render(previous); + } - let tuple = keyfind(key, n, list); + if (!(isVNode(renderedThunk) || isVText(renderedThunk) || isWidget(renderedThunk))) { + throw new Error("thunk did not return a valid node"); + } - return new Tuple(tuple.get(n), tuple, keydelete(key, n, list)); -} + return renderedThunk; + } + }, { "./is-thunk": 25, "./is-vnode": 27, "./is-vtext": 28, "./is-widget": 29 }], 25: [function (require, module, exports) { + module.exports = isThunk; -function keyreplace(key, n, list, newtuple) { + function isThunk(t) { + return t && t.type === "Thunk"; + } + }, {}], 26: [function (require, module, exports) { + module.exports = isHook; - for (let i = tuplelist.length - 1; i >= 0; i--) { - if (tuplelist[i].get(n) === key) { - return tuplelist.concat([]).splice(i, 1, newtuple); - } - } + function isHook(hook) { + return hook && (typeof hook.hook === "function" && !hook.hasOwnProperty("hook") || typeof hook.unhook === "function" && !hook.hasOwnProperty("unhook")); + } + }, {}], 27: [function (require, module, exports) { + var version = require("./version"); - return tuplelist; -} + module.exports = isVirtualNode; -function reverse(list) { - return list.concat([]).reverse(); -} + function isVirtualNode(x) { + return x && x.type === "VirtualNode" && x.version === version; + } + }, { "./version": 30 }], 28: [function (require, module, exports) { + var version = require("./version"); -function maps_find(key, map) { - if (key in get_object_keys(map)) { - return new Tuple(Symbol.for('ok'), map[key]); - } else { - return Symbol.for('error'); - } -} + module.exports = isVirtualText; -function flatten(list, tail = []) { - let new_list = []; + function isVirtualText(x) { + return x && x.type === "VirtualText" && x.version === version; + } + }, { "./version": 30 }], 29: [function (require, module, exports) { + module.exports = isWidget; - for (let e of list) { - if (isArray(e)) { - new_list = new_list.concat(flatten(e)); - } else { - new_list.push(e); - } - } + function isWidget(w) { + return w && w.type === "Widget"; + } + }, {}], 30: [function (require, module, exports) { + module.exports = "2"; + }, {}], 31: [function (require, module, exports) { + var version = require("./version"); + var isVNode = require("./is-vnode"); + var isWidget = require("./is-widget"); + var isThunk = require("./is-thunk"); + var isVHook = require("./is-vhook"); - return Object.freeze(new_list.concat(tail)); -} + module.exports = VirtualNode; -function duplicate(n, elem) { - let list = []; + var noProperties = {}; + var noChildren = []; - for (let i = 0; i < n; i++) { - list.push(elem); - } + function VirtualNode(tagName, properties, children, key, namespace) { + this.tagName = tagName; + this.properties = properties || noProperties; + this.children = children || noChildren; + this.key = key != null ? String(key) : undefined; + this.namespace = typeof namespace === "string" ? namespace : null; - return Object.freeze(list); -} + var count = children && children.length || 0; + var descendants = 0; + var hasWidgets = false; + var hasThunks = false; + var descendantHooks = false; + var hooks; -function mapfoldl(fun, acc, list) { - let newlist = []; + for (var propName in properties) { + if (properties.hasOwnProperty(propName)) { + var property = properties[propName]; + if (isVHook(property) && property.unhook) { + if (!hooks) { + hooks = {}; + } - for (let x of list) { - let tup = fun(x, acc); - newlist.push(tup.get(0)); - acc = tup.get(1); - } + hooks[propName] = property; + } + } + } + + for (var i = 0; i < count; i++) { + var child = children[i]; + if (isVNode(child)) { + descendants += child.count || 0; - return new Tuple(Object.freeze(newlist), acc); -} + if (!hasWidgets && child.hasWidgets) { + hasWidgets = true; + } -function filtermap(fun, list) { - let newlist = []; + if (!hasThunks && child.hasThunks) { + hasThunks = true; + } - for (x of list) { - let result = fun(x); + if (!descendantHooks && (child.hooks || child.descendantHooks)) { + descendantHooks = true; + } + } else if (!hasWidgets && isWidget(child)) { + if (typeof child.destroy === "function") { + hasWidgets = true; + } + } else if (!hasThunks && isThunk(child)) { + hasThunks = true; + } + } - if (result === true) { - newlist.push(x); - } else if (result instanceof Tuple) { - newlist.push(result.get(1)); - } - } + this.count = count + descendants; + this.hasWidgets = hasWidgets; + this.hasThunks = hasThunks; + this.hooks = hooks; + this.descendantHooks = descendantHooks; + } - return Object.freeze(newlist); -} + VirtualNode.prototype.version = version; + VirtualNode.prototype.type = "VirtualNode"; + }, { "./is-thunk": 25, "./is-vhook": 26, "./is-vnode": 27, "./is-widget": 29, "./version": 30 }], 32: [function (require, module, exports) { + var version = require("./version"); -function maps_fold(fun, acc, map) { - let acc1 = acc; + VirtualPatch.NONE = 0; + VirtualPatch.VTEXT = 1; + VirtualPatch.VNODE = 2; + VirtualPatch.WIDGET = 3; + VirtualPatch.PROPS = 4; + VirtualPatch.ORDER = 5; + VirtualPatch.INSERT = 6; + VirtualPatch.REMOVE = 7; + VirtualPatch.THUNK = 8; - for (let k of get_object_keys(map)) { - acc1 = fun(k, map[k], acc1); - } + module.exports = VirtualPatch; - return acc1; -} + function VirtualPatch(type, vNode, patch) { + this.type = Number(type); + this.vNode = vNode; + this.patch = patch; + } -var Functions = { - call_property, - apply, - contains, - get_global, - defstruct, - defexception, - defprotocol, - defimpl, - get_object_keys, - is_valid_character, - b64EncodeUnicode, - delete_property_from_map, - add_property_to_map, - class_to_obj, - can_decode64, - bnot, - band, - bor, - bsl, - bsr, - bxor, - zip, - foldl, - foldr, - remove_from_list, - keydelete, - keystore, - keyfind, - keytake, - keyreplace, - reverse, - update_map, - maps_find, - flatten, - duplicate, - mapfoldl, - filtermap, - maps_fold -}; + VirtualPatch.prototype.version = version; + VirtualPatch.prototype.type = "VirtualPatch"; + }, { "./version": 30 }], 33: [function (require, module, exports) { + var version = require("./version"); -function _case(condition, clauses) { - return Patterns.defmatch(...clauses)(condition); -} + module.exports = VirtualText; -function cond(clauses) { - for (let clause of clauses) { - if (clause[0]) { - return clause[1](); - } - } + function VirtualText(text) { + this.text = String(text); + } - throw new Error(); -} + VirtualText.prototype.version = version; + VirtualText.prototype.type = "VirtualText"; + }, { "./version": 30 }], 34: [function (require, module, exports) { + var isObject = require("is-object"); + var isHook = require("../vnode/is-vhook"); -function map_update(map, values) { - return Object.freeze(Object.assign(Object.create(map.constructor.prototype), map, values)); -} + module.exports = diffProps; -function _for(collections, fun, filter = () => true, into = [], previousValues = []) { - let pattern = collections[0][0]; - let collection = collections[0][1]; + function diffProps(a, b) { + var diff; - if (collections.length === 1) { + for (var aKey in a) { + if (!(aKey in b)) { + diff = diff || {}; + diff[aKey] = undefined; + } - for (let elem of collection) { - let r = Patterns.match_no_throw(pattern, elem); - let args = previousValues.concat(r); + var aValue = a[aKey]; + var bValue = b[aKey]; - if (r && filter.apply(this, args)) { - into = into.concat([fun.apply(this, args)]); - } - } + if (aValue === bValue) { + continue; + } else if (isObject(aValue) && isObject(bValue)) { + if (getPrototype(bValue) !== getPrototype(aValue)) { + diff = diff || {}; + diff[aKey] = bValue; + } else if (isHook(bValue)) { + diff = diff || {}; + diff[aKey] = bValue; + } else { + var objectDiff = diffProps(aValue, bValue); + if (objectDiff) { + diff = diff || {}; + diff[aKey] = objectDiff; + } + } + } else { + diff = diff || {}; + diff[aKey] = bValue; + } + } - return into; - } else { - let _into = []; + for (var bKey in b) { + if (!(bKey in a)) { + diff = diff || {}; + diff[bKey] = b[bKey]; + } + } - for (let elem of collection) { - let r = Patterns.match_no_throw(pattern, elem); - if (r) { - _into = into.concat(this._for(collections.slice(1), fun, filter, _into, previousValues.concat(r))); - } - } + return diff; + } - return _into; - } -} + function getPrototype(value) { + if (Object.getPrototypeOf) { + return Object.getPrototypeOf(value); + } else if (value.__proto__) { + return value.__proto__; + } else if (value.constructor) { + return value.constructor.prototype; + } + } + }, { "../vnode/is-vhook": 26, "is-object": 11 }], 35: [function (require, module, exports) { + var isArray = require("x-is-array"); -function _try(do_fun, rescue_function, catch_fun, else_function, after_function) { - let result = null; + var VPatch = require("../vnode/vpatch"); + var isVNode = require("../vnode/is-vnode"); + var isVText = require("../vnode/is-vtext"); + var isWidget = require("../vnode/is-widget"); + var isThunk = require("../vnode/is-thunk"); + var handleThunk = require("../vnode/handle-thunk"); - try { - result = do_fun(); - } catch (e) { - let ex_result = null; + var diffProps = require("./diff-props"); - if (rescue_function) { - try { - ex_result = rescue_function(e); - return ex_result; - } catch (ex) { - if (ex instanceof Patterns.MatchError) { - throw ex; - } - } - } + module.exports = diff; - if (catch_fun) { - try { - ex_result = catch_fun(e); - return ex_result; - } catch (ex) { - if (ex instanceof Patterns.MatchError) { - throw ex; - } - } - } + function diff(a, b) { + var patch = { a: a }; + walk(a, b, patch, 0); + return patch; + } - throw e; - } finally { - if (after_function) { - after_function(); - } - } + function walk(a, b, patch, index) { + if (a === b) { + return; + } + + var apply = patch[index]; + var applyClear = false; - if (else_function) { - try { - return else_function(result); - } catch (ex) { - if (ex instanceof Patterns.MatchError) { - throw new Error('No Match Found in Else'); - } + if (isThunk(a) || isThunk(b)) { + thunks(a, b, patch, index); + } else if (b == null) { - throw ex; - } - } else { - return result; - } -} + // If a is a widget we will add a remove patch for it + // Otherwise any child widgets/hooks must be destroyed. + // This prevents adding two remove patches for a widget. + if (!isWidget(a)) { + clearState(a, patch, index); + apply = patch[index]; + } -var SpecialForms$1 = { - _case, - cond, - map_update, - _for, - _try -}; + apply = appendPatch(apply, new VPatch(VPatch.REMOVE, a, b)); + } else if (isVNode(b)) { + if (isVNode(a)) { + if (a.tagName === b.tagName && a.namespace === b.namespace && a.key === b.key) { + var propsPatch = diffProps(a.properties, b.properties); + if (propsPatch) { + apply = appendPatch(apply, new VPatch(VPatch.PROPS, a, propsPatch)); + } + apply = diffChildren(a, b, patch, apply, index); + } else { + apply = appendPatch(apply, new VPatch(VPatch.VNODE, a, b)); + applyClear = true; + } + } else { + apply = appendPatch(apply, new VPatch(VPatch.VNODE, a, b)); + applyClear = true; + } + } else if (isVText(b)) { + if (!isVText(a)) { + apply = appendPatch(apply, new VPatch(VPatch.VTEXT, a, b)); + applyClear = true; + } else if (a.text !== b.text) { + apply = appendPatch(apply, new VPatch(VPatch.VTEXT, a, b)); + } + } else if (isWidget(b)) { + if (!isWidget(a)) { + applyClear = true; + } -Functions.get_global().processes = Functions.get_global().processes || new ProcessSystem(); + apply = appendPatch(apply, new VPatch(VPatch.WIDGET, a, b)); + } -var Core = { - ProcessSystem, - Tuple, - PID, - BitString, - Patterns, - Integer, - Float, - Functions, - SpecialForms: SpecialForms$1 -}; + if (apply) { + patch[index] = apply; + } -let Enum = { + if (applyClear) { + clearState(a, patch, index); + } + } - all__qmark__: function (collection, fun = x => x) { - for (let elem of collection) { - if (!fun(elem)) { - return false; - } - } + function diffChildren(a, b, patch, apply, index) { + var aChildren = a.children; + var orderedSet = reorder(aChildren, b.children); + var bChildren = orderedSet.children; - return true; - }, + var aLen = aChildren.length; + var bLen = bChildren.length; + var len = aLen > bLen ? aLen : bLen; - any__qmark__: function (collection, fun = x => x) { - for (let elem of collection) { - if (fun(elem)) { - return true; - } - } + for (var i = 0; i < len; i++) { + var leftNode = aChildren[i]; + var rightNode = bChildren[i]; + index += 1; - return false; - }, + if (!leftNode) { + if (rightNode) { + // Excess nodes in b need to be added + apply = appendPatch(apply, new VPatch(VPatch.INSERT, null, rightNode)); + } + } else { + walk(leftNode, rightNode, patch, index); + } - at: function (collection, n, the_default = null) { - if (n > this.count(collection) || n < 0) { - return the_default; - } + if (isVNode(leftNode) && leftNode.count) { + index += leftNode.count; + } + } - return collection[n]; - }, + if (orderedSet.moves) { + // Reorder nodes last + apply = appendPatch(apply, new VPatch(VPatch.ORDER, a, orderedSet.moves)); + } - concat: function (...enumables) { - return enumables[0].concat(enumables[1]); - }, + return apply; + } - count: function (collection, fun = null) { - if (fun == null) { - return collection.length; - } else { - return collection.filter(fun).length; - } - }, + function clearState(vNode, patch, index) { + // TODO: Make this a single walk, not two + unhook(vNode, patch, index); + destroyWidgets(vNode, patch, index); + } - drop: function (collection, count) { - return collection.slice(count); - }, + // Patch records for all destroyed widgets must be added because we need + // a DOM node reference for the destroy function + function destroyWidgets(vNode, patch, index) { + if (isWidget(vNode)) { + if (typeof vNode.destroy === "function") { + patch[index] = appendPatch(patch[index], new VPatch(VPatch.REMOVE, vNode, null)); + } + } else if (isVNode(vNode) && (vNode.hasWidgets || vNode.hasThunks)) { + var children = vNode.children; + var len = children.length; + for (var i = 0; i < len; i++) { + var child = children[i]; + index += 1; - drop_while: function (collection, fun) { - let count = 0; + destroyWidgets(child, patch, index); - for (let elem of collection) { - if (fun(elem)) { - count = count + 1; - } else { - break; - } - } + if (isVNode(child) && child.count) { + index += child.count; + } + } + } else if (isThunk(vNode)) { + thunks(vNode, null, patch, index); + } + } - return collection.slice(count); - }, + // Create a sub-patch for thunks + function thunks(a, b, patch, index) { + var nodes = handleThunk(a, b); + var thunkPatch = diff(nodes.a, nodes.b); + if (hasPatches(thunkPatch)) { + patch[index] = new VPatch(VPatch.THUNK, null, thunkPatch); + } + } - each: function (collection, fun) { - for (let elem of collection) { - fun(elem); - } - }, + function hasPatches(patch) { + for (var index in patch) { + if (index !== "a") { + return true; + } + } - empty__qmark__: function (collection) { - return collection.length === 0; - }, + return false; + } - fetch: function (collection, n) { - if (Array.isArray(collection)) { - if (n < this.count(collection) && n >= 0) { - return new Core.Tuple(Symbol.for("ok"), collection[n]); - } else { - return Symbol.for("error"); - } - } + // Execute hooks when two nodes are identical + function unhook(vNode, patch, index) { + if (isVNode(vNode)) { + if (vNode.hooks) { + patch[index] = appendPatch(patch[index], new VPatch(VPatch.PROPS, vNode, undefinedKeys(vNode.hooks))); + } - throw new Error("collection is not an Enumerable"); - }, + if (vNode.descendantHooks || vNode.hasThunks) { + var children = vNode.children; + var len = children.length; + for (var i = 0; i < len; i++) { + var child = children[i]; + index += 1; - fetch__emark__: function (collection, n) { - if (Array.isArray(collection)) { - if (n < this.count(collection) && n >= 0) { - return collection[n]; - } else { - throw new Error("out of bounds error"); - } - } + unhook(child, patch, index); - throw new Error("collection is not an Enumerable"); - }, + if (isVNode(child) && child.count) { + index += child.count; + } + } + } + } else if (isThunk(vNode)) { + thunks(vNode, null, patch, index); + } + } - filter: function (collection, fun) { - let result = []; + function undefinedKeys(obj) { + var result = {}; + + for (var key in obj) { + result[key] = undefined; + } - for (let elem of collection) { - if (fun(elem)) { - result.push(elem); - } - } + return result; + } - return result; - }, + // List diff, naive left to right reordering + function reorder(aChildren, bChildren) { + // O(M) time, O(M) memory + var bChildIndex = keyIndex(bChildren); + var bKeys = bChildIndex.keys; + var bFree = bChildIndex.free; - filter_map: function (collection, filter, mapper) { - return Enum.map(Enum.filter(collection, filter), mapper); - }, + if (bFree.length === bChildren.length) { + return { + children: bChildren, + moves: null + }; + } - find: function (collection, if_none = null, fun) { - for (let elem of collection) { - if (fun(elem)) { - return elem; - } - } + // O(N) time, O(N) memory + var aChildIndex = keyIndex(aChildren); + var aKeys = aChildIndex.keys; + var aFree = aChildIndex.free; - return if_none; - }, + if (aFree.length === aChildren.length) { + return { + children: bChildren, + moves: null + }; + } - into: function (collection, list) { - return list.concat(collection); - }, + // O(MAX(N, M)) memory + var newChildren = []; - map: function (collection, fun) { - let result = []; + var freeIndex = 0; + var freeCount = bFree.length; + var deletedItems = 0; - for (let elem of collection) { - result.push(fun(elem)); - } + // Iterate through a and match a node in b + // O(N) time, + for (var i = 0; i < aChildren.length; i++) { + var aItem = aChildren[i]; + var itemIndex; - return result; - }, + if (aItem.key) { + if (bKeys.hasOwnProperty(aItem.key)) { + // Match up the old keys + itemIndex = bKeys[aItem.key]; + newChildren.push(bChildren[itemIndex]); + } else { + // Remove old keyed items + itemIndex = i - deletedItems++; + newChildren.push(null); + } + } else { + // Match the item in a with the next free item in b + if (freeIndex < freeCount) { + itemIndex = bFree[freeIndex++]; + newChildren.push(bChildren[itemIndex]); + } else { + // There are no free items in b to match with + // the free items in a, so the extra free nodes + // are deleted. + itemIndex = i - deletedItems++; + newChildren.push(null); + } + } + } - map_reduce: function (collection, acc, fun) { - let mapped = Object.freeze([]); - let the_acc = acc; + var lastFreeIndex = freeIndex >= bFree.length ? bChildren.length : bFree[freeIndex]; - for (var i = 0; i < this.count(collection); i++) { - let tuple = fun(collection[i], the_acc); + // Iterate through b and append any new keys + // O(M) time + for (var j = 0; j < bChildren.length; j++) { + var newItem = bChildren[j]; - the_acc = tuple.get(1); - mapped = Object.freeze(mapped.concat([tuple.get(0)])); - } + if (newItem.key) { + if (!aKeys.hasOwnProperty(newItem.key)) { + // Add any new keyed items + // We are adding new items to the end and then sorting them + // in place. In future we should insert new items in place. + newChildren.push(newItem); + } + } else if (j >= lastFreeIndex) { + // Add any leftover non-keyed items + newChildren.push(newItem); + } + } - return new Core.Tuple(mapped, the_acc); - }, + var simulate = newChildren.slice(); + var simulateIndex = 0; + var removes = []; + var inserts = []; + var simulateItem; - member__qmark__: function (collection, value) { - return collection.includes(value); - }, + for (var k = 0; k < bChildren.length;) { + var wantedItem = bChildren[k]; + simulateItem = simulate[simulateIndex]; - reduce: function (collection, acc, fun) { - let the_acc = acc; + // remove items + while (simulateItem === null && simulate.length) { + removes.push(remove(simulate, simulateIndex, null)); + simulateItem = simulate[simulateIndex]; + } - for (var i = 0; i < this.count(collection); i++) { - let tuple = fun(collection[i], the_acc); + if (!simulateItem || simulateItem.key !== wantedItem.key) { + // if we need a key in this position... + if (wantedItem.key) { + if (simulateItem && simulateItem.key) { + // if an insert doesn't put this key in place, it needs to move + if (bKeys[simulateItem.key] !== k + 1) { + removes.push(remove(simulate, simulateIndex, simulateItem.key)); + simulateItem = simulate[simulateIndex]; + // if the remove didn't put the wanted item in place, we need to insert it + if (!simulateItem || simulateItem.key !== wantedItem.key) { + inserts.push({ key: wantedItem.key, to: k }); + } + // items are matching, so skip ahead + else { + simulateIndex++; + } + } else { + inserts.push({ key: wantedItem.key, to: k }); + } + } else { + inserts.push({ key: wantedItem.key, to: k }); + } + k++; + } + // a key in simulate has no matching wanted key, remove it + else if (simulateItem && simulateItem.key) { + removes.push(remove(simulate, simulateIndex, simulateItem.key)); + } + } else { + simulateIndex++; + k++; + } + } - the_acc = tuple.get(1); - } + // remove all the remaining nodes from simulate + while (simulateIndex < simulate.length) { + simulateItem = simulate[simulateIndex]; + removes.push(remove(simulate, simulateIndex, simulateItem && simulateItem.key)); + } - return the_acc; - }, + // If the only moves we have are deletes then we can just + // let the delete patch remove these items. + if (removes.length === deletedItems && !inserts.length) { + return { + children: newChildren, + moves: null + }; + } - take: function (collection, count) { - return collection.slice(0, count); - }, + return { + children: newChildren, + moves: { + removes: removes, + inserts: inserts + } + }; + } - take_every: function (collection, nth) { - let result = []; - let index = 0; + function remove(arr, index, key) { + arr.splice(index, 1); - for (let elem of collection) { - if (index % nth === 0) { - result.push(elem); - } - } + return { + from: index, + key: key + }; + } - return Object.freeze(result); - }, + function keyIndex(children) { + var keys = {}; + var free = []; + var length = children.length; - take_while: function (collection, fun) { - let count = 0; + for (var i = 0; i < length; i++) { + var child = children[i]; - for (let elem of collection) { - if (fun(elem)) { - count = count + 1; - } else { - break; - } - } + if (child.key) { + keys[child.key] = i; + } else { + free.push(i); + } + } - return collection.slice(0, count); - }, + return { + keys: keys, // A hash of key name to index + free: free // An array of unkeyed item indices + }; + } - to_list: function (collection) { - return collection; - } -}; + function appendPatch(apply, patch) { + if (apply) { + if (isArray(apply)) { + apply.push(patch); + } else { + apply = [apply, patch]; + } + + return apply; + } else { + return patch; + } + } + }, { "../vnode/handle-thunk": 24, "../vnode/is-thunk": 25, "../vnode/is-vnode": 27, "../vnode/is-vtext": 28, "../vnode/is-widget": 29, "../vnode/vpatch": 32, "./diff-props": 34, "x-is-array": 12 }] }, {}, [4])(4); +}); -var Elixir = { +var elixir = { Core, Enum, VirtualDOM }; -export default Elixir; -//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiIiwic291cmNlcyI6WyJFbGl4aXIuanMiXSwic291cmNlc0NvbnRlbnQiOlsibGV0IFZpcnR1YWxET00gPSAoZnVuY3Rpb24gKGUpIHtcbiAgICByZXR1cm4gZSgpO1xufSkoZnVuY3Rpb24gKCkge1xuICAgIHZhciBkZWZpbmUsIG1vZHVsZSwgZXhwb3J0cztcbiAgICByZXR1cm4gKGZ1bmN0aW9uIGUodCwgbiwgcikge1xuICAgICAgICBmdW5jdGlvbiBzKG8sIHUpIHtcbiAgICAgICAgICAgIGlmICghbltvXSkge1xuICAgICAgICAgICAgICAgIGlmICghdFtvXSkge1xuICAgICAgICAgICAgICAgICAgICB2YXIgYSA9IHR5cGVvZiByZXF1aXJlID09IFwiZnVuY3Rpb25cIiAmJiByZXF1aXJlO1xuICAgICAgICAgICAgICAgICAgICBpZiAoIXUgJiYgYSkgcmV0dXJuIGEobywgITApO1xuICAgICAgICAgICAgICAgICAgICBpZiAoaSkgcmV0dXJuIGkobywgITApO1xuICAgICAgICAgICAgICAgICAgICB2YXIgZiA9IG5ldyBFcnJvcihcIkNhbm5vdCBmaW5kIG1vZHVsZSAnXCIgKyBvICsgXCInXCIpO1xuICAgICAgICAgICAgICAgICAgICB0aHJvdyAoZi5jb2RlID0gXCJNT0RVTEVfTk9UX0ZPVU5EXCIsIGYpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB2YXIgbCA9IG5bb10gPSB7XG4gICAgICAgICAgICAgICAgICAgIGV4cG9ydHM6IHt9XG4gICAgICAgICAgICAgICAgfTtcbiAgICAgICAgICAgICAgICB0W29dWzBdLmNhbGwobC5leHBvcnRzLCBmdW5jdGlvbiAoZSkge1xuICAgICAgICAgICAgICAgICAgICB2YXIgbiA9IHRbb11bMV1bZV07XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBzKG4gPyBuIDogZSk7XG4gICAgICAgICAgICAgICAgfSwgbCwgbC5leHBvcnRzLCBlLCB0LCBuLCByKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJldHVybiBuW29dLmV4cG9ydHM7XG4gICAgICAgIH1cbiAgICAgICAgdmFyIGkgPSB0eXBlb2YgcmVxdWlyZSA9PSBcImZ1bmN0aW9uXCIgJiYgcmVxdWlyZTtcbiAgICAgICAgZm9yICh2YXIgbyA9IDA7IG8gPCByLmxlbmd0aDsgbysrKSBzKHJbb10pO1xuICAgICAgICByZXR1cm4gcztcbiAgICB9KSh7XG4gICAgICAgIDE6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG5cbiAgICAgICAgICAgIHZhciBjcmVhdGVFbGVtZW50ID0gcmVxdWlyZShcIi4vdmRvbS9jcmVhdGUtZWxlbWVudC5qc1wiKTtcblxuICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBjcmVhdGVFbGVtZW50O1xuICAgICAgICB9LCB7IFwiLi92ZG9tL2NyZWF0ZS1lbGVtZW50LmpzXCI6IDE1IH1dLCAyOiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge1xuICAgICAgICAgICAgdmFyIGRpZmYgPSByZXF1aXJlKFwiLi92dHJlZS9kaWZmLmpzXCIpO1xuXG4gICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IGRpZmY7XG4gICAgICAgIH0sIHsgXCIuL3Z0cmVlL2RpZmYuanNcIjogMzUgfV0sIDM6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICB2YXIgaCA9IHJlcXVpcmUoXCIuL3ZpcnR1YWwtaHlwZXJzY3JpcHQvaW5kZXguanNcIik7XG5cbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gaDtcbiAgICAgICAgfSwgeyBcIi4vdmlydHVhbC1oeXBlcnNjcmlwdC9pbmRleC5qc1wiOiAyMiB9XSwgNDogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHtcbiAgICAgICAgICAgIHZhciBkaWZmID0gcmVxdWlyZShcIi4vZGlmZi5qc1wiKTtcbiAgICAgICAgICAgIHZhciBwYXRjaCA9IHJlcXVpcmUoXCIuL3BhdGNoLmpzXCIpO1xuICAgICAgICAgICAgdmFyIGggPSByZXF1aXJlKFwiLi9oLmpzXCIpO1xuICAgICAgICAgICAgdmFyIGNyZWF0ZSA9IHJlcXVpcmUoXCIuL2NyZWF0ZS1lbGVtZW50LmpzXCIpO1xuICAgICAgICAgICAgdmFyIFZOb2RlID0gcmVxdWlyZShcIi4vdm5vZGUvdm5vZGUuanNcIik7XG4gICAgICAgICAgICB2YXIgVlRleHQgPSByZXF1aXJlKFwiLi92bm9kZS92dGV4dC5qc1wiKTtcblxuICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSB7XG4gICAgICAgICAgICAgICAgZGlmZjogZGlmZixcbiAgICAgICAgICAgICAgICBwYXRjaDogcGF0Y2gsXG4gICAgICAgICAgICAgICAgaDogaCxcbiAgICAgICAgICAgICAgICBjcmVhdGU6IGNyZWF0ZSxcbiAgICAgICAgICAgICAgICBWTm9kZTogVk5vZGUsXG4gICAgICAgICAgICAgICAgVlRleHQ6IFZUZXh0XG4gICAgICAgICAgICB9O1xuICAgICAgICB9LCB7IFwiLi9jcmVhdGUtZWxlbWVudC5qc1wiOiAxLCBcIi4vZGlmZi5qc1wiOiAyLCBcIi4vaC5qc1wiOiAzLCBcIi4vcGF0Y2guanNcIjogMTMsIFwiLi92bm9kZS92bm9kZS5qc1wiOiAzMSwgXCIuL3Zub2RlL3Z0ZXh0LmpzXCI6IDMzIH1dLCA1OiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge1xuICAgICAgICAgICAgLyohXG4gICAgICAgICAgICAgKiBDcm9zcy1Ccm93c2VyIFNwbGl0IDEuMS4xXG4gICAgICAgICAgICAgKiBDb3B5cmlnaHQgMjAwNy0yMDEyIFN0ZXZlbiBMZXZpdGhhbiA8c3RldmVubGV2aXRoYW4uY29tPlxuICAgICAgICAgICAgICogQXZhaWxhYmxlIHVuZGVyIHRoZSBNSVQgTGljZW5zZVxuICAgICAgICAgICAgICogRUNNQVNjcmlwdCBjb21wbGlhbnQsIHVuaWZvcm0gY3Jvc3MtYnJvd3NlciBzcGxpdCBtZXRob2RcbiAgICAgICAgICAgICAqL1xuXG4gICAgICAgICAgICAvKipcbiAgICAgICAgICAgICAqIFNwbGl0cyBhIHN0cmluZyBpbnRvIGFuIGFycmF5IG9mIHN0cmluZ3MgdXNpbmcgYSByZWdleCBvciBzdHJpbmcgc2VwYXJhdG9yLiBNYXRjaGVzIG9mIHRoZVxuICAgICAgICAgICAgICogc2VwYXJhdG9yIGFyZSBub3QgaW5jbHVkZWQgaW4gdGhlIHJlc3VsdCBhcnJheS4gSG93ZXZlciwgaWYgYHNlcGFyYXRvcmAgaXMgYSByZWdleCB0aGF0IGNvbnRhaW5zXG4gICAgICAgICAgICAgKiBjYXB0dXJpbmcgZ3JvdXBzLCBiYWNrcmVmZXJlbmNlcyBhcmUgc3BsaWNlZCBpbnRvIHRoZSByZXN1bHQgZWFjaCB0aW1lIGBzZXBhcmF0b3JgIGlzIG1hdGNoZWQuXG4gICAgICAgICAgICAgKiBGaXhlcyBicm93c2VyIGJ1Z3MgY29tcGFyZWQgdG8gdGhlIG5hdGl2ZSBgU3RyaW5nLnByb3RvdHlwZS5zcGxpdGAgYW5kIGNhbiBiZSB1c2VkIHJlbGlhYmx5XG4gICAgICAgICAgICAgKiBjcm9zcy1icm93c2VyLlxuICAgICAgICAgICAgICogQHBhcmFtIHtTdHJpbmd9IHN0ciBTdHJpbmcgdG8gc3BsaXQuXG4gICAgICAgICAgICAgKiBAcGFyYW0ge1JlZ0V4cHxTdHJpbmd9IHNlcGFyYXRvciBSZWdleCBvciBzdHJpbmcgdG8gdXNlIGZvciBzZXBhcmF0aW5nIHRoZSBzdHJpbmcuXG4gICAgICAgICAgICAgKiBAcGFyYW0ge051bWJlcn0gW2xpbWl0XSBNYXhpbXVtIG51bWJlciBvZiBpdGVtcyB0byBpbmNsdWRlIGluIHRoZSByZXN1bHQgYXJyYXkuXG4gICAgICAgICAgICAgKiBAcmV0dXJucyB7QXJyYXl9IEFycmF5IG9mIHN1YnN0cmluZ3MuXG4gICAgICAgICAgICAgKiBAZXhhbXBsZVxuICAgICAgICAgICAgICpcbiAgICAgICAgICAgICAqIC8vIEJhc2ljIHVzZVxuICAgICAgICAgICAgICogc3BsaXQoJ2EgYiBjIGQnLCAnICcpO1xuICAgICAgICAgICAgICogLy8gLT4gWydhJywgJ2InLCAnYycsICdkJ11cbiAgICAgICAgICAgICAqXG4gICAgICAgICAgICAgKiAvLyBXaXRoIGxpbWl0XG4gICAgICAgICAgICAgKiBzcGxpdCgnYSBiIGMgZCcsICcgJywgMik7XG4gICAgICAgICAgICAgKiAvLyAtPiBbJ2EnLCAnYiddXG4gICAgICAgICAgICAgKlxuICAgICAgICAgICAgICogLy8gQmFja3JlZmVyZW5jZXMgaW4gcmVzdWx0IGFycmF5XG4gICAgICAgICAgICAgKiBzcGxpdCgnLi53b3JkMSB3b3JkMi4uJywgLyhbYS16XSspKFxcZCspL2kpO1xuICAgICAgICAgICAgICogLy8gLT4gWycuLicsICd3b3JkJywgJzEnLCAnICcsICd3b3JkJywgJzInLCAnLi4nXVxuICAgICAgICAgICAgICovXG4gICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IChmdW5jdGlvbiBzcGxpdCh1bmRlZikge1xuXG4gICAgICAgICAgICAgICAgdmFyIG5hdGl2ZVNwbGl0ID0gU3RyaW5nLnByb3RvdHlwZS5zcGxpdCxcbiAgICAgICAgICAgICAgICAgICAgY29tcGxpYW50RXhlY05wY2cgPSAvKCk/Py8uZXhlYyhcIlwiKVsxXSA9PT0gdW5kZWYsXG5cbiAgICAgICAgICAgICAgICAvLyBOUENHOiBub25wYXJ0aWNpcGF0aW5nIGNhcHR1cmluZyBncm91cFxuICAgICAgICAgICAgICAgIHNlbGY7XG5cbiAgICAgICAgICAgICAgICBzZWxmID0gZnVuY3Rpb24gKHN0ciwgc2VwYXJhdG9yLCBsaW1pdCkge1xuICAgICAgICAgICAgICAgICAgICAvLyBJZiBgc2VwYXJhdG9yYCBpcyBub3QgYSByZWdleCwgdXNlIGBuYXRpdmVTcGxpdGBcbiAgICAgICAgICAgICAgICAgICAgaWYgKE9iamVjdC5wcm90b3R5cGUudG9TdHJpbmcuY2FsbChzZXBhcmF0b3IpICE9PSBcIltvYmplY3QgUmVnRXhwXVwiKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gbmF0aXZlU3BsaXQuY2FsbChzdHIsIHNlcGFyYXRvciwgbGltaXQpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIHZhciBvdXRwdXQgPSBbXSxcbiAgICAgICAgICAgICAgICAgICAgICAgIGZsYWdzID0gKHNlcGFyYXRvci5pZ25vcmVDYXNlID8gXCJpXCIgOiBcIlwiKSArIChzZXBhcmF0b3IubXVsdGlsaW5lID8gXCJtXCIgOiBcIlwiKSArIChzZXBhcmF0b3IuZXh0ZW5kZWQgPyBcInhcIiA6IFwiXCIpICsgKHNlcGFyYXRvci5zdGlja3kgPyBcInlcIiA6IFwiXCIpLFxuXG4gICAgICAgICAgICAgICAgICAgIC8vIEZpcmVmb3ggMytcbiAgICAgICAgICAgICAgICAgICAgbGFzdExhc3RJbmRleCA9IDAsXG5cbiAgICAgICAgICAgICAgICAgICAgLy8gTWFrZSBgZ2xvYmFsYCBhbmQgYXZvaWQgYGxhc3RJbmRleGAgaXNzdWVzIGJ5IHdvcmtpbmcgd2l0aCBhIGNvcHlcbiAgICAgICAgICAgICAgICAgICAgc2VwYXJhdG9yID0gbmV3IFJlZ0V4cChzZXBhcmF0b3Iuc291cmNlLCBmbGFncyArIFwiZ1wiKSxcbiAgICAgICAgICAgICAgICAgICAgICAgIHNlcGFyYXRvcjIsXG4gICAgICAgICAgICAgICAgICAgICAgICBtYXRjaCxcbiAgICAgICAgICAgICAgICAgICAgICAgIGxhc3RJbmRleCxcbiAgICAgICAgICAgICAgICAgICAgICAgIGxhc3RMZW5ndGg7XG4gICAgICAgICAgICAgICAgICAgIHN0ciArPSBcIlwiOyAvLyBUeXBlLWNvbnZlcnRcbiAgICAgICAgICAgICAgICAgICAgaWYgKCFjb21wbGlhbnRFeGVjTnBjZykge1xuICAgICAgICAgICAgICAgICAgICAgICAgLy8gRG9lc24ndCBuZWVkIGZsYWdzIGd5LCBidXQgdGhleSBkb24ndCBodXJ0XG4gICAgICAgICAgICAgICAgICAgICAgICBzZXBhcmF0b3IyID0gbmV3IFJlZ0V4cChcIl5cIiArIHNlcGFyYXRvci5zb3VyY2UgKyBcIiQoPyFcXFxccylcIiwgZmxhZ3MpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIC8qIFZhbHVlcyBmb3IgYGxpbWl0YCwgcGVyIHRoZSBzcGVjOlxuICAgICAgICAgICAgICAgICAgICAgKiBJZiB1bmRlZmluZWQ6IDQyOTQ5NjcyOTUgLy8gTWF0aC5wb3coMiwgMzIpIC0gMVxuICAgICAgICAgICAgICAgICAgICAgKiBJZiAwLCBJbmZpbml0eSwgb3IgTmFOOiAwXG4gICAgICAgICAgICAgICAgICAgICAqIElmIHBvc2l0aXZlIG51bWJlcjogbGltaXQgPSBNYXRoLmZsb29yKGxpbWl0KTsgaWYgKGxpbWl0ID4gNDI5NDk2NzI5NSkgbGltaXQgLT0gNDI5NDk2NzI5NjtcbiAgICAgICAgICAgICAgICAgICAgICogSWYgbmVnYXRpdmUgbnVtYmVyOiA0Mjk0OTY3Mjk2IC0gTWF0aC5mbG9vcihNYXRoLmFicyhsaW1pdCkpXG4gICAgICAgICAgICAgICAgICAgICAqIElmIG90aGVyOiBUeXBlLWNvbnZlcnQsIHRoZW4gdXNlIHRoZSBhYm92ZSBydWxlc1xuICAgICAgICAgICAgICAgICAgICAgKi9cbiAgICAgICAgICAgICAgICAgICAgbGltaXQgPSBsaW1pdCA9PT0gdW5kZWYgPyAtMSA+Pj4gMCA6IC8vIE1hdGgucG93KDIsIDMyKSAtIDFcbiAgICAgICAgICAgICAgICAgICAgbGltaXQgPj4+IDA7IC8vIFRvVWludDMyKGxpbWl0KVxuICAgICAgICAgICAgICAgICAgICB3aGlsZSAobWF0Y2ggPSBzZXBhcmF0b3IuZXhlYyhzdHIpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAvLyBgc2VwYXJhdG9yLmxhc3RJbmRleGAgaXMgbm90IHJlbGlhYmxlIGNyb3NzLWJyb3dzZXJcbiAgICAgICAgICAgICAgICAgICAgICAgIGxhc3RJbmRleCA9IG1hdGNoLmluZGV4ICsgbWF0Y2hbMF0ubGVuZ3RoO1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGxhc3RJbmRleCA+IGxhc3RMYXN0SW5kZXgpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBvdXRwdXQucHVzaChzdHIuc2xpY2UobGFzdExhc3RJbmRleCwgbWF0Y2guaW5kZXgpKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBGaXggYnJvd3NlcnMgd2hvc2UgYGV4ZWNgIG1ldGhvZHMgZG9uJ3QgY29uc2lzdGVudGx5IHJldHVybiBgdW5kZWZpbmVkYCBmb3JcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBub25wYXJ0aWNpcGF0aW5nIGNhcHR1cmluZyBncm91cHNcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoIWNvbXBsaWFudEV4ZWNOcGNnICYmIG1hdGNoLmxlbmd0aCA+IDEpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbWF0Y2hbMF0ucmVwbGFjZShzZXBhcmF0b3IyLCBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBmb3IgKHZhciBpID0gMTsgaSA8IGFyZ3VtZW50cy5sZW5ndGggLSAyOyBpKyspIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoYXJndW1lbnRzW2ldID09PSB1bmRlZikge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBtYXRjaFtpXSA9IHVuZGVmO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChtYXRjaC5sZW5ndGggPiAxICYmIG1hdGNoLmluZGV4IDwgc3RyLmxlbmd0aCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBBcnJheS5wcm90b3R5cGUucHVzaC5hcHBseShvdXRwdXQsIG1hdGNoLnNsaWNlKDEpKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgbGFzdExlbmd0aCA9IG1hdGNoWzBdLmxlbmd0aDtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBsYXN0TGFzdEluZGV4ID0gbGFzdEluZGV4O1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChvdXRwdXQubGVuZ3RoID49IGxpbWl0KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChzZXBhcmF0b3IubGFzdEluZGV4ID09PSBtYXRjaC5pbmRleCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNlcGFyYXRvci5sYXN0SW5kZXgrKzsgLy8gQXZvaWQgYW4gaW5maW5pdGUgbG9vcFxuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIGlmIChsYXN0TGFzdEluZGV4ID09PSBzdHIubGVuZ3RoKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAobGFzdExlbmd0aCB8fCAhc2VwYXJhdG9yLnRlc3QoXCJcIikpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBvdXRwdXQucHVzaChcIlwiKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIG91dHB1dC5wdXNoKHN0ci5zbGljZShsYXN0TGFzdEluZGV4KSk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIG91dHB1dC5sZW5ndGggPiBsaW1pdCA/IG91dHB1dC5zbGljZSgwLCBsaW1pdCkgOiBvdXRwdXQ7XG4gICAgICAgICAgICAgICAgfTtcblxuICAgICAgICAgICAgICAgIHJldHVybiBzZWxmO1xuICAgICAgICAgICAgfSkoKTtcbiAgICAgICAgfSwge31dLCA2OiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge30sIHt9XSwgNzogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHtcbiAgICAgICAgICAgIFwidXNlIHN0cmljdFwiO1xuXG4gICAgICAgICAgICB2YXIgT25lVmVyc2lvbkNvbnN0cmFpbnQgPSByZXF1aXJlKFwiaW5kaXZpZHVhbC9vbmUtdmVyc2lvblwiKTtcblxuICAgICAgICAgICAgdmFyIE1ZX1ZFUlNJT04gPSBcIjdcIjtcbiAgICAgICAgICAgIE9uZVZlcnNpb25Db25zdHJhaW50KFwiZXYtc3RvcmVcIiwgTVlfVkVSU0lPTik7XG5cbiAgICAgICAgICAgIHZhciBoYXNoS2V5ID0gXCJfX0VWX1NUT1JFX0tFWUBcIiArIE1ZX1ZFUlNJT047XG5cbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gRXZTdG9yZTtcblxuICAgICAgICAgICAgZnVuY3Rpb24gRXZTdG9yZShlbGVtKSB7XG4gICAgICAgICAgICAgICAgdmFyIGhhc2ggPSBlbGVtW2hhc2hLZXldO1xuXG4gICAgICAgICAgICAgICAgaWYgKCFoYXNoKSB7XG4gICAgICAgICAgICAgICAgICAgIGhhc2ggPSBlbGVtW2hhc2hLZXldID0ge307XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgcmV0dXJuIGhhc2g7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0sIHsgXCJpbmRpdmlkdWFsL29uZS12ZXJzaW9uXCI6IDkgfV0sIDg6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICAoZnVuY3Rpb24gKGdsb2JhbCkge1xuICAgICAgICAgICAgICAgIFwidXNlIHN0cmljdFwiO1xuXG4gICAgICAgICAgICAgICAgLypnbG9iYWwgd2luZG93LCBnbG9iYWwqL1xuXG4gICAgICAgICAgICAgICAgdmFyIHJvb3QgPSB0eXBlb2Ygd2luZG93ICE9PSBcInVuZGVmaW5lZFwiID8gd2luZG93IDogdHlwZW9mIGdsb2JhbCAhPT0gXCJ1bmRlZmluZWRcIiA/IGdsb2JhbCA6IHt9O1xuXG4gICAgICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBJbmRpdmlkdWFsO1xuXG4gICAgICAgICAgICAgICAgZnVuY3Rpb24gSW5kaXZpZHVhbChrZXksIHZhbHVlKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmIChrZXkgaW4gcm9vdCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHJvb3Rba2V5XTtcbiAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgIHJvb3Rba2V5XSA9IHZhbHVlO1xuXG4gICAgICAgICAgICAgICAgICAgIHJldHVybiB2YWx1ZTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9KS5jYWxsKHRoaXMsIHR5cGVvZiBnbG9iYWwgIT09IFwidW5kZWZpbmVkXCIgPyBnbG9iYWwgOiB0eXBlb2Ygc2VsZiAhPT0gXCJ1bmRlZmluZWRcIiA/IHNlbGYgOiB0eXBlb2Ygd2luZG93ICE9PSBcInVuZGVmaW5lZFwiID8gd2luZG93IDoge30pO1xuICAgICAgICB9LCB7fV0sIDk6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICBcInVzZSBzdHJpY3RcIjtcblxuICAgICAgICAgICAgdmFyIEluZGl2aWR1YWwgPSByZXF1aXJlKFwiLi9pbmRleC5qc1wiKTtcblxuICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBPbmVWZXJzaW9uO1xuXG4gICAgICAgICAgICBmdW5jdGlvbiBPbmVWZXJzaW9uKG1vZHVsZU5hbWUsIHZlcnNpb24sIGRlZmF1bHRWYWx1ZSkge1xuICAgICAgICAgICAgICAgIHZhciBrZXkgPSBcIl9fSU5ESVZJRFVBTF9PTkVfVkVSU0lPTl9cIiArIG1vZHVsZU5hbWU7XG4gICAgICAgICAgICAgICAgdmFyIGVuZm9yY2VLZXkgPSBrZXkgKyBcIl9FTkZPUkNFX1NJTkdMRVRPTlwiO1xuXG4gICAgICAgICAgICAgICAgdmFyIHZlcnNpb25WYWx1ZSA9IEluZGl2aWR1YWwoZW5mb3JjZUtleSwgdmVyc2lvbik7XG5cbiAgICAgICAgICAgICAgICBpZiAodmVyc2lvblZhbHVlICE9PSB2ZXJzaW9uKSB7XG4gICAgICAgICAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcihcIkNhbiBvbmx5IGhhdmUgb25lIGNvcHkgb2YgXCIgKyBtb2R1bGVOYW1lICsgXCIuXFxuXCIgKyBcIllvdSBhbHJlYWR5IGhhdmUgdmVyc2lvbiBcIiArIHZlcnNpb25WYWx1ZSArIFwiIGluc3RhbGxlZC5cXG5cIiArIFwiVGhpcyBtZWFucyB5b3UgY2Fubm90IGluc3RhbGwgdmVyc2lvbiBcIiArIHZlcnNpb24pO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHJldHVybiBJbmRpdmlkdWFsKGtleSwgZGVmYXVsdFZhbHVlKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSwgeyBcIi4vaW5kZXguanNcIjogOCB9XSwgMTA6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICAoZnVuY3Rpb24gKGdsb2JhbCkge1xuICAgICAgICAgICAgICAgIHZhciB0b3BMZXZlbCA9IHR5cGVvZiBnbG9iYWwgIT09IFwidW5kZWZpbmVkXCIgPyBnbG9iYWwgOiB0eXBlb2Ygd2luZG93ICE9PSBcInVuZGVmaW5lZFwiID8gd2luZG93IDoge307XG4gICAgICAgICAgICAgICAgdmFyIG1pbkRvYyA9IHJlcXVpcmUoXCJtaW4tZG9jdW1lbnRcIik7XG5cbiAgICAgICAgICAgICAgICBpZiAodHlwZW9mIGRvY3VtZW50ICE9PSBcInVuZGVmaW5lZFwiKSB7XG4gICAgICAgICAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gZG9jdW1lbnQ7XG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgdmFyIGRvY2N5ID0gdG9wTGV2ZWxbXCJfX0dMT0JBTF9ET0NVTUVOVF9DQUNIRUA0XCJdO1xuXG4gICAgICAgICAgICAgICAgICAgIGlmICghZG9jY3kpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGRvY2N5ID0gdG9wTGV2ZWxbXCJfX0dMT0JBTF9ET0NVTUVOVF9DQUNIRUA0XCJdID0gbWluRG9jO1xuICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBkb2NjeTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9KS5jYWxsKHRoaXMsIHR5cGVvZiBnbG9iYWwgIT09IFwidW5kZWZpbmVkXCIgPyBnbG9iYWwgOiB0eXBlb2Ygc2VsZiAhPT0gXCJ1bmRlZmluZWRcIiA/IHNlbGYgOiB0eXBlb2Ygd2luZG93ICE9PSBcInVuZGVmaW5lZFwiID8gd2luZG93IDoge30pO1xuICAgICAgICB9LCB7IFwibWluLWRvY3VtZW50XCI6IDYgfV0sIDExOiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge1xuICAgICAgICAgICAgXCJ1c2Ugc3RyaWN0XCI7XG5cbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gaXNPYmplY3QoeCkge1xuICAgICAgICAgICAgICAgIHJldHVybiB0eXBlb2YgeCA9PT0gXCJvYmplY3RcIiAmJiB4ICE9PSBudWxsO1xuICAgICAgICAgICAgfTtcbiAgICAgICAgfSwge31dLCAxMjogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHtcbiAgICAgICAgICAgIHZhciBuYXRpdmVJc0FycmF5ID0gQXJyYXkuaXNBcnJheTtcbiAgICAgICAgICAgIHZhciB0b1N0cmluZyA9IE9iamVjdC5wcm90b3R5cGUudG9TdHJpbmc7XG5cbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gbmF0aXZlSXNBcnJheSB8fCBpc0FycmF5O1xuXG4gICAgICAgICAgICBmdW5jdGlvbiBpc0FycmF5KG9iaikge1xuICAgICAgICAgICAgICAgIHJldHVybiB0b1N0cmluZy5jYWxsKG9iaikgPT09IFwiW29iamVjdCBBcnJheV1cIjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSwge31dLCAxMzogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHtcbiAgICAgICAgICAgIHZhciBwYXRjaCA9IHJlcXVpcmUoXCIuL3Zkb20vcGF0Y2guanNcIik7XG5cbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gcGF0Y2g7XG4gICAgICAgIH0sIHsgXCIuL3Zkb20vcGF0Y2guanNcIjogMTggfV0sIDE0OiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge1xuICAgICAgICAgICAgdmFyIGlzT2JqZWN0ID0gcmVxdWlyZShcImlzLW9iamVjdFwiKTtcbiAgICAgICAgICAgIHZhciBpc0hvb2sgPSByZXF1aXJlKFwiLi4vdm5vZGUvaXMtdmhvb2suanNcIik7XG5cbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gYXBwbHlQcm9wZXJ0aWVzO1xuXG4gICAgICAgICAgICBmdW5jdGlvbiBhcHBseVByb3BlcnRpZXMobm9kZSwgcHJvcHMsIHByZXZpb3VzKSB7XG4gICAgICAgICAgICAgICAgZm9yICh2YXIgcHJvcE5hbWUgaW4gcHJvcHMpIHtcbiAgICAgICAgICAgICAgICAgICAgdmFyIHByb3BWYWx1ZSA9IHByb3BzW3Byb3BOYW1lXTtcblxuICAgICAgICAgICAgICAgICAgICBpZiAocHJvcFZhbHVlID09PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJlbW92ZVByb3BlcnR5KG5vZGUsIHByb3BOYW1lLCBwcm9wVmFsdWUsIHByZXZpb3VzKTtcbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIGlmIChpc0hvb2socHJvcFZhbHVlKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgcmVtb3ZlUHJvcGVydHkobm9kZSwgcHJvcE5hbWUsIHByb3BWYWx1ZSwgcHJldmlvdXMpO1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHByb3BWYWx1ZS5ob29rKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcHJvcFZhbHVlLmhvb2sobm9kZSwgcHJvcE5hbWUsIHByZXZpb3VzID8gcHJldmlvdXNbcHJvcE5hbWVdIDogdW5kZWZpbmVkKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChpc09iamVjdChwcm9wVmFsdWUpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcGF0Y2hPYmplY3Qobm9kZSwgcHJvcHMsIHByZXZpb3VzLCBwcm9wTmFtZSwgcHJvcFZhbHVlKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgbm9kZVtwcm9wTmFtZV0gPSBwcm9wVmFsdWU7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIHJlbW92ZVByb3BlcnR5KG5vZGUsIHByb3BOYW1lLCBwcm9wVmFsdWUsIHByZXZpb3VzKSB7XG4gICAgICAgICAgICAgICAgaWYgKHByZXZpb3VzKSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciBwcmV2aW91c1ZhbHVlID0gcHJldmlvdXNbcHJvcE5hbWVdO1xuXG4gICAgICAgICAgICAgICAgICAgIGlmICghaXNIb29rKHByZXZpb3VzVmFsdWUpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAocHJvcE5hbWUgPT09IFwiYXR0cmlidXRlc1wiKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgZm9yICh2YXIgYXR0ck5hbWUgaW4gcHJldmlvdXNWYWx1ZSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBub2RlLnJlbW92ZUF0dHJpYnV0ZShhdHRyTmFtZSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIGlmIChwcm9wTmFtZSA9PT0gXCJzdHlsZVwiKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgZm9yICh2YXIgaSBpbiBwcmV2aW91c1ZhbHVlKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG5vZGUuc3R5bGVbaV0gPSBcIlwiO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAodHlwZW9mIHByZXZpb3VzVmFsdWUgPT09IFwic3RyaW5nXCIpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBub2RlW3Byb3BOYW1lXSA9IFwiXCI7XG4gICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIG5vZGVbcHJvcE5hbWVdID0gbnVsbDtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIGlmIChwcmV2aW91c1ZhbHVlLnVuaG9vaykge1xuICAgICAgICAgICAgICAgICAgICAgICAgcHJldmlvdXNWYWx1ZS51bmhvb2sobm9kZSwgcHJvcE5hbWUsIHByb3BWYWx1ZSk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIHBhdGNoT2JqZWN0KG5vZGUsIHByb3BzLCBwcmV2aW91cywgcHJvcE5hbWUsIHByb3BWYWx1ZSkge1xuICAgICAgICAgICAgICAgIHZhciBwcmV2aW91c1ZhbHVlID0gcHJldmlvdXMgPyBwcmV2aW91c1twcm9wTmFtZV0gOiB1bmRlZmluZWQ7XG5cbiAgICAgICAgICAgICAgICAvLyBTZXQgYXR0cmlidXRlc1xuICAgICAgICAgICAgICAgIGlmIChwcm9wTmFtZSA9PT0gXCJhdHRyaWJ1dGVzXCIpIHtcbiAgICAgICAgICAgICAgICAgICAgZm9yICh2YXIgYXR0ck5hbWUgaW4gcHJvcFZhbHVlKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICB2YXIgYXR0clZhbHVlID0gcHJvcFZhbHVlW2F0dHJOYW1lXTtcblxuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGF0dHJWYWx1ZSA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgbm9kZS5yZW1vdmVBdHRyaWJ1dGUoYXR0ck5hbWUpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBub2RlLnNldEF0dHJpYnV0ZShhdHRyTmFtZSwgYXR0clZhbHVlKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICBpZiAocHJldmlvdXNWYWx1ZSAmJiBpc09iamVjdChwcmV2aW91c1ZhbHVlKSAmJiBnZXRQcm90b3R5cGUocHJldmlvdXNWYWx1ZSkgIT09IGdldFByb3RvdHlwZShwcm9wVmFsdWUpKSB7XG4gICAgICAgICAgICAgICAgICAgIG5vZGVbcHJvcE5hbWVdID0gcHJvcFZhbHVlO1xuICAgICAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgaWYgKCFpc09iamVjdChub2RlW3Byb3BOYW1lXSkpIHtcbiAgICAgICAgICAgICAgICAgICAgbm9kZVtwcm9wTmFtZV0gPSB7fTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICB2YXIgcmVwbGFjZXIgPSBwcm9wTmFtZSA9PT0gXCJzdHlsZVwiID8gXCJcIiA6IHVuZGVmaW5lZDtcblxuICAgICAgICAgICAgICAgIGZvciAodmFyIGsgaW4gcHJvcFZhbHVlKSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciB2YWx1ZSA9IHByb3BWYWx1ZVtrXTtcbiAgICAgICAgICAgICAgICAgICAgbm9kZVtwcm9wTmFtZV1ba10gPSB2YWx1ZSA9PT0gdW5kZWZpbmVkID8gcmVwbGFjZXIgOiB2YWx1ZTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIGdldFByb3RvdHlwZSh2YWx1ZSkge1xuICAgICAgICAgICAgICAgIGlmIChPYmplY3QuZ2V0UHJvdG90eXBlT2YpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIE9iamVjdC5nZXRQcm90b3R5cGVPZih2YWx1ZSk7XG4gICAgICAgICAgICAgICAgfSBlbHNlIGlmICh2YWx1ZS5fX3Byb3RvX18pIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHZhbHVlLl9fcHJvdG9fXztcbiAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKHZhbHVlLmNvbnN0cnVjdG9yKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiB2YWx1ZS5jb25zdHJ1Y3Rvci5wcm90b3R5cGU7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9LCB7IFwiLi4vdm5vZGUvaXMtdmhvb2suanNcIjogMjYsIFwiaXMtb2JqZWN0XCI6IDExIH1dLCAxNTogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHtcbiAgICAgICAgICAgIHZhciBkb2N1bWVudCA9IHJlcXVpcmUoXCJnbG9iYWwvZG9jdW1lbnRcIik7XG5cbiAgICAgICAgICAgIHZhciBhcHBseVByb3BlcnRpZXMgPSByZXF1aXJlKFwiLi9hcHBseS1wcm9wZXJ0aWVzXCIpO1xuXG4gICAgICAgICAgICB2YXIgaXNWTm9kZSA9IHJlcXVpcmUoXCIuLi92bm9kZS9pcy12bm9kZS5qc1wiKTtcbiAgICAgICAgICAgIHZhciBpc1ZUZXh0ID0gcmVxdWlyZShcIi4uL3Zub2RlL2lzLXZ0ZXh0LmpzXCIpO1xuICAgICAgICAgICAgdmFyIGlzV2lkZ2V0ID0gcmVxdWlyZShcIi4uL3Zub2RlL2lzLXdpZGdldC5qc1wiKTtcbiAgICAgICAgICAgIHZhciBoYW5kbGVUaHVuayA9IHJlcXVpcmUoXCIuLi92bm9kZS9oYW5kbGUtdGh1bmsuanNcIik7XG5cbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gY3JlYXRlRWxlbWVudDtcblxuICAgICAgICAgICAgZnVuY3Rpb24gY3JlYXRlRWxlbWVudCh2bm9kZSwgb3B0cykge1xuICAgICAgICAgICAgICAgIHZhciBkb2MgPSBvcHRzID8gb3B0cy5kb2N1bWVudCB8fCBkb2N1bWVudCA6IGRvY3VtZW50O1xuICAgICAgICAgICAgICAgIHZhciB3YXJuID0gb3B0cyA/IG9wdHMud2FybiA6IG51bGw7XG5cbiAgICAgICAgICAgICAgICB2bm9kZSA9IGhhbmRsZVRodW5rKHZub2RlKS5hO1xuXG4gICAgICAgICAgICAgICAgaWYgKGlzV2lkZ2V0KHZub2RlKSkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gdm5vZGUuaW5pdCgpO1xuICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoaXNWVGV4dCh2bm9kZSkpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGRvYy5jcmVhdGVUZXh0Tm9kZSh2bm9kZS50ZXh0KTtcbiAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKCFpc1ZOb2RlKHZub2RlKSkge1xuICAgICAgICAgICAgICAgICAgICBpZiAod2Fybikge1xuICAgICAgICAgICAgICAgICAgICAgICAgd2FybihcIkl0ZW0gaXMgbm90IGEgdmFsaWQgdmlydHVhbCBkb20gbm9kZVwiLCB2bm9kZSk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIG51bGw7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgdmFyIG5vZGUgPSB2bm9kZS5uYW1lc3BhY2UgPT09IG51bGwgPyBkb2MuY3JlYXRlRWxlbWVudCh2bm9kZS50YWdOYW1lKSA6IGRvYy5jcmVhdGVFbGVtZW50TlModm5vZGUubmFtZXNwYWNlLCB2bm9kZS50YWdOYW1lKTtcblxuICAgICAgICAgICAgICAgIHZhciBwcm9wcyA9IHZub2RlLnByb3BlcnRpZXM7XG4gICAgICAgICAgICAgICAgYXBwbHlQcm9wZXJ0aWVzKG5vZGUsIHByb3BzKTtcblxuICAgICAgICAgICAgICAgIHZhciBjaGlsZHJlbiA9IHZub2RlLmNoaWxkcmVuO1xuXG4gICAgICAgICAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCBjaGlsZHJlbi5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgICAgICAgICB2YXIgY2hpbGROb2RlID0gY3JlYXRlRWxlbWVudChjaGlsZHJlbltpXSwgb3B0cyk7XG4gICAgICAgICAgICAgICAgICAgIGlmIChjaGlsZE5vZGUpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIG5vZGUuYXBwZW5kQ2hpbGQoY2hpbGROb2RlKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHJldHVybiBub2RlO1xuICAgICAgICAgICAgfVxuICAgICAgICB9LCB7IFwiLi4vdm5vZGUvaGFuZGxlLXRodW5rLmpzXCI6IDI0LCBcIi4uL3Zub2RlL2lzLXZub2RlLmpzXCI6IDI3LCBcIi4uL3Zub2RlL2lzLXZ0ZXh0LmpzXCI6IDI4LCBcIi4uL3Zub2RlL2lzLXdpZGdldC5qc1wiOiAyOSwgXCIuL2FwcGx5LXByb3BlcnRpZXNcIjogMTQsIFwiZ2xvYmFsL2RvY3VtZW50XCI6IDEwIH1dLCAxNjogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHtcbiAgICAgICAgICAgIC8vIE1hcHMgYSB2aXJ0dWFsIERPTSB0cmVlIG9udG8gYSByZWFsIERPTSB0cmVlIGluIGFuIGVmZmljaWVudCBtYW5uZXIuXG4gICAgICAgICAgICAvLyBXZSBkb24ndCB3YW50IHRvIHJlYWQgYWxsIG9mIHRoZSBET00gbm9kZXMgaW4gdGhlIHRyZWUgc28gd2UgdXNlXG4gICAgICAgICAgICAvLyB0aGUgaW4tb3JkZXIgdHJlZSBpbmRleGluZyB0byBlbGltaW5hdGUgcmVjdXJzaW9uIGRvd24gY2VydGFpbiBicmFuY2hlcy5cbiAgICAgICAgICAgIC8vIFdlIG9ubHkgcmVjdXJzZSBpbnRvIGEgRE9NIG5vZGUgaWYgd2Uga25vdyB0aGF0IGl0IGNvbnRhaW5zIGEgY2hpbGQgb2ZcbiAgICAgICAgICAgIC8vIGludGVyZXN0LlxuXG4gICAgICAgICAgICB2YXIgbm9DaGlsZCA9IHt9O1xuXG4gICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IGRvbUluZGV4O1xuXG4gICAgICAgICAgICBmdW5jdGlvbiBkb21JbmRleChyb290Tm9kZSwgdHJlZSwgaW5kaWNlcywgbm9kZXMpIHtcbiAgICAgICAgICAgICAgICBpZiAoIWluZGljZXMgfHwgaW5kaWNlcy5sZW5ndGggPT09IDApIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHt9O1xuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIGluZGljZXMuc29ydChhc2NlbmRpbmcpO1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gcmVjdXJzZShyb290Tm9kZSwgdHJlZSwgaW5kaWNlcywgbm9kZXMsIDApO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZnVuY3Rpb24gcmVjdXJzZShyb290Tm9kZSwgdHJlZSwgaW5kaWNlcywgbm9kZXMsIHJvb3RJbmRleCkge1xuICAgICAgICAgICAgICAgIG5vZGVzID0gbm9kZXMgfHwge307XG5cbiAgICAgICAgICAgICAgICBpZiAocm9vdE5vZGUpIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKGluZGV4SW5SYW5nZShpbmRpY2VzLCByb290SW5kZXgsIHJvb3RJbmRleCkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIG5vZGVzW3Jvb3RJbmRleF0gPSByb290Tm9kZTtcbiAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgIHZhciB2Q2hpbGRyZW4gPSB0cmVlLmNoaWxkcmVuO1xuXG4gICAgICAgICAgICAgICAgICAgIGlmICh2Q2hpbGRyZW4pIHtcblxuICAgICAgICAgICAgICAgICAgICAgICAgdmFyIGNoaWxkTm9kZXMgPSByb290Tm9kZS5jaGlsZE5vZGVzO1xuXG4gICAgICAgICAgICAgICAgICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IHRyZWUuY2hpbGRyZW4ubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICByb290SW5kZXggKz0gMTtcblxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZhciB2Q2hpbGQgPSB2Q2hpbGRyZW5baV0gfHwgbm9DaGlsZDtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB2YXIgbmV4dEluZGV4ID0gcm9vdEluZGV4ICsgKHZDaGlsZC5jb3VudCB8fCAwKTtcblxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIHNraXAgcmVjdXJzaW9uIGRvd24gdGhlIHRyZWUgaWYgdGhlcmUgYXJlIG5vIG5vZGVzIGRvd24gaGVyZVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChpbmRleEluUmFuZ2UoaW5kaWNlcywgcm9vdEluZGV4LCBuZXh0SW5kZXgpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlY3Vyc2UoY2hpbGROb2Rlc1tpXSwgdkNoaWxkLCBpbmRpY2VzLCBub2Rlcywgcm9vdEluZGV4KTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICByb290SW5kZXggPSBuZXh0SW5kZXg7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICByZXR1cm4gbm9kZXM7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIC8vIEJpbmFyeSBzZWFyY2ggZm9yIGFuIGluZGV4IGluIHRoZSBpbnRlcnZhbCBbbGVmdCwgcmlnaHRdXG4gICAgICAgICAgICBmdW5jdGlvbiBpbmRleEluUmFuZ2UoaW5kaWNlcywgbGVmdCwgcmlnaHQpIHtcbiAgICAgICAgICAgICAgICBpZiAoaW5kaWNlcy5sZW5ndGggPT09IDApIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHZhciBtaW5JbmRleCA9IDA7XG4gICAgICAgICAgICAgICAgdmFyIG1heEluZGV4ID0gaW5kaWNlcy5sZW5ndGggLSAxO1xuICAgICAgICAgICAgICAgIHZhciBjdXJyZW50SW5kZXg7XG4gICAgICAgICAgICAgICAgdmFyIGN1cnJlbnRJdGVtO1xuXG4gICAgICAgICAgICAgICAgd2hpbGUgKG1pbkluZGV4IDw9IG1heEluZGV4KSB7XG4gICAgICAgICAgICAgICAgICAgIGN1cnJlbnRJbmRleCA9IChtYXhJbmRleCArIG1pbkluZGV4KSAvIDIgPj4gMDtcbiAgICAgICAgICAgICAgICAgICAgY3VycmVudEl0ZW0gPSBpbmRpY2VzW2N1cnJlbnRJbmRleF07XG5cbiAgICAgICAgICAgICAgICAgICAgaWYgKG1pbkluZGV4ID09PSBtYXhJbmRleCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGN1cnJlbnRJdGVtID49IGxlZnQgJiYgY3VycmVudEl0ZW0gPD0gcmlnaHQ7XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoY3VycmVudEl0ZW0gPCBsZWZ0KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBtaW5JbmRleCA9IGN1cnJlbnRJbmRleCArIDE7XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoY3VycmVudEl0ZW0gPiByaWdodCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgbWF4SW5kZXggPSBjdXJyZW50SW5kZXggLSAxO1xuICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIGFzY2VuZGluZyhhLCBiKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGEgPiBiID8gMSA6IC0xO1xuICAgICAgICAgICAgfVxuICAgICAgICB9LCB7fV0sIDE3OiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge1xuICAgICAgICAgICAgdmFyIGFwcGx5UHJvcGVydGllcyA9IHJlcXVpcmUoXCIuL2FwcGx5LXByb3BlcnRpZXNcIik7XG5cbiAgICAgICAgICAgIHZhciBpc1dpZGdldCA9IHJlcXVpcmUoXCIuLi92bm9kZS9pcy13aWRnZXQuanNcIik7XG4gICAgICAgICAgICB2YXIgVlBhdGNoID0gcmVxdWlyZShcIi4uL3Zub2RlL3ZwYXRjaC5qc1wiKTtcblxuICAgICAgICAgICAgdmFyIHVwZGF0ZVdpZGdldCA9IHJlcXVpcmUoXCIuL3VwZGF0ZS13aWRnZXRcIik7XG5cbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gYXBwbHlQYXRjaDtcblxuICAgICAgICAgICAgZnVuY3Rpb24gYXBwbHlQYXRjaCh2cGF0Y2gsIGRvbU5vZGUsIHJlbmRlck9wdGlvbnMpIHtcbiAgICAgICAgICAgICAgICB2YXIgdHlwZSA9IHZwYXRjaC50eXBlO1xuICAgICAgICAgICAgICAgIHZhciB2Tm9kZSA9IHZwYXRjaC52Tm9kZTtcbiAgICAgICAgICAgICAgICB2YXIgcGF0Y2ggPSB2cGF0Y2gucGF0Y2g7XG5cbiAgICAgICAgICAgICAgICBzd2l0Y2ggKHR5cGUpIHtcbiAgICAgICAgICAgICAgICAgICAgY2FzZSBWUGF0Y2guUkVNT1ZFOlxuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHJlbW92ZU5vZGUoZG9tTm9kZSwgdk5vZGUpO1xuICAgICAgICAgICAgICAgICAgICBjYXNlIFZQYXRjaC5JTlNFUlQ6XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gaW5zZXJ0Tm9kZShkb21Ob2RlLCBwYXRjaCwgcmVuZGVyT3B0aW9ucyk7XG4gICAgICAgICAgICAgICAgICAgIGNhc2UgVlBhdGNoLlZURVhUOlxuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHN0cmluZ1BhdGNoKGRvbU5vZGUsIHZOb2RlLCBwYXRjaCwgcmVuZGVyT3B0aW9ucyk7XG4gICAgICAgICAgICAgICAgICAgIGNhc2UgVlBhdGNoLldJREdFVDpcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiB3aWRnZXRQYXRjaChkb21Ob2RlLCB2Tm9kZSwgcGF0Y2gsIHJlbmRlck9wdGlvbnMpO1xuICAgICAgICAgICAgICAgICAgICBjYXNlIFZQYXRjaC5WTk9ERTpcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiB2Tm9kZVBhdGNoKGRvbU5vZGUsIHZOb2RlLCBwYXRjaCwgcmVuZGVyT3B0aW9ucyk7XG4gICAgICAgICAgICAgICAgICAgIGNhc2UgVlBhdGNoLk9SREVSOlxuICAgICAgICAgICAgICAgICAgICAgICAgcmVvcmRlckNoaWxkcmVuKGRvbU5vZGUsIHBhdGNoKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBkb21Ob2RlO1xuICAgICAgICAgICAgICAgICAgICBjYXNlIFZQYXRjaC5QUk9QUzpcbiAgICAgICAgICAgICAgICAgICAgICAgIGFwcGx5UHJvcGVydGllcyhkb21Ob2RlLCBwYXRjaCwgdk5vZGUucHJvcGVydGllcyk7XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gZG9tTm9kZTtcbiAgICAgICAgICAgICAgICAgICAgY2FzZSBWUGF0Y2guVEhVTks6XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gcmVwbGFjZVJvb3QoZG9tTm9kZSwgcmVuZGVyT3B0aW9ucy5wYXRjaChkb21Ob2RlLCBwYXRjaCwgcmVuZGVyT3B0aW9ucykpO1xuICAgICAgICAgICAgICAgICAgICBkZWZhdWx0OlxuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGRvbU5vZGU7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBmdW5jdGlvbiByZW1vdmVOb2RlKGRvbU5vZGUsIHZOb2RlKSB7XG4gICAgICAgICAgICAgICAgdmFyIHBhcmVudE5vZGUgPSBkb21Ob2RlLnBhcmVudE5vZGU7XG5cbiAgICAgICAgICAgICAgICBpZiAocGFyZW50Tm9kZSkge1xuICAgICAgICAgICAgICAgICAgICBwYXJlbnROb2RlLnJlbW92ZUNoaWxkKGRvbU5vZGUpO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIGRlc3Ryb3lXaWRnZXQoZG9tTm9kZSwgdk5vZGUpO1xuXG4gICAgICAgICAgICAgICAgcmV0dXJuIG51bGw7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIGluc2VydE5vZGUocGFyZW50Tm9kZSwgdk5vZGUsIHJlbmRlck9wdGlvbnMpIHtcbiAgICAgICAgICAgICAgICB2YXIgbmV3Tm9kZSA9IHJlbmRlck9wdGlvbnMucmVuZGVyKHZOb2RlLCByZW5kZXJPcHRpb25zKTtcblxuICAgICAgICAgICAgICAgIGlmIChwYXJlbnROb2RlKSB7XG4gICAgICAgICAgICAgICAgICAgIHBhcmVudE5vZGUuYXBwZW5kQ2hpbGQobmV3Tm9kZSk7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgcmV0dXJuIHBhcmVudE5vZGU7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIHN0cmluZ1BhdGNoKGRvbU5vZGUsIGxlZnRWTm9kZSwgdlRleHQsIHJlbmRlck9wdGlvbnMpIHtcbiAgICAgICAgICAgICAgICB2YXIgbmV3Tm9kZTtcblxuICAgICAgICAgICAgICAgIGlmIChkb21Ob2RlLm5vZGVUeXBlID09PSAzKSB7XG4gICAgICAgICAgICAgICAgICAgIGRvbU5vZGUucmVwbGFjZURhdGEoMCwgZG9tTm9kZS5sZW5ndGgsIHZUZXh0LnRleHQpO1xuICAgICAgICAgICAgICAgICAgICBuZXdOb2RlID0gZG9tTm9kZTtcbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICB2YXIgcGFyZW50Tm9kZSA9IGRvbU5vZGUucGFyZW50Tm9kZTtcbiAgICAgICAgICAgICAgICAgICAgbmV3Tm9kZSA9IHJlbmRlck9wdGlvbnMucmVuZGVyKHZUZXh0LCByZW5kZXJPcHRpb25zKTtcblxuICAgICAgICAgICAgICAgICAgICBpZiAocGFyZW50Tm9kZSAmJiBuZXdOb2RlICE9PSBkb21Ob2RlKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBwYXJlbnROb2RlLnJlcGxhY2VDaGlsZChuZXdOb2RlLCBkb21Ob2RlKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHJldHVybiBuZXdOb2RlO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBmdW5jdGlvbiB3aWRnZXRQYXRjaChkb21Ob2RlLCBsZWZ0Vk5vZGUsIHdpZGdldCwgcmVuZGVyT3B0aW9ucykge1xuICAgICAgICAgICAgICAgIHZhciB1cGRhdGluZyA9IHVwZGF0ZVdpZGdldChsZWZ0Vk5vZGUsIHdpZGdldCk7XG4gICAgICAgICAgICAgICAgdmFyIG5ld05vZGU7XG5cbiAgICAgICAgICAgICAgICBpZiAodXBkYXRpbmcpIHtcbiAgICAgICAgICAgICAgICAgICAgbmV3Tm9kZSA9IHdpZGdldC51cGRhdGUobGVmdFZOb2RlLCBkb21Ob2RlKSB8fCBkb21Ob2RlO1xuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIG5ld05vZGUgPSByZW5kZXJPcHRpb25zLnJlbmRlcih3aWRnZXQsIHJlbmRlck9wdGlvbnMpO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHZhciBwYXJlbnROb2RlID0gZG9tTm9kZS5wYXJlbnROb2RlO1xuXG4gICAgICAgICAgICAgICAgaWYgKHBhcmVudE5vZGUgJiYgbmV3Tm9kZSAhPT0gZG9tTm9kZSkge1xuICAgICAgICAgICAgICAgICAgICBwYXJlbnROb2RlLnJlcGxhY2VDaGlsZChuZXdOb2RlLCBkb21Ob2RlKTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICBpZiAoIXVwZGF0aW5nKSB7XG4gICAgICAgICAgICAgICAgICAgIGRlc3Ryb3lXaWRnZXQoZG9tTm9kZSwgbGVmdFZOb2RlKTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICByZXR1cm4gbmV3Tm9kZTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZnVuY3Rpb24gdk5vZGVQYXRjaChkb21Ob2RlLCBsZWZ0Vk5vZGUsIHZOb2RlLCByZW5kZXJPcHRpb25zKSB7XG4gICAgICAgICAgICAgICAgdmFyIHBhcmVudE5vZGUgPSBkb21Ob2RlLnBhcmVudE5vZGU7XG4gICAgICAgICAgICAgICAgdmFyIG5ld05vZGUgPSByZW5kZXJPcHRpb25zLnJlbmRlcih2Tm9kZSwgcmVuZGVyT3B0aW9ucyk7XG5cbiAgICAgICAgICAgICAgICBpZiAocGFyZW50Tm9kZSAmJiBuZXdOb2RlICE9PSBkb21Ob2RlKSB7XG4gICAgICAgICAgICAgICAgICAgIHBhcmVudE5vZGUucmVwbGFjZUNoaWxkKG5ld05vZGUsIGRvbU5vZGUpO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHJldHVybiBuZXdOb2RlO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBmdW5jdGlvbiBkZXN0cm95V2lkZ2V0KGRvbU5vZGUsIHcpIHtcbiAgICAgICAgICAgICAgICBpZiAodHlwZW9mIHcuZGVzdHJveSA9PT0gXCJmdW5jdGlvblwiICYmIGlzV2lkZ2V0KHcpKSB7XG4gICAgICAgICAgICAgICAgICAgIHcuZGVzdHJveShkb21Ob2RlKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIHJlb3JkZXJDaGlsZHJlbihkb21Ob2RlLCBtb3Zlcykge1xuICAgICAgICAgICAgICAgIHZhciBjaGlsZE5vZGVzID0gZG9tTm9kZS5jaGlsZE5vZGVzO1xuICAgICAgICAgICAgICAgIHZhciBrZXlNYXAgPSB7fTtcbiAgICAgICAgICAgICAgICB2YXIgbm9kZTtcbiAgICAgICAgICAgICAgICB2YXIgcmVtb3ZlO1xuICAgICAgICAgICAgICAgIHZhciBpbnNlcnQ7XG5cbiAgICAgICAgICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IG1vdmVzLnJlbW92ZXMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgICAgICAgICAgcmVtb3ZlID0gbW92ZXMucmVtb3Zlc1tpXTtcbiAgICAgICAgICAgICAgICAgICAgbm9kZSA9IGNoaWxkTm9kZXNbcmVtb3ZlLmZyb21dO1xuICAgICAgICAgICAgICAgICAgICBpZiAocmVtb3ZlLmtleSkge1xuICAgICAgICAgICAgICAgICAgICAgICAga2V5TWFwW3JlbW92ZS5rZXldID0gbm9kZTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICBkb21Ob2RlLnJlbW92ZUNoaWxkKG5vZGUpO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHZhciBsZW5ndGggPSBjaGlsZE5vZGVzLmxlbmd0aDtcbiAgICAgICAgICAgICAgICBmb3IgKHZhciBqID0gMDsgaiA8IG1vdmVzLmluc2VydHMubGVuZ3RoOyBqKyspIHtcbiAgICAgICAgICAgICAgICAgICAgaW5zZXJ0ID0gbW92ZXMuaW5zZXJ0c1tqXTtcbiAgICAgICAgICAgICAgICAgICAgbm9kZSA9IGtleU1hcFtpbnNlcnQua2V5XTtcbiAgICAgICAgICAgICAgICAgICAgLy8gdGhpcyBpcyB0aGUgd2VpcmRlc3QgYnVnIGkndmUgZXZlciBzZWVuIGluIHdlYmtpdFxuICAgICAgICAgICAgICAgICAgICBkb21Ob2RlLmluc2VydEJlZm9yZShub2RlLCBpbnNlcnQudG8gPj0gbGVuZ3RoKysgPyBudWxsIDogY2hpbGROb2Rlc1tpbnNlcnQudG9dKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIHJlcGxhY2VSb290KG9sZFJvb3QsIG5ld1Jvb3QpIHtcbiAgICAgICAgICAgICAgICBpZiAob2xkUm9vdCAmJiBuZXdSb290ICYmIG9sZFJvb3QgIT09IG5ld1Jvb3QgJiYgb2xkUm9vdC5wYXJlbnROb2RlKSB7XG4gICAgICAgICAgICAgICAgICAgIG9sZFJvb3QucGFyZW50Tm9kZS5yZXBsYWNlQ2hpbGQobmV3Um9vdCwgb2xkUm9vdCk7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgcmV0dXJuIG5ld1Jvb3Q7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0sIHsgXCIuLi92bm9kZS9pcy13aWRnZXQuanNcIjogMjksIFwiLi4vdm5vZGUvdnBhdGNoLmpzXCI6IDMyLCBcIi4vYXBwbHktcHJvcGVydGllc1wiOiAxNCwgXCIuL3VwZGF0ZS13aWRnZXRcIjogMTkgfV0sIDE4OiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge1xuICAgICAgICAgICAgdmFyIGRvY3VtZW50ID0gcmVxdWlyZShcImdsb2JhbC9kb2N1bWVudFwiKTtcbiAgICAgICAgICAgIHZhciBpc0FycmF5ID0gcmVxdWlyZShcIngtaXMtYXJyYXlcIik7XG5cbiAgICAgICAgICAgIHZhciByZW5kZXIgPSByZXF1aXJlKFwiLi9jcmVhdGUtZWxlbWVudFwiKTtcbiAgICAgICAgICAgIHZhciBkb21JbmRleCA9IHJlcXVpcmUoXCIuL2RvbS1pbmRleFwiKTtcbiAgICAgICAgICAgIHZhciBwYXRjaE9wID0gcmVxdWlyZShcIi4vcGF0Y2gtb3BcIik7XG4gICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IHBhdGNoO1xuXG4gICAgICAgICAgICBmdW5jdGlvbiBwYXRjaChyb290Tm9kZSwgcGF0Y2hlcywgcmVuZGVyT3B0aW9ucykge1xuICAgICAgICAgICAgICAgIHJlbmRlck9wdGlvbnMgPSByZW5kZXJPcHRpb25zIHx8IHt9O1xuICAgICAgICAgICAgICAgIHJlbmRlck9wdGlvbnMucGF0Y2ggPSByZW5kZXJPcHRpb25zLnBhdGNoICYmIHJlbmRlck9wdGlvbnMucGF0Y2ggIT09IHBhdGNoID8gcmVuZGVyT3B0aW9ucy5wYXRjaCA6IHBhdGNoUmVjdXJzaXZlO1xuICAgICAgICAgICAgICAgIHJlbmRlck9wdGlvbnMucmVuZGVyID0gcmVuZGVyT3B0aW9ucy5yZW5kZXIgfHwgcmVuZGVyO1xuXG4gICAgICAgICAgICAgICAgcmV0dXJuIHJlbmRlck9wdGlvbnMucGF0Y2gocm9vdE5vZGUsIHBhdGNoZXMsIHJlbmRlck9wdGlvbnMpO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBmdW5jdGlvbiBwYXRjaFJlY3Vyc2l2ZShyb290Tm9kZSwgcGF0Y2hlcywgcmVuZGVyT3B0aW9ucykge1xuICAgICAgICAgICAgICAgIHZhciBpbmRpY2VzID0gcGF0Y2hJbmRpY2VzKHBhdGNoZXMpO1xuXG4gICAgICAgICAgICAgICAgaWYgKGluZGljZXMubGVuZ3RoID09PSAwKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiByb290Tm9kZTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICB2YXIgaW5kZXggPSBkb21JbmRleChyb290Tm9kZSwgcGF0Y2hlcy5hLCBpbmRpY2VzKTtcbiAgICAgICAgICAgICAgICB2YXIgb3duZXJEb2N1bWVudCA9IHJvb3ROb2RlLm93bmVyRG9jdW1lbnQ7XG5cbiAgICAgICAgICAgICAgICBpZiAoIXJlbmRlck9wdGlvbnMuZG9jdW1lbnQgJiYgb3duZXJEb2N1bWVudCAhPT0gZG9jdW1lbnQpIHtcbiAgICAgICAgICAgICAgICAgICAgcmVuZGVyT3B0aW9ucy5kb2N1bWVudCA9IG93bmVyRG9jdW1lbnQ7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCBpbmRpY2VzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciBub2RlSW5kZXggPSBpbmRpY2VzW2ldO1xuICAgICAgICAgICAgICAgICAgICByb290Tm9kZSA9IGFwcGx5UGF0Y2gocm9vdE5vZGUsIGluZGV4W25vZGVJbmRleF0sIHBhdGNoZXNbbm9kZUluZGV4XSwgcmVuZGVyT3B0aW9ucyk7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgcmV0dXJuIHJvb3ROb2RlO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBmdW5jdGlvbiBhcHBseVBhdGNoKHJvb3ROb2RlLCBkb21Ob2RlLCBwYXRjaExpc3QsIHJlbmRlck9wdGlvbnMpIHtcbiAgICAgICAgICAgICAgICBpZiAoIWRvbU5vZGUpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHJvb3ROb2RlO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHZhciBuZXdOb2RlO1xuXG4gICAgICAgICAgICAgICAgaWYgKGlzQXJyYXkocGF0Y2hMaXN0KSkge1xuICAgICAgICAgICAgICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IHBhdGNoTGlzdC5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgICAgICAgICAgICAgbmV3Tm9kZSA9IHBhdGNoT3AocGF0Y2hMaXN0W2ldLCBkb21Ob2RlLCByZW5kZXJPcHRpb25zKTtcblxuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGRvbU5vZGUgPT09IHJvb3ROb2RlKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcm9vdE5vZGUgPSBuZXdOb2RlO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgbmV3Tm9kZSA9IHBhdGNoT3AocGF0Y2hMaXN0LCBkb21Ob2RlLCByZW5kZXJPcHRpb25zKTtcblxuICAgICAgICAgICAgICAgICAgICBpZiAoZG9tTm9kZSA9PT0gcm9vdE5vZGUpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJvb3ROb2RlID0gbmV3Tm9kZTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHJldHVybiByb290Tm9kZTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZnVuY3Rpb24gcGF0Y2hJbmRpY2VzKHBhdGNoZXMpIHtcbiAgICAgICAgICAgICAgICB2YXIgaW5kaWNlcyA9IFtdO1xuXG4gICAgICAgICAgICAgICAgZm9yICh2YXIga2V5IGluIHBhdGNoZXMpIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKGtleSAhPT0gXCJhXCIpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGluZGljZXMucHVzaChOdW1iZXIoa2V5KSk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICByZXR1cm4gaW5kaWNlcztcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSwgeyBcIi4vY3JlYXRlLWVsZW1lbnRcIjogMTUsIFwiLi9kb20taW5kZXhcIjogMTYsIFwiLi9wYXRjaC1vcFwiOiAxNywgXCJnbG9iYWwvZG9jdW1lbnRcIjogMTAsIFwieC1pcy1hcnJheVwiOiAxMiB9XSwgMTk6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICB2YXIgaXNXaWRnZXQgPSByZXF1aXJlKFwiLi4vdm5vZGUvaXMtd2lkZ2V0LmpzXCIpO1xuXG4gICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IHVwZGF0ZVdpZGdldDtcblxuICAgICAgICAgICAgZnVuY3Rpb24gdXBkYXRlV2lkZ2V0KGEsIGIpIHtcbiAgICAgICAgICAgICAgICBpZiAoaXNXaWRnZXQoYSkgJiYgaXNXaWRnZXQoYikpIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKFwibmFtZVwiIGluIGEgJiYgXCJuYW1lXCIgaW4gYikge1xuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGEuaWQgPT09IGIuaWQ7XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gYS5pbml0ID09PSBiLmluaXQ7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0sIHsgXCIuLi92bm9kZS9pcy13aWRnZXQuanNcIjogMjkgfV0sIDIwOiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge1xuICAgICAgICAgICAgXCJ1c2Ugc3RyaWN0XCI7XG5cbiAgICAgICAgICAgIHZhciBFdlN0b3JlID0gcmVxdWlyZShcImV2LXN0b3JlXCIpO1xuXG4gICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IEV2SG9vaztcblxuICAgICAgICAgICAgZnVuY3Rpb24gRXZIb29rKHZhbHVlKSB7XG4gICAgICAgICAgICAgICAgaWYgKCEodGhpcyBpbnN0YW5jZW9mIEV2SG9vaykpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIG5ldyBFdkhvb2sodmFsdWUpO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHRoaXMudmFsdWUgPSB2YWx1ZTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgRXZIb29rLnByb3RvdHlwZS5ob29rID0gZnVuY3Rpb24gKG5vZGUsIHByb3BlcnR5TmFtZSkge1xuICAgICAgICAgICAgICAgIHZhciBlcyA9IEV2U3RvcmUobm9kZSk7XG4gICAgICAgICAgICAgICAgdmFyIHByb3BOYW1lID0gcHJvcGVydHlOYW1lLnN1YnN0cigzKTtcblxuICAgICAgICAgICAgICAgIGVzW3Byb3BOYW1lXSA9IHRoaXMudmFsdWU7XG4gICAgICAgICAgICB9O1xuXG4gICAgICAgICAgICBFdkhvb2sucHJvdG90eXBlLnVuaG9vayA9IGZ1bmN0aW9uIChub2RlLCBwcm9wZXJ0eU5hbWUpIHtcbiAgICAgICAgICAgICAgICB2YXIgZXMgPSBFdlN0b3JlKG5vZGUpO1xuICAgICAgICAgICAgICAgIHZhciBwcm9wTmFtZSA9IHByb3BlcnR5TmFtZS5zdWJzdHIoMyk7XG5cbiAgICAgICAgICAgICAgICBlc1twcm9wTmFtZV0gPSB1bmRlZmluZWQ7XG4gICAgICAgICAgICB9O1xuICAgICAgICB9LCB7IFwiZXYtc3RvcmVcIjogNyB9XSwgMjE6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICBcInVzZSBzdHJpY3RcIjtcblxuICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBTb2Z0U2V0SG9vaztcblxuICAgICAgICAgICAgZnVuY3Rpb24gU29mdFNldEhvb2sodmFsdWUpIHtcbiAgICAgICAgICAgICAgICBpZiAoISh0aGlzIGluc3RhbmNlb2YgU29mdFNldEhvb2spKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBuZXcgU29mdFNldEhvb2sodmFsdWUpO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHRoaXMudmFsdWUgPSB2YWx1ZTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgU29mdFNldEhvb2sucHJvdG90eXBlLmhvb2sgPSBmdW5jdGlvbiAobm9kZSwgcHJvcGVydHlOYW1lKSB7XG4gICAgICAgICAgICAgICAgaWYgKG5vZGVbcHJvcGVydHlOYW1lXSAhPT0gdGhpcy52YWx1ZSkge1xuICAgICAgICAgICAgICAgICAgICBub2RlW3Byb3BlcnR5TmFtZV0gPSB0aGlzLnZhbHVlO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH07XG4gICAgICAgIH0sIHt9XSwgMjI6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICBcInVzZSBzdHJpY3RcIjtcblxuICAgICAgICAgICAgdmFyIGlzQXJyYXkgPSByZXF1aXJlKFwieC1pcy1hcnJheVwiKTtcblxuICAgICAgICAgICAgdmFyIFZOb2RlID0gcmVxdWlyZShcIi4uL3Zub2RlL3Zub2RlLmpzXCIpO1xuICAgICAgICAgICAgdmFyIFZUZXh0ID0gcmVxdWlyZShcIi4uL3Zub2RlL3Z0ZXh0LmpzXCIpO1xuICAgICAgICAgICAgdmFyIGlzVk5vZGUgPSByZXF1aXJlKFwiLi4vdm5vZGUvaXMtdm5vZGVcIik7XG4gICAgICAgICAgICB2YXIgaXNWVGV4dCA9IHJlcXVpcmUoXCIuLi92bm9kZS9pcy12dGV4dFwiKTtcbiAgICAgICAgICAgIHZhciBpc1dpZGdldCA9IHJlcXVpcmUoXCIuLi92bm9kZS9pcy13aWRnZXRcIik7XG4gICAgICAgICAgICB2YXIgaXNIb29rID0gcmVxdWlyZShcIi4uL3Zub2RlL2lzLXZob29rXCIpO1xuICAgICAgICAgICAgdmFyIGlzVlRodW5rID0gcmVxdWlyZShcIi4uL3Zub2RlL2lzLXRodW5rXCIpO1xuXG4gICAgICAgICAgICB2YXIgcGFyc2VUYWcgPSByZXF1aXJlKFwiLi9wYXJzZS10YWcuanNcIik7XG4gICAgICAgICAgICB2YXIgc29mdFNldEhvb2sgPSByZXF1aXJlKFwiLi9ob29rcy9zb2Z0LXNldC1ob29rLmpzXCIpO1xuICAgICAgICAgICAgdmFyIGV2SG9vayA9IHJlcXVpcmUoXCIuL2hvb2tzL2V2LWhvb2suanNcIik7XG5cbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gaDtcblxuICAgICAgICAgICAgZnVuY3Rpb24gaCh0YWdOYW1lLCBwcm9wZXJ0aWVzLCBjaGlsZHJlbikge1xuICAgICAgICAgICAgICAgIHZhciBjaGlsZE5vZGVzID0gW107XG4gICAgICAgICAgICAgICAgdmFyIHRhZywgcHJvcHMsIGtleSwgbmFtZXNwYWNlO1xuXG4gICAgICAgICAgICAgICAgaWYgKCFjaGlsZHJlbiAmJiBpc0NoaWxkcmVuKHByb3BlcnRpZXMpKSB7XG4gICAgICAgICAgICAgICAgICAgIGNoaWxkcmVuID0gcHJvcGVydGllcztcbiAgICAgICAgICAgICAgICAgICAgcHJvcHMgPSB7fTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICBwcm9wcyA9IHByb3BzIHx8IHByb3BlcnRpZXMgfHwge307XG4gICAgICAgICAgICAgICAgdGFnID0gcGFyc2VUYWcodGFnTmFtZSwgcHJvcHMpO1xuXG4gICAgICAgICAgICAgICAgLy8gc3VwcG9ydCBrZXlzXG4gICAgICAgICAgICAgICAgaWYgKHByb3BzLmhhc093blByb3BlcnR5KFwia2V5XCIpKSB7XG4gICAgICAgICAgICAgICAgICAgIGtleSA9IHByb3BzLmtleTtcbiAgICAgICAgICAgICAgICAgICAgcHJvcHMua2V5ID0gdW5kZWZpbmVkO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIC8vIHN1cHBvcnQgbmFtZXNwYWNlXG4gICAgICAgICAgICAgICAgaWYgKHByb3BzLmhhc093blByb3BlcnR5KFwibmFtZXNwYWNlXCIpKSB7XG4gICAgICAgICAgICAgICAgICAgIG5hbWVzcGFjZSA9IHByb3BzLm5hbWVzcGFjZTtcbiAgICAgICAgICAgICAgICAgICAgcHJvcHMubmFtZXNwYWNlID0gdW5kZWZpbmVkO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIC8vIGZpeCBjdXJzb3IgYnVnXG4gICAgICAgICAgICAgICAgaWYgKHRhZyA9PT0gXCJJTlBVVFwiICYmICFuYW1lc3BhY2UgJiYgcHJvcHMuaGFzT3duUHJvcGVydHkoXCJ2YWx1ZVwiKSAmJiBwcm9wcy52YWx1ZSAhPT0gdW5kZWZpbmVkICYmICFpc0hvb2socHJvcHMudmFsdWUpKSB7XG4gICAgICAgICAgICAgICAgICAgIHByb3BzLnZhbHVlID0gc29mdFNldEhvb2socHJvcHMudmFsdWUpO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHRyYW5zZm9ybVByb3BlcnRpZXMocHJvcHMpO1xuXG4gICAgICAgICAgICAgICAgaWYgKGNoaWxkcmVuICE9PSB1bmRlZmluZWQgJiYgY2hpbGRyZW4gIT09IG51bGwpIHtcbiAgICAgICAgICAgICAgICAgICAgYWRkQ2hpbGQoY2hpbGRyZW4sIGNoaWxkTm9kZXMsIHRhZywgcHJvcHMpO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHJldHVybiBuZXcgVk5vZGUodGFnLCBwcm9wcywgY2hpbGROb2Rlcywga2V5LCBuYW1lc3BhY2UpO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBmdW5jdGlvbiBhZGRDaGlsZChjLCBjaGlsZE5vZGVzLCB0YWcsIHByb3BzKSB7XG4gICAgICAgICAgICAgICAgaWYgKHR5cGVvZiBjID09PSBcInN0cmluZ1wiKSB7XG4gICAgICAgICAgICAgICAgICAgIGNoaWxkTm9kZXMucHVzaChuZXcgVlRleHQoYykpO1xuICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAodHlwZW9mIGMgPT09IFwibnVtYmVyXCIpIHtcbiAgICAgICAgICAgICAgICAgICAgY2hpbGROb2Rlcy5wdXNoKG5ldyBWVGV4dChTdHJpbmcoYykpKTtcbiAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKGlzQ2hpbGQoYykpIHtcbiAgICAgICAgICAgICAgICAgICAgY2hpbGROb2Rlcy5wdXNoKGMpO1xuICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoaXNBcnJheShjKSkge1xuICAgICAgICAgICAgICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IGMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGFkZENoaWxkKGNbaV0sIGNoaWxkTm9kZXMsIHRhZywgcHJvcHMpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfSBlbHNlIGlmIChjID09PSBudWxsIHx8IGMgPT09IHVuZGVmaW5lZCkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgdGhyb3cgVW5leHBlY3RlZFZpcnR1YWxFbGVtZW50KHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGZvcmVpZ25PYmplY3Q6IGMsXG4gICAgICAgICAgICAgICAgICAgICAgICBwYXJlbnRWbm9kZToge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRhZ05hbWU6IHRhZyxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBwcm9wZXJ0aWVzOiBwcm9wc1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIHRyYW5zZm9ybVByb3BlcnRpZXMocHJvcHMpIHtcbiAgICAgICAgICAgICAgICBmb3IgKHZhciBwcm9wTmFtZSBpbiBwcm9wcykge1xuICAgICAgICAgICAgICAgICAgICBpZiAocHJvcHMuaGFzT3duUHJvcGVydHkocHJvcE5hbWUpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICB2YXIgdmFsdWUgPSBwcm9wc1twcm9wTmFtZV07XG5cbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChpc0hvb2sodmFsdWUpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgY29udGludWU7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChwcm9wTmFtZS5zdWJzdHIoMCwgMykgPT09IFwiZXYtXCIpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBhZGQgZXYtZm9vIHN1cHBvcnRcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBwcm9wc1twcm9wTmFtZV0gPSBldkhvb2sodmFsdWUpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBmdW5jdGlvbiBpc0NoaWxkKHgpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gaXNWTm9kZSh4KSB8fCBpc1ZUZXh0KHgpIHx8IGlzV2lkZ2V0KHgpIHx8IGlzVlRodW5rKHgpO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBmdW5jdGlvbiBpc0NoaWxkcmVuKHgpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gdHlwZW9mIHggPT09IFwic3RyaW5nXCIgfHwgaXNBcnJheSh4KSB8fCBpc0NoaWxkKHgpO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBmdW5jdGlvbiBVbmV4cGVjdGVkVmlydHVhbEVsZW1lbnQoZGF0YSkge1xuICAgICAgICAgICAgICAgIHZhciBlcnIgPSBuZXcgRXJyb3IoKTtcblxuICAgICAgICAgICAgICAgIGVyci50eXBlID0gXCJ2aXJ0dWFsLWh5cGVyc2NyaXB0LnVuZXhwZWN0ZWQudmlydHVhbC1lbGVtZW50XCI7XG4gICAgICAgICAgICAgICAgZXJyLm1lc3NhZ2UgPSBcIlVuZXhwZWN0ZWQgdmlydHVhbCBjaGlsZCBwYXNzZWQgdG8gaCgpLlxcblwiICsgXCJFeHBlY3RlZCBhIFZOb2RlIC8gVnRodW5rIC8gVldpZGdldCAvIHN0cmluZyBidXQ6XFxuXCIgKyBcImdvdDpcXG5cIiArIGVycm9yU3RyaW5nKGRhdGEuZm9yZWlnbk9iamVjdCkgKyBcIi5cXG5cIiArIFwiVGhlIHBhcmVudCB2bm9kZSBpczpcXG5cIiArIGVycm9yU3RyaW5nKGRhdGEucGFyZW50Vm5vZGUpO1xuICAgICAgICAgICAgICAgIFwiXFxuXCIgKyBcIlN1Z2dlc3RlZCBmaXg6IGNoYW5nZSB5b3VyIGBoKC4uLiwgWyAuLi4gXSlgIGNhbGxzaXRlLlwiO1xuICAgICAgICAgICAgICAgIGVyci5mb3JlaWduT2JqZWN0ID0gZGF0YS5mb3JlaWduT2JqZWN0O1xuICAgICAgICAgICAgICAgIGVyci5wYXJlbnRWbm9kZSA9IGRhdGEucGFyZW50Vm5vZGU7XG5cbiAgICAgICAgICAgICAgICByZXR1cm4gZXJyO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBmdW5jdGlvbiBlcnJvclN0cmluZyhvYmopIHtcbiAgICAgICAgICAgICAgICB0cnkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gSlNPTi5zdHJpbmdpZnkob2JqLCBudWxsLCBcIiAgICBcIik7XG4gICAgICAgICAgICAgICAgfSBjYXRjaCAoZSkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gU3RyaW5nKG9iaik7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9LCB7IFwiLi4vdm5vZGUvaXMtdGh1bmtcIjogMjUsIFwiLi4vdm5vZGUvaXMtdmhvb2tcIjogMjYsIFwiLi4vdm5vZGUvaXMtdm5vZGVcIjogMjcsIFwiLi4vdm5vZGUvaXMtdnRleHRcIjogMjgsIFwiLi4vdm5vZGUvaXMtd2lkZ2V0XCI6IDI5LCBcIi4uL3Zub2RlL3Zub2RlLmpzXCI6IDMxLCBcIi4uL3Zub2RlL3Z0ZXh0LmpzXCI6IDMzLCBcIi4vaG9va3MvZXYtaG9vay5qc1wiOiAyMCwgXCIuL2hvb2tzL3NvZnQtc2V0LWhvb2suanNcIjogMjEsIFwiLi9wYXJzZS10YWcuanNcIjogMjMsIFwieC1pcy1hcnJheVwiOiAxMiB9XSwgMjM6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICBcInVzZSBzdHJpY3RcIjtcblxuICAgICAgICAgICAgdmFyIHNwbGl0ID0gcmVxdWlyZShcImJyb3dzZXItc3BsaXRcIik7XG5cbiAgICAgICAgICAgIHZhciBjbGFzc0lkU3BsaXQgPSAvKFtcXC4jXT9bYS16QS1aMC05XFx1MDA3Ri1cXHVGRkZGXzotXSspLztcbiAgICAgICAgICAgIHZhciBub3RDbGFzc0lkID0gL15cXC58Iy87XG5cbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gcGFyc2VUYWc7XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIHBhcnNlVGFnKHRhZywgcHJvcHMpIHtcbiAgICAgICAgICAgICAgICBpZiAoIXRhZykge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gXCJESVZcIjtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICB2YXIgbm9JZCA9ICFwcm9wcy5oYXNPd25Qcm9wZXJ0eShcImlkXCIpO1xuXG4gICAgICAgICAgICAgICAgdmFyIHRhZ1BhcnRzID0gc3BsaXQodGFnLCBjbGFzc0lkU3BsaXQpO1xuICAgICAgICAgICAgICAgIHZhciB0YWdOYW1lID0gbnVsbDtcblxuICAgICAgICAgICAgICAgIGlmIChub3RDbGFzc0lkLnRlc3QodGFnUGFydHNbMV0pKSB7XG4gICAgICAgICAgICAgICAgICAgIHRhZ05hbWUgPSBcIkRJVlwiO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHZhciBjbGFzc2VzLCBwYXJ0LCB0eXBlLCBpO1xuXG4gICAgICAgICAgICAgICAgZm9yIChpID0gMDsgaSA8IHRhZ1BhcnRzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICAgICAgICAgIHBhcnQgPSB0YWdQYXJ0c1tpXTtcblxuICAgICAgICAgICAgICAgICAgICBpZiAoIXBhcnQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnRpbnVlO1xuICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgdHlwZSA9IHBhcnQuY2hhckF0KDApO1xuXG4gICAgICAgICAgICAgICAgICAgIGlmICghdGFnTmFtZSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgdGFnTmFtZSA9IHBhcnQ7XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAodHlwZSA9PT0gXCIuXCIpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGNsYXNzZXMgPSBjbGFzc2VzIHx8IFtdO1xuICAgICAgICAgICAgICAgICAgICAgICAgY2xhc3Nlcy5wdXNoKHBhcnQuc3Vic3RyaW5nKDEsIHBhcnQubGVuZ3RoKSk7XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAodHlwZSA9PT0gXCIjXCIgJiYgbm9JZCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgcHJvcHMuaWQgPSBwYXJ0LnN1YnN0cmluZygxLCBwYXJ0Lmxlbmd0aCk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICBpZiAoY2xhc3Nlcykge1xuICAgICAgICAgICAgICAgICAgICBpZiAocHJvcHMuY2xhc3NOYW1lKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBjbGFzc2VzLnB1c2gocHJvcHMuY2xhc3NOYW1lKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgIHByb3BzLmNsYXNzTmFtZSA9IGNsYXNzZXMuam9pbihcIiBcIik7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgcmV0dXJuIHByb3BzLm5hbWVzcGFjZSA/IHRhZ05hbWUgOiB0YWdOYW1lLnRvVXBwZXJDYXNlKCk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0sIHsgXCJicm93c2VyLXNwbGl0XCI6IDUgfV0sIDI0OiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge1xuICAgICAgICAgICAgdmFyIGlzVk5vZGUgPSByZXF1aXJlKFwiLi9pcy12bm9kZVwiKTtcbiAgICAgICAgICAgIHZhciBpc1ZUZXh0ID0gcmVxdWlyZShcIi4vaXMtdnRleHRcIik7XG4gICAgICAgICAgICB2YXIgaXNXaWRnZXQgPSByZXF1aXJlKFwiLi9pcy13aWRnZXRcIik7XG4gICAgICAgICAgICB2YXIgaXNUaHVuayA9IHJlcXVpcmUoXCIuL2lzLXRodW5rXCIpO1xuXG4gICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IGhhbmRsZVRodW5rO1xuXG4gICAgICAgICAgICBmdW5jdGlvbiBoYW5kbGVUaHVuayhhLCBiKSB7XG4gICAgICAgICAgICAgICAgdmFyIHJlbmRlcmVkQSA9IGE7XG4gICAgICAgICAgICAgICAgdmFyIHJlbmRlcmVkQiA9IGI7XG5cbiAgICAgICAgICAgICAgICBpZiAoaXNUaHVuayhiKSkge1xuICAgICAgICAgICAgICAgICAgICByZW5kZXJlZEIgPSByZW5kZXJUaHVuayhiLCBhKTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICBpZiAoaXNUaHVuayhhKSkge1xuICAgICAgICAgICAgICAgICAgICByZW5kZXJlZEEgPSByZW5kZXJUaHVuayhhLCBudWxsKTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgICAgICAgICBhOiByZW5kZXJlZEEsXG4gICAgICAgICAgICAgICAgICAgIGI6IHJlbmRlcmVkQlxuICAgICAgICAgICAgICAgIH07XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIHJlbmRlclRodW5rKHRodW5rLCBwcmV2aW91cykge1xuICAgICAgICAgICAgICAgIHZhciByZW5kZXJlZFRodW5rID0gdGh1bmsudm5vZGU7XG5cbiAgICAgICAgICAgICAgICBpZiAoIXJlbmRlcmVkVGh1bmspIHtcbiAgICAgICAgICAgICAgICAgICAgcmVuZGVyZWRUaHVuayA9IHRodW5rLnZub2RlID0gdGh1bmsucmVuZGVyKHByZXZpb3VzKTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICBpZiAoIShpc1ZOb2RlKHJlbmRlcmVkVGh1bmspIHx8IGlzVlRleHQocmVuZGVyZWRUaHVuaykgfHwgaXNXaWRnZXQocmVuZGVyZWRUaHVuaykpKSB7XG4gICAgICAgICAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcihcInRodW5rIGRpZCBub3QgcmV0dXJuIGEgdmFsaWQgbm9kZVwiKTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICByZXR1cm4gcmVuZGVyZWRUaHVuaztcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSwgeyBcIi4vaXMtdGh1bmtcIjogMjUsIFwiLi9pcy12bm9kZVwiOiAyNywgXCIuL2lzLXZ0ZXh0XCI6IDI4LCBcIi4vaXMtd2lkZ2V0XCI6IDI5IH1dLCAyNTogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHtcbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gaXNUaHVuaztcblxuICAgICAgICAgICAgZnVuY3Rpb24gaXNUaHVuayh0KSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHQgJiYgdC50eXBlID09PSBcIlRodW5rXCI7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0sIHt9XSwgMjY6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IGlzSG9vaztcblxuICAgICAgICAgICAgZnVuY3Rpb24gaXNIb29rKGhvb2spIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gaG9vayAmJiAodHlwZW9mIGhvb2suaG9vayA9PT0gXCJmdW5jdGlvblwiICYmICFob29rLmhhc093blByb3BlcnR5KFwiaG9va1wiKSB8fCB0eXBlb2YgaG9vay51bmhvb2sgPT09IFwiZnVuY3Rpb25cIiAmJiAhaG9vay5oYXNPd25Qcm9wZXJ0eShcInVuaG9va1wiKSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0sIHt9XSwgMjc6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICB2YXIgdmVyc2lvbiA9IHJlcXVpcmUoXCIuL3ZlcnNpb25cIik7XG5cbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gaXNWaXJ0dWFsTm9kZTtcblxuICAgICAgICAgICAgZnVuY3Rpb24gaXNWaXJ0dWFsTm9kZSh4KSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHggJiYgeC50eXBlID09PSBcIlZpcnR1YWxOb2RlXCIgJiYgeC52ZXJzaW9uID09PSB2ZXJzaW9uO1xuICAgICAgICAgICAgfVxuICAgICAgICB9LCB7IFwiLi92ZXJzaW9uXCI6IDMwIH1dLCAyODogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHtcbiAgICAgICAgICAgIHZhciB2ZXJzaW9uID0gcmVxdWlyZShcIi4vdmVyc2lvblwiKTtcblxuICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBpc1ZpcnR1YWxUZXh0O1xuXG4gICAgICAgICAgICBmdW5jdGlvbiBpc1ZpcnR1YWxUZXh0KHgpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4geCAmJiB4LnR5cGUgPT09IFwiVmlydHVhbFRleHRcIiAmJiB4LnZlcnNpb24gPT09IHZlcnNpb247XG4gICAgICAgICAgICB9XG4gICAgICAgIH0sIHsgXCIuL3ZlcnNpb25cIjogMzAgfV0sIDI5OiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge1xuICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBpc1dpZGdldDtcblxuICAgICAgICAgICAgZnVuY3Rpb24gaXNXaWRnZXQodykge1xuICAgICAgICAgICAgICAgIHJldHVybiB3ICYmIHcudHlwZSA9PT0gXCJXaWRnZXRcIjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSwge31dLCAzMDogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHtcbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gXCIyXCI7XG4gICAgICAgIH0sIHt9XSwgMzE6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICB2YXIgdmVyc2lvbiA9IHJlcXVpcmUoXCIuL3ZlcnNpb25cIik7XG4gICAgICAgICAgICB2YXIgaXNWTm9kZSA9IHJlcXVpcmUoXCIuL2lzLXZub2RlXCIpO1xuICAgICAgICAgICAgdmFyIGlzV2lkZ2V0ID0gcmVxdWlyZShcIi4vaXMtd2lkZ2V0XCIpO1xuICAgICAgICAgICAgdmFyIGlzVGh1bmsgPSByZXF1aXJlKFwiLi9pcy10aHVua1wiKTtcbiAgICAgICAgICAgIHZhciBpc1ZIb29rID0gcmVxdWlyZShcIi4vaXMtdmhvb2tcIik7XG5cbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gVmlydHVhbE5vZGU7XG5cbiAgICAgICAgICAgIHZhciBub1Byb3BlcnRpZXMgPSB7fTtcbiAgICAgICAgICAgIHZhciBub0NoaWxkcmVuID0gW107XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIFZpcnR1YWxOb2RlKHRhZ05hbWUsIHByb3BlcnRpZXMsIGNoaWxkcmVuLCBrZXksIG5hbWVzcGFjZSkge1xuICAgICAgICAgICAgICAgIHRoaXMudGFnTmFtZSA9IHRhZ05hbWU7XG4gICAgICAgICAgICAgICAgdGhpcy5wcm9wZXJ0aWVzID0gcHJvcGVydGllcyB8fCBub1Byb3BlcnRpZXM7XG4gICAgICAgICAgICAgICAgdGhpcy5jaGlsZHJlbiA9IGNoaWxkcmVuIHx8IG5vQ2hpbGRyZW47XG4gICAgICAgICAgICAgICAgdGhpcy5rZXkgPSBrZXkgIT0gbnVsbCA/IFN0cmluZyhrZXkpIDogdW5kZWZpbmVkO1xuICAgICAgICAgICAgICAgIHRoaXMubmFtZXNwYWNlID0gdHlwZW9mIG5hbWVzcGFjZSA9PT0gXCJzdHJpbmdcIiA/IG5hbWVzcGFjZSA6IG51bGw7XG5cbiAgICAgICAgICAgICAgICB2YXIgY291bnQgPSBjaGlsZHJlbiAmJiBjaGlsZHJlbi5sZW5ndGggfHwgMDtcbiAgICAgICAgICAgICAgICB2YXIgZGVzY2VuZGFudHMgPSAwO1xuICAgICAgICAgICAgICAgIHZhciBoYXNXaWRnZXRzID0gZmFsc2U7XG4gICAgICAgICAgICAgICAgdmFyIGhhc1RodW5rcyA9IGZhbHNlO1xuICAgICAgICAgICAgICAgIHZhciBkZXNjZW5kYW50SG9va3MgPSBmYWxzZTtcbiAgICAgICAgICAgICAgICB2YXIgaG9va3M7XG5cbiAgICAgICAgICAgICAgICBmb3IgKHZhciBwcm9wTmFtZSBpbiBwcm9wZXJ0aWVzKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmIChwcm9wZXJ0aWVzLmhhc093blByb3BlcnR5KHByb3BOYW1lKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgdmFyIHByb3BlcnR5ID0gcHJvcGVydGllc1twcm9wTmFtZV07XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoaXNWSG9vayhwcm9wZXJ0eSkgJiYgcHJvcGVydHkudW5ob29rKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKCFob29rcykge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBob29rcyA9IHt9O1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGhvb2tzW3Byb3BOYW1lXSA9IHByb3BlcnR5O1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCBjb3VudDsgaSsrKSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciBjaGlsZCA9IGNoaWxkcmVuW2ldO1xuICAgICAgICAgICAgICAgICAgICBpZiAoaXNWTm9kZShjaGlsZCkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGRlc2NlbmRhbnRzICs9IGNoaWxkLmNvdW50IHx8IDA7XG5cbiAgICAgICAgICAgICAgICAgICAgICAgIGlmICghaGFzV2lkZ2V0cyAmJiBjaGlsZC5oYXNXaWRnZXRzKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaGFzV2lkZ2V0cyA9IHRydWU7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgICAgIGlmICghaGFzVGh1bmtzICYmIGNoaWxkLmhhc1RodW5rcykge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGhhc1RodW5rcyA9IHRydWU7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgICAgIGlmICghZGVzY2VuZGFudEhvb2tzICYmIChjaGlsZC5ob29rcyB8fCBjaGlsZC5kZXNjZW5kYW50SG9va3MpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgZGVzY2VuZGFudEhvb2tzID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIGlmICghaGFzV2lkZ2V0cyAmJiBpc1dpZGdldChjaGlsZCkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmICh0eXBlb2YgY2hpbGQuZGVzdHJveSA9PT0gXCJmdW5jdGlvblwiKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaGFzV2lkZ2V0cyA9IHRydWU7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoIWhhc1RodW5rcyAmJiBpc1RodW5rKGNoaWxkKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgaGFzVGh1bmtzID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHRoaXMuY291bnQgPSBjb3VudCArIGRlc2NlbmRhbnRzO1xuICAgICAgICAgICAgICAgIHRoaXMuaGFzV2lkZ2V0cyA9IGhhc1dpZGdldHM7XG4gICAgICAgICAgICAgICAgdGhpcy5oYXNUaHVua3MgPSBoYXNUaHVua3M7XG4gICAgICAgICAgICAgICAgdGhpcy5ob29rcyA9IGhvb2tzO1xuICAgICAgICAgICAgICAgIHRoaXMuZGVzY2VuZGFudEhvb2tzID0gZGVzY2VuZGFudEhvb2tzO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBWaXJ0dWFsTm9kZS5wcm90b3R5cGUudmVyc2lvbiA9IHZlcnNpb247XG4gICAgICAgICAgICBWaXJ0dWFsTm9kZS5wcm90b3R5cGUudHlwZSA9IFwiVmlydHVhbE5vZGVcIjtcbiAgICAgICAgfSwgeyBcIi4vaXMtdGh1bmtcIjogMjUsIFwiLi9pcy12aG9va1wiOiAyNiwgXCIuL2lzLXZub2RlXCI6IDI3LCBcIi4vaXMtd2lkZ2V0XCI6IDI5LCBcIi4vdmVyc2lvblwiOiAzMCB9XSwgMzI6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICB2YXIgdmVyc2lvbiA9IHJlcXVpcmUoXCIuL3ZlcnNpb25cIik7XG5cbiAgICAgICAgICAgIFZpcnR1YWxQYXRjaC5OT05FID0gMDtcbiAgICAgICAgICAgIFZpcnR1YWxQYXRjaC5WVEVYVCA9IDE7XG4gICAgICAgICAgICBWaXJ0dWFsUGF0Y2guVk5PREUgPSAyO1xuICAgICAgICAgICAgVmlydHVhbFBhdGNoLldJREdFVCA9IDM7XG4gICAgICAgICAgICBWaXJ0dWFsUGF0Y2guUFJPUFMgPSA0O1xuICAgICAgICAgICAgVmlydHVhbFBhdGNoLk9SREVSID0gNTtcbiAgICAgICAgICAgIFZpcnR1YWxQYXRjaC5JTlNFUlQgPSA2O1xuICAgICAgICAgICAgVmlydHVhbFBhdGNoLlJFTU9WRSA9IDc7XG4gICAgICAgICAgICBWaXJ0dWFsUGF0Y2guVEhVTksgPSA4O1xuXG4gICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IFZpcnR1YWxQYXRjaDtcblxuICAgICAgICAgICAgZnVuY3Rpb24gVmlydHVhbFBhdGNoKHR5cGUsIHZOb2RlLCBwYXRjaCkge1xuICAgICAgICAgICAgICAgIHRoaXMudHlwZSA9IE51bWJlcih0eXBlKTtcbiAgICAgICAgICAgICAgICB0aGlzLnZOb2RlID0gdk5vZGU7XG4gICAgICAgICAgICAgICAgdGhpcy5wYXRjaCA9IHBhdGNoO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBWaXJ0dWFsUGF0Y2gucHJvdG90eXBlLnZlcnNpb24gPSB2ZXJzaW9uO1xuICAgICAgICAgICAgVmlydHVhbFBhdGNoLnByb3RvdHlwZS50eXBlID0gXCJWaXJ0dWFsUGF0Y2hcIjtcbiAgICAgICAgfSwgeyBcIi4vdmVyc2lvblwiOiAzMCB9XSwgMzM6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICB2YXIgdmVyc2lvbiA9IHJlcXVpcmUoXCIuL3ZlcnNpb25cIik7XG5cbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gVmlydHVhbFRleHQ7XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIFZpcnR1YWxUZXh0KHRleHQpIHtcbiAgICAgICAgICAgICAgICB0aGlzLnRleHQgPSBTdHJpbmcodGV4dCk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIFZpcnR1YWxUZXh0LnByb3RvdHlwZS52ZXJzaW9uID0gdmVyc2lvbjtcbiAgICAgICAgICAgIFZpcnR1YWxUZXh0LnByb3RvdHlwZS50eXBlID0gXCJWaXJ0dWFsVGV4dFwiO1xuICAgICAgICB9LCB7IFwiLi92ZXJzaW9uXCI6IDMwIH1dLCAzNDogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHtcbiAgICAgICAgICAgIHZhciBpc09iamVjdCA9IHJlcXVpcmUoXCJpcy1vYmplY3RcIik7XG4gICAgICAgICAgICB2YXIgaXNIb29rID0gcmVxdWlyZShcIi4uL3Zub2RlL2lzLXZob29rXCIpO1xuXG4gICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IGRpZmZQcm9wcztcblxuICAgICAgICAgICAgZnVuY3Rpb24gZGlmZlByb3BzKGEsIGIpIHtcbiAgICAgICAgICAgICAgICB2YXIgZGlmZjtcblxuICAgICAgICAgICAgICAgIGZvciAodmFyIGFLZXkgaW4gYSkge1xuICAgICAgICAgICAgICAgICAgICBpZiAoIShhS2V5IGluIGIpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBkaWZmID0gZGlmZiB8fCB7fTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGRpZmZbYUtleV0gPSB1bmRlZmluZWQ7XG4gICAgICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgICAgICB2YXIgYVZhbHVlID0gYVthS2V5XTtcbiAgICAgICAgICAgICAgICAgICAgdmFyIGJWYWx1ZSA9IGJbYUtleV07XG5cbiAgICAgICAgICAgICAgICAgICAgaWYgKGFWYWx1ZSA9PT0gYlZhbHVlKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBjb250aW51ZTtcbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIGlmIChpc09iamVjdChhVmFsdWUpICYmIGlzT2JqZWN0KGJWYWx1ZSkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChnZXRQcm90b3R5cGUoYlZhbHVlKSAhPT0gZ2V0UHJvdG90eXBlKGFWYWx1ZSkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBkaWZmID0gZGlmZiB8fCB7fTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBkaWZmW2FLZXldID0gYlZhbHVlO1xuICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIGlmIChpc0hvb2soYlZhbHVlKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRpZmYgPSBkaWZmIHx8IHt9O1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRpZmZbYUtleV0gPSBiVmFsdWU7XG4gICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZhciBvYmplY3REaWZmID0gZGlmZlByb3BzKGFWYWx1ZSwgYlZhbHVlKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAob2JqZWN0RGlmZikge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBkaWZmID0gZGlmZiB8fCB7fTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZGlmZlthS2V5XSA9IG9iamVjdERpZmY7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgZGlmZiA9IGRpZmYgfHwge307XG4gICAgICAgICAgICAgICAgICAgICAgICBkaWZmW2FLZXldID0gYlZhbHVlO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgZm9yICh2YXIgYktleSBpbiBiKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmICghKGJLZXkgaW4gYSkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGRpZmYgPSBkaWZmIHx8IHt9O1xuICAgICAgICAgICAgICAgICAgICAgICAgZGlmZltiS2V5XSA9IGJbYktleV07XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICByZXR1cm4gZGlmZjtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZnVuY3Rpb24gZ2V0UHJvdG90eXBlKHZhbHVlKSB7XG4gICAgICAgICAgICAgICAgaWYgKE9iamVjdC5nZXRQcm90b3R5cGVPZikge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gT2JqZWN0LmdldFByb3RvdHlwZU9mKHZhbHVlKTtcbiAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKHZhbHVlLl9fcHJvdG9fXykge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gdmFsdWUuX19wcm90b19fO1xuICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAodmFsdWUuY29uc3RydWN0b3IpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHZhbHVlLmNvbnN0cnVjdG9yLnByb3RvdHlwZTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH0sIHsgXCIuLi92bm9kZS9pcy12aG9va1wiOiAyNiwgXCJpcy1vYmplY3RcIjogMTEgfV0sIDM1OiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge1xuICAgICAgICAgICAgdmFyIGlzQXJyYXkgPSByZXF1aXJlKFwieC1pcy1hcnJheVwiKTtcblxuICAgICAgICAgICAgdmFyIFZQYXRjaCA9IHJlcXVpcmUoXCIuLi92bm9kZS92cGF0Y2hcIik7XG4gICAgICAgICAgICB2YXIgaXNWTm9kZSA9IHJlcXVpcmUoXCIuLi92bm9kZS9pcy12bm9kZVwiKTtcbiAgICAgICAgICAgIHZhciBpc1ZUZXh0ID0gcmVxdWlyZShcIi4uL3Zub2RlL2lzLXZ0ZXh0XCIpO1xuICAgICAgICAgICAgdmFyIGlzV2lkZ2V0ID0gcmVxdWlyZShcIi4uL3Zub2RlL2lzLXdpZGdldFwiKTtcbiAgICAgICAgICAgIHZhciBpc1RodW5rID0gcmVxdWlyZShcIi4uL3Zub2RlL2lzLXRodW5rXCIpO1xuICAgICAgICAgICAgdmFyIGhhbmRsZVRodW5rID0gcmVxdWlyZShcIi4uL3Zub2RlL2hhbmRsZS10aHVua1wiKTtcblxuICAgICAgICAgICAgdmFyIGRpZmZQcm9wcyA9IHJlcXVpcmUoXCIuL2RpZmYtcHJvcHNcIik7XG5cbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gZGlmZjtcblxuICAgICAgICAgICAgZnVuY3Rpb24gZGlmZihhLCBiKSB7XG4gICAgICAgICAgICAgICAgdmFyIHBhdGNoID0geyBhOiBhIH07XG4gICAgICAgICAgICAgICAgd2FsayhhLCBiLCBwYXRjaCwgMCk7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHBhdGNoO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBmdW5jdGlvbiB3YWxrKGEsIGIsIHBhdGNoLCBpbmRleCkge1xuICAgICAgICAgICAgICAgIGlmIChhID09PSBiKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICB2YXIgYXBwbHkgPSBwYXRjaFtpbmRleF07XG4gICAgICAgICAgICAgICAgdmFyIGFwcGx5Q2xlYXIgPSBmYWxzZTtcblxuICAgICAgICAgICAgICAgIGlmIChpc1RodW5rKGEpIHx8IGlzVGh1bmsoYikpIHtcbiAgICAgICAgICAgICAgICAgICAgdGh1bmtzKGEsIGIsIHBhdGNoLCBpbmRleCk7XG4gICAgICAgICAgICAgICAgfSBlbHNlIGlmIChiID09IG51bGwpIHtcblxuICAgICAgICAgICAgICAgICAgICAvLyBJZiBhIGlzIGEgd2lkZ2V0IHdlIHdpbGwgYWRkIGEgcmVtb3ZlIHBhdGNoIGZvciBpdFxuICAgICAgICAgICAgICAgICAgICAvLyBPdGhlcndpc2UgYW55IGNoaWxkIHdpZGdldHMvaG9va3MgbXVzdCBiZSBkZXN0cm95ZWQuXG4gICAgICAgICAgICAgICAgICAgIC8vIFRoaXMgcHJldmVudHMgYWRkaW5nIHR3byByZW1vdmUgcGF0Y2hlcyBmb3IgYSB3aWRnZXQuXG4gICAgICAgICAgICAgICAgICAgIGlmICghaXNXaWRnZXQoYSkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGNsZWFyU3RhdGUoYSwgcGF0Y2gsIGluZGV4KTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGFwcGx5ID0gcGF0Y2hbaW5kZXhdO1xuICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgYXBwbHkgPSBhcHBlbmRQYXRjaChhcHBseSwgbmV3IFZQYXRjaChWUGF0Y2guUkVNT1ZFLCBhLCBiKSk7XG4gICAgICAgICAgICAgICAgfSBlbHNlIGlmIChpc1ZOb2RlKGIpKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmIChpc1ZOb2RlKGEpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoYS50YWdOYW1lID09PSBiLnRhZ05hbWUgJiYgYS5uYW1lc3BhY2UgPT09IGIubmFtZXNwYWNlICYmIGEua2V5ID09PSBiLmtleSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZhciBwcm9wc1BhdGNoID0gZGlmZlByb3BzKGEucHJvcGVydGllcywgYi5wcm9wZXJ0aWVzKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAocHJvcHNQYXRjaCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBhcHBseSA9IGFwcGVuZFBhdGNoKGFwcGx5LCBuZXcgVlBhdGNoKFZQYXRjaC5QUk9QUywgYSwgcHJvcHNQYXRjaCkpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBhcHBseSA9IGRpZmZDaGlsZHJlbihhLCBiLCBwYXRjaCwgYXBwbHksIGluZGV4KTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgYXBwbHkgPSBhcHBlbmRQYXRjaChhcHBseSwgbmV3IFZQYXRjaChWUGF0Y2guVk5PREUsIGEsIGIpKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBhcHBseUNsZWFyID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGFwcGx5ID0gYXBwZW5kUGF0Y2goYXBwbHksIG5ldyBWUGF0Y2goVlBhdGNoLlZOT0RFLCBhLCBiKSk7XG4gICAgICAgICAgICAgICAgICAgICAgICBhcHBseUNsZWFyID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoaXNWVGV4dChiKSkge1xuICAgICAgICAgICAgICAgICAgICBpZiAoIWlzVlRleHQoYSkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGFwcGx5ID0gYXBwZW5kUGF0Y2goYXBwbHksIG5ldyBWUGF0Y2goVlBhdGNoLlZURVhULCBhLCBiKSk7XG4gICAgICAgICAgICAgICAgICAgICAgICBhcHBseUNsZWFyID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIGlmIChhLnRleHQgIT09IGIudGV4dCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgYXBwbHkgPSBhcHBlbmRQYXRjaChhcHBseSwgbmV3IFZQYXRjaChWUGF0Y2guVlRFWFQsIGEsIGIpKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoaXNXaWRnZXQoYikpIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKCFpc1dpZGdldChhKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgYXBwbHlDbGVhciA9IHRydWU7XG4gICAgICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgICAgICBhcHBseSA9IGFwcGVuZFBhdGNoKGFwcGx5LCBuZXcgVlBhdGNoKFZQYXRjaC5XSURHRVQsIGEsIGIpKTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICBpZiAoYXBwbHkpIHtcbiAgICAgICAgICAgICAgICAgICAgcGF0Y2hbaW5kZXhdID0gYXBwbHk7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgaWYgKGFwcGx5Q2xlYXIpIHtcbiAgICAgICAgICAgICAgICAgICAgY2xlYXJTdGF0ZShhLCBwYXRjaCwgaW5kZXgpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZnVuY3Rpb24gZGlmZkNoaWxkcmVuKGEsIGIsIHBhdGNoLCBhcHBseSwgaW5kZXgpIHtcbiAgICAgICAgICAgICAgICB2YXIgYUNoaWxkcmVuID0gYS5jaGlsZHJlbjtcbiAgICAgICAgICAgICAgICB2YXIgb3JkZXJlZFNldCA9IHJlb3JkZXIoYUNoaWxkcmVuLCBiLmNoaWxkcmVuKTtcbiAgICAgICAgICAgICAgICB2YXIgYkNoaWxkcmVuID0gb3JkZXJlZFNldC5jaGlsZHJlbjtcblxuICAgICAgICAgICAgICAgIHZhciBhTGVuID0gYUNoaWxkcmVuLmxlbmd0aDtcbiAgICAgICAgICAgICAgICB2YXIgYkxlbiA9IGJDaGlsZHJlbi5sZW5ndGg7XG4gICAgICAgICAgICAgICAgdmFyIGxlbiA9IGFMZW4gPiBiTGVuID8gYUxlbiA6IGJMZW47XG5cbiAgICAgICAgICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IGxlbjsgaSsrKSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciBsZWZ0Tm9kZSA9IGFDaGlsZHJlbltpXTtcbiAgICAgICAgICAgICAgICAgICAgdmFyIHJpZ2h0Tm9kZSA9IGJDaGlsZHJlbltpXTtcbiAgICAgICAgICAgICAgICAgICAgaW5kZXggKz0gMTtcblxuICAgICAgICAgICAgICAgICAgICBpZiAoIWxlZnROb2RlKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAocmlnaHROb2RlKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gRXhjZXNzIG5vZGVzIGluIGIgbmVlZCB0byBiZSBhZGRlZFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGFwcGx5ID0gYXBwZW5kUGF0Y2goYXBwbHksIG5ldyBWUGF0Y2goVlBhdGNoLklOU0VSVCwgbnVsbCwgcmlnaHROb2RlKSk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICB3YWxrKGxlZnROb2RlLCByaWdodE5vZGUsIHBhdGNoLCBpbmRleCk7XG4gICAgICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgICAgICBpZiAoaXNWTm9kZShsZWZ0Tm9kZSkgJiYgbGVmdE5vZGUuY291bnQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGluZGV4ICs9IGxlZnROb2RlLmNvdW50O1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgaWYgKG9yZGVyZWRTZXQubW92ZXMpIHtcbiAgICAgICAgICAgICAgICAgICAgLy8gUmVvcmRlciBub2RlcyBsYXN0XG4gICAgICAgICAgICAgICAgICAgIGFwcGx5ID0gYXBwZW5kUGF0Y2goYXBwbHksIG5ldyBWUGF0Y2goVlBhdGNoLk9SREVSLCBhLCBvcmRlcmVkU2V0Lm1vdmVzKSk7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgcmV0dXJuIGFwcGx5O1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBmdW5jdGlvbiBjbGVhclN0YXRlKHZOb2RlLCBwYXRjaCwgaW5kZXgpIHtcbiAgICAgICAgICAgICAgICAvLyBUT0RPOiBNYWtlIHRoaXMgYSBzaW5nbGUgd2Fsaywgbm90IHR3b1xuICAgICAgICAgICAgICAgIHVuaG9vayh2Tm9kZSwgcGF0Y2gsIGluZGV4KTtcbiAgICAgICAgICAgICAgICBkZXN0cm95V2lkZ2V0cyh2Tm9kZSwgcGF0Y2gsIGluZGV4KTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgLy8gUGF0Y2ggcmVjb3JkcyBmb3IgYWxsIGRlc3Ryb3llZCB3aWRnZXRzIG11c3QgYmUgYWRkZWQgYmVjYXVzZSB3ZSBuZWVkXG4gICAgICAgICAgICAvLyBhIERPTSBub2RlIHJlZmVyZW5jZSBmb3IgdGhlIGRlc3Ryb3kgZnVuY3Rpb25cbiAgICAgICAgICAgIGZ1bmN0aW9uIGRlc3Ryb3lXaWRnZXRzKHZOb2RlLCBwYXRjaCwgaW5kZXgpIHtcbiAgICAgICAgICAgICAgICBpZiAoaXNXaWRnZXQodk5vZGUpKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmICh0eXBlb2Ygdk5vZGUuZGVzdHJveSA9PT0gXCJmdW5jdGlvblwiKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBwYXRjaFtpbmRleF0gPSBhcHBlbmRQYXRjaChwYXRjaFtpbmRleF0sIG5ldyBWUGF0Y2goVlBhdGNoLlJFTU9WRSwgdk5vZGUsIG51bGwpKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoaXNWTm9kZSh2Tm9kZSkgJiYgKHZOb2RlLmhhc1dpZGdldHMgfHwgdk5vZGUuaGFzVGh1bmtzKSkge1xuICAgICAgICAgICAgICAgICAgICB2YXIgY2hpbGRyZW4gPSB2Tm9kZS5jaGlsZHJlbjtcbiAgICAgICAgICAgICAgICAgICAgdmFyIGxlbiA9IGNoaWxkcmVuLmxlbmd0aDtcbiAgICAgICAgICAgICAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCBsZW47IGkrKykge1xuICAgICAgICAgICAgICAgICAgICAgICAgdmFyIGNoaWxkID0gY2hpbGRyZW5baV07XG4gICAgICAgICAgICAgICAgICAgICAgICBpbmRleCArPSAxO1xuXG4gICAgICAgICAgICAgICAgICAgICAgICBkZXN0cm95V2lkZ2V0cyhjaGlsZCwgcGF0Y2gsIGluZGV4KTtcblxuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGlzVk5vZGUoY2hpbGQpICYmIGNoaWxkLmNvdW50KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaW5kZXggKz0gY2hpbGQuY291bnQ7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKGlzVGh1bmsodk5vZGUpKSB7XG4gICAgICAgICAgICAgICAgICAgIHRodW5rcyh2Tm9kZSwgbnVsbCwgcGF0Y2gsIGluZGV4KTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIC8vIENyZWF0ZSBhIHN1Yi1wYXRjaCBmb3IgdGh1bmtzXG4gICAgICAgICAgICBmdW5jdGlvbiB0aHVua3MoYSwgYiwgcGF0Y2gsIGluZGV4KSB7XG4gICAgICAgICAgICAgICAgdmFyIG5vZGVzID0gaGFuZGxlVGh1bmsoYSwgYik7XG4gICAgICAgICAgICAgICAgdmFyIHRodW5rUGF0Y2ggPSBkaWZmKG5vZGVzLmEsIG5vZGVzLmIpO1xuICAgICAgICAgICAgICAgIGlmIChoYXNQYXRjaGVzKHRodW5rUGF0Y2gpKSB7XG4gICAgICAgICAgICAgICAgICAgIHBhdGNoW2luZGV4XSA9IG5ldyBWUGF0Y2goVlBhdGNoLlRIVU5LLCBudWxsLCB0aHVua1BhdGNoKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIGhhc1BhdGNoZXMocGF0Y2gpIHtcbiAgICAgICAgICAgICAgICBmb3IgKHZhciBpbmRleCBpbiBwYXRjaCkge1xuICAgICAgICAgICAgICAgICAgICBpZiAoaW5kZXggIT09IFwiYVwiKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgLy8gRXhlY3V0ZSBob29rcyB3aGVuIHR3byBub2RlcyBhcmUgaWRlbnRpY2FsXG4gICAgICAgICAgICBmdW5jdGlvbiB1bmhvb2sodk5vZGUsIHBhdGNoLCBpbmRleCkge1xuICAgICAgICAgICAgICAgIGlmIChpc1ZOb2RlKHZOb2RlKSkge1xuICAgICAgICAgICAgICAgICAgICBpZiAodk5vZGUuaG9va3MpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHBhdGNoW2luZGV4XSA9IGFwcGVuZFBhdGNoKHBhdGNoW2luZGV4XSwgbmV3IFZQYXRjaChWUGF0Y2guUFJPUFMsIHZOb2RlLCB1bmRlZmluZWRLZXlzKHZOb2RlLmhvb2tzKSkpO1xuICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgaWYgKHZOb2RlLmRlc2NlbmRhbnRIb29rcyB8fCB2Tm9kZS5oYXNUaHVua3MpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHZhciBjaGlsZHJlbiA9IHZOb2RlLmNoaWxkcmVuO1xuICAgICAgICAgICAgICAgICAgICAgICAgdmFyIGxlbiA9IGNoaWxkcmVuLmxlbmd0aDtcbiAgICAgICAgICAgICAgICAgICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgbGVuOyBpKyspIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB2YXIgY2hpbGQgPSBjaGlsZHJlbltpXTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpbmRleCArPSAxO1xuXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdW5ob29rKGNoaWxkLCBwYXRjaCwgaW5kZXgpO1xuXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGlzVk5vZGUoY2hpbGQpICYmIGNoaWxkLmNvdW50KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGluZGV4ICs9IGNoaWxkLmNvdW50O1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoaXNUaHVuayh2Tm9kZSkpIHtcbiAgICAgICAgICAgICAgICAgICAgdGh1bmtzKHZOb2RlLCBudWxsLCBwYXRjaCwgaW5kZXgpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZnVuY3Rpb24gdW5kZWZpbmVkS2V5cyhvYmopIHtcbiAgICAgICAgICAgICAgICB2YXIgcmVzdWx0ID0ge307XG5cbiAgICAgICAgICAgICAgICBmb3IgKHZhciBrZXkgaW4gb2JqKSB7XG4gICAgICAgICAgICAgICAgICAgIHJlc3VsdFtrZXldID0gdW5kZWZpbmVkO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHJldHVybiByZXN1bHQ7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIC8vIExpc3QgZGlmZiwgbmFpdmUgbGVmdCB0byByaWdodCByZW9yZGVyaW5nXG4gICAgICAgICAgICBmdW5jdGlvbiByZW9yZGVyKGFDaGlsZHJlbiwgYkNoaWxkcmVuKSB7XG4gICAgICAgICAgICAgICAgLy8gTyhNKSB0aW1lLCBPKE0pIG1lbW9yeVxuICAgICAgICAgICAgICAgIHZhciBiQ2hpbGRJbmRleCA9IGtleUluZGV4KGJDaGlsZHJlbik7XG4gICAgICAgICAgICAgICAgdmFyIGJLZXlzID0gYkNoaWxkSW5kZXgua2V5cztcbiAgICAgICAgICAgICAgICB2YXIgYkZyZWUgPSBiQ2hpbGRJbmRleC5mcmVlO1xuXG4gICAgICAgICAgICAgICAgaWYgKGJGcmVlLmxlbmd0aCA9PT0gYkNoaWxkcmVuLmxlbmd0aCkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgICAgICAgICAgICAgY2hpbGRyZW46IGJDaGlsZHJlbixcbiAgICAgICAgICAgICAgICAgICAgICAgIG1vdmVzOiBudWxsXG4gICAgICAgICAgICAgICAgICAgIH07XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgLy8gTyhOKSB0aW1lLCBPKE4pIG1lbW9yeVxuICAgICAgICAgICAgICAgIHZhciBhQ2hpbGRJbmRleCA9IGtleUluZGV4KGFDaGlsZHJlbik7XG4gICAgICAgICAgICAgICAgdmFyIGFLZXlzID0gYUNoaWxkSW5kZXgua2V5cztcbiAgICAgICAgICAgICAgICB2YXIgYUZyZWUgPSBhQ2hpbGRJbmRleC5mcmVlO1xuXG4gICAgICAgICAgICAgICAgaWYgKGFGcmVlLmxlbmd0aCA9PT0gYUNoaWxkcmVuLmxlbmd0aCkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgICAgICAgICAgICAgY2hpbGRyZW46IGJDaGlsZHJlbixcbiAgICAgICAgICAgICAgICAgICAgICAgIG1vdmVzOiBudWxsXG4gICAgICAgICAgICAgICAgICAgIH07XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgLy8gTyhNQVgoTiwgTSkpIG1lbW9yeVxuICAgICAgICAgICAgICAgIHZhciBuZXdDaGlsZHJlbiA9IFtdO1xuXG4gICAgICAgICAgICAgICAgdmFyIGZyZWVJbmRleCA9IDA7XG4gICAgICAgICAgICAgICAgdmFyIGZyZWVDb3VudCA9IGJGcmVlLmxlbmd0aDtcbiAgICAgICAgICAgICAgICB2YXIgZGVsZXRlZEl0ZW1zID0gMDtcblxuICAgICAgICAgICAgICAgIC8vIEl0ZXJhdGUgdGhyb3VnaCBhIGFuZCBtYXRjaCBhIG5vZGUgaW4gYlxuICAgICAgICAgICAgICAgIC8vIE8oTikgdGltZSxcbiAgICAgICAgICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IGFDaGlsZHJlbi5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgICAgICAgICB2YXIgYUl0ZW0gPSBhQ2hpbGRyZW5baV07XG4gICAgICAgICAgICAgICAgICAgIHZhciBpdGVtSW5kZXg7XG5cbiAgICAgICAgICAgICAgICAgICAgaWYgKGFJdGVtLmtleSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGJLZXlzLmhhc093blByb3BlcnR5KGFJdGVtLmtleSkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBNYXRjaCB1cCB0aGUgb2xkIGtleXNcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpdGVtSW5kZXggPSBiS2V5c1thSXRlbS5rZXldO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIG5ld0NoaWxkcmVuLnB1c2goYkNoaWxkcmVuW2l0ZW1JbmRleF0pO1xuICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBSZW1vdmUgb2xkIGtleWVkIGl0ZW1zXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaXRlbUluZGV4ID0gaSAtIGRlbGV0ZWRJdGVtcysrO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIG5ld0NoaWxkcmVuLnB1c2gobnVsbCk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAvLyBNYXRjaCB0aGUgaXRlbSBpbiBhIHdpdGggdGhlIG5leHQgZnJlZSBpdGVtIGluIGJcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChmcmVlSW5kZXggPCBmcmVlQ291bnQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpdGVtSW5kZXggPSBiRnJlZVtmcmVlSW5kZXgrK107XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgbmV3Q2hpbGRyZW4ucHVzaChiQ2hpbGRyZW5baXRlbUluZGV4XSk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIFRoZXJlIGFyZSBubyBmcmVlIGl0ZW1zIGluIGIgdG8gbWF0Y2ggd2l0aFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIHRoZSBmcmVlIGl0ZW1zIGluIGEsIHNvIHRoZSBleHRyYSBmcmVlIG5vZGVzXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gYXJlIGRlbGV0ZWQuXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaXRlbUluZGV4ID0gaSAtIGRlbGV0ZWRJdGVtcysrO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIG5ld0NoaWxkcmVuLnB1c2gobnVsbCk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICB2YXIgbGFzdEZyZWVJbmRleCA9IGZyZWVJbmRleCA+PSBiRnJlZS5sZW5ndGggPyBiQ2hpbGRyZW4ubGVuZ3RoIDogYkZyZWVbZnJlZUluZGV4XTtcblxuICAgICAgICAgICAgICAgIC8vIEl0ZXJhdGUgdGhyb3VnaCBiIGFuZCBhcHBlbmQgYW55IG5ldyBrZXlzXG4gICAgICAgICAgICAgICAgLy8gTyhNKSB0aW1lXG4gICAgICAgICAgICAgICAgZm9yICh2YXIgaiA9IDA7IGogPCBiQ2hpbGRyZW4ubGVuZ3RoOyBqKyspIHtcbiAgICAgICAgICAgICAgICAgICAgdmFyIG5ld0l0ZW0gPSBiQ2hpbGRyZW5bal07XG5cbiAgICAgICAgICAgICAgICAgICAgaWYgKG5ld0l0ZW0ua2V5KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoIWFLZXlzLmhhc093blByb3BlcnR5KG5ld0l0ZW0ua2V5KSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIEFkZCBhbnkgbmV3IGtleWVkIGl0ZW1zXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gV2UgYXJlIGFkZGluZyBuZXcgaXRlbXMgdG8gdGhlIGVuZCBhbmQgdGhlbiBzb3J0aW5nIHRoZW1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBpbiBwbGFjZS4gSW4gZnV0dXJlIHdlIHNob3VsZCBpbnNlcnQgbmV3IGl0ZW1zIGluIHBsYWNlLlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIG5ld0NoaWxkcmVuLnB1c2gobmV3SXRlbSk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoaiA+PSBsYXN0RnJlZUluZGV4KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAvLyBBZGQgYW55IGxlZnRvdmVyIG5vbi1rZXllZCBpdGVtc1xuICAgICAgICAgICAgICAgICAgICAgICAgbmV3Q2hpbGRyZW4ucHVzaChuZXdJdGVtKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHZhciBzaW11bGF0ZSA9IG5ld0NoaWxkcmVuLnNsaWNlKCk7XG4gICAgICAgICAgICAgICAgdmFyIHNpbXVsYXRlSW5kZXggPSAwO1xuICAgICAgICAgICAgICAgIHZhciByZW1vdmVzID0gW107XG4gICAgICAgICAgICAgICAgdmFyIGluc2VydHMgPSBbXTtcbiAgICAgICAgICAgICAgICB2YXIgc2ltdWxhdGVJdGVtO1xuXG4gICAgICAgICAgICAgICAgZm9yICh2YXIgayA9IDA7IGsgPCBiQ2hpbGRyZW4ubGVuZ3RoOykge1xuICAgICAgICAgICAgICAgICAgICB2YXIgd2FudGVkSXRlbSA9IGJDaGlsZHJlbltrXTtcbiAgICAgICAgICAgICAgICAgICAgc2ltdWxhdGVJdGVtID0gc2ltdWxhdGVbc2ltdWxhdGVJbmRleF07XG5cbiAgICAgICAgICAgICAgICAgICAgLy8gcmVtb3ZlIGl0ZW1zXG4gICAgICAgICAgICAgICAgICAgIHdoaWxlIChzaW11bGF0ZUl0ZW0gPT09IG51bGwgJiYgc2ltdWxhdGUubGVuZ3RoKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICByZW1vdmVzLnB1c2gocmVtb3ZlKHNpbXVsYXRlLCBzaW11bGF0ZUluZGV4LCBudWxsKSk7XG4gICAgICAgICAgICAgICAgICAgICAgICBzaW11bGF0ZUl0ZW0gPSBzaW11bGF0ZVtzaW11bGF0ZUluZGV4XTtcbiAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgIGlmICghc2ltdWxhdGVJdGVtIHx8IHNpbXVsYXRlSXRlbS5rZXkgIT09IHdhbnRlZEl0ZW0ua2V5KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAvLyBpZiB3ZSBuZWVkIGEga2V5IGluIHRoaXMgcG9zaXRpb24uLi5cbiAgICAgICAgICAgICAgICAgICAgICAgIGlmICh3YW50ZWRJdGVtLmtleSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChzaW11bGF0ZUl0ZW0gJiYgc2ltdWxhdGVJdGVtLmtleSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBpZiBhbiBpbnNlcnQgZG9lc24ndCBwdXQgdGhpcyBrZXkgaW4gcGxhY2UsIGl0IG5lZWRzIHRvIG1vdmVcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGJLZXlzW3NpbXVsYXRlSXRlbS5rZXldICE9PSBrICsgMSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmVtb3Zlcy5wdXNoKHJlbW92ZShzaW11bGF0ZSwgc2ltdWxhdGVJbmRleCwgc2ltdWxhdGVJdGVtLmtleSkpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc2ltdWxhdGVJdGVtID0gc2ltdWxhdGVbc2ltdWxhdGVJbmRleF07XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBpZiB0aGUgcmVtb3ZlIGRpZG4ndCBwdXQgdGhlIHdhbnRlZCBpdGVtIGluIHBsYWNlLCB3ZSBuZWVkIHRvIGluc2VydCBpdFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKCFzaW11bGF0ZUl0ZW0gfHwgc2ltdWxhdGVJdGVtLmtleSAhPT0gd2FudGVkSXRlbS5rZXkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpbnNlcnRzLnB1c2goeyBrZXk6IHdhbnRlZEl0ZW0ua2V5LCB0bzogayB9KTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIGl0ZW1zIGFyZSBtYXRjaGluZywgc28gc2tpcCBhaGVhZFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc2ltdWxhdGVJbmRleCsrO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaW5zZXJ0cy5wdXNoKHsga2V5OiB3YW50ZWRJdGVtLmtleSwgdG86IGsgfSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpbnNlcnRzLnB1c2goeyBrZXk6IHdhbnRlZEl0ZW0ua2V5LCB0bzogayB9KTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaysrO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgLy8gYSBrZXkgaW4gc2ltdWxhdGUgaGFzIG5vIG1hdGNoaW5nIHdhbnRlZCBrZXksIHJlbW92ZSBpdFxuICAgICAgICAgICAgICAgICAgICAgICAgZWxzZSBpZiAoc2ltdWxhdGVJdGVtICYmIHNpbXVsYXRlSXRlbS5rZXkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICByZW1vdmVzLnB1c2gocmVtb3ZlKHNpbXVsYXRlLCBzaW11bGF0ZUluZGV4LCBzaW11bGF0ZUl0ZW0ua2V5KSk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBzaW11bGF0ZUluZGV4Kys7XG4gICAgICAgICAgICAgICAgICAgICAgICBrKys7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAvLyByZW1vdmUgYWxsIHRoZSByZW1haW5pbmcgbm9kZXMgZnJvbSBzaW11bGF0ZVxuICAgICAgICAgICAgICAgIHdoaWxlIChzaW11bGF0ZUluZGV4IDwgc2ltdWxhdGUubGVuZ3RoKSB7XG4gICAgICAgICAgICAgICAgICAgIHNpbXVsYXRlSXRlbSA9IHNpbXVsYXRlW3NpbXVsYXRlSW5kZXhdO1xuICAgICAgICAgICAgICAgICAgICByZW1vdmVzLnB1c2gocmVtb3ZlKHNpbXVsYXRlLCBzaW11bGF0ZUluZGV4LCBzaW11bGF0ZUl0ZW0gJiYgc2ltdWxhdGVJdGVtLmtleSkpO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIC8vIElmIHRoZSBvbmx5IG1vdmVzIHdlIGhhdmUgYXJlIGRlbGV0ZXMgdGhlbiB3ZSBjYW4ganVzdFxuICAgICAgICAgICAgICAgIC8vIGxldCB0aGUgZGVsZXRlIHBhdGNoIHJlbW92ZSB0aGVzZSBpdGVtcy5cbiAgICAgICAgICAgICAgICBpZiAocmVtb3Zlcy5sZW5ndGggPT09IGRlbGV0ZWRJdGVtcyAmJiAhaW5zZXJ0cy5sZW5ndGgpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGNoaWxkcmVuOiBuZXdDaGlsZHJlbixcbiAgICAgICAgICAgICAgICAgICAgICAgIG1vdmVzOiBudWxsXG4gICAgICAgICAgICAgICAgICAgIH07XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgICAgICAgICAgY2hpbGRyZW46IG5ld0NoaWxkcmVuLFxuICAgICAgICAgICAgICAgICAgICBtb3Zlczoge1xuICAgICAgICAgICAgICAgICAgICAgICAgcmVtb3ZlczogcmVtb3ZlcyxcbiAgICAgICAgICAgICAgICAgICAgICAgIGluc2VydHM6IGluc2VydHNcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH07XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIHJlbW92ZShhcnIsIGluZGV4LCBrZXkpIHtcbiAgICAgICAgICAgICAgICBhcnIuc3BsaWNlKGluZGV4LCAxKTtcblxuICAgICAgICAgICAgICAgIHJldHVybiB7XG4gICAgICAgICAgICAgICAgICAgIGZyb206IGluZGV4LFxuICAgICAgICAgICAgICAgICAgICBrZXk6IGtleVxuICAgICAgICAgICAgICAgIH07XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIGtleUluZGV4KGNoaWxkcmVuKSB7XG4gICAgICAgICAgICAgICAgdmFyIGtleXMgPSB7fTtcbiAgICAgICAgICAgICAgICB2YXIgZnJlZSA9IFtdO1xuICAgICAgICAgICAgICAgIHZhciBsZW5ndGggPSBjaGlsZHJlbi5sZW5ndGg7XG5cbiAgICAgICAgICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IGxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciBjaGlsZCA9IGNoaWxkcmVuW2ldO1xuXG4gICAgICAgICAgICAgICAgICAgIGlmIChjaGlsZC5rZXkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGtleXNbY2hpbGQua2V5XSA9IGk7XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBmcmVlLnB1c2goaSk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgICAgICAgICBrZXlzOiBrZXlzLCAvLyBBIGhhc2ggb2Yga2V5IG5hbWUgdG8gaW5kZXhcbiAgICAgICAgICAgICAgICAgICAgZnJlZTogZnJlZSAvLyBBbiBhcnJheSBvZiB1bmtleWVkIGl0ZW0gaW5kaWNlc1xuICAgICAgICAgICAgICAgIH07XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIGFwcGVuZFBhdGNoKGFwcGx5LCBwYXRjaCkge1xuICAgICAgICAgICAgICAgIGlmIChhcHBseSkge1xuICAgICAgICAgICAgICAgICAgICBpZiAoaXNBcnJheShhcHBseSkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGFwcGx5LnB1c2gocGF0Y2gpO1xuICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgYXBwbHkgPSBbYXBwbHksIHBhdGNoXTtcbiAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBhcHBseTtcbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gcGF0Y2g7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9LCB7IFwiLi4vdm5vZGUvaGFuZGxlLXRodW5rXCI6IDI0LCBcIi4uL3Zub2RlL2lzLXRodW5rXCI6IDI1LCBcIi4uL3Zub2RlL2lzLXZub2RlXCI6IDI3LCBcIi4uL3Zub2RlL2lzLXZ0ZXh0XCI6IDI4LCBcIi4uL3Zub2RlL2lzLXdpZGdldFwiOiAyOSwgXCIuLi92bm9kZS92cGF0Y2hcIjogMzIsIFwiLi9kaWZmLXByb3BzXCI6IDM0LCBcIngtaXMtYXJyYXlcIjogMTIgfV0gfSwge30sIFs0XSkoNCk7XG59KTtcblxuLyogQGZsb3cgKi9cblxuY2xhc3MgTWFpbGJveCB7XG5cbiAgY29uc3RydWN0b3IoKSB7XG4gICAgdGhpcy5tZXNzYWdlcyA9IFtdO1xuICB9XG5cbiAgZGVsaXZlcihtZXNzYWdlKSB7XG4gICAgdGhpcy5tZXNzYWdlcy5wdXNoKG1lc3NhZ2UpO1xuICAgIHJldHVybiBtZXNzYWdlO1xuICB9XG5cbiAgZ2V0KCkge1xuICAgIHJldHVybiB0aGlzLm1lc3NhZ2VzO1xuICB9XG5cbiAgaXNFbXB0eSgpIHtcbiAgICByZXR1cm4gdGhpcy5tZXNzYWdlcy5sZW5ndGggPT09IDA7XG4gIH1cblxuICByZW1vdmVBdChpbmRleCkge1xuICAgIHRoaXMubWVzc2FnZXMuc3BsaWNlKGluZGV4LCAxKTtcbiAgfVxufVxuXG52YXIgU3RhdGVzID0ge1xuICBOT1JNQUw6IFN5bWJvbC5mb3IoXCJub3JtYWxcIiksXG4gIEtJTEw6IFN5bWJvbC5mb3IoXCJraWxsXCIpLFxuICBTVVNQRU5EOiBTeW1ib2wuZm9yKFwic3VzcGVuZFwiKSxcbiAgQ09OVElOVUU6IFN5bWJvbC5mb3IoXCJjb250aW51ZVwiKSxcbiAgUkVDRUlWRTogU3ltYm9sLmZvcihcInJlY2VpdmVcIiksXG4gIFNFTkQ6IFN5bWJvbC5mb3IoXCJzZW5kXCIpLFxuICBTTEVFUElORzogU3ltYm9sLmZvcihcInNsZWVwaW5nXCIpLFxuICBSVU5OSU5HOiBTeW1ib2wuZm9yKFwicnVubmluZ1wiKSxcbiAgU1VTUEVOREVEOiBTeW1ib2wuZm9yKFwic3VzcGVuZGVkXCIpLFxuICBTVE9QUEVEOiBTeW1ib2wuZm9yKFwic3RvcHBlZFwiKSxcbiAgU0xFRVA6IFN5bWJvbC5mb3IoXCJzbGVlcFwiKSxcbiAgRVhJVDogU3ltYm9sLmZvcihcImV4aXRcIiksXG4gIE5PTUFUQ0g6IFN5bWJvbC5mb3IoXCJub19tYXRjaFwiKVxufTtcblxuY2xhc3MgUHJvY2VzcyB7XG5cbiAgY29uc3RydWN0b3IocGlkLCBtYWlsYm94KSB7XG4gICAgdGhpcy5waWQgPSBwaWQ7XG4gICAgdGhpcy5tYWlsYm94ID0gbWFpbGJveDtcbiAgICB0aGlzLnN0YXR1cyA9IFN0YXRlcy5TVE9QUEVEO1xuICAgIHRoaXMuZGljdCA9IHt9O1xuICB9XG59XG5cbmNsYXNzIFR1cGxlIHtcblxuICBjb25zdHJ1Y3RvciguLi5hcmdzKSB7XG4gICAgdGhpcy52YWx1ZXMgPSBPYmplY3QuZnJlZXplKGFyZ3MpO1xuICAgIHRoaXMubGVuZ3RoID0gdGhpcy52YWx1ZXMubGVuZ3RoO1xuICB9XG5cbiAgZ2V0KGluZGV4KSB7XG4gICAgcmV0dXJuIHRoaXMudmFsdWVzW2luZGV4XTtcbiAgfVxuXG4gIGNvdW50KCkge1xuICAgIHJldHVybiB0aGlzLnZhbHVlcy5sZW5ndGg7XG4gIH1cblxuICBbU3ltYm9sLml0ZXJhdG9yXSgpIHtcbiAgICByZXR1cm4gdGhpcy52YWx1ZXNbU3ltYm9sLml0ZXJhdG9yXSgpO1xuICB9XG5cbiAgdG9TdHJpbmcoKSB7XG4gICAgdmFyIGksXG4gICAgICAgIHMgPSBcIlwiO1xuICAgIGZvciAoaSA9IDA7IGkgPCB0aGlzLnZhbHVlcy5sZW5ndGg7IGkrKykge1xuICAgICAgaWYgKHMgIT09IFwiXCIpIHtcbiAgICAgICAgcyArPSBcIiwgXCI7XG4gICAgICB9XG4gICAgICBzICs9IHRoaXMudmFsdWVzW2ldLnRvU3RyaW5nKCk7XG4gICAgfVxuXG4gICAgcmV0dXJuIFwie1wiICsgcyArIFwifVwiO1xuICB9XG5cbiAgcHV0X2VsZW0oaW5kZXgsIGVsZW0pIHtcbiAgICBpZiAoaW5kZXggPT09IHRoaXMubGVuZ3RoKSB7XG4gICAgICBsZXQgbmV3X3ZhbHVlcyA9IHRoaXMudmFsdWVzLmNvbmNhdChbZWxlbV0pO1xuICAgICAgcmV0dXJuIG5ldyBUdXBsZSguLi5uZXdfdmFsdWVzKTtcbiAgICB9XG5cbiAgICBsZXQgbmV3X3ZhbHVlcyA9IHRoaXMudmFsdWVzLmNvbmNhdChbXSk7XG4gICAgbmV3X3ZhbHVlcy5zcGxpY2UoaW5kZXgsIDAsIGVsZW0pO1xuICAgIHJldHVybiBuZXcgVHVwbGUoLi4ubmV3X3ZhbHVlcyk7XG4gIH1cblxuICByZW1vdmVfZWxlbShpbmRleCkge1xuICAgIGxldCBuZXdfdmFsdWVzID0gdGhpcy52YWx1ZXMuY29uY2F0KFtdKTtcbiAgICBuZXdfdmFsdWVzLnNwbGljZShpbmRleCwgMSk7XG4gICAgcmV0dXJuIG5ldyBUdXBsZSguLi5uZXdfdmFsdWVzKTtcbiAgfVxuXG59XG5cbmxldCBwcm9jZXNzX2NvdW50ZXIgPSAtMTtcblxuY2xhc3MgUElEIHtcbiAgY29uc3RydWN0b3IoKSB7XG4gICAgcHJvY2Vzc19jb3VudGVyID0gcHJvY2Vzc19jb3VudGVyICsgMTtcbiAgICB0aGlzLmlkID0gcHJvY2Vzc19jb3VudGVyO1xuICB9XG5cbiAgdG9TdHJpbmcoKSB7XG4gICAgcmV0dXJuIFwiUElEIzwwLlwiICsgdGhpcy5pZCArIFwiLjA+XCI7XG4gIH1cbn1cblxuY2xhc3MgSW50ZWdlciB7fVxuY2xhc3MgRmxvYXQge31cblxuY2xhc3MgUHJvY2Vzc1N5c3RlbSB7XG5cbiAgY29uc3RydWN0b3IoKSB7XG4gICAgdGhpcy5waWRzID0gbmV3IE1hcCgpO1xuICAgIHRoaXMubWFpbGJveGVzID0gbmV3IE1hcCgpO1xuICAgIHRoaXMubmFtZXMgPSBuZXcgTWFwKCk7XG4gICAgdGhpcy5saW5rcyA9IG5ldyBNYXAoKTtcblxuICAgIHRoaXMuY3VycmVudF9wcm9jZXNzID0gbnVsbDtcbiAgICB0aGlzLnN1c3BlbmRlZCA9IG5ldyBNYXAoKTtcblxuICAgIHRoaXMubWFpbl9wcm9jZXNzX3BpZCA9IHRoaXMuc3Bhd24oKTtcbiAgICB0aGlzLnNldF9jdXJyZW50KHRoaXMubWFpbl9wcm9jZXNzX3BpZCk7XG4gIH1cblxuICBzcGF3bigpIHtcbiAgICByZXR1cm4gdGhpcy5hZGRfcHJvYyhmYWxzZSkucGlkO1xuICB9XG5cbiAgc3Bhd25fbGluaygpIHtcbiAgICByZXR1cm4gdGhpcy5hZGRfcHJvYyh0cnVlKS5waWQ7XG4gIH1cblxuICBsaW5rKHBpZCkge1xuICAgIHRoaXMubGlua3MuZ2V0KHRoaXMucGlkKCkpLmFkZChwaWQpO1xuICAgIHRoaXMubGlua3MuZ2V0KHBpZCkuYWRkKHRoaXMucGlkKCkpO1xuICB9XG5cbiAgdW5saW5rKHBpZCkge1xuICAgIHRoaXMubGlua3MuZ2V0KHRoaXMucGlkKCkpLmRlbGV0ZShwaWQpO1xuICAgIHRoaXMubGlua3MuZ2V0KHBpZCkuZGVsZXRlKHRoaXMucGlkKCkpO1xuICB9XG5cbiAgc2V0X2N1cnJlbnQoaWQpIHtcbiAgICBsZXQgcGlkID0gdGhpcy5waWRvZihpZCk7XG4gICAgaWYgKHBpZCAhPT0gbnVsbCkge1xuICAgICAgdGhpcy5jdXJyZW50X3Byb2Nlc3MgPSB0aGlzLnBpZHMuZ2V0KHBpZCk7XG4gICAgICB0aGlzLmN1cnJlbnRfcHJvY2Vzcy5zdGF0dXMgPSBTdGF0ZXMuUlVOTklORztcbiAgICB9XG4gIH1cblxuICBhZGRfcHJvYyhsaW5rZWQpIHtcbiAgICBsZXQgbmV3cGlkID0gbmV3IFBJRCgpO1xuICAgIGxldCBtYWlsYm94ID0gbmV3IE1haWxib3goKTtcbiAgICBsZXQgbmV3cHJvYyA9IG5ldyBQcm9jZXNzKG5ld3BpZCwgbWFpbGJveCk7XG5cbiAgICB0aGlzLnBpZHMuc2V0KG5ld3BpZCwgbmV3cHJvYyk7XG4gICAgdGhpcy5tYWlsYm94ZXMuc2V0KG5ld3BpZCwgbWFpbGJveCk7XG4gICAgdGhpcy5saW5rcy5zZXQobmV3cGlkLCBuZXcgU2V0KCkpO1xuXG4gICAgaWYgKGxpbmtlZCkge1xuICAgICAgdGhpcy5saW5rKG5ld3BpZCk7XG4gICAgfVxuXG4gICAgcmV0dXJuIG5ld3Byb2M7XG4gIH1cblxuICByZW1vdmVfcHJvYyhwaWQpIHtcbiAgICB0aGlzLnBpZHMuZGVsZXRlKHBpZCk7XG4gICAgdGhpcy51bnJlZ2lzdGVyKHBpZCk7XG5cbiAgICBpZiAodGhpcy5saW5rcy5oYXMocGlkKSkge1xuICAgICAgZm9yIChsZXQgbGlua3BpZCBvZiB0aGlzLmxpbmtzLmdldChwaWQpKSB7XG4gICAgICAgIHRoaXMubGlua3MuZ2V0KGxpbmtwaWQpLmRlbGV0ZShwaWQpO1xuICAgICAgfVxuXG4gICAgICB0aGlzLmxpbmtzLmRlbGV0ZShwaWQpO1xuICAgIH1cbiAgfVxuXG4gIGV4aXQoaWQpIHtcbiAgICBsZXQgcGlkID0gdGhpcy5waWRvZihpZCk7XG4gICAgdGhpcy5yZW1vdmVfcHJvYyhpZCk7XG4gIH1cblxuICByZWdpc3RlcihuYW1lLCBwaWQpIHtcbiAgICBpZiAoIXRoaXMubmFtZXMuaGFzKG5hbWUpKSB7XG4gICAgICB0aGlzLm5hbWVzLnNldChuYW1lLCBwaWQpO1xuICAgICAgcmV0dXJuIG5hbWU7XG4gICAgfSBlbHNlIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcihcIk5hbWUgaXMgYWxyZWFkeSByZWdpc3RlcmVkIHRvIGFub3RoZXIgcHJvY2Vzc1wiKTtcbiAgICB9XG4gIH1cblxuICByZWdpc3RlcmVkKG5hbWUpIHtcbiAgICByZXR1cm4gdGhpcy5uYW1lcy5oYXMobmFtZSkgPyB0aGlzLm5hbWVzLmdldChuYW1lKSA6IG51bGw7XG4gIH1cblxuICB1bnJlZ2lzdGVyKHBpZCkge1xuICAgIGZvciAobGV0IG5hbWUgb2YgdGhpcy5uYW1lcy5rZXlzKCkpIHtcbiAgICAgIGlmICh0aGlzLm5hbWVzLmhhcyhuYW1lKSAmJiB0aGlzLm5hbWVzLmdldChuYW1lKSA9PT0gcGlkKSB7XG4gICAgICAgIHRoaXMubmFtZXMuZGVsZXRlKG5hbWUpO1xuICAgICAgfVxuICAgIH1cbiAgfVxuXG4gIHBpZCgpIHtcbiAgICByZXR1cm4gdGhpcy5jdXJyZW50X3Byb2Nlc3MucGlkO1xuICB9XG5cbiAgcGlkb2YoaWQpIHtcbiAgICBpZiAoaWQgaW5zdGFuY2VvZiBQSUQpIHtcbiAgICAgIHJldHVybiB0aGlzLnBpZHMuaGFzKGlkKSA/IGlkIDogbnVsbDtcbiAgICB9IGVsc2UgaWYgKGlkIGluc3RhbmNlb2YgUHJvY2Vzcykge1xuICAgICAgcmV0dXJuIGlkLnBpZDtcbiAgICB9IGVsc2Uge1xuICAgICAgbGV0IHBpZCA9IHRoaXMucmVnaXN0ZXJlZChpZCk7XG4gICAgICBpZiAocGlkID09PSBudWxsKSB0aHJvdyBcIlByb2Nlc3MgbmFtZSBub3QgcmVnaXN0ZXJlZDogXCIgKyBpZCArIFwiIChcIiArIHR5cGVvZiBpZCArIFwiKVwiO1xuICAgICAgcmV0dXJuIHBpZDtcbiAgICB9XG4gIH1cblxuICBwdXQoaWQsIGtleSwgdmFsdWUpIHtcbiAgICBsZXQgcGlkID0gdGhpcy5waWRvZihpZCk7XG4gICAgbGV0IHByb2Nlc3MgPSB0aGlzLnBpZHMuZ2V0KHBpZCk7XG4gICAgcHJvY2Vzcy5kaWN0W2tleV0gPSB2YWx1ZTtcbiAgfVxuXG4gIGdldChpZCwga2V5KSB7XG4gICAgbGV0IHBpZCA9IHRoaXMucGlkb2YoaWQpO1xuICAgIGxldCBwcm9jZXNzID0gdGhpcy5waWRzLmdldChwaWQpO1xuXG4gICAgaWYgKGtleSAhPSBudWxsKSB7XG4gICAgICByZXR1cm4gcHJvY2Vzcy5kaWN0W2tleV07XG4gICAgfSBlbHNlIHtcbiAgICAgIHJldHVybiBwcm9jZXNzLmRpY3Q7XG4gICAgfVxuICB9XG5cbiAgZ2V0X2tleXMoaWQpIHtcbiAgICBsZXQgcGlkID0gdGhpcy5waWRvZihpZCk7XG4gICAgbGV0IHByb2Nlc3MgPSB0aGlzLnBpZHMuZ2V0KHBpZCk7XG5cbiAgICByZXR1cm4gT2JqZWN0LmtleXMocHJvY2Vzcy5kaWN0KTtcbiAgfVxuXG4gIGVyYXNlKGlkLCBrZXkpIHtcbiAgICBsZXQgcGlkID0gdGhpcy5waWRvZihpZCk7XG4gICAgbGV0IHByb2Nlc3MgPSB0aGlzLnBpZHMuZ2V0KHBpZCk7XG5cbiAgICBpZiAoa2V5ICE9IG51bGwpIHtcbiAgICAgIGRlbGV0ZSBwcm9jZXNzLmRpY3Rba2V5XTtcbiAgICB9IGVsc2Uge1xuICAgICAgcHJvY2Vzcy5kaWN0ID0ge307XG4gICAgfVxuICB9XG59XG5cbmNsYXNzIEJpdFN0cmluZyB7XG4gIGNvbnN0cnVjdG9yKC4uLmFyZ3MpIHtcbiAgICB0aGlzLnJhd192YWx1ZSA9IGZ1bmN0aW9uICgpIHtcbiAgICAgIHJldHVybiBPYmplY3QuZnJlZXplKGFyZ3MpO1xuICAgIH07XG5cbiAgICB0aGlzLnZhbHVlID0gT2JqZWN0LmZyZWV6ZSh0aGlzLnByb2Nlc3MoYXJncykpO1xuICAgIHRoaXMubGVuZ3RoID0gdGhpcy52YWx1ZS5sZW5ndGg7XG4gICAgdGhpcy5iaXRfc2l6ZSA9IHRoaXMucmF3X3ZhbHVlKCkucmVkdWNlKChwcmV2LCBjdXJyZW50KSA9PiBwcmV2ICsgY3VycmVudC5zaXplKTtcbiAgICB0aGlzLmJ5dGVfc2l6ZSA9IHRoaXMuYml0X3NpemUgLyA4ICsgKHRoaXMuYml0X3NpemUgJSA4ID4gMCA/IDEgOiAwKTtcbiAgfVxuXG4gIGdldChpbmRleCkge1xuICAgIHJldHVybiB0aGlzLnZhbHVlW2luZGV4XTtcbiAgfVxuXG4gIGNvdW50KCkge1xuICAgIHJldHVybiB0aGlzLnZhbHVlLmxlbmd0aDtcbiAgfVxuXG4gIFtTeW1ib2wuaXRlcmF0b3JdKCkge1xuICAgIHJldHVybiB0aGlzLnZhbHVlW1N5bWJvbC5pdGVyYXRvcl0oKTtcbiAgfVxuXG4gIHRvU3RyaW5nKCkge1xuICAgIHZhciBpLFxuICAgICAgICBzID0gXCJcIjtcbiAgICBmb3IgKGkgPSAwOyBpIDwgdGhpcy5jb3VudCgpOyBpKyspIHtcbiAgICAgIGlmIChzICE9PSBcIlwiKSB7XG4gICAgICAgIHMgKz0gXCIsIFwiO1xuICAgICAgfVxuICAgICAgcyArPSB0aGlzW2ldLnRvU3RyaW5nKCk7XG4gICAgfVxuXG4gICAgcmV0dXJuIFwiPDxcIiArIHMgKyBcIj4+XCI7XG4gIH1cblxuICBwcm9jZXNzKCkge1xuICAgIGxldCBwcm9jZXNzZWRfdmFsdWVzID0gW107XG5cbiAgICB2YXIgaTtcbiAgICBmb3IgKGkgPSAwOyBpIDwgdGhpcy5yYXdfdmFsdWUoKS5sZW5ndGg7IGkrKykge1xuICAgICAgbGV0IHByb2Nlc3NlZF92YWx1ZSA9IHRoaXNbXCJwcm9jZXNzX1wiICsgdGhpcy5yYXdfdmFsdWUoKVtpXS50eXBlXSh0aGlzLnJhd192YWx1ZSgpW2ldKTtcblxuICAgICAgZm9yIChsZXQgYXR0ciBvZiB0aGlzLnJhd192YWx1ZSgpW2ldLmF0dHJpYnV0ZXMpIHtcbiAgICAgICAgcHJvY2Vzc2VkX3ZhbHVlID0gdGhpc1tcInByb2Nlc3NfXCIgKyBhdHRyXShwcm9jZXNzZWRfdmFsdWUpO1xuICAgICAgfVxuXG4gICAgICBwcm9jZXNzZWRfdmFsdWVzID0gcHJvY2Vzc2VkX3ZhbHVlcy5jb25jYXQocHJvY2Vzc2VkX3ZhbHVlKTtcbiAgICB9XG5cbiAgICByZXR1cm4gcHJvY2Vzc2VkX3ZhbHVlcztcbiAgfVxuXG4gIHByb2Nlc3NfaW50ZWdlcih2YWx1ZSkge1xuICAgIHJldHVybiB2YWx1ZS52YWx1ZTtcbiAgfVxuXG4gIHByb2Nlc3NfZmxvYXQodmFsdWUpIHtcbiAgICBpZiAodmFsdWUuc2l6ZSA9PT0gNjQpIHtcbiAgICAgIHJldHVybiBCaXRTdHJpbmcuZmxvYXQ2NFRvQnl0ZXModmFsdWUudmFsdWUpO1xuICAgIH0gZWxzZSBpZiAodmFsdWUuc2l6ZSA9PT0gMzIpIHtcbiAgICAgIHJldHVybiBCaXRTdHJpbmcuZmxvYXQzMlRvQnl0ZXModmFsdWUudmFsdWUpO1xuICAgIH1cblxuICAgIHRocm93IG5ldyBFcnJvcihcIkludmFsaWQgc2l6ZSBmb3IgZmxvYXRcIik7XG4gIH1cblxuICBwcm9jZXNzX2JpdHN0cmluZyh2YWx1ZSkge1xuICAgIHJldHVybiB2YWx1ZS52YWx1ZS52YWx1ZTtcbiAgfVxuXG4gIHByb2Nlc3NfYmluYXJ5KHZhbHVlKSB7XG4gICAgcmV0dXJuIEJpdFN0cmluZy50b1VURjhBcnJheSh2YWx1ZS52YWx1ZSk7XG4gIH1cblxuICBwcm9jZXNzX3V0ZjgodmFsdWUpIHtcbiAgICByZXR1cm4gQml0U3RyaW5nLnRvVVRGOEFycmF5KHZhbHVlLnZhbHVlKTtcbiAgfVxuXG4gIHByb2Nlc3NfdXRmMTYodmFsdWUpIHtcbiAgICByZXR1cm4gQml0U3RyaW5nLnRvVVRGMTZBcnJheSh2YWx1ZS52YWx1ZSk7XG4gIH1cblxuICBwcm9jZXNzX3V0ZjMyKHZhbHVlKSB7XG4gICAgcmV0dXJuIEJpdFN0cmluZy50b1VURjMyQXJyYXkodmFsdWUudmFsdWUpO1xuICB9XG5cbiAgcHJvY2Vzc19zaWduZWQodmFsdWUpIHtcbiAgICByZXR1cm4gbmV3IFVpbnQ4QXJyYXkoW3ZhbHVlXSlbMF07XG4gIH1cblxuICBwcm9jZXNzX3Vuc2lnbmVkKHZhbHVlKSB7XG4gICAgcmV0dXJuIHZhbHVlO1xuICB9XG5cbiAgcHJvY2Vzc19uYXRpdmUodmFsdWUpIHtcbiAgICByZXR1cm4gdmFsdWU7XG4gIH1cblxuICBwcm9jZXNzX2JpZyh2YWx1ZSkge1xuICAgIHJldHVybiB2YWx1ZTtcbiAgfVxuXG4gIHByb2Nlc3NfbGl0dGxlKHZhbHVlKSB7XG4gICAgcmV0dXJuIHZhbHVlLnJldmVyc2UoKTtcbiAgfVxuXG4gIHByb2Nlc3Nfc2l6ZSh2YWx1ZSkge1xuICAgIHJldHVybiB2YWx1ZTtcbiAgfVxuXG4gIHByb2Nlc3NfdW5pdCh2YWx1ZSkge1xuICAgIHJldHVybiB2YWx1ZTtcbiAgfVxuXG4gIHN0YXRpYyBpbnRlZ2VyKHZhbHVlKSB7XG4gICAgcmV0dXJuIEJpdFN0cmluZy53cmFwKHZhbHVlLCB7IFwidHlwZVwiOiBcImludGVnZXJcIiwgXCJ1bml0XCI6IDEsIFwic2l6ZVwiOiA4IH0pO1xuICB9XG5cbiAgc3RhdGljIGZsb2F0KHZhbHVlKSB7XG4gICAgcmV0dXJuIEJpdFN0cmluZy53cmFwKHZhbHVlLCB7IFwidHlwZVwiOiBcImZsb2F0XCIsIFwidW5pdFwiOiAxLCBcInNpemVcIjogNjQgfSk7XG4gIH1cblxuICBzdGF0aWMgYml0c3RyaW5nKHZhbHVlKSB7XG4gICAgcmV0dXJuIEJpdFN0cmluZy53cmFwKHZhbHVlLCB7IFwidHlwZVwiOiBcImJpdHN0cmluZ1wiLCBcInVuaXRcIjogMSwgXCJzaXplXCI6IHZhbHVlLmJpdF9zaXplIH0pO1xuICB9XG5cbiAgc3RhdGljIGJpdHModmFsdWUpIHtcbiAgICByZXR1cm4gQml0U3RyaW5nLmJpdHN0cmluZyh2YWx1ZSk7XG4gIH1cblxuICBzdGF0aWMgYmluYXJ5KHZhbHVlKSB7XG4gICAgcmV0dXJuIEJpdFN0cmluZy53cmFwKHZhbHVlLCB7IFwidHlwZVwiOiBcImJpbmFyeVwiLCBcInVuaXRcIjogOCwgXCJzaXplXCI6IHZhbHVlLmxlbmd0aCB9KTtcbiAgfVxuXG4gIHN0YXRpYyBieXRlcyh2YWx1ZSkge1xuICAgIHJldHVybiBCaXRTdHJpbmcuYmluYXJ5KHZhbHVlKTtcbiAgfVxuXG4gIHN0YXRpYyB1dGY4KHZhbHVlKSB7XG4gICAgcmV0dXJuIEJpdFN0cmluZy53cmFwKHZhbHVlLCB7IFwidHlwZVwiOiBcInV0ZjhcIiB9KTtcbiAgfVxuXG4gIHN0YXRpYyB1dGYxNih2YWx1ZSkge1xuICAgIHJldHVybiBCaXRTdHJpbmcud3JhcCh2YWx1ZSwgeyBcInR5cGVcIjogXCJ1dGYxNlwiIH0pO1xuICB9XG5cbiAgc3RhdGljIHV0ZjMyKHZhbHVlKSB7XG4gICAgcmV0dXJuIEJpdFN0cmluZy53cmFwKHZhbHVlLCB7IFwidHlwZVwiOiBcInV0ZjMyXCIgfSk7XG4gIH1cblxuICBzdGF0aWMgc2lnbmVkKHZhbHVlKSB7XG4gICAgcmV0dXJuIEJpdFN0cmluZy53cmFwKHZhbHVlLCB7fSwgXCJzaWduZWRcIik7XG4gIH1cblxuICBzdGF0aWMgdW5zaWduZWQodmFsdWUpIHtcbiAgICByZXR1cm4gQml0U3RyaW5nLndyYXAodmFsdWUsIHt9LCBcInVuc2lnbmVkXCIpO1xuICB9XG5cbiAgc3RhdGljIG5hdGl2ZSh2YWx1ZSkge1xuICAgIHJldHVybiBCaXRTdHJpbmcud3JhcCh2YWx1ZSwge30sIFwibmF0aXZlXCIpO1xuICB9XG5cbiAgc3RhdGljIGJpZyh2YWx1ZSkge1xuICAgIHJldHVybiBCaXRTdHJpbmcud3JhcCh2YWx1ZSwge30sIFwiYmlnXCIpO1xuICB9XG5cbiAgc3RhdGljIGxpdHRsZSh2YWx1ZSkge1xuICAgIHJldHVybiBCaXRTdHJpbmcud3JhcCh2YWx1ZSwge30sIFwibGl0dGxlXCIpO1xuICB9XG5cbiAgc3RhdGljIHNpemUodmFsdWUsIGNvdW50KSB7XG4gICAgcmV0dXJuIEJpdFN0cmluZy53cmFwKHZhbHVlLCB7IFwic2l6ZVwiOiBjb3VudCB9KTtcbiAgfVxuXG4gIHN0YXRpYyB1bml0KHZhbHVlLCBjb3VudCkge1xuICAgIHJldHVybiBCaXRTdHJpbmcud3JhcCh2YWx1ZSwgeyBcInVuaXRcIjogY291bnQgfSk7XG4gIH1cblxuICBzdGF0aWMgd3JhcCh2YWx1ZSwgb3B0LCBuZXdfYXR0cmlidXRlID0gbnVsbCkge1xuICAgIGxldCB0aGVfdmFsdWUgPSB2YWx1ZTtcblxuICAgIGlmICghKHZhbHVlIGluc3RhbmNlb2YgT2JqZWN0KSkge1xuICAgICAgdGhlX3ZhbHVlID0geyBcInZhbHVlXCI6IHZhbHVlLCBcImF0dHJpYnV0ZXNcIjogW10gfTtcbiAgICB9XG5cbiAgICB0aGVfdmFsdWUgPSBPYmplY3QuYXNzaWduKHRoZV92YWx1ZSwgb3B0KTtcblxuICAgIGlmIChuZXdfYXR0cmlidXRlKSB7XG4gICAgICB0aGVfdmFsdWUuYXR0cmlidXRlcy5wdXNoKG5ld19hdHRyaWJ1dGUpO1xuICAgIH1cblxuICAgIHJldHVybiB0aGVfdmFsdWU7XG4gIH1cblxuICBzdGF0aWMgdG9VVEY4QXJyYXkoc3RyKSB7XG4gICAgdmFyIHV0ZjggPSBbXTtcbiAgICBmb3IgKHZhciBpID0gMDsgaSA8IHN0ci5sZW5ndGg7IGkrKykge1xuICAgICAgdmFyIGNoYXJjb2RlID0gc3RyLmNoYXJDb2RlQXQoaSk7XG4gICAgICBpZiAoY2hhcmNvZGUgPCAxMjgpIHtcbiAgICAgICAgdXRmOC5wdXNoKGNoYXJjb2RlKTtcbiAgICAgIH0gZWxzZSBpZiAoY2hhcmNvZGUgPCAyMDQ4KSB7XG4gICAgICAgIHV0ZjgucHVzaCgxOTIgfCBjaGFyY29kZSA+PiA2LCAxMjggfCBjaGFyY29kZSAmIDYzKTtcbiAgICAgIH0gZWxzZSBpZiAoY2hhcmNvZGUgPCA1NTI5NiB8fCBjaGFyY29kZSA+PSA1NzM0NCkge1xuICAgICAgICB1dGY4LnB1c2goMjI0IHwgY2hhcmNvZGUgPj4gMTIsIDEyOCB8IGNoYXJjb2RlID4+IDYgJiA2MywgMTI4IHwgY2hhcmNvZGUgJiA2Myk7XG4gICAgICB9XG4gICAgICAvLyBzdXJyb2dhdGUgcGFpclxuICAgICAgZWxzZSB7XG4gICAgICAgIGkrKztcbiAgICAgICAgLy8gVVRGLTE2IGVuY29kZXMgMHgxMDAwMC0weDEwRkZGRiBieVxuICAgICAgICAvLyBzdWJ0cmFjdGluZyAweDEwMDAwIGFuZCBzcGxpdHRpbmcgdGhlXG4gICAgICAgIC8vIDIwIGJpdHMgb2YgMHgwLTB4RkZGRkYgaW50byB0d28gaGFsdmVzXG4gICAgICAgIGNoYXJjb2RlID0gNjU1MzYgKyAoKGNoYXJjb2RlICYgMTAyMykgPDwgMTAgfCBzdHIuY2hhckNvZGVBdChpKSAmIDEwMjMpO1xuICAgICAgICB1dGY4LnB1c2goMjQwIHwgY2hhcmNvZGUgPj4gMTgsIDEyOCB8IGNoYXJjb2RlID4+IDEyICYgNjMsIDEyOCB8IGNoYXJjb2RlID4+IDYgJiA2MywgMTI4IHwgY2hhcmNvZGUgJiA2Myk7XG4gICAgICB9XG4gICAgfVxuICAgIHJldHVybiB1dGY4O1xuICB9XG5cbiAgc3RhdGljIHRvVVRGMTZBcnJheShzdHIpIHtcbiAgICB2YXIgdXRmMTYgPSBbXTtcbiAgICBmb3IgKHZhciBpID0gMDsgaSA8IHN0ci5sZW5ndGg7IGkrKykge1xuICAgICAgdmFyIGNvZGVQb2ludCA9IHN0ci5jb2RlUG9pbnRBdChpKTtcblxuICAgICAgaWYgKGNvZGVQb2ludCA8PSAyNTUpIHtcbiAgICAgICAgdXRmMTYucHVzaCgwKTtcbiAgICAgICAgdXRmMTYucHVzaChjb2RlUG9pbnQpO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgdXRmMTYucHVzaChjb2RlUG9pbnQgPj4gOCAmIDI1NSk7XG4gICAgICAgIHV0ZjE2LnB1c2goY29kZVBvaW50ICYgMjU1KTtcbiAgICAgIH1cbiAgICB9XG4gICAgcmV0dXJuIHV0ZjE2O1xuICB9XG5cbiAgc3RhdGljIHRvVVRGMzJBcnJheShzdHIpIHtcbiAgICB2YXIgdXRmMzIgPSBbXTtcbiAgICBmb3IgKHZhciBpID0gMDsgaSA8IHN0ci5sZW5ndGg7IGkrKykge1xuICAgICAgdmFyIGNvZGVQb2ludCA9IHN0ci5jb2RlUG9pbnRBdChpKTtcblxuICAgICAgaWYgKGNvZGVQb2ludCA8PSAyNTUpIHtcbiAgICAgICAgdXRmMzIucHVzaCgwKTtcbiAgICAgICAgdXRmMzIucHVzaCgwKTtcbiAgICAgICAgdXRmMzIucHVzaCgwKTtcbiAgICAgICAgdXRmMzIucHVzaChjb2RlUG9pbnQpO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgdXRmMzIucHVzaCgwKTtcbiAgICAgICAgdXRmMzIucHVzaCgwKTtcbiAgICAgICAgdXRmMzIucHVzaChjb2RlUG9pbnQgPj4gOCAmIDI1NSk7XG4gICAgICAgIHV0ZjMyLnB1c2goY29kZVBvaW50ICYgMjU1KTtcbiAgICAgIH1cbiAgICB9XG4gICAgcmV0dXJuIHV0ZjMyO1xuICB9XG5cbiAgLy9odHRwOi8vc3RhY2tvdmVyZmxvdy5jb20vcXVlc3Rpb25zLzIwMDM0OTMvamF2YXNjcmlwdC1mbG9hdC1mcm9tLXRvLWJpdHNcbiAgc3RhdGljIGZsb2F0MzJUb0J5dGVzKGYpIHtcbiAgICB2YXIgYnl0ZXMgPSBbXTtcblxuICAgIHZhciBidWYgPSBuZXcgQXJyYXlCdWZmZXIoNCk7XG4gICAgbmV3IEZsb2F0MzJBcnJheShidWYpWzBdID0gZjtcblxuICAgIGxldCBpbnRWZXJzaW9uID0gbmV3IFVpbnQzMkFycmF5KGJ1ZilbMF07XG5cbiAgICBieXRlcy5wdXNoKGludFZlcnNpb24gPj4gMjQgJiAyNTUpO1xuICAgIGJ5dGVzLnB1c2goaW50VmVyc2lvbiA+PiAxNiAmIDI1NSk7XG4gICAgYnl0ZXMucHVzaChpbnRWZXJzaW9uID4+IDggJiAyNTUpO1xuICAgIGJ5dGVzLnB1c2goaW50VmVyc2lvbiAmIDI1NSk7XG5cbiAgICByZXR1cm4gYnl0ZXM7XG4gIH1cblxuICBzdGF0aWMgZmxvYXQ2NFRvQnl0ZXMoZikge1xuICAgIHZhciBieXRlcyA9IFtdO1xuXG4gICAgdmFyIGJ1ZiA9IG5ldyBBcnJheUJ1ZmZlcig4KTtcbiAgICBuZXcgRmxvYXQ2NEFycmF5KGJ1ZilbMF0gPSBmO1xuXG4gICAgdmFyIGludFZlcnNpb24xID0gbmV3IFVpbnQzMkFycmF5KGJ1ZilbMF07XG4gICAgdmFyIGludFZlcnNpb24yID0gbmV3IFVpbnQzMkFycmF5KGJ1ZilbMV07XG5cbiAgICBieXRlcy5wdXNoKGludFZlcnNpb24yID4+IDI0ICYgMjU1KTtcbiAgICBieXRlcy5wdXNoKGludFZlcnNpb24yID4+IDE2ICYgMjU1KTtcbiAgICBieXRlcy5wdXNoKGludFZlcnNpb24yID4+IDggJiAyNTUpO1xuICAgIGJ5dGVzLnB1c2goaW50VmVyc2lvbjIgJiAyNTUpO1xuXG4gICAgYnl0ZXMucHVzaChpbnRWZXJzaW9uMSA+PiAyNCAmIDI1NSk7XG4gICAgYnl0ZXMucHVzaChpbnRWZXJzaW9uMSA+PiAxNiAmIDI1NSk7XG4gICAgYnl0ZXMucHVzaChpbnRWZXJzaW9uMSA+PiA4ICYgMjU1KTtcbiAgICBieXRlcy5wdXNoKGludFZlcnNpb24xICYgMjU1KTtcblxuICAgIHJldHVybiBieXRlcztcbiAgfVxufVxuXG4vKiBAZmxvdyAqL1xuXG5jbGFzcyBWYXJpYWJsZSB7XG5cbiAgY29uc3RydWN0b3IobmFtZSA9IG51bGwpIHtcbiAgICB0aGlzLm5hbWUgPSBuYW1lO1xuICB9XG59XG5cbmNsYXNzIFdpbGRjYXJkIHtcbiAgY29uc3RydWN0b3IoKSB7fVxufVxuXG5jbGFzcyBTdGFydHNXaXRoIHtcblxuICBjb25zdHJ1Y3RvcihwcmVmaXgpIHtcbiAgICB0aGlzLnByZWZpeCA9IHByZWZpeDtcbiAgfVxufVxuXG5jbGFzcyBDYXB0dXJlIHtcblxuICBjb25zdHJ1Y3Rvcih2YWx1ZSkge1xuICAgIHRoaXMudmFsdWUgPSB2YWx1ZTtcbiAgfVxufVxuXG5jbGFzcyBIZWFkVGFpbCB7XG5cbiAgY29uc3RydWN0b3IoaGVhZCA9IG51bGwsIHRhaWwgPSBudWxsKSB7XG4gICAgdGhpcy5oZWFkID0gaGVhZDtcbiAgICB0aGlzLnRhaWwgPSB0YWlsO1xuICB9XG59XG5cbmNsYXNzIFR5cGUge1xuXG4gIGNvbnN0cnVjdG9yKHR5cGUsIG9ialBhdHRlcm4gPSB7fSkge1xuICAgIHRoaXMudHlwZSA9IHR5cGU7XG4gICAgdGhpcy5vYmpQYXR0ZXJuID0gb2JqUGF0dGVybjtcbiAgfVxufVxuXG5jbGFzcyBCb3VuZCB7XG5cbiAgY29uc3RydWN0b3IodmFsdWUpIHtcbiAgICB0aGlzLnZhbHVlID0gdmFsdWU7XG4gIH1cbn1cblxuZnVuY3Rpb24gdmFyaWFibGUobmFtZSA9IG51bGwpIHtcbiAgcmV0dXJuIG5ldyBWYXJpYWJsZShuYW1lKTtcbn1cblxuZnVuY3Rpb24gd2lsZGNhcmQoKSB7XG4gIHJldHVybiBuZXcgV2lsZGNhcmQoKTtcbn1cblxuZnVuY3Rpb24gc3RhcnRzV2l0aChwcmVmaXgpIHtcbiAgcmV0dXJuIG5ldyBTdGFydHNXaXRoKHByZWZpeCk7XG59XG5cbmZ1bmN0aW9uIGNhcHR1cmUodmFsdWUpIHtcbiAgcmV0dXJuIG5ldyBDYXB0dXJlKHZhbHVlKTtcbn1cblxuZnVuY3Rpb24gaGVhZFRhaWwoaGVhZCA9IG51bGwsIHRhaWwgPSBudWxsKSB7XG4gIHJldHVybiBuZXcgSGVhZFRhaWwoaGVhZCwgdGFpbCk7XG59XG5cbmZ1bmN0aW9uIHR5cGUodHlwZSwgb2JqUGF0dGVybiA9IHt9KSB7XG4gIHJldHVybiBuZXcgVHlwZSh0eXBlLCBvYmpQYXR0ZXJuKTtcbn1cblxuZnVuY3Rpb24gYm91bmQodmFsdWUpIHtcbiAgcmV0dXJuIG5ldyBCb3VuZCh2YWx1ZSk7XG59XG5cbmZ1bmN0aW9uIGlzX251bWJlcih2YWx1ZSkge1xuICByZXR1cm4gdHlwZW9mIHZhbHVlID09PSAnbnVtYmVyJztcbn1cblxuZnVuY3Rpb24gaXNfc3RyaW5nKHZhbHVlKSB7XG4gIHJldHVybiB0eXBlb2YgdmFsdWUgPT09ICdzdHJpbmcnO1xufVxuXG5mdW5jdGlvbiBpc19ib29sZWFuKHZhbHVlKSB7XG4gIHJldHVybiB0eXBlb2YgdmFsdWUgPT09ICdib29sZWFuJztcbn1cblxuZnVuY3Rpb24gaXNfc3ltYm9sKHZhbHVlKSB7XG4gIHJldHVybiB0eXBlb2YgdmFsdWUgPT09ICdzeW1ib2wnO1xufVxuXG5mdW5jdGlvbiBpc19udWxsKHZhbHVlKSB7XG4gIHJldHVybiB2YWx1ZSA9PT0gbnVsbDtcbn1cblxuZnVuY3Rpb24gaXNfdW5kZWZpbmVkKHZhbHVlKSB7XG4gIHJldHVybiB0eXBlb2YgdmFsdWUgPT09ICd1bmRlZmluZWQnO1xufVxuXG5mdW5jdGlvbiBpc19mdW5jdGlvbih2YWx1ZSkge1xuICByZXR1cm4gT2JqZWN0LnByb3RvdHlwZS50b1N0cmluZy5jYWxsKHZhbHVlKSA9PSAnW29iamVjdCBGdW5jdGlvbl0nO1xufVxuXG5mdW5jdGlvbiBpc192YXJpYWJsZSh2YWx1ZSkge1xuICByZXR1cm4gdmFsdWUgaW5zdGFuY2VvZiBWYXJpYWJsZTtcbn1cblxuZnVuY3Rpb24gaXNfd2lsZGNhcmQodmFsdWUpIHtcbiAgcmV0dXJuIHZhbHVlIGluc3RhbmNlb2YgV2lsZGNhcmQ7XG59XG5cbmZ1bmN0aW9uIGlzX2hlYWRUYWlsKHZhbHVlKSB7XG4gIHJldHVybiB2YWx1ZSBpbnN0YW5jZW9mIEhlYWRUYWlsO1xufVxuXG5mdW5jdGlvbiBpc19jYXB0dXJlKHZhbHVlKSB7XG4gIHJldHVybiB2YWx1ZSBpbnN0YW5jZW9mIENhcHR1cmU7XG59XG5cbmZ1bmN0aW9uIGlzX3R5cGUodmFsdWUpIHtcbiAgcmV0dXJuIHZhbHVlIGluc3RhbmNlb2YgVHlwZTtcbn1cblxuZnVuY3Rpb24gaXNfc3RhcnRzV2l0aCh2YWx1ZSkge1xuICByZXR1cm4gdmFsdWUgaW5zdGFuY2VvZiBTdGFydHNXaXRoO1xufVxuXG5mdW5jdGlvbiBpc19ib3VuZCh2YWx1ZSkge1xuICByZXR1cm4gdmFsdWUgaW5zdGFuY2VvZiBCb3VuZDtcbn1cblxuZnVuY3Rpb24gaXNfb2JqZWN0KHZhbHVlKSB7XG4gIHJldHVybiB0eXBlb2YgdmFsdWUgPT09ICdvYmplY3QnO1xufVxuXG5mdW5jdGlvbiBpc19hcnJheSh2YWx1ZSkge1xuICByZXR1cm4gQXJyYXkuaXNBcnJheSh2YWx1ZSk7XG59XG5cbnZhciBDaGVja3MgPSB7XG4gIGlzX251bWJlcixcbiAgaXNfc3RyaW5nLFxuICBpc19ib29sZWFuLFxuICBpc19zeW1ib2wsXG4gIGlzX251bGwsXG4gIGlzX3VuZGVmaW5lZCxcbiAgaXNfZnVuY3Rpb24sXG4gIGlzX3ZhcmlhYmxlLFxuICBpc193aWxkY2FyZCxcbiAgaXNfaGVhZFRhaWwsXG4gIGlzX2NhcHR1cmUsXG4gIGlzX3R5cGUsXG4gIGlzX3N0YXJ0c1dpdGgsXG4gIGlzX2JvdW5kLFxuICBpc19vYmplY3QsXG4gIGlzX2FycmF5XG59O1xuXG5mdW5jdGlvbiByZXNvbHZlU3ltYm9sKHBhdHRlcm4pIHtcbiAgcmV0dXJuIGZ1bmN0aW9uICh2YWx1ZSkge1xuICAgIHJldHVybiBDaGVja3MuaXNfc3ltYm9sKHZhbHVlKSAmJiB2YWx1ZSA9PT0gcGF0dGVybjtcbiAgfTtcbn1cblxuZnVuY3Rpb24gcmVzb2x2ZVN0cmluZyhwYXR0ZXJuKSB7XG4gIHJldHVybiBmdW5jdGlvbiAodmFsdWUpIHtcbiAgICByZXR1cm4gQ2hlY2tzLmlzX3N0cmluZyh2YWx1ZSkgJiYgdmFsdWUgPT09IHBhdHRlcm47XG4gIH07XG59XG5cbmZ1bmN0aW9uIHJlc29sdmVOdW1iZXIocGF0dGVybikge1xuICByZXR1cm4gZnVuY3Rpb24gKHZhbHVlKSB7XG4gICAgcmV0dXJuIENoZWNrcy5pc19udW1iZXIodmFsdWUpICYmIHZhbHVlID09PSBwYXR0ZXJuO1xuICB9O1xufVxuXG5mdW5jdGlvbiByZXNvbHZlQm9vbGVhbihwYXR0ZXJuKSB7XG4gIHJldHVybiBmdW5jdGlvbiAodmFsdWUpIHtcbiAgICByZXR1cm4gQ2hlY2tzLmlzX2Jvb2xlYW4odmFsdWUpICYmIHZhbHVlID09PSBwYXR0ZXJuO1xuICB9O1xufVxuXG5mdW5jdGlvbiByZXNvbHZlRnVuY3Rpb24ocGF0dGVybikge1xuICByZXR1cm4gZnVuY3Rpb24gKHZhbHVlKSB7XG4gICAgcmV0dXJuIENoZWNrcy5pc19mdW5jdGlvbih2YWx1ZSkgJiYgdmFsdWUgPT09IHBhdHRlcm47XG4gIH07XG59XG5cbmZ1bmN0aW9uIHJlc29sdmVOdWxsKHBhdHRlcm4pIHtcbiAgcmV0dXJuIGZ1bmN0aW9uICh2YWx1ZSkge1xuICAgIHJldHVybiBDaGVja3MuaXNfbnVsbCh2YWx1ZSk7XG4gIH07XG59XG5cbmZ1bmN0aW9uIHJlc29sdmVCb3VuZChwYXR0ZXJuKSB7XG4gIHJldHVybiBmdW5jdGlvbiAodmFsdWUsIGFyZ3MpIHtcbiAgICBpZiAodHlwZW9mIHZhbHVlID09PSB0eXBlb2YgcGF0dGVybi52YWx1ZSAmJiB2YWx1ZSA9PT0gcGF0dGVybi52YWx1ZSkge1xuICAgICAgYXJncy5wdXNoKHZhbHVlKTtcbiAgICAgIHJldHVybiB0cnVlO1xuICAgIH1cblxuICAgIHJldHVybiBmYWxzZTtcbiAgfTtcbn1cblxuZnVuY3Rpb24gcmVzb2x2ZVdpbGRjYXJkKCkge1xuICByZXR1cm4gZnVuY3Rpb24gKCkge1xuICAgIHJldHVybiB0cnVlO1xuICB9O1xufVxuXG5mdW5jdGlvbiByZXNvbHZlVmFyaWFibGUoKSB7XG4gIHJldHVybiBmdW5jdGlvbiAodmFsdWUsIGFyZ3MpIHtcbiAgICBhcmdzLnB1c2godmFsdWUpO1xuICAgIHJldHVybiB0cnVlO1xuICB9O1xufVxuXG5mdW5jdGlvbiByZXNvbHZlSGVhZFRhaWwocGF0dGVybikge1xuICBjb25zdCBoZWFkTWF0Y2hlcyA9IGJ1aWxkTWF0Y2gocGF0dGVybi5oZWFkKTtcbiAgY29uc3QgdGFpbE1hdGNoZXMgPSBidWlsZE1hdGNoKHBhdHRlcm4udGFpbCk7XG5cbiAgcmV0dXJuIGZ1bmN0aW9uICh2YWx1ZSwgYXJncykge1xuICAgIGlmICghQ2hlY2tzLmlzX2FycmF5KHZhbHVlKSB8fCB2YWx1ZS5sZW5ndGggPCAyKSB7XG4gICAgICByZXR1cm4gZmFsc2U7XG4gICAgfVxuXG4gICAgY29uc3QgaGVhZCA9IHZhbHVlWzBdO1xuICAgIGNvbnN0IHRhaWwgPSB2YWx1ZS5zbGljZSgxKTtcblxuICAgIGlmIChoZWFkTWF0Y2hlcyhoZWFkLCBhcmdzKSAmJiB0YWlsTWF0Y2hlcyh0YWlsLCBhcmdzKSkge1xuICAgICAgcmV0dXJuIHRydWU7XG4gICAgfVxuICB9O1xufVxuXG5mdW5jdGlvbiByZXNvbHZlQ2FwdHVyZShwYXR0ZXJuKSB7XG4gIGNvbnN0IG1hdGNoZXMgPSBidWlsZE1hdGNoKHBhdHRlcm4udmFsdWUpO1xuXG4gIHJldHVybiBmdW5jdGlvbiAodmFsdWUsIGFyZ3MpIHtcbiAgICBpZiAobWF0Y2hlcyh2YWx1ZSwgYXJncykpIHtcbiAgICAgIGFyZ3MucHVzaCh2YWx1ZSk7XG4gICAgICByZXR1cm4gdHJ1ZTtcbiAgICB9XG5cbiAgICByZXR1cm4gZmFsc2U7XG4gIH07XG59XG5cbmZ1bmN0aW9uIHJlc29sdmVTdGFydHNXaXRoKHBhdHRlcm4pIHtcbiAgY29uc3QgcHJlZml4ID0gcGF0dGVybi5wcmVmaXg7XG5cbiAgcmV0dXJuIGZ1bmN0aW9uICh2YWx1ZSwgYXJncykge1xuICAgIGlmIChDaGVja3MuaXNfc3RyaW5nKHZhbHVlKSAmJiB2YWx1ZS5zdGFydHNXaXRoKHByZWZpeCkpIHtcbiAgICAgIGFyZ3MucHVzaCh2YWx1ZS5zdWJzdHJpbmcocHJlZml4Lmxlbmd0aCkpO1xuICAgICAgcmV0dXJuIHRydWU7XG4gICAgfVxuXG4gICAgcmV0dXJuIGZhbHNlO1xuICB9O1xufVxuXG5mdW5jdGlvbiByZXNvbHZlVHlwZShwYXR0ZXJuKSB7XG4gIHJldHVybiBmdW5jdGlvbiAodmFsdWUsIGFyZ3MpIHtcbiAgICBpZiAodmFsdWUgaW5zdGFuY2VvZiBwYXR0ZXJuLnR5cGUpIHtcbiAgICAgIGNvbnN0IG1hdGNoZXMgPSBidWlsZE1hdGNoKHBhdHRlcm4ub2JqUGF0dGVybik7XG4gICAgICByZXR1cm4gbWF0Y2hlcyh2YWx1ZSwgYXJncykgJiYgYXJncy5wdXNoKHZhbHVlKSA+IDA7XG4gICAgfVxuXG4gICAgcmV0dXJuIGZhbHNlO1xuICB9O1xufVxuXG5mdW5jdGlvbiByZXNvbHZlQXJyYXkocGF0dGVybikge1xuICBjb25zdCBtYXRjaGVzID0gcGF0dGVybi5tYXAoeCA9PiBidWlsZE1hdGNoKHgpKTtcblxuICByZXR1cm4gZnVuY3Rpb24gKHZhbHVlLCBhcmdzKSB7XG4gICAgaWYgKCFDaGVja3MuaXNfYXJyYXkodmFsdWUpIHx8IHZhbHVlLmxlbmd0aCAhPSBwYXR0ZXJuLmxlbmd0aCkge1xuICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH1cblxuICAgIHJldHVybiB2YWx1ZS5ldmVyeShmdW5jdGlvbiAodiwgaSkge1xuICAgICAgcmV0dXJuIG1hdGNoZXNbaV0odmFsdWVbaV0sIGFyZ3MpO1xuICAgIH0pO1xuICB9O1xufVxuXG5mdW5jdGlvbiByZXNvbHZlT2JqZWN0KHBhdHRlcm4pIHtcbiAgbGV0IG1hdGNoZXMgPSB7fTtcblxuICBmb3IgKGxldCBrZXkgb2YgT2JqZWN0LmtleXMocGF0dGVybikuY29uY2F0KE9iamVjdC5nZXRPd25Qcm9wZXJ0eVN5bWJvbHMocGF0dGVybikpKSB7XG4gICAgbWF0Y2hlc1trZXldID0gYnVpbGRNYXRjaChwYXR0ZXJuW2tleV0pO1xuICB9XG5cbiAgcmV0dXJuIGZ1bmN0aW9uICh2YWx1ZSwgYXJncykge1xuICAgIGlmICghQ2hlY2tzLmlzX29iamVjdCh2YWx1ZSkgfHwgcGF0dGVybi5sZW5ndGggPiB2YWx1ZS5sZW5ndGgpIHtcbiAgICAgIHJldHVybiBmYWxzZTtcbiAgICB9XG5cbiAgICBmb3IgKGxldCBrZXkgb2YgT2JqZWN0LmtleXMocGF0dGVybikuY29uY2F0KE9iamVjdC5nZXRPd25Qcm9wZXJ0eVN5bWJvbHMocGF0dGVybikpKSB7XG4gICAgICBpZiAoIShrZXkgaW4gdmFsdWUpIHx8ICFtYXRjaGVzW2tleV0odmFsdWVba2V5XSwgYXJncykpIHtcbiAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgfVxuICAgIH1cblxuICAgIHJldHVybiB0cnVlO1xuICB9O1xufVxuXG5mdW5jdGlvbiByZXNvbHZlTm9NYXRjaCgpIHtcbiAgcmV0dXJuIGZ1bmN0aW9uICgpIHtcbiAgICByZXR1cm4gZmFsc2U7XG4gIH07XG59XG5cbnZhciBSZXNvbHZlcnMgPSB7XG4gIHJlc29sdmVCb3VuZCxcbiAgcmVzb2x2ZVdpbGRjYXJkLFxuICByZXNvbHZlVmFyaWFibGUsXG4gIHJlc29sdmVIZWFkVGFpbCxcbiAgcmVzb2x2ZUNhcHR1cmUsXG4gIHJlc29sdmVTdGFydHNXaXRoLFxuICByZXNvbHZlVHlwZSxcbiAgcmVzb2x2ZUFycmF5LFxuICByZXNvbHZlT2JqZWN0LFxuICByZXNvbHZlTm9NYXRjaCxcbiAgcmVzb2x2ZVN5bWJvbCxcbiAgcmVzb2x2ZVN0cmluZyxcbiAgcmVzb2x2ZU51bWJlcixcbiAgcmVzb2x2ZUJvb2xlYW4sXG4gIHJlc29sdmVGdW5jdGlvbixcbiAgcmVzb2x2ZU51bGxcbn07XG5cbmZ1bmN0aW9uIGJ1aWxkTWF0Y2gocGF0dGVybikge1xuXG4gIGlmIChDaGVja3MuaXNfdmFyaWFibGUocGF0dGVybikpIHtcbiAgICByZXR1cm4gUmVzb2x2ZXJzLnJlc29sdmVWYXJpYWJsZShwYXR0ZXJuKTtcbiAgfVxuXG4gIGlmIChDaGVja3MuaXNfd2lsZGNhcmQocGF0dGVybikpIHtcbiAgICByZXR1cm4gUmVzb2x2ZXJzLnJlc29sdmVXaWxkY2FyZChwYXR0ZXJuKTtcbiAgfVxuXG4gIGlmIChDaGVja3MuaXNfdW5kZWZpbmVkKHBhdHRlcm4pKSB7XG4gICAgcmV0dXJuIFJlc29sdmVycy5yZXNvbHZlV2lsZGNhcmQocGF0dGVybik7XG4gIH1cblxuICBpZiAoQ2hlY2tzLmlzX2hlYWRUYWlsKHBhdHRlcm4pKSB7XG4gICAgcmV0dXJuIFJlc29sdmVycy5yZXNvbHZlSGVhZFRhaWwocGF0dGVybik7XG4gIH1cblxuICBpZiAoQ2hlY2tzLmlzX3N0YXJ0c1dpdGgocGF0dGVybikpIHtcbiAgICByZXR1cm4gUmVzb2x2ZXJzLnJlc29sdmVTdGFydHNXaXRoKHBhdHRlcm4pO1xuICB9XG5cbiAgaWYgKENoZWNrcy5pc19jYXB0dXJlKHBhdHRlcm4pKSB7XG4gICAgcmV0dXJuIFJlc29sdmVycy5yZXNvbHZlQ2FwdHVyZShwYXR0ZXJuKTtcbiAgfVxuXG4gIGlmIChDaGVja3MuaXNfYm91bmQocGF0dGVybikpIHtcbiAgICByZXR1cm4gUmVzb2x2ZXJzLnJlc29sdmVCb3VuZChwYXR0ZXJuKTtcbiAgfVxuXG4gIGlmIChDaGVja3MuaXNfdHlwZShwYXR0ZXJuKSkge1xuICAgIHJldHVybiBSZXNvbHZlcnMucmVzb2x2ZVR5cGUocGF0dGVybik7XG4gIH1cblxuICBpZiAoQ2hlY2tzLmlzX2FycmF5KHBhdHRlcm4pKSB7XG4gICAgcmV0dXJuIFJlc29sdmVycy5yZXNvbHZlQXJyYXkocGF0dGVybik7XG4gIH1cblxuICBpZiAoQ2hlY2tzLmlzX251bWJlcihwYXR0ZXJuKSkge1xuICAgIHJldHVybiBSZXNvbHZlcnMucmVzb2x2ZU51bWJlcihwYXR0ZXJuKTtcbiAgfVxuXG4gIGlmIChDaGVja3MuaXNfc3RyaW5nKHBhdHRlcm4pKSB7XG4gICAgcmV0dXJuIFJlc29sdmVycy5yZXNvbHZlU3RyaW5nKHBhdHRlcm4pO1xuICB9XG5cbiAgaWYgKENoZWNrcy5pc19ib29sZWFuKHBhdHRlcm4pKSB7XG4gICAgcmV0dXJuIFJlc29sdmVycy5yZXNvbHZlQm9vbGVhbihwYXR0ZXJuKTtcbiAgfVxuXG4gIGlmIChDaGVja3MuaXNfc3ltYm9sKHBhdHRlcm4pKSB7XG4gICAgcmV0dXJuIFJlc29sdmVycy5yZXNvbHZlU3ltYm9sKHBhdHRlcm4pO1xuICB9XG5cbiAgaWYgKENoZWNrcy5pc19udWxsKHBhdHRlcm4pKSB7XG4gICAgcmV0dXJuIFJlc29sdmVycy5yZXNvbHZlTnVsbChwYXR0ZXJuKTtcbiAgfVxuXG4gIGlmIChDaGVja3MuaXNfb2JqZWN0KHBhdHRlcm4pKSB7XG4gICAgcmV0dXJuIFJlc29sdmVycy5yZXNvbHZlT2JqZWN0KHBhdHRlcm4pO1xuICB9XG5cbiAgcmV0dXJuIFJlc29sdmVycy5yZXNvbHZlTm9NYXRjaCgpO1xufVxuXG5jbGFzcyBNYXRjaEVycm9yIGV4dGVuZHMgRXJyb3Ige1xuICBjb25zdHJ1Y3RvcihhcmcpIHtcbiAgICBzdXBlcigpO1xuXG4gICAgaWYgKHR5cGVvZiBhcmcgPT09ICdzeW1ib2wnKSB7XG4gICAgICB0aGlzLm1lc3NhZ2UgPSAnTm8gbWF0Y2ggZm9yOiAnICsgYXJnLnRvU3RyaW5nKCk7XG4gICAgfSBlbHNlIGlmIChBcnJheS5pc0FycmF5KGFyZykpIHtcbiAgICAgIGxldCBtYXBwZWRWYWx1ZXMgPSBhcmcubWFwKHggPT4geC50b1N0cmluZygpKTtcbiAgICAgIHRoaXMubWVzc2FnZSA9ICdObyBtYXRjaCBmb3I6ICcgKyBtYXBwZWRWYWx1ZXM7XG4gICAgfSBlbHNlIHtcbiAgICAgIHRoaXMubWVzc2FnZSA9ICdObyBtYXRjaCBmb3I6ICcgKyBhcmc7XG4gICAgfVxuXG4gICAgdGhpcy5zdGFjayA9IG5ldyBFcnJvcigpLnN0YWNrO1xuICAgIHRoaXMubmFtZSA9IHRoaXMuY29uc3RydWN0b3IubmFtZTtcbiAgfVxufVxuXG5jbGFzcyBDYXNlIHtcblxuICBjb25zdHJ1Y3RvcihwYXR0ZXJuLCBmbiwgZ3VhcmQgPSAoKSA9PiB0cnVlKSB7XG4gICAgdGhpcy5wYXR0ZXJuID0gYnVpbGRNYXRjaChwYXR0ZXJuKTtcbiAgICB0aGlzLmZuID0gZm47XG4gICAgdGhpcy5ndWFyZCA9IGd1YXJkO1xuICB9XG59XG5cbmZ1bmN0aW9uIG1ha2VfY2FzZShwYXR0ZXJuLCBmbiwgZ3VhcmQgPSAoKSA9PiB0cnVlKSB7XG4gIHJldHVybiBuZXcgQ2FzZShwYXR0ZXJuLCBmbiwgZ3VhcmQpO1xufVxuXG5mdW5jdGlvbiBkZWZtYXRjaCguLi5jYXNlcykge1xuICByZXR1cm4gZnVuY3Rpb24gKC4uLmFyZ3MpIHtcbiAgICBmb3IgKGxldCBwcm9jZXNzZWRDYXNlIG9mIGNhc2VzKSB7XG4gICAgICBsZXQgcmVzdWx0ID0gW107XG4gICAgICBpZiAocHJvY2Vzc2VkQ2FzZS5wYXR0ZXJuKGFyZ3MsIHJlc3VsdCkgJiYgcHJvY2Vzc2VkQ2FzZS5ndWFyZC5hcHBseSh0aGlzLCByZXN1bHQpKSB7XG4gICAgICAgIHJldHVybiBwcm9jZXNzZWRDYXNlLmZuLmFwcGx5KHRoaXMsIHJlc3VsdCk7XG4gICAgICB9XG4gICAgfVxuXG4gICAgdGhyb3cgbmV3IE1hdGNoRXJyb3IoYXJncyk7XG4gIH07XG59XG5cbmZ1bmN0aW9uIG1hdGNoKHBhdHRlcm4sIGV4cHIsIGd1YXJkID0gKCkgPT4gdHJ1ZSkge1xuICBsZXQgcmVzdWx0ID0gW107XG4gIGxldCBwcm9jZXNzZWRQYXR0ZXJuID0gYnVpbGRNYXRjaChwYXR0ZXJuKTtcbiAgaWYgKHByb2Nlc3NlZFBhdHRlcm4oZXhwciwgcmVzdWx0KSAmJiBndWFyZC5hcHBseSh0aGlzLCByZXN1bHQpKSB7XG4gICAgcmV0dXJuIHJlc3VsdDtcbiAgfSBlbHNlIHtcbiAgICB0aHJvdyBuZXcgTWF0Y2hFcnJvcihleHByKTtcbiAgfVxufVxuXG5mdW5jdGlvbiBtYXRjaF9ub190aHJvdyhwYXR0ZXJuLCBleHByLCBndWFyZCA9ICgpID0+IHRydWUpIHtcbiAgdHJ5IHtcbiAgICByZXR1cm4gbWF0Y2gocGF0dGVybiwgZXhwciwgZ3VhcmQpO1xuICB9IGNhdGNoIChlKSB7XG4gICAgaWYgKGUgaW5zdGFuY2VvZiBNYXRjaEVycm9yKSB7XG4gICAgICByZXR1cm4gbnVsbDtcbiAgICB9XG5cbiAgICB0aHJvdyBlO1xuICB9XG59XG5cbnZhciBQYXR0ZXJucyA9IHtcbiAgZGVmbWF0Y2gsIG1hdGNoLCBNYXRjaEVycm9yLCBtYXRjaF9ub190aHJvdyxcbiAgdmFyaWFibGUsIHdpbGRjYXJkLCBzdGFydHNXaXRoLFxuICBjYXB0dXJlLCBoZWFkVGFpbCwgdHlwZSwgYm91bmQsIENhc2UsIG1ha2VfY2FzZVxufTtcblxuLy9odHRwczovL2dpdGh1Yi5jb20vYWlycG9ydHloL3Byb3RvbW9ycGhpc21cbmNsYXNzIFByb3RvY29sIHtcbiAgY29uc3RydWN0b3Ioc3BlYykge1xuICAgIHRoaXMucmVnaXN0cnkgPSBuZXcgTWFwKCk7XG4gICAgdGhpcy5mYWxsYmFjayA9IG51bGw7XG5cbiAgICBmb3IgKGxldCBmdW5OYW1lIGluIHNwZWMpIHtcbiAgICAgIHRoaXNbZnVuTmFtZV0gPSBjcmVhdGVGdW4oZnVuTmFtZSkuYmluZCh0aGlzKTtcbiAgICB9XG5cbiAgICBmdW5jdGlvbiBjcmVhdGVGdW4oZnVuTmFtZSkge1xuXG4gICAgICByZXR1cm4gZnVuY3Rpb24gKC4uLmFyZ3MpIHtcbiAgICAgICAgbGV0IHRoaW5nID0gYXJnc1swXTtcbiAgICAgICAgbGV0IGZ1biA9IG51bGw7XG5cbiAgICAgICAgaWYgKE51bWJlci5pc0ludGVnZXIodGhpbmcpICYmIHRoaXMuaGFzSW1wbGVtZW50YXRpb24oSW50ZWdlcikpIHtcbiAgICAgICAgICBmdW4gPSB0aGlzLnJlZ2lzdHJ5LmdldChJbnRlZ2VyKVtmdW5OYW1lXTtcbiAgICAgICAgfSBlbHNlIGlmICh0eXBlb2YgdGhpbmcgPT09IFwibnVtYmVyXCIgJiYgIU51bWJlci5pc0ludGVnZXIodGhpbmcpICYmIHRoaXMuaGFzSW1wbGVtZW50YXRpb24oRmxvYXQpKSB7XG4gICAgICAgICAgZnVuID0gdGhpcy5yZWdpc3RyeS5nZXQoRmxvYXQpW2Z1bk5hbWVdO1xuICAgICAgICB9IGVsc2UgaWYgKHRoaXMuaGFzSW1wbGVtZW50YXRpb24odGhpbmcpKSB7XG4gICAgICAgICAgZnVuID0gdGhpcy5yZWdpc3RyeS5nZXQodGhpbmcuY29uc3RydWN0b3IpW2Z1bk5hbWVdO1xuICAgICAgICB9IGVsc2UgaWYgKHRoaXMuZmFsbGJhY2spIHtcbiAgICAgICAgICBmdW4gPSB0aGlzLmZhbGxiYWNrW2Z1bk5hbWVdO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKGZ1biAhPSBudWxsKSB7XG4gICAgICAgICAgbGV0IHJldHZhbCA9IGZ1bi5hcHBseSh0aGlzLCBhcmdzKTtcbiAgICAgICAgICByZXR1cm4gcmV0dmFsO1xuICAgICAgICB9XG5cbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKFwiTm8gaW1wbGVtZW50YXRpb24gZm91bmQgZm9yIFwiICsgdGhpbmcpO1xuICAgICAgfTtcbiAgICB9XG4gIH1cblxuICBpbXBsZW1lbnRhdGlvbih0eXBlLCBpbXBsZW1lbnRhdGlvbikge1xuICAgIGlmICh0eXBlID09PSBudWxsKSB7XG4gICAgICB0aGlzLmZhbGxiYWNrID0gaW1wbGVtZW50YXRpb247XG4gICAgfSBlbHNlIHtcbiAgICAgIHRoaXMucmVnaXN0cnkuc2V0KHR5cGUsIGltcGxlbWVudGF0aW9uKTtcbiAgICB9XG4gIH1cblxuICBoYXNJbXBsZW1lbnRhdGlvbih0aGluZykge1xuICAgIGlmICh0aGluZyA9PT0gSW50ZWdlciB8fCB0aGluZyA9PT0gRmxvYXQpIHtcbiAgICAgIHJldHVybiB0aGlzLnJlZ2lzdHJ5Lmhhcyh0aGluZyk7XG4gICAgfVxuXG4gICAgcmV0dXJuIHRoaXMucmVnaXN0cnkuaGFzKHRoaW5nLmNvbnN0cnVjdG9yKTtcbiAgfVxufVxuXG5mdW5jdGlvbiBjYWxsX3Byb3BlcnR5KGl0ZW0sIHByb3BlcnR5KSB7XG4gIGxldCBwcm9wID0gbnVsbDtcblxuICBpZiAodHlwZW9mIGl0ZW0gPT09ICdudW1iZXInIHx8IHR5cGVvZiBpdGVtID09PSAnc3ltYm9sJyB8fCB0eXBlb2YgaXRlbSA9PT0gJ2Jvb2xlYW4nIHx8IHR5cGVvZiBpdGVtID09PSAnc3RyaW5nJykge1xuICAgIGlmIChpdGVtW3Byb3BlcnR5XSAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICBwcm9wID0gcHJvcGVydHk7XG4gICAgfSBlbHNlIGlmIChpdGVtW1N5bWJvbC5mb3IocHJvcGVydHkpXSAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICBwcm9wID0gU3ltYm9sLmZvcihwcm9wZXJ0eSk7XG4gICAgfVxuICB9IGVsc2Uge1xuICAgIGlmIChwcm9wZXJ0eSBpbiBpdGVtKSB7XG4gICAgICBwcm9wID0gcHJvcGVydHk7XG4gICAgfSBlbHNlIGlmIChTeW1ib2wuZm9yKHByb3BlcnR5KSBpbiBpdGVtKSB7XG4gICAgICBwcm9wID0gU3ltYm9sLmZvcihwcm9wZXJ0eSk7XG4gICAgfVxuICB9XG5cbiAgaWYgKHByb3AgPT09IG51bGwpIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoYFByb3BlcnR5ICR7IHByb3BlcnR5IH0gbm90IGZvdW5kIGluICR7IGl0ZW0gfWApO1xuICB9XG5cbiAgaWYgKGl0ZW1bcHJvcF0gaW5zdGFuY2VvZiBGdW5jdGlvbikge1xuICAgIHJldHVybiBpdGVtW3Byb3BdKCk7XG4gIH0gZWxzZSB7XG4gICAgcmV0dXJuIGl0ZW1bcHJvcF07XG4gIH1cbn1cblxuZnVuY3Rpb24gYXBwbHkoLi4uYXJncykge1xuICBpZiAoYXJncy5sZW5ndGggPT09IDIpIHtcbiAgICBhcmdzWzBdLmFwcGx5KG51bGwsIGFyZ3Muc2xpY2UoMSkpO1xuICB9IGVsc2Uge1xuICAgIGFyZ3NbMF1bYXJnc1sxXV0uYXBwbHkobnVsbCwgYXJncy5zbGljZSgyKSk7XG4gIH1cbn1cblxuZnVuY3Rpb24gY29udGFpbnMobGVmdCwgcmlnaHQpIHtcbiAgZm9yIChsZXQgeCBvZiByaWdodCkge1xuICAgIGlmIChQYXR0ZXJucy5tYXRjaF9ub190aHJvdyhsZWZ0LCB4KSAhPSBudWxsKSB7XG4gICAgICByZXR1cm4gdHJ1ZTtcbiAgICB9XG4gIH1cblxuICByZXR1cm4gZmFsc2U7XG59XG5cbmZ1bmN0aW9uIGdldF9nbG9iYWwoKSB7XG4gIGlmICh0eXBlb2Ygc2VsZiAhPT0gJ3VuZGVmaW5lZCcpIHtcbiAgICByZXR1cm4gc2VsZjtcbiAgfSBlbHNlIGlmICh0eXBlb2Ygd2luZG93ICE9PSAndW5kZWZpbmVkJykge1xuICAgIHJldHVybiB3aW5kb3c7XG4gIH0gZWxzZSBpZiAodHlwZW9mIGdsb2JhbCAhPT0gJ3VuZGVmaW5lZCcpIHtcbiAgICByZXR1cm4gZ2xvYmFsO1xuICB9XG5cbiAgdGhyb3cgbmV3IEVycm9yKCdObyBnbG9iYWwgc3RhdGUgZm91bmQnKTtcbn1cblxuZnVuY3Rpb24gZGVmc3RydWN0KGRlZmF1bHRzKSB7XG4gIHJldHVybiBjbGFzcyB7XG4gICAgY29uc3RydWN0b3IodXBkYXRlID0ge30pIHtcbiAgICAgIGxldCB0aGVfdmFsdWVzID0gT2JqZWN0LmFzc2lnbihkZWZhdWx0cywgdXBkYXRlKTtcbiAgICAgIE9iamVjdC5hc3NpZ24odGhpcywgdGhlX3ZhbHVlcyk7XG4gICAgfVxuXG4gICAgc3RhdGljIGNyZWF0ZSh1cGRhdGVzID0ge30pIHtcbiAgICAgIGxldCB4ID0gbmV3IHRoaXModXBkYXRlcyk7XG4gICAgICByZXR1cm4gT2JqZWN0LmZyZWV6ZSh4KTtcbiAgICB9XG4gIH07XG59XG5cbmZ1bmN0aW9uIGRlZmV4Y2VwdGlvbihkZWZhdWx0cykge1xuICByZXR1cm4gY2xhc3MgZXh0ZW5kcyBFcnJvciB7XG4gICAgY29uc3RydWN0b3IodXBkYXRlID0ge30pIHtcbiAgICAgIGxldCBtZXNzYWdlID0gdXBkYXRlLm1lc3NhZ2UgfHwgJyc7XG4gICAgICBzdXBlcihtZXNzYWdlKTtcblxuICAgICAgbGV0IHRoZV92YWx1ZXMgPSBPYmplY3QuYXNzaWduKGRlZmF1bHRzLCB1cGRhdGUpO1xuICAgICAgT2JqZWN0LmFzc2lnbih0aGlzLCB0aGVfdmFsdWVzKTtcblxuICAgICAgdGhpcy5uYW1lID0gdGhpcy5jb25zdHJ1Y3Rvci5uYW1lO1xuICAgICAgdGhpcy5tZXNzYWdlID0gbWVzc2FnZTtcbiAgICAgIHRoaXNbU3BlY2lhbEZvcm1zLmF0b20oJ19fZXhjZXB0aW9uX18nKV0gPSB0cnVlO1xuICAgICAgRXJyb3IuY2FwdHVyZVN0YWNrVHJhY2UodGhpcywgdGhpcy5jb25zdHJ1Y3Rvci5uYW1lKTtcbiAgICB9XG5cbiAgICBzdGF0aWMgY3JlYXRlKHVwZGF0ZXMgPSB7fSkge1xuICAgICAgbGV0IHggPSBuZXcgdGhpcyh1cGRhdGVzKTtcbiAgICAgIHJldHVybiBPYmplY3QuZnJlZXplKHgpO1xuICAgIH1cbiAgfTtcbn1cblxuZnVuY3Rpb24gZGVmcHJvdG9jb2woc3BlYykge1xuICByZXR1cm4gbmV3IFByb3RvY29sKHNwZWMpO1xufVxuXG5mdW5jdGlvbiBkZWZpbXBsKHByb3RvY29sLCB0eXBlLCBpbXBsKSB7XG4gIHByb3RvY29sLmltcGxlbWVudGF0aW9uKHR5cGUsIGltcGwpO1xufVxuXG5mdW5jdGlvbiBnZXRfb2JqZWN0X2tleXMob2JqKSB7XG4gIHJldHVybiBPYmplY3Qua2V5cyhvYmopLmNvbmNhdChPYmplY3QuZ2V0T3duUHJvcGVydHlTeW1ib2xzKG9iaikpO1xufVxuXG5mdW5jdGlvbiBpc192YWxpZF9jaGFyYWN0ZXIoY29kZXBvaW50KSB7XG4gIHRyeSB7XG4gICAgcmV0dXJuIFN0cmluZy5mcm9tQ29kZVBvaW50KGNvZGVwb2ludCkgIT0gbnVsbDtcbiAgfSBjYXRjaCAoZSkge1xuICAgIHJldHVybiBmYWxzZTtcbiAgfVxufVxuXG4vL2h0dHBzOi8vZGV2ZWxvcGVyLm1vemlsbGEub3JnL2VuLVVTL2RvY3MvV2ViL0FQSS9XaW5kb3dCYXNlNjQvQmFzZTY0X2VuY29kaW5nX2FuZF9kZWNvZGluZyNTb2x1dGlvbl8yXyVFMiU4MCU5M19yZXdyaXRlX3RoZV9ET01zX2F0b2IoKV9hbmRfYnRvYSgpX3VzaW5nX0phdmFTY3JpcHQnc19UeXBlZEFycmF5c19hbmRfVVRGLThcbmZ1bmN0aW9uIGI2NEVuY29kZVVuaWNvZGUoc3RyKSB7XG4gIHJldHVybiBidG9hKGVuY29kZVVSSUNvbXBvbmVudChzdHIpLnJlcGxhY2UoLyUoWzAtOUEtRl17Mn0pL2csIGZ1bmN0aW9uIChtYXRjaCwgcDEpIHtcbiAgICByZXR1cm4gU3RyaW5nLmZyb21DaGFyQ29kZSgnMHgnICsgcDEpO1xuICB9KSk7XG59XG5cbmZ1bmN0aW9uIGRlbGV0ZV9wcm9wZXJ0eV9mcm9tX21hcChtYXAsIHByb3BlcnR5KSB7XG4gIGxldCBuZXdfbWFwID0gT2JqZWN0LmFzc2lnbihPYmplY3QuY3JlYXRlKG1hcC5jb25zdHJ1Y3Rvci5wcm90b3R5cGUpLCBtYXApO1xuICBkZWxldGUgbmV3X21hcFtwcm9wZXJ0eV07XG5cbiAgcmV0dXJuIE9iamVjdC5mcmVlemUobmV3X21hcCk7XG59XG5cbmZ1bmN0aW9uIGNsYXNzX3RvX29iaihtYXApIHtcbiAgbGV0IG5ld19tYXAgPSBPYmplY3QuYXNzaWduKHt9LCBtYXApO1xuICByZXR1cm4gT2JqZWN0LmZyZWV6ZShuZXdfbWFwKTtcbn1cblxuZnVuY3Rpb24gYWRkX3Byb3BlcnR5X3RvX21hcChtYXAsIHByb3BlcnR5LCB2YWx1ZSkge1xuICBsZXQgbmV3X21hcCA9IE9iamVjdC5hc3NpZ24oe30sIG1hcCk7XG4gIG5ld19tYXBbcHJvcGVydHldID0gdmFsdWU7XG4gIHJldHVybiBPYmplY3QuZnJlZXplKG5ld19tYXApO1xufVxuXG5mdW5jdGlvbiB1cGRhdGVfbWFwKG1hcCwgcHJvcGVydHksIHZhbHVlKSB7XG4gIGlmIChwcm9wZXJ0eSBpbiBnZXRfb2JqZWN0X2tleXMobWFwKSkge1xuICAgIHJldHVybiBhZGRfcHJvcGVydHlfdG9fbWFwKG1hcCwgcHJvcGVydHksIHZhbHVlKTtcbiAgfVxuXG4gIHRocm93ICdtYXAgZG9lcyBub3QgaGF2ZSBrZXknO1xufVxuXG5mdW5jdGlvbiBibm90KGV4cHIpIHtcbiAgcmV0dXJuIH5leHByO1xufVxuXG5mdW5jdGlvbiBiYW5kKGxlZnQsIHJpZ2h0KSB7XG4gIHJldHVybiBsZWZ0ICYgcmlnaHQ7XG59XG5cbmZ1bmN0aW9uIGJvcihsZWZ0LCByaWdodCkge1xuICByZXR1cm4gbGVmdCB8IHJpZ2h0O1xufVxuXG5mdW5jdGlvbiBic2wobGVmdCwgcmlnaHQpIHtcbiAgcmV0dXJuIGxlZnQgPDwgcmlnaHQ7XG59XG5cbmZ1bmN0aW9uIGJzcihsZWZ0LCByaWdodCkge1xuICByZXR1cm4gbGVmdCA+PiByaWdodDtcbn1cblxuZnVuY3Rpb24gYnhvcihsZWZ0LCByaWdodCkge1xuICByZXR1cm4gbGVmdCBeIHJpZ2h0O1xufVxuXG5mdW5jdGlvbiB6aXAobGlzdF9vZl9saXN0cykge1xuICBpZiAobGlzdF9vZl9saXN0cy5sZW5ndGggPT09IDApIHtcbiAgICByZXR1cm4gT2JqZWN0LmZyZWV6ZShbXSk7XG4gIH1cblxuICBsZXQgbmV3X3ZhbHVlID0gW107XG4gIGxldCBzbWFsbGVzdF9sZW5ndGggPSBsaXN0X29mX2xpc3RzWzBdO1xuXG4gIGZvciAobGV0IHggb2YgbGlzdF9vZl9saXN0cykge1xuICAgIGlmICh4Lmxlbmd0aCA8IHNtYWxsZXN0X2xlbmd0aCkge1xuICAgICAgc21hbGxlc3RfbGVuZ3RoID0geC5sZW5ndGg7XG4gICAgfVxuICB9XG5cbiAgZm9yIChsZXQgaSA9IDA7IGkgPCBzbWFsbGVzdF9sZW5ndGg7IGkrKykge1xuICAgIGxldCBjdXJyZW50X3ZhbHVlID0gW107XG4gICAgZm9yIChsZXQgaiA9IDA7IGogPCBsaXN0X29mX2xpc3RzLmxlbmd0aDsgaisrKSB7XG4gICAgICBjdXJyZW50X3ZhbHVlLnB1c2gobGlzdF9vZl9saXN0c1tqXVtpXSk7XG4gICAgfVxuXG4gICAgbmV3X3ZhbHVlLnB1c2gobmV3IFR1cGxlKC4uLmN1cnJlbnRfdmFsdWUpKTtcbiAgfVxuXG4gIHJldHVybiBPYmplY3QuZnJlZXplKG5ld192YWx1ZSk7XG59XG5cbmZ1bmN0aW9uIGNhbl9kZWNvZGU2NChkYXRhKSB7XG4gIHRyeSB7XG4gICAgYXRvYihkYXRhKTtcbiAgICByZXR1cm4gdHJ1ZTtcbiAgfSBjYXRjaCAoZSkge1xuICAgIHJldHVybiBmYWxzZTtcbiAgfVxufVxuXG5mdW5jdGlvbiByZW1vdmVfZnJvbV9saXN0KGxpc3QsIGVsZW1lbnQpIHtcbiAgbGV0IGZvdW5kID0gZmFsc2U7XG5cbiAgcmV0dXJuIGxpc3QuZmlsdGVyKGVsZW0gPT4ge1xuICAgIGlmICghZm91bmQgJiYgZWxlbSA9PT0gZWxlbWVudCkge1xuICAgICAgZm91bmQgPSB0cnVlO1xuICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH1cblxuICAgIHJldHVybiB0cnVlO1xuICB9KTtcbn1cblxuZnVuY3Rpb24gZm9sZGwoZnVuLCBhY2MsIGxpc3QpIHtcbiAgbGV0IGFjYzEgPSBhY2M7XG5cbiAgZm9yIChjb25zdCBlbCBvZiBsaXN0KSB7XG4gICAgYWNjMSA9IGZ1bihlbCwgYWNjMSk7XG4gIH1cblxuICByZXR1cm4gYWNjMTtcbn1cblxuZnVuY3Rpb24gZm9sZHIoZnVuLCBhY2MsIGxpc3QpIHtcbiAgbGV0IGFjYzEgPSBhY2M7XG5cbiAgZm9yIChsZXQgaSA9IGxpc3QubGVuZ3RoIC0gMTsgaSA+PSAwOyBpLS0pIHtcbiAgICBhY2MxID0gZnVuKGxpc3RbaV0sIGFjYzEpO1xuICB9XG5cbiAgcmV0dXJuIGFjYzE7XG59XG5cbmZ1bmN0aW9uIGtleWZpbmQoa2V5LCBuLCB0dXBsZWxpc3QpIHtcblxuICBmb3IgKGxldCBpID0gdHVwbGVsaXN0Lmxlbmd0aCAtIDE7IGkgPj0gMDsgaS0tKSB7XG4gICAgaWYgKHR1cGxlbGlzdFtpXS5nZXQobikgPT09IGtleSkge1xuICAgICAgcmV0dXJuIHR1cGxlbGlzdFtpXTtcbiAgICB9XG4gIH1cblxuICByZXR1cm4gZmFsc2U7XG59XG5cbmZ1bmN0aW9uIGtleWRlbGV0ZShrZXksIG4sIHR1cGxlbGlzdCkge1xuXG4gIGZvciAobGV0IGkgPSB0dXBsZWxpc3QubGVuZ3RoIC0gMTsgaSA+PSAwOyBpLS0pIHtcbiAgICBpZiAodHVwbGVsaXN0W2ldLmdldChuKSA9PT0ga2V5KSB7XG4gICAgICByZXR1cm4gdHVwbGVsaXN0LmNvbmNhdChbXSkuc3BsaWNlKGksIDEpO1xuICAgIH1cbiAgfVxuXG4gIHJldHVybiB0dXBsZWxpc3Q7XG59XG5cbmZ1bmN0aW9uIGtleXN0b3JlKGtleSwgbiwgbGlzdCwgbmV3dHVwbGUpIHtcbiAgZm9yIChsZXQgaSA9IGxpc3QubGVuZ3RoIC0gMTsgaSA+PSAwOyBpLS0pIHtcbiAgICBpZiAobGlzdFtpXS5nZXQobikgPT09IGtleSkge1xuICAgICAgcmV0dXJuIGxpc3QuY29uY2F0KFtdKS5zcGxpY2UoaSwgMSwgbmV3dHVwbGUpO1xuICAgIH1cbiAgfVxuXG4gIHJldHVybiBsaXN0LmNvbmNhdChbXSkucHVzaChuZXd0dXBsZSk7XG59XG5cbmZ1bmN0aW9uIGtleW1lbWJlcihrZXksIG4sIGxpc3QpIHtcbiAgZm9yIChsZXQgaSA9IGxpc3QubGVuZ3RoIC0gMTsgaSA+PSAwOyBpLS0pIHtcbiAgICBpZiAobGlzdFtpXS5nZXQobikgPT09IGtleSkge1xuICAgICAgcmV0dXJuIHRydWU7XG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIGZhbHNlO1xufVxuXG5mdW5jdGlvbiBrZXl0YWtlKGtleSwgbiwgbGlzdCkge1xuICBpZiAoIWtleW1lbWJlcihrZXksIG4sIGxpc3QpKSB7XG4gICAgcmV0dXJuIGZhbHNlO1xuICB9XG5cbiAgbGV0IHR1cGxlID0ga2V5ZmluZChrZXksIG4sIGxpc3QpO1xuXG4gIHJldHVybiBuZXcgVHVwbGUodHVwbGUuZ2V0KG4pLCB0dXBsZSwga2V5ZGVsZXRlKGtleSwgbiwgbGlzdCkpO1xufVxuXG5mdW5jdGlvbiBrZXlyZXBsYWNlKGtleSwgbiwgbGlzdCwgbmV3dHVwbGUpIHtcblxuICBmb3IgKGxldCBpID0gdHVwbGVsaXN0Lmxlbmd0aCAtIDE7IGkgPj0gMDsgaS0tKSB7XG4gICAgaWYgKHR1cGxlbGlzdFtpXS5nZXQobikgPT09IGtleSkge1xuICAgICAgcmV0dXJuIHR1cGxlbGlzdC5jb25jYXQoW10pLnNwbGljZShpLCAxLCBuZXd0dXBsZSk7XG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIHR1cGxlbGlzdDtcbn1cblxuZnVuY3Rpb24gcmV2ZXJzZShsaXN0KSB7XG4gIHJldHVybiBsaXN0LmNvbmNhdChbXSkucmV2ZXJzZSgpO1xufVxuXG5mdW5jdGlvbiBtYXBzX2ZpbmQoa2V5LCBtYXApIHtcbiAgaWYgKGtleSBpbiBnZXRfb2JqZWN0X2tleXMobWFwKSkge1xuICAgIHJldHVybiBuZXcgVHVwbGUoU3ltYm9sLmZvcignb2snKSwgbWFwW2tleV0pO1xuICB9IGVsc2Uge1xuICAgIHJldHVybiBTeW1ib2wuZm9yKCdlcnJvcicpO1xuICB9XG59XG5cbmZ1bmN0aW9uIGZsYXR0ZW4obGlzdCwgdGFpbCA9IFtdKSB7XG4gIGxldCBuZXdfbGlzdCA9IFtdO1xuXG4gIGZvciAobGV0IGUgb2YgbGlzdCkge1xuICAgIGlmIChpc0FycmF5KGUpKSB7XG4gICAgICBuZXdfbGlzdCA9IG5ld19saXN0LmNvbmNhdChmbGF0dGVuKGUpKTtcbiAgICB9IGVsc2Uge1xuICAgICAgbmV3X2xpc3QucHVzaChlKTtcbiAgICB9XG4gIH1cblxuICByZXR1cm4gT2JqZWN0LmZyZWV6ZShuZXdfbGlzdC5jb25jYXQodGFpbCkpO1xufVxuXG5mdW5jdGlvbiBkdXBsaWNhdGUobiwgZWxlbSkge1xuICBsZXQgbGlzdCA9IFtdO1xuXG4gIGZvciAobGV0IGkgPSAwOyBpIDwgbjsgaSsrKSB7XG4gICAgbGlzdC5wdXNoKGVsZW0pO1xuICB9XG5cbiAgcmV0dXJuIE9iamVjdC5mcmVlemUobGlzdCk7XG59XG5cbmZ1bmN0aW9uIG1hcGZvbGRsKGZ1biwgYWNjLCBsaXN0KSB7XG4gIGxldCBuZXdsaXN0ID0gW107XG5cbiAgZm9yIChsZXQgeCBvZiBsaXN0KSB7XG4gICAgbGV0IHR1cCA9IGZ1bih4LCBhY2MpO1xuICAgIG5ld2xpc3QucHVzaCh0dXAuZ2V0KDApKTtcbiAgICBhY2MgPSB0dXAuZ2V0KDEpO1xuICB9XG5cbiAgcmV0dXJuIG5ldyBUdXBsZShPYmplY3QuZnJlZXplKG5ld2xpc3QpLCBhY2MpO1xufVxuXG5mdW5jdGlvbiBmaWx0ZXJtYXAoZnVuLCBsaXN0KSB7XG4gIGxldCBuZXdsaXN0ID0gW107XG5cbiAgZm9yICh4IG9mIGxpc3QpIHtcbiAgICBsZXQgcmVzdWx0ID0gZnVuKHgpO1xuXG4gICAgaWYgKHJlc3VsdCA9PT0gdHJ1ZSkge1xuICAgICAgbmV3bGlzdC5wdXNoKHgpO1xuICAgIH0gZWxzZSBpZiAocmVzdWx0IGluc3RhbmNlb2YgVHVwbGUpIHtcbiAgICAgIG5ld2xpc3QucHVzaChyZXN1bHQuZ2V0KDEpKTtcbiAgICB9XG4gIH1cblxuICByZXR1cm4gT2JqZWN0LmZyZWV6ZShuZXdsaXN0KTtcbn1cblxuZnVuY3Rpb24gbWFwc19mb2xkKGZ1biwgYWNjLCBtYXApIHtcbiAgbGV0IGFjYzEgPSBhY2M7XG5cbiAgZm9yIChsZXQgayBvZiBnZXRfb2JqZWN0X2tleXMobWFwKSkge1xuICAgIGFjYzEgPSBmdW4oaywgbWFwW2tdLCBhY2MxKTtcbiAgfVxuXG4gIHJldHVybiBhY2MxO1xufVxuXG52YXIgRnVuY3Rpb25zID0ge1xuICBjYWxsX3Byb3BlcnR5LFxuICBhcHBseSxcbiAgY29udGFpbnMsXG4gIGdldF9nbG9iYWwsXG4gIGRlZnN0cnVjdCxcbiAgZGVmZXhjZXB0aW9uLFxuICBkZWZwcm90b2NvbCxcbiAgZGVmaW1wbCxcbiAgZ2V0X29iamVjdF9rZXlzLFxuICBpc192YWxpZF9jaGFyYWN0ZXIsXG4gIGI2NEVuY29kZVVuaWNvZGUsXG4gIGRlbGV0ZV9wcm9wZXJ0eV9mcm9tX21hcCxcbiAgYWRkX3Byb3BlcnR5X3RvX21hcCxcbiAgY2xhc3NfdG9fb2JqLFxuICBjYW5fZGVjb2RlNjQsXG4gIGJub3QsXG4gIGJhbmQsXG4gIGJvcixcbiAgYnNsLFxuICBic3IsXG4gIGJ4b3IsXG4gIHppcCxcbiAgZm9sZGwsXG4gIGZvbGRyLFxuICByZW1vdmVfZnJvbV9saXN0LFxuICBrZXlkZWxldGUsXG4gIGtleXN0b3JlLFxuICBrZXlmaW5kLFxuICBrZXl0YWtlLFxuICBrZXlyZXBsYWNlLFxuICByZXZlcnNlLFxuICB1cGRhdGVfbWFwLFxuICBtYXBzX2ZpbmQsXG4gIGZsYXR0ZW4sXG4gIGR1cGxpY2F0ZSxcbiAgbWFwZm9sZGwsXG4gIGZpbHRlcm1hcCxcbiAgbWFwc19mb2xkXG59O1xuXG5mdW5jdGlvbiBfY2FzZShjb25kaXRpb24sIGNsYXVzZXMpIHtcbiAgcmV0dXJuIFBhdHRlcm5zLmRlZm1hdGNoKC4uLmNsYXVzZXMpKGNvbmRpdGlvbik7XG59XG5cbmZ1bmN0aW9uIGNvbmQoY2xhdXNlcykge1xuICBmb3IgKGxldCBjbGF1c2Ugb2YgY2xhdXNlcykge1xuICAgIGlmIChjbGF1c2VbMF0pIHtcbiAgICAgIHJldHVybiBjbGF1c2VbMV0oKTtcbiAgICB9XG4gIH1cblxuICB0aHJvdyBuZXcgRXJyb3IoKTtcbn1cblxuZnVuY3Rpb24gbWFwX3VwZGF0ZShtYXAsIHZhbHVlcykge1xuICByZXR1cm4gT2JqZWN0LmZyZWV6ZShPYmplY3QuYXNzaWduKE9iamVjdC5jcmVhdGUobWFwLmNvbnN0cnVjdG9yLnByb3RvdHlwZSksIG1hcCwgdmFsdWVzKSk7XG59XG5cbmZ1bmN0aW9uIF9mb3IoY29sbGVjdGlvbnMsIGZ1biwgZmlsdGVyID0gKCkgPT4gdHJ1ZSwgaW50byA9IFtdLCBwcmV2aW91c1ZhbHVlcyA9IFtdKSB7XG4gIGxldCBwYXR0ZXJuID0gY29sbGVjdGlvbnNbMF1bMF07XG4gIGxldCBjb2xsZWN0aW9uID0gY29sbGVjdGlvbnNbMF1bMV07XG5cbiAgaWYgKGNvbGxlY3Rpb25zLmxlbmd0aCA9PT0gMSkge1xuXG4gICAgZm9yIChsZXQgZWxlbSBvZiBjb2xsZWN0aW9uKSB7XG4gICAgICBsZXQgciA9IFBhdHRlcm5zLm1hdGNoX25vX3Rocm93KHBhdHRlcm4sIGVsZW0pO1xuICAgICAgbGV0IGFyZ3MgPSBwcmV2aW91c1ZhbHVlcy5jb25jYXQocik7XG5cbiAgICAgIGlmIChyICYmIGZpbHRlci5hcHBseSh0aGlzLCBhcmdzKSkge1xuICAgICAgICBpbnRvID0gaW50by5jb25jYXQoW2Z1bi5hcHBseSh0aGlzLCBhcmdzKV0pO1xuICAgICAgfVxuICAgIH1cblxuICAgIHJldHVybiBpbnRvO1xuICB9IGVsc2Uge1xuICAgIGxldCBfaW50byA9IFtdO1xuXG4gICAgZm9yIChsZXQgZWxlbSBvZiBjb2xsZWN0aW9uKSB7XG4gICAgICBsZXQgciA9IFBhdHRlcm5zLm1hdGNoX25vX3Rocm93KHBhdHRlcm4sIGVsZW0pO1xuICAgICAgaWYgKHIpIHtcbiAgICAgICAgX2ludG8gPSBpbnRvLmNvbmNhdCh0aGlzLl9mb3IoY29sbGVjdGlvbnMuc2xpY2UoMSksIGZ1biwgZmlsdGVyLCBfaW50bywgcHJldmlvdXNWYWx1ZXMuY29uY2F0KHIpKSk7XG4gICAgICB9XG4gICAgfVxuXG4gICAgcmV0dXJuIF9pbnRvO1xuICB9XG59XG5cbmZ1bmN0aW9uIF90cnkoZG9fZnVuLCByZXNjdWVfZnVuY3Rpb24sIGNhdGNoX2Z1biwgZWxzZV9mdW5jdGlvbiwgYWZ0ZXJfZnVuY3Rpb24pIHtcbiAgbGV0IHJlc3VsdCA9IG51bGw7XG5cbiAgdHJ5IHtcbiAgICByZXN1bHQgPSBkb19mdW4oKTtcbiAgfSBjYXRjaCAoZSkge1xuICAgIGxldCBleF9yZXN1bHQgPSBudWxsO1xuXG4gICAgaWYgKHJlc2N1ZV9mdW5jdGlvbikge1xuICAgICAgdHJ5IHtcbiAgICAgICAgZXhfcmVzdWx0ID0gcmVzY3VlX2Z1bmN0aW9uKGUpO1xuICAgICAgICByZXR1cm4gZXhfcmVzdWx0O1xuICAgICAgfSBjYXRjaCAoZXgpIHtcbiAgICAgICAgaWYgKGV4IGluc3RhbmNlb2YgUGF0dGVybnMuTWF0Y2hFcnJvcikge1xuICAgICAgICAgIHRocm93IGV4O1xuICAgICAgICB9XG4gICAgICB9XG4gICAgfVxuXG4gICAgaWYgKGNhdGNoX2Z1bikge1xuICAgICAgdHJ5IHtcbiAgICAgICAgZXhfcmVzdWx0ID0gY2F0Y2hfZnVuKGUpO1xuICAgICAgICByZXR1cm4gZXhfcmVzdWx0O1xuICAgICAgfSBjYXRjaCAoZXgpIHtcbiAgICAgICAgaWYgKGV4IGluc3RhbmNlb2YgUGF0dGVybnMuTWF0Y2hFcnJvcikge1xuICAgICAgICAgIHRocm93IGV4O1xuICAgICAgICB9XG4gICAgICB9XG4gICAgfVxuXG4gICAgdGhyb3cgZTtcbiAgfSBmaW5hbGx5IHtcbiAgICBpZiAoYWZ0ZXJfZnVuY3Rpb24pIHtcbiAgICAgIGFmdGVyX2Z1bmN0aW9uKCk7XG4gICAgfVxuICB9XG5cbiAgaWYgKGVsc2VfZnVuY3Rpb24pIHtcbiAgICB0cnkge1xuICAgICAgcmV0dXJuIGVsc2VfZnVuY3Rpb24ocmVzdWx0KTtcbiAgICB9IGNhdGNoIChleCkge1xuICAgICAgaWYgKGV4IGluc3RhbmNlb2YgUGF0dGVybnMuTWF0Y2hFcnJvcikge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ05vIE1hdGNoIEZvdW5kIGluIEVsc2UnKTtcbiAgICAgIH1cblxuICAgICAgdGhyb3cgZXg7XG4gICAgfVxuICB9IGVsc2Uge1xuICAgIHJldHVybiByZXN1bHQ7XG4gIH1cbn1cblxudmFyIFNwZWNpYWxGb3JtcyQxID0ge1xuICBfY2FzZSxcbiAgY29uZCxcbiAgbWFwX3VwZGF0ZSxcbiAgX2ZvcixcbiAgX3RyeVxufTtcblxuRnVuY3Rpb25zLmdldF9nbG9iYWwoKS5wcm9jZXNzZXMgPSBGdW5jdGlvbnMuZ2V0X2dsb2JhbCgpLnByb2Nlc3NlcyB8fCBuZXcgUHJvY2Vzc1N5c3RlbSgpO1xuXG52YXIgQ29yZSA9IHtcbiAgUHJvY2Vzc1N5c3RlbSxcbiAgVHVwbGUsXG4gIFBJRCxcbiAgQml0U3RyaW5nLFxuICBQYXR0ZXJucyxcbiAgSW50ZWdlcixcbiAgRmxvYXQsXG4gIEZ1bmN0aW9ucyxcbiAgU3BlY2lhbEZvcm1zOiBTcGVjaWFsRm9ybXMkMVxufTtcblxubGV0IEVudW0gPSB7XG5cbiAgYWxsX19xbWFya19fOiBmdW5jdGlvbiAoY29sbGVjdGlvbiwgZnVuID0geCA9PiB4KSB7XG4gICAgZm9yIChsZXQgZWxlbSBvZiBjb2xsZWN0aW9uKSB7XG4gICAgICBpZiAoIWZ1bihlbGVtKSkge1xuICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICB9XG4gICAgfVxuXG4gICAgcmV0dXJuIHRydWU7XG4gIH0sXG5cbiAgYW55X19xbWFya19fOiBmdW5jdGlvbiAoY29sbGVjdGlvbiwgZnVuID0geCA9PiB4KSB7XG4gICAgZm9yIChsZXQgZWxlbSBvZiBjb2xsZWN0aW9uKSB7XG4gICAgICBpZiAoZnVuKGVsZW0pKSB7XG4gICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgfVxuICAgIH1cblxuICAgIHJldHVybiBmYWxzZTtcbiAgfSxcblxuICBhdDogZnVuY3Rpb24gKGNvbGxlY3Rpb24sIG4sIHRoZV9kZWZhdWx0ID0gbnVsbCkge1xuICAgIGlmIChuID4gdGhpcy5jb3VudChjb2xsZWN0aW9uKSB8fCBuIDwgMCkge1xuICAgICAgcmV0dXJuIHRoZV9kZWZhdWx0O1xuICAgIH1cblxuICAgIHJldHVybiBjb2xsZWN0aW9uW25dO1xuICB9LFxuXG4gIGNvbmNhdDogZnVuY3Rpb24gKC4uLmVudW1hYmxlcykge1xuICAgIHJldHVybiBlbnVtYWJsZXNbMF0uY29uY2F0KGVudW1hYmxlc1sxXSk7XG4gIH0sXG5cbiAgY291bnQ6IGZ1bmN0aW9uIChjb2xsZWN0aW9uLCBmdW4gPSBudWxsKSB7XG4gICAgaWYgKGZ1biA9PSBudWxsKSB7XG4gICAgICByZXR1cm4gY29sbGVjdGlvbi5sZW5ndGg7XG4gICAgfSBlbHNlIHtcbiAgICAgIHJldHVybiBjb2xsZWN0aW9uLmZpbHRlcihmdW4pLmxlbmd0aDtcbiAgICB9XG4gIH0sXG5cbiAgZHJvcDogZnVuY3Rpb24gKGNvbGxlY3Rpb24sIGNvdW50KSB7XG4gICAgcmV0dXJuIGNvbGxlY3Rpb24uc2xpY2UoY291bnQpO1xuICB9LFxuXG4gIGRyb3Bfd2hpbGU6IGZ1bmN0aW9uIChjb2xsZWN0aW9uLCBmdW4pIHtcbiAgICBsZXQgY291bnQgPSAwO1xuXG4gICAgZm9yIChsZXQgZWxlbSBvZiBjb2xsZWN0aW9uKSB7XG4gICAgICBpZiAoZnVuKGVsZW0pKSB7XG4gICAgICAgIGNvdW50ID0gY291bnQgKyAxO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgYnJlYWs7XG4gICAgICB9XG4gICAgfVxuXG4gICAgcmV0dXJuIGNvbGxlY3Rpb24uc2xpY2UoY291bnQpO1xuICB9LFxuXG4gIGVhY2g6IGZ1bmN0aW9uIChjb2xsZWN0aW9uLCBmdW4pIHtcbiAgICBmb3IgKGxldCBlbGVtIG9mIGNvbGxlY3Rpb24pIHtcbiAgICAgIGZ1bihlbGVtKTtcbiAgICB9XG4gIH0sXG5cbiAgZW1wdHlfX3FtYXJrX186IGZ1bmN0aW9uIChjb2xsZWN0aW9uKSB7XG4gICAgcmV0dXJuIGNvbGxlY3Rpb24ubGVuZ3RoID09PSAwO1xuICB9LFxuXG4gIGZldGNoOiBmdW5jdGlvbiAoY29sbGVjdGlvbiwgbikge1xuICAgIGlmIChBcnJheS5pc0FycmF5KGNvbGxlY3Rpb24pKSB7XG4gICAgICBpZiAobiA8IHRoaXMuY291bnQoY29sbGVjdGlvbikgJiYgbiA+PSAwKSB7XG4gICAgICAgIHJldHVybiBuZXcgQ29yZS5UdXBsZShTeW1ib2wuZm9yKFwib2tcIiksIGNvbGxlY3Rpb25bbl0pO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgcmV0dXJuIFN5bWJvbC5mb3IoXCJlcnJvclwiKTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICB0aHJvdyBuZXcgRXJyb3IoXCJjb2xsZWN0aW9uIGlzIG5vdCBhbiBFbnVtZXJhYmxlXCIpO1xuICB9LFxuXG4gIGZldGNoX19lbWFya19fOiBmdW5jdGlvbiAoY29sbGVjdGlvbiwgbikge1xuICAgIGlmIChBcnJheS5pc0FycmF5KGNvbGxlY3Rpb24pKSB7XG4gICAgICBpZiAobiA8IHRoaXMuY291bnQoY29sbGVjdGlvbikgJiYgbiA+PSAwKSB7XG4gICAgICAgIHJldHVybiBjb2xsZWN0aW9uW25dO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKFwib3V0IG9mIGJvdW5kcyBlcnJvclwiKTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICB0aHJvdyBuZXcgRXJyb3IoXCJjb2xsZWN0aW9uIGlzIG5vdCBhbiBFbnVtZXJhYmxlXCIpO1xuICB9LFxuXG4gIGZpbHRlcjogZnVuY3Rpb24gKGNvbGxlY3Rpb24sIGZ1bikge1xuICAgIGxldCByZXN1bHQgPSBbXTtcblxuICAgIGZvciAobGV0IGVsZW0gb2YgY29sbGVjdGlvbikge1xuICAgICAgaWYgKGZ1bihlbGVtKSkge1xuICAgICAgICByZXN1bHQucHVzaChlbGVtKTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICByZXR1cm4gcmVzdWx0O1xuICB9LFxuXG4gIGZpbHRlcl9tYXA6IGZ1bmN0aW9uIChjb2xsZWN0aW9uLCBmaWx0ZXIsIG1hcHBlcikge1xuICAgIHJldHVybiBFbnVtLm1hcChFbnVtLmZpbHRlcihjb2xsZWN0aW9uLCBmaWx0ZXIpLCBtYXBwZXIpO1xuICB9LFxuXG4gIGZpbmQ6IGZ1bmN0aW9uIChjb2xsZWN0aW9uLCBpZl9ub25lID0gbnVsbCwgZnVuKSB7XG4gICAgZm9yIChsZXQgZWxlbSBvZiBjb2xsZWN0aW9uKSB7XG4gICAgICBpZiAoZnVuKGVsZW0pKSB7XG4gICAgICAgIHJldHVybiBlbGVtO1xuICAgICAgfVxuICAgIH1cblxuICAgIHJldHVybiBpZl9ub25lO1xuICB9LFxuXG4gIGludG86IGZ1bmN0aW9uIChjb2xsZWN0aW9uLCBsaXN0KSB7XG4gICAgcmV0dXJuIGxpc3QuY29uY2F0KGNvbGxlY3Rpb24pO1xuICB9LFxuXG4gIG1hcDogZnVuY3Rpb24gKGNvbGxlY3Rpb24sIGZ1bikge1xuICAgIGxldCByZXN1bHQgPSBbXTtcblxuICAgIGZvciAobGV0IGVsZW0gb2YgY29sbGVjdGlvbikge1xuICAgICAgcmVzdWx0LnB1c2goZnVuKGVsZW0pKTtcbiAgICB9XG5cbiAgICByZXR1cm4gcmVzdWx0O1xuICB9LFxuXG4gIG1hcF9yZWR1Y2U6IGZ1bmN0aW9uIChjb2xsZWN0aW9uLCBhY2MsIGZ1bikge1xuICAgIGxldCBtYXBwZWQgPSBPYmplY3QuZnJlZXplKFtdKTtcbiAgICBsZXQgdGhlX2FjYyA9IGFjYztcblxuICAgIGZvciAodmFyIGkgPSAwOyBpIDwgdGhpcy5jb3VudChjb2xsZWN0aW9uKTsgaSsrKSB7XG4gICAgICBsZXQgdHVwbGUgPSBmdW4oY29sbGVjdGlvbltpXSwgdGhlX2FjYyk7XG5cbiAgICAgIHRoZV9hY2MgPSB0dXBsZS5nZXQoMSk7XG4gICAgICBtYXBwZWQgPSBPYmplY3QuZnJlZXplKG1hcHBlZC5jb25jYXQoW3R1cGxlLmdldCgwKV0pKTtcbiAgICB9XG5cbiAgICByZXR1cm4gbmV3IENvcmUuVHVwbGUobWFwcGVkLCB0aGVfYWNjKTtcbiAgfSxcblxuICBtZW1iZXJfX3FtYXJrX186IGZ1bmN0aW9uIChjb2xsZWN0aW9uLCB2YWx1ZSkge1xuICAgIHJldHVybiBjb2xsZWN0aW9uLmluY2x1ZGVzKHZhbHVlKTtcbiAgfSxcblxuICByZWR1Y2U6IGZ1bmN0aW9uIChjb2xsZWN0aW9uLCBhY2MsIGZ1bikge1xuICAgIGxldCB0aGVfYWNjID0gYWNjO1xuXG4gICAgZm9yICh2YXIgaSA9IDA7IGkgPCB0aGlzLmNvdW50KGNvbGxlY3Rpb24pOyBpKyspIHtcbiAgICAgIGxldCB0dXBsZSA9IGZ1bihjb2xsZWN0aW9uW2ldLCB0aGVfYWNjKTtcblxuICAgICAgdGhlX2FjYyA9IHR1cGxlLmdldCgxKTtcbiAgICB9XG5cbiAgICByZXR1cm4gdGhlX2FjYztcbiAgfSxcblxuICB0YWtlOiBmdW5jdGlvbiAoY29sbGVjdGlvbiwgY291bnQpIHtcbiAgICByZXR1cm4gY29sbGVjdGlvbi5zbGljZSgwLCBjb3VudCk7XG4gIH0sXG5cbiAgdGFrZV9ldmVyeTogZnVuY3Rpb24gKGNvbGxlY3Rpb24sIG50aCkge1xuICAgIGxldCByZXN1bHQgPSBbXTtcbiAgICBsZXQgaW5kZXggPSAwO1xuXG4gICAgZm9yIChsZXQgZWxlbSBvZiBjb2xsZWN0aW9uKSB7XG4gICAgICBpZiAoaW5kZXggJSBudGggPT09IDApIHtcbiAgICAgICAgcmVzdWx0LnB1c2goZWxlbSk7XG4gICAgICB9XG4gICAgfVxuXG4gICAgcmV0dXJuIE9iamVjdC5mcmVlemUocmVzdWx0KTtcbiAgfSxcblxuICB0YWtlX3doaWxlOiBmdW5jdGlvbiAoY29sbGVjdGlvbiwgZnVuKSB7XG4gICAgbGV0IGNvdW50ID0gMDtcblxuICAgIGZvciAobGV0IGVsZW0gb2YgY29sbGVjdGlvbikge1xuICAgICAgaWYgKGZ1bihlbGVtKSkge1xuICAgICAgICBjb3VudCA9IGNvdW50ICsgMTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIGJyZWFrO1xuICAgICAgfVxuICAgIH1cblxuICAgIHJldHVybiBjb2xsZWN0aW9uLnNsaWNlKDAsIGNvdW50KTtcbiAgfSxcblxuICB0b19saXN0OiBmdW5jdGlvbiAoY29sbGVjdGlvbikge1xuICAgIHJldHVybiBjb2xsZWN0aW9uO1xuICB9XG59O1xuXG52YXIgRWxpeGlyID0ge1xuICBDb3JlLFxuICBFbnVtLFxuICBWaXJ0dWFsRE9NXG59O1xuXG5leHBvcnQgZGVmYXVsdCBFbGl4aXI7Il0sImZpbGUiOiJFbGl4aXIuanMiLCJzb3VyY2VSb290IjoiL3NvdXJjZS8ifQ== \ No newline at end of file +export default elixir; +//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiRWxpeGlyLmpzIiwic291cmNlcyI6WyIuLi9zcmMvZWxpeGlyc2NyaXB0L2xpYi9jb3JlL3Byb2Nlc3Nlcy9tYWlsYm94LmpzIiwiLi4vc3JjL2VsaXhpcnNjcmlwdC9saWIvY29yZS9wcm9jZXNzZXMvc3RhdGVzLmpzIiwiLi4vc3JjL2VsaXhpcnNjcmlwdC9saWIvY29yZS9wcm9jZXNzZXMvcHJvY2Vzcy5qcyIsIi4uL3NyYy9lbGl4aXJzY3JpcHQvbGliL2NvcmUvcHJpbWl0aXZlcy5qcyIsIi4uL3NyYy9lbGl4aXJzY3JpcHQvbGliL2NvcmUvcHJvY2Vzc2VzL3Byb2Nlc3Nfc3lzdGVtLmpzIiwiLi4vc3JjL2VsaXhpcnNjcmlwdC9saWIvY29yZS9iaXRfc3RyaW5nLmpzIiwiLi4vc3JjL2VsaXhpcnNjcmlwdC9saWIvY29yZS9wYXR0ZXJucy90eXBlcy5qcyIsIi4uL3NyYy9lbGl4aXJzY3JpcHQvbGliL2NvcmUvcGF0dGVybnMvY2hlY2tzLmpzIiwiLi4vc3JjL2VsaXhpcnNjcmlwdC9saWIvY29yZS9wYXR0ZXJucy9yZXNvbHZlcnMuanMiLCIuLi9zcmMvZWxpeGlyc2NyaXB0L2xpYi9jb3JlL3BhdHRlcm5zL21hdGNoLmpzIiwiLi4vc3JjL2VsaXhpcnNjcmlwdC9saWIvY29yZS9wYXR0ZXJucy9kZWZtYXRjaC5qcyIsIi4uL3NyYy9lbGl4aXJzY3JpcHQvbGliL2NvcmUvcGF0dGVybnMuanMiLCIuLi9zcmMvZWxpeGlyc2NyaXB0L2xpYi9jb3JlL3Byb3RvY29sLmpzIiwiLi4vc3JjL2VsaXhpcnNjcmlwdC9saWIvY29yZS9mdW5jdGlvbnMuanMiLCIuLi9zcmMvZWxpeGlyc2NyaXB0L2xpYi9jb3JlL3NwZWNpYWxfZm9ybXMuanMiLCIuLi9zcmMvZWxpeGlyc2NyaXB0L2xpYi9jb3JlLmpzIiwiLi4vc3JjL2VsaXhpcnNjcmlwdC9saWIvZW51bS5qcyIsIi4uL3NyYy9lbGl4aXJzY3JpcHQvbGliL3ZpcnR1YWwtZG9tLmpzIiwiLi4vc3JjL2VsaXhpcnNjcmlwdC9lbGl4aXIuanMiXSwic291cmNlc0NvbnRlbnQiOlsiXCJ1c2Ugc3RyaWN0XCI7XG5cbmNsYXNzIE1haWxib3gge1xuXG4gIGNvbnN0cnVjdG9yKCkge1xuICAgIHRoaXMubWVzc2FnZXMgPSBbXTtcbiAgfVxuXG4gIGRlbGl2ZXIobWVzc2FnZSkge1xuICAgIHRoaXMubWVzc2FnZXMucHVzaChtZXNzYWdlKTtcbiAgICByZXR1cm4gbWVzc2FnZTtcbiAgfVxuXG4gIGdldCgpIHtcbiAgICByZXR1cm4gdGhpcy5tZXNzYWdlcztcbiAgfVxuXG4gIGlzRW1wdHkoKSB7XG4gICAgcmV0dXJuIHRoaXMubWVzc2FnZXMubGVuZ3RoID09PSAwO1xuICB9XG5cbiAgcmVtb3ZlQXQoaW5kZXgpIHtcbiAgICB0aGlzLm1lc3NhZ2VzLnNwbGljZShpbmRleCwgMSk7XG4gIH1cbn1cblxuZXhwb3J0IGRlZmF1bHQgTWFpbGJveDtcbi8vIyBzb3VyY2VNYXBwaW5nVVJMPWRhdGE6YXBwbGljYXRpb24vanNvbjtiYXNlNjQsZXlKMlpYSnphVzl1SWpvekxDSnpiM1Z5WTJWeklqcGJJbXhwWWk5amIzSmxMM0J5YjJObGMzTmxjeTl0WVdsc1ltOTRMbXB6SWwwc0ltNWhiV1Z6SWpwYlhTd2liV0Z3Y0dsdVozTWlPaUpCUVVGQk96dEJRVWxCTEUxQlFVMHNUMEZCVGl4RFFVRmhPenRCUVVkWUxHZENRVUZoTzBGQlExZ3NVMEZCU3l4UlFVRk1MRWRCUVdkQ0xFVkJRV2hDTEVOQlJGYzdSMEZCWWpzN1FVRkpRU3hWUVVGUkxFOUJRVklzUlVGQmNVSTdRVUZEYmtJc1UwRkJTeXhSUVVGTUxFTkJRV01zU1VGQlpDeERRVUZ0UWl4UFFVRnVRaXhGUVVSdFFqdEJRVVZ1UWl4WFFVRlBMRTlCUVZBc1EwRkdiVUk3UjBGQmNrSTdPMEZCUzBFc1VVRkJTenRCUVVOSUxGZEJRVThzUzBGQlN5eFJRVUZNTEVOQlJFbzdSMEZCVERzN1FVRkpRU3haUVVGVE8wRkJRMUFzVjBGQlR5eExRVUZMTEZGQlFVd3NRMEZCWXl4TlFVRmtMRXRCUVhsQ0xFTkJRWHBDTEVOQlJFRTdSMEZCVkRzN1FVRkpRU3hYUVVGVExFdEJRVlFzUlVGQlpUdEJRVU5pTEZOQlFVc3NVVUZCVEN4RFFVRmpMRTFCUVdRc1EwRkJjVUlzUzBGQmNrSXNSVUZCTkVJc1EwRkJOVUlzUlVGRVlUdEhRVUZtTzBOQmNFSkdPenRCUVhsQ1FTeGxRVUZsTEU5QlFXWWlMQ0ptYVd4bElqb2liR2xpTDJOdmNtVXZjSEp2WTJWemMyVnpMMjFoYVd4aWIzZ3Vhbk1pTENKemIzVnlZMlZ6UTI5dWRHVnVkQ0k2V3lKY0luVnpaU0J6ZEhKcFkzUmNJanRjYmx4dUx5b2dRR1pzYjNjZ0tpOWNibHh1WTJ4aGMzTWdUV0ZwYkdKdmVIdGNiaUFnYldWemMyRm5aWE02SUVGeWNtRjVQR0Z1ZVQ1Y2JseHVJQ0JqYjI1emRISjFZM1J2Y2lncGUxeHVJQ0FnSUhSb2FYTXViV1Z6YzJGblpYTWdQU0JiWFR0Y2JpQWdmVnh1WEc0Z0lHUmxiR2wyWlhJb2JXVnpjMkZuWlRvZ1lXNTVLWHRjYmlBZ0lDQjBhR2x6TG0xbGMzTmhaMlZ6TG5CMWMyZ29iV1Z6YzJGblpTazdYRzRnSUNBZ2NtVjBkWEp1SUcxbGMzTmhaMlU3WEc0Z0lIMWNibHh1SUNCblpYUW9LWHRjYmlBZ0lDQnlaWFIxY200Z2RHaHBjeTV0WlhOellXZGxjenRjYmlBZ2ZWeHVYRzRnSUdselJXMXdkSGtvS1h0Y2JpQWdJQ0J5WlhSMWNtNGdkR2hwY3k1dFpYTnpZV2RsY3k1c1pXNW5kR2dnUFQwOUlEQTdYRzRnSUgxY2JseHVJQ0J5WlcxdmRtVkJkQ2hwYm1SbGVDbDdYRzRnSUNBZ2RHaHBjeTV0WlhOellXZGxjeTV6Y0d4cFkyVW9hVzVrWlhnc0lERXBPMXh1SUNCOVhHNTlYRzVjYm1WNGNHOXlkQ0JrWldaaGRXeDBJRTFoYVd4aWIzZzdJbDBzSW5OdmRYSmpaVkp2YjNRaU9pSXZjMjkxY21ObEx5SjlcbiIsImV4cG9ydCBkZWZhdWx0IHtcbiAgTk9STUFMOiBTeW1ib2wuZm9yKFwibm9ybWFsXCIpLFxuICBLSUxMOiBTeW1ib2wuZm9yKFwia2lsbFwiKSxcbiAgU1VTUEVORDogU3ltYm9sLmZvcihcInN1c3BlbmRcIiksXG4gIENPTlRJTlVFOiBTeW1ib2wuZm9yKFwiY29udGludWVcIiksXG4gIFJFQ0VJVkU6IFN5bWJvbC5mb3IoXCJyZWNlaXZlXCIpLFxuICBTRU5EOiBTeW1ib2wuZm9yKFwic2VuZFwiKSxcbiAgU0xFRVBJTkc6IFN5bWJvbC5mb3IoXCJzbGVlcGluZ1wiKSxcbiAgUlVOTklORzogU3ltYm9sLmZvcihcInJ1bm5pbmdcIiksXG4gIFNVU1BFTkRFRDogU3ltYm9sLmZvcihcInN1c3BlbmRlZFwiKSxcbiAgU1RPUFBFRDogU3ltYm9sLmZvcihcInN0b3BwZWRcIiksXG4gIFNMRUVQOiBTeW1ib2wuZm9yKFwic2xlZXBcIiksXG4gIEVYSVQ6IFN5bWJvbC5mb3IoXCJleGl0XCIpLFxuICBOT01BVENIOiBTeW1ib2wuZm9yKFwibm9fbWF0Y2hcIilcbn07XG4vLyMgc291cmNlTWFwcGluZ1VSTD1kYXRhOmFwcGxpY2F0aW9uL2pzb247YmFzZTY0LGV5SjJaWEp6YVc5dUlqb3pMQ0p6YjNWeVkyVnpJanBiSW14cFlpOWpiM0psTDNCeWIyTmxjM05sY3k5emRHRjBaWE11YW5NaVhTd2libUZ0WlhNaU9sdGRMQ0p0WVhCd2FXNW5jeUk2SWtGQlFVRXNaVUZCWlR0QlFVTmlMRlZCUVZFc1QwRkJUeXhIUVVGUUxFTkJRVmNzVVVGQldDeERRVUZTTzBGQlEwRXNVVUZCVFN4UFFVRlBMRWRCUVZBc1EwRkJWeXhOUVVGWUxFTkJRVTQ3UVVGRFFTeFhRVUZUTEU5QlFVOHNSMEZCVUN4RFFVRlhMRk5CUVZnc1EwRkJWRHRCUVVOQkxGbEJRVlVzVDBGQlR5eEhRVUZRTEVOQlFWY3NWVUZCV0N4RFFVRldPMEZCUTBFc1YwRkJVeXhQUVVGUExFZEJRVkFzUTBGQlZ5eFRRVUZZTEVOQlFWUTdRVUZEUVN4UlFVRk5MRTlCUVU4c1IwRkJVQ3hEUVVGWExFMUJRVmdzUTBGQlRqdEJRVU5CTEZsQlFWVXNUMEZCVHl4SFFVRlFMRU5CUVZjc1ZVRkJXQ3hEUVVGV08wRkJRMEVzVjBGQlV5eFBRVUZQTEVkQlFWQXNRMEZCVnl4VFFVRllMRU5CUVZRN1FVRkRRU3hoUVVGWExFOUJRVThzUjBGQlVDeERRVUZYTEZkQlFWZ3NRMEZCV0R0QlFVTkJMRmRCUVZNc1QwRkJUeXhIUVVGUUxFTkJRVmNzVTBGQldDeERRVUZVTzBGQlEwRXNVMEZCVHl4UFFVRlBMRWRCUVZBc1EwRkJWeXhQUVVGWUxFTkJRVkE3UVVGRFFTeFJRVUZOTEU5QlFVOHNSMEZCVUN4RFFVRlhMRTFCUVZnc1EwRkJUanRCUVVOQkxGZEJRVk1zVDBGQlR5eEhRVUZRTEVOQlFWY3NWVUZCV0N4RFFVRlVPME5CWWtZaUxDSm1hV3hsSWpvaWJHbGlMMk52Y21VdmNISnZZMlZ6YzJWekwzTjBZWFJsY3k1cWN5SXNJbk52ZFhKalpYTkRiMjUwWlc1MElqcGJJbVY0Y0c5eWRDQmtaV1poZFd4MElIdGNiaUFnVGs5U1RVRk1PaUJUZVcxaWIyd3VabTl5S0Z3aWJtOXliV0ZzWENJcExGeHVJQ0JMU1V4TU9pQlRlVzFpYjJ3dVptOXlLRndpYTJsc2JGd2lLU3hjYmlBZ1UxVlRVRVZPUkRvZ1UzbHRZbTlzTG1admNpaGNJbk4xYzNCbGJtUmNJaWtzWEc0Z0lFTlBUbFJKVGxWRk9pQlRlVzFpYjJ3dVptOXlLRndpWTI5dWRHbHVkV1ZjSWlrc1hHNGdJRkpGUTBWSlZrVTZJRk41YldKdmJDNW1iM0lvWENKeVpXTmxhWFpsWENJcExGeHVJQ0JUUlU1RU9pQlRlVzFpYjJ3dVptOXlLRndpYzJWdVpGd2lLU3hjYmlBZ1UweEZSVkJKVGtjNklGTjViV0p2YkM1bWIzSW9YQ0p6YkdWbGNHbHVaMXdpS1N4Y2JpQWdVbFZPVGtsT1J6b2dVM2x0WW05c0xtWnZjaWhjSW5KMWJtNXBibWRjSWlrc1hHNGdJRk5WVTFCRlRrUkZSRG9nVTNsdFltOXNMbVp2Y2loY0luTjFjM0JsYm1SbFpGd2lLU3hjYmlBZ1UxUlBVRkJGUkRvZ1UzbHRZbTlzTG1admNpaGNJbk4wYjNCd1pXUmNJaWtzWEc0Z0lGTk1SVVZRT2lCVGVXMWliMnd1Wm05eUtGd2ljMnhsWlhCY0lpa3NYRzRnSUVWWVNWUTZJRk41YldKdmJDNW1iM0lvWENKbGVHbDBYQ0lwTEZ4dUlDQk9UMDFCVkVOSU9pQlRlVzFpYjJ3dVptOXlLRndpYm05ZmJXRjBZMmhjSWlsY2JuMGlYU3dpYzI5MWNtTmxVbTl2ZENJNklpOXpiM1Z5WTJVdkluMD1cbiIsIlwidXNlIHN0cmljdFwiO1xuXG5pbXBvcnQgTWFpbGJveCBmcm9tIFwiLi9tYWlsYm94XCI7XG5pbXBvcnQgU3RhdGVzIGZyb20gXCIuL3N0YXRlc1wiO1xuXG5jbGFzcyBQcm9jZXNzIHtcblxuICBjb25zdHJ1Y3RvcihwaWQsIG1haWxib3gpIHtcbiAgICB0aGlzLnBpZCA9IHBpZDtcbiAgICB0aGlzLm1haWxib3ggPSBtYWlsYm94O1xuICAgIHRoaXMuc3RhdHVzID0gU3RhdGVzLlNUT1BQRUQ7XG4gICAgdGhpcy5kaWN0ID0ge307XG4gIH1cbn1cblxuZXhwb3J0IGRlZmF1bHQgUHJvY2Vzcztcbi8vIyBzb3VyY2VNYXBwaW5nVVJMPWRhdGE6YXBwbGljYXRpb24vanNvbjtiYXNlNjQsZXlKMlpYSnphVzl1SWpvekxDSnpiM1Z5WTJWeklqcGJJbXhwWWk5amIzSmxMM0J5YjJObGMzTmxjeTl3Y205alpYTnpMbXB6SWwwc0ltNWhiV1Z6SWpwYlhTd2liV0Z3Y0dsdVozTWlPaUpCUVVGQk96dEJRVWRCTEU5QlFVOHNUMEZCVUN4TlFVRnZRaXhYUVVGd1FqdEJRVU5CTEU5QlFVOHNUVUZCVUN4TlFVRnRRaXhWUVVGdVFqczdRVUZGUVN4TlFVRk5MRTlCUVU0c1EwRkJZenM3UVVGTFdpeGpRVUZaTEVkQlFWb3NSVUZCZVVJc1QwRkJla0lzUlVGQk1FTTdRVUZEZUVNc1UwRkJTeXhIUVVGTUxFZEJRVmNzUjBGQldDeERRVVIzUXp0QlFVVjRReXhUUVVGTExFOUJRVXdzUjBGQlpTeFBRVUZtTEVOQlJuZERPMEZCUjNoRExGTkJRVXNzVFVGQlRDeEhRVUZqTEU5QlFVOHNUMEZCVUN4RFFVZ3dRanRCUVVsNFF5eFRRVUZMTEVsQlFVd3NSMEZCV1N4RlFVRmFMRU5CU25kRE8wZEJRVEZETzBOQlRFWTdPMEZCWVVFc1pVRkJaU3hQUVVGbUlpd2labWxzWlNJNklteHBZaTlqYjNKbEwzQnliMk5sYzNObGN5OXdjbTlqWlhOekxtcHpJaXdpYzI5MWNtTmxjME52Ym5SbGJuUWlPbHNpWENKMWMyVWdjM1J5YVdOMFhDSTdYRzVjYmk4cUlFQm1iRzkzSUNvdlhHNXBiWEJ2Y25RZ1RXRnBiR0p2ZUNCbWNtOXRJRndpTGk5dFlXbHNZbTk0WENJN1hHNXBiWEJ2Y25RZ1UzUmhkR1Z6SUdaeWIyMGdYQ0l1TDNOMFlYUmxjMXdpTzF4dVhHNWpiR0Z6Y3lCUWNtOWpaWE56SUh0Y2JpQWdjR2xrT2lCT2RXMWlaWEk3WEc0Z0lHMWhhV3hpYjNnNklFMWhhV3hpYjNnN1hHNGdJR1JwWTNRNklFOWlhbVZqZER0Y2JseHVJQ0JqYjI1emRISjFZM1J2Y2lod2FXUTZJRTUxYldKbGNpd2diV0ZwYkdKdmVEb2dUV0ZwYkdKdmVDbDdYRzRnSUNBZ2RHaHBjeTV3YVdRZ1BTQndhV1E3WEc0Z0lDQWdkR2hwY3k1dFlXbHNZbTk0SUQwZ2JXRnBiR0p2ZUR0Y2JpQWdJQ0IwYUdsekxuTjBZWFIxY3lBOUlGTjBZWFJsY3k1VFZFOVFVRVZFTzF4dUlDQWdJSFJvYVhNdVpHbGpkQ0E5SUh0OU8xeHVJQ0I5WEc1OVhHNWNibVY0Y0c5eWRDQmtaV1poZFd4MElGQnliMk5sYzNNN1hHNGlYU3dpYzI5MWNtTmxVbTl2ZENJNklpOXpiM1Z5WTJVdkluMD1cbiIsImNsYXNzIFR1cGxlIHtcblxuICBjb25zdHJ1Y3RvciguLi5hcmdzKSB7XG4gICAgdGhpcy52YWx1ZXMgPSBPYmplY3QuZnJlZXplKGFyZ3MpO1xuICAgIHRoaXMubGVuZ3RoID0gdGhpcy52YWx1ZXMubGVuZ3RoO1xuICB9XG5cbiAgZ2V0KGluZGV4KSB7XG4gICAgcmV0dXJuIHRoaXMudmFsdWVzW2luZGV4XTtcbiAgfVxuXG4gIGNvdW50KCkge1xuICAgIHJldHVybiB0aGlzLnZhbHVlcy5sZW5ndGg7XG4gIH1cblxuICBbU3ltYm9sLml0ZXJhdG9yXSgpIHtcbiAgICByZXR1cm4gdGhpcy52YWx1ZXNbU3ltYm9sLml0ZXJhdG9yXSgpO1xuICB9XG5cbiAgdG9TdHJpbmcoKSB7XG4gICAgdmFyIGksXG4gICAgICAgIHMgPSBcIlwiO1xuICAgIGZvciAoaSA9IDA7IGkgPCB0aGlzLnZhbHVlcy5sZW5ndGg7IGkrKykge1xuICAgICAgaWYgKHMgIT09IFwiXCIpIHtcbiAgICAgICAgcyArPSBcIiwgXCI7XG4gICAgICB9XG4gICAgICBzICs9IHRoaXMudmFsdWVzW2ldLnRvU3RyaW5nKCk7XG4gICAgfVxuXG4gICAgcmV0dXJuIFwie1wiICsgcyArIFwifVwiO1xuICB9XG5cbiAgcHV0X2VsZW0oaW5kZXgsIGVsZW0pIHtcbiAgICBpZiAoaW5kZXggPT09IHRoaXMubGVuZ3RoKSB7XG4gICAgICBsZXQgbmV3X3ZhbHVlcyA9IHRoaXMudmFsdWVzLmNvbmNhdChbZWxlbV0pO1xuICAgICAgcmV0dXJuIG5ldyBUdXBsZSguLi5uZXdfdmFsdWVzKTtcbiAgICB9XG5cbiAgICBsZXQgbmV3X3ZhbHVlcyA9IHRoaXMudmFsdWVzLmNvbmNhdChbXSk7XG4gICAgbmV3X3ZhbHVlcy5zcGxpY2UoaW5kZXgsIDAsIGVsZW0pO1xuICAgIHJldHVybiBuZXcgVHVwbGUoLi4ubmV3X3ZhbHVlcyk7XG4gIH1cblxuICByZW1vdmVfZWxlbShpbmRleCkge1xuICAgIGxldCBuZXdfdmFsdWVzID0gdGhpcy52YWx1ZXMuY29uY2F0KFtdKTtcbiAgICBuZXdfdmFsdWVzLnNwbGljZShpbmRleCwgMSk7XG4gICAgcmV0dXJuIG5ldyBUdXBsZSguLi5uZXdfdmFsdWVzKTtcbiAgfVxuXG59XG5cbmxldCBwcm9jZXNzX2NvdW50ZXIgPSAtMTtcblxuY2xhc3MgUElEIHtcbiAgY29uc3RydWN0b3IoKSB7XG4gICAgcHJvY2Vzc19jb3VudGVyID0gcHJvY2Vzc19jb3VudGVyICsgMTtcbiAgICB0aGlzLmlkID0gcHJvY2Vzc19jb3VudGVyO1xuICB9XG5cbiAgdG9TdHJpbmcoKSB7XG4gICAgcmV0dXJuIFwiUElEIzwwLlwiICsgdGhpcy5pZCArIFwiLjA+XCI7XG4gIH1cbn1cblxuY2xhc3MgSW50ZWdlciB7fVxuY2xhc3MgRmxvYXQge31cblxuZXhwb3J0IHsgUElELCBUdXBsZSwgSW50ZWdlciwgRmxvYXQgfTtcbi8vIyBzb3VyY2VNYXBwaW5nVVJMPWRhdGE6YXBwbGljYXRpb24vanNvbjtiYXNlNjQsZXlKMlpYSnphVzl1SWpvekxDSnpiM1Z5WTJWeklqcGJJbXhwWWk5amIzSmxMM0J5YVcxcGRHbDJaWE11YW5NaVhTd2libUZ0WlhNaU9sdGRMQ0p0WVhCd2FXNW5jeUk2SWtGQlFVRXNUVUZCVFN4TFFVRk9MRU5CUVZrN08wRkJSVllzWTBGQldTeEhRVUZITEVsQlFVZ3NSVUZCVVR0QlFVTnNRaXhUUVVGTExFMUJRVXdzUjBGQll5eFBRVUZQTEUxQlFWQXNRMEZCWXl4SlFVRmtMRU5CUVdRc1EwRkVhMEk3UVVGRmJFSXNVMEZCU3l4TlFVRk1MRWRCUVdNc1MwRkJTeXhOUVVGTUxFTkJRVmtzVFVGQldpeERRVVpKTzBkQlFYQkNPenRCUVV0QkxFMUJRVWtzUzBGQlNpeEZRVUZYTzBGQlExUXNWMEZCVHl4TFFVRkxMRTFCUVV3c1EwRkJXU3hMUVVGYUxFTkJRVkFzUTBGRVV6dEhRVUZZT3p0QlFVbEJMRlZCUVZFN1FVRkRUaXhYUVVGUExFdEJRVXNzVFVGQlRDeERRVUZaTEUxQlFWb3NRMEZFUkR0SFFVRlNPenRCUVVsQkxFZEJRVU1zVDBGQlR5eFJRVUZRTEVsQlFXMUNPMEZCUTJ4Q0xGZEJRVThzUzBGQlN5eE5RVUZNTEVOQlFWa3NUMEZCVHl4UlFVRlFMRU5CUVZvc1JVRkJVQ3hEUVVSclFqdEhRVUZ3UWpzN1FVRkpRU3hoUVVGWE8wRkJRMVFzVVVGQlNTeERRVUZLTzFGQlFVOHNTVUZCU1N4RlFVRktMRU5CUkVVN1FVRkZWQ3hUUVVGTExFbEJRVWtzUTBGQlNpeEZRVUZQTEVsQlFVa3NTMEZCU3l4TlFVRk1MRU5CUVZrc1RVRkJXaXhGUVVGdlFpeEhRVUZ3UXl4RlFVRjVRenRCUVVOMlF5eFZRVUZKTEUxQlFVMHNSVUZCVGl4RlFVRlZPMEZCUTFvc1lVRkJTeXhKUVVGTUxFTkJSRms3VDBGQlpEdEJRVWRCTEZkQlFVc3NTMEZCU3l4TlFVRk1MRU5CUVZrc1EwRkJXaXhGUVVGbExGRkJRV1lzUlVGQlRDeERRVXAxUXp0TFFVRjZRenM3UVVGUFFTeFhRVUZQTEUxQlFVMHNRMEZCVGl4SFFVRlZMRWRCUVZZc1EwRlVSVHRIUVVGWU96dEJRVmxCTEZkQlFWTXNTMEZCVkN4RlFVRm5RaXhKUVVGb1FpeEZRVUZ4UWp0QlFVTnVRaXhSUVVGSExGVkJRVlVzUzBGQlN5eE5RVUZNTEVWQlFWazdRVUZEZGtJc1ZVRkJTU3hoUVVGaExFdEJRVXNzVFVGQlRDeERRVUZaTEUxQlFWb3NRMEZCYlVJc1EwRkJReXhKUVVGRUxFTkJRVzVDTEVOQlFXSXNRMEZFYlVJN1FVRkZka0lzWVVGQlR5eEpRVUZKTEV0QlFVb3NRMEZCVlN4SFFVRkhMRlZCUVVnc1EwRkJha0lzUTBGR2RVSTdTMEZCZWtJN08wRkJTMEVzVVVGQlNTeGhRVUZoTEV0QlFVc3NUVUZCVEN4RFFVRlpMRTFCUVZvc1EwRkJiVUlzUlVGQmJrSXNRMEZCWWl4RFFVNWxPMEZCVDI1Q0xHVkJRVmNzVFVGQldDeERRVUZyUWl4TFFVRnNRaXhGUVVGNVFpeERRVUY2UWl4RlFVRTBRaXhKUVVFMVFpeEZRVkJ0UWp0QlFWRnVRaXhYUVVGUExFbEJRVWtzUzBGQlNpeERRVUZWTEVkQlFVY3NWVUZCU0N4RFFVRnFRaXhEUVZKdFFqdEhRVUZ5UWpzN1FVRlhRU3hqUVVGWkxFdEJRVm9zUlVGQmEwSTdRVUZEYUVJc1VVRkJTU3hoUVVGaExFdEJRVXNzVFVGQlRDeERRVUZaTEUxQlFWb3NRMEZCYlVJc1JVRkJia0lzUTBGQllpeERRVVJaTzBGQlJXaENMR1ZCUVZjc1RVRkJXQ3hEUVVGclFpeExRVUZzUWl4RlFVRjVRaXhEUVVGNlFpeEZRVVpuUWp0QlFVZG9RaXhYUVVGUExFbEJRVWtzUzBGQlNpeERRVUZWTEVkQlFVY3NWVUZCU0N4RFFVRnFRaXhEUVVoblFqdEhRVUZzUWpzN1EwRXhRMFk3TzBGQmJVUkJMRWxCUVVrc2EwSkJRV3RDTEVOQlFVTXNRMEZCUkRzN1FVRkZkRUlzVFVGQlRTeEhRVUZPTEVOQlFWVTdRVUZEVWl4blFrRkJZVHRCUVVOWUxITkNRVUZyUWl4clFrRkJhMElzUTBGQmJFSXNRMEZFVUR0QlFVVllMRk5CUVVzc1JVRkJUQ3hIUVVGVkxHVkJRVllzUTBGR1Z6dEhRVUZpT3p0QlFVdEJMR0ZCUVZVN1FVRkRVaXhYUVVGUExGbEJRVmtzUzBGQlN5eEZRVUZNTEVkQlFWVXNTMEZCZEVJc1EwRkVRenRIUVVGV08wTkJUa1k3TzBGQlYwRXNUVUZCVFN4UFFVRk9MRU5CUVdNc1JVRkJaRHRCUVVOQkxFMUJRVTBzUzBGQlRpeERRVUZaTEVWQlFWbzdPMEZCUlVFc1UwRkJVeXhIUVVGVUxFVkJRV01zUzBGQlpDeEZRVUZ4UWl4UFFVRnlRaXhGUVVFNFFpeExRVUU1UWlJc0ltWnBiR1VpT2lKc2FXSXZZMjl5WlM5d2NtbHRhWFJwZG1WekxtcHpJaXdpYzI5MWNtTmxjME52Ym5SbGJuUWlPbHNpWTJ4aGMzTWdWSFZ3YkdVZ2UxeHVYRzRnSUdOdmJuTjBjblZqZEc5eUtDNHVMbUZ5WjNNcGUxeHVJQ0FnSUhSb2FYTXVkbUZzZFdWeklEMGdUMkpxWldOMExtWnlaV1Y2WlNoaGNtZHpLVHRjYmlBZ0lDQjBhR2x6TG14bGJtZDBhQ0E5SUhSb2FYTXVkbUZzZFdWekxteGxibWQwYUR0Y2JpQWdmVnh1WEc0Z0lHZGxkQ2hwYm1SbGVDa2dlMXh1SUNBZ0lISmxkSFZ5YmlCMGFHbHpMblpoYkhWbGMxdHBibVJsZUYwN1hHNGdJSDFjYmx4dUlDQmpiM1Z1ZENncElIdGNiaUFnSUNCeVpYUjFjbTRnZEdocGN5NTJZV3gxWlhNdWJHVnVaM1JvTzF4dUlDQjlYRzVjYmlBZ1cxTjViV0p2YkM1cGRHVnlZWFJ2Y2wwb0tTQjdYRzRnSUNBZ2NtVjBkWEp1SUhSb2FYTXVkbUZzZFdWelcxTjViV0p2YkM1cGRHVnlZWFJ2Y2wwb0tUdGNiaUFnZlZ4dVhHNGdJSFJ2VTNSeWFXNW5LQ2tnZTF4dUlDQWdJSFpoY2lCcExDQnpJRDBnWENKY0lqdGNiaUFnSUNCbWIzSWdLR2tnUFNBd095QnBJRHdnZEdocGN5NTJZV3gxWlhNdWJHVnVaM1JvT3lCcEt5c3BJSHRjYmlBZ0lDQWdJR2xtSUNoeklDRTlQU0JjSWx3aUtTQjdYRzRnSUNBZ0lDQWdJSE1nS3owZ1hDSXNJRndpTzF4dUlDQWdJQ0FnZlZ4dUlDQWdJQ0FnY3lBclBTQjBhR2x6TG5aaGJIVmxjMXRwWFM1MGIxTjBjbWx1WnlncE8xeHVJQ0FnSUgxY2JseHVJQ0FnSUhKbGRIVnliaUJjSW50Y0lpQXJJSE1nS3lCY0luMWNJanRjYmlBZ2ZWeHVYRzRnSUhCMWRGOWxiR1Z0S0dsdVpHVjRMQ0JsYkdWdEtYdGNiaUFnSUNCcFppaHBibVJsZUNBOVBUMGdkR2hwY3k1c1pXNW5kR2dwZTF4dUlDQWdJQ0FnYkdWMElHNWxkMTkyWVd4MVpYTWdQU0IwYUdsekxuWmhiSFZsY3k1amIyNWpZWFFvVzJWc1pXMWRLVHRjYmlBZ0lDQWdJSEpsZEhWeWJpQnVaWGNnVkhWd2JHVW9MaTR1Ym1WM1gzWmhiSFZsY3lrN1hHNGdJQ0FnZlZ4dVhHNGdJQ0FnYkdWMElHNWxkMTkyWVd4MVpYTWdQU0IwYUdsekxuWmhiSFZsY3k1amIyNWpZWFFvVzEwcE8xeHVJQ0FnSUc1bGQxOTJZV3gxWlhNdWMzQnNhV05sS0dsdVpHVjRMQ0F3TENCbGJHVnRLVHRjYmlBZ0lDQnlaWFIxY200Z2JtVjNJRlIxY0d4bEtDNHVMbTVsZDE5MllXeDFaWE1wTzF4dUlDQjlYRzVjYmlBZ2NtVnRiM1psWDJWc1pXMG9hVzVrWlhncGUxeHVJQ0FnSUd4bGRDQnVaWGRmZG1Gc2RXVnpJRDBnZEdocGN5NTJZV3gxWlhNdVkyOXVZMkYwS0Z0ZEtUdGNiaUFnSUNCdVpYZGZkbUZzZFdWekxuTndiR2xqWlNocGJtUmxlQ3dnTVNrN1hHNGdJQ0FnY21WMGRYSnVJRzVsZHlCVWRYQnNaU2d1TGk1dVpYZGZkbUZzZFdWektUdGNiaUFnZlZ4dVhHNTlYRzVjYmx4dWJHVjBJSEJ5YjJObGMzTmZZMjkxYm5SbGNpQTlJQzB4TzF4dVhHNWpiR0Z6Y3lCUVNVUWdlMXh1SUNCamIyNXpkSEoxWTNSdmNpZ3BlMXh1SUNBZ0lIQnliMk5sYzNOZlkyOTFiblJsY2lBOUlIQnliMk5sYzNOZlkyOTFiblJsY2lBcklERTdYRzRnSUNBZ2RHaHBjeTVwWkNBOUlIQnliMk5sYzNOZlkyOTFiblJsY2p0Y2JpQWdmVnh1WEc0Z0lIUnZVM1J5YVc1bktDbDdYRzRnSUNBZ2NtVjBkWEp1SUZ3aVVFbEVJend3TGx3aUlDc2dkR2hwY3k1cFpDQXJJRndpTGpBK1hDSTdYRzRnSUgxY2JuMWNibHh1WTJ4aGMzTWdTVzUwWldkbGNpQjdmVnh1WTJ4aGMzTWdSbXh2WVhRZ2UzMWNibHh1Wlhod2IzSjBJSHNnVUVsRUxDQlVkWEJzWlN3Z1NXNTBaV2RsY2l3Z1JteHZZWFFnZlR0Y2JpSmRMQ0p6YjNWeVkyVlNiMjkwSWpvaUwzTnZkWEpqWlM4aWZRPT1cbiIsIlxuXCJ1c2Ugc3RyaWN0XCI7XG5cbmltcG9ydCBNYWlsYm94IGZyb20gXCIuL21haWxib3hcIjtcbmltcG9ydCBQcm9jZXNzIGZyb20gXCIuL3Byb2Nlc3NcIjtcbmltcG9ydCBTdGF0ZXMgZnJvbSBcIi4vc3RhdGVzXCI7XG5pbXBvcnQgKiBhcyBQcmltaXRpdmVzIGZyb20gXCIuLi9wcmltaXRpdmVzXCI7XG5cbmNsYXNzIFByb2Nlc3NTeXN0ZW0ge1xuXG4gIGNvbnN0cnVjdG9yKCkge1xuICAgIHRoaXMucGlkcyA9IG5ldyBNYXAoKTtcbiAgICB0aGlzLm1haWxib3hlcyA9IG5ldyBNYXAoKTtcbiAgICB0aGlzLm5hbWVzID0gbmV3IE1hcCgpO1xuICAgIHRoaXMubGlua3MgPSBuZXcgTWFwKCk7XG5cbiAgICB0aGlzLmN1cnJlbnRfcHJvY2VzcyA9IG51bGw7XG4gICAgdGhpcy5zdXNwZW5kZWQgPSBuZXcgTWFwKCk7XG5cbiAgICB0aGlzLm1haW5fcHJvY2Vzc19waWQgPSB0aGlzLnNwYXduKCk7XG4gICAgdGhpcy5zZXRfY3VycmVudCh0aGlzLm1haW5fcHJvY2Vzc19waWQpO1xuICB9XG5cbiAgc3Bhd24oKSB7XG4gICAgcmV0dXJuIHRoaXMuYWRkX3Byb2MoZmFsc2UpLnBpZDtcbiAgfVxuXG4gIHNwYXduX2xpbmsoKSB7XG4gICAgcmV0dXJuIHRoaXMuYWRkX3Byb2ModHJ1ZSkucGlkO1xuICB9XG5cbiAgbGluayhwaWQpIHtcbiAgICB0aGlzLmxpbmtzLmdldCh0aGlzLnBpZCgpKS5hZGQocGlkKTtcbiAgICB0aGlzLmxpbmtzLmdldChwaWQpLmFkZCh0aGlzLnBpZCgpKTtcbiAgfVxuXG4gIHVubGluayhwaWQpIHtcbiAgICB0aGlzLmxpbmtzLmdldCh0aGlzLnBpZCgpKS5kZWxldGUocGlkKTtcbiAgICB0aGlzLmxpbmtzLmdldChwaWQpLmRlbGV0ZSh0aGlzLnBpZCgpKTtcbiAgfVxuXG4gIHNldF9jdXJyZW50KGlkKSB7XG4gICAgbGV0IHBpZCA9IHRoaXMucGlkb2YoaWQpO1xuICAgIGlmIChwaWQgIT09IG51bGwpIHtcbiAgICAgIHRoaXMuY3VycmVudF9wcm9jZXNzID0gdGhpcy5waWRzLmdldChwaWQpO1xuICAgICAgdGhpcy5jdXJyZW50X3Byb2Nlc3Muc3RhdHVzID0gU3RhdGVzLlJVTk5JTkc7XG4gICAgfVxuICB9XG5cbiAgYWRkX3Byb2MobGlua2VkKSB7XG4gICAgbGV0IG5ld3BpZCA9IG5ldyBQcmltaXRpdmVzLlBJRCgpO1xuICAgIGxldCBtYWlsYm94ID0gbmV3IE1haWxib3goKTtcbiAgICBsZXQgbmV3cHJvYyA9IG5ldyBQcm9jZXNzKG5ld3BpZCwgbWFpbGJveCk7XG5cbiAgICB0aGlzLnBpZHMuc2V0KG5ld3BpZCwgbmV3cHJvYyk7XG4gICAgdGhpcy5tYWlsYm94ZXMuc2V0KG5ld3BpZCwgbWFpbGJveCk7XG4gICAgdGhpcy5saW5rcy5zZXQobmV3cGlkLCBuZXcgU2V0KCkpO1xuXG4gICAgaWYgKGxpbmtlZCkge1xuICAgICAgdGhpcy5saW5rKG5ld3BpZCk7XG4gICAgfVxuXG4gICAgcmV0dXJuIG5ld3Byb2M7XG4gIH1cblxuICByZW1vdmVfcHJvYyhwaWQpIHtcbiAgICB0aGlzLnBpZHMuZGVsZXRlKHBpZCk7XG4gICAgdGhpcy51bnJlZ2lzdGVyKHBpZCk7XG5cbiAgICBpZiAodGhpcy5saW5rcy5oYXMocGlkKSkge1xuICAgICAgZm9yIChsZXQgbGlua3BpZCBvZiB0aGlzLmxpbmtzLmdldChwaWQpKSB7XG4gICAgICAgIHRoaXMubGlua3MuZ2V0KGxpbmtwaWQpLmRlbGV0ZShwaWQpO1xuICAgICAgfVxuXG4gICAgICB0aGlzLmxpbmtzLmRlbGV0ZShwaWQpO1xuICAgIH1cbiAgfVxuXG4gIGV4aXQoaWQpIHtcbiAgICBsZXQgcGlkID0gdGhpcy5waWRvZihpZCk7XG4gICAgdGhpcy5yZW1vdmVfcHJvYyhpZCk7XG4gIH1cblxuICByZWdpc3RlcihuYW1lLCBwaWQpIHtcbiAgICBpZiAoIXRoaXMubmFtZXMuaGFzKG5hbWUpKSB7XG4gICAgICB0aGlzLm5hbWVzLnNldChuYW1lLCBwaWQpO1xuICAgICAgcmV0dXJuIG5hbWU7XG4gICAgfSBlbHNlIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcihcIk5hbWUgaXMgYWxyZWFkeSByZWdpc3RlcmVkIHRvIGFub3RoZXIgcHJvY2Vzc1wiKTtcbiAgICB9XG4gIH1cblxuICByZWdpc3RlcmVkKG5hbWUpIHtcbiAgICByZXR1cm4gdGhpcy5uYW1lcy5oYXMobmFtZSkgPyB0aGlzLm5hbWVzLmdldChuYW1lKSA6IG51bGw7XG4gIH1cblxuICB1bnJlZ2lzdGVyKHBpZCkge1xuICAgIGZvciAobGV0IG5hbWUgb2YgdGhpcy5uYW1lcy5rZXlzKCkpIHtcbiAgICAgIGlmICh0aGlzLm5hbWVzLmhhcyhuYW1lKSAmJiB0aGlzLm5hbWVzLmdldChuYW1lKSA9PT0gcGlkKSB7XG4gICAgICAgIHRoaXMubmFtZXMuZGVsZXRlKG5hbWUpO1xuICAgICAgfVxuICAgIH1cbiAgfVxuXG4gIHBpZCgpIHtcbiAgICByZXR1cm4gdGhpcy5jdXJyZW50X3Byb2Nlc3MucGlkO1xuICB9XG5cbiAgcGlkb2YoaWQpIHtcbiAgICBpZiAoaWQgaW5zdGFuY2VvZiBQcmltaXRpdmVzLlBJRCkge1xuICAgICAgcmV0dXJuIHRoaXMucGlkcy5oYXMoaWQpID8gaWQgOiBudWxsO1xuICAgIH0gZWxzZSBpZiAoaWQgaW5zdGFuY2VvZiBQcm9jZXNzKSB7XG4gICAgICByZXR1cm4gaWQucGlkO1xuICAgIH0gZWxzZSB7XG4gICAgICBsZXQgcGlkID0gdGhpcy5yZWdpc3RlcmVkKGlkKTtcbiAgICAgIGlmIChwaWQgPT09IG51bGwpIHRocm93IFwiUHJvY2VzcyBuYW1lIG5vdCByZWdpc3RlcmVkOiBcIiArIGlkICsgXCIgKFwiICsgdHlwZW9mIGlkICsgXCIpXCI7XG4gICAgICByZXR1cm4gcGlkO1xuICAgIH1cbiAgfVxuXG4gIHB1dChpZCwga2V5LCB2YWx1ZSkge1xuICAgIGxldCBwaWQgPSB0aGlzLnBpZG9mKGlkKTtcbiAgICBsZXQgcHJvY2VzcyA9IHRoaXMucGlkcy5nZXQocGlkKTtcbiAgICBwcm9jZXNzLmRpY3Rba2V5XSA9IHZhbHVlO1xuICB9XG5cbiAgZ2V0KGlkLCBrZXkpIHtcbiAgICBsZXQgcGlkID0gdGhpcy5waWRvZihpZCk7XG4gICAgbGV0IHByb2Nlc3MgPSB0aGlzLnBpZHMuZ2V0KHBpZCk7XG5cbiAgICBpZiAoa2V5ICE9IG51bGwpIHtcbiAgICAgIHJldHVybiBwcm9jZXNzLmRpY3Rba2V5XTtcbiAgICB9IGVsc2Uge1xuICAgICAgcmV0dXJuIHByb2Nlc3MuZGljdDtcbiAgICB9XG4gIH1cblxuICBnZXRfa2V5cyhpZCkge1xuICAgIGxldCBwaWQgPSB0aGlzLnBpZG9mKGlkKTtcbiAgICBsZXQgcHJvY2VzcyA9IHRoaXMucGlkcy5nZXQocGlkKTtcblxuICAgIHJldHVybiBPYmplY3Qua2V5cyhwcm9jZXNzLmRpY3QpO1xuICB9XG5cbiAgZXJhc2UoaWQsIGtleSkge1xuICAgIGxldCBwaWQgPSB0aGlzLnBpZG9mKGlkKTtcbiAgICBsZXQgcHJvY2VzcyA9IHRoaXMucGlkcy5nZXQocGlkKTtcblxuICAgIGlmIChrZXkgIT0gbnVsbCkge1xuICAgICAgZGVsZXRlIHByb2Nlc3MuZGljdFtrZXldO1xuICAgIH0gZWxzZSB7XG4gICAgICBwcm9jZXNzLmRpY3QgPSB7fTtcbiAgICB9XG4gIH1cbn1cblxuZXhwb3J0IGRlZmF1bHQgUHJvY2Vzc1N5c3RlbTtcbi8vIyBzb3VyY2VNYXBwaW5nVVJMPWRhdGE6YXBwbGljYXRpb24vanNvbjtiYXNlNjQsZXlKMlpYSnphVzl1SWpvekxDSnpiM1Z5WTJWeklqcGJJbXhwWWk5amIzSmxMM0J5YjJObGMzTmxjeTl3Y205alpYTnpYM041YzNSbGJTNXFjeUpkTENKdVlXMWxjeUk2VzEwc0ltMWhjSEJwYm1keklqb2lPMEZCUTBFN08wRkJSVUVzVDBGQlR5eFBRVUZRTEUxQlFXOUNMRmRCUVhCQ08wRkJRMEVzVDBGQlR5eFBRVUZRTEUxQlFXOUNMRmRCUVhCQ08wRkJRMEVzVDBGQlR5eE5RVUZRTEUxQlFXMUNMRlZCUVc1Q08wRkJRMEVzVDBGQlR5eExRVUZMTEZWQlFVd3NUVUZCY1VJc1pVRkJOVUk3TzBGQlJVRXNUVUZCVFN4aFFVRk9MRU5CUVc5Q096dEJRVVZzUWl4blFrRkJZVHRCUVVOWUxGTkJRVXNzU1VGQlRDeEhRVUZaTEVsQlFVa3NSMEZCU2l4RlFVRmFMRU5CUkZjN1FVRkZXQ3hUUVVGTExGTkJRVXdzUjBGQmFVSXNTVUZCU1N4SFFVRktMRVZCUVdwQ0xFTkJSbGM3UVVGSFdDeFRRVUZMTEV0QlFVd3NSMEZCWVN4SlFVRkpMRWRCUVVvc1JVRkJZaXhEUVVoWE8wRkJTVmdzVTBGQlN5eExRVUZNTEVkQlFXRXNTVUZCU1N4SFFVRktMRVZCUVdJc1EwRktWenM3UVVGTldDeFRRVUZMTEdWQlFVd3NSMEZCZFVJc1NVRkJka0lzUTBGT1Z6dEJRVTlZTEZOQlFVc3NVMEZCVEN4SFFVRnBRaXhKUVVGSkxFZEJRVW9zUlVGQmFrSXNRMEZRVnpzN1FVRlRXQ3hUUVVGTExHZENRVUZNTEVkQlFYZENMRXRCUVVzc1MwRkJUQ3hGUVVGNFFpeERRVlJYTzBGQlZWZ3NVMEZCU3l4WFFVRk1MRU5CUVdsQ0xFdEJRVXNzWjBKQlFVd3NRMEZCYWtJc1EwRldWenRIUVVGaU96dEJRV0ZCTEZWQlFVODdRVUZEVEN4WFFVRlBMRXRCUVVzc1VVRkJUQ3hEUVVGakxFdEJRV1FzUlVGQmNVSXNSMEZCY2tJc1EwRkVSanRIUVVGUU96dEJRVWxCTEdWQlFWazdRVUZEVml4WFFVRlBMRXRCUVVzc1VVRkJUQ3hEUVVGakxFbEJRV1FzUlVGQmIwSXNSMEZCY0VJc1EwRkVSenRIUVVGYU96dEJRVWxCTEU5QlFVc3NSMEZCVEN4RlFVRlRPMEZCUTFBc1UwRkJTeXhMUVVGTUxFTkJRVmNzUjBGQldDeERRVUZsTEV0QlFVc3NSMEZCVEN4RlFVRm1MRVZCUVRKQ0xFZEJRVE5DTEVOQlFTdENMRWRCUVM5Q0xFVkJSRTg3UVVGRlVDeFRRVUZMTEV0QlFVd3NRMEZCVnl4SFFVRllMRU5CUVdVc1IwRkJaaXhGUVVGdlFpeEhRVUZ3UWl4RFFVRjNRaXhMUVVGTExFZEJRVXdzUlVGQmVFSXNSVUZHVHp0SFFVRlVPenRCUVV0QkxGTkJRVThzUjBGQlVDeEZRVUZYTzBGQlExUXNVMEZCU3l4TFFVRk1MRU5CUVZjc1IwRkJXQ3hEUVVGbExFdEJRVXNzUjBGQlRDeEZRVUZtTEVWQlFUSkNMRTFCUVROQ0xFTkJRV3RETEVkQlFXeERMRVZCUkZNN1FVRkZWQ3hUUVVGTExFdEJRVXdzUTBGQlZ5eEhRVUZZTEVOQlFXVXNSMEZCWml4RlFVRnZRaXhOUVVGd1FpeERRVUV5UWl4TFFVRkxMRWRCUVV3c1JVRkJNMElzUlVGR1V6dEhRVUZZT3p0QlFVdEJMR05CUVZrc1JVRkJXaXhGUVVGbE8wRkJRMklzVVVGQlNTeE5RVUZOTEV0QlFVc3NTMEZCVEN4RFFVRlhMRVZCUVZnc1EwRkJUaXhEUVVSVE8wRkJSV0lzVVVGQlJ5eFJRVUZSTEVsQlFWSXNSVUZCWVR0QlFVTmtMRmRCUVVzc1pVRkJUQ3hIUVVGMVFpeExRVUZMTEVsQlFVd3NRMEZCVlN4SFFVRldMRU5CUVdNc1IwRkJaQ3hEUVVGMlFpeERRVVJqTzBGQlJXUXNWMEZCU3l4bFFVRk1MRU5CUVhGQ0xFMUJRWEpDTEVkQlFUaENMRTlCUVU4c1QwRkJVQ3hEUVVab1FqdExRVUZvUWp0SFFVWkdPenRCUVZGQkxGZEJRVk1zVFVGQlZDeEZRVUZuUWp0QlFVTmtMRkZCUVVrc1UwRkJVeXhKUVVGSkxGZEJRVmNzUjBGQldDeEZRVUZpTEVOQlJGVTdRVUZGWkN4UlFVRkpMRlZCUVZVc1NVRkJTU3hQUVVGS0xFVkJRVllzUTBGR1ZUdEJRVWRrTEZGQlFVa3NWVUZCVlN4SlFVRkpMRTlCUVVvc1EwRkJXU3hOUVVGYUxFVkJRVzlDTEU5QlFYQkNMRU5CUVZZc1EwRklWVHM3UVVGTFpDeFRRVUZMTEVsQlFVd3NRMEZCVlN4SFFVRldMRU5CUVdNc1RVRkJaQ3hGUVVGelFpeFBRVUYwUWl4RlFVeGpPMEZCVFdRc1UwRkJTeXhUUVVGTUxFTkJRV1VzUjBGQlppeERRVUZ0UWl4TlFVRnVRaXhGUVVFeVFpeFBRVUV6UWl4RlFVNWpPMEZCVDJRc1UwRkJTeXhMUVVGTUxFTkJRVmNzUjBGQldDeERRVUZsTEUxQlFXWXNSVUZCZFVJc1NVRkJTU3hIUVVGS0xFVkJRWFpDTEVWQlVHTTdPMEZCVTJRc1VVRkJSeXhOUVVGSUxFVkJRVlU3UVVGRFVpeFhRVUZMTEVsQlFVd3NRMEZCVlN4TlFVRldMRVZCUkZFN1MwRkJWanM3UVVGSlFTeFhRVUZQTEU5QlFWQXNRMEZpWXp0SFFVRm9RanM3UVVGblFrRXNZMEZCV1N4SFFVRmFMRVZCUVdkQ08wRkJRMlFzVTBGQlN5eEpRVUZNTEVOQlFWVXNUVUZCVml4RFFVRnBRaXhIUVVGcVFpeEZRVVJqTzBGQlJXUXNVMEZCU3l4VlFVRk1MRU5CUVdkQ0xFZEJRV2hDTEVWQlJtTTdPMEZCU1dRc1VVRkJSeXhMUVVGTExFdEJRVXdzUTBGQlZ5eEhRVUZZTEVOQlFXVXNSMEZCWml4RFFVRklMRVZCUVhWQ08wRkJRM0pDTEZkQlFVc3NTVUZCU1N4UFFVRktMRWxCUVdVc1MwRkJTeXhMUVVGTUxFTkJRVmNzUjBGQldDeERRVUZsTEVkQlFXWXNRMEZCY0VJc1JVRkJlVU03UVVGRGRrTXNZVUZCU3l4TFFVRk1MRU5CUVZjc1IwRkJXQ3hEUVVGbExFOUJRV1lzUlVGQmQwSXNUVUZCZUVJc1EwRkJLMElzUjBGQkwwSXNSVUZFZFVNN1QwRkJla003TzBGQlNVRXNWMEZCU3l4TFFVRk1MRU5CUVZjc1RVRkJXQ3hEUVVGclFpeEhRVUZzUWl4RlFVeHhRanRMUVVGMlFqdEhRVXBHT3p0QlFXRkJMRTlCUVVzc1JVRkJUQ3hGUVVGUk8wRkJRMDRzVVVGQlNTeE5RVUZOTEV0QlFVc3NTMEZCVEN4RFFVRlhMRVZCUVZnc1EwRkJUaXhEUVVSRk8wRkJSVTRzVTBGQlN5eFhRVUZNTEVOQlFXbENMRVZCUVdwQ0xFVkJSazA3UjBGQlVqczdRVUZMUVN4WFFVRlRMRWxCUVZRc1JVRkJaU3hIUVVGbUxFVkJRVzFDTzBGQlEycENMRkZCUVVjc1EwRkJReXhMUVVGTExFdEJRVXdzUTBGQlZ5eEhRVUZZTEVOQlFXVXNTVUZCWml4RFFVRkVMRVZCUVhOQ08wRkJRM1pDTEZkQlFVc3NTMEZCVEN4RFFVRlhMRWRCUVZnc1EwRkJaU3hKUVVGbUxFVkJRWEZDTEVkQlFYSkNMRVZCUkhWQ08wRkJSWFpDTEdGQlFVOHNTVUZCVUN4RFFVWjFRanRMUVVGNlFpeE5RVWRMTzBGQlEwZ3NXVUZCVFN4SlFVRkpMRXRCUVVvc1EwRkJWU3dyUTBGQlZpeERRVUZPTEVOQlJFYzdTMEZJVER0SFFVUkdPenRCUVZOQkxHRkJRVmNzU1VGQldDeEZRVUZuUWp0QlFVTmtMRmRCUVU4c1MwRkJTeXhMUVVGTUxFTkJRVmNzUjBGQldDeERRVUZsTEVsQlFXWXNTVUZCZFVJc1MwRkJTeXhMUVVGTUxFTkJRVmNzUjBGQldDeERRVUZsTEVsQlFXWXNRMEZCZGtJc1IwRkJPRU1zU1VGQk9VTXNRMEZFVHp0SFFVRm9RanM3UVVGSlFTeGhRVUZYTEVkQlFWZ3NSVUZCWlR0QlFVTmlMRk5CUVVrc1NVRkJTU3hKUVVGS0xFbEJRVmtzUzBGQlN5eExRVUZNTEVOQlFWY3NTVUZCV0N4RlFVRm9RaXhGUVVGclF6dEJRVU5vUXl4VlFVRkhMRXRCUVVzc1MwRkJUQ3hEUVVGWExFZEJRVmdzUTBGQlpTeEpRVUZtTEV0QlFYZENMRXRCUVVzc1MwRkJUQ3hEUVVGWExFZEJRVmdzUTBGQlpTeEpRVUZtTEUxQlFYbENMRWRCUVhwQ0xFVkJRVFpDTzBGQlEzUkVMR0ZCUVVzc1MwRkJUQ3hEUVVGWExFMUJRVmdzUTBGQmEwSXNTVUZCYkVJc1JVRkVjMFE3VDBGQmVFUTdTMEZFUmp0SFFVUkdPenRCUVZGQkxGRkJRVXM3UVVGRFNDeFhRVUZQTEV0QlFVc3NaVUZCVEN4RFFVRnhRaXhIUVVGeVFpeERRVVJLTzBkQlFVdzdPMEZCU1VFc1VVRkJUU3hGUVVGT0xFVkJRVk03UVVGRFVDeFJRVUZKTEdOQlFXTXNWMEZCVnl4SFFVRllMRVZCUVdkQ08wRkJReTlDTEdGQlFVOHNTMEZCU3l4SlFVRk1MRU5CUVZVc1IwRkJWaXhEUVVGakxFVkJRV1FzU1VGQmIwSXNSVUZCY0VJc1IwRkJlVUlzU1VGQmVrSXNRMEZFZDBJN1MwRkJiRU1zVFVGRlR5eEpRVUZKTEdOQlFXTXNUMEZCWkN4RlFVRjFRanRCUVVNdlFpeGhRVUZQTEVkQlFVY3NSMEZCU0N4RFFVUjNRanRMUVVFelFpeE5RVVZCTzBGQlEwb3NWVUZCU1N4TlFVRk5MRXRCUVVzc1ZVRkJUQ3hEUVVGblFpeEZRVUZvUWl4RFFVRk9MRU5CUkVFN1FVRkZTaXhWUVVGSkxGRkJRVkVzU1VGQlVpeEZRVU5FTEUxQlFVMHNhME5CUVd0RExFVkJRV3hETEVkQlFYVkRMRWxCUVhaRExFZEJRVGhETEU5QlFVOHNSVUZCVUN4SFFVRmhMRWRCUVRORUxFTkJSRlE3UVVGRlFTeGhRVUZQTEVkQlFWQXNRMEZLU1R0TFFVWkJPMGRCU0ZRN08wRkJZVUVzVFVGQlNTeEZRVUZLTEVWQlFWRXNSMEZCVWl4RlFVRmhMRXRCUVdJc1JVRkJiVUk3UVVGRGFrSXNVVUZCU1N4TlFVRk5MRXRCUVVzc1MwRkJUQ3hEUVVGWExFVkJRVmdzUTBGQlRpeERRVVJoTzBGQlJXcENMRkZCUVVrc1ZVRkJWU3hMUVVGTExFbEJRVXdzUTBGQlZTeEhRVUZXTEVOQlFXTXNSMEZCWkN4RFFVRldMRU5CUm1FN1FVRkhha0lzV1VGQlVTeEpRVUZTTEVOQlFXRXNSMEZCWWl4SlFVRnZRaXhMUVVGd1FpeERRVWhwUWp0SFFVRnVRanM3UVVGTlFTeE5RVUZKTEVWQlFVb3NSVUZCVVN4SFFVRlNMRVZCUVZrN1FVRkRWaXhSUVVGSkxFMUJRVTBzUzBGQlN5eExRVUZNTEVOQlFWY3NSVUZCV0N4RFFVRk9MRU5CUkUwN1FVRkZWaXhSUVVGSkxGVkJRVlVzUzBGQlN5eEpRVUZNTEVOQlFWVXNSMEZCVml4RFFVRmpMRWRCUVdRc1EwRkJWaXhEUVVaTk96dEJRVWxXTEZGQlFVY3NUMEZCVHl4SlFVRlFMRVZCUVZrN1FVRkRZaXhoUVVGUExGRkJRVkVzU1VGQlVpeERRVUZoTEVkQlFXSXNRMEZCVUN4RFFVUmhPMHRCUVdZc1RVRkZTenRCUVVOSUxHRkJRVThzVVVGQlVTeEpRVUZTTEVOQlJFbzdTMEZHVER0SFFVcEdPenRCUVZkQkxGZEJRVk1zUlVGQlZDeEZRVUZaTzBGQlExWXNVVUZCU1N4TlFVRk5MRXRCUVVzc1MwRkJUQ3hEUVVGWExFVkJRVmdzUTBGQlRpeERRVVJOTzBGQlJWWXNVVUZCU1N4VlFVRlZMRXRCUVVzc1NVRkJUQ3hEUVVGVkxFZEJRVllzUTBGQll5eEhRVUZrTEVOQlFWWXNRMEZHVFRzN1FVRkpWaXhYUVVGUExFOUJRVThzU1VGQlVDeERRVUZaTEZGQlFWRXNTVUZCVWl4RFFVRnVRaXhEUVVwVk8wZEJRVm83TzBGQlQwRXNVVUZCVFN4RlFVRk9MRVZCUVZVc1IwRkJWaXhGUVVGak8wRkJRMW9zVVVGQlNTeE5RVUZOTEV0QlFVc3NTMEZCVEN4RFFVRlhMRVZCUVZnc1EwRkJUaXhEUVVSUk8wRkJSVm9zVVVGQlNTeFZRVUZWTEV0QlFVc3NTVUZCVEN4RFFVRlZMRWRCUVZZc1EwRkJZeXhIUVVGa0xFTkJRVllzUTBGR1VUczdRVUZKV2l4UlFVRkhMRTlCUVU4c1NVRkJVQ3hGUVVGWk8wRkJRMklzWVVGQlR5eFJRVUZSTEVsQlFWSXNRMEZCWVN4SFFVRmlMRU5CUVZBc1EwRkVZVHRMUVVGbUxFMUJSVXM3UVVGRFNDeGpRVUZSTEVsQlFWSXNSMEZCWlN4RlFVRm1MRU5CUkVjN1MwRkdURHRIUVVwR08wTkJla2xHT3p0QlFYRktRU3hsUVVGbExHRkJRV1lpTENKbWFXeGxJam9pYkdsaUwyTnZjbVV2Y0hKdlkyVnpjMlZ6TDNCeWIyTmxjM05mYzNsemRHVnRMbXB6SWl3aWMyOTFjbU5sYzBOdmJuUmxiblFpT2xzaUx5b2dRR1pzYjNjZ0tpOWNibHdpZFhObElITjBjbWxqZEZ3aU8xeHVYRzVwYlhCdmNuUWdUV0ZwYkdKdmVDQm1jbTl0SUZ3aUxpOXRZV2xzWW05NFhDSTdYRzVwYlhCdmNuUWdVSEp2WTJWemN5Qm1jbTl0SUZ3aUxpOXdjbTlqWlhOelhDSTdYRzVwYlhCdmNuUWdVM1JoZEdWeklHWnliMjBnWENJdUwzTjBZWFJsYzF3aU8xeHVhVzF3YjNKMElDb2dZWE1nVUhKcGJXbDBhWFpsY3lCbWNtOXRJRndpTGk0dmNISnBiV2wwYVhabGMxd2lPMXh1WEc1amJHRnpjeUJRY205alpYTnpVM2x6ZEdWdElIdGNibHh1SUNCamIyNXpkSEoxWTNSdmNpZ3BlMXh1SUNBZ0lIUm9hWE11Y0dsa2N5QTlJRzVsZHlCTllYQW9LVHRjYmlBZ0lDQjBhR2x6TG0xaGFXeGliM2hsY3lBOUlHNWxkeUJOWVhBb0tUdGNiaUFnSUNCMGFHbHpMbTVoYldWeklEMGdibVYzSUUxaGNDZ3BPMXh1SUNBZ0lIUm9hWE11YkdsdWEzTWdQU0J1WlhjZ1RXRndLQ2s3WEc1Y2JpQWdJQ0IwYUdsekxtTjFjbkpsYm5SZmNISnZZMlZ6Y3lBOUlHNTFiR3c3WEc0Z0lDQWdkR2hwY3k1emRYTndaVzVrWldRZ1BTQnVaWGNnVFdGd0tDazdYRzVjYmlBZ0lDQjBhR2x6TG0xaGFXNWZjSEp2WTJWemMxOXdhV1FnUFNCMGFHbHpMbk53WVhkdUtDazdYRzRnSUNBZ2RHaHBjeTV6WlhSZlkzVnljbVZ1ZENoMGFHbHpMbTFoYVc1ZmNISnZZMlZ6YzE5d2FXUXBPMXh1SUNCOVhHNWNiaUFnYzNCaGQyNG9LWHRjYmlBZ0lDQnlaWFIxY200Z2RHaHBjeTVoWkdSZmNISnZZeWhtWVd4elpTa3VjR2xrTzF4dUlDQjlYRzVjYmlBZ2MzQmhkMjVmYkdsdWF5Z3BlMXh1SUNBZ0lISmxkSFZ5YmlCMGFHbHpMbUZrWkY5d2NtOWpLSFJ5ZFdVcExuQnBaRHRjYmlBZ2ZWeHVYRzRnSUd4cGJtc29jR2xrS1h0Y2JpQWdJQ0IwYUdsekxteHBibXR6TG1kbGRDaDBhR2x6TG5CcFpDZ3BLUzVoWkdRb2NHbGtLVHRjYmlBZ0lDQjBhR2x6TG14cGJtdHpMbWRsZENod2FXUXBMbUZrWkNoMGFHbHpMbkJwWkNncEtUdGNiaUFnZlZ4dVhHNGdJSFZ1YkdsdWF5aHdhV1FwZTF4dUlDQWdJSFJvYVhNdWJHbHVhM011WjJWMEtIUm9hWE11Y0dsa0tDa3BMbVJsYkdWMFpTaHdhV1FwTzF4dUlDQWdJSFJvYVhNdWJHbHVhM011WjJWMEtIQnBaQ2t1WkdWc1pYUmxLSFJvYVhNdWNHbGtLQ2twTzF4dUlDQjlYRzVjYmlBZ2MyVjBYMk4xY25KbGJuUW9hV1FwZTF4dUlDQWdJR3hsZENCd2FXUWdQU0IwYUdsekxuQnBaRzltS0dsa0tUdGNiaUFnSUNCcFppaHdhV1FnSVQwOUlHNTFiR3dwZTF4dUlDQWdJQ0FnZEdocGN5NWpkWEp5Wlc1MFgzQnliMk5sYzNNZ1BTQjBhR2x6TG5CcFpITXVaMlYwS0hCcFpDazdYRzRnSUNBZ0lDQjBhR2x6TG1OMWNuSmxiblJmY0hKdlkyVnpjeTV6ZEdGMGRYTWdQU0JUZEdGMFpYTXVVbFZPVGtsT1J6dGNiaUFnSUNCOVhHNGdJSDFjYmx4dUlDQmhaR1JmY0hKdll5aHNhVzVyWldRcGUxeHVJQ0FnSUd4bGRDQnVaWGR3YVdRZ1BTQnVaWGNnVUhKcGJXbDBhWFpsY3k1UVNVUW9LVHRjYmlBZ0lDQnNaWFFnYldGcGJHSnZlQ0E5SUc1bGR5Qk5ZV2xzWW05NEtDazdYRzRnSUNBZ2JHVjBJRzVsZDNCeWIyTWdQU0J1WlhjZ1VISnZZMlZ6Y3lodVpYZHdhV1FzSUcxaGFXeGliM2dwTzF4dVhHNGdJQ0FnZEdocGN5NXdhV1J6TG5ObGRDaHVaWGR3YVdRc0lHNWxkM0J5YjJNcE8xeHVJQ0FnSUhSb2FYTXViV0ZwYkdKdmVHVnpMbk5sZENodVpYZHdhV1FzSUcxaGFXeGliM2dwTzF4dUlDQWdJSFJvYVhNdWJHbHVhM011YzJWMEtHNWxkM0JwWkN3Z2JtVjNJRk5sZENncEtUdGNibHh1SUNBZ0lHbG1LR3hwYm10bFpDbDdYRzRnSUNBZ0lDQjBhR2x6TG14cGJtc29ibVYzY0dsa0tUdGNiaUFnSUNCOVhHNWNiaUFnSUNCeVpYUjFjbTRnYm1WM2NISnZZenRjYmlBZ2ZWeHVYRzRnSUhKbGJXOTJaVjl3Y205aktIQnBaQ2w3WEc0Z0lDQWdkR2hwY3k1d2FXUnpMbVJsYkdWMFpTaHdhV1FwTzF4dUlDQWdJSFJvYVhNdWRXNXlaV2RwYzNSbGNpaHdhV1FwTzF4dVhHNGdJQ0FnYVdZb2RHaHBjeTVzYVc1cmN5NW9ZWE1vY0dsa0tTbDdYRzRnSUNBZ0lDQm1iM0lnS0d4bGRDQnNhVzVyY0dsa0lHOW1JSFJvYVhNdWJHbHVhM011WjJWMEtIQnBaQ2twSUh0Y2JpQWdJQ0FnSUNBZ2RHaHBjeTVzYVc1cmN5NW5aWFFvYkdsdWEzQnBaQ2t1WkdWc1pYUmxLSEJwWkNrN1hHNGdJQ0FnSUNCOVhHNWNiaUFnSUNBZ0lIUm9hWE11YkdsdWEzTXVaR1ZzWlhSbEtIQnBaQ2s3WEc0Z0lDQWdmVnh1SUNCOVhHNWNiaUFnWlhocGRDaHBaQ2w3WEc0Z0lDQWdiR1YwSUhCcFpDQTlJSFJvYVhNdWNHbGtiMllvYVdRcE8xeHVJQ0FnSUhSb2FYTXVjbVZ0YjNabFgzQnliMk1vYVdRcE8xeHVJQ0I5WEc1Y2JpQWdjbVZuYVhOMFpYSW9ibUZ0WlN3Z2NHbGtLWHRjYmlBZ0lDQnBaaWdoZEdocGN5NXVZVzFsY3k1b1lYTW9ibUZ0WlNrcGUxeHVJQ0FnSUNBZ2RHaHBjeTV1WVcxbGN5NXpaWFFvYm1GdFpTd2djR2xrS1Z4dUlDQWdJQ0FnY21WMGRYSnVJRzVoYldVN1hHNGdJQ0FnZldWc2MyVjdYRzRnSUNBZ0lDQjBhSEp2ZHlCdVpYY2dSWEp5YjNJb1hDSk9ZVzFsSUdseklHRnNjbVZoWkhrZ2NtVm5hWE4wWlhKbFpDQjBieUJoYm05MGFHVnlJSEJ5YjJObGMzTmNJaWs3WEc0Z0lDQWdmVnh1SUNCOVhHNWNiaUFnY21WbmFYTjBaWEpsWkNodVlXMWxLWHRjYmlBZ0lDQnlaWFIxY200Z2RHaHBjeTV1WVcxbGN5NW9ZWE1vYm1GdFpTa2dQeUIwYUdsekxtNWhiV1Z6TG1kbGRDaHVZVzFsS1NBNklHNTFiR3c3WEc0Z0lIMWNibHh1SUNCMWJuSmxaMmx6ZEdWeUtIQnBaQ2w3WEc0Z0lDQWdabTl5S0d4bGRDQnVZVzFsSUc5bUlIUm9hWE11Ym1GdFpYTXVhMlY1Y3lncEtYdGNiaUFnSUNBZ0lHbG1LSFJvYVhNdWJtRnRaWE11YUdGektHNWhiV1VwSUNZbUlIUm9hWE11Ym1GdFpYTXVaMlYwS0c1aGJXVXBJRDA5UFNCd2FXUXBlMXh1SUNBZ0lDQWdJQ0IwYUdsekxtNWhiV1Z6TG1SbGJHVjBaU2h1WVcxbEtUdGNiaUFnSUNBZ0lIMWNiaUFnSUNCOVhHNGdJSDFjYmx4dUlDQndhV1FvS1h0Y2JpQWdJQ0J5WlhSMWNtNGdkR2hwY3k1amRYSnlaVzUwWDNCeWIyTmxjM011Y0dsa08xeHVJQ0I5WEc1Y2JpQWdjR2xrYjJZb2FXUXBlMXh1SUNBZ0lHbG1JQ2hwWkNCcGJuTjBZVzVqWlc5bUlGQnlhVzFwZEdsMlpYTXVVRWxFS1NCN1hHNGdJQ0FnSUNBZ2NtVjBkWEp1SUhSb2FYTXVjR2xrY3k1b1lYTW9hV1FwSUQ4Z2FXUWdPaUJ1ZFd4c08xeHVJQ0FnSUgwZ1pXeHpaU0JwWmlBb2FXUWdhVzV6ZEdGdVkyVnZaaUJRY205alpYTnpLU0I3WEc0Z0lDQWdJQ0FnY21WMGRYSnVJR2xrTG5CcFpEdGNiaUFnSUNCOUlHVnNjMlVnZTF4dUlDQWdJQ0FnSUd4bGRDQndhV1FnUFNCMGFHbHpMbkpsWjJsemRHVnlaV1FvYVdRcE8xeHVJQ0FnSUNBZ0lHbG1JQ2h3YVdRZ1BUMDlJRzUxYkd3cFhHNGdJQ0FnSUNBZ0lDQWdkR2h5YjNjb1hDSlFjbTlqWlhOeklHNWhiV1VnYm05MElISmxaMmx6ZEdWeVpXUTZJRndpSUNzZ2FXUWdLeUJjSWlBb1hDSWdLeUIwZVhCbGIyWW9hV1FwSUNzZ1hDSXBYQ0lwTzF4dUlDQWdJQ0FnSUhKbGRIVnliaUJ3YVdRN1hHNGdJQ0FnZlZ4dUlDQjlYRzVjYmlBZ2NIVjBLR2xrTENCclpYa3NJSFpoYkhWbEtYdGNiaUFnSUNCc1pYUWdjR2xrSUQwZ2RHaHBjeTV3YVdSdlppaHBaQ2s3WEc0Z0lDQWdiR1YwSUhCeWIyTmxjM01nUFNCMGFHbHpMbkJwWkhNdVoyVjBLSEJwWkNrN1hHNGdJQ0FnY0hKdlkyVnpjeTVrYVdOMFcydGxlVjBnUFNCMllXeDFaVHRjYmlBZ2ZWeHVYRzRnSUdkbGRDaHBaQ3dnYTJWNUtYdGNiaUFnSUNCc1pYUWdjR2xrSUQwZ2RHaHBjeTV3YVdSdlppaHBaQ2s3WEc0Z0lDQWdiR1YwSUhCeWIyTmxjM01nUFNCMGFHbHpMbkJwWkhNdVoyVjBLSEJwWkNrN1hHNWNiaUFnSUNCcFppaHJaWGtnSVQwZ2JuVnNiQ2w3WEc0Z0lDQWdJQ0J5WlhSMWNtNGdjSEp2WTJWemN5NWthV04wVzJ0bGVWMDdYRzRnSUNBZ2ZXVnNjMlY3WEc0Z0lDQWdJQ0J5WlhSMWNtNGdjSEp2WTJWemN5NWthV04wTzF4dUlDQWdJSDFjYmlBZ2ZWeHVYRzRnSUdkbGRGOXJaWGx6S0dsa0tYdGNiaUFnSUNCc1pYUWdjR2xrSUQwZ2RHaHBjeTV3YVdSdlppaHBaQ2s3WEc0Z0lDQWdiR1YwSUhCeWIyTmxjM01nUFNCMGFHbHpMbkJwWkhNdVoyVjBLSEJwWkNrN1hHNWNiaUFnSUNCeVpYUjFjbTRnVDJKcVpXTjBMbXRsZVhNb2NISnZZMlZ6Y3k1a2FXTjBLVHRjYmlBZ2ZWeHVYRzRnSUdWeVlYTmxLR2xrTENCclpYa3BlMXh1SUNBZ0lHeGxkQ0J3YVdRZ1BTQjBhR2x6TG5CcFpHOW1LR2xrS1R0Y2JpQWdJQ0JzWlhRZ2NISnZZMlZ6Y3lBOUlIUm9hWE11Y0dsa2N5NW5aWFFvY0dsa0tUdGNibHh1SUNBZ0lHbG1LR3RsZVNBaFBTQnVkV3hzS1h0Y2JpQWdJQ0FnSUdSbGJHVjBaU0J3Y205alpYTnpMbVJwWTNSYmEyVjVYVHRjYmlBZ0lDQjlaV3h6Wlh0Y2JpQWdJQ0FnSUhCeWIyTmxjM011WkdsamRDQTlJSHQ5TzF4dUlDQWdJSDFjYmlBZ2ZWeHVmVnh1WEc1bGVIQnZjblFnWkdWbVlYVnNkQ0JRY205alpYTnpVM2x6ZEdWdE8xeHVJbDBzSW5OdmRYSmpaVkp2YjNRaU9pSXZjMjkxY21ObEx5SjlcbiIsImNsYXNzIEJpdFN0cmluZyB7XG4gIGNvbnN0cnVjdG9yKC4uLmFyZ3MpIHtcbiAgICB0aGlzLnJhd192YWx1ZSA9IGZ1bmN0aW9uICgpIHtcbiAgICAgIHJldHVybiBPYmplY3QuZnJlZXplKGFyZ3MpO1xuICAgIH07XG5cbiAgICB0aGlzLnZhbHVlID0gT2JqZWN0LmZyZWV6ZSh0aGlzLnByb2Nlc3MoYXJncykpO1xuICAgIHRoaXMubGVuZ3RoID0gdGhpcy52YWx1ZS5sZW5ndGg7XG4gICAgdGhpcy5iaXRfc2l6ZSA9IHRoaXMucmF3X3ZhbHVlKCkucmVkdWNlKChwcmV2LCBjdXJyZW50KSA9PiBwcmV2ICsgY3VycmVudC5zaXplKTtcbiAgICB0aGlzLmJ5dGVfc2l6ZSA9IHRoaXMuYml0X3NpemUgLyA4ICsgKHRoaXMuYml0X3NpemUgJSA4ID4gMCA/IDEgOiAwKTtcbiAgfVxuXG4gIGdldChpbmRleCkge1xuICAgIHJldHVybiB0aGlzLnZhbHVlW2luZGV4XTtcbiAgfVxuXG4gIGNvdW50KCkge1xuICAgIHJldHVybiB0aGlzLnZhbHVlLmxlbmd0aDtcbiAgfVxuXG4gIFtTeW1ib2wuaXRlcmF0b3JdKCkge1xuICAgIHJldHVybiB0aGlzLnZhbHVlW1N5bWJvbC5pdGVyYXRvcl0oKTtcbiAgfVxuXG4gIHRvU3RyaW5nKCkge1xuICAgIHZhciBpLFxuICAgICAgICBzID0gXCJcIjtcbiAgICBmb3IgKGkgPSAwOyBpIDwgdGhpcy5jb3VudCgpOyBpKyspIHtcbiAgICAgIGlmIChzICE9PSBcIlwiKSB7XG4gICAgICAgIHMgKz0gXCIsIFwiO1xuICAgICAgfVxuICAgICAgcyArPSB0aGlzW2ldLnRvU3RyaW5nKCk7XG4gICAgfVxuXG4gICAgcmV0dXJuIFwiPDxcIiArIHMgKyBcIj4+XCI7XG4gIH1cblxuICBwcm9jZXNzKCkge1xuICAgIGxldCBwcm9jZXNzZWRfdmFsdWVzID0gW107XG5cbiAgICB2YXIgaTtcbiAgICBmb3IgKGkgPSAwOyBpIDwgdGhpcy5yYXdfdmFsdWUoKS5sZW5ndGg7IGkrKykge1xuICAgICAgbGV0IHByb2Nlc3NlZF92YWx1ZSA9IHRoaXNbJ3Byb2Nlc3NfJyArIHRoaXMucmF3X3ZhbHVlKClbaV0udHlwZV0odGhpcy5yYXdfdmFsdWUoKVtpXSk7XG5cbiAgICAgIGZvciAobGV0IGF0dHIgb2YgdGhpcy5yYXdfdmFsdWUoKVtpXS5hdHRyaWJ1dGVzKSB7XG4gICAgICAgIHByb2Nlc3NlZF92YWx1ZSA9IHRoaXNbJ3Byb2Nlc3NfJyArIGF0dHJdKHByb2Nlc3NlZF92YWx1ZSk7XG4gICAgICB9XG5cbiAgICAgIHByb2Nlc3NlZF92YWx1ZXMgPSBwcm9jZXNzZWRfdmFsdWVzLmNvbmNhdChwcm9jZXNzZWRfdmFsdWUpO1xuICAgIH1cblxuICAgIHJldHVybiBwcm9jZXNzZWRfdmFsdWVzO1xuICB9XG5cbiAgcHJvY2Vzc19pbnRlZ2VyKHZhbHVlKSB7XG4gICAgcmV0dXJuIHZhbHVlLnZhbHVlO1xuICB9XG5cbiAgcHJvY2Vzc19mbG9hdCh2YWx1ZSkge1xuICAgIGlmICh2YWx1ZS5zaXplID09PSA2NCkge1xuICAgICAgcmV0dXJuIEJpdFN0cmluZy5mbG9hdDY0VG9CeXRlcyh2YWx1ZS52YWx1ZSk7XG4gICAgfSBlbHNlIGlmICh2YWx1ZS5zaXplID09PSAzMikge1xuICAgICAgcmV0dXJuIEJpdFN0cmluZy5mbG9hdDMyVG9CeXRlcyh2YWx1ZS52YWx1ZSk7XG4gICAgfVxuXG4gICAgdGhyb3cgbmV3IEVycm9yKCdJbnZhbGlkIHNpemUgZm9yIGZsb2F0Jyk7XG4gIH1cblxuICBwcm9jZXNzX2JpdHN0cmluZyh2YWx1ZSkge1xuICAgIHJldHVybiB2YWx1ZS52YWx1ZS52YWx1ZTtcbiAgfVxuXG4gIHByb2Nlc3NfYmluYXJ5KHZhbHVlKSB7XG4gICAgcmV0dXJuIEJpdFN0cmluZy50b1VURjhBcnJheSh2YWx1ZS52YWx1ZSk7XG4gIH1cblxuICBwcm9jZXNzX3V0ZjgodmFsdWUpIHtcbiAgICByZXR1cm4gQml0U3RyaW5nLnRvVVRGOEFycmF5KHZhbHVlLnZhbHVlKTtcbiAgfVxuXG4gIHByb2Nlc3NfdXRmMTYodmFsdWUpIHtcbiAgICByZXR1cm4gQml0U3RyaW5nLnRvVVRGMTZBcnJheSh2YWx1ZS52YWx1ZSk7XG4gIH1cblxuICBwcm9jZXNzX3V0ZjMyKHZhbHVlKSB7XG4gICAgcmV0dXJuIEJpdFN0cmluZy50b1VURjMyQXJyYXkodmFsdWUudmFsdWUpO1xuICB9XG5cbiAgcHJvY2Vzc19zaWduZWQodmFsdWUpIHtcbiAgICByZXR1cm4gbmV3IFVpbnQ4QXJyYXkoW3ZhbHVlXSlbMF07XG4gIH1cblxuICBwcm9jZXNzX3Vuc2lnbmVkKHZhbHVlKSB7XG4gICAgcmV0dXJuIHZhbHVlO1xuICB9XG5cbiAgcHJvY2Vzc19uYXRpdmUodmFsdWUpIHtcbiAgICByZXR1cm4gdmFsdWU7XG4gIH1cblxuICBwcm9jZXNzX2JpZyh2YWx1ZSkge1xuICAgIHJldHVybiB2YWx1ZTtcbiAgfVxuXG4gIHByb2Nlc3NfbGl0dGxlKHZhbHVlKSB7XG4gICAgcmV0dXJuIHZhbHVlLnJldmVyc2UoKTtcbiAgfVxuXG4gIHByb2Nlc3Nfc2l6ZSh2YWx1ZSkge1xuICAgIHJldHVybiB2YWx1ZTtcbiAgfVxuXG4gIHByb2Nlc3NfdW5pdCh2YWx1ZSkge1xuICAgIHJldHVybiB2YWx1ZTtcbiAgfVxuXG4gIHN0YXRpYyBpbnRlZ2VyKHZhbHVlKSB7XG4gICAgcmV0dXJuIEJpdFN0cmluZy53cmFwKHZhbHVlLCB7ICd0eXBlJzogJ2ludGVnZXInLCAndW5pdCc6IDEsICdzaXplJzogOCB9KTtcbiAgfVxuXG4gIHN0YXRpYyBmbG9hdCh2YWx1ZSkge1xuICAgIHJldHVybiBCaXRTdHJpbmcud3JhcCh2YWx1ZSwgeyAndHlwZSc6ICdmbG9hdCcsICd1bml0JzogMSwgJ3NpemUnOiA2NCB9KTtcbiAgfVxuXG4gIHN0YXRpYyBiaXRzdHJpbmcodmFsdWUpIHtcbiAgICByZXR1cm4gQml0U3RyaW5nLndyYXAodmFsdWUsIHsgJ3R5cGUnOiAnYml0c3RyaW5nJywgJ3VuaXQnOiAxLCAnc2l6ZSc6IHZhbHVlLmJpdF9zaXplIH0pO1xuICB9XG5cbiAgc3RhdGljIGJpdHModmFsdWUpIHtcbiAgICByZXR1cm4gQml0U3RyaW5nLmJpdHN0cmluZyh2YWx1ZSk7XG4gIH1cblxuICBzdGF0aWMgYmluYXJ5KHZhbHVlKSB7XG4gICAgcmV0dXJuIEJpdFN0cmluZy53cmFwKHZhbHVlLCB7ICd0eXBlJzogJ2JpbmFyeScsICd1bml0JzogOCwgJ3NpemUnOiB2YWx1ZS5sZW5ndGggfSk7XG4gIH1cblxuICBzdGF0aWMgYnl0ZXModmFsdWUpIHtcbiAgICByZXR1cm4gQml0U3RyaW5nLmJpbmFyeSh2YWx1ZSk7XG4gIH1cblxuICBzdGF0aWMgdXRmOCh2YWx1ZSkge1xuICAgIHJldHVybiBCaXRTdHJpbmcud3JhcCh2YWx1ZSwgeyAndHlwZSc6ICd1dGY4JyB9KTtcbiAgfVxuXG4gIHN0YXRpYyB1dGYxNih2YWx1ZSkge1xuICAgIHJldHVybiBCaXRTdHJpbmcud3JhcCh2YWx1ZSwgeyAndHlwZSc6ICd1dGYxNicgfSk7XG4gIH1cblxuICBzdGF0aWMgdXRmMzIodmFsdWUpIHtcbiAgICByZXR1cm4gQml0U3RyaW5nLndyYXAodmFsdWUsIHsgJ3R5cGUnOiAndXRmMzInIH0pO1xuICB9XG5cbiAgc3RhdGljIHNpZ25lZCh2YWx1ZSkge1xuICAgIHJldHVybiBCaXRTdHJpbmcud3JhcCh2YWx1ZSwge30sICdzaWduZWQnKTtcbiAgfVxuXG4gIHN0YXRpYyB1bnNpZ25lZCh2YWx1ZSkge1xuICAgIHJldHVybiBCaXRTdHJpbmcud3JhcCh2YWx1ZSwge30sICd1bnNpZ25lZCcpO1xuICB9XG5cbiAgc3RhdGljIG5hdGl2ZSh2YWx1ZSkge1xuICAgIHJldHVybiBCaXRTdHJpbmcud3JhcCh2YWx1ZSwge30sICduYXRpdmUnKTtcbiAgfVxuXG4gIHN0YXRpYyBiaWcodmFsdWUpIHtcbiAgICByZXR1cm4gQml0U3RyaW5nLndyYXAodmFsdWUsIHt9LCAnYmlnJyk7XG4gIH1cblxuICBzdGF0aWMgbGl0dGxlKHZhbHVlKSB7XG4gICAgcmV0dXJuIEJpdFN0cmluZy53cmFwKHZhbHVlLCB7fSwgJ2xpdHRsZScpO1xuICB9XG5cbiAgc3RhdGljIHNpemUodmFsdWUsIGNvdW50KSB7XG4gICAgcmV0dXJuIEJpdFN0cmluZy53cmFwKHZhbHVlLCB7ICdzaXplJzogY291bnQgfSk7XG4gIH1cblxuICBzdGF0aWMgdW5pdCh2YWx1ZSwgY291bnQpIHtcbiAgICByZXR1cm4gQml0U3RyaW5nLndyYXAodmFsdWUsIHsgJ3VuaXQnOiBjb3VudCB9KTtcbiAgfVxuXG4gIHN0YXRpYyB3cmFwKHZhbHVlLCBvcHQsIG5ld19hdHRyaWJ1dGUgPSBudWxsKSB7XG4gICAgbGV0IHRoZV92YWx1ZSA9IHZhbHVlO1xuXG4gICAgaWYgKCEodmFsdWUgaW5zdGFuY2VvZiBPYmplY3QpKSB7XG4gICAgICB0aGVfdmFsdWUgPSB7ICd2YWx1ZSc6IHZhbHVlLCAnYXR0cmlidXRlcyc6IFtdIH07XG4gICAgfVxuXG4gICAgdGhlX3ZhbHVlID0gT2JqZWN0LmFzc2lnbih0aGVfdmFsdWUsIG9wdCk7XG5cbiAgICBpZiAobmV3X2F0dHJpYnV0ZSkge1xuICAgICAgdGhlX3ZhbHVlLmF0dHJpYnV0ZXMucHVzaChuZXdfYXR0cmlidXRlKTtcbiAgICB9XG5cbiAgICByZXR1cm4gdGhlX3ZhbHVlO1xuICB9XG5cbiAgc3RhdGljIHRvVVRGOEFycmF5KHN0cikge1xuICAgIHZhciB1dGY4ID0gW107XG4gICAgZm9yICh2YXIgaSA9IDA7IGkgPCBzdHIubGVuZ3RoOyBpKyspIHtcbiAgICAgIHZhciBjaGFyY29kZSA9IHN0ci5jaGFyQ29kZUF0KGkpO1xuICAgICAgaWYgKGNoYXJjb2RlIDwgMHg4MCkge1xuICAgICAgICB1dGY4LnB1c2goY2hhcmNvZGUpO1xuICAgICAgfSBlbHNlIGlmIChjaGFyY29kZSA8IDB4ODAwKSB7XG4gICAgICAgIHV0ZjgucHVzaCgweGMwIHwgY2hhcmNvZGUgPj4gNiwgMHg4MCB8IGNoYXJjb2RlICYgMHgzZik7XG4gICAgICB9IGVsc2UgaWYgKGNoYXJjb2RlIDwgMHhkODAwIHx8IGNoYXJjb2RlID49IDB4ZTAwMCkge1xuICAgICAgICB1dGY4LnB1c2goMHhlMCB8IGNoYXJjb2RlID4+IDEyLCAweDgwIHwgY2hhcmNvZGUgPj4gNiAmIDB4M2YsIDB4ODAgfCBjaGFyY29kZSAmIDB4M2YpO1xuICAgICAgfVxuICAgICAgLy8gc3Vycm9nYXRlIHBhaXJcbiAgICAgIGVsc2Uge1xuICAgICAgICAgIGkrKztcbiAgICAgICAgICAvLyBVVEYtMTYgZW5jb2RlcyAweDEwMDAwLTB4MTBGRkZGIGJ5XG4gICAgICAgICAgLy8gc3VidHJhY3RpbmcgMHgxMDAwMCBhbmQgc3BsaXR0aW5nIHRoZVxuICAgICAgICAgIC8vIDIwIGJpdHMgb2YgMHgwLTB4RkZGRkYgaW50byB0d28gaGFsdmVzXG4gICAgICAgICAgY2hhcmNvZGUgPSAweDEwMDAwICsgKChjaGFyY29kZSAmIDB4M2ZmKSA8PCAxMCB8IHN0ci5jaGFyQ29kZUF0KGkpICYgMHgzZmYpO1xuICAgICAgICAgIHV0ZjgucHVzaCgweGYwIHwgY2hhcmNvZGUgPj4gMTgsIDB4ODAgfCBjaGFyY29kZSA+PiAxMiAmIDB4M2YsIDB4ODAgfCBjaGFyY29kZSA+PiA2ICYgMHgzZiwgMHg4MCB8IGNoYXJjb2RlICYgMHgzZik7XG4gICAgICAgIH1cbiAgICB9XG4gICAgcmV0dXJuIHV0Zjg7XG4gIH1cblxuICBzdGF0aWMgdG9VVEYxNkFycmF5KHN0cikge1xuICAgIHZhciB1dGYxNiA9IFtdO1xuICAgIGZvciAodmFyIGkgPSAwOyBpIDwgc3RyLmxlbmd0aDsgaSsrKSB7XG4gICAgICB2YXIgY29kZVBvaW50ID0gc3RyLmNvZGVQb2ludEF0KGkpO1xuXG4gICAgICBpZiAoY29kZVBvaW50IDw9IDI1NSkge1xuICAgICAgICB1dGYxNi5wdXNoKDApO1xuICAgICAgICB1dGYxNi5wdXNoKGNvZGVQb2ludCk7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICB1dGYxNi5wdXNoKGNvZGVQb2ludCA+PiA4ICYgMHhGRik7XG4gICAgICAgIHV0ZjE2LnB1c2goY29kZVBvaW50ICYgMHhGRik7XG4gICAgICB9XG4gICAgfVxuICAgIHJldHVybiB1dGYxNjtcbiAgfVxuXG4gIHN0YXRpYyB0b1VURjMyQXJyYXkoc3RyKSB7XG4gICAgdmFyIHV0ZjMyID0gW107XG4gICAgZm9yICh2YXIgaSA9IDA7IGkgPCBzdHIubGVuZ3RoOyBpKyspIHtcbiAgICAgIHZhciBjb2RlUG9pbnQgPSBzdHIuY29kZVBvaW50QXQoaSk7XG5cbiAgICAgIGlmIChjb2RlUG9pbnQgPD0gMjU1KSB7XG4gICAgICAgIHV0ZjMyLnB1c2goMCk7XG4gICAgICAgIHV0ZjMyLnB1c2goMCk7XG4gICAgICAgIHV0ZjMyLnB1c2goMCk7XG4gICAgICAgIHV0ZjMyLnB1c2goY29kZVBvaW50KTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHV0ZjMyLnB1c2goMCk7XG4gICAgICAgIHV0ZjMyLnB1c2goMCk7XG4gICAgICAgIHV0ZjMyLnB1c2goY29kZVBvaW50ID4+IDggJiAweEZGKTtcbiAgICAgICAgdXRmMzIucHVzaChjb2RlUG9pbnQgJiAweEZGKTtcbiAgICAgIH1cbiAgICB9XG4gICAgcmV0dXJuIHV0ZjMyO1xuICB9XG5cbiAgLy9odHRwOi8vc3RhY2tvdmVyZmxvdy5jb20vcXVlc3Rpb25zLzIwMDM0OTMvamF2YXNjcmlwdC1mbG9hdC1mcm9tLXRvLWJpdHNcbiAgc3RhdGljIGZsb2F0MzJUb0J5dGVzKGYpIHtcbiAgICB2YXIgYnl0ZXMgPSBbXTtcblxuICAgIHZhciBidWYgPSBuZXcgQXJyYXlCdWZmZXIoNCk7XG4gICAgbmV3IEZsb2F0MzJBcnJheShidWYpWzBdID0gZjtcblxuICAgIGxldCBpbnRWZXJzaW9uID0gbmV3IFVpbnQzMkFycmF5KGJ1ZilbMF07XG5cbiAgICBieXRlcy5wdXNoKGludFZlcnNpb24gPj4gMjQgJiAweEZGKTtcbiAgICBieXRlcy5wdXNoKGludFZlcnNpb24gPj4gMTYgJiAweEZGKTtcbiAgICBieXRlcy5wdXNoKGludFZlcnNpb24gPj4gOCAmIDB4RkYpO1xuICAgIGJ5dGVzLnB1c2goaW50VmVyc2lvbiAmIDB4RkYpO1xuXG4gICAgcmV0dXJuIGJ5dGVzO1xuICB9XG5cbiAgc3RhdGljIGZsb2F0NjRUb0J5dGVzKGYpIHtcbiAgICB2YXIgYnl0ZXMgPSBbXTtcblxuICAgIHZhciBidWYgPSBuZXcgQXJyYXlCdWZmZXIoOCk7XG4gICAgbmV3IEZsb2F0NjRBcnJheShidWYpWzBdID0gZjtcblxuICAgIHZhciBpbnRWZXJzaW9uMSA9IG5ldyBVaW50MzJBcnJheShidWYpWzBdO1xuICAgIHZhciBpbnRWZXJzaW9uMiA9IG5ldyBVaW50MzJBcnJheShidWYpWzFdO1xuXG4gICAgYnl0ZXMucHVzaChpbnRWZXJzaW9uMiA+PiAyNCAmIDB4RkYpO1xuICAgIGJ5dGVzLnB1c2goaW50VmVyc2lvbjIgPj4gMTYgJiAweEZGKTtcbiAgICBieXRlcy5wdXNoKGludFZlcnNpb24yID4+IDggJiAweEZGKTtcbiAgICBieXRlcy5wdXNoKGludFZlcnNpb24yICYgMHhGRik7XG5cbiAgICBieXRlcy5wdXNoKGludFZlcnNpb24xID4+IDI0ICYgMHhGRik7XG4gICAgYnl0ZXMucHVzaChpbnRWZXJzaW9uMSA+PiAxNiAmIDB4RkYpO1xuICAgIGJ5dGVzLnB1c2goaW50VmVyc2lvbjEgPj4gOCAmIDB4RkYpO1xuICAgIGJ5dGVzLnB1c2goaW50VmVyc2lvbjEgJiAweEZGKTtcblxuICAgIHJldHVybiBieXRlcztcbiAgfVxufVxuXG5leHBvcnQgZGVmYXVsdCBCaXRTdHJpbmc7XG4vLyMgc291cmNlTWFwcGluZ1VSTD1kYXRhOmFwcGxpY2F0aW9uL2pzb247YmFzZTY0LGV5SjJaWEp6YVc5dUlqb3pMQ0p6YjNWeVkyVnpJanBiSW14cFlpOWpiM0psTDJKcGRGOXpkSEpwYm1jdWFuTWlYU3dpYm1GdFpYTWlPbHRkTENKdFlYQndhVzVuY3lJNklrRkJRVUVzVFVGQlRTeFRRVUZPTEVOQlFXZENPMEZCUTJRc1kwRkJXU3hIUVVGSExFbEJRVWdzUlVGQlVUdEJRVU5zUWl4VFFVRkxMRk5CUVV3c1IwRkJhVUlzV1VGQlZUdEJRVU42UWl4aFFVRlBMRTlCUVU4c1RVRkJVQ3hEUVVGakxFbEJRV1FzUTBGQlVDeERRVVI1UWp0TFFVRldMRU5CUkVNN08wRkJTMnhDTEZOQlFVc3NTMEZCVEN4SFFVRmhMRTlCUVU4c1RVRkJVQ3hEUVVGakxFdEJRVXNzVDBGQlRDeERRVUZoTEVsQlFXSXNRMEZCWkN4RFFVRmlMRU5CVEd0Q08wRkJUV3hDTEZOQlFVc3NUVUZCVEN4SFFVRmpMRXRCUVVzc1MwRkJUQ3hEUVVGWExFMUJRVmdzUTBGT1NUdEJRVTlzUWl4VFFVRkxMRkZCUVV3c1IwRkJaMElzUzBGQlN5eFRRVUZNTEVkQlFXbENMRTFCUVdwQ0xFTkJRWGRDTEVOQlFVTXNTVUZCUkN4RlFVRlBMRTlCUVZBc1MwRkJiVUlzVDBGQlR5eFJRVUZSTEVsQlFWSXNRMEZCYkVVc1EwRlFhMEk3UVVGUmJFSXNVMEZCU3l4VFFVRk1MRWRCUVdsQ0xFbEJRVU1zUTBGQlN5eFJRVUZNTEVkQlFXZENMRU5CUVdoQ0xFbEJRWE5DTEV0QlFVc3NVVUZCVEN4SFFVRm5RaXhEUVVGb1FpeEhRVUZ2UWl4RFFVRndRaXhIUVVGM1FpeERRVUY0UWl4SFFVRTBRaXhEUVVFMVFpeERRVUYyUWl4RFFWSkRPMGRCUVhCQ096dEJRVmRCTEUxQlFVa3NTMEZCU2l4RlFVRlZPMEZCUTFJc1YwRkJUeXhMUVVGTExFdEJRVXdzUTBGQlZ5eExRVUZZTEVOQlFWQXNRMEZFVVR0SFFVRldPenRCUVVsQkxGVkJRVTg3UVVGRFRDeFhRVUZQTEV0QlFVc3NTMEZCVEN4RFFVRlhMRTFCUVZnc1EwRkVSanRIUVVGUU96dEJRVWxCTEVkQlFVTXNUMEZCVHl4UlFVRlFMRWxCUVcxQ08wRkJRMnhDTEZkQlFVOHNTMEZCU3l4TFFVRk1MRU5CUVZjc1QwRkJUeXhSUVVGUUxFTkJRVmdzUlVGQlVDeERRVVJyUWp0SFFVRndRanM3UVVGSlFTeGhRVUZWTzBGQlExSXNVVUZCU1N4RFFVRktPMUZCUVU4c1NVRkJTU3hGUVVGS0xFTkJSRU03UVVGRlVpeFRRVUZMTEVsQlFVa3NRMEZCU2l4RlFVRlBMRWxCUVVrc1MwRkJTeXhMUVVGTUxFVkJRVW9zUlVGQmEwSXNSMEZCT1VJc1JVRkJiVU03UVVGRGFrTXNWVUZCU1N4TlFVRk5MRVZCUVU0c1JVRkJWVHRCUVVOYUxHRkJRVXNzU1VGQlRDeERRVVJaTzA5QlFXUTdRVUZIUVN4WFFVRkxMRXRCUVVzc1EwRkJUQ3hGUVVGUkxGRkJRVklzUlVGQlRDeERRVXBwUXp0TFFVRnVRenM3UVVGUFFTeFhRVUZQTEU5QlFVOHNRMEZCVUN4SFFVRlhMRWxCUVZnc1EwRlVRenRIUVVGV096dEJRVmxCTEZsQlFWTTdRVUZEVUN4UlFVRkpMRzFDUVVGdFFpeEZRVUZ1UWl4RFFVUkhPenRCUVVkUUxGRkJRVWtzUTBGQlNpeERRVWhQTzBGQlNWQXNVMEZCU3l4SlFVRkpMRU5CUVVvc1JVRkJUeXhKUVVGSkxFdEJRVXNzVTBGQlRDeEhRVUZwUWl4TlFVRnFRaXhGUVVGNVFpeEhRVUY2UXl4RlFVRTRRenRCUVVNMVF5eFZRVUZKTEd0Q1FVRnJRaXhMUVVGTExHRkJRV0VzUzBGQlN5eFRRVUZNTEVkQlFXbENMRU5CUVdwQ0xFVkJRVzlDTEVsQlFYQkNMRU5CUVd4Q0xFTkJRVFJETEV0QlFVc3NVMEZCVEN4SFFVRnBRaXhEUVVGcVFpeERRVUUxUXl4RFFVRnNRaXhEUVVSM1F6czdRVUZITlVNc1YwRkJTU3hKUVVGSkxFbEJRVW9zU1VGQldTeExRVUZMTEZOQlFVd3NSMEZCYVVJc1EwRkJha0lzUlVGQmIwSXNWVUZCY0VJc1JVRkJLMEk3UVVGRE4wTXNNRUpCUVd0Q0xFdEJRVXNzWVVGQllTeEpRVUZpTEVOQlFVd3NRMEZCZDBJc1pVRkJlRUlzUTBGQmJFSXNRMEZFTmtNN1QwRkJMME03TzBGQlNVRXNlVUpCUVcxQ0xHbENRVUZwUWl4TlFVRnFRaXhEUVVGM1FpeGxRVUY0UWl4RFFVRnVRaXhEUVZBMFF6dExRVUU1UXpzN1FVRlZRU3hYUVVGUExHZENRVUZRTEVOQlpFODdSMEZCVkRzN1FVRnBRa0VzYTBKQlFXZENMRXRCUVdoQ0xFVkJRWE5DTzBGQlEzQkNMRmRCUVU4c1RVRkJUU3hMUVVGT0xFTkJSR0U3UjBGQmRFSTdPMEZCU1VFc1owSkJRV01zUzBGQlpDeEZRVUZ2UWp0QlFVTnNRaXhSUVVGSExFMUJRVTBzU1VGQlRpeExRVUZsTEVWQlFXWXNSVUZCYTBJN1FVRkRia0lzWVVGQlR5eFZRVUZWTEdOQlFWWXNRMEZCZVVJc1RVRkJUU3hMUVVGT0xFTkJRV2hETEVOQlJHMUNPMHRCUVhKQ0xFMUJSVTBzU1VGQlJ5eE5RVUZOTEVsQlFVNHNTMEZCWlN4RlFVRm1MRVZCUVd0Q08wRkJRM3BDTEdGQlFVOHNWVUZCVlN4alFVRldMRU5CUVhsQ0xFMUJRVTBzUzBGQlRpeERRVUZvUXl4RFFVUjVRanRMUVVGeVFqczdRVUZKVGl4VlFVRk5MRWxCUVVrc1MwRkJTaXhEUVVGVkxIZENRVUZXTEVOQlFVNHNRMEZRYTBJN1IwRkJjRUk3TzBGQlZVRXNiMEpCUVd0Q0xFdEJRV3hDTEVWQlFYZENPMEZCUTNSQ0xGZEJRVThzVFVGQlRTeExRVUZPTEVOQlFWa3NTMEZCV2l4RFFVUmxPMGRCUVhoQ096dEJRVWxCTEdsQ1FVRmxMRXRCUVdZc1JVRkJjVUk3UVVGRGJrSXNWMEZCVHl4VlFVRlZMRmRCUVZZc1EwRkJjMElzVFVGQlRTeExRVUZPTEVOQlFUZENMRU5CUkcxQ08wZEJRWEpDT3p0QlFVbEJMR1ZCUVdFc1MwRkJZaXhGUVVGdFFqdEJRVU5xUWl4WFFVRlBMRlZCUVZVc1YwRkJWaXhEUVVGelFpeE5RVUZOTEV0QlFVNHNRMEZCTjBJc1EwRkVhVUk3UjBGQmJrSTdPMEZCU1VFc1owSkJRV01zUzBGQlpDeEZRVUZ2UWp0QlFVTnNRaXhYUVVGUExGVkJRVlVzV1VGQlZpeERRVUYxUWl4TlFVRk5MRXRCUVU0c1EwRkJPVUlzUTBGRWEwSTdSMEZCY0VJN08wRkJTVUVzWjBKQlFXTXNTMEZCWkN4RlFVRnZRanRCUVVOc1FpeFhRVUZQTEZWQlFWVXNXVUZCVml4RFFVRjFRaXhOUVVGTkxFdEJRVTRzUTBGQk9VSXNRMEZFYTBJN1IwRkJjRUk3TzBGQlNVRXNhVUpCUVdVc1MwRkJaaXhGUVVGeFFqdEJRVU51UWl4WFFVRlBMRWxCUVVzc1ZVRkJTaXhEUVVGbExFTkJRVU1zUzBGQlJDeERRVUZtTEVOQlFVUXNRMEZCTUVJc1EwRkJNVUlzUTBGQlVDeERRVVJ0UWp0SFFVRnlRanM3UVVGSlFTeHRRa0ZCYVVJc1MwRkJha0lzUlVGQmRVSTdRVUZEY2tJc1YwRkJUeXhMUVVGUUxFTkJSSEZDTzBkQlFYWkNPenRCUVVsQkxHbENRVUZsTEV0QlFXWXNSVUZCY1VJN1FVRkRia0lzVjBGQlR5eExRVUZRTEVOQlJHMUNPMGRCUVhKQ096dEJRVWxCTEdOQlFWa3NTMEZCV2l4RlFVRnJRanRCUVVOb1FpeFhRVUZQTEV0QlFWQXNRMEZFWjBJN1IwRkJiRUk3TzBGQlNVRXNhVUpCUVdVc1MwRkJaaXhGUVVGeFFqdEJRVU51UWl4WFFVRlBMRTFCUVUwc1QwRkJUaXhGUVVGUUxFTkJSRzFDTzBkQlFYSkNPenRCUVVsQkxHVkJRV0VzUzBGQllpeEZRVUZ0UWp0QlFVTnFRaXhYUVVGUExFdEJRVkFzUTBGRWFVSTdSMEZCYmtJN08wRkJTVUVzWlVGQllTeExRVUZpTEVWQlFXMUNPMEZCUTJwQ0xGZEJRVThzUzBGQlVDeERRVVJwUWp0SFFVRnVRanM3UVVGSlFTeFRRVUZQTEU5QlFWQXNRMEZCWlN4TFFVRm1MRVZCUVhGQ08wRkJRMjVDTEZkQlFVOHNWVUZCVlN4SlFVRldMRU5CUVdVc1MwRkJaaXhGUVVGelFpeEZRVUZGTEZGQlFWRXNVMEZCVWl4RlFVRnRRaXhSUVVGUkxFTkJRVklzUlVGQlZ5eFJRVUZSTEVOQlFWSXNSVUZCZEVRc1EwRkJVQ3hEUVVSdFFqdEhRVUZ5UWpzN1FVRkpRU3hUUVVGUExFdEJRVkFzUTBGQllTeExRVUZpTEVWQlFXMUNPMEZCUTJwQ0xGZEJRVThzVlVGQlZTeEpRVUZXTEVOQlFXVXNTMEZCWml4RlFVRnpRaXhGUVVGRkxGRkJRVkVzVDBGQlVpeEZRVUZwUWl4UlFVRlJMRU5CUVZJc1JVRkJWeXhSUVVGUkxFVkJRVklzUlVGQmNFUXNRMEZCVUN4RFFVUnBRanRIUVVGdVFqczdRVUZKUVN4VFFVRlBMRk5CUVZBc1EwRkJhVUlzUzBGQmFrSXNSVUZCZFVJN1FVRkRja0lzVjBGQlR5eFZRVUZWTEVsQlFWWXNRMEZCWlN4TFFVRm1MRVZCUVhOQ0xFVkJRVVVzVVVGQlVTeFhRVUZTTEVWQlFYRkNMRkZCUVZFc1EwRkJVaXhGUVVGWExGRkJRVkVzVFVGQlRTeFJRVUZPTEVWQlFXaEZMRU5CUVZBc1EwRkVjVUk3UjBGQmRrSTdPMEZCU1VFc1UwRkJUeXhKUVVGUUxFTkJRVmtzUzBGQldpeEZRVUZyUWp0QlFVTm9RaXhYUVVGUExGVkJRVlVzVTBGQlZpeERRVUZ2UWl4TFFVRndRaXhEUVVGUUxFTkJSR2RDTzBkQlFXeENPenRCUVVsQkxGTkJRVThzVFVGQlVDeERRVUZqTEV0QlFXUXNSVUZCYjBJN1FVRkRiRUlzVjBGQlR5eFZRVUZWTEVsQlFWWXNRMEZCWlN4TFFVRm1MRVZCUVhOQ0xFVkJRVVVzVVVGQlVTeFJRVUZTTEVWQlFXdENMRkZCUVZFc1EwRkJVaXhGUVVGWExGRkJRVkVzVFVGQlRTeE5RVUZPTEVWQlFUZEVMRU5CUVZBc1EwRkVhMEk3UjBGQmNFSTdPMEZCU1VFc1UwRkJUeXhMUVVGUUxFTkJRV0VzUzBGQllpeEZRVUZ0UWp0QlFVTnFRaXhYUVVGUExGVkJRVlVzVFVGQlZpeERRVUZwUWl4TFFVRnFRaXhEUVVGUUxFTkJSR2xDTzBkQlFXNUNPenRCUVVsQkxGTkJRVThzU1VGQlVDeERRVUZaTEV0QlFWb3NSVUZCYTBJN1FVRkRhRUlzVjBGQlR5eFZRVUZWTEVsQlFWWXNRMEZCWlN4TFFVRm1MRVZCUVhOQ0xFVkJRVVVzVVVGQlVTeE5RVUZTTEVWQlFYaENMRU5CUVZBc1EwRkVaMEk3UjBGQmJFSTdPMEZCU1VFc1UwRkJUeXhMUVVGUUxFTkJRV0VzUzBGQllpeEZRVUZ0UWp0QlFVTnFRaXhYUVVGUExGVkJRVlVzU1VGQlZpeERRVUZsTEV0QlFXWXNSVUZCYzBJc1JVRkJSU3hSUVVGUkxFOUJRVklzUlVGQmVFSXNRMEZCVUN4RFFVUnBRanRIUVVGdVFqczdRVUZKUVN4VFFVRlBMRXRCUVZBc1EwRkJZU3hMUVVGaUxFVkJRVzFDTzBGQlEycENMRmRCUVU4c1ZVRkJWU3hKUVVGV0xFTkJRV1VzUzBGQlppeEZRVUZ6UWl4RlFVRkZMRkZCUVZFc1QwRkJVaXhGUVVGNFFpeERRVUZRTEVOQlJHbENPMGRCUVc1Q096dEJRVWxCTEZOQlFVOHNUVUZCVUN4RFFVRmpMRXRCUVdRc1JVRkJiMEk3UVVGRGJFSXNWMEZCVHl4VlFVRlZMRWxCUVZZc1EwRkJaU3hMUVVGbUxFVkJRWE5DTEVWQlFYUkNMRVZCUVRCQ0xGRkJRVEZDTEVOQlFWQXNRMEZFYTBJN1IwRkJjRUk3TzBGQlNVRXNVMEZCVHl4UlFVRlFMRU5CUVdkQ0xFdEJRV2hDTEVWQlFYTkNPMEZCUTNCQ0xGZEJRVThzVlVGQlZTeEpRVUZXTEVOQlFXVXNTMEZCWml4RlFVRnpRaXhGUVVGMFFpeEZRVUV3UWl4VlFVRXhRaXhEUVVGUUxFTkJSRzlDTzBkQlFYUkNPenRCUVVsQkxGTkJRVThzVFVGQlVDeERRVUZqTEV0QlFXUXNSVUZCYjBJN1FVRkRiRUlzVjBGQlR5eFZRVUZWTEVsQlFWWXNRMEZCWlN4TFFVRm1MRVZCUVhOQ0xFVkJRWFJDTEVWQlFUQkNMRkZCUVRGQ0xFTkJRVkFzUTBGRWEwSTdSMEZCY0VJN08wRkJTVUVzVTBGQlR5eEhRVUZRTEVOQlFWY3NTMEZCV0N4RlFVRnBRanRCUVVObUxGZEJRVThzVlVGQlZTeEpRVUZXTEVOQlFXVXNTMEZCWml4RlFVRnpRaXhGUVVGMFFpeEZRVUV3UWl4TFFVRXhRaXhEUVVGUUxFTkJSR1U3UjBGQmFrSTdPMEZCU1VFc1UwRkJUeXhOUVVGUUxFTkJRV01zUzBGQlpDeEZRVUZ2UWp0QlFVTnNRaXhYUVVGUExGVkJRVlVzU1VGQlZpeERRVUZsTEV0QlFXWXNSVUZCYzBJc1JVRkJkRUlzUlVGQk1FSXNVVUZCTVVJc1EwRkJVQ3hEUVVSclFqdEhRVUZ3UWpzN1FVRkpRU3hUUVVGUExFbEJRVkFzUTBGQldTeExRVUZhTEVWQlFXMUNMRXRCUVc1Q0xFVkJRWGxDTzBGQlEzWkNMRmRCUVU4c1ZVRkJWU3hKUVVGV0xFTkJRV1VzUzBGQlppeEZRVUZ6UWl4RlFVRkRMRkZCUVZFc1MwRkJVaXhGUVVGMlFpeERRVUZRTEVOQlJIVkNPMGRCUVhwQ096dEJRVWxCTEZOQlFVOHNTVUZCVUN4RFFVRlpMRXRCUVZvc1JVRkJiVUlzUzBGQmJrSXNSVUZCZVVJN1FVRkRka0lzVjBGQlR5eFZRVUZWTEVsQlFWWXNRMEZCWlN4TFFVRm1MRVZCUVhOQ0xFVkJRVU1zVVVGQlVTeExRVUZTTEVWQlFYWkNMRU5CUVZBc1EwRkVkVUk3UjBGQmVrSTdPMEZCU1VFc1UwRkJUeXhKUVVGUUxFTkJRVmtzUzBGQldpeEZRVUZ0UWl4SFFVRnVRaXhGUVVGM1FpeG5Ra0ZCWjBJc1NVRkJhRUlzUlVGQmNVSTdRVUZETTBNc1VVRkJTU3haUVVGWkxFdEJRVm9zUTBGRWRVTTdPMEZCUnpORExGRkJRVWNzUlVGQlJTeHBRa0ZCYVVJc1RVRkJha0lzUTBGQlJpeEZRVUV5UWp0QlFVTTFRaXhyUWtGQldTeEZRVUZETEZOQlFWTXNTMEZCVkN4RlFVRm5RaXhqUVVGakxFVkJRV1FzUlVGQk4wSXNRMEZFTkVJN1MwRkJPVUk3TzBGQlNVRXNaMEpCUVZrc1QwRkJUeXhOUVVGUUxFTkJRV01zVTBGQlpDeEZRVUY1UWl4SFFVRjZRaXhEUVVGYUxFTkJVREpET3p0QlFWTXpReXhSUVVGSExHRkJRVWdzUlVGQmFVSTdRVUZEWml4blFrRkJWU3hWUVVGV0xFTkJRWEZDTEVsQlFYSkNMRU5CUVRCQ0xHRkJRVEZDTEVWQlJHVTdTMEZCYWtJN08wRkJTMEVzVjBGQlR5eFRRVUZRTEVOQlpESkRPMGRCUVRkRE96dEJRV2xDUVN4VFFVRlBMRmRCUVZBc1EwRkJiVUlzUjBGQmJrSXNSVUZCZDBJN1FVRkRkRUlzVVVGQlNTeFBRVUZQTEVWQlFWQXNRMEZFYTBJN1FVRkZkRUlzVTBGQlN5eEpRVUZKTEVsQlFVa3NRMEZCU2l4RlFVRlBMRWxCUVVrc1NVRkJTU3hOUVVGS0xFVkJRVmtzUjBGQmFFTXNSVUZCY1VNN1FVRkRia01zVlVGQlNTeFhRVUZYTEVsQlFVa3NWVUZCU2l4RFFVRmxMRU5CUVdZc1EwRkJXQ3hEUVVRclFqdEJRVVZ1UXl4VlFVRkpMRmRCUVZjc1NVRkJXQ3hGUVVGblFqdEJRVU5zUWl4aFFVRkxMRWxCUVV3c1EwRkJWU3hSUVVGV0xFVkJSR3RDTzA5QlFYQkNMRTFCUjBzc1NVRkJTU3hYUVVGWExFdEJRVmdzUlVGQmEwSTdRVUZEZWtJc1lVRkJTeXhKUVVGTUxFTkJRVlVzVDBGQlVTeFpRVUZaTEVOQlFWb3NSVUZEVWl4UFFVRlJMRmRCUVZjc1NVRkJXQ3hEUVVSc1FpeERRVVI1UWp0UFFVRjBRaXhOUVVsQkxFbEJRVWtzVjBGQlZ5eE5RVUZZTEVsQlFYRkNMRmxCUVZrc1RVRkJXaXhGUVVGdlFqdEJRVU5vUkN4aFFVRkxMRWxCUVV3c1EwRkJWU3hQUVVGUkxGbEJRVmtzUlVGQldpeEZRVU5TTEU5QlFWRXNVVUZCUXl4SlFVRlpMRU5CUVZvc1IwRkJhVUlzU1VGQmJFSXNSVUZEVWl4UFFVRlJMRmRCUVZjc1NVRkJXQ3hEUVVac1FpeERRVVJuUkRzN08wRkJRVGRETEZkQlRVRTdRVUZEU0RzN096dEJRVVJITEd0Q1FVdElMRWRCUVZjc1YwRkJWeXhEUVVGRkxGZEJRVmNzUzBGQldDeERRVUZFTEVsQlFYTkNMRVZCUVhSQ0xFZEJRMVlzU1VGQlNTeFZRVUZLTEVOQlFXVXNRMEZCWml4SlFVRnZRaXhMUVVGd1FpeERRVVJHTEVOQlRGSTdRVUZQU0N4bFFVRkxMRWxCUVV3c1EwRkJWU3hQUVVGUkxGbEJRVmtzUlVGQldpeEZRVU5TTEU5QlFWRXNVVUZCUXl4SlFVRlpMRVZCUVZvc1IwRkJhMElzU1VGQmJrSXNSVUZEVWl4UFFVRlJMRkZCUVVNc1NVRkJXU3hEUVVGYUxFZEJRV2xDTEVsQlFXeENMRVZCUTFJc1QwRkJVU3hYUVVGWExFbEJRVmdzUTBGSWJFSXNRMEZRUnp0VFFVNUJPMHRCVkZBN1FVRTBRa0VzVjBGQlR5eEpRVUZRTEVOQk9VSnpRanRIUVVGNFFqczdRVUZwUTBFc1UwRkJUeXhaUVVGUUxFTkJRVzlDTEVkQlFYQkNMRVZCUVhsQ08wRkJRM1pDTEZGQlFVa3NVVUZCVVN4RlFVRlNMRU5CUkcxQ08wRkJSWFpDTEZOQlFVc3NTVUZCU1N4SlFVRkpMRU5CUVVvc1JVRkJUeXhKUVVGSkxFbEJRVWtzVFVGQlNpeEZRVUZaTEVkQlFXaERMRVZCUVhGRE8wRkJRMjVETEZWQlFVa3NXVUZCV1N4SlFVRkpMRmRCUVVvc1EwRkJaMElzUTBGQmFFSXNRMEZCV2l4RFFVUXJRanM3UVVGSGJrTXNWVUZCUnl4aFFVRmhMRWRCUVdJc1JVRkJhVUk3UVVGRGJFSXNZMEZCVFN4SlFVRk9MRU5CUVZjc1EwRkJXQ3hGUVVSclFqdEJRVVZzUWl4alFVRk5MRWxCUVU0c1EwRkJWeXhUUVVGWUxFVkJSbXRDTzA5QlFYQkNMRTFCUjBzN1FVRkRTQ3hqUVVGTkxFbEJRVTRzUTBGQldTeFRRVUZETEVsQlFXRXNRMEZCWWl4SFFVRnJRaXhKUVVGdVFpeERRVUZhTEVOQlJFYzdRVUZGU0N4alFVRk5MRWxCUVU0c1EwRkJXU3haUVVGWkxFbEJRVm9zUTBGQldpeERRVVpITzA5QlNFdzdTMEZJUmp0QlFWZEJMRmRCUVU4c1MwRkJVQ3hEUVdKMVFqdEhRVUY2UWpzN1FVRnBRa0VzVTBGQlR5eFpRVUZRTEVOQlFXOUNMRWRCUVhCQ0xFVkJRWGxDTzBGQlEzWkNMRkZCUVVrc1VVRkJVU3hGUVVGU0xFTkJSRzFDTzBGQlJYWkNMRk5CUVVzc1NVRkJTU3hKUVVGSkxFTkJRVW9zUlVGQlR5eEpRVUZKTEVsQlFVa3NUVUZCU2l4RlFVRlpMRWRCUVdoRExFVkJRWEZETzBGQlEyNURMRlZCUVVrc1dVRkJXU3hKUVVGSkxGZEJRVW9zUTBGQlowSXNRMEZCYUVJc1EwRkJXaXhEUVVRclFqczdRVUZIYmtNc1ZVRkJSeXhoUVVGaExFZEJRV0lzUlVGQmFVSTdRVUZEYkVJc1kwRkJUU3hKUVVGT0xFTkJRVmNzUTBGQldDeEZRVVJyUWp0QlFVVnNRaXhqUVVGTkxFbEJRVTRzUTBGQlZ5eERRVUZZTEVWQlJtdENPMEZCUjJ4Q0xHTkJRVTBzU1VGQlRpeERRVUZYTEVOQlFWZ3NSVUZJYTBJN1FVRkpiRUlzWTBGQlRTeEpRVUZPTEVOQlFWY3NVMEZCV0N4RlFVcHJRanRQUVVGd1FpeE5RVXRMTzBGQlEwZ3NZMEZCVFN4SlFVRk9MRU5CUVZjc1EwRkJXQ3hGUVVSSE8wRkJSVWdzWTBGQlRTeEpRVUZPTEVOQlFWY3NRMEZCV0N4RlFVWkhPMEZCUjBnc1kwRkJUU3hKUVVGT0xFTkJRVmtzVTBGQlF5eEpRVUZoTEVOQlFXSXNSMEZCYTBJc1NVRkJia0lzUTBGQldpeERRVWhITzBGQlNVZ3NZMEZCVFN4SlFVRk9MRU5CUVZrc1dVRkJXU3hKUVVGYUxFTkJRVm9zUTBGS1J6dFBRVXhNTzB0QlNFWTdRVUZsUVN4WFFVRlBMRXRCUVZBc1EwRnFRblZDTzBkQlFYcENPenM3UVVGMFVHTXNVMEV5VVZBc1kwRkJVQ3hEUVVGelFpeERRVUYwUWl4RlFVRjVRanRCUVVOMlFpeFJRVUZKTEZGQlFWRXNSVUZCVWl4RFFVUnRRanM3UVVGSGRrSXNVVUZCU1N4TlFVRk5MRWxCUVVrc1YwRkJTaXhEUVVGblFpeERRVUZvUWl4RFFVRk9MRU5CU0cxQ08wRkJTWFpDTEZGQlFVc3NXVUZCU2l4RFFVRnBRaXhIUVVGcVFpeERRVUZFTEVOQlFYZENMRU5CUVhoQ0xFbEJRVFpDTEVOQlFUZENMRU5CU25WQ096dEJRVTEyUWl4UlFVRkpMR0ZCUVdFc1NVRkJTeXhYUVVGS0xFTkJRV2RDTEVkQlFXaENMRU5CUVVRc1EwRkJkVUlzUTBGQmRrSXNRMEZCWWl4RFFVNXRRanM3UVVGUmRrSXNWVUZCVFN4SlFVRk9MRU5CUVZrc1ZVRkJReXhKUVVGakxFVkJRV1FzUjBGQmIwSXNTVUZCY2tJc1EwRkJXaXhEUVZKMVFqdEJRVk4yUWl4VlFVRk5MRWxCUVU0c1EwRkJXU3hWUVVGRExFbEJRV01zUlVGQlpDeEhRVUZ2UWl4SlFVRnlRaXhEUVVGYUxFTkJWSFZDTzBGQlZYWkNMRlZCUVUwc1NVRkJUaXhEUVVGWkxGVkJRVU1zU1VGQll5eERRVUZrTEVkQlFXMUNMRWxCUVhCQ0xFTkJRVm9zUTBGV2RVSTdRVUZYZGtJc1ZVRkJUU3hKUVVGT0xFTkJRVmtzWVVGQllTeEpRVUZpTEVOQlFWb3NRMEZZZFVJN08wRkJZWFpDTEZkQlFVOHNTMEZCVUN4RFFXSjFRanRIUVVGNlFqczdRVUZuUWtFc1UwRkJUeXhqUVVGUUxFTkJRWE5DTEVOQlFYUkNMRVZCUVhsQ08wRkJRM1pDTEZGQlFVa3NVVUZCVVN4RlFVRlNMRU5CUkcxQ096dEJRVWQyUWl4UlFVRkpMRTFCUVUwc1NVRkJTU3hYUVVGS0xFTkJRV2RDTEVOQlFXaENMRU5CUVU0c1EwRkliVUk3UVVGSmRrSXNVVUZCU3l4WlFVRktMRU5CUVdsQ0xFZEJRV3BDTEVOQlFVUXNRMEZCZDBJc1EwRkJlRUlzU1VGQk5rSXNRMEZCTjBJc1EwRktkVUk3TzBGQlRYWkNMRkZCUVVrc1kwRkJZeXhKUVVGTExGZEJRVW9zUTBGQlowSXNSMEZCYUVJc1EwRkJSQ3hEUVVGMVFpeERRVUYyUWl4RFFVRmtMRU5CVG0xQ08wRkJUM1pDTEZGQlFVa3NZMEZCWXl4SlFVRkxMRmRCUVVvc1EwRkJaMElzUjBGQmFFSXNRMEZCUkN4RFFVRjFRaXhEUVVGMlFpeERRVUZrTEVOQlVHMUNPenRCUVZOMlFpeFZRVUZOTEVsQlFVNHNRMEZCV1N4WFFVRkRMRWxCUVdVc1JVRkJaaXhIUVVGeFFpeEpRVUYwUWl4RFFVRmFMRU5CVkhWQ08wRkJWWFpDTEZWQlFVMHNTVUZCVGl4RFFVRlpMRmRCUVVNc1NVRkJaU3hGUVVGbUxFZEJRWEZDTEVsQlFYUkNMRU5CUVZvc1EwRldkVUk3UVVGWGRrSXNWVUZCVFN4SlFVRk9MRU5CUVZrc1YwRkJReXhKUVVGbExFTkJRV1lzUjBGQmIwSXNTVUZCY2tJc1EwRkJXaXhEUVZoMVFqdEJRVmwyUWl4VlFVRk5MRWxCUVU0c1EwRkJXU3hqUVVGakxFbEJRV1FzUTBGQldpeERRVnAxUWpzN1FVRmpka0lzVlVGQlRTeEpRVUZPTEVOQlFWa3NWMEZCUXl4SlFVRmxMRVZCUVdZc1IwRkJjVUlzU1VGQmRFSXNRMEZCV2l4RFFXUjFRanRCUVdWMlFpeFZRVUZOTEVsQlFVNHNRMEZCV1N4WFFVRkRMRWxCUVdVc1JVRkJaaXhIUVVGeFFpeEpRVUYwUWl4RFFVRmFMRU5CWm5WQ08wRkJaMEoyUWl4VlFVRk5MRWxCUVU0c1EwRkJXU3hYUVVGRExFbEJRV1VzUTBGQlppeEhRVUZ2UWl4SlFVRnlRaXhEUVVGYUxFTkJhRUoxUWp0QlFXbENka0lzVlVGQlRTeEpRVUZPTEVOQlFWa3NZMEZCWXl4SlFVRmtMRU5CUVZvc1EwRnFRblZDT3p0QlFXMUNka0lzVjBGQlR5eExRVUZRTEVOQmJrSjFRanRIUVVGNlFqdERRVE5TUmpzN1FVRnJWRUVzWlVGQlpTeFRRVUZtSWl3aVptbHNaU0k2SW14cFlpOWpiM0psTDJKcGRGOXpkSEpwYm1jdWFuTWlMQ0p6YjNWeVkyVnpRMjl1ZEdWdWRDSTZXeUpqYkdGemN5QkNhWFJUZEhKcGJtY2dlMXh1SUNCamIyNXpkSEoxWTNSdmNpZ3VMaTVoY21kektYdGNiaUFnSUNCMGFHbHpMbkpoZDE5MllXeDFaU0E5SUdaMWJtTjBhVzl1S0NsN1hHNGdJQ0FnSUNCeVpYUjFjbTRnVDJKcVpXTjBMbVp5WldWNlpTaGhjbWR6S1R0Y2JpQWdJQ0I5TzF4dVhHNGdJQ0FnZEdocGN5NTJZV3gxWlNBOUlFOWlhbVZqZEM1bWNtVmxlbVVvZEdocGN5NXdjbTlqWlhOektHRnlaM01wS1R0Y2JpQWdJQ0IwYUdsekxteGxibWQwYUNBOUlIUm9hWE11ZG1Gc2RXVXViR1Z1WjNSb08xeHVJQ0FnSUhSb2FYTXVZbWwwWDNOcGVtVWdQU0IwYUdsekxuSmhkMTkyWVd4MVpTZ3BMbkpsWkhWalpTZ29jSEpsZGl3Z1kzVnljbVZ1ZENrZ1BUNGdjSEpsZGlBcklHTjFjbkpsYm5RdWMybDZaU2s3WEc0Z0lDQWdkR2hwY3k1aWVYUmxYM05wZW1VZ1BTQW9kR2hwY3k1aWFYUmZjMmw2WlNBdklEZ3BJQ3NnS0hSb2FYTXVZbWwwWDNOcGVtVWdKU0E0SUQ0Z01DQS9JREVnT2lBd0tUdGNiaUFnZlZ4dVhHNGdJR2RsZENocGJtUmxlQ2w3WEc0Z0lDQWdjbVYwZFhKdUlIUm9hWE11ZG1Gc2RXVmJhVzVrWlhoZE8xeHVJQ0I5WEc1Y2JpQWdZMjkxYm5Rb0tYdGNiaUFnSUNCeVpYUjFjbTRnZEdocGN5NTJZV3gxWlM1c1pXNW5kR2c3WEc0Z0lIMWNibHh1SUNCYlUzbHRZbTlzTG1sMFpYSmhkRzl5WFNncElIdGNiaUFnSUNCeVpYUjFjbTRnZEdocGN5NTJZV3gxWlZ0VGVXMWliMnd1YVhSbGNtRjBiM0pkS0NrN1hHNGdJSDFjYmx4dUlDQjBiMU4wY21sdVp5Z3BlMXh1SUNBZ0lIWmhjaUJwTENCeklEMGdYQ0pjSWp0Y2JpQWdJQ0JtYjNJZ0tHa2dQU0F3T3lCcElEd2dkR2hwY3k1amIzVnVkQ2dwT3lCcEt5c3BJSHRjYmlBZ0lDQWdJR2xtSUNoeklDRTlQU0JjSWx3aUtTQjdYRzRnSUNBZ0lDQWdJSE1nS3owZ1hDSXNJRndpTzF4dUlDQWdJQ0FnZlZ4dUlDQWdJQ0FnY3lBclBTQjBhR2x6VzJsZExuUnZVM1J5YVc1bktDazdYRzRnSUNBZ2ZWeHVYRzRnSUNBZ2NtVjBkWEp1SUZ3aVBEeGNJaUFySUhNZ0t5QmNJajQrWENJN1hHNGdJSDFjYmx4dUlDQndjbTlqWlhOektDbDdYRzRnSUNBZ2JHVjBJSEJ5YjJObGMzTmxaRjkyWVd4MVpYTWdQU0JiWFR0Y2JseHVJQ0FnSUhaaGNpQnBPMXh1SUNBZ0lHWnZjaUFvYVNBOUlEQTdJR2tnUENCMGFHbHpMbkpoZDE5MllXeDFaU2dwTG14bGJtZDBhRHNnYVNzcktTQjdYRzRnSUNBZ0lDQnNaWFFnY0hKdlkyVnpjMlZrWDNaaGJIVmxJRDBnZEdocGMxc25jSEp2WTJWemMxOG5JQ3NnZEdocGN5NXlZWGRmZG1Gc2RXVW9LVnRwWFM1MGVYQmxYU2gwYUdsekxuSmhkMTkyWVd4MVpTZ3BXMmxkS1R0Y2JseHVJQ0FnSUNBZ1ptOXlLR3hsZENCaGRIUnlJRzltSUhSb2FYTXVjbUYzWDNaaGJIVmxLQ2xiYVYwdVlYUjBjbWxpZFhSbGN5bDdYRzRnSUNBZ0lDQWdJSEJ5YjJObGMzTmxaRjkyWVd4MVpTQTlJSFJvYVhOYkozQnliMk5sYzNOZkp5QXJJR0YwZEhKZEtIQnliMk5sYzNObFpGOTJZV3gxWlNrN1hHNGdJQ0FnSUNCOVhHNWNiaUFnSUNBZ0lIQnliMk5sYzNObFpGOTJZV3gxWlhNZ1BTQndjbTlqWlhOelpXUmZkbUZzZFdWekxtTnZibU5oZENod2NtOWpaWE56WldSZmRtRnNkV1VwTzF4dUlDQWdJSDFjYmx4dUlDQWdJSEpsZEhWeWJpQndjbTlqWlhOelpXUmZkbUZzZFdWek8xeHVJQ0I5WEc1Y2JpQWdjSEp2WTJWemMxOXBiblJsWjJWeUtIWmhiSFZsS1h0Y2JpQWdJQ0J5WlhSMWNtNGdkbUZzZFdVdWRtRnNkV1U3WEc0Z0lIMWNibHh1SUNCd2NtOWpaWE56WDJac2IyRjBLSFpoYkhWbEtYdGNiaUFnSUNCcFppaDJZV3gxWlM1emFYcGxJRDA5UFNBMk5DbDdYRzRnSUNBZ0lDQnlaWFIxY200Z1FtbDBVM1J5YVc1bkxtWnNiMkYwTmpSVWIwSjVkR1Z6S0haaGJIVmxMblpoYkhWbEtUdGNiaUFnSUNCOVpXeHpaU0JwWmloMllXeDFaUzV6YVhwbElEMDlQU0F6TWlsN1hHNGdJQ0FnSUNCeVpYUjFjbTRnUW1sMFUzUnlhVzVuTG1ac2IyRjBNekpVYjBKNWRHVnpLSFpoYkhWbExuWmhiSFZsS1R0Y2JpQWdJQ0I5WEc1Y2JpQWdJQ0IwYUhKdmR5QnVaWGNnUlhKeWIzSW9KMGx1ZG1Gc2FXUWdjMmw2WlNCbWIzSWdabXh2WVhRbktUdGNiaUFnZlZ4dVhHNGdJSEJ5YjJObGMzTmZZbWwwYzNSeWFXNW5LSFpoYkhWbEtYdGNiaUFnSUNCeVpYUjFjbTRnZG1Gc2RXVXVkbUZzZFdVdWRtRnNkV1U3WEc0Z0lIMWNibHh1SUNCd2NtOWpaWE56WDJKcGJtRnllU2gyWVd4MVpTbDdYRzRnSUNBZ2NtVjBkWEp1SUVKcGRGTjBjbWx1Wnk1MGIxVlVSamhCY25KaGVTaDJZV3gxWlM1MllXeDFaU2s3WEc0Z0lIMWNibHh1SUNCd2NtOWpaWE56WDNWMFpqZ29kbUZzZFdVcGUxeHVJQ0FnSUhKbGRIVnliaUJDYVhSVGRISnBibWN1ZEc5VlZFWTRRWEp5WVhrb2RtRnNkV1V1ZG1Gc2RXVXBPMXh1SUNCOVhHNWNiaUFnY0hKdlkyVnpjMTkxZEdZeE5paDJZV3gxWlNsN1hHNGdJQ0FnY21WMGRYSnVJRUpwZEZOMGNtbHVaeTUwYjFWVVJqRTJRWEp5WVhrb2RtRnNkV1V1ZG1Gc2RXVXBPMXh1SUNCOVhHNWNiaUFnY0hKdlkyVnpjMTkxZEdZek1paDJZV3gxWlNsN1hHNGdJQ0FnY21WMGRYSnVJRUpwZEZOMGNtbHVaeTUwYjFWVVJqTXlRWEp5WVhrb2RtRnNkV1V1ZG1Gc2RXVXBPMXh1SUNCOVhHNWNiaUFnY0hKdlkyVnpjMTl6YVdkdVpXUW9kbUZzZFdVcGUxeHVJQ0FnSUhKbGRIVnliaUFvYm1WM0lGVnBiblE0UVhKeVlYa29XM1poYkhWbFhTa3BXekJkTzF4dUlDQjlYRzVjYmlBZ2NISnZZMlZ6YzE5MWJuTnBaMjVsWkNoMllXeDFaU2w3WEc0Z0lDQWdjbVYwZFhKdUlIWmhiSFZsTzF4dUlDQjlYRzVjYmlBZ2NISnZZMlZ6YzE5dVlYUnBkbVVvZG1Gc2RXVXBlMXh1SUNBZ0lISmxkSFZ5YmlCMllXeDFaVHRjYmlBZ2ZWeHVYRzRnSUhCeWIyTmxjM05mWW1sbktIWmhiSFZsS1h0Y2JpQWdJQ0J5WlhSMWNtNGdkbUZzZFdVN1hHNGdJSDFjYmx4dUlDQndjbTlqWlhOelgyeHBkSFJzWlNoMllXeDFaU2w3WEc0Z0lDQWdjbVYwZFhKdUlIWmhiSFZsTG5KbGRtVnljMlVvS1R0Y2JpQWdmVnh1WEc0Z0lIQnliMk5sYzNOZmMybDZaU2gyWVd4MVpTbDdYRzRnSUNBZ2NtVjBkWEp1SUhaaGJIVmxPMXh1SUNCOVhHNWNiaUFnY0hKdlkyVnpjMTkxYm1sMEtIWmhiSFZsS1h0Y2JpQWdJQ0J5WlhSMWNtNGdkbUZzZFdVN1hHNGdJSDFjYmx4dUlDQnpkR0YwYVdNZ2FXNTBaV2RsY2loMllXeDFaU2w3WEc0Z0lDQWdjbVYwZFhKdUlFSnBkRk4wY21sdVp5NTNjbUZ3S0haaGJIVmxMQ0I3SUNkMGVYQmxKem9nSjJsdWRHVm5aWEluTENBbmRXNXBkQ2M2SURFc0lDZHphWHBsSnpvZ09DQjlLVHRjYmlBZ2ZWeHVYRzRnSUhOMFlYUnBZeUJtYkc5aGRDaDJZV3gxWlNsN1hHNGdJQ0FnY21WMGRYSnVJRUpwZEZOMGNtbHVaeTUzY21Gd0tIWmhiSFZsTENCN0lDZDBlWEJsSnpvZ0oyWnNiMkYwSnl3Z0ozVnVhWFFuT2lBeExDQW5jMmw2WlNjNklEWTBJSDBwTzF4dUlDQjlYRzVjYmlBZ2MzUmhkR2xqSUdKcGRITjBjbWx1WnloMllXeDFaU2w3WEc0Z0lDQWdjbVYwZFhKdUlFSnBkRk4wY21sdVp5NTNjbUZ3S0haaGJIVmxMQ0I3SUNkMGVYQmxKem9nSjJKcGRITjBjbWx1Wnljc0lDZDFibWwwSnpvZ01Td2dKM05wZW1Vbk9pQjJZV3gxWlM1aWFYUmZjMmw2WlNCOUtUdGNiaUFnZlZ4dVhHNGdJSE4wWVhScFl5QmlhWFJ6S0haaGJIVmxLWHRjYmlBZ0lDQnlaWFIxY200Z1FtbDBVM1J5YVc1bkxtSnBkSE4wY21sdVp5aDJZV3gxWlNrN1hHNGdJSDFjYmx4dUlDQnpkR0YwYVdNZ1ltbHVZWEo1S0haaGJIVmxLWHRjYmlBZ0lDQnlaWFIxY200Z1FtbDBVM1J5YVc1bkxuZHlZWEFvZG1Gc2RXVXNJSHNnSjNSNWNHVW5PaUFuWW1sdVlYSjVKeXdnSjNWdWFYUW5PaUE0TENBbmMybDZaU2M2SUhaaGJIVmxMbXhsYm1kMGFDQjlLVHRjYmlBZ2ZWeHVYRzRnSUhOMFlYUnBZeUJpZVhSbGN5aDJZV3gxWlNsN1hHNGdJQ0FnY21WMGRYSnVJRUpwZEZOMGNtbHVaeTVpYVc1aGNua29kbUZzZFdVcE8xeHVJQ0I5WEc1Y2JpQWdjM1JoZEdsaklIVjBaamdvZG1Gc2RXVXBlMXh1SUNBZ0lISmxkSFZ5YmlCQ2FYUlRkSEpwYm1jdWQzSmhjQ2gyWVd4MVpTd2dleUFuZEhsd1pTYzZJQ2QxZEdZNEp5QjlLVHRjYmlBZ2ZWeHVYRzRnSUhOMFlYUnBZeUIxZEdZeE5paDJZV3gxWlNsN1hHNGdJQ0FnY21WMGRYSnVJRUpwZEZOMGNtbHVaeTUzY21Gd0tIWmhiSFZsTENCN0lDZDBlWEJsSnpvZ0ozVjBaakUySnlCOUtUdGNiaUFnZlZ4dVhHNGdJSE4wWVhScFl5QjFkR1l6TWloMllXeDFaU2w3WEc0Z0lDQWdjbVYwZFhKdUlFSnBkRk4wY21sdVp5NTNjbUZ3S0haaGJIVmxMQ0I3SUNkMGVYQmxKem9nSjNWMFpqTXlKeUI5S1R0Y2JpQWdmVnh1WEc0Z0lITjBZWFJwWXlCemFXZHVaV1FvZG1Gc2RXVXBlMXh1SUNBZ0lISmxkSFZ5YmlCQ2FYUlRkSEpwYm1jdWQzSmhjQ2gyWVd4MVpTd2dlMzBzSUNkemFXZHVaV1FuS1R0Y2JpQWdmVnh1WEc0Z0lITjBZWFJwWXlCMWJuTnBaMjVsWkNoMllXeDFaU2w3WEc0Z0lDQWdjbVYwZFhKdUlFSnBkRk4wY21sdVp5NTNjbUZ3S0haaGJIVmxMQ0I3ZlN3Z0ozVnVjMmxuYm1Wa0p5azdYRzRnSUgxY2JseHVJQ0J6ZEdGMGFXTWdibUYwYVhabEtIWmhiSFZsS1h0Y2JpQWdJQ0J5WlhSMWNtNGdRbWwwVTNSeWFXNW5MbmR5WVhBb2RtRnNkV1VzSUh0OUxDQW5ibUYwYVhabEp5azdYRzRnSUgxY2JseHVJQ0J6ZEdGMGFXTWdZbWxuS0haaGJIVmxLWHRjYmlBZ0lDQnlaWFIxY200Z1FtbDBVM1J5YVc1bkxuZHlZWEFvZG1Gc2RXVXNJSHQ5TENBblltbG5KeWs3WEc0Z0lIMWNibHh1SUNCemRHRjBhV01nYkdsMGRHeGxLSFpoYkhWbEtYdGNiaUFnSUNCeVpYUjFjbTRnUW1sMFUzUnlhVzVuTG5keVlYQW9kbUZzZFdVc0lIdDlMQ0FuYkdsMGRHeGxKeWs3WEc0Z0lIMWNibHh1SUNCemRHRjBhV01nYzJsNlpTaDJZV3gxWlN3Z1kyOTFiblFwZTF4dUlDQWdJSEpsZEhWeWJpQkNhWFJUZEhKcGJtY3VkM0poY0NoMllXeDFaU3dnZXlkemFYcGxKem9nWTI5MWJuUjlLVHRjYmlBZ2ZWeHVYRzRnSUhOMFlYUnBZeUIxYm1sMEtIWmhiSFZsTENCamIzVnVkQ2w3WEc0Z0lDQWdjbVYwZFhKdUlFSnBkRk4wY21sdVp5NTNjbUZ3S0haaGJIVmxMQ0I3SjNWdWFYUW5PaUJqYjNWdWRIMHBPMXh1SUNCOVhHNWNiaUFnYzNSaGRHbGpJSGR5WVhBb2RtRnNkV1VzSUc5d2RDd2dibVYzWDJGMGRISnBZblYwWlNBOUlHNTFiR3dwZTF4dUlDQWdJR3hsZENCMGFHVmZkbUZzZFdVZ1BTQjJZV3gxWlR0Y2JseHVJQ0FnSUdsbUtDRW9kbUZzZFdVZ2FXNXpkR0Z1WTJWdlppQlBZbXBsWTNRcEtYdGNiaUFnSUNBZ0lIUm9aVjkyWVd4MVpTQTlJSHNuZG1Gc2RXVW5PaUIyWVd4MVpTd2dKMkYwZEhKcFluVjBaWE1uT2lCYlhYMDdYRzRnSUNBZ2ZWeHVYRzRnSUNBZ2RHaGxYM1poYkhWbElEMGdUMkpxWldOMExtRnpjMmxuYmloMGFHVmZkbUZzZFdVc0lHOXdkQ2s3WEc1Y2JpQWdJQ0JwWmlodVpYZGZZWFIwY21saWRYUmxLWHRjYmlBZ0lDQWdJSFJvWlY5MllXeDFaUzVoZEhSeWFXSjFkR1Z6TG5CMWMyZ29ibVYzWDJGMGRISnBZblYwWlNrN1hHNGdJQ0FnZlZ4dVhHNWNiaUFnSUNCeVpYUjFjbTRnZEdobFgzWmhiSFZsTzF4dUlDQjlYRzVjYmlBZ2MzUmhkR2xqSUhSdlZWUkdPRUZ5Y21GNUtITjBjaWtnZTF4dUlDQWdJSFpoY2lCMWRHWTRJRDBnVzEwN1hHNGdJQ0FnWm05eUlDaDJZWElnYVNBOUlEQTdJR2tnUENCemRISXViR1Z1WjNSb095QnBLeXNwSUh0Y2JpQWdJQ0FnSUhaaGNpQmphR0Z5WTI5a1pTQTlJSE4wY2k1amFHRnlRMjlrWlVGMEtHa3BPMXh1SUNBZ0lDQWdhV1lnS0dOb1lYSmpiMlJsSUR3Z01IZzRNQ2w3WEc0Z0lDQWdJQ0FnSUhWMFpqZ3VjSFZ6YUNoamFHRnlZMjlrWlNrN1hHNGdJQ0FnSUNCOVhHNGdJQ0FnSUNCbGJITmxJR2xtSUNoamFHRnlZMjlrWlNBOElEQjRPREF3S1NCN1hHNGdJQ0FnSUNBZ0lIVjBaamd1Y0hWemFDZ3dlR013SUh3Z0tHTm9ZWEpqYjJSbElENCtJRFlwTEZ4dUlDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ01IZzRNQ0I4SUNoamFHRnlZMjlrWlNBbUlEQjRNMllwS1R0Y2JpQWdJQ0FnSUgxY2JpQWdJQ0FnSUdWc2MyVWdhV1lnS0dOb1lYSmpiMlJsSUR3Z01IaGtPREF3SUh4OElHTm9ZWEpqYjJSbElENDlJREI0WlRBd01Da2dlMXh1SUNBZ0lDQWdJQ0IxZEdZNExuQjFjMmdvTUhobE1DQjhJQ2hqYUdGeVkyOWtaU0ErUGlBeE1pa3NYRzRnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0F3ZURnd0lId2dLQ2hqYUdGeVkyOWtaU0ErUGlBMktTQW1JREI0TTJZcExGeHVJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdNSGc0TUNCOElDaGphR0Z5WTI5a1pTQW1JREI0TTJZcEtUdGNiaUFnSUNBZ0lIMWNiaUFnSUNBZ0lDOHZJSE4xY25KdloyRjBaU0J3WVdseVhHNGdJQ0FnSUNCbGJITmxJSHRjYmlBZ0lDQWdJQ0FnYVNzck8xeHVJQ0FnSUNBZ0lDQXZMeUJWVkVZdE1UWWdaVzVqYjJSbGN5QXdlREV3TURBd0xUQjRNVEJHUmtaR0lHSjVYRzRnSUNBZ0lDQWdJQzh2SUhOMVluUnlZV04wYVc1bklEQjRNVEF3TURBZ1lXNWtJSE53YkdsMGRHbHVaeUIwYUdWY2JpQWdJQ0FnSUNBZ0x5OGdNakFnWW1sMGN5QnZaaUF3ZURBdE1IaEdSa1pHUmlCcGJuUnZJSFIzYnlCb1lXeDJaWE5jYmlBZ0lDQWdJQ0FnWTJoaGNtTnZaR1VnUFNBd2VERXdNREF3SUNzZ0tDZ29ZMmhoY21OdlpHVWdKaUF3ZURObVppa2dQRHdnTVRBcFhHNGdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQjhJQ2h6ZEhJdVkyaGhja052WkdWQmRDaHBLU0FtSURCNE0yWm1LU2s3WEc0Z0lDQWdJQ0FnSUhWMFpqZ3VjSFZ6YUNnd2VHWXdJSHdnS0dOb1lYSmpiMlJsSUQ0K0lERTRLU3hjYmlBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSURCNE9EQWdmQ0FvS0dOb1lYSmpiMlJsSUQ0K0lERXlLU0FtSURCNE0yWXBMRnh1SUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnTUhnNE1DQjhJQ2dvWTJoaGNtTnZaR1VnUGo0Z05pa2dKaUF3ZURObUtTeGNiaUFnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJREI0T0RBZ2ZDQW9ZMmhoY21OdlpHVWdKaUF3ZURObUtTazdYRzRnSUNBZ0lDQjlYRzRnSUNBZ2ZWeHVJQ0FnSUhKbGRIVnliaUIxZEdZNE8xeHVJQ0I5WEc1Y2JpQWdjM1JoZEdsaklIUnZWVlJHTVRaQmNuSmhlU2h6ZEhJcElIdGNiaUFnSUNCMllYSWdkWFJtTVRZZ1BTQmJYVHRjYmlBZ0lDQm1iM0lnS0haaGNpQnBJRDBnTURzZ2FTQThJSE4wY2k1c1pXNW5kR2c3SUdrckt5a2dlMXh1SUNBZ0lDQWdkbUZ5SUdOdlpHVlFiMmx1ZENBOUlITjBjaTVqYjJSbFVHOXBiblJCZENocEtUdGNibHh1SUNBZ0lDQWdhV1lvWTI5a1pWQnZhVzUwSUR3OUlESTFOU2w3WEc0Z0lDQWdJQ0FnSUhWMFpqRTJMbkIxYzJnb01DazdYRzRnSUNBZ0lDQWdJSFYwWmpFMkxuQjFjMmdvWTI5a1pWQnZhVzUwS1R0Y2JpQWdJQ0FnSUgxbGJITmxlMXh1SUNBZ0lDQWdJQ0IxZEdZeE5pNXdkWE5vS0Nnb1kyOWtaVkJ2YVc1MElENCtJRGdwSUNZZ01IaEdSaWtwTzF4dUlDQWdJQ0FnSUNCMWRHWXhOaTV3ZFhOb0tDaGpiMlJsVUc5cGJuUWdKaUF3ZUVaR0tTazdYRzRnSUNBZ0lDQjlYRzRnSUNBZ2ZWeHVJQ0FnSUhKbGRIVnliaUIxZEdZeE5qdGNiaUFnZlZ4dVhHNWNiaUFnYzNSaGRHbGpJSFJ2VlZSR016SkJjbkpoZVNoemRISXBJSHRjYmlBZ0lDQjJZWElnZFhSbU16SWdQU0JiWFR0Y2JpQWdJQ0JtYjNJZ0tIWmhjaUJwSUQwZ01Ec2dhU0E4SUhOMGNpNXNaVzVuZEdnN0lHa3JLeWtnZTF4dUlDQWdJQ0FnZG1GeUlHTnZaR1ZRYjJsdWRDQTlJSE4wY2k1amIyUmxVRzlwYm5SQmRDaHBLVHRjYmx4dUlDQWdJQ0FnYVdZb1kyOWtaVkJ2YVc1MElEdzlJREkxTlNsN1hHNGdJQ0FnSUNBZ0lIVjBaak15TG5CMWMyZ29NQ2s3WEc0Z0lDQWdJQ0FnSUhWMFpqTXlMbkIxYzJnb01DazdYRzRnSUNBZ0lDQWdJSFYwWmpNeUxuQjFjMmdvTUNrN1hHNGdJQ0FnSUNBZ0lIVjBaak15TG5CMWMyZ29ZMjlrWlZCdmFXNTBLVHRjYmlBZ0lDQWdJSDFsYkhObGUxeHVJQ0FnSUNBZ0lDQjFkR1l6TWk1d2RYTm9LREFwTzF4dUlDQWdJQ0FnSUNCMWRHWXpNaTV3ZFhOb0tEQXBPMXh1SUNBZ0lDQWdJQ0IxZEdZek1pNXdkWE5vS0Nnb1kyOWtaVkJ2YVc1MElENCtJRGdwSUNZZ01IaEdSaWtwTzF4dUlDQWdJQ0FnSUNCMWRHWXpNaTV3ZFhOb0tDaGpiMlJsVUc5cGJuUWdKaUF3ZUVaR0tTazdYRzRnSUNBZ0lDQjlYRzRnSUNBZ2ZWeHVJQ0FnSUhKbGRIVnliaUIxZEdZek1qdGNiaUFnZlZ4dVhHNGdJQzh2YUhSMGNEb3ZMM04wWVdOcmIzWmxjbVpzYjNjdVkyOXRMM0YxWlhOMGFXOXVjeTh5TURBek5Ea3pMMnBoZG1GelkzSnBjSFF0Wm14dllYUXRabkp2YlMxMGJ5MWlhWFJ6WEc0Z0lITjBZWFJwWXlCbWJHOWhkRE15Vkc5Q2VYUmxjeWhtS1NCN1hHNGdJQ0FnZG1GeUlHSjVkR1Z6SUQwZ1cxMDdYRzVjYmlBZ0lDQjJZWElnWW5WbUlEMGdibVYzSUVGeWNtRjVRblZtWm1WeUtEUXBPMXh1SUNBZ0lDaHVaWGNnUm14dllYUXpNa0Z5Y21GNUtHSjFaaWtwV3pCZElEMGdaanRjYmx4dUlDQWdJR3hsZENCcGJuUldaWEp6YVc5dUlEMGdLRzVsZHlCVmFXNTBNekpCY25KaGVTaGlkV1lwS1Zzd1hUdGNibHh1SUNBZ0lHSjVkR1Z6TG5CMWMyZ29LQ2hwYm5SV1pYSnphVzl1SUQ0K0lESTBLU0FtSURCNFJrWXBLVHRjYmlBZ0lDQmllWFJsY3k1d2RYTm9LQ2dvYVc1MFZtVnljMmx2YmlBK1BpQXhOaWtnSmlBd2VFWkdLU2s3WEc0Z0lDQWdZbmwwWlhNdWNIVnphQ2dvS0dsdWRGWmxjbk5wYjI0Z1BqNGdPQ2tnSmlBd2VFWkdLU2s3WEc0Z0lDQWdZbmwwWlhNdWNIVnphQ2dvYVc1MFZtVnljMmx2YmlBbUlEQjRSa1lwS1R0Y2JseHVJQ0FnSUhKbGRIVnliaUJpZVhSbGN6dGNiaUFnZlZ4dVhHNGdJSE4wWVhScFl5Qm1iRzloZERZMFZHOUNlWFJsY3lobUtTQjdYRzRnSUNBZ2RtRnlJR0o1ZEdWeklEMGdXMTA3WEc1Y2JpQWdJQ0IyWVhJZ1luVm1JRDBnYm1WM0lFRnljbUY1UW5WbVptVnlLRGdwTzF4dUlDQWdJQ2h1WlhjZ1JteHZZWFEyTkVGeWNtRjVLR0oxWmlrcFd6QmRJRDBnWmp0Y2JseHVJQ0FnSUhaaGNpQnBiblJXWlhKemFXOXVNU0E5SUNodVpYY2dWV2x1ZERNeVFYSnlZWGtvWW5WbUtTbGJNRjA3WEc0Z0lDQWdkbUZ5SUdsdWRGWmxjbk5wYjI0eUlEMGdLRzVsZHlCVmFXNTBNekpCY25KaGVTaGlkV1lwS1ZzeFhUdGNibHh1SUNBZ0lHSjVkR1Z6TG5CMWMyZ29LQ2hwYm5SV1pYSnphVzl1TWlBK1BpQXlOQ2tnSmlBd2VFWkdLU2s3WEc0Z0lDQWdZbmwwWlhNdWNIVnphQ2dvS0dsdWRGWmxjbk5wYjI0eUlENCtJREUyS1NBbUlEQjRSa1lwS1R0Y2JpQWdJQ0JpZVhSbGN5NXdkWE5vS0Nnb2FXNTBWbVZ5YzJsdmJqSWdQajRnT0NrZ0ppQXdlRVpHS1NrN1hHNGdJQ0FnWW5sMFpYTXVjSFZ6YUNnb2FXNTBWbVZ5YzJsdmJqSWdKaUF3ZUVaR0tTazdYRzVjYmlBZ0lDQmllWFJsY3k1d2RYTm9LQ2dvYVc1MFZtVnljMmx2YmpFZ1BqNGdNalFwSUNZZ01IaEdSaWtwTzF4dUlDQWdJR0o1ZEdWekxuQjFjMmdvS0NocGJuUldaWEp6YVc5dU1TQStQaUF4TmlrZ0ppQXdlRVpHS1NrN1hHNGdJQ0FnWW5sMFpYTXVjSFZ6YUNnb0tHbHVkRlpsY25OcGIyNHhJRDQrSURncElDWWdNSGhHUmlrcE8xeHVJQ0FnSUdKNWRHVnpMbkIxYzJnb0tHbHVkRlpsY25OcGIyNHhJQ1lnTUhoR1Jpa3BPMXh1WEc0Z0lDQWdjbVYwZFhKdUlHSjVkR1Z6TzF4dUlDQjlYRzU5WEc1Y2JtVjRjRzl5ZENCa1pXWmhkV3gwSUVKcGRGTjBjbWx1Wnp0Y2JpSmRMQ0p6YjNWeVkyVlNiMjkwSWpvaUwzTnZkWEpqWlM4aWZRPT1cbiIsIlxuZXhwb3J0IGNsYXNzIFZhcmlhYmxlIHtcblxuICBjb25zdHJ1Y3RvcihuYW1lID0gbnVsbCkge1xuICAgIHRoaXMubmFtZSA9IG5hbWU7XG4gIH1cbn1cblxuZXhwb3J0IGNsYXNzIFdpbGRjYXJkIHtcbiAgY29uc3RydWN0b3IoKSB7fVxufVxuXG5leHBvcnQgY2xhc3MgU3RhcnRzV2l0aCB7XG5cbiAgY29uc3RydWN0b3IocHJlZml4KSB7XG4gICAgdGhpcy5wcmVmaXggPSBwcmVmaXg7XG4gIH1cbn1cblxuZXhwb3J0IGNsYXNzIENhcHR1cmUge1xuXG4gIGNvbnN0cnVjdG9yKHZhbHVlKSB7XG4gICAgdGhpcy52YWx1ZSA9IHZhbHVlO1xuICB9XG59XG5cbmV4cG9ydCBjbGFzcyBIZWFkVGFpbCB7XG5cbiAgY29uc3RydWN0b3IoaGVhZCA9IG51bGwsIHRhaWwgPSBudWxsKSB7XG4gICAgdGhpcy5oZWFkID0gaGVhZDtcbiAgICB0aGlzLnRhaWwgPSB0YWlsO1xuICB9XG59XG5cbmV4cG9ydCBjbGFzcyBUeXBlIHtcblxuICBjb25zdHJ1Y3Rvcih0eXBlLCBvYmpQYXR0ZXJuID0ge30pIHtcbiAgICB0aGlzLnR5cGUgPSB0eXBlO1xuICAgIHRoaXMub2JqUGF0dGVybiA9IG9ialBhdHRlcm47XG4gIH1cbn1cblxuZXhwb3J0IGNsYXNzIEJvdW5kIHtcblxuICBjb25zdHJ1Y3Rvcih2YWx1ZSkge1xuICAgIHRoaXMudmFsdWUgPSB2YWx1ZTtcbiAgfVxufVxuXG5leHBvcnQgZnVuY3Rpb24gdmFyaWFibGUobmFtZSA9IG51bGwpIHtcbiAgcmV0dXJuIG5ldyBWYXJpYWJsZShuYW1lKTtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIHdpbGRjYXJkKCkge1xuICByZXR1cm4gbmV3IFdpbGRjYXJkKCk7XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBzdGFydHNXaXRoKHByZWZpeCkge1xuICByZXR1cm4gbmV3IFN0YXJ0c1dpdGgocHJlZml4KTtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIGNhcHR1cmUodmFsdWUpIHtcbiAgcmV0dXJuIG5ldyBDYXB0dXJlKHZhbHVlKTtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIGhlYWRUYWlsKGhlYWQgPSBudWxsLCB0YWlsID0gbnVsbCkge1xuICByZXR1cm4gbmV3IEhlYWRUYWlsKGhlYWQsIHRhaWwpO1xufVxuXG5leHBvcnQgZnVuY3Rpb24gdHlwZSh0eXBlLCBvYmpQYXR0ZXJuID0ge30pIHtcbiAgcmV0dXJuIG5ldyBUeXBlKHR5cGUsIG9ialBhdHRlcm4pO1xufVxuXG5leHBvcnQgZnVuY3Rpb24gYm91bmQodmFsdWUpIHtcbiAgcmV0dXJuIG5ldyBCb3VuZCh2YWx1ZSk7XG59XG4vLyMgc291cmNlTWFwcGluZ1VSTD1kYXRhOmFwcGxpY2F0aW9uL2pzb247YmFzZTY0LGV5SjJaWEp6YVc5dUlqb3pMQ0p6YjNWeVkyVnpJanBiSW14cFlpOWpiM0psTDNCaGRIUmxjbTV6TDNSNWNHVnpMbXB6SWwwc0ltNWhiV1Z6SWpwYlhTd2liV0Z3Y0dsdVozTWlPaUk3UVVGRFFTeFBRVUZQTEUxQlFVMHNVVUZCVGl4RFFVRmxPenRCUVVkd1FpeGpRVUV3UWl4UFFVRkZMRWxCUVVZc1JVRkJVVHRCUVVOb1F5eFRRVUZMTEVsQlFVd3NSMEZCV1N4SlFVRmFMRU5CUkdkRE8wZEJRV3hETzBOQlNFczdPMEZCVVZBc1QwRkJUeXhOUVVGTkxGRkJRVTRzUTBGQlpUdEJRVU53UWl4blFrRkJZeXhGUVVGa08wTkJSRXM3TzBGQlMxQXNUMEZCVHl4TlFVRk5MRlZCUVU0c1EwRkJhVUk3TzBGQlIzUkNMR05CUVZrc1RVRkJXaXhGUVVFMFFqdEJRVU14UWl4VFFVRkxMRTFCUVV3c1IwRkJZeXhOUVVGa0xFTkJSREJDTzBkQlFUVkNPME5CU0VzN08wRkJVVkFzVDBGQlR5eE5RVUZOTEU5QlFVNHNRMEZCWXpzN1FVRkhia0lzWTBGQldTeExRVUZhTEVWQlFYZENPMEZCUTNSQ0xGTkJRVXNzUzBGQlRDeEhRVUZoTEV0QlFXSXNRMEZFYzBJN1IwRkJlRUk3UTBGSVN6czdRVUZSVUN4UFFVRlBMRTFCUVUwc1VVRkJUaXhEUVVGbE96dEJRVWx3UWl4alFVRnpRaXhQUVVGRkxFbEJRVVlzUlVGQmEwSXNUMEZCUlN4SlFVRkdMRVZCUVZFN1FVRkRPVU1zVTBGQlN5eEpRVUZNTEVkQlFWa3NTVUZCV2l4RFFVUTRRenRCUVVVNVF5eFRRVUZMTEVsQlFVd3NSMEZCV1N4SlFVRmFMRU5CUmpoRE8wZEJRV2hFTzBOQlNrczdPMEZCVlZBc1QwRkJUeXhOUVVGTkxFbEJRVTRzUTBGQlZ6czdRVUZKYUVJc1kwRkJXU3hKUVVGYUxFVkJRVEJETEdGQlFVVXNSVUZCUml4RlFVRk5PMEZCUXpsRExGTkJRVXNzU1VGQlRDeEhRVUZaTEVsQlFWb3NRMEZFT0VNN1FVRkZPVU1zVTBGQlN5eFZRVUZNTEVkQlFXdENMRlZCUVd4Q0xFTkJSamhETzBkQlFXaEVPME5CU2tzN08wRkJWVkFzVDBGQlR5eE5RVUZOTEV0QlFVNHNRMEZCV1RzN1FVRkhha0lzWTBGQldTeExRVUZhTEVWQlFYZENPMEZCUTNSQ0xGTkJRVXNzUzBGQlRDeEhRVUZoTEV0QlFXSXNRMEZFYzBJN1IwRkJlRUk3UTBGSVN6czdRVUZSVUN4UFFVRlBMRk5CUVZNc1VVRkJWQ3hEUVVGblF5eFBRVUZGTEVsQlFVWXNSVUZCYTBJN1FVRkRka1FzVTBGQlR5eEpRVUZKTEZGQlFVb3NRMEZCWVN4SlFVRmlMRU5CUVZBc1EwRkVkVVE3UTBGQmJFUTdPMEZCU1ZBc1QwRkJUeXhUUVVGVExGRkJRVlFzUjBGQk9FSTdRVUZEYmtNc1UwRkJUeXhKUVVGSkxGRkJRVW9zUlVGQlVDeERRVVJ0UXp0RFFVRTVRanM3UVVGSlVDeFBRVUZQTEZOQlFWTXNWVUZCVkN4RFFVRnZRaXhOUVVGd1FpeEZRVUZuUkR0QlFVTnlSQ3hUUVVGUExFbEJRVWtzVlVGQlNpeERRVUZsTEUxQlFXWXNRMEZCVUN4RFFVUnhSRHREUVVGb1JEczdRVUZKVUN4UFFVRlBMRk5CUVZNc1QwRkJWQ3hEUVVGcFFpeExRVUZxUWl4RlFVRnpRenRCUVVNelF5eFRRVUZQTEVsQlFVa3NUMEZCU2l4RFFVRlpMRXRCUVZvc1EwRkJVQ3hEUVVReVF6dERRVUYwUXpzN1FVRkpVQ3hQUVVGUExGTkJRVk1zVVVGQlZDeERRVUUwUWl4UFFVRkZMRWxCUVVZc1JVRkJhMElzVDBGQlJTeEpRVUZHTEVWQlFXdENPMEZCUTNKRkxGTkJRVThzU1VGQlNTeFJRVUZLTEVOQlFXRXNTVUZCWWl4RlFVRnRRaXhKUVVGdVFpeERRVUZRTEVOQlJIRkZPME5CUVdoRk96dEJRVWxRTEU5QlFVOHNVMEZCVXl4SlFVRlVMRU5CUVdNc1NVRkJaQ3hGUVVFMFF5eGhRVUZGTEVWQlFVWXNSVUZCV1R0QlFVTTNSQ3hUUVVGUExFbEJRVWtzU1VGQlNpeERRVUZUTEVsQlFWUXNSVUZCWlN4VlFVRm1MRU5CUVZBc1EwRkVOa1E3UTBGQmVFUTdPMEZCU1ZBc1QwRkJUeXhUUVVGVExFdEJRVlFzUTBGQlpTeExRVUZtTEVWQlFXdERPMEZCUTNaRExGTkJRVThzU1VGQlNTeExRVUZLTEVOQlFWVXNTMEZCVml4RFFVRlFMRU5CUkhWRE8wTkJRV3hESWl3aVptbHNaU0k2SW14cFlpOWpiM0psTDNCaGRIUmxjbTV6TDNSNWNHVnpMbXB6SWl3aWMyOTFjbU5sYzBOdmJuUmxiblFpT2xzaUx5b2dRR1pzYjNjZ0tpOWNibVY0Y0c5eWRDQmpiR0Z6Y3lCV1lYSnBZV0pzWlNCN1hHNGdJRzVoYldVNklEOXpkSEpwYm1jN1hHNWNiaUFnWTI5dWMzUnlkV04wYjNJb2JtRnRaVG9nUDNOMGNtbHVaeUE5SUc1MWJHd3BJSHRjYmlBZ0lDQjBhR2x6TG01aGJXVWdQU0J1WVcxbE8xeHVJQ0I5WEc1OVhHNWNibVY0Y0c5eWRDQmpiR0Z6Y3lCWGFXeGtZMkZ5WkNCN1hHNGdJR052Ym5OMGNuVmpkRzl5S0NrZ2UxeHVJQ0I5WEc1OVhHNWNibVY0Y0c5eWRDQmpiR0Z6Y3lCVGRHRnlkSE5YYVhSb0lIdGNiaUFnY0hKbFptbDRPaUJ6ZEhKcGJtYzdYRzVjYmlBZ1kyOXVjM1J5ZFdOMGIzSW9jSEpsWm1sNE9pQnpkSEpwYm1jcElIdGNiaUFnSUNCMGFHbHpMbkJ5WldacGVDQTlJSEJ5WldacGVEdGNiaUFnZlZ4dWZWeHVYRzVsZUhCdmNuUWdZMnhoYzNNZ1EyRndkSFZ5WlNCN1hHNGdJSFpoYkhWbE9pQmhibms3WEc1Y2JpQWdZMjl1YzNSeWRXTjBiM0lvZG1Gc2RXVTZJR0Z1ZVNrZ2UxeHVJQ0FnSUhSb2FYTXVkbUZzZFdVZ1BTQjJZV3gxWlR0Y2JpQWdmVnh1ZlZ4dVhHNWxlSEJ2Y25RZ1kyeGhjM01nU0dWaFpGUmhhV3dnZTF4dUlDQm9aV0ZrT2lCaGJuazdYRzRnSUhSaGFXdzZJR0Z1ZVR0Y2JseHVJQ0JqYjI1emRISjFZM1J2Y2lob1pXRmtPaUJoYm5rZ1BTQnVkV3hzTENCMFlXbHNPaUJoYm5rZ1BTQnVkV3hzS1NCN1hHNGdJQ0FnZEdocGN5NW9aV0ZrSUQwZ2FHVmhaRHRjYmlBZ0lDQjBhR2x6TG5SaGFXd2dQU0IwWVdsc08xeHVJQ0I5WEc1OVhHNWNibVY0Y0c5eWRDQmpiR0Z6Y3lCVWVYQmxJSHRjYmlBZ2RIbHdaVG9nWVc1NU8xeHVJQ0J2WW1wUVlYUjBaWEp1T2lCUFltcGxZM1E3WEc1Y2JpQWdZMjl1YzNSeWRXTjBiM0lvZEhsd1pUb2dZVzU1TENCdlltcFFZWFIwWlhKdU9pQlBZbXBsWTNRZ1BTQjdmU2tnZTF4dUlDQWdJSFJvYVhNdWRIbHdaU0E5SUhSNWNHVmNiaUFnSUNCMGFHbHpMbTlpYWxCaGRIUmxjbTRnUFNCdlltcFFZWFIwWlhKdVhHNGdJSDFjYm4xY2JseHVaWGh3YjNKMElHTnNZWE56SUVKdmRXNWtJSHRjYmlBZ2RtRnNkV1U2SUdGdWVUdGNibHh1SUNCamIyNXpkSEoxWTNSdmNpaDJZV3gxWlRvZ1lXNTVLU0I3WEc0Z0lDQWdkR2hwY3k1MllXeDFaU0E5SUhaaGJIVmxPMXh1SUNCOVhHNTlYRzVjYm1WNGNHOXlkQ0JtZFc1amRHbHZiaUIyWVhKcFlXSnNaU2h1WVcxbE9pQS9jM1J5YVc1bklEMGdiblZzYkNrNklGWmhjbWxoWW14bElIdGNiaUFnY21WMGRYSnVJRzVsZHlCV1lYSnBZV0pzWlNodVlXMWxLVHRjYm4xY2JseHVaWGh3YjNKMElHWjFibU4wYVc5dUlIZHBiR1JqWVhKa0tDazZJRmRwYkdSallYSmtJSHRjYmlBZ2NtVjBkWEp1SUc1bGR5QlhhV3hrWTJGeVpDZ3BPMXh1ZlZ4dVhHNWxlSEJ2Y25RZ1puVnVZM1JwYjI0Z2MzUmhjblJ6VjJsMGFDaHdjbVZtYVhnNklITjBjbWx1WnlrNklGTjBZWEowYzFkcGRHZ2dlMXh1SUNCeVpYUjFjbTRnYm1WM0lGTjBZWEowYzFkcGRHZ29jSEpsWm1sNEtUdGNibjFjYmx4dVpYaHdiM0owSUdaMWJtTjBhVzl1SUdOaGNIUjFjbVVvZG1Gc2RXVTZJR0Z1ZVNrNklFTmhjSFIxY21VZ2UxeHVJQ0J5WlhSMWNtNGdibVYzSUVOaGNIUjFjbVVvZG1Gc2RXVXBPMXh1ZlZ4dVhHNWxlSEJ2Y25RZ1puVnVZM1JwYjI0Z2FHVmhaRlJoYVd3b2FHVmhaRG9nWVc1NUlEMGdiblZzYkN3Z2RHRnBiRG9nWVc1NUlEMGdiblZzYkNrNklFaGxZV1JVWVdsc0lIdGNiaUFnY21WMGRYSnVJRzVsZHlCSVpXRmtWR0ZwYkNob1pXRmtMQ0IwWVdsc0tUdGNibjFjYmx4dVpYaHdiM0owSUdaMWJtTjBhVzl1SUhSNWNHVW9kSGx3WlRvZ1lXNTVMQ0J2WW1wUVlYUjBaWEp1T2lCUFltcGxZM1FnUFNCN2ZTazZJRlI1Y0dVZ2UxeHVJQ0J5WlhSMWNtNGdibVYzSUZSNWNHVW9kSGx3WlN3Z2IySnFVR0YwZEdWeWJpazdYRzU5WEc1Y2JtVjRjRzl5ZENCbWRXNWpkR2x2YmlCaWIzVnVaQ2gyWVd4MVpUb2dZVzU1S1RvZ1FtOTFibVFnZTF4dUlDQnlaWFIxY200Z2JtVjNJRUp2ZFc1a0tIWmhiSFZsS1R0Y2JuMWNiaUpkTENKemIzVnlZMlZTYjI5MElqb2lMM052ZFhKalpTOGlmUT09XG4iLCJcblxuaW1wb3J0IHsgVmFyaWFibGUsIFdpbGRjYXJkLCBIZWFkVGFpbCwgQ2FwdHVyZSwgVHlwZSwgU3RhcnRzV2l0aCwgQm91bmQgfSBmcm9tIFwiLi90eXBlc1wiO1xuXG5mdW5jdGlvbiBpc19udW1iZXIodmFsdWUpIHtcbiAgcmV0dXJuIHR5cGVvZiB2YWx1ZSA9PT0gJ251bWJlcic7XG59XG5cbmZ1bmN0aW9uIGlzX3N0cmluZyh2YWx1ZSkge1xuICByZXR1cm4gdHlwZW9mIHZhbHVlID09PSAnc3RyaW5nJztcbn1cblxuZnVuY3Rpb24gaXNfYm9vbGVhbih2YWx1ZSkge1xuICByZXR1cm4gdHlwZW9mIHZhbHVlID09PSAnYm9vbGVhbic7XG59XG5cbmZ1bmN0aW9uIGlzX3N5bWJvbCh2YWx1ZSkge1xuICByZXR1cm4gdHlwZW9mIHZhbHVlID09PSAnc3ltYm9sJztcbn1cblxuZnVuY3Rpb24gaXNfbnVsbCh2YWx1ZSkge1xuICByZXR1cm4gdmFsdWUgPT09IG51bGw7XG59XG5cbmZ1bmN0aW9uIGlzX3VuZGVmaW5lZCh2YWx1ZSkge1xuICByZXR1cm4gdHlwZW9mIHZhbHVlID09PSAndW5kZWZpbmVkJztcbn1cblxuZnVuY3Rpb24gaXNfZnVuY3Rpb24odmFsdWUpIHtcbiAgcmV0dXJuIE9iamVjdC5wcm90b3R5cGUudG9TdHJpbmcuY2FsbCh2YWx1ZSkgPT0gJ1tvYmplY3QgRnVuY3Rpb25dJztcbn1cblxuZnVuY3Rpb24gaXNfdmFyaWFibGUodmFsdWUpIHtcbiAgcmV0dXJuIHZhbHVlIGluc3RhbmNlb2YgVmFyaWFibGU7XG59XG5cbmZ1bmN0aW9uIGlzX3dpbGRjYXJkKHZhbHVlKSB7XG4gIHJldHVybiB2YWx1ZSBpbnN0YW5jZW9mIFdpbGRjYXJkO1xufVxuXG5mdW5jdGlvbiBpc19oZWFkVGFpbCh2YWx1ZSkge1xuICByZXR1cm4gdmFsdWUgaW5zdGFuY2VvZiBIZWFkVGFpbDtcbn1cblxuZnVuY3Rpb24gaXNfY2FwdHVyZSh2YWx1ZSkge1xuICByZXR1cm4gdmFsdWUgaW5zdGFuY2VvZiBDYXB0dXJlO1xufVxuXG5mdW5jdGlvbiBpc190eXBlKHZhbHVlKSB7XG4gIHJldHVybiB2YWx1ZSBpbnN0YW5jZW9mIFR5cGU7XG59XG5cbmZ1bmN0aW9uIGlzX3N0YXJ0c1dpdGgodmFsdWUpIHtcbiAgcmV0dXJuIHZhbHVlIGluc3RhbmNlb2YgU3RhcnRzV2l0aDtcbn1cblxuZnVuY3Rpb24gaXNfYm91bmQodmFsdWUpIHtcbiAgcmV0dXJuIHZhbHVlIGluc3RhbmNlb2YgQm91bmQ7XG59XG5cbmZ1bmN0aW9uIGlzX29iamVjdCh2YWx1ZSkge1xuICByZXR1cm4gdHlwZW9mIHZhbHVlID09PSAnb2JqZWN0Jztcbn1cblxuZnVuY3Rpb24gaXNfYXJyYXkodmFsdWUpIHtcbiAgcmV0dXJuIEFycmF5LmlzQXJyYXkodmFsdWUpO1xufVxuXG5leHBvcnQgZGVmYXVsdCB7XG4gIGlzX251bWJlcixcbiAgaXNfc3RyaW5nLFxuICBpc19ib29sZWFuLFxuICBpc19zeW1ib2wsXG4gIGlzX251bGwsXG4gIGlzX3VuZGVmaW5lZCxcbiAgaXNfZnVuY3Rpb24sXG4gIGlzX3ZhcmlhYmxlLFxuICBpc193aWxkY2FyZCxcbiAgaXNfaGVhZFRhaWwsXG4gIGlzX2NhcHR1cmUsXG4gIGlzX3R5cGUsXG4gIGlzX3N0YXJ0c1dpdGgsXG4gIGlzX2JvdW5kLFxuICBpc19vYmplY3QsXG4gIGlzX2FycmF5XG59O1xuLy8jIHNvdXJjZU1hcHBpbmdVUkw9ZGF0YTphcHBsaWNhdGlvbi9qc29uO2Jhc2U2NCxleUoyWlhKemFXOXVJam96TENKemIzVnlZMlZ6SWpwYklteHBZaTlqYjNKbEwzQmhkSFJsY201ekwyTm9aV05yY3k1cWN5SmRMQ0p1WVcxbGN5STZXMTBzSW0xaGNIQnBibWR6SWpvaU96dEJRVVZCTEZOQlFWTXNVVUZCVkN4RlFVRnRRaXhSUVVGdVFpeEZRVUUyUWl4UlFVRTNRaXhGUVVGMVF5eFBRVUYyUXl4RlFVRm5SQ3hKUVVGb1JDeEZRVUZ6UkN4VlFVRjBSQ3hGUVVGclJTeExRVUZzUlN4UlFVRXJSU3hUUVVFdlJUczdRVUZGUVN4VFFVRlRMRk5CUVZRc1EwRkJiVUlzUzBGQmJrSXNSVUZCZDBNN1FVRkRkRU1zVTBGQlR5eFBRVUZQTEV0QlFWQXNTMEZCYVVJc1VVRkJha0lzUTBGRUswSTdRMEZCZUVNN08wRkJTVUVzVTBGQlV5eFRRVUZVTEVOQlFXMUNMRXRCUVc1Q0xFVkJRWFZETzBGQlEzSkRMRk5CUVU4c1QwRkJUeXhMUVVGUUxFdEJRV2xDTEZGQlFXcENMRU5CUkRoQ08wTkJRWFpET3p0QlFVbEJMRk5CUVZNc1ZVRkJWQ3hEUVVGdlFpeExRVUZ3UWl4RlFVRjVRenRCUVVOMlF5eFRRVUZQTEU5QlFVOHNTMEZCVUN4TFFVRnBRaXhUUVVGcVFpeERRVVJuUXp0RFFVRjZRenM3UVVGSlFTeFRRVUZUTEZOQlFWUXNRMEZCYlVJc1MwRkJia0lzUlVGQmQwTTdRVUZEZEVNc1UwRkJUeXhQUVVGUExFdEJRVkFzUzBGQmFVSXNVVUZCYWtJc1EwRkVLMEk3UTBGQmVFTTdPMEZCU1VFc1UwRkJVeXhQUVVGVUxFTkJRV2xDTEV0QlFXcENMRVZCUVhORE8wRkJRM0JETEZOQlFVOHNWVUZCVlN4SlFVRldMRU5CUkRaQ08wTkJRWFJET3p0QlFVbEJMRk5CUVZNc1dVRkJWQ3hEUVVGelFpeExRVUYwUWl4RlFVRXlRenRCUVVONlF5eFRRVUZQTEU5QlFVOHNTMEZCVUN4TFFVRnBRaXhYUVVGcVFpeERRVVJyUXp0RFFVRXpRenM3UVVGSlFTeFRRVUZUTEZkQlFWUXNRMEZCY1VJc1MwRkJja0lzUlVGQk1FTTdRVUZEZUVNc1UwRkJUeXhQUVVGUExGTkJRVkFzUTBGQmFVSXNVVUZCYWtJc1EwRkJNRUlzU1VGQk1VSXNRMEZCSzBJc1MwRkJMMElzUzBGQmVVTXNiVUpCUVhwRExFTkJSR2xETzBOQlFURkRPenRCUVVsQkxGTkJRVk1zVjBGQlZDeERRVUZ4UWl4TFFVRnlRaXhGUVVFd1F6dEJRVU40UXl4VFFVRlBMR2xDUVVGcFFpeFJRVUZxUWl4RFFVUnBRenREUVVFeFF6czdRVUZKUVN4VFFVRlRMRmRCUVZRc1EwRkJjVUlzUzBGQmNrSXNSVUZCTUVNN1FVRkRlRU1zVTBGQlR5eHBRa0ZCYVVJc1VVRkJha0lzUTBGRWFVTTdRMEZCTVVNN08wRkJTVUVzVTBGQlV5eFhRVUZVTEVOQlFYRkNMRXRCUVhKQ0xFVkJRVEJETzBGQlEzaERMRk5CUVU4c2FVSkJRV2xDTEZGQlFXcENMRU5CUkdsRE8wTkJRVEZET3p0QlFVbEJMRk5CUVZNc1ZVRkJWQ3hEUVVGdlFpeExRVUZ3UWl4RlFVRjVRenRCUVVOMlF5eFRRVUZQTEdsQ1FVRnBRaXhQUVVGcVFpeERRVVJuUXp0RFFVRjZRenM3UVVGSlFTeFRRVUZUTEU5QlFWUXNRMEZCYVVJc1MwRkJha0lzUlVGQmMwTTdRVUZEY0VNc1UwRkJUeXhwUWtGQmFVSXNTVUZCYWtJc1EwRkVOa0k3UTBGQmRFTTdPMEZCU1VFc1UwRkJVeXhoUVVGVUxFTkJRWFZDTEV0QlFYWkNMRVZCUVRSRE8wRkJRekZETEZOQlFVOHNhVUpCUVdsQ0xGVkJRV3BDTEVOQlJHMURPME5CUVRWRE96dEJRVWxCTEZOQlFWTXNVVUZCVkN4RFFVRnJRaXhMUVVGc1FpeEZRVUYxUXp0QlFVTnlReXhUUVVGUExHbENRVUZwUWl4TFFVRnFRaXhEUVVRNFFqdERRVUYyUXpzN1FVRkpRU3hUUVVGVExGTkJRVlFzUTBGQmJVSXNTMEZCYmtJc1JVRkJkME03UVVGRGRFTXNVMEZCVHl4UFFVRlBMRXRCUVZBc1MwRkJhVUlzVVVGQmFrSXNRMEZFSzBJN1EwRkJlRU03TzBGQlNVRXNVMEZCVXl4UlFVRlVMRU5CUVd0Q0xFdEJRV3hDTEVWQlFYVkRPMEZCUTNKRExGTkJRVThzVFVGQlRTeFBRVUZPTEVOQlFXTXNTMEZCWkN4RFFVRlFMRU5CUkhGRE8wTkJRWFpET3p0QlFVbEJMR1ZCUVdVN1FVRkRZaXhYUVVSaE8wRkJSV0lzVjBGR1lUdEJRVWRpTEZsQlNHRTdRVUZKWWl4WFFVcGhPMEZCUzJJc1UwRk1ZVHRCUVUxaUxHTkJUbUU3UVVGUFlpeGhRVkJoTzBGQlVXSXNZVUZTWVR0QlFWTmlMR0ZCVkdFN1FVRlZZaXhoUVZaaE8wRkJWMklzV1VGWVlUdEJRVmxpTEZOQldtRTdRVUZoWWl4bFFXSmhPMEZCWTJJc1ZVRmtZVHRCUVdWaUxGZEJabUU3UVVGblFtSXNWVUZvUW1FN1EwRkJaaUlzSW1acGJHVWlPaUpzYVdJdlkyOXlaUzl3WVhSMFpYSnVjeTlqYUdWamEzTXVhbk1pTENKemIzVnlZMlZ6UTI5dWRHVnVkQ0k2V3lJdktpQkFabXh2ZHlBcUwxeHVYRzVwYlhCdmNuUWdleUJXWVhKcFlXSnNaU3dnVjJsc1pHTmhjbVFzSUVobFlXUlVZV2xzTENCRFlYQjBkWEpsTENCVWVYQmxMQ0JUZEdGeWRITlhhWFJvTENCQ2IzVnVaQ0I5SUdaeWIyMGdYQ0l1TDNSNWNHVnpYQ0k3WEc1Y2JtWjFibU4wYVc5dUlHbHpYMjUxYldKbGNpaDJZV3gxWlRvZ1lXNTVLVG9nWW05dmJHVmhiaUI3WEc0Z0lISmxkSFZ5YmlCMGVYQmxiMllnZG1Gc2RXVWdQVDA5SUNkdWRXMWlaWEluTzF4dWZWeHVYRzVtZFc1amRHbHZiaUJwYzE5emRISnBibWNvZG1Gc2RXVTZJR0Z1ZVNrNklHSnZiMnhsWVc1N1hHNGdJSEpsZEhWeWJpQjBlWEJsYjJZZ2RtRnNkV1VnUFQwOUlDZHpkSEpwYm1jbk8xeHVmVnh1WEc1bWRXNWpkR2x2YmlCcGMxOWliMjlzWldGdUtIWmhiSFZsT2lCaGJua3BPaUJpYjI5c1pXRnVJSHRjYmlBZ2NtVjBkWEp1SUhSNWNHVnZaaUIyWVd4MVpTQTlQVDBnSjJKdmIyeGxZVzRuTzF4dWZWeHVYRzVtZFc1amRHbHZiaUJwYzE5emVXMWliMndvZG1Gc2RXVTZJR0Z1ZVNrNklHSnZiMnhsWVc0Z2UxeHVJQ0J5WlhSMWNtNGdkSGx3Wlc5bUlIWmhiSFZsSUQwOVBTQW5jM2x0WW05c0p6dGNibjFjYmx4dVpuVnVZM1JwYjI0Z2FYTmZiblZzYkNoMllXeDFaVG9nWVc1NUtUb2dZbTl2YkdWaGJpQjdYRzRnSUhKbGRIVnliaUIyWVd4MVpTQTlQVDBnYm5Wc2JEdGNibjFjYmx4dVpuVnVZM1JwYjI0Z2FYTmZkVzVrWldacGJtVmtLSFpoYkhWbE9pQmhibmtwT2lCaWIyOXNaV0Z1SUh0Y2JpQWdjbVYwZFhKdUlIUjVjR1Z2WmlCMllXeDFaU0E5UFQwZ0ozVnVaR1ZtYVc1bFpDYzdYRzU5WEc1Y2JtWjFibU4wYVc5dUlHbHpYMloxYm1OMGFXOXVLSFpoYkhWbE9pQmhibmtwT2lCaWIyOXNaV0Z1SUh0Y2JpQWdjbVYwZFhKdUlFOWlhbVZqZEM1d2NtOTBiM1I1Y0dVdWRHOVRkSEpwYm1jdVkyRnNiQ2gyWVd4MVpTa2dQVDBnSjF0dlltcGxZM1FnUm5WdVkzUnBiMjVkSnp0Y2JuMWNibHh1Wm5WdVkzUnBiMjRnYVhOZmRtRnlhV0ZpYkdVb2RtRnNkV1U2SUdGdWVTazZJR0p2YjJ4bFlXNGdlMXh1SUNCeVpYUjFjbTRnZG1Gc2RXVWdhVzV6ZEdGdVkyVnZaaUJXWVhKcFlXSnNaVHRjYm4xY2JseHVablZ1WTNScGIyNGdhWE5mZDJsc1pHTmhjbVFvZG1Gc2RXVTZJR0Z1ZVNrNklHSnZiMnhsWVc0Z2UxeHVJQ0J5WlhSMWNtNGdkbUZzZFdVZ2FXNXpkR0Z1WTJWdlppQlhhV3hrWTJGeVpEdGNibjFjYmx4dVpuVnVZM1JwYjI0Z2FYTmZhR1ZoWkZSaGFXd29kbUZzZFdVNklHRnVlU2s2SUdKdmIyeGxZVzRnZTF4dUlDQnlaWFIxY200Z2RtRnNkV1VnYVc1emRHRnVZMlZ2WmlCSVpXRmtWR0ZwYkR0Y2JuMWNibHh1Wm5WdVkzUnBiMjRnYVhOZlkyRndkSFZ5WlNoMllXeDFaVG9nWVc1NUtUb2dZbTl2YkdWaGJpQjdYRzRnSUhKbGRIVnliaUIyWVd4MVpTQnBibk4wWVc1alpXOW1JRU5oY0hSMWNtVTdYRzU5WEc1Y2JtWjFibU4wYVc5dUlHbHpYM1I1Y0dVb2RtRnNkV1U2SUdGdWVTazZJR0p2YjJ4bFlXNGdlMXh1SUNCeVpYUjFjbTRnZG1Gc2RXVWdhVzV6ZEdGdVkyVnZaaUJVZVhCbE8xeHVmVnh1WEc1bWRXNWpkR2x2YmlCcGMxOXpkR0Z5ZEhOWGFYUm9LSFpoYkhWbE9pQmhibmtwT2lCaWIyOXNaV0Z1SUh0Y2JpQWdjbVYwZFhKdUlIWmhiSFZsSUdsdWMzUmhibU5sYjJZZ1UzUmhjblJ6VjJsMGFEdGNibjFjYmx4dVpuVnVZM1JwYjI0Z2FYTmZZbTkxYm1Rb2RtRnNkV1U2SUdGdWVTazZJR0p2YjJ4bFlXNGdlMXh1SUNCeVpYUjFjbTRnZG1Gc2RXVWdhVzV6ZEdGdVkyVnZaaUJDYjNWdVpEdGNibjFjYmx4dVpuVnVZM1JwYjI0Z2FYTmZiMkpxWldOMEtIWmhiSFZsT2lCaGJua3BPaUJpYjI5c1pXRnVJSHRjYmlBZ2NtVjBkWEp1SUhSNWNHVnZaaUIyWVd4MVpTQTlQVDBnSjI5aWFtVmpkQ2M3WEc1OVhHNWNibVoxYm1OMGFXOXVJR2x6WDJGeWNtRjVLSFpoYkhWbE9pQmhibmtwT2lCaWIyOXNaV0Z1SUh0Y2JpQWdjbVYwZFhKdUlFRnljbUY1TG1selFYSnlZWGtvZG1Gc2RXVXBPMXh1ZlZ4dVhHNWxlSEJ2Y25RZ1pHVm1ZWFZzZENCN1hHNGdJR2x6WDI1MWJXSmxjaXhjYmlBZ2FYTmZjM1J5YVc1bkxGeHVJQ0JwYzE5aWIyOXNaV0Z1TEZ4dUlDQnBjMTl6ZVcxaWIyd3NYRzRnSUdselgyNTFiR3dzWEc0Z0lHbHpYM1Z1WkdWbWFXNWxaQ3hjYmlBZ2FYTmZablZ1WTNScGIyNHNYRzRnSUdselgzWmhjbWxoWW14bExGeHVJQ0JwYzE5M2FXeGtZMkZ5WkN4Y2JpQWdhWE5mYUdWaFpGUmhhV3dzWEc0Z0lHbHpYMk5oY0hSMWNtVXNYRzRnSUdselgzUjVjR1VzWEc0Z0lHbHpYM04wWVhKMGMxZHBkR2dzWEc0Z0lHbHpYMkp2ZFc1a0xGeHVJQ0JwYzE5dlltcGxZM1FzWEc0Z0lHbHpYMkZ5Y21GNVhHNTlPMXh1SWwwc0luTnZkWEpqWlZKdmIzUWlPaUl2YzI5MWNtTmxMeUo5XG4iLCJcblxuaW1wb3J0IENoZWNrcyBmcm9tIFwiLi9jaGVja3NcIjtcbmltcG9ydCAqIGFzIFR5cGVzIGZyb20gXCIuL3R5cGVzXCI7XG5pbXBvcnQgeyBidWlsZE1hdGNoIH0gZnJvbSBcIi4vbWF0Y2hcIjtcblxuZnVuY3Rpb24gcmVzb2x2ZVN5bWJvbChwYXR0ZXJuKSB7XG4gIHJldHVybiBmdW5jdGlvbiAodmFsdWUpIHtcbiAgICByZXR1cm4gQ2hlY2tzLmlzX3N5bWJvbCh2YWx1ZSkgJiYgdmFsdWUgPT09IHBhdHRlcm47XG4gIH07XG59XG5cbmZ1bmN0aW9uIHJlc29sdmVTdHJpbmcocGF0dGVybikge1xuICByZXR1cm4gZnVuY3Rpb24gKHZhbHVlKSB7XG4gICAgcmV0dXJuIENoZWNrcy5pc19zdHJpbmcodmFsdWUpICYmIHZhbHVlID09PSBwYXR0ZXJuO1xuICB9O1xufVxuXG5mdW5jdGlvbiByZXNvbHZlTnVtYmVyKHBhdHRlcm4pIHtcbiAgcmV0dXJuIGZ1bmN0aW9uICh2YWx1ZSkge1xuICAgIHJldHVybiBDaGVja3MuaXNfbnVtYmVyKHZhbHVlKSAmJiB2YWx1ZSA9PT0gcGF0dGVybjtcbiAgfTtcbn1cblxuZnVuY3Rpb24gcmVzb2x2ZUJvb2xlYW4ocGF0dGVybikge1xuICByZXR1cm4gZnVuY3Rpb24gKHZhbHVlKSB7XG4gICAgcmV0dXJuIENoZWNrcy5pc19ib29sZWFuKHZhbHVlKSAmJiB2YWx1ZSA9PT0gcGF0dGVybjtcbiAgfTtcbn1cblxuZnVuY3Rpb24gcmVzb2x2ZUZ1bmN0aW9uKHBhdHRlcm4pIHtcbiAgcmV0dXJuIGZ1bmN0aW9uICh2YWx1ZSkge1xuICAgIHJldHVybiBDaGVja3MuaXNfZnVuY3Rpb24odmFsdWUpICYmIHZhbHVlID09PSBwYXR0ZXJuO1xuICB9O1xufVxuXG5mdW5jdGlvbiByZXNvbHZlTnVsbChwYXR0ZXJuKSB7XG4gIHJldHVybiBmdW5jdGlvbiAodmFsdWUpIHtcbiAgICByZXR1cm4gQ2hlY2tzLmlzX251bGwodmFsdWUpO1xuICB9O1xufVxuXG5mdW5jdGlvbiByZXNvbHZlQm91bmQocGF0dGVybikge1xuICByZXR1cm4gZnVuY3Rpb24gKHZhbHVlLCBhcmdzKSB7XG4gICAgaWYgKHR5cGVvZiB2YWx1ZSA9PT0gdHlwZW9mIHBhdHRlcm4udmFsdWUgJiYgdmFsdWUgPT09IHBhdHRlcm4udmFsdWUpIHtcbiAgICAgIGFyZ3MucHVzaCh2YWx1ZSk7XG4gICAgICByZXR1cm4gdHJ1ZTtcbiAgICB9XG5cbiAgICByZXR1cm4gZmFsc2U7XG4gIH07XG59XG5cbmZ1bmN0aW9uIHJlc29sdmVXaWxkY2FyZCgpIHtcbiAgcmV0dXJuIGZ1bmN0aW9uICgpIHtcbiAgICByZXR1cm4gdHJ1ZTtcbiAgfTtcbn1cblxuZnVuY3Rpb24gcmVzb2x2ZVZhcmlhYmxlKCkge1xuICByZXR1cm4gZnVuY3Rpb24gKHZhbHVlLCBhcmdzKSB7XG4gICAgYXJncy5wdXNoKHZhbHVlKTtcbiAgICByZXR1cm4gdHJ1ZTtcbiAgfTtcbn1cblxuZnVuY3Rpb24gcmVzb2x2ZUhlYWRUYWlsKHBhdHRlcm4pIHtcbiAgY29uc3QgaGVhZE1hdGNoZXMgPSBidWlsZE1hdGNoKHBhdHRlcm4uaGVhZCk7XG4gIGNvbnN0IHRhaWxNYXRjaGVzID0gYnVpbGRNYXRjaChwYXR0ZXJuLnRhaWwpO1xuXG4gIHJldHVybiBmdW5jdGlvbiAodmFsdWUsIGFyZ3MpIHtcbiAgICBpZiAoIUNoZWNrcy5pc19hcnJheSh2YWx1ZSkgfHwgdmFsdWUubGVuZ3RoIDwgMikge1xuICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH1cblxuICAgIGNvbnN0IGhlYWQgPSB2YWx1ZVswXTtcbiAgICBjb25zdCB0YWlsID0gdmFsdWUuc2xpY2UoMSk7XG5cbiAgICBpZiAoaGVhZE1hdGNoZXMoaGVhZCwgYXJncykgJiYgdGFpbE1hdGNoZXModGFpbCwgYXJncykpIHtcbiAgICAgIHJldHVybiB0cnVlO1xuICAgIH1cbiAgfTtcbn1cblxuZnVuY3Rpb24gcmVzb2x2ZUNhcHR1cmUocGF0dGVybikge1xuICBjb25zdCBtYXRjaGVzID0gYnVpbGRNYXRjaChwYXR0ZXJuLnZhbHVlKTtcblxuICByZXR1cm4gZnVuY3Rpb24gKHZhbHVlLCBhcmdzKSB7XG4gICAgaWYgKG1hdGNoZXModmFsdWUsIGFyZ3MpKSB7XG4gICAgICBhcmdzLnB1c2godmFsdWUpO1xuICAgICAgcmV0dXJuIHRydWU7XG4gICAgfVxuXG4gICAgcmV0dXJuIGZhbHNlO1xuICB9O1xufVxuXG5mdW5jdGlvbiByZXNvbHZlU3RhcnRzV2l0aChwYXR0ZXJuKSB7XG4gIGNvbnN0IHByZWZpeCA9IHBhdHRlcm4ucHJlZml4O1xuXG4gIHJldHVybiBmdW5jdGlvbiAodmFsdWUsIGFyZ3MpIHtcbiAgICBpZiAoQ2hlY2tzLmlzX3N0cmluZyh2YWx1ZSkgJiYgdmFsdWUuc3RhcnRzV2l0aChwcmVmaXgpKSB7XG4gICAgICBhcmdzLnB1c2godmFsdWUuc3Vic3RyaW5nKHByZWZpeC5sZW5ndGgpKTtcbiAgICAgIHJldHVybiB0cnVlO1xuICAgIH1cblxuICAgIHJldHVybiBmYWxzZTtcbiAgfTtcbn1cblxuZnVuY3Rpb24gcmVzb2x2ZVR5cGUocGF0dGVybikge1xuICByZXR1cm4gZnVuY3Rpb24gKHZhbHVlLCBhcmdzKSB7XG4gICAgaWYgKHZhbHVlIGluc3RhbmNlb2YgcGF0dGVybi50eXBlKSB7XG4gICAgICBjb25zdCBtYXRjaGVzID0gYnVpbGRNYXRjaChwYXR0ZXJuLm9ialBhdHRlcm4pO1xuICAgICAgcmV0dXJuIG1hdGNoZXModmFsdWUsIGFyZ3MpICYmIGFyZ3MucHVzaCh2YWx1ZSkgPiAwO1xuICAgIH1cblxuICAgIHJldHVybiBmYWxzZTtcbiAgfTtcbn1cblxuZnVuY3Rpb24gcmVzb2x2ZUFycmF5KHBhdHRlcm4pIHtcbiAgY29uc3QgbWF0Y2hlcyA9IHBhdHRlcm4ubWFwKHggPT4gYnVpbGRNYXRjaCh4KSk7XG5cbiAgcmV0dXJuIGZ1bmN0aW9uICh2YWx1ZSwgYXJncykge1xuICAgIGlmICghQ2hlY2tzLmlzX2FycmF5KHZhbHVlKSB8fCB2YWx1ZS5sZW5ndGggIT0gcGF0dGVybi5sZW5ndGgpIHtcbiAgICAgIHJldHVybiBmYWxzZTtcbiAgICB9XG5cbiAgICByZXR1cm4gdmFsdWUuZXZlcnkoZnVuY3Rpb24gKHYsIGkpIHtcbiAgICAgIHJldHVybiBtYXRjaGVzW2ldKHZhbHVlW2ldLCBhcmdzKTtcbiAgICB9KTtcbiAgfTtcbn1cblxuZnVuY3Rpb24gcmVzb2x2ZU9iamVjdChwYXR0ZXJuKSB7XG4gIGxldCBtYXRjaGVzID0ge307XG5cbiAgZm9yIChsZXQga2V5IG9mIE9iamVjdC5rZXlzKHBhdHRlcm4pLmNvbmNhdChPYmplY3QuZ2V0T3duUHJvcGVydHlTeW1ib2xzKHBhdHRlcm4pKSkge1xuICAgIG1hdGNoZXNba2V5XSA9IGJ1aWxkTWF0Y2gocGF0dGVybltrZXldKTtcbiAgfVxuXG4gIHJldHVybiBmdW5jdGlvbiAodmFsdWUsIGFyZ3MpIHtcbiAgICBpZiAoIUNoZWNrcy5pc19vYmplY3QodmFsdWUpIHx8IHBhdHRlcm4ubGVuZ3RoID4gdmFsdWUubGVuZ3RoKSB7XG4gICAgICByZXR1cm4gZmFsc2U7XG4gICAgfVxuXG4gICAgZm9yIChsZXQga2V5IG9mIE9iamVjdC5rZXlzKHBhdHRlcm4pLmNvbmNhdChPYmplY3QuZ2V0T3duUHJvcGVydHlTeW1ib2xzKHBhdHRlcm4pKSkge1xuICAgICAgaWYgKCEoa2V5IGluIHZhbHVlKSB8fCAhbWF0Y2hlc1trZXldKHZhbHVlW2tleV0sIGFyZ3MpKSB7XG4gICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICByZXR1cm4gdHJ1ZTtcbiAgfTtcbn1cblxuZnVuY3Rpb24gcmVzb2x2ZU5vTWF0Y2goKSB7XG4gIHJldHVybiBmdW5jdGlvbiAoKSB7XG4gICAgcmV0dXJuIGZhbHNlO1xuICB9O1xufVxuXG5leHBvcnQgZGVmYXVsdCB7XG4gIHJlc29sdmVCb3VuZCxcbiAgcmVzb2x2ZVdpbGRjYXJkLFxuICByZXNvbHZlVmFyaWFibGUsXG4gIHJlc29sdmVIZWFkVGFpbCxcbiAgcmVzb2x2ZUNhcHR1cmUsXG4gIHJlc29sdmVTdGFydHNXaXRoLFxuICByZXNvbHZlVHlwZSxcbiAgcmVzb2x2ZUFycmF5LFxuICByZXNvbHZlT2JqZWN0LFxuICByZXNvbHZlTm9NYXRjaCxcbiAgcmVzb2x2ZVN5bWJvbCxcbiAgcmVzb2x2ZVN0cmluZyxcbiAgcmVzb2x2ZU51bWJlcixcbiAgcmVzb2x2ZUJvb2xlYW4sXG4gIHJlc29sdmVGdW5jdGlvbixcbiAgcmVzb2x2ZU51bGxcbn07XG4vLyMgc291cmNlTWFwcGluZ1VSTD1kYXRhOmFwcGxpY2F0aW9uL2pzb247YmFzZTY0LGV5SjJaWEp6YVc5dUlqb3pMQ0p6YjNWeVkyVnpJanBiSW14cFlpOWpiM0psTDNCaGRIUmxjbTV6TDNKbGMyOXNkbVZ5Y3k1cWN5SmRMQ0p1WVcxbGN5STZXMTBzSW0xaGNIQnBibWR6SWpvaU96dEJRVVZCTEU5QlFVOHNUVUZCVUN4TlFVRnRRaXhWUVVGdVFqdEJRVU5CTEU5QlFVOHNTMEZCU3l4TFFVRk1MRTFCUVdkQ0xGTkJRWFpDTzBGQlEwRXNVMEZCVXl4VlFVRlVMRkZCUVRKQ0xGTkJRVE5DT3p0QlFVVkJMRk5CUVZNc1lVRkJWQ3hEUVVGMVFpeFBRVUYyUWl4RlFVRXJRenRCUVVNM1F5eFRRVUZQTEZWQlFWTXNTMEZCVkN4RlFVRTRRanRCUVVOdVF5eFhRVUZQTEU5QlFVOHNVMEZCVUN4RFFVRnBRaXhMUVVGcVFpeExRVUV5UWl4VlFVRlZMRTlCUVZZc1EwRkVRenRIUVVFNVFpeERRVVJ6UXp0RFFVRXZRenM3UVVGTlFTeFRRVUZUTEdGQlFWUXNRMEZCZFVJc1QwRkJka0lzUlVGQkswTTdRVUZETjBNc1UwRkJUeXhWUVVGVExFdEJRVlFzUlVGQk9FSTdRVUZEYmtNc1YwRkJUeXhQUVVGUExGTkJRVkFzUTBGQmFVSXNTMEZCYWtJc1MwRkJNa0lzVlVGQlZTeFBRVUZXTEVOQlJFTTdSMEZCT1VJc1EwRkVjME03UTBGQkwwTTdPMEZCVFVFc1UwRkJVeXhoUVVGVUxFTkJRWFZDTEU5QlFYWkNMRVZCUVN0RE8wRkJRemRETEZOQlFVOHNWVUZCVXl4TFFVRlVMRVZCUVRoQ08wRkJRMjVETEZkQlFVOHNUMEZCVHl4VFFVRlFMRU5CUVdsQ0xFdEJRV3BDTEV0QlFUSkNMRlZCUVZVc1QwRkJWaXhEUVVSRE8wZEJRVGxDTEVOQlJITkRPME5CUVM5RE96dEJRVTFCTEZOQlFWTXNZMEZCVkN4RFFVRjNRaXhQUVVGNFFpeEZRVUZuUkR0QlFVTTVReXhUUVVGUExGVkJRVk1zUzBGQlZDeEZRVUU0UWp0QlFVTnVReXhYUVVGUExFOUJRVThzVlVGQlVDeERRVUZyUWl4TFFVRnNRaXhMUVVFMFFpeFZRVUZWTEU5QlFWWXNRMEZFUVR0SFFVRTVRaXhEUVVSMVF6dERRVUZvUkRzN1FVRk5RU3hUUVVGVExHVkJRVlFzUTBGQmVVSXNUMEZCZWtJc1JVRkJhVVE3UVVGREwwTXNVMEZCVHl4VlFVRlRMRXRCUVZRc1JVRkJPRUk3UVVGRGJrTXNWMEZCVHl4UFFVRlBMRmRCUVZBc1EwRkJiVUlzUzBGQmJrSXNTMEZCTmtJc1ZVRkJWU3hQUVVGV0xFTkJSRVE3UjBGQk9VSXNRMEZFZDBNN1EwRkJha1E3TzBGQlRVRXNVMEZCVXl4WFFVRlVMRU5CUVhGQ0xFOUJRWEpDTEVWQlFUWkRPMEZCUXpORExGTkJRVThzVlVGQlV5eExRVUZVTEVWQlFUaENPMEZCUTI1RExGZEJRVThzVDBGQlR5eFBRVUZRTEVOQlFXVXNTMEZCWml4RFFVRlFMRU5CUkcxRE8wZEJRVGxDTEVOQlJHOURPME5CUVRkRE96dEJRVTFCTEZOQlFWTXNXVUZCVkN4RFFVRnpRaXhQUVVGMFFpeEZRVUZ6UkR0QlFVTndSQ3hUUVVGUExGVkJRVk1zUzBGQlZDeEZRVUZ4UWl4SlFVRnlRaXhGUVVGblJEdEJRVU55UkN4UlFVRkhMRTlCUVU4c1MwRkJVQ3hMUVVGcFFpeFBRVUZQTEZGQlFWRXNTMEZCVWl4SlFVRnBRaXhWUVVGVkxGRkJRVkVzUzBGQlVpeEZRVUZqTzBGQlEyeEZMRmRCUVVzc1NVRkJUQ3hEUVVGVkxFdEJRVllzUlVGRWEwVTdRVUZGYkVVc1lVRkJUeXhKUVVGUUxFTkJSbXRGTzB0QlFYQkZPenRCUVV0QkxGZEJRVThzUzBGQlVDeERRVTV4UkR0SFFVRm9SQ3hEUVVRMlF6dERRVUYwUkRzN1FVRlhRU3hUUVVGVExHVkJRVlFzUjBGQmNVTTdRVUZEYmtNc1UwRkJUeXhaUVVGdlFqdEJRVU42UWl4WFFVRlBMRWxCUVZBc1EwRkVlVUk3UjBGQmNFSXNRMEZFTkVJN1EwRkJja003TzBGQlRVRXNVMEZCVXl4bFFVRlVMRWRCUVhGRE8wRkJRMjVETEZOQlFVOHNWVUZCVXl4TFFVRlVMRVZCUVhGQ0xFbEJRWEpDTEVWQlFXZEVPMEZCUTNKRUxGTkJRVXNzU1VGQlRDeERRVUZWTEV0QlFWWXNSVUZFY1VRN1FVRkZja1FzVjBGQlR5eEpRVUZRTEVOQlJuRkVPMGRCUVdoRUxFTkJSRFJDTzBOQlFYSkRPenRCUVU5QkxGTkJRVk1zWlVGQlZDeERRVUY1UWl4UFFVRjZRaXhGUVVFMFJEdEJRVU14UkN4UlFVRk5MR05CUVdNc1YwRkJWeXhSUVVGUkxFbEJRVklzUTBGQmVrSXNRMEZFYjBRN1FVRkZNVVFzVVVGQlRTeGpRVUZqTEZkQlFWY3NVVUZCVVN4SlFVRlNMRU5CUVhwQ0xFTkJSbTlFT3p0QlFVa3hSQ3hUUVVGUExGVkJRVk1zUzBGQlZDeEZRVUZ4UWl4SlFVRnlRaXhGUVVGblJEdEJRVU55UkN4UlFVRkhMRU5CUVVNc1QwRkJUeXhSUVVGUUxFTkJRV2RDTEV0QlFXaENMRU5CUVVRc1NVRkJNa0lzVFVGQlRTeE5RVUZPTEVkQlFXVXNRMEZCWml4RlFVRnBRanRCUVVNM1F5eGhRVUZQTEV0QlFWQXNRMEZFTmtNN1MwRkJMME03TzBGQlNVRXNWVUZCVFN4UFFVRlBMRTFCUVUwc1EwRkJUaXhEUVVGUUxFTkJUQ3RETzBGQlRYSkVMRlZCUVUwc1QwRkJUeXhOUVVGTkxFdEJRVTRzUTBGQldTeERRVUZhTEVOQlFWQXNRMEZPSzBNN08wRkJVWEpFTEZGQlFVY3NXVUZCV1N4SlFVRmFMRVZCUVd0Q0xFbEJRV3hDTEV0QlFUSkNMRmxCUVZrc1NVRkJXaXhGUVVGclFpeEpRVUZzUWl4RFFVRXpRaXhGUVVGdFJEdEJRVU53UkN4aFFVRlBMRWxCUVZBc1EwRkViMFE3UzBGQmRFUTdSMEZTU3l4RFFVcHRSRHREUVVFMVJEczdRVUZyUWtFc1UwRkJVeXhqUVVGVUxFTkJRWGRDTEU5QlFYaENMRVZCUVRCRU8wRkJRM2hFTEZGQlFVMHNWVUZCVlN4WFFVRlhMRkZCUVZFc1MwRkJVaXhEUVVGeVFpeERRVVJyUkRzN1FVRkhlRVFzVTBGQlR5eFZRVUZUTEV0QlFWUXNSVUZCY1VJc1NVRkJja0lzUlVGQlowUTdRVUZEY2tRc1VVRkJSeXhSUVVGUkxFdEJRVklzUlVGQlpTeEpRVUZtTEVOQlFVZ3NSVUZCZDBJN1FVRkRkRUlzVjBGQlN5eEpRVUZNTEVOQlFWVXNTMEZCVml4RlFVUnpRanRCUVVWMFFpeGhRVUZQTEVsQlFWQXNRMEZHYzBJN1MwRkJlRUk3TzBGQlMwRXNWMEZCVHl4TFFVRlFMRU5CVG5GRU8wZEJRV2hFTEVOQlNHbEVPME5CUVRGRU96dEJRV0ZCTEZOQlFWTXNhVUpCUVZRc1EwRkJNa0lzVDBGQk0wSXNSVUZCWjBVN1FVRkRPVVFzVVVGQlRTeFRRVUZUTEZGQlFWRXNUVUZCVWl4RFFVUXJRenM3UVVGSE9VUXNVMEZCVHl4VlFVRlRMRXRCUVZRc1JVRkJjVUlzU1VGQmNrSXNSVUZCWjBRN1FVRkRja1FzVVVGQlJ5eFBRVUZQTEZOQlFWQXNRMEZCYVVJc1MwRkJha0lzUzBGQk1rSXNUVUZCVFN4VlFVRk9MRU5CUVdsQ0xFMUJRV3BDTEVOQlFUTkNMRVZCUVc5RU8wRkJRM0pFTEZkQlFVc3NTVUZCVEN4RFFVRlZMRTFCUVUwc1UwRkJUaXhEUVVGblFpeFBRVUZQTEUxQlFWQXNRMEZCTVVJc1JVRkVjVVE3UVVGRmNrUXNZVUZCVHl4SlFVRlFMRU5CUm5GRU8wdEJRWFpFT3p0QlFVdEJMRmRCUVU4c1MwRkJVQ3hEUVU1eFJEdEhRVUZvUkN4RFFVaDFSRHREUVVGb1JUczdRVUZoUVN4VFFVRlRMRmRCUVZRc1EwRkJjVUlzVDBGQmNrSXNSVUZCYjBRN1FVRkRiRVFzVTBGQlR5eFZRVUZUTEV0QlFWUXNSVUZCY1VJc1NVRkJja0lzUlVGQlowUTdRVUZEY2tRc1VVRkJSeXhwUWtGQmFVSXNVVUZCVVN4SlFVRlNMRVZCUVdFN1FVRkRMMElzV1VGQlRTeFZRVUZWTEZkQlFWY3NVVUZCVVN4VlFVRlNMRU5CUVhKQ0xFTkJSSGxDTzBGQlJTOUNMR0ZCUVU4c1VVRkJVU3hMUVVGU0xFVkJRV1VzU1VGQlppeExRVUYzUWl4TFFVRkxMRWxCUVV3c1EwRkJWU3hMUVVGV0xFbEJRVzFDTEVOQlFXNUNMRU5CUmtFN1MwRkJha003TzBGQlMwRXNWMEZCVHl4TFFVRlFMRU5CVG5GRU8wZEJRV2hFTEVOQlJESkRPME5CUVhCRU96dEJRVmRCTEZOQlFWTXNXVUZCVkN4RFFVRnpRaXhQUVVGMFFpeEZRVUZ4UkR0QlFVTnVSQ3hSUVVGTkxGVkJRVlVzVVVGQlVTeEhRVUZTTEVOQlFWa3NTMEZCU3l4WFFVRlhMRU5CUVZnc1EwRkJUQ3hEUVVGMFFpeERRVVEyUXpzN1FVRkhia1FzVTBGQlR5eFZRVUZUTEV0QlFWUXNSVUZCY1VJc1NVRkJja0lzUlVGQlowUTdRVUZEY2tRc1VVRkJSeXhEUVVGRExFOUJRVThzVVVGQlVDeERRVUZuUWl4TFFVRm9RaXhEUVVGRUxFbEJRVEpDTEUxQlFVMHNUVUZCVGl4SlFVRm5RaXhSUVVGUkxFMUJRVklzUlVGQlpUdEJRVU16UkN4aFFVRlBMRXRCUVZBc1EwRkVNa1E3UzBGQk4wUTdPMEZCU1VFc1YwRkJUeXhOUVVGTkxFdEJRVTRzUTBGQldTeFZRVUZUTEVOQlFWUXNSVUZCV1N4RFFVRmFMRVZCUVdVN1FVRkRhRU1zWVVGQlR5eFJRVUZSTEVOQlFWSXNSVUZCVnl4TlFVRk5MRU5CUVU0c1EwRkJXQ3hGUVVGeFFpeEpRVUZ5UWl4RFFVRlFMRU5CUkdkRE8wdEJRV1lzUTBGQmJrSXNRMEZNY1VRN1IwRkJhRVFzUTBGSU5FTTdRMEZCY2tRN08wRkJZMEVzVTBGQlV5eGhRVUZVTEVOQlFYVkNMRTlCUVhaQ0xFVkJRV3RFTzBGQlEyaEVMRTFCUVVrc1ZVRkJWU3hGUVVGV0xFTkJSRFJET3p0QlFVZG9SQ3hQUVVGSkxFbEJRVWtzUjBGQlNpeEpRVUZYTEU5QlFVOHNTVUZCVUN4RFFVRlpMRTlCUVZvc1JVRkJjVUlzVFVGQmNrSXNRMEZCTkVJc1QwRkJUeXh4UWtGQlVDeERRVUUyUWl4UFFVRTNRaXhEUVVFMVFpeERRVUZtTEVWQlFXdEdPMEZCUTJoR0xGbEJRVkVzUjBGQlVpeEpRVUZsTEZkQlFWY3NVVUZCVVN4SFFVRlNMRU5CUVZnc1EwRkJaaXhEUVVSblJqdEhRVUZzUmpzN1FVRkpRU3hUUVVGUExGVkJRVk1zUzBGQlZDeEZRVUZ4UWl4SlFVRnlRaXhGUVVGblJEdEJRVU55UkN4UlFVRkhMRU5CUVVNc1QwRkJUeXhUUVVGUUxFTkJRV2xDTEV0QlFXcENMRU5CUVVRc1NVRkJORUlzVVVGQlVTeE5RVUZTTEVkQlFXbENMRTFCUVUwc1RVRkJUaXhGUVVGaE8wRkJRek5FTEdGQlFVOHNTMEZCVUN4RFFVUXlSRHRMUVVFM1JEczdRVUZKUVN4VFFVRkpMRWxCUVVrc1IwRkJTaXhKUVVGWExFOUJRVThzU1VGQlVDeERRVUZaTEU5QlFWb3NSVUZCY1VJc1RVRkJja0lzUTBGQk5FSXNUMEZCVHl4eFFrRkJVQ3hEUVVFMlFpeFBRVUUzUWl4RFFVRTFRaXhEUVVGbUxFVkJRV3RHTzBGQlEyaEdMRlZCUVVjc1JVRkJSU3hQUVVGUExFdEJRVkFzUTBGQlJpeEpRVUZ0UWl4RFFVRkRMRkZCUVZFc1IwRkJVaXhGUVVGaExFMUJRVTBzUjBGQlRpeERRVUZpTEVWQlFYbENMRWxCUVhwQ0xFTkJRVVFzUlVGQmFVTTdRVUZEY2tRc1pVRkJUeXhMUVVGUUxFTkJSSEZFTzA5QlFYWkVPMHRCUkVZN08wRkJUVUVzVjBGQlR5eEpRVUZRTEVOQldIRkVPMGRCUVdoRUxFTkJVSGxETzBOQlFXeEVPenRCUVhOQ1FTeFRRVUZUTEdOQlFWUXNSMEZCYjBNN1FVRkRiRU1zVTBGQlR5eFpRVUZ2UWp0QlFVTjZRaXhYUVVGUExFdEJRVkFzUTBGRWVVSTdSMEZCY0VJc1EwRkVNa0k3UTBGQmNFTTdPMEZCVFVFc1pVRkJaVHRCUVVOaUxHTkJSR0U3UVVGRllpeHBRa0ZHWVR0QlFVZGlMR2xDUVVoaE8wRkJTV0lzYVVKQlNtRTdRVUZMWWl4blFrRk1ZVHRCUVUxaUxHMUNRVTVoTzBGQlQySXNZVUZRWVR0QlFWRmlMR05CVW1FN1FVRlRZaXhsUVZSaE8wRkJWV0lzWjBKQlZtRTdRVUZYWWl4bFFWaGhPMEZCV1dJc1pVRmFZVHRCUVdGaUxHVkJZbUU3UVVGallpeG5Ra0ZrWVR0QlFXVmlMR2xDUVdaaE8wRkJaMEppTEdGQmFFSmhPME5CUVdZaUxDSm1hV3hsSWpvaWJHbGlMMk52Y21VdmNHRjBkR1Z5Ym5NdmNtVnpiMngyWlhKekxtcHpJaXdpYzI5MWNtTmxjME52Ym5SbGJuUWlPbHNpTHlvZ1FHWnNiM2NnS2k5Y2JseHVhVzF3YjNKMElFTm9aV05yY3lCbWNtOXRJRndpTGk5amFHVmphM05jSWp0Y2JtbHRjRzl5ZENBcUlHRnpJRlI1Y0dWeklHWnliMjBnWENJdUwzUjVjR1Z6WENJN1hHNXBiWEJ2Y25RZ2V5QmlkV2xzWkUxaGRHTm9JSDBnWm5KdmJTQmNJaTR2YldGMFkyaGNJanRjYmx4dVpuVnVZM1JwYjI0Z2NtVnpiMngyWlZONWJXSnZiQ2h3WVhSMFpYSnVPaUJoYm5rcE9pQkdkVzVqZEdsdmJpQjdYRzRnSUhKbGRIVnliaUJtZFc1amRHbHZiaWgyWVd4MVpUb2dZVzU1S1RvZ1ltOXZiR1ZoYmlCN1hHNGdJQ0FnY21WMGRYSnVJRU5vWldOcmN5NXBjMTl6ZVcxaWIyd29kbUZzZFdVcElDWW1JSFpoYkhWbElEMDlQU0J3WVhSMFpYSnVPMXh1SUNCOU8xeHVmVnh1WEc1bWRXNWpkR2x2YmlCeVpYTnZiSFpsVTNSeWFXNW5LSEJoZEhSbGNtNDZJR0Z1ZVNrNklFWjFibU4wYVc5dUlIdGNiaUFnY21WMGRYSnVJR1oxYm1OMGFXOXVLSFpoYkhWbE9pQmhibmtwT2lCaWIyOXNaV0Z1SUh0Y2JpQWdJQ0J5WlhSMWNtNGdRMmhsWTJ0ekxtbHpYM04wY21sdVp5aDJZV3gxWlNrZ0ppWWdkbUZzZFdVZ1BUMDlJSEJoZEhSbGNtNWNiaUFnZlR0Y2JuMWNibHh1Wm5WdVkzUnBiMjRnY21WemIyeDJaVTUxYldKbGNpaHdZWFIwWlhKdU9pQmhibmtwT2lCR2RXNWpkR2x2YmlCN1hHNGdJSEpsZEhWeWJpQm1kVzVqZEdsdmJpaDJZV3gxWlRvZ1lXNTVLVG9nWW05dmJHVmhiaUI3WEc0Z0lDQWdjbVYwZFhKdUlFTm9aV05yY3k1cGMxOXVkVzFpWlhJb2RtRnNkV1VwSUNZbUlIWmhiSFZsSUQwOVBTQndZWFIwWlhKdU8xeHVJQ0I5TzF4dWZWeHVYRzVtZFc1amRHbHZiaUJ5WlhOdmJIWmxRbTl2YkdWaGJpaHdZWFIwWlhKdU9pQmhibmtwT2lCR2RXNWpkR2x2YmlCN1hHNGdJSEpsZEhWeWJpQm1kVzVqZEdsdmJpaDJZV3gxWlRvZ1lXNTVLVG9nWW05dmJHVmhiaUI3WEc0Z0lDQWdjbVYwZFhKdUlFTm9aV05yY3k1cGMxOWliMjlzWldGdUtIWmhiSFZsS1NBbUppQjJZV3gxWlNBOVBUMGdjR0YwZEdWeWJseHVJQ0I5TzF4dWZWeHVYRzVtZFc1amRHbHZiaUJ5WlhOdmJIWmxSblZ1WTNScGIyNG9jR0YwZEdWeWJqb2dZVzU1S1RvZ1JuVnVZM1JwYjI0Z2UxeHVJQ0J5WlhSMWNtNGdablZ1WTNScGIyNG9kbUZzZFdVNklHRnVlU2s2SUdKdmIyeGxZVzRnZTF4dUlDQWdJSEpsZEhWeWJpQkRhR1ZqYTNNdWFYTmZablZ1WTNScGIyNG9kbUZzZFdVcElDWW1JSFpoYkhWbElEMDlQU0J3WVhSMFpYSnVYRzRnSUgwN1hHNTlYRzVjYm1aMWJtTjBhVzl1SUhKbGMyOXNkbVZPZFd4c0tIQmhkSFJsY200NklHRnVlU2s2SUVaMWJtTjBhVzl1SUh0Y2JpQWdjbVYwZFhKdUlHWjFibU4wYVc5dUtIWmhiSFZsT2lCaGJua3BPaUJpYjI5c1pXRnVJSHRjYmlBZ0lDQnlaWFIxY200Z1EyaGxZMnR6TG1selgyNTFiR3dvZG1Gc2RXVXBPMXh1SUNCOU8xeHVmVnh1WEc1bWRXNWpkR2x2YmlCeVpYTnZiSFpsUW05MWJtUW9jR0YwZEdWeWJqb2dWSGx3WlhNdVFtOTFibVFwT2lCR2RXNWpkR2x2YmlCN1hHNGdJSEpsZEhWeWJpQm1kVzVqZEdsdmJpaDJZV3gxWlRvZ1lXNTVMQ0JoY21kek9pQkJjbkpoZVR4aGJuaytLVG9nWW05dmJHVmhiaUI3WEc0Z0lDQWdhV1lvZEhsd1pXOW1JSFpoYkhWbElEMDlQU0IwZVhCbGIyWWdjR0YwZEdWeWJpNTJZV3gxWlNBbUppQjJZV3gxWlNBOVBUMGdjR0YwZEdWeWJpNTJZV3gxWlNsN1hHNGdJQ0FnSUNCaGNtZHpMbkIxYzJnb2RtRnNkV1VwTzF4dUlDQWdJQ0FnY21WMGRYSnVJSFJ5ZFdVN1hHNGdJQ0FnZlZ4dVhHNGdJQ0FnY21WMGRYSnVJR1poYkhObE8xeHVJQ0I5TzF4dWZWeHVYRzVtZFc1amRHbHZiaUJ5WlhOdmJIWmxWMmxzWkdOaGNtUW9LVG9nUm5WdVkzUnBiMjRnZTF4dUlDQnlaWFIxY200Z1puVnVZM1JwYjI0b0tUb2dZbTl2YkdWaGJpQjdYRzRnSUNBZ2NtVjBkWEp1SUhSeWRXVTdYRzRnSUgwN1hHNTlYRzVjYm1aMWJtTjBhVzl1SUhKbGMyOXNkbVZXWVhKcFlXSnNaU2dwT2lCR2RXNWpkR2x2YmlCN1hHNGdJSEpsZEhWeWJpQm1kVzVqZEdsdmJpaDJZV3gxWlRvZ1lXNTVMQ0JoY21kek9pQkJjbkpoZVR4aGJuaytLVG9nWW05dmJHVmhiaUI3WEc0Z0lDQWdZWEpuY3k1d2RYTm9LSFpoYkhWbEtUdGNiaUFnSUNCeVpYUjFjbTRnZEhKMVpUdGNiaUFnZlR0Y2JuMWNibHh1Wm5WdVkzUnBiMjRnY21WemIyeDJaVWhsWVdSVVlXbHNLSEJoZEhSbGNtNDZJRlI1Y0dWekxraGxZV1JVWVdsc0tUb2dSblZ1WTNScGIyNGdlMXh1SUNCamIyNXpkQ0JvWldGa1RXRjBZMmhsY3lBOUlHSjFhV3hrVFdGMFkyZ29jR0YwZEdWeWJpNW9aV0ZrS1R0Y2JpQWdZMjl1YzNRZ2RHRnBiRTFoZEdOb1pYTWdQU0JpZFdsc1pFMWhkR05vS0hCaGRIUmxjbTR1ZEdGcGJDazdYRzVjYmlBZ2NtVjBkWEp1SUdaMWJtTjBhVzl1S0haaGJIVmxPaUJoYm5rc0lHRnlaM002SUVGeWNtRjVQR0Z1ZVQ0cE9pQmliMjlzWldGdUlIdGNiaUFnSUNCcFppZ2hRMmhsWTJ0ekxtbHpYMkZ5Y21GNUtIWmhiSFZsS1NCOGZDQjJZV3gxWlM1c1pXNW5kR2dnUENBeUtYdGNiaUFnSUNBZ0lISmxkSFZ5YmlCbVlXeHpaVHRjYmlBZ0lDQjlYRzVjYmlBZ0lDQmpiMjV6ZENCb1pXRmtJRDBnZG1Gc2RXVmJNRjA3WEc0Z0lDQWdZMjl1YzNRZ2RHRnBiQ0E5SUhaaGJIVmxMbk5zYVdObEtERXBPMXh1WEc0Z0lDQWdhV1lvYUdWaFpFMWhkR05vWlhNb2FHVmhaQ3dnWVhKbmN5a2dKaVlnZEdGcGJFMWhkR05vWlhNb2RHRnBiQ3dnWVhKbmN5a3BlMXh1SUNBZ0lDQWdjbVYwZFhKdUlIUnlkV1U3WEc0Z0lDQWdmVnh1SUNCOU8xeHVmVnh1WEc1bWRXNWpkR2x2YmlCeVpYTnZiSFpsUTJGd2RIVnlaU2h3WVhSMFpYSnVPaUJVZVhCbGN5NURZWEIwZFhKbEtUb2dSblZ1WTNScGIyNGdlMXh1SUNCamIyNXpkQ0J0WVhSamFHVnpJRDBnWW5WcGJHUk5ZWFJqYUNod1lYUjBaWEp1TG5aaGJIVmxLVHRjYmx4dUlDQnlaWFIxY200Z1puVnVZM1JwYjI0b2RtRnNkV1U2SUdGdWVTd2dZWEpuY3pvZ1FYSnlZWGs4WVc1NVBpazZJR0p2YjJ4bFlXNGdlMXh1SUNBZ0lHbG1LRzFoZEdOb1pYTW9kbUZzZFdVc0lHRnlaM01wS1h0Y2JpQWdJQ0FnSUdGeVozTXVjSFZ6YUNoMllXeDFaU2s3WEc0Z0lDQWdJQ0J5WlhSMWNtNGdkSEoxWlR0Y2JpQWdJQ0I5WEc1Y2JpQWdJQ0J5WlhSMWNtNGdabUZzYzJVN1hHNGdJSDA3WEc1OVhHNWNibVoxYm1OMGFXOXVJSEpsYzI5c2RtVlRkR0Z5ZEhOWGFYUm9LSEJoZEhSbGNtNDZJRlI1Y0dWekxsTjBZWEowYzFkcGRHZ3BPaUJHZFc1amRHbHZiaUI3WEc0Z0lHTnZibk4wSUhCeVpXWnBlQ0E5SUhCaGRIUmxjbTR1Y0hKbFptbDRPMXh1WEc0Z0lISmxkSFZ5YmlCbWRXNWpkR2x2YmloMllXeDFaVG9nWVc1NUxDQmhjbWR6T2lCQmNuSmhlVHhoYm5rK0tUb2dZbTl2YkdWaGJpQjdYRzRnSUNBZ2FXWW9RMmhsWTJ0ekxtbHpYM04wY21sdVp5aDJZV3gxWlNrZ0ppWWdkbUZzZFdVdWMzUmhjblJ6VjJsMGFDaHdjbVZtYVhncEtYdGNiaUFnSUNBZ0lHRnlaM011Y0hWemFDaDJZV3gxWlM1emRXSnpkSEpwYm1jb2NISmxabWw0TG14bGJtZDBhQ2twTzF4dUlDQWdJQ0FnY21WMGRYSnVJSFJ5ZFdVN1hHNGdJQ0FnZlZ4dVhHNGdJQ0FnY21WMGRYSnVJR1poYkhObE8xeHVJQ0I5TzF4dWZWeHVYRzVtZFc1amRHbHZiaUJ5WlhOdmJIWmxWSGx3WlNod1lYUjBaWEp1T2lCVWVYQmxjeTVVZVhCbEtUb2dSblZ1WTNScGIyNGdlMXh1SUNCeVpYUjFjbTRnWm5WdVkzUnBiMjRvZG1Gc2RXVTZJR0Z1ZVN3Z1lYSm5jem9nUVhKeVlYazhZVzU1UGlrNklHSnZiMnhsWVc0Z2UxeHVJQ0FnSUdsbUtIWmhiSFZsSUdsdWMzUmhibU5sYjJZZ2NHRjBkR1Z5Ymk1MGVYQmxLWHRjYmlBZ0lDQWdJR052Ym5OMElHMWhkR05vWlhNZ1BTQmlkV2xzWkUxaGRHTm9LSEJoZEhSbGNtNHViMkpxVUdGMGRHVnliaWs3WEc0Z0lDQWdJQ0J5WlhSMWNtNGdiV0YwWTJobGN5aDJZV3gxWlN3Z1lYSm5jeWtnSmlZZ1lYSm5jeTV3ZFhOb0tIWmhiSFZsS1NBK0lEQTdYRzRnSUNBZ2ZWeHVYRzRnSUNBZ2NtVjBkWEp1SUdaaGJITmxPMXh1SUNCOU8xeHVmVnh1WEc1bWRXNWpkR2x2YmlCeVpYTnZiSFpsUVhKeVlYa29jR0YwZEdWeWJqb2dRWEp5WVhrOFlXNTVQaWs2SUVaMWJtTjBhVzl1SUh0Y2JpQWdZMjl1YzNRZ2JXRjBZMmhsY3lBOUlIQmhkSFJsY200dWJXRndLSGdnUFQ0Z1luVnBiR1JOWVhSamFDaDRLU2s3WEc1Y2JpQWdjbVYwZFhKdUlHWjFibU4wYVc5dUtIWmhiSFZsT2lCaGJua3NJR0Z5WjNNNklFRnljbUY1UEdGdWVUNHBPaUJpYjI5c1pXRnVJSHRjYmlBZ0lDQnBaaWdoUTJobFkydHpMbWx6WDJGeWNtRjVLSFpoYkhWbEtTQjhmQ0IyWVd4MVpTNXNaVzVuZEdnZ0lUMGdjR0YwZEdWeWJpNXNaVzVuZEdncGUxeHVJQ0FnSUNBZ2NtVjBkWEp1SUdaaGJITmxPMXh1SUNBZ0lIMWNibHh1SUNBZ0lISmxkSFZ5YmlCMllXeDFaUzVsZG1WeWVTaG1kVzVqZEdsdmJpaDJMQ0JwS1NCN1hHNGdJQ0FnSUNCeVpYUjFjbTRnYldGMFkyaGxjMXRwWFNoMllXeDFaVnRwWFN3Z1lYSm5jeWs3WEc0Z0lDQWdmU2s3WEc0Z0lIMDdYRzU5WEc1Y2JtWjFibU4wYVc5dUlISmxjMjlzZG1WUFltcGxZM1FvY0dGMGRHVnliam9nVDJKcVpXTjBLVG9nUm5WdVkzUnBiMjRnZTF4dUlDQnNaWFFnYldGMFkyaGxjeUE5SUh0OU8xeHVYRzRnSUdadmNpaHNaWFFnYTJWNUlHOW1JRTlpYW1WamRDNXJaWGx6S0hCaGRIUmxjbTRwTG1OdmJtTmhkQ2hQWW1wbFkzUXVaMlYwVDNkdVVISnZjR1Z5ZEhsVGVXMWliMnh6S0hCaGRIUmxjbTRwS1NsN1hHNGdJQ0FnYldGMFkyaGxjMXRyWlhsZElEMGdZblZwYkdSTllYUmphQ2h3WVhSMFpYSnVXMnRsZVYwcE8xeHVJQ0I5WEc1Y2JpQWdjbVYwZFhKdUlHWjFibU4wYVc5dUtIWmhiSFZsT2lCaGJua3NJR0Z5WjNNNklFRnljbUY1UEdGdWVUNHBPaUJpYjI5c1pXRnVJSHRjYmlBZ0lDQnBaaWdoUTJobFkydHpMbWx6WDI5aWFtVmpkQ2gyWVd4MVpTa2dmSHdnY0dGMGRHVnliaTVzWlc1bmRHZ2dQaUIyWVd4MVpTNXNaVzVuZEdncGUxeHVJQ0FnSUNBZ2NtVjBkWEp1SUdaaGJITmxPMXh1SUNBZ0lIMWNibHh1SUNBZ0lHWnZjaWhzWlhRZ2EyVjVJRzltSUU5aWFtVmpkQzVyWlhsektIQmhkSFJsY200cExtTnZibU5oZENoUFltcGxZM1F1WjJWMFQzZHVVSEp2Y0dWeWRIbFRlVzFpYjJ4ektIQmhkSFJsY200cEtTbDdYRzRnSUNBZ0lDQnBaaWdoS0d0bGVTQnBiaUIyWVd4MVpTa2dmSHdnSVcxaGRHTm9aWE5iYTJWNVhTaDJZV3gxWlZ0clpYbGRMQ0JoY21kektTQXBlMXh1SUNBZ0lDQWdJQ0J5WlhSMWNtNGdabUZzYzJVN1hHNGdJQ0FnSUNCOVhHNGdJQ0FnZlZ4dVhHNGdJQ0FnY21WMGRYSnVJSFJ5ZFdVN1hHNGdJSDA3WEc1OVhHNWNibVoxYm1OMGFXOXVJSEpsYzI5c2RtVk9iMDFoZEdOb0tDazZJRVoxYm1OMGFXOXVJSHRjYmlBZ2NtVjBkWEp1SUdaMWJtTjBhVzl1S0NrNklHSnZiMnhsWVc0Z2UxeHVJQ0FnSUhKbGRIVnliaUJtWVd4elpUdGNiaUFnZlZ4dWZWeHVYRzVsZUhCdmNuUWdaR1ZtWVhWc2RDQjdYRzRnSUhKbGMyOXNkbVZDYjNWdVpDeGNiaUFnY21WemIyeDJaVmRwYkdSallYSmtMRnh1SUNCeVpYTnZiSFpsVm1GeWFXRmliR1VzWEc0Z0lISmxjMjlzZG1WSVpXRmtWR0ZwYkN4Y2JpQWdjbVZ6YjJ4MlpVTmhjSFIxY21Vc1hHNGdJSEpsYzI5c2RtVlRkR0Z5ZEhOWGFYUm9MRnh1SUNCeVpYTnZiSFpsVkhsd1pTeGNiaUFnY21WemIyeDJaVUZ5Y21GNUxGeHVJQ0J5WlhOdmJIWmxUMkpxWldOMExGeHVJQ0J5WlhOdmJIWmxUbTlOWVhSamFDeGNiaUFnY21WemIyeDJaVk41YldKdmJDeGNiaUFnY21WemIyeDJaVk4wY21sdVp5eGNiaUFnY21WemIyeDJaVTUxYldKbGNpeGNiaUFnY21WemIyeDJaVUp2YjJ4bFlXNHNYRzRnSUhKbGMyOXNkbVZHZFc1amRHbHZiaXhjYmlBZ2NtVnpiMngyWlU1MWJHeGNibjFjYmlKZExDSnpiM1Z5WTJWU2IyOTBJam9pTDNOdmRYSmpaUzhpZlE9PVxuIiwiXG5pbXBvcnQgQ2hlY2tzIGZyb20gXCIuL2NoZWNrc1wiO1xuaW1wb3J0IFJlc29sdmVycyBmcm9tIFwiLi9yZXNvbHZlcnNcIjtcblxuZXhwb3J0IGZ1bmN0aW9uIGJ1aWxkTWF0Y2gocGF0dGVybikge1xuXG4gIGlmIChDaGVja3MuaXNfdmFyaWFibGUocGF0dGVybikpIHtcbiAgICByZXR1cm4gUmVzb2x2ZXJzLnJlc29sdmVWYXJpYWJsZShwYXR0ZXJuKTtcbiAgfVxuXG4gIGlmIChDaGVja3MuaXNfd2lsZGNhcmQocGF0dGVybikpIHtcbiAgICByZXR1cm4gUmVzb2x2ZXJzLnJlc29sdmVXaWxkY2FyZChwYXR0ZXJuKTtcbiAgfVxuXG4gIGlmIChDaGVja3MuaXNfdW5kZWZpbmVkKHBhdHRlcm4pKSB7XG4gICAgcmV0dXJuIFJlc29sdmVycy5yZXNvbHZlV2lsZGNhcmQocGF0dGVybik7XG4gIH1cblxuICBpZiAoQ2hlY2tzLmlzX2hlYWRUYWlsKHBhdHRlcm4pKSB7XG4gICAgcmV0dXJuIFJlc29sdmVycy5yZXNvbHZlSGVhZFRhaWwocGF0dGVybik7XG4gIH1cblxuICBpZiAoQ2hlY2tzLmlzX3N0YXJ0c1dpdGgocGF0dGVybikpIHtcbiAgICByZXR1cm4gUmVzb2x2ZXJzLnJlc29sdmVTdGFydHNXaXRoKHBhdHRlcm4pO1xuICB9XG5cbiAgaWYgKENoZWNrcy5pc19jYXB0dXJlKHBhdHRlcm4pKSB7XG4gICAgcmV0dXJuIFJlc29sdmVycy5yZXNvbHZlQ2FwdHVyZShwYXR0ZXJuKTtcbiAgfVxuXG4gIGlmIChDaGVja3MuaXNfYm91bmQocGF0dGVybikpIHtcbiAgICByZXR1cm4gUmVzb2x2ZXJzLnJlc29sdmVCb3VuZChwYXR0ZXJuKTtcbiAgfVxuXG4gIGlmIChDaGVja3MuaXNfdHlwZShwYXR0ZXJuKSkge1xuICAgIHJldHVybiBSZXNvbHZlcnMucmVzb2x2ZVR5cGUocGF0dGVybik7XG4gIH1cblxuICBpZiAoQ2hlY2tzLmlzX2FycmF5KHBhdHRlcm4pKSB7XG4gICAgcmV0dXJuIFJlc29sdmVycy5yZXNvbHZlQXJyYXkocGF0dGVybik7XG4gIH1cblxuICBpZiAoQ2hlY2tzLmlzX251bWJlcihwYXR0ZXJuKSkge1xuICAgIHJldHVybiBSZXNvbHZlcnMucmVzb2x2ZU51bWJlcihwYXR0ZXJuKTtcbiAgfVxuXG4gIGlmIChDaGVja3MuaXNfc3RyaW5nKHBhdHRlcm4pKSB7XG4gICAgcmV0dXJuIFJlc29sdmVycy5yZXNvbHZlU3RyaW5nKHBhdHRlcm4pO1xuICB9XG5cbiAgaWYgKENoZWNrcy5pc19ib29sZWFuKHBhdHRlcm4pKSB7XG4gICAgcmV0dXJuIFJlc29sdmVycy5yZXNvbHZlQm9vbGVhbihwYXR0ZXJuKTtcbiAgfVxuXG4gIGlmIChDaGVja3MuaXNfc3ltYm9sKHBhdHRlcm4pKSB7XG4gICAgcmV0dXJuIFJlc29sdmVycy5yZXNvbHZlU3ltYm9sKHBhdHRlcm4pO1xuICB9XG5cbiAgaWYgKENoZWNrcy5pc19udWxsKHBhdHRlcm4pKSB7XG4gICAgcmV0dXJuIFJlc29sdmVycy5yZXNvbHZlTnVsbChwYXR0ZXJuKTtcbiAgfVxuXG4gIGlmIChDaGVja3MuaXNfb2JqZWN0KHBhdHRlcm4pKSB7XG4gICAgcmV0dXJuIFJlc29sdmVycy5yZXNvbHZlT2JqZWN0KHBhdHRlcm4pO1xuICB9XG5cbiAgcmV0dXJuIFJlc29sdmVycy5yZXNvbHZlTm9NYXRjaCgpO1xufVxuLy8jIHNvdXJjZU1hcHBpbmdVUkw9ZGF0YTphcHBsaWNhdGlvbi9qc29uO2Jhc2U2NCxleUoyWlhKemFXOXVJam96TENKemIzVnlZMlZ6SWpwYklteHBZaTlqYjNKbEwzQmhkSFJsY201ekwyMWhkR05vTG1weklsMHNJbTVoYldWeklqcGJYU3dpYldGd2NHbHVaM01pT2lJN1FVRkRRU3hQUVVGUExFMUJRVkFzVFVGQmJVSXNWVUZCYmtJN1FVRkRRU3hQUVVGUExGTkJRVkFzVFVGQmMwSXNZVUZCZEVJN08wRkJSVUVzVDBGQlR5eFRRVUZUTEZWQlFWUXNRMEZCYjBJc1QwRkJjRUlzUlVGQk5FTTdPMEZCUldwRUxFMUJRVWNzVDBGQlR5eFhRVUZRTEVOQlFXMUNMRTlCUVc1Q0xFTkJRVWdzUlVGQkswSTdRVUZETjBJc1YwRkJUeXhWUVVGVkxHVkJRVllzUTBGQk1FSXNUMEZCTVVJc1EwRkJVQ3hEUVVRMlFqdEhRVUV2UWpzN1FVRkpRU3hOUVVGSExFOUJRVThzVjBGQlVDeERRVUZ0UWl4UFFVRnVRaXhEUVVGSUxFVkJRU3RDTzBGQlF6ZENMRmRCUVU4c1ZVRkJWU3hsUVVGV0xFTkJRVEJDTEU5QlFURkNMRU5CUVZBc1EwRkVOa0k3UjBGQkwwSTdPMEZCU1VFc1RVRkJSeXhQUVVGUExGbEJRVkFzUTBGQmIwSXNUMEZCY0VJc1EwRkJTQ3hGUVVGblF6dEJRVU01UWl4WFFVRlBMRlZCUVZVc1pVRkJWaXhEUVVFd1FpeFBRVUV4UWl4RFFVRlFMRU5CUkRoQ08wZEJRV2hET3p0QlFVbEJMRTFCUVVjc1QwRkJUeXhYUVVGUUxFTkJRVzFDTEU5QlFXNUNMRU5CUVVnc1JVRkJLMEk3UVVGRE4wSXNWMEZCVHl4VlFVRlZMR1ZCUVZZc1EwRkJNRUlzVDBGQk1VSXNRMEZCVUN4RFFVUTJRanRIUVVFdlFqczdRVUZKUVN4TlFVRkhMRTlCUVU4c1lVRkJVQ3hEUVVGeFFpeFBRVUZ5UWl4RFFVRklMRVZCUVdsRE8wRkJReTlDTEZkQlFVOHNWVUZCVlN4cFFrRkJWaXhEUVVFMFFpeFBRVUUxUWl4RFFVRlFMRU5CUkN0Q08wZEJRV3BET3p0QlFVbEJMRTFCUVVjc1QwRkJUeXhWUVVGUUxFTkJRV3RDTEU5QlFXeENMRU5CUVVnc1JVRkJPRUk3UVVGRE5VSXNWMEZCVHl4VlFVRlZMR05CUVZZc1EwRkJlVUlzVDBGQmVrSXNRMEZCVUN4RFFVUTBRanRIUVVFNVFqczdRVUZKUVN4TlFVRkhMRTlCUVU4c1VVRkJVQ3hEUVVGblFpeFBRVUZvUWl4RFFVRklMRVZCUVRSQ08wRkJRekZDTEZkQlFVOHNWVUZCVlN4WlFVRldMRU5CUVhWQ0xFOUJRWFpDTEVOQlFWQXNRMEZFTUVJN1IwRkJOVUk3TzBGQlNVRXNUVUZCUnl4UFFVRlBMRTlCUVZBc1EwRkJaU3hQUVVGbUxFTkJRVWdzUlVGQk1rSTdRVUZEZWtJc1YwRkJUeXhWUVVGVkxGZEJRVllzUTBGQmMwSXNUMEZCZEVJc1EwRkJVQ3hEUVVSNVFqdEhRVUV6UWpzN1FVRkpRU3hOUVVGSExFOUJRVThzVVVGQlVDeERRVUZuUWl4UFFVRm9RaXhEUVVGSUxFVkJRVFJDTzBGQlF6RkNMRmRCUVU4c1ZVRkJWU3haUVVGV0xFTkJRWFZDTEU5QlFYWkNMRU5CUVZBc1EwRkVNRUk3UjBGQk5VSTdPMEZCU1VFc1RVRkJSeXhQUVVGUExGTkJRVkFzUTBGQmFVSXNUMEZCYWtJc1EwRkJTQ3hGUVVFMlFqdEJRVU16UWl4WFFVRlBMRlZCUVZVc1lVRkJWaXhEUVVGM1FpeFBRVUY0UWl4RFFVRlFMRU5CUkRKQ08wZEJRVGRDT3p0QlFVbEJMRTFCUVVjc1QwRkJUeXhUUVVGUUxFTkJRV2xDTEU5QlFXcENMRU5CUVVnc1JVRkJOa0k3UVVGRE0wSXNWMEZCVHl4VlFVRlZMR0ZCUVZZc1EwRkJkMElzVDBGQmVFSXNRMEZCVUN4RFFVUXlRanRIUVVFM1FqczdRVUZKUVN4TlFVRkhMRTlCUVU4c1ZVRkJVQ3hEUVVGclFpeFBRVUZzUWl4RFFVRklMRVZCUVRoQ08wRkJRelZDTEZkQlFVOHNWVUZCVlN4alFVRldMRU5CUVhsQ0xFOUJRWHBDTEVOQlFWQXNRMEZFTkVJN1IwRkJPVUk3TzBGQlNVRXNUVUZCUnl4UFFVRlBMRk5CUVZBc1EwRkJhVUlzVDBGQmFrSXNRMEZCU0N4RlFVRTJRanRCUVVNelFpeFhRVUZQTEZWQlFWVXNZVUZCVml4RFFVRjNRaXhQUVVGNFFpeERRVUZRTEVOQlJESkNPMGRCUVRkQ096dEJRVWxCTEUxQlFVY3NUMEZCVHl4UFFVRlFMRU5CUVdVc1QwRkJaaXhEUVVGSUxFVkJRVEpDTzBGQlEzcENMRmRCUVU4c1ZVRkJWU3hYUVVGV0xFTkJRWE5DTEU5QlFYUkNMRU5CUVZBc1EwRkVlVUk3UjBGQk0wSTdPMEZCU1VFc1RVRkJSeXhQUVVGUExGTkJRVkFzUTBGQmFVSXNUMEZCYWtJc1EwRkJTQ3hGUVVFMlFqdEJRVU16UWl4WFFVRlBMRlZCUVZVc1lVRkJWaXhEUVVGM1FpeFBRVUY0UWl4RFFVRlFMRU5CUkRKQ08wZEJRVGRDT3p0QlFVbEJMRk5CUVU4c1ZVRkJWU3hqUVVGV0xFVkJRVkFzUTBFNVJHbEVPME5CUVRWRElpd2labWxzWlNJNklteHBZaTlqYjNKbEwzQmhkSFJsY201ekwyMWhkR05vTG1weklpd2ljMjkxY21ObGMwTnZiblJsYm5RaU9sc2lMeW9nUUdac2IzY2dLaTljYm1sdGNHOXlkQ0JEYUdWamEzTWdabkp2YlNCY0lpNHZZMmhsWTJ0elhDSTdYRzVwYlhCdmNuUWdVbVZ6YjJ4MlpYSnpJR1p5YjIwZ1hDSXVMM0psYzI5c2RtVnljMXdpTzF4dVhHNWxlSEJ2Y25RZ1puVnVZM1JwYjI0Z1luVnBiR1JOWVhSamFDaHdZWFIwWlhKdU9pQmhibmtwT2lCR2RXNWpkR2x2YmlCN1hHNWNiaUFnYVdZb1EyaGxZMnR6TG1selgzWmhjbWxoWW14bEtIQmhkSFJsY200cEtYdGNiaUFnSUNCeVpYUjFjbTRnVW1WemIyeDJaWEp6TG5KbGMyOXNkbVZXWVhKcFlXSnNaU2h3WVhSMFpYSnVLVHRjYmlBZ2ZWeHVYRzRnSUdsbUtFTm9aV05yY3k1cGMxOTNhV3hrWTJGeVpDaHdZWFIwWlhKdUtTbDdYRzRnSUNBZ2NtVjBkWEp1SUZKbGMyOXNkbVZ5Y3k1eVpYTnZiSFpsVjJsc1pHTmhjbVFvY0dGMGRHVnliaWs3WEc0Z0lIMWNibHh1SUNCcFppaERhR1ZqYTNNdWFYTmZkVzVrWldacGJtVmtLSEJoZEhSbGNtNHBLWHRjYmlBZ0lDQnlaWFIxY200Z1VtVnpiMngyWlhKekxuSmxjMjlzZG1WWGFXeGtZMkZ5WkNod1lYUjBaWEp1S1R0Y2JpQWdmVnh1WEc0Z0lHbG1LRU5vWldOcmN5NXBjMTlvWldGa1ZHRnBiQ2h3WVhSMFpYSnVLU2w3WEc0Z0lDQWdjbVYwZFhKdUlGSmxjMjlzZG1WeWN5NXlaWE52YkhabFNHVmhaRlJoYVd3b2NHRjBkR1Z5YmlrN1hHNGdJSDFjYmx4dUlDQnBaaWhEYUdWamEzTXVhWE5mYzNSaGNuUnpWMmwwYUNod1lYUjBaWEp1S1NsN1hHNGdJQ0FnY21WMGRYSnVJRkpsYzI5c2RtVnljeTV5WlhOdmJIWmxVM1JoY25SelYybDBhQ2h3WVhSMFpYSnVLVHRjYmlBZ2ZWeHVYRzRnSUdsbUtFTm9aV05yY3k1cGMxOWpZWEIwZFhKbEtIQmhkSFJsY200cEtYdGNiaUFnSUNCeVpYUjFjbTRnVW1WemIyeDJaWEp6TG5KbGMyOXNkbVZEWVhCMGRYSmxLSEJoZEhSbGNtNHBPMXh1SUNCOVhHNWNiaUFnYVdZb1EyaGxZMnR6TG1selgySnZkVzVrS0hCaGRIUmxjbTRwS1h0Y2JpQWdJQ0J5WlhSMWNtNGdVbVZ6YjJ4MlpYSnpMbkpsYzI5c2RtVkNiM1Z1WkNod1lYUjBaWEp1S1R0Y2JpQWdmVnh1WEc0Z0lHbG1LRU5vWldOcmN5NXBjMTkwZVhCbEtIQmhkSFJsY200cEtYdGNiaUFnSUNCeVpYUjFjbTRnVW1WemIyeDJaWEp6TG5KbGMyOXNkbVZVZVhCbEtIQmhkSFJsY200cE8xeHVJQ0I5WEc1Y2JpQWdhV1lvUTJobFkydHpMbWx6WDJGeWNtRjVLSEJoZEhSbGNtNHBLWHRjYmlBZ0lDQnlaWFIxY200Z1VtVnpiMngyWlhKekxuSmxjMjlzZG1WQmNuSmhlU2h3WVhSMFpYSnVLVHRjYmlBZ2ZWeHVYRzRnSUdsbUtFTm9aV05yY3k1cGMxOXVkVzFpWlhJb2NHRjBkR1Z5YmlrcGUxeHVJQ0FnSUhKbGRIVnliaUJTWlhOdmJIWmxjbk11Y21WemIyeDJaVTUxYldKbGNpaHdZWFIwWlhKdUtUdGNiaUFnZlZ4dVhHNGdJR2xtS0VOb1pXTnJjeTVwYzE5emRISnBibWNvY0dGMGRHVnliaWtwZTF4dUlDQWdJSEpsZEhWeWJpQlNaWE52YkhabGNuTXVjbVZ6YjJ4MlpWTjBjbWx1Wnlod1lYUjBaWEp1S1R0Y2JpQWdmVnh1WEc0Z0lHbG1LRU5vWldOcmN5NXBjMTlpYjI5c1pXRnVLSEJoZEhSbGNtNHBLWHRjYmlBZ0lDQnlaWFIxY200Z1VtVnpiMngyWlhKekxuSmxjMjlzZG1WQ2IyOXNaV0Z1S0hCaGRIUmxjbTRwTzF4dUlDQjlYRzVjYmlBZ2FXWW9RMmhsWTJ0ekxtbHpYM041YldKdmJDaHdZWFIwWlhKdUtTbDdYRzRnSUNBZ2NtVjBkWEp1SUZKbGMyOXNkbVZ5Y3k1eVpYTnZiSFpsVTNsdFltOXNLSEJoZEhSbGNtNHBPMXh1SUNCOVhHNWNiaUFnYVdZb1EyaGxZMnR6TG1selgyNTFiR3dvY0dGMGRHVnliaWtwZTF4dUlDQWdJSEpsZEhWeWJpQlNaWE52YkhabGNuTXVjbVZ6YjJ4MlpVNTFiR3dvY0dGMGRHVnliaWs3WEc0Z0lIMWNibHh1SUNCcFppaERhR1ZqYTNNdWFYTmZiMkpxWldOMEtIQmhkSFJsY200cEtYdGNiaUFnSUNCeVpYUjFjbTRnVW1WemIyeDJaWEp6TG5KbGMyOXNkbVZQWW1wbFkzUW9jR0YwZEdWeWJpazdYRzRnSUgxY2JseHVJQ0J5WlhSMWNtNGdVbVZ6YjJ4MlpYSnpMbkpsYzI5c2RtVk9iMDFoZEdOb0tDazdYRzU5WEc0aVhTd2ljMjkxY21ObFVtOXZkQ0k2SWk5emIzVnlZMlV2SW4wPVxuIiwiXG5cbmltcG9ydCB7IGJ1aWxkTWF0Y2ggfSBmcm9tIFwiLi9tYXRjaFwiO1xuXG5leHBvcnQgY2xhc3MgTWF0Y2hFcnJvciBleHRlbmRzIEVycm9yIHtcbiAgY29uc3RydWN0b3IoYXJnKSB7XG4gICAgc3VwZXIoKTtcblxuICAgIGlmICh0eXBlb2YgYXJnID09PSAnc3ltYm9sJykge1xuICAgICAgdGhpcy5tZXNzYWdlID0gJ05vIG1hdGNoIGZvcjogJyArIGFyZy50b1N0cmluZygpO1xuICAgIH0gZWxzZSBpZiAoQXJyYXkuaXNBcnJheShhcmcpKSB7XG4gICAgICBsZXQgbWFwcGVkVmFsdWVzID0gYXJnLm1hcCh4ID0+IHgudG9TdHJpbmcoKSk7XG4gICAgICB0aGlzLm1lc3NhZ2UgPSAnTm8gbWF0Y2ggZm9yOiAnICsgbWFwcGVkVmFsdWVzO1xuICAgIH0gZWxzZSB7XG4gICAgICB0aGlzLm1lc3NhZ2UgPSAnTm8gbWF0Y2ggZm9yOiAnICsgYXJnO1xuICAgIH1cblxuICAgIHRoaXMuc3RhY2sgPSBuZXcgRXJyb3IoKS5zdGFjaztcbiAgICB0aGlzLm5hbWUgPSB0aGlzLmNvbnN0cnVjdG9yLm5hbWU7XG4gIH1cbn1cblxuZXhwb3J0IGNsYXNzIENhc2Uge1xuXG4gIGNvbnN0cnVjdG9yKHBhdHRlcm4sIGZuLCBndWFyZCA9ICgpID0+IHRydWUpIHtcbiAgICB0aGlzLnBhdHRlcm4gPSBidWlsZE1hdGNoKHBhdHRlcm4pO1xuICAgIHRoaXMuZm4gPSBmbjtcbiAgICB0aGlzLmd1YXJkID0gZ3VhcmQ7XG4gIH1cbn1cblxuZXhwb3J0IGZ1bmN0aW9uIG1ha2VfY2FzZShwYXR0ZXJuLCBmbiwgZ3VhcmQgPSAoKSA9PiB0cnVlKSB7XG4gIHJldHVybiBuZXcgQ2FzZShwYXR0ZXJuLCBmbiwgZ3VhcmQpO1xufVxuXG5leHBvcnQgZnVuY3Rpb24gZGVmbWF0Y2goLi4uY2FzZXMpIHtcbiAgcmV0dXJuIGZ1bmN0aW9uICguLi5hcmdzKSB7XG4gICAgZm9yIChsZXQgcHJvY2Vzc2VkQ2FzZSBvZiBjYXNlcykge1xuICAgICAgbGV0IHJlc3VsdCA9IFtdO1xuICAgICAgaWYgKHByb2Nlc3NlZENhc2UucGF0dGVybihhcmdzLCByZXN1bHQpICYmIHByb2Nlc3NlZENhc2UuZ3VhcmQuYXBwbHkodGhpcywgcmVzdWx0KSkge1xuICAgICAgICByZXR1cm4gcHJvY2Vzc2VkQ2FzZS5mbi5hcHBseSh0aGlzLCByZXN1bHQpO1xuICAgICAgfVxuICAgIH1cblxuICAgIHRocm93IG5ldyBNYXRjaEVycm9yKGFyZ3MpO1xuICB9O1xufVxuXG5leHBvcnQgZnVuY3Rpb24gbWF0Y2gocGF0dGVybiwgZXhwciwgZ3VhcmQgPSAoKSA9PiB0cnVlKSB7XG4gIGxldCByZXN1bHQgPSBbXTtcbiAgbGV0IHByb2Nlc3NlZFBhdHRlcm4gPSBidWlsZE1hdGNoKHBhdHRlcm4pO1xuICBpZiAocHJvY2Vzc2VkUGF0dGVybihleHByLCByZXN1bHQpICYmIGd1YXJkLmFwcGx5KHRoaXMsIHJlc3VsdCkpIHtcbiAgICByZXR1cm4gcmVzdWx0O1xuICB9IGVsc2Uge1xuICAgIHRocm93IG5ldyBNYXRjaEVycm9yKGV4cHIpO1xuICB9XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBtYXRjaF9ub190aHJvdyhwYXR0ZXJuLCBleHByLCBndWFyZCA9ICgpID0+IHRydWUpIHtcbiAgdHJ5IHtcbiAgICByZXR1cm4gbWF0Y2gocGF0dGVybiwgZXhwciwgZ3VhcmQpO1xuICB9IGNhdGNoIChlKSB7XG4gICAgaWYgKGUgaW5zdGFuY2VvZiBNYXRjaEVycm9yIHx8IGUubWVzc2FnZS5zdGFydHNXaXRoKCdObyBtYXRjaCBmb3I6JykpIHtcbiAgICAgIHJldHVybiBudWxsO1xuICAgIH1cblxuICAgIHRocm93IGU7XG4gIH1cbn1cblxuZXhwb3J0IGZ1bmN0aW9uIHBhdHRlcm5NYXAoY29sbGVjdGlvbiwgcGF0dGVybiwgZnVuLCBndWFyZCA9ICgpID0+IHRydWUpIHtcbiAgbGV0IHJldCA9IFtdO1xuXG4gIGZvciAobGV0IGVsZW0gb2YgY29sbGVjdGlvbikge1xuICAgIHRyeSB7XG4gICAgICBsZXQgcmVzdWx0ID0gZnVuLmFwcGx5KHRoaXMsIG1hdGNoKHBhdHRlcm4sIGVsZW0sIGd1YXJkKSk7XG4gICAgICByZXQgPSByZXQuY29uY2F0KHJlc3VsdCk7XG4gICAgfSBjYXRjaCAoZSkge1xuICAgICAgaWYgKCEoZSBpbnN0YW5jZW9mIE1hdGNoRXJyb3IpKSB7XG4gICAgICAgIHRocm93IGU7XG4gICAgICB9XG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIHJldDtcbn1cbi8vIyBzb3VyY2VNYXBwaW5nVVJMPWRhdGE6YXBwbGljYXRpb24vanNvbjtiYXNlNjQsZXlKMlpYSnphVzl1SWpvekxDSnpiM1Z5WTJWeklqcGJJbXhwWWk5amIzSmxMM0JoZEhSbGNtNXpMMlJsWm0xaGRHTm9MbXB6SWwwc0ltNWhiV1Z6SWpwYlhTd2liV0Z3Y0dsdVozTWlPaUk3TzBGQlJVRXNVMEZCVXl4VlFVRlVMRkZCUVRKQ0xGTkJRVE5DT3p0QlFVVkJMRTlCUVU4c1RVRkJUU3hWUVVGT0xGTkJRWGxDTEV0QlFYcENMRU5CUVN0Q08wRkJRM0JETEdOQlFWa3NSMEZCV2l4RlFVRnpRanRCUVVOd1FpeFpRVVJ2UWpzN1FVRkhjRUlzVVVGQlJ5eFBRVUZQTEVkQlFWQXNTMEZCWlN4UlFVRm1MRVZCUVhkQ08wRkJRM3BDTEZkQlFVc3NUMEZCVEN4SFFVRmxMRzFDUVVGdFFpeEpRVUZKTEZGQlFVb3NSVUZCYmtJc1EwRkVWVHRMUVVFelFpeE5RVVZQTEVsQlFVY3NUVUZCVFN4UFFVRk9MRU5CUVdNc1IwRkJaQ3hEUVVGSUxFVkJRWE5DTzBGQlF6TkNMRlZCUVVrc1pVRkJaU3hKUVVGSkxFZEJRVW9zUTBGQlVTeExRVUZQTEVWQlFVVXNVVUZCUml4RlFVRlFMRU5CUVhaQ0xFTkJSSFZDTzBGQlJUTkNMRmRCUVVzc1QwRkJUQ3hIUVVGbExHMUNRVUZ0UWl4WlFVRnVRaXhEUVVaWk8wdEJRWFJDTEUxQlIwWTdRVUZEU0N4WFFVRkxMRTlCUVV3c1IwRkJaU3h0UWtGQmJVSXNSMEZCYmtJc1EwRkVXanRMUVVoRk96dEJRVTlRTEZOQlFVc3NTMEZCVEN4SFFVRmhMRWxCUVVzc1MwRkJTaXhGUVVGRUxFTkJRV01zUzBGQlpDeERRVnBQTzBGQllYQkNMRk5CUVVzc1NVRkJUQ3hIUVVGWkxFdEJRVXNzVjBGQlRDeERRVUZwUWl4SlFVRnFRaXhEUVdKUk8wZEJRWFJDTzBOQlJFczdPMEZCYlVKUUxFOUJRVThzVFVGQlRTeEpRVUZPTEVOQlFWYzdPMEZCUzJoQ0xHTkJRVmtzVDBGQldpeEZRVUZwUXl4RlFVRnFReXhGUVVFclJDeFJRVUZGTEUxQlFVMHNTVUZCVGl4RlFVRlhPMEZCUXpGRkxGTkJRVXNzVDBGQlRDeEhRVUZsTEZkQlFWY3NUMEZCV0N4RFFVRm1MRU5CUkRCRk8wRkJSVEZGTEZOQlFVc3NSVUZCVEN4SFFVRlZMRVZCUVZZc1EwRkdNRVU3UVVGSE1VVXNVMEZCU3l4TFFVRk1MRWRCUVdFc1MwRkJZaXhEUVVnd1JUdEhRVUUxUlR0RFFVeExPenRCUVZsUUxFOUJRVThzVTBGQlV5eFRRVUZVTEVOQlFXMUNMRTlCUVc1Q0xFVkJRWGRETEVWQlFYaERMRVZCUVhORkxGRkJRVVVzVFVGQlRTeEpRVUZPTEVWQlFXdENPMEZCUXk5R0xGTkJRVThzU1VGQlNTeEpRVUZLTEVOQlFWTXNUMEZCVkN4RlFVRnJRaXhGUVVGc1FpeEZRVUZ6UWl4TFFVRjBRaXhEUVVGUUxFTkJSQ3RHTzBOQlFURkdPenRCUVVsUUxFOUJRVThzVTBGQlV5eFJRVUZVTEVOQlFXdENMRWRCUVVjc1MwRkJTQ3hGUVVGcFF6dEJRVU40UkN4VFFVRlBMRlZCUVZNc1IwRkJSeXhKUVVGSUxFVkJRVEJDTzBGQlEzaERMRk5CUVVzc1NVRkJTU3hoUVVGS0xFbEJRWEZDTEV0QlFURkNMRVZCUVdsRE8wRkJReTlDTEZWQlFVa3NVMEZCVXl4RlFVRlVMRU5CUkRKQ08wRkJSUzlDTEZWQlFVa3NZMEZCWXl4UFFVRmtMRU5CUVhOQ0xFbEJRWFJDTEVWQlFUUkNMRTFCUVRWQ0xFdEJRWFZETEdOQlFXTXNTMEZCWkN4RFFVRnZRaXhMUVVGd1FpeERRVUV3UWl4SlFVRXhRaXhGUVVGblF5eE5RVUZvUXl4RFFVRjJReXhGUVVGblJqdEJRVU5zUml4bFFVRlBMR05CUVdNc1JVRkJaQ3hEUVVGcFFpeExRVUZxUWl4RFFVRjFRaXhKUVVGMlFpeEZRVUUyUWl4TlFVRTNRaXhEUVVGUUxFTkJSR3RHTzA5QlFYQkdPMHRCUmtZN08wRkJUMEVzVlVGQlRTeEpRVUZKTEZWQlFVb3NRMEZCWlN4SlFVRm1MRU5CUVU0c1EwRlNkME03UjBGQmJrTXNRMEZFYVVRN1EwRkJia1E3TzBGQllWQXNUMEZCVHl4VFFVRlRMRXRCUVZRc1EwRkJaU3hQUVVGbUxFVkJRVFpDTEVsQlFUZENMRVZCUVhkRUxGRkJRVVVzVFVGQlRTeEpRVUZPTEVWQlFYZENPMEZCUTNaR0xFMUJRVWtzVTBGQlV5eEZRVUZVTEVOQlJHMUdPMEZCUlhaR0xFMUJRVWtzYlVKQlFXMUNMRmRCUVZjc1QwRkJXQ3hEUVVGdVFpeERRVVp0Ump0QlFVZDJSaXhOUVVGSkxHbENRVUZwUWl4SlFVRnFRaXhGUVVGMVFpeE5RVUYyUWl4TFFVRnJReXhOUVVGTkxFdEJRVTRzUTBGQldTeEpRVUZhTEVWQlFXdENMRTFCUVd4Q0xFTkJRV3hETEVWQlFUUkVPMEZCUXpsRUxGZEJRVThzVFVGQlVDeERRVVE0UkR0SFFVRm9SU3hOUVVWTE8wRkJRMGdzVlVGQlRTeEpRVUZKTEZWQlFVb3NRMEZCWlN4SlFVRm1MRU5CUVU0c1EwRkVSenRIUVVaTU8wTkJTRXM3TzBGQlZWQXNUMEZCVHl4VFFVRlRMR05CUVZRc1EwRkJkMElzVDBGQmVFSXNSVUZCYzBNc1NVRkJkRU1zUlVGQmFVVXNVVUZCUlN4TlFVRk5MRWxCUVU0c1JVRkJlVUk3UVVGRGFrY3NUVUZCUnp0QlFVTkVMRmRCUVU4c1RVRkJUU3hQUVVGT0xFVkJRV1VzU1VGQlppeEZRVUZ4UWl4TFFVRnlRaXhEUVVGUUxFTkJSRU03UjBGQlNDeERRVVZETEU5QlFVMHNRMEZCVGl4RlFVRlJPMEZCUTFBc1VVRkJSeXhoUVVGaExGVkJRV0lzU1VGQk1rSXNSVUZCUlN4UFFVRkdMRU5CUVZVc1ZVRkJWaXhEUVVGeFFpeGxRVUZ5UWl4RFFVRXpRaXhGUVVGcFJUdEJRVU5zUlN4aFFVRlBMRWxCUVZBc1EwRkVhMFU3UzBGQmNFVTdPMEZCU1VFc1ZVRkJUU3hEUVVGT0xFTkJURTg3UjBGQlVqdERRVWhKT3p0QlFWbFFMRTlCUVU4c1UwRkJVeXhWUVVGVUxFTkJRVzlDTEZWQlFYQkNMRVZCUVRSRExFOUJRVFZETEVWQlFUQkVMRWRCUVRGRUxFVkJRWGxHTEZGQlFVVXNUVUZCVFN4SlFVRk9MRVZCUVhkQ08wRkJRM2hJTEUxQlFVa3NUVUZCVFN4RlFVRk9MRU5CUkc5SU96dEJRVWQ0U0N4UFFVRkpMRWxCUVVrc1NVRkJTaXhKUVVGWkxGVkJRV2hDTEVWQlFUSkNPMEZCUTNwQ0xGRkJRVWM3UVVGRFJDeFZRVUZKTEZOQlFWTXNTVUZCU1N4TFFVRktMRU5CUVZVc1NVRkJWaXhGUVVGblFpeE5RVUZOTEU5QlFVNHNSVUZCWlN4SlFVRm1MRVZCUVhGQ0xFdEJRWEpDTEVOQlFXaENMRU5CUVZRc1EwRkVTRHRCUVVWRUxGbEJRVTBzU1VGQlNTeE5RVUZLTEVOQlFWY3NUVUZCV0N4RFFVRk9MRU5CUmtNN1MwRkJTQ3hEUVVkRExFOUJRVTBzUTBGQlRpeEZRVUZSTzBGQlExUXNWVUZCUnl4RlFVRkZMR0ZCUVdFc1ZVRkJZaXhEUVVGR0xFVkJRVEpDTzBGQlF6RkNMR05CUVUwc1EwRkJUaXhEUVVRd1FqdFBRVUU1UWp0TFFVUkRPMGRCU2tnN08wRkJWMEVzVTBGQlR5eEhRVUZRTEVOQlpIZElPME5CUVc1SUlpd2labWxzWlNJNklteHBZaTlqYjNKbEwzQmhkSFJsY201ekwyUmxabTFoZEdOb0xtcHpJaXdpYzI5MWNtTmxjME52Ym5SbGJuUWlPbHNpTHlvZ1FHWnNiM2NnS2k5Y2JseHVhVzF3YjNKMElIc2dZblZwYkdSTllYUmphQ0I5SUdaeWIyMGdYQ0l1TDIxaGRHTm9YQ0k3WEc1Y2JtVjRjRzl5ZENCamJHRnpjeUJOWVhSamFFVnljbTl5SUdWNGRHVnVaSE1nUlhKeWIzSWdlMXh1SUNCamIyNXpkSEoxWTNSdmNpaGhjbWM2SUdGdWVTa2dlMXh1SUNBZ0lITjFjR1Z5S0NrN1hHNWNiaUFnSUNCcFppaDBlWEJsYjJZZ1lYSm5JRDA5UFNBbmMzbHRZbTlzSnlsN1hHNGdJQ0FnSUNCMGFHbHpMbTFsYzNOaFoyVWdQU0FuVG04Z2JXRjBZMmdnWm05eU9pQW5JQ3NnWVhKbkxuUnZVM1J5YVc1bktDazdYRzRnSUNBZ2ZTQmxiSE5sSUdsbUtFRnljbUY1TG1selFYSnlZWGtvWVhKbktTbDdYRzRnSUNBZ0lDQnNaWFFnYldGd2NHVmtWbUZzZFdWeklEMGdZWEpuTG0xaGNDZ29lQ2tnUFQ0Z2VDNTBiMU4wY21sdVp5Z3BLVHRjYmlBZ0lDQWdJSFJvYVhNdWJXVnpjMkZuWlNBOUlDZE9ieUJ0WVhSamFDQm1iM0k2SUNjZ0t5QnRZWEJ3WldSV1lXeDFaWE03WEc0Z0lDQWdmV1ZzYzJWN1hHNGdJQ0FnSUNCMGFHbHpMbTFsYzNOaFoyVWdQU0FuVG04Z2JXRjBZMmdnWm05eU9pQW5JQ3NnWVhKbk8xeHVJQ0FnSUgxY2JseHVJQ0FnSUhSb2FYTXVjM1JoWTJzZ1BTQW9ibVYzSUVWeWNtOXlLQ2twTG5OMFlXTnJPMXh1SUNBZ0lIUm9hWE11Ym1GdFpTQTlJSFJvYVhNdVkyOXVjM1J5ZFdOMGIzSXVibUZ0WlR0Y2JpQWdmVnh1ZlZ4dVhHNWNibVY0Y0c5eWRDQmpiR0Z6Y3lCRFlYTmxJSHRjYmlBZ2NHRjBkR1Z5YmpvZ1JuVnVZM1JwYjI0N1hHNGdJR1p1T2lCR2RXNWpkR2x2Ymp0Y2JpQWdaM1ZoY21RNklFWjFibU4wYVc5dU8xeHVYRzRnSUdOdmJuTjBjblZqZEc5eUtIQmhkSFJsY200NklFRnljbUY1UEdGdWVUNHNJR1p1T2lCR2RXNWpkR2x2Yml3Z1ozVmhjbVE2SUVaMWJtTjBhVzl1SUQwZ0tDa2dQVDRnZEhKMVpTbDdYRzRnSUNBZ2RHaHBjeTV3WVhSMFpYSnVJRDBnWW5WcGJHUk5ZWFJqYUNod1lYUjBaWEp1S1R0Y2JpQWdJQ0IwYUdsekxtWnVJRDBnWm00N1hHNGdJQ0FnZEdocGN5NW5kV0Z5WkNBOUlHZDFZWEprTzF4dUlDQjlYRzU5WEc1Y2JtVjRjRzl5ZENCbWRXNWpkR2x2YmlCdFlXdGxYMk5oYzJVb2NHRjBkR1Z5YmpvZ1FYSnlZWGs4WVc1NVBpd2dabTQ2SUVaMWJtTjBhVzl1TENCbmRXRnlaRG9nUm5WdVkzUnBiMjRnUFNBb0tTQTlQaUIwY25WbEtUb2dRMkZ6WlNCN1hHNGdJSEpsZEhWeWJpQnVaWGNnUTJGelpTaHdZWFIwWlhKdUxDQm1iaXdnWjNWaGNtUXBPMXh1ZlZ4dVhHNWxlSEJ2Y25RZ1puVnVZM1JwYjI0Z1pHVm1iV0YwWTJnb0xpNHVZMkZ6WlhNNklFRnljbUY1UEVOaGMyVStLVG9nUm5WdVkzUnBiMjRnZTF4dUlDQnlaWFIxY200Z1puVnVZM1JwYjI0b0xpNHVZWEpuY3pvZ1FYSnlZWGs4WVc1NVBpazZJR0Z1ZVNCN1hHNGdJQ0FnWm05eUlDaHNaWFFnY0hKdlkyVnpjMlZrUTJGelpTQnZaaUJqWVhObGN5a2dlMXh1SUNBZ0lDQWdiR1YwSUhKbGMzVnNkQ0E5SUZ0ZE8xeHVJQ0FnSUNBZ2FXWWdLSEJ5YjJObGMzTmxaRU5oYzJVdWNHRjBkR1Z5YmloaGNtZHpMQ0J5WlhOMWJIUXBJQ1ltSUhCeWIyTmxjM05sWkVOaGMyVXVaM1ZoY21RdVlYQndiSGtvZEdocGN5d2djbVZ6ZFd4MEtTa2dlMXh1SUNBZ0lDQWdJQ0J5WlhSMWNtNGdjSEp2WTJWemMyVmtRMkZ6WlM1bWJpNWhjSEJzZVNoMGFHbHpMQ0J5WlhOMWJIUXBPMXh1SUNBZ0lDQWdmVnh1SUNBZ0lIMWNibHh1SUNBZ0lIUm9jbTkzSUc1bGR5Qk5ZWFJqYUVWeWNtOXlLR0Z5WjNNcE8xeHVJQ0I5TzF4dWZWeHVYRzVsZUhCdmNuUWdablZ1WTNScGIyNGdiV0YwWTJnb2NHRjBkR1Z5YmpvZ1lXNTVMQ0JsZUhCeU9pQmhibmtzSUdkMVlYSmtPaUJHZFc1amRHbHZiaUE5SUNncElEMCtJSFJ5ZFdVcE9pQkJjbkpoZVR4aGJuaytJSHRjYmlBZ2JHVjBJSEpsYzNWc2RDQTlJRnRkTzF4dUlDQnNaWFFnY0hKdlkyVnpjMlZrVUdGMGRHVnliaUE5SUdKMWFXeGtUV0YwWTJnb2NHRjBkR1Z5YmlrN1hHNGdJR2xtSUNod2NtOWpaWE56WldSUVlYUjBaWEp1S0dWNGNISXNJSEpsYzNWc2RDa2dKaVlnWjNWaGNtUXVZWEJ3Ykhrb2RHaHBjeXdnY21WemRXeDBLU2w3WEc0Z0lDQWdjbVYwZFhKdUlISmxjM1ZzZER0Y2JpQWdmV1ZzYzJWN1hHNGdJQ0FnZEdoeWIzY2dibVYzSUUxaGRHTm9SWEp5YjNJb1pYaHdjaWs3WEc0Z0lIMWNibjFjYmx4dVpYaHdiM0owSUdaMWJtTjBhVzl1SUcxaGRHTm9YMjV2WDNSb2NtOTNLSEJoZEhSbGNtNDZJR0Z1ZVN3Z1pYaHdjam9nWVc1NUxDQm5kV0Z5WkRvZ1JuVnVZM1JwYjI0Z1BTQW9LU0E5UGlCMGNuVmxLVG9nUDBGeWNtRjVQR0Z1ZVQ0Z2UxeHVJQ0IwY25sN1hHNGdJQ0FnY21WMGRYSnVJRzFoZEdOb0tIQmhkSFJsY200c0lHVjRjSElzSUdkMVlYSmtLVHRjYmlBZ2ZXTmhkR05vS0dVcGUxeHVJQ0FnSUdsbUtHVWdhVzV6ZEdGdVkyVnZaaUJOWVhSamFFVnljbTl5SUh4OElHVXViV1Z6YzJGblpTNXpkR0Z5ZEhOWGFYUm9LQ2RPYnlCdFlYUmphQ0JtYjNJNkp5a3BlMXh1SUNBZ0lDQWdjbVYwZFhKdUlHNTFiR3c3WEc0Z0lDQWdmVnh1WEc0Z0lDQWdkR2h5YjNjZ1pUdGNiaUFnZlZ4dWZWeHVYRzVsZUhCdmNuUWdablZ1WTNScGIyNGdjR0YwZEdWeWJrMWhjQ2hqYjJ4c1pXTjBhVzl1T2lCQmNuSmhlVHhoYm5rK0xDQndZWFIwWlhKdU9pQmhibmtzSUdaMWJqb2dSblZ1WTNScGIyNHNJR2QxWVhKa09pQkdkVzVqZEdsdmJpQTlJQ2dwSUQwK0lIUnlkV1VwT2lCQmNuSmhlVHhoYm5rK0lIdGNiaUFnYkdWMElISmxkQ0E5SUZ0ZE8xeHVYRzRnSUdadmNpaHNaWFFnWld4bGJTQnZaaUJqYjJ4c1pXTjBhVzl1S1h0Y2JpQWdJQ0IwY25sN1hHNGdJQ0FnSUNCc1pYUWdjbVZ6ZFd4MElEMGdablZ1TG1Gd2NHeDVLSFJvYVhNc0lHMWhkR05vS0hCaGRIUmxjbTRzSUdWc1pXMHNJR2QxWVhKa0tTazdYRzRnSUNBZ0lDQnlaWFFnUFNCeVpYUXVZMjl1WTJGMEtISmxjM1ZzZENrN1hHNGdJQ0FnZldOaGRHTm9LR1VwZTF4dUlDQWdJR2xtS0NFb1pTQnBibk4wWVc1alpXOW1JRTFoZEdOb1JYSnliM0lwS1h0Y2JpQWdJQ0FnSUNBZ2RHaHliM2NnWlR0Y2JpQWdJQ0FnSUgxY2JpQWdJQ0I5WEc0Z0lIMWNibHh1SUNCeVpYUjFjbTRnY21WME8xeHVmVnh1SWwwc0luTnZkWEpqWlZKdmIzUWlPaUl2YzI5MWNtTmxMeUo5XG4iLCJcblxuaW1wb3J0IHsgZGVmbWF0Y2gsIG1hdGNoLCBNYXRjaEVycm9yLCBtYXRjaF9ub190aHJvdywgcGF0dGVybk1hcCwgQ2FzZSwgbWFrZV9jYXNlIH0gZnJvbSBcIi4vcGF0dGVybnMvZGVmbWF0Y2hcIjtcbmltcG9ydCB7IHZhcmlhYmxlLCB3aWxkY2FyZCwgc3RhcnRzV2l0aCwgY2FwdHVyZSwgaGVhZFRhaWwsIHR5cGUsIGJvdW5kIH0gZnJvbSBcIi4vcGF0dGVybnMvdHlwZXNcIjtcblxuZXhwb3J0IGRlZmF1bHQge1xuICBkZWZtYXRjaCwgbWF0Y2gsIE1hdGNoRXJyb3IsIG1hdGNoX25vX3Rocm93LFxuICB2YXJpYWJsZSwgd2lsZGNhcmQsIHN0YXJ0c1dpdGgsXG4gIGNhcHR1cmUsIGhlYWRUYWlsLCB0eXBlLCBib3VuZCwgQ2FzZSwgbWFrZV9jYXNlXG59O1xuLy8jIHNvdXJjZU1hcHBpbmdVUkw9ZGF0YTphcHBsaWNhdGlvbi9qc29uO2Jhc2U2NCxleUoyWlhKemFXOXVJam96TENKemIzVnlZMlZ6SWpwYklteHBZaTlqYjNKbEwzQmhkSFJsY201ekxtcHpJbDBzSW01aGJXVnpJanBiWFN3aWJXRndjR2x1WjNNaU9pSTdPMEZCUlVFc1UwRkJVeXhSUVVGVUxFVkJRVzFDTEV0QlFXNUNMRVZCUVRCQ0xGVkJRVEZDTEVWQlFYTkRMR05CUVhSRExFVkJRWE5FTEZWQlFYUkVMRVZCUVd0RkxFbEJRV3hGTEVWQlFYZEZMRk5CUVhoRkxGRkJRWGxHTEhGQ1FVRjZSanRCUVVOQkxGTkJRVk1zVVVGQlZDeEZRVUZ0UWl4UlFVRnVRaXhGUVVFMlFpeFZRVUUzUWl4RlFVRjVReXhQUVVGNlF5eEZRVUZyUkN4UlFVRnNSQ3hGUVVFMFJDeEpRVUUxUkN4RlFVRnJSU3hMUVVGc1JTeFJRVUVyUlN4clFrRkJMMFU3TzBGQlIwRXNaVUZCWlR0QlFVTmlMRlZCUkdFc1JVRkRTQ3hMUVVSSExFVkJRMGtzVlVGRVNpeEZRVU5uUWl4alFVUm9RanRCUVVWaUxGVkJSbUVzUlVGRlNDeFJRVVpITEVWQlJVOHNWVUZHVUR0QlFVZGlMRk5CU0dFc1JVRkhTaXhSUVVoSkxFVkJSMDBzU1VGSVRpeEZRVWRaTEV0QlNGb3NSVUZIYlVJc1NVRklia0lzUlVGSGVVSXNVMEZJZWtJN1EwRkJaaUlzSW1acGJHVWlPaUpzYVdJdlkyOXlaUzl3WVhSMFpYSnVjeTVxY3lJc0luTnZkWEpqWlhORGIyNTBaVzUwSWpwYklpOHFJRUJtYkc5M0lDb3ZYRzVjYm1sdGNHOXlkQ0I3SUdSbFptMWhkR05vTENCdFlYUmphQ3dnVFdGMFkyaEZjbkp2Y2l3Z2JXRjBZMmhmYm05ZmRHaHliM2NzSUhCaGRIUmxjbTVOWVhBc0lFTmhjMlVzSUcxaGEyVmZZMkZ6WlNCOUlHWnliMjBnWENJdUwzQmhkSFJsY201ekwyUmxabTFoZEdOb1hDSTdYRzVwYlhCdmNuUWdleUIyWVhKcFlXSnNaU3dnZDJsc1pHTmhjbVFzSUhOMFlYSjBjMWRwZEdnc0lHTmhjSFIxY21Vc0lHaGxZV1JVWVdsc0xDQjBlWEJsTENCaWIzVnVaQ0I5SUdaeWIyMGdYQ0l1TDNCaGRIUmxjbTV6TDNSNWNHVnpYQ0k3WEc1Y2JseHVaWGh3YjNKMElHUmxabUYxYkhRZ2UxeHVJQ0JrWldadFlYUmphQ3dnYldGMFkyZ3NJRTFoZEdOb1JYSnliM0lzSUcxaGRHTm9YMjV2WDNSb2NtOTNMRnh1SUNCMllYSnBZV0pzWlN3Z2QybHNaR05oY21Rc0lITjBZWEowYzFkcGRHZ3NYRzRnSUdOaGNIUjFjbVVzSUdobFlXUlVZV2xzTENCMGVYQmxMQ0JpYjNWdVpDd2dRMkZ6WlN3Z2JXRnJaVjlqWVhObFhHNTlPMXh1SWwwc0luTnZkWEpqWlZKdmIzUWlPaUl2YzI5MWNtTmxMeUo5XG4iLCJpbXBvcnQgeyBJbnRlZ2VyLCBGbG9hdCB9IGZyb20gJy4vcHJpbWl0aXZlcyc7XG5cbi8vaHR0cHM6Ly9naXRodWIuY29tL2FpcnBvcnR5aC9wcm90b21vcnBoaXNtXG5jbGFzcyBQcm90b2NvbCB7XG4gIGNvbnN0cnVjdG9yKHNwZWMpIHtcbiAgICB0aGlzLnJlZ2lzdHJ5ID0gbmV3IE1hcCgpO1xuICAgIHRoaXMuZmFsbGJhY2sgPSBudWxsO1xuXG4gICAgZm9yIChsZXQgZnVuTmFtZSBpbiBzcGVjKSB7XG4gICAgICB0aGlzW2Z1bk5hbWVdID0gY3JlYXRlRnVuKGZ1bk5hbWUpLmJpbmQodGhpcyk7XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gY3JlYXRlRnVuKGZ1bk5hbWUpIHtcblxuICAgICAgcmV0dXJuIGZ1bmN0aW9uICguLi5hcmdzKSB7XG4gICAgICAgIGxldCB0aGluZyA9IGFyZ3NbMF07XG4gICAgICAgIGxldCBmdW4gPSBudWxsO1xuXG4gICAgICAgIGlmIChOdW1iZXIuaXNJbnRlZ2VyKHRoaW5nKSAmJiB0aGlzLmhhc0ltcGxlbWVudGF0aW9uKEludGVnZXIpKSB7XG4gICAgICAgICAgZnVuID0gdGhpcy5yZWdpc3RyeS5nZXQoSW50ZWdlcilbZnVuTmFtZV07XG4gICAgICAgIH0gZWxzZSBpZiAodHlwZW9mIHRoaW5nID09PSBcIm51bWJlclwiICYmICFOdW1iZXIuaXNJbnRlZ2VyKHRoaW5nKSAmJiB0aGlzLmhhc0ltcGxlbWVudGF0aW9uKEZsb2F0KSkge1xuICAgICAgICAgIGZ1biA9IHRoaXMucmVnaXN0cnkuZ2V0KEZsb2F0KVtmdW5OYW1lXTtcbiAgICAgICAgfSBlbHNlIGlmICh0aGlzLmhhc0ltcGxlbWVudGF0aW9uKHRoaW5nKSkge1xuICAgICAgICAgIGZ1biA9IHRoaXMucmVnaXN0cnkuZ2V0KHRoaW5nLmNvbnN0cnVjdG9yKVtmdW5OYW1lXTtcbiAgICAgICAgfSBlbHNlIGlmICh0aGlzLmZhbGxiYWNrKSB7XG4gICAgICAgICAgZnVuID0gdGhpcy5mYWxsYmFja1tmdW5OYW1lXTtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmIChmdW4gIT0gbnVsbCkge1xuICAgICAgICAgIGxldCByZXR2YWwgPSBmdW4uYXBwbHkodGhpcywgYXJncyk7XG4gICAgICAgICAgcmV0dXJuIHJldHZhbDtcbiAgICAgICAgfVxuXG4gICAgICAgIHRocm93IG5ldyBFcnJvcihcIk5vIGltcGxlbWVudGF0aW9uIGZvdW5kIGZvciBcIiArIHRoaW5nKTtcbiAgICAgIH07XG4gICAgfVxuICB9XG5cbiAgaW1wbGVtZW50YXRpb24odHlwZSwgaW1wbGVtZW50YXRpb24pIHtcbiAgICBpZiAodHlwZSA9PT0gbnVsbCkge1xuICAgICAgdGhpcy5mYWxsYmFjayA9IGltcGxlbWVudGF0aW9uO1xuICAgIH0gZWxzZSB7XG4gICAgICB0aGlzLnJlZ2lzdHJ5LnNldCh0eXBlLCBpbXBsZW1lbnRhdGlvbik7XG4gICAgfVxuICB9XG5cbiAgaGFzSW1wbGVtZW50YXRpb24odGhpbmcpIHtcbiAgICBpZiAodGhpbmcgPT09IEludGVnZXIgfHwgdGhpbmcgPT09IEZsb2F0KSB7XG4gICAgICByZXR1cm4gdGhpcy5yZWdpc3RyeS5oYXModGhpbmcpO1xuICAgIH1cblxuICAgIHJldHVybiB0aGlzLnJlZ2lzdHJ5Lmhhcyh0aGluZy5jb25zdHJ1Y3Rvcik7XG4gIH1cbn1cblxuZXhwb3J0IGRlZmF1bHQgUHJvdG9jb2w7XG4vLyMgc291cmNlTWFwcGluZ1VSTD1kYXRhOmFwcGxpY2F0aW9uL2pzb247YmFzZTY0LGV5SjJaWEp6YVc5dUlqb3pMQ0p6YjNWeVkyVnpJanBiSW14cFlpOWpiM0psTDNCeWIzUnZZMjlzTG1weklsMHNJbTVoYldWeklqcGJYU3dpYldGd2NHbHVaM01pT2lKQlFVRkJMRk5CUVZNc1QwRkJWQ3hGUVVGclFpeExRVUZzUWl4UlFVRXJRaXhqUVVFdlFqczdPMEZCUjBFc1RVRkJUU3hSUVVGT0xFTkJRV003UVVGRFdpeGpRVUZaTEVsQlFWb3NSVUZCYVVJN1FVRkRaaXhUUVVGTExGRkJRVXdzUjBGQlowSXNTVUZCU1N4SFFVRktMRVZCUVdoQ0xFTkJSR1U3UVVGRlppeFRRVUZMTEZGQlFVd3NSMEZCWjBJc1NVRkJhRUlzUTBGR1pUczdRVUZKWml4VFFVRkxMRWxCUVVrc1QwRkJTaXhKUVVGbExFbEJRWEJDTEVWQlFYbENPMEZCUTNaQ0xGZEJRVXNzVDBGQlRDeEpRVUZuUWl4VlFVRlZMRTlCUVZZc1JVRkJiVUlzU1VGQmJrSXNRMEZCZDBJc1NVRkJlRUlzUTBGQmFFSXNRMEZFZFVJN1MwRkJla0k3TzBGQlNVRXNZVUZCVXl4VFFVRlVMRU5CUVcxQ0xFOUJRVzVDTEVWQlFUSkNPenRCUVVWNlFpeGhRVUZQTEZWQlFWTXNSMEZCUnl4SlFVRklMRVZCUVZNN1FVRkRka0lzV1VGQlNTeFJRVUZSTEV0QlFVc3NRMEZCVEN4RFFVRlNMRU5CUkcxQ08wRkJSWFpDTEZsQlFVa3NUVUZCVFN4SlFVRk9MRU5CUm0xQ096dEJRVWwyUWl4WlFVRkhMRTlCUVU4c1UwRkJVQ3hEUVVGcFFpeExRVUZxUWl4TFFVRXlRaXhMUVVGTExHbENRVUZNTEVOQlFYVkNMRTlCUVhaQ0xFTkJRVE5DTEVWQlFUSkVPMEZCUXpWRUxHZENRVUZOTEV0QlFVc3NVVUZCVEN4RFFVRmpMRWRCUVdRc1EwRkJhMElzVDBGQmJFSXNSVUZCTWtJc1QwRkJNMElzUTBGQlRpeERRVVEwUkR0VFFVRTVSQ3hOUVVWTkxFbEJRVWNzVDBGQlR5eExRVUZRTEV0QlFXbENMRkZCUVdwQ0xFbEJRVFpDTEVOQlFVTXNUMEZCVHl4VFFVRlFMRU5CUVdsQ0xFdEJRV3BDTEVOQlFVUXNTVUZCTkVJc1MwRkJTeXhwUWtGQlRDeERRVUYxUWl4TFFVRjJRaXhEUVVGNlJDeEZRVUYxUmp0QlFVTTVSaXhuUWtGQlRTeExRVUZMTEZGQlFVd3NRMEZCWXl4SFFVRmtMRU5CUVd0Q0xFdEJRV3hDTEVWQlFYbENMRTlCUVhwQ0xFTkJRVTRzUTBGRU9FWTdVMEZCTVVZc1RVRkZRU3hKUVVGSExFdEJRVXNzYVVKQlFVd3NRMEZCZFVJc1MwRkJka0lzUTBGQlNDeEZRVUZwUXp0QlFVTnlReXhuUWtGQlRTeExRVUZMTEZGQlFVd3NRMEZCWXl4SFFVRmtMRU5CUVd0Q0xFMUJRVTBzVjBGQlRpeERRVUZzUWl4RFFVRnhReXhQUVVGeVF5eERRVUZPTEVOQlJIRkRPMU5CUVdwRExFMUJSVUVzU1VGQlJ5eExRVUZMTEZGQlFVd3NSVUZCWXp0QlFVTnlRaXhuUWtGQlRTeExRVUZMTEZGQlFVd3NRMEZCWXl4UFFVRmtMRU5CUVU0c1EwRkVjVUk3VTBGQmFrSTdPMEZCU1U0c1dVRkJSeXhQUVVGUExFbEJRVkFzUlVGQldUdEJRVU5pTEdOQlFVa3NVMEZCVXl4SlFVRkpMRXRCUVVvc1EwRkJWU3hKUVVGV0xFVkJRV2RDTEVsQlFXaENMRU5CUVZRc1EwRkVVenRCUVVWaUxHbENRVUZQTEUxQlFWQXNRMEZHWVR0VFFVRm1PenRCUVV0QkxHTkJRVTBzU1VGQlNTeExRVUZLTEVOQlFWVXNhVU5CUVdsRExFdEJRV3BETEVOQlFXaENMRU5CYmtKMVFqdFBRVUZzUWl4RFFVWnJRanRMUVVFelFqdEhRVkpHT3p0QlFXdERRU3hwUWtGQlpTeEpRVUZtTEVWQlFYRkNMR05CUVhKQ0xFVkJRVzlETzBGQlEyeERMRkZCUVVjc1UwRkJVeXhKUVVGVUxFVkJRV003UVVGRFppeFhRVUZMTEZGQlFVd3NSMEZCWjBJc1kwRkJhRUlzUTBGRVpUdExRVUZxUWl4TlFVVkxPMEZCUTBnc1YwRkJTeXhSUVVGTUxFTkJRV01zUjBGQlpDeERRVUZyUWl4SlFVRnNRaXhGUVVGM1FpeGpRVUY0UWl4RlFVUkhPMHRCUmt3N1IwRkVSanM3UVVGUlFTeHZRa0ZCYTBJc1MwRkJiRUlzUlVGQmVVSTdRVUZEZGtJc1VVRkJTU3hWUVVGVkxFOUJRVllzU1VGQmNVSXNWVUZCVlN4TFFVRldMRVZCUVdkQ08wRkJRM1pETEdGQlFVOHNTMEZCU3l4UlFVRk1MRU5CUVdNc1IwRkJaQ3hEUVVGclFpeExRVUZzUWl4RFFVRlFMRU5CUkhWRE8wdEJRWHBET3p0QlFVbEJMRmRCUVU4c1MwRkJTeXhSUVVGTUxFTkJRV01zUjBGQlpDeERRVUZyUWl4TlFVRk5MRmRCUVU0c1EwRkJla0lzUTBGTWRVSTdSMEZCZWtJN1EwRXpRMFk3TzBGQmNVUkJMR1ZCUVdVc1VVRkJaaUlzSW1acGJHVWlPaUpzYVdJdlkyOXlaUzl3Y205MGIyTnZiQzVxY3lJc0luTnZkWEpqWlhORGIyNTBaVzUwSWpwYkltbHRjRzl5ZENCN0lFbHVkR1ZuWlhJc0lFWnNiMkYwSUgwZ1puSnZiU0FuTGk5d2NtbHRhWFJwZG1Wekp6dGNibHh1THk5b2RIUndjem92TDJkcGRHaDFZaTVqYjIwdllXbHljRzl5ZEhsb0wzQnliM1J2Ylc5eWNHaHBjMjFjYm1Oc1lYTnpJRkJ5YjNSdlkyOXNlMXh1SUNCamIyNXpkSEoxWTNSdmNpaHpjR1ZqS1h0Y2JpQWdJQ0IwYUdsekxuSmxaMmx6ZEhKNUlEMGdibVYzSUUxaGNDZ3BPMXh1SUNBZ0lIUm9hWE11Wm1Gc2JHSmhZMnNnUFNCdWRXeHNPMXh1WEc0Z0lDQWdabTl5SUNoc1pYUWdablZ1VG1GdFpTQnBiaUJ6Y0dWaktYdGNiaUFnSUNBZ0lIUm9hWE5iWm5WdVRtRnRaVjBnUFNCamNtVmhkR1ZHZFc0b1puVnVUbUZ0WlNrdVltbHVaQ2gwYUdsektUdGNiaUFnSUNCOVhHNWNiaUFnSUNCbWRXNWpkR2x2YmlCamNtVmhkR1ZHZFc0b1puVnVUbUZ0WlNsN1hHNWNiaUFnSUNBZ0lISmxkSFZ5YmlCbWRXNWpkR2x2YmlndUxpNWhjbWR6S1NCN1hHNGdJQ0FnSUNBZ0lHeGxkQ0IwYUdsdVp5QTlJR0Z5WjNOYk1GMDdYRzRnSUNBZ0lDQWdJR3hsZENCbWRXNGdQU0J1ZFd4c08xeHVYRzRnSUNBZ0lDQWdJR2xtS0U1MWJXSmxjaTVwYzBsdWRHVm5aWElvZEdocGJtY3BJQ1ltSUhSb2FYTXVhR0Z6U1cxd2JHVnRaVzUwWVhScGIyNG9TVzUwWldkbGNpa3BlMXh1SUNBZ0lDQWdJQ0FnSUdaMWJpQTlJSFJvYVhNdWNtVm5hWE4wY25rdVoyVjBLRWx1ZEdWblpYSXBXMloxYms1aGJXVmRPMXh1SUNBZ0lDQWdJQ0I5Wld4elpTQnBaaWgwZVhCbGIyWWdkR2hwYm1jZ1BUMDlJRndpYm5WdFltVnlYQ0lnSmlZZ0lVNTFiV0psY2k1cGMwbHVkR1ZuWlhJb2RHaHBibWNwSUNZbUlIUm9hWE11YUdGelNXMXdiR1Z0Wlc1MFlYUnBiMjRvUm14dllYUXBLWHRjYmlBZ0lDQWdJQ0FnSUNCbWRXNGdQU0IwYUdsekxuSmxaMmx6ZEhKNUxtZGxkQ2hHYkc5aGRDbGJablZ1VG1GdFpWMDdYRzRnSUNBZ0lDQWdJSDFsYkhObElHbG1LSFJvYVhNdWFHRnpTVzF3YkdWdFpXNTBZWFJwYjI0b2RHaHBibWNwS1h0Y2JpQWdJQ0FnSUNBZ0lDQm1kVzRnUFNCMGFHbHpMbkpsWjJsemRISjVMbWRsZENoMGFHbHVaeTVqYjI1emRISjFZM1J2Y2lsYlpuVnVUbUZ0WlYwN1hHNGdJQ0FnSUNBZ0lIMWxiSE5sSUdsbUtIUm9hWE11Wm1Gc2JHSmhZMnNwZTF4dUlDQWdJQ0FnSUNBZ0lHWjFiaUE5SUhSb2FYTXVabUZzYkdKaFkydGJablZ1VG1GdFpWMDdYRzRnSUNBZ0lDQWdJSDFjYmx4dUlDQWdJQ0FnSUNCcFppaG1kVzRnSVQwZ2JuVnNiQ2w3WEc0Z0lDQWdJQ0FnSUNBZ2JHVjBJSEpsZEhaaGJDQTlJR1oxYmk1aGNIQnNlU2gwYUdsekxDQmhjbWR6S1R0Y2JpQWdJQ0FnSUNBZ0lDQnlaWFIxY200Z2NtVjBkbUZzTzF4dUlDQWdJQ0FnSUNCOVhHNWNiaUFnSUNBZ0lDQWdkR2h5YjNjZ2JtVjNJRVZ5Y205eUtGd2lUbThnYVcxd2JHVnRaVzUwWVhScGIyNGdabTkxYm1RZ1ptOXlJRndpSUNzZ2RHaHBibWNwTzF4dUlDQWdJQ0FnZlZ4dUlDQWdJSDFjYmlBZ2ZWeHVYRzRnSUdsdGNHeGxiV1Z1ZEdGMGFXOXVLSFI1Y0dVc0lHbHRjR3hsYldWdWRHRjBhVzl1S1h0Y2JpQWdJQ0JwWmloMGVYQmxJRDA5UFNCdWRXeHNLWHRjYmlBZ0lDQWdJSFJvYVhNdVptRnNiR0poWTJzZ1BTQnBiWEJzWlcxbGJuUmhkR2x2Ymp0Y2JpQWdJQ0I5Wld4elpYdGNiaUFnSUNBZ0lIUm9hWE11Y21WbmFYTjBjbmt1YzJWMEtIUjVjR1VzSUdsdGNHeGxiV1Z1ZEdGMGFXOXVLVHRjYmlBZ0lDQjlYRzRnSUgxY2JseHVJQ0JvWVhOSmJYQnNaVzFsYm5SaGRHbHZiaWgwYUdsdVp5a2dlMXh1SUNBZ0lHbG1JQ2gwYUdsdVp5QTlQVDBnU1c1MFpXZGxjaUI4ZkNCMGFHbHVaeUE5UFQwZ1JteHZZWFFwZTF4dUlDQWdJQ0FnY21WMGRYSnVJSFJvYVhNdWNtVm5hWE4wY25rdWFHRnpLSFJvYVc1bktUdGNiaUFnSUNCOVhHNWNiaUFnSUNCeVpYUjFjbTRnZEdocGN5NXlaV2RwYzNSeWVTNW9ZWE1vZEdocGJtY3VZMjl1YzNSeWRXTjBiM0lwTzF4dUlDQjlYRzU5WEc1Y2JseHVaWGh3YjNKMElHUmxabUYxYkhRZ1VISnZkRzlqYjJ3N1hHNGlYU3dpYzI5MWNtTmxVbTl2ZENJNklpOXpiM1Z5WTJVdkluMD1cbiIsImltcG9ydCB7IFR1cGxlIH0gZnJvbSAnLi9wcmltaXRpdmVzJztcbmltcG9ydCBCaXRTdHJpbmcgZnJvbSAnLi9iaXRfc3RyaW5nJztcbmltcG9ydCBQYXR0ZXJucyBmcm9tICcuL3BhdHRlcm5zJztcbmltcG9ydCBQcm90b2NvbCBmcm9tICcuL3Byb3RvY29sJztcblxuZnVuY3Rpb24gY2FsbF9wcm9wZXJ0eShpdGVtLCBwcm9wZXJ0eSkge1xuICBsZXQgcHJvcCA9IG51bGw7XG5cbiAgaWYgKHR5cGVvZiBpdGVtID09PSBcIm51bWJlclwiIHx8IHR5cGVvZiBpdGVtID09PSBcInN5bWJvbFwiIHx8IHR5cGVvZiBpdGVtID09PSBcImJvb2xlYW5cIiB8fCB0eXBlb2YgaXRlbSA9PT0gXCJzdHJpbmdcIikge1xuICAgIGlmIChpdGVtW3Byb3BlcnR5XSAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICBwcm9wID0gcHJvcGVydHk7XG4gICAgfSBlbHNlIGlmIChpdGVtW1N5bWJvbC5mb3IocHJvcGVydHkpXSAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICBwcm9wID0gU3ltYm9sLmZvcihwcm9wZXJ0eSk7XG4gICAgfVxuICB9IGVsc2Uge1xuICAgIGlmIChwcm9wZXJ0eSBpbiBpdGVtKSB7XG4gICAgICBwcm9wID0gcHJvcGVydHk7XG4gICAgfSBlbHNlIGlmIChTeW1ib2wuZm9yKHByb3BlcnR5KSBpbiBpdGVtKSB7XG4gICAgICBwcm9wID0gU3ltYm9sLmZvcihwcm9wZXJ0eSk7XG4gICAgfVxuICB9XG5cbiAgaWYgKHByb3AgPT09IG51bGwpIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoYFByb3BlcnR5ICR7IHByb3BlcnR5IH0gbm90IGZvdW5kIGluICR7IGl0ZW0gfWApO1xuICB9XG5cbiAgaWYgKGl0ZW1bcHJvcF0gaW5zdGFuY2VvZiBGdW5jdGlvbikge1xuICAgIHJldHVybiBpdGVtW3Byb3BdKCk7XG4gIH0gZWxzZSB7XG4gICAgcmV0dXJuIGl0ZW1bcHJvcF07XG4gIH1cbn1cblxuZnVuY3Rpb24gYXBwbHkoLi4uYXJncykge1xuICBpZiAoYXJncy5sZW5ndGggPT09IDIpIHtcbiAgICBhcmdzWzBdLmFwcGx5KG51bGwsIGFyZ3Muc2xpY2UoMSkpO1xuICB9IGVsc2Uge1xuICAgIGFyZ3NbMF1bYXJnc1sxXV0uYXBwbHkobnVsbCwgYXJncy5zbGljZSgyKSk7XG4gIH1cbn1cblxuZnVuY3Rpb24gY29udGFpbnMobGVmdCwgcmlnaHQpIHtcbiAgZm9yIChsZXQgeCBvZiByaWdodCkge1xuICAgIGlmIChQYXR0ZXJucy5tYXRjaF9ub190aHJvdyhsZWZ0LCB4KSAhPSBudWxsKSB7XG4gICAgICByZXR1cm4gdHJ1ZTtcbiAgICB9XG4gIH1cblxuICByZXR1cm4gZmFsc2U7XG59XG5cbmZ1bmN0aW9uIGdldF9nbG9iYWwoKSB7XG4gIGlmICh0eXBlb2Ygc2VsZiAhPT0gXCJ1bmRlZmluZWRcIikge1xuICAgIHJldHVybiBzZWxmO1xuICB9IGVsc2UgaWYgKHR5cGVvZiB3aW5kb3cgIT09IFwidW5kZWZpbmVkXCIpIHtcbiAgICByZXR1cm4gd2luZG93O1xuICB9IGVsc2UgaWYgKHR5cGVvZiBnbG9iYWwgIT09IFwidW5kZWZpbmVkXCIpIHtcbiAgICByZXR1cm4gZ2xvYmFsO1xuICB9XG5cbiAgdGhyb3cgbmV3IEVycm9yKFwiTm8gZ2xvYmFsIHN0YXRlIGZvdW5kXCIpO1xufVxuXG5mdW5jdGlvbiBkZWZzdHJ1Y3QoZGVmYXVsdHMpIHtcbiAgcmV0dXJuIGNsYXNzIHtcbiAgICBjb25zdHJ1Y3Rvcih1cGRhdGUgPSB7fSkge1xuICAgICAgbGV0IHRoZV92YWx1ZXMgPSBPYmplY3QuYXNzaWduKGRlZmF1bHRzLCB1cGRhdGUpO1xuICAgICAgT2JqZWN0LmFzc2lnbih0aGlzLCB0aGVfdmFsdWVzKTtcbiAgICB9XG5cbiAgICBzdGF0aWMgY3JlYXRlKHVwZGF0ZXMgPSB7fSkge1xuICAgICAgbGV0IHggPSBuZXcgdGhpcyh1cGRhdGVzKTtcbiAgICAgIHJldHVybiBPYmplY3QuZnJlZXplKHgpO1xuICAgIH1cbiAgfTtcbn1cblxuZnVuY3Rpb24gZGVmZXhjZXB0aW9uKGRlZmF1bHRzKSB7XG4gIHJldHVybiBjbGFzcyBleHRlbmRzIEVycm9yIHtcbiAgICBjb25zdHJ1Y3Rvcih1cGRhdGUgPSB7fSkge1xuICAgICAgbGV0IG1lc3NhZ2UgPSB1cGRhdGUubWVzc2FnZSB8fCBcIlwiO1xuICAgICAgc3VwZXIobWVzc2FnZSk7XG5cbiAgICAgIGxldCB0aGVfdmFsdWVzID0gT2JqZWN0LmFzc2lnbihkZWZhdWx0cywgdXBkYXRlKTtcbiAgICAgIE9iamVjdC5hc3NpZ24odGhpcywgdGhlX3ZhbHVlcyk7XG5cbiAgICAgIHRoaXMubmFtZSA9IHRoaXMuY29uc3RydWN0b3IubmFtZTtcbiAgICAgIHRoaXMubWVzc2FnZSA9IG1lc3NhZ2U7XG4gICAgICB0aGlzW1NwZWNpYWxGb3Jtcy5hdG9tKFwiX19leGNlcHRpb25fX1wiKV0gPSB0cnVlO1xuICAgICAgRXJyb3IuY2FwdHVyZVN0YWNrVHJhY2UodGhpcywgdGhpcy5jb25zdHJ1Y3Rvci5uYW1lKTtcbiAgICB9XG5cbiAgICBzdGF0aWMgY3JlYXRlKHVwZGF0ZXMgPSB7fSkge1xuICAgICAgbGV0IHggPSBuZXcgdGhpcyh1cGRhdGVzKTtcbiAgICAgIHJldHVybiBPYmplY3QuZnJlZXplKHgpO1xuICAgIH1cbiAgfTtcbn1cblxuZnVuY3Rpb24gZGVmcHJvdG9jb2woc3BlYykge1xuICByZXR1cm4gbmV3IFByb3RvY29sKHNwZWMpO1xufVxuXG5mdW5jdGlvbiBkZWZpbXBsKHByb3RvY29sLCB0eXBlLCBpbXBsKSB7XG4gIHByb3RvY29sLmltcGxlbWVudGF0aW9uKHR5cGUsIGltcGwpO1xufVxuXG5mdW5jdGlvbiBnZXRfb2JqZWN0X2tleXMob2JqKSB7XG4gIHJldHVybiBPYmplY3Qua2V5cyhvYmopLmNvbmNhdChPYmplY3QuZ2V0T3duUHJvcGVydHlTeW1ib2xzKG9iaikpO1xufVxuXG5mdW5jdGlvbiBpc192YWxpZF9jaGFyYWN0ZXIoY29kZXBvaW50KSB7XG4gIHRyeSB7XG4gICAgcmV0dXJuIFN0cmluZy5mcm9tQ29kZVBvaW50KGNvZGVwb2ludCkgIT0gbnVsbDtcbiAgfSBjYXRjaCAoZSkge1xuICAgIHJldHVybiBmYWxzZTtcbiAgfVxufVxuXG4vL2h0dHBzOi8vZGV2ZWxvcGVyLm1vemlsbGEub3JnL2VuLVVTL2RvY3MvV2ViL0FQSS9XaW5kb3dCYXNlNjQvQmFzZTY0X2VuY29kaW5nX2FuZF9kZWNvZGluZyNTb2x1dGlvbl8yXyVFMiU4MCU5M19yZXdyaXRlX3RoZV9ET01zX2F0b2IoKV9hbmRfYnRvYSgpX3VzaW5nX0phdmFTY3JpcHQnc19UeXBlZEFycmF5c19hbmRfVVRGLThcbmZ1bmN0aW9uIGI2NEVuY29kZVVuaWNvZGUoc3RyKSB7XG4gIHJldHVybiBidG9hKGVuY29kZVVSSUNvbXBvbmVudChzdHIpLnJlcGxhY2UoLyUoWzAtOUEtRl17Mn0pL2csIGZ1bmN0aW9uIChtYXRjaCwgcDEpIHtcbiAgICByZXR1cm4gU3RyaW5nLmZyb21DaGFyQ29kZSgnMHgnICsgcDEpO1xuICB9KSk7XG59XG5cbmZ1bmN0aW9uIGRlbGV0ZV9wcm9wZXJ0eV9mcm9tX21hcChtYXAsIHByb3BlcnR5KSB7XG4gIGxldCBuZXdfbWFwID0gT2JqZWN0LmFzc2lnbihPYmplY3QuY3JlYXRlKG1hcC5jb25zdHJ1Y3Rvci5wcm90b3R5cGUpLCBtYXApO1xuICBkZWxldGUgbmV3X21hcFtwcm9wZXJ0eV07XG5cbiAgcmV0dXJuIE9iamVjdC5mcmVlemUobmV3X21hcCk7XG59XG5cbmZ1bmN0aW9uIGNsYXNzX3RvX29iaihtYXApIHtcbiAgbGV0IG5ld19tYXAgPSBPYmplY3QuYXNzaWduKHt9LCBtYXApO1xuICByZXR1cm4gT2JqZWN0LmZyZWV6ZShuZXdfbWFwKTtcbn1cblxuZnVuY3Rpb24gYWRkX3Byb3BlcnR5X3RvX21hcChtYXAsIHByb3BlcnR5LCB2YWx1ZSkge1xuICBsZXQgbmV3X21hcCA9IE9iamVjdC5hc3NpZ24oe30sIG1hcCk7XG4gIG5ld19tYXBbcHJvcGVydHldID0gdmFsdWU7XG4gIHJldHVybiBPYmplY3QuZnJlZXplKG5ld19tYXApO1xufVxuXG5mdW5jdGlvbiB1cGRhdGVfbWFwKG1hcCwgcHJvcGVydHksIHZhbHVlKSB7XG4gIGlmIChwcm9wZXJ0eSBpbiBnZXRfb2JqZWN0X2tleXMobWFwKSkge1xuICAgIHJldHVybiBhZGRfcHJvcGVydHlfdG9fbWFwKG1hcCwgcHJvcGVydHksIHZhbHVlKTtcbiAgfVxuXG4gIHRocm93IFwibWFwIGRvZXMgbm90IGhhdmUga2V5XCI7XG59XG5cbmZ1bmN0aW9uIGJub3QoZXhwcikge1xuICByZXR1cm4gfmV4cHI7XG59XG5cbmZ1bmN0aW9uIGJhbmQobGVmdCwgcmlnaHQpIHtcbiAgcmV0dXJuIGxlZnQgJiByaWdodDtcbn1cblxuZnVuY3Rpb24gYm9yKGxlZnQsIHJpZ2h0KSB7XG4gIHJldHVybiBsZWZ0IHwgcmlnaHQ7XG59XG5cbmZ1bmN0aW9uIGJzbChsZWZ0LCByaWdodCkge1xuICByZXR1cm4gbGVmdCA8PCByaWdodDtcbn1cblxuZnVuY3Rpb24gYnNyKGxlZnQsIHJpZ2h0KSB7XG4gIHJldHVybiBsZWZ0ID4+IHJpZ2h0O1xufVxuXG5mdW5jdGlvbiBieG9yKGxlZnQsIHJpZ2h0KSB7XG4gIHJldHVybiBsZWZ0IF4gcmlnaHQ7XG59XG5cbmZ1bmN0aW9uIHppcChsaXN0X29mX2xpc3RzKSB7XG4gIGlmIChsaXN0X29mX2xpc3RzLmxlbmd0aCA9PT0gMCkge1xuICAgIHJldHVybiBPYmplY3QuZnJlZXplKFtdKTtcbiAgfVxuXG4gIGxldCBuZXdfdmFsdWUgPSBbXTtcbiAgbGV0IHNtYWxsZXN0X2xlbmd0aCA9IGxpc3Rfb2ZfbGlzdHNbMF07XG5cbiAgZm9yIChsZXQgeCBvZiBsaXN0X29mX2xpc3RzKSB7XG4gICAgaWYgKHgubGVuZ3RoIDwgc21hbGxlc3RfbGVuZ3RoKSB7XG4gICAgICBzbWFsbGVzdF9sZW5ndGggPSB4Lmxlbmd0aDtcbiAgICB9XG4gIH1cblxuICBmb3IgKGxldCBpID0gMDsgaSA8IHNtYWxsZXN0X2xlbmd0aDsgaSsrKSB7XG4gICAgbGV0IGN1cnJlbnRfdmFsdWUgPSBbXTtcbiAgICBmb3IgKGxldCBqID0gMDsgaiA8IGxpc3Rfb2ZfbGlzdHMubGVuZ3RoOyBqKyspIHtcbiAgICAgIGN1cnJlbnRfdmFsdWUucHVzaChsaXN0X29mX2xpc3RzW2pdW2ldKTtcbiAgICB9XG5cbiAgICBuZXdfdmFsdWUucHVzaChuZXcgVHVwbGUoLi4uY3VycmVudF92YWx1ZSkpO1xuICB9XG5cbiAgcmV0dXJuIE9iamVjdC5mcmVlemUobmV3X3ZhbHVlKTtcbn1cblxuZnVuY3Rpb24gY2FuX2RlY29kZTY0KGRhdGEpIHtcbiAgdHJ5IHtcbiAgICBhdG9iKGRhdGEpO1xuICAgIHJldHVybiB0cnVlO1xuICB9IGNhdGNoIChlKSB7XG4gICAgcmV0dXJuIGZhbHNlO1xuICB9XG59XG5cbmZ1bmN0aW9uIHJlbW92ZV9mcm9tX2xpc3QobGlzdCwgZWxlbWVudCkge1xuICBsZXQgZm91bmQgPSBmYWxzZTtcblxuICByZXR1cm4gbGlzdC5maWx0ZXIoZWxlbSA9PiB7XG4gICAgaWYgKCFmb3VuZCAmJiBlbGVtID09PSBlbGVtZW50KSB7XG4gICAgICBmb3VuZCA9IHRydWU7XG4gICAgICByZXR1cm4gZmFsc2U7XG4gICAgfVxuXG4gICAgcmV0dXJuIHRydWU7XG4gIH0pO1xufVxuXG5mdW5jdGlvbiBmb2xkbChmdW4sIGFjYywgbGlzdCkge1xuICBsZXQgYWNjMSA9IGFjYztcblxuICBmb3IgKGNvbnN0IGVsIG9mIGxpc3QpIHtcbiAgICBhY2MxID0gZnVuKGVsLCBhY2MxKTtcbiAgfVxuXG4gIHJldHVybiBhY2MxO1xufVxuXG5mdW5jdGlvbiBmb2xkcihmdW4sIGFjYywgbGlzdCkge1xuICBsZXQgYWNjMSA9IGFjYztcblxuICBmb3IgKGxldCBpID0gbGlzdC5sZW5ndGggLSAxOyBpID49IDA7IGktLSkge1xuICAgIGFjYzEgPSBmdW4obGlzdFtpXSwgYWNjMSk7XG4gIH1cblxuICByZXR1cm4gYWNjMTtcbn1cblxuZnVuY3Rpb24ga2V5ZmluZChrZXksIG4sIHR1cGxlbGlzdCkge1xuXG4gIGZvciAobGV0IGkgPSB0dXBsZWxpc3QubGVuZ3RoIC0gMTsgaSA+PSAwOyBpLS0pIHtcbiAgICBpZiAodHVwbGVsaXN0W2ldLmdldChuKSA9PT0ga2V5KSB7XG4gICAgICByZXR1cm4gdHVwbGVsaXN0W2ldO1xuICAgIH1cbiAgfVxuXG4gIHJldHVybiBmYWxzZTtcbn1cblxuZnVuY3Rpb24ga2V5ZGVsZXRlKGtleSwgbiwgdHVwbGVsaXN0KSB7XG5cbiAgZm9yIChsZXQgaSA9IHR1cGxlbGlzdC5sZW5ndGggLSAxOyBpID49IDA7IGktLSkge1xuICAgIGlmICh0dXBsZWxpc3RbaV0uZ2V0KG4pID09PSBrZXkpIHtcbiAgICAgIHJldHVybiB0dXBsZWxpc3QuY29uY2F0KFtdKS5zcGxpY2UoaSwgMSk7XG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIHR1cGxlbGlzdDtcbn1cblxuZnVuY3Rpb24ga2V5c3RvcmUoa2V5LCBuLCBsaXN0LCBuZXd0dXBsZSkge1xuICBmb3IgKGxldCBpID0gbGlzdC5sZW5ndGggLSAxOyBpID49IDA7IGktLSkge1xuICAgIGlmIChsaXN0W2ldLmdldChuKSA9PT0ga2V5KSB7XG4gICAgICByZXR1cm4gbGlzdC5jb25jYXQoW10pLnNwbGljZShpLCAxLCBuZXd0dXBsZSk7XG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIGxpc3QuY29uY2F0KFtdKS5wdXNoKG5ld3R1cGxlKTtcbn1cblxuZnVuY3Rpb24ga2V5bWVtYmVyKGtleSwgbiwgbGlzdCkge1xuICBmb3IgKGxldCBpID0gbGlzdC5sZW5ndGggLSAxOyBpID49IDA7IGktLSkge1xuICAgIGlmIChsaXN0W2ldLmdldChuKSA9PT0ga2V5KSB7XG4gICAgICByZXR1cm4gdHJ1ZTtcbiAgICB9XG4gIH1cblxuICByZXR1cm4gZmFsc2U7XG59XG5cbmZ1bmN0aW9uIGtleXRha2Uoa2V5LCBuLCBsaXN0KSB7XG4gIGlmICgha2V5bWVtYmVyKGtleSwgbiwgbGlzdCkpIHtcbiAgICByZXR1cm4gZmFsc2U7XG4gIH1cblxuICBsZXQgdHVwbGUgPSBrZXlmaW5kKGtleSwgbiwgbGlzdCk7XG5cbiAgcmV0dXJuIG5ldyBUdXBsZSh0dXBsZS5nZXQobiksIHR1cGxlLCBrZXlkZWxldGUoa2V5LCBuLCBsaXN0KSk7XG59XG5cbmZ1bmN0aW9uIGtleXJlcGxhY2Uoa2V5LCBuLCBsaXN0LCBuZXd0dXBsZSkge1xuXG4gIGZvciAobGV0IGkgPSB0dXBsZWxpc3QubGVuZ3RoIC0gMTsgaSA+PSAwOyBpLS0pIHtcbiAgICBpZiAodHVwbGVsaXN0W2ldLmdldChuKSA9PT0ga2V5KSB7XG4gICAgICByZXR1cm4gdHVwbGVsaXN0LmNvbmNhdChbXSkuc3BsaWNlKGksIDEsIG5ld3R1cGxlKTtcbiAgICB9XG4gIH1cblxuICByZXR1cm4gdHVwbGVsaXN0O1xufVxuXG5mdW5jdGlvbiByZXZlcnNlKGxpc3QpIHtcbiAgcmV0dXJuIGxpc3QuY29uY2F0KFtdKS5yZXZlcnNlKCk7XG59XG5cbmZ1bmN0aW9uIG1hcHNfZmluZChrZXksIG1hcCkge1xuICBpZiAoa2V5IGluIGdldF9vYmplY3Rfa2V5cyhtYXApKSB7XG4gICAgcmV0dXJuIG5ldyBUdXBsZShTeW1ib2wuZm9yKFwib2tcIiksIG1hcFtrZXldKTtcbiAgfSBlbHNlIHtcbiAgICByZXR1cm4gU3ltYm9sLmZvcihcImVycm9yXCIpO1xuICB9XG59XG5cbmZ1bmN0aW9uIGZsYXR0ZW4obGlzdCwgdGFpbCA9IFtdKSB7XG4gIGxldCBuZXdfbGlzdCA9IFtdO1xuXG4gIGZvciAobGV0IGUgb2YgbGlzdCkge1xuICAgIGlmIChpc0FycmF5KGUpKSB7XG4gICAgICBuZXdfbGlzdCA9IG5ld19saXN0LmNvbmNhdChmbGF0dGVuKGUpKTtcbiAgICB9IGVsc2Uge1xuICAgICAgbmV3X2xpc3QucHVzaChlKTtcbiAgICB9XG4gIH1cblxuICByZXR1cm4gT2JqZWN0LmZyZWV6ZShuZXdfbGlzdC5jb25jYXQodGFpbCkpO1xufVxuXG5mdW5jdGlvbiBkdXBsaWNhdGUobiwgZWxlbSkge1xuICBsZXQgbGlzdCA9IFtdO1xuXG4gIGZvciAobGV0IGkgPSAwOyBpIDwgbjsgaSsrKSB7XG4gICAgbGlzdC5wdXNoKGVsZW0pO1xuICB9XG5cbiAgcmV0dXJuIE9iamVjdC5mcmVlemUobGlzdCk7XG59XG5cbmZ1bmN0aW9uIG1hcGZvbGRsKGZ1biwgYWNjLCBsaXN0KSB7XG4gIGxldCBuZXdsaXN0ID0gW107XG5cbiAgZm9yIChsZXQgeCBvZiBsaXN0KSB7XG4gICAgbGV0IHR1cCA9IGZ1bih4LCBhY2MpO1xuICAgIG5ld2xpc3QucHVzaCh0dXAuZ2V0KDApKTtcbiAgICBhY2MgPSB0dXAuZ2V0KDEpO1xuICB9XG5cbiAgcmV0dXJuIG5ldyBUdXBsZShPYmplY3QuZnJlZXplKG5ld2xpc3QpLCBhY2MpO1xufVxuXG5mdW5jdGlvbiBmaWx0ZXJtYXAoZnVuLCBsaXN0KSB7XG4gIGxldCBuZXdsaXN0ID0gW107XG5cbiAgZm9yICh4IG9mIGxpc3QpIHtcbiAgICBsZXQgcmVzdWx0ID0gZnVuKHgpO1xuXG4gICAgaWYgKHJlc3VsdCA9PT0gdHJ1ZSkge1xuICAgICAgbmV3bGlzdC5wdXNoKHgpO1xuICAgIH0gZWxzZSBpZiAocmVzdWx0IGluc3RhbmNlb2YgVHVwbGUpIHtcbiAgICAgIG5ld2xpc3QucHVzaChyZXN1bHQuZ2V0KDEpKTtcbiAgICB9XG4gIH1cblxuICByZXR1cm4gT2JqZWN0LmZyZWV6ZShuZXdsaXN0KTtcbn1cblxuZnVuY3Rpb24gbWFwc19mb2xkKGZ1biwgYWNjLCBtYXApIHtcbiAgbGV0IGFjYzEgPSBhY2M7XG5cbiAgZm9yIChsZXQgayBvZiBnZXRfb2JqZWN0X2tleXMobWFwKSkge1xuICAgIGFjYzEgPSBmdW4oaywgbWFwW2tdLCBhY2MxKTtcbiAgfVxuXG4gIHJldHVybiBhY2MxO1xufVxuXG5mdW5jdGlvbiBtYXBzX2Zyb21fbGlzdChsaXN0KSB7XG4gIGxldCBtID0ge307XG5cbiAgZm9yICh4IG9mIGxpc3QpIHtcbiAgICBtW3guZ2V0KDApXSA9IHguZ2V0KDEpO1xuICB9XG5cbiAgcmV0dXJuIE9iamVjdC5mcmVlemUobSk7XG59XG5cbmV4cG9ydCBkZWZhdWx0IHtcbiAgY2FsbF9wcm9wZXJ0eSxcbiAgYXBwbHksXG4gIGNvbnRhaW5zLFxuICBnZXRfZ2xvYmFsLFxuICBkZWZzdHJ1Y3QsXG4gIGRlZmV4Y2VwdGlvbixcbiAgZGVmcHJvdG9jb2wsXG4gIGRlZmltcGwsXG4gIGdldF9vYmplY3Rfa2V5cyxcbiAgaXNfdmFsaWRfY2hhcmFjdGVyLFxuICBiNjRFbmNvZGVVbmljb2RlLFxuICBkZWxldGVfcHJvcGVydHlfZnJvbV9tYXAsXG4gIGFkZF9wcm9wZXJ0eV90b19tYXAsXG4gIGNsYXNzX3RvX29iaixcbiAgY2FuX2RlY29kZTY0LFxuICBibm90LFxuICBiYW5kLFxuICBib3IsXG4gIGJzbCxcbiAgYnNyLFxuICBieG9yLFxuICB6aXAsXG4gIGZvbGRsLFxuICBmb2xkcixcbiAgcmVtb3ZlX2Zyb21fbGlzdCxcbiAga2V5ZGVsZXRlLFxuICBrZXlzdG9yZSxcbiAga2V5ZmluZCxcbiAga2V5dGFrZSxcbiAga2V5cmVwbGFjZSxcbiAgcmV2ZXJzZSxcbiAgdXBkYXRlX21hcCxcbiAgbWFwc19maW5kLFxuICBmbGF0dGVuLFxuICBkdXBsaWNhdGUsXG4gIG1hcGZvbGRsLFxuICBmaWx0ZXJtYXAsXG4gIG1hcHNfZm9sZFxufTtcbi8vIyBzb3VyY2VNYXBwaW5nVVJMPWRhdGE6YXBwbGljYXRpb24vanNvbjtiYXNlNjQsZXlKMlpYSnphVzl1SWpvekxDSnpiM1Z5WTJWeklqcGJJbXhwWWk5amIzSmxMMloxYm1OMGFXOXVjeTVxY3lKZExDSnVZVzFsY3lJNlcxMHNJbTFoY0hCcGJtZHpJam9pUVVGQlFTeFRRVUZUTEV0QlFWUXNVVUZCYzBJc1kwRkJkRUk3UVVGRFFTeFBRVUZQTEZOQlFWQXNUVUZCYzBJc1kwRkJkRUk3UVVGRFFTeFBRVUZQTEZGQlFWQXNUVUZCY1VJc1dVRkJja0k3UVVGRFFTeFBRVUZQTEZGQlFWQXNUVUZCY1VJc1dVRkJja0k3TzBGQlJVRXNVMEZCVXl4aFFVRlVMRU5CUVhWQ0xFbEJRWFpDTEVWQlFUWkNMRkZCUVRkQ0xFVkJRWE5ETzBGQlEzQkRMRTFCUVVrc1QwRkJUeXhKUVVGUUxFTkJSR2RET3p0QlFVZHdReXhOUVVGSExFOUJRVThzU1VGQlVDeExRVUZuUWl4UlFVRm9RaXhKUVVFMFFpeFBRVUZQTEVsQlFWQXNTMEZCWjBJc1VVRkJhRUlzU1VGQk5FSXNUMEZCVHl4SlFVRlFMRXRCUVdkQ0xGTkJRV2hDTEVsQlFUWkNMRTlCUVU4c1NVRkJVQ3hMUVVGblFpeFJRVUZvUWl4RlFVRjVRanRCUVVNdlJ5eFJRVUZITEV0QlFVc3NVVUZCVEN4TlFVRnRRaXhUUVVGdVFpeEZRVUUyUWp0QlFVTTVRaXhoUVVGUExGRkJRVkFzUTBGRU9FSTdTMEZCYUVNc1RVRkZUU3hKUVVGSExFdEJRVXNzVDBGQlR5eEhRVUZRTEVOQlFWY3NVVUZCV0N4RFFVRk1MRTFCUVN0Q0xGTkJRUzlDTEVWQlFYbERPMEZCUTJoRUxHRkJRVThzVDBGQlR5eEhRVUZRTEVOQlFWY3NVVUZCV0N4RFFVRlFMRU5CUkdkRU8wdEJRVFZETzBkQlNGSXNUVUZOVHp0QlFVTk1MRkZCUVVjc1dVRkJXU3hKUVVGYUxFVkJRV2xDTzBGQlEyeENMR0ZCUVU4c1VVRkJVQ3hEUVVSclFqdExRVUZ3UWl4TlFVVk5MRWxCUVVjc1QwRkJUeXhIUVVGUUxFTkJRVmNzVVVGQldDeExRVUYzUWl4SlFVRjRRaXhGUVVFMlFqdEJRVU53UXl4aFFVRlBMRTlCUVU4c1IwRkJVQ3hEUVVGWExGRkJRVmdzUTBGQlVDeERRVVJ2UXp0TFFVRm9RenRIUVZSU096dEJRV05CTEUxQlFVY3NVMEZCVXl4SlFVRlVMRVZCUVdNN1FVRkRaaXhWUVVGTkxFbEJRVWtzUzBGQlNpeERRVUZWTEVOQlFVTXNVMEZCUkN4SFFVRmhMRkZCUVdJc1JVRkJkVUlzWTBGQmRrSXNSMEZCZDBNc1NVRkJlRU1zUlVGQk9FTXNRMEZCZUVRc1EwRkJUaXhEUVVSbE8wZEJRV3BDT3p0QlFVbEJMRTFCUVVjc1MwRkJTeXhKUVVGTUxHRkJRWE5DTEZGQlFYUkNMRVZCUVN0Q08wRkJRMmhETEZkQlFVOHNTMEZCU3l4SlFVRk1MRWRCUVZBc1EwRkVaME03UjBGQmJFTXNUVUZGU3p0QlFVTklMRmRCUVU4c1MwRkJTeXhKUVVGTUxFTkJRVkFzUTBGRVJ6dEhRVVpNTzBOQmNrSkdPenRCUVRSQ1FTeFRRVUZUTEV0QlFWUXNRMEZCWlN4SFFVRkhMRWxCUVVnc1JVRkJVVHRCUVVOeVFpeE5RVUZITEV0QlFVc3NUVUZCVEN4TFFVRm5RaXhEUVVGb1FpeEZRVUZyUWp0QlFVTnVRaXhUUVVGTExFTkJRVXdzUlVGQlVTeExRVUZTTEVOQlFXTXNTVUZCWkN4RlFVRnZRaXhMUVVGTExFdEJRVXdzUTBGQlZ5eERRVUZZTEVOQlFYQkNMRVZCUkcxQ08wZEJRWEpDTEUxQlJVczdRVUZEU0N4VFFVRkxMRU5CUVV3c1JVRkJVU3hMUVVGTExFTkJRVXdzUTBGQlVpeEZRVUZwUWl4TFFVRnFRaXhEUVVGMVFpeEpRVUYyUWl4RlFVRTJRaXhMUVVGTExFdEJRVXdzUTBGQlZ5eERRVUZZTEVOQlFUZENMRVZCUkVjN1IwRkdURHREUVVSR096dEJRVkZCTEZOQlFWTXNVVUZCVkN4RFFVRnJRaXhKUVVGc1FpeEZRVUYzUWl4TFFVRjRRaXhGUVVFNFFqdEJRVU0xUWl4UFFVRkpMRWxCUVVrc1EwRkJTaXhKUVVGVExFdEJRV0lzUlVGQmJVSTdRVUZEYWtJc1VVRkJSeXhUUVVGVExHTkJRVlFzUTBGQmQwSXNTVUZCZUVJc1JVRkJPRUlzUTBGQk9VSXNTMEZCYjBNc1NVRkJjRU1zUlVGQmVVTTdRVUZETVVNc1lVRkJUeXhKUVVGUUxFTkJSREJETzB0QlFUVkRPMGRCUkVZN08wRkJUVUVzVTBGQlR5eExRVUZRTEVOQlVEUkNPME5CUVRsQ096dEJRVlZCTEZOQlFWTXNWVUZCVkN4SFFVRnhRanRCUVVOdVFpeE5RVUZITEU5QlFVOHNTVUZCVUN4TFFVRnBRaXhYUVVGcVFpeEZRVUUyUWp0QlFVTTVRaXhYUVVGUExFbEJRVkFzUTBGRU9FSTdSMEZCYUVNc1RVRkZUU3hKUVVGSExFOUJRVThzVFVGQlVDeExRVUZ0UWl4WFFVRnVRaXhGUVVFclFqdEJRVU4wUXl4WFFVRlBMRTFCUVZBc1EwRkVjME03UjBGQmJFTXNUVUZGUVN4SlFVRkhMRTlCUVU4c1RVRkJVQ3hMUVVGdFFpeFhRVUZ1UWl4RlFVRXJRanRCUVVOMFF5eFhRVUZQTEUxQlFWQXNRMEZFYzBNN1IwRkJiRU03TzBGQlNVNHNVVUZCVFN4SlFVRkpMRXRCUVVvc1EwRkJWU3gxUWtGQlZpeERRVUZPTEVOQlZHMUNPME5CUVhKQ096dEJRVmxCTEZOQlFWTXNVMEZCVkN4RFFVRnRRaXhSUVVGdVFpeEZRVUUwUWp0QlFVTXhRaXhUUVVGUExFMUJRVTA3UVVGRFdDeG5Ra0ZCV1N4VFFVRlRMRVZCUVZRc1JVRkJXVHRCUVVOMFFpeFZRVUZKTEdGQlFXRXNUMEZCVHl4TlFVRlFMRU5CUVdNc1VVRkJaQ3hGUVVGM1FpeE5RVUY0UWl4RFFVRmlMRU5CUkd0Q08wRkJSWFJDTEdGQlFVOHNUVUZCVUN4RFFVRmpMRWxCUVdRc1JVRkJiMElzVlVGQmNFSXNSVUZHYzBJN1MwRkJlRUk3TzBGQlMwRXNWMEZCVHl4TlFVRlFMRU5CUVdNc1ZVRkJWU3hGUVVGV0xFVkJRV0U3UVVGRGVrSXNWVUZCU1N4SlFVRkpMRWxCUVVrc1NVRkJTaXhEUVVGVExFOUJRVlFzUTBGQlNpeERRVVJ4UWp0QlFVVjZRaXhoUVVGUExFOUJRVThzVFVGQlVDeERRVUZqTEVOQlFXUXNRMEZCVUN4RFFVWjVRanRMUVVFelFqdEhRVTVMTEVOQlJHMUNPME5CUVRWQ096dEJRV1ZCTEZOQlFWTXNXVUZCVkN4RFFVRnpRaXhSUVVGMFFpeEZRVUVyUWp0QlFVTTNRaXhUUVVGUExHTkJRV01zUzBGQlpDeERRVUZ2UWp0QlFVTjZRaXhuUWtGQldTeFRRVUZUTEVWQlFWUXNSVUZCV1R0QlFVTjBRaXhWUVVGSkxGVkJRVlVzVDBGQlR5eFBRVUZRTEVsQlFXdENMRVZCUVd4Q0xFTkJSRkU3UVVGRmRFSXNXVUZCVFN4UFFVRk9MRVZCUm5OQ096dEJRVWwwUWl4VlFVRkpMR0ZCUVdFc1QwRkJUeXhOUVVGUUxFTkJRV01zVVVGQlpDeEZRVUYzUWl4TlFVRjRRaXhEUVVGaUxFTkJTbXRDTzBGQlMzUkNMR0ZCUVU4c1RVRkJVQ3hEUVVGakxFbEJRV1FzUlVGQmIwSXNWVUZCY0VJc1JVRk1jMEk3TzBGQlQzUkNMRmRCUVVzc1NVRkJUQ3hIUVVGWkxFdEJRVXNzVjBGQlRDeERRVUZwUWl4SlFVRnFRaXhEUVZCVk8wRkJVWFJDTEZkQlFVc3NUMEZCVEN4SFFVRmxMRTlCUVdZc1EwRlNjMEk3UVVGVGRFSXNWMEZCU3l4aFFVRmhMRWxCUVdJc1EwRkJhMElzWlVGQmJFSXNRMEZCVEN4SlFVRXlReXhKUVVFelF5eERRVlJ6UWp0QlFWVjBRaXhaUVVGTkxHbENRVUZPTEVOQlFYZENMRWxCUVhoQ0xFVkJRVGhDTEV0QlFVc3NWMEZCVEN4RFFVRnBRaXhKUVVGcVFpeERRVUU1UWl4RFFWWnpRanRMUVVGNFFqczdRVUZoUVN4WFFVRlBMRTFCUVZBc1EwRkJZeXhWUVVGVkxFVkJRVllzUlVGQllUdEJRVU42UWl4VlFVRkpMRWxCUVVrc1NVRkJTU3hKUVVGS0xFTkJRVk1zVDBGQlZDeERRVUZLTEVOQlJIRkNPMEZCUlhwQ0xHRkJRVThzVDBGQlR5eE5RVUZRTEVOQlFXTXNRMEZCWkN4RFFVRlFMRU5CUm5sQ08wdEJRVE5DTzBkQlpFc3NRMEZFYzBJN1EwRkJMMEk3TzBGQmMwSkJMRk5CUVZNc1YwRkJWQ3hEUVVGeFFpeEpRVUZ5UWl4RlFVRXdRanRCUVVONFFpeFRRVUZQTEVsQlFVa3NVVUZCU2l4RFFVRmhMRWxCUVdJc1EwRkJVQ3hEUVVSM1FqdERRVUV4UWpzN1FVRkpRU3hUUVVGVExFOUJRVlFzUTBGQmFVSXNVVUZCYWtJc1JVRkJNa0lzU1VGQk0wSXNSVUZCYVVNc1NVRkJha01zUlVGQmMwTTdRVUZEY0VNc1YwRkJVeXhqUVVGVUxFTkJRWGRDTEVsQlFYaENMRVZCUVRoQ0xFbEJRVGxDTEVWQlJHOURPME5CUVhSRE96dEJRVWxCTEZOQlFWTXNaVUZCVkN4RFFVRjVRaXhIUVVGNlFpeEZRVUUyUWp0QlFVTjZRaXhUUVVGUExFOUJRVThzU1VGQlVDeERRVUZaTEVkQlFWb3NSVUZCYVVJc1RVRkJha0lzUTBGQmQwSXNUMEZCVHl4eFFrRkJVQ3hEUVVFMlFpeEhRVUUzUWl4RFFVRjRRaXhEUVVGUUxFTkJSSGxDTzBOQlFUZENPenRCUVVsQkxGTkJRVk1zYTBKQlFWUXNRMEZCTkVJc1UwRkJOVUlzUlVGQmMwTTdRVUZEY0VNc1RVRkJSenRCUVVORUxGZEJRVThzVDBGQlR5eGhRVUZRTEVOQlFYRkNMRk5CUVhKQ0xFdEJRVzFETEVsQlFXNURMRU5CUkU0N1IwRkJTQ3hEUVVWRExFOUJRVTBzUTBGQlRpeEZRVUZSTzBGQlExQXNWMEZCVHl4TFFVRlFMRU5CUkU4N1IwRkJVanREUVVoSU96czdRVUZUUVN4VFFVRlRMR2RDUVVGVUxFTkJRVEJDTEVkQlFURkNMRVZCUVN0Q08wRkJRek5DTEZOQlFVOHNTMEZCU3l4dFFrRkJiVUlzUjBGQmJrSXNSVUZCZDBJc1QwRkJlRUlzUTBGQlowTXNhVUpCUVdoRExFVkJRVzFFTEZWQlFWTXNTMEZCVkN4RlFVRm5RaXhGUVVGb1FpeEZRVUZ2UWp0QlFVTXZSU3hYUVVGUExFOUJRVThzV1VGQlVDeERRVUZ2UWl4UFFVRlBMRVZCUVZBc1EwRkJNMElzUTBGRUswVTdSMEZCY0VJc1EwRkJlRVFzUTBGQlVDeERRVVF5UWp0RFFVRXZRanM3UVVGTlFTeFRRVUZUTEhkQ1FVRlVMRU5CUVd0RExFZEJRV3hETEVWQlFYVkRMRkZCUVhaRExFVkJRV2RFTzBGQlF6VkRMRTFCUVVrc1ZVRkJWU3hQUVVGUExFMUJRVkFzUTBGQll5eFBRVUZQTEUxQlFWQXNRMEZCWXl4SlFVRkpMRmRCUVVvc1EwRkJaMElzVTBGQmFFSXNRMEZCTlVJc1JVRkJkMFFzUjBGQmVFUXNRMEZCVml4RFFVUjNRenRCUVVVMVF5eFRRVUZQTEZGQlFWRXNVVUZCVWl4RFFVRlFMRU5CUmpSRE96dEJRVWs1UXl4VFFVRlBMRTlCUVU4c1RVRkJVQ3hEUVVGakxFOUJRV1FzUTBGQlVDeERRVW80UXp0RFFVRm9SRHM3UVVGUFFTeFRRVUZUTEZsQlFWUXNRMEZCYzBJc1IwRkJkRUlzUlVGQk1FSTdRVUZEZEVJc1RVRkJTU3hWUVVGVkxFOUJRVThzVFVGQlVDeERRVUZqTEVWQlFXUXNSVUZCYTBJc1IwRkJiRUlzUTBGQlZpeERRVVJyUWp0QlFVVjRRaXhUUVVGUExFOUJRVThzVFVGQlVDeERRVUZqTEU5QlFXUXNRMEZCVUN4RFFVWjNRanREUVVFeFFqczdRVUZMUVN4VFFVRlRMRzFDUVVGVUxFTkJRVFpDTEVkQlFUZENMRVZCUVd0RExGRkJRV3hETEVWQlFUUkRMRXRCUVRWRExFVkJRV3RFTzBGQlEyaEVMRTFCUVVrc1ZVRkJWU3hQUVVGUExFMUJRVkFzUTBGQll5eEZRVUZrTEVWQlFXdENMRWRCUVd4Q0xFTkJRVllzUTBGRU5FTTdRVUZGYUVRc1ZVRkJVU3hSUVVGU0xFbEJRVzlDTEV0QlFYQkNMRU5CUm1kRU8wRkJSMmhFTEZOQlFVOHNUMEZCVHl4TlFVRlFMRU5CUVdNc1QwRkJaQ3hEUVVGUUxFTkJTR2RFTzBOQlFXeEVPenRCUVU5QkxGTkJRVk1zVlVGQlZDeERRVUZ2UWl4SFFVRndRaXhGUVVGNVFpeFJRVUY2UWl4RlFVRnRReXhMUVVGdVF5eEZRVUY1UXp0QlFVTnlReXhOUVVGSExGbEJRVmtzWjBKQlFXZENMRWRCUVdoQ0xFTkJRVm9zUlVGQmFVTTdRVUZEYUVNc1YwRkJUeXh2UWtGQmIwSXNSMEZCY0VJc1JVRkJlVUlzVVVGQmVrSXNSVUZCYlVNc1MwRkJia01zUTBGQlVDeERRVVJuUXp0SFFVRndRenM3UVVGSlFTeFJRVUZOTEhWQ1FVRk9MRU5CVEhGRE8wTkJRWHBET3p0QlFWRkJMRk5CUVZNc1NVRkJWQ3hEUVVGakxFbEJRV1FzUlVGQmJVSTdRVUZEYWtJc1UwRkJUeXhEUVVGRExFbEJRVVFzUTBGRVZUdERRVUZ1UWpzN1FVRkpRU3hUUVVGVExFbEJRVlFzUTBGQll5eEpRVUZrTEVWQlFXOUNMRXRCUVhCQ0xFVkJRVEJDTzBGQlEzaENMRk5CUVU4c1QwRkJUeXhMUVVGUUxFTkJSR2xDTzBOQlFURkNPenRCUVVsQkxGTkJRVk1zUjBGQlZDeERRVUZoTEVsQlFXSXNSVUZCYlVJc1MwRkJia0lzUlVGQmVVSTdRVUZEZGtJc1UwRkJUeXhQUVVGUExFdEJRVkFzUTBGRVowSTdRMEZCZWtJN08wRkJTVUVzVTBGQlV5eEhRVUZVTEVOQlFXRXNTVUZCWWl4RlFVRnRRaXhMUVVGdVFpeEZRVUY1UWp0QlFVTjJRaXhUUVVGUExGRkJRVkVzUzBGQlVpeERRVVJuUWp0RFFVRjZRanM3UVVGSlFTeFRRVUZUTEVkQlFWUXNRMEZCWVN4SlFVRmlMRVZCUVcxQ0xFdEJRVzVDTEVWQlFYbENPMEZCUTNaQ0xGTkJRVThzVVVGQlVTeExRVUZTTEVOQlJHZENPME5CUVhwQ096dEJRVWxCTEZOQlFWTXNTVUZCVkN4RFFVRmpMRWxCUVdRc1JVRkJiMElzUzBGQmNFSXNSVUZCTUVJN1FVRkRlRUlzVTBGQlR5eFBRVUZQTEV0QlFWQXNRMEZFYVVJN1EwRkJNVUk3TzBGQlNVRXNVMEZCVXl4SFFVRlVMRU5CUVdFc1lVRkJZaXhGUVVFeVFqdEJRVU42UWl4TlFVRkhMR05CUVdNc1RVRkJaQ3hMUVVGNVFpeERRVUY2UWl4RlFVRXlRanRCUVVNMVFpeFhRVUZQTEU5QlFVOHNUVUZCVUN4RFFVRmpMRVZCUVdRc1EwRkJVQ3hEUVVRMFFqdEhRVUU1UWpzN1FVRkpRU3hOUVVGSkxGbEJRVmtzUlVGQldpeERRVXh4UWp0QlFVMTZRaXhOUVVGSkxHdENRVUZyUWl4alFVRmpMRU5CUVdRc1EwRkJiRUlzUTBGT2NVSTdPMEZCVVhwQ0xFOUJRVWtzU1VGQlNTeERRVUZLTEVsQlFWTXNZVUZCWWl4RlFVRXlRanRCUVVONlFpeFJRVUZITEVWQlFVVXNUVUZCUml4SFFVRlhMR1ZCUVZnc1JVRkJNa0k3UVVGRE5VSXNkMEpCUVd0Q0xFVkJRVVVzVFVGQlJpeERRVVJWTzB0QlFUbENPMGRCUkVZN08wRkJUVUVzVDBGQlNTeEpRVUZKTEVsQlFVa3NRMEZCU2l4RlFVRlBMRWxCUVVrc1pVRkJTaXhGUVVGeFFpeEhRVUZ3UXl4RlFVRjNRenRCUVVOMFF5eFJRVUZKTEdkQ1FVRm5RaXhGUVVGb1FpeERRVVJyUXp0QlFVVjBReXhUUVVGSkxFbEJRVWtzU1VGQlNTeERRVUZLTEVWQlFVOHNTVUZCU1N4alFVRmpMRTFCUVdRc1JVRkJjMElzUjBGQmVrTXNSVUZCTmtNN1FVRkRNME1zYjBKQlFXTXNTVUZCWkN4RFFVRnRRaXhqUVVGakxFTkJRV1FzUlVGQmFVSXNRMEZCYWtJc1EwRkJia0lzUlVGRU1rTTdTMEZCTjBNN08wRkJTVUVzWTBGQlZTeEpRVUZXTEVOQlFXVXNTVUZCU1N4TFFVRktMRU5CUVZVc1IwRkJSeXhoUVVGSUxFTkJRWHBDTEVWQlRuTkRPMGRCUVhoRE96dEJRVk5CTEZOQlFVOHNUMEZCVHl4TlFVRlFMRU5CUVdNc1UwRkJaQ3hEUVVGUUxFTkJka0o1UWp0RFFVRXpRanM3UVVFd1FrRXNVMEZCVXl4WlFVRlVMRU5CUVhOQ0xFbEJRWFJDTEVWQlFUUkNPMEZCUXpGQ0xFMUJRVWM3UVVGRFJDeFRRVUZMTEVsQlFVd3NSVUZFUXp0QlFVVkVMRmRCUVU4c1NVRkJVQ3hEUVVaRE8wZEJRVWdzUTBGSFF5eFBRVUZOTEVOQlFVNHNSVUZCVVR0QlFVTlFMRmRCUVU4c1MwRkJVQ3hEUVVSUE8wZEJRVkk3UTBGS1NEczdRVUZUUVN4VFFVRlRMR2RDUVVGVUxFTkJRVEJDTEVsQlFURkNMRVZCUVdkRExFOUJRV2hETEVWQlFYZERPMEZCUTNCRExFMUJRVWtzVVVGQlVTeExRVUZTTEVOQlJHZERPenRCUVVkd1F5eFRRVUZQTEV0QlFVc3NUVUZCVEN4RFFVRlpMRkZCUVZVN1FVRkRla0lzVVVGQlJ5eERRVUZETEV0QlFVUXNTVUZCVlN4VFFVRlRMRTlCUVZRc1JVRkJhVUk3UVVGRE1VSXNZMEZCVVN4SlFVRlNMRU5CUkRCQ08wRkJSVEZDTEdGQlFVOHNTMEZCVUN4RFFVWXdRanRMUVVFNVFqczdRVUZMUVN4WFFVRlBMRWxCUVZBc1EwRk9lVUk3UjBGQlZpeERRVUZ1UWl4RFFVaHZRenREUVVGNFF6czdRVUZoUVN4VFFVRlRMRXRCUVZRc1EwRkJaU3hIUVVGbUxFVkJRVzlDTEVkQlFYQkNMRVZCUVhsQ0xFbEJRWHBDTEVWQlFUaENPMEZCUXpGQ0xFMUJRVWtzVDBGQlR5eEhRVUZRTEVOQlJITkNPenRCUVVjeFFpeFBRVUZKTEUxQlFVMHNSVUZCVGl4SlFVRlpMRWxCUVdoQ0xFVkJRWEZDTzBGQlEycENMRmRCUVU4c1NVRkJTU3hGUVVGS0xFVkJRVkVzU1VGQlVpeERRVUZRTEVOQlJHbENPMGRCUVhKQ096dEJRVWxCTEZOQlFVOHNTVUZCVUN4RFFWQXdRanREUVVFNVFqczdRVUZYUVN4VFFVRlRMRXRCUVZRc1EwRkJaU3hIUVVGbUxFVkJRVzlDTEVkQlFYQkNMRVZCUVhsQ0xFbEJRWHBDTEVWQlFUaENPMEZCUXpGQ0xFMUJRVWtzVDBGQlR5eEhRVUZRTEVOQlJITkNPenRCUVVjeFFpeFBRVUZKTEVsQlFVa3NTVUZCU1N4TFFVRkxMRTFCUVV3c1IwRkJZeXhEUVVGa0xFVkJRV2xDTEV0QlFVc3NRMEZCVEN4RlFVRlJMRWRCUVhKRExFVkJRWGxETzBGQlEzSkRMRmRCUVU4c1NVRkJTU3hMUVVGTExFTkJRVXdzUTBGQlNpeEZRVUZoTEVsQlFXSXNRMEZCVUN4RFFVUnhRenRIUVVGNlF6czdRVUZKUVN4VFFVRlBMRWxCUVZBc1EwRlFNRUk3UTBGQk9VSTdPMEZCVlVFc1UwRkJVeXhQUVVGVUxFTkJRV2xDTEVkQlFXcENMRVZCUVhOQ0xFTkJRWFJDTEVWQlFYbENMRk5CUVhwQ0xFVkJRVzFET3p0QlFVVnFReXhQUVVGSkxFbEJRVWtzU1VGQlNTeFZRVUZWTEUxQlFWWXNSMEZCYlVJc1EwRkJia0lzUlVGQmMwSXNTMEZCU3l4RFFVRk1MRVZCUVZFc1IwRkJNVU1zUlVGQk9FTTdRVUZETlVNc1VVRkJSeXhWUVVGVkxFTkJRVllzUlVGQllTeEhRVUZpTEVOQlFXbENMRU5CUVdwQ0xFMUJRWGRDTEVkQlFYaENMRVZCUVRSQ08wRkJRemRDTEdGQlFVOHNWVUZCVlN4RFFVRldMRU5CUVZBc1EwRkVOa0k3UzBGQkwwSTdSMEZFUmpzN1FVRk5RU3hUUVVGUExFdEJRVkFzUTBGU2FVTTdRMEZCYmtNN08wRkJWMEVzVTBGQlV5eFRRVUZVTEVOQlFXMUNMRWRCUVc1Q0xFVkJRWGRDTEVOQlFYaENMRVZCUVRKQ0xGTkJRVE5DTEVWQlFYRkRPenRCUVVWcVF5eFBRVUZKTEVsQlFVa3NTVUZCU1N4VlFVRlZMRTFCUVZZc1IwRkJiVUlzUTBGQmJrSXNSVUZCYzBJc1MwRkJTeXhEUVVGTUxFVkJRVkVzUjBGQk1VTXNSVUZCT0VNN1FVRkRNVU1zVVVGQlJ5eFZRVUZWTEVOQlFWWXNSVUZCWVN4SFFVRmlMRU5CUVdsQ0xFTkJRV3BDTEUxQlFYZENMRWRCUVhoQ0xFVkJRVFJDTzBGQlF6TkNMR0ZCUVU4c1ZVRkJWU3hOUVVGV0xFTkJRV2xDTEVWQlFXcENMRVZCUVhGQ0xFMUJRWEpDTEVOQlFUUkNMRU5CUVRWQ0xFVkJRU3RDTEVOQlFTOUNMRU5CUVZBc1EwRkVNa0k3UzBGQkwwSTdSMEZFU2pzN1FVRk5RU3hUUVVGUExGTkJRVkFzUTBGU2FVTTdRMEZCY2tNN08wRkJWMEVzVTBGQlV5eFJRVUZVTEVOQlFXdENMRWRCUVd4Q0xFVkJRWFZDTEVOQlFYWkNMRVZCUVRCQ0xFbEJRVEZDTEVWQlFXZERMRkZCUVdoRExFVkJRWGxETzBGQlEzSkRMRTlCUVVrc1NVRkJTU3hKUVVGSkxFdEJRVXNzVFVGQlRDeEhRVUZqTEVOQlFXUXNSVUZCYVVJc1MwRkJTeXhEUVVGTUxFVkJRVkVzUjBGQmNrTXNSVUZCZVVNN1FVRkRja01zVVVGQlJ5eExRVUZMTEVOQlFVd3NSVUZCVVN4SFFVRlNMRU5CUVZrc1EwRkJXaXhOUVVGdFFpeEhRVUZ1UWl4RlFVRjFRanRCUVVOMFFpeGhRVUZQTEV0QlFVc3NUVUZCVEN4RFFVRlpMRVZCUVZvc1JVRkJaMElzVFVGQmFFSXNRMEZCZFVJc1EwRkJka0lzUlVGQk1FSXNRMEZCTVVJc1JVRkJOa0lzVVVGQk4wSXNRMEZCVUN4RFFVUnpRanRMUVVFeFFqdEhRVVJLT3p0QlFVMUdMRk5CUVU4c1MwRkJTeXhOUVVGTUxFTkJRVmtzUlVGQldpeEZRVUZuUWl4SlFVRm9RaXhEUVVGeFFpeFJRVUZ5UWl4RFFVRlFMRU5CVUhWRE8wTkJRWHBET3p0QlFWVkJMRk5CUVZNc1UwRkJWQ3hEUVVGdFFpeEhRVUZ1UWl4RlFVRjNRaXhEUVVGNFFpeEZRVUV5UWl4SlFVRXpRaXhGUVVGblF6dEJRVU01UWl4UFFVRkpMRWxCUVVrc1NVRkJTU3hMUVVGTExFMUJRVXdzUjBGQll5eERRVUZrTEVWQlFXbENMRXRCUVVzc1EwRkJUQ3hGUVVGUkxFZEJRWEpETEVWQlFYbERPMEZCUTNaRExGRkJRVWNzUzBGQlN5eERRVUZNTEVWQlFWRXNSMEZCVWl4RFFVRlpMRU5CUVZvc1RVRkJiVUlzUjBGQmJrSXNSVUZCZFVJN1FVRkRlRUlzWVVGQlR5eEpRVUZRTEVOQlJIZENPMHRCUVRGQ08wZEJSRVk3TzBGQlRVRXNVMEZCVHl4TFFVRlFMRU5CVURoQ08wTkJRV2hET3p0QlFWVkJMRk5CUVZNc1QwRkJWQ3hEUVVGcFFpeEhRVUZxUWl4RlFVRnpRaXhEUVVGMFFpeEZRVUY1UWl4SlFVRjZRaXhGUVVFNFFqdEJRVU0xUWl4TlFVRkhMRU5CUVVNc1ZVRkJWU3hIUVVGV0xFVkJRV1VzUTBGQlppeEZRVUZyUWl4SlFVRnNRaXhEUVVGRUxFVkJRWGxDTzBGQlF6RkNMRmRCUVU4c1MwRkJVQ3hEUVVRd1FqdEhRVUUxUWpzN1FVRkpRU3hOUVVGSkxGRkJRVkVzVVVGQlVTeEhRVUZTTEVWQlFXRXNRMEZCWWl4RlFVRm5RaXhKUVVGb1FpeERRVUZTTEVOQlRIZENPenRCUVU4MVFpeFRRVUZQTEVsQlFVa3NTMEZCU2l4RFFVRlZMRTFCUVUwc1IwRkJUaXhEUVVGVkxFTkJRVllzUTBGQlZpeEZRVUYzUWl4TFFVRjRRaXhGUVVFclFpeFZRVUZWTEVkQlFWWXNSVUZCWlN4RFFVRm1MRVZCUVd0Q0xFbEJRV3hDTEVOQlFTOUNMRU5CUVZBc1EwRlFORUk3UTBGQk9VSTdPMEZCVlVFc1UwRkJVeXhWUVVGVUxFTkJRVzlDTEVkQlFYQkNMRVZCUVhsQ0xFTkJRWHBDTEVWQlFUUkNMRWxCUVRWQ0xFVkJRV3RETEZGQlFXeERMRVZCUVRKRE96dEJRVVY2UXl4UFFVRkpMRWxCUVVrc1NVRkJTU3hWUVVGVkxFMUJRVllzUjBGQmJVSXNRMEZCYmtJc1JVRkJjMElzUzBGQlN5eERRVUZNTEVWQlFWRXNSMEZCTVVNc1JVRkJPRU03UVVGRE5VTXNVVUZCUnl4VlFVRlZMRU5CUVZZc1JVRkJZU3hIUVVGaUxFTkJRV2xDTEVOQlFXcENMRTFCUVhkQ0xFZEJRWGhDTEVWQlFUUkNPMEZCUXpkQ0xHRkJRVThzVlVGQlZTeE5RVUZXTEVOQlFXbENMRVZCUVdwQ0xFVkJRWEZDTEUxQlFYSkNMRU5CUVRSQ0xFTkJRVFZDTEVWQlFTdENMRU5CUVM5Q0xFVkJRV3RETEZGQlFXeERMRU5CUVZBc1EwRkVOa0k3UzBGQkwwSTdSMEZFUmpzN1FVRk5RU3hUUVVGUExGTkJRVkFzUTBGU2VVTTdRMEZCTTBNN08wRkJXVUVzVTBGQlV5eFBRVUZVTEVOQlFXbENMRWxCUVdwQ0xFVkJRWE5DTzBGQlEyeENMRk5CUVU4c1MwRkJTeXhOUVVGTUxFTkJRVmtzUlVGQldpeEZRVUZuUWl4UFFVRm9RaXhGUVVGUUxFTkJSR3RDTzBOQlFYUkNPenRCUVVsQkxGTkJRVk1zVTBGQlZDeERRVUZ0UWl4SFFVRnVRaXhGUVVGM1FpeEhRVUY0UWl4RlFVRTBRanRCUVVONFFpeE5RVUZITEU5QlFVOHNaMEpCUVdkQ0xFZEJRV2hDTEVOQlFWQXNSVUZCTkVJN1FVRkRNMElzVjBGQlR5eEpRVUZKTEV0QlFVb3NRMEZCVlN4UFFVRlBMRWRCUVZBc1EwRkJWeXhKUVVGWUxFTkJRVllzUlVGQk5FSXNTVUZCU1N4SFFVRktMRU5CUVRWQ0xFTkJRVkFzUTBGRU1rSTdSMEZCTDBJc1RVRkZTenRCUVVORUxGZEJRVThzVDBGQlR5eEhRVUZRTEVOQlFWY3NUMEZCV0N4RFFVRlFMRU5CUkVNN1IwRkdURHREUVVSS096dEJRVkZCTEZOQlFWTXNUMEZCVkN4RFFVRnBRaXhKUVVGcVFpeEZRVUYxUWl4UFFVRlBMRVZCUVZBc1JVRkJWenRCUVVOb1F5eE5RVUZKTEZkQlFWY3NSVUZCV0N4RFFVUTBRanM3UVVGSGFFTXNUMEZCU1N4SlFVRkpMRU5CUVVvc1NVRkJVeXhKUVVGaUxFVkJRV3RDTzBGQlEyaENMRkZCUVVjc1VVRkJVU3hEUVVGU0xFTkJRVWdzUlVGQll6dEJRVU5hTEdsQ1FVRlhMRk5CUVZNc1RVRkJWQ3hEUVVGblFpeFJRVUZSTEVOQlFWSXNRMEZCYUVJc1EwRkJXQ3hEUVVSWk8wdEJRV1FzVFVGRlN6dEJRVU5JTEdWQlFWTXNTVUZCVkN4RFFVRmpMRU5CUVdRc1JVRkVSenRMUVVaTU8wZEJSRVk3TzBGQlVVRXNVMEZCVHl4UFFVRlBMRTFCUVZBc1EwRkJZeXhUUVVGVExFMUJRVlFzUTBGQlowSXNTVUZCYUVJc1EwRkJaQ3hEUVVGUUxFTkJXR2RETzBOQlFXeERPenRCUVdOQkxGTkJRVk1zVTBGQlZDeERRVUZ0UWl4RFFVRnVRaXhGUVVGelFpeEpRVUYwUWl4RlFVRXlRanRCUVVONlFpeE5RVUZKTEU5QlFVOHNSVUZCVUN4RFFVUnhRanM3UVVGSGVrSXNUMEZCU1N4SlFVRkpMRWxCUVVrc1EwRkJTaXhGUVVGUExFbEJRVWtzUTBGQlNpeEZRVUZQTEVkQlFYUkNMRVZCUVRCQ08wRkJRM2hDTEZOQlFVc3NTVUZCVEN4RFFVRlZMRWxCUVZZc1JVRkVkMEk3UjBGQk1VSTdPMEZCU1VFc1UwRkJUeXhQUVVGUExFMUJRVkFzUTBGQll5eEpRVUZrTEVOQlFWQXNRMEZRZVVJN1EwRkJNMEk3TzBGQlZVRXNVMEZCVXl4UlFVRlVMRU5CUVd0Q0xFZEJRV3hDTEVWQlFYVkNMRWRCUVhaQ0xFVkJRVFJDTEVsQlFUVkNMRVZCUVdsRE8wRkJReTlDTEUxQlFVa3NWVUZCVlN4RlFVRldMRU5CUkRKQ096dEJRVWN2UWl4UFFVRkpMRWxCUVVrc1EwRkJTaXhKUVVGVExFbEJRV0lzUlVGQmEwSTdRVUZEYUVJc1VVRkJTU3hOUVVGTkxFbEJRVWtzUTBGQlNpeEZRVUZQTEVkQlFWQXNRMEZCVGl4RFFVUlpPMEZCUldoQ0xGbEJRVkVzU1VGQlVpeERRVUZoTEVsQlFVa3NSMEZCU2l4RFFVRlJMRU5CUVZJc1EwRkJZaXhGUVVablFqdEJRVWRvUWl4VlFVRk5MRWxCUVVrc1IwRkJTaXhEUVVGUkxFTkJRVklzUTBGQlRpeERRVWhuUWp0SFFVRnNRanM3UVVGUFFTeFRRVUZQTEVsQlFVa3NTMEZCU2l4RFFVRlZMRTlCUVU4c1RVRkJVQ3hEUVVGakxFOUJRV1FzUTBGQlZpeEZRVUZyUXl4SFFVRnNReXhEUVVGUUxFTkJWaXRDTzBOQlFXcERPenRCUVdGQkxGTkJRVk1zVTBGQlZDeERRVUZ0UWl4SFFVRnVRaXhGUVVGM1FpeEpRVUY0UWl4RlFVRTJRanRCUVVNelFpeE5RVUZKTEZWQlFWVXNSVUZCVml4RFFVUjFRanM3UVVGSE0wSXNUMEZCU1N4RFFVRktMRWxCUVZNc1NVRkJWQ3hGUVVGak8wRkJRMW9zVVVGQlNTeFRRVUZUTEVsQlFVa3NRMEZCU2l4RFFVRlVMRU5CUkZFN08wRkJSMW9zVVVGQlJ5eFhRVUZYTEVsQlFWZ3NSVUZCWjBJN1FVRkRha0lzWTBGQlVTeEpRVUZTTEVOQlFXRXNRMEZCWWl4RlFVUnBRanRMUVVGdVFpeE5RVVZOTEVsQlFVY3NhMEpCUVd0Q0xFdEJRV3hDTEVWQlFYZENPMEZCUXk5Q0xHTkJRVkVzU1VGQlVpeERRVUZoTEU5QlFVOHNSMEZCVUN4RFFVRlhMRU5CUVZnc1EwRkJZaXhGUVVRclFqdExRVUV6UWp0SFFVeFNPenRCUVZWQkxGTkJRVThzVDBGQlR5eE5RVUZRTEVOQlFXTXNUMEZCWkN4RFFVRlFMRU5CWWpKQ08wTkJRVGRDT3p0QlFXZENRU3hUUVVGVExGTkJRVlFzUTBGQmJVSXNSMEZCYmtJc1JVRkJkMElzUjBGQmVFSXNSVUZCTmtJc1IwRkJOMElzUlVGQmFVTTdRVUZETDBJc1RVRkJTU3hQUVVGUExFZEJRVkFzUTBGRU1rSTdPMEZCUnk5Q0xFOUJRVWtzU1VGQlNTeERRVUZLTEVsQlFWTXNaMEpCUVdkQ0xFZEJRV2hDTEVOQlFXSXNSVUZCYTBNN1FVRkRhRU1zVjBGQlR5eEpRVUZKTEVOQlFVb3NSVUZCVHl4SlFVRkpMRU5CUVVvc1EwRkJVQ3hGUVVGbExFbEJRV1lzUTBGQlVDeERRVVJuUXp0SFFVRnNRenM3UVVGSlFTeFRRVUZQTEVsQlFWQXNRMEZRSzBJN1EwRkJha003TzBGQlZVRXNVMEZCVXl4alFVRlVMRU5CUVhkQ0xFbEJRWGhDTEVWQlFUWkNPMEZCUXpOQ0xFMUJRVWtzU1VGQlNTeEZRVUZLTEVOQlJIVkNPenRCUVVjelFpeFBRVUZKTEVOQlFVb3NTVUZCVXl4SlFVRlVMRVZCUVdNN1FVRkRXaXhOUVVGRkxFVkJRVVVzUjBGQlJpeERRVUZOTEVOQlFVNHNRMEZCUml4SlFVRmpMRVZCUVVVc1IwRkJSaXhEUVVGTkxFTkJRVTRzUTBGQlpDeERRVVJaTzBkQlFXUTdPMEZCU1VFc1UwRkJUeXhQUVVGUExFMUJRVkFzUTBGQll5eERRVUZrTEVOQlFWQXNRMEZRTWtJN1EwRkJOMEk3TzBGQlZVRXNaVUZCWlR0QlFVTmlMR1ZCUkdFN1FVRkZZaXhQUVVaaE8wRkJSMklzVlVGSVlUdEJRVWxpTEZsQlNtRTdRVUZMWWl4WFFVeGhPMEZCVFdJc1kwRk9ZVHRCUVU5aUxHRkJVR0U3UVVGUllpeFRRVkpoTzBGQlUySXNhVUpCVkdFN1FVRlZZaXh2UWtGV1lUdEJRVmRpTEd0Q1FWaGhPMEZCV1dJc01FSkJXbUU3UVVGaFlpeHhRa0ZpWVR0QlFXTmlMR05CWkdFN1FVRmxZaXhqUVdaaE8wRkJaMEppTEUxQmFFSmhPMEZCYVVKaUxFMUJha0poTzBGQmEwSmlMRXRCYkVKaE8wRkJiVUppTEV0QmJrSmhPMEZCYjBKaUxFdEJjRUpoTzBGQmNVSmlMRTFCY2tKaE8wRkJjMEppTEV0QmRFSmhPMEZCZFVKaUxFOUJka0poTzBGQmQwSmlMRTlCZUVKaE8wRkJlVUppTEd0Q1FYcENZVHRCUVRCQ1lpeFhRVEZDWVR0QlFUSkNZaXhWUVROQ1lUdEJRVFJDWWl4VFFUVkNZVHRCUVRaQ1lpeFRRVGRDWVR0QlFUaENZaXhaUVRsQ1lUdEJRU3RDWWl4VFFTOUNZVHRCUVdkRFlpeFpRV2hEWVR0QlFXbERZaXhYUVdwRFlUdEJRV3REWWl4VFFXeERZVHRCUVcxRFlpeFhRVzVEWVR0QlFXOURZaXhWUVhCRFlUdEJRWEZEWWl4WFFYSkRZVHRCUVhORFlpeFhRWFJEWVR0RFFVRm1JaXdpWm1sc1pTSTZJbXhwWWk5amIzSmxMMloxYm1OMGFXOXVjeTVxY3lJc0luTnZkWEpqWlhORGIyNTBaVzUwSWpwYkltbHRjRzl5ZENCN0lGUjFjR3hsSUgwZ1puSnZiU0FuTGk5d2NtbHRhWFJwZG1Wekp6dGNibWx0Y0c5eWRDQkNhWFJUZEhKcGJtY2dabkp2YlNBbkxpOWlhWFJmYzNSeWFXNW5KenRjYm1sdGNHOXlkQ0JRWVhSMFpYSnVjeUJtY205dElDY3VMM0JoZEhSbGNtNXpKenRjYm1sdGNHOXlkQ0JRY205MGIyTnZiQ0JtY205dElDY3VMM0J5YjNSdlkyOXNKenRjYmx4dVpuVnVZM1JwYjI0Z1kyRnNiRjl3Y205d1pYSjBlU2hwZEdWdExDQndjbTl3WlhKMGVTbDdYRzRnSUd4bGRDQndjbTl3SUQwZ2JuVnNiRHRjYmx4dUlDQnBaaWgwZVhCbGIyWWdhWFJsYlNBOVBUMGdYQ0p1ZFcxaVpYSmNJaUI4ZkNCMGVYQmxiMllnYVhSbGJTQTlQVDBnWENKemVXMWliMnhjSWlCOGZDQjBlWEJsYjJZZ2FYUmxiU0E5UFQwZ1hDSmliMjlzWldGdVhDSWdmSHdnZEhsd1pXOW1JR2wwWlcwZ1BUMDlJRndpYzNSeWFXNW5YQ0lwZTF4dUlDQWdJR2xtS0dsMFpXMWJjSEp2Y0dWeWRIbGRJQ0U5UFNCMWJtUmxabWx1WldRcGUxeHVJQ0FnSUNBZ2NISnZjQ0E5SUhCeWIzQmxjblI1TzF4dUlDQWdJSDFsYkhObElHbG1LR2wwWlcxYlUzbHRZbTlzTG1admNpaHdjbTl3WlhKMGVTbGRJQ0U5UFNCMWJtUmxabWx1WldRcGUxeHVJQ0FnSUNBZ2NISnZjQ0E5SUZONWJXSnZiQzVtYjNJb2NISnZjR1Z5ZEhrcE8xeHVJQ0FnSUgxY2JpQWdmU0JsYkhObElIdGNiaUFnSUNCcFppaHdjbTl3WlhKMGVTQnBiaUJwZEdWdEtYdGNiaUFnSUNBZ0lIQnliM0FnUFNCd2NtOXdaWEowZVR0Y2JpQWdJQ0I5Wld4elpTQnBaaWhUZVcxaWIyd3VabTl5S0hCeWIzQmxjblI1S1NCcGJpQnBkR1Z0S1h0Y2JpQWdJQ0FnSUhCeWIzQWdQU0JUZVcxaWIyd3VabTl5S0hCeWIzQmxjblI1S1R0Y2JpQWdJQ0I5WEc0Z0lIMWNibHh1SUNCcFppaHdjbTl3SUQwOVBTQnVkV3hzS1h0Y2JpQWdJQ0IwYUhKdmR5QnVaWGNnUlhKeWIzSW9ZRkJ5YjNCbGNuUjVJQ1I3SUhCeWIzQmxjblI1SUgwZ2JtOTBJR1p2ZFc1a0lHbHVJQ1I3SUdsMFpXMGdmV0FwT3lCY2JpQWdmVnh1WEc0Z0lHbG1LR2wwWlcxYmNISnZjRjBnYVc1emRHRnVZMlZ2WmlCR2RXNWpkR2x2YmlsN1hHNGdJQ0FnY21WMGRYSnVJR2wwWlcxYmNISnZjRjBvS1R0Y2JpQWdmV1ZzYzJWN1hHNGdJQ0FnY21WMGRYSnVJR2wwWlcxYmNISnZjRjA3WEc0Z0lIMWNibjFjYmx4dVpuVnVZM1JwYjI0Z1lYQndiSGtvTGk0dVlYSm5jeWw3WEc0Z0lHbG1LR0Z5WjNNdWJHVnVaM1JvSUQwOVBTQXlLWHRjYmlBZ0lDQmhjbWR6V3pCZExtRndjR3g1S0c1MWJHd3NJR0Z5WjNNdWMyeHBZMlVvTVNrcE8xeHVJQ0I5Wld4elpYdGNiaUFnSUNCaGNtZHpXekJkVzJGeVozTmJNVjFkTG1Gd2NHeDVLRzUxYkd3c0lHRnlaM011YzJ4cFkyVW9NaWtwTzF4dUlDQjlYRzU5WEc1Y2JtWjFibU4wYVc5dUlHTnZiblJoYVc1ektHeGxablFzSUhKcFoyaDBLWHRjYmlBZ1ptOXlLR3hsZENCNElHOW1JSEpwWjJoMEtYdGNiaUFnSUNCcFppaFFZWFIwWlhKdWN5NXRZWFJqYUY5dWIxOTBhSEp2ZHloc1pXWjBMQ0I0S1NBaFBTQnVkV3hzS1h0Y2JpQWdJQ0FnSUhKbGRIVnliaUIwY25WbE8xeHVJQ0FnSUgxY2JpQWdmVnh1WEc0Z0lISmxkSFZ5YmlCbVlXeHpaVHRjYm4xY2JseHVablZ1WTNScGIyNGdaMlYwWDJkc2IySmhiQ2dwZTF4dUlDQnBaaWgwZVhCbGIyWW9jMlZzWmlrZ0lUMDlJRndpZFc1a1pXWnBibVZrWENJcGUxeHVJQ0FnSUhKbGRIVnliaUJ6Wld4bU8xeHVJQ0I5Wld4elpTQnBaaWgwZVhCbGIyWW9kMmx1Wkc5M0tTQWhQVDBnWENKMWJtUmxabWx1WldSY0lpbDdYRzRnSUNBZ2NtVjBkWEp1SUhkcGJtUnZkenRjYmlBZ2ZXVnNjMlVnYVdZb2RIbHdaVzltS0dkc2IySmhiQ2tnSVQwOUlGd2lkVzVrWldacGJtVmtYQ0lwZTF4dUlDQWdJSEpsZEhWeWJpQm5iRzlpWVd3N1hHNGdJSDFjYmx4dUlDQjBhSEp2ZHlCdVpYY2dSWEp5YjNJb1hDSk9ieUJuYkc5aVlXd2djM1JoZEdVZ1ptOTFibVJjSWlrN1hHNTlYRzVjYm1aMWJtTjBhVzl1SUdSbFpuTjBjblZqZENoa1pXWmhkV3gwY3lsN1hHNGdJSEpsZEhWeWJpQmpiR0Z6Y3lCN1hHNGdJQ0FnWTI5dWMzUnlkV04wYjNJb2RYQmtZWFJsSUQwZ2UzMHBlMXh1SUNBZ0lDQWdiR1YwSUhSb1pWOTJZV3gxWlhNZ1BTQlBZbXBsWTNRdVlYTnphV2R1S0dSbFptRjFiSFJ6TENCMWNHUmhkR1VwTzF4dUlDQWdJQ0FnVDJKcVpXTjBMbUZ6YzJsbmJpaDBhR2x6TENCMGFHVmZkbUZzZFdWektUdGNiaUFnSUNCOVhHNWNiaUFnSUNCemRHRjBhV01nWTNKbFlYUmxLSFZ3WkdGMFpYTWdQU0I3ZlNsN1hHNGdJQ0FnSUNCc1pYUWdlQ0E5SUc1bGR5QjBhR2x6S0hWd1pHRjBaWE1wTzF4dUlDQWdJQ0FnY21WMGRYSnVJRTlpYW1WamRDNW1jbVZsZW1Vb2VDazdYRzRnSUNBZ2ZWeHVJQ0I5TzF4dWZWeHVYRzVjYm1aMWJtTjBhVzl1SUdSbFptVjRZMlZ3ZEdsdmJpaGtaV1poZFd4MGN5bDdYRzRnSUhKbGRIVnliaUJqYkdGemN5QmxlSFJsYm1SeklFVnljbTl5SUh0Y2JpQWdJQ0JqYjI1emRISjFZM1J2Y2loMWNHUmhkR1VnUFNCN2ZTbDdYRzRnSUNBZ0lDQnNaWFFnYldWemMyRm5aU0E5SUhWd1pHRjBaUzV0WlhOellXZGxJSHg4SUZ3aVhDSTdYRzRnSUNBZ0lDQnpkWEJsY2lodFpYTnpZV2RsS1R0Y2JseHVJQ0FnSUNBZ2JHVjBJSFJvWlY5MllXeDFaWE1nUFNCUFltcGxZM1F1WVhOemFXZHVLR1JsWm1GMWJIUnpMQ0IxY0dSaGRHVXBPMXh1SUNBZ0lDQWdUMkpxWldOMExtRnpjMmxuYmloMGFHbHpMQ0IwYUdWZmRtRnNkV1Z6S1R0Y2JseHVJQ0FnSUNBZ2RHaHBjeTV1WVcxbElEMGdkR2hwY3k1amIyNXpkSEoxWTNSdmNpNXVZVzFsTzF4dUlDQWdJQ0FnZEdocGN5NXRaWE56WVdkbElEMGdiV1Z6YzJGblpUdGNiaUFnSUNBZ0lIUm9hWE5iVTNCbFkybGhiRVp2Y20xekxtRjBiMjBvWENKZlgyVjRZMlZ3ZEdsdmJsOWZYQ0lwWFNBOUlIUnlkV1U3WEc0Z0lDQWdJQ0JGY25KdmNpNWpZWEIwZFhKbFUzUmhZMnRVY21GalpTaDBhR2x6TENCMGFHbHpMbU52Ym5OMGNuVmpkRzl5TG01aGJXVXBPMXh1SUNBZ0lIMWNibHh1SUNBZ0lITjBZWFJwWXlCamNtVmhkR1VvZFhCa1lYUmxjeUE5SUh0OUtYdGNiaUFnSUNBZ0lHeGxkQ0I0SUQwZ2JtVjNJSFJvYVhNb2RYQmtZWFJsY3lrN1hHNGdJQ0FnSUNCeVpYUjFjbTRnVDJKcVpXTjBMbVp5WldWNlpTaDRLVHRjYmlBZ0lDQjlYRzRnSUgwN1hHNTlYRzVjYm1aMWJtTjBhVzl1SUdSbFpuQnliM1J2WTI5c0tITndaV01wZTF4dUlDQnlaWFIxY200Z2JtVjNJRkJ5YjNSdlkyOXNLSE53WldNcE8xeHVmVnh1WEc1bWRXNWpkR2x2YmlCa1pXWnBiWEJzS0hCeWIzUnZZMjlzTENCMGVYQmxMQ0JwYlhCc0tYdGNiaUFnY0hKdmRHOWpiMnd1YVcxd2JHVnRaVzUwWVhScGIyNG9kSGx3WlN3Z2FXMXdiQ2s3WEc1OVhHNWNibVoxYm1OMGFXOXVJR2RsZEY5dlltcGxZM1JmYTJWNWN5aHZZbW9wZTF4dUlDQWdJSEpsZEhWeWJpQlBZbXBsWTNRdWEyVjVjeWh2WW1vcExtTnZibU5oZENoUFltcGxZM1F1WjJWMFQzZHVVSEp2Y0dWeWRIbFRlVzFpYjJ4ektHOWlhaWtwTzF4dWZWeHVYRzVtZFc1amRHbHZiaUJwYzE5MllXeHBaRjlqYUdGeVlXTjBaWElvWTI5a1pYQnZhVzUwS1h0Y2JpQWdkSEo1ZTF4dUlDQWdJSEpsZEhWeWJpQlRkSEpwYm1jdVpuSnZiVU52WkdWUWIybHVkQ2hqYjJSbGNHOXBiblFwSUNFOUlHNTFiR3c3WEc0Z0lIMWpZWFJqYUNobEtYdGNiaUFnSUNCeVpYUjFjbTRnWm1Gc2MyVTdYRzRnSUgxY2JuMWNibHh1THk5b2RIUndjem92TDJSbGRtVnNiM0JsY2k1dGIzcHBiR3hoTG05eVp5OWxiaTFWVXk5a2IyTnpMMWRsWWk5QlVFa3ZWMmx1Wkc5M1FtRnpaVFkwTDBKaGMyVTJORjlsYm1OdlpHbHVaMTloYm1SZlpHVmpiMlJwYm1jalUyOXNkWFJwYjI1Zk1sOGxSVElsT0RBbE9UTmZjbVYzY21sMFpWOTBhR1ZmUkU5TmMxOWhkRzlpS0NsZllXNWtYMkowYjJFb0tWOTFjMmx1WjE5S1lYWmhVMk55YVhCMEozTmZWSGx3WldSQmNuSmhlWE5mWVc1a1gxVlVSaTA0WEc1bWRXNWpkR2x2YmlCaU5qUkZibU52WkdWVmJtbGpiMlJsS0hOMGNpa2dlMXh1SUNBZ0lISmxkSFZ5YmlCaWRHOWhLR1Z1WTI5a1pWVlNTVU52YlhCdmJtVnVkQ2h6ZEhJcExuSmxjR3hoWTJVb0x5VW9XekF0T1VFdFJsMTdNbjBwTDJjc0lHWjFibU4wYVc5dUtHMWhkR05vTENCd01Ta2dlMXh1SUNBZ0lDQWdJQ0J5WlhSMWNtNGdVM1J5YVc1bkxtWnliMjFEYUdGeVEyOWtaU2duTUhnbklDc2djREVwTzF4dUlDQWdJSDBwS1R0Y2JuMWNibHh1Wm5WdVkzUnBiMjRnWkdWc1pYUmxYM0J5YjNCbGNuUjVYMlp5YjIxZmJXRndLRzFoY0N3Z2NISnZjR1Z5ZEhrcGUxeHVJQ0FnSUd4bGRDQnVaWGRmYldGd0lEMGdUMkpxWldOMExtRnpjMmxuYmloUFltcGxZM1F1WTNKbFlYUmxLRzFoY0M1amIyNXpkSEoxWTNSdmNpNXdjbTkwYjNSNWNHVXBMQ0J0WVhBcE8xeHVJQ0FnSUdSbGJHVjBaU0J1WlhkZmJXRndXM0J5YjNCbGNuUjVYVHRjYmx4dUlDQnlaWFIxY200Z1QySnFaV04wTG1aeVpXVjZaU2h1WlhkZmJXRndLVHRjYm4xY2JseHVablZ1WTNScGIyNGdZMnhoYzNOZmRHOWZiMkpxS0cxaGNDbDdYRzRnSUNBZ2JHVjBJRzVsZDE5dFlYQWdQU0JQWW1wbFkzUXVZWE56YVdkdUtIdDlMQ0J0WVhBcE8xeHVJQ0J5WlhSMWNtNGdUMkpxWldOMExtWnlaV1Y2WlNodVpYZGZiV0Z3S1R0Y2JuMWNibHh1Wm5WdVkzUnBiMjRnWVdSa1gzQnliM0JsY25SNVgzUnZYMjFoY0NodFlYQXNJSEJ5YjNCbGNuUjVMQ0IyWVd4MVpTbDdYRzRnSUd4bGRDQnVaWGRmYldGd0lEMGdUMkpxWldOMExtRnpjMmxuYmloN2ZTd2diV0Z3S1R0Y2JpQWdibVYzWDIxaGNGdHdjbTl3WlhKMGVWMGdQU0IyWVd4MVpUdGNiaUFnY21WMGRYSnVJRTlpYW1WamRDNW1jbVZsZW1Vb2JtVjNYMjFoY0NrN1hHNTlYRzVjYmx4dVpuVnVZM1JwYjI0Z2RYQmtZWFJsWDIxaGNDaHRZWEFzSUhCeWIzQmxjblI1TENCMllXeDFaU2w3WEc0Z0lDQWdhV1lvY0hKdmNHVnlkSGtnYVc0Z1oyVjBYMjlpYW1WamRGOXJaWGx6S0cxaGNDa3BlMXh1SUNBZ0lDQWdJQ0J5WlhSMWNtNGdZV1JrWDNCeWIzQmxjblI1WDNSdlgyMWhjQ2h0WVhBc0lIQnliM0JsY25SNUxDQjJZV3gxWlNrN1hHNGdJQ0FnZlZ4dVhHNGdJQ0FnZEdoeWIzY2dYQ0p0WVhBZ1pHOWxjeUJ1YjNRZ2FHRjJaU0JyWlhsY0lqdGNibjFjYmx4dVpuVnVZM1JwYjI0Z1ltNXZkQ2hsZUhCeUtYdGNiaUFnY21WMGRYSnVJSDVsZUhCeU8xeHVmVnh1WEc1bWRXNWpkR2x2YmlCaVlXNWtLR3hsWm5Rc0lISnBaMmgwS1h0Y2JpQWdjbVYwZFhKdUlHeGxablFnSmlCeWFXZG9kRHRjYm4xY2JseHVablZ1WTNScGIyNGdZbTl5S0d4bFpuUXNJSEpwWjJoMEtYdGNiaUFnY21WMGRYSnVJR3hsWm5RZ2ZDQnlhV2RvZER0Y2JuMWNibHh1Wm5WdVkzUnBiMjRnWW5Oc0tHeGxablFzSUhKcFoyaDBLWHRjYmlBZ2NtVjBkWEp1SUd4bFpuUWdQRHdnY21sbmFIUTdYRzU5WEc1Y2JtWjFibU4wYVc5dUlHSnpjaWhzWldaMExDQnlhV2RvZENsN1hHNGdJSEpsZEhWeWJpQnNaV1owSUQ0K0lISnBaMmgwTzF4dWZWeHVYRzVtZFc1amRHbHZiaUJpZUc5eUtHeGxablFzSUhKcFoyaDBLWHRjYmlBZ2NtVjBkWEp1SUd4bFpuUWdYaUJ5YVdkb2REdGNibjFjYmx4dVpuVnVZM1JwYjI0Z2VtbHdLR3hwYzNSZmIyWmZiR2x6ZEhNcGUxeHVJQ0JwWmloc2FYTjBYMjltWDJ4cGMzUnpMbXhsYm1kMGFDQTlQVDBnTUNsN1hHNGdJQ0FnY21WMGRYSnVJRTlpYW1WamRDNW1jbVZsZW1Vb1cxMHBPMXh1SUNCOVhHNWNiaUFnYkdWMElHNWxkMTkyWVd4MVpTQTlJRnRkTzF4dUlDQnNaWFFnYzIxaGJHeGxjM1JmYkdWdVozUm9JRDBnYkdsemRGOXZabDlzYVhOMGMxc3dYVHRjYmx4dUlDQm1iM0lvYkdWMElIZ2diMllnYkdsemRGOXZabDlzYVhOMGN5bDdYRzRnSUNBZ2FXWW9lQzVzWlc1bmRHZ2dQQ0J6YldGc2JHVnpkRjlzWlc1bmRHZ3BlMXh1SUNBZ0lDQWdjMjFoYkd4bGMzUmZiR1Z1WjNSb0lEMGdlQzVzWlc1bmRHZzdYRzRnSUNBZ2ZWeHVJQ0I5WEc1Y2JpQWdabTl5S0d4bGRDQnBJRDBnTURzZ2FTQThJSE50WVd4c1pYTjBYMnhsYm1kMGFEc2dhU3NyS1h0Y2JpQWdJQ0JzWlhRZ1kzVnljbVZ1ZEY5MllXeDFaU0E5SUZ0ZE8xeHVJQ0FnSUdadmNpaHNaWFFnYWlBOUlEQTdJR29nUENCc2FYTjBYMjltWDJ4cGMzUnpMbXhsYm1kMGFEc2dhaXNyS1h0Y2JpQWdJQ0FnSUdOMWNuSmxiblJmZG1Gc2RXVXVjSFZ6YUNoc2FYTjBYMjltWDJ4cGMzUnpXMnBkVzJsZEtUdGNiaUFnSUNCOVhHNWNiaUFnSUNCdVpYZGZkbUZzZFdVdWNIVnphQ2h1WlhjZ1ZIVndiR1VvTGk0dVkzVnljbVZ1ZEY5MllXeDFaU2twTzF4dUlDQjlYRzVjYmlBZ2NtVjBkWEp1SUU5aWFtVmpkQzVtY21WbGVtVW9ibVYzWDNaaGJIVmxLVHRjYm4xY2JseHVablZ1WTNScGIyNGdZMkZ1WDJSbFkyOWtaVFkwS0dSaGRHRXBJSHRjYmlBZ2RISjVlMXh1SUNBZ0lHRjBiMklvWkdGMFlTazdYRzRnSUNBZ2NtVjBkWEp1SUhSeWRXVTdYRzRnSUgxallYUmphQ2hsS1h0Y2JpQWdJQ0J5WlhSMWNtNGdabUZzYzJVN1hHNGdJSDFjYm4xY2JseHVablZ1WTNScGIyNGdjbVZ0YjNabFgyWnliMjFmYkdsemRDaHNhWE4wTENCbGJHVnRaVzUwS1h0Y2JpQWdJQ0JzWlhRZ1ptOTFibVFnUFNCbVlXeHpaVHRjYmx4dUlDQWdJSEpsZEhWeWJpQnNhWE4wTG1acGJIUmxjaWdvWld4bGJTa2dQVDRnZTF4dUlDQWdJQ0FnSUNCcFppZ2habTkxYm1RZ0ppWWdaV3hsYlNBOVBUMGdaV3hsYldWdWRDbDdYRzRnSUNBZ0lDQWdJQ0FnSUNCbWIzVnVaQ0E5SUhSeWRXVTdYRzRnSUNBZ0lDQWdJQ0FnSUNCeVpYUjFjbTRnWm1Gc2MyVTdYRzRnSUNBZ0lDQWdJSDFjYmx4dUlDQWdJQ0FnSUNCeVpYUjFjbTRnZEhKMVpUdGNiaUFnSUNCOUtUdGNibjFjYmx4dVpuVnVZM1JwYjI0Z1ptOXNaR3dvWm5WdUxDQmhZMk1zSUd4cGMzUXBlMXh1SUNBZ0lHeGxkQ0JoWTJNeElEMGdZV05qTzF4dVhHNGdJQ0FnWm05eUtHTnZibk4wSUdWc0lHOW1JR3hwYzNRcGUxeHVJQ0FnSUNBZ0lDQmhZMk14SUQwZ1puVnVLR1ZzTENCaFkyTXhLVHRjYmlBZ0lDQjlYRzVjYmlBZ0lDQnlaWFIxY200Z1lXTmpNVHRjYm4xY2JseHVYRzVtZFc1amRHbHZiaUJtYjJ4a2NpaG1kVzRzSUdGall5d2diR2x6ZENsN1hHNGdJQ0FnYkdWMElHRmpZekVnUFNCaFkyTTdYRzVjYmlBZ0lDQm1iM0lvYkdWMElHa2dQU0JzYVhOMExteGxibWQwYUNBdElERTdJR2tnUGowZ01Ec2dhUzB0S1h0Y2JpQWdJQ0FnSUNBZ1lXTmpNU0E5SUdaMWJpaHNhWE4wVzJsZExDQmhZMk14S1R0Y2JpQWdJQ0I5WEc1Y2JpQWdJQ0J5WlhSMWNtNGdZV05qTVR0Y2JuMWNibHh1Wm5WdVkzUnBiMjRnYTJWNVptbHVaQ2hyWlhrc0lHNHNJSFIxY0d4bGJHbHpkQ2w3WEc1Y2JpQWdabTl5S0d4bGRDQnBJRDBnZEhWd2JHVnNhWE4wTG14bGJtZDBhQ0F0SURFN0lHa2dQajBnTURzZ2FTMHRLWHRjYmlBZ0lDQnBaaWgwZFhCc1pXeHBjM1JiYVYwdVoyVjBLRzRwSUQwOVBTQnJaWGtwZTF4dUlDQWdJQ0FnY21WMGRYSnVJSFIxY0d4bGJHbHpkRnRwWFR0Y2JpQWdJQ0I5WEc0Z0lIMWNibHh1SUNCeVpYUjFjbTRnWm1Gc2MyVTdYRzU5WEc1Y2JtWjFibU4wYVc5dUlHdGxlV1JsYkdWMFpTaHJaWGtzSUc0c0lIUjFjR3hsYkdsemRDbDdYRzVjYmlBZ0lDQm1iM0lvYkdWMElHa2dQU0IwZFhCc1pXeHBjM1F1YkdWdVozUm9JQzBnTVRzZ2FTQStQU0F3T3lCcExTMHBlMXh1SUNBZ0lDQWdJQ0JwWmloMGRYQnNaV3hwYzNSYmFWMHVaMlYwS0c0cElEMDlQU0JyWlhrcGUxeHVJQ0FnSUNBZ0lDQWdJQ0FnY21WMGRYSnVJSFIxY0d4bGJHbHpkQzVqYjI1allYUW9XMTBwTG5Od2JHbGpaU2hwTENBeEtUdGNiaUFnSUNBZ0lDQWdmVnh1SUNBZ0lIMWNibHh1SUNBZ0lISmxkSFZ5YmlCMGRYQnNaV3hwYzNRN1hHNTlYRzVjYm1aMWJtTjBhVzl1SUd0bGVYTjBiM0psS0d0bGVTd2diaXdnYkdsemRDd2dibVYzZEhWd2JHVXBlMXh1SUNBZ0lHWnZjaWhzWlhRZ2FTQTlJR3hwYzNRdWJHVnVaM1JvSUMwZ01Uc2dhU0ErUFNBd095QnBMUzBwZTF4dUlDQWdJQ0FnSUNCcFppaHNhWE4wVzJsZExtZGxkQ2h1S1NBOVBUMGdhMlY1S1h0Y2JpQWdJQ0FnSUNBZ0lDQWdJSEpsZEhWeWJpQnNhWE4wTG1OdmJtTmhkQ2hiWFNrdWMzQnNhV05sS0drc0lERXNJRzVsZDNSMWNHeGxLVHRjYmlBZ0lDQWdJQ0FnZlZ4dUlDQWdJSDFjYmx4dUlDQnlaWFIxY200Z2JHbHpkQzVqYjI1allYUW9XMTBwTG5CMWMyZ29ibVYzZEhWd2JHVXBPMXh1ZlZ4dVhHNW1kVzVqZEdsdmJpQnJaWGx0WlcxaVpYSW9hMlY1TENCdUxDQnNhWE4wS1h0Y2JpQWdabTl5S0d4bGRDQnBJRDBnYkdsemRDNXNaVzVuZEdnZ0xTQXhPeUJwSUQ0OUlEQTdJR2t0TFNsN1hHNGdJQ0FnYVdZb2JHbHpkRnRwWFM1blpYUW9iaWtnUFQwOUlHdGxlU2w3WEc0Z0lDQWdJQ0J5WlhSMWNtNGdkSEoxWlR0Y2JpQWdJQ0I5WEc0Z0lIMWNibHh1SUNCeVpYUjFjbTRnWm1Gc2MyVTdYRzU5WEc1Y2JtWjFibU4wYVc5dUlHdGxlWFJoYTJVb2EyVjVMQ0J1TENCc2FYTjBLWHRjYmlBZ2FXWW9JV3RsZVcxbGJXSmxjaWhyWlhrc0lHNHNJR3hwYzNRcEtYdGNiaUFnSUNCeVpYUjFjbTRnWm1Gc2MyVTdYRzRnSUgxY2JseHVJQ0JzWlhRZ2RIVndiR1VnUFNCclpYbG1hVzVrS0d0bGVTd2diaXdnYkdsemRDazdYRzVjYmlBZ2NtVjBkWEp1SUc1bGR5QlVkWEJzWlNoMGRYQnNaUzVuWlhRb2Jpa3NJSFIxY0d4bExDQnJaWGxrWld4bGRHVW9hMlY1TENCdUxDQnNhWE4wS1NrN1hHNTlYRzVjYm1aMWJtTjBhVzl1SUd0bGVYSmxjR3hoWTJVb2EyVjVMQ0J1TENCc2FYTjBMQ0J1WlhkMGRYQnNaU2w3WEc0Z0lGeHVJQ0JtYjNJb2JHVjBJR2tnUFNCMGRYQnNaV3hwYzNRdWJHVnVaM1JvSUMwZ01Uc2dhU0ErUFNBd095QnBMUzBwZTF4dUlDQWdJR2xtS0hSMWNHeGxiR2x6ZEZ0cFhTNW5aWFFvYmlrZ1BUMDlJR3RsZVNsN1hHNGdJQ0FnSUNCeVpYUjFjbTRnZEhWd2JHVnNhWE4wTG1OdmJtTmhkQ2hiWFNrdWMzQnNhV05sS0drc0lERXNJRzVsZDNSMWNHeGxLVHRjYmlBZ0lDQjlYRzRnSUgxY2JseHVJQ0J5WlhSMWNtNGdkSFZ3YkdWc2FYTjBPMXh1ZlZ4dVhHNWNibVoxYm1OMGFXOXVJSEpsZG1WeWMyVW9iR2x6ZENsN1hHNGdJQ0FnY21WMGRYSnVJR3hwYzNRdVkyOXVZMkYwS0Z0ZEtTNXlaWFpsY25ObEtDazdYRzU5WEc1Y2JtWjFibU4wYVc5dUlHMWhjSE5mWm1sdVpDaHJaWGtzSUcxaGNDbDdYRzRnSUNBZ2FXWW9hMlY1SUdsdUlHZGxkRjl2WW1wbFkzUmZhMlY1Y3lodFlYQXBLWHRjYmlBZ0lDQWdJQ0FnY21WMGRYSnVJRzVsZHlCVWRYQnNaU2hUZVcxaWIyd3VabTl5S0Z3aWIydGNJaWtzSUcxaGNGdHJaWGxkS1R0Y2JpQWdJQ0I5Wld4elpYdGNiaUFnSUNBZ0lDQWdjbVYwZFhKdUlGTjViV0p2YkM1bWIzSW9YQ0psY25KdmNsd2lLVHRjYmlBZ0lDQjlYRzU5WEc1Y2JtWjFibU4wYVc5dUlHWnNZWFIwWlc0b2JHbHpkQ3dnZEdGcGJDQTlJRnRkS1NCN1hHNGdJR3hsZENCdVpYZGZiR2x6ZENBOUlGdGRPMXh1WEc0Z0lHWnZjaWhzWlhRZ1pTQnZaaUJzYVhOMEtYdGNiaUFnSUNCcFppaHBjMEZ5Y21GNUtHVXBLWHRjYmlBZ0lDQWdJRzVsZDE5c2FYTjBJRDBnYm1WM1gyeHBjM1F1WTI5dVkyRjBLR1pzWVhSMFpXNG9aU2twTzF4dUlDQWdJSDFsYkhObGUxeHVJQ0FnSUNBZ2JtVjNYMnhwYzNRdWNIVnphQ2hsS1R0Y2JpQWdJQ0I5WEc0Z0lIMWNibHh1SUNCeVpYUjFjbTRnVDJKcVpXTjBMbVp5WldWNlpTaHVaWGRmYkdsemRDNWpiMjVqWVhRb2RHRnBiQ2twTzF4dWZWeHVYRzVtZFc1amRHbHZiaUJrZFhCc2FXTmhkR1VvYml3Z1pXeGxiU2w3WEc0Z0lHeGxkQ0JzYVhOMElEMGdXMTA3WEc1Y2JpQWdabTl5S0d4bGRDQnBJRDBnTURzZ2FTQThJRzQ3SUdrckt5bDdYRzRnSUNBZ2JHbHpkQzV3ZFhOb0tHVnNaVzBwTzF4dUlDQjlYRzVjYmlBZ2NtVjBkWEp1SUU5aWFtVmpkQzVtY21WbGVtVW9iR2x6ZENrN1hHNTlYRzVjYm1aMWJtTjBhVzl1SUcxaGNHWnZiR1JzS0daMWJpd2dZV05qTENCc2FYTjBLWHRjYmlBZ2JHVjBJRzVsZDJ4cGMzUWdQU0JiWFR0Y2JseHVJQ0JtYjNJb2JHVjBJSGdnYjJZZ2JHbHpkQ2w3WEc0Z0lDQWdiR1YwSUhSMWNDQTlJR1oxYmloNExDQmhZMk1wTzF4dUlDQWdJRzVsZDJ4cGMzUXVjSFZ6YUNoMGRYQXVaMlYwS0RBcEtUdGNiaUFnSUNCaFkyTWdQU0IwZFhBdVoyVjBLREVwTzF4dUlDQjlYRzVjYmx4dUlDQnlaWFIxY200Z2JtVjNJRlIxY0d4bEtFOWlhbVZqZEM1bWNtVmxlbVVvYm1WM2JHbHpkQ2tzSUdGall5azdYRzU5WEc1Y2JtWjFibU4wYVc5dUlHWnBiSFJsY20xaGNDaG1kVzRzSUd4cGMzUXBlMXh1SUNCc1pYUWdibVYzYkdsemRDQTlJRnRkTzF4dVhHNGdJR1p2Y2loNElHOW1JR3hwYzNRcGUxeHVJQ0FnSUd4bGRDQnlaWE4xYkhRZ1BTQm1kVzRvZUNrN1hHNWNiaUFnSUNCcFppaHlaWE4xYkhRZ1BUMDlJSFJ5ZFdVcGUxeHVJQ0FnSUNBZ2JtVjNiR2x6ZEM1d2RYTm9LSGdwTzF4dUlDQWdJSDFsYkhObElHbG1LSEpsYzNWc2RDQnBibk4wWVc1alpXOW1JRlIxY0d4bEtYdGNiaUFnSUNBZ0lHNWxkMnhwYzNRdWNIVnphQ2h5WlhOMWJIUXVaMlYwS0RFcEtUdGNiaUFnSUNCOVhHNGdJSDFjYmx4dUlDQnlaWFIxY200Z1QySnFaV04wTG1aeVpXVjZaU2h1Wlhkc2FYTjBLVHRjYm4xY2JseHVablZ1WTNScGIyNGdiV0Z3YzE5bWIyeGtLR1oxYml3Z1lXTmpMQ0J0WVhBcGUxeHVJQ0JzWlhRZ1lXTmpNU0E5SUdGall6dGNibHh1SUNCbWIzSW9iR1YwSUdzZ2IyWWdaMlYwWDI5aWFtVmpkRjlyWlhsektHMWhjQ2twZTF4dUlDQWdJR0ZqWXpFZ1BTQm1kVzRvYXl3Z2JXRndXMnRkTENCaFkyTXhLVHRjYmlBZ2ZWeHVYRzRnSUhKbGRIVnliaUJoWTJNeE8xeHVmVnh1WEc1bWRXNWpkR2x2YmlCdFlYQnpYMlp5YjIxZmJHbHpkQ2hzYVhOMEtYdGNiaUFnYkdWMElHMGdQU0I3ZlR0Y2JseHVJQ0JtYjNJb2VDQnZaaUJzYVhOMEtYdGNiaUFnSUNCdFczZ3VaMlYwS0RBcFhTQTlJSGd1WjJWMEtERXBPMXh1SUNCOVhHNWNiaUFnY21WMGRYSnVJRTlpYW1WamRDNW1jbVZsZW1Vb2JTazdYRzU5WEc1Y2JtVjRjRzl5ZENCa1pXWmhkV3gwSUh0Y2JpQWdZMkZzYkY5d2NtOXdaWEowZVN4Y2JpQWdZWEJ3Ykhrc1hHNGdJR052Ym5SaGFXNXpMRnh1SUNCblpYUmZaMnh2WW1Gc0xGeHVJQ0JrWldaemRISjFZM1FzWEc0Z0lHUmxabVY0WTJWd2RHbHZiaXhjYmlBZ1pHVm1jSEp2ZEc5amIyd3NYRzRnSUdSbFptbHRjR3dzWEc0Z0lHZGxkRjl2WW1wbFkzUmZhMlY1Y3l4Y2JpQWdhWE5mZG1Gc2FXUmZZMmhoY21GamRHVnlMRnh1SUNCaU5qUkZibU52WkdWVmJtbGpiMlJsTEZ4dUlDQmtaV3hsZEdWZmNISnZjR1Z5ZEhsZlpuSnZiVjl0WVhBc1hHNGdJR0ZrWkY5d2NtOXdaWEowZVY5MGIxOXRZWEFzWEc0Z0lHTnNZWE56WDNSdlgyOWlhaXhjYmlBZ1kyRnVYMlJsWTI5a1pUWTBMRnh1SUNCaWJtOTBMRnh1SUNCaVlXNWtMRnh1SUNCaWIzSXNYRzRnSUdKemJDeGNiaUFnWW5OeUxGeHVJQ0JpZUc5eUxGeHVJQ0I2YVhBc1hHNGdJR1p2YkdSc0xGeHVJQ0JtYjJ4a2NpeGNiaUFnY21WdGIzWmxYMlp5YjIxZmJHbHpkQ3hjYmlBZ2EyVjVaR1ZzWlhSbExGeHVJQ0JyWlhsemRHOXlaU3hjYmlBZ2EyVjVabWx1WkN4Y2JpQWdhMlY1ZEdGclpTeGNiaUFnYTJWNWNtVndiR0ZqWlN4Y2JpQWdjbVYyWlhKelpTeGNiaUFnZFhCa1lYUmxYMjFoY0N4Y2JpQWdiV0Z3YzE5bWFXNWtMRnh1SUNCbWJHRjBkR1Z1TEZ4dUlDQmtkWEJzYVdOaGRHVXNYRzRnSUcxaGNHWnZiR1JzTEZ4dUlDQm1hV3gwWlhKdFlYQXNYRzRnSUcxaGNITmZabTlzWkZ4dWZUdGNiaUpkTENKemIzVnlZMlZTYjI5MElqb2lMM052ZFhKalpTOGlmUT09XG4iLCJpbXBvcnQgQml0U3RyaW5nIGZyb20gJy4vYml0X3N0cmluZyc7XG5pbXBvcnQgUGF0dGVybnMgZnJvbSAnLi9wYXR0ZXJucyc7XG5pbXBvcnQgeyBUdXBsZSB9IGZyb20gJy4vcHJpbWl0aXZlcyc7XG5cbmZ1bmN0aW9uIF9jYXNlKGNvbmRpdGlvbiwgY2xhdXNlcykge1xuICByZXR1cm4gUGF0dGVybnMuZGVmbWF0Y2goLi4uY2xhdXNlcykoY29uZGl0aW9uKTtcbn1cblxuZnVuY3Rpb24gY29uZChjbGF1c2VzKSB7XG4gIGZvciAobGV0IGNsYXVzZSBvZiBjbGF1c2VzKSB7XG4gICAgaWYgKGNsYXVzZVswXSkge1xuICAgICAgcmV0dXJuIGNsYXVzZVsxXSgpO1xuICAgIH1cbiAgfVxuXG4gIHRocm93IG5ldyBFcnJvcigpO1xufVxuXG5mdW5jdGlvbiBtYXBfdXBkYXRlKG1hcCwgdmFsdWVzKSB7XG4gIHJldHVybiBPYmplY3QuZnJlZXplKE9iamVjdC5hc3NpZ24oT2JqZWN0LmNyZWF0ZShtYXAuY29uc3RydWN0b3IucHJvdG90eXBlKSwgbWFwLCB2YWx1ZXMpKTtcbn1cblxuZnVuY3Rpb24gX2Zvcihjb2xsZWN0aW9ucywgZnVuLCBmaWx0ZXIgPSAoKSA9PiB0cnVlLCBpbnRvID0gW10sIHByZXZpb3VzVmFsdWVzID0gW10pIHtcbiAgbGV0IHBhdHRlcm4gPSBjb2xsZWN0aW9uc1swXVswXTtcbiAgbGV0IGNvbGxlY3Rpb24gPSBjb2xsZWN0aW9uc1swXVsxXTtcblxuICBpZiAoY29sbGVjdGlvbnMubGVuZ3RoID09PSAxKSB7XG5cbiAgICBmb3IgKGxldCBlbGVtIG9mIGNvbGxlY3Rpb24pIHtcbiAgICAgIGxldCByID0gUGF0dGVybnMubWF0Y2hfbm9fdGhyb3cocGF0dGVybiwgZWxlbSk7XG4gICAgICBsZXQgYXJncyA9IHByZXZpb3VzVmFsdWVzLmNvbmNhdChyKTtcblxuICAgICAgaWYgKHIgJiYgZmlsdGVyLmFwcGx5KHRoaXMsIGFyZ3MpKSB7XG4gICAgICAgIGludG8gPSBpbnRvLmNvbmNhdChbZnVuLmFwcGx5KHRoaXMsIGFyZ3MpXSk7XG4gICAgICB9XG4gICAgfVxuXG4gICAgcmV0dXJuIGludG87XG4gIH0gZWxzZSB7XG4gICAgbGV0IF9pbnRvID0gW107XG5cbiAgICBmb3IgKGxldCBlbGVtIG9mIGNvbGxlY3Rpb24pIHtcbiAgICAgIGxldCByID0gUGF0dGVybnMubWF0Y2hfbm9fdGhyb3cocGF0dGVybiwgZWxlbSk7XG4gICAgICBpZiAocikge1xuICAgICAgICBfaW50byA9IGludG8uY29uY2F0KHRoaXMuX2Zvcihjb2xsZWN0aW9ucy5zbGljZSgxKSwgZnVuLCBmaWx0ZXIsIF9pbnRvLCBwcmV2aW91c1ZhbHVlcy5jb25jYXQocikpKTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICByZXR1cm4gX2ludG87XG4gIH1cbn1cblxuZnVuY3Rpb24gX3RyeShkb19mdW4sIHJlc2N1ZV9mdW5jdGlvbiwgY2F0Y2hfZnVuLCBlbHNlX2Z1bmN0aW9uLCBhZnRlcl9mdW5jdGlvbikge1xuICBsZXQgcmVzdWx0ID0gbnVsbDtcblxuICB0cnkge1xuICAgIHJlc3VsdCA9IGRvX2Z1bigpO1xuICB9IGNhdGNoIChlKSB7XG4gICAgbGV0IGV4X3Jlc3VsdCA9IG51bGw7XG5cbiAgICBpZiAocmVzY3VlX2Z1bmN0aW9uKSB7XG4gICAgICB0cnkge1xuICAgICAgICBleF9yZXN1bHQgPSByZXNjdWVfZnVuY3Rpb24oZSk7XG4gICAgICAgIHJldHVybiBleF9yZXN1bHQ7XG4gICAgICB9IGNhdGNoIChleCkge1xuICAgICAgICBpZiAoZXggaW5zdGFuY2VvZiBQYXR0ZXJucy5NYXRjaEVycm9yKSB7XG4gICAgICAgICAgdGhyb3cgZXg7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9XG5cbiAgICBpZiAoY2F0Y2hfZnVuKSB7XG4gICAgICB0cnkge1xuICAgICAgICBleF9yZXN1bHQgPSBjYXRjaF9mdW4oZSk7XG4gICAgICAgIHJldHVybiBleF9yZXN1bHQ7XG4gICAgICB9IGNhdGNoIChleCkge1xuICAgICAgICBpZiAoZXggaW5zdGFuY2VvZiBQYXR0ZXJucy5NYXRjaEVycm9yKSB7XG4gICAgICAgICAgdGhyb3cgZXg7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9XG5cbiAgICB0aHJvdyBlO1xuICB9IGZpbmFsbHkge1xuICAgIGlmIChhZnRlcl9mdW5jdGlvbikge1xuICAgICAgYWZ0ZXJfZnVuY3Rpb24oKTtcbiAgICB9XG4gIH1cblxuICBpZiAoZWxzZV9mdW5jdGlvbikge1xuICAgIHRyeSB7XG4gICAgICByZXR1cm4gZWxzZV9mdW5jdGlvbihyZXN1bHQpO1xuICAgIH0gY2F0Y2ggKGV4KSB7XG4gICAgICBpZiAoZXggaW5zdGFuY2VvZiBQYXR0ZXJucy5NYXRjaEVycm9yKSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcihcIk5vIE1hdGNoIEZvdW5kIGluIEVsc2VcIik7XG4gICAgICB9XG5cbiAgICAgIHRocm93IGV4O1xuICAgIH1cbiAgfSBlbHNlIHtcbiAgICByZXR1cm4gcmVzdWx0O1xuICB9XG59XG5cbmV4cG9ydCBkZWZhdWx0IHtcbiAgX2Nhc2UsXG4gIGNvbmQsXG4gIG1hcF91cGRhdGUsXG4gIF9mb3IsXG4gIF90cnlcbn07XG4vLyMgc291cmNlTWFwcGluZ1VSTD1kYXRhOmFwcGxpY2F0aW9uL2pzb247YmFzZTY0LGV5SjJaWEp6YVc5dUlqb3pMQ0p6YjNWeVkyVnpJanBiSW14cFlpOWpiM0psTDNOd1pXTnBZV3hmWm05eWJYTXVhbk1pWFN3aWJtRnRaWE1pT2x0ZExDSnRZWEJ3YVc1bmN5STZJa0ZCUVVFc1QwRkJUeXhUUVVGUUxFMUJRWE5DTEdOQlFYUkNPMEZCUTBFc1QwRkJUeXhSUVVGUUxFMUJRWEZDTEZsQlFYSkNPMEZCUTBFc1UwRkJVeXhMUVVGVUxGRkJRWE5DTEdOQlFYUkNPenRCUVVWQkxGTkJRVk1zUzBGQlZDeERRVUZsTEZOQlFXWXNSVUZCTUVJc1QwRkJNVUlzUlVGQmEwTTdRVUZEYUVNc1UwRkJUeXhUUVVGVExGRkJRVlFzUTBGQmEwSXNSMEZCUnl4UFFVRklMRU5CUVd4Q0xFTkJRVGhDTEZOQlFUbENMRU5CUVZBc1EwRkVaME03UTBGQmJFTTdPMEZCU1VFc1UwRkJVeXhKUVVGVUxFTkJRV01zVDBGQlpDeEZRVUZ6UWp0QlFVTndRaXhQUVVGSkxFbEJRVWtzVFVGQlNpeEpRVUZqTEU5QlFXeENMRVZCUVRCQ08wRkJRM2hDTEZGQlFVY3NUMEZCVHl4RFFVRlFMRU5CUVVnc1JVRkJZVHRCUVVOWUxHRkJRVThzVDBGQlR5eERRVUZRTEVkQlFWQXNRMEZFVnp0TFFVRmlPMGRCUkVZN08wRkJUVUVzVVVGQlRTeEpRVUZKTEV0QlFVb3NSVUZCVGl4RFFWQnZRanREUVVGMFFqczdRVUZWUVN4VFFVRlRMRlZCUVZRc1EwRkJiMElzUjBGQmNFSXNSVUZCZVVJc1RVRkJla0lzUlVGQlowTTdRVUZET1VJc1UwRkJUeXhQUVVGUExFMUJRVkFzUTBGRFRDeFBRVUZQTEUxQlFWQXNRMEZEUlN4UFFVRlBMRTFCUVZBc1EwRkJZeXhKUVVGSkxGZEJRVW9zUTBGQlowSXNVMEZCYUVJc1EwRkVhRUlzUlVGRE5FTXNSMEZFTlVNc1JVRkRhVVFzVFVGRWFrUXNRMEZFU3l4RFFVRlFMRU5CUkRoQ08wTkJRV2hET3p0QlFWRkJMRk5CUVZNc1NVRkJWQ3hEUVVGakxGZEJRV1FzUlVGQk1rSXNSMEZCTTBJc1JVRkJaME1zVTBGQlV5eE5RVUZOTEVsQlFVNHNSVUZCV1N4UFFVRlBMRVZCUVZBc1JVRkJWeXhwUWtGQmFVSXNSVUZCYWtJc1JVRkJiMEk3UVVGRGJFWXNUVUZCU1N4VlFVRlZMRmxCUVZrc1EwRkJXaXhGUVVGbExFTkJRV1lzUTBGQlZpeERRVVE0UlR0QlFVVnNSaXhOUVVGSkxHRkJRV0VzV1VGQldTeERRVUZhTEVWQlFXVXNRMEZCWml4RFFVRmlMRU5CUmpoRk96dEJRVWxzUml4TlFVRkhMRmxCUVZrc1RVRkJXaXhMUVVGMVFpeERRVUYyUWl4RlFVRjVRanM3UVVGRk1VSXNVMEZCU1N4SlFVRkpMRWxCUVVvc1NVRkJXU3hWUVVGb1FpeEZRVUV5UWp0QlFVTjZRaXhWUVVGSkxFbEJRVWtzVTBGQlV5eGpRVUZVTEVOQlFYZENMRTlCUVhoQ0xFVkJRV2xETEVsQlFXcERMRU5CUVVvc1EwRkVjVUk3UVVGRmVrSXNWVUZCU1N4UFFVRlBMR1ZCUVdVc1RVRkJaaXhEUVVGelFpeERRVUYwUWl4RFFVRlFMRU5CUm5GQ096dEJRVWw2UWl4VlFVRkhMRXRCUVVzc1QwRkJUeXhMUVVGUUxFTkJRV0VzU1VGQllpeEZRVUZ0UWl4SlFVRnVRaXhEUVVGTUxFVkJRVGhDTzBGQlF5OUNMR1ZCUVU4c1MwRkJTeXhOUVVGTUxFTkJRVmtzUTBGQlF5eEpRVUZKTEV0QlFVb3NRMEZCVlN4SlFVRldMRVZCUVdkQ0xFbEJRV2hDTEVOQlFVUXNRMEZCV2l4RFFVRlFMRU5CUkN0Q08wOUJRV3BETzB0QlNrWTdPMEZCVTBFc1YwRkJUeXhKUVVGUUxFTkJXREJDTzBkQlFUVkNMRTFCV1VzN1FVRkRTQ3hSUVVGSkxGRkJRVkVzUlVGQlVpeERRVVJFT3p0QlFVZElMRk5CUVVrc1NVRkJTU3hKUVVGS0xFbEJRVmtzVlVGQmFFSXNSVUZCTWtJN1FVRkRla0lzVlVGQlNTeEpRVUZKTEZOQlFWTXNZMEZCVkN4RFFVRjNRaXhQUVVGNFFpeEZRVUZwUXl4SlFVRnFReXhEUVVGS0xFTkJSSEZDTzBGQlJYcENMRlZCUVVjc1EwRkJTQ3hGUVVGTE8wRkJRMGdzWjBKQlFWRXNTMEZCU3l4TlFVRk1MRU5CUVZrc1MwRkJTeXhKUVVGTUxFTkJRVlVzV1VGQldTeExRVUZhTEVOQlFXdENMRU5CUVd4Q0xFTkJRVllzUlVGQlowTXNSMEZCYUVNc1JVRkJjVU1zVFVGQmNrTXNSVUZCTmtNc1MwRkJOME1zUlVGQmIwUXNaVUZCWlN4TlFVRm1MRU5CUVhOQ0xFTkJRWFJDTEVOQlFYQkVMRU5CUVZvc1EwRkJVaXhEUVVSSE8wOUJRVXc3UzBGR1JqczdRVUZQUVN4WFFVRlBMRXRCUVZBc1EwRldSenRIUVZwTU8wTkJTa1k3TzBGQk9FSkJMRk5CUVZNc1NVRkJWQ3hEUVVGakxFMUJRV1FzUlVGQmMwSXNaVUZCZEVJc1JVRkJkVU1zVTBGQmRrTXNSVUZCYTBRc1lVRkJiRVFzUlVGQmFVVXNZMEZCYWtVc1JVRkJaMFk3UVVGRE9VVXNUVUZCU1N4VFFVRlRMRWxCUVZRc1EwRkVNRVU3TzBGQlJ6bEZMRTFCUVVjN1FVRkRSQ3hoUVVGVExGRkJRVlFzUTBGRVF6dEhRVUZJTEVOQlJVTXNUMEZCVFN4RFFVRk9MRVZCUVZFN1FVRkRVQ3hSUVVGSkxGbEJRVmtzU1VGQldpeERRVVJIT3p0QlFVZFFMRkZCUVVjc1pVRkJTQ3hGUVVGdFFqdEJRVU5xUWl4VlFVRkhPMEZCUTBRc2IwSkJRVmtzWjBKQlFXZENMRU5CUVdoQ0xFTkJRVm9zUTBGRVF6dEJRVVZFTEdWQlFVOHNVMEZCVUN4RFFVWkRPMDlCUVVnc1EwRkhReXhQUVVGTkxFVkJRVTRzUlVGQlV6dEJRVU5TTEZsQlFVY3NZMEZCWXl4VFFVRlRMRlZCUVZRc1JVRkJiMEk3UVVGRGJrTXNaMEpCUVUwc1JVRkJUaXhEUVVSdFF6dFRRVUZ5UXp0UFFVUkVPMHRCU2tnN08wRkJWMEVzVVVGQlJ5eFRRVUZJTEVWQlFXRTdRVUZEV0N4VlFVRkhPMEZCUTBRc2IwSkJRVmtzVlVGQlZTeERRVUZXTEVOQlFWb3NRMEZFUXp0QlFVVkVMR1ZCUVU4c1UwRkJVQ3hEUVVaRE8wOUJRVWdzUTBGSFF5eFBRVUZOTEVWQlFVNHNSVUZCVXp0QlFVTlNMRmxCUVVjc1kwRkJZeXhUUVVGVExGVkJRVlFzUlVGQmIwSTdRVUZEYmtNc1owSkJRVTBzUlVGQlRpeERRVVJ0UXp0VFFVRnlRenRQUVVSRU8wdEJTa2c3TzBGQlYwRXNWVUZCVFN4RFFVRk9MRU5CZWtKUE8wZEJRVklzVTBFeVFrODdRVUZEVGl4UlFVRkhMR05CUVVnc1JVRkJhMEk3UVVGRGFFSXNkVUpCUkdkQ08wdEJRV3hDTzBkQk9VSkdPenRCUVcxRFFTeE5RVUZITEdGQlFVZ3NSVUZCYVVJN1FVRkRaaXhSUVVGSE8wRkJRMFFzWVVGQlR5eGpRVUZqTEUxQlFXUXNRMEZCVUN4RFFVUkRPMHRCUVVnc1EwRkZReXhQUVVGTkxFVkJRVTRzUlVGQlV6dEJRVU5PTEZWQlFVY3NZMEZCWXl4VFFVRlRMRlZCUVZRc1JVRkJiMEk3UVVGRGJrTXNZMEZCVFN4SlFVRkpMRXRCUVVvc1EwRkJWU3gzUWtGQlZpeERRVUZPTEVOQlJHMURPMDlCUVhKRE96dEJRVWxHTEZsQlFVMHNSVUZCVGl4RFFVeFJPMHRCUVZRN1IwRklTQ3hOUVZWTE8wRkJRMGdzVjBGQlR5eE5RVUZRTEVOQlJFYzdSMEZXVER0RFFYUkRSanM3UVVGeFJFRXNaVUZCWlR0QlFVTmlMRTlCUkdFN1FVRkZZaXhOUVVaaE8wRkJSMklzV1VGSVlUdEJRVWxpTEUxQlNtRTdRVUZMWWl4TlFVeGhPME5CUVdZaUxDSm1hV3hsSWpvaWJHbGlMMk52Y21VdmMzQmxZMmxoYkY5bWIzSnRjeTVxY3lJc0luTnZkWEpqWlhORGIyNTBaVzUwSWpwYkltbHRjRzl5ZENCQ2FYUlRkSEpwYm1jZ1puSnZiU0FuTGk5aWFYUmZjM1J5YVc1bkp6dGNibWx0Y0c5eWRDQlFZWFIwWlhKdWN5Qm1jbTl0SUNjdUwzQmhkSFJsY201ekp6dGNibWx0Y0c5eWRDQjdJRlIxY0d4bElIMGdabkp2YlNBbkxpOXdjbWx0YVhScGRtVnpKenRjYmx4dVpuVnVZM1JwYjI0Z1gyTmhjMlVvWTI5dVpHbDBhVzl1TENCamJHRjFjMlZ6S1h0Y2JpQWdjbVYwZFhKdUlGQmhkSFJsY201ekxtUmxabTFoZEdOb0tDNHVMbU5zWVhWelpYTXBLR052Ym1ScGRHbHZiaWs3WEc1OVhHNWNibVoxYm1OMGFXOXVJR052Ym1Rb1kyeGhkWE5sY3lsN1hHNGdJR1p2Y2loc1pYUWdZMnhoZFhObElHOW1JR05zWVhWelpYTXBlMXh1SUNBZ0lHbG1LR05zWVhWelpWc3dYU2w3WEc0Z0lDQWdJQ0J5WlhSMWNtNGdZMnhoZFhObFd6RmRLQ2s3WEc0Z0lDQWdmVnh1SUNCOVhHNWNiaUFnZEdoeWIzY2dibVYzSUVWeWNtOXlLQ2s3WEc1OVhHNWNibVoxYm1OMGFXOXVJRzFoY0Y5MWNHUmhkR1VvYldGd0xDQjJZV3gxWlhNcGUxeHVJQ0J5WlhSMWNtNGdUMkpxWldOMExtWnlaV1Y2WlNoY2JpQWdJQ0JQWW1wbFkzUXVZWE56YVdkdUtGeHVJQ0FnSUNBZ1QySnFaV04wTG1OeVpXRjBaU2h0WVhBdVkyOXVjM1J5ZFdOMGIzSXVjSEp2ZEc5MGVYQmxLU3dnYldGd0xDQjJZV3gxWlhOY2JpQWdJQ0FwWEc0Z0lDazdYRzU5WEc1Y2JtWjFibU4wYVc5dUlGOW1iM0lvWTI5c2JHVmpkR2x2Ym5Nc0lHWjFiaXdnWm1sc2RHVnlJRDBnS0NrZ1BUNGdkSEoxWlN3Z2FXNTBieUE5SUZ0ZExDQndjbVYyYVc5MWMxWmhiSFZsY3lBOUlGdGRLWHRjYmlBZ2JHVjBJSEJoZEhSbGNtNGdQU0JqYjJ4c1pXTjBhVzl1YzFzd1hWc3dYVHRjYmlBZ2JHVjBJR052Ykd4bFkzUnBiMjRnUFNCamIyeHNaV04wYVc5dWMxc3dYVnN4WFR0Y2JseHVJQ0JwWmloamIyeHNaV04wYVc5dWN5NXNaVzVuZEdnZ1BUMDlJREVwZTF4dVhHNGdJQ0FnWm05eUtHeGxkQ0JsYkdWdElHOW1JR052Ykd4bFkzUnBiMjRwZTF4dUlDQWdJQ0FnYkdWMElISWdQU0JRWVhSMFpYSnVjeTV0WVhSamFGOXViMTkwYUhKdmR5aHdZWFIwWlhKdUxDQmxiR1Z0S1R0Y2JpQWdJQ0FnSUd4bGRDQmhjbWR6SUQwZ2NISmxkbWx2ZFhOV1lXeDFaWE11WTI5dVkyRjBLSElwTzF4dVhHNGdJQ0FnSUNCcFppaHlJQ1ltSUdacGJIUmxjaTVoY0hCc2VTaDBhR2x6TENCaGNtZHpLU2w3WEc0Z0lDQWdJQ0FnSUdsdWRHOGdQU0JwYm5SdkxtTnZibU5oZENoYlpuVnVMbUZ3Y0d4NUtIUm9hWE1zSUdGeVozTXBYU2s3WEc0Z0lDQWdJQ0I5WEc0Z0lDQWdmVnh1WEc0Z0lDQWdjbVYwZFhKdUlHbHVkRzg3WEc0Z0lIMWxiSE5sZTF4dUlDQWdJR3hsZENCZmFXNTBieUE5SUZ0ZE8xeHVYRzRnSUNBZ1ptOXlLR3hsZENCbGJHVnRJRzltSUdOdmJHeGxZM1JwYjI0cGUxeHVJQ0FnSUNBZ2JHVjBJSElnUFNCUVlYUjBaWEp1Y3k1dFlYUmphRjl1YjE5MGFISnZkeWh3WVhSMFpYSnVMQ0JsYkdWdEtUdGNiaUFnSUNBZ0lHbG1LSElwZTF4dUlDQWdJQ0FnSUNCZmFXNTBieUE5SUdsdWRHOHVZMjl1WTJGMEtIUm9hWE11WDJadmNpaGpiMnhzWldOMGFXOXVjeTV6YkdsalpTZ3hLU3dnWm5WdUxDQm1hV3gwWlhJc0lGOXBiblJ2TENCd2NtVjJhVzkxYzFaaGJIVmxjeTVqYjI1allYUW9jaWtwS1R0Y2JpQWdJQ0FnSUgxY2JpQWdJQ0I5WEc1Y2JpQWdJQ0J5WlhSMWNtNGdYMmx1ZEc4N1hHNGdJSDFjYm4xY2JseHVablZ1WTNScGIyNGdYM1J5ZVNoa2IxOW1kVzRzSUhKbGMyTjFaVjltZFc1amRHbHZiaXdnWTJGMFkyaGZablZ1TENCbGJITmxYMloxYm1OMGFXOXVMQ0JoWm5SbGNsOW1kVzVqZEdsdmJpbDdYRzRnSUd4bGRDQnlaWE4xYkhRZ1BTQnVkV3hzTzF4dVhHNGdJSFJ5ZVh0Y2JpQWdJQ0J5WlhOMWJIUWdQU0JrYjE5bWRXNG9LVHRjYmlBZ2ZXTmhkR05vS0dVcGUxeHVJQ0FnSUd4bGRDQmxlRjl5WlhOMWJIUWdQU0J1ZFd4c08xeHVYRzRnSUNBZ2FXWW9jbVZ6WTNWbFgyWjFibU4wYVc5dUtYdGNiaUFnSUNBZ0lIUnllWHRjYmlBZ0lDQWdJQ0FnWlhoZmNtVnpkV3gwSUQwZ2NtVnpZM1ZsWDJaMWJtTjBhVzl1S0dVcE8xeHVJQ0FnSUNBZ0lDQnlaWFIxY200Z1pYaGZjbVZ6ZFd4ME8xeHVJQ0FnSUNBZ2ZXTmhkR05vS0dWNEtYdGNiaUFnSUNBZ0lDQWdhV1lvWlhnZ2FXNXpkR0Z1WTJWdlppQlFZWFIwWlhKdWN5NU5ZWFJqYUVWeWNtOXlLWHRjYmlBZ0lDQWdJQ0FnSUNCMGFISnZkeUJsZUR0Y2JpQWdJQ0FnSUNBZ2ZWeHVJQ0FnSUNBZ2ZWeHVJQ0FnSUgxY2JseHVJQ0FnSUdsbUtHTmhkR05vWDJaMWJpbDdYRzRnSUNBZ0lDQjBjbmw3WEc0Z0lDQWdJQ0FnSUdWNFgzSmxjM1ZzZENBOUlHTmhkR05vWDJaMWJpaGxLVHRjYmlBZ0lDQWdJQ0FnY21WMGRYSnVJR1Y0WDNKbGMzVnNkRHRjYmlBZ0lDQWdJSDFqWVhSamFDaGxlQ2w3WEc0Z0lDQWdJQ0FnSUdsbUtHVjRJR2x1YzNSaGJtTmxiMllnVUdGMGRHVnlibk11VFdGMFkyaEZjbkp2Y2lsN1hHNGdJQ0FnSUNBZ0lDQWdkR2h5YjNjZ1pYZzdYRzRnSUNBZ0lDQWdJSDFjYmlBZ0lDQWdJSDFjYmlBZ0lDQjlYRzVjYmlBZ0lDQjBhSEp2ZHlCbE8xeHVYRzRnSUgxbWFXNWhiR3g1ZTF4dUlDQWdJR2xtS0dGbWRHVnlYMloxYm1OMGFXOXVLWHRjYmlBZ0lDQWdJR0ZtZEdWeVgyWjFibU4wYVc5dUtDazdYRzRnSUNBZ2ZWeHVJQ0I5WEc1Y2JpQWdhV1lvWld4elpWOW1kVzVqZEdsdmJpbDdYRzRnSUNBZ2RISjVlMXh1SUNBZ0lDQWdjbVYwZFhKdUlHVnNjMlZmWm5WdVkzUnBiMjRvY21WemRXeDBLVHRjYmlBZ0lDQjlZMkYwWTJnb1pYZ3BlMXh1SUNBZ0lDQWdJQ0JwWmlobGVDQnBibk4wWVc1alpXOW1JRkJoZEhSbGNtNXpMazFoZEdOb1JYSnliM0lwZTF4dUlDQWdJQ0FnSUNBZ0lIUm9jbTkzSUc1bGR5QkZjbkp2Y2loY0lrNXZJRTFoZEdOb0lFWnZkVzVrSUdsdUlFVnNjMlZjSWlrN1hHNGdJQ0FnSUNBZ0lIMWNibHh1SUNBZ0lDQWdkR2h5YjNjZ1pYZzdYRzRnSUNBZ2ZWeHVJQ0I5Wld4elpYdGNiaUFnSUNCeVpYUjFjbTRnY21WemRXeDBPMXh1SUNCOVhHNTlYRzVjYm1WNGNHOXlkQ0JrWldaaGRXeDBJSHRjYmlBZ1gyTmhjMlVzWEc0Z0lHTnZibVFzWEc0Z0lHMWhjRjkxY0dSaGRHVXNYRzRnSUY5bWIzSXNYRzRnSUY5MGNubGNibjA3WEc0aVhTd2ljMjkxY21ObFVtOXZkQ0k2SWk5emIzVnlZMlV2SW4wPVxuIiwiaW1wb3J0IFByb2Nlc3NTeXN0ZW0gZnJvbSAnLi9jb3JlL3Byb2Nlc3Nlcy9wcm9jZXNzX3N5c3RlbSc7XG5pbXBvcnQgeyBUdXBsZSwgUElELCBJbnRlZ2VyLCBGbG9hdCB9IGZyb20gJy4vY29yZS9wcmltaXRpdmVzJztcbmltcG9ydCBCaXRTdHJpbmcgZnJvbSAnLi9jb3JlL2JpdF9zdHJpbmcnO1xuaW1wb3J0IFBhdHRlcm5zIGZyb20gJy4vY29yZS9wYXR0ZXJucyc7XG5pbXBvcnQgRnVuY3Rpb25zIGZyb20gJy4vY29yZS9mdW5jdGlvbnMnO1xuaW1wb3J0IFNwZWNpYWxGb3JtcyBmcm9tICcuL2NvcmUvc3BlY2lhbF9mb3Jtcyc7XG5cbkZ1bmN0aW9ucy5nZXRfZ2xvYmFsKCkucHJvY2Vzc2VzID0gRnVuY3Rpb25zLmdldF9nbG9iYWwoKS5wcm9jZXNzZXMgfHwgbmV3IFByb2Nlc3NTeXN0ZW0oKTtcblxuZXhwb3J0IGRlZmF1bHQge1xuICBQcm9jZXNzU3lzdGVtLFxuICBUdXBsZSxcbiAgUElELFxuICBCaXRTdHJpbmcsXG4gIFBhdHRlcm5zLFxuICBJbnRlZ2VyLFxuICBGbG9hdCxcbiAgRnVuY3Rpb25zLFxuICBTcGVjaWFsRm9ybXNcbn07XG4vLyMgc291cmNlTWFwcGluZ1VSTD1kYXRhOmFwcGxpY2F0aW9uL2pzb247YmFzZTY0LGV5SjJaWEp6YVc5dUlqb3pMQ0p6YjNWeVkyVnpJanBiSW14cFlpOWpiM0psTG1weklsMHNJbTVoYldWeklqcGJYU3dpYldGd2NHbHVaM01pT2lKQlFVRkJMRTlCUVU4c1lVRkJVQ3hOUVVFd1FpeHBRMEZCTVVJN1FVRkRRU3hUUVVGVExFdEJRVlFzUlVGQlowSXNSMEZCYUVJc1JVRkJjVUlzVDBGQmNrSXNSVUZCT0VJc1MwRkJPVUlzVVVGQk1rTXNiVUpCUVRORE8wRkJRMEVzVDBGQlR5eFRRVUZRTEUxQlFYTkNMRzFDUVVGMFFqdEJRVU5CTEU5QlFVOHNVVUZCVUN4TlFVRnhRaXhwUWtGQmNrSTdRVUZEUVN4UFFVRlBMRk5CUVZBc1RVRkJjMElzYTBKQlFYUkNPMEZCUTBFc1QwRkJUeXhaUVVGUUxFMUJRWGxDTEhOQ1FVRjZRanM3UVVGRlFTeFZRVUZWTEZWQlFWWXNSMEZCZFVJc1UwRkJka0lzUjBGQmJVTXNWVUZCVlN4VlFVRldMRWRCUVhWQ0xGTkJRWFpDTEVsQlFXOURMRWxCUVVrc1lVRkJTaXhGUVVGd1F6czdRVUZGYmtNc1pVRkJaVHRCUVVOaUxHVkJSR0U3UVVGRllpeFBRVVpoTzBGQlIySXNTMEZJWVR0QlFVbGlMRmRCU21FN1FVRkxZaXhWUVV4aE8wRkJUV0lzVTBGT1lUdEJRVTlpTEU5QlVHRTdRVUZSWWl4WFFWSmhPMEZCVTJJc1kwRlVZVHREUVVGbUlpd2labWxzWlNJNklteHBZaTlqYjNKbExtcHpJaXdpYzI5MWNtTmxjME52Ym5SbGJuUWlPbHNpYVcxd2IzSjBJRkJ5YjJObGMzTlRlWE4wWlcwZ1puSnZiU0FuTGk5amIzSmxMM0J5YjJObGMzTmxjeTl3Y205alpYTnpYM041YzNSbGJTYzdYRzVwYlhCdmNuUWdleUJVZFhCc1pTd2dVRWxFTENCSmJuUmxaMlZ5TENCR2JHOWhkQ0I5SUdaeWIyMGdKeTR2WTI5eVpTOXdjbWx0YVhScGRtVnpKenRjYm1sdGNHOXlkQ0JDYVhSVGRISnBibWNnWm5KdmJTQW5MaTlqYjNKbEwySnBkRjl6ZEhKcGJtY25PMXh1YVcxd2IzSjBJRkJoZEhSbGNtNXpJR1p5YjIwZ0p5NHZZMjl5WlM5d1lYUjBaWEp1Y3ljN1hHNXBiWEJ2Y25RZ1JuVnVZM1JwYjI1eklHWnliMjBnSnk0dlkyOXlaUzltZFc1amRHbHZibk1uTzF4dWFXMXdiM0owSUZOd1pXTnBZV3hHYjNKdGN5Qm1jbTl0SUNjdUwyTnZjbVV2YzNCbFkybGhiRjltYjNKdGN5YzdYRzVjYmtaMWJtTjBhVzl1Y3k1blpYUmZaMnh2WW1Gc0tDa3VjSEp2WTJWemMyVnpJRDBnUm5WdVkzUnBiMjV6TG1kbGRGOW5iRzlpWVd3b0tTNXdjbTlqWlhOelpYTWdmSHdnYm1WM0lGQnliMk5sYzNOVGVYTjBaVzBvS1R0Y2JseHVaWGh3YjNKMElHUmxabUYxYkhRZ2UxeHVJQ0JRY205alpYTnpVM2x6ZEdWdExGeHVJQ0JVZFhCc1pTeGNiaUFnVUVsRUxGeHVJQ0JDYVhSVGRISnBibWNzWEc0Z0lGQmhkSFJsY201ekxGeHVJQ0JKYm5SbFoyVnlMRnh1SUNCR2JHOWhkQ3hjYmlBZ1JuVnVZM1JwYjI1ekxGeHVJQ0JUY0dWamFXRnNSbTl5YlhOY2JuMWNiaUpkTENKemIzVnlZMlZTYjI5MElqb2lMM052ZFhKalpTOGlmUT09XG4iLCJpbXBvcnQgQ29yZSBmcm9tICcuL2NvcmUnO1xuXG5sZXQgRW51bSA9IHtcblxuICBhbGxfX3FtYXJrX186IGZ1bmN0aW9uIChjb2xsZWN0aW9uLCBmdW4gPSB4ID0+IHgpIHtcbiAgICBmb3IgKGxldCBlbGVtIG9mIGNvbGxlY3Rpb24pIHtcbiAgICAgIGlmICghZnVuKGVsZW0pKSB7XG4gICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICByZXR1cm4gdHJ1ZTtcbiAgfSxcblxuICBhbnlfX3FtYXJrX186IGZ1bmN0aW9uIChjb2xsZWN0aW9uLCBmdW4gPSB4ID0+IHgpIHtcbiAgICBmb3IgKGxldCBlbGVtIG9mIGNvbGxlY3Rpb24pIHtcbiAgICAgIGlmIChmdW4oZWxlbSkpIHtcbiAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICB9XG4gICAgfVxuXG4gICAgcmV0dXJuIGZhbHNlO1xuICB9LFxuXG4gIGF0OiBmdW5jdGlvbiAoY29sbGVjdGlvbiwgbiwgdGhlX2RlZmF1bHQgPSBudWxsKSB7XG4gICAgaWYgKG4gPiB0aGlzLmNvdW50KGNvbGxlY3Rpb24pIHx8IG4gPCAwKSB7XG4gICAgICByZXR1cm4gdGhlX2RlZmF1bHQ7XG4gICAgfVxuXG4gICAgcmV0dXJuIGNvbGxlY3Rpb25bbl07XG4gIH0sXG5cbiAgY29uY2F0OiBmdW5jdGlvbiAoLi4uZW51bWFibGVzKSB7XG4gICAgcmV0dXJuIGVudW1hYmxlc1swXS5jb25jYXQoZW51bWFibGVzWzFdKTtcbiAgfSxcblxuICBjb3VudDogZnVuY3Rpb24gKGNvbGxlY3Rpb24sIGZ1biA9IG51bGwpIHtcbiAgICBpZiAoZnVuID09IG51bGwpIHtcbiAgICAgIHJldHVybiBjb2xsZWN0aW9uLmxlbmd0aDtcbiAgICB9IGVsc2Uge1xuICAgICAgcmV0dXJuIGNvbGxlY3Rpb24uZmlsdGVyKGZ1bikubGVuZ3RoO1xuICAgIH1cbiAgfSxcblxuICBkcm9wOiBmdW5jdGlvbiAoY29sbGVjdGlvbiwgY291bnQpIHtcbiAgICByZXR1cm4gY29sbGVjdGlvbi5zbGljZShjb3VudCk7XG4gIH0sXG5cbiAgZHJvcF93aGlsZTogZnVuY3Rpb24gKGNvbGxlY3Rpb24sIGZ1bikge1xuICAgIGxldCBjb3VudCA9IDA7XG5cbiAgICBmb3IgKGxldCBlbGVtIG9mIGNvbGxlY3Rpb24pIHtcbiAgICAgIGlmIChmdW4oZWxlbSkpIHtcbiAgICAgICAgY291bnQgPSBjb3VudCArIDE7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBicmVhaztcbiAgICAgIH1cbiAgICB9XG5cbiAgICByZXR1cm4gY29sbGVjdGlvbi5zbGljZShjb3VudCk7XG4gIH0sXG5cbiAgZWFjaDogZnVuY3Rpb24gKGNvbGxlY3Rpb24sIGZ1bikge1xuICAgIGZvciAobGV0IGVsZW0gb2YgY29sbGVjdGlvbikge1xuICAgICAgZnVuKGVsZW0pO1xuICAgIH1cbiAgfSxcblxuICBlbXB0eV9fcW1hcmtfXzogZnVuY3Rpb24gKGNvbGxlY3Rpb24pIHtcbiAgICByZXR1cm4gY29sbGVjdGlvbi5sZW5ndGggPT09IDA7XG4gIH0sXG5cbiAgZmV0Y2g6IGZ1bmN0aW9uIChjb2xsZWN0aW9uLCBuKSB7XG4gICAgaWYgKEFycmF5LmlzQXJyYXkoY29sbGVjdGlvbikpIHtcbiAgICAgIGlmIChuIDwgdGhpcy5jb3VudChjb2xsZWN0aW9uKSAmJiBuID49IDApIHtcbiAgICAgICAgcmV0dXJuIG5ldyBDb3JlLlR1cGxlKFN5bWJvbC5mb3IoXCJva1wiKSwgY29sbGVjdGlvbltuXSk7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICByZXR1cm4gU3ltYm9sLmZvcihcImVycm9yXCIpO1xuICAgICAgfVxuICAgIH1cblxuICAgIHRocm93IG5ldyBFcnJvcihcImNvbGxlY3Rpb24gaXMgbm90IGFuIEVudW1lcmFibGVcIik7XG4gIH0sXG5cbiAgZmV0Y2hfX2VtYXJrX186IGZ1bmN0aW9uIChjb2xsZWN0aW9uLCBuKSB7XG4gICAgaWYgKEFycmF5LmlzQXJyYXkoY29sbGVjdGlvbikpIHtcbiAgICAgIGlmIChuIDwgdGhpcy5jb3VudChjb2xsZWN0aW9uKSAmJiBuID49IDApIHtcbiAgICAgICAgcmV0dXJuIGNvbGxlY3Rpb25bbl07XG4gICAgICB9IGVsc2Uge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoXCJvdXQgb2YgYm91bmRzIGVycm9yXCIpO1xuICAgICAgfVxuICAgIH1cblxuICAgIHRocm93IG5ldyBFcnJvcihcImNvbGxlY3Rpb24gaXMgbm90IGFuIEVudW1lcmFibGVcIik7XG4gIH0sXG5cbiAgZmlsdGVyOiBmdW5jdGlvbiAoY29sbGVjdGlvbiwgZnVuKSB7XG4gICAgbGV0IHJlc3VsdCA9IFtdO1xuXG4gICAgZm9yIChsZXQgZWxlbSBvZiBjb2xsZWN0aW9uKSB7XG4gICAgICBpZiAoZnVuKGVsZW0pKSB7XG4gICAgICAgIHJlc3VsdC5wdXNoKGVsZW0pO1xuICAgICAgfVxuICAgIH1cblxuICAgIHJldHVybiByZXN1bHQ7XG4gIH0sXG5cbiAgZmlsdGVyX21hcDogZnVuY3Rpb24gKGNvbGxlY3Rpb24sIGZpbHRlciwgbWFwcGVyKSB7XG4gICAgcmV0dXJuIEVudW0ubWFwKEVudW0uZmlsdGVyKGNvbGxlY3Rpb24sIGZpbHRlciksIG1hcHBlcik7XG4gIH0sXG5cbiAgZmluZDogZnVuY3Rpb24gKGNvbGxlY3Rpb24sIGlmX25vbmUgPSBudWxsLCBmdW4pIHtcbiAgICBmb3IgKGxldCBlbGVtIG9mIGNvbGxlY3Rpb24pIHtcbiAgICAgIGlmIChmdW4oZWxlbSkpIHtcbiAgICAgICAgcmV0dXJuIGVsZW07XG4gICAgICB9XG4gICAgfVxuXG4gICAgcmV0dXJuIGlmX25vbmU7XG4gIH0sXG5cbiAgaW50bzogZnVuY3Rpb24gKGNvbGxlY3Rpb24sIGxpc3QpIHtcbiAgICByZXR1cm4gbGlzdC5jb25jYXQoY29sbGVjdGlvbik7XG4gIH0sXG5cbiAgbWFwOiBmdW5jdGlvbiAoY29sbGVjdGlvbiwgZnVuKSB7XG4gICAgbGV0IHJlc3VsdCA9IFtdO1xuXG4gICAgZm9yIChsZXQgZWxlbSBvZiBjb2xsZWN0aW9uKSB7XG4gICAgICByZXN1bHQucHVzaChmdW4oZWxlbSkpO1xuICAgIH1cblxuICAgIHJldHVybiByZXN1bHQ7XG4gIH0sXG5cbiAgbWFwX3JlZHVjZTogZnVuY3Rpb24gKGNvbGxlY3Rpb24sIGFjYywgZnVuKSB7XG4gICAgbGV0IG1hcHBlZCA9IE9iamVjdC5mcmVlemUoW10pO1xuICAgIGxldCB0aGVfYWNjID0gYWNjO1xuXG4gICAgZm9yICh2YXIgaSA9IDA7IGkgPCB0aGlzLmNvdW50KGNvbGxlY3Rpb24pOyBpKyspIHtcbiAgICAgIGxldCB0dXBsZSA9IGZ1bihjb2xsZWN0aW9uW2ldLCB0aGVfYWNjKTtcblxuICAgICAgdGhlX2FjYyA9IHR1cGxlLmdldCgxKTtcbiAgICAgIG1hcHBlZCA9IE9iamVjdC5mcmVlemUobWFwcGVkLmNvbmNhdChbdHVwbGUuZ2V0KDApXSkpO1xuICAgIH1cblxuICAgIHJldHVybiBuZXcgQ29yZS5UdXBsZShtYXBwZWQsIHRoZV9hY2MpO1xuICB9LFxuXG4gIG1lbWJlcl9fcW1hcmtfXzogZnVuY3Rpb24gKGNvbGxlY3Rpb24sIHZhbHVlKSB7XG4gICAgcmV0dXJuIGNvbGxlY3Rpb24uaW5jbHVkZXModmFsdWUpO1xuICB9LFxuXG4gIHJlZHVjZTogZnVuY3Rpb24gKGNvbGxlY3Rpb24sIGFjYywgZnVuKSB7XG4gICAgbGV0IHRoZV9hY2MgPSBhY2M7XG5cbiAgICBmb3IgKHZhciBpID0gMDsgaSA8IHRoaXMuY291bnQoY29sbGVjdGlvbik7IGkrKykge1xuICAgICAgbGV0IHR1cGxlID0gZnVuKGNvbGxlY3Rpb25baV0sIHRoZV9hY2MpO1xuXG4gICAgICB0aGVfYWNjID0gdHVwbGUuZ2V0KDEpO1xuICAgIH1cblxuICAgIHJldHVybiB0aGVfYWNjO1xuICB9LFxuXG4gIHRha2U6IGZ1bmN0aW9uIChjb2xsZWN0aW9uLCBjb3VudCkge1xuICAgIHJldHVybiBjb2xsZWN0aW9uLnNsaWNlKDAsIGNvdW50KTtcbiAgfSxcblxuICB0YWtlX2V2ZXJ5OiBmdW5jdGlvbiAoY29sbGVjdGlvbiwgbnRoKSB7XG4gICAgbGV0IHJlc3VsdCA9IFtdO1xuICAgIGxldCBpbmRleCA9IDA7XG5cbiAgICBmb3IgKGxldCBlbGVtIG9mIGNvbGxlY3Rpb24pIHtcbiAgICAgIGlmIChpbmRleCAlIG50aCA9PT0gMCkge1xuICAgICAgICByZXN1bHQucHVzaChlbGVtKTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICByZXR1cm4gT2JqZWN0LmZyZWV6ZShyZXN1bHQpO1xuICB9LFxuXG4gIHRha2Vfd2hpbGU6IGZ1bmN0aW9uIChjb2xsZWN0aW9uLCBmdW4pIHtcbiAgICBsZXQgY291bnQgPSAwO1xuXG4gICAgZm9yIChsZXQgZWxlbSBvZiBjb2xsZWN0aW9uKSB7XG4gICAgICBpZiAoZnVuKGVsZW0pKSB7XG4gICAgICAgIGNvdW50ID0gY291bnQgKyAxO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgYnJlYWs7XG4gICAgICB9XG4gICAgfVxuXG4gICAgcmV0dXJuIGNvbGxlY3Rpb24uc2xpY2UoMCwgY291bnQpO1xuICB9LFxuXG4gIHRvX2xpc3Q6IGZ1bmN0aW9uIChjb2xsZWN0aW9uKSB7XG4gICAgcmV0dXJuIGNvbGxlY3Rpb247XG4gIH1cbn07XG5cbmV4cG9ydCBkZWZhdWx0IEVudW07XG4vLyMgc291cmNlTWFwcGluZ1VSTD1kYXRhOmFwcGxpY2F0aW9uL2pzb247YmFzZTY0LGV5SjJaWEp6YVc5dUlqb3pMQ0p6YjNWeVkyVnpJanBiSW14cFlpOWxiblZ0TG1weklsMHNJbTVoYldWeklqcGJYU3dpYldGd2NHbHVaM01pT2lKQlFVRkJMRTlCUVU4c1NVRkJVQ3hOUVVGcFFpeFJRVUZxUWpzN1FVRkZRU3hKUVVGSkxFOUJRVTg3TzBGQlJWUXNaMEpCUVdNc1ZVRkJVeXhWUVVGVUxFVkJRWEZDTEUxQlFVMHNTMEZCVHl4RFFVRlFMRVZCUVZNN1FVRkRhRVFzVTBGQlNTeEpRVUZKTEVsQlFVb3NTVUZCV1N4VlFVRm9RaXhGUVVFeVFqdEJRVU42UWl4VlFVRkhMRU5CUVVNc1NVRkJTU3hKUVVGS0xFTkJRVVFzUlVGQlZ6dEJRVU5hTEdWQlFVOHNTMEZCVUN4RFFVUlpPMDlCUVdRN1MwRkVSanM3UVVGTlFTeFhRVUZQTEVsQlFWQXNRMEZRWjBRN1IwRkJjRU03TzBGQlZXUXNaMEpCUVdNc1ZVRkJVeXhWUVVGVUxFVkJRWEZDTEUxQlFVMHNTMEZCVHl4RFFVRlFMRVZCUVZNN1FVRkRhRVFzVTBGQlNTeEpRVUZKTEVsQlFVb3NTVUZCV1N4VlFVRm9RaXhGUVVFeVFqdEJRVU42UWl4VlFVRkhMRWxCUVVrc1NVRkJTaXhEUVVGSUxFVkJRV0U3UVVGRFdDeGxRVUZQTEVsQlFWQXNRMEZFVnp0UFFVRmlPMHRCUkVZN08wRkJUVUVzVjBGQlR5eExRVUZRTEVOQlVHZEVPMGRCUVhCRE96dEJRVlZrTEUxQlFVa3NWVUZCVXl4VlFVRlVMRVZCUVhGQ0xFTkJRWEpDTEVWQlFYZENMR05CUVdNc1NVRkJaQ3hGUVVGdFFqdEJRVU0zUXl4UlFVRkhMRWxCUVVrc1MwRkJTeXhMUVVGTUxFTkJRVmNzVlVGQldDeERRVUZLTEVsQlFUaENMRWxCUVVrc1EwRkJTaXhGUVVGTk8wRkJRM0pETEdGQlFVOHNWMEZCVUN4RFFVUnhRenRMUVVGMlF6czdRVUZKUVN4WFFVRlBMRmRCUVZjc1EwRkJXQ3hEUVVGUUxFTkJURFpETzBkQlFUTkRPenRCUVZGS0xGVkJRVkVzVlVGQlV5eEhRVUZITEZOQlFVZ3NSVUZCWVR0QlFVTTFRaXhYUVVGUExGVkJRVlVzUTBGQlZpeEZRVUZoTEUxQlFXSXNRMEZCYjBJc1ZVRkJWU3hEUVVGV0xFTkJRWEJDTEVOQlFWQXNRMEZFTkVJN1IwRkJkRUk3TzBGQlNWSXNVMEZCVHl4VlFVRlRMRlZCUVZRc1JVRkJjVUlzVFVGQlRTeEpRVUZPTEVWQlFWYzdRVUZEY2tNc1VVRkJSeXhQUVVGUExFbEJRVkFzUlVGQldUdEJRVU5pTEdGQlFVOHNWMEZCVnl4TlFVRllMRU5CUkUwN1MwRkJaaXhOUVVWUE8wRkJRMHdzWVVGQlR5eFhRVUZYTEUxQlFWZ3NRMEZCYTBJc1IwRkJiRUlzUlVGQmRVSXNUVUZCZGtJc1EwRkVSanRMUVVaUU8wZEJSRXM3TzBGQlVWQXNVVUZCVFN4VlFVRlRMRlZCUVZRc1JVRkJjVUlzUzBGQmNrSXNSVUZCTWtJN1FVRkRMMElzVjBGQlR5eFhRVUZYTEV0QlFWZ3NRMEZCYVVJc1MwRkJha0lzUTBGQlVDeERRVVFyUWp0SFFVRXpRanM3UVVGSlRpeGpRVUZaTEZWQlFWTXNWVUZCVkN4RlFVRnhRaXhIUVVGeVFpeEZRVUY1UWp0QlFVTnVReXhSUVVGSkxGRkJRVkVzUTBGQlVpeERRVVFyUWpzN1FVRkhia01zVTBGQlNTeEpRVUZKTEVsQlFVb3NTVUZCV1N4VlFVRm9RaXhGUVVFeVFqdEJRVU42UWl4VlFVRkhMRWxCUVVrc1NVRkJTaXhEUVVGSUxFVkJRV0U3UVVGRFdDeG5Ra0ZCVVN4UlFVRlJMRU5CUVZJc1EwRkVSenRQUVVGaUxFMUJSVXM3UVVGRFNDeGpRVVJITzA5QlJrdzdTMEZFUmpzN1FVRlJRU3hYUVVGUExGZEJRVmNzUzBGQldDeERRVUZwUWl4TFFVRnFRaXhEUVVGUUxFTkJXRzFETzBkQlFYcENPenRCUVdOYUxGRkJRVTBzVlVGQlV5eFZRVUZVTEVWQlFYRkNMRWRCUVhKQ0xFVkJRWGxDTzBGQlF6ZENMRk5CUVVrc1NVRkJTU3hKUVVGS0xFbEJRVmtzVlVGQmFFSXNSVUZCTWtJN1FVRkRla0lzVlVGQlNTeEpRVUZLTEVWQlJIbENPMHRCUVROQ08wZEJSRWs3TzBGQlRVNHNhMEpCUVdkQ0xGVkJRVk1zVlVGQlZDeEZRVUZ2UWp0QlFVTnNReXhYUVVGUExGZEJRVmNzVFVGQldDeExRVUZ6UWl4RFFVRjBRaXhEUVVReVFqdEhRVUZ3UWpzN1FVRkphRUlzVTBGQlR5eFZRVUZUTEZWQlFWUXNSVUZCY1VJc1EwRkJja0lzUlVGQmRVSTdRVUZETlVJc1VVRkJSeXhOUVVGTkxFOUJRVTRzUTBGQll5eFZRVUZrTEVOQlFVZ3NSVUZCTmtJN1FVRkRNMElzVlVGQlJ5eEpRVUZKTEV0QlFVc3NTMEZCVEN4RFFVRlhMRlZCUVZnc1EwRkJTaXhKUVVFNFFpeExRVUZMTEVOQlFVd3NSVUZCVHp0QlFVTjBReXhsUVVGUExFbEJRVWtzUzBGQlN5eExRVUZNTEVOQlFWY3NUMEZCVHl4SFFVRlFMRU5CUVZjc1NVRkJXQ3hEUVVGbUxFVkJRV2xETEZkQlFWY3NRMEZCV0N4RFFVRnFReXhEUVVGUUxFTkJSSE5ETzA5QlFYaERMRTFCUlVzN1FVRkRTQ3hsUVVGUExFOUJRVThzUjBGQlVDeERRVUZYTEU5QlFWZ3NRMEZCVUN4RFFVUkhPMDlCUmt3N1MwRkVSanM3UVVGUlFTeFZRVUZOTEVsQlFVa3NTMEZCU2l4RFFVRlZMR2xEUVVGV0xFTkJRVTRzUTBGVU5FSTdSMEZCZGtJN08wRkJXVkFzYTBKQlFXZENMRlZCUVZNc1ZVRkJWQ3hGUVVGeFFpeERRVUZ5UWl4RlFVRjFRanRCUVVOeVF5eFJRVUZITEUxQlFVMHNUMEZCVGl4RFFVRmpMRlZCUVdRc1EwRkJTQ3hGUVVFMlFqdEJRVU16UWl4VlFVRkhMRWxCUVVrc1MwRkJTeXhMUVVGTUxFTkJRVmNzVlVGQldDeERRVUZLTEVsQlFUaENMRXRCUVVzc1EwRkJUQ3hGUVVGUE8wRkJRM1JETEdWQlFVOHNWMEZCVnl4RFFVRllMRU5CUVZBc1EwRkVjME03VDBGQmVFTXNUVUZGU3p0QlFVTklMR05CUVUwc1NVRkJTU3hMUVVGS0xFTkJRVlVzY1VKQlFWWXNRMEZCVGl4RFFVUkhPMDlCUmt3N1MwRkVSanM3UVVGUlFTeFZRVUZOTEVsQlFVa3NTMEZCU2l4RFFVRlZMR2xEUVVGV0xFTkJRVTRzUTBGVWNVTTdSMEZCZGtJN08wRkJXV2hDTEZWQlFWRXNWVUZCVXl4VlFVRlVMRVZCUVhGQ0xFZEJRWEpDTEVWQlFYbENPMEZCUXk5Q0xGRkJRVWtzVTBGQlV5eEZRVUZVTEVOQlJESkNPenRCUVVjdlFpeFRRVUZKTEVsQlFVa3NTVUZCU2l4SlFVRlpMRlZCUVdoQ0xFVkJRVEpDTzBGQlEzcENMRlZCUVVjc1NVRkJTU3hKUVVGS0xFTkJRVWdzUlVGQllUdEJRVU5ZTEdWQlFVOHNTVUZCVUN4RFFVRlpMRWxCUVZvc1JVRkVWenRQUVVGaU8wdEJSRVk3TzBGQlRVRXNWMEZCVHl4TlFVRlFMRU5CVkN0Q08wZEJRWHBDT3p0QlFWbFNMR05CUVZrc1ZVRkJVeXhWUVVGVUxFVkJRWEZDTEUxQlFYSkNMRVZCUVRaQ0xFMUJRVGRDTEVWQlFXOURPMEZCUXpsRExGZEJRVThzUzBGQlN5eEhRVUZNTEVOQlFWTXNTMEZCU3l4TlFVRk1MRU5CUVZrc1ZVRkJXaXhGUVVGM1FpeE5RVUY0UWl4RFFVRlVMRVZCUVRCRExFMUJRVEZETEVOQlFWQXNRMEZFT0VNN1IwRkJjRU03TzBGQlNWb3NVVUZCVFN4VlFVRlRMRlZCUVZRc1JVRkJjVUlzVlVGQlZTeEpRVUZXTEVWQlFXZENMRWRCUVhKRExFVkJRWGxETzBGQlF6ZERMRk5CUVVrc1NVRkJTU3hKUVVGS0xFbEJRVmtzVlVGQmFFSXNSVUZCTWtJN1FVRkRla0lzVlVGQlJ5eEpRVUZKTEVsQlFVb3NRMEZCU0N4RlFVRmhPMEZCUTFnc1pVRkJUeXhKUVVGUUxFTkJSRmM3VDBGQllqdExRVVJHT3p0QlFVMUJMRmRCUVU4c1QwRkJVQ3hEUVZBMlF6dEhRVUY2UXpzN1FVRlZUaXhSUVVGTkxGVkJRVk1zVlVGQlZDeEZRVUZ4UWl4SlFVRnlRaXhGUVVFd1FqdEJRVU01UWl4WFFVRlBMRXRCUVVzc1RVRkJUQ3hEUVVGWkxGVkJRVm9zUTBGQlVDeERRVVE0UWp0SFFVRXhRanM3UVVGSlRpeFBRVUZMTEZWQlFWTXNWVUZCVkN4RlFVRnhRaXhIUVVGeVFpeEZRVUY1UWp0QlFVTTFRaXhSUVVGSkxGTkJRVk1zUlVGQlZDeERRVVIzUWpzN1FVRkhOVUlzVTBGQlNTeEpRVUZKTEVsQlFVb3NTVUZCV1N4VlFVRm9RaXhGUVVFeVFqdEJRVU42UWl4aFFVRlBMRWxCUVZBc1EwRkJXU3hKUVVGSkxFbEJRVW9zUTBGQldpeEZRVVI1UWp0TFFVRXpRanM3UVVGSlFTeFhRVUZQTEUxQlFWQXNRMEZRTkVJN1IwRkJla0k3TzBGQlZVd3NZMEZCV1N4VlFVRlRMRlZCUVZRc1JVRkJjVUlzUjBGQmNrSXNSVUZCTUVJc1IwRkJNVUlzUlVGQk9FSTdRVUZEZUVNc1VVRkJTU3hUUVVGVExFOUJRVThzVFVGQlVDeERRVUZqTEVWQlFXUXNRMEZCVkN4RFFVUnZRenRCUVVWNFF5eFJRVUZKTEZWQlFWVXNSMEZCVml4RFFVWnZRenM3UVVGSmVFTXNVMEZCU3l4SlFVRkpMRWxCUVVrc1EwRkJTaXhGUVVGUExFbEJRVWtzUzBGQlN5eExRVUZNTEVOQlFWY3NWVUZCV0N4RFFVRktMRVZCUVRSQ0xFZEJRVFZETEVWQlFXbEVPMEZCUXk5RExGVkJRVWtzVVVGQlVTeEpRVUZKTEZkQlFWY3NRMEZCV0N4RFFVRktMRVZCUVcxQ0xFOUJRVzVDTEVOQlFWSXNRMEZFTWtNN08wRkJSeTlETEdkQ1FVRlZMRTFCUVUwc1IwRkJUaXhEUVVGVkxFTkJRVllzUTBGQlZpeERRVWdyUXp0QlFVa3ZReXhsUVVGVExFOUJRVThzVFVGQlVDeERRVUZqTEU5QlFVOHNUVUZCVUN4RFFVRmpMRU5CUVVNc1RVRkJUU3hIUVVGT0xFTkJRVlVzUTBGQlZpeERRVUZFTEVOQlFXUXNRMEZCWkN4RFFVRlVMRU5CU2l0RE8wdEJRV3BFT3p0QlFVOUJMRmRCUVU4c1NVRkJTU3hMUVVGTExFdEJRVXdzUTBGQlZ5eE5RVUZtTEVWQlFYVkNMRTlCUVhaQ0xFTkJRVkFzUTBGWWQwTTdSMEZCT1VJN08wRkJZMW9zYlVKQlFXbENMRlZCUVZNc1ZVRkJWQ3hGUVVGeFFpeExRVUZ5UWl4RlFVRXlRanRCUVVNeFF5eFhRVUZQTEZkQlFWY3NVVUZCV0N4RFFVRnZRaXhMUVVGd1FpeERRVUZRTEVOQlJEQkRPMGRCUVROQ096dEJRVWxxUWl4VlFVRlJMRlZCUVZNc1ZVRkJWQ3hGUVVGeFFpeEhRVUZ5UWl4RlFVRXdRaXhIUVVFeFFpeEZRVUU0UWp0QlFVTndReXhSUVVGSkxGVkJRVlVzUjBGQlZpeERRVVJuUXpzN1FVRkhjRU1zVTBGQlN5eEpRVUZKTEVsQlFVa3NRMEZCU2l4RlFVRlBMRWxCUVVrc1MwRkJTeXhMUVVGTUxFTkJRVmNzVlVGQldDeERRVUZLTEVWQlFUUkNMRWRCUVRWRExFVkJRV2xFTzBGQlF5OURMRlZCUVVrc1VVRkJVU3hKUVVGSkxGZEJRVmNzUTBGQldDeERRVUZLTEVWQlFXMUNMRTlCUVc1Q0xFTkJRVklzUTBGRU1rTTdPMEZCUnk5RExHZENRVUZWTEUxQlFVMHNSMEZCVGl4RFFVRlZMRU5CUVZZc1EwRkJWaXhEUVVnclF6dExRVUZxUkRzN1FVRk5RU3hYUVVGUExFOUJRVkFzUTBGVWIwTTdSMEZCT1VJN08wRkJXVklzVVVGQlRTeFZRVUZUTEZWQlFWUXNSVUZCY1VJc1MwRkJja0lzUlVGQk1rSTdRVUZETDBJc1YwRkJUeXhYUVVGWExFdEJRVmdzUTBGQmFVSXNRMEZCYWtJc1JVRkJiMElzUzBGQmNFSXNRMEZCVUN4RFFVUXJRanRIUVVFelFqczdRVUZKVGl4alFVRlpMRlZCUVZNc1ZVRkJWQ3hGUVVGeFFpeEhRVUZ5UWl4RlFVRjVRanRCUVVOdVF5eFJRVUZKTEZOQlFWTXNSVUZCVkN4RFFVUXJRanRCUVVWdVF5eFJRVUZKTEZGQlFWRXNRMEZCVWl4RFFVWXJRanM3UVVGSmJrTXNVMEZCU1N4SlFVRkpMRWxCUVVvc1NVRkJXU3hWUVVGb1FpeEZRVUV5UWp0QlFVTjZRaXhWUVVGSExGRkJRVkVzUjBGQlVpeExRVUZuUWl4RFFVRm9RaXhGUVVGclFqdEJRVU51UWl4bFFVRlBMRWxCUVZBc1EwRkJXU3hKUVVGYUxFVkJSRzFDTzA5QlFYSkNPMHRCUkVZN08wRkJUVUVzVjBGQlR5eFBRVUZQTEUxQlFWQXNRMEZCWXl4TlFVRmtMRU5CUVZBc1EwRldiVU03UjBGQmVrSTdPMEZCWVZvc1kwRkJXU3hWUVVGVExGVkJRVlFzUlVGQmNVSXNSMEZCY2tJc1JVRkJlVUk3UVVGRGJrTXNVVUZCU1N4UlFVRlJMRU5CUVZJc1EwRkVLMEk3TzBGQlIyNURMRk5CUVVrc1NVRkJTU3hKUVVGS0xFbEJRVmtzVlVGQmFFSXNSVUZCTWtJN1FVRkRla0lzVlVGQlJ5eEpRVUZKTEVsQlFVb3NRMEZCU0N4RlFVRmhPMEZCUTFnc1owSkJRVkVzVVVGQlVTeERRVUZTTEVOQlJFYzdUMEZCWWl4TlFVVkxPMEZCUTBnc1kwRkVSenRQUVVaTU8wdEJSRVk3TzBGQlVVRXNWMEZCVHl4WFFVRlhMRXRCUVZnc1EwRkJhVUlzUTBGQmFrSXNSVUZCYjBJc1MwRkJjRUlzUTBGQlVDeERRVmh0UXp0SFFVRjZRanM3UVVGaldpeFhRVUZUTEZWQlFWTXNWVUZCVkN4RlFVRnZRanRCUVVNelFpeFhRVUZQTEZWQlFWQXNRMEZFTWtJN1IwRkJjRUk3UTBGdVRWQTdPMEZCZDAxS0xHVkJRV1VzU1VGQlppSXNJbVpwYkdVaU9pSnNhV0l2Wlc1MWJTNXFjeUlzSW5OdmRYSmpaWE5EYjI1MFpXNTBJanBiSW1sdGNHOXlkQ0JEYjNKbElHWnliMjBnSnk0dlkyOXlaU2M3WEc1Y2JteGxkQ0JGYm5WdElEMGdlMXh1WEc0Z0lHRnNiRjlmY1cxaGNtdGZYem9nWm5WdVkzUnBiMjRvWTI5c2JHVmpkR2x2Yml3Z1puVnVJRDBnS0hncElEMCtJSGdwZTF4dUlDQWdJR1p2Y2loc1pYUWdaV3hsYlNCdlppQmpiMnhzWldOMGFXOXVLWHRjYmlBZ0lDQWdJR2xtS0NGbWRXNG9aV3hsYlNrcGUxeHVJQ0FnSUNBZ0lDQnlaWFIxY200Z1ptRnNjMlU3WEc0Z0lDQWdJQ0I5WEc0Z0lDQWdmVnh1WEc0Z0lDQWdjbVYwZFhKdUlIUnlkV1U3WEc0Z0lIMHNYRzVjYmlBZ1lXNTVYMTl4YldGeWExOWZPaUJtZFc1amRHbHZiaWhqYjJ4c1pXTjBhVzl1TENCbWRXNGdQU0FvZUNrZ1BUNGdlQ2w3WEc0Z0lDQWdabTl5S0d4bGRDQmxiR1Z0SUc5bUlHTnZiR3hsWTNScGIyNHBlMXh1SUNBZ0lDQWdhV1lvWm5WdUtHVnNaVzBwS1h0Y2JpQWdJQ0FnSUNBZ2NtVjBkWEp1SUhSeWRXVTdYRzRnSUNBZ0lDQjlYRzRnSUNBZ2ZWeHVYRzRnSUNBZ2NtVjBkWEp1SUdaaGJITmxPMXh1SUNCOUxGeHVYRzRnSUdGME9pQm1kVzVqZEdsdmJpaGpiMnhzWldOMGFXOXVMQ0J1TENCMGFHVmZaR1ZtWVhWc2RDQTlJRzUxYkd3cGUxeHVJQ0FnSUdsbUtHNGdQaUIwYUdsekxtTnZkVzUwS0dOdmJHeGxZM1JwYjI0cElIeDhJRzRnUENBd0tYdGNiaUFnSUNBZ0lISmxkSFZ5YmlCMGFHVmZaR1ZtWVhWc2REdGNiaUFnSUNCOVhHNWNiaUFnSUNCeVpYUjFjbTRnWTI5c2JHVmpkR2x2Ymx0dVhUdGNiaUFnZlN4Y2JseHVJQ0JqYjI1allYUTZJR1oxYm1OMGFXOXVLQzR1TG1WdWRXMWhZbXhsY3lsN1hHNGdJQ0FnY21WMGRYSnVJR1Z1ZFcxaFlteGxjMXN3WFM1amIyNWpZWFFvWlc1MWJXRmliR1Z6V3pGZEtUdGNiaUFnZlN4Y2JseHVJQ0JqYjNWdWREb2dablZ1WTNScGIyNG9ZMjlzYkdWamRHbHZiaXdnWm5WdUlEMGdiblZzYkNsN1hHNGdJQ0FnYVdZb1puVnVJRDA5SUc1MWJHd3BlMXh1SUNBZ0lDQWdjbVYwZFhKdUlHTnZiR3hsWTNScGIyNHViR1Z1WjNSb08xeHVJQ0FnSUgwZ1pXeHpaU0I3WEc0Z0lDQWdJQ0J5WlhSMWNtNGdZMjlzYkdWamRHbHZiaTVtYVd4MFpYSW9ablZ1S1M1c1pXNW5kR2c3WEc0Z0lDQWdmVnh1SUNCOUxGeHVYRzRnSUdSeWIzQTZJR1oxYm1OMGFXOXVLR052Ykd4bFkzUnBiMjRzSUdOdmRXNTBLWHRjYmlBZ0lDQnlaWFIxY200Z1kyOXNiR1ZqZEdsdmJpNXpiR2xqWlNoamIzVnVkQ2s3WEc0Z0lIMHNYRzVjYmlBZ1pISnZjRjkzYUdsc1pUb2dablZ1WTNScGIyNG9ZMjlzYkdWamRHbHZiaXdnWm5WdUtYdGNiaUFnSUNCc1pYUWdZMjkxYm5RZ1BTQXdPMXh1WEc0Z0lDQWdabTl5S0d4bGRDQmxiR1Z0SUc5bUlHTnZiR3hsWTNScGIyNHBlMXh1SUNBZ0lDQWdhV1lvWm5WdUtHVnNaVzBwS1h0Y2JpQWdJQ0FnSUNBZ1kyOTFiblFnUFNCamIzVnVkQ0FySURFN1hHNGdJQ0FnSUNCOVpXeHpaWHRjYmlBZ0lDQWdJQ0FnWW5KbFlXczdYRzRnSUNBZ0lDQjlYRzRnSUNBZ2ZWeHVYRzRnSUNBZ2NtVjBkWEp1SUdOdmJHeGxZM1JwYjI0dWMyeHBZMlVvWTI5MWJuUXBPMXh1SUNCOUxGeHVYRzRnSUdWaFkyZzZJR1oxYm1OMGFXOXVLR052Ykd4bFkzUnBiMjRzSUdaMWJpbDdYRzRnSUNBZ1ptOXlLR3hsZENCbGJHVnRJRzltSUdOdmJHeGxZM1JwYjI0cGUxeHVJQ0FnSUNBZ1puVnVLR1ZzWlcwcE8xeHVJQ0FnSUgxY2JpQWdmU3hjYmx4dUlDQmxiWEIwZVY5ZmNXMWhjbXRmWHpvZ1puVnVZM1JwYjI0b1kyOXNiR1ZqZEdsdmJpbDdYRzRnSUNBZ2NtVjBkWEp1SUdOdmJHeGxZM1JwYjI0dWJHVnVaM1JvSUQwOVBTQXdPMXh1SUNCOUxGeHVYRzRnSUdabGRHTm9PaUJtZFc1amRHbHZiaWhqYjJ4c1pXTjBhVzl1TENCdUtYdGNiaUFnSUNCcFppaEJjbkpoZVM1cGMwRnljbUY1S0dOdmJHeGxZM1JwYjI0cEtYdGNiaUFnSUNBZ0lHbG1LRzRnUENCMGFHbHpMbU52ZFc1MEtHTnZiR3hsWTNScGIyNHBJQ1ltSUc0Z1BqMGdNQ2w3WEc0Z0lDQWdJQ0FnSUhKbGRIVnliaUJ1WlhjZ1EyOXlaUzVVZFhCc1pTaFRlVzFpYjJ3dVptOXlLRndpYjJ0Y0lpa3NJR052Ykd4bFkzUnBiMjViYmwwcE8xeHVJQ0FnSUNBZ2ZXVnNjMlY3WEc0Z0lDQWdJQ0FnSUhKbGRIVnliaUJUZVcxaWIyd3VabTl5S0Z3aVpYSnliM0pjSWlrN1hHNGdJQ0FnSUNCOVhHNGdJQ0FnZlZ4dVhHNGdJQ0FnZEdoeWIzY2dibVYzSUVWeWNtOXlLRndpWTI5c2JHVmpkR2x2YmlCcGN5QnViM1FnWVc0Z1JXNTFiV1Z5WVdKc1pWd2lLVHRjYmlBZ2ZTeGNibHh1SUNCbVpYUmphRjlmWlcxaGNtdGZYem9nWm5WdVkzUnBiMjRvWTI5c2JHVmpkR2x2Yml3Z2JpbDdYRzRnSUNBZ2FXWW9RWEp5WVhrdWFYTkJjbkpoZVNoamIyeHNaV04wYVc5dUtTbDdYRzRnSUNBZ0lDQnBaaWh1SUR3Z2RHaHBjeTVqYjNWdWRDaGpiMnhzWldOMGFXOXVLU0FtSmlCdUlENDlJREFwZTF4dUlDQWdJQ0FnSUNCeVpYUjFjbTRnWTI5c2JHVmpkR2x2Ymx0dVhUdGNiaUFnSUNBZ0lIMWxiSE5sZTF4dUlDQWdJQ0FnSUNCMGFISnZkeUJ1WlhjZ1JYSnliM0lvWENKdmRYUWdiMllnWW05MWJtUnpJR1Z5Y205eVhDSXBPMXh1SUNBZ0lDQWdmVnh1SUNBZ0lIMWNibHh1SUNBZ0lIUm9jbTkzSUc1bGR5QkZjbkp2Y2loY0ltTnZiR3hsWTNScGIyNGdhWE1nYm05MElHRnVJRVZ1ZFcxbGNtRmliR1ZjSWlrN1hHNGdJSDBzWEc1Y2JpQWdabWxzZEdWeU9pQm1kVzVqZEdsdmJpaGpiMnhzWldOMGFXOXVMQ0JtZFc0cGUxeHVJQ0FnSUd4bGRDQnlaWE4xYkhRZ1BTQmJYVHRjYmx4dUlDQWdJR1p2Y2loc1pYUWdaV3hsYlNCdlppQmpiMnhzWldOMGFXOXVLWHRjYmlBZ0lDQWdJR2xtS0daMWJpaGxiR1Z0S1NsN1hHNGdJQ0FnSUNBZ0lISmxjM1ZzZEM1d2RYTm9LR1ZzWlcwcE8xeHVJQ0FnSUNBZ2ZWeHVJQ0FnSUgxY2JseHVJQ0FnSUhKbGRIVnliaUJ5WlhOMWJIUTdYRzRnSUgwc1hHNWNiaUFnWm1sc2RHVnlYMjFoY0RvZ1puVnVZM1JwYjI0b1kyOXNiR1ZqZEdsdmJpd2dabWxzZEdWeUxDQnRZWEJ3WlhJcGUxeHVJQ0FnSUhKbGRIVnliaUJGYm5WdExtMWhjQ2hGYm5WdExtWnBiSFJsY2loamIyeHNaV04wYVc5dUxDQm1hV3gwWlhJcExDQnRZWEJ3WlhJcE8xeHVJQ0I5TEZ4dVhHNGdJR1pwYm1RNklHWjFibU4wYVc5dUtHTnZiR3hsWTNScGIyNHNJR2xtWDI1dmJtVWdQU0J1ZFd4c0xDQm1kVzRwZTF4dUlDQWdJR1p2Y2loc1pYUWdaV3hsYlNCdlppQmpiMnhzWldOMGFXOXVLWHRjYmlBZ0lDQWdJR2xtS0daMWJpaGxiR1Z0S1NsN1hHNGdJQ0FnSUNBZ0lISmxkSFZ5YmlCbGJHVnRPMXh1SUNBZ0lDQWdmVnh1SUNBZ0lIMWNibHh1SUNBZ0lISmxkSFZ5YmlCcFpsOXViMjVsTzF4dUlDQjlMRnh1WEc0Z0lHbHVkRzg2SUdaMWJtTjBhVzl1S0dOdmJHeGxZM1JwYjI0c0lHeHBjM1FwZTF4dUlDQWdJSEpsZEhWeWJpQnNhWE4wTG1OdmJtTmhkQ2hqYjJ4c1pXTjBhVzl1S1R0Y2JpQWdmU3hjYmx4dUlDQnRZWEE2SUdaMWJtTjBhVzl1S0dOdmJHeGxZM1JwYjI0c0lHWjFiaWw3WEc0Z0lDQWdiR1YwSUhKbGMzVnNkQ0E5SUZ0ZE8xeHVYRzRnSUNBZ1ptOXlLR3hsZENCbGJHVnRJRzltSUdOdmJHeGxZM1JwYjI0cGUxeHVJQ0FnSUNBZ2NtVnpkV3gwTG5CMWMyZ29ablZ1S0dWc1pXMHBLVHRjYmlBZ0lDQjlYRzVjYmlBZ0lDQnlaWFIxY200Z2NtVnpkV3gwTzF4dUlDQjlMRnh1WEc0Z0lHMWhjRjl5WldSMVkyVTZJR1oxYm1OMGFXOXVLR052Ykd4bFkzUnBiMjRzSUdGall5d2dablZ1S1h0Y2JpQWdJQ0JzWlhRZ2JXRndjR1ZrSUQwZ1QySnFaV04wTG1aeVpXVjZaU2hiWFNrN1hHNGdJQ0FnYkdWMElIUm9aVjloWTJNZ1BTQmhZMk03WEc1Y2JpQWdJQ0JtYjNJZ0tIWmhjaUJwSUQwZ01Ec2dhU0E4SUhSb2FYTXVZMjkxYm5Rb1kyOXNiR1ZqZEdsdmJpazdJR2tyS3lrZ2UxeHVJQ0FnSUNBZ2JHVjBJSFIxY0d4bElEMGdablZ1S0dOdmJHeGxZM1JwYjI1YmFWMHNJSFJvWlY5aFkyTXBPMXh1WEc0Z0lDQWdJQ0IwYUdWZllXTmpJRDBnZEhWd2JHVXVaMlYwS0RFcE8xeHVJQ0FnSUNBZ2JXRndjR1ZrSUQwZ1QySnFaV04wTG1aeVpXVjZaU2h0WVhCd1pXUXVZMjl1WTJGMEtGdDBkWEJzWlM1blpYUW9NQ2xkS1NrN1hHNGdJQ0FnZlZ4dVhHNGdJQ0FnY21WMGRYSnVJRzVsZHlCRGIzSmxMbFIxY0d4bEtHMWhjSEJsWkN3Z2RHaGxYMkZqWXlrN1hHNGdJSDBzWEc1Y2JpQWdiV1Z0WW1WeVgxOXhiV0Z5YTE5Zk9pQm1kVzVqZEdsdmJpaGpiMnhzWldOMGFXOXVMQ0IyWVd4MVpTbDdYRzRnSUNBZ2NtVjBkWEp1SUdOdmJHeGxZM1JwYjI0dWFXNWpiSFZrWlhNb2RtRnNkV1VwTzF4dUlDQjlMRnh1WEc0Z0lISmxaSFZqWlRvZ1puVnVZM1JwYjI0b1kyOXNiR1ZqZEdsdmJpd2dZV05qTENCbWRXNHBlMXh1SUNBZ0lHeGxkQ0IwYUdWZllXTmpJRDBnWVdOak8xeHVYRzRnSUNBZ1ptOXlJQ2gyWVhJZ2FTQTlJREE3SUdrZ1BDQjBhR2x6TG1OdmRXNTBLR052Ykd4bFkzUnBiMjRwT3lCcEt5c3BJSHRjYmlBZ0lDQWdJR3hsZENCMGRYQnNaU0E5SUdaMWJpaGpiMnhzWldOMGFXOXVXMmxkTENCMGFHVmZZV05qS1R0Y2JseHVJQ0FnSUNBZ2RHaGxYMkZqWXlBOUlIUjFjR3hsTG1kbGRDZ3hLVHRjYmlBZ0lDQjlYRzVjYmlBZ0lDQnlaWFIxY200Z2RHaGxYMkZqWXp0Y2JpQWdmU3hjYmx4dUlDQjBZV3RsT2lCbWRXNWpkR2x2YmloamIyeHNaV04wYVc5dUxDQmpiM1Z1ZENsN1hHNGdJQ0FnY21WMGRYSnVJR052Ykd4bFkzUnBiMjR1YzJ4cFkyVW9NQ3dnWTI5MWJuUXBPMXh1SUNCOUxGeHVYRzRnSUhSaGEyVmZaWFpsY25rNklHWjFibU4wYVc5dUtHTnZiR3hsWTNScGIyNHNJRzUwYUNsN1hHNGdJQ0FnYkdWMElISmxjM1ZzZENBOUlGdGRPMXh1SUNBZ0lHeGxkQ0JwYm1SbGVDQTlJREE3WEc1Y2JpQWdJQ0JtYjNJb2JHVjBJR1ZzWlcwZ2IyWWdZMjlzYkdWamRHbHZiaWw3WEc0Z0lDQWdJQ0JwWmlocGJtUmxlQ0FsSUc1MGFDQTlQVDBnTUNsN1hHNGdJQ0FnSUNBZ0lISmxjM1ZzZEM1d2RYTm9LR1ZzWlcwcE8xeHVJQ0FnSUNBZ2ZWeHVJQ0FnSUgxY2JseHVJQ0FnSUhKbGRIVnliaUJQWW1wbFkzUXVabkpsWlhwbEtISmxjM1ZzZENrN1hHNGdJSDBzWEc1Y2JpQWdkR0ZyWlY5M2FHbHNaVG9nWm5WdVkzUnBiMjRvWTI5c2JHVmpkR2x2Yml3Z1puVnVLWHRjYmlBZ0lDQnNaWFFnWTI5MWJuUWdQU0F3TzF4dVhHNGdJQ0FnWm05eUtHeGxkQ0JsYkdWdElHOW1JR052Ykd4bFkzUnBiMjRwZTF4dUlDQWdJQ0FnYVdZb1puVnVLR1ZzWlcwcEtYdGNiaUFnSUNBZ0lDQWdZMjkxYm5RZ1BTQmpiM1Z1ZENBcklERTdYRzRnSUNBZ0lDQjlaV3h6Wlh0Y2JpQWdJQ0FnSUNBZ1luSmxZV3M3WEc0Z0lDQWdJQ0I5WEc0Z0lDQWdmVnh1WEc0Z0lDQWdjbVYwZFhKdUlHTnZiR3hsWTNScGIyNHVjMnhwWTJVb01Dd2dZMjkxYm5RcE8xeHVJQ0I5TEZ4dVhHNGdJSFJ2WDJ4cGMzUTZJR1oxYm1OMGFXOXVLR052Ykd4bFkzUnBiMjRwZTF4dUlDQWdJSEpsZEhWeWJpQmpiMnhzWldOMGFXOXVPMXh1SUNCOVhHNTlPMXh1WEc1bGVIQnZjblFnWkdWbVlYVnNkQ0JGYm5WdE8xeHVJbDBzSW5OdmRYSmpaVkp2YjNRaU9pSXZjMjkxY21ObEx5SjlcbiIsImxldCBWaXJ0dWFsRE9NID0gZnVuY3Rpb24gKGUpIHtcbiAgICByZXR1cm4gZSgpO1xufShmdW5jdGlvbiAoKSB7XG4gICAgdmFyIGRlZmluZSwgbW9kdWxlLCBleHBvcnRzO1xuICAgIHJldHVybiBmdW5jdGlvbiBlKHQsIG4sIHIpIHtcbiAgICAgICAgZnVuY3Rpb24gcyhvLCB1KSB7XG4gICAgICAgICAgICBpZiAoIW5bb10pIHtcbiAgICAgICAgICAgICAgICBpZiAoIXRbb10pIHtcbiAgICAgICAgICAgICAgICAgICAgdmFyIGEgPSB0eXBlb2YgcmVxdWlyZSA9PSBcImZ1bmN0aW9uXCIgJiYgcmVxdWlyZTtcbiAgICAgICAgICAgICAgICAgICAgaWYgKCF1ICYmIGEpIHJldHVybiBhKG8sICEwKTtcbiAgICAgICAgICAgICAgICAgICAgaWYgKGkpIHJldHVybiBpKG8sICEwKTtcbiAgICAgICAgICAgICAgICAgICAgdmFyIGYgPSBuZXcgRXJyb3IoXCJDYW5ub3QgZmluZCBtb2R1bGUgJ1wiICsgbyArIFwiJ1wiKTtcbiAgICAgICAgICAgICAgICAgICAgdGhyb3cgZi5jb2RlID0gXCJNT0RVTEVfTk9UX0ZPVU5EXCIsIGY7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHZhciBsID0gbltvXSA9IHtcbiAgICAgICAgICAgICAgICAgICAgZXhwb3J0czoge31cbiAgICAgICAgICAgICAgICB9O1xuICAgICAgICAgICAgICAgIHRbb11bMF0uY2FsbChsLmV4cG9ydHMsIGZ1bmN0aW9uIChlKSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciBuID0gdFtvXVsxXVtlXTtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHMobiA/IG4gOiBlKTtcbiAgICAgICAgICAgICAgICB9LCBsLCBsLmV4cG9ydHMsIGUsIHQsIG4sIHIpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmV0dXJuIG5bb10uZXhwb3J0cztcbiAgICAgICAgfVxuICAgICAgICB2YXIgaSA9IHR5cGVvZiByZXF1aXJlID09IFwiZnVuY3Rpb25cIiAmJiByZXF1aXJlO1xuICAgICAgICBmb3IgKHZhciBvID0gMDsgbyA8IHIubGVuZ3RoOyBvKyspIHMocltvXSk7XG4gICAgICAgIHJldHVybiBzO1xuICAgIH0oe1xuICAgICAgICAxOiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge1xuXG4gICAgICAgICAgICB2YXIgY3JlYXRlRWxlbWVudCA9IHJlcXVpcmUoXCIuL3Zkb20vY3JlYXRlLWVsZW1lbnQuanNcIik7XG5cbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gY3JlYXRlRWxlbWVudDtcbiAgICAgICAgfSwgeyBcIi4vdmRvbS9jcmVhdGUtZWxlbWVudC5qc1wiOiAxNSB9XSwgMjogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHtcbiAgICAgICAgICAgIHZhciBkaWZmID0gcmVxdWlyZShcIi4vdnRyZWUvZGlmZi5qc1wiKTtcblxuICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBkaWZmO1xuICAgICAgICB9LCB7IFwiLi92dHJlZS9kaWZmLmpzXCI6IDM1IH1dLCAzOiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge1xuICAgICAgICAgICAgdmFyIGggPSByZXF1aXJlKFwiLi92aXJ0dWFsLWh5cGVyc2NyaXB0L2luZGV4LmpzXCIpO1xuXG4gICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IGg7XG4gICAgICAgIH0sIHsgXCIuL3ZpcnR1YWwtaHlwZXJzY3JpcHQvaW5kZXguanNcIjogMjIgfV0sIDQ6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICB2YXIgZGlmZiA9IHJlcXVpcmUoXCIuL2RpZmYuanNcIik7XG4gICAgICAgICAgICB2YXIgcGF0Y2ggPSByZXF1aXJlKFwiLi9wYXRjaC5qc1wiKTtcbiAgICAgICAgICAgIHZhciBoID0gcmVxdWlyZShcIi4vaC5qc1wiKTtcbiAgICAgICAgICAgIHZhciBjcmVhdGUgPSByZXF1aXJlKFwiLi9jcmVhdGUtZWxlbWVudC5qc1wiKTtcbiAgICAgICAgICAgIHZhciBWTm9kZSA9IHJlcXVpcmUoJy4vdm5vZGUvdm5vZGUuanMnKTtcbiAgICAgICAgICAgIHZhciBWVGV4dCA9IHJlcXVpcmUoJy4vdm5vZGUvdnRleHQuanMnKTtcblxuICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSB7XG4gICAgICAgICAgICAgICAgZGlmZjogZGlmZixcbiAgICAgICAgICAgICAgICBwYXRjaDogcGF0Y2gsXG4gICAgICAgICAgICAgICAgaDogaCxcbiAgICAgICAgICAgICAgICBjcmVhdGU6IGNyZWF0ZSxcbiAgICAgICAgICAgICAgICBWTm9kZTogVk5vZGUsXG4gICAgICAgICAgICAgICAgVlRleHQ6IFZUZXh0XG4gICAgICAgICAgICB9O1xuICAgICAgICB9LCB7IFwiLi9jcmVhdGUtZWxlbWVudC5qc1wiOiAxLCBcIi4vZGlmZi5qc1wiOiAyLCBcIi4vaC5qc1wiOiAzLCBcIi4vcGF0Y2guanNcIjogMTMsIFwiLi92bm9kZS92bm9kZS5qc1wiOiAzMSwgXCIuL3Zub2RlL3Z0ZXh0LmpzXCI6IDMzIH1dLCA1OiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge1xuICAgICAgICAgICAgLyohXG4gICAgICAgICAgICAgKiBDcm9zcy1Ccm93c2VyIFNwbGl0IDEuMS4xXG4gICAgICAgICAgICAgKiBDb3B5cmlnaHQgMjAwNy0yMDEyIFN0ZXZlbiBMZXZpdGhhbiA8c3RldmVubGV2aXRoYW4uY29tPlxuICAgICAgICAgICAgICogQXZhaWxhYmxlIHVuZGVyIHRoZSBNSVQgTGljZW5zZVxuICAgICAgICAgICAgICogRUNNQVNjcmlwdCBjb21wbGlhbnQsIHVuaWZvcm0gY3Jvc3MtYnJvd3NlciBzcGxpdCBtZXRob2RcbiAgICAgICAgICAgICAqL1xuXG4gICAgICAgICAgICAvKipcbiAgICAgICAgICAgICAqIFNwbGl0cyBhIHN0cmluZyBpbnRvIGFuIGFycmF5IG9mIHN0cmluZ3MgdXNpbmcgYSByZWdleCBvciBzdHJpbmcgc2VwYXJhdG9yLiBNYXRjaGVzIG9mIHRoZVxuICAgICAgICAgICAgICogc2VwYXJhdG9yIGFyZSBub3QgaW5jbHVkZWQgaW4gdGhlIHJlc3VsdCBhcnJheS4gSG93ZXZlciwgaWYgYHNlcGFyYXRvcmAgaXMgYSByZWdleCB0aGF0IGNvbnRhaW5zXG4gICAgICAgICAgICAgKiBjYXB0dXJpbmcgZ3JvdXBzLCBiYWNrcmVmZXJlbmNlcyBhcmUgc3BsaWNlZCBpbnRvIHRoZSByZXN1bHQgZWFjaCB0aW1lIGBzZXBhcmF0b3JgIGlzIG1hdGNoZWQuXG4gICAgICAgICAgICAgKiBGaXhlcyBicm93c2VyIGJ1Z3MgY29tcGFyZWQgdG8gdGhlIG5hdGl2ZSBgU3RyaW5nLnByb3RvdHlwZS5zcGxpdGAgYW5kIGNhbiBiZSB1c2VkIHJlbGlhYmx5XG4gICAgICAgICAgICAgKiBjcm9zcy1icm93c2VyLlxuICAgICAgICAgICAgICogQHBhcmFtIHtTdHJpbmd9IHN0ciBTdHJpbmcgdG8gc3BsaXQuXG4gICAgICAgICAgICAgKiBAcGFyYW0ge1JlZ0V4cHxTdHJpbmd9IHNlcGFyYXRvciBSZWdleCBvciBzdHJpbmcgdG8gdXNlIGZvciBzZXBhcmF0aW5nIHRoZSBzdHJpbmcuXG4gICAgICAgICAgICAgKiBAcGFyYW0ge051bWJlcn0gW2xpbWl0XSBNYXhpbXVtIG51bWJlciBvZiBpdGVtcyB0byBpbmNsdWRlIGluIHRoZSByZXN1bHQgYXJyYXkuXG4gICAgICAgICAgICAgKiBAcmV0dXJucyB7QXJyYXl9IEFycmF5IG9mIHN1YnN0cmluZ3MuXG4gICAgICAgICAgICAgKiBAZXhhbXBsZVxuICAgICAgICAgICAgICpcbiAgICAgICAgICAgICAqIC8vIEJhc2ljIHVzZVxuICAgICAgICAgICAgICogc3BsaXQoJ2EgYiBjIGQnLCAnICcpO1xuICAgICAgICAgICAgICogLy8gLT4gWydhJywgJ2InLCAnYycsICdkJ11cbiAgICAgICAgICAgICAqXG4gICAgICAgICAgICAgKiAvLyBXaXRoIGxpbWl0XG4gICAgICAgICAgICAgKiBzcGxpdCgnYSBiIGMgZCcsICcgJywgMik7XG4gICAgICAgICAgICAgKiAvLyAtPiBbJ2EnLCAnYiddXG4gICAgICAgICAgICAgKlxuICAgICAgICAgICAgICogLy8gQmFja3JlZmVyZW5jZXMgaW4gcmVzdWx0IGFycmF5XG4gICAgICAgICAgICAgKiBzcGxpdCgnLi53b3JkMSB3b3JkMi4uJywgLyhbYS16XSspKFxcZCspL2kpO1xuICAgICAgICAgICAgICogLy8gLT4gWycuLicsICd3b3JkJywgJzEnLCAnICcsICd3b3JkJywgJzInLCAnLi4nXVxuICAgICAgICAgICAgICovXG4gICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uIHNwbGl0KHVuZGVmKSB7XG5cbiAgICAgICAgICAgICAgICB2YXIgbmF0aXZlU3BsaXQgPSBTdHJpbmcucHJvdG90eXBlLnNwbGl0LFxuICAgICAgICAgICAgICAgICAgICBjb21wbGlhbnRFeGVjTnBjZyA9IC8oKT8/Ly5leGVjKFwiXCIpWzFdID09PSB1bmRlZixcblxuICAgICAgICAgICAgICAgIC8vIE5QQ0c6IG5vbnBhcnRpY2lwYXRpbmcgY2FwdHVyaW5nIGdyb3VwXG4gICAgICAgICAgICAgICAgc2VsZjtcblxuICAgICAgICAgICAgICAgIHNlbGYgPSBmdW5jdGlvbiAoc3RyLCBzZXBhcmF0b3IsIGxpbWl0KSB7XG4gICAgICAgICAgICAgICAgICAgIC8vIElmIGBzZXBhcmF0b3JgIGlzIG5vdCBhIHJlZ2V4LCB1c2UgYG5hdGl2ZVNwbGl0YFxuICAgICAgICAgICAgICAgICAgICBpZiAoT2JqZWN0LnByb3RvdHlwZS50b1N0cmluZy5jYWxsKHNlcGFyYXRvcikgIT09IFwiW29iamVjdCBSZWdFeHBdXCIpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBuYXRpdmVTcGxpdC5jYWxsKHN0ciwgc2VwYXJhdG9yLCBsaW1pdCk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgdmFyIG91dHB1dCA9IFtdLFxuICAgICAgICAgICAgICAgICAgICAgICAgZmxhZ3MgPSAoc2VwYXJhdG9yLmlnbm9yZUNhc2UgPyBcImlcIiA6IFwiXCIpICsgKHNlcGFyYXRvci5tdWx0aWxpbmUgPyBcIm1cIiA6IFwiXCIpICsgKHNlcGFyYXRvci5leHRlbmRlZCA/IFwieFwiIDogXCJcIikgKyAoIC8vIFByb3Bvc2VkIGZvciBFUzZcbiAgICAgICAgICAgICAgICAgICAgc2VwYXJhdG9yLnN0aWNreSA/IFwieVwiIDogXCJcIiksXG5cbiAgICAgICAgICAgICAgICAgICAgLy8gRmlyZWZveCAzK1xuICAgICAgICAgICAgICAgICAgICBsYXN0TGFzdEluZGV4ID0gMCxcblxuICAgICAgICAgICAgICAgICAgICAvLyBNYWtlIGBnbG9iYWxgIGFuZCBhdm9pZCBgbGFzdEluZGV4YCBpc3N1ZXMgYnkgd29ya2luZyB3aXRoIGEgY29weVxuICAgICAgICAgICAgICAgICAgICBzZXBhcmF0b3IgPSBuZXcgUmVnRXhwKHNlcGFyYXRvci5zb3VyY2UsIGZsYWdzICsgXCJnXCIpLFxuICAgICAgICAgICAgICAgICAgICAgICAgc2VwYXJhdG9yMixcbiAgICAgICAgICAgICAgICAgICAgICAgIG1hdGNoLFxuICAgICAgICAgICAgICAgICAgICAgICAgbGFzdEluZGV4LFxuICAgICAgICAgICAgICAgICAgICAgICAgbGFzdExlbmd0aDtcbiAgICAgICAgICAgICAgICAgICAgc3RyICs9IFwiXCI7IC8vIFR5cGUtY29udmVydFxuICAgICAgICAgICAgICAgICAgICBpZiAoIWNvbXBsaWFudEV4ZWNOcGNnKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAvLyBEb2Vzbid0IG5lZWQgZmxhZ3MgZ3ksIGJ1dCB0aGV5IGRvbid0IGh1cnRcbiAgICAgICAgICAgICAgICAgICAgICAgIHNlcGFyYXRvcjIgPSBuZXcgUmVnRXhwKFwiXlwiICsgc2VwYXJhdG9yLnNvdXJjZSArIFwiJCg/IVxcXFxzKVwiLCBmbGFncyk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgLyogVmFsdWVzIGZvciBgbGltaXRgLCBwZXIgdGhlIHNwZWM6XG4gICAgICAgICAgICAgICAgICAgICAqIElmIHVuZGVmaW5lZDogNDI5NDk2NzI5NSAvLyBNYXRoLnBvdygyLCAzMikgLSAxXG4gICAgICAgICAgICAgICAgICAgICAqIElmIDAsIEluZmluaXR5LCBvciBOYU46IDBcbiAgICAgICAgICAgICAgICAgICAgICogSWYgcG9zaXRpdmUgbnVtYmVyOiBsaW1pdCA9IE1hdGguZmxvb3IobGltaXQpOyBpZiAobGltaXQgPiA0Mjk0OTY3Mjk1KSBsaW1pdCAtPSA0Mjk0OTY3Mjk2O1xuICAgICAgICAgICAgICAgICAgICAgKiBJZiBuZWdhdGl2ZSBudW1iZXI6IDQyOTQ5NjcyOTYgLSBNYXRoLmZsb29yKE1hdGguYWJzKGxpbWl0KSlcbiAgICAgICAgICAgICAgICAgICAgICogSWYgb3RoZXI6IFR5cGUtY29udmVydCwgdGhlbiB1c2UgdGhlIGFib3ZlIHJ1bGVzXG4gICAgICAgICAgICAgICAgICAgICAqL1xuICAgICAgICAgICAgICAgICAgICBsaW1pdCA9IGxpbWl0ID09PSB1bmRlZiA/IC0xID4+PiAwIDogLy8gTWF0aC5wb3coMiwgMzIpIC0gMVxuICAgICAgICAgICAgICAgICAgICBsaW1pdCA+Pj4gMDsgLy8gVG9VaW50MzIobGltaXQpXG4gICAgICAgICAgICAgICAgICAgIHdoaWxlIChtYXRjaCA9IHNlcGFyYXRvci5leGVjKHN0cikpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIGBzZXBhcmF0b3IubGFzdEluZGV4YCBpcyBub3QgcmVsaWFibGUgY3Jvc3MtYnJvd3NlclxuICAgICAgICAgICAgICAgICAgICAgICAgbGFzdEluZGV4ID0gbWF0Y2guaW5kZXggKyBtYXRjaFswXS5sZW5ndGg7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAobGFzdEluZGV4ID4gbGFzdExhc3RJbmRleCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIG91dHB1dC5wdXNoKHN0ci5zbGljZShsYXN0TGFzdEluZGV4LCBtYXRjaC5pbmRleCkpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIEZpeCBicm93c2VycyB3aG9zZSBgZXhlY2AgbWV0aG9kcyBkb24ndCBjb25zaXN0ZW50bHkgcmV0dXJuIGB1bmRlZmluZWRgIGZvclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIG5vbnBhcnRpY2lwYXRpbmcgY2FwdHVyaW5nIGdyb3Vwc1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmICghY29tcGxpYW50RXhlY05wY2cgJiYgbWF0Y2gubGVuZ3RoID4gMSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBtYXRjaFswXS5yZXBsYWNlKHNlcGFyYXRvcjIsIGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZvciAodmFyIGkgPSAxOyBpIDwgYXJndW1lbnRzLmxlbmd0aCAtIDI7IGkrKykge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChhcmd1bWVudHNbaV0gPT09IHVuZGVmKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1hdGNoW2ldID0gdW5kZWY7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKG1hdGNoLmxlbmd0aCA+IDEgJiYgbWF0Y2guaW5kZXggPCBzdHIubGVuZ3RoKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIEFycmF5LnByb3RvdHlwZS5wdXNoLmFwcGx5KG91dHB1dCwgbWF0Y2guc2xpY2UoMSkpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBsYXN0TGVuZ3RoID0gbWF0Y2hbMF0ubGVuZ3RoO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxhc3RMYXN0SW5kZXggPSBsYXN0SW5kZXg7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKG91dHB1dC5sZW5ndGggPj0gbGltaXQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHNlcGFyYXRvci5sYXN0SW5kZXggPT09IG1hdGNoLmluZGV4KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgc2VwYXJhdG9yLmxhc3RJbmRleCsrOyAvLyBBdm9pZCBhbiBpbmZpbml0ZSBsb29wXG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgaWYgKGxhc3RMYXN0SW5kZXggPT09IHN0ci5sZW5ndGgpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChsYXN0TGVuZ3RoIHx8ICFzZXBhcmF0b3IudGVzdChcIlwiKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIG91dHB1dC5wdXNoKFwiXCIpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgb3V0cHV0LnB1c2goc3RyLnNsaWNlKGxhc3RMYXN0SW5kZXgpKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICByZXR1cm4gb3V0cHV0Lmxlbmd0aCA+IGxpbWl0ID8gb3V0cHV0LnNsaWNlKDAsIGxpbWl0KSA6IG91dHB1dDtcbiAgICAgICAgICAgICAgICB9O1xuXG4gICAgICAgICAgICAgICAgcmV0dXJuIHNlbGY7XG4gICAgICAgICAgICB9KCk7XG4gICAgICAgIH0sIHt9XSwgNjogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHt9LCB7fV0sIDc6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICAndXNlIHN0cmljdCc7XG5cbiAgICAgICAgICAgIHZhciBPbmVWZXJzaW9uQ29uc3RyYWludCA9IHJlcXVpcmUoJ2luZGl2aWR1YWwvb25lLXZlcnNpb24nKTtcblxuICAgICAgICAgICAgdmFyIE1ZX1ZFUlNJT04gPSAnNyc7XG4gICAgICAgICAgICBPbmVWZXJzaW9uQ29uc3RyYWludCgnZXYtc3RvcmUnLCBNWV9WRVJTSU9OKTtcblxuICAgICAgICAgICAgdmFyIGhhc2hLZXkgPSAnX19FVl9TVE9SRV9LRVlAJyArIE1ZX1ZFUlNJT047XG5cbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gRXZTdG9yZTtcblxuICAgICAgICAgICAgZnVuY3Rpb24gRXZTdG9yZShlbGVtKSB7XG4gICAgICAgICAgICAgICAgdmFyIGhhc2ggPSBlbGVtW2hhc2hLZXldO1xuXG4gICAgICAgICAgICAgICAgaWYgKCFoYXNoKSB7XG4gICAgICAgICAgICAgICAgICAgIGhhc2ggPSBlbGVtW2hhc2hLZXldID0ge307XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgcmV0dXJuIGhhc2g7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0sIHsgXCJpbmRpdmlkdWFsL29uZS12ZXJzaW9uXCI6IDkgfV0sIDg6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICAoZnVuY3Rpb24gKGdsb2JhbCkge1xuICAgICAgICAgICAgICAgICd1c2Ugc3RyaWN0JztcblxuICAgICAgICAgICAgICAgIC8qZ2xvYmFsIHdpbmRvdywgZ2xvYmFsKi9cblxuICAgICAgICAgICAgICAgIHZhciByb290ID0gdHlwZW9mIHdpbmRvdyAhPT0gJ3VuZGVmaW5lZCcgPyB3aW5kb3cgOiB0eXBlb2YgZ2xvYmFsICE9PSAndW5kZWZpbmVkJyA/IGdsb2JhbCA6IHt9O1xuXG4gICAgICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBJbmRpdmlkdWFsO1xuXG4gICAgICAgICAgICAgICAgZnVuY3Rpb24gSW5kaXZpZHVhbChrZXksIHZhbHVlKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmIChrZXkgaW4gcm9vdCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHJvb3Rba2V5XTtcbiAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgIHJvb3Rba2V5XSA9IHZhbHVlO1xuXG4gICAgICAgICAgICAgICAgICAgIHJldHVybiB2YWx1ZTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9KS5jYWxsKHRoaXMsIHR5cGVvZiBnbG9iYWwgIT09IFwidW5kZWZpbmVkXCIgPyBnbG9iYWwgOiB0eXBlb2Ygc2VsZiAhPT0gXCJ1bmRlZmluZWRcIiA/IHNlbGYgOiB0eXBlb2Ygd2luZG93ICE9PSBcInVuZGVmaW5lZFwiID8gd2luZG93IDoge30pO1xuICAgICAgICB9LCB7fV0sIDk6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICAndXNlIHN0cmljdCc7XG5cbiAgICAgICAgICAgIHZhciBJbmRpdmlkdWFsID0gcmVxdWlyZSgnLi9pbmRleC5qcycpO1xuXG4gICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IE9uZVZlcnNpb247XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIE9uZVZlcnNpb24obW9kdWxlTmFtZSwgdmVyc2lvbiwgZGVmYXVsdFZhbHVlKSB7XG4gICAgICAgICAgICAgICAgdmFyIGtleSA9ICdfX0lORElWSURVQUxfT05FX1ZFUlNJT05fJyArIG1vZHVsZU5hbWU7XG4gICAgICAgICAgICAgICAgdmFyIGVuZm9yY2VLZXkgPSBrZXkgKyAnX0VORk9SQ0VfU0lOR0xFVE9OJztcblxuICAgICAgICAgICAgICAgIHZhciB2ZXJzaW9uVmFsdWUgPSBJbmRpdmlkdWFsKGVuZm9yY2VLZXksIHZlcnNpb24pO1xuXG4gICAgICAgICAgICAgICAgaWYgKHZlcnNpb25WYWx1ZSAhPT0gdmVyc2lvbikge1xuICAgICAgICAgICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ0NhbiBvbmx5IGhhdmUgb25lIGNvcHkgb2YgJyArIG1vZHVsZU5hbWUgKyAnLlxcbicgKyAnWW91IGFscmVhZHkgaGF2ZSB2ZXJzaW9uICcgKyB2ZXJzaW9uVmFsdWUgKyAnIGluc3RhbGxlZC5cXG4nICsgJ1RoaXMgbWVhbnMgeW91IGNhbm5vdCBpbnN0YWxsIHZlcnNpb24gJyArIHZlcnNpb24pO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHJldHVybiBJbmRpdmlkdWFsKGtleSwgZGVmYXVsdFZhbHVlKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSwgeyBcIi4vaW5kZXguanNcIjogOCB9XSwgMTA6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICAoZnVuY3Rpb24gKGdsb2JhbCkge1xuICAgICAgICAgICAgICAgIHZhciB0b3BMZXZlbCA9IHR5cGVvZiBnbG9iYWwgIT09ICd1bmRlZmluZWQnID8gZ2xvYmFsIDogdHlwZW9mIHdpbmRvdyAhPT0gJ3VuZGVmaW5lZCcgPyB3aW5kb3cgOiB7fTtcbiAgICAgICAgICAgICAgICB2YXIgbWluRG9jID0gcmVxdWlyZSgnbWluLWRvY3VtZW50Jyk7XG5cbiAgICAgICAgICAgICAgICBpZiAodHlwZW9mIGRvY3VtZW50ICE9PSAndW5kZWZpbmVkJykge1xuICAgICAgICAgICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IGRvY3VtZW50O1xuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciBkb2NjeSA9IHRvcExldmVsWydfX0dMT0JBTF9ET0NVTUVOVF9DQUNIRUA0J107XG5cbiAgICAgICAgICAgICAgICAgICAgaWYgKCFkb2NjeSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgZG9jY3kgPSB0b3BMZXZlbFsnX19HTE9CQUxfRE9DVU1FTlRfQ0FDSEVANCddID0gbWluRG9jO1xuICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBkb2NjeTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9KS5jYWxsKHRoaXMsIHR5cGVvZiBnbG9iYWwgIT09IFwidW5kZWZpbmVkXCIgPyBnbG9iYWwgOiB0eXBlb2Ygc2VsZiAhPT0gXCJ1bmRlZmluZWRcIiA/IHNlbGYgOiB0eXBlb2Ygd2luZG93ICE9PSBcInVuZGVmaW5lZFwiID8gd2luZG93IDoge30pO1xuICAgICAgICB9LCB7IFwibWluLWRvY3VtZW50XCI6IDYgfV0sIDExOiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge1xuICAgICAgICAgICAgXCJ1c2Ugc3RyaWN0XCI7XG5cbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gaXNPYmplY3QoeCkge1xuICAgICAgICAgICAgICAgIHJldHVybiB0eXBlb2YgeCA9PT0gXCJvYmplY3RcIiAmJiB4ICE9PSBudWxsO1xuICAgICAgICAgICAgfTtcbiAgICAgICAgfSwge31dLCAxMjogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHtcbiAgICAgICAgICAgIHZhciBuYXRpdmVJc0FycmF5ID0gQXJyYXkuaXNBcnJheTtcbiAgICAgICAgICAgIHZhciB0b1N0cmluZyA9IE9iamVjdC5wcm90b3R5cGUudG9TdHJpbmc7XG5cbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gbmF0aXZlSXNBcnJheSB8fCBpc0FycmF5O1xuXG4gICAgICAgICAgICBmdW5jdGlvbiBpc0FycmF5KG9iaikge1xuICAgICAgICAgICAgICAgIHJldHVybiB0b1N0cmluZy5jYWxsKG9iaikgPT09IFwiW29iamVjdCBBcnJheV1cIjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSwge31dLCAxMzogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHtcbiAgICAgICAgICAgIHZhciBwYXRjaCA9IHJlcXVpcmUoXCIuL3Zkb20vcGF0Y2guanNcIik7XG5cbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gcGF0Y2g7XG4gICAgICAgIH0sIHsgXCIuL3Zkb20vcGF0Y2guanNcIjogMTggfV0sIDE0OiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge1xuICAgICAgICAgICAgdmFyIGlzT2JqZWN0ID0gcmVxdWlyZShcImlzLW9iamVjdFwiKTtcbiAgICAgICAgICAgIHZhciBpc0hvb2sgPSByZXF1aXJlKFwiLi4vdm5vZGUvaXMtdmhvb2suanNcIik7XG5cbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gYXBwbHlQcm9wZXJ0aWVzO1xuXG4gICAgICAgICAgICBmdW5jdGlvbiBhcHBseVByb3BlcnRpZXMobm9kZSwgcHJvcHMsIHByZXZpb3VzKSB7XG4gICAgICAgICAgICAgICAgZm9yICh2YXIgcHJvcE5hbWUgaW4gcHJvcHMpIHtcbiAgICAgICAgICAgICAgICAgICAgdmFyIHByb3BWYWx1ZSA9IHByb3BzW3Byb3BOYW1lXTtcblxuICAgICAgICAgICAgICAgICAgICBpZiAocHJvcFZhbHVlID09PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJlbW92ZVByb3BlcnR5KG5vZGUsIHByb3BOYW1lLCBwcm9wVmFsdWUsIHByZXZpb3VzKTtcbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIGlmIChpc0hvb2socHJvcFZhbHVlKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgcmVtb3ZlUHJvcGVydHkobm9kZSwgcHJvcE5hbWUsIHByb3BWYWx1ZSwgcHJldmlvdXMpO1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHByb3BWYWx1ZS5ob29rKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcHJvcFZhbHVlLmhvb2sobm9kZSwgcHJvcE5hbWUsIHByZXZpb3VzID8gcHJldmlvdXNbcHJvcE5hbWVdIDogdW5kZWZpbmVkKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChpc09iamVjdChwcm9wVmFsdWUpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcGF0Y2hPYmplY3Qobm9kZSwgcHJvcHMsIHByZXZpb3VzLCBwcm9wTmFtZSwgcHJvcFZhbHVlKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgbm9kZVtwcm9wTmFtZV0gPSBwcm9wVmFsdWU7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIHJlbW92ZVByb3BlcnR5KG5vZGUsIHByb3BOYW1lLCBwcm9wVmFsdWUsIHByZXZpb3VzKSB7XG4gICAgICAgICAgICAgICAgaWYgKHByZXZpb3VzKSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciBwcmV2aW91c1ZhbHVlID0gcHJldmlvdXNbcHJvcE5hbWVdO1xuXG4gICAgICAgICAgICAgICAgICAgIGlmICghaXNIb29rKHByZXZpb3VzVmFsdWUpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAocHJvcE5hbWUgPT09IFwiYXR0cmlidXRlc1wiKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgZm9yICh2YXIgYXR0ck5hbWUgaW4gcHJldmlvdXNWYWx1ZSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBub2RlLnJlbW92ZUF0dHJpYnV0ZShhdHRyTmFtZSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIGlmIChwcm9wTmFtZSA9PT0gXCJzdHlsZVwiKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgZm9yICh2YXIgaSBpbiBwcmV2aW91c1ZhbHVlKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG5vZGUuc3R5bGVbaV0gPSBcIlwiO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAodHlwZW9mIHByZXZpb3VzVmFsdWUgPT09IFwic3RyaW5nXCIpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBub2RlW3Byb3BOYW1lXSA9IFwiXCI7XG4gICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIG5vZGVbcHJvcE5hbWVdID0gbnVsbDtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIGlmIChwcmV2aW91c1ZhbHVlLnVuaG9vaykge1xuICAgICAgICAgICAgICAgICAgICAgICAgcHJldmlvdXNWYWx1ZS51bmhvb2sobm9kZSwgcHJvcE5hbWUsIHByb3BWYWx1ZSk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIHBhdGNoT2JqZWN0KG5vZGUsIHByb3BzLCBwcmV2aW91cywgcHJvcE5hbWUsIHByb3BWYWx1ZSkge1xuICAgICAgICAgICAgICAgIHZhciBwcmV2aW91c1ZhbHVlID0gcHJldmlvdXMgPyBwcmV2aW91c1twcm9wTmFtZV0gOiB1bmRlZmluZWQ7XG5cbiAgICAgICAgICAgICAgICAvLyBTZXQgYXR0cmlidXRlc1xuICAgICAgICAgICAgICAgIGlmIChwcm9wTmFtZSA9PT0gXCJhdHRyaWJ1dGVzXCIpIHtcbiAgICAgICAgICAgICAgICAgICAgZm9yICh2YXIgYXR0ck5hbWUgaW4gcHJvcFZhbHVlKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICB2YXIgYXR0clZhbHVlID0gcHJvcFZhbHVlW2F0dHJOYW1lXTtcblxuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGF0dHJWYWx1ZSA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgbm9kZS5yZW1vdmVBdHRyaWJ1dGUoYXR0ck5hbWUpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBub2RlLnNldEF0dHJpYnV0ZShhdHRyTmFtZSwgYXR0clZhbHVlKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICBpZiAocHJldmlvdXNWYWx1ZSAmJiBpc09iamVjdChwcmV2aW91c1ZhbHVlKSAmJiBnZXRQcm90b3R5cGUocHJldmlvdXNWYWx1ZSkgIT09IGdldFByb3RvdHlwZShwcm9wVmFsdWUpKSB7XG4gICAgICAgICAgICAgICAgICAgIG5vZGVbcHJvcE5hbWVdID0gcHJvcFZhbHVlO1xuICAgICAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgaWYgKCFpc09iamVjdChub2RlW3Byb3BOYW1lXSkpIHtcbiAgICAgICAgICAgICAgICAgICAgbm9kZVtwcm9wTmFtZV0gPSB7fTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICB2YXIgcmVwbGFjZXIgPSBwcm9wTmFtZSA9PT0gXCJzdHlsZVwiID8gXCJcIiA6IHVuZGVmaW5lZDtcblxuICAgICAgICAgICAgICAgIGZvciAodmFyIGsgaW4gcHJvcFZhbHVlKSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciB2YWx1ZSA9IHByb3BWYWx1ZVtrXTtcbiAgICAgICAgICAgICAgICAgICAgbm9kZVtwcm9wTmFtZV1ba10gPSB2YWx1ZSA9PT0gdW5kZWZpbmVkID8gcmVwbGFjZXIgOiB2YWx1ZTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIGdldFByb3RvdHlwZSh2YWx1ZSkge1xuICAgICAgICAgICAgICAgIGlmIChPYmplY3QuZ2V0UHJvdG90eXBlT2YpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIE9iamVjdC5nZXRQcm90b3R5cGVPZih2YWx1ZSk7XG4gICAgICAgICAgICAgICAgfSBlbHNlIGlmICh2YWx1ZS5fX3Byb3RvX18pIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHZhbHVlLl9fcHJvdG9fXztcbiAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKHZhbHVlLmNvbnN0cnVjdG9yKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiB2YWx1ZS5jb25zdHJ1Y3Rvci5wcm90b3R5cGU7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9LCB7IFwiLi4vdm5vZGUvaXMtdmhvb2suanNcIjogMjYsIFwiaXMtb2JqZWN0XCI6IDExIH1dLCAxNTogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHtcbiAgICAgICAgICAgIHZhciBkb2N1bWVudCA9IHJlcXVpcmUoXCJnbG9iYWwvZG9jdW1lbnRcIik7XG5cbiAgICAgICAgICAgIHZhciBhcHBseVByb3BlcnRpZXMgPSByZXF1aXJlKFwiLi9hcHBseS1wcm9wZXJ0aWVzXCIpO1xuXG4gICAgICAgICAgICB2YXIgaXNWTm9kZSA9IHJlcXVpcmUoXCIuLi92bm9kZS9pcy12bm9kZS5qc1wiKTtcbiAgICAgICAgICAgIHZhciBpc1ZUZXh0ID0gcmVxdWlyZShcIi4uL3Zub2RlL2lzLXZ0ZXh0LmpzXCIpO1xuICAgICAgICAgICAgdmFyIGlzV2lkZ2V0ID0gcmVxdWlyZShcIi4uL3Zub2RlL2lzLXdpZGdldC5qc1wiKTtcbiAgICAgICAgICAgIHZhciBoYW5kbGVUaHVuayA9IHJlcXVpcmUoXCIuLi92bm9kZS9oYW5kbGUtdGh1bmsuanNcIik7XG5cbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gY3JlYXRlRWxlbWVudDtcblxuICAgICAgICAgICAgZnVuY3Rpb24gY3JlYXRlRWxlbWVudCh2bm9kZSwgb3B0cykge1xuICAgICAgICAgICAgICAgIHZhciBkb2MgPSBvcHRzID8gb3B0cy5kb2N1bWVudCB8fCBkb2N1bWVudCA6IGRvY3VtZW50O1xuICAgICAgICAgICAgICAgIHZhciB3YXJuID0gb3B0cyA/IG9wdHMud2FybiA6IG51bGw7XG5cbiAgICAgICAgICAgICAgICB2bm9kZSA9IGhhbmRsZVRodW5rKHZub2RlKS5hO1xuXG4gICAgICAgICAgICAgICAgaWYgKGlzV2lkZ2V0KHZub2RlKSkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gdm5vZGUuaW5pdCgpO1xuICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoaXNWVGV4dCh2bm9kZSkpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGRvYy5jcmVhdGVUZXh0Tm9kZSh2bm9kZS50ZXh0KTtcbiAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKCFpc1ZOb2RlKHZub2RlKSkge1xuICAgICAgICAgICAgICAgICAgICBpZiAod2Fybikge1xuICAgICAgICAgICAgICAgICAgICAgICAgd2FybihcIkl0ZW0gaXMgbm90IGEgdmFsaWQgdmlydHVhbCBkb20gbm9kZVwiLCB2bm9kZSk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIG51bGw7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgdmFyIG5vZGUgPSB2bm9kZS5uYW1lc3BhY2UgPT09IG51bGwgPyBkb2MuY3JlYXRlRWxlbWVudCh2bm9kZS50YWdOYW1lKSA6IGRvYy5jcmVhdGVFbGVtZW50TlModm5vZGUubmFtZXNwYWNlLCB2bm9kZS50YWdOYW1lKTtcblxuICAgICAgICAgICAgICAgIHZhciBwcm9wcyA9IHZub2RlLnByb3BlcnRpZXM7XG4gICAgICAgICAgICAgICAgYXBwbHlQcm9wZXJ0aWVzKG5vZGUsIHByb3BzKTtcblxuICAgICAgICAgICAgICAgIHZhciBjaGlsZHJlbiA9IHZub2RlLmNoaWxkcmVuO1xuXG4gICAgICAgICAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCBjaGlsZHJlbi5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgICAgICAgICB2YXIgY2hpbGROb2RlID0gY3JlYXRlRWxlbWVudChjaGlsZHJlbltpXSwgb3B0cyk7XG4gICAgICAgICAgICAgICAgICAgIGlmIChjaGlsZE5vZGUpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIG5vZGUuYXBwZW5kQ2hpbGQoY2hpbGROb2RlKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHJldHVybiBub2RlO1xuICAgICAgICAgICAgfVxuICAgICAgICB9LCB7IFwiLi4vdm5vZGUvaGFuZGxlLXRodW5rLmpzXCI6IDI0LCBcIi4uL3Zub2RlL2lzLXZub2RlLmpzXCI6IDI3LCBcIi4uL3Zub2RlL2lzLXZ0ZXh0LmpzXCI6IDI4LCBcIi4uL3Zub2RlL2lzLXdpZGdldC5qc1wiOiAyOSwgXCIuL2FwcGx5LXByb3BlcnRpZXNcIjogMTQsIFwiZ2xvYmFsL2RvY3VtZW50XCI6IDEwIH1dLCAxNjogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHtcbiAgICAgICAgICAgIC8vIE1hcHMgYSB2aXJ0dWFsIERPTSB0cmVlIG9udG8gYSByZWFsIERPTSB0cmVlIGluIGFuIGVmZmljaWVudCBtYW5uZXIuXG4gICAgICAgICAgICAvLyBXZSBkb24ndCB3YW50IHRvIHJlYWQgYWxsIG9mIHRoZSBET00gbm9kZXMgaW4gdGhlIHRyZWUgc28gd2UgdXNlXG4gICAgICAgICAgICAvLyB0aGUgaW4tb3JkZXIgdHJlZSBpbmRleGluZyB0byBlbGltaW5hdGUgcmVjdXJzaW9uIGRvd24gY2VydGFpbiBicmFuY2hlcy5cbiAgICAgICAgICAgIC8vIFdlIG9ubHkgcmVjdXJzZSBpbnRvIGEgRE9NIG5vZGUgaWYgd2Uga25vdyB0aGF0IGl0IGNvbnRhaW5zIGEgY2hpbGQgb2ZcbiAgICAgICAgICAgIC8vIGludGVyZXN0LlxuXG4gICAgICAgICAgICB2YXIgbm9DaGlsZCA9IHt9O1xuXG4gICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IGRvbUluZGV4O1xuXG4gICAgICAgICAgICBmdW5jdGlvbiBkb21JbmRleChyb290Tm9kZSwgdHJlZSwgaW5kaWNlcywgbm9kZXMpIHtcbiAgICAgICAgICAgICAgICBpZiAoIWluZGljZXMgfHwgaW5kaWNlcy5sZW5ndGggPT09IDApIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHt9O1xuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIGluZGljZXMuc29ydChhc2NlbmRpbmcpO1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gcmVjdXJzZShyb290Tm9kZSwgdHJlZSwgaW5kaWNlcywgbm9kZXMsIDApO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZnVuY3Rpb24gcmVjdXJzZShyb290Tm9kZSwgdHJlZSwgaW5kaWNlcywgbm9kZXMsIHJvb3RJbmRleCkge1xuICAgICAgICAgICAgICAgIG5vZGVzID0gbm9kZXMgfHwge307XG5cbiAgICAgICAgICAgICAgICBpZiAocm9vdE5vZGUpIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKGluZGV4SW5SYW5nZShpbmRpY2VzLCByb290SW5kZXgsIHJvb3RJbmRleCkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIG5vZGVzW3Jvb3RJbmRleF0gPSByb290Tm9kZTtcbiAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgIHZhciB2Q2hpbGRyZW4gPSB0cmVlLmNoaWxkcmVuO1xuXG4gICAgICAgICAgICAgICAgICAgIGlmICh2Q2hpbGRyZW4pIHtcblxuICAgICAgICAgICAgICAgICAgICAgICAgdmFyIGNoaWxkTm9kZXMgPSByb290Tm9kZS5jaGlsZE5vZGVzO1xuXG4gICAgICAgICAgICAgICAgICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IHRyZWUuY2hpbGRyZW4ubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICByb290SW5kZXggKz0gMTtcblxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZhciB2Q2hpbGQgPSB2Q2hpbGRyZW5baV0gfHwgbm9DaGlsZDtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB2YXIgbmV4dEluZGV4ID0gcm9vdEluZGV4ICsgKHZDaGlsZC5jb3VudCB8fCAwKTtcblxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIHNraXAgcmVjdXJzaW9uIGRvd24gdGhlIHRyZWUgaWYgdGhlcmUgYXJlIG5vIG5vZGVzIGRvd24gaGVyZVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChpbmRleEluUmFuZ2UoaW5kaWNlcywgcm9vdEluZGV4LCBuZXh0SW5kZXgpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlY3Vyc2UoY2hpbGROb2Rlc1tpXSwgdkNoaWxkLCBpbmRpY2VzLCBub2Rlcywgcm9vdEluZGV4KTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICByb290SW5kZXggPSBuZXh0SW5kZXg7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICByZXR1cm4gbm9kZXM7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIC8vIEJpbmFyeSBzZWFyY2ggZm9yIGFuIGluZGV4IGluIHRoZSBpbnRlcnZhbCBbbGVmdCwgcmlnaHRdXG4gICAgICAgICAgICBmdW5jdGlvbiBpbmRleEluUmFuZ2UoaW5kaWNlcywgbGVmdCwgcmlnaHQpIHtcbiAgICAgICAgICAgICAgICBpZiAoaW5kaWNlcy5sZW5ndGggPT09IDApIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHZhciBtaW5JbmRleCA9IDA7XG4gICAgICAgICAgICAgICAgdmFyIG1heEluZGV4ID0gaW5kaWNlcy5sZW5ndGggLSAxO1xuICAgICAgICAgICAgICAgIHZhciBjdXJyZW50SW5kZXg7XG4gICAgICAgICAgICAgICAgdmFyIGN1cnJlbnRJdGVtO1xuXG4gICAgICAgICAgICAgICAgd2hpbGUgKG1pbkluZGV4IDw9IG1heEluZGV4KSB7XG4gICAgICAgICAgICAgICAgICAgIGN1cnJlbnRJbmRleCA9IChtYXhJbmRleCArIG1pbkluZGV4KSAvIDIgPj4gMDtcbiAgICAgICAgICAgICAgICAgICAgY3VycmVudEl0ZW0gPSBpbmRpY2VzW2N1cnJlbnRJbmRleF07XG5cbiAgICAgICAgICAgICAgICAgICAgaWYgKG1pbkluZGV4ID09PSBtYXhJbmRleCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGN1cnJlbnRJdGVtID49IGxlZnQgJiYgY3VycmVudEl0ZW0gPD0gcmlnaHQ7XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoY3VycmVudEl0ZW0gPCBsZWZ0KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBtaW5JbmRleCA9IGN1cnJlbnRJbmRleCArIDE7XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoY3VycmVudEl0ZW0gPiByaWdodCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgbWF4SW5kZXggPSBjdXJyZW50SW5kZXggLSAxO1xuICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIGFzY2VuZGluZyhhLCBiKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGEgPiBiID8gMSA6IC0xO1xuICAgICAgICAgICAgfVxuICAgICAgICB9LCB7fV0sIDE3OiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge1xuICAgICAgICAgICAgdmFyIGFwcGx5UHJvcGVydGllcyA9IHJlcXVpcmUoXCIuL2FwcGx5LXByb3BlcnRpZXNcIik7XG5cbiAgICAgICAgICAgIHZhciBpc1dpZGdldCA9IHJlcXVpcmUoXCIuLi92bm9kZS9pcy13aWRnZXQuanNcIik7XG4gICAgICAgICAgICB2YXIgVlBhdGNoID0gcmVxdWlyZShcIi4uL3Zub2RlL3ZwYXRjaC5qc1wiKTtcblxuICAgICAgICAgICAgdmFyIHVwZGF0ZVdpZGdldCA9IHJlcXVpcmUoXCIuL3VwZGF0ZS13aWRnZXRcIik7XG5cbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gYXBwbHlQYXRjaDtcblxuICAgICAgICAgICAgZnVuY3Rpb24gYXBwbHlQYXRjaCh2cGF0Y2gsIGRvbU5vZGUsIHJlbmRlck9wdGlvbnMpIHtcbiAgICAgICAgICAgICAgICB2YXIgdHlwZSA9IHZwYXRjaC50eXBlO1xuICAgICAgICAgICAgICAgIHZhciB2Tm9kZSA9IHZwYXRjaC52Tm9kZTtcbiAgICAgICAgICAgICAgICB2YXIgcGF0Y2ggPSB2cGF0Y2gucGF0Y2g7XG5cbiAgICAgICAgICAgICAgICBzd2l0Y2ggKHR5cGUpIHtcbiAgICAgICAgICAgICAgICAgICAgY2FzZSBWUGF0Y2guUkVNT1ZFOlxuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHJlbW92ZU5vZGUoZG9tTm9kZSwgdk5vZGUpO1xuICAgICAgICAgICAgICAgICAgICBjYXNlIFZQYXRjaC5JTlNFUlQ6XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gaW5zZXJ0Tm9kZShkb21Ob2RlLCBwYXRjaCwgcmVuZGVyT3B0aW9ucyk7XG4gICAgICAgICAgICAgICAgICAgIGNhc2UgVlBhdGNoLlZURVhUOlxuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHN0cmluZ1BhdGNoKGRvbU5vZGUsIHZOb2RlLCBwYXRjaCwgcmVuZGVyT3B0aW9ucyk7XG4gICAgICAgICAgICAgICAgICAgIGNhc2UgVlBhdGNoLldJREdFVDpcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiB3aWRnZXRQYXRjaChkb21Ob2RlLCB2Tm9kZSwgcGF0Y2gsIHJlbmRlck9wdGlvbnMpO1xuICAgICAgICAgICAgICAgICAgICBjYXNlIFZQYXRjaC5WTk9ERTpcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiB2Tm9kZVBhdGNoKGRvbU5vZGUsIHZOb2RlLCBwYXRjaCwgcmVuZGVyT3B0aW9ucyk7XG4gICAgICAgICAgICAgICAgICAgIGNhc2UgVlBhdGNoLk9SREVSOlxuICAgICAgICAgICAgICAgICAgICAgICAgcmVvcmRlckNoaWxkcmVuKGRvbU5vZGUsIHBhdGNoKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBkb21Ob2RlO1xuICAgICAgICAgICAgICAgICAgICBjYXNlIFZQYXRjaC5QUk9QUzpcbiAgICAgICAgICAgICAgICAgICAgICAgIGFwcGx5UHJvcGVydGllcyhkb21Ob2RlLCBwYXRjaCwgdk5vZGUucHJvcGVydGllcyk7XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gZG9tTm9kZTtcbiAgICAgICAgICAgICAgICAgICAgY2FzZSBWUGF0Y2guVEhVTks6XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gcmVwbGFjZVJvb3QoZG9tTm9kZSwgcmVuZGVyT3B0aW9ucy5wYXRjaChkb21Ob2RlLCBwYXRjaCwgcmVuZGVyT3B0aW9ucykpO1xuICAgICAgICAgICAgICAgICAgICBkZWZhdWx0OlxuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGRvbU5vZGU7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBmdW5jdGlvbiByZW1vdmVOb2RlKGRvbU5vZGUsIHZOb2RlKSB7XG4gICAgICAgICAgICAgICAgdmFyIHBhcmVudE5vZGUgPSBkb21Ob2RlLnBhcmVudE5vZGU7XG5cbiAgICAgICAgICAgICAgICBpZiAocGFyZW50Tm9kZSkge1xuICAgICAgICAgICAgICAgICAgICBwYXJlbnROb2RlLnJlbW92ZUNoaWxkKGRvbU5vZGUpO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIGRlc3Ryb3lXaWRnZXQoZG9tTm9kZSwgdk5vZGUpO1xuXG4gICAgICAgICAgICAgICAgcmV0dXJuIG51bGw7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIGluc2VydE5vZGUocGFyZW50Tm9kZSwgdk5vZGUsIHJlbmRlck9wdGlvbnMpIHtcbiAgICAgICAgICAgICAgICB2YXIgbmV3Tm9kZSA9IHJlbmRlck9wdGlvbnMucmVuZGVyKHZOb2RlLCByZW5kZXJPcHRpb25zKTtcblxuICAgICAgICAgICAgICAgIGlmIChwYXJlbnROb2RlKSB7XG4gICAgICAgICAgICAgICAgICAgIHBhcmVudE5vZGUuYXBwZW5kQ2hpbGQobmV3Tm9kZSk7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgcmV0dXJuIHBhcmVudE5vZGU7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIHN0cmluZ1BhdGNoKGRvbU5vZGUsIGxlZnRWTm9kZSwgdlRleHQsIHJlbmRlck9wdGlvbnMpIHtcbiAgICAgICAgICAgICAgICB2YXIgbmV3Tm9kZTtcblxuICAgICAgICAgICAgICAgIGlmIChkb21Ob2RlLm5vZGVUeXBlID09PSAzKSB7XG4gICAgICAgICAgICAgICAgICAgIGRvbU5vZGUucmVwbGFjZURhdGEoMCwgZG9tTm9kZS5sZW5ndGgsIHZUZXh0LnRleHQpO1xuICAgICAgICAgICAgICAgICAgICBuZXdOb2RlID0gZG9tTm9kZTtcbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICB2YXIgcGFyZW50Tm9kZSA9IGRvbU5vZGUucGFyZW50Tm9kZTtcbiAgICAgICAgICAgICAgICAgICAgbmV3Tm9kZSA9IHJlbmRlck9wdGlvbnMucmVuZGVyKHZUZXh0LCByZW5kZXJPcHRpb25zKTtcblxuICAgICAgICAgICAgICAgICAgICBpZiAocGFyZW50Tm9kZSAmJiBuZXdOb2RlICE9PSBkb21Ob2RlKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBwYXJlbnROb2RlLnJlcGxhY2VDaGlsZChuZXdOb2RlLCBkb21Ob2RlKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHJldHVybiBuZXdOb2RlO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBmdW5jdGlvbiB3aWRnZXRQYXRjaChkb21Ob2RlLCBsZWZ0Vk5vZGUsIHdpZGdldCwgcmVuZGVyT3B0aW9ucykge1xuICAgICAgICAgICAgICAgIHZhciB1cGRhdGluZyA9IHVwZGF0ZVdpZGdldChsZWZ0Vk5vZGUsIHdpZGdldCk7XG4gICAgICAgICAgICAgICAgdmFyIG5ld05vZGU7XG5cbiAgICAgICAgICAgICAgICBpZiAodXBkYXRpbmcpIHtcbiAgICAgICAgICAgICAgICAgICAgbmV3Tm9kZSA9IHdpZGdldC51cGRhdGUobGVmdFZOb2RlLCBkb21Ob2RlKSB8fCBkb21Ob2RlO1xuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIG5ld05vZGUgPSByZW5kZXJPcHRpb25zLnJlbmRlcih3aWRnZXQsIHJlbmRlck9wdGlvbnMpO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHZhciBwYXJlbnROb2RlID0gZG9tTm9kZS5wYXJlbnROb2RlO1xuXG4gICAgICAgICAgICAgICAgaWYgKHBhcmVudE5vZGUgJiYgbmV3Tm9kZSAhPT0gZG9tTm9kZSkge1xuICAgICAgICAgICAgICAgICAgICBwYXJlbnROb2RlLnJlcGxhY2VDaGlsZChuZXdOb2RlLCBkb21Ob2RlKTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICBpZiAoIXVwZGF0aW5nKSB7XG4gICAgICAgICAgICAgICAgICAgIGRlc3Ryb3lXaWRnZXQoZG9tTm9kZSwgbGVmdFZOb2RlKTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICByZXR1cm4gbmV3Tm9kZTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZnVuY3Rpb24gdk5vZGVQYXRjaChkb21Ob2RlLCBsZWZ0Vk5vZGUsIHZOb2RlLCByZW5kZXJPcHRpb25zKSB7XG4gICAgICAgICAgICAgICAgdmFyIHBhcmVudE5vZGUgPSBkb21Ob2RlLnBhcmVudE5vZGU7XG4gICAgICAgICAgICAgICAgdmFyIG5ld05vZGUgPSByZW5kZXJPcHRpb25zLnJlbmRlcih2Tm9kZSwgcmVuZGVyT3B0aW9ucyk7XG5cbiAgICAgICAgICAgICAgICBpZiAocGFyZW50Tm9kZSAmJiBuZXdOb2RlICE9PSBkb21Ob2RlKSB7XG4gICAgICAgICAgICAgICAgICAgIHBhcmVudE5vZGUucmVwbGFjZUNoaWxkKG5ld05vZGUsIGRvbU5vZGUpO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHJldHVybiBuZXdOb2RlO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBmdW5jdGlvbiBkZXN0cm95V2lkZ2V0KGRvbU5vZGUsIHcpIHtcbiAgICAgICAgICAgICAgICBpZiAodHlwZW9mIHcuZGVzdHJveSA9PT0gXCJmdW5jdGlvblwiICYmIGlzV2lkZ2V0KHcpKSB7XG4gICAgICAgICAgICAgICAgICAgIHcuZGVzdHJveShkb21Ob2RlKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIHJlb3JkZXJDaGlsZHJlbihkb21Ob2RlLCBtb3Zlcykge1xuICAgICAgICAgICAgICAgIHZhciBjaGlsZE5vZGVzID0gZG9tTm9kZS5jaGlsZE5vZGVzO1xuICAgICAgICAgICAgICAgIHZhciBrZXlNYXAgPSB7fTtcbiAgICAgICAgICAgICAgICB2YXIgbm9kZTtcbiAgICAgICAgICAgICAgICB2YXIgcmVtb3ZlO1xuICAgICAgICAgICAgICAgIHZhciBpbnNlcnQ7XG5cbiAgICAgICAgICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IG1vdmVzLnJlbW92ZXMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgICAgICAgICAgcmVtb3ZlID0gbW92ZXMucmVtb3Zlc1tpXTtcbiAgICAgICAgICAgICAgICAgICAgbm9kZSA9IGNoaWxkTm9kZXNbcmVtb3ZlLmZyb21dO1xuICAgICAgICAgICAgICAgICAgICBpZiAocmVtb3ZlLmtleSkge1xuICAgICAgICAgICAgICAgICAgICAgICAga2V5TWFwW3JlbW92ZS5rZXldID0gbm9kZTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICBkb21Ob2RlLnJlbW92ZUNoaWxkKG5vZGUpO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHZhciBsZW5ndGggPSBjaGlsZE5vZGVzLmxlbmd0aDtcbiAgICAgICAgICAgICAgICBmb3IgKHZhciBqID0gMDsgaiA8IG1vdmVzLmluc2VydHMubGVuZ3RoOyBqKyspIHtcbiAgICAgICAgICAgICAgICAgICAgaW5zZXJ0ID0gbW92ZXMuaW5zZXJ0c1tqXTtcbiAgICAgICAgICAgICAgICAgICAgbm9kZSA9IGtleU1hcFtpbnNlcnQua2V5XTtcbiAgICAgICAgICAgICAgICAgICAgLy8gdGhpcyBpcyB0aGUgd2VpcmRlc3QgYnVnIGkndmUgZXZlciBzZWVuIGluIHdlYmtpdFxuICAgICAgICAgICAgICAgICAgICBkb21Ob2RlLmluc2VydEJlZm9yZShub2RlLCBpbnNlcnQudG8gPj0gbGVuZ3RoKysgPyBudWxsIDogY2hpbGROb2Rlc1tpbnNlcnQudG9dKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIHJlcGxhY2VSb290KG9sZFJvb3QsIG5ld1Jvb3QpIHtcbiAgICAgICAgICAgICAgICBpZiAob2xkUm9vdCAmJiBuZXdSb290ICYmIG9sZFJvb3QgIT09IG5ld1Jvb3QgJiYgb2xkUm9vdC5wYXJlbnROb2RlKSB7XG4gICAgICAgICAgICAgICAgICAgIG9sZFJvb3QucGFyZW50Tm9kZS5yZXBsYWNlQ2hpbGQobmV3Um9vdCwgb2xkUm9vdCk7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgcmV0dXJuIG5ld1Jvb3Q7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0sIHsgXCIuLi92bm9kZS9pcy13aWRnZXQuanNcIjogMjksIFwiLi4vdm5vZGUvdnBhdGNoLmpzXCI6IDMyLCBcIi4vYXBwbHktcHJvcGVydGllc1wiOiAxNCwgXCIuL3VwZGF0ZS13aWRnZXRcIjogMTkgfV0sIDE4OiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge1xuICAgICAgICAgICAgdmFyIGRvY3VtZW50ID0gcmVxdWlyZShcImdsb2JhbC9kb2N1bWVudFwiKTtcbiAgICAgICAgICAgIHZhciBpc0FycmF5ID0gcmVxdWlyZShcIngtaXMtYXJyYXlcIik7XG5cbiAgICAgICAgICAgIHZhciByZW5kZXIgPSByZXF1aXJlKFwiLi9jcmVhdGUtZWxlbWVudFwiKTtcbiAgICAgICAgICAgIHZhciBkb21JbmRleCA9IHJlcXVpcmUoXCIuL2RvbS1pbmRleFwiKTtcbiAgICAgICAgICAgIHZhciBwYXRjaE9wID0gcmVxdWlyZShcIi4vcGF0Y2gtb3BcIik7XG4gICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IHBhdGNoO1xuXG4gICAgICAgICAgICBmdW5jdGlvbiBwYXRjaChyb290Tm9kZSwgcGF0Y2hlcywgcmVuZGVyT3B0aW9ucykge1xuICAgICAgICAgICAgICAgIHJlbmRlck9wdGlvbnMgPSByZW5kZXJPcHRpb25zIHx8IHt9O1xuICAgICAgICAgICAgICAgIHJlbmRlck9wdGlvbnMucGF0Y2ggPSByZW5kZXJPcHRpb25zLnBhdGNoICYmIHJlbmRlck9wdGlvbnMucGF0Y2ggIT09IHBhdGNoID8gcmVuZGVyT3B0aW9ucy5wYXRjaCA6IHBhdGNoUmVjdXJzaXZlO1xuICAgICAgICAgICAgICAgIHJlbmRlck9wdGlvbnMucmVuZGVyID0gcmVuZGVyT3B0aW9ucy5yZW5kZXIgfHwgcmVuZGVyO1xuXG4gICAgICAgICAgICAgICAgcmV0dXJuIHJlbmRlck9wdGlvbnMucGF0Y2gocm9vdE5vZGUsIHBhdGNoZXMsIHJlbmRlck9wdGlvbnMpO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBmdW5jdGlvbiBwYXRjaFJlY3Vyc2l2ZShyb290Tm9kZSwgcGF0Y2hlcywgcmVuZGVyT3B0aW9ucykge1xuICAgICAgICAgICAgICAgIHZhciBpbmRpY2VzID0gcGF0Y2hJbmRpY2VzKHBhdGNoZXMpO1xuXG4gICAgICAgICAgICAgICAgaWYgKGluZGljZXMubGVuZ3RoID09PSAwKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiByb290Tm9kZTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICB2YXIgaW5kZXggPSBkb21JbmRleChyb290Tm9kZSwgcGF0Y2hlcy5hLCBpbmRpY2VzKTtcbiAgICAgICAgICAgICAgICB2YXIgb3duZXJEb2N1bWVudCA9IHJvb3ROb2RlLm93bmVyRG9jdW1lbnQ7XG5cbiAgICAgICAgICAgICAgICBpZiAoIXJlbmRlck9wdGlvbnMuZG9jdW1lbnQgJiYgb3duZXJEb2N1bWVudCAhPT0gZG9jdW1lbnQpIHtcbiAgICAgICAgICAgICAgICAgICAgcmVuZGVyT3B0aW9ucy5kb2N1bWVudCA9IG93bmVyRG9jdW1lbnQ7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCBpbmRpY2VzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciBub2RlSW5kZXggPSBpbmRpY2VzW2ldO1xuICAgICAgICAgICAgICAgICAgICByb290Tm9kZSA9IGFwcGx5UGF0Y2gocm9vdE5vZGUsIGluZGV4W25vZGVJbmRleF0sIHBhdGNoZXNbbm9kZUluZGV4XSwgcmVuZGVyT3B0aW9ucyk7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgcmV0dXJuIHJvb3ROb2RlO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBmdW5jdGlvbiBhcHBseVBhdGNoKHJvb3ROb2RlLCBkb21Ob2RlLCBwYXRjaExpc3QsIHJlbmRlck9wdGlvbnMpIHtcbiAgICAgICAgICAgICAgICBpZiAoIWRvbU5vZGUpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHJvb3ROb2RlO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHZhciBuZXdOb2RlO1xuXG4gICAgICAgICAgICAgICAgaWYgKGlzQXJyYXkocGF0Y2hMaXN0KSkge1xuICAgICAgICAgICAgICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IHBhdGNoTGlzdC5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgICAgICAgICAgICAgbmV3Tm9kZSA9IHBhdGNoT3AocGF0Y2hMaXN0W2ldLCBkb21Ob2RlLCByZW5kZXJPcHRpb25zKTtcblxuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGRvbU5vZGUgPT09IHJvb3ROb2RlKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcm9vdE5vZGUgPSBuZXdOb2RlO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgbmV3Tm9kZSA9IHBhdGNoT3AocGF0Y2hMaXN0LCBkb21Ob2RlLCByZW5kZXJPcHRpb25zKTtcblxuICAgICAgICAgICAgICAgICAgICBpZiAoZG9tTm9kZSA9PT0gcm9vdE5vZGUpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJvb3ROb2RlID0gbmV3Tm9kZTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHJldHVybiByb290Tm9kZTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZnVuY3Rpb24gcGF0Y2hJbmRpY2VzKHBhdGNoZXMpIHtcbiAgICAgICAgICAgICAgICB2YXIgaW5kaWNlcyA9IFtdO1xuXG4gICAgICAgICAgICAgICAgZm9yICh2YXIga2V5IGluIHBhdGNoZXMpIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKGtleSAhPT0gXCJhXCIpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGluZGljZXMucHVzaChOdW1iZXIoa2V5KSk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICByZXR1cm4gaW5kaWNlcztcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSwgeyBcIi4vY3JlYXRlLWVsZW1lbnRcIjogMTUsIFwiLi9kb20taW5kZXhcIjogMTYsIFwiLi9wYXRjaC1vcFwiOiAxNywgXCJnbG9iYWwvZG9jdW1lbnRcIjogMTAsIFwieC1pcy1hcnJheVwiOiAxMiB9XSwgMTk6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICB2YXIgaXNXaWRnZXQgPSByZXF1aXJlKFwiLi4vdm5vZGUvaXMtd2lkZ2V0LmpzXCIpO1xuXG4gICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IHVwZGF0ZVdpZGdldDtcblxuICAgICAgICAgICAgZnVuY3Rpb24gdXBkYXRlV2lkZ2V0KGEsIGIpIHtcbiAgICAgICAgICAgICAgICBpZiAoaXNXaWRnZXQoYSkgJiYgaXNXaWRnZXQoYikpIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKFwibmFtZVwiIGluIGEgJiYgXCJuYW1lXCIgaW4gYikge1xuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGEuaWQgPT09IGIuaWQ7XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gYS5pbml0ID09PSBiLmluaXQ7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0sIHsgXCIuLi92bm9kZS9pcy13aWRnZXQuanNcIjogMjkgfV0sIDIwOiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge1xuICAgICAgICAgICAgJ3VzZSBzdHJpY3QnO1xuXG4gICAgICAgICAgICB2YXIgRXZTdG9yZSA9IHJlcXVpcmUoJ2V2LXN0b3JlJyk7XG5cbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gRXZIb29rO1xuXG4gICAgICAgICAgICBmdW5jdGlvbiBFdkhvb2sodmFsdWUpIHtcbiAgICAgICAgICAgICAgICBpZiAoISh0aGlzIGluc3RhbmNlb2YgRXZIb29rKSkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gbmV3IEV2SG9vayh2YWx1ZSk7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgdGhpcy52YWx1ZSA9IHZhbHVlO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBFdkhvb2sucHJvdG90eXBlLmhvb2sgPSBmdW5jdGlvbiAobm9kZSwgcHJvcGVydHlOYW1lKSB7XG4gICAgICAgICAgICAgICAgdmFyIGVzID0gRXZTdG9yZShub2RlKTtcbiAgICAgICAgICAgICAgICB2YXIgcHJvcE5hbWUgPSBwcm9wZXJ0eU5hbWUuc3Vic3RyKDMpO1xuXG4gICAgICAgICAgICAgICAgZXNbcHJvcE5hbWVdID0gdGhpcy52YWx1ZTtcbiAgICAgICAgICAgIH07XG5cbiAgICAgICAgICAgIEV2SG9vay5wcm90b3R5cGUudW5ob29rID0gZnVuY3Rpb24gKG5vZGUsIHByb3BlcnR5TmFtZSkge1xuICAgICAgICAgICAgICAgIHZhciBlcyA9IEV2U3RvcmUobm9kZSk7XG4gICAgICAgICAgICAgICAgdmFyIHByb3BOYW1lID0gcHJvcGVydHlOYW1lLnN1YnN0cigzKTtcblxuICAgICAgICAgICAgICAgIGVzW3Byb3BOYW1lXSA9IHVuZGVmaW5lZDtcbiAgICAgICAgICAgIH07XG4gICAgICAgIH0sIHsgXCJldi1zdG9yZVwiOiA3IH1dLCAyMTogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHtcbiAgICAgICAgICAgICd1c2Ugc3RyaWN0JztcblxuICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBTb2Z0U2V0SG9vaztcblxuICAgICAgICAgICAgZnVuY3Rpb24gU29mdFNldEhvb2sodmFsdWUpIHtcbiAgICAgICAgICAgICAgICBpZiAoISh0aGlzIGluc3RhbmNlb2YgU29mdFNldEhvb2spKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBuZXcgU29mdFNldEhvb2sodmFsdWUpO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHRoaXMudmFsdWUgPSB2YWx1ZTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgU29mdFNldEhvb2sucHJvdG90eXBlLmhvb2sgPSBmdW5jdGlvbiAobm9kZSwgcHJvcGVydHlOYW1lKSB7XG4gICAgICAgICAgICAgICAgaWYgKG5vZGVbcHJvcGVydHlOYW1lXSAhPT0gdGhpcy52YWx1ZSkge1xuICAgICAgICAgICAgICAgICAgICBub2RlW3Byb3BlcnR5TmFtZV0gPSB0aGlzLnZhbHVlO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH07XG4gICAgICAgIH0sIHt9XSwgMjI6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICAndXNlIHN0cmljdCc7XG5cbiAgICAgICAgICAgIHZhciBpc0FycmF5ID0gcmVxdWlyZSgneC1pcy1hcnJheScpO1xuXG4gICAgICAgICAgICB2YXIgVk5vZGUgPSByZXF1aXJlKCcuLi92bm9kZS92bm9kZS5qcycpO1xuICAgICAgICAgICAgdmFyIFZUZXh0ID0gcmVxdWlyZSgnLi4vdm5vZGUvdnRleHQuanMnKTtcbiAgICAgICAgICAgIHZhciBpc1ZOb2RlID0gcmVxdWlyZSgnLi4vdm5vZGUvaXMtdm5vZGUnKTtcbiAgICAgICAgICAgIHZhciBpc1ZUZXh0ID0gcmVxdWlyZSgnLi4vdm5vZGUvaXMtdnRleHQnKTtcbiAgICAgICAgICAgIHZhciBpc1dpZGdldCA9IHJlcXVpcmUoJy4uL3Zub2RlL2lzLXdpZGdldCcpO1xuICAgICAgICAgICAgdmFyIGlzSG9vayA9IHJlcXVpcmUoJy4uL3Zub2RlL2lzLXZob29rJyk7XG4gICAgICAgICAgICB2YXIgaXNWVGh1bmsgPSByZXF1aXJlKCcuLi92bm9kZS9pcy10aHVuaycpO1xuXG4gICAgICAgICAgICB2YXIgcGFyc2VUYWcgPSByZXF1aXJlKCcuL3BhcnNlLXRhZy5qcycpO1xuICAgICAgICAgICAgdmFyIHNvZnRTZXRIb29rID0gcmVxdWlyZSgnLi9ob29rcy9zb2Z0LXNldC1ob29rLmpzJyk7XG4gICAgICAgICAgICB2YXIgZXZIb29rID0gcmVxdWlyZSgnLi9ob29rcy9ldi1ob29rLmpzJyk7XG5cbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gaDtcblxuICAgICAgICAgICAgZnVuY3Rpb24gaCh0YWdOYW1lLCBwcm9wZXJ0aWVzLCBjaGlsZHJlbikge1xuICAgICAgICAgICAgICAgIHZhciBjaGlsZE5vZGVzID0gW107XG4gICAgICAgICAgICAgICAgdmFyIHRhZywgcHJvcHMsIGtleSwgbmFtZXNwYWNlO1xuXG4gICAgICAgICAgICAgICAgaWYgKCFjaGlsZHJlbiAmJiBpc0NoaWxkcmVuKHByb3BlcnRpZXMpKSB7XG4gICAgICAgICAgICAgICAgICAgIGNoaWxkcmVuID0gcHJvcGVydGllcztcbiAgICAgICAgICAgICAgICAgICAgcHJvcHMgPSB7fTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICBwcm9wcyA9IHByb3BzIHx8IHByb3BlcnRpZXMgfHwge307XG4gICAgICAgICAgICAgICAgdGFnID0gcGFyc2VUYWcodGFnTmFtZSwgcHJvcHMpO1xuXG4gICAgICAgICAgICAgICAgLy8gc3VwcG9ydCBrZXlzXG4gICAgICAgICAgICAgICAgaWYgKHByb3BzLmhhc093blByb3BlcnR5KCdrZXknKSkge1xuICAgICAgICAgICAgICAgICAgICBrZXkgPSBwcm9wcy5rZXk7XG4gICAgICAgICAgICAgICAgICAgIHByb3BzLmtleSA9IHVuZGVmaW5lZDtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAvLyBzdXBwb3J0IG5hbWVzcGFjZVxuICAgICAgICAgICAgICAgIGlmIChwcm9wcy5oYXNPd25Qcm9wZXJ0eSgnbmFtZXNwYWNlJykpIHtcbiAgICAgICAgICAgICAgICAgICAgbmFtZXNwYWNlID0gcHJvcHMubmFtZXNwYWNlO1xuICAgICAgICAgICAgICAgICAgICBwcm9wcy5uYW1lc3BhY2UgPSB1bmRlZmluZWQ7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgLy8gZml4IGN1cnNvciBidWdcbiAgICAgICAgICAgICAgICBpZiAodGFnID09PSAnSU5QVVQnICYmICFuYW1lc3BhY2UgJiYgcHJvcHMuaGFzT3duUHJvcGVydHkoJ3ZhbHVlJykgJiYgcHJvcHMudmFsdWUgIT09IHVuZGVmaW5lZCAmJiAhaXNIb29rKHByb3BzLnZhbHVlKSkge1xuICAgICAgICAgICAgICAgICAgICBwcm9wcy52YWx1ZSA9IHNvZnRTZXRIb29rKHByb3BzLnZhbHVlKTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICB0cmFuc2Zvcm1Qcm9wZXJ0aWVzKHByb3BzKTtcblxuICAgICAgICAgICAgICAgIGlmIChjaGlsZHJlbiAhPT0gdW5kZWZpbmVkICYmIGNoaWxkcmVuICE9PSBudWxsKSB7XG4gICAgICAgICAgICAgICAgICAgIGFkZENoaWxkKGNoaWxkcmVuLCBjaGlsZE5vZGVzLCB0YWcsIHByb3BzKTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICByZXR1cm4gbmV3IFZOb2RlKHRhZywgcHJvcHMsIGNoaWxkTm9kZXMsIGtleSwgbmFtZXNwYWNlKTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZnVuY3Rpb24gYWRkQ2hpbGQoYywgY2hpbGROb2RlcywgdGFnLCBwcm9wcykge1xuICAgICAgICAgICAgICAgIGlmICh0eXBlb2YgYyA9PT0gJ3N0cmluZycpIHtcbiAgICAgICAgICAgICAgICAgICAgY2hpbGROb2Rlcy5wdXNoKG5ldyBWVGV4dChjKSk7XG4gICAgICAgICAgICAgICAgfSBlbHNlIGlmICh0eXBlb2YgYyA9PT0gJ251bWJlcicpIHtcbiAgICAgICAgICAgICAgICAgICAgY2hpbGROb2Rlcy5wdXNoKG5ldyBWVGV4dChTdHJpbmcoYykpKTtcbiAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKGlzQ2hpbGQoYykpIHtcbiAgICAgICAgICAgICAgICAgICAgY2hpbGROb2Rlcy5wdXNoKGMpO1xuICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoaXNBcnJheShjKSkge1xuICAgICAgICAgICAgICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IGMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGFkZENoaWxkKGNbaV0sIGNoaWxkTm9kZXMsIHRhZywgcHJvcHMpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfSBlbHNlIGlmIChjID09PSBudWxsIHx8IGMgPT09IHVuZGVmaW5lZCkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgdGhyb3cgVW5leHBlY3RlZFZpcnR1YWxFbGVtZW50KHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGZvcmVpZ25PYmplY3Q6IGMsXG4gICAgICAgICAgICAgICAgICAgICAgICBwYXJlbnRWbm9kZToge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRhZ05hbWU6IHRhZyxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBwcm9wZXJ0aWVzOiBwcm9wc1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIHRyYW5zZm9ybVByb3BlcnRpZXMocHJvcHMpIHtcbiAgICAgICAgICAgICAgICBmb3IgKHZhciBwcm9wTmFtZSBpbiBwcm9wcykge1xuICAgICAgICAgICAgICAgICAgICBpZiAocHJvcHMuaGFzT3duUHJvcGVydHkocHJvcE5hbWUpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICB2YXIgdmFsdWUgPSBwcm9wc1twcm9wTmFtZV07XG5cbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChpc0hvb2sodmFsdWUpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgY29udGludWU7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChwcm9wTmFtZS5zdWJzdHIoMCwgMykgPT09ICdldi0nKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gYWRkIGV2LWZvbyBzdXBwb3J0XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcHJvcHNbcHJvcE5hbWVdID0gZXZIb29rKHZhbHVlKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZnVuY3Rpb24gaXNDaGlsZCh4KSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGlzVk5vZGUoeCkgfHwgaXNWVGV4dCh4KSB8fCBpc1dpZGdldCh4KSB8fCBpc1ZUaHVuayh4KTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZnVuY3Rpb24gaXNDaGlsZHJlbih4KSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHR5cGVvZiB4ID09PSAnc3RyaW5nJyB8fCBpc0FycmF5KHgpIHx8IGlzQ2hpbGQoeCk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIFVuZXhwZWN0ZWRWaXJ0dWFsRWxlbWVudChkYXRhKSB7XG4gICAgICAgICAgICAgICAgdmFyIGVyciA9IG5ldyBFcnJvcigpO1xuXG4gICAgICAgICAgICAgICAgZXJyLnR5cGUgPSAndmlydHVhbC1oeXBlcnNjcmlwdC51bmV4cGVjdGVkLnZpcnR1YWwtZWxlbWVudCc7XG4gICAgICAgICAgICAgICAgZXJyLm1lc3NhZ2UgPSAnVW5leHBlY3RlZCB2aXJ0dWFsIGNoaWxkIHBhc3NlZCB0byBoKCkuXFxuJyArICdFeHBlY3RlZCBhIFZOb2RlIC8gVnRodW5rIC8gVldpZGdldCAvIHN0cmluZyBidXQ6XFxuJyArICdnb3Q6XFxuJyArIGVycm9yU3RyaW5nKGRhdGEuZm9yZWlnbk9iamVjdCkgKyAnLlxcbicgKyAnVGhlIHBhcmVudCB2bm9kZSBpczpcXG4nICsgZXJyb3JTdHJpbmcoZGF0YS5wYXJlbnRWbm9kZSk7XG4gICAgICAgICAgICAgICAgJ1xcbicgKyAnU3VnZ2VzdGVkIGZpeDogY2hhbmdlIHlvdXIgYGgoLi4uLCBbIC4uLiBdKWAgY2FsbHNpdGUuJztcbiAgICAgICAgICAgICAgICBlcnIuZm9yZWlnbk9iamVjdCA9IGRhdGEuZm9yZWlnbk9iamVjdDtcbiAgICAgICAgICAgICAgICBlcnIucGFyZW50Vm5vZGUgPSBkYXRhLnBhcmVudFZub2RlO1xuXG4gICAgICAgICAgICAgICAgcmV0dXJuIGVycjtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZnVuY3Rpb24gZXJyb3JTdHJpbmcob2JqKSB7XG4gICAgICAgICAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIEpTT04uc3RyaW5naWZ5KG9iaiwgbnVsbCwgJyAgICAnKTtcbiAgICAgICAgICAgICAgICB9IGNhdGNoIChlKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBTdHJpbmcob2JqKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH0sIHsgXCIuLi92bm9kZS9pcy10aHVua1wiOiAyNSwgXCIuLi92bm9kZS9pcy12aG9va1wiOiAyNiwgXCIuLi92bm9kZS9pcy12bm9kZVwiOiAyNywgXCIuLi92bm9kZS9pcy12dGV4dFwiOiAyOCwgXCIuLi92bm9kZS9pcy13aWRnZXRcIjogMjksIFwiLi4vdm5vZGUvdm5vZGUuanNcIjogMzEsIFwiLi4vdm5vZGUvdnRleHQuanNcIjogMzMsIFwiLi9ob29rcy9ldi1ob29rLmpzXCI6IDIwLCBcIi4vaG9va3Mvc29mdC1zZXQtaG9vay5qc1wiOiAyMSwgXCIuL3BhcnNlLXRhZy5qc1wiOiAyMywgXCJ4LWlzLWFycmF5XCI6IDEyIH1dLCAyMzogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHtcbiAgICAgICAgICAgICd1c2Ugc3RyaWN0JztcblxuICAgICAgICAgICAgdmFyIHNwbGl0ID0gcmVxdWlyZSgnYnJvd3Nlci1zcGxpdCcpO1xuXG4gICAgICAgICAgICB2YXIgY2xhc3NJZFNwbGl0ID0gLyhbXFwuI10/W2EtekEtWjAtOVxcdTAwN0YtXFx1RkZGRl86LV0rKS87XG4gICAgICAgICAgICB2YXIgbm90Q2xhc3NJZCA9IC9eXFwufCMvO1xuXG4gICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IHBhcnNlVGFnO1xuXG4gICAgICAgICAgICBmdW5jdGlvbiBwYXJzZVRhZyh0YWcsIHByb3BzKSB7XG4gICAgICAgICAgICAgICAgaWYgKCF0YWcpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuICdESVYnO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHZhciBub0lkID0gIXByb3BzLmhhc093blByb3BlcnR5KCdpZCcpO1xuXG4gICAgICAgICAgICAgICAgdmFyIHRhZ1BhcnRzID0gc3BsaXQodGFnLCBjbGFzc0lkU3BsaXQpO1xuICAgICAgICAgICAgICAgIHZhciB0YWdOYW1lID0gbnVsbDtcblxuICAgICAgICAgICAgICAgIGlmIChub3RDbGFzc0lkLnRlc3QodGFnUGFydHNbMV0pKSB7XG4gICAgICAgICAgICAgICAgICAgIHRhZ05hbWUgPSAnRElWJztcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICB2YXIgY2xhc3NlcywgcGFydCwgdHlwZSwgaTtcblxuICAgICAgICAgICAgICAgIGZvciAoaSA9IDA7IGkgPCB0YWdQYXJ0cy5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgICAgICAgICBwYXJ0ID0gdGFnUGFydHNbaV07XG5cbiAgICAgICAgICAgICAgICAgICAgaWYgKCFwYXJ0KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBjb250aW51ZTtcbiAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgIHR5cGUgPSBwYXJ0LmNoYXJBdCgwKTtcblxuICAgICAgICAgICAgICAgICAgICBpZiAoIXRhZ05hbWUpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHRhZ05hbWUgPSBwYXJ0O1xuICAgICAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKHR5cGUgPT09ICcuJykge1xuICAgICAgICAgICAgICAgICAgICAgICAgY2xhc3NlcyA9IGNsYXNzZXMgfHwgW107XG4gICAgICAgICAgICAgICAgICAgICAgICBjbGFzc2VzLnB1c2gocGFydC5zdWJzdHJpbmcoMSwgcGFydC5sZW5ndGgpKTtcbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIGlmICh0eXBlID09PSAnIycgJiYgbm9JZCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgcHJvcHMuaWQgPSBwYXJ0LnN1YnN0cmluZygxLCBwYXJ0Lmxlbmd0aCk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICBpZiAoY2xhc3Nlcykge1xuICAgICAgICAgICAgICAgICAgICBpZiAocHJvcHMuY2xhc3NOYW1lKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBjbGFzc2VzLnB1c2gocHJvcHMuY2xhc3NOYW1lKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgIHByb3BzLmNsYXNzTmFtZSA9IGNsYXNzZXMuam9pbignICcpO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHJldHVybiBwcm9wcy5uYW1lc3BhY2UgPyB0YWdOYW1lIDogdGFnTmFtZS50b1VwcGVyQ2FzZSgpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9LCB7IFwiYnJvd3Nlci1zcGxpdFwiOiA1IH1dLCAyNDogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHtcbiAgICAgICAgICAgIHZhciBpc1ZOb2RlID0gcmVxdWlyZShcIi4vaXMtdm5vZGVcIik7XG4gICAgICAgICAgICB2YXIgaXNWVGV4dCA9IHJlcXVpcmUoXCIuL2lzLXZ0ZXh0XCIpO1xuICAgICAgICAgICAgdmFyIGlzV2lkZ2V0ID0gcmVxdWlyZShcIi4vaXMtd2lkZ2V0XCIpO1xuICAgICAgICAgICAgdmFyIGlzVGh1bmsgPSByZXF1aXJlKFwiLi9pcy10aHVua1wiKTtcblxuICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBoYW5kbGVUaHVuaztcblxuICAgICAgICAgICAgZnVuY3Rpb24gaGFuZGxlVGh1bmsoYSwgYikge1xuICAgICAgICAgICAgICAgIHZhciByZW5kZXJlZEEgPSBhO1xuICAgICAgICAgICAgICAgIHZhciByZW5kZXJlZEIgPSBiO1xuXG4gICAgICAgICAgICAgICAgaWYgKGlzVGh1bmsoYikpIHtcbiAgICAgICAgICAgICAgICAgICAgcmVuZGVyZWRCID0gcmVuZGVyVGh1bmsoYiwgYSk7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgaWYgKGlzVGh1bmsoYSkpIHtcbiAgICAgICAgICAgICAgICAgICAgcmVuZGVyZWRBID0gcmVuZGVyVGh1bmsoYSwgbnVsbCk7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgICAgICAgICAgYTogcmVuZGVyZWRBLFxuICAgICAgICAgICAgICAgICAgICBiOiByZW5kZXJlZEJcbiAgICAgICAgICAgICAgICB9O1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBmdW5jdGlvbiByZW5kZXJUaHVuayh0aHVuaywgcHJldmlvdXMpIHtcbiAgICAgICAgICAgICAgICB2YXIgcmVuZGVyZWRUaHVuayA9IHRodW5rLnZub2RlO1xuXG4gICAgICAgICAgICAgICAgaWYgKCFyZW5kZXJlZFRodW5rKSB7XG4gICAgICAgICAgICAgICAgICAgIHJlbmRlcmVkVGh1bmsgPSB0aHVuay52bm9kZSA9IHRodW5rLnJlbmRlcihwcmV2aW91cyk7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgaWYgKCEoaXNWTm9kZShyZW5kZXJlZFRodW5rKSB8fCBpc1ZUZXh0KHJlbmRlcmVkVGh1bmspIHx8IGlzV2lkZ2V0KHJlbmRlcmVkVGh1bmspKSkge1xuICAgICAgICAgICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoXCJ0aHVuayBkaWQgbm90IHJldHVybiBhIHZhbGlkIG5vZGVcIik7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgcmV0dXJuIHJlbmRlcmVkVGh1bms7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0sIHsgXCIuL2lzLXRodW5rXCI6IDI1LCBcIi4vaXMtdm5vZGVcIjogMjcsIFwiLi9pcy12dGV4dFwiOiAyOCwgXCIuL2lzLXdpZGdldFwiOiAyOSB9XSwgMjU6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IGlzVGh1bms7XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIGlzVGh1bmsodCkge1xuICAgICAgICAgICAgICAgIHJldHVybiB0ICYmIHQudHlwZSA9PT0gXCJUaHVua1wiO1xuICAgICAgICAgICAgfVxuICAgICAgICB9LCB7fV0sIDI2OiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge1xuICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBpc0hvb2s7XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIGlzSG9vayhob29rKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGhvb2sgJiYgKHR5cGVvZiBob29rLmhvb2sgPT09IFwiZnVuY3Rpb25cIiAmJiAhaG9vay5oYXNPd25Qcm9wZXJ0eShcImhvb2tcIikgfHwgdHlwZW9mIGhvb2sudW5ob29rID09PSBcImZ1bmN0aW9uXCIgJiYgIWhvb2suaGFzT3duUHJvcGVydHkoXCJ1bmhvb2tcIikpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9LCB7fV0sIDI3OiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge1xuICAgICAgICAgICAgdmFyIHZlcnNpb24gPSByZXF1aXJlKFwiLi92ZXJzaW9uXCIpO1xuXG4gICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IGlzVmlydHVhbE5vZGU7XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIGlzVmlydHVhbE5vZGUoeCkge1xuICAgICAgICAgICAgICAgIHJldHVybiB4ICYmIHgudHlwZSA9PT0gXCJWaXJ0dWFsTm9kZVwiICYmIHgudmVyc2lvbiA9PT0gdmVyc2lvbjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSwgeyBcIi4vdmVyc2lvblwiOiAzMCB9XSwgMjg6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICB2YXIgdmVyc2lvbiA9IHJlcXVpcmUoXCIuL3ZlcnNpb25cIik7XG5cbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gaXNWaXJ0dWFsVGV4dDtcblxuICAgICAgICAgICAgZnVuY3Rpb24gaXNWaXJ0dWFsVGV4dCh4KSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHggJiYgeC50eXBlID09PSBcIlZpcnR1YWxUZXh0XCIgJiYgeC52ZXJzaW9uID09PSB2ZXJzaW9uO1xuICAgICAgICAgICAgfVxuICAgICAgICB9LCB7IFwiLi92ZXJzaW9uXCI6IDMwIH1dLCAyOTogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHtcbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gaXNXaWRnZXQ7XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIGlzV2lkZ2V0KHcpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gdyAmJiB3LnR5cGUgPT09IFwiV2lkZ2V0XCI7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0sIHt9XSwgMzA6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IFwiMlwiO1xuICAgICAgICB9LCB7fV0sIDMxOiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge1xuICAgICAgICAgICAgdmFyIHZlcnNpb24gPSByZXF1aXJlKFwiLi92ZXJzaW9uXCIpO1xuICAgICAgICAgICAgdmFyIGlzVk5vZGUgPSByZXF1aXJlKFwiLi9pcy12bm9kZVwiKTtcbiAgICAgICAgICAgIHZhciBpc1dpZGdldCA9IHJlcXVpcmUoXCIuL2lzLXdpZGdldFwiKTtcbiAgICAgICAgICAgIHZhciBpc1RodW5rID0gcmVxdWlyZShcIi4vaXMtdGh1bmtcIik7XG4gICAgICAgICAgICB2YXIgaXNWSG9vayA9IHJlcXVpcmUoXCIuL2lzLXZob29rXCIpO1xuXG4gICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IFZpcnR1YWxOb2RlO1xuXG4gICAgICAgICAgICB2YXIgbm9Qcm9wZXJ0aWVzID0ge307XG4gICAgICAgICAgICB2YXIgbm9DaGlsZHJlbiA9IFtdO1xuXG4gICAgICAgICAgICBmdW5jdGlvbiBWaXJ0dWFsTm9kZSh0YWdOYW1lLCBwcm9wZXJ0aWVzLCBjaGlsZHJlbiwga2V5LCBuYW1lc3BhY2UpIHtcbiAgICAgICAgICAgICAgICB0aGlzLnRhZ05hbWUgPSB0YWdOYW1lO1xuICAgICAgICAgICAgICAgIHRoaXMucHJvcGVydGllcyA9IHByb3BlcnRpZXMgfHwgbm9Qcm9wZXJ0aWVzO1xuICAgICAgICAgICAgICAgIHRoaXMuY2hpbGRyZW4gPSBjaGlsZHJlbiB8fCBub0NoaWxkcmVuO1xuICAgICAgICAgICAgICAgIHRoaXMua2V5ID0ga2V5ICE9IG51bGwgPyBTdHJpbmcoa2V5KSA6IHVuZGVmaW5lZDtcbiAgICAgICAgICAgICAgICB0aGlzLm5hbWVzcGFjZSA9IHR5cGVvZiBuYW1lc3BhY2UgPT09IFwic3RyaW5nXCIgPyBuYW1lc3BhY2UgOiBudWxsO1xuXG4gICAgICAgICAgICAgICAgdmFyIGNvdW50ID0gY2hpbGRyZW4gJiYgY2hpbGRyZW4ubGVuZ3RoIHx8IDA7XG4gICAgICAgICAgICAgICAgdmFyIGRlc2NlbmRhbnRzID0gMDtcbiAgICAgICAgICAgICAgICB2YXIgaGFzV2lkZ2V0cyA9IGZhbHNlO1xuICAgICAgICAgICAgICAgIHZhciBoYXNUaHVua3MgPSBmYWxzZTtcbiAgICAgICAgICAgICAgICB2YXIgZGVzY2VuZGFudEhvb2tzID0gZmFsc2U7XG4gICAgICAgICAgICAgICAgdmFyIGhvb2tzO1xuXG4gICAgICAgICAgICAgICAgZm9yICh2YXIgcHJvcE5hbWUgaW4gcHJvcGVydGllcykge1xuICAgICAgICAgICAgICAgICAgICBpZiAocHJvcGVydGllcy5oYXNPd25Qcm9wZXJ0eShwcm9wTmFtZSkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHZhciBwcm9wZXJ0eSA9IHByb3BlcnRpZXNbcHJvcE5hbWVdO1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGlzVkhvb2socHJvcGVydHkpICYmIHByb3BlcnR5LnVuaG9vaykge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmICghaG9va3MpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaG9va3MgPSB7fTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBob29rc1twcm9wTmFtZV0gPSBwcm9wZXJ0eTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgY291bnQ7IGkrKykge1xuICAgICAgICAgICAgICAgICAgICB2YXIgY2hpbGQgPSBjaGlsZHJlbltpXTtcbiAgICAgICAgICAgICAgICAgICAgaWYgKGlzVk5vZGUoY2hpbGQpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBkZXNjZW5kYW50cyArPSBjaGlsZC5jb3VudCB8fCAwO1xuXG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoIWhhc1dpZGdldHMgJiYgY2hpbGQuaGFzV2lkZ2V0cykge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGhhc1dpZGdldHMgPSB0cnVlO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoIWhhc1RodW5rcyAmJiBjaGlsZC5oYXNUaHVua3MpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBoYXNUaHVua3MgPSB0cnVlO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoIWRlc2NlbmRhbnRIb29rcyAmJiAoY2hpbGQuaG9va3MgfHwgY2hpbGQuZGVzY2VuZGFudEhvb2tzKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRlc2NlbmRhbnRIb29rcyA9IHRydWU7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoIWhhc1dpZGdldHMgJiYgaXNXaWRnZXQoY2hpbGQpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAodHlwZW9mIGNoaWxkLmRlc3Ryb3kgPT09IFwiZnVuY3Rpb25cIikge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGhhc1dpZGdldHMgPSB0cnVlO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKCFoYXNUaHVua3MgJiYgaXNUaHVuayhjaGlsZCkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGhhc1RodW5rcyA9IHRydWU7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICB0aGlzLmNvdW50ID0gY291bnQgKyBkZXNjZW5kYW50cztcbiAgICAgICAgICAgICAgICB0aGlzLmhhc1dpZGdldHMgPSBoYXNXaWRnZXRzO1xuICAgICAgICAgICAgICAgIHRoaXMuaGFzVGh1bmtzID0gaGFzVGh1bmtzO1xuICAgICAgICAgICAgICAgIHRoaXMuaG9va3MgPSBob29rcztcbiAgICAgICAgICAgICAgICB0aGlzLmRlc2NlbmRhbnRIb29rcyA9IGRlc2NlbmRhbnRIb29rcztcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgVmlydHVhbE5vZGUucHJvdG90eXBlLnZlcnNpb24gPSB2ZXJzaW9uO1xuICAgICAgICAgICAgVmlydHVhbE5vZGUucHJvdG90eXBlLnR5cGUgPSBcIlZpcnR1YWxOb2RlXCI7XG4gICAgICAgIH0sIHsgXCIuL2lzLXRodW5rXCI6IDI1LCBcIi4vaXMtdmhvb2tcIjogMjYsIFwiLi9pcy12bm9kZVwiOiAyNywgXCIuL2lzLXdpZGdldFwiOiAyOSwgXCIuL3ZlcnNpb25cIjogMzAgfV0sIDMyOiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge1xuICAgICAgICAgICAgdmFyIHZlcnNpb24gPSByZXF1aXJlKFwiLi92ZXJzaW9uXCIpO1xuXG4gICAgICAgICAgICBWaXJ0dWFsUGF0Y2guTk9ORSA9IDA7XG4gICAgICAgICAgICBWaXJ0dWFsUGF0Y2guVlRFWFQgPSAxO1xuICAgICAgICAgICAgVmlydHVhbFBhdGNoLlZOT0RFID0gMjtcbiAgICAgICAgICAgIFZpcnR1YWxQYXRjaC5XSURHRVQgPSAzO1xuICAgICAgICAgICAgVmlydHVhbFBhdGNoLlBST1BTID0gNDtcbiAgICAgICAgICAgIFZpcnR1YWxQYXRjaC5PUkRFUiA9IDU7XG4gICAgICAgICAgICBWaXJ0dWFsUGF0Y2guSU5TRVJUID0gNjtcbiAgICAgICAgICAgIFZpcnR1YWxQYXRjaC5SRU1PVkUgPSA3O1xuICAgICAgICAgICAgVmlydHVhbFBhdGNoLlRIVU5LID0gODtcblxuICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBWaXJ0dWFsUGF0Y2g7XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIFZpcnR1YWxQYXRjaCh0eXBlLCB2Tm9kZSwgcGF0Y2gpIHtcbiAgICAgICAgICAgICAgICB0aGlzLnR5cGUgPSBOdW1iZXIodHlwZSk7XG4gICAgICAgICAgICAgICAgdGhpcy52Tm9kZSA9IHZOb2RlO1xuICAgICAgICAgICAgICAgIHRoaXMucGF0Y2ggPSBwYXRjaDtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgVmlydHVhbFBhdGNoLnByb3RvdHlwZS52ZXJzaW9uID0gdmVyc2lvbjtcbiAgICAgICAgICAgIFZpcnR1YWxQYXRjaC5wcm90b3R5cGUudHlwZSA9IFwiVmlydHVhbFBhdGNoXCI7XG4gICAgICAgIH0sIHsgXCIuL3ZlcnNpb25cIjogMzAgfV0sIDMzOiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge1xuICAgICAgICAgICAgdmFyIHZlcnNpb24gPSByZXF1aXJlKFwiLi92ZXJzaW9uXCIpO1xuXG4gICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IFZpcnR1YWxUZXh0O1xuXG4gICAgICAgICAgICBmdW5jdGlvbiBWaXJ0dWFsVGV4dCh0ZXh0KSB7XG4gICAgICAgICAgICAgICAgdGhpcy50ZXh0ID0gU3RyaW5nKHRleHQpO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBWaXJ0dWFsVGV4dC5wcm90b3R5cGUudmVyc2lvbiA9IHZlcnNpb247XG4gICAgICAgICAgICBWaXJ0dWFsVGV4dC5wcm90b3R5cGUudHlwZSA9IFwiVmlydHVhbFRleHRcIjtcbiAgICAgICAgfSwgeyBcIi4vdmVyc2lvblwiOiAzMCB9XSwgMzQ6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICB2YXIgaXNPYmplY3QgPSByZXF1aXJlKFwiaXMtb2JqZWN0XCIpO1xuICAgICAgICAgICAgdmFyIGlzSG9vayA9IHJlcXVpcmUoXCIuLi92bm9kZS9pcy12aG9va1wiKTtcblxuICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBkaWZmUHJvcHM7XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIGRpZmZQcm9wcyhhLCBiKSB7XG4gICAgICAgICAgICAgICAgdmFyIGRpZmY7XG5cbiAgICAgICAgICAgICAgICBmb3IgKHZhciBhS2V5IGluIGEpIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKCEoYUtleSBpbiBiKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgZGlmZiA9IGRpZmYgfHwge307XG4gICAgICAgICAgICAgICAgICAgICAgICBkaWZmW2FLZXldID0gdW5kZWZpbmVkO1xuICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgdmFyIGFWYWx1ZSA9IGFbYUtleV07XG4gICAgICAgICAgICAgICAgICAgIHZhciBiVmFsdWUgPSBiW2FLZXldO1xuXG4gICAgICAgICAgICAgICAgICAgIGlmIChhVmFsdWUgPT09IGJWYWx1ZSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgY29udGludWU7XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoaXNPYmplY3QoYVZhbHVlKSAmJiBpc09iamVjdChiVmFsdWUpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoZ2V0UHJvdG90eXBlKGJWYWx1ZSkgIT09IGdldFByb3RvdHlwZShhVmFsdWUpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgZGlmZiA9IGRpZmYgfHwge307XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgZGlmZlthS2V5XSA9IGJWYWx1ZTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoaXNIb29rKGJWYWx1ZSkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBkaWZmID0gZGlmZiB8fCB7fTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBkaWZmW2FLZXldID0gYlZhbHVlO1xuICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB2YXIgb2JqZWN0RGlmZiA9IGRpZmZQcm9wcyhhVmFsdWUsIGJWYWx1ZSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKG9iamVjdERpZmYpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZGlmZiA9IGRpZmYgfHwge307XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRpZmZbYUtleV0gPSBvYmplY3REaWZmO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGRpZmYgPSBkaWZmIHx8IHt9O1xuICAgICAgICAgICAgICAgICAgICAgICAgZGlmZlthS2V5XSA9IGJWYWx1ZTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIGZvciAodmFyIGJLZXkgaW4gYikge1xuICAgICAgICAgICAgICAgICAgICBpZiAoIShiS2V5IGluIGEpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBkaWZmID0gZGlmZiB8fCB7fTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGRpZmZbYktleV0gPSBiW2JLZXldO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgcmV0dXJuIGRpZmY7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIGdldFByb3RvdHlwZSh2YWx1ZSkge1xuICAgICAgICAgICAgICAgIGlmIChPYmplY3QuZ2V0UHJvdG90eXBlT2YpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIE9iamVjdC5nZXRQcm90b3R5cGVPZih2YWx1ZSk7XG4gICAgICAgICAgICAgICAgfSBlbHNlIGlmICh2YWx1ZS5fX3Byb3RvX18pIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHZhbHVlLl9fcHJvdG9fXztcbiAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKHZhbHVlLmNvbnN0cnVjdG9yKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiB2YWx1ZS5jb25zdHJ1Y3Rvci5wcm90b3R5cGU7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9LCB7IFwiLi4vdm5vZGUvaXMtdmhvb2tcIjogMjYsIFwiaXMtb2JqZWN0XCI6IDExIH1dLCAzNTogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHtcbiAgICAgICAgICAgIHZhciBpc0FycmF5ID0gcmVxdWlyZShcIngtaXMtYXJyYXlcIik7XG5cbiAgICAgICAgICAgIHZhciBWUGF0Y2ggPSByZXF1aXJlKFwiLi4vdm5vZGUvdnBhdGNoXCIpO1xuICAgICAgICAgICAgdmFyIGlzVk5vZGUgPSByZXF1aXJlKFwiLi4vdm5vZGUvaXMtdm5vZGVcIik7XG4gICAgICAgICAgICB2YXIgaXNWVGV4dCA9IHJlcXVpcmUoXCIuLi92bm9kZS9pcy12dGV4dFwiKTtcbiAgICAgICAgICAgIHZhciBpc1dpZGdldCA9IHJlcXVpcmUoXCIuLi92bm9kZS9pcy13aWRnZXRcIik7XG4gICAgICAgICAgICB2YXIgaXNUaHVuayA9IHJlcXVpcmUoXCIuLi92bm9kZS9pcy10aHVua1wiKTtcbiAgICAgICAgICAgIHZhciBoYW5kbGVUaHVuayA9IHJlcXVpcmUoXCIuLi92bm9kZS9oYW5kbGUtdGh1bmtcIik7XG5cbiAgICAgICAgICAgIHZhciBkaWZmUHJvcHMgPSByZXF1aXJlKFwiLi9kaWZmLXByb3BzXCIpO1xuXG4gICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IGRpZmY7XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIGRpZmYoYSwgYikge1xuICAgICAgICAgICAgICAgIHZhciBwYXRjaCA9IHsgYTogYSB9O1xuICAgICAgICAgICAgICAgIHdhbGsoYSwgYiwgcGF0Y2gsIDApO1xuICAgICAgICAgICAgICAgIHJldHVybiBwYXRjaDtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZnVuY3Rpb24gd2FsayhhLCBiLCBwYXRjaCwgaW5kZXgpIHtcbiAgICAgICAgICAgICAgICBpZiAoYSA9PT0gYikge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgdmFyIGFwcGx5ID0gcGF0Y2hbaW5kZXhdO1xuICAgICAgICAgICAgICAgIHZhciBhcHBseUNsZWFyID0gZmFsc2U7XG5cbiAgICAgICAgICAgICAgICBpZiAoaXNUaHVuayhhKSB8fCBpc1RodW5rKGIpKSB7XG4gICAgICAgICAgICAgICAgICAgIHRodW5rcyhhLCBiLCBwYXRjaCwgaW5kZXgpO1xuICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoYiA9PSBudWxsKSB7XG5cbiAgICAgICAgICAgICAgICAgICAgLy8gSWYgYSBpcyBhIHdpZGdldCB3ZSB3aWxsIGFkZCBhIHJlbW92ZSBwYXRjaCBmb3IgaXRcbiAgICAgICAgICAgICAgICAgICAgLy8gT3RoZXJ3aXNlIGFueSBjaGlsZCB3aWRnZXRzL2hvb2tzIG11c3QgYmUgZGVzdHJveWVkLlxuICAgICAgICAgICAgICAgICAgICAvLyBUaGlzIHByZXZlbnRzIGFkZGluZyB0d28gcmVtb3ZlIHBhdGNoZXMgZm9yIGEgd2lkZ2V0LlxuICAgICAgICAgICAgICAgICAgICBpZiAoIWlzV2lkZ2V0KGEpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBjbGVhclN0YXRlKGEsIHBhdGNoLCBpbmRleCk7XG4gICAgICAgICAgICAgICAgICAgICAgICBhcHBseSA9IHBhdGNoW2luZGV4XTtcbiAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgIGFwcGx5ID0gYXBwZW5kUGF0Y2goYXBwbHksIG5ldyBWUGF0Y2goVlBhdGNoLlJFTU9WRSwgYSwgYikpO1xuICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoaXNWTm9kZShiKSkge1xuICAgICAgICAgICAgICAgICAgICBpZiAoaXNWTm9kZShhKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGEudGFnTmFtZSA9PT0gYi50YWdOYW1lICYmIGEubmFtZXNwYWNlID09PSBiLm5hbWVzcGFjZSAmJiBhLmtleSA9PT0gYi5rZXkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB2YXIgcHJvcHNQYXRjaCA9IGRpZmZQcm9wcyhhLnByb3BlcnRpZXMsIGIucHJvcGVydGllcyk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHByb3BzUGF0Y2gpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYXBwbHkgPSBhcHBlbmRQYXRjaChhcHBseSwgbmV3IFZQYXRjaChWUGF0Y2guUFJPUFMsIGEsIHByb3BzUGF0Y2gpKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgYXBwbHkgPSBkaWZmQ2hpbGRyZW4oYSwgYiwgcGF0Y2gsIGFwcGx5LCBpbmRleCk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGFwcGx5ID0gYXBwZW5kUGF0Y2goYXBwbHksIG5ldyBWUGF0Y2goVlBhdGNoLlZOT0RFLCBhLCBiKSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgYXBwbHlDbGVhciA9IHRydWU7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBhcHBseSA9IGFwcGVuZFBhdGNoKGFwcGx5LCBuZXcgVlBhdGNoKFZQYXRjaC5WTk9ERSwgYSwgYikpO1xuICAgICAgICAgICAgICAgICAgICAgICAgYXBwbHlDbGVhciA9IHRydWU7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKGlzVlRleHQoYikpIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKCFpc1ZUZXh0KGEpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBhcHBseSA9IGFwcGVuZFBhdGNoKGFwcGx5LCBuZXcgVlBhdGNoKFZQYXRjaC5WVEVYVCwgYSwgYikpO1xuICAgICAgICAgICAgICAgICAgICAgICAgYXBwbHlDbGVhciA9IHRydWU7XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoYS50ZXh0ICE9PSBiLnRleHQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGFwcGx5ID0gYXBwZW5kUGF0Y2goYXBwbHksIG5ldyBWUGF0Y2goVlBhdGNoLlZURVhULCBhLCBiKSk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKGlzV2lkZ2V0KGIpKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmICghaXNXaWRnZXQoYSkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGFwcGx5Q2xlYXIgPSB0cnVlO1xuICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgYXBwbHkgPSBhcHBlbmRQYXRjaChhcHBseSwgbmV3IFZQYXRjaChWUGF0Y2guV0lER0VULCBhLCBiKSk7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgaWYgKGFwcGx5KSB7XG4gICAgICAgICAgICAgICAgICAgIHBhdGNoW2luZGV4XSA9IGFwcGx5O1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIGlmIChhcHBseUNsZWFyKSB7XG4gICAgICAgICAgICAgICAgICAgIGNsZWFyU3RhdGUoYSwgcGF0Y2gsIGluZGV4KTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIGRpZmZDaGlsZHJlbihhLCBiLCBwYXRjaCwgYXBwbHksIGluZGV4KSB7XG4gICAgICAgICAgICAgICAgdmFyIGFDaGlsZHJlbiA9IGEuY2hpbGRyZW47XG4gICAgICAgICAgICAgICAgdmFyIG9yZGVyZWRTZXQgPSByZW9yZGVyKGFDaGlsZHJlbiwgYi5jaGlsZHJlbik7XG4gICAgICAgICAgICAgICAgdmFyIGJDaGlsZHJlbiA9IG9yZGVyZWRTZXQuY2hpbGRyZW47XG5cbiAgICAgICAgICAgICAgICB2YXIgYUxlbiA9IGFDaGlsZHJlbi5sZW5ndGg7XG4gICAgICAgICAgICAgICAgdmFyIGJMZW4gPSBiQ2hpbGRyZW4ubGVuZ3RoO1xuICAgICAgICAgICAgICAgIHZhciBsZW4gPSBhTGVuID4gYkxlbiA/IGFMZW4gOiBiTGVuO1xuXG4gICAgICAgICAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCBsZW47IGkrKykge1xuICAgICAgICAgICAgICAgICAgICB2YXIgbGVmdE5vZGUgPSBhQ2hpbGRyZW5baV07XG4gICAgICAgICAgICAgICAgICAgIHZhciByaWdodE5vZGUgPSBiQ2hpbGRyZW5baV07XG4gICAgICAgICAgICAgICAgICAgIGluZGV4ICs9IDE7XG5cbiAgICAgICAgICAgICAgICAgICAgaWYgKCFsZWZ0Tm9kZSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHJpZ2h0Tm9kZSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIEV4Y2VzcyBub2RlcyBpbiBiIG5lZWQgdG8gYmUgYWRkZWRcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBhcHBseSA9IGFwcGVuZFBhdGNoKGFwcGx5LCBuZXcgVlBhdGNoKFZQYXRjaC5JTlNFUlQsIG51bGwsIHJpZ2h0Tm9kZSkpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgd2FsayhsZWZ0Tm9kZSwgcmlnaHROb2RlLCBwYXRjaCwgaW5kZXgpO1xuICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgaWYgKGlzVk5vZGUobGVmdE5vZGUpICYmIGxlZnROb2RlLmNvdW50KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBpbmRleCArPSBsZWZ0Tm9kZS5jb3VudDtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIGlmIChvcmRlcmVkU2V0Lm1vdmVzKSB7XG4gICAgICAgICAgICAgICAgICAgIC8vIFJlb3JkZXIgbm9kZXMgbGFzdFxuICAgICAgICAgICAgICAgICAgICBhcHBseSA9IGFwcGVuZFBhdGNoKGFwcGx5LCBuZXcgVlBhdGNoKFZQYXRjaC5PUkRFUiwgYSwgb3JkZXJlZFNldC5tb3ZlcykpO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHJldHVybiBhcHBseTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZnVuY3Rpb24gY2xlYXJTdGF0ZSh2Tm9kZSwgcGF0Y2gsIGluZGV4KSB7XG4gICAgICAgICAgICAgICAgLy8gVE9ETzogTWFrZSB0aGlzIGEgc2luZ2xlIHdhbGssIG5vdCB0d29cbiAgICAgICAgICAgICAgICB1bmhvb2sodk5vZGUsIHBhdGNoLCBpbmRleCk7XG4gICAgICAgICAgICAgICAgZGVzdHJveVdpZGdldHModk5vZGUsIHBhdGNoLCBpbmRleCk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIC8vIFBhdGNoIHJlY29yZHMgZm9yIGFsbCBkZXN0cm95ZWQgd2lkZ2V0cyBtdXN0IGJlIGFkZGVkIGJlY2F1c2Ugd2UgbmVlZFxuICAgICAgICAgICAgLy8gYSBET00gbm9kZSByZWZlcmVuY2UgZm9yIHRoZSBkZXN0cm95IGZ1bmN0aW9uXG4gICAgICAgICAgICBmdW5jdGlvbiBkZXN0cm95V2lkZ2V0cyh2Tm9kZSwgcGF0Y2gsIGluZGV4KSB7XG4gICAgICAgICAgICAgICAgaWYgKGlzV2lkZ2V0KHZOb2RlKSkge1xuICAgICAgICAgICAgICAgICAgICBpZiAodHlwZW9mIHZOb2RlLmRlc3Ryb3kgPT09IFwiZnVuY3Rpb25cIikge1xuICAgICAgICAgICAgICAgICAgICAgICAgcGF0Y2hbaW5kZXhdID0gYXBwZW5kUGF0Y2gocGF0Y2hbaW5kZXhdLCBuZXcgVlBhdGNoKFZQYXRjaC5SRU1PVkUsIHZOb2RlLCBudWxsKSk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKGlzVk5vZGUodk5vZGUpICYmICh2Tm9kZS5oYXNXaWRnZXRzIHx8IHZOb2RlLmhhc1RodW5rcykpIHtcbiAgICAgICAgICAgICAgICAgICAgdmFyIGNoaWxkcmVuID0gdk5vZGUuY2hpbGRyZW47XG4gICAgICAgICAgICAgICAgICAgIHZhciBsZW4gPSBjaGlsZHJlbi5sZW5ndGg7XG4gICAgICAgICAgICAgICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgbGVuOyBpKyspIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHZhciBjaGlsZCA9IGNoaWxkcmVuW2ldO1xuICAgICAgICAgICAgICAgICAgICAgICAgaW5kZXggKz0gMTtcblxuICAgICAgICAgICAgICAgICAgICAgICAgZGVzdHJveVdpZGdldHMoY2hpbGQsIHBhdGNoLCBpbmRleCk7XG5cbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChpc1ZOb2RlKGNoaWxkKSAmJiBjaGlsZC5jb3VudCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGluZGV4ICs9IGNoaWxkLmNvdW50O1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfSBlbHNlIGlmIChpc1RodW5rKHZOb2RlKSkge1xuICAgICAgICAgICAgICAgICAgICB0aHVua3Modk5vZGUsIG51bGwsIHBhdGNoLCBpbmRleCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAvLyBDcmVhdGUgYSBzdWItcGF0Y2ggZm9yIHRodW5rc1xuICAgICAgICAgICAgZnVuY3Rpb24gdGh1bmtzKGEsIGIsIHBhdGNoLCBpbmRleCkge1xuICAgICAgICAgICAgICAgIHZhciBub2RlcyA9IGhhbmRsZVRodW5rKGEsIGIpO1xuICAgICAgICAgICAgICAgIHZhciB0aHVua1BhdGNoID0gZGlmZihub2Rlcy5hLCBub2Rlcy5iKTtcbiAgICAgICAgICAgICAgICBpZiAoaGFzUGF0Y2hlcyh0aHVua1BhdGNoKSkge1xuICAgICAgICAgICAgICAgICAgICBwYXRjaFtpbmRleF0gPSBuZXcgVlBhdGNoKFZQYXRjaC5USFVOSywgbnVsbCwgdGh1bmtQYXRjaCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBmdW5jdGlvbiBoYXNQYXRjaGVzKHBhdGNoKSB7XG4gICAgICAgICAgICAgICAgZm9yICh2YXIgaW5kZXggaW4gcGF0Y2gpIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKGluZGV4ICE9PSBcImFcIikge1xuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIC8vIEV4ZWN1dGUgaG9va3Mgd2hlbiB0d28gbm9kZXMgYXJlIGlkZW50aWNhbFxuICAgICAgICAgICAgZnVuY3Rpb24gdW5ob29rKHZOb2RlLCBwYXRjaCwgaW5kZXgpIHtcbiAgICAgICAgICAgICAgICBpZiAoaXNWTm9kZSh2Tm9kZSkpIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKHZOb2RlLmhvb2tzKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBwYXRjaFtpbmRleF0gPSBhcHBlbmRQYXRjaChwYXRjaFtpbmRleF0sIG5ldyBWUGF0Y2goVlBhdGNoLlBST1BTLCB2Tm9kZSwgdW5kZWZpbmVkS2V5cyh2Tm9kZS5ob29rcykpKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgIGlmICh2Tm9kZS5kZXNjZW5kYW50SG9va3MgfHwgdk5vZGUuaGFzVGh1bmtzKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICB2YXIgY2hpbGRyZW4gPSB2Tm9kZS5jaGlsZHJlbjtcbiAgICAgICAgICAgICAgICAgICAgICAgIHZhciBsZW4gPSBjaGlsZHJlbi5sZW5ndGg7XG4gICAgICAgICAgICAgICAgICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IGxlbjsgaSsrKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdmFyIGNoaWxkID0gY2hpbGRyZW5baV07XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaW5kZXggKz0gMTtcblxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHVuaG9vayhjaGlsZCwgcGF0Y2gsIGluZGV4KTtcblxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChpc1ZOb2RlKGNoaWxkKSAmJiBjaGlsZC5jb3VudCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpbmRleCArPSBjaGlsZC5jb3VudDtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKGlzVGh1bmsodk5vZGUpKSB7XG4gICAgICAgICAgICAgICAgICAgIHRodW5rcyh2Tm9kZSwgbnVsbCwgcGF0Y2gsIGluZGV4KTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIHVuZGVmaW5lZEtleXMob2JqKSB7XG4gICAgICAgICAgICAgICAgdmFyIHJlc3VsdCA9IHt9O1xuXG4gICAgICAgICAgICAgICAgZm9yICh2YXIga2V5IGluIG9iaikge1xuICAgICAgICAgICAgICAgICAgICByZXN1bHRba2V5XSA9IHVuZGVmaW5lZDtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICByZXR1cm4gcmVzdWx0O1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAvLyBMaXN0IGRpZmYsIG5haXZlIGxlZnQgdG8gcmlnaHQgcmVvcmRlcmluZ1xuICAgICAgICAgICAgZnVuY3Rpb24gcmVvcmRlcihhQ2hpbGRyZW4sIGJDaGlsZHJlbikge1xuICAgICAgICAgICAgICAgIC8vIE8oTSkgdGltZSwgTyhNKSBtZW1vcnlcbiAgICAgICAgICAgICAgICB2YXIgYkNoaWxkSW5kZXggPSBrZXlJbmRleChiQ2hpbGRyZW4pO1xuICAgICAgICAgICAgICAgIHZhciBiS2V5cyA9IGJDaGlsZEluZGV4LmtleXM7XG4gICAgICAgICAgICAgICAgdmFyIGJGcmVlID0gYkNoaWxkSW5kZXguZnJlZTtcblxuICAgICAgICAgICAgICAgIGlmIChiRnJlZS5sZW5ndGggPT09IGJDaGlsZHJlbi5sZW5ndGgpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGNoaWxkcmVuOiBiQ2hpbGRyZW4sXG4gICAgICAgICAgICAgICAgICAgICAgICBtb3ZlczogbnVsbFxuICAgICAgICAgICAgICAgICAgICB9O1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIC8vIE8oTikgdGltZSwgTyhOKSBtZW1vcnlcbiAgICAgICAgICAgICAgICB2YXIgYUNoaWxkSW5kZXggPSBrZXlJbmRleChhQ2hpbGRyZW4pO1xuICAgICAgICAgICAgICAgIHZhciBhS2V5cyA9IGFDaGlsZEluZGV4LmtleXM7XG4gICAgICAgICAgICAgICAgdmFyIGFGcmVlID0gYUNoaWxkSW5kZXguZnJlZTtcblxuICAgICAgICAgICAgICAgIGlmIChhRnJlZS5sZW5ndGggPT09IGFDaGlsZHJlbi5sZW5ndGgpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGNoaWxkcmVuOiBiQ2hpbGRyZW4sXG4gICAgICAgICAgICAgICAgICAgICAgICBtb3ZlczogbnVsbFxuICAgICAgICAgICAgICAgICAgICB9O1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIC8vIE8oTUFYKE4sIE0pKSBtZW1vcnlcbiAgICAgICAgICAgICAgICB2YXIgbmV3Q2hpbGRyZW4gPSBbXTtcblxuICAgICAgICAgICAgICAgIHZhciBmcmVlSW5kZXggPSAwO1xuICAgICAgICAgICAgICAgIHZhciBmcmVlQ291bnQgPSBiRnJlZS5sZW5ndGg7XG4gICAgICAgICAgICAgICAgdmFyIGRlbGV0ZWRJdGVtcyA9IDA7XG5cbiAgICAgICAgICAgICAgICAvLyBJdGVyYXRlIHRocm91Z2ggYSBhbmQgbWF0Y2ggYSBub2RlIGluIGJcbiAgICAgICAgICAgICAgICAvLyBPKE4pIHRpbWUsXG4gICAgICAgICAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCBhQ2hpbGRyZW4ubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgICAgICAgICAgdmFyIGFJdGVtID0gYUNoaWxkcmVuW2ldO1xuICAgICAgICAgICAgICAgICAgICB2YXIgaXRlbUluZGV4O1xuXG4gICAgICAgICAgICAgICAgICAgIGlmIChhSXRlbS5rZXkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChiS2V5cy5oYXNPd25Qcm9wZXJ0eShhSXRlbS5rZXkpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gTWF0Y2ggdXAgdGhlIG9sZCBrZXlzXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaXRlbUluZGV4ID0gYktleXNbYUl0ZW0ua2V5XTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBuZXdDaGlsZHJlbi5wdXNoKGJDaGlsZHJlbltpdGVtSW5kZXhdKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gUmVtb3ZlIG9sZCBrZXllZCBpdGVtc1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGl0ZW1JbmRleCA9IGkgLSBkZWxldGVkSXRlbXMrKztcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBuZXdDaGlsZHJlbi5wdXNoKG51bGwpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgLy8gTWF0Y2ggdGhlIGl0ZW0gaW4gYSB3aXRoIHRoZSBuZXh0IGZyZWUgaXRlbSBpbiBiXG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoZnJlZUluZGV4IDwgZnJlZUNvdW50KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaXRlbUluZGV4ID0gYkZyZWVbZnJlZUluZGV4KytdO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIG5ld0NoaWxkcmVuLnB1c2goYkNoaWxkcmVuW2l0ZW1JbmRleF0pO1xuICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBUaGVyZSBhcmUgbm8gZnJlZSBpdGVtcyBpbiBiIHRvIG1hdGNoIHdpdGhcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyB0aGUgZnJlZSBpdGVtcyBpbiBhLCBzbyB0aGUgZXh0cmEgZnJlZSBub2Rlc1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIGFyZSBkZWxldGVkLlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGl0ZW1JbmRleCA9IGkgLSBkZWxldGVkSXRlbXMrKztcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBuZXdDaGlsZHJlbi5wdXNoKG51bGwpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgdmFyIGxhc3RGcmVlSW5kZXggPSBmcmVlSW5kZXggPj0gYkZyZWUubGVuZ3RoID8gYkNoaWxkcmVuLmxlbmd0aCA6IGJGcmVlW2ZyZWVJbmRleF07XG5cbiAgICAgICAgICAgICAgICAvLyBJdGVyYXRlIHRocm91Z2ggYiBhbmQgYXBwZW5kIGFueSBuZXcga2V5c1xuICAgICAgICAgICAgICAgIC8vIE8oTSkgdGltZVxuICAgICAgICAgICAgICAgIGZvciAodmFyIGogPSAwOyBqIDwgYkNoaWxkcmVuLmxlbmd0aDsgaisrKSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciBuZXdJdGVtID0gYkNoaWxkcmVuW2pdO1xuXG4gICAgICAgICAgICAgICAgICAgIGlmIChuZXdJdGVtLmtleSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKCFhS2V5cy5oYXNPd25Qcm9wZXJ0eShuZXdJdGVtLmtleSkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBBZGQgYW55IG5ldyBrZXllZCBpdGVtc1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIFdlIGFyZSBhZGRpbmcgbmV3IGl0ZW1zIHRvIHRoZSBlbmQgYW5kIHRoZW4gc29ydGluZyB0aGVtXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gaW4gcGxhY2UuIEluIGZ1dHVyZSB3ZSBzaG91bGQgaW5zZXJ0IG5ldyBpdGVtcyBpbiBwbGFjZS5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBuZXdDaGlsZHJlbi5wdXNoKG5ld0l0ZW0pO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKGogPj0gbGFzdEZyZWVJbmRleCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgLy8gQWRkIGFueSBsZWZ0b3ZlciBub24ta2V5ZWQgaXRlbXNcbiAgICAgICAgICAgICAgICAgICAgICAgIG5ld0NoaWxkcmVuLnB1c2gobmV3SXRlbSk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICB2YXIgc2ltdWxhdGUgPSBuZXdDaGlsZHJlbi5zbGljZSgpO1xuICAgICAgICAgICAgICAgIHZhciBzaW11bGF0ZUluZGV4ID0gMDtcbiAgICAgICAgICAgICAgICB2YXIgcmVtb3ZlcyA9IFtdO1xuICAgICAgICAgICAgICAgIHZhciBpbnNlcnRzID0gW107XG4gICAgICAgICAgICAgICAgdmFyIHNpbXVsYXRlSXRlbTtcblxuICAgICAgICAgICAgICAgIGZvciAodmFyIGsgPSAwOyBrIDwgYkNoaWxkcmVuLmxlbmd0aDspIHtcbiAgICAgICAgICAgICAgICAgICAgdmFyIHdhbnRlZEl0ZW0gPSBiQ2hpbGRyZW5ba107XG4gICAgICAgICAgICAgICAgICAgIHNpbXVsYXRlSXRlbSA9IHNpbXVsYXRlW3NpbXVsYXRlSW5kZXhdO1xuXG4gICAgICAgICAgICAgICAgICAgIC8vIHJlbW92ZSBpdGVtc1xuICAgICAgICAgICAgICAgICAgICB3aGlsZSAoc2ltdWxhdGVJdGVtID09PSBudWxsICYmIHNpbXVsYXRlLmxlbmd0aCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgcmVtb3Zlcy5wdXNoKHJlbW92ZShzaW11bGF0ZSwgc2ltdWxhdGVJbmRleCwgbnVsbCkpO1xuICAgICAgICAgICAgICAgICAgICAgICAgc2ltdWxhdGVJdGVtID0gc2ltdWxhdGVbc2ltdWxhdGVJbmRleF07XG4gICAgICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgICAgICBpZiAoIXNpbXVsYXRlSXRlbSB8fCBzaW11bGF0ZUl0ZW0ua2V5ICE9PSB3YW50ZWRJdGVtLmtleSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgLy8gaWYgd2UgbmVlZCBhIGtleSBpbiB0aGlzIHBvc2l0aW9uLi4uXG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAod2FudGVkSXRlbS5rZXkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoc2ltdWxhdGVJdGVtICYmIHNpbXVsYXRlSXRlbS5rZXkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gaWYgYW4gaW5zZXJ0IGRvZXNuJ3QgcHV0IHRoaXMga2V5IGluIHBsYWNlLCBpdCBuZWVkcyB0byBtb3ZlXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChiS2V5c1tzaW11bGF0ZUl0ZW0ua2V5XSAhPT0gayArIDEpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlbW92ZXMucHVzaChyZW1vdmUoc2ltdWxhdGUsIHNpbXVsYXRlSW5kZXgsIHNpbXVsYXRlSXRlbS5rZXkpKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNpbXVsYXRlSXRlbSA9IHNpbXVsYXRlW3NpbXVsYXRlSW5kZXhdO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gaWYgdGhlIHJlbW92ZSBkaWRuJ3QgcHV0IHRoZSB3YW50ZWQgaXRlbSBpbiBwbGFjZSwgd2UgbmVlZCB0byBpbnNlcnQgaXRcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmICghc2ltdWxhdGVJdGVtIHx8IHNpbXVsYXRlSXRlbS5rZXkgIT09IHdhbnRlZEl0ZW0ua2V5KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaW5zZXJ0cy5wdXNoKHsga2V5OiB3YW50ZWRJdGVtLmtleSwgdG86IGsgfSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBpdGVtcyBhcmUgbWF0Y2hpbmcsIHNvIHNraXAgYWhlYWRcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzaW11bGF0ZUluZGV4Kys7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaW5zZXJ0cy5wdXNoKHsga2V5OiB3YW50ZWRJdGVtLmtleSwgdG86IGsgfSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpbnNlcnRzLnB1c2goeyBrZXk6IHdhbnRlZEl0ZW0ua2V5LCB0bzogayB9KTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaysrO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgLy8gYSBrZXkgaW4gc2ltdWxhdGUgaGFzIG5vIG1hdGNoaW5nIHdhbnRlZCBrZXksIHJlbW92ZSBpdFxuICAgICAgICAgICAgICAgICAgICAgICAgZWxzZSBpZiAoc2ltdWxhdGVJdGVtICYmIHNpbXVsYXRlSXRlbS5rZXkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmVtb3Zlcy5wdXNoKHJlbW92ZShzaW11bGF0ZSwgc2ltdWxhdGVJbmRleCwgc2ltdWxhdGVJdGVtLmtleSkpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHNpbXVsYXRlSW5kZXgrKztcbiAgICAgICAgICAgICAgICAgICAgICAgIGsrKztcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIC8vIHJlbW92ZSBhbGwgdGhlIHJlbWFpbmluZyBub2RlcyBmcm9tIHNpbXVsYXRlXG4gICAgICAgICAgICAgICAgd2hpbGUgKHNpbXVsYXRlSW5kZXggPCBzaW11bGF0ZS5sZW5ndGgpIHtcbiAgICAgICAgICAgICAgICAgICAgc2ltdWxhdGVJdGVtID0gc2ltdWxhdGVbc2ltdWxhdGVJbmRleF07XG4gICAgICAgICAgICAgICAgICAgIHJlbW92ZXMucHVzaChyZW1vdmUoc2ltdWxhdGUsIHNpbXVsYXRlSW5kZXgsIHNpbXVsYXRlSXRlbSAmJiBzaW11bGF0ZUl0ZW0ua2V5KSk7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgLy8gSWYgdGhlIG9ubHkgbW92ZXMgd2UgaGF2ZSBhcmUgZGVsZXRlcyB0aGVuIHdlIGNhbiBqdXN0XG4gICAgICAgICAgICAgICAgLy8gbGV0IHRoZSBkZWxldGUgcGF0Y2ggcmVtb3ZlIHRoZXNlIGl0ZW1zLlxuICAgICAgICAgICAgICAgIGlmIChyZW1vdmVzLmxlbmd0aCA9PT0gZGVsZXRlZEl0ZW1zICYmICFpbnNlcnRzLmxlbmd0aCkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgICAgICAgICAgICAgY2hpbGRyZW46IG5ld0NoaWxkcmVuLFxuICAgICAgICAgICAgICAgICAgICAgICAgbW92ZXM6IG51bGxcbiAgICAgICAgICAgICAgICAgICAgfTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgICAgICAgICBjaGlsZHJlbjogbmV3Q2hpbGRyZW4sXG4gICAgICAgICAgICAgICAgICAgIG1vdmVzOiB7XG4gICAgICAgICAgICAgICAgICAgICAgICByZW1vdmVzOiByZW1vdmVzLFxuICAgICAgICAgICAgICAgICAgICAgICAgaW5zZXJ0czogaW5zZXJ0c1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZnVuY3Rpb24gcmVtb3ZlKGFyciwgaW5kZXgsIGtleSkge1xuICAgICAgICAgICAgICAgIGFyci5zcGxpY2UoaW5kZXgsIDEpO1xuXG4gICAgICAgICAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgICAgICAgICAgZnJvbTogaW5kZXgsXG4gICAgICAgICAgICAgICAgICAgIGtleToga2V5XG4gICAgICAgICAgICAgICAgfTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZnVuY3Rpb24ga2V5SW5kZXgoY2hpbGRyZW4pIHtcbiAgICAgICAgICAgICAgICB2YXIga2V5cyA9IHt9O1xuICAgICAgICAgICAgICAgIHZhciBmcmVlID0gW107XG4gICAgICAgICAgICAgICAgdmFyIGxlbmd0aCA9IGNoaWxkcmVuLmxlbmd0aDtcblxuICAgICAgICAgICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgbGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgICAgICAgICAgdmFyIGNoaWxkID0gY2hpbGRyZW5baV07XG5cbiAgICAgICAgICAgICAgICAgICAgaWYgKGNoaWxkLmtleSkge1xuICAgICAgICAgICAgICAgICAgICAgICAga2V5c1tjaGlsZC5rZXldID0gaTtcbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGZyZWUucHVzaChpKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHJldHVybiB7XG4gICAgICAgICAgICAgICAgICAgIGtleXM6IGtleXMsIC8vIEEgaGFzaCBvZiBrZXkgbmFtZSB0byBpbmRleFxuICAgICAgICAgICAgICAgICAgICBmcmVlOiBmcmVlIC8vIEFuIGFycmF5IG9mIHVua2V5ZWQgaXRlbSBpbmRpY2VzXG4gICAgICAgICAgICAgICAgfTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZnVuY3Rpb24gYXBwZW5kUGF0Y2goYXBwbHksIHBhdGNoKSB7XG4gICAgICAgICAgICAgICAgaWYgKGFwcGx5KSB7XG4gICAgICAgICAgICAgICAgICAgIGlmIChpc0FycmF5KGFwcGx5KSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgYXBwbHkucHVzaChwYXRjaCk7XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBhcHBseSA9IFthcHBseSwgcGF0Y2hdO1xuICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGFwcGx5O1xuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBwYXRjaDtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH0sIHsgXCIuLi92bm9kZS9oYW5kbGUtdGh1bmtcIjogMjQsIFwiLi4vdm5vZGUvaXMtdGh1bmtcIjogMjUsIFwiLi4vdm5vZGUvaXMtdm5vZGVcIjogMjcsIFwiLi4vdm5vZGUvaXMtdnRleHRcIjogMjgsIFwiLi4vdm5vZGUvaXMtd2lkZ2V0XCI6IDI5LCBcIi4uL3Zub2RlL3ZwYXRjaFwiOiAzMiwgXCIuL2RpZmYtcHJvcHNcIjogMzQsIFwieC1pcy1hcnJheVwiOiAxMiB9XSB9LCB7fSwgWzRdKSg0KTtcbn0pO1xuXG5leHBvcnQgZGVmYXVsdCBWaXJ0dWFsRE9NO1xuLy8jIHNvdXJjZU1hcHBpbmdVUkw9ZGF0YTphcHBsaWNhdGlvbi9qc29uO2Jhc2U2NCxleUoyWlhKemFXOXVJam96TENKemIzVnlZMlZ6SWpwYklteHBZaTkyYVhKMGRXRnNMV1J2YlM1cWN5SmRMQ0p1WVcxbGN5STZXMTBzSW0xaGNIQnBibWR6SWpvaVFVRkJRU3hKUVVGSkxHRkJRV0VzVlVGQlV5eERRVUZVTEVWQlFWazdRVUZETTBJc1YwRkJUeXhIUVVGUUxFTkJSREpDTzBOQlFWb3NRMEZGWml4WlFVRlhPMEZCUTB3c1VVRkJTU3hOUVVGS0xFVkJRVmtzVFVGQldpeEZRVUZ2UWl4UFFVRndRaXhEUVVSTE8wRkJSVXdzVjBGQlR5eFRRVUZWTEVOQlFWUXNRMEZCVnl4RFFVRllMRVZCUVdNc1EwRkJaQ3hGUVVGcFFpeERRVUZxUWl4RlFVRnZRanRCUVVOd1FpeHBRa0ZCVXl4RFFVRlVMRU5CUVZjc1EwRkJXQ3hGUVVGakxFTkJRV1FzUlVGQmFVSTdRVUZEWWl4blFrRkJTU3hEUVVGRExFVkJRVVVzUTBGQlJpeERRVUZFTEVWQlFVODdRVUZEVUN4dlFrRkJTU3hEUVVGRExFVkJRVVVzUTBGQlJpeERRVUZFTEVWQlFVODdRVUZEVUN4M1FrRkJTU3hKUVVGSkxFOUJRVThzVDBGQlVDeEpRVUZyUWl4VlFVRnNRaXhKUVVGblF5eFBRVUZvUXl4RFFVUkVPMEZCUlZBc2QwSkJRVWtzUTBGQlF5eERRVUZFTEVsQlFVMHNRMEZCVGl4RlFVRlRMRTlCUVU4c1JVRkJSU3hEUVVGR0xFVkJRVXNzUTBGQlF5eERRVUZFTEVOQlFWb3NRMEZCWWp0QlFVTkJMSGRDUVVGSkxFTkJRVW9zUlVGQlR5eFBRVUZQTEVWQlFVVXNRMEZCUml4RlFVRkxMRU5CUVVNc1EwRkJSQ3hEUVVGYUxFTkJRVkE3UVVGRFFTeDNRa0ZCU1N4SlFVRkpMRWxCUVVrc1MwRkJTaXhEUVVGVkxIbENRVUY1UWl4RFFVRjZRaXhIUVVFMlFpeEhRVUUzUWl4RFFVRmtMRU5CU2tjN1FVRkxVQ3d3UWtGQlRTeEZRVUZGTEVsQlFVWXNSMEZCVXl4clFrRkJWQ3hGUVVFMlFpeERRVUUzUWl4RFFVeERPMmxDUVVGWU8wRkJUMEVzYjBKQlFVa3NTVUZCU1N4RlFVRkZMRU5CUVVZc1NVRkJUenRCUVVOWUxEWkNRVUZUTEVWQlFWUTdhVUpCUkVrc1EwRlNSRHRCUVZkUUxHdENRVUZGTEVOQlFVWXNSVUZCU3l4RFFVRk1MRVZCUVZFc1NVRkJVaXhEUVVGaExFVkJRVVVzVDBGQlJpeEZRVUZYTEZWQlFWTXNRMEZCVkN4RlFVRlpPMEZCUTJoRExIZENRVUZKTEVsQlFVa3NSVUZCUlN4RFFVRkdMRVZCUVVzc1EwRkJUQ3hGUVVGUkxFTkJRVklzUTBGQlNpeERRVVEwUWp0QlFVVm9ReXd5UWtGQlR5eEZRVUZGTEVsQlFVa3NRMEZCU2l4SFFVRlJMRU5CUVZJc1EwRkJWQ3hEUVVablF6dHBRa0ZCV2l4RlFVZHlRaXhEUVVoSUxFVkJSMDBzUlVGQlJTeFBRVUZHTEVWQlFWY3NRMEZJYWtJc1JVRkhiMElzUTBGSWNFSXNSVUZIZFVJc1EwRklka0lzUlVGSE1FSXNRMEZJTVVJc1JVRllUenRoUVVGWU8wRkJaMEpCTEcxQ1FVRlBMRVZCUVVVc1EwRkJSaXhGUVVGTExFOUJRVXdzUTBGcVFrMDdVMEZCYWtJN1FVRnRRa0VzV1VGQlNTeEpRVUZKTEU5QlFVOHNUMEZCVUN4SlFVRnJRaXhWUVVGc1FpeEpRVUZuUXl4UFFVRm9ReXhEUVhCQ1dUdEJRWEZDY0VJc1lVRkJTeXhKUVVGSkxFbEJRVWtzUTBGQlNpeEZRVUZQTEVsQlFVa3NSVUZCUlN4TlFVRkdMRVZCUVZVc1IwRkJPVUlzUlVGQmJVTXNSVUZCUlN4RlFVRkZMRU5CUVVZc1EwRkJSaXhGUVVGdVF6dEJRVU5CTEdWQlFVOHNRMEZCVUN4RFFYUkNiMEk3UzBGQmNFSXNRMEYxUWtRN1FVRkRTeXhYUVVGSExFTkJRVU1zVlVGQlV5eFBRVUZVTEVWQlFXdENMRTFCUVd4Q0xFVkJRVEJDTEU5QlFURkNMRVZCUVcxRE96dEJRVVV6UkN4blFrRkJTU3huUWtGQlowSXNVVUZCVVN3d1FrRkJVaXhEUVVGb1FpeERRVVoxUkRzN1FVRkpNMFFzYlVKQlFVOHNUMEZCVUN4SFFVRnBRaXhoUVVGcVFpeERRVW95UkR0VFFVRnVReXhGUVUxMFFpeEZRVUZETERSQ1FVRXlRaXhGUVVFelFpeEZRVTV2UWl4RFFVRklMRVZCVFdVc1IwRkJSU3hEUVVGRExGVkJRVk1zVDBGQlZDeEZRVUZwUWl4TlFVRnFRaXhGUVVGM1FpeFBRVUY0UWl4RlFVRm5RenRCUVVOMFJTeG5Ra0ZCU1N4UFFVRlBMRkZCUVZFc2FVSkJRVklzUTBGQlVDeERRVVJyUlRzN1FVRkhkRVVzYlVKQlFVOHNUMEZCVUN4SFFVRnBRaXhKUVVGcVFpeERRVWh6UlR0VFFVRm9ReXhGUVV0d1F5eEZRVUZETEcxQ1FVRnJRaXhGUVVGc1FpeEZRVXhyUXl4RFFVRkdMRVZCUzFRc1IwRkJSU3hEUVVGRExGVkJRVk1zVDBGQlZDeEZRVUZwUWl4TlFVRnFRaXhGUVVGM1FpeFBRVUY0UWl4RlFVRm5RenRCUVVNM1JDeG5Ra0ZCU1N4SlFVRkpMRkZCUVZFc1owTkJRVklzUTBGQlNpeERRVVI1UkRzN1FVRkhOMFFzYlVKQlFVOHNUMEZCVUN4SFFVRnBRaXhEUVVGcVFpeERRVWcyUkR0VFFVRm9ReXhGUVVzelFpeEZRVUZETEd0RFFVRnBReXhGUVVGcVF5eEZRVXg1UWl4RFFVRkdMRVZCUzJVc1IwRkJSU3hEUVVGRExGVkJRVk1zVDBGQlZDeEZRVUZwUWl4TlFVRnFRaXhGUVVGM1FpeFBRVUY0UWl4RlFVRm5RenRCUVVNMVJTeG5Ra0ZCU1N4UFFVRlBMRkZCUVZFc1YwRkJVaXhEUVVGUUxFTkJSSGRGTzBGQlJUVkZMR2RDUVVGSkxGRkJRVkVzVVVGQlVTeFpRVUZTTEVOQlFWSXNRMEZHZDBVN1FVRkhOVVVzWjBKQlFVa3NTVUZCU1N4UlFVRlJMRkZCUVZJc1EwRkJTaXhEUVVoM1JUdEJRVWsxUlN4blFrRkJTU3hUUVVGVExGRkJRVkVzY1VKQlFWSXNRMEZCVkN4RFFVcDNSVHRCUVVzMVJTeG5Ra0ZCU1N4UlFVRlJMRkZCUVZFc2EwSkJRVklzUTBGQlVpeERRVXgzUlR0QlFVMDFSU3huUWtGQlNTeFJRVUZSTEZGQlFWRXNhMEpCUVZJc1EwRkJVaXhEUVU1M1JUczdRVUZSTlVVc2JVSkJRVThzVDBGQlVDeEhRVUZwUWp0QlFVTmlMSE5DUVVGTkxFbEJRVTQ3UVVGRFFTeDFRa0ZCVHl4TFFVRlFPMEZCUTBFc2JVSkJRVWNzUTBGQlNEdEJRVU5CTEhkQ1FVRlJMRTFCUVZJN1FVRkRRU3gxUWtGQlR5eExRVUZRTzBGQlEwRXNkVUpCUVU4c1MwRkJVRHRoUVU1S0xFTkJValJGTzFOQlFXaERMRVZCYVVJeFF5eEZRVUZETEhWQ1FVRnpRaXhEUVVGMFFpeEZRVUYzUWl4aFFVRlpMRU5CUVZvc1JVRkJZeXhWUVVGVExFTkJRVlFzUlVGQlZ5eGpRVUZoTEVWQlFXSXNSVUZCWjBJc2IwSkJRVzFDTEVWQlFXNUNMRVZCUVhOQ0xHOUNRVUZ0UWl4RlFVRnVRaXhGUVdwQ0wwTXNRMEZCUml4RlFXbENlVVVzUjBGQlJTeERRVUZETEZWQlFWTXNUMEZCVkN4RlFVRnBRaXhOUVVGcVFpeEZRVUYzUWl4UFFVRjRRaXhGUVVGblF6czdPenM3T3pzN096czdPenM3T3pzN096czdPenM3T3pzN096czdPenM3UVVGblEzSktMRzFDUVVGUExFOUJRVkFzUjBGQmFVSXNVMEZCVlN4TFFVRlVMRU5CUVdVc1MwRkJaaXhGUVVGelFqczdRVUZGZEVNc2IwSkJRVWtzWTBGQll5eFBRVUZQTEZOQlFWQXNRMEZCYVVJc1MwRkJha0k3YjBKQlEyaENMRzlDUVVGdlFpeFBRVUZQTEVsQlFWQXNRMEZCV1N4RlFVRmFMRVZCUVdkQ0xFTkJRV2hDTEUxQlFYVkNMRXRCUVhaQ096czdRVUZGY0VJc2IwSkJTRVlzUTBGR2MwTTdPMEZCVDNSRExIVkNRVUZQTEZWQlFWTXNSMEZCVkN4RlFVRmpMRk5CUVdRc1JVRkJlVUlzUzBGQmVrSXNSVUZCWjBNN08wRkJSWEpETEhkQ1FVRkpMRTlCUVU4c1UwRkJVQ3hEUVVGcFFpeFJRVUZxUWl4RFFVRXdRaXhKUVVFeFFpeERRVUVyUWl4VFFVRXZRaXhOUVVFNFF5eHBRa0ZCT1VNc1JVRkJhVVU3UVVGRGJrVXNLMEpCUVU4c1dVRkJXU3hKUVVGYUxFTkJRV2xDTEVkQlFXcENMRVZCUVhOQ0xGTkJRWFJDTEVWQlFXbERMRXRCUVdwRExFTkJRVkFzUTBGRWJVVTdjVUpCUVhKRk8wRkJSMEVzZDBKQlFVa3NVMEZCVXl4RlFVRlVPM2RDUVVOR0xGRkJRVkVzUTBGQlF5eFZRVUZWTEZWQlFWWXNSMEZCZFVJc1IwRkJka0lzUjBGQk5rSXNSVUZCTjBJc1EwRkJSQ3hKUVVGeFF5eFZRVUZWTEZOQlFWWXNSMEZCYzBJc1IwRkJkRUlzUjBGQk5FSXNSVUZCTlVJc1EwRkJja01zU1VGQmQwVXNWVUZCVlN4UlFVRldMRWRCUVhGQ0xFZEJRWEpDTEVkQlFUSkNMRVZCUVROQ0xFTkJRWGhGTzBGQlExQXNPRUpCUVZVc1RVRkJWaXhIUVVGdFFpeEhRVUZ1UWl4SFFVRjVRaXhGUVVGNlFpeERRVVJQT3pzN1FVRkhVaXh2UTBGQlowSXNRMEZCYUVJN096dEJRVVZCTEdkRFFVRlpMRWxCUVVrc1RVRkJTaXhEUVVGWExGVkJRVlVzVFVGQlZpeEZRVUZyUWl4UlFVRlJMRWRCUVZJc1EwRkJla003ZDBKQlEwRXNWVUZRUmp0M1FrRlBZeXhMUVZCa08zZENRVTl4UWl4VFFWQnlRanQzUWtGUFowTXNWVUZRYUVNc1EwRk1jVU03UVVGaGNrTXNNa0pCUVU4c1JVRkJVRHRCUVdKeFF5eDNRa0ZqYWtNc1EwRkJReXhwUWtGQlJDeEZRVUZ2UWpzN1FVRkZkRUlzY1VOQlFXRXNTVUZCU1N4TlFVRktMRU5CUVZjc1RVRkJUU3hWUVVGVkxFMUJRVllzUjBGQmJVSXNWVUZCZWtJc1JVRkJjVU1zUzBGQmFFUXNRMEZCWWl4RFFVWnpRanR4UWtGQmVFSTdPenM3T3pzN08wRkJaSEZETEhsQ1FYbENja01zUjBGQlVTeFZRVUZWTEV0QlFWWXNSMEZCYTBJc1EwRkJReXhEUVVGRUxFdEJRVThzUTBGQlVEdEJRVU14UWl3NFFrRkJWU3hEUVVGV08wRkJNVUp4UXl3eVFrRXlRamxDTEZGQlFWRXNWVUZCVlN4SlFVRldMRU5CUVdVc1IwRkJaaXhEUVVGU0xFVkJRVFpDT3p0QlFVVnNReXh2UTBGQldTeE5RVUZOTEV0QlFVNHNSMEZCWXl4TlFVRk5MRU5CUVU0c1JVRkJVeXhOUVVGVUxFTkJSbEU3UVVGSGJFTXNORUpCUVVrc1dVRkJXU3hoUVVGYUxFVkJRVEpDTzBGQlF6ZENMRzFEUVVGUExFbEJRVkFzUTBGQldTeEpRVUZKTEV0QlFVb3NRMEZCVlN4aFFVRldMRVZCUVhsQ0xFMUJRVTBzUzBGQlRpeERRVUZ5UXpzN08wRkJSRFpDTEdkRFFVbDZRaXhEUVVGRExHbENRVUZFTEVsQlFYTkNMRTFCUVUwc1RVRkJUaXhIUVVGbExFTkJRV1lzUlVGQmEwSTdRVUZETVVNc2MwTkJRVTBzUTBGQlRpeEZRVUZUTEU5QlFWUXNRMEZCYVVJc1ZVRkJha0lzUlVGQk5rSXNXVUZCVnp0QlFVTjBReXg1UTBGQlN5eEpRVUZKTEVsQlFVa3NRMEZCU2l4RlFVRlBMRWxCUVVrc1ZVRkJWU3hOUVVGV0xFZEJRVzFDTEVOQlFXNUNMRVZCUVhOQ0xFZEJRVEZETEVWQlFTdERPMEZCUXpkRExEUkRRVUZKTEZWQlFWVXNRMEZCVml4TlFVRnBRaXhMUVVGcVFpeEZRVUYzUWp0QlFVTXhRaXhyUkVGQlRTeERRVUZPTEVsQlFWY3NTMEZCV0N4RFFVUXdRanQ1UTBGQk5VSTdjVU5CUkVZN2FVTkJSREpDTEVOQlFUZENMRU5CUkRCRE96WkNRVUUxUXp0QlFWTkJMR2REUVVGSkxFMUJRVTBzVFVGQlRpeEhRVUZsTEVOQlFXWXNTVUZCYjBJc1RVRkJUU3hMUVVGT0xFZEJRV01zU1VGQlNTeE5RVUZLTEVWQlFWazdRVUZEYUVRc2MwTkJRVTBzVTBGQlRpeERRVUZuUWl4SlFVRm9RaXhEUVVGeFFpeExRVUZ5UWl4RFFVRXlRaXhOUVVFelFpeEZRVUZ0UXl4TlFVRk5MRXRCUVU0c1EwRkJXU3hEUVVGYUxFTkJRVzVETEVWQlJHZEVPelpDUVVGc1JEdEJRVWRCTEhsRFFVRmhMRTFCUVUwc1EwRkJUaXhGUVVGVExFMUJRVlFzUTBGb1FtZENPMEZCYVVJM1FpdzBRMEZCWjBJc1UwRkJhRUlzUTBGcVFqWkNPMEZCYTBJM1FpeG5RMEZCU1N4UFFVRlBMRTFCUVZBc1NVRkJhVUlzUzBGQmFrSXNSVUZCZDBJN1FVRkRNVUlzYzBOQlJEQkNPelpDUVVFMVFqdDVRa0ZzUWtZN1FVRnpRa0VzTkVKQlFVa3NWVUZCVlN4VFFVRldMRXRCUVhkQ0xFMUJRVTBzUzBGQlRpeEZRVUZoTzBGQlEzWkRMSE5EUVVGVkxGTkJRVlk3UVVGRWRVTXNlVUpCUVhwRE8zRkNRWHBDUmp0QlFUWkNRU3gzUWtGQlNTeHJRa0ZCYTBJc1NVRkJTU3hOUVVGS0xFVkJRVms3UVVGRGFFTXNORUpCUVVrc1kwRkJZeXhEUVVGRExGVkJRVlVzU1VGQlZpeERRVUZsTEVWQlFXWXNRMEZCUkN4RlFVRnhRanRCUVVOeVF5eHRRMEZCVHl4SlFVRlFMRU5CUVZrc1JVRkJXaXhGUVVSeFF6dDVRa0ZCZGtNN2NVSkJSRVlzVFVGSlR6dEJRVU5NTEN0Q1FVRlBMRWxCUVZBc1EwRkJXU3hKUVVGSkxFdEJRVW9zUTBGQlZTeGhRVUZXTEVOQlFWb3NSVUZFU3p0eFFrRktVRHRCUVU5QkxESkNRVUZQTEU5QlFVOHNUVUZCVUN4SFFVRm5RaXhMUVVGb1FpeEhRVUYzUWl4UFFVRlBMRXRCUVZBc1EwRkJZU3hEUVVGaUxFVkJRV2RDTEV0QlFXaENMRU5CUVhoQ0xFZEJRV2xFTEUxQlFXcEVMRU5CTDBRNFFqdHBRa0ZCYUVNc1EwRlFLMEk3TzBGQmVVVjBReXgxUWtGQlR5eEpRVUZRTEVOQmVrVnpRenRoUVVGMFFpeEZRVUZzUWl4RFFXaERjVW83VTBGQmFFTXNSVUUwUjI1SUxFVkJOVWRyU0N4RFFVRkdMRVZCTkVjMVJ5eEhRVUZGTEVOQlFVTXNWVUZCVXl4UFFVRlVMRVZCUVdsQ0xFMUJRV3BDTEVWQlFYZENMRTlCUVhoQ0xFVkJRV2RETEVWQlFXaERMRVZCUlZBc1JVRkdUU3hEUVVGR0xFVkJSVUVzUjBGQlJTeERRVUZETEZWQlFWTXNUMEZCVkN4RlFVRnBRaXhOUVVGcVFpeEZRVUYzUWl4UFFVRjRRaXhGUVVGblF6dEJRVU42UXl4NVFrRkVlVU03TzBGQlIzcERMR2RDUVVGSkxIVkNRVUYxUWl4UlFVRlJMSGRDUVVGU0xFTkJRWFpDTEVOQlNIRkRPenRCUVV0NlF5eG5Ra0ZCU1N4aFFVRmhMRWRCUVdJc1EwRk1jVU03UVVGTmVrTXNhVU5CUVhGQ0xGVkJRWEpDTEVWQlFXbERMRlZCUVdwRExFVkJUbmxET3p0QlFWRjZReXhuUWtGQlNTeFZRVUZWTEc5Q1FVRnZRaXhWUVVGd1FpeERRVkl5UWpzN1FVRlZla01zYlVKQlFVOHNUMEZCVUN4SFFVRnBRaXhQUVVGcVFpeERRVlo1UXpzN1FVRlpla01zY1VKQlFWTXNUMEZCVkN4RFFVRnBRaXhKUVVGcVFpeEZRVUYxUWp0QlFVTnVRaXh2UWtGQlNTeFBRVUZQTEV0QlFVc3NUMEZCVEN4RFFVRlFMRU5CUkdVN08wRkJSMjVDTEc5Q1FVRkpMRU5CUVVNc1NVRkJSQ3hGUVVGUE8wRkJRMUFzTWtKQlFVOHNTMEZCU3l4UFFVRk1MRWxCUVdkQ0xFVkJRV2hDTEVOQlJFRTdhVUpCUVZnN08wRkJTVUVzZFVKQlFVOHNTVUZCVUN4RFFWQnRRanRoUVVGMlFqdFRRVnBUTEVWQmMwSlFMRVZCUVVNc01FSkJRWGxDTEVOQlFYcENMRVZCZEVKTExFTkJRVVlzUlVGelFqQkNMRWRCUVVVc1EwRkJReXhWUVVGVExFOUJRVlFzUlVGQmFVSXNUVUZCYWtJc1JVRkJkMElzVDBGQmVFSXNSVUZCWjBNN1FVRkRia1VzWVVGQlF5eFZRVUZWTEUxQlFWWXNSVUZCYVVJN1FVRkRiRUk3T3pzN1FVRkVhMElzYjBKQlMyUXNUMEZCVHl4UFFVRlBMRTFCUVZBc1MwRkJhMElzVjBGQmJFSXNSMEZEVUN4TlFVUlBMRWRCUTBVc1QwRkJUeXhOUVVGUUxFdEJRV3RDTEZkQlFXeENMRWRCUTFRc1RVRkVVeXhIUVVOQkxFVkJSRUVzUTBGT1N6czdRVUZUYkVJc2RVSkJRVThzVDBGQlVDeEhRVUZwUWl4VlFVRnFRaXhEUVZSclFqczdRVUZYYkVJc2VVSkJRVk1zVlVGQlZDeERRVUZ2UWl4SFFVRndRaXhGUVVGNVFpeExRVUY2UWl4RlFVRm5RenRCUVVNMVFpeDNRa0ZCU1N4UFFVRlBMRWxCUVZBc1JVRkJZVHRCUVVOaUxDdENRVUZQTEV0QlFVc3NSMEZCVEN4RFFVRlFMRU5CUkdFN2NVSkJRV3BDT3p0QlFVbEJMSGxDUVVGTExFZEJRVXdzU1VGQldTeExRVUZhTEVOQlREUkNPenRCUVU4MVFpd3lRa0ZCVHl4TFFVRlFMRU5CVURSQ08ybENRVUZvUXp0aFFWaERMRU5CUVVRc1EwRnhRa2NzU1VGeVFrZ3NRMEZ4UWxFc1NVRnlRbElzUlVGeFFtRXNUMEZCVHl4TlFVRlFMRXRCUVd0Q0xGZEJRV3hDTEVkQlFXZERMRTFCUVdoRExFZEJRWGxETEU5QlFVOHNTVUZCVUN4TFFVRm5RaXhYUVVGb1FpeEhRVUU0UWl4SlFVRTVRaXhIUVVGeFF5eFBRVUZQTEUxQlFWQXNTMEZCYTBJc1YwRkJiRUlzUjBGQlowTXNUVUZCYUVNc1IwRkJlVU1zUlVGQmVrTXNRMEZ5UWpOR0xFTkJSRzFGTzFOQlFXaERMRVZCZFVKcVF5eEZRWFpDWjBNc1EwRkJSaXhGUVhWQ01VSXNSMEZCUlN4RFFVRkRMRlZCUVZNc1QwRkJWQ3hGUVVGcFFpeE5RVUZxUWl4RlFVRjNRaXhQUVVGNFFpeEZRVUZuUXp0QlFVTjZReXg1UWtGRWVVTTdPMEZCUjNwRExHZENRVUZKTEdGQlFXRXNVVUZCVVN4WlFVRlNMRU5CUVdJc1EwRkljVU03TzBGQlMzcERMRzFDUVVGUExFOUJRVkFzUjBGQmFVSXNWVUZCYWtJc1EwRk1lVU03TzBGQlQzcERMSEZDUVVGVExGVkJRVlFzUTBGQmIwSXNWVUZCY0VJc1JVRkJaME1zVDBGQmFFTXNSVUZCZVVNc1dVRkJla01zUlVGQmRVUTdRVUZEYmtRc2IwSkJRVWtzVFVGQlRTdzRRa0ZCT0VJc1ZVRkJPVUlzUTBGRWVVTTdRVUZGYmtRc2IwSkJRVWtzWVVGQllTeE5RVUZOTEc5Q1FVRk9MRU5CUm10RE96dEJRVWx1UkN4dlFrRkJTU3hsUVVGbExGZEJRVmNzVlVGQldDeEZRVUYxUWl4UFFVRjJRaXhEUVVGbUxFTkJTaXRET3p0QlFVMXVSQ3h2UWtGQlNTeHBRa0ZCYVVJc1QwRkJha0lzUlVGQk1FSTdRVUZETVVJc01FSkJRVTBzU1VGQlNTeExRVUZLTEVOQlFWVXNLMEpCUTFvc1ZVRkVXU3hIUVVORExFdEJSRVFzUjBGRldpd3lRa0ZHV1N4SFFVVnJRaXhaUVVac1FpeEhRVWRhTEdWQlNGa3NSMEZKV2l4M1EwRktXU3hIUVVrclFpeFBRVW92UWl4RFFVRm9RaXhEUVVRd1FqdHBRa0ZCT1VJN08wRkJVVUVzZFVKQlFVOHNWMEZCVnl4SFFVRllMRVZCUVdkQ0xGbEJRV2hDTEVOQlFWQXNRMEZrYlVRN1lVRkJka1E3VTBGUVV5eEZRWGRDVUN4RlFVRkRMR05CUVdFc1EwRkJZaXhGUVhoQ1N5eERRVUZHTEVWQmQwSmpMRWxCUVVjc1EwRkJReXhWUVVGVExFOUJRVlFzUlVGQmFVSXNUVUZCYWtJc1JVRkJkMElzVDBGQmVFSXNSVUZCWjBNN1FVRkRlRVFzWVVGQlF5eFZRVUZWTEUxQlFWWXNSVUZCYVVJN1FVRkRiRUlzYjBKQlFVa3NWMEZCVnl4UFFVRlBMRTFCUVZBc1MwRkJhMElzVjBGQmJFSXNSMEZCWjBNc1RVRkJhRU1zUjBGRFdDeFBRVUZQTEUxQlFWQXNTMEZCYTBJc1YwRkJiRUlzUjBGQlowTXNUVUZCYUVNc1IwRkJlVU1zUlVGQmVrTXNRMEZHWXp0QlFVZHNRaXh2UWtGQlNTeFRRVUZUTEZGQlFWRXNZMEZCVWl4RFFVRlVMRU5CU0dNN08wRkJTMnhDTEc5Q1FVRkpMRTlCUVU4c1VVRkJVQ3hMUVVGdlFpeFhRVUZ3UWl4RlFVRnBRenRCUVVOcVF5d3lRa0ZCVHl4UFFVRlFMRWRCUVdsQ0xGRkJRV3BDTEVOQlJHbERPMmxDUVVGeVF5eE5RVVZQTzBGQlEwZ3NkMEpCUVVrc1VVRkJVU3hUUVVGVExESkNRVUZVTEVOQlFWSXNRMEZFUkRzN1FVRkhTQ3gzUWtGQlNTeERRVUZETEV0QlFVUXNSVUZCVVR0QlFVTlNMR2REUVVGUkxGTkJRVk1zTWtKQlFWUXNTVUZCZDBNc1RVRkJlRU1zUTBGRVFUdHhRa0ZCV2pzN1FVRkpRU3d5UWtGQlR5eFBRVUZRTEVkQlFXbENMRXRCUVdwQ0xFTkJVRWM3YVVKQlJsQTdZVUZNUXl4RFFVRkVMRU5CYVVKSExFbEJha0pJTEVOQmFVSlJMRWxCYWtKU0xFVkJhVUpoTEU5QlFVOHNUVUZCVUN4TFFVRnJRaXhYUVVGc1FpeEhRVUZuUXl4TlFVRm9ReXhIUVVGNVF5eFBRVUZQTEVsQlFWQXNTMEZCWjBJc1YwRkJhRUlzUjBGQk9FSXNTVUZCT1VJc1IwRkJjVU1zVDBGQlR5eE5RVUZRTEV0QlFXdENMRmRCUVd4Q0xFZEJRV2RETEUxQlFXaERMRWRCUVhsRExFVkJRWHBETEVOQmFrSXpSaXhEUVVSM1JEdFRRVUZvUXl4RlFXMUNkRUlzUlVGQlF5eG5Ra0ZCWlN4RFFVRm1MRVZCYmtKdlFpeERRVUZJTEVWQmJVSkZMRWxCUVVjc1EwRkJReXhWUVVGVExFOUJRVlFzUlVGQmFVSXNUVUZCYWtJc1JVRkJkMElzVDBGQmVFSXNSVUZCWjBNN1FVRkRNVVFzZVVKQlJEQkVPenRCUVVjeFJDeHRRa0ZCVHl4UFFVRlFMRWRCUVdsQ0xGTkJRVk1zVVVGQlZDeERRVUZyUWl4RFFVRnNRaXhGUVVGeFFqdEJRVU55UXl4MVFrRkJUeXhQUVVGUExFTkJRVkFzUzBGQllTeFJRVUZpTEVsQlFYbENMRTFCUVUwc1NVRkJUaXhEUVVSTE8yRkJRWEpDTEVOQlNIbERPMU5CUVdoRExFVkJUM2hDTEVWQlVIVkNMRU5CUVVnc1JVRlBhRUlzU1VGQlJ5eERRVUZETEZWQlFWTXNUMEZCVkN4RlFVRnBRaXhOUVVGcVFpeEZRVUYzUWl4UFFVRjRRaXhGUVVGblF6dEJRVU14UXl4blFrRkJTU3huUWtGQlowSXNUVUZCVFN4UFFVRk9MRU5CUkhOQ08wRkJSVEZETEdkQ1FVRkpMRmRCUVZjc1QwRkJUeXhUUVVGUUxFTkJRV2xDTEZGQlFXcENMRU5CUmpKQ096dEJRVWt4UXl4dFFrRkJUeXhQUVVGUUxFZEJRV2xDTEdsQ1FVRnBRaXhQUVVGcVFpeERRVXA1UWpzN1FVRk5NVU1zY1VKQlFWTXNUMEZCVkN4RFFVRnBRaXhIUVVGcVFpeEZRVUZ6UWp0QlFVTnNRaXgxUWtGQlR5eFRRVUZUTEVsQlFWUXNRMEZCWXl4SFFVRmtMRTFCUVhWQ0xHZENRVUYyUWl4RFFVUlhPMkZCUVhSQ08xTkJUbFVzUlVGVlVpeEZRVlpQTEVOQlFVZ3NSVUZWUVN4SlFVRkhMRU5CUVVNc1ZVRkJVeXhQUVVGVUxFVkJRV2xDTEUxQlFXcENMRVZCUVhkQ0xFOUJRWGhDTEVWQlFXZERPMEZCUXpGRExHZENRVUZKTEZGQlFWRXNVVUZCVVN4cFFrRkJVaXhEUVVGU0xFTkJSSE5ET3p0QlFVY3hReXh0UWtGQlR5eFBRVUZRTEVkQlFXbENMRXRCUVdwQ0xFTkJTREJETzFOQlFXaERMRVZCUzFJc1JVRkJReXh0UWtGQmEwSXNSVUZCYkVJc1JVRk1UU3hEUVVGSUxFVkJTMjlDTEVsQlFVY3NRMEZCUXl4VlFVRlRMRTlCUVZRc1JVRkJhVUlzVFVGQmFrSXNSVUZCZDBJc1QwRkJlRUlzUlVGQlowTTdRVUZET1VRc1owSkJRVWtzVjBGQlZ5eFJRVUZSTEZkQlFWSXNRMEZCV0N4RFFVUXdSRHRCUVVVNVJDeG5Ra0ZCU1N4VFFVRlRMRkZCUVZFc2MwSkJRVklzUTBGQlZDeERRVVl3UkRzN1FVRkpPVVFzYlVKQlFVOHNUMEZCVUN4SFFVRnBRaXhsUVVGcVFpeERRVW80UkRzN1FVRk5PVVFzY1VKQlFWTXNaVUZCVkN4RFFVRjVRaXhKUVVGNlFpeEZRVUVyUWl4TFFVRXZRaXhGUVVGelF5eFJRVUYwUXl4RlFVRm5SRHRCUVVNMVF5eHhRa0ZCU3l4SlFVRkpMRkZCUVVvc1NVRkJaMElzUzBGQmNrSXNSVUZCTkVJN1FVRkRlRUlzZDBKQlFVa3NXVUZCV1N4TlFVRk5MRkZCUVU0c1EwRkJXaXhEUVVSdlFqczdRVUZIZUVJc2QwSkJRVWtzWTBGQll5eFRRVUZrTEVWQlFYbENPMEZCUTNwQ0xIVkRRVUZsTEVsQlFXWXNSVUZCY1VJc1VVRkJja0lzUlVGQkswSXNVMEZCTDBJc1JVRkJNRU1zVVVGQk1VTXNSVUZFZVVJN2NVSkJRVGRDTEUxQlJVOHNTVUZCU1N4UFFVRlBMRk5CUVZBc1EwRkJTaXhGUVVGMVFqdEJRVU14UWl4MVEwRkJaU3hKUVVGbUxFVkJRWEZDTEZGQlFYSkNMRVZCUVN0Q0xGTkJRUzlDTEVWQlFUQkRMRkZCUVRGRExFVkJSREJDTzBGQlJURkNMRFJDUVVGSkxGVkJRVlVzU1VGQlZpeEZRVUZuUWp0QlFVTm9RaXh6UTBGQlZTeEpRVUZXTEVOQlFXVXNTVUZCWml4RlFVTkpMRkZCUkVvc1JVRkZTU3hYUVVGWExGTkJRVk1zVVVGQlZDeERRVUZZTEVkQlFXZERMRk5CUVdoRExFTkJSa29zUTBGRVowSTdlVUpCUVhCQ08zRkNRVVpITEUxQlQwRTdRVUZEU0N3MFFrRkJTU3hUUVVGVExGTkJRVlFzUTBGQlNpeEZRVUY1UWp0QlFVTnlRaXgzUTBGQldTeEpRVUZhTEVWQlFXdENMRXRCUVd4Q0xFVkJRWGxDTEZGQlFYcENMRVZCUVcxRExGRkJRVzVETEVWQlFUWkRMRk5CUVRkRExFVkJSSEZDTzNsQ1FVRjZRaXhOUVVWUE8wRkJRMGdzYVVOQlFVc3NVVUZCVEN4SlFVRnBRaXhUUVVGcVFpeERRVVJITzNsQ1FVWlFPM0ZDUVZKSE8ybENRVXhZTzJGQlJFbzdPMEZCZFVKQkxIRkNRVUZUTEdOQlFWUXNRMEZCZDBJc1NVRkJlRUlzUlVGQk9FSXNVVUZCT1VJc1JVRkJkME1zVTBGQmVFTXNSVUZCYlVRc1VVRkJia1FzUlVGQk5rUTdRVUZEZWtRc2IwSkJRVWtzVVVGQlNpeEZRVUZqTzBGQlExWXNkMEpCUVVrc1owSkJRV2RDTEZOQlFWTXNVVUZCVkN4RFFVRm9RaXhEUVVSTk96dEJRVWRXTEhkQ1FVRkpMRU5CUVVNc1QwRkJUeXhoUVVGUUxFTkJRVVFzUlVGQmQwSTdRVUZEZUVJc05FSkJRVWtzWVVGQllTeFpRVUZpTEVWQlFUSkNPMEZCUXpOQ0xHbERRVUZMTEVsQlFVa3NVVUZCU2l4SlFVRm5RaXhoUVVGeVFpeEZRVUZ2UXp0QlFVTm9ReXh4UTBGQlN5eGxRVUZNTEVOQlFYRkNMRkZCUVhKQ0xFVkJSR2RET3paQ1FVRndRenQ1UWtGRVNpeE5RVWxQTEVsQlFVa3NZVUZCWVN4UFFVRmlMRVZCUVhOQ08wRkJRemRDTEdsRFFVRkxMRWxCUVVrc1EwRkJTaXhKUVVGVExHRkJRV1FzUlVGQk5rSTdRVUZEZWtJc2NVTkJRVXNzUzBGQlRDeERRVUZYTEVOQlFWZ3NTVUZCWjBJc1JVRkJhRUlzUTBGRWVVSTdOa0pCUVRkQ08zbENRVVJITEUxQlNVRXNTVUZCU1N4UFFVRlBMR0ZCUVZBc1MwRkJlVUlzVVVGQmVrSXNSVUZCYlVNN1FVRkRNVU1zYVVOQlFVc3NVVUZCVEN4SlFVRnBRaXhGUVVGcVFpeERRVVF3UXp0NVFrRkJka01zVFVGRlFUdEJRVU5JTEdsRFFVRkxMRkZCUVV3c1NVRkJhVUlzU1VGQmFrSXNRMEZFUnp0NVFrRkdRVHR4UWtGVVdDeE5RV05QTEVsQlFVa3NZMEZCWXl4TlFVRmtMRVZCUVhOQ08wRkJRemRDTEhORFFVRmpMRTFCUVdRc1EwRkJjVUlzU1VGQmNrSXNSVUZCTWtJc1VVRkJNMElzUlVGQmNVTXNVMEZCY2tNc1JVRkVOa0k3Y1VKQlFURkNPMmxDUVdwQ1dEdGhRVVJLT3p0QlFYZENRU3h4UWtGQlV5eFhRVUZVTEVOQlFYRkNMRWxCUVhKQ0xFVkJRVEpDTEV0QlFUTkNMRVZCUVd0RExGRkJRV3hETEVWQlFUUkRMRkZCUVRWRExFVkJRWE5FTEZOQlFYUkVMRVZCUVdsRk8wRkJRemRFTEc5Q1FVRkpMR2RDUVVGblFpeFhRVUZYTEZOQlFWTXNVVUZCVkN4RFFVRllMRWRCUVdkRExGTkJRV2hET3pzN1FVRkVlVU1zYjBKQlNYcEVMR0ZCUVdFc1dVRkJZaXhGUVVFeVFqdEJRVU16UWl4NVFrRkJTeXhKUVVGSkxGRkJRVW9zU1VGQlowSXNVMEZCY2tJc1JVRkJaME03UVVGRE5VSXNORUpCUVVrc1dVRkJXU3hWUVVGVkxGRkJRVllzUTBGQldpeERRVVIzUWpzN1FVRkhOVUlzTkVKQlFVa3NZMEZCWXl4VFFVRmtMRVZCUVhsQ08wRkJRM3BDTEdsRFFVRkxMR1ZCUVV3c1EwRkJjVUlzVVVGQmNrSXNSVUZFZVVJN2VVSkJRVGRDTEUxQlJVODdRVUZEU0N4cFEwRkJTeXhaUVVGTUxFTkJRV3RDTEZGQlFXeENMRVZCUVRSQ0xGTkJRVFZDTEVWQlJFYzdlVUpCUmxBN2NVSkJTRW83TzBGQlZVRXNNa0pCV0RKQ08ybENRVUV2UWpzN1FVRmpRU3h2UWtGQlJ5eHBRa0ZCYVVJc1UwRkJVeXhoUVVGVUxFTkJRV3BDTEVsQlEwTXNZVUZCWVN4aFFVRmlMRTFCUVdkRExHRkJRV0VzVTBGQllpeERRVUZvUXl4RlFVRjVSRHRCUVVONlJDeDVRa0ZCU3l4UlFVRk1MRWxCUVdsQ0xGTkJRV3BDTEVOQlJIbEVPMEZCUlhwRUxESkNRVVo1UkR0cFFrRkVOMFE3TzBGQlRVRXNiMEpCUVVrc1EwRkJReXhUUVVGVExFdEJRVXNzVVVGQlRDeERRVUZVTEVOQlFVUXNSVUZCTWtJN1FVRkRNMElzZVVKQlFVc3NVVUZCVEN4SlFVRnBRaXhGUVVGcVFpeERRVVF5UWp0cFFrRkJMMEk3TzBGQlNVRXNiMEpCUVVrc1YwRkJWeXhoUVVGaExFOUJRV0lzUjBGQmRVSXNSVUZCZGtJc1IwRkJORUlzVTBGQk5VSXNRMEUxUWpoRE96dEJRVGhDTjBRc2NVSkJRVXNzU1VGQlNTeERRVUZLTEVsQlFWTXNVMEZCWkN4RlFVRjVRanRCUVVOeVFpeDNRa0ZCU1N4UlFVRlJMRlZCUVZVc1EwRkJWaXhEUVVGU0xFTkJSR2xDTzBGQlJYSkNMSGxDUVVGTExGRkJRVXdzUlVGQlpTeERRVUZtTEVsQlFXOUNMRXRCUVVNc1MwRkJWU3hUUVVGV0xFZEJRWFZDTEZGQlFYaENMRWRCUVcxRExFdEJRVzVETEVOQlJrTTdhVUpCUVhwQ08yRkJPVUpLT3p0QlFXOURRU3h4UWtGQlV5eFpRVUZVTEVOQlFYTkNMRXRCUVhSQ0xFVkJRVFpDTzBGQlEzcENMRzlDUVVGSkxFOUJRVThzWTBGQlVDeEZRVUYxUWp0QlFVTjJRaXd5UWtGQlR5eFBRVUZQTEdOQlFWQXNRMEZCYzBJc1MwRkJkRUlzUTBGQlVDeERRVVIxUWp0cFFrRkJNMElzVFVGRlR5eEpRVUZKTEUxQlFVMHNVMEZCVGl4RlFVRnBRanRCUVVONFFpd3lRa0ZCVHl4TlFVRk5MRk5CUVU0c1EwRkVhVUk3YVVKQlFYSkNMRTFCUlVFc1NVRkJTU3hOUVVGTkxGZEJRVTRzUlVGQmJVSTdRVUZETVVJc01rSkJRVThzVFVGQlRTeFhRVUZPTEVOQlFXdENMRk5CUVd4Q0xFTkJSRzFDTzJsQ1FVRjJRanRoUVV4WU8xTkJla1k0UWl4RlFXMUhOVUlzUlVGQlF5eDNRa0ZCZFVJc1JVRkJka0lzUlVGQk1FSXNZVUZCV1N4RlFVRmFMRVZCYmtkQkxFTkJRVWdzUlVGdFIyOUNMRWxCUVVjc1EwRkJReXhWUVVGVExFOUJRVlFzUlVGQmFVSXNUVUZCYWtJc1JVRkJkMElzVDBGQmVFSXNSVUZCWjBNN1FVRkRiRVlzWjBKQlFVa3NWMEZCVnl4UlFVRlJMR2xDUVVGU0xFTkJRVmdzUTBGRU9FVTdPMEZCUjJ4R0xHZENRVUZKTEd0Q1FVRnJRaXhSUVVGUkxHOUNRVUZTTEVOQlFXeENMRU5CU0RoRk96dEJRVXRzUml4blFrRkJTU3hWUVVGVkxGRkJRVkVzYzBKQlFWSXNRMEZCVml4RFFVdzRSVHRCUVUxc1JpeG5Ra0ZCU1N4VlFVRlZMRkZCUVZFc2MwSkJRVklzUTBGQlZpeERRVTQ0UlR0QlFVOXNSaXhuUWtGQlNTeFhRVUZYTEZGQlFWRXNkVUpCUVZJc1EwRkJXQ3hEUVZBNFJUdEJRVkZzUml4blFrRkJTU3hqUVVGakxGRkJRVkVzTUVKQlFWSXNRMEZCWkN4RFFWSTRSVHM3UVVGVmJFWXNiVUpCUVU4c1QwRkJVQ3hIUVVGcFFpeGhRVUZxUWl4RFFWWnJSanM3UVVGWmJFWXNjVUpCUVZNc1lVRkJWQ3hEUVVGMVFpeExRVUYyUWl4RlFVRTRRaXhKUVVFNVFpeEZRVUZ2UXp0QlFVTm9ReXh2UWtGQlNTeE5RVUZOTEU5QlFVOHNTMEZCU3l4UlFVRk1MRWxCUVdsQ0xGRkJRV3BDTEVkQlFUUkNMRkZCUVc1RExFTkJSSE5DTzBGQlJXaERMRzlDUVVGSkxFOUJRVThzVDBGQlR5eExRVUZMTEVsQlFVd3NSMEZCV1N4SlFVRnVRaXhEUVVaeFFqczdRVUZKYUVNc2QwSkJRVkVzV1VGQldTeExRVUZhTEVWQlFXMUNMRU5CUVc1Q0xFTkJTbmRDT3p0QlFVMW9ReXh2UWtGQlNTeFRRVUZUTEV0QlFWUXNRMEZCU2l4RlFVRnhRanRCUVVOcVFpd3lRa0ZCVHl4TlFVRk5MRWxCUVU0c1JVRkJVQ3hEUVVScFFqdHBRa0ZCY2tJc1RVRkZUeXhKUVVGSkxGRkJRVkVzUzBGQlVpeERRVUZLTEVWQlFXOUNPMEZCUTNaQ0xESkNRVUZQTEVsQlFVa3NZMEZCU2l4RFFVRnRRaXhOUVVGTkxFbEJRVTRzUTBGQk1VSXNRMEZFZFVJN2FVSkJRWEJDTEUxQlJVRXNTVUZCU1N4RFFVRkRMRkZCUVZFc1MwRkJVaXhEUVVGRUxFVkJRV2xDTzBGQlEzaENMSGRDUVVGSkxFbEJRVW9zUlVGQlZUdEJRVU5PTERaQ1FVRkxMSE5EUVVGTUxFVkJRVFpETEV0QlFUZERMRVZCUkUwN2NVSkJRVlk3UVVGSFFTd3lRa0ZCVHl4SlFVRlFMRU5CU25kQ08ybENRVUZ5UWpzN1FVRlBVQ3h2UWtGQlNTeFBRVUZQTEV0QlFVTXNRMEZCVFN4VFFVRk9MRXRCUVc5Q0xFbEJRWEJDTEVkQlExSXNTVUZCU1N4aFFVRktMRU5CUVd0Q0xFMUJRVTBzVDBGQlRpeERRVVJZTEVkQlJWQXNTVUZCU1N4bFFVRktMRU5CUVc5Q0xFMUJRVTBzVTBGQlRpeEZRVUZwUWl4TlFVRk5MRTlCUVU0c1EwRkdPVUlzUTBGcVFuRkNPenRCUVhGQ2FFTXNiMEpCUVVrc1VVRkJVU3hOUVVGTkxGVkJRVTRzUTBGeVFtOUNPMEZCYzBKb1F5eG5RMEZCWjBJc1NVRkJhRUlzUlVGQmMwSXNTMEZCZEVJc1JVRjBRbWRET3p0QlFYZENhRU1zYjBKQlFVa3NWMEZCVnl4TlFVRk5MRkZCUVU0c1EwRjRRbWxDT3p0QlFUQkNhRU1zY1VKQlFVc3NTVUZCU1N4SlFVRkpMRU5CUVVvc1JVRkJUeXhKUVVGSkxGTkJRVk1zVFVGQlZDeEZRVUZwUWl4SFFVRnlReXhGUVVFd1F6dEJRVU4wUXl4M1FrRkJTU3haUVVGWkxHTkJRV01zVTBGQlV5eERRVUZVTEVOQlFXUXNSVUZCTWtJc1NVRkJNMElzUTBGQldpeERRVVJyUXp0QlFVVjBReXgzUWtGQlNTeFRRVUZLTEVWQlFXVTdRVUZEV0N3MlFrRkJTeXhYUVVGTUxFTkJRV2xDTEZOQlFXcENMRVZCUkZjN2NVSkJRV1k3YVVKQlJrbzdPMEZCVDBFc2RVSkJRVThzU1VGQlVDeERRV3BEWjBNN1lVRkJjRU03VTBGYWEwUXNSVUZuUkdoRUxFVkJRVU1zTkVKQlFUSkNMRVZCUVROQ0xFVkJRVGhDTEhkQ1FVRjFRaXhGUVVGMlFpeEZRVUV3UWl4M1FrRkJkVUlzUlVGQmRrSXNSVUZCTUVJc2VVSkJRWGRDTEVWQlFYaENMRVZCUVRKQ0xITkNRVUZ4UWl4RlFVRnlRaXhGUVVGM1FpeHRRa0ZCYTBJc1JVRkJiRUlzUlVGb1JIWkdMRU5CUVVnc1JVRm5SR2xJTEVsQlFVY3NRMEZCUXl4VlFVRlRMRTlCUVZRc1JVRkJhVUlzVFVGQmFrSXNSVUZCZDBJc1QwRkJlRUlzUlVGQlowTTdPenM3T3pzN1FVRlBiazBzWjBKQlFVa3NWVUZCVlN4RlFVRldMRU5CVUN0TU96dEJRVk51VFN4dFFrRkJUeXhQUVVGUUxFZEJRV2xDTEZGQlFXcENMRU5CVkcxTk96dEJRVmR1VFN4eFFrRkJVeXhSUVVGVUxFTkJRV3RDTEZGQlFXeENMRVZCUVRSQ0xFbEJRVFZDTEVWQlFXdERMRTlCUVd4RExFVkJRVEpETEV0QlFUTkRMRVZCUVd0RU8wRkJRemxETEc5Q1FVRkpMRU5CUVVNc1QwRkJSQ3hKUVVGWkxGRkJRVkVzVFVGQlVpeExRVUZ0UWl4RFFVRnVRaXhGUVVGelFqdEJRVU5zUXl3eVFrRkJUeXhGUVVGUUxFTkJSR3RETzJsQ1FVRjBReXhOUVVWUE8wRkJRMGdzTkVKQlFWRXNTVUZCVWl4RFFVRmhMRk5CUVdJc1JVRkVSenRCUVVWSUxESkNRVUZQTEZGQlFWRXNVVUZCVWl4RlFVRnJRaXhKUVVGc1FpeEZRVUYzUWl4UFFVRjRRaXhGUVVGcFF5eExRVUZxUXl4RlFVRjNReXhEUVVGNFF5eERRVUZRTEVOQlJrYzdhVUpCUmxBN1lVRkVTanM3UVVGVFFTeHhRa0ZCVXl4UFFVRlVMRU5CUVdsQ0xGRkJRV3BDTEVWQlFUSkNMRWxCUVROQ0xFVkJRV2xETEU5QlFXcERMRVZCUVRCRExFdEJRVEZETEVWQlFXbEVMRk5CUVdwRUxFVkJRVFJFTzBGQlEzaEVMSGRDUVVGUkxGTkJRVk1zUlVGQlZDeERRVVJuUkRzN1FVRkplRVFzYjBKQlFVa3NVVUZCU2l4RlFVRmpPMEZCUTFZc2QwSkJRVWtzWVVGQllTeFBRVUZpTEVWQlFYTkNMRk5CUVhSQ0xFVkJRV2xETEZOQlFXcERMRU5CUVVvc1JVRkJhVVE3UVVGRE4wTXNPRUpCUVUwc1UwRkJUaXhKUVVGdFFpeFJRVUZ1UWl4RFFVUTJRenR4UWtGQmFrUTdPMEZCU1VFc2QwSkJRVWtzV1VGQldTeExRVUZMTEZGQlFVd3NRMEZNVGpzN1FVRlBWaXgzUWtGQlNTeFRRVUZLTEVWQlFXVTdPMEZCUlZnc05FSkJRVWtzWVVGQllTeFRRVUZUTEZWQlFWUXNRMEZHVGpzN1FVRkpXQ3cyUWtGQlN5eEpRVUZKTEVsQlFVa3NRMEZCU2l4RlFVRlBMRWxCUVVrc1MwRkJTeXhSUVVGTUxFTkJRV01zVFVGQlpDeEZRVUZ6UWl4SFFVRXhReXhGUVVFclF6dEJRVU16UXl4NVEwRkJZU3hEUVVGaUxFTkJSREpET3p0QlFVY3pReXhuUTBGQlNTeFRRVUZUTEZWQlFWVXNRMEZCVml4TFFVRm5RaXhQUVVGb1FpeERRVWc0UWp0QlFVa3pReXhuUTBGQlNTeFpRVUZaTEdGQlFXRXNUMEZCVHl4TFFVRlFMRWxCUVdkQ0xFTkJRV2hDTEVOQlFXSTdPenRCUVVveVFpeG5RMEZQZGtNc1lVRkJZU3hQUVVGaUxFVkJRWE5DTEZOQlFYUkNMRVZCUVdsRExGTkJRV3BETEVOQlFVb3NSVUZCYVVRN1FVRkROME1zZDBOQlFWRXNWMEZCVnl4RFFVRllMRU5CUVZJc1JVRkJkVUlzVFVGQmRrSXNSVUZCSzBJc1QwRkJMMElzUlVGQmQwTXNTMEZCZUVNc1JVRkJLME1zVTBGQkwwTXNSVUZFTmtNN05rSkJRV3BFT3p0QlFVbEJMSGREUVVGWkxGTkJRVm9zUTBGWU1rTTdlVUpCUVM5RE8zRkNRVXBLTzJsQ1FWQktPenRCUVRKQ1FTeDFRa0ZCVHl4TFFVRlFMRU5CTDBKM1JEdGhRVUUxUkRzN08wRkJjRUp0VFN4eFFrRjFSREZNTEZsQlFWUXNRMEZCYzBJc1QwRkJkRUlzUlVGQkswSXNTVUZCTDBJc1JVRkJjVU1zUzBGQmNrTXNSVUZCTkVNN1FVRkRlRU1zYjBKQlFVa3NVVUZCVVN4TlFVRlNMRXRCUVcxQ0xFTkJRVzVDTEVWQlFYTkNPMEZCUTNSQ0xESkNRVUZQTEV0QlFWQXNRMEZFYzBJN2FVSkJRVEZDT3p0QlFVbEJMRzlDUVVGSkxGZEJRVmNzUTBGQldDeERRVXh2UXp0QlFVMTRReXh2UWtGQlNTeFhRVUZYTEZGQlFWRXNUVUZCVWl4SFFVRnBRaXhEUVVGcVFpeERRVTU1UWp0QlFVOTRReXh2UWtGQlNTeFpRVUZLTEVOQlVIZERPMEZCVVhoRExHOUNRVUZKTEZkQlFVb3NRMEZTZDBNN08wRkJWWGhETEhWQ1FVRlBMRmxCUVZrc1VVRkJXaXhGUVVGelFqdEJRVU42UWl4dFEwRkJaU3hEUVVGRkxGZEJRVmNzVVVGQldDeERRVUZFTEVkQlFYZENMRU5CUVhoQ0xFbEJRVGhDTEVOQlFTOUNMRU5CUkZVN1FVRkZla0lzYTBOQlFXTXNVVUZCVVN4WlFVRlNMRU5CUVdRc1EwRkdlVUk3TzBGQlNYcENMSGRDUVVGSkxHRkJRV0VzVVVGQllpeEZRVUYxUWp0QlFVTjJRaXdyUWtGQlR5eGxRVUZsTEVsQlFXWXNTVUZCZFVJc1pVRkJaU3hMUVVGbUxFTkJSRkE3Y1VKQlFUTkNMRTFCUlU4c1NVRkJTU3hqUVVGakxFbEJRV1FzUlVGQmIwSTdRVUZETTBJc2JVTkJRVmNzWlVGQlpTeERRVUZtTEVOQlJHZENPM0ZDUVVGNFFpeE5RVVZETEVsQlFVa3NZMEZCWXl4TFFVRmtMRVZCUVhGQ08wRkJRemRDTEcxRFFVRlhMR1ZCUVdVc1EwRkJaaXhEUVVSclFqdHhRa0ZCZWtJc1RVRkZSRHRCUVVOSUxDdENRVUZQTEVsQlFWQXNRMEZFUnp0eFFrRkdRenRwUWtGU1dqczdRVUZsUVN4MVFrRkJUeXhMUVVGUUxFTkJla0ozUXp0aFFVRTFRenM3UVVFMFFrRXNjVUpCUVZNc1UwRkJWQ3hEUVVGdFFpeERRVUZ1UWl4RlFVRnpRaXhEUVVGMFFpeEZRVUY1UWp0QlFVTnlRaXgxUWtGQlR5eEpRVUZKTEVOQlFVb3NSMEZCVVN4RFFVRlNMRWRCUVZrc1EwRkJReXhEUVVGRUxFTkJSRVU3WVVGQmVrSTdVMEZ1Um0xTExFVkJkVVpxU3l4RlFYWkdaMHNzUTBGQlNDeEZRWFZHZWtvc1NVRkJSeXhEUVVGRExGVkJRVk1zVDBGQlZDeEZRVUZwUWl4TlFVRnFRaXhGUVVGM1FpeFBRVUY0UWl4RlFVRm5RenRCUVVNeFF5eG5Ra0ZCU1N4clFrRkJhMElzVVVGQlVTeHZRa0ZCVWl4RFFVRnNRaXhEUVVSelF6czdRVUZITVVNc1owSkJRVWtzVjBGQlZ5eFJRVUZSTEhWQ1FVRlNMRU5CUVZnc1EwRkljME03UVVGSk1VTXNaMEpCUVVrc1UwRkJVeXhSUVVGUkxHOUNRVUZTTEVOQlFWUXNRMEZLYzBNN08wRkJUVEZETEdkQ1FVRkpMR1ZCUVdVc1VVRkJVU3hwUWtGQlVpeERRVUZtTEVOQlRuTkRPenRCUVZFeFF5eHRRa0ZCVHl4UFFVRlFMRWRCUVdsQ0xGVkJRV3BDTEVOQlVqQkRPenRCUVZVeFF5eHhRa0ZCVXl4VlFVRlVMRU5CUVc5Q0xFMUJRWEJDTEVWQlFUUkNMRTlCUVRWQ0xFVkJRWEZETEdGQlFYSkRMRVZCUVc5RU8wRkJRMmhFTEc5Q1FVRkpMRTlCUVU4c1QwRkJUeXhKUVVGUUxFTkJSSEZETzBGQlJXaEVMRzlDUVVGSkxGRkJRVkVzVDBGQlR5eExRVUZRTEVOQlJtOURPMEZCUjJoRUxHOUNRVUZKTEZGQlFWRXNUMEZCVHl4TFFVRlFMRU5CU0c5RE96dEJRVXRvUkN4M1FrRkJVU3hKUVVGU08wRkJRMGtzZVVKQlFVc3NUMEZCVHl4TlFVRlFPMEZCUTBRc0swSkJRVThzVjBGQlZ5eFBRVUZZTEVWQlFXOUNMRXRCUVhCQ0xFTkJRVkFzUTBGRVNqdEJRVVJLTEhsQ1FVZFRMRTlCUVU4c1RVRkJVRHRCUVVORUxDdENRVUZQTEZkQlFWY3NUMEZCV0N4RlFVRnZRaXhMUVVGd1FpeEZRVUV5UWl4aFFVRXpRaXhEUVVGUUxFTkJSRW83UVVGSVNpeDVRa0ZMVXl4UFFVRlBMRXRCUVZBN1FVRkRSQ3dyUWtGQlR5eFpRVUZaTEU5QlFWb3NSVUZCY1VJc1MwRkJja0lzUlVGQk5FSXNTMEZCTlVJc1JVRkJiVU1zWVVGQmJrTXNRMEZCVUN4RFFVUktPMEZCVEVvc2VVSkJUMU1zVDBGQlR5eE5RVUZRTzBGQlEwUXNLMEpCUVU4c1dVRkJXU3hQUVVGYUxFVkJRWEZDTEV0QlFYSkNMRVZCUVRSQ0xFdEJRVFZDTEVWQlFXMURMR0ZCUVc1RExFTkJRVkFzUTBGRVNqdEJRVkJLTEhsQ1FWTlRMRTlCUVU4c1MwRkJVRHRCUVVORUxDdENRVUZQTEZkQlFWY3NUMEZCV0N4RlFVRnZRaXhMUVVGd1FpeEZRVUV5UWl4TFFVRXpRaXhGUVVGclF5eGhRVUZzUXl4RFFVRlFMRU5CUkVvN1FVRlVTaXg1UWtGWFV5eFBRVUZQTEV0QlFWQTdRVUZEUkN4M1EwRkJaMElzVDBGQmFFSXNSVUZCZVVJc1MwRkJla0lzUlVGRVNqdEJRVVZKTEN0Q1FVRlBMRTlCUVZBc1EwRkdTanRCUVZoS0xIbENRV05UTEU5QlFVOHNTMEZCVUR0QlFVTkVMSGREUVVGblFpeFBRVUZvUWl4RlFVRjVRaXhMUVVGNlFpeEZRVUZuUXl4TlFVRk5MRlZCUVU0c1EwRkJhRU1zUTBGRVNqdEJRVVZKTEN0Q1FVRlBMRTlCUVZBc1EwRkdTanRCUVdSS0xIbENRV2xDVXl4UFFVRlBMRXRCUVZBN1FVRkRSQ3dyUWtGQlR5eFpRVUZaTEU5QlFWb3NSVUZEU0N4alFVRmpMRXRCUVdRc1EwRkJiMElzVDBGQmNFSXNSVUZCTmtJc1MwRkJOMElzUlVGQmIwTXNZVUZCY0VNc1EwRkVSeXhEUVVGUUxFTkJSRW83UVVGcVFrbzdRVUZ4UWxFc0swSkJRVThzVDBGQlVDeERRVVJLTzBGQmNFSktMR2xDUVV4blJEdGhRVUZ3UkRzN1FVRTRRa0VzY1VKQlFWTXNWVUZCVkN4RFFVRnZRaXhQUVVGd1FpeEZRVUUyUWl4TFFVRTNRaXhGUVVGdlF6dEJRVU5vUXl4dlFrRkJTU3hoUVVGaExGRkJRVkVzVlVGQlVpeERRVVJsT3p0QlFVZG9ReXh2UWtGQlNTeFZRVUZLTEVWQlFXZENPMEZCUTFvc0swSkJRVmNzVjBGQldDeERRVUYxUWl4UFFVRjJRaXhGUVVSWk8ybENRVUZvUWpzN1FVRkpRU3c0UWtGQll5eFBRVUZrTEVWQlFYVkNMRXRCUVhaQ0xFVkJVR2RET3p0QlFWTm9ReXgxUWtGQlR5eEpRVUZRTEVOQlZHZERPMkZCUVhCRE96dEJRVmxCTEhGQ1FVRlRMRlZCUVZRc1EwRkJiMElzVlVGQmNFSXNSVUZCWjBNc1MwRkJhRU1zUlVGQmRVTXNZVUZCZGtNc1JVRkJjMFE3UVVGRGJFUXNiMEpCUVVrc1ZVRkJWU3hqUVVGakxFMUJRV1FzUTBGQmNVSXNTMEZCY2tJc1JVRkJORUlzWVVGQk5VSXNRMEZCVml4RFFVUTRRenM3UVVGSGJFUXNiMEpCUVVrc1ZVRkJTaXhGUVVGblFqdEJRVU5hTEN0Q1FVRlhMRmRCUVZnc1EwRkJkVUlzVDBGQmRrSXNSVUZFV1R0cFFrRkJhRUk3TzBGQlNVRXNkVUpCUVU4c1ZVRkJVQ3hEUVZCclJEdGhRVUYwUkRzN1FVRlZRU3h4UWtGQlV5eFhRVUZVTEVOQlFYRkNMRTlCUVhKQ0xFVkJRVGhDTEZOQlFUbENMRVZCUVhsRExFdEJRWHBETEVWQlFXZEVMR0ZCUVdoRUxFVkJRU3RFTzBGQlF6TkVMRzlDUVVGSkxFOUJRVW9zUTBGRU1rUTdPMEZCUnpORUxHOUNRVUZKTEZGQlFWRXNVVUZCVWl4TFFVRnhRaXhEUVVGeVFpeEZRVUYzUWp0QlFVTjRRaXcwUWtGQlVTeFhRVUZTTEVOQlFXOUNMRU5CUVhCQ0xFVkJRWFZDTEZGQlFWRXNUVUZCVWl4RlFVRm5RaXhOUVVGTkxFbEJRVTRzUTBGQmRrTXNRMEZFZDBJN1FVRkZlRUlzT0VKQlFWVXNUMEZCVml4RFFVWjNRanRwUWtGQk5VSXNUVUZIVHp0QlFVTklMSGRDUVVGSkxHRkJRV0VzVVVGQlVTeFZRVUZTTEVOQlJHUTdRVUZGU0N3NFFrRkJWU3hqUVVGakxFMUJRV1FzUTBGQmNVSXNTMEZCY2tJc1JVRkJORUlzWVVGQk5VSXNRMEZCVml4RFFVWkhPenRCUVVsSUxIZENRVUZKTEdOQlFXTXNXVUZCV1N4UFFVRmFMRVZCUVhGQ08wRkJRMjVETEcxRFFVRlhMRmxCUVZnc1EwRkJkMElzVDBGQmVFSXNSVUZCYVVNc1QwRkJha01zUlVGRWJVTTdjVUpCUVhaRE8ybENRVkJLT3p0QlFWbEJMSFZDUVVGUExFOUJRVkFzUTBGbU1rUTdZVUZCTDBRN08wRkJhMEpCTEhGQ1FVRlRMRmRCUVZRc1EwRkJjVUlzVDBGQmNrSXNSVUZCT0VJc1UwRkJPVUlzUlVGQmVVTXNUVUZCZWtNc1JVRkJhVVFzWVVGQmFrUXNSVUZCWjBVN1FVRkROVVFzYjBKQlFVa3NWMEZCVnl4aFFVRmhMRk5CUVdJc1JVRkJkMElzVFVGQmVFSXNRMEZCV0N4RFFVUjNSRHRCUVVVMVJDeHZRa0ZCU1N4UFFVRktMRU5CUmpSRU96dEJRVWsxUkN4dlFrRkJTU3hSUVVGS0xFVkJRV003UVVGRFZpdzRRa0ZCVlN4UFFVRlBMRTFCUVZBc1EwRkJZeXhUUVVGa0xFVkJRWGxDTEU5QlFYcENMRXRCUVhGRExFOUJRWEpETEVOQlJFRTdhVUpCUVdRc1RVRkZUenRCUVVOSUxEaENRVUZWTEdOQlFXTXNUVUZCWkN4RFFVRnhRaXhOUVVGeVFpeEZRVUUyUWl4aFFVRTNRaXhEUVVGV0xFTkJSRWM3YVVKQlJsQTdPMEZCVFVFc2IwSkJRVWtzWVVGQllTeFJRVUZSTEZWQlFWSXNRMEZXTWtNN08wRkJXVFZFTEc5Q1FVRkpMR05CUVdNc1dVRkJXU3hQUVVGYUxFVkJRWEZDTzBGQlEyNURMQ3RDUVVGWExGbEJRVmdzUTBGQmQwSXNUMEZCZUVJc1JVRkJhVU1zVDBGQmFrTXNSVUZFYlVNN2FVSkJRWFpET3p0QlFVbEJMRzlDUVVGSkxFTkJRVU1zVVVGQlJDeEZRVUZYTzBGQlExZ3NhME5CUVdNc1QwRkJaQ3hGUVVGMVFpeFRRVUYyUWl4RlFVUlhPMmxDUVVGbU96dEJRVWxCTEhWQ1FVRlBMRTlCUVZBc1EwRndRalJFTzJGQlFXaEZPenRCUVhWQ1FTeHhRa0ZCVXl4VlFVRlVMRU5CUVc5Q0xFOUJRWEJDTEVWQlFUWkNMRk5CUVRkQ0xFVkJRWGRETEV0QlFYaERMRVZCUVN0RExHRkJRUzlETEVWQlFUaEVPMEZCUXpGRUxHOUNRVUZKTEdGQlFXRXNVVUZCVVN4VlFVRlNMRU5CUkhsRE8wRkJSVEZFTEc5Q1FVRkpMRlZCUVZVc1kwRkJZeXhOUVVGa0xFTkJRWEZDTEV0QlFYSkNMRVZCUVRSQ0xHRkJRVFZDTEVOQlFWWXNRMEZHYzBRN08wRkJTVEZFTEc5Q1FVRkpMR05CUVdNc1dVRkJXU3hQUVVGYUxFVkJRWEZDTzBGQlEyNURMQ3RDUVVGWExGbEJRVmdzUTBGQmQwSXNUMEZCZUVJc1JVRkJhVU1zVDBGQmFrTXNSVUZFYlVNN2FVSkJRWFpET3p0QlFVbEJMSFZDUVVGUExFOUJRVkFzUTBGU01FUTdZVUZCT1VRN08wRkJWMEVzY1VKQlFWTXNZVUZCVkN4RFFVRjFRaXhQUVVGMlFpeEZRVUZuUXl4RFFVRm9ReXhGUVVGdFF6dEJRVU12UWl4dlFrRkJTU3hQUVVGUExFVkJRVVVzVDBGQlJpeExRVUZqTEZWQlFYSkNMRWxCUVcxRExGTkJRVk1zUTBGQlZDeERRVUZ1UXl4RlFVRm5SRHRCUVVOb1JDeHpRa0ZCUlN4UFFVRkdMRU5CUVZVc1QwRkJWaXhGUVVSblJEdHBRa0ZCY0VRN1lVRkVTanM3UVVGTlFTeHhRa0ZCVXl4bFFVRlVMRU5CUVhsQ0xFOUJRWHBDTEVWQlFXdERMRXRCUVd4RExFVkJRWGxETzBGQlEzSkRMRzlDUVVGSkxHRkJRV0VzVVVGQlVTeFZRVUZTTEVOQlJHOUNPMEZCUlhKRExHOUNRVUZKTEZOQlFWTXNSVUZCVkN4RFFVWnBRenRCUVVkeVF5eHZRa0ZCU1N4SlFVRktMRU5CU0hGRE8wRkJTWEpETEc5Q1FVRkpMRTFCUVVvc1EwRktjVU03UVVGTGNrTXNiMEpCUVVrc1RVRkJTaXhEUVV4eFF6czdRVUZQY2tNc2NVSkJRVXNzU1VGQlNTeEpRVUZKTEVOQlFVb3NSVUZCVHl4SlFVRkpMRTFCUVUwc1QwRkJUaXhEUVVGakxFMUJRV1FzUlVGQmMwSXNSMEZCTVVNc1JVRkJLME03UVVGRE0wTXNOa0pCUVZNc1RVRkJUU3hQUVVGT0xFTkJRV01zUTBGQlpDeERRVUZVTEVOQlJESkRPMEZCUlRORExESkNRVUZQTEZkQlFWY3NUMEZCVHl4SlFVRlFMRU5CUVd4Q0xFTkJSakpETzBGQlJ6TkRMSGRDUVVGSkxFOUJRVThzUjBGQlVDeEZRVUZaTzBGQlExb3NLMEpCUVU4c1QwRkJUeXhIUVVGUUxFTkJRVkFzUjBGQmNVSXNTVUZCY2tJc1EwRkVXVHR4UWtGQmFFSTdRVUZIUVN3MFFrRkJVU3hYUVVGU0xFTkJRVzlDTEVsQlFYQkNMRVZCVGpKRE8ybENRVUV2UXpzN1FVRlRRU3h2UWtGQlNTeFRRVUZUTEZkQlFWY3NUVUZCV0N4RFFXaENkMEk3UVVGcFFuSkRMSEZDUVVGTExFbEJRVWtzU1VGQlNTeERRVUZLTEVWQlFVOHNTVUZCU1N4TlFVRk5MRTlCUVU0c1EwRkJZeXhOUVVGa0xFVkJRWE5DTEVkQlFURkRMRVZCUVN0RE8wRkJRek5ETERaQ1FVRlRMRTFCUVUwc1QwRkJUaXhEUVVGakxFTkJRV1FzUTBGQlZDeERRVVF5UXp0QlFVVXpReXd5UWtGQlR5eFBRVUZQTEU5QlFVOHNSMEZCVUN4RFFVRmtPenRCUVVZeVF5d3lRa0ZKTTBNc1EwRkJVU3haUVVGU0xFTkJRWEZDTEVsQlFYSkNMRVZCUVRKQ0xFOUJRVThzUlVGQlVDeEpRVUZoTEZGQlFXSXNSMEZCZDBJc1NVRkJlRUlzUjBGQkswSXNWMEZCVnl4UFFVRlBMRVZCUVZBc1EwRkJNVU1zUTBGQk0wSXNRMEZLTWtNN2FVSkJRUzlETzJGQmFrSktPenRCUVhsQ1FTeHhRa0ZCVXl4WFFVRlVMRU5CUVhGQ0xFOUJRWEpDTEVWQlFUaENMRTlCUVRsQ0xFVkJRWFZETzBGQlEyNURMRzlDUVVGSkxGZEJRVmNzVDBGQldDeEpRVUZ6UWl4WlFVRlpMRTlCUVZvc1NVRkJkVUlzVVVGQlVTeFZRVUZTTEVWQlFXOUNPMEZCUTJwRkxEUkNRVUZSTEZWQlFWSXNRMEZCYlVJc1dVRkJia0lzUTBGQlowTXNUMEZCYUVNc1JVRkJlVU1zVDBGQmVrTXNSVUZFYVVVN2FVSkJRWEpGT3p0QlFVbEJMSFZDUVVGUExFOUJRVkFzUTBGTWJVTTdZVUZCZGtNN1UwRnFTbFVzUlVGNVNsSXNSVUZCUXl4NVFrRkJkMElzUlVGQmVFSXNSVUZCTWtJc2MwSkJRWEZDTEVWQlFYSkNMRVZCUVhkQ0xITkNRVUZ4UWl4RlFVRnlRaXhGUVVGM1FpeHRRa0ZCYTBJc1JVRkJiRUlzUlVGNlNuSkZMRU5CUVVnc1JVRjVTaXRHTEVsQlFVY3NRMEZCUXl4VlFVRlRMRTlCUVZRc1JVRkJhVUlzVFVGQmFrSXNSVUZCZDBJc1QwRkJlRUlzUlVGQlowTTdRVUZEZWtrc1owSkJRVWtzVjBGQlZ5eFJRVUZSTEdsQ1FVRlNMRU5CUVZnc1EwRkVjVWs3UVVGRmVra3NaMEpCUVVrc1ZVRkJWU3hSUVVGUkxGbEJRVklzUTBGQlZpeERRVVp4U1RzN1FVRkpla2tzWjBKQlFVa3NVMEZCVXl4UlFVRlJMR3RDUVVGU0xFTkJRVlFzUTBGS2NVazdRVUZMZWtrc1owSkJRVWtzVjBGQlZ5eFJRVUZSTEdGQlFWSXNRMEZCV0N4RFFVeHhTVHRCUVUxNlNTeG5Ra0ZCU1N4VlFVRlZMRkZCUVZFc1dVRkJVaXhEUVVGV0xFTkJUbkZKTzBGQlQzcEpMRzFDUVVGUExFOUJRVkFzUjBGQmFVSXNTMEZCYWtJc1EwRlFlVWs3TzBGQlUzcEpMSEZDUVVGVExFdEJRVlFzUTBGQlpTeFJRVUZtTEVWQlFYbENMRTlCUVhwQ0xFVkJRV3RETEdGQlFXeERMRVZCUVdsRU8wRkJRemRETEdkRFFVRm5RaXhwUWtGQmFVSXNSVUZCYWtJc1EwRkVOa0k3UVVGRk4wTXNPRUpCUVdNc1MwRkJaQ3hIUVVGelFpeGpRVUZqTEV0QlFXUXNTVUZCZFVJc1kwRkJZeXhMUVVGa0xFdEJRWGRDTEV0QlFYaENMRWRCUTNaRExHTkJRV01zUzBGQlpDeEhRVU5CTEdOQlJtZENMRU5CUm5WQ08wRkJTemRETERoQ1FVRmpMRTFCUVdRc1IwRkJkVUlzWTBGQll5eE5RVUZrTEVsQlFYZENMRTFCUVhoQ0xFTkJUSE5DT3p0QlFVODNReXgxUWtGQlR5eGpRVUZqTEV0QlFXUXNRMEZCYjBJc1VVRkJjRUlzUlVGQk9FSXNUMEZCT1VJc1JVRkJkVU1zWVVGQmRrTXNRMEZCVUN4RFFWQTJRenRoUVVGcVJEczdRVUZWUVN4eFFrRkJVeXhqUVVGVUxFTkJRWGRDTEZGQlFYaENMRVZCUVd0RExFOUJRV3hETEVWQlFUSkRMR0ZCUVRORExFVkJRVEJFTzBGQlEzUkVMRzlDUVVGSkxGVkJRVlVzWVVGQllTeFBRVUZpTEVOQlFWWXNRMEZFYTBRN08wRkJSM1JFTEc5Q1FVRkpMRkZCUVZFc1RVRkJVaXhMUVVGdFFpeERRVUZ1UWl4RlFVRnpRanRCUVVOMFFpd3lRa0ZCVHl4UlFVRlFMRU5CUkhOQ08ybENRVUV4UWpzN1FVRkpRU3h2UWtGQlNTeFJRVUZSTEZOQlFWTXNVVUZCVkN4RlFVRnRRaXhSUVVGUkxFTkJRVklzUlVGQlZ5eFBRVUU1UWl4RFFVRlNMRU5CVUd0RU8wRkJVWFJFTEc5Q1FVRkpMR2RDUVVGblFpeFRRVUZUTEdGQlFWUXNRMEZTYTBNN08wRkJWWFJFTEc5Q1FVRkpMRU5CUVVNc1kwRkJZeXhSUVVGa0xFbEJRVEJDTEd0Q1FVRnJRaXhSUVVGc1FpeEZRVUUwUWp0QlFVTjJSQ3hyUTBGQll5eFJRVUZrTEVkQlFYbENMR0ZCUVhwQ0xFTkJSSFZFTzJsQ1FVRXpSRHM3UVVGSlFTeHhRa0ZCU3l4SlFVRkpMRWxCUVVrc1EwRkJTaXhGUVVGUExFbEJRVWtzVVVGQlVTeE5RVUZTTEVWQlFXZENMRWRCUVhCRExFVkJRWGxETzBGQlEzSkRMSGRDUVVGSkxGbEJRVmtzVVVGQlVTeERRVUZTTEVOQlFWb3NRMEZFYVVNN1FVRkZja01zSzBKQlFWY3NWMEZCVnl4UlFVRllMRVZCUTFBc1RVRkJUU3hUUVVGT0xFTkJSRThzUlVGRlVDeFJRVUZSTEZOQlFWSXNRMEZHVHl4RlFVZFFMR0ZCU0U4c1EwRkJXQ3hEUVVaeFF6dHBRa0ZCZWtNN08wRkJVVUVzZFVKQlFVOHNVVUZCVUN4RFFYUkNjMFE3WVVGQk1VUTdPMEZCZVVKQkxIRkNRVUZUTEZWQlFWUXNRMEZCYjBJc1VVRkJjRUlzUlVGQk9FSXNUMEZCT1VJc1JVRkJkVU1zVTBGQmRrTXNSVUZCYTBRc1lVRkJiRVFzUlVGQmFVVTdRVUZETjBRc2IwSkJRVWtzUTBGQlF5eFBRVUZFTEVWQlFWVTdRVUZEVml3eVFrRkJUeXhSUVVGUUxFTkJSRlU3YVVKQlFXUTdPMEZCU1VFc2IwSkJRVWtzVDBGQlNpeERRVXcyUkRzN1FVRlBOMFFzYjBKQlFVa3NVVUZCVVN4VFFVRlNMRU5CUVVvc1JVRkJkMEk3UVVGRGNFSXNlVUpCUVVzc1NVRkJTU3hKUVVGSkxFTkJRVW9zUlVGQlR5eEpRVUZKTEZWQlFWVXNUVUZCVml4RlFVRnJRaXhIUVVGMFF5eEZRVUV5UXp0QlFVTjJReXhyUTBGQlZTeFJRVUZSTEZWQlFWVXNRMEZCVml4RFFVRlNMRVZCUVhOQ0xFOUJRWFJDTEVWQlFTdENMR0ZCUVM5Q0xFTkJRVllzUTBGRWRVTTdPMEZCUjNaRExEUkNRVUZKTEZsQlFWa3NVVUZCV2l4RlFVRnpRanRCUVVOMFFpeDFRMEZCVnl4UFFVRllMRU5CUkhOQ08zbENRVUV4UWp0eFFrRklTanRwUWtGRVNpeE5RVkZQTzBGQlEwZ3NPRUpCUVZVc1VVRkJVU3hUUVVGU0xFVkJRVzFDTEU5QlFXNUNMRVZCUVRSQ0xHRkJRVFZDTEVOQlFWWXNRMEZFUnpzN1FVRkhTQ3gzUWtGQlNTeFpRVUZaTEZGQlFWb3NSVUZCYzBJN1FVRkRkRUlzYlVOQlFWY3NUMEZCV0N4RFFVUnpRanR4UWtGQk1VSTdhVUpCV0VvN08wRkJaMEpCTEhWQ1FVRlBMRkZCUVZBc1EwRjJRalpFTzJGQlFXcEZPenRCUVRCQ1FTeHhRa0ZCVXl4WlFVRlVMRU5CUVhOQ0xFOUJRWFJDTEVWQlFTdENPMEZCUXpOQ0xHOUNRVUZKTEZWQlFWVXNSVUZCVml4RFFVUjFRanM3UVVGSE0wSXNjVUpCUVVzc1NVRkJTU3hIUVVGS0xFbEJRVmNzVDBGQmFFSXNSVUZCZVVJN1FVRkRja0lzZDBKQlFVa3NVVUZCVVN4SFFVRlNMRVZCUVdFN1FVRkRZaXhuUTBGQlVTeEpRVUZTTEVOQlFXRXNUMEZCVHl4SFFVRlFMRU5CUVdJc1JVRkVZVHR4UWtGQmFrSTdhVUpCUkVvN08wRkJUVUVzZFVKQlFVOHNUMEZCVUN4RFFWUXlRanRoUVVFdlFqdFRRWFJGZVVjc1JVRnJSblpITEVWQlFVTXNiMEpCUVcxQ0xFVkJRVzVDTEVWQlFYTkNMR1ZCUVdNc1JVRkJaQ3hGUVVGcFFpeGpRVUZoTEVWQlFXSXNSVUZCWjBJc2JVSkJRV3RDTEVWQlFXeENMRVZCUVhGQ0xHTkJRV0VzUlVGQllpeEZRV3hHZVVJc1EwRkJTQ3hGUVd0R1NpeEpRVUZITEVOQlFVTXNWVUZCVXl4UFFVRlVMRVZCUVdsQ0xFMUJRV3BDTEVWQlFYZENMRTlCUVhoQ0xFVkJRV2RETzBGQlEzSkpMR2RDUVVGSkxGZEJRVmNzVVVGQlVTeDFRa0ZCVWl4RFFVRllMRU5CUkdsSk96dEJRVWR5U1N4dFFrRkJUeXhQUVVGUUxFZEJRV2xDTEZsQlFXcENMRU5CU0hGSk96dEJRVXR5U1N4eFFrRkJVeXhaUVVGVUxFTkJRWE5DTEVOQlFYUkNMRVZCUVhsQ0xFTkJRWHBDTEVWQlFUUkNPMEZCUTNoQ0xHOUNRVUZKTEZOQlFWTXNRMEZCVkN4TFFVRmxMRk5CUVZNc1EwRkJWQ3hEUVVGbUxFVkJRVFJDTzBGQlF6VkNMSGRDUVVGSkxGVkJRVlVzUTBGQlZpeEpRVUZsTEZWQlFWVXNRMEZCVml4RlFVRmhPMEZCUXpWQ0xDdENRVUZQTEVWQlFVVXNSVUZCUml4TFFVRlRMRVZCUVVVc1JVRkJSaXhEUVVSWk8zRkNRVUZvUXl4TlFVVlBPMEZCUTBnc0swSkJRVThzUlVGQlJTeEpRVUZHTEV0QlFWY3NSVUZCUlN4SlFVRkdMRU5CUkdZN2NVSkJSbEE3YVVKQlJFbzdPMEZCVVVFc2RVSkJRVThzUzBGQlVDeERRVlIzUWp0aFFVRTFRanRUUVV4eFJ5eEZRV2xDYmtjc1JVRkJReXg1UWtGQmQwSXNSVUZCZUVJc1JVRnFRbWxITEVOQlFVZ3NSVUZwUW1wRkxFbEJRVWNzUTBGQlF5eFZRVUZUTEU5QlFWUXNSVUZCYVVJc1RVRkJha0lzUlVGQmQwSXNUMEZCZUVJc1JVRkJaME03UVVGRGNFVXNlVUpCUkc5Rk96dEJRVWR3UlN4blFrRkJTU3hWUVVGVkxGRkJRVkVzVlVGQlVpeERRVUZXTEVOQlNHZEZPenRCUVV0d1JTeHRRa0ZCVHl4UFFVRlFMRWRCUVdsQ0xFMUJRV3BDTEVOQlRHOUZPenRCUVU5d1JTeHhRa0ZCVXl4TlFVRlVMRU5CUVdkQ0xFdEJRV2hDTEVWQlFYVkNPMEZCUTI1Q0xHOUNRVUZKTEVWQlFVVXNaMEpCUVdkQ0xFMUJRV2hDTEVOQlFVWXNSVUZCTWtJN1FVRkRNMElzTWtKQlFVOHNTVUZCU1N4TlFVRktMRU5CUVZjc1MwRkJXQ3hEUVVGUUxFTkJSREpDTzJsQ1FVRXZRanM3UVVGSlFTeHhRa0ZCU3l4TFFVRk1MRWRCUVdFc1MwRkJZaXhEUVV4dFFqdGhRVUYyUWpzN1FVRlJRU3h0UWtGQlR5eFRRVUZRTEVOQlFXbENMRWxCUVdwQ0xFZEJRWGRDTEZWQlFWVXNTVUZCVml4RlFVRm5RaXhaUVVGb1FpeEZRVUU0UWp0QlFVTnNSQ3h2UWtGQlNTeExRVUZMTEZGQlFWRXNTVUZCVWl4RFFVRk1MRU5CUkRoRE8wRkJSV3hFTEc5Q1FVRkpMRmRCUVZjc1lVRkJZU3hOUVVGaUxFTkJRVzlDTEVOQlFYQkNMRU5CUVZnc1EwRkdPRU03TzBGQlNXeEVMRzFDUVVGSExGRkJRVWdzU1VGQlpTeExRVUZMTEV0QlFVd3NRMEZLYlVNN1lVRkJPVUlzUTBGbU5FTTdPMEZCYzBKd1JTeHRRa0ZCVHl4VFFVRlFMRU5CUVdsQ0xFMUJRV3BDTEVkQlFUQkNMRlZCUVZNc1NVRkJWQ3hGUVVGbExGbEJRV1lzUlVGQk5rSTdRVUZEYmtRc2IwSkJRVWtzUzBGQlN5eFJRVUZSTEVsQlFWSXNRMEZCVEN4RFFVUXJRenRCUVVWdVJDeHZRa0ZCU1N4WFFVRlhMR0ZCUVdFc1RVRkJZaXhEUVVGdlFpeERRVUZ3UWl4RFFVRllMRU5CUml0RE96dEJRVWx1UkN4dFFrRkJSeXhSUVVGSUxFbEJRV1VzVTBGQlppeERRVXB0UkR0aFFVRTNRaXhEUVhSQ01FTTdVMEZCYUVNc1JVRTJRbXhETEVWQlFVTXNXVUZCVnl4RFFVRllMRVZCTjBKblF5eERRVUZJTEVWQk5rSmtMRWxCUVVjc1EwRkJReXhWUVVGVExFOUJRVlFzUlVGQmFVSXNUVUZCYWtJc1JVRkJkMElzVDBGQmVFSXNSVUZCWjBNN1FVRkRkRVFzZVVKQlJITkVPenRCUVVkMFJDeHRRa0ZCVHl4UFFVRlFMRWRCUVdsQ0xGZEJRV3BDTEVOQlNITkVPenRCUVV0MFJDeHhRa0ZCVXl4WFFVRlVMRU5CUVhGQ0xFdEJRWEpDTEVWQlFUUkNPMEZCUTNoQ0xHOUNRVUZKTEVWQlFVVXNaMEpCUVdkQ0xGZEJRV2hDTEVOQlFVWXNSVUZCWjBNN1FVRkRhRU1zTWtKQlFVOHNTVUZCU1N4WFFVRktMRU5CUVdkQ0xFdEJRV2hDTEVOQlFWQXNRMEZFWjBNN2FVSkJRWEJET3p0QlFVbEJMSEZDUVVGTExFdEJRVXdzUjBGQllTeExRVUZpTEVOQlRIZENPMkZCUVRWQ096dEJRVkZCTEhkQ1FVRlpMRk5CUVZvc1EwRkJjMElzU1VGQmRFSXNSMEZCTmtJc1ZVRkJWU3hKUVVGV0xFVkJRV2RDTEZsQlFXaENMRVZCUVRoQ08wRkJRM1pFTEc5Q1FVRkpMRXRCUVVzc1dVRkJUQ3hOUVVGMVFpeExRVUZMTEV0QlFVd3NSVUZCV1R0QlFVTnVReXg1UWtGQlN5eFpRVUZNTEVsQlFYRkNMRXRCUVVzc1MwRkJUQ3hEUVVSak8ybENRVUYyUXp0aFFVUjVRaXhEUVdKNVFqdFRRVUZvUXl4RlFXMUNjRUlzUlVGdVFtMUNMRU5CUVVnc1JVRnRRbG9zU1VGQlJ5eERRVUZETEZWQlFWTXNUMEZCVkN4RlFVRnBRaXhOUVVGcVFpeEZRVUYzUWl4UFFVRjRRaXhGUVVGblF6dEJRVU14UXl4NVFrRkVNRU03TzBGQlJ6RkRMR2RDUVVGSkxGVkJRVlVzVVVGQlVTeFpRVUZTTEVOQlFWWXNRMEZJYzBNN08wRkJTekZETEdkQ1FVRkpMRkZCUVZFc1VVRkJVU3h0UWtGQlVpeERRVUZTTEVOQlRITkRPMEZCVFRGRExHZENRVUZKTEZGQlFWRXNVVUZCVVN4dFFrRkJVaXhEUVVGU0xFTkJUbk5ETzBGQlR6RkRMR2RDUVVGSkxGVkJRVlVzVVVGQlVTeHRRa0ZCVWl4RFFVRldMRU5CVUhORE8wRkJVVEZETEdkQ1FVRkpMRlZCUVZVc1VVRkJVU3h0UWtGQlVpeERRVUZXTEVOQlVuTkRPMEZCVXpGRExHZENRVUZKTEZkQlFWY3NVVUZCVVN4dlFrRkJVaXhEUVVGWUxFTkJWSE5ETzBGQlZURkRMR2RDUVVGSkxGTkJRVk1zVVVGQlVTeHRRa0ZCVWl4RFFVRlVMRU5CVm5ORE8wRkJWekZETEdkQ1FVRkpMRmRCUVZjc1VVRkJVU3h0UWtGQlVpeERRVUZZTEVOQldITkRPenRCUVdFeFF5eG5Ra0ZCU1N4WFFVRlhMRkZCUVZFc1owSkJRVklzUTBGQldDeERRV0p6UXp0QlFXTXhReXhuUWtGQlNTeGpRVUZqTEZGQlFWRXNNRUpCUVZJc1EwRkJaQ3hEUVdSelF6dEJRV1V4UXl4blFrRkJTU3hUUVVGVExGRkJRVkVzYjBKQlFWSXNRMEZCVkN4RFFXWnpRenM3UVVGcFFqRkRMRzFDUVVGUExFOUJRVkFzUjBGQmFVSXNRMEZCYWtJc1EwRnFRakJET3p0QlFXMUNNVU1zY1VKQlFWTXNRMEZCVkN4RFFVRlhMRTlCUVZnc1JVRkJiMElzVlVGQmNFSXNSVUZCWjBNc1VVRkJhRU1zUlVGQk1FTTdRVUZEZEVNc2IwSkJRVWtzWVVGQllTeEZRVUZpTEVOQlJHdERPMEZCUlhSRExHOUNRVUZKTEVkQlFVb3NSVUZCVXl4TFFVRlVMRVZCUVdkQ0xFZEJRV2hDTEVWQlFYRkNMRk5CUVhKQ0xFTkJSbk5ET3p0QlFVbDBReXh2UWtGQlNTeERRVUZETEZGQlFVUXNTVUZCWVN4WFFVRlhMRlZCUVZnc1EwRkJZaXhGUVVGeFF6dEJRVU55UXl3clFrRkJWeXhWUVVGWUxFTkJSSEZETzBGQlJYSkRMRFJDUVVGUkxFVkJRVklzUTBGR2NVTTdhVUpCUVhwRE96dEJRVXRCTEhkQ1FVRlJMRk5CUVZNc1ZVRkJWQ3hKUVVGMVFpeEZRVUYyUWl4RFFWUTRRanRCUVZWMFF5eHpRa0ZCVFN4VFFVRlRMRTlCUVZRc1JVRkJhMElzUzBGQmJFSXNRMEZCVGpzN08wRkJWbk5ETEc5Q1FXRnNReXhOUVVGTkxHTkJRVTRzUTBGQmNVSXNTMEZCY2tJc1EwRkJTaXhGUVVGcFF6dEJRVU0zUWl3d1FrRkJUU3hOUVVGTkxFZEJRVTRzUTBGRWRVSTdRVUZGTjBJc01FSkJRVTBzUjBGQlRpeEhRVUZaTEZOQlFWb3NRMEZHTmtJN2FVSkJRV3BET3pzN1FVRmljME1zYjBKQmJVSnNReXhOUVVGTkxHTkJRVTRzUTBGQmNVSXNWMEZCY2tJc1EwRkJTaXhGUVVGMVF6dEJRVU51UXl4blEwRkJXU3hOUVVGTkxGTkJRVTRzUTBGRWRVSTdRVUZGYmtNc01FSkJRVTBzVTBGQlRpeEhRVUZyUWl4VFFVRnNRaXhEUVVadFF6dHBRa0ZCZGtNN096dEJRVzVDYzBNc2IwSkJlVUpzUXl4UlFVRlJMRTlCUVZJc1NVRkRRU3hEUVVGRExGTkJRVVFzU1VGRFFTeE5RVUZOTEdOQlFVNHNRMEZCY1VJc1QwRkJja0lzUTBGR1FTeEpRVWRCTEUxQlFVMHNTMEZCVGl4TFFVRm5RaXhUUVVGb1FpeEpRVU5CTEVOQlFVTXNUMEZCVHl4TlFVRk5MRXRCUVU0c1EwRkJVaXhGUVVOR08wRkJRMFVzTUVKQlFVMHNTMEZCVGl4SFFVRmpMRmxCUVZrc1RVRkJUU3hMUVVGT0xFTkJRVEZDTEVOQlJFWTdhVUpCVEVZN08wRkJVMEVzYjBOQlFXOUNMRXRCUVhCQ0xFVkJiRU56UXpzN1FVRnZRM1JETEc5Q1FVRkpMR0ZCUVdFc1UwRkJZaXhKUVVFd1FpeGhRVUZoTEVsQlFXSXNSVUZCYlVJN1FVRkROME1zTmtKQlFWTXNVVUZCVkN4RlFVRnRRaXhWUVVGdVFpeEZRVUVyUWl4SFFVRXZRaXhGUVVGdlF5eExRVUZ3UXl4RlFVUTJRenRwUWtGQmFrUTdPMEZCUzBFc2RVSkJRVThzU1VGQlNTeExRVUZLTEVOQlFWVXNSMEZCVml4RlFVRmxMRXRCUVdZc1JVRkJjMElzVlVGQmRFSXNSVUZCYTBNc1IwRkJiRU1zUlVGQmRVTXNVMEZCZGtNc1EwRkJVQ3hEUVhwRGMwTTdZVUZCTVVNN08wRkJORU5CTEhGQ1FVRlRMRkZCUVZRc1EwRkJhMElzUTBGQmJFSXNSVUZCY1VJc1ZVRkJja0lzUlVGQmFVTXNSMEZCYWtNc1JVRkJjME1zUzBGQmRFTXNSVUZCTmtNN1FVRkRla01zYjBKQlFVa3NUMEZCVHl4RFFVRlFMRXRCUVdFc1VVRkJZaXhGUVVGMVFqdEJRVU4yUWl3clFrRkJWeXhKUVVGWUxFTkJRV2RDTEVsQlFVa3NTMEZCU2l4RFFVRlZMRU5CUVZZc1EwRkJhRUlzUlVGRWRVSTdhVUpCUVROQ0xFMUJSVThzU1VGQlNTeFBRVUZQTEVOQlFWQXNTMEZCWVN4UlFVRmlMRVZCUVhWQ08wRkJRemxDTEN0Q1FVRlhMRWxCUVZnc1EwRkJaMElzU1VGQlNTeExRVUZLTEVOQlFWVXNUMEZCVHl4RFFVRlFMRU5CUVZZc1EwRkJhRUlzUlVGRU9FSTdhVUpCUVROQ0xFMUJSVUVzU1VGQlNTeFJRVUZSTEVOQlFWSXNRMEZCU2l4RlFVRm5RanRCUVVOdVFpd3JRa0ZCVnl4SlFVRllMRU5CUVdkQ0xFTkJRV2hDTEVWQlJHMUNPMmxDUVVGb1FpeE5RVVZCTEVsQlFVa3NVVUZCVVN4RFFVRlNMRU5CUVVvc1JVRkJaMEk3UVVGRGJrSXNlVUpCUVVzc1NVRkJTU3hKUVVGSkxFTkJRVW9zUlVGQlR5eEpRVUZKTEVWQlFVVXNUVUZCUml4RlFVRlZMRWRCUVRsQ0xFVkJRVzFETzBGQlF5OUNMR2xEUVVGVExFVkJRVVVzUTBGQlJpeERRVUZVTEVWQlFXVXNWVUZCWml4RlFVRXlRaXhIUVVFelFpeEZRVUZuUXl4TFFVRm9ReXhGUVVRclFqdHhRa0ZCYmtNN2FVSkJSRWNzVFVGSlFTeEpRVUZKTEUxQlFVMHNTVUZCVGl4SlFVRmpMRTFCUVUwc1UwRkJUaXhGUVVGcFFqdEJRVU4wUXl3eVFrRkVjME03YVVKQlFXNURMRTFCUlVFN1FVRkRTQ3d3UWtGQlRTeDVRa0ZCZVVJN1FVRkRNMElzZFVOQlFXVXNRMEZCWmp0QlFVTkJMSEZEUVVGaE8wRkJRMVFzY1VOQlFWTXNSMEZCVkR0QlFVTkJMSGREUVVGWkxFdEJRVm83ZVVKQlJrbzdjVUpCUmtVc1EwRkJUaXhEUVVSSE8ybENRVVpCTzJGQldGZzdPMEZCZDBKQkxIRkNRVUZUTEcxQ1FVRlVMRU5CUVRaQ0xFdEJRVGRDTEVWQlFXOURPMEZCUTJoRExIRkNRVUZMTEVsQlFVa3NVVUZCU2l4SlFVRm5RaXhMUVVGeVFpeEZRVUUwUWp0QlFVTjRRaXgzUWtGQlNTeE5RVUZOTEdOQlFVNHNRMEZCY1VJc1VVRkJja0lzUTBGQlNpeEZRVUZ2UXp0QlFVTm9ReXcwUWtGQlNTeFJRVUZSTEUxQlFVMHNVVUZCVGl4RFFVRlNMRU5CUkRSQ096dEJRVWRvUXl3MFFrRkJTU3hQUVVGUExFdEJRVkFzUTBGQlNpeEZRVUZ0UWp0QlFVTm1MSEZEUVVSbE8zbENRVUZ1UWpzN1FVRkpRU3cwUWtGQlNTeFRRVUZUTEUxQlFWUXNRMEZCWjBJc1EwRkJhRUlzUlVGQmJVSXNRMEZCYmtJc1RVRkJNRUlzUzBGQk1VSXNSVUZCYVVNN08wRkJSV3BETEd0RFFVRk5MRkZCUVU0c1NVRkJhMElzVDBGQlR5eExRVUZRTEVOQlFXeENMRU5CUm1sRE8zbENRVUZ5UXp0eFFrRlFTanRwUWtGRVNqdGhRVVJLT3p0QlFXbENRU3h4UWtGQlV5eFBRVUZVTEVOQlFXbENMRU5CUVdwQ0xFVkJRVzlDTzBGQlEyaENMSFZDUVVGUExGRkJRVkVzUTBGQlVpeExRVUZqTEZGQlFWRXNRMEZCVWl4RFFVRmtMRWxCUVRSQ0xGTkJRVk1zUTBGQlZDeERRVUUxUWl4SlFVRXlReXhUUVVGVExFTkJRVlFzUTBGQk0wTXNRMEZFVXp0aFFVRndRanM3UVVGSlFTeHhRa0ZCVXl4VlFVRlVMRU5CUVc5Q0xFTkJRWEJDTEVWQlFYVkNPMEZCUTI1Q0xIVkNRVUZQTEU5QlFVOHNRMEZCVUN4TFFVRmhMRkZCUVdJc1NVRkJlVUlzVVVGQlVTeERRVUZTTEVOQlFYcENMRWxCUVhWRExGRkJRVkVzUTBGQlVpeERRVUYyUXl4RFFVUlpPMkZCUVhaQ096dEJRVWxCTEhGQ1FVRlRMSGRDUVVGVUxFTkJRV3RETEVsQlFXeERMRVZCUVhkRE8wRkJRM0JETEc5Q1FVRkpMRTFCUVUwc1NVRkJTU3hMUVVGS0xFVkJRVTRzUTBGRVowTTdPMEZCUjNCRExHOUNRVUZKTEVsQlFVb3NSMEZCVnl4blJFRkJXQ3hEUVVodlF6dEJRVWx3UXl4dlFrRkJTU3hQUVVGS0xFZEJRV01zT0VOQlExWXNjVVJCUkZVc1IwRkZWaXhSUVVaVkxFZEJSMVlzV1VGQldTeExRVUZMTEdGQlFVd3NRMEZJUml4SFFVbFdMRXRCU2xVc1IwRkxWaXgzUWtGTVZTeEhRVTFXTEZsQlFWa3NTMEZCU3l4WFFVRk1MRU5CVGtZc1EwRktjMEk3UVVGWGFFTXNkVUpCUTBFc2QwUkJSRUVzUTBGWVowTTdRVUZoY0VNc2IwSkJRVWtzWVVGQlNpeEhRVUZ2UWl4TFFVRkxMR0ZCUVV3c1EwRmlaMEk3UVVGamNFTXNiMEpCUVVrc1YwRkJTaXhIUVVGclFpeExRVUZMTEZkQlFVd3NRMEZrYTBJN08wRkJaMEp3UXl4MVFrRkJUeXhIUVVGUUxFTkJhRUp2UXp0aFFVRjRRenM3UVVGdFFrRXNjVUpCUVZNc1YwRkJWQ3hEUVVGeFFpeEhRVUZ5UWl4RlFVRXdRanRCUVVOMFFpeHZRa0ZCU1R0QlFVTkJMREpDUVVGUExFdEJRVXNzVTBGQlRDeERRVUZsTEVkQlFXWXNSVUZCYjBJc1NVRkJjRUlzUlVGQk1FSXNUVUZCTVVJc1EwRkJVQ3hEUVVSQk8ybENRVUZLTEVOQlJVVXNUMEZCVHl4RFFVRlFMRVZCUVZVN1FVRkRVaXd5UWtGQlR5eFBRVUZQTEVkQlFWQXNRMEZCVUN4RFFVUlJPMmxDUVVGV08yRkJTRTQ3VTBGdVNWVXNSVUV5U1ZJc1JVRkJReXh4UWtGQmIwSXNSVUZCY0VJc1JVRkJkVUlzY1VKQlFXOUNMRVZCUVhCQ0xFVkJRWFZDTEhGQ1FVRnZRaXhGUVVGd1FpeEZRVUYxUWl4eFFrRkJiMElzUlVGQmNFSXNSVUZCZFVJc2MwSkJRWEZDTEVWQlFYSkNMRVZCUVhkQ0xIRkNRVUZ2UWl4RlFVRndRaXhGUVVGMVFpeHhRa0ZCYjBJc1JVRkJjRUlzUlVGQmRVSXNjMEpCUVhGQ0xFVkJRWEpDTEVWQlFYZENMRFJDUVVFeVFpeEZRVUV6UWl4RlFVRTRRaXhyUWtGQmFVSXNSVUZCYWtJc1JVRkJiMElzWTBGQllTeEZRVUZpTEVWQk0wbDBUeXhEUVVGSUxFVkJNa2t5VUN4SlFVRkhMRU5CUVVNc1ZVRkJVeXhQUVVGVUxFVkJRV2xDTEUxQlFXcENMRVZCUVhkQ0xFOUJRWGhDTEVWQlFXZERPMEZCUTNKVExIbENRVVJ4VXpzN1FVRkhjbE1zWjBKQlFVa3NVVUZCVVN4UlFVRlJMR1ZCUVZJc1EwRkJVaXhEUVVocFV6czdRVUZMY2xNc1owSkJRVWtzWlVGQlpTeHpRMEZCWml4RFFVeHBVenRCUVUxeVV5eG5Ra0ZCU1N4aFFVRmhMRTlCUVdJc1EwRk9hVk03TzBGQlVYSlRMRzFDUVVGUExFOUJRVkFzUjBGQmFVSXNVVUZCYWtJc1EwRlNjVk03TzBGQlZYSlRMSEZDUVVGVExGRkJRVlFzUTBGQmEwSXNSMEZCYkVJc1JVRkJkVUlzUzBGQmRrSXNSVUZCT0VJN1FVRkRNVUlzYjBKQlFVa3NRMEZCUXl4SFFVRkVMRVZCUVUwN1FVRkRUaXd5UWtGQlR5eExRVUZRTEVOQlJFMDdhVUpCUVZZN08wRkJTVUVzYjBKQlFVa3NUMEZCVHl4RFFVRkZMRTFCUVUwc1kwRkJUaXhEUVVGeFFpeEpRVUZ5UWl4RFFVRkdMRU5CVEdVN08wRkJUekZDTEc5Q1FVRkpMRmRCUVZjc1RVRkJUU3hIUVVGT0xFVkJRVmNzV1VGQldDeERRVUZZTEVOQlVITkNPMEZCVVRGQ0xHOUNRVUZKTEZWQlFWVXNTVUZCVml4RFFWSnpRanM3UVVGVk1VSXNiMEpCUVVrc1YwRkJWeXhKUVVGWUxFTkJRV2RDTEZOQlFWTXNRMEZCVkN4RFFVRm9RaXhEUVVGS0xFVkJRV3RETzBGQlF6bENMRGhDUVVGVkxFdEJRVllzUTBGRU9FSTdhVUpCUVd4RE96dEJRVWxCTEc5Q1FVRkpMRTlCUVVvc1JVRkJZU3hKUVVGaUxFVkJRVzFDTEVsQlFXNUNMRVZCUVhsQ0xFTkJRWHBDTEVOQlpEQkNPenRCUVdkQ01VSXNjVUpCUVVzc1NVRkJTU3hEUVVGS0xFVkJRVThzU1VGQlNTeFRRVUZUTEUxQlFWUXNSVUZCYVVJc1IwRkJha01zUlVGQmMwTTdRVUZEYkVNc01rSkJRVThzVTBGQlV5eERRVUZVTEVOQlFWQXNRMEZFYTBNN08wRkJSMnhETEhkQ1FVRkpMRU5CUVVNc1NVRkJSQ3hGUVVGUE8wRkJRMUFzYVVOQlJFODdjVUpCUVZnN08wRkJTVUVzTWtKQlFVOHNTMEZCU3l4TlFVRk1MRU5CUVZrc1EwRkJXaXhEUVVGUUxFTkJVR3RET3p0QlFWTnNReXgzUWtGQlNTeERRVUZETEU5QlFVUXNSVUZCVlR0QlFVTldMR3REUVVGVkxFbEJRVllzUTBGRVZUdHhRa0ZCWkN4TlFVVlBMRWxCUVVrc1UwRkJVeXhIUVVGVUxFVkJRV003UVVGRGNrSXNhME5CUVZVc1YwRkJWeXhGUVVGWUxFTkJSRmM3UVVGRmNrSXNaME5CUVZFc1NVRkJVaXhEUVVGaExFdEJRVXNzVTBGQlRDeERRVUZsTEVOQlFXWXNSVUZCYTBJc1MwRkJTeXhOUVVGTUxFTkJRUzlDTEVWQlJuRkNPM0ZDUVVGc1FpeE5RVWRCTEVsQlFVa3NVMEZCVXl4SFFVRlVMRWxCUVdkQ0xFbEJRV2hDTEVWQlFYTkNPMEZCUXpkQ0xEaENRVUZOTEVWQlFVNHNSMEZCVnl4TFFVRkxMRk5CUVV3c1EwRkJaU3hEUVVGbUxFVkJRV3RDTEV0QlFVc3NUVUZCVEN4RFFVRTNRaXhEUVVRMlFqdHhRa0ZCTVVJN2FVSkJaRmc3TzBGQmJVSkJMRzlDUVVGSkxFOUJRVW9zUlVGQllUdEJRVU5VTEhkQ1FVRkpMRTFCUVUwc1UwRkJUaXhGUVVGcFFqdEJRVU5xUWl4blEwRkJVU3hKUVVGU0xFTkJRV0VzVFVGQlRTeFRRVUZPTEVOQlFXSXNRMEZFYVVJN2NVSkJRWEpDT3p0QlFVbEJMREJDUVVGTkxGTkJRVTRzUjBGQmEwSXNVVUZCVVN4SlFVRlNMRU5CUVdFc1IwRkJZaXhEUVVGc1FpeERRVXhUTzJsQ1FVRmlPenRCUVZGQkxIVkNRVUZQTEUxQlFVMHNVMEZCVGl4SFFVRnJRaXhQUVVGc1FpeEhRVUUwUWl4UlFVRlJMRmRCUVZJc1JVRkJOVUlzUTBFelEyMUNPMkZCUVRsQ08xTkJWbkZSTEVWQmQwUnVVU3hGUVVGRExHbENRVUZuUWl4RFFVRm9RaXhGUVhoRWFWRXNRMEZCU0N4RlFYZEVNVThzU1VGQlJ5eERRVUZETEZWQlFWTXNUMEZCVkN4RlFVRnBRaXhOUVVGcVFpeEZRVUYzUWl4UFFVRjRRaXhGUVVGblF6dEJRVU16UkN4blFrRkJTU3hWUVVGVkxGRkJRVkVzV1VGQlVpeERRVUZXTEVOQlJIVkVPMEZCUlRORUxHZENRVUZKTEZWQlFWVXNVVUZCVVN4WlFVRlNMRU5CUVZZc1EwRkdkVVE3UVVGSE0wUXNaMEpCUVVrc1YwRkJWeXhSUVVGUkxHRkJRVklzUTBGQldDeERRVWgxUkR0QlFVa3pSQ3huUWtGQlNTeFZRVUZWTEZGQlFWRXNXVUZCVWl4RFFVRldMRU5CU25WRU96dEJRVTB6UkN4dFFrRkJUeXhQUVVGUUxFZEJRV2xDTEZkQlFXcENMRU5CVGpKRU96dEJRVkV6UkN4eFFrRkJVeXhYUVVGVUxFTkJRWEZDTEVOQlFYSkNMRVZCUVhkQ0xFTkJRWGhDTEVWQlFUSkNPMEZCUTNaQ0xHOUNRVUZKTEZsQlFWa3NRMEZCV2l4RFFVUnRRanRCUVVWMlFpeHZRa0ZCU1N4WlFVRlpMRU5CUVZvc1EwRkdiVUk3TzBGQlNYWkNMRzlDUVVGSkxGRkJRVkVzUTBGQlVpeERRVUZLTEVWQlFXZENPMEZCUTFvc1owTkJRVmtzV1VGQldTeERRVUZhTEVWQlFXVXNRMEZCWml4RFFVRmFMRU5CUkZrN2FVSkJRV2hDT3p0QlFVbEJMRzlDUVVGSkxGRkJRVkVzUTBGQlVpeERRVUZLTEVWQlFXZENPMEZCUTFvc1owTkJRVmtzV1VGQldTeERRVUZhTEVWQlFXVXNTVUZCWml4RFFVRmFMRU5CUkZrN2FVSkJRV2hDT3p0QlFVbEJMSFZDUVVGUE8wRkJRMGdzZFVKQlFVY3NVMEZCU0R0QlFVTkJMSFZDUVVGSExGTkJRVWc3YVVKQlJrb3NRMEZhZFVJN1lVRkJNMEk3TzBGQmEwSkJMSEZDUVVGVExGZEJRVlFzUTBGQmNVSXNTMEZCY2tJc1JVRkJORUlzVVVGQk5VSXNSVUZCYzBNN1FVRkRiRU1zYjBKQlFVa3NaMEpCUVdkQ0xFMUJRVTBzUzBGQlRpeERRVVJqT3p0QlFVZHNReXh2UWtGQlNTeERRVUZETEdGQlFVUXNSVUZCWjBJN1FVRkRhRUlzYjBOQlFXZENMRTFCUVUwc1MwRkJUaXhIUVVGakxFMUJRVTBzVFVGQlRpeERRVUZoTEZGQlFXSXNRMEZCWkN4RFFVUkJPMmxDUVVGd1FqczdRVUZKUVN4dlFrRkJTU3hGUVVGRkxGRkJRVkVzWVVGQlVpeExRVU5GTEZGQlFWRXNZVUZCVWl4RFFVUkdMRWxCUlVVc1UwRkJVeXhoUVVGVUxFTkJSa1lzUTBGQlJpeEZRVVU0UWp0QlFVTTVRaXd3UWtGQlRTeEpRVUZKTEV0QlFVb3NRMEZCVlN4dFEwRkJWaXhEUVVGT0xFTkJSRGhDTzJsQ1FVWnNRenM3UVVGTlFTeDFRa0ZCVHl4aFFVRlFMRU5CWW10RE8yRkJRWFJETzFOQk1VSXlRaXhGUVRCRGVrSXNSVUZCUXl4alFVRmhMRVZCUVdJc1JVRkJaMElzWTBGQllTeEZRVUZpTEVWQlFXZENMR05CUVdFc1JVRkJZaXhGUVVGblFpeGxRVUZqTEVWQlFXUXNSVUV4UTNwQ0xFTkJRVWdzUlVFd1F5dERMRWxCUVVjc1EwRkJReXhWUVVGVExFOUJRVlFzUlVGQmFVSXNUVUZCYWtJc1JVRkJkMElzVDBGQmVFSXNSVUZCWjBNN1FVRkRNVWNzYlVKQlFVOHNUMEZCVUN4SFFVRnBRaXhQUVVGcVFpeERRVVF3UnpzN1FVRkhNVWNzY1VKQlFWTXNUMEZCVkN4RFFVRnBRaXhEUVVGcVFpeEZRVUZ2UWp0QlFVTm9RaXgxUWtGQlR5eExRVUZMTEVWQlFVVXNTVUZCUml4TFFVRlhMRTlCUVZnc1EwRkVTVHRoUVVGd1FqdFRRVWd3UlN4RlFVOTRSU3hGUVZCMVJTeERRVUZJTEVWQlQyaEZMRWxCUVVjc1EwRkJReXhWUVVGVExFOUJRVlFzUlVGQmFVSXNUVUZCYWtJc1JVRkJkMElzVDBGQmVFSXNSVUZCWjBNN1FVRkRNVU1zYlVKQlFVOHNUMEZCVUN4SFFVRnBRaXhOUVVGcVFpeERRVVF3UXpzN1FVRkhNVU1zY1VKQlFWTXNUVUZCVkN4RFFVRm5RaXhKUVVGb1FpeEZRVUZ6UWp0QlFVTnNRaXgxUWtGQlR5eFRRVU5LTEU5QlFVOHNTMEZCU3l4SlFVRk1MRXRCUVdNc1ZVRkJja0lzU1VGQmJVTXNRMEZCUXl4TFFVRkxMR05CUVV3c1EwRkJiMElzVFVGQmNFSXNRMEZCUkN4SlFVTnVReXhQUVVGUExFdEJRVXNzVFVGQlRDeExRVUZuUWl4VlFVRjJRaXhKUVVGeFF5eERRVUZETEV0QlFVc3NZMEZCVEN4RFFVRnZRaXhSUVVGd1FpeERRVUZFTEVOQlJtcERMRU5CUkZjN1lVRkJkRUk3VTBGSVZTeEZRVk5TTEVWQlZFOHNRMEZCU0N4RlFWTkJMRWxCUVVjc1EwRkJReXhWUVVGVExFOUJRVlFzUlVGQmFVSXNUVUZCYWtJc1JVRkJkMElzVDBGQmVFSXNSVUZCWjBNN1FVRkRNVU1zWjBKQlFVa3NWVUZCVlN4UlFVRlJMRmRCUVZJc1EwRkJWaXhEUVVSelF6czdRVUZITVVNc2JVSkJRVThzVDBGQlVDeEhRVUZwUWl4aFFVRnFRaXhEUVVnd1F6czdRVUZMTVVNc2NVSkJRVk1zWVVGQlZDeERRVUYxUWl4RFFVRjJRaXhGUVVFd1FqdEJRVU4wUWl4MVFrRkJUeXhMUVVGTExFVkJRVVVzU1VGQlJpeExRVUZYTEdGQlFWZ3NTVUZCTkVJc1JVRkJSU3hQUVVGR0xFdEJRV01zVDBGQlpDeERRVVJzUWp0aFFVRXhRanRUUVV4VkxFVkJVMUlzUlVGQlF5eGhRVUZaTEVWQlFWb3NSVUZVVFN4RFFVRklMRVZCVTJNc1NVRkJSeXhEUVVGRExGVkJRVk1zVDBGQlZDeEZRVUZwUWl4TlFVRnFRaXhGUVVGM1FpeFBRVUY0UWl4RlFVRm5RenRCUVVONFJDeG5Ra0ZCU1N4VlFVRlZMRkZCUVZFc1YwRkJVaXhEUVVGV0xFTkJSRzlFT3p0QlFVZDRSQ3h0UWtGQlR5eFBRVUZRTEVkQlFXbENMR0ZCUVdwQ0xFTkJTSGRFT3p0QlFVdDRSQ3h4UWtGQlV5eGhRVUZVTEVOQlFYVkNMRU5CUVhaQ0xFVkJRVEJDTzBGQlEzUkNMSFZDUVVGUExFdEJRVXNzUlVGQlJTeEpRVUZHTEV0QlFWY3NZVUZCV0N4SlFVRTBRaXhGUVVGRkxFOUJRVVlzUzBGQll5eFBRVUZrTEVOQlJHeENPMkZCUVRGQ08xTkJUSGRDTEVWQlUzUkNMRVZCUVVNc1lVRkJXU3hGUVVGYUxFVkJWRzlDTEVOQlFVZ3NSVUZUUVN4SlFVRkhMRU5CUVVNc1ZVRkJVeXhQUVVGVUxFVkJRV2xDTEUxQlFXcENMRVZCUVhkQ0xFOUJRWGhDTEVWQlFXZERPMEZCUTNoRUxHMUNRVUZQTEU5QlFWQXNSMEZCYVVJc1VVRkJha0lzUTBGRWQwUTdPMEZCUjNoRUxIRkNRVUZUTEZGQlFWUXNRMEZCYTBJc1EwRkJiRUlzUlVGQmNVSTdRVUZEYWtJc2RVSkJRVThzUzBGQlN5eEZRVUZGTEVsQlFVWXNTMEZCVnl4UlFVRllMRU5CUkVzN1lVRkJja0k3VTBGSWQwSXNSVUZQZEVJc1JVRlFjVUlzUTBGQlNDeEZRVTlrTEVsQlFVY3NRMEZCUXl4VlFVRlRMRTlCUVZRc1JVRkJhVUlzVFVGQmFrSXNSVUZCZDBJc1QwRkJlRUlzUlVGQlowTTdRVUZETVVNc2JVSkJRVThzVDBGQlVDeEhRVUZwUWl4SFFVRnFRaXhEUVVRd1F6dFRRVUZvUXl4RlFVZFNMRVZCU0U4c1EwRkJTQ3hGUVVkQkxFbEJRVWNzUTBGQlF5eFZRVUZUTEU5QlFWUXNSVUZCYVVJc1RVRkJha0lzUlVGQmQwSXNUMEZCZUVJc1JVRkJaME03UVVGRE1VTXNaMEpCUVVrc1ZVRkJWU3hSUVVGUkxGZEJRVklzUTBGQlZpeERRVVJ6UXp0QlFVVXhReXhuUWtGQlNTeFZRVUZWTEZGQlFWRXNXVUZCVWl4RFFVRldMRU5CUm5ORE8wRkJSekZETEdkQ1FVRkpMRmRCUVZjc1VVRkJVU3hoUVVGU0xFTkJRVmdzUTBGSWMwTTdRVUZKTVVNc1owSkJRVWtzVlVGQlZTeFJRVUZSTEZsQlFWSXNRMEZCVml4RFFVcHpRenRCUVVzeFF5eG5Ra0ZCU1N4VlFVRlZMRkZCUVZFc1dVRkJVaXhEUVVGV0xFTkJUSE5ET3p0QlFVOHhReXh0UWtGQlR5eFBRVUZRTEVkQlFXbENMRmRCUVdwQ0xFTkJVREJET3p0QlFWTXhReXhuUWtGQlNTeGxRVUZsTEVWQlFXWXNRMEZVYzBNN1FVRlZNVU1zWjBKQlFVa3NZVUZCWVN4RlFVRmlMRU5CVm5ORE96dEJRVmt4UXl4eFFrRkJVeXhYUVVGVUxFTkJRWEZDTEU5QlFYSkNMRVZCUVRoQ0xGVkJRVGxDTEVWQlFUQkRMRkZCUVRGRExFVkJRVzlFTEVkQlFYQkVMRVZCUVhsRUxGTkJRWHBFTEVWQlFXOUZPMEZCUTJoRkxIRkNRVUZMTEU5QlFVd3NSMEZCWlN4UFFVRm1MRU5CUkdkRk8wRkJSV2hGTEhGQ1FVRkxMRlZCUVV3c1IwRkJhMElzWTBGQll5eFpRVUZrTEVOQlJqaERPMEZCUjJoRkxIRkNRVUZMTEZGQlFVd3NSMEZCWjBJc1dVRkJXU3hWUVVGYUxFTkJTR2RFTzBGQlNXaEZMSEZDUVVGTExFZEJRVXdzUjBGQlZ5eFBRVUZQTEVsQlFWQXNSMEZCWXl4UFFVRlBMRWRCUVZBc1EwRkJaQ3hIUVVFMFFpeFRRVUUxUWl4RFFVcHhSRHRCUVV0b1JTeHhRa0ZCU3l4VFFVRk1MRWRCUVdsQ0xFOUJRVkVzVTBGQlVDeExRVUZ4UWl4UlFVRnlRaXhIUVVGcFF5eFRRVUZzUXl4SFFVRTRReXhKUVVFNVF5eERRVXdyUXpzN1FVRlBhRVVzYjBKQlFVa3NVVUZCVVN4UlFVRkRMRWxCUVZrc1UwRkJVeXhOUVVGVUxFbEJRVzlDTEVOQlFXcERMRU5CVUc5RU8wRkJVV2hGTEc5Q1FVRkpMR05CUVdNc1EwRkJaQ3hEUVZJMFJEdEJRVk5vUlN4dlFrRkJTU3hoUVVGaExFdEJRV0lzUTBGVU5FUTdRVUZWYUVVc2IwSkJRVWtzV1VGQldTeExRVUZhTEVOQlZqUkVPMEZCVjJoRkxHOUNRVUZKTEd0Q1FVRnJRaXhMUVVGc1FpeERRVmcwUkR0QlFWbG9SU3h2UWtGQlNTeExRVUZLTEVOQldtZEZPenRCUVdOb1JTeHhRa0ZCU3l4SlFVRkpMRkZCUVVvc1NVRkJaMElzVlVGQmNrSXNSVUZCYVVNN1FVRkROMElzZDBKQlFVa3NWMEZCVnl4alFVRllMRU5CUVRCQ0xGRkJRVEZDTEVOQlFVb3NSVUZCZVVNN1FVRkRja01zTkVKQlFVa3NWMEZCVnl4WFFVRlhMRkZCUVZnc1EwRkJXQ3hEUVVScFF6dEJRVVZ5UXl3MFFrRkJTU3hSUVVGUkxGRkJRVklzUzBGQmNVSXNVMEZCVXl4TlFVRlVMRVZCUVdsQ08wRkJRM1JETEdkRFFVRkpMRU5CUVVNc1MwRkJSQ3hGUVVGUk8wRkJRMUlzZDBOQlFWRXNSVUZCVWl4RFFVUlJPelpDUVVGYU96dEJRVWxCTEd0RFFVRk5MRkZCUVU0c1NVRkJhMElzVVVGQmJFSXNRMEZNYzBNN2VVSkJRVEZETzNGQ1FVWktPMmxDUVVSS096dEJRV0ZCTEhGQ1FVRkxMRWxCUVVrc1NVRkJTU3hEUVVGS0xFVkJRVThzU1VGQlNTeExRVUZLTEVWQlFWY3NSMEZCTTBJc1JVRkJaME03UVVGRE5VSXNkMEpCUVVrc1VVRkJVU3hUUVVGVExFTkJRVlFzUTBGQlVpeERRVVIzUWp0QlFVVTFRaXgzUWtGQlNTeFJRVUZSTEV0QlFWSXNRMEZCU2l4RlFVRnZRanRCUVVOb1FpeDFRMEZCWlN4TlFVRk5MRXRCUVU0c1NVRkJaU3hEUVVGbUxFTkJSRU03TzBGQlIyaENMRFJDUVVGSkxFTkJRVU1zVlVGQlJDeEpRVUZsTEUxQlFVMHNWVUZCVGl4RlFVRnJRanRCUVVOcVF5eDVRMEZCWVN4SlFVRmlMRU5CUkdsRE8zbENRVUZ5UXpzN1FVRkpRU3cwUWtGQlNTeERRVUZETEZOQlFVUXNTVUZCWXl4TlFVRk5MRk5CUVU0c1JVRkJhVUk3UVVGREwwSXNkME5CUVZrc1NVRkJXaXhEUVVRclFqdDVRa0ZCYmtNN08wRkJTVUVzTkVKQlFVa3NRMEZCUXl4bFFVRkVMRXRCUVhGQ0xFMUJRVTBzUzBGQlRpeEpRVUZsTEUxQlFVMHNaVUZCVGl4RFFVRndReXhGUVVFMFJEdEJRVU0xUkN3NFEwRkJhMElzU1VGQmJFSXNRMEZFTkVRN2VVSkJRV2hGTzNGQ1FWaEtMRTFCWTA4c1NVRkJTU3hEUVVGRExGVkJRVVFzU1VGQlpTeFRRVUZUTEV0QlFWUXNRMEZCWml4RlFVRm5RenRCUVVOMlF5dzBRa0ZCU1N4UFFVRlBMRTFCUVUwc1QwRkJUaXhMUVVGclFpeFZRVUY2UWl4RlFVRnhRenRCUVVOeVF5eDVRMEZCWVN4SlFVRmlMRU5CUkhGRE8zbENRVUY2UXp0eFFrRkVSeXhOUVVsQkxFbEJRVWtzUTBGQlF5eFRRVUZFTEVsQlFXTXNVVUZCVVN4TFFVRlNMRU5CUVdRc1JVRkJPRUk3UVVGRGNrTXNiME5CUVZrc1NVRkJXaXhEUVVSeFF6dHhRa0ZCYkVNN2FVSkJjRUpZT3p0QlFYbENRU3h4UWtGQlN5eExRVUZNTEVkQlFXRXNVVUZCVVN4WFFVRlNMRU5CY0VSdFJEdEJRWEZFYUVVc2NVSkJRVXNzVlVGQlRDeEhRVUZyUWl4VlFVRnNRaXhEUVhKRVowVTdRVUZ6UkdoRkxIRkNRVUZMTEZOQlFVd3NSMEZCYVVJc1UwRkJha0lzUTBGMFJHZEZPMEZCZFVSb1JTeHhRa0ZCU3l4TFFVRk1MRWRCUVdFc1MwRkJZaXhEUVhaRVowVTdRVUYzUkdoRkxIRkNRVUZMTEdWQlFVd3NSMEZCZFVJc1pVRkJka0lzUTBGNFJHZEZPMkZCUVhCRk96dEJRVEpFUVN4M1FrRkJXU3hUUVVGYUxFTkJRWE5DTEU5QlFYUkNMRWRCUVdkRExFOUJRV2hETEVOQmRrVXdRenRCUVhkRk1VTXNkMEpCUVZrc1UwRkJXaXhEUVVGelFpeEpRVUYwUWl4SFFVRTJRaXhoUVVFM1FpeERRWGhGTUVNN1UwRkJhRU1zUlVFd1JWSXNSVUZCUXl4alFVRmhMRVZCUVdJc1JVRkJaMElzWTBGQllTeEZRVUZpTEVWQlFXZENMR05CUVdFc1JVRkJZaXhGUVVGblFpeGxRVUZqTEVWQlFXUXNSVUZCYVVJc1lVRkJXU3hGUVVGYUxFVkJNVVV6UkN4RFFVRklMRVZCTUVVclJTeEpRVUZITEVOQlFVTXNWVUZCVXl4UFFVRlVMRVZCUVdsQ0xFMUJRV3BDTEVWQlFYZENMRTlCUVhoQ0xFVkJRV2RETzBGQlEzcElMR2RDUVVGSkxGVkJRVlVzVVVGQlVTeFhRVUZTTEVOQlFWWXNRMEZFY1VnN08wRkJSM3BJTEhsQ1FVRmhMRWxCUVdJc1IwRkJiMElzUTBGQmNFSXNRMEZJZVVnN1FVRkpla2dzZVVKQlFXRXNTMEZCWWl4SFFVRnhRaXhEUVVGeVFpeERRVXA1U0R0QlFVdDZTQ3g1UWtGQllTeExRVUZpTEVkQlFYRkNMRU5CUVhKQ0xFTkJUSGxJTzBGQlRYcElMSGxDUVVGaExFMUJRV0lzUjBGQmMwSXNRMEZCZEVJc1EwRk9lVWc3UVVGUGVrZ3NlVUpCUVdFc1MwRkJZaXhIUVVGeFFpeERRVUZ5UWl4RFFWQjVTRHRCUVZGNlNDeDVRa0ZCWVN4TFFVRmlMRWRCUVhGQ0xFTkJRWEpDTEVOQlVubElPMEZCVTNwSUxIbENRVUZoTEUxQlFXSXNSMEZCYzBJc1EwRkJkRUlzUTBGVWVVZzdRVUZWZWtnc2VVSkJRV0VzVFVGQllpeEhRVUZ6UWl4RFFVRjBRaXhEUVZaNVNEdEJRVmQ2U0N4NVFrRkJZU3hMUVVGaUxFZEJRWEZDTEVOQlFYSkNMRU5CV0hsSU96dEJRV0Y2U0N4dFFrRkJUeXhQUVVGUUxFZEJRV2xDTEZsQlFXcENMRU5CWW5sSU96dEJRV1Y2U0N4eFFrRkJVeXhaUVVGVUxFTkJRWE5DTEVsQlFYUkNMRVZCUVRSQ0xFdEJRVFZDTEVWQlFXMURMRXRCUVc1RExFVkJRVEJETzBGQlEzUkRMSEZDUVVGTExFbEJRVXdzUjBGQldTeFBRVUZQTEVsQlFWQXNRMEZCV2l4RFFVUnpRenRCUVVWMFF5eHhRa0ZCU3l4TFFVRk1MRWRCUVdFc1MwRkJZaXhEUVVaelF6dEJRVWQwUXl4eFFrRkJTeXhMUVVGTUxFZEJRV0VzUzBGQllpeERRVWh6UXp0aFFVRXhRenM3UVVGTlFTeDVRa0ZCWVN4VFFVRmlMRU5CUVhWQ0xFOUJRWFpDTEVkQlFXbERMRTlCUVdwRExFTkJja0o1U0R0QlFYTkNla2dzZVVKQlFXRXNVMEZCWWl4RFFVRjFRaXhKUVVGMlFpeEhRVUU0UWl4alFVRTVRaXhEUVhSQ2VVZzdVMEZCYUVNc1JVRjNRblpHTEVWQlFVTXNZVUZCV1N4RlFVRmFMRVZCZUVKeFJpeERRVUZJTEVWQmQwSnFSU3hKUVVGSExFTkJRVU1zVlVGQlV5eFBRVUZVTEVWQlFXbENMRTFCUVdwQ0xFVkJRWGRDTEU5QlFYaENMRVZCUVdkRE8wRkJRM2hFTEdkQ1FVRkpMRlZCUVZVc1VVRkJVU3hYUVVGU0xFTkJRVllzUTBGRWIwUTdPMEZCUjNoRUxHMUNRVUZQTEU5QlFWQXNSMEZCYVVJc1YwRkJha0lzUTBGSWQwUTdPMEZCUzNoRUxIRkNRVUZUTEZkQlFWUXNRMEZCY1VJc1NVRkJja0lzUlVGQk1rSTdRVUZEZGtJc2NVSkJRVXNzU1VGQlRDeEhRVUZaTEU5QlFVOHNTVUZCVUN4RFFVRmFMRU5CUkhWQ08yRkJRVE5DT3p0QlFVbEJMSGRDUVVGWkxGTkJRVm9zUTBGQmMwSXNUMEZCZEVJc1IwRkJaME1zVDBGQmFFTXNRMEZVZDBRN1FVRlZlRVFzZDBKQlFWa3NVMEZCV2l4RFFVRnpRaXhKUVVGMFFpeEhRVUUyUWl4aFFVRTNRaXhEUVZaM1JEdFRRVUZvUXl4RlFWbDBRaXhGUVVGRExHRkJRVmtzUlVGQldpeEZRVnB2UWl4RFFVRklMRVZCV1VFc1NVRkJSeXhEUVVGRExGVkJRVk1zVDBGQlZDeEZRVUZwUWl4TlFVRnFRaXhGUVVGM1FpeFBRVUY0UWl4RlFVRm5RenRCUVVONFJDeG5Ra0ZCU1N4WFFVRlhMRkZCUVZFc1YwRkJVaXhEUVVGWUxFTkJSRzlFTzBGQlJYaEVMR2RDUVVGSkxGTkJRVk1zVVVGQlVTeHRRa0ZCVWl4RFFVRlVMRU5CUm05RU96dEJRVWw0UkN4dFFrRkJUeXhQUVVGUUxFZEJRV2xDTEZOQlFXcENMRU5CU25kRU96dEJRVTE0UkN4eFFrRkJVeXhUUVVGVUxFTkJRVzFDTEVOQlFXNUNMRVZCUVhOQ0xFTkJRWFJDTEVWQlFYbENPMEZCUTNKQ0xHOUNRVUZKTEVsQlFVb3NRMEZFY1VJN08wRkJSM0pDTEhGQ1FVRkxMRWxCUVVrc1NVRkJTaXhKUVVGWkxFTkJRV3BDTEVWQlFXOUNPMEZCUTJoQ0xIZENRVUZKTEVWQlFVVXNVVUZCVVN4RFFVRlNMRU5CUVVZc1JVRkJZenRCUVVOa0xDdENRVUZQTEZGQlFWRXNSVUZCVWl4RFFVUlBPMEZCUldRc05rSkJRVXNzU1VGQlRDeEpRVUZoTEZOQlFXSXNRMEZHWXp0eFFrRkJiRUk3TzBGQlMwRXNkMEpCUVVrc1UwRkJVeXhGUVVGRkxFbEJRVVlzUTBGQlZDeERRVTVaTzBGQlQyaENMSGRDUVVGSkxGTkJRVk1zUlVGQlJTeEpRVUZHTEVOQlFWUXNRMEZRV1RzN1FVRlRhRUlzZDBKQlFVa3NWMEZCVnl4TlFVRllMRVZCUVcxQ08wRkJRMjVDTEdsRFFVUnRRanR4UWtGQmRrSXNUVUZGVHl4SlFVRkpMRk5CUVZNc1RVRkJWQ3hMUVVGdlFpeFRRVUZUTEUxQlFWUXNRMEZCY0VJc1JVRkJjME03UVVGRE4wTXNORUpCUVVrc1lVRkJZU3hOUVVGaUxFMUJRWGxDTEdGQlFXRXNUVUZCWWl4RFFVRjZRaXhGUVVFclF6dEJRVU12UXl4dFEwRkJUeXhSUVVGUkxFVkJRVklzUTBGRWQwTTdRVUZGTDBNc2FVTkJRVXNzU1VGQlRDeEpRVUZoTEUxQlFXSXNRMEZHSzBNN2VVSkJRVzVFTEUxQlIwOHNTVUZCU1N4UFFVRlBMRTFCUVZBc1EwRkJTaXhGUVVGdlFqdEJRVU4wUWl4dFEwRkJUeXhSUVVGUkxFVkJRVklzUTBGRVpUdEJRVVYwUWl4cFEwRkJTeXhKUVVGTUxFbEJRV0VzVFVGQllpeERRVVp6UWp0NVFrRkJjRUlzVFVGSFFUdEJRVU5JTEdkRFFVRkpMR0ZCUVdFc1ZVRkJWU3hOUVVGV0xFVkJRV3RDTEUxQlFXeENMRU5CUVdJc1EwRkVSRHRCUVVWSUxHZERRVUZKTEZWQlFVb3NSVUZCWjBJN1FVRkRXaXgxUTBGQlR5eFJRVUZSTEVWQlFWSXNRMEZFU3p0QlFVVmFMSEZEUVVGTExFbEJRVXdzU1VGQllTeFZRVUZpTEVOQlJsazdOa0pCUVdoQ08zbENRVXhITzNGQ1FVcEtMRTFCWTBFN1FVRkRTQ3dyUWtGQlR5eFJRVUZSTEVWQlFWSXNRMEZFU2p0QlFVVklMRFpDUVVGTExFbEJRVXdzU1VGQllTeE5RVUZpTEVOQlJrYzdjVUpCWkVFN2FVSkJXRmc3TzBGQkswSkJMSEZDUVVGTExFbEJRVWtzU1VGQlNpeEpRVUZaTEVOQlFXcENMRVZCUVc5Q08wRkJRMmhDTEhkQ1FVRkpMRVZCUVVVc1VVRkJVU3hEUVVGU0xFTkJRVVlzUlVGQll6dEJRVU5rTEN0Q1FVRlBMRkZCUVZFc1JVRkJVaXhEUVVSUE8wRkJSV1FzTmtKQlFVc3NTVUZCVEN4SlFVRmhMRVZCUVVVc1NVRkJSaXhEUVVGaUxFTkJSbU03Y1VKQlFXeENPMmxDUVVSS096dEJRVTlCTEhWQ1FVRlBMRWxCUVZBc1EwRjZRM0ZDTzJGQlFYcENPenRCUVRSRFFTeHhRa0ZCVXl4WlFVRlVMRU5CUVhOQ0xFdEJRWFJDTEVWQlFUWkNPMEZCUXpOQ0xHOUNRVUZKTEU5QlFVOHNZMEZCVUN4RlFVRjFRanRCUVVONlFpd3lRa0ZCVHl4UFFVRlBMR05CUVZBc1EwRkJjMElzUzBGQmRFSXNRMEZCVUN4RFFVUjVRanRwUWtGQk0wSXNUVUZGVHl4SlFVRkpMRTFCUVUwc1UwRkJUaXhGUVVGcFFqdEJRVU14UWl3eVFrRkJUeXhOUVVGTkxGTkJRVTRzUTBGRWJVSTdhVUpCUVhKQ0xFMUJSVUVzU1VGQlNTeE5RVUZOTEZkQlFVNHNSVUZCYlVJN1FVRkROVUlzTWtKQlFVOHNUVUZCVFN4WFFVRk9MRU5CUVd0Q0xGTkJRV3hDTEVOQlJIRkNPMmxDUVVGMlFqdGhRVXhVTzFOQmJFUjNRaXhGUVRSRWRFSXNSVUZCUXl4eFFrRkJiMElzUlVGQmNFSXNSVUZCZFVJc1lVRkJXU3hGUVVGYUxFVkJOVVJJTEVOQlFVZ3NSVUUwUkhWQ0xFbEJRVWNzUTBGQlF5eFZRVUZUTEU5QlFWUXNSVUZCYVVJc1RVRkJha0lzUlVGQmQwSXNUMEZCZUVJc1JVRkJaME03UVVGREwwVXNaMEpCUVVrc1ZVRkJWU3hSUVVGUkxGbEJRVklzUTBGQlZpeERRVVF5UlRzN1FVRkhMMFVzWjBKQlFVa3NVMEZCVXl4UlFVRlJMR2xDUVVGU0xFTkJRVlFzUTBGSU1rVTdRVUZKTDBVc1owSkJRVWtzVlVGQlZTeFJRVUZSTEcxQ1FVRlNMRU5CUVZZc1EwRktNa1U3UVVGTEwwVXNaMEpCUVVrc1ZVRkJWU3hSUVVGUkxHMUNRVUZTTEVOQlFWWXNRMEZNTWtVN1FVRk5MMFVzWjBKQlFVa3NWMEZCVnl4UlFVRlJMRzlDUVVGU0xFTkJRVmdzUTBGT01rVTdRVUZQTDBVc1owSkJRVWtzVlVGQlZTeFJRVUZSTEcxQ1FVRlNMRU5CUVZZc1EwRlFNa1U3UVVGUkwwVXNaMEpCUVVrc1kwRkJZeXhSUVVGUkxIVkNRVUZTTEVOQlFXUXNRMEZTTWtVN08wRkJWUzlGTEdkQ1FVRkpMRmxCUVZrc1VVRkJVU3hqUVVGU0xFTkJRVm9zUTBGV01rVTdPMEZCV1M5RkxHMUNRVUZQTEU5QlFWQXNSMEZCYVVJc1NVRkJha0lzUTBGYUswVTdPMEZCWXk5RkxIRkNRVUZUTEVsQlFWUXNRMEZCWXl4RFFVRmtMRVZCUVdsQ0xFTkJRV3BDTEVWQlFXOUNPMEZCUTJoQ0xHOUNRVUZKTEZGQlFWRXNSVUZCUlN4SFFVRkhMRU5CUVVnc1JVRkJWaXhEUVVSWk8wRkJSV2hDTEhGQ1FVRkxMRU5CUVV3c1JVRkJVU3hEUVVGU0xFVkJRVmNzUzBGQldDeEZRVUZyUWl4RFFVRnNRaXhGUVVablFqdEJRVWRvUWl4MVFrRkJUeXhMUVVGUUxFTkJTR2RDTzJGQlFYQkNPenRCUVUxQkxIRkNRVUZUTEVsQlFWUXNRMEZCWXl4RFFVRmtMRVZCUVdsQ0xFTkJRV3BDTEVWQlFXOUNMRXRCUVhCQ0xFVkJRVEpDTEV0QlFUTkNMRVZCUVd0RE8wRkJRemxDTEc5Q1FVRkpMRTFCUVUwc1EwRkJUaXhGUVVGVE8wRkJRMVFzTWtKQlJGTTdhVUpCUVdJN08wRkJTVUVzYjBKQlFVa3NVVUZCVVN4TlFVRk5MRXRCUVU0c1EwRkJVaXhEUVV3d1FqdEJRVTA1UWl4dlFrRkJTU3hoUVVGaExFdEJRV0lzUTBGT01FSTdPMEZCVVRsQ0xHOUNRVUZKTEZGQlFWRXNRMEZCVWl4TFFVRmpMRkZCUVZFc1EwRkJVaXhEUVVGa0xFVkJRVEJDTzBGQlF6RkNMREpDUVVGUExFTkJRVkFzUlVGQlZTeERRVUZXTEVWQlFXRXNTMEZCWWl4RlFVRnZRaXhMUVVGd1FpeEZRVVF3UWp0cFFrRkJPVUlzVFVGRlR5eEpRVUZKTEV0QlFVc3NTVUZCVEN4RlFVRlhPenM3T3p0QlFVdHNRaXgzUWtGQlNTeERRVUZETEZOQlFWTXNRMEZCVkN4RFFVRkVMRVZCUVdNN1FVRkRaQ3h0UTBGQlZ5eERRVUZZTEVWQlFXTXNTMEZCWkN4RlFVRnhRaXhMUVVGeVFpeEZRVVJqTzBGQlJXUXNaME5CUVZFc1RVRkJUU3hMUVVGT0xFTkJRVklzUTBGR1l6dHhRa0ZCYkVJN08wRkJTMEVzTkVKQlFWRXNXVUZCV1N4TFFVRmFMRVZCUVcxQ0xFbEJRVWtzVFVGQlNpeERRVUZYTEU5QlFVOHNUVUZCVUN4RlFVRmxMRU5CUVRGQ0xFVkJRVFpDTEVOQlFUZENMRU5CUVc1Q0xFTkJRVklzUTBGV2EwSTdhVUpCUVdZc1RVRlhRU3hKUVVGSkxGRkJRVkVzUTBGQlVpeERRVUZLTEVWQlFXZENPMEZCUTI1Q0xIZENRVUZKTEZGQlFWRXNRMEZCVWl4RFFVRktMRVZCUVdkQ08wRkJRMW9zTkVKQlFVa3NSVUZCUlN4UFFVRkdMRXRCUVdNc1JVRkJSU3hQUVVGR0xFbEJRMlFzUlVGQlJTeFRRVUZHTEV0QlFXZENMRVZCUVVVc1UwRkJSaXhKUVVOb1FpeEZRVUZGTEVkQlFVWXNTMEZCVlN4RlFVRkZMRWRCUVVZc1JVRkJUenRCUVVOcVFpeG5RMEZCU1N4aFFVRmhMRlZCUVZVc1JVRkJSU3hWUVVGR0xFVkJRV01zUlVGQlJTeFZRVUZHTEVOQlFYSkRMRU5CUkdFN1FVRkZha0lzWjBOQlFVa3NWVUZCU2l4RlFVRm5RanRCUVVOYUxIZERRVUZSTEZsQlFWa3NTMEZCV2l4RlFVTktMRWxCUVVrc1RVRkJTaXhEUVVGWExFOUJRVThzUzBGQlVDeEZRVUZqTEVOQlFYcENMRVZCUVRSQ0xGVkJRVFZDTEVOQlJFa3NRMEZCVWl4RFFVUlpPelpDUVVGb1FqdEJRVWxCTEc5RFFVRlJMR0ZCUVdFc1EwRkJZaXhGUVVGblFpeERRVUZvUWl4RlFVRnRRaXhMUVVGdVFpeEZRVUV3UWl4TFFVRXhRaXhGUVVGcFF5eExRVUZxUXl4RFFVRlNMRU5CVG1sQ08zbENRVVp5UWl4TlFWTlBPMEZCUTBnc2IwTkJRVkVzV1VGQldTeExRVUZhTEVWQlFXMUNMRWxCUVVrc1RVRkJTaXhEUVVGWExFOUJRVThzUzBGQlVDeEZRVUZqTEVOQlFYcENMRVZCUVRSQ0xFTkJRVFZDTEVOQlFXNUNMRU5CUVZJc1EwRkVSenRCUVVWSUxIbERRVUZoTEVsQlFXSXNRMEZHUnp0NVFrRlVVRHR4UWtGRVNpeE5RV05QTzBGQlEwZ3NaME5CUVZFc1dVRkJXU3hMUVVGYUxFVkJRVzFDTEVsQlFVa3NUVUZCU2l4RFFVRlhMRTlCUVU4c1MwRkJVQ3hGUVVGakxFTkJRWHBDTEVWQlFUUkNMRU5CUVRWQ0xFTkJRVzVDTEVOQlFWSXNRMEZFUnp0QlFVVklMSEZEUVVGaExFbEJRV0lzUTBGR1J6dHhRa0ZrVUR0cFFrRkVSeXhOUVcxQ1FTeEpRVUZKTEZGQlFWRXNRMEZCVWl4RFFVRktMRVZCUVdkQ08wRkJRMjVDTEhkQ1FVRkpMRU5CUVVNc1VVRkJVU3hEUVVGU0xFTkJRVVFzUlVGQllUdEJRVU5pTEdkRFFVRlJMRmxCUVZrc1MwRkJXaXhGUVVGdFFpeEpRVUZKTEUxQlFVb3NRMEZCVnl4UFFVRlBMRXRCUVZBc1JVRkJZeXhEUVVGNlFpeEZRVUUwUWl4RFFVRTFRaXhEUVVGdVFpeERRVUZTTEVOQlJHRTdRVUZGWWl4eFEwRkJZU3hKUVVGaUxFTkJSbUU3Y1VKQlFXcENMRTFCUjA4c1NVRkJTU3hGUVVGRkxFbEJRVVlzUzBGQlZ5eEZRVUZGTEVsQlFVWXNSVUZCVVR0QlFVTXhRaXhuUTBGQlVTeFpRVUZaTEV0QlFWb3NSVUZCYlVJc1NVRkJTU3hOUVVGS0xFTkJRVmNzVDBGQlR5eExRVUZRTEVWQlFXTXNRMEZCZWtJc1JVRkJORUlzUTBGQk5VSXNRMEZCYmtJc1EwRkJVaXhEUVVRd1FqdHhRa0ZCZGtJN2FVSkJTa29zVFVGUFFTeEpRVUZKTEZOQlFWTXNRMEZCVkN4RFFVRktMRVZCUVdsQ08wRkJRM0JDTEhkQ1FVRkpMRU5CUVVNc1UwRkJVeXhEUVVGVUxFTkJRVVFzUlVGQll6dEJRVU5rTEhGRFFVRmhMRWxCUVdJc1EwRkVZenR4UWtGQmJFSTdPMEZCU1VFc05FSkJRVkVzV1VGQldTeExRVUZhTEVWQlFXMUNMRWxCUVVrc1RVRkJTaXhEUVVGWExFOUJRVThzVFVGQlVDeEZRVUZsTEVOQlFURkNMRVZCUVRaQ0xFTkJRVGRDTEVOQlFXNUNMRU5CUVZJc1EwRk1iMEk3YVVKQlFXcENPenRCUVZGUUxHOUNRVUZKTEV0QlFVb3NSVUZCVnp0QlFVTlFMREJDUVVGTkxFdEJRVTRzU1VGQlpTeExRVUZtTEVOQlJFODdhVUpCUVZnN08wRkJTVUVzYjBKQlFVa3NWVUZCU2l4RlFVRm5RanRCUVVOYUxDdENRVUZYTEVOQlFWZ3NSVUZCWXl4TFFVRmtMRVZCUVhGQ0xFdEJRWEpDTEVWQlJGazdhVUpCUVdoQ08yRkJNMFJLT3p0QlFXZEZRU3h4UWtGQlV5eFpRVUZVTEVOQlFYTkNMRU5CUVhSQ0xFVkJRWGxDTEVOQlFYcENMRVZCUVRSQ0xFdEJRVFZDTEVWQlFXMURMRXRCUVc1RExFVkJRVEJETEV0QlFURkRMRVZCUVdsRU8wRkJRemRETEc5Q1FVRkpMRmxCUVZrc1JVRkJSU3hSUVVGR0xFTkJSRFpDTzBGQlJUZERMRzlDUVVGSkxHRkJRV0VzVVVGQlVTeFRRVUZTTEVWQlFXMUNMRVZCUVVVc1VVRkJSaXhEUVVGb1F5eERRVVo1UXp0QlFVYzNReXh2UWtGQlNTeFpRVUZaTEZkQlFWY3NVVUZCV0N4RFFVZzJRanM3UVVGTE4wTXNiMEpCUVVrc1QwRkJUeXhWUVVGVkxFMUJRVllzUTBGTWEwTTdRVUZOTjBNc2IwSkJRVWtzVDBGQlR5eFZRVUZWTEUxQlFWWXNRMEZPYTBNN1FVRlBOME1zYjBKQlFVa3NUVUZCVFN4UFFVRlBMRWxCUVZBc1IwRkJZeXhKUVVGa0xFZEJRWEZDTEVsQlFYSkNMRU5CVUcxRE96dEJRVk0zUXl4eFFrRkJTeXhKUVVGSkxFbEJRVWtzUTBGQlNpeEZRVUZQTEVsQlFVa3NSMEZCU2l4RlFVRlRMRWRCUVhwQ0xFVkJRVGhDTzBGQlF6RkNMSGRDUVVGSkxGZEJRVmNzVlVGQlZTeERRVUZXTEVOQlFWZ3NRMEZFYzBJN1FVRkZNVUlzZDBKQlFVa3NXVUZCV1N4VlFVRlZMRU5CUVZZc1EwRkJXaXhEUVVaelFqdEJRVWN4UWl3MlFrRkJVeXhEUVVGVUxFTkJTREJDT3p0QlFVc3hRaXgzUWtGQlNTeERRVUZETEZGQlFVUXNSVUZCVnp0QlFVTllMRFJDUVVGSkxGTkJRVW9zUlVGQlpUczdRVUZGV0N4dlEwRkJVU3haUVVGWkxFdEJRVm9zUlVGRFNpeEpRVUZKTEUxQlFVb3NRMEZCVnl4UFFVRlBMRTFCUVZBc1JVRkJaU3hKUVVFeFFpeEZRVUZuUXl4VFFVRm9ReXhEUVVSSkxFTkJRVklzUTBGR1Z6dDVRa0ZCWmp0eFFrRkVTaXhOUVUxUE8wRkJRMGdzTmtKQlFVc3NVVUZCVEN4RlFVRmxMRk5CUVdZc1JVRkJNRUlzUzBGQk1VSXNSVUZCYVVNc1MwRkJha01zUlVGRVJ6dHhRa0ZPVURzN1FVRlZRU3gzUWtGQlNTeFJRVUZSTEZGQlFWSXNTMEZCY1VJc1UwRkJVeXhMUVVGVUxFVkJRV2RDTzBGQlEzSkRMR2xEUVVGVExGTkJRVk1zUzBGQlZDeERRVVEwUWp0eFFrRkJla003YVVKQlprbzdPMEZCYjBKQkxHOUNRVUZKTEZkQlFWY3NTMEZCV0N4RlFVRnJRanM3UVVGRmJFSXNORUpCUVZFc1dVRkJXU3hMUVVGYUxFVkJRVzFDTEVsQlFVa3NUVUZCU2l4RFFVTjJRaXhQUVVGUExFdEJRVkFzUlVGRFFTeERRVVoxUWl4RlFVZDJRaXhYUVVGWExFdEJRVmdzUTBGSVNTeERRVUZTTEVOQlJtdENPMmxDUVVGMFFqczdRVUZUUVN4MVFrRkJUeXhMUVVGUUxFTkJkRU0yUXp0aFFVRnFSRHM3UVVGNVEwRXNjVUpCUVZNc1ZVRkJWQ3hEUVVGdlFpeExRVUZ3UWl4RlFVRXlRaXhMUVVFelFpeEZRVUZyUXl4TFFVRnNReXhGUVVGNVF6czdRVUZGY2tNc2RVSkJRVThzUzBGQlVDeEZRVUZqTEV0QlFXUXNSVUZCY1VJc1MwRkJja0lzUlVGR2NVTTdRVUZIY2tNc0swSkJRV1VzUzBGQlppeEZRVUZ6UWl4TFFVRjBRaXhGUVVFMlFpeExRVUUzUWl4RlFVaHhRenRoUVVGNlF6czdPenRCUVRkSUswVXNjVUpCY1VsMFJTeGpRVUZVTEVOQlFYZENMRXRCUVhoQ0xFVkJRU3RDTEV0QlFTOUNMRVZCUVhORExFdEJRWFJETEVWQlFUWkRPMEZCUTNwRExHOUNRVUZKTEZOQlFWTXNTMEZCVkN4RFFVRktMRVZCUVhGQ08wRkJRMnBDTEhkQ1FVRkpMRTlCUVU4c1RVRkJUU3hQUVVGT0xFdEJRV3RDTEZWQlFYcENMRVZCUVhGRE8wRkJRM0pETERoQ1FVRk5MRXRCUVU0c1NVRkJaU3haUVVOWUxFMUJRVTBzUzBGQlRpeERRVVJYTEVWQlJWZ3NTVUZCU1N4TlFVRktMRU5CUVZjc1QwRkJUeXhOUVVGUUxFVkJRV1VzUzBGQk1VSXNSVUZCYVVNc1NVRkJha01zUTBGR1Z5eERRVUZtTEVOQlJIRkRPM0ZDUVVGNlF6dHBRa0ZFU2l4TlFVOVBMRWxCUVVrc1VVRkJVU3hMUVVGU0xFMUJRVzFDTEUxQlFVMHNWVUZCVGl4SlFVRnZRaXhOUVVGTkxGTkJRVTRzUTBGQmRrTXNSVUZCZVVRN1FVRkRhRVVzZDBKQlFVa3NWMEZCVnl4TlFVRk5MRkZCUVU0c1EwRkVhVVE3UVVGRmFFVXNkMEpCUVVrc1RVRkJUU3hUUVVGVExFMUJRVlFzUTBGR2MwUTdRVUZIYUVVc2VVSkJRVXNzU1VGQlNTeEpRVUZKTEVOQlFVb3NSVUZCVHl4SlFVRkpMRWRCUVVvc1JVRkJVeXhIUVVGNlFpeEZRVUU0UWp0QlFVTXhRaXcwUWtGQlNTeFJRVUZSTEZOQlFWTXNRMEZCVkN4RFFVRlNMRU5CUkhOQ08wRkJSVEZDTEdsRFFVRlRMRU5CUVZRc1EwRkdNRUk3TzBGQlNURkNMSFZEUVVGbExFdEJRV1lzUlVGQmMwSXNTMEZCZEVJc1JVRkJOa0lzUzBGQk4wSXNSVUZLTUVJN08wRkJUVEZDTERSQ1FVRkpMRkZCUVZFc1MwRkJVaXhMUVVGclFpeE5RVUZOTEV0QlFVNHNSVUZCWVR0QlFVTXZRaXh4UTBGQlV5eE5RVUZOTEV0QlFVNHNRMEZFYzBJN2VVSkJRVzVETzNGQ1FVNUtPMmxDUVVoSExFMUJZVUVzU1VGQlNTeFJRVUZSTEV0QlFWSXNRMEZCU2l4RlFVRnZRanRCUVVOMlFpd3lRa0ZCVHl4TFFVRlFMRVZCUVdNc1NVRkJaQ3hGUVVGdlFpeExRVUZ3UWl4RlFVRXlRaXhMUVVFelFpeEZRVVIxUWp0cFFrRkJjRUk3WVVGeVFsZzdPenRCUVhKSkswVXNjVUpCWjB0MFJTeE5RVUZVTEVOQlFXZENMRU5CUVdoQ0xFVkJRVzFDTEVOQlFXNUNMRVZCUVhOQ0xFdEJRWFJDTEVWQlFUWkNMRXRCUVRkQ0xFVkJRVzlETzBGQlEyaERMRzlDUVVGSkxGRkJRVkVzV1VGQldTeERRVUZhTEVWQlFXVXNRMEZCWml4RFFVRlNMRU5CUkRSQ08wRkJSV2hETEc5Q1FVRkpMR0ZCUVdFc1MwRkJTeXhOUVVGTkxFTkJRVTRzUlVGQlV5eE5RVUZOTEVOQlFVNHNRMEZCTTBJc1EwRkdORUk3UVVGSGFFTXNiMEpCUVVrc1YwRkJWeXhWUVVGWUxFTkJRVW9zUlVGQk5FSTdRVUZEZUVJc01FSkJRVTBzUzBGQlRpeEpRVUZsTEVsQlFVa3NUVUZCU2l4RFFVRlhMRTlCUVU4c1MwRkJVQ3hGUVVGakxFbEJRWHBDTEVWQlFTdENMRlZCUVM5Q0xFTkJRV1lzUTBGRWQwSTdhVUpCUVRWQ08yRkJTRW83TzBGQlVVRXNjVUpCUVZNc1ZVRkJWQ3hEUVVGdlFpeExRVUZ3UWl4RlFVRXlRanRCUVVOMlFpeHhRa0ZCU3l4SlFVRkpMRXRCUVVvc1NVRkJZU3hMUVVGc1FpeEZRVUY1UWp0QlFVTnlRaXgzUWtGQlNTeFZRVUZWTEVkQlFWWXNSVUZCWlR0QlFVTm1MQ3RDUVVGUExFbEJRVkFzUTBGRVpUdHhRa0ZCYmtJN2FVSkJSRW83TzBGQlRVRXNkVUpCUVU4c1MwRkJVQ3hEUVZCMVFqdGhRVUV6UWpzN08wRkJlRXNyUlN4eFFrRnRUSFJGTEUxQlFWUXNRMEZCWjBJc1MwRkJhRUlzUlVGQmRVSXNTMEZCZGtJc1JVRkJPRUlzUzBGQk9VSXNSVUZCY1VNN1FVRkRha01zYjBKQlFVa3NVVUZCVVN4TFFVRlNMRU5CUVVvc1JVRkJiMEk3UVVGRGFFSXNkMEpCUVVrc1RVRkJUU3hMUVVGT0xFVkJRV0U3UVVGRFlpdzRRa0ZCVFN4TFFVRk9MRWxCUVdVc1dVRkRXQ3hOUVVGTkxFdEJRVTRzUTBGRVZ5eEZRVVZZTEVsQlFVa3NUVUZCU2l4RFFVTkpMRTlCUVU4c1MwRkJVQ3hGUVVOQkxFdEJSa29zUlVGSFNTeGpRVUZqTEUxQlFVMHNTMEZCVGl4RFFVaHNRaXhEUVVaWExFTkJRV1lzUTBGRVlUdHhRa0ZCYWtJN08wRkJWMEVzZDBKQlFVa3NUVUZCVFN4bFFVRk9MRWxCUVhsQ0xFMUJRVTBzVTBGQlRpeEZRVUZwUWp0QlFVTXhReXcwUWtGQlNTeFhRVUZYTEUxQlFVMHNVVUZCVGl4RFFVUXlRanRCUVVVeFF5dzBRa0ZCU1N4TlFVRk5MRk5CUVZNc1RVRkJWQ3hEUVVablF6dEJRVWN4UXl3MlFrRkJTeXhKUVVGSkxFbEJRVWtzUTBGQlNpeEZRVUZQTEVsQlFVa3NSMEZCU2l4RlFVRlRMRWRCUVhwQ0xFVkJRVGhDTzBGQlF6RkNMR2REUVVGSkxGRkJRVkVzVTBGQlV5eERRVUZVTEVOQlFWSXNRMEZFYzBJN1FVRkZNVUlzY1VOQlFWTXNRMEZCVkN4RFFVWXdRanM3UVVGSk1VSXNiVU5CUVU4c1MwRkJVQ3hGUVVGakxFdEJRV1FzUlVGQmNVSXNTMEZCY2tJc1JVRktNRUk3TzBGQlRURkNMR2REUVVGSkxGRkJRVkVzUzBGQlVpeExRVUZyUWl4TlFVRk5MRXRCUVU0c1JVRkJZVHRCUVVNdlFpeDVRMEZCVXl4TlFVRk5MRXRCUVU0c1EwRkVjMEk3TmtKQlFXNURPM2xDUVU1S08zRkNRVWhLTzJsQ1FWcEtMRTFCTUVKUExFbEJRVWtzVVVGQlVTeExRVUZTTEVOQlFVb3NSVUZCYjBJN1FVRkRka0lzTWtKQlFVOHNTMEZCVUN4RlFVRmpMRWxCUVdRc1JVRkJiMElzUzBGQmNFSXNSVUZCTWtJc1MwRkJNMElzUlVGRWRVSTdhVUpCUVhCQ08yRkJNMEpZT3p0QlFXZERRU3h4UWtGQlV5eGhRVUZVTEVOQlFYVkNMRWRCUVhaQ0xFVkJRVFJDTzBGQlEzaENMRzlDUVVGSkxGTkJRVk1zUlVGQlZDeERRVVJ2UWpzN1FVRkhlRUlzY1VKQlFVc3NTVUZCU1N4SFFVRktMRWxCUVZjc1IwRkJhRUlzUlVGQmNVSTdRVUZEYWtJc01rSkJRVThzUjBGQlVDeEpRVUZqTEZOQlFXUXNRMEZFYVVJN2FVSkJRWEpDT3p0QlFVbEJMSFZDUVVGUExFMUJRVkFzUTBGUWQwSTdZVUZCTlVJN096dEJRVzVPSzBVc2NVSkJPRTUwUlN4UFFVRlVMRU5CUVdsQ0xGTkJRV3BDTEVWQlFUUkNMRk5CUVRWQ0xFVkJRWFZET3p0QlFVVnVReXh2UWtGQlNTeGpRVUZqTEZOQlFWTXNVMEZCVkN4RFFVRmtMRU5CUml0Q08wRkJSMjVETEc5Q1FVRkpMRkZCUVZFc1dVRkJXU3hKUVVGYUxFTkJTSFZDTzBGQlNXNURMRzlDUVVGSkxGRkJRVkVzV1VGQldTeEpRVUZhTEVOQlNuVkNPenRCUVUxdVF5eHZRa0ZCU1N4TlFVRk5MRTFCUVU0c1MwRkJhVUlzVlVGQlZTeE5RVUZXTEVWQlFXdENPMEZCUTI1RExESkNRVUZQTzBGQlEwZ3NhME5CUVZVc1UwRkJWanRCUVVOQkxDdENRVUZQTEVsQlFWQTdjVUpCUmtvc1EwRkViVU03YVVKQlFYWkRPenM3UVVGT2JVTXNiMEpCWXk5Q0xHTkJRV01zVTBGQlV5eFRRVUZVTEVOQlFXUXNRMEZrSzBJN1FVRmxia01zYjBKQlFVa3NVVUZCVVN4WlFVRlpMRWxCUVZvc1EwRm1kVUk3UVVGblFtNURMRzlDUVVGSkxGRkJRVkVzV1VGQldTeEpRVUZhTEVOQmFFSjFRanM3UVVGclFtNURMRzlDUVVGSkxFMUJRVTBzVFVGQlRpeExRVUZwUWl4VlFVRlZMRTFCUVZZc1JVRkJhMEk3UVVGRGJrTXNNa0pCUVU4N1FVRkRTQ3hyUTBGQlZTeFRRVUZXTzBGQlEwRXNLMEpCUVU4c1NVRkJVRHR4UWtGR1NpeERRVVJ0UXp0cFFrRkJka003T3p0QlFXeENiVU1zYjBKQk1FSXZRaXhqUVVGakxFVkJRV1FzUTBFeFFpdENPenRCUVRSQ2JrTXNiMEpCUVVrc1dVRkJXU3hEUVVGYUxFTkJOVUlyUWp0QlFUWkNia01zYjBKQlFVa3NXVUZCV1N4TlFVRk5MRTFCUVU0c1EwRTNRbTFDTzBGQk9FSnVReXh2UWtGQlNTeGxRVUZsTEVOQlFXWTdPenM3UVVFNVFpdENMSEZDUVd0RE9VSXNTVUZCU1N4SlFVRkpMRU5CUVVvc1JVRkJVU3hKUVVGSkxGVkJRVlVzVFVGQlZpeEZRVUZyUWl4SFFVRjJReXhGUVVFMFF6dEJRVU40UXl4M1FrRkJTU3hSUVVGUkxGVkJRVlVzUTBGQlZpeERRVUZTTEVOQlJHOURPMEZCUlhoRExIZENRVUZKTEZOQlFVb3NRMEZHZDBNN08wRkJTWGhETEhkQ1FVRkpMRTFCUVUwc1IwRkJUaXhGUVVGWE8wRkJRMWdzTkVKQlFVa3NUVUZCVFN4alFVRk9MRU5CUVhGQ0xFMUJRVTBzUjBGQlRpeERRVUY2UWl4RlFVRnhRenM3UVVGRmFrTXNkME5CUVZrc1RVRkJUU3hOUVVGTkxFZEJRVTRzUTBGQmJFSXNRMEZHYVVNN1FVRkhha01zZDBOQlFWa3NTVUZCV2l4RFFVRnBRaXhWUVVGVkxGTkJRVllzUTBGQmFrSXNSVUZJYVVNN2VVSkJRWEpETEUxQlMwODdPMEZCUlVnc2QwTkJRVmtzU1VGQlNTeGpRVUZLTEVOQlJsUTdRVUZIU0N4M1EwRkJXU3hKUVVGYUxFTkJRV2xDTEVsQlFXcENMRVZCU0VjN2VVSkJURkE3Y1VKQlJFb3NUVUZYVHpzN1FVRkZTQ3cwUWtGQlNTeFpRVUZaTEZOQlFWb3NSVUZCZFVJN1FVRkRka0lzZDBOQlFWa3NUVUZCVFN4WFFVRk9MRU5CUVZvc1EwRkVkVUk3UVVGRmRrSXNkME5CUVZrc1NVRkJXaXhEUVVGcFFpeFZRVUZWTEZOQlFWWXNRMEZCYWtJc1JVRkdkVUk3ZVVKQlFUTkNMRTFCUjA4N096czdRVUZKU0N4M1EwRkJXU3hKUVVGSkxHTkJRVW9zUTBGS1ZEdEJRVXRJTEhkRFFVRlpMRWxCUVZvc1EwRkJhVUlzU1VGQmFrSXNSVUZNUnp0NVFrRklVRHR4UWtGaVNqdHBRa0ZLU2pzN1FVRTRRa0VzYjBKQlFVa3NaMEpCUVdkQ0xHRkJRV0VzVFVGQlRTeE5RVUZPTEVkQlF6ZENMRlZCUVZVc1RVRkJWaXhIUVVOQkxFMUJRVTBzVTBGQlRpeERRVVpuUWpzN096dEJRV2hGWlN4eFFrRnpSVGxDTEVsQlFVa3NTVUZCU1N4RFFVRktMRVZCUVU4c1NVRkJTU3hWUVVGVkxFMUJRVllzUlVGQmEwSXNSMEZCZEVNc1JVRkJNa003UVVGRGRrTXNkMEpCUVVrc1ZVRkJWU3hWUVVGVkxFTkJRVllzUTBGQlZpeERRVVJ0UXpzN1FVRkhka01zZDBKQlFVa3NVVUZCVVN4SFFVRlNMRVZCUVdFN1FVRkRZaXcwUWtGQlNTeERRVUZETEUxQlFVMHNZMEZCVGl4RFFVRnhRaXhSUVVGUkxFZEJRVklzUTBGQmRFSXNSVUZCYjBNN096czdRVUZKY0VNc2QwTkJRVmtzU1VGQldpeERRVUZwUWl4UFFVRnFRaXhGUVVwdlF6dDVRa0ZCZUVNN2NVSkJSRW9zVFVGUFR5eEpRVUZKTEV0QlFVc3NZVUZCVEN4RlFVRnZRanM3UVVGRk0wSXNiME5CUVZrc1NVRkJXaXhEUVVGcFFpeFBRVUZxUWl4RlFVWXlRanR4UWtGQmVFSTdhVUpCVmxnN08wRkJaMEpCTEc5Q1FVRkpMRmRCUVZjc1dVRkJXU3hMUVVGYUxFVkJRVmdzUTBGMFJpdENPMEZCZFVadVF5eHZRa0ZCU1N4blFrRkJaMElzUTBGQmFFSXNRMEYyUml0Q08wRkJkMFp1UXl4dlFrRkJTU3hWUVVGVkxFVkJRVllzUTBGNFJpdENPMEZCZVVadVF5eHZRa0ZCU1N4VlFVRlZMRVZCUVZZc1EwRjZSaXRDTzBGQk1FWnVReXh2UWtGQlNTeFpRVUZLTEVOQk1VWnRRenM3UVVFMFJtNURMSEZDUVVGTExFbEJRVWtzU1VGQlNTeERRVUZLTEVWQlFVOHNTVUZCU1N4VlFVRlZMRTFCUVZZc1IwRkJiVUk3UVVGRGJrTXNkMEpCUVVrc1lVRkJZU3hWUVVGVkxFTkJRVllzUTBGQllpeERRVVFyUWp0QlFVVnVReXh0UTBGQlpTeFRRVUZUTEdGQlFWUXNRMEZCWmpzN08wRkJSbTFETERKQ1FVczFRaXhwUWtGQmFVSXNTVUZCYWtJc1NVRkJlVUlzVTBGQlV5eE5RVUZVTEVWQlFXbENPMEZCUXpkRExHZERRVUZSTEVsQlFWSXNRMEZCWVN4UFFVRlBMRkZCUVZBc1JVRkJhVUlzWVVGQmFrSXNSVUZCWjBNc1NVRkJhRU1zUTBGQllpeEZRVVEyUXp0QlFVVTNReXgxUTBGQlpTeFRRVUZUTEdGQlFWUXNRMEZCWml4RFFVWTJRenR4UWtGQmFrUTdPMEZCUzBFc2QwSkJRVWtzUTBGQlF5eFpRVUZFTEVsQlFXbENMR0ZCUVdFc1IwRkJZaXhMUVVGeFFpeFhRVUZYTEVkQlFWZ3NSVUZCWjBJN08wRkJSWFJFTERSQ1FVRkpMRmRCUVZjc1IwRkJXQ3hGUVVGblFqdEJRVU5vUWl4blEwRkJTU3huUWtGQlowSXNZVUZCWVN4SFFVRmlMRVZCUVd0Q096dEJRVVZzUXl4dlEwRkJTU3hOUVVGTkxHRkJRV0VzUjBGQllpeERRVUZPTEV0QlFUUkNMRWxCUVVrc1EwRkJTaXhGUVVGUE8wRkJRMjVETERSRFFVRlJMRWxCUVZJc1EwRkJZU3hQUVVGUExGRkJRVkFzUlVGQmFVSXNZVUZCYWtJc1JVRkJaME1zWVVGQllTeEhRVUZpTEVOQlFUZERMRVZCUkcxRE8wRkJSVzVETEcxRVFVRmxMRk5CUVZNc1lVRkJWQ3hEUVVGbU96dEJRVVp0UXl4M1EwRkpMMElzUTBGQlF5eFpRVUZFTEVsQlFXbENMR0ZCUVdFc1IwRkJZaXhMUVVGeFFpeFhRVUZYTEVkQlFWZ3NSVUZCWjBJN1FVRkRkRVFzWjBSQlFWRXNTVUZCVWl4RFFVRmhMRVZCUVVNc1MwRkJTeXhYUVVGWExFZEJRVmdzUlVGQlowSXNTVUZCU1N4RFFVRktMRVZCUVc1RExFVkJSSE5FT3pzN1FVRkJNVVFzZVVOQlNVczdRVUZEUkN3MFJFRkVRenQ1UTBGS1REdHBRMEZLU2l4TlFWbExPMEZCUTBRc05FTkJRVkVzU1VGQlVpeERRVUZoTEVWQlFVTXNTMEZCU3l4WFFVRlhMRWRCUVZnc1JVRkJaMElzU1VGQlNTeERRVUZLTEVWQlFXNURMRVZCUkVNN2FVTkJXa3c3TmtKQlJrb3NUVUZyUWtzN1FVRkRSQ3gzUTBGQlVTeEpRVUZTTEVOQlFXRXNSVUZCUXl4TFFVRkxMRmRCUVZjc1IwRkJXQ3hGUVVGblFpeEpRVUZKTEVOQlFVb3NSVUZCYmtNc1JVRkVRenMyUWtGc1FrdzdRVUZ4UWtFc1owTkJkRUpuUWpzN08wRkJRWEJDTERaQ1FYbENTeXhKUVVGSkxHZENRVUZuUWl4aFFVRmhMRWRCUVdJc1JVRkJhMEk3UVVGRGRrTXNkME5CUVZFc1NVRkJVaXhEUVVGaExFOUJRVThzVVVGQlVDeEZRVUZwUWl4aFFVRnFRaXhGUVVGblF5eGhRVUZoTEVkQlFXSXNRMEZCTjBNc1JVRkVkVU03TmtKQlFYUkRPM0ZDUVROQ1ZDeE5RU3RDU3p0QlFVTkVMSGREUVVSRE8wRkJSVVFzTkVKQlJrTTdjVUpCTDBKTU8ybENRVlpLT3pzN1FVRTFSbTFETEhWQ1FUUkpOMElzWjBKQlFXZENMRk5CUVZNc1RVRkJWQ3hGUVVGcFFqdEJRVU51UXl4dFEwRkJaU3hUUVVGVExHRkJRVlFzUTBGQlppeERRVVJ0UXp0QlFVVnVReXcwUWtGQlVTeEpRVUZTTEVOQlFXRXNUMEZCVHl4UlFVRlFMRVZCUVdsQ0xHRkJRV3BDTEVWQlFXZERMR2RDUVVGblFpeGhRVUZoTEVkQlFXSXNRMEZCTjBRc1JVRkdiVU03YVVKQlFYWkRPenM3TzBGQk5VbHRReXh2UWtGdFNpOUNMRkZCUVZFc1RVRkJVaXhMUVVGdFFpeFpRVUZ1UWl4SlFVRnRReXhEUVVGRExGRkJRVkVzVFVGQlVpeEZRVUZuUWp0QlFVTndSQ3d5UWtGQlR6dEJRVU5JTEd0RFFVRlZMRmRCUVZZN1FVRkRRU3dyUWtGQlR5eEpRVUZRTzNGQ1FVWktMRU5CUkc5RU8ybENRVUY0UkRzN1FVRlBRU3gxUWtGQlR6dEJRVU5JTERoQ1FVRlZMRmRCUVZZN1FVRkRRU3d5UWtGQlR6dEJRVU5JTEdsRFFVRlRMRTlCUVZRN1FVRkRRU3hwUTBGQlV5eFBRVUZVTzNGQ1FVWktPMmxDUVVaS0xFTkJNVXB0UXp0aFFVRjJRenM3UVVGdFMwRXNjVUpCUVZNc1RVRkJWQ3hEUVVGblFpeEhRVUZvUWl4RlFVRnhRaXhMUVVGeVFpeEZRVUUwUWl4SFFVRTFRaXhGUVVGcFF6dEJRVU0zUWl4dlFrRkJTU3hOUVVGS0xFTkJRVmNzUzBGQldDeEZRVUZyUWl4RFFVRnNRaXhGUVVRMlFqczdRVUZITjBJc2RVSkJRVTg3UVVGRFNDd3dRa0ZCVFN4TFFVRk9PMEZCUTBFc2VVSkJRVXNzUjBGQlREdHBRa0ZHU2l4RFFVZzJRanRoUVVGcVF6czdRVUZUUVN4eFFrRkJVeXhSUVVGVUxFTkJRV3RDTEZGQlFXeENMRVZCUVRSQ08wRkJRM2hDTEc5Q1FVRkpMRTlCUVU4c1JVRkJVQ3hEUVVSdlFqdEJRVVY0UWl4dlFrRkJTU3hQUVVGUExFVkJRVkFzUTBGR2IwSTdRVUZIZUVJc2IwSkJRVWtzVTBGQlV5eFRRVUZUTEUxQlFWUXNRMEZJVnpzN1FVRkxlRUlzY1VKQlFVc3NTVUZCU1N4SlFVRkpMRU5CUVVvc1JVRkJUeXhKUVVGSkxFMUJRVW9zUlVGQldTeEhRVUUxUWl4RlFVRnBRenRCUVVNM1FpeDNRa0ZCU1N4UlFVRlJMRk5CUVZNc1EwRkJWQ3hEUVVGU0xFTkJSSGxDT3p0QlFVYzNRaXgzUWtGQlNTeE5RVUZOTEVkQlFVNHNSVUZCVnp0QlFVTllMRFpDUVVGTExFMUJRVTBzUjBGQlRpeERRVUZNTEVkQlFXdENMRU5CUVd4Q0xFTkJSRmM3Y1VKQlFXWXNUVUZGVHp0QlFVTklMRFpDUVVGTExFbEJRVXdzUTBGQlZTeERRVUZXTEVWQlJFYzdjVUpCUmxBN2FVSkJTRW83TzBGQlZVRXNkVUpCUVU4N1FVRkRTQ3d3UWtGQlRTeEpRVUZPTzBGQlEwRXNNRUpCUVUwc1NVRkJUanRCUVVaSExHbENRVUZRTEVOQlpuZENPMkZCUVRWQ096dEJRWEZDUVN4eFFrRkJVeXhYUVVGVUxFTkJRWEZDTEV0QlFYSkNMRVZCUVRSQ0xFdEJRVFZDTEVWQlFXMURPMEZCUXk5Q0xHOUNRVUZKTEV0QlFVb3NSVUZCVnp0QlFVTlFMSGRDUVVGSkxGRkJRVkVzUzBGQlVpeERRVUZLTEVWQlFXOUNPMEZCUTJoQ0xEaENRVUZOTEVsQlFVNHNRMEZCVnl4TFFVRllMRVZCUkdkQ08zRkNRVUZ3UWl4TlFVVlBPMEZCUTBnc1owTkJRVkVzUTBGQlF5eExRVUZFTEVWQlFWRXNTMEZCVWl4RFFVRlNMRU5CUkVjN2NVSkJSbEE3TzBGQlRVRXNNa0pCUVU4c1MwRkJVQ3hEUVZCUE8ybENRVUZZTEUxQlVVODdRVUZEU0N3eVFrRkJUeXhMUVVGUUxFTkJSRWM3YVVKQlVsQTdZVUZFU2p0VFFTOWFLME1zUlVFMllUZERMRVZCUVVNc2VVSkJRWGRDTEVWQlFYaENMRVZCUVRKQ0xIRkNRVUZ2UWl4RlFVRndRaXhGUVVGMVFpeHhRa0ZCYjBJc1JVRkJjRUlzUlVGQmRVSXNjVUpCUVc5Q0xFVkJRWEJDTEVWQlFYVkNMSE5DUVVGeFFpeEZRVUZ5UWl4RlFVRjNRaXh0UWtGQmEwSXNSVUZCYkVJc1JVRkJjVUlzWjBKQlFXVXNSVUZCWml4RlFVRnJRaXhqUVVGaExFVkJRV0lzUlVFM1lYQklMRU5CUVVnc1JVRTVkVU0xUWl4RlFUSndSSE5MTEVWQk0zQkVkRXNzUlVFeWNFUjVTeXhEUVVGRExFTkJRVVFzUTBFemNFUjZTeXhGUVRKd1JEaExMRU5CTTNCRU9Vc3NRMEZCVUN4RFFVWkxPME5CUVZnc1EwRkdSVHM3UVVGcmNVUktMR1ZCUVdVc1ZVRkJaaUlzSW1acGJHVWlPaUpzYVdJdmRtbHlkSFZoYkMxa2IyMHVhbk1pTENKemIzVnlZMlZ6UTI5dWRHVnVkQ0k2V3lKc1pYUWdWbWx5ZEhWaGJFUlBUU0E5SUdaMWJtTjBhVzl1S0dVcElIdGNiaUFnY21WMGRYSnVJR1VvS1R0Y2JuMG9ablZ1WTNScGIyNG9LU0I3WEc0Z0lDQWdJQ0FnSUhaaGNpQmtaV1pwYm1Vc0lHMXZaSFZzWlN3Z1pYaHdiM0owY3p0Y2JpQWdJQ0FnSUNBZ2NtVjBkWEp1SUNobWRXNWpkR2x2YmlCbEtIUXNJRzRzSUhJcElIdGNiaUFnSUNBZ0lDQWdJQ0FnSUNBZ0lDQm1kVzVqZEdsdmJpQnpLRzhzSUhVcElIdGNiaUFnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnYVdZZ0tDRnVXMjlkS1NCN1hHNGdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNCcFppQW9JWFJiYjEwcElIdGNiaUFnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0IyWVhJZ1lTQTlJSFI1Y0dWdlppQnlaWEYxYVhKbElEMDlJRndpWm5WdVkzUnBiMjVjSWlBbUppQnlaWEYxYVhKbE8xeHVJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJR2xtSUNnaGRTQW1KaUJoS1NCeVpYUjFjbTRnWVNodkxDQWhNQ2s3WEc0Z0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ2FXWWdLR2twSUhKbGRIVnliaUJwS0c4c0lDRXdLVHRjYmlBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNCMllYSWdaaUE5SUc1bGR5QkZjbkp2Y2loY0lrTmhibTV2ZENCbWFXNWtJRzF2WkhWc1pTQW5YQ0lnS3lCdklDc2dYQ0luWENJcE8xeHVJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJSFJvY205M0lHWXVZMjlrWlNBOUlGd2lUVTlFVlV4RlgwNVBWRjlHVDFWT1JGd2lMQ0JtWEc0Z0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0I5WEc0Z0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0IyWVhJZ2JDQTlJRzViYjEwZ1BTQjdYRzRnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnWlhod2IzSjBjem9nZTMxY2JpQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUgwN1hHNGdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNCMFcyOWRXekJkTG1OaGJHd29iQzVsZUhCdmNuUnpMQ0JtZFc1amRHbHZiaWhsS1NCN1hHNGdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdkbUZ5SUc0Z1BTQjBXMjlkV3pGZFcyVmRPMXh1SUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUhKbGRIVnliaUJ6S0c0Z1B5QnVJRG9nWlNsY2JpQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUgwc0lHd3NJR3d1Wlhod2IzSjBjeXdnWlN3Z2RDd2diaXdnY2lsY2JpQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdmVnh1SUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNCeVpYUjFjbTRnYmx0dlhTNWxlSEJ2Y25SelhHNGdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ2ZWeHVJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lIWmhjaUJwSUQwZ2RIbHdaVzltSUhKbGNYVnBjbVVnUFQwZ1hDSm1kVzVqZEdsdmJsd2lJQ1ltSUhKbGNYVnBjbVU3WEc0Z0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnWm05eUlDaDJZWElnYnlBOUlEQTdJRzhnUENCeUxteGxibWQwYURzZ2J5c3JLU0J6S0hKYmIxMHBPMXh1SUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJSEpsZEhWeWJpQnpYRzRnSUNBZ0lDQWdJQ0FnSUNCOUtTaDdYRzRnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSURFNklGdG1kVzVqZEdsdmJpaHlaWEYxYVhKbExDQnRiMlIxYkdVc0lHVjRjRzl5ZEhNcElIdGNibHh1ZG1GeUlHTnlaV0YwWlVWc1pXMWxiblFnUFNCeVpYRjFhWEpsS0Z3aUxpOTJaRzl0TDJOeVpXRjBaUzFsYkdWdFpXNTBMbXB6WENJcFhHNWNibTF2WkhWc1pTNWxlSEJ2Y25SeklEMGdZM0psWVhSbFJXeGxiV1Z1ZEZ4dVhHNTlMSHRjSWk0dmRtUnZiUzlqY21WaGRHVXRaV3hsYldWdWRDNXFjMXdpT2pFMWZWMHNNanBiWm5WdVkzUnBiMjRvY21WeGRXbHlaU3h0YjJSMWJHVXNaWGh3YjNKMGN5bDdYRzUyWVhJZ1pHbG1aaUE5SUhKbGNYVnBjbVVvWENJdUwzWjBjbVZsTDJScFptWXVhbk5jSWlsY2JseHViVzlrZFd4bExtVjRjRzl5ZEhNZ1BTQmthV1ptWEc1Y2JuMHNlMXdpTGk5MmRISmxaUzlrYVdabUxtcHpYQ0k2TXpWOVhTd3pPbHRtZFc1amRHbHZiaWh5WlhGMWFYSmxMRzF2WkhWc1pTeGxlSEJ2Y25SektYdGNiblpoY2lCb0lEMGdjbVZ4ZFdseVpTaGNJaTR2ZG1seWRIVmhiQzFvZVhCbGNuTmpjbWx3ZEM5cGJtUmxlQzVxYzF3aUtWeHVYRzV0YjJSMWJHVXVaWGh3YjNKMGN5QTlJR2hjYmx4dWZTeDdYQ0l1TDNacGNuUjFZV3d0YUhsd1pYSnpZM0pwY0hRdmFXNWtaWGd1YW5OY0lqb3lNbjFkTERRNlcyWjFibU4wYVc5dUtISmxjWFZwY21Vc2JXOWtkV3hsTEdWNGNHOXlkSE1wZTF4dWRtRnlJR1JwWm1ZZ1BTQnlaWEYxYVhKbEtGd2lMaTlrYVdabUxtcHpYQ0lwWEc1MllYSWdjR0YwWTJnZ1BTQnlaWEYxYVhKbEtGd2lMaTl3WVhSamFDNXFjMXdpS1Z4dWRtRnlJR2dnUFNCeVpYRjFhWEpsS0Z3aUxpOW9MbXB6WENJcFhHNTJZWElnWTNKbFlYUmxJRDBnY21WeGRXbHlaU2hjSWk0dlkzSmxZWFJsTFdWc1pXMWxiblF1YW5OY0lpbGNiblpoY2lCV1RtOWtaU0E5SUhKbGNYVnBjbVVvSnk0dmRtNXZaR1V2ZG01dlpHVXVhbk1uS1Z4dWRtRnlJRlpVWlhoMElEMGdjbVZ4ZFdseVpTZ25MaTkyYm05a1pTOTJkR1Y0ZEM1cWN5Y3BYRzVjYm0xdlpIVnNaUzVsZUhCdmNuUnpJRDBnZTF4dUlDQWdJR1JwWm1ZNklHUnBabVlzWEc0Z0lDQWdjR0YwWTJnNklIQmhkR05vTEZ4dUlDQWdJR2c2SUdnc1hHNGdJQ0FnWTNKbFlYUmxPaUJqY21WaGRHVXNYRzRnSUNBZ1ZrNXZaR1U2SUZaT2IyUmxMRnh1SUNBZ0lGWlVaWGgwT2lCV1ZHVjRkRnh1ZlZ4dVhHNTlMSHRjSWk0dlkzSmxZWFJsTFdWc1pXMWxiblF1YW5OY0lqb3hMRndpTGk5a2FXWm1MbXB6WENJNk1peGNJaTR2YUM1cWMxd2lPak1zWENJdUwzQmhkR05vTG1welhDSTZNVE1zWENJdUwzWnViMlJsTDNadWIyUmxMbXB6WENJNk16RXNYQ0l1TDNadWIyUmxMM1owWlhoMExtcHpYQ0k2TXpOOVhTdzFPbHRtZFc1amRHbHZiaWh5WlhGMWFYSmxMRzF2WkhWc1pTeGxlSEJ2Y25SektYdGNiaThxSVZ4dUlDb2dRM0p2YzNNdFFuSnZkM05sY2lCVGNHeHBkQ0F4TGpFdU1WeHVJQ29nUTI5d2VYSnBaMmgwSURJd01EY3RNakF4TWlCVGRHVjJaVzRnVEdWMmFYUm9ZVzRnUEhOMFpYWmxibXhsZG1sMGFHRnVMbU52YlQ1Y2JpQXFJRUYyWVdsc1lXSnNaU0IxYm1SbGNpQjBhR1VnVFVsVUlFeHBZMlZ1YzJWY2JpQXFJRVZEVFVGVFkzSnBjSFFnWTI5dGNHeHBZVzUwTENCMWJtbG1iM0p0SUdOeWIzTnpMV0p5YjNkelpYSWdjM0JzYVhRZ2JXVjBhRzlrWEc0Z0tpOWNibHh1THlvcVhHNGdLaUJUY0d4cGRITWdZU0J6ZEhKcGJtY2dhVzUwYnlCaGJpQmhjbkpoZVNCdlppQnpkSEpwYm1keklIVnphVzVuSUdFZ2NtVm5aWGdnYjNJZ2MzUnlhVzVuSUhObGNHRnlZWFJ2Y2k0Z1RXRjBZMmhsY3lCdlppQjBhR1ZjYmlBcUlITmxjR0Z5WVhSdmNpQmhjbVVnYm05MElHbHVZMngxWkdWa0lHbHVJSFJvWlNCeVpYTjFiSFFnWVhKeVlYa3VJRWh2ZDJWMlpYSXNJR2xtSUdCelpYQmhjbUYwYjNKZ0lHbHpJR0VnY21WblpYZ2dkR2hoZENCamIyNTBZV2x1YzF4dUlDb2dZMkZ3ZEhWeWFXNW5JR2R5YjNWd2N5d2dZbUZqYTNKbFptVnlaVzVqWlhNZ1lYSmxJSE53YkdsalpXUWdhVzUwYnlCMGFHVWdjbVZ6ZFd4MElHVmhZMmdnZEdsdFpTQmdjMlZ3WVhKaGRHOXlZQ0JwY3lCdFlYUmphR1ZrTGx4dUlDb2dSbWw0WlhNZ1luSnZkM05sY2lCaWRXZHpJR052YlhCaGNtVmtJSFJ2SUhSb1pTQnVZWFJwZG1VZ1lGTjBjbWx1Wnk1d2NtOTBiM1I1Y0dVdWMzQnNhWFJnSUdGdVpDQmpZVzRnWW1VZ2RYTmxaQ0J5Wld4cFlXSnNlVnh1SUNvZ1kzSnZjM010WW5KdmQzTmxjaTVjYmlBcUlFQndZWEpoYlNCN1UzUnlhVzVuZlNCemRISWdVM1J5YVc1bklIUnZJSE53YkdsMExseHVJQ29nUUhCaGNtRnRJSHRTWldkRmVIQjhVM1J5YVc1bmZTQnpaWEJoY21GMGIzSWdVbVZuWlhnZ2IzSWdjM1J5YVc1bklIUnZJSFZ6WlNCbWIzSWdjMlZ3WVhKaGRHbHVaeUIwYUdVZ2MzUnlhVzVuTGx4dUlDb2dRSEJoY21GdElIdE9kVzFpWlhKOUlGdHNhVzFwZEYwZ1RXRjRhVzExYlNCdWRXMWlaWElnYjJZZ2FYUmxiWE1nZEc4Z2FXNWpiSFZrWlNCcGJpQjBhR1VnY21WemRXeDBJR0Z5Y21GNUxseHVJQ29nUUhKbGRIVnlibk1nZTBGeWNtRjVmU0JCY25KaGVTQnZaaUJ6ZFdKemRISnBibWR6TGx4dUlDb2dRR1Y0WVcxd2JHVmNiaUFxWEc0Z0tpQXZMeUJDWVhOcFl5QjFjMlZjYmlBcUlITndiR2wwS0NkaElHSWdZeUJrSnl3Z0p5QW5LVHRjYmlBcUlDOHZJQzArSUZzbllTY3NJQ2RpSnl3Z0oyTW5MQ0FuWkNkZFhHNGdLbHh1SUNvZ0x5OGdWMmwwYUNCc2FXMXBkRnh1SUNvZ2MzQnNhWFFvSjJFZ1lpQmpJR1FuTENBbklDY3NJRElwTzF4dUlDb2dMeThnTFQ0Z1d5ZGhKeXdnSjJJblhWeHVJQ3BjYmlBcUlDOHZJRUpoWTJ0eVpXWmxjbVZ1WTJWeklHbHVJSEpsYzNWc2RDQmhjbkpoZVZ4dUlDb2djM0JzYVhRb0p5NHVkMjl5WkRFZ2QyOXlaREl1TGljc0lDOG9XMkV0ZWwwcktTaGNYR1FyS1M5cEtUdGNiaUFxSUM4dklDMCtJRnNuTGk0bkxDQW5kMjl5WkNjc0lDY3hKeXdnSnlBbkxDQW5kMjl5WkNjc0lDY3lKeXdnSnk0dUoxMWNiaUFxTDF4dWJXOWtkV3hsTG1WNGNHOXlkSE1nUFNBb1puVnVZM1JwYjI0Z2MzQnNhWFFvZFc1a1pXWXBJSHRjYmx4dUlDQjJZWElnYm1GMGFYWmxVM0JzYVhRZ1BTQlRkSEpwYm1jdWNISnZkRzkwZVhCbExuTndiR2wwTEZ4dUlDQWdJR052YlhCc2FXRnVkRVY0WldOT2NHTm5JRDBnTHlncFB6OHZMbVY0WldNb1hDSmNJaWxiTVYwZ1BUMDlJSFZ1WkdWbUxGeHVJQ0FnSUM4dklFNVFRMGM2SUc1dmJuQmhjblJwWTJsd1lYUnBibWNnWTJGd2RIVnlhVzVuSUdkeWIzVndYRzRnSUNBZ2MyVnNaanRjYmx4dUlDQnpaV3htSUQwZ1puVnVZM1JwYjI0b2MzUnlMQ0J6WlhCaGNtRjBiM0lzSUd4cGJXbDBLU0I3WEc0Z0lDQWdMeThnU1dZZ1lITmxjR0Z5WVhSdmNtQWdhWE1nYm05MElHRWdjbVZuWlhnc0lIVnpaU0JnYm1GMGFYWmxVM0JzYVhSZ1hHNGdJQ0FnYVdZZ0tFOWlhbVZqZEM1d2NtOTBiM1I1Y0dVdWRHOVRkSEpwYm1jdVkyRnNiQ2h6WlhCaGNtRjBiM0lwSUNFOVBTQmNJbHR2WW1wbFkzUWdVbVZuUlhod1hWd2lLU0I3WEc0Z0lDQWdJQ0J5WlhSMWNtNGdibUYwYVhabFUzQnNhWFF1WTJGc2JDaHpkSElzSUhObGNHRnlZWFJ2Y2l3Z2JHbHRhWFFwTzF4dUlDQWdJSDFjYmlBZ0lDQjJZWElnYjNWMGNIVjBJRDBnVzEwc1hHNGdJQ0FnSUNCbWJHRm5jeUE5SUNoelpYQmhjbUYwYjNJdWFXZHViM0psUTJGelpTQS9JRndpYVZ3aUlEb2dYQ0pjSWlrZ0t5QW9jMlZ3WVhKaGRHOXlMbTExYkhScGJHbHVaU0EvSUZ3aWJWd2lJRG9nWENKY0lpa2dLeUFvYzJWd1lYSmhkRzl5TG1WNGRHVnVaR1ZrSUQ4Z1hDSjRYQ0lnT2lCY0lsd2lLU0FySUM4dklGQnliM0J2YzJWa0lHWnZjaUJGVXpaY2JpQWdJQ0FnSUNoelpYQmhjbUYwYjNJdWMzUnBZMnQ1SUQ4Z1hDSjVYQ0lnT2lCY0lsd2lLU3hjYmlBZ0lDQWdJQzh2SUVacGNtVm1iM2dnTXl0Y2JpQWdJQ0FnSUd4aGMzUk1ZWE4wU1c1a1pYZ2dQU0F3TEZ4dUlDQWdJQ0FnTHk4Z1RXRnJaU0JnWjJ4dlltRnNZQ0JoYm1RZ1lYWnZhV1FnWUd4aGMzUkpibVJsZUdBZ2FYTnpkV1Z6SUdKNUlIZHZjbXRwYm1jZ2QybDBhQ0JoSUdOdmNIbGNiaUFnSUNBZ0lITmxjR0Z5WVhSdmNpQTlJRzVsZHlCU1pXZEZlSEFvYzJWd1lYSmhkRzl5TG5OdmRYSmpaU3dnWm14aFozTWdLeUJjSW1kY0lpa3NYRzRnSUNBZ0lDQnpaWEJoY21GMGIzSXlMQ0J0WVhSamFDd2diR0Z6ZEVsdVpHVjRMQ0JzWVhOMFRHVnVaM1JvTzF4dUlDQWdJSE4wY2lBclBTQmNJbHdpT3lBdkx5QlVlWEJsTFdOdmJuWmxjblJjYmlBZ0lDQnBaaUFvSVdOdmJYQnNhV0Z1ZEVWNFpXTk9jR05uS1NCN1hHNGdJQ0FnSUNBdkx5QkViMlZ6YmlkMElHNWxaV1FnWm14aFozTWdaM2tzSUdKMWRDQjBhR1Y1SUdSdmJpZDBJR2gxY25SY2JpQWdJQ0FnSUhObGNHRnlZWFJ2Y2pJZ1BTQnVaWGNnVW1WblJYaHdLRndpWGx3aUlDc2djMlZ3WVhKaGRHOXlMbk52ZFhKalpTQXJJRndpSkNnL0lWeGNYRnh6S1Z3aUxDQm1iR0ZuY3lrN1hHNGdJQ0FnZlZ4dUlDQWdJQzhxSUZaaGJIVmxjeUJtYjNJZ1lHeHBiV2wwWUN3Z2NHVnlJSFJvWlNCemNHVmpPbHh1SUNBZ0lDQXFJRWxtSUhWdVpHVm1hVzVsWkRvZ05ESTVORGsyTnpJNU5TQXZMeUJOWVhSb0xuQnZkeWd5TENBek1pa2dMU0F4WEc0Z0lDQWdJQ29nU1dZZ01Dd2dTVzVtYVc1cGRIa3NJRzl5SUU1aFRqb2dNRnh1SUNBZ0lDQXFJRWxtSUhCdmMybDBhWFpsSUc1MWJXSmxjam9nYkdsdGFYUWdQU0JOWVhSb0xtWnNiMjl5S0d4cGJXbDBLVHNnYVdZZ0tHeHBiV2wwSUQ0Z05ESTVORGsyTnpJNU5Ta2diR2x0YVhRZ0xUMGdOREk1TkRrMk56STVOanRjYmlBZ0lDQWdLaUJKWmlCdVpXZGhkR2wyWlNCdWRXMWlaWEk2SURReU9UUTVOamN5T1RZZ0xTQk5ZWFJvTG1ac2IyOXlLRTFoZEdndVlXSnpLR3hwYldsMEtTbGNiaUFnSUNBZ0tpQkpaaUJ2ZEdobGNqb2dWSGx3WlMxamIyNTJaWEowTENCMGFHVnVJSFZ6WlNCMGFHVWdZV0p2ZG1VZ2NuVnNaWE5jYmlBZ0lDQWdLaTljYmlBZ0lDQnNhVzFwZENBOUlHeHBiV2wwSUQwOVBTQjFibVJsWmlBL0lDMHhJRDQrUGlBd0lEb2dMeThnVFdGMGFDNXdiM2NvTWl3Z016SXBJQzBnTVZ4dUlDQWdJR3hwYldsMElENCtQaUF3T3lBdkx5QlViMVZwYm5Rek1paHNhVzFwZENsY2JpQWdJQ0IzYUdsc1pTQW9iV0YwWTJnZ1BTQnpaWEJoY21GMGIzSXVaWGhsWXloemRISXBLU0I3WEc0Z0lDQWdJQ0F2THlCZ2MyVndZWEpoZEc5eUxteGhjM1JKYm1SbGVHQWdhWE1nYm05MElISmxiR2xoWW14bElHTnliM056TFdKeWIzZHpaWEpjYmlBZ0lDQWdJR3hoYzNSSmJtUmxlQ0E5SUcxaGRHTm9MbWx1WkdWNElDc2diV0YwWTJoYk1GMHViR1Z1WjNSb08xeHVJQ0FnSUNBZ2FXWWdLR3hoYzNSSmJtUmxlQ0ErSUd4aGMzUk1ZWE4wU1c1a1pYZ3BJSHRjYmlBZ0lDQWdJQ0FnYjNWMGNIVjBMbkIxYzJnb2MzUnlMbk5zYVdObEtHeGhjM1JNWVhOMFNXNWtaWGdzSUcxaGRHTm9MbWx1WkdWNEtTazdYRzRnSUNBZ0lDQWdJQzh2SUVacGVDQmljbTkzYzJWeWN5QjNhRzl6WlNCZ1pYaGxZMkFnYldWMGFHOWtjeUJrYjI0bmRDQmpiMjV6YVhOMFpXNTBiSGtnY21WMGRYSnVJR0IxYm1SbFptbHVaV1JnSUdadmNseHVJQ0FnSUNBZ0lDQXZMeUJ1YjI1d1lYSjBhV05wY0dGMGFXNW5JR05oY0hSMWNtbHVaeUJuY205MWNITmNiaUFnSUNBZ0lDQWdhV1lnS0NGamIyMXdiR2xoYm5SRmVHVmpUbkJqWnlBbUppQnRZWFJqYUM1c1pXNW5kR2dnUGlBeEtTQjdYRzRnSUNBZ0lDQWdJQ0FnYldGMFkyaGJNRjB1Y21Wd2JHRmpaU2h6WlhCaGNtRjBiM0l5TENCbWRXNWpkR2x2YmlncElIdGNiaUFnSUNBZ0lDQWdJQ0FnSUdadmNpQW9kbUZ5SUdrZ1BTQXhPeUJwSUR3Z1lYSm5kVzFsYm5SekxteGxibWQwYUNBdElESTdJR2tyS3lrZ2UxeHVJQ0FnSUNBZ0lDQWdJQ0FnSUNCcFppQW9ZWEpuZFcxbGJuUnpXMmxkSUQwOVBTQjFibVJsWmlrZ2UxeHVJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lHMWhkR05vVzJsZElEMGdkVzVrWldZN1hHNGdJQ0FnSUNBZ0lDQWdJQ0FnSUgxY2JpQWdJQ0FnSUNBZ0lDQWdJSDFjYmlBZ0lDQWdJQ0FnSUNCOUtUdGNiaUFnSUNBZ0lDQWdmVnh1SUNBZ0lDQWdJQ0JwWmlBb2JXRjBZMmd1YkdWdVozUm9JRDRnTVNBbUppQnRZWFJqYUM1cGJtUmxlQ0E4SUhOMGNpNXNaVzVuZEdncElIdGNiaUFnSUNBZ0lDQWdJQ0JCY25KaGVTNXdjbTkwYjNSNWNHVXVjSFZ6YUM1aGNIQnNlU2h2ZFhSd2RYUXNJRzFoZEdOb0xuTnNhV05sS0RFcEtUdGNiaUFnSUNBZ0lDQWdmVnh1SUNBZ0lDQWdJQ0JzWVhOMFRHVnVaM1JvSUQwZ2JXRjBZMmhiTUYwdWJHVnVaM1JvTzF4dUlDQWdJQ0FnSUNCc1lYTjBUR0Z6ZEVsdVpHVjRJRDBnYkdGemRFbHVaR1Y0TzF4dUlDQWdJQ0FnSUNCcFppQW9iM1YwY0hWMExteGxibWQwYUNBK1BTQnNhVzFwZENrZ2UxeHVJQ0FnSUNBZ0lDQWdJR0p5WldGck8xeHVJQ0FnSUNBZ0lDQjlYRzRnSUNBZ0lDQjlYRzRnSUNBZ0lDQnBaaUFvYzJWd1lYSmhkRzl5TG14aGMzUkpibVJsZUNBOVBUMGdiV0YwWTJndWFXNWtaWGdwSUh0Y2JpQWdJQ0FnSUNBZ2MyVndZWEpoZEc5eUxteGhjM1JKYm1SbGVDc3JPeUF2THlCQmRtOXBaQ0JoYmlCcGJtWnBibWwwWlNCc2IyOXdYRzRnSUNBZ0lDQjlYRzRnSUNBZ2ZWeHVJQ0FnSUdsbUlDaHNZWE4wVEdGemRFbHVaR1Y0SUQwOVBTQnpkSEl1YkdWdVozUm9LU0I3WEc0Z0lDQWdJQ0JwWmlBb2JHRnpkRXhsYm1kMGFDQjhmQ0FoYzJWd1lYSmhkRzl5TG5SbGMzUW9YQ0pjSWlrcElIdGNiaUFnSUNBZ0lDQWdiM1YwY0hWMExuQjFjMmdvWENKY0lpazdYRzRnSUNBZ0lDQjlYRzRnSUNBZ2ZTQmxiSE5sSUh0Y2JpQWdJQ0FnSUc5MWRIQjFkQzV3ZFhOb0tITjBjaTV6YkdsalpTaHNZWE4wVEdGemRFbHVaR1Y0S1NrN1hHNGdJQ0FnZlZ4dUlDQWdJSEpsZEhWeWJpQnZkWFJ3ZFhRdWJHVnVaM1JvSUQ0Z2JHbHRhWFFnUHlCdmRYUndkWFF1YzJ4cFkyVW9NQ3dnYkdsdGFYUXBJRG9nYjNWMGNIVjBPMXh1SUNCOU8xeHVYRzRnSUhKbGRIVnliaUJ6Wld4bU8xeHVmU2tvS1R0Y2JseHVmU3g3ZlYwc05qcGJablZ1WTNScGIyNG9jbVZ4ZFdseVpTeHRiMlIxYkdVc1pYaHdiM0owY3lsN1hHNWNibjBzZTMxZExEYzZXMloxYm1OMGFXOXVLSEpsY1hWcGNtVXNiVzlrZFd4bExHVjRjRzl5ZEhNcGUxeHVKM1Z6WlNCemRISnBZM1FuTzF4dVhHNTJZWElnVDI1bFZtVnljMmx2YmtOdmJuTjBjbUZwYm5RZ1BTQnlaWEYxYVhKbEtDZHBibVJwZG1sa2RXRnNMMjl1WlMxMlpYSnphVzl1SnlrN1hHNWNiblpoY2lCTldWOVdSVkpUU1U5T0lEMGdKemNuTzF4dVQyNWxWbVZ5YzJsdmJrTnZibk4wY21GcGJuUW9KMlYyTFhOMGIzSmxKeXdnVFZsZlZrVlNVMGxQVGlrN1hHNWNiblpoY2lCb1lYTm9TMlY1SUQwZ0oxOWZSVlpmVTFSUFVrVmZTMFZaUUNjZ0t5Qk5XVjlXUlZKVFNVOU9PMXh1WEc1dGIyUjFiR1V1Wlhod2IzSjBjeUE5SUVWMlUzUnZjbVU3WEc1Y2JtWjFibU4wYVc5dUlFVjJVM1J2Y21Vb1pXeGxiU2tnZTF4dUlDQWdJSFpoY2lCb1lYTm9JRDBnWld4bGJWdG9ZWE5vUzJWNVhUdGNibHh1SUNBZ0lHbG1JQ2doYUdGemFDa2dlMXh1SUNBZ0lDQWdJQ0JvWVhOb0lEMGdaV3hsYlZ0b1lYTm9TMlY1WFNBOUlIdDlPMXh1SUNBZ0lIMWNibHh1SUNBZ0lISmxkSFZ5YmlCb1lYTm9PMXh1ZlZ4dVhHNTlMSHRjSW1sdVpHbDJhV1IxWVd3dmIyNWxMWFpsY25OcGIyNWNJam81ZlYwc09EcGJablZ1WTNScGIyNG9jbVZ4ZFdseVpTeHRiMlIxYkdVc1pYaHdiM0owY3lsN1hHNG9ablZ1WTNScGIyNGdLR2RzYjJKaGJDbDdYRzRuZFhObElITjBjbWxqZENjN1hHNWNiaThxWjJ4dlltRnNJSGRwYm1SdmR5d2daMnh2WW1Gc0tpOWNibHh1ZG1GeUlISnZiM1FnUFNCMGVYQmxiMllnZDJsdVpHOTNJQ0U5UFNBbmRXNWtaV1pwYm1Wa0p5QS9YRzRnSUNBZ2QybHVaRzkzSURvZ2RIbHdaVzltSUdkc2IySmhiQ0FoUFQwZ0ozVnVaR1ZtYVc1bFpDY2dQMXh1SUNBZ0lHZHNiMkpoYkNBNklIdDlPMXh1WEc1dGIyUjFiR1V1Wlhod2IzSjBjeUE5SUVsdVpHbDJhV1IxWVd3N1hHNWNibVoxYm1OMGFXOXVJRWx1WkdsMmFXUjFZV3dvYTJWNUxDQjJZV3gxWlNrZ2UxeHVJQ0FnSUdsbUlDaHJaWGtnYVc0Z2NtOXZkQ2tnZTF4dUlDQWdJQ0FnSUNCeVpYUjFjbTRnY205dmRGdHJaWGxkTzF4dUlDQWdJSDFjYmx4dUlDQWdJSEp2YjNSYmEyVjVYU0E5SUhaaGJIVmxPMXh1WEc0Z0lDQWdjbVYwZFhKdUlIWmhiSFZsTzF4dWZWeHVYRzU5S1M1allXeHNLSFJvYVhNc2RIbHdaVzltSUdkc2IySmhiQ0FoUFQwZ1hDSjFibVJsWm1sdVpXUmNJaUEvSUdkc2IySmhiQ0E2SUhSNWNHVnZaaUJ6Wld4bUlDRTlQU0JjSW5WdVpHVm1hVzVsWkZ3aUlEOGdjMlZzWmlBNklIUjVjR1Z2WmlCM2FXNWtiM2NnSVQwOUlGd2lkVzVrWldacGJtVmtYQ0lnUHlCM2FXNWtiM2NnT2lCN2ZTbGNibjBzZTMxZExEazZXMloxYm1OMGFXOXVLSEpsY1hWcGNtVXNiVzlrZFd4bExHVjRjRzl5ZEhNcGUxeHVKM1Z6WlNCemRISnBZM1FuTzF4dVhHNTJZWElnU1c1a2FYWnBaSFZoYkNBOUlISmxjWFZwY21Vb0p5NHZhVzVrWlhndWFuTW5LVHRjYmx4dWJXOWtkV3hsTG1WNGNHOXlkSE1nUFNCUGJtVldaWEp6YVc5dU8xeHVYRzVtZFc1amRHbHZiaUJQYm1WV1pYSnphVzl1S0cxdlpIVnNaVTVoYldVc0lIWmxjbk5wYjI0c0lHUmxabUYxYkhSV1lXeDFaU2tnZTF4dUlDQWdJSFpoY2lCclpYa2dQU0FuWDE5SlRrUkpWa2xFVlVGTVgwOU9SVjlXUlZKVFNVOU9YeWNnS3lCdGIyUjFiR1ZPWVcxbE8xeHVJQ0FnSUhaaGNpQmxibVp2Y21ObFMyVjVJRDBnYTJWNUlDc2dKMTlGVGtaUFVrTkZYMU5KVGtkTVJWUlBUaWM3WEc1Y2JpQWdJQ0IyWVhJZ2RtVnljMmx2YmxaaGJIVmxJRDBnU1c1a2FYWnBaSFZoYkNobGJtWnZjbU5sUzJWNUxDQjJaWEp6YVc5dUtUdGNibHh1SUNBZ0lHbG1JQ2gyWlhKemFXOXVWbUZzZFdVZ0lUMDlJSFpsY25OcGIyNHBJSHRjYmlBZ0lDQWdJQ0FnZEdoeWIzY2dibVYzSUVWeWNtOXlLQ2REWVc0Z2IyNXNlU0JvWVhabElHOXVaU0JqYjNCNUlHOW1JQ2NnSzF4dUlDQWdJQ0FnSUNBZ0lDQWdiVzlrZFd4bFRtRnRaU0FySUNjdVhGeHVKeUFyWEc0Z0lDQWdJQ0FnSUNBZ0lDQW5XVzkxSUdGc2NtVmhaSGtnYUdGMlpTQjJaWEp6YVc5dUlDY2dLeUIyWlhKemFXOXVWbUZzZFdVZ0sxeHVJQ0FnSUNBZ0lDQWdJQ0FnSnlCcGJuTjBZV3hzWldRdVhGeHVKeUFyWEc0Z0lDQWdJQ0FnSUNBZ0lDQW5WR2hwY3lCdFpXRnVjeUI1YjNVZ1kyRnVibTkwSUdsdWMzUmhiR3dnZG1WeWMybHZiaUFuSUNzZ2RtVnljMmx2YmlrN1hHNGdJQ0FnZlZ4dVhHNGdJQ0FnY21WMGRYSnVJRWx1WkdsMmFXUjFZV3dvYTJWNUxDQmtaV1poZFd4MFZtRnNkV1VwTzF4dWZWeHVYRzU5TEh0Y0lpNHZhVzVrWlhndWFuTmNJam80ZlYwc01UQTZXMloxYm1OMGFXOXVLSEpsY1hWcGNtVXNiVzlrZFd4bExHVjRjRzl5ZEhNcGUxeHVLR1oxYm1OMGFXOXVJQ2huYkc5aVlXd3BlMXh1ZG1GeUlIUnZjRXhsZG1Wc0lEMGdkSGx3Wlc5bUlHZHNiMkpoYkNBaFBUMGdKM1Z1WkdWbWFXNWxaQ2NnUHlCbmJHOWlZV3dnT2x4dUlDQWdJSFI1Y0dWdlppQjNhVzVrYjNjZ0lUMDlJQ2QxYm1SbFptbHVaV1FuSUQ4Z2QybHVaRzkzSURvZ2UzMWNiblpoY2lCdGFXNUViMk1nUFNCeVpYRjFhWEpsS0NkdGFXNHRaRzlqZFcxbGJuUW5LVHRjYmx4dWFXWWdLSFI1Y0dWdlppQmtiMk4xYldWdWRDQWhQVDBnSjNWdVpHVm1hVzVsWkNjcElIdGNiaUFnSUNCdGIyUjFiR1V1Wlhod2IzSjBjeUE5SUdSdlkzVnRaVzUwTzF4dWZTQmxiSE5sSUh0Y2JpQWdJQ0IyWVhJZ1pHOWpZM2tnUFNCMGIzQk1aWFpsYkZzblgxOUhURTlDUVV4ZlJFOURWVTFGVGxSZlEwRkRTRVZBTkNkZE8xeHVYRzRnSUNBZ2FXWWdLQ0ZrYjJOamVTa2dlMXh1SUNBZ0lDQWdJQ0JrYjJOamVTQTlJSFJ2Y0V4bGRtVnNXeWRmWDBkTVQwSkJURjlFVDBOVlRVVk9WRjlEUVVOSVJVQTBKMTBnUFNCdGFXNUViMk03WEc0Z0lDQWdmVnh1WEc0Z0lDQWdiVzlrZFd4bExtVjRjRzl5ZEhNZ1BTQmtiMk5qZVR0Y2JuMWNibHh1ZlNrdVkyRnNiQ2gwYUdsekxIUjVjR1Z2WmlCbmJHOWlZV3dnSVQwOUlGd2lkVzVrWldacGJtVmtYQ0lnUHlCbmJHOWlZV3dnT2lCMGVYQmxiMllnYzJWc1ppQWhQVDBnWENKMWJtUmxabWx1WldSY0lpQS9JSE5sYkdZZ09pQjBlWEJsYjJZZ2QybHVaRzkzSUNFOVBTQmNJblZ1WkdWbWFXNWxaRndpSUQ4Z2QybHVaRzkzSURvZ2UzMHBYRzU5TEh0Y0ltMXBiaTFrYjJOMWJXVnVkRndpT2paOVhTd3hNVHBiWm5WdVkzUnBiMjRvY21WeGRXbHlaU3h0YjJSMWJHVXNaWGh3YjNKMGN5bDdYRzVjSW5WelpTQnpkSEpwWTNSY0lqdGNibHh1Ylc5a2RXeGxMbVY0Y0c5eWRITWdQU0JtZFc1amRHbHZiaUJwYzA5aWFtVmpkQ2g0S1NCN1hHNWNkSEpsZEhWeWJpQjBlWEJsYjJZZ2VDQTlQVDBnWENKdlltcGxZM1JjSWlBbUppQjRJQ0U5UFNCdWRXeHNPMXh1ZlR0Y2JseHVmU3g3ZlYwc01USTZXMloxYm1OMGFXOXVLSEpsY1hWcGNtVXNiVzlrZFd4bExHVjRjRzl5ZEhNcGUxeHVkbUZ5SUc1aGRHbDJaVWx6UVhKeVlYa2dQU0JCY25KaGVTNXBjMEZ5Y21GNVhHNTJZWElnZEc5VGRISnBibWNnUFNCUFltcGxZM1F1Y0hKdmRHOTBlWEJsTG5SdlUzUnlhVzVuWEc1Y2JtMXZaSFZzWlM1bGVIQnZjblJ6SUQwZ2JtRjBhWFpsU1hOQmNuSmhlU0I4ZkNCcGMwRnljbUY1WEc1Y2JtWjFibU4wYVc5dUlHbHpRWEp5WVhrb2IySnFLU0I3WEc0Z0lDQWdjbVYwZFhKdUlIUnZVM1J5YVc1bkxtTmhiR3dvYjJKcUtTQTlQVDBnWENKYmIySnFaV04wSUVGeWNtRjVYVndpWEc1OVhHNWNibjBzZTMxZExERXpPbHRtZFc1amRHbHZiaWh5WlhGMWFYSmxMRzF2WkhWc1pTeGxlSEJ2Y25SektYdGNiblpoY2lCd1lYUmphQ0E5SUhKbGNYVnBjbVVvWENJdUwzWmtiMjB2Y0dGMFkyZ3Vhbk5jSWlsY2JseHViVzlrZFd4bExtVjRjRzl5ZEhNZ1BTQndZWFJqYUZ4dVhHNTlMSHRjSWk0dmRtUnZiUzl3WVhSamFDNXFjMXdpT2pFNGZWMHNNVFE2VzJaMWJtTjBhVzl1S0hKbGNYVnBjbVVzYlc5a2RXeGxMR1Y0Y0c5eWRITXBlMXh1ZG1GeUlHbHpUMkpxWldOMElEMGdjbVZ4ZFdseVpTaGNJbWx6TFc5aWFtVmpkRndpS1Z4dWRtRnlJR2x6U0c5dmF5QTlJSEpsY1hWcGNtVW9YQ0l1TGk5MmJtOWtaUzlwY3kxMmFHOXZheTVxYzF3aUtWeHVYRzV0YjJSMWJHVXVaWGh3YjNKMGN5QTlJR0Z3Y0d4NVVISnZjR1Z5ZEdsbGMxeHVYRzVtZFc1amRHbHZiaUJoY0hCc2VWQnliM0JsY25ScFpYTW9ibTlrWlN3Z2NISnZjSE1zSUhCeVpYWnBiM1Z6S1NCN1hHNGdJQ0FnWm05eUlDaDJZWElnY0hKdmNFNWhiV1VnYVc0Z2NISnZjSE1wSUh0Y2JpQWdJQ0FnSUNBZ2RtRnlJSEJ5YjNCV1lXeDFaU0E5SUhCeWIzQnpXM0J5YjNCT1lXMWxYVnh1WEc0Z0lDQWdJQ0FnSUdsbUlDaHdjbTl3Vm1Gc2RXVWdQVDA5SUhWdVpHVm1hVzVsWkNrZ2UxeHVJQ0FnSUNBZ0lDQWdJQ0FnY21WdGIzWmxVSEp2Y0dWeWRIa29ibTlrWlN3Z2NISnZjRTVoYldVc0lIQnliM0JXWVd4MVpTd2djSEpsZG1sdmRYTXBPMXh1SUNBZ0lDQWdJQ0I5SUdWc2MyVWdhV1lnS0dselNHOXZheWh3Y205d1ZtRnNkV1VwS1NCN1hHNGdJQ0FnSUNBZ0lDQWdJQ0J5WlcxdmRtVlFjbTl3WlhKMGVTaHViMlJsTENCd2NtOXdUbUZ0WlN3Z2NISnZjRlpoYkhWbExDQndjbVYyYVc5MWN5bGNiaUFnSUNBZ0lDQWdJQ0FnSUdsbUlDaHdjbTl3Vm1Gc2RXVXVhRzl2YXlrZ2UxeHVJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lIQnliM0JXWVd4MVpTNW9iMjlyS0c1dlpHVXNYRzRnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUhCeWIzQk9ZVzFsTEZ4dUlDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQndjbVYyYVc5MWN5QS9JSEJ5WlhacGIzVnpXM0J5YjNCT1lXMWxYU0E2SUhWdVpHVm1hVzVsWkNsY2JpQWdJQ0FnSUNBZ0lDQWdJSDFjYmlBZ0lDQWdJQ0FnZlNCbGJITmxJSHRjYmlBZ0lDQWdJQ0FnSUNBZ0lHbG1JQ2hwYzA5aWFtVmpkQ2h3Y205d1ZtRnNkV1VwS1NCN1hHNGdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ2NHRjBZMmhQWW1wbFkzUW9ibTlrWlN3Z2NISnZjSE1zSUhCeVpYWnBiM1Z6TENCd2NtOXdUbUZ0WlN3Z2NISnZjRlpoYkhWbEtUdGNiaUFnSUNBZ0lDQWdJQ0FnSUgwZ1pXeHpaU0I3WEc0Z0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnYm05a1pWdHdjbTl3VG1GdFpWMGdQU0J3Y205d1ZtRnNkV1ZjYmlBZ0lDQWdJQ0FnSUNBZ0lIMWNiaUFnSUNBZ0lDQWdmVnh1SUNBZ0lIMWNibjFjYmx4dVpuVnVZM1JwYjI0Z2NtVnRiM1psVUhKdmNHVnlkSGtvYm05a1pTd2djSEp2Y0U1aGJXVXNJSEJ5YjNCV1lXeDFaU3dnY0hKbGRtbHZkWE1wSUh0Y2JpQWdJQ0JwWmlBb2NISmxkbWx2ZFhNcElIdGNiaUFnSUNBZ0lDQWdkbUZ5SUhCeVpYWnBiM1Z6Vm1Gc2RXVWdQU0J3Y21WMmFXOTFjMXR3Y205d1RtRnRaVjFjYmx4dUlDQWdJQ0FnSUNCcFppQW9JV2x6U0c5dmF5aHdjbVYyYVc5MWMxWmhiSFZsS1NrZ2UxeHVJQ0FnSUNBZ0lDQWdJQ0FnYVdZZ0tIQnliM0JPWVcxbElEMDlQU0JjSW1GMGRISnBZblYwWlhOY0lpa2dlMXh1SUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJR1p2Y2lBb2RtRnlJR0YwZEhKT1lXMWxJR2x1SUhCeVpYWnBiM1Z6Vm1Gc2RXVXBJSHRjYmlBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ2JtOWtaUzV5WlcxdmRtVkJkSFJ5YVdKMWRHVW9ZWFIwY2s1aGJXVXBYRzRnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdmVnh1SUNBZ0lDQWdJQ0FnSUNBZ2ZTQmxiSE5sSUdsbUlDaHdjbTl3VG1GdFpTQTlQVDBnWENKemRIbHNaVndpS1NCN1hHNGdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ1ptOXlJQ2gyWVhJZ2FTQnBiaUJ3Y21WMmFXOTFjMVpoYkhWbEtTQjdYRzRnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUc1dlpHVXVjM1I1YkdWYmFWMGdQU0JjSWx3aVhHNGdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ2ZWeHVJQ0FnSUNBZ0lDQWdJQ0FnZlNCbGJITmxJR2xtSUNoMGVYQmxiMllnY0hKbGRtbHZkWE5XWVd4MVpTQTlQVDBnWENKemRISnBibWRjSWlrZ2UxeHVJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lHNXZaR1ZiY0hKdmNFNWhiV1ZkSUQwZ1hDSmNJbHh1SUNBZ0lDQWdJQ0FnSUNBZ2ZTQmxiSE5sSUh0Y2JpQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNCdWIyUmxXM0J5YjNCT1lXMWxYU0E5SUc1MWJHeGNiaUFnSUNBZ0lDQWdJQ0FnSUgxY2JpQWdJQ0FnSUNBZ2ZTQmxiSE5sSUdsbUlDaHdjbVYyYVc5MWMxWmhiSFZsTG5WdWFHOXZheWtnZTF4dUlDQWdJQ0FnSUNBZ0lDQWdjSEpsZG1sdmRYTldZV3gxWlM1MWJtaHZiMnNvYm05a1pTd2djSEp2Y0U1aGJXVXNJSEJ5YjNCV1lXeDFaU2xjYmlBZ0lDQWdJQ0FnZlZ4dUlDQWdJSDFjYm4xY2JseHVablZ1WTNScGIyNGdjR0YwWTJoUFltcGxZM1FvYm05a1pTd2djSEp2Y0hNc0lIQnlaWFpwYjNWekxDQndjbTl3VG1GdFpTd2djSEp2Y0ZaaGJIVmxLU0I3WEc0Z0lDQWdkbUZ5SUhCeVpYWnBiM1Z6Vm1Gc2RXVWdQU0J3Y21WMmFXOTFjeUEvSUhCeVpYWnBiM1Z6VzNCeWIzQk9ZVzFsWFNBNklIVnVaR1ZtYVc1bFpGeHVYRzRnSUNBZ0x5OGdVMlYwSUdGMGRISnBZblYwWlhOY2JpQWdJQ0JwWmlBb2NISnZjRTVoYldVZ1BUMDlJRndpWVhSMGNtbGlkWFJsYzF3aUtTQjdYRzRnSUNBZ0lDQWdJR1p2Y2lBb2RtRnlJR0YwZEhKT1lXMWxJR2x1SUhCeWIzQldZV3gxWlNrZ2UxeHVJQ0FnSUNBZ0lDQWdJQ0FnZG1GeUlHRjBkSEpXWVd4MVpTQTlJSEJ5YjNCV1lXeDFaVnRoZEhSeVRtRnRaVjFjYmx4dUlDQWdJQ0FnSUNBZ0lDQWdhV1lnS0dGMGRISldZV3gxWlNBOVBUMGdkVzVrWldacGJtVmtLU0I3WEc0Z0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnYm05a1pTNXlaVzF2ZG1WQmRIUnlhV0oxZEdVb1lYUjBjazVoYldVcFhHNGdJQ0FnSUNBZ0lDQWdJQ0I5SUdWc2MyVWdlMXh1SUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJRzV2WkdVdWMyVjBRWFIwY21saWRYUmxLR0YwZEhKT1lXMWxMQ0JoZEhSeVZtRnNkV1VwWEc0Z0lDQWdJQ0FnSUNBZ0lDQjlYRzRnSUNBZ0lDQWdJSDFjYmx4dUlDQWdJQ0FnSUNCeVpYUjFjbTVjYmlBZ0lDQjlYRzVjYmlBZ0lDQnBaaWh3Y21WMmFXOTFjMVpoYkhWbElDWW1JR2x6VDJKcVpXTjBLSEJ5WlhacGIzVnpWbUZzZFdVcElDWW1YRzRnSUNBZ0lDQWdJR2RsZEZCeWIzUnZkSGx3WlNod2NtVjJhVzkxYzFaaGJIVmxLU0FoUFQwZ1oyVjBVSEp2ZEc5MGVYQmxLSEJ5YjNCV1lXeDFaU2twSUh0Y2JpQWdJQ0FnSUNBZ2JtOWtaVnR3Y205d1RtRnRaVjBnUFNCd2NtOXdWbUZzZFdWY2JpQWdJQ0FnSUNBZ2NtVjBkWEp1WEc0Z0lDQWdmVnh1WEc0Z0lDQWdhV1lnS0NGcGMwOWlhbVZqZENodWIyUmxXM0J5YjNCT1lXMWxYU2twSUh0Y2JpQWdJQ0FnSUNBZ2JtOWtaVnR3Y205d1RtRnRaVjBnUFNCN2ZWeHVJQ0FnSUgxY2JseHVJQ0FnSUhaaGNpQnlaWEJzWVdObGNpQTlJSEJ5YjNCT1lXMWxJRDA5UFNCY0luTjBlV3hsWENJZ1B5QmNJbHdpSURvZ2RXNWtaV1pwYm1Wa1hHNWNiaUFnSUNCbWIzSWdLSFpoY2lCcklHbHVJSEJ5YjNCV1lXeDFaU2tnZTF4dUlDQWdJQ0FnSUNCMllYSWdkbUZzZFdVZ1BTQndjbTl3Vm1Gc2RXVmJhMTFjYmlBZ0lDQWdJQ0FnYm05a1pWdHdjbTl3VG1GdFpWMWJhMTBnUFNBb2RtRnNkV1VnUFQwOUlIVnVaR1ZtYVc1bFpDa2dQeUJ5WlhCc1lXTmxjaUE2SUhaaGJIVmxYRzRnSUNBZ2ZWeHVmVnh1WEc1bWRXNWpkR2x2YmlCblpYUlFjbTkwYjNSNWNHVW9kbUZzZFdVcElIdGNiaUFnSUNCcFppQW9UMkpxWldOMExtZGxkRkJ5YjNSdmRIbHdaVTltS1NCN1hHNGdJQ0FnSUNBZ0lISmxkSFZ5YmlCUFltcGxZM1F1WjJWMFVISnZkRzkwZVhCbFQyWW9kbUZzZFdVcFhHNGdJQ0FnZlNCbGJITmxJR2xtSUNoMllXeDFaUzVmWDNCeWIzUnZYMThwSUh0Y2JpQWdJQ0FnSUNBZ2NtVjBkWEp1SUhaaGJIVmxMbDlmY0hKdmRHOWZYMXh1SUNBZ0lIMGdaV3h6WlNCcFppQW9kbUZzZFdVdVkyOXVjM1J5ZFdOMGIzSXBJSHRjYmlBZ0lDQWdJQ0FnY21WMGRYSnVJSFpoYkhWbExtTnZibk4wY25WamRHOXlMbkJ5YjNSdmRIbHdaVnh1SUNBZ0lIMWNibjFjYmx4dWZTeDdYQ0l1TGk5MmJtOWtaUzlwY3kxMmFHOXZheTVxYzF3aU9qSTJMRndpYVhNdGIySnFaV04wWENJNk1URjlYU3d4TlRwYlpuVnVZM1JwYjI0b2NtVnhkV2x5WlN4dGIyUjFiR1VzWlhod2IzSjBjeWw3WEc1MllYSWdaRzlqZFcxbGJuUWdQU0J5WlhGMWFYSmxLRndpWjJ4dlltRnNMMlJ2WTNWdFpXNTBYQ0lwWEc1Y2JuWmhjaUJoY0hCc2VWQnliM0JsY25ScFpYTWdQU0J5WlhGMWFYSmxLRndpTGk5aGNIQnNlUzF3Y205d1pYSjBhV1Z6WENJcFhHNWNiblpoY2lCcGMxWk9iMlJsSUQwZ2NtVnhkV2x5WlNoY0lpNHVMM1p1YjJSbEwybHpMWFp1YjJSbExtcHpYQ0lwWEc1MllYSWdhWE5XVkdWNGRDQTlJSEpsY1hWcGNtVW9YQ0l1TGk5MmJtOWtaUzlwY3kxMmRHVjRkQzVxYzF3aUtWeHVkbUZ5SUdselYybGtaMlYwSUQwZ2NtVnhkV2x5WlNoY0lpNHVMM1p1YjJSbEwybHpMWGRwWkdkbGRDNXFjMXdpS1Z4dWRtRnlJR2hoYm1Sc1pWUm9kVzVySUQwZ2NtVnhkV2x5WlNoY0lpNHVMM1p1YjJSbEwyaGhibVJzWlMxMGFIVnVheTVxYzF3aUtWeHVYRzV0YjJSMWJHVXVaWGh3YjNKMGN5QTlJR055WldGMFpVVnNaVzFsYm5SY2JseHVablZ1WTNScGIyNGdZM0psWVhSbFJXeGxiV1Z1ZENoMmJtOWtaU3dnYjNCMGN5a2dlMXh1SUNBZ0lIWmhjaUJrYjJNZ1BTQnZjSFJ6SUQ4Z2IzQjBjeTVrYjJOMWJXVnVkQ0I4ZkNCa2IyTjFiV1Z1ZENBNklHUnZZM1Z0Wlc1MFhHNGdJQ0FnZG1GeUlIZGhjbTRnUFNCdmNIUnpJRDhnYjNCMGN5NTNZWEp1SURvZ2JuVnNiRnh1WEc0Z0lDQWdkbTV2WkdVZ1BTQm9ZVzVrYkdWVWFIVnVheWgyYm05a1pTa3VZVnh1WEc0Z0lDQWdhV1lnS0dselYybGtaMlYwS0hadWIyUmxLU2tnZTF4dUlDQWdJQ0FnSUNCeVpYUjFjbTRnZG01dlpHVXVhVzVwZENncFhHNGdJQ0FnZlNCbGJITmxJR2xtSUNocGMxWlVaWGgwS0hadWIyUmxLU2tnZTF4dUlDQWdJQ0FnSUNCeVpYUjFjbTRnWkc5akxtTnlaV0YwWlZSbGVIUk9iMlJsS0hadWIyUmxMblJsZUhRcFhHNGdJQ0FnZlNCbGJITmxJR2xtSUNnaGFYTldUbTlrWlNoMmJtOWtaU2twSUh0Y2JpQWdJQ0FnSUNBZ2FXWWdLSGRoY200cElIdGNiaUFnSUNBZ0lDQWdJQ0FnSUhkaGNtNG9YQ0pKZEdWdElHbHpJRzV2ZENCaElIWmhiR2xrSUhacGNuUjFZV3dnWkc5dElHNXZaR1ZjSWl3Z2RtNXZaR1VwWEc0Z0lDQWdJQ0FnSUgxY2JpQWdJQ0FnSUNBZ2NtVjBkWEp1SUc1MWJHeGNiaUFnSUNCOVhHNWNiaUFnSUNCMllYSWdibTlrWlNBOUlDaDJibTlrWlM1dVlXMWxjM0JoWTJVZ1BUMDlJRzUxYkd3cElEOWNiaUFnSUNBZ0lDQWdaRzlqTG1OeVpXRjBaVVZzWlcxbGJuUW9kbTV2WkdVdWRHRm5UbUZ0WlNrZ09seHVJQ0FnSUNBZ0lDQmtiMk11WTNKbFlYUmxSV3hsYldWdWRFNVRLSFp1YjJSbExtNWhiV1Z6Y0dGalpTd2dkbTV2WkdVdWRHRm5UbUZ0WlNsY2JseHVJQ0FnSUhaaGNpQndjbTl3Y3lBOUlIWnViMlJsTG5CeWIzQmxjblJwWlhOY2JpQWdJQ0JoY0hCc2VWQnliM0JsY25ScFpYTW9ibTlrWlN3Z2NISnZjSE1wWEc1Y2JpQWdJQ0IyWVhJZ1kyaHBiR1J5Wlc0Z1BTQjJibTlrWlM1amFHbHNaSEpsYmx4dVhHNGdJQ0FnWm05eUlDaDJZWElnYVNBOUlEQTdJR2tnUENCamFHbHNaSEpsYmk1c1pXNW5kR2c3SUdrckt5a2dlMXh1SUNBZ0lDQWdJQ0IyWVhJZ1kyaHBiR1JPYjJSbElEMGdZM0psWVhSbFJXeGxiV1Z1ZENoamFHbHNaSEpsYmx0cFhTd2diM0IwY3lsY2JpQWdJQ0FnSUNBZ2FXWWdLR05vYVd4a1RtOWtaU2tnZTF4dUlDQWdJQ0FnSUNBZ0lDQWdibTlrWlM1aGNIQmxibVJEYUdsc1pDaGphR2xzWkU1dlpHVXBYRzRnSUNBZ0lDQWdJSDFjYmlBZ0lDQjlYRzVjYmlBZ0lDQnlaWFIxY200Z2JtOWtaVnh1ZlZ4dVhHNTlMSHRjSWk0dUwzWnViMlJsTDJoaGJtUnNaUzEwYUhWdWF5NXFjMXdpT2pJMExGd2lMaTR2ZG01dlpHVXZhWE10ZG01dlpHVXVhbk5jSWpveU55eGNJaTR1TDNadWIyUmxMMmx6TFhaMFpYaDBMbXB6WENJNk1qZ3NYQ0l1TGk5MmJtOWtaUzlwY3kxM2FXUm5aWFF1YW5OY0lqb3lPU3hjSWk0dllYQndiSGt0Y0hKdmNHVnlkR2xsYzF3aU9qRTBMRndpWjJ4dlltRnNMMlJ2WTNWdFpXNTBYQ0k2TVRCOVhTd3hOanBiWm5WdVkzUnBiMjRvY21WeGRXbHlaU3h0YjJSMWJHVXNaWGh3YjNKMGN5bDdYRzR2THlCTllYQnpJR0VnZG1seWRIVmhiQ0JFVDAwZ2RISmxaU0J2Ym5SdklHRWdjbVZoYkNCRVQwMGdkSEpsWlNCcGJpQmhiaUJsWm1acFkybGxiblFnYldGdWJtVnlMbHh1THk4Z1YyVWdaRzl1SjNRZ2QyRnVkQ0IwYnlCeVpXRmtJR0ZzYkNCdlppQjBhR1VnUkU5TklHNXZaR1Z6SUdsdUlIUm9aU0IwY21WbElITnZJSGRsSUhWelpWeHVMeThnZEdobElHbHVMVzl5WkdWeUlIUnlaV1VnYVc1a1pYaHBibWNnZEc4Z1pXeHBiV2x1WVhSbElISmxZM1Z5YzJsdmJpQmtiM2R1SUdObGNuUmhhVzRnWW5KaGJtTm9aWE11WEc0dkx5QlhaU0J2Ym14NUlISmxZM1Z5YzJVZ2FXNTBieUJoSUVSUFRTQnViMlJsSUdsbUlIZGxJR3R1YjNjZ2RHaGhkQ0JwZENCamIyNTBZV2x1Y3lCaElHTm9hV3hrSUc5bVhHNHZMeUJwYm5SbGNtVnpkQzVjYmx4dWRtRnlJRzV2UTJocGJHUWdQU0I3ZlZ4dVhHNXRiMlIxYkdVdVpYaHdiM0owY3lBOUlHUnZiVWx1WkdWNFhHNWNibVoxYm1OMGFXOXVJR1J2YlVsdVpHVjRLSEp2YjNST2IyUmxMQ0IwY21WbExDQnBibVJwWTJWekxDQnViMlJsY3lrZ2UxeHVJQ0FnSUdsbUlDZ2hhVzVrYVdObGN5QjhmQ0JwYm1ScFkyVnpMbXhsYm1kMGFDQTlQVDBnTUNrZ2UxeHVJQ0FnSUNBZ0lDQnlaWFIxY200Z2UzMWNiaUFnSUNCOUlHVnNjMlVnZTF4dUlDQWdJQ0FnSUNCcGJtUnBZMlZ6TG5OdmNuUW9ZWE5qWlc1a2FXNW5LVnh1SUNBZ0lDQWdJQ0J5WlhSMWNtNGdjbVZqZFhKelpTaHliMjkwVG05a1pTd2dkSEpsWlN3Z2FXNWthV05sY3l3Z2JtOWtaWE1zSURBcFhHNGdJQ0FnZlZ4dWZWeHVYRzVtZFc1amRHbHZiaUJ5WldOMWNuTmxLSEp2YjNST2IyUmxMQ0IwY21WbExDQnBibVJwWTJWekxDQnViMlJsY3l3Z2NtOXZkRWx1WkdWNEtTQjdYRzRnSUNBZ2JtOWtaWE1nUFNCdWIyUmxjeUI4ZkNCN2ZWeHVYRzVjYmlBZ0lDQnBaaUFvY205dmRFNXZaR1VwSUh0Y2JpQWdJQ0FnSUNBZ2FXWWdLR2x1WkdWNFNXNVNZVzVuWlNocGJtUnBZMlZ6TENCeWIyOTBTVzVrWlhnc0lISnZiM1JKYm1SbGVDa3BJSHRjYmlBZ0lDQWdJQ0FnSUNBZ0lHNXZaR1Z6VzNKdmIzUkpibVJsZUYwZ1BTQnliMjkwVG05a1pWeHVJQ0FnSUNBZ0lDQjlYRzVjYmlBZ0lDQWdJQ0FnZG1GeUlIWkRhR2xzWkhKbGJpQTlJSFJ5WldVdVkyaHBiR1J5Wlc1Y2JseHVJQ0FnSUNBZ0lDQnBaaUFvZGtOb2FXeGtjbVZ1S1NCN1hHNWNiaUFnSUNBZ0lDQWdJQ0FnSUhaaGNpQmphR2xzWkU1dlpHVnpJRDBnY205dmRFNXZaR1V1WTJocGJHUk9iMlJsYzF4dVhHNGdJQ0FnSUNBZ0lDQWdJQ0JtYjNJZ0tIWmhjaUJwSUQwZ01Ec2dhU0E4SUhSeVpXVXVZMmhwYkdSeVpXNHViR1Z1WjNSb095QnBLeXNwSUh0Y2JpQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNCeWIyOTBTVzVrWlhnZ0t6MGdNVnh1WEc0Z0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnZG1GeUlIWkRhR2xzWkNBOUlIWkRhR2xzWkhKbGJsdHBYU0I4ZkNCdWIwTm9hV3hrWEc0Z0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnZG1GeUlHNWxlSFJKYm1SbGVDQTlJSEp2YjNSSmJtUmxlQ0FySUNoMlEyaHBiR1F1WTI5MWJuUWdmSHdnTUNsY2JseHVJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDOHZJSE5yYVhBZ2NtVmpkWEp6YVc5dUlHUnZkMjRnZEdobElIUnlaV1VnYVdZZ2RHaGxjbVVnWVhKbElHNXZJRzV2WkdWeklHUnZkMjRnYUdWeVpWeHVJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lHbG1JQ2hwYm1SbGVFbHVVbUZ1WjJVb2FXNWthV05sY3l3Z2NtOXZkRWx1WkdWNExDQnVaWGgwU1c1a1pYZ3BLU0I3WEc0Z0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lISmxZM1Z5YzJVb1kyaHBiR1JPYjJSbGMxdHBYU3dnZGtOb2FXeGtMQ0JwYm1ScFkyVnpMQ0J1YjJSbGN5d2djbTl2ZEVsdVpHVjRLVnh1SUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJSDFjYmx4dUlDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUhKdmIzUkpibVJsZUNBOUlHNWxlSFJKYm1SbGVGeHVJQ0FnSUNBZ0lDQWdJQ0FnZlZ4dUlDQWdJQ0FnSUNCOVhHNGdJQ0FnZlZ4dVhHNGdJQ0FnY21WMGRYSnVJRzV2WkdWelhHNTlYRzVjYmk4dklFSnBibUZ5ZVNCelpXRnlZMmdnWm05eUlHRnVJR2x1WkdWNElHbHVJSFJvWlNCcGJuUmxjblpoYkNCYmJHVm1kQ3dnY21sbmFIUmRYRzVtZFc1amRHbHZiaUJwYm1SbGVFbHVVbUZ1WjJVb2FXNWthV05sY3l3Z2JHVm1kQ3dnY21sbmFIUXBJSHRjYmlBZ0lDQnBaaUFvYVc1a2FXTmxjeTVzWlc1bmRHZ2dQVDA5SURBcElIdGNiaUFnSUNBZ0lDQWdjbVYwZFhKdUlHWmhiSE5sWEc0Z0lDQWdmVnh1WEc0Z0lDQWdkbUZ5SUcxcGJrbHVaR1Y0SUQwZ01GeHVJQ0FnSUhaaGNpQnRZWGhKYm1SbGVDQTlJR2x1WkdsalpYTXViR1Z1WjNSb0lDMGdNVnh1SUNBZ0lIWmhjaUJqZFhKeVpXNTBTVzVrWlhoY2JpQWdJQ0IyWVhJZ1kzVnljbVZ1ZEVsMFpXMWNibHh1SUNBZ0lIZG9hV3hsSUNodGFXNUpibVJsZUNBOFBTQnRZWGhKYm1SbGVDa2dlMXh1SUNBZ0lDQWdJQ0JqZFhKeVpXNTBTVzVrWlhnZ1BTQW9LRzFoZUVsdVpHVjRJQ3NnYldsdVNXNWtaWGdwSUM4Z01pa2dQajRnTUZ4dUlDQWdJQ0FnSUNCamRYSnlaVzUwU1hSbGJTQTlJR2x1WkdsalpYTmJZM1Z5Y21WdWRFbHVaR1Y0WFZ4dVhHNGdJQ0FnSUNBZ0lHbG1JQ2h0YVc1SmJtUmxlQ0E5UFQwZ2JXRjRTVzVrWlhncElIdGNiaUFnSUNBZ0lDQWdJQ0FnSUhKbGRIVnliaUJqZFhKeVpXNTBTWFJsYlNBK1BTQnNaV1owSUNZbUlHTjFjbkpsYm5SSmRHVnRJRHc5SUhKcFoyaDBYRzRnSUNBZ0lDQWdJSDBnWld4elpTQnBaaUFvWTNWeWNtVnVkRWwwWlcwZ1BDQnNaV1owS1NCN1hHNGdJQ0FnSUNBZ0lDQWdJQ0J0YVc1SmJtUmxlQ0E5SUdOMWNuSmxiblJKYm1SbGVDQXJJREZjYmlBZ0lDQWdJQ0FnZlNCbGJITmxJQ0JwWmlBb1kzVnljbVZ1ZEVsMFpXMGdQaUJ5YVdkb2RDa2dlMXh1SUNBZ0lDQWdJQ0FnSUNBZ2JXRjRTVzVrWlhnZ1BTQmpkWEp5Wlc1MFNXNWtaWGdnTFNBeFhHNGdJQ0FnSUNBZ0lIMGdaV3h6WlNCN1hHNGdJQ0FnSUNBZ0lDQWdJQ0J5WlhSMWNtNGdkSEoxWlZ4dUlDQWdJQ0FnSUNCOVhHNGdJQ0FnZlZ4dVhHNGdJQ0FnY21WMGRYSnVJR1poYkhObE8xeHVmVnh1WEc1bWRXNWpkR2x2YmlCaGMyTmxibVJwYm1jb1lTd2dZaWtnZTF4dUlDQWdJSEpsZEhWeWJpQmhJRDRnWWlBL0lERWdPaUF0TVZ4dWZWeHVYRzU5TEh0OVhTd3hOenBiWm5WdVkzUnBiMjRvY21WeGRXbHlaU3h0YjJSMWJHVXNaWGh3YjNKMGN5bDdYRzUyWVhJZ1lYQndiSGxRY205d1pYSjBhV1Z6SUQwZ2NtVnhkV2x5WlNoY0lpNHZZWEJ3YkhrdGNISnZjR1Z5ZEdsbGMxd2lLVnh1WEc1MllYSWdhWE5YYVdSblpYUWdQU0J5WlhGMWFYSmxLRndpTGk0dmRtNXZaR1V2YVhNdGQybGtaMlYwTG1welhDSXBYRzUyWVhJZ1ZsQmhkR05vSUQwZ2NtVnhkV2x5WlNoY0lpNHVMM1p1YjJSbEwzWndZWFJqYUM1cWMxd2lLVnh1WEc1MllYSWdkWEJrWVhSbFYybGtaMlYwSUQwZ2NtVnhkV2x5WlNoY0lpNHZkWEJrWVhSbExYZHBaR2RsZEZ3aUtWeHVYRzV0YjJSMWJHVXVaWGh3YjNKMGN5QTlJR0Z3Y0d4NVVHRjBZMmhjYmx4dVpuVnVZM1JwYjI0Z1lYQndiSGxRWVhSamFDaDJjR0YwWTJnc0lHUnZiVTV2WkdVc0lISmxibVJsY2s5d2RHbHZibk1wSUh0Y2JpQWdJQ0IyWVhJZ2RIbHdaU0E5SUhad1lYUmphQzUwZVhCbFhHNGdJQ0FnZG1GeUlIWk9iMlJsSUQwZ2RuQmhkR05vTG5aT2IyUmxYRzRnSUNBZ2RtRnlJSEJoZEdOb0lEMGdkbkJoZEdOb0xuQmhkR05vWEc1Y2JpQWdJQ0J6ZDJsMFkyZ2dLSFI1Y0dVcElIdGNiaUFnSUNBZ0lDQWdZMkZ6WlNCV1VHRjBZMmd1VWtWTlQxWkZPbHh1SUNBZ0lDQWdJQ0FnSUNBZ2NtVjBkWEp1SUhKbGJXOTJaVTV2WkdVb1pHOXRUbTlrWlN3Z2RrNXZaR1VwWEc0Z0lDQWdJQ0FnSUdOaGMyVWdWbEJoZEdOb0xrbE9VMFZTVkRwY2JpQWdJQ0FnSUNBZ0lDQWdJSEpsZEhWeWJpQnBibk5sY25ST2IyUmxLR1J2YlU1dlpHVXNJSEJoZEdOb0xDQnlaVzVrWlhKUGNIUnBiMjV6S1Z4dUlDQWdJQ0FnSUNCallYTmxJRlpRWVhSamFDNVdWRVZZVkRwY2JpQWdJQ0FnSUNBZ0lDQWdJSEpsZEhWeWJpQnpkSEpwYm1kUVlYUmphQ2hrYjIxT2IyUmxMQ0IyVG05a1pTd2djR0YwWTJnc0lISmxibVJsY2s5d2RHbHZibk1wWEc0Z0lDQWdJQ0FnSUdOaGMyVWdWbEJoZEdOb0xsZEpSRWRGVkRwY2JpQWdJQ0FnSUNBZ0lDQWdJSEpsZEhWeWJpQjNhV1JuWlhSUVlYUmphQ2hrYjIxT2IyUmxMQ0IyVG05a1pTd2djR0YwWTJnc0lISmxibVJsY2s5d2RHbHZibk1wWEc0Z0lDQWdJQ0FnSUdOaGMyVWdWbEJoZEdOb0xsWk9UMFJGT2x4dUlDQWdJQ0FnSUNBZ0lDQWdjbVYwZFhKdUlIWk9iMlJsVUdGMFkyZ29aRzl0VG05a1pTd2dkazV2WkdVc0lIQmhkR05vTENCeVpXNWtaWEpQY0hScGIyNXpLVnh1SUNBZ0lDQWdJQ0JqWVhObElGWlFZWFJqYUM1UFVrUkZVanBjYmlBZ0lDQWdJQ0FnSUNBZ0lISmxiM0prWlhKRGFHbHNaSEpsYmloa2IyMU9iMlJsTENCd1lYUmphQ2xjYmlBZ0lDQWdJQ0FnSUNBZ0lISmxkSFZ5YmlCa2IyMU9iMlJsWEc0Z0lDQWdJQ0FnSUdOaGMyVWdWbEJoZEdOb0xsQlNUMUJUT2x4dUlDQWdJQ0FnSUNBZ0lDQWdZWEJ3YkhsUWNtOXdaWEowYVdWektHUnZiVTV2WkdVc0lIQmhkR05vTENCMlRtOWtaUzV3Y205d1pYSjBhV1Z6S1Z4dUlDQWdJQ0FnSUNBZ0lDQWdjbVYwZFhKdUlHUnZiVTV2WkdWY2JpQWdJQ0FnSUNBZ1kyRnpaU0JXVUdGMFkyZ3VWRWhWVGtzNlhHNGdJQ0FnSUNBZ0lDQWdJQ0J5WlhSMWNtNGdjbVZ3YkdGalpWSnZiM1FvWkc5dFRtOWtaU3hjYmlBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0J5Wlc1a1pYSlBjSFJwYjI1ekxuQmhkR05vS0dSdmJVNXZaR1VzSUhCaGRHTm9MQ0J5Wlc1a1pYSlBjSFJwYjI1ektTbGNiaUFnSUNBZ0lDQWdaR1ZtWVhWc2REcGNiaUFnSUNBZ0lDQWdJQ0FnSUhKbGRIVnliaUJrYjIxT2IyUmxYRzRnSUNBZ2ZWeHVmVnh1WEc1bWRXNWpkR2x2YmlCeVpXMXZkbVZPYjJSbEtHUnZiVTV2WkdVc0lIWk9iMlJsS1NCN1hHNGdJQ0FnZG1GeUlIQmhjbVZ1ZEU1dlpHVWdQU0JrYjIxT2IyUmxMbkJoY21WdWRFNXZaR1ZjYmx4dUlDQWdJR2xtSUNod1lYSmxiblJPYjJSbEtTQjdYRzRnSUNBZ0lDQWdJSEJoY21WdWRFNXZaR1V1Y21WdGIzWmxRMmhwYkdRb1pHOXRUbTlrWlNsY2JpQWdJQ0I5WEc1Y2JpQWdJQ0JrWlhOMGNtOTVWMmxrWjJWMEtHUnZiVTV2WkdVc0lIWk9iMlJsS1R0Y2JseHVJQ0FnSUhKbGRIVnliaUJ1ZFd4c1hHNTlYRzVjYm1aMWJtTjBhVzl1SUdsdWMyVnlkRTV2WkdVb2NHRnlaVzUwVG05a1pTd2dkazV2WkdVc0lISmxibVJsY2s5d2RHbHZibk1wSUh0Y2JpQWdJQ0IyWVhJZ2JtVjNUbTlrWlNBOUlISmxibVJsY2s5d2RHbHZibk11Y21WdVpHVnlLSFpPYjJSbExDQnlaVzVrWlhKUGNIUnBiMjV6S1Z4dVhHNGdJQ0FnYVdZZ0tIQmhjbVZ1ZEU1dlpHVXBJSHRjYmlBZ0lDQWdJQ0FnY0dGeVpXNTBUbTlrWlM1aGNIQmxibVJEYUdsc1pDaHVaWGRPYjJSbEtWeHVJQ0FnSUgxY2JseHVJQ0FnSUhKbGRIVnliaUJ3WVhKbGJuUk9iMlJsWEc1OVhHNWNibVoxYm1OMGFXOXVJSE4wY21sdVoxQmhkR05vS0dSdmJVNXZaR1VzSUd4bFpuUldUbTlrWlN3Z2RsUmxlSFFzSUhKbGJtUmxjazl3ZEdsdmJuTXBJSHRjYmlBZ0lDQjJZWElnYm1WM1RtOWtaVnh1WEc0Z0lDQWdhV1lnS0dSdmJVNXZaR1V1Ym05a1pWUjVjR1VnUFQwOUlETXBJSHRjYmlBZ0lDQWdJQ0FnWkc5dFRtOWtaUzV5WlhCc1lXTmxSR0YwWVNnd0xDQmtiMjFPYjJSbExteGxibWQwYUN3Z2RsUmxlSFF1ZEdWNGRDbGNiaUFnSUNBZ0lDQWdibVYzVG05a1pTQTlJR1J2YlU1dlpHVmNiaUFnSUNCOUlHVnNjMlVnZTF4dUlDQWdJQ0FnSUNCMllYSWdjR0Z5Wlc1MFRtOWtaU0E5SUdSdmJVNXZaR1V1Y0dGeVpXNTBUbTlrWlZ4dUlDQWdJQ0FnSUNCdVpYZE9iMlJsSUQwZ2NtVnVaR1Z5VDNCMGFXOXVjeTV5Wlc1a1pYSW9kbFJsZUhRc0lISmxibVJsY2s5d2RHbHZibk1wWEc1Y2JpQWdJQ0FnSUNBZ2FXWWdLSEJoY21WdWRFNXZaR1VnSmlZZ2JtVjNUbTlrWlNBaFBUMGdaRzl0VG05a1pTa2dlMXh1SUNBZ0lDQWdJQ0FnSUNBZ2NHRnlaVzUwVG05a1pTNXlaWEJzWVdObFEyaHBiR1FvYm1WM1RtOWtaU3dnWkc5dFRtOWtaU2xjYmlBZ0lDQWdJQ0FnZlZ4dUlDQWdJSDFjYmx4dUlDQWdJSEpsZEhWeWJpQnVaWGRPYjJSbFhHNTlYRzVjYm1aMWJtTjBhVzl1SUhkcFpHZGxkRkJoZEdOb0tHUnZiVTV2WkdVc0lHeGxablJXVG05a1pTd2dkMmxrWjJWMExDQnlaVzVrWlhKUGNIUnBiMjV6S1NCN1hHNGdJQ0FnZG1GeUlIVndaR0YwYVc1bklEMGdkWEJrWVhSbFYybGtaMlYwS0d4bFpuUldUbTlrWlN3Z2QybGtaMlYwS1Z4dUlDQWdJSFpoY2lCdVpYZE9iMlJsWEc1Y2JpQWdJQ0JwWmlBb2RYQmtZWFJwYm1jcElIdGNiaUFnSUNBZ0lDQWdibVYzVG05a1pTQTlJSGRwWkdkbGRDNTFjR1JoZEdVb2JHVm1kRlpPYjJSbExDQmtiMjFPYjJSbEtTQjhmQ0JrYjIxT2IyUmxYRzRnSUNBZ2ZTQmxiSE5sSUh0Y2JpQWdJQ0FnSUNBZ2JtVjNUbTlrWlNBOUlISmxibVJsY2s5d2RHbHZibk11Y21WdVpHVnlLSGRwWkdkbGRDd2djbVZ1WkdWeVQzQjBhVzl1Y3lsY2JpQWdJQ0I5WEc1Y2JpQWdJQ0IyWVhJZ2NHRnlaVzUwVG05a1pTQTlJR1J2YlU1dlpHVXVjR0Z5Wlc1MFRtOWtaVnh1WEc0Z0lDQWdhV1lnS0hCaGNtVnVkRTV2WkdVZ0ppWWdibVYzVG05a1pTQWhQVDBnWkc5dFRtOWtaU2tnZTF4dUlDQWdJQ0FnSUNCd1lYSmxiblJPYjJSbExuSmxjR3hoWTJWRGFHbHNaQ2h1WlhkT2IyUmxMQ0JrYjIxT2IyUmxLVnh1SUNBZ0lIMWNibHh1SUNBZ0lHbG1JQ2doZFhCa1lYUnBibWNwSUh0Y2JpQWdJQ0FnSUNBZ1pHVnpkSEp2ZVZkcFpHZGxkQ2hrYjIxT2IyUmxMQ0JzWldaMFZrNXZaR1VwWEc0Z0lDQWdmVnh1WEc0Z0lDQWdjbVYwZFhKdUlHNWxkMDV2WkdWY2JuMWNibHh1Wm5WdVkzUnBiMjRnZGs1dlpHVlFZWFJqYUNoa2IyMU9iMlJsTENCc1pXWjBWazV2WkdVc0lIWk9iMlJsTENCeVpXNWtaWEpQY0hScGIyNXpLU0I3WEc0Z0lDQWdkbUZ5SUhCaGNtVnVkRTV2WkdVZ1BTQmtiMjFPYjJSbExuQmhjbVZ1ZEU1dlpHVmNiaUFnSUNCMllYSWdibVYzVG05a1pTQTlJSEpsYm1SbGNrOXdkR2x2Ym5NdWNtVnVaR1Z5S0haT2IyUmxMQ0J5Wlc1a1pYSlBjSFJwYjI1ektWeHVYRzRnSUNBZ2FXWWdLSEJoY21WdWRFNXZaR1VnSmlZZ2JtVjNUbTlrWlNBaFBUMGdaRzl0VG05a1pTa2dlMXh1SUNBZ0lDQWdJQ0J3WVhKbGJuUk9iMlJsTG5KbGNHeGhZMlZEYUdsc1pDaHVaWGRPYjJSbExDQmtiMjFPYjJSbEtWeHVJQ0FnSUgxY2JseHVJQ0FnSUhKbGRIVnliaUJ1WlhkT2IyUmxYRzU5WEc1Y2JtWjFibU4wYVc5dUlHUmxjM1J5YjNsWGFXUm5aWFFvWkc5dFRtOWtaU3dnZHlrZ2UxeHVJQ0FnSUdsbUlDaDBlWEJsYjJZZ2R5NWtaWE4wY205NUlEMDlQU0JjSW1aMWJtTjBhVzl1WENJZ0ppWWdhWE5YYVdSblpYUW9keWtwSUh0Y2JpQWdJQ0FnSUNBZ2R5NWtaWE4wY205NUtHUnZiVTV2WkdVcFhHNGdJQ0FnZlZ4dWZWeHVYRzVtZFc1amRHbHZiaUJ5Wlc5eVpHVnlRMmhwYkdSeVpXNG9aRzl0VG05a1pTd2diVzkyWlhNcElIdGNiaUFnSUNCMllYSWdZMmhwYkdST2IyUmxjeUE5SUdSdmJVNXZaR1V1WTJocGJHUk9iMlJsYzF4dUlDQWdJSFpoY2lCclpYbE5ZWEFnUFNCN2ZWeHVJQ0FnSUhaaGNpQnViMlJsWEc0Z0lDQWdkbUZ5SUhKbGJXOTJaVnh1SUNBZ0lIWmhjaUJwYm5ObGNuUmNibHh1SUNBZ0lHWnZjaUFvZG1GeUlHa2dQU0F3T3lCcElEd2diVzkyWlhNdWNtVnRiM1psY3k1c1pXNW5kR2c3SUdrckt5a2dlMXh1SUNBZ0lDQWdJQ0J5WlcxdmRtVWdQU0J0YjNabGN5NXlaVzF2ZG1WelcybGRYRzRnSUNBZ0lDQWdJRzV2WkdVZ1BTQmphR2xzWkU1dlpHVnpXM0psYlc5MlpTNW1jbTl0WFZ4dUlDQWdJQ0FnSUNCcFppQW9jbVZ0YjNabExtdGxlU2tnZTF4dUlDQWdJQ0FnSUNBZ0lDQWdhMlY1VFdGd1czSmxiVzkyWlM1clpYbGRJRDBnYm05a1pWeHVJQ0FnSUNBZ0lDQjlYRzRnSUNBZ0lDQWdJR1J2YlU1dlpHVXVjbVZ0YjNabFEyaHBiR1FvYm05a1pTbGNiaUFnSUNCOVhHNWNiaUFnSUNCMllYSWdiR1Z1WjNSb0lEMGdZMmhwYkdST2IyUmxjeTVzWlc1bmRHaGNiaUFnSUNCbWIzSWdLSFpoY2lCcUlEMGdNRHNnYWlBOElHMXZkbVZ6TG1sdWMyVnlkSE11YkdWdVozUm9PeUJxS3lzcElIdGNiaUFnSUNBZ0lDQWdhVzV6WlhKMElEMGdiVzkyWlhNdWFXNXpaWEowYzF0cVhWeHVJQ0FnSUNBZ0lDQnViMlJsSUQwZ2EyVjVUV0Z3VzJsdWMyVnlkQzVyWlhsZFhHNGdJQ0FnSUNBZ0lDOHZJSFJvYVhNZ2FYTWdkR2hsSUhkbGFYSmtaWE4wSUdKMVp5QnBKM1psSUdWMlpYSWdjMlZsYmlCcGJpQjNaV0pyYVhSY2JpQWdJQ0FnSUNBZ1pHOXRUbTlrWlM1cGJuTmxjblJDWldadmNtVW9ibTlrWlN3Z2FXNXpaWEowTG5SdklENDlJR3hsYm1kMGFDc3JJRDhnYm5Wc2JDQTZJR05vYVd4a1RtOWtaWE5iYVc1elpYSjBMblJ2WFNsY2JpQWdJQ0I5WEc1OVhHNWNibVoxYm1OMGFXOXVJSEpsY0d4aFkyVlNiMjkwS0c5c1pGSnZiM1FzSUc1bGQxSnZiM1FwSUh0Y2JpQWdJQ0JwWmlBb2IyeGtVbTl2ZENBbUppQnVaWGRTYjI5MElDWW1JRzlzWkZKdmIzUWdJVDA5SUc1bGQxSnZiM1FnSmlZZ2IyeGtVbTl2ZEM1d1lYSmxiblJPYjJSbEtTQjdYRzRnSUNBZ0lDQWdJRzlzWkZKdmIzUXVjR0Z5Wlc1MFRtOWtaUzV5WlhCc1lXTmxRMmhwYkdRb2JtVjNVbTl2ZEN3Z2IyeGtVbTl2ZENsY2JpQWdJQ0I5WEc1Y2JpQWdJQ0J5WlhSMWNtNGdibVYzVW05dmREdGNibjFjYmx4dWZTeDdYQ0l1TGk5MmJtOWtaUzlwY3kxM2FXUm5aWFF1YW5OY0lqb3lPU3hjSWk0dUwzWnViMlJsTDNad1lYUmphQzVxYzF3aU9qTXlMRndpTGk5aGNIQnNlUzF3Y205d1pYSjBhV1Z6WENJNk1UUXNYQ0l1TDNWd1pHRjBaUzEzYVdSblpYUmNJam94T1gxZExERTRPbHRtZFc1amRHbHZiaWh5WlhGMWFYSmxMRzF2WkhWc1pTeGxlSEJ2Y25SektYdGNiblpoY2lCa2IyTjFiV1Z1ZENBOUlISmxjWFZwY21Vb1hDSm5iRzlpWVd3dlpHOWpkVzFsYm5SY0lpbGNiblpoY2lCcGMwRnljbUY1SUQwZ2NtVnhkV2x5WlNoY0luZ3RhWE10WVhKeVlYbGNJaWxjYmx4dWRtRnlJSEpsYm1SbGNpQTlJSEpsY1hWcGNtVW9YQ0l1TDJOeVpXRjBaUzFsYkdWdFpXNTBYQ0lwWEc1MllYSWdaRzl0U1c1a1pYZ2dQU0J5WlhGMWFYSmxLRndpTGk5a2IyMHRhVzVrWlhoY0lpbGNiblpoY2lCd1lYUmphRTl3SUQwZ2NtVnhkV2x5WlNoY0lpNHZjR0YwWTJndGIzQmNJaWxjYm0xdlpIVnNaUzVsZUhCdmNuUnpJRDBnY0dGMFkyaGNibHh1Wm5WdVkzUnBiMjRnY0dGMFkyZ29jbTl2ZEU1dlpHVXNJSEJoZEdOb1pYTXNJSEpsYm1SbGNrOXdkR2x2Ym5NcElIdGNiaUFnSUNCeVpXNWtaWEpQY0hScGIyNXpJRDBnY21WdVpHVnlUM0IwYVc5dWN5QjhmQ0I3ZlZ4dUlDQWdJSEpsYm1SbGNrOXdkR2x2Ym5NdWNHRjBZMmdnUFNCeVpXNWtaWEpQY0hScGIyNXpMbkJoZEdOb0lDWW1JSEpsYm1SbGNrOXdkR2x2Ym5NdWNHRjBZMmdnSVQwOUlIQmhkR05vWEc0Z0lDQWdJQ0FnSUQ4Z2NtVnVaR1Z5VDNCMGFXOXVjeTV3WVhSamFGeHVJQ0FnSUNBZ0lDQTZJSEJoZEdOb1VtVmpkWEp6YVhabFhHNGdJQ0FnY21WdVpHVnlUM0IwYVc5dWN5NXlaVzVrWlhJZ1BTQnlaVzVrWlhKUGNIUnBiMjV6TG5KbGJtUmxjaUI4ZkNCeVpXNWtaWEpjYmx4dUlDQWdJSEpsZEhWeWJpQnlaVzVrWlhKUGNIUnBiMjV6TG5CaGRHTm9LSEp2YjNST2IyUmxMQ0J3WVhSamFHVnpMQ0J5Wlc1a1pYSlBjSFJwYjI1ektWeHVmVnh1WEc1bWRXNWpkR2x2YmlCd1lYUmphRkpsWTNWeWMybDJaU2h5YjI5MFRtOWtaU3dnY0dGMFkyaGxjeXdnY21WdVpHVnlUM0IwYVc5dWN5a2dlMXh1SUNBZ0lIWmhjaUJwYm1ScFkyVnpJRDBnY0dGMFkyaEpibVJwWTJWektIQmhkR05vWlhNcFhHNWNiaUFnSUNCcFppQW9hVzVrYVdObGN5NXNaVzVuZEdnZ1BUMDlJREFwSUh0Y2JpQWdJQ0FnSUNBZ2NtVjBkWEp1SUhKdmIzUk9iMlJsWEc0Z0lDQWdmVnh1WEc0Z0lDQWdkbUZ5SUdsdVpHVjRJRDBnWkc5dFNXNWtaWGdvY205dmRFNXZaR1VzSUhCaGRHTm9aWE11WVN3Z2FXNWthV05sY3lsY2JpQWdJQ0IyWVhJZ2IzZHVaWEpFYjJOMWJXVnVkQ0E5SUhKdmIzUk9iMlJsTG05M2JtVnlSRzlqZFcxbGJuUmNibHh1SUNBZ0lHbG1JQ2doY21WdVpHVnlUM0IwYVc5dWN5NWtiMk4xYldWdWRDQW1KaUJ2ZDI1bGNrUnZZM1Z0Wlc1MElDRTlQU0JrYjJOMWJXVnVkQ2tnZTF4dUlDQWdJQ0FnSUNCeVpXNWtaWEpQY0hScGIyNXpMbVJ2WTNWdFpXNTBJRDBnYjNkdVpYSkViMk4xYldWdWRGeHVJQ0FnSUgxY2JseHVJQ0FnSUdadmNpQW9kbUZ5SUdrZ1BTQXdPeUJwSUR3Z2FXNWthV05sY3k1c1pXNW5kR2c3SUdrckt5a2dlMXh1SUNBZ0lDQWdJQ0IyWVhJZ2JtOWtaVWx1WkdWNElEMGdhVzVrYVdObGMxdHBYVnh1SUNBZ0lDQWdJQ0J5YjI5MFRtOWtaU0E5SUdGd2NHeDVVR0YwWTJnb2NtOXZkRTV2WkdVc1hHNGdJQ0FnSUNBZ0lDQWdJQ0JwYm1SbGVGdHViMlJsU1c1a1pYaGRMRnh1SUNBZ0lDQWdJQ0FnSUNBZ2NHRjBZMmhsYzF0dWIyUmxTVzVrWlhoZExGeHVJQ0FnSUNBZ0lDQWdJQ0FnY21WdVpHVnlUM0IwYVc5dWN5bGNiaUFnSUNCOVhHNWNiaUFnSUNCeVpYUjFjbTRnY205dmRFNXZaR1ZjYm4xY2JseHVablZ1WTNScGIyNGdZWEJ3YkhsUVlYUmphQ2h5YjI5MFRtOWtaU3dnWkc5dFRtOWtaU3dnY0dGMFkyaE1hWE4wTENCeVpXNWtaWEpQY0hScGIyNXpLU0I3WEc0Z0lDQWdhV1lnS0NGa2IyMU9iMlJsS1NCN1hHNGdJQ0FnSUNBZ0lISmxkSFZ5YmlCeWIyOTBUbTlrWlZ4dUlDQWdJSDFjYmx4dUlDQWdJSFpoY2lCdVpYZE9iMlJsWEc1Y2JpQWdJQ0JwWmlBb2FYTkJjbkpoZVNod1lYUmphRXhwYzNRcEtTQjdYRzRnSUNBZ0lDQWdJR1p2Y2lBb2RtRnlJR2tnUFNBd095QnBJRHdnY0dGMFkyaE1hWE4wTG14bGJtZDBhRHNnYVNzcktTQjdYRzRnSUNBZ0lDQWdJQ0FnSUNCdVpYZE9iMlJsSUQwZ2NHRjBZMmhQY0Nod1lYUmphRXhwYzNSYmFWMHNJR1J2YlU1dlpHVXNJSEpsYm1SbGNrOXdkR2x2Ym5NcFhHNWNiaUFnSUNBZ0lDQWdJQ0FnSUdsbUlDaGtiMjFPYjJSbElEMDlQU0J5YjI5MFRtOWtaU2tnZTF4dUlDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUhKdmIzUk9iMlJsSUQwZ2JtVjNUbTlrWlZ4dUlDQWdJQ0FnSUNBZ0lDQWdmVnh1SUNBZ0lDQWdJQ0I5WEc0Z0lDQWdmU0JsYkhObElIdGNiaUFnSUNBZ0lDQWdibVYzVG05a1pTQTlJSEJoZEdOb1QzQW9jR0YwWTJoTWFYTjBMQ0JrYjIxT2IyUmxMQ0J5Wlc1a1pYSlBjSFJwYjI1ektWeHVYRzRnSUNBZ0lDQWdJR2xtSUNoa2IyMU9iMlJsSUQwOVBTQnliMjkwVG05a1pTa2dlMXh1SUNBZ0lDQWdJQ0FnSUNBZ2NtOXZkRTV2WkdVZ1BTQnVaWGRPYjJSbFhHNGdJQ0FnSUNBZ0lIMWNiaUFnSUNCOVhHNWNiaUFnSUNCeVpYUjFjbTRnY205dmRFNXZaR1ZjYm4xY2JseHVablZ1WTNScGIyNGdjR0YwWTJoSmJtUnBZMlZ6S0hCaGRHTm9aWE1wSUh0Y2JpQWdJQ0IyWVhJZ2FXNWthV05sY3lBOUlGdGRYRzVjYmlBZ0lDQm1iM0lnS0haaGNpQnJaWGtnYVc0Z2NHRjBZMmhsY3lrZ2UxeHVJQ0FnSUNBZ0lDQnBaaUFvYTJWNUlDRTlQU0JjSW1GY0lpa2dlMXh1SUNBZ0lDQWdJQ0FnSUNBZ2FXNWthV05sY3k1d2RYTm9LRTUxYldKbGNpaHJaWGtwS1Z4dUlDQWdJQ0FnSUNCOVhHNGdJQ0FnZlZ4dVhHNGdJQ0FnY21WMGRYSnVJR2x1WkdsalpYTmNibjFjYmx4dWZTeDdYQ0l1TDJOeVpXRjBaUzFsYkdWdFpXNTBYQ0k2TVRVc1hDSXVMMlJ2YlMxcGJtUmxlRndpT2pFMkxGd2lMaTl3WVhSamFDMXZjRndpT2pFM0xGd2laMnh2WW1Gc0wyUnZZM1Z0Wlc1MFhDSTZNVEFzWENKNExXbHpMV0Z5Y21GNVhDSTZNVEo5WFN3eE9UcGJablZ1WTNScGIyNG9jbVZ4ZFdseVpTeHRiMlIxYkdVc1pYaHdiM0owY3lsN1hHNTJZWElnYVhOWGFXUm5aWFFnUFNCeVpYRjFhWEpsS0Z3aUxpNHZkbTV2WkdVdmFYTXRkMmxrWjJWMExtcHpYQ0lwWEc1Y2JtMXZaSFZzWlM1bGVIQnZjblJ6SUQwZ2RYQmtZWFJsVjJsa1oyVjBYRzVjYm1aMWJtTjBhVzl1SUhWd1pHRjBaVmRwWkdkbGRDaGhMQ0JpS1NCN1hHNGdJQ0FnYVdZZ0tHbHpWMmxrWjJWMEtHRXBJQ1ltSUdselYybGtaMlYwS0dJcEtTQjdYRzRnSUNBZ0lDQWdJR2xtSUNoY0ltNWhiV1ZjSWlCcGJpQmhJQ1ltSUZ3aWJtRnRaVndpSUdsdUlHSXBJSHRjYmlBZ0lDQWdJQ0FnSUNBZ0lISmxkSFZ5YmlCaExtbGtJRDA5UFNCaUxtbGtYRzRnSUNBZ0lDQWdJSDBnWld4elpTQjdYRzRnSUNBZ0lDQWdJQ0FnSUNCeVpYUjFjbTRnWVM1cGJtbDBJRDA5UFNCaUxtbHVhWFJjYmlBZ0lDQWdJQ0FnZlZ4dUlDQWdJSDFjYmx4dUlDQWdJSEpsZEhWeWJpQm1ZV3h6WlZ4dWZWeHVYRzU5TEh0Y0lpNHVMM1p1YjJSbEwybHpMWGRwWkdkbGRDNXFjMXdpT2pJNWZWMHNNakE2VzJaMWJtTjBhVzl1S0hKbGNYVnBjbVVzYlc5a2RXeGxMR1Y0Y0c5eWRITXBlMXh1SjNWelpTQnpkSEpwWTNRbk8xeHVYRzUyWVhJZ1JYWlRkRzl5WlNBOUlISmxjWFZwY21Vb0oyVjJMWE4wYjNKbEp5azdYRzVjYm0xdlpIVnNaUzVsZUhCdmNuUnpJRDBnUlhaSWIyOXJPMXh1WEc1bWRXNWpkR2x2YmlCRmRraHZiMnNvZG1Gc2RXVXBJSHRjYmlBZ0lDQnBaaUFvSVNoMGFHbHpJR2x1YzNSaGJtTmxiMllnUlhaSWIyOXJLU2tnZTF4dUlDQWdJQ0FnSUNCeVpYUjFjbTRnYm1WM0lFVjJTRzl2YXloMllXeDFaU2s3WEc0Z0lDQWdmVnh1WEc0Z0lDQWdkR2hwY3k1MllXeDFaU0E5SUhaaGJIVmxPMXh1ZlZ4dVhHNUZka2h2YjJzdWNISnZkRzkwZVhCbExtaHZiMnNnUFNCbWRXNWpkR2x2YmlBb2JtOWtaU3dnY0hKdmNHVnlkSGxPWVcxbEtTQjdYRzRnSUNBZ2RtRnlJR1Z6SUQwZ1JYWlRkRzl5WlNodWIyUmxLVHRjYmlBZ0lDQjJZWElnY0hKdmNFNWhiV1VnUFNCd2NtOXdaWEowZVU1aGJXVXVjM1ZpYzNSeUtETXBPMXh1WEc0Z0lDQWdaWE5iY0hKdmNFNWhiV1ZkSUQwZ2RHaHBjeTUyWVd4MVpUdGNibjA3WEc1Y2JrVjJTRzl2YXk1d2NtOTBiM1I1Y0dVdWRXNW9iMjlySUQwZ1puVnVZM1JwYjI0b2JtOWtaU3dnY0hKdmNHVnlkSGxPWVcxbEtTQjdYRzRnSUNBZ2RtRnlJR1Z6SUQwZ1JYWlRkRzl5WlNodWIyUmxLVHRjYmlBZ0lDQjJZWElnY0hKdmNFNWhiV1VnUFNCd2NtOXdaWEowZVU1aGJXVXVjM1ZpYzNSeUtETXBPMXh1WEc0Z0lDQWdaWE5iY0hKdmNFNWhiV1ZkSUQwZ2RXNWtaV1pwYm1Wa08xeHVmVHRjYmx4dWZTeDdYQ0psZGkxemRHOXlaVndpT2pkOVhTd3lNVHBiWm5WdVkzUnBiMjRvY21WeGRXbHlaU3h0YjJSMWJHVXNaWGh3YjNKMGN5bDdYRzRuZFhObElITjBjbWxqZENjN1hHNWNibTF2WkhWc1pTNWxlSEJ2Y25SeklEMGdVMjltZEZObGRFaHZiMnM3WEc1Y2JtWjFibU4wYVc5dUlGTnZablJUWlhSSWIyOXJLSFpoYkhWbEtTQjdYRzRnSUNBZ2FXWWdLQ0VvZEdocGN5QnBibk4wWVc1alpXOW1JRk52Wm5SVFpYUkliMjlyS1NrZ2UxeHVJQ0FnSUNBZ0lDQnlaWFIxY200Z2JtVjNJRk52Wm5SVFpYUkliMjlyS0haaGJIVmxLVHRjYmlBZ0lDQjlYRzVjYmlBZ0lDQjBhR2x6TG5aaGJIVmxJRDBnZG1Gc2RXVTdYRzU5WEc1Y2JsTnZablJUWlhSSWIyOXJMbkJ5YjNSdmRIbHdaUzVvYjI5cklEMGdablZ1WTNScGIyNGdLRzV2WkdVc0lIQnliM0JsY25SNVRtRnRaU2tnZTF4dUlDQWdJR2xtSUNodWIyUmxXM0J5YjNCbGNuUjVUbUZ0WlYwZ0lUMDlJSFJvYVhNdWRtRnNkV1VwSUh0Y2JpQWdJQ0FnSUNBZ2JtOWtaVnR3Y205d1pYSjBlVTVoYldWZElEMGdkR2hwY3k1MllXeDFaVHRjYmlBZ0lDQjlYRzU5TzF4dVhHNTlMSHQ5WFN3eU1qcGJablZ1WTNScGIyNG9jbVZ4ZFdseVpTeHRiMlIxYkdVc1pYaHdiM0owY3lsN1hHNG5kWE5sSUhOMGNtbGpkQ2M3WEc1Y2JuWmhjaUJwYzBGeWNtRjVJRDBnY21WeGRXbHlaU2duZUMxcGN5MWhjbkpoZVNjcE8xeHVYRzUyWVhJZ1ZrNXZaR1VnUFNCeVpYRjFhWEpsS0NjdUxpOTJibTlrWlM5MmJtOWtaUzVxY3ljcE8xeHVkbUZ5SUZaVVpYaDBJRDBnY21WeGRXbHlaU2duTGk0dmRtNXZaR1V2ZG5SbGVIUXVhbk1uS1R0Y2JuWmhjaUJwYzFaT2IyUmxJRDBnY21WeGRXbHlaU2duTGk0dmRtNXZaR1V2YVhNdGRtNXZaR1VuS1R0Y2JuWmhjaUJwYzFaVVpYaDBJRDBnY21WeGRXbHlaU2duTGk0dmRtNXZaR1V2YVhNdGRuUmxlSFFuS1R0Y2JuWmhjaUJwYzFkcFpHZGxkQ0E5SUhKbGNYVnBjbVVvSnk0dUwzWnViMlJsTDJsekxYZHBaR2RsZENjcE8xeHVkbUZ5SUdselNHOXZheUE5SUhKbGNYVnBjbVVvSnk0dUwzWnViMlJsTDJsekxYWm9iMjlySnlrN1hHNTJZWElnYVhOV1ZHaDFibXNnUFNCeVpYRjFhWEpsS0NjdUxpOTJibTlrWlM5cGN5MTBhSFZ1YXljcE8xeHVYRzUyWVhJZ2NHRnljMlZVWVdjZ1BTQnlaWEYxYVhKbEtDY3VMM0JoY25ObExYUmhaeTVxY3ljcE8xeHVkbUZ5SUhOdlpuUlRaWFJJYjI5cklEMGdjbVZ4ZFdseVpTZ25MaTlvYjI5cmN5OXpiMlowTFhObGRDMW9iMjlyTG1wekp5azdYRzUyWVhJZ1pYWkliMjlySUQwZ2NtVnhkV2x5WlNnbkxpOW9iMjlyY3k5bGRpMW9iMjlyTG1wekp5azdYRzVjYm0xdlpIVnNaUzVsZUhCdmNuUnpJRDBnYUR0Y2JseHVablZ1WTNScGIyNGdhQ2gwWVdkT1lXMWxMQ0J3Y205d1pYSjBhV1Z6TENCamFHbHNaSEpsYmlrZ2UxeHVJQ0FnSUhaaGNpQmphR2xzWkU1dlpHVnpJRDBnVzEwN1hHNGdJQ0FnZG1GeUlIUmhaeXdnY0hKdmNITXNJR3RsZVN3Z2JtRnRaWE53WVdObE8xeHVYRzRnSUNBZ2FXWWdLQ0ZqYUdsc1pISmxiaUFtSmlCcGMwTm9hV3hrY21WdUtIQnliM0JsY25ScFpYTXBLU0I3WEc0Z0lDQWdJQ0FnSUdOb2FXeGtjbVZ1SUQwZ2NISnZjR1Z5ZEdsbGN6dGNiaUFnSUNBZ0lDQWdjSEp2Y0hNZ1BTQjdmVHRjYmlBZ0lDQjlYRzVjYmlBZ0lDQndjbTl3Y3lBOUlIQnliM0J6SUh4OElIQnliM0JsY25ScFpYTWdmSHdnZTMwN1hHNGdJQ0FnZEdGbklEMGdjR0Z5YzJWVVlXY29kR0ZuVG1GdFpTd2djSEp2Y0hNcE8xeHVYRzRnSUNBZ0x5OGdjM1Z3Y0c5eWRDQnJaWGx6WEc0Z0lDQWdhV1lnS0hCeWIzQnpMbWhoYzA5M2JsQnliM0JsY25SNUtDZHJaWGtuS1NrZ2UxeHVJQ0FnSUNBZ0lDQnJaWGtnUFNCd2NtOXdjeTVyWlhrN1hHNGdJQ0FnSUNBZ0lIQnliM0J6TG10bGVTQTlJSFZ1WkdWbWFXNWxaRHRjYmlBZ0lDQjlYRzVjYmlBZ0lDQXZMeUJ6ZFhCd2IzSjBJRzVoYldWemNHRmpaVnh1SUNBZ0lHbG1JQ2h3Y205d2N5NW9ZWE5QZDI1UWNtOXdaWEowZVNnbmJtRnRaWE53WVdObEp5a3BJSHRjYmlBZ0lDQWdJQ0FnYm1GdFpYTndZV05sSUQwZ2NISnZjSE11Ym1GdFpYTndZV05sTzF4dUlDQWdJQ0FnSUNCd2NtOXdjeTV1WVcxbGMzQmhZMlVnUFNCMWJtUmxabWx1WldRN1hHNGdJQ0FnZlZ4dVhHNGdJQ0FnTHk4Z1ptbDRJR04xY25OdmNpQmlkV2RjYmlBZ0lDQnBaaUFvZEdGbklEMDlQU0FuU1U1UVZWUW5JQ1ltWEc0Z0lDQWdJQ0FnSUNGdVlXMWxjM0JoWTJVZ0ppWmNiaUFnSUNBZ0lDQWdjSEp2Y0hNdWFHRnpUM2R1VUhKdmNHVnlkSGtvSjNaaGJIVmxKeWtnSmlaY2JpQWdJQ0FnSUNBZ2NISnZjSE11ZG1Gc2RXVWdJVDA5SUhWdVpHVm1hVzVsWkNBbUpseHVJQ0FnSUNBZ0lDQWhhWE5JYjI5cktIQnliM0J6TG5aaGJIVmxLVnh1SUNBZ0lDa2dlMXh1SUNBZ0lDQWdJQ0J3Y205d2N5NTJZV3gxWlNBOUlITnZablJUWlhSSWIyOXJLSEJ5YjNCekxuWmhiSFZsS1R0Y2JpQWdJQ0I5WEc1Y2JpQWdJQ0IwY21GdWMyWnZjbTFRY205d1pYSjBhV1Z6S0hCeWIzQnpLVHRjYmx4dUlDQWdJR2xtSUNoamFHbHNaSEpsYmlBaFBUMGdkVzVrWldacGJtVmtJQ1ltSUdOb2FXeGtjbVZ1SUNFOVBTQnVkV3hzS1NCN1hHNGdJQ0FnSUNBZ0lHRmtaRU5vYVd4a0tHTm9hV3hrY21WdUxDQmphR2xzWkU1dlpHVnpMQ0IwWVdjc0lIQnliM0J6S1R0Y2JpQWdJQ0I5WEc1Y2JseHVJQ0FnSUhKbGRIVnliaUJ1WlhjZ1ZrNXZaR1VvZEdGbkxDQndjbTl3Y3l3Z1kyaHBiR1JPYjJSbGN5d2dhMlY1TENCdVlXMWxjM0JoWTJVcE8xeHVmVnh1WEc1bWRXNWpkR2x2YmlCaFpHUkRhR2xzWkNoakxDQmphR2xzWkU1dlpHVnpMQ0IwWVdjc0lIQnliM0J6S1NCN1hHNGdJQ0FnYVdZZ0tIUjVjR1Z2WmlCaklEMDlQU0FuYzNSeWFXNW5KeWtnZTF4dUlDQWdJQ0FnSUNCamFHbHNaRTV2WkdWekxuQjFjMmdvYm1WM0lGWlVaWGgwS0dNcEtUdGNiaUFnSUNCOUlHVnNjMlVnYVdZZ0tIUjVjR1Z2WmlCaklEMDlQU0FuYm5WdFltVnlKeWtnZTF4dUlDQWdJQ0FnSUNCamFHbHNaRTV2WkdWekxuQjFjMmdvYm1WM0lGWlVaWGgwS0ZOMGNtbHVaeWhqS1NrcE8xeHVJQ0FnSUgwZ1pXeHpaU0JwWmlBb2FYTkRhR2xzWkNoaktTa2dlMXh1SUNBZ0lDQWdJQ0JqYUdsc1pFNXZaR1Z6TG5CMWMyZ29ZeWs3WEc0Z0lDQWdmU0JsYkhObElHbG1JQ2hwYzBGeWNtRjVLR01wS1NCN1hHNGdJQ0FnSUNBZ0lHWnZjaUFvZG1GeUlHa2dQU0F3T3lCcElEd2dZeTVzWlc1bmRHZzdJR2tyS3lrZ2UxeHVJQ0FnSUNBZ0lDQWdJQ0FnWVdSa1EyaHBiR1FvWTF0cFhTd2dZMmhwYkdST2IyUmxjeXdnZEdGbkxDQndjbTl3Y3lrN1hHNGdJQ0FnSUNBZ0lIMWNiaUFnSUNCOUlHVnNjMlVnYVdZZ0tHTWdQVDA5SUc1MWJHd2dmSHdnWXlBOVBUMGdkVzVrWldacGJtVmtLU0I3WEc0Z0lDQWdJQ0FnSUhKbGRIVnlianRjYmlBZ0lDQjlJR1ZzYzJVZ2UxeHVJQ0FnSUNBZ0lDQjBhSEp2ZHlCVmJtVjRjR1ZqZEdWa1ZtbHlkSFZoYkVWc1pXMWxiblFvZTF4dUlDQWdJQ0FnSUNBZ0lDQWdabTl5WldsbmJrOWlhbVZqZERvZ1l5eGNiaUFnSUNBZ0lDQWdJQ0FnSUhCaGNtVnVkRlp1YjJSbE9pQjdYRzRnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdkR0ZuVG1GdFpUb2dkR0ZuTEZ4dUlDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUhCeWIzQmxjblJwWlhNNklIQnliM0J6WEc0Z0lDQWdJQ0FnSUNBZ0lDQjlYRzRnSUNBZ0lDQWdJSDBwTzF4dUlDQWdJSDFjYm4xY2JseHVablZ1WTNScGIyNGdkSEpoYm5ObWIzSnRVSEp2Y0dWeWRHbGxjeWh3Y205d2N5a2dlMXh1SUNBZ0lHWnZjaUFvZG1GeUlIQnliM0JPWVcxbElHbHVJSEJ5YjNCektTQjdYRzRnSUNBZ0lDQWdJR2xtSUNod2NtOXdjeTVvWVhOUGQyNVFjbTl3WlhKMGVTaHdjbTl3VG1GdFpTa3BJSHRjYmlBZ0lDQWdJQ0FnSUNBZ0lIWmhjaUIyWVd4MVpTQTlJSEJ5YjNCelczQnliM0JPWVcxbFhUdGNibHh1SUNBZ0lDQWdJQ0FnSUNBZ2FXWWdLR2x6U0c5dmF5aDJZV3gxWlNrcElIdGNiaUFnSUNBZ0lDQWdJQ0FnSUNBZ0lDQmpiMjUwYVc1MVpUdGNiaUFnSUNBZ0lDQWdJQ0FnSUgxY2JseHVJQ0FnSUNBZ0lDQWdJQ0FnYVdZZ0tIQnliM0JPWVcxbExuTjFZbk4wY2lnd0xDQXpLU0E5UFQwZ0oyVjJMU2NwSUh0Y2JpQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBdkx5QmhaR1FnWlhZdFptOXZJSE4xY0hCdmNuUmNiaUFnSUNBZ0lDQWdJQ0FnSUNBZ0lDQndjbTl3YzF0d2NtOXdUbUZ0WlYwZ1BTQmxka2h2YjJzb2RtRnNkV1VwTzF4dUlDQWdJQ0FnSUNBZ0lDQWdmVnh1SUNBZ0lDQWdJQ0I5WEc0Z0lDQWdmVnh1ZlZ4dVhHNW1kVzVqZEdsdmJpQnBjME5vYVd4a0tIZ3BJSHRjYmlBZ0lDQnlaWFIxY200Z2FYTldUbTlrWlNoNEtTQjhmQ0JwYzFaVVpYaDBLSGdwSUh4OElHbHpWMmxrWjJWMEtIZ3BJSHg4SUdselZsUm9kVzVyS0hncE8xeHVmVnh1WEc1bWRXNWpkR2x2YmlCcGMwTm9hV3hrY21WdUtIZ3BJSHRjYmlBZ0lDQnlaWFIxY200Z2RIbHdaVzltSUhnZ1BUMDlJQ2R6ZEhKcGJtY25JSHg4SUdselFYSnlZWGtvZUNrZ2ZId2dhWE5EYUdsc1pDaDRLVHRjYm4xY2JseHVablZ1WTNScGIyNGdWVzVsZUhCbFkzUmxaRlpwY25SMVlXeEZiR1Z0Wlc1MEtHUmhkR0VwSUh0Y2JpQWdJQ0IyWVhJZ1pYSnlJRDBnYm1WM0lFVnljbTl5S0NrN1hHNWNiaUFnSUNCbGNuSXVkSGx3WlNBOUlDZDJhWEowZFdGc0xXaDVjR1Z5YzJOeWFYQjBMblZ1Wlhod1pXTjBaV1F1ZG1seWRIVmhiQzFsYkdWdFpXNTBKenRjYmlBZ0lDQmxjbkl1YldWemMyRm5aU0E5SUNkVmJtVjRjR1ZqZEdWa0lIWnBjblIxWVd3Z1kyaHBiR1FnY0dGemMyVmtJSFJ2SUdnb0tTNWNYRzRuSUN0Y2JpQWdJQ0FnSUNBZ0owVjRjR1ZqZEdWa0lHRWdWazV2WkdVZ0x5QldkR2gxYm1zZ0x5QldWMmxrWjJWMElDOGdjM1J5YVc1bklHSjFkRHBjWEc0bklDdGNiaUFnSUNBZ0lDQWdKMmR2ZERwY1hHNG5JQ3RjYmlBZ0lDQWdJQ0FnWlhKeWIzSlRkSEpwYm1jb1pHRjBZUzVtYjNKbGFXZHVUMkpxWldOMEtTQXJYRzRnSUNBZ0lDQWdJQ2N1WEZ4dUp5QXJYRzRnSUNBZ0lDQWdJQ2RVYUdVZ2NHRnlaVzUwSUhadWIyUmxJR2x6T2x4Y2JpY2dLMXh1SUNBZ0lDQWdJQ0JsY25KdmNsTjBjbWx1Wnloa1lYUmhMbkJoY21WdWRGWnViMlJsS1Z4dUlDQWdJQ0FnSUNBblhGeHVKeUFyWEc0Z0lDQWdJQ0FnSUNkVGRXZG5aWE4wWldRZ1ptbDRPaUJqYUdGdVoyVWdlVzkxY2lCZ2FDZ3VMaTRzSUZzZ0xpNHVJRjBwWUNCallXeHNjMmwwWlM0bk8xeHVJQ0FnSUdWeWNpNW1iM0psYVdkdVQySnFaV04wSUQwZ1pHRjBZUzVtYjNKbGFXZHVUMkpxWldOME8xeHVJQ0FnSUdWeWNpNXdZWEpsYm5SV2JtOWtaU0E5SUdSaGRHRXVjR0Z5Wlc1MFZtNXZaR1U3WEc1Y2JpQWdJQ0J5WlhSMWNtNGdaWEp5TzF4dWZWeHVYRzVtZFc1amRHbHZiaUJsY25KdmNsTjBjbWx1Wnlodlltb3BJSHRjYmlBZ0lDQjBjbmtnZTF4dUlDQWdJQ0FnSUNCeVpYUjFjbTRnU2xOUFRpNXpkSEpwYm1kcFpua29iMkpxTENCdWRXeHNMQ0FuSUNBZ0lDY3BPMXh1SUNBZ0lIMGdZMkYwWTJnZ0tHVXBJSHRjYmlBZ0lDQWdJQ0FnY21WMGRYSnVJRk4wY21sdVp5aHZZbW9wTzF4dUlDQWdJSDFjYm4xY2JseHVmU3g3WENJdUxpOTJibTlrWlM5cGN5MTBhSFZ1YTF3aU9qSTFMRndpTGk0dmRtNXZaR1V2YVhNdGRtaHZiMnRjSWpveU5peGNJaTR1TDNadWIyUmxMMmx6TFhadWIyUmxYQ0k2TWpjc1hDSXVMaTkyYm05a1pTOXBjeTEyZEdWNGRGd2lPakk0TEZ3aUxpNHZkbTV2WkdVdmFYTXRkMmxrWjJWMFhDSTZNamtzWENJdUxpOTJibTlrWlM5MmJtOWtaUzVxYzF3aU9qTXhMRndpTGk0dmRtNXZaR1V2ZG5SbGVIUXVhbk5jSWpvek15eGNJaTR2YUc5dmEzTXZaWFl0YUc5dmF5NXFjMXdpT2pJd0xGd2lMaTlvYjI5cmN5OXpiMlowTFhObGRDMW9iMjlyTG1welhDSTZNakVzWENJdUwzQmhjbk5sTFhSaFp5NXFjMXdpT2pJekxGd2llQzFwY3kxaGNuSmhlVndpT2pFeWZWMHNNak02VzJaMWJtTjBhVzl1S0hKbGNYVnBjbVVzYlc5a2RXeGxMR1Y0Y0c5eWRITXBlMXh1SjNWelpTQnpkSEpwWTNRbk8xeHVYRzUyWVhJZ2MzQnNhWFFnUFNCeVpYRjFhWEpsS0NkaWNtOTNjMlZ5TFhOd2JHbDBKeWs3WEc1Y2JuWmhjaUJqYkdGemMwbGtVM0JzYVhRZ1BTQXZLRnRjWEM0alhUOWJZUzE2UVMxYU1DMDVYRngxTURBM1JpMWNYSFZHUmtaR1h6b3RYU3NwTHp0Y2JuWmhjaUJ1YjNSRGJHRnpjMGxrSUQwZ0wxNWNYQzU4SXk4N1hHNWNibTF2WkhWc1pTNWxlSEJ2Y25SeklEMGdjR0Z5YzJWVVlXYzdYRzVjYm1aMWJtTjBhVzl1SUhCaGNuTmxWR0ZuS0hSaFp5d2djSEp2Y0hNcElIdGNiaUFnSUNCcFppQW9JWFJoWnlrZ2UxeHVJQ0FnSUNBZ0lDQnlaWFIxY200Z0owUkpWaWM3WEc0Z0lDQWdmVnh1WEc0Z0lDQWdkbUZ5SUc1dlNXUWdQU0FoS0hCeWIzQnpMbWhoYzA5M2JsQnliM0JsY25SNUtDZHBaQ2NwS1R0Y2JseHVJQ0FnSUhaaGNpQjBZV2RRWVhKMGN5QTlJSE53YkdsMEtIUmhaeXdnWTJ4aGMzTkpaRk53YkdsMEtUdGNiaUFnSUNCMllYSWdkR0ZuVG1GdFpTQTlJRzUxYkd3N1hHNWNiaUFnSUNCcFppQW9ibTkwUTJ4aGMzTkpaQzUwWlhOMEtIUmhaMUJoY25Seld6RmRLU2tnZTF4dUlDQWdJQ0FnSUNCMFlXZE9ZVzFsSUQwZ0owUkpWaWM3WEc0Z0lDQWdmVnh1WEc0Z0lDQWdkbUZ5SUdOc1lYTnpaWE1zSUhCaGNuUXNJSFI1Y0dVc0lHazdYRzVjYmlBZ0lDQm1iM0lnS0drZ1BTQXdPeUJwSUR3Z2RHRm5VR0Z5ZEhNdWJHVnVaM1JvT3lCcEt5c3BJSHRjYmlBZ0lDQWdJQ0FnY0dGeWRDQTlJSFJoWjFCaGNuUnpXMmxkTzF4dVhHNGdJQ0FnSUNBZ0lHbG1JQ2doY0dGeWRDa2dlMXh1SUNBZ0lDQWdJQ0FnSUNBZ1kyOXVkR2x1ZFdVN1hHNGdJQ0FnSUNBZ0lIMWNibHh1SUNBZ0lDQWdJQ0IwZVhCbElEMGdjR0Z5ZEM1amFHRnlRWFFvTUNrN1hHNWNiaUFnSUNBZ0lDQWdhV1lnS0NGMFlXZE9ZVzFsS1NCN1hHNGdJQ0FnSUNBZ0lDQWdJQ0IwWVdkT1lXMWxJRDBnY0dGeWREdGNiaUFnSUNBZ0lDQWdmU0JsYkhObElHbG1JQ2gwZVhCbElEMDlQU0FuTGljcElIdGNiaUFnSUNBZ0lDQWdJQ0FnSUdOc1lYTnpaWE1nUFNCamJHRnpjMlZ6SUh4OElGdGRPMXh1SUNBZ0lDQWdJQ0FnSUNBZ1kyeGhjM05sY3k1d2RYTm9LSEJoY25RdWMzVmljM1J5YVc1bktERXNJSEJoY25RdWJHVnVaM1JvS1NrN1hHNGdJQ0FnSUNBZ0lIMGdaV3h6WlNCcFppQW9kSGx3WlNBOVBUMGdKeU1uSUNZbUlHNXZTV1FwSUh0Y2JpQWdJQ0FnSUNBZ0lDQWdJSEJ5YjNCekxtbGtJRDBnY0dGeWRDNXpkV0p6ZEhKcGJtY29NU3dnY0dGeWRDNXNaVzVuZEdncE8xeHVJQ0FnSUNBZ0lDQjlYRzRnSUNBZ2ZWeHVYRzRnSUNBZ2FXWWdLR05zWVhOelpYTXBJSHRjYmlBZ0lDQWdJQ0FnYVdZZ0tIQnliM0J6TG1Oc1lYTnpUbUZ0WlNrZ2UxeHVJQ0FnSUNBZ0lDQWdJQ0FnWTJ4aGMzTmxjeTV3ZFhOb0tIQnliM0J6TG1Oc1lYTnpUbUZ0WlNrN1hHNGdJQ0FnSUNBZ0lIMWNibHh1SUNBZ0lDQWdJQ0J3Y205d2N5NWpiR0Z6YzA1aGJXVWdQU0JqYkdGemMyVnpMbXB2YVc0b0p5QW5LVHRjYmlBZ0lDQjlYRzVjYmlBZ0lDQnlaWFIxY200Z2NISnZjSE11Ym1GdFpYTndZV05sSUQ4Z2RHRm5UbUZ0WlNBNklIUmhaMDVoYldVdWRHOVZjSEJsY2tOaGMyVW9LVHRjYm4xY2JseHVmU3g3WENKaWNtOTNjMlZ5TFhOd2JHbDBYQ0k2TlgxZExESTBPbHRtZFc1amRHbHZiaWh5WlhGMWFYSmxMRzF2WkhWc1pTeGxlSEJ2Y25SektYdGNiblpoY2lCcGMxWk9iMlJsSUQwZ2NtVnhkV2x5WlNoY0lpNHZhWE10ZG01dlpHVmNJaWxjYm5aaGNpQnBjMVpVWlhoMElEMGdjbVZ4ZFdseVpTaGNJaTR2YVhNdGRuUmxlSFJjSWlsY2JuWmhjaUJwYzFkcFpHZGxkQ0E5SUhKbGNYVnBjbVVvWENJdUwybHpMWGRwWkdkbGRGd2lLVnh1ZG1GeUlHbHpWR2gxYm1zZ1BTQnlaWEYxYVhKbEtGd2lMaTlwY3kxMGFIVnVhMXdpS1Z4dVhHNXRiMlIxYkdVdVpYaHdiM0owY3lBOUlHaGhibVJzWlZSb2RXNXJYRzVjYm1aMWJtTjBhVzl1SUdoaGJtUnNaVlJvZFc1cktHRXNJR0lwSUh0Y2JpQWdJQ0IyWVhJZ2NtVnVaR1Z5WldSQklEMGdZVnh1SUNBZ0lIWmhjaUJ5Wlc1a1pYSmxaRUlnUFNCaVhHNWNiaUFnSUNCcFppQW9hWE5VYUhWdWF5aGlLU2tnZTF4dUlDQWdJQ0FnSUNCeVpXNWtaWEpsWkVJZ1BTQnlaVzVrWlhKVWFIVnVheWhpTENCaEtWeHVJQ0FnSUgxY2JseHVJQ0FnSUdsbUlDaHBjMVJvZFc1cktHRXBLU0I3WEc0Z0lDQWdJQ0FnSUhKbGJtUmxjbVZrUVNBOUlISmxibVJsY2xSb2RXNXJLR0VzSUc1MWJHd3BYRzRnSUNBZ2ZWeHVYRzRnSUNBZ2NtVjBkWEp1SUh0Y2JpQWdJQ0FnSUNBZ1lUb2djbVZ1WkdWeVpXUkJMRnh1SUNBZ0lDQWdJQ0JpT2lCeVpXNWtaWEpsWkVKY2JpQWdJQ0I5WEc1OVhHNWNibVoxYm1OMGFXOXVJSEpsYm1SbGNsUm9kVzVyS0hSb2RXNXJMQ0J3Y21WMmFXOTFjeWtnZTF4dUlDQWdJSFpoY2lCeVpXNWtaWEpsWkZSb2RXNXJJRDBnZEdoMWJtc3VkbTV2WkdWY2JseHVJQ0FnSUdsbUlDZ2hjbVZ1WkdWeVpXUlVhSFZ1YXlrZ2UxeHVJQ0FnSUNBZ0lDQnlaVzVrWlhKbFpGUm9kVzVySUQwZ2RHaDFibXN1ZG01dlpHVWdQU0IwYUhWdWF5NXlaVzVrWlhJb2NISmxkbWx2ZFhNcFhHNGdJQ0FnZlZ4dVhHNGdJQ0FnYVdZZ0tDRW9hWE5XVG05a1pTaHlaVzVrWlhKbFpGUm9kVzVyS1NCOGZGeHVJQ0FnSUNBZ0lDQWdJQ0FnYVhOV1ZHVjRkQ2h5Wlc1a1pYSmxaRlJvZFc1cktTQjhmRnh1SUNBZ0lDQWdJQ0FnSUNBZ2FYTlhhV1JuWlhRb2NtVnVaR1Z5WldSVWFIVnVheWtwS1NCN1hHNGdJQ0FnSUNBZ0lIUm9jbTkzSUc1bGR5QkZjbkp2Y2loY0luUm9kVzVySUdScFpDQnViM1FnY21WMGRYSnVJR0VnZG1Gc2FXUWdibTlrWlZ3aUtUdGNiaUFnSUNCOVhHNWNiaUFnSUNCeVpYUjFjbTRnY21WdVpHVnlaV1JVYUhWdWExeHVmVnh1WEc1OUxIdGNJaTR2YVhNdGRHaDFibXRjSWpveU5TeGNJaTR2YVhNdGRtNXZaR1ZjSWpveU55eGNJaTR2YVhNdGRuUmxlSFJjSWpveU9DeGNJaTR2YVhNdGQybGtaMlYwWENJNk1qbDlYU3d5TlRwYlpuVnVZM1JwYjI0b2NtVnhkV2x5WlN4dGIyUjFiR1VzWlhod2IzSjBjeWw3WEc1dGIyUjFiR1V1Wlhod2IzSjBjeUE5SUdselZHaDFibXRjYmx4dVpuVnVZM1JwYjI0Z2FYTlVhSFZ1YXloMEtTQjdYRzRnSUNBZ2NtVjBkWEp1SUhRZ0ppWWdkQzUwZVhCbElEMDlQU0JjSWxSb2RXNXJYQ0pjYm4xY2JseHVmU3g3ZlYwc01qWTZXMloxYm1OMGFXOXVLSEpsY1hWcGNtVXNiVzlrZFd4bExHVjRjRzl5ZEhNcGUxeHViVzlrZFd4bExtVjRjRzl5ZEhNZ1BTQnBjMGh2YjJ0Y2JseHVablZ1WTNScGIyNGdhWE5JYjI5cktHaHZiMnNwSUh0Y2JpQWdJQ0J5WlhSMWNtNGdhRzl2YXlBbUpseHVJQ0FnSUNBZ0tIUjVjR1Z2WmlCb2IyOXJMbWh2YjJzZ1BUMDlJRndpWm5WdVkzUnBiMjVjSWlBbUppQWhhRzl2YXk1b1lYTlBkMjVRY205d1pYSjBlU2hjSW1odmIydGNJaWtnZkh4Y2JpQWdJQ0FnSUNCMGVYQmxiMllnYUc5dmF5NTFibWh2YjJzZ1BUMDlJRndpWm5WdVkzUnBiMjVjSWlBbUppQWhhRzl2YXk1b1lYTlBkMjVRY205d1pYSjBlU2hjSW5WdWFHOXZhMXdpS1NsY2JuMWNibHh1ZlN4N2ZWMHNNamM2VzJaMWJtTjBhVzl1S0hKbGNYVnBjbVVzYlc5a2RXeGxMR1Y0Y0c5eWRITXBlMXh1ZG1GeUlIWmxjbk5wYjI0Z1BTQnlaWEYxYVhKbEtGd2lMaTkyWlhKemFXOXVYQ0lwWEc1Y2JtMXZaSFZzWlM1bGVIQnZjblJ6SUQwZ2FYTldhWEowZFdGc1RtOWtaVnh1WEc1bWRXNWpkR2x2YmlCcGMxWnBjblIxWVd4T2IyUmxLSGdwSUh0Y2JpQWdJQ0J5WlhSMWNtNGdlQ0FtSmlCNExuUjVjR1VnUFQwOUlGd2lWbWx5ZEhWaGJFNXZaR1ZjSWlBbUppQjRMblpsY25OcGIyNGdQVDA5SUhabGNuTnBiMjVjYm4xY2JseHVmU3g3WENJdUwzWmxjbk5wYjI1Y0lqb3pNSDFkTERJNE9sdG1kVzVqZEdsdmJpaHlaWEYxYVhKbExHMXZaSFZzWlN4bGVIQnZjblJ6S1h0Y2JuWmhjaUIyWlhKemFXOXVJRDBnY21WeGRXbHlaU2hjSWk0dmRtVnljMmx2Ymx3aUtWeHVYRzV0YjJSMWJHVXVaWGh3YjNKMGN5QTlJR2x6Vm1seWRIVmhiRlJsZUhSY2JseHVablZ1WTNScGIyNGdhWE5XYVhKMGRXRnNWR1Y0ZENoNEtTQjdYRzRnSUNBZ2NtVjBkWEp1SUhnZ0ppWWdlQzUwZVhCbElEMDlQU0JjSWxacGNuUjFZV3hVWlhoMFhDSWdKaVlnZUM1MlpYSnphVzl1SUQwOVBTQjJaWEp6YVc5dVhHNTlYRzVjYm4wc2Uxd2lMaTkyWlhKemFXOXVYQ0k2TXpCOVhTd3lPVHBiWm5WdVkzUnBiMjRvY21WeGRXbHlaU3h0YjJSMWJHVXNaWGh3YjNKMGN5bDdYRzV0YjJSMWJHVXVaWGh3YjNKMGN5QTlJR2x6VjJsa1oyVjBYRzVjYm1aMWJtTjBhVzl1SUdselYybGtaMlYwS0hjcElIdGNiaUFnSUNCeVpYUjFjbTRnZHlBbUppQjNMblI1Y0dVZ1BUMDlJRndpVjJsa1oyVjBYQ0pjYm4xY2JseHVmU3g3ZlYwc016QTZXMloxYm1OMGFXOXVLSEpsY1hWcGNtVXNiVzlrZFd4bExHVjRjRzl5ZEhNcGUxeHViVzlrZFd4bExtVjRjRzl5ZEhNZ1BTQmNJakpjSWx4dVhHNTlMSHQ5WFN3ek1UcGJablZ1WTNScGIyNG9jbVZ4ZFdseVpTeHRiMlIxYkdVc1pYaHdiM0owY3lsN1hHNTJZWElnZG1WeWMybHZiaUE5SUhKbGNYVnBjbVVvWENJdUwzWmxjbk5wYjI1Y0lpbGNiblpoY2lCcGMxWk9iMlJsSUQwZ2NtVnhkV2x5WlNoY0lpNHZhWE10ZG01dlpHVmNJaWxjYm5aaGNpQnBjMWRwWkdkbGRDQTlJSEpsY1hWcGNtVW9YQ0l1TDJsekxYZHBaR2RsZEZ3aUtWeHVkbUZ5SUdselZHaDFibXNnUFNCeVpYRjFhWEpsS0Z3aUxpOXBjeTEwYUhWdWExd2lLVnh1ZG1GeUlHbHpWa2h2YjJzZ1BTQnlaWEYxYVhKbEtGd2lMaTlwY3kxMmFHOXZhMXdpS1Z4dVhHNXRiMlIxYkdVdVpYaHdiM0owY3lBOUlGWnBjblIxWVd4T2IyUmxYRzVjYm5aaGNpQnViMUJ5YjNCbGNuUnBaWE1nUFNCN2ZWeHVkbUZ5SUc1dlEyaHBiR1J5Wlc0Z1BTQmJYVnh1WEc1bWRXNWpkR2x2YmlCV2FYSjBkV0ZzVG05a1pTaDBZV2RPWVcxbExDQndjbTl3WlhKMGFXVnpMQ0JqYUdsc1pISmxiaXdnYTJWNUxDQnVZVzFsYzNCaFkyVXBJSHRjYmlBZ0lDQjBhR2x6TG5SaFowNWhiV1VnUFNCMFlXZE9ZVzFsWEc0Z0lDQWdkR2hwY3k1d2NtOXdaWEowYVdWeklEMGdjSEp2Y0dWeWRHbGxjeUI4ZkNCdWIxQnliM0JsY25ScFpYTmNiaUFnSUNCMGFHbHpMbU5vYVd4a2NtVnVJRDBnWTJocGJHUnlaVzRnZkh3Z2JtOURhR2xzWkhKbGJseHVJQ0FnSUhSb2FYTXVhMlY1SUQwZ2EyVjVJQ0U5SUc1MWJHd2dQeUJUZEhKcGJtY29hMlY1S1NBNklIVnVaR1ZtYVc1bFpGeHVJQ0FnSUhSb2FYTXVibUZ0WlhOd1lXTmxJRDBnS0hSNWNHVnZaaUJ1WVcxbGMzQmhZMlVnUFQwOUlGd2ljM1J5YVc1blhDSXBJRDhnYm1GdFpYTndZV05sSURvZ2JuVnNiRnh1WEc0Z0lDQWdkbUZ5SUdOdmRXNTBJRDBnS0dOb2FXeGtjbVZ1SUNZbUlHTm9hV3hrY21WdUxteGxibWQwYUNrZ2ZId2dNRnh1SUNBZ0lIWmhjaUJrWlhOalpXNWtZVzUwY3lBOUlEQmNiaUFnSUNCMllYSWdhR0Z6VjJsa1oyVjBjeUE5SUdaaGJITmxYRzRnSUNBZ2RtRnlJR2hoYzFSb2RXNXJjeUE5SUdaaGJITmxYRzRnSUNBZ2RtRnlJR1JsYzJObGJtUmhiblJJYjI5cmN5QTlJR1poYkhObFhHNGdJQ0FnZG1GeUlHaHZiMnR6WEc1Y2JpQWdJQ0JtYjNJZ0tIWmhjaUJ3Y205d1RtRnRaU0JwYmlCd2NtOXdaWEowYVdWektTQjdYRzRnSUNBZ0lDQWdJR2xtSUNod2NtOXdaWEowYVdWekxtaGhjMDkzYmxCeWIzQmxjblI1S0hCeWIzQk9ZVzFsS1NrZ2UxeHVJQ0FnSUNBZ0lDQWdJQ0FnZG1GeUlIQnliM0JsY25SNUlEMGdjSEp2Y0dWeWRHbGxjMXR3Y205d1RtRnRaVjFjYmlBZ0lDQWdJQ0FnSUNBZ0lHbG1JQ2hwYzFaSWIyOXJLSEJ5YjNCbGNuUjVLU0FtSmlCd2NtOXdaWEowZVM1MWJtaHZiMnNwSUh0Y2JpQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNCcFppQW9JV2h2YjJ0ektTQjdYRzRnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUdodmIydHpJRDBnZTMxY2JpQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNCOVhHNWNiaUFnSUNBZ0lDQWdJQ0FnSUNBZ0lDQm9iMjlyYzF0d2NtOXdUbUZ0WlYwZ1BTQndjbTl3WlhKMGVWeHVJQ0FnSUNBZ0lDQWdJQ0FnZlZ4dUlDQWdJQ0FnSUNCOVhHNGdJQ0FnZlZ4dVhHNGdJQ0FnWm05eUlDaDJZWElnYVNBOUlEQTdJR2tnUENCamIzVnVkRHNnYVNzcktTQjdYRzRnSUNBZ0lDQWdJSFpoY2lCamFHbHNaQ0E5SUdOb2FXeGtjbVZ1VzJsZFhHNGdJQ0FnSUNBZ0lHbG1JQ2hwYzFaT2IyUmxLR05vYVd4a0tTa2dlMXh1SUNBZ0lDQWdJQ0FnSUNBZ1pHVnpZMlZ1WkdGdWRITWdLejBnWTJocGJHUXVZMjkxYm5RZ2ZId2dNRnh1WEc0Z0lDQWdJQ0FnSUNBZ0lDQnBaaUFvSVdoaGMxZHBaR2RsZEhNZ0ppWWdZMmhwYkdRdWFHRnpWMmxrWjJWMGN5a2dlMXh1SUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJR2hoYzFkcFpHZGxkSE1nUFNCMGNuVmxYRzRnSUNBZ0lDQWdJQ0FnSUNCOVhHNWNiaUFnSUNBZ0lDQWdJQ0FnSUdsbUlDZ2hhR0Z6VkdoMWJtdHpJQ1ltSUdOb2FXeGtMbWhoYzFSb2RXNXJjeWtnZTF4dUlDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUdoaGMxUm9kVzVyY3lBOUlIUnlkV1ZjYmlBZ0lDQWdJQ0FnSUNBZ0lIMWNibHh1SUNBZ0lDQWdJQ0FnSUNBZ2FXWWdLQ0ZrWlhOalpXNWtZVzUwU0c5dmEzTWdKaVlnS0dOb2FXeGtMbWh2YjJ0eklIeDhJR05vYVd4a0xtUmxjMk5sYm1SaGJuUkliMjlyY3lrcElIdGNiaUFnSUNBZ0lDQWdJQ0FnSUNBZ0lDQmtaWE5qWlc1a1lXNTBTRzl2YTNNZ1BTQjBjblZsWEc0Z0lDQWdJQ0FnSUNBZ0lDQjlYRzRnSUNBZ0lDQWdJSDBnWld4elpTQnBaaUFvSVdoaGMxZHBaR2RsZEhNZ0ppWWdhWE5YYVdSblpYUW9ZMmhwYkdRcEtTQjdYRzRnSUNBZ0lDQWdJQ0FnSUNCcFppQW9kSGx3Wlc5bUlHTm9hV3hrTG1SbGMzUnliM2tnUFQwOUlGd2lablZ1WTNScGIyNWNJaWtnZTF4dUlDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUdoaGMxZHBaR2RsZEhNZ1BTQjBjblZsWEc0Z0lDQWdJQ0FnSUNBZ0lDQjlYRzRnSUNBZ0lDQWdJSDBnWld4elpTQnBaaUFvSVdoaGMxUm9kVzVyY3lBbUppQnBjMVJvZFc1cktHTm9hV3hrS1NrZ2UxeHVJQ0FnSUNBZ0lDQWdJQ0FnYUdGelZHaDFibXR6SUQwZ2RISjFaVHRjYmlBZ0lDQWdJQ0FnZlZ4dUlDQWdJSDFjYmx4dUlDQWdJSFJvYVhNdVkyOTFiblFnUFNCamIzVnVkQ0FySUdSbGMyTmxibVJoYm5SelhHNGdJQ0FnZEdocGN5NW9ZWE5YYVdSblpYUnpJRDBnYUdGelYybGtaMlYwYzF4dUlDQWdJSFJvYVhNdWFHRnpWR2gxYm10eklEMGdhR0Z6VkdoMWJtdHpYRzRnSUNBZ2RHaHBjeTVvYjI5cmN5QTlJR2h2YjJ0elhHNGdJQ0FnZEdocGN5NWtaWE5qWlc1a1lXNTBTRzl2YTNNZ1BTQmtaWE5qWlc1a1lXNTBTRzl2YTNOY2JuMWNibHh1Vm1seWRIVmhiRTV2WkdVdWNISnZkRzkwZVhCbExuWmxjbk5wYjI0Z1BTQjJaWEp6YVc5dVhHNVdhWEowZFdGc1RtOWtaUzV3Y205MGIzUjVjR1V1ZEhsd1pTQTlJRndpVm1seWRIVmhiRTV2WkdWY0lseHVYRzU5TEh0Y0lpNHZhWE10ZEdoMWJtdGNJam95TlN4Y0lpNHZhWE10ZG1odmIydGNJam95Tml4Y0lpNHZhWE10ZG01dlpHVmNJam95Tnl4Y0lpNHZhWE10ZDJsa1oyVjBYQ0k2TWprc1hDSXVMM1psY25OcGIyNWNJam96TUgxZExETXlPbHRtZFc1amRHbHZiaWh5WlhGMWFYSmxMRzF2WkhWc1pTeGxlSEJ2Y25SektYdGNiblpoY2lCMlpYSnphVzl1SUQwZ2NtVnhkV2x5WlNoY0lpNHZkbVZ5YzJsdmJsd2lLVnh1WEc1V2FYSjBkV0ZzVUdGMFkyZ3VUazlPUlNBOUlEQmNibFpwY25SMVlXeFFZWFJqYUM1V1ZFVllWQ0E5SURGY2JsWnBjblIxWVd4UVlYUmphQzVXVGs5RVJTQTlJREpjYmxacGNuUjFZV3hRWVhSamFDNVhTVVJIUlZRZ1BTQXpYRzVXYVhKMGRXRnNVR0YwWTJndVVGSlBVRk1nUFNBMFhHNVdhWEowZFdGc1VHRjBZMmd1VDFKRVJWSWdQU0ExWEc1V2FYSjBkV0ZzVUdGMFkyZ3VTVTVUUlZKVUlEMGdObHh1Vm1seWRIVmhiRkJoZEdOb0xsSkZUVTlXUlNBOUlEZGNibFpwY25SMVlXeFFZWFJqYUM1VVNGVk9TeUE5SURoY2JseHViVzlrZFd4bExtVjRjRzl5ZEhNZ1BTQldhWEowZFdGc1VHRjBZMmhjYmx4dVpuVnVZM1JwYjI0Z1ZtbHlkSFZoYkZCaGRHTm9LSFI1Y0dVc0lIWk9iMlJsTENCd1lYUmphQ2tnZTF4dUlDQWdJSFJvYVhNdWRIbHdaU0E5SUU1MWJXSmxjaWgwZVhCbEtWeHVJQ0FnSUhSb2FYTXVkazV2WkdVZ1BTQjJUbTlrWlZ4dUlDQWdJSFJvYVhNdWNHRjBZMmdnUFNCd1lYUmphRnh1ZlZ4dVhHNVdhWEowZFdGc1VHRjBZMmd1Y0hKdmRHOTBlWEJsTG5abGNuTnBiMjRnUFNCMlpYSnphVzl1WEc1V2FYSjBkV0ZzVUdGMFkyZ3VjSEp2ZEc5MGVYQmxMblI1Y0dVZ1BTQmNJbFpwY25SMVlXeFFZWFJqYUZ3aVhHNWNibjBzZTF3aUxpOTJaWEp6YVc5dVhDSTZNekI5WFN3ek16cGJablZ1WTNScGIyNG9jbVZ4ZFdseVpTeHRiMlIxYkdVc1pYaHdiM0owY3lsN1hHNTJZWElnZG1WeWMybHZiaUE5SUhKbGNYVnBjbVVvWENJdUwzWmxjbk5wYjI1Y0lpbGNibHh1Ylc5a2RXeGxMbVY0Y0c5eWRITWdQU0JXYVhKMGRXRnNWR1Y0ZEZ4dVhHNW1kVzVqZEdsdmJpQldhWEowZFdGc1ZHVjRkQ2gwWlhoMEtTQjdYRzRnSUNBZ2RHaHBjeTUwWlhoMElEMGdVM1J5YVc1bktIUmxlSFFwWEc1OVhHNWNibFpwY25SMVlXeFVaWGgwTG5CeWIzUnZkSGx3WlM1MlpYSnphVzl1SUQwZ2RtVnljMmx2Ymx4dVZtbHlkSFZoYkZSbGVIUXVjSEp2ZEc5MGVYQmxMblI1Y0dVZ1BTQmNJbFpwY25SMVlXeFVaWGgwWENKY2JseHVmU3g3WENJdUwzWmxjbk5wYjI1Y0lqb3pNSDFkTERNME9sdG1kVzVqZEdsdmJpaHlaWEYxYVhKbExHMXZaSFZzWlN4bGVIQnZjblJ6S1h0Y2JuWmhjaUJwYzA5aWFtVmpkQ0E5SUhKbGNYVnBjbVVvWENKcGN5MXZZbXBsWTNSY0lpbGNiblpoY2lCcGMwaHZiMnNnUFNCeVpYRjFhWEpsS0Z3aUxpNHZkbTV2WkdVdmFYTXRkbWh2YjJ0Y0lpbGNibHh1Ylc5a2RXeGxMbVY0Y0c5eWRITWdQU0JrYVdabVVISnZjSE5jYmx4dVpuVnVZM1JwYjI0Z1pHbG1abEJ5YjNCektHRXNJR0lwSUh0Y2JpQWdJQ0IyWVhJZ1pHbG1abHh1WEc0Z0lDQWdabTl5SUNoMllYSWdZVXRsZVNCcGJpQmhLU0I3WEc0Z0lDQWdJQ0FnSUdsbUlDZ2hLR0ZMWlhrZ2FXNGdZaWtwSUh0Y2JpQWdJQ0FnSUNBZ0lDQWdJR1JwWm1ZZ1BTQmthV1ptSUh4OElIdDlYRzRnSUNBZ0lDQWdJQ0FnSUNCa2FXWm1XMkZMWlhsZElEMGdkVzVrWldacGJtVmtYRzRnSUNBZ0lDQWdJSDFjYmx4dUlDQWdJQ0FnSUNCMllYSWdZVlpoYkhWbElEMGdZVnRoUzJWNVhWeHVJQ0FnSUNBZ0lDQjJZWElnWWxaaGJIVmxJRDBnWWx0aFMyVjVYVnh1WEc0Z0lDQWdJQ0FnSUdsbUlDaGhWbUZzZFdVZ1BUMDlJR0pXWVd4MVpTa2dlMXh1SUNBZ0lDQWdJQ0FnSUNBZ1kyOXVkR2x1ZFdWY2JpQWdJQ0FnSUNBZ2ZTQmxiSE5sSUdsbUlDaHBjMDlpYW1WamRDaGhWbUZzZFdVcElDWW1JR2x6VDJKcVpXTjBLR0pXWVd4MVpTa3BJSHRjYmlBZ0lDQWdJQ0FnSUNBZ0lHbG1JQ2huWlhSUWNtOTBiM1I1Y0dVb1lsWmhiSFZsS1NBaFBUMGdaMlYwVUhKdmRHOTBlWEJsS0dGV1lXeDFaU2twSUh0Y2JpQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNCa2FXWm1JRDBnWkdsbVppQjhmQ0I3ZlZ4dUlDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUdScFptWmJZVXRsZVYwZ1BTQmlWbUZzZFdWY2JpQWdJQ0FnSUNBZ0lDQWdJSDBnWld4elpTQnBaaUFvYVhOSWIyOXJLR0pXWVd4MVpTa3BJSHRjYmlBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnWkdsbVppQTlJR1JwWm1ZZ2ZId2dlMzFjYmlBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnWkdsbVpsdGhTMlY1WFNBOUlHSldZV3gxWlZ4dUlDQWdJQ0FnSUNBZ0lDQWdmU0JsYkhObElIdGNiaUFnSUNBZ0lDQWdJQ0FnSUNBZ0lDQjJZWElnYjJKcVpXTjBSR2xtWmlBOUlHUnBabVpRY205d2N5aGhWbUZzZFdVc0lHSldZV3gxWlNsY2JpQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNCcFppQW9iMkpxWldOMFJHbG1aaWtnZTF4dUlDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQmthV1ptSUQwZ1pHbG1aaUI4ZkNCN2ZWeHVJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0JrYVdabVcyRkxaWGxkSUQwZ2IySnFaV04wUkdsbVpseHVJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lIMWNiaUFnSUNBZ0lDQWdJQ0FnSUgxY2JpQWdJQ0FnSUNBZ2ZTQmxiSE5sSUh0Y2JpQWdJQ0FnSUNBZ0lDQWdJR1JwWm1ZZ1BTQmthV1ptSUh4OElIdDlYRzRnSUNBZ0lDQWdJQ0FnSUNCa2FXWm1XMkZMWlhsZElEMGdZbFpoYkhWbFhHNGdJQ0FnSUNBZ0lIMWNiaUFnSUNCOVhHNWNiaUFnSUNCbWIzSWdLSFpoY2lCaVMyVjVJR2x1SUdJcElIdGNiaUFnSUNBZ0lDQWdhV1lnS0NFb1lrdGxlU0JwYmlCaEtTa2dlMXh1SUNBZ0lDQWdJQ0FnSUNBZ1pHbG1aaUE5SUdScFptWWdmSHdnZTMxY2JpQWdJQ0FnSUNBZ0lDQWdJR1JwWm1aYllrdGxlVjBnUFNCaVcySkxaWGxkWEc0Z0lDQWdJQ0FnSUgxY2JpQWdJQ0I5WEc1Y2JpQWdJQ0J5WlhSMWNtNGdaR2xtWmx4dWZWeHVYRzVtZFc1amRHbHZiaUJuWlhSUWNtOTBiM1I1Y0dVb2RtRnNkV1VwSUh0Y2JpQWdhV1lnS0U5aWFtVmpkQzVuWlhSUWNtOTBiM1I1Y0dWUFppa2dlMXh1SUNBZ0lISmxkSFZ5YmlCUFltcGxZM1F1WjJWMFVISnZkRzkwZVhCbFQyWW9kbUZzZFdVcFhHNGdJSDBnWld4elpTQnBaaUFvZG1Gc2RXVXVYMTl3Y205MGIxOWZLU0I3WEc0Z0lDQWdjbVYwZFhKdUlIWmhiSFZsTGw5ZmNISnZkRzlmWDF4dUlDQjlJR1ZzYzJVZ2FXWWdLSFpoYkhWbExtTnZibk4wY25WamRHOXlLU0I3WEc0Z0lDQWdjbVYwZFhKdUlIWmhiSFZsTG1OdmJuTjBjblZqZEc5eUxuQnliM1J2ZEhsd1pWeHVJQ0I5WEc1OVhHNWNibjBzZTF3aUxpNHZkbTV2WkdVdmFYTXRkbWh2YjJ0Y0lqb3lOaXhjSW1sekxXOWlhbVZqZEZ3aU9qRXhmVjBzTXpVNlcyWjFibU4wYVc5dUtISmxjWFZwY21Vc2JXOWtkV3hsTEdWNGNHOXlkSE1wZTF4dWRtRnlJR2x6UVhKeVlYa2dQU0J5WlhGMWFYSmxLRndpZUMxcGN5MWhjbkpoZVZ3aUtWeHVYRzUyWVhJZ1ZsQmhkR05vSUQwZ2NtVnhkV2x5WlNoY0lpNHVMM1p1YjJSbEwzWndZWFJqYUZ3aUtWeHVkbUZ5SUdselZrNXZaR1VnUFNCeVpYRjFhWEpsS0Z3aUxpNHZkbTV2WkdVdmFYTXRkbTV2WkdWY0lpbGNiblpoY2lCcGMxWlVaWGgwSUQwZ2NtVnhkV2x5WlNoY0lpNHVMM1p1YjJSbEwybHpMWFowWlhoMFhDSXBYRzUyWVhJZ2FYTlhhV1JuWlhRZ1BTQnlaWEYxYVhKbEtGd2lMaTR2ZG01dlpHVXZhWE10ZDJsa1oyVjBYQ0lwWEc1MllYSWdhWE5VYUhWdWF5QTlJSEpsY1hWcGNtVW9YQ0l1TGk5MmJtOWtaUzlwY3kxMGFIVnVhMXdpS1Z4dWRtRnlJR2hoYm1Sc1pWUm9kVzVySUQwZ2NtVnhkV2x5WlNoY0lpNHVMM1p1YjJSbEwyaGhibVJzWlMxMGFIVnVhMXdpS1Z4dVhHNTJZWElnWkdsbVpsQnliM0J6SUQwZ2NtVnhkV2x5WlNoY0lpNHZaR2xtWmkxd2NtOXdjMXdpS1Z4dVhHNXRiMlIxYkdVdVpYaHdiM0owY3lBOUlHUnBabVpjYmx4dVpuVnVZM1JwYjI0Z1pHbG1aaWhoTENCaUtTQjdYRzRnSUNBZ2RtRnlJSEJoZEdOb0lEMGdleUJoT2lCaElIMWNiaUFnSUNCM1lXeHJLR0VzSUdJc0lIQmhkR05vTENBd0tWeHVJQ0FnSUhKbGRIVnliaUJ3WVhSamFGeHVmVnh1WEc1bWRXNWpkR2x2YmlCM1lXeHJLR0VzSUdJc0lIQmhkR05vTENCcGJtUmxlQ2tnZTF4dUlDQWdJR2xtSUNoaElEMDlQU0JpS1NCN1hHNGdJQ0FnSUNBZ0lISmxkSFZ5Ymx4dUlDQWdJSDFjYmx4dUlDQWdJSFpoY2lCaGNIQnNlU0E5SUhCaGRHTm9XMmx1WkdWNFhWeHVJQ0FnSUhaaGNpQmhjSEJzZVVOc1pXRnlJRDBnWm1Gc2MyVmNibHh1SUNBZ0lHbG1JQ2hwYzFSb2RXNXJLR0VwSUh4OElHbHpWR2gxYm1zb1lpa3BJSHRjYmlBZ0lDQWdJQ0FnZEdoMWJtdHpLR0VzSUdJc0lIQmhkR05vTENCcGJtUmxlQ2xjYmlBZ0lDQjlJR1ZzYzJVZ2FXWWdLR0lnUFQwZ2JuVnNiQ2tnZTF4dVhHNGdJQ0FnSUNBZ0lDOHZJRWxtSUdFZ2FYTWdZU0IzYVdSblpYUWdkMlVnZDJsc2JDQmhaR1FnWVNCeVpXMXZkbVVnY0dGMFkyZ2dabTl5SUdsMFhHNGdJQ0FnSUNBZ0lDOHZJRTkwYUdWeWQybHpaU0JoYm5rZ1kyaHBiR1FnZDJsa1oyVjBjeTlvYjI5cmN5QnRkWE4wSUdKbElHUmxjM1J5YjNsbFpDNWNiaUFnSUNBZ0lDQWdMeThnVkdocGN5QndjbVYyWlc1MGN5QmhaR1JwYm1jZ2RIZHZJSEpsYlc5MlpTQndZWFJqYUdWeklHWnZjaUJoSUhkcFpHZGxkQzVjYmlBZ0lDQWdJQ0FnYVdZZ0tDRnBjMWRwWkdkbGRDaGhLU2tnZTF4dUlDQWdJQ0FnSUNBZ0lDQWdZMnhsWVhKVGRHRjBaU2hoTENCd1lYUmphQ3dnYVc1a1pYZ3BYRzRnSUNBZ0lDQWdJQ0FnSUNCaGNIQnNlU0E5SUhCaGRHTm9XMmx1WkdWNFhWeHVJQ0FnSUNBZ0lDQjlYRzVjYmlBZ0lDQWdJQ0FnWVhCd2JIa2dQU0JoY0hCbGJtUlFZWFJqYUNoaGNIQnNlU3dnYm1WM0lGWlFZWFJqYUNoV1VHRjBZMmd1VWtWTlQxWkZMQ0JoTENCaUtTbGNiaUFnSUNCOUlHVnNjMlVnYVdZZ0tHbHpWazV2WkdVb1lpa3BJSHRjYmlBZ0lDQWdJQ0FnYVdZZ0tHbHpWazV2WkdVb1lTa3BJSHRjYmlBZ0lDQWdJQ0FnSUNBZ0lHbG1JQ2hoTG5SaFowNWhiV1VnUFQwOUlHSXVkR0ZuVG1GdFpTQW1KbHh1SUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJR0V1Ym1GdFpYTndZV05sSUQwOVBTQmlMbTVoYldWemNHRmpaU0FtSmx4dUlDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUdFdWEyVjVJRDA5UFNCaUxtdGxlU2tnZTF4dUlDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUhaaGNpQndjbTl3YzFCaGRHTm9JRDBnWkdsbVpsQnliM0J6S0dFdWNISnZjR1Z5ZEdsbGN5d2dZaTV3Y205d1pYSjBhV1Z6S1Z4dUlDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUdsbUlDaHdjbTl3YzFCaGRHTm9LU0I3WEc0Z0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lHRndjR3g1SUQwZ1lYQndaVzVrVUdGMFkyZ29ZWEJ3Ykhrc1hHNGdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNCdVpYY2dWbEJoZEdOb0tGWlFZWFJqYUM1UVVrOVFVeXdnWVN3Z2NISnZjSE5RWVhSamFDa3BYRzRnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdmVnh1SUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJR0Z3Y0d4NUlEMGdaR2xtWmtOb2FXeGtjbVZ1S0dFc0lHSXNJSEJoZEdOb0xDQmhjSEJzZVN3Z2FXNWtaWGdwWEc0Z0lDQWdJQ0FnSUNBZ0lDQjlJR1ZzYzJVZ2UxeHVJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lHRndjR3g1SUQwZ1lYQndaVzVrVUdGMFkyZ29ZWEJ3Ykhrc0lHNWxkeUJXVUdGMFkyZ29WbEJoZEdOb0xsWk9UMFJGTENCaExDQmlLU2xjYmlBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0JoY0hCc2VVTnNaV0Z5SUQwZ2RISjFaVnh1SUNBZ0lDQWdJQ0FnSUNBZ2ZWeHVJQ0FnSUNBZ0lDQjlJR1ZzYzJVZ2UxeHVJQ0FnSUNBZ0lDQWdJQ0FnWVhCd2JIa2dQU0JoY0hCbGJtUlFZWFJqYUNoaGNIQnNlU3dnYm1WM0lGWlFZWFJqYUNoV1VHRjBZMmd1Vms1UFJFVXNJR0VzSUdJcEtWeHVJQ0FnSUNBZ0lDQWdJQ0FnWVhCd2JIbERiR1ZoY2lBOUlIUnlkV1ZjYmlBZ0lDQWdJQ0FnZlZ4dUlDQWdJSDBnWld4elpTQnBaaUFvYVhOV1ZHVjRkQ2hpS1NrZ2UxeHVJQ0FnSUNBZ0lDQnBaaUFvSVdselZsUmxlSFFvWVNrcElIdGNiaUFnSUNBZ0lDQWdJQ0FnSUdGd2NHeDVJRDBnWVhCd1pXNWtVR0YwWTJnb1lYQndiSGtzSUc1bGR5QldVR0YwWTJnb1ZsQmhkR05vTGxaVVJWaFVMQ0JoTENCaUtTbGNiaUFnSUNBZ0lDQWdJQ0FnSUdGd2NHeDVRMnhsWVhJZ1BTQjBjblZsWEc0Z0lDQWdJQ0FnSUgwZ1pXeHpaU0JwWmlBb1lTNTBaWGgwSUNFOVBTQmlMblJsZUhRcElIdGNiaUFnSUNBZ0lDQWdJQ0FnSUdGd2NHeDVJRDBnWVhCd1pXNWtVR0YwWTJnb1lYQndiSGtzSUc1bGR5QldVR0YwWTJnb1ZsQmhkR05vTGxaVVJWaFVMQ0JoTENCaUtTbGNiaUFnSUNBZ0lDQWdmVnh1SUNBZ0lIMGdaV3h6WlNCcFppQW9hWE5YYVdSblpYUW9ZaWtwSUh0Y2JpQWdJQ0FnSUNBZ2FXWWdLQ0ZwYzFkcFpHZGxkQ2hoS1NrZ2UxeHVJQ0FnSUNBZ0lDQWdJQ0FnWVhCd2JIbERiR1ZoY2lBOUlIUnlkV1ZjYmlBZ0lDQWdJQ0FnZlZ4dVhHNGdJQ0FnSUNBZ0lHRndjR3g1SUQwZ1lYQndaVzVrVUdGMFkyZ29ZWEJ3Ykhrc0lHNWxkeUJXVUdGMFkyZ29WbEJoZEdOb0xsZEpSRWRGVkN3Z1lTd2dZaWtwWEc0Z0lDQWdmVnh1WEc0Z0lDQWdhV1lnS0dGd2NHeDVLU0I3WEc0Z0lDQWdJQ0FnSUhCaGRHTm9XMmx1WkdWNFhTQTlJR0Z3Y0d4NVhHNGdJQ0FnZlZ4dVhHNGdJQ0FnYVdZZ0tHRndjR3g1UTJ4bFlYSXBJSHRjYmlBZ0lDQWdJQ0FnWTJ4bFlYSlRkR0YwWlNoaExDQndZWFJqYUN3Z2FXNWtaWGdwWEc0Z0lDQWdmVnh1ZlZ4dVhHNW1kVzVqZEdsdmJpQmthV1ptUTJocGJHUnlaVzRvWVN3Z1lpd2djR0YwWTJnc0lHRndjR3g1TENCcGJtUmxlQ2tnZTF4dUlDQWdJSFpoY2lCaFEyaHBiR1J5Wlc0Z1BTQmhMbU5vYVd4a2NtVnVYRzRnSUNBZ2RtRnlJRzl5WkdWeVpXUlRaWFFnUFNCeVpXOXlaR1Z5S0dGRGFHbHNaSEpsYml3Z1lpNWphR2xzWkhKbGJpbGNiaUFnSUNCMllYSWdZa05vYVd4a2NtVnVJRDBnYjNKa1pYSmxaRk5sZEM1amFHbHNaSEpsYmx4dVhHNGdJQ0FnZG1GeUlHRk1aVzRnUFNCaFEyaHBiR1J5Wlc0dWJHVnVaM1JvWEc0Z0lDQWdkbUZ5SUdKTVpXNGdQU0JpUTJocGJHUnlaVzR1YkdWdVozUm9YRzRnSUNBZ2RtRnlJR3hsYmlBOUlHRk1aVzRnUGlCaVRHVnVJRDhnWVV4bGJpQTZJR0pNWlc1Y2JseHVJQ0FnSUdadmNpQW9kbUZ5SUdrZ1BTQXdPeUJwSUR3Z2JHVnVPeUJwS3lzcElIdGNiaUFnSUNBZ0lDQWdkbUZ5SUd4bFpuUk9iMlJsSUQwZ1lVTm9hV3hrY21WdVcybGRYRzRnSUNBZ0lDQWdJSFpoY2lCeWFXZG9kRTV2WkdVZ1BTQmlRMmhwYkdSeVpXNWJhVjFjYmlBZ0lDQWdJQ0FnYVc1a1pYZ2dLejBnTVZ4dVhHNGdJQ0FnSUNBZ0lHbG1JQ2doYkdWbWRFNXZaR1VwSUh0Y2JpQWdJQ0FnSUNBZ0lDQWdJR2xtSUNoeWFXZG9kRTV2WkdVcElIdGNiaUFnSUNBZ0lDQWdJQ0FnSUNBZ0lDQXZMeUJGZUdObGMzTWdibTlrWlhNZ2FXNGdZaUJ1WldWa0lIUnZJR0psSUdGa1pHVmtYRzRnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdZWEJ3YkhrZ1BTQmhjSEJsYm1SUVlYUmphQ2hoY0hCc2VTeGNiaUFnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnYm1WM0lGWlFZWFJqYUNoV1VHRjBZMmd1U1U1VFJWSlVMQ0J1ZFd4c0xDQnlhV2RvZEU1dlpHVXBLVnh1SUNBZ0lDQWdJQ0FnSUNBZ2ZWeHVJQ0FnSUNBZ0lDQjlJR1ZzYzJVZ2UxeHVJQ0FnSUNBZ0lDQWdJQ0FnZDJGc2F5aHNaV1owVG05a1pTd2djbWxuYUhST2IyUmxMQ0J3WVhSamFDd2dhVzVrWlhncFhHNGdJQ0FnSUNBZ0lIMWNibHh1SUNBZ0lDQWdJQ0JwWmlBb2FYTldUbTlrWlNoc1pXWjBUbTlrWlNrZ0ppWWdiR1ZtZEU1dlpHVXVZMjkxYm5RcElIdGNiaUFnSUNBZ0lDQWdJQ0FnSUdsdVpHVjRJQ3M5SUd4bFpuUk9iMlJsTG1OdmRXNTBYRzRnSUNBZ0lDQWdJSDFjYmlBZ0lDQjlYRzVjYmlBZ0lDQnBaaUFvYjNKa1pYSmxaRk5sZEM1dGIzWmxjeWtnZTF4dUlDQWdJQ0FnSUNBdkx5QlNaVzl5WkdWeUlHNXZaR1Z6SUd4aGMzUmNiaUFnSUNBZ0lDQWdZWEJ3YkhrZ1BTQmhjSEJsYm1SUVlYUmphQ2hoY0hCc2VTd2dibVYzSUZaUVlYUmphQ2hjYmlBZ0lDQWdJQ0FnSUNBZ0lGWlFZWFJqYUM1UFVrUkZVaXhjYmlBZ0lDQWdJQ0FnSUNBZ0lHRXNYRzRnSUNBZ0lDQWdJQ0FnSUNCdmNtUmxjbVZrVTJWMExtMXZkbVZ6WEc0Z0lDQWdJQ0FnSUNrcFhHNGdJQ0FnZlZ4dVhHNGdJQ0FnY21WMGRYSnVJR0Z3Y0d4NVhHNTlYRzVjYm1aMWJtTjBhVzl1SUdOc1pXRnlVM1JoZEdVb2RrNXZaR1VzSUhCaGRHTm9MQ0JwYm1SbGVDa2dlMXh1SUNBZ0lDOHZJRlJQUkU4NklFMWhhMlVnZEdocGN5QmhJSE5wYm1kc1pTQjNZV3hyTENCdWIzUWdkSGR2WEc0Z0lDQWdkVzVvYjI5cktIWk9iMlJsTENCd1lYUmphQ3dnYVc1a1pYZ3BYRzRnSUNBZ1pHVnpkSEp2ZVZkcFpHZGxkSE1vZGs1dlpHVXNJSEJoZEdOb0xDQnBibVJsZUNsY2JuMWNibHh1THk4Z1VHRjBZMmdnY21WamIzSmtjeUJtYjNJZ1lXeHNJR1JsYzNSeWIzbGxaQ0IzYVdSblpYUnpJRzExYzNRZ1ltVWdZV1JrWldRZ1ltVmpZWFZ6WlNCM1pTQnVaV1ZrWEc0dkx5QmhJRVJQVFNCdWIyUmxJSEpsWm1WeVpXNWpaU0JtYjNJZ2RHaGxJR1JsYzNSeWIza2dablZ1WTNScGIyNWNibVoxYm1OMGFXOXVJR1JsYzNSeWIzbFhhV1JuWlhSektIWk9iMlJsTENCd1lYUmphQ3dnYVc1a1pYZ3BJSHRjYmlBZ0lDQnBaaUFvYVhOWGFXUm5aWFFvZGs1dlpHVXBLU0I3WEc0Z0lDQWdJQ0FnSUdsbUlDaDBlWEJsYjJZZ2RrNXZaR1V1WkdWemRISnZlU0E5UFQwZ1hDSm1kVzVqZEdsdmJsd2lLU0I3WEc0Z0lDQWdJQ0FnSUNBZ0lDQndZWFJqYUZ0cGJtUmxlRjBnUFNCaGNIQmxibVJRWVhSamFDaGNiaUFnSUNBZ0lDQWdJQ0FnSUNBZ0lDQndZWFJqYUZ0cGJtUmxlRjBzWEc0Z0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnYm1WM0lGWlFZWFJqYUNoV1VHRjBZMmd1VWtWTlQxWkZMQ0IyVG05a1pTd2diblZzYkNsY2JpQWdJQ0FnSUNBZ0lDQWdJQ2xjYmlBZ0lDQWdJQ0FnZlZ4dUlDQWdJSDBnWld4elpTQnBaaUFvYVhOV1RtOWtaU2gyVG05a1pTa2dKaVlnS0haT2IyUmxMbWhoYzFkcFpHZGxkSE1nZkh3Z2RrNXZaR1V1YUdGelZHaDFibXR6S1NrZ2UxeHVJQ0FnSUNBZ0lDQjJZWElnWTJocGJHUnlaVzRnUFNCMlRtOWtaUzVqYUdsc1pISmxibHh1SUNBZ0lDQWdJQ0IyWVhJZ2JHVnVJRDBnWTJocGJHUnlaVzR1YkdWdVozUm9YRzRnSUNBZ0lDQWdJR1p2Y2lBb2RtRnlJR2tnUFNBd095QnBJRHdnYkdWdU95QnBLeXNwSUh0Y2JpQWdJQ0FnSUNBZ0lDQWdJSFpoY2lCamFHbHNaQ0E5SUdOb2FXeGtjbVZ1VzJsZFhHNGdJQ0FnSUNBZ0lDQWdJQ0JwYm1SbGVDQXJQU0F4WEc1Y2JpQWdJQ0FnSUNBZ0lDQWdJR1JsYzNSeWIzbFhhV1JuWlhSektHTm9hV3hrTENCd1lYUmphQ3dnYVc1a1pYZ3BYRzVjYmlBZ0lDQWdJQ0FnSUNBZ0lHbG1JQ2hwYzFaT2IyUmxLR05vYVd4a0tTQW1KaUJqYUdsc1pDNWpiM1Z1ZENrZ2UxeHVJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lHbHVaR1Y0SUNzOUlHTm9hV3hrTG1OdmRXNTBYRzRnSUNBZ0lDQWdJQ0FnSUNCOVhHNGdJQ0FnSUNBZ0lIMWNiaUFnSUNCOUlHVnNjMlVnYVdZZ0tHbHpWR2gxYm1zb2RrNXZaR1VwS1NCN1hHNGdJQ0FnSUNBZ0lIUm9kVzVyY3loMlRtOWtaU3dnYm5Wc2JDd2djR0YwWTJnc0lHbHVaR1Y0S1Z4dUlDQWdJSDFjYm4xY2JseHVMeThnUTNKbFlYUmxJR0VnYzNWaUxYQmhkR05vSUdadmNpQjBhSFZ1YTNOY2JtWjFibU4wYVc5dUlIUm9kVzVyY3loaExDQmlMQ0J3WVhSamFDd2dhVzVrWlhncElIdGNiaUFnSUNCMllYSWdibTlrWlhNZ1BTQm9ZVzVrYkdWVWFIVnVheWhoTENCaUtWeHVJQ0FnSUhaaGNpQjBhSFZ1YTFCaGRHTm9JRDBnWkdsbVppaHViMlJsY3k1aExDQnViMlJsY3k1aUtWeHVJQ0FnSUdsbUlDaG9ZWE5RWVhSamFHVnpLSFJvZFc1clVHRjBZMmdwS1NCN1hHNGdJQ0FnSUNBZ0lIQmhkR05vVzJsdVpHVjRYU0E5SUc1bGR5QldVR0YwWTJnb1ZsQmhkR05vTGxSSVZVNUxMQ0J1ZFd4c0xDQjBhSFZ1YTFCaGRHTm9LVnh1SUNBZ0lIMWNibjFjYmx4dVpuVnVZM1JwYjI0Z2FHRnpVR0YwWTJobGN5aHdZWFJqYUNrZ2UxeHVJQ0FnSUdadmNpQW9kbUZ5SUdsdVpHVjRJR2x1SUhCaGRHTm9LU0I3WEc0Z0lDQWdJQ0FnSUdsbUlDaHBibVJsZUNBaFBUMGdYQ0poWENJcElIdGNiaUFnSUNBZ0lDQWdJQ0FnSUhKbGRIVnliaUIwY25WbFhHNGdJQ0FnSUNBZ0lIMWNiaUFnSUNCOVhHNWNiaUFnSUNCeVpYUjFjbTRnWm1Gc2MyVmNibjFjYmx4dUx5OGdSWGhsWTNWMFpTQm9iMjlyY3lCM2FHVnVJSFIzYnlCdWIyUmxjeUJoY21VZ2FXUmxiblJwWTJGc1hHNW1kVzVqZEdsdmJpQjFibWh2YjJzb2RrNXZaR1VzSUhCaGRHTm9MQ0JwYm1SbGVDa2dlMXh1SUNBZ0lHbG1JQ2hwYzFaT2IyUmxLSFpPYjJSbEtTa2dlMXh1SUNBZ0lDQWdJQ0JwWmlBb2RrNXZaR1V1YUc5dmEzTXBJSHRjYmlBZ0lDQWdJQ0FnSUNBZ0lIQmhkR05vVzJsdVpHVjRYU0E5SUdGd2NHVnVaRkJoZEdOb0tGeHVJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lIQmhkR05vVzJsdVpHVjRYU3hjYmlBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0J1WlhjZ1ZsQmhkR05vS0Z4dUlDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQldVR0YwWTJndVVGSlBVRk1zWEc0Z0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lIWk9iMlJsTEZ4dUlDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQjFibVJsWm1sdVpXUkxaWGx6S0haT2IyUmxMbWh2YjJ0ektWeHVJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDbGNiaUFnSUNBZ0lDQWdJQ0FnSUNsY2JpQWdJQ0FnSUNBZ2ZWeHVYRzRnSUNBZ0lDQWdJR2xtSUNoMlRtOWtaUzVrWlhOalpXNWtZVzUwU0c5dmEzTWdmSHdnZGs1dlpHVXVhR0Z6VkdoMWJtdHpLU0I3WEc0Z0lDQWdJQ0FnSUNBZ0lDQjJZWElnWTJocGJHUnlaVzRnUFNCMlRtOWtaUzVqYUdsc1pISmxibHh1SUNBZ0lDQWdJQ0FnSUNBZ2RtRnlJR3hsYmlBOUlHTm9hV3hrY21WdUxteGxibWQwYUZ4dUlDQWdJQ0FnSUNBZ0lDQWdabTl5SUNoMllYSWdhU0E5SURBN0lHa2dQQ0JzWlc0N0lHa3JLeWtnZTF4dUlDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUhaaGNpQmphR2xzWkNBOUlHTm9hV3hrY21WdVcybGRYRzRnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdhVzVrWlhnZ0t6MGdNVnh1WEc0Z0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnZFc1b2IyOXJLR05vYVd4a0xDQndZWFJqYUN3Z2FXNWtaWGdwWEc1Y2JpQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNCcFppQW9hWE5XVG05a1pTaGphR2xzWkNrZ0ppWWdZMmhwYkdRdVkyOTFiblFwSUh0Y2JpQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdhVzVrWlhnZ0t6MGdZMmhwYkdRdVkyOTFiblJjYmlBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0I5WEc0Z0lDQWdJQ0FnSUNBZ0lDQjlYRzRnSUNBZ0lDQWdJSDFjYmlBZ0lDQjlJR1ZzYzJVZ2FXWWdLR2x6VkdoMWJtc29kazV2WkdVcEtTQjdYRzRnSUNBZ0lDQWdJSFJvZFc1cmN5aDJUbTlrWlN3Z2JuVnNiQ3dnY0dGMFkyZ3NJR2x1WkdWNEtWeHVJQ0FnSUgxY2JuMWNibHh1Wm5WdVkzUnBiMjRnZFc1a1pXWnBibVZrUzJWNWN5aHZZbW9wSUh0Y2JpQWdJQ0IyWVhJZ2NtVnpkV3gwSUQwZ2UzMWNibHh1SUNBZ0lHWnZjaUFvZG1GeUlHdGxlU0JwYmlCdlltb3BJSHRjYmlBZ0lDQWdJQ0FnY21WemRXeDBXMnRsZVYwZ1BTQjFibVJsWm1sdVpXUmNiaUFnSUNCOVhHNWNiaUFnSUNCeVpYUjFjbTRnY21WemRXeDBYRzU5WEc1Y2JpOHZJRXhwYzNRZ1pHbG1aaXdnYm1GcGRtVWdiR1ZtZENCMGJ5QnlhV2RvZENCeVpXOXlaR1Z5YVc1blhHNW1kVzVqZEdsdmJpQnlaVzl5WkdWeUtHRkRhR2xzWkhKbGJpd2dZa05vYVd4a2NtVnVLU0I3WEc0Z0lDQWdMeThnVHloTktTQjBhVzFsTENCUEtFMHBJRzFsYlc5eWVWeHVJQ0FnSUhaaGNpQmlRMmhwYkdSSmJtUmxlQ0E5SUd0bGVVbHVaR1Y0S0dKRGFHbHNaSEpsYmlsY2JpQWdJQ0IyWVhJZ1lrdGxlWE1nUFNCaVEyaHBiR1JKYm1SbGVDNXJaWGx6WEc0Z0lDQWdkbUZ5SUdKR2NtVmxJRDBnWWtOb2FXeGtTVzVrWlhndVpuSmxaVnh1WEc0Z0lDQWdhV1lnS0dKR2NtVmxMbXhsYm1kMGFDQTlQVDBnWWtOb2FXeGtjbVZ1TG14bGJtZDBhQ2tnZTF4dUlDQWdJQ0FnSUNCeVpYUjFjbTRnZTF4dUlDQWdJQ0FnSUNBZ0lDQWdZMmhwYkdSeVpXNDZJR0pEYUdsc1pISmxiaXhjYmlBZ0lDQWdJQ0FnSUNBZ0lHMXZkbVZ6T2lCdWRXeHNYRzRnSUNBZ0lDQWdJSDFjYmlBZ0lDQjlYRzVjYmlBZ0lDQXZMeUJQS0U0cElIUnBiV1VzSUU4b1Rpa2diV1Z0YjNKNVhHNGdJQ0FnZG1GeUlHRkRhR2xzWkVsdVpHVjRJRDBnYTJWNVNXNWtaWGdvWVVOb2FXeGtjbVZ1S1Z4dUlDQWdJSFpoY2lCaFMyVjVjeUE5SUdGRGFHbHNaRWx1WkdWNExtdGxlWE5jYmlBZ0lDQjJZWElnWVVaeVpXVWdQU0JoUTJocGJHUkpibVJsZUM1bWNtVmxYRzVjYmlBZ0lDQnBaaUFvWVVaeVpXVXViR1Z1WjNSb0lEMDlQU0JoUTJocGJHUnlaVzR1YkdWdVozUm9LU0I3WEc0Z0lDQWdJQ0FnSUhKbGRIVnliaUI3WEc0Z0lDQWdJQ0FnSUNBZ0lDQmphR2xzWkhKbGJqb2dZa05vYVd4a2NtVnVMRnh1SUNBZ0lDQWdJQ0FnSUNBZ2JXOTJaWE02SUc1MWJHeGNiaUFnSUNBZ0lDQWdmVnh1SUNBZ0lIMWNibHh1SUNBZ0lDOHZJRThvVFVGWUtFNHNJRTBwS1NCdFpXMXZjbmxjYmlBZ0lDQjJZWElnYm1WM1EyaHBiR1J5Wlc0Z1BTQmJYVnh1WEc0Z0lDQWdkbUZ5SUdaeVpXVkpibVJsZUNBOUlEQmNiaUFnSUNCMllYSWdabkpsWlVOdmRXNTBJRDBnWWtaeVpXVXViR1Z1WjNSb1hHNGdJQ0FnZG1GeUlHUmxiR1YwWldSSmRHVnRjeUE5SURCY2JseHVJQ0FnSUM4dklFbDBaWEpoZEdVZ2RHaHliM1ZuYUNCaElHRnVaQ0J0WVhSamFDQmhJRzV2WkdVZ2FXNGdZbHh1SUNBZ0lDOHZJRThvVGlrZ2RHbHRaU3hjYmlBZ0lDQm1iM0lnS0haaGNpQnBJRDBnTUNBN0lHa2dQQ0JoUTJocGJHUnlaVzR1YkdWdVozUm9PeUJwS3lzcElIdGNiaUFnSUNBZ0lDQWdkbUZ5SUdGSmRHVnRJRDBnWVVOb2FXeGtjbVZ1VzJsZFhHNGdJQ0FnSUNBZ0lIWmhjaUJwZEdWdFNXNWtaWGhjYmx4dUlDQWdJQ0FnSUNCcFppQW9ZVWwwWlcwdWEyVjVLU0I3WEc0Z0lDQWdJQ0FnSUNBZ0lDQnBaaUFvWWt0bGVYTXVhR0Z6VDNkdVVISnZjR1Z5ZEhrb1lVbDBaVzB1YTJWNUtTa2dlMXh1SUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQzh2SUUxaGRHTm9JSFZ3SUhSb1pTQnZiR1FnYTJWNWMxeHVJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lHbDBaVzFKYm1SbGVDQTlJR0pMWlhselcyRkpkR1Z0TG10bGVWMWNiaUFnSUNBZ0lDQWdJQ0FnSUNBZ0lDQnVaWGREYUdsc1pISmxiaTV3ZFhOb0tHSkRhR2xzWkhKbGJsdHBkR1Z0U1c1a1pYaGRLVnh1WEc0Z0lDQWdJQ0FnSUNBZ0lDQjlJR1ZzYzJVZ2UxeHVJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDOHZJRkpsYlc5MlpTQnZiR1FnYTJWNVpXUWdhWFJsYlhOY2JpQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNCcGRHVnRTVzVrWlhnZ1BTQnBJQzBnWkdWc1pYUmxaRWwwWlcxekt5dGNiaUFnSUNBZ0lDQWdJQ0FnSUNBZ0lDQnVaWGREYUdsc1pISmxiaTV3ZFhOb0tHNTFiR3dwWEc0Z0lDQWdJQ0FnSUNBZ0lDQjlYRzRnSUNBZ0lDQWdJSDBnWld4elpTQjdYRzRnSUNBZ0lDQWdJQ0FnSUNBdkx5Qk5ZWFJqYUNCMGFHVWdhWFJsYlNCcGJpQmhJSGRwZEdnZ2RHaGxJRzVsZUhRZ1puSmxaU0JwZEdWdElHbHVJR0pjYmlBZ0lDQWdJQ0FnSUNBZ0lHbG1JQ2htY21WbFNXNWtaWGdnUENCbWNtVmxRMjkxYm5RcElIdGNiaUFnSUNBZ0lDQWdJQ0FnSUNBZ0lDQnBkR1Z0U1c1a1pYZ2dQU0JpUm5KbFpWdG1jbVZsU1c1a1pYZ3JLMTFjYmlBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0J1WlhkRGFHbHNaSEpsYmk1d2RYTm9LR0pEYUdsc1pISmxibHRwZEdWdFNXNWtaWGhkS1Z4dUlDQWdJQ0FnSUNBZ0lDQWdmU0JsYkhObElIdGNiaUFnSUNBZ0lDQWdJQ0FnSUNBZ0lDQXZMeUJVYUdWeVpTQmhjbVVnYm04Z1puSmxaU0JwZEdWdGN5QnBiaUJpSUhSdklHMWhkR05vSUhkcGRHaGNiaUFnSUNBZ0lDQWdJQ0FnSUNBZ0lDQXZMeUIwYUdVZ1puSmxaU0JwZEdWdGN5QnBiaUJoTENCemJ5QjBhR1VnWlhoMGNtRWdabkpsWlNCdWIyUmxjMXh1SUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQzh2SUdGeVpTQmtaV3hsZEdWa0xseHVJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lHbDBaVzFKYm1SbGVDQTlJR2tnTFNCa1pXeGxkR1ZrU1hSbGJYTXJLMXh1SUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJRzVsZDBOb2FXeGtjbVZ1TG5CMWMyZ29iblZzYkNsY2JpQWdJQ0FnSUNBZ0lDQWdJSDFjYmlBZ0lDQWdJQ0FnZlZ4dUlDQWdJSDFjYmx4dUlDQWdJSFpoY2lCc1lYTjBSbkpsWlVsdVpHVjRJRDBnWm5KbFpVbHVaR1Y0SUQ0OUlHSkdjbVZsTG14bGJtZDBhQ0EvWEc0Z0lDQWdJQ0FnSUdKRGFHbHNaSEpsYmk1c1pXNW5kR2dnT2x4dUlDQWdJQ0FnSUNCaVJuSmxaVnRtY21WbFNXNWtaWGhkWEc1Y2JpQWdJQ0F2THlCSmRHVnlZWFJsSUhSb2NtOTFaMmdnWWlCaGJtUWdZWEJ3Wlc1a0lHRnVlU0J1WlhjZ2EyVjVjMXh1SUNBZ0lDOHZJRThvVFNrZ2RHbHRaVnh1SUNBZ0lHWnZjaUFvZG1GeUlHb2dQU0F3T3lCcUlEd2dZa05vYVd4a2NtVnVMbXhsYm1kMGFEc2dhaXNyS1NCN1hHNGdJQ0FnSUNBZ0lIWmhjaUJ1WlhkSmRHVnRJRDBnWWtOb2FXeGtjbVZ1VzJwZFhHNWNiaUFnSUNBZ0lDQWdhV1lnS0c1bGQwbDBaVzB1YTJWNUtTQjdYRzRnSUNBZ0lDQWdJQ0FnSUNCcFppQW9JV0ZMWlhsekxtaGhjMDkzYmxCeWIzQmxjblI1S0c1bGQwbDBaVzB1YTJWNUtTa2dlMXh1SUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQzh2SUVGa1pDQmhibmtnYm1WM0lHdGxlV1ZrSUdsMFpXMXpYRzRnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdMeThnVjJVZ1lYSmxJR0ZrWkdsdVp5QnVaWGNnYVhSbGJYTWdkRzhnZEdobElHVnVaQ0JoYm1RZ2RHaGxiaUJ6YjNKMGFXNW5JSFJvWlcxY2JpQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBdkx5QnBiaUJ3YkdGalpTNGdTVzRnWm5WMGRYSmxJSGRsSUhOb2IzVnNaQ0JwYm5ObGNuUWdibVYzSUdsMFpXMXpJR2x1SUhCc1lXTmxMbHh1SUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJRzVsZDBOb2FXeGtjbVZ1TG5CMWMyZ29ibVYzU1hSbGJTbGNiaUFnSUNBZ0lDQWdJQ0FnSUgxY2JpQWdJQ0FnSUNBZ2ZTQmxiSE5sSUdsbUlDaHFJRDQ5SUd4aGMzUkdjbVZsU1c1a1pYZ3BJSHRjYmlBZ0lDQWdJQ0FnSUNBZ0lDOHZJRUZrWkNCaGJua2diR1ZtZEc5MlpYSWdibTl1TFd0bGVXVmtJR2wwWlcxelhHNGdJQ0FnSUNBZ0lDQWdJQ0J1WlhkRGFHbHNaSEpsYmk1d2RYTm9LRzVsZDBsMFpXMHBYRzRnSUNBZ0lDQWdJSDFjYmlBZ0lDQjlYRzVjYmlBZ0lDQjJZWElnYzJsdGRXeGhkR1VnUFNCdVpYZERhR2xzWkhKbGJpNXpiR2xqWlNncFhHNGdJQ0FnZG1GeUlITnBiWFZzWVhSbFNXNWtaWGdnUFNBd1hHNGdJQ0FnZG1GeUlISmxiVzkyWlhNZ1BTQmJYVnh1SUNBZ0lIWmhjaUJwYm5ObGNuUnpJRDBnVzExY2JpQWdJQ0IyWVhJZ2MybHRkV3hoZEdWSmRHVnRYRzVjYmlBZ0lDQm1iM0lnS0haaGNpQnJJRDBnTURzZ2F5QThJR0pEYUdsc1pISmxiaTVzWlc1bmRHZzdLU0I3WEc0Z0lDQWdJQ0FnSUhaaGNpQjNZVzUwWldSSmRHVnRJRDBnWWtOb2FXeGtjbVZ1VzJ0ZFhHNGdJQ0FnSUNBZ0lITnBiWFZzWVhSbFNYUmxiU0E5SUhOcGJYVnNZWFJsVzNOcGJYVnNZWFJsU1c1a1pYaGRYRzVjYmlBZ0lDQWdJQ0FnTHk4Z2NtVnRiM1psSUdsMFpXMXpYRzRnSUNBZ0lDQWdJSGRvYVd4bElDaHphVzExYkdGMFpVbDBaVzBnUFQwOUlHNTFiR3dnSmlZZ2MybHRkV3hoZEdVdWJHVnVaM1JvS1NCN1hHNGdJQ0FnSUNBZ0lDQWdJQ0J5WlcxdmRtVnpMbkIxYzJnb2NtVnRiM1psS0hOcGJYVnNZWFJsTENCemFXMTFiR0YwWlVsdVpHVjRMQ0J1ZFd4c0tTbGNiaUFnSUNBZ0lDQWdJQ0FnSUhOcGJYVnNZWFJsU1hSbGJTQTlJSE5wYlhWc1lYUmxXM05wYlhWc1lYUmxTVzVrWlhoZFhHNGdJQ0FnSUNBZ0lIMWNibHh1SUNBZ0lDQWdJQ0JwWmlBb0lYTnBiWFZzWVhSbFNYUmxiU0I4ZkNCemFXMTFiR0YwWlVsMFpXMHVhMlY1SUNFOVBTQjNZVzUwWldSSmRHVnRMbXRsZVNrZ2UxeHVJQ0FnSUNBZ0lDQWdJQ0FnTHk4Z2FXWWdkMlVnYm1WbFpDQmhJR3RsZVNCcGJpQjBhR2x6SUhCdmMybDBhVzl1TGk0dVhHNGdJQ0FnSUNBZ0lDQWdJQ0JwWmlBb2QyRnVkR1ZrU1hSbGJTNXJaWGtwSUh0Y2JpQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNCcFppQW9jMmx0ZFd4aGRHVkpkR1Z0SUNZbUlITnBiWFZzWVhSbFNYUmxiUzVyWlhrcElIdGNiaUFnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnTHk4Z2FXWWdZVzRnYVc1elpYSjBJR1J2WlhOdUozUWdjSFYwSUhSb2FYTWdhMlY1SUdsdUlIQnNZV05sTENCcGRDQnVaV1ZrY3lCMGJ5QnRiM1psWEc0Z0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lHbG1JQ2hpUzJWNWMxdHphVzExYkdGMFpVbDBaVzB1YTJWNVhTQWhQVDBnYXlBcklERXBJSHRjYmlBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJSEpsYlc5MlpYTXVjSFZ6YUNoeVpXMXZkbVVvYzJsdGRXeGhkR1VzSUhOcGJYVnNZWFJsU1c1a1pYZ3NJSE5wYlhWc1lYUmxTWFJsYlM1clpYa3BLVnh1SUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdjMmx0ZFd4aGRHVkpkR1Z0SUQwZ2MybHRkV3hoZEdWYmMybHRkV3hoZEdWSmJtUmxlRjFjYmlBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQzh2SUdsbUlIUm9aU0J5WlcxdmRtVWdaR2xrYmlkMElIQjFkQ0IwYUdVZ2QyRnVkR1ZrSUdsMFpXMGdhVzRnY0d4aFkyVXNJSGRsSUc1bFpXUWdkRzhnYVc1elpYSjBJR2wwWEc0Z0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0JwWmlBb0lYTnBiWFZzWVhSbFNYUmxiU0I4ZkNCemFXMTFiR0YwWlVsMFpXMHVhMlY1SUNFOVBTQjNZVzUwWldSSmRHVnRMbXRsZVNrZ2UxeHVJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJR2x1YzJWeWRITXVjSFZ6YUNoN2EyVjVPaUIzWVc1MFpXUkpkR1Z0TG10bGVTd2dkRzg2SUd0OUtWeHVJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ2ZWeHVJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0x5OGdhWFJsYlhNZ1lYSmxJRzFoZEdOb2FXNW5MQ0J6YnlCemEybHdJR0ZvWldGa1hHNGdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNCbGJITmxJSHRjYmlBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNCemFXMTFiR0YwWlVsdVpHVjRLeXRjYmlBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJSDFjYmlBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ2ZWeHVJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0JsYkhObElIdGNiaUFnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lHbHVjMlZ5ZEhNdWNIVnphQ2g3YTJWNU9pQjNZVzUwWldSSmRHVnRMbXRsZVN3Z2RHODZJR3Q5S1Z4dUlDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQjlYRzRnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdmVnh1SUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJR1ZzYzJVZ2UxeHVJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0JwYm5ObGNuUnpMbkIxYzJnb2UydGxlVG9nZDJGdWRHVmtTWFJsYlM1clpYa3NJSFJ2T2lCcmZTbGNiaUFnSUNBZ0lDQWdJQ0FnSUNBZ0lDQjlYRzRnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdheXNyWEc0Z0lDQWdJQ0FnSUNBZ0lDQjlYRzRnSUNBZ0lDQWdJQ0FnSUNBdkx5QmhJR3RsZVNCcGJpQnphVzExYkdGMFpTQm9ZWE1nYm04Z2JXRjBZMmhwYm1jZ2QyRnVkR1ZrSUd0bGVTd2djbVZ0YjNabElHbDBYRzRnSUNBZ0lDQWdJQ0FnSUNCbGJITmxJR2xtSUNoemFXMTFiR0YwWlVsMFpXMGdKaVlnYzJsdGRXeGhkR1ZKZEdWdExtdGxlU2tnZTF4dUlDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUhKbGJXOTJaWE11Y0hWemFDaHlaVzF2ZG1Vb2MybHRkV3hoZEdVc0lITnBiWFZzWVhSbFNXNWtaWGdzSUhOcGJYVnNZWFJsU1hSbGJTNXJaWGtwS1Z4dUlDQWdJQ0FnSUNBZ0lDQWdmVnh1SUNBZ0lDQWdJQ0I5WEc0Z0lDQWdJQ0FnSUdWc2MyVWdlMXh1SUNBZ0lDQWdJQ0FnSUNBZ2MybHRkV3hoZEdWSmJtUmxlQ3NyWEc0Z0lDQWdJQ0FnSUNBZ0lDQnJLeXRjYmlBZ0lDQWdJQ0FnZlZ4dUlDQWdJSDFjYmx4dUlDQWdJQzh2SUhKbGJXOTJaU0JoYkd3Z2RHaGxJSEpsYldGcGJtbHVaeUJ1YjJSbGN5Qm1jbTl0SUhOcGJYVnNZWFJsWEc0Z0lDQWdkMmhwYkdVb2MybHRkV3hoZEdWSmJtUmxlQ0E4SUhOcGJYVnNZWFJsTG14bGJtZDBhQ2tnZTF4dUlDQWdJQ0FnSUNCemFXMTFiR0YwWlVsMFpXMGdQU0J6YVcxMWJHRjBaVnR6YVcxMWJHRjBaVWx1WkdWNFhWeHVJQ0FnSUNBZ0lDQnlaVzF2ZG1WekxuQjFjMmdvY21WdGIzWmxLSE5wYlhWc1lYUmxMQ0J6YVcxMWJHRjBaVWx1WkdWNExDQnphVzExYkdGMFpVbDBaVzBnSmlZZ2MybHRkV3hoZEdWSmRHVnRMbXRsZVNrcFhHNGdJQ0FnZlZ4dVhHNGdJQ0FnTHk4Z1NXWWdkR2hsSUc5dWJIa2diVzkyWlhNZ2QyVWdhR0YyWlNCaGNtVWdaR1ZzWlhSbGN5QjBhR1Z1SUhkbElHTmhiaUJxZFhOMFhHNGdJQ0FnTHk4Z2JHVjBJSFJvWlNCa1pXeGxkR1VnY0dGMFkyZ2djbVZ0YjNabElIUm9aWE5sSUdsMFpXMXpMbHh1SUNBZ0lHbG1JQ2h5WlcxdmRtVnpMbXhsYm1kMGFDQTlQVDBnWkdWc1pYUmxaRWwwWlcxeklDWW1JQ0ZwYm5ObGNuUnpMbXhsYm1kMGFDa2dlMXh1SUNBZ0lDQWdJQ0J5WlhSMWNtNGdlMXh1SUNBZ0lDQWdJQ0FnSUNBZ1kyaHBiR1J5Wlc0NklHNWxkME5vYVd4a2NtVnVMRnh1SUNBZ0lDQWdJQ0FnSUNBZ2JXOTJaWE02SUc1MWJHeGNiaUFnSUNBZ0lDQWdmVnh1SUNBZ0lIMWNibHh1SUNBZ0lISmxkSFZ5YmlCN1hHNGdJQ0FnSUNBZ0lHTm9hV3hrY21WdU9pQnVaWGREYUdsc1pISmxiaXhjYmlBZ0lDQWdJQ0FnYlc5MlpYTTZJSHRjYmlBZ0lDQWdJQ0FnSUNBZ0lISmxiVzkyWlhNNklISmxiVzkyWlhNc1hHNGdJQ0FnSUNBZ0lDQWdJQ0JwYm5ObGNuUnpPaUJwYm5ObGNuUnpYRzRnSUNBZ0lDQWdJSDFjYmlBZ0lDQjlYRzU5WEc1Y2JtWjFibU4wYVc5dUlISmxiVzkyWlNoaGNuSXNJR2x1WkdWNExDQnJaWGtwSUh0Y2JpQWdJQ0JoY25JdWMzQnNhV05sS0dsdVpHVjRMQ0F4S1Z4dVhHNGdJQ0FnY21WMGRYSnVJSHRjYmlBZ0lDQWdJQ0FnWm5KdmJUb2dhVzVrWlhnc1hHNGdJQ0FnSUNBZ0lHdGxlVG9nYTJWNVhHNGdJQ0FnZlZ4dWZWeHVYRzVtZFc1amRHbHZiaUJyWlhsSmJtUmxlQ2hqYUdsc1pISmxiaWtnZTF4dUlDQWdJSFpoY2lCclpYbHpJRDBnZTMxY2JpQWdJQ0IyWVhJZ1puSmxaU0E5SUZ0ZFhHNGdJQ0FnZG1GeUlHeGxibWQwYUNBOUlHTm9hV3hrY21WdUxteGxibWQwYUZ4dVhHNGdJQ0FnWm05eUlDaDJZWElnYVNBOUlEQTdJR2tnUENCc1pXNW5kR2c3SUdrckt5a2dlMXh1SUNBZ0lDQWdJQ0IyWVhJZ1kyaHBiR1FnUFNCamFHbHNaSEpsYmx0cFhWeHVYRzRnSUNBZ0lDQWdJR2xtSUNoamFHbHNaQzVyWlhrcElIdGNiaUFnSUNBZ0lDQWdJQ0FnSUd0bGVYTmJZMmhwYkdRdWEyVjVYU0E5SUdsY2JpQWdJQ0FnSUNBZ2ZTQmxiSE5sSUh0Y2JpQWdJQ0FnSUNBZ0lDQWdJR1p5WldVdWNIVnphQ2hwS1Z4dUlDQWdJQ0FnSUNCOVhHNGdJQ0FnZlZ4dVhHNGdJQ0FnY21WMGRYSnVJSHRjYmlBZ0lDQWdJQ0FnYTJWNWN6b2dhMlY1Y3l3Z0lDQWdJQzh2SUVFZ2FHRnphQ0J2WmlCclpYa2dibUZ0WlNCMGJ5QnBibVJsZUZ4dUlDQWdJQ0FnSUNCbWNtVmxPaUJtY21WbElDQWdJQ0FnTHk4Z1FXNGdZWEp5WVhrZ2IyWWdkVzVyWlhsbFpDQnBkR1Z0SUdsdVpHbGpaWE5jYmlBZ0lDQjlYRzU5WEc1Y2JtWjFibU4wYVc5dUlHRndjR1Z1WkZCaGRHTm9LR0Z3Y0d4NUxDQndZWFJqYUNrZ2UxeHVJQ0FnSUdsbUlDaGhjSEJzZVNrZ2UxeHVJQ0FnSUNBZ0lDQnBaaUFvYVhOQmNuSmhlU2hoY0hCc2VTa3BJSHRjYmlBZ0lDQWdJQ0FnSUNBZ0lHRndjR3g1TG5CMWMyZ29jR0YwWTJncFhHNGdJQ0FnSUNBZ0lIMGdaV3h6WlNCN1hHNGdJQ0FnSUNBZ0lDQWdJQ0JoY0hCc2VTQTlJRnRoY0hCc2VTd2djR0YwWTJoZFhHNGdJQ0FnSUNBZ0lIMWNibHh1SUNBZ0lDQWdJQ0J5WlhSMWNtNGdZWEJ3YkhsY2JpQWdJQ0I5SUdWc2MyVWdlMXh1SUNBZ0lDQWdJQ0J5WlhSMWNtNGdjR0YwWTJoY2JpQWdJQ0I5WEc1OVhHNWNibjBzZTF3aUxpNHZkbTV2WkdVdmFHRnVaR3hsTFhSb2RXNXJYQ0k2TWpRc1hDSXVMaTkyYm05a1pTOXBjeTEwYUhWdWExd2lPakkxTEZ3aUxpNHZkbTV2WkdVdmFYTXRkbTV2WkdWY0lqb3lOeXhjSWk0dUwzWnViMlJsTDJsekxYWjBaWGgwWENJNk1qZ3NYQ0l1TGk5MmJtOWtaUzlwY3kxM2FXUm5aWFJjSWpveU9TeGNJaTR1TDNadWIyUmxMM1p3WVhSamFGd2lPak15TEZ3aUxpOWthV1ptTFhCeWIzQnpYQ0k2TXpRc1hDSjRMV2x6TFdGeWNtRjVYQ0k2TVRKOVhYMHNlMzBzV3pSZEtTZzBLVnh1ZlNrN1hHNWNibVY0Y0c5eWRDQmtaV1poZFd4MElGWnBjblIxWVd4RVQwMDdYRzRpWFN3aWMyOTFjbU5sVW05dmRDSTZJaTl6YjNWeVkyVXZJbjA9XG4iLCJpbXBvcnQgQ29yZSBmcm9tICcuL2xpYi9jb3JlJztcbmltcG9ydCBFbnVtIGZyb20gJy4vbGliL2VudW0nO1xuaW1wb3J0IFZpcnR1YWxET00gZnJvbSAnLi9saWIvdmlydHVhbC1kb20nO1xuXG5leHBvcnQgZGVmYXVsdCB7XG4gIENvcmUsXG4gIEVudW0sXG4gIFZpcnR1YWxET01cbn07XG4vLyMgc291cmNlTWFwcGluZ1VSTD1kYXRhOmFwcGxpY2F0aW9uL2pzb247YmFzZTY0LGV5SjJaWEp6YVc5dUlqb3pMQ0p6YjNWeVkyVnpJanBiSW1Wc2FYaHBjaTVxY3lKZExDSnVZVzFsY3lJNlcxMHNJbTFoY0hCcGJtZHpJam9pUVVGQlFTeFBRVUZQTEVsQlFWQXNUVUZCYVVJc1dVRkJha0k3UVVGRFFTeFBRVUZQTEVsQlFWQXNUVUZCYVVJc1dVRkJha0k3UVVGRFFTeFBRVUZQTEZWQlFWQXNUVUZCZFVJc2JVSkJRWFpDT3p0QlFVVkJMR1ZCUVdVN1FVRkRZaXhOUVVSaE8wRkJSV0lzVFVGR1lUdEJRVWRpTEZsQlNHRTdRMEZCWmlJc0ltWnBiR1VpT2lKbGJHbDRhWEl1YW5NaUxDSnpiM1Z5WTJWelEyOXVkR1Z1ZENJNld5SnBiWEJ2Y25RZ1EyOXlaU0JtY205dElDY3VMMnhwWWk5amIzSmxKenRjYm1sdGNHOXlkQ0JGYm5WdElHWnliMjBnSnk0dmJHbGlMMlZ1ZFcwbk8xeHVhVzF3YjNKMElGWnBjblIxWVd4RVQwMGdabkp2YlNBbkxpOXNhV0l2ZG1seWRIVmhiQzFrYjIwbk8xeHVYRzVsZUhCdmNuUWdaR1ZtWVhWc2RDQjdYRzRnSUVOdmNtVXNYRzRnSUVWdWRXMHNYRzRnSUZacGNuUjFZV3hFVDAxY2JuMDdYRzRpWFN3aWMyOTFjbU5sVW05dmRDSTZJaTl6YjNWeVkyVXZJbjA9XG4iXSwibmFtZXMiOlsiUHJpbWl0aXZlcy5QSUQiXSwibWFwcGluZ3MiOiJBQUVBLE1BQU0sT0FBTyxDQUFDOztFQUVaLFdBQVcsR0FBRztJQUNaLElBQUksQ0FBQyxRQUFRLEdBQUcsRUFBRSxDQUFDO0dBQ3BCOztFQUVELE9BQU8sQ0FBQyxPQUFPLEVBQUU7SUFDZixJQUFJLENBQUMsUUFBUSxDQUFDLElBQUksQ0FBQyxPQUFPLENBQUMsQ0FBQztJQUM1QixPQUFPLE9BQU8sQ0FBQztHQUNoQjs7RUFFRCxHQUFHLEdBQUc7SUFDSixPQUFPLElBQUksQ0FBQyxRQUFRLENBQUM7R0FDdEI7O0VBRUQsT0FBTyxHQUFHO0lBQ1IsT0FBTyxJQUFJLENBQUMsUUFBUSxDQUFDLE1BQU0sS0FBSyxDQUFDLENBQUM7R0FDbkM7O0VBRUQsUUFBUSxDQUFDLEtBQUssRUFBRTtJQUNkLElBQUksQ0FBQyxRQUFRLENBQUMsTUFBTSxDQUFDLEtBQUssRUFBRSxDQUFDLENBQUMsQ0FBQztHQUNoQztDQUNGOzthQ3hCYztFQUNi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QUFDO0dBQ2Q7O0VBRUQsT0FBTyxjQUFjLENBQUMsQ0FBQyxFQUFFO0lBQ3ZCLElBQUksS0FBSyxHQUFHLEVBQUUsQ0FBQzs7SUFFZixJQUFJLEdBQUcsR0FBRyxJQUFJLFdBQVcsQ0FBQyxDQUFDLENBQUMsQ0FBQztJQUM3QixJQUFJLFlBQVksQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDLENBQUMsR0FBRyxDQUFDLENBQUM7O0lBRTdCLElBQUksV0FBVyxHQUFHLElBQUksV0FBVyxDQUFDLEdBQUcsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDO0lBQzFDLElBQUksV0FBVyxHQUFHLElBQUksV0FBVyxDQUFDLEdBQUcsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDOztJQUUxQyxLQUFLLENBQUMsSUFBSSxDQUFDLFdBQVcsSUFBSSxFQUFFLEdBQUcsSUFBSSxDQUFDLENBQUM7SUFDckMsS0FBSyxDQUFDLElBQUksQ0FBQyxXQUFXLElBQUksRUFBRSxHQUFHLElBQUksQ0FBQyxDQUFDO0lBQ3JDLEtBQUssQ0FBQyxJQUFJLENBQUMsV0FBVyxJQUFJLENBQUMsR0FBRyxJQUFJLENBQUMsQ0FBQztJQUNwQyxLQUFLLENBQUMsSUFBSSxDQUFDLFdBQVcsR0FBRyxJQUFJLENBQUMsQ0FBQzs7SUFFL0IsS0FBSyxDQUFDLElBQUksQ0FBQyxXQUFXLElBQUksRUFBRSxHQUFHLElBQUksQ0FBQyxDQUFDO0lBQ3JDLEtBQUssQ0FBQyxJQUFJLENBQUMsV0FBVyxJQUFJLEVBQUUsR0FBRyxJQUFJLENBQUMsQ0FBQztJQUNyQyxLQUFLLENBQUMsSUFBSSxDQUFDLFdBQVcsSUFBSSxDQUFDLEdBQUcsSUFBSSxDQUFDLENBQUM7SUFDcEMsS0FBSyxDQUFDLElBQUksQ0FBQyxXQUFXLEdBQUcsSUFBSSxDQUFDLENBQUM7O0lBRS9CLE9BQU8sS0FBSyxDQUFDO0dBQ2Q7Q0FDRjs7QUNyU00sTUFBTSxRQUFRLENBQUM7O0VBRXBCLFdBQVcsQ0FBQyxJQUFJLEdBQUcsSUFBSSxFQUFFO0lBQ3ZCLElBQUksQ0FBQyxJQUFJLEdB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 \ No newline at end of file diff --git a/src/javascript/lib/core/patterns/defmatch.js b/src/javascript/lib/core/patterns/defmatch.js index 743544ce..fa05c07e 100644 --- a/src/javascript/lib/core/patterns/defmatch.js +++ b/src/javascript/lib/core/patterns/defmatch.js @@ -64,7 +64,7 @@ export function match_no_throw(pattern: any, expr: any, guard: Function = () => try{ return match(pattern, expr, guard); }catch(e){ - if(e instanceof MatchError){ + if(e instanceof MatchError || e.message.startsWith('No match for:')){ return null; } diff --git a/src/javascript/lib/core/special_forms.js b/src/javascript/lib/core/special_forms.js index 3e988613..f8e9611c 100644 --- a/src/javascript/lib/core/special_forms.js +++ b/src/javascript/lib/core/special_forms.js @@ -41,7 +41,7 @@ function _for(collections, fun, filter = () => true, into = [], previousValues = return into; }else{ - let _into = [] + let _into = []; for(let elem of collection){ let r = Patterns.match_no_throw(pattern, elem); diff --git a/src/javascript/tests/bit_string.spec.js b/src/javascript/tests/bit_string.spec.js index 30a05f44..90f5d48c 100644 --- a/src/javascript/tests/bit_string.spec.js +++ b/src/javascript/tests/bit_string.spec.js @@ -1,6 +1,11 @@ -var BitString = require('../lib/core').BitString; -var Patterns = require('../lib/core').Patterns; -var expect = require('chai').expect; +import Core from "../lib/core"; +const Patterns = Core.Patterns; +const BitString = Core.BitString; + +import Enum from "../lib/enum"; + +import chai from 'chai'; +var expect = chai.expect; function is_match(pattern, expr, guard = () => true){ return Patterns.match_no_throw(pattern, expr, guard) != null; diff --git a/src/javascript/tests/case.spec.js b/src/javascript/tests/case.spec.js index 6224157a..1dc9b8cc 100644 --- a/src/javascript/tests/case.spec.js +++ b/src/javascript/tests/case.spec.js @@ -1,8 +1,12 @@ -var Patterns = require("../lib/core/patterns"); -var Enum = require('../lib/enum'); -var Tuple = require('../lib/core').Tuple; -var SpecialForms = require('../lib/core').SpecialForms; -var expect = require('chai').expect; +import Core from "../lib/core"; +const Patterns = Core.Patterns; +const SpecialForms = Core.SpecialForms; +const Tuple = Core.Tuple; + +import Enum from "../lib/enum"; + +import chai from 'chai'; +var expect = chai.expect; describe('case', () => { diff --git a/src/javascript/tests/cond.spec.js b/src/javascript/tests/cond.spec.js index ff53a9d2..2fea8baa 100644 --- a/src/javascript/tests/cond.spec.js +++ b/src/javascript/tests/cond.spec.js @@ -1,7 +1,11 @@ -var Patterns = require("../lib/core/patterns"); -var Enum = require('../lib/enum'); -var SpecialForms = require('../lib/core').SpecialForms; -var expect = require('chai').expect; +import Core from "../lib/core"; +const Patterns = Core.Patterns; +const SpecialForms = Core.SpecialForms; + +import Enum from "../lib/enum"; + +import chai from 'chai'; +var expect = chai.expect; describe('cond', () => { diff --git a/src/javascript/tests/core/functions.spec.js b/src/javascript/tests/core/functions.spec.js index 9b110c20..aef7192d 100644 --- a/src/javascript/tests/core/functions.spec.js +++ b/src/javascript/tests/core/functions.spec.js @@ -1,5 +1,8 @@ -var Functions = require('../../lib/core').Functions; -var expect = require('chai').expect; +import Core from "../../lib/core"; +const Functions = Core.Functions; + +import chai from 'chai'; +var expect = chai.expect; describe('Functions', function(){ diff --git a/src/javascript/tests/for.spec.js b/src/javascript/tests/for.spec.js index c8effdb0..8221fcc0 100644 --- a/src/javascript/tests/for.spec.js +++ b/src/javascript/tests/for.spec.js @@ -1,7 +1,11 @@ -var Patterns = require("../lib/core").Patterns; -var Enum = require('../lib/enum'); -var SpecialForms = require('../lib/core').SpecialForms; -var expect = require('chai').expect; +import Core from "../lib/core"; +const Patterns = Core.Patterns; +const SpecialForms = Core.SpecialForms; + +import Enum from "../lib/enum"; + +import chai from 'chai'; +var expect = chai.expect; const $ = Patterns.variable(); diff --git a/src/javascript/tests/patterns/defmatch.spec.js b/src/javascript/tests/patterns/defmatch.spec.js index 747774cf..28c686af 100644 --- a/src/javascript/tests/patterns/defmatch.spec.js +++ b/src/javascript/tests/patterns/defmatch.spec.js @@ -1,6 +1,9 @@ -var expect = require('chai').expect; -var Patterns = require("../../lib/core").Patterns; -var Tuple = require("../../lib/core").Tuple; +import Core from "../../lib/core"; +const Patterns = Core.Patterns; +const Tuple = Core.Tuple; + +import chai from 'chai'; +var expect = chai.expect; const _ = Patterns.wildcard(); const $ = Patterns.variable(); diff --git a/src/javascript/tests/patterns/match.spec.js b/src/javascript/tests/patterns/match.spec.js index 13045e82..f2d2dd16 100644 --- a/src/javascript/tests/patterns/match.spec.js +++ b/src/javascript/tests/patterns/match.spec.js @@ -1,5 +1,8 @@ -var expect = require('chai').expect; -var Patterns = require("../../lib/core").Patterns; +import Core from "../../lib/core"; +const Patterns = Core.Patterns; + +import chai from 'chai'; +var expect = chai.expect; const _ = Patterns.wildcard(); const $ = Patterns.variable(); diff --git a/src/javascript/tests/special_forms.spec.js b/src/javascript/tests/special_forms.spec.js index f4dc1434..cc540546 100644 --- a/src/javascript/tests/special_forms.spec.js +++ b/src/javascript/tests/special_forms.spec.js @@ -1,5 +1,8 @@ -var SpecialForms = require('../lib/core').SpecialForms; -var expect = require('chai').expect; +import Core from "../lib/core"; +const SpecialForms = Core.SpecialForms; + +import chai from 'chai'; +var expect = chai.expect; describe('SpecialForms', function(){ @@ -20,7 +23,7 @@ describe('SpecialForms', function(){ } const foo = new MyClass("bar"); - const bar = SpecialForms.map_update(foo, {baz: "bar", fizz: "fizzbuzz"}) + const bar = SpecialForms.map_update(foo, {baz: "bar", fizz: "fizzbuzz"}); expect(foo instanceof MyClass).to.equal(bar instanceof MyClass); expect(foo.foo).to.equal(bar.foo); diff --git a/src/javascript/tests/try.spec.js b/src/javascript/tests/try.spec.js index df6b9971..2009c022 100644 --- a/src/javascript/tests/try.spec.js +++ b/src/javascript/tests/try.spec.js @@ -1,7 +1,11 @@ -var Patterns = require("../lib/core/patterns"); -var Enum = require('../lib/enum'); -var SpecialForms = require('../lib/core').SpecialForms; -var expect = require('chai').expect; +import Core from "../lib/core"; +const Patterns = Core.Patterns; +const SpecialForms = Core.SpecialForms; + +import Enum from "../lib/enum"; + +import chai from 'chai'; +var expect = chai.expect; describe('try', () => { @@ -29,7 +33,7 @@ describe('try', () => { return (y < 1) && (y > -1); }), Patterns.make_case([Patterns.wildcard()], function() { return Symbol.for('large'); - })), null) + })), null); expect(value).to.equal(Symbol.for('large')); }); From 617c7b12b10ddfcd6dc21b2cdd0edc3940e515ee Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Sat, 20 Feb 2016 17:17:43 -0600 Subject: [PATCH 151/860] Added ability to use variable as map key --- CHANGELOG.md | 5 ++++- lib/elixir_script/translator/map.ex | 8 +++++++- test/translator/map_test.exs | 7 +++++++ 3 files changed, 18 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 68ca4ce2..2617fa42 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,7 +1,10 @@ # v0.15.2-dev +* Enhancements + * Support for variables as map keys + * Bug fixes * Fixed protocol implementations for Integer and Float which where not recognized - * Fixed calling properties on non-objects + * Fixed calling properties on non-objects # v0.15.1 * Bug fixes diff --git a/lib/elixir_script/translator/map.ex b/lib/elixir_script/translator/map.ex index 31f65247..02f17691 100644 --- a/lib/elixir_script/translator/map.ex +++ b/lib/elixir_script/translator/map.ex @@ -26,7 +26,13 @@ defmodule ElixirScript.Translator.Map do properties |> Enum.map(fn ({x, {:__aliases__, _, [value]}}) -> make_property(Translator.translate!(x, env), JS.identifier(value)) - ({x, y}) -> make_property(Translator.translate!(x, env), Translator.translate!(y, env)) + ({x, y}) -> + case x do + {_, _, atom } when is_atom(atom) -> + JS.property(Translator.translate!(x, env), Translator.translate!(y, env), :init, false, false, true) + _ -> + make_property(Translator.translate!(x, env), Translator.translate!(y, env)) + end end) |> JS.object_expression |> make_map diff --git a/test/translator/map_test.exs b/test/translator/map_test.exs index 356c2d0d..43419637 100644 --- a/test/translator/map_test.exs +++ b/test/translator/map_test.exs @@ -52,4 +52,11 @@ defmodule ElixirScript.Translator.Map.Test do assert_translation(ex_ast, js_code) end + + test "translate variable key" do + ex_ast = quote do: %{key => value} + js_code = "Object.freeze({ [key]: value })" + assert_translation(ex_ast, js_code) + end + end From d02f5f1b7a1421b20ef75f623b639ae42ccfd6e8 Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Sat, 20 Feb 2016 17:20:31 -0600 Subject: [PATCH 152/860] updated documentation --- CONTRIBUTING.md | 2 +- README.md | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index d0f742d4..ae6315ab 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -79,7 +79,7 @@ Please look at [this issue](https://github.com/bryanjos/elixirscript/issues/143) The ElixirScript tests can be run using `mix test` -The JavaScript tests can be run using `gulp test` +The JavaScript tests can be run using `npm test` Please make sure all tests pass after making changes. Also make sure to include tests for the changes you made. diff --git a/README.md b/README.md index 8de410e1..d432d400 100644 --- a/README.md +++ b/README.md @@ -38,7 +38,7 @@ Compile Test mix test - gulp test + npm test Contributing From 159d6f29fd55706848d753192785cf7609f32b10 Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Sat, 20 Feb 2016 17:37:07 -0600 Subject: [PATCH 153/860] preparing for release --- CHANGELOG.md | 2 +- mix.exs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 2617fa42..3eff4858 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,4 +1,4 @@ -# v0.15.2-dev +# v0.15.2 * Enhancements * Support for variables as map keys diff --git a/mix.exs b/mix.exs index a08ff024..ffacd5ae 100644 --- a/mix.exs +++ b/mix.exs @@ -4,7 +4,7 @@ defmodule ElixirScript.Mixfile do def project do [ app: :elixir_script, - version: "0.15.2-dev", + version: "0.15.2", elixir: "~> 1.0", escript: escript_config, deps: deps, From f692068d04c5330a9a5688243bb3c1d3006b4179 Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Mon, 22 Feb 2016 21:52:28 -0600 Subject: [PATCH 154/860] Added implementation for bitstring matching in patterns library --- mix.lock | 6 +- src/javascript/lib/core/bit_string.js | 10 +- src/javascript/lib/core/patterns.js | 4 +- src/javascript/lib/core/patterns/checks.js | 10 +- src/javascript/lib/core/patterns/match.js | 4 + src/javascript/lib/core/patterns/resolvers.js | 154 +++++++++++++++++- src/javascript/lib/core/patterns/types.js | 48 ++++++ .../tests/patterns/defmatch.spec.js | 89 ++++++++++ 8 files changed, 309 insertions(+), 16 deletions(-) diff --git a/mix.lock b/mix.lock index 4c01630a..6b153af9 100644 --- a/mix.lock +++ b/mix.lock @@ -1,12 +1,12 @@ %{"benchfella": {:hex, :benchfella, "0.3.1"}, - "bunt": {:hex, :bunt, "0.1.4"}, + "bunt": {:hex, :bunt, "0.1.5"}, "certifi": {:hex, :certifi, "0.3.0"}, - "credo": {:hex, :credo, "0.2.5"}, + "credo": {:hex, :credo, "0.2.6"}, "dogma": {:hex, :dogma, "0.0.7"}, "earmark": {:hex, :earmark, "0.2.1"}, "estree": {:hex, :estree, "2.2.0"}, "ex_doc": {:hex, :ex_doc, "0.11.4"}, - "excoveralls": {:hex, :excoveralls, "0.4.5"}, + "excoveralls": {:hex, :excoveralls, "0.5.1"}, "exjsx": {:hex, :exjsx, "3.2.0"}, "hackney": {:hex, :hackney, "1.4.8"}, "idna": {:hex, :idna, "1.0.3"}, diff --git a/src/javascript/lib/core/bit_string.js b/src/javascript/lib/core/bit_string.js index b548015f..42b50a75 100644 --- a/src/javascript/lib/core/bit_string.js +++ b/src/javascript/lib/core/bit_string.js @@ -6,7 +6,7 @@ class BitString { this.value = Object.freeze(this.process(args)); this.length = this.value.length; - this.bit_size = this.raw_value().reduce((prev, current) => prev + current.size); + this.bit_size = this.raw_value().reduce((prev, current) => prev + (current.unit * current.size), 0); this.byte_size = (this.bit_size / 8) + (this.bit_size % 8 > 0 ? 1 : 0); } @@ -28,7 +28,7 @@ class BitString { if (s !== "") { s += ", "; } - s += this[i].toString(); + s += this.get(i).toString(); } return "<<" + s + ">>"; @@ -138,15 +138,15 @@ class BitString { } static utf8(value){ - return BitString.wrap(value, { 'type': 'utf8' }); + return BitString.wrap(value, { 'type': 'utf8', 'unit': 1, 'size': value.length }); } static utf16(value){ - return BitString.wrap(value, { 'type': 'utf16' }); + return BitString.wrap(value, { 'type': 'utf16', 'unit': 1, 'size': value.length * 2 }); } static utf32(value){ - return BitString.wrap(value, { 'type': 'utf32' }); + return BitString.wrap(value, { 'type': 'utf32', 'unit': 1, 'size': value.length * 4 }); } static signed(value){ diff --git a/src/javascript/lib/core/patterns.js b/src/javascript/lib/core/patterns.js index 2978dbc2..81876a78 100644 --- a/src/javascript/lib/core/patterns.js +++ b/src/javascript/lib/core/patterns.js @@ -1,11 +1,11 @@ /* @flow */ import { defmatch, match, MatchError, match_no_throw, patternMap, Case, make_case } from "./patterns/defmatch"; -import { variable, wildcard, startsWith, capture, headTail, type, bound } from "./patterns/types"; +import { variable, wildcard, startsWith, capture, headTail, type, bound, bitStringMatch } from "./patterns/types"; export default { defmatch, match, MatchError, match_no_throw, variable, wildcard, startsWith, - capture, headTail, type, bound, Case, make_case + capture, headTail, type, bound, Case, make_case, bitStringMatch }; diff --git a/src/javascript/lib/core/patterns/checks.js b/src/javascript/lib/core/patterns/checks.js index 1840e5c4..d5f59778 100644 --- a/src/javascript/lib/core/patterns/checks.js +++ b/src/javascript/lib/core/patterns/checks.js @@ -1,6 +1,6 @@ /* @flow */ -import { Variable, Wildcard, HeadTail, Capture, Type, StartsWith, Bound } from "./types"; +import { Variable, Wildcard, HeadTail, Capture, Type, StartsWith, Bound, BitStringMatch } from "./types"; function is_number(value: any): boolean { return typeof value === 'number'; @@ -66,6 +66,11 @@ function is_array(value: any): boolean { return Array.isArray(value); } +function is_bitstring(value: any): boolean { + return value instanceof BitStringMatch; +} + + export default { is_number, is_string, @@ -82,5 +87,6 @@ export default { is_startsWith, is_bound, is_object, - is_array + is_array, + is_bitstring }; diff --git a/src/javascript/lib/core/patterns/match.js b/src/javascript/lib/core/patterns/match.js index f2e1c140..79fb718f 100644 --- a/src/javascript/lib/core/patterns/match.js +++ b/src/javascript/lib/core/patterns/match.js @@ -60,6 +60,10 @@ export function buildMatch(pattern: any): Function { return Resolvers.resolveNull(pattern); } + if(Checks.is_bitstring(pattern)){ + return Resolvers.resolveBitString(pattern); + } + if(Checks.is_object(pattern)){ return Resolvers.resolveObject(pattern); } diff --git a/src/javascript/lib/core/patterns/resolvers.js b/src/javascript/lib/core/patterns/resolvers.js index fbd05dc4..a92c7d27 100644 --- a/src/javascript/lib/core/patterns/resolvers.js +++ b/src/javascript/lib/core/patterns/resolvers.js @@ -3,6 +3,7 @@ import Checks from "./checks"; import * as Types from "./types"; import { buildMatch } from "./match"; +import BitString from "../bit_string"; function resolveSymbol(pattern: any): Function { return function(value: any): boolean { @@ -12,7 +13,7 @@ function resolveSymbol(pattern: any): Function { function resolveString(pattern: any): Function { return function(value: any): boolean { - return Checks.is_string(value) && value === pattern + return Checks.is_string(value) && value === pattern; }; } @@ -24,13 +25,13 @@ function resolveNumber(pattern: any): Function { function resolveBoolean(pattern: any): Function { return function(value: any): boolean { - return Checks.is_boolean(value) && value === pattern + return Checks.is_boolean(value) && value === pattern; }; } function resolveFunction(pattern: any): Function { return function(value: any): boolean { - return Checks.is_function(value) && value === pattern + return Checks.is_function(value) && value === pattern; }; } @@ -155,6 +156,150 @@ function resolveObject(pattern: Object): Function { }; } +function resolveBitString(pattern: Types.BitStringMatch): Function { + let patternBitString = []; + + for(let bitstringMatchPart of pattern.values){ + if(Checks.is_variable(bitstringMatchPart.value)){ + let size = getLength(bitstringMatchPart.type, bitstringMatchPart.unit, bitstringMatchPart.size); + fillArray(patternBitString, size); + }else{ + patternBitString = patternBitString.concat(new BitString(bitstringMatchPart).value); + } + } + + let patternValues = pattern.values; + + return function(value: any, args: Array): boolean { + let bsValue = null; + + if(!Checks.is_string(value) && !(value instanceof BitString) ){ + return false; + } + + if(Checks.is_string(value)){ + bsValue = new BitString(BitString.binary(value)); + }else{ + bsValue = value; + } + + let beginningIndex = 0; + + for(let i = 0; i < patternValues.length; i++){ + let bitstringMatchPart = patternValues[i]; + + if(Checks.is_variable(bitstringMatchPart.value) && + bitstringMatchPart.type == 'binary' && + bitstringMatchPart.size === undefined && + i < patternValues.length - 1){ + throw new Error("a binary field without size is only allowed at the end of a binary pattern"); + } + + let size = 0; + let bsValueArrayPart = []; + let patternBitStringArrayPart = []; + size = getLength(bitstringMatchPart.type, bitstringMatchPart.unit, bitstringMatchPart.size); + + if(i === patternValues.length - 1){ + bsValueArrayPart = bsValue.value.slice(beginningIndex); + patternBitStringArrayPart = patternBitString.slice(beginningIndex); + } else { + bsValueArrayPart = bsValue.value.slice(beginningIndex, beginningIndex + size); + patternBitStringArrayPart = patternBitString.slice(beginningIndex, beginningIndex + size); + } + + if(Checks.is_variable(bitstringMatchPart.value)){ + switch(bitstringMatchPart.type) { + case 'integer': + if(bitstringMatchPart.attributes && bitstringMatchPart.attributes.indexOf("signed") != -1){ + args.push(new Int8Array([bsValueArrayPart[0]])[0]); + } else { + args.push(new Uint8Array([bsValueArrayPart[0]])[0]); + } + break; + + case 'float': + if(size === 64){ + args.push(Float64Array.from(bsValueArrayPart)[0]); + } else if(size === 32){ + args.push(Float32Array.from(bsValueArrayPart)[0]); + }else{ + return false; + } + break; + + case 'bitstring': + args.push(createBitString(bsValueArrayPart)); + break; + + case 'binary': + args.push(String.fromCharCode.apply(null, new Uint8Array(bsValueArrayPart))); + break; + + case 'utf8': + args.push(String.fromCharCode.apply(null, new Uint8Array(bsValueArrayPart))); + break; + + case 'utf16': + args.push(String.fromCharCode.apply(null, new Uint16Array(bsValueArrayPart))); + break; + + case 'utf32': + args.push(String.fromCharCode.apply(null, new Uint32Array(bsValueArrayPart))); + break; + + default: + return false; + } + }else if(!arraysEqual(bsValueArrayPart, patternBitStringArrayPart)) { + return false; + } + + beginningIndex = beginningIndex + size; + } + + return true; + } + +} + +function getLength(type, unit, size){ + if(type === 'integer' && size === 8){ + return 1; + }else if(type === 'float' && size === 32){ + return 4; + } else if(type === 'float' && size === 64){ + return 8; + } else if(type === 'binary'){ + return size; + }else{ + return unit * size; + } +} + +function arraysEqual(a, b) { + if (a === b) return true; + if (a == null || b == null) return false; + if (a.length != b.length) return false; + + for (var i = 0; i < a.length; ++i) { + if (a[i] !== b[i]) return false; + } + + return true; +} + +function fillArray(arr, num){ + for(let i = 0; i < num; i++){ + arr.push(0); + } +} + +function createBitString(arr){ + let integerParts = arr.map((elem) => BitString.integer(elem)); + return new BitString(...integerParts); +} + function resolveNoMatch(): Function { return function(): boolean { return false; @@ -177,5 +322,6 @@ export default { resolveNumber, resolveBoolean, resolveFunction, - resolveNull + resolveNull, + resolveBitString } diff --git a/src/javascript/lib/core/patterns/types.js b/src/javascript/lib/core/patterns/types.js index 05362fdf..2a8f37f6 100644 --- a/src/javascript/lib/core/patterns/types.js +++ b/src/javascript/lib/core/patterns/types.js @@ -56,6 +56,50 @@ export class Bound { } } +export class BitStringMatch { + values: Array + + //{'value': value, 'attributes': [type, unit, size]}; + + //length = unit * size + + //use that info to map value to subset of bitstring + //use type to turn subset of bitstring into desired type + //if value is a variable, add variable to args list + //if value is just a value, match up substring with generated bitstring from value + + constructor(...values: Array){ + this.values = values; + } + + length() { + return values.length; + } + + size(){ + let s = 0; + + for(let val of this.values){ + s = s + val.unit * val.size; + } + + return s; + } + + getValue(index){ + return this.values(index); + } + + getSizeOfValue(index){ + let val = this.getValue(index); + return val.unit * val.size; + } + + getTypeOfValue(index){ + return this.getValue(index).type; + } +} + export function variable(name: ?string = null): Variable { return new Variable(name); } @@ -83,3 +127,7 @@ export function type(type: any, objPattern: Object = {}): Type { export function bound(value: any): Bound { return new Bound(value); } + +export function bitStringMatch(...values: Array){ + return new BitStringMatch(...values); +} diff --git a/src/javascript/tests/patterns/defmatch.spec.js b/src/javascript/tests/patterns/defmatch.spec.js index 28c686af..486c3ed6 100644 --- a/src/javascript/tests/patterns/defmatch.spec.js +++ b/src/javascript/tests/patterns/defmatch.spec.js @@ -1,6 +1,7 @@ import Core from "../../lib/core"; const Patterns = Core.Patterns; const Tuple = Core.Tuple; +const BitString = Core.BitString; import chai from 'chai'; var expect = chai.expect; @@ -146,4 +147,92 @@ describe('defmatch', () => { expect(fn(new Tuple(1, 2, 3))).to.equal(3); expect(fn.bind(fn, new Tuple(1, 2, 4))).to.throw("No match for: {1, 2, 4}"); }); + + describe('BitString', () => { + it('must match on a string', () => { + + let fn = Patterns.defmatch( + Patterns.make_case( + [Patterns.bitStringMatch(BitString.integer(102), BitString.integer(111), BitString.integer(111))], + () => 3 + ) + ); + + expect(fn("foo")).to.equal(3); + expect(fn.bind(fn, "bar")).to.throw("No match for: bar"); + }); + + it('must match on a bitstring', () => { + + let fn = Patterns.defmatch( + Patterns.make_case( + [Patterns.bitStringMatch(BitString.integer(102), BitString.integer(111), BitString.integer(111))], + () => 3 + ) + ); + + expect(fn(new BitString(BitString.integer(102), BitString.integer(111), BitString.integer(111)))).to.equal(3); + }); + + it('must allow for variables', () => { + + let fn = Patterns.defmatch( + Patterns.make_case( + [Patterns.bitStringMatch(BitString.integer({value: $}), BitString.integer(111), BitString.integer(111))], + (pattern) => pattern + ) + ); + + expect(fn(new BitString(BitString.integer(102), BitString.integer(111), BitString.integer(111)))).to.equal(102); + }); + + it('must match on variable and convert to type', () => { + + let fn = Patterns.defmatch( + Patterns.make_case( + [Patterns.bitStringMatch(BitString.integer(102), BitString.binary({value: $}))], + (b) => b + ) + ); + + expect(fn(new BitString(BitString.integer(102), BitString.integer(111), BitString.integer(111)))).to.equal("oo"); + }); + + it('throw error when binary is used without size', () => { + + let fn = Patterns.defmatch( + Patterns.make_case( + [Patterns.bitStringMatch(BitString.binary({value: $}), BitString.binary(" the "), BitString.binary({value: $}))], + (name, species) => name + ) + ); + + expect(fn.bind(fn, "Frank the Walrus")).to.throw("a binary field without size is only allowed at the end of a binary pattern"); + }); + + it('allow binary pattern with size', () => { + + let fn = Patterns.defmatch( + Patterns.make_case( + [Patterns.bitStringMatch(BitString.size(BitString.binary({value: $}), 5), BitString.binary(" the "), BitString.binary({value: $}))], + (name, species) => name + ) + ); + + expect(fn("Frank the Walrus")).to.equal("Frank"); + }); + + + it('allow unsigned integer', () => { + + let fn = Patterns.defmatch( + Patterns.make_case( + [Patterns.bitStringMatch(BitString.integer({value: $}))], + (int) => int + ) + ); + + expect(fn(new BitString(BitString.integer(-100)))).to.equal(156); + }); + }); }); From 41644f7fc2eb955f8e1fff3cd9a10039a0677cd6 Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Mon, 22 Feb 2016 22:51:58 -0600 Subject: [PATCH 155/860] Added bitstring pattern matching for bitstrings to PatternMatching library --- lib/elixir_script/translator/bitstring.ex | 18 +++++----- .../translator/pattern_matching.ex | 34 +++++++++++++++++++ test/translator/bitstring_test.exs | 14 ++++++++ 3 files changed, 57 insertions(+), 9 deletions(-) diff --git a/lib/elixir_script/translator/bitstring.ex b/lib/elixir_script/translator/bitstring.ex index 57d373dc..a8e7b43d 100644 --- a/lib/elixir_script/translator/bitstring.ex +++ b/lib/elixir_script/translator/bitstring.ex @@ -19,41 +19,41 @@ defmodule ElixirScript.Translator.Bitstring do { js_ast, env } end - defp make_bitstring_element(element, env) when is_number(element) do + def make_bitstring_element(element, env) when is_number(element) do do_make_bitstring_element({:integer, Translator.translate!(element, env)}) end - defp make_bitstring_element(element, env) when is_binary(element) do + def make_bitstring_element(element, env) when is_binary(element) do do_make_bitstring_element({:binary, Translator.translate!(element, env)}) end - defp make_bitstring_element({:<<>>, [], elements}, env) do + def make_bitstring_element({:<<>>, [], elements}, env) do {ast, _} = make_bitstring(elements, env) ast end - defp make_bitstring_element({:::, _, [element, {type, _, _}]}, env) when type in [:integer, :float, :bitstring, :bits, :binary, :bytes, :utf8, :utf16, :utf32] do + def make_bitstring_element({:::, _, [element, {type, _, _}]}, env) when type in [:integer, :float, :bitstring, :bits, :binary, :bytes, :utf8, :utf16, :utf32] do do_make_bitstring_element({type, Translator.translate!(element, env)}) end - defp make_bitstring_element({:::, _, [element, {type, _, params}]}, env) when type in [:size, :unit] do + def make_bitstring_element({:::, _, [element, {type, _, params}]}, env) when type in [:size, :unit] do do_make_bitstring_element({type, Translator.translate!(element, env), Enum.map(params, &Translator.translate!(&1, env))}) end - defp make_bitstring_element({:::, _, [element, {:*, _, [size, unit]}]}, env) do + def make_bitstring_element({:::, _, [element, {:*, _, [size, unit]}]}, env) do size_ast = do_make_bitstring_element({:size, Translator.translate!(element, env), [Translator.translate!(size, env)]}) do_make_bitstring_element({:unit, size_ast, [Translator.translate!(unit, env)]}) end - defp make_bitstring_element({:::, _, [element, {:-, _, types}]}, env) do + def make_bitstring_element({:::, _, [element, {:-, _, types}]}, env) do handle_type_adjectives({:-, [], types}, Translator.translate!(element, env), env) end - defp make_bitstring_element({:::, _, [element, size]}, env) do + def make_bitstring_element({:::, _, [element, size]}, env) do do_make_bitstring_element({:size, Translator.translate!(element, env), [Translator.translate!(size, env)]}) end - defp make_bitstring_element(element, env) do + def make_bitstring_element(element, env) do do_make_bitstring_element({:binary, Translator.translate!(element, env)}) end diff --git a/lib/elixir_script/translator/pattern_matching.ex b/lib/elixir_script/translator/pattern_matching.ex index 0c77b40e..5490fad7 100644 --- a/lib/elixir_script/translator/pattern_matching.ex +++ b/lib/elixir_script/translator/pattern_matching.ex @@ -7,6 +7,7 @@ defmodule ElixirScript.Translator.PatternMatching do alias ElixirScript.Translator.Utils alias ElixirScript.Translator.Map alias ElixirScript.Translator.Struct + alias ElixirScript.Translator.Bitstring @patterns JS.member_expression( JS.member_expression( @@ -51,6 +52,11 @@ defmodule ElixirScript.Translator.PatternMatching do JS.identifier(:type) ) + @bitstring_match JS.member_expression( + @patterns, + JS.identifier(:bitStringMatch) + ) + def wildcard() do JS.call_expression( @wildcard, @@ -100,6 +106,14 @@ defmodule ElixirScript.Translator.PatternMatching do ) end + def bitstring_match(values) do + JS.call_expression( + @bitstring_match, + values + ) + end + + def process_match(params, env) do build_match(params, env) |> update_env(env) @@ -137,6 +151,26 @@ defmodule ElixirScript.Translator.PatternMatching do { [wildcard()], [JS.identifier(:undefined)] } end + defp do_build_match({:<<>>, _, elements}, env) do + params = Enum.reduce(elements, [], fn + ({:::, _, [{ variable, [], params }, _]}, state) when is_atom(params) -> + state ++ [JS.identifier(variable)] + _, state -> + state + end) + + var = {{:., [], [{:__aliases__, [], [Elixir, :Core, :Patterns]}, :variable]}, [], []} + + elements = Enum.map(elements, fn + ({:::, context, [{ variable, [], params }, options]}) when is_atom(params) -> + Bitstring.make_bitstring_element({:::, context, [{:%{}, [], [{"value", var}]}, options]}, env) + x -> + Bitstring.make_bitstring_element(x, env) + end) + + { [bitstring_match(elements)], params } + end + defp do_build_match([{:|, _, [head, tail]}], env) do { head_patterns, head_params } = do_build_match(head, env) { tail_patterns, tail_params } = do_build_match(tail, env) diff --git a/test/translator/bitstring_test.exs b/test/translator/bitstring_test.exs index c0ec38d2..0fe84c1e 100644 --- a/test/translator/bitstring_test.exs +++ b/test/translator/bitstring_test.exs @@ -39,4 +39,18 @@ defmodule ElixirScript.Translator.Bitstring.Test do ex_ast = quote do: << 1, <<2>> >> assert_translation(ex_ast, "new Elixir.Core.BitString(Elixir.Core.BitString.integer(1), new Elixir.Core.BitString(Elixir.Core.BitString.integer(2)))") end + + test "translate pattern matching bitstring" do + ex_ast = quote do: <> = <<"Frank the Walrus">> + js_code = """ + let [name,species] = Elixir.Core.Patterns.match(Elixir.Core.Patterns.bitStringMatch(Elixir.Core.BitString.size(Elixir.Core.BitString.binary(Object.freeze({ + value: Elixir.Core.Functions.call_property(Elixir.Core.Patterns,'variable') + })),5),Elixir.Core.BitString.binary(' the '),Elixir.Core.BitString.binary(Object.freeze({ + value: Elixir.Core.Functions.call_property(Elixir.Core.Patterns,'variable') + }))),'Frank the Walrus'); + """ + + assert_translation(ex_ast, js_code) + end + end From d6858919ce81e08c4a87ac01f1919d4df3f66529 Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Mon, 22 Feb 2016 23:30:16 -0600 Subject: [PATCH 156/860] Updated documentation. Added more bitstring tests --- CHANGELOG.md | 4 ++++ FAQ.md | 1 - mix.exs | 2 +- test/translator/bitstring_test.exs | 20 ++++++++++++++++++++ 4 files changed, 25 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 3eff4858..98286fc9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,7 @@ +# v0.16.0-dev +* Enhancements + * Support for bitstring pattern matching + # v0.15.2 * Enhancements * Support for variables as map keys diff --git a/FAQ.md b/FAQ.md index 606ae41d..2cffe069 100644 --- a/FAQ.md +++ b/FAQ.md @@ -41,7 +41,6 @@ The compiler to this point has been focused on translating Kernel.SpecialForms a * `with` * Caveats - * `<>` - not supported in pattern matching yet * `quote` - ignores `location` and `context` options * `left = right` does not support full unification yet. ```elixir diff --git a/mix.exs b/mix.exs index ffacd5ae..4a2dec7d 100644 --- a/mix.exs +++ b/mix.exs @@ -4,7 +4,7 @@ defmodule ElixirScript.Mixfile do def project do [ app: :elixir_script, - version: "0.15.2", + version: "0.16.0-dev", elixir: "~> 1.0", escript: escript_config, deps: deps, diff --git a/test/translator/bitstring_test.exs b/test/translator/bitstring_test.exs index 0fe84c1e..8632fb7f 100644 --- a/test/translator/bitstring_test.exs +++ b/test/translator/bitstring_test.exs @@ -51,6 +51,26 @@ defmodule ElixirScript.Translator.Bitstring.Test do """ assert_translation(ex_ast, js_code) + + + ex_ast = quote do: <> = <<-100>> + js_code = """ + let [int] = Elixir.Core.Patterns.match(Elixir.Core.Patterns.bitStringMatch(Elixir.Core.BitString.integer(Object.freeze({ + value: Elixir.Core.Functions.call_property(Elixir.Core.Patterns,'variable') + }))),new Elixir.Core.BitString(Elixir.Core.BitString.binary(-100))); + """ + + assert_translation(ex_ast, js_code) + + + ex_ast = quote do: <<-100::signed, _rest::binary>> = <<-100, "foo">> + js_code = """ + let [_rest] = Elixir.Core.Patterns.match(Elixir.Core.Patterns.bitStringMatch(Elixir.Core.BitString.size(-100, signed),Elixir.Core.BitString.binary(Object.freeze({ + value: Elixir.Core.Functions.call_property(Elixir.Core.Patterns,'variable') + }))),new Elixir.Core.BitString(Elixir.Core.BitString.binary(-100),Elixir.Core.BitString.binary('foo'))); + """ + + assert_translation(ex_ast, js_code) end end From 29626d6768f031b7bd365de394465b2f80da164f Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Tue, 23 Feb 2016 06:58:58 -0600 Subject: [PATCH 157/860] Refactored getSize function used for bitstring pattern matching --- src/javascript/lib/core/patterns/resolvers.js | 18 ++++-------------- 1 file changed, 4 insertions(+), 14 deletions(-) diff --git a/src/javascript/lib/core/patterns/resolvers.js b/src/javascript/lib/core/patterns/resolvers.js index a92c7d27..defe9f2d 100644 --- a/src/javascript/lib/core/patterns/resolvers.js +++ b/src/javascript/lib/core/patterns/resolvers.js @@ -161,7 +161,7 @@ function resolveBitString(pattern: Types.BitStringMatch): Function { for(let bitstringMatchPart of pattern.values){ if(Checks.is_variable(bitstringMatchPart.value)){ - let size = getLength(bitstringMatchPart.type, bitstringMatchPart.unit, bitstringMatchPart.size); + let size = getSize(bitstringMatchPart.unit, bitstringMatchPart.size); fillArray(patternBitString, size); }else{ patternBitString = patternBitString.concat(new BitString(bitstringMatchPart).value); @@ -198,7 +198,7 @@ function resolveBitString(pattern: Types.BitStringMatch): Function { let size = 0; let bsValueArrayPart = []; let patternBitStringArrayPart = []; - size = getLength(bitstringMatchPart.type, bitstringMatchPart.unit, bitstringMatchPart.size); + size = getSize(bitstringMatchPart.unit, bitstringMatchPart.size); if(i === patternValues.length - 1){ bsValueArrayPart = bsValue.value.slice(beginningIndex); @@ -263,18 +263,8 @@ function resolveBitString(pattern: Types.BitStringMatch): Function { } -function getLength(type, unit, size){ - if(type === 'integer' && size === 8){ - return 1; - }else if(type === 'float' && size === 32){ - return 4; - } else if(type === 'float' && size === 64){ - return 8; - } else if(type === 'binary'){ - return size; - }else{ - return unit * size; - } +function getSize(unit, size){ + return (unit * size) / 8; } function arraysEqual(a, b) { From cfbc4e9a184a2e88024a0aef669c22cec9d7868e Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Tue, 23 Feb 2016 08:34:06 -0600 Subject: [PATCH 158/860] updated for translation to work for bitstrings --- lib/elixir_script/translator/for.ex | 13 +++++++++++ test/translator/for_test.exs | 34 +++++++++++++++++++++++++++-- 2 files changed, 45 insertions(+), 2 deletions(-) diff --git a/lib/elixir_script/translator/for.ex b/lib/elixir_script/translator/for.ex index b6fecb64..acff77bf 100644 --- a/lib/elixir_script/translator/for.ex +++ b/lib/elixir_script/translator/for.ex @@ -28,6 +28,19 @@ defmodule ElixirScript.Translator.For do defp handle_args(generators, env) do Enum.reduce(generators, %{collections: [], args: [], filter: nil, fun: nil, into: nil}, fn + + ({:<<>>, [], body}, state) -> + { bs_parts, collection } = Enum.map_reduce(body, nil, fn + {:::, _, _} = ast, state -> + {ast, state} + {:<-, [], [var, collection]}, state -> + { var, collection } + end) + + { patterns, params, env } = PatternMatching.process_match([{:<<>>, [], bs_parts}], env) + list = Primitive.make_list_no_translate([hd(patterns), Translator.translate!(collection, env)]) + %{state | collections: state.collections ++ [list], args: state.args ++ params } + ({:<-, _, [identifier, enum]}, state) -> { patterns, params, env } = PatternMatching.process_match([identifier], env) diff --git a/test/translator/for_test.exs b/test/translator/for_test.exs index cbce5df3..4dc2b16d 100644 --- a/test/translator/for_test.exs +++ b/test/translator/for_test.exs @@ -24,11 +24,14 @@ defmodule ElixirScript.Translator.For.Test do end js_code = """ - Elixir.Core.SpecialForms._for(Object.freeze([Object.freeze([Elixir.Core.Patterns.variable(), Object.freeze([1, 2, 3, 4])])]),function(n) { + Elixir.Core.SpecialForms._for( + Object.freeze([Object.freeze([Elixir.Core.Patterns.variable(), Object.freeze([1, 2, 3, 4])])]), + function(n) { return n * 2; },function() { return true; - },Object.freeze([])) + }, + Object.freeze([])) """ assert_translation(ex_ast, js_code) @@ -119,4 +122,31 @@ defmodule ElixirScript.Translator.For.Test do assert_translation(ex_ast, js_code) end + + test "translate for with bitstring" do + ex_ast = quote do + for <> do + {r, g, b} + end + end + + js_code = """ + Elixir.Core.SpecialForms._for(Object.freeze([Object.freeze([Elixir.Core.Patterns.bitStringMatch(Elixir.Core.BitString.size(Object.freeze({ + value: Elixir.Core.Functions.call_property(Elixir.Core.Patterns,'variable') + }),8),Elixir.Core.BitString.size(Object.freeze({ + value: Elixir.Core.Functions.call_property(Elixir.Core.Patterns,'variable') + }),8),Elixir.Core.BitString.size(Object.freeze({ + value: Elixir.Core.Functions.call_property(Elixir.Core.Patterns,'variable') + }),8)), pixels])]), + function(r,g,b) { + return new Elixir.Core.Tuple(r,g,b); + }, + function() { + return true; + }, + Object.freeze([])) + """ + + assert_translation(ex_ast, js_code) + end end From e8cf4b9a76e490728554e85189ee788c22c2a575 Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Tue, 23 Feb 2016 09:39:00 -0600 Subject: [PATCH 159/860] Got for working with bitstrings --- src/javascript/lib/core/bit_string.js | 22 ++++----- src/javascript/lib/core/patterns/types.js | 17 +++---- src/javascript/lib/core/special_forms.js | 55 ++++++++++++++++++----- src/javascript/tests/for.spec.js | 32 +++++++++++++ 4 files changed, 94 insertions(+), 32 deletions(-) diff --git a/src/javascript/lib/core/bit_string.js b/src/javascript/lib/core/bit_string.js index 42b50a75..fbec5544 100644 --- a/src/javascript/lib/core/bit_string.js +++ b/src/javascript/lib/core/bit_string.js @@ -1,13 +1,9 @@ class BitString { constructor(...args){ - this.raw_value = function(){ - return Object.freeze(args); - }; - this.value = Object.freeze(this.process(args)); this.length = this.value.length; - this.bit_size = this.raw_value().reduce((prev, current) => prev + (current.unit * current.size), 0); - this.byte_size = (this.bit_size / 8) + (this.bit_size % 8 > 0 ? 1 : 0); + this.bit_size = this.length * 8; + this.byte_size = this.length; } get(index){ @@ -18,6 +14,12 @@ class BitString { return this.value.length; } + slice(start, end = null){ + let s = this.value.slice(start, end); + let ms = s.map((elem) => BitString.integer(elem)); + return new BitString(...ms); + } + [Symbol.iterator]() { return this.value[Symbol.iterator](); } @@ -34,14 +36,14 @@ class BitString { return "<<" + s + ">>"; } - process(){ + process(bitStringParts){ let processed_values = []; var i; - for (i = 0; i < this.raw_value().length; i++) { - let processed_value = this['process_' + this.raw_value()[i].type](this.raw_value()[i]); + for (i = 0; i < bitStringParts.length; i++) { + let processed_value = this['process_' + bitStringParts[i].type](bitStringParts[i]); - for(let attr of this.raw_value()[i].attributes){ + for(let attr of bitStringParts[i].attributes){ processed_value = this['process_' + attr](processed_value); } diff --git a/src/javascript/lib/core/patterns/types.js b/src/javascript/lib/core/patterns/types.js index 2a8f37f6..52bb4654 100644 --- a/src/javascript/lib/core/patterns/types.js +++ b/src/javascript/lib/core/patterns/types.js @@ -59,15 +59,6 @@ export class Bound { export class BitStringMatch { values: Array - //{'value': value, 'attributes': [type, unit, size]}; - - //length = unit * size - - //use that info to map value to subset of bitstring - //use type to turn subset of bitstring into desired type - //if value is a variable, add variable to args list - //if value is just a value, match up substring with generated bitstring from value - constructor(...values: Array){ this.values = values; } @@ -76,11 +67,15 @@ export class BitStringMatch { return values.length; } - size(){ + bit_size() { + return this.byte_size() * 8; + } + + byte_size(){ let s = 0; for(let val of this.values){ - s = s + val.unit * val.size; + s = s + ((val.unit * val.size)/8); } return s; diff --git a/src/javascript/lib/core/special_forms.js b/src/javascript/lib/core/special_forms.js index f8e9611c..1257bb57 100644 --- a/src/javascript/lib/core/special_forms.js +++ b/src/javascript/lib/core/special_forms.js @@ -29,25 +29,58 @@ function _for(collections, fun, filter = () => true, into = [], previousValues = let collection = collections[0][1]; if(collections.length === 1){ + if(collection instanceof BitString){ + let bsSlice = collection.slice(0, pattern.byte_size()); + let i = 1; - for(let elem of collection){ - let r = Patterns.match_no_throw(pattern, elem); - let args = previousValues.concat(r); + while(bsSlice.byte_size == pattern.byte_size()){ + let r = Patterns.match_no_throw(pattern, bsSlice); + let args = previousValues.concat(r); - if(r && filter.apply(this, args)){ - into = into.concat([fun.apply(this, args)]); + if(r && filter.apply(this, args)){ + into = into.concat([fun.apply(this, args)]); + } + + bsSlice = collection.slice(pattern.byte_size() * i, pattern.byte_size() * (i + 1)); + i++; + } + + return into; + }else{ + for(let elem of collection){ + let r = Patterns.match_no_throw(pattern, elem); + let args = previousValues.concat(r); + + if(r && filter.apply(this, args)){ + into = into.concat([fun.apply(this, args)]); + } } - } - return into; + return into; + } }else{ let _into = []; - for(let elem of collection){ - let r = Patterns.match_no_throw(pattern, elem); - if(r){ - _into = into.concat(this._for(collections.slice(1), fun, filter, _into, previousValues.concat(r))); + if(collection instanceof BitString){ + let bsSlice = collection.slice(0, pattern.byte_size()); + let i = 1; + + while(bsSlice.byte_size == pattern.byte_size()){ + let r = Patterns.match_no_throw(pattern, bsSlice); + if(r){ + _into = into.concat(this._for(collections.slice(1), fun, filter, _into, previousValues.concat(r))); + } + + bsSlice = collection.slice(pattern.byte_size() * i, pattern.byte_size() * (i + 1)); + i++; } + }else{ + for(let elem of collection){ + let r = Patterns.match_no_throw(pattern, elem); + if(r){ + _into = into.concat(this._for(collections.slice(1), fun, filter, _into, previousValues.concat(r))); + } + } } return _into; diff --git a/src/javascript/tests/for.spec.js b/src/javascript/tests/for.spec.js index 8221fcc0..5ae6f667 100644 --- a/src/javascript/tests/for.spec.js +++ b/src/javascript/tests/for.spec.js @@ -1,6 +1,8 @@ import Core from "../lib/core"; const Patterns = Core.Patterns; const SpecialForms = Core.SpecialForms; +const Tuple = Core.Tuple; +const BitString = Core.BitString; import Enum from "../lib/enum"; @@ -56,4 +58,34 @@ describe('for', () => { expect(result).to.eql(["JOHN", "MEG"]); }); + + + it('for with bitstring', () => { + //for <> >>, do: {r, g, b} + + let collections = [ + [ + Patterns.bitStringMatch(BitString.integer({value: $}), BitString.integer({value: $}), BitString.integer({value: $})), + new BitString( + BitString.integer(213), + BitString.integer(45), + BitString.integer(132), + BitString.integer(64), + BitString.integer(76), + BitString.integer(32), + BitString.integer(76), + BitString.integer(0), + BitString.integer(0), + BitString.integer(234), + BitString.integer(32), + BitString.integer(15) + ) + ] + ]; + + let result = SpecialForms._for(collections, (r, g, b) => new Tuple(r, g, b)); + + expect(result).to.eql([new Tuple(213, 45, 132), new Tuple(64, 76, 32), new Tuple(76, 0, 0), new Tuple(234, 32, 15)]); + }); + }); From 921b81ed2e311191e60d6a6e2b2e84019ebc6c47 Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Tue, 23 Feb 2016 09:41:35 -0600 Subject: [PATCH 160/860] Updated docs --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 98286fc9..b9938d86 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,7 @@ # v0.16.0-dev * Enhancements * Support for bitstring pattern matching + * Support for bitstrings in for comprehensions # v0.15.2 * Enhancements From d36c2b5f698a9ab5e867857135424d98ed245c44 Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Tue, 23 Feb 2016 15:31:41 -0600 Subject: [PATCH 161/860] Supporting functions with catch, after, or else clauses --- CHANGELOG.md | 1 + lib/elixir_script/translator.ex | 6 +-- lib/elixir_script/translator/function.ex | 15 ++++++- .../translator/module_collector.ex | 11 +++-- test/translator/function_test.exs | 40 +++++++++++++++++++ 5 files changed, 62 insertions(+), 11 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index b9938d86..ba4d2835 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,7 @@ * Enhancements * Support for bitstring pattern matching * Support for bitstrings in for comprehensions + * Support for functions with catch, after, else clauses # v0.15.2 * Enhancements diff --git a/lib/elixir_script/translator.ex b/lib/elixir_script/translator.ex index 8608ea21..0144bdcf 100644 --- a/lib/elixir_script/translator.ex +++ b/lib/elixir_script/translator.ex @@ -432,15 +432,15 @@ defmodule ElixirScript.Translator do Assignment.make_assignment(left, right, env) end - defp do_translate({function, _, [{:when, _, [{name, _, _params} | _guards] }, [do: _body]] } = ast, env) when function in [:def, :defp] do + defp do_translate({function, _, [{:when, _, [{name, _, _params} | _guards] }, _] } = ast, env) when function in [:def, :defp] do Function.process_function(Utils.filter_name(name), [ast], env) end - defp do_translate({function, _, [{name, _, params}, [do: _body]]} = ast, env) when function in [:def, :defp] and is_atom(params) do + defp do_translate({function, _, [{name, _, params}, _]} = ast, env) when function in [:def, :defp] and is_atom(params) do Function.process_function(Utils.filter_name(name), [ast], env) end - defp do_translate({function, _, [{name, _, _params}, [do: _body]]} = ast, env) when function in [:def, :defp] do + defp do_translate({function, _, [{name, _, _params}, _]} = ast, env) when function in [:def, :defp] do Function.process_function(Utils.filter_name(name), [ast], env) end diff --git a/lib/elixir_script/translator/function.ex b/lib/elixir_script/translator/function.ex index 1a620c86..906b3e3e 100644 --- a/lib/elixir_script/translator/function.ex +++ b/lib/elixir_script/translator/function.ex @@ -29,13 +29,16 @@ defmodule ElixirScript.Translator.Function do |> Enum.map(fn {:->, _, [ [{:when, _, [params | guards]}], body ]} -> process_function_body(params, body, env, name, guards) + ({:->, _, [params, body]}) -> process_function_body(params, body, env, name) - ({_, _, [{:when, _, [{_, _, params} | guards] }, [do: body]]}) -> + ({_, _, [{:when, _, [{_, _, params} | guards] }, body]}) -> + body = convert_to_try(body) process_function_body(params, body, env, name, guards) - ({_, _, [{_, _, params}, [do: body]]}) -> + ({_, _, [{_, _, params}, body]}) -> + body = convert_to_try(body) process_function_body(params, body, env, name) ({_, _, [{_, _, params}]}) -> @@ -45,6 +48,14 @@ defmodule ElixirScript.Translator.Function do { make_defmatch(clauses), env } end + def convert_to_try([do: body]) do + body + end + + def convert_to_try(function_kw_list) do + { :__block__, [], [{ :try, [], [function_kw_list] }] } + end + def make_defmatch(clauses) do JS.call_expression( JS.member_expression( diff --git a/lib/elixir_script/translator/module_collector.ex b/lib/elixir_script/translator/module_collector.ex index 64512882..ce0f26cd 100644 --- a/lib/elixir_script/translator/module_collector.ex +++ b/lib/elixir_script/translator/module_collector.ex @@ -167,26 +167,25 @@ defmodule ElixirScript.Translator.ModuleCollector do defp get_functions_from_module({:__block__, _, list}) do Enum.reduce(list, %{ def: Keyword.new, defp: Keyword.new, defmacro: Keyword.new, defmacrop: Keyword.new }, fn - ({type, _, [{:when, _, [{name, _, params} | _guards] }, [do: _body]] }, state) when type in [:def, :defp] and is_atom(params) -> + ({type, _, [{:when, _, [{name, _, params} | _guards] }, _] }, state) when type in [:def, :defp] and is_atom(params) -> arity = 0 add_function_to_map(state, type, name, arity) - ({type, _, [{:when, _, [{name, _, params} | _guards] }, [do: _body]] }, state) when type in [:def, :defp] -> + ({type, _, [{:when, _, [{name, _, params} | _guards] }, _] }, state) when type in [:def, :defp] -> arity = if is_nil(params), do: 0, else: length(params) add_function_to_map(state, type, name, arity) - ({type, _, [{name, _, params}, [do: _body]]}, state) when type in [:def, :defp] and is_atom(params) -> + ({type, _, [{name, _, params}, _]}, state) when type in [:def, :defp] and is_atom(params) -> arity = 0 add_function_to_map(state, type, name, arity) - ({type, _, [{name, _, params}, [do: _body]]}, state) when type in [:def, :defp] -> + ({type, _, [{name, _, params}, _]}, state) when type in [:def, :defp] -> arity = if is_nil(params), do: 0, else: length(params) - - add_function_to_map(state, type, name, arity) + add_function_to_map(state, type, name, arity) ({type, _, [{:when, _, [{name, _, params} | _guards] }, [do: _body]] }, state) when type in [:defmacro, :defmacrop] -> arity = length(params) diff --git a/test/translator/function_test.exs b/test/translator/function_test.exs index baa0d82b..913fc086 100644 --- a/test/translator/function_test.exs +++ b/test/translator/function_test.exs @@ -777,4 +777,44 @@ defmodule ElixirScript.Translator.Function.Test do assert_translation(ex_ast, js_code) end + + test "def with catch" do + ex_ast = quote do + defp func(param) do + if true do + nil + else + :error + end + catch + :invalid -> :error + end + end + + js_code = """ + const func = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable()], + function(param) { + return Elixir.Core.SpecialForms._try(function() { + return Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable()], function(x) { + return Symbol.for('error'); + }, + function(x) { + return Elixir.Enum.member__qmark__(Object.freeze([false, null]), x); + }), + Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.wildcard()], function() { + return null; + })).call(this, true); + }, + null, + Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Symbol.for('invalid')], function() { + return Symbol.for('error'); + })), + null, + null + ); + })); + """ + + assert_translation(ex_ast, js_code) + end end From 4b2ee9e9ceb6ff50407330d44f05a9789334585b Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Tue, 23 Feb 2016 19:31:59 -0600 Subject: [PATCH 162/860] Update README.md --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index d432d400..ae1a03f8 100644 --- a/README.md +++ b/README.md @@ -48,6 +48,7 @@ Please check the [CONTRIBUTING.md](CONTRIBUTING.md) ### Example projects +* [todo-elixirscript](https://github.com/bryanjos/todo-elixirscript) A Todo App built with Elixirscript and Phoenix * [phoenix_chat_example](https://github.com/bryanjos/phoenix_chat_example) The Phoenix Chat App using ElixirScript. * [MobileElixir](https://github.com/bryanjos/MobileElixir) Using ElixirScript with React Native * [color_bar_spike](https://github.com/bryanjos/color_bar_spike) A canvas drawing example using ElixirScript, React and a Redux-like design From 2ac4963f9b34728645370ac00a004746153bdba5 Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Tue, 23 Feb 2016 20:23:30 -0600 Subject: [PATCH 163/860] Added with special form implementation in javascript --- src/javascript/lib/core/special_forms.js | 27 ++++++- src/javascript/tests/with.spec.js | 94 ++++++++++++++++++++++++ 2 files changed, 120 insertions(+), 1 deletion(-) create mode 100644 src/javascript/tests/with.spec.js diff --git a/src/javascript/lib/core/special_forms.js b/src/javascript/lib/core/special_forms.js index 1257bb57..76f700c4 100644 --- a/src/javascript/lib/core/special_forms.js +++ b/src/javascript/lib/core/special_forms.js @@ -140,10 +140,35 @@ function _try(do_fun, rescue_function, catch_fun, else_function, after_function) } } +function _with(...args){ + let argsToPass = []; + + for(let i = 0; i < args.length; i++){ + if(i === args.length - 1){ + return args[i].apply(null, argsToPass); + }else{ + let [pattern, func] = args[i]; + + let result = func.apply(null, argsToPass); + + let patternResult = Patterns.match_no_throw(pattern, result); + + if(patternResult == null){ + return result; + }else{ + argsToPass = argsToPass.concat(patternResult); + } + } + } + + return null; +} + export default { _case, cond, map_update, _for, - _try + _try, + _with }; diff --git a/src/javascript/tests/with.spec.js b/src/javascript/tests/with.spec.js new file mode 100644 index 00000000..8fef947a --- /dev/null +++ b/src/javascript/tests/with.spec.js @@ -0,0 +1,94 @@ +import Core from "../lib/core"; +const Patterns = Core.Patterns; +const SpecialForms = Core.SpecialForms; +const Tuple = Core.Tuple; + +import Enum from "../lib/enum"; + +import chai from 'chai'; +var expect = chai.expect; + +const $ = Patterns.variable(); + +function map_fetch(map, key){ + if(key in map){ + return new Tuple(Symbol.for('ok'), map[key]); + } + + return Symbol.for('error'); +} + +describe('with', () => { + + it('normal', () => { + /* + opts = %{width: 10, height: 15} + + with {:ok, width} <- Map.fetch(opts, :width), + {:ok, height} <- Map.fetch(opts, :height), + do: {:ok, width * height} + + {:ok, 150} + */ + + let opts = { width: 10, height: 15 }; + + let value = SpecialForms._with( + [new Tuple(Symbol.for('ok'), $), () => map_fetch(opts, "width")], + [new Tuple(Symbol.for('ok'), $), (width) => map_fetch(opts, "height")], + (width, height) => new Tuple(Symbol.for('ok'), width * height) + ); + + expect(value).to.eql(new Tuple(Symbol.for('ok'), 150)); + }); + + + it('without match', () => { + /* + opts = %{width: 10} + + with {:ok, width} <- Map.fetch(opts, :width), + {:ok, height} <- Map.fetch(opts, :height), + do: {:ok, width * height} + + :error + */ + + let opts = { width: 10 }; + + let value = SpecialForms._with( + [new Tuple(Symbol.for('ok'), $), () => map_fetch(opts, "width")], + [new Tuple(Symbol.for('ok'), $), (width) => map_fetch(opts, "height")], + (width, height) => new Tuple(Symbol.for('ok'), width * height) + ); + + expect(value).to.eql(Symbol.for('error')); + }); + + + it('bare expression', () => { + /* + opts = %{width: 10} + + with {:ok, width} <- Map.fetch(opts, :width), + double_width = width * 2, + {:ok, height} <- Map.fetch(opts, :height), + do: {:ok, double_width * height} + + {:ok, 300} + */ + + let opts = { width: 10, height: 15 }; + + let value = SpecialForms._with( + [new Tuple(Symbol.for('ok'), $), () => map_fetch(opts, "width")], + [$, (width) => width * 2], + [new Tuple(Symbol.for('ok'), $), (width, double_width) => map_fetch(opts, "height")], + (width, double_width, height) => new Tuple(Symbol.for('ok'), double_width * height) + ); + + expect(value).to.eql(new Tuple(Symbol.for('ok'), 300)); + }); + +}); + From 0e3f1ce063676b5d14f8ed74b2b140b3d5a33cd1 Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Tue, 23 Feb 2016 20:54:05 -0600 Subject: [PATCH 164/860] Added with translation --- lib/elixir_script/translator.ex | 5 +++ lib/elixir_script/translator/with.ex | 43 +++++++++++++++++++++ test/translator/with_test.exs | 56 ++++++++++++++++++++++++++++ 3 files changed, 104 insertions(+) create mode 100644 lib/elixir_script/translator/with.ex create mode 100644 test/translator/with_test.exs diff --git a/lib/elixir_script/translator.ex b/lib/elixir_script/translator.ex index 0144bdcf..3c644cd0 100644 --- a/lib/elixir_script/translator.ex +++ b/lib/elixir_script/translator.ex @@ -12,6 +12,7 @@ defmodule ElixirScript.Translator do alias ElixirScript.Translator.Case alias ElixirScript.Translator.For alias ElixirScript.Translator.Try + alias ElixirScript.Translator.With alias ElixirScript.Translator.Block alias ElixirScript.Translator.Struct alias ElixirScript.Translator.Module @@ -291,6 +292,10 @@ defmodule ElixirScript.Translator do Try.make_try(blocks, env) end + defp do_translate({:with, _, args }, env ) do + With.make_with(args, env) + end + defp do_translate({:receive, _, _ }, _ ) do raise ElixirScript.Translator.UnsupportedError, "receive" end diff --git a/lib/elixir_script/translator/with.ex b/lib/elixir_script/translator/with.ex new file mode 100644 index 00000000..7ca3865b --- /dev/null +++ b/lib/elixir_script/translator/with.ex @@ -0,0 +1,43 @@ +defmodule ElixirScript.Translator.With do + @moduledoc false + + alias ESTree.Tools.Builder, as: JS + alias ElixirScript.Translator.Function + alias ElixirScript.Translator.Primitive + alias ElixirScript.Translator.PatternMatching + + def make_with(args, env) do + result = Enum.reduce(args, %{ expressions: [], arguments: [] }, fn + {symbol, _, [pattern, expr] }, state when symbol in [:<-, :=] -> + {body , _} = Function.prepare_function_body(expr, env) + translated_body = JS.block_statement(body) + expr_function = JS.function_expression(state.arguments, [], translated_body) + + { patterns, params, env } = PatternMatching.process_match([pattern], env) + + %{state | arguments: state.arguments ++ params, + expressions: state.expressions ++ [ JS.array_expression([hd(patterns), expr_function]) ] } + + [do: expr], state -> + + {body , _} = Function.prepare_function_body(expr, env) + translated_body = JS.block_statement(body) + expr_function = JS.function_expression(state.arguments, [], translated_body) + + %{state | expressions: state.expressions ++ [ expr_function ] } + end) + + expressions = result.expressions + + js_ast = JS.call_expression( + JS.member_expression( + Primitive.special_forms(), + JS.identifier("_with") + ), + expressions + ) + + { js_ast, env } + + end +end diff --git a/test/translator/with_test.exs b/test/translator/with_test.exs new file mode 100644 index 00000000..28a4c8b3 --- /dev/null +++ b/test/translator/with_test.exs @@ -0,0 +1,56 @@ +defmodule ElixirScript.Translator.With.Test do + use ExUnit.Case + import ElixirScript.TestHelper + + + test "translate with" do + ex_ast = quote do + with {:ok, width} <- Map.fetch(opts, :width), + {:ok, height} <- Map.fetch(opts, :height), + do: {:ok, width * height} + end + + js_code = """ + Elixir.Core.SpecialForms._with([Elixir.Core.Patterns.type(Elixir.Core.Tuple,{ + values: [Symbol.for('ok'), Elixir.Core.Patterns.variable()] + }), function() { + return Elixir$ElixirScript$Map.fetch(opts,Symbol.for('width')); + }],[Elixir.Core.Patterns.type(Elixir.Core.Tuple,{ + values: [Symbol.for('ok'), Elixir.Core.Patterns.variable()] + }), function(width) { + return Elixir$ElixirScript$Map.fetch(opts,Symbol.for('height')); + }],function(width,height) { + return new Elixir.Core.Tuple(Symbol.for('ok'),width * height); + }) + """ + + assert_translation(ex_ast, js_code) + end + + test "translate with with bare expression" do + ex_ast = quote do + with {:ok, width} <- Map.fetch(opts, :width), + double_width = width * 2, + {:ok, height} <- Map.fetch(opts, :height), + do: {:ok, double_width * height} + end + + js_code = """ + Elixir.Core.SpecialForms._with([Elixir.Core.Patterns.type(Elixir.Core.Tuple,{ + values: [Symbol.for('ok'), Elixir.Core.Patterns.variable()] + }), function() { + return Elixir$ElixirScript$Map.fetch(opts,Symbol.for('width')); + }],[Elixir.Core.Patterns.variable(), function(width) { + return width * 2; + }],[Elixir.Core.Patterns.type(Elixir.Core.Tuple,{ + values: [Symbol.for('ok'), Elixir.Core.Patterns.variable()] + }), function(width,double_width) { + return Elixir$ElixirScript$Map.fetch(opts,Symbol.for('height')); + }],function(width,double_width,height) { + return new Elixir.Core.Tuple(Symbol.for('ok'),double_width * height); + }) + """ + + assert_translation(ex_ast, js_code) + end +end From 823cc7061d5d1a2ef282093e1e140c322f921ef2 Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Tue, 23 Feb 2016 20:55:20 -0600 Subject: [PATCH 165/860] Updated docs --- CHANGELOG.md | 1 + FAQ.md | 1 - 2 files changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index ba4d2835..fdb075e3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,7 @@ * Support for bitstring pattern matching * Support for bitstrings in for comprehensions * Support for functions with catch, after, else clauses + * Support for `with` special form # v0.15.2 * Enhancements diff --git a/FAQ.md b/FAQ.md index 2cffe069..8b11ba90 100644 --- a/FAQ.md +++ b/FAQ.md @@ -38,7 +38,6 @@ The compiler to this point has been focused on translating Kernel.SpecialForms a * Missing * `super(args)` * `receive` - * `with` * Caveats * `quote` - ignores `location` and `context` options From a1b69e5e2b9f1be2d4e52d91633a206386e57100 Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Thu, 25 Feb 2016 09:08:55 -0600 Subject: [PATCH 166/860] Added support for pin operator in function and map keys --- CHANGELOG.md | 9 ++++---- .../translator/pattern_matching.ex | 9 +++++++- test/translator/function_test.exs | 23 +++++++++++++++++++ test/translator/map_test.exs | 10 ++++++++ 4 files changed, 46 insertions(+), 5 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index fdb075e3..b0947149 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,9 +1,10 @@ # v0.16.0-dev * Enhancements - * Support for bitstring pattern matching - * Support for bitstrings in for comprehensions - * Support for functions with catch, after, else clauses - * Support for `with` special form + * Bitstring pattern matching + * Bitstrings in for comprehensions + * Functions with catch, after, else clauses + * `with` special form + * Pin operator in map keys and function clauses # v0.15.2 * Enhancements diff --git a/lib/elixir_script/translator/pattern_matching.ex b/lib/elixir_script/translator/pattern_matching.ex index 5490fad7..5a898eb1 100644 --- a/lib/elixir_script/translator/pattern_matching.ex +++ b/lib/elixir_script/translator/pattern_matching.ex @@ -186,7 +186,14 @@ defmodule ElixirScript.Translator.PatternMatching do defp do_build_match({:%{}, _, props}, env) do properties = Enum.map(props, fn({key, value}) -> {pattern, params} = do_build_match(value, env) - { Map.make_property(Translator.translate!(key, env), hd(List.wrap(pattern))), params } + property = case key do + {:^, _, [the_key]} -> + JS.property(Translator.translate!(the_key, env), hd(List.wrap(pattern)), :init, false, false, true) + _ -> + Map.make_property(Translator.translate!(key, env), hd(List.wrap(pattern))) + end + + { property, params } end) {props, params} = Enum.reduce(properties, {[], []}, fn({prop, param}, {props, params}) -> diff --git a/test/translator/function_test.exs b/test/translator/function_test.exs index 913fc086..84c195fb 100644 --- a/test/translator/function_test.exs +++ b/test/translator/function_test.exs @@ -817,4 +817,27 @@ defmodule ElixirScript.Translator.Function.Test do assert_translation(ex_ast, js_code) end + + + test "translate anonymous function with variable bound" do + ex_ast = quote do + key = "test" + fn ^key -> :ok end + end + + js_code = """ + let [key] = Elixir.Core.Patterns.match(Elixir.Core.Patterns.variable(),'test'); + + Elixir.Core.Patterns.defmatch( + Elixir.Core.Patterns.make_case( + [Elixir.Core.Patterns.bound(key)], + function() { + return Symbol.for('ok'); + } + ) + ) + """ + + assert_translation(ex_ast, js_code) + end end diff --git a/test/translator/map_test.exs b/test/translator/map_test.exs index 43419637..2ea36e51 100644 --- a/test/translator/map_test.exs +++ b/test/translator/map_test.exs @@ -59,4 +59,14 @@ defmodule ElixirScript.Translator.Map.Test do assert_translation(ex_ast, js_code) end + test "translate bound map key" do + ex_ast = quote do: %{^key => value} = %{key => value} + js_code = """ + let [value] = Elixir.Core.Patterns.match( + { [key]: Elixir.Core.Patterns.variable() }, + Object.freeze({ [key]: value }) + ); + """ + assert_translation(ex_ast, js_code) + end end From d09b7855ce9dc149644a84ccb8bce35b36364a07 Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Thu, 25 Feb 2016 17:25:10 -0600 Subject: [PATCH 167/860] Fixed optional parameter implementation --- CHANGELOG.md | 3 + .../translator/pattern_matching.ex | 9 +- priv/Elixir.js | 350 ++++++++++++++++-- src/javascript/lib/core/patterns/defmatch.js | 43 +++ src/javascript/lib/core/patterns/types.js | 10 +- .../tests/patterns/defmatch.spec.js | 61 +++ test/translator/function_test.exs | 17 +- 7 files changed, 445 insertions(+), 48 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index b0947149..f959cdee 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,9 @@ * Functions with catch, after, else clauses * `with` special form * Pin operator in map keys and function clauses + +* Bugfixes + * Fixed optional parameter implementation # v0.15.2 * Enhancements diff --git a/lib/elixir_script/translator/pattern_matching.ex b/lib/elixir_script/translator/pattern_matching.ex index 5a898eb1..63bb413e 100644 --- a/lib/elixir_script/translator/pattern_matching.ex +++ b/lib/elixir_script/translator/pattern_matching.ex @@ -71,6 +71,13 @@ defmodule ElixirScript.Translator.PatternMatching do ) end + def parameter(default_value) do + JS.call_expression( + @parameter, + [default_value] + ) + end + def head_tail(headParameter, tailParameter) do JS.call_expression( @head_tail, @@ -251,7 +258,7 @@ defmodule ElixirScript.Translator.PatternMatching do defp do_build_match({:\\, _, [{name, _, _}, default]}, env) do name = Utils.filter_name(name) - { [parameter()], [ JS.assignment_expression(:=, JS.identifier(name), Translator.translate!(default, env))] } + { [parameter(Translator.translate!(default, env))], [JS.identifier(name)] } end diff --git a/priv/Elixir.js b/priv/Elixir.js index dfe476f1..2eebc37c 100644 --- a/priv/Elixir.js +++ b/priv/Elixir.js @@ -265,14 +265,10 @@ class ProcessSystem { class BitString { constructor(...args) { - this.raw_value = function () { - return Object.freeze(args); - }; - this.value = Object.freeze(this.process(args)); this.length = this.value.length; - this.bit_size = this.raw_value().reduce((prev, current) => prev + current.size); - this.byte_size = this.bit_size / 8 + (this.bit_size % 8 > 0 ? 1 : 0); + this.bit_size = this.length * 8; + this.byte_size = this.length; } get(index) { @@ -283,6 +279,12 @@ class BitString { return this.value.length; } + slice(start, end = null) { + let s = this.value.slice(start, end); + let ms = s.map(elem => BitString.integer(elem)); + return new BitString(...ms); + } + [Symbol.iterator]() { return this.value[Symbol.iterator](); } @@ -294,20 +296,20 @@ class BitString { if (s !== "") { s += ", "; } - s += this[i].toString(); + s += this.get(i).toString(); } return "<<" + s + ">>"; } - process() { + process(bitStringParts) { let processed_values = []; var i; - for (i = 0; i < this.raw_value().length; i++) { - let processed_value = this['process_' + this.raw_value()[i].type](this.raw_value()[i]); + for (i = 0; i < bitStringParts.length; i++) { + let processed_value = this['process_' + bitStringParts[i].type](bitStringParts[i]); - for (let attr of this.raw_value()[i].attributes) { + for (let attr of bitStringParts[i].attributes) { processed_value = this['process_' + attr](processed_value); } @@ -404,15 +406,15 @@ class BitString { } static utf8(value) { - return BitString.wrap(value, { 'type': 'utf8' }); + return BitString.wrap(value, { 'type': 'utf8', 'unit': 1, 'size': value.length }); } static utf16(value) { - return BitString.wrap(value, { 'type': 'utf16' }); + return BitString.wrap(value, { 'type': 'utf16', 'unit': 1, 'size': value.length * 2 }); } static utf32(value) { - return BitString.wrap(value, { 'type': 'utf32' }); + return BitString.wrap(value, { 'type': 'utf32', 'unit': 1, 'size': value.length * 4 }); } static signed(value) { @@ -561,8 +563,8 @@ class BitString { class Variable { - constructor(name = null) { - this.name = name; + constructor(default_value = Symbol.for("elixirscript.no_value")) { + this.default_value = default_value; } } @@ -607,8 +609,46 @@ class Bound { } } -function variable(name = null) { - return new Variable(name); +class BitStringMatch { + + constructor(...values) { + this.values = values; + } + + length() { + return values.length; + } + + bit_size() { + return this.byte_size() * 8; + } + + byte_size() { + let s = 0; + + for (let val of this.values) { + s = s + val.unit * val.size / 8; + } + + return s; + } + + getValue(index) { + return this.values(index); + } + + getSizeOfValue(index) { + let val = this.getValue(index); + return val.unit * val.size; + } + + getTypeOfValue(index) { + return this.getValue(index).type; + } +} + +function variable(default_value = Symbol.for("elixirscript.no_value")) { + return new Variable(default_value); } function wildcard() { @@ -635,6 +675,10 @@ function bound(value) { return new Bound(value); } +function bitStringMatch(...values) { + return new BitStringMatch(...values); +} + function is_number(value) { return typeof value === 'number'; } @@ -699,6 +743,10 @@ function is_array(value) { return Array.isArray(value); } +function is_bitstring(value) { + return value instanceof BitStringMatch; +} + var Checks = { is_number, is_string, @@ -715,7 +763,8 @@ var Checks = { is_startsWith, is_bound, is_object, - is_array + is_array, + is_bitstring }; function resolveSymbol(pattern) { @@ -869,6 +918,136 @@ function resolveObject(pattern) { }; } +function resolveBitString(pattern) { + let patternBitString = []; + + for (let bitstringMatchPart of pattern.values) { + if (Checks.is_variable(bitstringMatchPart.value)) { + let size = getSize(bitstringMatchPart.unit, bitstringMatchPart.size); + fillArray(patternBitString, size); + } else { + patternBitString = patternBitString.concat(new BitString(bitstringMatchPart).value); + } + } + + let patternValues = pattern.values; + + return function (value, args) { + let bsValue = null; + + if (!Checks.is_string(value) && !(value instanceof BitString)) { + return false; + } + + if (Checks.is_string(value)) { + bsValue = new BitString(BitString.binary(value)); + } else { + bsValue = value; + } + + let beginningIndex = 0; + + for (let i = 0; i < patternValues.length; i++) { + let bitstringMatchPart = patternValues[i]; + + if (Checks.is_variable(bitstringMatchPart.value) && bitstringMatchPart.type == 'binary' && bitstringMatchPart.size === undefined && i < patternValues.length - 1) { + throw new Error("a binary field without size is only allowed at the end of a binary pattern"); + } + + let size = 0; + let bsValueArrayPart = []; + let patternBitStringArrayPart = []; + size = getSize(bitstringMatchPart.unit, bitstringMatchPart.size); + + if (i === patternValues.length - 1) { + bsValueArrayPart = bsValue.value.slice(beginningIndex); + patternBitStringArrayPart = patternBitString.slice(beginningIndex); + } else { + bsValueArrayPart = bsValue.value.slice(beginningIndex, beginningIndex + size); + patternBitStringArrayPart = patternBitString.slice(beginningIndex, beginningIndex + size); + } + + if (Checks.is_variable(bitstringMatchPart.value)) { + switch (bitstringMatchPart.type) { + case 'integer': + if (bitstringMatchPart.attributes && bitstringMatchPart.attributes.indexOf("signed") != -1) { + args.push(new Int8Array([bsValueArrayPart[0]])[0]); + } else { + args.push(new Uint8Array([bsValueArrayPart[0]])[0]); + } + break; + + case 'float': + if (size === 64) { + args.push(Float64Array.from(bsValueArrayPart)[0]); + } else if (size === 32) { + args.push(Float32Array.from(bsValueArrayPart)[0]); + } else { + return false; + } + break; + + case 'bitstring': + args.push(createBitString(bsValueArrayPart)); + break; + + case 'binary': + args.push(String.fromCharCode.apply(null, new Uint8Array(bsValueArrayPart))); + break; + + case 'utf8': + args.push(String.fromCharCode.apply(null, new Uint8Array(bsValueArrayPart))); + break; + + case 'utf16': + args.push(String.fromCharCode.apply(null, new Uint16Array(bsValueArrayPart))); + break; + + case 'utf32': + args.push(String.fromCharCode.apply(null, new Uint32Array(bsValueArrayPart))); + break; + + default: + return false; + } + } else if (!arraysEqual(bsValueArrayPart, patternBitStringArrayPart)) { + return false; + } + + beginningIndex = beginningIndex + size; + } + + return true; + }; +} + +function getSize(unit, size) { + return unit * size / 8; +} + +function arraysEqual(a, b) { + if (a === b) return true; + if (a == null || b == null) return false; + if (a.length != b.length) return false; + + for (var i = 0; i < a.length; ++i) { + if (a[i] !== b[i]) return false; + } + + return true; +} + +function fillArray(arr, num) { + for (let i = 0; i < num; i++) { + arr.push(0); + } +} + +function createBitString(arr) { + let integerParts = arr.map(elem => BitString.integer(elem)); + return new BitString(...integerParts); +} + function resolveNoMatch() { return function () { return false; @@ -891,7 +1070,8 @@ var Resolvers = { resolveNumber, resolveBoolean, resolveFunction, - resolveNull + resolveNull, + resolveBitString }; function buildMatch(pattern) { @@ -952,6 +1132,10 @@ function buildMatch(pattern) { return Resolvers.resolveNull(pattern); } + if (Checks.is_bitstring(pattern)) { + return Resolvers.resolveBitString(pattern); + } + if (Checks.is_object(pattern)) { return Resolvers.resolveObject(pattern); } @@ -981,6 +1165,8 @@ class Case { constructor(pattern, fn, guard = () => true) { this.pattern = buildMatch(pattern); + this.arity = pattern.length; + this.optionals = getOptionalValues(pattern); this.fn = fn; this.guard = guard; } @@ -994,6 +1180,8 @@ function defmatch(...cases) { return function (...args) { for (let processedCase of cases) { let result = []; + args = fillInOptionalValues(args, processedCase.arity, processedCase.optionals); + if (processedCase.pattern(args, result) && processedCase.guard.apply(this, result)) { return processedCase.fn.apply(this, result); } @@ -1003,6 +1191,42 @@ function defmatch(...cases) { }; } +function getOptionalValues(pattern) { + let optionals = []; + + for (let i = 0; i < pattern.length; i++) { + if (pattern[i] instanceof Variable && pattern[i].default_value != Symbol.for("elixirscript.no_value")) { + optionals.push([i, pattern[i].default_value]); + } + } + + return optionals; +} + +function fillInOptionalValues(args, arity, optionals) { + if (args.length === arity || optionals.length === 0) { + return args; + } + + if (args.length + optionals.length < arity) { + return args; + } + + let numberOfOptionalsToFill = arity - args.length; + let optionalsToRemove = optionals.length - numberOfOptionalsToFill; + + let optionalsToUse = optionals.slice(optionalsToRemove); + + for (let [index, value] of optionalsToUse) { + args.splice(index, 0, value); + if (args.length === arity) { + break; + } + } + + return args; +} + function match(pattern, expr, guard = () => true) { let result = []; let processedPattern = buildMatch(pattern); @@ -1028,7 +1252,7 @@ function match_no_throw(pattern, expr, guard = () => true) { var Patterns = { defmatch, match, MatchError, match_no_throw, variable, wildcard, startsWith, - capture, headTail, type, bound, Case, make_case + capture, headTail, type, bound, Case, make_case, bitStringMatch }; //https://github.com/airportyh/protomorphism @@ -1524,24 +1748,57 @@ function _for(collections, fun, filter = () => true, into = [], previousValues = let collection = collections[0][1]; if (collections.length === 1) { + if (collection instanceof BitString) { + let bsSlice = collection.slice(0, pattern.byte_size()); + let i = 1; - for (let elem of collection) { - let r = Patterns.match_no_throw(pattern, elem); - let args = previousValues.concat(r); + while (bsSlice.byte_size == pattern.byte_size()) { + let r = Patterns.match_no_throw(pattern, bsSlice); + let args = previousValues.concat(r); + + if (r && filter.apply(this, args)) { + into = into.concat([fun.apply(this, args)]); + } - if (r && filter.apply(this, args)) { - into = into.concat([fun.apply(this, args)]); + bsSlice = collection.slice(pattern.byte_size() * i, pattern.byte_size() * (i + 1)); + i++; } - } - return into; + return into; + } else { + for (let elem of collection) { + let r = Patterns.match_no_throw(pattern, elem); + let args = previousValues.concat(r); + + if (r && filter.apply(this, args)) { + into = into.concat([fun.apply(this, args)]); + } + } + + return into; + } } else { let _into = []; - for (let elem of collection) { - let r = Patterns.match_no_throw(pattern, elem); - if (r) { - _into = into.concat(this._for(collections.slice(1), fun, filter, _into, previousValues.concat(r))); + if (collection instanceof BitString) { + let bsSlice = collection.slice(0, pattern.byte_size()); + let i = 1; + + while (bsSlice.byte_size == pattern.byte_size()) { + let r = Patterns.match_no_throw(pattern, bsSlice); + if (r) { + _into = into.concat(this._for(collections.slice(1), fun, filter, _into, previousValues.concat(r))); + } + + bsSlice = collection.slice(pattern.byte_size() * i, pattern.byte_size() * (i + 1)); + i++; + } + } else { + for (let elem of collection) { + let r = Patterns.match_no_throw(pattern, elem); + if (r) { + _into = into.concat(this._for(collections.slice(1), fun, filter, _into, previousValues.concat(r))); + } } } @@ -1601,12 +1858,37 @@ function _try(do_fun, rescue_function, catch_fun, else_function, after_function) } } +function _with(...args) { + let argsToPass = []; + + for (let i = 0; i < args.length; i++) { + if (i === args.length - 1) { + return args[i].apply(null, argsToPass); + } else { + let [pattern, func] = args[i]; + + let result = func.apply(null, argsToPass); + + let patternResult = Patterns.match_no_throw(pattern, result); + + if (patternResult == null) { + return result; + } else { + argsToPass = argsToPass.concat(patternResult); + } + } + } + + return null; +} + var SpecialForms$1 = { _case, cond, map_update, _for, - _try + _try, + _with }; Functions.get_global().processes = Functions.get_global().processes || new ProcessSystem(); @@ -3438,4 +3720,4 @@ var elixir = { }; export default elixir; -//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiRWxpeGlyLmpzIiwic291cmNlcyI6WyIuLi9zcmMvZWxpeGlyc2NyaXB0L2xpYi9jb3JlL3Byb2Nlc3Nlcy9tYWlsYm94LmpzIiwiLi4vc3JjL2VsaXhpcnNjcmlwdC9saWIvY29yZS9wcm9jZXNzZXMvc3RhdGVzLmpzIiwiLi4vc3JjL2VsaXhpcnNjcmlwdC9saWIvY29yZS9wcm9jZXNzZXMvcHJvY2Vzcy5qcyIsIi4uL3NyYy9lbGl4aXJzY3JpcHQvbGliL2NvcmUvcHJpbWl0aXZlcy5qcyIsIi4uL3NyYy9lbGl4aXJzY3JpcHQvbGliL2NvcmUvcHJvY2Vzc2VzL3Byb2Nlc3Nfc3lzdGVtLmpzIiwiLi4vc3JjL2VsaXhpcnNjcmlwdC9saWIvY29yZS9iaXRfc3RyaW5nLmpzIiwiLi4vc3JjL2VsaXhpcnNjcmlwdC9saWIvY29yZS9wYXR0ZXJucy90eXBlcy5qcyIsIi4uL3NyYy9lbGl4aXJzY3JpcHQvbGliL2NvcmUvcGF0dGVybnMvY2hlY2tzLmpzIiwiLi4vc3JjL2VsaXhpcnNjcmlwdC9saWIvY29yZS9wYXR0ZXJucy9yZXNvbHZlcnMuanMiLCIuLi9zcmMvZWxpeGlyc2NyaXB0L2xpYi9jb3JlL3BhdHRlcm5zL21hdGNoLmpzIiwiLi4vc3JjL2VsaXhpcnNjcmlwdC9saWIvY29yZS9wYXR0ZXJucy9kZWZtYXRjaC5qcyIsIi4uL3NyYy9lbGl4aXJzY3JpcHQvbGliL2NvcmUvcGF0dGVybnMuanMiLCIuLi9zcmMvZWxpeGlyc2NyaXB0L2xpYi9jb3JlL3Byb3RvY29sLmpzIiwiLi4vc3JjL2VsaXhpcnNjcmlwdC9saWIvY29yZS9mdW5jdGlvbnMuanMiLCIuLi9zcmMvZWxpeGlyc2NyaXB0L2xpYi9jb3JlL3NwZWNpYWxfZm9ybXMuanMiLCIuLi9zcmMvZWxpeGlyc2NyaXB0L2xpYi9jb3JlLmpzIiwiLi4vc3JjL2VsaXhpcnNjcmlwdC9saWIvZW51bS5qcyIsIi4uL3NyYy9lbGl4aXJzY3JpcHQvbGliL3ZpcnR1YWwtZG9tLmpzIiwiLi4vc3JjL2VsaXhpcnNjcmlwdC9lbGl4aXIuanMiXSwic291cmNlc0NvbnRlbnQiOlsiXCJ1c2Ugc3RyaWN0XCI7XG5cbmNsYXNzIE1haWxib3gge1xuXG4gIGNvbnN0cnVjdG9yKCkge1xuICAgIHRoaXMubWVzc2FnZXMgPSBbXTtcbiAgfVxuXG4gIGRlbGl2ZXIobWVzc2FnZSkge1xuICAgIHRoaXMubWVzc2FnZXMucHVzaChtZXNzYWdlKTtcbiAgICByZXR1cm4gbWVzc2FnZTtcbiAgfVxuXG4gIGdldCgpIHtcbiAgICByZXR1cm4gdGhpcy5tZXNzYWdlcztcbiAgfVxuXG4gIGlzRW1wdHkoKSB7XG4gICAgcmV0dXJuIHRoaXMubWVzc2FnZXMubGVuZ3RoID09PSAwO1xuICB9XG5cbiAgcmVtb3ZlQXQoaW5kZXgpIHtcbiAgICB0aGlzLm1lc3NhZ2VzLnNwbGljZShpbmRleCwgMSk7XG4gIH1cbn1cblxuZXhwb3J0IGRlZmF1bHQgTWFpbGJveDtcbi8vIyBzb3VyY2VNYXBwaW5nVVJMPWRhdGE6YXBwbGljYXRpb24vanNvbjtiYXNlNjQsZXlKMlpYSnphVzl1SWpvekxDSnpiM1Z5WTJWeklqcGJJbXhwWWk5amIzSmxMM0J5YjJObGMzTmxjeTl0WVdsc1ltOTRMbXB6SWwwc0ltNWhiV1Z6SWpwYlhTd2liV0Z3Y0dsdVozTWlPaUpCUVVGQk96dEJRVWxCTEUxQlFVMHNUMEZCVGl4RFFVRmhPenRCUVVkWUxHZENRVUZoTzBGQlExZ3NVMEZCU3l4UlFVRk1MRWRCUVdkQ0xFVkJRV2hDTEVOQlJGYzdSMEZCWWpzN1FVRkpRU3hWUVVGUkxFOUJRVklzUlVGQmNVSTdRVUZEYmtJc1UwRkJTeXhSUVVGTUxFTkJRV01zU1VGQlpDeERRVUZ0UWl4UFFVRnVRaXhGUVVSdFFqdEJRVVZ1UWl4WFFVRlBMRTlCUVZBc1EwRkdiVUk3UjBGQmNrSTdPMEZCUzBFc1VVRkJTenRCUVVOSUxGZEJRVThzUzBGQlN5eFJRVUZNTEVOQlJFbzdSMEZCVERzN1FVRkpRU3haUVVGVE8wRkJRMUFzVjBGQlR5eExRVUZMTEZGQlFVd3NRMEZCWXl4TlFVRmtMRXRCUVhsQ0xFTkJRWHBDTEVOQlJFRTdSMEZCVkRzN1FVRkpRU3hYUVVGVExFdEJRVlFzUlVGQlpUdEJRVU5pTEZOQlFVc3NVVUZCVEN4RFFVRmpMRTFCUVdRc1EwRkJjVUlzUzBGQmNrSXNSVUZCTkVJc1EwRkJOVUlzUlVGRVlUdEhRVUZtTzBOQmNFSkdPenRCUVhsQ1FTeGxRVUZsTEU5QlFXWWlMQ0ptYVd4bElqb2liR2xpTDJOdmNtVXZjSEp2WTJWemMyVnpMMjFoYVd4aWIzZ3Vhbk1pTENKemIzVnlZMlZ6UTI5dWRHVnVkQ0k2V3lKY0luVnpaU0J6ZEhKcFkzUmNJanRjYmx4dUx5b2dRR1pzYjNjZ0tpOWNibHh1WTJ4aGMzTWdUV0ZwYkdKdmVIdGNiaUFnYldWemMyRm5aWE02SUVGeWNtRjVQR0Z1ZVQ1Y2JseHVJQ0JqYjI1emRISjFZM1J2Y2lncGUxeHVJQ0FnSUhSb2FYTXViV1Z6YzJGblpYTWdQU0JiWFR0Y2JpQWdmVnh1WEc0Z0lHUmxiR2wyWlhJb2JXVnpjMkZuWlRvZ1lXNTVLWHRjYmlBZ0lDQjBhR2x6TG0xbGMzTmhaMlZ6TG5CMWMyZ29iV1Z6YzJGblpTazdYRzRnSUNBZ2NtVjBkWEp1SUcxbGMzTmhaMlU3WEc0Z0lIMWNibHh1SUNCblpYUW9LWHRjYmlBZ0lDQnlaWFIxY200Z2RHaHBjeTV0WlhOellXZGxjenRjYmlBZ2ZWeHVYRzRnSUdselJXMXdkSGtvS1h0Y2JpQWdJQ0J5WlhSMWNtNGdkR2hwY3k1dFpYTnpZV2RsY3k1c1pXNW5kR2dnUFQwOUlEQTdYRzRnSUgxY2JseHVJQ0J5WlcxdmRtVkJkQ2hwYm1SbGVDbDdYRzRnSUNBZ2RHaHBjeTV0WlhOellXZGxjeTV6Y0d4cFkyVW9hVzVrWlhnc0lERXBPMXh1SUNCOVhHNTlYRzVjYm1WNGNHOXlkQ0JrWldaaGRXeDBJRTFoYVd4aWIzZzdJbDBzSW5OdmRYSmpaVkp2YjNRaU9pSXZjMjkxY21ObEx5SjlcbiIsImV4cG9ydCBkZWZhdWx0IHtcbiAgTk9STUFMOiBTeW1ib2wuZm9yKFwibm9ybWFsXCIpLFxuICBLSUxMOiBTeW1ib2wuZm9yKFwia2lsbFwiKSxcbiAgU1VTUEVORDogU3ltYm9sLmZvcihcInN1c3BlbmRcIiksXG4gIENPTlRJTlVFOiBTeW1ib2wuZm9yKFwiY29udGludWVcIiksXG4gIFJFQ0VJVkU6IFN5bWJvbC5mb3IoXCJyZWNlaXZlXCIpLFxuICBTRU5EOiBTeW1ib2wuZm9yKFwic2VuZFwiKSxcbiAgU0xFRVBJTkc6IFN5bWJvbC5mb3IoXCJzbGVlcGluZ1wiKSxcbiAgUlVOTklORzogU3ltYm9sLmZvcihcInJ1bm5pbmdcIiksXG4gIFNVU1BFTkRFRDogU3ltYm9sLmZvcihcInN1c3BlbmRlZFwiKSxcbiAgU1RPUFBFRDogU3ltYm9sLmZvcihcInN0b3BwZWRcIiksXG4gIFNMRUVQOiBTeW1ib2wuZm9yKFwic2xlZXBcIiksXG4gIEVYSVQ6IFN5bWJvbC5mb3IoXCJleGl0XCIpLFxuICBOT01BVENIOiBTeW1ib2wuZm9yKFwibm9fbWF0Y2hcIilcbn07XG4vLyMgc291cmNlTWFwcGluZ1VSTD1kYXRhOmFwcGxpY2F0aW9uL2pzb247YmFzZTY0LGV5SjJaWEp6YVc5dUlqb3pMQ0p6YjNWeVkyVnpJanBiSW14cFlpOWpiM0psTDNCeWIyTmxjM05sY3k5emRHRjBaWE11YW5NaVhTd2libUZ0WlhNaU9sdGRMQ0p0WVhCd2FXNW5jeUk2SWtGQlFVRXNaVUZCWlR0QlFVTmlMRlZCUVZFc1QwRkJUeXhIUVVGUUxFTkJRVmNzVVVGQldDeERRVUZTTzBGQlEwRXNVVUZCVFN4UFFVRlBMRWRCUVZBc1EwRkJWeXhOUVVGWUxFTkJRVTQ3UVVGRFFTeFhRVUZUTEU5QlFVOHNSMEZCVUN4RFFVRlhMRk5CUVZnc1EwRkJWRHRCUVVOQkxGbEJRVlVzVDBGQlR5eEhRVUZRTEVOQlFWY3NWVUZCV0N4RFFVRldPMEZCUTBFc1YwRkJVeXhQUVVGUExFZEJRVkFzUTBGQlZ5eFRRVUZZTEVOQlFWUTdRVUZEUVN4UlFVRk5MRTlCUVU4c1IwRkJVQ3hEUVVGWExFMUJRVmdzUTBGQlRqdEJRVU5CTEZsQlFWVXNUMEZCVHl4SFFVRlFMRU5CUVZjc1ZVRkJXQ3hEUVVGV08wRkJRMEVzVjBGQlV5eFBRVUZQTEVkQlFWQXNRMEZCVnl4VFFVRllMRU5CUVZRN1FVRkRRU3hoUVVGWExFOUJRVThzUjBGQlVDeERRVUZYTEZkQlFWZ3NRMEZCV0R0QlFVTkJMRmRCUVZNc1QwRkJUeXhIUVVGUUxFTkJRVmNzVTBGQldDeERRVUZVTzBGQlEwRXNVMEZCVHl4UFFVRlBMRWRCUVZBc1EwRkJWeXhQUVVGWUxFTkJRVkE3UVVGRFFTeFJRVUZOTEU5QlFVOHNSMEZCVUN4RFFVRlhMRTFCUVZnc1EwRkJUanRCUVVOQkxGZEJRVk1zVDBGQlR5eEhRVUZRTEVOQlFWY3NWVUZCV0N4RFFVRlVPME5CWWtZaUxDSm1hV3hsSWpvaWJHbGlMMk52Y21VdmNISnZZMlZ6YzJWekwzTjBZWFJsY3k1cWN5SXNJbk52ZFhKalpYTkRiMjUwWlc1MElqcGJJbVY0Y0c5eWRDQmtaV1poZFd4MElIdGNiaUFnVGs5U1RVRk1PaUJUZVcxaWIyd3VabTl5S0Z3aWJtOXliV0ZzWENJcExGeHVJQ0JMU1V4TU9pQlRlVzFpYjJ3dVptOXlLRndpYTJsc2JGd2lLU3hjYmlBZ1UxVlRVRVZPUkRvZ1UzbHRZbTlzTG1admNpaGNJbk4xYzNCbGJtUmNJaWtzWEc0Z0lFTlBUbFJKVGxWRk9pQlRlVzFpYjJ3dVptOXlLRndpWTI5dWRHbHVkV1ZjSWlrc1hHNGdJRkpGUTBWSlZrVTZJRk41YldKdmJDNW1iM0lvWENKeVpXTmxhWFpsWENJcExGeHVJQ0JUUlU1RU9pQlRlVzFpYjJ3dVptOXlLRndpYzJWdVpGd2lLU3hjYmlBZ1UweEZSVkJKVGtjNklGTjViV0p2YkM1bWIzSW9YQ0p6YkdWbGNHbHVaMXdpS1N4Y2JpQWdVbFZPVGtsT1J6b2dVM2x0WW05c0xtWnZjaWhjSW5KMWJtNXBibWRjSWlrc1hHNGdJRk5WVTFCRlRrUkZSRG9nVTNsdFltOXNMbVp2Y2loY0luTjFjM0JsYm1SbFpGd2lLU3hjYmlBZ1UxUlBVRkJGUkRvZ1UzbHRZbTlzTG1admNpaGNJbk4wYjNCd1pXUmNJaWtzWEc0Z0lGTk1SVVZRT2lCVGVXMWliMnd1Wm05eUtGd2ljMnhsWlhCY0lpa3NYRzRnSUVWWVNWUTZJRk41YldKdmJDNW1iM0lvWENKbGVHbDBYQ0lwTEZ4dUlDQk9UMDFCVkVOSU9pQlRlVzFpYjJ3dVptOXlLRndpYm05ZmJXRjBZMmhjSWlsY2JuMGlYU3dpYzI5MWNtTmxVbTl2ZENJNklpOXpiM1Z5WTJVdkluMD1cbiIsIlwidXNlIHN0cmljdFwiO1xuXG5pbXBvcnQgTWFpbGJveCBmcm9tIFwiLi9tYWlsYm94XCI7XG5pbXBvcnQgU3RhdGVzIGZyb20gXCIuL3N0YXRlc1wiO1xuXG5jbGFzcyBQcm9jZXNzIHtcblxuICBjb25zdHJ1Y3RvcihwaWQsIG1haWxib3gpIHtcbiAgICB0aGlzLnBpZCA9IHBpZDtcbiAgICB0aGlzLm1haWxib3ggPSBtYWlsYm94O1xuICAgIHRoaXMuc3RhdHVzID0gU3RhdGVzLlNUT1BQRUQ7XG4gICAgdGhpcy5kaWN0ID0ge307XG4gIH1cbn1cblxuZXhwb3J0IGRlZmF1bHQgUHJvY2Vzcztcbi8vIyBzb3VyY2VNYXBwaW5nVVJMPWRhdGE6YXBwbGljYXRpb24vanNvbjtiYXNlNjQsZXlKMlpYSnphVzl1SWpvekxDSnpiM1Z5WTJWeklqcGJJbXhwWWk5amIzSmxMM0J5YjJObGMzTmxjeTl3Y205alpYTnpMbXB6SWwwc0ltNWhiV1Z6SWpwYlhTd2liV0Z3Y0dsdVozTWlPaUpCUVVGQk96dEJRVWRCTEU5QlFVOHNUMEZCVUN4TlFVRnZRaXhYUVVGd1FqdEJRVU5CTEU5QlFVOHNUVUZCVUN4TlFVRnRRaXhWUVVGdVFqczdRVUZGUVN4TlFVRk5MRTlCUVU0c1EwRkJZenM3UVVGTFdpeGpRVUZaTEVkQlFWb3NSVUZCZVVJc1QwRkJla0lzUlVGQk1FTTdRVUZEZUVNc1UwRkJTeXhIUVVGTUxFZEJRVmNzUjBGQldDeERRVVIzUXp0QlFVVjRReXhUUVVGTExFOUJRVXdzUjBGQlpTeFBRVUZtTEVOQlJuZERPMEZCUjNoRExGTkJRVXNzVFVGQlRDeEhRVUZqTEU5QlFVOHNUMEZCVUN4RFFVZ3dRanRCUVVsNFF5eFRRVUZMTEVsQlFVd3NSMEZCV1N4RlFVRmFMRU5CU25kRE8wZEJRVEZETzBOQlRFWTdPMEZCWVVFc1pVRkJaU3hQUVVGbUlpd2labWxzWlNJNklteHBZaTlqYjNKbEwzQnliMk5sYzNObGN5OXdjbTlqWlhOekxtcHpJaXdpYzI5MWNtTmxjME52Ym5SbGJuUWlPbHNpWENKMWMyVWdjM1J5YVdOMFhDSTdYRzVjYmk4cUlFQm1iRzkzSUNvdlhHNXBiWEJ2Y25RZ1RXRnBiR0p2ZUNCbWNtOXRJRndpTGk5dFlXbHNZbTk0WENJN1hHNXBiWEJ2Y25RZ1UzUmhkR1Z6SUdaeWIyMGdYQ0l1TDNOMFlYUmxjMXdpTzF4dVhHNWpiR0Z6Y3lCUWNtOWpaWE56SUh0Y2JpQWdjR2xrT2lCT2RXMWlaWEk3WEc0Z0lHMWhhV3hpYjNnNklFMWhhV3hpYjNnN1hHNGdJR1JwWTNRNklFOWlhbVZqZER0Y2JseHVJQ0JqYjI1emRISjFZM1J2Y2lod2FXUTZJRTUxYldKbGNpd2diV0ZwYkdKdmVEb2dUV0ZwYkdKdmVDbDdYRzRnSUNBZ2RHaHBjeTV3YVdRZ1BTQndhV1E3WEc0Z0lDQWdkR2hwY3k1dFlXbHNZbTk0SUQwZ2JXRnBiR0p2ZUR0Y2JpQWdJQ0IwYUdsekxuTjBZWFIxY3lBOUlGTjBZWFJsY3k1VFZFOVFVRVZFTzF4dUlDQWdJSFJvYVhNdVpHbGpkQ0E5SUh0OU8xeHVJQ0I5WEc1OVhHNWNibVY0Y0c5eWRDQmtaV1poZFd4MElGQnliMk5sYzNNN1hHNGlYU3dpYzI5MWNtTmxVbTl2ZENJNklpOXpiM1Z5WTJVdkluMD1cbiIsImNsYXNzIFR1cGxlIHtcblxuICBjb25zdHJ1Y3RvciguLi5hcmdzKSB7XG4gICAgdGhpcy52YWx1ZXMgPSBPYmplY3QuZnJlZXplKGFyZ3MpO1xuICAgIHRoaXMubGVuZ3RoID0gdGhpcy52YWx1ZXMubGVuZ3RoO1xuICB9XG5cbiAgZ2V0KGluZGV4KSB7XG4gICAgcmV0dXJuIHRoaXMudmFsdWVzW2luZGV4XTtcbiAgfVxuXG4gIGNvdW50KCkge1xuICAgIHJldHVybiB0aGlzLnZhbHVlcy5sZW5ndGg7XG4gIH1cblxuICBbU3ltYm9sLml0ZXJhdG9yXSgpIHtcbiAgICByZXR1cm4gdGhpcy52YWx1ZXNbU3ltYm9sLml0ZXJhdG9yXSgpO1xuICB9XG5cbiAgdG9TdHJpbmcoKSB7XG4gICAgdmFyIGksXG4gICAgICAgIHMgPSBcIlwiO1xuICAgIGZvciAoaSA9IDA7IGkgPCB0aGlzLnZhbHVlcy5sZW5ndGg7IGkrKykge1xuICAgICAgaWYgKHMgIT09IFwiXCIpIHtcbiAgICAgICAgcyArPSBcIiwgXCI7XG4gICAgICB9XG4gICAgICBzICs9IHRoaXMudmFsdWVzW2ldLnRvU3RyaW5nKCk7XG4gICAgfVxuXG4gICAgcmV0dXJuIFwie1wiICsgcyArIFwifVwiO1xuICB9XG5cbiAgcHV0X2VsZW0oaW5kZXgsIGVsZW0pIHtcbiAgICBpZiAoaW5kZXggPT09IHRoaXMubGVuZ3RoKSB7XG4gICAgICBsZXQgbmV3X3ZhbHVlcyA9IHRoaXMudmFsdWVzLmNvbmNhdChbZWxlbV0pO1xuICAgICAgcmV0dXJuIG5ldyBUdXBsZSguLi5uZXdfdmFsdWVzKTtcbiAgICB9XG5cbiAgICBsZXQgbmV3X3ZhbHVlcyA9IHRoaXMudmFsdWVzLmNvbmNhdChbXSk7XG4gICAgbmV3X3ZhbHVlcy5zcGxpY2UoaW5kZXgsIDAsIGVsZW0pO1xuICAgIHJldHVybiBuZXcgVHVwbGUoLi4ubmV3X3ZhbHVlcyk7XG4gIH1cblxuICByZW1vdmVfZWxlbShpbmRleCkge1xuICAgIGxldCBuZXdfdmFsdWVzID0gdGhpcy52YWx1ZXMuY29uY2F0KFtdKTtcbiAgICBuZXdfdmFsdWVzLnNwbGljZShpbmRleCwgMSk7XG4gICAgcmV0dXJuIG5ldyBUdXBsZSguLi5uZXdfdmFsdWVzKTtcbiAgfVxuXG59XG5cbmxldCBwcm9jZXNzX2NvdW50ZXIgPSAtMTtcblxuY2xhc3MgUElEIHtcbiAgY29uc3RydWN0b3IoKSB7XG4gICAgcHJvY2Vzc19jb3VudGVyID0gcHJvY2Vzc19jb3VudGVyICsgMTtcbiAgICB0aGlzLmlkID0gcHJvY2Vzc19jb3VudGVyO1xuICB9XG5cbiAgdG9TdHJpbmcoKSB7XG4gICAgcmV0dXJuIFwiUElEIzwwLlwiICsgdGhpcy5pZCArIFwiLjA+XCI7XG4gIH1cbn1cblxuY2xhc3MgSW50ZWdlciB7fVxuY2xhc3MgRmxvYXQge31cblxuZXhwb3J0IHsgUElELCBUdXBsZSwgSW50ZWdlciwgRmxvYXQgfTtcbi8vIyBzb3VyY2VNYXBwaW5nVVJMPWRhdGE6YXBwbGljYXRpb24vanNvbjtiYXNlNjQsZXlKMlpYSnphVzl1SWpvekxDSnpiM1Z5WTJWeklqcGJJbXhwWWk5amIzSmxMM0J5YVcxcGRHbDJaWE11YW5NaVhTd2libUZ0WlhNaU9sdGRMQ0p0WVhCd2FXNW5jeUk2SWtGQlFVRXNUVUZCVFN4TFFVRk9MRU5CUVZrN08wRkJSVllzWTBGQldTeEhRVUZITEVsQlFVZ3NSVUZCVVR0QlFVTnNRaXhUUVVGTExFMUJRVXdzUjBGQll5eFBRVUZQTEUxQlFWQXNRMEZCWXl4SlFVRmtMRU5CUVdRc1EwRkVhMEk3UVVGRmJFSXNVMEZCU3l4TlFVRk1MRWRCUVdNc1MwRkJTeXhOUVVGTUxFTkJRVmtzVFVGQldpeERRVVpKTzBkQlFYQkNPenRCUVV0QkxFMUJRVWtzUzBGQlNpeEZRVUZYTzBGQlExUXNWMEZCVHl4TFFVRkxMRTFCUVV3c1EwRkJXU3hMUVVGYUxFTkJRVkFzUTBGRVV6dEhRVUZZT3p0QlFVbEJMRlZCUVZFN1FVRkRUaXhYUVVGUExFdEJRVXNzVFVGQlRDeERRVUZaTEUxQlFWb3NRMEZFUkR0SFFVRlNPenRCUVVsQkxFZEJRVU1zVDBGQlR5eFJRVUZRTEVsQlFXMUNPMEZCUTJ4Q0xGZEJRVThzUzBGQlN5eE5RVUZNTEVOQlFWa3NUMEZCVHl4UlFVRlFMRU5CUVZvc1JVRkJVQ3hEUVVSclFqdEhRVUZ3UWpzN1FVRkpRU3hoUVVGWE8wRkJRMVFzVVVGQlNTeERRVUZLTzFGQlFVOHNTVUZCU1N4RlFVRktMRU5CUkVVN1FVRkZWQ3hUUVVGTExFbEJRVWtzUTBGQlNpeEZRVUZQTEVsQlFVa3NTMEZCU3l4TlFVRk1MRU5CUVZrc1RVRkJXaXhGUVVGdlFpeEhRVUZ3UXl4RlFVRjVRenRCUVVOMlF5eFZRVUZKTEUxQlFVMHNSVUZCVGl4RlFVRlZPMEZCUTFvc1lVRkJTeXhKUVVGTUxFTkJSRms3VDBGQlpEdEJRVWRCTEZkQlFVc3NTMEZCU3l4TlFVRk1MRU5CUVZrc1EwRkJXaXhGUVVGbExGRkJRV1lzUlVGQlRDeERRVXAxUXp0TFFVRjZRenM3UVVGUFFTeFhRVUZQTEUxQlFVMHNRMEZCVGl4SFFVRlZMRWRCUVZZc1EwRlVSVHRIUVVGWU96dEJRVmxCTEZkQlFWTXNTMEZCVkN4RlFVRm5RaXhKUVVGb1FpeEZRVUZ4UWp0QlFVTnVRaXhSUVVGSExGVkJRVlVzUzBGQlN5eE5RVUZNTEVWQlFWazdRVUZEZGtJc1ZVRkJTU3hoUVVGaExFdEJRVXNzVFVGQlRDeERRVUZaTEUxQlFWb3NRMEZCYlVJc1EwRkJReXhKUVVGRUxFTkJRVzVDTEVOQlFXSXNRMEZFYlVJN1FVRkZka0lzWVVGQlR5eEpRVUZKTEV0QlFVb3NRMEZCVlN4SFFVRkhMRlZCUVVnc1EwRkJha0lzUTBGR2RVSTdTMEZCZWtJN08wRkJTMEVzVVVGQlNTeGhRVUZoTEV0QlFVc3NUVUZCVEN4RFFVRlpMRTFCUVZvc1EwRkJiVUlzUlVGQmJrSXNRMEZCWWl4RFFVNWxPMEZCVDI1Q0xHVkJRVmNzVFVGQldDeERRVUZyUWl4TFFVRnNRaXhGUVVGNVFpeERRVUY2UWl4RlFVRTBRaXhKUVVFMVFpeEZRVkJ0UWp0QlFWRnVRaXhYUVVGUExFbEJRVWtzUzBGQlNpeERRVUZWTEVkQlFVY3NWVUZCU0N4RFFVRnFRaXhEUVZKdFFqdEhRVUZ5UWpzN1FVRlhRU3hqUVVGWkxFdEJRVm9zUlVGQmEwSTdRVUZEYUVJc1VVRkJTU3hoUVVGaExFdEJRVXNzVFVGQlRDeERRVUZaTEUxQlFWb3NRMEZCYlVJc1JVRkJia0lzUTBGQllpeERRVVJaTzBGQlJXaENMR1ZCUVZjc1RVRkJXQ3hEUVVGclFpeExRVUZzUWl4RlFVRjVRaXhEUVVGNlFpeEZRVVpuUWp0QlFVZG9RaXhYUVVGUExFbEJRVWtzUzBGQlNpeERRVUZWTEVkQlFVY3NWVUZCU0N4RFFVRnFRaXhEUVVoblFqdEhRVUZzUWpzN1EwRXhRMFk3TzBGQmJVUkJMRWxCUVVrc2EwSkJRV3RDTEVOQlFVTXNRMEZCUkRzN1FVRkZkRUlzVFVGQlRTeEhRVUZPTEVOQlFWVTdRVUZEVWl4blFrRkJZVHRCUVVOWUxITkNRVUZyUWl4clFrRkJhMElzUTBGQmJFSXNRMEZFVUR0QlFVVllMRk5CUVVzc1JVRkJUQ3hIUVVGVkxHVkJRVllzUTBGR1Z6dEhRVUZpT3p0QlFVdEJMR0ZCUVZVN1FVRkRVaXhYUVVGUExGbEJRVmtzUzBGQlN5eEZRVUZNTEVkQlFWVXNTMEZCZEVJc1EwRkVRenRIUVVGV08wTkJUa1k3TzBGQlYwRXNUVUZCVFN4UFFVRk9MRU5CUVdNc1JVRkJaRHRCUVVOQkxFMUJRVTBzUzBGQlRpeERRVUZaTEVWQlFWbzdPMEZCUlVFc1UwRkJVeXhIUVVGVUxFVkJRV01zUzBGQlpDeEZRVUZ4UWl4UFFVRnlRaXhGUVVFNFFpeExRVUU1UWlJc0ltWnBiR1VpT2lKc2FXSXZZMjl5WlM5d2NtbHRhWFJwZG1WekxtcHpJaXdpYzI5MWNtTmxjME52Ym5SbGJuUWlPbHNpWTJ4aGMzTWdWSFZ3YkdVZ2UxeHVYRzRnSUdOdmJuTjBjblZqZEc5eUtDNHVMbUZ5WjNNcGUxeHVJQ0FnSUhSb2FYTXVkbUZzZFdWeklEMGdUMkpxWldOMExtWnlaV1Y2WlNoaGNtZHpLVHRjYmlBZ0lDQjBhR2x6TG14bGJtZDBhQ0E5SUhSb2FYTXVkbUZzZFdWekxteGxibWQwYUR0Y2JpQWdmVnh1WEc0Z0lHZGxkQ2hwYm1SbGVDa2dlMXh1SUNBZ0lISmxkSFZ5YmlCMGFHbHpMblpoYkhWbGMxdHBibVJsZUYwN1hHNGdJSDFjYmx4dUlDQmpiM1Z1ZENncElIdGNiaUFnSUNCeVpYUjFjbTRnZEdocGN5NTJZV3gxWlhNdWJHVnVaM1JvTzF4dUlDQjlYRzVjYmlBZ1cxTjViV0p2YkM1cGRHVnlZWFJ2Y2wwb0tTQjdYRzRnSUNBZ2NtVjBkWEp1SUhSb2FYTXVkbUZzZFdWelcxTjViV0p2YkM1cGRHVnlZWFJ2Y2wwb0tUdGNiaUFnZlZ4dVhHNGdJSFJ2VTNSeWFXNW5LQ2tnZTF4dUlDQWdJSFpoY2lCcExDQnpJRDBnWENKY0lqdGNiaUFnSUNCbWIzSWdLR2tnUFNBd095QnBJRHdnZEdocGN5NTJZV3gxWlhNdWJHVnVaM1JvT3lCcEt5c3BJSHRjYmlBZ0lDQWdJR2xtSUNoeklDRTlQU0JjSWx3aUtTQjdYRzRnSUNBZ0lDQWdJSE1nS3owZ1hDSXNJRndpTzF4dUlDQWdJQ0FnZlZ4dUlDQWdJQ0FnY3lBclBTQjBhR2x6TG5aaGJIVmxjMXRwWFM1MGIxTjBjbWx1WnlncE8xeHVJQ0FnSUgxY2JseHVJQ0FnSUhKbGRIVnliaUJjSW50Y0lpQXJJSE1nS3lCY0luMWNJanRjYmlBZ2ZWeHVYRzRnSUhCMWRGOWxiR1Z0S0dsdVpHVjRMQ0JsYkdWdEtYdGNiaUFnSUNCcFppaHBibVJsZUNBOVBUMGdkR2hwY3k1c1pXNW5kR2dwZTF4dUlDQWdJQ0FnYkdWMElHNWxkMTkyWVd4MVpYTWdQU0IwYUdsekxuWmhiSFZsY3k1amIyNWpZWFFvVzJWc1pXMWRLVHRjYmlBZ0lDQWdJSEpsZEhWeWJpQnVaWGNnVkhWd2JHVW9MaTR1Ym1WM1gzWmhiSFZsY3lrN1hHNGdJQ0FnZlZ4dVhHNGdJQ0FnYkdWMElHNWxkMTkyWVd4MVpYTWdQU0IwYUdsekxuWmhiSFZsY3k1amIyNWpZWFFvVzEwcE8xeHVJQ0FnSUc1bGQxOTJZV3gxWlhNdWMzQnNhV05sS0dsdVpHVjRMQ0F3TENCbGJHVnRLVHRjYmlBZ0lDQnlaWFIxY200Z2JtVjNJRlIxY0d4bEtDNHVMbTVsZDE5MllXeDFaWE1wTzF4dUlDQjlYRzVjYmlBZ2NtVnRiM1psWDJWc1pXMG9hVzVrWlhncGUxeHVJQ0FnSUd4bGRDQnVaWGRmZG1Gc2RXVnpJRDBnZEdocGN5NTJZV3gxWlhNdVkyOXVZMkYwS0Z0ZEtUdGNiaUFnSUNCdVpYZGZkbUZzZFdWekxuTndiR2xqWlNocGJtUmxlQ3dnTVNrN1hHNGdJQ0FnY21WMGRYSnVJRzVsZHlCVWRYQnNaU2d1TGk1dVpYZGZkbUZzZFdWektUdGNiaUFnZlZ4dVhHNTlYRzVjYmx4dWJHVjBJSEJ5YjJObGMzTmZZMjkxYm5SbGNpQTlJQzB4TzF4dVhHNWpiR0Z6Y3lCUVNVUWdlMXh1SUNCamIyNXpkSEoxWTNSdmNpZ3BlMXh1SUNBZ0lIQnliMk5sYzNOZlkyOTFiblJsY2lBOUlIQnliMk5sYzNOZlkyOTFiblJsY2lBcklERTdYRzRnSUNBZ2RHaHBjeTVwWkNBOUlIQnliMk5sYzNOZlkyOTFiblJsY2p0Y2JpQWdmVnh1WEc0Z0lIUnZVM1J5YVc1bktDbDdYRzRnSUNBZ2NtVjBkWEp1SUZ3aVVFbEVJend3TGx3aUlDc2dkR2hwY3k1cFpDQXJJRndpTGpBK1hDSTdYRzRnSUgxY2JuMWNibHh1WTJ4aGMzTWdTVzUwWldkbGNpQjdmVnh1WTJ4aGMzTWdSbXh2WVhRZ2UzMWNibHh1Wlhod2IzSjBJSHNnVUVsRUxDQlVkWEJzWlN3Z1NXNTBaV2RsY2l3Z1JteHZZWFFnZlR0Y2JpSmRMQ0p6YjNWeVkyVlNiMjkwSWpvaUwzTnZkWEpqWlM4aWZRPT1cbiIsIlxuXCJ1c2Ugc3RyaWN0XCI7XG5cbmltcG9ydCBNYWlsYm94IGZyb20gXCIuL21haWxib3hcIjtcbmltcG9ydCBQcm9jZXNzIGZyb20gXCIuL3Byb2Nlc3NcIjtcbmltcG9ydCBTdGF0ZXMgZnJvbSBcIi4vc3RhdGVzXCI7XG5pbXBvcnQgKiBhcyBQcmltaXRpdmVzIGZyb20gXCIuLi9wcmltaXRpdmVzXCI7XG5cbmNsYXNzIFByb2Nlc3NTeXN0ZW0ge1xuXG4gIGNvbnN0cnVjdG9yKCkge1xuICAgIHRoaXMucGlkcyA9IG5ldyBNYXAoKTtcbiAgICB0aGlzLm1haWxib3hlcyA9IG5ldyBNYXAoKTtcbiAgICB0aGlzLm5hbWVzID0gbmV3IE1hcCgpO1xuICAgIHRoaXMubGlua3MgPSBuZXcgTWFwKCk7XG5cbiAgICB0aGlzLmN1cnJlbnRfcHJvY2VzcyA9IG51bGw7XG4gICAgdGhpcy5zdXNwZW5kZWQgPSBuZXcgTWFwKCk7XG5cbiAgICB0aGlzLm1haW5fcHJvY2Vzc19waWQgPSB0aGlzLnNwYXduKCk7XG4gICAgdGhpcy5zZXRfY3VycmVudCh0aGlzLm1haW5fcHJvY2Vzc19waWQpO1xuICB9XG5cbiAgc3Bhd24oKSB7XG4gICAgcmV0dXJuIHRoaXMuYWRkX3Byb2MoZmFsc2UpLnBpZDtcbiAgfVxuXG4gIHNwYXduX2xpbmsoKSB7XG4gICAgcmV0dXJuIHRoaXMuYWRkX3Byb2ModHJ1ZSkucGlkO1xuICB9XG5cbiAgbGluayhwaWQpIHtcbiAgICB0aGlzLmxpbmtzLmdldCh0aGlzLnBpZCgpKS5hZGQocGlkKTtcbiAgICB0aGlzLmxpbmtzLmdldChwaWQpLmFkZCh0aGlzLnBpZCgpKTtcbiAgfVxuXG4gIHVubGluayhwaWQpIHtcbiAgICB0aGlzLmxpbmtzLmdldCh0aGlzLnBpZCgpKS5kZWxldGUocGlkKTtcbiAgICB0aGlzLmxpbmtzLmdldChwaWQpLmRlbGV0ZSh0aGlzLnBpZCgpKTtcbiAgfVxuXG4gIHNldF9jdXJyZW50KGlkKSB7XG4gICAgbGV0IHBpZCA9IHRoaXMucGlkb2YoaWQpO1xuICAgIGlmIChwaWQgIT09IG51bGwpIHtcbiAgICAgIHRoaXMuY3VycmVudF9wcm9jZXNzID0gdGhpcy5waWRzLmdldChwaWQpO1xuICAgICAgdGhpcy5jdXJyZW50X3Byb2Nlc3Muc3RhdHVzID0gU3RhdGVzLlJVTk5JTkc7XG4gICAgfVxuICB9XG5cbiAgYWRkX3Byb2MobGlua2VkKSB7XG4gICAgbGV0IG5ld3BpZCA9IG5ldyBQcmltaXRpdmVzLlBJRCgpO1xuICAgIGxldCBtYWlsYm94ID0gbmV3IE1haWxib3goKTtcbiAgICBsZXQgbmV3cHJvYyA9IG5ldyBQcm9jZXNzKG5ld3BpZCwgbWFpbGJveCk7XG5cbiAgICB0aGlzLnBpZHMuc2V0KG5ld3BpZCwgbmV3cHJvYyk7XG4gICAgdGhpcy5tYWlsYm94ZXMuc2V0KG5ld3BpZCwgbWFpbGJveCk7XG4gICAgdGhpcy5saW5rcy5zZXQobmV3cGlkLCBuZXcgU2V0KCkpO1xuXG4gICAgaWYgKGxpbmtlZCkge1xuICAgICAgdGhpcy5saW5rKG5ld3BpZCk7XG4gICAgfVxuXG4gICAgcmV0dXJuIG5ld3Byb2M7XG4gIH1cblxuICByZW1vdmVfcHJvYyhwaWQpIHtcbiAgICB0aGlzLnBpZHMuZGVsZXRlKHBpZCk7XG4gICAgdGhpcy51bnJlZ2lzdGVyKHBpZCk7XG5cbiAgICBpZiAodGhpcy5saW5rcy5oYXMocGlkKSkge1xuICAgICAgZm9yIChsZXQgbGlua3BpZCBvZiB0aGlzLmxpbmtzLmdldChwaWQpKSB7XG4gICAgICAgIHRoaXMubGlua3MuZ2V0KGxpbmtwaWQpLmRlbGV0ZShwaWQpO1xuICAgICAgfVxuXG4gICAgICB0aGlzLmxpbmtzLmRlbGV0ZShwaWQpO1xuICAgIH1cbiAgfVxuXG4gIGV4aXQoaWQpIHtcbiAgICBsZXQgcGlkID0gdGhpcy5waWRvZihpZCk7XG4gICAgdGhpcy5yZW1vdmVfcHJvYyhpZCk7XG4gIH1cblxuICByZWdpc3RlcihuYW1lLCBwaWQpIHtcbiAgICBpZiAoIXRoaXMubmFtZXMuaGFzKG5hbWUpKSB7XG4gICAgICB0aGlzLm5hbWVzLnNldChuYW1lLCBwaWQpO1xuICAgICAgcmV0dXJuIG5hbWU7XG4gICAgfSBlbHNlIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcihcIk5hbWUgaXMgYWxyZWFkeSByZWdpc3RlcmVkIHRvIGFub3RoZXIgcHJvY2Vzc1wiKTtcbiAgICB9XG4gIH1cblxuICByZWdpc3RlcmVkKG5hbWUpIHtcbiAgICByZXR1cm4gdGhpcy5uYW1lcy5oYXMobmFtZSkgPyB0aGlzLm5hbWVzLmdldChuYW1lKSA6IG51bGw7XG4gIH1cblxuICB1bnJlZ2lzdGVyKHBpZCkge1xuICAgIGZvciAobGV0IG5hbWUgb2YgdGhpcy5uYW1lcy5rZXlzKCkpIHtcbiAgICAgIGlmICh0aGlzLm5hbWVzLmhhcyhuYW1lKSAmJiB0aGlzLm5hbWVzLmdldChuYW1lKSA9PT0gcGlkKSB7XG4gICAgICAgIHRoaXMubmFtZXMuZGVsZXRlKG5hbWUpO1xuICAgICAgfVxuICAgIH1cbiAgfVxuXG4gIHBpZCgpIHtcbiAgICByZXR1cm4gdGhpcy5jdXJyZW50X3Byb2Nlc3MucGlkO1xuICB9XG5cbiAgcGlkb2YoaWQpIHtcbiAgICBpZiAoaWQgaW5zdGFuY2VvZiBQcmltaXRpdmVzLlBJRCkge1xuICAgICAgcmV0dXJuIHRoaXMucGlkcy5oYXMoaWQpID8gaWQgOiBudWxsO1xuICAgIH0gZWxzZSBpZiAoaWQgaW5zdGFuY2VvZiBQcm9jZXNzKSB7XG4gICAgICByZXR1cm4gaWQucGlkO1xuICAgIH0gZWxzZSB7XG4gICAgICBsZXQgcGlkID0gdGhpcy5yZWdpc3RlcmVkKGlkKTtcbiAgICAgIGlmIChwaWQgPT09IG51bGwpIHRocm93IFwiUHJvY2VzcyBuYW1lIG5vdCByZWdpc3RlcmVkOiBcIiArIGlkICsgXCIgKFwiICsgdHlwZW9mIGlkICsgXCIpXCI7XG4gICAgICByZXR1cm4gcGlkO1xuICAgIH1cbiAgfVxuXG4gIHB1dChpZCwga2V5LCB2YWx1ZSkge1xuICAgIGxldCBwaWQgPSB0aGlzLnBpZG9mKGlkKTtcbiAgICBsZXQgcHJvY2VzcyA9IHRoaXMucGlkcy5nZXQocGlkKTtcbiAgICBwcm9jZXNzLmRpY3Rba2V5XSA9IHZhbHVlO1xuICB9XG5cbiAgZ2V0KGlkLCBrZXkpIHtcbiAgICBsZXQgcGlkID0gdGhpcy5waWRvZihpZCk7XG4gICAgbGV0IHByb2Nlc3MgPSB0aGlzLnBpZHMuZ2V0KHBpZCk7XG5cbiAgICBpZiAoa2V5ICE9IG51bGwpIHtcbiAgICAgIHJldHVybiBwcm9jZXNzLmRpY3Rba2V5XTtcbiAgICB9IGVsc2Uge1xuICAgICAgcmV0dXJuIHByb2Nlc3MuZGljdDtcbiAgICB9XG4gIH1cblxuICBnZXRfa2V5cyhpZCkge1xuICAgIGxldCBwaWQgPSB0aGlzLnBpZG9mKGlkKTtcbiAgICBsZXQgcHJvY2VzcyA9IHRoaXMucGlkcy5nZXQocGlkKTtcblxuICAgIHJldHVybiBPYmplY3Qua2V5cyhwcm9jZXNzLmRpY3QpO1xuICB9XG5cbiAgZXJhc2UoaWQsIGtleSkge1xuICAgIGxldCBwaWQgPSB0aGlzLnBpZG9mKGlkKTtcbiAgICBsZXQgcHJvY2VzcyA9IHRoaXMucGlkcy5nZXQocGlkKTtcblxuICAgIGlmIChrZXkgIT0gbnVsbCkge1xuICAgICAgZGVsZXRlIHByb2Nlc3MuZGljdFtrZXldO1xuICAgIH0gZWxzZSB7XG4gICAgICBwcm9jZXNzLmRpY3QgPSB7fTtcbiAgICB9XG4gIH1cbn1cblxuZXhwb3J0IGRlZmF1bHQgUHJvY2Vzc1N5c3RlbTtcbi8vIyBzb3VyY2VNYXBwaW5nVVJMPWRhdGE6YXBwbGljYXRpb24vanNvbjtiYXNlNjQsZXlKMlpYSnphVzl1SWpvekxDSnpiM1Z5WTJWeklqcGJJbXhwWWk5amIzSmxMM0J5YjJObGMzTmxjeTl3Y205alpYTnpYM041YzNSbGJTNXFjeUpkTENKdVlXMWxjeUk2VzEwc0ltMWhjSEJwYm1keklqb2lPMEZCUTBFN08wRkJSVUVzVDBGQlR5eFBRVUZRTEUxQlFXOUNMRmRCUVhCQ08wRkJRMEVzVDBGQlR5eFBRVUZRTEUxQlFXOUNMRmRCUVhCQ08wRkJRMEVzVDBGQlR5eE5RVUZRTEUxQlFXMUNMRlZCUVc1Q08wRkJRMEVzVDBGQlR5eExRVUZMTEZWQlFVd3NUVUZCY1VJc1pVRkJOVUk3TzBGQlJVRXNUVUZCVFN4aFFVRk9MRU5CUVc5Q096dEJRVVZzUWl4blFrRkJZVHRCUVVOWUxGTkJRVXNzU1VGQlRDeEhRVUZaTEVsQlFVa3NSMEZCU2l4RlFVRmFMRU5CUkZjN1FVRkZXQ3hUUVVGTExGTkJRVXdzUjBGQmFVSXNTVUZCU1N4SFFVRktMRVZCUVdwQ0xFTkJSbGM3UVVGSFdDeFRRVUZMTEV0QlFVd3NSMEZCWVN4SlFVRkpMRWRCUVVvc1JVRkJZaXhEUVVoWE8wRkJTVmdzVTBGQlN5eExRVUZNTEVkQlFXRXNTVUZCU1N4SFFVRktMRVZCUVdJc1EwRktWenM3UVVGTldDeFRRVUZMTEdWQlFVd3NSMEZCZFVJc1NVRkJka0lzUTBGT1Z6dEJRVTlZTEZOQlFVc3NVMEZCVEN4SFFVRnBRaXhKUVVGSkxFZEJRVW9zUlVGQmFrSXNRMEZRVnpzN1FVRlRXQ3hUUVVGTExHZENRVUZNTEVkQlFYZENMRXRCUVVzc1MwRkJUQ3hGUVVGNFFpeERRVlJYTzBGQlZWZ3NVMEZCU3l4WFFVRk1MRU5CUVdsQ0xFdEJRVXNzWjBKQlFVd3NRMEZCYWtJc1EwRldWenRIUVVGaU96dEJRV0ZCTEZWQlFVODdRVUZEVEN4WFFVRlBMRXRCUVVzc1VVRkJUQ3hEUVVGakxFdEJRV1FzUlVGQmNVSXNSMEZCY2tJc1EwRkVSanRIUVVGUU96dEJRVWxCTEdWQlFWazdRVUZEVml4WFFVRlBMRXRCUVVzc1VVRkJUQ3hEUVVGakxFbEJRV1FzUlVGQmIwSXNSMEZCY0VJc1EwRkVSenRIUVVGYU96dEJRVWxCTEU5QlFVc3NSMEZCVEN4RlFVRlRPMEZCUTFBc1UwRkJTeXhMUVVGTUxFTkJRVmNzUjBGQldDeERRVUZsTEV0QlFVc3NSMEZCVEN4RlFVRm1MRVZCUVRKQ0xFZEJRVE5DTEVOQlFTdENMRWRCUVM5Q0xFVkJSRTg3UVVGRlVDeFRRVUZMTEV0QlFVd3NRMEZCVnl4SFFVRllMRU5CUVdVc1IwRkJaaXhGUVVGdlFpeEhRVUZ3UWl4RFFVRjNRaXhMUVVGTExFZEJRVXdzUlVGQmVFSXNSVUZHVHp0SFFVRlVPenRCUVV0QkxGTkJRVThzUjBGQlVDeEZRVUZYTzBGQlExUXNVMEZCU3l4TFFVRk1MRU5CUVZjc1IwRkJXQ3hEUVVGbExFdEJRVXNzUjBGQlRDeEZRVUZtTEVWQlFUSkNMRTFCUVROQ0xFTkJRV3RETEVkQlFXeERMRVZCUkZNN1FVRkZWQ3hUUVVGTExFdEJRVXdzUTBGQlZ5eEhRVUZZTEVOQlFXVXNSMEZCWml4RlFVRnZRaXhOUVVGd1FpeERRVUV5UWl4TFFVRkxMRWRCUVV3c1JVRkJNMElzUlVGR1V6dEhRVUZZT3p0QlFVdEJMR05CUVZrc1JVRkJXaXhGUVVGbE8wRkJRMklzVVVGQlNTeE5RVUZOTEV0QlFVc3NTMEZCVEN4RFFVRlhMRVZCUVZnc1EwRkJUaXhEUVVSVE8wRkJSV0lzVVVGQlJ5eFJRVUZSTEVsQlFWSXNSVUZCWVR0QlFVTmtMRmRCUVVzc1pVRkJUQ3hIUVVGMVFpeExRVUZMTEVsQlFVd3NRMEZCVlN4SFFVRldMRU5CUVdNc1IwRkJaQ3hEUVVGMlFpeERRVVJqTzBGQlJXUXNWMEZCU3l4bFFVRk1MRU5CUVhGQ0xFMUJRWEpDTEVkQlFUaENMRTlCUVU4c1QwRkJVQ3hEUVVab1FqdExRVUZvUWp0SFFVWkdPenRCUVZGQkxGZEJRVk1zVFVGQlZDeEZRVUZuUWp0QlFVTmtMRkZCUVVrc1UwRkJVeXhKUVVGSkxGZEJRVmNzUjBGQldDeEZRVUZpTEVOQlJGVTdRVUZGWkN4UlFVRkpMRlZCUVZVc1NVRkJTU3hQUVVGS0xFVkJRVllzUTBGR1ZUdEJRVWRrTEZGQlFVa3NWVUZCVlN4SlFVRkpMRTlCUVVvc1EwRkJXU3hOUVVGYUxFVkJRVzlDTEU5QlFYQkNMRU5CUVZZc1EwRklWVHM3UVVGTFpDeFRRVUZMTEVsQlFVd3NRMEZCVlN4SFFVRldMRU5CUVdNc1RVRkJaQ3hGUVVGelFpeFBRVUYwUWl4RlFVeGpPMEZCVFdRc1UwRkJTeXhUUVVGTUxFTkJRV1VzUjBGQlppeERRVUZ0UWl4TlFVRnVRaXhGUVVFeVFpeFBRVUV6UWl4RlFVNWpPMEZCVDJRc1UwRkJTeXhMUVVGTUxFTkJRVmNzUjBGQldDeERRVUZsTEUxQlFXWXNSVUZCZFVJc1NVRkJTU3hIUVVGS0xFVkJRWFpDTEVWQlVHTTdPMEZCVTJRc1VVRkJSeXhOUVVGSUxFVkJRVlU3UVVGRFVpeFhRVUZMTEVsQlFVd3NRMEZCVlN4TlFVRldMRVZCUkZFN1MwRkJWanM3UVVGSlFTeFhRVUZQTEU5QlFWQXNRMEZpWXp0SFFVRm9RanM3UVVGblFrRXNZMEZCV1N4SFFVRmFMRVZCUVdkQ08wRkJRMlFzVTBGQlN5eEpRVUZNTEVOQlFWVXNUVUZCVml4RFFVRnBRaXhIUVVGcVFpeEZRVVJqTzBGQlJXUXNVMEZCU3l4VlFVRk1MRU5CUVdkQ0xFZEJRV2hDTEVWQlJtTTdPMEZCU1dRc1VVRkJSeXhMUVVGTExFdEJRVXdzUTBGQlZ5eEhRVUZZTEVOQlFXVXNSMEZCWml4RFFVRklMRVZCUVhWQ08wRkJRM0pDTEZkQlFVc3NTVUZCU1N4UFFVRktMRWxCUVdVc1MwRkJTeXhMUVVGTUxFTkJRVmNzUjBGQldDeERRVUZsTEVkQlFXWXNRMEZCY0VJc1JVRkJlVU03UVVGRGRrTXNZVUZCU3l4TFFVRk1MRU5CUVZjc1IwRkJXQ3hEUVVGbExFOUJRV1lzUlVGQmQwSXNUVUZCZUVJc1EwRkJLMElzUjBGQkwwSXNSVUZFZFVNN1QwRkJla003TzBGQlNVRXNWMEZCU3l4TFFVRk1MRU5CUVZjc1RVRkJXQ3hEUVVGclFpeEhRVUZzUWl4RlFVeHhRanRMUVVGMlFqdEhRVXBHT3p0QlFXRkJMRTlCUVVzc1JVRkJUQ3hGUVVGUk8wRkJRMDRzVVVGQlNTeE5RVUZOTEV0QlFVc3NTMEZCVEN4RFFVRlhMRVZCUVZnc1EwRkJUaXhEUVVSRk8wRkJSVTRzVTBGQlN5eFhRVUZNTEVOQlFXbENMRVZCUVdwQ0xFVkJSazA3UjBGQlVqczdRVUZMUVN4WFFVRlRMRWxCUVZRc1JVRkJaU3hIUVVGbUxFVkJRVzFDTzBGQlEycENMRkZCUVVjc1EwRkJReXhMUVVGTExFdEJRVXdzUTBGQlZ5eEhRVUZZTEVOQlFXVXNTVUZCWml4RFFVRkVMRVZCUVhOQ08wRkJRM1pDTEZkQlFVc3NTMEZCVEN4RFFVRlhMRWRCUVZnc1EwRkJaU3hKUVVGbUxFVkJRWEZDTEVkQlFYSkNMRVZCUkhWQ08wRkJSWFpDTEdGQlFVOHNTVUZCVUN4RFFVWjFRanRMUVVGNlFpeE5RVWRMTzBGQlEwZ3NXVUZCVFN4SlFVRkpMRXRCUVVvc1EwRkJWU3dyUTBGQlZpeERRVUZPTEVOQlJFYzdTMEZJVER0SFFVUkdPenRCUVZOQkxHRkJRVmNzU1VGQldDeEZRVUZuUWp0QlFVTmtMRmRCUVU4c1MwRkJTeXhMUVVGTUxFTkJRVmNzUjBGQldDeERRVUZsTEVsQlFXWXNTVUZCZFVJc1MwRkJTeXhMUVVGTUxFTkJRVmNzUjBGQldDeERRVUZsTEVsQlFXWXNRMEZCZGtJc1IwRkJPRU1zU1VGQk9VTXNRMEZFVHp0SFFVRm9RanM3UVVGSlFTeGhRVUZYTEVkQlFWZ3NSVUZCWlR0QlFVTmlMRk5CUVVrc1NVRkJTU3hKUVVGS0xFbEJRVmtzUzBGQlN5eExRVUZNTEVOQlFWY3NTVUZCV0N4RlFVRm9RaXhGUVVGclF6dEJRVU5vUXl4VlFVRkhMRXRCUVVzc1MwRkJUQ3hEUVVGWExFZEJRVmdzUTBGQlpTeEpRVUZtTEV0QlFYZENMRXRCUVVzc1MwRkJUQ3hEUVVGWExFZEJRVmdzUTBGQlpTeEpRVUZtTEUxQlFYbENMRWRCUVhwQ0xFVkJRVFpDTzBGQlEzUkVMR0ZCUVVzc1MwRkJUQ3hEUVVGWExFMUJRVmdzUTBGQmEwSXNTVUZCYkVJc1JVRkVjMFE3VDBGQmVFUTdTMEZFUmp0SFFVUkdPenRCUVZGQkxGRkJRVXM3UVVGRFNDeFhRVUZQTEV0QlFVc3NaVUZCVEN4RFFVRnhRaXhIUVVGeVFpeERRVVJLTzBkQlFVdzdPMEZCU1VFc1VVRkJUU3hGUVVGT0xFVkJRVk03UVVGRFVDeFJRVUZKTEdOQlFXTXNWMEZCVnl4SFFVRllMRVZCUVdkQ08wRkJReTlDTEdGQlFVOHNTMEZCU3l4SlFVRk1MRU5CUVZVc1IwRkJWaXhEUVVGakxFVkJRV1FzU1VGQmIwSXNSVUZCY0VJc1IwRkJlVUlzU1VGQmVrSXNRMEZFZDBJN1MwRkJiRU1zVFVGRlR5eEpRVUZKTEdOQlFXTXNUMEZCWkN4RlFVRjFRanRCUVVNdlFpeGhRVUZQTEVkQlFVY3NSMEZCU0N4RFFVUjNRanRMUVVFelFpeE5RVVZCTzBGQlEwb3NWVUZCU1N4TlFVRk5MRXRCUVVzc1ZVRkJUQ3hEUVVGblFpeEZRVUZvUWl4RFFVRk9MRU5CUkVFN1FVRkZTaXhWUVVGSkxGRkJRVkVzU1VGQlVpeEZRVU5FTEUxQlFVMHNhME5CUVd0RExFVkJRV3hETEVkQlFYVkRMRWxCUVhaRExFZEJRVGhETEU5QlFVOHNSVUZCVUN4SFFVRmhMRWRCUVRORUxFTkJSRlE3UVVGRlFTeGhRVUZQTEVkQlFWQXNRMEZLU1R0TFFVWkJPMGRCU0ZRN08wRkJZVUVzVFVGQlNTeEZRVUZLTEVWQlFWRXNSMEZCVWl4RlFVRmhMRXRCUVdJc1JVRkJiVUk3UVVGRGFrSXNVVUZCU1N4TlFVRk5MRXRCUVVzc1MwRkJUQ3hEUVVGWExFVkJRVmdzUTBGQlRpeERRVVJoTzBGQlJXcENMRkZCUVVrc1ZVRkJWU3hMUVVGTExFbEJRVXdzUTBGQlZTeEhRVUZXTEVOQlFXTXNSMEZCWkN4RFFVRldMRU5CUm1FN1FVRkhha0lzV1VGQlVTeEpRVUZTTEVOQlFXRXNSMEZCWWl4SlFVRnZRaXhMUVVGd1FpeERRVWhwUWp0SFFVRnVRanM3UVVGTlFTeE5RVUZKTEVWQlFVb3NSVUZCVVN4SFFVRlNMRVZCUVZrN1FVRkRWaXhSUVVGSkxFMUJRVTBzUzBGQlN5eExRVUZNTEVOQlFWY3NSVUZCV0N4RFFVRk9MRU5CUkUwN1FVRkZWaXhSUVVGSkxGVkJRVlVzUzBGQlN5eEpRVUZNTEVOQlFWVXNSMEZCVml4RFFVRmpMRWRCUVdRc1EwRkJWaXhEUVVaTk96dEJRVWxXTEZGQlFVY3NUMEZCVHl4SlFVRlFMRVZCUVZrN1FVRkRZaXhoUVVGUExGRkJRVkVzU1VGQlVpeERRVUZoTEVkQlFXSXNRMEZCVUN4RFFVUmhPMHRCUVdZc1RVRkZTenRCUVVOSUxHRkJRVThzVVVGQlVTeEpRVUZTTEVOQlJFbzdTMEZHVER0SFFVcEdPenRCUVZkQkxGZEJRVk1zUlVGQlZDeEZRVUZaTzBGQlExWXNVVUZCU1N4TlFVRk5MRXRCUVVzc1MwRkJUQ3hEUVVGWExFVkJRVmdzUTBGQlRpeERRVVJOTzBGQlJWWXNVVUZCU1N4VlFVRlZMRXRCUVVzc1NVRkJUQ3hEUVVGVkxFZEJRVllzUTBGQll5eEhRVUZrTEVOQlFWWXNRMEZHVFRzN1FVRkpWaXhYUVVGUExFOUJRVThzU1VGQlVDeERRVUZaTEZGQlFWRXNTVUZCVWl4RFFVRnVRaXhEUVVwVk8wZEJRVm83TzBGQlQwRXNVVUZCVFN4RlFVRk9MRVZCUVZVc1IwRkJWaXhGUVVGak8wRkJRMW9zVVVGQlNTeE5RVUZOTEV0QlFVc3NTMEZCVEN4RFFVRlhMRVZCUVZnc1EwRkJUaXhEUVVSUk8wRkJSVm9zVVVGQlNTeFZRVUZWTEV0QlFVc3NTVUZCVEN4RFFVRlZMRWRCUVZZc1EwRkJZeXhIUVVGa0xFTkJRVllzUTBGR1VUczdRVUZKV2l4UlFVRkhMRTlCUVU4c1NVRkJVQ3hGUVVGWk8wRkJRMklzWVVGQlR5eFJRVUZSTEVsQlFWSXNRMEZCWVN4SFFVRmlMRU5CUVZBc1EwRkVZVHRMUVVGbUxFMUJSVXM3UVVGRFNDeGpRVUZSTEVsQlFWSXNSMEZCWlN4RlFVRm1MRU5CUkVjN1MwRkdURHRIUVVwR08wTkJla2xHT3p0QlFYRktRU3hsUVVGbExHRkJRV1lpTENKbWFXeGxJam9pYkdsaUwyTnZjbVV2Y0hKdlkyVnpjMlZ6TDNCeWIyTmxjM05mYzNsemRHVnRMbXB6SWl3aWMyOTFjbU5sYzBOdmJuUmxiblFpT2xzaUx5b2dRR1pzYjNjZ0tpOWNibHdpZFhObElITjBjbWxqZEZ3aU8xeHVYRzVwYlhCdmNuUWdUV0ZwYkdKdmVDQm1jbTl0SUZ3aUxpOXRZV2xzWW05NFhDSTdYRzVwYlhCdmNuUWdVSEp2WTJWemN5Qm1jbTl0SUZ3aUxpOXdjbTlqWlhOelhDSTdYRzVwYlhCdmNuUWdVM1JoZEdWeklHWnliMjBnWENJdUwzTjBZWFJsYzF3aU8xeHVhVzF3YjNKMElDb2dZWE1nVUhKcGJXbDBhWFpsY3lCbWNtOXRJRndpTGk0dmNISnBiV2wwYVhabGMxd2lPMXh1WEc1amJHRnpjeUJRY205alpYTnpVM2x6ZEdWdElIdGNibHh1SUNCamIyNXpkSEoxWTNSdmNpZ3BlMXh1SUNBZ0lIUm9hWE11Y0dsa2N5QTlJRzVsZHlCTllYQW9LVHRjYmlBZ0lDQjBhR2x6TG0xaGFXeGliM2hsY3lBOUlHNWxkeUJOWVhBb0tUdGNiaUFnSUNCMGFHbHpMbTVoYldWeklEMGdibVYzSUUxaGNDZ3BPMXh1SUNBZ0lIUm9hWE11YkdsdWEzTWdQU0J1WlhjZ1RXRndLQ2s3WEc1Y2JpQWdJQ0IwYUdsekxtTjFjbkpsYm5SZmNISnZZMlZ6Y3lBOUlHNTFiR3c3WEc0Z0lDQWdkR2hwY3k1emRYTndaVzVrWldRZ1BTQnVaWGNnVFdGd0tDazdYRzVjYmlBZ0lDQjBhR2x6TG0xaGFXNWZjSEp2WTJWemMxOXdhV1FnUFNCMGFHbHpMbk53WVhkdUtDazdYRzRnSUNBZ2RHaHBjeTV6WlhSZlkzVnljbVZ1ZENoMGFHbHpMbTFoYVc1ZmNISnZZMlZ6YzE5d2FXUXBPMXh1SUNCOVhHNWNiaUFnYzNCaGQyNG9LWHRjYmlBZ0lDQnlaWFIxY200Z2RHaHBjeTVoWkdSZmNISnZZeWhtWVd4elpTa3VjR2xrTzF4dUlDQjlYRzVjYmlBZ2MzQmhkMjVmYkdsdWF5Z3BlMXh1SUNBZ0lISmxkSFZ5YmlCMGFHbHpMbUZrWkY5d2NtOWpLSFJ5ZFdVcExuQnBaRHRjYmlBZ2ZWeHVYRzRnSUd4cGJtc29jR2xrS1h0Y2JpQWdJQ0IwYUdsekxteHBibXR6TG1kbGRDaDBhR2x6TG5CcFpDZ3BLUzVoWkdRb2NHbGtLVHRjYmlBZ0lDQjBhR2x6TG14cGJtdHpMbWRsZENod2FXUXBMbUZrWkNoMGFHbHpMbkJwWkNncEtUdGNiaUFnZlZ4dVhHNGdJSFZ1YkdsdWF5aHdhV1FwZTF4dUlDQWdJSFJvYVhNdWJHbHVhM011WjJWMEtIUm9hWE11Y0dsa0tDa3BMbVJsYkdWMFpTaHdhV1FwTzF4dUlDQWdJSFJvYVhNdWJHbHVhM011WjJWMEtIQnBaQ2t1WkdWc1pYUmxLSFJvYVhNdWNHbGtLQ2twTzF4dUlDQjlYRzVjYmlBZ2MyVjBYMk4xY25KbGJuUW9hV1FwZTF4dUlDQWdJR3hsZENCd2FXUWdQU0IwYUdsekxuQnBaRzltS0dsa0tUdGNiaUFnSUNCcFppaHdhV1FnSVQwOUlHNTFiR3dwZTF4dUlDQWdJQ0FnZEdocGN5NWpkWEp5Wlc1MFgzQnliMk5sYzNNZ1BTQjBhR2x6TG5CcFpITXVaMlYwS0hCcFpDazdYRzRnSUNBZ0lDQjBhR2x6TG1OMWNuSmxiblJmY0hKdlkyVnpjeTV6ZEdGMGRYTWdQU0JUZEdGMFpYTXVVbFZPVGtsT1J6dGNiaUFnSUNCOVhHNGdJSDFjYmx4dUlDQmhaR1JmY0hKdll5aHNhVzVyWldRcGUxeHVJQ0FnSUd4bGRDQnVaWGR3YVdRZ1BTQnVaWGNnVUhKcGJXbDBhWFpsY3k1UVNVUW9LVHRjYmlBZ0lDQnNaWFFnYldGcGJHSnZlQ0E5SUc1bGR5Qk5ZV2xzWW05NEtDazdYRzRnSUNBZ2JHVjBJRzVsZDNCeWIyTWdQU0J1WlhjZ1VISnZZMlZ6Y3lodVpYZHdhV1FzSUcxaGFXeGliM2dwTzF4dVhHNGdJQ0FnZEdocGN5NXdhV1J6TG5ObGRDaHVaWGR3YVdRc0lHNWxkM0J5YjJNcE8xeHVJQ0FnSUhSb2FYTXViV0ZwYkdKdmVHVnpMbk5sZENodVpYZHdhV1FzSUcxaGFXeGliM2dwTzF4dUlDQWdJSFJvYVhNdWJHbHVhM011YzJWMEtHNWxkM0JwWkN3Z2JtVjNJRk5sZENncEtUdGNibHh1SUNBZ0lHbG1LR3hwYm10bFpDbDdYRzRnSUNBZ0lDQjBhR2x6TG14cGJtc29ibVYzY0dsa0tUdGNiaUFnSUNCOVhHNWNiaUFnSUNCeVpYUjFjbTRnYm1WM2NISnZZenRjYmlBZ2ZWeHVYRzRnSUhKbGJXOTJaVjl3Y205aktIQnBaQ2w3WEc0Z0lDQWdkR2hwY3k1d2FXUnpMbVJsYkdWMFpTaHdhV1FwTzF4dUlDQWdJSFJvYVhNdWRXNXlaV2RwYzNSbGNpaHdhV1FwTzF4dVhHNGdJQ0FnYVdZb2RHaHBjeTVzYVc1cmN5NW9ZWE1vY0dsa0tTbDdYRzRnSUNBZ0lDQm1iM0lnS0d4bGRDQnNhVzVyY0dsa0lHOW1JSFJvYVhNdWJHbHVhM011WjJWMEtIQnBaQ2twSUh0Y2JpQWdJQ0FnSUNBZ2RHaHBjeTVzYVc1cmN5NW5aWFFvYkdsdWEzQnBaQ2t1WkdWc1pYUmxLSEJwWkNrN1hHNGdJQ0FnSUNCOVhHNWNiaUFnSUNBZ0lIUm9hWE11YkdsdWEzTXVaR1ZzWlhSbEtIQnBaQ2s3WEc0Z0lDQWdmVnh1SUNCOVhHNWNiaUFnWlhocGRDaHBaQ2w3WEc0Z0lDQWdiR1YwSUhCcFpDQTlJSFJvYVhNdWNHbGtiMllvYVdRcE8xeHVJQ0FnSUhSb2FYTXVjbVZ0YjNabFgzQnliMk1vYVdRcE8xeHVJQ0I5WEc1Y2JpQWdjbVZuYVhOMFpYSW9ibUZ0WlN3Z2NHbGtLWHRjYmlBZ0lDQnBaaWdoZEdocGN5NXVZVzFsY3k1b1lYTW9ibUZ0WlNrcGUxeHVJQ0FnSUNBZ2RHaHBjeTV1WVcxbGN5NXpaWFFvYm1GdFpTd2djR2xrS1Z4dUlDQWdJQ0FnY21WMGRYSnVJRzVoYldVN1hHNGdJQ0FnZldWc2MyVjdYRzRnSUNBZ0lDQjBhSEp2ZHlCdVpYY2dSWEp5YjNJb1hDSk9ZVzFsSUdseklHRnNjbVZoWkhrZ2NtVm5hWE4wWlhKbFpDQjBieUJoYm05MGFHVnlJSEJ5YjJObGMzTmNJaWs3WEc0Z0lDQWdmVnh1SUNCOVhHNWNiaUFnY21WbmFYTjBaWEpsWkNodVlXMWxLWHRjYmlBZ0lDQnlaWFIxY200Z2RHaHBjeTV1WVcxbGN5NW9ZWE1vYm1GdFpTa2dQeUIwYUdsekxtNWhiV1Z6TG1kbGRDaHVZVzFsS1NBNklHNTFiR3c3WEc0Z0lIMWNibHh1SUNCMWJuSmxaMmx6ZEdWeUtIQnBaQ2w3WEc0Z0lDQWdabTl5S0d4bGRDQnVZVzFsSUc5bUlIUm9hWE11Ym1GdFpYTXVhMlY1Y3lncEtYdGNiaUFnSUNBZ0lHbG1LSFJvYVhNdWJtRnRaWE11YUdGektHNWhiV1VwSUNZbUlIUm9hWE11Ym1GdFpYTXVaMlYwS0c1aGJXVXBJRDA5UFNCd2FXUXBlMXh1SUNBZ0lDQWdJQ0IwYUdsekxtNWhiV1Z6TG1SbGJHVjBaU2h1WVcxbEtUdGNiaUFnSUNBZ0lIMWNiaUFnSUNCOVhHNGdJSDFjYmx4dUlDQndhV1FvS1h0Y2JpQWdJQ0J5WlhSMWNtNGdkR2hwY3k1amRYSnlaVzUwWDNCeWIyTmxjM011Y0dsa08xeHVJQ0I5WEc1Y2JpQWdjR2xrYjJZb2FXUXBlMXh1SUNBZ0lHbG1JQ2hwWkNCcGJuTjBZVzVqWlc5bUlGQnlhVzFwZEdsMlpYTXVVRWxFS1NCN1hHNGdJQ0FnSUNBZ2NtVjBkWEp1SUhSb2FYTXVjR2xrY3k1b1lYTW9hV1FwSUQ4Z2FXUWdPaUJ1ZFd4c08xeHVJQ0FnSUgwZ1pXeHpaU0JwWmlBb2FXUWdhVzV6ZEdGdVkyVnZaaUJRY205alpYTnpLU0I3WEc0Z0lDQWdJQ0FnY21WMGRYSnVJR2xrTG5CcFpEdGNiaUFnSUNCOUlHVnNjMlVnZTF4dUlDQWdJQ0FnSUd4bGRDQndhV1FnUFNCMGFHbHpMbkpsWjJsemRHVnlaV1FvYVdRcE8xeHVJQ0FnSUNBZ0lHbG1JQ2h3YVdRZ1BUMDlJRzUxYkd3cFhHNGdJQ0FnSUNBZ0lDQWdkR2h5YjNjb1hDSlFjbTlqWlhOeklHNWhiV1VnYm05MElISmxaMmx6ZEdWeVpXUTZJRndpSUNzZ2FXUWdLeUJjSWlBb1hDSWdLeUIwZVhCbGIyWW9hV1FwSUNzZ1hDSXBYQ0lwTzF4dUlDQWdJQ0FnSUhKbGRIVnliaUJ3YVdRN1hHNGdJQ0FnZlZ4dUlDQjlYRzVjYmlBZ2NIVjBLR2xrTENCclpYa3NJSFpoYkhWbEtYdGNiaUFnSUNCc1pYUWdjR2xrSUQwZ2RHaHBjeTV3YVdSdlppaHBaQ2s3WEc0Z0lDQWdiR1YwSUhCeWIyTmxjM01nUFNCMGFHbHpMbkJwWkhNdVoyVjBLSEJwWkNrN1hHNGdJQ0FnY0hKdlkyVnpjeTVrYVdOMFcydGxlVjBnUFNCMllXeDFaVHRjYmlBZ2ZWeHVYRzRnSUdkbGRDaHBaQ3dnYTJWNUtYdGNiaUFnSUNCc1pYUWdjR2xrSUQwZ2RHaHBjeTV3YVdSdlppaHBaQ2s3WEc0Z0lDQWdiR1YwSUhCeWIyTmxjM01nUFNCMGFHbHpMbkJwWkhNdVoyVjBLSEJwWkNrN1hHNWNiaUFnSUNCcFppaHJaWGtnSVQwZ2JuVnNiQ2w3WEc0Z0lDQWdJQ0J5WlhSMWNtNGdjSEp2WTJWemN5NWthV04wVzJ0bGVWMDdYRzRnSUNBZ2ZXVnNjMlY3WEc0Z0lDQWdJQ0J5WlhSMWNtNGdjSEp2WTJWemN5NWthV04wTzF4dUlDQWdJSDFjYmlBZ2ZWeHVYRzRnSUdkbGRGOXJaWGx6S0dsa0tYdGNiaUFnSUNCc1pYUWdjR2xrSUQwZ2RHaHBjeTV3YVdSdlppaHBaQ2s3WEc0Z0lDQWdiR1YwSUhCeWIyTmxjM01nUFNCMGFHbHpMbkJwWkhNdVoyVjBLSEJwWkNrN1hHNWNiaUFnSUNCeVpYUjFjbTRnVDJKcVpXTjBMbXRsZVhNb2NISnZZMlZ6Y3k1a2FXTjBLVHRjYmlBZ2ZWeHVYRzRnSUdWeVlYTmxLR2xrTENCclpYa3BlMXh1SUNBZ0lHeGxkQ0J3YVdRZ1BTQjBhR2x6TG5CcFpHOW1LR2xrS1R0Y2JpQWdJQ0JzWlhRZ2NISnZZMlZ6Y3lBOUlIUm9hWE11Y0dsa2N5NW5aWFFvY0dsa0tUdGNibHh1SUNBZ0lHbG1LR3RsZVNBaFBTQnVkV3hzS1h0Y2JpQWdJQ0FnSUdSbGJHVjBaU0J3Y205alpYTnpMbVJwWTNSYmEyVjVYVHRjYmlBZ0lDQjlaV3h6Wlh0Y2JpQWdJQ0FnSUhCeWIyTmxjM011WkdsamRDQTlJSHQ5TzF4dUlDQWdJSDFjYmlBZ2ZWeHVmVnh1WEc1bGVIQnZjblFnWkdWbVlYVnNkQ0JRY205alpYTnpVM2x6ZEdWdE8xeHVJbDBzSW5OdmRYSmpaVkp2YjNRaU9pSXZjMjkxY21ObEx5SjlcbiIsImNsYXNzIEJpdFN0cmluZyB7XG4gIGNvbnN0cnVjdG9yKC4uLmFyZ3MpIHtcbiAgICB0aGlzLnJhd192YWx1ZSA9IGZ1bmN0aW9uICgpIHtcbiAgICAgIHJldHVybiBPYmplY3QuZnJlZXplKGFyZ3MpO1xuICAgIH07XG5cbiAgICB0aGlzLnZhbHVlID0gT2JqZWN0LmZyZWV6ZSh0aGlzLnByb2Nlc3MoYXJncykpO1xuICAgIHRoaXMubGVuZ3RoID0gdGhpcy52YWx1ZS5sZW5ndGg7XG4gICAgdGhpcy5iaXRfc2l6ZSA9IHRoaXMucmF3X3ZhbHVlKCkucmVkdWNlKChwcmV2LCBjdXJyZW50KSA9PiBwcmV2ICsgY3VycmVudC5zaXplKTtcbiAgICB0aGlzLmJ5dGVfc2l6ZSA9IHRoaXMuYml0X3NpemUgLyA4ICsgKHRoaXMuYml0X3NpemUgJSA4ID4gMCA/IDEgOiAwKTtcbiAgfVxuXG4gIGdldChpbmRleCkge1xuICAgIHJldHVybiB0aGlzLnZhbHVlW2luZGV4XTtcbiAgfVxuXG4gIGNvdW50KCkge1xuICAgIHJldHVybiB0aGlzLnZhbHVlLmxlbmd0aDtcbiAgfVxuXG4gIFtTeW1ib2wuaXRlcmF0b3JdKCkge1xuICAgIHJldHVybiB0aGlzLnZhbHVlW1N5bWJvbC5pdGVyYXRvcl0oKTtcbiAgfVxuXG4gIHRvU3RyaW5nKCkge1xuICAgIHZhciBpLFxuICAgICAgICBzID0gXCJcIjtcbiAgICBmb3IgKGkgPSAwOyBpIDwgdGhpcy5jb3VudCgpOyBpKyspIHtcbiAgICAgIGlmIChzICE9PSBcIlwiKSB7XG4gICAgICAgIHMgKz0gXCIsIFwiO1xuICAgICAgfVxuICAgICAgcyArPSB0aGlzW2ldLnRvU3RyaW5nKCk7XG4gICAgfVxuXG4gICAgcmV0dXJuIFwiPDxcIiArIHMgKyBcIj4+XCI7XG4gIH1cblxuICBwcm9jZXNzKCkge1xuICAgIGxldCBwcm9jZXNzZWRfdmFsdWVzID0gW107XG5cbiAgICB2YXIgaTtcbiAgICBmb3IgKGkgPSAwOyBpIDwgdGhpcy5yYXdfdmFsdWUoKS5sZW5ndGg7IGkrKykge1xuICAgICAgbGV0IHByb2Nlc3NlZF92YWx1ZSA9IHRoaXNbJ3Byb2Nlc3NfJyArIHRoaXMucmF3X3ZhbHVlKClbaV0udHlwZV0odGhpcy5yYXdfdmFsdWUoKVtpXSk7XG5cbiAgICAgIGZvciAobGV0IGF0dHIgb2YgdGhpcy5yYXdfdmFsdWUoKVtpXS5hdHRyaWJ1dGVzKSB7XG4gICAgICAgIHByb2Nlc3NlZF92YWx1ZSA9IHRoaXNbJ3Byb2Nlc3NfJyArIGF0dHJdKHByb2Nlc3NlZF92YWx1ZSk7XG4gICAgICB9XG5cbiAgICAgIHByb2Nlc3NlZF92YWx1ZXMgPSBwcm9jZXNzZWRfdmFsdWVzLmNvbmNhdChwcm9jZXNzZWRfdmFsdWUpO1xuICAgIH1cblxuICAgIHJldHVybiBwcm9jZXNzZWRfdmFsdWVzO1xuICB9XG5cbiAgcHJvY2Vzc19pbnRlZ2VyKHZhbHVlKSB7XG4gICAgcmV0dXJuIHZhbHVlLnZhbHVlO1xuICB9XG5cbiAgcHJvY2Vzc19mbG9hdCh2YWx1ZSkge1xuICAgIGlmICh2YWx1ZS5zaXplID09PSA2NCkge1xuICAgICAgcmV0dXJuIEJpdFN0cmluZy5mbG9hdDY0VG9CeXRlcyh2YWx1ZS52YWx1ZSk7XG4gICAgfSBlbHNlIGlmICh2YWx1ZS5zaXplID09PSAzMikge1xuICAgICAgcmV0dXJuIEJpdFN0cmluZy5mbG9hdDMyVG9CeXRlcyh2YWx1ZS52YWx1ZSk7XG4gICAgfVxuXG4gICAgdGhyb3cgbmV3IEVycm9yKCdJbnZhbGlkIHNpemUgZm9yIGZsb2F0Jyk7XG4gIH1cblxuICBwcm9jZXNzX2JpdHN0cmluZyh2YWx1ZSkge1xuICAgIHJldHVybiB2YWx1ZS52YWx1ZS52YWx1ZTtcbiAgfVxuXG4gIHByb2Nlc3NfYmluYXJ5KHZhbHVlKSB7XG4gICAgcmV0dXJuIEJpdFN0cmluZy50b1VURjhBcnJheSh2YWx1ZS52YWx1ZSk7XG4gIH1cblxuICBwcm9jZXNzX3V0ZjgodmFsdWUpIHtcbiAgICByZXR1cm4gQml0U3RyaW5nLnRvVVRGOEFycmF5KHZhbHVlLnZhbHVlKTtcbiAgfVxuXG4gIHByb2Nlc3NfdXRmMTYodmFsdWUpIHtcbiAgICByZXR1cm4gQml0U3RyaW5nLnRvVVRGMTZBcnJheSh2YWx1ZS52YWx1ZSk7XG4gIH1cblxuICBwcm9jZXNzX3V0ZjMyKHZhbHVlKSB7XG4gICAgcmV0dXJuIEJpdFN0cmluZy50b1VURjMyQXJyYXkodmFsdWUudmFsdWUpO1xuICB9XG5cbiAgcHJvY2Vzc19zaWduZWQodmFsdWUpIHtcbiAgICByZXR1cm4gbmV3IFVpbnQ4QXJyYXkoW3ZhbHVlXSlbMF07XG4gIH1cblxuICBwcm9jZXNzX3Vuc2lnbmVkKHZhbHVlKSB7XG4gICAgcmV0dXJuIHZhbHVlO1xuICB9XG5cbiAgcHJvY2Vzc19uYXRpdmUodmFsdWUpIHtcbiAgICByZXR1cm4gdmFsdWU7XG4gIH1cblxuICBwcm9jZXNzX2JpZyh2YWx1ZSkge1xuICAgIHJldHVybiB2YWx1ZTtcbiAgfVxuXG4gIHByb2Nlc3NfbGl0dGxlKHZhbHVlKSB7XG4gICAgcmV0dXJuIHZhbHVlLnJldmVyc2UoKTtcbiAgfVxuXG4gIHByb2Nlc3Nfc2l6ZSh2YWx1ZSkge1xuICAgIHJldHVybiB2YWx1ZTtcbiAgfVxuXG4gIHByb2Nlc3NfdW5pdCh2YWx1ZSkge1xuICAgIHJldHVybiB2YWx1ZTtcbiAgfVxuXG4gIHN0YXRpYyBpbnRlZ2VyKHZhbHVlKSB7XG4gICAgcmV0dXJuIEJpdFN0cmluZy53cmFwKHZhbHVlLCB7ICd0eXBlJzogJ2ludGVnZXInLCAndW5pdCc6IDEsICdzaXplJzogOCB9KTtcbiAgfVxuXG4gIHN0YXRpYyBmbG9hdCh2YWx1ZSkge1xuICAgIHJldHVybiBCaXRTdHJpbmcud3JhcCh2YWx1ZSwgeyAndHlwZSc6ICdmbG9hdCcsICd1bml0JzogMSwgJ3NpemUnOiA2NCB9KTtcbiAgfVxuXG4gIHN0YXRpYyBiaXRzdHJpbmcodmFsdWUpIHtcbiAgICByZXR1cm4gQml0U3RyaW5nLndyYXAodmFsdWUsIHsgJ3R5cGUnOiAnYml0c3RyaW5nJywgJ3VuaXQnOiAxLCAnc2l6ZSc6IHZhbHVlLmJpdF9zaXplIH0pO1xuICB9XG5cbiAgc3RhdGljIGJpdHModmFsdWUpIHtcbiAgICByZXR1cm4gQml0U3RyaW5nLmJpdHN0cmluZyh2YWx1ZSk7XG4gIH1cblxuICBzdGF0aWMgYmluYXJ5KHZhbHVlKSB7XG4gICAgcmV0dXJuIEJpdFN0cmluZy53cmFwKHZhbHVlLCB7ICd0eXBlJzogJ2JpbmFyeScsICd1bml0JzogOCwgJ3NpemUnOiB2YWx1ZS5sZW5ndGggfSk7XG4gIH1cblxuICBzdGF0aWMgYnl0ZXModmFsdWUpIHtcbiAgICByZXR1cm4gQml0U3RyaW5nLmJpbmFyeSh2YWx1ZSk7XG4gIH1cblxuICBzdGF0aWMgdXRmOCh2YWx1ZSkge1xuICAgIHJldHVybiBCaXRTdHJpbmcud3JhcCh2YWx1ZSwgeyAndHlwZSc6ICd1dGY4JyB9KTtcbiAgfVxuXG4gIHN0YXRpYyB1dGYxNih2YWx1ZSkge1xuICAgIHJldHVybiBCaXRTdHJpbmcud3JhcCh2YWx1ZSwgeyAndHlwZSc6ICd1dGYxNicgfSk7XG4gIH1cblxuICBzdGF0aWMgdXRmMzIodmFsdWUpIHtcbiAgICByZXR1cm4gQml0U3RyaW5nLndyYXAodmFsdWUsIHsgJ3R5cGUnOiAndXRmMzInIH0pO1xuICB9XG5cbiAgc3RhdGljIHNpZ25lZCh2YWx1ZSkge1xuICAgIHJldHVybiBCaXRTdHJpbmcud3JhcCh2YWx1ZSwge30sICdzaWduZWQnKTtcbiAgfVxuXG4gIHN0YXRpYyB1bnNpZ25lZCh2YWx1ZSkge1xuICAgIHJldHVybiBCaXRTdHJpbmcud3JhcCh2YWx1ZSwge30sICd1bnNpZ25lZCcpO1xuICB9XG5cbiAgc3RhdGljIG5hdGl2ZSh2YWx1ZSkge1xuICAgIHJldHVybiBCaXRTdHJpbmcud3JhcCh2YWx1ZSwge30sICduYXRpdmUnKTtcbiAgfVxuXG4gIHN0YXRpYyBiaWcodmFsdWUpIHtcbiAgICByZXR1cm4gQml0U3RyaW5nLndyYXAodmFsdWUsIHt9LCAnYmlnJyk7XG4gIH1cblxuICBzdGF0aWMgbGl0dGxlKHZhbHVlKSB7XG4gICAgcmV0dXJuIEJpdFN0cmluZy53cmFwKHZhbHVlLCB7fSwgJ2xpdHRsZScpO1xuICB9XG5cbiAgc3RhdGljIHNpemUodmFsdWUsIGNvdW50KSB7XG4gICAgcmV0dXJuIEJpdFN0cmluZy53cmFwKHZhbHVlLCB7ICdzaXplJzogY291bnQgfSk7XG4gIH1cblxuICBzdGF0aWMgdW5pdCh2YWx1ZSwgY291bnQpIHtcbiAgICByZXR1cm4gQml0U3RyaW5nLndyYXAodmFsdWUsIHsgJ3VuaXQnOiBjb3VudCB9KTtcbiAgfVxuXG4gIHN0YXRpYyB3cmFwKHZhbHVlLCBvcHQsIG5ld19hdHRyaWJ1dGUgPSBudWxsKSB7XG4gICAgbGV0IHRoZV92YWx1ZSA9IHZhbHVlO1xuXG4gICAgaWYgKCEodmFsdWUgaW5zdGFuY2VvZiBPYmplY3QpKSB7XG4gICAgICB0aGVfdmFsdWUgPSB7ICd2YWx1ZSc6IHZhbHVlLCAnYXR0cmlidXRlcyc6IFtdIH07XG4gICAgfVxuXG4gICAgdGhlX3ZhbHVlID0gT2JqZWN0LmFzc2lnbih0aGVfdmFsdWUsIG9wdCk7XG5cbiAgICBpZiAobmV3X2F0dHJpYnV0ZSkge1xuICAgICAgdGhlX3ZhbHVlLmF0dHJpYnV0ZXMucHVzaChuZXdfYXR0cmlidXRlKTtcbiAgICB9XG5cbiAgICByZXR1cm4gdGhlX3ZhbHVlO1xuICB9XG5cbiAgc3RhdGljIHRvVVRGOEFycmF5KHN0cikge1xuICAgIHZhciB1dGY4ID0gW107XG4gICAgZm9yICh2YXIgaSA9IDA7IGkgPCBzdHIubGVuZ3RoOyBpKyspIHtcbiAgICAgIHZhciBjaGFyY29kZSA9IHN0ci5jaGFyQ29kZUF0KGkpO1xuICAgICAgaWYgKGNoYXJjb2RlIDwgMHg4MCkge1xuICAgICAgICB1dGY4LnB1c2goY2hhcmNvZGUpO1xuICAgICAgfSBlbHNlIGlmIChjaGFyY29kZSA8IDB4ODAwKSB7XG4gICAgICAgIHV0ZjgucHVzaCgweGMwIHwgY2hhcmNvZGUgPj4gNiwgMHg4MCB8IGNoYXJjb2RlICYgMHgzZik7XG4gICAgICB9IGVsc2UgaWYgKGNoYXJjb2RlIDwgMHhkODAwIHx8IGNoYXJjb2RlID49IDB4ZTAwMCkge1xuICAgICAgICB1dGY4LnB1c2goMHhlMCB8IGNoYXJjb2RlID4+IDEyLCAweDgwIHwgY2hhcmNvZGUgPj4gNiAmIDB4M2YsIDB4ODAgfCBjaGFyY29kZSAmIDB4M2YpO1xuICAgICAgfVxuICAgICAgLy8gc3Vycm9nYXRlIHBhaXJcbiAgICAgIGVsc2Uge1xuICAgICAgICAgIGkrKztcbiAgICAgICAgICAvLyBVVEYtMTYgZW5jb2RlcyAweDEwMDAwLTB4MTBGRkZGIGJ5XG4gICAgICAgICAgLy8gc3VidHJhY3RpbmcgMHgxMDAwMCBhbmQgc3BsaXR0aW5nIHRoZVxuICAgICAgICAgIC8vIDIwIGJpdHMgb2YgMHgwLTB4RkZGRkYgaW50byB0d28gaGFsdmVzXG4gICAgICAgICAgY2hhcmNvZGUgPSAweDEwMDAwICsgKChjaGFyY29kZSAmIDB4M2ZmKSA8PCAxMCB8IHN0ci5jaGFyQ29kZUF0KGkpICYgMHgzZmYpO1xuICAgICAgICAgIHV0ZjgucHVzaCgweGYwIHwgY2hhcmNvZGUgPj4gMTgsIDB4ODAgfCBjaGFyY29kZSA+PiAxMiAmIDB4M2YsIDB4ODAgfCBjaGFyY29kZSA+PiA2ICYgMHgzZiwgMHg4MCB8IGNoYXJjb2RlICYgMHgzZik7XG4gICAgICAgIH1cbiAgICB9XG4gICAgcmV0dXJuIHV0Zjg7XG4gIH1cblxuICBzdGF0aWMgdG9VVEYxNkFycmF5KHN0cikge1xuICAgIHZhciB1dGYxNiA9IFtdO1xuICAgIGZvciAodmFyIGkgPSAwOyBpIDwgc3RyLmxlbmd0aDsgaSsrKSB7XG4gICAgICB2YXIgY29kZVBvaW50ID0gc3RyLmNvZGVQb2ludEF0KGkpO1xuXG4gICAgICBpZiAoY29kZVBvaW50IDw9IDI1NSkge1xuICAgICAgICB1dGYxNi5wdXNoKDApO1xuICAgICAgICB1dGYxNi5wdXNoKGNvZGVQb2ludCk7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICB1dGYxNi5wdXNoKGNvZGVQb2ludCA+PiA4ICYgMHhGRik7XG4gICAgICAgIHV0ZjE2LnB1c2goY29kZVBvaW50ICYgMHhGRik7XG4gICAgICB9XG4gICAgfVxuICAgIHJldHVybiB1dGYxNjtcbiAgfVxuXG4gIHN0YXRpYyB0b1VURjMyQXJyYXkoc3RyKSB7XG4gICAgdmFyIHV0ZjMyID0gW107XG4gICAgZm9yICh2YXIgaSA9IDA7IGkgPCBzdHIubGVuZ3RoOyBpKyspIHtcbiAgICAgIHZhciBjb2RlUG9pbnQgPSBzdHIuY29kZVBvaW50QXQoaSk7XG5cbiAgICAgIGlmIChjb2RlUG9pbnQgPD0gMjU1KSB7XG4gICAgICAgIHV0ZjMyLnB1c2goMCk7XG4gICAgICAgIHV0ZjMyLnB1c2goMCk7XG4gICAgICAgIHV0ZjMyLnB1c2goMCk7XG4gICAgICAgIHV0ZjMyLnB1c2goY29kZVBvaW50KTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHV0ZjMyLnB1c2goMCk7XG4gICAgICAgIHV0ZjMyLnB1c2goMCk7XG4gICAgICAgIHV0ZjMyLnB1c2goY29kZVBvaW50ID4+IDggJiAweEZGKTtcbiAgICAgICAgdXRmMzIucHVzaChjb2RlUG9pbnQgJiAweEZGKTtcbiAgICAgIH1cbiAgICB9XG4gICAgcmV0dXJuIHV0ZjMyO1xuICB9XG5cbiAgLy9odHRwOi8vc3RhY2tvdmVyZmxvdy5jb20vcXVlc3Rpb25zLzIwMDM0OTMvamF2YXNjcmlwdC1mbG9hdC1mcm9tLXRvLWJpdHNcbiAgc3RhdGljIGZsb2F0MzJUb0J5dGVzKGYpIHtcbiAgICB2YXIgYnl0ZXMgPSBbXTtcblxuICAgIHZhciBidWYgPSBuZXcgQXJyYXlCdWZmZXIoNCk7XG4gICAgbmV3IEZsb2F0MzJBcnJheShidWYpWzBdID0gZjtcblxuICAgIGxldCBpbnRWZXJzaW9uID0gbmV3IFVpbnQzMkFycmF5KGJ1ZilbMF07XG5cbiAgICBieXRlcy5wdXNoKGludFZlcnNpb24gPj4gMjQgJiAweEZGKTtcbiAgICBieXRlcy5wdXNoKGludFZlcnNpb24gPj4gMTYgJiAweEZGKTtcbiAgICBieXRlcy5wdXNoKGludFZlcnNpb24gPj4gOCAmIDB4RkYpO1xuICAgIGJ5dGVzLnB1c2goaW50VmVyc2lvbiAmIDB4RkYpO1xuXG4gICAgcmV0dXJuIGJ5dGVzO1xuICB9XG5cbiAgc3RhdGljIGZsb2F0NjRUb0J5dGVzKGYpIHtcbiAgICB2YXIgYnl0ZXMgPSBbXTtcblxuICAgIHZhciBidWYgPSBuZXcgQXJyYXlCdWZmZXIoOCk7XG4gICAgbmV3IEZsb2F0NjRBcnJheShidWYpWzBdID0gZjtcblxuICAgIHZhciBpbnRWZXJzaW9uMSA9IG5ldyBVaW50MzJBcnJheShidWYpWzBdO1xuICAgIHZhciBpbnRWZXJzaW9uMiA9IG5ldyBVaW50MzJBcnJheShidWYpWzFdO1xuXG4gICAgYnl0ZXMucHVzaChpbnRWZXJzaW9uMiA+PiAyNCAmIDB4RkYpO1xuICAgIGJ5dGVzLnB1c2goaW50VmVyc2lvbjIgPj4gMTYgJiAweEZGKTtcbiAgICBieXRlcy5wdXNoKGludFZlcnNpb24yID4+IDggJiAweEZGKTtcbiAgICBieXRlcy5wdXNoKGludFZlcnNpb24yICYgMHhGRik7XG5cbiAgICBieXRlcy5wdXNoKGludFZlcnNpb24xID4+IDI0ICYgMHhGRik7XG4gICAgYnl0ZXMucHVzaChpbnRWZXJzaW9uMSA+PiAxNiAmIDB4RkYpO1xuICAgIGJ5dGVzLnB1c2goaW50VmVyc2lvbjEgPj4gOCAmIDB4RkYpO1xuICAgIGJ5dGVzLnB1c2goaW50VmVyc2lvbjEgJiAweEZGKTtcblxuICAgIHJldHVybiBieXRlcztcbiAgfVxufVxuXG5leHBvcnQgZGVmYXVsdCBCaXRTdHJpbmc7XG4vLyMgc291cmNlTWFwcGluZ1VSTD1kYXRhOmFwcGxpY2F0aW9uL2pzb247YmFzZTY0LGV5SjJaWEp6YVc5dUlqb3pMQ0p6YjNWeVkyVnpJanBiSW14cFlpOWpiM0psTDJKcGRGOXpkSEpwYm1jdWFuTWlYU3dpYm1GdFpYTWlPbHRkTENKdFlYQndhVzVuY3lJNklrRkJRVUVzVFVGQlRTeFRRVUZPTEVOQlFXZENPMEZCUTJRc1kwRkJXU3hIUVVGSExFbEJRVWdzUlVGQlVUdEJRVU5zUWl4VFFVRkxMRk5CUVV3c1IwRkJhVUlzV1VGQlZUdEJRVU42UWl4aFFVRlBMRTlCUVU4c1RVRkJVQ3hEUVVGakxFbEJRV1FzUTBGQlVDeERRVVI1UWp0TFFVRldMRU5CUkVNN08wRkJTMnhDTEZOQlFVc3NTMEZCVEN4SFFVRmhMRTlCUVU4c1RVRkJVQ3hEUVVGakxFdEJRVXNzVDBGQlRDeERRVUZoTEVsQlFXSXNRMEZCWkN4RFFVRmlMRU5CVEd0Q08wRkJUV3hDTEZOQlFVc3NUVUZCVEN4SFFVRmpMRXRCUVVzc1MwRkJUQ3hEUVVGWExFMUJRVmdzUTBGT1NUdEJRVTlzUWl4VFFVRkxMRkZCUVV3c1IwRkJaMElzUzBGQlN5eFRRVUZNTEVkQlFXbENMRTFCUVdwQ0xFTkJRWGRDTEVOQlFVTXNTVUZCUkN4RlFVRlBMRTlCUVZBc1MwRkJiVUlzVDBGQlR5eFJRVUZSTEVsQlFWSXNRMEZCYkVVc1EwRlFhMEk3UVVGUmJFSXNVMEZCU3l4VFFVRk1MRWRCUVdsQ0xFbEJRVU1zUTBGQlN5eFJRVUZNTEVkQlFXZENMRU5CUVdoQ0xFbEJRWE5DTEV0QlFVc3NVVUZCVEN4SFFVRm5RaXhEUVVGb1FpeEhRVUZ2UWl4RFFVRndRaXhIUVVGM1FpeERRVUY0UWl4SFFVRTBRaXhEUVVFMVFpeERRVUYyUWl4RFFWSkRPMGRCUVhCQ096dEJRVmRCTEUxQlFVa3NTMEZCU2l4RlFVRlZPMEZCUTFJc1YwRkJUeXhMUVVGTExFdEJRVXdzUTBGQlZ5eExRVUZZTEVOQlFWQXNRMEZFVVR0SFFVRldPenRCUVVsQkxGVkJRVTg3UVVGRFRDeFhRVUZQTEV0QlFVc3NTMEZCVEN4RFFVRlhMRTFCUVZnc1EwRkVSanRIUVVGUU96dEJRVWxCTEVkQlFVTXNUMEZCVHl4UlFVRlFMRWxCUVcxQ08wRkJRMnhDTEZkQlFVOHNTMEZCU3l4TFFVRk1MRU5CUVZjc1QwRkJUeXhSUVVGUUxFTkJRVmdzUlVGQlVDeERRVVJyUWp0SFFVRndRanM3UVVGSlFTeGhRVUZWTzBGQlExSXNVVUZCU1N4RFFVRktPMUZCUVU4c1NVRkJTU3hGUVVGS0xFTkJSRU03UVVGRlVpeFRRVUZMTEVsQlFVa3NRMEZCU2l4RlFVRlBMRWxCUVVrc1MwRkJTeXhMUVVGTUxFVkJRVW9zUlVGQmEwSXNSMEZCT1VJc1JVRkJiVU03UVVGRGFrTXNWVUZCU1N4TlFVRk5MRVZCUVU0c1JVRkJWVHRCUVVOYUxHRkJRVXNzU1VGQlRDeERRVVJaTzA5QlFXUTdRVUZIUVN4WFFVRkxMRXRCUVVzc1EwRkJUQ3hGUVVGUkxGRkJRVklzUlVGQlRDeERRVXBwUXp0TFFVRnVRenM3UVVGUFFTeFhRVUZQTEU5QlFVOHNRMEZCVUN4SFFVRlhMRWxCUVZnc1EwRlVRenRIUVVGV096dEJRVmxCTEZsQlFWTTdRVUZEVUN4UlFVRkpMRzFDUVVGdFFpeEZRVUZ1UWl4RFFVUkhPenRCUVVkUUxGRkJRVWtzUTBGQlNpeERRVWhQTzBGQlNWQXNVMEZCU3l4SlFVRkpMRU5CUVVvc1JVRkJUeXhKUVVGSkxFdEJRVXNzVTBGQlRDeEhRVUZwUWl4TlFVRnFRaXhGUVVGNVFpeEhRVUY2UXl4RlFVRTRRenRCUVVNMVF5eFZRVUZKTEd0Q1FVRnJRaXhMUVVGTExHRkJRV0VzUzBGQlN5eFRRVUZNTEVkQlFXbENMRU5CUVdwQ0xFVkJRVzlDTEVsQlFYQkNMRU5CUVd4Q0xFTkJRVFJETEV0QlFVc3NVMEZCVEN4SFFVRnBRaXhEUVVGcVFpeERRVUUxUXl4RFFVRnNRaXhEUVVSM1F6czdRVUZITlVNc1YwRkJTU3hKUVVGSkxFbEJRVW9zU1VGQldTeExRVUZMTEZOQlFVd3NSMEZCYVVJc1EwRkJha0lzUlVGQmIwSXNWVUZCY0VJc1JVRkJLMEk3UVVGRE4wTXNNRUpCUVd0Q0xFdEJRVXNzWVVGQllTeEpRVUZpTEVOQlFVd3NRMEZCZDBJc1pVRkJlRUlzUTBGQmJFSXNRMEZFTmtNN1QwRkJMME03TzBGQlNVRXNlVUpCUVcxQ0xHbENRVUZwUWl4TlFVRnFRaXhEUVVGM1FpeGxRVUY0UWl4RFFVRnVRaXhEUVZBMFF6dExRVUU1UXpzN1FVRlZRU3hYUVVGUExHZENRVUZRTEVOQlpFODdSMEZCVkRzN1FVRnBRa0VzYTBKQlFXZENMRXRCUVdoQ0xFVkJRWE5DTzBGQlEzQkNMRmRCUVU4c1RVRkJUU3hMUVVGT0xFTkJSR0U3UjBGQmRFSTdPMEZCU1VFc1owSkJRV01zUzBGQlpDeEZRVUZ2UWp0QlFVTnNRaXhSUVVGSExFMUJRVTBzU1VGQlRpeExRVUZsTEVWQlFXWXNSVUZCYTBJN1FVRkRia0lzWVVGQlR5eFZRVUZWTEdOQlFWWXNRMEZCZVVJc1RVRkJUU3hMUVVGT0xFTkJRV2hETEVOQlJHMUNPMHRCUVhKQ0xFMUJSVTBzU1VGQlJ5eE5RVUZOTEVsQlFVNHNTMEZCWlN4RlFVRm1MRVZCUVd0Q08wRkJRM3BDTEdGQlFVOHNWVUZCVlN4alFVRldMRU5CUVhsQ0xFMUJRVTBzUzBGQlRpeERRVUZvUXl4RFFVUjVRanRMUVVGeVFqczdRVUZKVGl4VlFVRk5MRWxCUVVrc1MwRkJTaXhEUVVGVkxIZENRVUZXTEVOQlFVNHNRMEZRYTBJN1IwRkJjRUk3TzBGQlZVRXNiMEpCUVd0Q0xFdEJRV3hDTEVWQlFYZENPMEZCUTNSQ0xGZEJRVThzVFVGQlRTeExRVUZPTEVOQlFWa3NTMEZCV2l4RFFVUmxPMGRCUVhoQ096dEJRVWxCTEdsQ1FVRmxMRXRCUVdZc1JVRkJjVUk3UVVGRGJrSXNWMEZCVHl4VlFVRlZMRmRCUVZZc1EwRkJjMElzVFVGQlRTeExRVUZPTEVOQlFUZENMRU5CUkcxQ08wZEJRWEpDT3p0QlFVbEJMR1ZCUVdFc1MwRkJZaXhGUVVGdFFqdEJRVU5xUWl4WFFVRlBMRlZCUVZVc1YwRkJWaXhEUVVGelFpeE5RVUZOTEV0QlFVNHNRMEZCTjBJc1EwRkVhVUk3UjBGQmJrSTdPMEZCU1VFc1owSkJRV01zUzBGQlpDeEZRVUZ2UWp0QlFVTnNRaXhYUVVGUExGVkJRVlVzV1VGQlZpeERRVUYxUWl4TlFVRk5MRXRCUVU0c1EwRkJPVUlzUTBGRWEwSTdSMEZCY0VJN08wRkJTVUVzWjBKQlFXTXNTMEZCWkN4RlFVRnZRanRCUVVOc1FpeFhRVUZQTEZWQlFWVXNXVUZCVml4RFFVRjFRaXhOUVVGTkxFdEJRVTRzUTBGQk9VSXNRMEZFYTBJN1IwRkJjRUk3TzBGQlNVRXNhVUpCUVdVc1MwRkJaaXhGUVVGeFFqdEJRVU51UWl4WFFVRlBMRWxCUVVzc1ZVRkJTaXhEUVVGbExFTkJRVU1zUzBGQlJDeERRVUZtTEVOQlFVUXNRMEZCTUVJc1EwRkJNVUlzUTBGQlVDeERRVVJ0UWp0SFFVRnlRanM3UVVGSlFTeHRRa0ZCYVVJc1MwRkJha0lzUlVGQmRVSTdRVUZEY2tJc1YwRkJUeXhMUVVGUUxFTkJSSEZDTzBkQlFYWkNPenRCUVVsQkxHbENRVUZsTEV0QlFXWXNSVUZCY1VJN1FVRkRia0lzVjBGQlR5eExRVUZRTEVOQlJHMUNPMGRCUVhKQ096dEJRVWxCTEdOQlFWa3NTMEZCV2l4RlFVRnJRanRCUVVOb1FpeFhRVUZQTEV0QlFWQXNRMEZFWjBJN1IwRkJiRUk3TzBGQlNVRXNhVUpCUVdVc1MwRkJaaXhGUVVGeFFqdEJRVU51UWl4WFFVRlBMRTFCUVUwc1QwRkJUaXhGUVVGUUxFTkJSRzFDTzBkQlFYSkNPenRCUVVsQkxHVkJRV0VzUzBGQllpeEZRVUZ0UWp0QlFVTnFRaXhYUVVGUExFdEJRVkFzUTBGRWFVSTdSMEZCYmtJN08wRkJTVUVzWlVGQllTeExRVUZpTEVWQlFXMUNPMEZCUTJwQ0xGZEJRVThzUzBGQlVDeERRVVJwUWp0SFFVRnVRanM3UVVGSlFTeFRRVUZQTEU5QlFWQXNRMEZCWlN4TFFVRm1MRVZCUVhGQ08wRkJRMjVDTEZkQlFVOHNWVUZCVlN4SlFVRldMRU5CUVdVc1MwRkJaaXhGUVVGelFpeEZRVUZGTEZGQlFWRXNVMEZCVWl4RlFVRnRRaXhSUVVGUkxFTkJRVklzUlVGQlZ5eFJRVUZSTEVOQlFWSXNSVUZCZEVRc1EwRkJVQ3hEUVVSdFFqdEhRVUZ5UWpzN1FVRkpRU3hUUVVGUExFdEJRVkFzUTBGQllTeExRVUZpTEVWQlFXMUNPMEZCUTJwQ0xGZEJRVThzVlVGQlZTeEpRVUZXTEVOQlFXVXNTMEZCWml4RlFVRnpRaXhGUVVGRkxGRkJRVkVzVDBGQlVpeEZRVUZwUWl4UlFVRlJMRU5CUVZJc1JVRkJWeXhSUVVGUkxFVkJRVklzUlVGQmNFUXNRMEZCVUN4RFFVUnBRanRIUVVGdVFqczdRVUZKUVN4VFFVRlBMRk5CUVZBc1EwRkJhVUlzUzBGQmFrSXNSVUZCZFVJN1FVRkRja0lzVjBGQlR5eFZRVUZWTEVsQlFWWXNRMEZCWlN4TFFVRm1MRVZCUVhOQ0xFVkJRVVVzVVVGQlVTeFhRVUZTTEVWQlFYRkNMRkZCUVZFc1EwRkJVaXhGUVVGWExGRkJRVkVzVFVGQlRTeFJRVUZPTEVWQlFXaEZMRU5CUVZBc1EwRkVjVUk3UjBGQmRrSTdPMEZCU1VFc1UwRkJUeXhKUVVGUUxFTkJRVmtzUzBGQldpeEZRVUZyUWp0QlFVTm9RaXhYUVVGUExGVkJRVlVzVTBGQlZpeERRVUZ2UWl4TFFVRndRaXhEUVVGUUxFTkJSR2RDTzBkQlFXeENPenRCUVVsQkxGTkJRVThzVFVGQlVDeERRVUZqTEV0QlFXUXNSVUZCYjBJN1FVRkRiRUlzVjBGQlR5eFZRVUZWTEVsQlFWWXNRMEZCWlN4TFFVRm1MRVZCUVhOQ0xFVkJRVVVzVVVGQlVTeFJRVUZTTEVWQlFXdENMRkZCUVZFc1EwRkJVaXhGUVVGWExGRkJRVkVzVFVGQlRTeE5RVUZPTEVWQlFUZEVMRU5CUVZBc1EwRkVhMEk3UjBGQmNFSTdPMEZCU1VFc1UwRkJUeXhMUVVGUUxFTkJRV0VzUzBGQllpeEZRVUZ0UWp0QlFVTnFRaXhYUVVGUExGVkJRVlVzVFVGQlZpeERRVUZwUWl4TFFVRnFRaXhEUVVGUUxFTkJSR2xDTzBkQlFXNUNPenRCUVVsQkxGTkJRVThzU1VGQlVDeERRVUZaTEV0QlFWb3NSVUZCYTBJN1FVRkRhRUlzVjBGQlR5eFZRVUZWTEVsQlFWWXNRMEZCWlN4TFFVRm1MRVZCUVhOQ0xFVkJRVVVzVVVGQlVTeE5RVUZTTEVWQlFYaENMRU5CUVZBc1EwRkVaMEk3UjBGQmJFSTdPMEZCU1VFc1UwRkJUeXhMUVVGUUxFTkJRV0VzUzBGQllpeEZRVUZ0UWp0QlFVTnFRaXhYUVVGUExGVkJRVlVzU1VGQlZpeERRVUZsTEV0QlFXWXNSVUZCYzBJc1JVRkJSU3hSUVVGUkxFOUJRVklzUlVGQmVFSXNRMEZCVUN4RFFVUnBRanRIUVVGdVFqczdRVUZKUVN4VFFVRlBMRXRCUVZBc1EwRkJZU3hMUVVGaUxFVkJRVzFDTzBGQlEycENMRmRCUVU4c1ZVRkJWU3hKUVVGV0xFTkJRV1VzUzBGQlppeEZRVUZ6UWl4RlFVRkZMRkZCUVZFc1QwRkJVaXhGUVVGNFFpeERRVUZRTEVOQlJHbENPMGRCUVc1Q096dEJRVWxCTEZOQlFVOHNUVUZCVUN4RFFVRmpMRXRCUVdRc1JVRkJiMEk3UVVGRGJFSXNWMEZCVHl4VlFVRlZMRWxCUVZZc1EwRkJaU3hMUVVGbUxFVkJRWE5DTEVWQlFYUkNMRVZCUVRCQ0xGRkJRVEZDTEVOQlFWQXNRMEZFYTBJN1IwRkJjRUk3TzBGQlNVRXNVMEZCVHl4UlFVRlFMRU5CUVdkQ0xFdEJRV2hDTEVWQlFYTkNPMEZCUTNCQ0xGZEJRVThzVlVGQlZTeEpRVUZXTEVOQlFXVXNTMEZCWml4RlFVRnpRaXhGUVVGMFFpeEZRVUV3UWl4VlFVRXhRaXhEUVVGUUxFTkJSRzlDTzBkQlFYUkNPenRCUVVsQkxGTkJRVThzVFVGQlVDeERRVUZqTEV0QlFXUXNSVUZCYjBJN1FVRkRiRUlzVjBGQlR5eFZRVUZWTEVsQlFWWXNRMEZCWlN4TFFVRm1MRVZCUVhOQ0xFVkJRWFJDTEVWQlFUQkNMRkZCUVRGQ0xFTkJRVkFzUTBGRWEwSTdSMEZCY0VJN08wRkJTVUVzVTBGQlR5eEhRVUZRTEVOQlFWY3NTMEZCV0N4RlFVRnBRanRCUVVObUxGZEJRVThzVlVGQlZTeEpRVUZXTEVOQlFXVXNTMEZCWml4RlFVRnpRaXhGUVVGMFFpeEZRVUV3UWl4TFFVRXhRaXhEUVVGUUxFTkJSR1U3UjBGQmFrSTdPMEZCU1VFc1UwRkJUeXhOUVVGUUxFTkJRV01zUzBGQlpDeEZRVUZ2UWp0QlFVTnNRaXhYUVVGUExGVkJRVlVzU1VGQlZpeERRVUZsTEV0QlFXWXNSVUZCYzBJc1JVRkJkRUlzUlVGQk1FSXNVVUZCTVVJc1EwRkJVQ3hEUVVSclFqdEhRVUZ3UWpzN1FVRkpRU3hUUVVGUExFbEJRVkFzUTBGQldTeExRVUZhTEVWQlFXMUNMRXRCUVc1Q0xFVkJRWGxDTzBGQlEzWkNMRmRCUVU4c1ZVRkJWU3hKUVVGV0xFTkJRV1VzUzBGQlppeEZRVUZ6UWl4RlFVRkRMRkZCUVZFc1MwRkJVaXhGUVVGMlFpeERRVUZRTEVOQlJIVkNPMGRCUVhwQ096dEJRVWxCTEZOQlFVOHNTVUZCVUN4RFFVRlpMRXRCUVZvc1JVRkJiVUlzUzBGQmJrSXNSVUZCZVVJN1FVRkRka0lzVjBGQlR5eFZRVUZWTEVsQlFWWXNRMEZCWlN4TFFVRm1MRVZCUVhOQ0xFVkJRVU1zVVVGQlVTeExRVUZTTEVWQlFYWkNMRU5CUVZBc1EwRkVkVUk3UjBGQmVrSTdPMEZCU1VFc1UwRkJUeXhKUVVGUUxFTkJRVmtzUzBGQldpeEZRVUZ0UWl4SFFVRnVRaXhGUVVGM1FpeG5Ra0ZCWjBJc1NVRkJhRUlzUlVGQmNVSTdRVUZETTBNc1VVRkJTU3haUVVGWkxFdEJRVm9zUTBGRWRVTTdPMEZCUnpORExGRkJRVWNzUlVGQlJTeHBRa0ZCYVVJc1RVRkJha0lzUTBGQlJpeEZRVUV5UWp0QlFVTTFRaXhyUWtGQldTeEZRVUZETEZOQlFWTXNTMEZCVkN4RlFVRm5RaXhqUVVGakxFVkJRV1FzUlVGQk4wSXNRMEZFTkVJN1MwRkJPVUk3TzBGQlNVRXNaMEpCUVZrc1QwRkJUeXhOUVVGUUxFTkJRV01zVTBGQlpDeEZRVUY1UWl4SFFVRjZRaXhEUVVGYUxFTkJVREpET3p0QlFWTXpReXhSUVVGSExHRkJRVWdzUlVGQmFVSTdRVUZEWml4blFrRkJWU3hWUVVGV0xFTkJRWEZDTEVsQlFYSkNMRU5CUVRCQ0xHRkJRVEZDTEVWQlJHVTdTMEZCYWtJN08wRkJTMEVzVjBGQlR5eFRRVUZRTEVOQlpESkRPMGRCUVRkRE96dEJRV2xDUVN4VFFVRlBMRmRCUVZBc1EwRkJiVUlzUjBGQmJrSXNSVUZCZDBJN1FVRkRkRUlzVVVGQlNTeFBRVUZQTEVWQlFWQXNRMEZFYTBJN1FVRkZkRUlzVTBGQlN5eEpRVUZKTEVsQlFVa3NRMEZCU2l4RlFVRlBMRWxCUVVrc1NVRkJTU3hOUVVGS0xFVkJRVmtzUjBGQmFFTXNSVUZCY1VNN1FVRkRia01zVlVGQlNTeFhRVUZYTEVsQlFVa3NWVUZCU2l4RFFVRmxMRU5CUVdZc1EwRkJXQ3hEUVVRclFqdEJRVVZ1UXl4VlFVRkpMRmRCUVZjc1NVRkJXQ3hGUVVGblFqdEJRVU5zUWl4aFFVRkxMRWxCUVV3c1EwRkJWU3hSUVVGV0xFVkJSR3RDTzA5QlFYQkNMRTFCUjBzc1NVRkJTU3hYUVVGWExFdEJRVmdzUlVGQmEwSTdRVUZEZWtJc1lVRkJTeXhKUVVGTUxFTkJRVlVzVDBGQlVTeFpRVUZaTEVOQlFWb3NSVUZEVWl4UFFVRlJMRmRCUVZjc1NVRkJXQ3hEUVVSc1FpeERRVVI1UWp0UFFVRjBRaXhOUVVsQkxFbEJRVWtzVjBGQlZ5eE5RVUZZTEVsQlFYRkNMRmxCUVZrc1RVRkJXaXhGUVVGdlFqdEJRVU5vUkN4aFFVRkxMRWxCUVV3c1EwRkJWU3hQUVVGUkxGbEJRVmtzUlVGQldpeEZRVU5TTEU5QlFWRXNVVUZCUXl4SlFVRlpMRU5CUVZvc1IwRkJhVUlzU1VGQmJFSXNSVUZEVWl4UFFVRlJMRmRCUVZjc1NVRkJXQ3hEUVVac1FpeERRVVJuUkRzN08wRkJRVGRETEZkQlRVRTdRVUZEU0RzN096dEJRVVJITEd0Q1FVdElMRWRCUVZjc1YwRkJWeXhEUVVGRkxGZEJRVmNzUzBGQldDeERRVUZFTEVsQlFYTkNMRVZCUVhSQ0xFZEJRMVlzU1VGQlNTeFZRVUZLTEVOQlFXVXNRMEZCWml4SlFVRnZRaXhMUVVGd1FpeERRVVJHTEVOQlRGSTdRVUZQU0N4bFFVRkxMRWxCUVV3c1EwRkJWU3hQUVVGUkxGbEJRVmtzUlVGQldpeEZRVU5TTEU5QlFWRXNVVUZCUXl4SlFVRlpMRVZCUVZvc1IwRkJhMElzU1VGQmJrSXNSVUZEVWl4UFFVRlJMRkZCUVVNc1NVRkJXU3hEUVVGYUxFZEJRV2xDTEVsQlFXeENMRVZCUTFJc1QwRkJVU3hYUVVGWExFbEJRVmdzUTBGSWJFSXNRMEZRUnp0VFFVNUJPMHRCVkZBN1FVRTBRa0VzVjBGQlR5eEpRVUZRTEVOQk9VSnpRanRIUVVGNFFqczdRVUZwUTBFc1UwRkJUeXhaUVVGUUxFTkJRVzlDTEVkQlFYQkNMRVZCUVhsQ08wRkJRM1pDTEZGQlFVa3NVVUZCVVN4RlFVRlNMRU5CUkcxQ08wRkJSWFpDTEZOQlFVc3NTVUZCU1N4SlFVRkpMRU5CUVVvc1JVRkJUeXhKUVVGSkxFbEJRVWtzVFVGQlNpeEZRVUZaTEVkQlFXaERMRVZCUVhGRE8wRkJRMjVETEZWQlFVa3NXVUZCV1N4SlFVRkpMRmRCUVVvc1EwRkJaMElzUTBGQmFFSXNRMEZCV2l4RFFVUXJRanM3UVVGSGJrTXNWVUZCUnl4aFFVRmhMRWRCUVdJc1JVRkJhVUk3UVVGRGJFSXNZMEZCVFN4SlFVRk9MRU5CUVZjc1EwRkJXQ3hGUVVSclFqdEJRVVZzUWl4alFVRk5MRWxCUVU0c1EwRkJWeXhUUVVGWUxFVkJSbXRDTzA5QlFYQkNMRTFCUjBzN1FVRkRTQ3hqUVVGTkxFbEJRVTRzUTBGQldTeFRRVUZETEVsQlFXRXNRMEZCWWl4SFFVRnJRaXhKUVVGdVFpeERRVUZhTEVOQlJFYzdRVUZGU0N4alFVRk5MRWxCUVU0c1EwRkJXU3haUVVGWkxFbEJRVm9zUTBGQldpeERRVVpITzA5QlNFdzdTMEZJUmp0QlFWZEJMRmRCUVU4c1MwRkJVQ3hEUVdKMVFqdEhRVUY2UWpzN1FVRnBRa0VzVTBGQlR5eFpRVUZRTEVOQlFXOUNMRWRCUVhCQ0xFVkJRWGxDTzBGQlEzWkNMRkZCUVVrc1VVRkJVU3hGUVVGU0xFTkJSRzFDTzBGQlJYWkNMRk5CUVVzc1NVRkJTU3hKUVVGSkxFTkJRVW9zUlVGQlR5eEpRVUZKTEVsQlFVa3NUVUZCU2l4RlFVRlpMRWRCUVdoRExFVkJRWEZETzBGQlEyNURMRlZCUVVrc1dVRkJXU3hKUVVGSkxGZEJRVW9zUTBGQlowSXNRMEZCYUVJc1EwRkJXaXhEUVVRclFqczdRVUZIYmtNc1ZVRkJSeXhoUVVGaExFZEJRV0lzUlVGQmFVSTdRVUZEYkVJc1kwRkJUU3hKUVVGT0xFTkJRVmNzUTBGQldDeEZRVVJyUWp0QlFVVnNRaXhqUVVGTkxFbEJRVTRzUTBGQlZ5eERRVUZZTEVWQlJtdENPMEZCUjJ4Q0xHTkJRVTBzU1VGQlRpeERRVUZYTEVOQlFWZ3NSVUZJYTBJN1FVRkpiRUlzWTBGQlRTeEpRVUZPTEVOQlFWY3NVMEZCV0N4RlFVcHJRanRQUVVGd1FpeE5RVXRMTzBGQlEwZ3NZMEZCVFN4SlFVRk9MRU5CUVZjc1EwRkJXQ3hGUVVSSE8wRkJSVWdzWTBGQlRTeEpRVUZPTEVOQlFWY3NRMEZCV0N4RlFVWkhPMEZCUjBnc1kwRkJUU3hKUVVGT0xFTkJRVmtzVTBGQlF5eEpRVUZoTEVOQlFXSXNSMEZCYTBJc1NVRkJia0lzUTBGQldpeERRVWhITzBGQlNVZ3NZMEZCVFN4SlFVRk9MRU5CUVZrc1dVRkJXU3hKUVVGYUxFTkJRVm9zUTBGS1J6dFBRVXhNTzB0QlNFWTdRVUZsUVN4WFFVRlBMRXRCUVZBc1EwRnFRblZDTzBkQlFYcENPenM3UVVGMFVHTXNVMEV5VVZBc1kwRkJVQ3hEUVVGelFpeERRVUYwUWl4RlFVRjVRanRCUVVOMlFpeFJRVUZKTEZGQlFWRXNSVUZCVWl4RFFVUnRRanM3UVVGSGRrSXNVVUZCU1N4TlFVRk5MRWxCUVVrc1YwRkJTaXhEUVVGblFpeERRVUZvUWl4RFFVRk9MRU5CU0cxQ08wRkJTWFpDTEZGQlFVc3NXVUZCU2l4RFFVRnBRaXhIUVVGcVFpeERRVUZFTEVOQlFYZENMRU5CUVhoQ0xFbEJRVFpDTEVOQlFUZENMRU5CU25WQ096dEJRVTEyUWl4UlFVRkpMR0ZCUVdFc1NVRkJTeXhYUVVGS0xFTkJRV2RDTEVkQlFXaENMRU5CUVVRc1EwRkJkVUlzUTBGQmRrSXNRMEZCWWl4RFFVNXRRanM3UVVGUmRrSXNWVUZCVFN4SlFVRk9MRU5CUVZrc1ZVRkJReXhKUVVGakxFVkJRV1FzUjBGQmIwSXNTVUZCY2tJc1EwRkJXaXhEUVZKMVFqdEJRVk4yUWl4VlFVRk5MRWxCUVU0c1EwRkJXU3hWUVVGRExFbEJRV01zUlVGQlpDeEhRVUZ2UWl4SlFVRnlRaXhEUVVGYUxFTkJWSFZDTzBGQlZYWkNMRlZCUVUwc1NVRkJUaXhEUVVGWkxGVkJRVU1zU1VGQll5eERRVUZrTEVkQlFXMUNMRWxCUVhCQ0xFTkJRVm9zUTBGV2RVSTdRVUZYZGtJc1ZVRkJUU3hKUVVGT0xFTkJRVmtzWVVGQllTeEpRVUZpTEVOQlFWb3NRMEZZZFVJN08wRkJZWFpDTEZkQlFVOHNTMEZCVUN4RFFXSjFRanRIUVVGNlFqczdRVUZuUWtFc1UwRkJUeXhqUVVGUUxFTkJRWE5DTEVOQlFYUkNMRVZCUVhsQ08wRkJRM1pDTEZGQlFVa3NVVUZCVVN4RlFVRlNMRU5CUkcxQ096dEJRVWQyUWl4UlFVRkpMRTFCUVUwc1NVRkJTU3hYUVVGS0xFTkJRV2RDTEVOQlFXaENMRU5CUVU0c1EwRkliVUk3UVVGSmRrSXNVVUZCU3l4WlFVRktMRU5CUVdsQ0xFZEJRV3BDTEVOQlFVUXNRMEZCZDBJc1EwRkJlRUlzU1VGQk5rSXNRMEZCTjBJc1EwRktkVUk3TzBGQlRYWkNMRkZCUVVrc1kwRkJZeXhKUVVGTExGZEJRVW9zUTBGQlowSXNSMEZCYUVJc1EwRkJSQ3hEUVVGMVFpeERRVUYyUWl4RFFVRmtMRU5CVG0xQ08wRkJUM1pDTEZGQlFVa3NZMEZCWXl4SlFVRkxMRmRCUVVvc1EwRkJaMElzUjBGQmFFSXNRMEZCUkN4RFFVRjFRaXhEUVVGMlFpeERRVUZrTEVOQlVHMUNPenRCUVZOMlFpeFZRVUZOTEVsQlFVNHNRMEZCV1N4WFFVRkRMRWxCUVdVc1JVRkJaaXhIUVVGeFFpeEpRVUYwUWl4RFFVRmFMRU5CVkhWQ08wRkJWWFpDTEZWQlFVMHNTVUZCVGl4RFFVRlpMRmRCUVVNc1NVRkJaU3hGUVVGbUxFZEJRWEZDTEVsQlFYUkNMRU5CUVZvc1EwRldkVUk3UVVGWGRrSXNWVUZCVFN4SlFVRk9MRU5CUVZrc1YwRkJReXhKUVVGbExFTkJRV1lzUjBGQmIwSXNTVUZCY2tJc1EwRkJXaXhEUVZoMVFqdEJRVmwyUWl4VlFVRk5MRWxCUVU0c1EwRkJXU3hqUVVGakxFbEJRV1FzUTBGQldpeERRVnAxUWpzN1FVRmpka0lzVlVGQlRTeEpRVUZPTEVOQlFWa3NWMEZCUXl4SlFVRmxMRVZCUVdZc1IwRkJjVUlzU1VGQmRFSXNRMEZCV2l4RFFXUjFRanRCUVdWMlFpeFZRVUZOTEVsQlFVNHNRMEZCV1N4WFFVRkRMRWxCUVdVc1JVRkJaaXhIUVVGeFFpeEpRVUYwUWl4RFFVRmFMRU5CWm5WQ08wRkJaMEoyUWl4VlFVRk5MRWxCUVU0c1EwRkJXU3hYUVVGRExFbEJRV1VzUTBGQlppeEhRVUZ2UWl4SlFVRnlRaXhEUVVGYUxFTkJhRUoxUWp0QlFXbENka0lzVlVGQlRTeEpRVUZPTEVOQlFWa3NZMEZCWXl4SlFVRmtMRU5CUVZvc1EwRnFRblZDT3p0QlFXMUNka0lzVjBGQlR5eExRVUZRTEVOQmJrSjFRanRIUVVGNlFqdERRVE5TUmpzN1FVRnJWRUVzWlVGQlpTeFRRVUZtSWl3aVptbHNaU0k2SW14cFlpOWpiM0psTDJKcGRGOXpkSEpwYm1jdWFuTWlMQ0p6YjNWeVkyVnpRMjl1ZEdWdWRDSTZXeUpqYkdGemN5QkNhWFJUZEhKcGJtY2dlMXh1SUNCamIyNXpkSEoxWTNSdmNpZ3VMaTVoY21kektYdGNiaUFnSUNCMGFHbHpMbkpoZDE5MllXeDFaU0E5SUdaMWJtTjBhVzl1S0NsN1hHNGdJQ0FnSUNCeVpYUjFjbTRnVDJKcVpXTjBMbVp5WldWNlpTaGhjbWR6S1R0Y2JpQWdJQ0I5TzF4dVhHNGdJQ0FnZEdocGN5NTJZV3gxWlNBOUlFOWlhbVZqZEM1bWNtVmxlbVVvZEdocGN5NXdjbTlqWlhOektHRnlaM01wS1R0Y2JpQWdJQ0IwYUdsekxteGxibWQwYUNBOUlIUm9hWE11ZG1Gc2RXVXViR1Z1WjNSb08xeHVJQ0FnSUhSb2FYTXVZbWwwWDNOcGVtVWdQU0IwYUdsekxuSmhkMTkyWVd4MVpTZ3BMbkpsWkhWalpTZ29jSEpsZGl3Z1kzVnljbVZ1ZENrZ1BUNGdjSEpsZGlBcklHTjFjbkpsYm5RdWMybDZaU2s3WEc0Z0lDQWdkR2hwY3k1aWVYUmxYM05wZW1VZ1BTQW9kR2hwY3k1aWFYUmZjMmw2WlNBdklEZ3BJQ3NnS0hSb2FYTXVZbWwwWDNOcGVtVWdKU0E0SUQ0Z01DQS9JREVnT2lBd0tUdGNiaUFnZlZ4dVhHNGdJR2RsZENocGJtUmxlQ2w3WEc0Z0lDQWdjbVYwZFhKdUlIUm9hWE11ZG1Gc2RXVmJhVzVrWlhoZE8xeHVJQ0I5WEc1Y2JpQWdZMjkxYm5Rb0tYdGNiaUFnSUNCeVpYUjFjbTRnZEdocGN5NTJZV3gxWlM1c1pXNW5kR2c3WEc0Z0lIMWNibHh1SUNCYlUzbHRZbTlzTG1sMFpYSmhkRzl5WFNncElIdGNiaUFnSUNCeVpYUjFjbTRnZEdocGN5NTJZV3gxWlZ0VGVXMWliMnd1YVhSbGNtRjBiM0pkS0NrN1hHNGdJSDFjYmx4dUlDQjBiMU4wY21sdVp5Z3BlMXh1SUNBZ0lIWmhjaUJwTENCeklEMGdYQ0pjSWp0Y2JpQWdJQ0JtYjNJZ0tHa2dQU0F3T3lCcElEd2dkR2hwY3k1amIzVnVkQ2dwT3lCcEt5c3BJSHRjYmlBZ0lDQWdJR2xtSUNoeklDRTlQU0JjSWx3aUtTQjdYRzRnSUNBZ0lDQWdJSE1nS3owZ1hDSXNJRndpTzF4dUlDQWdJQ0FnZlZ4dUlDQWdJQ0FnY3lBclBTQjBhR2x6VzJsZExuUnZVM1J5YVc1bktDazdYRzRnSUNBZ2ZWeHVYRzRnSUNBZ2NtVjBkWEp1SUZ3aVBEeGNJaUFySUhNZ0t5QmNJajQrWENJN1hHNGdJSDFjYmx4dUlDQndjbTlqWlhOektDbDdYRzRnSUNBZ2JHVjBJSEJ5YjJObGMzTmxaRjkyWVd4MVpYTWdQU0JiWFR0Y2JseHVJQ0FnSUhaaGNpQnBPMXh1SUNBZ0lHWnZjaUFvYVNBOUlEQTdJR2tnUENCMGFHbHpMbkpoZDE5MllXeDFaU2dwTG14bGJtZDBhRHNnYVNzcktTQjdYRzRnSUNBZ0lDQnNaWFFnY0hKdlkyVnpjMlZrWDNaaGJIVmxJRDBnZEdocGMxc25jSEp2WTJWemMxOG5JQ3NnZEdocGN5NXlZWGRmZG1Gc2RXVW9LVnRwWFM1MGVYQmxYU2gwYUdsekxuSmhkMTkyWVd4MVpTZ3BXMmxkS1R0Y2JseHVJQ0FnSUNBZ1ptOXlLR3hsZENCaGRIUnlJRzltSUhSb2FYTXVjbUYzWDNaaGJIVmxLQ2xiYVYwdVlYUjBjbWxpZFhSbGN5bDdYRzRnSUNBZ0lDQWdJSEJ5YjJObGMzTmxaRjkyWVd4MVpTQTlJSFJvYVhOYkozQnliMk5sYzNOZkp5QXJJR0YwZEhKZEtIQnliMk5sYzNObFpGOTJZV3gxWlNrN1hHNGdJQ0FnSUNCOVhHNWNiaUFnSUNBZ0lIQnliMk5sYzNObFpGOTJZV3gxWlhNZ1BTQndjbTlqWlhOelpXUmZkbUZzZFdWekxtTnZibU5oZENod2NtOWpaWE56WldSZmRtRnNkV1VwTzF4dUlDQWdJSDFjYmx4dUlDQWdJSEpsZEhWeWJpQndjbTlqWlhOelpXUmZkbUZzZFdWek8xeHVJQ0I5WEc1Y2JpQWdjSEp2WTJWemMxOXBiblJsWjJWeUtIWmhiSFZsS1h0Y2JpQWdJQ0J5WlhSMWNtNGdkbUZzZFdVdWRtRnNkV1U3WEc0Z0lIMWNibHh1SUNCd2NtOWpaWE56WDJac2IyRjBLSFpoYkhWbEtYdGNiaUFnSUNCcFppaDJZV3gxWlM1emFYcGxJRDA5UFNBMk5DbDdYRzRnSUNBZ0lDQnlaWFIxY200Z1FtbDBVM1J5YVc1bkxtWnNiMkYwTmpSVWIwSjVkR1Z6S0haaGJIVmxMblpoYkhWbEtUdGNiaUFnSUNCOVpXeHpaU0JwWmloMllXeDFaUzV6YVhwbElEMDlQU0F6TWlsN1hHNGdJQ0FnSUNCeVpYUjFjbTRnUW1sMFUzUnlhVzVuTG1ac2IyRjBNekpVYjBKNWRHVnpLSFpoYkhWbExuWmhiSFZsS1R0Y2JpQWdJQ0I5WEc1Y2JpQWdJQ0IwYUhKdmR5QnVaWGNnUlhKeWIzSW9KMGx1ZG1Gc2FXUWdjMmw2WlNCbWIzSWdabXh2WVhRbktUdGNiaUFnZlZ4dVhHNGdJSEJ5YjJObGMzTmZZbWwwYzNSeWFXNW5LSFpoYkhWbEtYdGNiaUFnSUNCeVpYUjFjbTRnZG1Gc2RXVXVkbUZzZFdVdWRtRnNkV1U3WEc0Z0lIMWNibHh1SUNCd2NtOWpaWE56WDJKcGJtRnllU2gyWVd4MVpTbDdYRzRnSUNBZ2NtVjBkWEp1SUVKcGRGTjBjbWx1Wnk1MGIxVlVSamhCY25KaGVTaDJZV3gxWlM1MllXeDFaU2s3WEc0Z0lIMWNibHh1SUNCd2NtOWpaWE56WDNWMFpqZ29kbUZzZFdVcGUxeHVJQ0FnSUhKbGRIVnliaUJDYVhSVGRISnBibWN1ZEc5VlZFWTRRWEp5WVhrb2RtRnNkV1V1ZG1Gc2RXVXBPMXh1SUNCOVhHNWNiaUFnY0hKdlkyVnpjMTkxZEdZeE5paDJZV3gxWlNsN1hHNGdJQ0FnY21WMGRYSnVJRUpwZEZOMGNtbHVaeTUwYjFWVVJqRTJRWEp5WVhrb2RtRnNkV1V1ZG1Gc2RXVXBPMXh1SUNCOVhHNWNiaUFnY0hKdlkyVnpjMTkxZEdZek1paDJZV3gxWlNsN1hHNGdJQ0FnY21WMGRYSnVJRUpwZEZOMGNtbHVaeTUwYjFWVVJqTXlRWEp5WVhrb2RtRnNkV1V1ZG1Gc2RXVXBPMXh1SUNCOVhHNWNiaUFnY0hKdlkyVnpjMTl6YVdkdVpXUW9kbUZzZFdVcGUxeHVJQ0FnSUhKbGRIVnliaUFvYm1WM0lGVnBiblE0UVhKeVlYa29XM1poYkhWbFhTa3BXekJkTzF4dUlDQjlYRzVjYmlBZ2NISnZZMlZ6YzE5MWJuTnBaMjVsWkNoMllXeDFaU2w3WEc0Z0lDQWdjbVYwZFhKdUlIWmhiSFZsTzF4dUlDQjlYRzVjYmlBZ2NISnZZMlZ6YzE5dVlYUnBkbVVvZG1Gc2RXVXBlMXh1SUNBZ0lISmxkSFZ5YmlCMllXeDFaVHRjYmlBZ2ZWeHVYRzRnSUhCeWIyTmxjM05mWW1sbktIWmhiSFZsS1h0Y2JpQWdJQ0J5WlhSMWNtNGdkbUZzZFdVN1hHNGdJSDFjYmx4dUlDQndjbTlqWlhOelgyeHBkSFJzWlNoMllXeDFaU2w3WEc0Z0lDQWdjbVYwZFhKdUlIWmhiSFZsTG5KbGRtVnljMlVvS1R0Y2JpQWdmVnh1WEc0Z0lIQnliMk5sYzNOZmMybDZaU2gyWVd4MVpTbDdYRzRnSUNBZ2NtVjBkWEp1SUhaaGJIVmxPMXh1SUNCOVhHNWNiaUFnY0hKdlkyVnpjMTkxYm1sMEtIWmhiSFZsS1h0Y2JpQWdJQ0J5WlhSMWNtNGdkbUZzZFdVN1hHNGdJSDFjYmx4dUlDQnpkR0YwYVdNZ2FXNTBaV2RsY2loMllXeDFaU2w3WEc0Z0lDQWdjbVYwZFhKdUlFSnBkRk4wY21sdVp5NTNjbUZ3S0haaGJIVmxMQ0I3SUNkMGVYQmxKem9nSjJsdWRHVm5aWEluTENBbmRXNXBkQ2M2SURFc0lDZHphWHBsSnpvZ09DQjlLVHRjYmlBZ2ZWeHVYRzRnSUhOMFlYUnBZeUJtYkc5aGRDaDJZV3gxWlNsN1hHNGdJQ0FnY21WMGRYSnVJRUpwZEZOMGNtbHVaeTUzY21Gd0tIWmhiSFZsTENCN0lDZDBlWEJsSnpvZ0oyWnNiMkYwSnl3Z0ozVnVhWFFuT2lBeExDQW5jMmw2WlNjNklEWTBJSDBwTzF4dUlDQjlYRzVjYmlBZ2MzUmhkR2xqSUdKcGRITjBjbWx1WnloMllXeDFaU2w3WEc0Z0lDQWdjbVYwZFhKdUlFSnBkRk4wY21sdVp5NTNjbUZ3S0haaGJIVmxMQ0I3SUNkMGVYQmxKem9nSjJKcGRITjBjbWx1Wnljc0lDZDFibWwwSnpvZ01Td2dKM05wZW1Vbk9pQjJZV3gxWlM1aWFYUmZjMmw2WlNCOUtUdGNiaUFnZlZ4dVhHNGdJSE4wWVhScFl5QmlhWFJ6S0haaGJIVmxLWHRjYmlBZ0lDQnlaWFIxY200Z1FtbDBVM1J5YVc1bkxtSnBkSE4wY21sdVp5aDJZV3gxWlNrN1hHNGdJSDFjYmx4dUlDQnpkR0YwYVdNZ1ltbHVZWEo1S0haaGJIVmxLWHRjYmlBZ0lDQnlaWFIxY200Z1FtbDBVM1J5YVc1bkxuZHlZWEFvZG1Gc2RXVXNJSHNnSjNSNWNHVW5PaUFuWW1sdVlYSjVKeXdnSjNWdWFYUW5PaUE0TENBbmMybDZaU2M2SUhaaGJIVmxMbXhsYm1kMGFDQjlLVHRjYmlBZ2ZWeHVYRzRnSUhOMFlYUnBZeUJpZVhSbGN5aDJZV3gxWlNsN1hHNGdJQ0FnY21WMGRYSnVJRUpwZEZOMGNtbHVaeTVpYVc1aGNua29kbUZzZFdVcE8xeHVJQ0I5WEc1Y2JpQWdjM1JoZEdsaklIVjBaamdvZG1Gc2RXVXBlMXh1SUNBZ0lISmxkSFZ5YmlCQ2FYUlRkSEpwYm1jdWQzSmhjQ2gyWVd4MVpTd2dleUFuZEhsd1pTYzZJQ2QxZEdZNEp5QjlLVHRjYmlBZ2ZWeHVYRzRnSUhOMFlYUnBZeUIxZEdZeE5paDJZV3gxWlNsN1hHNGdJQ0FnY21WMGRYSnVJRUpwZEZOMGNtbHVaeTUzY21Gd0tIWmhiSFZsTENCN0lDZDBlWEJsSnpvZ0ozVjBaakUySnlCOUtUdGNiaUFnZlZ4dVhHNGdJSE4wWVhScFl5QjFkR1l6TWloMllXeDFaU2w3WEc0Z0lDQWdjbVYwZFhKdUlFSnBkRk4wY21sdVp5NTNjbUZ3S0haaGJIVmxMQ0I3SUNkMGVYQmxKem9nSjNWMFpqTXlKeUI5S1R0Y2JpQWdmVnh1WEc0Z0lITjBZWFJwWXlCemFXZHVaV1FvZG1Gc2RXVXBlMXh1SUNBZ0lISmxkSFZ5YmlCQ2FYUlRkSEpwYm1jdWQzSmhjQ2gyWVd4MVpTd2dlMzBzSUNkemFXZHVaV1FuS1R0Y2JpQWdmVnh1WEc0Z0lITjBZWFJwWXlCMWJuTnBaMjVsWkNoMllXeDFaU2w3WEc0Z0lDQWdjbVYwZFhKdUlFSnBkRk4wY21sdVp5NTNjbUZ3S0haaGJIVmxMQ0I3ZlN3Z0ozVnVjMmxuYm1Wa0p5azdYRzRnSUgxY2JseHVJQ0J6ZEdGMGFXTWdibUYwYVhabEtIWmhiSFZsS1h0Y2JpQWdJQ0J5WlhSMWNtNGdRbWwwVTNSeWFXNW5MbmR5WVhBb2RtRnNkV1VzSUh0OUxDQW5ibUYwYVhabEp5azdYRzRnSUgxY2JseHVJQ0J6ZEdGMGFXTWdZbWxuS0haaGJIVmxLWHRjYmlBZ0lDQnlaWFIxY200Z1FtbDBVM1J5YVc1bkxuZHlZWEFvZG1Gc2RXVXNJSHQ5TENBblltbG5KeWs3WEc0Z0lIMWNibHh1SUNCemRHRjBhV01nYkdsMGRHeGxLSFpoYkhWbEtYdGNiaUFnSUNCeVpYUjFjbTRnUW1sMFUzUnlhVzVuTG5keVlYQW9kbUZzZFdVc0lIdDlMQ0FuYkdsMGRHeGxKeWs3WEc0Z0lIMWNibHh1SUNCemRHRjBhV01nYzJsNlpTaDJZV3gxWlN3Z1kyOTFiblFwZTF4dUlDQWdJSEpsZEhWeWJpQkNhWFJUZEhKcGJtY3VkM0poY0NoMllXeDFaU3dnZXlkemFYcGxKem9nWTI5MWJuUjlLVHRjYmlBZ2ZWeHVYRzRnSUhOMFlYUnBZeUIxYm1sMEtIWmhiSFZsTENCamIzVnVkQ2w3WEc0Z0lDQWdjbVYwZFhKdUlFSnBkRk4wY21sdVp5NTNjbUZ3S0haaGJIVmxMQ0I3SjNWdWFYUW5PaUJqYjNWdWRIMHBPMXh1SUNCOVhHNWNiaUFnYzNSaGRHbGpJSGR5WVhBb2RtRnNkV1VzSUc5d2RDd2dibVYzWDJGMGRISnBZblYwWlNBOUlHNTFiR3dwZTF4dUlDQWdJR3hsZENCMGFHVmZkbUZzZFdVZ1BTQjJZV3gxWlR0Y2JseHVJQ0FnSUdsbUtDRW9kbUZzZFdVZ2FXNXpkR0Z1WTJWdlppQlBZbXBsWTNRcEtYdGNiaUFnSUNBZ0lIUm9aVjkyWVd4MVpTQTlJSHNuZG1Gc2RXVW5PaUIyWVd4MVpTd2dKMkYwZEhKcFluVjBaWE1uT2lCYlhYMDdYRzRnSUNBZ2ZWeHVYRzRnSUNBZ2RHaGxYM1poYkhWbElEMGdUMkpxWldOMExtRnpjMmxuYmloMGFHVmZkbUZzZFdVc0lHOXdkQ2s3WEc1Y2JpQWdJQ0JwWmlodVpYZGZZWFIwY21saWRYUmxLWHRjYmlBZ0lDQWdJSFJvWlY5MllXeDFaUzVoZEhSeWFXSjFkR1Z6TG5CMWMyZ29ibVYzWDJGMGRISnBZblYwWlNrN1hHNGdJQ0FnZlZ4dVhHNWNiaUFnSUNCeVpYUjFjbTRnZEdobFgzWmhiSFZsTzF4dUlDQjlYRzVjYmlBZ2MzUmhkR2xqSUhSdlZWUkdPRUZ5Y21GNUtITjBjaWtnZTF4dUlDQWdJSFpoY2lCMWRHWTRJRDBnVzEwN1hHNGdJQ0FnWm05eUlDaDJZWElnYVNBOUlEQTdJR2tnUENCemRISXViR1Z1WjNSb095QnBLeXNwSUh0Y2JpQWdJQ0FnSUhaaGNpQmphR0Z5WTI5a1pTQTlJSE4wY2k1amFHRnlRMjlrWlVGMEtHa3BPMXh1SUNBZ0lDQWdhV1lnS0dOb1lYSmpiMlJsSUR3Z01IZzRNQ2w3WEc0Z0lDQWdJQ0FnSUhWMFpqZ3VjSFZ6YUNoamFHRnlZMjlrWlNrN1hHNGdJQ0FnSUNCOVhHNGdJQ0FnSUNCbGJITmxJR2xtSUNoamFHRnlZMjlrWlNBOElEQjRPREF3S1NCN1hHNGdJQ0FnSUNBZ0lIVjBaamd1Y0hWemFDZ3dlR013SUh3Z0tHTm9ZWEpqYjJSbElENCtJRFlwTEZ4dUlDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ01IZzRNQ0I4SUNoamFHRnlZMjlrWlNBbUlEQjRNMllwS1R0Y2JpQWdJQ0FnSUgxY2JpQWdJQ0FnSUdWc2MyVWdhV1lnS0dOb1lYSmpiMlJsSUR3Z01IaGtPREF3SUh4OElHTm9ZWEpqYjJSbElENDlJREI0WlRBd01Da2dlMXh1SUNBZ0lDQWdJQ0IxZEdZNExuQjFjMmdvTUhobE1DQjhJQ2hqYUdGeVkyOWtaU0ErUGlBeE1pa3NYRzRnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0F3ZURnd0lId2dLQ2hqYUdGeVkyOWtaU0ErUGlBMktTQW1JREI0TTJZcExGeHVJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdNSGc0TUNCOElDaGphR0Z5WTI5a1pTQW1JREI0TTJZcEtUdGNiaUFnSUNBZ0lIMWNiaUFnSUNBZ0lDOHZJSE4xY25KdloyRjBaU0J3WVdseVhHNGdJQ0FnSUNCbGJITmxJSHRjYmlBZ0lDQWdJQ0FnYVNzck8xeHVJQ0FnSUNBZ0lDQXZMeUJWVkVZdE1UWWdaVzVqYjJSbGN5QXdlREV3TURBd0xUQjRNVEJHUmtaR0lHSjVYRzRnSUNBZ0lDQWdJQzh2SUhOMVluUnlZV04wYVc1bklEQjRNVEF3TURBZ1lXNWtJSE53YkdsMGRHbHVaeUIwYUdWY2JpQWdJQ0FnSUNBZ0x5OGdNakFnWW1sMGN5QnZaaUF3ZURBdE1IaEdSa1pHUmlCcGJuUnZJSFIzYnlCb1lXeDJaWE5jYmlBZ0lDQWdJQ0FnWTJoaGNtTnZaR1VnUFNBd2VERXdNREF3SUNzZ0tDZ29ZMmhoY21OdlpHVWdKaUF3ZURObVppa2dQRHdnTVRBcFhHNGdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQjhJQ2h6ZEhJdVkyaGhja052WkdWQmRDaHBLU0FtSURCNE0yWm1LU2s3WEc0Z0lDQWdJQ0FnSUhWMFpqZ3VjSFZ6YUNnd2VHWXdJSHdnS0dOb1lYSmpiMlJsSUQ0K0lERTRLU3hjYmlBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSURCNE9EQWdmQ0FvS0dOb1lYSmpiMlJsSUQ0K0lERXlLU0FtSURCNE0yWXBMRnh1SUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnTUhnNE1DQjhJQ2dvWTJoaGNtTnZaR1VnUGo0Z05pa2dKaUF3ZURObUtTeGNiaUFnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJREI0T0RBZ2ZDQW9ZMmhoY21OdlpHVWdKaUF3ZURObUtTazdYRzRnSUNBZ0lDQjlYRzRnSUNBZ2ZWeHVJQ0FnSUhKbGRIVnliaUIxZEdZNE8xeHVJQ0I5WEc1Y2JpQWdjM1JoZEdsaklIUnZWVlJHTVRaQmNuSmhlU2h6ZEhJcElIdGNiaUFnSUNCMllYSWdkWFJtTVRZZ1BTQmJYVHRjYmlBZ0lDQm1iM0lnS0haaGNpQnBJRDBnTURzZ2FTQThJSE4wY2k1c1pXNW5kR2c3SUdrckt5a2dlMXh1SUNBZ0lDQWdkbUZ5SUdOdlpHVlFiMmx1ZENBOUlITjBjaTVqYjJSbFVHOXBiblJCZENocEtUdGNibHh1SUNBZ0lDQWdhV1lvWTI5a1pWQnZhVzUwSUR3OUlESTFOU2w3WEc0Z0lDQWdJQ0FnSUhWMFpqRTJMbkIxYzJnb01DazdYRzRnSUNBZ0lDQWdJSFYwWmpFMkxuQjFjMmdvWTI5a1pWQnZhVzUwS1R0Y2JpQWdJQ0FnSUgxbGJITmxlMXh1SUNBZ0lDQWdJQ0IxZEdZeE5pNXdkWE5vS0Nnb1kyOWtaVkJ2YVc1MElENCtJRGdwSUNZZ01IaEdSaWtwTzF4dUlDQWdJQ0FnSUNCMWRHWXhOaTV3ZFhOb0tDaGpiMlJsVUc5cGJuUWdKaUF3ZUVaR0tTazdYRzRnSUNBZ0lDQjlYRzRnSUNBZ2ZWeHVJQ0FnSUhKbGRIVnliaUIxZEdZeE5qdGNiaUFnZlZ4dVhHNWNiaUFnYzNSaGRHbGpJSFJ2VlZSR016SkJjbkpoZVNoemRISXBJSHRjYmlBZ0lDQjJZWElnZFhSbU16SWdQU0JiWFR0Y2JpQWdJQ0JtYjNJZ0tIWmhjaUJwSUQwZ01Ec2dhU0E4SUhOMGNpNXNaVzVuZEdnN0lHa3JLeWtnZTF4dUlDQWdJQ0FnZG1GeUlHTnZaR1ZRYjJsdWRDQTlJSE4wY2k1amIyUmxVRzlwYm5SQmRDaHBLVHRjYmx4dUlDQWdJQ0FnYVdZb1kyOWtaVkJ2YVc1MElEdzlJREkxTlNsN1hHNGdJQ0FnSUNBZ0lIVjBaak15TG5CMWMyZ29NQ2s3WEc0Z0lDQWdJQ0FnSUhWMFpqTXlMbkIxYzJnb01DazdYRzRnSUNBZ0lDQWdJSFYwWmpNeUxuQjFjMmdvTUNrN1hHNGdJQ0FnSUNBZ0lIVjBaak15TG5CMWMyZ29ZMjlrWlZCdmFXNTBLVHRjYmlBZ0lDQWdJSDFsYkhObGUxeHVJQ0FnSUNBZ0lDQjFkR1l6TWk1d2RYTm9LREFwTzF4dUlDQWdJQ0FnSUNCMWRHWXpNaTV3ZFhOb0tEQXBPMXh1SUNBZ0lDQWdJQ0IxZEdZek1pNXdkWE5vS0Nnb1kyOWtaVkJ2YVc1MElENCtJRGdwSUNZZ01IaEdSaWtwTzF4dUlDQWdJQ0FnSUNCMWRHWXpNaTV3ZFhOb0tDaGpiMlJsVUc5cGJuUWdKaUF3ZUVaR0tTazdYRzRnSUNBZ0lDQjlYRzRnSUNBZ2ZWeHVJQ0FnSUhKbGRIVnliaUIxZEdZek1qdGNiaUFnZlZ4dVhHNGdJQzh2YUhSMGNEb3ZMM04wWVdOcmIzWmxjbVpzYjNjdVkyOXRMM0YxWlhOMGFXOXVjeTh5TURBek5Ea3pMMnBoZG1GelkzSnBjSFF0Wm14dllYUXRabkp2YlMxMGJ5MWlhWFJ6WEc0Z0lITjBZWFJwWXlCbWJHOWhkRE15Vkc5Q2VYUmxjeWhtS1NCN1hHNGdJQ0FnZG1GeUlHSjVkR1Z6SUQwZ1cxMDdYRzVjYmlBZ0lDQjJZWElnWW5WbUlEMGdibVYzSUVGeWNtRjVRblZtWm1WeUtEUXBPMXh1SUNBZ0lDaHVaWGNnUm14dllYUXpNa0Z5Y21GNUtHSjFaaWtwV3pCZElEMGdaanRjYmx4dUlDQWdJR3hsZENCcGJuUldaWEp6YVc5dUlEMGdLRzVsZHlCVmFXNTBNekpCY25KaGVTaGlkV1lwS1Zzd1hUdGNibHh1SUNBZ0lHSjVkR1Z6TG5CMWMyZ29LQ2hwYm5SV1pYSnphVzl1SUQ0K0lESTBLU0FtSURCNFJrWXBLVHRjYmlBZ0lDQmllWFJsY3k1d2RYTm9LQ2dvYVc1MFZtVnljMmx2YmlBK1BpQXhOaWtnSmlBd2VFWkdLU2s3WEc0Z0lDQWdZbmwwWlhNdWNIVnphQ2dvS0dsdWRGWmxjbk5wYjI0Z1BqNGdPQ2tnSmlBd2VFWkdLU2s3WEc0Z0lDQWdZbmwwWlhNdWNIVnphQ2dvYVc1MFZtVnljMmx2YmlBbUlEQjRSa1lwS1R0Y2JseHVJQ0FnSUhKbGRIVnliaUJpZVhSbGN6dGNiaUFnZlZ4dVhHNGdJSE4wWVhScFl5Qm1iRzloZERZMFZHOUNlWFJsY3lobUtTQjdYRzRnSUNBZ2RtRnlJR0o1ZEdWeklEMGdXMTA3WEc1Y2JpQWdJQ0IyWVhJZ1luVm1JRDBnYm1WM0lFRnljbUY1UW5WbVptVnlLRGdwTzF4dUlDQWdJQ2h1WlhjZ1JteHZZWFEyTkVGeWNtRjVLR0oxWmlrcFd6QmRJRDBnWmp0Y2JseHVJQ0FnSUhaaGNpQnBiblJXWlhKemFXOXVNU0E5SUNodVpYY2dWV2x1ZERNeVFYSnlZWGtvWW5WbUtTbGJNRjA3WEc0Z0lDQWdkbUZ5SUdsdWRGWmxjbk5wYjI0eUlEMGdLRzVsZHlCVmFXNTBNekpCY25KaGVTaGlkV1lwS1ZzeFhUdGNibHh1SUNBZ0lHSjVkR1Z6TG5CMWMyZ29LQ2hwYm5SV1pYSnphVzl1TWlBK1BpQXlOQ2tnSmlBd2VFWkdLU2s3WEc0Z0lDQWdZbmwwWlhNdWNIVnphQ2dvS0dsdWRGWmxjbk5wYjI0eUlENCtJREUyS1NBbUlEQjRSa1lwS1R0Y2JpQWdJQ0JpZVhSbGN5NXdkWE5vS0Nnb2FXNTBWbVZ5YzJsdmJqSWdQajRnT0NrZ0ppQXdlRVpHS1NrN1hHNGdJQ0FnWW5sMFpYTXVjSFZ6YUNnb2FXNTBWbVZ5YzJsdmJqSWdKaUF3ZUVaR0tTazdYRzVjYmlBZ0lDQmllWFJsY3k1d2RYTm9LQ2dvYVc1MFZtVnljMmx2YmpFZ1BqNGdNalFwSUNZZ01IaEdSaWtwTzF4dUlDQWdJR0o1ZEdWekxuQjFjMmdvS0NocGJuUldaWEp6YVc5dU1TQStQaUF4TmlrZ0ppQXdlRVpHS1NrN1hHNGdJQ0FnWW5sMFpYTXVjSFZ6YUNnb0tHbHVkRlpsY25OcGIyNHhJRDQrSURncElDWWdNSGhHUmlrcE8xeHVJQ0FnSUdKNWRHVnpMbkIxYzJnb0tHbHVkRlpsY25OcGIyNHhJQ1lnTUhoR1Jpa3BPMXh1WEc0Z0lDQWdjbVYwZFhKdUlHSjVkR1Z6TzF4dUlDQjlYRzU5WEc1Y2JtVjRjRzl5ZENCa1pXWmhkV3gwSUVKcGRGTjBjbWx1Wnp0Y2JpSmRMQ0p6YjNWeVkyVlNiMjkwSWpvaUwzTnZkWEpqWlM4aWZRPT1cbiIsIlxuZXhwb3J0IGNsYXNzIFZhcmlhYmxlIHtcblxuICBjb25zdHJ1Y3RvcihuYW1lID0gbnVsbCkge1xuICAgIHRoaXMubmFtZSA9IG5hbWU7XG4gIH1cbn1cblxuZXhwb3J0IGNsYXNzIFdpbGRjYXJkIHtcbiAgY29uc3RydWN0b3IoKSB7fVxufVxuXG5leHBvcnQgY2xhc3MgU3RhcnRzV2l0aCB7XG5cbiAgY29uc3RydWN0b3IocHJlZml4KSB7XG4gICAgdGhpcy5wcmVmaXggPSBwcmVmaXg7XG4gIH1cbn1cblxuZXhwb3J0IGNsYXNzIENhcHR1cmUge1xuXG4gIGNvbnN0cnVjdG9yKHZhbHVlKSB7XG4gICAgdGhpcy52YWx1ZSA9IHZhbHVlO1xuICB9XG59XG5cbmV4cG9ydCBjbGFzcyBIZWFkVGFpbCB7XG5cbiAgY29uc3RydWN0b3IoaGVhZCA9IG51bGwsIHRhaWwgPSBudWxsKSB7XG4gICAgdGhpcy5oZWFkID0gaGVhZDtcbiAgICB0aGlzLnRhaWwgPSB0YWlsO1xuICB9XG59XG5cbmV4cG9ydCBjbGFzcyBUeXBlIHtcblxuICBjb25zdHJ1Y3Rvcih0eXBlLCBvYmpQYXR0ZXJuID0ge30pIHtcbiAgICB0aGlzLnR5cGUgPSB0eXBlO1xuICAgIHRoaXMub2JqUGF0dGVybiA9IG9ialBhdHRlcm47XG4gIH1cbn1cblxuZXhwb3J0IGNsYXNzIEJvdW5kIHtcblxuICBjb25zdHJ1Y3Rvcih2YWx1ZSkge1xuICAgIHRoaXMudmFsdWUgPSB2YWx1ZTtcbiAgfVxufVxuXG5leHBvcnQgZnVuY3Rpb24gdmFyaWFibGUobmFtZSA9IG51bGwpIHtcbiAgcmV0dXJuIG5ldyBWYXJpYWJsZShuYW1lKTtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIHdpbGRjYXJkKCkge1xuICByZXR1cm4gbmV3IFdpbGRjYXJkKCk7XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBzdGFydHNXaXRoKHByZWZpeCkge1xuICByZXR1cm4gbmV3IFN0YXJ0c1dpdGgocHJlZml4KTtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIGNhcHR1cmUodmFsdWUpIHtcbiAgcmV0dXJuIG5ldyBDYXB0dXJlKHZhbHVlKTtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIGhlYWRUYWlsKGhlYWQgPSBudWxsLCB0YWlsID0gbnVsbCkge1xuICByZXR1cm4gbmV3IEhlYWRUYWlsKGhlYWQsIHRhaWwpO1xufVxuXG5leHBvcnQgZnVuY3Rpb24gdHlwZSh0eXBlLCBvYmpQYXR0ZXJuID0ge30pIHtcbiAgcmV0dXJuIG5ldyBUeXBlKHR5cGUsIG9ialBhdHRlcm4pO1xufVxuXG5leHBvcnQgZnVuY3Rpb24gYm91bmQodmFsdWUpIHtcbiAgcmV0dXJuIG5ldyBCb3VuZCh2YWx1ZSk7XG59XG4vLyMgc291cmNlTWFwcGluZ1VSTD1kYXRhOmFwcGxpY2F0aW9uL2pzb247YmFzZTY0LGV5SjJaWEp6YVc5dUlqb3pMQ0p6YjNWeVkyVnpJanBiSW14cFlpOWpiM0psTDNCaGRIUmxjbTV6TDNSNWNHVnpMbXB6SWwwc0ltNWhiV1Z6SWpwYlhTd2liV0Z3Y0dsdVozTWlPaUk3UVVGRFFTeFBRVUZQTEUxQlFVMHNVVUZCVGl4RFFVRmxPenRCUVVkd1FpeGpRVUV3UWl4UFFVRkZMRWxCUVVZc1JVRkJVVHRCUVVOb1F5eFRRVUZMTEVsQlFVd3NSMEZCV1N4SlFVRmFMRU5CUkdkRE8wZEJRV3hETzBOQlNFczdPMEZCVVZBc1QwRkJUeXhOUVVGTkxGRkJRVTRzUTBGQlpUdEJRVU53UWl4blFrRkJZeXhGUVVGa08wTkJSRXM3TzBGQlMxQXNUMEZCVHl4TlFVRk5MRlZCUVU0c1EwRkJhVUk3TzBGQlIzUkNMR05CUVZrc1RVRkJXaXhGUVVFMFFqdEJRVU14UWl4VFFVRkxMRTFCUVV3c1IwRkJZeXhOUVVGa0xFTkJSREJDTzBkQlFUVkNPME5CU0VzN08wRkJVVkFzVDBGQlR5eE5RVUZOTEU5QlFVNHNRMEZCWXpzN1FVRkhia0lzWTBGQldTeExRVUZhTEVWQlFYZENPMEZCUTNSQ0xGTkJRVXNzUzBGQlRDeEhRVUZoTEV0QlFXSXNRMEZFYzBJN1IwRkJlRUk3UTBGSVN6czdRVUZSVUN4UFFVRlBMRTFCUVUwc1VVRkJUaXhEUVVGbE96dEJRVWx3UWl4alFVRnpRaXhQUVVGRkxFbEJRVVlzUlVGQmEwSXNUMEZCUlN4SlFVRkdMRVZCUVZFN1FVRkRPVU1zVTBGQlN5eEpRVUZNTEVkQlFWa3NTVUZCV2l4RFFVUTRRenRCUVVVNVF5eFRRVUZMTEVsQlFVd3NSMEZCV1N4SlFVRmFMRU5CUmpoRE8wZEJRV2hFTzBOQlNrczdPMEZCVlZBc1QwRkJUeXhOUVVGTkxFbEJRVTRzUTBGQlZ6czdRVUZKYUVJc1kwRkJXU3hKUVVGYUxFVkJRVEJETEdGQlFVVXNSVUZCUml4RlFVRk5PMEZCUXpsRExGTkJRVXNzU1VGQlRDeEhRVUZaTEVsQlFWb3NRMEZFT0VNN1FVRkZPVU1zVTBGQlN5eFZRVUZNTEVkQlFXdENMRlZCUVd4Q0xFTkJSamhETzBkQlFXaEVPME5CU2tzN08wRkJWVkFzVDBGQlR5eE5RVUZOTEV0QlFVNHNRMEZCV1RzN1FVRkhha0lzWTBGQldTeExRVUZhTEVWQlFYZENPMEZCUTNSQ0xGTkJRVXNzUzBGQlRDeEhRVUZoTEV0QlFXSXNRMEZFYzBJN1IwRkJlRUk3UTBGSVN6czdRVUZSVUN4UFFVRlBMRk5CUVZNc1VVRkJWQ3hEUVVGblF5eFBRVUZGTEVsQlFVWXNSVUZCYTBJN1FVRkRka1FzVTBGQlR5eEpRVUZKTEZGQlFVb3NRMEZCWVN4SlFVRmlMRU5CUVZBc1EwRkVkVVE3UTBGQmJFUTdPMEZCU1ZBc1QwRkJUeXhUUVVGVExGRkJRVlFzUjBGQk9FSTdRVUZEYmtNc1UwRkJUeXhKUVVGSkxGRkJRVW9zUlVGQlVDeERRVVJ0UXp0RFFVRTVRanM3UVVGSlVDeFBRVUZQTEZOQlFWTXNWVUZCVkN4RFFVRnZRaXhOUVVGd1FpeEZRVUZuUkR0QlFVTnlSQ3hUUVVGUExFbEJRVWtzVlVGQlNpeERRVUZsTEUxQlFXWXNRMEZCVUN4RFFVUnhSRHREUVVGb1JEczdRVUZKVUN4UFFVRlBMRk5CUVZNc1QwRkJWQ3hEUVVGcFFpeExRVUZxUWl4RlFVRnpRenRCUVVNelF5eFRRVUZQTEVsQlFVa3NUMEZCU2l4RFFVRlpMRXRCUVZvc1EwRkJVQ3hEUVVReVF6dERRVUYwUXpzN1FVRkpVQ3hQUVVGUExGTkJRVk1zVVVGQlZDeERRVUUwUWl4UFFVRkZMRWxCUVVZc1JVRkJhMElzVDBGQlJTeEpRVUZHTEVWQlFXdENPMEZCUTNKRkxGTkJRVThzU1VGQlNTeFJRVUZLTEVOQlFXRXNTVUZCWWl4RlFVRnRRaXhKUVVGdVFpeERRVUZRTEVOQlJIRkZPME5CUVdoRk96dEJRVWxRTEU5QlFVOHNVMEZCVXl4SlFVRlVMRU5CUVdNc1NVRkJaQ3hGUVVFMFF5eGhRVUZGTEVWQlFVWXNSVUZCV1R0QlFVTTNSQ3hUUVVGUExFbEJRVWtzU1VGQlNpeERRVUZUTEVsQlFWUXNSVUZCWlN4VlFVRm1MRU5CUVZBc1EwRkVOa1E3UTBGQmVFUTdPMEZCU1ZBc1QwRkJUeXhUUVVGVExFdEJRVlFzUTBGQlpTeExRVUZtTEVWQlFXdERPMEZCUTNaRExGTkJRVThzU1VGQlNTeExRVUZLTEVOQlFWVXNTMEZCVml4RFFVRlFMRU5CUkhWRE8wTkJRV3hESWl3aVptbHNaU0k2SW14cFlpOWpiM0psTDNCaGRIUmxjbTV6TDNSNWNHVnpMbXB6SWl3aWMyOTFjbU5sYzBOdmJuUmxiblFpT2xzaUx5b2dRR1pzYjNjZ0tpOWNibVY0Y0c5eWRDQmpiR0Z6Y3lCV1lYSnBZV0pzWlNCN1hHNGdJRzVoYldVNklEOXpkSEpwYm1jN1hHNWNiaUFnWTI5dWMzUnlkV04wYjNJb2JtRnRaVG9nUDNOMGNtbHVaeUE5SUc1MWJHd3BJSHRjYmlBZ0lDQjBhR2x6TG01aGJXVWdQU0J1WVcxbE8xeHVJQ0I5WEc1OVhHNWNibVY0Y0c5eWRDQmpiR0Z6Y3lCWGFXeGtZMkZ5WkNCN1hHNGdJR052Ym5OMGNuVmpkRzl5S0NrZ2UxeHVJQ0I5WEc1OVhHNWNibVY0Y0c5eWRDQmpiR0Z6Y3lCVGRHRnlkSE5YYVhSb0lIdGNiaUFnY0hKbFptbDRPaUJ6ZEhKcGJtYzdYRzVjYmlBZ1kyOXVjM1J5ZFdOMGIzSW9jSEpsWm1sNE9pQnpkSEpwYm1jcElIdGNiaUFnSUNCMGFHbHpMbkJ5WldacGVDQTlJSEJ5WldacGVEdGNiaUFnZlZ4dWZWeHVYRzVsZUhCdmNuUWdZMnhoYzNNZ1EyRndkSFZ5WlNCN1hHNGdJSFpoYkhWbE9pQmhibms3WEc1Y2JpQWdZMjl1YzNSeWRXTjBiM0lvZG1Gc2RXVTZJR0Z1ZVNrZ2UxeHVJQ0FnSUhSb2FYTXVkbUZzZFdVZ1BTQjJZV3gxWlR0Y2JpQWdmVnh1ZlZ4dVhHNWxlSEJ2Y25RZ1kyeGhjM01nU0dWaFpGUmhhV3dnZTF4dUlDQm9aV0ZrT2lCaGJuazdYRzRnSUhSaGFXdzZJR0Z1ZVR0Y2JseHVJQ0JqYjI1emRISjFZM1J2Y2lob1pXRmtPaUJoYm5rZ1BTQnVkV3hzTENCMFlXbHNPaUJoYm5rZ1BTQnVkV3hzS1NCN1hHNGdJQ0FnZEdocGN5NW9aV0ZrSUQwZ2FHVmhaRHRjYmlBZ0lDQjBhR2x6TG5SaGFXd2dQU0IwWVdsc08xeHVJQ0I5WEc1OVhHNWNibVY0Y0c5eWRDQmpiR0Z6Y3lCVWVYQmxJSHRjYmlBZ2RIbHdaVG9nWVc1NU8xeHVJQ0J2WW1wUVlYUjBaWEp1T2lCUFltcGxZM1E3WEc1Y2JpQWdZMjl1YzNSeWRXTjBiM0lvZEhsd1pUb2dZVzU1TENCdlltcFFZWFIwWlhKdU9pQlBZbXBsWTNRZ1BTQjdmU2tnZTF4dUlDQWdJSFJvYVhNdWRIbHdaU0E5SUhSNWNHVmNiaUFnSUNCMGFHbHpMbTlpYWxCaGRIUmxjbTRnUFNCdlltcFFZWFIwWlhKdVhHNGdJSDFjYm4xY2JseHVaWGh3YjNKMElHTnNZWE56SUVKdmRXNWtJSHRjYmlBZ2RtRnNkV1U2SUdGdWVUdGNibHh1SUNCamIyNXpkSEoxWTNSdmNpaDJZV3gxWlRvZ1lXNTVLU0I3WEc0Z0lDQWdkR2hwY3k1MllXeDFaU0E5SUhaaGJIVmxPMXh1SUNCOVhHNTlYRzVjYm1WNGNHOXlkQ0JtZFc1amRHbHZiaUIyWVhKcFlXSnNaU2h1WVcxbE9pQS9jM1J5YVc1bklEMGdiblZzYkNrNklGWmhjbWxoWW14bElIdGNiaUFnY21WMGRYSnVJRzVsZHlCV1lYSnBZV0pzWlNodVlXMWxLVHRjYm4xY2JseHVaWGh3YjNKMElHWjFibU4wYVc5dUlIZHBiR1JqWVhKa0tDazZJRmRwYkdSallYSmtJSHRjYmlBZ2NtVjBkWEp1SUc1bGR5QlhhV3hrWTJGeVpDZ3BPMXh1ZlZ4dVhHNWxlSEJ2Y25RZ1puVnVZM1JwYjI0Z2MzUmhjblJ6VjJsMGFDaHdjbVZtYVhnNklITjBjbWx1WnlrNklGTjBZWEowYzFkcGRHZ2dlMXh1SUNCeVpYUjFjbTRnYm1WM0lGTjBZWEowYzFkcGRHZ29jSEpsWm1sNEtUdGNibjFjYmx4dVpYaHdiM0owSUdaMWJtTjBhVzl1SUdOaGNIUjFjbVVvZG1Gc2RXVTZJR0Z1ZVNrNklFTmhjSFIxY21VZ2UxeHVJQ0J5WlhSMWNtNGdibVYzSUVOaGNIUjFjbVVvZG1Gc2RXVXBPMXh1ZlZ4dVhHNWxlSEJ2Y25RZ1puVnVZM1JwYjI0Z2FHVmhaRlJoYVd3b2FHVmhaRG9nWVc1NUlEMGdiblZzYkN3Z2RHRnBiRG9nWVc1NUlEMGdiblZzYkNrNklFaGxZV1JVWVdsc0lIdGNiaUFnY21WMGRYSnVJRzVsZHlCSVpXRmtWR0ZwYkNob1pXRmtMQ0IwWVdsc0tUdGNibjFjYmx4dVpYaHdiM0owSUdaMWJtTjBhVzl1SUhSNWNHVW9kSGx3WlRvZ1lXNTVMQ0J2WW1wUVlYUjBaWEp1T2lCUFltcGxZM1FnUFNCN2ZTazZJRlI1Y0dVZ2UxeHVJQ0J5WlhSMWNtNGdibVYzSUZSNWNHVW9kSGx3WlN3Z2IySnFVR0YwZEdWeWJpazdYRzU5WEc1Y2JtVjRjRzl5ZENCbWRXNWpkR2x2YmlCaWIzVnVaQ2gyWVd4MVpUb2dZVzU1S1RvZ1FtOTFibVFnZTF4dUlDQnlaWFIxY200Z2JtVjNJRUp2ZFc1a0tIWmhiSFZsS1R0Y2JuMWNiaUpkTENKemIzVnlZMlZTYjI5MElqb2lMM052ZFhKalpTOGlmUT09XG4iLCJcblxuaW1wb3J0IHsgVmFyaWFibGUsIFdpbGRjYXJkLCBIZWFkVGFpbCwgQ2FwdHVyZSwgVHlwZSwgU3RhcnRzV2l0aCwgQm91bmQgfSBmcm9tIFwiLi90eXBlc1wiO1xuXG5mdW5jdGlvbiBpc19udW1iZXIodmFsdWUpIHtcbiAgcmV0dXJuIHR5cGVvZiB2YWx1ZSA9PT0gJ251bWJlcic7XG59XG5cbmZ1bmN0aW9uIGlzX3N0cmluZyh2YWx1ZSkge1xuICByZXR1cm4gdHlwZW9mIHZhbHVlID09PSAnc3RyaW5nJztcbn1cblxuZnVuY3Rpb24gaXNfYm9vbGVhbih2YWx1ZSkge1xuICByZXR1cm4gdHlwZW9mIHZhbHVlID09PSAnYm9vbGVhbic7XG59XG5cbmZ1bmN0aW9uIGlzX3N5bWJvbCh2YWx1ZSkge1xuICByZXR1cm4gdHlwZW9mIHZhbHVlID09PSAnc3ltYm9sJztcbn1cblxuZnVuY3Rpb24gaXNfbnVsbCh2YWx1ZSkge1xuICByZXR1cm4gdmFsdWUgPT09IG51bGw7XG59XG5cbmZ1bmN0aW9uIGlzX3VuZGVmaW5lZCh2YWx1ZSkge1xuICByZXR1cm4gdHlwZW9mIHZhbHVlID09PSAndW5kZWZpbmVkJztcbn1cblxuZnVuY3Rpb24gaXNfZnVuY3Rpb24odmFsdWUpIHtcbiAgcmV0dXJuIE9iamVjdC5wcm90b3R5cGUudG9TdHJpbmcuY2FsbCh2YWx1ZSkgPT0gJ1tvYmplY3QgRnVuY3Rpb25dJztcbn1cblxuZnVuY3Rpb24gaXNfdmFyaWFibGUodmFsdWUpIHtcbiAgcmV0dXJuIHZhbHVlIGluc3RhbmNlb2YgVmFyaWFibGU7XG59XG5cbmZ1bmN0aW9uIGlzX3dpbGRjYXJkKHZhbHVlKSB7XG4gIHJldHVybiB2YWx1ZSBpbnN0YW5jZW9mIFdpbGRjYXJkO1xufVxuXG5mdW5jdGlvbiBpc19oZWFkVGFpbCh2YWx1ZSkge1xuICByZXR1cm4gdmFsdWUgaW5zdGFuY2VvZiBIZWFkVGFpbDtcbn1cblxuZnVuY3Rpb24gaXNfY2FwdHVyZSh2YWx1ZSkge1xuICByZXR1cm4gdmFsdWUgaW5zdGFuY2VvZiBDYXB0dXJlO1xufVxuXG5mdW5jdGlvbiBpc190eXBlKHZhbHVlKSB7XG4gIHJldHVybiB2YWx1ZSBpbnN0YW5jZW9mIFR5cGU7XG59XG5cbmZ1bmN0aW9uIGlzX3N0YXJ0c1dpdGgodmFsdWUpIHtcbiAgcmV0dXJuIHZhbHVlIGluc3RhbmNlb2YgU3RhcnRzV2l0aDtcbn1cblxuZnVuY3Rpb24gaXNfYm91bmQodmFsdWUpIHtcbiAgcmV0dXJuIHZhbHVlIGluc3RhbmNlb2YgQm91bmQ7XG59XG5cbmZ1bmN0aW9uIGlzX29iamVjdCh2YWx1ZSkge1xuICByZXR1cm4gdHlwZW9mIHZhbHVlID09PSAnb2JqZWN0Jztcbn1cblxuZnVuY3Rpb24gaXNfYXJyYXkodmFsdWUpIHtcbiAgcmV0dXJuIEFycmF5LmlzQXJyYXkodmFsdWUpO1xufVxuXG5leHBvcnQgZGVmYXVsdCB7XG4gIGlzX251bWJlcixcbiAgaXNfc3RyaW5nLFxuICBpc19ib29sZWFuLFxuICBpc19zeW1ib2wsXG4gIGlzX251bGwsXG4gIGlzX3VuZGVmaW5lZCxcbiAgaXNfZnVuY3Rpb24sXG4gIGlzX3ZhcmlhYmxlLFxuICBpc193aWxkY2FyZCxcbiAgaXNfaGVhZFRhaWwsXG4gIGlzX2NhcHR1cmUsXG4gIGlzX3R5cGUsXG4gIGlzX3N0YXJ0c1dpdGgsXG4gIGlzX2JvdW5kLFxuICBpc19vYmplY3QsXG4gIGlzX2FycmF5XG59O1xuLy8jIHNvdXJjZU1hcHBpbmdVUkw9ZGF0YTphcHBsaWNhdGlvbi9qc29uO2Jhc2U2NCxleUoyWlhKemFXOXVJam96TENKemIzVnlZMlZ6SWpwYklteHBZaTlqYjNKbEwzQmhkSFJsY201ekwyTm9aV05yY3k1cWN5SmRMQ0p1WVcxbGN5STZXMTBzSW0xaGNIQnBibWR6SWpvaU96dEJRVVZCTEZOQlFWTXNVVUZCVkN4RlFVRnRRaXhSUVVGdVFpeEZRVUUyUWl4UlFVRTNRaXhGUVVGMVF5eFBRVUYyUXl4RlFVRm5SQ3hKUVVGb1JDeEZRVUZ6UkN4VlFVRjBSQ3hGUVVGclJTeExRVUZzUlN4UlFVRXJSU3hUUVVFdlJUczdRVUZGUVN4VFFVRlRMRk5CUVZRc1EwRkJiVUlzUzBGQmJrSXNSVUZCZDBNN1FVRkRkRU1zVTBGQlR5eFBRVUZQTEV0QlFWQXNTMEZCYVVJc1VVRkJha0lzUTBGRUswSTdRMEZCZUVNN08wRkJTVUVzVTBGQlV5eFRRVUZVTEVOQlFXMUNMRXRCUVc1Q0xFVkJRWFZETzBGQlEzSkRMRk5CUVU4c1QwRkJUeXhMUVVGUUxFdEJRV2xDTEZGQlFXcENMRU5CUkRoQ08wTkJRWFpET3p0QlFVbEJMRk5CUVZNc1ZVRkJWQ3hEUVVGdlFpeExRVUZ3UWl4RlFVRjVRenRCUVVOMlF5eFRRVUZQTEU5QlFVOHNTMEZCVUN4TFFVRnBRaXhUUVVGcVFpeERRVVJuUXp0RFFVRjZRenM3UVVGSlFTeFRRVUZUTEZOQlFWUXNRMEZCYlVJc1MwRkJia0lzUlVGQmQwTTdRVUZEZEVNc1UwRkJUeXhQUVVGUExFdEJRVkFzUzBGQmFVSXNVVUZCYWtJc1EwRkVLMEk3UTBGQmVFTTdPMEZCU1VFc1UwRkJVeXhQUVVGVUxFTkJRV2xDTEV0QlFXcENMRVZCUVhORE8wRkJRM0JETEZOQlFVOHNWVUZCVlN4SlFVRldMRU5CUkRaQ08wTkJRWFJET3p0QlFVbEJMRk5CUVZNc1dVRkJWQ3hEUVVGelFpeExRVUYwUWl4RlFVRXlRenRCUVVONlF5eFRRVUZQTEU5QlFVOHNTMEZCVUN4TFFVRnBRaXhYUVVGcVFpeERRVVJyUXp0RFFVRXpRenM3UVVGSlFTeFRRVUZUTEZkQlFWUXNRMEZCY1VJc1MwRkJja0lzUlVGQk1FTTdRVUZEZUVNc1UwRkJUeXhQUVVGUExGTkJRVkFzUTBGQmFVSXNVVUZCYWtJc1EwRkJNRUlzU1VGQk1VSXNRMEZCSzBJc1MwRkJMMElzUzBGQmVVTXNiVUpCUVhwRExFTkJSR2xETzBOQlFURkRPenRCUVVsQkxGTkJRVk1zVjBGQlZDeERRVUZ4UWl4TFFVRnlRaXhGUVVFd1F6dEJRVU40UXl4VFFVRlBMR2xDUVVGcFFpeFJRVUZxUWl4RFFVUnBRenREUVVFeFF6czdRVUZKUVN4VFFVRlRMRmRCUVZRc1EwRkJjVUlzUzBGQmNrSXNSVUZCTUVNN1FVRkRlRU1zVTBGQlR5eHBRa0ZCYVVJc1VVRkJha0lzUTBGRWFVTTdRMEZCTVVNN08wRkJTVUVzVTBGQlV5eFhRVUZVTEVOQlFYRkNMRXRCUVhKQ0xFVkJRVEJETzBGQlEzaERMRk5CUVU4c2FVSkJRV2xDTEZGQlFXcENMRU5CUkdsRE8wTkJRVEZET3p0QlFVbEJMRk5CUVZNc1ZVRkJWQ3hEUVVGdlFpeExRVUZ3UWl4RlFVRjVRenRCUVVOMlF5eFRRVUZQTEdsQ1FVRnBRaXhQUVVGcVFpeERRVVJuUXp0RFFVRjZRenM3UVVGSlFTeFRRVUZUTEU5QlFWUXNRMEZCYVVJc1MwRkJha0lzUlVGQmMwTTdRVUZEY0VNc1UwRkJUeXhwUWtGQmFVSXNTVUZCYWtJc1EwRkVOa0k3UTBGQmRFTTdPMEZCU1VFc1UwRkJVeXhoUVVGVUxFTkJRWFZDTEV0QlFYWkNMRVZCUVRSRE8wRkJRekZETEZOQlFVOHNhVUpCUVdsQ0xGVkJRV3BDTEVOQlJHMURPME5CUVRWRE96dEJRVWxCTEZOQlFWTXNVVUZCVkN4RFFVRnJRaXhMUVVGc1FpeEZRVUYxUXp0QlFVTnlReXhUUVVGUExHbENRVUZwUWl4TFFVRnFRaXhEUVVRNFFqdERRVUYyUXpzN1FVRkpRU3hUUVVGVExGTkJRVlFzUTBGQmJVSXNTMEZCYmtJc1JVRkJkME03UVVGRGRFTXNVMEZCVHl4UFFVRlBMRXRCUVZBc1MwRkJhVUlzVVVGQmFrSXNRMEZFSzBJN1EwRkJlRU03TzBGQlNVRXNVMEZCVXl4UlFVRlVMRU5CUVd0Q0xFdEJRV3hDTEVWQlFYVkRPMEZCUTNKRExGTkJRVThzVFVGQlRTeFBRVUZPTEVOQlFXTXNTMEZCWkN4RFFVRlFMRU5CUkhGRE8wTkJRWFpET3p0QlFVbEJMR1ZCUVdVN1FVRkRZaXhYUVVSaE8wRkJSV0lzVjBGR1lUdEJRVWRpTEZsQlNHRTdRVUZKWWl4WFFVcGhPMEZCUzJJc1UwRk1ZVHRCUVUxaUxHTkJUbUU3UVVGUFlpeGhRVkJoTzBGQlVXSXNZVUZTWVR0QlFWTmlMR0ZCVkdFN1FVRlZZaXhoUVZaaE8wRkJWMklzV1VGWVlUdEJRVmxpTEZOQldtRTdRVUZoWWl4bFFXSmhPMEZCWTJJc1ZVRmtZVHRCUVdWaUxGZEJabUU3UVVGblFtSXNWVUZvUW1FN1EwRkJaaUlzSW1acGJHVWlPaUpzYVdJdlkyOXlaUzl3WVhSMFpYSnVjeTlqYUdWamEzTXVhbk1pTENKemIzVnlZMlZ6UTI5dWRHVnVkQ0k2V3lJdktpQkFabXh2ZHlBcUwxeHVYRzVwYlhCdmNuUWdleUJXWVhKcFlXSnNaU3dnVjJsc1pHTmhjbVFzSUVobFlXUlVZV2xzTENCRFlYQjBkWEpsTENCVWVYQmxMQ0JUZEdGeWRITlhhWFJvTENCQ2IzVnVaQ0I5SUdaeWIyMGdYQ0l1TDNSNWNHVnpYQ0k3WEc1Y2JtWjFibU4wYVc5dUlHbHpYMjUxYldKbGNpaDJZV3gxWlRvZ1lXNTVLVG9nWW05dmJHVmhiaUI3WEc0Z0lISmxkSFZ5YmlCMGVYQmxiMllnZG1Gc2RXVWdQVDA5SUNkdWRXMWlaWEluTzF4dWZWeHVYRzVtZFc1amRHbHZiaUJwYzE5emRISnBibWNvZG1Gc2RXVTZJR0Z1ZVNrNklHSnZiMnhsWVc1N1hHNGdJSEpsZEhWeWJpQjBlWEJsYjJZZ2RtRnNkV1VnUFQwOUlDZHpkSEpwYm1jbk8xeHVmVnh1WEc1bWRXNWpkR2x2YmlCcGMxOWliMjlzWldGdUtIWmhiSFZsT2lCaGJua3BPaUJpYjI5c1pXRnVJSHRjYmlBZ2NtVjBkWEp1SUhSNWNHVnZaaUIyWVd4MVpTQTlQVDBnSjJKdmIyeGxZVzRuTzF4dWZWeHVYRzVtZFc1amRHbHZiaUJwYzE5emVXMWliMndvZG1Gc2RXVTZJR0Z1ZVNrNklHSnZiMnhsWVc0Z2UxeHVJQ0J5WlhSMWNtNGdkSGx3Wlc5bUlIWmhiSFZsSUQwOVBTQW5jM2x0WW05c0p6dGNibjFjYmx4dVpuVnVZM1JwYjI0Z2FYTmZiblZzYkNoMllXeDFaVG9nWVc1NUtUb2dZbTl2YkdWaGJpQjdYRzRnSUhKbGRIVnliaUIyWVd4MVpTQTlQVDBnYm5Wc2JEdGNibjFjYmx4dVpuVnVZM1JwYjI0Z2FYTmZkVzVrWldacGJtVmtLSFpoYkhWbE9pQmhibmtwT2lCaWIyOXNaV0Z1SUh0Y2JpQWdjbVYwZFhKdUlIUjVjR1Z2WmlCMllXeDFaU0E5UFQwZ0ozVnVaR1ZtYVc1bFpDYzdYRzU5WEc1Y2JtWjFibU4wYVc5dUlHbHpYMloxYm1OMGFXOXVLSFpoYkhWbE9pQmhibmtwT2lCaWIyOXNaV0Z1SUh0Y2JpQWdjbVYwZFhKdUlFOWlhbVZqZEM1d2NtOTBiM1I1Y0dVdWRHOVRkSEpwYm1jdVkyRnNiQ2gyWVd4MVpTa2dQVDBnSjF0dlltcGxZM1FnUm5WdVkzUnBiMjVkSnp0Y2JuMWNibHh1Wm5WdVkzUnBiMjRnYVhOZmRtRnlhV0ZpYkdVb2RtRnNkV1U2SUdGdWVTazZJR0p2YjJ4bFlXNGdlMXh1SUNCeVpYUjFjbTRnZG1Gc2RXVWdhVzV6ZEdGdVkyVnZaaUJXWVhKcFlXSnNaVHRjYm4xY2JseHVablZ1WTNScGIyNGdhWE5mZDJsc1pHTmhjbVFvZG1Gc2RXVTZJR0Z1ZVNrNklHSnZiMnhsWVc0Z2UxeHVJQ0J5WlhSMWNtNGdkbUZzZFdVZ2FXNXpkR0Z1WTJWdlppQlhhV3hrWTJGeVpEdGNibjFjYmx4dVpuVnVZM1JwYjI0Z2FYTmZhR1ZoWkZSaGFXd29kbUZzZFdVNklHRnVlU2s2SUdKdmIyeGxZVzRnZTF4dUlDQnlaWFIxY200Z2RtRnNkV1VnYVc1emRHRnVZMlZ2WmlCSVpXRmtWR0ZwYkR0Y2JuMWNibHh1Wm5WdVkzUnBiMjRnYVhOZlkyRndkSFZ5WlNoMllXeDFaVG9nWVc1NUtUb2dZbTl2YkdWaGJpQjdYRzRnSUhKbGRIVnliaUIyWVd4MVpTQnBibk4wWVc1alpXOW1JRU5oY0hSMWNtVTdYRzU5WEc1Y2JtWjFibU4wYVc5dUlHbHpYM1I1Y0dVb2RtRnNkV1U2SUdGdWVTazZJR0p2YjJ4bFlXNGdlMXh1SUNCeVpYUjFjbTRnZG1Gc2RXVWdhVzV6ZEdGdVkyVnZaaUJVZVhCbE8xeHVmVnh1WEc1bWRXNWpkR2x2YmlCcGMxOXpkR0Z5ZEhOWGFYUm9LSFpoYkhWbE9pQmhibmtwT2lCaWIyOXNaV0Z1SUh0Y2JpQWdjbVYwZFhKdUlIWmhiSFZsSUdsdWMzUmhibU5sYjJZZ1UzUmhjblJ6VjJsMGFEdGNibjFjYmx4dVpuVnVZM1JwYjI0Z2FYTmZZbTkxYm1Rb2RtRnNkV1U2SUdGdWVTazZJR0p2YjJ4bFlXNGdlMXh1SUNCeVpYUjFjbTRnZG1Gc2RXVWdhVzV6ZEdGdVkyVnZaaUJDYjNWdVpEdGNibjFjYmx4dVpuVnVZM1JwYjI0Z2FYTmZiMkpxWldOMEtIWmhiSFZsT2lCaGJua3BPaUJpYjI5c1pXRnVJSHRjYmlBZ2NtVjBkWEp1SUhSNWNHVnZaaUIyWVd4MVpTQTlQVDBnSjI5aWFtVmpkQ2M3WEc1OVhHNWNibVoxYm1OMGFXOXVJR2x6WDJGeWNtRjVLSFpoYkhWbE9pQmhibmtwT2lCaWIyOXNaV0Z1SUh0Y2JpQWdjbVYwZFhKdUlFRnljbUY1TG1selFYSnlZWGtvZG1Gc2RXVXBPMXh1ZlZ4dVhHNWxlSEJ2Y25RZ1pHVm1ZWFZzZENCN1hHNGdJR2x6WDI1MWJXSmxjaXhjYmlBZ2FYTmZjM1J5YVc1bkxGeHVJQ0JwYzE5aWIyOXNaV0Z1TEZ4dUlDQnBjMTl6ZVcxaWIyd3NYRzRnSUdselgyNTFiR3dzWEc0Z0lHbHpYM1Z1WkdWbWFXNWxaQ3hjYmlBZ2FYTmZablZ1WTNScGIyNHNYRzRnSUdselgzWmhjbWxoWW14bExGeHVJQ0JwYzE5M2FXeGtZMkZ5WkN4Y2JpQWdhWE5mYUdWaFpGUmhhV3dzWEc0Z0lHbHpYMk5oY0hSMWNtVXNYRzRnSUdselgzUjVjR1VzWEc0Z0lHbHpYM04wWVhKMGMxZHBkR2dzWEc0Z0lHbHpYMkp2ZFc1a0xGeHVJQ0JwYzE5dlltcGxZM1FzWEc0Z0lHbHpYMkZ5Y21GNVhHNTlPMXh1SWwwc0luTnZkWEpqWlZKdmIzUWlPaUl2YzI5MWNtTmxMeUo5XG4iLCJcblxuaW1wb3J0IENoZWNrcyBmcm9tIFwiLi9jaGVja3NcIjtcbmltcG9ydCAqIGFzIFR5cGVzIGZyb20gXCIuL3R5cGVzXCI7XG5pbXBvcnQgeyBidWlsZE1hdGNoIH0gZnJvbSBcIi4vbWF0Y2hcIjtcblxuZnVuY3Rpb24gcmVzb2x2ZVN5bWJvbChwYXR0ZXJuKSB7XG4gIHJldHVybiBmdW5jdGlvbiAodmFsdWUpIHtcbiAgICByZXR1cm4gQ2hlY2tzLmlzX3N5bWJvbCh2YWx1ZSkgJiYgdmFsdWUgPT09IHBhdHRlcm47XG4gIH07XG59XG5cbmZ1bmN0aW9uIHJlc29sdmVTdHJpbmcocGF0dGVybikge1xuICByZXR1cm4gZnVuY3Rpb24gKHZhbHVlKSB7XG4gICAgcmV0dXJuIENoZWNrcy5pc19zdHJpbmcodmFsdWUpICYmIHZhbHVlID09PSBwYXR0ZXJuO1xuICB9O1xufVxuXG5mdW5jdGlvbiByZXNvbHZlTnVtYmVyKHBhdHRlcm4pIHtcbiAgcmV0dXJuIGZ1bmN0aW9uICh2YWx1ZSkge1xuICAgIHJldHVybiBDaGVja3MuaXNfbnVtYmVyKHZhbHVlKSAmJiB2YWx1ZSA9PT0gcGF0dGVybjtcbiAgfTtcbn1cblxuZnVuY3Rpb24gcmVzb2x2ZUJvb2xlYW4ocGF0dGVybikge1xuICByZXR1cm4gZnVuY3Rpb24gKHZhbHVlKSB7XG4gICAgcmV0dXJuIENoZWNrcy5pc19ib29sZWFuKHZhbHVlKSAmJiB2YWx1ZSA9PT0gcGF0dGVybjtcbiAgfTtcbn1cblxuZnVuY3Rpb24gcmVzb2x2ZUZ1bmN0aW9uKHBhdHRlcm4pIHtcbiAgcmV0dXJuIGZ1bmN0aW9uICh2YWx1ZSkge1xuICAgIHJldHVybiBDaGVja3MuaXNfZnVuY3Rpb24odmFsdWUpICYmIHZhbHVlID09PSBwYXR0ZXJuO1xuICB9O1xufVxuXG5mdW5jdGlvbiByZXNvbHZlTnVsbChwYXR0ZXJuKSB7XG4gIHJldHVybiBmdW5jdGlvbiAodmFsdWUpIHtcbiAgICByZXR1cm4gQ2hlY2tzLmlzX251bGwodmFsdWUpO1xuICB9O1xufVxuXG5mdW5jdGlvbiByZXNvbHZlQm91bmQocGF0dGVybikge1xuICByZXR1cm4gZnVuY3Rpb24gKHZhbHVlLCBhcmdzKSB7XG4gICAgaWYgKHR5cGVvZiB2YWx1ZSA9PT0gdHlwZW9mIHBhdHRlcm4udmFsdWUgJiYgdmFsdWUgPT09IHBhdHRlcm4udmFsdWUpIHtcbiAgICAgIGFyZ3MucHVzaCh2YWx1ZSk7XG4gICAgICByZXR1cm4gdHJ1ZTtcbiAgICB9XG5cbiAgICByZXR1cm4gZmFsc2U7XG4gIH07XG59XG5cbmZ1bmN0aW9uIHJlc29sdmVXaWxkY2FyZCgpIHtcbiAgcmV0dXJuIGZ1bmN0aW9uICgpIHtcbiAgICByZXR1cm4gdHJ1ZTtcbiAgfTtcbn1cblxuZnVuY3Rpb24gcmVzb2x2ZVZhcmlhYmxlKCkge1xuICByZXR1cm4gZnVuY3Rpb24gKHZhbHVlLCBhcmdzKSB7XG4gICAgYXJncy5wdXNoKHZhbHVlKTtcbiAgICByZXR1cm4gdHJ1ZTtcbiAgfTtcbn1cblxuZnVuY3Rpb24gcmVzb2x2ZUhlYWRUYWlsKHBhdHRlcm4pIHtcbiAgY29uc3QgaGVhZE1hdGNoZXMgPSBidWlsZE1hdGNoKHBhdHRlcm4uaGVhZCk7XG4gIGNvbnN0IHRhaWxNYXRjaGVzID0gYnVpbGRNYXRjaChwYXR0ZXJuLnRhaWwpO1xuXG4gIHJldHVybiBmdW5jdGlvbiAodmFsdWUsIGFyZ3MpIHtcbiAgICBpZiAoIUNoZWNrcy5pc19hcnJheSh2YWx1ZSkgfHwgdmFsdWUubGVuZ3RoIDwgMikge1xuICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH1cblxuICAgIGNvbnN0IGhlYWQgPSB2YWx1ZVswXTtcbiAgICBjb25zdCB0YWlsID0gdmFsdWUuc2xpY2UoMSk7XG5cbiAgICBpZiAoaGVhZE1hdGNoZXMoaGVhZCwgYXJncykgJiYgdGFpbE1hdGNoZXModGFpbCwgYXJncykpIHtcbiAgICAgIHJldHVybiB0cnVlO1xuICAgIH1cbiAgfTtcbn1cblxuZnVuY3Rpb24gcmVzb2x2ZUNhcHR1cmUocGF0dGVybikge1xuICBjb25zdCBtYXRjaGVzID0gYnVpbGRNYXRjaChwYXR0ZXJuLnZhbHVlKTtcblxuICByZXR1cm4gZnVuY3Rpb24gKHZhbHVlLCBhcmdzKSB7XG4gICAgaWYgKG1hdGNoZXModmFsdWUsIGFyZ3MpKSB7XG4gICAgICBhcmdzLnB1c2godmFsdWUpO1xuICAgICAgcmV0dXJuIHRydWU7XG4gICAgfVxuXG4gICAgcmV0dXJuIGZhbHNlO1xuICB9O1xufVxuXG5mdW5jdGlvbiByZXNvbHZlU3RhcnRzV2l0aChwYXR0ZXJuKSB7XG4gIGNvbnN0IHByZWZpeCA9IHBhdHRlcm4ucHJlZml4O1xuXG4gIHJldHVybiBmdW5jdGlvbiAodmFsdWUsIGFyZ3MpIHtcbiAgICBpZiAoQ2hlY2tzLmlzX3N0cmluZyh2YWx1ZSkgJiYgdmFsdWUuc3RhcnRzV2l0aChwcmVmaXgpKSB7XG4gICAgICBhcmdzLnB1c2godmFsdWUuc3Vic3RyaW5nKHByZWZpeC5sZW5ndGgpKTtcbiAgICAgIHJldHVybiB0cnVlO1xuICAgIH1cblxuICAgIHJldHVybiBmYWxzZTtcbiAgfTtcbn1cblxuZnVuY3Rpb24gcmVzb2x2ZVR5cGUocGF0dGVybikge1xuICByZXR1cm4gZnVuY3Rpb24gKHZhbHVlLCBhcmdzKSB7XG4gICAgaWYgKHZhbHVlIGluc3RhbmNlb2YgcGF0dGVybi50eXBlKSB7XG4gICAgICBjb25zdCBtYXRjaGVzID0gYnVpbGRNYXRjaChwYXR0ZXJuLm9ialBhdHRlcm4pO1xuICAgICAgcmV0dXJuIG1hdGNoZXModmFsdWUsIGFyZ3MpICYmIGFyZ3MucHVzaCh2YWx1ZSkgPiAwO1xuICAgIH1cblxuICAgIHJldHVybiBmYWxzZTtcbiAgfTtcbn1cblxuZnVuY3Rpb24gcmVzb2x2ZUFycmF5KHBhdHRlcm4pIHtcbiAgY29uc3QgbWF0Y2hlcyA9IHBhdHRlcm4ubWFwKHggPT4gYnVpbGRNYXRjaCh4KSk7XG5cbiAgcmV0dXJuIGZ1bmN0aW9uICh2YWx1ZSwgYXJncykge1xuICAgIGlmICghQ2hlY2tzLmlzX2FycmF5KHZhbHVlKSB8fCB2YWx1ZS5sZW5ndGggIT0gcGF0dGVybi5sZW5ndGgpIHtcbiAgICAgIHJldHVybiBmYWxzZTtcbiAgICB9XG5cbiAgICByZXR1cm4gdmFsdWUuZXZlcnkoZnVuY3Rpb24gKHYsIGkpIHtcbiAgICAgIHJldHVybiBtYXRjaGVzW2ldKHZhbHVlW2ldLCBhcmdzKTtcbiAgICB9KTtcbiAgfTtcbn1cblxuZnVuY3Rpb24gcmVzb2x2ZU9iamVjdChwYXR0ZXJuKSB7XG4gIGxldCBtYXRjaGVzID0ge307XG5cbiAgZm9yIChsZXQga2V5IG9mIE9iamVjdC5rZXlzKHBhdHRlcm4pLmNvbmNhdChPYmplY3QuZ2V0T3duUHJvcGVydHlTeW1ib2xzKHBhdHRlcm4pKSkge1xuICAgIG1hdGNoZXNba2V5XSA9IGJ1aWxkTWF0Y2gocGF0dGVybltrZXldKTtcbiAgfVxuXG4gIHJldHVybiBmdW5jdGlvbiAodmFsdWUsIGFyZ3MpIHtcbiAgICBpZiAoIUNoZWNrcy5pc19vYmplY3QodmFsdWUpIHx8IHBhdHRlcm4ubGVuZ3RoID4gdmFsdWUubGVuZ3RoKSB7XG4gICAgICByZXR1cm4gZmFsc2U7XG4gICAgfVxuXG4gICAgZm9yIChsZXQga2V5IG9mIE9iamVjdC5rZXlzKHBhdHRlcm4pLmNvbmNhdChPYmplY3QuZ2V0T3duUHJvcGVydHlTeW1ib2xzKHBhdHRlcm4pKSkge1xuICAgICAgaWYgKCEoa2V5IGluIHZhbHVlKSB8fCAhbWF0Y2hlc1trZXldKHZhbHVlW2tleV0sIGFyZ3MpKSB7XG4gICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICByZXR1cm4gdHJ1ZTtcbiAgfTtcbn1cblxuZnVuY3Rpb24gcmVzb2x2ZU5vTWF0Y2goKSB7XG4gIHJldHVybiBmdW5jdGlvbiAoKSB7XG4gICAgcmV0dXJuIGZhbHNlO1xuICB9O1xufVxuXG5leHBvcnQgZGVmYXVsdCB7XG4gIHJlc29sdmVCb3VuZCxcbiAgcmVzb2x2ZVdpbGRjYXJkLFxuICByZXNvbHZlVmFyaWFibGUsXG4gIHJlc29sdmVIZWFkVGFpbCxcbiAgcmVzb2x2ZUNhcHR1cmUsXG4gIHJlc29sdmVTdGFydHNXaXRoLFxuICByZXNvbHZlVHlwZSxcbiAgcmVzb2x2ZUFycmF5LFxuICByZXNvbHZlT2JqZWN0LFxuICByZXNvbHZlTm9NYXRjaCxcbiAgcmVzb2x2ZVN5bWJvbCxcbiAgcmVzb2x2ZVN0cmluZyxcbiAgcmVzb2x2ZU51bWJlcixcbiAgcmVzb2x2ZUJvb2xlYW4sXG4gIHJlc29sdmVGdW5jdGlvbixcbiAgcmVzb2x2ZU51bGxcbn07XG4vLyMgc291cmNlTWFwcGluZ1VSTD1kYXRhOmFwcGxpY2F0aW9uL2pzb247YmFzZTY0LGV5SjJaWEp6YVc5dUlqb3pMQ0p6YjNWeVkyVnpJanBiSW14cFlpOWpiM0psTDNCaGRIUmxjbTV6TDNKbGMyOXNkbVZ5Y3k1cWN5SmRMQ0p1WVcxbGN5STZXMTBzSW0xaGNIQnBibWR6SWpvaU96dEJRVVZCTEU5QlFVOHNUVUZCVUN4TlFVRnRRaXhWUVVGdVFqdEJRVU5CTEU5QlFVOHNTMEZCU3l4TFFVRk1MRTFCUVdkQ0xGTkJRWFpDTzBGQlEwRXNVMEZCVXl4VlFVRlVMRkZCUVRKQ0xGTkJRVE5DT3p0QlFVVkJMRk5CUVZNc1lVRkJWQ3hEUVVGMVFpeFBRVUYyUWl4RlFVRXJRenRCUVVNM1F5eFRRVUZQTEZWQlFWTXNTMEZCVkN4RlFVRTRRanRCUVVOdVF5eFhRVUZQTEU5QlFVOHNVMEZCVUN4RFFVRnBRaXhMUVVGcVFpeExRVUV5UWl4VlFVRlZMRTlCUVZZc1EwRkVRenRIUVVFNVFpeERRVVJ6UXp0RFFVRXZRenM3UVVGTlFTeFRRVUZUTEdGQlFWUXNRMEZCZFVJc1QwRkJka0lzUlVGQkswTTdRVUZETjBNc1UwRkJUeXhWUVVGVExFdEJRVlFzUlVGQk9FSTdRVUZEYmtNc1YwRkJUeXhQUVVGUExGTkJRVkFzUTBGQmFVSXNTMEZCYWtJc1MwRkJNa0lzVlVGQlZTeFBRVUZXTEVOQlJFTTdSMEZCT1VJc1EwRkVjME03UTBGQkwwTTdPMEZCVFVFc1UwRkJVeXhoUVVGVUxFTkJRWFZDTEU5QlFYWkNMRVZCUVN0RE8wRkJRemRETEZOQlFVOHNWVUZCVXl4TFFVRlVMRVZCUVRoQ08wRkJRMjVETEZkQlFVOHNUMEZCVHl4VFFVRlFMRU5CUVdsQ0xFdEJRV3BDTEV0QlFUSkNMRlZCUVZVc1QwRkJWaXhEUVVSRE8wZEJRVGxDTEVOQlJITkRPME5CUVM5RE96dEJRVTFCTEZOQlFWTXNZMEZCVkN4RFFVRjNRaXhQUVVGNFFpeEZRVUZuUkR0QlFVTTVReXhUUVVGUExGVkJRVk1zUzBGQlZDeEZRVUU0UWp0QlFVTnVReXhYUVVGUExFOUJRVThzVlVGQlVDeERRVUZyUWl4TFFVRnNRaXhMUVVFMFFpeFZRVUZWTEU5QlFWWXNRMEZFUVR0SFFVRTVRaXhEUVVSMVF6dERRVUZvUkRzN1FVRk5RU3hUUVVGVExHVkJRVlFzUTBGQmVVSXNUMEZCZWtJc1JVRkJhVVE3UVVGREwwTXNVMEZCVHl4VlFVRlRMRXRCUVZRc1JVRkJPRUk3UVVGRGJrTXNWMEZCVHl4UFFVRlBMRmRCUVZBc1EwRkJiVUlzUzBGQmJrSXNTMEZCTmtJc1ZVRkJWU3hQUVVGV0xFTkJSRVE3UjBGQk9VSXNRMEZFZDBNN1EwRkJha1E3TzBGQlRVRXNVMEZCVXl4WFFVRlVMRU5CUVhGQ0xFOUJRWEpDTEVWQlFUWkRPMEZCUXpORExGTkJRVThzVlVGQlV5eExRVUZVTEVWQlFUaENPMEZCUTI1RExGZEJRVThzVDBGQlR5eFBRVUZRTEVOQlFXVXNTMEZCWml4RFFVRlFMRU5CUkcxRE8wZEJRVGxDTEVOQlJHOURPME5CUVRkRE96dEJRVTFCTEZOQlFWTXNXVUZCVkN4RFFVRnpRaXhQUVVGMFFpeEZRVUZ6UkR0QlFVTndSQ3hUUVVGUExGVkJRVk1zUzBGQlZDeEZRVUZ4UWl4SlFVRnlRaXhGUVVGblJEdEJRVU55UkN4UlFVRkhMRTlCUVU4c1MwRkJVQ3hMUVVGcFFpeFBRVUZQTEZGQlFWRXNTMEZCVWl4SlFVRnBRaXhWUVVGVkxGRkJRVkVzUzBGQlVpeEZRVUZqTzBGQlEyeEZMRmRCUVVzc1NVRkJUQ3hEUVVGVkxFdEJRVllzUlVGRWEwVTdRVUZGYkVVc1lVRkJUeXhKUVVGUUxFTkJSbXRGTzB0QlFYQkZPenRCUVV0QkxGZEJRVThzUzBGQlVDeERRVTV4UkR0SFFVRm9SQ3hEUVVRMlF6dERRVUYwUkRzN1FVRlhRU3hUUVVGVExHVkJRVlFzUjBGQmNVTTdRVUZEYmtNc1UwRkJUeXhaUVVGdlFqdEJRVU42UWl4WFFVRlBMRWxCUVZBc1EwRkVlVUk3UjBGQmNFSXNRMEZFTkVJN1EwRkJja003TzBGQlRVRXNVMEZCVXl4bFFVRlVMRWRCUVhGRE8wRkJRMjVETEZOQlFVOHNWVUZCVXl4TFFVRlVMRVZCUVhGQ0xFbEJRWEpDTEVWQlFXZEVPMEZCUTNKRUxGTkJRVXNzU1VGQlRDeERRVUZWTEV0QlFWWXNSVUZFY1VRN1FVRkZja1FzVjBGQlR5eEpRVUZRTEVOQlJuRkVPMGRCUVdoRUxFTkJSRFJDTzBOQlFYSkRPenRCUVU5QkxGTkJRVk1zWlVGQlZDeERRVUY1UWl4UFFVRjZRaXhGUVVFMFJEdEJRVU14UkN4UlFVRk5MR05CUVdNc1YwRkJWeXhSUVVGUkxFbEJRVklzUTBGQmVrSXNRMEZFYjBRN1FVRkZNVVFzVVVGQlRTeGpRVUZqTEZkQlFWY3NVVUZCVVN4SlFVRlNMRU5CUVhwQ0xFTkJSbTlFT3p0QlFVa3hSQ3hUUVVGUExGVkJRVk1zUzBGQlZDeEZRVUZ4UWl4SlFVRnlRaXhGUVVGblJEdEJRVU55UkN4UlFVRkhMRU5CUVVNc1QwRkJUeXhSUVVGUUxFTkJRV2RDTEV0QlFXaENMRU5CUVVRc1NVRkJNa0lzVFVGQlRTeE5RVUZPTEVkQlFXVXNRMEZCWml4RlFVRnBRanRCUVVNM1F5eGhRVUZQTEV0QlFWQXNRMEZFTmtNN1MwRkJMME03TzBGQlNVRXNWVUZCVFN4UFFVRlBMRTFCUVUwc1EwRkJUaXhEUVVGUUxFTkJUQ3RETzBGQlRYSkVMRlZCUVUwc1QwRkJUeXhOUVVGTkxFdEJRVTRzUTBGQldTeERRVUZhTEVOQlFWQXNRMEZPSzBNN08wRkJVWEpFTEZGQlFVY3NXVUZCV1N4SlFVRmFMRVZCUVd0Q0xFbEJRV3hDTEV0QlFUSkNMRmxCUVZrc1NVRkJXaXhGUVVGclFpeEpRVUZzUWl4RFFVRXpRaXhGUVVGdFJEdEJRVU53UkN4aFFVRlBMRWxCUVZBc1EwRkViMFE3UzBGQmRFUTdSMEZTU3l4RFFVcHRSRHREUVVFMVJEczdRVUZyUWtFc1UwRkJVeXhqUVVGVUxFTkJRWGRDTEU5QlFYaENMRVZCUVRCRU8wRkJRM2hFTEZGQlFVMHNWVUZCVlN4WFFVRlhMRkZCUVZFc1MwRkJVaXhEUVVGeVFpeERRVVJyUkRzN1FVRkhlRVFzVTBGQlR5eFZRVUZUTEV0QlFWUXNSVUZCY1VJc1NVRkJja0lzUlVGQlowUTdRVUZEY2tRc1VVRkJSeXhSUVVGUkxFdEJRVklzUlVGQlpTeEpRVUZtTEVOQlFVZ3NSVUZCZDBJN1FVRkRkRUlzVjBGQlN5eEpRVUZNTEVOQlFWVXNTMEZCVml4RlFVUnpRanRCUVVWMFFpeGhRVUZQTEVsQlFWQXNRMEZHYzBJN1MwRkJlRUk3TzBGQlMwRXNWMEZCVHl4TFFVRlFMRU5CVG5GRU8wZEJRV2hFTEVOQlNHbEVPME5CUVRGRU96dEJRV0ZCTEZOQlFWTXNhVUpCUVZRc1EwRkJNa0lzVDBGQk0wSXNSVUZCWjBVN1FVRkRPVVFzVVVGQlRTeFRRVUZUTEZGQlFWRXNUVUZCVWl4RFFVUXJRenM3UVVGSE9VUXNVMEZCVHl4VlFVRlRMRXRCUVZRc1JVRkJjVUlzU1VGQmNrSXNSVUZCWjBRN1FVRkRja1FzVVVGQlJ5eFBRVUZQTEZOQlFWQXNRMEZCYVVJc1MwRkJha0lzUzBGQk1rSXNUVUZCVFN4VlFVRk9MRU5CUVdsQ0xFMUJRV3BDTEVOQlFUTkNMRVZCUVc5RU8wRkJRM0pFTEZkQlFVc3NTVUZCVEN4RFFVRlZMRTFCUVUwc1UwRkJUaXhEUVVGblFpeFBRVUZQTEUxQlFWQXNRMEZCTVVJc1JVRkVjVVE3UVVGRmNrUXNZVUZCVHl4SlFVRlFMRU5CUm5GRU8wdEJRWFpFT3p0QlFVdEJMRmRCUVU4c1MwRkJVQ3hEUVU1eFJEdEhRVUZvUkN4RFFVaDFSRHREUVVGb1JUczdRVUZoUVN4VFFVRlRMRmRCUVZRc1EwRkJjVUlzVDBGQmNrSXNSVUZCYjBRN1FVRkRiRVFzVTBGQlR5eFZRVUZUTEV0QlFWUXNSVUZCY1VJc1NVRkJja0lzUlVGQlowUTdRVUZEY2tRc1VVRkJSeXhwUWtGQmFVSXNVVUZCVVN4SlFVRlNMRVZCUVdFN1FVRkRMMElzV1VGQlRTeFZRVUZWTEZkQlFWY3NVVUZCVVN4VlFVRlNMRU5CUVhKQ0xFTkJSSGxDTzBGQlJTOUNMR0ZCUVU4c1VVRkJVU3hMUVVGU0xFVkJRV1VzU1VGQlppeExRVUYzUWl4TFFVRkxMRWxCUVV3c1EwRkJWU3hMUVVGV0xFbEJRVzFDTEVOQlFXNUNMRU5CUmtFN1MwRkJha003TzBGQlMwRXNWMEZCVHl4TFFVRlFMRU5CVG5GRU8wZEJRV2hFTEVOQlJESkRPME5CUVhCRU96dEJRVmRCTEZOQlFWTXNXVUZCVkN4RFFVRnpRaXhQUVVGMFFpeEZRVUZ4UkR0QlFVTnVSQ3hSUVVGTkxGVkJRVlVzVVVGQlVTeEhRVUZTTEVOQlFWa3NTMEZCU3l4WFFVRlhMRU5CUVZnc1EwRkJUQ3hEUVVGMFFpeERRVVEyUXpzN1FVRkhia1FzVTBGQlR5eFZRVUZUTEV0QlFWUXNSVUZCY1VJc1NVRkJja0lzUlVGQlowUTdRVUZEY2tRc1VVRkJSeXhEUVVGRExFOUJRVThzVVVGQlVDeERRVUZuUWl4TFFVRm9RaXhEUVVGRUxFbEJRVEpDTEUxQlFVMHNUVUZCVGl4SlFVRm5RaXhSUVVGUkxFMUJRVklzUlVGQlpUdEJRVU16UkN4aFFVRlBMRXRCUVZBc1EwRkVNa1E3UzBGQk4wUTdPMEZCU1VFc1YwRkJUeXhOUVVGTkxFdEJRVTRzUTBGQldTeFZRVUZUTEVOQlFWUXNSVUZCV1N4RFFVRmFMRVZCUVdVN1FVRkRhRU1zWVVGQlR5eFJRVUZSTEVOQlFWSXNSVUZCVnl4TlFVRk5MRU5CUVU0c1EwRkJXQ3hGUVVGeFFpeEpRVUZ5UWl4RFFVRlFMRU5CUkdkRE8wdEJRV1lzUTBGQmJrSXNRMEZNY1VRN1IwRkJhRVFzUTBGSU5FTTdRMEZCY2tRN08wRkJZMEVzVTBGQlV5eGhRVUZVTEVOQlFYVkNMRTlCUVhaQ0xFVkJRV3RFTzBGQlEyaEVMRTFCUVVrc1ZVRkJWU3hGUVVGV0xFTkJSRFJET3p0QlFVZG9SQ3hQUVVGSkxFbEJRVWtzUjBGQlNpeEpRVUZYTEU5QlFVOHNTVUZCVUN4RFFVRlpMRTlCUVZvc1JVRkJjVUlzVFVGQmNrSXNRMEZCTkVJc1QwRkJUeXh4UWtGQlVDeERRVUUyUWl4UFFVRTNRaXhEUVVFMVFpeERRVUZtTEVWQlFXdEdPMEZCUTJoR0xGbEJRVkVzUjBGQlVpeEpRVUZsTEZkQlFWY3NVVUZCVVN4SFFVRlNMRU5CUVZnc1EwRkJaaXhEUVVSblJqdEhRVUZzUmpzN1FVRkpRU3hUUVVGUExGVkJRVk1zUzBGQlZDeEZRVUZ4UWl4SlFVRnlRaXhGUVVGblJEdEJRVU55UkN4UlFVRkhMRU5CUVVNc1QwRkJUeXhUUVVGUUxFTkJRV2xDTEV0QlFXcENMRU5CUVVRc1NVRkJORUlzVVVGQlVTeE5RVUZTTEVkQlFXbENMRTFCUVUwc1RVRkJUaXhGUVVGaE8wRkJRek5FTEdGQlFVOHNTMEZCVUN4RFFVUXlSRHRMUVVFM1JEczdRVUZKUVN4VFFVRkpMRWxCUVVrc1IwRkJTaXhKUVVGWExFOUJRVThzU1VGQlVDeERRVUZaTEU5QlFWb3NSVUZCY1VJc1RVRkJja0lzUTBGQk5FSXNUMEZCVHl4eFFrRkJVQ3hEUVVFMlFpeFBRVUUzUWl4RFFVRTFRaXhEUVVGbUxFVkJRV3RHTzBGQlEyaEdMRlZCUVVjc1JVRkJSU3hQUVVGUExFdEJRVkFzUTBGQlJpeEpRVUZ0UWl4RFFVRkRMRkZCUVZFc1IwRkJVaXhGUVVGaExFMUJRVTBzUjBGQlRpeERRVUZpTEVWQlFYbENMRWxCUVhwQ0xFTkJRVVFzUlVGQmFVTTdRVUZEY2tRc1pVRkJUeXhMUVVGUUxFTkJSSEZFTzA5QlFYWkVPMHRCUkVZN08wRkJUVUVzVjBGQlR5eEpRVUZRTEVOQldIRkVPMGRCUVdoRUxFTkJVSGxETzBOQlFXeEVPenRCUVhOQ1FTeFRRVUZUTEdOQlFWUXNSMEZCYjBNN1FVRkRiRU1zVTBGQlR5eFpRVUZ2UWp0QlFVTjZRaXhYUVVGUExFdEJRVkFzUTBGRWVVSTdSMEZCY0VJc1EwRkVNa0k3UTBGQmNFTTdPMEZCVFVFc1pVRkJaVHRCUVVOaUxHTkJSR0U3UVVGRllpeHBRa0ZHWVR0QlFVZGlMR2xDUVVoaE8wRkJTV0lzYVVKQlNtRTdRVUZMWWl4blFrRk1ZVHRCUVUxaUxHMUNRVTVoTzBGQlQySXNZVUZRWVR0QlFWRmlMR05CVW1FN1FVRlRZaXhsUVZSaE8wRkJWV0lzWjBKQlZtRTdRVUZYWWl4bFFWaGhPMEZCV1dJc1pVRmFZVHRCUVdGaUxHVkJZbUU3UVVGallpeG5Ra0ZrWVR0QlFXVmlMR2xDUVdaaE8wRkJaMEppTEdGQmFFSmhPME5CUVdZaUxDSm1hV3hsSWpvaWJHbGlMMk52Y21VdmNHRjBkR1Z5Ym5NdmNtVnpiMngyWlhKekxtcHpJaXdpYzI5MWNtTmxjME52Ym5SbGJuUWlPbHNpTHlvZ1FHWnNiM2NnS2k5Y2JseHVhVzF3YjNKMElFTm9aV05yY3lCbWNtOXRJRndpTGk5amFHVmphM05jSWp0Y2JtbHRjRzl5ZENBcUlHRnpJRlI1Y0dWeklHWnliMjBnWENJdUwzUjVjR1Z6WENJN1hHNXBiWEJ2Y25RZ2V5QmlkV2xzWkUxaGRHTm9JSDBnWm5KdmJTQmNJaTR2YldGMFkyaGNJanRjYmx4dVpuVnVZM1JwYjI0Z2NtVnpiMngyWlZONWJXSnZiQ2h3WVhSMFpYSnVPaUJoYm5rcE9pQkdkVzVqZEdsdmJpQjdYRzRnSUhKbGRIVnliaUJtZFc1amRHbHZiaWgyWVd4MVpUb2dZVzU1S1RvZ1ltOXZiR1ZoYmlCN1hHNGdJQ0FnY21WMGRYSnVJRU5vWldOcmN5NXBjMTl6ZVcxaWIyd29kbUZzZFdVcElDWW1JSFpoYkhWbElEMDlQU0J3WVhSMFpYSnVPMXh1SUNCOU8xeHVmVnh1WEc1bWRXNWpkR2x2YmlCeVpYTnZiSFpsVTNSeWFXNW5LSEJoZEhSbGNtNDZJR0Z1ZVNrNklFWjFibU4wYVc5dUlIdGNiaUFnY21WMGRYSnVJR1oxYm1OMGFXOXVLSFpoYkhWbE9pQmhibmtwT2lCaWIyOXNaV0Z1SUh0Y2JpQWdJQ0J5WlhSMWNtNGdRMmhsWTJ0ekxtbHpYM04wY21sdVp5aDJZV3gxWlNrZ0ppWWdkbUZzZFdVZ1BUMDlJSEJoZEhSbGNtNWNiaUFnZlR0Y2JuMWNibHh1Wm5WdVkzUnBiMjRnY21WemIyeDJaVTUxYldKbGNpaHdZWFIwWlhKdU9pQmhibmtwT2lCR2RXNWpkR2x2YmlCN1hHNGdJSEpsZEhWeWJpQm1kVzVqZEdsdmJpaDJZV3gxWlRvZ1lXNTVLVG9nWW05dmJHVmhiaUI3WEc0Z0lDQWdjbVYwZFhKdUlFTm9aV05yY3k1cGMxOXVkVzFpWlhJb2RtRnNkV1VwSUNZbUlIWmhiSFZsSUQwOVBTQndZWFIwWlhKdU8xeHVJQ0I5TzF4dWZWeHVYRzVtZFc1amRHbHZiaUJ5WlhOdmJIWmxRbTl2YkdWaGJpaHdZWFIwWlhKdU9pQmhibmtwT2lCR2RXNWpkR2x2YmlCN1hHNGdJSEpsZEhWeWJpQm1kVzVqZEdsdmJpaDJZV3gxWlRvZ1lXNTVLVG9nWW05dmJHVmhiaUI3WEc0Z0lDQWdjbVYwZFhKdUlFTm9aV05yY3k1cGMxOWliMjlzWldGdUtIWmhiSFZsS1NBbUppQjJZV3gxWlNBOVBUMGdjR0YwZEdWeWJseHVJQ0I5TzF4dWZWeHVYRzVtZFc1amRHbHZiaUJ5WlhOdmJIWmxSblZ1WTNScGIyNG9jR0YwZEdWeWJqb2dZVzU1S1RvZ1JuVnVZM1JwYjI0Z2UxeHVJQ0J5WlhSMWNtNGdablZ1WTNScGIyNG9kbUZzZFdVNklHRnVlU2s2SUdKdmIyeGxZVzRnZTF4dUlDQWdJSEpsZEhWeWJpQkRhR1ZqYTNNdWFYTmZablZ1WTNScGIyNG9kbUZzZFdVcElDWW1JSFpoYkhWbElEMDlQU0J3WVhSMFpYSnVYRzRnSUgwN1hHNTlYRzVjYm1aMWJtTjBhVzl1SUhKbGMyOXNkbVZPZFd4c0tIQmhkSFJsY200NklHRnVlU2s2SUVaMWJtTjBhVzl1SUh0Y2JpQWdjbVYwZFhKdUlHWjFibU4wYVc5dUtIWmhiSFZsT2lCaGJua3BPaUJpYjI5c1pXRnVJSHRjYmlBZ0lDQnlaWFIxY200Z1EyaGxZMnR6TG1selgyNTFiR3dvZG1Gc2RXVXBPMXh1SUNCOU8xeHVmVnh1WEc1bWRXNWpkR2x2YmlCeVpYTnZiSFpsUW05MWJtUW9jR0YwZEdWeWJqb2dWSGx3WlhNdVFtOTFibVFwT2lCR2RXNWpkR2x2YmlCN1hHNGdJSEpsZEhWeWJpQm1kVzVqZEdsdmJpaDJZV3gxWlRvZ1lXNTVMQ0JoY21kek9pQkJjbkpoZVR4aGJuaytLVG9nWW05dmJHVmhiaUI3WEc0Z0lDQWdhV1lvZEhsd1pXOW1JSFpoYkhWbElEMDlQU0IwZVhCbGIyWWdjR0YwZEdWeWJpNTJZV3gxWlNBbUppQjJZV3gxWlNBOVBUMGdjR0YwZEdWeWJpNTJZV3gxWlNsN1hHNGdJQ0FnSUNCaGNtZHpMbkIxYzJnb2RtRnNkV1VwTzF4dUlDQWdJQ0FnY21WMGRYSnVJSFJ5ZFdVN1hHNGdJQ0FnZlZ4dVhHNGdJQ0FnY21WMGRYSnVJR1poYkhObE8xeHVJQ0I5TzF4dWZWeHVYRzVtZFc1amRHbHZiaUJ5WlhOdmJIWmxWMmxzWkdOaGNtUW9LVG9nUm5WdVkzUnBiMjRnZTF4dUlDQnlaWFIxY200Z1puVnVZM1JwYjI0b0tUb2dZbTl2YkdWaGJpQjdYRzRnSUNBZ2NtVjBkWEp1SUhSeWRXVTdYRzRnSUgwN1hHNTlYRzVjYm1aMWJtTjBhVzl1SUhKbGMyOXNkbVZXWVhKcFlXSnNaU2dwT2lCR2RXNWpkR2x2YmlCN1hHNGdJSEpsZEhWeWJpQm1kVzVqZEdsdmJpaDJZV3gxWlRvZ1lXNTVMQ0JoY21kek9pQkJjbkpoZVR4aGJuaytLVG9nWW05dmJHVmhiaUI3WEc0Z0lDQWdZWEpuY3k1d2RYTm9LSFpoYkhWbEtUdGNiaUFnSUNCeVpYUjFjbTRnZEhKMVpUdGNiaUFnZlR0Y2JuMWNibHh1Wm5WdVkzUnBiMjRnY21WemIyeDJaVWhsWVdSVVlXbHNLSEJoZEhSbGNtNDZJRlI1Y0dWekxraGxZV1JVWVdsc0tUb2dSblZ1WTNScGIyNGdlMXh1SUNCamIyNXpkQ0JvWldGa1RXRjBZMmhsY3lBOUlHSjFhV3hrVFdGMFkyZ29jR0YwZEdWeWJpNW9aV0ZrS1R0Y2JpQWdZMjl1YzNRZ2RHRnBiRTFoZEdOb1pYTWdQU0JpZFdsc1pFMWhkR05vS0hCaGRIUmxjbTR1ZEdGcGJDazdYRzVjYmlBZ2NtVjBkWEp1SUdaMWJtTjBhVzl1S0haaGJIVmxPaUJoYm5rc0lHRnlaM002SUVGeWNtRjVQR0Z1ZVQ0cE9pQmliMjlzWldGdUlIdGNiaUFnSUNCcFppZ2hRMmhsWTJ0ekxtbHpYMkZ5Y21GNUtIWmhiSFZsS1NCOGZDQjJZV3gxWlM1c1pXNW5kR2dnUENBeUtYdGNiaUFnSUNBZ0lISmxkSFZ5YmlCbVlXeHpaVHRjYmlBZ0lDQjlYRzVjYmlBZ0lDQmpiMjV6ZENCb1pXRmtJRDBnZG1Gc2RXVmJNRjA3WEc0Z0lDQWdZMjl1YzNRZ2RHRnBiQ0E5SUhaaGJIVmxMbk5zYVdObEtERXBPMXh1WEc0Z0lDQWdhV1lvYUdWaFpFMWhkR05vWlhNb2FHVmhaQ3dnWVhKbmN5a2dKaVlnZEdGcGJFMWhkR05vWlhNb2RHRnBiQ3dnWVhKbmN5a3BlMXh1SUNBZ0lDQWdjbVYwZFhKdUlIUnlkV1U3WEc0Z0lDQWdmVnh1SUNCOU8xeHVmVnh1WEc1bWRXNWpkR2x2YmlCeVpYTnZiSFpsUTJGd2RIVnlaU2h3WVhSMFpYSnVPaUJVZVhCbGN5NURZWEIwZFhKbEtUb2dSblZ1WTNScGIyNGdlMXh1SUNCamIyNXpkQ0J0WVhSamFHVnpJRDBnWW5WcGJHUk5ZWFJqYUNod1lYUjBaWEp1TG5aaGJIVmxLVHRjYmx4dUlDQnlaWFIxY200Z1puVnVZM1JwYjI0b2RtRnNkV1U2SUdGdWVTd2dZWEpuY3pvZ1FYSnlZWGs4WVc1NVBpazZJR0p2YjJ4bFlXNGdlMXh1SUNBZ0lHbG1LRzFoZEdOb1pYTW9kbUZzZFdVc0lHRnlaM01wS1h0Y2JpQWdJQ0FnSUdGeVozTXVjSFZ6YUNoMllXeDFaU2s3WEc0Z0lDQWdJQ0J5WlhSMWNtNGdkSEoxWlR0Y2JpQWdJQ0I5WEc1Y2JpQWdJQ0J5WlhSMWNtNGdabUZzYzJVN1hHNGdJSDA3WEc1OVhHNWNibVoxYm1OMGFXOXVJSEpsYzI5c2RtVlRkR0Z5ZEhOWGFYUm9LSEJoZEhSbGNtNDZJRlI1Y0dWekxsTjBZWEowYzFkcGRHZ3BPaUJHZFc1amRHbHZiaUI3WEc0Z0lHTnZibk4wSUhCeVpXWnBlQ0E5SUhCaGRIUmxjbTR1Y0hKbFptbDRPMXh1WEc0Z0lISmxkSFZ5YmlCbWRXNWpkR2x2YmloMllXeDFaVG9nWVc1NUxDQmhjbWR6T2lCQmNuSmhlVHhoYm5rK0tUb2dZbTl2YkdWaGJpQjdYRzRnSUNBZ2FXWW9RMmhsWTJ0ekxtbHpYM04wY21sdVp5aDJZV3gxWlNrZ0ppWWdkbUZzZFdVdWMzUmhjblJ6VjJsMGFDaHdjbVZtYVhncEtYdGNiaUFnSUNBZ0lHRnlaM011Y0hWemFDaDJZV3gxWlM1emRXSnpkSEpwYm1jb2NISmxabWw0TG14bGJtZDBhQ2twTzF4dUlDQWdJQ0FnY21WMGRYSnVJSFJ5ZFdVN1hHNGdJQ0FnZlZ4dVhHNGdJQ0FnY21WMGRYSnVJR1poYkhObE8xeHVJQ0I5TzF4dWZWeHVYRzVtZFc1amRHbHZiaUJ5WlhOdmJIWmxWSGx3WlNod1lYUjBaWEp1T2lCVWVYQmxjeTVVZVhCbEtUb2dSblZ1WTNScGIyNGdlMXh1SUNCeVpYUjFjbTRnWm5WdVkzUnBiMjRvZG1Gc2RXVTZJR0Z1ZVN3Z1lYSm5jem9nUVhKeVlYazhZVzU1UGlrNklHSnZiMnhsWVc0Z2UxeHVJQ0FnSUdsbUtIWmhiSFZsSUdsdWMzUmhibU5sYjJZZ2NHRjBkR1Z5Ymk1MGVYQmxLWHRjYmlBZ0lDQWdJR052Ym5OMElHMWhkR05vWlhNZ1BTQmlkV2xzWkUxaGRHTm9LSEJoZEhSbGNtNHViMkpxVUdGMGRHVnliaWs3WEc0Z0lDQWdJQ0J5WlhSMWNtNGdiV0YwWTJobGN5aDJZV3gxWlN3Z1lYSm5jeWtnSmlZZ1lYSm5jeTV3ZFhOb0tIWmhiSFZsS1NBK0lEQTdYRzRnSUNBZ2ZWeHVYRzRnSUNBZ2NtVjBkWEp1SUdaaGJITmxPMXh1SUNCOU8xeHVmVnh1WEc1bWRXNWpkR2x2YmlCeVpYTnZiSFpsUVhKeVlYa29jR0YwZEdWeWJqb2dRWEp5WVhrOFlXNTVQaWs2SUVaMWJtTjBhVzl1SUh0Y2JpQWdZMjl1YzNRZ2JXRjBZMmhsY3lBOUlIQmhkSFJsY200dWJXRndLSGdnUFQ0Z1luVnBiR1JOWVhSamFDaDRLU2s3WEc1Y2JpQWdjbVYwZFhKdUlHWjFibU4wYVc5dUtIWmhiSFZsT2lCaGJua3NJR0Z5WjNNNklFRnljbUY1UEdGdWVUNHBPaUJpYjI5c1pXRnVJSHRjYmlBZ0lDQnBaaWdoUTJobFkydHpMbWx6WDJGeWNtRjVLSFpoYkhWbEtTQjhmQ0IyWVd4MVpTNXNaVzVuZEdnZ0lUMGdjR0YwZEdWeWJpNXNaVzVuZEdncGUxeHVJQ0FnSUNBZ2NtVjBkWEp1SUdaaGJITmxPMXh1SUNBZ0lIMWNibHh1SUNBZ0lISmxkSFZ5YmlCMllXeDFaUzVsZG1WeWVTaG1kVzVqZEdsdmJpaDJMQ0JwS1NCN1hHNGdJQ0FnSUNCeVpYUjFjbTRnYldGMFkyaGxjMXRwWFNoMllXeDFaVnRwWFN3Z1lYSm5jeWs3WEc0Z0lDQWdmU2s3WEc0Z0lIMDdYRzU5WEc1Y2JtWjFibU4wYVc5dUlISmxjMjlzZG1WUFltcGxZM1FvY0dGMGRHVnliam9nVDJKcVpXTjBLVG9nUm5WdVkzUnBiMjRnZTF4dUlDQnNaWFFnYldGMFkyaGxjeUE5SUh0OU8xeHVYRzRnSUdadmNpaHNaWFFnYTJWNUlHOW1JRTlpYW1WamRDNXJaWGx6S0hCaGRIUmxjbTRwTG1OdmJtTmhkQ2hQWW1wbFkzUXVaMlYwVDNkdVVISnZjR1Z5ZEhsVGVXMWliMnh6S0hCaGRIUmxjbTRwS1NsN1hHNGdJQ0FnYldGMFkyaGxjMXRyWlhsZElEMGdZblZwYkdSTllYUmphQ2h3WVhSMFpYSnVXMnRsZVYwcE8xeHVJQ0I5WEc1Y2JpQWdjbVYwZFhKdUlHWjFibU4wYVc5dUtIWmhiSFZsT2lCaGJua3NJR0Z5WjNNNklFRnljbUY1UEdGdWVUNHBPaUJpYjI5c1pXRnVJSHRjYmlBZ0lDQnBaaWdoUTJobFkydHpMbWx6WDI5aWFtVmpkQ2gyWVd4MVpTa2dmSHdnY0dGMGRHVnliaTVzWlc1bmRHZ2dQaUIyWVd4MVpTNXNaVzVuZEdncGUxeHVJQ0FnSUNBZ2NtVjBkWEp1SUdaaGJITmxPMXh1SUNBZ0lIMWNibHh1SUNBZ0lHWnZjaWhzWlhRZ2EyVjVJRzltSUU5aWFtVmpkQzVyWlhsektIQmhkSFJsY200cExtTnZibU5oZENoUFltcGxZM1F1WjJWMFQzZHVVSEp2Y0dWeWRIbFRlVzFpYjJ4ektIQmhkSFJsY200cEtTbDdYRzRnSUNBZ0lDQnBaaWdoS0d0bGVTQnBiaUIyWVd4MVpTa2dmSHdnSVcxaGRHTm9aWE5iYTJWNVhTaDJZV3gxWlZ0clpYbGRMQ0JoY21kektTQXBlMXh1SUNBZ0lDQWdJQ0J5WlhSMWNtNGdabUZzYzJVN1hHNGdJQ0FnSUNCOVhHNGdJQ0FnZlZ4dVhHNGdJQ0FnY21WMGRYSnVJSFJ5ZFdVN1hHNGdJSDA3WEc1OVhHNWNibVoxYm1OMGFXOXVJSEpsYzI5c2RtVk9iMDFoZEdOb0tDazZJRVoxYm1OMGFXOXVJSHRjYmlBZ2NtVjBkWEp1SUdaMWJtTjBhVzl1S0NrNklHSnZiMnhsWVc0Z2UxeHVJQ0FnSUhKbGRIVnliaUJtWVd4elpUdGNiaUFnZlZ4dWZWeHVYRzVsZUhCdmNuUWdaR1ZtWVhWc2RDQjdYRzRnSUhKbGMyOXNkbVZDYjNWdVpDeGNiaUFnY21WemIyeDJaVmRwYkdSallYSmtMRnh1SUNCeVpYTnZiSFpsVm1GeWFXRmliR1VzWEc0Z0lISmxjMjlzZG1WSVpXRmtWR0ZwYkN4Y2JpQWdjbVZ6YjJ4MlpVTmhjSFIxY21Vc1hHNGdJSEpsYzI5c2RtVlRkR0Z5ZEhOWGFYUm9MRnh1SUNCeVpYTnZiSFpsVkhsd1pTeGNiaUFnY21WemIyeDJaVUZ5Y21GNUxGeHVJQ0J5WlhOdmJIWmxUMkpxWldOMExGeHVJQ0J5WlhOdmJIWmxUbTlOWVhSamFDeGNiaUFnY21WemIyeDJaVk41YldKdmJDeGNiaUFnY21WemIyeDJaVk4wY21sdVp5eGNiaUFnY21WemIyeDJaVTUxYldKbGNpeGNiaUFnY21WemIyeDJaVUp2YjJ4bFlXNHNYRzRnSUhKbGMyOXNkbVZHZFc1amRHbHZiaXhjYmlBZ2NtVnpiMngyWlU1MWJHeGNibjFjYmlKZExDSnpiM1Z5WTJWU2IyOTBJam9pTDNOdmRYSmpaUzhpZlE9PVxuIiwiXG5pbXBvcnQgQ2hlY2tzIGZyb20gXCIuL2NoZWNrc1wiO1xuaW1wb3J0IFJlc29sdmVycyBmcm9tIFwiLi9yZXNvbHZlcnNcIjtcblxuZXhwb3J0IGZ1bmN0aW9uIGJ1aWxkTWF0Y2gocGF0dGVybikge1xuXG4gIGlmIChDaGVja3MuaXNfdmFyaWFibGUocGF0dGVybikpIHtcbiAgICByZXR1cm4gUmVzb2x2ZXJzLnJlc29sdmVWYXJpYWJsZShwYXR0ZXJuKTtcbiAgfVxuXG4gIGlmIChDaGVja3MuaXNfd2lsZGNhcmQocGF0dGVybikpIHtcbiAgICByZXR1cm4gUmVzb2x2ZXJzLnJlc29sdmVXaWxkY2FyZChwYXR0ZXJuKTtcbiAgfVxuXG4gIGlmIChDaGVja3MuaXNfdW5kZWZpbmVkKHBhdHRlcm4pKSB7XG4gICAgcmV0dXJuIFJlc29sdmVycy5yZXNvbHZlV2lsZGNhcmQocGF0dGVybik7XG4gIH1cblxuICBpZiAoQ2hlY2tzLmlzX2hlYWRUYWlsKHBhdHRlcm4pKSB7XG4gICAgcmV0dXJuIFJlc29sdmVycy5yZXNvbHZlSGVhZFRhaWwocGF0dGVybik7XG4gIH1cblxuICBpZiAoQ2hlY2tzLmlzX3N0YXJ0c1dpdGgocGF0dGVybikpIHtcbiAgICByZXR1cm4gUmVzb2x2ZXJzLnJlc29sdmVTdGFydHNXaXRoKHBhdHRlcm4pO1xuICB9XG5cbiAgaWYgKENoZWNrcy5pc19jYXB0dXJlKHBhdHRlcm4pKSB7XG4gICAgcmV0dXJuIFJlc29sdmVycy5yZXNvbHZlQ2FwdHVyZShwYXR0ZXJuKTtcbiAgfVxuXG4gIGlmIChDaGVja3MuaXNfYm91bmQocGF0dGVybikpIHtcbiAgICByZXR1cm4gUmVzb2x2ZXJzLnJlc29sdmVCb3VuZChwYXR0ZXJuKTtcbiAgfVxuXG4gIGlmIChDaGVja3MuaXNfdHlwZShwYXR0ZXJuKSkge1xuICAgIHJldHVybiBSZXNvbHZlcnMucmVzb2x2ZVR5cGUocGF0dGVybik7XG4gIH1cblxuICBpZiAoQ2hlY2tzLmlzX2FycmF5KHBhdHRlcm4pKSB7XG4gICAgcmV0dXJuIFJlc29sdmVycy5yZXNvbHZlQXJyYXkocGF0dGVybik7XG4gIH1cblxuICBpZiAoQ2hlY2tzLmlzX251bWJlcihwYXR0ZXJuKSkge1xuICAgIHJldHVybiBSZXNvbHZlcnMucmVzb2x2ZU51bWJlcihwYXR0ZXJuKTtcbiAgfVxuXG4gIGlmIChDaGVja3MuaXNfc3RyaW5nKHBhdHRlcm4pKSB7XG4gICAgcmV0dXJuIFJlc29sdmVycy5yZXNvbHZlU3RyaW5nKHBhdHRlcm4pO1xuICB9XG5cbiAgaWYgKENoZWNrcy5pc19ib29sZWFuKHBhdHRlcm4pKSB7XG4gICAgcmV0dXJuIFJlc29sdmVycy5yZXNvbHZlQm9vbGVhbihwYXR0ZXJuKTtcbiAgfVxuXG4gIGlmIChDaGVja3MuaXNfc3ltYm9sKHBhdHRlcm4pKSB7XG4gICAgcmV0dXJuIFJlc29sdmVycy5yZXNvbHZlU3ltYm9sKHBhdHRlcm4pO1xuICB9XG5cbiAgaWYgKENoZWNrcy5pc19udWxsKHBhdHRlcm4pKSB7XG4gICAgcmV0dXJuIFJlc29sdmVycy5yZXNvbHZlTnVsbChwYXR0ZXJuKTtcbiAgfVxuXG4gIGlmIChDaGVja3MuaXNfb2JqZWN0KHBhdHRlcm4pKSB7XG4gICAgcmV0dXJuIFJlc29sdmVycy5yZXNvbHZlT2JqZWN0KHBhdHRlcm4pO1xuICB9XG5cbiAgcmV0dXJuIFJlc29sdmVycy5yZXNvbHZlTm9NYXRjaCgpO1xufVxuLy8jIHNvdXJjZU1hcHBpbmdVUkw9ZGF0YTphcHBsaWNhdGlvbi9qc29uO2Jhc2U2NCxleUoyWlhKemFXOXVJam96TENKemIzVnlZMlZ6SWpwYklteHBZaTlqYjNKbEwzQmhkSFJsY201ekwyMWhkR05vTG1weklsMHNJbTVoYldWeklqcGJYU3dpYldGd2NHbHVaM01pT2lJN1FVRkRRU3hQUVVGUExFMUJRVkFzVFVGQmJVSXNWVUZCYmtJN1FVRkRRU3hQUVVGUExGTkJRVkFzVFVGQmMwSXNZVUZCZEVJN08wRkJSVUVzVDBGQlR5eFRRVUZUTEZWQlFWUXNRMEZCYjBJc1QwRkJjRUlzUlVGQk5FTTdPMEZCUldwRUxFMUJRVWNzVDBGQlR5eFhRVUZRTEVOQlFXMUNMRTlCUVc1Q0xFTkJRVWdzUlVGQkswSTdRVUZETjBJc1YwRkJUeXhWUVVGVkxHVkJRVllzUTBGQk1FSXNUMEZCTVVJc1EwRkJVQ3hEUVVRMlFqdEhRVUV2UWpzN1FVRkpRU3hOUVVGSExFOUJRVThzVjBGQlVDeERRVUZ0UWl4UFFVRnVRaXhEUVVGSUxFVkJRU3RDTzBGQlF6ZENMRmRCUVU4c1ZVRkJWU3hsUVVGV0xFTkJRVEJDTEU5QlFURkNMRU5CUVZBc1EwRkVOa0k3UjBGQkwwSTdPMEZCU1VFc1RVRkJSeXhQUVVGUExGbEJRVkFzUTBGQmIwSXNUMEZCY0VJc1EwRkJTQ3hGUVVGblF6dEJRVU01UWl4WFFVRlBMRlZCUVZVc1pVRkJWaXhEUVVFd1FpeFBRVUV4UWl4RFFVRlFMRU5CUkRoQ08wZEJRV2hET3p0QlFVbEJMRTFCUVVjc1QwRkJUeXhYUVVGUUxFTkJRVzFDTEU5QlFXNUNMRU5CUVVnc1JVRkJLMEk3UVVGRE4wSXNWMEZCVHl4VlFVRlZMR1ZCUVZZc1EwRkJNRUlzVDBGQk1VSXNRMEZCVUN4RFFVUTJRanRIUVVFdlFqczdRVUZKUVN4TlFVRkhMRTlCUVU4c1lVRkJVQ3hEUVVGeFFpeFBRVUZ5UWl4RFFVRklMRVZCUVdsRE8wRkJReTlDTEZkQlFVOHNWVUZCVlN4cFFrRkJWaXhEUVVFMFFpeFBRVUUxUWl4RFFVRlFMRU5CUkN0Q08wZEJRV3BET3p0QlFVbEJMRTFCUVVjc1QwRkJUeXhWUVVGUUxFTkJRV3RDTEU5QlFXeENMRU5CUVVnc1JVRkJPRUk3UVVGRE5VSXNWMEZCVHl4VlFVRlZMR05CUVZZc1EwRkJlVUlzVDBGQmVrSXNRMEZCVUN4RFFVUTBRanRIUVVFNVFqczdRVUZKUVN4TlFVRkhMRTlCUVU4c1VVRkJVQ3hEUVVGblFpeFBRVUZvUWl4RFFVRklMRVZCUVRSQ08wRkJRekZDTEZkQlFVOHNWVUZCVlN4WlFVRldMRU5CUVhWQ0xFOUJRWFpDTEVOQlFWQXNRMEZFTUVJN1IwRkJOVUk3TzBGQlNVRXNUVUZCUnl4UFFVRlBMRTlCUVZBc1EwRkJaU3hQUVVGbUxFTkJRVWdzUlVGQk1rSTdRVUZEZWtJc1YwRkJUeXhWUVVGVkxGZEJRVllzUTBGQmMwSXNUMEZCZEVJc1EwRkJVQ3hEUVVSNVFqdEhRVUV6UWpzN1FVRkpRU3hOUVVGSExFOUJRVThzVVVGQlVDeERRVUZuUWl4UFFVRm9RaXhEUVVGSUxFVkJRVFJDTzBGQlF6RkNMRmRCUVU4c1ZVRkJWU3haUVVGV0xFTkJRWFZDTEU5QlFYWkNMRU5CUVZBc1EwRkVNRUk3UjBGQk5VSTdPMEZCU1VFc1RVRkJSeXhQUVVGUExGTkJRVkFzUTBGQmFVSXNUMEZCYWtJc1EwRkJTQ3hGUVVFMlFqdEJRVU16UWl4WFFVRlBMRlZCUVZVc1lVRkJWaXhEUVVGM1FpeFBRVUY0UWl4RFFVRlFMRU5CUkRKQ08wZEJRVGRDT3p0QlFVbEJMRTFCUVVjc1QwRkJUeXhUUVVGUUxFTkJRV2xDTEU5QlFXcENMRU5CUVVnc1JVRkJOa0k3UVVGRE0wSXNWMEZCVHl4VlFVRlZMR0ZCUVZZc1EwRkJkMElzVDBGQmVFSXNRMEZCVUN4RFFVUXlRanRIUVVFM1FqczdRVUZKUVN4TlFVRkhMRTlCUVU4c1ZVRkJVQ3hEUVVGclFpeFBRVUZzUWl4RFFVRklMRVZCUVRoQ08wRkJRelZDTEZkQlFVOHNWVUZCVlN4alFVRldMRU5CUVhsQ0xFOUJRWHBDTEVOQlFWQXNRMEZFTkVJN1IwRkJPVUk3TzBGQlNVRXNUVUZCUnl4UFFVRlBMRk5CUVZBc1EwRkJhVUlzVDBGQmFrSXNRMEZCU0N4RlFVRTJRanRCUVVNelFpeFhRVUZQTEZWQlFWVXNZVUZCVml4RFFVRjNRaXhQUVVGNFFpeERRVUZRTEVOQlJESkNPMGRCUVRkQ096dEJRVWxCTEUxQlFVY3NUMEZCVHl4UFFVRlFMRU5CUVdVc1QwRkJaaXhEUVVGSUxFVkJRVEpDTzBGQlEzcENMRmRCUVU4c1ZVRkJWU3hYUVVGV0xFTkJRWE5DTEU5QlFYUkNMRU5CUVZBc1EwRkVlVUk3UjBGQk0wSTdPMEZCU1VFc1RVRkJSeXhQUVVGUExGTkJRVkFzUTBGQmFVSXNUMEZCYWtJc1EwRkJTQ3hGUVVFMlFqdEJRVU16UWl4WFFVRlBMRlZCUVZVc1lVRkJWaXhEUVVGM1FpeFBRVUY0UWl4RFFVRlFMRU5CUkRKQ08wZEJRVGRDT3p0QlFVbEJMRk5CUVU4c1ZVRkJWU3hqUVVGV0xFVkJRVkFzUTBFNVJHbEVPME5CUVRWRElpd2labWxzWlNJNklteHBZaTlqYjNKbEwzQmhkSFJsY201ekwyMWhkR05vTG1weklpd2ljMjkxY21ObGMwTnZiblJsYm5RaU9sc2lMeW9nUUdac2IzY2dLaTljYm1sdGNHOXlkQ0JEYUdWamEzTWdabkp2YlNCY0lpNHZZMmhsWTJ0elhDSTdYRzVwYlhCdmNuUWdVbVZ6YjJ4MlpYSnpJR1p5YjIwZ1hDSXVMM0psYzI5c2RtVnljMXdpTzF4dVhHNWxlSEJ2Y25RZ1puVnVZM1JwYjI0Z1luVnBiR1JOWVhSamFDaHdZWFIwWlhKdU9pQmhibmtwT2lCR2RXNWpkR2x2YmlCN1hHNWNiaUFnYVdZb1EyaGxZMnR6TG1selgzWmhjbWxoWW14bEtIQmhkSFJsY200cEtYdGNiaUFnSUNCeVpYUjFjbTRnVW1WemIyeDJaWEp6TG5KbGMyOXNkbVZXWVhKcFlXSnNaU2h3WVhSMFpYSnVLVHRjYmlBZ2ZWeHVYRzRnSUdsbUtFTm9aV05yY3k1cGMxOTNhV3hrWTJGeVpDaHdZWFIwWlhKdUtTbDdYRzRnSUNBZ2NtVjBkWEp1SUZKbGMyOXNkbVZ5Y3k1eVpYTnZiSFpsVjJsc1pHTmhjbVFvY0dGMGRHVnliaWs3WEc0Z0lIMWNibHh1SUNCcFppaERhR1ZqYTNNdWFYTmZkVzVrWldacGJtVmtLSEJoZEhSbGNtNHBLWHRjYmlBZ0lDQnlaWFIxY200Z1VtVnpiMngyWlhKekxuSmxjMjlzZG1WWGFXeGtZMkZ5WkNod1lYUjBaWEp1S1R0Y2JpQWdmVnh1WEc0Z0lHbG1LRU5vWldOcmN5NXBjMTlvWldGa1ZHRnBiQ2h3WVhSMFpYSnVLU2w3WEc0Z0lDQWdjbVYwZFhKdUlGSmxjMjlzZG1WeWN5NXlaWE52YkhabFNHVmhaRlJoYVd3b2NHRjBkR1Z5YmlrN1hHNGdJSDFjYmx4dUlDQnBaaWhEYUdWamEzTXVhWE5mYzNSaGNuUnpWMmwwYUNod1lYUjBaWEp1S1NsN1hHNGdJQ0FnY21WMGRYSnVJRkpsYzI5c2RtVnljeTV5WlhOdmJIWmxVM1JoY25SelYybDBhQ2h3WVhSMFpYSnVLVHRjYmlBZ2ZWeHVYRzRnSUdsbUtFTm9aV05yY3k1cGMxOWpZWEIwZFhKbEtIQmhkSFJsY200cEtYdGNiaUFnSUNCeVpYUjFjbTRnVW1WemIyeDJaWEp6TG5KbGMyOXNkbVZEWVhCMGRYSmxLSEJoZEhSbGNtNHBPMXh1SUNCOVhHNWNiaUFnYVdZb1EyaGxZMnR6TG1selgySnZkVzVrS0hCaGRIUmxjbTRwS1h0Y2JpQWdJQ0J5WlhSMWNtNGdVbVZ6YjJ4MlpYSnpMbkpsYzI5c2RtVkNiM1Z1WkNod1lYUjBaWEp1S1R0Y2JpQWdmVnh1WEc0Z0lHbG1LRU5vWldOcmN5NXBjMTkwZVhCbEtIQmhkSFJsY200cEtYdGNiaUFnSUNCeVpYUjFjbTRnVW1WemIyeDJaWEp6TG5KbGMyOXNkbVZVZVhCbEtIQmhkSFJsY200cE8xeHVJQ0I5WEc1Y2JpQWdhV1lvUTJobFkydHpMbWx6WDJGeWNtRjVLSEJoZEhSbGNtNHBLWHRjYmlBZ0lDQnlaWFIxY200Z1VtVnpiMngyWlhKekxuSmxjMjlzZG1WQmNuSmhlU2h3WVhSMFpYSnVLVHRjYmlBZ2ZWeHVYRzRnSUdsbUtFTm9aV05yY3k1cGMxOXVkVzFpWlhJb2NHRjBkR1Z5YmlrcGUxeHVJQ0FnSUhKbGRIVnliaUJTWlhOdmJIWmxjbk11Y21WemIyeDJaVTUxYldKbGNpaHdZWFIwWlhKdUtUdGNiaUFnZlZ4dVhHNGdJR2xtS0VOb1pXTnJjeTVwYzE5emRISnBibWNvY0dGMGRHVnliaWtwZTF4dUlDQWdJSEpsZEhWeWJpQlNaWE52YkhabGNuTXVjbVZ6YjJ4MlpWTjBjbWx1Wnlod1lYUjBaWEp1S1R0Y2JpQWdmVnh1WEc0Z0lHbG1LRU5vWldOcmN5NXBjMTlpYjI5c1pXRnVLSEJoZEhSbGNtNHBLWHRjYmlBZ0lDQnlaWFIxY200Z1VtVnpiMngyWlhKekxuSmxjMjlzZG1WQ2IyOXNaV0Z1S0hCaGRIUmxjbTRwTzF4dUlDQjlYRzVjYmlBZ2FXWW9RMmhsWTJ0ekxtbHpYM041YldKdmJDaHdZWFIwWlhKdUtTbDdYRzRnSUNBZ2NtVjBkWEp1SUZKbGMyOXNkbVZ5Y3k1eVpYTnZiSFpsVTNsdFltOXNLSEJoZEhSbGNtNHBPMXh1SUNCOVhHNWNiaUFnYVdZb1EyaGxZMnR6TG1selgyNTFiR3dvY0dGMGRHVnliaWtwZTF4dUlDQWdJSEpsZEhWeWJpQlNaWE52YkhabGNuTXVjbVZ6YjJ4MlpVNTFiR3dvY0dGMGRHVnliaWs3WEc0Z0lIMWNibHh1SUNCcFppaERhR1ZqYTNNdWFYTmZiMkpxWldOMEtIQmhkSFJsY200cEtYdGNiaUFnSUNCeVpYUjFjbTRnVW1WemIyeDJaWEp6TG5KbGMyOXNkbVZQWW1wbFkzUW9jR0YwZEdWeWJpazdYRzRnSUgxY2JseHVJQ0J5WlhSMWNtNGdVbVZ6YjJ4MlpYSnpMbkpsYzI5c2RtVk9iMDFoZEdOb0tDazdYRzU5WEc0aVhTd2ljMjkxY21ObFVtOXZkQ0k2SWk5emIzVnlZMlV2SW4wPVxuIiwiXG5cbmltcG9ydCB7IGJ1aWxkTWF0Y2ggfSBmcm9tIFwiLi9tYXRjaFwiO1xuXG5leHBvcnQgY2xhc3MgTWF0Y2hFcnJvciBleHRlbmRzIEVycm9yIHtcbiAgY29uc3RydWN0b3IoYXJnKSB7XG4gICAgc3VwZXIoKTtcblxuICAgIGlmICh0eXBlb2YgYXJnID09PSAnc3ltYm9sJykge1xuICAgICAgdGhpcy5tZXNzYWdlID0gJ05vIG1hdGNoIGZvcjogJyArIGFyZy50b1N0cmluZygpO1xuICAgIH0gZWxzZSBpZiAoQXJyYXkuaXNBcnJheShhcmcpKSB7XG4gICAgICBsZXQgbWFwcGVkVmFsdWVzID0gYXJnLm1hcCh4ID0+IHgudG9TdHJpbmcoKSk7XG4gICAgICB0aGlzLm1lc3NhZ2UgPSAnTm8gbWF0Y2ggZm9yOiAnICsgbWFwcGVkVmFsdWVzO1xuICAgIH0gZWxzZSB7XG4gICAgICB0aGlzLm1lc3NhZ2UgPSAnTm8gbWF0Y2ggZm9yOiAnICsgYXJnO1xuICAgIH1cblxuICAgIHRoaXMuc3RhY2sgPSBuZXcgRXJyb3IoKS5zdGFjaztcbiAgICB0aGlzLm5hbWUgPSB0aGlzLmNvbnN0cnVjdG9yLm5hbWU7XG4gIH1cbn1cblxuZXhwb3J0IGNsYXNzIENhc2Uge1xuXG4gIGNvbnN0cnVjdG9yKHBhdHRlcm4sIGZuLCBndWFyZCA9ICgpID0+IHRydWUpIHtcbiAgICB0aGlzLnBhdHRlcm4gPSBidWlsZE1hdGNoKHBhdHRlcm4pO1xuICAgIHRoaXMuZm4gPSBmbjtcbiAgICB0aGlzLmd1YXJkID0gZ3VhcmQ7XG4gIH1cbn1cblxuZXhwb3J0IGZ1bmN0aW9uIG1ha2VfY2FzZShwYXR0ZXJuLCBmbiwgZ3VhcmQgPSAoKSA9PiB0cnVlKSB7XG4gIHJldHVybiBuZXcgQ2FzZShwYXR0ZXJuLCBmbiwgZ3VhcmQpO1xufVxuXG5leHBvcnQgZnVuY3Rpb24gZGVmbWF0Y2goLi4uY2FzZXMpIHtcbiAgcmV0dXJuIGZ1bmN0aW9uICguLi5hcmdzKSB7XG4gICAgZm9yIChsZXQgcHJvY2Vzc2VkQ2FzZSBvZiBjYXNlcykge1xuICAgICAgbGV0IHJlc3VsdCA9IFtdO1xuICAgICAgaWYgKHByb2Nlc3NlZENhc2UucGF0dGVybihhcmdzLCByZXN1bHQpICYmIHByb2Nlc3NlZENhc2UuZ3VhcmQuYXBwbHkodGhpcywgcmVzdWx0KSkge1xuICAgICAgICByZXR1cm4gcHJvY2Vzc2VkQ2FzZS5mbi5hcHBseSh0aGlzLCByZXN1bHQpO1xuICAgICAgfVxuICAgIH1cblxuICAgIHRocm93IG5ldyBNYXRjaEVycm9yKGFyZ3MpO1xuICB9O1xufVxuXG5leHBvcnQgZnVuY3Rpb24gbWF0Y2gocGF0dGVybiwgZXhwciwgZ3VhcmQgPSAoKSA9PiB0cnVlKSB7XG4gIGxldCByZXN1bHQgPSBbXTtcbiAgbGV0IHByb2Nlc3NlZFBhdHRlcm4gPSBidWlsZE1hdGNoKHBhdHRlcm4pO1xuICBpZiAocHJvY2Vzc2VkUGF0dGVybihleHByLCByZXN1bHQpICYmIGd1YXJkLmFwcGx5KHRoaXMsIHJlc3VsdCkpIHtcbiAgICByZXR1cm4gcmVzdWx0O1xuICB9IGVsc2Uge1xuICAgIHRocm93IG5ldyBNYXRjaEVycm9yKGV4cHIpO1xuICB9XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBtYXRjaF9ub190aHJvdyhwYXR0ZXJuLCBleHByLCBndWFyZCA9ICgpID0+IHRydWUpIHtcbiAgdHJ5IHtcbiAgICByZXR1cm4gbWF0Y2gocGF0dGVybiwgZXhwciwgZ3VhcmQpO1xuICB9IGNhdGNoIChlKSB7XG4gICAgaWYgKGUgaW5zdGFuY2VvZiBNYXRjaEVycm9yIHx8IGUubWVzc2FnZS5zdGFydHNXaXRoKCdObyBtYXRjaCBmb3I6JykpIHtcbiAgICAgIHJldHVybiBudWxsO1xuICAgIH1cblxuICAgIHRocm93IGU7XG4gIH1cbn1cblxuZXhwb3J0IGZ1bmN0aW9uIHBhdHRlcm5NYXAoY29sbGVjdGlvbiwgcGF0dGVybiwgZnVuLCBndWFyZCA9ICgpID0+IHRydWUpIHtcbiAgbGV0IHJldCA9IFtdO1xuXG4gIGZvciAobGV0IGVsZW0gb2YgY29sbGVjdGlvbikge1xuICAgIHRyeSB7XG4gICAgICBsZXQgcmVzdWx0ID0gZnVuLmFwcGx5KHRoaXMsIG1hdGNoKHBhdHRlcm4sIGVsZW0sIGd1YXJkKSk7XG4gICAgICByZXQgPSByZXQuY29uY2F0KHJlc3VsdCk7XG4gICAgfSBjYXRjaCAoZSkge1xuICAgICAgaWYgKCEoZSBpbnN0YW5jZW9mIE1hdGNoRXJyb3IpKSB7XG4gICAgICAgIHRocm93IGU7XG4gICAgICB9XG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIHJldDtcbn1cbi8vIyBzb3VyY2VNYXBwaW5nVVJMPWRhdGE6YXBwbGljYXRpb24vanNvbjtiYXNlNjQsZXlKMlpYSnphVzl1SWpvekxDSnpiM1Z5WTJWeklqcGJJbXhwWWk5amIzSmxMM0JoZEhSbGNtNXpMMlJsWm0xaGRHTm9MbXB6SWwwc0ltNWhiV1Z6SWpwYlhTd2liV0Z3Y0dsdVozTWlPaUk3TzBGQlJVRXNVMEZCVXl4VlFVRlVMRkZCUVRKQ0xGTkJRVE5DT3p0QlFVVkJMRTlCUVU4c1RVRkJUU3hWUVVGT0xGTkJRWGxDTEV0QlFYcENMRU5CUVN0Q08wRkJRM0JETEdOQlFWa3NSMEZCV2l4RlFVRnpRanRCUVVOd1FpeFpRVVJ2UWpzN1FVRkhjRUlzVVVGQlJ5eFBRVUZQTEVkQlFWQXNTMEZCWlN4UlFVRm1MRVZCUVhkQ08wRkJRM3BDTEZkQlFVc3NUMEZCVEN4SFFVRmxMRzFDUVVGdFFpeEpRVUZKTEZGQlFVb3NSVUZCYmtJc1EwRkVWVHRMUVVFelFpeE5RVVZQTEVsQlFVY3NUVUZCVFN4UFFVRk9MRU5CUVdNc1IwRkJaQ3hEUVVGSUxFVkJRWE5DTzBGQlF6TkNMRlZCUVVrc1pVRkJaU3hKUVVGSkxFZEJRVW9zUTBGQlVTeExRVUZQTEVWQlFVVXNVVUZCUml4RlFVRlFMRU5CUVhaQ0xFTkJSSFZDTzBGQlJUTkNMRmRCUVVzc1QwRkJUQ3hIUVVGbExHMUNRVUZ0UWl4WlFVRnVRaXhEUVVaWk8wdEJRWFJDTEUxQlIwWTdRVUZEU0N4WFFVRkxMRTlCUVV3c1IwRkJaU3h0UWtGQmJVSXNSMEZCYmtJc1EwRkVXanRMUVVoRk96dEJRVTlRTEZOQlFVc3NTMEZCVEN4SFFVRmhMRWxCUVVzc1MwRkJTaXhGUVVGRUxFTkJRV01zUzBGQlpDeERRVnBQTzBGQllYQkNMRk5CUVVzc1NVRkJUQ3hIUVVGWkxFdEJRVXNzVjBGQlRDeERRVUZwUWl4SlFVRnFRaXhEUVdKUk8wZEJRWFJDTzBOQlJFczdPMEZCYlVKUUxFOUJRVThzVFVGQlRTeEpRVUZPTEVOQlFWYzdPMEZCUzJoQ0xHTkJRVmtzVDBGQldpeEZRVUZwUXl4RlFVRnFReXhGUVVFclJDeFJRVUZGTEUxQlFVMHNTVUZCVGl4RlFVRlhPMEZCUXpGRkxGTkJRVXNzVDBGQlRDeEhRVUZsTEZkQlFWY3NUMEZCV0N4RFFVRm1MRU5CUkRCRk8wRkJSVEZGTEZOQlFVc3NSVUZCVEN4SFFVRlZMRVZCUVZZc1EwRkdNRVU3UVVGSE1VVXNVMEZCU3l4TFFVRk1MRWRCUVdFc1MwRkJZaXhEUVVnd1JUdEhRVUUxUlR0RFFVeExPenRCUVZsUUxFOUJRVThzVTBGQlV5eFRRVUZVTEVOQlFXMUNMRTlCUVc1Q0xFVkJRWGRETEVWQlFYaERMRVZCUVhORkxGRkJRVVVzVFVGQlRTeEpRVUZPTEVWQlFXdENPMEZCUXk5R0xGTkJRVThzU1VGQlNTeEpRVUZLTEVOQlFWTXNUMEZCVkN4RlFVRnJRaXhGUVVGc1FpeEZRVUZ6UWl4TFFVRjBRaXhEUVVGUUxFTkJSQ3RHTzBOQlFURkdPenRCUVVsUUxFOUJRVThzVTBGQlV5eFJRVUZVTEVOQlFXdENMRWRCUVVjc1MwRkJTQ3hGUVVGcFF6dEJRVU40UkN4VFFVRlBMRlZCUVZNc1IwRkJSeXhKUVVGSUxFVkJRVEJDTzBGQlEzaERMRk5CUVVzc1NVRkJTU3hoUVVGS0xFbEJRWEZDTEV0QlFURkNMRVZCUVdsRE8wRkJReTlDTEZWQlFVa3NVMEZCVXl4RlFVRlVMRU5CUkRKQ08wRkJSUzlDTEZWQlFVa3NZMEZCWXl4UFFVRmtMRU5CUVhOQ0xFbEJRWFJDTEVWQlFUUkNMRTFCUVRWQ0xFdEJRWFZETEdOQlFXTXNTMEZCWkN4RFFVRnZRaXhMUVVGd1FpeERRVUV3UWl4SlFVRXhRaXhGUVVGblF5eE5RVUZvUXl4RFFVRjJReXhGUVVGblJqdEJRVU5zUml4bFFVRlBMR05CUVdNc1JVRkJaQ3hEUVVGcFFpeExRVUZxUWl4RFFVRjFRaXhKUVVGMlFpeEZRVUUyUWl4TlFVRTNRaXhEUVVGUUxFTkJSR3RHTzA5QlFYQkdPMHRCUmtZN08wRkJUMEVzVlVGQlRTeEpRVUZKTEZWQlFVb3NRMEZCWlN4SlFVRm1MRU5CUVU0c1EwRlNkME03UjBGQmJrTXNRMEZFYVVRN1EwRkJia1E3TzBGQllWQXNUMEZCVHl4VFFVRlRMRXRCUVZRc1EwRkJaU3hQUVVGbUxFVkJRVFpDTEVsQlFUZENMRVZCUVhkRUxGRkJRVVVzVFVGQlRTeEpRVUZPTEVWQlFYZENPMEZCUTNaR0xFMUJRVWtzVTBGQlV5eEZRVUZVTEVOQlJHMUdPMEZCUlhaR0xFMUJRVWtzYlVKQlFXMUNMRmRCUVZjc1QwRkJXQ3hEUVVGdVFpeERRVVp0Ump0QlFVZDJSaXhOUVVGSkxHbENRVUZwUWl4SlFVRnFRaXhGUVVGMVFpeE5RVUYyUWl4TFFVRnJReXhOUVVGTkxFdEJRVTRzUTBGQldTeEpRVUZhTEVWQlFXdENMRTFCUVd4Q0xFTkJRV3hETEVWQlFUUkVPMEZCUXpsRUxGZEJRVThzVFVGQlVDeERRVVE0UkR0SFFVRm9SU3hOUVVWTE8wRkJRMGdzVlVGQlRTeEpRVUZKTEZWQlFVb3NRMEZCWlN4SlFVRm1MRU5CUVU0c1EwRkVSenRIUVVaTU8wTkJTRXM3TzBGQlZWQXNUMEZCVHl4VFFVRlRMR05CUVZRc1EwRkJkMElzVDBGQmVFSXNSVUZCYzBNc1NVRkJkRU1zUlVGQmFVVXNVVUZCUlN4TlFVRk5MRWxCUVU0c1JVRkJlVUk3UVVGRGFrY3NUVUZCUnp0QlFVTkVMRmRCUVU4c1RVRkJUU3hQUVVGT0xFVkJRV1VzU1VGQlppeEZRVUZ4UWl4TFFVRnlRaXhEUVVGUUxFTkJSRU03UjBGQlNDeERRVVZETEU5QlFVMHNRMEZCVGl4RlFVRlJPMEZCUTFBc1VVRkJSeXhoUVVGaExGVkJRV0lzU1VGQk1rSXNSVUZCUlN4UFFVRkdMRU5CUVZVc1ZVRkJWaXhEUVVGeFFpeGxRVUZ5UWl4RFFVRXpRaXhGUVVGcFJUdEJRVU5zUlN4aFFVRlBMRWxCUVZBc1EwRkVhMFU3UzBGQmNFVTdPMEZCU1VFc1ZVRkJUU3hEUVVGT0xFTkJURTg3UjBGQlVqdERRVWhKT3p0QlFWbFFMRTlCUVU4c1UwRkJVeXhWUVVGVUxFTkJRVzlDTEZWQlFYQkNMRVZCUVRSRExFOUJRVFZETEVWQlFUQkVMRWRCUVRGRUxFVkJRWGxHTEZGQlFVVXNUVUZCVFN4SlFVRk9MRVZCUVhkQ08wRkJRM2hJTEUxQlFVa3NUVUZCVFN4RlFVRk9MRU5CUkc5SU96dEJRVWQ0U0N4UFFVRkpMRWxCUVVrc1NVRkJTaXhKUVVGWkxGVkJRV2hDTEVWQlFUSkNPMEZCUTNwQ0xGRkJRVWM3UVVGRFJDeFZRVUZKTEZOQlFWTXNTVUZCU1N4TFFVRktMRU5CUVZVc1NVRkJWaXhGUVVGblFpeE5RVUZOTEU5QlFVNHNSVUZCWlN4SlFVRm1MRVZCUVhGQ0xFdEJRWEpDTEVOQlFXaENMRU5CUVZRc1EwRkVTRHRCUVVWRUxGbEJRVTBzU1VGQlNTeE5RVUZLTEVOQlFWY3NUVUZCV0N4RFFVRk9MRU5CUmtNN1MwRkJTQ3hEUVVkRExFOUJRVTBzUTBGQlRpeEZRVUZSTzBGQlExUXNWVUZCUnl4RlFVRkZMR0ZCUVdFc1ZVRkJZaXhEUVVGR0xFVkJRVEpDTzBGQlF6RkNMR05CUVUwc1EwRkJUaXhEUVVRd1FqdFBRVUU1UWp0TFFVUkRPMGRCU2tnN08wRkJWMEVzVTBGQlR5eEhRVUZRTEVOQlpIZElPME5CUVc1SUlpd2labWxzWlNJNklteHBZaTlqYjNKbEwzQmhkSFJsY201ekwyUmxabTFoZEdOb0xtcHpJaXdpYzI5MWNtTmxjME52Ym5SbGJuUWlPbHNpTHlvZ1FHWnNiM2NnS2k5Y2JseHVhVzF3YjNKMElIc2dZblZwYkdSTllYUmphQ0I5SUdaeWIyMGdYQ0l1TDIxaGRHTm9YQ0k3WEc1Y2JtVjRjRzl5ZENCamJHRnpjeUJOWVhSamFFVnljbTl5SUdWNGRHVnVaSE1nUlhKeWIzSWdlMXh1SUNCamIyNXpkSEoxWTNSdmNpaGhjbWM2SUdGdWVTa2dlMXh1SUNBZ0lITjFjR1Z5S0NrN1hHNWNiaUFnSUNCcFppaDBlWEJsYjJZZ1lYSm5JRDA5UFNBbmMzbHRZbTlzSnlsN1hHNGdJQ0FnSUNCMGFHbHpMbTFsYzNOaFoyVWdQU0FuVG04Z2JXRjBZMmdnWm05eU9pQW5JQ3NnWVhKbkxuUnZVM1J5YVc1bktDazdYRzRnSUNBZ2ZTQmxiSE5sSUdsbUtFRnljbUY1TG1selFYSnlZWGtvWVhKbktTbDdYRzRnSUNBZ0lDQnNaWFFnYldGd2NHVmtWbUZzZFdWeklEMGdZWEpuTG0xaGNDZ29lQ2tnUFQ0Z2VDNTBiMU4wY21sdVp5Z3BLVHRjYmlBZ0lDQWdJSFJvYVhNdWJXVnpjMkZuWlNBOUlDZE9ieUJ0WVhSamFDQm1iM0k2SUNjZ0t5QnRZWEJ3WldSV1lXeDFaWE03WEc0Z0lDQWdmV1ZzYzJWN1hHNGdJQ0FnSUNCMGFHbHpMbTFsYzNOaFoyVWdQU0FuVG04Z2JXRjBZMmdnWm05eU9pQW5JQ3NnWVhKbk8xeHVJQ0FnSUgxY2JseHVJQ0FnSUhSb2FYTXVjM1JoWTJzZ1BTQW9ibVYzSUVWeWNtOXlLQ2twTG5OMFlXTnJPMXh1SUNBZ0lIUm9hWE11Ym1GdFpTQTlJSFJvYVhNdVkyOXVjM1J5ZFdOMGIzSXVibUZ0WlR0Y2JpQWdmVnh1ZlZ4dVhHNWNibVY0Y0c5eWRDQmpiR0Z6Y3lCRFlYTmxJSHRjYmlBZ2NHRjBkR1Z5YmpvZ1JuVnVZM1JwYjI0N1hHNGdJR1p1T2lCR2RXNWpkR2x2Ymp0Y2JpQWdaM1ZoY21RNklFWjFibU4wYVc5dU8xeHVYRzRnSUdOdmJuTjBjblZqZEc5eUtIQmhkSFJsY200NklFRnljbUY1UEdGdWVUNHNJR1p1T2lCR2RXNWpkR2x2Yml3Z1ozVmhjbVE2SUVaMWJtTjBhVzl1SUQwZ0tDa2dQVDRnZEhKMVpTbDdYRzRnSUNBZ2RHaHBjeTV3WVhSMFpYSnVJRDBnWW5WcGJHUk5ZWFJqYUNod1lYUjBaWEp1S1R0Y2JpQWdJQ0IwYUdsekxtWnVJRDBnWm00N1hHNGdJQ0FnZEdocGN5NW5kV0Z5WkNBOUlHZDFZWEprTzF4dUlDQjlYRzU5WEc1Y2JtVjRjRzl5ZENCbWRXNWpkR2x2YmlCdFlXdGxYMk5oYzJVb2NHRjBkR1Z5YmpvZ1FYSnlZWGs4WVc1NVBpd2dabTQ2SUVaMWJtTjBhVzl1TENCbmRXRnlaRG9nUm5WdVkzUnBiMjRnUFNBb0tTQTlQaUIwY25WbEtUb2dRMkZ6WlNCN1hHNGdJSEpsZEhWeWJpQnVaWGNnUTJGelpTaHdZWFIwWlhKdUxDQm1iaXdnWjNWaGNtUXBPMXh1ZlZ4dVhHNWxlSEJ2Y25RZ1puVnVZM1JwYjI0Z1pHVm1iV0YwWTJnb0xpNHVZMkZ6WlhNNklFRnljbUY1UEVOaGMyVStLVG9nUm5WdVkzUnBiMjRnZTF4dUlDQnlaWFIxY200Z1puVnVZM1JwYjI0b0xpNHVZWEpuY3pvZ1FYSnlZWGs4WVc1NVBpazZJR0Z1ZVNCN1hHNGdJQ0FnWm05eUlDaHNaWFFnY0hKdlkyVnpjMlZrUTJGelpTQnZaaUJqWVhObGN5a2dlMXh1SUNBZ0lDQWdiR1YwSUhKbGMzVnNkQ0E5SUZ0ZE8xeHVJQ0FnSUNBZ2FXWWdLSEJ5YjJObGMzTmxaRU5oYzJVdWNHRjBkR1Z5YmloaGNtZHpMQ0J5WlhOMWJIUXBJQ1ltSUhCeWIyTmxjM05sWkVOaGMyVXVaM1ZoY21RdVlYQndiSGtvZEdocGN5d2djbVZ6ZFd4MEtTa2dlMXh1SUNBZ0lDQWdJQ0J5WlhSMWNtNGdjSEp2WTJWemMyVmtRMkZ6WlM1bWJpNWhjSEJzZVNoMGFHbHpMQ0J5WlhOMWJIUXBPMXh1SUNBZ0lDQWdmVnh1SUNBZ0lIMWNibHh1SUNBZ0lIUm9jbTkzSUc1bGR5Qk5ZWFJqYUVWeWNtOXlLR0Z5WjNNcE8xeHVJQ0I5TzF4dWZWeHVYRzVsZUhCdmNuUWdablZ1WTNScGIyNGdiV0YwWTJnb2NHRjBkR1Z5YmpvZ1lXNTVMQ0JsZUhCeU9pQmhibmtzSUdkMVlYSmtPaUJHZFc1amRHbHZiaUE5SUNncElEMCtJSFJ5ZFdVcE9pQkJjbkpoZVR4aGJuaytJSHRjYmlBZ2JHVjBJSEpsYzNWc2RDQTlJRnRkTzF4dUlDQnNaWFFnY0hKdlkyVnpjMlZrVUdGMGRHVnliaUE5SUdKMWFXeGtUV0YwWTJnb2NHRjBkR1Z5YmlrN1hHNGdJR2xtSUNod2NtOWpaWE56WldSUVlYUjBaWEp1S0dWNGNISXNJSEpsYzNWc2RDa2dKaVlnWjNWaGNtUXVZWEJ3Ykhrb2RHaHBjeXdnY21WemRXeDBLU2w3WEc0Z0lDQWdjbVYwZFhKdUlISmxjM1ZzZER0Y2JpQWdmV1ZzYzJWN1hHNGdJQ0FnZEdoeWIzY2dibVYzSUUxaGRHTm9SWEp5YjNJb1pYaHdjaWs3WEc0Z0lIMWNibjFjYmx4dVpYaHdiM0owSUdaMWJtTjBhVzl1SUcxaGRHTm9YMjV2WDNSb2NtOTNLSEJoZEhSbGNtNDZJR0Z1ZVN3Z1pYaHdjam9nWVc1NUxDQm5kV0Z5WkRvZ1JuVnVZM1JwYjI0Z1BTQW9LU0E5UGlCMGNuVmxLVG9nUDBGeWNtRjVQR0Z1ZVQ0Z2UxeHVJQ0IwY25sN1hHNGdJQ0FnY21WMGRYSnVJRzFoZEdOb0tIQmhkSFJsY200c0lHVjRjSElzSUdkMVlYSmtLVHRjYmlBZ2ZXTmhkR05vS0dVcGUxeHVJQ0FnSUdsbUtHVWdhVzV6ZEdGdVkyVnZaaUJOWVhSamFFVnljbTl5SUh4OElHVXViV1Z6YzJGblpTNXpkR0Z5ZEhOWGFYUm9LQ2RPYnlCdFlYUmphQ0JtYjNJNkp5a3BlMXh1SUNBZ0lDQWdjbVYwZFhKdUlHNTFiR3c3WEc0Z0lDQWdmVnh1WEc0Z0lDQWdkR2h5YjNjZ1pUdGNiaUFnZlZ4dWZWeHVYRzVsZUhCdmNuUWdablZ1WTNScGIyNGdjR0YwZEdWeWJrMWhjQ2hqYjJ4c1pXTjBhVzl1T2lCQmNuSmhlVHhoYm5rK0xDQndZWFIwWlhKdU9pQmhibmtzSUdaMWJqb2dSblZ1WTNScGIyNHNJR2QxWVhKa09pQkdkVzVqZEdsdmJpQTlJQ2dwSUQwK0lIUnlkV1VwT2lCQmNuSmhlVHhoYm5rK0lIdGNiaUFnYkdWMElISmxkQ0E5SUZ0ZE8xeHVYRzRnSUdadmNpaHNaWFFnWld4bGJTQnZaaUJqYjJ4c1pXTjBhVzl1S1h0Y2JpQWdJQ0IwY25sN1hHNGdJQ0FnSUNCc1pYUWdjbVZ6ZFd4MElEMGdablZ1TG1Gd2NHeDVLSFJvYVhNc0lHMWhkR05vS0hCaGRIUmxjbTRzSUdWc1pXMHNJR2QxWVhKa0tTazdYRzRnSUNBZ0lDQnlaWFFnUFNCeVpYUXVZMjl1WTJGMEtISmxjM1ZzZENrN1hHNGdJQ0FnZldOaGRHTm9LR1VwZTF4dUlDQWdJR2xtS0NFb1pTQnBibk4wWVc1alpXOW1JRTFoZEdOb1JYSnliM0lwS1h0Y2JpQWdJQ0FnSUNBZ2RHaHliM2NnWlR0Y2JpQWdJQ0FnSUgxY2JpQWdJQ0I5WEc0Z0lIMWNibHh1SUNCeVpYUjFjbTRnY21WME8xeHVmVnh1SWwwc0luTnZkWEpqWlZKdmIzUWlPaUl2YzI5MWNtTmxMeUo5XG4iLCJcblxuaW1wb3J0IHsgZGVmbWF0Y2gsIG1hdGNoLCBNYXRjaEVycm9yLCBtYXRjaF9ub190aHJvdywgcGF0dGVybk1hcCwgQ2FzZSwgbWFrZV9jYXNlIH0gZnJvbSBcIi4vcGF0dGVybnMvZGVmbWF0Y2hcIjtcbmltcG9ydCB7IHZhcmlhYmxlLCB3aWxkY2FyZCwgc3RhcnRzV2l0aCwgY2FwdHVyZSwgaGVhZFRhaWwsIHR5cGUsIGJvdW5kIH0gZnJvbSBcIi4vcGF0dGVybnMvdHlwZXNcIjtcblxuZXhwb3J0IGRlZmF1bHQge1xuICBkZWZtYXRjaCwgbWF0Y2gsIE1hdGNoRXJyb3IsIG1hdGNoX25vX3Rocm93LFxuICB2YXJpYWJsZSwgd2lsZGNhcmQsIHN0YXJ0c1dpdGgsXG4gIGNhcHR1cmUsIGhlYWRUYWlsLCB0eXBlLCBib3VuZCwgQ2FzZSwgbWFrZV9jYXNlXG59O1xuLy8jIHNvdXJjZU1hcHBpbmdVUkw9ZGF0YTphcHBsaWNhdGlvbi9qc29uO2Jhc2U2NCxleUoyWlhKemFXOXVJam96TENKemIzVnlZMlZ6SWpwYklteHBZaTlqYjNKbEwzQmhkSFJsY201ekxtcHpJbDBzSW01aGJXVnpJanBiWFN3aWJXRndjR2x1WjNNaU9pSTdPMEZCUlVFc1UwRkJVeXhSUVVGVUxFVkJRVzFDTEV0QlFXNUNMRVZCUVRCQ0xGVkJRVEZDTEVWQlFYTkRMR05CUVhSRExFVkJRWE5FTEZWQlFYUkVMRVZCUVd0RkxFbEJRV3hGTEVWQlFYZEZMRk5CUVhoRkxGRkJRWGxHTEhGQ1FVRjZSanRCUVVOQkxGTkJRVk1zVVVGQlZDeEZRVUZ0UWl4UlFVRnVRaXhGUVVFMlFpeFZRVUUzUWl4RlFVRjVReXhQUVVGNlF5eEZRVUZyUkN4UlFVRnNSQ3hGUVVFMFJDeEpRVUUxUkN4RlFVRnJSU3hMUVVGc1JTeFJRVUVyUlN4clFrRkJMMFU3TzBGQlIwRXNaVUZCWlR0QlFVTmlMRlZCUkdFc1JVRkRTQ3hMUVVSSExFVkJRMGtzVlVGRVNpeEZRVU5uUWl4alFVUm9RanRCUVVWaUxGVkJSbUVzUlVGRlNDeFJRVVpITEVWQlJVOHNWVUZHVUR0QlFVZGlMRk5CU0dFc1JVRkhTaXhSUVVoSkxFVkJSMDBzU1VGSVRpeEZRVWRaTEV0QlNGb3NSVUZIYlVJc1NVRklia0lzUlVGSGVVSXNVMEZJZWtJN1EwRkJaaUlzSW1acGJHVWlPaUpzYVdJdlkyOXlaUzl3WVhSMFpYSnVjeTVxY3lJc0luTnZkWEpqWlhORGIyNTBaVzUwSWpwYklpOHFJRUJtYkc5M0lDb3ZYRzVjYm1sdGNHOXlkQ0I3SUdSbFptMWhkR05vTENCdFlYUmphQ3dnVFdGMFkyaEZjbkp2Y2l3Z2JXRjBZMmhmYm05ZmRHaHliM2NzSUhCaGRIUmxjbTVOWVhBc0lFTmhjMlVzSUcxaGEyVmZZMkZ6WlNCOUlHWnliMjBnWENJdUwzQmhkSFJsY201ekwyUmxabTFoZEdOb1hDSTdYRzVwYlhCdmNuUWdleUIyWVhKcFlXSnNaU3dnZDJsc1pHTmhjbVFzSUhOMFlYSjBjMWRwZEdnc0lHTmhjSFIxY21Vc0lHaGxZV1JVWVdsc0xDQjBlWEJsTENCaWIzVnVaQ0I5SUdaeWIyMGdYQ0l1TDNCaGRIUmxjbTV6TDNSNWNHVnpYQ0k3WEc1Y2JseHVaWGh3YjNKMElHUmxabUYxYkhRZ2UxeHVJQ0JrWldadFlYUmphQ3dnYldGMFkyZ3NJRTFoZEdOb1JYSnliM0lzSUcxaGRHTm9YMjV2WDNSb2NtOTNMRnh1SUNCMllYSnBZV0pzWlN3Z2QybHNaR05oY21Rc0lITjBZWEowYzFkcGRHZ3NYRzRnSUdOaGNIUjFjbVVzSUdobFlXUlVZV2xzTENCMGVYQmxMQ0JpYjNWdVpDd2dRMkZ6WlN3Z2JXRnJaVjlqWVhObFhHNTlPMXh1SWwwc0luTnZkWEpqWlZKdmIzUWlPaUl2YzI5MWNtTmxMeUo5XG4iLCJpbXBvcnQgeyBJbnRlZ2VyLCBGbG9hdCB9IGZyb20gJy4vcHJpbWl0aXZlcyc7XG5cbi8vaHR0cHM6Ly9naXRodWIuY29tL2FpcnBvcnR5aC9wcm90b21vcnBoaXNtXG5jbGFzcyBQcm90b2NvbCB7XG4gIGNvbnN0cnVjdG9yKHNwZWMpIHtcbiAgICB0aGlzLnJlZ2lzdHJ5ID0gbmV3IE1hcCgpO1xuICAgIHRoaXMuZmFsbGJhY2sgPSBudWxsO1xuXG4gICAgZm9yIChsZXQgZnVuTmFtZSBpbiBzcGVjKSB7XG4gICAgICB0aGlzW2Z1bk5hbWVdID0gY3JlYXRlRnVuKGZ1bk5hbWUpLmJpbmQodGhpcyk7XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gY3JlYXRlRnVuKGZ1bk5hbWUpIHtcblxuICAgICAgcmV0dXJuIGZ1bmN0aW9uICguLi5hcmdzKSB7XG4gICAgICAgIGxldCB0aGluZyA9IGFyZ3NbMF07XG4gICAgICAgIGxldCBmdW4gPSBudWxsO1xuXG4gICAgICAgIGlmIChOdW1iZXIuaXNJbnRlZ2VyKHRoaW5nKSAmJiB0aGlzLmhhc0ltcGxlbWVudGF0aW9uKEludGVnZXIpKSB7XG4gICAgICAgICAgZnVuID0gdGhpcy5yZWdpc3RyeS5nZXQoSW50ZWdlcilbZnVuTmFtZV07XG4gICAgICAgIH0gZWxzZSBpZiAodHlwZW9mIHRoaW5nID09PSBcIm51bWJlclwiICYmICFOdW1iZXIuaXNJbnRlZ2VyKHRoaW5nKSAmJiB0aGlzLmhhc0ltcGxlbWVudGF0aW9uKEZsb2F0KSkge1xuICAgICAgICAgIGZ1biA9IHRoaXMucmVnaXN0cnkuZ2V0KEZsb2F0KVtmdW5OYW1lXTtcbiAgICAgICAgfSBlbHNlIGlmICh0aGlzLmhhc0ltcGxlbWVudGF0aW9uKHRoaW5nKSkge1xuICAgICAgICAgIGZ1biA9IHRoaXMucmVnaXN0cnkuZ2V0KHRoaW5nLmNvbnN0cnVjdG9yKVtmdW5OYW1lXTtcbiAgICAgICAgfSBlbHNlIGlmICh0aGlzLmZhbGxiYWNrKSB7XG4gICAgICAgICAgZnVuID0gdGhpcy5mYWxsYmFja1tmdW5OYW1lXTtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmIChmdW4gIT0gbnVsbCkge1xuICAgICAgICAgIGxldCByZXR2YWwgPSBmdW4uYXBwbHkodGhpcywgYXJncyk7XG4gICAgICAgICAgcmV0dXJuIHJldHZhbDtcbiAgICAgICAgfVxuXG4gICAgICAgIHRocm93IG5ldyBFcnJvcihcIk5vIGltcGxlbWVudGF0aW9uIGZvdW5kIGZvciBcIiArIHRoaW5nKTtcbiAgICAgIH07XG4gICAgfVxuICB9XG5cbiAgaW1wbGVtZW50YXRpb24odHlwZSwgaW1wbGVtZW50YXRpb24pIHtcbiAgICBpZiAodHlwZSA9PT0gbnVsbCkge1xuICAgICAgdGhpcy5mYWxsYmFjayA9IGltcGxlbWVudGF0aW9uO1xuICAgIH0gZWxzZSB7XG4gICAgICB0aGlzLnJlZ2lzdHJ5LnNldCh0eXBlLCBpbXBsZW1lbnRhdGlvbik7XG4gICAgfVxuICB9XG5cbiAgaGFzSW1wbGVtZW50YXRpb24odGhpbmcpIHtcbiAgICBpZiAodGhpbmcgPT09IEludGVnZXIgfHwgdGhpbmcgPT09IEZsb2F0KSB7XG4gICAgICByZXR1cm4gdGhpcy5yZWdpc3RyeS5oYXModGhpbmcpO1xuICAgIH1cblxuICAgIHJldHVybiB0aGlzLnJlZ2lzdHJ5Lmhhcyh0aGluZy5jb25zdHJ1Y3Rvcik7XG4gIH1cbn1cblxuZXhwb3J0IGRlZmF1bHQgUHJvdG9jb2w7XG4vLyMgc291cmNlTWFwcGluZ1VSTD1kYXRhOmFwcGxpY2F0aW9uL2pzb247YmFzZTY0LGV5SjJaWEp6YVc5dUlqb3pMQ0p6YjNWeVkyVnpJanBiSW14cFlpOWpiM0psTDNCeWIzUnZZMjlzTG1weklsMHNJbTVoYldWeklqcGJYU3dpYldGd2NHbHVaM01pT2lKQlFVRkJMRk5CUVZNc1QwRkJWQ3hGUVVGclFpeExRVUZzUWl4UlFVRXJRaXhqUVVFdlFqczdPMEZCUjBFc1RVRkJUU3hSUVVGT0xFTkJRV003UVVGRFdpeGpRVUZaTEVsQlFWb3NSVUZCYVVJN1FVRkRaaXhUUVVGTExGRkJRVXdzUjBGQlowSXNTVUZCU1N4SFFVRktMRVZCUVdoQ0xFTkJSR1U3UVVGRlppeFRRVUZMTEZGQlFVd3NSMEZCWjBJc1NVRkJhRUlzUTBGR1pUczdRVUZKWml4VFFVRkxMRWxCUVVrc1QwRkJTaXhKUVVGbExFbEJRWEJDTEVWQlFYbENPMEZCUTNaQ0xGZEJRVXNzVDBGQlRDeEpRVUZuUWl4VlFVRlZMRTlCUVZZc1JVRkJiVUlzU1VGQmJrSXNRMEZCZDBJc1NVRkJlRUlzUTBGQmFFSXNRMEZFZFVJN1MwRkJla0k3TzBGQlNVRXNZVUZCVXl4VFFVRlVMRU5CUVcxQ0xFOUJRVzVDTEVWQlFUSkNPenRCUVVWNlFpeGhRVUZQTEZWQlFWTXNSMEZCUnl4SlFVRklMRVZCUVZNN1FVRkRka0lzV1VGQlNTeFJRVUZSTEV0QlFVc3NRMEZCVEN4RFFVRlNMRU5CUkcxQ08wRkJSWFpDTEZsQlFVa3NUVUZCVFN4SlFVRk9MRU5CUm0xQ096dEJRVWwyUWl4WlFVRkhMRTlCUVU4c1UwRkJVQ3hEUVVGcFFpeExRVUZxUWl4TFFVRXlRaXhMUVVGTExHbENRVUZNTEVOQlFYVkNMRTlCUVhaQ0xFTkJRVE5DTEVWQlFUSkVPMEZCUXpWRUxHZENRVUZOTEV0QlFVc3NVVUZCVEN4RFFVRmpMRWRCUVdRc1EwRkJhMElzVDBGQmJFSXNSVUZCTWtJc1QwRkJNMElzUTBGQlRpeERRVVEwUkR0VFFVRTVSQ3hOUVVWTkxFbEJRVWNzVDBGQlR5eExRVUZRTEV0QlFXbENMRkZCUVdwQ0xFbEJRVFpDTEVOQlFVTXNUMEZCVHl4VFFVRlFMRU5CUVdsQ0xFdEJRV3BDTEVOQlFVUXNTVUZCTkVJc1MwRkJTeXhwUWtGQlRDeERRVUYxUWl4TFFVRjJRaXhEUVVGNlJDeEZRVUYxUmp0QlFVTTVSaXhuUWtGQlRTeExRVUZMTEZGQlFVd3NRMEZCWXl4SFFVRmtMRU5CUVd0Q0xFdEJRV3hDTEVWQlFYbENMRTlCUVhwQ0xFTkJRVTRzUTBGRU9FWTdVMEZCTVVZc1RVRkZRU3hKUVVGSExFdEJRVXNzYVVKQlFVd3NRMEZCZFVJc1MwRkJka0lzUTBGQlNDeEZRVUZwUXp0QlFVTnlReXhuUWtGQlRTeExRVUZMTEZGQlFVd3NRMEZCWXl4SFFVRmtMRU5CUVd0Q0xFMUJRVTBzVjBGQlRpeERRVUZzUWl4RFFVRnhReXhQUVVGeVF5eERRVUZPTEVOQlJIRkRPMU5CUVdwRExFMUJSVUVzU1VGQlJ5eExRVUZMTEZGQlFVd3NSVUZCWXp0QlFVTnlRaXhuUWtGQlRTeExRVUZMTEZGQlFVd3NRMEZCWXl4UFFVRmtMRU5CUVU0c1EwRkVjVUk3VTBGQmFrSTdPMEZCU1U0c1dVRkJSeXhQUVVGUExFbEJRVkFzUlVGQldUdEJRVU5pTEdOQlFVa3NVMEZCVXl4SlFVRkpMRXRCUVVvc1EwRkJWU3hKUVVGV0xFVkJRV2RDTEVsQlFXaENMRU5CUVZRc1EwRkVVenRCUVVWaUxHbENRVUZQTEUxQlFWQXNRMEZHWVR0VFFVRm1PenRCUVV0QkxHTkJRVTBzU1VGQlNTeExRVUZLTEVOQlFWVXNhVU5CUVdsRExFdEJRV3BETEVOQlFXaENMRU5CYmtKMVFqdFBRVUZzUWl4RFFVWnJRanRMUVVFelFqdEhRVkpHT3p0QlFXdERRU3hwUWtGQlpTeEpRVUZtTEVWQlFYRkNMR05CUVhKQ0xFVkJRVzlETzBGQlEyeERMRkZCUVVjc1UwRkJVeXhKUVVGVUxFVkJRV003UVVGRFppeFhRVUZMTEZGQlFVd3NSMEZCWjBJc1kwRkJhRUlzUTBGRVpUdExRVUZxUWl4TlFVVkxPMEZCUTBnc1YwRkJTeXhSUVVGTUxFTkJRV01zUjBGQlpDeERRVUZyUWl4SlFVRnNRaXhGUVVGM1FpeGpRVUY0UWl4RlFVUkhPMHRCUmt3N1IwRkVSanM3UVVGUlFTeHZRa0ZCYTBJc1MwRkJiRUlzUlVGQmVVSTdRVUZEZGtJc1VVRkJTU3hWUVVGVkxFOUJRVllzU1VGQmNVSXNWVUZCVlN4TFFVRldMRVZCUVdkQ08wRkJRM1pETEdGQlFVOHNTMEZCU3l4UlFVRk1MRU5CUVdNc1IwRkJaQ3hEUVVGclFpeExRVUZzUWl4RFFVRlFMRU5CUkhWRE8wdEJRWHBET3p0QlFVbEJMRmRCUVU4c1MwRkJTeXhSUVVGTUxFTkJRV01zUjBGQlpDeERRVUZyUWl4TlFVRk5MRmRCUVU0c1EwRkJla0lzUTBGTWRVSTdSMEZCZWtJN1EwRXpRMFk3TzBGQmNVUkJMR1ZCUVdVc1VVRkJaaUlzSW1acGJHVWlPaUpzYVdJdlkyOXlaUzl3Y205MGIyTnZiQzVxY3lJc0luTnZkWEpqWlhORGIyNTBaVzUwSWpwYkltbHRjRzl5ZENCN0lFbHVkR1ZuWlhJc0lFWnNiMkYwSUgwZ1puSnZiU0FuTGk5d2NtbHRhWFJwZG1Wekp6dGNibHh1THk5b2RIUndjem92TDJkcGRHaDFZaTVqYjIwdllXbHljRzl5ZEhsb0wzQnliM1J2Ylc5eWNHaHBjMjFjYm1Oc1lYTnpJRkJ5YjNSdlkyOXNlMXh1SUNCamIyNXpkSEoxWTNSdmNpaHpjR1ZqS1h0Y2JpQWdJQ0IwYUdsekxuSmxaMmx6ZEhKNUlEMGdibVYzSUUxaGNDZ3BPMXh1SUNBZ0lIUm9hWE11Wm1Gc2JHSmhZMnNnUFNCdWRXeHNPMXh1WEc0Z0lDQWdabTl5SUNoc1pYUWdablZ1VG1GdFpTQnBiaUJ6Y0dWaktYdGNiaUFnSUNBZ0lIUm9hWE5iWm5WdVRtRnRaVjBnUFNCamNtVmhkR1ZHZFc0b1puVnVUbUZ0WlNrdVltbHVaQ2gwYUdsektUdGNiaUFnSUNCOVhHNWNiaUFnSUNCbWRXNWpkR2x2YmlCamNtVmhkR1ZHZFc0b1puVnVUbUZ0WlNsN1hHNWNiaUFnSUNBZ0lISmxkSFZ5YmlCbWRXNWpkR2x2YmlndUxpNWhjbWR6S1NCN1hHNGdJQ0FnSUNBZ0lHeGxkQ0IwYUdsdVp5QTlJR0Z5WjNOYk1GMDdYRzRnSUNBZ0lDQWdJR3hsZENCbWRXNGdQU0J1ZFd4c08xeHVYRzRnSUNBZ0lDQWdJR2xtS0U1MWJXSmxjaTVwYzBsdWRHVm5aWElvZEdocGJtY3BJQ1ltSUhSb2FYTXVhR0Z6U1cxd2JHVnRaVzUwWVhScGIyNG9TVzUwWldkbGNpa3BlMXh1SUNBZ0lDQWdJQ0FnSUdaMWJpQTlJSFJvYVhNdWNtVm5hWE4wY25rdVoyVjBLRWx1ZEdWblpYSXBXMloxYms1aGJXVmRPMXh1SUNBZ0lDQWdJQ0I5Wld4elpTQnBaaWgwZVhCbGIyWWdkR2hwYm1jZ1BUMDlJRndpYm5WdFltVnlYQ0lnSmlZZ0lVNTFiV0psY2k1cGMwbHVkR1ZuWlhJb2RHaHBibWNwSUNZbUlIUm9hWE11YUdGelNXMXdiR1Z0Wlc1MFlYUnBiMjRvUm14dllYUXBLWHRjYmlBZ0lDQWdJQ0FnSUNCbWRXNGdQU0IwYUdsekxuSmxaMmx6ZEhKNUxtZGxkQ2hHYkc5aGRDbGJablZ1VG1GdFpWMDdYRzRnSUNBZ0lDQWdJSDFsYkhObElHbG1LSFJvYVhNdWFHRnpTVzF3YkdWdFpXNTBZWFJwYjI0b2RHaHBibWNwS1h0Y2JpQWdJQ0FnSUNBZ0lDQm1kVzRnUFNCMGFHbHpMbkpsWjJsemRISjVMbWRsZENoMGFHbHVaeTVqYjI1emRISjFZM1J2Y2lsYlpuVnVUbUZ0WlYwN1hHNGdJQ0FnSUNBZ0lIMWxiSE5sSUdsbUtIUm9hWE11Wm1Gc2JHSmhZMnNwZTF4dUlDQWdJQ0FnSUNBZ0lHWjFiaUE5SUhSb2FYTXVabUZzYkdKaFkydGJablZ1VG1GdFpWMDdYRzRnSUNBZ0lDQWdJSDFjYmx4dUlDQWdJQ0FnSUNCcFppaG1kVzRnSVQwZ2JuVnNiQ2w3WEc0Z0lDQWdJQ0FnSUNBZ2JHVjBJSEpsZEhaaGJDQTlJR1oxYmk1aGNIQnNlU2gwYUdsekxDQmhjbWR6S1R0Y2JpQWdJQ0FnSUNBZ0lDQnlaWFIxY200Z2NtVjBkbUZzTzF4dUlDQWdJQ0FnSUNCOVhHNWNiaUFnSUNBZ0lDQWdkR2h5YjNjZ2JtVjNJRVZ5Y205eUtGd2lUbThnYVcxd2JHVnRaVzUwWVhScGIyNGdabTkxYm1RZ1ptOXlJRndpSUNzZ2RHaHBibWNwTzF4dUlDQWdJQ0FnZlZ4dUlDQWdJSDFjYmlBZ2ZWeHVYRzRnSUdsdGNHeGxiV1Z1ZEdGMGFXOXVLSFI1Y0dVc0lHbHRjR3hsYldWdWRHRjBhVzl1S1h0Y2JpQWdJQ0JwWmloMGVYQmxJRDA5UFNCdWRXeHNLWHRjYmlBZ0lDQWdJSFJvYVhNdVptRnNiR0poWTJzZ1BTQnBiWEJzWlcxbGJuUmhkR2x2Ymp0Y2JpQWdJQ0I5Wld4elpYdGNiaUFnSUNBZ0lIUm9hWE11Y21WbmFYTjBjbmt1YzJWMEtIUjVjR1VzSUdsdGNHeGxiV1Z1ZEdGMGFXOXVLVHRjYmlBZ0lDQjlYRzRnSUgxY2JseHVJQ0JvWVhOSmJYQnNaVzFsYm5SaGRHbHZiaWgwYUdsdVp5a2dlMXh1SUNBZ0lHbG1JQ2gwYUdsdVp5QTlQVDBnU1c1MFpXZGxjaUI4ZkNCMGFHbHVaeUE5UFQwZ1JteHZZWFFwZTF4dUlDQWdJQ0FnY21WMGRYSnVJSFJvYVhNdWNtVm5hWE4wY25rdWFHRnpLSFJvYVc1bktUdGNiaUFnSUNCOVhHNWNiaUFnSUNCeVpYUjFjbTRnZEdocGN5NXlaV2RwYzNSeWVTNW9ZWE1vZEdocGJtY3VZMjl1YzNSeWRXTjBiM0lwTzF4dUlDQjlYRzU5WEc1Y2JseHVaWGh3YjNKMElHUmxabUYxYkhRZ1VISnZkRzlqYjJ3N1hHNGlYU3dpYzI5MWNtTmxVbTl2ZENJNklpOXpiM1Z5WTJVdkluMD1cbiIsImltcG9ydCB7IFR1cGxlIH0gZnJvbSAnLi9wcmltaXRpdmVzJztcbmltcG9ydCBCaXRTdHJpbmcgZnJvbSAnLi9iaXRfc3RyaW5nJztcbmltcG9ydCBQYXR0ZXJucyBmcm9tICcuL3BhdHRlcm5zJztcbmltcG9ydCBQcm90b2NvbCBmcm9tICcuL3Byb3RvY29sJztcblxuZnVuY3Rpb24gY2FsbF9wcm9wZXJ0eShpdGVtLCBwcm9wZXJ0eSkge1xuICBsZXQgcHJvcCA9IG51bGw7XG5cbiAgaWYgKHR5cGVvZiBpdGVtID09PSBcIm51bWJlclwiIHx8IHR5cGVvZiBpdGVtID09PSBcInN5bWJvbFwiIHx8IHR5cGVvZiBpdGVtID09PSBcImJvb2xlYW5cIiB8fCB0eXBlb2YgaXRlbSA9PT0gXCJzdHJpbmdcIikge1xuICAgIGlmIChpdGVtW3Byb3BlcnR5XSAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICBwcm9wID0gcHJvcGVydHk7XG4gICAgfSBlbHNlIGlmIChpdGVtW1N5bWJvbC5mb3IocHJvcGVydHkpXSAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICBwcm9wID0gU3ltYm9sLmZvcihwcm9wZXJ0eSk7XG4gICAgfVxuICB9IGVsc2Uge1xuICAgIGlmIChwcm9wZXJ0eSBpbiBpdGVtKSB7XG4gICAgICBwcm9wID0gcHJvcGVydHk7XG4gICAgfSBlbHNlIGlmIChTeW1ib2wuZm9yKHByb3BlcnR5KSBpbiBpdGVtKSB7XG4gICAgICBwcm9wID0gU3ltYm9sLmZvcihwcm9wZXJ0eSk7XG4gICAgfVxuICB9XG5cbiAgaWYgKHByb3AgPT09IG51bGwpIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoYFByb3BlcnR5ICR7IHByb3BlcnR5IH0gbm90IGZvdW5kIGluICR7IGl0ZW0gfWApO1xuICB9XG5cbiAgaWYgKGl0ZW1bcHJvcF0gaW5zdGFuY2VvZiBGdW5jdGlvbikge1xuICAgIHJldHVybiBpdGVtW3Byb3BdKCk7XG4gIH0gZWxzZSB7XG4gICAgcmV0dXJuIGl0ZW1bcHJvcF07XG4gIH1cbn1cblxuZnVuY3Rpb24gYXBwbHkoLi4uYXJncykge1xuICBpZiAoYXJncy5sZW5ndGggPT09IDIpIHtcbiAgICBhcmdzWzBdLmFwcGx5KG51bGwsIGFyZ3Muc2xpY2UoMSkpO1xuICB9IGVsc2Uge1xuICAgIGFyZ3NbMF1bYXJnc1sxXV0uYXBwbHkobnVsbCwgYXJncy5zbGljZSgyKSk7XG4gIH1cbn1cblxuZnVuY3Rpb24gY29udGFpbnMobGVmdCwgcmlnaHQpIHtcbiAgZm9yIChsZXQgeCBvZiByaWdodCkge1xuICAgIGlmIChQYXR0ZXJucy5tYXRjaF9ub190aHJvdyhsZWZ0LCB4KSAhPSBudWxsKSB7XG4gICAgICByZXR1cm4gdHJ1ZTtcbiAgICB9XG4gIH1cblxuICByZXR1cm4gZmFsc2U7XG59XG5cbmZ1bmN0aW9uIGdldF9nbG9iYWwoKSB7XG4gIGlmICh0eXBlb2Ygc2VsZiAhPT0gXCJ1bmRlZmluZWRcIikge1xuICAgIHJldHVybiBzZWxmO1xuICB9IGVsc2UgaWYgKHR5cGVvZiB3aW5kb3cgIT09IFwidW5kZWZpbmVkXCIpIHtcbiAgICByZXR1cm4gd2luZG93O1xuICB9IGVsc2UgaWYgKHR5cGVvZiBnbG9iYWwgIT09IFwidW5kZWZpbmVkXCIpIHtcbiAgICByZXR1cm4gZ2xvYmFsO1xuICB9XG5cbiAgdGhyb3cgbmV3IEVycm9yKFwiTm8gZ2xvYmFsIHN0YXRlIGZvdW5kXCIpO1xufVxuXG5mdW5jdGlvbiBkZWZzdHJ1Y3QoZGVmYXVsdHMpIHtcbiAgcmV0dXJuIGNsYXNzIHtcbiAgICBjb25zdHJ1Y3Rvcih1cGRhdGUgPSB7fSkge1xuICAgICAgbGV0IHRoZV92YWx1ZXMgPSBPYmplY3QuYXNzaWduKGRlZmF1bHRzLCB1cGRhdGUpO1xuICAgICAgT2JqZWN0LmFzc2lnbih0aGlzLCB0aGVfdmFsdWVzKTtcbiAgICB9XG5cbiAgICBzdGF0aWMgY3JlYXRlKHVwZGF0ZXMgPSB7fSkge1xuICAgICAgbGV0IHggPSBuZXcgdGhpcyh1cGRhdGVzKTtcbiAgICAgIHJldHVybiBPYmplY3QuZnJlZXplKHgpO1xuICAgIH1cbiAgfTtcbn1cblxuZnVuY3Rpb24gZGVmZXhjZXB0aW9uKGRlZmF1bHRzKSB7XG4gIHJldHVybiBjbGFzcyBleHRlbmRzIEVycm9yIHtcbiAgICBjb25zdHJ1Y3Rvcih1cGRhdGUgPSB7fSkge1xuICAgICAgbGV0IG1lc3NhZ2UgPSB1cGRhdGUubWVzc2FnZSB8fCBcIlwiO1xuICAgICAgc3VwZXIobWVzc2FnZSk7XG5cbiAgICAgIGxldCB0aGVfdmFsdWVzID0gT2JqZWN0LmFzc2lnbihkZWZhdWx0cywgdXBkYXRlKTtcbiAgICAgIE9iamVjdC5hc3NpZ24odGhpcywgdGhlX3ZhbHVlcyk7XG5cbiAgICAgIHRoaXMubmFtZSA9IHRoaXMuY29uc3RydWN0b3IubmFtZTtcbiAgICAgIHRoaXMubWVzc2FnZSA9IG1lc3NhZ2U7XG4gICAgICB0aGlzW1NwZWNpYWxGb3Jtcy5hdG9tKFwiX19leGNlcHRpb25fX1wiKV0gPSB0cnVlO1xuICAgICAgRXJyb3IuY2FwdHVyZVN0YWNrVHJhY2UodGhpcywgdGhpcy5jb25zdHJ1Y3Rvci5uYW1lKTtcbiAgICB9XG5cbiAgICBzdGF0aWMgY3JlYXRlKHVwZGF0ZXMgPSB7fSkge1xuICAgICAgbGV0IHggPSBuZXcgdGhpcyh1cGRhdGVzKTtcbiAgICAgIHJldHVybiBPYmplY3QuZnJlZXplKHgpO1xuICAgIH1cbiAgfTtcbn1cblxuZnVuY3Rpb24gZGVmcHJvdG9jb2woc3BlYykge1xuICByZXR1cm4gbmV3IFByb3RvY29sKHNwZWMpO1xufVxuXG5mdW5jdGlvbiBkZWZpbXBsKHByb3RvY29sLCB0eXBlLCBpbXBsKSB7XG4gIHByb3RvY29sLmltcGxlbWVudGF0aW9uKHR5cGUsIGltcGwpO1xufVxuXG5mdW5jdGlvbiBnZXRfb2JqZWN0X2tleXMob2JqKSB7XG4gIHJldHVybiBPYmplY3Qua2V5cyhvYmopLmNvbmNhdChPYmplY3QuZ2V0T3duUHJvcGVydHlTeW1ib2xzKG9iaikpO1xufVxuXG5mdW5jdGlvbiBpc192YWxpZF9jaGFyYWN0ZXIoY29kZXBvaW50KSB7XG4gIHRyeSB7XG4gICAgcmV0dXJuIFN0cmluZy5mcm9tQ29kZVBvaW50KGNvZGVwb2ludCkgIT0gbnVsbDtcbiAgfSBjYXRjaCAoZSkge1xuICAgIHJldHVybiBmYWxzZTtcbiAgfVxufVxuXG4vL2h0dHBzOi8vZGV2ZWxvcGVyLm1vemlsbGEub3JnL2VuLVVTL2RvY3MvV2ViL0FQSS9XaW5kb3dCYXNlNjQvQmFzZTY0X2VuY29kaW5nX2FuZF9kZWNvZGluZyNTb2x1dGlvbl8yXyVFMiU4MCU5M19yZXdyaXRlX3RoZV9ET01zX2F0b2IoKV9hbmRfYnRvYSgpX3VzaW5nX0phdmFTY3JpcHQnc19UeXBlZEFycmF5c19hbmRfVVRGLThcbmZ1bmN0aW9uIGI2NEVuY29kZVVuaWNvZGUoc3RyKSB7XG4gIHJldHVybiBidG9hKGVuY29kZVVSSUNvbXBvbmVudChzdHIpLnJlcGxhY2UoLyUoWzAtOUEtRl17Mn0pL2csIGZ1bmN0aW9uIChtYXRjaCwgcDEpIHtcbiAgICByZXR1cm4gU3RyaW5nLmZyb21DaGFyQ29kZSgnMHgnICsgcDEpO1xuICB9KSk7XG59XG5cbmZ1bmN0aW9uIGRlbGV0ZV9wcm9wZXJ0eV9mcm9tX21hcChtYXAsIHByb3BlcnR5KSB7XG4gIGxldCBuZXdfbWFwID0gT2JqZWN0LmFzc2lnbihPYmplY3QuY3JlYXRlKG1hcC5jb25zdHJ1Y3Rvci5wcm90b3R5cGUpLCBtYXApO1xuICBkZWxldGUgbmV3X21hcFtwcm9wZXJ0eV07XG5cbiAgcmV0dXJuIE9iamVjdC5mcmVlemUobmV3X21hcCk7XG59XG5cbmZ1bmN0aW9uIGNsYXNzX3RvX29iaihtYXApIHtcbiAgbGV0IG5ld19tYXAgPSBPYmplY3QuYXNzaWduKHt9LCBtYXApO1xuICByZXR1cm4gT2JqZWN0LmZyZWV6ZShuZXdfbWFwKTtcbn1cblxuZnVuY3Rpb24gYWRkX3Byb3BlcnR5X3RvX21hcChtYXAsIHByb3BlcnR5LCB2YWx1ZSkge1xuICBsZXQgbmV3X21hcCA9IE9iamVjdC5hc3NpZ24oe30sIG1hcCk7XG4gIG5ld19tYXBbcHJvcGVydHldID0gdmFsdWU7XG4gIHJldHVybiBPYmplY3QuZnJlZXplKG5ld19tYXApO1xufVxuXG5mdW5jdGlvbiB1cGRhdGVfbWFwKG1hcCwgcHJvcGVydHksIHZhbHVlKSB7XG4gIGlmIChwcm9wZXJ0eSBpbiBnZXRfb2JqZWN0X2tleXMobWFwKSkge1xuICAgIHJldHVybiBhZGRfcHJvcGVydHlfdG9fbWFwKG1hcCwgcHJvcGVydHksIHZhbHVlKTtcbiAgfVxuXG4gIHRocm93IFwibWFwIGRvZXMgbm90IGhhdmUga2V5XCI7XG59XG5cbmZ1bmN0aW9uIGJub3QoZXhwcikge1xuICByZXR1cm4gfmV4cHI7XG59XG5cbmZ1bmN0aW9uIGJhbmQobGVmdCwgcmlnaHQpIHtcbiAgcmV0dXJuIGxlZnQgJiByaWdodDtcbn1cblxuZnVuY3Rpb24gYm9yKGxlZnQsIHJpZ2h0KSB7XG4gIHJldHVybiBsZWZ0IHwgcmlnaHQ7XG59XG5cbmZ1bmN0aW9uIGJzbChsZWZ0LCByaWdodCkge1xuICByZXR1cm4gbGVmdCA8PCByaWdodDtcbn1cblxuZnVuY3Rpb24gYnNyKGxlZnQsIHJpZ2h0KSB7XG4gIHJldHVybiBsZWZ0ID4+IHJpZ2h0O1xufVxuXG5mdW5jdGlvbiBieG9yKGxlZnQsIHJpZ2h0KSB7XG4gIHJldHVybiBsZWZ0IF4gcmlnaHQ7XG59XG5cbmZ1bmN0aW9uIHppcChsaXN0X29mX2xpc3RzKSB7XG4gIGlmIChsaXN0X29mX2xpc3RzLmxlbmd0aCA9PT0gMCkge1xuICAgIHJldHVybiBPYmplY3QuZnJlZXplKFtdKTtcbiAgfVxuXG4gIGxldCBuZXdfdmFsdWUgPSBbXTtcbiAgbGV0IHNtYWxsZXN0X2xlbmd0aCA9IGxpc3Rfb2ZfbGlzdHNbMF07XG5cbiAgZm9yIChsZXQgeCBvZiBsaXN0X29mX2xpc3RzKSB7XG4gICAgaWYgKHgubGVuZ3RoIDwgc21hbGxlc3RfbGVuZ3RoKSB7XG4gICAgICBzbWFsbGVzdF9sZW5ndGggPSB4Lmxlbmd0aDtcbiAgICB9XG4gIH1cblxuICBmb3IgKGxldCBpID0gMDsgaSA8IHNtYWxsZXN0X2xlbmd0aDsgaSsrKSB7XG4gICAgbGV0IGN1cnJlbnRfdmFsdWUgPSBbXTtcbiAgICBmb3IgKGxldCBqID0gMDsgaiA8IGxpc3Rfb2ZfbGlzdHMubGVuZ3RoOyBqKyspIHtcbiAgICAgIGN1cnJlbnRfdmFsdWUucHVzaChsaXN0X29mX2xpc3RzW2pdW2ldKTtcbiAgICB9XG5cbiAgICBuZXdfdmFsdWUucHVzaChuZXcgVHVwbGUoLi4uY3VycmVudF92YWx1ZSkpO1xuICB9XG5cbiAgcmV0dXJuIE9iamVjdC5mcmVlemUobmV3X3ZhbHVlKTtcbn1cblxuZnVuY3Rpb24gY2FuX2RlY29kZTY0KGRhdGEpIHtcbiAgdHJ5IHtcbiAgICBhdG9iKGRhdGEpO1xuICAgIHJldHVybiB0cnVlO1xuICB9IGNhdGNoIChlKSB7XG4gICAgcmV0dXJuIGZhbHNlO1xuICB9XG59XG5cbmZ1bmN0aW9uIHJlbW92ZV9mcm9tX2xpc3QobGlzdCwgZWxlbWVudCkge1xuICBsZXQgZm91bmQgPSBmYWxzZTtcblxuICByZXR1cm4gbGlzdC5maWx0ZXIoZWxlbSA9PiB7XG4gICAgaWYgKCFmb3VuZCAmJiBlbGVtID09PSBlbGVtZW50KSB7XG4gICAgICBmb3VuZCA9IHRydWU7XG4gICAgICByZXR1cm4gZmFsc2U7XG4gICAgfVxuXG4gICAgcmV0dXJuIHRydWU7XG4gIH0pO1xufVxuXG5mdW5jdGlvbiBmb2xkbChmdW4sIGFjYywgbGlzdCkge1xuICBsZXQgYWNjMSA9IGFjYztcblxuICBmb3IgKGNvbnN0IGVsIG9mIGxpc3QpIHtcbiAgICBhY2MxID0gZnVuKGVsLCBhY2MxKTtcbiAgfVxuXG4gIHJldHVybiBhY2MxO1xufVxuXG5mdW5jdGlvbiBmb2xkcihmdW4sIGFjYywgbGlzdCkge1xuICBsZXQgYWNjMSA9IGFjYztcblxuICBmb3IgKGxldCBpID0gbGlzdC5sZW5ndGggLSAxOyBpID49IDA7IGktLSkge1xuICAgIGFjYzEgPSBmdW4obGlzdFtpXSwgYWNjMSk7XG4gIH1cblxuICByZXR1cm4gYWNjMTtcbn1cblxuZnVuY3Rpb24ga2V5ZmluZChrZXksIG4sIHR1cGxlbGlzdCkge1xuXG4gIGZvciAobGV0IGkgPSB0dXBsZWxpc3QubGVuZ3RoIC0gMTsgaSA+PSAwOyBpLS0pIHtcbiAgICBpZiAodHVwbGVsaXN0W2ldLmdldChuKSA9PT0ga2V5KSB7XG4gICAgICByZXR1cm4gdHVwbGVsaXN0W2ldO1xuICAgIH1cbiAgfVxuXG4gIHJldHVybiBmYWxzZTtcbn1cblxuZnVuY3Rpb24ga2V5ZGVsZXRlKGtleSwgbiwgdHVwbGVsaXN0KSB7XG5cbiAgZm9yIChsZXQgaSA9IHR1cGxlbGlzdC5sZW5ndGggLSAxOyBpID49IDA7IGktLSkge1xuICAgIGlmICh0dXBsZWxpc3RbaV0uZ2V0KG4pID09PSBrZXkpIHtcbiAgICAgIHJldHVybiB0dXBsZWxpc3QuY29uY2F0KFtdKS5zcGxpY2UoaSwgMSk7XG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIHR1cGxlbGlzdDtcbn1cblxuZnVuY3Rpb24ga2V5c3RvcmUoa2V5LCBuLCBsaXN0LCBuZXd0dXBsZSkge1xuICBmb3IgKGxldCBpID0gbGlzdC5sZW5ndGggLSAxOyBpID49IDA7IGktLSkge1xuICAgIGlmIChsaXN0W2ldLmdldChuKSA9PT0ga2V5KSB7XG4gICAgICByZXR1cm4gbGlzdC5jb25jYXQoW10pLnNwbGljZShpLCAxLCBuZXd0dXBsZSk7XG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIGxpc3QuY29uY2F0KFtdKS5wdXNoKG5ld3R1cGxlKTtcbn1cblxuZnVuY3Rpb24ga2V5bWVtYmVyKGtleSwgbiwgbGlzdCkge1xuICBmb3IgKGxldCBpID0gbGlzdC5sZW5ndGggLSAxOyBpID49IDA7IGktLSkge1xuICAgIGlmIChsaXN0W2ldLmdldChuKSA9PT0ga2V5KSB7XG4gICAgICByZXR1cm4gdHJ1ZTtcbiAgICB9XG4gIH1cblxuICByZXR1cm4gZmFsc2U7XG59XG5cbmZ1bmN0aW9uIGtleXRha2Uoa2V5LCBuLCBsaXN0KSB7XG4gIGlmICgha2V5bWVtYmVyKGtleSwgbiwgbGlzdCkpIHtcbiAgICByZXR1cm4gZmFsc2U7XG4gIH1cblxuICBsZXQgdHVwbGUgPSBrZXlmaW5kKGtleSwgbiwgbGlzdCk7XG5cbiAgcmV0dXJuIG5ldyBUdXBsZSh0dXBsZS5nZXQobiksIHR1cGxlLCBrZXlkZWxldGUoa2V5LCBuLCBsaXN0KSk7XG59XG5cbmZ1bmN0aW9uIGtleXJlcGxhY2Uoa2V5LCBuLCBsaXN0LCBuZXd0dXBsZSkge1xuXG4gIGZvciAobGV0IGkgPSB0dXBsZWxpc3QubGVuZ3RoIC0gMTsgaSA+PSAwOyBpLS0pIHtcbiAgICBpZiAodHVwbGVsaXN0W2ldLmdldChuKSA9PT0ga2V5KSB7XG4gICAgICByZXR1cm4gdHVwbGVsaXN0LmNvbmNhdChbXSkuc3BsaWNlKGksIDEsIG5ld3R1cGxlKTtcbiAgICB9XG4gIH1cblxuICByZXR1cm4gdHVwbGVsaXN0O1xufVxuXG5mdW5jdGlvbiByZXZlcnNlKGxpc3QpIHtcbiAgcmV0dXJuIGxpc3QuY29uY2F0KFtdKS5yZXZlcnNlKCk7XG59XG5cbmZ1bmN0aW9uIG1hcHNfZmluZChrZXksIG1hcCkge1xuICBpZiAoa2V5IGluIGdldF9vYmplY3Rfa2V5cyhtYXApKSB7XG4gICAgcmV0dXJuIG5ldyBUdXBsZShTeW1ib2wuZm9yKFwib2tcIiksIG1hcFtrZXldKTtcbiAgfSBlbHNlIHtcbiAgICByZXR1cm4gU3ltYm9sLmZvcihcImVycm9yXCIpO1xuICB9XG59XG5cbmZ1bmN0aW9uIGZsYXR0ZW4obGlzdCwgdGFpbCA9IFtdKSB7XG4gIGxldCBuZXdfbGlzdCA9IFtdO1xuXG4gIGZvciAobGV0IGUgb2YgbGlzdCkge1xuICAgIGlmIChpc0FycmF5KGUpKSB7XG4gICAgICBuZXdfbGlzdCA9IG5ld19saXN0LmNvbmNhdChmbGF0dGVuKGUpKTtcbiAgICB9IGVsc2Uge1xuICAgICAgbmV3X2xpc3QucHVzaChlKTtcbiAgICB9XG4gIH1cblxuICByZXR1cm4gT2JqZWN0LmZyZWV6ZShuZXdfbGlzdC5jb25jYXQodGFpbCkpO1xufVxuXG5mdW5jdGlvbiBkdXBsaWNhdGUobiwgZWxlbSkge1xuICBsZXQgbGlzdCA9IFtdO1xuXG4gIGZvciAobGV0IGkgPSAwOyBpIDwgbjsgaSsrKSB7XG4gICAgbGlzdC5wdXNoKGVsZW0pO1xuICB9XG5cbiAgcmV0dXJuIE9iamVjdC5mcmVlemUobGlzdCk7XG59XG5cbmZ1bmN0aW9uIG1hcGZvbGRsKGZ1biwgYWNjLCBsaXN0KSB7XG4gIGxldCBuZXdsaXN0ID0gW107XG5cbiAgZm9yIChsZXQgeCBvZiBsaXN0KSB7XG4gICAgbGV0IHR1cCA9IGZ1bih4LCBhY2MpO1xuICAgIG5ld2xpc3QucHVzaCh0dXAuZ2V0KDApKTtcbiAgICBhY2MgPSB0dXAuZ2V0KDEpO1xuICB9XG5cbiAgcmV0dXJuIG5ldyBUdXBsZShPYmplY3QuZnJlZXplKG5ld2xpc3QpLCBhY2MpO1xufVxuXG5mdW5jdGlvbiBmaWx0ZXJtYXAoZnVuLCBsaXN0KSB7XG4gIGxldCBuZXdsaXN0ID0gW107XG5cbiAgZm9yICh4IG9mIGxpc3QpIHtcbiAgICBsZXQgcmVzdWx0ID0gZnVuKHgpO1xuXG4gICAgaWYgKHJlc3VsdCA9PT0gdHJ1ZSkge1xuICAgICAgbmV3bGlzdC5wdXNoKHgpO1xuICAgIH0gZWxzZSBpZiAocmVzdWx0IGluc3RhbmNlb2YgVHVwbGUpIHtcbiAgICAgIG5ld2xpc3QucHVzaChyZXN1bHQuZ2V0KDEpKTtcbiAgICB9XG4gIH1cblxuICByZXR1cm4gT2JqZWN0LmZyZWV6ZShuZXdsaXN0KTtcbn1cblxuZnVuY3Rpb24gbWFwc19mb2xkKGZ1biwgYWNjLCBtYXApIHtcbiAgbGV0IGFjYzEgPSBhY2M7XG5cbiAgZm9yIChsZXQgayBvZiBnZXRfb2JqZWN0X2tleXMobWFwKSkge1xuICAgIGFjYzEgPSBmdW4oaywgbWFwW2tdLCBhY2MxKTtcbiAgfVxuXG4gIHJldHVybiBhY2MxO1xufVxuXG5mdW5jdGlvbiBtYXBzX2Zyb21fbGlzdChsaXN0KSB7XG4gIGxldCBtID0ge307XG5cbiAgZm9yICh4IG9mIGxpc3QpIHtcbiAgICBtW3guZ2V0KDApXSA9IHguZ2V0KDEpO1xuICB9XG5cbiAgcmV0dXJuIE9iamVjdC5mcmVlemUobSk7XG59XG5cbmV4cG9ydCBkZWZhdWx0IHtcbiAgY2FsbF9wcm9wZXJ0eSxcbiAgYXBwbHksXG4gIGNvbnRhaW5zLFxuICBnZXRfZ2xvYmFsLFxuICBkZWZzdHJ1Y3QsXG4gIGRlZmV4Y2VwdGlvbixcbiAgZGVmcHJvdG9jb2wsXG4gIGRlZmltcGwsXG4gIGdldF9vYmplY3Rfa2V5cyxcbiAgaXNfdmFsaWRfY2hhcmFjdGVyLFxuICBiNjRFbmNvZGVVbmljb2RlLFxuICBkZWxldGVfcHJvcGVydHlfZnJvbV9tYXAsXG4gIGFkZF9wcm9wZXJ0eV90b19tYXAsXG4gIGNsYXNzX3RvX29iaixcbiAgY2FuX2RlY29kZTY0LFxuICBibm90LFxuICBiYW5kLFxuICBib3IsXG4gIGJzbCxcbiAgYnNyLFxuICBieG9yLFxuICB6aXAsXG4gIGZvbGRsLFxuICBmb2xkcixcbiAgcmVtb3ZlX2Zyb21fbGlzdCxcbiAga2V5ZGVsZXRlLFxuICBrZXlzdG9yZSxcbiAga2V5ZmluZCxcbiAga2V5dGFrZSxcbiAga2V5cmVwbGFjZSxcbiAgcmV2ZXJzZSxcbiAgdXBkYXRlX21hcCxcbiAgbWFwc19maW5kLFxuICBmbGF0dGVuLFxuICBkdXBsaWNhdGUsXG4gIG1hcGZvbGRsLFxuICBmaWx0ZXJtYXAsXG4gIG1hcHNfZm9sZFxufTtcbi8vIyBzb3VyY2VNYXBwaW5nVVJMPWRhdGE6YXBwbGljYXRpb24vanNvbjtiYXNlNjQsZXlKMlpYSnphVzl1SWpvekxDSnpiM1Z5WTJWeklqcGJJbXhwWWk5amIzSmxMMloxYm1OMGFXOXVjeTVxY3lKZExDSnVZVzFsY3lJNlcxMHNJbTFoY0hCcGJtZHpJam9pUVVGQlFTeFRRVUZUTEV0QlFWUXNVVUZCYzBJc1kwRkJkRUk3UVVGRFFTeFBRVUZQTEZOQlFWQXNUVUZCYzBJc1kwRkJkRUk3UVVGRFFTeFBRVUZQTEZGQlFWQXNUVUZCY1VJc1dVRkJja0k3UVVGRFFTeFBRVUZQTEZGQlFWQXNUVUZCY1VJc1dVRkJja0k3TzBGQlJVRXNVMEZCVXl4aFFVRlVMRU5CUVhWQ0xFbEJRWFpDTEVWQlFUWkNMRkZCUVRkQ0xFVkJRWE5ETzBGQlEzQkRMRTFCUVVrc1QwRkJUeXhKUVVGUUxFTkJSR2RET3p0QlFVZHdReXhOUVVGSExFOUJRVThzU1VGQlVDeExRVUZuUWl4UlFVRm9RaXhKUVVFMFFpeFBRVUZQTEVsQlFWQXNTMEZCWjBJc1VVRkJhRUlzU1VGQk5FSXNUMEZCVHl4SlFVRlFMRXRCUVdkQ0xGTkJRV2hDTEVsQlFUWkNMRTlCUVU4c1NVRkJVQ3hMUVVGblFpeFJRVUZvUWl4RlFVRjVRanRCUVVNdlJ5eFJRVUZITEV0QlFVc3NVVUZCVEN4TlFVRnRRaXhUUVVGdVFpeEZRVUUyUWp0QlFVTTVRaXhoUVVGUExGRkJRVkFzUTBGRU9FSTdTMEZCYUVNc1RVRkZUU3hKUVVGSExFdEJRVXNzVDBGQlR5eEhRVUZRTEVOQlFWY3NVVUZCV0N4RFFVRk1MRTFCUVN0Q0xGTkJRUzlDTEVWQlFYbERPMEZCUTJoRUxHRkJRVThzVDBGQlR5eEhRVUZRTEVOQlFWY3NVVUZCV0N4RFFVRlFMRU5CUkdkRU8wdEJRVFZETzBkQlNGSXNUVUZOVHp0QlFVTk1MRkZCUVVjc1dVRkJXU3hKUVVGYUxFVkJRV2xDTzBGQlEyeENMR0ZCUVU4c1VVRkJVQ3hEUVVSclFqdExRVUZ3UWl4TlFVVk5MRWxCUVVjc1QwRkJUeXhIUVVGUUxFTkJRVmNzVVVGQldDeExRVUYzUWl4SlFVRjRRaXhGUVVFMlFqdEJRVU53UXl4aFFVRlBMRTlCUVU4c1IwRkJVQ3hEUVVGWExGRkJRVmdzUTBGQlVDeERRVVJ2UXp0TFFVRm9RenRIUVZSU096dEJRV05CTEUxQlFVY3NVMEZCVXl4SlFVRlVMRVZCUVdNN1FVRkRaaXhWUVVGTkxFbEJRVWtzUzBGQlNpeERRVUZWTEVOQlFVTXNVMEZCUkN4SFFVRmhMRkZCUVdJc1JVRkJkVUlzWTBGQmRrSXNSMEZCZDBNc1NVRkJlRU1zUlVGQk9FTXNRMEZCZUVRc1EwRkJUaXhEUVVSbE8wZEJRV3BDT3p0QlFVbEJMRTFCUVVjc1MwRkJTeXhKUVVGTUxHRkJRWE5DTEZGQlFYUkNMRVZCUVN0Q08wRkJRMmhETEZkQlFVOHNTMEZCU3l4SlFVRk1MRWRCUVZBc1EwRkVaME03UjBGQmJFTXNUVUZGU3p0QlFVTklMRmRCUVU4c1MwRkJTeXhKUVVGTUxFTkJRVkFzUTBGRVJ6dEhRVVpNTzBOQmNrSkdPenRCUVRSQ1FTeFRRVUZUTEV0QlFWUXNRMEZCWlN4SFFVRkhMRWxCUVVnc1JVRkJVVHRCUVVOeVFpeE5RVUZITEV0QlFVc3NUVUZCVEN4TFFVRm5RaXhEUVVGb1FpeEZRVUZyUWp0QlFVTnVRaXhUUVVGTExFTkJRVXdzUlVGQlVTeExRVUZTTEVOQlFXTXNTVUZCWkN4RlFVRnZRaXhMUVVGTExFdEJRVXdzUTBGQlZ5eERRVUZZTEVOQlFYQkNMRVZCUkcxQ08wZEJRWEpDTEUxQlJVczdRVUZEU0N4VFFVRkxMRU5CUVV3c1JVRkJVU3hMUVVGTExFTkJRVXdzUTBGQlVpeEZRVUZwUWl4TFFVRnFRaXhEUVVGMVFpeEpRVUYyUWl4RlFVRTJRaXhMUVVGTExFdEJRVXdzUTBGQlZ5eERRVUZZTEVOQlFUZENMRVZCUkVjN1IwRkdURHREUVVSR096dEJRVkZCTEZOQlFWTXNVVUZCVkN4RFFVRnJRaXhKUVVGc1FpeEZRVUYzUWl4TFFVRjRRaXhGUVVFNFFqdEJRVU0xUWl4UFFVRkpMRWxCUVVrc1EwRkJTaXhKUVVGVExFdEJRV0lzUlVGQmJVSTdRVUZEYWtJc1VVRkJSeXhUUVVGVExHTkJRVlFzUTBGQmQwSXNTVUZCZUVJc1JVRkJPRUlzUTBGQk9VSXNTMEZCYjBNc1NVRkJjRU1zUlVGQmVVTTdRVUZETVVNc1lVRkJUeXhKUVVGUUxFTkJSREJETzB0QlFUVkRPMGRCUkVZN08wRkJUVUVzVTBGQlR5eExRVUZRTEVOQlVEUkNPME5CUVRsQ096dEJRVlZCTEZOQlFWTXNWVUZCVkN4SFFVRnhRanRCUVVOdVFpeE5RVUZITEU5QlFVOHNTVUZCVUN4TFFVRnBRaXhYUVVGcVFpeEZRVUUyUWp0QlFVTTVRaXhYUVVGUExFbEJRVkFzUTBGRU9FSTdSMEZCYUVNc1RVRkZUU3hKUVVGSExFOUJRVThzVFVGQlVDeExRVUZ0UWl4WFFVRnVRaXhGUVVFclFqdEJRVU4wUXl4WFFVRlBMRTFCUVZBc1EwRkVjME03UjBGQmJFTXNUVUZGUVN4SlFVRkhMRTlCUVU4c1RVRkJVQ3hMUVVGdFFpeFhRVUZ1UWl4RlFVRXJRanRCUVVOMFF5eFhRVUZQTEUxQlFWQXNRMEZFYzBNN1IwRkJiRU03TzBGQlNVNHNVVUZCVFN4SlFVRkpMRXRCUVVvc1EwRkJWU3gxUWtGQlZpeERRVUZPTEVOQlZHMUNPME5CUVhKQ096dEJRVmxCTEZOQlFWTXNVMEZCVkN4RFFVRnRRaXhSUVVGdVFpeEZRVUUwUWp0QlFVTXhRaXhUUVVGUExFMUJRVTA3UVVGRFdDeG5Ra0ZCV1N4VFFVRlRMRVZCUVZRc1JVRkJXVHRCUVVOMFFpeFZRVUZKTEdGQlFXRXNUMEZCVHl4TlFVRlFMRU5CUVdNc1VVRkJaQ3hGUVVGM1FpeE5RVUY0UWl4RFFVRmlMRU5CUkd0Q08wRkJSWFJDTEdGQlFVOHNUVUZCVUN4RFFVRmpMRWxCUVdRc1JVRkJiMElzVlVGQmNFSXNSVUZHYzBJN1MwRkJlRUk3TzBGQlMwRXNWMEZCVHl4TlFVRlFMRU5CUVdNc1ZVRkJWU3hGUVVGV0xFVkJRV0U3UVVGRGVrSXNWVUZCU1N4SlFVRkpMRWxCUVVrc1NVRkJTaXhEUVVGVExFOUJRVlFzUTBGQlNpeERRVVJ4UWp0QlFVVjZRaXhoUVVGUExFOUJRVThzVFVGQlVDeERRVUZqTEVOQlFXUXNRMEZCVUN4RFFVWjVRanRMUVVFelFqdEhRVTVMTEVOQlJHMUNPME5CUVRWQ096dEJRV1ZCTEZOQlFWTXNXVUZCVkN4RFFVRnpRaXhSUVVGMFFpeEZRVUVyUWp0QlFVTTNRaXhUUVVGUExHTkJRV01zUzBGQlpDeERRVUZ2UWp0QlFVTjZRaXhuUWtGQldTeFRRVUZUTEVWQlFWUXNSVUZCV1R0QlFVTjBRaXhWUVVGSkxGVkJRVlVzVDBGQlR5eFBRVUZRTEVsQlFXdENMRVZCUVd4Q0xFTkJSRkU3UVVGRmRFSXNXVUZCVFN4UFFVRk9MRVZCUm5OQ096dEJRVWwwUWl4VlFVRkpMR0ZCUVdFc1QwRkJUeXhOUVVGUUxFTkJRV01zVVVGQlpDeEZRVUYzUWl4TlFVRjRRaXhEUVVGaUxFTkJTbXRDTzBGQlMzUkNMR0ZCUVU4c1RVRkJVQ3hEUVVGakxFbEJRV1FzUlVGQmIwSXNWVUZCY0VJc1JVRk1jMEk3TzBGQlQzUkNMRmRCUVVzc1NVRkJUQ3hIUVVGWkxFdEJRVXNzVjBGQlRDeERRVUZwUWl4SlFVRnFRaXhEUVZCVk8wRkJVWFJDTEZkQlFVc3NUMEZCVEN4SFFVRmxMRTlCUVdZc1EwRlNjMEk3UVVGVGRFSXNWMEZCU3l4aFFVRmhMRWxCUVdJc1EwRkJhMElzWlVGQmJFSXNRMEZCVEN4SlFVRXlReXhKUVVFelF5eERRVlJ6UWp0QlFWVjBRaXhaUVVGTkxHbENRVUZPTEVOQlFYZENMRWxCUVhoQ0xFVkJRVGhDTEV0QlFVc3NWMEZCVEN4RFFVRnBRaXhKUVVGcVFpeERRVUU1UWl4RFFWWnpRanRMUVVGNFFqczdRVUZoUVN4WFFVRlBMRTFCUVZBc1EwRkJZeXhWUVVGVkxFVkJRVllzUlVGQllUdEJRVU42UWl4VlFVRkpMRWxCUVVrc1NVRkJTU3hKUVVGS0xFTkJRVk1zVDBGQlZDeERRVUZLTEVOQlJIRkNPMEZCUlhwQ0xHRkJRVThzVDBGQlR5eE5RVUZRTEVOQlFXTXNRMEZCWkN4RFFVRlFMRU5CUm5sQ08wdEJRVE5DTzBkQlpFc3NRMEZFYzBJN1EwRkJMMEk3TzBGQmMwSkJMRk5CUVZNc1YwRkJWQ3hEUVVGeFFpeEpRVUZ5UWl4RlFVRXdRanRCUVVONFFpeFRRVUZQTEVsQlFVa3NVVUZCU2l4RFFVRmhMRWxCUVdJc1EwRkJVQ3hEUVVSM1FqdERRVUV4UWpzN1FVRkpRU3hUUVVGVExFOUJRVlFzUTBGQmFVSXNVVUZCYWtJc1JVRkJNa0lzU1VGQk0wSXNSVUZCYVVNc1NVRkJha01zUlVGQmMwTTdRVUZEY0VNc1YwRkJVeXhqUVVGVUxFTkJRWGRDTEVsQlFYaENMRVZCUVRoQ0xFbEJRVGxDTEVWQlJHOURPME5CUVhSRE96dEJRVWxCTEZOQlFWTXNaVUZCVkN4RFFVRjVRaXhIUVVGNlFpeEZRVUUyUWp0QlFVTjZRaXhUUVVGUExFOUJRVThzU1VGQlVDeERRVUZaTEVkQlFWb3NSVUZCYVVJc1RVRkJha0lzUTBGQmQwSXNUMEZCVHl4eFFrRkJVQ3hEUVVFMlFpeEhRVUUzUWl4RFFVRjRRaXhEUVVGUUxFTkJSSGxDTzBOQlFUZENPenRCUVVsQkxGTkJRVk1zYTBKQlFWUXNRMEZCTkVJc1UwRkJOVUlzUlVGQmMwTTdRVUZEY0VNc1RVRkJSenRCUVVORUxGZEJRVThzVDBGQlR5eGhRVUZRTEVOQlFYRkNMRk5CUVhKQ0xFdEJRVzFETEVsQlFXNURMRU5CUkU0N1IwRkJTQ3hEUVVWRExFOUJRVTBzUTBGQlRpeEZRVUZSTzBGQlExQXNWMEZCVHl4TFFVRlFMRU5CUkU4N1IwRkJVanREUVVoSU96czdRVUZUUVN4VFFVRlRMR2RDUVVGVUxFTkJRVEJDTEVkQlFURkNMRVZCUVN0Q08wRkJRek5DTEZOQlFVOHNTMEZCU3l4dFFrRkJiVUlzUjBGQmJrSXNSVUZCZDBJc1QwRkJlRUlzUTBGQlowTXNhVUpCUVdoRExFVkJRVzFFTEZWQlFWTXNTMEZCVkN4RlFVRm5RaXhGUVVGb1FpeEZRVUZ2UWp0QlFVTXZSU3hYUVVGUExFOUJRVThzV1VGQlVDeERRVUZ2UWl4UFFVRlBMRVZCUVZBc1EwRkJNMElzUTBGRUswVTdSMEZCY0VJc1EwRkJlRVFzUTBGQlVDeERRVVF5UWp0RFFVRXZRanM3UVVGTlFTeFRRVUZUTEhkQ1FVRlVMRU5CUVd0RExFZEJRV3hETEVWQlFYVkRMRkZCUVhaRExFVkJRV2RFTzBGQlF6VkRMRTFCUVVrc1ZVRkJWU3hQUVVGUExFMUJRVkFzUTBGQll5eFBRVUZQTEUxQlFWQXNRMEZCWXl4SlFVRkpMRmRCUVVvc1EwRkJaMElzVTBGQmFFSXNRMEZCTlVJc1JVRkJkMFFzUjBGQmVFUXNRMEZCVml4RFFVUjNRenRCUVVVMVF5eFRRVUZQTEZGQlFWRXNVVUZCVWl4RFFVRlFMRU5CUmpSRE96dEJRVWs1UXl4VFFVRlBMRTlCUVU4c1RVRkJVQ3hEUVVGakxFOUJRV1FzUTBGQlVDeERRVW80UXp0RFFVRm9SRHM3UVVGUFFTeFRRVUZUTEZsQlFWUXNRMEZCYzBJc1IwRkJkRUlzUlVGQk1FSTdRVUZEZEVJc1RVRkJTU3hWUVVGVkxFOUJRVThzVFVGQlVDeERRVUZqTEVWQlFXUXNSVUZCYTBJc1IwRkJiRUlzUTBGQlZpeERRVVJyUWp0QlFVVjRRaXhUUVVGUExFOUJRVThzVFVGQlVDeERRVUZqTEU5QlFXUXNRMEZCVUN4RFFVWjNRanREUVVFeFFqczdRVUZMUVN4VFFVRlRMRzFDUVVGVUxFTkJRVFpDTEVkQlFUZENMRVZCUVd0RExGRkJRV3hETEVWQlFUUkRMRXRCUVRWRExFVkJRV3RFTzBGQlEyaEVMRTFCUVVrc1ZVRkJWU3hQUVVGUExFMUJRVkFzUTBGQll5eEZRVUZrTEVWQlFXdENMRWRCUVd4Q0xFTkJRVllzUTBGRU5FTTdRVUZGYUVRc1ZVRkJVU3hSUVVGU0xFbEJRVzlDTEV0QlFYQkNMRU5CUm1kRU8wRkJSMmhFTEZOQlFVOHNUMEZCVHl4TlFVRlFMRU5CUVdNc1QwRkJaQ3hEUVVGUUxFTkJTR2RFTzBOQlFXeEVPenRCUVU5QkxGTkJRVk1zVlVGQlZDeERRVUZ2UWl4SFFVRndRaXhGUVVGNVFpeFJRVUY2UWl4RlFVRnRReXhMUVVGdVF5eEZRVUY1UXp0QlFVTnlReXhOUVVGSExGbEJRVmtzWjBKQlFXZENMRWRCUVdoQ0xFTkJRVm9zUlVGQmFVTTdRVUZEYUVNc1YwRkJUeXh2UWtGQmIwSXNSMEZCY0VJc1JVRkJlVUlzVVVGQmVrSXNSVUZCYlVNc1MwRkJia01zUTBGQlVDeERRVVJuUXp0SFFVRndRenM3UVVGSlFTeFJRVUZOTEhWQ1FVRk9MRU5CVEhGRE8wTkJRWHBET3p0QlFWRkJMRk5CUVZNc1NVRkJWQ3hEUVVGakxFbEJRV1FzUlVGQmJVSTdRVUZEYWtJc1UwRkJUeXhEUVVGRExFbEJRVVFzUTBGRVZUdERRVUZ1UWpzN1FVRkpRU3hUUVVGVExFbEJRVlFzUTBGQll5eEpRVUZrTEVWQlFXOUNMRXRCUVhCQ0xFVkJRVEJDTzBGQlEzaENMRk5CUVU4c1QwRkJUeXhMUVVGUUxFTkJSR2xDTzBOQlFURkNPenRCUVVsQkxGTkJRVk1zUjBGQlZDeERRVUZoTEVsQlFXSXNSVUZCYlVJc1MwRkJia0lzUlVGQmVVSTdRVUZEZGtJc1UwRkJUeXhQUVVGUExFdEJRVkFzUTBGRVowSTdRMEZCZWtJN08wRkJTVUVzVTBGQlV5eEhRVUZVTEVOQlFXRXNTVUZCWWl4RlFVRnRRaXhMUVVGdVFpeEZRVUY1UWp0QlFVTjJRaXhUUVVGUExGRkJRVkVzUzBGQlVpeERRVVJuUWp0RFFVRjZRanM3UVVGSlFTeFRRVUZUTEVkQlFWUXNRMEZCWVN4SlFVRmlMRVZCUVcxQ0xFdEJRVzVDTEVWQlFYbENPMEZCUTNaQ0xGTkJRVThzVVVGQlVTeExRVUZTTEVOQlJHZENPME5CUVhwQ096dEJRVWxCTEZOQlFWTXNTVUZCVkN4RFFVRmpMRWxCUVdRc1JVRkJiMElzUzBGQmNFSXNSVUZCTUVJN1FVRkRlRUlzVTBGQlR5eFBRVUZQTEV0QlFWQXNRMEZFYVVJN1EwRkJNVUk3TzBGQlNVRXNVMEZCVXl4SFFVRlVMRU5CUVdFc1lVRkJZaXhGUVVFeVFqdEJRVU42UWl4TlFVRkhMR05CUVdNc1RVRkJaQ3hMUVVGNVFpeERRVUY2UWl4RlFVRXlRanRCUVVNMVFpeFhRVUZQTEU5QlFVOHNUVUZCVUN4RFFVRmpMRVZCUVdRc1EwRkJVQ3hEUVVRMFFqdEhRVUU1UWpzN1FVRkpRU3hOUVVGSkxGbEJRVmtzUlVGQldpeERRVXh4UWp0QlFVMTZRaXhOUVVGSkxHdENRVUZyUWl4alFVRmpMRU5CUVdRc1EwRkJiRUlzUTBGT2NVSTdPMEZCVVhwQ0xFOUJRVWtzU1VGQlNTeERRVUZLTEVsQlFWTXNZVUZCWWl4RlFVRXlRanRCUVVONlFpeFJRVUZITEVWQlFVVXNUVUZCUml4SFFVRlhMR1ZCUVZnc1JVRkJNa0k3UVVGRE5VSXNkMEpCUVd0Q0xFVkJRVVVzVFVGQlJpeERRVVJWTzB0QlFUbENPMGRCUkVZN08wRkJUVUVzVDBGQlNTeEpRVUZKTEVsQlFVa3NRMEZCU2l4RlFVRlBMRWxCUVVrc1pVRkJTaXhGUVVGeFFpeEhRVUZ3UXl4RlFVRjNRenRCUVVOMFF5eFJRVUZKTEdkQ1FVRm5RaXhGUVVGb1FpeERRVVJyUXp0QlFVVjBReXhUUVVGSkxFbEJRVWtzU1VGQlNTeERRVUZLTEVWQlFVOHNTVUZCU1N4alFVRmpMRTFCUVdRc1JVRkJjMElzUjBGQmVrTXNSVUZCTmtNN1FVRkRNME1zYjBKQlFXTXNTVUZCWkN4RFFVRnRRaXhqUVVGakxFTkJRV1FzUlVGQmFVSXNRMEZCYWtJc1EwRkJia0lzUlVGRU1rTTdTMEZCTjBNN08wRkJTVUVzWTBGQlZTeEpRVUZXTEVOQlFXVXNTVUZCU1N4TFFVRktMRU5CUVZVc1IwRkJSeXhoUVVGSUxFTkJRWHBDTEVWQlRuTkRPMGRCUVhoRE96dEJRVk5CTEZOQlFVOHNUMEZCVHl4TlFVRlFMRU5CUVdNc1UwRkJaQ3hEUVVGUUxFTkJka0o1UWp0RFFVRXpRanM3UVVFd1FrRXNVMEZCVXl4WlFVRlVMRU5CUVhOQ0xFbEJRWFJDTEVWQlFUUkNPMEZCUXpGQ0xFMUJRVWM3UVVGRFJDeFRRVUZMTEVsQlFVd3NSVUZFUXp0QlFVVkVMRmRCUVU4c1NVRkJVQ3hEUVVaRE8wZEJRVWdzUTBGSFF5eFBRVUZOTEVOQlFVNHNSVUZCVVR0QlFVTlFMRmRCUVU4c1MwRkJVQ3hEUVVSUE8wZEJRVkk3UTBGS1NEczdRVUZUUVN4VFFVRlRMR2RDUVVGVUxFTkJRVEJDTEVsQlFURkNMRVZCUVdkRExFOUJRV2hETEVWQlFYZERPMEZCUTNCRExFMUJRVWtzVVVGQlVTeExRVUZTTEVOQlJHZERPenRCUVVkd1F5eFRRVUZQTEV0QlFVc3NUVUZCVEN4RFFVRlpMRkZCUVZVN1FVRkRla0lzVVVGQlJ5eERRVUZETEV0QlFVUXNTVUZCVlN4VFFVRlRMRTlCUVZRc1JVRkJhVUk3UVVGRE1VSXNZMEZCVVN4SlFVRlNMRU5CUkRCQ08wRkJSVEZDTEdGQlFVOHNTMEZCVUN4RFFVWXdRanRMUVVFNVFqczdRVUZMUVN4WFFVRlBMRWxCUVZBc1EwRk9lVUk3UjBGQlZpeERRVUZ1UWl4RFFVaHZRenREUVVGNFF6czdRVUZoUVN4VFFVRlRMRXRCUVZRc1EwRkJaU3hIUVVGbUxFVkJRVzlDTEVkQlFYQkNMRVZCUVhsQ0xFbEJRWHBDTEVWQlFUaENPMEZCUXpGQ0xFMUJRVWtzVDBGQlR5eEhRVUZRTEVOQlJITkNPenRCUVVjeFFpeFBRVUZKTEUxQlFVMHNSVUZCVGl4SlFVRlpMRWxCUVdoQ0xFVkJRWEZDTzBGQlEycENMRmRCUVU4c1NVRkJTU3hGUVVGS0xFVkJRVkVzU1VGQlVpeERRVUZRTEVOQlJHbENPMGRCUVhKQ096dEJRVWxCTEZOQlFVOHNTVUZCVUN4RFFWQXdRanREUVVFNVFqczdRVUZYUVN4VFFVRlRMRXRCUVZRc1EwRkJaU3hIUVVGbUxFVkJRVzlDTEVkQlFYQkNMRVZCUVhsQ0xFbEJRWHBDTEVWQlFUaENPMEZCUXpGQ0xFMUJRVWtzVDBGQlR5eEhRVUZRTEVOQlJITkNPenRCUVVjeFFpeFBRVUZKTEVsQlFVa3NTVUZCU1N4TFFVRkxMRTFCUVV3c1IwRkJZeXhEUVVGa0xFVkJRV2xDTEV0QlFVc3NRMEZCVEN4RlFVRlJMRWRCUVhKRExFVkJRWGxETzBGQlEzSkRMRmRCUVU4c1NVRkJTU3hMUVVGTExFTkJRVXdzUTBGQlNpeEZRVUZoTEVsQlFXSXNRMEZCVUN4RFFVUnhRenRIUVVGNlF6czdRVUZKUVN4VFFVRlBMRWxCUVZBc1EwRlFNRUk3UTBGQk9VSTdPMEZCVlVFc1UwRkJVeXhQUVVGVUxFTkJRV2xDTEVkQlFXcENMRVZCUVhOQ0xFTkJRWFJDTEVWQlFYbENMRk5CUVhwQ0xFVkJRVzFET3p0QlFVVnFReXhQUVVGSkxFbEJRVWtzU1VGQlNTeFZRVUZWTEUxQlFWWXNSMEZCYlVJc1EwRkJia0lzUlVGQmMwSXNTMEZCU3l4RFFVRk1MRVZCUVZFc1IwRkJNVU1zUlVGQk9FTTdRVUZETlVNc1VVRkJSeXhWUVVGVkxFTkJRVllzUlVGQllTeEhRVUZpTEVOQlFXbENMRU5CUVdwQ0xFMUJRWGRDTEVkQlFYaENMRVZCUVRSQ08wRkJRemRDTEdGQlFVOHNWVUZCVlN4RFFVRldMRU5CUVZBc1EwRkVOa0k3UzBGQkwwSTdSMEZFUmpzN1FVRk5RU3hUUVVGUExFdEJRVkFzUTBGU2FVTTdRMEZCYmtNN08wRkJWMEVzVTBGQlV5eFRRVUZVTEVOQlFXMUNMRWRCUVc1Q0xFVkJRWGRDTEVOQlFYaENMRVZCUVRKQ0xGTkJRVE5DTEVWQlFYRkRPenRCUVVWcVF5eFBRVUZKTEVsQlFVa3NTVUZCU1N4VlFVRlZMRTFCUVZZc1IwRkJiVUlzUTBGQmJrSXNSVUZCYzBJc1MwRkJTeXhEUVVGTUxFVkJRVkVzUjBGQk1VTXNSVUZCT0VNN1FVRkRNVU1zVVVGQlJ5eFZRVUZWTEVOQlFWWXNSVUZCWVN4SFFVRmlMRU5CUVdsQ0xFTkJRV3BDTEUxQlFYZENMRWRCUVhoQ0xFVkJRVFJDTzBGQlF6TkNMR0ZCUVU4c1ZVRkJWU3hOUVVGV0xFTkJRV2xDTEVWQlFXcENMRVZCUVhGQ0xFMUJRWEpDTEVOQlFUUkNMRU5CUVRWQ0xFVkJRU3RDTEVOQlFTOUNMRU5CUVZBc1EwRkVNa0k3UzBGQkwwSTdSMEZFU2pzN1FVRk5RU3hUUVVGUExGTkJRVkFzUTBGU2FVTTdRMEZCY2tNN08wRkJWMEVzVTBGQlV5eFJRVUZVTEVOQlFXdENMRWRCUVd4Q0xFVkJRWFZDTEVOQlFYWkNMRVZCUVRCQ0xFbEJRVEZDTEVWQlFXZERMRkZCUVdoRExFVkJRWGxETzBGQlEzSkRMRTlCUVVrc1NVRkJTU3hKUVVGSkxFdEJRVXNzVFVGQlRDeEhRVUZqTEVOQlFXUXNSVUZCYVVJc1MwRkJTeXhEUVVGTUxFVkJRVkVzUjBGQmNrTXNSVUZCZVVNN1FVRkRja01zVVVGQlJ5eExRVUZMTEVOQlFVd3NSVUZCVVN4SFFVRlNMRU5CUVZrc1EwRkJXaXhOUVVGdFFpeEhRVUZ1UWl4RlFVRjFRanRCUVVOMFFpeGhRVUZQTEV0QlFVc3NUVUZCVEN4RFFVRlpMRVZCUVZvc1JVRkJaMElzVFVGQmFFSXNRMEZCZFVJc1EwRkJka0lzUlVGQk1FSXNRMEZCTVVJc1JVRkJOa0lzVVVGQk4wSXNRMEZCVUN4RFFVUnpRanRMUVVFeFFqdEhRVVJLT3p0QlFVMUdMRk5CUVU4c1MwRkJTeXhOUVVGTUxFTkJRVmtzUlVGQldpeEZRVUZuUWl4SlFVRm9RaXhEUVVGeFFpeFJRVUZ5UWl4RFFVRlFMRU5CVUhWRE8wTkJRWHBET3p0QlFWVkJMRk5CUVZNc1UwRkJWQ3hEUVVGdFFpeEhRVUZ1UWl4RlFVRjNRaXhEUVVGNFFpeEZRVUV5UWl4SlFVRXpRaXhGUVVGblF6dEJRVU01UWl4UFFVRkpMRWxCUVVrc1NVRkJTU3hMUVVGTExFMUJRVXdzUjBGQll5eERRVUZrTEVWQlFXbENMRXRCUVVzc1EwRkJUQ3hGUVVGUkxFZEJRWEpETEVWQlFYbERPMEZCUTNaRExGRkJRVWNzUzBGQlN5eERRVUZNTEVWQlFWRXNSMEZCVWl4RFFVRlpMRU5CUVZvc1RVRkJiVUlzUjBGQmJrSXNSVUZCZFVJN1FVRkRlRUlzWVVGQlR5eEpRVUZRTEVOQlJIZENPMHRCUVRGQ08wZEJSRVk3TzBGQlRVRXNVMEZCVHl4TFFVRlFMRU5CVURoQ08wTkJRV2hET3p0QlFWVkJMRk5CUVZNc1QwRkJWQ3hEUVVGcFFpeEhRVUZxUWl4RlFVRnpRaXhEUVVGMFFpeEZRVUY1UWl4SlFVRjZRaXhGUVVFNFFqdEJRVU0xUWl4TlFVRkhMRU5CUVVNc1ZVRkJWU3hIUVVGV0xFVkJRV1VzUTBGQlppeEZRVUZyUWl4SlFVRnNRaXhEUVVGRUxFVkJRWGxDTzBGQlF6RkNMRmRCUVU4c1MwRkJVQ3hEUVVRd1FqdEhRVUUxUWpzN1FVRkpRU3hOUVVGSkxGRkJRVkVzVVVGQlVTeEhRVUZTTEVWQlFXRXNRMEZCWWl4RlFVRm5RaXhKUVVGb1FpeERRVUZTTEVOQlRIZENPenRCUVU4MVFpeFRRVUZQTEVsQlFVa3NTMEZCU2l4RFFVRlZMRTFCUVUwc1IwRkJUaXhEUVVGVkxFTkJRVllzUTBGQlZpeEZRVUYzUWl4TFFVRjRRaXhGUVVFclFpeFZRVUZWTEVkQlFWWXNSVUZCWlN4RFFVRm1MRVZCUVd0Q0xFbEJRV3hDTEVOQlFTOUNMRU5CUVZBc1EwRlFORUk3UTBGQk9VSTdPMEZCVlVFc1UwRkJVeXhWUVVGVUxFTkJRVzlDTEVkQlFYQkNMRVZCUVhsQ0xFTkJRWHBDTEVWQlFUUkNMRWxCUVRWQ0xFVkJRV3RETEZGQlFXeERMRVZCUVRKRE96dEJRVVY2UXl4UFFVRkpMRWxCUVVrc1NVRkJTU3hWUVVGVkxFMUJRVllzUjBGQmJVSXNRMEZCYmtJc1JVRkJjMElzUzBGQlN5eERRVUZNTEVWQlFWRXNSMEZCTVVNc1JVRkJPRU03UVVGRE5VTXNVVUZCUnl4VlFVRlZMRU5CUVZZc1JVRkJZU3hIUVVGaUxFTkJRV2xDTEVOQlFXcENMRTFCUVhkQ0xFZEJRWGhDTEVWQlFUUkNPMEZCUXpkQ0xHRkJRVThzVlVGQlZTeE5RVUZXTEVOQlFXbENMRVZCUVdwQ0xFVkJRWEZDTEUxQlFYSkNMRU5CUVRSQ0xFTkJRVFZDTEVWQlFTdENMRU5CUVM5Q0xFVkJRV3RETEZGQlFXeERMRU5CUVZBc1EwRkVOa0k3UzBGQkwwSTdSMEZFUmpzN1FVRk5RU3hUUVVGUExGTkJRVkFzUTBGU2VVTTdRMEZCTTBNN08wRkJXVUVzVTBGQlV5eFBRVUZVTEVOQlFXbENMRWxCUVdwQ0xFVkJRWE5DTzBGQlEyeENMRk5CUVU4c1MwRkJTeXhOUVVGTUxFTkJRVmtzUlVGQldpeEZRVUZuUWl4UFFVRm9RaXhGUVVGUUxFTkJSR3RDTzBOQlFYUkNPenRCUVVsQkxGTkJRVk1zVTBGQlZDeERRVUZ0UWl4SFFVRnVRaXhGUVVGM1FpeEhRVUY0UWl4RlFVRTBRanRCUVVONFFpeE5RVUZITEU5QlFVOHNaMEpCUVdkQ0xFZEJRV2hDTEVOQlFWQXNSVUZCTkVJN1FVRkRNMElzVjBGQlR5eEpRVUZKTEV0QlFVb3NRMEZCVlN4UFFVRlBMRWRCUVZBc1EwRkJWeXhKUVVGWUxFTkJRVllzUlVGQk5FSXNTVUZCU1N4SFFVRktMRU5CUVRWQ0xFTkJRVkFzUTBGRU1rSTdSMEZCTDBJc1RVRkZTenRCUVVORUxGZEJRVThzVDBGQlR5eEhRVUZRTEVOQlFWY3NUMEZCV0N4RFFVRlFMRU5CUkVNN1IwRkdURHREUVVSS096dEJRVkZCTEZOQlFWTXNUMEZCVkN4RFFVRnBRaXhKUVVGcVFpeEZRVUYxUWl4UFFVRlBMRVZCUVZBc1JVRkJWenRCUVVOb1F5eE5RVUZKTEZkQlFWY3NSVUZCV0N4RFFVUTBRanM3UVVGSGFFTXNUMEZCU1N4SlFVRkpMRU5CUVVvc1NVRkJVeXhKUVVGaUxFVkJRV3RDTzBGQlEyaENMRkZCUVVjc1VVRkJVU3hEUVVGU0xFTkJRVWdzUlVGQll6dEJRVU5hTEdsQ1FVRlhMRk5CUVZNc1RVRkJWQ3hEUVVGblFpeFJRVUZSTEVOQlFWSXNRMEZCYUVJc1EwRkJXQ3hEUVVSWk8wdEJRV1FzVFVGRlN6dEJRVU5JTEdWQlFWTXNTVUZCVkN4RFFVRmpMRU5CUVdRc1JVRkVSenRMUVVaTU8wZEJSRVk3TzBGQlVVRXNVMEZCVHl4UFFVRlBMRTFCUVZBc1EwRkJZeXhUUVVGVExFMUJRVlFzUTBGQlowSXNTVUZCYUVJc1EwRkJaQ3hEUVVGUUxFTkJXR2RETzBOQlFXeERPenRCUVdOQkxGTkJRVk1zVTBGQlZDeERRVUZ0UWl4RFFVRnVRaXhGUVVGelFpeEpRVUYwUWl4RlFVRXlRanRCUVVONlFpeE5RVUZKTEU5QlFVOHNSVUZCVUN4RFFVUnhRanM3UVVGSGVrSXNUMEZCU1N4SlFVRkpMRWxCUVVrc1EwRkJTaXhGUVVGUExFbEJRVWtzUTBGQlNpeEZRVUZQTEVkQlFYUkNMRVZCUVRCQ08wRkJRM2hDTEZOQlFVc3NTVUZCVEN4RFFVRlZMRWxCUVZZc1JVRkVkMEk3UjBGQk1VSTdPMEZCU1VFc1UwRkJUeXhQUVVGUExFMUJRVkFzUTBGQll5eEpRVUZrTEVOQlFWQXNRMEZRZVVJN1EwRkJNMEk3TzBGQlZVRXNVMEZCVXl4UlFVRlVMRU5CUVd0Q0xFZEJRV3hDTEVWQlFYVkNMRWRCUVhaQ0xFVkJRVFJDTEVsQlFUVkNMRVZCUVdsRE8wRkJReTlDTEUxQlFVa3NWVUZCVlN4RlFVRldMRU5CUkRKQ096dEJRVWN2UWl4UFFVRkpMRWxCUVVrc1EwRkJTaXhKUVVGVExFbEJRV0lzUlVGQmEwSTdRVUZEYUVJc1VVRkJTU3hOUVVGTkxFbEJRVWtzUTBGQlNpeEZRVUZQTEVkQlFWQXNRMEZCVGl4RFFVUlpPMEZCUldoQ0xGbEJRVkVzU1VGQlVpeERRVUZoTEVsQlFVa3NSMEZCU2l4RFFVRlJMRU5CUVZJc1EwRkJZaXhGUVVablFqdEJRVWRvUWl4VlFVRk5MRWxCUVVrc1IwRkJTaXhEUVVGUkxFTkJRVklzUTBGQlRpeERRVWhuUWp0SFFVRnNRanM3UVVGUFFTeFRRVUZQTEVsQlFVa3NTMEZCU2l4RFFVRlZMRTlCUVU4c1RVRkJVQ3hEUVVGakxFOUJRV1FzUTBGQlZpeEZRVUZyUXl4SFFVRnNReXhEUVVGUUxFTkJWaXRDTzBOQlFXcERPenRCUVdGQkxGTkJRVk1zVTBGQlZDeERRVUZ0UWl4SFFVRnVRaXhGUVVGM1FpeEpRVUY0UWl4RlFVRTJRanRCUVVNelFpeE5RVUZKTEZWQlFWVXNSVUZCVml4RFFVUjFRanM3UVVGSE0wSXNUMEZCU1N4RFFVRktMRWxCUVZNc1NVRkJWQ3hGUVVGak8wRkJRMW9zVVVGQlNTeFRRVUZUTEVsQlFVa3NRMEZCU2l4RFFVRlVMRU5CUkZFN08wRkJSMW9zVVVGQlJ5eFhRVUZYTEVsQlFWZ3NSVUZCWjBJN1FVRkRha0lzWTBGQlVTeEpRVUZTTEVOQlFXRXNRMEZCWWl4RlFVUnBRanRMUVVGdVFpeE5RVVZOTEVsQlFVY3NhMEpCUVd0Q0xFdEJRV3hDTEVWQlFYZENPMEZCUXk5Q0xHTkJRVkVzU1VGQlVpeERRVUZoTEU5QlFVOHNSMEZCVUN4RFFVRlhMRU5CUVZnc1EwRkJZaXhGUVVRclFqdExRVUV6UWp0SFFVeFNPenRCUVZWQkxGTkJRVThzVDBGQlR5eE5RVUZRTEVOQlFXTXNUMEZCWkN4RFFVRlFMRU5CWWpKQ08wTkJRVGRDT3p0QlFXZENRU3hUUVVGVExGTkJRVlFzUTBGQmJVSXNSMEZCYmtJc1JVRkJkMElzUjBGQmVFSXNSVUZCTmtJc1IwRkJOMElzUlVGQmFVTTdRVUZETDBJc1RVRkJTU3hQUVVGUExFZEJRVkFzUTBGRU1rSTdPMEZCUnk5Q0xFOUJRVWtzU1VGQlNTeERRVUZLTEVsQlFWTXNaMEpCUVdkQ0xFZEJRV2hDTEVOQlFXSXNSVUZCYTBNN1FVRkRhRU1zVjBGQlR5eEpRVUZKTEVOQlFVb3NSVUZCVHl4SlFVRkpMRU5CUVVvc1EwRkJVQ3hGUVVGbExFbEJRV1lzUTBGQlVDeERRVVJuUXp0SFFVRnNRenM3UVVGSlFTeFRRVUZQTEVsQlFWQXNRMEZRSzBJN1EwRkJha003TzBGQlZVRXNVMEZCVXl4alFVRlVMRU5CUVhkQ0xFbEJRWGhDTEVWQlFUWkNPMEZCUXpOQ0xFMUJRVWtzU1VGQlNTeEZRVUZLTEVOQlJIVkNPenRCUVVjelFpeFBRVUZKTEVOQlFVb3NTVUZCVXl4SlFVRlVMRVZCUVdNN1FVRkRXaXhOUVVGRkxFVkJRVVVzUjBGQlJpeERRVUZOTEVOQlFVNHNRMEZCUml4SlFVRmpMRVZCUVVVc1IwRkJSaXhEUVVGTkxFTkJRVTRzUTBGQlpDeERRVVJaTzBkQlFXUTdPMEZCU1VFc1UwRkJUeXhQUVVGUExFMUJRVkFzUTBGQll5eERRVUZrTEVOQlFWQXNRMEZRTWtJN1EwRkJOMEk3TzBGQlZVRXNaVUZCWlR0QlFVTmlMR1ZCUkdFN1FVRkZZaXhQUVVaaE8wRkJSMklzVlVGSVlUdEJRVWxpTEZsQlNtRTdRVUZMWWl4WFFVeGhPMEZCVFdJc1kwRk9ZVHRCUVU5aUxHRkJVR0U3UVVGUllpeFRRVkpoTzBGQlUySXNhVUpCVkdFN1FVRlZZaXh2UWtGV1lUdEJRVmRpTEd0Q1FWaGhPMEZCV1dJc01FSkJXbUU3UVVGaFlpeHhRa0ZpWVR0QlFXTmlMR05CWkdFN1FVRmxZaXhqUVdaaE8wRkJaMEppTEUxQmFFSmhPMEZCYVVKaUxFMUJha0poTzBGQmEwSmlMRXRCYkVKaE8wRkJiVUppTEV0QmJrSmhPMEZCYjBKaUxFdEJjRUpoTzBGQmNVSmlMRTFCY2tKaE8wRkJjMEppTEV0QmRFSmhPMEZCZFVKaUxFOUJka0poTzBGQmQwSmlMRTlCZUVKaE8wRkJlVUppTEd0Q1FYcENZVHRCUVRCQ1lpeFhRVEZDWVR0QlFUSkNZaXhWUVROQ1lUdEJRVFJDWWl4VFFUVkNZVHRCUVRaQ1lpeFRRVGRDWVR0QlFUaENZaXhaUVRsQ1lUdEJRU3RDWWl4VFFTOUNZVHRCUVdkRFlpeFpRV2hEWVR0QlFXbERZaXhYUVdwRFlUdEJRV3REWWl4VFFXeERZVHRCUVcxRFlpeFhRVzVEWVR0QlFXOURZaXhWUVhCRFlUdEJRWEZEWWl4WFFYSkRZVHRCUVhORFlpeFhRWFJEWVR0RFFVRm1JaXdpWm1sc1pTSTZJbXhwWWk5amIzSmxMMloxYm1OMGFXOXVjeTVxY3lJc0luTnZkWEpqWlhORGIyNTBaVzUwSWpwYkltbHRjRzl5ZENCN0lGUjFjR3hsSUgwZ1puSnZiU0FuTGk5d2NtbHRhWFJwZG1Wekp6dGNibWx0Y0c5eWRDQkNhWFJUZEhKcGJtY2dabkp2YlNBbkxpOWlhWFJmYzNSeWFXNW5KenRjYm1sdGNHOXlkQ0JRWVhSMFpYSnVjeUJtY205dElDY3VMM0JoZEhSbGNtNXpKenRjYm1sdGNHOXlkQ0JRY205MGIyTnZiQ0JtY205dElDY3VMM0J5YjNSdlkyOXNKenRjYmx4dVpuVnVZM1JwYjI0Z1kyRnNiRjl3Y205d1pYSjBlU2hwZEdWdExDQndjbTl3WlhKMGVTbDdYRzRnSUd4bGRDQndjbTl3SUQwZ2JuVnNiRHRjYmx4dUlDQnBaaWgwZVhCbGIyWWdhWFJsYlNBOVBUMGdYQ0p1ZFcxaVpYSmNJaUI4ZkNCMGVYQmxiMllnYVhSbGJTQTlQVDBnWENKemVXMWliMnhjSWlCOGZDQjBlWEJsYjJZZ2FYUmxiU0E5UFQwZ1hDSmliMjlzWldGdVhDSWdmSHdnZEhsd1pXOW1JR2wwWlcwZ1BUMDlJRndpYzNSeWFXNW5YQ0lwZTF4dUlDQWdJR2xtS0dsMFpXMWJjSEp2Y0dWeWRIbGRJQ0U5UFNCMWJtUmxabWx1WldRcGUxeHVJQ0FnSUNBZ2NISnZjQ0E5SUhCeWIzQmxjblI1TzF4dUlDQWdJSDFsYkhObElHbG1LR2wwWlcxYlUzbHRZbTlzTG1admNpaHdjbTl3WlhKMGVTbGRJQ0U5UFNCMWJtUmxabWx1WldRcGUxeHVJQ0FnSUNBZ2NISnZjQ0E5SUZONWJXSnZiQzVtYjNJb2NISnZjR1Z5ZEhrcE8xeHVJQ0FnSUgxY2JpQWdmU0JsYkhObElIdGNiaUFnSUNCcFppaHdjbTl3WlhKMGVTQnBiaUJwZEdWdEtYdGNiaUFnSUNBZ0lIQnliM0FnUFNCd2NtOXdaWEowZVR0Y2JpQWdJQ0I5Wld4elpTQnBaaWhUZVcxaWIyd3VabTl5S0hCeWIzQmxjblI1S1NCcGJpQnBkR1Z0S1h0Y2JpQWdJQ0FnSUhCeWIzQWdQU0JUZVcxaWIyd3VabTl5S0hCeWIzQmxjblI1S1R0Y2JpQWdJQ0I5WEc0Z0lIMWNibHh1SUNCcFppaHdjbTl3SUQwOVBTQnVkV3hzS1h0Y2JpQWdJQ0IwYUhKdmR5QnVaWGNnUlhKeWIzSW9ZRkJ5YjNCbGNuUjVJQ1I3SUhCeWIzQmxjblI1SUgwZ2JtOTBJR1p2ZFc1a0lHbHVJQ1I3SUdsMFpXMGdmV0FwT3lCY2JpQWdmVnh1WEc0Z0lHbG1LR2wwWlcxYmNISnZjRjBnYVc1emRHRnVZMlZ2WmlCR2RXNWpkR2x2YmlsN1hHNGdJQ0FnY21WMGRYSnVJR2wwWlcxYmNISnZjRjBvS1R0Y2JpQWdmV1ZzYzJWN1hHNGdJQ0FnY21WMGRYSnVJR2wwWlcxYmNISnZjRjA3WEc0Z0lIMWNibjFjYmx4dVpuVnVZM1JwYjI0Z1lYQndiSGtvTGk0dVlYSm5jeWw3WEc0Z0lHbG1LR0Z5WjNNdWJHVnVaM1JvSUQwOVBTQXlLWHRjYmlBZ0lDQmhjbWR6V3pCZExtRndjR3g1S0c1MWJHd3NJR0Z5WjNNdWMyeHBZMlVvTVNrcE8xeHVJQ0I5Wld4elpYdGNiaUFnSUNCaGNtZHpXekJkVzJGeVozTmJNVjFkTG1Gd2NHeDVLRzUxYkd3c0lHRnlaM011YzJ4cFkyVW9NaWtwTzF4dUlDQjlYRzU5WEc1Y2JtWjFibU4wYVc5dUlHTnZiblJoYVc1ektHeGxablFzSUhKcFoyaDBLWHRjYmlBZ1ptOXlLR3hsZENCNElHOW1JSEpwWjJoMEtYdGNiaUFnSUNCcFppaFFZWFIwWlhKdWN5NXRZWFJqYUY5dWIxOTBhSEp2ZHloc1pXWjBMQ0I0S1NBaFBTQnVkV3hzS1h0Y2JpQWdJQ0FnSUhKbGRIVnliaUIwY25WbE8xeHVJQ0FnSUgxY2JpQWdmVnh1WEc0Z0lISmxkSFZ5YmlCbVlXeHpaVHRjYm4xY2JseHVablZ1WTNScGIyNGdaMlYwWDJkc2IySmhiQ2dwZTF4dUlDQnBaaWgwZVhCbGIyWW9jMlZzWmlrZ0lUMDlJRndpZFc1a1pXWnBibVZrWENJcGUxeHVJQ0FnSUhKbGRIVnliaUJ6Wld4bU8xeHVJQ0I5Wld4elpTQnBaaWgwZVhCbGIyWW9kMmx1Wkc5M0tTQWhQVDBnWENKMWJtUmxabWx1WldSY0lpbDdYRzRnSUNBZ2NtVjBkWEp1SUhkcGJtUnZkenRjYmlBZ2ZXVnNjMlVnYVdZb2RIbHdaVzltS0dkc2IySmhiQ2tnSVQwOUlGd2lkVzVrWldacGJtVmtYQ0lwZTF4dUlDQWdJSEpsZEhWeWJpQm5iRzlpWVd3N1hHNGdJSDFjYmx4dUlDQjBhSEp2ZHlCdVpYY2dSWEp5YjNJb1hDSk9ieUJuYkc5aVlXd2djM1JoZEdVZ1ptOTFibVJjSWlrN1hHNTlYRzVjYm1aMWJtTjBhVzl1SUdSbFpuTjBjblZqZENoa1pXWmhkV3gwY3lsN1hHNGdJSEpsZEhWeWJpQmpiR0Z6Y3lCN1hHNGdJQ0FnWTI5dWMzUnlkV04wYjNJb2RYQmtZWFJsSUQwZ2UzMHBlMXh1SUNBZ0lDQWdiR1YwSUhSb1pWOTJZV3gxWlhNZ1BTQlBZbXBsWTNRdVlYTnphV2R1S0dSbFptRjFiSFJ6TENCMWNHUmhkR1VwTzF4dUlDQWdJQ0FnVDJKcVpXTjBMbUZ6YzJsbmJpaDBhR2x6TENCMGFHVmZkbUZzZFdWektUdGNiaUFnSUNCOVhHNWNiaUFnSUNCemRHRjBhV01nWTNKbFlYUmxLSFZ3WkdGMFpYTWdQU0I3ZlNsN1hHNGdJQ0FnSUNCc1pYUWdlQ0E5SUc1bGR5QjBhR2x6S0hWd1pHRjBaWE1wTzF4dUlDQWdJQ0FnY21WMGRYSnVJRTlpYW1WamRDNW1jbVZsZW1Vb2VDazdYRzRnSUNBZ2ZWeHVJQ0I5TzF4dWZWeHVYRzVjYm1aMWJtTjBhVzl1SUdSbFptVjRZMlZ3ZEdsdmJpaGtaV1poZFd4MGN5bDdYRzRnSUhKbGRIVnliaUJqYkdGemN5QmxlSFJsYm1SeklFVnljbTl5SUh0Y2JpQWdJQ0JqYjI1emRISjFZM1J2Y2loMWNHUmhkR1VnUFNCN2ZTbDdYRzRnSUNBZ0lDQnNaWFFnYldWemMyRm5aU0E5SUhWd1pHRjBaUzV0WlhOellXZGxJSHg4SUZ3aVhDSTdYRzRnSUNBZ0lDQnpkWEJsY2lodFpYTnpZV2RsS1R0Y2JseHVJQ0FnSUNBZ2JHVjBJSFJvWlY5MllXeDFaWE1nUFNCUFltcGxZM1F1WVhOemFXZHVLR1JsWm1GMWJIUnpMQ0IxY0dSaGRHVXBPMXh1SUNBZ0lDQWdUMkpxWldOMExtRnpjMmxuYmloMGFHbHpMQ0IwYUdWZmRtRnNkV1Z6S1R0Y2JseHVJQ0FnSUNBZ2RHaHBjeTV1WVcxbElEMGdkR2hwY3k1amIyNXpkSEoxWTNSdmNpNXVZVzFsTzF4dUlDQWdJQ0FnZEdocGN5NXRaWE56WVdkbElEMGdiV1Z6YzJGblpUdGNiaUFnSUNBZ0lIUm9hWE5iVTNCbFkybGhiRVp2Y20xekxtRjBiMjBvWENKZlgyVjRZMlZ3ZEdsdmJsOWZYQ0lwWFNBOUlIUnlkV1U3WEc0Z0lDQWdJQ0JGY25KdmNpNWpZWEIwZFhKbFUzUmhZMnRVY21GalpTaDBhR2x6TENCMGFHbHpMbU52Ym5OMGNuVmpkRzl5TG01aGJXVXBPMXh1SUNBZ0lIMWNibHh1SUNBZ0lITjBZWFJwWXlCamNtVmhkR1VvZFhCa1lYUmxjeUE5SUh0OUtYdGNiaUFnSUNBZ0lHeGxkQ0I0SUQwZ2JtVjNJSFJvYVhNb2RYQmtZWFJsY3lrN1hHNGdJQ0FnSUNCeVpYUjFjbTRnVDJKcVpXTjBMbVp5WldWNlpTaDRLVHRjYmlBZ0lDQjlYRzRnSUgwN1hHNTlYRzVjYm1aMWJtTjBhVzl1SUdSbFpuQnliM1J2WTI5c0tITndaV01wZTF4dUlDQnlaWFIxY200Z2JtVjNJRkJ5YjNSdlkyOXNLSE53WldNcE8xeHVmVnh1WEc1bWRXNWpkR2x2YmlCa1pXWnBiWEJzS0hCeWIzUnZZMjlzTENCMGVYQmxMQ0JwYlhCc0tYdGNiaUFnY0hKdmRHOWpiMnd1YVcxd2JHVnRaVzUwWVhScGIyNG9kSGx3WlN3Z2FXMXdiQ2s3WEc1OVhHNWNibVoxYm1OMGFXOXVJR2RsZEY5dlltcGxZM1JmYTJWNWN5aHZZbW9wZTF4dUlDQWdJSEpsZEhWeWJpQlBZbXBsWTNRdWEyVjVjeWh2WW1vcExtTnZibU5oZENoUFltcGxZM1F1WjJWMFQzZHVVSEp2Y0dWeWRIbFRlVzFpYjJ4ektHOWlhaWtwTzF4dWZWeHVYRzVtZFc1amRHbHZiaUJwYzE5MllXeHBaRjlqYUdGeVlXTjBaWElvWTI5a1pYQnZhVzUwS1h0Y2JpQWdkSEo1ZTF4dUlDQWdJSEpsZEhWeWJpQlRkSEpwYm1jdVpuSnZiVU52WkdWUWIybHVkQ2hqYjJSbGNHOXBiblFwSUNFOUlHNTFiR3c3WEc0Z0lIMWpZWFJqYUNobEtYdGNiaUFnSUNCeVpYUjFjbTRnWm1Gc2MyVTdYRzRnSUgxY2JuMWNibHh1THk5b2RIUndjem92TDJSbGRtVnNiM0JsY2k1dGIzcHBiR3hoTG05eVp5OWxiaTFWVXk5a2IyTnpMMWRsWWk5QlVFa3ZWMmx1Wkc5M1FtRnpaVFkwTDBKaGMyVTJORjlsYm1OdlpHbHVaMTloYm1SZlpHVmpiMlJwYm1jalUyOXNkWFJwYjI1Zk1sOGxSVElsT0RBbE9UTmZjbVYzY21sMFpWOTBhR1ZmUkU5TmMxOWhkRzlpS0NsZllXNWtYMkowYjJFb0tWOTFjMmx1WjE5S1lYWmhVMk55YVhCMEozTmZWSGx3WldSQmNuSmhlWE5mWVc1a1gxVlVSaTA0WEc1bWRXNWpkR2x2YmlCaU5qUkZibU52WkdWVmJtbGpiMlJsS0hOMGNpa2dlMXh1SUNBZ0lISmxkSFZ5YmlCaWRHOWhLR1Z1WTI5a1pWVlNTVU52YlhCdmJtVnVkQ2h6ZEhJcExuSmxjR3hoWTJVb0x5VW9XekF0T1VFdFJsMTdNbjBwTDJjc0lHWjFibU4wYVc5dUtHMWhkR05vTENCd01Ta2dlMXh1SUNBZ0lDQWdJQ0J5WlhSMWNtNGdVM1J5YVc1bkxtWnliMjFEYUdGeVEyOWtaU2duTUhnbklDc2djREVwTzF4dUlDQWdJSDBwS1R0Y2JuMWNibHh1Wm5WdVkzUnBiMjRnWkdWc1pYUmxYM0J5YjNCbGNuUjVYMlp5YjIxZmJXRndLRzFoY0N3Z2NISnZjR1Z5ZEhrcGUxeHVJQ0FnSUd4bGRDQnVaWGRmYldGd0lEMGdUMkpxWldOMExtRnpjMmxuYmloUFltcGxZM1F1WTNKbFlYUmxLRzFoY0M1amIyNXpkSEoxWTNSdmNpNXdjbTkwYjNSNWNHVXBMQ0J0WVhBcE8xeHVJQ0FnSUdSbGJHVjBaU0J1WlhkZmJXRndXM0J5YjNCbGNuUjVYVHRjYmx4dUlDQnlaWFIxY200Z1QySnFaV04wTG1aeVpXVjZaU2h1WlhkZmJXRndLVHRjYm4xY2JseHVablZ1WTNScGIyNGdZMnhoYzNOZmRHOWZiMkpxS0cxaGNDbDdYRzRnSUNBZ2JHVjBJRzVsZDE5dFlYQWdQU0JQWW1wbFkzUXVZWE56YVdkdUtIdDlMQ0J0WVhBcE8xeHVJQ0J5WlhSMWNtNGdUMkpxWldOMExtWnlaV1Y2WlNodVpYZGZiV0Z3S1R0Y2JuMWNibHh1Wm5WdVkzUnBiMjRnWVdSa1gzQnliM0JsY25SNVgzUnZYMjFoY0NodFlYQXNJSEJ5YjNCbGNuUjVMQ0IyWVd4MVpTbDdYRzRnSUd4bGRDQnVaWGRmYldGd0lEMGdUMkpxWldOMExtRnpjMmxuYmloN2ZTd2diV0Z3S1R0Y2JpQWdibVYzWDIxaGNGdHdjbTl3WlhKMGVWMGdQU0IyWVd4MVpUdGNiaUFnY21WMGRYSnVJRTlpYW1WamRDNW1jbVZsZW1Vb2JtVjNYMjFoY0NrN1hHNTlYRzVjYmx4dVpuVnVZM1JwYjI0Z2RYQmtZWFJsWDIxaGNDaHRZWEFzSUhCeWIzQmxjblI1TENCMllXeDFaU2w3WEc0Z0lDQWdhV1lvY0hKdmNHVnlkSGtnYVc0Z1oyVjBYMjlpYW1WamRGOXJaWGx6S0cxaGNDa3BlMXh1SUNBZ0lDQWdJQ0J5WlhSMWNtNGdZV1JrWDNCeWIzQmxjblI1WDNSdlgyMWhjQ2h0WVhBc0lIQnliM0JsY25SNUxDQjJZV3gxWlNrN1hHNGdJQ0FnZlZ4dVhHNGdJQ0FnZEdoeWIzY2dYQ0p0WVhBZ1pHOWxjeUJ1YjNRZ2FHRjJaU0JyWlhsY0lqdGNibjFjYmx4dVpuVnVZM1JwYjI0Z1ltNXZkQ2hsZUhCeUtYdGNiaUFnY21WMGRYSnVJSDVsZUhCeU8xeHVmVnh1WEc1bWRXNWpkR2x2YmlCaVlXNWtLR3hsWm5Rc0lISnBaMmgwS1h0Y2JpQWdjbVYwZFhKdUlHeGxablFnSmlCeWFXZG9kRHRjYm4xY2JseHVablZ1WTNScGIyNGdZbTl5S0d4bFpuUXNJSEpwWjJoMEtYdGNiaUFnY21WMGRYSnVJR3hsWm5RZ2ZDQnlhV2RvZER0Y2JuMWNibHh1Wm5WdVkzUnBiMjRnWW5Oc0tHeGxablFzSUhKcFoyaDBLWHRjYmlBZ2NtVjBkWEp1SUd4bFpuUWdQRHdnY21sbmFIUTdYRzU5WEc1Y2JtWjFibU4wYVc5dUlHSnpjaWhzWldaMExDQnlhV2RvZENsN1hHNGdJSEpsZEhWeWJpQnNaV1owSUQ0K0lISnBaMmgwTzF4dWZWeHVYRzVtZFc1amRHbHZiaUJpZUc5eUtHeGxablFzSUhKcFoyaDBLWHRjYmlBZ2NtVjBkWEp1SUd4bFpuUWdYaUJ5YVdkb2REdGNibjFjYmx4dVpuVnVZM1JwYjI0Z2VtbHdLR3hwYzNSZmIyWmZiR2x6ZEhNcGUxeHVJQ0JwWmloc2FYTjBYMjltWDJ4cGMzUnpMbXhsYm1kMGFDQTlQVDBnTUNsN1hHNGdJQ0FnY21WMGRYSnVJRTlpYW1WamRDNW1jbVZsZW1Vb1cxMHBPMXh1SUNCOVhHNWNiaUFnYkdWMElHNWxkMTkyWVd4MVpTQTlJRnRkTzF4dUlDQnNaWFFnYzIxaGJHeGxjM1JmYkdWdVozUm9JRDBnYkdsemRGOXZabDlzYVhOMGMxc3dYVHRjYmx4dUlDQm1iM0lvYkdWMElIZ2diMllnYkdsemRGOXZabDlzYVhOMGN5bDdYRzRnSUNBZ2FXWW9lQzVzWlc1bmRHZ2dQQ0J6YldGc2JHVnpkRjlzWlc1bmRHZ3BlMXh1SUNBZ0lDQWdjMjFoYkd4bGMzUmZiR1Z1WjNSb0lEMGdlQzVzWlc1bmRHZzdYRzRnSUNBZ2ZWeHVJQ0I5WEc1Y2JpQWdabTl5S0d4bGRDQnBJRDBnTURzZ2FTQThJSE50WVd4c1pYTjBYMnhsYm1kMGFEc2dhU3NyS1h0Y2JpQWdJQ0JzWlhRZ1kzVnljbVZ1ZEY5MllXeDFaU0E5SUZ0ZE8xeHVJQ0FnSUdadmNpaHNaWFFnYWlBOUlEQTdJR29nUENCc2FYTjBYMjltWDJ4cGMzUnpMbXhsYm1kMGFEc2dhaXNyS1h0Y2JpQWdJQ0FnSUdOMWNuSmxiblJmZG1Gc2RXVXVjSFZ6YUNoc2FYTjBYMjltWDJ4cGMzUnpXMnBkVzJsZEtUdGNiaUFnSUNCOVhHNWNiaUFnSUNCdVpYZGZkbUZzZFdVdWNIVnphQ2h1WlhjZ1ZIVndiR1VvTGk0dVkzVnljbVZ1ZEY5MllXeDFaU2twTzF4dUlDQjlYRzVjYmlBZ2NtVjBkWEp1SUU5aWFtVmpkQzVtY21WbGVtVW9ibVYzWDNaaGJIVmxLVHRjYm4xY2JseHVablZ1WTNScGIyNGdZMkZ1WDJSbFkyOWtaVFkwS0dSaGRHRXBJSHRjYmlBZ2RISjVlMXh1SUNBZ0lHRjBiMklvWkdGMFlTazdYRzRnSUNBZ2NtVjBkWEp1SUhSeWRXVTdYRzRnSUgxallYUmphQ2hsS1h0Y2JpQWdJQ0J5WlhSMWNtNGdabUZzYzJVN1hHNGdJSDFjYm4xY2JseHVablZ1WTNScGIyNGdjbVZ0YjNabFgyWnliMjFmYkdsemRDaHNhWE4wTENCbGJHVnRaVzUwS1h0Y2JpQWdJQ0JzWlhRZ1ptOTFibVFnUFNCbVlXeHpaVHRjYmx4dUlDQWdJSEpsZEhWeWJpQnNhWE4wTG1acGJIUmxjaWdvWld4bGJTa2dQVDRnZTF4dUlDQWdJQ0FnSUNCcFppZ2habTkxYm1RZ0ppWWdaV3hsYlNBOVBUMGdaV3hsYldWdWRDbDdYRzRnSUNBZ0lDQWdJQ0FnSUNCbWIzVnVaQ0E5SUhSeWRXVTdYRzRnSUNBZ0lDQWdJQ0FnSUNCeVpYUjFjbTRnWm1Gc2MyVTdYRzRnSUNBZ0lDQWdJSDFjYmx4dUlDQWdJQ0FnSUNCeVpYUjFjbTRnZEhKMVpUdGNiaUFnSUNCOUtUdGNibjFjYmx4dVpuVnVZM1JwYjI0Z1ptOXNaR3dvWm5WdUxDQmhZMk1zSUd4cGMzUXBlMXh1SUNBZ0lHeGxkQ0JoWTJNeElEMGdZV05qTzF4dVhHNGdJQ0FnWm05eUtHTnZibk4wSUdWc0lHOW1JR3hwYzNRcGUxeHVJQ0FnSUNBZ0lDQmhZMk14SUQwZ1puVnVLR1ZzTENCaFkyTXhLVHRjYmlBZ0lDQjlYRzVjYmlBZ0lDQnlaWFIxY200Z1lXTmpNVHRjYm4xY2JseHVYRzVtZFc1amRHbHZiaUJtYjJ4a2NpaG1kVzRzSUdGall5d2diR2x6ZENsN1hHNGdJQ0FnYkdWMElHRmpZekVnUFNCaFkyTTdYRzVjYmlBZ0lDQm1iM0lvYkdWMElHa2dQU0JzYVhOMExteGxibWQwYUNBdElERTdJR2tnUGowZ01Ec2dhUzB0S1h0Y2JpQWdJQ0FnSUNBZ1lXTmpNU0E5SUdaMWJpaHNhWE4wVzJsZExDQmhZMk14S1R0Y2JpQWdJQ0I5WEc1Y2JpQWdJQ0J5WlhSMWNtNGdZV05qTVR0Y2JuMWNibHh1Wm5WdVkzUnBiMjRnYTJWNVptbHVaQ2hyWlhrc0lHNHNJSFIxY0d4bGJHbHpkQ2w3WEc1Y2JpQWdabTl5S0d4bGRDQnBJRDBnZEhWd2JHVnNhWE4wTG14bGJtZDBhQ0F0SURFN0lHa2dQajBnTURzZ2FTMHRLWHRjYmlBZ0lDQnBaaWgwZFhCc1pXeHBjM1JiYVYwdVoyVjBLRzRwSUQwOVBTQnJaWGtwZTF4dUlDQWdJQ0FnY21WMGRYSnVJSFIxY0d4bGJHbHpkRnRwWFR0Y2JpQWdJQ0I5WEc0Z0lIMWNibHh1SUNCeVpYUjFjbTRnWm1Gc2MyVTdYRzU5WEc1Y2JtWjFibU4wYVc5dUlHdGxlV1JsYkdWMFpTaHJaWGtzSUc0c0lIUjFjR3hsYkdsemRDbDdYRzVjYmlBZ0lDQm1iM0lvYkdWMElHa2dQU0IwZFhCc1pXeHBjM1F1YkdWdVozUm9JQzBnTVRzZ2FTQStQU0F3T3lCcExTMHBlMXh1SUNBZ0lDQWdJQ0JwWmloMGRYQnNaV3hwYzNSYmFWMHVaMlYwS0c0cElEMDlQU0JyWlhrcGUxeHVJQ0FnSUNBZ0lDQWdJQ0FnY21WMGRYSnVJSFIxY0d4bGJHbHpkQzVqYjI1allYUW9XMTBwTG5Od2JHbGpaU2hwTENBeEtUdGNiaUFnSUNBZ0lDQWdmVnh1SUNBZ0lIMWNibHh1SUNBZ0lISmxkSFZ5YmlCMGRYQnNaV3hwYzNRN1hHNTlYRzVjYm1aMWJtTjBhVzl1SUd0bGVYTjBiM0psS0d0bGVTd2diaXdnYkdsemRDd2dibVYzZEhWd2JHVXBlMXh1SUNBZ0lHWnZjaWhzWlhRZ2FTQTlJR3hwYzNRdWJHVnVaM1JvSUMwZ01Uc2dhU0ErUFNBd095QnBMUzBwZTF4dUlDQWdJQ0FnSUNCcFppaHNhWE4wVzJsZExtZGxkQ2h1S1NBOVBUMGdhMlY1S1h0Y2JpQWdJQ0FnSUNBZ0lDQWdJSEpsZEhWeWJpQnNhWE4wTG1OdmJtTmhkQ2hiWFNrdWMzQnNhV05sS0drc0lERXNJRzVsZDNSMWNHeGxLVHRjYmlBZ0lDQWdJQ0FnZlZ4dUlDQWdJSDFjYmx4dUlDQnlaWFIxY200Z2JHbHpkQzVqYjI1allYUW9XMTBwTG5CMWMyZ29ibVYzZEhWd2JHVXBPMXh1ZlZ4dVhHNW1kVzVqZEdsdmJpQnJaWGx0WlcxaVpYSW9hMlY1TENCdUxDQnNhWE4wS1h0Y2JpQWdabTl5S0d4bGRDQnBJRDBnYkdsemRDNXNaVzVuZEdnZ0xTQXhPeUJwSUQ0OUlEQTdJR2t0TFNsN1hHNGdJQ0FnYVdZb2JHbHpkRnRwWFM1blpYUW9iaWtnUFQwOUlHdGxlU2w3WEc0Z0lDQWdJQ0J5WlhSMWNtNGdkSEoxWlR0Y2JpQWdJQ0I5WEc0Z0lIMWNibHh1SUNCeVpYUjFjbTRnWm1Gc2MyVTdYRzU5WEc1Y2JtWjFibU4wYVc5dUlHdGxlWFJoYTJVb2EyVjVMQ0J1TENCc2FYTjBLWHRjYmlBZ2FXWW9JV3RsZVcxbGJXSmxjaWhyWlhrc0lHNHNJR3hwYzNRcEtYdGNiaUFnSUNCeVpYUjFjbTRnWm1Gc2MyVTdYRzRnSUgxY2JseHVJQ0JzWlhRZ2RIVndiR1VnUFNCclpYbG1hVzVrS0d0bGVTd2diaXdnYkdsemRDazdYRzVjYmlBZ2NtVjBkWEp1SUc1bGR5QlVkWEJzWlNoMGRYQnNaUzVuWlhRb2Jpa3NJSFIxY0d4bExDQnJaWGxrWld4bGRHVW9hMlY1TENCdUxDQnNhWE4wS1NrN1hHNTlYRzVjYm1aMWJtTjBhVzl1SUd0bGVYSmxjR3hoWTJVb2EyVjVMQ0J1TENCc2FYTjBMQ0J1WlhkMGRYQnNaU2w3WEc0Z0lGeHVJQ0JtYjNJb2JHVjBJR2tnUFNCMGRYQnNaV3hwYzNRdWJHVnVaM1JvSUMwZ01Uc2dhU0ErUFNBd095QnBMUzBwZTF4dUlDQWdJR2xtS0hSMWNHeGxiR2x6ZEZ0cFhTNW5aWFFvYmlrZ1BUMDlJR3RsZVNsN1hHNGdJQ0FnSUNCeVpYUjFjbTRnZEhWd2JHVnNhWE4wTG1OdmJtTmhkQ2hiWFNrdWMzQnNhV05sS0drc0lERXNJRzVsZDNSMWNHeGxLVHRjYmlBZ0lDQjlYRzRnSUgxY2JseHVJQ0J5WlhSMWNtNGdkSFZ3YkdWc2FYTjBPMXh1ZlZ4dVhHNWNibVoxYm1OMGFXOXVJSEpsZG1WeWMyVW9iR2x6ZENsN1hHNGdJQ0FnY21WMGRYSnVJR3hwYzNRdVkyOXVZMkYwS0Z0ZEtTNXlaWFpsY25ObEtDazdYRzU5WEc1Y2JtWjFibU4wYVc5dUlHMWhjSE5mWm1sdVpDaHJaWGtzSUcxaGNDbDdYRzRnSUNBZ2FXWW9hMlY1SUdsdUlHZGxkRjl2WW1wbFkzUmZhMlY1Y3lodFlYQXBLWHRjYmlBZ0lDQWdJQ0FnY21WMGRYSnVJRzVsZHlCVWRYQnNaU2hUZVcxaWIyd3VabTl5S0Z3aWIydGNJaWtzSUcxaGNGdHJaWGxkS1R0Y2JpQWdJQ0I5Wld4elpYdGNiaUFnSUNBZ0lDQWdjbVYwZFhKdUlGTjViV0p2YkM1bWIzSW9YQ0psY25KdmNsd2lLVHRjYmlBZ0lDQjlYRzU5WEc1Y2JtWjFibU4wYVc5dUlHWnNZWFIwWlc0b2JHbHpkQ3dnZEdGcGJDQTlJRnRkS1NCN1hHNGdJR3hsZENCdVpYZGZiR2x6ZENBOUlGdGRPMXh1WEc0Z0lHWnZjaWhzWlhRZ1pTQnZaaUJzYVhOMEtYdGNiaUFnSUNCcFppaHBjMEZ5Y21GNUtHVXBLWHRjYmlBZ0lDQWdJRzVsZDE5c2FYTjBJRDBnYm1WM1gyeHBjM1F1WTI5dVkyRjBLR1pzWVhSMFpXNG9aU2twTzF4dUlDQWdJSDFsYkhObGUxeHVJQ0FnSUNBZ2JtVjNYMnhwYzNRdWNIVnphQ2hsS1R0Y2JpQWdJQ0I5WEc0Z0lIMWNibHh1SUNCeVpYUjFjbTRnVDJKcVpXTjBMbVp5WldWNlpTaHVaWGRmYkdsemRDNWpiMjVqWVhRb2RHRnBiQ2twTzF4dWZWeHVYRzVtZFc1amRHbHZiaUJrZFhCc2FXTmhkR1VvYml3Z1pXeGxiU2w3WEc0Z0lHeGxkQ0JzYVhOMElEMGdXMTA3WEc1Y2JpQWdabTl5S0d4bGRDQnBJRDBnTURzZ2FTQThJRzQ3SUdrckt5bDdYRzRnSUNBZ2JHbHpkQzV3ZFhOb0tHVnNaVzBwTzF4dUlDQjlYRzVjYmlBZ2NtVjBkWEp1SUU5aWFtVmpkQzVtY21WbGVtVW9iR2x6ZENrN1hHNTlYRzVjYm1aMWJtTjBhVzl1SUcxaGNHWnZiR1JzS0daMWJpd2dZV05qTENCc2FYTjBLWHRjYmlBZ2JHVjBJRzVsZDJ4cGMzUWdQU0JiWFR0Y2JseHVJQ0JtYjNJb2JHVjBJSGdnYjJZZ2JHbHpkQ2w3WEc0Z0lDQWdiR1YwSUhSMWNDQTlJR1oxYmloNExDQmhZMk1wTzF4dUlDQWdJRzVsZDJ4cGMzUXVjSFZ6YUNoMGRYQXVaMlYwS0RBcEtUdGNiaUFnSUNCaFkyTWdQU0IwZFhBdVoyVjBLREVwTzF4dUlDQjlYRzVjYmx4dUlDQnlaWFIxY200Z2JtVjNJRlIxY0d4bEtFOWlhbVZqZEM1bWNtVmxlbVVvYm1WM2JHbHpkQ2tzSUdGall5azdYRzU5WEc1Y2JtWjFibU4wYVc5dUlHWnBiSFJsY20xaGNDaG1kVzRzSUd4cGMzUXBlMXh1SUNCc1pYUWdibVYzYkdsemRDQTlJRnRkTzF4dVhHNGdJR1p2Y2loNElHOW1JR3hwYzNRcGUxeHVJQ0FnSUd4bGRDQnlaWE4xYkhRZ1BTQm1kVzRvZUNrN1hHNWNiaUFnSUNCcFppaHlaWE4xYkhRZ1BUMDlJSFJ5ZFdVcGUxeHVJQ0FnSUNBZ2JtVjNiR2x6ZEM1d2RYTm9LSGdwTzF4dUlDQWdJSDFsYkhObElHbG1LSEpsYzNWc2RDQnBibk4wWVc1alpXOW1JRlIxY0d4bEtYdGNiaUFnSUNBZ0lHNWxkMnhwYzNRdWNIVnphQ2h5WlhOMWJIUXVaMlYwS0RFcEtUdGNiaUFnSUNCOVhHNGdJSDFjYmx4dUlDQnlaWFIxY200Z1QySnFaV04wTG1aeVpXVjZaU2h1Wlhkc2FYTjBLVHRjYm4xY2JseHVablZ1WTNScGIyNGdiV0Z3YzE5bWIyeGtLR1oxYml3Z1lXTmpMQ0J0WVhBcGUxeHVJQ0JzWlhRZ1lXTmpNU0E5SUdGall6dGNibHh1SUNCbWIzSW9iR1YwSUdzZ2IyWWdaMlYwWDI5aWFtVmpkRjlyWlhsektHMWhjQ2twZTF4dUlDQWdJR0ZqWXpFZ1BTQm1kVzRvYXl3Z2JXRndXMnRkTENCaFkyTXhLVHRjYmlBZ2ZWeHVYRzRnSUhKbGRIVnliaUJoWTJNeE8xeHVmVnh1WEc1bWRXNWpkR2x2YmlCdFlYQnpYMlp5YjIxZmJHbHpkQ2hzYVhOMEtYdGNiaUFnYkdWMElHMGdQU0I3ZlR0Y2JseHVJQ0JtYjNJb2VDQnZaaUJzYVhOMEtYdGNiaUFnSUNCdFczZ3VaMlYwS0RBcFhTQTlJSGd1WjJWMEtERXBPMXh1SUNCOVhHNWNiaUFnY21WMGRYSnVJRTlpYW1WamRDNW1jbVZsZW1Vb2JTazdYRzU5WEc1Y2JtVjRjRzl5ZENCa1pXWmhkV3gwSUh0Y2JpQWdZMkZzYkY5d2NtOXdaWEowZVN4Y2JpQWdZWEJ3Ykhrc1hHNGdJR052Ym5SaGFXNXpMRnh1SUNCblpYUmZaMnh2WW1Gc0xGeHVJQ0JrWldaemRISjFZM1FzWEc0Z0lHUmxabVY0WTJWd2RHbHZiaXhjYmlBZ1pHVm1jSEp2ZEc5amIyd3NYRzRnSUdSbFptbHRjR3dzWEc0Z0lHZGxkRjl2WW1wbFkzUmZhMlY1Y3l4Y2JpQWdhWE5mZG1Gc2FXUmZZMmhoY21GamRHVnlMRnh1SUNCaU5qUkZibU52WkdWVmJtbGpiMlJsTEZ4dUlDQmtaV3hsZEdWZmNISnZjR1Z5ZEhsZlpuSnZiVjl0WVhBc1hHNGdJR0ZrWkY5d2NtOXdaWEowZVY5MGIxOXRZWEFzWEc0Z0lHTnNZWE56WDNSdlgyOWlhaXhjYmlBZ1kyRnVYMlJsWTI5a1pUWTBMRnh1SUNCaWJtOTBMRnh1SUNCaVlXNWtMRnh1SUNCaWIzSXNYRzRnSUdKemJDeGNiaUFnWW5OeUxGeHVJQ0JpZUc5eUxGeHVJQ0I2YVhBc1hHNGdJR1p2YkdSc0xGeHVJQ0JtYjJ4a2NpeGNiaUFnY21WdGIzWmxYMlp5YjIxZmJHbHpkQ3hjYmlBZ2EyVjVaR1ZzWlhSbExGeHVJQ0JyWlhsemRHOXlaU3hjYmlBZ2EyVjVabWx1WkN4Y2JpQWdhMlY1ZEdGclpTeGNiaUFnYTJWNWNtVndiR0ZqWlN4Y2JpQWdjbVYyWlhKelpTeGNiaUFnZFhCa1lYUmxYMjFoY0N4Y2JpQWdiV0Z3YzE5bWFXNWtMRnh1SUNCbWJHRjBkR1Z1TEZ4dUlDQmtkWEJzYVdOaGRHVXNYRzRnSUcxaGNHWnZiR1JzTEZ4dUlDQm1hV3gwWlhKdFlYQXNYRzRnSUcxaGNITmZabTlzWkZ4dWZUdGNiaUpkTENKemIzVnlZMlZTYjI5MElqb2lMM052ZFhKalpTOGlmUT09XG4iLCJpbXBvcnQgQml0U3RyaW5nIGZyb20gJy4vYml0X3N0cmluZyc7XG5pbXBvcnQgUGF0dGVybnMgZnJvbSAnLi9wYXR0ZXJucyc7XG5pbXBvcnQgeyBUdXBsZSB9IGZyb20gJy4vcHJpbWl0aXZlcyc7XG5cbmZ1bmN0aW9uIF9jYXNlKGNvbmRpdGlvbiwgY2xhdXNlcykge1xuICByZXR1cm4gUGF0dGVybnMuZGVmbWF0Y2goLi4uY2xhdXNlcykoY29uZGl0aW9uKTtcbn1cblxuZnVuY3Rpb24gY29uZChjbGF1c2VzKSB7XG4gIGZvciAobGV0IGNsYXVzZSBvZiBjbGF1c2VzKSB7XG4gICAgaWYgKGNsYXVzZVswXSkge1xuICAgICAgcmV0dXJuIGNsYXVzZVsxXSgpO1xuICAgIH1cbiAgfVxuXG4gIHRocm93IG5ldyBFcnJvcigpO1xufVxuXG5mdW5jdGlvbiBtYXBfdXBkYXRlKG1hcCwgdmFsdWVzKSB7XG4gIHJldHVybiBPYmplY3QuZnJlZXplKE9iamVjdC5hc3NpZ24oT2JqZWN0LmNyZWF0ZShtYXAuY29uc3RydWN0b3IucHJvdG90eXBlKSwgbWFwLCB2YWx1ZXMpKTtcbn1cblxuZnVuY3Rpb24gX2Zvcihjb2xsZWN0aW9ucywgZnVuLCBmaWx0ZXIgPSAoKSA9PiB0cnVlLCBpbnRvID0gW10sIHByZXZpb3VzVmFsdWVzID0gW10pIHtcbiAgbGV0IHBhdHRlcm4gPSBjb2xsZWN0aW9uc1swXVswXTtcbiAgbGV0IGNvbGxlY3Rpb24gPSBjb2xsZWN0aW9uc1swXVsxXTtcblxuICBpZiAoY29sbGVjdGlvbnMubGVuZ3RoID09PSAxKSB7XG5cbiAgICBmb3IgKGxldCBlbGVtIG9mIGNvbGxlY3Rpb24pIHtcbiAgICAgIGxldCByID0gUGF0dGVybnMubWF0Y2hfbm9fdGhyb3cocGF0dGVybiwgZWxlbSk7XG4gICAgICBsZXQgYXJncyA9IHByZXZpb3VzVmFsdWVzLmNvbmNhdChyKTtcblxuICAgICAgaWYgKHIgJiYgZmlsdGVyLmFwcGx5KHRoaXMsIGFyZ3MpKSB7XG4gICAgICAgIGludG8gPSBpbnRvLmNvbmNhdChbZnVuLmFwcGx5KHRoaXMsIGFyZ3MpXSk7XG4gICAgICB9XG4gICAgfVxuXG4gICAgcmV0dXJuIGludG87XG4gIH0gZWxzZSB7XG4gICAgbGV0IF9pbnRvID0gW107XG5cbiAgICBmb3IgKGxldCBlbGVtIG9mIGNvbGxlY3Rpb24pIHtcbiAgICAgIGxldCByID0gUGF0dGVybnMubWF0Y2hfbm9fdGhyb3cocGF0dGVybiwgZWxlbSk7XG4gICAgICBpZiAocikge1xuICAgICAgICBfaW50byA9IGludG8uY29uY2F0KHRoaXMuX2Zvcihjb2xsZWN0aW9ucy5zbGljZSgxKSwgZnVuLCBmaWx0ZXIsIF9pbnRvLCBwcmV2aW91c1ZhbHVlcy5jb25jYXQocikpKTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICByZXR1cm4gX2ludG87XG4gIH1cbn1cblxuZnVuY3Rpb24gX3RyeShkb19mdW4sIHJlc2N1ZV9mdW5jdGlvbiwgY2F0Y2hfZnVuLCBlbHNlX2Z1bmN0aW9uLCBhZnRlcl9mdW5jdGlvbikge1xuICBsZXQgcmVzdWx0ID0gbnVsbDtcblxuICB0cnkge1xuICAgIHJlc3VsdCA9IGRvX2Z1bigpO1xuICB9IGNhdGNoIChlKSB7XG4gICAgbGV0IGV4X3Jlc3VsdCA9IG51bGw7XG5cbiAgICBpZiAocmVzY3VlX2Z1bmN0aW9uKSB7XG4gICAgICB0cnkge1xuICAgICAgICBleF9yZXN1bHQgPSByZXNjdWVfZnVuY3Rpb24oZSk7XG4gICAgICAgIHJldHVybiBleF9yZXN1bHQ7XG4gICAgICB9IGNhdGNoIChleCkge1xuICAgICAgICBpZiAoZXggaW5zdGFuY2VvZiBQYXR0ZXJucy5NYXRjaEVycm9yKSB7XG4gICAgICAgICAgdGhyb3cgZXg7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9XG5cbiAgICBpZiAoY2F0Y2hfZnVuKSB7XG4gICAgICB0cnkge1xuICAgICAgICBleF9yZXN1bHQgPSBjYXRjaF9mdW4oZSk7XG4gICAgICAgIHJldHVybiBleF9yZXN1bHQ7XG4gICAgICB9IGNhdGNoIChleCkge1xuICAgICAgICBpZiAoZXggaW5zdGFuY2VvZiBQYXR0ZXJucy5NYXRjaEVycm9yKSB7XG4gICAgICAgICAgdGhyb3cgZXg7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9XG5cbiAgICB0aHJvdyBlO1xuICB9IGZpbmFsbHkge1xuICAgIGlmIChhZnRlcl9mdW5jdGlvbikge1xuICAgICAgYWZ0ZXJfZnVuY3Rpb24oKTtcbiAgICB9XG4gIH1cblxuICBpZiAoZWxzZV9mdW5jdGlvbikge1xuICAgIHRyeSB7XG4gICAgICByZXR1cm4gZWxzZV9mdW5jdGlvbihyZXN1bHQpO1xuICAgIH0gY2F0Y2ggKGV4KSB7XG4gICAgICBpZiAoZXggaW5zdGFuY2VvZiBQYXR0ZXJucy5NYXRjaEVycm9yKSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcihcIk5vIE1hdGNoIEZvdW5kIGluIEVsc2VcIik7XG4gICAgICB9XG5cbiAgICAgIHRocm93IGV4O1xuICAgIH1cbiAgfSBlbHNlIHtcbiAgICByZXR1cm4gcmVzdWx0O1xuICB9XG59XG5cbmV4cG9ydCBkZWZhdWx0IHtcbiAgX2Nhc2UsXG4gIGNvbmQsXG4gIG1hcF91cGRhdGUsXG4gIF9mb3IsXG4gIF90cnlcbn07XG4vLyMgc291cmNlTWFwcGluZ1VSTD1kYXRhOmFwcGxpY2F0aW9uL2pzb247YmFzZTY0LGV5SjJaWEp6YVc5dUlqb3pMQ0p6YjNWeVkyVnpJanBiSW14cFlpOWpiM0psTDNOd1pXTnBZV3hmWm05eWJYTXVhbk1pWFN3aWJtRnRaWE1pT2x0ZExDSnRZWEJ3YVc1bmN5STZJa0ZCUVVFc1QwRkJUeXhUUVVGUUxFMUJRWE5DTEdOQlFYUkNPMEZCUTBFc1QwRkJUeXhSUVVGUUxFMUJRWEZDTEZsQlFYSkNPMEZCUTBFc1UwRkJVeXhMUVVGVUxGRkJRWE5DTEdOQlFYUkNPenRCUVVWQkxGTkJRVk1zUzBGQlZDeERRVUZsTEZOQlFXWXNSVUZCTUVJc1QwRkJNVUlzUlVGQmEwTTdRVUZEYUVNc1UwRkJUeXhUUVVGVExGRkJRVlFzUTBGQmEwSXNSMEZCUnl4UFFVRklMRU5CUVd4Q0xFTkJRVGhDTEZOQlFUbENMRU5CUVZBc1EwRkVaME03UTBGQmJFTTdPMEZCU1VFc1UwRkJVeXhKUVVGVUxFTkJRV01zVDBGQlpDeEZRVUZ6UWp0QlFVTndRaXhQUVVGSkxFbEJRVWtzVFVGQlNpeEpRVUZqTEU5QlFXeENMRVZCUVRCQ08wRkJRM2hDTEZGQlFVY3NUMEZCVHl4RFFVRlFMRU5CUVVnc1JVRkJZVHRCUVVOWUxHRkJRVThzVDBGQlR5eERRVUZRTEVkQlFWQXNRMEZFVnp0TFFVRmlPMGRCUkVZN08wRkJUVUVzVVVGQlRTeEpRVUZKTEV0QlFVb3NSVUZCVGl4RFFWQnZRanREUVVGMFFqczdRVUZWUVN4VFFVRlRMRlZCUVZRc1EwRkJiMElzUjBGQmNFSXNSVUZCZVVJc1RVRkJla0lzUlVGQlowTTdRVUZET1VJc1UwRkJUeXhQUVVGUExFMUJRVkFzUTBGRFRDeFBRVUZQTEUxQlFWQXNRMEZEUlN4UFFVRlBMRTFCUVZBc1EwRkJZeXhKUVVGSkxGZEJRVW9zUTBGQlowSXNVMEZCYUVJc1EwRkVhRUlzUlVGRE5FTXNSMEZFTlVNc1JVRkRhVVFzVFVGRWFrUXNRMEZFU3l4RFFVRlFMRU5CUkRoQ08wTkJRV2hET3p0QlFWRkJMRk5CUVZNc1NVRkJWQ3hEUVVGakxGZEJRV1FzUlVGQk1rSXNSMEZCTTBJc1JVRkJaME1zVTBGQlV5eE5RVUZOTEVsQlFVNHNSVUZCV1N4UFFVRlBMRVZCUVZBc1JVRkJWeXhwUWtGQmFVSXNSVUZCYWtJc1JVRkJiMEk3UVVGRGJFWXNUVUZCU1N4VlFVRlZMRmxCUVZrc1EwRkJXaXhGUVVGbExFTkJRV1lzUTBGQlZpeERRVVE0UlR0QlFVVnNSaXhOUVVGSkxHRkJRV0VzV1VGQldTeERRVUZhTEVWQlFXVXNRMEZCWml4RFFVRmlMRU5CUmpoRk96dEJRVWxzUml4TlFVRkhMRmxCUVZrc1RVRkJXaXhMUVVGMVFpeERRVUYyUWl4RlFVRjVRanM3UVVGRk1VSXNVMEZCU1N4SlFVRkpMRWxCUVVvc1NVRkJXU3hWUVVGb1FpeEZRVUV5UWp0QlFVTjZRaXhWUVVGSkxFbEJRVWtzVTBGQlV5eGpRVUZVTEVOQlFYZENMRTlCUVhoQ0xFVkJRV2xETEVsQlFXcERMRU5CUVVvc1EwRkVjVUk3UVVGRmVrSXNWVUZCU1N4UFFVRlBMR1ZCUVdVc1RVRkJaaXhEUVVGelFpeERRVUYwUWl4RFFVRlFMRU5CUm5GQ096dEJRVWw2UWl4VlFVRkhMRXRCUVVzc1QwRkJUeXhMUVVGUUxFTkJRV0VzU1VGQllpeEZRVUZ0UWl4SlFVRnVRaXhEUVVGTUxFVkJRVGhDTzBGQlF5OUNMR1ZCUVU4c1MwRkJTeXhOUVVGTUxFTkJRVmtzUTBGQlF5eEpRVUZKTEV0QlFVb3NRMEZCVlN4SlFVRldMRVZCUVdkQ0xFbEJRV2hDTEVOQlFVUXNRMEZCV2l4RFFVRlFMRU5CUkN0Q08wOUJRV3BETzB0QlNrWTdPMEZCVTBFc1YwRkJUeXhKUVVGUUxFTkJXREJDTzBkQlFUVkNMRTFCV1VzN1FVRkRTQ3hSUVVGSkxGRkJRVkVzUlVGQlVpeERRVVJFT3p0QlFVZElMRk5CUVVrc1NVRkJTU3hKUVVGS0xFbEJRVmtzVlVGQmFFSXNSVUZCTWtJN1FVRkRla0lzVlVGQlNTeEpRVUZKTEZOQlFWTXNZMEZCVkN4RFFVRjNRaXhQUVVGNFFpeEZRVUZwUXl4SlFVRnFReXhEUVVGS0xFTkJSSEZDTzBGQlJYcENMRlZCUVVjc1EwRkJTQ3hGUVVGTE8wRkJRMGdzWjBKQlFWRXNTMEZCU3l4TlFVRk1MRU5CUVZrc1MwRkJTeXhKUVVGTUxFTkJRVlVzV1VGQldTeExRVUZhTEVOQlFXdENMRU5CUVd4Q0xFTkJRVllzUlVGQlowTXNSMEZCYUVNc1JVRkJjVU1zVFVGQmNrTXNSVUZCTmtNc1MwRkJOME1zUlVGQmIwUXNaVUZCWlN4TlFVRm1MRU5CUVhOQ0xFTkJRWFJDTEVOQlFYQkVMRU5CUVZvc1EwRkJVaXhEUVVSSE8wOUJRVXc3UzBGR1JqczdRVUZQUVN4WFFVRlBMRXRCUVZBc1EwRldSenRIUVZwTU8wTkJTa1k3TzBGQk9FSkJMRk5CUVZNc1NVRkJWQ3hEUVVGakxFMUJRV1FzUlVGQmMwSXNaVUZCZEVJc1JVRkJkVU1zVTBGQmRrTXNSVUZCYTBRc1lVRkJiRVFzUlVGQmFVVXNZMEZCYWtVc1JVRkJaMFk3UVVGRE9VVXNUVUZCU1N4VFFVRlRMRWxCUVZRc1EwRkVNRVU3TzBGQlJ6bEZMRTFCUVVjN1FVRkRSQ3hoUVVGVExGRkJRVlFzUTBGRVF6dEhRVUZJTEVOQlJVTXNUMEZCVFN4RFFVRk9MRVZCUVZFN1FVRkRVQ3hSUVVGSkxGbEJRVmtzU1VGQldpeERRVVJIT3p0QlFVZFFMRkZCUVVjc1pVRkJTQ3hGUVVGdFFqdEJRVU5xUWl4VlFVRkhPMEZCUTBRc2IwSkJRVmtzWjBKQlFXZENMRU5CUVdoQ0xFTkJRVm9zUTBGRVF6dEJRVVZFTEdWQlFVOHNVMEZCVUN4RFFVWkRPMDlCUVVnc1EwRkhReXhQUVVGTkxFVkJRVTRzUlVGQlV6dEJRVU5TTEZsQlFVY3NZMEZCWXl4VFFVRlRMRlZCUVZRc1JVRkJiMEk3UVVGRGJrTXNaMEpCUVUwc1JVRkJUaXhEUVVSdFF6dFRRVUZ5UXp0UFFVUkVPMHRCU2tnN08wRkJWMEVzVVVGQlJ5eFRRVUZJTEVWQlFXRTdRVUZEV0N4VlFVRkhPMEZCUTBRc2IwSkJRVmtzVlVGQlZTeERRVUZXTEVOQlFWb3NRMEZFUXp0QlFVVkVMR1ZCUVU4c1UwRkJVQ3hEUVVaRE8wOUJRVWdzUTBGSFF5eFBRVUZOTEVWQlFVNHNSVUZCVXp0QlFVTlNMRmxCUVVjc1kwRkJZeXhUUVVGVExGVkJRVlFzUlVGQmIwSTdRVUZEYmtNc1owSkJRVTBzUlVGQlRpeERRVVJ0UXp0VFFVRnlRenRQUVVSRU8wdEJTa2c3TzBGQlYwRXNWVUZCVFN4RFFVRk9MRU5CZWtKUE8wZEJRVklzVTBFeVFrODdRVUZEVGl4UlFVRkhMR05CUVVnc1JVRkJhMEk3UVVGRGFFSXNkVUpCUkdkQ08wdEJRV3hDTzBkQk9VSkdPenRCUVcxRFFTeE5RVUZITEdGQlFVZ3NSVUZCYVVJN1FVRkRaaXhSUVVGSE8wRkJRMFFzWVVGQlR5eGpRVUZqTEUxQlFXUXNRMEZCVUN4RFFVUkRPMHRCUVVnc1EwRkZReXhQUVVGTkxFVkJRVTRzUlVGQlV6dEJRVU5PTEZWQlFVY3NZMEZCWXl4VFFVRlRMRlZCUVZRc1JVRkJiMEk3UVVGRGJrTXNZMEZCVFN4SlFVRkpMRXRCUVVvc1EwRkJWU3gzUWtGQlZpeERRVUZPTEVOQlJHMURPMDlCUVhKRE96dEJRVWxHTEZsQlFVMHNSVUZCVGl4RFFVeFJPMHRCUVZRN1IwRklTQ3hOUVZWTE8wRkJRMGdzVjBGQlR5eE5RVUZRTEVOQlJFYzdSMEZXVER0RFFYUkRSanM3UVVGeFJFRXNaVUZCWlR0QlFVTmlMRTlCUkdFN1FVRkZZaXhOUVVaaE8wRkJSMklzV1VGSVlUdEJRVWxpTEUxQlNtRTdRVUZMWWl4TlFVeGhPME5CUVdZaUxDSm1hV3hsSWpvaWJHbGlMMk52Y21VdmMzQmxZMmxoYkY5bWIzSnRjeTVxY3lJc0luTnZkWEpqWlhORGIyNTBaVzUwSWpwYkltbHRjRzl5ZENCQ2FYUlRkSEpwYm1jZ1puSnZiU0FuTGk5aWFYUmZjM1J5YVc1bkp6dGNibWx0Y0c5eWRDQlFZWFIwWlhKdWN5Qm1jbTl0SUNjdUwzQmhkSFJsY201ekp6dGNibWx0Y0c5eWRDQjdJRlIxY0d4bElIMGdabkp2YlNBbkxpOXdjbWx0YVhScGRtVnpKenRjYmx4dVpuVnVZM1JwYjI0Z1gyTmhjMlVvWTI5dVpHbDBhVzl1TENCamJHRjFjMlZ6S1h0Y2JpQWdjbVYwZFhKdUlGQmhkSFJsY201ekxtUmxabTFoZEdOb0tDNHVMbU5zWVhWelpYTXBLR052Ym1ScGRHbHZiaWs3WEc1OVhHNWNibVoxYm1OMGFXOXVJR052Ym1Rb1kyeGhkWE5sY3lsN1hHNGdJR1p2Y2loc1pYUWdZMnhoZFhObElHOW1JR05zWVhWelpYTXBlMXh1SUNBZ0lHbG1LR05zWVhWelpWc3dYU2w3WEc0Z0lDQWdJQ0J5WlhSMWNtNGdZMnhoZFhObFd6RmRLQ2s3WEc0Z0lDQWdmVnh1SUNCOVhHNWNiaUFnZEdoeWIzY2dibVYzSUVWeWNtOXlLQ2s3WEc1OVhHNWNibVoxYm1OMGFXOXVJRzFoY0Y5MWNHUmhkR1VvYldGd0xDQjJZV3gxWlhNcGUxeHVJQ0J5WlhSMWNtNGdUMkpxWldOMExtWnlaV1Y2WlNoY2JpQWdJQ0JQWW1wbFkzUXVZWE56YVdkdUtGeHVJQ0FnSUNBZ1QySnFaV04wTG1OeVpXRjBaU2h0WVhBdVkyOXVjM1J5ZFdOMGIzSXVjSEp2ZEc5MGVYQmxLU3dnYldGd0xDQjJZV3gxWlhOY2JpQWdJQ0FwWEc0Z0lDazdYRzU5WEc1Y2JtWjFibU4wYVc5dUlGOW1iM0lvWTI5c2JHVmpkR2x2Ym5Nc0lHWjFiaXdnWm1sc2RHVnlJRDBnS0NrZ1BUNGdkSEoxWlN3Z2FXNTBieUE5SUZ0ZExDQndjbVYyYVc5MWMxWmhiSFZsY3lBOUlGdGRLWHRjYmlBZ2JHVjBJSEJoZEhSbGNtNGdQU0JqYjJ4c1pXTjBhVzl1YzFzd1hWc3dYVHRjYmlBZ2JHVjBJR052Ykd4bFkzUnBiMjRnUFNCamIyeHNaV04wYVc5dWMxc3dYVnN4WFR0Y2JseHVJQ0JwWmloamIyeHNaV04wYVc5dWN5NXNaVzVuZEdnZ1BUMDlJREVwZTF4dVhHNGdJQ0FnWm05eUtHeGxkQ0JsYkdWdElHOW1JR052Ykd4bFkzUnBiMjRwZTF4dUlDQWdJQ0FnYkdWMElISWdQU0JRWVhSMFpYSnVjeTV0WVhSamFGOXViMTkwYUhKdmR5aHdZWFIwWlhKdUxDQmxiR1Z0S1R0Y2JpQWdJQ0FnSUd4bGRDQmhjbWR6SUQwZ2NISmxkbWx2ZFhOV1lXeDFaWE11WTI5dVkyRjBLSElwTzF4dVhHNGdJQ0FnSUNCcFppaHlJQ1ltSUdacGJIUmxjaTVoY0hCc2VTaDBhR2x6TENCaGNtZHpLU2w3WEc0Z0lDQWdJQ0FnSUdsdWRHOGdQU0JwYm5SdkxtTnZibU5oZENoYlpuVnVMbUZ3Y0d4NUtIUm9hWE1zSUdGeVozTXBYU2s3WEc0Z0lDQWdJQ0I5WEc0Z0lDQWdmVnh1WEc0Z0lDQWdjbVYwZFhKdUlHbHVkRzg3WEc0Z0lIMWxiSE5sZTF4dUlDQWdJR3hsZENCZmFXNTBieUE5SUZ0ZE8xeHVYRzRnSUNBZ1ptOXlLR3hsZENCbGJHVnRJRzltSUdOdmJHeGxZM1JwYjI0cGUxeHVJQ0FnSUNBZ2JHVjBJSElnUFNCUVlYUjBaWEp1Y3k1dFlYUmphRjl1YjE5MGFISnZkeWh3WVhSMFpYSnVMQ0JsYkdWdEtUdGNiaUFnSUNBZ0lHbG1LSElwZTF4dUlDQWdJQ0FnSUNCZmFXNTBieUE5SUdsdWRHOHVZMjl1WTJGMEtIUm9hWE11WDJadmNpaGpiMnhzWldOMGFXOXVjeTV6YkdsalpTZ3hLU3dnWm5WdUxDQm1hV3gwWlhJc0lGOXBiblJ2TENCd2NtVjJhVzkxYzFaaGJIVmxjeTVqYjI1allYUW9jaWtwS1R0Y2JpQWdJQ0FnSUgxY2JpQWdJQ0I5WEc1Y2JpQWdJQ0J5WlhSMWNtNGdYMmx1ZEc4N1hHNGdJSDFjYm4xY2JseHVablZ1WTNScGIyNGdYM1J5ZVNoa2IxOW1kVzRzSUhKbGMyTjFaVjltZFc1amRHbHZiaXdnWTJGMFkyaGZablZ1TENCbGJITmxYMloxYm1OMGFXOXVMQ0JoWm5SbGNsOW1kVzVqZEdsdmJpbDdYRzRnSUd4bGRDQnlaWE4xYkhRZ1BTQnVkV3hzTzF4dVhHNGdJSFJ5ZVh0Y2JpQWdJQ0J5WlhOMWJIUWdQU0JrYjE5bWRXNG9LVHRjYmlBZ2ZXTmhkR05vS0dVcGUxeHVJQ0FnSUd4bGRDQmxlRjl5WlhOMWJIUWdQU0J1ZFd4c08xeHVYRzRnSUNBZ2FXWW9jbVZ6WTNWbFgyWjFibU4wYVc5dUtYdGNiaUFnSUNBZ0lIUnllWHRjYmlBZ0lDQWdJQ0FnWlhoZmNtVnpkV3gwSUQwZ2NtVnpZM1ZsWDJaMWJtTjBhVzl1S0dVcE8xeHVJQ0FnSUNBZ0lDQnlaWFIxY200Z1pYaGZjbVZ6ZFd4ME8xeHVJQ0FnSUNBZ2ZXTmhkR05vS0dWNEtYdGNiaUFnSUNBZ0lDQWdhV1lvWlhnZ2FXNXpkR0Z1WTJWdlppQlFZWFIwWlhKdWN5NU5ZWFJqYUVWeWNtOXlLWHRjYmlBZ0lDQWdJQ0FnSUNCMGFISnZkeUJsZUR0Y2JpQWdJQ0FnSUNBZ2ZWeHVJQ0FnSUNBZ2ZWeHVJQ0FnSUgxY2JseHVJQ0FnSUdsbUtHTmhkR05vWDJaMWJpbDdYRzRnSUNBZ0lDQjBjbmw3WEc0Z0lDQWdJQ0FnSUdWNFgzSmxjM1ZzZENBOUlHTmhkR05vWDJaMWJpaGxLVHRjYmlBZ0lDQWdJQ0FnY21WMGRYSnVJR1Y0WDNKbGMzVnNkRHRjYmlBZ0lDQWdJSDFqWVhSamFDaGxlQ2w3WEc0Z0lDQWdJQ0FnSUdsbUtHVjRJR2x1YzNSaGJtTmxiMllnVUdGMGRHVnlibk11VFdGMFkyaEZjbkp2Y2lsN1hHNGdJQ0FnSUNBZ0lDQWdkR2h5YjNjZ1pYZzdYRzRnSUNBZ0lDQWdJSDFjYmlBZ0lDQWdJSDFjYmlBZ0lDQjlYRzVjYmlBZ0lDQjBhSEp2ZHlCbE8xeHVYRzRnSUgxbWFXNWhiR3g1ZTF4dUlDQWdJR2xtS0dGbWRHVnlYMloxYm1OMGFXOXVLWHRjYmlBZ0lDQWdJR0ZtZEdWeVgyWjFibU4wYVc5dUtDazdYRzRnSUNBZ2ZWeHVJQ0I5WEc1Y2JpQWdhV1lvWld4elpWOW1kVzVqZEdsdmJpbDdYRzRnSUNBZ2RISjVlMXh1SUNBZ0lDQWdjbVYwZFhKdUlHVnNjMlZmWm5WdVkzUnBiMjRvY21WemRXeDBLVHRjYmlBZ0lDQjlZMkYwWTJnb1pYZ3BlMXh1SUNBZ0lDQWdJQ0JwWmlobGVDQnBibk4wWVc1alpXOW1JRkJoZEhSbGNtNXpMazFoZEdOb1JYSnliM0lwZTF4dUlDQWdJQ0FnSUNBZ0lIUm9jbTkzSUc1bGR5QkZjbkp2Y2loY0lrNXZJRTFoZEdOb0lFWnZkVzVrSUdsdUlFVnNjMlZjSWlrN1hHNGdJQ0FnSUNBZ0lIMWNibHh1SUNBZ0lDQWdkR2h5YjNjZ1pYZzdYRzRnSUNBZ2ZWeHVJQ0I5Wld4elpYdGNiaUFnSUNCeVpYUjFjbTRnY21WemRXeDBPMXh1SUNCOVhHNTlYRzVjYm1WNGNHOXlkQ0JrWldaaGRXeDBJSHRjYmlBZ1gyTmhjMlVzWEc0Z0lHTnZibVFzWEc0Z0lHMWhjRjkxY0dSaGRHVXNYRzRnSUY5bWIzSXNYRzRnSUY5MGNubGNibjA3WEc0aVhTd2ljMjkxY21ObFVtOXZkQ0k2SWk5emIzVnlZMlV2SW4wPVxuIiwiaW1wb3J0IFByb2Nlc3NTeXN0ZW0gZnJvbSAnLi9jb3JlL3Byb2Nlc3Nlcy9wcm9jZXNzX3N5c3RlbSc7XG5pbXBvcnQgeyBUdXBsZSwgUElELCBJbnRlZ2VyLCBGbG9hdCB9IGZyb20gJy4vY29yZS9wcmltaXRpdmVzJztcbmltcG9ydCBCaXRTdHJpbmcgZnJvbSAnLi9jb3JlL2JpdF9zdHJpbmcnO1xuaW1wb3J0IFBhdHRlcm5zIGZyb20gJy4vY29yZS9wYXR0ZXJucyc7XG5pbXBvcnQgRnVuY3Rpb25zIGZyb20gJy4vY29yZS9mdW5jdGlvbnMnO1xuaW1wb3J0IFNwZWNpYWxGb3JtcyBmcm9tICcuL2NvcmUvc3BlY2lhbF9mb3Jtcyc7XG5cbkZ1bmN0aW9ucy5nZXRfZ2xvYmFsKCkucHJvY2Vzc2VzID0gRnVuY3Rpb25zLmdldF9nbG9iYWwoKS5wcm9jZXNzZXMgfHwgbmV3IFByb2Nlc3NTeXN0ZW0oKTtcblxuZXhwb3J0IGRlZmF1bHQge1xuICBQcm9jZXNzU3lzdGVtLFxuICBUdXBsZSxcbiAgUElELFxuICBCaXRTdHJpbmcsXG4gIFBhdHRlcm5zLFxuICBJbnRlZ2VyLFxuICBGbG9hdCxcbiAgRnVuY3Rpb25zLFxuICBTcGVjaWFsRm9ybXNcbn07XG4vLyMgc291cmNlTWFwcGluZ1VSTD1kYXRhOmFwcGxpY2F0aW9uL2pzb247YmFzZTY0LGV5SjJaWEp6YVc5dUlqb3pMQ0p6YjNWeVkyVnpJanBiSW14cFlpOWpiM0psTG1weklsMHNJbTVoYldWeklqcGJYU3dpYldGd2NHbHVaM01pT2lKQlFVRkJMRTlCUVU4c1lVRkJVQ3hOUVVFd1FpeHBRMEZCTVVJN1FVRkRRU3hUUVVGVExFdEJRVlFzUlVGQlowSXNSMEZCYUVJc1JVRkJjVUlzVDBGQmNrSXNSVUZCT0VJc1MwRkJPVUlzVVVGQk1rTXNiVUpCUVRORE8wRkJRMEVzVDBGQlR5eFRRVUZRTEUxQlFYTkNMRzFDUVVGMFFqdEJRVU5CTEU5QlFVOHNVVUZCVUN4TlFVRnhRaXhwUWtGQmNrSTdRVUZEUVN4UFFVRlBMRk5CUVZBc1RVRkJjMElzYTBKQlFYUkNPMEZCUTBFc1QwRkJUeXhaUVVGUUxFMUJRWGxDTEhOQ1FVRjZRanM3UVVGRlFTeFZRVUZWTEZWQlFWWXNSMEZCZFVJc1UwRkJka0lzUjBGQmJVTXNWVUZCVlN4VlFVRldMRWRCUVhWQ0xGTkJRWFpDTEVsQlFXOURMRWxCUVVrc1lVRkJTaXhGUVVGd1F6czdRVUZGYmtNc1pVRkJaVHRCUVVOaUxHVkJSR0U3UVVGRllpeFBRVVpoTzBGQlIySXNTMEZJWVR0QlFVbGlMRmRCU21FN1FVRkxZaXhWUVV4aE8wRkJUV0lzVTBGT1lUdEJRVTlpTEU5QlVHRTdRVUZSWWl4WFFWSmhPMEZCVTJJc1kwRlVZVHREUVVGbUlpd2labWxzWlNJNklteHBZaTlqYjNKbExtcHpJaXdpYzI5MWNtTmxjME52Ym5SbGJuUWlPbHNpYVcxd2IzSjBJRkJ5YjJObGMzTlRlWE4wWlcwZ1puSnZiU0FuTGk5amIzSmxMM0J5YjJObGMzTmxjeTl3Y205alpYTnpYM041YzNSbGJTYzdYRzVwYlhCdmNuUWdleUJVZFhCc1pTd2dVRWxFTENCSmJuUmxaMlZ5TENCR2JHOWhkQ0I5SUdaeWIyMGdKeTR2WTI5eVpTOXdjbWx0YVhScGRtVnpKenRjYm1sdGNHOXlkQ0JDYVhSVGRISnBibWNnWm5KdmJTQW5MaTlqYjNKbEwySnBkRjl6ZEhKcGJtY25PMXh1YVcxd2IzSjBJRkJoZEhSbGNtNXpJR1p5YjIwZ0p5NHZZMjl5WlM5d1lYUjBaWEp1Y3ljN1hHNXBiWEJ2Y25RZ1JuVnVZM1JwYjI1eklHWnliMjBnSnk0dlkyOXlaUzltZFc1amRHbHZibk1uTzF4dWFXMXdiM0owSUZOd1pXTnBZV3hHYjNKdGN5Qm1jbTl0SUNjdUwyTnZjbVV2YzNCbFkybGhiRjltYjNKdGN5YzdYRzVjYmtaMWJtTjBhVzl1Y3k1blpYUmZaMnh2WW1Gc0tDa3VjSEp2WTJWemMyVnpJRDBnUm5WdVkzUnBiMjV6TG1kbGRGOW5iRzlpWVd3b0tTNXdjbTlqWlhOelpYTWdmSHdnYm1WM0lGQnliMk5sYzNOVGVYTjBaVzBvS1R0Y2JseHVaWGh3YjNKMElHUmxabUYxYkhRZ2UxeHVJQ0JRY205alpYTnpVM2x6ZEdWdExGeHVJQ0JVZFhCc1pTeGNiaUFnVUVsRUxGeHVJQ0JDYVhSVGRISnBibWNzWEc0Z0lGQmhkSFJsY201ekxGeHVJQ0JKYm5SbFoyVnlMRnh1SUNCR2JHOWhkQ3hjYmlBZ1JuVnVZM1JwYjI1ekxGeHVJQ0JUY0dWamFXRnNSbTl5YlhOY2JuMWNiaUpkTENKemIzVnlZMlZTYjI5MElqb2lMM052ZFhKalpTOGlmUT09XG4iLCJpbXBvcnQgQ29yZSBmcm9tICcuL2NvcmUnO1xuXG5sZXQgRW51bSA9IHtcblxuICBhbGxfX3FtYXJrX186IGZ1bmN0aW9uIChjb2xsZWN0aW9uLCBmdW4gPSB4ID0+IHgpIHtcbiAgICBmb3IgKGxldCBlbGVtIG9mIGNvbGxlY3Rpb24pIHtcbiAgICAgIGlmICghZnVuKGVsZW0pKSB7XG4gICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICByZXR1cm4gdHJ1ZTtcbiAgfSxcblxuICBhbnlfX3FtYXJrX186IGZ1bmN0aW9uIChjb2xsZWN0aW9uLCBmdW4gPSB4ID0+IHgpIHtcbiAgICBmb3IgKGxldCBlbGVtIG9mIGNvbGxlY3Rpb24pIHtcbiAgICAgIGlmIChmdW4oZWxlbSkpIHtcbiAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICB9XG4gICAgfVxuXG4gICAgcmV0dXJuIGZhbHNlO1xuICB9LFxuXG4gIGF0OiBmdW5jdGlvbiAoY29sbGVjdGlvbiwgbiwgdGhlX2RlZmF1bHQgPSBudWxsKSB7XG4gICAgaWYgKG4gPiB0aGlzLmNvdW50KGNvbGxlY3Rpb24pIHx8IG4gPCAwKSB7XG4gICAgICByZXR1cm4gdGhlX2RlZmF1bHQ7XG4gICAgfVxuXG4gICAgcmV0dXJuIGNvbGxlY3Rpb25bbl07XG4gIH0sXG5cbiAgY29uY2F0OiBmdW5jdGlvbiAoLi4uZW51bWFibGVzKSB7XG4gICAgcmV0dXJuIGVudW1hYmxlc1swXS5jb25jYXQoZW51bWFibGVzWzFdKTtcbiAgfSxcblxuICBjb3VudDogZnVuY3Rpb24gKGNvbGxlY3Rpb24sIGZ1biA9IG51bGwpIHtcbiAgICBpZiAoZnVuID09IG51bGwpIHtcbiAgICAgIHJldHVybiBjb2xsZWN0aW9uLmxlbmd0aDtcbiAgICB9IGVsc2Uge1xuICAgICAgcmV0dXJuIGNvbGxlY3Rpb24uZmlsdGVyKGZ1bikubGVuZ3RoO1xuICAgIH1cbiAgfSxcblxuICBkcm9wOiBmdW5jdGlvbiAoY29sbGVjdGlvbiwgY291bnQpIHtcbiAgICByZXR1cm4gY29sbGVjdGlvbi5zbGljZShjb3VudCk7XG4gIH0sXG5cbiAgZHJvcF93aGlsZTogZnVuY3Rpb24gKGNvbGxlY3Rpb24sIGZ1bikge1xuICAgIGxldCBjb3VudCA9IDA7XG5cbiAgICBmb3IgKGxldCBlbGVtIG9mIGNvbGxlY3Rpb24pIHtcbiAgICAgIGlmIChmdW4oZWxlbSkpIHtcbiAgICAgICAgY291bnQgPSBjb3VudCArIDE7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBicmVhaztcbiAgICAgIH1cbiAgICB9XG5cbiAgICByZXR1cm4gY29sbGVjdGlvbi5zbGljZShjb3VudCk7XG4gIH0sXG5cbiAgZWFjaDogZnVuY3Rpb24gKGNvbGxlY3Rpb24sIGZ1bikge1xuICAgIGZvciAobGV0IGVsZW0gb2YgY29sbGVjdGlvbikge1xuICAgICAgZnVuKGVsZW0pO1xuICAgIH1cbiAgfSxcblxuICBlbXB0eV9fcW1hcmtfXzogZnVuY3Rpb24gKGNvbGxlY3Rpb24pIHtcbiAgICByZXR1cm4gY29sbGVjdGlvbi5sZW5ndGggPT09IDA7XG4gIH0sXG5cbiAgZmV0Y2g6IGZ1bmN0aW9uIChjb2xsZWN0aW9uLCBuKSB7XG4gICAgaWYgKEFycmF5LmlzQXJyYXkoY29sbGVjdGlvbikpIHtcbiAgICAgIGlmIChuIDwgdGhpcy5jb3VudChjb2xsZWN0aW9uKSAmJiBuID49IDApIHtcbiAgICAgICAgcmV0dXJuIG5ldyBDb3JlLlR1cGxlKFN5bWJvbC5mb3IoXCJva1wiKSwgY29sbGVjdGlvbltuXSk7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICByZXR1cm4gU3ltYm9sLmZvcihcImVycm9yXCIpO1xuICAgICAgfVxuICAgIH1cblxuICAgIHRocm93IG5ldyBFcnJvcihcImNvbGxlY3Rpb24gaXMgbm90IGFuIEVudW1lcmFibGVcIik7XG4gIH0sXG5cbiAgZmV0Y2hfX2VtYXJrX186IGZ1bmN0aW9uIChjb2xsZWN0aW9uLCBuKSB7XG4gICAgaWYgKEFycmF5LmlzQXJyYXkoY29sbGVjdGlvbikpIHtcbiAgICAgIGlmIChuIDwgdGhpcy5jb3VudChjb2xsZWN0aW9uKSAmJiBuID49IDApIHtcbiAgICAgICAgcmV0dXJuIGNvbGxlY3Rpb25bbl07XG4gICAgICB9IGVsc2Uge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoXCJvdXQgb2YgYm91bmRzIGVycm9yXCIpO1xuICAgICAgfVxuICAgIH1cblxuICAgIHRocm93IG5ldyBFcnJvcihcImNvbGxlY3Rpb24gaXMgbm90IGFuIEVudW1lcmFibGVcIik7XG4gIH0sXG5cbiAgZmlsdGVyOiBmdW5jdGlvbiAoY29sbGVjdGlvbiwgZnVuKSB7XG4gICAgbGV0IHJlc3VsdCA9IFtdO1xuXG4gICAgZm9yIChsZXQgZWxlbSBvZiBjb2xsZWN0aW9uKSB7XG4gICAgICBpZiAoZnVuKGVsZW0pKSB7XG4gICAgICAgIHJlc3VsdC5wdXNoKGVsZW0pO1xuICAgICAgfVxuICAgIH1cblxuICAgIHJldHVybiByZXN1bHQ7XG4gIH0sXG5cbiAgZmlsdGVyX21hcDogZnVuY3Rpb24gKGNvbGxlY3Rpb24sIGZpbHRlciwgbWFwcGVyKSB7XG4gICAgcmV0dXJuIEVudW0ubWFwKEVudW0uZmlsdGVyKGNvbGxlY3Rpb24sIGZpbHRlciksIG1hcHBlcik7XG4gIH0sXG5cbiAgZmluZDogZnVuY3Rpb24gKGNvbGxlY3Rpb24sIGlmX25vbmUgPSBudWxsLCBmdW4pIHtcbiAgICBmb3IgKGxldCBlbGVtIG9mIGNvbGxlY3Rpb24pIHtcbiAgICAgIGlmIChmdW4oZWxlbSkpIHtcbiAgICAgICAgcmV0dXJuIGVsZW07XG4gICAgICB9XG4gICAgfVxuXG4gICAgcmV0dXJuIGlmX25vbmU7XG4gIH0sXG5cbiAgaW50bzogZnVuY3Rpb24gKGNvbGxlY3Rpb24sIGxpc3QpIHtcbiAgICByZXR1cm4gbGlzdC5jb25jYXQoY29sbGVjdGlvbik7XG4gIH0sXG5cbiAgbWFwOiBmdW5jdGlvbiAoY29sbGVjdGlvbiwgZnVuKSB7XG4gICAgbGV0IHJlc3VsdCA9IFtdO1xuXG4gICAgZm9yIChsZXQgZWxlbSBvZiBjb2xsZWN0aW9uKSB7XG4gICAgICByZXN1bHQucHVzaChmdW4oZWxlbSkpO1xuICAgIH1cblxuICAgIHJldHVybiByZXN1bHQ7XG4gIH0sXG5cbiAgbWFwX3JlZHVjZTogZnVuY3Rpb24gKGNvbGxlY3Rpb24sIGFjYywgZnVuKSB7XG4gICAgbGV0IG1hcHBlZCA9IE9iamVjdC5mcmVlemUoW10pO1xuICAgIGxldCB0aGVfYWNjID0gYWNjO1xuXG4gICAgZm9yICh2YXIgaSA9IDA7IGkgPCB0aGlzLmNvdW50KGNvbGxlY3Rpb24pOyBpKyspIHtcbiAgICAgIGxldCB0dXBsZSA9IGZ1bihjb2xsZWN0aW9uW2ldLCB0aGVfYWNjKTtcblxuICAgICAgdGhlX2FjYyA9IHR1cGxlLmdldCgxKTtcbiAgICAgIG1hcHBlZCA9IE9iamVjdC5mcmVlemUobWFwcGVkLmNvbmNhdChbdHVwbGUuZ2V0KDApXSkpO1xuICAgIH1cblxuICAgIHJldHVybiBuZXcgQ29yZS5UdXBsZShtYXBwZWQsIHRoZV9hY2MpO1xuICB9LFxuXG4gIG1lbWJlcl9fcW1hcmtfXzogZnVuY3Rpb24gKGNvbGxlY3Rpb24sIHZhbHVlKSB7XG4gICAgcmV0dXJuIGNvbGxlY3Rpb24uaW5jbHVkZXModmFsdWUpO1xuICB9LFxuXG4gIHJlZHVjZTogZnVuY3Rpb24gKGNvbGxlY3Rpb24sIGFjYywgZnVuKSB7XG4gICAgbGV0IHRoZV9hY2MgPSBhY2M7XG5cbiAgICBmb3IgKHZhciBpID0gMDsgaSA8IHRoaXMuY291bnQoY29sbGVjdGlvbik7IGkrKykge1xuICAgICAgbGV0IHR1cGxlID0gZnVuKGNvbGxlY3Rpb25baV0sIHRoZV9hY2MpO1xuXG4gICAgICB0aGVfYWNjID0gdHVwbGUuZ2V0KDEpO1xuICAgIH1cblxuICAgIHJldHVybiB0aGVfYWNjO1xuICB9LFxuXG4gIHRha2U6IGZ1bmN0aW9uIChjb2xsZWN0aW9uLCBjb3VudCkge1xuICAgIHJldHVybiBjb2xsZWN0aW9uLnNsaWNlKDAsIGNvdW50KTtcbiAgfSxcblxuICB0YWtlX2V2ZXJ5OiBmdW5jdGlvbiAoY29sbGVjdGlvbiwgbnRoKSB7XG4gICAgbGV0IHJlc3VsdCA9IFtdO1xuICAgIGxldCBpbmRleCA9IDA7XG5cbiAgICBmb3IgKGxldCBlbGVtIG9mIGNvbGxlY3Rpb24pIHtcbiAgICAgIGlmIChpbmRleCAlIG50aCA9PT0gMCkge1xuICAgICAgICByZXN1bHQucHVzaChlbGVtKTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICByZXR1cm4gT2JqZWN0LmZyZWV6ZShyZXN1bHQpO1xuICB9LFxuXG4gIHRha2Vfd2hpbGU6IGZ1bmN0aW9uIChjb2xsZWN0aW9uLCBmdW4pIHtcbiAgICBsZXQgY291bnQgPSAwO1xuXG4gICAgZm9yIChsZXQgZWxlbSBvZiBjb2xsZWN0aW9uKSB7XG4gICAgICBpZiAoZnVuKGVsZW0pKSB7XG4gICAgICAgIGNvdW50ID0gY291bnQgKyAxO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgYnJlYWs7XG4gICAgICB9XG4gICAgfVxuXG4gICAgcmV0dXJuIGNvbGxlY3Rpb24uc2xpY2UoMCwgY291bnQpO1xuICB9LFxuXG4gIHRvX2xpc3Q6IGZ1bmN0aW9uIChjb2xsZWN0aW9uKSB7XG4gICAgcmV0dXJuIGNvbGxlY3Rpb247XG4gIH1cbn07XG5cbmV4cG9ydCBkZWZhdWx0IEVudW07XG4vLyMgc291cmNlTWFwcGluZ1VSTD1kYXRhOmFwcGxpY2F0aW9uL2pzb247YmFzZTY0LGV5SjJaWEp6YVc5dUlqb3pMQ0p6YjNWeVkyVnpJanBiSW14cFlpOWxiblZ0TG1weklsMHNJbTVoYldWeklqcGJYU3dpYldGd2NHbHVaM01pT2lKQlFVRkJMRTlCUVU4c1NVRkJVQ3hOUVVGcFFpeFJRVUZxUWpzN1FVRkZRU3hKUVVGSkxFOUJRVTg3TzBGQlJWUXNaMEpCUVdNc1ZVRkJVeXhWUVVGVUxFVkJRWEZDTEUxQlFVMHNTMEZCVHl4RFFVRlFMRVZCUVZNN1FVRkRhRVFzVTBGQlNTeEpRVUZKTEVsQlFVb3NTVUZCV1N4VlFVRm9RaXhGUVVFeVFqdEJRVU42UWl4VlFVRkhMRU5CUVVNc1NVRkJTU3hKUVVGS0xFTkJRVVFzUlVGQlZ6dEJRVU5hTEdWQlFVOHNTMEZCVUN4RFFVUlpPMDlCUVdRN1MwRkVSanM3UVVGTlFTeFhRVUZQTEVsQlFWQXNRMEZRWjBRN1IwRkJjRU03TzBGQlZXUXNaMEpCUVdNc1ZVRkJVeXhWUVVGVUxFVkJRWEZDTEUxQlFVMHNTMEZCVHl4RFFVRlFMRVZCUVZNN1FVRkRhRVFzVTBGQlNTeEpRVUZKTEVsQlFVb3NTVUZCV1N4VlFVRm9RaXhGUVVFeVFqdEJRVU42UWl4VlFVRkhMRWxCUVVrc1NVRkJTaXhEUVVGSUxFVkJRV0U3UVVGRFdDeGxRVUZQTEVsQlFWQXNRMEZFVnp0UFFVRmlPMHRCUkVZN08wRkJUVUVzVjBGQlR5eExRVUZRTEVOQlVHZEVPMGRCUVhCRE96dEJRVlZrTEUxQlFVa3NWVUZCVXl4VlFVRlVMRVZCUVhGQ0xFTkJRWEpDTEVWQlFYZENMR05CUVdNc1NVRkJaQ3hGUVVGdFFqdEJRVU0zUXl4UlFVRkhMRWxCUVVrc1MwRkJTeXhMUVVGTUxFTkJRVmNzVlVGQldDeERRVUZLTEVsQlFUaENMRWxCUVVrc1EwRkJTaXhGUVVGTk8wRkJRM0pETEdGQlFVOHNWMEZCVUN4RFFVUnhRenRMUVVGMlF6czdRVUZKUVN4WFFVRlBMRmRCUVZjc1EwRkJXQ3hEUVVGUUxFTkJURFpETzBkQlFUTkRPenRCUVZGS0xGVkJRVkVzVlVGQlV5eEhRVUZITEZOQlFVZ3NSVUZCWVR0QlFVTTFRaXhYUVVGUExGVkJRVlVzUTBGQlZpeEZRVUZoTEUxQlFXSXNRMEZCYjBJc1ZVRkJWU3hEUVVGV0xFTkJRWEJDTEVOQlFWQXNRMEZFTkVJN1IwRkJkRUk3TzBGQlNWSXNVMEZCVHl4VlFVRlRMRlZCUVZRc1JVRkJjVUlzVFVGQlRTeEpRVUZPTEVWQlFWYzdRVUZEY2tNc1VVRkJSeXhQUVVGUExFbEJRVkFzUlVGQldUdEJRVU5pTEdGQlFVOHNWMEZCVnl4TlFVRllMRU5CUkUwN1MwRkJaaXhOUVVWUE8wRkJRMHdzWVVGQlR5eFhRVUZYTEUxQlFWZ3NRMEZCYTBJc1IwRkJiRUlzUlVGQmRVSXNUVUZCZGtJc1EwRkVSanRMUVVaUU8wZEJSRXM3TzBGQlVWQXNVVUZCVFN4VlFVRlRMRlZCUVZRc1JVRkJjVUlzUzBGQmNrSXNSVUZCTWtJN1FVRkRMMElzVjBGQlR5eFhRVUZYTEV0QlFWZ3NRMEZCYVVJc1MwRkJha0lzUTBGQlVDeERRVVFyUWp0SFFVRXpRanM3UVVGSlRpeGpRVUZaTEZWQlFWTXNWVUZCVkN4RlFVRnhRaXhIUVVGeVFpeEZRVUY1UWp0QlFVTnVReXhSUVVGSkxGRkJRVkVzUTBGQlVpeERRVVFyUWpzN1FVRkhia01zVTBGQlNTeEpRVUZKTEVsQlFVb3NTVUZCV1N4VlFVRm9RaXhGUVVFeVFqdEJRVU42UWl4VlFVRkhMRWxCUVVrc1NVRkJTaXhEUVVGSUxFVkJRV0U3UVVGRFdDeG5Ra0ZCVVN4UlFVRlJMRU5CUVZJc1EwRkVSenRQUVVGaUxFMUJSVXM3UVVGRFNDeGpRVVJITzA5QlJrdzdTMEZFUmpzN1FVRlJRU3hYUVVGUExGZEJRVmNzUzBGQldDeERRVUZwUWl4TFFVRnFRaXhEUVVGUUxFTkJXRzFETzBkQlFYcENPenRCUVdOYUxGRkJRVTBzVlVGQlV5eFZRVUZVTEVWQlFYRkNMRWRCUVhKQ0xFVkJRWGxDTzBGQlF6ZENMRk5CUVVrc1NVRkJTU3hKUVVGS0xFbEJRVmtzVlVGQmFFSXNSVUZCTWtJN1FVRkRla0lzVlVGQlNTeEpRVUZLTEVWQlJIbENPMHRCUVROQ08wZEJSRWs3TzBGQlRVNHNhMEpCUVdkQ0xGVkJRVk1zVlVGQlZDeEZRVUZ2UWp0QlFVTnNReXhYUVVGUExGZEJRVmNzVFVGQldDeExRVUZ6UWl4RFFVRjBRaXhEUVVReVFqdEhRVUZ3UWpzN1FVRkphRUlzVTBGQlR5eFZRVUZUTEZWQlFWUXNSVUZCY1VJc1EwRkJja0lzUlVGQmRVSTdRVUZETlVJc1VVRkJSeXhOUVVGTkxFOUJRVTRzUTBGQll5eFZRVUZrTEVOQlFVZ3NSVUZCTmtJN1FVRkRNMElzVlVGQlJ5eEpRVUZKTEV0QlFVc3NTMEZCVEN4RFFVRlhMRlZCUVZnc1EwRkJTaXhKUVVFNFFpeExRVUZMTEVOQlFVd3NSVUZCVHp0QlFVTjBReXhsUVVGUExFbEJRVWtzUzBGQlN5eExRVUZNTEVOQlFWY3NUMEZCVHl4SFFVRlFMRU5CUVZjc1NVRkJXQ3hEUVVGbUxFVkJRV2xETEZkQlFWY3NRMEZCV0N4RFFVRnFReXhEUVVGUUxFTkJSSE5ETzA5QlFYaERMRTFCUlVzN1FVRkRTQ3hsUVVGUExFOUJRVThzUjBGQlVDeERRVUZYTEU5QlFWZ3NRMEZCVUN4RFFVUkhPMDlCUmt3N1MwRkVSanM3UVVGUlFTeFZRVUZOTEVsQlFVa3NTMEZCU2l4RFFVRlZMR2xEUVVGV0xFTkJRVTRzUTBGVU5FSTdSMEZCZGtJN08wRkJXVkFzYTBKQlFXZENMRlZCUVZNc1ZVRkJWQ3hGUVVGeFFpeERRVUZ5UWl4RlFVRjFRanRCUVVOeVF5eFJRVUZITEUxQlFVMHNUMEZCVGl4RFFVRmpMRlZCUVdRc1EwRkJTQ3hGUVVFMlFqdEJRVU16UWl4VlFVRkhMRWxCUVVrc1MwRkJTeXhMUVVGTUxFTkJRVmNzVlVGQldDeERRVUZLTEVsQlFUaENMRXRCUVVzc1EwRkJUQ3hGUVVGUE8wRkJRM1JETEdWQlFVOHNWMEZCVnl4RFFVRllMRU5CUVZBc1EwRkVjME03VDBGQmVFTXNUVUZGU3p0QlFVTklMR05CUVUwc1NVRkJTU3hMUVVGS0xFTkJRVlVzY1VKQlFWWXNRMEZCVGl4RFFVUkhPMDlCUmt3N1MwRkVSanM3UVVGUlFTeFZRVUZOTEVsQlFVa3NTMEZCU2l4RFFVRlZMR2xEUVVGV0xFTkJRVTRzUTBGVWNVTTdSMEZCZGtJN08wRkJXV2hDTEZWQlFWRXNWVUZCVXl4VlFVRlVMRVZCUVhGQ0xFZEJRWEpDTEVWQlFYbENPMEZCUXk5Q0xGRkJRVWtzVTBGQlV5eEZRVUZVTEVOQlJESkNPenRCUVVjdlFpeFRRVUZKTEVsQlFVa3NTVUZCU2l4SlFVRlpMRlZCUVdoQ0xFVkJRVEpDTzBGQlEzcENMRlZCUVVjc1NVRkJTU3hKUVVGS0xFTkJRVWdzUlVGQllUdEJRVU5ZTEdWQlFVOHNTVUZCVUN4RFFVRlpMRWxCUVZvc1JVRkVWenRQUVVGaU8wdEJSRVk3TzBGQlRVRXNWMEZCVHl4TlFVRlFMRU5CVkN0Q08wZEJRWHBDT3p0QlFWbFNMR05CUVZrc1ZVRkJVeXhWUVVGVUxFVkJRWEZDTEUxQlFYSkNMRVZCUVRaQ0xFMUJRVGRDTEVWQlFXOURPMEZCUXpsRExGZEJRVThzUzBGQlN5eEhRVUZNTEVOQlFWTXNTMEZCU3l4TlFVRk1MRU5CUVZrc1ZVRkJXaXhGUVVGM1FpeE5RVUY0UWl4RFFVRlVMRVZCUVRCRExFMUJRVEZETEVOQlFWQXNRMEZFT0VNN1IwRkJjRU03TzBGQlNWb3NVVUZCVFN4VlFVRlRMRlZCUVZRc1JVRkJjVUlzVlVGQlZTeEpRVUZXTEVWQlFXZENMRWRCUVhKRExFVkJRWGxETzBGQlF6ZERMRk5CUVVrc1NVRkJTU3hKUVVGS0xFbEJRVmtzVlVGQmFFSXNSVUZCTWtJN1FVRkRla0lzVlVGQlJ5eEpRVUZKTEVsQlFVb3NRMEZCU0N4RlFVRmhPMEZCUTFnc1pVRkJUeXhKUVVGUUxFTkJSRmM3VDBGQllqdExRVVJHT3p0QlFVMUJMRmRCUVU4c1QwRkJVQ3hEUVZBMlF6dEhRVUY2UXpzN1FVRlZUaXhSUVVGTkxGVkJRVk1zVlVGQlZDeEZRVUZ4UWl4SlFVRnlRaXhGUVVFd1FqdEJRVU01UWl4WFFVRlBMRXRCUVVzc1RVRkJUQ3hEUVVGWkxGVkJRVm9zUTBGQlVDeERRVVE0UWp0SFFVRXhRanM3UVVGSlRpeFBRVUZMTEZWQlFWTXNWVUZCVkN4RlFVRnhRaXhIUVVGeVFpeEZRVUY1UWp0QlFVTTFRaXhSUVVGSkxGTkJRVk1zUlVGQlZDeERRVVIzUWpzN1FVRkhOVUlzVTBGQlNTeEpRVUZKTEVsQlFVb3NTVUZCV1N4VlFVRm9RaXhGUVVFeVFqdEJRVU42UWl4aFFVRlBMRWxCUVZBc1EwRkJXU3hKUVVGSkxFbEJRVW9zUTBGQldpeEZRVVI1UWp0TFFVRXpRanM3UVVGSlFTeFhRVUZQTEUxQlFWQXNRMEZRTkVJN1IwRkJla0k3TzBGQlZVd3NZMEZCV1N4VlFVRlRMRlZCUVZRc1JVRkJjVUlzUjBGQmNrSXNSVUZCTUVJc1IwRkJNVUlzUlVGQk9FSTdRVUZEZUVNc1VVRkJTU3hUUVVGVExFOUJRVThzVFVGQlVDeERRVUZqTEVWQlFXUXNRMEZCVkN4RFFVUnZRenRCUVVWNFF5eFJRVUZKTEZWQlFWVXNSMEZCVml4RFFVWnZRenM3UVVGSmVFTXNVMEZCU3l4SlFVRkpMRWxCUVVrc1EwRkJTaXhGUVVGUExFbEJRVWtzUzBGQlN5eExRVUZNTEVOQlFWY3NWVUZCV0N4RFFVRktMRVZCUVRSQ0xFZEJRVFZETEVWQlFXbEVPMEZCUXk5RExGVkJRVWtzVVVGQlVTeEpRVUZKTEZkQlFWY3NRMEZCV0N4RFFVRktMRVZCUVcxQ0xFOUJRVzVDTEVOQlFWSXNRMEZFTWtNN08wRkJSeTlETEdkQ1FVRlZMRTFCUVUwc1IwRkJUaXhEUVVGVkxFTkJRVllzUTBGQlZpeERRVWdyUXp0QlFVa3ZReXhsUVVGVExFOUJRVThzVFVGQlVDeERRVUZqTEU5QlFVOHNUVUZCVUN4RFFVRmpMRU5CUVVNc1RVRkJUU3hIUVVGT0xFTkJRVlVzUTBGQlZpeERRVUZFTEVOQlFXUXNRMEZCWkN4RFFVRlVMRU5CU2l0RE8wdEJRV3BFT3p0QlFVOUJMRmRCUVU4c1NVRkJTU3hMUVVGTExFdEJRVXdzUTBGQlZ5eE5RVUZtTEVWQlFYVkNMRTlCUVhaQ0xFTkJRVkFzUTBGWWQwTTdSMEZCT1VJN08wRkJZMW9zYlVKQlFXbENMRlZCUVZNc1ZVRkJWQ3hGUVVGeFFpeExRVUZ5UWl4RlFVRXlRanRCUVVNeFF5eFhRVUZQTEZkQlFWY3NVVUZCV0N4RFFVRnZRaXhMUVVGd1FpeERRVUZRTEVOQlJEQkRPMGRCUVROQ096dEJRVWxxUWl4VlFVRlJMRlZCUVZNc1ZVRkJWQ3hGUVVGeFFpeEhRVUZ5UWl4RlFVRXdRaXhIUVVFeFFpeEZRVUU0UWp0QlFVTndReXhSUVVGSkxGVkJRVlVzUjBGQlZpeERRVVJuUXpzN1FVRkhjRU1zVTBGQlN5eEpRVUZKTEVsQlFVa3NRMEZCU2l4RlFVRlBMRWxCUVVrc1MwRkJTeXhMUVVGTUxFTkJRVmNzVlVGQldDeERRVUZLTEVWQlFUUkNMRWRCUVRWRExFVkJRV2xFTzBGQlF5OURMRlZCUVVrc1VVRkJVU3hKUVVGSkxGZEJRVmNzUTBGQldDeERRVUZLTEVWQlFXMUNMRTlCUVc1Q0xFTkJRVklzUTBGRU1rTTdPMEZCUnk5RExHZENRVUZWTEUxQlFVMHNSMEZCVGl4RFFVRlZMRU5CUVZZc1EwRkJWaXhEUVVnclF6dExRVUZxUkRzN1FVRk5RU3hYUVVGUExFOUJRVkFzUTBGVWIwTTdSMEZCT1VJN08wRkJXVklzVVVGQlRTeFZRVUZUTEZWQlFWUXNSVUZCY1VJc1MwRkJja0lzUlVGQk1rSTdRVUZETDBJc1YwRkJUeXhYUVVGWExFdEJRVmdzUTBGQmFVSXNRMEZCYWtJc1JVRkJiMElzUzBGQmNFSXNRMEZCVUN4RFFVUXJRanRIUVVFelFqczdRVUZKVGl4alFVRlpMRlZCUVZNc1ZVRkJWQ3hGUVVGeFFpeEhRVUZ5UWl4RlFVRjVRanRCUVVOdVF5eFJRVUZKTEZOQlFWTXNSVUZCVkN4RFFVUXJRanRCUVVWdVF5eFJRVUZKTEZGQlFWRXNRMEZCVWl4RFFVWXJRanM3UVVGSmJrTXNVMEZCU1N4SlFVRkpMRWxCUVVvc1NVRkJXU3hWUVVGb1FpeEZRVUV5UWp0QlFVTjZRaXhWUVVGSExGRkJRVkVzUjBGQlVpeExRVUZuUWl4RFFVRm9RaXhGUVVGclFqdEJRVU51UWl4bFFVRlBMRWxCUVZBc1EwRkJXU3hKUVVGYUxFVkJSRzFDTzA5QlFYSkNPMHRCUkVZN08wRkJUVUVzVjBGQlR5eFBRVUZQTEUxQlFWQXNRMEZCWXl4TlFVRmtMRU5CUVZBc1EwRldiVU03UjBGQmVrSTdPMEZCWVZvc1kwRkJXU3hWUVVGVExGVkJRVlFzUlVGQmNVSXNSMEZCY2tJc1JVRkJlVUk3UVVGRGJrTXNVVUZCU1N4UlFVRlJMRU5CUVZJc1EwRkVLMEk3TzBGQlIyNURMRk5CUVVrc1NVRkJTU3hKUVVGS0xFbEJRVmtzVlVGQmFFSXNSVUZCTWtJN1FVRkRla0lzVlVGQlJ5eEpRVUZKTEVsQlFVb3NRMEZCU0N4RlFVRmhPMEZCUTFnc1owSkJRVkVzVVVGQlVTeERRVUZTTEVOQlJFYzdUMEZCWWl4TlFVVkxPMEZCUTBnc1kwRkVSenRQUVVaTU8wdEJSRVk3TzBGQlVVRXNWMEZCVHl4WFFVRlhMRXRCUVZnc1EwRkJhVUlzUTBGQmFrSXNSVUZCYjBJc1MwRkJjRUlzUTBGQlVDeERRVmh0UXp0SFFVRjZRanM3UVVGaldpeFhRVUZUTEZWQlFWTXNWVUZCVkN4RlFVRnZRanRCUVVNelFpeFhRVUZQTEZWQlFWQXNRMEZFTWtJN1IwRkJjRUk3UTBGdVRWQTdPMEZCZDAxS0xHVkJRV1VzU1VGQlppSXNJbVpwYkdVaU9pSnNhV0l2Wlc1MWJTNXFjeUlzSW5OdmRYSmpaWE5EYjI1MFpXNTBJanBiSW1sdGNHOXlkQ0JEYjNKbElHWnliMjBnSnk0dlkyOXlaU2M3WEc1Y2JteGxkQ0JGYm5WdElEMGdlMXh1WEc0Z0lHRnNiRjlmY1cxaGNtdGZYem9nWm5WdVkzUnBiMjRvWTI5c2JHVmpkR2x2Yml3Z1puVnVJRDBnS0hncElEMCtJSGdwZTF4dUlDQWdJR1p2Y2loc1pYUWdaV3hsYlNCdlppQmpiMnhzWldOMGFXOXVLWHRjYmlBZ0lDQWdJR2xtS0NGbWRXNG9aV3hsYlNrcGUxeHVJQ0FnSUNBZ0lDQnlaWFIxY200Z1ptRnNjMlU3WEc0Z0lDQWdJQ0I5WEc0Z0lDQWdmVnh1WEc0Z0lDQWdjbVYwZFhKdUlIUnlkV1U3WEc0Z0lIMHNYRzVjYmlBZ1lXNTVYMTl4YldGeWExOWZPaUJtZFc1amRHbHZiaWhqYjJ4c1pXTjBhVzl1TENCbWRXNGdQU0FvZUNrZ1BUNGdlQ2w3WEc0Z0lDQWdabTl5S0d4bGRDQmxiR1Z0SUc5bUlHTnZiR3hsWTNScGIyNHBlMXh1SUNBZ0lDQWdhV1lvWm5WdUtHVnNaVzBwS1h0Y2JpQWdJQ0FnSUNBZ2NtVjBkWEp1SUhSeWRXVTdYRzRnSUNBZ0lDQjlYRzRnSUNBZ2ZWeHVYRzRnSUNBZ2NtVjBkWEp1SUdaaGJITmxPMXh1SUNCOUxGeHVYRzRnSUdGME9pQm1kVzVqZEdsdmJpaGpiMnhzWldOMGFXOXVMQ0J1TENCMGFHVmZaR1ZtWVhWc2RDQTlJRzUxYkd3cGUxeHVJQ0FnSUdsbUtHNGdQaUIwYUdsekxtTnZkVzUwS0dOdmJHeGxZM1JwYjI0cElIeDhJRzRnUENBd0tYdGNiaUFnSUNBZ0lISmxkSFZ5YmlCMGFHVmZaR1ZtWVhWc2REdGNiaUFnSUNCOVhHNWNiaUFnSUNCeVpYUjFjbTRnWTI5c2JHVmpkR2x2Ymx0dVhUdGNiaUFnZlN4Y2JseHVJQ0JqYjI1allYUTZJR1oxYm1OMGFXOXVLQzR1TG1WdWRXMWhZbXhsY3lsN1hHNGdJQ0FnY21WMGRYSnVJR1Z1ZFcxaFlteGxjMXN3WFM1amIyNWpZWFFvWlc1MWJXRmliR1Z6V3pGZEtUdGNiaUFnZlN4Y2JseHVJQ0JqYjNWdWREb2dablZ1WTNScGIyNG9ZMjlzYkdWamRHbHZiaXdnWm5WdUlEMGdiblZzYkNsN1hHNGdJQ0FnYVdZb1puVnVJRDA5SUc1MWJHd3BlMXh1SUNBZ0lDQWdjbVYwZFhKdUlHTnZiR3hsWTNScGIyNHViR1Z1WjNSb08xeHVJQ0FnSUgwZ1pXeHpaU0I3WEc0Z0lDQWdJQ0J5WlhSMWNtNGdZMjlzYkdWamRHbHZiaTVtYVd4MFpYSW9ablZ1S1M1c1pXNW5kR2c3WEc0Z0lDQWdmVnh1SUNCOUxGeHVYRzRnSUdSeWIzQTZJR1oxYm1OMGFXOXVLR052Ykd4bFkzUnBiMjRzSUdOdmRXNTBLWHRjYmlBZ0lDQnlaWFIxY200Z1kyOXNiR1ZqZEdsdmJpNXpiR2xqWlNoamIzVnVkQ2s3WEc0Z0lIMHNYRzVjYmlBZ1pISnZjRjkzYUdsc1pUb2dablZ1WTNScGIyNG9ZMjlzYkdWamRHbHZiaXdnWm5WdUtYdGNiaUFnSUNCc1pYUWdZMjkxYm5RZ1BTQXdPMXh1WEc0Z0lDQWdabTl5S0d4bGRDQmxiR1Z0SUc5bUlHTnZiR3hsWTNScGIyNHBlMXh1SUNBZ0lDQWdhV1lvWm5WdUtHVnNaVzBwS1h0Y2JpQWdJQ0FnSUNBZ1kyOTFiblFnUFNCamIzVnVkQ0FySURFN1hHNGdJQ0FnSUNCOVpXeHpaWHRjYmlBZ0lDQWdJQ0FnWW5KbFlXczdYRzRnSUNBZ0lDQjlYRzRnSUNBZ2ZWeHVYRzRnSUNBZ2NtVjBkWEp1SUdOdmJHeGxZM1JwYjI0dWMyeHBZMlVvWTI5MWJuUXBPMXh1SUNCOUxGeHVYRzRnSUdWaFkyZzZJR1oxYm1OMGFXOXVLR052Ykd4bFkzUnBiMjRzSUdaMWJpbDdYRzRnSUNBZ1ptOXlLR3hsZENCbGJHVnRJRzltSUdOdmJHeGxZM1JwYjI0cGUxeHVJQ0FnSUNBZ1puVnVLR1ZzWlcwcE8xeHVJQ0FnSUgxY2JpQWdmU3hjYmx4dUlDQmxiWEIwZVY5ZmNXMWhjbXRmWHpvZ1puVnVZM1JwYjI0b1kyOXNiR1ZqZEdsdmJpbDdYRzRnSUNBZ2NtVjBkWEp1SUdOdmJHeGxZM1JwYjI0dWJHVnVaM1JvSUQwOVBTQXdPMXh1SUNCOUxGeHVYRzRnSUdabGRHTm9PaUJtZFc1amRHbHZiaWhqYjJ4c1pXTjBhVzl1TENCdUtYdGNiaUFnSUNCcFppaEJjbkpoZVM1cGMwRnljbUY1S0dOdmJHeGxZM1JwYjI0cEtYdGNiaUFnSUNBZ0lHbG1LRzRnUENCMGFHbHpMbU52ZFc1MEtHTnZiR3hsWTNScGIyNHBJQ1ltSUc0Z1BqMGdNQ2w3WEc0Z0lDQWdJQ0FnSUhKbGRIVnliaUJ1WlhjZ1EyOXlaUzVVZFhCc1pTaFRlVzFpYjJ3dVptOXlLRndpYjJ0Y0lpa3NJR052Ykd4bFkzUnBiMjViYmwwcE8xeHVJQ0FnSUNBZ2ZXVnNjMlY3WEc0Z0lDQWdJQ0FnSUhKbGRIVnliaUJUZVcxaWIyd3VabTl5S0Z3aVpYSnliM0pjSWlrN1hHNGdJQ0FnSUNCOVhHNGdJQ0FnZlZ4dVhHNGdJQ0FnZEdoeWIzY2dibVYzSUVWeWNtOXlLRndpWTI5c2JHVmpkR2x2YmlCcGN5QnViM1FnWVc0Z1JXNTFiV1Z5WVdKc1pWd2lLVHRjYmlBZ2ZTeGNibHh1SUNCbVpYUmphRjlmWlcxaGNtdGZYem9nWm5WdVkzUnBiMjRvWTI5c2JHVmpkR2x2Yml3Z2JpbDdYRzRnSUNBZ2FXWW9RWEp5WVhrdWFYTkJjbkpoZVNoamIyeHNaV04wYVc5dUtTbDdYRzRnSUNBZ0lDQnBaaWh1SUR3Z2RHaHBjeTVqYjNWdWRDaGpiMnhzWldOMGFXOXVLU0FtSmlCdUlENDlJREFwZTF4dUlDQWdJQ0FnSUNCeVpYUjFjbTRnWTI5c2JHVmpkR2x2Ymx0dVhUdGNiaUFnSUNBZ0lIMWxiSE5sZTF4dUlDQWdJQ0FnSUNCMGFISnZkeUJ1WlhjZ1JYSnliM0lvWENKdmRYUWdiMllnWW05MWJtUnpJR1Z5Y205eVhDSXBPMXh1SUNBZ0lDQWdmVnh1SUNBZ0lIMWNibHh1SUNBZ0lIUm9jbTkzSUc1bGR5QkZjbkp2Y2loY0ltTnZiR3hsWTNScGIyNGdhWE1nYm05MElHRnVJRVZ1ZFcxbGNtRmliR1ZjSWlrN1hHNGdJSDBzWEc1Y2JpQWdabWxzZEdWeU9pQm1kVzVqZEdsdmJpaGpiMnhzWldOMGFXOXVMQ0JtZFc0cGUxeHVJQ0FnSUd4bGRDQnlaWE4xYkhRZ1BTQmJYVHRjYmx4dUlDQWdJR1p2Y2loc1pYUWdaV3hsYlNCdlppQmpiMnhzWldOMGFXOXVLWHRjYmlBZ0lDQWdJR2xtS0daMWJpaGxiR1Z0S1NsN1hHNGdJQ0FnSUNBZ0lISmxjM1ZzZEM1d2RYTm9LR1ZzWlcwcE8xeHVJQ0FnSUNBZ2ZWeHVJQ0FnSUgxY2JseHVJQ0FnSUhKbGRIVnliaUJ5WlhOMWJIUTdYRzRnSUgwc1hHNWNiaUFnWm1sc2RHVnlYMjFoY0RvZ1puVnVZM1JwYjI0b1kyOXNiR1ZqZEdsdmJpd2dabWxzZEdWeUxDQnRZWEJ3WlhJcGUxeHVJQ0FnSUhKbGRIVnliaUJGYm5WdExtMWhjQ2hGYm5WdExtWnBiSFJsY2loamIyeHNaV04wYVc5dUxDQm1hV3gwWlhJcExDQnRZWEJ3WlhJcE8xeHVJQ0I5TEZ4dVhHNGdJR1pwYm1RNklHWjFibU4wYVc5dUtHTnZiR3hsWTNScGIyNHNJR2xtWDI1dmJtVWdQU0J1ZFd4c0xDQm1kVzRwZTF4dUlDQWdJR1p2Y2loc1pYUWdaV3hsYlNCdlppQmpiMnhzWldOMGFXOXVLWHRjYmlBZ0lDQWdJR2xtS0daMWJpaGxiR1Z0S1NsN1hHNGdJQ0FnSUNBZ0lISmxkSFZ5YmlCbGJHVnRPMXh1SUNBZ0lDQWdmVnh1SUNBZ0lIMWNibHh1SUNBZ0lISmxkSFZ5YmlCcFpsOXViMjVsTzF4dUlDQjlMRnh1WEc0Z0lHbHVkRzg2SUdaMWJtTjBhVzl1S0dOdmJHeGxZM1JwYjI0c0lHeHBjM1FwZTF4dUlDQWdJSEpsZEhWeWJpQnNhWE4wTG1OdmJtTmhkQ2hqYjJ4c1pXTjBhVzl1S1R0Y2JpQWdmU3hjYmx4dUlDQnRZWEE2SUdaMWJtTjBhVzl1S0dOdmJHeGxZM1JwYjI0c0lHWjFiaWw3WEc0Z0lDQWdiR1YwSUhKbGMzVnNkQ0E5SUZ0ZE8xeHVYRzRnSUNBZ1ptOXlLR3hsZENCbGJHVnRJRzltSUdOdmJHeGxZM1JwYjI0cGUxeHVJQ0FnSUNBZ2NtVnpkV3gwTG5CMWMyZ29ablZ1S0dWc1pXMHBLVHRjYmlBZ0lDQjlYRzVjYmlBZ0lDQnlaWFIxY200Z2NtVnpkV3gwTzF4dUlDQjlMRnh1WEc0Z0lHMWhjRjl5WldSMVkyVTZJR1oxYm1OMGFXOXVLR052Ykd4bFkzUnBiMjRzSUdGall5d2dablZ1S1h0Y2JpQWdJQ0JzWlhRZ2JXRndjR1ZrSUQwZ1QySnFaV04wTG1aeVpXVjZaU2hiWFNrN1hHNGdJQ0FnYkdWMElIUm9aVjloWTJNZ1BTQmhZMk03WEc1Y2JpQWdJQ0JtYjNJZ0tIWmhjaUJwSUQwZ01Ec2dhU0E4SUhSb2FYTXVZMjkxYm5Rb1kyOXNiR1ZqZEdsdmJpazdJR2tyS3lrZ2UxeHVJQ0FnSUNBZ2JHVjBJSFIxY0d4bElEMGdablZ1S0dOdmJHeGxZM1JwYjI1YmFWMHNJSFJvWlY5aFkyTXBPMXh1WEc0Z0lDQWdJQ0IwYUdWZllXTmpJRDBnZEhWd2JHVXVaMlYwS0RFcE8xeHVJQ0FnSUNBZ2JXRndjR1ZrSUQwZ1QySnFaV04wTG1aeVpXVjZaU2h0WVhCd1pXUXVZMjl1WTJGMEtGdDBkWEJzWlM1blpYUW9NQ2xkS1NrN1hHNGdJQ0FnZlZ4dVhHNGdJQ0FnY21WMGRYSnVJRzVsZHlCRGIzSmxMbFIxY0d4bEtHMWhjSEJsWkN3Z2RHaGxYMkZqWXlrN1hHNGdJSDBzWEc1Y2JpQWdiV1Z0WW1WeVgxOXhiV0Z5YTE5Zk9pQm1kVzVqZEdsdmJpaGpiMnhzWldOMGFXOXVMQ0IyWVd4MVpTbDdYRzRnSUNBZ2NtVjBkWEp1SUdOdmJHeGxZM1JwYjI0dWFXNWpiSFZrWlhNb2RtRnNkV1VwTzF4dUlDQjlMRnh1WEc0Z0lISmxaSFZqWlRvZ1puVnVZM1JwYjI0b1kyOXNiR1ZqZEdsdmJpd2dZV05qTENCbWRXNHBlMXh1SUNBZ0lHeGxkQ0IwYUdWZllXTmpJRDBnWVdOak8xeHVYRzRnSUNBZ1ptOXlJQ2gyWVhJZ2FTQTlJREE3SUdrZ1BDQjBhR2x6TG1OdmRXNTBLR052Ykd4bFkzUnBiMjRwT3lCcEt5c3BJSHRjYmlBZ0lDQWdJR3hsZENCMGRYQnNaU0E5SUdaMWJpaGpiMnhzWldOMGFXOXVXMmxkTENCMGFHVmZZV05qS1R0Y2JseHVJQ0FnSUNBZ2RHaGxYMkZqWXlBOUlIUjFjR3hsTG1kbGRDZ3hLVHRjYmlBZ0lDQjlYRzVjYmlBZ0lDQnlaWFIxY200Z2RHaGxYMkZqWXp0Y2JpQWdmU3hjYmx4dUlDQjBZV3RsT2lCbWRXNWpkR2x2YmloamIyeHNaV04wYVc5dUxDQmpiM1Z1ZENsN1hHNGdJQ0FnY21WMGRYSnVJR052Ykd4bFkzUnBiMjR1YzJ4cFkyVW9NQ3dnWTI5MWJuUXBPMXh1SUNCOUxGeHVYRzRnSUhSaGEyVmZaWFpsY25rNklHWjFibU4wYVc5dUtHTnZiR3hsWTNScGIyNHNJRzUwYUNsN1hHNGdJQ0FnYkdWMElISmxjM1ZzZENBOUlGdGRPMXh1SUNBZ0lHeGxkQ0JwYm1SbGVDQTlJREE3WEc1Y2JpQWdJQ0JtYjNJb2JHVjBJR1ZzWlcwZ2IyWWdZMjlzYkdWamRHbHZiaWw3WEc0Z0lDQWdJQ0JwWmlocGJtUmxlQ0FsSUc1MGFDQTlQVDBnTUNsN1hHNGdJQ0FnSUNBZ0lISmxjM1ZzZEM1d2RYTm9LR1ZzWlcwcE8xeHVJQ0FnSUNBZ2ZWeHVJQ0FnSUgxY2JseHVJQ0FnSUhKbGRIVnliaUJQWW1wbFkzUXVabkpsWlhwbEtISmxjM1ZzZENrN1hHNGdJSDBzWEc1Y2JpQWdkR0ZyWlY5M2FHbHNaVG9nWm5WdVkzUnBiMjRvWTI5c2JHVmpkR2x2Yml3Z1puVnVLWHRjYmlBZ0lDQnNaWFFnWTI5MWJuUWdQU0F3TzF4dVhHNGdJQ0FnWm05eUtHeGxkQ0JsYkdWdElHOW1JR052Ykd4bFkzUnBiMjRwZTF4dUlDQWdJQ0FnYVdZb1puVnVLR1ZzWlcwcEtYdGNiaUFnSUNBZ0lDQWdZMjkxYm5RZ1BTQmpiM1Z1ZENBcklERTdYRzRnSUNBZ0lDQjlaV3h6Wlh0Y2JpQWdJQ0FnSUNBZ1luSmxZV3M3WEc0Z0lDQWdJQ0I5WEc0Z0lDQWdmVnh1WEc0Z0lDQWdjbVYwZFhKdUlHTnZiR3hsWTNScGIyNHVjMnhwWTJVb01Dd2dZMjkxYm5RcE8xeHVJQ0I5TEZ4dVhHNGdJSFJ2WDJ4cGMzUTZJR1oxYm1OMGFXOXVLR052Ykd4bFkzUnBiMjRwZTF4dUlDQWdJSEpsZEhWeWJpQmpiMnhzWldOMGFXOXVPMXh1SUNCOVhHNTlPMXh1WEc1bGVIQnZjblFnWkdWbVlYVnNkQ0JGYm5WdE8xeHVJbDBzSW5OdmRYSmpaVkp2YjNRaU9pSXZjMjkxY21ObEx5SjlcbiIsImxldCBWaXJ0dWFsRE9NID0gZnVuY3Rpb24gKGUpIHtcbiAgICByZXR1cm4gZSgpO1xufShmdW5jdGlvbiAoKSB7XG4gICAgdmFyIGRlZmluZSwgbW9kdWxlLCBleHBvcnRzO1xuICAgIHJldHVybiBmdW5jdGlvbiBlKHQsIG4sIHIpIHtcbiAgICAgICAgZnVuY3Rpb24gcyhvLCB1KSB7XG4gICAgICAgICAgICBpZiAoIW5bb10pIHtcbiAgICAgICAgICAgICAgICBpZiAoIXRbb10pIHtcbiAgICAgICAgICAgICAgICAgICAgdmFyIGEgPSB0eXBlb2YgcmVxdWlyZSA9PSBcImZ1bmN0aW9uXCIgJiYgcmVxdWlyZTtcbiAgICAgICAgICAgICAgICAgICAgaWYgKCF1ICYmIGEpIHJldHVybiBhKG8sICEwKTtcbiAgICAgICAgICAgICAgICAgICAgaWYgKGkpIHJldHVybiBpKG8sICEwKTtcbiAgICAgICAgICAgICAgICAgICAgdmFyIGYgPSBuZXcgRXJyb3IoXCJDYW5ub3QgZmluZCBtb2R1bGUgJ1wiICsgbyArIFwiJ1wiKTtcbiAgICAgICAgICAgICAgICAgICAgdGhyb3cgZi5jb2RlID0gXCJNT0RVTEVfTk9UX0ZPVU5EXCIsIGY7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHZhciBsID0gbltvXSA9IHtcbiAgICAgICAgICAgICAgICAgICAgZXhwb3J0czoge31cbiAgICAgICAgICAgICAgICB9O1xuICAgICAgICAgICAgICAgIHRbb11bMF0uY2FsbChsLmV4cG9ydHMsIGZ1bmN0aW9uIChlKSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciBuID0gdFtvXVsxXVtlXTtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHMobiA/IG4gOiBlKTtcbiAgICAgICAgICAgICAgICB9LCBsLCBsLmV4cG9ydHMsIGUsIHQsIG4sIHIpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmV0dXJuIG5bb10uZXhwb3J0cztcbiAgICAgICAgfVxuICAgICAgICB2YXIgaSA9IHR5cGVvZiByZXF1aXJlID09IFwiZnVuY3Rpb25cIiAmJiByZXF1aXJlO1xuICAgICAgICBmb3IgKHZhciBvID0gMDsgbyA8IHIubGVuZ3RoOyBvKyspIHMocltvXSk7XG4gICAgICAgIHJldHVybiBzO1xuICAgIH0oe1xuICAgICAgICAxOiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge1xuXG4gICAgICAgICAgICB2YXIgY3JlYXRlRWxlbWVudCA9IHJlcXVpcmUoXCIuL3Zkb20vY3JlYXRlLWVsZW1lbnQuanNcIik7XG5cbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gY3JlYXRlRWxlbWVudDtcbiAgICAgICAgfSwgeyBcIi4vdmRvbS9jcmVhdGUtZWxlbWVudC5qc1wiOiAxNSB9XSwgMjogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHtcbiAgICAgICAgICAgIHZhciBkaWZmID0gcmVxdWlyZShcIi4vdnRyZWUvZGlmZi5qc1wiKTtcblxuICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBkaWZmO1xuICAgICAgICB9LCB7IFwiLi92dHJlZS9kaWZmLmpzXCI6IDM1IH1dLCAzOiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge1xuICAgICAgICAgICAgdmFyIGggPSByZXF1aXJlKFwiLi92aXJ0dWFsLWh5cGVyc2NyaXB0L2luZGV4LmpzXCIpO1xuXG4gICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IGg7XG4gICAgICAgIH0sIHsgXCIuL3ZpcnR1YWwtaHlwZXJzY3JpcHQvaW5kZXguanNcIjogMjIgfV0sIDQ6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICB2YXIgZGlmZiA9IHJlcXVpcmUoXCIuL2RpZmYuanNcIik7XG4gICAgICAgICAgICB2YXIgcGF0Y2ggPSByZXF1aXJlKFwiLi9wYXRjaC5qc1wiKTtcbiAgICAgICAgICAgIHZhciBoID0gcmVxdWlyZShcIi4vaC5qc1wiKTtcbiAgICAgICAgICAgIHZhciBjcmVhdGUgPSByZXF1aXJlKFwiLi9jcmVhdGUtZWxlbWVudC5qc1wiKTtcbiAgICAgICAgICAgIHZhciBWTm9kZSA9IHJlcXVpcmUoJy4vdm5vZGUvdm5vZGUuanMnKTtcbiAgICAgICAgICAgIHZhciBWVGV4dCA9IHJlcXVpcmUoJy4vdm5vZGUvdnRleHQuanMnKTtcblxuICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSB7XG4gICAgICAgICAgICAgICAgZGlmZjogZGlmZixcbiAgICAgICAgICAgICAgICBwYXRjaDogcGF0Y2gsXG4gICAgICAgICAgICAgICAgaDogaCxcbiAgICAgICAgICAgICAgICBjcmVhdGU6IGNyZWF0ZSxcbiAgICAgICAgICAgICAgICBWTm9kZTogVk5vZGUsXG4gICAgICAgICAgICAgICAgVlRleHQ6IFZUZXh0XG4gICAgICAgICAgICB9O1xuICAgICAgICB9LCB7IFwiLi9jcmVhdGUtZWxlbWVudC5qc1wiOiAxLCBcIi4vZGlmZi5qc1wiOiAyLCBcIi4vaC5qc1wiOiAzLCBcIi4vcGF0Y2guanNcIjogMTMsIFwiLi92bm9kZS92bm9kZS5qc1wiOiAzMSwgXCIuL3Zub2RlL3Z0ZXh0LmpzXCI6IDMzIH1dLCA1OiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge1xuICAgICAgICAgICAgLyohXG4gICAgICAgICAgICAgKiBDcm9zcy1Ccm93c2VyIFNwbGl0IDEuMS4xXG4gICAgICAgICAgICAgKiBDb3B5cmlnaHQgMjAwNy0yMDEyIFN0ZXZlbiBMZXZpdGhhbiA8c3RldmVubGV2aXRoYW4uY29tPlxuICAgICAgICAgICAgICogQXZhaWxhYmxlIHVuZGVyIHRoZSBNSVQgTGljZW5zZVxuICAgICAgICAgICAgICogRUNNQVNjcmlwdCBjb21wbGlhbnQsIHVuaWZvcm0gY3Jvc3MtYnJvd3NlciBzcGxpdCBtZXRob2RcbiAgICAgICAgICAgICAqL1xuXG4gICAgICAgICAgICAvKipcbiAgICAgICAgICAgICAqIFNwbGl0cyBhIHN0cmluZyBpbnRvIGFuIGFycmF5IG9mIHN0cmluZ3MgdXNpbmcgYSByZWdleCBvciBzdHJpbmcgc2VwYXJhdG9yLiBNYXRjaGVzIG9mIHRoZVxuICAgICAgICAgICAgICogc2VwYXJhdG9yIGFyZSBub3QgaW5jbHVkZWQgaW4gdGhlIHJlc3VsdCBhcnJheS4gSG93ZXZlciwgaWYgYHNlcGFyYXRvcmAgaXMgYSByZWdleCB0aGF0IGNvbnRhaW5zXG4gICAgICAgICAgICAgKiBjYXB0dXJpbmcgZ3JvdXBzLCBiYWNrcmVmZXJlbmNlcyBhcmUgc3BsaWNlZCBpbnRvIHRoZSByZXN1bHQgZWFjaCB0aW1lIGBzZXBhcmF0b3JgIGlzIG1hdGNoZWQuXG4gICAgICAgICAgICAgKiBGaXhlcyBicm93c2VyIGJ1Z3MgY29tcGFyZWQgdG8gdGhlIG5hdGl2ZSBgU3RyaW5nLnByb3RvdHlwZS5zcGxpdGAgYW5kIGNhbiBiZSB1c2VkIHJlbGlhYmx5XG4gICAgICAgICAgICAgKiBjcm9zcy1icm93c2VyLlxuICAgICAgICAgICAgICogQHBhcmFtIHtTdHJpbmd9IHN0ciBTdHJpbmcgdG8gc3BsaXQuXG4gICAgICAgICAgICAgKiBAcGFyYW0ge1JlZ0V4cHxTdHJpbmd9IHNlcGFyYXRvciBSZWdleCBvciBzdHJpbmcgdG8gdXNlIGZvciBzZXBhcmF0aW5nIHRoZSBzdHJpbmcuXG4gICAgICAgICAgICAgKiBAcGFyYW0ge051bWJlcn0gW2xpbWl0XSBNYXhpbXVtIG51bWJlciBvZiBpdGVtcyB0byBpbmNsdWRlIGluIHRoZSByZXN1bHQgYXJyYXkuXG4gICAgICAgICAgICAgKiBAcmV0dXJucyB7QXJyYXl9IEFycmF5IG9mIHN1YnN0cmluZ3MuXG4gICAgICAgICAgICAgKiBAZXhhbXBsZVxuICAgICAgICAgICAgICpcbiAgICAgICAgICAgICAqIC8vIEJhc2ljIHVzZVxuICAgICAgICAgICAgICogc3BsaXQoJ2EgYiBjIGQnLCAnICcpO1xuICAgICAgICAgICAgICogLy8gLT4gWydhJywgJ2InLCAnYycsICdkJ11cbiAgICAgICAgICAgICAqXG4gICAgICAgICAgICAgKiAvLyBXaXRoIGxpbWl0XG4gICAgICAgICAgICAgKiBzcGxpdCgnYSBiIGMgZCcsICcgJywgMik7XG4gICAgICAgICAgICAgKiAvLyAtPiBbJ2EnLCAnYiddXG4gICAgICAgICAgICAgKlxuICAgICAgICAgICAgICogLy8gQmFja3JlZmVyZW5jZXMgaW4gcmVzdWx0IGFycmF5XG4gICAgICAgICAgICAgKiBzcGxpdCgnLi53b3JkMSB3b3JkMi4uJywgLyhbYS16XSspKFxcZCspL2kpO1xuICAgICAgICAgICAgICogLy8gLT4gWycuLicsICd3b3JkJywgJzEnLCAnICcsICd3b3JkJywgJzInLCAnLi4nXVxuICAgICAgICAgICAgICovXG4gICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uIHNwbGl0KHVuZGVmKSB7XG5cbiAgICAgICAgICAgICAgICB2YXIgbmF0aXZlU3BsaXQgPSBTdHJpbmcucHJvdG90eXBlLnNwbGl0LFxuICAgICAgICAgICAgICAgICAgICBjb21wbGlhbnRFeGVjTnBjZyA9IC8oKT8/Ly5leGVjKFwiXCIpWzFdID09PSB1bmRlZixcblxuICAgICAgICAgICAgICAgIC8vIE5QQ0c6IG5vbnBhcnRpY2lwYXRpbmcgY2FwdHVyaW5nIGdyb3VwXG4gICAgICAgICAgICAgICAgc2VsZjtcblxuICAgICAgICAgICAgICAgIHNlbGYgPSBmdW5jdGlvbiAoc3RyLCBzZXBhcmF0b3IsIGxpbWl0KSB7XG4gICAgICAgICAgICAgICAgICAgIC8vIElmIGBzZXBhcmF0b3JgIGlzIG5vdCBhIHJlZ2V4LCB1c2UgYG5hdGl2ZVNwbGl0YFxuICAgICAgICAgICAgICAgICAgICBpZiAoT2JqZWN0LnByb3RvdHlwZS50b1N0cmluZy5jYWxsKHNlcGFyYXRvcikgIT09IFwiW29iamVjdCBSZWdFeHBdXCIpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBuYXRpdmVTcGxpdC5jYWxsKHN0ciwgc2VwYXJhdG9yLCBsaW1pdCk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgdmFyIG91dHB1dCA9IFtdLFxuICAgICAgICAgICAgICAgICAgICAgICAgZmxhZ3MgPSAoc2VwYXJhdG9yLmlnbm9yZUNhc2UgPyBcImlcIiA6IFwiXCIpICsgKHNlcGFyYXRvci5tdWx0aWxpbmUgPyBcIm1cIiA6IFwiXCIpICsgKHNlcGFyYXRvci5leHRlbmRlZCA/IFwieFwiIDogXCJcIikgKyAoIC8vIFByb3Bvc2VkIGZvciBFUzZcbiAgICAgICAgICAgICAgICAgICAgc2VwYXJhdG9yLnN0aWNreSA/IFwieVwiIDogXCJcIiksXG5cbiAgICAgICAgICAgICAgICAgICAgLy8gRmlyZWZveCAzK1xuICAgICAgICAgICAgICAgICAgICBsYXN0TGFzdEluZGV4ID0gMCxcblxuICAgICAgICAgICAgICAgICAgICAvLyBNYWtlIGBnbG9iYWxgIGFuZCBhdm9pZCBgbGFzdEluZGV4YCBpc3N1ZXMgYnkgd29ya2luZyB3aXRoIGEgY29weVxuICAgICAgICAgICAgICAgICAgICBzZXBhcmF0b3IgPSBuZXcgUmVnRXhwKHNlcGFyYXRvci5zb3VyY2UsIGZsYWdzICsgXCJnXCIpLFxuICAgICAgICAgICAgICAgICAgICAgICAgc2VwYXJhdG9yMixcbiAgICAgICAgICAgICAgICAgICAgICAgIG1hdGNoLFxuICAgICAgICAgICAgICAgICAgICAgICAgbGFzdEluZGV4LFxuICAgICAgICAgICAgICAgICAgICAgICAgbGFzdExlbmd0aDtcbiAgICAgICAgICAgICAgICAgICAgc3RyICs9IFwiXCI7IC8vIFR5cGUtY29udmVydFxuICAgICAgICAgICAgICAgICAgICBpZiAoIWNvbXBsaWFudEV4ZWNOcGNnKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAvLyBEb2Vzbid0IG5lZWQgZmxhZ3MgZ3ksIGJ1dCB0aGV5IGRvbid0IGh1cnRcbiAgICAgICAgICAgICAgICAgICAgICAgIHNlcGFyYXRvcjIgPSBuZXcgUmVnRXhwKFwiXlwiICsgc2VwYXJhdG9yLnNvdXJjZSArIFwiJCg/IVxcXFxzKVwiLCBmbGFncyk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgLyogVmFsdWVzIGZvciBgbGltaXRgLCBwZXIgdGhlIHNwZWM6XG4gICAgICAgICAgICAgICAgICAgICAqIElmIHVuZGVmaW5lZDogNDI5NDk2NzI5NSAvLyBNYXRoLnBvdygyLCAzMikgLSAxXG4gICAgICAgICAgICAgICAgICAgICAqIElmIDAsIEluZmluaXR5LCBvciBOYU46IDBcbiAgICAgICAgICAgICAgICAgICAgICogSWYgcG9zaXRpdmUgbnVtYmVyOiBsaW1pdCA9IE1hdGguZmxvb3IobGltaXQpOyBpZiAobGltaXQgPiA0Mjk0OTY3Mjk1KSBsaW1pdCAtPSA0Mjk0OTY3Mjk2O1xuICAgICAgICAgICAgICAgICAgICAgKiBJZiBuZWdhdGl2ZSBudW1iZXI6IDQyOTQ5NjcyOTYgLSBNYXRoLmZsb29yKE1hdGguYWJzKGxpbWl0KSlcbiAgICAgICAgICAgICAgICAgICAgICogSWYgb3RoZXI6IFR5cGUtY29udmVydCwgdGhlbiB1c2UgdGhlIGFib3ZlIHJ1bGVzXG4gICAgICAgICAgICAgICAgICAgICAqL1xuICAgICAgICAgICAgICAgICAgICBsaW1pdCA9IGxpbWl0ID09PSB1bmRlZiA/IC0xID4+PiAwIDogLy8gTWF0aC5wb3coMiwgMzIpIC0gMVxuICAgICAgICAgICAgICAgICAgICBsaW1pdCA+Pj4gMDsgLy8gVG9VaW50MzIobGltaXQpXG4gICAgICAgICAgICAgICAgICAgIHdoaWxlIChtYXRjaCA9IHNlcGFyYXRvci5leGVjKHN0cikpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIGBzZXBhcmF0b3IubGFzdEluZGV4YCBpcyBub3QgcmVsaWFibGUgY3Jvc3MtYnJvd3NlclxuICAgICAgICAgICAgICAgICAgICAgICAgbGFzdEluZGV4ID0gbWF0Y2guaW5kZXggKyBtYXRjaFswXS5sZW5ndGg7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAobGFzdEluZGV4ID4gbGFzdExhc3RJbmRleCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIG91dHB1dC5wdXNoKHN0ci5zbGljZShsYXN0TGFzdEluZGV4LCBtYXRjaC5pbmRleCkpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIEZpeCBicm93c2VycyB3aG9zZSBgZXhlY2AgbWV0aG9kcyBkb24ndCBjb25zaXN0ZW50bHkgcmV0dXJuIGB1bmRlZmluZWRgIGZvclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIG5vbnBhcnRpY2lwYXRpbmcgY2FwdHVyaW5nIGdyb3Vwc1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmICghY29tcGxpYW50RXhlY05wY2cgJiYgbWF0Y2gubGVuZ3RoID4gMSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBtYXRjaFswXS5yZXBsYWNlKHNlcGFyYXRvcjIsIGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZvciAodmFyIGkgPSAxOyBpIDwgYXJndW1lbnRzLmxlbmd0aCAtIDI7IGkrKykge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChhcmd1bWVudHNbaV0gPT09IHVuZGVmKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1hdGNoW2ldID0gdW5kZWY7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKG1hdGNoLmxlbmd0aCA+IDEgJiYgbWF0Y2guaW5kZXggPCBzdHIubGVuZ3RoKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIEFycmF5LnByb3RvdHlwZS5wdXNoLmFwcGx5KG91dHB1dCwgbWF0Y2guc2xpY2UoMSkpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBsYXN0TGVuZ3RoID0gbWF0Y2hbMF0ubGVuZ3RoO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxhc3RMYXN0SW5kZXggPSBsYXN0SW5kZXg7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKG91dHB1dC5sZW5ndGggPj0gbGltaXQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHNlcGFyYXRvci5sYXN0SW5kZXggPT09IG1hdGNoLmluZGV4KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgc2VwYXJhdG9yLmxhc3RJbmRleCsrOyAvLyBBdm9pZCBhbiBpbmZpbml0ZSBsb29wXG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgaWYgKGxhc3RMYXN0SW5kZXggPT09IHN0ci5sZW5ndGgpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChsYXN0TGVuZ3RoIHx8ICFzZXBhcmF0b3IudGVzdChcIlwiKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIG91dHB1dC5wdXNoKFwiXCIpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgb3V0cHV0LnB1c2goc3RyLnNsaWNlKGxhc3RMYXN0SW5kZXgpKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICByZXR1cm4gb3V0cHV0Lmxlbmd0aCA+IGxpbWl0ID8gb3V0cHV0LnNsaWNlKDAsIGxpbWl0KSA6IG91dHB1dDtcbiAgICAgICAgICAgICAgICB9O1xuXG4gICAgICAgICAgICAgICAgcmV0dXJuIHNlbGY7XG4gICAgICAgICAgICB9KCk7XG4gICAgICAgIH0sIHt9XSwgNjogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHt9LCB7fV0sIDc6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICAndXNlIHN0cmljdCc7XG5cbiAgICAgICAgICAgIHZhciBPbmVWZXJzaW9uQ29uc3RyYWludCA9IHJlcXVpcmUoJ2luZGl2aWR1YWwvb25lLXZlcnNpb24nKTtcblxuICAgICAgICAgICAgdmFyIE1ZX1ZFUlNJT04gPSAnNyc7XG4gICAgICAgICAgICBPbmVWZXJzaW9uQ29uc3RyYWludCgnZXYtc3RvcmUnLCBNWV9WRVJTSU9OKTtcblxuICAgICAgICAgICAgdmFyIGhhc2hLZXkgPSAnX19FVl9TVE9SRV9LRVlAJyArIE1ZX1ZFUlNJT047XG5cbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gRXZTdG9yZTtcblxuICAgICAgICAgICAgZnVuY3Rpb24gRXZTdG9yZShlbGVtKSB7XG4gICAgICAgICAgICAgICAgdmFyIGhhc2ggPSBlbGVtW2hhc2hLZXldO1xuXG4gICAgICAgICAgICAgICAgaWYgKCFoYXNoKSB7XG4gICAgICAgICAgICAgICAgICAgIGhhc2ggPSBlbGVtW2hhc2hLZXldID0ge307XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgcmV0dXJuIGhhc2g7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0sIHsgXCJpbmRpdmlkdWFsL29uZS12ZXJzaW9uXCI6IDkgfV0sIDg6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICAoZnVuY3Rpb24gKGdsb2JhbCkge1xuICAgICAgICAgICAgICAgICd1c2Ugc3RyaWN0JztcblxuICAgICAgICAgICAgICAgIC8qZ2xvYmFsIHdpbmRvdywgZ2xvYmFsKi9cblxuICAgICAgICAgICAgICAgIHZhciByb290ID0gdHlwZW9mIHdpbmRvdyAhPT0gJ3VuZGVmaW5lZCcgPyB3aW5kb3cgOiB0eXBlb2YgZ2xvYmFsICE9PSAndW5kZWZpbmVkJyA/IGdsb2JhbCA6IHt9O1xuXG4gICAgICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBJbmRpdmlkdWFsO1xuXG4gICAgICAgICAgICAgICAgZnVuY3Rpb24gSW5kaXZpZHVhbChrZXksIHZhbHVlKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmIChrZXkgaW4gcm9vdCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHJvb3Rba2V5XTtcbiAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgIHJvb3Rba2V5XSA9IHZhbHVlO1xuXG4gICAgICAgICAgICAgICAgICAgIHJldHVybiB2YWx1ZTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9KS5jYWxsKHRoaXMsIHR5cGVvZiBnbG9iYWwgIT09IFwidW5kZWZpbmVkXCIgPyBnbG9iYWwgOiB0eXBlb2Ygc2VsZiAhPT0gXCJ1bmRlZmluZWRcIiA/IHNlbGYgOiB0eXBlb2Ygd2luZG93ICE9PSBcInVuZGVmaW5lZFwiID8gd2luZG93IDoge30pO1xuICAgICAgICB9LCB7fV0sIDk6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICAndXNlIHN0cmljdCc7XG5cbiAgICAgICAgICAgIHZhciBJbmRpdmlkdWFsID0gcmVxdWlyZSgnLi9pbmRleC5qcycpO1xuXG4gICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IE9uZVZlcnNpb247XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIE9uZVZlcnNpb24obW9kdWxlTmFtZSwgdmVyc2lvbiwgZGVmYXVsdFZhbHVlKSB7XG4gICAgICAgICAgICAgICAgdmFyIGtleSA9ICdfX0lORElWSURVQUxfT05FX1ZFUlNJT05fJyArIG1vZHVsZU5hbWU7XG4gICAgICAgICAgICAgICAgdmFyIGVuZm9yY2VLZXkgPSBrZXkgKyAnX0VORk9SQ0VfU0lOR0xFVE9OJztcblxuICAgICAgICAgICAgICAgIHZhciB2ZXJzaW9uVmFsdWUgPSBJbmRpdmlkdWFsKGVuZm9yY2VLZXksIHZlcnNpb24pO1xuXG4gICAgICAgICAgICAgICAgaWYgKHZlcnNpb25WYWx1ZSAhPT0gdmVyc2lvbikge1xuICAgICAgICAgICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ0NhbiBvbmx5IGhhdmUgb25lIGNvcHkgb2YgJyArIG1vZHVsZU5hbWUgKyAnLlxcbicgKyAnWW91IGFscmVhZHkgaGF2ZSB2ZXJzaW9uICcgKyB2ZXJzaW9uVmFsdWUgKyAnIGluc3RhbGxlZC5cXG4nICsgJ1RoaXMgbWVhbnMgeW91IGNhbm5vdCBpbnN0YWxsIHZlcnNpb24gJyArIHZlcnNpb24pO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHJldHVybiBJbmRpdmlkdWFsKGtleSwgZGVmYXVsdFZhbHVlKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSwgeyBcIi4vaW5kZXguanNcIjogOCB9XSwgMTA6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICAoZnVuY3Rpb24gKGdsb2JhbCkge1xuICAgICAgICAgICAgICAgIHZhciB0b3BMZXZlbCA9IHR5cGVvZiBnbG9iYWwgIT09ICd1bmRlZmluZWQnID8gZ2xvYmFsIDogdHlwZW9mIHdpbmRvdyAhPT0gJ3VuZGVmaW5lZCcgPyB3aW5kb3cgOiB7fTtcbiAgICAgICAgICAgICAgICB2YXIgbWluRG9jID0gcmVxdWlyZSgnbWluLWRvY3VtZW50Jyk7XG5cbiAgICAgICAgICAgICAgICBpZiAodHlwZW9mIGRvY3VtZW50ICE9PSAndW5kZWZpbmVkJykge1xuICAgICAgICAgICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IGRvY3VtZW50O1xuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciBkb2NjeSA9IHRvcExldmVsWydfX0dMT0JBTF9ET0NVTUVOVF9DQUNIRUA0J107XG5cbiAgICAgICAgICAgICAgICAgICAgaWYgKCFkb2NjeSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgZG9jY3kgPSB0b3BMZXZlbFsnX19HTE9CQUxfRE9DVU1FTlRfQ0FDSEVANCddID0gbWluRG9jO1xuICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBkb2NjeTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9KS5jYWxsKHRoaXMsIHR5cGVvZiBnbG9iYWwgIT09IFwidW5kZWZpbmVkXCIgPyBnbG9iYWwgOiB0eXBlb2Ygc2VsZiAhPT0gXCJ1bmRlZmluZWRcIiA/IHNlbGYgOiB0eXBlb2Ygd2luZG93ICE9PSBcInVuZGVmaW5lZFwiID8gd2luZG93IDoge30pO1xuICAgICAgICB9LCB7IFwibWluLWRvY3VtZW50XCI6IDYgfV0sIDExOiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge1xuICAgICAgICAgICAgXCJ1c2Ugc3RyaWN0XCI7XG5cbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gaXNPYmplY3QoeCkge1xuICAgICAgICAgICAgICAgIHJldHVybiB0eXBlb2YgeCA9PT0gXCJvYmplY3RcIiAmJiB4ICE9PSBudWxsO1xuICAgICAgICAgICAgfTtcbiAgICAgICAgfSwge31dLCAxMjogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHtcbiAgICAgICAgICAgIHZhciBuYXRpdmVJc0FycmF5ID0gQXJyYXkuaXNBcnJheTtcbiAgICAgICAgICAgIHZhciB0b1N0cmluZyA9IE9iamVjdC5wcm90b3R5cGUudG9TdHJpbmc7XG5cbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gbmF0aXZlSXNBcnJheSB8fCBpc0FycmF5O1xuXG4gICAgICAgICAgICBmdW5jdGlvbiBpc0FycmF5KG9iaikge1xuICAgICAgICAgICAgICAgIHJldHVybiB0b1N0cmluZy5jYWxsKG9iaikgPT09IFwiW29iamVjdCBBcnJheV1cIjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSwge31dLCAxMzogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHtcbiAgICAgICAgICAgIHZhciBwYXRjaCA9IHJlcXVpcmUoXCIuL3Zkb20vcGF0Y2guanNcIik7XG5cbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gcGF0Y2g7XG4gICAgICAgIH0sIHsgXCIuL3Zkb20vcGF0Y2guanNcIjogMTggfV0sIDE0OiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge1xuICAgICAgICAgICAgdmFyIGlzT2JqZWN0ID0gcmVxdWlyZShcImlzLW9iamVjdFwiKTtcbiAgICAgICAgICAgIHZhciBpc0hvb2sgPSByZXF1aXJlKFwiLi4vdm5vZGUvaXMtdmhvb2suanNcIik7XG5cbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gYXBwbHlQcm9wZXJ0aWVzO1xuXG4gICAgICAgICAgICBmdW5jdGlvbiBhcHBseVByb3BlcnRpZXMobm9kZSwgcHJvcHMsIHByZXZpb3VzKSB7XG4gICAgICAgICAgICAgICAgZm9yICh2YXIgcHJvcE5hbWUgaW4gcHJvcHMpIHtcbiAgICAgICAgICAgICAgICAgICAgdmFyIHByb3BWYWx1ZSA9IHByb3BzW3Byb3BOYW1lXTtcblxuICAgICAgICAgICAgICAgICAgICBpZiAocHJvcFZhbHVlID09PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJlbW92ZVByb3BlcnR5KG5vZGUsIHByb3BOYW1lLCBwcm9wVmFsdWUsIHByZXZpb3VzKTtcbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIGlmIChpc0hvb2socHJvcFZhbHVlKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgcmVtb3ZlUHJvcGVydHkobm9kZSwgcHJvcE5hbWUsIHByb3BWYWx1ZSwgcHJldmlvdXMpO1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHByb3BWYWx1ZS5ob29rKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcHJvcFZhbHVlLmhvb2sobm9kZSwgcHJvcE5hbWUsIHByZXZpb3VzID8gcHJldmlvdXNbcHJvcE5hbWVdIDogdW5kZWZpbmVkKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChpc09iamVjdChwcm9wVmFsdWUpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcGF0Y2hPYmplY3Qobm9kZSwgcHJvcHMsIHByZXZpb3VzLCBwcm9wTmFtZSwgcHJvcFZhbHVlKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgbm9kZVtwcm9wTmFtZV0gPSBwcm9wVmFsdWU7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIHJlbW92ZVByb3BlcnR5KG5vZGUsIHByb3BOYW1lLCBwcm9wVmFsdWUsIHByZXZpb3VzKSB7XG4gICAgICAgICAgICAgICAgaWYgKHByZXZpb3VzKSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciBwcmV2aW91c1ZhbHVlID0gcHJldmlvdXNbcHJvcE5hbWVdO1xuXG4gICAgICAgICAgICAgICAgICAgIGlmICghaXNIb29rKHByZXZpb3VzVmFsdWUpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAocHJvcE5hbWUgPT09IFwiYXR0cmlidXRlc1wiKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgZm9yICh2YXIgYXR0ck5hbWUgaW4gcHJldmlvdXNWYWx1ZSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBub2RlLnJlbW92ZUF0dHJpYnV0ZShhdHRyTmFtZSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIGlmIChwcm9wTmFtZSA9PT0gXCJzdHlsZVwiKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgZm9yICh2YXIgaSBpbiBwcmV2aW91c1ZhbHVlKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG5vZGUuc3R5bGVbaV0gPSBcIlwiO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAodHlwZW9mIHByZXZpb3VzVmFsdWUgPT09IFwic3RyaW5nXCIpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBub2RlW3Byb3BOYW1lXSA9IFwiXCI7XG4gICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIG5vZGVbcHJvcE5hbWVdID0gbnVsbDtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIGlmIChwcmV2aW91c1ZhbHVlLnVuaG9vaykge1xuICAgICAgICAgICAgICAgICAgICAgICAgcHJldmlvdXNWYWx1ZS51bmhvb2sobm9kZSwgcHJvcE5hbWUsIHByb3BWYWx1ZSk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIHBhdGNoT2JqZWN0KG5vZGUsIHByb3BzLCBwcmV2aW91cywgcHJvcE5hbWUsIHByb3BWYWx1ZSkge1xuICAgICAgICAgICAgICAgIHZhciBwcmV2aW91c1ZhbHVlID0gcHJldmlvdXMgPyBwcmV2aW91c1twcm9wTmFtZV0gOiB1bmRlZmluZWQ7XG5cbiAgICAgICAgICAgICAgICAvLyBTZXQgYXR0cmlidXRlc1xuICAgICAgICAgICAgICAgIGlmIChwcm9wTmFtZSA9PT0gXCJhdHRyaWJ1dGVzXCIpIHtcbiAgICAgICAgICAgICAgICAgICAgZm9yICh2YXIgYXR0ck5hbWUgaW4gcHJvcFZhbHVlKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICB2YXIgYXR0clZhbHVlID0gcHJvcFZhbHVlW2F0dHJOYW1lXTtcblxuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGF0dHJWYWx1ZSA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgbm9kZS5yZW1vdmVBdHRyaWJ1dGUoYXR0ck5hbWUpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBub2RlLnNldEF0dHJpYnV0ZShhdHRyTmFtZSwgYXR0clZhbHVlKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICBpZiAocHJldmlvdXNWYWx1ZSAmJiBpc09iamVjdChwcmV2aW91c1ZhbHVlKSAmJiBnZXRQcm90b3R5cGUocHJldmlvdXNWYWx1ZSkgIT09IGdldFByb3RvdHlwZShwcm9wVmFsdWUpKSB7XG4gICAgICAgICAgICAgICAgICAgIG5vZGVbcHJvcE5hbWVdID0gcHJvcFZhbHVlO1xuICAgICAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgaWYgKCFpc09iamVjdChub2RlW3Byb3BOYW1lXSkpIHtcbiAgICAgICAgICAgICAgICAgICAgbm9kZVtwcm9wTmFtZV0gPSB7fTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICB2YXIgcmVwbGFjZXIgPSBwcm9wTmFtZSA9PT0gXCJzdHlsZVwiID8gXCJcIiA6IHVuZGVmaW5lZDtcblxuICAgICAgICAgICAgICAgIGZvciAodmFyIGsgaW4gcHJvcFZhbHVlKSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciB2YWx1ZSA9IHByb3BWYWx1ZVtrXTtcbiAgICAgICAgICAgICAgICAgICAgbm9kZVtwcm9wTmFtZV1ba10gPSB2YWx1ZSA9PT0gdW5kZWZpbmVkID8gcmVwbGFjZXIgOiB2YWx1ZTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIGdldFByb3RvdHlwZSh2YWx1ZSkge1xuICAgICAgICAgICAgICAgIGlmIChPYmplY3QuZ2V0UHJvdG90eXBlT2YpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIE9iamVjdC5nZXRQcm90b3R5cGVPZih2YWx1ZSk7XG4gICAgICAgICAgICAgICAgfSBlbHNlIGlmICh2YWx1ZS5fX3Byb3RvX18pIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHZhbHVlLl9fcHJvdG9fXztcbiAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKHZhbHVlLmNvbnN0cnVjdG9yKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiB2YWx1ZS5jb25zdHJ1Y3Rvci5wcm90b3R5cGU7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9LCB7IFwiLi4vdm5vZGUvaXMtdmhvb2suanNcIjogMjYsIFwiaXMtb2JqZWN0XCI6IDExIH1dLCAxNTogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHtcbiAgICAgICAgICAgIHZhciBkb2N1bWVudCA9IHJlcXVpcmUoXCJnbG9iYWwvZG9jdW1lbnRcIik7XG5cbiAgICAgICAgICAgIHZhciBhcHBseVByb3BlcnRpZXMgPSByZXF1aXJlKFwiLi9hcHBseS1wcm9wZXJ0aWVzXCIpO1xuXG4gICAgICAgICAgICB2YXIgaXNWTm9kZSA9IHJlcXVpcmUoXCIuLi92bm9kZS9pcy12bm9kZS5qc1wiKTtcbiAgICAgICAgICAgIHZhciBpc1ZUZXh0ID0gcmVxdWlyZShcIi4uL3Zub2RlL2lzLXZ0ZXh0LmpzXCIpO1xuICAgICAgICAgICAgdmFyIGlzV2lkZ2V0ID0gcmVxdWlyZShcIi4uL3Zub2RlL2lzLXdpZGdldC5qc1wiKTtcbiAgICAgICAgICAgIHZhciBoYW5kbGVUaHVuayA9IHJlcXVpcmUoXCIuLi92bm9kZS9oYW5kbGUtdGh1bmsuanNcIik7XG5cbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gY3JlYXRlRWxlbWVudDtcblxuICAgICAgICAgICAgZnVuY3Rpb24gY3JlYXRlRWxlbWVudCh2bm9kZSwgb3B0cykge1xuICAgICAgICAgICAgICAgIHZhciBkb2MgPSBvcHRzID8gb3B0cy5kb2N1bWVudCB8fCBkb2N1bWVudCA6IGRvY3VtZW50O1xuICAgICAgICAgICAgICAgIHZhciB3YXJuID0gb3B0cyA/IG9wdHMud2FybiA6IG51bGw7XG5cbiAgICAgICAgICAgICAgICB2bm9kZSA9IGhhbmRsZVRodW5rKHZub2RlKS5hO1xuXG4gICAgICAgICAgICAgICAgaWYgKGlzV2lkZ2V0KHZub2RlKSkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gdm5vZGUuaW5pdCgpO1xuICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoaXNWVGV4dCh2bm9kZSkpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGRvYy5jcmVhdGVUZXh0Tm9kZSh2bm9kZS50ZXh0KTtcbiAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKCFpc1ZOb2RlKHZub2RlKSkge1xuICAgICAgICAgICAgICAgICAgICBpZiAod2Fybikge1xuICAgICAgICAgICAgICAgICAgICAgICAgd2FybihcIkl0ZW0gaXMgbm90IGEgdmFsaWQgdmlydHVhbCBkb20gbm9kZVwiLCB2bm9kZSk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIG51bGw7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgdmFyIG5vZGUgPSB2bm9kZS5uYW1lc3BhY2UgPT09IG51bGwgPyBkb2MuY3JlYXRlRWxlbWVudCh2bm9kZS50YWdOYW1lKSA6IGRvYy5jcmVhdGVFbGVtZW50TlModm5vZGUubmFtZXNwYWNlLCB2bm9kZS50YWdOYW1lKTtcblxuICAgICAgICAgICAgICAgIHZhciBwcm9wcyA9IHZub2RlLnByb3BlcnRpZXM7XG4gICAgICAgICAgICAgICAgYXBwbHlQcm9wZXJ0aWVzKG5vZGUsIHByb3BzKTtcblxuICAgICAgICAgICAgICAgIHZhciBjaGlsZHJlbiA9IHZub2RlLmNoaWxkcmVuO1xuXG4gICAgICAgICAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCBjaGlsZHJlbi5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgICAgICAgICB2YXIgY2hpbGROb2RlID0gY3JlYXRlRWxlbWVudChjaGlsZHJlbltpXSwgb3B0cyk7XG4gICAgICAgICAgICAgICAgICAgIGlmIChjaGlsZE5vZGUpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIG5vZGUuYXBwZW5kQ2hpbGQoY2hpbGROb2RlKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHJldHVybiBub2RlO1xuICAgICAgICAgICAgfVxuICAgICAgICB9LCB7IFwiLi4vdm5vZGUvaGFuZGxlLXRodW5rLmpzXCI6IDI0LCBcIi4uL3Zub2RlL2lzLXZub2RlLmpzXCI6IDI3LCBcIi4uL3Zub2RlL2lzLXZ0ZXh0LmpzXCI6IDI4LCBcIi4uL3Zub2RlL2lzLXdpZGdldC5qc1wiOiAyOSwgXCIuL2FwcGx5LXByb3BlcnRpZXNcIjogMTQsIFwiZ2xvYmFsL2RvY3VtZW50XCI6IDEwIH1dLCAxNjogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHtcbiAgICAgICAgICAgIC8vIE1hcHMgYSB2aXJ0dWFsIERPTSB0cmVlIG9udG8gYSByZWFsIERPTSB0cmVlIGluIGFuIGVmZmljaWVudCBtYW5uZXIuXG4gICAgICAgICAgICAvLyBXZSBkb24ndCB3YW50IHRvIHJlYWQgYWxsIG9mIHRoZSBET00gbm9kZXMgaW4gdGhlIHRyZWUgc28gd2UgdXNlXG4gICAgICAgICAgICAvLyB0aGUgaW4tb3JkZXIgdHJlZSBpbmRleGluZyB0byBlbGltaW5hdGUgcmVjdXJzaW9uIGRvd24gY2VydGFpbiBicmFuY2hlcy5cbiAgICAgICAgICAgIC8vIFdlIG9ubHkgcmVjdXJzZSBpbnRvIGEgRE9NIG5vZGUgaWYgd2Uga25vdyB0aGF0IGl0IGNvbnRhaW5zIGEgY2hpbGQgb2ZcbiAgICAgICAgICAgIC8vIGludGVyZXN0LlxuXG4gICAgICAgICAgICB2YXIgbm9DaGlsZCA9IHt9O1xuXG4gICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IGRvbUluZGV4O1xuXG4gICAgICAgICAgICBmdW5jdGlvbiBkb21JbmRleChyb290Tm9kZSwgdHJlZSwgaW5kaWNlcywgbm9kZXMpIHtcbiAgICAgICAgICAgICAgICBpZiAoIWluZGljZXMgfHwgaW5kaWNlcy5sZW5ndGggPT09IDApIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHt9O1xuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIGluZGljZXMuc29ydChhc2NlbmRpbmcpO1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gcmVjdXJzZShyb290Tm9kZSwgdHJlZSwgaW5kaWNlcywgbm9kZXMsIDApO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZnVuY3Rpb24gcmVjdXJzZShyb290Tm9kZSwgdHJlZSwgaW5kaWNlcywgbm9kZXMsIHJvb3RJbmRleCkge1xuICAgICAgICAgICAgICAgIG5vZGVzID0gbm9kZXMgfHwge307XG5cbiAgICAgICAgICAgICAgICBpZiAocm9vdE5vZGUpIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKGluZGV4SW5SYW5nZShpbmRpY2VzLCByb290SW5kZXgsIHJvb3RJbmRleCkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIG5vZGVzW3Jvb3RJbmRleF0gPSByb290Tm9kZTtcbiAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgIHZhciB2Q2hpbGRyZW4gPSB0cmVlLmNoaWxkcmVuO1xuXG4gICAgICAgICAgICAgICAgICAgIGlmICh2Q2hpbGRyZW4pIHtcblxuICAgICAgICAgICAgICAgICAgICAgICAgdmFyIGNoaWxkTm9kZXMgPSByb290Tm9kZS5jaGlsZE5vZGVzO1xuXG4gICAgICAgICAgICAgICAgICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IHRyZWUuY2hpbGRyZW4ubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICByb290SW5kZXggKz0gMTtcblxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZhciB2Q2hpbGQgPSB2Q2hpbGRyZW5baV0gfHwgbm9DaGlsZDtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB2YXIgbmV4dEluZGV4ID0gcm9vdEluZGV4ICsgKHZDaGlsZC5jb3VudCB8fCAwKTtcblxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIHNraXAgcmVjdXJzaW9uIGRvd24gdGhlIHRyZWUgaWYgdGhlcmUgYXJlIG5vIG5vZGVzIGRvd24gaGVyZVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChpbmRleEluUmFuZ2UoaW5kaWNlcywgcm9vdEluZGV4LCBuZXh0SW5kZXgpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlY3Vyc2UoY2hpbGROb2Rlc1tpXSwgdkNoaWxkLCBpbmRpY2VzLCBub2Rlcywgcm9vdEluZGV4KTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICByb290SW5kZXggPSBuZXh0SW5kZXg7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICByZXR1cm4gbm9kZXM7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIC8vIEJpbmFyeSBzZWFyY2ggZm9yIGFuIGluZGV4IGluIHRoZSBpbnRlcnZhbCBbbGVmdCwgcmlnaHRdXG4gICAgICAgICAgICBmdW5jdGlvbiBpbmRleEluUmFuZ2UoaW5kaWNlcywgbGVmdCwgcmlnaHQpIHtcbiAgICAgICAgICAgICAgICBpZiAoaW5kaWNlcy5sZW5ndGggPT09IDApIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHZhciBtaW5JbmRleCA9IDA7XG4gICAgICAgICAgICAgICAgdmFyIG1heEluZGV4ID0gaW5kaWNlcy5sZW5ndGggLSAxO1xuICAgICAgICAgICAgICAgIHZhciBjdXJyZW50SW5kZXg7XG4gICAgICAgICAgICAgICAgdmFyIGN1cnJlbnRJdGVtO1xuXG4gICAgICAgICAgICAgICAgd2hpbGUgKG1pbkluZGV4IDw9IG1heEluZGV4KSB7XG4gICAgICAgICAgICAgICAgICAgIGN1cnJlbnRJbmRleCA9IChtYXhJbmRleCArIG1pbkluZGV4KSAvIDIgPj4gMDtcbiAgICAgICAgICAgICAgICAgICAgY3VycmVudEl0ZW0gPSBpbmRpY2VzW2N1cnJlbnRJbmRleF07XG5cbiAgICAgICAgICAgICAgICAgICAgaWYgKG1pbkluZGV4ID09PSBtYXhJbmRleCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGN1cnJlbnRJdGVtID49IGxlZnQgJiYgY3VycmVudEl0ZW0gPD0gcmlnaHQ7XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoY3VycmVudEl0ZW0gPCBsZWZ0KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBtaW5JbmRleCA9IGN1cnJlbnRJbmRleCArIDE7XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoY3VycmVudEl0ZW0gPiByaWdodCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgbWF4SW5kZXggPSBjdXJyZW50SW5kZXggLSAxO1xuICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIGFzY2VuZGluZyhhLCBiKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGEgPiBiID8gMSA6IC0xO1xuICAgICAgICAgICAgfVxuICAgICAgICB9LCB7fV0sIDE3OiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge1xuICAgICAgICAgICAgdmFyIGFwcGx5UHJvcGVydGllcyA9IHJlcXVpcmUoXCIuL2FwcGx5LXByb3BlcnRpZXNcIik7XG5cbiAgICAgICAgICAgIHZhciBpc1dpZGdldCA9IHJlcXVpcmUoXCIuLi92bm9kZS9pcy13aWRnZXQuanNcIik7XG4gICAgICAgICAgICB2YXIgVlBhdGNoID0gcmVxdWlyZShcIi4uL3Zub2RlL3ZwYXRjaC5qc1wiKTtcblxuICAgICAgICAgICAgdmFyIHVwZGF0ZVdpZGdldCA9IHJlcXVpcmUoXCIuL3VwZGF0ZS13aWRnZXRcIik7XG5cbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gYXBwbHlQYXRjaDtcblxuICAgICAgICAgICAgZnVuY3Rpb24gYXBwbHlQYXRjaCh2cGF0Y2gsIGRvbU5vZGUsIHJlbmRlck9wdGlvbnMpIHtcbiAgICAgICAgICAgICAgICB2YXIgdHlwZSA9IHZwYXRjaC50eXBlO1xuICAgICAgICAgICAgICAgIHZhciB2Tm9kZSA9IHZwYXRjaC52Tm9kZTtcbiAgICAgICAgICAgICAgICB2YXIgcGF0Y2ggPSB2cGF0Y2gucGF0Y2g7XG5cbiAgICAgICAgICAgICAgICBzd2l0Y2ggKHR5cGUpIHtcbiAgICAgICAgICAgICAgICAgICAgY2FzZSBWUGF0Y2guUkVNT1ZFOlxuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHJlbW92ZU5vZGUoZG9tTm9kZSwgdk5vZGUpO1xuICAgICAgICAgICAgICAgICAgICBjYXNlIFZQYXRjaC5JTlNFUlQ6XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gaW5zZXJ0Tm9kZShkb21Ob2RlLCBwYXRjaCwgcmVuZGVyT3B0aW9ucyk7XG4gICAgICAgICAgICAgICAgICAgIGNhc2UgVlBhdGNoLlZURVhUOlxuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHN0cmluZ1BhdGNoKGRvbU5vZGUsIHZOb2RlLCBwYXRjaCwgcmVuZGVyT3B0aW9ucyk7XG4gICAgICAgICAgICAgICAgICAgIGNhc2UgVlBhdGNoLldJREdFVDpcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiB3aWRnZXRQYXRjaChkb21Ob2RlLCB2Tm9kZSwgcGF0Y2gsIHJlbmRlck9wdGlvbnMpO1xuICAgICAgICAgICAgICAgICAgICBjYXNlIFZQYXRjaC5WTk9ERTpcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiB2Tm9kZVBhdGNoKGRvbU5vZGUsIHZOb2RlLCBwYXRjaCwgcmVuZGVyT3B0aW9ucyk7XG4gICAgICAgICAgICAgICAgICAgIGNhc2UgVlBhdGNoLk9SREVSOlxuICAgICAgICAgICAgICAgICAgICAgICAgcmVvcmRlckNoaWxkcmVuKGRvbU5vZGUsIHBhdGNoKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBkb21Ob2RlO1xuICAgICAgICAgICAgICAgICAgICBjYXNlIFZQYXRjaC5QUk9QUzpcbiAgICAgICAgICAgICAgICAgICAgICAgIGFwcGx5UHJvcGVydGllcyhkb21Ob2RlLCBwYXRjaCwgdk5vZGUucHJvcGVydGllcyk7XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gZG9tTm9kZTtcbiAgICAgICAgICAgICAgICAgICAgY2FzZSBWUGF0Y2guVEhVTks6XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gcmVwbGFjZVJvb3QoZG9tTm9kZSwgcmVuZGVyT3B0aW9ucy5wYXRjaChkb21Ob2RlLCBwYXRjaCwgcmVuZGVyT3B0aW9ucykpO1xuICAgICAgICAgICAgICAgICAgICBkZWZhdWx0OlxuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGRvbU5vZGU7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBmdW5jdGlvbiByZW1vdmVOb2RlKGRvbU5vZGUsIHZOb2RlKSB7XG4gICAgICAgICAgICAgICAgdmFyIHBhcmVudE5vZGUgPSBkb21Ob2RlLnBhcmVudE5vZGU7XG5cbiAgICAgICAgICAgICAgICBpZiAocGFyZW50Tm9kZSkge1xuICAgICAgICAgICAgICAgICAgICBwYXJlbnROb2RlLnJlbW92ZUNoaWxkKGRvbU5vZGUpO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIGRlc3Ryb3lXaWRnZXQoZG9tTm9kZSwgdk5vZGUpO1xuXG4gICAgICAgICAgICAgICAgcmV0dXJuIG51bGw7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIGluc2VydE5vZGUocGFyZW50Tm9kZSwgdk5vZGUsIHJlbmRlck9wdGlvbnMpIHtcbiAgICAgICAgICAgICAgICB2YXIgbmV3Tm9kZSA9IHJlbmRlck9wdGlvbnMucmVuZGVyKHZOb2RlLCByZW5kZXJPcHRpb25zKTtcblxuICAgICAgICAgICAgICAgIGlmIChwYXJlbnROb2RlKSB7XG4gICAgICAgICAgICAgICAgICAgIHBhcmVudE5vZGUuYXBwZW5kQ2hpbGQobmV3Tm9kZSk7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgcmV0dXJuIHBhcmVudE5vZGU7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIHN0cmluZ1BhdGNoKGRvbU5vZGUsIGxlZnRWTm9kZSwgdlRleHQsIHJlbmRlck9wdGlvbnMpIHtcbiAgICAgICAgICAgICAgICB2YXIgbmV3Tm9kZTtcblxuICAgICAgICAgICAgICAgIGlmIChkb21Ob2RlLm5vZGVUeXBlID09PSAzKSB7XG4gICAgICAgICAgICAgICAgICAgIGRvbU5vZGUucmVwbGFjZURhdGEoMCwgZG9tTm9kZS5sZW5ndGgsIHZUZXh0LnRleHQpO1xuICAgICAgICAgICAgICAgICAgICBuZXdOb2RlID0gZG9tTm9kZTtcbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICB2YXIgcGFyZW50Tm9kZSA9IGRvbU5vZGUucGFyZW50Tm9kZTtcbiAgICAgICAgICAgICAgICAgICAgbmV3Tm9kZSA9IHJlbmRlck9wdGlvbnMucmVuZGVyKHZUZXh0LCByZW5kZXJPcHRpb25zKTtcblxuICAgICAgICAgICAgICAgICAgICBpZiAocGFyZW50Tm9kZSAmJiBuZXdOb2RlICE9PSBkb21Ob2RlKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBwYXJlbnROb2RlLnJlcGxhY2VDaGlsZChuZXdOb2RlLCBkb21Ob2RlKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHJldHVybiBuZXdOb2RlO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBmdW5jdGlvbiB3aWRnZXRQYXRjaChkb21Ob2RlLCBsZWZ0Vk5vZGUsIHdpZGdldCwgcmVuZGVyT3B0aW9ucykge1xuICAgICAgICAgICAgICAgIHZhciB1cGRhdGluZyA9IHVwZGF0ZVdpZGdldChsZWZ0Vk5vZGUsIHdpZGdldCk7XG4gICAgICAgICAgICAgICAgdmFyIG5ld05vZGU7XG5cbiAgICAgICAgICAgICAgICBpZiAodXBkYXRpbmcpIHtcbiAgICAgICAgICAgICAgICAgICAgbmV3Tm9kZSA9IHdpZGdldC51cGRhdGUobGVmdFZOb2RlLCBkb21Ob2RlKSB8fCBkb21Ob2RlO1xuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIG5ld05vZGUgPSByZW5kZXJPcHRpb25zLnJlbmRlcih3aWRnZXQsIHJlbmRlck9wdGlvbnMpO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHZhciBwYXJlbnROb2RlID0gZG9tTm9kZS5wYXJlbnROb2RlO1xuXG4gICAgICAgICAgICAgICAgaWYgKHBhcmVudE5vZGUgJiYgbmV3Tm9kZSAhPT0gZG9tTm9kZSkge1xuICAgICAgICAgICAgICAgICAgICBwYXJlbnROb2RlLnJlcGxhY2VDaGlsZChuZXdOb2RlLCBkb21Ob2RlKTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICBpZiAoIXVwZGF0aW5nKSB7XG4gICAgICAgICAgICAgICAgICAgIGRlc3Ryb3lXaWRnZXQoZG9tTm9kZSwgbGVmdFZOb2RlKTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICByZXR1cm4gbmV3Tm9kZTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZnVuY3Rpb24gdk5vZGVQYXRjaChkb21Ob2RlLCBsZWZ0Vk5vZGUsIHZOb2RlLCByZW5kZXJPcHRpb25zKSB7XG4gICAgICAgICAgICAgICAgdmFyIHBhcmVudE5vZGUgPSBkb21Ob2RlLnBhcmVudE5vZGU7XG4gICAgICAgICAgICAgICAgdmFyIG5ld05vZGUgPSByZW5kZXJPcHRpb25zLnJlbmRlcih2Tm9kZSwgcmVuZGVyT3B0aW9ucyk7XG5cbiAgICAgICAgICAgICAgICBpZiAocGFyZW50Tm9kZSAmJiBuZXdOb2RlICE9PSBkb21Ob2RlKSB7XG4gICAgICAgICAgICAgICAgICAgIHBhcmVudE5vZGUucmVwbGFjZUNoaWxkKG5ld05vZGUsIGRvbU5vZGUpO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHJldHVybiBuZXdOb2RlO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBmdW5jdGlvbiBkZXN0cm95V2lkZ2V0KGRvbU5vZGUsIHcpIHtcbiAgICAgICAgICAgICAgICBpZiAodHlwZW9mIHcuZGVzdHJveSA9PT0gXCJmdW5jdGlvblwiICYmIGlzV2lkZ2V0KHcpKSB7XG4gICAgICAgICAgICAgICAgICAgIHcuZGVzdHJveShkb21Ob2RlKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIHJlb3JkZXJDaGlsZHJlbihkb21Ob2RlLCBtb3Zlcykge1xuICAgICAgICAgICAgICAgIHZhciBjaGlsZE5vZGVzID0gZG9tTm9kZS5jaGlsZE5vZGVzO1xuICAgICAgICAgICAgICAgIHZhciBrZXlNYXAgPSB7fTtcbiAgICAgICAgICAgICAgICB2YXIgbm9kZTtcbiAgICAgICAgICAgICAgICB2YXIgcmVtb3ZlO1xuICAgICAgICAgICAgICAgIHZhciBpbnNlcnQ7XG5cbiAgICAgICAgICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IG1vdmVzLnJlbW92ZXMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgICAgICAgICAgcmVtb3ZlID0gbW92ZXMucmVtb3Zlc1tpXTtcbiAgICAgICAgICAgICAgICAgICAgbm9kZSA9IGNoaWxkTm9kZXNbcmVtb3ZlLmZyb21dO1xuICAgICAgICAgICAgICAgICAgICBpZiAocmVtb3ZlLmtleSkge1xuICAgICAgICAgICAgICAgICAgICAgICAga2V5TWFwW3JlbW92ZS5rZXldID0gbm9kZTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICBkb21Ob2RlLnJlbW92ZUNoaWxkKG5vZGUpO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHZhciBsZW5ndGggPSBjaGlsZE5vZGVzLmxlbmd0aDtcbiAgICAgICAgICAgICAgICBmb3IgKHZhciBqID0gMDsgaiA8IG1vdmVzLmluc2VydHMubGVuZ3RoOyBqKyspIHtcbiAgICAgICAgICAgICAgICAgICAgaW5zZXJ0ID0gbW92ZXMuaW5zZXJ0c1tqXTtcbiAgICAgICAgICAgICAgICAgICAgbm9kZSA9IGtleU1hcFtpbnNlcnQua2V5XTtcbiAgICAgICAgICAgICAgICAgICAgLy8gdGhpcyBpcyB0aGUgd2VpcmRlc3QgYnVnIGkndmUgZXZlciBzZWVuIGluIHdlYmtpdFxuICAgICAgICAgICAgICAgICAgICBkb21Ob2RlLmluc2VydEJlZm9yZShub2RlLCBpbnNlcnQudG8gPj0gbGVuZ3RoKysgPyBudWxsIDogY2hpbGROb2Rlc1tpbnNlcnQudG9dKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIHJlcGxhY2VSb290KG9sZFJvb3QsIG5ld1Jvb3QpIHtcbiAgICAgICAgICAgICAgICBpZiAob2xkUm9vdCAmJiBuZXdSb290ICYmIG9sZFJvb3QgIT09IG5ld1Jvb3QgJiYgb2xkUm9vdC5wYXJlbnROb2RlKSB7XG4gICAgICAgICAgICAgICAgICAgIG9sZFJvb3QucGFyZW50Tm9kZS5yZXBsYWNlQ2hpbGQobmV3Um9vdCwgb2xkUm9vdCk7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgcmV0dXJuIG5ld1Jvb3Q7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0sIHsgXCIuLi92bm9kZS9pcy13aWRnZXQuanNcIjogMjksIFwiLi4vdm5vZGUvdnBhdGNoLmpzXCI6IDMyLCBcIi4vYXBwbHktcHJvcGVydGllc1wiOiAxNCwgXCIuL3VwZGF0ZS13aWRnZXRcIjogMTkgfV0sIDE4OiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge1xuICAgICAgICAgICAgdmFyIGRvY3VtZW50ID0gcmVxdWlyZShcImdsb2JhbC9kb2N1bWVudFwiKTtcbiAgICAgICAgICAgIHZhciBpc0FycmF5ID0gcmVxdWlyZShcIngtaXMtYXJyYXlcIik7XG5cbiAgICAgICAgICAgIHZhciByZW5kZXIgPSByZXF1aXJlKFwiLi9jcmVhdGUtZWxlbWVudFwiKTtcbiAgICAgICAgICAgIHZhciBkb21JbmRleCA9IHJlcXVpcmUoXCIuL2RvbS1pbmRleFwiKTtcbiAgICAgICAgICAgIHZhciBwYXRjaE9wID0gcmVxdWlyZShcIi4vcGF0Y2gtb3BcIik7XG4gICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IHBhdGNoO1xuXG4gICAgICAgICAgICBmdW5jdGlvbiBwYXRjaChyb290Tm9kZSwgcGF0Y2hlcywgcmVuZGVyT3B0aW9ucykge1xuICAgICAgICAgICAgICAgIHJlbmRlck9wdGlvbnMgPSByZW5kZXJPcHRpb25zIHx8IHt9O1xuICAgICAgICAgICAgICAgIHJlbmRlck9wdGlvbnMucGF0Y2ggPSByZW5kZXJPcHRpb25zLnBhdGNoICYmIHJlbmRlck9wdGlvbnMucGF0Y2ggIT09IHBhdGNoID8gcmVuZGVyT3B0aW9ucy5wYXRjaCA6IHBhdGNoUmVjdXJzaXZlO1xuICAgICAgICAgICAgICAgIHJlbmRlck9wdGlvbnMucmVuZGVyID0gcmVuZGVyT3B0aW9ucy5yZW5kZXIgfHwgcmVuZGVyO1xuXG4gICAgICAgICAgICAgICAgcmV0dXJuIHJlbmRlck9wdGlvbnMucGF0Y2gocm9vdE5vZGUsIHBhdGNoZXMsIHJlbmRlck9wdGlvbnMpO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBmdW5jdGlvbiBwYXRjaFJlY3Vyc2l2ZShyb290Tm9kZSwgcGF0Y2hlcywgcmVuZGVyT3B0aW9ucykge1xuICAgICAgICAgICAgICAgIHZhciBpbmRpY2VzID0gcGF0Y2hJbmRpY2VzKHBhdGNoZXMpO1xuXG4gICAgICAgICAgICAgICAgaWYgKGluZGljZXMubGVuZ3RoID09PSAwKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiByb290Tm9kZTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICB2YXIgaW5kZXggPSBkb21JbmRleChyb290Tm9kZSwgcGF0Y2hlcy5hLCBpbmRpY2VzKTtcbiAgICAgICAgICAgICAgICB2YXIgb3duZXJEb2N1bWVudCA9IHJvb3ROb2RlLm93bmVyRG9jdW1lbnQ7XG5cbiAgICAgICAgICAgICAgICBpZiAoIXJlbmRlck9wdGlvbnMuZG9jdW1lbnQgJiYgb3duZXJEb2N1bWVudCAhPT0gZG9jdW1lbnQpIHtcbiAgICAgICAgICAgICAgICAgICAgcmVuZGVyT3B0aW9ucy5kb2N1bWVudCA9IG93bmVyRG9jdW1lbnQ7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCBpbmRpY2VzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciBub2RlSW5kZXggPSBpbmRpY2VzW2ldO1xuICAgICAgICAgICAgICAgICAgICByb290Tm9kZSA9IGFwcGx5UGF0Y2gocm9vdE5vZGUsIGluZGV4W25vZGVJbmRleF0sIHBhdGNoZXNbbm9kZUluZGV4XSwgcmVuZGVyT3B0aW9ucyk7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgcmV0dXJuIHJvb3ROb2RlO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBmdW5jdGlvbiBhcHBseVBhdGNoKHJvb3ROb2RlLCBkb21Ob2RlLCBwYXRjaExpc3QsIHJlbmRlck9wdGlvbnMpIHtcbiAgICAgICAgICAgICAgICBpZiAoIWRvbU5vZGUpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHJvb3ROb2RlO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHZhciBuZXdOb2RlO1xuXG4gICAgICAgICAgICAgICAgaWYgKGlzQXJyYXkocGF0Y2hMaXN0KSkge1xuICAgICAgICAgICAgICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IHBhdGNoTGlzdC5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgICAgICAgICAgICAgbmV3Tm9kZSA9IHBhdGNoT3AocGF0Y2hMaXN0W2ldLCBkb21Ob2RlLCByZW5kZXJPcHRpb25zKTtcblxuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGRvbU5vZGUgPT09IHJvb3ROb2RlKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcm9vdE5vZGUgPSBuZXdOb2RlO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgbmV3Tm9kZSA9IHBhdGNoT3AocGF0Y2hMaXN0LCBkb21Ob2RlLCByZW5kZXJPcHRpb25zKTtcblxuICAgICAgICAgICAgICAgICAgICBpZiAoZG9tTm9kZSA9PT0gcm9vdE5vZGUpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJvb3ROb2RlID0gbmV3Tm9kZTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHJldHVybiByb290Tm9kZTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZnVuY3Rpb24gcGF0Y2hJbmRpY2VzKHBhdGNoZXMpIHtcbiAgICAgICAgICAgICAgICB2YXIgaW5kaWNlcyA9IFtdO1xuXG4gICAgICAgICAgICAgICAgZm9yICh2YXIga2V5IGluIHBhdGNoZXMpIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKGtleSAhPT0gXCJhXCIpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGluZGljZXMucHVzaChOdW1iZXIoa2V5KSk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICByZXR1cm4gaW5kaWNlcztcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSwgeyBcIi4vY3JlYXRlLWVsZW1lbnRcIjogMTUsIFwiLi9kb20taW5kZXhcIjogMTYsIFwiLi9wYXRjaC1vcFwiOiAxNywgXCJnbG9iYWwvZG9jdW1lbnRcIjogMTAsIFwieC1pcy1hcnJheVwiOiAxMiB9XSwgMTk6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICB2YXIgaXNXaWRnZXQgPSByZXF1aXJlKFwiLi4vdm5vZGUvaXMtd2lkZ2V0LmpzXCIpO1xuXG4gICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IHVwZGF0ZVdpZGdldDtcblxuICAgICAgICAgICAgZnVuY3Rpb24gdXBkYXRlV2lkZ2V0KGEsIGIpIHtcbiAgICAgICAgICAgICAgICBpZiAoaXNXaWRnZXQoYSkgJiYgaXNXaWRnZXQoYikpIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKFwibmFtZVwiIGluIGEgJiYgXCJuYW1lXCIgaW4gYikge1xuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGEuaWQgPT09IGIuaWQ7XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gYS5pbml0ID09PSBiLmluaXQ7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0sIHsgXCIuLi92bm9kZS9pcy13aWRnZXQuanNcIjogMjkgfV0sIDIwOiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge1xuICAgICAgICAgICAgJ3VzZSBzdHJpY3QnO1xuXG4gICAgICAgICAgICB2YXIgRXZTdG9yZSA9IHJlcXVpcmUoJ2V2LXN0b3JlJyk7XG5cbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gRXZIb29rO1xuXG4gICAgICAgICAgICBmdW5jdGlvbiBFdkhvb2sodmFsdWUpIHtcbiAgICAgICAgICAgICAgICBpZiAoISh0aGlzIGluc3RhbmNlb2YgRXZIb29rKSkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gbmV3IEV2SG9vayh2YWx1ZSk7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgdGhpcy52YWx1ZSA9IHZhbHVlO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBFdkhvb2sucHJvdG90eXBlLmhvb2sgPSBmdW5jdGlvbiAobm9kZSwgcHJvcGVydHlOYW1lKSB7XG4gICAgICAgICAgICAgICAgdmFyIGVzID0gRXZTdG9yZShub2RlKTtcbiAgICAgICAgICAgICAgICB2YXIgcHJvcE5hbWUgPSBwcm9wZXJ0eU5hbWUuc3Vic3RyKDMpO1xuXG4gICAgICAgICAgICAgICAgZXNbcHJvcE5hbWVdID0gdGhpcy52YWx1ZTtcbiAgICAgICAgICAgIH07XG5cbiAgICAgICAgICAgIEV2SG9vay5wcm90b3R5cGUudW5ob29rID0gZnVuY3Rpb24gKG5vZGUsIHByb3BlcnR5TmFtZSkge1xuICAgICAgICAgICAgICAgIHZhciBlcyA9IEV2U3RvcmUobm9kZSk7XG4gICAgICAgICAgICAgICAgdmFyIHByb3BOYW1lID0gcHJvcGVydHlOYW1lLnN1YnN0cigzKTtcblxuICAgICAgICAgICAgICAgIGVzW3Byb3BOYW1lXSA9IHVuZGVmaW5lZDtcbiAgICAgICAgICAgIH07XG4gICAgICAgIH0sIHsgXCJldi1zdG9yZVwiOiA3IH1dLCAyMTogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHtcbiAgICAgICAgICAgICd1c2Ugc3RyaWN0JztcblxuICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBTb2Z0U2V0SG9vaztcblxuICAgICAgICAgICAgZnVuY3Rpb24gU29mdFNldEhvb2sodmFsdWUpIHtcbiAgICAgICAgICAgICAgICBpZiAoISh0aGlzIGluc3RhbmNlb2YgU29mdFNldEhvb2spKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBuZXcgU29mdFNldEhvb2sodmFsdWUpO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHRoaXMudmFsdWUgPSB2YWx1ZTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgU29mdFNldEhvb2sucHJvdG90eXBlLmhvb2sgPSBmdW5jdGlvbiAobm9kZSwgcHJvcGVydHlOYW1lKSB7XG4gICAgICAgICAgICAgICAgaWYgKG5vZGVbcHJvcGVydHlOYW1lXSAhPT0gdGhpcy52YWx1ZSkge1xuICAgICAgICAgICAgICAgICAgICBub2RlW3Byb3BlcnR5TmFtZV0gPSB0aGlzLnZhbHVlO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH07XG4gICAgICAgIH0sIHt9XSwgMjI6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICAndXNlIHN0cmljdCc7XG5cbiAgICAgICAgICAgIHZhciBpc0FycmF5ID0gcmVxdWlyZSgneC1pcy1hcnJheScpO1xuXG4gICAgICAgICAgICB2YXIgVk5vZGUgPSByZXF1aXJlKCcuLi92bm9kZS92bm9kZS5qcycpO1xuICAgICAgICAgICAgdmFyIFZUZXh0ID0gcmVxdWlyZSgnLi4vdm5vZGUvdnRleHQuanMnKTtcbiAgICAgICAgICAgIHZhciBpc1ZOb2RlID0gcmVxdWlyZSgnLi4vdm5vZGUvaXMtdm5vZGUnKTtcbiAgICAgICAgICAgIHZhciBpc1ZUZXh0ID0gcmVxdWlyZSgnLi4vdm5vZGUvaXMtdnRleHQnKTtcbiAgICAgICAgICAgIHZhciBpc1dpZGdldCA9IHJlcXVpcmUoJy4uL3Zub2RlL2lzLXdpZGdldCcpO1xuICAgICAgICAgICAgdmFyIGlzSG9vayA9IHJlcXVpcmUoJy4uL3Zub2RlL2lzLXZob29rJyk7XG4gICAgICAgICAgICB2YXIgaXNWVGh1bmsgPSByZXF1aXJlKCcuLi92bm9kZS9pcy10aHVuaycpO1xuXG4gICAgICAgICAgICB2YXIgcGFyc2VUYWcgPSByZXF1aXJlKCcuL3BhcnNlLXRhZy5qcycpO1xuICAgICAgICAgICAgdmFyIHNvZnRTZXRIb29rID0gcmVxdWlyZSgnLi9ob29rcy9zb2Z0LXNldC1ob29rLmpzJyk7XG4gICAgICAgICAgICB2YXIgZXZIb29rID0gcmVxdWlyZSgnLi9ob29rcy9ldi1ob29rLmpzJyk7XG5cbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gaDtcblxuICAgICAgICAgICAgZnVuY3Rpb24gaCh0YWdOYW1lLCBwcm9wZXJ0aWVzLCBjaGlsZHJlbikge1xuICAgICAgICAgICAgICAgIHZhciBjaGlsZE5vZGVzID0gW107XG4gICAgICAgICAgICAgICAgdmFyIHRhZywgcHJvcHMsIGtleSwgbmFtZXNwYWNlO1xuXG4gICAgICAgICAgICAgICAgaWYgKCFjaGlsZHJlbiAmJiBpc0NoaWxkcmVuKHByb3BlcnRpZXMpKSB7XG4gICAgICAgICAgICAgICAgICAgIGNoaWxkcmVuID0gcHJvcGVydGllcztcbiAgICAgICAgICAgICAgICAgICAgcHJvcHMgPSB7fTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICBwcm9wcyA9IHByb3BzIHx8IHByb3BlcnRpZXMgfHwge307XG4gICAgICAgICAgICAgICAgdGFnID0gcGFyc2VUYWcodGFnTmFtZSwgcHJvcHMpO1xuXG4gICAgICAgICAgICAgICAgLy8gc3VwcG9ydCBrZXlzXG4gICAgICAgICAgICAgICAgaWYgKHByb3BzLmhhc093blByb3BlcnR5KCdrZXknKSkge1xuICAgICAgICAgICAgICAgICAgICBrZXkgPSBwcm9wcy5rZXk7XG4gICAgICAgICAgICAgICAgICAgIHByb3BzLmtleSA9IHVuZGVmaW5lZDtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAvLyBzdXBwb3J0IG5hbWVzcGFjZVxuICAgICAgICAgICAgICAgIGlmIChwcm9wcy5oYXNPd25Qcm9wZXJ0eSgnbmFtZXNwYWNlJykpIHtcbiAgICAgICAgICAgICAgICAgICAgbmFtZXNwYWNlID0gcHJvcHMubmFtZXNwYWNlO1xuICAgICAgICAgICAgICAgICAgICBwcm9wcy5uYW1lc3BhY2UgPSB1bmRlZmluZWQ7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgLy8gZml4IGN1cnNvciBidWdcbiAgICAgICAgICAgICAgICBpZiAodGFnID09PSAnSU5QVVQnICYmICFuYW1lc3BhY2UgJiYgcHJvcHMuaGFzT3duUHJvcGVydHkoJ3ZhbHVlJykgJiYgcHJvcHMudmFsdWUgIT09IHVuZGVmaW5lZCAmJiAhaXNIb29rKHByb3BzLnZhbHVlKSkge1xuICAgICAgICAgICAgICAgICAgICBwcm9wcy52YWx1ZSA9IHNvZnRTZXRIb29rKHByb3BzLnZhbHVlKTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICB0cmFuc2Zvcm1Qcm9wZXJ0aWVzKHByb3BzKTtcblxuICAgICAgICAgICAgICAgIGlmIChjaGlsZHJlbiAhPT0gdW5kZWZpbmVkICYmIGNoaWxkcmVuICE9PSBudWxsKSB7XG4gICAgICAgICAgICAgICAgICAgIGFkZENoaWxkKGNoaWxkcmVuLCBjaGlsZE5vZGVzLCB0YWcsIHByb3BzKTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICByZXR1cm4gbmV3IFZOb2RlKHRhZywgcHJvcHMsIGNoaWxkTm9kZXMsIGtleSwgbmFtZXNwYWNlKTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZnVuY3Rpb24gYWRkQ2hpbGQoYywgY2hpbGROb2RlcywgdGFnLCBwcm9wcykge1xuICAgICAgICAgICAgICAgIGlmICh0eXBlb2YgYyA9PT0gJ3N0cmluZycpIHtcbiAgICAgICAgICAgICAgICAgICAgY2hpbGROb2Rlcy5wdXNoKG5ldyBWVGV4dChjKSk7XG4gICAgICAgICAgICAgICAgfSBlbHNlIGlmICh0eXBlb2YgYyA9PT0gJ251bWJlcicpIHtcbiAgICAgICAgICAgICAgICAgICAgY2hpbGROb2Rlcy5wdXNoKG5ldyBWVGV4dChTdHJpbmcoYykpKTtcbiAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKGlzQ2hpbGQoYykpIHtcbiAgICAgICAgICAgICAgICAgICAgY2hpbGROb2Rlcy5wdXNoKGMpO1xuICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoaXNBcnJheShjKSkge1xuICAgICAgICAgICAgICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IGMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGFkZENoaWxkKGNbaV0sIGNoaWxkTm9kZXMsIHRhZywgcHJvcHMpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfSBlbHNlIGlmIChjID09PSBudWxsIHx8IGMgPT09IHVuZGVmaW5lZCkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgdGhyb3cgVW5leHBlY3RlZFZpcnR1YWxFbGVtZW50KHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGZvcmVpZ25PYmplY3Q6IGMsXG4gICAgICAgICAgICAgICAgICAgICAgICBwYXJlbnRWbm9kZToge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRhZ05hbWU6IHRhZyxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBwcm9wZXJ0aWVzOiBwcm9wc1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIHRyYW5zZm9ybVByb3BlcnRpZXMocHJvcHMpIHtcbiAgICAgICAgICAgICAgICBmb3IgKHZhciBwcm9wTmFtZSBpbiBwcm9wcykge1xuICAgICAgICAgICAgICAgICAgICBpZiAocHJvcHMuaGFzT3duUHJvcGVydHkocHJvcE5hbWUpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICB2YXIgdmFsdWUgPSBwcm9wc1twcm9wTmFtZV07XG5cbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChpc0hvb2sodmFsdWUpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgY29udGludWU7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChwcm9wTmFtZS5zdWJzdHIoMCwgMykgPT09ICdldi0nKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gYWRkIGV2LWZvbyBzdXBwb3J0XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcHJvcHNbcHJvcE5hbWVdID0gZXZIb29rKHZhbHVlKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZnVuY3Rpb24gaXNDaGlsZCh4KSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGlzVk5vZGUoeCkgfHwgaXNWVGV4dCh4KSB8fCBpc1dpZGdldCh4KSB8fCBpc1ZUaHVuayh4KTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZnVuY3Rpb24gaXNDaGlsZHJlbih4KSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHR5cGVvZiB4ID09PSAnc3RyaW5nJyB8fCBpc0FycmF5KHgpIHx8IGlzQ2hpbGQoeCk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIFVuZXhwZWN0ZWRWaXJ0dWFsRWxlbWVudChkYXRhKSB7XG4gICAgICAgICAgICAgICAgdmFyIGVyciA9IG5ldyBFcnJvcigpO1xuXG4gICAgICAgICAgICAgICAgZXJyLnR5cGUgPSAndmlydHVhbC1oeXBlcnNjcmlwdC51bmV4cGVjdGVkLnZpcnR1YWwtZWxlbWVudCc7XG4gICAgICAgICAgICAgICAgZXJyLm1lc3NhZ2UgPSAnVW5leHBlY3RlZCB2aXJ0dWFsIGNoaWxkIHBhc3NlZCB0byBoKCkuXFxuJyArICdFeHBlY3RlZCBhIFZOb2RlIC8gVnRodW5rIC8gVldpZGdldCAvIHN0cmluZyBidXQ6XFxuJyArICdnb3Q6XFxuJyArIGVycm9yU3RyaW5nKGRhdGEuZm9yZWlnbk9iamVjdCkgKyAnLlxcbicgKyAnVGhlIHBhcmVudCB2bm9kZSBpczpcXG4nICsgZXJyb3JTdHJpbmcoZGF0YS5wYXJlbnRWbm9kZSk7XG4gICAgICAgICAgICAgICAgJ1xcbicgKyAnU3VnZ2VzdGVkIGZpeDogY2hhbmdlIHlvdXIgYGgoLi4uLCBbIC4uLiBdKWAgY2FsbHNpdGUuJztcbiAgICAgICAgICAgICAgICBlcnIuZm9yZWlnbk9iamVjdCA9IGRhdGEuZm9yZWlnbk9iamVjdDtcbiAgICAgICAgICAgICAgICBlcnIucGFyZW50Vm5vZGUgPSBkYXRhLnBhcmVudFZub2RlO1xuXG4gICAgICAgICAgICAgICAgcmV0dXJuIGVycjtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZnVuY3Rpb24gZXJyb3JTdHJpbmcob2JqKSB7XG4gICAgICAgICAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIEpTT04uc3RyaW5naWZ5KG9iaiwgbnVsbCwgJyAgICAnKTtcbiAgICAgICAgICAgICAgICB9IGNhdGNoIChlKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBTdHJpbmcob2JqKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH0sIHsgXCIuLi92bm9kZS9pcy10aHVua1wiOiAyNSwgXCIuLi92bm9kZS9pcy12aG9va1wiOiAyNiwgXCIuLi92bm9kZS9pcy12bm9kZVwiOiAyNywgXCIuLi92bm9kZS9pcy12dGV4dFwiOiAyOCwgXCIuLi92bm9kZS9pcy13aWRnZXRcIjogMjksIFwiLi4vdm5vZGUvdm5vZGUuanNcIjogMzEsIFwiLi4vdm5vZGUvdnRleHQuanNcIjogMzMsIFwiLi9ob29rcy9ldi1ob29rLmpzXCI6IDIwLCBcIi4vaG9va3Mvc29mdC1zZXQtaG9vay5qc1wiOiAyMSwgXCIuL3BhcnNlLXRhZy5qc1wiOiAyMywgXCJ4LWlzLWFycmF5XCI6IDEyIH1dLCAyMzogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHtcbiAgICAgICAgICAgICd1c2Ugc3RyaWN0JztcblxuICAgICAgICAgICAgdmFyIHNwbGl0ID0gcmVxdWlyZSgnYnJvd3Nlci1zcGxpdCcpO1xuXG4gICAgICAgICAgICB2YXIgY2xhc3NJZFNwbGl0ID0gLyhbXFwuI10/W2EtekEtWjAtOVxcdTAwN0YtXFx1RkZGRl86LV0rKS87XG4gICAgICAgICAgICB2YXIgbm90Q2xhc3NJZCA9IC9eXFwufCMvO1xuXG4gICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IHBhcnNlVGFnO1xuXG4gICAgICAgICAgICBmdW5jdGlvbiBwYXJzZVRhZyh0YWcsIHByb3BzKSB7XG4gICAgICAgICAgICAgICAgaWYgKCF0YWcpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuICdESVYnO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHZhciBub0lkID0gIXByb3BzLmhhc093blByb3BlcnR5KCdpZCcpO1xuXG4gICAgICAgICAgICAgICAgdmFyIHRhZ1BhcnRzID0gc3BsaXQodGFnLCBjbGFzc0lkU3BsaXQpO1xuICAgICAgICAgICAgICAgIHZhciB0YWdOYW1lID0gbnVsbDtcblxuICAgICAgICAgICAgICAgIGlmIChub3RDbGFzc0lkLnRlc3QodGFnUGFydHNbMV0pKSB7XG4gICAgICAgICAgICAgICAgICAgIHRhZ05hbWUgPSAnRElWJztcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICB2YXIgY2xhc3NlcywgcGFydCwgdHlwZSwgaTtcblxuICAgICAgICAgICAgICAgIGZvciAoaSA9IDA7IGkgPCB0YWdQYXJ0cy5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgICAgICAgICBwYXJ0ID0gdGFnUGFydHNbaV07XG5cbiAgICAgICAgICAgICAgICAgICAgaWYgKCFwYXJ0KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBjb250aW51ZTtcbiAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgIHR5cGUgPSBwYXJ0LmNoYXJBdCgwKTtcblxuICAgICAgICAgICAgICAgICAgICBpZiAoIXRhZ05hbWUpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHRhZ05hbWUgPSBwYXJ0O1xuICAgICAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKHR5cGUgPT09ICcuJykge1xuICAgICAgICAgICAgICAgICAgICAgICAgY2xhc3NlcyA9IGNsYXNzZXMgfHwgW107XG4gICAgICAgICAgICAgICAgICAgICAgICBjbGFzc2VzLnB1c2gocGFydC5zdWJzdHJpbmcoMSwgcGFydC5sZW5ndGgpKTtcbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIGlmICh0eXBlID09PSAnIycgJiYgbm9JZCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgcHJvcHMuaWQgPSBwYXJ0LnN1YnN0cmluZygxLCBwYXJ0Lmxlbmd0aCk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICBpZiAoY2xhc3Nlcykge1xuICAgICAgICAgICAgICAgICAgICBpZiAocHJvcHMuY2xhc3NOYW1lKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBjbGFzc2VzLnB1c2gocHJvcHMuY2xhc3NOYW1lKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgIHByb3BzLmNsYXNzTmFtZSA9IGNsYXNzZXMuam9pbignICcpO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHJldHVybiBwcm9wcy5uYW1lc3BhY2UgPyB0YWdOYW1lIDogdGFnTmFtZS50b1VwcGVyQ2FzZSgpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9LCB7IFwiYnJvd3Nlci1zcGxpdFwiOiA1IH1dLCAyNDogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHtcbiAgICAgICAgICAgIHZhciBpc1ZOb2RlID0gcmVxdWlyZShcIi4vaXMtdm5vZGVcIik7XG4gICAgICAgICAgICB2YXIgaXNWVGV4dCA9IHJlcXVpcmUoXCIuL2lzLXZ0ZXh0XCIpO1xuICAgICAgICAgICAgdmFyIGlzV2lkZ2V0ID0gcmVxdWlyZShcIi4vaXMtd2lkZ2V0XCIpO1xuICAgICAgICAgICAgdmFyIGlzVGh1bmsgPSByZXF1aXJlKFwiLi9pcy10aHVua1wiKTtcblxuICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBoYW5kbGVUaHVuaztcblxuICAgICAgICAgICAgZnVuY3Rpb24gaGFuZGxlVGh1bmsoYSwgYikge1xuICAgICAgICAgICAgICAgIHZhciByZW5kZXJlZEEgPSBhO1xuICAgICAgICAgICAgICAgIHZhciByZW5kZXJlZEIgPSBiO1xuXG4gICAgICAgICAgICAgICAgaWYgKGlzVGh1bmsoYikpIHtcbiAgICAgICAgICAgICAgICAgICAgcmVuZGVyZWRCID0gcmVuZGVyVGh1bmsoYiwgYSk7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgaWYgKGlzVGh1bmsoYSkpIHtcbiAgICAgICAgICAgICAgICAgICAgcmVuZGVyZWRBID0gcmVuZGVyVGh1bmsoYSwgbnVsbCk7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgICAgICAgICAgYTogcmVuZGVyZWRBLFxuICAgICAgICAgICAgICAgICAgICBiOiByZW5kZXJlZEJcbiAgICAgICAgICAgICAgICB9O1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBmdW5jdGlvbiByZW5kZXJUaHVuayh0aHVuaywgcHJldmlvdXMpIHtcbiAgICAgICAgICAgICAgICB2YXIgcmVuZGVyZWRUaHVuayA9IHRodW5rLnZub2RlO1xuXG4gICAgICAgICAgICAgICAgaWYgKCFyZW5kZXJlZFRodW5rKSB7XG4gICAgICAgICAgICAgICAgICAgIHJlbmRlcmVkVGh1bmsgPSB0aHVuay52bm9kZSA9IHRodW5rLnJlbmRlcihwcmV2aW91cyk7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgaWYgKCEoaXNWTm9kZShyZW5kZXJlZFRodW5rKSB8fCBpc1ZUZXh0KHJlbmRlcmVkVGh1bmspIHx8IGlzV2lkZ2V0KHJlbmRlcmVkVGh1bmspKSkge1xuICAgICAgICAgICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoXCJ0aHVuayBkaWQgbm90IHJldHVybiBhIHZhbGlkIG5vZGVcIik7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgcmV0dXJuIHJlbmRlcmVkVGh1bms7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0sIHsgXCIuL2lzLXRodW5rXCI6IDI1LCBcIi4vaXMtdm5vZGVcIjogMjcsIFwiLi9pcy12dGV4dFwiOiAyOCwgXCIuL2lzLXdpZGdldFwiOiAyOSB9XSwgMjU6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IGlzVGh1bms7XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIGlzVGh1bmsodCkge1xuICAgICAgICAgICAgICAgIHJldHVybiB0ICYmIHQudHlwZSA9PT0gXCJUaHVua1wiO1xuICAgICAgICAgICAgfVxuICAgICAgICB9LCB7fV0sIDI2OiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge1xuICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBpc0hvb2s7XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIGlzSG9vayhob29rKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGhvb2sgJiYgKHR5cGVvZiBob29rLmhvb2sgPT09IFwiZnVuY3Rpb25cIiAmJiAhaG9vay5oYXNPd25Qcm9wZXJ0eShcImhvb2tcIikgfHwgdHlwZW9mIGhvb2sudW5ob29rID09PSBcImZ1bmN0aW9uXCIgJiYgIWhvb2suaGFzT3duUHJvcGVydHkoXCJ1bmhvb2tcIikpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9LCB7fV0sIDI3OiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge1xuICAgICAgICAgICAgdmFyIHZlcnNpb24gPSByZXF1aXJlKFwiLi92ZXJzaW9uXCIpO1xuXG4gICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IGlzVmlydHVhbE5vZGU7XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIGlzVmlydHVhbE5vZGUoeCkge1xuICAgICAgICAgICAgICAgIHJldHVybiB4ICYmIHgudHlwZSA9PT0gXCJWaXJ0dWFsTm9kZVwiICYmIHgudmVyc2lvbiA9PT0gdmVyc2lvbjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSwgeyBcIi4vdmVyc2lvblwiOiAzMCB9XSwgMjg6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICB2YXIgdmVyc2lvbiA9IHJlcXVpcmUoXCIuL3ZlcnNpb25cIik7XG5cbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gaXNWaXJ0dWFsVGV4dDtcblxuICAgICAgICAgICAgZnVuY3Rpb24gaXNWaXJ0dWFsVGV4dCh4KSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHggJiYgeC50eXBlID09PSBcIlZpcnR1YWxUZXh0XCIgJiYgeC52ZXJzaW9uID09PSB2ZXJzaW9uO1xuICAgICAgICAgICAgfVxuICAgICAgICB9LCB7IFwiLi92ZXJzaW9uXCI6IDMwIH1dLCAyOTogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHtcbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gaXNXaWRnZXQ7XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIGlzV2lkZ2V0KHcpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gdyAmJiB3LnR5cGUgPT09IFwiV2lkZ2V0XCI7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0sIHt9XSwgMzA6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IFwiMlwiO1xuICAgICAgICB9LCB7fV0sIDMxOiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge1xuICAgICAgICAgICAgdmFyIHZlcnNpb24gPSByZXF1aXJlKFwiLi92ZXJzaW9uXCIpO1xuICAgICAgICAgICAgdmFyIGlzVk5vZGUgPSByZXF1aXJlKFwiLi9pcy12bm9kZVwiKTtcbiAgICAgICAgICAgIHZhciBpc1dpZGdldCA9IHJlcXVpcmUoXCIuL2lzLXdpZGdldFwiKTtcbiAgICAgICAgICAgIHZhciBpc1RodW5rID0gcmVxdWlyZShcIi4vaXMtdGh1bmtcIik7XG4gICAgICAgICAgICB2YXIgaXNWSG9vayA9IHJlcXVpcmUoXCIuL2lzLXZob29rXCIpO1xuXG4gICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IFZpcnR1YWxOb2RlO1xuXG4gICAgICAgICAgICB2YXIgbm9Qcm9wZXJ0aWVzID0ge307XG4gICAgICAgICAgICB2YXIgbm9DaGlsZHJlbiA9IFtdO1xuXG4gICAgICAgICAgICBmdW5jdGlvbiBWaXJ0dWFsTm9kZSh0YWdOYW1lLCBwcm9wZXJ0aWVzLCBjaGlsZHJlbiwga2V5LCBuYW1lc3BhY2UpIHtcbiAgICAgICAgICAgICAgICB0aGlzLnRhZ05hbWUgPSB0YWdOYW1lO1xuICAgICAgICAgICAgICAgIHRoaXMucHJvcGVydGllcyA9IHByb3BlcnRpZXMgfHwgbm9Qcm9wZXJ0aWVzO1xuICAgICAgICAgICAgICAgIHRoaXMuY2hpbGRyZW4gPSBjaGlsZHJlbiB8fCBub0NoaWxkcmVuO1xuICAgICAgICAgICAgICAgIHRoaXMua2V5ID0ga2V5ICE9IG51bGwgPyBTdHJpbmcoa2V5KSA6IHVuZGVmaW5lZDtcbiAgICAgICAgICAgICAgICB0aGlzLm5hbWVzcGFjZSA9IHR5cGVvZiBuYW1lc3BhY2UgPT09IFwic3RyaW5nXCIgPyBuYW1lc3BhY2UgOiBudWxsO1xuXG4gICAgICAgICAgICAgICAgdmFyIGNvdW50ID0gY2hpbGRyZW4gJiYgY2hpbGRyZW4ubGVuZ3RoIHx8IDA7XG4gICAgICAgICAgICAgICAgdmFyIGRlc2NlbmRhbnRzID0gMDtcbiAgICAgICAgICAgICAgICB2YXIgaGFzV2lkZ2V0cyA9IGZhbHNlO1xuICAgICAgICAgICAgICAgIHZhciBoYXNUaHVua3MgPSBmYWxzZTtcbiAgICAgICAgICAgICAgICB2YXIgZGVzY2VuZGFudEhvb2tzID0gZmFsc2U7XG4gICAgICAgICAgICAgICAgdmFyIGhvb2tzO1xuXG4gICAgICAgICAgICAgICAgZm9yICh2YXIgcHJvcE5hbWUgaW4gcHJvcGVydGllcykge1xuICAgICAgICAgICAgICAgICAgICBpZiAocHJvcGVydGllcy5oYXNPd25Qcm9wZXJ0eShwcm9wTmFtZSkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHZhciBwcm9wZXJ0eSA9IHByb3BlcnRpZXNbcHJvcE5hbWVdO1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGlzVkhvb2socHJvcGVydHkpICYmIHByb3BlcnR5LnVuaG9vaykge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmICghaG9va3MpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaG9va3MgPSB7fTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBob29rc1twcm9wTmFtZV0gPSBwcm9wZXJ0eTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgY291bnQ7IGkrKykge1xuICAgICAgICAgICAgICAgICAgICB2YXIgY2hpbGQgPSBjaGlsZHJlbltpXTtcbiAgICAgICAgICAgICAgICAgICAgaWYgKGlzVk5vZGUoY2hpbGQpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBkZXNjZW5kYW50cyArPSBjaGlsZC5jb3VudCB8fCAwO1xuXG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoIWhhc1dpZGdldHMgJiYgY2hpbGQuaGFzV2lkZ2V0cykge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGhhc1dpZGdldHMgPSB0cnVlO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoIWhhc1RodW5rcyAmJiBjaGlsZC5oYXNUaHVua3MpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBoYXNUaHVua3MgPSB0cnVlO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoIWRlc2NlbmRhbnRIb29rcyAmJiAoY2hpbGQuaG9va3MgfHwgY2hpbGQuZGVzY2VuZGFudEhvb2tzKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRlc2NlbmRhbnRIb29rcyA9IHRydWU7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoIWhhc1dpZGdldHMgJiYgaXNXaWRnZXQoY2hpbGQpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAodHlwZW9mIGNoaWxkLmRlc3Ryb3kgPT09IFwiZnVuY3Rpb25cIikge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGhhc1dpZGdldHMgPSB0cnVlO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKCFoYXNUaHVua3MgJiYgaXNUaHVuayhjaGlsZCkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGhhc1RodW5rcyA9IHRydWU7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICB0aGlzLmNvdW50ID0gY291bnQgKyBkZXNjZW5kYW50cztcbiAgICAgICAgICAgICAgICB0aGlzLmhhc1dpZGdldHMgPSBoYXNXaWRnZXRzO1xuICAgICAgICAgICAgICAgIHRoaXMuaGFzVGh1bmtzID0gaGFzVGh1bmtzO1xuICAgICAgICAgICAgICAgIHRoaXMuaG9va3MgPSBob29rcztcbiAgICAgICAgICAgICAgICB0aGlzLmRlc2NlbmRhbnRIb29rcyA9IGRlc2NlbmRhbnRIb29rcztcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgVmlydHVhbE5vZGUucHJvdG90eXBlLnZlcnNpb24gPSB2ZXJzaW9uO1xuICAgICAgICAgICAgVmlydHVhbE5vZGUucHJvdG90eXBlLnR5cGUgPSBcIlZpcnR1YWxOb2RlXCI7XG4gICAgICAgIH0sIHsgXCIuL2lzLXRodW5rXCI6IDI1LCBcIi4vaXMtdmhvb2tcIjogMjYsIFwiLi9pcy12bm9kZVwiOiAyNywgXCIuL2lzLXdpZGdldFwiOiAyOSwgXCIuL3ZlcnNpb25cIjogMzAgfV0sIDMyOiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge1xuICAgICAgICAgICAgdmFyIHZlcnNpb24gPSByZXF1aXJlKFwiLi92ZXJzaW9uXCIpO1xuXG4gICAgICAgICAgICBWaXJ0dWFsUGF0Y2guTk9ORSA9IDA7XG4gICAgICAgICAgICBWaXJ0dWFsUGF0Y2guVlRFWFQgPSAxO1xuICAgICAgICAgICAgVmlydHVhbFBhdGNoLlZOT0RFID0gMjtcbiAgICAgICAgICAgIFZpcnR1YWxQYXRjaC5XSURHRVQgPSAzO1xuICAgICAgICAgICAgVmlydHVhbFBhdGNoLlBST1BTID0gNDtcbiAgICAgICAgICAgIFZpcnR1YWxQYXRjaC5PUkRFUiA9IDU7XG4gICAgICAgICAgICBWaXJ0dWFsUGF0Y2guSU5TRVJUID0gNjtcbiAgICAgICAgICAgIFZpcnR1YWxQYXRjaC5SRU1PVkUgPSA3O1xuICAgICAgICAgICAgVmlydHVhbFBhdGNoLlRIVU5LID0gODtcblxuICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBWaXJ0dWFsUGF0Y2g7XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIFZpcnR1YWxQYXRjaCh0eXBlLCB2Tm9kZSwgcGF0Y2gpIHtcbiAgICAgICAgICAgICAgICB0aGlzLnR5cGUgPSBOdW1iZXIodHlwZSk7XG4gICAgICAgICAgICAgICAgdGhpcy52Tm9kZSA9IHZOb2RlO1xuICAgICAgICAgICAgICAgIHRoaXMucGF0Y2ggPSBwYXRjaDtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgVmlydHVhbFBhdGNoLnByb3RvdHlwZS52ZXJzaW9uID0gdmVyc2lvbjtcbiAgICAgICAgICAgIFZpcnR1YWxQYXRjaC5wcm90b3R5cGUudHlwZSA9IFwiVmlydHVhbFBhdGNoXCI7XG4gICAgICAgIH0sIHsgXCIuL3ZlcnNpb25cIjogMzAgfV0sIDMzOiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge1xuICAgICAgICAgICAgdmFyIHZlcnNpb24gPSByZXF1aXJlKFwiLi92ZXJzaW9uXCIpO1xuXG4gICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IFZpcnR1YWxUZXh0O1xuXG4gICAgICAgICAgICBmdW5jdGlvbiBWaXJ0dWFsVGV4dCh0ZXh0KSB7XG4gICAgICAgICAgICAgICAgdGhpcy50ZXh0ID0gU3RyaW5nKHRleHQpO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBWaXJ0dWFsVGV4dC5wcm90b3R5cGUudmVyc2lvbiA9IHZlcnNpb247XG4gICAgICAgICAgICBWaXJ0dWFsVGV4dC5wcm90b3R5cGUudHlwZSA9IFwiVmlydHVhbFRleHRcIjtcbiAgICAgICAgfSwgeyBcIi4vdmVyc2lvblwiOiAzMCB9XSwgMzQ6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICB2YXIgaXNPYmplY3QgPSByZXF1aXJlKFwiaXMtb2JqZWN0XCIpO1xuICAgICAgICAgICAgdmFyIGlzSG9vayA9IHJlcXVpcmUoXCIuLi92bm9kZS9pcy12aG9va1wiKTtcblxuICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBkaWZmUHJvcHM7XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIGRpZmZQcm9wcyhhLCBiKSB7XG4gICAgICAgICAgICAgICAgdmFyIGRpZmY7XG5cbiAgICAgICAgICAgICAgICBmb3IgKHZhciBhS2V5IGluIGEpIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKCEoYUtleSBpbiBiKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgZGlmZiA9IGRpZmYgfHwge307XG4gICAgICAgICAgICAgICAgICAgICAgICBkaWZmW2FLZXldID0gdW5kZWZpbmVkO1xuICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgdmFyIGFWYWx1ZSA9IGFbYUtleV07XG4gICAgICAgICAgICAgICAgICAgIHZhciBiVmFsdWUgPSBiW2FLZXldO1xuXG4gICAgICAgICAgICAgICAgICAgIGlmIChhVmFsdWUgPT09IGJWYWx1ZSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgY29udGludWU7XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoaXNPYmplY3QoYVZhbHVlKSAmJiBpc09iamVjdChiVmFsdWUpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoZ2V0UHJvdG90eXBlKGJWYWx1ZSkgIT09IGdldFByb3RvdHlwZShhVmFsdWUpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgZGlmZiA9IGRpZmYgfHwge307XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgZGlmZlthS2V5XSA9IGJWYWx1ZTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoaXNIb29rKGJWYWx1ZSkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBkaWZmID0gZGlmZiB8fCB7fTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBkaWZmW2FLZXldID0gYlZhbHVlO1xuICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB2YXIgb2JqZWN0RGlmZiA9IGRpZmZQcm9wcyhhVmFsdWUsIGJWYWx1ZSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKG9iamVjdERpZmYpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZGlmZiA9IGRpZmYgfHwge307XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRpZmZbYUtleV0gPSBvYmplY3REaWZmO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGRpZmYgPSBkaWZmIHx8IHt9O1xuICAgICAgICAgICAgICAgICAgICAgICAgZGlmZlthS2V5XSA9IGJWYWx1ZTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIGZvciAodmFyIGJLZXkgaW4gYikge1xuICAgICAgICAgICAgICAgICAgICBpZiAoIShiS2V5IGluIGEpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBkaWZmID0gZGlmZiB8fCB7fTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGRpZmZbYktleV0gPSBiW2JLZXldO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgcmV0dXJuIGRpZmY7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIGdldFByb3RvdHlwZSh2YWx1ZSkge1xuICAgICAgICAgICAgICAgIGlmIChPYmplY3QuZ2V0UHJvdG90eXBlT2YpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIE9iamVjdC5nZXRQcm90b3R5cGVPZih2YWx1ZSk7XG4gICAgICAgICAgICAgICAgfSBlbHNlIGlmICh2YWx1ZS5fX3Byb3RvX18pIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHZhbHVlLl9fcHJvdG9fXztcbiAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKHZhbHVlLmNvbnN0cnVjdG9yKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiB2YWx1ZS5jb25zdHJ1Y3Rvci5wcm90b3R5cGU7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9LCB7IFwiLi4vdm5vZGUvaXMtdmhvb2tcIjogMjYsIFwiaXMtb2JqZWN0XCI6IDExIH1dLCAzNTogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHtcbiAgICAgICAgICAgIHZhciBpc0FycmF5ID0gcmVxdWlyZShcIngtaXMtYXJyYXlcIik7XG5cbiAgICAgICAgICAgIHZhciBWUGF0Y2ggPSByZXF1aXJlKFwiLi4vdm5vZGUvdnBhdGNoXCIpO1xuICAgICAgICAgICAgdmFyIGlzVk5vZGUgPSByZXF1aXJlKFwiLi4vdm5vZGUvaXMtdm5vZGVcIik7XG4gICAgICAgICAgICB2YXIgaXNWVGV4dCA9IHJlcXVpcmUoXCIuLi92bm9kZS9pcy12dGV4dFwiKTtcbiAgICAgICAgICAgIHZhciBpc1dpZGdldCA9IHJlcXVpcmUoXCIuLi92bm9kZS9pcy13aWRnZXRcIik7XG4gICAgICAgICAgICB2YXIgaXNUaHVuayA9IHJlcXVpcmUoXCIuLi92bm9kZS9pcy10aHVua1wiKTtcbiAgICAgICAgICAgIHZhciBoYW5kbGVUaHVuayA9IHJlcXVpcmUoXCIuLi92bm9kZS9oYW5kbGUtdGh1bmtcIik7XG5cbiAgICAgICAgICAgIHZhciBkaWZmUHJvcHMgPSByZXF1aXJlKFwiLi9kaWZmLXByb3BzXCIpO1xuXG4gICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IGRpZmY7XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIGRpZmYoYSwgYikge1xuICAgICAgICAgICAgICAgIHZhciBwYXRjaCA9IHsgYTogYSB9O1xuICAgICAgICAgICAgICAgIHdhbGsoYSwgYiwgcGF0Y2gsIDApO1xuICAgICAgICAgICAgICAgIHJldHVybiBwYXRjaDtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZnVuY3Rpb24gd2FsayhhLCBiLCBwYXRjaCwgaW5kZXgpIHtcbiAgICAgICAgICAgICAgICBpZiAoYSA9PT0gYikge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgdmFyIGFwcGx5ID0gcGF0Y2hbaW5kZXhdO1xuICAgICAgICAgICAgICAgIHZhciBhcHBseUNsZWFyID0gZmFsc2U7XG5cbiAgICAgICAgICAgICAgICBpZiAoaXNUaHVuayhhKSB8fCBpc1RodW5rKGIpKSB7XG4gICAgICAgICAgICAgICAgICAgIHRodW5rcyhhLCBiLCBwYXRjaCwgaW5kZXgpO1xuICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoYiA9PSBudWxsKSB7XG5cbiAgICAgICAgICAgICAgICAgICAgLy8gSWYgYSBpcyBhIHdpZGdldCB3ZSB3aWxsIGFkZCBhIHJlbW92ZSBwYXRjaCBmb3IgaXRcbiAgICAgICAgICAgICAgICAgICAgLy8gT3RoZXJ3aXNlIGFueSBjaGlsZCB3aWRnZXRzL2hvb2tzIG11c3QgYmUgZGVzdHJveWVkLlxuICAgICAgICAgICAgICAgICAgICAvLyBUaGlzIHByZXZlbnRzIGFkZGluZyB0d28gcmVtb3ZlIHBhdGNoZXMgZm9yIGEgd2lkZ2V0LlxuICAgICAgICAgICAgICAgICAgICBpZiAoIWlzV2lkZ2V0KGEpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBjbGVhclN0YXRlKGEsIHBhdGNoLCBpbmRleCk7XG4gICAgICAgICAgICAgICAgICAgICAgICBhcHBseSA9IHBhdGNoW2luZGV4XTtcbiAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgIGFwcGx5ID0gYXBwZW5kUGF0Y2goYXBwbHksIG5ldyBWUGF0Y2goVlBhdGNoLlJFTU9WRSwgYSwgYikpO1xuICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoaXNWTm9kZShiKSkge1xuICAgICAgICAgICAgICAgICAgICBpZiAoaXNWTm9kZShhKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGEudGFnTmFtZSA9PT0gYi50YWdOYW1lICYmIGEubmFtZXNwYWNlID09PSBiLm5hbWVzcGFjZSAmJiBhLmtleSA9PT0gYi5rZXkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB2YXIgcHJvcHNQYXRjaCA9IGRpZmZQcm9wcyhhLnByb3BlcnRpZXMsIGIucHJvcGVydGllcyk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHByb3BzUGF0Y2gpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYXBwbHkgPSBhcHBlbmRQYXRjaChhcHBseSwgbmV3IFZQYXRjaChWUGF0Y2guUFJPUFMsIGEsIHByb3BzUGF0Y2gpKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgYXBwbHkgPSBkaWZmQ2hpbGRyZW4oYSwgYiwgcGF0Y2gsIGFwcGx5LCBpbmRleCk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGFwcGx5ID0gYXBwZW5kUGF0Y2goYXBwbHksIG5ldyBWUGF0Y2goVlBhdGNoLlZOT0RFLCBhLCBiKSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgYXBwbHlDbGVhciA9IHRydWU7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBhcHBseSA9IGFwcGVuZFBhdGNoKGFwcGx5LCBuZXcgVlBhdGNoKFZQYXRjaC5WTk9ERSwgYSwgYikpO1xuICAgICAgICAgICAgICAgICAgICAgICAgYXBwbHlDbGVhciA9IHRydWU7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKGlzVlRleHQoYikpIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKCFpc1ZUZXh0KGEpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBhcHBseSA9IGFwcGVuZFBhdGNoKGFwcGx5LCBuZXcgVlBhdGNoKFZQYXRjaC5WVEVYVCwgYSwgYikpO1xuICAgICAgICAgICAgICAgICAgICAgICAgYXBwbHlDbGVhciA9IHRydWU7XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoYS50ZXh0ICE9PSBiLnRleHQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGFwcGx5ID0gYXBwZW5kUGF0Y2goYXBwbHksIG5ldyBWUGF0Y2goVlBhdGNoLlZURVhULCBhLCBiKSk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKGlzV2lkZ2V0KGIpKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmICghaXNXaWRnZXQoYSkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGFwcGx5Q2xlYXIgPSB0cnVlO1xuICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgYXBwbHkgPSBhcHBlbmRQYXRjaChhcHBseSwgbmV3IFZQYXRjaChWUGF0Y2guV0lER0VULCBhLCBiKSk7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgaWYgKGFwcGx5KSB7XG4gICAgICAgICAgICAgICAgICAgIHBhdGNoW2luZGV4XSA9IGFwcGx5O1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIGlmIChhcHBseUNsZWFyKSB7XG4gICAgICAgICAgICAgICAgICAgIGNsZWFyU3RhdGUoYSwgcGF0Y2gsIGluZGV4KTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIGRpZmZDaGlsZHJlbihhLCBiLCBwYXRjaCwgYXBwbHksIGluZGV4KSB7XG4gICAgICAgICAgICAgICAgdmFyIGFDaGlsZHJlbiA9IGEuY2hpbGRyZW47XG4gICAgICAgICAgICAgICAgdmFyIG9yZGVyZWRTZXQgPSByZW9yZGVyKGFDaGlsZHJlbiwgYi5jaGlsZHJlbik7XG4gICAgICAgICAgICAgICAgdmFyIGJDaGlsZHJlbiA9IG9yZGVyZWRTZXQuY2hpbGRyZW47XG5cbiAgICAgICAgICAgICAgICB2YXIgYUxlbiA9IGFDaGlsZHJlbi5sZW5ndGg7XG4gICAgICAgICAgICAgICAgdmFyIGJMZW4gPSBiQ2hpbGRyZW4ubGVuZ3RoO1xuICAgICAgICAgICAgICAgIHZhciBsZW4gPSBhTGVuID4gYkxlbiA/IGFMZW4gOiBiTGVuO1xuXG4gICAgICAgICAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCBsZW47IGkrKykge1xuICAgICAgICAgICAgICAgICAgICB2YXIgbGVmdE5vZGUgPSBhQ2hpbGRyZW5baV07XG4gICAgICAgICAgICAgICAgICAgIHZhciByaWdodE5vZGUgPSBiQ2hpbGRyZW5baV07XG4gICAgICAgICAgICAgICAgICAgIGluZGV4ICs9IDE7XG5cbiAgICAgICAgICAgICAgICAgICAgaWYgKCFsZWZ0Tm9kZSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHJpZ2h0Tm9kZSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIEV4Y2VzcyBub2RlcyBpbiBiIG5lZWQgdG8gYmUgYWRkZWRcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBhcHBseSA9IGFwcGVuZFBhdGNoKGFwcGx5LCBuZXcgVlBhdGNoKFZQYXRjaC5JTlNFUlQsIG51bGwsIHJpZ2h0Tm9kZSkpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgd2FsayhsZWZ0Tm9kZSwgcmlnaHROb2RlLCBwYXRjaCwgaW5kZXgpO1xuICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgaWYgKGlzVk5vZGUobGVmdE5vZGUpICYmIGxlZnROb2RlLmNvdW50KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBpbmRleCArPSBsZWZ0Tm9kZS5jb3VudDtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIGlmIChvcmRlcmVkU2V0Lm1vdmVzKSB7XG4gICAgICAgICAgICAgICAgICAgIC8vIFJlb3JkZXIgbm9kZXMgbGFzdFxuICAgICAgICAgICAgICAgICAgICBhcHBseSA9IGFwcGVuZFBhdGNoKGFwcGx5LCBuZXcgVlBhdGNoKFZQYXRjaC5PUkRFUiwgYSwgb3JkZXJlZFNldC5tb3ZlcykpO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHJldHVybiBhcHBseTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZnVuY3Rpb24gY2xlYXJTdGF0ZSh2Tm9kZSwgcGF0Y2gsIGluZGV4KSB7XG4gICAgICAgICAgICAgICAgLy8gVE9ETzogTWFrZSB0aGlzIGEgc2luZ2xlIHdhbGssIG5vdCB0d29cbiAgICAgICAgICAgICAgICB1bmhvb2sodk5vZGUsIHBhdGNoLCBpbmRleCk7XG4gICAgICAgICAgICAgICAgZGVzdHJveVdpZGdldHModk5vZGUsIHBhdGNoLCBpbmRleCk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIC8vIFBhdGNoIHJlY29yZHMgZm9yIGFsbCBkZXN0cm95ZWQgd2lkZ2V0cyBtdXN0IGJlIGFkZGVkIGJlY2F1c2Ugd2UgbmVlZFxuICAgICAgICAgICAgLy8gYSBET00gbm9kZSByZWZlcmVuY2UgZm9yIHRoZSBkZXN0cm95IGZ1bmN0aW9uXG4gICAgICAgICAgICBmdW5jdGlvbiBkZXN0cm95V2lkZ2V0cyh2Tm9kZSwgcGF0Y2gsIGluZGV4KSB7XG4gICAgICAgICAgICAgICAgaWYgKGlzV2lkZ2V0KHZOb2RlKSkge1xuICAgICAgICAgICAgICAgICAgICBpZiAodHlwZW9mIHZOb2RlLmRlc3Ryb3kgPT09IFwiZnVuY3Rpb25cIikge1xuICAgICAgICAgICAgICAgICAgICAgICAgcGF0Y2hbaW5kZXhdID0gYXBwZW5kUGF0Y2gocGF0Y2hbaW5kZXhdLCBuZXcgVlBhdGNoKFZQYXRjaC5SRU1PVkUsIHZOb2RlLCBudWxsKSk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKGlzVk5vZGUodk5vZGUpICYmICh2Tm9kZS5oYXNXaWRnZXRzIHx8IHZOb2RlLmhhc1RodW5rcykpIHtcbiAgICAgICAgICAgICAgICAgICAgdmFyIGNoaWxkcmVuID0gdk5vZGUuY2hpbGRyZW47XG4gICAgICAgICAgICAgICAgICAgIHZhciBsZW4gPSBjaGlsZHJlbi5sZW5ndGg7XG4gICAgICAgICAgICAgICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgbGVuOyBpKyspIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHZhciBjaGlsZCA9IGNoaWxkcmVuW2ldO1xuICAgICAgICAgICAgICAgICAgICAgICAgaW5kZXggKz0gMTtcblxuICAgICAgICAgICAgICAgICAgICAgICAgZGVzdHJveVdpZGdldHMoY2hpbGQsIHBhdGNoLCBpbmRleCk7XG5cbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChpc1ZOb2RlKGNoaWxkKSAmJiBjaGlsZC5jb3VudCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGluZGV4ICs9IGNoaWxkLmNvdW50O1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfSBlbHNlIGlmIChpc1RodW5rKHZOb2RlKSkge1xuICAgICAgICAgICAgICAgICAgICB0aHVua3Modk5vZGUsIG51bGwsIHBhdGNoLCBpbmRleCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAvLyBDcmVhdGUgYSBzdWItcGF0Y2ggZm9yIHRodW5rc1xuICAgICAgICAgICAgZnVuY3Rpb24gdGh1bmtzKGEsIGIsIHBhdGNoLCBpbmRleCkge1xuICAgICAgICAgICAgICAgIHZhciBub2RlcyA9IGhhbmRsZVRodW5rKGEsIGIpO1xuICAgICAgICAgICAgICAgIHZhciB0aHVua1BhdGNoID0gZGlmZihub2Rlcy5hLCBub2Rlcy5iKTtcbiAgICAgICAgICAgICAgICBpZiAoaGFzUGF0Y2hlcyh0aHVua1BhdGNoKSkge1xuICAgICAgICAgICAgICAgICAgICBwYXRjaFtpbmRleF0gPSBuZXcgVlBhdGNoKFZQYXRjaC5USFVOSywgbnVsbCwgdGh1bmtQYXRjaCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBmdW5jdGlvbiBoYXNQYXRjaGVzKHBhdGNoKSB7XG4gICAgICAgICAgICAgICAgZm9yICh2YXIgaW5kZXggaW4gcGF0Y2gpIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKGluZGV4ICE9PSBcImFcIikge1xuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIC8vIEV4ZWN1dGUgaG9va3Mgd2hlbiB0d28gbm9kZXMgYXJlIGlkZW50aWNhbFxuICAgICAgICAgICAgZnVuY3Rpb24gdW5ob29rKHZOb2RlLCBwYXRjaCwgaW5kZXgpIHtcbiAgICAgICAgICAgICAgICBpZiAoaXNWTm9kZSh2Tm9kZSkpIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKHZOb2RlLmhvb2tzKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBwYXRjaFtpbmRleF0gPSBhcHBlbmRQYXRjaChwYXRjaFtpbmRleF0sIG5ldyBWUGF0Y2goVlBhdGNoLlBST1BTLCB2Tm9kZSwgdW5kZWZpbmVkS2V5cyh2Tm9kZS5ob29rcykpKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgIGlmICh2Tm9kZS5kZXNjZW5kYW50SG9va3MgfHwgdk5vZGUuaGFzVGh1bmtzKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICB2YXIgY2hpbGRyZW4gPSB2Tm9kZS5jaGlsZHJlbjtcbiAgICAgICAgICAgICAgICAgICAgICAgIHZhciBsZW4gPSBjaGlsZHJlbi5sZW5ndGg7XG4gICAgICAgICAgICAgICAgICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IGxlbjsgaSsrKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdmFyIGNoaWxkID0gY2hpbGRyZW5baV07XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaW5kZXggKz0gMTtcblxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHVuaG9vayhjaGlsZCwgcGF0Y2gsIGluZGV4KTtcblxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChpc1ZOb2RlKGNoaWxkKSAmJiBjaGlsZC5jb3VudCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpbmRleCArPSBjaGlsZC5jb3VudDtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKGlzVGh1bmsodk5vZGUpKSB7XG4gICAgICAgICAgICAgICAgICAgIHRodW5rcyh2Tm9kZSwgbnVsbCwgcGF0Y2gsIGluZGV4KTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIHVuZGVmaW5lZEtleXMob2JqKSB7XG4gICAgICAgICAgICAgICAgdmFyIHJlc3VsdCA9IHt9O1xuXG4gICAgICAgICAgICAgICAgZm9yICh2YXIga2V5IGluIG9iaikge1xuICAgICAgICAgICAgICAgICAgICByZXN1bHRba2V5XSA9IHVuZGVmaW5lZDtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICByZXR1cm4gcmVzdWx0O1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAvLyBMaXN0IGRpZmYsIG5haXZlIGxlZnQgdG8gcmlnaHQgcmVvcmRlcmluZ1xuICAgICAgICAgICAgZnVuY3Rpb24gcmVvcmRlcihhQ2hpbGRyZW4sIGJDaGlsZHJlbikge1xuICAgICAgICAgICAgICAgIC8vIE8oTSkgdGltZSwgTyhNKSBtZW1vcnlcbiAgICAgICAgICAgICAgICB2YXIgYkNoaWxkSW5kZXggPSBrZXlJbmRleChiQ2hpbGRyZW4pO1xuICAgICAgICAgICAgICAgIHZhciBiS2V5cyA9IGJDaGlsZEluZGV4LmtleXM7XG4gICAgICAgICAgICAgICAgdmFyIGJGcmVlID0gYkNoaWxkSW5kZXguZnJlZTtcblxuICAgICAgICAgICAgICAgIGlmIChiRnJlZS5sZW5ndGggPT09IGJDaGlsZHJlbi5sZW5ndGgpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGNoaWxkcmVuOiBiQ2hpbGRyZW4sXG4gICAgICAgICAgICAgICAgICAgICAgICBtb3ZlczogbnVsbFxuICAgICAgICAgICAgICAgICAgICB9O1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIC8vIE8oTikgdGltZSwgTyhOKSBtZW1vcnlcbiAgICAgICAgICAgICAgICB2YXIgYUNoaWxkSW5kZXggPSBrZXlJbmRleChhQ2hpbGRyZW4pO1xuICAgICAgICAgICAgICAgIHZhciBhS2V5cyA9IGFDaGlsZEluZGV4LmtleXM7XG4gICAgICAgICAgICAgICAgdmFyIGFGcmVlID0gYUNoaWxkSW5kZXguZnJlZTtcblxuICAgICAgICAgICAgICAgIGlmIChhRnJlZS5sZW5ndGggPT09IGFDaGlsZHJlbi5sZW5ndGgpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGNoaWxkcmVuOiBiQ2hpbGRyZW4sXG4gICAgICAgICAgICAgICAgICAgICAgICBtb3ZlczogbnVsbFxuICAgICAgICAgICAgICAgICAgICB9O1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIC8vIE8oTUFYKE4sIE0pKSBtZW1vcnlcbiAgICAgICAgICAgICAgICB2YXIgbmV3Q2hpbGRyZW4gPSBbXTtcblxuICAgICAgICAgICAgICAgIHZhciBmcmVlSW5kZXggPSAwO1xuICAgICAgICAgICAgICAgIHZhciBmcmVlQ291bnQgPSBiRnJlZS5sZW5ndGg7XG4gICAgICAgICAgICAgICAgdmFyIGRlbGV0ZWRJdGVtcyA9IDA7XG5cbiAgICAgICAgICAgICAgICAvLyBJdGVyYXRlIHRocm91Z2ggYSBhbmQgbWF0Y2ggYSBub2RlIGluIGJcbiAgICAgICAgICAgICAgICAvLyBPKE4pIHRpbWUsXG4gICAgICAgICAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCBhQ2hpbGRyZW4ubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgICAgICAgICAgdmFyIGFJdGVtID0gYUNoaWxkcmVuW2ldO1xuICAgICAgICAgICAgICAgICAgICB2YXIgaXRlbUluZGV4O1xuXG4gICAgICAgICAgICAgICAgICAgIGlmIChhSXRlbS5rZXkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChiS2V5cy5oYXNPd25Qcm9wZXJ0eShhSXRlbS5rZXkpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gTWF0Y2ggdXAgdGhlIG9sZCBrZXlzXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaXRlbUluZGV4ID0gYktleXNbYUl0ZW0ua2V5XTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBuZXdDaGlsZHJlbi5wdXNoKGJDaGlsZHJlbltpdGVtSW5kZXhdKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gUmVtb3ZlIG9sZCBrZXllZCBpdGVtc1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGl0ZW1JbmRleCA9IGkgLSBkZWxldGVkSXRlbXMrKztcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBuZXdDaGlsZHJlbi5wdXNoKG51bGwpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgLy8gTWF0Y2ggdGhlIGl0ZW0gaW4gYSB3aXRoIHRoZSBuZXh0IGZyZWUgaXRlbSBpbiBiXG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoZnJlZUluZGV4IDwgZnJlZUNvdW50KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaXRlbUluZGV4ID0gYkZyZWVbZnJlZUluZGV4KytdO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIG5ld0NoaWxkcmVuLnB1c2goYkNoaWxkcmVuW2l0ZW1JbmRleF0pO1xuICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBUaGVyZSBhcmUgbm8gZnJlZSBpdGVtcyBpbiBiIHRvIG1hdGNoIHdpdGhcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyB0aGUgZnJlZSBpdGVtcyBpbiBhLCBzbyB0aGUgZXh0cmEgZnJlZSBub2Rlc1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIGFyZSBkZWxldGVkLlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGl0ZW1JbmRleCA9IGkgLSBkZWxldGVkSXRlbXMrKztcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBuZXdDaGlsZHJlbi5wdXNoKG51bGwpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgdmFyIGxhc3RGcmVlSW5kZXggPSBmcmVlSW5kZXggPj0gYkZyZWUubGVuZ3RoID8gYkNoaWxkcmVuLmxlbmd0aCA6IGJGcmVlW2ZyZWVJbmRleF07XG5cbiAgICAgICAgICAgICAgICAvLyBJdGVyYXRlIHRocm91Z2ggYiBhbmQgYXBwZW5kIGFueSBuZXcga2V5c1xuICAgICAgICAgICAgICAgIC8vIE8oTSkgdGltZVxuICAgICAgICAgICAgICAgIGZvciAodmFyIGogPSAwOyBqIDwgYkNoaWxkcmVuLmxlbmd0aDsgaisrKSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciBuZXdJdGVtID0gYkNoaWxkcmVuW2pdO1xuXG4gICAgICAgICAgICAgICAgICAgIGlmIChuZXdJdGVtLmtleSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKCFhS2V5cy5oYXNPd25Qcm9wZXJ0eShuZXdJdGVtLmtleSkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBBZGQgYW55IG5ldyBrZXllZCBpdGVtc1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIFdlIGFyZSBhZGRpbmcgbmV3IGl0ZW1zIHRvIHRoZSBlbmQgYW5kIHRoZW4gc29ydGluZyB0aGVtXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gaW4gcGxhY2UuIEluIGZ1dHVyZSB3ZSBzaG91bGQgaW5zZXJ0IG5ldyBpdGVtcyBpbiBwbGFjZS5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBuZXdDaGlsZHJlbi5wdXNoKG5ld0l0ZW0pO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKGogPj0gbGFzdEZyZWVJbmRleCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgLy8gQWRkIGFueSBsZWZ0b3ZlciBub24ta2V5ZWQgaXRlbXNcbiAgICAgICAgICAgICAgICAgICAgICAgIG5ld0NoaWxkcmVuLnB1c2gobmV3SXRlbSk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICB2YXIgc2ltdWxhdGUgPSBuZXdDaGlsZHJlbi5zbGljZSgpO1xuICAgICAgICAgICAgICAgIHZhciBzaW11bGF0ZUluZGV4ID0gMDtcbiAgICAgICAgICAgICAgICB2YXIgcmVtb3ZlcyA9IFtdO1xuICAgICAgICAgICAgICAgIHZhciBpbnNlcnRzID0gW107XG4gICAgICAgICAgICAgICAgdmFyIHNpbXVsYXRlSXRlbTtcblxuICAgICAgICAgICAgICAgIGZvciAodmFyIGsgPSAwOyBrIDwgYkNoaWxkcmVuLmxlbmd0aDspIHtcbiAgICAgICAgICAgICAgICAgICAgdmFyIHdhbnRlZEl0ZW0gPSBiQ2hpbGRyZW5ba107XG4gICAgICAgICAgICAgICAgICAgIHNpbXVsYXRlSXRlbSA9IHNpbXVsYXRlW3NpbXVsYXRlSW5kZXhdO1xuXG4gICAgICAgICAgICAgICAgICAgIC8vIHJlbW92ZSBpdGVtc1xuICAgICAgICAgICAgICAgICAgICB3aGlsZSAoc2ltdWxhdGVJdGVtID09PSBudWxsICYmIHNpbXVsYXRlLmxlbmd0aCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgcmVtb3Zlcy5wdXNoKHJlbW92ZShzaW11bGF0ZSwgc2ltdWxhdGVJbmRleCwgbnVsbCkpO1xuICAgICAgICAgICAgICAgICAgICAgICAgc2ltdWxhdGVJdGVtID0gc2ltdWxhdGVbc2ltdWxhdGVJbmRleF07XG4gICAgICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgICAgICBpZiAoIXNpbXVsYXRlSXRlbSB8fCBzaW11bGF0ZUl0ZW0ua2V5ICE9PSB3YW50ZWRJdGVtLmtleSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgLy8gaWYgd2UgbmVlZCBhIGtleSBpbiB0aGlzIHBvc2l0aW9uLi4uXG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAod2FudGVkSXRlbS5rZXkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoc2ltdWxhdGVJdGVtICYmIHNpbXVsYXRlSXRlbS5rZXkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gaWYgYW4gaW5zZXJ0IGRvZXNuJ3QgcHV0IHRoaXMga2V5IGluIHBsYWNlLCBpdCBuZWVkcyB0byBtb3ZlXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChiS2V5c1tzaW11bGF0ZUl0ZW0ua2V5XSAhPT0gayArIDEpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlbW92ZXMucHVzaChyZW1vdmUoc2ltdWxhdGUsIHNpbXVsYXRlSW5kZXgsIHNpbXVsYXRlSXRlbS5rZXkpKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNpbXVsYXRlSXRlbSA9IHNpbXVsYXRlW3NpbXVsYXRlSW5kZXhdO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gaWYgdGhlIHJlbW92ZSBkaWRuJ3QgcHV0IHRoZSB3YW50ZWQgaXRlbSBpbiBwbGFjZSwgd2UgbmVlZCB0byBpbnNlcnQgaXRcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmICghc2ltdWxhdGVJdGVtIHx8IHNpbXVsYXRlSXRlbS5rZXkgIT09IHdhbnRlZEl0ZW0ua2V5KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaW5zZXJ0cy5wdXNoKHsga2V5OiB3YW50ZWRJdGVtLmtleSwgdG86IGsgfSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBpdGVtcyBhcmUgbWF0Y2hpbmcsIHNvIHNraXAgYWhlYWRcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzaW11bGF0ZUluZGV4Kys7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaW5zZXJ0cy5wdXNoKHsga2V5OiB3YW50ZWRJdGVtLmtleSwgdG86IGsgfSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpbnNlcnRzLnB1c2goeyBrZXk6IHdhbnRlZEl0ZW0ua2V5LCB0bzogayB9KTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaysrO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgLy8gYSBrZXkgaW4gc2ltdWxhdGUgaGFzIG5vIG1hdGNoaW5nIHdhbnRlZCBrZXksIHJlbW92ZSBpdFxuICAgICAgICAgICAgICAgICAgICAgICAgZWxzZSBpZiAoc2ltdWxhdGVJdGVtICYmIHNpbXVsYXRlSXRlbS5rZXkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmVtb3Zlcy5wdXNoKHJlbW92ZShzaW11bGF0ZSwgc2ltdWxhdGVJbmRleCwgc2ltdWxhdGVJdGVtLmtleSkpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHNpbXVsYXRlSW5kZXgrKztcbiAgICAgICAgICAgICAgICAgICAgICAgIGsrKztcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIC8vIHJlbW92ZSBhbGwgdGhlIHJlbWFpbmluZyBub2RlcyBmcm9tIHNpbXVsYXRlXG4gICAgICAgICAgICAgICAgd2hpbGUgKHNpbXVsYXRlSW5kZXggPCBzaW11bGF0ZS5sZW5ndGgpIHtcbiAgICAgICAgICAgICAgICAgICAgc2ltdWxhdGVJdGVtID0gc2ltdWxhdGVbc2ltdWxhdGVJbmRleF07XG4gICAgICAgICAgICAgICAgICAgIHJlbW92ZXMucHVzaChyZW1vdmUoc2ltdWxhdGUsIHNpbXVsYXRlSW5kZXgsIHNpbXVsYXRlSXRlbSAmJiBzaW11bGF0ZUl0ZW0ua2V5KSk7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgLy8gSWYgdGhlIG9ubHkgbW92ZXMgd2UgaGF2ZSBhcmUgZGVsZXRlcyB0aGVuIHdlIGNhbiBqdXN0XG4gICAgICAgICAgICAgICAgLy8gbGV0IHRoZSBkZWxldGUgcGF0Y2ggcmVtb3ZlIHRoZXNlIGl0ZW1zLlxuICAgICAgICAgICAgICAgIGlmIChyZW1vdmVzLmxlbmd0aCA9PT0gZGVsZXRlZEl0ZW1zICYmICFpbnNlcnRzLmxlbmd0aCkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgICAgICAgICAgICAgY2hpbGRyZW46IG5ld0NoaWxkcmVuLFxuICAgICAgICAgICAgICAgICAgICAgICAgbW92ZXM6IG51bGxcbiAgICAgICAgICAgICAgICAgICAgfTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgICAgICAgICBjaGlsZHJlbjogbmV3Q2hpbGRyZW4sXG4gICAgICAgICAgICAgICAgICAgIG1vdmVzOiB7XG4gICAgICAgICAgICAgICAgICAgICAgICByZW1vdmVzOiByZW1vdmVzLFxuICAgICAgICAgICAgICAgICAgICAgICAgaW5zZXJ0czogaW5zZXJ0c1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZnVuY3Rpb24gcmVtb3ZlKGFyciwgaW5kZXgsIGtleSkge1xuICAgICAgICAgICAgICAgIGFyci5zcGxpY2UoaW5kZXgsIDEpO1xuXG4gICAgICAgICAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgICAgICAgICAgZnJvbTogaW5kZXgsXG4gICAgICAgICAgICAgICAgICAgIGtleToga2V5XG4gICAgICAgICAgICAgICAgfTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZnVuY3Rpb24ga2V5SW5kZXgoY2hpbGRyZW4pIHtcbiAgICAgICAgICAgICAgICB2YXIga2V5cyA9IHt9O1xuICAgICAgICAgICAgICAgIHZhciBmcmVlID0gW107XG4gICAgICAgICAgICAgICAgdmFyIGxlbmd0aCA9IGNoaWxkcmVuLmxlbmd0aDtcblxuICAgICAgICAgICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgbGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgICAgICAgICAgdmFyIGNoaWxkID0gY2hpbGRyZW5baV07XG5cbiAgICAgICAgICAgICAgICAgICAgaWYgKGNoaWxkLmtleSkge1xuICAgICAgICAgICAgICAgICAgICAgICAga2V5c1tjaGlsZC5rZXldID0gaTtcbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGZyZWUucHVzaChpKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHJldHVybiB7XG4gICAgICAgICAgICAgICAgICAgIGtleXM6IGtleXMsIC8vIEEgaGFzaCBvZiBrZXkgbmFtZSB0byBpbmRleFxuICAgICAgICAgICAgICAgICAgICBmcmVlOiBmcmVlIC8vIEFuIGFycmF5IG9mIHVua2V5ZWQgaXRlbSBpbmRpY2VzXG4gICAgICAgICAgICAgICAgfTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZnVuY3Rpb24gYXBwZW5kUGF0Y2goYXBwbHksIHBhdGNoKSB7XG4gICAgICAgICAgICAgICAgaWYgKGFwcGx5KSB7XG4gICAgICAgICAgICAgICAgICAgIGlmIChpc0FycmF5KGFwcGx5KSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgYXBwbHkucHVzaChwYXRjaCk7XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBhcHBseSA9IFthcHBseSwgcGF0Y2hdO1xuICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGFwcGx5O1xuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBwYXRjaDtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH0sIHsgXCIuLi92bm9kZS9oYW5kbGUtdGh1bmtcIjogMjQsIFwiLi4vdm5vZGUvaXMtdGh1bmtcIjogMjUsIFwiLi4vdm5vZGUvaXMtdm5vZGVcIjogMjcsIFwiLi4vdm5vZGUvaXMtdnRleHRcIjogMjgsIFwiLi4vdm5vZGUvaXMtd2lkZ2V0XCI6IDI5LCBcIi4uL3Zub2RlL3ZwYXRjaFwiOiAzMiwgXCIuL2RpZmYtcHJvcHNcIjogMzQsIFwieC1pcy1hcnJheVwiOiAxMiB9XSB9LCB7fSwgWzRdKSg0KTtcbn0pO1xuXG5leHBvcnQgZGVmYXVsdCBWaXJ0dWFsRE9NO1xuLy8jIHNvdXJjZU1hcHBpbmdVUkw9ZGF0YTphcHBsaWNhdGlvbi9qc29uO2Jhc2U2NCxleUoyWlhKemFXOXVJam96TENKemIzVnlZMlZ6SWpwYklteHBZaTkyYVhKMGRXRnNMV1J2YlM1cWN5SmRMQ0p1WVcxbGN5STZXMTBzSW0xaGNIQnBibWR6SWpvaVFVRkJRU3hKUVVGSkxHRkJRV0VzVlVGQlV5eERRVUZVTEVWQlFWazdRVUZETTBJc1YwRkJUeXhIUVVGUUxFTkJSREpDTzBOQlFWb3NRMEZGWml4WlFVRlhPMEZCUTB3c1VVRkJTU3hOUVVGS0xFVkJRVmtzVFVGQldpeEZRVUZ2UWl4UFFVRndRaXhEUVVSTE8wRkJSVXdzVjBGQlR5eFRRVUZWTEVOQlFWUXNRMEZCVnl4RFFVRllMRVZCUVdNc1EwRkJaQ3hGUVVGcFFpeERRVUZxUWl4RlFVRnZRanRCUVVOd1FpeHBRa0ZCVXl4RFFVRlVMRU5CUVZjc1EwRkJXQ3hGUVVGakxFTkJRV1FzUlVGQmFVSTdRVUZEWWl4blFrRkJTU3hEUVVGRExFVkJRVVVzUTBGQlJpeERRVUZFTEVWQlFVODdRVUZEVUN4dlFrRkJTU3hEUVVGRExFVkJRVVVzUTBGQlJpeERRVUZFTEVWQlFVODdRVUZEVUN4M1FrRkJTU3hKUVVGSkxFOUJRVThzVDBGQlVDeEpRVUZyUWl4VlFVRnNRaXhKUVVGblF5eFBRVUZvUXl4RFFVUkVPMEZCUlZBc2QwSkJRVWtzUTBGQlF5eERRVUZFTEVsQlFVMHNRMEZCVGl4RlFVRlRMRTlCUVU4c1JVRkJSU3hEUVVGR0xFVkJRVXNzUTBGQlF5eERRVUZFTEVOQlFWb3NRMEZCWWp0QlFVTkJMSGRDUVVGSkxFTkJRVW9zUlVGQlR5eFBRVUZQTEVWQlFVVXNRMEZCUml4RlFVRkxMRU5CUVVNc1EwRkJSQ3hEUVVGYUxFTkJRVkE3UVVGRFFTeDNRa0ZCU1N4SlFVRkpMRWxCUVVrc1MwRkJTaXhEUVVGVkxIbENRVUY1UWl4RFFVRjZRaXhIUVVFMlFpeEhRVUUzUWl4RFFVRmtMRU5CU2tjN1FVRkxVQ3d3UWtGQlRTeEZRVUZGTEVsQlFVWXNSMEZCVXl4clFrRkJWQ3hGUVVFMlFpeERRVUUzUWl4RFFVeERPMmxDUVVGWU8wRkJUMEVzYjBKQlFVa3NTVUZCU1N4RlFVRkZMRU5CUVVZc1NVRkJUenRCUVVOWUxEWkNRVUZUTEVWQlFWUTdhVUpCUkVrc1EwRlNSRHRCUVZkUUxHdENRVUZGTEVOQlFVWXNSVUZCU3l4RFFVRk1MRVZCUVZFc1NVRkJVaXhEUVVGaExFVkJRVVVzVDBGQlJpeEZRVUZYTEZWQlFWTXNRMEZCVkN4RlFVRlpPMEZCUTJoRExIZENRVUZKTEVsQlFVa3NSVUZCUlN4RFFVRkdMRVZCUVVzc1EwRkJUQ3hGUVVGUkxFTkJRVklzUTBGQlNpeERRVVEwUWp0QlFVVm9ReXd5UWtGQlR5eEZRVUZGTEVsQlFVa3NRMEZCU2l4SFFVRlJMRU5CUVZJc1EwRkJWQ3hEUVVablF6dHBRa0ZCV2l4RlFVZHlRaXhEUVVoSUxFVkJSMDBzUlVGQlJTeFBRVUZHTEVWQlFWY3NRMEZJYWtJc1JVRkhiMElzUTBGSWNFSXNSVUZIZFVJc1EwRklka0lzUlVGSE1FSXNRMEZJTVVJc1JVRllUenRoUVVGWU8wRkJaMEpCTEcxQ1FVRlBMRVZCUVVVc1EwRkJSaXhGUVVGTExFOUJRVXdzUTBGcVFrMDdVMEZCYWtJN1FVRnRRa0VzV1VGQlNTeEpRVUZKTEU5QlFVOHNUMEZCVUN4SlFVRnJRaXhWUVVGc1FpeEpRVUZuUXl4UFFVRm9ReXhEUVhCQ1dUdEJRWEZDY0VJc1lVRkJTeXhKUVVGSkxFbEJRVWtzUTBGQlNpeEZRVUZQTEVsQlFVa3NSVUZCUlN4TlFVRkdMRVZCUVZVc1IwRkJPVUlzUlVGQmJVTXNSVUZCUlN4RlFVRkZMRU5CUVVZc1EwRkJSaXhGUVVGdVF6dEJRVU5CTEdWQlFVOHNRMEZCVUN4RFFYUkNiMEk3UzBGQmNFSXNRMEYxUWtRN1FVRkRTeXhYUVVGSExFTkJRVU1zVlVGQlV5eFBRVUZVTEVWQlFXdENMRTFCUVd4Q0xFVkJRVEJDTEU5QlFURkNMRVZCUVcxRE96dEJRVVV6UkN4blFrRkJTU3huUWtGQlowSXNVVUZCVVN3d1FrRkJVaXhEUVVGb1FpeERRVVoxUkRzN1FVRkpNMFFzYlVKQlFVOHNUMEZCVUN4SFFVRnBRaXhoUVVGcVFpeERRVW95UkR0VFFVRnVReXhGUVUxMFFpeEZRVUZETERSQ1FVRXlRaXhGUVVFelFpeEZRVTV2UWl4RFFVRklMRVZCVFdVc1IwRkJSU3hEUVVGRExGVkJRVk1zVDBGQlZDeEZRVUZwUWl4TlFVRnFRaXhGUVVGM1FpeFBRVUY0UWl4RlFVRm5RenRCUVVOMFJTeG5Ra0ZCU1N4UFFVRlBMRkZCUVZFc2FVSkJRVklzUTBGQlVDeERRVVJyUlRzN1FVRkhkRVVzYlVKQlFVOHNUMEZCVUN4SFFVRnBRaXhKUVVGcVFpeERRVWh6UlR0VFFVRm9ReXhGUVV0d1F5eEZRVUZETEcxQ1FVRnJRaXhGUVVGc1FpeEZRVXhyUXl4RFFVRkdMRVZCUzFRc1IwRkJSU3hEUVVGRExGVkJRVk1zVDBGQlZDeEZRVUZwUWl4TlFVRnFRaXhGUVVGM1FpeFBRVUY0UWl4RlFVRm5RenRCUVVNM1JDeG5Ra0ZCU1N4SlFVRkpMRkZCUVZFc1owTkJRVklzUTBGQlNpeERRVVI1UkRzN1FVRkhOMFFzYlVKQlFVOHNUMEZCVUN4SFFVRnBRaXhEUVVGcVFpeERRVWcyUkR0VFFVRm9ReXhGUVVzelFpeEZRVUZETEd0RFFVRnBReXhGUVVGcVF5eEZRVXg1UWl4RFFVRkdMRVZCUzJVc1IwRkJSU3hEUVVGRExGVkJRVk1zVDBGQlZDeEZRVUZwUWl4TlFVRnFRaXhGUVVGM1FpeFBRVUY0UWl4RlFVRm5RenRCUVVNMVJTeG5Ra0ZCU1N4UFFVRlBMRkZCUVZFc1YwRkJVaXhEUVVGUUxFTkJSSGRGTzBGQlJUVkZMR2RDUVVGSkxGRkJRVkVzVVVGQlVTeFpRVUZTTEVOQlFWSXNRMEZHZDBVN1FVRkhOVVVzWjBKQlFVa3NTVUZCU1N4UlFVRlJMRkZCUVZJc1EwRkJTaXhEUVVoM1JUdEJRVWsxUlN4blFrRkJTU3hUUVVGVExGRkJRVkVzY1VKQlFWSXNRMEZCVkN4RFFVcDNSVHRCUVVzMVJTeG5Ra0ZCU1N4UlFVRlJMRkZCUVZFc2EwSkJRVklzUTBGQlVpeERRVXgzUlR0QlFVMDFSU3huUWtGQlNTeFJRVUZSTEZGQlFWRXNhMEpCUVZJc1EwRkJVaXhEUVU1M1JUczdRVUZSTlVVc2JVSkJRVThzVDBGQlVDeEhRVUZwUWp0QlFVTmlMSE5DUVVGTkxFbEJRVTQ3UVVGRFFTeDFRa0ZCVHl4TFFVRlFPMEZCUTBFc2JVSkJRVWNzUTBGQlNEdEJRVU5CTEhkQ1FVRlJMRTFCUVZJN1FVRkRRU3gxUWtGQlR5eExRVUZRTzBGQlEwRXNkVUpCUVU4c1MwRkJVRHRoUVU1S0xFTkJValJGTzFOQlFXaERMRVZCYVVJeFF5eEZRVUZETEhWQ1FVRnpRaXhEUVVGMFFpeEZRVUYzUWl4aFFVRlpMRU5CUVZvc1JVRkJZeXhWUVVGVExFTkJRVlFzUlVGQlZ5eGpRVUZoTEVWQlFXSXNSVUZCWjBJc2IwSkJRVzFDTEVWQlFXNUNMRVZCUVhOQ0xHOUNRVUZ0UWl4RlFVRnVRaXhGUVdwQ0wwTXNRMEZCUml4RlFXbENlVVVzUjBGQlJTeERRVUZETEZWQlFWTXNUMEZCVkN4RlFVRnBRaXhOUVVGcVFpeEZRVUYzUWl4UFFVRjRRaXhGUVVGblF6czdPenM3T3pzN096czdPenM3T3pzN096czdPenM3T3pzN096czdPenM3UVVGblEzSktMRzFDUVVGUExFOUJRVkFzUjBGQmFVSXNVMEZCVlN4TFFVRlVMRU5CUVdVc1MwRkJaaXhGUVVGelFqczdRVUZGZEVNc2IwSkJRVWtzWTBGQll5eFBRVUZQTEZOQlFWQXNRMEZCYVVJc1MwRkJha0k3YjBKQlEyaENMRzlDUVVGdlFpeFBRVUZQTEVsQlFWQXNRMEZCV1N4RlFVRmFMRVZCUVdkQ0xFTkJRV2hDTEUxQlFYVkNMRXRCUVhaQ096czdRVUZGY0VJc2IwSkJTRVlzUTBGR2MwTTdPMEZCVDNSRExIVkNRVUZQTEZWQlFWTXNSMEZCVkN4RlFVRmpMRk5CUVdRc1JVRkJlVUlzUzBGQmVrSXNSVUZCWjBNN08wRkJSWEpETEhkQ1FVRkpMRTlCUVU4c1UwRkJVQ3hEUVVGcFFpeFJRVUZxUWl4RFFVRXdRaXhKUVVFeFFpeERRVUVyUWl4VFFVRXZRaXhOUVVFNFF5eHBRa0ZCT1VNc1JVRkJhVVU3UVVGRGJrVXNLMEpCUVU4c1dVRkJXU3hKUVVGYUxFTkJRV2xDTEVkQlFXcENMRVZCUVhOQ0xGTkJRWFJDTEVWQlFXbERMRXRCUVdwRExFTkJRVkFzUTBGRWJVVTdjVUpCUVhKRk8wRkJSMEVzZDBKQlFVa3NVMEZCVXl4RlFVRlVPM2RDUVVOR0xGRkJRVkVzUTBGQlF5eFZRVUZWTEZWQlFWWXNSMEZCZFVJc1IwRkJka0lzUjBGQk5rSXNSVUZCTjBJc1EwRkJSQ3hKUVVGeFF5eFZRVUZWTEZOQlFWWXNSMEZCYzBJc1IwRkJkRUlzUjBGQk5FSXNSVUZCTlVJc1EwRkJja01zU1VGQmQwVXNWVUZCVlN4UlFVRldMRWRCUVhGQ0xFZEJRWEpDTEVkQlFUSkNMRVZCUVROQ0xFTkJRWGhGTzBGQlExQXNPRUpCUVZVc1RVRkJWaXhIUVVGdFFpeEhRVUZ1UWl4SFFVRjVRaXhGUVVGNlFpeERRVVJQT3pzN1FVRkhVaXh2UTBGQlowSXNRMEZCYUVJN096dEJRVVZCTEdkRFFVRlpMRWxCUVVrc1RVRkJTaXhEUVVGWExGVkJRVlVzVFVGQlZpeEZRVUZyUWl4UlFVRlJMRWRCUVZJc1EwRkJla003ZDBKQlEwRXNWVUZRUmp0M1FrRlBZeXhMUVZCa08zZENRVTl4UWl4VFFWQnlRanQzUWtGUFowTXNWVUZRYUVNc1EwRk1jVU03UVVGaGNrTXNNa0pCUVU4c1JVRkJVRHRCUVdKeFF5eDNRa0ZqYWtNc1EwRkJReXhwUWtGQlJDeEZRVUZ2UWpzN1FVRkZkRUlzY1VOQlFXRXNTVUZCU1N4TlFVRktMRU5CUVZjc1RVRkJUU3hWUVVGVkxFMUJRVllzUjBGQmJVSXNWVUZCZWtJc1JVRkJjVU1zUzBGQmFFUXNRMEZCWWl4RFFVWnpRanR4UWtGQmVFSTdPenM3T3pzN08wRkJaSEZETEhsQ1FYbENja01zUjBGQlVTeFZRVUZWTEV0QlFWWXNSMEZCYTBJc1EwRkJReXhEUVVGRUxFdEJRVThzUTBGQlVEdEJRVU14UWl3NFFrRkJWU3hEUVVGV08wRkJNVUp4UXl3eVFrRXlRamxDTEZGQlFWRXNWVUZCVlN4SlFVRldMRU5CUVdVc1IwRkJaaXhEUVVGU0xFVkJRVFpDT3p0QlFVVnNReXh2UTBGQldTeE5RVUZOTEV0QlFVNHNSMEZCWXl4TlFVRk5MRU5CUVU0c1JVRkJVeXhOUVVGVUxFTkJSbEU3UVVGSGJFTXNORUpCUVVrc1dVRkJXU3hoUVVGYUxFVkJRVEpDTzBGQlF6ZENMRzFEUVVGUExFbEJRVkFzUTBGQldTeEpRVUZKTEV0QlFVb3NRMEZCVlN4aFFVRldMRVZCUVhsQ0xFMUJRVTBzUzBGQlRpeERRVUZ5UXpzN08wRkJSRFpDTEdkRFFVbDZRaXhEUVVGRExHbENRVUZFTEVsQlFYTkNMRTFCUVUwc1RVRkJUaXhIUVVGbExFTkJRV1lzUlVGQmEwSTdRVUZETVVNc2MwTkJRVTBzUTBGQlRpeEZRVUZUTEU5QlFWUXNRMEZCYVVJc1ZVRkJha0lzUlVGQk5rSXNXVUZCVnp0QlFVTjBReXg1UTBGQlN5eEpRVUZKTEVsQlFVa3NRMEZCU2l4RlFVRlBMRWxCUVVrc1ZVRkJWU3hOUVVGV0xFZEJRVzFDTEVOQlFXNUNMRVZCUVhOQ0xFZEJRVEZETEVWQlFTdERPMEZCUXpkRExEUkRRVUZKTEZWQlFWVXNRMEZCVml4TlFVRnBRaXhMUVVGcVFpeEZRVUYzUWp0QlFVTXhRaXhyUkVGQlRTeERRVUZPTEVsQlFWY3NTMEZCV0N4RFFVUXdRanQ1UTBGQk5VSTdjVU5CUkVZN2FVTkJSREpDTEVOQlFUZENMRU5CUkRCRE96WkNRVUUxUXp0QlFWTkJMR2REUVVGSkxFMUJRVTBzVFVGQlRpeEhRVUZsTEVOQlFXWXNTVUZCYjBJc1RVRkJUU3hMUVVGT0xFZEJRV01zU1VGQlNTeE5RVUZLTEVWQlFWazdRVUZEYUVRc2MwTkJRVTBzVTBGQlRpeERRVUZuUWl4SlFVRm9RaXhEUVVGeFFpeExRVUZ5UWl4RFFVRXlRaXhOUVVFelFpeEZRVUZ0UXl4TlFVRk5MRXRCUVU0c1EwRkJXU3hEUVVGYUxFTkJRVzVETEVWQlJHZEVPelpDUVVGc1JEdEJRVWRCTEhsRFFVRmhMRTFCUVUwc1EwRkJUaXhGUVVGVExFMUJRVlFzUTBGb1FtZENPMEZCYVVJM1FpdzBRMEZCWjBJc1UwRkJhRUlzUTBGcVFqWkNPMEZCYTBJM1FpeG5RMEZCU1N4UFFVRlBMRTFCUVZBc1NVRkJhVUlzUzBGQmFrSXNSVUZCZDBJN1FVRkRNVUlzYzBOQlJEQkNPelpDUVVFMVFqdDVRa0ZzUWtZN1FVRnpRa0VzTkVKQlFVa3NWVUZCVlN4VFFVRldMRXRCUVhkQ0xFMUJRVTBzUzBGQlRpeEZRVUZoTzBGQlEzWkRMSE5EUVVGVkxGTkJRVlk3UVVGRWRVTXNlVUpCUVhwRE8zRkNRWHBDUmp0QlFUWkNRU3gzUWtGQlNTeHJRa0ZCYTBJc1NVRkJTU3hOUVVGS0xFVkJRVms3UVVGRGFFTXNORUpCUVVrc1kwRkJZeXhEUVVGRExGVkJRVlVzU1VGQlZpeERRVUZsTEVWQlFXWXNRMEZCUkN4RlFVRnhRanRCUVVOeVF5eHRRMEZCVHl4SlFVRlFMRU5CUVZrc1JVRkJXaXhGUVVSeFF6dDVRa0ZCZGtNN2NVSkJSRVlzVFVGSlR6dEJRVU5NTEN0Q1FVRlBMRWxCUVZBc1EwRkJXU3hKUVVGSkxFdEJRVW9zUTBGQlZTeGhRVUZXTEVOQlFWb3NSVUZFU3p0eFFrRktVRHRCUVU5QkxESkNRVUZQTEU5QlFVOHNUVUZCVUN4SFFVRm5RaXhMUVVGb1FpeEhRVUYzUWl4UFFVRlBMRXRCUVZBc1EwRkJZU3hEUVVGaUxFVkJRV2RDTEV0QlFXaENMRU5CUVhoQ0xFZEJRV2xFTEUxQlFXcEVMRU5CTDBRNFFqdHBRa0ZCYUVNc1EwRlFLMEk3TzBGQmVVVjBReXgxUWtGQlR5eEpRVUZRTEVOQmVrVnpRenRoUVVGMFFpeEZRVUZzUWl4RFFXaERjVW83VTBGQmFFTXNSVUUwUjI1SUxFVkJOVWRyU0N4RFFVRkdMRVZCTkVjMVJ5eEhRVUZGTEVOQlFVTXNWVUZCVXl4UFFVRlVMRVZCUVdsQ0xFMUJRV3BDTEVWQlFYZENMRTlCUVhoQ0xFVkJRV2RETEVWQlFXaERMRVZCUlZBc1JVRkdUU3hEUVVGR0xFVkJSVUVzUjBGQlJTeERRVUZETEZWQlFWTXNUMEZCVkN4RlFVRnBRaXhOUVVGcVFpeEZRVUYzUWl4UFFVRjRRaXhGUVVGblF6dEJRVU42UXl4NVFrRkVlVU03TzBGQlIzcERMR2RDUVVGSkxIVkNRVUYxUWl4UlFVRlJMSGRDUVVGU0xFTkJRWFpDTEVOQlNIRkRPenRCUVV0NlF5eG5Ra0ZCU1N4aFFVRmhMRWRCUVdJc1EwRk1jVU03UVVGTmVrTXNhVU5CUVhGQ0xGVkJRWEpDTEVWQlFXbERMRlZCUVdwRExFVkJUbmxET3p0QlFWRjZReXhuUWtGQlNTeFZRVUZWTEc5Q1FVRnZRaXhWUVVGd1FpeERRVkl5UWpzN1FVRlZla01zYlVKQlFVOHNUMEZCVUN4SFFVRnBRaXhQUVVGcVFpeERRVlo1UXpzN1FVRlpla01zY1VKQlFWTXNUMEZCVkN4RFFVRnBRaXhKUVVGcVFpeEZRVUYxUWp0QlFVTnVRaXh2UWtGQlNTeFBRVUZQTEV0QlFVc3NUMEZCVEN4RFFVRlFMRU5CUkdVN08wRkJSMjVDTEc5Q1FVRkpMRU5CUVVNc1NVRkJSQ3hGUVVGUE8wRkJRMUFzTWtKQlFVOHNTMEZCU3l4UFFVRk1MRWxCUVdkQ0xFVkJRV2hDTEVOQlJFRTdhVUpCUVZnN08wRkJTVUVzZFVKQlFVOHNTVUZCVUN4RFFWQnRRanRoUVVGMlFqdFRRVnBUTEVWQmMwSlFMRVZCUVVNc01FSkJRWGxDTEVOQlFYcENMRVZCZEVKTExFTkJRVVlzUlVGelFqQkNMRWRCUVVVc1EwRkJReXhWUVVGVExFOUJRVlFzUlVGQmFVSXNUVUZCYWtJc1JVRkJkMElzVDBGQmVFSXNSVUZCWjBNN1FVRkRia1VzWVVGQlF5eFZRVUZWTEUxQlFWWXNSVUZCYVVJN1FVRkRiRUk3T3pzN1FVRkVhMElzYjBKQlMyUXNUMEZCVHl4UFFVRlBMRTFCUVZBc1MwRkJhMElzVjBGQmJFSXNSMEZEVUN4TlFVUlBMRWRCUTBVc1QwRkJUeXhOUVVGUUxFdEJRV3RDTEZkQlFXeENMRWRCUTFRc1RVRkVVeXhIUVVOQkxFVkJSRUVzUTBGT1N6czdRVUZUYkVJc2RVSkJRVThzVDBGQlVDeEhRVUZwUWl4VlFVRnFRaXhEUVZSclFqczdRVUZYYkVJc2VVSkJRVk1zVlVGQlZDeERRVUZ2UWl4SFFVRndRaXhGUVVGNVFpeExRVUY2UWl4RlFVRm5RenRCUVVNMVFpeDNRa0ZCU1N4UFFVRlBMRWxCUVZBc1JVRkJZVHRCUVVOaUxDdENRVUZQTEV0QlFVc3NSMEZCVEN4RFFVRlFMRU5CUkdFN2NVSkJRV3BDT3p0QlFVbEJMSGxDUVVGTExFZEJRVXdzU1VGQldTeExRVUZhTEVOQlREUkNPenRCUVU4MVFpd3lRa0ZCVHl4TFFVRlFMRU5CVURSQ08ybENRVUZvUXp0aFFWaERMRU5CUVVRc1EwRnhRa2NzU1VGeVFrZ3NRMEZ4UWxFc1NVRnlRbElzUlVGeFFtRXNUMEZCVHl4TlFVRlFMRXRCUVd0Q0xGZEJRV3hDTEVkQlFXZERMRTFCUVdoRExFZEJRWGxETEU5QlFVOHNTVUZCVUN4TFFVRm5RaXhYUVVGb1FpeEhRVUU0UWl4SlFVRTVRaXhIUVVGeFF5eFBRVUZQTEUxQlFWQXNTMEZCYTBJc1YwRkJiRUlzUjBGQlowTXNUVUZCYUVNc1IwRkJlVU1zUlVGQmVrTXNRMEZ5UWpOR0xFTkJSRzFGTzFOQlFXaERMRVZCZFVKcVF5eEZRWFpDWjBNc1EwRkJSaXhGUVhWQ01VSXNSMEZCUlN4RFFVRkRMRlZCUVZNc1QwRkJWQ3hGUVVGcFFpeE5RVUZxUWl4RlFVRjNRaXhQUVVGNFFpeEZRVUZuUXp0QlFVTjZReXg1UWtGRWVVTTdPMEZCUjNwRExHZENRVUZKTEdGQlFXRXNVVUZCVVN4WlFVRlNMRU5CUVdJc1EwRkljVU03TzBGQlMzcERMRzFDUVVGUExFOUJRVkFzUjBGQmFVSXNWVUZCYWtJc1EwRk1lVU03TzBGQlQzcERMSEZDUVVGVExGVkJRVlFzUTBGQmIwSXNWVUZCY0VJc1JVRkJaME1zVDBGQmFFTXNSVUZCZVVNc1dVRkJla01zUlVGQmRVUTdRVUZEYmtRc2IwSkJRVWtzVFVGQlRTdzRRa0ZCT0VJc1ZVRkJPVUlzUTBGRWVVTTdRVUZGYmtRc2IwSkJRVWtzWVVGQllTeE5RVUZOTEc5Q1FVRk9MRU5CUm10RE96dEJRVWx1UkN4dlFrRkJTU3hsUVVGbExGZEJRVmNzVlVGQldDeEZRVUYxUWl4UFFVRjJRaXhEUVVGbUxFTkJTaXRET3p0QlFVMXVSQ3h2UWtGQlNTeHBRa0ZCYVVJc1QwRkJha0lzUlVGQk1FSTdRVUZETVVJc01FSkJRVTBzU1VGQlNTeExRVUZLTEVOQlFWVXNLMEpCUTFvc1ZVRkVXU3hIUVVORExFdEJSRVFzUjBGRldpd3lRa0ZHV1N4SFFVVnJRaXhaUVVac1FpeEhRVWRhTEdWQlNGa3NSMEZKV2l4M1EwRktXU3hIUVVrclFpeFBRVW92UWl4RFFVRm9RaXhEUVVRd1FqdHBRa0ZCT1VJN08wRkJVVUVzZFVKQlFVOHNWMEZCVnl4SFFVRllMRVZCUVdkQ0xGbEJRV2hDTEVOQlFWQXNRMEZrYlVRN1lVRkJka1E3VTBGUVV5eEZRWGRDVUN4RlFVRkRMR05CUVdFc1EwRkJZaXhGUVhoQ1N5eERRVUZHTEVWQmQwSmpMRWxCUVVjc1EwRkJReXhWUVVGVExFOUJRVlFzUlVGQmFVSXNUVUZCYWtJc1JVRkJkMElzVDBGQmVFSXNSVUZCWjBNN1FVRkRlRVFzWVVGQlF5eFZRVUZWTEUxQlFWWXNSVUZCYVVJN1FVRkRiRUlzYjBKQlFVa3NWMEZCVnl4UFFVRlBMRTFCUVZBc1MwRkJhMElzVjBGQmJFSXNSMEZCWjBNc1RVRkJhRU1zUjBGRFdDeFBRVUZQTEUxQlFWQXNTMEZCYTBJc1YwRkJiRUlzUjBGQlowTXNUVUZCYUVNc1IwRkJlVU1zUlVGQmVrTXNRMEZHWXp0QlFVZHNRaXh2UWtGQlNTeFRRVUZUTEZGQlFWRXNZMEZCVWl4RFFVRlVMRU5CU0dNN08wRkJTMnhDTEc5Q1FVRkpMRTlCUVU4c1VVRkJVQ3hMUVVGdlFpeFhRVUZ3UWl4RlFVRnBRenRCUVVOcVF5d3lRa0ZCVHl4UFFVRlFMRWRCUVdsQ0xGRkJRV3BDTEVOQlJHbERPMmxDUVVGeVF5eE5RVVZQTzBGQlEwZ3NkMEpCUVVrc1VVRkJVU3hUUVVGVExESkNRVUZVTEVOQlFWSXNRMEZFUkRzN1FVRkhTQ3gzUWtGQlNTeERRVUZETEV0QlFVUXNSVUZCVVR0QlFVTlNMR2REUVVGUkxGTkJRVk1zTWtKQlFWUXNTVUZCZDBNc1RVRkJlRU1zUTBGRVFUdHhRa0ZCV2pzN1FVRkpRU3d5UWtGQlR5eFBRVUZRTEVkQlFXbENMRXRCUVdwQ0xFTkJVRWM3YVVKQlJsQTdZVUZNUXl4RFFVRkVMRU5CYVVKSExFbEJha0pJTEVOQmFVSlJMRWxCYWtKU0xFVkJhVUpoTEU5QlFVOHNUVUZCVUN4TFFVRnJRaXhYUVVGc1FpeEhRVUZuUXl4TlFVRm9ReXhIUVVGNVF5eFBRVUZQTEVsQlFWQXNTMEZCWjBJc1YwRkJhRUlzUjBGQk9FSXNTVUZCT1VJc1IwRkJjVU1zVDBGQlR5eE5RVUZRTEV0QlFXdENMRmRCUVd4Q0xFZEJRV2RETEUxQlFXaERMRWRCUVhsRExFVkJRWHBETEVOQmFrSXpSaXhEUVVSM1JEdFRRVUZvUXl4RlFXMUNkRUlzUlVGQlF5eG5Ra0ZCWlN4RFFVRm1MRVZCYmtKdlFpeERRVUZJTEVWQmJVSkZMRWxCUVVjc1EwRkJReXhWUVVGVExFOUJRVlFzUlVGQmFVSXNUVUZCYWtJc1JVRkJkMElzVDBGQmVFSXNSVUZCWjBNN1FVRkRNVVFzZVVKQlJEQkVPenRCUVVjeFJDeHRRa0ZCVHl4UFFVRlFMRWRCUVdsQ0xGTkJRVk1zVVVGQlZDeERRVUZyUWl4RFFVRnNRaXhGUVVGeFFqdEJRVU55UXl4MVFrRkJUeXhQUVVGUExFTkJRVkFzUzBGQllTeFJRVUZpTEVsQlFYbENMRTFCUVUwc1NVRkJUaXhEUVVSTE8yRkJRWEpDTEVOQlNIbERPMU5CUVdoRExFVkJUM2hDTEVWQlVIVkNMRU5CUVVnc1JVRlBhRUlzU1VGQlJ5eERRVUZETEZWQlFWTXNUMEZCVkN4RlFVRnBRaXhOUVVGcVFpeEZRVUYzUWl4UFFVRjRRaXhGUVVGblF6dEJRVU14UXl4blFrRkJTU3huUWtGQlowSXNUVUZCVFN4UFFVRk9MRU5CUkhOQ08wRkJSVEZETEdkQ1FVRkpMRmRCUVZjc1QwRkJUeXhUUVVGUUxFTkJRV2xDTEZGQlFXcENMRU5CUmpKQ096dEJRVWt4UXl4dFFrRkJUeXhQUVVGUUxFZEJRV2xDTEdsQ1FVRnBRaXhQUVVGcVFpeERRVXA1UWpzN1FVRk5NVU1zY1VKQlFWTXNUMEZCVkN4RFFVRnBRaXhIUVVGcVFpeEZRVUZ6UWp0QlFVTnNRaXgxUWtGQlR5eFRRVUZUTEVsQlFWUXNRMEZCWXl4SFFVRmtMRTFCUVhWQ0xHZENRVUYyUWl4RFFVUlhPMkZCUVhSQ08xTkJUbFVzUlVGVlVpeEZRVlpQTEVOQlFVZ3NSVUZWUVN4SlFVRkhMRU5CUVVNc1ZVRkJVeXhQUVVGVUxFVkJRV2xDTEUxQlFXcENMRVZCUVhkQ0xFOUJRWGhDTEVWQlFXZERPMEZCUXpGRExHZENRVUZKTEZGQlFWRXNVVUZCVVN4cFFrRkJVaXhEUVVGU0xFTkJSSE5ET3p0QlFVY3hReXh0UWtGQlR5eFBRVUZRTEVkQlFXbENMRXRCUVdwQ0xFTkJTREJETzFOQlFXaERMRVZCUzFJc1JVRkJReXh0UWtGQmEwSXNSVUZCYkVJc1JVRk1UU3hEUVVGSUxFVkJTMjlDTEVsQlFVY3NRMEZCUXl4VlFVRlRMRTlCUVZRc1JVRkJhVUlzVFVGQmFrSXNSVUZCZDBJc1QwRkJlRUlzUlVGQlowTTdRVUZET1VRc1owSkJRVWtzVjBGQlZ5eFJRVUZSTEZkQlFWSXNRMEZCV0N4RFFVUXdSRHRCUVVVNVJDeG5Ra0ZCU1N4VFFVRlRMRkZCUVZFc2MwSkJRVklzUTBGQlZDeERRVVl3UkRzN1FVRkpPVVFzYlVKQlFVOHNUMEZCVUN4SFFVRnBRaXhsUVVGcVFpeERRVW80UkRzN1FVRk5PVVFzY1VKQlFWTXNaVUZCVkN4RFFVRjVRaXhKUVVGNlFpeEZRVUVyUWl4TFFVRXZRaXhGUVVGelF5eFJRVUYwUXl4RlFVRm5SRHRCUVVNMVF5eHhRa0ZCU3l4SlFVRkpMRkZCUVVvc1NVRkJaMElzUzBGQmNrSXNSVUZCTkVJN1FVRkRlRUlzZDBKQlFVa3NXVUZCV1N4TlFVRk5MRkZCUVU0c1EwRkJXaXhEUVVSdlFqczdRVUZIZUVJc2QwSkJRVWtzWTBGQll5eFRRVUZrTEVWQlFYbENPMEZCUTNwQ0xIVkRRVUZsTEVsQlFXWXNSVUZCY1VJc1VVRkJja0lzUlVGQkswSXNVMEZCTDBJc1JVRkJNRU1zVVVGQk1VTXNSVUZFZVVJN2NVSkJRVGRDTEUxQlJVOHNTVUZCU1N4UFFVRlBMRk5CUVZBc1EwRkJTaXhGUVVGMVFqdEJRVU14UWl4MVEwRkJaU3hKUVVGbUxFVkJRWEZDTEZGQlFYSkNMRVZCUVN0Q0xGTkJRUzlDTEVWQlFUQkRMRkZCUVRGRExFVkJSREJDTzBGQlJURkNMRFJDUVVGSkxGVkJRVlVzU1VGQlZpeEZRVUZuUWp0QlFVTm9RaXh6UTBGQlZTeEpRVUZXTEVOQlFXVXNTVUZCWml4RlFVTkpMRkZCUkVvc1JVRkZTU3hYUVVGWExGTkJRVk1zVVVGQlZDeERRVUZZTEVkQlFXZERMRk5CUVdoRExFTkJSa29zUTBGRVowSTdlVUpCUVhCQ08zRkNRVVpITEUxQlQwRTdRVUZEU0N3MFFrRkJTU3hUUVVGVExGTkJRVlFzUTBGQlNpeEZRVUY1UWp0QlFVTnlRaXgzUTBGQldTeEpRVUZhTEVWQlFXdENMRXRCUVd4Q0xFVkJRWGxDTEZGQlFYcENMRVZCUVcxRExGRkJRVzVETEVWQlFUWkRMRk5CUVRkRExFVkJSSEZDTzNsQ1FVRjZRaXhOUVVWUE8wRkJRMGdzYVVOQlFVc3NVVUZCVEN4SlFVRnBRaXhUUVVGcVFpeERRVVJITzNsQ1FVWlFPM0ZDUVZKSE8ybENRVXhZTzJGQlJFbzdPMEZCZFVKQkxIRkNRVUZUTEdOQlFWUXNRMEZCZDBJc1NVRkJlRUlzUlVGQk9FSXNVVUZCT1VJc1JVRkJkME1zVTBGQmVFTXNSVUZCYlVRc1VVRkJia1FzUlVGQk5rUTdRVUZEZWtRc2IwSkJRVWtzVVVGQlNpeEZRVUZqTzBGQlExWXNkMEpCUVVrc1owSkJRV2RDTEZOQlFWTXNVVUZCVkN4RFFVRm9RaXhEUVVSTk96dEJRVWRXTEhkQ1FVRkpMRU5CUVVNc1QwRkJUeXhoUVVGUUxFTkJRVVFzUlVGQmQwSTdRVUZEZUVJc05FSkJRVWtzWVVGQllTeFpRVUZpTEVWQlFUSkNPMEZCUXpOQ0xHbERRVUZMTEVsQlFVa3NVVUZCU2l4SlFVRm5RaXhoUVVGeVFpeEZRVUZ2UXp0QlFVTm9ReXh4UTBGQlN5eGxRVUZNTEVOQlFYRkNMRkZCUVhKQ0xFVkJSR2RET3paQ1FVRndRenQ1UWtGRVNpeE5RVWxQTEVsQlFVa3NZVUZCWVN4UFFVRmlMRVZCUVhOQ08wRkJRemRDTEdsRFFVRkxMRWxCUVVrc1EwRkJTaXhKUVVGVExHRkJRV1FzUlVGQk5rSTdRVUZEZWtJc2NVTkJRVXNzUzBGQlRDeERRVUZYTEVOQlFWZ3NTVUZCWjBJc1JVRkJhRUlzUTBGRWVVSTdOa0pCUVRkQ08zbENRVVJITEUxQlNVRXNTVUZCU1N4UFFVRlBMR0ZCUVZBc1MwRkJlVUlzVVVGQmVrSXNSVUZCYlVNN1FVRkRNVU1zYVVOQlFVc3NVVUZCVEN4SlFVRnBRaXhGUVVGcVFpeERRVVF3UXp0NVFrRkJka01zVFVGRlFUdEJRVU5JTEdsRFFVRkxMRkZCUVV3c1NVRkJhVUlzU1VGQmFrSXNRMEZFUnp0NVFrRkdRVHR4UWtGVVdDeE5RV05QTEVsQlFVa3NZMEZCWXl4TlFVRmtMRVZCUVhOQ08wRkJRemRDTEhORFFVRmpMRTFCUVdRc1EwRkJjVUlzU1VGQmNrSXNSVUZCTWtJc1VVRkJNMElzUlVGQmNVTXNVMEZCY2tNc1JVRkVOa0k3Y1VKQlFURkNPMmxDUVdwQ1dEdGhRVVJLT3p0QlFYZENRU3h4UWtGQlV5eFhRVUZVTEVOQlFYRkNMRWxCUVhKQ0xFVkJRVEpDTEV0QlFUTkNMRVZCUVd0RExGRkJRV3hETEVWQlFUUkRMRkZCUVRWRExFVkJRWE5FTEZOQlFYUkVMRVZCUVdsRk8wRkJRemRFTEc5Q1FVRkpMR2RDUVVGblFpeFhRVUZYTEZOQlFWTXNVVUZCVkN4RFFVRllMRWRCUVdkRExGTkJRV2hET3pzN1FVRkVlVU1zYjBKQlNYcEVMR0ZCUVdFc1dVRkJZaXhGUVVFeVFqdEJRVU16UWl4NVFrRkJTeXhKUVVGSkxGRkJRVW9zU1VGQlowSXNVMEZCY2tJc1JVRkJaME03UVVGRE5VSXNORUpCUVVrc1dVRkJXU3hWUVVGVkxGRkJRVllzUTBGQldpeERRVVIzUWpzN1FVRkhOVUlzTkVKQlFVa3NZMEZCWXl4VFFVRmtMRVZCUVhsQ08wRkJRM3BDTEdsRFFVRkxMR1ZCUVV3c1EwRkJjVUlzVVVGQmNrSXNSVUZFZVVJN2VVSkJRVGRDTEUxQlJVODdRVUZEU0N4cFEwRkJTeXhaUVVGTUxFTkJRV3RDTEZGQlFXeENMRVZCUVRSQ0xGTkJRVFZDTEVWQlJFYzdlVUpCUmxBN2NVSkJTRW83TzBGQlZVRXNNa0pCV0RKQ08ybENRVUV2UWpzN1FVRmpRU3h2UWtGQlJ5eHBRa0ZCYVVJc1UwRkJVeXhoUVVGVUxFTkJRV3BDTEVsQlEwTXNZVUZCWVN4aFFVRmlMRTFCUVdkRExHRkJRV0VzVTBGQllpeERRVUZvUXl4RlFVRjVSRHRCUVVONlJDeDVRa0ZCU3l4UlFVRk1MRWxCUVdsQ0xGTkJRV3BDTEVOQlJIbEVPMEZCUlhwRUxESkNRVVo1UkR0cFFrRkVOMFE3TzBGQlRVRXNiMEpCUVVrc1EwRkJReXhUUVVGVExFdEJRVXNzVVVGQlRDeERRVUZVTEVOQlFVUXNSVUZCTWtJN1FVRkRNMElzZVVKQlFVc3NVVUZCVEN4SlFVRnBRaXhGUVVGcVFpeERRVVF5UWp0cFFrRkJMMEk3TzBGQlNVRXNiMEpCUVVrc1YwRkJWeXhoUVVGaExFOUJRV0lzUjBGQmRVSXNSVUZCZGtJc1IwRkJORUlzVTBGQk5VSXNRMEUxUWpoRE96dEJRVGhDTjBRc2NVSkJRVXNzU1VGQlNTeERRVUZLTEVsQlFWTXNVMEZCWkN4RlFVRjVRanRCUVVOeVFpeDNRa0ZCU1N4UlFVRlJMRlZCUVZVc1EwRkJWaXhEUVVGU0xFTkJSR2xDTzBGQlJYSkNMSGxDUVVGTExGRkJRVXdzUlVGQlpTeERRVUZtTEVsQlFXOUNMRXRCUVVNc1MwRkJWU3hUUVVGV0xFZEJRWFZDTEZGQlFYaENMRWRCUVcxRExFdEJRVzVETEVOQlJrTTdhVUpCUVhwQ08yRkJPVUpLT3p0QlFXOURRU3h4UWtGQlV5eFpRVUZVTEVOQlFYTkNMRXRCUVhSQ0xFVkJRVFpDTzBGQlEzcENMRzlDUVVGSkxFOUJRVThzWTBGQlVDeEZRVUYxUWp0QlFVTjJRaXd5UWtGQlR5eFBRVUZQTEdOQlFWQXNRMEZCYzBJc1MwRkJkRUlzUTBGQlVDeERRVVIxUWp0cFFrRkJNMElzVFVGRlR5eEpRVUZKTEUxQlFVMHNVMEZCVGl4RlFVRnBRanRCUVVONFFpd3lRa0ZCVHl4TlFVRk5MRk5CUVU0c1EwRkVhVUk3YVVKQlFYSkNMRTFCUlVFc1NVRkJTU3hOUVVGTkxGZEJRVTRzUlVGQmJVSTdRVUZETVVJc01rSkJRVThzVFVGQlRTeFhRVUZPTEVOQlFXdENMRk5CUVd4Q0xFTkJSRzFDTzJsQ1FVRjJRanRoUVV4WU8xTkJla1k0UWl4RlFXMUhOVUlzUlVGQlF5eDNRa0ZCZFVJc1JVRkJka0lzUlVGQk1FSXNZVUZCV1N4RlFVRmFMRVZCYmtkQkxFTkJRVWdzUlVGdFIyOUNMRWxCUVVjc1EwRkJReXhWUVVGVExFOUJRVlFzUlVGQmFVSXNUVUZCYWtJc1JVRkJkMElzVDBGQmVFSXNSVUZCWjBNN1FVRkRiRVlzWjBKQlFVa3NWMEZCVnl4UlFVRlJMR2xDUVVGU0xFTkJRVmdzUTBGRU9FVTdPMEZCUjJ4R0xHZENRVUZKTEd0Q1FVRnJRaXhSUVVGUkxHOUNRVUZTTEVOQlFXeENMRU5CU0RoRk96dEJRVXRzUml4blFrRkJTU3hWUVVGVkxGRkJRVkVzYzBKQlFWSXNRMEZCVml4RFFVdzRSVHRCUVUxc1JpeG5Ra0ZCU1N4VlFVRlZMRkZCUVZFc2MwSkJRVklzUTBGQlZpeERRVTQ0UlR0QlFVOXNSaXhuUWtGQlNTeFhRVUZYTEZGQlFWRXNkVUpCUVZJc1EwRkJXQ3hEUVZBNFJUdEJRVkZzUml4blFrRkJTU3hqUVVGakxGRkJRVkVzTUVKQlFWSXNRMEZCWkN4RFFWSTRSVHM3UVVGVmJFWXNiVUpCUVU4c1QwRkJVQ3hIUVVGcFFpeGhRVUZxUWl4RFFWWnJSanM3UVVGWmJFWXNjVUpCUVZNc1lVRkJWQ3hEUVVGMVFpeExRVUYyUWl4RlFVRTRRaXhKUVVFNVFpeEZRVUZ2UXp0QlFVTm9ReXh2UWtGQlNTeE5RVUZOTEU5QlFVOHNTMEZCU3l4UlFVRk1MRWxCUVdsQ0xGRkJRV3BDTEVkQlFUUkNMRkZCUVc1RExFTkJSSE5DTzBGQlJXaERMRzlDUVVGSkxFOUJRVThzVDBGQlR5eExRVUZMTEVsQlFVd3NSMEZCV1N4SlFVRnVRaXhEUVVaeFFqczdRVUZKYUVNc2QwSkJRVkVzV1VGQldTeExRVUZhTEVWQlFXMUNMRU5CUVc1Q0xFTkJTbmRDT3p0QlFVMW9ReXh2UWtGQlNTeFRRVUZUTEV0QlFWUXNRMEZCU2l4RlFVRnhRanRCUVVOcVFpd3lRa0ZCVHl4TlFVRk5MRWxCUVU0c1JVRkJVQ3hEUVVScFFqdHBRa0ZCY2tJc1RVRkZUeXhKUVVGSkxGRkJRVkVzUzBGQlVpeERRVUZLTEVWQlFXOUNPMEZCUTNaQ0xESkNRVUZQTEVsQlFVa3NZMEZCU2l4RFFVRnRRaXhOUVVGTkxFbEJRVTRzUTBGQk1VSXNRMEZFZFVJN2FVSkJRWEJDTEUxQlJVRXNTVUZCU1N4RFFVRkRMRkZCUVZFc1MwRkJVaXhEUVVGRUxFVkJRV2xDTzBGQlEzaENMSGRDUVVGSkxFbEJRVW9zUlVGQlZUdEJRVU5PTERaQ1FVRkxMSE5EUVVGTUxFVkJRVFpETEV0QlFUZERMRVZCUkUwN2NVSkJRVlk3UVVGSFFTd3lRa0ZCVHl4SlFVRlFMRU5CU25kQ08ybENRVUZ5UWpzN1FVRlBVQ3h2UWtGQlNTeFBRVUZQTEV0QlFVTXNRMEZCVFN4VFFVRk9MRXRCUVc5Q0xFbEJRWEJDTEVkQlExSXNTVUZCU1N4aFFVRktMRU5CUVd0Q0xFMUJRVTBzVDBGQlRpeERRVVJZTEVkQlJWQXNTVUZCU1N4bFFVRktMRU5CUVc5Q0xFMUJRVTBzVTBGQlRpeEZRVUZwUWl4TlFVRk5MRTlCUVU0c1EwRkdPVUlzUTBGcVFuRkNPenRCUVhGQ2FFTXNiMEpCUVVrc1VVRkJVU3hOUVVGTkxGVkJRVTRzUTBGeVFtOUNPMEZCYzBKb1F5eG5RMEZCWjBJc1NVRkJhRUlzUlVGQmMwSXNTMEZCZEVJc1JVRjBRbWRET3p0QlFYZENhRU1zYjBKQlFVa3NWMEZCVnl4TlFVRk5MRkZCUVU0c1EwRjRRbWxDT3p0QlFUQkNhRU1zY1VKQlFVc3NTVUZCU1N4SlFVRkpMRU5CUVVvc1JVRkJUeXhKUVVGSkxGTkJRVk1zVFVGQlZDeEZRVUZwUWl4SFFVRnlReXhGUVVFd1F6dEJRVU4wUXl4M1FrRkJTU3haUVVGWkxHTkJRV01zVTBGQlV5eERRVUZVTEVOQlFXUXNSVUZCTWtJc1NVRkJNMElzUTBGQldpeERRVVJyUXp0QlFVVjBReXgzUWtGQlNTeFRRVUZLTEVWQlFXVTdRVUZEV0N3MlFrRkJTeXhYUVVGTUxFTkJRV2xDTEZOQlFXcENMRVZCUkZjN2NVSkJRV1k3YVVKQlJrbzdPMEZCVDBFc2RVSkJRVThzU1VGQlVDeERRV3BEWjBNN1lVRkJjRU03VTBGYWEwUXNSVUZuUkdoRUxFVkJRVU1zTkVKQlFUSkNMRVZCUVROQ0xFVkJRVGhDTEhkQ1FVRjFRaXhGUVVGMlFpeEZRVUV3UWl4M1FrRkJkVUlzUlVGQmRrSXNSVUZCTUVJc2VVSkJRWGRDTEVWQlFYaENMRVZCUVRKQ0xITkNRVUZ4UWl4RlFVRnlRaXhGUVVGM1FpeHRRa0ZCYTBJc1JVRkJiRUlzUlVGb1JIWkdMRU5CUVVnc1JVRm5SR2xJTEVsQlFVY3NRMEZCUXl4VlFVRlRMRTlCUVZRc1JVRkJhVUlzVFVGQmFrSXNSVUZCZDBJc1QwRkJlRUlzUlVGQlowTTdPenM3T3pzN1FVRlBiazBzWjBKQlFVa3NWVUZCVlN4RlFVRldMRU5CVUN0TU96dEJRVk51VFN4dFFrRkJUeXhQUVVGUUxFZEJRV2xDTEZGQlFXcENMRU5CVkcxTk96dEJRVmR1VFN4eFFrRkJVeXhSUVVGVUxFTkJRV3RDTEZGQlFXeENMRVZCUVRSQ0xFbEJRVFZDTEVWQlFXdERMRTlCUVd4RExFVkJRVEpETEV0QlFUTkRMRVZCUVd0RU8wRkJRemxETEc5Q1FVRkpMRU5CUVVNc1QwRkJSQ3hKUVVGWkxGRkJRVkVzVFVGQlVpeExRVUZ0UWl4RFFVRnVRaXhGUVVGelFqdEJRVU5zUXl3eVFrRkJUeXhGUVVGUUxFTkJSR3RETzJsQ1FVRjBReXhOUVVWUE8wRkJRMGdzTkVKQlFWRXNTVUZCVWl4RFFVRmhMRk5CUVdJc1JVRkVSenRCUVVWSUxESkNRVUZQTEZGQlFWRXNVVUZCVWl4RlFVRnJRaXhKUVVGc1FpeEZRVUYzUWl4UFFVRjRRaXhGUVVGcFF5eExRVUZxUXl4RlFVRjNReXhEUVVGNFF5eERRVUZRTEVOQlJrYzdhVUpCUmxBN1lVRkVTanM3UVVGVFFTeHhRa0ZCVXl4UFFVRlVMRU5CUVdsQ0xGRkJRV3BDTEVWQlFUSkNMRWxCUVROQ0xFVkJRV2xETEU5QlFXcERMRVZCUVRCRExFdEJRVEZETEVWQlFXbEVMRk5CUVdwRUxFVkJRVFJFTzBGQlEzaEVMSGRDUVVGUkxGTkJRVk1zUlVGQlZDeERRVVJuUkRzN1FVRkplRVFzYjBKQlFVa3NVVUZCU2l4RlFVRmpPMEZCUTFZc2QwSkJRVWtzWVVGQllTeFBRVUZpTEVWQlFYTkNMRk5CUVhSQ0xFVkJRV2xETEZOQlFXcERMRU5CUVVvc1JVRkJhVVE3UVVGRE4wTXNPRUpCUVUwc1UwRkJUaXhKUVVGdFFpeFJRVUZ1UWl4RFFVUTJRenR4UWtGQmFrUTdPMEZCU1VFc2QwSkJRVWtzV1VGQldTeExRVUZMTEZGQlFVd3NRMEZNVGpzN1FVRlBWaXgzUWtGQlNTeFRRVUZLTEVWQlFXVTdPMEZCUlZnc05FSkJRVWtzWVVGQllTeFRRVUZUTEZWQlFWUXNRMEZHVGpzN1FVRkpXQ3cyUWtGQlN5eEpRVUZKTEVsQlFVa3NRMEZCU2l4RlFVRlBMRWxCUVVrc1MwRkJTeXhSUVVGTUxFTkJRV01zVFVGQlpDeEZRVUZ6UWl4SFFVRXhReXhGUVVFclF6dEJRVU16UXl4NVEwRkJZU3hEUVVGaUxFTkJSREpET3p0QlFVY3pReXhuUTBGQlNTeFRRVUZUTEZWQlFWVXNRMEZCVml4TFFVRm5RaXhQUVVGb1FpeERRVWc0UWp0QlFVa3pReXhuUTBGQlNTeFpRVUZaTEdGQlFXRXNUMEZCVHl4TFFVRlFMRWxCUVdkQ0xFTkJRV2hDTEVOQlFXSTdPenRCUVVveVFpeG5RMEZQZGtNc1lVRkJZU3hQUVVGaUxFVkJRWE5DTEZOQlFYUkNMRVZCUVdsRExGTkJRV3BETEVOQlFVb3NSVUZCYVVRN1FVRkROME1zZDBOQlFWRXNWMEZCVnl4RFFVRllMRU5CUVZJc1JVRkJkVUlzVFVGQmRrSXNSVUZCSzBJc1QwRkJMMElzUlVGQmQwTXNTMEZCZUVNc1JVRkJLME1zVTBGQkwwTXNSVUZFTmtNN05rSkJRV3BFT3p0QlFVbEJMSGREUVVGWkxGTkJRVm9zUTBGWU1rTTdlVUpCUVM5RE8zRkNRVXBLTzJsQ1FWQktPenRCUVRKQ1FTeDFRa0ZCVHl4TFFVRlFMRU5CTDBKM1JEdGhRVUUxUkRzN08wRkJjRUp0VFN4eFFrRjFSREZNTEZsQlFWUXNRMEZCYzBJc1QwRkJkRUlzUlVGQkswSXNTVUZCTDBJc1JVRkJjVU1zUzBGQmNrTXNSVUZCTkVNN1FVRkRlRU1zYjBKQlFVa3NVVUZCVVN4TlFVRlNMRXRCUVcxQ0xFTkJRVzVDTEVWQlFYTkNPMEZCUTNSQ0xESkNRVUZQTEV0QlFWQXNRMEZFYzBJN2FVSkJRVEZDT3p0QlFVbEJMRzlDUVVGSkxGZEJRVmNzUTBGQldDeERRVXh2UXp0QlFVMTRReXh2UWtGQlNTeFhRVUZYTEZGQlFWRXNUVUZCVWl4SFFVRnBRaXhEUVVGcVFpeERRVTU1UWp0QlFVOTRReXh2UWtGQlNTeFpRVUZLTEVOQlVIZERPMEZCVVhoRExHOUNRVUZKTEZkQlFVb3NRMEZTZDBNN08wRkJWWGhETEhWQ1FVRlBMRmxCUVZrc1VVRkJXaXhGUVVGelFqdEJRVU42UWl4dFEwRkJaU3hEUVVGRkxGZEJRVmNzVVVGQldDeERRVUZFTEVkQlFYZENMRU5CUVhoQ0xFbEJRVGhDTEVOQlFTOUNMRU5CUkZVN1FVRkZla0lzYTBOQlFXTXNVVUZCVVN4WlFVRlNMRU5CUVdRc1EwRkdlVUk3TzBGQlNYcENMSGRDUVVGSkxHRkJRV0VzVVVGQllpeEZRVUYxUWp0QlFVTjJRaXdyUWtGQlR5eGxRVUZsTEVsQlFXWXNTVUZCZFVJc1pVRkJaU3hMUVVGbUxFTkJSRkE3Y1VKQlFUTkNMRTFCUlU4c1NVRkJTU3hqUVVGakxFbEJRV1FzUlVGQmIwSTdRVUZETTBJc2JVTkJRVmNzWlVGQlpTeERRVUZtTEVOQlJHZENPM0ZDUVVGNFFpeE5RVVZETEVsQlFVa3NZMEZCWXl4TFFVRmtMRVZCUVhGQ08wRkJRemRDTEcxRFFVRlhMR1ZCUVdVc1EwRkJaaXhEUVVSclFqdHhRa0ZCZWtJc1RVRkZSRHRCUVVOSUxDdENRVUZQTEVsQlFWQXNRMEZFUnp0eFFrRkdRenRwUWtGU1dqczdRVUZsUVN4MVFrRkJUeXhMUVVGUUxFTkJla0ozUXp0aFFVRTFRenM3UVVFMFFrRXNjVUpCUVZNc1UwRkJWQ3hEUVVGdFFpeERRVUZ1UWl4RlFVRnpRaXhEUVVGMFFpeEZRVUY1UWp0QlFVTnlRaXgxUWtGQlR5eEpRVUZKTEVOQlFVb3NSMEZCVVN4RFFVRlNMRWRCUVZrc1EwRkJReXhEUVVGRUxFTkJSRVU3WVVGQmVrSTdVMEZ1Um0xTExFVkJkVVpxU3l4RlFYWkdaMHNzUTBGQlNDeEZRWFZHZWtvc1NVRkJSeXhEUVVGRExGVkJRVk1zVDBGQlZDeEZRVUZwUWl4TlFVRnFRaXhGUVVGM1FpeFBRVUY0UWl4RlFVRm5RenRCUVVNeFF5eG5Ra0ZCU1N4clFrRkJhMElzVVVGQlVTeHZRa0ZCVWl4RFFVRnNRaXhEUVVSelF6czdRVUZITVVNc1owSkJRVWtzVjBGQlZ5eFJRVUZSTEhWQ1FVRlNMRU5CUVZnc1EwRkljME03UVVGSk1VTXNaMEpCUVVrc1UwRkJVeXhSUVVGUkxHOUNRVUZTTEVOQlFWUXNRMEZLYzBNN08wRkJUVEZETEdkQ1FVRkpMR1ZCUVdVc1VVRkJVU3hwUWtGQlVpeERRVUZtTEVOQlRuTkRPenRCUVZFeFF5eHRRa0ZCVHl4UFFVRlFMRWRCUVdsQ0xGVkJRV3BDTEVOQlVqQkRPenRCUVZVeFF5eHhRa0ZCVXl4VlFVRlVMRU5CUVc5Q0xFMUJRWEJDTEVWQlFUUkNMRTlCUVRWQ0xFVkJRWEZETEdGQlFYSkRMRVZCUVc5RU8wRkJRMmhFTEc5Q1FVRkpMRTlCUVU4c1QwRkJUeXhKUVVGUUxFTkJSSEZETzBGQlJXaEVMRzlDUVVGSkxGRkJRVkVzVDBGQlR5eExRVUZRTEVOQlJtOURPMEZCUjJoRUxHOUNRVUZKTEZGQlFWRXNUMEZCVHl4TFFVRlFMRU5CU0c5RE96dEJRVXRvUkN4M1FrRkJVU3hKUVVGU08wRkJRMGtzZVVKQlFVc3NUMEZCVHl4TlFVRlFPMEZCUTBRc0swSkJRVThzVjBGQlZ5eFBRVUZZTEVWQlFXOUNMRXRCUVhCQ0xFTkJRVkFzUTBGRVNqdEJRVVJLTEhsQ1FVZFRMRTlCUVU4c1RVRkJVRHRCUVVORUxDdENRVUZQTEZkQlFWY3NUMEZCV0N4RlFVRnZRaXhMUVVGd1FpeEZRVUV5UWl4aFFVRXpRaXhEUVVGUUxFTkJSRW83UVVGSVNpeDVRa0ZMVXl4UFFVRlBMRXRCUVZBN1FVRkRSQ3dyUWtGQlR5eFpRVUZaTEU5QlFWb3NSVUZCY1VJc1MwRkJja0lzUlVGQk5FSXNTMEZCTlVJc1JVRkJiVU1zWVVGQmJrTXNRMEZCVUN4RFFVUktPMEZCVEVvc2VVSkJUMU1zVDBGQlR5eE5RVUZRTzBGQlEwUXNLMEpCUVU4c1dVRkJXU3hQUVVGYUxFVkJRWEZDTEV0QlFYSkNMRVZCUVRSQ0xFdEJRVFZDTEVWQlFXMURMR0ZCUVc1RExFTkJRVkFzUTBGRVNqdEJRVkJLTEhsQ1FWTlRMRTlCUVU4c1MwRkJVRHRCUVVORUxDdENRVUZQTEZkQlFWY3NUMEZCV0N4RlFVRnZRaXhMUVVGd1FpeEZRVUV5UWl4TFFVRXpRaXhGUVVGclF5eGhRVUZzUXl4RFFVRlFMRU5CUkVvN1FVRlVTaXg1UWtGWFV5eFBRVUZQTEV0QlFWQTdRVUZEUkN4M1EwRkJaMElzVDBGQmFFSXNSVUZCZVVJc1MwRkJla0lzUlVGRVNqdEJRVVZKTEN0Q1FVRlBMRTlCUVZBc1EwRkdTanRCUVZoS0xIbENRV05UTEU5QlFVOHNTMEZCVUR0QlFVTkVMSGREUVVGblFpeFBRVUZvUWl4RlFVRjVRaXhMUVVGNlFpeEZRVUZuUXl4TlFVRk5MRlZCUVU0c1EwRkJhRU1zUTBGRVNqdEJRVVZKTEN0Q1FVRlBMRTlCUVZBc1EwRkdTanRCUVdSS0xIbENRV2xDVXl4UFFVRlBMRXRCUVZBN1FVRkRSQ3dyUWtGQlR5eFpRVUZaTEU5QlFWb3NSVUZEU0N4alFVRmpMRXRCUVdRc1EwRkJiMElzVDBGQmNFSXNSVUZCTmtJc1MwRkJOMElzUlVGQmIwTXNZVUZCY0VNc1EwRkVSeXhEUVVGUUxFTkJSRW83UVVGcVFrbzdRVUZ4UWxFc0swSkJRVThzVDBGQlVDeERRVVJLTzBGQmNFSktMR2xDUVV4blJEdGhRVUZ3UkRzN1FVRTRRa0VzY1VKQlFWTXNWVUZCVkN4RFFVRnZRaXhQUVVGd1FpeEZRVUUyUWl4TFFVRTNRaXhGUVVGdlF6dEJRVU5vUXl4dlFrRkJTU3hoUVVGaExGRkJRVkVzVlVGQlVpeERRVVJsT3p0QlFVZG9ReXh2UWtGQlNTeFZRVUZLTEVWQlFXZENPMEZCUTFvc0swSkJRVmNzVjBGQldDeERRVUYxUWl4UFFVRjJRaXhGUVVSWk8ybENRVUZvUWpzN1FVRkpRU3c0UWtGQll5eFBRVUZrTEVWQlFYVkNMRXRCUVhaQ0xFVkJVR2RET3p0QlFWTm9ReXgxUWtGQlR5eEpRVUZRTEVOQlZHZERPMkZCUVhCRE96dEJRVmxCTEhGQ1FVRlRMRlZCUVZRc1EwRkJiMElzVlVGQmNFSXNSVUZCWjBNc1MwRkJhRU1zUlVGQmRVTXNZVUZCZGtNc1JVRkJjMFE3UVVGRGJFUXNiMEpCUVVrc1ZVRkJWU3hqUVVGakxFMUJRV1FzUTBGQmNVSXNTMEZCY2tJc1JVRkJORUlzWVVGQk5VSXNRMEZCVml4RFFVUTRRenM3UVVGSGJFUXNiMEpCUVVrc1ZVRkJTaXhGUVVGblFqdEJRVU5hTEN0Q1FVRlhMRmRCUVZnc1EwRkJkVUlzVDBGQmRrSXNSVUZFV1R0cFFrRkJhRUk3TzBGQlNVRXNkVUpCUVU4c1ZVRkJVQ3hEUVZCclJEdGhRVUYwUkRzN1FVRlZRU3h4UWtGQlV5eFhRVUZVTEVOQlFYRkNMRTlCUVhKQ0xFVkJRVGhDTEZOQlFUbENMRVZCUVhsRExFdEJRWHBETEVWQlFXZEVMR0ZCUVdoRUxFVkJRU3RFTzBGQlF6TkVMRzlDUVVGSkxFOUJRVW9zUTBGRU1rUTdPMEZCUnpORUxHOUNRVUZKTEZGQlFWRXNVVUZCVWl4TFFVRnhRaXhEUVVGeVFpeEZRVUYzUWp0QlFVTjRRaXcwUWtGQlVTeFhRVUZTTEVOQlFXOUNMRU5CUVhCQ0xFVkJRWFZDTEZGQlFWRXNUVUZCVWl4RlFVRm5RaXhOUVVGTkxFbEJRVTRzUTBGQmRrTXNRMEZFZDBJN1FVRkZlRUlzT0VKQlFWVXNUMEZCVml4RFFVWjNRanRwUWtGQk5VSXNUVUZIVHp0QlFVTklMSGRDUVVGSkxHRkJRV0VzVVVGQlVTeFZRVUZTTEVOQlJHUTdRVUZGU0N3NFFrRkJWU3hqUVVGakxFMUJRV1FzUTBGQmNVSXNTMEZCY2tJc1JVRkJORUlzWVVGQk5VSXNRMEZCVml4RFFVWkhPenRCUVVsSUxIZENRVUZKTEdOQlFXTXNXVUZCV1N4UFFVRmFMRVZCUVhGQ08wRkJRMjVETEcxRFFVRlhMRmxCUVZnc1EwRkJkMElzVDBGQmVFSXNSVUZCYVVNc1QwRkJha01zUlVGRWJVTTdjVUpCUVhaRE8ybENRVkJLT3p0QlFWbEJMSFZDUVVGUExFOUJRVkFzUTBGbU1rUTdZVUZCTDBRN08wRkJhMEpCTEhGQ1FVRlRMRmRCUVZRc1EwRkJjVUlzVDBGQmNrSXNSVUZCT0VJc1UwRkJPVUlzUlVGQmVVTXNUVUZCZWtNc1JVRkJhVVFzWVVGQmFrUXNSVUZCWjBVN1FVRkROVVFzYjBKQlFVa3NWMEZCVnl4aFFVRmhMRk5CUVdJc1JVRkJkMElzVFVGQmVFSXNRMEZCV0N4RFFVUjNSRHRCUVVVMVJDeHZRa0ZCU1N4UFFVRktMRU5CUmpSRU96dEJRVWsxUkN4dlFrRkJTU3hSUVVGS0xFVkJRV003UVVGRFZpdzRRa0ZCVlN4UFFVRlBMRTFCUVZBc1EwRkJZeXhUUVVGa0xFVkJRWGxDTEU5QlFYcENMRXRCUVhGRExFOUJRWEpETEVOQlJFRTdhVUpCUVdRc1RVRkZUenRCUVVOSUxEaENRVUZWTEdOQlFXTXNUVUZCWkN4RFFVRnhRaXhOUVVGeVFpeEZRVUUyUWl4aFFVRTNRaXhEUVVGV0xFTkJSRWM3YVVKQlJsQTdPMEZCVFVFc2IwSkJRVWtzWVVGQllTeFJRVUZSTEZWQlFWSXNRMEZXTWtNN08wRkJXVFZFTEc5Q1FVRkpMR05CUVdNc1dVRkJXU3hQUVVGYUxFVkJRWEZDTzBGQlEyNURMQ3RDUVVGWExGbEJRVmdzUTBGQmQwSXNUMEZCZUVJc1JVRkJhVU1zVDBGQmFrTXNSVUZFYlVNN2FVSkJRWFpET3p0QlFVbEJMRzlDUVVGSkxFTkJRVU1zVVVGQlJDeEZRVUZYTzBGQlExZ3NhME5CUVdNc1QwRkJaQ3hGUVVGMVFpeFRRVUYyUWl4RlFVUlhPMmxDUVVGbU96dEJRVWxCTEhWQ1FVRlBMRTlCUVZBc1EwRndRalJFTzJGQlFXaEZPenRCUVhWQ1FTeHhRa0ZCVXl4VlFVRlVMRU5CUVc5Q0xFOUJRWEJDTEVWQlFUWkNMRk5CUVRkQ0xFVkJRWGRETEV0QlFYaERMRVZCUVN0RExHRkJRUzlETEVWQlFUaEVPMEZCUXpGRUxHOUNRVUZKTEdGQlFXRXNVVUZCVVN4VlFVRlNMRU5CUkhsRE8wRkJSVEZFTEc5Q1FVRkpMRlZCUVZVc1kwRkJZeXhOUVVGa0xFTkJRWEZDTEV0QlFYSkNMRVZCUVRSQ0xHRkJRVFZDTEVOQlFWWXNRMEZHYzBRN08wRkJTVEZFTEc5Q1FVRkpMR05CUVdNc1dVRkJXU3hQUVVGYUxFVkJRWEZDTzBGQlEyNURMQ3RDUVVGWExGbEJRVmdzUTBGQmQwSXNUMEZCZUVJc1JVRkJhVU1zVDBGQmFrTXNSVUZFYlVNN2FVSkJRWFpET3p0QlFVbEJMSFZDUVVGUExFOUJRVkFzUTBGU01FUTdZVUZCT1VRN08wRkJWMEVzY1VKQlFWTXNZVUZCVkN4RFFVRjFRaXhQUVVGMlFpeEZRVUZuUXl4RFFVRm9ReXhGUVVGdFF6dEJRVU12UWl4dlFrRkJTU3hQUVVGUExFVkJRVVVzVDBGQlJpeExRVUZqTEZWQlFYSkNMRWxCUVcxRExGTkJRVk1zUTBGQlZDeERRVUZ1UXl4RlFVRm5SRHRCUVVOb1JDeHpRa0ZCUlN4UFFVRkdMRU5CUVZVc1QwRkJWaXhGUVVSblJEdHBRa0ZCY0VRN1lVRkVTanM3UVVGTlFTeHhRa0ZCVXl4bFFVRlVMRU5CUVhsQ0xFOUJRWHBDTEVWQlFXdERMRXRCUVd4RExFVkJRWGxETzBGQlEzSkRMRzlDUVVGSkxHRkJRV0VzVVVGQlVTeFZRVUZTTEVOQlJHOUNPMEZCUlhKRExHOUNRVUZKTEZOQlFWTXNSVUZCVkN4RFFVWnBRenRCUVVkeVF5eHZRa0ZCU1N4SlFVRktMRU5CU0hGRE8wRkJTWEpETEc5Q1FVRkpMRTFCUVVvc1EwRktjVU03UVVGTGNrTXNiMEpCUVVrc1RVRkJTaXhEUVV4eFF6czdRVUZQY2tNc2NVSkJRVXNzU1VGQlNTeEpRVUZKTEVOQlFVb3NSVUZCVHl4SlFVRkpMRTFCUVUwc1QwRkJUaXhEUVVGakxFMUJRV1FzUlVGQmMwSXNSMEZCTVVNc1JVRkJLME03UVVGRE0wTXNOa0pCUVZNc1RVRkJUU3hQUVVGT0xFTkJRV01zUTBGQlpDeERRVUZVTEVOQlJESkRPMEZCUlRORExESkNRVUZQTEZkQlFWY3NUMEZCVHl4SlFVRlFMRU5CUVd4Q0xFTkJSakpETzBGQlJ6TkRMSGRDUVVGSkxFOUJRVThzUjBGQlVDeEZRVUZaTzBGQlExb3NLMEpCUVU4c1QwRkJUeXhIUVVGUUxFTkJRVkFzUjBGQmNVSXNTVUZCY2tJc1EwRkVXVHR4UWtGQmFFSTdRVUZIUVN3MFFrRkJVU3hYUVVGU0xFTkJRVzlDTEVsQlFYQkNMRVZCVGpKRE8ybENRVUV2UXpzN1FVRlRRU3h2UWtGQlNTeFRRVUZUTEZkQlFWY3NUVUZCV0N4RFFXaENkMEk3UVVGcFFuSkRMSEZDUVVGTExFbEJRVWtzU1VGQlNTeERRVUZLTEVWQlFVOHNTVUZCU1N4TlFVRk5MRTlCUVU0c1EwRkJZeXhOUVVGa0xFVkJRWE5DTEVkQlFURkRMRVZCUVN0RE8wRkJRek5ETERaQ1FVRlRMRTFCUVUwc1QwRkJUaXhEUVVGakxFTkJRV1FzUTBGQlZDeERRVVF5UXp0QlFVVXpReXd5UWtGQlR5eFBRVUZQTEU5QlFVOHNSMEZCVUN4RFFVRmtPenRCUVVZeVF5d3lRa0ZKTTBNc1EwRkJVU3haUVVGU0xFTkJRWEZDTEVsQlFYSkNMRVZCUVRKQ0xFOUJRVThzUlVGQlVDeEpRVUZoTEZGQlFXSXNSMEZCZDBJc1NVRkJlRUlzUjBGQkswSXNWMEZCVnl4UFFVRlBMRVZCUVZBc1EwRkJNVU1zUTBGQk0wSXNRMEZLTWtNN2FVSkJRUzlETzJGQmFrSktPenRCUVhsQ1FTeHhRa0ZCVXl4WFFVRlVMRU5CUVhGQ0xFOUJRWEpDTEVWQlFUaENMRTlCUVRsQ0xFVkJRWFZETzBGQlEyNURMRzlDUVVGSkxGZEJRVmNzVDBGQldDeEpRVUZ6UWl4WlFVRlpMRTlCUVZvc1NVRkJkVUlzVVVGQlVTeFZRVUZTTEVWQlFXOUNPMEZCUTJwRkxEUkNRVUZSTEZWQlFWSXNRMEZCYlVJc1dVRkJia0lzUTBGQlowTXNUMEZCYUVNc1JVRkJlVU1zVDBGQmVrTXNSVUZFYVVVN2FVSkJRWEpGT3p0QlFVbEJMSFZDUVVGUExFOUJRVkFzUTBGTWJVTTdZVUZCZGtNN1UwRnFTbFVzUlVGNVNsSXNSVUZCUXl4NVFrRkJkMElzUlVGQmVFSXNSVUZCTWtJc2MwSkJRWEZDTEVWQlFYSkNMRVZCUVhkQ0xITkNRVUZ4UWl4RlFVRnlRaXhGUVVGM1FpeHRRa0ZCYTBJc1JVRkJiRUlzUlVGNlNuSkZMRU5CUVVnc1JVRjVTaXRHTEVsQlFVY3NRMEZCUXl4VlFVRlRMRTlCUVZRc1JVRkJhVUlzVFVGQmFrSXNSVUZCZDBJc1QwRkJlRUlzUlVGQlowTTdRVUZEZWtrc1owSkJRVWtzVjBGQlZ5eFJRVUZSTEdsQ1FVRlNMRU5CUVZnc1EwRkVjVWs3UVVGRmVra3NaMEpCUVVrc1ZVRkJWU3hSUVVGUkxGbEJRVklzUTBGQlZpeERRVVp4U1RzN1FVRkpla2tzWjBKQlFVa3NVMEZCVXl4UlFVRlJMR3RDUVVGU0xFTkJRVlFzUTBGS2NVazdRVUZMZWtrc1owSkJRVWtzVjBGQlZ5eFJRVUZSTEdGQlFWSXNRMEZCV0N4RFFVeHhTVHRCUVUxNlNTeG5Ra0ZCU1N4VlFVRlZMRkZCUVZFc1dVRkJVaXhEUVVGV0xFTkJUbkZKTzBGQlQzcEpMRzFDUVVGUExFOUJRVkFzUjBGQmFVSXNTMEZCYWtJc1EwRlFlVWs3TzBGQlUzcEpMSEZDUVVGVExFdEJRVlFzUTBGQlpTeFJRVUZtTEVWQlFYbENMRTlCUVhwQ0xFVkJRV3RETEdGQlFXeERMRVZCUVdsRU8wRkJRemRETEdkRFFVRm5RaXhwUWtGQmFVSXNSVUZCYWtJc1EwRkVOa0k3UVVGRk4wTXNPRUpCUVdNc1MwRkJaQ3hIUVVGelFpeGpRVUZqTEV0QlFXUXNTVUZCZFVJc1kwRkJZeXhMUVVGa0xFdEJRWGRDTEV0QlFYaENMRWRCUTNaRExHTkJRV01zUzBGQlpDeEhRVU5CTEdOQlJtZENMRU5CUm5WQ08wRkJTemRETERoQ1FVRmpMRTFCUVdRc1IwRkJkVUlzWTBGQll5eE5RVUZrTEVsQlFYZENMRTFCUVhoQ0xFTkJUSE5DT3p0QlFVODNReXgxUWtGQlR5eGpRVUZqTEV0QlFXUXNRMEZCYjBJc1VVRkJjRUlzUlVGQk9FSXNUMEZCT1VJc1JVRkJkVU1zWVVGQmRrTXNRMEZCVUN4RFFWQTJRenRoUVVGcVJEczdRVUZWUVN4eFFrRkJVeXhqUVVGVUxFTkJRWGRDTEZGQlFYaENMRVZCUVd0RExFOUJRV3hETEVWQlFUSkRMR0ZCUVRORExFVkJRVEJFTzBGQlEzUkVMRzlDUVVGSkxGVkJRVlVzWVVGQllTeFBRVUZpTEVOQlFWWXNRMEZFYTBRN08wRkJSM1JFTEc5Q1FVRkpMRkZCUVZFc1RVRkJVaXhMUVVGdFFpeERRVUZ1UWl4RlFVRnpRanRCUVVOMFFpd3lRa0ZCVHl4UlFVRlFMRU5CUkhOQ08ybENRVUV4UWpzN1FVRkpRU3h2UWtGQlNTeFJRVUZSTEZOQlFWTXNVVUZCVkN4RlFVRnRRaXhSUVVGUkxFTkJRVklzUlVGQlZ5eFBRVUU1UWl4RFFVRlNMRU5CVUd0RU8wRkJVWFJFTEc5Q1FVRkpMR2RDUVVGblFpeFRRVUZUTEdGQlFWUXNRMEZTYTBNN08wRkJWWFJFTEc5Q1FVRkpMRU5CUVVNc1kwRkJZeXhSUVVGa0xFbEJRVEJDTEd0Q1FVRnJRaXhSUVVGc1FpeEZRVUUwUWp0QlFVTjJSQ3hyUTBGQll5eFJRVUZrTEVkQlFYbENMR0ZCUVhwQ0xFTkJSSFZFTzJsQ1FVRXpSRHM3UVVGSlFTeHhRa0ZCU3l4SlFVRkpMRWxCUVVrc1EwRkJTaXhGUVVGUExFbEJRVWtzVVVGQlVTeE5RVUZTTEVWQlFXZENMRWRCUVhCRExFVkJRWGxETzBGQlEzSkRMSGRDUVVGSkxGbEJRVmtzVVVGQlVTeERRVUZTTEVOQlFWb3NRMEZFYVVNN1FVRkZja01zSzBKQlFWY3NWMEZCVnl4UlFVRllMRVZCUTFBc1RVRkJUU3hUUVVGT0xFTkJSRThzUlVGRlVDeFJRVUZSTEZOQlFWSXNRMEZHVHl4RlFVZFFMR0ZCU0U4c1EwRkJXQ3hEUVVaeFF6dHBRa0ZCZWtNN08wRkJVVUVzZFVKQlFVOHNVVUZCVUN4RFFYUkNjMFE3WVVGQk1VUTdPMEZCZVVKQkxIRkNRVUZUTEZWQlFWUXNRMEZCYjBJc1VVRkJjRUlzUlVGQk9FSXNUMEZCT1VJc1JVRkJkVU1zVTBGQmRrTXNSVUZCYTBRc1lVRkJiRVFzUlVGQmFVVTdRVUZETjBRc2IwSkJRVWtzUTBGQlF5eFBRVUZFTEVWQlFWVTdRVUZEVml3eVFrRkJUeXhSUVVGUUxFTkJSRlU3YVVKQlFXUTdPMEZCU1VFc2IwSkJRVWtzVDBGQlNpeERRVXcyUkRzN1FVRlBOMFFzYjBKQlFVa3NVVUZCVVN4VFFVRlNMRU5CUVVvc1JVRkJkMEk3UVVGRGNFSXNlVUpCUVVzc1NVRkJTU3hKUVVGSkxFTkJRVW9zUlVGQlR5eEpRVUZKTEZWQlFWVXNUVUZCVml4RlFVRnJRaXhIUVVGMFF5eEZRVUV5UXp0QlFVTjJReXhyUTBGQlZTeFJRVUZSTEZWQlFWVXNRMEZCVml4RFFVRlNMRVZCUVhOQ0xFOUJRWFJDTEVWQlFTdENMR0ZCUVM5Q0xFTkJRVllzUTBGRWRVTTdPMEZCUjNaRExEUkNRVUZKTEZsQlFWa3NVVUZCV2l4RlFVRnpRanRCUVVOMFFpeDFRMEZCVnl4UFFVRllMRU5CUkhOQ08zbENRVUV4UWp0eFFrRklTanRwUWtGRVNpeE5RVkZQTzBGQlEwZ3NPRUpCUVZVc1VVRkJVU3hUUVVGU0xFVkJRVzFDTEU5QlFXNUNMRVZCUVRSQ0xHRkJRVFZDTEVOQlFWWXNRMEZFUnpzN1FVRkhTQ3gzUWtGQlNTeFpRVUZaTEZGQlFWb3NSVUZCYzBJN1FVRkRkRUlzYlVOQlFWY3NUMEZCV0N4RFFVUnpRanR4UWtGQk1VSTdhVUpCV0VvN08wRkJaMEpCTEhWQ1FVRlBMRkZCUVZBc1EwRjJRalpFTzJGQlFXcEZPenRCUVRCQ1FTeHhRa0ZCVXl4WlFVRlVMRU5CUVhOQ0xFOUJRWFJDTEVWQlFTdENPMEZCUXpOQ0xHOUNRVUZKTEZWQlFWVXNSVUZCVml4RFFVUjFRanM3UVVGSE0wSXNjVUpCUVVzc1NVRkJTU3hIUVVGS0xFbEJRVmNzVDBGQmFFSXNSVUZCZVVJN1FVRkRja0lzZDBKQlFVa3NVVUZCVVN4SFFVRlNMRVZCUVdFN1FVRkRZaXhuUTBGQlVTeEpRVUZTTEVOQlFXRXNUMEZCVHl4SFFVRlFMRU5CUVdJc1JVRkVZVHR4UWtGQmFrSTdhVUpCUkVvN08wRkJUVUVzZFVKQlFVOHNUMEZCVUN4RFFWUXlRanRoUVVFdlFqdFRRWFJGZVVjc1JVRnJSblpITEVWQlFVTXNiMEpCUVcxQ0xFVkJRVzVDTEVWQlFYTkNMR1ZCUVdNc1JVRkJaQ3hGUVVGcFFpeGpRVUZoTEVWQlFXSXNSVUZCWjBJc2JVSkJRV3RDTEVWQlFXeENMRVZCUVhGQ0xHTkJRV0VzUlVGQllpeEZRV3hHZVVJc1EwRkJTQ3hGUVd0R1NpeEpRVUZITEVOQlFVTXNWVUZCVXl4UFFVRlVMRVZCUVdsQ0xFMUJRV3BDTEVWQlFYZENMRTlCUVhoQ0xFVkJRV2RETzBGQlEzSkpMR2RDUVVGSkxGZEJRVmNzVVVGQlVTeDFRa0ZCVWl4RFFVRllMRU5CUkdsSk96dEJRVWR5U1N4dFFrRkJUeXhQUVVGUUxFZEJRV2xDTEZsQlFXcENMRU5CU0hGSk96dEJRVXR5U1N4eFFrRkJVeXhaUVVGVUxFTkJRWE5DTEVOQlFYUkNMRVZCUVhsQ0xFTkJRWHBDTEVWQlFUUkNPMEZCUTNoQ0xHOUNRVUZKTEZOQlFWTXNRMEZCVkN4TFFVRmxMRk5CUVZNc1EwRkJWQ3hEUVVGbUxFVkJRVFJDTzBGQlF6VkNMSGRDUVVGSkxGVkJRVlVzUTBGQlZpeEpRVUZsTEZWQlFWVXNRMEZCVml4RlFVRmhPMEZCUXpWQ0xDdENRVUZQTEVWQlFVVXNSVUZCUml4TFFVRlRMRVZCUVVVc1JVRkJSaXhEUVVSWk8zRkNRVUZvUXl4TlFVVlBPMEZCUTBnc0swSkJRVThzUlVGQlJTeEpRVUZHTEV0QlFWY3NSVUZCUlN4SlFVRkdMRU5CUkdZN2NVSkJSbEE3YVVKQlJFbzdPMEZCVVVFc2RVSkJRVThzUzBGQlVDeERRVlIzUWp0aFFVRTFRanRUUVV4eFJ5eEZRV2xDYmtjc1JVRkJReXg1UWtGQmQwSXNSVUZCZUVJc1JVRnFRbWxITEVOQlFVZ3NSVUZwUW1wRkxFbEJRVWNzUTBGQlF5eFZRVUZUTEU5QlFWUXNSVUZCYVVJc1RVRkJha0lzUlVGQmQwSXNUMEZCZUVJc1JVRkJaME03UVVGRGNFVXNlVUpCUkc5Rk96dEJRVWR3UlN4blFrRkJTU3hWUVVGVkxGRkJRVkVzVlVGQlVpeERRVUZXTEVOQlNHZEZPenRCUVV0d1JTeHRRa0ZCVHl4UFFVRlFMRWRCUVdsQ0xFMUJRV3BDTEVOQlRHOUZPenRCUVU5d1JTeHhRa0ZCVXl4TlFVRlVMRU5CUVdkQ0xFdEJRV2hDTEVWQlFYVkNPMEZCUTI1Q0xHOUNRVUZKTEVWQlFVVXNaMEpCUVdkQ0xFMUJRV2hDTEVOQlFVWXNSVUZCTWtJN1FVRkRNMElzTWtKQlFVOHNTVUZCU1N4TlFVRktMRU5CUVZjc1MwRkJXQ3hEUVVGUUxFTkJSREpDTzJsQ1FVRXZRanM3UVVGSlFTeHhRa0ZCU3l4TFFVRk1MRWRCUVdFc1MwRkJZaXhEUVV4dFFqdGhRVUYyUWpzN1FVRlJRU3h0UWtGQlR5eFRRVUZRTEVOQlFXbENMRWxCUVdwQ0xFZEJRWGRDTEZWQlFWVXNTVUZCVml4RlFVRm5RaXhaUVVGb1FpeEZRVUU0UWp0QlFVTnNSQ3h2UWtGQlNTeExRVUZMTEZGQlFWRXNTVUZCVWl4RFFVRk1MRU5CUkRoRE8wRkJSV3hFTEc5Q1FVRkpMRmRCUVZjc1lVRkJZU3hOUVVGaUxFTkJRVzlDTEVOQlFYQkNMRU5CUVZnc1EwRkdPRU03TzBGQlNXeEVMRzFDUVVGSExGRkJRVWdzU1VGQlpTeExRVUZMTEV0QlFVd3NRMEZLYlVNN1lVRkJPVUlzUTBGbU5FTTdPMEZCYzBKd1JTeHRRa0ZCVHl4VFFVRlFMRU5CUVdsQ0xFMUJRV3BDTEVkQlFUQkNMRlZCUVZNc1NVRkJWQ3hGUVVGbExGbEJRV1lzUlVGQk5rSTdRVUZEYmtRc2IwSkJRVWtzUzBGQlN5eFJRVUZSTEVsQlFWSXNRMEZCVEN4RFFVUXJRenRCUVVWdVJDeHZRa0ZCU1N4WFFVRlhMR0ZCUVdFc1RVRkJZaXhEUVVGdlFpeERRVUZ3UWl4RFFVRllMRU5CUml0RE96dEJRVWx1UkN4dFFrRkJSeXhSUVVGSUxFbEJRV1VzVTBGQlppeERRVXB0UkR0aFFVRTNRaXhEUVhSQ01FTTdVMEZCYUVNc1JVRTJRbXhETEVWQlFVTXNXVUZCVnl4RFFVRllMRVZCTjBKblF5eERRVUZJTEVWQk5rSmtMRWxCUVVjc1EwRkJReXhWUVVGVExFOUJRVlFzUlVGQmFVSXNUVUZCYWtJc1JVRkJkMElzVDBGQmVFSXNSVUZCWjBNN1FVRkRkRVFzZVVKQlJITkVPenRCUVVkMFJDeHRRa0ZCVHl4UFFVRlFMRWRCUVdsQ0xGZEJRV3BDTEVOQlNITkVPenRCUVV0MFJDeHhRa0ZCVXl4WFFVRlVMRU5CUVhGQ0xFdEJRWEpDTEVWQlFUUkNPMEZCUTNoQ0xHOUNRVUZKTEVWQlFVVXNaMEpCUVdkQ0xGZEJRV2hDTEVOQlFVWXNSVUZCWjBNN1FVRkRhRU1zTWtKQlFVOHNTVUZCU1N4WFFVRktMRU5CUVdkQ0xFdEJRV2hDTEVOQlFWQXNRMEZFWjBNN2FVSkJRWEJET3p0QlFVbEJMSEZDUVVGTExFdEJRVXdzUjBGQllTeExRVUZpTEVOQlRIZENPMkZCUVRWQ096dEJRVkZCTEhkQ1FVRlpMRk5CUVZvc1EwRkJjMElzU1VGQmRFSXNSMEZCTmtJc1ZVRkJWU3hKUVVGV0xFVkJRV2RDTEZsQlFXaENMRVZCUVRoQ08wRkJRM1pFTEc5Q1FVRkpMRXRCUVVzc1dVRkJUQ3hOUVVGMVFpeExRVUZMTEV0QlFVd3NSVUZCV1R0QlFVTnVReXg1UWtGQlN5eFpRVUZNTEVsQlFYRkNMRXRCUVVzc1MwRkJUQ3hEUVVSak8ybENRVUYyUXp0aFFVUjVRaXhEUVdKNVFqdFRRVUZvUXl4RlFXMUNjRUlzUlVGdVFtMUNMRU5CUVVnc1JVRnRRbG9zU1VGQlJ5eERRVUZETEZWQlFWTXNUMEZCVkN4RlFVRnBRaXhOUVVGcVFpeEZRVUYzUWl4UFFVRjRRaXhGUVVGblF6dEJRVU14UXl4NVFrRkVNRU03TzBGQlJ6RkRMR2RDUVVGSkxGVkJRVlVzVVVGQlVTeFpRVUZTTEVOQlFWWXNRMEZJYzBNN08wRkJTekZETEdkQ1FVRkpMRkZCUVZFc1VVRkJVU3h0UWtGQlVpeERRVUZTTEVOQlRITkRPMEZCVFRGRExHZENRVUZKTEZGQlFWRXNVVUZCVVN4dFFrRkJVaXhEUVVGU0xFTkJUbk5ETzBGQlR6RkRMR2RDUVVGSkxGVkJRVlVzVVVGQlVTeHRRa0ZCVWl4RFFVRldMRU5CVUhORE8wRkJVVEZETEdkQ1FVRkpMRlZCUVZVc1VVRkJVU3h0UWtGQlVpeERRVUZXTEVOQlVuTkRPMEZCVXpGRExHZENRVUZKTEZkQlFWY3NVVUZCVVN4dlFrRkJVaXhEUVVGWUxFTkJWSE5ETzBGQlZURkRMR2RDUVVGSkxGTkJRVk1zVVVGQlVTeHRRa0ZCVWl4RFFVRlVMRU5CVm5ORE8wRkJWekZETEdkQ1FVRkpMRmRCUVZjc1VVRkJVU3h0UWtGQlVpeERRVUZZTEVOQldITkRPenRCUVdFeFF5eG5Ra0ZCU1N4WFFVRlhMRkZCUVZFc1owSkJRVklzUTBGQldDeERRV0p6UXp0QlFXTXhReXhuUWtGQlNTeGpRVUZqTEZGQlFWRXNNRUpCUVZJc1EwRkJaQ3hEUVdSelF6dEJRV1V4UXl4blFrRkJTU3hUUVVGVExGRkJRVkVzYjBKQlFWSXNRMEZCVkN4RFFXWnpRenM3UVVGcFFqRkRMRzFDUVVGUExFOUJRVkFzUjBGQmFVSXNRMEZCYWtJc1EwRnFRakJET3p0QlFXMUNNVU1zY1VKQlFWTXNRMEZCVkN4RFFVRlhMRTlCUVZnc1JVRkJiMElzVlVGQmNFSXNSVUZCWjBNc1VVRkJhRU1zUlVGQk1FTTdRVUZEZEVNc2IwSkJRVWtzWVVGQllTeEZRVUZpTEVOQlJHdERPMEZCUlhSRExHOUNRVUZKTEVkQlFVb3NSVUZCVXl4TFFVRlVMRVZCUVdkQ0xFZEJRV2hDTEVWQlFYRkNMRk5CUVhKQ0xFTkJSbk5ET3p0QlFVbDBReXh2UWtGQlNTeERRVUZETEZGQlFVUXNTVUZCWVN4WFFVRlhMRlZCUVZnc1EwRkJZaXhGUVVGeFF6dEJRVU55UXl3clFrRkJWeXhWUVVGWUxFTkJSSEZETzBGQlJYSkRMRFJDUVVGUkxFVkJRVklzUTBGR2NVTTdhVUpCUVhwRE96dEJRVXRCTEhkQ1FVRlJMRk5CUVZNc1ZVRkJWQ3hKUVVGMVFpeEZRVUYyUWl4RFFWUTRRanRCUVZWMFF5eHpRa0ZCVFN4VFFVRlRMRTlCUVZRc1JVRkJhMElzUzBGQmJFSXNRMEZCVGpzN08wRkJWbk5ETEc5Q1FXRnNReXhOUVVGTkxHTkJRVTRzUTBGQmNVSXNTMEZCY2tJc1EwRkJTaXhGUVVGcFF6dEJRVU0zUWl3d1FrRkJUU3hOUVVGTkxFZEJRVTRzUTBGRWRVSTdRVUZGTjBJc01FSkJRVTBzUjBGQlRpeEhRVUZaTEZOQlFWb3NRMEZHTmtJN2FVSkJRV3BET3pzN1FVRmljME1zYjBKQmJVSnNReXhOUVVGTkxHTkJRVTRzUTBGQmNVSXNWMEZCY2tJc1EwRkJTaXhGUVVGMVF6dEJRVU51UXl4blEwRkJXU3hOUVVGTkxGTkJRVTRzUTBGRWRVSTdRVUZGYmtNc01FSkJRVTBzVTBGQlRpeEhRVUZyUWl4VFFVRnNRaXhEUVVadFF6dHBRa0ZCZGtNN096dEJRVzVDYzBNc2IwSkJlVUpzUXl4UlFVRlJMRTlCUVZJc1NVRkRRU3hEUVVGRExGTkJRVVFzU1VGRFFTeE5RVUZOTEdOQlFVNHNRMEZCY1VJc1QwRkJja0lzUTBGR1FTeEpRVWRCTEUxQlFVMHNTMEZCVGl4TFFVRm5RaXhUUVVGb1FpeEpRVU5CTEVOQlFVTXNUMEZCVHl4TlFVRk5MRXRCUVU0c1EwRkJVaXhGUVVOR08wRkJRMFVzTUVKQlFVMHNTMEZCVGl4SFFVRmpMRmxCUVZrc1RVRkJUU3hMUVVGT0xFTkJRVEZDTEVOQlJFWTdhVUpCVEVZN08wRkJVMEVzYjBOQlFXOUNMRXRCUVhCQ0xFVkJiRU56UXpzN1FVRnZRM1JETEc5Q1FVRkpMR0ZCUVdFc1UwRkJZaXhKUVVFd1FpeGhRVUZoTEVsQlFXSXNSVUZCYlVJN1FVRkROME1zTmtKQlFWTXNVVUZCVkN4RlFVRnRRaXhWUVVGdVFpeEZRVUVyUWl4SFFVRXZRaXhGUVVGdlF5eExRVUZ3UXl4RlFVUTJRenRwUWtGQmFrUTdPMEZCUzBFc2RVSkJRVThzU1VGQlNTeExRVUZLTEVOQlFWVXNSMEZCVml4RlFVRmxMRXRCUVdZc1JVRkJjMElzVlVGQmRFSXNSVUZCYTBNc1IwRkJiRU1zUlVGQmRVTXNVMEZCZGtNc1EwRkJVQ3hEUVhwRGMwTTdZVUZCTVVNN08wRkJORU5CTEhGQ1FVRlRMRkZCUVZRc1EwRkJhMElzUTBGQmJFSXNSVUZCY1VJc1ZVRkJja0lzUlVGQmFVTXNSMEZCYWtNc1JVRkJjME1zUzBGQmRFTXNSVUZCTmtNN1FVRkRla01zYjBKQlFVa3NUMEZCVHl4RFFVRlFMRXRCUVdFc1VVRkJZaXhGUVVGMVFqdEJRVU4yUWl3clFrRkJWeXhKUVVGWUxFTkJRV2RDTEVsQlFVa3NTMEZCU2l4RFFVRlZMRU5CUVZZc1EwRkJhRUlzUlVGRWRVSTdhVUpCUVROQ0xFMUJSVThzU1VGQlNTeFBRVUZQTEVOQlFWQXNTMEZCWVN4UlFVRmlMRVZCUVhWQ08wRkJRemxDTEN0Q1FVRlhMRWxCUVZnc1EwRkJaMElzU1VGQlNTeExRVUZLTEVOQlFWVXNUMEZCVHl4RFFVRlFMRU5CUVZZc1EwRkJhRUlzUlVGRU9FSTdhVUpCUVROQ0xFMUJSVUVzU1VGQlNTeFJRVUZSTEVOQlFWSXNRMEZCU2l4RlFVRm5RanRCUVVOdVFpd3JRa0ZCVnl4SlFVRllMRU5CUVdkQ0xFTkJRV2hDTEVWQlJHMUNPMmxDUVVGb1FpeE5RVVZCTEVsQlFVa3NVVUZCVVN4RFFVRlNMRU5CUVVvc1JVRkJaMEk3UVVGRGJrSXNlVUpCUVVzc1NVRkJTU3hKUVVGSkxFTkJRVW9zUlVGQlR5eEpRVUZKTEVWQlFVVXNUVUZCUml4RlFVRlZMRWRCUVRsQ0xFVkJRVzFETzBGQlF5OUNMR2xEUVVGVExFVkJRVVVzUTBGQlJpeERRVUZVTEVWQlFXVXNWVUZCWml4RlFVRXlRaXhIUVVFelFpeEZRVUZuUXl4TFFVRm9ReXhGUVVRclFqdHhRa0ZCYmtNN2FVSkJSRWNzVFVGSlFTeEpRVUZKTEUxQlFVMHNTVUZCVGl4SlFVRmpMRTFCUVUwc1UwRkJUaXhGUVVGcFFqdEJRVU4wUXl3eVFrRkVjME03YVVKQlFXNURMRTFCUlVFN1FVRkRTQ3d3UWtGQlRTeDVRa0ZCZVVJN1FVRkRNMElzZFVOQlFXVXNRMEZCWmp0QlFVTkJMSEZEUVVGaE8wRkJRMVFzY1VOQlFWTXNSMEZCVkR0QlFVTkJMSGREUVVGWkxFdEJRVm83ZVVKQlJrbzdjVUpCUmtVc1EwRkJUaXhEUVVSSE8ybENRVVpCTzJGQldGZzdPMEZCZDBKQkxIRkNRVUZUTEcxQ1FVRlVMRU5CUVRaQ0xFdEJRVGRDTEVWQlFXOURPMEZCUTJoRExIRkNRVUZMTEVsQlFVa3NVVUZCU2l4SlFVRm5RaXhMUVVGeVFpeEZRVUUwUWp0QlFVTjRRaXgzUWtGQlNTeE5RVUZOTEdOQlFVNHNRMEZCY1VJc1VVRkJja0lzUTBGQlNpeEZRVUZ2UXp0QlFVTm9ReXcwUWtGQlNTeFJRVUZSTEUxQlFVMHNVVUZCVGl4RFFVRlNMRU5CUkRSQ096dEJRVWRvUXl3MFFrRkJTU3hQUVVGUExFdEJRVkFzUTBGQlNpeEZRVUZ0UWp0QlFVTm1MSEZEUVVSbE8zbENRVUZ1UWpzN1FVRkpRU3cwUWtGQlNTeFRRVUZUTEUxQlFWUXNRMEZCWjBJc1EwRkJhRUlzUlVGQmJVSXNRMEZCYmtJc1RVRkJNRUlzUzBGQk1VSXNSVUZCYVVNN08wRkJSV3BETEd0RFFVRk5MRkZCUVU0c1NVRkJhMElzVDBGQlR5eExRVUZRTEVOQlFXeENMRU5CUm1sRE8zbENRVUZ5UXp0eFFrRlFTanRwUWtGRVNqdGhRVVJLT3p0QlFXbENRU3h4UWtGQlV5eFBRVUZVTEVOQlFXbENMRU5CUVdwQ0xFVkJRVzlDTzBGQlEyaENMSFZDUVVGUExGRkJRVkVzUTBGQlVpeExRVUZqTEZGQlFWRXNRMEZCVWl4RFFVRmtMRWxCUVRSQ0xGTkJRVk1zUTBGQlZDeERRVUUxUWl4SlFVRXlReXhUUVVGVExFTkJRVlFzUTBGQk0wTXNRMEZFVXp0aFFVRndRanM3UVVGSlFTeHhRa0ZCVXl4VlFVRlVMRU5CUVc5Q0xFTkJRWEJDTEVWQlFYVkNPMEZCUTI1Q0xIVkNRVUZQTEU5QlFVOHNRMEZCVUN4TFFVRmhMRkZCUVdJc1NVRkJlVUlzVVVGQlVTeERRVUZTTEVOQlFYcENMRWxCUVhWRExGRkJRVkVzUTBGQlVpeERRVUYyUXl4RFFVUlpPMkZCUVhaQ096dEJRVWxCTEhGQ1FVRlRMSGRDUVVGVUxFTkJRV3RETEVsQlFXeERMRVZCUVhkRE8wRkJRM0JETEc5Q1FVRkpMRTFCUVUwc1NVRkJTU3hMUVVGS0xFVkJRVTRzUTBGRVowTTdPMEZCUjNCRExHOUNRVUZKTEVsQlFVb3NSMEZCVnl4blJFRkJXQ3hEUVVodlF6dEJRVWx3UXl4dlFrRkJTU3hQUVVGS0xFZEJRV01zT0VOQlExWXNjVVJCUkZVc1IwRkZWaXhSUVVaVkxFZEJSMVlzV1VGQldTeExRVUZMTEdGQlFVd3NRMEZJUml4SFFVbFdMRXRCU2xVc1IwRkxWaXgzUWtGTVZTeEhRVTFXTEZsQlFWa3NTMEZCU3l4WFFVRk1MRU5CVGtZc1EwRktjMEk3UVVGWGFFTXNkVUpCUTBFc2QwUkJSRUVzUTBGWVowTTdRVUZoY0VNc2IwSkJRVWtzWVVGQlNpeEhRVUZ2UWl4TFFVRkxMR0ZCUVV3c1EwRmlaMEk3UVVGamNFTXNiMEpCUVVrc1YwRkJTaXhIUVVGclFpeExRVUZMTEZkQlFVd3NRMEZrYTBJN08wRkJaMEp3UXl4MVFrRkJUeXhIUVVGUUxFTkJhRUp2UXp0aFFVRjRRenM3UVVGdFFrRXNjVUpCUVZNc1YwRkJWQ3hEUVVGeFFpeEhRVUZ5UWl4RlFVRXdRanRCUVVOMFFpeHZRa0ZCU1R0QlFVTkJMREpDUVVGUExFdEJRVXNzVTBGQlRDeERRVUZsTEVkQlFXWXNSVUZCYjBJc1NVRkJjRUlzUlVGQk1FSXNUVUZCTVVJc1EwRkJVQ3hEUVVSQk8ybENRVUZLTEVOQlJVVXNUMEZCVHl4RFFVRlFMRVZCUVZVN1FVRkRVaXd5UWtGQlR5eFBRVUZQTEVkQlFWQXNRMEZCVUN4RFFVUlJPMmxDUVVGV08yRkJTRTQ3VTBGdVNWVXNSVUV5U1ZJc1JVRkJReXh4UWtGQmIwSXNSVUZCY0VJc1JVRkJkVUlzY1VKQlFXOUNMRVZCUVhCQ0xFVkJRWFZDTEhGQ1FVRnZRaXhGUVVGd1FpeEZRVUYxUWl4eFFrRkJiMElzUlVGQmNFSXNSVUZCZFVJc2MwSkJRWEZDTEVWQlFYSkNMRVZCUVhkQ0xIRkNRVUZ2UWl4RlFVRndRaXhGUVVGMVFpeHhRa0ZCYjBJc1JVRkJjRUlzUlVGQmRVSXNjMEpCUVhGQ0xFVkJRWEpDTEVWQlFYZENMRFJDUVVFeVFpeEZRVUV6UWl4RlFVRTRRaXhyUWtGQmFVSXNSVUZCYWtJc1JVRkJiMElzWTBGQllTeEZRVUZpTEVWQk0wbDBUeXhEUVVGSUxFVkJNa2t5VUN4SlFVRkhMRU5CUVVNc1ZVRkJVeXhQUVVGVUxFVkJRV2xDTEUxQlFXcENMRVZCUVhkQ0xFOUJRWGhDTEVWQlFXZERPMEZCUTNKVExIbENRVVJ4VXpzN1FVRkhjbE1zWjBKQlFVa3NVVUZCVVN4UlFVRlJMR1ZCUVZJc1EwRkJVaXhEUVVocFV6czdRVUZMY2xNc1owSkJRVWtzWlVGQlpTeHpRMEZCWml4RFFVeHBVenRCUVUxeVV5eG5Ra0ZCU1N4aFFVRmhMRTlCUVdJc1EwRk9hVk03TzBGQlVYSlRMRzFDUVVGUExFOUJRVkFzUjBGQmFVSXNVVUZCYWtJc1EwRlNjVk03TzBGQlZYSlRMSEZDUVVGVExGRkJRVlFzUTBGQmEwSXNSMEZCYkVJc1JVRkJkVUlzUzBGQmRrSXNSVUZCT0VJN1FVRkRNVUlzYjBKQlFVa3NRMEZCUXl4SFFVRkVMRVZCUVUwN1FVRkRUaXd5UWtGQlR5eExRVUZRTEVOQlJFMDdhVUpCUVZZN08wRkJTVUVzYjBKQlFVa3NUMEZCVHl4RFFVRkZMRTFCUVUwc1kwRkJUaXhEUVVGeFFpeEpRVUZ5UWl4RFFVRkdMRU5CVEdVN08wRkJUekZDTEc5Q1FVRkpMRmRCUVZjc1RVRkJUU3hIUVVGT0xFVkJRVmNzV1VGQldDeERRVUZZTEVOQlVITkNPMEZCVVRGQ0xHOUNRVUZKTEZWQlFWVXNTVUZCVml4RFFWSnpRanM3UVVGVk1VSXNiMEpCUVVrc1YwRkJWeXhKUVVGWUxFTkJRV2RDTEZOQlFWTXNRMEZCVkN4RFFVRm9RaXhEUVVGS0xFVkJRV3RETzBGQlF6bENMRGhDUVVGVkxFdEJRVllzUTBGRU9FSTdhVUpCUVd4RE96dEJRVWxCTEc5Q1FVRkpMRTlCUVVvc1JVRkJZU3hKUVVGaUxFVkJRVzFDTEVsQlFXNUNMRVZCUVhsQ0xFTkJRWHBDTEVOQlpEQkNPenRCUVdkQ01VSXNjVUpCUVVzc1NVRkJTU3hEUVVGS0xFVkJRVThzU1VGQlNTeFRRVUZUTEUxQlFWUXNSVUZCYVVJc1IwRkJha01zUlVGQmMwTTdRVUZEYkVNc01rSkJRVThzVTBGQlV5eERRVUZVTEVOQlFWQXNRMEZFYTBNN08wRkJSMnhETEhkQ1FVRkpMRU5CUVVNc1NVRkJSQ3hGUVVGUE8wRkJRMUFzYVVOQlJFODdjVUpCUVZnN08wRkJTVUVzTWtKQlFVOHNTMEZCU3l4TlFVRk1MRU5CUVZrc1EwRkJXaXhEUVVGUUxFTkJVR3RET3p0QlFWTnNReXgzUWtGQlNTeERRVUZETEU5QlFVUXNSVUZCVlR0QlFVTldMR3REUVVGVkxFbEJRVllzUTBGRVZUdHhRa0ZCWkN4TlFVVlBMRWxCUVVrc1UwRkJVeXhIUVVGVUxFVkJRV003UVVGRGNrSXNhME5CUVZVc1YwRkJWeXhGUVVGWUxFTkJSRmM3UVVGRmNrSXNaME5CUVZFc1NVRkJVaXhEUVVGaExFdEJRVXNzVTBGQlRDeERRVUZsTEVOQlFXWXNSVUZCYTBJc1MwRkJTeXhOUVVGTUxFTkJRUzlDTEVWQlJuRkNPM0ZDUVVGc1FpeE5RVWRCTEVsQlFVa3NVMEZCVXl4SFFVRlVMRWxCUVdkQ0xFbEJRV2hDTEVWQlFYTkNPMEZCUXpkQ0xEaENRVUZOTEVWQlFVNHNSMEZCVnl4TFFVRkxMRk5CUVV3c1EwRkJaU3hEUVVGbUxFVkJRV3RDTEV0QlFVc3NUVUZCVEN4RFFVRTNRaXhEUVVRMlFqdHhRa0ZCTVVJN2FVSkJaRmc3TzBGQmJVSkJMRzlDUVVGSkxFOUJRVW9zUlVGQllUdEJRVU5VTEhkQ1FVRkpMRTFCUVUwc1UwRkJUaXhGUVVGcFFqdEJRVU5xUWl4blEwRkJVU3hKUVVGU0xFTkJRV0VzVFVGQlRTeFRRVUZPTEVOQlFXSXNRMEZFYVVJN2NVSkJRWEpDT3p0QlFVbEJMREJDUVVGTkxGTkJRVTRzUjBGQmEwSXNVVUZCVVN4SlFVRlNMRU5CUVdFc1IwRkJZaXhEUVVGc1FpeERRVXhUTzJsQ1FVRmlPenRCUVZGQkxIVkNRVUZQTEUxQlFVMHNVMEZCVGl4SFFVRnJRaXhQUVVGc1FpeEhRVUUwUWl4UlFVRlJMRmRCUVZJc1JVRkJOVUlzUTBFelEyMUNPMkZCUVRsQ08xTkJWbkZSTEVWQmQwUnVVU3hGUVVGRExHbENRVUZuUWl4RFFVRm9RaXhGUVhoRWFWRXNRMEZCU0N4RlFYZEVNVThzU1VGQlJ5eERRVUZETEZWQlFWTXNUMEZCVkN4RlFVRnBRaXhOUVVGcVFpeEZRVUYzUWl4UFFVRjRRaXhGUVVGblF6dEJRVU16UkN4blFrRkJTU3hWUVVGVkxGRkJRVkVzV1VGQlVpeERRVUZXTEVOQlJIVkVPMEZCUlRORUxHZENRVUZKTEZWQlFWVXNVVUZCVVN4WlFVRlNMRU5CUVZZc1EwRkdkVVE3UVVGSE0wUXNaMEpCUVVrc1YwRkJWeXhSUVVGUkxHRkJRVklzUTBGQldDeERRVWgxUkR0QlFVa3pSQ3huUWtGQlNTeFZRVUZWTEZGQlFWRXNXVUZCVWl4RFFVRldMRU5CU25WRU96dEJRVTB6UkN4dFFrRkJUeXhQUVVGUUxFZEJRV2xDTEZkQlFXcENMRU5CVGpKRU96dEJRVkV6UkN4eFFrRkJVeXhYUVVGVUxFTkJRWEZDTEVOQlFYSkNMRVZCUVhkQ0xFTkJRWGhDTEVWQlFUSkNPMEZCUTNaQ0xHOUNRVUZKTEZsQlFWa3NRMEZCV2l4RFFVUnRRanRCUVVWMlFpeHZRa0ZCU1N4WlFVRlpMRU5CUVZvc1EwRkdiVUk3TzBGQlNYWkNMRzlDUVVGSkxGRkJRVkVzUTBGQlVpeERRVUZLTEVWQlFXZENPMEZCUTFvc1owTkJRVmtzV1VGQldTeERRVUZhTEVWQlFXVXNRMEZCWml4RFFVRmFMRU5CUkZrN2FVSkJRV2hDT3p0QlFVbEJMRzlDUVVGSkxGRkJRVkVzUTBGQlVpeERRVUZLTEVWQlFXZENPMEZCUTFvc1owTkJRVmtzV1VGQldTeERRVUZhTEVWQlFXVXNTVUZCWml4RFFVRmFMRU5CUkZrN2FVSkJRV2hDT3p0QlFVbEJMSFZDUVVGUE8wRkJRMGdzZFVKQlFVY3NVMEZCU0R0QlFVTkJMSFZDUVVGSExGTkJRVWc3YVVKQlJrb3NRMEZhZFVJN1lVRkJNMEk3TzBGQmEwSkJMSEZDUVVGVExGZEJRVlFzUTBGQmNVSXNTMEZCY2tJc1JVRkJORUlzVVVGQk5VSXNSVUZCYzBNN1FVRkRiRU1zYjBKQlFVa3NaMEpCUVdkQ0xFMUJRVTBzUzBGQlRpeERRVVJqT3p0QlFVZHNReXh2UWtGQlNTeERRVUZETEdGQlFVUXNSVUZCWjBJN1FVRkRhRUlzYjBOQlFXZENMRTFCUVUwc1MwRkJUaXhIUVVGakxFMUJRVTBzVFVGQlRpeERRVUZoTEZGQlFXSXNRMEZCWkN4RFFVUkJPMmxDUVVGd1FqczdRVUZKUVN4dlFrRkJTU3hGUVVGRkxGRkJRVkVzWVVGQlVpeExRVU5GTEZGQlFWRXNZVUZCVWl4RFFVUkdMRWxCUlVVc1UwRkJVeXhoUVVGVUxFTkJSa1lzUTBGQlJpeEZRVVU0UWp0QlFVTTVRaXd3UWtGQlRTeEpRVUZKTEV0QlFVb3NRMEZCVlN4dFEwRkJWaXhEUVVGT0xFTkJSRGhDTzJsQ1FVWnNRenM3UVVGTlFTeDFRa0ZCVHl4aFFVRlFMRU5CWW10RE8yRkJRWFJETzFOQk1VSXlRaXhGUVRCRGVrSXNSVUZCUXl4alFVRmhMRVZCUVdJc1JVRkJaMElzWTBGQllTeEZRVUZpTEVWQlFXZENMR05CUVdFc1JVRkJZaXhGUVVGblFpeGxRVUZqTEVWQlFXUXNSVUV4UTNwQ0xFTkJRVWdzUlVFd1F5dERMRWxCUVVjc1EwRkJReXhWUVVGVExFOUJRVlFzUlVGQmFVSXNUVUZCYWtJc1JVRkJkMElzVDBGQmVFSXNSVUZCWjBNN1FVRkRNVWNzYlVKQlFVOHNUMEZCVUN4SFFVRnBRaXhQUVVGcVFpeERRVVF3UnpzN1FVRkhNVWNzY1VKQlFWTXNUMEZCVkN4RFFVRnBRaXhEUVVGcVFpeEZRVUZ2UWp0QlFVTm9RaXgxUWtGQlR5eExRVUZMTEVWQlFVVXNTVUZCUml4TFFVRlhMRTlCUVZnc1EwRkVTVHRoUVVGd1FqdFRRVWd3UlN4RlFVOTRSU3hGUVZCMVJTeERRVUZJTEVWQlQyaEZMRWxCUVVjc1EwRkJReXhWUVVGVExFOUJRVlFzUlVGQmFVSXNUVUZCYWtJc1JVRkJkMElzVDBGQmVFSXNSVUZCWjBNN1FVRkRNVU1zYlVKQlFVOHNUMEZCVUN4SFFVRnBRaXhOUVVGcVFpeERRVVF3UXpzN1FVRkhNVU1zY1VKQlFWTXNUVUZCVkN4RFFVRm5RaXhKUVVGb1FpeEZRVUZ6UWp0QlFVTnNRaXgxUWtGQlR5eFRRVU5LTEU5QlFVOHNTMEZCU3l4SlFVRk1MRXRCUVdNc1ZVRkJja0lzU1VGQmJVTXNRMEZCUXl4TFFVRkxMR05CUVV3c1EwRkJiMElzVFVGQmNFSXNRMEZCUkN4SlFVTnVReXhQUVVGUExFdEJRVXNzVFVGQlRDeExRVUZuUWl4VlFVRjJRaXhKUVVGeFF5eERRVUZETEV0QlFVc3NZMEZCVEN4RFFVRnZRaXhSUVVGd1FpeERRVUZFTEVOQlJtcERMRU5CUkZjN1lVRkJkRUk3VTBGSVZTeEZRVk5TTEVWQlZFOHNRMEZCU0N4RlFWTkJMRWxCUVVjc1EwRkJReXhWUVVGVExFOUJRVlFzUlVGQmFVSXNUVUZCYWtJc1JVRkJkMElzVDBGQmVFSXNSVUZCWjBNN1FVRkRNVU1zWjBKQlFVa3NWVUZCVlN4UlFVRlJMRmRCUVZJc1EwRkJWaXhEUVVSelF6czdRVUZITVVNc2JVSkJRVThzVDBGQlVDeEhRVUZwUWl4aFFVRnFRaXhEUVVnd1F6czdRVUZMTVVNc2NVSkJRVk1zWVVGQlZDeERRVUYxUWl4RFFVRjJRaXhGUVVFd1FqdEJRVU4wUWl4MVFrRkJUeXhMUVVGTExFVkJRVVVzU1VGQlJpeExRVUZYTEdGQlFWZ3NTVUZCTkVJc1JVRkJSU3hQUVVGR0xFdEJRV01zVDBGQlpDeERRVVJzUWp0aFFVRXhRanRUUVV4VkxFVkJVMUlzUlVGQlF5eGhRVUZaTEVWQlFWb3NSVUZVVFN4RFFVRklMRVZCVTJNc1NVRkJSeXhEUVVGRExGVkJRVk1zVDBGQlZDeEZRVUZwUWl4TlFVRnFRaXhGUVVGM1FpeFBRVUY0UWl4RlFVRm5RenRCUVVONFJDeG5Ra0ZCU1N4VlFVRlZMRkZCUVZFc1YwRkJVaXhEUVVGV0xFTkJSRzlFT3p0QlFVZDRSQ3h0UWtGQlR5eFBRVUZRTEVkQlFXbENMR0ZCUVdwQ0xFTkJTSGRFT3p0QlFVdDRSQ3h4UWtGQlV5eGhRVUZVTEVOQlFYVkNMRU5CUVhaQ0xFVkJRVEJDTzBGQlEzUkNMSFZDUVVGUExFdEJRVXNzUlVGQlJTeEpRVUZHTEV0QlFWY3NZVUZCV0N4SlFVRTBRaXhGUVVGRkxFOUJRVVlzUzBGQll5eFBRVUZrTEVOQlJHeENPMkZCUVRGQ08xTkJUSGRDTEVWQlUzUkNMRVZCUVVNc1lVRkJXU3hGUVVGYUxFVkJWRzlDTEVOQlFVZ3NSVUZUUVN4SlFVRkhMRU5CUVVNc1ZVRkJVeXhQUVVGVUxFVkJRV2xDTEUxQlFXcENMRVZCUVhkQ0xFOUJRWGhDTEVWQlFXZERPMEZCUTNoRUxHMUNRVUZQTEU5QlFWQXNSMEZCYVVJc1VVRkJha0lzUTBGRWQwUTdPMEZCUjNoRUxIRkNRVUZUTEZGQlFWUXNRMEZCYTBJc1EwRkJiRUlzUlVGQmNVSTdRVUZEYWtJc2RVSkJRVThzUzBGQlN5eEZRVUZGTEVsQlFVWXNTMEZCVnl4UlFVRllMRU5CUkVzN1lVRkJja0k3VTBGSWQwSXNSVUZQZEVJc1JVRlFjVUlzUTBGQlNDeEZRVTlrTEVsQlFVY3NRMEZCUXl4VlFVRlRMRTlCUVZRc1JVRkJhVUlzVFVGQmFrSXNSVUZCZDBJc1QwRkJlRUlzUlVGQlowTTdRVUZETVVNc2JVSkJRVThzVDBGQlVDeEhRVUZwUWl4SFFVRnFRaXhEUVVRd1F6dFRRVUZvUXl4RlFVZFNMRVZCU0U4c1EwRkJTQ3hGUVVkQkxFbEJRVWNzUTBGQlF5eFZRVUZUTEU5QlFWUXNSVUZCYVVJc1RVRkJha0lzUlVGQmQwSXNUMEZCZUVJc1JVRkJaME03UVVGRE1VTXNaMEpCUVVrc1ZVRkJWU3hSUVVGUkxGZEJRVklzUTBGQlZpeERRVVJ6UXp0QlFVVXhReXhuUWtGQlNTeFZRVUZWTEZGQlFWRXNXVUZCVWl4RFFVRldMRU5CUm5ORE8wRkJSekZETEdkQ1FVRkpMRmRCUVZjc1VVRkJVU3hoUVVGU0xFTkJRVmdzUTBGSWMwTTdRVUZKTVVNc1owSkJRVWtzVlVGQlZTeFJRVUZSTEZsQlFWSXNRMEZCVml4RFFVcHpRenRCUVVzeFF5eG5Ra0ZCU1N4VlFVRlZMRkZCUVZFc1dVRkJVaXhEUVVGV0xFTkJUSE5ET3p0QlFVOHhReXh0UWtGQlR5eFBRVUZRTEVkQlFXbENMRmRCUVdwQ0xFTkJVREJET3p0QlFWTXhReXhuUWtGQlNTeGxRVUZsTEVWQlFXWXNRMEZVYzBNN1FVRlZNVU1zWjBKQlFVa3NZVUZCWVN4RlFVRmlMRU5CVm5ORE96dEJRVmt4UXl4eFFrRkJVeXhYUVVGVUxFTkJRWEZDTEU5QlFYSkNMRVZCUVRoQ0xGVkJRVGxDTEVWQlFUQkRMRkZCUVRGRExFVkJRVzlFTEVkQlFYQkVMRVZCUVhsRUxGTkJRWHBFTEVWQlFXOUZPMEZCUTJoRkxIRkNRVUZMTEU5QlFVd3NSMEZCWlN4UFFVRm1MRU5CUkdkRk8wRkJSV2hGTEhGQ1FVRkxMRlZCUVV3c1IwRkJhMElzWTBGQll5eFpRVUZrTEVOQlJqaERPMEZCUjJoRkxIRkNRVUZMTEZGQlFVd3NSMEZCWjBJc1dVRkJXU3hWUVVGYUxFTkJTR2RFTzBGQlNXaEZMSEZDUVVGTExFZEJRVXdzUjBGQlZ5eFBRVUZQTEVsQlFWQXNSMEZCWXl4UFFVRlBMRWRCUVZBc1EwRkJaQ3hIUVVFMFFpeFRRVUUxUWl4RFFVcHhSRHRCUVV0b1JTeHhRa0ZCU3l4VFFVRk1MRWRCUVdsQ0xFOUJRVkVzVTBGQlVDeExRVUZ4UWl4UlFVRnlRaXhIUVVGcFF5eFRRVUZzUXl4SFFVRTRReXhKUVVFNVF5eERRVXdyUXpzN1FVRlBhRVVzYjBKQlFVa3NVVUZCVVN4UlFVRkRMRWxCUVZrc1UwRkJVeXhOUVVGVUxFbEJRVzlDTEVOQlFXcERMRU5CVUc5RU8wRkJVV2hGTEc5Q1FVRkpMR05CUVdNc1EwRkJaQ3hEUVZJMFJEdEJRVk5vUlN4dlFrRkJTU3hoUVVGaExFdEJRV0lzUTBGVU5FUTdRVUZWYUVVc2IwSkJRVWtzV1VGQldTeExRVUZhTEVOQlZqUkVPMEZCVjJoRkxHOUNRVUZKTEd0Q1FVRnJRaXhMUVVGc1FpeERRVmcwUkR0QlFWbG9SU3h2UWtGQlNTeExRVUZLTEVOQldtZEZPenRCUVdOb1JTeHhRa0ZCU3l4SlFVRkpMRkZCUVVvc1NVRkJaMElzVlVGQmNrSXNSVUZCYVVNN1FVRkROMElzZDBKQlFVa3NWMEZCVnl4alFVRllMRU5CUVRCQ0xGRkJRVEZDTEVOQlFVb3NSVUZCZVVNN1FVRkRja01zTkVKQlFVa3NWMEZCVnl4WFFVRlhMRkZCUVZnc1EwRkJXQ3hEUVVScFF6dEJRVVZ5UXl3MFFrRkJTU3hSUVVGUkxGRkJRVklzUzBGQmNVSXNVMEZCVXl4TlFVRlVMRVZCUVdsQ08wRkJRM1JETEdkRFFVRkpMRU5CUVVNc1MwRkJSQ3hGUVVGUk8wRkJRMUlzZDBOQlFWRXNSVUZCVWl4RFFVUlJPelpDUVVGYU96dEJRVWxCTEd0RFFVRk5MRkZCUVU0c1NVRkJhMElzVVVGQmJFSXNRMEZNYzBNN2VVSkJRVEZETzNGQ1FVWktPMmxDUVVSS096dEJRV0ZCTEhGQ1FVRkxMRWxCUVVrc1NVRkJTU3hEUVVGS0xFVkJRVThzU1VGQlNTeExRVUZLTEVWQlFWY3NSMEZCTTBJc1JVRkJaME03UVVGRE5VSXNkMEpCUVVrc1VVRkJVU3hUUVVGVExFTkJRVlFzUTBGQlVpeERRVVIzUWp0QlFVVTFRaXgzUWtGQlNTeFJRVUZSTEV0QlFWSXNRMEZCU2l4RlFVRnZRanRCUVVOb1FpeDFRMEZCWlN4TlFVRk5MRXRCUVU0c1NVRkJaU3hEUVVGbUxFTkJSRU03TzBGQlIyaENMRFJDUVVGSkxFTkJRVU1zVlVGQlJDeEpRVUZsTEUxQlFVMHNWVUZCVGl4RlFVRnJRanRCUVVOcVF5eDVRMEZCWVN4SlFVRmlMRU5CUkdsRE8zbENRVUZ5UXpzN1FVRkpRU3cwUWtGQlNTeERRVUZETEZOQlFVUXNTVUZCWXl4TlFVRk5MRk5CUVU0c1JVRkJhVUk3UVVGREwwSXNkME5CUVZrc1NVRkJXaXhEUVVRclFqdDVRa0ZCYmtNN08wRkJTVUVzTkVKQlFVa3NRMEZCUXl4bFFVRkVMRXRCUVhGQ0xFMUJRVTBzUzBGQlRpeEpRVUZsTEUxQlFVMHNaVUZCVGl4RFFVRndReXhGUVVFMFJEdEJRVU0xUkN3NFEwRkJhMElzU1VGQmJFSXNRMEZFTkVRN2VVSkJRV2hGTzNGQ1FWaEtMRTFCWTA4c1NVRkJTU3hEUVVGRExGVkJRVVFzU1VGQlpTeFRRVUZUTEV0QlFWUXNRMEZCWml4RlFVRm5RenRCUVVOMlF5dzBRa0ZCU1N4UFFVRlBMRTFCUVUwc1QwRkJUaXhMUVVGclFpeFZRVUY2UWl4RlFVRnhRenRCUVVOeVF5eDVRMEZCWVN4SlFVRmlMRU5CUkhGRE8zbENRVUY2UXp0eFFrRkVSeXhOUVVsQkxFbEJRVWtzUTBGQlF5eFRRVUZFTEVsQlFXTXNVVUZCVVN4TFFVRlNMRU5CUVdRc1JVRkJPRUk3UVVGRGNrTXNiME5CUVZrc1NVRkJXaXhEUVVSeFF6dHhRa0ZCYkVNN2FVSkJjRUpZT3p0QlFYbENRU3h4UWtGQlN5eExRVUZNTEVkQlFXRXNVVUZCVVN4WFFVRlNMRU5CY0VSdFJEdEJRWEZFYUVVc2NVSkJRVXNzVlVGQlRDeEhRVUZyUWl4VlFVRnNRaXhEUVhKRVowVTdRVUZ6UkdoRkxIRkNRVUZMTEZOQlFVd3NSMEZCYVVJc1UwRkJha0lzUTBGMFJHZEZPMEZCZFVSb1JTeHhRa0ZCU3l4TFFVRk1MRWRCUVdFc1MwRkJZaXhEUVhaRVowVTdRVUYzUkdoRkxIRkNRVUZMTEdWQlFVd3NSMEZCZFVJc1pVRkJka0lzUTBGNFJHZEZPMkZCUVhCRk96dEJRVEpFUVN4M1FrRkJXU3hUUVVGYUxFTkJRWE5DTEU5QlFYUkNMRWRCUVdkRExFOUJRV2hETEVOQmRrVXdRenRCUVhkRk1VTXNkMEpCUVZrc1UwRkJXaXhEUVVGelFpeEpRVUYwUWl4SFFVRTJRaXhoUVVFM1FpeERRWGhGTUVNN1UwRkJhRU1zUlVFd1JWSXNSVUZCUXl4alFVRmhMRVZCUVdJc1JVRkJaMElzWTBGQllTeEZRVUZpTEVWQlFXZENMR05CUVdFc1JVRkJZaXhGUVVGblFpeGxRVUZqTEVWQlFXUXNSVUZCYVVJc1lVRkJXU3hGUVVGYUxFVkJNVVV6UkN4RFFVRklMRVZCTUVVclJTeEpRVUZITEVOQlFVTXNWVUZCVXl4UFFVRlVMRVZCUVdsQ0xFMUJRV3BDTEVWQlFYZENMRTlCUVhoQ0xFVkJRV2RETzBGQlEzcElMR2RDUVVGSkxGVkJRVlVzVVVGQlVTeFhRVUZTTEVOQlFWWXNRMEZFY1VnN08wRkJSM3BJTEhsQ1FVRmhMRWxCUVdJc1IwRkJiMElzUTBGQmNFSXNRMEZJZVVnN1FVRkpla2dzZVVKQlFXRXNTMEZCWWl4SFFVRnhRaXhEUVVGeVFpeERRVXA1U0R0QlFVdDZTQ3g1UWtGQllTeExRVUZpTEVkQlFYRkNMRU5CUVhKQ0xFTkJUSGxJTzBGQlRYcElMSGxDUVVGaExFMUJRV0lzUjBGQmMwSXNRMEZCZEVJc1EwRk9lVWc3UVVGUGVrZ3NlVUpCUVdFc1MwRkJZaXhIUVVGeFFpeERRVUZ5UWl4RFFWQjVTRHRCUVZGNlNDeDVRa0ZCWVN4TFFVRmlMRWRCUVhGQ0xFTkJRWEpDTEVOQlVubElPMEZCVTNwSUxIbENRVUZoTEUxQlFXSXNSMEZCYzBJc1EwRkJkRUlzUTBGVWVVZzdRVUZWZWtnc2VVSkJRV0VzVFVGQllpeEhRVUZ6UWl4RFFVRjBRaXhEUVZaNVNEdEJRVmQ2U0N4NVFrRkJZU3hMUVVGaUxFZEJRWEZDTEVOQlFYSkNMRU5CV0hsSU96dEJRV0Y2U0N4dFFrRkJUeXhQUVVGUUxFZEJRV2xDTEZsQlFXcENMRU5CWW5sSU96dEJRV1Y2U0N4eFFrRkJVeXhaUVVGVUxFTkJRWE5DTEVsQlFYUkNMRVZCUVRSQ0xFdEJRVFZDTEVWQlFXMURMRXRCUVc1RExFVkJRVEJETzBGQlEzUkRMSEZDUVVGTExFbEJRVXdzUjBGQldTeFBRVUZQTEVsQlFWQXNRMEZCV2l4RFFVUnpRenRCUVVWMFF5eHhRa0ZCU3l4TFFVRk1MRWRCUVdFc1MwRkJZaXhEUVVaelF6dEJRVWQwUXl4eFFrRkJTeXhMUVVGTUxFZEJRV0VzUzBGQllpeERRVWh6UXp0aFFVRXhRenM3UVVGTlFTeDVRa0ZCWVN4VFFVRmlMRU5CUVhWQ0xFOUJRWFpDTEVkQlFXbERMRTlCUVdwRExFTkJja0o1U0R0QlFYTkNla2dzZVVKQlFXRXNVMEZCWWl4RFFVRjFRaXhKUVVGMlFpeEhRVUU0UWl4alFVRTVRaXhEUVhSQ2VVZzdVMEZCYUVNc1JVRjNRblpHTEVWQlFVTXNZVUZCV1N4RlFVRmFMRVZCZUVKeFJpeERRVUZJTEVWQmQwSnFSU3hKUVVGSExFTkJRVU1zVlVGQlV5eFBRVUZVTEVWQlFXbENMRTFCUVdwQ0xFVkJRWGRDTEU5QlFYaENMRVZCUVdkRE8wRkJRM2hFTEdkQ1FVRkpMRlZCUVZVc1VVRkJVU3hYUVVGU0xFTkJRVllzUTBGRWIwUTdPMEZCUjNoRUxHMUNRVUZQTEU5QlFWQXNSMEZCYVVJc1YwRkJha0lzUTBGSWQwUTdPMEZCUzNoRUxIRkNRVUZUTEZkQlFWUXNRMEZCY1VJc1NVRkJja0lzUlVGQk1rSTdRVUZEZGtJc2NVSkJRVXNzU1VGQlRDeEhRVUZaTEU5QlFVOHNTVUZCVUN4RFFVRmFMRU5CUkhWQ08yRkJRVE5DT3p0QlFVbEJMSGRDUVVGWkxGTkJRVm9zUTBGQmMwSXNUMEZCZEVJc1IwRkJaME1zVDBGQmFFTXNRMEZVZDBRN1FVRlZlRVFzZDBKQlFWa3NVMEZCV2l4RFFVRnpRaXhKUVVGMFFpeEhRVUUyUWl4aFFVRTNRaXhEUVZaM1JEdFRRVUZvUXl4RlFWbDBRaXhGUVVGRExHRkJRVmtzUlVGQldpeEZRVnB2UWl4RFFVRklMRVZCV1VFc1NVRkJSeXhEUVVGRExGVkJRVk1zVDBGQlZDeEZRVUZwUWl4TlFVRnFRaXhGUVVGM1FpeFBRVUY0UWl4RlFVRm5RenRCUVVONFJDeG5Ra0ZCU1N4WFFVRlhMRkZCUVZFc1YwRkJVaXhEUVVGWUxFTkJSRzlFTzBGQlJYaEVMR2RDUVVGSkxGTkJRVk1zVVVGQlVTeHRRa0ZCVWl4RFFVRlVMRU5CUm05RU96dEJRVWw0UkN4dFFrRkJUeXhQUVVGUUxFZEJRV2xDTEZOQlFXcENMRU5CU25kRU96dEJRVTE0UkN4eFFrRkJVeXhUUVVGVUxFTkJRVzFDTEVOQlFXNUNMRVZCUVhOQ0xFTkJRWFJDTEVWQlFYbENPMEZCUTNKQ0xHOUNRVUZKTEVsQlFVb3NRMEZFY1VJN08wRkJSM0pDTEhGQ1FVRkxMRWxCUVVrc1NVRkJTaXhKUVVGWkxFTkJRV3BDTEVWQlFXOUNPMEZCUTJoQ0xIZENRVUZKTEVWQlFVVXNVVUZCVVN4RFFVRlNMRU5CUVVZc1JVRkJZenRCUVVOa0xDdENRVUZQTEZGQlFWRXNSVUZCVWl4RFFVUlBPMEZCUldRc05rSkJRVXNzU1VGQlRDeEpRVUZoTEZOQlFXSXNRMEZHWXp0eFFrRkJiRUk3TzBGQlMwRXNkMEpCUVVrc1UwRkJVeXhGUVVGRkxFbEJRVVlzUTBGQlZDeERRVTVaTzBGQlQyaENMSGRDUVVGSkxGTkJRVk1zUlVGQlJTeEpRVUZHTEVOQlFWUXNRMEZRV1RzN1FVRlRhRUlzZDBKQlFVa3NWMEZCVnl4TlFVRllMRVZCUVcxQ08wRkJRMjVDTEdsRFFVUnRRanR4UWtGQmRrSXNUVUZGVHl4SlFVRkpMRk5CUVZNc1RVRkJWQ3hMUVVGdlFpeFRRVUZUTEUxQlFWUXNRMEZCY0VJc1JVRkJjME03UVVGRE4wTXNORUpCUVVrc1lVRkJZU3hOUVVGaUxFMUJRWGxDTEdGQlFXRXNUVUZCWWl4RFFVRjZRaXhGUVVFclF6dEJRVU12UXl4dFEwRkJUeXhSUVVGUkxFVkJRVklzUTBGRWQwTTdRVUZGTDBNc2FVTkJRVXNzU1VGQlRDeEpRVUZoTEUxQlFXSXNRMEZHSzBNN2VVSkJRVzVFTEUxQlIwOHNTVUZCU1N4UFFVRlBMRTFCUVZBc1EwRkJTaXhGUVVGdlFqdEJRVU4wUWl4dFEwRkJUeXhSUVVGUkxFVkJRVklzUTBGRVpUdEJRVVYwUWl4cFEwRkJTeXhKUVVGTUxFbEJRV0VzVFVGQllpeERRVVp6UWp0NVFrRkJjRUlzVFVGSFFUdEJRVU5JTEdkRFFVRkpMR0ZCUVdFc1ZVRkJWU3hOUVVGV0xFVkJRV3RDTEUxQlFXeENMRU5CUVdJc1EwRkVSRHRCUVVWSUxHZERRVUZKTEZWQlFVb3NSVUZCWjBJN1FVRkRXaXgxUTBGQlR5eFJRVUZSTEVWQlFWSXNRMEZFU3p0QlFVVmFMSEZEUVVGTExFbEJRVXdzU1VGQllTeFZRVUZpTEVOQlJsazdOa0pCUVdoQ08zbENRVXhITzNGQ1FVcEtMRTFCWTBFN1FVRkRTQ3dyUWtGQlR5eFJRVUZSTEVWQlFWSXNRMEZFU2p0QlFVVklMRFpDUVVGTExFbEJRVXdzU1VGQllTeE5RVUZpTEVOQlJrYzdjVUpCWkVFN2FVSkJXRmc3TzBGQkswSkJMSEZDUVVGTExFbEJRVWtzU1VGQlNpeEpRVUZaTEVOQlFXcENMRVZCUVc5Q08wRkJRMmhDTEhkQ1FVRkpMRVZCUVVVc1VVRkJVU3hEUVVGU0xFTkJRVVlzUlVGQll6dEJRVU5rTEN0Q1FVRlBMRkZCUVZFc1JVRkJVaXhEUVVSUE8wRkJSV1FzTmtKQlFVc3NTVUZCVEN4SlFVRmhMRVZCUVVVc1NVRkJSaXhEUVVGaUxFTkJSbU03Y1VKQlFXeENPMmxDUVVSS096dEJRVTlCTEhWQ1FVRlBMRWxCUVZBc1EwRjZRM0ZDTzJGQlFYcENPenRCUVRSRFFTeHhRa0ZCVXl4WlFVRlVMRU5CUVhOQ0xFdEJRWFJDTEVWQlFUWkNPMEZCUXpOQ0xHOUNRVUZKTEU5QlFVOHNZMEZCVUN4RlFVRjFRanRCUVVONlFpd3lRa0ZCVHl4UFFVRlBMR05CUVZBc1EwRkJjMElzUzBGQmRFSXNRMEZCVUN4RFFVUjVRanRwUWtGQk0wSXNUVUZGVHl4SlFVRkpMRTFCUVUwc1UwRkJUaXhGUVVGcFFqdEJRVU14UWl3eVFrRkJUeXhOUVVGTkxGTkJRVTRzUTBGRWJVSTdhVUpCUVhKQ0xFMUJSVUVzU1VGQlNTeE5RVUZOTEZkQlFVNHNSVUZCYlVJN1FVRkROVUlzTWtKQlFVOHNUVUZCVFN4WFFVRk9MRU5CUVd0Q0xGTkJRV3hDTEVOQlJIRkNPMmxDUVVGMlFqdGhRVXhVTzFOQmJFUjNRaXhGUVRSRWRFSXNSVUZCUXl4eFFrRkJiMElzUlVGQmNFSXNSVUZCZFVJc1lVRkJXU3hGUVVGYUxFVkJOVVJJTEVOQlFVZ3NSVUUwUkhWQ0xFbEJRVWNzUTBGQlF5eFZRVUZUTEU5QlFWUXNSVUZCYVVJc1RVRkJha0lzUlVGQmQwSXNUMEZCZUVJc1JVRkJaME03UVVGREwwVXNaMEpCUVVrc1ZVRkJWU3hSUVVGUkxGbEJRVklzUTBGQlZpeERRVVF5UlRzN1FVRkhMMFVzWjBKQlFVa3NVMEZCVXl4UlFVRlJMR2xDUVVGU0xFTkJRVlFzUTBGSU1rVTdRVUZKTDBVc1owSkJRVWtzVlVGQlZTeFJRVUZSTEcxQ1FVRlNMRU5CUVZZc1EwRktNa1U3UVVGTEwwVXNaMEpCUVVrc1ZVRkJWU3hSUVVGUkxHMUNRVUZTTEVOQlFWWXNRMEZNTWtVN1FVRk5MMFVzWjBKQlFVa3NWMEZCVnl4UlFVRlJMRzlDUVVGU0xFTkJRVmdzUTBGT01rVTdRVUZQTDBVc1owSkJRVWtzVlVGQlZTeFJRVUZSTEcxQ1FVRlNMRU5CUVZZc1EwRlFNa1U3UVVGUkwwVXNaMEpCUVVrc1kwRkJZeXhSUVVGUkxIVkNRVUZTTEVOQlFXUXNRMEZTTWtVN08wRkJWUzlGTEdkQ1FVRkpMRmxCUVZrc1VVRkJVU3hqUVVGU0xFTkJRVm9zUTBGV01rVTdPMEZCV1M5RkxHMUNRVUZQTEU5QlFWQXNSMEZCYVVJc1NVRkJha0lzUTBGYUswVTdPMEZCWXk5RkxIRkNRVUZUTEVsQlFWUXNRMEZCWXl4RFFVRmtMRVZCUVdsQ0xFTkJRV3BDTEVWQlFXOUNPMEZCUTJoQ0xHOUNRVUZKTEZGQlFWRXNSVUZCUlN4SFFVRkhMRU5CUVVnc1JVRkJWaXhEUVVSWk8wRkJSV2hDTEhGQ1FVRkxMRU5CUVV3c1JVRkJVU3hEUVVGU0xFVkJRVmNzUzBGQldDeEZRVUZyUWl4RFFVRnNRaXhGUVVablFqdEJRVWRvUWl4MVFrRkJUeXhMUVVGUUxFTkJTR2RDTzJGQlFYQkNPenRCUVUxQkxIRkNRVUZUTEVsQlFWUXNRMEZCWXl4RFFVRmtMRVZCUVdsQ0xFTkJRV3BDTEVWQlFXOUNMRXRCUVhCQ0xFVkJRVEpDTEV0QlFUTkNMRVZCUVd0RE8wRkJRemxDTEc5Q1FVRkpMRTFCUVUwc1EwRkJUaXhGUVVGVE8wRkJRMVFzTWtKQlJGTTdhVUpCUVdJN08wRkJTVUVzYjBKQlFVa3NVVUZCVVN4TlFVRk5MRXRCUVU0c1EwRkJVaXhEUVV3d1FqdEJRVTA1UWl4dlFrRkJTU3hoUVVGaExFdEJRV0lzUTBGT01FSTdPMEZCVVRsQ0xHOUNRVUZKTEZGQlFWRXNRMEZCVWl4TFFVRmpMRkZCUVZFc1EwRkJVaXhEUVVGa0xFVkJRVEJDTzBGQlF6RkNMREpDUVVGUExFTkJRVkFzUlVGQlZTeERRVUZXTEVWQlFXRXNTMEZCWWl4RlFVRnZRaXhMUVVGd1FpeEZRVVF3UWp0cFFrRkJPVUlzVFVGRlR5eEpRVUZKTEV0QlFVc3NTVUZCVEN4RlFVRlhPenM3T3p0QlFVdHNRaXgzUWtGQlNTeERRVUZETEZOQlFWTXNRMEZCVkN4RFFVRkVMRVZCUVdNN1FVRkRaQ3h0UTBGQlZ5eERRVUZZTEVWQlFXTXNTMEZCWkN4RlFVRnhRaXhMUVVGeVFpeEZRVVJqTzBGQlJXUXNaME5CUVZFc1RVRkJUU3hMUVVGT0xFTkJRVklzUTBGR1l6dHhRa0ZCYkVJN08wRkJTMEVzTkVKQlFWRXNXVUZCV1N4TFFVRmFMRVZCUVcxQ0xFbEJRVWtzVFVGQlNpeERRVUZYTEU5QlFVOHNUVUZCVUN4RlFVRmxMRU5CUVRGQ0xFVkJRVFpDTEVOQlFUZENMRU5CUVc1Q0xFTkJRVklzUTBGV2EwSTdhVUpCUVdZc1RVRlhRU3hKUVVGSkxGRkJRVkVzUTBGQlVpeERRVUZLTEVWQlFXZENPMEZCUTI1Q0xIZENRVUZKTEZGQlFWRXNRMEZCVWl4RFFVRktMRVZCUVdkQ08wRkJRMW9zTkVKQlFVa3NSVUZCUlN4UFFVRkdMRXRCUVdNc1JVRkJSU3hQUVVGR0xFbEJRMlFzUlVGQlJTeFRRVUZHTEV0QlFXZENMRVZCUVVVc1UwRkJSaXhKUVVOb1FpeEZRVUZGTEVkQlFVWXNTMEZCVlN4RlFVRkZMRWRCUVVZc1JVRkJUenRCUVVOcVFpeG5RMEZCU1N4aFFVRmhMRlZCUVZVc1JVRkJSU3hWUVVGR0xFVkJRV01zUlVGQlJTeFZRVUZHTEVOQlFYSkRMRU5CUkdFN1FVRkZha0lzWjBOQlFVa3NWVUZCU2l4RlFVRm5RanRCUVVOYUxIZERRVUZSTEZsQlFWa3NTMEZCV2l4RlFVTktMRWxCUVVrc1RVRkJTaXhEUVVGWExFOUJRVThzUzBGQlVDeEZRVUZqTEVOQlFYcENMRVZCUVRSQ0xGVkJRVFZDTEVOQlJFa3NRMEZCVWl4RFFVUlpPelpDUVVGb1FqdEJRVWxCTEc5RFFVRlJMR0ZCUVdFc1EwRkJZaXhGUVVGblFpeERRVUZvUWl4RlFVRnRRaXhMUVVGdVFpeEZRVUV3UWl4TFFVRXhRaXhGUVVGcFF5eExRVUZxUXl4RFFVRlNMRU5CVG1sQ08zbENRVVp5UWl4TlFWTlBPMEZCUTBnc2IwTkJRVkVzV1VGQldTeExRVUZhTEVWQlFXMUNMRWxCUVVrc1RVRkJTaXhEUVVGWExFOUJRVThzUzBGQlVDeEZRVUZqTEVOQlFYcENMRVZCUVRSQ0xFTkJRVFZDTEVOQlFXNUNMRU5CUVZJc1EwRkVSenRCUVVWSUxIbERRVUZoTEVsQlFXSXNRMEZHUnp0NVFrRlVVRHR4UWtGRVNpeE5RV05QTzBGQlEwZ3NaME5CUVZFc1dVRkJXU3hMUVVGYUxFVkJRVzFDTEVsQlFVa3NUVUZCU2l4RFFVRlhMRTlCUVU4c1MwRkJVQ3hGUVVGakxFTkJRWHBDTEVWQlFUUkNMRU5CUVRWQ0xFTkJRVzVDTEVOQlFWSXNRMEZFUnp0QlFVVklMSEZEUVVGaExFbEJRV0lzUTBGR1J6dHhRa0ZrVUR0cFFrRkVSeXhOUVcxQ1FTeEpRVUZKTEZGQlFWRXNRMEZCVWl4RFFVRktMRVZCUVdkQ08wRkJRMjVDTEhkQ1FVRkpMRU5CUVVNc1VVRkJVU3hEUVVGU0xFTkJRVVFzUlVGQllUdEJRVU5pTEdkRFFVRlJMRmxCUVZrc1MwRkJXaXhGUVVGdFFpeEpRVUZKTEUxQlFVb3NRMEZCVnl4UFFVRlBMRXRCUVZBc1JVRkJZeXhEUVVGNlFpeEZRVUUwUWl4RFFVRTFRaXhEUVVGdVFpeERRVUZTTEVOQlJHRTdRVUZGWWl4eFEwRkJZU3hKUVVGaUxFTkJSbUU3Y1VKQlFXcENMRTFCUjA4c1NVRkJTU3hGUVVGRkxFbEJRVVlzUzBGQlZ5eEZRVUZGTEVsQlFVWXNSVUZCVVR0QlFVTXhRaXhuUTBGQlVTeFpRVUZaTEV0QlFWb3NSVUZCYlVJc1NVRkJTU3hOUVVGS0xFTkJRVmNzVDBGQlR5eExRVUZRTEVWQlFXTXNRMEZCZWtJc1JVRkJORUlzUTBGQk5VSXNRMEZCYmtJc1EwRkJVaXhEUVVRd1FqdHhRa0ZCZGtJN2FVSkJTa29zVFVGUFFTeEpRVUZKTEZOQlFWTXNRMEZCVkN4RFFVRktMRVZCUVdsQ08wRkJRM0JDTEhkQ1FVRkpMRU5CUVVNc1UwRkJVeXhEUVVGVUxFTkJRVVFzUlVGQll6dEJRVU5rTEhGRFFVRmhMRWxCUVdJc1EwRkVZenR4UWtGQmJFSTdPMEZCU1VFc05FSkJRVkVzV1VGQldTeExRVUZhTEVWQlFXMUNMRWxCUVVrc1RVRkJTaXhEUVVGWExFOUJRVThzVFVGQlVDeEZRVUZsTEVOQlFURkNMRVZCUVRaQ0xFTkJRVGRDTEVOQlFXNUNMRU5CUVZJc1EwRk1iMEk3YVVKQlFXcENPenRCUVZGUUxHOUNRVUZKTEV0QlFVb3NSVUZCVnp0QlFVTlFMREJDUVVGTkxFdEJRVTRzU1VGQlpTeExRVUZtTEVOQlJFODdhVUpCUVZnN08wRkJTVUVzYjBKQlFVa3NWVUZCU2l4RlFVRm5RanRCUVVOYUxDdENRVUZYTEVOQlFWZ3NSVUZCWXl4TFFVRmtMRVZCUVhGQ0xFdEJRWEpDTEVWQlJGazdhVUpCUVdoQ08yRkJNMFJLT3p0QlFXZEZRU3h4UWtGQlV5eFpRVUZVTEVOQlFYTkNMRU5CUVhSQ0xFVkJRWGxDTEVOQlFYcENMRVZCUVRSQ0xFdEJRVFZDTEVWQlFXMURMRXRCUVc1RExFVkJRVEJETEV0QlFURkRMRVZCUVdsRU8wRkJRemRETEc5Q1FVRkpMRmxCUVZrc1JVRkJSU3hSUVVGR0xFTkJSRFpDTzBGQlJUZERMRzlDUVVGSkxHRkJRV0VzVVVGQlVTeFRRVUZTTEVWQlFXMUNMRVZCUVVVc1VVRkJSaXhEUVVGb1F5eERRVVo1UXp0QlFVYzNReXh2UWtGQlNTeFpRVUZaTEZkQlFWY3NVVUZCV0N4RFFVZzJRanM3UVVGTE4wTXNiMEpCUVVrc1QwRkJUeXhWUVVGVkxFMUJRVllzUTBGTWEwTTdRVUZOTjBNc2IwSkJRVWtzVDBGQlR5eFZRVUZWTEUxQlFWWXNRMEZPYTBNN1FVRlBOME1zYjBKQlFVa3NUVUZCVFN4UFFVRlBMRWxCUVZBc1IwRkJZeXhKUVVGa0xFZEJRWEZDTEVsQlFYSkNMRU5CVUcxRE96dEJRVk0zUXl4eFFrRkJTeXhKUVVGSkxFbEJRVWtzUTBGQlNpeEZRVUZQTEVsQlFVa3NSMEZCU2l4RlFVRlRMRWRCUVhwQ0xFVkJRVGhDTzBGQlF6RkNMSGRDUVVGSkxGZEJRVmNzVlVGQlZTeERRVUZXTEVOQlFWZ3NRMEZFYzBJN1FVRkZNVUlzZDBKQlFVa3NXVUZCV1N4VlFVRlZMRU5CUVZZc1EwRkJXaXhEUVVaelFqdEJRVWN4UWl3MlFrRkJVeXhEUVVGVUxFTkJTREJDT3p0QlFVc3hRaXgzUWtGQlNTeERRVUZETEZGQlFVUXNSVUZCVnp0QlFVTllMRFJDUVVGSkxGTkJRVW9zUlVGQlpUczdRVUZGV0N4dlEwRkJVU3haUVVGWkxFdEJRVm9zUlVGRFNpeEpRVUZKTEUxQlFVb3NRMEZCVnl4UFFVRlBMRTFCUVZBc1JVRkJaU3hKUVVFeFFpeEZRVUZuUXl4VFFVRm9ReXhEUVVSSkxFTkJRVklzUTBGR1Z6dDVRa0ZCWmp0eFFrRkVTaXhOUVUxUE8wRkJRMGdzTmtKQlFVc3NVVUZCVEN4RlFVRmxMRk5CUVdZc1JVRkJNRUlzUzBGQk1VSXNSVUZCYVVNc1MwRkJha01zUlVGRVJ6dHhRa0ZPVURzN1FVRlZRU3gzUWtGQlNTeFJRVUZSTEZGQlFWSXNTMEZCY1VJc1UwRkJVeXhMUVVGVUxFVkJRV2RDTzBGQlEzSkRMR2xEUVVGVExGTkJRVk1zUzBGQlZDeERRVVEwUWp0eFFrRkJla003YVVKQlprbzdPMEZCYjBKQkxHOUNRVUZKTEZkQlFWY3NTMEZCV0N4RlFVRnJRanM3UVVGRmJFSXNORUpCUVZFc1dVRkJXU3hMUVVGYUxFVkJRVzFDTEVsQlFVa3NUVUZCU2l4RFFVTjJRaXhQUVVGUExFdEJRVkFzUlVGRFFTeERRVVoxUWl4RlFVZDJRaXhYUVVGWExFdEJRVmdzUTBGSVNTeERRVUZTTEVOQlJtdENPMmxDUVVGMFFqczdRVUZUUVN4MVFrRkJUeXhMUVVGUUxFTkJkRU0yUXp0aFFVRnFSRHM3UVVGNVEwRXNjVUpCUVZNc1ZVRkJWQ3hEUVVGdlFpeExRVUZ3UWl4RlFVRXlRaXhMUVVFelFpeEZRVUZyUXl4TFFVRnNReXhGUVVGNVF6czdRVUZGY2tNc2RVSkJRVThzUzBGQlVDeEZRVUZqTEV0QlFXUXNSVUZCY1VJc1MwRkJja0lzUlVGR2NVTTdRVUZIY2tNc0swSkJRV1VzUzBGQlppeEZRVUZ6UWl4TFFVRjBRaXhGUVVFMlFpeExRVUUzUWl4RlFVaHhRenRoUVVGNlF6czdPenRCUVRkSUswVXNjVUpCY1VsMFJTeGpRVUZVTEVOQlFYZENMRXRCUVhoQ0xFVkJRU3RDTEV0QlFTOUNMRVZCUVhORExFdEJRWFJETEVWQlFUWkRPMEZCUTNwRExHOUNRVUZKTEZOQlFWTXNTMEZCVkN4RFFVRktMRVZCUVhGQ08wRkJRMnBDTEhkQ1FVRkpMRTlCUVU4c1RVRkJUU3hQUVVGT0xFdEJRV3RDTEZWQlFYcENMRVZCUVhGRE8wRkJRM0pETERoQ1FVRk5MRXRCUVU0c1NVRkJaU3haUVVOWUxFMUJRVTBzUzBGQlRpeERRVVJYTEVWQlJWZ3NTVUZCU1N4TlFVRktMRU5CUVZjc1QwRkJUeXhOUVVGUUxFVkJRV1VzUzBGQk1VSXNSVUZCYVVNc1NVRkJha01zUTBGR1Z5eERRVUZtTEVOQlJIRkRPM0ZDUVVGNlF6dHBRa0ZFU2l4TlFVOVBMRWxCUVVrc1VVRkJVU3hMUVVGU0xFMUJRVzFDTEUxQlFVMHNWVUZCVGl4SlFVRnZRaXhOUVVGTkxGTkJRVTRzUTBGQmRrTXNSVUZCZVVRN1FVRkRhRVVzZDBKQlFVa3NWMEZCVnl4TlFVRk5MRkZCUVU0c1EwRkVhVVE3UVVGRmFFVXNkMEpCUVVrc1RVRkJUU3hUUVVGVExFMUJRVlFzUTBGR2MwUTdRVUZIYUVVc2VVSkJRVXNzU1VGQlNTeEpRVUZKTEVOQlFVb3NSVUZCVHl4SlFVRkpMRWRCUVVvc1JVRkJVeXhIUVVGNlFpeEZRVUU0UWp0QlFVTXhRaXcwUWtGQlNTeFJRVUZSTEZOQlFWTXNRMEZCVkN4RFFVRlNMRU5CUkhOQ08wRkJSVEZDTEdsRFFVRlRMRU5CUVZRc1EwRkdNRUk3TzBGQlNURkNMSFZEUVVGbExFdEJRV1lzUlVGQmMwSXNTMEZCZEVJc1JVRkJOa0lzUzBGQk4wSXNSVUZLTUVJN08wRkJUVEZDTERSQ1FVRkpMRkZCUVZFc1MwRkJVaXhMUVVGclFpeE5RVUZOTEV0QlFVNHNSVUZCWVR0QlFVTXZRaXh4UTBGQlV5eE5RVUZOTEV0QlFVNHNRMEZFYzBJN2VVSkJRVzVETzNGQ1FVNUtPMmxDUVVoSExFMUJZVUVzU1VGQlNTeFJRVUZSTEV0QlFWSXNRMEZCU2l4RlFVRnZRanRCUVVOMlFpd3lRa0ZCVHl4TFFVRlFMRVZCUVdNc1NVRkJaQ3hGUVVGdlFpeExRVUZ3UWl4RlFVRXlRaXhMUVVFelFpeEZRVVIxUWp0cFFrRkJjRUk3WVVGeVFsZzdPenRCUVhKSkswVXNjVUpCWjB0MFJTeE5RVUZVTEVOQlFXZENMRU5CUVdoQ0xFVkJRVzFDTEVOQlFXNUNMRVZCUVhOQ0xFdEJRWFJDTEVWQlFUWkNMRXRCUVRkQ0xFVkJRVzlETzBGQlEyaERMRzlDUVVGSkxGRkJRVkVzV1VGQldTeERRVUZhTEVWQlFXVXNRMEZCWml4RFFVRlNMRU5CUkRSQ08wRkJSV2hETEc5Q1FVRkpMR0ZCUVdFc1MwRkJTeXhOUVVGTkxFTkJRVTRzUlVGQlV5eE5RVUZOTEVOQlFVNHNRMEZCTTBJc1EwRkdORUk3UVVGSGFFTXNiMEpCUVVrc1YwRkJWeXhWUVVGWUxFTkJRVW9zUlVGQk5FSTdRVUZEZUVJc01FSkJRVTBzUzBGQlRpeEpRVUZsTEVsQlFVa3NUVUZCU2l4RFFVRlhMRTlCUVU4c1MwRkJVQ3hGUVVGakxFbEJRWHBDTEVWQlFTdENMRlZCUVM5Q0xFTkJRV1lzUTBGRWQwSTdhVUpCUVRWQ08yRkJTRW83TzBGQlVVRXNjVUpCUVZNc1ZVRkJWQ3hEUVVGdlFpeExRVUZ3UWl4RlFVRXlRanRCUVVOMlFpeHhRa0ZCU3l4SlFVRkpMRXRCUVVvc1NVRkJZU3hMUVVGc1FpeEZRVUY1UWp0QlFVTnlRaXgzUWtGQlNTeFZRVUZWTEVkQlFWWXNSVUZCWlR0QlFVTm1MQ3RDUVVGUExFbEJRVkFzUTBGRVpUdHhRa0ZCYmtJN2FVSkJSRW83TzBGQlRVRXNkVUpCUVU4c1MwRkJVQ3hEUVZCMVFqdGhRVUV6UWpzN08wRkJlRXNyUlN4eFFrRnRUSFJGTEUxQlFWUXNRMEZCWjBJc1MwRkJhRUlzUlVGQmRVSXNTMEZCZGtJc1JVRkJPRUlzUzBGQk9VSXNSVUZCY1VNN1FVRkRha01zYjBKQlFVa3NVVUZCVVN4TFFVRlNMRU5CUVVvc1JVRkJiMEk3UVVGRGFFSXNkMEpCUVVrc1RVRkJUU3hMUVVGT0xFVkJRV0U3UVVGRFlpdzRRa0ZCVFN4TFFVRk9MRWxCUVdVc1dVRkRXQ3hOUVVGTkxFdEJRVTRzUTBGRVZ5eEZRVVZZTEVsQlFVa3NUVUZCU2l4RFFVTkpMRTlCUVU4c1MwRkJVQ3hGUVVOQkxFdEJSa29zUlVGSFNTeGpRVUZqTEUxQlFVMHNTMEZCVGl4RFFVaHNRaXhEUVVaWExFTkJRV1lzUTBGRVlUdHhRa0ZCYWtJN08wRkJWMEVzZDBKQlFVa3NUVUZCVFN4bFFVRk9MRWxCUVhsQ0xFMUJRVTBzVTBGQlRpeEZRVUZwUWp0QlFVTXhReXcwUWtGQlNTeFhRVUZYTEUxQlFVMHNVVUZCVGl4RFFVUXlRanRCUVVVeFF5dzBRa0ZCU1N4TlFVRk5MRk5CUVZNc1RVRkJWQ3hEUVVablF6dEJRVWN4UXl3MlFrRkJTeXhKUVVGSkxFbEJRVWtzUTBGQlNpeEZRVUZQTEVsQlFVa3NSMEZCU2l4RlFVRlRMRWRCUVhwQ0xFVkJRVGhDTzBGQlF6RkNMR2REUVVGSkxGRkJRVkVzVTBGQlV5eERRVUZVTEVOQlFWSXNRMEZFYzBJN1FVRkZNVUlzY1VOQlFWTXNRMEZCVkN4RFFVWXdRanM3UVVGSk1VSXNiVU5CUVU4c1MwRkJVQ3hGUVVGakxFdEJRV1FzUlVGQmNVSXNTMEZCY2tJc1JVRktNRUk3TzBGQlRURkNMR2REUVVGSkxGRkJRVkVzUzBGQlVpeExRVUZyUWl4TlFVRk5MRXRCUVU0c1JVRkJZVHRCUVVNdlFpeDVRMEZCVXl4TlFVRk5MRXRCUVU0c1EwRkVjMEk3TmtKQlFXNURPM2xDUVU1S08zRkNRVWhLTzJsQ1FWcEtMRTFCTUVKUExFbEJRVWtzVVVGQlVTeExRVUZTTEVOQlFVb3NSVUZCYjBJN1FVRkRka0lzTWtKQlFVOHNTMEZCVUN4RlFVRmpMRWxCUVdRc1JVRkJiMElzUzBGQmNFSXNSVUZCTWtJc1MwRkJNMElzUlVGRWRVSTdhVUpCUVhCQ08yRkJNMEpZT3p0QlFXZERRU3h4UWtGQlV5eGhRVUZVTEVOQlFYVkNMRWRCUVhaQ0xFVkJRVFJDTzBGQlEzaENMRzlDUVVGSkxGTkJRVk1zUlVGQlZDeERRVVJ2UWpzN1FVRkhlRUlzY1VKQlFVc3NTVUZCU1N4SFFVRktMRWxCUVZjc1IwRkJhRUlzUlVGQmNVSTdRVUZEYWtJc01rSkJRVThzUjBGQlVDeEpRVUZqTEZOQlFXUXNRMEZFYVVJN2FVSkJRWEpDT3p0QlFVbEJMSFZDUVVGUExFMUJRVkFzUTBGUWQwSTdZVUZCTlVJN096dEJRVzVPSzBVc2NVSkJPRTUwUlN4UFFVRlVMRU5CUVdsQ0xGTkJRV3BDTEVWQlFUUkNMRk5CUVRWQ0xFVkJRWFZET3p0QlFVVnVReXh2UWtGQlNTeGpRVUZqTEZOQlFWTXNVMEZCVkN4RFFVRmtMRU5CUml0Q08wRkJSMjVETEc5Q1FVRkpMRkZCUVZFc1dVRkJXU3hKUVVGYUxFTkJTSFZDTzBGQlNXNURMRzlDUVVGSkxGRkJRVkVzV1VGQldTeEpRVUZhTEVOQlNuVkNPenRCUVUxdVF5eHZRa0ZCU1N4TlFVRk5MRTFCUVU0c1MwRkJhVUlzVlVGQlZTeE5RVUZXTEVWQlFXdENPMEZCUTI1RExESkNRVUZQTzBGQlEwZ3NhME5CUVZVc1UwRkJWanRCUVVOQkxDdENRVUZQTEVsQlFWQTdjVUpCUmtvc1EwRkViVU03YVVKQlFYWkRPenM3UVVGT2JVTXNiMEpCWXk5Q0xHTkJRV01zVTBGQlV5eFRRVUZVTEVOQlFXUXNRMEZrSzBJN1FVRmxia01zYjBKQlFVa3NVVUZCVVN4WlFVRlpMRWxCUVZvc1EwRm1kVUk3UVVGblFtNURMRzlDUVVGSkxGRkJRVkVzV1VGQldTeEpRVUZhTEVOQmFFSjFRanM3UVVGclFtNURMRzlDUVVGSkxFMUJRVTBzVFVGQlRpeExRVUZwUWl4VlFVRlZMRTFCUVZZc1JVRkJhMEk3UVVGRGJrTXNNa0pCUVU4N1FVRkRTQ3hyUTBGQlZTeFRRVUZXTzBGQlEwRXNLMEpCUVU4c1NVRkJVRHR4UWtGR1NpeERRVVJ0UXp0cFFrRkJka003T3p0QlFXeENiVU1zYjBKQk1FSXZRaXhqUVVGakxFVkJRV1FzUTBFeFFpdENPenRCUVRSQ2JrTXNiMEpCUVVrc1dVRkJXU3hEUVVGYUxFTkJOVUlyUWp0QlFUWkNia01zYjBKQlFVa3NXVUZCV1N4TlFVRk5MRTFCUVU0c1EwRTNRbTFDTzBGQk9FSnVReXh2UWtGQlNTeGxRVUZsTEVOQlFXWTdPenM3UVVFNVFpdENMSEZDUVd0RE9VSXNTVUZCU1N4SlFVRkpMRU5CUVVvc1JVRkJVU3hKUVVGSkxGVkJRVlVzVFVGQlZpeEZRVUZyUWl4SFFVRjJReXhGUVVFMFF6dEJRVU40UXl4M1FrRkJTU3hSUVVGUkxGVkJRVlVzUTBGQlZpeERRVUZTTEVOQlJHOURPMEZCUlhoRExIZENRVUZKTEZOQlFVb3NRMEZHZDBNN08wRkJTWGhETEhkQ1FVRkpMRTFCUVUwc1IwRkJUaXhGUVVGWE8wRkJRMWdzTkVKQlFVa3NUVUZCVFN4alFVRk9MRU5CUVhGQ0xFMUJRVTBzUjBGQlRpeERRVUY2UWl4RlFVRnhRenM3UVVGRmFrTXNkME5CUVZrc1RVRkJUU3hOUVVGTkxFZEJRVTRzUTBGQmJFSXNRMEZHYVVNN1FVRkhha01zZDBOQlFWa3NTVUZCV2l4RFFVRnBRaXhWUVVGVkxGTkJRVllzUTBGQmFrSXNSVUZJYVVNN2VVSkJRWEpETEUxQlMwODdPMEZCUlVnc2QwTkJRVmtzU1VGQlNTeGpRVUZLTEVOQlJsUTdRVUZIU0N4M1EwRkJXU3hKUVVGYUxFTkJRV2xDTEVsQlFXcENMRVZCU0VjN2VVSkJURkE3Y1VKQlJFb3NUVUZYVHpzN1FVRkZTQ3cwUWtGQlNTeFpRVUZaTEZOQlFWb3NSVUZCZFVJN1FVRkRka0lzZDBOQlFWa3NUVUZCVFN4WFFVRk9MRU5CUVZvc1EwRkVkVUk3UVVGRmRrSXNkME5CUVZrc1NVRkJXaXhEUVVGcFFpeFZRVUZWTEZOQlFWWXNRMEZCYWtJc1JVRkdkVUk3ZVVKQlFUTkNMRTFCUjA4N096czdRVUZKU0N4M1EwRkJXU3hKUVVGSkxHTkJRVW9zUTBGS1ZEdEJRVXRJTEhkRFFVRlpMRWxCUVZvc1EwRkJhVUlzU1VGQmFrSXNSVUZNUnp0NVFrRklVRHR4UWtGaVNqdHBRa0ZLU2pzN1FVRTRRa0VzYjBKQlFVa3NaMEpCUVdkQ0xHRkJRV0VzVFVGQlRTeE5RVUZPTEVkQlF6ZENMRlZCUVZVc1RVRkJWaXhIUVVOQkxFMUJRVTBzVTBGQlRpeERRVVpuUWpzN096dEJRV2hGWlN4eFFrRnpSVGxDTEVsQlFVa3NTVUZCU1N4RFFVRktMRVZCUVU4c1NVRkJTU3hWUVVGVkxFMUJRVllzUlVGQmEwSXNSMEZCZEVNc1JVRkJNa003UVVGRGRrTXNkMEpCUVVrc1ZVRkJWU3hWUVVGVkxFTkJRVllzUTBGQlZpeERRVVJ0UXpzN1FVRkhka01zZDBKQlFVa3NVVUZCVVN4SFFVRlNMRVZCUVdFN1FVRkRZaXcwUWtGQlNTeERRVUZETEUxQlFVMHNZMEZCVGl4RFFVRnhRaXhSUVVGUkxFZEJRVklzUTBGQmRFSXNSVUZCYjBNN096czdRVUZKY0VNc2QwTkJRVmtzU1VGQldpeERRVUZwUWl4UFFVRnFRaXhGUVVwdlF6dDVRa0ZCZUVNN2NVSkJSRW9zVFVGUFR5eEpRVUZKTEV0QlFVc3NZVUZCVEN4RlFVRnZRanM3UVVGRk0wSXNiME5CUVZrc1NVRkJXaXhEUVVGcFFpeFBRVUZxUWl4RlFVWXlRanR4UWtGQmVFSTdhVUpCVmxnN08wRkJaMEpCTEc5Q1FVRkpMRmRCUVZjc1dVRkJXU3hMUVVGYUxFVkJRVmdzUTBGMFJpdENPMEZCZFVadVF5eHZRa0ZCU1N4blFrRkJaMElzUTBGQmFFSXNRMEYyUml0Q08wRkJkMFp1UXl4dlFrRkJTU3hWUVVGVkxFVkJRVllzUTBGNFJpdENPMEZCZVVadVF5eHZRa0ZCU1N4VlFVRlZMRVZCUVZZc1EwRjZSaXRDTzBGQk1FWnVReXh2UWtGQlNTeFpRVUZLTEVOQk1VWnRRenM3UVVFMFJtNURMSEZDUVVGTExFbEJRVWtzU1VGQlNTeERRVUZLTEVWQlFVOHNTVUZCU1N4VlFVRlZMRTFCUVZZc1IwRkJiVUk3UVVGRGJrTXNkMEpCUVVrc1lVRkJZU3hWUVVGVkxFTkJRVllzUTBGQllpeERRVVFyUWp0QlFVVnVReXh0UTBGQlpTeFRRVUZUTEdGQlFWUXNRMEZCWmpzN08wRkJSbTFETERKQ1FVczFRaXhwUWtGQmFVSXNTVUZCYWtJc1NVRkJlVUlzVTBGQlV5eE5RVUZVTEVWQlFXbENPMEZCUXpkRExHZERRVUZSTEVsQlFWSXNRMEZCWVN4UFFVRlBMRkZCUVZBc1JVRkJhVUlzWVVGQmFrSXNSVUZCWjBNc1NVRkJhRU1zUTBGQllpeEZRVVEyUXp0QlFVVTNReXgxUTBGQlpTeFRRVUZUTEdGQlFWUXNRMEZCWml4RFFVWTJRenR4UWtGQmFrUTdPMEZCUzBFc2QwSkJRVWtzUTBGQlF5eFpRVUZFTEVsQlFXbENMR0ZCUVdFc1IwRkJZaXhMUVVGeFFpeFhRVUZYTEVkQlFWZ3NSVUZCWjBJN08wRkJSWFJFTERSQ1FVRkpMRmRCUVZjc1IwRkJXQ3hGUVVGblFqdEJRVU5vUWl4blEwRkJTU3huUWtGQlowSXNZVUZCWVN4SFFVRmlMRVZCUVd0Q096dEJRVVZzUXl4dlEwRkJTU3hOUVVGTkxHRkJRV0VzUjBGQllpeERRVUZPTEV0QlFUUkNMRWxCUVVrc1EwRkJTaXhGUVVGUE8wRkJRMjVETERSRFFVRlJMRWxCUVZJc1EwRkJZU3hQUVVGUExGRkJRVkFzUlVGQmFVSXNZVUZCYWtJc1JVRkJaME1zWVVGQllTeEhRVUZpTEVOQlFUZERMRVZCUkcxRE8wRkJSVzVETEcxRVFVRmxMRk5CUVZNc1lVRkJWQ3hEUVVGbU96dEJRVVp0UXl4M1EwRkpMMElzUTBGQlF5eFpRVUZFTEVsQlFXbENMR0ZCUVdFc1IwRkJZaXhMUVVGeFFpeFhRVUZYTEVkQlFWZ3NSVUZCWjBJN1FVRkRkRVFzWjBSQlFWRXNTVUZCVWl4RFFVRmhMRVZCUVVNc1MwRkJTeXhYUVVGWExFZEJRVmdzUlVGQlowSXNTVUZCU1N4RFFVRktMRVZCUVc1RExFVkJSSE5FT3pzN1FVRkJNVVFzZVVOQlNVczdRVUZEUkN3MFJFRkVRenQ1UTBGS1REdHBRMEZLU2l4TlFWbExPMEZCUTBRc05FTkJRVkVzU1VGQlVpeERRVUZoTEVWQlFVTXNTMEZCU3l4WFFVRlhMRWRCUVZnc1JVRkJaMElzU1VGQlNTeERRVUZLTEVWQlFXNURMRVZCUkVNN2FVTkJXa3c3TmtKQlJrb3NUVUZyUWtzN1FVRkRSQ3gzUTBGQlVTeEpRVUZTTEVOQlFXRXNSVUZCUXl4TFFVRkxMRmRCUVZjc1IwRkJXQ3hGUVVGblFpeEpRVUZKTEVOQlFVb3NSVUZCYmtNc1JVRkVRenMyUWtGc1FrdzdRVUZ4UWtFc1owTkJkRUpuUWpzN08wRkJRWEJDTERaQ1FYbENTeXhKUVVGSkxHZENRVUZuUWl4aFFVRmhMRWRCUVdJc1JVRkJhMEk3UVVGRGRrTXNkME5CUVZFc1NVRkJVaXhEUVVGaExFOUJRVThzVVVGQlVDeEZRVUZwUWl4aFFVRnFRaXhGUVVGblF5eGhRVUZoTEVkQlFXSXNRMEZCTjBNc1JVRkVkVU03TmtKQlFYUkRPM0ZDUVROQ1ZDeE5RU3RDU3p0QlFVTkVMSGREUVVSRE8wRkJSVVFzTkVKQlJrTTdjVUpCTDBKTU8ybENRVlpLT3pzN1FVRTFSbTFETEhWQ1FUUkpOMElzWjBKQlFXZENMRk5CUVZNc1RVRkJWQ3hGUVVGcFFqdEJRVU51UXl4dFEwRkJaU3hUUVVGVExHRkJRVlFzUTBGQlppeERRVVJ0UXp0QlFVVnVReXcwUWtGQlVTeEpRVUZTTEVOQlFXRXNUMEZCVHl4UlFVRlFMRVZCUVdsQ0xHRkJRV3BDTEVWQlFXZERMR2RDUVVGblFpeGhRVUZoTEVkQlFXSXNRMEZCTjBRc1JVRkdiVU03YVVKQlFYWkRPenM3TzBGQk5VbHRReXh2UWtGdFNpOUNMRkZCUVZFc1RVRkJVaXhMUVVGdFFpeFpRVUZ1UWl4SlFVRnRReXhEUVVGRExGRkJRVkVzVFVGQlVpeEZRVUZuUWp0QlFVTndSQ3d5UWtGQlR6dEJRVU5JTEd0RFFVRlZMRmRCUVZZN1FVRkRRU3dyUWtGQlR5eEpRVUZRTzNGQ1FVWktMRU5CUkc5RU8ybENRVUY0UkRzN1FVRlBRU3gxUWtGQlR6dEJRVU5JTERoQ1FVRlZMRmRCUVZZN1FVRkRRU3d5UWtGQlR6dEJRVU5JTEdsRFFVRlRMRTlCUVZRN1FVRkRRU3hwUTBGQlV5eFBRVUZVTzNGQ1FVWktPMmxDUVVaS0xFTkJNVXB0UXp0aFFVRjJRenM3UVVGdFMwRXNjVUpCUVZNc1RVRkJWQ3hEUVVGblFpeEhRVUZvUWl4RlFVRnhRaXhMUVVGeVFpeEZRVUUwUWl4SFFVRTFRaXhGUVVGcFF6dEJRVU0zUWl4dlFrRkJTU3hOUVVGS0xFTkJRVmNzUzBGQldDeEZRVUZyUWl4RFFVRnNRaXhGUVVRMlFqczdRVUZITjBJc2RVSkJRVTg3UVVGRFNDd3dRa0ZCVFN4TFFVRk9PMEZCUTBFc2VVSkJRVXNzUjBGQlREdHBRa0ZHU2l4RFFVZzJRanRoUVVGcVF6czdRVUZUUVN4eFFrRkJVeXhSUVVGVUxFTkJRV3RDTEZGQlFXeENMRVZCUVRSQ08wRkJRM2hDTEc5Q1FVRkpMRTlCUVU4c1JVRkJVQ3hEUVVSdlFqdEJRVVY0UWl4dlFrRkJTU3hQUVVGUExFVkJRVkFzUTBGR2IwSTdRVUZIZUVJc2IwSkJRVWtzVTBGQlV5eFRRVUZUTEUxQlFWUXNRMEZJVnpzN1FVRkxlRUlzY1VKQlFVc3NTVUZCU1N4SlFVRkpMRU5CUVVvc1JVRkJUeXhKUVVGSkxFMUJRVW9zUlVGQldTeEhRVUUxUWl4RlFVRnBRenRCUVVNM1FpeDNRa0ZCU1N4UlFVRlJMRk5CUVZNc1EwRkJWQ3hEUVVGU0xFTkJSSGxDT3p0QlFVYzNRaXgzUWtGQlNTeE5RVUZOTEVkQlFVNHNSVUZCVnp0QlFVTllMRFpDUVVGTExFMUJRVTBzUjBGQlRpeERRVUZNTEVkQlFXdENMRU5CUVd4Q0xFTkJSRmM3Y1VKQlFXWXNUVUZGVHp0QlFVTklMRFpDUVVGTExFbEJRVXdzUTBGQlZTeERRVUZXTEVWQlJFYzdjVUpCUmxBN2FVSkJTRW83TzBGQlZVRXNkVUpCUVU4N1FVRkRTQ3d3UWtGQlRTeEpRVUZPTzBGQlEwRXNNRUpCUVUwc1NVRkJUanRCUVVaSExHbENRVUZRTEVOQlpuZENPMkZCUVRWQ096dEJRWEZDUVN4eFFrRkJVeXhYUVVGVUxFTkJRWEZDTEV0QlFYSkNMRVZCUVRSQ0xFdEJRVFZDTEVWQlFXMURPMEZCUXk5Q0xHOUNRVUZKTEV0QlFVb3NSVUZCVnp0QlFVTlFMSGRDUVVGSkxGRkJRVkVzUzBGQlVpeERRVUZLTEVWQlFXOUNPMEZCUTJoQ0xEaENRVUZOTEVsQlFVNHNRMEZCVnl4TFFVRllMRVZCUkdkQ08zRkNRVUZ3UWl4TlFVVlBPMEZCUTBnc1owTkJRVkVzUTBGQlF5eExRVUZFTEVWQlFWRXNTMEZCVWl4RFFVRlNMRU5CUkVjN2NVSkJSbEE3TzBGQlRVRXNNa0pCUVU4c1MwRkJVQ3hEUVZCUE8ybENRVUZZTEUxQlVVODdRVUZEU0N3eVFrRkJUeXhMUVVGUUxFTkJSRWM3YVVKQlVsQTdZVUZFU2p0VFFTOWFLME1zUlVFMllUZERMRVZCUVVNc2VVSkJRWGRDTEVWQlFYaENMRVZCUVRKQ0xIRkNRVUZ2UWl4RlFVRndRaXhGUVVGMVFpeHhRa0ZCYjBJc1JVRkJjRUlzUlVGQmRVSXNjVUpCUVc5Q0xFVkJRWEJDTEVWQlFYVkNMSE5DUVVGeFFpeEZRVUZ5UWl4RlFVRjNRaXh0UWtGQmEwSXNSVUZCYkVJc1JVRkJjVUlzWjBKQlFXVXNSVUZCWml4RlFVRnJRaXhqUVVGaExFVkJRV0lzUlVFM1lYQklMRU5CUVVnc1JVRTVkVU0xUWl4RlFUSndSSE5MTEVWQk0zQkVkRXNzUlVFeWNFUjVTeXhEUVVGRExFTkJRVVFzUTBFemNFUjZTeXhGUVRKd1JEaExMRU5CTTNCRU9Vc3NRMEZCVUN4RFFVWkxPME5CUVZnc1EwRkdSVHM3UVVGcmNVUktMR1ZCUVdVc1ZVRkJaaUlzSW1acGJHVWlPaUpzYVdJdmRtbHlkSFZoYkMxa2IyMHVhbk1pTENKemIzVnlZMlZ6UTI5dWRHVnVkQ0k2V3lKc1pYUWdWbWx5ZEhWaGJFUlBUU0E5SUdaMWJtTjBhVzl1S0dVcElIdGNiaUFnY21WMGRYSnVJR1VvS1R0Y2JuMG9ablZ1WTNScGIyNG9LU0I3WEc0Z0lDQWdJQ0FnSUhaaGNpQmtaV1pwYm1Vc0lHMXZaSFZzWlN3Z1pYaHdiM0owY3p0Y2JpQWdJQ0FnSUNBZ2NtVjBkWEp1SUNobWRXNWpkR2x2YmlCbEtIUXNJRzRzSUhJcElIdGNiaUFnSUNBZ0lDQWdJQ0FnSUNBZ0lDQm1kVzVqZEdsdmJpQnpLRzhzSUhVcElIdGNiaUFnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnYVdZZ0tDRnVXMjlkS1NCN1hHNGdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNCcFppQW9JWFJiYjEwcElIdGNiaUFnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0IyWVhJZ1lTQTlJSFI1Y0dWdlppQnlaWEYxYVhKbElEMDlJRndpWm5WdVkzUnBiMjVjSWlBbUppQnlaWEYxYVhKbE8xeHVJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJR2xtSUNnaGRTQW1KaUJoS1NCeVpYUjFjbTRnWVNodkxDQWhNQ2s3WEc0Z0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ2FXWWdLR2twSUhKbGRIVnliaUJwS0c4c0lDRXdLVHRjYmlBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNCMllYSWdaaUE5SUc1bGR5QkZjbkp2Y2loY0lrTmhibTV2ZENCbWFXNWtJRzF2WkhWc1pTQW5YQ0lnS3lCdklDc2dYQ0luWENJcE8xeHVJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJSFJvY205M0lHWXVZMjlrWlNBOUlGd2lUVTlFVlV4RlgwNVBWRjlHVDFWT1JGd2lMQ0JtWEc0Z0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0I5WEc0Z0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0IyWVhJZ2JDQTlJRzViYjEwZ1BTQjdYRzRnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnWlhod2IzSjBjem9nZTMxY2JpQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUgwN1hHNGdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNCMFcyOWRXekJkTG1OaGJHd29iQzVsZUhCdmNuUnpMQ0JtZFc1amRHbHZiaWhsS1NCN1hHNGdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdkbUZ5SUc0Z1BTQjBXMjlkV3pGZFcyVmRPMXh1SUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUhKbGRIVnliaUJ6S0c0Z1B5QnVJRG9nWlNsY2JpQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUgwc0lHd3NJR3d1Wlhod2IzSjBjeXdnWlN3Z2RDd2diaXdnY2lsY2JpQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdmVnh1SUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNCeVpYUjFjbTRnYmx0dlhTNWxlSEJ2Y25SelhHNGdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ2ZWeHVJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lIWmhjaUJwSUQwZ2RIbHdaVzltSUhKbGNYVnBjbVVnUFQwZ1hDSm1kVzVqZEdsdmJsd2lJQ1ltSUhKbGNYVnBjbVU3WEc0Z0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnWm05eUlDaDJZWElnYnlBOUlEQTdJRzhnUENCeUxteGxibWQwYURzZ2J5c3JLU0J6S0hKYmIxMHBPMXh1SUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJSEpsZEhWeWJpQnpYRzRnSUNBZ0lDQWdJQ0FnSUNCOUtTaDdYRzRnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSURFNklGdG1kVzVqZEdsdmJpaHlaWEYxYVhKbExDQnRiMlIxYkdVc0lHVjRjRzl5ZEhNcElIdGNibHh1ZG1GeUlHTnlaV0YwWlVWc1pXMWxiblFnUFNCeVpYRjFhWEpsS0Z3aUxpOTJaRzl0TDJOeVpXRjBaUzFsYkdWdFpXNTBMbXB6WENJcFhHNWNibTF2WkhWc1pTNWxlSEJ2Y25SeklEMGdZM0psWVhSbFJXeGxiV1Z1ZEZ4dVhHNTlMSHRjSWk0dmRtUnZiUzlqY21WaGRHVXRaV3hsYldWdWRDNXFjMXdpT2pFMWZWMHNNanBiWm5WdVkzUnBiMjRvY21WeGRXbHlaU3h0YjJSMWJHVXNaWGh3YjNKMGN5bDdYRzUyWVhJZ1pHbG1aaUE5SUhKbGNYVnBjbVVvWENJdUwzWjBjbVZsTDJScFptWXVhbk5jSWlsY2JseHViVzlrZFd4bExtVjRjRzl5ZEhNZ1BTQmthV1ptWEc1Y2JuMHNlMXdpTGk5MmRISmxaUzlrYVdabUxtcHpYQ0k2TXpWOVhTd3pPbHRtZFc1amRHbHZiaWh5WlhGMWFYSmxMRzF2WkhWc1pTeGxlSEJ2Y25SektYdGNiblpoY2lCb0lEMGdjbVZ4ZFdseVpTaGNJaTR2ZG1seWRIVmhiQzFvZVhCbGNuTmpjbWx3ZEM5cGJtUmxlQzVxYzF3aUtWeHVYRzV0YjJSMWJHVXVaWGh3YjNKMGN5QTlJR2hjYmx4dWZTeDdYQ0l1TDNacGNuUjFZV3d0YUhsd1pYSnpZM0pwY0hRdmFXNWtaWGd1YW5OY0lqb3lNbjFkTERRNlcyWjFibU4wYVc5dUtISmxjWFZwY21Vc2JXOWtkV3hsTEdWNGNHOXlkSE1wZTF4dWRtRnlJR1JwWm1ZZ1BTQnlaWEYxYVhKbEtGd2lMaTlrYVdabUxtcHpYQ0lwWEc1MllYSWdjR0YwWTJnZ1BTQnlaWEYxYVhKbEtGd2lMaTl3WVhSamFDNXFjMXdpS1Z4dWRtRnlJR2dnUFNCeVpYRjFhWEpsS0Z3aUxpOW9MbXB6WENJcFhHNTJZWElnWTNKbFlYUmxJRDBnY21WeGRXbHlaU2hjSWk0dlkzSmxZWFJsTFdWc1pXMWxiblF1YW5OY0lpbGNiblpoY2lCV1RtOWtaU0E5SUhKbGNYVnBjbVVvSnk0dmRtNXZaR1V2ZG01dlpHVXVhbk1uS1Z4dWRtRnlJRlpVWlhoMElEMGdjbVZ4ZFdseVpTZ25MaTkyYm05a1pTOTJkR1Y0ZEM1cWN5Y3BYRzVjYm0xdlpIVnNaUzVsZUhCdmNuUnpJRDBnZTF4dUlDQWdJR1JwWm1ZNklHUnBabVlzWEc0Z0lDQWdjR0YwWTJnNklIQmhkR05vTEZ4dUlDQWdJR2c2SUdnc1hHNGdJQ0FnWTNKbFlYUmxPaUJqY21WaGRHVXNYRzRnSUNBZ1ZrNXZaR1U2SUZaT2IyUmxMRnh1SUNBZ0lGWlVaWGgwT2lCV1ZHVjRkRnh1ZlZ4dVhHNTlMSHRjSWk0dlkzSmxZWFJsTFdWc1pXMWxiblF1YW5OY0lqb3hMRndpTGk5a2FXWm1MbXB6WENJNk1peGNJaTR2YUM1cWMxd2lPak1zWENJdUwzQmhkR05vTG1welhDSTZNVE1zWENJdUwzWnViMlJsTDNadWIyUmxMbXB6WENJNk16RXNYQ0l1TDNadWIyUmxMM1owWlhoMExtcHpYQ0k2TXpOOVhTdzFPbHRtZFc1amRHbHZiaWh5WlhGMWFYSmxMRzF2WkhWc1pTeGxlSEJ2Y25SektYdGNiaThxSVZ4dUlDb2dRM0p2YzNNdFFuSnZkM05sY2lCVGNHeHBkQ0F4TGpFdU1WeHVJQ29nUTI5d2VYSnBaMmgwSURJd01EY3RNakF4TWlCVGRHVjJaVzRnVEdWMmFYUm9ZVzRnUEhOMFpYWmxibXhsZG1sMGFHRnVMbU52YlQ1Y2JpQXFJRUYyWVdsc1lXSnNaU0IxYm1SbGNpQjBhR1VnVFVsVUlFeHBZMlZ1YzJWY2JpQXFJRVZEVFVGVFkzSnBjSFFnWTI5dGNHeHBZVzUwTENCMWJtbG1iM0p0SUdOeWIzTnpMV0p5YjNkelpYSWdjM0JzYVhRZ2JXVjBhRzlrWEc0Z0tpOWNibHh1THlvcVhHNGdLaUJUY0d4cGRITWdZU0J6ZEhKcGJtY2dhVzUwYnlCaGJpQmhjbkpoZVNCdlppQnpkSEpwYm1keklIVnphVzVuSUdFZ2NtVm5aWGdnYjNJZ2MzUnlhVzVuSUhObGNHRnlZWFJ2Y2k0Z1RXRjBZMmhsY3lCdlppQjBhR1ZjYmlBcUlITmxjR0Z5WVhSdmNpQmhjbVVnYm05MElHbHVZMngxWkdWa0lHbHVJSFJvWlNCeVpYTjFiSFFnWVhKeVlYa3VJRWh2ZDJWMlpYSXNJR2xtSUdCelpYQmhjbUYwYjNKZ0lHbHpJR0VnY21WblpYZ2dkR2hoZENCamIyNTBZV2x1YzF4dUlDb2dZMkZ3ZEhWeWFXNW5JR2R5YjNWd2N5d2dZbUZqYTNKbFptVnlaVzVqWlhNZ1lYSmxJSE53YkdsalpXUWdhVzUwYnlCMGFHVWdjbVZ6ZFd4MElHVmhZMmdnZEdsdFpTQmdjMlZ3WVhKaGRHOXlZQ0JwY3lCdFlYUmphR1ZrTGx4dUlDb2dSbWw0WlhNZ1luSnZkM05sY2lCaWRXZHpJR052YlhCaGNtVmtJSFJ2SUhSb1pTQnVZWFJwZG1VZ1lGTjBjbWx1Wnk1d2NtOTBiM1I1Y0dVdWMzQnNhWFJnSUdGdVpDQmpZVzRnWW1VZ2RYTmxaQ0J5Wld4cFlXSnNlVnh1SUNvZ1kzSnZjM010WW5KdmQzTmxjaTVjYmlBcUlFQndZWEpoYlNCN1UzUnlhVzVuZlNCemRISWdVM1J5YVc1bklIUnZJSE53YkdsMExseHVJQ29nUUhCaGNtRnRJSHRTWldkRmVIQjhVM1J5YVc1bmZTQnpaWEJoY21GMGIzSWdVbVZuWlhnZ2IzSWdjM1J5YVc1bklIUnZJSFZ6WlNCbWIzSWdjMlZ3WVhKaGRHbHVaeUIwYUdVZ2MzUnlhVzVuTGx4dUlDb2dRSEJoY21GdElIdE9kVzFpWlhKOUlGdHNhVzFwZEYwZ1RXRjRhVzExYlNCdWRXMWlaWElnYjJZZ2FYUmxiWE1nZEc4Z2FXNWpiSFZrWlNCcGJpQjBhR1VnY21WemRXeDBJR0Z5Y21GNUxseHVJQ29nUUhKbGRIVnlibk1nZTBGeWNtRjVmU0JCY25KaGVTQnZaaUJ6ZFdKemRISnBibWR6TGx4dUlDb2dRR1Y0WVcxd2JHVmNiaUFxWEc0Z0tpQXZMeUJDWVhOcFl5QjFjMlZjYmlBcUlITndiR2wwS0NkaElHSWdZeUJrSnl3Z0p5QW5LVHRjYmlBcUlDOHZJQzArSUZzbllTY3NJQ2RpSnl3Z0oyTW5MQ0FuWkNkZFhHNGdLbHh1SUNvZ0x5OGdWMmwwYUNCc2FXMXBkRnh1SUNvZ2MzQnNhWFFvSjJFZ1lpQmpJR1FuTENBbklDY3NJRElwTzF4dUlDb2dMeThnTFQ0Z1d5ZGhKeXdnSjJJblhWeHVJQ3BjYmlBcUlDOHZJRUpoWTJ0eVpXWmxjbVZ1WTJWeklHbHVJSEpsYzNWc2RDQmhjbkpoZVZ4dUlDb2djM0JzYVhRb0p5NHVkMjl5WkRFZ2QyOXlaREl1TGljc0lDOG9XMkV0ZWwwcktTaGNYR1FyS1M5cEtUdGNiaUFxSUM4dklDMCtJRnNuTGk0bkxDQW5kMjl5WkNjc0lDY3hKeXdnSnlBbkxDQW5kMjl5WkNjc0lDY3lKeXdnSnk0dUoxMWNiaUFxTDF4dWJXOWtkV3hsTG1WNGNHOXlkSE1nUFNBb1puVnVZM1JwYjI0Z2MzQnNhWFFvZFc1a1pXWXBJSHRjYmx4dUlDQjJZWElnYm1GMGFYWmxVM0JzYVhRZ1BTQlRkSEpwYm1jdWNISnZkRzkwZVhCbExuTndiR2wwTEZ4dUlDQWdJR052YlhCc2FXRnVkRVY0WldOT2NHTm5JRDBnTHlncFB6OHZMbVY0WldNb1hDSmNJaWxiTVYwZ1BUMDlJSFZ1WkdWbUxGeHVJQ0FnSUM4dklFNVFRMGM2SUc1dmJuQmhjblJwWTJsd1lYUnBibWNnWTJGd2RIVnlhVzVuSUdkeWIzVndYRzRnSUNBZ2MyVnNaanRjYmx4dUlDQnpaV3htSUQwZ1puVnVZM1JwYjI0b2MzUnlMQ0J6WlhCaGNtRjBiM0lzSUd4cGJXbDBLU0I3WEc0Z0lDQWdMeThnU1dZZ1lITmxjR0Z5WVhSdmNtQWdhWE1nYm05MElHRWdjbVZuWlhnc0lIVnpaU0JnYm1GMGFYWmxVM0JzYVhSZ1hHNGdJQ0FnYVdZZ0tFOWlhbVZqZEM1d2NtOTBiM1I1Y0dVdWRHOVRkSEpwYm1jdVkyRnNiQ2h6WlhCaGNtRjBiM0lwSUNFOVBTQmNJbHR2WW1wbFkzUWdVbVZuUlhod1hWd2lLU0I3WEc0Z0lDQWdJQ0J5WlhSMWNtNGdibUYwYVhabFUzQnNhWFF1WTJGc2JDaHpkSElzSUhObGNHRnlZWFJ2Y2l3Z2JHbHRhWFFwTzF4dUlDQWdJSDFjYmlBZ0lDQjJZWElnYjNWMGNIVjBJRDBnVzEwc1hHNGdJQ0FnSUNCbWJHRm5jeUE5SUNoelpYQmhjbUYwYjNJdWFXZHViM0psUTJGelpTQS9JRndpYVZ3aUlEb2dYQ0pjSWlrZ0t5QW9jMlZ3WVhKaGRHOXlMbTExYkhScGJHbHVaU0EvSUZ3aWJWd2lJRG9nWENKY0lpa2dLeUFvYzJWd1lYSmhkRzl5TG1WNGRHVnVaR1ZrSUQ4Z1hDSjRYQ0lnT2lCY0lsd2lLU0FySUM4dklGQnliM0J2YzJWa0lHWnZjaUJGVXpaY2JpQWdJQ0FnSUNoelpYQmhjbUYwYjNJdWMzUnBZMnQ1SUQ4Z1hDSjVYQ0lnT2lCY0lsd2lLU3hjYmlBZ0lDQWdJQzh2SUVacGNtVm1iM2dnTXl0Y2JpQWdJQ0FnSUd4aGMzUk1ZWE4wU1c1a1pYZ2dQU0F3TEZ4dUlDQWdJQ0FnTHk4Z1RXRnJaU0JnWjJ4dlltRnNZQ0JoYm1RZ1lYWnZhV1FnWUd4aGMzUkpibVJsZUdBZ2FYTnpkV1Z6SUdKNUlIZHZjbXRwYm1jZ2QybDBhQ0JoSUdOdmNIbGNiaUFnSUNBZ0lITmxjR0Z5WVhSdmNpQTlJRzVsZHlCU1pXZEZlSEFvYzJWd1lYSmhkRzl5TG5OdmRYSmpaU3dnWm14aFozTWdLeUJjSW1kY0lpa3NYRzRnSUNBZ0lDQnpaWEJoY21GMGIzSXlMQ0J0WVhSamFDd2diR0Z6ZEVsdVpHVjRMQ0JzWVhOMFRHVnVaM1JvTzF4dUlDQWdJSE4wY2lBclBTQmNJbHdpT3lBdkx5QlVlWEJsTFdOdmJuWmxjblJjYmlBZ0lDQnBaaUFvSVdOdmJYQnNhV0Z1ZEVWNFpXTk9jR05uS1NCN1hHNGdJQ0FnSUNBdkx5QkViMlZ6YmlkMElHNWxaV1FnWm14aFozTWdaM2tzSUdKMWRDQjBhR1Y1SUdSdmJpZDBJR2gxY25SY2JpQWdJQ0FnSUhObGNHRnlZWFJ2Y2pJZ1BTQnVaWGNnVW1WblJYaHdLRndpWGx3aUlDc2djMlZ3WVhKaGRHOXlMbk52ZFhKalpTQXJJRndpSkNnL0lWeGNYRnh6S1Z3aUxDQm1iR0ZuY3lrN1hHNGdJQ0FnZlZ4dUlDQWdJQzhxSUZaaGJIVmxjeUJtYjNJZ1lHeHBiV2wwWUN3Z2NHVnlJSFJvWlNCemNHVmpPbHh1SUNBZ0lDQXFJRWxtSUhWdVpHVm1hVzVsWkRvZ05ESTVORGsyTnpJNU5TQXZMeUJOWVhSb0xuQnZkeWd5TENBek1pa2dMU0F4WEc0Z0lDQWdJQ29nU1dZZ01Dd2dTVzVtYVc1cGRIa3NJRzl5SUU1aFRqb2dNRnh1SUNBZ0lDQXFJRWxtSUhCdmMybDBhWFpsSUc1MWJXSmxjam9nYkdsdGFYUWdQU0JOWVhSb0xtWnNiMjl5S0d4cGJXbDBLVHNnYVdZZ0tHeHBiV2wwSUQ0Z05ESTVORGsyTnpJNU5Ta2diR2x0YVhRZ0xUMGdOREk1TkRrMk56STVOanRjYmlBZ0lDQWdLaUJKWmlCdVpXZGhkR2wyWlNCdWRXMWlaWEk2SURReU9UUTVOamN5T1RZZ0xTQk5ZWFJvTG1ac2IyOXlLRTFoZEdndVlXSnpLR3hwYldsMEtTbGNiaUFnSUNBZ0tpQkpaaUJ2ZEdobGNqb2dWSGx3WlMxamIyNTJaWEowTENCMGFHVnVJSFZ6WlNCMGFHVWdZV0p2ZG1VZ2NuVnNaWE5jYmlBZ0lDQWdLaTljYmlBZ0lDQnNhVzFwZENBOUlHeHBiV2wwSUQwOVBTQjFibVJsWmlBL0lDMHhJRDQrUGlBd0lEb2dMeThnVFdGMGFDNXdiM2NvTWl3Z016SXBJQzBnTVZ4dUlDQWdJR3hwYldsMElENCtQaUF3T3lBdkx5QlViMVZwYm5Rek1paHNhVzFwZENsY2JpQWdJQ0IzYUdsc1pTQW9iV0YwWTJnZ1BTQnpaWEJoY21GMGIzSXVaWGhsWXloemRISXBLU0I3WEc0Z0lDQWdJQ0F2THlCZ2MyVndZWEpoZEc5eUxteGhjM1JKYm1SbGVHQWdhWE1nYm05MElISmxiR2xoWW14bElHTnliM056TFdKeWIzZHpaWEpjYmlBZ0lDQWdJR3hoYzNSSmJtUmxlQ0E5SUcxaGRHTm9MbWx1WkdWNElDc2diV0YwWTJoYk1GMHViR1Z1WjNSb08xeHVJQ0FnSUNBZ2FXWWdLR3hoYzNSSmJtUmxlQ0ErSUd4aGMzUk1ZWE4wU1c1a1pYZ3BJSHRjYmlBZ0lDQWdJQ0FnYjNWMGNIVjBMbkIxYzJnb2MzUnlMbk5zYVdObEtHeGhjM1JNWVhOMFNXNWtaWGdzSUcxaGRHTm9MbWx1WkdWNEtTazdYRzRnSUNBZ0lDQWdJQzh2SUVacGVDQmljbTkzYzJWeWN5QjNhRzl6WlNCZ1pYaGxZMkFnYldWMGFHOWtjeUJrYjI0bmRDQmpiMjV6YVhOMFpXNTBiSGtnY21WMGRYSnVJR0IxYm1SbFptbHVaV1JnSUdadmNseHVJQ0FnSUNBZ0lDQXZMeUJ1YjI1d1lYSjBhV05wY0dGMGFXNW5JR05oY0hSMWNtbHVaeUJuY205MWNITmNiaUFnSUNBZ0lDQWdhV1lnS0NGamIyMXdiR2xoYm5SRmVHVmpUbkJqWnlBbUppQnRZWFJqYUM1c1pXNW5kR2dnUGlBeEtTQjdYRzRnSUNBZ0lDQWdJQ0FnYldGMFkyaGJNRjB1Y21Wd2JHRmpaU2h6WlhCaGNtRjBiM0l5TENCbWRXNWpkR2x2YmlncElIdGNiaUFnSUNBZ0lDQWdJQ0FnSUdadmNpQW9kbUZ5SUdrZ1BTQXhPeUJwSUR3Z1lYSm5kVzFsYm5SekxteGxibWQwYUNBdElESTdJR2tyS3lrZ2UxeHVJQ0FnSUNBZ0lDQWdJQ0FnSUNCcFppQW9ZWEpuZFcxbGJuUnpXMmxkSUQwOVBTQjFibVJsWmlrZ2UxeHVJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lHMWhkR05vVzJsZElEMGdkVzVrWldZN1hHNGdJQ0FnSUNBZ0lDQWdJQ0FnSUgxY2JpQWdJQ0FnSUNBZ0lDQWdJSDFjYmlBZ0lDQWdJQ0FnSUNCOUtUdGNiaUFnSUNBZ0lDQWdmVnh1SUNBZ0lDQWdJQ0JwWmlBb2JXRjBZMmd1YkdWdVozUm9JRDRnTVNBbUppQnRZWFJqYUM1cGJtUmxlQ0E4SUhOMGNpNXNaVzVuZEdncElIdGNiaUFnSUNBZ0lDQWdJQ0JCY25KaGVTNXdjbTkwYjNSNWNHVXVjSFZ6YUM1aGNIQnNlU2h2ZFhSd2RYUXNJRzFoZEdOb0xuTnNhV05sS0RFcEtUdGNiaUFnSUNBZ0lDQWdmVnh1SUNBZ0lDQWdJQ0JzWVhOMFRHVnVaM1JvSUQwZ2JXRjBZMmhiTUYwdWJHVnVaM1JvTzF4dUlDQWdJQ0FnSUNCc1lYTjBUR0Z6ZEVsdVpHVjRJRDBnYkdGemRFbHVaR1Y0TzF4dUlDQWdJQ0FnSUNCcFppQW9iM1YwY0hWMExteGxibWQwYUNBK1BTQnNhVzFwZENrZ2UxeHVJQ0FnSUNBZ0lDQWdJR0p5WldGck8xeHVJQ0FnSUNBZ0lDQjlYRzRnSUNBZ0lDQjlYRzRnSUNBZ0lDQnBaaUFvYzJWd1lYSmhkRzl5TG14aGMzUkpibVJsZUNBOVBUMGdiV0YwWTJndWFXNWtaWGdwSUh0Y2JpQWdJQ0FnSUNBZ2MyVndZWEpoZEc5eUxteGhjM1JKYm1SbGVDc3JPeUF2THlCQmRtOXBaQ0JoYmlCcGJtWnBibWwwWlNCc2IyOXdYRzRnSUNBZ0lDQjlYRzRnSUNBZ2ZWeHVJQ0FnSUdsbUlDaHNZWE4wVEdGemRFbHVaR1Y0SUQwOVBTQnpkSEl1YkdWdVozUm9LU0I3WEc0Z0lDQWdJQ0JwWmlBb2JHRnpkRXhsYm1kMGFDQjhmQ0FoYzJWd1lYSmhkRzl5TG5SbGMzUW9YQ0pjSWlrcElIdGNiaUFnSUNBZ0lDQWdiM1YwY0hWMExuQjFjMmdvWENKY0lpazdYRzRnSUNBZ0lDQjlYRzRnSUNBZ2ZTQmxiSE5sSUh0Y2JpQWdJQ0FnSUc5MWRIQjFkQzV3ZFhOb0tITjBjaTV6YkdsalpTaHNZWE4wVEdGemRFbHVaR1Y0S1NrN1hHNGdJQ0FnZlZ4dUlDQWdJSEpsZEhWeWJpQnZkWFJ3ZFhRdWJHVnVaM1JvSUQ0Z2JHbHRhWFFnUHlCdmRYUndkWFF1YzJ4cFkyVW9NQ3dnYkdsdGFYUXBJRG9nYjNWMGNIVjBPMXh1SUNCOU8xeHVYRzRnSUhKbGRIVnliaUJ6Wld4bU8xeHVmU2tvS1R0Y2JseHVmU3g3ZlYwc05qcGJablZ1WTNScGIyNG9jbVZ4ZFdseVpTeHRiMlIxYkdVc1pYaHdiM0owY3lsN1hHNWNibjBzZTMxZExEYzZXMloxYm1OMGFXOXVLSEpsY1hWcGNtVXNiVzlrZFd4bExHVjRjRzl5ZEhNcGUxeHVKM1Z6WlNCemRISnBZM1FuTzF4dVhHNTJZWElnVDI1bFZtVnljMmx2YmtOdmJuTjBjbUZwYm5RZ1BTQnlaWEYxYVhKbEtDZHBibVJwZG1sa2RXRnNMMjl1WlMxMlpYSnphVzl1SnlrN1hHNWNiblpoY2lCTldWOVdSVkpUU1U5T0lEMGdKemNuTzF4dVQyNWxWbVZ5YzJsdmJrTnZibk4wY21GcGJuUW9KMlYyTFhOMGIzSmxKeXdnVFZsZlZrVlNVMGxQVGlrN1hHNWNiblpoY2lCb1lYTm9TMlY1SUQwZ0oxOWZSVlpmVTFSUFVrVmZTMFZaUUNjZ0t5Qk5XVjlXUlZKVFNVOU9PMXh1WEc1dGIyUjFiR1V1Wlhod2IzSjBjeUE5SUVWMlUzUnZjbVU3WEc1Y2JtWjFibU4wYVc5dUlFVjJVM1J2Y21Vb1pXeGxiU2tnZTF4dUlDQWdJSFpoY2lCb1lYTm9JRDBnWld4bGJWdG9ZWE5vUzJWNVhUdGNibHh1SUNBZ0lHbG1JQ2doYUdGemFDa2dlMXh1SUNBZ0lDQWdJQ0JvWVhOb0lEMGdaV3hsYlZ0b1lYTm9TMlY1WFNBOUlIdDlPMXh1SUNBZ0lIMWNibHh1SUNBZ0lISmxkSFZ5YmlCb1lYTm9PMXh1ZlZ4dVhHNTlMSHRjSW1sdVpHbDJhV1IxWVd3dmIyNWxMWFpsY25OcGIyNWNJam81ZlYwc09EcGJablZ1WTNScGIyNG9jbVZ4ZFdseVpTeHRiMlIxYkdVc1pYaHdiM0owY3lsN1hHNG9ablZ1WTNScGIyNGdLR2RzYjJKaGJDbDdYRzRuZFhObElITjBjbWxqZENjN1hHNWNiaThxWjJ4dlltRnNJSGRwYm1SdmR5d2daMnh2WW1Gc0tpOWNibHh1ZG1GeUlISnZiM1FnUFNCMGVYQmxiMllnZDJsdVpHOTNJQ0U5UFNBbmRXNWtaV1pwYm1Wa0p5QS9YRzRnSUNBZ2QybHVaRzkzSURvZ2RIbHdaVzltSUdkc2IySmhiQ0FoUFQwZ0ozVnVaR1ZtYVc1bFpDY2dQMXh1SUNBZ0lHZHNiMkpoYkNBNklIdDlPMXh1WEc1dGIyUjFiR1V1Wlhod2IzSjBjeUE5SUVsdVpHbDJhV1IxWVd3N1hHNWNibVoxYm1OMGFXOXVJRWx1WkdsMmFXUjFZV3dvYTJWNUxDQjJZV3gxWlNrZ2UxeHVJQ0FnSUdsbUlDaHJaWGtnYVc0Z2NtOXZkQ2tnZTF4dUlDQWdJQ0FnSUNCeVpYUjFjbTRnY205dmRGdHJaWGxkTzF4dUlDQWdJSDFjYmx4dUlDQWdJSEp2YjNSYmEyVjVYU0E5SUhaaGJIVmxPMXh1WEc0Z0lDQWdjbVYwZFhKdUlIWmhiSFZsTzF4dWZWeHVYRzU5S1M1allXeHNLSFJvYVhNc2RIbHdaVzltSUdkc2IySmhiQ0FoUFQwZ1hDSjFibVJsWm1sdVpXUmNJaUEvSUdkc2IySmhiQ0E2SUhSNWNHVnZaaUJ6Wld4bUlDRTlQU0JjSW5WdVpHVm1hVzVsWkZ3aUlEOGdjMlZzWmlBNklIUjVjR1Z2WmlCM2FXNWtiM2NnSVQwOUlGd2lkVzVrWldacGJtVmtYQ0lnUHlCM2FXNWtiM2NnT2lCN2ZTbGNibjBzZTMxZExEazZXMloxYm1OMGFXOXVLSEpsY1hWcGNtVXNiVzlrZFd4bExHVjRjRzl5ZEhNcGUxeHVKM1Z6WlNCemRISnBZM1FuTzF4dVhHNTJZWElnU1c1a2FYWnBaSFZoYkNBOUlISmxjWFZwY21Vb0p5NHZhVzVrWlhndWFuTW5LVHRjYmx4dWJXOWtkV3hsTG1WNGNHOXlkSE1nUFNCUGJtVldaWEp6YVc5dU8xeHVYRzVtZFc1amRHbHZiaUJQYm1WV1pYSnphVzl1S0cxdlpIVnNaVTVoYldVc0lIWmxjbk5wYjI0c0lHUmxabUYxYkhSV1lXeDFaU2tnZTF4dUlDQWdJSFpoY2lCclpYa2dQU0FuWDE5SlRrUkpWa2xFVlVGTVgwOU9SVjlXUlZKVFNVOU9YeWNnS3lCdGIyUjFiR1ZPWVcxbE8xeHVJQ0FnSUhaaGNpQmxibVp2Y21ObFMyVjVJRDBnYTJWNUlDc2dKMTlGVGtaUFVrTkZYMU5KVGtkTVJWUlBUaWM3WEc1Y2JpQWdJQ0IyWVhJZ2RtVnljMmx2YmxaaGJIVmxJRDBnU1c1a2FYWnBaSFZoYkNobGJtWnZjbU5sUzJWNUxDQjJaWEp6YVc5dUtUdGNibHh1SUNBZ0lHbG1JQ2gyWlhKemFXOXVWbUZzZFdVZ0lUMDlJSFpsY25OcGIyNHBJSHRjYmlBZ0lDQWdJQ0FnZEdoeWIzY2dibVYzSUVWeWNtOXlLQ2REWVc0Z2IyNXNlU0JvWVhabElHOXVaU0JqYjNCNUlHOW1JQ2NnSzF4dUlDQWdJQ0FnSUNBZ0lDQWdiVzlrZFd4bFRtRnRaU0FySUNjdVhGeHVKeUFyWEc0Z0lDQWdJQ0FnSUNBZ0lDQW5XVzkxSUdGc2NtVmhaSGtnYUdGMlpTQjJaWEp6YVc5dUlDY2dLeUIyWlhKemFXOXVWbUZzZFdVZ0sxeHVJQ0FnSUNBZ0lDQWdJQ0FnSnlCcGJuTjBZV3hzWldRdVhGeHVKeUFyWEc0Z0lDQWdJQ0FnSUNBZ0lDQW5WR2hwY3lCdFpXRnVjeUI1YjNVZ1kyRnVibTkwSUdsdWMzUmhiR3dnZG1WeWMybHZiaUFuSUNzZ2RtVnljMmx2YmlrN1hHNGdJQ0FnZlZ4dVhHNGdJQ0FnY21WMGRYSnVJRWx1WkdsMmFXUjFZV3dvYTJWNUxDQmtaV1poZFd4MFZtRnNkV1VwTzF4dWZWeHVYRzU5TEh0Y0lpNHZhVzVrWlhndWFuTmNJam80ZlYwc01UQTZXMloxYm1OMGFXOXVLSEpsY1hWcGNtVXNiVzlrZFd4bExHVjRjRzl5ZEhNcGUxeHVLR1oxYm1OMGFXOXVJQ2huYkc5aVlXd3BlMXh1ZG1GeUlIUnZjRXhsZG1Wc0lEMGdkSGx3Wlc5bUlHZHNiMkpoYkNBaFBUMGdKM1Z1WkdWbWFXNWxaQ2NnUHlCbmJHOWlZV3dnT2x4dUlDQWdJSFI1Y0dWdlppQjNhVzVrYjNjZ0lUMDlJQ2QxYm1SbFptbHVaV1FuSUQ4Z2QybHVaRzkzSURvZ2UzMWNiblpoY2lCdGFXNUViMk1nUFNCeVpYRjFhWEpsS0NkdGFXNHRaRzlqZFcxbGJuUW5LVHRjYmx4dWFXWWdLSFI1Y0dWdlppQmtiMk4xYldWdWRDQWhQVDBnSjNWdVpHVm1hVzVsWkNjcElIdGNiaUFnSUNCdGIyUjFiR1V1Wlhod2IzSjBjeUE5SUdSdlkzVnRaVzUwTzF4dWZTQmxiSE5sSUh0Y2JpQWdJQ0IyWVhJZ1pHOWpZM2tnUFNCMGIzQk1aWFpsYkZzblgxOUhURTlDUVV4ZlJFOURWVTFGVGxSZlEwRkRTRVZBTkNkZE8xeHVYRzRnSUNBZ2FXWWdLQ0ZrYjJOamVTa2dlMXh1SUNBZ0lDQWdJQ0JrYjJOamVTQTlJSFJ2Y0V4bGRtVnNXeWRmWDBkTVQwSkJURjlFVDBOVlRVVk9WRjlEUVVOSVJVQTBKMTBnUFNCdGFXNUViMk03WEc0Z0lDQWdmVnh1WEc0Z0lDQWdiVzlrZFd4bExtVjRjRzl5ZEhNZ1BTQmtiMk5qZVR0Y2JuMWNibHh1ZlNrdVkyRnNiQ2gwYUdsekxIUjVjR1Z2WmlCbmJHOWlZV3dnSVQwOUlGd2lkVzVrWldacGJtVmtYQ0lnUHlCbmJHOWlZV3dnT2lCMGVYQmxiMllnYzJWc1ppQWhQVDBnWENKMWJtUmxabWx1WldSY0lpQS9JSE5sYkdZZ09pQjBlWEJsYjJZZ2QybHVaRzkzSUNFOVBTQmNJblZ1WkdWbWFXNWxaRndpSUQ4Z2QybHVaRzkzSURvZ2UzMHBYRzU5TEh0Y0ltMXBiaTFrYjJOMWJXVnVkRndpT2paOVhTd3hNVHBiWm5WdVkzUnBiMjRvY21WeGRXbHlaU3h0YjJSMWJHVXNaWGh3YjNKMGN5bDdYRzVjSW5WelpTQnpkSEpwWTNSY0lqdGNibHh1Ylc5a2RXeGxMbVY0Y0c5eWRITWdQU0JtZFc1amRHbHZiaUJwYzA5aWFtVmpkQ2g0S1NCN1hHNWNkSEpsZEhWeWJpQjBlWEJsYjJZZ2VDQTlQVDBnWENKdlltcGxZM1JjSWlBbUppQjRJQ0U5UFNCdWRXeHNPMXh1ZlR0Y2JseHVmU3g3ZlYwc01USTZXMloxYm1OMGFXOXVLSEpsY1hWcGNtVXNiVzlrZFd4bExHVjRjRzl5ZEhNcGUxeHVkbUZ5SUc1aGRHbDJaVWx6UVhKeVlYa2dQU0JCY25KaGVTNXBjMEZ5Y21GNVhHNTJZWElnZEc5VGRISnBibWNnUFNCUFltcGxZM1F1Y0hKdmRHOTBlWEJsTG5SdlUzUnlhVzVuWEc1Y2JtMXZaSFZzWlM1bGVIQnZjblJ6SUQwZ2JtRjBhWFpsU1hOQmNuSmhlU0I4ZkNCcGMwRnljbUY1WEc1Y2JtWjFibU4wYVc5dUlHbHpRWEp5WVhrb2IySnFLU0I3WEc0Z0lDQWdjbVYwZFhKdUlIUnZVM1J5YVc1bkxtTmhiR3dvYjJKcUtTQTlQVDBnWENKYmIySnFaV04wSUVGeWNtRjVYVndpWEc1OVhHNWNibjBzZTMxZExERXpPbHRtZFc1amRHbHZiaWh5WlhGMWFYSmxMRzF2WkhWc1pTeGxlSEJ2Y25SektYdGNiblpoY2lCd1lYUmphQ0E5SUhKbGNYVnBjbVVvWENJdUwzWmtiMjB2Y0dGMFkyZ3Vhbk5jSWlsY2JseHViVzlrZFd4bExtVjRjRzl5ZEhNZ1BTQndZWFJqYUZ4dVhHNTlMSHRjSWk0dmRtUnZiUzl3WVhSamFDNXFjMXdpT2pFNGZWMHNNVFE2VzJaMWJtTjBhVzl1S0hKbGNYVnBjbVVzYlc5a2RXeGxMR1Y0Y0c5eWRITXBlMXh1ZG1GeUlHbHpUMkpxWldOMElEMGdjbVZ4ZFdseVpTaGNJbWx6TFc5aWFtVmpkRndpS1Z4dWRtRnlJR2x6U0c5dmF5QTlJSEpsY1hWcGNtVW9YQ0l1TGk5MmJtOWtaUzlwY3kxMmFHOXZheTVxYzF3aUtWeHVYRzV0YjJSMWJHVXVaWGh3YjNKMGN5QTlJR0Z3Y0d4NVVISnZjR1Z5ZEdsbGMxeHVYRzVtZFc1amRHbHZiaUJoY0hCc2VWQnliM0JsY25ScFpYTW9ibTlrWlN3Z2NISnZjSE1zSUhCeVpYWnBiM1Z6S1NCN1hHNGdJQ0FnWm05eUlDaDJZWElnY0hKdmNFNWhiV1VnYVc0Z2NISnZjSE1wSUh0Y2JpQWdJQ0FnSUNBZ2RtRnlJSEJ5YjNCV1lXeDFaU0E5SUhCeWIzQnpXM0J5YjNCT1lXMWxYVnh1WEc0Z0lDQWdJQ0FnSUdsbUlDaHdjbTl3Vm1Gc2RXVWdQVDA5SUhWdVpHVm1hVzVsWkNrZ2UxeHVJQ0FnSUNBZ0lDQWdJQ0FnY21WdGIzWmxVSEp2Y0dWeWRIa29ibTlrWlN3Z2NISnZjRTVoYldVc0lIQnliM0JXWVd4MVpTd2djSEpsZG1sdmRYTXBPMXh1SUNBZ0lDQWdJQ0I5SUdWc2MyVWdhV1lnS0dselNHOXZheWh3Y205d1ZtRnNkV1VwS1NCN1hHNGdJQ0FnSUNBZ0lDQWdJQ0J5WlcxdmRtVlFjbTl3WlhKMGVTaHViMlJsTENCd2NtOXdUbUZ0WlN3Z2NISnZjRlpoYkhWbExDQndjbVYyYVc5MWN5bGNiaUFnSUNBZ0lDQWdJQ0FnSUdsbUlDaHdjbTl3Vm1Gc2RXVXVhRzl2YXlrZ2UxeHVJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lIQnliM0JXWVd4MVpTNW9iMjlyS0c1dlpHVXNYRzRnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUhCeWIzQk9ZVzFsTEZ4dUlDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQndjbVYyYVc5MWN5QS9JSEJ5WlhacGIzVnpXM0J5YjNCT1lXMWxYU0E2SUhWdVpHVm1hVzVsWkNsY2JpQWdJQ0FnSUNBZ0lDQWdJSDFjYmlBZ0lDQWdJQ0FnZlNCbGJITmxJSHRjYmlBZ0lDQWdJQ0FnSUNBZ0lHbG1JQ2hwYzA5aWFtVmpkQ2h3Y205d1ZtRnNkV1VwS1NCN1hHNGdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ2NHRjBZMmhQWW1wbFkzUW9ibTlrWlN3Z2NISnZjSE1zSUhCeVpYWnBiM1Z6TENCd2NtOXdUbUZ0WlN3Z2NISnZjRlpoYkhWbEtUdGNiaUFnSUNBZ0lDQWdJQ0FnSUgwZ1pXeHpaU0I3WEc0Z0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnYm05a1pWdHdjbTl3VG1GdFpWMGdQU0J3Y205d1ZtRnNkV1ZjYmlBZ0lDQWdJQ0FnSUNBZ0lIMWNiaUFnSUNBZ0lDQWdmVnh1SUNBZ0lIMWNibjFjYmx4dVpuVnVZM1JwYjI0Z2NtVnRiM1psVUhKdmNHVnlkSGtvYm05a1pTd2djSEp2Y0U1aGJXVXNJSEJ5YjNCV1lXeDFaU3dnY0hKbGRtbHZkWE1wSUh0Y2JpQWdJQ0JwWmlBb2NISmxkbWx2ZFhNcElIdGNiaUFnSUNBZ0lDQWdkbUZ5SUhCeVpYWnBiM1Z6Vm1Gc2RXVWdQU0J3Y21WMmFXOTFjMXR3Y205d1RtRnRaVjFjYmx4dUlDQWdJQ0FnSUNCcFppQW9JV2x6U0c5dmF5aHdjbVYyYVc5MWMxWmhiSFZsS1NrZ2UxeHVJQ0FnSUNBZ0lDQWdJQ0FnYVdZZ0tIQnliM0JPWVcxbElEMDlQU0JjSW1GMGRISnBZblYwWlhOY0lpa2dlMXh1SUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJR1p2Y2lBb2RtRnlJR0YwZEhKT1lXMWxJR2x1SUhCeVpYWnBiM1Z6Vm1Gc2RXVXBJSHRjYmlBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ2JtOWtaUzV5WlcxdmRtVkJkSFJ5YVdKMWRHVW9ZWFIwY2s1aGJXVXBYRzRnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdmVnh1SUNBZ0lDQWdJQ0FnSUNBZ2ZTQmxiSE5sSUdsbUlDaHdjbTl3VG1GdFpTQTlQVDBnWENKemRIbHNaVndpS1NCN1hHNGdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ1ptOXlJQ2gyWVhJZ2FTQnBiaUJ3Y21WMmFXOTFjMVpoYkhWbEtTQjdYRzRnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUc1dlpHVXVjM1I1YkdWYmFWMGdQU0JjSWx3aVhHNGdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ2ZWeHVJQ0FnSUNBZ0lDQWdJQ0FnZlNCbGJITmxJR2xtSUNoMGVYQmxiMllnY0hKbGRtbHZkWE5XWVd4MVpTQTlQVDBnWENKemRISnBibWRjSWlrZ2UxeHVJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lHNXZaR1ZiY0hKdmNFNWhiV1ZkSUQwZ1hDSmNJbHh1SUNBZ0lDQWdJQ0FnSUNBZ2ZTQmxiSE5sSUh0Y2JpQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNCdWIyUmxXM0J5YjNCT1lXMWxYU0E5SUc1MWJHeGNiaUFnSUNBZ0lDQWdJQ0FnSUgxY2JpQWdJQ0FnSUNBZ2ZTQmxiSE5sSUdsbUlDaHdjbVYyYVc5MWMxWmhiSFZsTG5WdWFHOXZheWtnZTF4dUlDQWdJQ0FnSUNBZ0lDQWdjSEpsZG1sdmRYTldZV3gxWlM1MWJtaHZiMnNvYm05a1pTd2djSEp2Y0U1aGJXVXNJSEJ5YjNCV1lXeDFaU2xjYmlBZ0lDQWdJQ0FnZlZ4dUlDQWdJSDFjYm4xY2JseHVablZ1WTNScGIyNGdjR0YwWTJoUFltcGxZM1FvYm05a1pTd2djSEp2Y0hNc0lIQnlaWFpwYjNWekxDQndjbTl3VG1GdFpTd2djSEp2Y0ZaaGJIVmxLU0I3WEc0Z0lDQWdkbUZ5SUhCeVpYWnBiM1Z6Vm1Gc2RXVWdQU0J3Y21WMmFXOTFjeUEvSUhCeVpYWnBiM1Z6VzNCeWIzQk9ZVzFsWFNBNklIVnVaR1ZtYVc1bFpGeHVYRzRnSUNBZ0x5OGdVMlYwSUdGMGRISnBZblYwWlhOY2JpQWdJQ0JwWmlBb2NISnZjRTVoYldVZ1BUMDlJRndpWVhSMGNtbGlkWFJsYzF3aUtTQjdYRzRnSUNBZ0lDQWdJR1p2Y2lBb2RtRnlJR0YwZEhKT1lXMWxJR2x1SUhCeWIzQldZV3gxWlNrZ2UxeHVJQ0FnSUNBZ0lDQWdJQ0FnZG1GeUlHRjBkSEpXWVd4MVpTQTlJSEJ5YjNCV1lXeDFaVnRoZEhSeVRtRnRaVjFjYmx4dUlDQWdJQ0FnSUNBZ0lDQWdhV1lnS0dGMGRISldZV3gxWlNBOVBUMGdkVzVrWldacGJtVmtLU0I3WEc0Z0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnYm05a1pTNXlaVzF2ZG1WQmRIUnlhV0oxZEdVb1lYUjBjazVoYldVcFhHNGdJQ0FnSUNBZ0lDQWdJQ0I5SUdWc2MyVWdlMXh1SUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJRzV2WkdVdWMyVjBRWFIwY21saWRYUmxLR0YwZEhKT1lXMWxMQ0JoZEhSeVZtRnNkV1VwWEc0Z0lDQWdJQ0FnSUNBZ0lDQjlYRzRnSUNBZ0lDQWdJSDFjYmx4dUlDQWdJQ0FnSUNCeVpYUjFjbTVjYmlBZ0lDQjlYRzVjYmlBZ0lDQnBaaWh3Y21WMmFXOTFjMVpoYkhWbElDWW1JR2x6VDJKcVpXTjBLSEJ5WlhacGIzVnpWbUZzZFdVcElDWW1YRzRnSUNBZ0lDQWdJR2RsZEZCeWIzUnZkSGx3WlNod2NtVjJhVzkxYzFaaGJIVmxLU0FoUFQwZ1oyVjBVSEp2ZEc5MGVYQmxLSEJ5YjNCV1lXeDFaU2twSUh0Y2JpQWdJQ0FnSUNBZ2JtOWtaVnR3Y205d1RtRnRaVjBnUFNCd2NtOXdWbUZzZFdWY2JpQWdJQ0FnSUNBZ2NtVjBkWEp1WEc0Z0lDQWdmVnh1WEc0Z0lDQWdhV1lnS0NGcGMwOWlhbVZqZENodWIyUmxXM0J5YjNCT1lXMWxYU2twSUh0Y2JpQWdJQ0FnSUNBZ2JtOWtaVnR3Y205d1RtRnRaVjBnUFNCN2ZWeHVJQ0FnSUgxY2JseHVJQ0FnSUhaaGNpQnlaWEJzWVdObGNpQTlJSEJ5YjNCT1lXMWxJRDA5UFNCY0luTjBlV3hsWENJZ1B5QmNJbHdpSURvZ2RXNWtaV1pwYm1Wa1hHNWNiaUFnSUNCbWIzSWdLSFpoY2lCcklHbHVJSEJ5YjNCV1lXeDFaU2tnZTF4dUlDQWdJQ0FnSUNCMllYSWdkbUZzZFdVZ1BTQndjbTl3Vm1Gc2RXVmJhMTFjYmlBZ0lDQWdJQ0FnYm05a1pWdHdjbTl3VG1GdFpWMWJhMTBnUFNBb2RtRnNkV1VnUFQwOUlIVnVaR1ZtYVc1bFpDa2dQeUJ5WlhCc1lXTmxjaUE2SUhaaGJIVmxYRzRnSUNBZ2ZWeHVmVnh1WEc1bWRXNWpkR2x2YmlCblpYUlFjbTkwYjNSNWNHVW9kbUZzZFdVcElIdGNiaUFnSUNCcFppQW9UMkpxWldOMExtZGxkRkJ5YjNSdmRIbHdaVTltS1NCN1hHNGdJQ0FnSUNBZ0lISmxkSFZ5YmlCUFltcGxZM1F1WjJWMFVISnZkRzkwZVhCbFQyWW9kbUZzZFdVcFhHNGdJQ0FnZlNCbGJITmxJR2xtSUNoMllXeDFaUzVmWDNCeWIzUnZYMThwSUh0Y2JpQWdJQ0FnSUNBZ2NtVjBkWEp1SUhaaGJIVmxMbDlmY0hKdmRHOWZYMXh1SUNBZ0lIMGdaV3h6WlNCcFppQW9kbUZzZFdVdVkyOXVjM1J5ZFdOMGIzSXBJSHRjYmlBZ0lDQWdJQ0FnY21WMGRYSnVJSFpoYkhWbExtTnZibk4wY25WamRHOXlMbkJ5YjNSdmRIbHdaVnh1SUNBZ0lIMWNibjFjYmx4dWZTeDdYQ0l1TGk5MmJtOWtaUzlwY3kxMmFHOXZheTVxYzF3aU9qSTJMRndpYVhNdGIySnFaV04wWENJNk1URjlYU3d4TlRwYlpuVnVZM1JwYjI0b2NtVnhkV2x5WlN4dGIyUjFiR1VzWlhod2IzSjBjeWw3WEc1MllYSWdaRzlqZFcxbGJuUWdQU0J5WlhGMWFYSmxLRndpWjJ4dlltRnNMMlJ2WTNWdFpXNTBYQ0lwWEc1Y2JuWmhjaUJoY0hCc2VWQnliM0JsY25ScFpYTWdQU0J5WlhGMWFYSmxLRndpTGk5aGNIQnNlUzF3Y205d1pYSjBhV1Z6WENJcFhHNWNiblpoY2lCcGMxWk9iMlJsSUQwZ2NtVnhkV2x5WlNoY0lpNHVMM1p1YjJSbEwybHpMWFp1YjJSbExtcHpYQ0lwWEc1MllYSWdhWE5XVkdWNGRDQTlJSEpsY1hWcGNtVW9YQ0l1TGk5MmJtOWtaUzlwY3kxMmRHVjRkQzVxYzF3aUtWeHVkbUZ5SUdselYybGtaMlYwSUQwZ2NtVnhkV2x5WlNoY0lpNHVMM1p1YjJSbEwybHpMWGRwWkdkbGRDNXFjMXdpS1Z4dWRtRnlJR2hoYm1Sc1pWUm9kVzVySUQwZ2NtVnhkV2x5WlNoY0lpNHVMM1p1YjJSbEwyaGhibVJzWlMxMGFIVnVheTVxYzF3aUtWeHVYRzV0YjJSMWJHVXVaWGh3YjNKMGN5QTlJR055WldGMFpVVnNaVzFsYm5SY2JseHVablZ1WTNScGIyNGdZM0psWVhSbFJXeGxiV1Z1ZENoMmJtOWtaU3dnYjNCMGN5a2dlMXh1SUNBZ0lIWmhjaUJrYjJNZ1BTQnZjSFJ6SUQ4Z2IzQjBjeTVrYjJOMWJXVnVkQ0I4ZkNCa2IyTjFiV1Z1ZENBNklHUnZZM1Z0Wlc1MFhHNGdJQ0FnZG1GeUlIZGhjbTRnUFNCdmNIUnpJRDhnYjNCMGN5NTNZWEp1SURvZ2JuVnNiRnh1WEc0Z0lDQWdkbTV2WkdVZ1BTQm9ZVzVrYkdWVWFIVnVheWgyYm05a1pTa3VZVnh1WEc0Z0lDQWdhV1lnS0dselYybGtaMlYwS0hadWIyUmxLU2tnZTF4dUlDQWdJQ0FnSUNCeVpYUjFjbTRnZG01dlpHVXVhVzVwZENncFhHNGdJQ0FnZlNCbGJITmxJR2xtSUNocGMxWlVaWGgwS0hadWIyUmxLU2tnZTF4dUlDQWdJQ0FnSUNCeVpYUjFjbTRnWkc5akxtTnlaV0YwWlZSbGVIUk9iMlJsS0hadWIyUmxMblJsZUhRcFhHNGdJQ0FnZlNCbGJITmxJR2xtSUNnaGFYTldUbTlrWlNoMmJtOWtaU2twSUh0Y2JpQWdJQ0FnSUNBZ2FXWWdLSGRoY200cElIdGNiaUFnSUNBZ0lDQWdJQ0FnSUhkaGNtNG9YQ0pKZEdWdElHbHpJRzV2ZENCaElIWmhiR2xrSUhacGNuUjFZV3dnWkc5dElHNXZaR1ZjSWl3Z2RtNXZaR1VwWEc0Z0lDQWdJQ0FnSUgxY2JpQWdJQ0FnSUNBZ2NtVjBkWEp1SUc1MWJHeGNiaUFnSUNCOVhHNWNiaUFnSUNCMllYSWdibTlrWlNBOUlDaDJibTlrWlM1dVlXMWxjM0JoWTJVZ1BUMDlJRzUxYkd3cElEOWNiaUFnSUNBZ0lDQWdaRzlqTG1OeVpXRjBaVVZzWlcxbGJuUW9kbTV2WkdVdWRHRm5UbUZ0WlNrZ09seHVJQ0FnSUNBZ0lDQmtiMk11WTNKbFlYUmxSV3hsYldWdWRFNVRLSFp1YjJSbExtNWhiV1Z6Y0dGalpTd2dkbTV2WkdVdWRHRm5UbUZ0WlNsY2JseHVJQ0FnSUhaaGNpQndjbTl3Y3lBOUlIWnViMlJsTG5CeWIzQmxjblJwWlhOY2JpQWdJQ0JoY0hCc2VWQnliM0JsY25ScFpYTW9ibTlrWlN3Z2NISnZjSE1wWEc1Y2JpQWdJQ0IyWVhJZ1kyaHBiR1J5Wlc0Z1BTQjJibTlrWlM1amFHbHNaSEpsYmx4dVhHNGdJQ0FnWm05eUlDaDJZWElnYVNBOUlEQTdJR2tnUENCamFHbHNaSEpsYmk1c1pXNW5kR2c3SUdrckt5a2dlMXh1SUNBZ0lDQWdJQ0IyWVhJZ1kyaHBiR1JPYjJSbElEMGdZM0psWVhSbFJXeGxiV1Z1ZENoamFHbHNaSEpsYmx0cFhTd2diM0IwY3lsY2JpQWdJQ0FnSUNBZ2FXWWdLR05vYVd4a1RtOWtaU2tnZTF4dUlDQWdJQ0FnSUNBZ0lDQWdibTlrWlM1aGNIQmxibVJEYUdsc1pDaGphR2xzWkU1dlpHVXBYRzRnSUNBZ0lDQWdJSDFjYmlBZ0lDQjlYRzVjYmlBZ0lDQnlaWFIxY200Z2JtOWtaVnh1ZlZ4dVhHNTlMSHRjSWk0dUwzWnViMlJsTDJoaGJtUnNaUzEwYUhWdWF5NXFjMXdpT2pJMExGd2lMaTR2ZG01dlpHVXZhWE10ZG01dlpHVXVhbk5jSWpveU55eGNJaTR1TDNadWIyUmxMMmx6TFhaMFpYaDBMbXB6WENJNk1qZ3NYQ0l1TGk5MmJtOWtaUzlwY3kxM2FXUm5aWFF1YW5OY0lqb3lPU3hjSWk0dllYQndiSGt0Y0hKdmNHVnlkR2xsYzF3aU9qRTBMRndpWjJ4dlltRnNMMlJ2WTNWdFpXNTBYQ0k2TVRCOVhTd3hOanBiWm5WdVkzUnBiMjRvY21WeGRXbHlaU3h0YjJSMWJHVXNaWGh3YjNKMGN5bDdYRzR2THlCTllYQnpJR0VnZG1seWRIVmhiQ0JFVDAwZ2RISmxaU0J2Ym5SdklHRWdjbVZoYkNCRVQwMGdkSEpsWlNCcGJpQmhiaUJsWm1acFkybGxiblFnYldGdWJtVnlMbHh1THk4Z1YyVWdaRzl1SjNRZ2QyRnVkQ0IwYnlCeVpXRmtJR0ZzYkNCdlppQjBhR1VnUkU5TklHNXZaR1Z6SUdsdUlIUm9aU0IwY21WbElITnZJSGRsSUhWelpWeHVMeThnZEdobElHbHVMVzl5WkdWeUlIUnlaV1VnYVc1a1pYaHBibWNnZEc4Z1pXeHBiV2x1WVhSbElISmxZM1Z5YzJsdmJpQmtiM2R1SUdObGNuUmhhVzRnWW5KaGJtTm9aWE11WEc0dkx5QlhaU0J2Ym14NUlISmxZM1Z5YzJVZ2FXNTBieUJoSUVSUFRTQnViMlJsSUdsbUlIZGxJR3R1YjNjZ2RHaGhkQ0JwZENCamIyNTBZV2x1Y3lCaElHTm9hV3hrSUc5bVhHNHZMeUJwYm5SbGNtVnpkQzVjYmx4dWRtRnlJRzV2UTJocGJHUWdQU0I3ZlZ4dVhHNXRiMlIxYkdVdVpYaHdiM0owY3lBOUlHUnZiVWx1WkdWNFhHNWNibVoxYm1OMGFXOXVJR1J2YlVsdVpHVjRLSEp2YjNST2IyUmxMQ0IwY21WbExDQnBibVJwWTJWekxDQnViMlJsY3lrZ2UxeHVJQ0FnSUdsbUlDZ2hhVzVrYVdObGN5QjhmQ0JwYm1ScFkyVnpMbXhsYm1kMGFDQTlQVDBnTUNrZ2UxeHVJQ0FnSUNBZ0lDQnlaWFIxY200Z2UzMWNiaUFnSUNCOUlHVnNjMlVnZTF4dUlDQWdJQ0FnSUNCcGJtUnBZMlZ6TG5OdmNuUW9ZWE5qWlc1a2FXNW5LVnh1SUNBZ0lDQWdJQ0J5WlhSMWNtNGdjbVZqZFhKelpTaHliMjkwVG05a1pTd2dkSEpsWlN3Z2FXNWthV05sY3l3Z2JtOWtaWE1zSURBcFhHNGdJQ0FnZlZ4dWZWeHVYRzVtZFc1amRHbHZiaUJ5WldOMWNuTmxLSEp2YjNST2IyUmxMQ0IwY21WbExDQnBibVJwWTJWekxDQnViMlJsY3l3Z2NtOXZkRWx1WkdWNEtTQjdYRzRnSUNBZ2JtOWtaWE1nUFNCdWIyUmxjeUI4ZkNCN2ZWeHVYRzVjYmlBZ0lDQnBaaUFvY205dmRFNXZaR1VwSUh0Y2JpQWdJQ0FnSUNBZ2FXWWdLR2x1WkdWNFNXNVNZVzVuWlNocGJtUnBZMlZ6TENCeWIyOTBTVzVrWlhnc0lISnZiM1JKYm1SbGVDa3BJSHRjYmlBZ0lDQWdJQ0FnSUNBZ0lHNXZaR1Z6VzNKdmIzUkpibVJsZUYwZ1BTQnliMjkwVG05a1pWeHVJQ0FnSUNBZ0lDQjlYRzVjYmlBZ0lDQWdJQ0FnZG1GeUlIWkRhR2xzWkhKbGJpQTlJSFJ5WldVdVkyaHBiR1J5Wlc1Y2JseHVJQ0FnSUNBZ0lDQnBaaUFvZGtOb2FXeGtjbVZ1S1NCN1hHNWNiaUFnSUNBZ0lDQWdJQ0FnSUhaaGNpQmphR2xzWkU1dlpHVnpJRDBnY205dmRFNXZaR1V1WTJocGJHUk9iMlJsYzF4dVhHNGdJQ0FnSUNBZ0lDQWdJQ0JtYjNJZ0tIWmhjaUJwSUQwZ01Ec2dhU0E4SUhSeVpXVXVZMmhwYkdSeVpXNHViR1Z1WjNSb095QnBLeXNwSUh0Y2JpQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNCeWIyOTBTVzVrWlhnZ0t6MGdNVnh1WEc0Z0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnZG1GeUlIWkRhR2xzWkNBOUlIWkRhR2xzWkhKbGJsdHBYU0I4ZkNCdWIwTm9hV3hrWEc0Z0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnZG1GeUlHNWxlSFJKYm1SbGVDQTlJSEp2YjNSSmJtUmxlQ0FySUNoMlEyaHBiR1F1WTI5MWJuUWdmSHdnTUNsY2JseHVJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDOHZJSE5yYVhBZ2NtVmpkWEp6YVc5dUlHUnZkMjRnZEdobElIUnlaV1VnYVdZZ2RHaGxjbVVnWVhKbElHNXZJRzV2WkdWeklHUnZkMjRnYUdWeVpWeHVJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lHbG1JQ2hwYm1SbGVFbHVVbUZ1WjJVb2FXNWthV05sY3l3Z2NtOXZkRWx1WkdWNExDQnVaWGgwU1c1a1pYZ3BLU0I3WEc0Z0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lISmxZM1Z5YzJVb1kyaHBiR1JPYjJSbGMxdHBYU3dnZGtOb2FXeGtMQ0JwYm1ScFkyVnpMQ0J1YjJSbGN5d2djbTl2ZEVsdVpHVjRLVnh1SUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJSDFjYmx4dUlDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUhKdmIzUkpibVJsZUNBOUlHNWxlSFJKYm1SbGVGeHVJQ0FnSUNBZ0lDQWdJQ0FnZlZ4dUlDQWdJQ0FnSUNCOVhHNGdJQ0FnZlZ4dVhHNGdJQ0FnY21WMGRYSnVJRzV2WkdWelhHNTlYRzVjYmk4dklFSnBibUZ5ZVNCelpXRnlZMmdnWm05eUlHRnVJR2x1WkdWNElHbHVJSFJvWlNCcGJuUmxjblpoYkNCYmJHVm1kQ3dnY21sbmFIUmRYRzVtZFc1amRHbHZiaUJwYm1SbGVFbHVVbUZ1WjJVb2FXNWthV05sY3l3Z2JHVm1kQ3dnY21sbmFIUXBJSHRjYmlBZ0lDQnBaaUFvYVc1a2FXTmxjeTVzWlc1bmRHZ2dQVDA5SURBcElIdGNiaUFnSUNBZ0lDQWdjbVYwZFhKdUlHWmhiSE5sWEc0Z0lDQWdmVnh1WEc0Z0lDQWdkbUZ5SUcxcGJrbHVaR1Y0SUQwZ01GeHVJQ0FnSUhaaGNpQnRZWGhKYm1SbGVDQTlJR2x1WkdsalpYTXViR1Z1WjNSb0lDMGdNVnh1SUNBZ0lIWmhjaUJqZFhKeVpXNTBTVzVrWlhoY2JpQWdJQ0IyWVhJZ1kzVnljbVZ1ZEVsMFpXMWNibHh1SUNBZ0lIZG9hV3hsSUNodGFXNUpibVJsZUNBOFBTQnRZWGhKYm1SbGVDa2dlMXh1SUNBZ0lDQWdJQ0JqZFhKeVpXNTBTVzVrWlhnZ1BTQW9LRzFoZUVsdVpHVjRJQ3NnYldsdVNXNWtaWGdwSUM4Z01pa2dQajRnTUZ4dUlDQWdJQ0FnSUNCamRYSnlaVzUwU1hSbGJTQTlJR2x1WkdsalpYTmJZM1Z5Y21WdWRFbHVaR1Y0WFZ4dVhHNGdJQ0FnSUNBZ0lHbG1JQ2h0YVc1SmJtUmxlQ0E5UFQwZ2JXRjRTVzVrWlhncElIdGNiaUFnSUNBZ0lDQWdJQ0FnSUhKbGRIVnliaUJqZFhKeVpXNTBTWFJsYlNBK1BTQnNaV1owSUNZbUlHTjFjbkpsYm5SSmRHVnRJRHc5SUhKcFoyaDBYRzRnSUNBZ0lDQWdJSDBnWld4elpTQnBaaUFvWTNWeWNtVnVkRWwwWlcwZ1BDQnNaV1owS1NCN1hHNGdJQ0FnSUNBZ0lDQWdJQ0J0YVc1SmJtUmxlQ0E5SUdOMWNuSmxiblJKYm1SbGVDQXJJREZjYmlBZ0lDQWdJQ0FnZlNCbGJITmxJQ0JwWmlBb1kzVnljbVZ1ZEVsMFpXMGdQaUJ5YVdkb2RDa2dlMXh1SUNBZ0lDQWdJQ0FnSUNBZ2JXRjRTVzVrWlhnZ1BTQmpkWEp5Wlc1MFNXNWtaWGdnTFNBeFhHNGdJQ0FnSUNBZ0lIMGdaV3h6WlNCN1hHNGdJQ0FnSUNBZ0lDQWdJQ0J5WlhSMWNtNGdkSEoxWlZ4dUlDQWdJQ0FnSUNCOVhHNGdJQ0FnZlZ4dVhHNGdJQ0FnY21WMGRYSnVJR1poYkhObE8xeHVmVnh1WEc1bWRXNWpkR2x2YmlCaGMyTmxibVJwYm1jb1lTd2dZaWtnZTF4dUlDQWdJSEpsZEhWeWJpQmhJRDRnWWlBL0lERWdPaUF0TVZ4dWZWeHVYRzU5TEh0OVhTd3hOenBiWm5WdVkzUnBiMjRvY21WeGRXbHlaU3h0YjJSMWJHVXNaWGh3YjNKMGN5bDdYRzUyWVhJZ1lYQndiSGxRY205d1pYSjBhV1Z6SUQwZ2NtVnhkV2x5WlNoY0lpNHZZWEJ3YkhrdGNISnZjR1Z5ZEdsbGMxd2lLVnh1WEc1MllYSWdhWE5YYVdSblpYUWdQU0J5WlhGMWFYSmxLRndpTGk0dmRtNXZaR1V2YVhNdGQybGtaMlYwTG1welhDSXBYRzUyWVhJZ1ZsQmhkR05vSUQwZ2NtVnhkV2x5WlNoY0lpNHVMM1p1YjJSbEwzWndZWFJqYUM1cWMxd2lLVnh1WEc1MllYSWdkWEJrWVhSbFYybGtaMlYwSUQwZ2NtVnhkV2x5WlNoY0lpNHZkWEJrWVhSbExYZHBaR2RsZEZ3aUtWeHVYRzV0YjJSMWJHVXVaWGh3YjNKMGN5QTlJR0Z3Y0d4NVVHRjBZMmhjYmx4dVpuVnVZM1JwYjI0Z1lYQndiSGxRWVhSamFDaDJjR0YwWTJnc0lHUnZiVTV2WkdVc0lISmxibVJsY2s5d2RHbHZibk1wSUh0Y2JpQWdJQ0IyWVhJZ2RIbHdaU0E5SUhad1lYUmphQzUwZVhCbFhHNGdJQ0FnZG1GeUlIWk9iMlJsSUQwZ2RuQmhkR05vTG5aT2IyUmxYRzRnSUNBZ2RtRnlJSEJoZEdOb0lEMGdkbkJoZEdOb0xuQmhkR05vWEc1Y2JpQWdJQ0J6ZDJsMFkyZ2dLSFI1Y0dVcElIdGNiaUFnSUNBZ0lDQWdZMkZ6WlNCV1VHRjBZMmd1VWtWTlQxWkZPbHh1SUNBZ0lDQWdJQ0FnSUNBZ2NtVjBkWEp1SUhKbGJXOTJaVTV2WkdVb1pHOXRUbTlrWlN3Z2RrNXZaR1VwWEc0Z0lDQWdJQ0FnSUdOaGMyVWdWbEJoZEdOb0xrbE9VMFZTVkRwY2JpQWdJQ0FnSUNBZ0lDQWdJSEpsZEhWeWJpQnBibk5sY25ST2IyUmxLR1J2YlU1dlpHVXNJSEJoZEdOb0xDQnlaVzVrWlhKUGNIUnBiMjV6S1Z4dUlDQWdJQ0FnSUNCallYTmxJRlpRWVhSamFDNVdWRVZZVkRwY2JpQWdJQ0FnSUNBZ0lDQWdJSEpsZEhWeWJpQnpkSEpwYm1kUVlYUmphQ2hrYjIxT2IyUmxMQ0IyVG05a1pTd2djR0YwWTJnc0lISmxibVJsY2s5d2RHbHZibk1wWEc0Z0lDQWdJQ0FnSUdOaGMyVWdWbEJoZEdOb0xsZEpSRWRGVkRwY2JpQWdJQ0FnSUNBZ0lDQWdJSEpsZEhWeWJpQjNhV1JuWlhSUVlYUmphQ2hrYjIxT2IyUmxMQ0IyVG05a1pTd2djR0YwWTJnc0lISmxibVJsY2s5d2RHbHZibk1wWEc0Z0lDQWdJQ0FnSUdOaGMyVWdWbEJoZEdOb0xsWk9UMFJGT2x4dUlDQWdJQ0FnSUNBZ0lDQWdjbVYwZFhKdUlIWk9iMlJsVUdGMFkyZ29aRzl0VG05a1pTd2dkazV2WkdVc0lIQmhkR05vTENCeVpXNWtaWEpQY0hScGIyNXpLVnh1SUNBZ0lDQWdJQ0JqWVhObElGWlFZWFJqYUM1UFVrUkZVanBjYmlBZ0lDQWdJQ0FnSUNBZ0lISmxiM0prWlhKRGFHbHNaSEpsYmloa2IyMU9iMlJsTENCd1lYUmphQ2xjYmlBZ0lDQWdJQ0FnSUNBZ0lISmxkSFZ5YmlCa2IyMU9iMlJsWEc0Z0lDQWdJQ0FnSUdOaGMyVWdWbEJoZEdOb0xsQlNUMUJUT2x4dUlDQWdJQ0FnSUNBZ0lDQWdZWEJ3YkhsUWNtOXdaWEowYVdWektHUnZiVTV2WkdVc0lIQmhkR05vTENCMlRtOWtaUzV3Y205d1pYSjBhV1Z6S1Z4dUlDQWdJQ0FnSUNBZ0lDQWdjbVYwZFhKdUlHUnZiVTV2WkdWY2JpQWdJQ0FnSUNBZ1kyRnpaU0JXVUdGMFkyZ3VWRWhWVGtzNlhHNGdJQ0FnSUNBZ0lDQWdJQ0J5WlhSMWNtNGdjbVZ3YkdGalpWSnZiM1FvWkc5dFRtOWtaU3hjYmlBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0J5Wlc1a1pYSlBjSFJwYjI1ekxuQmhkR05vS0dSdmJVNXZaR1VzSUhCaGRHTm9MQ0J5Wlc1a1pYSlBjSFJwYjI1ektTbGNiaUFnSUNBZ0lDQWdaR1ZtWVhWc2REcGNiaUFnSUNBZ0lDQWdJQ0FnSUhKbGRIVnliaUJrYjIxT2IyUmxYRzRnSUNBZ2ZWeHVmVnh1WEc1bWRXNWpkR2x2YmlCeVpXMXZkbVZPYjJSbEtHUnZiVTV2WkdVc0lIWk9iMlJsS1NCN1hHNGdJQ0FnZG1GeUlIQmhjbVZ1ZEU1dlpHVWdQU0JrYjIxT2IyUmxMbkJoY21WdWRFNXZaR1ZjYmx4dUlDQWdJR2xtSUNod1lYSmxiblJPYjJSbEtTQjdYRzRnSUNBZ0lDQWdJSEJoY21WdWRFNXZaR1V1Y21WdGIzWmxRMmhwYkdRb1pHOXRUbTlrWlNsY2JpQWdJQ0I5WEc1Y2JpQWdJQ0JrWlhOMGNtOTVWMmxrWjJWMEtHUnZiVTV2WkdVc0lIWk9iMlJsS1R0Y2JseHVJQ0FnSUhKbGRIVnliaUJ1ZFd4c1hHNTlYRzVjYm1aMWJtTjBhVzl1SUdsdWMyVnlkRTV2WkdVb2NHRnlaVzUwVG05a1pTd2dkazV2WkdVc0lISmxibVJsY2s5d2RHbHZibk1wSUh0Y2JpQWdJQ0IyWVhJZ2JtVjNUbTlrWlNBOUlISmxibVJsY2s5d2RHbHZibk11Y21WdVpHVnlLSFpPYjJSbExDQnlaVzVrWlhKUGNIUnBiMjV6S1Z4dVhHNGdJQ0FnYVdZZ0tIQmhjbVZ1ZEU1dlpHVXBJSHRjYmlBZ0lDQWdJQ0FnY0dGeVpXNTBUbTlrWlM1aGNIQmxibVJEYUdsc1pDaHVaWGRPYjJSbEtWeHVJQ0FnSUgxY2JseHVJQ0FnSUhKbGRIVnliaUJ3WVhKbGJuUk9iMlJsWEc1OVhHNWNibVoxYm1OMGFXOXVJSE4wY21sdVoxQmhkR05vS0dSdmJVNXZaR1VzSUd4bFpuUldUbTlrWlN3Z2RsUmxlSFFzSUhKbGJtUmxjazl3ZEdsdmJuTXBJSHRjYmlBZ0lDQjJZWElnYm1WM1RtOWtaVnh1WEc0Z0lDQWdhV1lnS0dSdmJVNXZaR1V1Ym05a1pWUjVjR1VnUFQwOUlETXBJSHRjYmlBZ0lDQWdJQ0FnWkc5dFRtOWtaUzV5WlhCc1lXTmxSR0YwWVNnd0xDQmtiMjFPYjJSbExteGxibWQwYUN3Z2RsUmxlSFF1ZEdWNGRDbGNiaUFnSUNBZ0lDQWdibVYzVG05a1pTQTlJR1J2YlU1dlpHVmNiaUFnSUNCOUlHVnNjMlVnZTF4dUlDQWdJQ0FnSUNCMllYSWdjR0Z5Wlc1MFRtOWtaU0E5SUdSdmJVNXZaR1V1Y0dGeVpXNTBUbTlrWlZ4dUlDQWdJQ0FnSUNCdVpYZE9iMlJsSUQwZ2NtVnVaR1Z5VDNCMGFXOXVjeTV5Wlc1a1pYSW9kbFJsZUhRc0lISmxibVJsY2s5d2RHbHZibk1wWEc1Y2JpQWdJQ0FnSUNBZ2FXWWdLSEJoY21WdWRFNXZaR1VnSmlZZ2JtVjNUbTlrWlNBaFBUMGdaRzl0VG05a1pTa2dlMXh1SUNBZ0lDQWdJQ0FnSUNBZ2NHRnlaVzUwVG05a1pTNXlaWEJzWVdObFEyaHBiR1FvYm1WM1RtOWtaU3dnWkc5dFRtOWtaU2xjYmlBZ0lDQWdJQ0FnZlZ4dUlDQWdJSDFjYmx4dUlDQWdJSEpsZEhWeWJpQnVaWGRPYjJSbFhHNTlYRzVjYm1aMWJtTjBhVzl1SUhkcFpHZGxkRkJoZEdOb0tHUnZiVTV2WkdVc0lHeGxablJXVG05a1pTd2dkMmxrWjJWMExDQnlaVzVrWlhKUGNIUnBiMjV6S1NCN1hHNGdJQ0FnZG1GeUlIVndaR0YwYVc1bklEMGdkWEJrWVhSbFYybGtaMlYwS0d4bFpuUldUbTlrWlN3Z2QybGtaMlYwS1Z4dUlDQWdJSFpoY2lCdVpYZE9iMlJsWEc1Y2JpQWdJQ0JwWmlBb2RYQmtZWFJwYm1jcElIdGNiaUFnSUNBZ0lDQWdibVYzVG05a1pTQTlJSGRwWkdkbGRDNTFjR1JoZEdVb2JHVm1kRlpPYjJSbExDQmtiMjFPYjJSbEtTQjhmQ0JrYjIxT2IyUmxYRzRnSUNBZ2ZTQmxiSE5sSUh0Y2JpQWdJQ0FnSUNBZ2JtVjNUbTlrWlNBOUlISmxibVJsY2s5d2RHbHZibk11Y21WdVpHVnlLSGRwWkdkbGRDd2djbVZ1WkdWeVQzQjBhVzl1Y3lsY2JpQWdJQ0I5WEc1Y2JpQWdJQ0IyWVhJZ2NHRnlaVzUwVG05a1pTQTlJR1J2YlU1dlpHVXVjR0Z5Wlc1MFRtOWtaVnh1WEc0Z0lDQWdhV1lnS0hCaGNtVnVkRTV2WkdVZ0ppWWdibVYzVG05a1pTQWhQVDBnWkc5dFRtOWtaU2tnZTF4dUlDQWdJQ0FnSUNCd1lYSmxiblJPYjJSbExuSmxjR3hoWTJWRGFHbHNaQ2h1WlhkT2IyUmxMQ0JrYjIxT2IyUmxLVnh1SUNBZ0lIMWNibHh1SUNBZ0lHbG1JQ2doZFhCa1lYUnBibWNwSUh0Y2JpQWdJQ0FnSUNBZ1pHVnpkSEp2ZVZkcFpHZGxkQ2hrYjIxT2IyUmxMQ0JzWldaMFZrNXZaR1VwWEc0Z0lDQWdmVnh1WEc0Z0lDQWdjbVYwZFhKdUlHNWxkMDV2WkdWY2JuMWNibHh1Wm5WdVkzUnBiMjRnZGs1dlpHVlFZWFJqYUNoa2IyMU9iMlJsTENCc1pXWjBWazV2WkdVc0lIWk9iMlJsTENCeVpXNWtaWEpQY0hScGIyNXpLU0I3WEc0Z0lDQWdkbUZ5SUhCaGNtVnVkRTV2WkdVZ1BTQmtiMjFPYjJSbExuQmhjbVZ1ZEU1dlpHVmNiaUFnSUNCMllYSWdibVYzVG05a1pTQTlJSEpsYm1SbGNrOXdkR2x2Ym5NdWNtVnVaR1Z5S0haT2IyUmxMQ0J5Wlc1a1pYSlBjSFJwYjI1ektWeHVYRzRnSUNBZ2FXWWdLSEJoY21WdWRFNXZaR1VnSmlZZ2JtVjNUbTlrWlNBaFBUMGdaRzl0VG05a1pTa2dlMXh1SUNBZ0lDQWdJQ0J3WVhKbGJuUk9iMlJsTG5KbGNHeGhZMlZEYUdsc1pDaHVaWGRPYjJSbExDQmtiMjFPYjJSbEtWeHVJQ0FnSUgxY2JseHVJQ0FnSUhKbGRIVnliaUJ1WlhkT2IyUmxYRzU5WEc1Y2JtWjFibU4wYVc5dUlHUmxjM1J5YjNsWGFXUm5aWFFvWkc5dFRtOWtaU3dnZHlrZ2UxeHVJQ0FnSUdsbUlDaDBlWEJsYjJZZ2R5NWtaWE4wY205NUlEMDlQU0JjSW1aMWJtTjBhVzl1WENJZ0ppWWdhWE5YYVdSblpYUW9keWtwSUh0Y2JpQWdJQ0FnSUNBZ2R5NWtaWE4wY205NUtHUnZiVTV2WkdVcFhHNGdJQ0FnZlZ4dWZWeHVYRzVtZFc1amRHbHZiaUJ5Wlc5eVpHVnlRMmhwYkdSeVpXNG9aRzl0VG05a1pTd2diVzkyWlhNcElIdGNiaUFnSUNCMllYSWdZMmhwYkdST2IyUmxjeUE5SUdSdmJVNXZaR1V1WTJocGJHUk9iMlJsYzF4dUlDQWdJSFpoY2lCclpYbE5ZWEFnUFNCN2ZWeHVJQ0FnSUhaaGNpQnViMlJsWEc0Z0lDQWdkbUZ5SUhKbGJXOTJaVnh1SUNBZ0lIWmhjaUJwYm5ObGNuUmNibHh1SUNBZ0lHWnZjaUFvZG1GeUlHa2dQU0F3T3lCcElEd2diVzkyWlhNdWNtVnRiM1psY3k1c1pXNW5kR2c3SUdrckt5a2dlMXh1SUNBZ0lDQWdJQ0J5WlcxdmRtVWdQU0J0YjNabGN5NXlaVzF2ZG1WelcybGRYRzRnSUNBZ0lDQWdJRzV2WkdVZ1BTQmphR2xzWkU1dlpHVnpXM0psYlc5MlpTNW1jbTl0WFZ4dUlDQWdJQ0FnSUNCcFppQW9jbVZ0YjNabExtdGxlU2tnZTF4dUlDQWdJQ0FnSUNBZ0lDQWdhMlY1VFdGd1czSmxiVzkyWlM1clpYbGRJRDBnYm05a1pWeHVJQ0FnSUNBZ0lDQjlYRzRnSUNBZ0lDQWdJR1J2YlU1dlpHVXVjbVZ0YjNabFEyaHBiR1FvYm05a1pTbGNiaUFnSUNCOVhHNWNiaUFnSUNCMllYSWdiR1Z1WjNSb0lEMGdZMmhwYkdST2IyUmxjeTVzWlc1bmRHaGNiaUFnSUNCbWIzSWdLSFpoY2lCcUlEMGdNRHNnYWlBOElHMXZkbVZ6TG1sdWMyVnlkSE11YkdWdVozUm9PeUJxS3lzcElIdGNiaUFnSUNBZ0lDQWdhVzV6WlhKMElEMGdiVzkyWlhNdWFXNXpaWEowYzF0cVhWeHVJQ0FnSUNBZ0lDQnViMlJsSUQwZ2EyVjVUV0Z3VzJsdWMyVnlkQzVyWlhsZFhHNGdJQ0FnSUNBZ0lDOHZJSFJvYVhNZ2FYTWdkR2hsSUhkbGFYSmtaWE4wSUdKMVp5QnBKM1psSUdWMlpYSWdjMlZsYmlCcGJpQjNaV0pyYVhSY2JpQWdJQ0FnSUNBZ1pHOXRUbTlrWlM1cGJuTmxjblJDWldadmNtVW9ibTlrWlN3Z2FXNXpaWEowTG5SdklENDlJR3hsYm1kMGFDc3JJRDhnYm5Wc2JDQTZJR05vYVd4a1RtOWtaWE5iYVc1elpYSjBMblJ2WFNsY2JpQWdJQ0I5WEc1OVhHNWNibVoxYm1OMGFXOXVJSEpsY0d4aFkyVlNiMjkwS0c5c1pGSnZiM1FzSUc1bGQxSnZiM1FwSUh0Y2JpQWdJQ0JwWmlBb2IyeGtVbTl2ZENBbUppQnVaWGRTYjI5MElDWW1JRzlzWkZKdmIzUWdJVDA5SUc1bGQxSnZiM1FnSmlZZ2IyeGtVbTl2ZEM1d1lYSmxiblJPYjJSbEtTQjdYRzRnSUNBZ0lDQWdJRzlzWkZKdmIzUXVjR0Z5Wlc1MFRtOWtaUzV5WlhCc1lXTmxRMmhwYkdRb2JtVjNVbTl2ZEN3Z2IyeGtVbTl2ZENsY2JpQWdJQ0I5WEc1Y2JpQWdJQ0J5WlhSMWNtNGdibVYzVW05dmREdGNibjFjYmx4dWZTeDdYQ0l1TGk5MmJtOWtaUzlwY3kxM2FXUm5aWFF1YW5OY0lqb3lPU3hjSWk0dUwzWnViMlJsTDNad1lYUmphQzVxYzF3aU9qTXlMRndpTGk5aGNIQnNlUzF3Y205d1pYSjBhV1Z6WENJNk1UUXNYQ0l1TDNWd1pHRjBaUzEzYVdSblpYUmNJam94T1gxZExERTRPbHRtZFc1amRHbHZiaWh5WlhGMWFYSmxMRzF2WkhWc1pTeGxlSEJ2Y25SektYdGNiblpoY2lCa2IyTjFiV1Z1ZENBOUlISmxjWFZwY21Vb1hDSm5iRzlpWVd3dlpHOWpkVzFsYm5SY0lpbGNiblpoY2lCcGMwRnljbUY1SUQwZ2NtVnhkV2x5WlNoY0luZ3RhWE10WVhKeVlYbGNJaWxjYmx4dWRtRnlJSEpsYm1SbGNpQTlJSEpsY1hWcGNtVW9YQ0l1TDJOeVpXRjBaUzFsYkdWdFpXNTBYQ0lwWEc1MllYSWdaRzl0U1c1a1pYZ2dQU0J5WlhGMWFYSmxLRndpTGk5a2IyMHRhVzVrWlhoY0lpbGNiblpoY2lCd1lYUmphRTl3SUQwZ2NtVnhkV2x5WlNoY0lpNHZjR0YwWTJndGIzQmNJaWxjYm0xdlpIVnNaUzVsZUhCdmNuUnpJRDBnY0dGMFkyaGNibHh1Wm5WdVkzUnBiMjRnY0dGMFkyZ29jbTl2ZEU1dlpHVXNJSEJoZEdOb1pYTXNJSEpsYm1SbGNrOXdkR2x2Ym5NcElIdGNiaUFnSUNCeVpXNWtaWEpQY0hScGIyNXpJRDBnY21WdVpHVnlUM0IwYVc5dWN5QjhmQ0I3ZlZ4dUlDQWdJSEpsYm1SbGNrOXdkR2x2Ym5NdWNHRjBZMmdnUFNCeVpXNWtaWEpQY0hScGIyNXpMbkJoZEdOb0lDWW1JSEpsYm1SbGNrOXdkR2x2Ym5NdWNHRjBZMmdnSVQwOUlIQmhkR05vWEc0Z0lDQWdJQ0FnSUQ4Z2NtVnVaR1Z5VDNCMGFXOXVjeTV3WVhSamFGeHVJQ0FnSUNBZ0lDQTZJSEJoZEdOb1VtVmpkWEp6YVhabFhHNGdJQ0FnY21WdVpHVnlUM0IwYVc5dWN5NXlaVzVrWlhJZ1BTQnlaVzVrWlhKUGNIUnBiMjV6TG5KbGJtUmxjaUI4ZkNCeVpXNWtaWEpjYmx4dUlDQWdJSEpsZEhWeWJpQnlaVzVrWlhKUGNIUnBiMjV6TG5CaGRHTm9LSEp2YjNST2IyUmxMQ0J3WVhSamFHVnpMQ0J5Wlc1a1pYSlBjSFJwYjI1ektWeHVmVnh1WEc1bWRXNWpkR2x2YmlCd1lYUmphRkpsWTNWeWMybDJaU2h5YjI5MFRtOWtaU3dnY0dGMFkyaGxjeXdnY21WdVpHVnlUM0IwYVc5dWN5a2dlMXh1SUNBZ0lIWmhjaUJwYm1ScFkyVnpJRDBnY0dGMFkyaEpibVJwWTJWektIQmhkR05vWlhNcFhHNWNiaUFnSUNCcFppQW9hVzVrYVdObGN5NXNaVzVuZEdnZ1BUMDlJREFwSUh0Y2JpQWdJQ0FnSUNBZ2NtVjBkWEp1SUhKdmIzUk9iMlJsWEc0Z0lDQWdmVnh1WEc0Z0lDQWdkbUZ5SUdsdVpHVjRJRDBnWkc5dFNXNWtaWGdvY205dmRFNXZaR1VzSUhCaGRHTm9aWE11WVN3Z2FXNWthV05sY3lsY2JpQWdJQ0IyWVhJZ2IzZHVaWEpFYjJOMWJXVnVkQ0E5SUhKdmIzUk9iMlJsTG05M2JtVnlSRzlqZFcxbGJuUmNibHh1SUNBZ0lHbG1JQ2doY21WdVpHVnlUM0IwYVc5dWN5NWtiMk4xYldWdWRDQW1KaUJ2ZDI1bGNrUnZZM1Z0Wlc1MElDRTlQU0JrYjJOMWJXVnVkQ2tnZTF4dUlDQWdJQ0FnSUNCeVpXNWtaWEpQY0hScGIyNXpMbVJ2WTNWdFpXNTBJRDBnYjNkdVpYSkViMk4xYldWdWRGeHVJQ0FnSUgxY2JseHVJQ0FnSUdadmNpQW9kbUZ5SUdrZ1BTQXdPeUJwSUR3Z2FXNWthV05sY3k1c1pXNW5kR2c3SUdrckt5a2dlMXh1SUNBZ0lDQWdJQ0IyWVhJZ2JtOWtaVWx1WkdWNElEMGdhVzVrYVdObGMxdHBYVnh1SUNBZ0lDQWdJQ0J5YjI5MFRtOWtaU0E5SUdGd2NHeDVVR0YwWTJnb2NtOXZkRTV2WkdVc1hHNGdJQ0FnSUNBZ0lDQWdJQ0JwYm1SbGVGdHViMlJsU1c1a1pYaGRMRnh1SUNBZ0lDQWdJQ0FnSUNBZ2NHRjBZMmhsYzF0dWIyUmxTVzVrWlhoZExGeHVJQ0FnSUNBZ0lDQWdJQ0FnY21WdVpHVnlUM0IwYVc5dWN5bGNiaUFnSUNCOVhHNWNiaUFnSUNCeVpYUjFjbTRnY205dmRFNXZaR1ZjYm4xY2JseHVablZ1WTNScGIyNGdZWEJ3YkhsUVlYUmphQ2h5YjI5MFRtOWtaU3dnWkc5dFRtOWtaU3dnY0dGMFkyaE1hWE4wTENCeVpXNWtaWEpQY0hScGIyNXpLU0I3WEc0Z0lDQWdhV1lnS0NGa2IyMU9iMlJsS1NCN1hHNGdJQ0FnSUNBZ0lISmxkSFZ5YmlCeWIyOTBUbTlrWlZ4dUlDQWdJSDFjYmx4dUlDQWdJSFpoY2lCdVpYZE9iMlJsWEc1Y2JpQWdJQ0JwWmlBb2FYTkJjbkpoZVNod1lYUmphRXhwYzNRcEtTQjdYRzRnSUNBZ0lDQWdJR1p2Y2lBb2RtRnlJR2tnUFNBd095QnBJRHdnY0dGMFkyaE1hWE4wTG14bGJtZDBhRHNnYVNzcktTQjdYRzRnSUNBZ0lDQWdJQ0FnSUNCdVpYZE9iMlJsSUQwZ2NHRjBZMmhQY0Nod1lYUmphRXhwYzNSYmFWMHNJR1J2YlU1dlpHVXNJSEpsYm1SbGNrOXdkR2x2Ym5NcFhHNWNiaUFnSUNBZ0lDQWdJQ0FnSUdsbUlDaGtiMjFPYjJSbElEMDlQU0J5YjI5MFRtOWtaU2tnZTF4dUlDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUhKdmIzUk9iMlJsSUQwZ2JtVjNUbTlrWlZ4dUlDQWdJQ0FnSUNBZ0lDQWdmVnh1SUNBZ0lDQWdJQ0I5WEc0Z0lDQWdmU0JsYkhObElIdGNiaUFnSUNBZ0lDQWdibVYzVG05a1pTQTlJSEJoZEdOb1QzQW9jR0YwWTJoTWFYTjBMQ0JrYjIxT2IyUmxMQ0J5Wlc1a1pYSlBjSFJwYjI1ektWeHVYRzRnSUNBZ0lDQWdJR2xtSUNoa2IyMU9iMlJsSUQwOVBTQnliMjkwVG05a1pTa2dlMXh1SUNBZ0lDQWdJQ0FnSUNBZ2NtOXZkRTV2WkdVZ1BTQnVaWGRPYjJSbFhHNGdJQ0FnSUNBZ0lIMWNiaUFnSUNCOVhHNWNiaUFnSUNCeVpYUjFjbTRnY205dmRFNXZaR1ZjYm4xY2JseHVablZ1WTNScGIyNGdjR0YwWTJoSmJtUnBZMlZ6S0hCaGRHTm9aWE1wSUh0Y2JpQWdJQ0IyWVhJZ2FXNWthV05sY3lBOUlGdGRYRzVjYmlBZ0lDQm1iM0lnS0haaGNpQnJaWGtnYVc0Z2NHRjBZMmhsY3lrZ2UxeHVJQ0FnSUNBZ0lDQnBaaUFvYTJWNUlDRTlQU0JjSW1GY0lpa2dlMXh1SUNBZ0lDQWdJQ0FnSUNBZ2FXNWthV05sY3k1d2RYTm9LRTUxYldKbGNpaHJaWGtwS1Z4dUlDQWdJQ0FnSUNCOVhHNGdJQ0FnZlZ4dVhHNGdJQ0FnY21WMGRYSnVJR2x1WkdsalpYTmNibjFjYmx4dWZTeDdYQ0l1TDJOeVpXRjBaUzFsYkdWdFpXNTBYQ0k2TVRVc1hDSXVMMlJ2YlMxcGJtUmxlRndpT2pFMkxGd2lMaTl3WVhSamFDMXZjRndpT2pFM0xGd2laMnh2WW1Gc0wyUnZZM1Z0Wlc1MFhDSTZNVEFzWENKNExXbHpMV0Z5Y21GNVhDSTZNVEo5WFN3eE9UcGJablZ1WTNScGIyNG9jbVZ4ZFdseVpTeHRiMlIxYkdVc1pYaHdiM0owY3lsN1hHNTJZWElnYVhOWGFXUm5aWFFnUFNCeVpYRjFhWEpsS0Z3aUxpNHZkbTV2WkdVdmFYTXRkMmxrWjJWMExtcHpYQ0lwWEc1Y2JtMXZaSFZzWlM1bGVIQnZjblJ6SUQwZ2RYQmtZWFJsVjJsa1oyVjBYRzVjYm1aMWJtTjBhVzl1SUhWd1pHRjBaVmRwWkdkbGRDaGhMQ0JpS1NCN1hHNGdJQ0FnYVdZZ0tHbHpWMmxrWjJWMEtHRXBJQ1ltSUdselYybGtaMlYwS0dJcEtTQjdYRzRnSUNBZ0lDQWdJR2xtSUNoY0ltNWhiV1ZjSWlCcGJpQmhJQ1ltSUZ3aWJtRnRaVndpSUdsdUlHSXBJSHRjYmlBZ0lDQWdJQ0FnSUNBZ0lISmxkSFZ5YmlCaExtbGtJRDA5UFNCaUxtbGtYRzRnSUNBZ0lDQWdJSDBnWld4elpTQjdYRzRnSUNBZ0lDQWdJQ0FnSUNCeVpYUjFjbTRnWVM1cGJtbDBJRDA5UFNCaUxtbHVhWFJjYmlBZ0lDQWdJQ0FnZlZ4dUlDQWdJSDFjYmx4dUlDQWdJSEpsZEhWeWJpQm1ZV3h6WlZ4dWZWeHVYRzU5TEh0Y0lpNHVMM1p1YjJSbEwybHpMWGRwWkdkbGRDNXFjMXdpT2pJNWZWMHNNakE2VzJaMWJtTjBhVzl1S0hKbGNYVnBjbVVzYlc5a2RXeGxMR1Y0Y0c5eWRITXBlMXh1SjNWelpTQnpkSEpwWTNRbk8xeHVYRzUyWVhJZ1JYWlRkRzl5WlNBOUlISmxjWFZwY21Vb0oyVjJMWE4wYjNKbEp5azdYRzVjYm0xdlpIVnNaUzVsZUhCdmNuUnpJRDBnUlhaSWIyOXJPMXh1WEc1bWRXNWpkR2x2YmlCRmRraHZiMnNvZG1Gc2RXVXBJSHRjYmlBZ0lDQnBaaUFvSVNoMGFHbHpJR2x1YzNSaGJtTmxiMllnUlhaSWIyOXJLU2tnZTF4dUlDQWdJQ0FnSUNCeVpYUjFjbTRnYm1WM0lFVjJTRzl2YXloMllXeDFaU2s3WEc0Z0lDQWdmVnh1WEc0Z0lDQWdkR2hwY3k1MllXeDFaU0E5SUhaaGJIVmxPMXh1ZlZ4dVhHNUZka2h2YjJzdWNISnZkRzkwZVhCbExtaHZiMnNnUFNCbWRXNWpkR2x2YmlBb2JtOWtaU3dnY0hKdmNHVnlkSGxPWVcxbEtTQjdYRzRnSUNBZ2RtRnlJR1Z6SUQwZ1JYWlRkRzl5WlNodWIyUmxLVHRjYmlBZ0lDQjJZWElnY0hKdmNFNWhiV1VnUFNCd2NtOXdaWEowZVU1aGJXVXVjM1ZpYzNSeUtETXBPMXh1WEc0Z0lDQWdaWE5iY0hKdmNFNWhiV1ZkSUQwZ2RHaHBjeTUyWVd4MVpUdGNibjA3WEc1Y2JrVjJTRzl2YXk1d2NtOTBiM1I1Y0dVdWRXNW9iMjlySUQwZ1puVnVZM1JwYjI0b2JtOWtaU3dnY0hKdmNHVnlkSGxPWVcxbEtTQjdYRzRnSUNBZ2RtRnlJR1Z6SUQwZ1JYWlRkRzl5WlNodWIyUmxLVHRjYmlBZ0lDQjJZWElnY0hKdmNFNWhiV1VnUFNCd2NtOXdaWEowZVU1aGJXVXVjM1ZpYzNSeUtETXBPMXh1WEc0Z0lDQWdaWE5iY0hKdmNFNWhiV1ZkSUQwZ2RXNWtaV1pwYm1Wa08xeHVmVHRjYmx4dWZTeDdYQ0psZGkxemRHOXlaVndpT2pkOVhTd3lNVHBiWm5WdVkzUnBiMjRvY21WeGRXbHlaU3h0YjJSMWJHVXNaWGh3YjNKMGN5bDdYRzRuZFhObElITjBjbWxqZENjN1hHNWNibTF2WkhWc1pTNWxlSEJ2Y25SeklEMGdVMjltZEZObGRFaHZiMnM3WEc1Y2JtWjFibU4wYVc5dUlGTnZablJUWlhSSWIyOXJLSFpoYkhWbEtTQjdYRzRnSUNBZ2FXWWdLQ0VvZEdocGN5QnBibk4wWVc1alpXOW1JRk52Wm5SVFpYUkliMjlyS1NrZ2UxeHVJQ0FnSUNBZ0lDQnlaWFIxY200Z2JtVjNJRk52Wm5SVFpYUkliMjlyS0haaGJIVmxLVHRjYmlBZ0lDQjlYRzVjYmlBZ0lDQjBhR2x6TG5aaGJIVmxJRDBnZG1Gc2RXVTdYRzU5WEc1Y2JsTnZablJUWlhSSWIyOXJMbkJ5YjNSdmRIbHdaUzVvYjI5cklEMGdablZ1WTNScGIyNGdLRzV2WkdVc0lIQnliM0JsY25SNVRtRnRaU2tnZTF4dUlDQWdJR2xtSUNodWIyUmxXM0J5YjNCbGNuUjVUbUZ0WlYwZ0lUMDlJSFJvYVhNdWRtRnNkV1VwSUh0Y2JpQWdJQ0FnSUNBZ2JtOWtaVnR3Y205d1pYSjBlVTVoYldWZElEMGdkR2hwY3k1MllXeDFaVHRjYmlBZ0lDQjlYRzU5TzF4dVhHNTlMSHQ5WFN3eU1qcGJablZ1WTNScGIyNG9jbVZ4ZFdseVpTeHRiMlIxYkdVc1pYaHdiM0owY3lsN1hHNG5kWE5sSUhOMGNtbGpkQ2M3WEc1Y2JuWmhjaUJwYzBGeWNtRjVJRDBnY21WeGRXbHlaU2duZUMxcGN5MWhjbkpoZVNjcE8xeHVYRzUyWVhJZ1ZrNXZaR1VnUFNCeVpYRjFhWEpsS0NjdUxpOTJibTlrWlM5MmJtOWtaUzVxY3ljcE8xeHVkbUZ5SUZaVVpYaDBJRDBnY21WeGRXbHlaU2duTGk0dmRtNXZaR1V2ZG5SbGVIUXVhbk1uS1R0Y2JuWmhjaUJwYzFaT2IyUmxJRDBnY21WeGRXbHlaU2duTGk0dmRtNXZaR1V2YVhNdGRtNXZaR1VuS1R0Y2JuWmhjaUJwYzFaVVpYaDBJRDBnY21WeGRXbHlaU2duTGk0dmRtNXZaR1V2YVhNdGRuUmxlSFFuS1R0Y2JuWmhjaUJwYzFkcFpHZGxkQ0E5SUhKbGNYVnBjbVVvSnk0dUwzWnViMlJsTDJsekxYZHBaR2RsZENjcE8xeHVkbUZ5SUdselNHOXZheUE5SUhKbGNYVnBjbVVvSnk0dUwzWnViMlJsTDJsekxYWm9iMjlySnlrN1hHNTJZWElnYVhOV1ZHaDFibXNnUFNCeVpYRjFhWEpsS0NjdUxpOTJibTlrWlM5cGN5MTBhSFZ1YXljcE8xeHVYRzUyWVhJZ2NHRnljMlZVWVdjZ1BTQnlaWEYxYVhKbEtDY3VMM0JoY25ObExYUmhaeTVxY3ljcE8xeHVkbUZ5SUhOdlpuUlRaWFJJYjI5cklEMGdjbVZ4ZFdseVpTZ25MaTlvYjI5cmN5OXpiMlowTFhObGRDMW9iMjlyTG1wekp5azdYRzUyWVhJZ1pYWkliMjlySUQwZ2NtVnhkV2x5WlNnbkxpOW9iMjlyY3k5bGRpMW9iMjlyTG1wekp5azdYRzVjYm0xdlpIVnNaUzVsZUhCdmNuUnpJRDBnYUR0Y2JseHVablZ1WTNScGIyNGdhQ2gwWVdkT1lXMWxMQ0J3Y205d1pYSjBhV1Z6TENCamFHbHNaSEpsYmlrZ2UxeHVJQ0FnSUhaaGNpQmphR2xzWkU1dlpHVnpJRDBnVzEwN1hHNGdJQ0FnZG1GeUlIUmhaeXdnY0hKdmNITXNJR3RsZVN3Z2JtRnRaWE53WVdObE8xeHVYRzRnSUNBZ2FXWWdLQ0ZqYUdsc1pISmxiaUFtSmlCcGMwTm9hV3hrY21WdUtIQnliM0JsY25ScFpYTXBLU0I3WEc0Z0lDQWdJQ0FnSUdOb2FXeGtjbVZ1SUQwZ2NISnZjR1Z5ZEdsbGN6dGNiaUFnSUNBZ0lDQWdjSEp2Y0hNZ1BTQjdmVHRjYmlBZ0lDQjlYRzVjYmlBZ0lDQndjbTl3Y3lBOUlIQnliM0J6SUh4OElIQnliM0JsY25ScFpYTWdmSHdnZTMwN1hHNGdJQ0FnZEdGbklEMGdjR0Z5YzJWVVlXY29kR0ZuVG1GdFpTd2djSEp2Y0hNcE8xeHVYRzRnSUNBZ0x5OGdjM1Z3Y0c5eWRDQnJaWGx6WEc0Z0lDQWdhV1lnS0hCeWIzQnpMbWhoYzA5M2JsQnliM0JsY25SNUtDZHJaWGtuS1NrZ2UxeHVJQ0FnSUNBZ0lDQnJaWGtnUFNCd2NtOXdjeTVyWlhrN1hHNGdJQ0FnSUNBZ0lIQnliM0J6TG10bGVTQTlJSFZ1WkdWbWFXNWxaRHRjYmlBZ0lDQjlYRzVjYmlBZ0lDQXZMeUJ6ZFhCd2IzSjBJRzVoYldWemNHRmpaVnh1SUNBZ0lHbG1JQ2h3Y205d2N5NW9ZWE5QZDI1UWNtOXdaWEowZVNnbmJtRnRaWE53WVdObEp5a3BJSHRjYmlBZ0lDQWdJQ0FnYm1GdFpYTndZV05sSUQwZ2NISnZjSE11Ym1GdFpYTndZV05sTzF4dUlDQWdJQ0FnSUNCd2NtOXdjeTV1WVcxbGMzQmhZMlVnUFNCMWJtUmxabWx1WldRN1hHNGdJQ0FnZlZ4dVhHNGdJQ0FnTHk4Z1ptbDRJR04xY25OdmNpQmlkV2RjYmlBZ0lDQnBaaUFvZEdGbklEMDlQU0FuU1U1UVZWUW5JQ1ltWEc0Z0lDQWdJQ0FnSUNGdVlXMWxjM0JoWTJVZ0ppWmNiaUFnSUNBZ0lDQWdjSEp2Y0hNdWFHRnpUM2R1VUhKdmNHVnlkSGtvSjNaaGJIVmxKeWtnSmlaY2JpQWdJQ0FnSUNBZ2NISnZjSE11ZG1Gc2RXVWdJVDA5SUhWdVpHVm1hVzVsWkNBbUpseHVJQ0FnSUNBZ0lDQWhhWE5JYjI5cktIQnliM0J6TG5aaGJIVmxLVnh1SUNBZ0lDa2dlMXh1SUNBZ0lDQWdJQ0J3Y205d2N5NTJZV3gxWlNBOUlITnZablJUWlhSSWIyOXJLSEJ5YjNCekxuWmhiSFZsS1R0Y2JpQWdJQ0I5WEc1Y2JpQWdJQ0IwY21GdWMyWnZjbTFRY205d1pYSjBhV1Z6S0hCeWIzQnpLVHRjYmx4dUlDQWdJR2xtSUNoamFHbHNaSEpsYmlBaFBUMGdkVzVrWldacGJtVmtJQ1ltSUdOb2FXeGtjbVZ1SUNFOVBTQnVkV3hzS1NCN1hHNGdJQ0FnSUNBZ0lHRmtaRU5vYVd4a0tHTm9hV3hrY21WdUxDQmphR2xzWkU1dlpHVnpMQ0IwWVdjc0lIQnliM0J6S1R0Y2JpQWdJQ0I5WEc1Y2JseHVJQ0FnSUhKbGRIVnliaUJ1WlhjZ1ZrNXZaR1VvZEdGbkxDQndjbTl3Y3l3Z1kyaHBiR1JPYjJSbGN5d2dhMlY1TENCdVlXMWxjM0JoWTJVcE8xeHVmVnh1WEc1bWRXNWpkR2x2YmlCaFpHUkRhR2xzWkNoakxDQmphR2xzWkU1dlpHVnpMQ0IwWVdjc0lIQnliM0J6S1NCN1hHNGdJQ0FnYVdZZ0tIUjVjR1Z2WmlCaklEMDlQU0FuYzNSeWFXNW5KeWtnZTF4dUlDQWdJQ0FnSUNCamFHbHNaRTV2WkdWekxuQjFjMmdvYm1WM0lGWlVaWGgwS0dNcEtUdGNiaUFnSUNCOUlHVnNjMlVnYVdZZ0tIUjVjR1Z2WmlCaklEMDlQU0FuYm5WdFltVnlKeWtnZTF4dUlDQWdJQ0FnSUNCamFHbHNaRTV2WkdWekxuQjFjMmdvYm1WM0lGWlVaWGgwS0ZOMGNtbHVaeWhqS1NrcE8xeHVJQ0FnSUgwZ1pXeHpaU0JwWmlBb2FYTkRhR2xzWkNoaktTa2dlMXh1SUNBZ0lDQWdJQ0JqYUdsc1pFNXZaR1Z6TG5CMWMyZ29ZeWs3WEc0Z0lDQWdmU0JsYkhObElHbG1JQ2hwYzBGeWNtRjVLR01wS1NCN1hHNGdJQ0FnSUNBZ0lHWnZjaUFvZG1GeUlHa2dQU0F3T3lCcElEd2dZeTVzWlc1bmRHZzdJR2tyS3lrZ2UxeHVJQ0FnSUNBZ0lDQWdJQ0FnWVdSa1EyaHBiR1FvWTF0cFhTd2dZMmhwYkdST2IyUmxjeXdnZEdGbkxDQndjbTl3Y3lrN1hHNGdJQ0FnSUNBZ0lIMWNiaUFnSUNCOUlHVnNjMlVnYVdZZ0tHTWdQVDA5SUc1MWJHd2dmSHdnWXlBOVBUMGdkVzVrWldacGJtVmtLU0I3WEc0Z0lDQWdJQ0FnSUhKbGRIVnlianRjYmlBZ0lDQjlJR1ZzYzJVZ2UxeHVJQ0FnSUNBZ0lDQjBhSEp2ZHlCVmJtVjRjR1ZqZEdWa1ZtbHlkSFZoYkVWc1pXMWxiblFvZTF4dUlDQWdJQ0FnSUNBZ0lDQWdabTl5WldsbmJrOWlhbVZqZERvZ1l5eGNiaUFnSUNBZ0lDQWdJQ0FnSUhCaGNtVnVkRlp1YjJSbE9pQjdYRzRnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdkR0ZuVG1GdFpUb2dkR0ZuTEZ4dUlDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUhCeWIzQmxjblJwWlhNNklIQnliM0J6WEc0Z0lDQWdJQ0FnSUNBZ0lDQjlYRzRnSUNBZ0lDQWdJSDBwTzF4dUlDQWdJSDFjYm4xY2JseHVablZ1WTNScGIyNGdkSEpoYm5ObWIzSnRVSEp2Y0dWeWRHbGxjeWh3Y205d2N5a2dlMXh1SUNBZ0lHWnZjaUFvZG1GeUlIQnliM0JPWVcxbElHbHVJSEJ5YjNCektTQjdYRzRnSUNBZ0lDQWdJR2xtSUNod2NtOXdjeTVvWVhOUGQyNVFjbTl3WlhKMGVTaHdjbTl3VG1GdFpTa3BJSHRjYmlBZ0lDQWdJQ0FnSUNBZ0lIWmhjaUIyWVd4MVpTQTlJSEJ5YjNCelczQnliM0JPWVcxbFhUdGNibHh1SUNBZ0lDQWdJQ0FnSUNBZ2FXWWdLR2x6U0c5dmF5aDJZV3gxWlNrcElIdGNiaUFnSUNBZ0lDQWdJQ0FnSUNBZ0lDQmpiMjUwYVc1MVpUdGNiaUFnSUNBZ0lDQWdJQ0FnSUgxY2JseHVJQ0FnSUNBZ0lDQWdJQ0FnYVdZZ0tIQnliM0JPWVcxbExuTjFZbk4wY2lnd0xDQXpLU0E5UFQwZ0oyVjJMU2NwSUh0Y2JpQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBdkx5QmhaR1FnWlhZdFptOXZJSE4xY0hCdmNuUmNiaUFnSUNBZ0lDQWdJQ0FnSUNBZ0lDQndjbTl3YzF0d2NtOXdUbUZ0WlYwZ1BTQmxka2h2YjJzb2RtRnNkV1VwTzF4dUlDQWdJQ0FnSUNBZ0lDQWdmVnh1SUNBZ0lDQWdJQ0I5WEc0Z0lDQWdmVnh1ZlZ4dVhHNW1kVzVqZEdsdmJpQnBjME5vYVd4a0tIZ3BJSHRjYmlBZ0lDQnlaWFIxY200Z2FYTldUbTlrWlNoNEtTQjhmQ0JwYzFaVVpYaDBLSGdwSUh4OElHbHpWMmxrWjJWMEtIZ3BJSHg4SUdselZsUm9kVzVyS0hncE8xeHVmVnh1WEc1bWRXNWpkR2x2YmlCcGMwTm9hV3hrY21WdUtIZ3BJSHRjYmlBZ0lDQnlaWFIxY200Z2RIbHdaVzltSUhnZ1BUMDlJQ2R6ZEhKcGJtY25JSHg4SUdselFYSnlZWGtvZUNrZ2ZId2dhWE5EYUdsc1pDaDRLVHRjYm4xY2JseHVablZ1WTNScGIyNGdWVzVsZUhCbFkzUmxaRlpwY25SMVlXeEZiR1Z0Wlc1MEtHUmhkR0VwSUh0Y2JpQWdJQ0IyWVhJZ1pYSnlJRDBnYm1WM0lFVnljbTl5S0NrN1hHNWNiaUFnSUNCbGNuSXVkSGx3WlNBOUlDZDJhWEowZFdGc0xXaDVjR1Z5YzJOeWFYQjBMblZ1Wlhod1pXTjBaV1F1ZG1seWRIVmhiQzFsYkdWdFpXNTBKenRjYmlBZ0lDQmxjbkl1YldWemMyRm5aU0E5SUNkVmJtVjRjR1ZqZEdWa0lIWnBjblIxWVd3Z1kyaHBiR1FnY0dGemMyVmtJSFJ2SUdnb0tTNWNYRzRuSUN0Y2JpQWdJQ0FnSUNBZ0owVjRjR1ZqZEdWa0lHRWdWazV2WkdVZ0x5QldkR2gxYm1zZ0x5QldWMmxrWjJWMElDOGdjM1J5YVc1bklHSjFkRHBjWEc0bklDdGNiaUFnSUNBZ0lDQWdKMmR2ZERwY1hHNG5JQ3RjYmlBZ0lDQWdJQ0FnWlhKeWIzSlRkSEpwYm1jb1pHRjBZUzVtYjNKbGFXZHVUMkpxWldOMEtTQXJYRzRnSUNBZ0lDQWdJQ2N1WEZ4dUp5QXJYRzRnSUNBZ0lDQWdJQ2RVYUdVZ2NHRnlaVzUwSUhadWIyUmxJR2x6T2x4Y2JpY2dLMXh1SUNBZ0lDQWdJQ0JsY25KdmNsTjBjbWx1Wnloa1lYUmhMbkJoY21WdWRGWnViMlJsS1Z4dUlDQWdJQ0FnSUNBblhGeHVKeUFyWEc0Z0lDQWdJQ0FnSUNkVGRXZG5aWE4wWldRZ1ptbDRPaUJqYUdGdVoyVWdlVzkxY2lCZ2FDZ3VMaTRzSUZzZ0xpNHVJRjBwWUNCallXeHNjMmwwWlM0bk8xeHVJQ0FnSUdWeWNpNW1iM0psYVdkdVQySnFaV04wSUQwZ1pHRjBZUzVtYjNKbGFXZHVUMkpxWldOME8xeHVJQ0FnSUdWeWNpNXdZWEpsYm5SV2JtOWtaU0E5SUdSaGRHRXVjR0Z5Wlc1MFZtNXZaR1U3WEc1Y2JpQWdJQ0J5WlhSMWNtNGdaWEp5TzF4dWZWeHVYRzVtZFc1amRHbHZiaUJsY25KdmNsTjBjbWx1Wnlodlltb3BJSHRjYmlBZ0lDQjBjbmtnZTF4dUlDQWdJQ0FnSUNCeVpYUjFjbTRnU2xOUFRpNXpkSEpwYm1kcFpua29iMkpxTENCdWRXeHNMQ0FuSUNBZ0lDY3BPMXh1SUNBZ0lIMGdZMkYwWTJnZ0tHVXBJSHRjYmlBZ0lDQWdJQ0FnY21WMGRYSnVJRk4wY21sdVp5aHZZbW9wTzF4dUlDQWdJSDFjYm4xY2JseHVmU3g3WENJdUxpOTJibTlrWlM5cGN5MTBhSFZ1YTF3aU9qSTFMRndpTGk0dmRtNXZaR1V2YVhNdGRtaHZiMnRjSWpveU5peGNJaTR1TDNadWIyUmxMMmx6TFhadWIyUmxYQ0k2TWpjc1hDSXVMaTkyYm05a1pTOXBjeTEyZEdWNGRGd2lPakk0TEZ3aUxpNHZkbTV2WkdVdmFYTXRkMmxrWjJWMFhDSTZNamtzWENJdUxpOTJibTlrWlM5MmJtOWtaUzVxYzF3aU9qTXhMRndpTGk0dmRtNXZaR1V2ZG5SbGVIUXVhbk5jSWpvek15eGNJaTR2YUc5dmEzTXZaWFl0YUc5dmF5NXFjMXdpT2pJd0xGd2lMaTlvYjI5cmN5OXpiMlowTFhObGRDMW9iMjlyTG1welhDSTZNakVzWENJdUwzQmhjbk5sTFhSaFp5NXFjMXdpT2pJekxGd2llQzFwY3kxaGNuSmhlVndpT2pFeWZWMHNNak02VzJaMWJtTjBhVzl1S0hKbGNYVnBjbVVzYlc5a2RXeGxMR1Y0Y0c5eWRITXBlMXh1SjNWelpTQnpkSEpwWTNRbk8xeHVYRzUyWVhJZ2MzQnNhWFFnUFNCeVpYRjFhWEpsS0NkaWNtOTNjMlZ5TFhOd2JHbDBKeWs3WEc1Y2JuWmhjaUJqYkdGemMwbGtVM0JzYVhRZ1BTQXZLRnRjWEM0alhUOWJZUzE2UVMxYU1DMDVYRngxTURBM1JpMWNYSFZHUmtaR1h6b3RYU3NwTHp0Y2JuWmhjaUJ1YjNSRGJHRnpjMGxrSUQwZ0wxNWNYQzU4SXk4N1hHNWNibTF2WkhWc1pTNWxlSEJ2Y25SeklEMGdjR0Z5YzJWVVlXYzdYRzVjYm1aMWJtTjBhVzl1SUhCaGNuTmxWR0ZuS0hSaFp5d2djSEp2Y0hNcElIdGNiaUFnSUNCcFppQW9JWFJoWnlrZ2UxeHVJQ0FnSUNBZ0lDQnlaWFIxY200Z0owUkpWaWM3WEc0Z0lDQWdmVnh1WEc0Z0lDQWdkbUZ5SUc1dlNXUWdQU0FoS0hCeWIzQnpMbWhoYzA5M2JsQnliM0JsY25SNUtDZHBaQ2NwS1R0Y2JseHVJQ0FnSUhaaGNpQjBZV2RRWVhKMGN5QTlJSE53YkdsMEtIUmhaeXdnWTJ4aGMzTkpaRk53YkdsMEtUdGNiaUFnSUNCMllYSWdkR0ZuVG1GdFpTQTlJRzUxYkd3N1hHNWNiaUFnSUNCcFppQW9ibTkwUTJ4aGMzTkpaQzUwWlhOMEtIUmhaMUJoY25Seld6RmRLU2tnZTF4dUlDQWdJQ0FnSUNCMFlXZE9ZVzFsSUQwZ0owUkpWaWM3WEc0Z0lDQWdmVnh1WEc0Z0lDQWdkbUZ5SUdOc1lYTnpaWE1zSUhCaGNuUXNJSFI1Y0dVc0lHazdYRzVjYmlBZ0lDQm1iM0lnS0drZ1BTQXdPeUJwSUR3Z2RHRm5VR0Z5ZEhNdWJHVnVaM1JvT3lCcEt5c3BJSHRjYmlBZ0lDQWdJQ0FnY0dGeWRDQTlJSFJoWjFCaGNuUnpXMmxkTzF4dVhHNGdJQ0FnSUNBZ0lHbG1JQ2doY0dGeWRDa2dlMXh1SUNBZ0lDQWdJQ0FnSUNBZ1kyOXVkR2x1ZFdVN1hHNGdJQ0FnSUNBZ0lIMWNibHh1SUNBZ0lDQWdJQ0IwZVhCbElEMGdjR0Z5ZEM1amFHRnlRWFFvTUNrN1hHNWNiaUFnSUNBZ0lDQWdhV1lnS0NGMFlXZE9ZVzFsS1NCN1hHNGdJQ0FnSUNBZ0lDQWdJQ0IwWVdkT1lXMWxJRDBnY0dGeWREdGNiaUFnSUNBZ0lDQWdmU0JsYkhObElHbG1JQ2gwZVhCbElEMDlQU0FuTGljcElIdGNiaUFnSUNBZ0lDQWdJQ0FnSUdOc1lYTnpaWE1nUFNCamJHRnpjMlZ6SUh4OElGdGRPMXh1SUNBZ0lDQWdJQ0FnSUNBZ1kyeGhjM05sY3k1d2RYTm9LSEJoY25RdWMzVmljM1J5YVc1bktERXNJSEJoY25RdWJHVnVaM1JvS1NrN1hHNGdJQ0FnSUNBZ0lIMGdaV3h6WlNCcFppQW9kSGx3WlNBOVBUMGdKeU1uSUNZbUlHNXZTV1FwSUh0Y2JpQWdJQ0FnSUNBZ0lDQWdJSEJ5YjNCekxtbGtJRDBnY0dGeWRDNXpkV0p6ZEhKcGJtY29NU3dnY0dGeWRDNXNaVzVuZEdncE8xeHVJQ0FnSUNBZ0lDQjlYRzRnSUNBZ2ZWeHVYRzRnSUNBZ2FXWWdLR05zWVhOelpYTXBJSHRjYmlBZ0lDQWdJQ0FnYVdZZ0tIQnliM0J6TG1Oc1lYTnpUbUZ0WlNrZ2UxeHVJQ0FnSUNBZ0lDQWdJQ0FnWTJ4aGMzTmxjeTV3ZFhOb0tIQnliM0J6TG1Oc1lYTnpUbUZ0WlNrN1hHNGdJQ0FnSUNBZ0lIMWNibHh1SUNBZ0lDQWdJQ0J3Y205d2N5NWpiR0Z6YzA1aGJXVWdQU0JqYkdGemMyVnpMbXB2YVc0b0p5QW5LVHRjYmlBZ0lDQjlYRzVjYmlBZ0lDQnlaWFIxY200Z2NISnZjSE11Ym1GdFpYTndZV05sSUQ4Z2RHRm5UbUZ0WlNBNklIUmhaMDVoYldVdWRHOVZjSEJsY2tOaGMyVW9LVHRjYm4xY2JseHVmU3g3WENKaWNtOTNjMlZ5TFhOd2JHbDBYQ0k2TlgxZExESTBPbHRtZFc1amRHbHZiaWh5WlhGMWFYSmxMRzF2WkhWc1pTeGxlSEJ2Y25SektYdGNiblpoY2lCcGMxWk9iMlJsSUQwZ2NtVnhkV2x5WlNoY0lpNHZhWE10ZG01dlpHVmNJaWxjYm5aaGNpQnBjMVpVWlhoMElEMGdjbVZ4ZFdseVpTaGNJaTR2YVhNdGRuUmxlSFJjSWlsY2JuWmhjaUJwYzFkcFpHZGxkQ0E5SUhKbGNYVnBjbVVvWENJdUwybHpMWGRwWkdkbGRGd2lLVnh1ZG1GeUlHbHpWR2gxYm1zZ1BTQnlaWEYxYVhKbEtGd2lMaTlwY3kxMGFIVnVhMXdpS1Z4dVhHNXRiMlIxYkdVdVpYaHdiM0owY3lBOUlHaGhibVJzWlZSb2RXNXJYRzVjYm1aMWJtTjBhVzl1SUdoaGJtUnNaVlJvZFc1cktHRXNJR0lwSUh0Y2JpQWdJQ0IyWVhJZ2NtVnVaR1Z5WldSQklEMGdZVnh1SUNBZ0lIWmhjaUJ5Wlc1a1pYSmxaRUlnUFNCaVhHNWNiaUFnSUNCcFppQW9hWE5VYUhWdWF5aGlLU2tnZTF4dUlDQWdJQ0FnSUNCeVpXNWtaWEpsWkVJZ1BTQnlaVzVrWlhKVWFIVnVheWhpTENCaEtWeHVJQ0FnSUgxY2JseHVJQ0FnSUdsbUlDaHBjMVJvZFc1cktHRXBLU0I3WEc0Z0lDQWdJQ0FnSUhKbGJtUmxjbVZrUVNBOUlISmxibVJsY2xSb2RXNXJLR0VzSUc1MWJHd3BYRzRnSUNBZ2ZWeHVYRzRnSUNBZ2NtVjBkWEp1SUh0Y2JpQWdJQ0FnSUNBZ1lUb2djbVZ1WkdWeVpXUkJMRnh1SUNBZ0lDQWdJQ0JpT2lCeVpXNWtaWEpsWkVKY2JpQWdJQ0I5WEc1OVhHNWNibVoxYm1OMGFXOXVJSEpsYm1SbGNsUm9kVzVyS0hSb2RXNXJMQ0J3Y21WMmFXOTFjeWtnZTF4dUlDQWdJSFpoY2lCeVpXNWtaWEpsWkZSb2RXNXJJRDBnZEdoMWJtc3VkbTV2WkdWY2JseHVJQ0FnSUdsbUlDZ2hjbVZ1WkdWeVpXUlVhSFZ1YXlrZ2UxeHVJQ0FnSUNBZ0lDQnlaVzVrWlhKbFpGUm9kVzVySUQwZ2RHaDFibXN1ZG01dlpHVWdQU0IwYUhWdWF5NXlaVzVrWlhJb2NISmxkbWx2ZFhNcFhHNGdJQ0FnZlZ4dVhHNGdJQ0FnYVdZZ0tDRW9hWE5XVG05a1pTaHlaVzVrWlhKbFpGUm9kVzVyS1NCOGZGeHVJQ0FnSUNBZ0lDQWdJQ0FnYVhOV1ZHVjRkQ2h5Wlc1a1pYSmxaRlJvZFc1cktTQjhmRnh1SUNBZ0lDQWdJQ0FnSUNBZ2FYTlhhV1JuWlhRb2NtVnVaR1Z5WldSVWFIVnVheWtwS1NCN1hHNGdJQ0FnSUNBZ0lIUm9jbTkzSUc1bGR5QkZjbkp2Y2loY0luUm9kVzVySUdScFpDQnViM1FnY21WMGRYSnVJR0VnZG1Gc2FXUWdibTlrWlZ3aUtUdGNiaUFnSUNCOVhHNWNiaUFnSUNCeVpYUjFjbTRnY21WdVpHVnlaV1JVYUhWdWExeHVmVnh1WEc1OUxIdGNJaTR2YVhNdGRHaDFibXRjSWpveU5TeGNJaTR2YVhNdGRtNXZaR1ZjSWpveU55eGNJaTR2YVhNdGRuUmxlSFJjSWpveU9DeGNJaTR2YVhNdGQybGtaMlYwWENJNk1qbDlYU3d5TlRwYlpuVnVZM1JwYjI0b2NtVnhkV2x5WlN4dGIyUjFiR1VzWlhod2IzSjBjeWw3WEc1dGIyUjFiR1V1Wlhod2IzSjBjeUE5SUdselZHaDFibXRjYmx4dVpuVnVZM1JwYjI0Z2FYTlVhSFZ1YXloMEtTQjdYRzRnSUNBZ2NtVjBkWEp1SUhRZ0ppWWdkQzUwZVhCbElEMDlQU0JjSWxSb2RXNXJYQ0pjYm4xY2JseHVmU3g3ZlYwc01qWTZXMloxYm1OMGFXOXVLSEpsY1hWcGNtVXNiVzlrZFd4bExHVjRjRzl5ZEhNcGUxeHViVzlrZFd4bExtVjRjRzl5ZEhNZ1BTQnBjMGh2YjJ0Y2JseHVablZ1WTNScGIyNGdhWE5JYjI5cktHaHZiMnNwSUh0Y2JpQWdJQ0J5WlhSMWNtNGdhRzl2YXlBbUpseHVJQ0FnSUNBZ0tIUjVjR1Z2WmlCb2IyOXJMbWh2YjJzZ1BUMDlJRndpWm5WdVkzUnBiMjVjSWlBbUppQWhhRzl2YXk1b1lYTlBkMjVRY205d1pYSjBlU2hjSW1odmIydGNJaWtnZkh4Y2JpQWdJQ0FnSUNCMGVYQmxiMllnYUc5dmF5NTFibWh2YjJzZ1BUMDlJRndpWm5WdVkzUnBiMjVjSWlBbUppQWhhRzl2YXk1b1lYTlBkMjVRY205d1pYSjBlU2hjSW5WdWFHOXZhMXdpS1NsY2JuMWNibHh1ZlN4N2ZWMHNNamM2VzJaMWJtTjBhVzl1S0hKbGNYVnBjbVVzYlc5a2RXeGxMR1Y0Y0c5eWRITXBlMXh1ZG1GeUlIWmxjbk5wYjI0Z1BTQnlaWEYxYVhKbEtGd2lMaTkyWlhKemFXOXVYQ0lwWEc1Y2JtMXZaSFZzWlM1bGVIQnZjblJ6SUQwZ2FYTldhWEowZFdGc1RtOWtaVnh1WEc1bWRXNWpkR2x2YmlCcGMxWnBjblIxWVd4T2IyUmxLSGdwSUh0Y2JpQWdJQ0J5WlhSMWNtNGdlQ0FtSmlCNExuUjVjR1VnUFQwOUlGd2lWbWx5ZEhWaGJFNXZaR1ZjSWlBbUppQjRMblpsY25OcGIyNGdQVDA5SUhabGNuTnBiMjVjYm4xY2JseHVmU3g3WENJdUwzWmxjbk5wYjI1Y0lqb3pNSDFkTERJNE9sdG1kVzVqZEdsdmJpaHlaWEYxYVhKbExHMXZaSFZzWlN4bGVIQnZjblJ6S1h0Y2JuWmhjaUIyWlhKemFXOXVJRDBnY21WeGRXbHlaU2hjSWk0dmRtVnljMmx2Ymx3aUtWeHVYRzV0YjJSMWJHVXVaWGh3YjNKMGN5QTlJR2x6Vm1seWRIVmhiRlJsZUhSY2JseHVablZ1WTNScGIyNGdhWE5XYVhKMGRXRnNWR1Y0ZENoNEtTQjdYRzRnSUNBZ2NtVjBkWEp1SUhnZ0ppWWdlQzUwZVhCbElEMDlQU0JjSWxacGNuUjFZV3hVWlhoMFhDSWdKaVlnZUM1MlpYSnphVzl1SUQwOVBTQjJaWEp6YVc5dVhHNTlYRzVjYm4wc2Uxd2lMaTkyWlhKemFXOXVYQ0k2TXpCOVhTd3lPVHBiWm5WdVkzUnBiMjRvY21WeGRXbHlaU3h0YjJSMWJHVXNaWGh3YjNKMGN5bDdYRzV0YjJSMWJHVXVaWGh3YjNKMGN5QTlJR2x6VjJsa1oyVjBYRzVjYm1aMWJtTjBhVzl1SUdselYybGtaMlYwS0hjcElIdGNiaUFnSUNCeVpYUjFjbTRnZHlBbUppQjNMblI1Y0dVZ1BUMDlJRndpVjJsa1oyVjBYQ0pjYm4xY2JseHVmU3g3ZlYwc016QTZXMloxYm1OMGFXOXVLSEpsY1hWcGNtVXNiVzlrZFd4bExHVjRjRzl5ZEhNcGUxeHViVzlrZFd4bExtVjRjRzl5ZEhNZ1BTQmNJakpjSWx4dVhHNTlMSHQ5WFN3ek1UcGJablZ1WTNScGIyNG9jbVZ4ZFdseVpTeHRiMlIxYkdVc1pYaHdiM0owY3lsN1hHNTJZWElnZG1WeWMybHZiaUE5SUhKbGNYVnBjbVVvWENJdUwzWmxjbk5wYjI1Y0lpbGNiblpoY2lCcGMxWk9iMlJsSUQwZ2NtVnhkV2x5WlNoY0lpNHZhWE10ZG01dlpHVmNJaWxjYm5aaGNpQnBjMWRwWkdkbGRDQTlJSEpsY1hWcGNtVW9YQ0l1TDJsekxYZHBaR2RsZEZ3aUtWeHVkbUZ5SUdselZHaDFibXNnUFNCeVpYRjFhWEpsS0Z3aUxpOXBjeTEwYUhWdWExd2lLVnh1ZG1GeUlHbHpWa2h2YjJzZ1BTQnlaWEYxYVhKbEtGd2lMaTlwY3kxMmFHOXZhMXdpS1Z4dVhHNXRiMlIxYkdVdVpYaHdiM0owY3lBOUlGWnBjblIxWVd4T2IyUmxYRzVjYm5aaGNpQnViMUJ5YjNCbGNuUnBaWE1nUFNCN2ZWeHVkbUZ5SUc1dlEyaHBiR1J5Wlc0Z1BTQmJYVnh1WEc1bWRXNWpkR2x2YmlCV2FYSjBkV0ZzVG05a1pTaDBZV2RPWVcxbExDQndjbTl3WlhKMGFXVnpMQ0JqYUdsc1pISmxiaXdnYTJWNUxDQnVZVzFsYzNCaFkyVXBJSHRjYmlBZ0lDQjBhR2x6TG5SaFowNWhiV1VnUFNCMFlXZE9ZVzFsWEc0Z0lDQWdkR2hwY3k1d2NtOXdaWEowYVdWeklEMGdjSEp2Y0dWeWRHbGxjeUI4ZkNCdWIxQnliM0JsY25ScFpYTmNiaUFnSUNCMGFHbHpMbU5vYVd4a2NtVnVJRDBnWTJocGJHUnlaVzRnZkh3Z2JtOURhR2xzWkhKbGJseHVJQ0FnSUhSb2FYTXVhMlY1SUQwZ2EyVjVJQ0U5SUc1MWJHd2dQeUJUZEhKcGJtY29hMlY1S1NBNklIVnVaR1ZtYVc1bFpGeHVJQ0FnSUhSb2FYTXVibUZ0WlhOd1lXTmxJRDBnS0hSNWNHVnZaaUJ1WVcxbGMzQmhZMlVnUFQwOUlGd2ljM1J5YVc1blhDSXBJRDhnYm1GdFpYTndZV05sSURvZ2JuVnNiRnh1WEc0Z0lDQWdkbUZ5SUdOdmRXNTBJRDBnS0dOb2FXeGtjbVZ1SUNZbUlHTm9hV3hrY21WdUxteGxibWQwYUNrZ2ZId2dNRnh1SUNBZ0lIWmhjaUJrWlhOalpXNWtZVzUwY3lBOUlEQmNiaUFnSUNCMllYSWdhR0Z6VjJsa1oyVjBjeUE5SUdaaGJITmxYRzRnSUNBZ2RtRnlJR2hoYzFSb2RXNXJjeUE5SUdaaGJITmxYRzRnSUNBZ2RtRnlJR1JsYzJObGJtUmhiblJJYjI5cmN5QTlJR1poYkhObFhHNGdJQ0FnZG1GeUlHaHZiMnR6WEc1Y2JpQWdJQ0JtYjNJZ0tIWmhjaUJ3Y205d1RtRnRaU0JwYmlCd2NtOXdaWEowYVdWektTQjdYRzRnSUNBZ0lDQWdJR2xtSUNod2NtOXdaWEowYVdWekxtaGhjMDkzYmxCeWIzQmxjblI1S0hCeWIzQk9ZVzFsS1NrZ2UxeHVJQ0FnSUNBZ0lDQWdJQ0FnZG1GeUlIQnliM0JsY25SNUlEMGdjSEp2Y0dWeWRHbGxjMXR3Y205d1RtRnRaVjFjYmlBZ0lDQWdJQ0FnSUNBZ0lHbG1JQ2hwYzFaSWIyOXJLSEJ5YjNCbGNuUjVLU0FtSmlCd2NtOXdaWEowZVM1MWJtaHZiMnNwSUh0Y2JpQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNCcFppQW9JV2h2YjJ0ektTQjdYRzRnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUdodmIydHpJRDBnZTMxY2JpQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNCOVhHNWNiaUFnSUNBZ0lDQWdJQ0FnSUNBZ0lDQm9iMjlyYzF0d2NtOXdUbUZ0WlYwZ1BTQndjbTl3WlhKMGVWeHVJQ0FnSUNBZ0lDQWdJQ0FnZlZ4dUlDQWdJQ0FnSUNCOVhHNGdJQ0FnZlZ4dVhHNGdJQ0FnWm05eUlDaDJZWElnYVNBOUlEQTdJR2tnUENCamIzVnVkRHNnYVNzcktTQjdYRzRnSUNBZ0lDQWdJSFpoY2lCamFHbHNaQ0E5SUdOb2FXeGtjbVZ1VzJsZFhHNGdJQ0FnSUNBZ0lHbG1JQ2hwYzFaT2IyUmxLR05vYVd4a0tTa2dlMXh1SUNBZ0lDQWdJQ0FnSUNBZ1pHVnpZMlZ1WkdGdWRITWdLejBnWTJocGJHUXVZMjkxYm5RZ2ZId2dNRnh1WEc0Z0lDQWdJQ0FnSUNBZ0lDQnBaaUFvSVdoaGMxZHBaR2RsZEhNZ0ppWWdZMmhwYkdRdWFHRnpWMmxrWjJWMGN5a2dlMXh1SUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJR2hoYzFkcFpHZGxkSE1nUFNCMGNuVmxYRzRnSUNBZ0lDQWdJQ0FnSUNCOVhHNWNiaUFnSUNBZ0lDQWdJQ0FnSUdsbUlDZ2hhR0Z6VkdoMWJtdHpJQ1ltSUdOb2FXeGtMbWhoYzFSb2RXNXJjeWtnZTF4dUlDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUdoaGMxUm9kVzVyY3lBOUlIUnlkV1ZjYmlBZ0lDQWdJQ0FnSUNBZ0lIMWNibHh1SUNBZ0lDQWdJQ0FnSUNBZ2FXWWdLQ0ZrWlhOalpXNWtZVzUwU0c5dmEzTWdKaVlnS0dOb2FXeGtMbWh2YjJ0eklIeDhJR05vYVd4a0xtUmxjMk5sYm1SaGJuUkliMjlyY3lrcElIdGNiaUFnSUNBZ0lDQWdJQ0FnSUNBZ0lDQmtaWE5qWlc1a1lXNTBTRzl2YTNNZ1BTQjBjblZsWEc0Z0lDQWdJQ0FnSUNBZ0lDQjlYRzRnSUNBZ0lDQWdJSDBnWld4elpTQnBaaUFvSVdoaGMxZHBaR2RsZEhNZ0ppWWdhWE5YYVdSblpYUW9ZMmhwYkdRcEtTQjdYRzRnSUNBZ0lDQWdJQ0FnSUNCcFppQW9kSGx3Wlc5bUlHTm9hV3hrTG1SbGMzUnliM2tnUFQwOUlGd2lablZ1WTNScGIyNWNJaWtnZTF4dUlDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUdoaGMxZHBaR2RsZEhNZ1BTQjBjblZsWEc0Z0lDQWdJQ0FnSUNBZ0lDQjlYRzRnSUNBZ0lDQWdJSDBnWld4elpTQnBaaUFvSVdoaGMxUm9kVzVyY3lBbUppQnBjMVJvZFc1cktHTm9hV3hrS1NrZ2UxeHVJQ0FnSUNBZ0lDQWdJQ0FnYUdGelZHaDFibXR6SUQwZ2RISjFaVHRjYmlBZ0lDQWdJQ0FnZlZ4dUlDQWdJSDFjYmx4dUlDQWdJSFJvYVhNdVkyOTFiblFnUFNCamIzVnVkQ0FySUdSbGMyTmxibVJoYm5SelhHNGdJQ0FnZEdocGN5NW9ZWE5YYVdSblpYUnpJRDBnYUdGelYybGtaMlYwYzF4dUlDQWdJSFJvYVhNdWFHRnpWR2gxYm10eklEMGdhR0Z6VkdoMWJtdHpYRzRnSUNBZ2RHaHBjeTVvYjI5cmN5QTlJR2h2YjJ0elhHNGdJQ0FnZEdocGN5NWtaWE5qWlc1a1lXNTBTRzl2YTNNZ1BTQmtaWE5qWlc1a1lXNTBTRzl2YTNOY2JuMWNibHh1Vm1seWRIVmhiRTV2WkdVdWNISnZkRzkwZVhCbExuWmxjbk5wYjI0Z1BTQjJaWEp6YVc5dVhHNVdhWEowZFdGc1RtOWtaUzV3Y205MGIzUjVjR1V1ZEhsd1pTQTlJRndpVm1seWRIVmhiRTV2WkdWY0lseHVYRzU5TEh0Y0lpNHZhWE10ZEdoMWJtdGNJam95TlN4Y0lpNHZhWE10ZG1odmIydGNJam95Tml4Y0lpNHZhWE10ZG01dlpHVmNJam95Tnl4Y0lpNHZhWE10ZDJsa1oyVjBYQ0k2TWprc1hDSXVMM1psY25OcGIyNWNJam96TUgxZExETXlPbHRtZFc1amRHbHZiaWh5WlhGMWFYSmxMRzF2WkhWc1pTeGxlSEJ2Y25SektYdGNiblpoY2lCMlpYSnphVzl1SUQwZ2NtVnhkV2x5WlNoY0lpNHZkbVZ5YzJsdmJsd2lLVnh1WEc1V2FYSjBkV0ZzVUdGMFkyZ3VUazlPUlNBOUlEQmNibFpwY25SMVlXeFFZWFJqYUM1V1ZFVllWQ0E5SURGY2JsWnBjblIxWVd4UVlYUmphQzVXVGs5RVJTQTlJREpjYmxacGNuUjFZV3hRWVhSamFDNVhTVVJIUlZRZ1BTQXpYRzVXYVhKMGRXRnNVR0YwWTJndVVGSlBVRk1nUFNBMFhHNVdhWEowZFdGc1VHRjBZMmd1VDFKRVJWSWdQU0ExWEc1V2FYSjBkV0ZzVUdGMFkyZ3VTVTVUUlZKVUlEMGdObHh1Vm1seWRIVmhiRkJoZEdOb0xsSkZUVTlXUlNBOUlEZGNibFpwY25SMVlXeFFZWFJqYUM1VVNGVk9TeUE5SURoY2JseHViVzlrZFd4bExtVjRjRzl5ZEhNZ1BTQldhWEowZFdGc1VHRjBZMmhjYmx4dVpuVnVZM1JwYjI0Z1ZtbHlkSFZoYkZCaGRHTm9LSFI1Y0dVc0lIWk9iMlJsTENCd1lYUmphQ2tnZTF4dUlDQWdJSFJvYVhNdWRIbHdaU0E5SUU1MWJXSmxjaWgwZVhCbEtWeHVJQ0FnSUhSb2FYTXVkazV2WkdVZ1BTQjJUbTlrWlZ4dUlDQWdJSFJvYVhNdWNHRjBZMmdnUFNCd1lYUmphRnh1ZlZ4dVhHNVdhWEowZFdGc1VHRjBZMmd1Y0hKdmRHOTBlWEJsTG5abGNuTnBiMjRnUFNCMlpYSnphVzl1WEc1V2FYSjBkV0ZzVUdGMFkyZ3VjSEp2ZEc5MGVYQmxMblI1Y0dVZ1BTQmNJbFpwY25SMVlXeFFZWFJqYUZ3aVhHNWNibjBzZTF3aUxpOTJaWEp6YVc5dVhDSTZNekI5WFN3ek16cGJablZ1WTNScGIyNG9jbVZ4ZFdseVpTeHRiMlIxYkdVc1pYaHdiM0owY3lsN1hHNTJZWElnZG1WeWMybHZiaUE5SUhKbGNYVnBjbVVvWENJdUwzWmxjbk5wYjI1Y0lpbGNibHh1Ylc5a2RXeGxMbVY0Y0c5eWRITWdQU0JXYVhKMGRXRnNWR1Y0ZEZ4dVhHNW1kVzVqZEdsdmJpQldhWEowZFdGc1ZHVjRkQ2gwWlhoMEtTQjdYRzRnSUNBZ2RHaHBjeTUwWlhoMElEMGdVM1J5YVc1bktIUmxlSFFwWEc1OVhHNWNibFpwY25SMVlXeFVaWGgwTG5CeWIzUnZkSGx3WlM1MlpYSnphVzl1SUQwZ2RtVnljMmx2Ymx4dVZtbHlkSFZoYkZSbGVIUXVjSEp2ZEc5MGVYQmxMblI1Y0dVZ1BTQmNJbFpwY25SMVlXeFVaWGgwWENKY2JseHVmU3g3WENJdUwzWmxjbk5wYjI1Y0lqb3pNSDFkTERNME9sdG1kVzVqZEdsdmJpaHlaWEYxYVhKbExHMXZaSFZzWlN4bGVIQnZjblJ6S1h0Y2JuWmhjaUJwYzA5aWFtVmpkQ0E5SUhKbGNYVnBjbVVvWENKcGN5MXZZbXBsWTNSY0lpbGNiblpoY2lCcGMwaHZiMnNnUFNCeVpYRjFhWEpsS0Z3aUxpNHZkbTV2WkdVdmFYTXRkbWh2YjJ0Y0lpbGNibHh1Ylc5a2RXeGxMbVY0Y0c5eWRITWdQU0JrYVdabVVISnZjSE5jYmx4dVpuVnVZM1JwYjI0Z1pHbG1abEJ5YjNCektHRXNJR0lwSUh0Y2JpQWdJQ0IyWVhJZ1pHbG1abHh1WEc0Z0lDQWdabTl5SUNoMllYSWdZVXRsZVNCcGJpQmhLU0I3WEc0Z0lDQWdJQ0FnSUdsbUlDZ2hLR0ZMWlhrZ2FXNGdZaWtwSUh0Y2JpQWdJQ0FnSUNBZ0lDQWdJR1JwWm1ZZ1BTQmthV1ptSUh4OElIdDlYRzRnSUNBZ0lDQWdJQ0FnSUNCa2FXWm1XMkZMWlhsZElEMGdkVzVrWldacGJtVmtYRzRnSUNBZ0lDQWdJSDFjYmx4dUlDQWdJQ0FnSUNCMllYSWdZVlpoYkhWbElEMGdZVnRoUzJWNVhWeHVJQ0FnSUNBZ0lDQjJZWElnWWxaaGJIVmxJRDBnWWx0aFMyVjVYVnh1WEc0Z0lDQWdJQ0FnSUdsbUlDaGhWbUZzZFdVZ1BUMDlJR0pXWVd4MVpTa2dlMXh1SUNBZ0lDQWdJQ0FnSUNBZ1kyOXVkR2x1ZFdWY2JpQWdJQ0FnSUNBZ2ZTQmxiSE5sSUdsbUlDaHBjMDlpYW1WamRDaGhWbUZzZFdVcElDWW1JR2x6VDJKcVpXTjBLR0pXWVd4MVpTa3BJSHRjYmlBZ0lDQWdJQ0FnSUNBZ0lHbG1JQ2huWlhSUWNtOTBiM1I1Y0dVb1lsWmhiSFZsS1NBaFBUMGdaMlYwVUhKdmRHOTBlWEJsS0dGV1lXeDFaU2twSUh0Y2JpQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNCa2FXWm1JRDBnWkdsbVppQjhmQ0I3ZlZ4dUlDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUdScFptWmJZVXRsZVYwZ1BTQmlWbUZzZFdWY2JpQWdJQ0FnSUNBZ0lDQWdJSDBnWld4elpTQnBaaUFvYVhOSWIyOXJLR0pXWVd4MVpTa3BJSHRjYmlBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnWkdsbVppQTlJR1JwWm1ZZ2ZId2dlMzFjYmlBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnWkdsbVpsdGhTMlY1WFNBOUlHSldZV3gxWlZ4dUlDQWdJQ0FnSUNBZ0lDQWdmU0JsYkhObElIdGNiaUFnSUNBZ0lDQWdJQ0FnSUNBZ0lDQjJZWElnYjJKcVpXTjBSR2xtWmlBOUlHUnBabVpRY205d2N5aGhWbUZzZFdVc0lHSldZV3gxWlNsY2JpQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNCcFppQW9iMkpxWldOMFJHbG1aaWtnZTF4dUlDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQmthV1ptSUQwZ1pHbG1aaUI4ZkNCN2ZWeHVJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0JrYVdabVcyRkxaWGxkSUQwZ2IySnFaV04wUkdsbVpseHVJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lIMWNiaUFnSUNBZ0lDQWdJQ0FnSUgxY2JpQWdJQ0FnSUNBZ2ZTQmxiSE5sSUh0Y2JpQWdJQ0FnSUNBZ0lDQWdJR1JwWm1ZZ1BTQmthV1ptSUh4OElIdDlYRzRnSUNBZ0lDQWdJQ0FnSUNCa2FXWm1XMkZMWlhsZElEMGdZbFpoYkhWbFhHNGdJQ0FnSUNBZ0lIMWNiaUFnSUNCOVhHNWNiaUFnSUNCbWIzSWdLSFpoY2lCaVMyVjVJR2x1SUdJcElIdGNiaUFnSUNBZ0lDQWdhV1lnS0NFb1lrdGxlU0JwYmlCaEtTa2dlMXh1SUNBZ0lDQWdJQ0FnSUNBZ1pHbG1aaUE5SUdScFptWWdmSHdnZTMxY2JpQWdJQ0FnSUNBZ0lDQWdJR1JwWm1aYllrdGxlVjBnUFNCaVcySkxaWGxkWEc0Z0lDQWdJQ0FnSUgxY2JpQWdJQ0I5WEc1Y2JpQWdJQ0J5WlhSMWNtNGdaR2xtWmx4dWZWeHVYRzVtZFc1amRHbHZiaUJuWlhSUWNtOTBiM1I1Y0dVb2RtRnNkV1VwSUh0Y2JpQWdhV1lnS0U5aWFtVmpkQzVuWlhSUWNtOTBiM1I1Y0dWUFppa2dlMXh1SUNBZ0lISmxkSFZ5YmlCUFltcGxZM1F1WjJWMFVISnZkRzkwZVhCbFQyWW9kbUZzZFdVcFhHNGdJSDBnWld4elpTQnBaaUFvZG1Gc2RXVXVYMTl3Y205MGIxOWZLU0I3WEc0Z0lDQWdjbVYwZFhKdUlIWmhiSFZsTGw5ZmNISnZkRzlmWDF4dUlDQjlJR1ZzYzJVZ2FXWWdLSFpoYkhWbExtTnZibk4wY25WamRHOXlLU0I3WEc0Z0lDQWdjbVYwZFhKdUlIWmhiSFZsTG1OdmJuTjBjblZqZEc5eUxuQnliM1J2ZEhsd1pWeHVJQ0I5WEc1OVhHNWNibjBzZTF3aUxpNHZkbTV2WkdVdmFYTXRkbWh2YjJ0Y0lqb3lOaXhjSW1sekxXOWlhbVZqZEZ3aU9qRXhmVjBzTXpVNlcyWjFibU4wYVc5dUtISmxjWFZwY21Vc2JXOWtkV3hsTEdWNGNHOXlkSE1wZTF4dWRtRnlJR2x6UVhKeVlYa2dQU0J5WlhGMWFYSmxLRndpZUMxcGN5MWhjbkpoZVZ3aUtWeHVYRzUyWVhJZ1ZsQmhkR05vSUQwZ2NtVnhkV2x5WlNoY0lpNHVMM1p1YjJSbEwzWndZWFJqYUZ3aUtWeHVkbUZ5SUdselZrNXZaR1VnUFNCeVpYRjFhWEpsS0Z3aUxpNHZkbTV2WkdVdmFYTXRkbTV2WkdWY0lpbGNiblpoY2lCcGMxWlVaWGgwSUQwZ2NtVnhkV2x5WlNoY0lpNHVMM1p1YjJSbEwybHpMWFowWlhoMFhDSXBYRzUyWVhJZ2FYTlhhV1JuWlhRZ1BTQnlaWEYxYVhKbEtGd2lMaTR2ZG01dlpHVXZhWE10ZDJsa1oyVjBYQ0lwWEc1MllYSWdhWE5VYUhWdWF5QTlJSEpsY1hWcGNtVW9YQ0l1TGk5MmJtOWtaUzlwY3kxMGFIVnVhMXdpS1Z4dWRtRnlJR2hoYm1Sc1pWUm9kVzVySUQwZ2NtVnhkV2x5WlNoY0lpNHVMM1p1YjJSbEwyaGhibVJzWlMxMGFIVnVhMXdpS1Z4dVhHNTJZWElnWkdsbVpsQnliM0J6SUQwZ2NtVnhkV2x5WlNoY0lpNHZaR2xtWmkxd2NtOXdjMXdpS1Z4dVhHNXRiMlIxYkdVdVpYaHdiM0owY3lBOUlHUnBabVpjYmx4dVpuVnVZM1JwYjI0Z1pHbG1aaWhoTENCaUtTQjdYRzRnSUNBZ2RtRnlJSEJoZEdOb0lEMGdleUJoT2lCaElIMWNiaUFnSUNCM1lXeHJLR0VzSUdJc0lIQmhkR05vTENBd0tWeHVJQ0FnSUhKbGRIVnliaUJ3WVhSamFGeHVmVnh1WEc1bWRXNWpkR2x2YmlCM1lXeHJLR0VzSUdJc0lIQmhkR05vTENCcGJtUmxlQ2tnZTF4dUlDQWdJR2xtSUNoaElEMDlQU0JpS1NCN1hHNGdJQ0FnSUNBZ0lISmxkSFZ5Ymx4dUlDQWdJSDFjYmx4dUlDQWdJSFpoY2lCaGNIQnNlU0E5SUhCaGRHTm9XMmx1WkdWNFhWeHVJQ0FnSUhaaGNpQmhjSEJzZVVOc1pXRnlJRDBnWm1Gc2MyVmNibHh1SUNBZ0lHbG1JQ2hwYzFSb2RXNXJLR0VwSUh4OElHbHpWR2gxYm1zb1lpa3BJSHRjYmlBZ0lDQWdJQ0FnZEdoMWJtdHpLR0VzSUdJc0lIQmhkR05vTENCcGJtUmxlQ2xjYmlBZ0lDQjlJR1ZzYzJVZ2FXWWdLR0lnUFQwZ2JuVnNiQ2tnZTF4dVhHNGdJQ0FnSUNBZ0lDOHZJRWxtSUdFZ2FYTWdZU0IzYVdSblpYUWdkMlVnZDJsc2JDQmhaR1FnWVNCeVpXMXZkbVVnY0dGMFkyZ2dabTl5SUdsMFhHNGdJQ0FnSUNBZ0lDOHZJRTkwYUdWeWQybHpaU0JoYm5rZ1kyaHBiR1FnZDJsa1oyVjBjeTlvYjI5cmN5QnRkWE4wSUdKbElHUmxjM1J5YjNsbFpDNWNiaUFnSUNBZ0lDQWdMeThnVkdocGN5QndjbVYyWlc1MGN5QmhaR1JwYm1jZ2RIZHZJSEpsYlc5MlpTQndZWFJqYUdWeklHWnZjaUJoSUhkcFpHZGxkQzVjYmlBZ0lDQWdJQ0FnYVdZZ0tDRnBjMWRwWkdkbGRDaGhLU2tnZTF4dUlDQWdJQ0FnSUNBZ0lDQWdZMnhsWVhKVGRHRjBaU2hoTENCd1lYUmphQ3dnYVc1a1pYZ3BYRzRnSUNBZ0lDQWdJQ0FnSUNCaGNIQnNlU0E5SUhCaGRHTm9XMmx1WkdWNFhWeHVJQ0FnSUNBZ0lDQjlYRzVjYmlBZ0lDQWdJQ0FnWVhCd2JIa2dQU0JoY0hCbGJtUlFZWFJqYUNoaGNIQnNlU3dnYm1WM0lGWlFZWFJqYUNoV1VHRjBZMmd1VWtWTlQxWkZMQ0JoTENCaUtTbGNiaUFnSUNCOUlHVnNjMlVnYVdZZ0tHbHpWazV2WkdVb1lpa3BJSHRjYmlBZ0lDQWdJQ0FnYVdZZ0tHbHpWazV2WkdVb1lTa3BJSHRjYmlBZ0lDQWdJQ0FnSUNBZ0lHbG1JQ2hoTG5SaFowNWhiV1VnUFQwOUlHSXVkR0ZuVG1GdFpTQW1KbHh1SUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJR0V1Ym1GdFpYTndZV05sSUQwOVBTQmlMbTVoYldWemNHRmpaU0FtSmx4dUlDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUdFdWEyVjVJRDA5UFNCaUxtdGxlU2tnZTF4dUlDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUhaaGNpQndjbTl3YzFCaGRHTm9JRDBnWkdsbVpsQnliM0J6S0dFdWNISnZjR1Z5ZEdsbGN5d2dZaTV3Y205d1pYSjBhV1Z6S1Z4dUlDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUdsbUlDaHdjbTl3YzFCaGRHTm9LU0I3WEc0Z0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lHRndjR3g1SUQwZ1lYQndaVzVrVUdGMFkyZ29ZWEJ3Ykhrc1hHNGdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNCdVpYY2dWbEJoZEdOb0tGWlFZWFJqYUM1UVVrOVFVeXdnWVN3Z2NISnZjSE5RWVhSamFDa3BYRzRnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdmVnh1SUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJR0Z3Y0d4NUlEMGdaR2xtWmtOb2FXeGtjbVZ1S0dFc0lHSXNJSEJoZEdOb0xDQmhjSEJzZVN3Z2FXNWtaWGdwWEc0Z0lDQWdJQ0FnSUNBZ0lDQjlJR1ZzYzJVZ2UxeHVJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lHRndjR3g1SUQwZ1lYQndaVzVrVUdGMFkyZ29ZWEJ3Ykhrc0lHNWxkeUJXVUdGMFkyZ29WbEJoZEdOb0xsWk9UMFJGTENCaExDQmlLU2xjYmlBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0JoY0hCc2VVTnNaV0Z5SUQwZ2RISjFaVnh1SUNBZ0lDQWdJQ0FnSUNBZ2ZWeHVJQ0FnSUNBZ0lDQjlJR1ZzYzJVZ2UxeHVJQ0FnSUNBZ0lDQWdJQ0FnWVhCd2JIa2dQU0JoY0hCbGJtUlFZWFJqYUNoaGNIQnNlU3dnYm1WM0lGWlFZWFJqYUNoV1VHRjBZMmd1Vms1UFJFVXNJR0VzSUdJcEtWeHVJQ0FnSUNBZ0lDQWdJQ0FnWVhCd2JIbERiR1ZoY2lBOUlIUnlkV1ZjYmlBZ0lDQWdJQ0FnZlZ4dUlDQWdJSDBnWld4elpTQnBaaUFvYVhOV1ZHVjRkQ2hpS1NrZ2UxeHVJQ0FnSUNBZ0lDQnBaaUFvSVdselZsUmxlSFFvWVNrcElIdGNiaUFnSUNBZ0lDQWdJQ0FnSUdGd2NHeDVJRDBnWVhCd1pXNWtVR0YwWTJnb1lYQndiSGtzSUc1bGR5QldVR0YwWTJnb1ZsQmhkR05vTGxaVVJWaFVMQ0JoTENCaUtTbGNiaUFnSUNBZ0lDQWdJQ0FnSUdGd2NHeDVRMnhsWVhJZ1BTQjBjblZsWEc0Z0lDQWdJQ0FnSUgwZ1pXeHpaU0JwWmlBb1lTNTBaWGgwSUNFOVBTQmlMblJsZUhRcElIdGNiaUFnSUNBZ0lDQWdJQ0FnSUdGd2NHeDVJRDBnWVhCd1pXNWtVR0YwWTJnb1lYQndiSGtzSUc1bGR5QldVR0YwWTJnb1ZsQmhkR05vTGxaVVJWaFVMQ0JoTENCaUtTbGNiaUFnSUNBZ0lDQWdmVnh1SUNBZ0lIMGdaV3h6WlNCcFppQW9hWE5YYVdSblpYUW9ZaWtwSUh0Y2JpQWdJQ0FnSUNBZ2FXWWdLQ0ZwYzFkcFpHZGxkQ2hoS1NrZ2UxeHVJQ0FnSUNBZ0lDQWdJQ0FnWVhCd2JIbERiR1ZoY2lBOUlIUnlkV1ZjYmlBZ0lDQWdJQ0FnZlZ4dVhHNGdJQ0FnSUNBZ0lHRndjR3g1SUQwZ1lYQndaVzVrVUdGMFkyZ29ZWEJ3Ykhrc0lHNWxkeUJXVUdGMFkyZ29WbEJoZEdOb0xsZEpSRWRGVkN3Z1lTd2dZaWtwWEc0Z0lDQWdmVnh1WEc0Z0lDQWdhV1lnS0dGd2NHeDVLU0I3WEc0Z0lDQWdJQ0FnSUhCaGRHTm9XMmx1WkdWNFhTQTlJR0Z3Y0d4NVhHNGdJQ0FnZlZ4dVhHNGdJQ0FnYVdZZ0tHRndjR3g1UTJ4bFlYSXBJSHRjYmlBZ0lDQWdJQ0FnWTJ4bFlYSlRkR0YwWlNoaExDQndZWFJqYUN3Z2FXNWtaWGdwWEc0Z0lDQWdmVnh1ZlZ4dVhHNW1kVzVqZEdsdmJpQmthV1ptUTJocGJHUnlaVzRvWVN3Z1lpd2djR0YwWTJnc0lHRndjR3g1TENCcGJtUmxlQ2tnZTF4dUlDQWdJSFpoY2lCaFEyaHBiR1J5Wlc0Z1BTQmhMbU5vYVd4a2NtVnVYRzRnSUNBZ2RtRnlJRzl5WkdWeVpXUlRaWFFnUFNCeVpXOXlaR1Z5S0dGRGFHbHNaSEpsYml3Z1lpNWphR2xzWkhKbGJpbGNiaUFnSUNCMllYSWdZa05vYVd4a2NtVnVJRDBnYjNKa1pYSmxaRk5sZEM1amFHbHNaSEpsYmx4dVhHNGdJQ0FnZG1GeUlHRk1aVzRnUFNCaFEyaHBiR1J5Wlc0dWJHVnVaM1JvWEc0Z0lDQWdkbUZ5SUdKTVpXNGdQU0JpUTJocGJHUnlaVzR1YkdWdVozUm9YRzRnSUNBZ2RtRnlJR3hsYmlBOUlHRk1aVzRnUGlCaVRHVnVJRDhnWVV4bGJpQTZJR0pNWlc1Y2JseHVJQ0FnSUdadmNpQW9kbUZ5SUdrZ1BTQXdPeUJwSUR3Z2JHVnVPeUJwS3lzcElIdGNiaUFnSUNBZ0lDQWdkbUZ5SUd4bFpuUk9iMlJsSUQwZ1lVTm9hV3hrY21WdVcybGRYRzRnSUNBZ0lDQWdJSFpoY2lCeWFXZG9kRTV2WkdVZ1BTQmlRMmhwYkdSeVpXNWJhVjFjYmlBZ0lDQWdJQ0FnYVc1a1pYZ2dLejBnTVZ4dVhHNGdJQ0FnSUNBZ0lHbG1JQ2doYkdWbWRFNXZaR1VwSUh0Y2JpQWdJQ0FnSUNBZ0lDQWdJR2xtSUNoeWFXZG9kRTV2WkdVcElIdGNiaUFnSUNBZ0lDQWdJQ0FnSUNBZ0lDQXZMeUJGZUdObGMzTWdibTlrWlhNZ2FXNGdZaUJ1WldWa0lIUnZJR0psSUdGa1pHVmtYRzRnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdZWEJ3YkhrZ1BTQmhjSEJsYm1SUVlYUmphQ2hoY0hCc2VTeGNiaUFnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnYm1WM0lGWlFZWFJqYUNoV1VHRjBZMmd1U1U1VFJWSlVMQ0J1ZFd4c0xDQnlhV2RvZEU1dlpHVXBLVnh1SUNBZ0lDQWdJQ0FnSUNBZ2ZWeHVJQ0FnSUNBZ0lDQjlJR1ZzYzJVZ2UxeHVJQ0FnSUNBZ0lDQWdJQ0FnZDJGc2F5aHNaV1owVG05a1pTd2djbWxuYUhST2IyUmxMQ0J3WVhSamFDd2dhVzVrWlhncFhHNGdJQ0FnSUNBZ0lIMWNibHh1SUNBZ0lDQWdJQ0JwWmlBb2FYTldUbTlrWlNoc1pXWjBUbTlrWlNrZ0ppWWdiR1ZtZEU1dlpHVXVZMjkxYm5RcElIdGNiaUFnSUNBZ0lDQWdJQ0FnSUdsdVpHVjRJQ3M5SUd4bFpuUk9iMlJsTG1OdmRXNTBYRzRnSUNBZ0lDQWdJSDFjYmlBZ0lDQjlYRzVjYmlBZ0lDQnBaaUFvYjNKa1pYSmxaRk5sZEM1dGIzWmxjeWtnZTF4dUlDQWdJQ0FnSUNBdkx5QlNaVzl5WkdWeUlHNXZaR1Z6SUd4aGMzUmNiaUFnSUNBZ0lDQWdZWEJ3YkhrZ1BTQmhjSEJsYm1SUVlYUmphQ2hoY0hCc2VTd2dibVYzSUZaUVlYUmphQ2hjYmlBZ0lDQWdJQ0FnSUNBZ0lGWlFZWFJqYUM1UFVrUkZVaXhjYmlBZ0lDQWdJQ0FnSUNBZ0lHRXNYRzRnSUNBZ0lDQWdJQ0FnSUNCdmNtUmxjbVZrVTJWMExtMXZkbVZ6WEc0Z0lDQWdJQ0FnSUNrcFhHNGdJQ0FnZlZ4dVhHNGdJQ0FnY21WMGRYSnVJR0Z3Y0d4NVhHNTlYRzVjYm1aMWJtTjBhVzl1SUdOc1pXRnlVM1JoZEdVb2RrNXZaR1VzSUhCaGRHTm9MQ0JwYm1SbGVDa2dlMXh1SUNBZ0lDOHZJRlJQUkU4NklFMWhhMlVnZEdocGN5QmhJSE5wYm1kc1pTQjNZV3hyTENCdWIzUWdkSGR2WEc0Z0lDQWdkVzVvYjI5cktIWk9iMlJsTENCd1lYUmphQ3dnYVc1a1pYZ3BYRzRnSUNBZ1pHVnpkSEp2ZVZkcFpHZGxkSE1vZGs1dlpHVXNJSEJoZEdOb0xDQnBibVJsZUNsY2JuMWNibHh1THk4Z1VHRjBZMmdnY21WamIzSmtjeUJtYjNJZ1lXeHNJR1JsYzNSeWIzbGxaQ0IzYVdSblpYUnpJRzExYzNRZ1ltVWdZV1JrWldRZ1ltVmpZWFZ6WlNCM1pTQnVaV1ZrWEc0dkx5QmhJRVJQVFNCdWIyUmxJSEpsWm1WeVpXNWpaU0JtYjNJZ2RHaGxJR1JsYzNSeWIza2dablZ1WTNScGIyNWNibVoxYm1OMGFXOXVJR1JsYzNSeWIzbFhhV1JuWlhSektIWk9iMlJsTENCd1lYUmphQ3dnYVc1a1pYZ3BJSHRjYmlBZ0lDQnBaaUFvYVhOWGFXUm5aWFFvZGs1dlpHVXBLU0I3WEc0Z0lDQWdJQ0FnSUdsbUlDaDBlWEJsYjJZZ2RrNXZaR1V1WkdWemRISnZlU0E5UFQwZ1hDSm1kVzVqZEdsdmJsd2lLU0I3WEc0Z0lDQWdJQ0FnSUNBZ0lDQndZWFJqYUZ0cGJtUmxlRjBnUFNCaGNIQmxibVJRWVhSamFDaGNiaUFnSUNBZ0lDQWdJQ0FnSUNBZ0lDQndZWFJqYUZ0cGJtUmxlRjBzWEc0Z0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnYm1WM0lGWlFZWFJqYUNoV1VHRjBZMmd1VWtWTlQxWkZMQ0IyVG05a1pTd2diblZzYkNsY2JpQWdJQ0FnSUNBZ0lDQWdJQ2xjYmlBZ0lDQWdJQ0FnZlZ4dUlDQWdJSDBnWld4elpTQnBaaUFvYVhOV1RtOWtaU2gyVG05a1pTa2dKaVlnS0haT2IyUmxMbWhoYzFkcFpHZGxkSE1nZkh3Z2RrNXZaR1V1YUdGelZHaDFibXR6S1NrZ2UxeHVJQ0FnSUNBZ0lDQjJZWElnWTJocGJHUnlaVzRnUFNCMlRtOWtaUzVqYUdsc1pISmxibHh1SUNBZ0lDQWdJQ0IyWVhJZ2JHVnVJRDBnWTJocGJHUnlaVzR1YkdWdVozUm9YRzRnSUNBZ0lDQWdJR1p2Y2lBb2RtRnlJR2tnUFNBd095QnBJRHdnYkdWdU95QnBLeXNwSUh0Y2JpQWdJQ0FnSUNBZ0lDQWdJSFpoY2lCamFHbHNaQ0E5SUdOb2FXeGtjbVZ1VzJsZFhHNGdJQ0FnSUNBZ0lDQWdJQ0JwYm1SbGVDQXJQU0F4WEc1Y2JpQWdJQ0FnSUNBZ0lDQWdJR1JsYzNSeWIzbFhhV1JuWlhSektHTm9hV3hrTENCd1lYUmphQ3dnYVc1a1pYZ3BYRzVjYmlBZ0lDQWdJQ0FnSUNBZ0lHbG1JQ2hwYzFaT2IyUmxLR05vYVd4a0tTQW1KaUJqYUdsc1pDNWpiM1Z1ZENrZ2UxeHVJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lHbHVaR1Y0SUNzOUlHTm9hV3hrTG1OdmRXNTBYRzRnSUNBZ0lDQWdJQ0FnSUNCOVhHNGdJQ0FnSUNBZ0lIMWNiaUFnSUNCOUlHVnNjMlVnYVdZZ0tHbHpWR2gxYm1zb2RrNXZaR1VwS1NCN1hHNGdJQ0FnSUNBZ0lIUm9kVzVyY3loMlRtOWtaU3dnYm5Wc2JDd2djR0YwWTJnc0lHbHVaR1Y0S1Z4dUlDQWdJSDFjYm4xY2JseHVMeThnUTNKbFlYUmxJR0VnYzNWaUxYQmhkR05vSUdadmNpQjBhSFZ1YTNOY2JtWjFibU4wYVc5dUlIUm9kVzVyY3loaExDQmlMQ0J3WVhSamFDd2dhVzVrWlhncElIdGNiaUFnSUNCMllYSWdibTlrWlhNZ1BTQm9ZVzVrYkdWVWFIVnVheWhoTENCaUtWeHVJQ0FnSUhaaGNpQjBhSFZ1YTFCaGRHTm9JRDBnWkdsbVppaHViMlJsY3k1aExDQnViMlJsY3k1aUtWeHVJQ0FnSUdsbUlDaG9ZWE5RWVhSamFHVnpLSFJvZFc1clVHRjBZMmdwS1NCN1hHNGdJQ0FnSUNBZ0lIQmhkR05vVzJsdVpHVjRYU0E5SUc1bGR5QldVR0YwWTJnb1ZsQmhkR05vTGxSSVZVNUxMQ0J1ZFd4c0xDQjBhSFZ1YTFCaGRHTm9LVnh1SUNBZ0lIMWNibjFjYmx4dVpuVnVZM1JwYjI0Z2FHRnpVR0YwWTJobGN5aHdZWFJqYUNrZ2UxeHVJQ0FnSUdadmNpQW9kbUZ5SUdsdVpHVjRJR2x1SUhCaGRHTm9LU0I3WEc0Z0lDQWdJQ0FnSUdsbUlDaHBibVJsZUNBaFBUMGdYQ0poWENJcElIdGNiaUFnSUNBZ0lDQWdJQ0FnSUhKbGRIVnliaUIwY25WbFhHNGdJQ0FnSUNBZ0lIMWNiaUFnSUNCOVhHNWNiaUFnSUNCeVpYUjFjbTRnWm1Gc2MyVmNibjFjYmx4dUx5OGdSWGhsWTNWMFpTQm9iMjlyY3lCM2FHVnVJSFIzYnlCdWIyUmxjeUJoY21VZ2FXUmxiblJwWTJGc1hHNW1kVzVqZEdsdmJpQjFibWh2YjJzb2RrNXZaR1VzSUhCaGRHTm9MQ0JwYm1SbGVDa2dlMXh1SUNBZ0lHbG1JQ2hwYzFaT2IyUmxLSFpPYjJSbEtTa2dlMXh1SUNBZ0lDQWdJQ0JwWmlBb2RrNXZaR1V1YUc5dmEzTXBJSHRjYmlBZ0lDQWdJQ0FnSUNBZ0lIQmhkR05vVzJsdVpHVjRYU0E5SUdGd2NHVnVaRkJoZEdOb0tGeHVJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lIQmhkR05vVzJsdVpHVjRYU3hjYmlBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0J1WlhjZ1ZsQmhkR05vS0Z4dUlDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQldVR0YwWTJndVVGSlBVRk1zWEc0Z0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lIWk9iMlJsTEZ4dUlDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQjFibVJsWm1sdVpXUkxaWGx6S0haT2IyUmxMbWh2YjJ0ektWeHVJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDbGNiaUFnSUNBZ0lDQWdJQ0FnSUNsY2JpQWdJQ0FnSUNBZ2ZWeHVYRzRnSUNBZ0lDQWdJR2xtSUNoMlRtOWtaUzVrWlhOalpXNWtZVzUwU0c5dmEzTWdmSHdnZGs1dlpHVXVhR0Z6VkdoMWJtdHpLU0I3WEc0Z0lDQWdJQ0FnSUNBZ0lDQjJZWElnWTJocGJHUnlaVzRnUFNCMlRtOWtaUzVqYUdsc1pISmxibHh1SUNBZ0lDQWdJQ0FnSUNBZ2RtRnlJR3hsYmlBOUlHTm9hV3hrY21WdUxteGxibWQwYUZ4dUlDQWdJQ0FnSUNBZ0lDQWdabTl5SUNoMllYSWdhU0E5SURBN0lHa2dQQ0JzWlc0N0lHa3JLeWtnZTF4dUlDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUhaaGNpQmphR2xzWkNBOUlHTm9hV3hrY21WdVcybGRYRzRnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdhVzVrWlhnZ0t6MGdNVnh1WEc0Z0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnZFc1b2IyOXJLR05vYVd4a0xDQndZWFJqYUN3Z2FXNWtaWGdwWEc1Y2JpQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNCcFppQW9hWE5XVG05a1pTaGphR2xzWkNrZ0ppWWdZMmhwYkdRdVkyOTFiblFwSUh0Y2JpQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdhVzVrWlhnZ0t6MGdZMmhwYkdRdVkyOTFiblJjYmlBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0I5WEc0Z0lDQWdJQ0FnSUNBZ0lDQjlYRzRnSUNBZ0lDQWdJSDFjYmlBZ0lDQjlJR1ZzYzJVZ2FXWWdLR2x6VkdoMWJtc29kazV2WkdVcEtTQjdYRzRnSUNBZ0lDQWdJSFJvZFc1cmN5aDJUbTlrWlN3Z2JuVnNiQ3dnY0dGMFkyZ3NJR2x1WkdWNEtWeHVJQ0FnSUgxY2JuMWNibHh1Wm5WdVkzUnBiMjRnZFc1a1pXWnBibVZrUzJWNWN5aHZZbW9wSUh0Y2JpQWdJQ0IyWVhJZ2NtVnpkV3gwSUQwZ2UzMWNibHh1SUNBZ0lHWnZjaUFvZG1GeUlHdGxlU0JwYmlCdlltb3BJSHRjYmlBZ0lDQWdJQ0FnY21WemRXeDBXMnRsZVYwZ1BTQjFibVJsWm1sdVpXUmNiaUFnSUNCOVhHNWNiaUFnSUNCeVpYUjFjbTRnY21WemRXeDBYRzU5WEc1Y2JpOHZJRXhwYzNRZ1pHbG1aaXdnYm1GcGRtVWdiR1ZtZENCMGJ5QnlhV2RvZENCeVpXOXlaR1Z5YVc1blhHNW1kVzVqZEdsdmJpQnlaVzl5WkdWeUtHRkRhR2xzWkhKbGJpd2dZa05vYVd4a2NtVnVLU0I3WEc0Z0lDQWdMeThnVHloTktTQjBhVzFsTENCUEtFMHBJRzFsYlc5eWVWeHVJQ0FnSUhaaGNpQmlRMmhwYkdSSmJtUmxlQ0E5SUd0bGVVbHVaR1Y0S0dKRGFHbHNaSEpsYmlsY2JpQWdJQ0IyWVhJZ1lrdGxlWE1nUFNCaVEyaHBiR1JKYm1SbGVDNXJaWGx6WEc0Z0lDQWdkbUZ5SUdKR2NtVmxJRDBnWWtOb2FXeGtTVzVrWlhndVpuSmxaVnh1WEc0Z0lDQWdhV1lnS0dKR2NtVmxMbXhsYm1kMGFDQTlQVDBnWWtOb2FXeGtjbVZ1TG14bGJtZDBhQ2tnZTF4dUlDQWdJQ0FnSUNCeVpYUjFjbTRnZTF4dUlDQWdJQ0FnSUNBZ0lDQWdZMmhwYkdSeVpXNDZJR0pEYUdsc1pISmxiaXhjYmlBZ0lDQWdJQ0FnSUNBZ0lHMXZkbVZ6T2lCdWRXeHNYRzRnSUNBZ0lDQWdJSDFjYmlBZ0lDQjlYRzVjYmlBZ0lDQXZMeUJQS0U0cElIUnBiV1VzSUU4b1Rpa2diV1Z0YjNKNVhHNGdJQ0FnZG1GeUlHRkRhR2xzWkVsdVpHVjRJRDBnYTJWNVNXNWtaWGdvWVVOb2FXeGtjbVZ1S1Z4dUlDQWdJSFpoY2lCaFMyVjVjeUE5SUdGRGFHbHNaRWx1WkdWNExtdGxlWE5jYmlBZ0lDQjJZWElnWVVaeVpXVWdQU0JoUTJocGJHUkpibVJsZUM1bWNtVmxYRzVjYmlBZ0lDQnBaaUFvWVVaeVpXVXViR1Z1WjNSb0lEMDlQU0JoUTJocGJHUnlaVzR1YkdWdVozUm9LU0I3WEc0Z0lDQWdJQ0FnSUhKbGRIVnliaUI3WEc0Z0lDQWdJQ0FnSUNBZ0lDQmphR2xzWkhKbGJqb2dZa05vYVd4a2NtVnVMRnh1SUNBZ0lDQWdJQ0FnSUNBZ2JXOTJaWE02SUc1MWJHeGNiaUFnSUNBZ0lDQWdmVnh1SUNBZ0lIMWNibHh1SUNBZ0lDOHZJRThvVFVGWUtFNHNJRTBwS1NCdFpXMXZjbmxjYmlBZ0lDQjJZWElnYm1WM1EyaHBiR1J5Wlc0Z1BTQmJYVnh1WEc0Z0lDQWdkbUZ5SUdaeVpXVkpibVJsZUNBOUlEQmNiaUFnSUNCMllYSWdabkpsWlVOdmRXNTBJRDBnWWtaeVpXVXViR1Z1WjNSb1hHNGdJQ0FnZG1GeUlHUmxiR1YwWldSSmRHVnRjeUE5SURCY2JseHVJQ0FnSUM4dklFbDBaWEpoZEdVZ2RHaHliM1ZuYUNCaElHRnVaQ0J0WVhSamFDQmhJRzV2WkdVZ2FXNGdZbHh1SUNBZ0lDOHZJRThvVGlrZ2RHbHRaU3hjYmlBZ0lDQm1iM0lnS0haaGNpQnBJRDBnTUNBN0lHa2dQQ0JoUTJocGJHUnlaVzR1YkdWdVozUm9PeUJwS3lzcElIdGNiaUFnSUNBZ0lDQWdkbUZ5SUdGSmRHVnRJRDBnWVVOb2FXeGtjbVZ1VzJsZFhHNGdJQ0FnSUNBZ0lIWmhjaUJwZEdWdFNXNWtaWGhjYmx4dUlDQWdJQ0FnSUNCcFppQW9ZVWwwWlcwdWEyVjVLU0I3WEc0Z0lDQWdJQ0FnSUNBZ0lDQnBaaUFvWWt0bGVYTXVhR0Z6VDNkdVVISnZjR1Z5ZEhrb1lVbDBaVzB1YTJWNUtTa2dlMXh1SUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQzh2SUUxaGRHTm9JSFZ3SUhSb1pTQnZiR1FnYTJWNWMxeHVJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lHbDBaVzFKYm1SbGVDQTlJR0pMWlhselcyRkpkR1Z0TG10bGVWMWNiaUFnSUNBZ0lDQWdJQ0FnSUNBZ0lDQnVaWGREYUdsc1pISmxiaTV3ZFhOb0tHSkRhR2xzWkhKbGJsdHBkR1Z0U1c1a1pYaGRLVnh1WEc0Z0lDQWdJQ0FnSUNBZ0lDQjlJR1ZzYzJVZ2UxeHVJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDOHZJRkpsYlc5MlpTQnZiR1FnYTJWNVpXUWdhWFJsYlhOY2JpQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNCcGRHVnRTVzVrWlhnZ1BTQnBJQzBnWkdWc1pYUmxaRWwwWlcxekt5dGNiaUFnSUNBZ0lDQWdJQ0FnSUNBZ0lDQnVaWGREYUdsc1pISmxiaTV3ZFhOb0tHNTFiR3dwWEc0Z0lDQWdJQ0FnSUNBZ0lDQjlYRzRnSUNBZ0lDQWdJSDBnWld4elpTQjdYRzRnSUNBZ0lDQWdJQ0FnSUNBdkx5Qk5ZWFJqYUNCMGFHVWdhWFJsYlNCcGJpQmhJSGRwZEdnZ2RHaGxJRzVsZUhRZ1puSmxaU0JwZEdWdElHbHVJR0pjYmlBZ0lDQWdJQ0FnSUNBZ0lHbG1JQ2htY21WbFNXNWtaWGdnUENCbWNtVmxRMjkxYm5RcElIdGNiaUFnSUNBZ0lDQWdJQ0FnSUNBZ0lDQnBkR1Z0U1c1a1pYZ2dQU0JpUm5KbFpWdG1jbVZsU1c1a1pYZ3JLMTFjYmlBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0J1WlhkRGFHbHNaSEpsYmk1d2RYTm9LR0pEYUdsc1pISmxibHRwZEdWdFNXNWtaWGhkS1Z4dUlDQWdJQ0FnSUNBZ0lDQWdmU0JsYkhObElIdGNiaUFnSUNBZ0lDQWdJQ0FnSUNBZ0lDQXZMeUJVYUdWeVpTQmhjbVVnYm04Z1puSmxaU0JwZEdWdGN5QnBiaUJpSUhSdklHMWhkR05vSUhkcGRHaGNiaUFnSUNBZ0lDQWdJQ0FnSUNBZ0lDQXZMeUIwYUdVZ1puSmxaU0JwZEdWdGN5QnBiaUJoTENCemJ5QjBhR1VnWlhoMGNtRWdabkpsWlNCdWIyUmxjMXh1SUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQzh2SUdGeVpTQmtaV3hsZEdWa0xseHVJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lHbDBaVzFKYm1SbGVDQTlJR2tnTFNCa1pXeGxkR1ZrU1hSbGJYTXJLMXh1SUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJRzVsZDBOb2FXeGtjbVZ1TG5CMWMyZ29iblZzYkNsY2JpQWdJQ0FnSUNBZ0lDQWdJSDFjYmlBZ0lDQWdJQ0FnZlZ4dUlDQWdJSDFjYmx4dUlDQWdJSFpoY2lCc1lYTjBSbkpsWlVsdVpHVjRJRDBnWm5KbFpVbHVaR1Y0SUQ0OUlHSkdjbVZsTG14bGJtZDBhQ0EvWEc0Z0lDQWdJQ0FnSUdKRGFHbHNaSEpsYmk1c1pXNW5kR2dnT2x4dUlDQWdJQ0FnSUNCaVJuSmxaVnRtY21WbFNXNWtaWGhkWEc1Y2JpQWdJQ0F2THlCSmRHVnlZWFJsSUhSb2NtOTFaMmdnWWlCaGJtUWdZWEJ3Wlc1a0lHRnVlU0J1WlhjZ2EyVjVjMXh1SUNBZ0lDOHZJRThvVFNrZ2RHbHRaVnh1SUNBZ0lHWnZjaUFvZG1GeUlHb2dQU0F3T3lCcUlEd2dZa05vYVd4a2NtVnVMbXhsYm1kMGFEc2dhaXNyS1NCN1hHNGdJQ0FnSUNBZ0lIWmhjaUJ1WlhkSmRHVnRJRDBnWWtOb2FXeGtjbVZ1VzJwZFhHNWNiaUFnSUNBZ0lDQWdhV1lnS0c1bGQwbDBaVzB1YTJWNUtTQjdYRzRnSUNBZ0lDQWdJQ0FnSUNCcFppQW9JV0ZMWlhsekxtaGhjMDkzYmxCeWIzQmxjblI1S0c1bGQwbDBaVzB1YTJWNUtTa2dlMXh1SUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQzh2SUVGa1pDQmhibmtnYm1WM0lHdGxlV1ZrSUdsMFpXMXpYRzRnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdMeThnVjJVZ1lYSmxJR0ZrWkdsdVp5QnVaWGNnYVhSbGJYTWdkRzhnZEdobElHVnVaQ0JoYm1RZ2RHaGxiaUJ6YjNKMGFXNW5JSFJvWlcxY2JpQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBdkx5QnBiaUJ3YkdGalpTNGdTVzRnWm5WMGRYSmxJSGRsSUhOb2IzVnNaQ0JwYm5ObGNuUWdibVYzSUdsMFpXMXpJR2x1SUhCc1lXTmxMbHh1SUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJRzVsZDBOb2FXeGtjbVZ1TG5CMWMyZ29ibVYzU1hSbGJTbGNiaUFnSUNBZ0lDQWdJQ0FnSUgxY2JpQWdJQ0FnSUNBZ2ZTQmxiSE5sSUdsbUlDaHFJRDQ5SUd4aGMzUkdjbVZsU1c1a1pYZ3BJSHRjYmlBZ0lDQWdJQ0FnSUNBZ0lDOHZJRUZrWkNCaGJua2diR1ZtZEc5MlpYSWdibTl1TFd0bGVXVmtJR2wwWlcxelhHNGdJQ0FnSUNBZ0lDQWdJQ0J1WlhkRGFHbHNaSEpsYmk1d2RYTm9LRzVsZDBsMFpXMHBYRzRnSUNBZ0lDQWdJSDFjYmlBZ0lDQjlYRzVjYmlBZ0lDQjJZWElnYzJsdGRXeGhkR1VnUFNCdVpYZERhR2xzWkhKbGJpNXpiR2xqWlNncFhHNGdJQ0FnZG1GeUlITnBiWFZzWVhSbFNXNWtaWGdnUFNBd1hHNGdJQ0FnZG1GeUlISmxiVzkyWlhNZ1BTQmJYVnh1SUNBZ0lIWmhjaUJwYm5ObGNuUnpJRDBnVzExY2JpQWdJQ0IyWVhJZ2MybHRkV3hoZEdWSmRHVnRYRzVjYmlBZ0lDQm1iM0lnS0haaGNpQnJJRDBnTURzZ2F5QThJR0pEYUdsc1pISmxiaTVzWlc1bmRHZzdLU0I3WEc0Z0lDQWdJQ0FnSUhaaGNpQjNZVzUwWldSSmRHVnRJRDBnWWtOb2FXeGtjbVZ1VzJ0ZFhHNGdJQ0FnSUNBZ0lITnBiWFZzWVhSbFNYUmxiU0E5SUhOcGJYVnNZWFJsVzNOcGJYVnNZWFJsU1c1a1pYaGRYRzVjYmlBZ0lDQWdJQ0FnTHk4Z2NtVnRiM1psSUdsMFpXMXpYRzRnSUNBZ0lDQWdJSGRvYVd4bElDaHphVzExYkdGMFpVbDBaVzBnUFQwOUlHNTFiR3dnSmlZZ2MybHRkV3hoZEdVdWJHVnVaM1JvS1NCN1hHNGdJQ0FnSUNBZ0lDQWdJQ0J5WlcxdmRtVnpMbkIxYzJnb2NtVnRiM1psS0hOcGJYVnNZWFJsTENCemFXMTFiR0YwWlVsdVpHVjRMQ0J1ZFd4c0tTbGNiaUFnSUNBZ0lDQWdJQ0FnSUhOcGJYVnNZWFJsU1hSbGJTQTlJSE5wYlhWc1lYUmxXM05wYlhWc1lYUmxTVzVrWlhoZFhHNGdJQ0FnSUNBZ0lIMWNibHh1SUNBZ0lDQWdJQ0JwWmlBb0lYTnBiWFZzWVhSbFNYUmxiU0I4ZkNCemFXMTFiR0YwWlVsMFpXMHVhMlY1SUNFOVBTQjNZVzUwWldSSmRHVnRMbXRsZVNrZ2UxeHVJQ0FnSUNBZ0lDQWdJQ0FnTHk4Z2FXWWdkMlVnYm1WbFpDQmhJR3RsZVNCcGJpQjBhR2x6SUhCdmMybDBhVzl1TGk0dVhHNGdJQ0FnSUNBZ0lDQWdJQ0JwWmlBb2QyRnVkR1ZrU1hSbGJTNXJaWGtwSUh0Y2JpQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNCcFppQW9jMmx0ZFd4aGRHVkpkR1Z0SUNZbUlITnBiWFZzWVhSbFNYUmxiUzVyWlhrcElIdGNiaUFnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnTHk4Z2FXWWdZVzRnYVc1elpYSjBJR1J2WlhOdUozUWdjSFYwSUhSb2FYTWdhMlY1SUdsdUlIQnNZV05sTENCcGRDQnVaV1ZrY3lCMGJ5QnRiM1psWEc0Z0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lHbG1JQ2hpUzJWNWMxdHphVzExYkdGMFpVbDBaVzB1YTJWNVhTQWhQVDBnYXlBcklERXBJSHRjYmlBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJSEpsYlc5MlpYTXVjSFZ6YUNoeVpXMXZkbVVvYzJsdGRXeGhkR1VzSUhOcGJYVnNZWFJsU1c1a1pYZ3NJSE5wYlhWc1lYUmxTWFJsYlM1clpYa3BLVnh1SUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdjMmx0ZFd4aGRHVkpkR1Z0SUQwZ2MybHRkV3hoZEdWYmMybHRkV3hoZEdWSmJtUmxlRjFjYmlBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQzh2SUdsbUlIUm9aU0J5WlcxdmRtVWdaR2xrYmlkMElIQjFkQ0IwYUdVZ2QyRnVkR1ZrSUdsMFpXMGdhVzRnY0d4aFkyVXNJSGRsSUc1bFpXUWdkRzhnYVc1elpYSjBJR2wwWEc0Z0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0JwWmlBb0lYTnBiWFZzWVhSbFNYUmxiU0I4ZkNCemFXMTFiR0YwWlVsMFpXMHVhMlY1SUNFOVBTQjNZVzUwWldSSmRHVnRMbXRsZVNrZ2UxeHVJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJR2x1YzJWeWRITXVjSFZ6YUNoN2EyVjVPaUIzWVc1MFpXUkpkR1Z0TG10bGVTd2dkRzg2SUd0OUtWeHVJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ2ZWeHVJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0x5OGdhWFJsYlhNZ1lYSmxJRzFoZEdOb2FXNW5MQ0J6YnlCemEybHdJR0ZvWldGa1hHNGdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNCbGJITmxJSHRjYmlBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNCemFXMTFiR0YwWlVsdVpHVjRLeXRjYmlBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJSDFjYmlBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ2ZWeHVJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0JsYkhObElIdGNiaUFnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lHbHVjMlZ5ZEhNdWNIVnphQ2g3YTJWNU9pQjNZVzUwWldSSmRHVnRMbXRsZVN3Z2RHODZJR3Q5S1Z4dUlDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQjlYRzRnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdmVnh1SUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJR1ZzYzJVZ2UxeHVJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0JwYm5ObGNuUnpMbkIxYzJnb2UydGxlVG9nZDJGdWRHVmtTWFJsYlM1clpYa3NJSFJ2T2lCcmZTbGNiaUFnSUNBZ0lDQWdJQ0FnSUNBZ0lDQjlYRzRnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdheXNyWEc0Z0lDQWdJQ0FnSUNBZ0lDQjlYRzRnSUNBZ0lDQWdJQ0FnSUNBdkx5QmhJR3RsZVNCcGJpQnphVzExYkdGMFpTQm9ZWE1nYm04Z2JXRjBZMmhwYm1jZ2QyRnVkR1ZrSUd0bGVTd2djbVZ0YjNabElHbDBYRzRnSUNBZ0lDQWdJQ0FnSUNCbGJITmxJR2xtSUNoemFXMTFiR0YwWlVsMFpXMGdKaVlnYzJsdGRXeGhkR1ZKZEdWdExtdGxlU2tnZTF4dUlDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUhKbGJXOTJaWE11Y0hWemFDaHlaVzF2ZG1Vb2MybHRkV3hoZEdVc0lITnBiWFZzWVhSbFNXNWtaWGdzSUhOcGJYVnNZWFJsU1hSbGJTNXJaWGtwS1Z4dUlDQWdJQ0FnSUNBZ0lDQWdmVnh1SUNBZ0lDQWdJQ0I5WEc0Z0lDQWdJQ0FnSUdWc2MyVWdlMXh1SUNBZ0lDQWdJQ0FnSUNBZ2MybHRkV3hoZEdWSmJtUmxlQ3NyWEc0Z0lDQWdJQ0FnSUNBZ0lDQnJLeXRjYmlBZ0lDQWdJQ0FnZlZ4dUlDQWdJSDFjYmx4dUlDQWdJQzh2SUhKbGJXOTJaU0JoYkd3Z2RHaGxJSEpsYldGcGJtbHVaeUJ1YjJSbGN5Qm1jbTl0SUhOcGJYVnNZWFJsWEc0Z0lDQWdkMmhwYkdVb2MybHRkV3hoZEdWSmJtUmxlQ0E4SUhOcGJYVnNZWFJsTG14bGJtZDBhQ2tnZTF4dUlDQWdJQ0FnSUNCemFXMTFiR0YwWlVsMFpXMGdQU0J6YVcxMWJHRjBaVnR6YVcxMWJHRjBaVWx1WkdWNFhWeHVJQ0FnSUNBZ0lDQnlaVzF2ZG1WekxuQjFjMmdvY21WdGIzWmxLSE5wYlhWc1lYUmxMQ0J6YVcxMWJHRjBaVWx1WkdWNExDQnphVzExYkdGMFpVbDBaVzBnSmlZZ2MybHRkV3hoZEdWSmRHVnRMbXRsZVNrcFhHNGdJQ0FnZlZ4dVhHNGdJQ0FnTHk4Z1NXWWdkR2hsSUc5dWJIa2diVzkyWlhNZ2QyVWdhR0YyWlNCaGNtVWdaR1ZzWlhSbGN5QjBhR1Z1SUhkbElHTmhiaUJxZFhOMFhHNGdJQ0FnTHk4Z2JHVjBJSFJvWlNCa1pXeGxkR1VnY0dGMFkyZ2djbVZ0YjNabElIUm9aWE5sSUdsMFpXMXpMbHh1SUNBZ0lHbG1JQ2h5WlcxdmRtVnpMbXhsYm1kMGFDQTlQVDBnWkdWc1pYUmxaRWwwWlcxeklDWW1JQ0ZwYm5ObGNuUnpMbXhsYm1kMGFDa2dlMXh1SUNBZ0lDQWdJQ0J5WlhSMWNtNGdlMXh1SUNBZ0lDQWdJQ0FnSUNBZ1kyaHBiR1J5Wlc0NklHNWxkME5vYVd4a2NtVnVMRnh1SUNBZ0lDQWdJQ0FnSUNBZ2JXOTJaWE02SUc1MWJHeGNiaUFnSUNBZ0lDQWdmVnh1SUNBZ0lIMWNibHh1SUNBZ0lISmxkSFZ5YmlCN1hHNGdJQ0FnSUNBZ0lHTm9hV3hrY21WdU9pQnVaWGREYUdsc1pISmxiaXhjYmlBZ0lDQWdJQ0FnYlc5MlpYTTZJSHRjYmlBZ0lDQWdJQ0FnSUNBZ0lISmxiVzkyWlhNNklISmxiVzkyWlhNc1hHNGdJQ0FnSUNBZ0lDQWdJQ0JwYm5ObGNuUnpPaUJwYm5ObGNuUnpYRzRnSUNBZ0lDQWdJSDFjYmlBZ0lDQjlYRzU5WEc1Y2JtWjFibU4wYVc5dUlISmxiVzkyWlNoaGNuSXNJR2x1WkdWNExDQnJaWGtwSUh0Y2JpQWdJQ0JoY25JdWMzQnNhV05sS0dsdVpHVjRMQ0F4S1Z4dVhHNGdJQ0FnY21WMGRYSnVJSHRjYmlBZ0lDQWdJQ0FnWm5KdmJUb2dhVzVrWlhnc1hHNGdJQ0FnSUNBZ0lHdGxlVG9nYTJWNVhHNGdJQ0FnZlZ4dWZWeHVYRzVtZFc1amRHbHZiaUJyWlhsSmJtUmxlQ2hqYUdsc1pISmxiaWtnZTF4dUlDQWdJSFpoY2lCclpYbHpJRDBnZTMxY2JpQWdJQ0IyWVhJZ1puSmxaU0E5SUZ0ZFhHNGdJQ0FnZG1GeUlHeGxibWQwYUNBOUlHTm9hV3hrY21WdUxteGxibWQwYUZ4dVhHNGdJQ0FnWm05eUlDaDJZWElnYVNBOUlEQTdJR2tnUENCc1pXNW5kR2c3SUdrckt5a2dlMXh1SUNBZ0lDQWdJQ0IyWVhJZ1kyaHBiR1FnUFNCamFHbHNaSEpsYmx0cFhWeHVYRzRnSUNBZ0lDQWdJR2xtSUNoamFHbHNaQzVyWlhrcElIdGNiaUFnSUNBZ0lDQWdJQ0FnSUd0bGVYTmJZMmhwYkdRdWEyVjVYU0E5SUdsY2JpQWdJQ0FnSUNBZ2ZTQmxiSE5sSUh0Y2JpQWdJQ0FnSUNBZ0lDQWdJR1p5WldVdWNIVnphQ2hwS1Z4dUlDQWdJQ0FnSUNCOVhHNGdJQ0FnZlZ4dVhHNGdJQ0FnY21WMGRYSnVJSHRjYmlBZ0lDQWdJQ0FnYTJWNWN6b2dhMlY1Y3l3Z0lDQWdJQzh2SUVFZ2FHRnphQ0J2WmlCclpYa2dibUZ0WlNCMGJ5QnBibVJsZUZ4dUlDQWdJQ0FnSUNCbWNtVmxPaUJtY21WbElDQWdJQ0FnTHk4Z1FXNGdZWEp5WVhrZ2IyWWdkVzVyWlhsbFpDQnBkR1Z0SUdsdVpHbGpaWE5jYmlBZ0lDQjlYRzU5WEc1Y2JtWjFibU4wYVc5dUlHRndjR1Z1WkZCaGRHTm9LR0Z3Y0d4NUxDQndZWFJqYUNrZ2UxeHVJQ0FnSUdsbUlDaGhjSEJzZVNrZ2UxeHVJQ0FnSUNBZ0lDQnBaaUFvYVhOQmNuSmhlU2hoY0hCc2VTa3BJSHRjYmlBZ0lDQWdJQ0FnSUNBZ0lHRndjR3g1TG5CMWMyZ29jR0YwWTJncFhHNGdJQ0FnSUNBZ0lIMGdaV3h6WlNCN1hHNGdJQ0FnSUNBZ0lDQWdJQ0JoY0hCc2VTQTlJRnRoY0hCc2VTd2djR0YwWTJoZFhHNGdJQ0FnSUNBZ0lIMWNibHh1SUNBZ0lDQWdJQ0J5WlhSMWNtNGdZWEJ3YkhsY2JpQWdJQ0I5SUdWc2MyVWdlMXh1SUNBZ0lDQWdJQ0J5WlhSMWNtNGdjR0YwWTJoY2JpQWdJQ0I5WEc1OVhHNWNibjBzZTF3aUxpNHZkbTV2WkdVdmFHRnVaR3hsTFhSb2RXNXJYQ0k2TWpRc1hDSXVMaTkyYm05a1pTOXBjeTEwYUhWdWExd2lPakkxTEZ3aUxpNHZkbTV2WkdVdmFYTXRkbTV2WkdWY0lqb3lOeXhjSWk0dUwzWnViMlJsTDJsekxYWjBaWGgwWENJNk1qZ3NYQ0l1TGk5MmJtOWtaUzlwY3kxM2FXUm5aWFJjSWpveU9TeGNJaTR1TDNadWIyUmxMM1p3WVhSamFGd2lPak15TEZ3aUxpOWthV1ptTFhCeWIzQnpYQ0k2TXpRc1hDSjRMV2x6TFdGeWNtRjVYQ0k2TVRKOVhYMHNlMzBzV3pSZEtTZzBLVnh1ZlNrN1hHNWNibVY0Y0c5eWRDQmtaV1poZFd4MElGWnBjblIxWVd4RVQwMDdYRzRpWFN3aWMyOTFjbU5sVW05dmRDSTZJaTl6YjNWeVkyVXZJbjA9XG4iLCJpbXBvcnQgQ29yZSBmcm9tICcuL2xpYi9jb3JlJztcbmltcG9ydCBFbnVtIGZyb20gJy4vbGliL2VudW0nO1xuaW1wb3J0IFZpcnR1YWxET00gZnJvbSAnLi9saWIvdmlydHVhbC1kb20nO1xuXG5leHBvcnQgZGVmYXVsdCB7XG4gIENvcmUsXG4gIEVudW0sXG4gIFZpcnR1YWxET01cbn07XG4vLyMgc291cmNlTWFwcGluZ1VSTD1kYXRhOmFwcGxpY2F0aW9uL2pzb247YmFzZTY0LGV5SjJaWEp6YVc5dUlqb3pMQ0p6YjNWeVkyVnpJanBiSW1Wc2FYaHBjaTVxY3lKZExDSnVZVzFsY3lJNlcxMHNJbTFoY0hCcGJtZHpJam9pUVVGQlFTeFBRVUZQTEVsQlFWQXNUVUZCYVVJc1dVRkJha0k3UVVGRFFTeFBRVUZQTEVsQlFWQXNUVUZCYVVJc1dVRkJha0k3UVVGRFFTeFBRVUZQTEZWQlFWQXNUVUZCZFVJc2JVSkJRWFpDT3p0QlFVVkJMR1ZCUVdVN1FVRkRZaXhOUVVSaE8wRkJSV0lzVFVGR1lUdEJRVWRpTEZsQlNHRTdRMEZCWmlJc0ltWnBiR1VpT2lKbGJHbDRhWEl1YW5NaUxDSnpiM1Z5WTJWelEyOXVkR1Z1ZENJNld5SnBiWEJ2Y25RZ1EyOXlaU0JtY205dElDY3VMMnhwWWk5amIzSmxKenRjYm1sdGNHOXlkQ0JGYm5WdElHWnliMjBnSnk0dmJHbGlMMlZ1ZFcwbk8xeHVhVzF3YjNKMElGWnBjblIxWVd4RVQwMGdabkp2YlNBbkxpOXNhV0l2ZG1seWRIVmhiQzFrYjIwbk8xeHVYRzVsZUhCdmNuUWdaR1ZtWVhWc2RDQjdYRzRnSUVOdmNtVXNYRzRnSUVWdWRXMHNYRzRnSUZacGNuUjFZV3hFVDAxY2JuMDdYRzRpWFN3aWMyOTFjbU5sVW05dmRDSTZJaTl6YjNWeVkyVXZJbjA9XG4iXSwibmFtZXMiOlsiUHJpbWl0aXZlcy5QSUQiXSwibWFwcGluZ3MiOiJBQUVBLE1BQU0sT0FBTyxDQUFDOztFQUVaLFdBQVcsR0FBRztJQUNaLElBQUksQ0FBQyxRQUFRLEdBQUcsRUFBRSxDQUFDO0dBQ3BCOztFQUVELE9BQU8sQ0FBQyxPQUFPLEVBQUU7SUFDZixJQUFJLENBQUMsUUFBUSxDQUFDLElBQUksQ0FBQyxPQUFPLENBQUMsQ0FBQztJQUM1QixPQUFPLE9BQU8sQ0FBQztHQUNoQjs7RUFFRCxHQUFHLEdBQUc7SUFDSixPQUFPLElBQUksQ0FBQyxRQUFRLENBQUM7R0FDdEI7O0VBRUQsT0FBTyxHQUFHO0lBQ1IsT0FBTyxJQUFJLENBQUMsUUFBUSxDQUFDLE1BQU0sS0FBSyxDQUFDLENBQUM7R0FDbkM7O0VBRUQsUUFBUSxDQUFDLEtBQUssRUFBRTtJQUNkLElBQUksQ0FBQyxRQUFRLENBQUMsTUFBTSxDQUFDLEtBQUssRUFBRSxDQUFDLENBQUMsQ0FBQztHQUNoQztDQUNGOzthQ3hCYztFQUNi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QUFDO0dBQ2Q7O0VBRUQsT0FBTyxjQUFjLENBQUMsQ0FBQyxFQUFFO0lBQ3ZCLElBQUksS0FBSyxHQUFHLEVBQUUsQ0FBQzs7SUFFZixJQUFJLEdBQUcsR0FBRyxJQUFJLFdBQVcsQ0FBQyxDQUFDLENBQUMsQ0FBQztJQUM3QixJQUFJLFlBQVksQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDLENBQUMsR0FBRyxDQUFDLENBQUM7O0lBRTdCLElBQUksV0FBVyxHQUFHLElBQUksV0FBVyxDQUFDLEdBQUcsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDO0lBQzFDLElBQUksV0FBVyxHQUFHLElBQUksV0FBVyxDQUFDLEdBQUcsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDOztJQUUxQyxLQUFLLENBQUMsSUFBSSxDQUFDLFdBQVcsSUFBSSxFQUFFLEdBQUcsSUFBSSxDQUFDLENBQUM7SUFDckMsS0FBSyxDQUFDLElBQUksQ0FBQyxXQUFXLElBQUksRUFBRSxHQUFHLElBQUksQ0FBQyxDQUFDO0lBQ3JDLEtBQUssQ0FBQyxJQUFJLENBQUMsV0FBVyxJQUFJLENBQUMsR0FBRyxJQUFJLENBQUMsQ0FBQztJQUNwQyxLQUFLLENBQUMsSUFBSSxDQUFDLFdBQVcsR0FBRyxJQUFJLENBQUMsQ0FBQzs7SUFFL0IsS0FBSyxDQUFDLElBQUksQ0FBQyxXQUFXLElBQUksRUFBRSxHQUFHLElBQUksQ0FBQyxDQUFDO0lBQ3JDLEtBQUssQ0FBQyxJQUFJLENBQUMsV0FBVyxJQUFJLEVBQUUsR0FBRyxJQUFJLENBQUMsQ0FBQztJQUNyQyxLQUFLLENBQUMsSUFBSSxDQUFDLFdBQVcsSUFBSSxDQUFDLEdBQUcsSUFBSSxDQUFDLENBQUM7SUFDcEMsS0FBSyxDQUFDLElBQUksQ0FBQyxXQUFXLEdBQUcsSUFBSSxDQUFDLENBQUM7O0lBRS9CLE9BQU8sS0FBSyxDQUFDO0dBQ2Q7Q0FDRjs7QUNyU00sTUFBTSxRQUFRLENBQUM7O0VBRXBCLFdBQVcsQ0FBQyxJQUFJLEdBQUcsSUFBSSxFQUFFO0lBQ3ZCLElBQUksQ0FBQyxJQUFJLEdB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 \ No newline at end of file +//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiRWxpeGlyLmpzIiwic291cmNlcyI6WyIuLi9zcmMvZWxpeGlyc2NyaXB0L2xpYi9jb3JlL3Byb2Nlc3Nlcy9tYWlsYm94LmpzIiwiLi4vc3JjL2VsaXhpcnNjcmlwdC9saWIvY29yZS9wcm9jZXNzZXMvc3RhdGVzLmpzIiwiLi4vc3JjL2VsaXhpcnNjcmlwdC9saWIvY29yZS9wcm9jZXNzZXMvcHJvY2Vzcy5qcyIsIi4uL3NyYy9lbGl4aXJzY3JpcHQvbGliL2NvcmUvcHJpbWl0aXZlcy5qcyIsIi4uL3NyYy9lbGl4aXJzY3JpcHQvbGliL2NvcmUvcHJvY2Vzc2VzL3Byb2Nlc3Nfc3lzdGVtLmpzIiwiLi4vc3JjL2VsaXhpcnNjcmlwdC9saWIvY29yZS9iaXRfc3RyaW5nLmpzIiwiLi4vc3JjL2VsaXhpcnNjcmlwdC9saWIvY29yZS9wYXR0ZXJucy90eXBlcy5qcyIsIi4uL3NyYy9lbGl4aXJzY3JpcHQvbGliL2NvcmUvcGF0dGVybnMvY2hlY2tzLmpzIiwiLi4vc3JjL2VsaXhpcnNjcmlwdC9saWIvY29yZS9wYXR0ZXJucy9yZXNvbHZlcnMuanMiLCIuLi9zcmMvZWxpeGlyc2NyaXB0L2xpYi9jb3JlL3BhdHRlcm5zL21hdGNoLmpzIiwiLi4vc3JjL2VsaXhpcnNjcmlwdC9saWIvY29yZS9wYXR0ZXJucy9kZWZtYXRjaC5qcyIsIi4uL3NyYy9lbGl4aXJzY3JpcHQvbGliL2NvcmUvcGF0dGVybnMuanMiLCIuLi9zcmMvZWxpeGlyc2NyaXB0L2xpYi9jb3JlL3Byb3RvY29sLmpzIiwiLi4vc3JjL2VsaXhpcnNjcmlwdC9saWIvY29yZS9mdW5jdGlvbnMuanMiLCIuLi9zcmMvZWxpeGlyc2NyaXB0L2xpYi9jb3JlL3NwZWNpYWxfZm9ybXMuanMiLCIuLi9zcmMvZWxpeGlyc2NyaXB0L2xpYi9jb3JlLmpzIiwiLi4vc3JjL2VsaXhpcnNjcmlwdC9saWIvZW51bS5qcyIsIi4uL3NyYy9lbGl4aXJzY3JpcHQvbGliL3ZpcnR1YWwtZG9tLmpzIiwiLi4vc3JjL2VsaXhpcnNjcmlwdC9lbGl4aXIuanMiXSwic291cmNlc0NvbnRlbnQiOlsiXCJ1c2Ugc3RyaWN0XCI7XG5cbmNsYXNzIE1haWxib3gge1xuXG4gIGNvbnN0cnVjdG9yKCkge1xuICAgIHRoaXMubWVzc2FnZXMgPSBbXTtcbiAgfVxuXG4gIGRlbGl2ZXIobWVzc2FnZSkge1xuICAgIHRoaXMubWVzc2FnZXMucHVzaChtZXNzYWdlKTtcbiAgICByZXR1cm4gbWVzc2FnZTtcbiAgfVxuXG4gIGdldCgpIHtcbiAgICByZXR1cm4gdGhpcy5tZXNzYWdlcztcbiAgfVxuXG4gIGlzRW1wdHkoKSB7XG4gICAgcmV0dXJuIHRoaXMubWVzc2FnZXMubGVuZ3RoID09PSAwO1xuICB9XG5cbiAgcmVtb3ZlQXQoaW5kZXgpIHtcbiAgICB0aGlzLm1lc3NhZ2VzLnNwbGljZShpbmRleCwgMSk7XG4gIH1cbn1cblxuZXhwb3J0IGRlZmF1bHQgTWFpbGJveDtcbi8vIyBzb3VyY2VNYXBwaW5nVVJMPWRhdGE6YXBwbGljYXRpb24vanNvbjtiYXNlNjQsZXlKMlpYSnphVzl1SWpvekxDSnpiM1Z5WTJWeklqcGJJbXhwWWk5amIzSmxMM0J5YjJObGMzTmxjeTl0WVdsc1ltOTRMbXB6SWwwc0ltNWhiV1Z6SWpwYlhTd2liV0Z3Y0dsdVozTWlPaUpCUVVGQk96dEJRVWxCTEUxQlFVMHNUMEZCVGl4RFFVRmhPenRCUVVkWUxHZENRVUZoTzBGQlExZ3NVMEZCU3l4UlFVRk1MRWRCUVdkQ0xFVkJRV2hDTEVOQlJGYzdSMEZCWWpzN1FVRkpRU3hWUVVGUkxFOUJRVklzUlVGQmNVSTdRVUZEYmtJc1UwRkJTeXhSUVVGTUxFTkJRV01zU1VGQlpDeERRVUZ0UWl4UFFVRnVRaXhGUVVSdFFqdEJRVVZ1UWl4WFFVRlBMRTlCUVZBc1EwRkdiVUk3UjBGQmNrSTdPMEZCUzBFc1VVRkJTenRCUVVOSUxGZEJRVThzUzBGQlN5eFJRVUZNTEVOQlJFbzdSMEZCVERzN1FVRkpRU3haUVVGVE8wRkJRMUFzVjBGQlR5eExRVUZMTEZGQlFVd3NRMEZCWXl4TlFVRmtMRXRCUVhsQ0xFTkJRWHBDTEVOQlJFRTdSMEZCVkRzN1FVRkpRU3hYUVVGVExFdEJRVlFzUlVGQlpUdEJRVU5pTEZOQlFVc3NVVUZCVEN4RFFVRmpMRTFCUVdRc1EwRkJjVUlzUzBGQmNrSXNSVUZCTkVJc1EwRkJOVUlzUlVGRVlUdEhRVUZtTzBOQmNFSkdPenRCUVhsQ1FTeGxRVUZsTEU5QlFXWWlMQ0ptYVd4bElqb2liR2xpTDJOdmNtVXZjSEp2WTJWemMyVnpMMjFoYVd4aWIzZ3Vhbk1pTENKemIzVnlZMlZ6UTI5dWRHVnVkQ0k2V3lKY0luVnpaU0J6ZEhKcFkzUmNJanRjYmx4dUx5b2dRR1pzYjNjZ0tpOWNibHh1WTJ4aGMzTWdUV0ZwYkdKdmVIdGNiaUFnYldWemMyRm5aWE02SUVGeWNtRjVQR0Z1ZVQ1Y2JseHVJQ0JqYjI1emRISjFZM1J2Y2lncGUxeHVJQ0FnSUhSb2FYTXViV1Z6YzJGblpYTWdQU0JiWFR0Y2JpQWdmVnh1WEc0Z0lHUmxiR2wyWlhJb2JXVnpjMkZuWlRvZ1lXNTVLWHRjYmlBZ0lDQjBhR2x6TG0xbGMzTmhaMlZ6TG5CMWMyZ29iV1Z6YzJGblpTazdYRzRnSUNBZ2NtVjBkWEp1SUcxbGMzTmhaMlU3WEc0Z0lIMWNibHh1SUNCblpYUW9LWHRjYmlBZ0lDQnlaWFIxY200Z2RHaHBjeTV0WlhOellXZGxjenRjYmlBZ2ZWeHVYRzRnSUdselJXMXdkSGtvS1h0Y2JpQWdJQ0J5WlhSMWNtNGdkR2hwY3k1dFpYTnpZV2RsY3k1c1pXNW5kR2dnUFQwOUlEQTdYRzRnSUgxY2JseHVJQ0J5WlcxdmRtVkJkQ2hwYm1SbGVDbDdYRzRnSUNBZ2RHaHBjeTV0WlhOellXZGxjeTV6Y0d4cFkyVW9hVzVrWlhnc0lERXBPMXh1SUNCOVhHNTlYRzVjYm1WNGNHOXlkQ0JrWldaaGRXeDBJRTFoYVd4aWIzZzdJbDBzSW5OdmRYSmpaVkp2YjNRaU9pSXZjMjkxY21ObEx5SjlcbiIsImV4cG9ydCBkZWZhdWx0IHtcbiAgTk9STUFMOiBTeW1ib2wuZm9yKFwibm9ybWFsXCIpLFxuICBLSUxMOiBTeW1ib2wuZm9yKFwia2lsbFwiKSxcbiAgU1VTUEVORDogU3ltYm9sLmZvcihcInN1c3BlbmRcIiksXG4gIENPTlRJTlVFOiBTeW1ib2wuZm9yKFwiY29udGludWVcIiksXG4gIFJFQ0VJVkU6IFN5bWJvbC5mb3IoXCJyZWNlaXZlXCIpLFxuICBTRU5EOiBTeW1ib2wuZm9yKFwic2VuZFwiKSxcbiAgU0xFRVBJTkc6IFN5bWJvbC5mb3IoXCJzbGVlcGluZ1wiKSxcbiAgUlVOTklORzogU3ltYm9sLmZvcihcInJ1bm5pbmdcIiksXG4gIFNVU1BFTkRFRDogU3ltYm9sLmZvcihcInN1c3BlbmRlZFwiKSxcbiAgU1RPUFBFRDogU3ltYm9sLmZvcihcInN0b3BwZWRcIiksXG4gIFNMRUVQOiBTeW1ib2wuZm9yKFwic2xlZXBcIiksXG4gIEVYSVQ6IFN5bWJvbC5mb3IoXCJleGl0XCIpLFxuICBOT01BVENIOiBTeW1ib2wuZm9yKFwibm9fbWF0Y2hcIilcbn07XG4vLyMgc291cmNlTWFwcGluZ1VSTD1kYXRhOmFwcGxpY2F0aW9uL2pzb247YmFzZTY0LGV5SjJaWEp6YVc5dUlqb3pMQ0p6YjNWeVkyVnpJanBiSW14cFlpOWpiM0psTDNCeWIyTmxjM05sY3k5emRHRjBaWE11YW5NaVhTd2libUZ0WlhNaU9sdGRMQ0p0WVhCd2FXNW5jeUk2SWtGQlFVRXNaVUZCWlR0QlFVTmlMRlZCUVZFc1QwRkJUeXhIUVVGUUxFTkJRVmNzVVVGQldDeERRVUZTTzBGQlEwRXNVVUZCVFN4UFFVRlBMRWRCUVZBc1EwRkJWeXhOUVVGWUxFTkJRVTQ3UVVGRFFTeFhRVUZUTEU5QlFVOHNSMEZCVUN4RFFVRlhMRk5CUVZnc1EwRkJWRHRCUVVOQkxGbEJRVlVzVDBGQlR5eEhRVUZRTEVOQlFWY3NWVUZCV0N4RFFVRldPMEZCUTBFc1YwRkJVeXhQUVVGUExFZEJRVkFzUTBGQlZ5eFRRVUZZTEVOQlFWUTdRVUZEUVN4UlFVRk5MRTlCUVU4c1IwRkJVQ3hEUVVGWExFMUJRVmdzUTBGQlRqdEJRVU5CTEZsQlFWVXNUMEZCVHl4SFFVRlFMRU5CUVZjc1ZVRkJXQ3hEUVVGV08wRkJRMEVzVjBGQlV5eFBRVUZQTEVkQlFWQXNRMEZCVnl4VFFVRllMRU5CUVZRN1FVRkRRU3hoUVVGWExFOUJRVThzUjBGQlVDeERRVUZYTEZkQlFWZ3NRMEZCV0R0QlFVTkJMRmRCUVZNc1QwRkJUeXhIUVVGUUxFTkJRVmNzVTBGQldDeERRVUZVTzBGQlEwRXNVMEZCVHl4UFFVRlBMRWRCUVZBc1EwRkJWeXhQUVVGWUxFTkJRVkE3UVVGRFFTeFJRVUZOTEU5QlFVOHNSMEZCVUN4RFFVRlhMRTFCUVZnc1EwRkJUanRCUVVOQkxGZEJRVk1zVDBGQlR5eEhRVUZRTEVOQlFWY3NWVUZCV0N4RFFVRlVPME5CWWtZaUxDSm1hV3hsSWpvaWJHbGlMMk52Y21VdmNISnZZMlZ6YzJWekwzTjBZWFJsY3k1cWN5SXNJbk52ZFhKalpYTkRiMjUwWlc1MElqcGJJbVY0Y0c5eWRDQmtaV1poZFd4MElIdGNiaUFnVGs5U1RVRk1PaUJUZVcxaWIyd3VabTl5S0Z3aWJtOXliV0ZzWENJcExGeHVJQ0JMU1V4TU9pQlRlVzFpYjJ3dVptOXlLRndpYTJsc2JGd2lLU3hjYmlBZ1UxVlRVRVZPUkRvZ1UzbHRZbTlzTG1admNpaGNJbk4xYzNCbGJtUmNJaWtzWEc0Z0lFTlBUbFJKVGxWRk9pQlRlVzFpYjJ3dVptOXlLRndpWTI5dWRHbHVkV1ZjSWlrc1hHNGdJRkpGUTBWSlZrVTZJRk41YldKdmJDNW1iM0lvWENKeVpXTmxhWFpsWENJcExGeHVJQ0JUUlU1RU9pQlRlVzFpYjJ3dVptOXlLRndpYzJWdVpGd2lLU3hjYmlBZ1UweEZSVkJKVGtjNklGTjViV0p2YkM1bWIzSW9YQ0p6YkdWbGNHbHVaMXdpS1N4Y2JpQWdVbFZPVGtsT1J6b2dVM2x0WW05c0xtWnZjaWhjSW5KMWJtNXBibWRjSWlrc1hHNGdJRk5WVTFCRlRrUkZSRG9nVTNsdFltOXNMbVp2Y2loY0luTjFjM0JsYm1SbFpGd2lLU3hjYmlBZ1UxUlBVRkJGUkRvZ1UzbHRZbTlzTG1admNpaGNJbk4wYjNCd1pXUmNJaWtzWEc0Z0lGTk1SVVZRT2lCVGVXMWliMnd1Wm05eUtGd2ljMnhsWlhCY0lpa3NYRzRnSUVWWVNWUTZJRk41YldKdmJDNW1iM0lvWENKbGVHbDBYQ0lwTEZ4dUlDQk9UMDFCVkVOSU9pQlRlVzFpYjJ3dVptOXlLRndpYm05ZmJXRjBZMmhjSWlsY2JuMGlYU3dpYzI5MWNtTmxVbTl2ZENJNklpOXpiM1Z5WTJVdkluMD1cbiIsIlwidXNlIHN0cmljdFwiO1xuXG5pbXBvcnQgTWFpbGJveCBmcm9tIFwiLi9tYWlsYm94XCI7XG5pbXBvcnQgU3RhdGVzIGZyb20gXCIuL3N0YXRlc1wiO1xuXG5jbGFzcyBQcm9jZXNzIHtcblxuICBjb25zdHJ1Y3RvcihwaWQsIG1haWxib3gpIHtcbiAgICB0aGlzLnBpZCA9IHBpZDtcbiAgICB0aGlzLm1haWxib3ggPSBtYWlsYm94O1xuICAgIHRoaXMuc3RhdHVzID0gU3RhdGVzLlNUT1BQRUQ7XG4gICAgdGhpcy5kaWN0ID0ge307XG4gIH1cbn1cblxuZXhwb3J0IGRlZmF1bHQgUHJvY2Vzcztcbi8vIyBzb3VyY2VNYXBwaW5nVVJMPWRhdGE6YXBwbGljYXRpb24vanNvbjtiYXNlNjQsZXlKMlpYSnphVzl1SWpvekxDSnpiM1Z5WTJWeklqcGJJbXhwWWk5amIzSmxMM0J5YjJObGMzTmxjeTl3Y205alpYTnpMbXB6SWwwc0ltNWhiV1Z6SWpwYlhTd2liV0Z3Y0dsdVozTWlPaUpCUVVGQk96dEJRVWRCTEU5QlFVOHNUMEZCVUN4TlFVRnZRaXhYUVVGd1FqdEJRVU5CTEU5QlFVOHNUVUZCVUN4TlFVRnRRaXhWUVVGdVFqczdRVUZGUVN4TlFVRk5MRTlCUVU0c1EwRkJZenM3UVVGTFdpeGpRVUZaTEVkQlFWb3NSVUZCZVVJc1QwRkJla0lzUlVGQk1FTTdRVUZEZUVNc1UwRkJTeXhIUVVGTUxFZEJRVmNzUjBGQldDeERRVVIzUXp0QlFVVjRReXhUUVVGTExFOUJRVXdzUjBGQlpTeFBRVUZtTEVOQlJuZERPMEZCUjNoRExGTkJRVXNzVFVGQlRDeEhRVUZqTEU5QlFVOHNUMEZCVUN4RFFVZ3dRanRCUVVsNFF5eFRRVUZMTEVsQlFVd3NSMEZCV1N4RlFVRmFMRU5CU25kRE8wZEJRVEZETzBOQlRFWTdPMEZCWVVFc1pVRkJaU3hQUVVGbUlpd2labWxzWlNJNklteHBZaTlqYjNKbEwzQnliMk5sYzNObGN5OXdjbTlqWlhOekxtcHpJaXdpYzI5MWNtTmxjME52Ym5SbGJuUWlPbHNpWENKMWMyVWdjM1J5YVdOMFhDSTdYRzVjYmk4cUlFQm1iRzkzSUNvdlhHNXBiWEJ2Y25RZ1RXRnBiR0p2ZUNCbWNtOXRJRndpTGk5dFlXbHNZbTk0WENJN1hHNXBiWEJ2Y25RZ1UzUmhkR1Z6SUdaeWIyMGdYQ0l1TDNOMFlYUmxjMXdpTzF4dVhHNWpiR0Z6Y3lCUWNtOWpaWE56SUh0Y2JpQWdjR2xrT2lCT2RXMWlaWEk3WEc0Z0lHMWhhV3hpYjNnNklFMWhhV3hpYjNnN1hHNGdJR1JwWTNRNklFOWlhbVZqZER0Y2JseHVJQ0JqYjI1emRISjFZM1J2Y2lod2FXUTZJRTUxYldKbGNpd2diV0ZwYkdKdmVEb2dUV0ZwYkdKdmVDbDdYRzRnSUNBZ2RHaHBjeTV3YVdRZ1BTQndhV1E3WEc0Z0lDQWdkR2hwY3k1dFlXbHNZbTk0SUQwZ2JXRnBiR0p2ZUR0Y2JpQWdJQ0IwYUdsekxuTjBZWFIxY3lBOUlGTjBZWFJsY3k1VFZFOVFVRVZFTzF4dUlDQWdJSFJvYVhNdVpHbGpkQ0E5SUh0OU8xeHVJQ0I5WEc1OVhHNWNibVY0Y0c5eWRDQmtaV1poZFd4MElGQnliMk5sYzNNN1hHNGlYU3dpYzI5MWNtTmxVbTl2ZENJNklpOXpiM1Z5WTJVdkluMD1cbiIsImNsYXNzIFR1cGxlIHtcblxuICBjb25zdHJ1Y3RvciguLi5hcmdzKSB7XG4gICAgdGhpcy52YWx1ZXMgPSBPYmplY3QuZnJlZXplKGFyZ3MpO1xuICAgIHRoaXMubGVuZ3RoID0gdGhpcy52YWx1ZXMubGVuZ3RoO1xuICB9XG5cbiAgZ2V0KGluZGV4KSB7XG4gICAgcmV0dXJuIHRoaXMudmFsdWVzW2luZGV4XTtcbiAgfVxuXG4gIGNvdW50KCkge1xuICAgIHJldHVybiB0aGlzLnZhbHVlcy5sZW5ndGg7XG4gIH1cblxuICBbU3ltYm9sLml0ZXJhdG9yXSgpIHtcbiAgICByZXR1cm4gdGhpcy52YWx1ZXNbU3ltYm9sLml0ZXJhdG9yXSgpO1xuICB9XG5cbiAgdG9TdHJpbmcoKSB7XG4gICAgdmFyIGksXG4gICAgICAgIHMgPSBcIlwiO1xuICAgIGZvciAoaSA9IDA7IGkgPCB0aGlzLnZhbHVlcy5sZW5ndGg7IGkrKykge1xuICAgICAgaWYgKHMgIT09IFwiXCIpIHtcbiAgICAgICAgcyArPSBcIiwgXCI7XG4gICAgICB9XG4gICAgICBzICs9IHRoaXMudmFsdWVzW2ldLnRvU3RyaW5nKCk7XG4gICAgfVxuXG4gICAgcmV0dXJuIFwie1wiICsgcyArIFwifVwiO1xuICB9XG5cbiAgcHV0X2VsZW0oaW5kZXgsIGVsZW0pIHtcbiAgICBpZiAoaW5kZXggPT09IHRoaXMubGVuZ3RoKSB7XG4gICAgICBsZXQgbmV3X3ZhbHVlcyA9IHRoaXMudmFsdWVzLmNvbmNhdChbZWxlbV0pO1xuICAgICAgcmV0dXJuIG5ldyBUdXBsZSguLi5uZXdfdmFsdWVzKTtcbiAgICB9XG5cbiAgICBsZXQgbmV3X3ZhbHVlcyA9IHRoaXMudmFsdWVzLmNvbmNhdChbXSk7XG4gICAgbmV3X3ZhbHVlcy5zcGxpY2UoaW5kZXgsIDAsIGVsZW0pO1xuICAgIHJldHVybiBuZXcgVHVwbGUoLi4ubmV3X3ZhbHVlcyk7XG4gIH1cblxuICByZW1vdmVfZWxlbShpbmRleCkge1xuICAgIGxldCBuZXdfdmFsdWVzID0gdGhpcy52YWx1ZXMuY29uY2F0KFtdKTtcbiAgICBuZXdfdmFsdWVzLnNwbGljZShpbmRleCwgMSk7XG4gICAgcmV0dXJuIG5ldyBUdXBsZSguLi5uZXdfdmFsdWVzKTtcbiAgfVxuXG59XG5cbmxldCBwcm9jZXNzX2NvdW50ZXIgPSAtMTtcblxuY2xhc3MgUElEIHtcbiAgY29uc3RydWN0b3IoKSB7XG4gICAgcHJvY2Vzc19jb3VudGVyID0gcHJvY2Vzc19jb3VudGVyICsgMTtcbiAgICB0aGlzLmlkID0gcHJvY2Vzc19jb3VudGVyO1xuICB9XG5cbiAgdG9TdHJpbmcoKSB7XG4gICAgcmV0dXJuIFwiUElEIzwwLlwiICsgdGhpcy5pZCArIFwiLjA+XCI7XG4gIH1cbn1cblxuY2xhc3MgSW50ZWdlciB7fVxuY2xhc3MgRmxvYXQge31cblxuZXhwb3J0IHsgUElELCBUdXBsZSwgSW50ZWdlciwgRmxvYXQgfTtcbi8vIyBzb3VyY2VNYXBwaW5nVVJMPWRhdGE6YXBwbGljYXRpb24vanNvbjtiYXNlNjQsZXlKMlpYSnphVzl1SWpvekxDSnpiM1Z5WTJWeklqcGJJbXhwWWk5amIzSmxMM0J5YVcxcGRHbDJaWE11YW5NaVhTd2libUZ0WlhNaU9sdGRMQ0p0WVhCd2FXNW5jeUk2SWtGQlFVRXNUVUZCVFN4TFFVRk9MRU5CUVZrN08wRkJSVllzWTBGQldTeEhRVUZITEVsQlFVZ3NSVUZCVVR0QlFVTnNRaXhUUVVGTExFMUJRVXdzUjBGQll5eFBRVUZQTEUxQlFWQXNRMEZCWXl4SlFVRmtMRU5CUVdRc1EwRkVhMEk3UVVGRmJFSXNVMEZCU3l4TlFVRk1MRWRCUVdNc1MwRkJTeXhOUVVGTUxFTkJRVmtzVFVGQldpeERRVVpKTzBkQlFYQkNPenRCUVV0QkxFMUJRVWtzUzBGQlNpeEZRVUZYTzBGQlExUXNWMEZCVHl4TFFVRkxMRTFCUVV3c1EwRkJXU3hMUVVGYUxFTkJRVkFzUTBGRVV6dEhRVUZZT3p0QlFVbEJMRlZCUVZFN1FVRkRUaXhYUVVGUExFdEJRVXNzVFVGQlRDeERRVUZaTEUxQlFWb3NRMEZFUkR0SFFVRlNPenRCUVVsQkxFZEJRVU1zVDBGQlR5eFJRVUZRTEVsQlFXMUNPMEZCUTJ4Q0xGZEJRVThzUzBGQlN5eE5RVUZNTEVOQlFWa3NUMEZCVHl4UlFVRlFMRU5CUVZvc1JVRkJVQ3hEUVVSclFqdEhRVUZ3UWpzN1FVRkpRU3hoUVVGWE8wRkJRMVFzVVVGQlNTeERRVUZLTzFGQlFVOHNTVUZCU1N4RlFVRktMRU5CUkVVN1FVRkZWQ3hUUVVGTExFbEJRVWtzUTBGQlNpeEZRVUZQTEVsQlFVa3NTMEZCU3l4TlFVRk1MRU5CUVZrc1RVRkJXaXhGUVVGdlFpeEhRVUZ3UXl4RlFVRjVRenRCUVVOMlF5eFZRVUZKTEUxQlFVMHNSVUZCVGl4RlFVRlZPMEZCUTFvc1lVRkJTeXhKUVVGTUxFTkJSRms3VDBGQlpEdEJRVWRCTEZkQlFVc3NTMEZCU3l4TlFVRk1MRU5CUVZrc1EwRkJXaXhGUVVGbExGRkJRV1lzUlVGQlRDeERRVXAxUXp0TFFVRjZRenM3UVVGUFFTeFhRVUZQTEUxQlFVMHNRMEZCVGl4SFFVRlZMRWRCUVZZc1EwRlVSVHRIUVVGWU96dEJRVmxCTEZkQlFWTXNTMEZCVkN4RlFVRm5RaXhKUVVGb1FpeEZRVUZ4UWp0QlFVTnVRaXhSUVVGSExGVkJRVlVzUzBGQlN5eE5RVUZNTEVWQlFWazdRVUZEZGtJc1ZVRkJTU3hoUVVGaExFdEJRVXNzVFVGQlRDeERRVUZaTEUxQlFWb3NRMEZCYlVJc1EwRkJReXhKUVVGRUxFTkJRVzVDTEVOQlFXSXNRMEZFYlVJN1FVRkZka0lzWVVGQlR5eEpRVUZKTEV0QlFVb3NRMEZCVlN4SFFVRkhMRlZCUVVnc1EwRkJha0lzUTBGR2RVSTdTMEZCZWtJN08wRkJTMEVzVVVGQlNTeGhRVUZoTEV0QlFVc3NUVUZCVEN4RFFVRlpMRTFCUVZvc1EwRkJiVUlzUlVGQmJrSXNRMEZCWWl4RFFVNWxPMEZCVDI1Q0xHVkJRVmNzVFVGQldDeERRVUZyUWl4TFFVRnNRaXhGUVVGNVFpeERRVUY2UWl4RlFVRTBRaXhKUVVFMVFpeEZRVkJ0UWp0QlFWRnVRaXhYUVVGUExFbEJRVWtzUzBGQlNpeERRVUZWTEVkQlFVY3NWVUZCU0N4RFFVRnFRaXhEUVZKdFFqdEhRVUZ5UWpzN1FVRlhRU3hqUVVGWkxFdEJRVm9zUlVGQmEwSTdRVUZEYUVJc1VVRkJTU3hoUVVGaExFdEJRVXNzVFVGQlRDeERRVUZaTEUxQlFWb3NRMEZCYlVJc1JVRkJia0lzUTBGQllpeERRVVJaTzBGQlJXaENMR1ZCUVZjc1RVRkJXQ3hEUVVGclFpeExRVUZzUWl4RlFVRjVRaXhEUVVGNlFpeEZRVVpuUWp0QlFVZG9RaXhYUVVGUExFbEJRVWtzUzBGQlNpeERRVUZWTEVkQlFVY3NWVUZCU0N4RFFVRnFRaXhEUVVoblFqdEhRVUZzUWpzN1EwRXhRMFk3TzBGQmJVUkJMRWxCUVVrc2EwSkJRV3RDTEVOQlFVTXNRMEZCUkRzN1FVRkZkRUlzVFVGQlRTeEhRVUZPTEVOQlFWVTdRVUZEVWl4blFrRkJZVHRCUVVOWUxITkNRVUZyUWl4clFrRkJhMElzUTBGQmJFSXNRMEZFVUR0QlFVVllMRk5CUVVzc1JVRkJUQ3hIUVVGVkxHVkJRVllzUTBGR1Z6dEhRVUZpT3p0QlFVdEJMR0ZCUVZVN1FVRkRVaXhYUVVGUExGbEJRVmtzUzBGQlN5eEZRVUZNTEVkQlFWVXNTMEZCZEVJc1EwRkVRenRIUVVGV08wTkJUa1k3TzBGQlYwRXNUVUZCVFN4UFFVRk9MRU5CUVdNc1JVRkJaRHRCUVVOQkxFMUJRVTBzUzBGQlRpeERRVUZaTEVWQlFWbzdPMEZCUlVFc1UwRkJVeXhIUVVGVUxFVkJRV01zUzBGQlpDeEZRVUZ4UWl4UFFVRnlRaXhGUVVFNFFpeExRVUU1UWlJc0ltWnBiR1VpT2lKc2FXSXZZMjl5WlM5d2NtbHRhWFJwZG1WekxtcHpJaXdpYzI5MWNtTmxjME52Ym5SbGJuUWlPbHNpWTJ4aGMzTWdWSFZ3YkdVZ2UxeHVYRzRnSUdOdmJuTjBjblZqZEc5eUtDNHVMbUZ5WjNNcGUxeHVJQ0FnSUhSb2FYTXVkbUZzZFdWeklEMGdUMkpxWldOMExtWnlaV1Y2WlNoaGNtZHpLVHRjYmlBZ0lDQjBhR2x6TG14bGJtZDBhQ0E5SUhSb2FYTXVkbUZzZFdWekxteGxibWQwYUR0Y2JpQWdmVnh1WEc0Z0lHZGxkQ2hwYm1SbGVDa2dlMXh1SUNBZ0lISmxkSFZ5YmlCMGFHbHpMblpoYkhWbGMxdHBibVJsZUYwN1hHNGdJSDFjYmx4dUlDQmpiM1Z1ZENncElIdGNiaUFnSUNCeVpYUjFjbTRnZEdocGN5NTJZV3gxWlhNdWJHVnVaM1JvTzF4dUlDQjlYRzVjYmlBZ1cxTjViV0p2YkM1cGRHVnlZWFJ2Y2wwb0tTQjdYRzRnSUNBZ2NtVjBkWEp1SUhSb2FYTXVkbUZzZFdWelcxTjViV0p2YkM1cGRHVnlZWFJ2Y2wwb0tUdGNiaUFnZlZ4dVhHNGdJSFJ2VTNSeWFXNW5LQ2tnZTF4dUlDQWdJSFpoY2lCcExDQnpJRDBnWENKY0lqdGNiaUFnSUNCbWIzSWdLR2tnUFNBd095QnBJRHdnZEdocGN5NTJZV3gxWlhNdWJHVnVaM1JvT3lCcEt5c3BJSHRjYmlBZ0lDQWdJR2xtSUNoeklDRTlQU0JjSWx3aUtTQjdYRzRnSUNBZ0lDQWdJSE1nS3owZ1hDSXNJRndpTzF4dUlDQWdJQ0FnZlZ4dUlDQWdJQ0FnY3lBclBTQjBhR2x6TG5aaGJIVmxjMXRwWFM1MGIxTjBjbWx1WnlncE8xeHVJQ0FnSUgxY2JseHVJQ0FnSUhKbGRIVnliaUJjSW50Y0lpQXJJSE1nS3lCY0luMWNJanRjYmlBZ2ZWeHVYRzRnSUhCMWRGOWxiR1Z0S0dsdVpHVjRMQ0JsYkdWdEtYdGNiaUFnSUNCcFppaHBibVJsZUNBOVBUMGdkR2hwY3k1c1pXNW5kR2dwZTF4dUlDQWdJQ0FnYkdWMElHNWxkMTkyWVd4MVpYTWdQU0IwYUdsekxuWmhiSFZsY3k1amIyNWpZWFFvVzJWc1pXMWRLVHRjYmlBZ0lDQWdJSEpsZEhWeWJpQnVaWGNnVkhWd2JHVW9MaTR1Ym1WM1gzWmhiSFZsY3lrN1hHNGdJQ0FnZlZ4dVhHNGdJQ0FnYkdWMElHNWxkMTkyWVd4MVpYTWdQU0IwYUdsekxuWmhiSFZsY3k1amIyNWpZWFFvVzEwcE8xeHVJQ0FnSUc1bGQxOTJZV3gxWlhNdWMzQnNhV05sS0dsdVpHVjRMQ0F3TENCbGJHVnRLVHRjYmlBZ0lDQnlaWFIxY200Z2JtVjNJRlIxY0d4bEtDNHVMbTVsZDE5MllXeDFaWE1wTzF4dUlDQjlYRzVjYmlBZ2NtVnRiM1psWDJWc1pXMG9hVzVrWlhncGUxeHVJQ0FnSUd4bGRDQnVaWGRmZG1Gc2RXVnpJRDBnZEdocGN5NTJZV3gxWlhNdVkyOXVZMkYwS0Z0ZEtUdGNiaUFnSUNCdVpYZGZkbUZzZFdWekxuTndiR2xqWlNocGJtUmxlQ3dnTVNrN1hHNGdJQ0FnY21WMGRYSnVJRzVsZHlCVWRYQnNaU2d1TGk1dVpYZGZkbUZzZFdWektUdGNiaUFnZlZ4dVhHNTlYRzVjYmx4dWJHVjBJSEJ5YjJObGMzTmZZMjkxYm5SbGNpQTlJQzB4TzF4dVhHNWpiR0Z6Y3lCUVNVUWdlMXh1SUNCamIyNXpkSEoxWTNSdmNpZ3BlMXh1SUNBZ0lIQnliMk5sYzNOZlkyOTFiblJsY2lBOUlIQnliMk5sYzNOZlkyOTFiblJsY2lBcklERTdYRzRnSUNBZ2RHaHBjeTVwWkNBOUlIQnliMk5sYzNOZlkyOTFiblJsY2p0Y2JpQWdmVnh1WEc0Z0lIUnZVM1J5YVc1bktDbDdYRzRnSUNBZ2NtVjBkWEp1SUZ3aVVFbEVJend3TGx3aUlDc2dkR2hwY3k1cFpDQXJJRndpTGpBK1hDSTdYRzRnSUgxY2JuMWNibHh1WTJ4aGMzTWdTVzUwWldkbGNpQjdmVnh1WTJ4aGMzTWdSbXh2WVhRZ2UzMWNibHh1Wlhod2IzSjBJSHNnVUVsRUxDQlVkWEJzWlN3Z1NXNTBaV2RsY2l3Z1JteHZZWFFnZlR0Y2JpSmRMQ0p6YjNWeVkyVlNiMjkwSWpvaUwzTnZkWEpqWlM4aWZRPT1cbiIsIlxuXCJ1c2Ugc3RyaWN0XCI7XG5cbmltcG9ydCBNYWlsYm94IGZyb20gXCIuL21haWxib3hcIjtcbmltcG9ydCBQcm9jZXNzIGZyb20gXCIuL3Byb2Nlc3NcIjtcbmltcG9ydCBTdGF0ZXMgZnJvbSBcIi4vc3RhdGVzXCI7XG5pbXBvcnQgKiBhcyBQcmltaXRpdmVzIGZyb20gXCIuLi9wcmltaXRpdmVzXCI7XG5cbmNsYXNzIFByb2Nlc3NTeXN0ZW0ge1xuXG4gIGNvbnN0cnVjdG9yKCkge1xuICAgIHRoaXMucGlkcyA9IG5ldyBNYXAoKTtcbiAgICB0aGlzLm1haWxib3hlcyA9IG5ldyBNYXAoKTtcbiAgICB0aGlzLm5hbWVzID0gbmV3IE1hcCgpO1xuICAgIHRoaXMubGlua3MgPSBuZXcgTWFwKCk7XG5cbiAgICB0aGlzLmN1cnJlbnRfcHJvY2VzcyA9IG51bGw7XG4gICAgdGhpcy5zdXNwZW5kZWQgPSBuZXcgTWFwKCk7XG5cbiAgICB0aGlzLm1haW5fcHJvY2Vzc19waWQgPSB0aGlzLnNwYXduKCk7XG4gICAgdGhpcy5zZXRfY3VycmVudCh0aGlzLm1haW5fcHJvY2Vzc19waWQpO1xuICB9XG5cbiAgc3Bhd24oKSB7XG4gICAgcmV0dXJuIHRoaXMuYWRkX3Byb2MoZmFsc2UpLnBpZDtcbiAgfVxuXG4gIHNwYXduX2xpbmsoKSB7XG4gICAgcmV0dXJuIHRoaXMuYWRkX3Byb2ModHJ1ZSkucGlkO1xuICB9XG5cbiAgbGluayhwaWQpIHtcbiAgICB0aGlzLmxpbmtzLmdldCh0aGlzLnBpZCgpKS5hZGQocGlkKTtcbiAgICB0aGlzLmxpbmtzLmdldChwaWQpLmFkZCh0aGlzLnBpZCgpKTtcbiAgfVxuXG4gIHVubGluayhwaWQpIHtcbiAgICB0aGlzLmxpbmtzLmdldCh0aGlzLnBpZCgpKS5kZWxldGUocGlkKTtcbiAgICB0aGlzLmxpbmtzLmdldChwaWQpLmRlbGV0ZSh0aGlzLnBpZCgpKTtcbiAgfVxuXG4gIHNldF9jdXJyZW50KGlkKSB7XG4gICAgbGV0IHBpZCA9IHRoaXMucGlkb2YoaWQpO1xuICAgIGlmIChwaWQgIT09IG51bGwpIHtcbiAgICAgIHRoaXMuY3VycmVudF9wcm9jZXNzID0gdGhpcy5waWRzLmdldChwaWQpO1xuICAgICAgdGhpcy5jdXJyZW50X3Byb2Nlc3Muc3RhdHVzID0gU3RhdGVzLlJVTk5JTkc7XG4gICAgfVxuICB9XG5cbiAgYWRkX3Byb2MobGlua2VkKSB7XG4gICAgbGV0IG5ld3BpZCA9IG5ldyBQcmltaXRpdmVzLlBJRCgpO1xuICAgIGxldCBtYWlsYm94ID0gbmV3IE1haWxib3goKTtcbiAgICBsZXQgbmV3cHJvYyA9IG5ldyBQcm9jZXNzKG5ld3BpZCwgbWFpbGJveCk7XG5cbiAgICB0aGlzLnBpZHMuc2V0KG5ld3BpZCwgbmV3cHJvYyk7XG4gICAgdGhpcy5tYWlsYm94ZXMuc2V0KG5ld3BpZCwgbWFpbGJveCk7XG4gICAgdGhpcy5saW5rcy5zZXQobmV3cGlkLCBuZXcgU2V0KCkpO1xuXG4gICAgaWYgKGxpbmtlZCkge1xuICAgICAgdGhpcy5saW5rKG5ld3BpZCk7XG4gICAgfVxuXG4gICAgcmV0dXJuIG5ld3Byb2M7XG4gIH1cblxuICByZW1vdmVfcHJvYyhwaWQpIHtcbiAgICB0aGlzLnBpZHMuZGVsZXRlKHBpZCk7XG4gICAgdGhpcy51bnJlZ2lzdGVyKHBpZCk7XG5cbiAgICBpZiAodGhpcy5saW5rcy5oYXMocGlkKSkge1xuICAgICAgZm9yIChsZXQgbGlua3BpZCBvZiB0aGlzLmxpbmtzLmdldChwaWQpKSB7XG4gICAgICAgIHRoaXMubGlua3MuZ2V0KGxpbmtwaWQpLmRlbGV0ZShwaWQpO1xuICAgICAgfVxuXG4gICAgICB0aGlzLmxpbmtzLmRlbGV0ZShwaWQpO1xuICAgIH1cbiAgfVxuXG4gIGV4aXQoaWQpIHtcbiAgICBsZXQgcGlkID0gdGhpcy5waWRvZihpZCk7XG4gICAgdGhpcy5yZW1vdmVfcHJvYyhpZCk7XG4gIH1cblxuICByZWdpc3RlcihuYW1lLCBwaWQpIHtcbiAgICBpZiAoIXRoaXMubmFtZXMuaGFzKG5hbWUpKSB7XG4gICAgICB0aGlzLm5hbWVzLnNldChuYW1lLCBwaWQpO1xuICAgICAgcmV0dXJuIG5hbWU7XG4gICAgfSBlbHNlIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcihcIk5hbWUgaXMgYWxyZWFkeSByZWdpc3RlcmVkIHRvIGFub3RoZXIgcHJvY2Vzc1wiKTtcbiAgICB9XG4gIH1cblxuICByZWdpc3RlcmVkKG5hbWUpIHtcbiAgICByZXR1cm4gdGhpcy5uYW1lcy5oYXMobmFtZSkgPyB0aGlzLm5hbWVzLmdldChuYW1lKSA6IG51bGw7XG4gIH1cblxuICB1bnJlZ2lzdGVyKHBpZCkge1xuICAgIGZvciAobGV0IG5hbWUgb2YgdGhpcy5uYW1lcy5rZXlzKCkpIHtcbiAgICAgIGlmICh0aGlzLm5hbWVzLmhhcyhuYW1lKSAmJiB0aGlzLm5hbWVzLmdldChuYW1lKSA9PT0gcGlkKSB7XG4gICAgICAgIHRoaXMubmFtZXMuZGVsZXRlKG5hbWUpO1xuICAgICAgfVxuICAgIH1cbiAgfVxuXG4gIHBpZCgpIHtcbiAgICByZXR1cm4gdGhpcy5jdXJyZW50X3Byb2Nlc3MucGlkO1xuICB9XG5cbiAgcGlkb2YoaWQpIHtcbiAgICBpZiAoaWQgaW5zdGFuY2VvZiBQcmltaXRpdmVzLlBJRCkge1xuICAgICAgcmV0dXJuIHRoaXMucGlkcy5oYXMoaWQpID8gaWQgOiBudWxsO1xuICAgIH0gZWxzZSBpZiAoaWQgaW5zdGFuY2VvZiBQcm9jZXNzKSB7XG4gICAgICByZXR1cm4gaWQucGlkO1xuICAgIH0gZWxzZSB7XG4gICAgICBsZXQgcGlkID0gdGhpcy5yZWdpc3RlcmVkKGlkKTtcbiAgICAgIGlmIChwaWQgPT09IG51bGwpIHRocm93IFwiUHJvY2VzcyBuYW1lIG5vdCByZWdpc3RlcmVkOiBcIiArIGlkICsgXCIgKFwiICsgdHlwZW9mIGlkICsgXCIpXCI7XG4gICAgICByZXR1cm4gcGlkO1xuICAgIH1cbiAgfVxuXG4gIHB1dChpZCwga2V5LCB2YWx1ZSkge1xuICAgIGxldCBwaWQgPSB0aGlzLnBpZG9mKGlkKTtcbiAgICBsZXQgcHJvY2VzcyA9IHRoaXMucGlkcy5nZXQocGlkKTtcbiAgICBwcm9jZXNzLmRpY3Rba2V5XSA9IHZhbHVlO1xuICB9XG5cbiAgZ2V0KGlkLCBrZXkpIHtcbiAgICBsZXQgcGlkID0gdGhpcy5waWRvZihpZCk7XG4gICAgbGV0IHByb2Nlc3MgPSB0aGlzLnBpZHMuZ2V0KHBpZCk7XG5cbiAgICBpZiAoa2V5ICE9IG51bGwpIHtcbiAgICAgIHJldHVybiBwcm9jZXNzLmRpY3Rba2V5XTtcbiAgICB9IGVsc2Uge1xuICAgICAgcmV0dXJuIHByb2Nlc3MuZGljdDtcbiAgICB9XG4gIH1cblxuICBnZXRfa2V5cyhpZCkge1xuICAgIGxldCBwaWQgPSB0aGlzLnBpZG9mKGlkKTtcbiAgICBsZXQgcHJvY2VzcyA9IHRoaXMucGlkcy5nZXQocGlkKTtcblxuICAgIHJldHVybiBPYmplY3Qua2V5cyhwcm9jZXNzLmRpY3QpO1xuICB9XG5cbiAgZXJhc2UoaWQsIGtleSkge1xuICAgIGxldCBwaWQgPSB0aGlzLnBpZG9mKGlkKTtcbiAgICBsZXQgcHJvY2VzcyA9IHRoaXMucGlkcy5nZXQocGlkKTtcblxuICAgIGlmIChrZXkgIT0gbnVsbCkge1xuICAgICAgZGVsZXRlIHByb2Nlc3MuZGljdFtrZXldO1xuICAgIH0gZWxzZSB7XG4gICAgICBwcm9jZXNzLmRpY3QgPSB7fTtcbiAgICB9XG4gIH1cbn1cblxuZXhwb3J0IGRlZmF1bHQgUHJvY2Vzc1N5c3RlbTtcbi8vIyBzb3VyY2VNYXBwaW5nVVJMPWRhdGE6YXBwbGljYXRpb24vanNvbjtiYXNlNjQsZXlKMlpYSnphVzl1SWpvekxDSnpiM1Z5WTJWeklqcGJJbXhwWWk5amIzSmxMM0J5YjJObGMzTmxjeTl3Y205alpYTnpYM041YzNSbGJTNXFjeUpkTENKdVlXMWxjeUk2VzEwc0ltMWhjSEJwYm1keklqb2lPMEZCUTBFN08wRkJSVUVzVDBGQlR5eFBRVUZRTEUxQlFXOUNMRmRCUVhCQ08wRkJRMEVzVDBGQlR5eFBRVUZRTEUxQlFXOUNMRmRCUVhCQ08wRkJRMEVzVDBGQlR5eE5RVUZRTEUxQlFXMUNMRlZCUVc1Q08wRkJRMEVzVDBGQlR5eExRVUZMTEZWQlFVd3NUVUZCY1VJc1pVRkJOVUk3TzBGQlJVRXNUVUZCVFN4aFFVRk9MRU5CUVc5Q096dEJRVVZzUWl4blFrRkJZVHRCUVVOWUxGTkJRVXNzU1VGQlRDeEhRVUZaTEVsQlFVa3NSMEZCU2l4RlFVRmFMRU5CUkZjN1FVRkZXQ3hUUVVGTExGTkJRVXdzUjBGQmFVSXNTVUZCU1N4SFFVRktMRVZCUVdwQ0xFTkJSbGM3UVVGSFdDeFRRVUZMTEV0QlFVd3NSMEZCWVN4SlFVRkpMRWRCUVVvc1JVRkJZaXhEUVVoWE8wRkJTVmdzVTBGQlN5eExRVUZNTEVkQlFXRXNTVUZCU1N4SFFVRktMRVZCUVdJc1EwRktWenM3UVVGTldDeFRRVUZMTEdWQlFVd3NSMEZCZFVJc1NVRkJka0lzUTBGT1Z6dEJRVTlZTEZOQlFVc3NVMEZCVEN4SFFVRnBRaXhKUVVGSkxFZEJRVW9zUlVGQmFrSXNRMEZRVnpzN1FVRlRXQ3hUUVVGTExHZENRVUZNTEVkQlFYZENMRXRCUVVzc1MwRkJUQ3hGUVVGNFFpeERRVlJYTzBGQlZWZ3NVMEZCU3l4WFFVRk1MRU5CUVdsQ0xFdEJRVXNzWjBKQlFVd3NRMEZCYWtJc1EwRldWenRIUVVGaU96dEJRV0ZCTEZWQlFVODdRVUZEVEN4WFFVRlBMRXRCUVVzc1VVRkJUQ3hEUVVGakxFdEJRV1FzUlVGQmNVSXNSMEZCY2tJc1EwRkVSanRIUVVGUU96dEJRVWxCTEdWQlFWazdRVUZEVml4WFFVRlBMRXRCUVVzc1VVRkJUQ3hEUVVGakxFbEJRV1FzUlVGQmIwSXNSMEZCY0VJc1EwRkVSenRIUVVGYU96dEJRVWxCTEU5QlFVc3NSMEZCVEN4RlFVRlRPMEZCUTFBc1UwRkJTeXhMUVVGTUxFTkJRVmNzUjBGQldDeERRVUZsTEV0QlFVc3NSMEZCVEN4RlFVRm1MRVZCUVRKQ0xFZEJRVE5DTEVOQlFTdENMRWRCUVM5Q0xFVkJSRTg3UVVGRlVDeFRRVUZMTEV0QlFVd3NRMEZCVnl4SFFVRllMRU5CUVdVc1IwRkJaaXhGUVVGdlFpeEhRVUZ3UWl4RFFVRjNRaXhMUVVGTExFZEJRVXdzUlVGQmVFSXNSVUZHVHp0SFFVRlVPenRCUVV0QkxGTkJRVThzUjBGQlVDeEZRVUZYTzBGQlExUXNVMEZCU3l4TFFVRk1MRU5CUVZjc1IwRkJXQ3hEUVVGbExFdEJRVXNzUjBGQlRDeEZRVUZtTEVWQlFUSkNMRTFCUVROQ0xFTkJRV3RETEVkQlFXeERMRVZCUkZNN1FVRkZWQ3hUUVVGTExFdEJRVXdzUTBGQlZ5eEhRVUZZTEVOQlFXVXNSMEZCWml4RlFVRnZRaXhOUVVGd1FpeERRVUV5UWl4TFFVRkxMRWRCUVV3c1JVRkJNMElzUlVGR1V6dEhRVUZZT3p0QlFVdEJMR05CUVZrc1JVRkJXaXhGUVVGbE8wRkJRMklzVVVGQlNTeE5RVUZOTEV0QlFVc3NTMEZCVEN4RFFVRlhMRVZCUVZnc1EwRkJUaXhEUVVSVE8wRkJSV0lzVVVGQlJ5eFJRVUZSTEVsQlFWSXNSVUZCWVR0QlFVTmtMRmRCUVVzc1pVRkJUQ3hIUVVGMVFpeExRVUZMTEVsQlFVd3NRMEZCVlN4SFFVRldMRU5CUVdNc1IwRkJaQ3hEUVVGMlFpeERRVVJqTzBGQlJXUXNWMEZCU3l4bFFVRk1MRU5CUVhGQ0xFMUJRWEpDTEVkQlFUaENMRTlCUVU4c1QwRkJVQ3hEUVVab1FqdExRVUZvUWp0SFFVWkdPenRCUVZGQkxGZEJRVk1zVFVGQlZDeEZRVUZuUWp0QlFVTmtMRkZCUVVrc1UwRkJVeXhKUVVGSkxGZEJRVmNzUjBGQldDeEZRVUZpTEVOQlJGVTdRVUZGWkN4UlFVRkpMRlZCUVZVc1NVRkJTU3hQUVVGS0xFVkJRVllzUTBGR1ZUdEJRVWRrTEZGQlFVa3NWVUZCVlN4SlFVRkpMRTlCUVVvc1EwRkJXU3hOUVVGYUxFVkJRVzlDTEU5QlFYQkNMRU5CUVZZc1EwRklWVHM3UVVGTFpDeFRRVUZMTEVsQlFVd3NRMEZCVlN4SFFVRldMRU5CUVdNc1RVRkJaQ3hGUVVGelFpeFBRVUYwUWl4RlFVeGpPMEZCVFdRc1UwRkJTeXhUUVVGTUxFTkJRV1VzUjBGQlppeERRVUZ0UWl4TlFVRnVRaXhGUVVFeVFpeFBRVUV6UWl4RlFVNWpPMEZCVDJRc1UwRkJTeXhMUVVGTUxFTkJRVmNzUjBGQldDeERRVUZsTEUxQlFXWXNSVUZCZFVJc1NVRkJTU3hIUVVGS0xFVkJRWFpDTEVWQlVHTTdPMEZCVTJRc1VVRkJSeXhOUVVGSUxFVkJRVlU3UVVGRFVpeFhRVUZMTEVsQlFVd3NRMEZCVlN4TlFVRldMRVZCUkZFN1MwRkJWanM3UVVGSlFTeFhRVUZQTEU5QlFWQXNRMEZpWXp0SFFVRm9RanM3UVVGblFrRXNZMEZCV1N4SFFVRmFMRVZCUVdkQ08wRkJRMlFzVTBGQlN5eEpRVUZNTEVOQlFWVXNUVUZCVml4RFFVRnBRaXhIUVVGcVFpeEZRVVJqTzBGQlJXUXNVMEZCU3l4VlFVRk1MRU5CUVdkQ0xFZEJRV2hDTEVWQlJtTTdPMEZCU1dRc1VVRkJSeXhMUVVGTExFdEJRVXdzUTBGQlZ5eEhRVUZZTEVOQlFXVXNSMEZCWml4RFFVRklMRVZCUVhWQ08wRkJRM0pDTEZkQlFVc3NTVUZCU1N4UFFVRktMRWxCUVdVc1MwRkJTeXhMUVVGTUxFTkJRVmNzUjBGQldDeERRVUZsTEVkQlFXWXNRMEZCY0VJc1JVRkJlVU03UVVGRGRrTXNZVUZCU3l4TFFVRk1MRU5CUVZjc1IwRkJXQ3hEUVVGbExFOUJRV1lzUlVGQmQwSXNUVUZCZUVJc1EwRkJLMElzUjBGQkwwSXNSVUZFZFVNN1QwRkJla003TzBGQlNVRXNWMEZCU3l4TFFVRk1MRU5CUVZjc1RVRkJXQ3hEUVVGclFpeEhRVUZzUWl4RlFVeHhRanRMUVVGMlFqdEhRVXBHT3p0QlFXRkJMRTlCUVVzc1JVRkJUQ3hGUVVGUk8wRkJRMDRzVVVGQlNTeE5RVUZOTEV0QlFVc3NTMEZCVEN4RFFVRlhMRVZCUVZnc1EwRkJUaXhEUVVSRk8wRkJSVTRzVTBGQlN5eFhRVUZNTEVOQlFXbENMRVZCUVdwQ0xFVkJSazA3UjBGQlVqczdRVUZMUVN4WFFVRlRMRWxCUVZRc1JVRkJaU3hIUVVGbUxFVkJRVzFDTzBGQlEycENMRkZCUVVjc1EwRkJReXhMUVVGTExFdEJRVXdzUTBGQlZ5eEhRVUZZTEVOQlFXVXNTVUZCWml4RFFVRkVMRVZCUVhOQ08wRkJRM1pDTEZkQlFVc3NTMEZCVEN4RFFVRlhMRWRCUVZnc1EwRkJaU3hKUVVGbUxFVkJRWEZDTEVkQlFYSkNMRVZCUkhWQ08wRkJSWFpDTEdGQlFVOHNTVUZCVUN4RFFVWjFRanRMUVVGNlFpeE5RVWRMTzBGQlEwZ3NXVUZCVFN4SlFVRkpMRXRCUVVvc1EwRkJWU3dyUTBGQlZpeERRVUZPTEVOQlJFYzdTMEZJVER0SFFVUkdPenRCUVZOQkxHRkJRVmNzU1VGQldDeEZRVUZuUWp0QlFVTmtMRmRCUVU4c1MwRkJTeXhMUVVGTUxFTkJRVmNzUjBGQldDeERRVUZsTEVsQlFXWXNTVUZCZFVJc1MwRkJTeXhMUVVGTUxFTkJRVmNzUjBGQldDeERRVUZsTEVsQlFXWXNRMEZCZGtJc1IwRkJPRU1zU1VGQk9VTXNRMEZFVHp0SFFVRm9RanM3UVVGSlFTeGhRVUZYTEVkQlFWZ3NSVUZCWlR0QlFVTmlMRk5CUVVrc1NVRkJTU3hKUVVGS0xFbEJRVmtzUzBGQlN5eExRVUZNTEVOQlFWY3NTVUZCV0N4RlFVRm9RaXhGUVVGclF6dEJRVU5vUXl4VlFVRkhMRXRCUVVzc1MwRkJUQ3hEUVVGWExFZEJRVmdzUTBGQlpTeEpRVUZtTEV0QlFYZENMRXRCUVVzc1MwRkJUQ3hEUVVGWExFZEJRVmdzUTBGQlpTeEpRVUZtTEUxQlFYbENMRWRCUVhwQ0xFVkJRVFpDTzBGQlEzUkVMR0ZCUVVzc1MwRkJUQ3hEUVVGWExFMUJRVmdzUTBGQmEwSXNTVUZCYkVJc1JVRkVjMFE3VDBGQmVFUTdTMEZFUmp0SFFVUkdPenRCUVZGQkxGRkJRVXM3UVVGRFNDeFhRVUZQTEV0QlFVc3NaVUZCVEN4RFFVRnhRaXhIUVVGeVFpeERRVVJLTzBkQlFVdzdPMEZCU1VFc1VVRkJUU3hGUVVGT0xFVkJRVk03UVVGRFVDeFJRVUZKTEdOQlFXTXNWMEZCVnl4SFFVRllMRVZCUVdkQ08wRkJReTlDTEdGQlFVOHNTMEZCU3l4SlFVRk1MRU5CUVZVc1IwRkJWaXhEUVVGakxFVkJRV1FzU1VGQmIwSXNSVUZCY0VJc1IwRkJlVUlzU1VGQmVrSXNRMEZFZDBJN1MwRkJiRU1zVFVGRlR5eEpRVUZKTEdOQlFXTXNUMEZCWkN4RlFVRjFRanRCUVVNdlFpeGhRVUZQTEVkQlFVY3NSMEZCU0N4RFFVUjNRanRMUVVFelFpeE5RVVZCTzBGQlEwb3NWVUZCU1N4TlFVRk5MRXRCUVVzc1ZVRkJUQ3hEUVVGblFpeEZRVUZvUWl4RFFVRk9MRU5CUkVFN1FVRkZTaXhWUVVGSkxGRkJRVkVzU1VGQlVpeEZRVU5FTEUxQlFVMHNhME5CUVd0RExFVkJRV3hETEVkQlFYVkRMRWxCUVhaRExFZEJRVGhETEU5QlFVOHNSVUZCVUN4SFFVRmhMRWRCUVRORUxFTkJSRlE3UVVGRlFTeGhRVUZQTEVkQlFWQXNRMEZLU1R0TFFVWkJPMGRCU0ZRN08wRkJZVUVzVFVGQlNTeEZRVUZLTEVWQlFWRXNSMEZCVWl4RlFVRmhMRXRCUVdJc1JVRkJiVUk3UVVGRGFrSXNVVUZCU1N4TlFVRk5MRXRCUVVzc1MwRkJUQ3hEUVVGWExFVkJRVmdzUTBGQlRpeERRVVJoTzBGQlJXcENMRkZCUVVrc1ZVRkJWU3hMUVVGTExFbEJRVXdzUTBGQlZTeEhRVUZXTEVOQlFXTXNSMEZCWkN4RFFVRldMRU5CUm1FN1FVRkhha0lzV1VGQlVTeEpRVUZTTEVOQlFXRXNSMEZCWWl4SlFVRnZRaXhMUVVGd1FpeERRVWhwUWp0SFFVRnVRanM3UVVGTlFTeE5RVUZKTEVWQlFVb3NSVUZCVVN4SFFVRlNMRVZCUVZrN1FVRkRWaXhSUVVGSkxFMUJRVTBzUzBGQlN5eExRVUZNTEVOQlFWY3NSVUZCV0N4RFFVRk9MRU5CUkUwN1FVRkZWaXhSUVVGSkxGVkJRVlVzUzBGQlN5eEpRVUZNTEVOQlFWVXNSMEZCVml4RFFVRmpMRWRCUVdRc1EwRkJWaXhEUVVaTk96dEJRVWxXTEZGQlFVY3NUMEZCVHl4SlFVRlFMRVZCUVZrN1FVRkRZaXhoUVVGUExGRkJRVkVzU1VGQlVpeERRVUZoTEVkQlFXSXNRMEZCVUN4RFFVUmhPMHRCUVdZc1RVRkZTenRCUVVOSUxHRkJRVThzVVVGQlVTeEpRVUZTTEVOQlJFbzdTMEZHVER0SFFVcEdPenRCUVZkQkxGZEJRVk1zUlVGQlZDeEZRVUZaTzBGQlExWXNVVUZCU1N4TlFVRk5MRXRCUVVzc1MwRkJUQ3hEUVVGWExFVkJRVmdzUTBGQlRpeERRVVJOTzBGQlJWWXNVVUZCU1N4VlFVRlZMRXRCUVVzc1NVRkJUQ3hEUVVGVkxFZEJRVllzUTBGQll5eEhRVUZrTEVOQlFWWXNRMEZHVFRzN1FVRkpWaXhYUVVGUExFOUJRVThzU1VGQlVDeERRVUZaTEZGQlFWRXNTVUZCVWl4RFFVRnVRaXhEUVVwVk8wZEJRVm83TzBGQlQwRXNVVUZCVFN4RlFVRk9MRVZCUVZVc1IwRkJWaXhGUVVGak8wRkJRMW9zVVVGQlNTeE5RVUZOTEV0QlFVc3NTMEZCVEN4RFFVRlhMRVZCUVZnc1EwRkJUaXhEUVVSUk8wRkJSVm9zVVVGQlNTeFZRVUZWTEV0QlFVc3NTVUZCVEN4RFFVRlZMRWRCUVZZc1EwRkJZeXhIUVVGa0xFTkJRVllzUTBGR1VUczdRVUZKV2l4UlFVRkhMRTlCUVU4c1NVRkJVQ3hGUVVGWk8wRkJRMklzWVVGQlR5eFJRVUZSTEVsQlFWSXNRMEZCWVN4SFFVRmlMRU5CUVZBc1EwRkVZVHRMUVVGbUxFMUJSVXM3UVVGRFNDeGpRVUZSTEVsQlFWSXNSMEZCWlN4RlFVRm1MRU5CUkVjN1MwRkdURHRIUVVwR08wTkJla2xHT3p0QlFYRktRU3hsUVVGbExHRkJRV1lpTENKbWFXeGxJam9pYkdsaUwyTnZjbVV2Y0hKdlkyVnpjMlZ6TDNCeWIyTmxjM05mYzNsemRHVnRMbXB6SWl3aWMyOTFjbU5sYzBOdmJuUmxiblFpT2xzaUx5b2dRR1pzYjNjZ0tpOWNibHdpZFhObElITjBjbWxqZEZ3aU8xeHVYRzVwYlhCdmNuUWdUV0ZwYkdKdmVDQm1jbTl0SUZ3aUxpOXRZV2xzWW05NFhDSTdYRzVwYlhCdmNuUWdVSEp2WTJWemN5Qm1jbTl0SUZ3aUxpOXdjbTlqWlhOelhDSTdYRzVwYlhCdmNuUWdVM1JoZEdWeklHWnliMjBnWENJdUwzTjBZWFJsYzF3aU8xeHVhVzF3YjNKMElDb2dZWE1nVUhKcGJXbDBhWFpsY3lCbWNtOXRJRndpTGk0dmNISnBiV2wwYVhabGMxd2lPMXh1WEc1amJHRnpjeUJRY205alpYTnpVM2x6ZEdWdElIdGNibHh1SUNCamIyNXpkSEoxWTNSdmNpZ3BlMXh1SUNBZ0lIUm9hWE11Y0dsa2N5QTlJRzVsZHlCTllYQW9LVHRjYmlBZ0lDQjBhR2x6TG0xaGFXeGliM2hsY3lBOUlHNWxkeUJOWVhBb0tUdGNiaUFnSUNCMGFHbHpMbTVoYldWeklEMGdibVYzSUUxaGNDZ3BPMXh1SUNBZ0lIUm9hWE11YkdsdWEzTWdQU0J1WlhjZ1RXRndLQ2s3WEc1Y2JpQWdJQ0IwYUdsekxtTjFjbkpsYm5SZmNISnZZMlZ6Y3lBOUlHNTFiR3c3WEc0Z0lDQWdkR2hwY3k1emRYTndaVzVrWldRZ1BTQnVaWGNnVFdGd0tDazdYRzVjYmlBZ0lDQjBhR2x6TG0xaGFXNWZjSEp2WTJWemMxOXdhV1FnUFNCMGFHbHpMbk53WVhkdUtDazdYRzRnSUNBZ2RHaHBjeTV6WlhSZlkzVnljbVZ1ZENoMGFHbHpMbTFoYVc1ZmNISnZZMlZ6YzE5d2FXUXBPMXh1SUNCOVhHNWNiaUFnYzNCaGQyNG9LWHRjYmlBZ0lDQnlaWFIxY200Z2RHaHBjeTVoWkdSZmNISnZZeWhtWVd4elpTa3VjR2xrTzF4dUlDQjlYRzVjYmlBZ2MzQmhkMjVmYkdsdWF5Z3BlMXh1SUNBZ0lISmxkSFZ5YmlCMGFHbHpMbUZrWkY5d2NtOWpLSFJ5ZFdVcExuQnBaRHRjYmlBZ2ZWeHVYRzRnSUd4cGJtc29jR2xrS1h0Y2JpQWdJQ0IwYUdsekxteHBibXR6TG1kbGRDaDBhR2x6TG5CcFpDZ3BLUzVoWkdRb2NHbGtLVHRjYmlBZ0lDQjBhR2x6TG14cGJtdHpMbWRsZENod2FXUXBMbUZrWkNoMGFHbHpMbkJwWkNncEtUdGNiaUFnZlZ4dVhHNGdJSFZ1YkdsdWF5aHdhV1FwZTF4dUlDQWdJSFJvYVhNdWJHbHVhM011WjJWMEtIUm9hWE11Y0dsa0tDa3BMbVJsYkdWMFpTaHdhV1FwTzF4dUlDQWdJSFJvYVhNdWJHbHVhM011WjJWMEtIQnBaQ2t1WkdWc1pYUmxLSFJvYVhNdWNHbGtLQ2twTzF4dUlDQjlYRzVjYmlBZ2MyVjBYMk4xY25KbGJuUW9hV1FwZTF4dUlDQWdJR3hsZENCd2FXUWdQU0IwYUdsekxuQnBaRzltS0dsa0tUdGNiaUFnSUNCcFppaHdhV1FnSVQwOUlHNTFiR3dwZTF4dUlDQWdJQ0FnZEdocGN5NWpkWEp5Wlc1MFgzQnliMk5sYzNNZ1BTQjBhR2x6TG5CcFpITXVaMlYwS0hCcFpDazdYRzRnSUNBZ0lDQjBhR2x6TG1OMWNuSmxiblJmY0hKdlkyVnpjeTV6ZEdGMGRYTWdQU0JUZEdGMFpYTXVVbFZPVGtsT1J6dGNiaUFnSUNCOVhHNGdJSDFjYmx4dUlDQmhaR1JmY0hKdll5aHNhVzVyWldRcGUxeHVJQ0FnSUd4bGRDQnVaWGR3YVdRZ1BTQnVaWGNnVUhKcGJXbDBhWFpsY3k1UVNVUW9LVHRjYmlBZ0lDQnNaWFFnYldGcGJHSnZlQ0E5SUc1bGR5Qk5ZV2xzWW05NEtDazdYRzRnSUNBZ2JHVjBJRzVsZDNCeWIyTWdQU0J1WlhjZ1VISnZZMlZ6Y3lodVpYZHdhV1FzSUcxaGFXeGliM2dwTzF4dVhHNGdJQ0FnZEdocGN5NXdhV1J6TG5ObGRDaHVaWGR3YVdRc0lHNWxkM0J5YjJNcE8xeHVJQ0FnSUhSb2FYTXViV0ZwYkdKdmVHVnpMbk5sZENodVpYZHdhV1FzSUcxaGFXeGliM2dwTzF4dUlDQWdJSFJvYVhNdWJHbHVhM011YzJWMEtHNWxkM0JwWkN3Z2JtVjNJRk5sZENncEtUdGNibHh1SUNBZ0lHbG1LR3hwYm10bFpDbDdYRzRnSUNBZ0lDQjBhR2x6TG14cGJtc29ibVYzY0dsa0tUdGNiaUFnSUNCOVhHNWNiaUFnSUNCeVpYUjFjbTRnYm1WM2NISnZZenRjYmlBZ2ZWeHVYRzRnSUhKbGJXOTJaVjl3Y205aktIQnBaQ2w3WEc0Z0lDQWdkR2hwY3k1d2FXUnpMbVJsYkdWMFpTaHdhV1FwTzF4dUlDQWdJSFJvYVhNdWRXNXlaV2RwYzNSbGNpaHdhV1FwTzF4dVhHNGdJQ0FnYVdZb2RHaHBjeTVzYVc1cmN5NW9ZWE1vY0dsa0tTbDdYRzRnSUNBZ0lDQm1iM0lnS0d4bGRDQnNhVzVyY0dsa0lHOW1JSFJvYVhNdWJHbHVhM011WjJWMEtIQnBaQ2twSUh0Y2JpQWdJQ0FnSUNBZ2RHaHBjeTVzYVc1cmN5NW5aWFFvYkdsdWEzQnBaQ2t1WkdWc1pYUmxLSEJwWkNrN1hHNGdJQ0FnSUNCOVhHNWNiaUFnSUNBZ0lIUm9hWE11YkdsdWEzTXVaR1ZzWlhSbEtIQnBaQ2s3WEc0Z0lDQWdmVnh1SUNCOVhHNWNiaUFnWlhocGRDaHBaQ2w3WEc0Z0lDQWdiR1YwSUhCcFpDQTlJSFJvYVhNdWNHbGtiMllvYVdRcE8xeHVJQ0FnSUhSb2FYTXVjbVZ0YjNabFgzQnliMk1vYVdRcE8xeHVJQ0I5WEc1Y2JpQWdjbVZuYVhOMFpYSW9ibUZ0WlN3Z2NHbGtLWHRjYmlBZ0lDQnBaaWdoZEdocGN5NXVZVzFsY3k1b1lYTW9ibUZ0WlNrcGUxeHVJQ0FnSUNBZ2RHaHBjeTV1WVcxbGN5NXpaWFFvYm1GdFpTd2djR2xrS1Z4dUlDQWdJQ0FnY21WMGRYSnVJRzVoYldVN1hHNGdJQ0FnZldWc2MyVjdYRzRnSUNBZ0lDQjBhSEp2ZHlCdVpYY2dSWEp5YjNJb1hDSk9ZVzFsSUdseklHRnNjbVZoWkhrZ2NtVm5hWE4wWlhKbFpDQjBieUJoYm05MGFHVnlJSEJ5YjJObGMzTmNJaWs3WEc0Z0lDQWdmVnh1SUNCOVhHNWNiaUFnY21WbmFYTjBaWEpsWkNodVlXMWxLWHRjYmlBZ0lDQnlaWFIxY200Z2RHaHBjeTV1WVcxbGN5NW9ZWE1vYm1GdFpTa2dQeUIwYUdsekxtNWhiV1Z6TG1kbGRDaHVZVzFsS1NBNklHNTFiR3c3WEc0Z0lIMWNibHh1SUNCMWJuSmxaMmx6ZEdWeUtIQnBaQ2w3WEc0Z0lDQWdabTl5S0d4bGRDQnVZVzFsSUc5bUlIUm9hWE11Ym1GdFpYTXVhMlY1Y3lncEtYdGNiaUFnSUNBZ0lHbG1LSFJvYVhNdWJtRnRaWE11YUdGektHNWhiV1VwSUNZbUlIUm9hWE11Ym1GdFpYTXVaMlYwS0c1aGJXVXBJRDA5UFNCd2FXUXBlMXh1SUNBZ0lDQWdJQ0IwYUdsekxtNWhiV1Z6TG1SbGJHVjBaU2h1WVcxbEtUdGNiaUFnSUNBZ0lIMWNiaUFnSUNCOVhHNGdJSDFjYmx4dUlDQndhV1FvS1h0Y2JpQWdJQ0J5WlhSMWNtNGdkR2hwY3k1amRYSnlaVzUwWDNCeWIyTmxjM011Y0dsa08xeHVJQ0I5WEc1Y2JpQWdjR2xrYjJZb2FXUXBlMXh1SUNBZ0lHbG1JQ2hwWkNCcGJuTjBZVzVqWlc5bUlGQnlhVzFwZEdsMlpYTXVVRWxFS1NCN1hHNGdJQ0FnSUNBZ2NtVjBkWEp1SUhSb2FYTXVjR2xrY3k1b1lYTW9hV1FwSUQ4Z2FXUWdPaUJ1ZFd4c08xeHVJQ0FnSUgwZ1pXeHpaU0JwWmlBb2FXUWdhVzV6ZEdGdVkyVnZaaUJRY205alpYTnpLU0I3WEc0Z0lDQWdJQ0FnY21WMGRYSnVJR2xrTG5CcFpEdGNiaUFnSUNCOUlHVnNjMlVnZTF4dUlDQWdJQ0FnSUd4bGRDQndhV1FnUFNCMGFHbHpMbkpsWjJsemRHVnlaV1FvYVdRcE8xeHVJQ0FnSUNBZ0lHbG1JQ2h3YVdRZ1BUMDlJRzUxYkd3cFhHNGdJQ0FnSUNBZ0lDQWdkR2h5YjNjb1hDSlFjbTlqWlhOeklHNWhiV1VnYm05MElISmxaMmx6ZEdWeVpXUTZJRndpSUNzZ2FXUWdLeUJjSWlBb1hDSWdLeUIwZVhCbGIyWW9hV1FwSUNzZ1hDSXBYQ0lwTzF4dUlDQWdJQ0FnSUhKbGRIVnliaUJ3YVdRN1hHNGdJQ0FnZlZ4dUlDQjlYRzVjYmlBZ2NIVjBLR2xrTENCclpYa3NJSFpoYkhWbEtYdGNiaUFnSUNCc1pYUWdjR2xrSUQwZ2RHaHBjeTV3YVdSdlppaHBaQ2s3WEc0Z0lDQWdiR1YwSUhCeWIyTmxjM01nUFNCMGFHbHpMbkJwWkhNdVoyVjBLSEJwWkNrN1hHNGdJQ0FnY0hKdlkyVnpjeTVrYVdOMFcydGxlVjBnUFNCMllXeDFaVHRjYmlBZ2ZWeHVYRzRnSUdkbGRDaHBaQ3dnYTJWNUtYdGNiaUFnSUNCc1pYUWdjR2xrSUQwZ2RHaHBjeTV3YVdSdlppaHBaQ2s3WEc0Z0lDQWdiR1YwSUhCeWIyTmxjM01nUFNCMGFHbHpMbkJwWkhNdVoyVjBLSEJwWkNrN1hHNWNiaUFnSUNCcFppaHJaWGtnSVQwZ2JuVnNiQ2w3WEc0Z0lDQWdJQ0J5WlhSMWNtNGdjSEp2WTJWemN5NWthV04wVzJ0bGVWMDdYRzRnSUNBZ2ZXVnNjMlY3WEc0Z0lDQWdJQ0J5WlhSMWNtNGdjSEp2WTJWemN5NWthV04wTzF4dUlDQWdJSDFjYmlBZ2ZWeHVYRzRnSUdkbGRGOXJaWGx6S0dsa0tYdGNiaUFnSUNCc1pYUWdjR2xrSUQwZ2RHaHBjeTV3YVdSdlppaHBaQ2s3WEc0Z0lDQWdiR1YwSUhCeWIyTmxjM01nUFNCMGFHbHpMbkJwWkhNdVoyVjBLSEJwWkNrN1hHNWNiaUFnSUNCeVpYUjFjbTRnVDJKcVpXTjBMbXRsZVhNb2NISnZZMlZ6Y3k1a2FXTjBLVHRjYmlBZ2ZWeHVYRzRnSUdWeVlYTmxLR2xrTENCclpYa3BlMXh1SUNBZ0lHeGxkQ0J3YVdRZ1BTQjBhR2x6TG5CcFpHOW1LR2xrS1R0Y2JpQWdJQ0JzWlhRZ2NISnZZMlZ6Y3lBOUlIUm9hWE11Y0dsa2N5NW5aWFFvY0dsa0tUdGNibHh1SUNBZ0lHbG1LR3RsZVNBaFBTQnVkV3hzS1h0Y2JpQWdJQ0FnSUdSbGJHVjBaU0J3Y205alpYTnpMbVJwWTNSYmEyVjVYVHRjYmlBZ0lDQjlaV3h6Wlh0Y2JpQWdJQ0FnSUhCeWIyTmxjM011WkdsamRDQTlJSHQ5TzF4dUlDQWdJSDFjYmlBZ2ZWeHVmVnh1WEc1bGVIQnZjblFnWkdWbVlYVnNkQ0JRY205alpYTnpVM2x6ZEdWdE8xeHVJbDBzSW5OdmRYSmpaVkp2YjNRaU9pSXZjMjkxY21ObEx5SjlcbiIsImNsYXNzIEJpdFN0cmluZyB7XG4gIGNvbnN0cnVjdG9yKC4uLmFyZ3MpIHtcbiAgICB0aGlzLnZhbHVlID0gT2JqZWN0LmZyZWV6ZSh0aGlzLnByb2Nlc3MoYXJncykpO1xuICAgIHRoaXMubGVuZ3RoID0gdGhpcy52YWx1ZS5sZW5ndGg7XG4gICAgdGhpcy5iaXRfc2l6ZSA9IHRoaXMubGVuZ3RoICogODtcbiAgICB0aGlzLmJ5dGVfc2l6ZSA9IHRoaXMubGVuZ3RoO1xuICB9XG5cbiAgZ2V0KGluZGV4KSB7XG4gICAgcmV0dXJuIHRoaXMudmFsdWVbaW5kZXhdO1xuICB9XG5cbiAgY291bnQoKSB7XG4gICAgcmV0dXJuIHRoaXMudmFsdWUubGVuZ3RoO1xuICB9XG5cbiAgc2xpY2Uoc3RhcnQsIGVuZCA9IG51bGwpIHtcbiAgICBsZXQgcyA9IHRoaXMudmFsdWUuc2xpY2Uoc3RhcnQsIGVuZCk7XG4gICAgbGV0IG1zID0gcy5tYXAoZWxlbSA9PiBCaXRTdHJpbmcuaW50ZWdlcihlbGVtKSk7XG4gICAgcmV0dXJuIG5ldyBCaXRTdHJpbmcoLi4ubXMpO1xuICB9XG5cbiAgW1N5bWJvbC5pdGVyYXRvcl0oKSB7XG4gICAgcmV0dXJuIHRoaXMudmFsdWVbU3ltYm9sLml0ZXJhdG9yXSgpO1xuICB9XG5cbiAgdG9TdHJpbmcoKSB7XG4gICAgdmFyIGksXG4gICAgICAgIHMgPSBcIlwiO1xuICAgIGZvciAoaSA9IDA7IGkgPCB0aGlzLmNvdW50KCk7IGkrKykge1xuICAgICAgaWYgKHMgIT09IFwiXCIpIHtcbiAgICAgICAgcyArPSBcIiwgXCI7XG4gICAgICB9XG4gICAgICBzICs9IHRoaXMuZ2V0KGkpLnRvU3RyaW5nKCk7XG4gICAgfVxuXG4gICAgcmV0dXJuIFwiPDxcIiArIHMgKyBcIj4+XCI7XG4gIH1cblxuICBwcm9jZXNzKGJpdFN0cmluZ1BhcnRzKSB7XG4gICAgbGV0IHByb2Nlc3NlZF92YWx1ZXMgPSBbXTtcblxuICAgIHZhciBpO1xuICAgIGZvciAoaSA9IDA7IGkgPCBiaXRTdHJpbmdQYXJ0cy5sZW5ndGg7IGkrKykge1xuICAgICAgbGV0IHByb2Nlc3NlZF92YWx1ZSA9IHRoaXNbJ3Byb2Nlc3NfJyArIGJpdFN0cmluZ1BhcnRzW2ldLnR5cGVdKGJpdFN0cmluZ1BhcnRzW2ldKTtcblxuICAgICAgZm9yIChsZXQgYXR0ciBvZiBiaXRTdHJpbmdQYXJ0c1tpXS5hdHRyaWJ1dGVzKSB7XG4gICAgICAgIHByb2Nlc3NlZF92YWx1ZSA9IHRoaXNbJ3Byb2Nlc3NfJyArIGF0dHJdKHByb2Nlc3NlZF92YWx1ZSk7XG4gICAgICB9XG5cbiAgICAgIHByb2Nlc3NlZF92YWx1ZXMgPSBwcm9jZXNzZWRfdmFsdWVzLmNvbmNhdChwcm9jZXNzZWRfdmFsdWUpO1xuICAgIH1cblxuICAgIHJldHVybiBwcm9jZXNzZWRfdmFsdWVzO1xuICB9XG5cbiAgcHJvY2Vzc19pbnRlZ2VyKHZhbHVlKSB7XG4gICAgcmV0dXJuIHZhbHVlLnZhbHVlO1xuICB9XG5cbiAgcHJvY2Vzc19mbG9hdCh2YWx1ZSkge1xuICAgIGlmICh2YWx1ZS5zaXplID09PSA2NCkge1xuICAgICAgcmV0dXJuIEJpdFN0cmluZy5mbG9hdDY0VG9CeXRlcyh2YWx1ZS52YWx1ZSk7XG4gICAgfSBlbHNlIGlmICh2YWx1ZS5zaXplID09PSAzMikge1xuICAgICAgcmV0dXJuIEJpdFN0cmluZy5mbG9hdDMyVG9CeXRlcyh2YWx1ZS52YWx1ZSk7XG4gICAgfVxuXG4gICAgdGhyb3cgbmV3IEVycm9yKCdJbnZhbGlkIHNpemUgZm9yIGZsb2F0Jyk7XG4gIH1cblxuICBwcm9jZXNzX2JpdHN0cmluZyh2YWx1ZSkge1xuICAgIHJldHVybiB2YWx1ZS52YWx1ZS52YWx1ZTtcbiAgfVxuXG4gIHByb2Nlc3NfYmluYXJ5KHZhbHVlKSB7XG4gICAgcmV0dXJuIEJpdFN0cmluZy50b1VURjhBcnJheSh2YWx1ZS52YWx1ZSk7XG4gIH1cblxuICBwcm9jZXNzX3V0ZjgodmFsdWUpIHtcbiAgICByZXR1cm4gQml0U3RyaW5nLnRvVVRGOEFycmF5KHZhbHVlLnZhbHVlKTtcbiAgfVxuXG4gIHByb2Nlc3NfdXRmMTYodmFsdWUpIHtcbiAgICByZXR1cm4gQml0U3RyaW5nLnRvVVRGMTZBcnJheSh2YWx1ZS52YWx1ZSk7XG4gIH1cblxuICBwcm9jZXNzX3V0ZjMyKHZhbHVlKSB7XG4gICAgcmV0dXJuIEJpdFN0cmluZy50b1VURjMyQXJyYXkodmFsdWUudmFsdWUpO1xuICB9XG5cbiAgcHJvY2Vzc19zaWduZWQodmFsdWUpIHtcbiAgICByZXR1cm4gbmV3IFVpbnQ4QXJyYXkoW3ZhbHVlXSlbMF07XG4gIH1cblxuICBwcm9jZXNzX3Vuc2lnbmVkKHZhbHVlKSB7XG4gICAgcmV0dXJuIHZhbHVlO1xuICB9XG5cbiAgcHJvY2Vzc19uYXRpdmUodmFsdWUpIHtcbiAgICByZXR1cm4gdmFsdWU7XG4gIH1cblxuICBwcm9jZXNzX2JpZyh2YWx1ZSkge1xuICAgIHJldHVybiB2YWx1ZTtcbiAgfVxuXG4gIHByb2Nlc3NfbGl0dGxlKHZhbHVlKSB7XG4gICAgcmV0dXJuIHZhbHVlLnJldmVyc2UoKTtcbiAgfVxuXG4gIHByb2Nlc3Nfc2l6ZSh2YWx1ZSkge1xuICAgIHJldHVybiB2YWx1ZTtcbiAgfVxuXG4gIHByb2Nlc3NfdW5pdCh2YWx1ZSkge1xuICAgIHJldHVybiB2YWx1ZTtcbiAgfVxuXG4gIHN0YXRpYyBpbnRlZ2VyKHZhbHVlKSB7XG4gICAgcmV0dXJuIEJpdFN0cmluZy53cmFwKHZhbHVlLCB7ICd0eXBlJzogJ2ludGVnZXInLCAndW5pdCc6IDEsICdzaXplJzogOCB9KTtcbiAgfVxuXG4gIHN0YXRpYyBmbG9hdCh2YWx1ZSkge1xuICAgIHJldHVybiBCaXRTdHJpbmcud3JhcCh2YWx1ZSwgeyAndHlwZSc6ICdmbG9hdCcsICd1bml0JzogMSwgJ3NpemUnOiA2NCB9KTtcbiAgfVxuXG4gIHN0YXRpYyBiaXRzdHJpbmcodmFsdWUpIHtcbiAgICByZXR1cm4gQml0U3RyaW5nLndyYXAodmFsdWUsIHsgJ3R5cGUnOiAnYml0c3RyaW5nJywgJ3VuaXQnOiAxLCAnc2l6ZSc6IHZhbHVlLmJpdF9zaXplIH0pO1xuICB9XG5cbiAgc3RhdGljIGJpdHModmFsdWUpIHtcbiAgICByZXR1cm4gQml0U3RyaW5nLmJpdHN0cmluZyh2YWx1ZSk7XG4gIH1cblxuICBzdGF0aWMgYmluYXJ5KHZhbHVlKSB7XG4gICAgcmV0dXJuIEJpdFN0cmluZy53cmFwKHZhbHVlLCB7ICd0eXBlJzogJ2JpbmFyeScsICd1bml0JzogOCwgJ3NpemUnOiB2YWx1ZS5sZW5ndGggfSk7XG4gIH1cblxuICBzdGF0aWMgYnl0ZXModmFsdWUpIHtcbiAgICByZXR1cm4gQml0U3RyaW5nLmJpbmFyeSh2YWx1ZSk7XG4gIH1cblxuICBzdGF0aWMgdXRmOCh2YWx1ZSkge1xuICAgIHJldHVybiBCaXRTdHJpbmcud3JhcCh2YWx1ZSwgeyAndHlwZSc6ICd1dGY4JywgJ3VuaXQnOiAxLCAnc2l6ZSc6IHZhbHVlLmxlbmd0aCB9KTtcbiAgfVxuXG4gIHN0YXRpYyB1dGYxNih2YWx1ZSkge1xuICAgIHJldHVybiBCaXRTdHJpbmcud3JhcCh2YWx1ZSwgeyAndHlwZSc6ICd1dGYxNicsICd1bml0JzogMSwgJ3NpemUnOiB2YWx1ZS5sZW5ndGggKiAyIH0pO1xuICB9XG5cbiAgc3RhdGljIHV0ZjMyKHZhbHVlKSB7XG4gICAgcmV0dXJuIEJpdFN0cmluZy53cmFwKHZhbHVlLCB7ICd0eXBlJzogJ3V0ZjMyJywgJ3VuaXQnOiAxLCAnc2l6ZSc6IHZhbHVlLmxlbmd0aCAqIDQgfSk7XG4gIH1cblxuICBzdGF0aWMgc2lnbmVkKHZhbHVlKSB7XG4gICAgcmV0dXJuIEJpdFN0cmluZy53cmFwKHZhbHVlLCB7fSwgJ3NpZ25lZCcpO1xuICB9XG5cbiAgc3RhdGljIHVuc2lnbmVkKHZhbHVlKSB7XG4gICAgcmV0dXJuIEJpdFN0cmluZy53cmFwKHZhbHVlLCB7fSwgJ3Vuc2lnbmVkJyk7XG4gIH1cblxuICBzdGF0aWMgbmF0aXZlKHZhbHVlKSB7XG4gICAgcmV0dXJuIEJpdFN0cmluZy53cmFwKHZhbHVlLCB7fSwgJ25hdGl2ZScpO1xuICB9XG5cbiAgc3RhdGljIGJpZyh2YWx1ZSkge1xuICAgIHJldHVybiBCaXRTdHJpbmcud3JhcCh2YWx1ZSwge30sICdiaWcnKTtcbiAgfVxuXG4gIHN0YXRpYyBsaXR0bGUodmFsdWUpIHtcbiAgICByZXR1cm4gQml0U3RyaW5nLndyYXAodmFsdWUsIHt9LCAnbGl0dGxlJyk7XG4gIH1cblxuICBzdGF0aWMgc2l6ZSh2YWx1ZSwgY291bnQpIHtcbiAgICByZXR1cm4gQml0U3RyaW5nLndyYXAodmFsdWUsIHsgJ3NpemUnOiBjb3VudCB9KTtcbiAgfVxuXG4gIHN0YXRpYyB1bml0KHZhbHVlLCBjb3VudCkge1xuICAgIHJldHVybiBCaXRTdHJpbmcud3JhcCh2YWx1ZSwgeyAndW5pdCc6IGNvdW50IH0pO1xuICB9XG5cbiAgc3RhdGljIHdyYXAodmFsdWUsIG9wdCwgbmV3X2F0dHJpYnV0ZSA9IG51bGwpIHtcbiAgICBsZXQgdGhlX3ZhbHVlID0gdmFsdWU7XG5cbiAgICBpZiAoISh2YWx1ZSBpbnN0YW5jZW9mIE9iamVjdCkpIHtcbiAgICAgIHRoZV92YWx1ZSA9IHsgJ3ZhbHVlJzogdmFsdWUsICdhdHRyaWJ1dGVzJzogW10gfTtcbiAgICB9XG5cbiAgICB0aGVfdmFsdWUgPSBPYmplY3QuYXNzaWduKHRoZV92YWx1ZSwgb3B0KTtcblxuICAgIGlmIChuZXdfYXR0cmlidXRlKSB7XG4gICAgICB0aGVfdmFsdWUuYXR0cmlidXRlcy5wdXNoKG5ld19hdHRyaWJ1dGUpO1xuICAgIH1cblxuICAgIHJldHVybiB0aGVfdmFsdWU7XG4gIH1cblxuICBzdGF0aWMgdG9VVEY4QXJyYXkoc3RyKSB7XG4gICAgdmFyIHV0ZjggPSBbXTtcbiAgICBmb3IgKHZhciBpID0gMDsgaSA8IHN0ci5sZW5ndGg7IGkrKykge1xuICAgICAgdmFyIGNoYXJjb2RlID0gc3RyLmNoYXJDb2RlQXQoaSk7XG4gICAgICBpZiAoY2hhcmNvZGUgPCAweDgwKSB7XG4gICAgICAgIHV0ZjgucHVzaChjaGFyY29kZSk7XG4gICAgICB9IGVsc2UgaWYgKGNoYXJjb2RlIDwgMHg4MDApIHtcbiAgICAgICAgdXRmOC5wdXNoKDB4YzAgfCBjaGFyY29kZSA+PiA2LCAweDgwIHwgY2hhcmNvZGUgJiAweDNmKTtcbiAgICAgIH0gZWxzZSBpZiAoY2hhcmNvZGUgPCAweGQ4MDAgfHwgY2hhcmNvZGUgPj0gMHhlMDAwKSB7XG4gICAgICAgIHV0ZjgucHVzaCgweGUwIHwgY2hhcmNvZGUgPj4gMTIsIDB4ODAgfCBjaGFyY29kZSA+PiA2ICYgMHgzZiwgMHg4MCB8IGNoYXJjb2RlICYgMHgzZik7XG4gICAgICB9XG4gICAgICAvLyBzdXJyb2dhdGUgcGFpclxuICAgICAgZWxzZSB7XG4gICAgICAgICAgaSsrO1xuICAgICAgICAgIC8vIFVURi0xNiBlbmNvZGVzIDB4MTAwMDAtMHgxMEZGRkYgYnlcbiAgICAgICAgICAvLyBzdWJ0cmFjdGluZyAweDEwMDAwIGFuZCBzcGxpdHRpbmcgdGhlXG4gICAgICAgICAgLy8gMjAgYml0cyBvZiAweDAtMHhGRkZGRiBpbnRvIHR3byBoYWx2ZXNcbiAgICAgICAgICBjaGFyY29kZSA9IDB4MTAwMDAgKyAoKGNoYXJjb2RlICYgMHgzZmYpIDw8IDEwIHwgc3RyLmNoYXJDb2RlQXQoaSkgJiAweDNmZik7XG4gICAgICAgICAgdXRmOC5wdXNoKDB4ZjAgfCBjaGFyY29kZSA+PiAxOCwgMHg4MCB8IGNoYXJjb2RlID4+IDEyICYgMHgzZiwgMHg4MCB8IGNoYXJjb2RlID4+IDYgJiAweDNmLCAweDgwIHwgY2hhcmNvZGUgJiAweDNmKTtcbiAgICAgICAgfVxuICAgIH1cbiAgICByZXR1cm4gdXRmODtcbiAgfVxuXG4gIHN0YXRpYyB0b1VURjE2QXJyYXkoc3RyKSB7XG4gICAgdmFyIHV0ZjE2ID0gW107XG4gICAgZm9yICh2YXIgaSA9IDA7IGkgPCBzdHIubGVuZ3RoOyBpKyspIHtcbiAgICAgIHZhciBjb2RlUG9pbnQgPSBzdHIuY29kZVBvaW50QXQoaSk7XG5cbiAgICAgIGlmIChjb2RlUG9pbnQgPD0gMjU1KSB7XG4gICAgICAgIHV0ZjE2LnB1c2goMCk7XG4gICAgICAgIHV0ZjE2LnB1c2goY29kZVBvaW50KTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHV0ZjE2LnB1c2goY29kZVBvaW50ID4+IDggJiAweEZGKTtcbiAgICAgICAgdXRmMTYucHVzaChjb2RlUG9pbnQgJiAweEZGKTtcbiAgICAgIH1cbiAgICB9XG4gICAgcmV0dXJuIHV0ZjE2O1xuICB9XG5cbiAgc3RhdGljIHRvVVRGMzJBcnJheShzdHIpIHtcbiAgICB2YXIgdXRmMzIgPSBbXTtcbiAgICBmb3IgKHZhciBpID0gMDsgaSA8IHN0ci5sZW5ndGg7IGkrKykge1xuICAgICAgdmFyIGNvZGVQb2ludCA9IHN0ci5jb2RlUG9pbnRBdChpKTtcblxuICAgICAgaWYgKGNvZGVQb2ludCA8PSAyNTUpIHtcbiAgICAgICAgdXRmMzIucHVzaCgwKTtcbiAgICAgICAgdXRmMzIucHVzaCgwKTtcbiAgICAgICAgdXRmMzIucHVzaCgwKTtcbiAgICAgICAgdXRmMzIucHVzaChjb2RlUG9pbnQpO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgdXRmMzIucHVzaCgwKTtcbiAgICAgICAgdXRmMzIucHVzaCgwKTtcbiAgICAgICAgdXRmMzIucHVzaChjb2RlUG9pbnQgPj4gOCAmIDB4RkYpO1xuICAgICAgICB1dGYzMi5wdXNoKGNvZGVQb2ludCAmIDB4RkYpO1xuICAgICAgfVxuICAgIH1cbiAgICByZXR1cm4gdXRmMzI7XG4gIH1cblxuICAvL2h0dHA6Ly9zdGFja292ZXJmbG93LmNvbS9xdWVzdGlvbnMvMjAwMzQ5My9qYXZhc2NyaXB0LWZsb2F0LWZyb20tdG8tYml0c1xuICBzdGF0aWMgZmxvYXQzMlRvQnl0ZXMoZikge1xuICAgIHZhciBieXRlcyA9IFtdO1xuXG4gICAgdmFyIGJ1ZiA9IG5ldyBBcnJheUJ1ZmZlcig0KTtcbiAgICBuZXcgRmxvYXQzMkFycmF5KGJ1ZilbMF0gPSBmO1xuXG4gICAgbGV0IGludFZlcnNpb24gPSBuZXcgVWludDMyQXJyYXkoYnVmKVswXTtcblxuICAgIGJ5dGVzLnB1c2goaW50VmVyc2lvbiA+PiAyNCAmIDB4RkYpO1xuICAgIGJ5dGVzLnB1c2goaW50VmVyc2lvbiA+PiAxNiAmIDB4RkYpO1xuICAgIGJ5dGVzLnB1c2goaW50VmVyc2lvbiA+PiA4ICYgMHhGRik7XG4gICAgYnl0ZXMucHVzaChpbnRWZXJzaW9uICYgMHhGRik7XG5cbiAgICByZXR1cm4gYnl0ZXM7XG4gIH1cblxuICBzdGF0aWMgZmxvYXQ2NFRvQnl0ZXMoZikge1xuICAgIHZhciBieXRlcyA9IFtdO1xuXG4gICAgdmFyIGJ1ZiA9IG5ldyBBcnJheUJ1ZmZlcig4KTtcbiAgICBuZXcgRmxvYXQ2NEFycmF5KGJ1ZilbMF0gPSBmO1xuXG4gICAgdmFyIGludFZlcnNpb24xID0gbmV3IFVpbnQzMkFycmF5KGJ1ZilbMF07XG4gICAgdmFyIGludFZlcnNpb24yID0gbmV3IFVpbnQzMkFycmF5KGJ1ZilbMV07XG5cbiAgICBieXRlcy5wdXNoKGludFZlcnNpb24yID4+IDI0ICYgMHhGRik7XG4gICAgYnl0ZXMucHVzaChpbnRWZXJzaW9uMiA+PiAxNiAmIDB4RkYpO1xuICAgIGJ5dGVzLnB1c2goaW50VmVyc2lvbjIgPj4gOCAmIDB4RkYpO1xuICAgIGJ5dGVzLnB1c2goaW50VmVyc2lvbjIgJiAweEZGKTtcblxuICAgIGJ5dGVzLnB1c2goaW50VmVyc2lvbjEgPj4gMjQgJiAweEZGKTtcbiAgICBieXRlcy5wdXNoKGludFZlcnNpb24xID4+IDE2ICYgMHhGRik7XG4gICAgYnl0ZXMucHVzaChpbnRWZXJzaW9uMSA+PiA4ICYgMHhGRik7XG4gICAgYnl0ZXMucHVzaChpbnRWZXJzaW9uMSAmIDB4RkYpO1xuXG4gICAgcmV0dXJuIGJ5dGVzO1xuICB9XG59XG5cbmV4cG9ydCBkZWZhdWx0IEJpdFN0cmluZztcbi8vIyBzb3VyY2VNYXBwaW5nVVJMPWRhdGE6YXBwbGljYXRpb24vanNvbjtiYXNlNjQsZXlKMlpYSnphVzl1SWpvekxDSnpiM1Z5WTJWeklqcGJJbXhwWWk5amIzSmxMMkpwZEY5emRISnBibWN1YW5NaVhTd2libUZ0WlhNaU9sdGRMQ0p0WVhCd2FXNW5jeUk2SWtGQlFVRXNUVUZCVFN4VFFVRk9MRU5CUVdkQ08wRkJRMlFzWTBGQldTeEhRVUZITEVsQlFVZ3NSVUZCVVR0QlFVTnNRaXhUUVVGTExFdEJRVXdzUjBGQllTeFBRVUZQTEUxQlFWQXNRMEZCWXl4TFFVRkxMRTlCUVV3c1EwRkJZU3hKUVVGaUxFTkJRV1FzUTBGQllpeERRVVJyUWp0QlFVVnNRaXhUUVVGTExFMUJRVXdzUjBGQll5eExRVUZMTEV0QlFVd3NRMEZCVnl4TlFVRllMRU5CUmtrN1FVRkhiRUlzVTBGQlN5eFJRVUZNTEVkQlFXZENMRXRCUVVzc1RVRkJUQ3hIUVVGakxFTkJRV1FzUTBGSVJUdEJRVWxzUWl4VFFVRkxMRk5CUVV3c1IwRkJhVUlzUzBGQlN5eE5RVUZNTEVOQlNrTTdSMEZCY0VJN08wRkJUMEVzVFVGQlNTeExRVUZLTEVWQlFWVTdRVUZEVWl4WFFVRlBMRXRCUVVzc1MwRkJUQ3hEUVVGWExFdEJRVmdzUTBGQlVDeERRVVJSTzBkQlFWWTdPMEZCU1VFc1ZVRkJUenRCUVVOTUxGZEJRVThzUzBGQlN5eExRVUZNTEVOQlFWY3NUVUZCV0N4RFFVUkdPMGRCUVZBN08wRkJTVUVzVVVGQlRTeExRVUZPTEVWQlFXRXNUVUZCVFN4SlFVRk9MRVZCUVZjN1FVRkRkRUlzVVVGQlNTeEpRVUZKTEV0QlFVc3NTMEZCVEN4RFFVRlhMRXRCUVZnc1EwRkJhVUlzUzBGQmFrSXNSVUZCZDBJc1IwRkJlRUlzUTBGQlNpeERRVVJyUWp0QlFVVjBRaXhSUVVGSkxFdEJRVXNzUlVGQlJTeEhRVUZHTEVOQlFVMHNVVUZCVlN4VlFVRlZMRTlCUVZZc1EwRkJhMElzU1VGQmJFSXNRMEZCVml4RFFVRllMRU5CUm10Q08wRkJSM1JDTEZkQlFVOHNTVUZCU1N4VFFVRktMRU5CUVdNc1IwRkJSeXhGUVVGSUxFTkJRWEpDTEVOQlNITkNPMGRCUVhoQ096dEJRVTFCTEVkQlFVTXNUMEZCVHl4UlFVRlFMRWxCUVcxQ08wRkJRMnhDTEZkQlFVOHNTMEZCU3l4TFFVRk1MRU5CUVZjc1QwRkJUeXhSUVVGUUxFTkJRVmdzUlVGQlVDeERRVVJyUWp0SFFVRndRanM3UVVGSlFTeGhRVUZWTzBGQlExSXNVVUZCU1N4RFFVRktPMUZCUVU4c1NVRkJTU3hGUVVGS0xFTkJSRU03UVVGRlVpeFRRVUZMTEVsQlFVa3NRMEZCU2l4RlFVRlBMRWxCUVVrc1MwRkJTeXhMUVVGTUxFVkJRVW9zUlVGQmEwSXNSMEZCT1VJc1JVRkJiVU03UVVGRGFrTXNWVUZCU1N4TlFVRk5MRVZCUVU0c1JVRkJWVHRCUVVOYUxHRkJRVXNzU1VGQlRDeERRVVJaTzA5QlFXUTdRVUZIUVN4WFFVRkxMRXRCUVVzc1IwRkJUQ3hEUVVGVExFTkJRVlFzUlVGQldTeFJRVUZhTEVWQlFVd3NRMEZLYVVNN1MwRkJia003TzBGQlQwRXNWMEZCVHl4UFFVRlBMRU5CUVZBc1IwRkJWeXhKUVVGWUxFTkJWRU03UjBGQlZqczdRVUZaUVN4VlFVRlJMR05CUVZJc1JVRkJkVUk3UVVGRGNrSXNVVUZCU1N4dFFrRkJiVUlzUlVGQmJrSXNRMEZFYVVJN08wRkJSM0pDTEZGQlFVa3NRMEZCU2l4RFFVaHhRanRCUVVseVFpeFRRVUZMTEVsQlFVa3NRMEZCU2l4RlFVRlBMRWxCUVVrc1pVRkJaU3hOUVVGbUxFVkJRWFZDTEVkQlFYWkRMRVZCUVRSRE8wRkJRekZETEZWQlFVa3NhMEpCUVd0Q0xFdEJRVXNzWVVGQllTeGxRVUZsTEVOQlFXWXNSVUZCYTBJc1NVRkJiRUlzUTBGQmJFSXNRMEZCTUVNc1pVRkJaU3hEUVVGbUxFTkJRVEZETEVOQlFXeENMRU5CUkhORE96dEJRVWN4UXl4WFFVRkpMRWxCUVVrc1NVRkJTaXhKUVVGWkxHVkJRV1VzUTBGQlppeEZRVUZyUWl4VlFVRnNRaXhGUVVFMlFqdEJRVU16UXl3d1FrRkJhMElzUzBGQlN5eGhRVUZoTEVsQlFXSXNRMEZCVEN4RFFVRjNRaXhsUVVGNFFpeERRVUZzUWl4RFFVUXlRenRQUVVFM1F6czdRVUZKUVN4NVFrRkJiVUlzYVVKQlFXbENMRTFCUVdwQ0xFTkJRWGRDTEdWQlFYaENMRU5CUVc1Q0xFTkJVREJETzB0QlFUVkRPenRCUVZWQkxGZEJRVThzWjBKQlFWQXNRMEZrY1VJN1IwRkJka0k3TzBGQmFVSkJMR3RDUVVGblFpeExRVUZvUWl4RlFVRnpRanRCUVVOd1FpeFhRVUZQTEUxQlFVMHNTMEZCVGl4RFFVUmhPMGRCUVhSQ096dEJRVWxCTEdkQ1FVRmpMRXRCUVdRc1JVRkJiMEk3UVVGRGJFSXNVVUZCUnl4TlFVRk5MRWxCUVU0c1MwRkJaU3hGUVVGbUxFVkJRV3RDTzBGQlEyNUNMR0ZCUVU4c1ZVRkJWU3hqUVVGV0xFTkJRWGxDTEUxQlFVMHNTMEZCVGl4RFFVRm9ReXhEUVVSdFFqdExRVUZ5UWl4TlFVVk5MRWxCUVVjc1RVRkJUU3hKUVVGT0xFdEJRV1VzUlVGQlppeEZRVUZyUWp0QlFVTjZRaXhoUVVGUExGVkJRVlVzWTBGQlZpeERRVUY1UWl4TlFVRk5MRXRCUVU0c1EwRkJhRU1zUTBGRWVVSTdTMEZCY2tJN08wRkJTVTRzVlVGQlRTeEpRVUZKTEV0QlFVb3NRMEZCVlN4M1FrRkJWaXhEUVVGT0xFTkJVR3RDTzBkQlFYQkNPenRCUVZWQkxHOUNRVUZyUWl4TFFVRnNRaXhGUVVGM1FqdEJRVU4wUWl4WFFVRlBMRTFCUVUwc1MwRkJUaXhEUVVGWkxFdEJRVm9zUTBGRVpUdEhRVUY0UWpzN1FVRkpRU3hwUWtGQlpTeExRVUZtTEVWQlFYRkNPMEZCUTI1Q0xGZEJRVThzVlVGQlZTeFhRVUZXTEVOQlFYTkNMRTFCUVUwc1MwRkJUaXhEUVVFM1FpeERRVVJ0UWp0SFFVRnlRanM3UVVGSlFTeGxRVUZoTEV0QlFXSXNSVUZCYlVJN1FVRkRha0lzVjBGQlR5eFZRVUZWTEZkQlFWWXNRMEZCYzBJc1RVRkJUU3hMUVVGT0xFTkJRVGRDTEVOQlJHbENPMGRCUVc1Q096dEJRVWxCTEdkQ1FVRmpMRXRCUVdRc1JVRkJiMEk3UVVGRGJFSXNWMEZCVHl4VlFVRlZMRmxCUVZZc1EwRkJkVUlzVFVGQlRTeExRVUZPTEVOQlFUbENMRU5CUkd0Q08wZEJRWEJDT3p0QlFVbEJMR2RDUVVGakxFdEJRV1FzUlVGQmIwSTdRVUZEYkVJc1YwRkJUeXhWUVVGVkxGbEJRVllzUTBGQmRVSXNUVUZCVFN4TFFVRk9MRU5CUVRsQ0xFTkJSR3RDTzBkQlFYQkNPenRCUVVsQkxHbENRVUZsTEV0QlFXWXNSVUZCY1VJN1FVRkRia0lzVjBGQlR5eEpRVUZMTEZWQlFVb3NRMEZCWlN4RFFVRkRMRXRCUVVRc1EwRkJaaXhEUVVGRUxFTkJRVEJDTEVOQlFURkNMRU5CUVZBc1EwRkViVUk3UjBGQmNrSTdPMEZCU1VFc2JVSkJRV2xDTEV0QlFXcENMRVZCUVhWQ08wRkJRM0pDTEZkQlFVOHNTMEZCVUN4RFFVUnhRanRIUVVGMlFqczdRVUZKUVN4cFFrRkJaU3hMUVVGbUxFVkJRWEZDTzBGQlEyNUNMRmRCUVU4c1MwRkJVQ3hEUVVSdFFqdEhRVUZ5UWpzN1FVRkpRU3hqUVVGWkxFdEJRVm9zUlVGQmEwSTdRVUZEYUVJc1YwRkJUeXhMUVVGUUxFTkJSR2RDTzBkQlFXeENPenRCUVVsQkxHbENRVUZsTEV0QlFXWXNSVUZCY1VJN1FVRkRia0lzVjBGQlR5eE5RVUZOTEU5QlFVNHNSVUZCVUN4RFFVUnRRanRIUVVGeVFqczdRVUZKUVN4bFFVRmhMRXRCUVdJc1JVRkJiVUk3UVVGRGFrSXNWMEZCVHl4TFFVRlFMRU5CUkdsQ08wZEJRVzVDT3p0QlFVbEJMR1ZCUVdFc1MwRkJZaXhGUVVGdFFqdEJRVU5xUWl4WFFVRlBMRXRCUVZBc1EwRkVhVUk3UjBGQmJrSTdPMEZCU1VFc1UwRkJUeXhQUVVGUUxFTkJRV1VzUzBGQlppeEZRVUZ4UWp0QlFVTnVRaXhYUVVGUExGVkJRVlVzU1VGQlZpeERRVUZsTEV0QlFXWXNSVUZCYzBJc1JVRkJSU3hSUVVGUkxGTkJRVklzUlVGQmJVSXNVVUZCVVN4RFFVRlNMRVZCUVZjc1VVRkJVU3hEUVVGU0xFVkJRWFJFTEVOQlFWQXNRMEZFYlVJN1IwRkJja0k3TzBGQlNVRXNVMEZCVHl4TFFVRlFMRU5CUVdFc1MwRkJZaXhGUVVGdFFqdEJRVU5xUWl4WFFVRlBMRlZCUVZVc1NVRkJWaXhEUVVGbExFdEJRV1lzUlVGQmMwSXNSVUZCUlN4UlFVRlJMRTlCUVZJc1JVRkJhVUlzVVVGQlVTeERRVUZTTEVWQlFWY3NVVUZCVVN4RlFVRlNMRVZCUVhCRUxFTkJRVkFzUTBGRWFVSTdSMEZCYmtJN08wRkJTVUVzVTBGQlR5eFRRVUZRTEVOQlFXbENMRXRCUVdwQ0xFVkJRWFZDTzBGQlEzSkNMRmRCUVU4c1ZVRkJWU3hKUVVGV0xFTkJRV1VzUzBGQlppeEZRVUZ6UWl4RlFVRkZMRkZCUVZFc1YwRkJVaXhGUVVGeFFpeFJRVUZSTEVOQlFWSXNSVUZCVnl4UlFVRlJMRTFCUVUwc1VVRkJUaXhGUVVGb1JTeERRVUZRTEVOQlJIRkNPMGRCUVhaQ096dEJRVWxCTEZOQlFVOHNTVUZCVUN4RFFVRlpMRXRCUVZvc1JVRkJhMEk3UVVGRGFFSXNWMEZCVHl4VlFVRlZMRk5CUVZZc1EwRkJiMElzUzBGQmNFSXNRMEZCVUN4RFFVUm5RanRIUVVGc1FqczdRVUZKUVN4VFFVRlBMRTFCUVZBc1EwRkJZeXhMUVVGa0xFVkJRVzlDTzBGQlEyeENMRmRCUVU4c1ZVRkJWU3hKUVVGV0xFTkJRV1VzUzBGQlppeEZRVUZ6UWl4RlFVRkZMRkZCUVZFc1VVRkJVaXhGUVVGclFpeFJRVUZSTEVOQlFWSXNSVUZCVnl4UlFVRlJMRTFCUVUwc1RVRkJUaXhGUVVFM1JDeERRVUZRTEVOQlJHdENPMGRCUVhCQ096dEJRVWxCTEZOQlFVOHNTMEZCVUN4RFFVRmhMRXRCUVdJc1JVRkJiVUk3UVVGRGFrSXNWMEZCVHl4VlFVRlZMRTFCUVZZc1EwRkJhVUlzUzBGQmFrSXNRMEZCVUN4RFFVUnBRanRIUVVGdVFqczdRVUZKUVN4VFFVRlBMRWxCUVZBc1EwRkJXU3hMUVVGYUxFVkJRV3RDTzBGQlEyaENMRmRCUVU4c1ZVRkJWU3hKUVVGV0xFTkJRV1VzUzBGQlppeEZRVUZ6UWl4RlFVRkZMRkZCUVZFc1RVRkJVaXhGUVVGblFpeFJRVUZSTEVOQlFWSXNSVUZCVnl4UlFVRlJMRTFCUVUwc1RVRkJUaXhGUVVFelJDeERRVUZRTEVOQlJHZENPMGRCUVd4Q096dEJRVWxCTEZOQlFVOHNTMEZCVUN4RFFVRmhMRXRCUVdJc1JVRkJiVUk3UVVGRGFrSXNWMEZCVHl4VlFVRlZMRWxCUVZZc1EwRkJaU3hMUVVGbUxFVkJRWE5DTEVWQlFVVXNVVUZCVVN4UFFVRlNMRVZCUVdsQ0xGRkJRVkVzUTBGQlVpeEZRVUZYTEZGQlFWRXNUVUZCVFN4TlFVRk9MRWRCUVdVc1EwRkJaaXhGUVVFMVJDeERRVUZRTEVOQlJHbENPMGRCUVc1Q096dEJRVWxCTEZOQlFVOHNTMEZCVUN4RFFVRmhMRXRCUVdJc1JVRkJiVUk3UVVGRGFrSXNWMEZCVHl4VlFVRlZMRWxCUVZZc1EwRkJaU3hMUVVGbUxFVkJRWE5DTEVWQlFVVXNVVUZCVVN4UFFVRlNMRVZCUVdsQ0xGRkJRVkVzUTBGQlVpeEZRVUZYTEZGQlFWRXNUVUZCVFN4TlFVRk9MRWRCUVdVc1EwRkJaaXhGUVVFMVJDeERRVUZRTEVOQlJHbENPMGRCUVc1Q096dEJRVWxCTEZOQlFVOHNUVUZCVUN4RFFVRmpMRXRCUVdRc1JVRkJiMEk3UVVGRGJFSXNWMEZCVHl4VlFVRlZMRWxCUVZZc1EwRkJaU3hMUVVGbUxFVkJRWE5DTEVWQlFYUkNMRVZCUVRCQ0xGRkJRVEZDTEVOQlFWQXNRMEZFYTBJN1IwRkJjRUk3TzBGQlNVRXNVMEZCVHl4UlFVRlFMRU5CUVdkQ0xFdEJRV2hDTEVWQlFYTkNPMEZCUTNCQ0xGZEJRVThzVlVGQlZTeEpRVUZXTEVOQlFXVXNTMEZCWml4RlFVRnpRaXhGUVVGMFFpeEZRVUV3UWl4VlFVRXhRaXhEUVVGUUxFTkJSRzlDTzBkQlFYUkNPenRCUVVsQkxGTkJRVThzVFVGQlVDeERRVUZqTEV0QlFXUXNSVUZCYjBJN1FVRkRiRUlzVjBGQlR5eFZRVUZWTEVsQlFWWXNRMEZCWlN4TFFVRm1MRVZCUVhOQ0xFVkJRWFJDTEVWQlFUQkNMRkZCUVRGQ0xFTkJRVkFzUTBGRWEwSTdSMEZCY0VJN08wRkJTVUVzVTBGQlR5eEhRVUZRTEVOQlFWY3NTMEZCV0N4RlFVRnBRanRCUVVObUxGZEJRVThzVlVGQlZTeEpRVUZXTEVOQlFXVXNTMEZCWml4RlFVRnpRaXhGUVVGMFFpeEZRVUV3UWl4TFFVRXhRaXhEUVVGUUxFTkJSR1U3UjBGQmFrSTdPMEZCU1VFc1UwRkJUeXhOUVVGUUxFTkJRV01zUzBGQlpDeEZRVUZ2UWp0QlFVTnNRaXhYUVVGUExGVkJRVlVzU1VGQlZpeERRVUZsTEV0QlFXWXNSVUZCYzBJc1JVRkJkRUlzUlVGQk1FSXNVVUZCTVVJc1EwRkJVQ3hEUVVSclFqdEhRVUZ3UWpzN1FVRkpRU3hUUVVGUExFbEJRVkFzUTBGQldTeExRVUZhTEVWQlFXMUNMRXRCUVc1Q0xFVkJRWGxDTzBGQlEzWkNMRmRCUVU4c1ZVRkJWU3hKUVVGV0xFTkJRV1VzUzBGQlppeEZRVUZ6UWl4RlFVRkRMRkZCUVZFc1MwRkJVaXhGUVVGMlFpeERRVUZRTEVOQlJIVkNPMGRCUVhwQ096dEJRVWxCTEZOQlFVOHNTVUZCVUN4RFFVRlpMRXRCUVZvc1JVRkJiVUlzUzBGQmJrSXNSVUZCZVVJN1FVRkRka0lzVjBGQlR5eFZRVUZWTEVsQlFWWXNRMEZCWlN4TFFVRm1MRVZCUVhOQ0xFVkJRVU1zVVVGQlVTeExRVUZTTEVWQlFYWkNMRU5CUVZBc1EwRkVkVUk3UjBGQmVrSTdPMEZCU1VFc1UwRkJUeXhKUVVGUUxFTkJRVmtzUzBGQldpeEZRVUZ0UWl4SFFVRnVRaXhGUVVGM1FpeG5Ra0ZCWjBJc1NVRkJhRUlzUlVGQmNVSTdRVUZETTBNc1VVRkJTU3haUVVGWkxFdEJRVm9zUTBGRWRVTTdPMEZCUnpORExGRkJRVWNzUlVGQlJTeHBRa0ZCYVVJc1RVRkJha0lzUTBGQlJpeEZRVUV5UWp0QlFVTTFRaXhyUWtGQldTeEZRVUZETEZOQlFWTXNTMEZCVkN4RlFVRm5RaXhqUVVGakxFVkJRV1FzUlVGQk4wSXNRMEZFTkVJN1MwRkJPVUk3TzBGQlNVRXNaMEpCUVZrc1QwRkJUeXhOUVVGUUxFTkJRV01zVTBGQlpDeEZRVUY1UWl4SFFVRjZRaXhEUVVGYUxFTkJVREpET3p0QlFWTXpReXhSUVVGSExHRkJRVWdzUlVGQmFVSTdRVUZEWml4blFrRkJWU3hWUVVGV0xFTkJRWEZDTEVsQlFYSkNMRU5CUVRCQ0xHRkJRVEZDTEVWQlJHVTdTMEZCYWtJN08wRkJTMEVzVjBGQlR5eFRRVUZRTEVOQlpESkRPMGRCUVRkRE96dEJRV2xDUVN4VFFVRlBMRmRCUVZBc1EwRkJiVUlzUjBGQmJrSXNSVUZCZDBJN1FVRkRkRUlzVVVGQlNTeFBRVUZQTEVWQlFWQXNRMEZFYTBJN1FVRkZkRUlzVTBGQlN5eEpRVUZKTEVsQlFVa3NRMEZCU2l4RlFVRlBMRWxCUVVrc1NVRkJTU3hOUVVGS0xFVkJRVmtzUjBGQmFFTXNSVUZCY1VNN1FVRkRia01zVlVGQlNTeFhRVUZYTEVsQlFVa3NWVUZCU2l4RFFVRmxMRU5CUVdZc1EwRkJXQ3hEUVVRclFqdEJRVVZ1UXl4VlFVRkpMRmRCUVZjc1NVRkJXQ3hGUVVGblFqdEJRVU5zUWl4aFFVRkxMRWxCUVV3c1EwRkJWU3hSUVVGV0xFVkJSR3RDTzA5QlFYQkNMRTFCUjBzc1NVRkJTU3hYUVVGWExFdEJRVmdzUlVGQmEwSTdRVUZEZWtJc1lVRkJTeXhKUVVGTUxFTkJRVlVzVDBGQlVTeFpRVUZaTEVOQlFWb3NSVUZEVWl4UFFVRlJMRmRCUVZjc1NVRkJXQ3hEUVVSc1FpeERRVVI1UWp0UFFVRjBRaXhOUVVsQkxFbEJRVWtzVjBGQlZ5eE5RVUZZTEVsQlFYRkNMRmxCUVZrc1RVRkJXaXhGUVVGdlFqdEJRVU5vUkN4aFFVRkxMRWxCUVV3c1EwRkJWU3hQUVVGUkxGbEJRVmtzUlVGQldpeEZRVU5TTEU5QlFWRXNVVUZCUXl4SlFVRlpMRU5CUVZvc1IwRkJhVUlzU1VGQmJFSXNSVUZEVWl4UFFVRlJMRmRCUVZjc1NVRkJXQ3hEUVVac1FpeERRVVJuUkRzN08wRkJRVGRETEZkQlRVRTdRVUZEU0RzN096dEJRVVJITEd0Q1FVdElMRWRCUVZjc1YwRkJWeXhEUVVGRkxGZEJRVmNzUzBGQldDeERRVUZFTEVsQlFYTkNMRVZCUVhSQ0xFZEJRMVlzU1VGQlNTeFZRVUZLTEVOQlFXVXNRMEZCWml4SlFVRnZRaXhMUVVGd1FpeERRVVJHTEVOQlRGSTdRVUZQU0N4bFFVRkxMRWxCUVV3c1EwRkJWU3hQUVVGUkxGbEJRVmtzUlVGQldpeEZRVU5TTEU5QlFWRXNVVUZCUXl4SlFVRlpMRVZCUVZvc1IwRkJhMElzU1VGQmJrSXNSVUZEVWl4UFFVRlJMRkZCUVVNc1NVRkJXU3hEUVVGYUxFZEJRV2xDTEVsQlFXeENMRVZCUTFJc1QwRkJVU3hYUVVGWExFbEJRVmdzUTBGSWJFSXNRMEZRUnp0VFFVNUJPMHRCVkZBN1FVRTBRa0VzVjBGQlR5eEpRVUZRTEVOQk9VSnpRanRIUVVGNFFqczdRVUZwUTBFc1UwRkJUeXhaUVVGUUxFTkJRVzlDTEVkQlFYQkNMRVZCUVhsQ08wRkJRM1pDTEZGQlFVa3NVVUZCVVN4RlFVRlNMRU5CUkcxQ08wRkJSWFpDTEZOQlFVc3NTVUZCU1N4SlFVRkpMRU5CUVVvc1JVRkJUeXhKUVVGSkxFbEJRVWtzVFVGQlNpeEZRVUZaTEVkQlFXaERMRVZCUVhGRE8wRkJRMjVETEZWQlFVa3NXVUZCV1N4SlFVRkpMRmRCUVVvc1EwRkJaMElzUTBGQmFFSXNRMEZCV2l4RFFVUXJRanM3UVVGSGJrTXNWVUZCUnl4aFFVRmhMRWRCUVdJc1JVRkJhVUk3UVVGRGJFSXNZMEZCVFN4SlFVRk9MRU5CUVZjc1EwRkJXQ3hGUVVSclFqdEJRVVZzUWl4alFVRk5MRWxCUVU0c1EwRkJWeXhUUVVGWUxFVkJSbXRDTzA5QlFYQkNMRTFCUjBzN1FVRkRTQ3hqUVVGTkxFbEJRVTRzUTBGQldTeFRRVUZETEVsQlFXRXNRMEZCWWl4SFFVRnJRaXhKUVVGdVFpeERRVUZhTEVOQlJFYzdRVUZGU0N4alFVRk5MRWxCUVU0c1EwRkJXU3haUVVGWkxFbEJRVm9zUTBGQldpeERRVVpITzA5QlNFdzdTMEZJUmp0QlFWZEJMRmRCUVU4c1MwRkJVQ3hEUVdKMVFqdEhRVUY2UWpzN1FVRnBRa0VzVTBGQlR5eFpRVUZRTEVOQlFXOUNMRWRCUVhCQ0xFVkJRWGxDTzBGQlEzWkNMRkZCUVVrc1VVRkJVU3hGUVVGU0xFTkJSRzFDTzBGQlJYWkNMRk5CUVVzc1NVRkJTU3hKUVVGSkxFTkJRVW9zUlVGQlR5eEpRVUZKTEVsQlFVa3NUVUZCU2l4RlFVRlpMRWRCUVdoRExFVkJRWEZETzBGQlEyNURMRlZCUVVrc1dVRkJXU3hKUVVGSkxGZEJRVW9zUTBGQlowSXNRMEZCYUVJc1EwRkJXaXhEUVVRclFqczdRVUZIYmtNc1ZVRkJSeXhoUVVGaExFZEJRV0lzUlVGQmFVSTdRVUZEYkVJc1kwRkJUU3hKUVVGT0xFTkJRVmNzUTBGQldDeEZRVVJyUWp0QlFVVnNRaXhqUVVGTkxFbEJRVTRzUTBGQlZ5eERRVUZZTEVWQlJtdENPMEZCUjJ4Q0xHTkJRVTBzU1VGQlRpeERRVUZYTEVOQlFWZ3NSVUZJYTBJN1FVRkpiRUlzWTBGQlRTeEpRVUZPTEVOQlFWY3NVMEZCV0N4RlFVcHJRanRQUVVGd1FpeE5RVXRMTzBGQlEwZ3NZMEZCVFN4SlFVRk9MRU5CUVZjc1EwRkJXQ3hGUVVSSE8wRkJSVWdzWTBGQlRTeEpRVUZPTEVOQlFWY3NRMEZCV0N4RlFVWkhPMEZCUjBnc1kwRkJUU3hKUVVGT0xFTkJRVmtzVTBGQlF5eEpRVUZoTEVOQlFXSXNSMEZCYTBJc1NVRkJia0lzUTBGQldpeERRVWhITzBGQlNVZ3NZMEZCVFN4SlFVRk9MRU5CUVZrc1dVRkJXU3hKUVVGYUxFTkJRVm9zUTBGS1J6dFBRVXhNTzB0QlNFWTdRVUZsUVN4WFFVRlBMRXRCUVZBc1EwRnFRblZDTzBkQlFYcENPenM3UVVGNFVHTXNVMEUyVVZBc1kwRkJVQ3hEUVVGelFpeERRVUYwUWl4RlFVRjVRanRCUVVOMlFpeFJRVUZKTEZGQlFWRXNSVUZCVWl4RFFVUnRRanM3UVVGSGRrSXNVVUZCU1N4TlFVRk5MRWxCUVVrc1YwRkJTaXhEUVVGblFpeERRVUZvUWl4RFFVRk9MRU5CU0cxQ08wRkJTWFpDTEZGQlFVc3NXVUZCU2l4RFFVRnBRaXhIUVVGcVFpeERRVUZFTEVOQlFYZENMRU5CUVhoQ0xFbEJRVFpDTEVOQlFUZENMRU5CU25WQ096dEJRVTEyUWl4UlFVRkpMR0ZCUVdFc1NVRkJTeXhYUVVGS0xFTkJRV2RDTEVkQlFXaENMRU5CUVVRc1EwRkJkVUlzUTBGQmRrSXNRMEZCWWl4RFFVNXRRanM3UVVGUmRrSXNWVUZCVFN4SlFVRk9MRU5CUVZrc1ZVRkJReXhKUVVGakxFVkJRV1FzUjBGQmIwSXNTVUZCY2tJc1EwRkJXaXhEUVZKMVFqdEJRVk4yUWl4VlFVRk5MRWxCUVU0c1EwRkJXU3hWUVVGRExFbEJRV01zUlVGQlpDeEhRVUZ2UWl4SlFVRnlRaXhEUVVGYUxFTkJWSFZDTzBGQlZYWkNMRlZCUVUwc1NVRkJUaXhEUVVGWkxGVkJRVU1zU1VGQll5eERRVUZrTEVkQlFXMUNMRWxCUVhCQ0xFTkJRVm9zUTBGV2RVSTdRVUZYZGtJc1ZVRkJUU3hKUVVGT0xFTkJRVmtzWVVGQllTeEpRVUZpTEVOQlFWb3NRMEZZZFVJN08wRkJZWFpDTEZkQlFVOHNTMEZCVUN4RFFXSjFRanRIUVVGNlFqczdRVUZuUWtFc1UwRkJUeXhqUVVGUUxFTkJRWE5DTEVOQlFYUkNMRVZCUVhsQ08wRkJRM1pDTEZGQlFVa3NVVUZCVVN4RlFVRlNMRU5CUkcxQ096dEJRVWQyUWl4UlFVRkpMRTFCUVUwc1NVRkJTU3hYUVVGS0xFTkJRV2RDTEVOQlFXaENMRU5CUVU0c1EwRkliVUk3UVVGSmRrSXNVVUZCU3l4WlFVRktMRU5CUVdsQ0xFZEJRV3BDTEVOQlFVUXNRMEZCZDBJc1EwRkJlRUlzU1VGQk5rSXNRMEZCTjBJc1EwRktkVUk3TzBGQlRYWkNMRkZCUVVrc1kwRkJZeXhKUVVGTExGZEJRVW9zUTBGQlowSXNSMEZCYUVJc1EwRkJSQ3hEUVVGMVFpeERRVUYyUWl4RFFVRmtMRU5CVG0xQ08wRkJUM1pDTEZGQlFVa3NZMEZCWXl4SlFVRkxMRmRCUVVvc1EwRkJaMElzUjBGQmFFSXNRMEZCUkN4RFFVRjFRaXhEUVVGMlFpeERRVUZrTEVOQlVHMUNPenRCUVZOMlFpeFZRVUZOTEVsQlFVNHNRMEZCV1N4WFFVRkRMRWxCUVdVc1JVRkJaaXhIUVVGeFFpeEpRVUYwUWl4RFFVRmFMRU5CVkhWQ08wRkJWWFpDTEZWQlFVMHNTVUZCVGl4RFFVRlpMRmRCUVVNc1NVRkJaU3hGUVVGbUxFZEJRWEZDTEVsQlFYUkNMRU5CUVZvc1EwRldkVUk3UVVGWGRrSXNWVUZCVFN4SlFVRk9MRU5CUVZrc1YwRkJReXhKUVVGbExFTkJRV1lzUjBGQmIwSXNTVUZCY2tJc1EwRkJXaXhEUVZoMVFqdEJRVmwyUWl4VlFVRk5MRWxCUVU0c1EwRkJXU3hqUVVGakxFbEJRV1FzUTBGQldpeERRVnAxUWpzN1FVRmpka0lzVlVGQlRTeEpRVUZPTEVOQlFWa3NWMEZCUXl4SlFVRmxMRVZCUVdZc1IwRkJjVUlzU1VGQmRFSXNRMEZCV2l4RFFXUjFRanRCUVdWMlFpeFZRVUZOTEVsQlFVNHNRMEZCV1N4WFFVRkRMRWxCUVdVc1JVRkJaaXhIUVVGeFFpeEpRVUYwUWl4RFFVRmFMRU5CWm5WQ08wRkJaMEoyUWl4VlFVRk5MRWxCUVU0c1EwRkJXU3hYUVVGRExFbEJRV1VzUTBGQlppeEhRVUZ2UWl4SlFVRnlRaXhEUVVGYUxFTkJhRUoxUWp0QlFXbENka0lzVlVGQlRTeEpRVUZPTEVOQlFWa3NZMEZCWXl4SlFVRmtMRU5CUVZvc1EwRnFRblZDT3p0QlFXMUNka0lzVjBGQlR5eExRVUZRTEVOQmJrSjFRanRIUVVGNlFqdERRVGRTUmpzN1FVRnZWRUVzWlVGQlpTeFRRVUZtSWl3aVptbHNaU0k2SW14cFlpOWpiM0psTDJKcGRGOXpkSEpwYm1jdWFuTWlMQ0p6YjNWeVkyVnpRMjl1ZEdWdWRDSTZXeUpqYkdGemN5QkNhWFJUZEhKcGJtY2dlMXh1SUNCamIyNXpkSEoxWTNSdmNpZ3VMaTVoY21kektYdGNiaUFnSUNCMGFHbHpMblpoYkhWbElEMGdUMkpxWldOMExtWnlaV1Y2WlNoMGFHbHpMbkJ5YjJObGMzTW9ZWEpuY3lrcE8xeHVJQ0FnSUhSb2FYTXViR1Z1WjNSb0lEMGdkR2hwY3k1MllXeDFaUzVzWlc1bmRHZzdYRzRnSUNBZ2RHaHBjeTVpYVhSZmMybDZaU0E5SUhSb2FYTXViR1Z1WjNSb0lDb2dPRHRjYmlBZ0lDQjBhR2x6TG1KNWRHVmZjMmw2WlNBOUlIUm9hWE11YkdWdVozUm9PMXh1SUNCOVhHNWNiaUFnWjJWMEtHbHVaR1Y0S1h0Y2JpQWdJQ0J5WlhSMWNtNGdkR2hwY3k1MllXeDFaVnRwYm1SbGVGMDdYRzRnSUgxY2JseHVJQ0JqYjNWdWRDZ3BlMXh1SUNBZ0lISmxkSFZ5YmlCMGFHbHpMblpoYkhWbExteGxibWQwYUR0Y2JpQWdmVnh1WEc0Z0lITnNhV05sS0hOMFlYSjBMQ0JsYm1RZ1BTQnVkV3hzS1h0Y2JpQWdJQ0JzWlhRZ2N5QTlJSFJvYVhNdWRtRnNkV1V1YzJ4cFkyVW9jM1JoY25Rc0lHVnVaQ2s3WEc0Z0lDQWdiR1YwSUcxeklEMGdjeTV0WVhBb0tHVnNaVzBwSUQwK0lFSnBkRk4wY21sdVp5NXBiblJsWjJWeUtHVnNaVzBwS1R0Y2JpQWdJQ0J5WlhSMWNtNGdibVYzSUVKcGRGTjBjbWx1WnlndUxpNXRjeWs3WEc0Z0lIMWNibHh1SUNCYlUzbHRZbTlzTG1sMFpYSmhkRzl5WFNncElIdGNiaUFnSUNCeVpYUjFjbTRnZEdocGN5NTJZV3gxWlZ0VGVXMWliMnd1YVhSbGNtRjBiM0pkS0NrN1hHNGdJSDFjYmx4dUlDQjBiMU4wY21sdVp5Z3BlMXh1SUNBZ0lIWmhjaUJwTENCeklEMGdYQ0pjSWp0Y2JpQWdJQ0JtYjNJZ0tHa2dQU0F3T3lCcElEd2dkR2hwY3k1amIzVnVkQ2dwT3lCcEt5c3BJSHRjYmlBZ0lDQWdJR2xtSUNoeklDRTlQU0JjSWx3aUtTQjdYRzRnSUNBZ0lDQWdJSE1nS3owZ1hDSXNJRndpTzF4dUlDQWdJQ0FnZlZ4dUlDQWdJQ0FnY3lBclBTQjBhR2x6TG1kbGRDaHBLUzUwYjFOMGNtbHVaeWdwTzF4dUlDQWdJSDFjYmx4dUlDQWdJSEpsZEhWeWJpQmNJanc4WENJZ0t5QnpJQ3NnWENJK1Bsd2lPMXh1SUNCOVhHNWNiaUFnY0hKdlkyVnpjeWhpYVhSVGRISnBibWRRWVhKMGN5bDdYRzRnSUNBZ2JHVjBJSEJ5YjJObGMzTmxaRjkyWVd4MVpYTWdQU0JiWFR0Y2JseHVJQ0FnSUhaaGNpQnBPMXh1SUNBZ0lHWnZjaUFvYVNBOUlEQTdJR2tnUENCaWFYUlRkSEpwYm1kUVlYSjBjeTVzWlc1bmRHZzdJR2tyS3lrZ2UxeHVJQ0FnSUNBZ2JHVjBJSEJ5YjJObGMzTmxaRjkyWVd4MVpTQTlJSFJvYVhOYkozQnliMk5sYzNOZkp5QXJJR0pwZEZOMGNtbHVaMUJoY25SelcybGRMblI1Y0dWZEtHSnBkRk4wY21sdVoxQmhjblJ6VzJsZEtUdGNibHh1SUNBZ0lDQWdabTl5S0d4bGRDQmhkSFJ5SUc5bUlHSnBkRk4wY21sdVoxQmhjblJ6VzJsZExtRjBkSEpwWW5WMFpYTXBlMXh1SUNBZ0lDQWdJQ0J3Y205alpYTnpaV1JmZG1Gc2RXVWdQU0IwYUdseld5ZHdjbTlqWlhOelh5Y2dLeUJoZEhSeVhTaHdjbTlqWlhOelpXUmZkbUZzZFdVcE8xeHVJQ0FnSUNBZ2ZWeHVYRzRnSUNBZ0lDQndjbTlqWlhOelpXUmZkbUZzZFdWeklEMGdjSEp2WTJWemMyVmtYM1poYkhWbGN5NWpiMjVqWVhRb2NISnZZMlZ6YzJWa1gzWmhiSFZsS1R0Y2JpQWdJQ0I5WEc1Y2JpQWdJQ0J5WlhSMWNtNGdjSEp2WTJWemMyVmtYM1poYkhWbGN6dGNiaUFnZlZ4dVhHNGdJSEJ5YjJObGMzTmZhVzUwWldkbGNpaDJZV3gxWlNsN1hHNGdJQ0FnY21WMGRYSnVJSFpoYkhWbExuWmhiSFZsTzF4dUlDQjlYRzVjYmlBZ2NISnZZMlZ6YzE5bWJHOWhkQ2gyWVd4MVpTbDdYRzRnSUNBZ2FXWW9kbUZzZFdVdWMybDZaU0E5UFQwZ05qUXBlMXh1SUNBZ0lDQWdjbVYwZFhKdUlFSnBkRk4wY21sdVp5NW1iRzloZERZMFZHOUNlWFJsY3loMllXeDFaUzUyWVd4MVpTazdYRzRnSUNBZ2ZXVnNjMlVnYVdZb2RtRnNkV1V1YzJsNlpTQTlQVDBnTXpJcGUxeHVJQ0FnSUNBZ2NtVjBkWEp1SUVKcGRGTjBjbWx1Wnk1bWJHOWhkRE15Vkc5Q2VYUmxjeWgyWVd4MVpTNTJZV3gxWlNrN1hHNGdJQ0FnZlZ4dVhHNGdJQ0FnZEdoeWIzY2dibVYzSUVWeWNtOXlLQ2RKYm5aaGJHbGtJSE5wZW1VZ1ptOXlJR1pzYjJGMEp5azdYRzRnSUgxY2JseHVJQ0J3Y205alpYTnpYMkpwZEhOMGNtbHVaeWgyWVd4MVpTbDdYRzRnSUNBZ2NtVjBkWEp1SUhaaGJIVmxMblpoYkhWbExuWmhiSFZsTzF4dUlDQjlYRzVjYmlBZ2NISnZZMlZ6YzE5aWFXNWhjbmtvZG1Gc2RXVXBlMXh1SUNBZ0lISmxkSFZ5YmlCQ2FYUlRkSEpwYm1jdWRHOVZWRVk0UVhKeVlYa29kbUZzZFdVdWRtRnNkV1VwTzF4dUlDQjlYRzVjYmlBZ2NISnZZMlZ6YzE5MWRHWTRLSFpoYkhWbEtYdGNiaUFnSUNCeVpYUjFjbTRnUW1sMFUzUnlhVzVuTG5SdlZWUkdPRUZ5Y21GNUtIWmhiSFZsTG5aaGJIVmxLVHRjYmlBZ2ZWeHVYRzRnSUhCeWIyTmxjM05mZFhSbU1UWW9kbUZzZFdVcGUxeHVJQ0FnSUhKbGRIVnliaUJDYVhSVGRISnBibWN1ZEc5VlZFWXhOa0Z5Y21GNUtIWmhiSFZsTG5aaGJIVmxLVHRjYmlBZ2ZWeHVYRzRnSUhCeWIyTmxjM05mZFhSbU16SW9kbUZzZFdVcGUxeHVJQ0FnSUhKbGRIVnliaUJDYVhSVGRISnBibWN1ZEc5VlZFWXpNa0Z5Y21GNUtIWmhiSFZsTG5aaGJIVmxLVHRjYmlBZ2ZWeHVYRzRnSUhCeWIyTmxjM05mYzJsbmJtVmtLSFpoYkhWbEtYdGNiaUFnSUNCeVpYUjFjbTRnS0c1bGR5QlZhVzUwT0VGeWNtRjVLRnQyWVd4MVpWMHBLVnN3WFR0Y2JpQWdmVnh1WEc0Z0lIQnliMk5sYzNOZmRXNXphV2R1WldRb2RtRnNkV1VwZTF4dUlDQWdJSEpsZEhWeWJpQjJZV3gxWlR0Y2JpQWdmVnh1WEc0Z0lIQnliMk5sYzNOZmJtRjBhWFpsS0haaGJIVmxLWHRjYmlBZ0lDQnlaWFIxY200Z2RtRnNkV1U3WEc0Z0lIMWNibHh1SUNCd2NtOWpaWE56WDJKcFp5aDJZV3gxWlNsN1hHNGdJQ0FnY21WMGRYSnVJSFpoYkhWbE8xeHVJQ0I5WEc1Y2JpQWdjSEp2WTJWemMxOXNhWFIwYkdVb2RtRnNkV1VwZTF4dUlDQWdJSEpsZEhWeWJpQjJZV3gxWlM1eVpYWmxjbk5sS0NrN1hHNGdJSDFjYmx4dUlDQndjbTlqWlhOelgzTnBlbVVvZG1Gc2RXVXBlMXh1SUNBZ0lISmxkSFZ5YmlCMllXeDFaVHRjYmlBZ2ZWeHVYRzRnSUhCeWIyTmxjM05mZFc1cGRDaDJZV3gxWlNsN1hHNGdJQ0FnY21WMGRYSnVJSFpoYkhWbE8xeHVJQ0I5WEc1Y2JpQWdjM1JoZEdsaklHbHVkR1ZuWlhJb2RtRnNkV1VwZTF4dUlDQWdJSEpsZEhWeWJpQkNhWFJUZEhKcGJtY3VkM0poY0NoMllXeDFaU3dnZXlBbmRIbHdaU2M2SUNkcGJuUmxaMlZ5Snl3Z0ozVnVhWFFuT2lBeExDQW5jMmw2WlNjNklEZ2dmU2s3WEc0Z0lIMWNibHh1SUNCemRHRjBhV01nWm14dllYUW9kbUZzZFdVcGUxeHVJQ0FnSUhKbGRIVnliaUJDYVhSVGRISnBibWN1ZDNKaGNDaDJZV3gxWlN3Z2V5QW5kSGx3WlNjNklDZG1iRzloZENjc0lDZDFibWwwSnpvZ01Td2dKM05wZW1Vbk9pQTJOQ0I5S1R0Y2JpQWdmVnh1WEc0Z0lITjBZWFJwWXlCaWFYUnpkSEpwYm1jb2RtRnNkV1VwZTF4dUlDQWdJSEpsZEhWeWJpQkNhWFJUZEhKcGJtY3VkM0poY0NoMllXeDFaU3dnZXlBbmRIbHdaU2M2SUNkaWFYUnpkSEpwYm1jbkxDQW5kVzVwZENjNklERXNJQ2R6YVhwbEp6b2dkbUZzZFdVdVltbDBYM05wZW1VZ2ZTazdYRzRnSUgxY2JseHVJQ0J6ZEdGMGFXTWdZbWwwY3loMllXeDFaU2w3WEc0Z0lDQWdjbVYwZFhKdUlFSnBkRk4wY21sdVp5NWlhWFJ6ZEhKcGJtY29kbUZzZFdVcE8xeHVJQ0I5WEc1Y2JpQWdjM1JoZEdsaklHSnBibUZ5ZVNoMllXeDFaU2w3WEc0Z0lDQWdjbVYwZFhKdUlFSnBkRk4wY21sdVp5NTNjbUZ3S0haaGJIVmxMQ0I3SUNkMGVYQmxKem9nSjJKcGJtRnllU2NzSUNkMWJtbDBKem9nT0N3Z0ozTnBlbVVuT2lCMllXeDFaUzVzWlc1bmRHZ2dmU2s3WEc0Z0lIMWNibHh1SUNCemRHRjBhV01nWW5sMFpYTW9kbUZzZFdVcGUxeHVJQ0FnSUhKbGRIVnliaUJDYVhSVGRISnBibWN1WW1sdVlYSjVLSFpoYkhWbEtUdGNiaUFnZlZ4dVhHNGdJSE4wWVhScFl5QjFkR1k0S0haaGJIVmxLWHRjYmlBZ0lDQnlaWFIxY200Z1FtbDBVM1J5YVc1bkxuZHlZWEFvZG1Gc2RXVXNJSHNnSjNSNWNHVW5PaUFuZFhSbU9DY3NJQ2QxYm1sMEp6b2dNU3dnSjNOcGVtVW5PaUIyWVd4MVpTNXNaVzVuZEdnZ0lIMHBPMXh1SUNCOVhHNWNiaUFnYzNSaGRHbGpJSFYwWmpFMktIWmhiSFZsS1h0Y2JpQWdJQ0J5WlhSMWNtNGdRbWwwVTNSeWFXNW5MbmR5WVhBb2RtRnNkV1VzSUhzZ0ozUjVjR1VuT2lBbmRYUm1NVFluTENBbmRXNXBkQ2M2SURFc0lDZHphWHBsSnpvZ2RtRnNkV1V1YkdWdVozUm9JQ29nTWlCOUtUdGNiaUFnZlZ4dVhHNGdJSE4wWVhScFl5QjFkR1l6TWloMllXeDFaU2w3WEc0Z0lDQWdjbVYwZFhKdUlFSnBkRk4wY21sdVp5NTNjbUZ3S0haaGJIVmxMQ0I3SUNkMGVYQmxKem9nSjNWMFpqTXlKeXdnSjNWdWFYUW5PaUF4TENBbmMybDZaU2M2SUhaaGJIVmxMbXhsYm1kMGFDQXFJRFFnZlNrN1hHNGdJSDFjYmx4dUlDQnpkR0YwYVdNZ2MybG5ibVZrS0haaGJIVmxLWHRjYmlBZ0lDQnlaWFIxY200Z1FtbDBVM1J5YVc1bkxuZHlZWEFvZG1Gc2RXVXNJSHQ5TENBbmMybG5ibVZrSnlrN1hHNGdJSDFjYmx4dUlDQnpkR0YwYVdNZ2RXNXphV2R1WldRb2RtRnNkV1VwZTF4dUlDQWdJSEpsZEhWeWJpQkNhWFJUZEhKcGJtY3VkM0poY0NoMllXeDFaU3dnZTMwc0lDZDFibk5wWjI1bFpDY3BPMXh1SUNCOVhHNWNiaUFnYzNSaGRHbGpJRzVoZEdsMlpTaDJZV3gxWlNsN1hHNGdJQ0FnY21WMGRYSnVJRUpwZEZOMGNtbHVaeTUzY21Gd0tIWmhiSFZsTENCN2ZTd2dKMjVoZEdsMlpTY3BPMXh1SUNCOVhHNWNiaUFnYzNSaGRHbGpJR0pwWnloMllXeDFaU2w3WEc0Z0lDQWdjbVYwZFhKdUlFSnBkRk4wY21sdVp5NTNjbUZ3S0haaGJIVmxMQ0I3ZlN3Z0oySnBaeWNwTzF4dUlDQjlYRzVjYmlBZ2MzUmhkR2xqSUd4cGRIUnNaU2gyWVd4MVpTbDdYRzRnSUNBZ2NtVjBkWEp1SUVKcGRGTjBjbWx1Wnk1M2NtRndLSFpoYkhWbExDQjdmU3dnSjJ4cGRIUnNaU2NwTzF4dUlDQjlYRzVjYmlBZ2MzUmhkR2xqSUhOcGVtVW9kbUZzZFdVc0lHTnZkVzUwS1h0Y2JpQWdJQ0J5WlhSMWNtNGdRbWwwVTNSeWFXNW5MbmR5WVhBb2RtRnNkV1VzSUhzbmMybDZaU2M2SUdOdmRXNTBmU2s3WEc0Z0lIMWNibHh1SUNCemRHRjBhV01nZFc1cGRDaDJZV3gxWlN3Z1kyOTFiblFwZTF4dUlDQWdJSEpsZEhWeWJpQkNhWFJUZEhKcGJtY3VkM0poY0NoMllXeDFaU3dnZXlkMWJtbDBKem9nWTI5MWJuUjlLVHRjYmlBZ2ZWeHVYRzRnSUhOMFlYUnBZeUIzY21Gd0tIWmhiSFZsTENCdmNIUXNJRzVsZDE5aGRIUnlhV0oxZEdVZ1BTQnVkV3hzS1h0Y2JpQWdJQ0JzWlhRZ2RHaGxYM1poYkhWbElEMGdkbUZzZFdVN1hHNWNiaUFnSUNCcFppZ2hLSFpoYkhWbElHbHVjM1JoYm1ObGIyWWdUMkpxWldOMEtTbDdYRzRnSUNBZ0lDQjBhR1ZmZG1Gc2RXVWdQU0I3SjNaaGJIVmxKem9nZG1Gc2RXVXNJQ2RoZEhSeWFXSjFkR1Z6SnpvZ1cxMTlPMXh1SUNBZ0lIMWNibHh1SUNBZ0lIUm9aVjkyWVd4MVpTQTlJRTlpYW1WamRDNWhjM05wWjI0b2RHaGxYM1poYkhWbExDQnZjSFFwTzF4dVhHNGdJQ0FnYVdZb2JtVjNYMkYwZEhKcFluVjBaU2w3WEc0Z0lDQWdJQ0IwYUdWZmRtRnNkV1V1WVhSMGNtbGlkWFJsY3k1d2RYTm9LRzVsZDE5aGRIUnlhV0oxZEdVcE8xeHVJQ0FnSUgxY2JseHVYRzRnSUNBZ2NtVjBkWEp1SUhSb1pWOTJZV3gxWlR0Y2JpQWdmVnh1WEc0Z0lITjBZWFJwWXlCMGIxVlVSamhCY25KaGVTaHpkSElwSUh0Y2JpQWdJQ0IyWVhJZ2RYUm1PQ0E5SUZ0ZE8xeHVJQ0FnSUdadmNpQW9kbUZ5SUdrZ1BTQXdPeUJwSUR3Z2MzUnlMbXhsYm1kMGFEc2dhU3NyS1NCN1hHNGdJQ0FnSUNCMllYSWdZMmhoY21OdlpHVWdQU0J6ZEhJdVkyaGhja052WkdWQmRDaHBLVHRjYmlBZ0lDQWdJR2xtSUNoamFHRnlZMjlrWlNBOElEQjRPREFwZTF4dUlDQWdJQ0FnSUNCMWRHWTRMbkIxYzJnb1kyaGhjbU52WkdVcE8xeHVJQ0FnSUNBZ2ZWeHVJQ0FnSUNBZ1pXeHpaU0JwWmlBb1kyaGhjbU52WkdVZ1BDQXdlRGd3TUNrZ2UxeHVJQ0FnSUNBZ0lDQjFkR1k0TG5CMWMyZ29NSGhqTUNCOElDaGphR0Z5WTI5a1pTQStQaUEyS1N4Y2JpQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lEQjRPREFnZkNBb1kyaGhjbU52WkdVZ0ppQXdlRE5tS1NrN1hHNGdJQ0FnSUNCOVhHNGdJQ0FnSUNCbGJITmxJR2xtSUNoamFHRnlZMjlrWlNBOElEQjRaRGd3TUNCOGZDQmphR0Z5WTI5a1pTQStQU0F3ZUdVd01EQXBJSHRjYmlBZ0lDQWdJQ0FnZFhSbU9DNXdkWE5vS0RCNFpUQWdmQ0FvWTJoaGNtTnZaR1VnUGo0Z01USXBMRnh1SUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnTUhnNE1DQjhJQ2dvWTJoaGNtTnZaR1VnUGo0Z05pa2dKaUF3ZURObUtTeGNiaUFnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJREI0T0RBZ2ZDQW9ZMmhoY21OdlpHVWdKaUF3ZURObUtTazdYRzRnSUNBZ0lDQjlYRzRnSUNBZ0lDQXZMeUJ6ZFhKeWIyZGhkR1VnY0dGcGNseHVJQ0FnSUNBZ1pXeHpaU0I3WEc0Z0lDQWdJQ0FnSUdrckt6dGNiaUFnSUNBZ0lDQWdMeThnVlZSR0xURTJJR1Z1WTI5a1pYTWdNSGd4TURBd01DMHdlREV3UmtaR1JpQmllVnh1SUNBZ0lDQWdJQ0F2THlCemRXSjBjbUZqZEdsdVp5QXdlREV3TURBd0lHRnVaQ0J6Y0d4cGRIUnBibWNnZEdobFhHNGdJQ0FnSUNBZ0lDOHZJREl3SUdKcGRITWdiMllnTUhnd0xUQjRSa1pHUmtZZ2FXNTBieUIwZDI4Z2FHRnNkbVZ6WEc0Z0lDQWdJQ0FnSUdOb1lYSmpiMlJsSUQwZ01IZ3hNREF3TUNBcklDZ29LR05vWVhKamIyUmxJQ1lnTUhnelptWXBJRHc4SURFd0tWeHVJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdmQ0FvYzNSeUxtTm9ZWEpEYjJSbFFYUW9hU2tnSmlBd2VETm1aaWtwTzF4dUlDQWdJQ0FnSUNCMWRHWTRMbkIxYzJnb01IaG1NQ0I4SUNoamFHRnlZMjlrWlNBK1BpQXhPQ2tzWEc0Z0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBd2VEZ3dJSHdnS0NoamFHRnlZMjlrWlNBK1BpQXhNaWtnSmlBd2VETm1LU3hjYmlBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSURCNE9EQWdmQ0FvS0dOb1lYSmpiMlJsSUQ0K0lEWXBJQ1lnTUhnelppa3NYRzRnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0F3ZURnd0lId2dLR05vWVhKamIyUmxJQ1lnTUhnelppa3BPMXh1SUNBZ0lDQWdmVnh1SUNBZ0lIMWNiaUFnSUNCeVpYUjFjbTRnZFhSbU9EdGNiaUFnZlZ4dVhHNGdJSE4wWVhScFl5QjBiMVZVUmpFMlFYSnlZWGtvYzNSeUtTQjdYRzRnSUNBZ2RtRnlJSFYwWmpFMklEMGdXMTA3WEc0Z0lDQWdabTl5SUNoMllYSWdhU0E5SURBN0lHa2dQQ0J6ZEhJdWJHVnVaM1JvT3lCcEt5c3BJSHRjYmlBZ0lDQWdJSFpoY2lCamIyUmxVRzlwYm5RZ1BTQnpkSEl1WTI5a1pWQnZhVzUwUVhRb2FTazdYRzVjYmlBZ0lDQWdJR2xtS0dOdlpHVlFiMmx1ZENBOFBTQXlOVFVwZTF4dUlDQWdJQ0FnSUNCMWRHWXhOaTV3ZFhOb0tEQXBPMXh1SUNBZ0lDQWdJQ0IxZEdZeE5pNXdkWE5vS0dOdlpHVlFiMmx1ZENrN1hHNGdJQ0FnSUNCOVpXeHpaWHRjYmlBZ0lDQWdJQ0FnZFhSbU1UWXVjSFZ6YUNnb0tHTnZaR1ZRYjJsdWRDQStQaUE0S1NBbUlEQjRSa1lwS1R0Y2JpQWdJQ0FnSUNBZ2RYUm1NVFl1Y0hWemFDZ29ZMjlrWlZCdmFXNTBJQ1lnTUhoR1Jpa3BPMXh1SUNBZ0lDQWdmVnh1SUNBZ0lIMWNiaUFnSUNCeVpYUjFjbTRnZFhSbU1UWTdYRzRnSUgxY2JseHVYRzRnSUhOMFlYUnBZeUIwYjFWVVJqTXlRWEp5WVhrb2MzUnlLU0I3WEc0Z0lDQWdkbUZ5SUhWMFpqTXlJRDBnVzEwN1hHNGdJQ0FnWm05eUlDaDJZWElnYVNBOUlEQTdJR2tnUENCemRISXViR1Z1WjNSb095QnBLeXNwSUh0Y2JpQWdJQ0FnSUhaaGNpQmpiMlJsVUc5cGJuUWdQU0J6ZEhJdVkyOWtaVkJ2YVc1MFFYUW9hU2s3WEc1Y2JpQWdJQ0FnSUdsbUtHTnZaR1ZRYjJsdWRDQThQU0F5TlRVcGUxeHVJQ0FnSUNBZ0lDQjFkR1l6TWk1d2RYTm9LREFwTzF4dUlDQWdJQ0FnSUNCMWRHWXpNaTV3ZFhOb0tEQXBPMXh1SUNBZ0lDQWdJQ0IxZEdZek1pNXdkWE5vS0RBcE8xeHVJQ0FnSUNBZ0lDQjFkR1l6TWk1d2RYTm9LR052WkdWUWIybHVkQ2s3WEc0Z0lDQWdJQ0I5Wld4elpYdGNiaUFnSUNBZ0lDQWdkWFJtTXpJdWNIVnphQ2d3S1R0Y2JpQWdJQ0FnSUNBZ2RYUm1Nekl1Y0hWemFDZ3dLVHRjYmlBZ0lDQWdJQ0FnZFhSbU16SXVjSFZ6YUNnb0tHTnZaR1ZRYjJsdWRDQStQaUE0S1NBbUlEQjRSa1lwS1R0Y2JpQWdJQ0FnSUNBZ2RYUm1Nekl1Y0hWemFDZ29ZMjlrWlZCdmFXNTBJQ1lnTUhoR1Jpa3BPMXh1SUNBZ0lDQWdmVnh1SUNBZ0lIMWNiaUFnSUNCeVpYUjFjbTRnZFhSbU16STdYRzRnSUgxY2JseHVJQ0F2TDJoMGRIQTZMeTl6ZEdGamEyOTJaWEptYkc5M0xtTnZiUzl4ZFdWemRHbHZibk12TWpBd016UTVNeTlxWVhaaGMyTnlhWEIwTFdac2IyRjBMV1p5YjIwdGRHOHRZbWwwYzF4dUlDQnpkR0YwYVdNZ1pteHZZWFF6TWxSdlFubDBaWE1vWmlrZ2UxeHVJQ0FnSUhaaGNpQmllWFJsY3lBOUlGdGRPMXh1WEc0Z0lDQWdkbUZ5SUdKMVppQTlJRzVsZHlCQmNuSmhlVUoxWm1abGNpZzBLVHRjYmlBZ0lDQW9ibVYzSUVac2IyRjBNekpCY25KaGVTaGlkV1lwS1Zzd1hTQTlJR1k3WEc1Y2JpQWdJQ0JzWlhRZ2FXNTBWbVZ5YzJsdmJpQTlJQ2h1WlhjZ1ZXbHVkRE15UVhKeVlYa29ZblZtS1NsYk1GMDdYRzVjYmlBZ0lDQmllWFJsY3k1d2RYTm9LQ2dvYVc1MFZtVnljMmx2YmlBK1BpQXlOQ2tnSmlBd2VFWkdLU2s3WEc0Z0lDQWdZbmwwWlhNdWNIVnphQ2dvS0dsdWRGWmxjbk5wYjI0Z1BqNGdNVFlwSUNZZ01IaEdSaWtwTzF4dUlDQWdJR0o1ZEdWekxuQjFjMmdvS0NocGJuUldaWEp6YVc5dUlENCtJRGdwSUNZZ01IaEdSaWtwTzF4dUlDQWdJR0o1ZEdWekxuQjFjMmdvS0dsdWRGWmxjbk5wYjI0Z0ppQXdlRVpHS1NrN1hHNWNiaUFnSUNCeVpYUjFjbTRnWW5sMFpYTTdYRzRnSUgxY2JseHVJQ0J6ZEdGMGFXTWdabXh2WVhRMk5GUnZRbmwwWlhNb1ppa2dlMXh1SUNBZ0lIWmhjaUJpZVhSbGN5QTlJRnRkTzF4dVhHNGdJQ0FnZG1GeUlHSjFaaUE5SUc1bGR5QkJjbkpoZVVKMVptWmxjaWc0S1R0Y2JpQWdJQ0FvYm1WM0lFWnNiMkYwTmpSQmNuSmhlU2hpZFdZcEtWc3dYU0E5SUdZN1hHNWNiaUFnSUNCMllYSWdhVzUwVm1WeWMybHZiakVnUFNBb2JtVjNJRlZwYm5Rek1rRnljbUY1S0dKMVppa3BXekJkTzF4dUlDQWdJSFpoY2lCcGJuUldaWEp6YVc5dU1pQTlJQ2h1WlhjZ1ZXbHVkRE15UVhKeVlYa29ZblZtS1NsYk1WMDdYRzVjYmlBZ0lDQmllWFJsY3k1d2RYTm9LQ2dvYVc1MFZtVnljMmx2YmpJZ1BqNGdNalFwSUNZZ01IaEdSaWtwTzF4dUlDQWdJR0o1ZEdWekxuQjFjMmdvS0NocGJuUldaWEp6YVc5dU1pQStQaUF4TmlrZ0ppQXdlRVpHS1NrN1hHNGdJQ0FnWW5sMFpYTXVjSFZ6YUNnb0tHbHVkRlpsY25OcGIyNHlJRDQrSURncElDWWdNSGhHUmlrcE8xeHVJQ0FnSUdKNWRHVnpMbkIxYzJnb0tHbHVkRlpsY25OcGIyNHlJQ1lnTUhoR1Jpa3BPMXh1WEc0Z0lDQWdZbmwwWlhNdWNIVnphQ2dvS0dsdWRGWmxjbk5wYjI0eElENCtJREkwS1NBbUlEQjRSa1lwS1R0Y2JpQWdJQ0JpZVhSbGN5NXdkWE5vS0Nnb2FXNTBWbVZ5YzJsdmJqRWdQajRnTVRZcElDWWdNSGhHUmlrcE8xeHVJQ0FnSUdKNWRHVnpMbkIxYzJnb0tDaHBiblJXWlhKemFXOXVNU0ErUGlBNEtTQW1JREI0UmtZcEtUdGNiaUFnSUNCaWVYUmxjeTV3ZFhOb0tDaHBiblJXWlhKemFXOXVNU0FtSURCNFJrWXBLVHRjYmx4dUlDQWdJSEpsZEhWeWJpQmllWFJsY3p0Y2JpQWdmVnh1ZlZ4dVhHNWxlSEJ2Y25RZ1pHVm1ZWFZzZENCQ2FYUlRkSEpwYm1jN1hHNGlYU3dpYzI5MWNtTmxVbTl2ZENJNklpOXpiM1Z5WTJVdkluMD1cbiIsIlxuZXhwb3J0IGNsYXNzIFZhcmlhYmxlIHtcblxuICBjb25zdHJ1Y3RvcihkZWZhdWx0X3ZhbHVlID0gU3ltYm9sLmZvcihcImVsaXhpcnNjcmlwdC5ub192YWx1ZVwiKSkge1xuICAgIHRoaXMuZGVmYXVsdF92YWx1ZSA9IGRlZmF1bHRfdmFsdWU7XG4gIH1cbn1cblxuZXhwb3J0IGNsYXNzIFdpbGRjYXJkIHtcbiAgY29uc3RydWN0b3IoKSB7fVxufVxuXG5leHBvcnQgY2xhc3MgU3RhcnRzV2l0aCB7XG5cbiAgY29uc3RydWN0b3IocHJlZml4KSB7XG4gICAgdGhpcy5wcmVmaXggPSBwcmVmaXg7XG4gIH1cbn1cblxuZXhwb3J0IGNsYXNzIENhcHR1cmUge1xuXG4gIGNvbnN0cnVjdG9yKHZhbHVlKSB7XG4gICAgdGhpcy52YWx1ZSA9IHZhbHVlO1xuICB9XG59XG5cbmV4cG9ydCBjbGFzcyBIZWFkVGFpbCB7XG5cbiAgY29uc3RydWN0b3IoaGVhZCA9IG51bGwsIHRhaWwgPSBudWxsKSB7XG4gICAgdGhpcy5oZWFkID0gaGVhZDtcbiAgICB0aGlzLnRhaWwgPSB0YWlsO1xuICB9XG59XG5cbmV4cG9ydCBjbGFzcyBUeXBlIHtcblxuICBjb25zdHJ1Y3Rvcih0eXBlLCBvYmpQYXR0ZXJuID0ge30pIHtcbiAgICB0aGlzLnR5cGUgPSB0eXBlO1xuICAgIHRoaXMub2JqUGF0dGVybiA9IG9ialBhdHRlcm47XG4gIH1cbn1cblxuZXhwb3J0IGNsYXNzIEJvdW5kIHtcblxuICBjb25zdHJ1Y3Rvcih2YWx1ZSkge1xuICAgIHRoaXMudmFsdWUgPSB2YWx1ZTtcbiAgfVxufVxuXG5leHBvcnQgY2xhc3MgQml0U3RyaW5nTWF0Y2gge1xuXG4gIGNvbnN0cnVjdG9yKC4uLnZhbHVlcykge1xuICAgIHRoaXMudmFsdWVzID0gdmFsdWVzO1xuICB9XG5cbiAgbGVuZ3RoKCkge1xuICAgIHJldHVybiB2YWx1ZXMubGVuZ3RoO1xuICB9XG5cbiAgYml0X3NpemUoKSB7XG4gICAgcmV0dXJuIHRoaXMuYnl0ZV9zaXplKCkgKiA4O1xuICB9XG5cbiAgYnl0ZV9zaXplKCkge1xuICAgIGxldCBzID0gMDtcblxuICAgIGZvciAobGV0IHZhbCBvZiB0aGlzLnZhbHVlcykge1xuICAgICAgcyA9IHMgKyB2YWwudW5pdCAqIHZhbC5zaXplIC8gODtcbiAgICB9XG5cbiAgICByZXR1cm4gcztcbiAgfVxuXG4gIGdldFZhbHVlKGluZGV4KSB7XG4gICAgcmV0dXJuIHRoaXMudmFsdWVzKGluZGV4KTtcbiAgfVxuXG4gIGdldFNpemVPZlZhbHVlKGluZGV4KSB7XG4gICAgbGV0IHZhbCA9IHRoaXMuZ2V0VmFsdWUoaW5kZXgpO1xuICAgIHJldHVybiB2YWwudW5pdCAqIHZhbC5zaXplO1xuICB9XG5cbiAgZ2V0VHlwZU9mVmFsdWUoaW5kZXgpIHtcbiAgICByZXR1cm4gdGhpcy5nZXRWYWx1ZShpbmRleCkudHlwZTtcbiAgfVxufVxuXG5leHBvcnQgZnVuY3Rpb24gdmFyaWFibGUoZGVmYXVsdF92YWx1ZSA9IFN5bWJvbC5mb3IoXCJlbGl4aXJzY3JpcHQubm9fdmFsdWVcIikpIHtcbiAgcmV0dXJuIG5ldyBWYXJpYWJsZShkZWZhdWx0X3ZhbHVlKTtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIHdpbGRjYXJkKCkge1xuICByZXR1cm4gbmV3IFdpbGRjYXJkKCk7XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBzdGFydHNXaXRoKHByZWZpeCkge1xuICByZXR1cm4gbmV3IFN0YXJ0c1dpdGgocHJlZml4KTtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIGNhcHR1cmUodmFsdWUpIHtcbiAgcmV0dXJuIG5ldyBDYXB0dXJlKHZhbHVlKTtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIGhlYWRUYWlsKGhlYWQgPSBudWxsLCB0YWlsID0gbnVsbCkge1xuICByZXR1cm4gbmV3IEhlYWRUYWlsKGhlYWQsIHRhaWwpO1xufVxuXG5leHBvcnQgZnVuY3Rpb24gdHlwZSh0eXBlLCBvYmpQYXR0ZXJuID0ge30pIHtcbiAgcmV0dXJuIG5ldyBUeXBlKHR5cGUsIG9ialBhdHRlcm4pO1xufVxuXG5leHBvcnQgZnVuY3Rpb24gYm91bmQodmFsdWUpIHtcbiAgcmV0dXJuIG5ldyBCb3VuZCh2YWx1ZSk7XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBiaXRTdHJpbmdNYXRjaCguLi52YWx1ZXMpIHtcbiAgcmV0dXJuIG5ldyBCaXRTdHJpbmdNYXRjaCguLi52YWx1ZXMpO1xufVxuLy8jIHNvdXJjZU1hcHBpbmdVUkw9ZGF0YTphcHBsaWNhdGlvbi9qc29uO2Jhc2U2NCxleUoyWlhKemFXOXVJam96TENKemIzVnlZMlZ6SWpwYklteHBZaTlqYjNKbEwzQmhkSFJsY201ekwzUjVjR1Z6TG1weklsMHNJbTVoYldWeklqcGJYU3dpYldGd2NHbHVaM01pT2lJN1FVRkRRU3hQUVVGUExFMUJRVTBzVVVGQlRpeERRVUZsT3p0QlFVZHdRaXhqUVVGblF5eG5Ra0ZCUlN4UFFVRlBMRWRCUVZBc1EwRkJWeXgxUWtGQldDeERRVUZHTEVWQlFYVkRPMEZCUTNKRkxGTkJRVXNzWVVGQlRDeEhRVUZ4UWl4aFFVRnlRaXhEUVVSeFJUdEhRVUYyUlR0RFFVaExPenRCUVZGUUxFOUJRVThzVFVGQlRTeFJRVUZPTEVOQlFXVTdRVUZEY0VJc1owSkJRV01zUlVGQlpEdERRVVJMT3p0QlFVdFFMRTlCUVU4c1RVRkJUU3hWUVVGT0xFTkJRV2xDT3p0QlFVZDBRaXhqUVVGWkxFMUJRVm9zUlVGQk5FSTdRVUZETVVJc1UwRkJTeXhOUVVGTUxFZEJRV01zVFVGQlpDeERRVVF3UWp0SFFVRTFRanREUVVoTE96dEJRVkZRTEU5QlFVOHNUVUZCVFN4UFFVRk9MRU5CUVdNN08wRkJSMjVDTEdOQlFWa3NTMEZCV2l4RlFVRjNRanRCUVVOMFFpeFRRVUZMTEV0QlFVd3NSMEZCWVN4TFFVRmlMRU5CUkhOQ08wZEJRWGhDTzBOQlNFczdPMEZCVVZBc1QwRkJUeXhOUVVGTkxGRkJRVTRzUTBGQlpUczdRVUZKY0VJc1kwRkJjMElzVDBGQlJTeEpRVUZHTEVWQlFXdENMRTlCUVVVc1NVRkJSaXhGUVVGUk8wRkJRemxETEZOQlFVc3NTVUZCVEN4SFFVRlpMRWxCUVZvc1EwRkVPRU03UVVGRk9VTXNVMEZCU3l4SlFVRk1MRWRCUVZrc1NVRkJXaXhEUVVZNFF6dEhRVUZvUkR0RFFVcExPenRCUVZWUUxFOUJRVThzVFVGQlRTeEpRVUZPTEVOQlFWYzdPMEZCU1doQ0xHTkJRVmtzU1VGQldpeEZRVUV3UXl4aFFVRkZMRVZCUVVZc1JVRkJUVHRCUVVNNVF5eFRRVUZMTEVsQlFVd3NSMEZCV1N4SlFVRmFMRU5CUkRoRE8wRkJSVGxETEZOQlFVc3NWVUZCVEN4SFFVRnJRaXhWUVVGc1FpeERRVVk0UXp0SFFVRm9SRHREUVVwTE96dEJRVlZRTEU5QlFVOHNUVUZCVFN4TFFVRk9MRU5CUVZrN08wRkJSMnBDTEdOQlFWa3NTMEZCV2l4RlFVRjNRanRCUVVOMFFpeFRRVUZMTEV0QlFVd3NSMEZCWVN4TFFVRmlMRU5CUkhOQ08wZEJRWGhDTzBOQlNFczdPMEZCVVZBc1QwRkJUeXhOUVVGTkxHTkJRVTRzUTBGQmNVSTdPMEZCUnpGQ0xHTkJRVmtzUjBGQlJ5eE5RVUZJTEVWQlFYbENPMEZCUTI1RExGTkJRVXNzVFVGQlRDeEhRVUZqTEUxQlFXUXNRMEZFYlVNN1IwRkJja003TzBGQlNVRXNWMEZCVXp0QlFVTlFMRmRCUVU4c1QwRkJUeXhOUVVGUUxFTkJSRUU3UjBGQlZEczdRVUZKUVN4aFFVRlhPMEZCUTFRc1YwRkJUeXhMUVVGTExGTkJRVXdzUzBGQmJVSXNRMEZCYmtJc1EwRkVSVHRIUVVGWU96dEJRVWxCTEdOQlFWYzdRVUZEVkN4UlFVRkpMRWxCUVVrc1EwRkJTaXhEUVVSTE96dEJRVWRVTEZOQlFVa3NTVUZCU1N4SFFVRktMRWxCUVZjc1MwRkJTeXhOUVVGTUxFVkJRVms3UVVGRGVrSXNWVUZCU1N4SlFVRkxMRWRCUVVNc1EwRkJTU3hKUVVGS0xFZEJRVmNzU1VGQlNTeEpRVUZLTEVkQlFWVXNRMEZCZEVJc1EwRkVaMEk3UzBGQk0wSTdPMEZCU1VFc1YwRkJUeXhEUVVGUUxFTkJVRk03UjBGQldEczdRVUZWUVN4WFFVRlRMRXRCUVZRc1JVRkJaVHRCUVVOaUxGZEJRVThzUzBGQlN5eE5RVUZNTEVOQlFWa3NTMEZCV2l4RFFVRlFMRU5CUkdFN1IwRkJaanM3UVVGSlFTeHBRa0ZCWlN4TFFVRm1MRVZCUVhGQ08wRkJRMjVDTEZGQlFVa3NUVUZCVFN4TFFVRkxMRkZCUVV3c1EwRkJZeXhMUVVGa0xFTkJRVTRzUTBGRVpUdEJRVVZ1UWl4WFFVRlBMRWxCUVVrc1NVRkJTaXhIUVVGWExFbEJRVWtzU1VGQlNpeERRVVpETzBkQlFYSkNPenRCUVV0QkxHbENRVUZsTEV0QlFXWXNSVUZCY1VJN1FVRkRia0lzVjBGQlR5eExRVUZMTEZGQlFVd3NRMEZCWXl4TFFVRmtMRVZCUVhGQ0xFbEJRWEpDTEVOQlJGazdSMEZCY2tJN1EwRnNRMHM3TzBGQmRVTlFMRTlCUVU4c1UwRkJVeXhSUVVGVUxFTkJRWE5ETEdkQ1FVRkZMRTlCUVU4c1IwRkJVQ3hEUVVGWExIVkNRVUZZTEVOQlFVWXNSVUZCYVVRN1FVRkROVVlzVTBGQlR5eEpRVUZKTEZGQlFVb3NRMEZCWVN4aFFVRmlMRU5CUVZBc1EwRkVORVk3UTBGQmRrWTdPMEZCU1ZBc1QwRkJUeXhUUVVGVExGRkJRVlFzUjBGQk9FSTdRVUZEYmtNc1UwRkJUeXhKUVVGSkxGRkJRVW9zUlVGQlVDeERRVVJ0UXp0RFFVRTVRanM3UVVGSlVDeFBRVUZQTEZOQlFWTXNWVUZCVkN4RFFVRnZRaXhOUVVGd1FpeEZRVUZuUkR0QlFVTnlSQ3hUUVVGUExFbEJRVWtzVlVGQlNpeERRVUZsTEUxQlFXWXNRMEZCVUN4RFFVUnhSRHREUVVGb1JEczdRVUZKVUN4UFFVRlBMRk5CUVZNc1QwRkJWQ3hEUVVGcFFpeExRVUZxUWl4RlFVRnpRenRCUVVNelF5eFRRVUZQTEVsQlFVa3NUMEZCU2l4RFFVRlpMRXRCUVZvc1EwRkJVQ3hEUVVReVF6dERRVUYwUXpzN1FVRkpVQ3hQUVVGUExGTkJRVk1zVVVGQlZDeERRVUUwUWl4UFFVRkZMRWxCUVVZc1JVRkJhMElzVDBGQlJTeEpRVUZHTEVWQlFXdENPMEZCUTNKRkxGTkJRVThzU1VGQlNTeFJRVUZLTEVOQlFXRXNTVUZCWWl4RlFVRnRRaXhKUVVGdVFpeERRVUZRTEVOQlJIRkZPME5CUVdoRk96dEJRVWxRTEU5QlFVOHNVMEZCVXl4SlFVRlVMRU5CUVdNc1NVRkJaQ3hGUVVFMFF5eGhRVUZGTEVWQlFVWXNSVUZCV1R0QlFVTTNSQ3hUUVVGUExFbEJRVWtzU1VGQlNpeERRVUZUTEVsQlFWUXNSVUZCWlN4VlFVRm1MRU5CUVZBc1EwRkVOa1E3UTBGQmVFUTdPMEZCU1ZBc1QwRkJUeXhUUVVGVExFdEJRVlFzUTBGQlpTeExRVUZtTEVWQlFXdERPMEZCUTNaRExGTkJRVThzU1VGQlNTeExRVUZLTEVOQlFWVXNTMEZCVml4RFFVRlFMRU5CUkhWRE8wTkJRV3hET3p0QlFVbFFMRTlCUVU4c1UwRkJVeXhqUVVGVUxFTkJRWGRDTEVkQlFVY3NUVUZCU0N4RlFVRjVRanRCUVVOMFJDeFRRVUZQTEVsQlFVa3NZMEZCU2l4RFFVRnRRaXhIUVVGSExFMUJRVWdzUTBGQk1VSXNRMEZFYzBRN1EwRkJha1FpTENKbWFXeGxJam9pYkdsaUwyTnZjbVV2Y0dGMGRHVnlibk12ZEhsd1pYTXVhbk1pTENKemIzVnlZMlZ6UTI5dWRHVnVkQ0k2V3lJdktpQkFabXh2ZHlBcUwxeHVaWGh3YjNKMElHTnNZWE56SUZaaGNtbGhZbXhsSUh0Y2JpQWdaR1ZtWVhWc2RGOTJZV3gxWlRvZ1AyRnVlVHRjYmx4dUlDQmpiMjV6ZEhKMVkzUnZjaWhrWldaaGRXeDBYM1poYkhWbE9pQS9ZVzU1SUQwZ1UzbHRZbTlzTG1admNpaGNJbVZzYVhocGNuTmpjbWx3ZEM1dWIxOTJZV3gxWlZ3aUtTa2dlMXh1SUNBZ0lIUm9hWE11WkdWbVlYVnNkRjkyWVd4MVpTQTlJR1JsWm1GMWJIUmZkbUZzZFdVN1hHNGdJSDFjYm4xY2JseHVaWGh3YjNKMElHTnNZWE56SUZkcGJHUmpZWEprSUh0Y2JpQWdZMjl1YzNSeWRXTjBiM0lvS1NCN1hHNGdJSDFjYm4xY2JseHVaWGh3YjNKMElHTnNZWE56SUZOMFlYSjBjMWRwZEdnZ2UxeHVJQ0J3Y21WbWFYZzZJSE4wY21sdVp6dGNibHh1SUNCamIyNXpkSEoxWTNSdmNpaHdjbVZtYVhnNklITjBjbWx1WnlrZ2UxeHVJQ0FnSUhSb2FYTXVjSEpsWm1sNElEMGdjSEpsWm1sNE8xeHVJQ0I5WEc1OVhHNWNibVY0Y0c5eWRDQmpiR0Z6Y3lCRFlYQjBkWEpsSUh0Y2JpQWdkbUZzZFdVNklHRnVlVHRjYmx4dUlDQmpiMjV6ZEhKMVkzUnZjaWgyWVd4MVpUb2dZVzU1S1NCN1hHNGdJQ0FnZEdocGN5NTJZV3gxWlNBOUlIWmhiSFZsTzF4dUlDQjlYRzU5WEc1Y2JtVjRjRzl5ZENCamJHRnpjeUJJWldGa1ZHRnBiQ0I3WEc0Z0lHaGxZV1E2SUdGdWVUdGNiaUFnZEdGcGJEb2dZVzU1TzF4dVhHNGdJR052Ym5OMGNuVmpkRzl5S0dobFlXUTZJR0Z1ZVNBOUlHNTFiR3dzSUhSaGFXdzZJR0Z1ZVNBOUlHNTFiR3dwSUh0Y2JpQWdJQ0IwYUdsekxtaGxZV1FnUFNCb1pXRmtPMXh1SUNBZ0lIUm9hWE11ZEdGcGJDQTlJSFJoYVd3N1hHNGdJSDFjYm4xY2JseHVaWGh3YjNKMElHTnNZWE56SUZSNWNHVWdlMXh1SUNCMGVYQmxPaUJoYm5rN1hHNGdJRzlpYWxCaGRIUmxjbTQ2SUU5aWFtVmpkRHRjYmx4dUlDQmpiMjV6ZEhKMVkzUnZjaWgwZVhCbE9pQmhibmtzSUc5aWFsQmhkSFJsY200NklFOWlhbVZqZENBOUlIdDlLU0I3WEc0Z0lDQWdkR2hwY3k1MGVYQmxJRDBnZEhsd1pWeHVJQ0FnSUhSb2FYTXViMkpxVUdGMGRHVnliaUE5SUc5aWFsQmhkSFJsY201Y2JpQWdmVnh1ZlZ4dVhHNWxlSEJ2Y25RZ1kyeGhjM01nUW05MWJtUWdlMXh1SUNCMllXeDFaVG9nWVc1NU8xeHVYRzRnSUdOdmJuTjBjblZqZEc5eUtIWmhiSFZsT2lCaGJua3BJSHRjYmlBZ0lDQjBhR2x6TG5aaGJIVmxJRDBnZG1Gc2RXVTdYRzRnSUgxY2JuMWNibHh1Wlhod2IzSjBJR05zWVhOeklFSnBkRk4wY21sdVowMWhkR05vSUh0Y2JpQWdkbUZzZFdWek9pQkJjbkpoZVR4UFltcGxZM1ErWEc1Y2JpQWdZMjl1YzNSeWRXTjBiM0lvTGk0dWRtRnNkV1Z6T2lCQmNuSmhlVHhQWW1wbFkzUStLWHRjYmlBZ0lDQjBhR2x6TG5aaGJIVmxjeUE5SUhaaGJIVmxjenRjYmlBZ2ZWeHVYRzRnSUd4bGJtZDBhQ2dwSUh0Y2JpQWdJQ0J5WlhSMWNtNGdkbUZzZFdWekxteGxibWQwYUR0Y2JpQWdmVnh1WEc0Z0lHSnBkRjl6YVhwbEtDa2dlMXh1SUNBZ0lISmxkSFZ5YmlCMGFHbHpMbUo1ZEdWZmMybDZaU2dwSUNvZ09EdGNiaUFnZlZ4dVhHNGdJR0o1ZEdWZmMybDZaU2dwZTF4dUlDQWdJR3hsZENCeklEMGdNRHRjYmx4dUlDQWdJR1p2Y2loc1pYUWdkbUZzSUc5bUlIUm9hWE11ZG1Gc2RXVnpLWHRjYmlBZ0lDQWdJSE1nUFNCeklDc2dLQ2gyWVd3dWRXNXBkQ0FxSUhaaGJDNXphWHBsS1M4NEtUdGNiaUFnSUNCOVhHNWNiaUFnSUNCeVpYUjFjbTRnY3p0Y2JpQWdmVnh1WEc0Z0lHZGxkRlpoYkhWbEtHbHVaR1Y0S1h0Y2JpQWdJQ0J5WlhSMWNtNGdkR2hwY3k1MllXeDFaWE1vYVc1a1pYZ3BPMXh1SUNCOVhHNWNiaUFnWjJWMFUybDZaVTltVm1Gc2RXVW9hVzVrWlhncGUxeHVJQ0FnSUd4bGRDQjJZV3dnUFNCMGFHbHpMbWRsZEZaaGJIVmxLR2x1WkdWNEtUdGNiaUFnSUNCeVpYUjFjbTRnZG1Gc0xuVnVhWFFnS2lCMllXd3VjMmw2WlR0Y2JpQWdmVnh1WEc0Z0lHZGxkRlI1Y0dWUFpsWmhiSFZsS0dsdVpHVjRLWHRjYmlBZ0lDQnlaWFIxY200Z2RHaHBjeTVuWlhSV1lXeDFaU2hwYm1SbGVDa3VkSGx3WlR0Y2JpQWdmVnh1ZlZ4dVhHNWxlSEJ2Y25RZ1puVnVZM1JwYjI0Z2RtRnlhV0ZpYkdVb1pHVm1ZWFZzZEY5MllXeDFaVG9nUDJGdWVTQTlJRk41YldKdmJDNW1iM0lvWENKbGJHbDRhWEp6WTNKcGNIUXVibTlmZG1Gc2RXVmNJaWtwT2lCV1lYSnBZV0pzWlNCN1hHNGdJSEpsZEhWeWJpQnVaWGNnVm1GeWFXRmliR1VvWkdWbVlYVnNkRjkyWVd4MVpTazdYRzU5WEc1Y2JtVjRjRzl5ZENCbWRXNWpkR2x2YmlCM2FXeGtZMkZ5WkNncE9pQlhhV3hrWTJGeVpDQjdYRzRnSUhKbGRIVnliaUJ1WlhjZ1YybHNaR05oY21Rb0tUdGNibjFjYmx4dVpYaHdiM0owSUdaMWJtTjBhVzl1SUhOMFlYSjBjMWRwZEdnb2NISmxabWw0T2lCemRISnBibWNwT2lCVGRHRnlkSE5YYVhSb0lIdGNiaUFnY21WMGRYSnVJRzVsZHlCVGRHRnlkSE5YYVhSb0tIQnlaV1pwZUNrN1hHNTlYRzVjYm1WNGNHOXlkQ0JtZFc1amRHbHZiaUJqWVhCMGRYSmxLSFpoYkhWbE9pQmhibmtwT2lCRFlYQjBkWEpsSUh0Y2JpQWdjbVYwZFhKdUlHNWxkeUJEWVhCMGRYSmxLSFpoYkhWbEtUdGNibjFjYmx4dVpYaHdiM0owSUdaMWJtTjBhVzl1SUdobFlXUlVZV2xzS0dobFlXUTZJR0Z1ZVNBOUlHNTFiR3dzSUhSaGFXdzZJR0Z1ZVNBOUlHNTFiR3dwT2lCSVpXRmtWR0ZwYkNCN1hHNGdJSEpsZEhWeWJpQnVaWGNnU0dWaFpGUmhhV3dvYUdWaFpDd2dkR0ZwYkNrN1hHNTlYRzVjYm1WNGNHOXlkQ0JtZFc1amRHbHZiaUIwZVhCbEtIUjVjR1U2SUdGdWVTd2diMkpxVUdGMGRHVnliam9nVDJKcVpXTjBJRDBnZTMwcE9pQlVlWEJsSUh0Y2JpQWdjbVYwZFhKdUlHNWxkeUJVZVhCbEtIUjVjR1VzSUc5aWFsQmhkSFJsY200cE8xeHVmVnh1WEc1bGVIQnZjblFnWm5WdVkzUnBiMjRnWW05MWJtUW9kbUZzZFdVNklHRnVlU2s2SUVKdmRXNWtJSHRjYmlBZ2NtVjBkWEp1SUc1bGR5QkNiM1Z1WkNoMllXeDFaU2s3WEc1OVhHNWNibVY0Y0c5eWRDQm1kVzVqZEdsdmJpQmlhWFJUZEhKcGJtZE5ZWFJqYUNndUxpNTJZV3gxWlhNNklFRnljbUY1UEU5aWFtVmpkRDRwZTF4dUlDQnlaWFIxY200Z2JtVjNJRUpwZEZOMGNtbHVaMDFoZEdOb0tDNHVMblpoYkhWbGN5azdYRzU5WEc0aVhTd2ljMjkxY21ObFVtOXZkQ0k2SWk5emIzVnlZMlV2SW4wPVxuIiwiXG5cbmltcG9ydCB7IFZhcmlhYmxlLCBXaWxkY2FyZCwgSGVhZFRhaWwsIENhcHR1cmUsIFR5cGUsIFN0YXJ0c1dpdGgsIEJvdW5kLCBCaXRTdHJpbmdNYXRjaCB9IGZyb20gXCIuL3R5cGVzXCI7XG5cbmZ1bmN0aW9uIGlzX251bWJlcih2YWx1ZSkge1xuICByZXR1cm4gdHlwZW9mIHZhbHVlID09PSAnbnVtYmVyJztcbn1cblxuZnVuY3Rpb24gaXNfc3RyaW5nKHZhbHVlKSB7XG4gIHJldHVybiB0eXBlb2YgdmFsdWUgPT09ICdzdHJpbmcnO1xufVxuXG5mdW5jdGlvbiBpc19ib29sZWFuKHZhbHVlKSB7XG4gIHJldHVybiB0eXBlb2YgdmFsdWUgPT09ICdib29sZWFuJztcbn1cblxuZnVuY3Rpb24gaXNfc3ltYm9sKHZhbHVlKSB7XG4gIHJldHVybiB0eXBlb2YgdmFsdWUgPT09ICdzeW1ib2wnO1xufVxuXG5mdW5jdGlvbiBpc19udWxsKHZhbHVlKSB7XG4gIHJldHVybiB2YWx1ZSA9PT0gbnVsbDtcbn1cblxuZnVuY3Rpb24gaXNfdW5kZWZpbmVkKHZhbHVlKSB7XG4gIHJldHVybiB0eXBlb2YgdmFsdWUgPT09ICd1bmRlZmluZWQnO1xufVxuXG5mdW5jdGlvbiBpc19mdW5jdGlvbih2YWx1ZSkge1xuICByZXR1cm4gT2JqZWN0LnByb3RvdHlwZS50b1N0cmluZy5jYWxsKHZhbHVlKSA9PSAnW29iamVjdCBGdW5jdGlvbl0nO1xufVxuXG5mdW5jdGlvbiBpc192YXJpYWJsZSh2YWx1ZSkge1xuICByZXR1cm4gdmFsdWUgaW5zdGFuY2VvZiBWYXJpYWJsZTtcbn1cblxuZnVuY3Rpb24gaXNfd2lsZGNhcmQodmFsdWUpIHtcbiAgcmV0dXJuIHZhbHVlIGluc3RhbmNlb2YgV2lsZGNhcmQ7XG59XG5cbmZ1bmN0aW9uIGlzX2hlYWRUYWlsKHZhbHVlKSB7XG4gIHJldHVybiB2YWx1ZSBpbnN0YW5jZW9mIEhlYWRUYWlsO1xufVxuXG5mdW5jdGlvbiBpc19jYXB0dXJlKHZhbHVlKSB7XG4gIHJldHVybiB2YWx1ZSBpbnN0YW5jZW9mIENhcHR1cmU7XG59XG5cbmZ1bmN0aW9uIGlzX3R5cGUodmFsdWUpIHtcbiAgcmV0dXJuIHZhbHVlIGluc3RhbmNlb2YgVHlwZTtcbn1cblxuZnVuY3Rpb24gaXNfc3RhcnRzV2l0aCh2YWx1ZSkge1xuICByZXR1cm4gdmFsdWUgaW5zdGFuY2VvZiBTdGFydHNXaXRoO1xufVxuXG5mdW5jdGlvbiBpc19ib3VuZCh2YWx1ZSkge1xuICByZXR1cm4gdmFsdWUgaW5zdGFuY2VvZiBCb3VuZDtcbn1cblxuZnVuY3Rpb24gaXNfb2JqZWN0KHZhbHVlKSB7XG4gIHJldHVybiB0eXBlb2YgdmFsdWUgPT09ICdvYmplY3QnO1xufVxuXG5mdW5jdGlvbiBpc19hcnJheSh2YWx1ZSkge1xuICByZXR1cm4gQXJyYXkuaXNBcnJheSh2YWx1ZSk7XG59XG5cbmZ1bmN0aW9uIGlzX2JpdHN0cmluZyh2YWx1ZSkge1xuICByZXR1cm4gdmFsdWUgaW5zdGFuY2VvZiBCaXRTdHJpbmdNYXRjaDtcbn1cblxuZXhwb3J0IGRlZmF1bHQge1xuICBpc19udW1iZXIsXG4gIGlzX3N0cmluZyxcbiAgaXNfYm9vbGVhbixcbiAgaXNfc3ltYm9sLFxuICBpc19udWxsLFxuICBpc191bmRlZmluZWQsXG4gIGlzX2Z1bmN0aW9uLFxuICBpc192YXJpYWJsZSxcbiAgaXNfd2lsZGNhcmQsXG4gIGlzX2hlYWRUYWlsLFxuICBpc19jYXB0dXJlLFxuICBpc190eXBlLFxuICBpc19zdGFydHNXaXRoLFxuICBpc19ib3VuZCxcbiAgaXNfb2JqZWN0LFxuICBpc19hcnJheSxcbiAgaXNfYml0c3RyaW5nXG59O1xuLy8jIHNvdXJjZU1hcHBpbmdVUkw9ZGF0YTphcHBsaWNhdGlvbi9qc29uO2Jhc2U2NCxleUoyWlhKemFXOXVJam96TENKemIzVnlZMlZ6SWpwYklteHBZaTlqYjNKbEwzQmhkSFJsY201ekwyTm9aV05yY3k1cWN5SmRMQ0p1WVcxbGN5STZXMTBzSW0xaGNIQnBibWR6SWpvaU96dEJRVVZCTEZOQlFWTXNVVUZCVkN4RlFVRnRRaXhSUVVGdVFpeEZRVUUyUWl4UlFVRTNRaXhGUVVGMVF5eFBRVUYyUXl4RlFVRm5SQ3hKUVVGb1JDeEZRVUZ6UkN4VlFVRjBSQ3hGUVVGclJTeExRVUZzUlN4RlFVRjVSU3hqUVVGNlJTeFJRVUVyUml4VFFVRXZSanM3UVVGRlFTeFRRVUZUTEZOQlFWUXNRMEZCYlVJc1MwRkJia0lzUlVGQmQwTTdRVUZEZEVNc1UwRkJUeXhQUVVGUExFdEJRVkFzUzBGQmFVSXNVVUZCYWtJc1EwRkVLMEk3UTBGQmVFTTdPMEZCU1VFc1UwRkJVeXhUUVVGVUxFTkJRVzFDTEV0QlFXNUNMRVZCUVhWRE8wRkJRM0pETEZOQlFVOHNUMEZCVHl4TFFVRlFMRXRCUVdsQ0xGRkJRV3BDTEVOQlJEaENPME5CUVhaRE96dEJRVWxCTEZOQlFWTXNWVUZCVkN4RFFVRnZRaXhMUVVGd1FpeEZRVUY1UXp0QlFVTjJReXhUUVVGUExFOUJRVThzUzBGQlVDeExRVUZwUWl4VFFVRnFRaXhEUVVSblF6dERRVUY2UXpzN1FVRkpRU3hUUVVGVExGTkJRVlFzUTBGQmJVSXNTMEZCYmtJc1JVRkJkME03UVVGRGRFTXNVMEZCVHl4UFFVRlBMRXRCUVZBc1MwRkJhVUlzVVVGQmFrSXNRMEZFSzBJN1EwRkJlRU03TzBGQlNVRXNVMEZCVXl4UFFVRlVMRU5CUVdsQ0xFdEJRV3BDTEVWQlFYTkRPMEZCUTNCRExGTkJRVThzVlVGQlZTeEpRVUZXTEVOQlJEWkNPME5CUVhSRE96dEJRVWxCTEZOQlFWTXNXVUZCVkN4RFFVRnpRaXhMUVVGMFFpeEZRVUV5UXp0QlFVTjZReXhUUVVGUExFOUJRVThzUzBGQlVDeExRVUZwUWl4WFFVRnFRaXhEUVVSclF6dERRVUV6UXpzN1FVRkpRU3hUUVVGVExGZEJRVlFzUTBGQmNVSXNTMEZCY2tJc1JVRkJNRU03UVVGRGVFTXNVMEZCVHl4UFFVRlBMRk5CUVZBc1EwRkJhVUlzVVVGQmFrSXNRMEZCTUVJc1NVRkJNVUlzUTBGQkswSXNTMEZCTDBJc1MwRkJlVU1zYlVKQlFYcERMRU5CUkdsRE8wTkJRVEZET3p0QlFVbEJMRk5CUVZNc1YwRkJWQ3hEUVVGeFFpeExRVUZ5UWl4RlFVRXdRenRCUVVONFF5eFRRVUZQTEdsQ1FVRnBRaXhSUVVGcVFpeERRVVJwUXp0RFFVRXhRenM3UVVGSlFTeFRRVUZUTEZkQlFWUXNRMEZCY1VJc1MwRkJja0lzUlVGQk1FTTdRVUZEZUVNc1UwRkJUeXhwUWtGQmFVSXNVVUZCYWtJc1EwRkVhVU03UTBGQk1VTTdPMEZCU1VFc1UwRkJVeXhYUVVGVUxFTkJRWEZDTEV0QlFYSkNMRVZCUVRCRE8wRkJRM2hETEZOQlFVOHNhVUpCUVdsQ0xGRkJRV3BDTEVOQlJHbERPME5CUVRGRE96dEJRVWxCTEZOQlFWTXNWVUZCVkN4RFFVRnZRaXhMUVVGd1FpeEZRVUY1UXp0QlFVTjJReXhUUVVGUExHbENRVUZwUWl4UFFVRnFRaXhEUVVSblF6dERRVUY2UXpzN1FVRkpRU3hUUVVGVExFOUJRVlFzUTBGQmFVSXNTMEZCYWtJc1JVRkJjME03UVVGRGNFTXNVMEZCVHl4cFFrRkJhVUlzU1VGQmFrSXNRMEZFTmtJN1EwRkJkRU03TzBGQlNVRXNVMEZCVXl4aFFVRlVMRU5CUVhWQ0xFdEJRWFpDTEVWQlFUUkRPMEZCUXpGRExGTkJRVThzYVVKQlFXbENMRlZCUVdwQ0xFTkJSRzFETzBOQlFUVkRPenRCUVVsQkxGTkJRVk1zVVVGQlZDeERRVUZyUWl4TFFVRnNRaXhGUVVGMVF6dEJRVU55UXl4VFFVRlBMR2xDUVVGcFFpeExRVUZxUWl4RFFVUTRRanREUVVGMlF6czdRVUZKUVN4VFFVRlRMRk5CUVZRc1EwRkJiVUlzUzBGQmJrSXNSVUZCZDBNN1FVRkRkRU1zVTBGQlR5eFBRVUZQTEV0QlFWQXNTMEZCYVVJc1VVRkJha0lzUTBGRUswSTdRMEZCZUVNN08wRkJTVUVzVTBGQlV5eFJRVUZVTEVOQlFXdENMRXRCUVd4Q0xFVkJRWFZETzBGQlEzSkRMRk5CUVU4c1RVRkJUU3hQUVVGT0xFTkJRV01zUzBGQlpDeERRVUZRTEVOQlJIRkRPME5CUVhaRE96dEJRVWxCTEZOQlFWTXNXVUZCVkN4RFFVRnpRaXhMUVVGMFFpeEZRVUV5UXp0QlFVTjZReXhUUVVGUExHbENRVUZwUWl4alFVRnFRaXhEUVVSclF6dERRVUV6UXpzN1FVRkxRU3hsUVVGbE8wRkJRMklzVjBGRVlUdEJRVVZpTEZkQlJtRTdRVUZIWWl4WlFVaGhPMEZCU1dJc1YwRktZVHRCUVV0aUxGTkJUR0U3UVVGTllpeGpRVTVoTzBGQlQySXNZVUZRWVR0QlFWRmlMR0ZCVW1FN1FVRlRZaXhoUVZSaE8wRkJWV0lzWVVGV1lUdEJRVmRpTEZsQldHRTdRVUZaWWl4VFFWcGhPMEZCWVdJc1pVRmlZVHRCUVdOaUxGVkJaR0U3UVVGbFlpeFhRV1poTzBGQlowSmlMRlZCYUVKaE8wRkJhVUppTEdOQmFrSmhPME5CUVdZaUxDSm1hV3hsSWpvaWJHbGlMMk52Y21VdmNHRjBkR1Z5Ym5NdlkyaGxZMnR6TG1weklpd2ljMjkxY21ObGMwTnZiblJsYm5RaU9sc2lMeW9nUUdac2IzY2dLaTljYmx4dWFXMXdiM0owSUhzZ1ZtRnlhV0ZpYkdVc0lGZHBiR1JqWVhKa0xDQklaV0ZrVkdGcGJDd2dRMkZ3ZEhWeVpTd2dWSGx3WlN3Z1UzUmhjblJ6VjJsMGFDd2dRbTkxYm1Rc0lFSnBkRk4wY21sdVowMWhkR05vSUgwZ1puSnZiU0JjSWk0dmRIbHdaWE5jSWp0Y2JseHVablZ1WTNScGIyNGdhWE5mYm5WdFltVnlLSFpoYkhWbE9pQmhibmtwT2lCaWIyOXNaV0Z1SUh0Y2JpQWdjbVYwZFhKdUlIUjVjR1Z2WmlCMllXeDFaU0E5UFQwZ0oyNTFiV0psY2ljN1hHNTlYRzVjYm1aMWJtTjBhVzl1SUdselgzTjBjbWx1WnloMllXeDFaVG9nWVc1NUtUb2dZbTl2YkdWaGJudGNiaUFnY21WMGRYSnVJSFI1Y0dWdlppQjJZV3gxWlNBOVBUMGdKM04wY21sdVp5YzdYRzU5WEc1Y2JtWjFibU4wYVc5dUlHbHpYMkp2YjJ4bFlXNG9kbUZzZFdVNklHRnVlU2s2SUdKdmIyeGxZVzRnZTF4dUlDQnlaWFIxY200Z2RIbHdaVzltSUhaaGJIVmxJRDA5UFNBblltOXZiR1ZoYmljN1hHNTlYRzVjYm1aMWJtTjBhVzl1SUdselgzTjViV0p2YkNoMllXeDFaVG9nWVc1NUtUb2dZbTl2YkdWaGJpQjdYRzRnSUhKbGRIVnliaUIwZVhCbGIyWWdkbUZzZFdVZ1BUMDlJQ2R6ZVcxaWIyd25PMXh1ZlZ4dVhHNW1kVzVqZEdsdmJpQnBjMTl1ZFd4c0tIWmhiSFZsT2lCaGJua3BPaUJpYjI5c1pXRnVJSHRjYmlBZ2NtVjBkWEp1SUhaaGJIVmxJRDA5UFNCdWRXeHNPMXh1ZlZ4dVhHNW1kVzVqZEdsdmJpQnBjMTkxYm1SbFptbHVaV1FvZG1Gc2RXVTZJR0Z1ZVNrNklHSnZiMnhsWVc0Z2UxeHVJQ0J5WlhSMWNtNGdkSGx3Wlc5bUlIWmhiSFZsSUQwOVBTQW5kVzVrWldacGJtVmtKenRjYm4xY2JseHVablZ1WTNScGIyNGdhWE5mWm5WdVkzUnBiMjRvZG1Gc2RXVTZJR0Z1ZVNrNklHSnZiMnhsWVc0Z2UxeHVJQ0J5WlhSMWNtNGdUMkpxWldOMExuQnliM1J2ZEhsd1pTNTBiMU4wY21sdVp5NWpZV3hzS0haaGJIVmxLU0E5UFNBblcyOWlhbVZqZENCR2RXNWpkR2x2Ymwwbk8xeHVmVnh1WEc1bWRXNWpkR2x2YmlCcGMxOTJZWEpwWVdKc1pTaDJZV3gxWlRvZ1lXNTVLVG9nWW05dmJHVmhiaUI3WEc0Z0lISmxkSFZ5YmlCMllXeDFaU0JwYm5OMFlXNWpaVzltSUZaaGNtbGhZbXhsTzF4dWZWeHVYRzVtZFc1amRHbHZiaUJwYzE5M2FXeGtZMkZ5WkNoMllXeDFaVG9nWVc1NUtUb2dZbTl2YkdWaGJpQjdYRzRnSUhKbGRIVnliaUIyWVd4MVpTQnBibk4wWVc1alpXOW1JRmRwYkdSallYSmtPMXh1ZlZ4dVhHNW1kVzVqZEdsdmJpQnBjMTlvWldGa1ZHRnBiQ2gyWVd4MVpUb2dZVzU1S1RvZ1ltOXZiR1ZoYmlCN1hHNGdJSEpsZEhWeWJpQjJZV3gxWlNCcGJuTjBZVzVqWlc5bUlFaGxZV1JVWVdsc08xeHVmVnh1WEc1bWRXNWpkR2x2YmlCcGMxOWpZWEIwZFhKbEtIWmhiSFZsT2lCaGJua3BPaUJpYjI5c1pXRnVJSHRjYmlBZ2NtVjBkWEp1SUhaaGJIVmxJR2x1YzNSaGJtTmxiMllnUTJGd2RIVnlaVHRjYm4xY2JseHVablZ1WTNScGIyNGdhWE5mZEhsd1pTaDJZV3gxWlRvZ1lXNTVLVG9nWW05dmJHVmhiaUI3WEc0Z0lISmxkSFZ5YmlCMllXeDFaU0JwYm5OMFlXNWpaVzltSUZSNWNHVTdYRzU5WEc1Y2JtWjFibU4wYVc5dUlHbHpYM04wWVhKMGMxZHBkR2dvZG1Gc2RXVTZJR0Z1ZVNrNklHSnZiMnhsWVc0Z2UxeHVJQ0J5WlhSMWNtNGdkbUZzZFdVZ2FXNXpkR0Z1WTJWdlppQlRkR0Z5ZEhOWGFYUm9PMXh1ZlZ4dVhHNW1kVzVqZEdsdmJpQnBjMTlpYjNWdVpDaDJZV3gxWlRvZ1lXNTVLVG9nWW05dmJHVmhiaUI3WEc0Z0lISmxkSFZ5YmlCMllXeDFaU0JwYm5OMFlXNWpaVzltSUVKdmRXNWtPMXh1ZlZ4dVhHNW1kVzVqZEdsdmJpQnBjMTl2WW1wbFkzUW9kbUZzZFdVNklHRnVlU2s2SUdKdmIyeGxZVzRnZTF4dUlDQnlaWFIxY200Z2RIbHdaVzltSUhaaGJIVmxJRDA5UFNBbmIySnFaV04wSnp0Y2JuMWNibHh1Wm5WdVkzUnBiMjRnYVhOZllYSnlZWGtvZG1Gc2RXVTZJR0Z1ZVNrNklHSnZiMnhsWVc0Z2UxeHVJQ0J5WlhSMWNtNGdRWEp5WVhrdWFYTkJjbkpoZVNoMllXeDFaU2s3WEc1OVhHNWNibVoxYm1OMGFXOXVJR2x6WDJKcGRITjBjbWx1WnloMllXeDFaVG9nWVc1NUtUb2dZbTl2YkdWaGJpQjdYRzRnSUhKbGRIVnliaUIyWVd4MVpTQnBibk4wWVc1alpXOW1JRUpwZEZOMGNtbHVaMDFoZEdOb08xeHVmVnh1WEc1Y2JtVjRjRzl5ZENCa1pXWmhkV3gwSUh0Y2JpQWdhWE5mYm5WdFltVnlMRnh1SUNCcGMxOXpkSEpwYm1jc1hHNGdJR2x6WDJKdmIyeGxZVzRzWEc0Z0lHbHpYM041YldKdmJDeGNiaUFnYVhOZmJuVnNiQ3hjYmlBZ2FYTmZkVzVrWldacGJtVmtMRnh1SUNCcGMxOW1kVzVqZEdsdmJpeGNiaUFnYVhOZmRtRnlhV0ZpYkdVc1hHNGdJR2x6WDNkcGJHUmpZWEprTEZ4dUlDQnBjMTlvWldGa1ZHRnBiQ3hjYmlBZ2FYTmZZMkZ3ZEhWeVpTeGNiaUFnYVhOZmRIbHdaU3hjYmlBZ2FYTmZjM1JoY25SelYybDBhQ3hjYmlBZ2FYTmZZbTkxYm1Rc1hHNGdJR2x6WDI5aWFtVmpkQ3hjYmlBZ2FYTmZZWEp5WVhrc1hHNGdJR2x6WDJKcGRITjBjbWx1WjF4dWZUdGNiaUpkTENKemIzVnlZMlZTYjI5MElqb2lMM052ZFhKalpTOGlmUT09XG4iLCJcblxuaW1wb3J0IENoZWNrcyBmcm9tIFwiLi9jaGVja3NcIjtcbmltcG9ydCAqIGFzIFR5cGVzIGZyb20gXCIuL3R5cGVzXCI7XG5pbXBvcnQgeyBidWlsZE1hdGNoIH0gZnJvbSBcIi4vbWF0Y2hcIjtcbmltcG9ydCBCaXRTdHJpbmcgZnJvbSBcIi4uL2JpdF9zdHJpbmdcIjtcblxuZnVuY3Rpb24gcmVzb2x2ZVN5bWJvbChwYXR0ZXJuKSB7XG4gIHJldHVybiBmdW5jdGlvbiAodmFsdWUpIHtcbiAgICByZXR1cm4gQ2hlY2tzLmlzX3N5bWJvbCh2YWx1ZSkgJiYgdmFsdWUgPT09IHBhdHRlcm47XG4gIH07XG59XG5cbmZ1bmN0aW9uIHJlc29sdmVTdHJpbmcocGF0dGVybikge1xuICByZXR1cm4gZnVuY3Rpb24gKHZhbHVlKSB7XG4gICAgcmV0dXJuIENoZWNrcy5pc19zdHJpbmcodmFsdWUpICYmIHZhbHVlID09PSBwYXR0ZXJuO1xuICB9O1xufVxuXG5mdW5jdGlvbiByZXNvbHZlTnVtYmVyKHBhdHRlcm4pIHtcbiAgcmV0dXJuIGZ1bmN0aW9uICh2YWx1ZSkge1xuICAgIHJldHVybiBDaGVja3MuaXNfbnVtYmVyKHZhbHVlKSAmJiB2YWx1ZSA9PT0gcGF0dGVybjtcbiAgfTtcbn1cblxuZnVuY3Rpb24gcmVzb2x2ZUJvb2xlYW4ocGF0dGVybikge1xuICByZXR1cm4gZnVuY3Rpb24gKHZhbHVlKSB7XG4gICAgcmV0dXJuIENoZWNrcy5pc19ib29sZWFuKHZhbHVlKSAmJiB2YWx1ZSA9PT0gcGF0dGVybjtcbiAgfTtcbn1cblxuZnVuY3Rpb24gcmVzb2x2ZUZ1bmN0aW9uKHBhdHRlcm4pIHtcbiAgcmV0dXJuIGZ1bmN0aW9uICh2YWx1ZSkge1xuICAgIHJldHVybiBDaGVja3MuaXNfZnVuY3Rpb24odmFsdWUpICYmIHZhbHVlID09PSBwYXR0ZXJuO1xuICB9O1xufVxuXG5mdW5jdGlvbiByZXNvbHZlTnVsbChwYXR0ZXJuKSB7XG4gIHJldHVybiBmdW5jdGlvbiAodmFsdWUpIHtcbiAgICByZXR1cm4gQ2hlY2tzLmlzX251bGwodmFsdWUpO1xuICB9O1xufVxuXG5mdW5jdGlvbiByZXNvbHZlQm91bmQocGF0dGVybikge1xuICByZXR1cm4gZnVuY3Rpb24gKHZhbHVlLCBhcmdzKSB7XG4gICAgaWYgKHR5cGVvZiB2YWx1ZSA9PT0gdHlwZW9mIHBhdHRlcm4udmFsdWUgJiYgdmFsdWUgPT09IHBhdHRlcm4udmFsdWUpIHtcbiAgICAgIGFyZ3MucHVzaCh2YWx1ZSk7XG4gICAgICByZXR1cm4gdHJ1ZTtcbiAgICB9XG5cbiAgICByZXR1cm4gZmFsc2U7XG4gIH07XG59XG5cbmZ1bmN0aW9uIHJlc29sdmVXaWxkY2FyZCgpIHtcbiAgcmV0dXJuIGZ1bmN0aW9uICgpIHtcbiAgICByZXR1cm4gdHJ1ZTtcbiAgfTtcbn1cblxuZnVuY3Rpb24gcmVzb2x2ZVZhcmlhYmxlKCkge1xuICByZXR1cm4gZnVuY3Rpb24gKHZhbHVlLCBhcmdzKSB7XG4gICAgYXJncy5wdXNoKHZhbHVlKTtcbiAgICByZXR1cm4gdHJ1ZTtcbiAgfTtcbn1cblxuZnVuY3Rpb24gcmVzb2x2ZUhlYWRUYWlsKHBhdHRlcm4pIHtcbiAgY29uc3QgaGVhZE1hdGNoZXMgPSBidWlsZE1hdGNoKHBhdHRlcm4uaGVhZCk7XG4gIGNvbnN0IHRhaWxNYXRjaGVzID0gYnVpbGRNYXRjaChwYXR0ZXJuLnRhaWwpO1xuXG4gIHJldHVybiBmdW5jdGlvbiAodmFsdWUsIGFyZ3MpIHtcbiAgICBpZiAoIUNoZWNrcy5pc19hcnJheSh2YWx1ZSkgfHwgdmFsdWUubGVuZ3RoIDwgMikge1xuICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH1cblxuICAgIGNvbnN0IGhlYWQgPSB2YWx1ZVswXTtcbiAgICBjb25zdCB0YWlsID0gdmFsdWUuc2xpY2UoMSk7XG5cbiAgICBpZiAoaGVhZE1hdGNoZXMoaGVhZCwgYXJncykgJiYgdGFpbE1hdGNoZXModGFpbCwgYXJncykpIHtcbiAgICAgIHJldHVybiB0cnVlO1xuICAgIH1cbiAgfTtcbn1cblxuZnVuY3Rpb24gcmVzb2x2ZUNhcHR1cmUocGF0dGVybikge1xuICBjb25zdCBtYXRjaGVzID0gYnVpbGRNYXRjaChwYXR0ZXJuLnZhbHVlKTtcblxuICByZXR1cm4gZnVuY3Rpb24gKHZhbHVlLCBhcmdzKSB7XG4gICAgaWYgKG1hdGNoZXModmFsdWUsIGFyZ3MpKSB7XG4gICAgICBhcmdzLnB1c2godmFsdWUpO1xuICAgICAgcmV0dXJuIHRydWU7XG4gICAgfVxuXG4gICAgcmV0dXJuIGZhbHNlO1xuICB9O1xufVxuXG5mdW5jdGlvbiByZXNvbHZlU3RhcnRzV2l0aChwYXR0ZXJuKSB7XG4gIGNvbnN0IHByZWZpeCA9IHBhdHRlcm4ucHJlZml4O1xuXG4gIHJldHVybiBmdW5jdGlvbiAodmFsdWUsIGFyZ3MpIHtcbiAgICBpZiAoQ2hlY2tzLmlzX3N0cmluZyh2YWx1ZSkgJiYgdmFsdWUuc3RhcnRzV2l0aChwcmVmaXgpKSB7XG4gICAgICBhcmdzLnB1c2godmFsdWUuc3Vic3RyaW5nKHByZWZpeC5sZW5ndGgpKTtcbiAgICAgIHJldHVybiB0cnVlO1xuICAgIH1cblxuICAgIHJldHVybiBmYWxzZTtcbiAgfTtcbn1cblxuZnVuY3Rpb24gcmVzb2x2ZVR5cGUocGF0dGVybikge1xuICByZXR1cm4gZnVuY3Rpb24gKHZhbHVlLCBhcmdzKSB7XG4gICAgaWYgKHZhbHVlIGluc3RhbmNlb2YgcGF0dGVybi50eXBlKSB7XG4gICAgICBjb25zdCBtYXRjaGVzID0gYnVpbGRNYXRjaChwYXR0ZXJuLm9ialBhdHRlcm4pO1xuICAgICAgcmV0dXJuIG1hdGNoZXModmFsdWUsIGFyZ3MpICYmIGFyZ3MucHVzaCh2YWx1ZSkgPiAwO1xuICAgIH1cblxuICAgIHJldHVybiBmYWxzZTtcbiAgfTtcbn1cblxuZnVuY3Rpb24gcmVzb2x2ZUFycmF5KHBhdHRlcm4pIHtcbiAgY29uc3QgbWF0Y2hlcyA9IHBhdHRlcm4ubWFwKHggPT4gYnVpbGRNYXRjaCh4KSk7XG5cbiAgcmV0dXJuIGZ1bmN0aW9uICh2YWx1ZSwgYXJncykge1xuICAgIGlmICghQ2hlY2tzLmlzX2FycmF5KHZhbHVlKSB8fCB2YWx1ZS5sZW5ndGggIT0gcGF0dGVybi5sZW5ndGgpIHtcbiAgICAgIHJldHVybiBmYWxzZTtcbiAgICB9XG5cbiAgICByZXR1cm4gdmFsdWUuZXZlcnkoZnVuY3Rpb24gKHYsIGkpIHtcbiAgICAgIHJldHVybiBtYXRjaGVzW2ldKHZhbHVlW2ldLCBhcmdzKTtcbiAgICB9KTtcbiAgfTtcbn1cblxuZnVuY3Rpb24gcmVzb2x2ZU9iamVjdChwYXR0ZXJuKSB7XG4gIGxldCBtYXRjaGVzID0ge307XG5cbiAgZm9yIChsZXQga2V5IG9mIE9iamVjdC5rZXlzKHBhdHRlcm4pLmNvbmNhdChPYmplY3QuZ2V0T3duUHJvcGVydHlTeW1ib2xzKHBhdHRlcm4pKSkge1xuICAgIG1hdGNoZXNba2V5XSA9IGJ1aWxkTWF0Y2gocGF0dGVybltrZXldKTtcbiAgfVxuXG4gIHJldHVybiBmdW5jdGlvbiAodmFsdWUsIGFyZ3MpIHtcbiAgICBpZiAoIUNoZWNrcy5pc19vYmplY3QodmFsdWUpIHx8IHBhdHRlcm4ubGVuZ3RoID4gdmFsdWUubGVuZ3RoKSB7XG4gICAgICByZXR1cm4gZmFsc2U7XG4gICAgfVxuXG4gICAgZm9yIChsZXQga2V5IG9mIE9iamVjdC5rZXlzKHBhdHRlcm4pLmNvbmNhdChPYmplY3QuZ2V0T3duUHJvcGVydHlTeW1ib2xzKHBhdHRlcm4pKSkge1xuICAgICAgaWYgKCEoa2V5IGluIHZhbHVlKSB8fCAhbWF0Y2hlc1trZXldKHZhbHVlW2tleV0sIGFyZ3MpKSB7XG4gICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICByZXR1cm4gdHJ1ZTtcbiAgfTtcbn1cblxuZnVuY3Rpb24gcmVzb2x2ZUJpdFN0cmluZyhwYXR0ZXJuKSB7XG4gIGxldCBwYXR0ZXJuQml0U3RyaW5nID0gW107XG5cbiAgZm9yIChsZXQgYml0c3RyaW5nTWF0Y2hQYXJ0IG9mIHBhdHRlcm4udmFsdWVzKSB7XG4gICAgaWYgKENoZWNrcy5pc192YXJpYWJsZShiaXRzdHJpbmdNYXRjaFBhcnQudmFsdWUpKSB7XG4gICAgICBsZXQgc2l6ZSA9IGdldFNpemUoYml0c3RyaW5nTWF0Y2hQYXJ0LnVuaXQsIGJpdHN0cmluZ01hdGNoUGFydC5zaXplKTtcbiAgICAgIGZpbGxBcnJheShwYXR0ZXJuQml0U3RyaW5nLCBzaXplKTtcbiAgICB9IGVsc2Uge1xuICAgICAgcGF0dGVybkJpdFN0cmluZyA9IHBhdHRlcm5CaXRTdHJpbmcuY29uY2F0KG5ldyBCaXRTdHJpbmcoYml0c3RyaW5nTWF0Y2hQYXJ0KS52YWx1ZSk7XG4gICAgfVxuICB9XG5cbiAgbGV0IHBhdHRlcm5WYWx1ZXMgPSBwYXR0ZXJuLnZhbHVlcztcblxuICByZXR1cm4gZnVuY3Rpb24gKHZhbHVlLCBhcmdzKSB7XG4gICAgbGV0IGJzVmFsdWUgPSBudWxsO1xuXG4gICAgaWYgKCFDaGVja3MuaXNfc3RyaW5nKHZhbHVlKSAmJiAhKHZhbHVlIGluc3RhbmNlb2YgQml0U3RyaW5nKSkge1xuICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH1cblxuICAgIGlmIChDaGVja3MuaXNfc3RyaW5nKHZhbHVlKSkge1xuICAgICAgYnNWYWx1ZSA9IG5ldyBCaXRTdHJpbmcoQml0U3RyaW5nLmJpbmFyeSh2YWx1ZSkpO1xuICAgIH0gZWxzZSB7XG4gICAgICBic1ZhbHVlID0gdmFsdWU7XG4gICAgfVxuXG4gICAgbGV0IGJlZ2lubmluZ0luZGV4ID0gMDtcblxuICAgIGZvciAobGV0IGkgPSAwOyBpIDwgcGF0dGVyblZhbHVlcy5sZW5ndGg7IGkrKykge1xuICAgICAgbGV0IGJpdHN0cmluZ01hdGNoUGFydCA9IHBhdHRlcm5WYWx1ZXNbaV07XG5cbiAgICAgIGlmIChDaGVja3MuaXNfdmFyaWFibGUoYml0c3RyaW5nTWF0Y2hQYXJ0LnZhbHVlKSAmJiBiaXRzdHJpbmdNYXRjaFBhcnQudHlwZSA9PSAnYmluYXJ5JyAmJiBiaXRzdHJpbmdNYXRjaFBhcnQuc2l6ZSA9PT0gdW5kZWZpbmVkICYmIGkgPCBwYXR0ZXJuVmFsdWVzLmxlbmd0aCAtIDEpIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKFwiYSBiaW5hcnkgZmllbGQgd2l0aG91dCBzaXplIGlzIG9ubHkgYWxsb3dlZCBhdCB0aGUgZW5kIG9mIGEgYmluYXJ5IHBhdHRlcm5cIik7XG4gICAgICB9XG5cbiAgICAgIGxldCBzaXplID0gMDtcbiAgICAgIGxldCBic1ZhbHVlQXJyYXlQYXJ0ID0gW107XG4gICAgICBsZXQgcGF0dGVybkJpdFN0cmluZ0FycmF5UGFydCA9IFtdO1xuICAgICAgc2l6ZSA9IGdldFNpemUoYml0c3RyaW5nTWF0Y2hQYXJ0LnVuaXQsIGJpdHN0cmluZ01hdGNoUGFydC5zaXplKTtcblxuICAgICAgaWYgKGkgPT09IHBhdHRlcm5WYWx1ZXMubGVuZ3RoIC0gMSkge1xuICAgICAgICBic1ZhbHVlQXJyYXlQYXJ0ID0gYnNWYWx1ZS52YWx1ZS5zbGljZShiZWdpbm5pbmdJbmRleCk7XG4gICAgICAgIHBhdHRlcm5CaXRTdHJpbmdBcnJheVBhcnQgPSBwYXR0ZXJuQml0U3RyaW5nLnNsaWNlKGJlZ2lubmluZ0luZGV4KTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIGJzVmFsdWVBcnJheVBhcnQgPSBic1ZhbHVlLnZhbHVlLnNsaWNlKGJlZ2lubmluZ0luZGV4LCBiZWdpbm5pbmdJbmRleCArIHNpemUpO1xuICAgICAgICBwYXR0ZXJuQml0U3RyaW5nQXJyYXlQYXJ0ID0gcGF0dGVybkJpdFN0cmluZy5zbGljZShiZWdpbm5pbmdJbmRleCwgYmVnaW5uaW5nSW5kZXggKyBzaXplKTtcbiAgICAgIH1cblxuICAgICAgaWYgKENoZWNrcy5pc192YXJpYWJsZShiaXRzdHJpbmdNYXRjaFBhcnQudmFsdWUpKSB7XG4gICAgICAgIHN3aXRjaCAoYml0c3RyaW5nTWF0Y2hQYXJ0LnR5cGUpIHtcbiAgICAgICAgICBjYXNlICdpbnRlZ2VyJzpcbiAgICAgICAgICAgIGlmIChiaXRzdHJpbmdNYXRjaFBhcnQuYXR0cmlidXRlcyAmJiBiaXRzdHJpbmdNYXRjaFBhcnQuYXR0cmlidXRlcy5pbmRleE9mKFwic2lnbmVkXCIpICE9IC0xKSB7XG4gICAgICAgICAgICAgIGFyZ3MucHVzaChuZXcgSW50OEFycmF5KFtic1ZhbHVlQXJyYXlQYXJ0WzBdXSlbMF0pO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgYXJncy5wdXNoKG5ldyBVaW50OEFycmF5KFtic1ZhbHVlQXJyYXlQYXJ0WzBdXSlbMF0pO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgYnJlYWs7XG5cbiAgICAgICAgICBjYXNlICdmbG9hdCc6XG4gICAgICAgICAgICBpZiAoc2l6ZSA9PT0gNjQpIHtcbiAgICAgICAgICAgICAgYXJncy5wdXNoKEZsb2F0NjRBcnJheS5mcm9tKGJzVmFsdWVBcnJheVBhcnQpWzBdKTtcbiAgICAgICAgICAgIH0gZWxzZSBpZiAoc2l6ZSA9PT0gMzIpIHtcbiAgICAgICAgICAgICAgYXJncy5wdXNoKEZsb2F0MzJBcnJheS5mcm9tKGJzVmFsdWVBcnJheVBhcnQpWzBdKTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGJyZWFrO1xuXG4gICAgICAgICAgY2FzZSAnYml0c3RyaW5nJzpcbiAgICAgICAgICAgIGFyZ3MucHVzaChjcmVhdGVCaXRTdHJpbmcoYnNWYWx1ZUFycmF5UGFydCkpO1xuICAgICAgICAgICAgYnJlYWs7XG5cbiAgICAgICAgICBjYXNlICdiaW5hcnknOlxuICAgICAgICAgICAgYXJncy5wdXNoKFN0cmluZy5mcm9tQ2hhckNvZGUuYXBwbHkobnVsbCwgbmV3IFVpbnQ4QXJyYXkoYnNWYWx1ZUFycmF5UGFydCkpKTtcbiAgICAgICAgICAgIGJyZWFrO1xuXG4gICAgICAgICAgY2FzZSAndXRmOCc6XG4gICAgICAgICAgICBhcmdzLnB1c2goU3RyaW5nLmZyb21DaGFyQ29kZS5hcHBseShudWxsLCBuZXcgVWludDhBcnJheShic1ZhbHVlQXJyYXlQYXJ0KSkpO1xuICAgICAgICAgICAgYnJlYWs7XG5cbiAgICAgICAgICBjYXNlICd1dGYxNic6XG4gICAgICAgICAgICBhcmdzLnB1c2goU3RyaW5nLmZyb21DaGFyQ29kZS5hcHBseShudWxsLCBuZXcgVWludDE2QXJyYXkoYnNWYWx1ZUFycmF5UGFydCkpKTtcbiAgICAgICAgICAgIGJyZWFrO1xuXG4gICAgICAgICAgY2FzZSAndXRmMzInOlxuICAgICAgICAgICAgYXJncy5wdXNoKFN0cmluZy5mcm9tQ2hhckNvZGUuYXBwbHkobnVsbCwgbmV3IFVpbnQzMkFycmF5KGJzVmFsdWVBcnJheVBhcnQpKSk7XG4gICAgICAgICAgICBicmVhaztcblxuICAgICAgICAgIGRlZmF1bHQ6XG4gICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgIH1cbiAgICAgIH0gZWxzZSBpZiAoIWFycmF5c0VxdWFsKGJzVmFsdWVBcnJheVBhcnQsIHBhdHRlcm5CaXRTdHJpbmdBcnJheVBhcnQpKSB7XG4gICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgIH1cblxuICAgICAgYmVnaW5uaW5nSW5kZXggPSBiZWdpbm5pbmdJbmRleCArIHNpemU7XG4gICAgfVxuXG4gICAgcmV0dXJuIHRydWU7XG4gIH07XG59XG5cbmZ1bmN0aW9uIGdldFNpemUodW5pdCwgc2l6ZSkge1xuICByZXR1cm4gdW5pdCAqIHNpemUgLyA4O1xufVxuXG5mdW5jdGlvbiBhcnJheXNFcXVhbChhLCBiKSB7XG4gIGlmIChhID09PSBiKSByZXR1cm4gdHJ1ZTtcbiAgaWYgKGEgPT0gbnVsbCB8fCBiID09IG51bGwpIHJldHVybiBmYWxzZTtcbiAgaWYgKGEubGVuZ3RoICE9IGIubGVuZ3RoKSByZXR1cm4gZmFsc2U7XG5cbiAgZm9yICh2YXIgaSA9IDA7IGkgPCBhLmxlbmd0aDsgKytpKSB7XG4gICAgaWYgKGFbaV0gIT09IGJbaV0pIHJldHVybiBmYWxzZTtcbiAgfVxuXG4gIHJldHVybiB0cnVlO1xufVxuXG5mdW5jdGlvbiBmaWxsQXJyYXkoYXJyLCBudW0pIHtcbiAgZm9yIChsZXQgaSA9IDA7IGkgPCBudW07IGkrKykge1xuICAgIGFyci5wdXNoKDApO1xuICB9XG59XG5cbmZ1bmN0aW9uIGNyZWF0ZUJpdFN0cmluZyhhcnIpIHtcbiAgbGV0IGludGVnZXJQYXJ0cyA9IGFyci5tYXAoZWxlbSA9PiBCaXRTdHJpbmcuaW50ZWdlcihlbGVtKSk7XG4gIHJldHVybiBuZXcgQml0U3RyaW5nKC4uLmludGVnZXJQYXJ0cyk7XG59XG5cbmZ1bmN0aW9uIHJlc29sdmVOb01hdGNoKCkge1xuICByZXR1cm4gZnVuY3Rpb24gKCkge1xuICAgIHJldHVybiBmYWxzZTtcbiAgfTtcbn1cblxuZXhwb3J0IGRlZmF1bHQge1xuICByZXNvbHZlQm91bmQsXG4gIHJlc29sdmVXaWxkY2FyZCxcbiAgcmVzb2x2ZVZhcmlhYmxlLFxuICByZXNvbHZlSGVhZFRhaWwsXG4gIHJlc29sdmVDYXB0dXJlLFxuICByZXNvbHZlU3RhcnRzV2l0aCxcbiAgcmVzb2x2ZVR5cGUsXG4gIHJlc29sdmVBcnJheSxcbiAgcmVzb2x2ZU9iamVjdCxcbiAgcmVzb2x2ZU5vTWF0Y2gsXG4gIHJlc29sdmVTeW1ib2wsXG4gIHJlc29sdmVTdHJpbmcsXG4gIHJlc29sdmVOdW1iZXIsXG4gIHJlc29sdmVCb29sZWFuLFxuICByZXNvbHZlRnVuY3Rpb24sXG4gIHJlc29sdmVOdWxsLFxuICByZXNvbHZlQml0U3RyaW5nXG59O1xuLy8jIHNvdXJjZU1hcHBpbmdVUkw9ZGF0YTphcHBsaWNhdGlvbi9qc29uO2Jhc2U2NCxleUoyWlhKemFXOXVJam96TENKemIzVnlZMlZ6SWpwYklteHBZaTlqYjNKbEwzQmhkSFJsY201ekwzSmxjMjlzZG1WeWN5NXFjeUpkTENKdVlXMWxjeUk2VzEwc0ltMWhjSEJwYm1keklqb2lPenRCUVVWQkxFOUJRVThzVFVGQlVDeE5RVUZ0UWl4VlFVRnVRanRCUVVOQkxFOUJRVThzUzBGQlN5eExRVUZNTEUxQlFXZENMRk5CUVhaQ08wRkJRMEVzVTBGQlV5eFZRVUZVTEZGQlFUSkNMRk5CUVROQ08wRkJRMEVzVDBGQlR5eFRRVUZRTEUxQlFYTkNMR1ZCUVhSQ096dEJRVVZCTEZOQlFWTXNZVUZCVkN4RFFVRjFRaXhQUVVGMlFpeEZRVUVyUXp0QlFVTTNReXhUUVVGUExGVkJRVk1zUzBGQlZDeEZRVUU0UWp0QlFVTnVReXhYUVVGUExFOUJRVThzVTBGQlVDeERRVUZwUWl4TFFVRnFRaXhMUVVFeVFpeFZRVUZWTEU5QlFWWXNRMEZFUXp0SFFVRTVRaXhEUVVSelF6dERRVUV2UXpzN1FVRk5RU3hUUVVGVExHRkJRVlFzUTBGQmRVSXNUMEZCZGtJc1JVRkJLME03UVVGRE4wTXNVMEZCVHl4VlFVRlRMRXRCUVZRc1JVRkJPRUk3UVVGRGJrTXNWMEZCVHl4UFFVRlBMRk5CUVZBc1EwRkJhVUlzUzBGQmFrSXNTMEZCTWtJc1ZVRkJWU3hQUVVGV0xFTkJSRU03UjBGQk9VSXNRMEZFYzBNN1EwRkJMME03TzBGQlRVRXNVMEZCVXl4aFFVRlVMRU5CUVhWQ0xFOUJRWFpDTEVWQlFTdERPMEZCUXpkRExGTkJRVThzVlVGQlV5eExRVUZVTEVWQlFUaENPMEZCUTI1RExGZEJRVThzVDBGQlR5eFRRVUZRTEVOQlFXbENMRXRCUVdwQ0xFdEJRVEpDTEZWQlFWVXNUMEZCVml4RFFVUkRPMGRCUVRsQ0xFTkJSSE5ETzBOQlFTOURPenRCUVUxQkxGTkJRVk1zWTBGQlZDeERRVUYzUWl4UFFVRjRRaXhGUVVGblJEdEJRVU01UXl4VFFVRlBMRlZCUVZNc1MwRkJWQ3hGUVVFNFFqdEJRVU51UXl4WFFVRlBMRTlCUVU4c1ZVRkJVQ3hEUVVGclFpeExRVUZzUWl4TFFVRTBRaXhWUVVGVkxFOUJRVllzUTBGRVFUdEhRVUU1UWl4RFFVUjFRenREUVVGb1JEczdRVUZOUVN4VFFVRlRMR1ZCUVZRc1EwRkJlVUlzVDBGQmVrSXNSVUZCYVVRN1FVRkRMME1zVTBGQlR5eFZRVUZUTEV0QlFWUXNSVUZCT0VJN1FVRkRia01zVjBGQlR5eFBRVUZQTEZkQlFWQXNRMEZCYlVJc1MwRkJia0lzUzBGQk5rSXNWVUZCVlN4UFFVRldMRU5CUkVRN1IwRkJPVUlzUTBGRWQwTTdRMEZCYWtRN08wRkJUVUVzVTBGQlV5eFhRVUZVTEVOQlFYRkNMRTlCUVhKQ0xFVkJRVFpETzBGQlF6TkRMRk5CUVU4c1ZVRkJVeXhMUVVGVUxFVkJRVGhDTzBGQlEyNURMRmRCUVU4c1QwRkJUeXhQUVVGUUxFTkJRV1VzUzBGQlppeERRVUZRTEVOQlJHMURPMGRCUVRsQ0xFTkJSRzlETzBOQlFUZERPenRCUVUxQkxGTkJRVk1zV1VGQlZDeERRVUZ6UWl4UFFVRjBRaXhGUVVGelJEdEJRVU53UkN4VFFVRlBMRlZCUVZNc1MwRkJWQ3hGUVVGeFFpeEpRVUZ5UWl4RlFVRm5SRHRCUVVOeVJDeFJRVUZITEU5QlFVOHNTMEZCVUN4TFFVRnBRaXhQUVVGUExGRkJRVkVzUzBGQlVpeEpRVUZwUWl4VlFVRlZMRkZCUVZFc1MwRkJVaXhGUVVGak8wRkJRMnhGTEZkQlFVc3NTVUZCVEN4RFFVRlZMRXRCUVZZc1JVRkVhMFU3UVVGRmJFVXNZVUZCVHl4SlFVRlFMRU5CUm10Rk8wdEJRWEJGT3p0QlFVdEJMRmRCUVU4c1MwRkJVQ3hEUVU1eFJEdEhRVUZvUkN4RFFVUTJRenREUVVGMFJEczdRVUZYUVN4VFFVRlRMR1ZCUVZRc1IwRkJjVU03UVVGRGJrTXNVMEZCVHl4WlFVRnZRanRCUVVONlFpeFhRVUZQTEVsQlFWQXNRMEZFZVVJN1IwRkJjRUlzUTBGRU5FSTdRMEZCY2tNN08wRkJUVUVzVTBGQlV5eGxRVUZVTEVkQlFYRkRPMEZCUTI1RExGTkJRVThzVlVGQlV5eExRVUZVTEVWQlFYRkNMRWxCUVhKQ0xFVkJRV2RFTzBGQlEzSkVMRk5CUVVzc1NVRkJUQ3hEUVVGVkxFdEJRVllzUlVGRWNVUTdRVUZGY2tRc1YwRkJUeXhKUVVGUUxFTkJSbkZFTzBkQlFXaEVMRU5CUkRSQ08wTkJRWEpET3p0QlFVOUJMRk5CUVZNc1pVRkJWQ3hEUVVGNVFpeFBRVUY2UWl4RlFVRTBSRHRCUVVNeFJDeFJRVUZOTEdOQlFXTXNWMEZCVnl4UlFVRlJMRWxCUVZJc1EwRkJla0lzUTBGRWIwUTdRVUZGTVVRc1VVRkJUU3hqUVVGakxGZEJRVmNzVVVGQlVTeEpRVUZTTEVOQlFYcENMRU5CUm05RU96dEJRVWt4UkN4VFFVRlBMRlZCUVZNc1MwRkJWQ3hGUVVGeFFpeEpRVUZ5UWl4RlFVRm5SRHRCUVVOeVJDeFJRVUZITEVOQlFVTXNUMEZCVHl4UlFVRlFMRU5CUVdkQ0xFdEJRV2hDTEVOQlFVUXNTVUZCTWtJc1RVRkJUU3hOUVVGT0xFZEJRV1VzUTBGQlppeEZRVUZwUWp0QlFVTTNReXhoUVVGUExFdEJRVkFzUTBGRU5rTTdTMEZCTDBNN08wRkJTVUVzVlVGQlRTeFBRVUZQTEUxQlFVMHNRMEZCVGl4RFFVRlFMRU5CVEN0RE8wRkJUWEpFTEZWQlFVMHNUMEZCVHl4TlFVRk5MRXRCUVU0c1EwRkJXU3hEUVVGYUxFTkJRVkFzUTBGT0swTTdPMEZCVVhKRUxGRkJRVWNzV1VGQldTeEpRVUZhTEVWQlFXdENMRWxCUVd4Q0xFdEJRVEpDTEZsQlFWa3NTVUZCV2l4RlFVRnJRaXhKUVVGc1FpeERRVUV6UWl4RlFVRnRSRHRCUVVOd1JDeGhRVUZQTEVsQlFWQXNRMEZFYjBRN1MwRkJkRVE3UjBGU1N5eERRVXB0UkR0RFFVRTFSRHM3UVVGclFrRXNVMEZCVXl4alFVRlVMRU5CUVhkQ0xFOUJRWGhDTEVWQlFUQkVPMEZCUTNoRUxGRkJRVTBzVlVGQlZTeFhRVUZYTEZGQlFWRXNTMEZCVWl4RFFVRnlRaXhEUVVSclJEczdRVUZIZUVRc1UwRkJUeXhWUVVGVExFdEJRVlFzUlVGQmNVSXNTVUZCY2tJc1JVRkJaMFE3UVVGRGNrUXNVVUZCUnl4UlFVRlJMRXRCUVZJc1JVRkJaU3hKUVVGbUxFTkJRVWdzUlVGQmQwSTdRVUZEZEVJc1YwRkJTeXhKUVVGTUxFTkJRVlVzUzBGQlZpeEZRVVJ6UWp0QlFVVjBRaXhoUVVGUExFbEJRVkFzUTBGR2MwSTdTMEZCZUVJN08wRkJTMEVzVjBGQlR5eExRVUZRTEVOQlRuRkVPMGRCUVdoRUxFTkJTR2xFTzBOQlFURkVPenRCUVdGQkxGTkJRVk1zYVVKQlFWUXNRMEZCTWtJc1QwRkJNMElzUlVGQlowVTdRVUZET1VRc1VVRkJUU3hUUVVGVExGRkJRVkVzVFVGQlVpeERRVVFyUXpzN1FVRkhPVVFzVTBGQlR5eFZRVUZUTEV0QlFWUXNSVUZCY1VJc1NVRkJja0lzUlVGQlowUTdRVUZEY2tRc1VVRkJSeXhQUVVGUExGTkJRVkFzUTBGQmFVSXNTMEZCYWtJc1MwRkJNa0lzVFVGQlRTeFZRVUZPTEVOQlFXbENMRTFCUVdwQ0xFTkJRVE5DTEVWQlFXOUVPMEZCUTNKRUxGZEJRVXNzU1VGQlRDeERRVUZWTEUxQlFVMHNVMEZCVGl4RFFVRm5RaXhQUVVGUExFMUJRVkFzUTBGQk1VSXNSVUZFY1VRN1FVRkZja1FzWVVGQlR5eEpRVUZRTEVOQlJuRkVPMHRCUVhaRU96dEJRVXRCTEZkQlFVOHNTMEZCVUN4RFFVNXhSRHRIUVVGb1JDeERRVWgxUkR0RFFVRm9SVHM3UVVGaFFTeFRRVUZUTEZkQlFWUXNRMEZCY1VJc1QwRkJja0lzUlVGQmIwUTdRVUZEYkVRc1UwRkJUeXhWUVVGVExFdEJRVlFzUlVGQmNVSXNTVUZCY2tJc1JVRkJaMFE3UVVGRGNrUXNVVUZCUnl4cFFrRkJhVUlzVVVGQlVTeEpRVUZTTEVWQlFXRTdRVUZETDBJc1dVRkJUU3hWUVVGVkxGZEJRVmNzVVVGQlVTeFZRVUZTTEVOQlFYSkNMRU5CUkhsQ08wRkJSUzlDTEdGQlFVOHNVVUZCVVN4TFFVRlNMRVZCUVdVc1NVRkJaaXhMUVVGM1FpeExRVUZMTEVsQlFVd3NRMEZCVlN4TFFVRldMRWxCUVcxQ0xFTkJRVzVDTEVOQlJrRTdTMEZCYWtNN08wRkJTMEVzVjBGQlR5eExRVUZRTEVOQlRuRkVPMGRCUVdoRUxFTkJSREpETzBOQlFYQkVPenRCUVZkQkxGTkJRVk1zV1VGQlZDeERRVUZ6UWl4UFFVRjBRaXhGUVVGeFJEdEJRVU51UkN4UlFVRk5MRlZCUVZVc1VVRkJVU3hIUVVGU0xFTkJRVmtzUzBGQlN5eFhRVUZYTEVOQlFWZ3NRMEZCVEN4RFFVRjBRaXhEUVVRMlF6czdRVUZIYmtRc1UwRkJUeXhWUVVGVExFdEJRVlFzUlVGQmNVSXNTVUZCY2tJc1JVRkJaMFE3UVVGRGNrUXNVVUZCUnl4RFFVRkRMRTlCUVU4c1VVRkJVQ3hEUVVGblFpeExRVUZvUWl4RFFVRkVMRWxCUVRKQ0xFMUJRVTBzVFVGQlRpeEpRVUZuUWl4UlFVRlJMRTFCUVZJc1JVRkJaVHRCUVVNelJDeGhRVUZQTEV0QlFWQXNRMEZFTWtRN1MwRkJOMFE3TzBGQlNVRXNWMEZCVHl4TlFVRk5MRXRCUVU0c1EwRkJXU3hWUVVGVExFTkJRVlFzUlVGQldTeERRVUZhTEVWQlFXVTdRVUZEYUVNc1lVRkJUeXhSUVVGUkxFTkJRVklzUlVGQlZ5eE5RVUZOTEVOQlFVNHNRMEZCV0N4RlFVRnhRaXhKUVVGeVFpeERRVUZRTEVOQlJHZERPMHRCUVdZc1EwRkJia0lzUTBGTWNVUTdSMEZCYUVRc1EwRklORU03UTBGQmNrUTdPMEZCWTBFc1UwRkJVeXhoUVVGVUxFTkJRWFZDTEU5QlFYWkNMRVZCUVd0RU8wRkJRMmhFTEUxQlFVa3NWVUZCVlN4RlFVRldMRU5CUkRSRE96dEJRVWRvUkN4UFFVRkpMRWxCUVVrc1IwRkJTaXhKUVVGWExFOUJRVThzU1VGQlVDeERRVUZaTEU5QlFWb3NSVUZCY1VJc1RVRkJja0lzUTBGQk5FSXNUMEZCVHl4eFFrRkJVQ3hEUVVFMlFpeFBRVUUzUWl4RFFVRTFRaXhEUVVGbUxFVkJRV3RHTzBGQlEyaEdMRmxCUVZFc1IwRkJVaXhKUVVGbExGZEJRVmNzVVVGQlVTeEhRVUZTTEVOQlFWZ3NRMEZCWml4RFFVUm5SanRIUVVGc1JqczdRVUZKUVN4VFFVRlBMRlZCUVZNc1MwRkJWQ3hGUVVGeFFpeEpRVUZ5UWl4RlFVRm5SRHRCUVVOeVJDeFJRVUZITEVOQlFVTXNUMEZCVHl4VFFVRlFMRU5CUVdsQ0xFdEJRV3BDTEVOQlFVUXNTVUZCTkVJc1VVRkJVU3hOUVVGU0xFZEJRV2xDTEUxQlFVMHNUVUZCVGl4RlFVRmhPMEZCUXpORUxHRkJRVThzUzBGQlVDeERRVVF5UkR0TFFVRTNSRHM3UVVGSlFTeFRRVUZKTEVsQlFVa3NSMEZCU2l4SlFVRlhMRTlCUVU4c1NVRkJVQ3hEUVVGWkxFOUJRVm9zUlVGQmNVSXNUVUZCY2tJc1EwRkJORUlzVDBGQlR5eHhRa0ZCVUN4RFFVRTJRaXhQUVVFM1FpeERRVUUxUWl4RFFVRm1MRVZCUVd0R08wRkJRMmhHTEZWQlFVY3NSVUZCUlN4UFFVRlBMRXRCUVZBc1EwRkJSaXhKUVVGdFFpeERRVUZETEZGQlFWRXNSMEZCVWl4RlFVRmhMRTFCUVUwc1IwRkJUaXhEUVVGaUxFVkJRWGxDTEVsQlFYcENMRU5CUVVRc1JVRkJhVU03UVVGRGNrUXNaVUZCVHl4TFFVRlFMRU5CUkhGRU8wOUJRWFpFTzB0QlJFWTdPMEZCVFVFc1YwRkJUeXhKUVVGUUxFTkJXSEZFTzBkQlFXaEVMRU5CVUhsRE8wTkJRV3hFT3p0QlFYTkNRU3hUUVVGVExHZENRVUZVTEVOQlFUQkNMRTlCUVRGQ0xFVkJRVzFGTzBGQlEycEZMRTFCUVVrc2JVSkJRVzFDTEVWQlFXNUNMRU5CUkRaRU96dEJRVWRxUlN4UFFVRkpMRWxCUVVrc2EwSkJRVW9zU1VGQk1FSXNVVUZCVVN4TlFVRlNMRVZCUVdVN1FVRkRNME1zVVVGQlJ5eFBRVUZQTEZkQlFWQXNRMEZCYlVJc2JVSkJRVzFDTEV0QlFXNUNMRU5CUVhSQ0xFVkJRV2RFTzBGQlF6bERMRlZCUVVrc1QwRkJUeXhSUVVGUkxHMUNRVUZ0UWl4SlFVRnVRaXhGUVVGNVFpeHRRa0ZCYlVJc1NVRkJia0lzUTBGQmVFTXNRMEZFTUVNN1FVRkZPVU1zWjBKQlFWVXNaMEpCUVZZc1JVRkJORUlzU1VGQk5VSXNSVUZHT0VNN1MwRkJhRVFzVFVGSFN6dEJRVU5JTEhsQ1FVRnRRaXhwUWtGQmFVSXNUVUZCYWtJc1EwRkJkMElzU1VGQlNTeFRRVUZLTEVOQlFXTXNhMEpCUVdRc1JVRkJhME1zUzBGQmJFTXNRMEZCTTBNc1EwRkVSenRMUVVoTU8wZEJSRVk3TzBGQlUwRXNUVUZCU1N4blFrRkJaMElzVVVGQlVTeE5RVUZTTEVOQldqWkRPenRCUVdOcVJTeFRRVUZQTEZWQlFWTXNTMEZCVkN4RlFVRnhRaXhKUVVGeVFpeEZRVUZuUkR0QlFVTnlSQ3hSUVVGSkxGVkJRVlVzU1VGQlZpeERRVVJwUkRzN1FVRkhja1FzVVVGQlJ5eERRVUZETEU5QlFVOHNVMEZCVUN4RFFVRnBRaXhMUVVGcVFpeERRVUZFTEVsQlFUUkNMRVZCUVVVc2FVSkJRV2xDTEZOQlFXcENMRU5CUVVZc1JVRkJLMEk3UVVGRE5VUXNZVUZCVHl4TFFVRlFMRU5CUkRSRU8wdEJRVGxFT3p0QlFVbEJMRkZCUVVjc1QwRkJUeXhUUVVGUUxFTkJRV2xDTEV0QlFXcENMRU5CUVVnc1JVRkJNa0k3UVVGRGVrSXNaMEpCUVZVc1NVRkJTU3hUUVVGS0xFTkJRV01zVlVGQlZTeE5RVUZXTEVOQlFXbENMRXRCUVdwQ0xFTkJRV1FzUTBGQlZpeERRVVI1UWp0TFFVRXpRaXhOUVVWTE8wRkJRMGdzWjBKQlFWVXNTMEZCVml4RFFVUkhPMHRCUmt3N08wRkJUVUVzVVVGQlNTeHBRa0ZCYVVJc1EwRkJha0lzUTBGaWFVUTdPMEZCWlhKRUxGTkJRVWtzU1VGQlNTeEpRVUZKTEVOQlFVb3NSVUZCVHl4SlFVRkpMR05CUVdNc1RVRkJaQ3hGUVVGelFpeEhRVUY2UXl4RlFVRTJRenRCUVVNelF5eFZRVUZKTEhGQ1FVRnhRaXhqUVVGakxFTkJRV1FzUTBGQmNrSXNRMEZFZFVNN08wRkJSek5ETEZWQlFVY3NUMEZCVHl4WFFVRlFMRU5CUVcxQ0xHMUNRVUZ0UWl4TFFVRnVRaXhEUVVGdVFpeEpRVU5CTEcxQ1FVRnRRaXhKUVVGdVFpeEpRVUV5UWl4UlFVRXpRaXhKUVVOQkxHMUNRVUZ0UWl4SlFVRnVRaXhMUVVFMFFpeFRRVUUxUWl4SlFVTkJMRWxCUVVrc1kwRkJZeXhOUVVGa0xFZEJRWFZDTEVOQlFYWkNMRVZCUVhsQ08wRkJRemxDTEdOQlFVMHNTVUZCU1N4TFFVRktMRU5CUVZVc05FVkJRVllzUTBGQlRpeERRVVE0UWp0UFFVaG9RenM3UVVGUFFTeFZRVUZKTEU5QlFVOHNRMEZCVUN4RFFWWjFRenRCUVZjelF5eFZRVUZKTEcxQ1FVRnRRaXhGUVVGdVFpeERRVmgxUXp0QlFWa3pReXhWUVVGSkxEUkNRVUUwUWl4RlFVRTFRaXhEUVZwMVF6dEJRV0V6UXl4aFFVRlBMRkZCUVZFc2JVSkJRVzFDTEVsQlFXNUNMRVZCUVhsQ0xHMUNRVUZ0UWl4SlFVRnVRaXhEUVVGNFF5eERRV0l5UXpzN1FVRmxNME1zVlVGQlJ5eE5RVUZOTEdOQlFXTXNUVUZCWkN4SFFVRjFRaXhEUVVGMlFpeEZRVUY1UWp0QlFVTm9ReXd5UWtGQmJVSXNVVUZCVVN4TFFVRlNMRU5CUVdNc1MwRkJaQ3hEUVVGdlFpeGpRVUZ3UWl4RFFVRnVRaXhEUVVSblF6dEJRVVZvUXl4dlEwRkJORUlzYVVKQlFXbENMRXRCUVdwQ0xFTkJRWFZDTEdOQlFYWkNMRU5CUVRWQ0xFTkJSbWRETzA5QlFXeERMRTFCUjA4N1FVRkRUQ3d5UWtGQmJVSXNVVUZCVVN4TFFVRlNMRU5CUVdNc1MwRkJaQ3hEUVVGdlFpeGpRVUZ3UWl4RlFVRnZReXhwUWtGQmFVSXNTVUZCYWtJc1EwRkJka1FzUTBGRVN6dEJRVVZNTEc5RFFVRTBRaXhwUWtGQmFVSXNTMEZCYWtJc1EwRkJkVUlzWTBGQmRrSXNSVUZCZFVNc2FVSkJRV2xDTEVsQlFXcENMRU5CUVc1RkxFTkJSa3M3VDBGSVVEczdRVUZSUVN4VlFVRkhMRTlCUVU4c1YwRkJVQ3hEUVVGdFFpeHRRa0ZCYlVJc1MwRkJia0lzUTBGQmRFSXNSVUZCWjBRN1FVRkRPVU1zWjBKQlFVOHNiVUpCUVcxQ0xFbEJRVzVDTzBGQlExQXNaVUZCU3l4VFFVRk1PMEZCUTBVc1owSkJRVWNzYlVKQlFXMUNMRlZCUVc1Q0xFbEJRV2xETEcxQ1FVRnRRaXhWUVVGdVFpeERRVUU0UWl4UFFVRTVRaXhEUVVGelF5eFJRVUYwUXl4TFFVRnRSQ3hEUVVGRExFTkJRVVFzUlVGQlJ6dEJRVU40Uml4dFFrRkJTeXhKUVVGTUxFTkJRVlVzU1VGQlNTeFRRVUZLTEVOQlFXTXNRMEZCUXl4cFFrRkJhVUlzUTBGQmFrSXNRMEZCUkN4RFFVRmtMRVZCUVhGRExFTkJRWEpETEVOQlFWWXNSVUZFZDBZN1lVRkJNVVlzVFVGRlR6dEJRVU5NTEcxQ1FVRkxMRWxCUVV3c1EwRkJWU3hKUVVGSkxGVkJRVW9zUTBGQlpTeERRVUZETEdsQ1FVRnBRaXhEUVVGcVFpeERRVUZFTEVOQlFXWXNSVUZCYzBNc1EwRkJkRU1zUTBGQlZpeEZRVVJMTzJGQlJsQTdRVUZMUVN4clFrRk9SanM3UVVGRVFTeGxRVk5MTEU5QlFVdzdRVUZEUlN4blFrRkJSeXhUUVVGVExFVkJRVlFzUlVGQldUdEJRVU5pTEcxQ1FVRkxMRWxCUVV3c1EwRkJWU3hoUVVGaExFbEJRV0lzUTBGQmEwSXNaMEpCUVd4Q0xFVkJRVzlETEVOQlFYQkRMRU5CUVZZc1JVRkVZVHRoUVVGbUxFMUJSVThzU1VGQlJ5eFRRVUZUTEVWQlFWUXNSVUZCV1R0QlFVTndRaXh0UWtGQlN5eEpRVUZNTEVOQlFWVXNZVUZCWVN4SlFVRmlMRU5CUVd0Q0xHZENRVUZzUWl4RlFVRnZReXhEUVVGd1F5eERRVUZXTEVWQlJHOUNPMkZCUVdZc1RVRkZSanRCUVVOSUxIRkNRVUZQTEV0QlFWQXNRMEZFUnp0aFFVWkZPMEZCUzFBc2EwSkJVa1k3TzBGQlZFRXNaVUZ0UWtzc1YwRkJURHRCUVVORkxHbENRVUZMTEVsQlFVd3NRMEZCVlN4blFrRkJaMElzWjBKQlFXaENMRU5CUVZZc1JVRkVSanRCUVVWRkxHdENRVVpHT3p0QlFXNUNRU3hsUVhWQ1N5eFJRVUZNTzBGQlEwVXNhVUpCUVVzc1NVRkJUQ3hEUVVGVkxFOUJRVThzV1VGQlVDeERRVUZ2UWl4TFFVRndRaXhEUVVFd1FpeEpRVUV4UWl4RlFVRm5ReXhKUVVGSkxGVkJRVW9zUTBGQlpTeG5Ra0ZCWml4RFFVRm9ReXhEUVVGV0xFVkJSRVk3UVVGRlJTeHJRa0ZHUmpzN1FVRjJRa0VzWlVFeVFrc3NUVUZCVER0QlFVTkZMR2xDUVVGTExFbEJRVXdzUTBGQlZTeFBRVUZQTEZsQlFWQXNRMEZCYjBJc1MwRkJjRUlzUTBGQk1FSXNTVUZCTVVJc1JVRkJaME1zU1VGQlNTeFZRVUZLTEVOQlFXVXNaMEpCUVdZc1EwRkJhRU1zUTBGQlZpeEZRVVJHTzBGQlJVVXNhMEpCUmtZN08wRkJNMEpCTEdWQkswSkxMRTlCUVV3N1FVRkRSU3hwUWtGQlN5eEpRVUZNTEVOQlFWVXNUMEZCVHl4WlFVRlFMRU5CUVc5Q0xFdEJRWEJDTEVOQlFUQkNMRWxCUVRGQ0xFVkJRV2RETEVsQlFVa3NWMEZCU2l4RFFVRm5RaXhuUWtGQmFFSXNRMEZCYUVNc1EwRkJWaXhGUVVSR08wRkJSVVVzYTBKQlJrWTdPMEZCTDBKQkxHVkJiVU5MTEU5QlFVdzdRVUZEUlN4cFFrRkJTeXhKUVVGTUxFTkJRVlVzVDBGQlR5eFpRVUZRTEVOQlFXOUNMRXRCUVhCQ0xFTkJRVEJDTEVsQlFURkNMRVZCUVdkRExFbEJRVWtzVjBGQlNpeERRVUZuUWl4blFrRkJhRUlzUTBGQmFFTXNRMEZCVml4RlFVUkdPMEZCUlVVc2EwSkJSa1k3TzBGQmJrTkJPMEZCZDBORkxHMUNRVUZQTEV0QlFWQXNRMEZFUmp0QlFYWkRRU3hUUVVRNFF6dFBRVUZvUkN4TlFUSkRUU3hKUVVGSExFTkJRVU1zV1VGQldTeG5Ra0ZCV2l4RlFVRTRRaXg1UWtGQk9VSXNRMEZCUkN4RlFVRXlSRHRCUVVOc1JTeGxRVUZQTEV0QlFWQXNRMEZFYTBVN1QwRkJPVVE3TzBGQlNVNHNkVUpCUVdsQ0xHbENRVUZwUWl4SlFVRnFRaXhEUVhSRk1FSTdTMEZCTjBNN08wRkJlVVZCTEZkQlFVOHNTVUZCVUN4RFFYaEdjVVE3UjBGQmFFUXNRMEZrTUVRN1EwRkJia1U3TzBGQk1rZEJMRk5CUVZNc1QwRkJWQ3hEUVVGcFFpeEpRVUZxUWl4RlFVRjFRaXhKUVVGMlFpeEZRVUUwUWp0QlFVTXhRaXhUUVVGUExFbEJRVU1zUjBGQlR5eEpRVUZRTEVkQlFXVXNRMEZCYUVJc1EwRkViVUk3UTBGQk5VSTdPMEZCU1VFc1UwRkJVeXhYUVVGVUxFTkJRWEZDTEVOQlFYSkNMRVZCUVhkQ0xFTkJRWGhDTEVWQlFUSkNPMEZCUTNwQ0xFMUJRVWtzVFVGQlRTeERRVUZPTEVWQlFWTXNUMEZCVHl4SlFVRlFMRU5CUVdJN1FVRkRRU3hOUVVGSkxFdEJRVXNzU1VGQlRDeEpRVUZoTEV0QlFVc3NTVUZCVEN4RlFVRlhMRTlCUVU4c1MwRkJVQ3hEUVVFMVFqdEJRVU5CTEUxQlFVa3NSVUZCUlN4TlFVRkdMRWxCUVZrc1JVRkJSU3hOUVVGR0xFVkJRVlVzVDBGQlR5eExRVUZRTEVOQlFURkNPenRCUVVWQkxFOUJRVXNzU1VGQlNTeEpRVUZKTEVOQlFVb3NSVUZCVHl4SlFVRkpMRVZCUVVVc1RVRkJSaXhGUVVGVkxFVkJRVVVzUTBGQlJpeEZRVUZMTzBGQlEycERMRkZCUVVrc1JVRkJSU3hEUVVGR0xFMUJRVk1zUlVGQlJTeERRVUZHTEVOQlFWUXNSVUZCWlN4UFFVRlBMRXRCUVZBc1EwRkJia0k3UjBGRVJqczdRVUZKUVN4VFFVRlBMRWxCUVZBc1EwRlVlVUk3UTBGQk0wSTdPMEZCV1VFc1UwRkJVeXhUUVVGVUxFTkJRVzFDTEVkQlFXNUNMRVZCUVhkQ0xFZEJRWGhDTEVWQlFUUkNPMEZCUXpGQ0xFOUJRVWtzU1VGQlNTeEpRVUZKTEVOQlFVb3NSVUZCVHl4SlFVRkpMRWRCUVVvc1JVRkJVeXhIUVVGNFFpeEZRVUUwUWp0QlFVTXhRaXhSUVVGSkxFbEJRVW9zUTBGQlV5eERRVUZVTEVWQlJEQkNPMGRCUVRWQ08wTkJSRVk3TzBGQlRVRXNVMEZCVXl4bFFVRlVMRU5CUVhsQ0xFZEJRWHBDTEVWQlFUWkNPMEZCUXpOQ0xFMUJRVWtzWlVGQlpTeEpRVUZKTEVkQlFVb3NRMEZCVVN4UlFVRlZMRlZCUVZVc1QwRkJWaXhEUVVGclFpeEpRVUZzUWl4RFFVRldMRU5CUVhaQ0xFTkJSSFZDTzBGQlJUTkNMRk5CUVU4c1NVRkJTU3hUUVVGS0xFTkJRV01zUjBGQlJ5eFpRVUZJTEVOQlFYSkNMRU5CUmpKQ08wTkJRVGRDT3p0QlFVdEJMRk5CUVZNc1kwRkJWQ3hIUVVGdlF6dEJRVU5zUXl4VFFVRlBMRmxCUVc5Q08wRkJRM3BDTEZkQlFVOHNTMEZCVUN4RFFVUjVRanRIUVVGd1FpeERRVVF5UWp0RFFVRndRenM3UVVGTlFTeGxRVUZsTzBGQlEySXNZMEZFWVR0QlFVVmlMR2xDUVVaaE8wRkJSMklzYVVKQlNHRTdRVUZKWWl4cFFrRktZVHRCUVV0aUxHZENRVXhoTzBGQlRXSXNiVUpCVG1FN1FVRlBZaXhoUVZCaE8wRkJVV0lzWTBGU1lUdEJRVk5pTEdWQlZHRTdRVUZWWWl4blFrRldZVHRCUVZkaUxHVkJXR0U3UVVGWllpeGxRVnBoTzBGQllXSXNaVUZpWVR0QlFXTmlMR2RDUVdSaE8wRkJaV0lzYVVKQlptRTdRVUZuUW1Jc1lVRm9RbUU3UVVGcFFtSXNhMEpCYWtKaE8wTkJRV1lpTENKbWFXeGxJam9pYkdsaUwyTnZjbVV2Y0dGMGRHVnlibk12Y21WemIyeDJaWEp6TG1weklpd2ljMjkxY21ObGMwTnZiblJsYm5RaU9sc2lMeW9nUUdac2IzY2dLaTljYmx4dWFXMXdiM0owSUVOb1pXTnJjeUJtY205dElGd2lMaTlqYUdWamEzTmNJanRjYm1sdGNHOXlkQ0FxSUdGeklGUjVjR1Z6SUdaeWIyMGdYQ0l1TDNSNWNHVnpYQ0k3WEc1cGJYQnZjblFnZXlCaWRXbHNaRTFoZEdOb0lIMGdabkp2YlNCY0lpNHZiV0YwWTJoY0lqdGNibWx0Y0c5eWRDQkNhWFJUZEhKcGJtY2dabkp2YlNCY0lpNHVMMkpwZEY5emRISnBibWRjSWp0Y2JseHVablZ1WTNScGIyNGdjbVZ6YjJ4MlpWTjViV0p2YkNod1lYUjBaWEp1T2lCaGJua3BPaUJHZFc1amRHbHZiaUI3WEc0Z0lISmxkSFZ5YmlCbWRXNWpkR2x2YmloMllXeDFaVG9nWVc1NUtUb2dZbTl2YkdWaGJpQjdYRzRnSUNBZ2NtVjBkWEp1SUVOb1pXTnJjeTVwYzE5emVXMWliMndvZG1Gc2RXVXBJQ1ltSUhaaGJIVmxJRDA5UFNCd1lYUjBaWEp1TzF4dUlDQjlPMXh1ZlZ4dVhHNW1kVzVqZEdsdmJpQnlaWE52YkhabFUzUnlhVzVuS0hCaGRIUmxjbTQ2SUdGdWVTazZJRVoxYm1OMGFXOXVJSHRjYmlBZ2NtVjBkWEp1SUdaMWJtTjBhVzl1S0haaGJIVmxPaUJoYm5rcE9pQmliMjlzWldGdUlIdGNiaUFnSUNCeVpYUjFjbTRnUTJobFkydHpMbWx6WDNOMGNtbHVaeWgyWVd4MVpTa2dKaVlnZG1Gc2RXVWdQVDA5SUhCaGRIUmxjbTQ3WEc0Z0lIMDdYRzU5WEc1Y2JtWjFibU4wYVc5dUlISmxjMjlzZG1WT2RXMWlaWElvY0dGMGRHVnliam9nWVc1NUtUb2dSblZ1WTNScGIyNGdlMXh1SUNCeVpYUjFjbTRnWm5WdVkzUnBiMjRvZG1Gc2RXVTZJR0Z1ZVNrNklHSnZiMnhsWVc0Z2UxeHVJQ0FnSUhKbGRIVnliaUJEYUdWamEzTXVhWE5mYm5WdFltVnlLSFpoYkhWbEtTQW1KaUIyWVd4MVpTQTlQVDBnY0dGMGRHVnlianRjYmlBZ2ZUdGNibjFjYmx4dVpuVnVZM1JwYjI0Z2NtVnpiMngyWlVKdmIyeGxZVzRvY0dGMGRHVnliam9nWVc1NUtUb2dSblZ1WTNScGIyNGdlMXh1SUNCeVpYUjFjbTRnWm5WdVkzUnBiMjRvZG1Gc2RXVTZJR0Z1ZVNrNklHSnZiMnhsWVc0Z2UxeHVJQ0FnSUhKbGRIVnliaUJEYUdWamEzTXVhWE5mWW05dmJHVmhiaWgyWVd4MVpTa2dKaVlnZG1Gc2RXVWdQVDA5SUhCaGRIUmxjbTQ3WEc0Z0lIMDdYRzU5WEc1Y2JtWjFibU4wYVc5dUlISmxjMjlzZG1WR2RXNWpkR2x2Ymlod1lYUjBaWEp1T2lCaGJua3BPaUJHZFc1amRHbHZiaUI3WEc0Z0lISmxkSFZ5YmlCbWRXNWpkR2x2YmloMllXeDFaVG9nWVc1NUtUb2dZbTl2YkdWaGJpQjdYRzRnSUNBZ2NtVjBkWEp1SUVOb1pXTnJjeTVwYzE5bWRXNWpkR2x2YmloMllXeDFaU2tnSmlZZ2RtRnNkV1VnUFQwOUlIQmhkSFJsY200N1hHNGdJSDA3WEc1OVhHNWNibVoxYm1OMGFXOXVJSEpsYzI5c2RtVk9kV3hzS0hCaGRIUmxjbTQ2SUdGdWVTazZJRVoxYm1OMGFXOXVJSHRjYmlBZ2NtVjBkWEp1SUdaMWJtTjBhVzl1S0haaGJIVmxPaUJoYm5rcE9pQmliMjlzWldGdUlIdGNiaUFnSUNCeVpYUjFjbTRnUTJobFkydHpMbWx6WDI1MWJHd29kbUZzZFdVcE8xeHVJQ0I5TzF4dWZWeHVYRzVtZFc1amRHbHZiaUJ5WlhOdmJIWmxRbTkxYm1Rb2NHRjBkR1Z5YmpvZ1ZIbHdaWE11UW05MWJtUXBPaUJHZFc1amRHbHZiaUI3WEc0Z0lISmxkSFZ5YmlCbWRXNWpkR2x2YmloMllXeDFaVG9nWVc1NUxDQmhjbWR6T2lCQmNuSmhlVHhoYm5rK0tUb2dZbTl2YkdWaGJpQjdYRzRnSUNBZ2FXWW9kSGx3Wlc5bUlIWmhiSFZsSUQwOVBTQjBlWEJsYjJZZ2NHRjBkR1Z5Ymk1MllXeDFaU0FtSmlCMllXeDFaU0E5UFQwZ2NHRjBkR1Z5Ymk1MllXeDFaU2w3WEc0Z0lDQWdJQ0JoY21kekxuQjFjMmdvZG1Gc2RXVXBPMXh1SUNBZ0lDQWdjbVYwZFhKdUlIUnlkV1U3WEc0Z0lDQWdmVnh1WEc0Z0lDQWdjbVYwZFhKdUlHWmhiSE5sTzF4dUlDQjlPMXh1ZlZ4dVhHNW1kVzVqZEdsdmJpQnlaWE52YkhabFYybHNaR05oY21Rb0tUb2dSblZ1WTNScGIyNGdlMXh1SUNCeVpYUjFjbTRnWm5WdVkzUnBiMjRvS1RvZ1ltOXZiR1ZoYmlCN1hHNGdJQ0FnY21WMGRYSnVJSFJ5ZFdVN1hHNGdJSDA3WEc1OVhHNWNibVoxYm1OMGFXOXVJSEpsYzI5c2RtVldZWEpwWVdKc1pTZ3BPaUJHZFc1amRHbHZiaUI3WEc0Z0lISmxkSFZ5YmlCbWRXNWpkR2x2YmloMllXeDFaVG9nWVc1NUxDQmhjbWR6T2lCQmNuSmhlVHhoYm5rK0tUb2dZbTl2YkdWaGJpQjdYRzRnSUNBZ1lYSm5jeTV3ZFhOb0tIWmhiSFZsS1R0Y2JpQWdJQ0J5WlhSMWNtNGdkSEoxWlR0Y2JpQWdmVHRjYm4xY2JseHVablZ1WTNScGIyNGdjbVZ6YjJ4MlpVaGxZV1JVWVdsc0tIQmhkSFJsY200NklGUjVjR1Z6TGtobFlXUlVZV2xzS1RvZ1JuVnVZM1JwYjI0Z2UxeHVJQ0JqYjI1emRDQm9aV0ZrVFdGMFkyaGxjeUE5SUdKMWFXeGtUV0YwWTJnb2NHRjBkR1Z5Ymk1b1pXRmtLVHRjYmlBZ1kyOXVjM1FnZEdGcGJFMWhkR05vWlhNZ1BTQmlkV2xzWkUxaGRHTm9LSEJoZEhSbGNtNHVkR0ZwYkNrN1hHNWNiaUFnY21WMGRYSnVJR1oxYm1OMGFXOXVLSFpoYkhWbE9pQmhibmtzSUdGeVozTTZJRUZ5Y21GNVBHRnVlVDRwT2lCaWIyOXNaV0Z1SUh0Y2JpQWdJQ0JwWmlnaFEyaGxZMnR6TG1selgyRnljbUY1S0haaGJIVmxLU0I4ZkNCMllXeDFaUzVzWlc1bmRHZ2dQQ0F5S1h0Y2JpQWdJQ0FnSUhKbGRIVnliaUJtWVd4elpUdGNiaUFnSUNCOVhHNWNiaUFnSUNCamIyNXpkQ0JvWldGa0lEMGdkbUZzZFdWYk1GMDdYRzRnSUNBZ1kyOXVjM1FnZEdGcGJDQTlJSFpoYkhWbExuTnNhV05sS0RFcE8xeHVYRzRnSUNBZ2FXWW9hR1ZoWkUxaGRHTm9aWE1vYUdWaFpDd2dZWEpuY3lrZ0ppWWdkR0ZwYkUxaGRHTm9aWE1vZEdGcGJDd2dZWEpuY3lrcGUxeHVJQ0FnSUNBZ2NtVjBkWEp1SUhSeWRXVTdYRzRnSUNBZ2ZWeHVJQ0I5TzF4dWZWeHVYRzVtZFc1amRHbHZiaUJ5WlhOdmJIWmxRMkZ3ZEhWeVpTaHdZWFIwWlhKdU9pQlVlWEJsY3k1RFlYQjBkWEpsS1RvZ1JuVnVZM1JwYjI0Z2UxeHVJQ0JqYjI1emRDQnRZWFJqYUdWeklEMGdZblZwYkdSTllYUmphQ2h3WVhSMFpYSnVMblpoYkhWbEtUdGNibHh1SUNCeVpYUjFjbTRnWm5WdVkzUnBiMjRvZG1Gc2RXVTZJR0Z1ZVN3Z1lYSm5jem9nUVhKeVlYazhZVzU1UGlrNklHSnZiMnhsWVc0Z2UxeHVJQ0FnSUdsbUtHMWhkR05vWlhNb2RtRnNkV1VzSUdGeVozTXBLWHRjYmlBZ0lDQWdJR0Z5WjNNdWNIVnphQ2gyWVd4MVpTazdYRzRnSUNBZ0lDQnlaWFIxY200Z2RISjFaVHRjYmlBZ0lDQjlYRzVjYmlBZ0lDQnlaWFIxY200Z1ptRnNjMlU3WEc0Z0lIMDdYRzU5WEc1Y2JtWjFibU4wYVc5dUlISmxjMjlzZG1WVGRHRnlkSE5YYVhSb0tIQmhkSFJsY200NklGUjVjR1Z6TGxOMFlYSjBjMWRwZEdncE9pQkdkVzVqZEdsdmJpQjdYRzRnSUdOdmJuTjBJSEJ5WldacGVDQTlJSEJoZEhSbGNtNHVjSEpsWm1sNE8xeHVYRzRnSUhKbGRIVnliaUJtZFc1amRHbHZiaWgyWVd4MVpUb2dZVzU1TENCaGNtZHpPaUJCY25KaGVUeGhibmsrS1RvZ1ltOXZiR1ZoYmlCN1hHNGdJQ0FnYVdZb1EyaGxZMnR6TG1selgzTjBjbWx1WnloMllXeDFaU2tnSmlZZ2RtRnNkV1V1YzNSaGNuUnpWMmwwYUNod2NtVm1hWGdwS1h0Y2JpQWdJQ0FnSUdGeVozTXVjSFZ6YUNoMllXeDFaUzV6ZFdKemRISnBibWNvY0hKbFptbDRMbXhsYm1kMGFDa3BPMXh1SUNBZ0lDQWdjbVYwZFhKdUlIUnlkV1U3WEc0Z0lDQWdmVnh1WEc0Z0lDQWdjbVYwZFhKdUlHWmhiSE5sTzF4dUlDQjlPMXh1ZlZ4dVhHNW1kVzVqZEdsdmJpQnlaWE52YkhabFZIbHdaU2h3WVhSMFpYSnVPaUJVZVhCbGN5NVVlWEJsS1RvZ1JuVnVZM1JwYjI0Z2UxeHVJQ0J5WlhSMWNtNGdablZ1WTNScGIyNG9kbUZzZFdVNklHRnVlU3dnWVhKbmN6b2dRWEp5WVhrOFlXNTVQaWs2SUdKdmIyeGxZVzRnZTF4dUlDQWdJR2xtS0haaGJIVmxJR2x1YzNSaGJtTmxiMllnY0dGMGRHVnliaTUwZVhCbEtYdGNiaUFnSUNBZ0lHTnZibk4wSUcxaGRHTm9aWE1nUFNCaWRXbHNaRTFoZEdOb0tIQmhkSFJsY200dWIySnFVR0YwZEdWeWJpazdYRzRnSUNBZ0lDQnlaWFIxY200Z2JXRjBZMmhsY3loMllXeDFaU3dnWVhKbmN5a2dKaVlnWVhKbmN5NXdkWE5vS0haaGJIVmxLU0ErSURBN1hHNGdJQ0FnZlZ4dVhHNGdJQ0FnY21WMGRYSnVJR1poYkhObE8xeHVJQ0I5TzF4dWZWeHVYRzVtZFc1amRHbHZiaUJ5WlhOdmJIWmxRWEp5WVhrb2NHRjBkR1Z5YmpvZ1FYSnlZWGs4WVc1NVBpazZJRVoxYm1OMGFXOXVJSHRjYmlBZ1kyOXVjM1FnYldGMFkyaGxjeUE5SUhCaGRIUmxjbTR1YldGd0tIZ2dQVDRnWW5WcGJHUk5ZWFJqYUNoNEtTazdYRzVjYmlBZ2NtVjBkWEp1SUdaMWJtTjBhVzl1S0haaGJIVmxPaUJoYm5rc0lHRnlaM002SUVGeWNtRjVQR0Z1ZVQ0cE9pQmliMjlzWldGdUlIdGNiaUFnSUNCcFppZ2hRMmhsWTJ0ekxtbHpYMkZ5Y21GNUtIWmhiSFZsS1NCOGZDQjJZV3gxWlM1c1pXNW5kR2dnSVQwZ2NHRjBkR1Z5Ymk1c1pXNW5kR2dwZTF4dUlDQWdJQ0FnY21WMGRYSnVJR1poYkhObE8xeHVJQ0FnSUgxY2JseHVJQ0FnSUhKbGRIVnliaUIyWVd4MVpTNWxkbVZ5ZVNobWRXNWpkR2x2YmloMkxDQnBLU0I3WEc0Z0lDQWdJQ0J5WlhSMWNtNGdiV0YwWTJobGMxdHBYU2gyWVd4MVpWdHBYU3dnWVhKbmN5azdYRzRnSUNBZ2ZTazdYRzRnSUgwN1hHNTlYRzVjYm1aMWJtTjBhVzl1SUhKbGMyOXNkbVZQWW1wbFkzUW9jR0YwZEdWeWJqb2dUMkpxWldOMEtUb2dSblZ1WTNScGIyNGdlMXh1SUNCc1pYUWdiV0YwWTJobGN5QTlJSHQ5TzF4dVhHNGdJR1p2Y2loc1pYUWdhMlY1SUc5bUlFOWlhbVZqZEM1clpYbHpLSEJoZEhSbGNtNHBMbU52Ym1OaGRDaFBZbXBsWTNRdVoyVjBUM2R1VUhKdmNHVnlkSGxUZVcxaWIyeHpLSEJoZEhSbGNtNHBLU2w3WEc0Z0lDQWdiV0YwWTJobGMxdHJaWGxkSUQwZ1luVnBiR1JOWVhSamFDaHdZWFIwWlhKdVcydGxlVjBwTzF4dUlDQjlYRzVjYmlBZ2NtVjBkWEp1SUdaMWJtTjBhVzl1S0haaGJIVmxPaUJoYm5rc0lHRnlaM002SUVGeWNtRjVQR0Z1ZVQ0cE9pQmliMjlzWldGdUlIdGNiaUFnSUNCcFppZ2hRMmhsWTJ0ekxtbHpYMjlpYW1WamRDaDJZV3gxWlNrZ2ZId2djR0YwZEdWeWJpNXNaVzVuZEdnZ1BpQjJZV3gxWlM1c1pXNW5kR2dwZTF4dUlDQWdJQ0FnY21WMGRYSnVJR1poYkhObE8xeHVJQ0FnSUgxY2JseHVJQ0FnSUdadmNpaHNaWFFnYTJWNUlHOW1JRTlpYW1WamRDNXJaWGx6S0hCaGRIUmxjbTRwTG1OdmJtTmhkQ2hQWW1wbFkzUXVaMlYwVDNkdVVISnZjR1Z5ZEhsVGVXMWliMnh6S0hCaGRIUmxjbTRwS1NsN1hHNGdJQ0FnSUNCcFppZ2hLR3RsZVNCcGJpQjJZV3gxWlNrZ2ZId2dJVzFoZEdOb1pYTmJhMlY1WFNoMllXeDFaVnRyWlhsZExDQmhjbWR6S1NBcGUxeHVJQ0FnSUNBZ0lDQnlaWFIxY200Z1ptRnNjMlU3WEc0Z0lDQWdJQ0I5WEc0Z0lDQWdmVnh1WEc0Z0lDQWdjbVYwZFhKdUlIUnlkV1U3WEc0Z0lIMDdYRzU5WEc1Y2JtWjFibU4wYVc5dUlISmxjMjlzZG1WQ2FYUlRkSEpwYm1jb2NHRjBkR1Z5YmpvZ1ZIbHdaWE11UW1sMFUzUnlhVzVuVFdGMFkyZ3BPaUJHZFc1amRHbHZiaUI3WEc0Z0lHeGxkQ0J3WVhSMFpYSnVRbWwwVTNSeWFXNW5JRDBnVzEwN1hHNWNiaUFnWm05eUtHeGxkQ0JpYVhSemRISnBibWROWVhSamFGQmhjblFnYjJZZ2NHRjBkR1Z5Ymk1MllXeDFaWE1wZTF4dUlDQWdJR2xtS0VOb1pXTnJjeTVwYzE5MllYSnBZV0pzWlNoaWFYUnpkSEpwYm1kTllYUmphRkJoY25RdWRtRnNkV1VwS1h0Y2JpQWdJQ0FnSUd4bGRDQnphWHBsSUQwZ1oyVjBVMmw2WlNoaWFYUnpkSEpwYm1kTllYUmphRkJoY25RdWRXNXBkQ3dnWW1sMGMzUnlhVzVuVFdGMFkyaFFZWEowTG5OcGVtVXBPMXh1SUNBZ0lDQWdabWxzYkVGeWNtRjVLSEJoZEhSbGNtNUNhWFJUZEhKcGJtY3NJSE5wZW1VcE8xeHVJQ0FnSUgxbGJITmxlMXh1SUNBZ0lDQWdjR0YwZEdWeWJrSnBkRk4wY21sdVp5QTlJSEJoZEhSbGNtNUNhWFJUZEhKcGJtY3VZMjl1WTJGMEtHNWxkeUJDYVhSVGRISnBibWNvWW1sMGMzUnlhVzVuVFdGMFkyaFFZWEowS1M1MllXeDFaU2s3WEc0Z0lDQWdmVnh1SUNCOVhHNWNiaUFnYkdWMElIQmhkSFJsY201V1lXeDFaWE1nUFNCd1lYUjBaWEp1TG5aaGJIVmxjenRjYmx4dUlDQnlaWFIxY200Z1puVnVZM1JwYjI0b2RtRnNkV1U2SUdGdWVTd2dZWEpuY3pvZ1FYSnlZWGs4WVc1NVBpazZJR0p2YjJ4bFlXNGdlMXh1SUNBZ0lHeGxkQ0JpYzFaaGJIVmxJRDBnYm5Wc2JEdGNibHh1SUNBZ0lHbG1LQ0ZEYUdWamEzTXVhWE5mYzNSeWFXNW5LSFpoYkhWbEtTQW1KaUFoS0haaGJIVmxJR2x1YzNSaGJtTmxiMllnUW1sMFUzUnlhVzVuS1NBcGUxeHVJQ0FnSUNBZ2NtVjBkWEp1SUdaaGJITmxPMXh1SUNBZ0lIMWNibHh1SUNBZ0lHbG1LRU5vWldOcmN5NXBjMTl6ZEhKcGJtY29kbUZzZFdVcEtYdGNiaUFnSUNBZ0lHSnpWbUZzZFdVZ1BTQnVaWGNnUW1sMFUzUnlhVzVuS0VKcGRGTjBjbWx1Wnk1aWFXNWhjbmtvZG1Gc2RXVXBLVHRjYmlBZ0lDQjlaV3h6Wlh0Y2JpQWdJQ0FnSUdKelZtRnNkV1VnUFNCMllXeDFaVHRjYmlBZ0lDQjlYRzVjYmlBZ0lDQnNaWFFnWW1WbmFXNXVhVzVuU1c1a1pYZ2dQU0F3TzF4dVhHNGdJQ0FnWm05eUtHeGxkQ0JwSUQwZ01Ec2dhU0E4SUhCaGRIUmxjbTVXWVd4MVpYTXViR1Z1WjNSb095QnBLeXNwZTF4dUlDQWdJQ0FnYkdWMElHSnBkSE4wY21sdVowMWhkR05vVUdGeWRDQTlJSEJoZEhSbGNtNVdZV3gxWlhOYmFWMDdYRzVjYmlBZ0lDQWdJR2xtS0VOb1pXTnJjeTVwYzE5MllYSnBZV0pzWlNoaWFYUnpkSEpwYm1kTllYUmphRkJoY25RdWRtRnNkV1VwSUNZbVhHNGdJQ0FnSUNBZ0lDQmlhWFJ6ZEhKcGJtZE5ZWFJqYUZCaGNuUXVkSGx3WlNBOVBTQW5ZbWx1WVhKNUp5QW1KbHh1SUNBZ0lDQWdJQ0FnWW1sMGMzUnlhVzVuVFdGMFkyaFFZWEowTG5OcGVtVWdQVDA5SUhWdVpHVm1hVzVsWkNBbUpseHVJQ0FnSUNBZ0lDQWdhU0E4SUhCaGRIUmxjbTVXWVd4MVpYTXViR1Z1WjNSb0lDMGdNU2w3WEc0Z0lDQWdJQ0FnSUhSb2NtOTNJRzVsZHlCRmNuSnZjaWhjSW1FZ1ltbHVZWEo1SUdacFpXeGtJSGRwZEdodmRYUWdjMmw2WlNCcGN5QnZibXg1SUdGc2JHOTNaV1FnWVhRZ2RHaGxJR1Z1WkNCdlppQmhJR0pwYm1GeWVTQndZWFIwWlhKdVhDSXBPMXh1SUNBZ0lDQWdmVnh1WEc0Z0lDQWdJQ0JzWlhRZ2MybDZaU0E5SURBN1hHNGdJQ0FnSUNCc1pYUWdZbk5XWVd4MVpVRnljbUY1VUdGeWRDQTlJRnRkTzF4dUlDQWdJQ0FnYkdWMElIQmhkSFJsY201Q2FYUlRkSEpwYm1kQmNuSmhlVkJoY25RZ1BTQmJYVHRjYmlBZ0lDQWdJSE5wZW1VZ1BTQm5aWFJUYVhwbEtHSnBkSE4wY21sdVowMWhkR05vVUdGeWRDNTFibWwwTENCaWFYUnpkSEpwYm1kTllYUmphRkJoY25RdWMybDZaU2s3WEc1Y2JpQWdJQ0FnSUdsbUtHa2dQVDA5SUhCaGRIUmxjbTVXWVd4MVpYTXViR1Z1WjNSb0lDMGdNU2w3WEc0Z0lDQWdJQ0FnSUdKelZtRnNkV1ZCY25KaGVWQmhjblFnUFNCaWMxWmhiSFZsTG5aaGJIVmxMbk5zYVdObEtHSmxaMmx1Ym1sdVowbHVaR1Y0S1R0Y2JpQWdJQ0FnSUNBZ2NHRjBkR1Z5YmtKcGRGTjBjbWx1WjBGeWNtRjVVR0Z5ZENBOUlIQmhkSFJsY201Q2FYUlRkSEpwYm1jdWMyeHBZMlVvWW1WbmFXNXVhVzVuU1c1a1pYZ3BPMXh1SUNBZ0lDQWdmU0JsYkhObElIdGNiaUFnSUNBZ0lDQWdZbk5XWVd4MVpVRnljbUY1VUdGeWRDQTlJR0p6Vm1Gc2RXVXVkbUZzZFdVdWMyeHBZMlVvWW1WbmFXNXVhVzVuU1c1a1pYZ3NJR0psWjJsdWJtbHVaMGx1WkdWNElDc2djMmw2WlNrN1hHNGdJQ0FnSUNBZ0lIQmhkSFJsY201Q2FYUlRkSEpwYm1kQmNuSmhlVkJoY25RZ1BTQndZWFIwWlhKdVFtbDBVM1J5YVc1bkxuTnNhV05sS0dKbFoybHVibWx1WjBsdVpHVjRMQ0JpWldkcGJtNXBibWRKYm1SbGVDQXJJSE5wZW1VcE8xeHVJQ0FnSUNBZ2ZWeHVYRzRnSUNBZ0lDQnBaaWhEYUdWamEzTXVhWE5mZG1GeWFXRmliR1VvWW1sMGMzUnlhVzVuVFdGMFkyaFFZWEowTG5aaGJIVmxLU2w3WEc0Z0lDQWdJQ0FnSUhOM2FYUmphQ2hpYVhSemRISnBibWROWVhSamFGQmhjblF1ZEhsd1pTa2dlMXh1SUNBZ0lDQWdJQ0JqWVhObElDZHBiblJsWjJWeUp6cGNiaUFnSUNBZ0lDQWdJQ0JwWmloaWFYUnpkSEpwYm1kTllYUmphRkJoY25RdVlYUjBjbWxpZFhSbGN5QW1KaUJpYVhSemRISnBibWROWVhSamFGQmhjblF1WVhSMGNtbGlkWFJsY3k1cGJtUmxlRTltS0Z3aWMybG5ibVZrWENJcElDRTlJQzB4S1h0Y2JpQWdJQ0FnSUNBZ0lDQWdJR0Z5WjNNdWNIVnphQ2h1WlhjZ1NXNTBPRUZ5Y21GNUtGdGljMVpoYkhWbFFYSnlZWGxRWVhKMFd6QmRYU2xiTUYwcE8xeHVJQ0FnSUNBZ0lDQWdJSDBnWld4elpTQjdYRzRnSUNBZ0lDQWdJQ0FnSUNCaGNtZHpMbkIxYzJnb2JtVjNJRlZwYm5RNFFYSnlZWGtvVzJKelZtRnNkV1ZCY25KaGVWQmhjblJiTUYxZEtWc3dYU2s3WEc0Z0lDQWdJQ0FnSUNBZ2ZWeHVJQ0FnSUNBZ0lDQWdJR0p5WldGck8xeHVYRzRnSUNBZ0lDQWdJR05oYzJVZ0oyWnNiMkYwSnpwY2JpQWdJQ0FnSUNBZ0lDQnBaaWh6YVhwbElEMDlQU0EyTkNsN1hHNGdJQ0FnSUNBZ0lDQWdJQ0JoY21kekxuQjFjMmdvUm14dllYUTJORUZ5Y21GNUxtWnliMjBvWW5OV1lXeDFaVUZ5Y21GNVVHRnlkQ2xiTUYwcE8xeHVJQ0FnSUNBZ0lDQWdJSDBnWld4elpTQnBaaWh6YVhwbElEMDlQU0F6TWlsN1hHNGdJQ0FnSUNBZ0lDQWdJQ0JoY21kekxuQjFjMmdvUm14dllYUXpNa0Z5Y21GNUxtWnliMjBvWW5OV1lXeDFaVUZ5Y21GNVVHRnlkQ2xiTUYwcE8xeHVJQ0FnSUNBZ0lDQWdJSDFsYkhObGUxeHVJQ0FnSUNBZ0lDQWdJQ0FnY21WMGRYSnVJR1poYkhObE8xeHVJQ0FnSUNBZ0lDQWdJSDFjYmlBZ0lDQWdJQ0FnSUNCaWNtVmhhenRjYmx4dUlDQWdJQ0FnSUNCallYTmxJQ2RpYVhSemRISnBibWNuT2x4dUlDQWdJQ0FnSUNBZ0lHRnlaM011Y0hWemFDaGpjbVZoZEdWQ2FYUlRkSEpwYm1jb1luTldZV3gxWlVGeWNtRjVVR0Z5ZENrcE8xeHVJQ0FnSUNBZ0lDQWdJR0p5WldGck8xeHVYRzRnSUNBZ0lDQWdJR05oYzJVZ0oySnBibUZ5ZVNjNlhHNGdJQ0FnSUNBZ0lDQWdZWEpuY3k1d2RYTm9LRk4wY21sdVp5NW1jbTl0UTJoaGNrTnZaR1V1WVhCd2JIa29iblZzYkN3Z2JtVjNJRlZwYm5RNFFYSnlZWGtvWW5OV1lXeDFaVUZ5Y21GNVVHRnlkQ2twS1R0Y2JpQWdJQ0FnSUNBZ0lDQmljbVZoYXp0Y2JseHVJQ0FnSUNBZ0lDQmpZWE5sSUNkMWRHWTRKenBjYmlBZ0lDQWdJQ0FnSUNCaGNtZHpMbkIxYzJnb1UzUnlhVzVuTG1aeWIyMURhR0Z5UTI5a1pTNWhjSEJzZVNodWRXeHNMQ0J1WlhjZ1ZXbHVkRGhCY25KaGVTaGljMVpoYkhWbFFYSnlZWGxRWVhKMEtTa3BPMXh1SUNBZ0lDQWdJQ0FnSUdKeVpXRnJPMXh1WEc0Z0lDQWdJQ0FnSUdOaGMyVWdKM1YwWmpFMkp6cGNiaUFnSUNBZ0lDQWdJQ0JoY21kekxuQjFjMmdvVTNSeWFXNW5MbVp5YjIxRGFHRnlRMjlrWlM1aGNIQnNlU2h1ZFd4c0xDQnVaWGNnVldsdWRERTJRWEp5WVhrb1luTldZV3gxWlVGeWNtRjVVR0Z5ZENrcEtUdGNiaUFnSUNBZ0lDQWdJQ0JpY21WaGF6dGNibHh1SUNBZ0lDQWdJQ0JqWVhObElDZDFkR1l6TWljNlhHNGdJQ0FnSUNBZ0lDQWdZWEpuY3k1d2RYTm9LRk4wY21sdVp5NW1jbTl0UTJoaGNrTnZaR1V1WVhCd2JIa29iblZzYkN3Z2JtVjNJRlZwYm5Rek1rRnljbUY1S0dKelZtRnNkV1ZCY25KaGVWQmhjblFwS1NrN1hHNGdJQ0FnSUNBZ0lDQWdZbkpsWVdzN1hHNWNiaUFnSUNBZ0lDQWdaR1ZtWVhWc2REcGNiaUFnSUNBZ0lDQWdJQ0J5WlhSMWNtNGdabUZzYzJVN1hHNGdJQ0FnSUNBZ0lIMWNiaUFnSUNBZ0lIMWxiSE5sSUdsbUtDRmhjbkpoZVhORmNYVmhiQ2hpYzFaaGJIVmxRWEp5WVhsUVlYSjBMQ0J3WVhSMFpYSnVRbWwwVTNSeWFXNW5RWEp5WVhsUVlYSjBLU2tnZTF4dUlDQWdJQ0FnSUNCeVpYUjFjbTRnWm1Gc2MyVTdYRzRnSUNBZ0lDQjlYRzVjYmlBZ0lDQWdJR0psWjJsdWJtbHVaMGx1WkdWNElEMGdZbVZuYVc1dWFXNW5TVzVrWlhnZ0t5QnphWHBsTzF4dUlDQWdJSDFjYmx4dUlDQWdJSEpsZEhWeWJpQjBjblZsTzF4dUlDQjlYRzVjYm4xY2JseHVablZ1WTNScGIyNGdaMlYwVTJsNlpTaDFibWwwTENCemFYcGxLWHRjYmlBZ2NtVjBkWEp1SUNoMWJtbDBJQ29nYzJsNlpTa2dMeUE0TzF4dWZWeHVYRzVtZFc1amRHbHZiaUJoY25KaGVYTkZjWFZoYkNoaExDQmlLU0I3WEc0Z0lHbG1JQ2hoSUQwOVBTQmlLU0J5WlhSMWNtNGdkSEoxWlR0Y2JpQWdhV1lnS0dFZ1BUMGdiblZzYkNCOGZDQmlJRDA5SUc1MWJHd3BJSEpsZEhWeWJpQm1ZV3h6WlR0Y2JpQWdhV1lnS0dFdWJHVnVaM1JvSUNFOUlHSXViR1Z1WjNSb0tTQnlaWFIxY200Z1ptRnNjMlU3WEc1Y2JpQWdabTl5SUNoMllYSWdhU0E5SURBN0lHa2dQQ0JoTG14bGJtZDBhRHNnS3l0cEtTQjdYRzRnSUNBZ2FXWWdLR0ZiYVYwZ0lUMDlJR0piYVYwcElISmxkSFZ5YmlCbVlXeHpaVHRjYmlBZ2ZWeHVYRzRnSUhKbGRIVnliaUIwY25WbE8xeHVmVnh1WEc1bWRXNWpkR2x2YmlCbWFXeHNRWEp5WVhrb1lYSnlMQ0J1ZFcwcGUxeHVJQ0JtYjNJb2JHVjBJR2tnUFNBd095QnBJRHdnYm5WdE95QnBLeXNwZTF4dUlDQWdJR0Z5Y2k1d2RYTm9LREFwTzF4dUlDQjlYRzU5WEc1Y2JtWjFibU4wYVc5dUlHTnlaV0YwWlVKcGRGTjBjbWx1WnloaGNuSXBlMXh1SUNCc1pYUWdhVzUwWldkbGNsQmhjblJ6SUQwZ1lYSnlMbTFoY0Nnb1pXeGxiU2tnUFQ0Z1FtbDBVM1J5YVc1bkxtbHVkR1ZuWlhJb1pXeGxiU2twTzF4dUlDQnlaWFIxY200Z2JtVjNJRUpwZEZOMGNtbHVaeWd1TGk1cGJuUmxaMlZ5VUdGeWRITXBPMXh1ZlZ4dVhHNW1kVzVqZEdsdmJpQnlaWE52YkhabFRtOU5ZWFJqYUNncE9pQkdkVzVqZEdsdmJpQjdYRzRnSUhKbGRIVnliaUJtZFc1amRHbHZiaWdwT2lCaWIyOXNaV0Z1SUh0Y2JpQWdJQ0J5WlhSMWNtNGdabUZzYzJVN1hHNGdJSDFjYm4xY2JseHVaWGh3YjNKMElHUmxabUYxYkhRZ2UxeHVJQ0J5WlhOdmJIWmxRbTkxYm1Rc1hHNGdJSEpsYzI5c2RtVlhhV3hrWTJGeVpDeGNiaUFnY21WemIyeDJaVlpoY21saFlteGxMRnh1SUNCeVpYTnZiSFpsU0dWaFpGUmhhV3dzWEc0Z0lISmxjMjlzZG1WRFlYQjBkWEpsTEZ4dUlDQnlaWE52YkhabFUzUmhjblJ6VjJsMGFDeGNiaUFnY21WemIyeDJaVlI1Y0dVc1hHNGdJSEpsYzI5c2RtVkJjbkpoZVN4Y2JpQWdjbVZ6YjJ4MlpVOWlhbVZqZEN4Y2JpQWdjbVZ6YjJ4MlpVNXZUV0YwWTJnc1hHNGdJSEpsYzI5c2RtVlRlVzFpYjJ3c1hHNGdJSEpsYzI5c2RtVlRkSEpwYm1jc1hHNGdJSEpsYzI5c2RtVk9kVzFpWlhJc1hHNGdJSEpsYzI5c2RtVkNiMjlzWldGdUxGeHVJQ0J5WlhOdmJIWmxSblZ1WTNScGIyNHNYRzRnSUhKbGMyOXNkbVZPZFd4c0xGeHVJQ0J5WlhOdmJIWmxRbWwwVTNSeWFXNW5YRzU5WEc0aVhTd2ljMjkxY21ObFVtOXZkQ0k2SWk5emIzVnlZMlV2SW4wPVxuIiwiXG5pbXBvcnQgQ2hlY2tzIGZyb20gXCIuL2NoZWNrc1wiO1xuaW1wb3J0IFJlc29sdmVycyBmcm9tIFwiLi9yZXNvbHZlcnNcIjtcblxuZXhwb3J0IGZ1bmN0aW9uIGJ1aWxkTWF0Y2gocGF0dGVybikge1xuXG4gIGlmIChDaGVja3MuaXNfdmFyaWFibGUocGF0dGVybikpIHtcbiAgICByZXR1cm4gUmVzb2x2ZXJzLnJlc29sdmVWYXJpYWJsZShwYXR0ZXJuKTtcbiAgfVxuXG4gIGlmIChDaGVja3MuaXNfd2lsZGNhcmQocGF0dGVybikpIHtcbiAgICByZXR1cm4gUmVzb2x2ZXJzLnJlc29sdmVXaWxkY2FyZChwYXR0ZXJuKTtcbiAgfVxuXG4gIGlmIChDaGVja3MuaXNfdW5kZWZpbmVkKHBhdHRlcm4pKSB7XG4gICAgcmV0dXJuIFJlc29sdmVycy5yZXNvbHZlV2lsZGNhcmQocGF0dGVybik7XG4gIH1cblxuICBpZiAoQ2hlY2tzLmlzX2hlYWRUYWlsKHBhdHRlcm4pKSB7XG4gICAgcmV0dXJuIFJlc29sdmVycy5yZXNvbHZlSGVhZFRhaWwocGF0dGVybik7XG4gIH1cblxuICBpZiAoQ2hlY2tzLmlzX3N0YXJ0c1dpdGgocGF0dGVybikpIHtcbiAgICByZXR1cm4gUmVzb2x2ZXJzLnJlc29sdmVTdGFydHNXaXRoKHBhdHRlcm4pO1xuICB9XG5cbiAgaWYgKENoZWNrcy5pc19jYXB0dXJlKHBhdHRlcm4pKSB7XG4gICAgcmV0dXJuIFJlc29sdmVycy5yZXNvbHZlQ2FwdHVyZShwYXR0ZXJuKTtcbiAgfVxuXG4gIGlmIChDaGVja3MuaXNfYm91bmQocGF0dGVybikpIHtcbiAgICByZXR1cm4gUmVzb2x2ZXJzLnJlc29sdmVCb3VuZChwYXR0ZXJuKTtcbiAgfVxuXG4gIGlmIChDaGVja3MuaXNfdHlwZShwYXR0ZXJuKSkge1xuICAgIHJldHVybiBSZXNvbHZlcnMucmVzb2x2ZVR5cGUocGF0dGVybik7XG4gIH1cblxuICBpZiAoQ2hlY2tzLmlzX2FycmF5KHBhdHRlcm4pKSB7XG4gICAgcmV0dXJuIFJlc29sdmVycy5yZXNvbHZlQXJyYXkocGF0dGVybik7XG4gIH1cblxuICBpZiAoQ2hlY2tzLmlzX251bWJlcihwYXR0ZXJuKSkge1xuICAgIHJldHVybiBSZXNvbHZlcnMucmVzb2x2ZU51bWJlcihwYXR0ZXJuKTtcbiAgfVxuXG4gIGlmIChDaGVja3MuaXNfc3RyaW5nKHBhdHRlcm4pKSB7XG4gICAgcmV0dXJuIFJlc29sdmVycy5yZXNvbHZlU3RyaW5nKHBhdHRlcm4pO1xuICB9XG5cbiAgaWYgKENoZWNrcy5pc19ib29sZWFuKHBhdHRlcm4pKSB7XG4gICAgcmV0dXJuIFJlc29sdmVycy5yZXNvbHZlQm9vbGVhbihwYXR0ZXJuKTtcbiAgfVxuXG4gIGlmIChDaGVja3MuaXNfc3ltYm9sKHBhdHRlcm4pKSB7XG4gICAgcmV0dXJuIFJlc29sdmVycy5yZXNvbHZlU3ltYm9sKHBhdHRlcm4pO1xuICB9XG5cbiAgaWYgKENoZWNrcy5pc19udWxsKHBhdHRlcm4pKSB7XG4gICAgcmV0dXJuIFJlc29sdmVycy5yZXNvbHZlTnVsbChwYXR0ZXJuKTtcbiAgfVxuXG4gIGlmIChDaGVja3MuaXNfYml0c3RyaW5nKHBhdHRlcm4pKSB7XG4gICAgcmV0dXJuIFJlc29sdmVycy5yZXNvbHZlQml0U3RyaW5nKHBhdHRlcm4pO1xuICB9XG5cbiAgaWYgKENoZWNrcy5pc19vYmplY3QocGF0dGVybikpIHtcbiAgICByZXR1cm4gUmVzb2x2ZXJzLnJlc29sdmVPYmplY3QocGF0dGVybik7XG4gIH1cblxuICByZXR1cm4gUmVzb2x2ZXJzLnJlc29sdmVOb01hdGNoKCk7XG59XG4vLyMgc291cmNlTWFwcGluZ1VSTD1kYXRhOmFwcGxpY2F0aW9uL2pzb247YmFzZTY0LGV5SjJaWEp6YVc5dUlqb3pMQ0p6YjNWeVkyVnpJanBiSW14cFlpOWpiM0psTDNCaGRIUmxjbTV6TDIxaGRHTm9MbXB6SWwwc0ltNWhiV1Z6SWpwYlhTd2liV0Z3Y0dsdVozTWlPaUk3UVVGRFFTeFBRVUZQTEUxQlFWQXNUVUZCYlVJc1ZVRkJia0k3UVVGRFFTeFBRVUZQTEZOQlFWQXNUVUZCYzBJc1lVRkJkRUk3TzBGQlJVRXNUMEZCVHl4VFFVRlRMRlZCUVZRc1EwRkJiMElzVDBGQmNFSXNSVUZCTkVNN08wRkJSV3BFTEUxQlFVY3NUMEZCVHl4WFFVRlFMRU5CUVcxQ0xFOUJRVzVDTEVOQlFVZ3NSVUZCSzBJN1FVRkROMElzVjBGQlR5eFZRVUZWTEdWQlFWWXNRMEZCTUVJc1QwRkJNVUlzUTBGQlVDeERRVVEyUWp0SFFVRXZRanM3UVVGSlFTeE5RVUZITEU5QlFVOHNWMEZCVUN4RFFVRnRRaXhQUVVGdVFpeERRVUZJTEVWQlFTdENPMEZCUXpkQ0xGZEJRVThzVlVGQlZTeGxRVUZXTEVOQlFUQkNMRTlCUVRGQ0xFTkJRVkFzUTBGRU5rSTdSMEZCTDBJN08wRkJTVUVzVFVGQlJ5eFBRVUZQTEZsQlFWQXNRMEZCYjBJc1QwRkJjRUlzUTBGQlNDeEZRVUZuUXp0QlFVTTVRaXhYUVVGUExGVkJRVlVzWlVGQlZpeERRVUV3UWl4UFFVRXhRaXhEUVVGUUxFTkJSRGhDTzBkQlFXaERPenRCUVVsQkxFMUJRVWNzVDBGQlR5eFhRVUZRTEVOQlFXMUNMRTlCUVc1Q0xFTkJRVWdzUlVGQkswSTdRVUZETjBJc1YwRkJUeXhWUVVGVkxHVkJRVllzUTBGQk1FSXNUMEZCTVVJc1EwRkJVQ3hEUVVRMlFqdEhRVUV2UWpzN1FVRkpRU3hOUVVGSExFOUJRVThzWVVGQlVDeERRVUZ4UWl4UFFVRnlRaXhEUVVGSUxFVkJRV2xETzBGQlF5OUNMRmRCUVU4c1ZVRkJWU3hwUWtGQlZpeERRVUUwUWl4UFFVRTFRaXhEUVVGUUxFTkJSQ3RDTzBkQlFXcERPenRCUVVsQkxFMUJRVWNzVDBGQlR5eFZRVUZRTEVOQlFXdENMRTlCUVd4Q0xFTkJRVWdzUlVGQk9FSTdRVUZETlVJc1YwRkJUeXhWUVVGVkxHTkJRVllzUTBGQmVVSXNUMEZCZWtJc1EwRkJVQ3hEUVVRMFFqdEhRVUU1UWpzN1FVRkpRU3hOUVVGSExFOUJRVThzVVVGQlVDeERRVUZuUWl4UFFVRm9RaXhEUVVGSUxFVkJRVFJDTzBGQlF6RkNMRmRCUVU4c1ZVRkJWU3haUVVGV0xFTkJRWFZDTEU5QlFYWkNMRU5CUVZBc1EwRkVNRUk3UjBGQk5VSTdPMEZCU1VFc1RVRkJSeXhQUVVGUExFOUJRVkFzUTBGQlpTeFBRVUZtTEVOQlFVZ3NSVUZCTWtJN1FVRkRla0lzVjBGQlR5eFZRVUZWTEZkQlFWWXNRMEZCYzBJc1QwRkJkRUlzUTBGQlVDeERRVVI1UWp0SFFVRXpRanM3UVVGSlFTeE5RVUZITEU5QlFVOHNVVUZCVUN4RFFVRm5RaXhQUVVGb1FpeERRVUZJTEVWQlFUUkNPMEZCUXpGQ0xGZEJRVThzVlVGQlZTeFpRVUZXTEVOQlFYVkNMRTlCUVhaQ0xFTkJRVkFzUTBGRU1FSTdSMEZCTlVJN08wRkJTVUVzVFVGQlJ5eFBRVUZQTEZOQlFWQXNRMEZCYVVJc1QwRkJha0lzUTBGQlNDeEZRVUUyUWp0QlFVTXpRaXhYUVVGUExGVkJRVlVzWVVGQlZpeERRVUYzUWl4UFFVRjRRaXhEUVVGUUxFTkJSREpDTzBkQlFUZENPenRCUVVsQkxFMUJRVWNzVDBGQlR5eFRRVUZRTEVOQlFXbENMRTlCUVdwQ0xFTkJRVWdzUlVGQk5rSTdRVUZETTBJc1YwRkJUeXhWUVVGVkxHRkJRVllzUTBGQmQwSXNUMEZCZUVJc1EwRkJVQ3hEUVVReVFqdEhRVUUzUWpzN1FVRkpRU3hOUVVGSExFOUJRVThzVlVGQlVDeERRVUZyUWl4UFFVRnNRaXhEUVVGSUxFVkJRVGhDTzBGQlF6VkNMRmRCUVU4c1ZVRkJWU3hqUVVGV0xFTkJRWGxDTEU5QlFYcENMRU5CUVZBc1EwRkVORUk3UjBGQk9VSTdPMEZCU1VFc1RVRkJSeXhQUVVGUExGTkJRVkFzUTBGQmFVSXNUMEZCYWtJc1EwRkJTQ3hGUVVFMlFqdEJRVU16UWl4WFFVRlBMRlZCUVZVc1lVRkJWaXhEUVVGM1FpeFBRVUY0UWl4RFFVRlFMRU5CUkRKQ08wZEJRVGRDT3p0QlFVbEJMRTFCUVVjc1QwRkJUeXhQUVVGUUxFTkJRV1VzVDBGQlppeERRVUZJTEVWQlFUSkNPMEZCUTNwQ0xGZEJRVThzVlVGQlZTeFhRVUZXTEVOQlFYTkNMRTlCUVhSQ0xFTkJRVkFzUTBGRWVVSTdSMEZCTTBJN08wRkJTVUVzVFVGQlJ5eFBRVUZQTEZsQlFWQXNRMEZCYjBJc1QwRkJjRUlzUTBGQlNDeEZRVUZuUXp0QlFVTTVRaXhYUVVGUExGVkJRVlVzWjBKQlFWWXNRMEZCTWtJc1QwRkJNMElzUTBGQlVDeERRVVE0UWp0SFFVRm9RenM3UVVGSlFTeE5RVUZITEU5QlFVOHNVMEZCVUN4RFFVRnBRaXhQUVVGcVFpeERRVUZJTEVWQlFUWkNPMEZCUXpOQ0xGZEJRVThzVlVGQlZTeGhRVUZXTEVOQlFYZENMRTlCUVhoQ0xFTkJRVkFzUTBGRU1rSTdSMEZCTjBJN08wRkJTVUVzVTBGQlR5eFZRVUZWTEdOQlFWWXNSVUZCVUN4RFFXeEZhVVE3UTBGQk5VTWlMQ0ptYVd4bElqb2liR2xpTDJOdmNtVXZjR0YwZEdWeWJuTXZiV0YwWTJndWFuTWlMQ0p6YjNWeVkyVnpRMjl1ZEdWdWRDSTZXeUl2S2lCQVpteHZkeUFxTDF4dWFXMXdiM0owSUVOb1pXTnJjeUJtY205dElGd2lMaTlqYUdWamEzTmNJanRjYm1sdGNHOXlkQ0JTWlhOdmJIWmxjbk1nWm5KdmJTQmNJaTR2Y21WemIyeDJaWEp6WENJN1hHNWNibVY0Y0c5eWRDQm1kVzVqZEdsdmJpQmlkV2xzWkUxaGRHTm9LSEJoZEhSbGNtNDZJR0Z1ZVNrNklFWjFibU4wYVc5dUlIdGNibHh1SUNCcFppaERhR1ZqYTNNdWFYTmZkbUZ5YVdGaWJHVW9jR0YwZEdWeWJpa3BlMXh1SUNBZ0lISmxkSFZ5YmlCU1pYTnZiSFpsY25NdWNtVnpiMngyWlZaaGNtbGhZbXhsS0hCaGRIUmxjbTRwTzF4dUlDQjlYRzVjYmlBZ2FXWW9RMmhsWTJ0ekxtbHpYM2RwYkdSallYSmtLSEJoZEhSbGNtNHBLWHRjYmlBZ0lDQnlaWFIxY200Z1VtVnpiMngyWlhKekxuSmxjMjlzZG1WWGFXeGtZMkZ5WkNod1lYUjBaWEp1S1R0Y2JpQWdmVnh1WEc0Z0lHbG1LRU5vWldOcmN5NXBjMTkxYm1SbFptbHVaV1FvY0dGMGRHVnliaWtwZTF4dUlDQWdJSEpsZEhWeWJpQlNaWE52YkhabGNuTXVjbVZ6YjJ4MlpWZHBiR1JqWVhKa0tIQmhkSFJsY200cE8xeHVJQ0I5WEc1Y2JpQWdhV1lvUTJobFkydHpMbWx6WDJobFlXUlVZV2xzS0hCaGRIUmxjbTRwS1h0Y2JpQWdJQ0J5WlhSMWNtNGdVbVZ6YjJ4MlpYSnpMbkpsYzI5c2RtVklaV0ZrVkdGcGJDaHdZWFIwWlhKdUtUdGNiaUFnZlZ4dVhHNGdJR2xtS0VOb1pXTnJjeTVwYzE5emRHRnlkSE5YYVhSb0tIQmhkSFJsY200cEtYdGNiaUFnSUNCeVpYUjFjbTRnVW1WemIyeDJaWEp6TG5KbGMyOXNkbVZUZEdGeWRITlhhWFJvS0hCaGRIUmxjbTRwTzF4dUlDQjlYRzVjYmlBZ2FXWW9RMmhsWTJ0ekxtbHpYMk5oY0hSMWNtVW9jR0YwZEdWeWJpa3BlMXh1SUNBZ0lISmxkSFZ5YmlCU1pYTnZiSFpsY25NdWNtVnpiMngyWlVOaGNIUjFjbVVvY0dGMGRHVnliaWs3WEc0Z0lIMWNibHh1SUNCcFppaERhR1ZqYTNNdWFYTmZZbTkxYm1Rb2NHRjBkR1Z5YmlrcGUxeHVJQ0FnSUhKbGRIVnliaUJTWlhOdmJIWmxjbk11Y21WemIyeDJaVUp2ZFc1a0tIQmhkSFJsY200cE8xeHVJQ0I5WEc1Y2JpQWdhV1lvUTJobFkydHpMbWx6WDNSNWNHVW9jR0YwZEdWeWJpa3BlMXh1SUNBZ0lISmxkSFZ5YmlCU1pYTnZiSFpsY25NdWNtVnpiMngyWlZSNWNHVW9jR0YwZEdWeWJpazdYRzRnSUgxY2JseHVJQ0JwWmloRGFHVmphM011YVhOZllYSnlZWGtvY0dGMGRHVnliaWtwZTF4dUlDQWdJSEpsZEhWeWJpQlNaWE52YkhabGNuTXVjbVZ6YjJ4MlpVRnljbUY1S0hCaGRIUmxjbTRwTzF4dUlDQjlYRzVjYmlBZ2FXWW9RMmhsWTJ0ekxtbHpYMjUxYldKbGNpaHdZWFIwWlhKdUtTbDdYRzRnSUNBZ2NtVjBkWEp1SUZKbGMyOXNkbVZ5Y3k1eVpYTnZiSFpsVG5WdFltVnlLSEJoZEhSbGNtNHBPMXh1SUNCOVhHNWNiaUFnYVdZb1EyaGxZMnR6TG1selgzTjBjbWx1Wnlod1lYUjBaWEp1S1NsN1hHNGdJQ0FnY21WMGRYSnVJRkpsYzI5c2RtVnljeTV5WlhOdmJIWmxVM1J5YVc1bktIQmhkSFJsY200cE8xeHVJQ0I5WEc1Y2JpQWdhV1lvUTJobFkydHpMbWx6WDJKdmIyeGxZVzRvY0dGMGRHVnliaWtwZTF4dUlDQWdJSEpsZEhWeWJpQlNaWE52YkhabGNuTXVjbVZ6YjJ4MlpVSnZiMnhsWVc0b2NHRjBkR1Z5YmlrN1hHNGdJSDFjYmx4dUlDQnBaaWhEYUdWamEzTXVhWE5mYzNsdFltOXNLSEJoZEhSbGNtNHBLWHRjYmlBZ0lDQnlaWFIxY200Z1VtVnpiMngyWlhKekxuSmxjMjlzZG1WVGVXMWliMndvY0dGMGRHVnliaWs3WEc0Z0lIMWNibHh1SUNCcFppaERhR1ZqYTNNdWFYTmZiblZzYkNod1lYUjBaWEp1S1NsN1hHNGdJQ0FnY21WMGRYSnVJRkpsYzI5c2RtVnljeTV5WlhOdmJIWmxUblZzYkNod1lYUjBaWEp1S1R0Y2JpQWdmVnh1WEc0Z0lHbG1LRU5vWldOcmN5NXBjMTlpYVhSemRISnBibWNvY0dGMGRHVnliaWtwZTF4dUlDQWdJSEpsZEhWeWJpQlNaWE52YkhabGNuTXVjbVZ6YjJ4MlpVSnBkRk4wY21sdVp5aHdZWFIwWlhKdUtUdGNiaUFnZlZ4dVhHNGdJR2xtS0VOb1pXTnJjeTVwYzE5dlltcGxZM1FvY0dGMGRHVnliaWtwZTF4dUlDQWdJSEpsZEhWeWJpQlNaWE52YkhabGNuTXVjbVZ6YjJ4MlpVOWlhbVZqZENod1lYUjBaWEp1S1R0Y2JpQWdmVnh1WEc0Z0lISmxkSFZ5YmlCU1pYTnZiSFpsY25NdWNtVnpiMngyWlU1dlRXRjBZMmdvS1R0Y2JuMWNiaUpkTENKemIzVnlZMlZTYjI5MElqb2lMM052ZFhKalpTOGlmUT09XG4iLCJcblxuaW1wb3J0IHsgYnVpbGRNYXRjaCB9IGZyb20gXCIuL21hdGNoXCI7XG5pbXBvcnQgKiBhcyBUeXBlcyBmcm9tIFwiLi90eXBlc1wiO1xuXG5leHBvcnQgY2xhc3MgTWF0Y2hFcnJvciBleHRlbmRzIEVycm9yIHtcbiAgY29uc3RydWN0b3IoYXJnKSB7XG4gICAgc3VwZXIoKTtcblxuICAgIGlmICh0eXBlb2YgYXJnID09PSAnc3ltYm9sJykge1xuICAgICAgdGhpcy5tZXNzYWdlID0gJ05vIG1hdGNoIGZvcjogJyArIGFyZy50b1N0cmluZygpO1xuICAgIH0gZWxzZSBpZiAoQXJyYXkuaXNBcnJheShhcmcpKSB7XG4gICAgICBsZXQgbWFwcGVkVmFsdWVzID0gYXJnLm1hcCh4ID0+IHgudG9TdHJpbmcoKSk7XG4gICAgICB0aGlzLm1lc3NhZ2UgPSAnTm8gbWF0Y2ggZm9yOiAnICsgbWFwcGVkVmFsdWVzO1xuICAgIH0gZWxzZSB7XG4gICAgICB0aGlzLm1lc3NhZ2UgPSAnTm8gbWF0Y2ggZm9yOiAnICsgYXJnO1xuICAgIH1cblxuICAgIHRoaXMuc3RhY2sgPSBuZXcgRXJyb3IoKS5zdGFjaztcbiAgICB0aGlzLm5hbWUgPSB0aGlzLmNvbnN0cnVjdG9yLm5hbWU7XG4gIH1cbn1cblxuZXhwb3J0IGNsYXNzIENhc2Uge1xuXG4gIGNvbnN0cnVjdG9yKHBhdHRlcm4sIGZuLCBndWFyZCA9ICgpID0+IHRydWUpIHtcbiAgICB0aGlzLnBhdHRlcm4gPSBidWlsZE1hdGNoKHBhdHRlcm4pO1xuICAgIHRoaXMuYXJpdHkgPSBwYXR0ZXJuLmxlbmd0aDtcbiAgICB0aGlzLm9wdGlvbmFscyA9IGdldE9wdGlvbmFsVmFsdWVzKHBhdHRlcm4pO1xuICAgIHRoaXMuZm4gPSBmbjtcbiAgICB0aGlzLmd1YXJkID0gZ3VhcmQ7XG4gIH1cbn1cblxuZXhwb3J0IGZ1bmN0aW9uIG1ha2VfY2FzZShwYXR0ZXJuLCBmbiwgZ3VhcmQgPSAoKSA9PiB0cnVlKSB7XG4gIHJldHVybiBuZXcgQ2FzZShwYXR0ZXJuLCBmbiwgZ3VhcmQpO1xufVxuXG5leHBvcnQgZnVuY3Rpb24gZGVmbWF0Y2goLi4uY2FzZXMpIHtcbiAgcmV0dXJuIGZ1bmN0aW9uICguLi5hcmdzKSB7XG4gICAgZm9yIChsZXQgcHJvY2Vzc2VkQ2FzZSBvZiBjYXNlcykge1xuICAgICAgbGV0IHJlc3VsdCA9IFtdO1xuICAgICAgYXJncyA9IGZpbGxJbk9wdGlvbmFsVmFsdWVzKGFyZ3MsIHByb2Nlc3NlZENhc2UuYXJpdHksIHByb2Nlc3NlZENhc2Uub3B0aW9uYWxzKTtcblxuICAgICAgaWYgKHByb2Nlc3NlZENhc2UucGF0dGVybihhcmdzLCByZXN1bHQpICYmIHByb2Nlc3NlZENhc2UuZ3VhcmQuYXBwbHkodGhpcywgcmVzdWx0KSkge1xuICAgICAgICByZXR1cm4gcHJvY2Vzc2VkQ2FzZS5mbi5hcHBseSh0aGlzLCByZXN1bHQpO1xuICAgICAgfVxuICAgIH1cblxuICAgIHRocm93IG5ldyBNYXRjaEVycm9yKGFyZ3MpO1xuICB9O1xufVxuXG5mdW5jdGlvbiBnZXRPcHRpb25hbFZhbHVlcyhwYXR0ZXJuKSB7XG4gIGxldCBvcHRpb25hbHMgPSBbXTtcblxuICBmb3IgKGxldCBpID0gMDsgaSA8IHBhdHRlcm4ubGVuZ3RoOyBpKyspIHtcbiAgICBpZiAocGF0dGVybltpXSBpbnN0YW5jZW9mIFR5cGVzLlZhcmlhYmxlICYmIHBhdHRlcm5baV0uZGVmYXVsdF92YWx1ZSAhPSBTeW1ib2wuZm9yKFwiZWxpeGlyc2NyaXB0Lm5vX3ZhbHVlXCIpKSB7XG4gICAgICBvcHRpb25hbHMucHVzaChbaSwgcGF0dGVybltpXS5kZWZhdWx0X3ZhbHVlXSk7XG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIG9wdGlvbmFscztcbn1cblxuZnVuY3Rpb24gZmlsbEluT3B0aW9uYWxWYWx1ZXMoYXJncywgYXJpdHksIG9wdGlvbmFscykge1xuICBpZiAoYXJncy5sZW5ndGggPT09IGFyaXR5IHx8IG9wdGlvbmFscy5sZW5ndGggPT09IDApIHtcbiAgICByZXR1cm4gYXJncztcbiAgfVxuXG4gIGlmIChhcmdzLmxlbmd0aCArIG9wdGlvbmFscy5sZW5ndGggPCBhcml0eSkge1xuICAgIHJldHVybiBhcmdzO1xuICB9XG5cbiAgbGV0IG51bWJlck9mT3B0aW9uYWxzVG9GaWxsID0gYXJpdHkgLSBhcmdzLmxlbmd0aDtcbiAgbGV0IG9wdGlvbmFsc1RvUmVtb3ZlID0gb3B0aW9uYWxzLmxlbmd0aCAtIG51bWJlck9mT3B0aW9uYWxzVG9GaWxsO1xuXG4gIGxldCBvcHRpb25hbHNUb1VzZSA9IG9wdGlvbmFscy5zbGljZShvcHRpb25hbHNUb1JlbW92ZSk7XG5cbiAgZm9yIChsZXQgW2luZGV4LCB2YWx1ZV0gb2Ygb3B0aW9uYWxzVG9Vc2UpIHtcbiAgICBhcmdzLnNwbGljZShpbmRleCwgMCwgdmFsdWUpO1xuICAgIGlmIChhcmdzLmxlbmd0aCA9PT0gYXJpdHkpIHtcbiAgICAgIGJyZWFrO1xuICAgIH1cbiAgfVxuXG4gIHJldHVybiBhcmdzO1xufVxuXG5leHBvcnQgZnVuY3Rpb24gbWF0Y2gocGF0dGVybiwgZXhwciwgZ3VhcmQgPSAoKSA9PiB0cnVlKSB7XG4gIGxldCByZXN1bHQgPSBbXTtcbiAgbGV0IHByb2Nlc3NlZFBhdHRlcm4gPSBidWlsZE1hdGNoKHBhdHRlcm4pO1xuICBpZiAocHJvY2Vzc2VkUGF0dGVybihleHByLCByZXN1bHQpICYmIGd1YXJkLmFwcGx5KHRoaXMsIHJlc3VsdCkpIHtcbiAgICByZXR1cm4gcmVzdWx0O1xuICB9IGVsc2Uge1xuICAgIHRocm93IG5ldyBNYXRjaEVycm9yKGV4cHIpO1xuICB9XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBtYXRjaF9ub190aHJvdyhwYXR0ZXJuLCBleHByLCBndWFyZCA9ICgpID0+IHRydWUpIHtcbiAgdHJ5IHtcbiAgICByZXR1cm4gbWF0Y2gocGF0dGVybiwgZXhwciwgZ3VhcmQpO1xuICB9IGNhdGNoIChlKSB7XG4gICAgaWYgKGUgaW5zdGFuY2VvZiBNYXRjaEVycm9yIHx8IGUubWVzc2FnZS5zdGFydHNXaXRoKCdObyBtYXRjaCBmb3I6JykpIHtcbiAgICAgIHJldHVybiBudWxsO1xuICAgIH1cblxuICAgIHRocm93IGU7XG4gIH1cbn1cblxuZXhwb3J0IGZ1bmN0aW9uIHBhdHRlcm5NYXAoY29sbGVjdGlvbiwgcGF0dGVybiwgZnVuLCBndWFyZCA9ICgpID0+IHRydWUpIHtcbiAgbGV0IHJldCA9IFtdO1xuXG4gIGZvciAobGV0IGVsZW0gb2YgY29sbGVjdGlvbikge1xuICAgIHRyeSB7XG4gICAgICBsZXQgcmVzdWx0ID0gZnVuLmFwcGx5KHRoaXMsIG1hdGNoKHBhdHRlcm4sIGVsZW0sIGd1YXJkKSk7XG4gICAgICByZXQgPSByZXQuY29uY2F0KHJlc3VsdCk7XG4gICAgfSBjYXRjaCAoZSkge1xuICAgICAgaWYgKCEoZSBpbnN0YW5jZW9mIE1hdGNoRXJyb3IpKSB7XG4gICAgICAgIHRocm93IGU7XG4gICAgICB9XG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIHJldDtcbn1cbi8vIyBzb3VyY2VNYXBwaW5nVVJMPWRhdGE6YXBwbGljYXRpb24vanNvbjtiYXNlNjQsZXlKMlpYSnphVzl1SWpvekxDSnpiM1Z5WTJWeklqcGJJbXhwWWk5amIzSmxMM0JoZEhSbGNtNXpMMlJsWm0xaGRHTm9MbXB6SWwwc0ltNWhiV1Z6SWpwYlhTd2liV0Z3Y0dsdVozTWlPaUk3TzBGQlJVRXNVMEZCVXl4VlFVRlVMRkZCUVRKQ0xGTkJRVE5DTzBGQlEwRXNUMEZCVHl4TFFVRkxMRXRCUVV3c1RVRkJaMElzVTBGQmRrSTdPMEZCUlVFc1QwRkJUeXhOUVVGTkxGVkJRVTRzVTBGQmVVSXNTMEZCZWtJc1EwRkJLMEk3UVVGRGNFTXNZMEZCV1N4SFFVRmFMRVZCUVhOQ08wRkJRM0JDTEZsQlJHOUNPenRCUVVkd1FpeFJRVUZITEU5QlFVOHNSMEZCVUN4TFFVRmxMRkZCUVdZc1JVRkJkMEk3UVVGRGVrSXNWMEZCU3l4UFFVRk1MRWRCUVdVc2JVSkJRVzFDTEVsQlFVa3NVVUZCU2l4RlFVRnVRaXhEUVVSVk8wdEJRVE5DTEUxQlJVOHNTVUZCUnl4TlFVRk5MRTlCUVU0c1EwRkJZeXhIUVVGa0xFTkJRVWdzUlVGQmMwSTdRVUZETTBJc1ZVRkJTU3hsUVVGbExFbEJRVWtzUjBGQlNpeERRVUZSTEV0QlFVOHNSVUZCUlN4UlFVRkdMRVZCUVZBc1EwRkJka0lzUTBGRWRVSTdRVUZGTTBJc1YwRkJTeXhQUVVGTUxFZEJRV1VzYlVKQlFXMUNMRmxCUVc1Q0xFTkJSbGs3UzBGQmRFSXNUVUZIUmp0QlFVTklMRmRCUVVzc1QwRkJUQ3hIUVVGbExHMUNRVUZ0UWl4SFFVRnVRaXhEUVVSYU8wdEJTRVU3TzBGQlQxQXNVMEZCU3l4TFFVRk1MRWRCUVdFc1NVRkJTeXhMUVVGS0xFVkJRVVFzUTBGQll5eExRVUZrTEVOQldrODdRVUZoY0VJc1UwRkJTeXhKUVVGTUxFZEJRVmtzUzBGQlN5eFhRVUZNTEVOQlFXbENMRWxCUVdwQ0xFTkJZbEU3UjBGQmRFSTdRMEZFU3pzN1FVRnRRbEFzVDBGQlR5eE5RVUZOTEVsQlFVNHNRMEZCVnpzN1FVRlBhRUlzWTBGQldTeFBRVUZhTEVWQlFXbERMRVZCUVdwRExFVkJRU3RFTEZGQlFVVXNUVUZCVFN4SlFVRk9MRVZCUVZjN1FVRkRNVVVzVTBGQlN5eFBRVUZNTEVkQlFXVXNWMEZCVnl4UFFVRllMRU5CUVdZc1EwRkVNRVU3UVVGRk1VVXNVMEZCU3l4TFFVRk1MRWRCUVdFc1VVRkJVU3hOUVVGU0xFTkJSalpFTzBGQlJ6RkZMRk5CUVVzc1UwRkJUQ3hIUVVGcFFpeHJRa0ZCYTBJc1QwRkJiRUlzUTBGQmFrSXNRMEZJTUVVN1FVRkpNVVVzVTBGQlN5eEZRVUZNTEVkQlFWVXNSVUZCVml4RFFVb3dSVHRCUVVzeFJTeFRRVUZMTEV0QlFVd3NSMEZCWVN4TFFVRmlMRU5CVERCRk8wZEJRVFZGTzBOQlVFczdPMEZCWjBKUUxFOUJRVThzVTBGQlV5eFRRVUZVTEVOQlFXMUNMRTlCUVc1Q0xFVkJRWGRETEVWQlFYaERMRVZCUVhORkxGRkJRVVVzVFVGQlRTeEpRVUZPTEVWQlFXdENPMEZCUXk5R0xGTkJRVThzU1VGQlNTeEpRVUZLTEVOQlFWTXNUMEZCVkN4RlFVRnJRaXhGUVVGc1FpeEZRVUZ6UWl4TFFVRjBRaXhEUVVGUUxFTkJSQ3RHTzBOQlFURkdPenRCUVVsUUxFOUJRVThzVTBGQlV5eFJRVUZVTEVOQlFXdENMRWRCUVVjc1MwRkJTQ3hGUVVGcFF6dEJRVU40UkN4VFFVRlBMRlZCUVZNc1IwRkJSeXhKUVVGSUxFVkJRVEJDTzBGQlEzaERMRk5CUVVzc1NVRkJTU3hoUVVGS0xFbEJRWEZDTEV0QlFURkNMRVZCUVdsRE8wRkJReTlDTEZWQlFVa3NVMEZCVXl4RlFVRlVMRU5CUkRKQ08wRkJSUzlDTEdGQlFVOHNjVUpCUVhGQ0xFbEJRWEpDTEVWQlFUSkNMR05CUVdNc1MwRkJaQ3hGUVVGeFFpeGpRVUZqTEZOQlFXUXNRMEZCZGtRc1EwRkdLMEk3TzBGQlNTOUNMRlZCUVVrc1kwRkJZeXhQUVVGa0xFTkJRWE5DTEVsQlFYUkNMRVZCUVRSQ0xFMUJRVFZDTEV0QlFYVkRMR05CUVdNc1MwRkJaQ3hEUVVGdlFpeExRVUZ3UWl4RFFVRXdRaXhKUVVFeFFpeEZRVUZuUXl4TlFVRm9ReXhEUVVGMlF5eEZRVUZuUmp0QlFVTnNSaXhsUVVGUExHTkJRV01zUlVGQlpDeERRVUZwUWl4TFFVRnFRaXhEUVVGMVFpeEpRVUYyUWl4RlFVRTJRaXhOUVVFM1FpeERRVUZRTEVOQlJHdEdPMDlCUVhCR08wdEJTa1k3TzBGQlUwRXNWVUZCVFN4SlFVRkpMRlZCUVVvc1EwRkJaU3hKUVVGbUxFTkJRVTRzUTBGV2QwTTdSMEZCYmtNc1EwRkVhVVE3UTBGQmJrUTdPMEZCWlZBc1UwRkJVeXhwUWtGQlZDeERRVUV5UWl4UFFVRXpRaXhGUVVFclF6dEJRVU0zUXl4TlFVRkpMRmxCUVZrc1JVRkJXaXhEUVVSNVF6czdRVUZITjBNc1QwRkJTU3hKUVVGSkxFbEJRVWtzUTBGQlNpeEZRVUZQTEVsQlFVa3NVVUZCVVN4TlFVRlNMRVZCUVdkQ0xFZEJRVzVETEVWQlFYVkRPMEZCUTNKRExGRkJRVWNzVVVGQlVTeERRVUZTTEdGQlFYTkNMRTFCUVUwc1VVRkJUaXhKUVVGclFpeFJRVUZSTEVOQlFWSXNSVUZCVnl4aFFVRllMRWxCUVRSQ0xFOUJRVThzUjBGQlVDeERRVUZYTEhWQ1FVRllMRU5CUVRWQ0xFVkJRV2RGTzBGQlEzcEhMR2RDUVVGVkxFbEJRVllzUTBGQlpTeERRVUZETEVOQlFVUXNSVUZCU1N4UlFVRlJMRU5CUVZJc1JVRkJWeXhoUVVGWUxFTkJRVzVDTEVWQlJIbEhPMHRCUVROSE8wZEJSRVk3TzBGQlRVRXNVMEZCVHl4VFFVRlFMRU5CVkRaRE8wTkJRUzlET3p0QlFWbEJMRk5CUVZNc2IwSkJRVlFzUTBGQk9FSXNTVUZCT1VJc1JVRkJiME1zUzBGQmNFTXNSVUZCTWtNc1UwRkJNME1zUlVGQmNVUTdRVUZEYmtRc1RVRkJSeXhMUVVGTExFMUJRVXdzUzBGQlowSXNTMEZCYUVJc1NVRkJlVUlzVlVGQlZTeE5RVUZXTEV0QlFYRkNMRU5CUVhKQ0xFVkJRWFZDTzBGQlEycEVMRmRCUVU4c1NVRkJVQ3hEUVVScFJEdEhRVUZ1UkRzN1FVRkpRU3hOUVVGSExFdEJRVXNzVFVGQlRDeEhRVUZqTEZWQlFWVXNUVUZCVml4SFFVRnRRaXhMUVVGcVF5eEZRVUYxUXp0QlFVTjRReXhYUVVGUExFbEJRVkFzUTBGRWQwTTdSMEZCTVVNN08wRkJTVUVzVFVGQlNTd3dRa0ZCTUVJc1VVRkJVU3hMUVVGTExFMUJRVXdzUTBGVVlUdEJRVlZ1UkN4TlFVRkpMRzlDUVVGdlFpeFZRVUZWTEUxQlFWWXNSMEZCYlVJc2RVSkJRVzVDTEVOQlZqSkNPenRCUVZsdVJDeE5RVUZKTEdsQ1FVRnBRaXhWUVVGVkxFdEJRVllzUTBGQlowSXNhVUpCUVdoQ0xFTkJRV3BDTEVOQldpdERPenRCUVdOdVJDeFBRVUZKTEVsQlFVa3NRMEZCUXl4TFFVRkVMRVZCUVZFc1MwRkJVaXhEUVVGS0xFbEJRWE5DTEdOQlFURkNMRVZCUVhsRE8wRkJRM1pETEZOQlFVc3NUVUZCVEN4RFFVRlpMRXRCUVZvc1JVRkJiVUlzUTBGQmJrSXNSVUZCYzBJc1MwRkJkRUlzUlVGRWRVTTdRVUZGZGtNc1VVRkJSeXhMUVVGTExFMUJRVXdzUzBGQlowSXNTMEZCYUVJc1JVRkJjMEk3UVVGRGRrSXNXVUZFZFVJN1MwRkJla0k3UjBGR1JqczdRVUZQUVN4VFFVRlBMRWxCUVZBc1EwRnlRbTFFTzBOQlFYSkVPenRCUVhkQ1FTeFBRVUZQTEZOQlFWTXNTMEZCVkN4RFFVRmxMRTlCUVdZc1JVRkJOa0lzU1VGQk4wSXNSVUZCZDBRc1VVRkJSU3hOUVVGTkxFbEJRVTRzUlVGQmQwSTdRVUZEZGtZc1RVRkJTU3hUUVVGVExFVkJRVlFzUTBGRWJVWTdRVUZGZGtZc1RVRkJTU3h0UWtGQmJVSXNWMEZCVnl4UFFVRllMRU5CUVc1Q0xFTkJSbTFHTzBGQlIzWkdMRTFCUVVrc2FVSkJRV2xDTEVsQlFXcENMRVZCUVhWQ0xFMUJRWFpDTEV0QlFXdERMRTFCUVUwc1MwRkJUaXhEUVVGWkxFbEJRVm9zUlVGQmEwSXNUVUZCYkVJc1EwRkJiRU1zUlVGQk5FUTdRVUZET1VRc1YwRkJUeXhOUVVGUUxFTkJSRGhFTzBkQlFXaEZMRTFCUlVzN1FVRkRTQ3hWUVVGTkxFbEJRVWtzVlVGQlNpeERRVUZsTEVsQlFXWXNRMEZCVGl4RFFVUkhPMGRCUmt3N1EwRklTenM3UVVGVlVDeFBRVUZQTEZOQlFWTXNZMEZCVkN4RFFVRjNRaXhQUVVGNFFpeEZRVUZ6UXl4SlFVRjBReXhGUVVGcFJTeFJRVUZGTEUxQlFVMHNTVUZCVGl4RlFVRjVRanRCUVVOcVJ5eE5RVUZITzBGQlEwUXNWMEZCVHl4TlFVRk5MRTlCUVU0c1JVRkJaU3hKUVVGbUxFVkJRWEZDTEV0QlFYSkNMRU5CUVZBc1EwRkVRenRIUVVGSUxFTkJSVU1zVDBGQlRTeERRVUZPTEVWQlFWRTdRVUZEVUN4UlFVRkhMR0ZCUVdFc1ZVRkJZaXhKUVVFeVFpeEZRVUZGTEU5QlFVWXNRMEZCVlN4VlFVRldMRU5CUVhGQ0xHVkJRWEpDTEVOQlFUTkNMRVZCUVdsRk8wRkJRMnhGTEdGQlFVOHNTVUZCVUN4RFFVUnJSVHRMUVVGd1JUczdRVUZKUVN4VlFVRk5MRU5CUVU0c1EwRk1UenRIUVVGU08wTkJTRWs3TzBGQldWQXNUMEZCVHl4VFFVRlRMRlZCUVZRc1EwRkJiMElzVlVGQmNFSXNSVUZCTkVNc1QwRkJOVU1zUlVGQk1FUXNSMEZCTVVRc1JVRkJlVVlzVVVGQlJTeE5RVUZOTEVsQlFVNHNSVUZCZDBJN1FVRkRlRWdzVFVGQlNTeE5RVUZOTEVWQlFVNHNRMEZFYjBnN08wRkJSM2hJTEU5QlFVa3NTVUZCU1N4SlFVRktMRWxCUVZrc1ZVRkJhRUlzUlVGQk1rSTdRVUZEZWtJc1VVRkJSenRCUVVORUxGVkJRVWtzVTBGQlV5eEpRVUZKTEV0QlFVb3NRMEZCVlN4SlFVRldMRVZCUVdkQ0xFMUJRVTBzVDBGQlRpeEZRVUZsTEVsQlFXWXNSVUZCY1VJc1MwRkJja0lzUTBGQmFFSXNRMEZCVkN4RFFVUklPMEZCUlVRc1dVRkJUU3hKUVVGSkxFMUJRVW9zUTBGQlZ5eE5RVUZZTEVOQlFVNHNRMEZHUXp0TFFVRklMRU5CUjBNc1QwRkJUU3hEUVVGT0xFVkJRVkU3UVVGRFZDeFZRVUZITEVWQlFVVXNZVUZCWVN4VlFVRmlMRU5CUVVZc1JVRkJNa0k3UVVGRE1VSXNZMEZCVFN4RFFVRk9MRU5CUkRCQ08wOUJRVGxDTzB0QlJFTTdSMEZLU0RzN1FVRlhRU3hUUVVGUExFZEJRVkFzUTBGa2QwZzdRMEZCYmtnaUxDSm1hV3hsSWpvaWJHbGlMMk52Y21VdmNHRjBkR1Z5Ym5NdlpHVm1iV0YwWTJndWFuTWlMQ0p6YjNWeVkyVnpRMjl1ZEdWdWRDSTZXeUl2S2lCQVpteHZkeUFxTDF4dVhHNXBiWEJ2Y25RZ2V5QmlkV2xzWkUxaGRHTm9JSDBnWm5KdmJTQmNJaTR2YldGMFkyaGNJanRjYm1sdGNHOXlkQ0FxSUdGeklGUjVjR1Z6SUdaeWIyMGdYQ0l1TDNSNWNHVnpYQ0k3WEc1Y2JtVjRjRzl5ZENCamJHRnpjeUJOWVhSamFFVnljbTl5SUdWNGRHVnVaSE1nUlhKeWIzSWdlMXh1SUNCamIyNXpkSEoxWTNSdmNpaGhjbWM2SUdGdWVTa2dlMXh1SUNBZ0lITjFjR1Z5S0NrN1hHNWNiaUFnSUNCcFppaDBlWEJsYjJZZ1lYSm5JRDA5UFNBbmMzbHRZbTlzSnlsN1hHNGdJQ0FnSUNCMGFHbHpMbTFsYzNOaFoyVWdQU0FuVG04Z2JXRjBZMmdnWm05eU9pQW5JQ3NnWVhKbkxuUnZVM1J5YVc1bktDazdYRzRnSUNBZ2ZTQmxiSE5sSUdsbUtFRnljbUY1TG1selFYSnlZWGtvWVhKbktTbDdYRzRnSUNBZ0lDQnNaWFFnYldGd2NHVmtWbUZzZFdWeklEMGdZWEpuTG0xaGNDZ29lQ2tnUFQ0Z2VDNTBiMU4wY21sdVp5Z3BLVHRjYmlBZ0lDQWdJSFJvYVhNdWJXVnpjMkZuWlNBOUlDZE9ieUJ0WVhSamFDQm1iM0k2SUNjZ0t5QnRZWEJ3WldSV1lXeDFaWE03WEc0Z0lDQWdmV1ZzYzJWN1hHNGdJQ0FnSUNCMGFHbHpMbTFsYzNOaFoyVWdQU0FuVG04Z2JXRjBZMmdnWm05eU9pQW5JQ3NnWVhKbk8xeHVJQ0FnSUgxY2JseHVJQ0FnSUhSb2FYTXVjM1JoWTJzZ1BTQW9ibVYzSUVWeWNtOXlLQ2twTG5OMFlXTnJPMXh1SUNBZ0lIUm9hWE11Ym1GdFpTQTlJSFJvYVhNdVkyOXVjM1J5ZFdOMGIzSXVibUZ0WlR0Y2JpQWdmVnh1ZlZ4dVhHNWNibVY0Y0c5eWRDQmpiR0Z6Y3lCRFlYTmxJSHRjYmlBZ2NHRjBkR1Z5YmpvZ1JuVnVZM1JwYjI0N1hHNGdJR1p1T2lCR2RXNWpkR2x2Ymp0Y2JpQWdaM1ZoY21RNklFWjFibU4wYVc5dU8xeHVJQ0JoY21sMGVUb2diblZ0WW1WeU8xeHVJQ0J2Y0hScGIyNWhiSE02SUVGeWNtRjVQR0Z1ZVQ0N1hHNWNiaUFnWTI5dWMzUnlkV04wYjNJb2NHRjBkR1Z5YmpvZ1FYSnlZWGs4WVc1NVBpd2dabTQ2SUVaMWJtTjBhVzl1TENCbmRXRnlaRG9nUm5WdVkzUnBiMjRnUFNBb0tTQTlQaUIwY25WbEtYdGNiaUFnSUNCMGFHbHpMbkJoZEhSbGNtNGdQU0JpZFdsc1pFMWhkR05vS0hCaGRIUmxjbTRwTzF4dUlDQWdJSFJvYVhNdVlYSnBkSGtnUFNCd1lYUjBaWEp1TG14bGJtZDBhRHRjYmlBZ0lDQjBhR2x6TG05d2RHbHZibUZzY3lBOUlHZGxkRTl3ZEdsdmJtRnNWbUZzZFdWektIQmhkSFJsY200cE8xeHVJQ0FnSUhSb2FYTXVabTRnUFNCbWJqdGNiaUFnSUNCMGFHbHpMbWQxWVhKa0lEMGdaM1ZoY21RN1hHNGdJSDFjYm4xY2JseHVaWGh3YjNKMElHWjFibU4wYVc5dUlHMWhhMlZmWTJGelpTaHdZWFIwWlhKdU9pQkJjbkpoZVR4aGJuaytMQ0JtYmpvZ1JuVnVZM1JwYjI0c0lHZDFZWEprT2lCR2RXNWpkR2x2YmlBOUlDZ3BJRDArSUhSeWRXVXBPaUJEWVhObElIdGNiaUFnY21WMGRYSnVJRzVsZHlCRFlYTmxLSEJoZEhSbGNtNHNJR1p1TENCbmRXRnlaQ2s3WEc1OVhHNWNibVY0Y0c5eWRDQm1kVzVqZEdsdmJpQmtaV1p0WVhSamFDZ3VMaTVqWVhObGN6b2dRWEp5WVhrOFEyRnpaVDRwT2lCR2RXNWpkR2x2YmlCN1hHNGdJSEpsZEhWeWJpQm1kVzVqZEdsdmJpZ3VMaTVoY21kek9pQkJjbkpoZVR4aGJuaytLVG9nWVc1NUlIdGNiaUFnSUNCbWIzSWdLR3hsZENCd2NtOWpaWE56WldSRFlYTmxJRzltSUdOaGMyVnpLU0I3WEc0Z0lDQWdJQ0JzWlhRZ2NtVnpkV3gwSUQwZ1cxMDdYRzRnSUNBZ0lDQmhjbWR6SUQwZ1ptbHNiRWx1VDNCMGFXOXVZV3hXWVd4MVpYTW9ZWEpuY3l3Z2NISnZZMlZ6YzJWa1EyRnpaUzVoY21sMGVTd2djSEp2WTJWemMyVmtRMkZ6WlM1dmNIUnBiMjVoYkhNcE8xeHVYRzRnSUNBZ0lDQnBaaUFvY0hKdlkyVnpjMlZrUTJGelpTNXdZWFIwWlhKdUtHRnlaM01zSUhKbGMzVnNkQ2tnSmlZZ2NISnZZMlZ6YzJWa1EyRnpaUzVuZFdGeVpDNWhjSEJzZVNoMGFHbHpMQ0J5WlhOMWJIUXBLU0I3WEc0Z0lDQWdJQ0FnSUhKbGRIVnliaUJ3Y205alpYTnpaV1JEWVhObExtWnVMbUZ3Y0d4NUtIUm9hWE1zSUhKbGMzVnNkQ2s3WEc0Z0lDQWdJQ0I5WEc0Z0lDQWdmVnh1WEc0Z0lDQWdkR2h5YjNjZ2JtVjNJRTFoZEdOb1JYSnliM0lvWVhKbmN5azdYRzRnSUgwN1hHNTlYRzVjYm1aMWJtTjBhVzl1SUdkbGRFOXdkR2x2Ym1Gc1ZtRnNkV1Z6S0hCaGRIUmxjbTQ2SUVGeWNtRjVQR0Z1ZVQ0cGUxeHVJQ0JzWlhRZ2IzQjBhVzl1WVd4eklEMGdXMTA3WEc1Y2JpQWdabTl5S0d4bGRDQnBJRDBnTURzZ2FTQThJSEJoZEhSbGNtNHViR1Z1WjNSb095QnBLeXNwZTF4dUlDQWdJR2xtS0hCaGRIUmxjbTViYVYwZ2FXNXpkR0Z1WTJWdlppQlVlWEJsY3k1V1lYSnBZV0pzWlNBbUppQndZWFIwWlhKdVcybGRMbVJsWm1GMWJIUmZkbUZzZFdVZ0lUMGdVM2x0WW05c0xtWnZjaWhjSW1Wc2FYaHBjbk5qY21sd2RDNXViMTkyWVd4MVpWd2lLU2w3WEc0Z0lDQWdJQ0J2Y0hScGIyNWhiSE11Y0hWemFDaGJhU3dnY0dGMGRHVnlibHRwWFM1a1pXWmhkV3gwWDNaaGJIVmxYU2s3WEc0Z0lDQWdmVnh1SUNCOVhHNWNiaUFnY21WMGRYSnVJRzl3ZEdsdmJtRnNjenRjYm4xY2JseHVablZ1WTNScGIyNGdabWxzYkVsdVQzQjBhVzl1WVd4V1lXeDFaWE1vWVhKbmN5d2dZWEpwZEhrc0lHOXdkR2x2Ym1Gc2N5bDdYRzRnSUdsbUtHRnlaM011YkdWdVozUm9JRDA5UFNCaGNtbDBlU0I4ZkNCdmNIUnBiMjVoYkhNdWJHVnVaM1JvSUQwOVBTQXdLWHRjYmlBZ0lDQnlaWFIxY200Z1lYSm5jenRjYmlBZ2ZWeHVYRzRnSUdsbUtHRnlaM011YkdWdVozUm9JQ3NnYjNCMGFXOXVZV3h6TG14bGJtZDBhQ0E4SUdGeWFYUjVLWHRjYmlBZ0lDQnlaWFIxY200Z1lYSm5jenRjYmlBZ2ZWeHVYRzRnSUd4bGRDQnVkVzFpWlhKUFprOXdkR2x2Ym1Gc2MxUnZSbWxzYkNBOUlHRnlhWFI1SUMwZ1lYSm5jeTVzWlc1bmRHZzdYRzRnSUd4bGRDQnZjSFJwYjI1aGJITlViMUpsYlc5MlpTQTlJRzl3ZEdsdmJtRnNjeTVzWlc1bmRHZ2dMU0J1ZFcxaVpYSlBaazl3ZEdsdmJtRnNjMVJ2Um1sc2JEdGNibHh1SUNCc1pYUWdiM0IwYVc5dVlXeHpWRzlWYzJVZ1BTQnZjSFJwYjI1aGJITXVjMnhwWTJVb2IzQjBhVzl1WVd4elZHOVNaVzF2ZG1VcE8xeHVYRzRnSUdadmNpaHNaWFFnVzJsdVpHVjRMQ0IyWVd4MVpWMGdiMllnYjNCMGFXOXVZV3h6Vkc5VmMyVXBlMXh1SUNBZ0lHRnlaM011YzNCc2FXTmxLR2x1WkdWNExDQXdMQ0IyWVd4MVpTazdYRzRnSUNBZ2FXWW9ZWEpuY3k1c1pXNW5kR2dnUFQwOUlHRnlhWFI1S1h0Y2JpQWdJQ0FnSUdKeVpXRnJPMXh1SUNBZ0lIMWNiaUFnZlZ4dVhHNGdJSEpsZEhWeWJpQmhjbWR6TzF4dWZWeHVYRzVsZUhCdmNuUWdablZ1WTNScGIyNGdiV0YwWTJnb2NHRjBkR1Z5YmpvZ1lXNTVMQ0JsZUhCeU9pQmhibmtzSUdkMVlYSmtPaUJHZFc1amRHbHZiaUE5SUNncElEMCtJSFJ5ZFdVcE9pQkJjbkpoZVR4aGJuaytJSHRjYmlBZ2JHVjBJSEpsYzNWc2RDQTlJRnRkTzF4dUlDQnNaWFFnY0hKdlkyVnpjMlZrVUdGMGRHVnliaUE5SUdKMWFXeGtUV0YwWTJnb2NHRjBkR1Z5YmlrN1hHNGdJR2xtSUNod2NtOWpaWE56WldSUVlYUjBaWEp1S0dWNGNISXNJSEpsYzNWc2RDa2dKaVlnWjNWaGNtUXVZWEJ3Ykhrb2RHaHBjeXdnY21WemRXeDBLU2w3WEc0Z0lDQWdjbVYwZFhKdUlISmxjM1ZzZER0Y2JpQWdmV1ZzYzJWN1hHNGdJQ0FnZEdoeWIzY2dibVYzSUUxaGRHTm9SWEp5YjNJb1pYaHdjaWs3WEc0Z0lIMWNibjFjYmx4dVpYaHdiM0owSUdaMWJtTjBhVzl1SUcxaGRHTm9YMjV2WDNSb2NtOTNLSEJoZEhSbGNtNDZJR0Z1ZVN3Z1pYaHdjam9nWVc1NUxDQm5kV0Z5WkRvZ1JuVnVZM1JwYjI0Z1BTQW9LU0E5UGlCMGNuVmxLVG9nUDBGeWNtRjVQR0Z1ZVQ0Z2UxeHVJQ0IwY25sN1hHNGdJQ0FnY21WMGRYSnVJRzFoZEdOb0tIQmhkSFJsY200c0lHVjRjSElzSUdkMVlYSmtLVHRjYmlBZ2ZXTmhkR05vS0dVcGUxeHVJQ0FnSUdsbUtHVWdhVzV6ZEdGdVkyVnZaaUJOWVhSamFFVnljbTl5SUh4OElHVXViV1Z6YzJGblpTNXpkR0Z5ZEhOWGFYUm9LQ2RPYnlCdFlYUmphQ0JtYjNJNkp5a3BlMXh1SUNBZ0lDQWdjbVYwZFhKdUlHNTFiR3c3WEc0Z0lDQWdmVnh1WEc0Z0lDQWdkR2h5YjNjZ1pUdGNiaUFnZlZ4dWZWeHVYRzVsZUhCdmNuUWdablZ1WTNScGIyNGdjR0YwZEdWeWJrMWhjQ2hqYjJ4c1pXTjBhVzl1T2lCQmNuSmhlVHhoYm5rK0xDQndZWFIwWlhKdU9pQmhibmtzSUdaMWJqb2dSblZ1WTNScGIyNHNJR2QxWVhKa09pQkdkVzVqZEdsdmJpQTlJQ2dwSUQwK0lIUnlkV1VwT2lCQmNuSmhlVHhoYm5rK0lIdGNiaUFnYkdWMElISmxkQ0E5SUZ0ZE8xeHVYRzRnSUdadmNpaHNaWFFnWld4bGJTQnZaaUJqYjJ4c1pXTjBhVzl1S1h0Y2JpQWdJQ0IwY25sN1hHNGdJQ0FnSUNCc1pYUWdjbVZ6ZFd4MElEMGdablZ1TG1Gd2NHeDVLSFJvYVhNc0lHMWhkR05vS0hCaGRIUmxjbTRzSUdWc1pXMHNJR2QxWVhKa0tTazdYRzRnSUNBZ0lDQnlaWFFnUFNCeVpYUXVZMjl1WTJGMEtISmxjM1ZzZENrN1hHNGdJQ0FnZldOaGRHTm9LR1VwZTF4dUlDQWdJR2xtS0NFb1pTQnBibk4wWVc1alpXOW1JRTFoZEdOb1JYSnliM0lwS1h0Y2JpQWdJQ0FnSUNBZ2RHaHliM2NnWlR0Y2JpQWdJQ0FnSUgxY2JpQWdJQ0I5WEc0Z0lIMWNibHh1SUNCeVpYUjFjbTRnY21WME8xeHVmVnh1SWwwc0luTnZkWEpqWlZKdmIzUWlPaUl2YzI5MWNtTmxMeUo5XG4iLCJcblxuaW1wb3J0IHsgZGVmbWF0Y2gsIG1hdGNoLCBNYXRjaEVycm9yLCBtYXRjaF9ub190aHJvdywgcGF0dGVybk1hcCwgQ2FzZSwgbWFrZV9jYXNlIH0gZnJvbSBcIi4vcGF0dGVybnMvZGVmbWF0Y2hcIjtcbmltcG9ydCB7IHZhcmlhYmxlLCB3aWxkY2FyZCwgc3RhcnRzV2l0aCwgY2FwdHVyZSwgaGVhZFRhaWwsIHR5cGUsIGJvdW5kLCBiaXRTdHJpbmdNYXRjaCB9IGZyb20gXCIuL3BhdHRlcm5zL3R5cGVzXCI7XG5cbmV4cG9ydCBkZWZhdWx0IHtcbiAgZGVmbWF0Y2gsIG1hdGNoLCBNYXRjaEVycm9yLCBtYXRjaF9ub190aHJvdyxcbiAgdmFyaWFibGUsIHdpbGRjYXJkLCBzdGFydHNXaXRoLFxuICBjYXB0dXJlLCBoZWFkVGFpbCwgdHlwZSwgYm91bmQsIENhc2UsIG1ha2VfY2FzZSwgYml0U3RyaW5nTWF0Y2hcbn07XG4vLyMgc291cmNlTWFwcGluZ1VSTD1kYXRhOmFwcGxpY2F0aW9uL2pzb247YmFzZTY0LGV5SjJaWEp6YVc5dUlqb3pMQ0p6YjNWeVkyVnpJanBiSW14cFlpOWpiM0psTDNCaGRIUmxjbTV6TG1weklsMHNJbTVoYldWeklqcGJYU3dpYldGd2NHbHVaM01pT2lJN08wRkJSVUVzVTBGQlV5eFJRVUZVTEVWQlFXMUNMRXRCUVc1Q0xFVkJRVEJDTEZWQlFURkNMRVZCUVhORExHTkJRWFJETEVWQlFYTkVMRlZCUVhSRUxFVkJRV3RGTEVsQlFXeEZMRVZCUVhkRkxGTkJRWGhGTEZGQlFYbEdMSEZDUVVGNlJqdEJRVU5CTEZOQlFWTXNVVUZCVkN4RlFVRnRRaXhSUVVGdVFpeEZRVUUyUWl4VlFVRTNRaXhGUVVGNVF5eFBRVUY2UXl4RlFVRnJSQ3hSUVVGc1JDeEZRVUUwUkN4SlFVRTFSQ3hGUVVGclJTeExRVUZzUlN4RlFVRjVSU3hqUVVGNlJTeFJRVUVyUml4clFrRkJMMFk3TzBGQlIwRXNaVUZCWlR0QlFVTmlMRlZCUkdFc1JVRkRTQ3hMUVVSSExFVkJRMGtzVlVGRVNpeEZRVU5uUWl4alFVUm9RanRCUVVWaUxGVkJSbUVzUlVGRlNDeFJRVVpITEVWQlJVOHNWVUZHVUR0QlFVZGlMRk5CU0dFc1JVRkhTaXhSUVVoSkxFVkJSMDBzU1VGSVRpeEZRVWRaTEV0QlNGb3NSVUZIYlVJc1NVRklia0lzUlVGSGVVSXNVMEZJZWtJc1JVRkhiME1zWTBGSWNFTTdRMEZCWmlJc0ltWnBiR1VpT2lKc2FXSXZZMjl5WlM5d1lYUjBaWEp1Y3k1cWN5SXNJbk52ZFhKalpYTkRiMjUwWlc1MElqcGJJaThxSUVCbWJHOTNJQ292WEc1Y2JtbHRjRzl5ZENCN0lHUmxabTFoZEdOb0xDQnRZWFJqYUN3Z1RXRjBZMmhGY25KdmNpd2diV0YwWTJoZmJtOWZkR2h5YjNjc0lIQmhkSFJsY201TllYQXNJRU5oYzJVc0lHMWhhMlZmWTJGelpTQjlJR1p5YjIwZ1hDSXVMM0JoZEhSbGNtNXpMMlJsWm0xaGRHTm9YQ0k3WEc1cGJYQnZjblFnZXlCMllYSnBZV0pzWlN3Z2QybHNaR05oY21Rc0lITjBZWEowYzFkcGRHZ3NJR05oY0hSMWNtVXNJR2hsWVdSVVlXbHNMQ0IwZVhCbExDQmliM1Z1WkN3Z1ltbDBVM1J5YVc1blRXRjBZMmdnZlNCbWNtOXRJRndpTGk5d1lYUjBaWEp1Y3k5MGVYQmxjMXdpTzF4dVhHNWNibVY0Y0c5eWRDQmtaV1poZFd4MElIdGNiaUFnWkdWbWJXRjBZMmdzSUcxaGRHTm9MQ0JOWVhSamFFVnljbTl5TENCdFlYUmphRjl1YjE5MGFISnZkeXhjYmlBZ2RtRnlhV0ZpYkdVc0lIZHBiR1JqWVhKa0xDQnpkR0Z5ZEhOWGFYUm9MRnh1SUNCallYQjBkWEpsTENCb1pXRmtWR0ZwYkN3Z2RIbHdaU3dnWW05MWJtUXNJRU5oYzJVc0lHMWhhMlZmWTJGelpTd2dZbWwwVTNSeWFXNW5UV0YwWTJoY2JuMDdYRzRpWFN3aWMyOTFjbU5sVW05dmRDSTZJaTl6YjNWeVkyVXZJbjA9XG4iLCJpbXBvcnQgeyBJbnRlZ2VyLCBGbG9hdCB9IGZyb20gJy4vcHJpbWl0aXZlcyc7XG5cbi8vaHR0cHM6Ly9naXRodWIuY29tL2FpcnBvcnR5aC9wcm90b21vcnBoaXNtXG5jbGFzcyBQcm90b2NvbCB7XG4gIGNvbnN0cnVjdG9yKHNwZWMpIHtcbiAgICB0aGlzLnJlZ2lzdHJ5ID0gbmV3IE1hcCgpO1xuICAgIHRoaXMuZmFsbGJhY2sgPSBudWxsO1xuXG4gICAgZm9yIChsZXQgZnVuTmFtZSBpbiBzcGVjKSB7XG4gICAgICB0aGlzW2Z1bk5hbWVdID0gY3JlYXRlRnVuKGZ1bk5hbWUpLmJpbmQodGhpcyk7XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gY3JlYXRlRnVuKGZ1bk5hbWUpIHtcblxuICAgICAgcmV0dXJuIGZ1bmN0aW9uICguLi5hcmdzKSB7XG4gICAgICAgIGxldCB0aGluZyA9IGFyZ3NbMF07XG4gICAgICAgIGxldCBmdW4gPSBudWxsO1xuXG4gICAgICAgIGlmIChOdW1iZXIuaXNJbnRlZ2VyKHRoaW5nKSAmJiB0aGlzLmhhc0ltcGxlbWVudGF0aW9uKEludGVnZXIpKSB7XG4gICAgICAgICAgZnVuID0gdGhpcy5yZWdpc3RyeS5nZXQoSW50ZWdlcilbZnVuTmFtZV07XG4gICAgICAgIH0gZWxzZSBpZiAodHlwZW9mIHRoaW5nID09PSBcIm51bWJlclwiICYmICFOdW1iZXIuaXNJbnRlZ2VyKHRoaW5nKSAmJiB0aGlzLmhhc0ltcGxlbWVudGF0aW9uKEZsb2F0KSkge1xuICAgICAgICAgIGZ1biA9IHRoaXMucmVnaXN0cnkuZ2V0KEZsb2F0KVtmdW5OYW1lXTtcbiAgICAgICAgfSBlbHNlIGlmICh0aGlzLmhhc0ltcGxlbWVudGF0aW9uKHRoaW5nKSkge1xuICAgICAgICAgIGZ1biA9IHRoaXMucmVnaXN0cnkuZ2V0KHRoaW5nLmNvbnN0cnVjdG9yKVtmdW5OYW1lXTtcbiAgICAgICAgfSBlbHNlIGlmICh0aGlzLmZhbGxiYWNrKSB7XG4gICAgICAgICAgZnVuID0gdGhpcy5mYWxsYmFja1tmdW5OYW1lXTtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmIChmdW4gIT0gbnVsbCkge1xuICAgICAgICAgIGxldCByZXR2YWwgPSBmdW4uYXBwbHkodGhpcywgYXJncyk7XG4gICAgICAgICAgcmV0dXJuIHJldHZhbDtcbiAgICAgICAgfVxuXG4gICAgICAgIHRocm93IG5ldyBFcnJvcihcIk5vIGltcGxlbWVudGF0aW9uIGZvdW5kIGZvciBcIiArIHRoaW5nKTtcbiAgICAgIH07XG4gICAgfVxuICB9XG5cbiAgaW1wbGVtZW50YXRpb24odHlwZSwgaW1wbGVtZW50YXRpb24pIHtcbiAgICBpZiAodHlwZSA9PT0gbnVsbCkge1xuICAgICAgdGhpcy5mYWxsYmFjayA9IGltcGxlbWVudGF0aW9uO1xuICAgIH0gZWxzZSB7XG4gICAgICB0aGlzLnJlZ2lzdHJ5LnNldCh0eXBlLCBpbXBsZW1lbnRhdGlvbik7XG4gICAgfVxuICB9XG5cbiAgaGFzSW1wbGVtZW50YXRpb24odGhpbmcpIHtcbiAgICBpZiAodGhpbmcgPT09IEludGVnZXIgfHwgdGhpbmcgPT09IEZsb2F0KSB7XG4gICAgICByZXR1cm4gdGhpcy5yZWdpc3RyeS5oYXModGhpbmcpO1xuICAgIH1cblxuICAgIHJldHVybiB0aGlzLnJlZ2lzdHJ5Lmhhcyh0aGluZy5jb25zdHJ1Y3Rvcik7XG4gIH1cbn1cblxuZXhwb3J0IGRlZmF1bHQgUHJvdG9jb2w7XG4vLyMgc291cmNlTWFwcGluZ1VSTD1kYXRhOmFwcGxpY2F0aW9uL2pzb247YmFzZTY0LGV5SjJaWEp6YVc5dUlqb3pMQ0p6YjNWeVkyVnpJanBiSW14cFlpOWpiM0psTDNCeWIzUnZZMjlzTG1weklsMHNJbTVoYldWeklqcGJYU3dpYldGd2NHbHVaM01pT2lKQlFVRkJMRk5CUVZNc1QwRkJWQ3hGUVVGclFpeExRVUZzUWl4UlFVRXJRaXhqUVVFdlFqczdPMEZCUjBFc1RVRkJUU3hSUVVGT0xFTkJRV003UVVGRFdpeGpRVUZaTEVsQlFWb3NSVUZCYVVJN1FVRkRaaXhUUVVGTExGRkJRVXdzUjBGQlowSXNTVUZCU1N4SFFVRktMRVZCUVdoQ0xFTkJSR1U3UVVGRlppeFRRVUZMTEZGQlFVd3NSMEZCWjBJc1NVRkJhRUlzUTBGR1pUczdRVUZKWml4VFFVRkxMRWxCUVVrc1QwRkJTaXhKUVVGbExFbEJRWEJDTEVWQlFYbENPMEZCUTNaQ0xGZEJRVXNzVDBGQlRDeEpRVUZuUWl4VlFVRlZMRTlCUVZZc1JVRkJiVUlzU1VGQmJrSXNRMEZCZDBJc1NVRkJlRUlzUTBGQmFFSXNRMEZFZFVJN1MwRkJla0k3TzBGQlNVRXNZVUZCVXl4VFFVRlVMRU5CUVcxQ0xFOUJRVzVDTEVWQlFUSkNPenRCUVVWNlFpeGhRVUZQTEZWQlFWTXNSMEZCUnl4SlFVRklMRVZCUVZNN1FVRkRka0lzV1VGQlNTeFJRVUZSTEV0QlFVc3NRMEZCVEN4RFFVRlNMRU5CUkcxQ08wRkJSWFpDTEZsQlFVa3NUVUZCVFN4SlFVRk9MRU5CUm0xQ096dEJRVWwyUWl4WlFVRkhMRTlCUVU4c1UwRkJVQ3hEUVVGcFFpeExRVUZxUWl4TFFVRXlRaXhMUVVGTExHbENRVUZNTEVOQlFYVkNMRTlCUVhaQ0xFTkJRVE5DTEVWQlFUSkVPMEZCUXpWRUxHZENRVUZOTEV0QlFVc3NVVUZCVEN4RFFVRmpMRWRCUVdRc1EwRkJhMElzVDBGQmJFSXNSVUZCTWtJc1QwRkJNMElzUTBGQlRpeERRVVEwUkR0VFFVRTVSQ3hOUVVWTkxFbEJRVWNzVDBGQlR5eExRVUZRTEV0QlFXbENMRkZCUVdwQ0xFbEJRVFpDTEVOQlFVTXNUMEZCVHl4VFFVRlFMRU5CUVdsQ0xFdEJRV3BDTEVOQlFVUXNTVUZCTkVJc1MwRkJTeXhwUWtGQlRDeERRVUYxUWl4TFFVRjJRaXhEUVVGNlJDeEZRVUYxUmp0QlFVTTVSaXhuUWtGQlRTeExRVUZMTEZGQlFVd3NRMEZCWXl4SFFVRmtMRU5CUVd0Q0xFdEJRV3hDTEVWQlFYbENMRTlCUVhwQ0xFTkJRVTRzUTBGRU9FWTdVMEZCTVVZc1RVRkZRU3hKUVVGSExFdEJRVXNzYVVKQlFVd3NRMEZCZFVJc1MwRkJka0lzUTBGQlNDeEZRVUZwUXp0QlFVTnlReXhuUWtGQlRTeExRVUZMTEZGQlFVd3NRMEZCWXl4SFFVRmtMRU5CUVd0Q0xFMUJRVTBzVjBGQlRpeERRVUZzUWl4RFFVRnhReXhQUVVGeVF5eERRVUZPTEVOQlJIRkRPMU5CUVdwRExFMUJSVUVzU1VGQlJ5eExRVUZMTEZGQlFVd3NSVUZCWXp0QlFVTnlRaXhuUWtGQlRTeExRVUZMTEZGQlFVd3NRMEZCWXl4UFFVRmtMRU5CUVU0c1EwRkVjVUk3VTBGQmFrSTdPMEZCU1U0c1dVRkJSeXhQUVVGUExFbEJRVkFzUlVGQldUdEJRVU5pTEdOQlFVa3NVMEZCVXl4SlFVRkpMRXRCUVVvc1EwRkJWU3hKUVVGV0xFVkJRV2RDTEVsQlFXaENMRU5CUVZRc1EwRkVVenRCUVVWaUxHbENRVUZQTEUxQlFWQXNRMEZHWVR0VFFVRm1PenRCUVV0QkxHTkJRVTBzU1VGQlNTeExRVUZLTEVOQlFWVXNhVU5CUVdsRExFdEJRV3BETEVOQlFXaENMRU5CYmtKMVFqdFBRVUZzUWl4RFFVWnJRanRMUVVFelFqdEhRVkpHT3p0QlFXdERRU3hwUWtGQlpTeEpRVUZtTEVWQlFYRkNMR05CUVhKQ0xFVkJRVzlETzBGQlEyeERMRkZCUVVjc1UwRkJVeXhKUVVGVUxFVkJRV003UVVGRFppeFhRVUZMTEZGQlFVd3NSMEZCWjBJc1kwRkJhRUlzUTBGRVpUdExRVUZxUWl4TlFVVkxPMEZCUTBnc1YwRkJTeXhSUVVGTUxFTkJRV01zUjBGQlpDeERRVUZyUWl4SlFVRnNRaXhGUVVGM1FpeGpRVUY0UWl4RlFVUkhPMHRCUmt3N1IwRkVSanM3UVVGUlFTeHZRa0ZCYTBJc1MwRkJiRUlzUlVGQmVVSTdRVUZEZGtJc1VVRkJTU3hWUVVGVkxFOUJRVllzU1VGQmNVSXNWVUZCVlN4TFFVRldMRVZCUVdkQ08wRkJRM1pETEdGQlFVOHNTMEZCU3l4UlFVRk1MRU5CUVdNc1IwRkJaQ3hEUVVGclFpeExRVUZzUWl4RFFVRlFMRU5CUkhWRE8wdEJRWHBET3p0QlFVbEJMRmRCUVU4c1MwRkJTeXhSUVVGTUxFTkJRV01zUjBGQlpDeERRVUZyUWl4TlFVRk5MRmRCUVU0c1EwRkJla0lzUTBGTWRVSTdSMEZCZWtJN1EwRXpRMFk3TzBGQmNVUkJMR1ZCUVdVc1VVRkJaaUlzSW1acGJHVWlPaUpzYVdJdlkyOXlaUzl3Y205MGIyTnZiQzVxY3lJc0luTnZkWEpqWlhORGIyNTBaVzUwSWpwYkltbHRjRzl5ZENCN0lFbHVkR1ZuWlhJc0lFWnNiMkYwSUgwZ1puSnZiU0FuTGk5d2NtbHRhWFJwZG1Wekp6dGNibHh1THk5b2RIUndjem92TDJkcGRHaDFZaTVqYjIwdllXbHljRzl5ZEhsb0wzQnliM1J2Ylc5eWNHaHBjMjFjYm1Oc1lYTnpJRkJ5YjNSdlkyOXNlMXh1SUNCamIyNXpkSEoxWTNSdmNpaHpjR1ZqS1h0Y2JpQWdJQ0IwYUdsekxuSmxaMmx6ZEhKNUlEMGdibVYzSUUxaGNDZ3BPMXh1SUNBZ0lIUm9hWE11Wm1Gc2JHSmhZMnNnUFNCdWRXeHNPMXh1WEc0Z0lDQWdabTl5SUNoc1pYUWdablZ1VG1GdFpTQnBiaUJ6Y0dWaktYdGNiaUFnSUNBZ0lIUm9hWE5iWm5WdVRtRnRaVjBnUFNCamNtVmhkR1ZHZFc0b1puVnVUbUZ0WlNrdVltbHVaQ2gwYUdsektUdGNiaUFnSUNCOVhHNWNiaUFnSUNCbWRXNWpkR2x2YmlCamNtVmhkR1ZHZFc0b1puVnVUbUZ0WlNsN1hHNWNiaUFnSUNBZ0lISmxkSFZ5YmlCbWRXNWpkR2x2YmlndUxpNWhjbWR6S1NCN1hHNGdJQ0FnSUNBZ0lHeGxkQ0IwYUdsdVp5QTlJR0Z5WjNOYk1GMDdYRzRnSUNBZ0lDQWdJR3hsZENCbWRXNGdQU0J1ZFd4c08xeHVYRzRnSUNBZ0lDQWdJR2xtS0U1MWJXSmxjaTVwYzBsdWRHVm5aWElvZEdocGJtY3BJQ1ltSUhSb2FYTXVhR0Z6U1cxd2JHVnRaVzUwWVhScGIyNG9TVzUwWldkbGNpa3BlMXh1SUNBZ0lDQWdJQ0FnSUdaMWJpQTlJSFJvYVhNdWNtVm5hWE4wY25rdVoyVjBLRWx1ZEdWblpYSXBXMloxYms1aGJXVmRPMXh1SUNBZ0lDQWdJQ0I5Wld4elpTQnBaaWgwZVhCbGIyWWdkR2hwYm1jZ1BUMDlJRndpYm5WdFltVnlYQ0lnSmlZZ0lVNTFiV0psY2k1cGMwbHVkR1ZuWlhJb2RHaHBibWNwSUNZbUlIUm9hWE11YUdGelNXMXdiR1Z0Wlc1MFlYUnBiMjRvUm14dllYUXBLWHRjYmlBZ0lDQWdJQ0FnSUNCbWRXNGdQU0IwYUdsekxuSmxaMmx6ZEhKNUxtZGxkQ2hHYkc5aGRDbGJablZ1VG1GdFpWMDdYRzRnSUNBZ0lDQWdJSDFsYkhObElHbG1LSFJvYVhNdWFHRnpTVzF3YkdWdFpXNTBZWFJwYjI0b2RHaHBibWNwS1h0Y2JpQWdJQ0FnSUNBZ0lDQm1kVzRnUFNCMGFHbHpMbkpsWjJsemRISjVMbWRsZENoMGFHbHVaeTVqYjI1emRISjFZM1J2Y2lsYlpuVnVUbUZ0WlYwN1hHNGdJQ0FnSUNBZ0lIMWxiSE5sSUdsbUtIUm9hWE11Wm1Gc2JHSmhZMnNwZTF4dUlDQWdJQ0FnSUNBZ0lHWjFiaUE5SUhSb2FYTXVabUZzYkdKaFkydGJablZ1VG1GdFpWMDdYRzRnSUNBZ0lDQWdJSDFjYmx4dUlDQWdJQ0FnSUNCcFppaG1kVzRnSVQwZ2JuVnNiQ2w3WEc0Z0lDQWdJQ0FnSUNBZ2JHVjBJSEpsZEhaaGJDQTlJR1oxYmk1aGNIQnNlU2gwYUdsekxDQmhjbWR6S1R0Y2JpQWdJQ0FnSUNBZ0lDQnlaWFIxY200Z2NtVjBkbUZzTzF4dUlDQWdJQ0FnSUNCOVhHNWNiaUFnSUNBZ0lDQWdkR2h5YjNjZ2JtVjNJRVZ5Y205eUtGd2lUbThnYVcxd2JHVnRaVzUwWVhScGIyNGdabTkxYm1RZ1ptOXlJRndpSUNzZ2RHaHBibWNwTzF4dUlDQWdJQ0FnZlZ4dUlDQWdJSDFjYmlBZ2ZWeHVYRzRnSUdsdGNHeGxiV1Z1ZEdGMGFXOXVLSFI1Y0dVc0lHbHRjR3hsYldWdWRHRjBhVzl1S1h0Y2JpQWdJQ0JwWmloMGVYQmxJRDA5UFNCdWRXeHNLWHRjYmlBZ0lDQWdJSFJvYVhNdVptRnNiR0poWTJzZ1BTQnBiWEJzWlcxbGJuUmhkR2x2Ymp0Y2JpQWdJQ0I5Wld4elpYdGNiaUFnSUNBZ0lIUm9hWE11Y21WbmFYTjBjbmt1YzJWMEtIUjVjR1VzSUdsdGNHeGxiV1Z1ZEdGMGFXOXVLVHRjYmlBZ0lDQjlYRzRnSUgxY2JseHVJQ0JvWVhOSmJYQnNaVzFsYm5SaGRHbHZiaWgwYUdsdVp5a2dlMXh1SUNBZ0lHbG1JQ2gwYUdsdVp5QTlQVDBnU1c1MFpXZGxjaUI4ZkNCMGFHbHVaeUE5UFQwZ1JteHZZWFFwZTF4dUlDQWdJQ0FnY21WMGRYSnVJSFJvYVhNdWNtVm5hWE4wY25rdWFHRnpLSFJvYVc1bktUdGNiaUFnSUNCOVhHNWNiaUFnSUNCeVpYUjFjbTRnZEdocGN5NXlaV2RwYzNSeWVTNW9ZWE1vZEdocGJtY3VZMjl1YzNSeWRXTjBiM0lwTzF4dUlDQjlYRzU5WEc1Y2JseHVaWGh3YjNKMElHUmxabUYxYkhRZ1VISnZkRzlqYjJ3N1hHNGlYU3dpYzI5MWNtTmxVbTl2ZENJNklpOXpiM1Z5WTJVdkluMD1cbiIsImltcG9ydCB7IFR1cGxlIH0gZnJvbSAnLi9wcmltaXRpdmVzJztcbmltcG9ydCBCaXRTdHJpbmcgZnJvbSAnLi9iaXRfc3RyaW5nJztcbmltcG9ydCBQYXR0ZXJucyBmcm9tICcuL3BhdHRlcm5zJztcbmltcG9ydCBQcm90b2NvbCBmcm9tICcuL3Byb3RvY29sJztcblxuZnVuY3Rpb24gY2FsbF9wcm9wZXJ0eShpdGVtLCBwcm9wZXJ0eSkge1xuICBsZXQgcHJvcCA9IG51bGw7XG5cbiAgaWYgKHR5cGVvZiBpdGVtID09PSBcIm51bWJlclwiIHx8IHR5cGVvZiBpdGVtID09PSBcInN5bWJvbFwiIHx8IHR5cGVvZiBpdGVtID09PSBcImJvb2xlYW5cIiB8fCB0eXBlb2YgaXRlbSA9PT0gXCJzdHJpbmdcIikge1xuICAgIGlmIChpdGVtW3Byb3BlcnR5XSAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICBwcm9wID0gcHJvcGVydHk7XG4gICAgfSBlbHNlIGlmIChpdGVtW1N5bWJvbC5mb3IocHJvcGVydHkpXSAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICBwcm9wID0gU3ltYm9sLmZvcihwcm9wZXJ0eSk7XG4gICAgfVxuICB9IGVsc2Uge1xuICAgIGlmIChwcm9wZXJ0eSBpbiBpdGVtKSB7XG4gICAgICBwcm9wID0gcHJvcGVydHk7XG4gICAgfSBlbHNlIGlmIChTeW1ib2wuZm9yKHByb3BlcnR5KSBpbiBpdGVtKSB7XG4gICAgICBwcm9wID0gU3ltYm9sLmZvcihwcm9wZXJ0eSk7XG4gICAgfVxuICB9XG5cbiAgaWYgKHByb3AgPT09IG51bGwpIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoYFByb3BlcnR5ICR7IHByb3BlcnR5IH0gbm90IGZvdW5kIGluICR7IGl0ZW0gfWApO1xuICB9XG5cbiAgaWYgKGl0ZW1bcHJvcF0gaW5zdGFuY2VvZiBGdW5jdGlvbikge1xuICAgIHJldHVybiBpdGVtW3Byb3BdKCk7XG4gIH0gZWxzZSB7XG4gICAgcmV0dXJuIGl0ZW1bcHJvcF07XG4gIH1cbn1cblxuZnVuY3Rpb24gYXBwbHkoLi4uYXJncykge1xuICBpZiAoYXJncy5sZW5ndGggPT09IDIpIHtcbiAgICBhcmdzWzBdLmFwcGx5KG51bGwsIGFyZ3Muc2xpY2UoMSkpO1xuICB9IGVsc2Uge1xuICAgIGFyZ3NbMF1bYXJnc1sxXV0uYXBwbHkobnVsbCwgYXJncy5zbGljZSgyKSk7XG4gIH1cbn1cblxuZnVuY3Rpb24gY29udGFpbnMobGVmdCwgcmlnaHQpIHtcbiAgZm9yIChsZXQgeCBvZiByaWdodCkge1xuICAgIGlmIChQYXR0ZXJucy5tYXRjaF9ub190aHJvdyhsZWZ0LCB4KSAhPSBudWxsKSB7XG4gICAgICByZXR1cm4gdHJ1ZTtcbiAgICB9XG4gIH1cblxuICByZXR1cm4gZmFsc2U7XG59XG5cbmZ1bmN0aW9uIGdldF9nbG9iYWwoKSB7XG4gIGlmICh0eXBlb2Ygc2VsZiAhPT0gXCJ1bmRlZmluZWRcIikge1xuICAgIHJldHVybiBzZWxmO1xuICB9IGVsc2UgaWYgKHR5cGVvZiB3aW5kb3cgIT09IFwidW5kZWZpbmVkXCIpIHtcbiAgICByZXR1cm4gd2luZG93O1xuICB9IGVsc2UgaWYgKHR5cGVvZiBnbG9iYWwgIT09IFwidW5kZWZpbmVkXCIpIHtcbiAgICByZXR1cm4gZ2xvYmFsO1xuICB9XG5cbiAgdGhyb3cgbmV3IEVycm9yKFwiTm8gZ2xvYmFsIHN0YXRlIGZvdW5kXCIpO1xufVxuXG5mdW5jdGlvbiBkZWZzdHJ1Y3QoZGVmYXVsdHMpIHtcbiAgcmV0dXJuIGNsYXNzIHtcbiAgICBjb25zdHJ1Y3Rvcih1cGRhdGUgPSB7fSkge1xuICAgICAgbGV0IHRoZV92YWx1ZXMgPSBPYmplY3QuYXNzaWduKGRlZmF1bHRzLCB1cGRhdGUpO1xuICAgICAgT2JqZWN0LmFzc2lnbih0aGlzLCB0aGVfdmFsdWVzKTtcbiAgICB9XG5cbiAgICBzdGF0aWMgY3JlYXRlKHVwZGF0ZXMgPSB7fSkge1xuICAgICAgbGV0IHggPSBuZXcgdGhpcyh1cGRhdGVzKTtcbiAgICAgIHJldHVybiBPYmplY3QuZnJlZXplKHgpO1xuICAgIH1cbiAgfTtcbn1cblxuZnVuY3Rpb24gZGVmZXhjZXB0aW9uKGRlZmF1bHRzKSB7XG4gIHJldHVybiBjbGFzcyBleHRlbmRzIEVycm9yIHtcbiAgICBjb25zdHJ1Y3Rvcih1cGRhdGUgPSB7fSkge1xuICAgICAgbGV0IG1lc3NhZ2UgPSB1cGRhdGUubWVzc2FnZSB8fCBcIlwiO1xuICAgICAgc3VwZXIobWVzc2FnZSk7XG5cbiAgICAgIGxldCB0aGVfdmFsdWVzID0gT2JqZWN0LmFzc2lnbihkZWZhdWx0cywgdXBkYXRlKTtcbiAgICAgIE9iamVjdC5hc3NpZ24odGhpcywgdGhlX3ZhbHVlcyk7XG5cbiAgICAgIHRoaXMubmFtZSA9IHRoaXMuY29uc3RydWN0b3IubmFtZTtcbiAgICAgIHRoaXMubWVzc2FnZSA9IG1lc3NhZ2U7XG4gICAgICB0aGlzW1NwZWNpYWxGb3Jtcy5hdG9tKFwiX19leGNlcHRpb25fX1wiKV0gPSB0cnVlO1xuICAgICAgRXJyb3IuY2FwdHVyZVN0YWNrVHJhY2UodGhpcywgdGhpcy5jb25zdHJ1Y3Rvci5uYW1lKTtcbiAgICB9XG5cbiAgICBzdGF0aWMgY3JlYXRlKHVwZGF0ZXMgPSB7fSkge1xuICAgICAgbGV0IHggPSBuZXcgdGhpcyh1cGRhdGVzKTtcbiAgICAgIHJldHVybiBPYmplY3QuZnJlZXplKHgpO1xuICAgIH1cbiAgfTtcbn1cblxuZnVuY3Rpb24gZGVmcHJvdG9jb2woc3BlYykge1xuICByZXR1cm4gbmV3IFByb3RvY29sKHNwZWMpO1xufVxuXG5mdW5jdGlvbiBkZWZpbXBsKHByb3RvY29sLCB0eXBlLCBpbXBsKSB7XG4gIHByb3RvY29sLmltcGxlbWVudGF0aW9uKHR5cGUsIGltcGwpO1xufVxuXG5mdW5jdGlvbiBnZXRfb2JqZWN0X2tleXMob2JqKSB7XG4gIHJldHVybiBPYmplY3Qua2V5cyhvYmopLmNvbmNhdChPYmplY3QuZ2V0T3duUHJvcGVydHlTeW1ib2xzKG9iaikpO1xufVxuXG5mdW5jdGlvbiBpc192YWxpZF9jaGFyYWN0ZXIoY29kZXBvaW50KSB7XG4gIHRyeSB7XG4gICAgcmV0dXJuIFN0cmluZy5mcm9tQ29kZVBvaW50KGNvZGVwb2ludCkgIT0gbnVsbDtcbiAgfSBjYXRjaCAoZSkge1xuICAgIHJldHVybiBmYWxzZTtcbiAgfVxufVxuXG4vL2h0dHBzOi8vZGV2ZWxvcGVyLm1vemlsbGEub3JnL2VuLVVTL2RvY3MvV2ViL0FQSS9XaW5kb3dCYXNlNjQvQmFzZTY0X2VuY29kaW5nX2FuZF9kZWNvZGluZyNTb2x1dGlvbl8yXyVFMiU4MCU5M19yZXdyaXRlX3RoZV9ET01zX2F0b2IoKV9hbmRfYnRvYSgpX3VzaW5nX0phdmFTY3JpcHQnc19UeXBlZEFycmF5c19hbmRfVVRGLThcbmZ1bmN0aW9uIGI2NEVuY29kZVVuaWNvZGUoc3RyKSB7XG4gIHJldHVybiBidG9hKGVuY29kZVVSSUNvbXBvbmVudChzdHIpLnJlcGxhY2UoLyUoWzAtOUEtRl17Mn0pL2csIGZ1bmN0aW9uIChtYXRjaCwgcDEpIHtcbiAgICByZXR1cm4gU3RyaW5nLmZyb21DaGFyQ29kZSgnMHgnICsgcDEpO1xuICB9KSk7XG59XG5cbmZ1bmN0aW9uIGRlbGV0ZV9wcm9wZXJ0eV9mcm9tX21hcChtYXAsIHByb3BlcnR5KSB7XG4gIGxldCBuZXdfbWFwID0gT2JqZWN0LmFzc2lnbihPYmplY3QuY3JlYXRlKG1hcC5jb25zdHJ1Y3Rvci5wcm90b3R5cGUpLCBtYXApO1xuICBkZWxldGUgbmV3X21hcFtwcm9wZXJ0eV07XG5cbiAgcmV0dXJuIE9iamVjdC5mcmVlemUobmV3X21hcCk7XG59XG5cbmZ1bmN0aW9uIGNsYXNzX3RvX29iaihtYXApIHtcbiAgbGV0IG5ld19tYXAgPSBPYmplY3QuYXNzaWduKHt9LCBtYXApO1xuICByZXR1cm4gT2JqZWN0LmZyZWV6ZShuZXdfbWFwKTtcbn1cblxuZnVuY3Rpb24gYWRkX3Byb3BlcnR5X3RvX21hcChtYXAsIHByb3BlcnR5LCB2YWx1ZSkge1xuICBsZXQgbmV3X21hcCA9IE9iamVjdC5hc3NpZ24oe30sIG1hcCk7XG4gIG5ld19tYXBbcHJvcGVydHldID0gdmFsdWU7XG4gIHJldHVybiBPYmplY3QuZnJlZXplKG5ld19tYXApO1xufVxuXG5mdW5jdGlvbiB1cGRhdGVfbWFwKG1hcCwgcHJvcGVydHksIHZhbHVlKSB7XG4gIGlmIChwcm9wZXJ0eSBpbiBnZXRfb2JqZWN0X2tleXMobWFwKSkge1xuICAgIHJldHVybiBhZGRfcHJvcGVydHlfdG9fbWFwKG1hcCwgcHJvcGVydHksIHZhbHVlKTtcbiAgfVxuXG4gIHRocm93IFwibWFwIGRvZXMgbm90IGhhdmUga2V5XCI7XG59XG5cbmZ1bmN0aW9uIGJub3QoZXhwcikge1xuICByZXR1cm4gfmV4cHI7XG59XG5cbmZ1bmN0aW9uIGJhbmQobGVmdCwgcmlnaHQpIHtcbiAgcmV0dXJuIGxlZnQgJiByaWdodDtcbn1cblxuZnVuY3Rpb24gYm9yKGxlZnQsIHJpZ2h0KSB7XG4gIHJldHVybiBsZWZ0IHwgcmlnaHQ7XG59XG5cbmZ1bmN0aW9uIGJzbChsZWZ0LCByaWdodCkge1xuICByZXR1cm4gbGVmdCA8PCByaWdodDtcbn1cblxuZnVuY3Rpb24gYnNyKGxlZnQsIHJpZ2h0KSB7XG4gIHJldHVybiBsZWZ0ID4+IHJpZ2h0O1xufVxuXG5mdW5jdGlvbiBieG9yKGxlZnQsIHJpZ2h0KSB7XG4gIHJldHVybiBsZWZ0IF4gcmlnaHQ7XG59XG5cbmZ1bmN0aW9uIHppcChsaXN0X29mX2xpc3RzKSB7XG4gIGlmIChsaXN0X29mX2xpc3RzLmxlbmd0aCA9PT0gMCkge1xuICAgIHJldHVybiBPYmplY3QuZnJlZXplKFtdKTtcbiAgfVxuXG4gIGxldCBuZXdfdmFsdWUgPSBbXTtcbiAgbGV0IHNtYWxsZXN0X2xlbmd0aCA9IGxpc3Rfb2ZfbGlzdHNbMF07XG5cbiAgZm9yIChsZXQgeCBvZiBsaXN0X29mX2xpc3RzKSB7XG4gICAgaWYgKHgubGVuZ3RoIDwgc21hbGxlc3RfbGVuZ3RoKSB7XG4gICAgICBzbWFsbGVzdF9sZW5ndGggPSB4Lmxlbmd0aDtcbiAgICB9XG4gIH1cblxuICBmb3IgKGxldCBpID0gMDsgaSA8IHNtYWxsZXN0X2xlbmd0aDsgaSsrKSB7XG4gICAgbGV0IGN1cnJlbnRfdmFsdWUgPSBbXTtcbiAgICBmb3IgKGxldCBqID0gMDsgaiA8IGxpc3Rfb2ZfbGlzdHMubGVuZ3RoOyBqKyspIHtcbiAgICAgIGN1cnJlbnRfdmFsdWUucHVzaChsaXN0X29mX2xpc3RzW2pdW2ldKTtcbiAgICB9XG5cbiAgICBuZXdfdmFsdWUucHVzaChuZXcgVHVwbGUoLi4uY3VycmVudF92YWx1ZSkpO1xuICB9XG5cbiAgcmV0dXJuIE9iamVjdC5mcmVlemUobmV3X3ZhbHVlKTtcbn1cblxuZnVuY3Rpb24gY2FuX2RlY29kZTY0KGRhdGEpIHtcbiAgdHJ5IHtcbiAgICBhdG9iKGRhdGEpO1xuICAgIHJldHVybiB0cnVlO1xuICB9IGNhdGNoIChlKSB7XG4gICAgcmV0dXJuIGZhbHNlO1xuICB9XG59XG5cbmZ1bmN0aW9uIHJlbW92ZV9mcm9tX2xpc3QobGlzdCwgZWxlbWVudCkge1xuICBsZXQgZm91bmQgPSBmYWxzZTtcblxuICByZXR1cm4gbGlzdC5maWx0ZXIoZWxlbSA9PiB7XG4gICAgaWYgKCFmb3VuZCAmJiBlbGVtID09PSBlbGVtZW50KSB7XG4gICAgICBmb3VuZCA9IHRydWU7XG4gICAgICByZXR1cm4gZmFsc2U7XG4gICAgfVxuXG4gICAgcmV0dXJuIHRydWU7XG4gIH0pO1xufVxuXG5mdW5jdGlvbiBmb2xkbChmdW4sIGFjYywgbGlzdCkge1xuICBsZXQgYWNjMSA9IGFjYztcblxuICBmb3IgKGNvbnN0IGVsIG9mIGxpc3QpIHtcbiAgICBhY2MxID0gZnVuKGVsLCBhY2MxKTtcbiAgfVxuXG4gIHJldHVybiBhY2MxO1xufVxuXG5mdW5jdGlvbiBmb2xkcihmdW4sIGFjYywgbGlzdCkge1xuICBsZXQgYWNjMSA9IGFjYztcblxuICBmb3IgKGxldCBpID0gbGlzdC5sZW5ndGggLSAxOyBpID49IDA7IGktLSkge1xuICAgIGFjYzEgPSBmdW4obGlzdFtpXSwgYWNjMSk7XG4gIH1cblxuICByZXR1cm4gYWNjMTtcbn1cblxuZnVuY3Rpb24ga2V5ZmluZChrZXksIG4sIHR1cGxlbGlzdCkge1xuXG4gIGZvciAobGV0IGkgPSB0dXBsZWxpc3QubGVuZ3RoIC0gMTsgaSA+PSAwOyBpLS0pIHtcbiAgICBpZiAodHVwbGVsaXN0W2ldLmdldChuKSA9PT0ga2V5KSB7XG4gICAgICByZXR1cm4gdHVwbGVsaXN0W2ldO1xuICAgIH1cbiAgfVxuXG4gIHJldHVybiBmYWxzZTtcbn1cblxuZnVuY3Rpb24ga2V5ZGVsZXRlKGtleSwgbiwgdHVwbGVsaXN0KSB7XG5cbiAgZm9yIChsZXQgaSA9IHR1cGxlbGlzdC5sZW5ndGggLSAxOyBpID49IDA7IGktLSkge1xuICAgIGlmICh0dXBsZWxpc3RbaV0uZ2V0KG4pID09PSBrZXkpIHtcbiAgICAgIHJldHVybiB0dXBsZWxpc3QuY29uY2F0KFtdKS5zcGxpY2UoaSwgMSk7XG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIHR1cGxlbGlzdDtcbn1cblxuZnVuY3Rpb24ga2V5c3RvcmUoa2V5LCBuLCBsaXN0LCBuZXd0dXBsZSkge1xuICBmb3IgKGxldCBpID0gbGlzdC5sZW5ndGggLSAxOyBpID49IDA7IGktLSkge1xuICAgIGlmIChsaXN0W2ldLmdldChuKSA9PT0ga2V5KSB7XG4gICAgICByZXR1cm4gbGlzdC5jb25jYXQoW10pLnNwbGljZShpLCAxLCBuZXd0dXBsZSk7XG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIGxpc3QuY29uY2F0KFtdKS5wdXNoKG5ld3R1cGxlKTtcbn1cblxuZnVuY3Rpb24ga2V5bWVtYmVyKGtleSwgbiwgbGlzdCkge1xuICBmb3IgKGxldCBpID0gbGlzdC5sZW5ndGggLSAxOyBpID49IDA7IGktLSkge1xuICAgIGlmIChsaXN0W2ldLmdldChuKSA9PT0ga2V5KSB7XG4gICAgICByZXR1cm4gdHJ1ZTtcbiAgICB9XG4gIH1cblxuICByZXR1cm4gZmFsc2U7XG59XG5cbmZ1bmN0aW9uIGtleXRha2Uoa2V5LCBuLCBsaXN0KSB7XG4gIGlmICgha2V5bWVtYmVyKGtleSwgbiwgbGlzdCkpIHtcbiAgICByZXR1cm4gZmFsc2U7XG4gIH1cblxuICBsZXQgdHVwbGUgPSBrZXlmaW5kKGtleSwgbiwgbGlzdCk7XG5cbiAgcmV0dXJuIG5ldyBUdXBsZSh0dXBsZS5nZXQobiksIHR1cGxlLCBrZXlkZWxldGUoa2V5LCBuLCBsaXN0KSk7XG59XG5cbmZ1bmN0aW9uIGtleXJlcGxhY2Uoa2V5LCBuLCBsaXN0LCBuZXd0dXBsZSkge1xuXG4gIGZvciAobGV0IGkgPSB0dXBsZWxpc3QubGVuZ3RoIC0gMTsgaSA+PSAwOyBpLS0pIHtcbiAgICBpZiAodHVwbGVsaXN0W2ldLmdldChuKSA9PT0ga2V5KSB7XG4gICAgICByZXR1cm4gdHVwbGVsaXN0LmNvbmNhdChbXSkuc3BsaWNlKGksIDEsIG5ld3R1cGxlKTtcbiAgICB9XG4gIH1cblxuICByZXR1cm4gdHVwbGVsaXN0O1xufVxuXG5mdW5jdGlvbiByZXZlcnNlKGxpc3QpIHtcbiAgcmV0dXJuIGxpc3QuY29uY2F0KFtdKS5yZXZlcnNlKCk7XG59XG5cbmZ1bmN0aW9uIG1hcHNfZmluZChrZXksIG1hcCkge1xuICBpZiAoa2V5IGluIGdldF9vYmplY3Rfa2V5cyhtYXApKSB7XG4gICAgcmV0dXJuIG5ldyBUdXBsZShTeW1ib2wuZm9yKFwib2tcIiksIG1hcFtrZXldKTtcbiAgfSBlbHNlIHtcbiAgICByZXR1cm4gU3ltYm9sLmZvcihcImVycm9yXCIpO1xuICB9XG59XG5cbmZ1bmN0aW9uIGZsYXR0ZW4obGlzdCwgdGFpbCA9IFtdKSB7XG4gIGxldCBuZXdfbGlzdCA9IFtdO1xuXG4gIGZvciAobGV0IGUgb2YgbGlzdCkge1xuICAgIGlmIChpc0FycmF5KGUpKSB7XG4gICAgICBuZXdfbGlzdCA9IG5ld19saXN0LmNvbmNhdChmbGF0dGVuKGUpKTtcbiAgICB9IGVsc2Uge1xuICAgICAgbmV3X2xpc3QucHVzaChlKTtcbiAgICB9XG4gIH1cblxuICByZXR1cm4gT2JqZWN0LmZyZWV6ZShuZXdfbGlzdC5jb25jYXQodGFpbCkpO1xufVxuXG5mdW5jdGlvbiBkdXBsaWNhdGUobiwgZWxlbSkge1xuICBsZXQgbGlzdCA9IFtdO1xuXG4gIGZvciAobGV0IGkgPSAwOyBpIDwgbjsgaSsrKSB7XG4gICAgbGlzdC5wdXNoKGVsZW0pO1xuICB9XG5cbiAgcmV0dXJuIE9iamVjdC5mcmVlemUobGlzdCk7XG59XG5cbmZ1bmN0aW9uIG1hcGZvbGRsKGZ1biwgYWNjLCBsaXN0KSB7XG4gIGxldCBuZXdsaXN0ID0gW107XG5cbiAgZm9yIChsZXQgeCBvZiBsaXN0KSB7XG4gICAgbGV0IHR1cCA9IGZ1bih4LCBhY2MpO1xuICAgIG5ld2xpc3QucHVzaCh0dXAuZ2V0KDApKTtcbiAgICBhY2MgPSB0dXAuZ2V0KDEpO1xuICB9XG5cbiAgcmV0dXJuIG5ldyBUdXBsZShPYmplY3QuZnJlZXplKG5ld2xpc3QpLCBhY2MpO1xufVxuXG5mdW5jdGlvbiBmaWx0ZXJtYXAoZnVuLCBsaXN0KSB7XG4gIGxldCBuZXdsaXN0ID0gW107XG5cbiAgZm9yICh4IG9mIGxpc3QpIHtcbiAgICBsZXQgcmVzdWx0ID0gZnVuKHgpO1xuXG4gICAgaWYgKHJlc3VsdCA9PT0gdHJ1ZSkge1xuICAgICAgbmV3bGlzdC5wdXNoKHgpO1xuICAgIH0gZWxzZSBpZiAocmVzdWx0IGluc3RhbmNlb2YgVHVwbGUpIHtcbiAgICAgIG5ld2xpc3QucHVzaChyZXN1bHQuZ2V0KDEpKTtcbiAgICB9XG4gIH1cblxuICByZXR1cm4gT2JqZWN0LmZyZWV6ZShuZXdsaXN0KTtcbn1cblxuZnVuY3Rpb24gbWFwc19mb2xkKGZ1biwgYWNjLCBtYXApIHtcbiAgbGV0IGFjYzEgPSBhY2M7XG5cbiAgZm9yIChsZXQgayBvZiBnZXRfb2JqZWN0X2tleXMobWFwKSkge1xuICAgIGFjYzEgPSBmdW4oaywgbWFwW2tdLCBhY2MxKTtcbiAgfVxuXG4gIHJldHVybiBhY2MxO1xufVxuXG5mdW5jdGlvbiBtYXBzX2Zyb21fbGlzdChsaXN0KSB7XG4gIGxldCBtID0ge307XG5cbiAgZm9yICh4IG9mIGxpc3QpIHtcbiAgICBtW3guZ2V0KDApXSA9IHguZ2V0KDEpO1xuICB9XG5cbiAgcmV0dXJuIE9iamVjdC5mcmVlemUobSk7XG59XG5cbmV4cG9ydCBkZWZhdWx0IHtcbiAgY2FsbF9wcm9wZXJ0eSxcbiAgYXBwbHksXG4gIGNvbnRhaW5zLFxuICBnZXRfZ2xvYmFsLFxuICBkZWZzdHJ1Y3QsXG4gIGRlZmV4Y2VwdGlvbixcbiAgZGVmcHJvdG9jb2wsXG4gIGRlZmltcGwsXG4gIGdldF9vYmplY3Rfa2V5cyxcbiAgaXNfdmFsaWRfY2hhcmFjdGVyLFxuICBiNjRFbmNvZGVVbmljb2RlLFxuICBkZWxldGVfcHJvcGVydHlfZnJvbV9tYXAsXG4gIGFkZF9wcm9wZXJ0eV90b19tYXAsXG4gIGNsYXNzX3RvX29iaixcbiAgY2FuX2RlY29kZTY0LFxuICBibm90LFxuICBiYW5kLFxuICBib3IsXG4gIGJzbCxcbiAgYnNyLFxuICBieG9yLFxuICB6aXAsXG4gIGZvbGRsLFxuICBmb2xkcixcbiAgcmVtb3ZlX2Zyb21fbGlzdCxcbiAga2V5ZGVsZXRlLFxuICBrZXlzdG9yZSxcbiAga2V5ZmluZCxcbiAga2V5dGFrZSxcbiAga2V5cmVwbGFjZSxcbiAgcmV2ZXJzZSxcbiAgdXBkYXRlX21hcCxcbiAgbWFwc19maW5kLFxuICBmbGF0dGVuLFxuICBkdXBsaWNhdGUsXG4gIG1hcGZvbGRsLFxuICBmaWx0ZXJtYXAsXG4gIG1hcHNfZm9sZFxufTtcbi8vIyBzb3VyY2VNYXBwaW5nVVJMPWRhdGE6YXBwbGljYXRpb24vanNvbjtiYXNlNjQsZXlKMlpYSnphVzl1SWpvekxDSnpiM1Z5WTJWeklqcGJJbXhwWWk5amIzSmxMMloxYm1OMGFXOXVjeTVxY3lKZExDSnVZVzFsY3lJNlcxMHNJbTFoY0hCcGJtZHpJam9pUVVGQlFTeFRRVUZUTEV0QlFWUXNVVUZCYzBJc1kwRkJkRUk3UVVGRFFTeFBRVUZQTEZOQlFWQXNUVUZCYzBJc1kwRkJkRUk3UVVGRFFTeFBRVUZQTEZGQlFWQXNUVUZCY1VJc1dVRkJja0k3UVVGRFFTeFBRVUZQTEZGQlFWQXNUVUZCY1VJc1dVRkJja0k3TzBGQlJVRXNVMEZCVXl4aFFVRlVMRU5CUVhWQ0xFbEJRWFpDTEVWQlFUWkNMRkZCUVRkQ0xFVkJRWE5ETzBGQlEzQkRMRTFCUVVrc1QwRkJUeXhKUVVGUUxFTkJSR2RET3p0QlFVZHdReXhOUVVGSExFOUJRVThzU1VGQlVDeExRVUZuUWl4UlFVRm9RaXhKUVVFMFFpeFBRVUZQTEVsQlFWQXNTMEZCWjBJc1VVRkJhRUlzU1VGQk5FSXNUMEZCVHl4SlFVRlFMRXRCUVdkQ0xGTkJRV2hDTEVsQlFUWkNMRTlCUVU4c1NVRkJVQ3hMUVVGblFpeFJRVUZvUWl4RlFVRjVRanRCUVVNdlJ5eFJRVUZITEV0QlFVc3NVVUZCVEN4TlFVRnRRaXhUUVVGdVFpeEZRVUUyUWp0QlFVTTVRaXhoUVVGUExGRkJRVkFzUTBGRU9FSTdTMEZCYUVNc1RVRkZUU3hKUVVGSExFdEJRVXNzVDBGQlR5eEhRVUZRTEVOQlFWY3NVVUZCV0N4RFFVRk1MRTFCUVN0Q0xGTkJRUzlDTEVWQlFYbERPMEZCUTJoRUxHRkJRVThzVDBGQlR5eEhRVUZRTEVOQlFWY3NVVUZCV0N4RFFVRlFMRU5CUkdkRU8wdEJRVFZETzBkQlNGSXNUVUZOVHp0QlFVTk1MRkZCUVVjc1dVRkJXU3hKUVVGYUxFVkJRV2xDTzBGQlEyeENMR0ZCUVU4c1VVRkJVQ3hEUVVSclFqdExRVUZ3UWl4TlFVVk5MRWxCUVVjc1QwRkJUeXhIUVVGUUxFTkJRVmNzVVVGQldDeExRVUYzUWl4SlFVRjRRaXhGUVVFMlFqdEJRVU53UXl4aFFVRlBMRTlCUVU4c1IwRkJVQ3hEUVVGWExGRkJRVmdzUTBGQlVDeERRVVJ2UXp0TFFVRm9RenRIUVZSU096dEJRV05CTEUxQlFVY3NVMEZCVXl4SlFVRlVMRVZCUVdNN1FVRkRaaXhWUVVGTkxFbEJRVWtzUzBGQlNpeERRVUZWTEVOQlFVTXNVMEZCUkN4SFFVRmhMRkZCUVdJc1JVRkJkVUlzWTBGQmRrSXNSMEZCZDBNc1NVRkJlRU1zUlVGQk9FTXNRMEZCZUVRc1EwRkJUaXhEUVVSbE8wZEJRV3BDT3p0QlFVbEJMRTFCUVVjc1MwRkJTeXhKUVVGTUxHRkJRWE5DTEZGQlFYUkNMRVZCUVN0Q08wRkJRMmhETEZkQlFVOHNTMEZCU3l4SlFVRk1MRWRCUVZBc1EwRkVaME03UjBGQmJFTXNUVUZGU3p0QlFVTklMRmRCUVU4c1MwRkJTeXhKUVVGTUxFTkJRVkFzUTBGRVJ6dEhRVVpNTzBOQmNrSkdPenRCUVRSQ1FTeFRRVUZUTEV0QlFWUXNRMEZCWlN4SFFVRkhMRWxCUVVnc1JVRkJVVHRCUVVOeVFpeE5RVUZITEV0QlFVc3NUVUZCVEN4TFFVRm5RaXhEUVVGb1FpeEZRVUZyUWp0QlFVTnVRaXhUUVVGTExFTkJRVXdzUlVGQlVTeExRVUZTTEVOQlFXTXNTVUZCWkN4RlFVRnZRaXhMUVVGTExFdEJRVXdzUTBGQlZ5eERRVUZZTEVOQlFYQkNMRVZCUkcxQ08wZEJRWEpDTEUxQlJVczdRVUZEU0N4VFFVRkxMRU5CUVV3c1JVRkJVU3hMUVVGTExFTkJRVXdzUTBGQlVpeEZRVUZwUWl4TFFVRnFRaXhEUVVGMVFpeEpRVUYyUWl4RlFVRTJRaXhMUVVGTExFdEJRVXdzUTBGQlZ5eERRVUZZTEVOQlFUZENMRVZCUkVjN1IwRkdURHREUVVSR096dEJRVkZCTEZOQlFWTXNVVUZCVkN4RFFVRnJRaXhKUVVGc1FpeEZRVUYzUWl4TFFVRjRRaXhGUVVFNFFqdEJRVU0xUWl4UFFVRkpMRWxCUVVrc1EwRkJTaXhKUVVGVExFdEJRV0lzUlVGQmJVSTdRVUZEYWtJc1VVRkJSeXhUUVVGVExHTkJRVlFzUTBGQmQwSXNTVUZCZUVJc1JVRkJPRUlzUTBGQk9VSXNTMEZCYjBNc1NVRkJjRU1zUlVGQmVVTTdRVUZETVVNc1lVRkJUeXhKUVVGUUxFTkJSREJETzB0QlFUVkRPMGRCUkVZN08wRkJUVUVzVTBGQlR5eExRVUZRTEVOQlVEUkNPME5CUVRsQ096dEJRVlZCTEZOQlFWTXNWVUZCVkN4SFFVRnhRanRCUVVOdVFpeE5RVUZITEU5QlFVOHNTVUZCVUN4TFFVRnBRaXhYUVVGcVFpeEZRVUUyUWp0QlFVTTVRaXhYUVVGUExFbEJRVkFzUTBGRU9FSTdSMEZCYUVNc1RVRkZUU3hKUVVGSExFOUJRVThzVFVGQlVDeExRVUZ0UWl4WFFVRnVRaXhGUVVFclFqdEJRVU4wUXl4WFFVRlBMRTFCUVZBc1EwRkVjME03UjBGQmJFTXNUVUZGUVN4SlFVRkhMRTlCUVU4c1RVRkJVQ3hMUVVGdFFpeFhRVUZ1UWl4RlFVRXJRanRCUVVOMFF5eFhRVUZQTEUxQlFWQXNRMEZFYzBNN1IwRkJiRU03TzBGQlNVNHNVVUZCVFN4SlFVRkpMRXRCUVVvc1EwRkJWU3gxUWtGQlZpeERRVUZPTEVOQlZHMUNPME5CUVhKQ096dEJRVmxCTEZOQlFWTXNVMEZCVkN4RFFVRnRRaXhSUVVGdVFpeEZRVUUwUWp0QlFVTXhRaXhUUVVGUExFMUJRVTA3UVVGRFdDeG5Ra0ZCV1N4VFFVRlRMRVZCUVZRc1JVRkJXVHRCUVVOMFFpeFZRVUZKTEdGQlFXRXNUMEZCVHl4TlFVRlFMRU5CUVdNc1VVRkJaQ3hGUVVGM1FpeE5RVUY0UWl4RFFVRmlMRU5CUkd0Q08wRkJSWFJDTEdGQlFVOHNUVUZCVUN4RFFVRmpMRWxCUVdRc1JVRkJiMElzVlVGQmNFSXNSVUZHYzBJN1MwRkJlRUk3TzBGQlMwRXNWMEZCVHl4TlFVRlFMRU5CUVdNc1ZVRkJWU3hGUVVGV0xFVkJRV0U3UVVGRGVrSXNWVUZCU1N4SlFVRkpMRWxCUVVrc1NVRkJTaXhEUVVGVExFOUJRVlFzUTBGQlNpeERRVVJ4UWp0QlFVVjZRaXhoUVVGUExFOUJRVThzVFVGQlVDeERRVUZqTEVOQlFXUXNRMEZCVUN4RFFVWjVRanRMUVVFelFqdEhRVTVMTEVOQlJHMUNPME5CUVRWQ096dEJRV1ZCTEZOQlFWTXNXVUZCVkN4RFFVRnpRaXhSUVVGMFFpeEZRVUVyUWp0QlFVTTNRaXhUUVVGUExHTkJRV01zUzBGQlpDeERRVUZ2UWp0QlFVTjZRaXhuUWtGQldTeFRRVUZUTEVWQlFWUXNSVUZCV1R0QlFVTjBRaXhWUVVGSkxGVkJRVlVzVDBGQlR5eFBRVUZRTEVsQlFXdENMRVZCUVd4Q0xFTkJSRkU3UVVGRmRFSXNXVUZCVFN4UFFVRk9MRVZCUm5OQ096dEJRVWwwUWl4VlFVRkpMR0ZCUVdFc1QwRkJUeXhOUVVGUUxFTkJRV01zVVVGQlpDeEZRVUYzUWl4TlFVRjRRaXhEUVVGaUxFTkJTbXRDTzBGQlMzUkNMR0ZCUVU4c1RVRkJVQ3hEUVVGakxFbEJRV1FzUlVGQmIwSXNWVUZCY0VJc1JVRk1jMEk3TzBGQlQzUkNMRmRCUVVzc1NVRkJUQ3hIUVVGWkxFdEJRVXNzVjBGQlRDeERRVUZwUWl4SlFVRnFRaXhEUVZCVk8wRkJVWFJDTEZkQlFVc3NUMEZCVEN4SFFVRmxMRTlCUVdZc1EwRlNjMEk3UVVGVGRFSXNWMEZCU3l4aFFVRmhMRWxCUVdJc1EwRkJhMElzWlVGQmJFSXNRMEZCVEN4SlFVRXlReXhKUVVFelF5eERRVlJ6UWp0QlFWVjBRaXhaUVVGTkxHbENRVUZPTEVOQlFYZENMRWxCUVhoQ0xFVkJRVGhDTEV0QlFVc3NWMEZCVEN4RFFVRnBRaXhKUVVGcVFpeERRVUU1UWl4RFFWWnpRanRMUVVGNFFqczdRVUZoUVN4WFFVRlBMRTFCUVZBc1EwRkJZeXhWUVVGVkxFVkJRVllzUlVGQllUdEJRVU42UWl4VlFVRkpMRWxCUVVrc1NVRkJTU3hKUVVGS0xFTkJRVk1zVDBGQlZDeERRVUZLTEVOQlJIRkNPMEZCUlhwQ0xHRkJRVThzVDBGQlR5eE5RVUZRTEVOQlFXTXNRMEZCWkN4RFFVRlFMRU5CUm5sQ08wdEJRVE5DTzBkQlpFc3NRMEZFYzBJN1EwRkJMMEk3TzBGQmMwSkJMRk5CUVZNc1YwRkJWQ3hEUVVGeFFpeEpRVUZ5UWl4RlFVRXdRanRCUVVONFFpeFRRVUZQTEVsQlFVa3NVVUZCU2l4RFFVRmhMRWxCUVdJc1EwRkJVQ3hEUVVSM1FqdERRVUV4UWpzN1FVRkpRU3hUUVVGVExFOUJRVlFzUTBGQmFVSXNVVUZCYWtJc1JVRkJNa0lzU1VGQk0wSXNSVUZCYVVNc1NVRkJha01zUlVGQmMwTTdRVUZEY0VNc1YwRkJVeXhqUVVGVUxFTkJRWGRDTEVsQlFYaENMRVZCUVRoQ0xFbEJRVGxDTEVWQlJHOURPME5CUVhSRE96dEJRVWxCTEZOQlFWTXNaVUZCVkN4RFFVRjVRaXhIUVVGNlFpeEZRVUUyUWp0QlFVTjZRaXhUUVVGUExFOUJRVThzU1VGQlVDeERRVUZaTEVkQlFWb3NSVUZCYVVJc1RVRkJha0lzUTBGQmQwSXNUMEZCVHl4eFFrRkJVQ3hEUVVFMlFpeEhRVUUzUWl4RFFVRjRRaXhEUVVGUUxFTkJSSGxDTzBOQlFUZENPenRCUVVsQkxGTkJRVk1zYTBKQlFWUXNRMEZCTkVJc1UwRkJOVUlzUlVGQmMwTTdRVUZEY0VNc1RVRkJSenRCUVVORUxGZEJRVThzVDBGQlR5eGhRVUZRTEVOQlFYRkNMRk5CUVhKQ0xFdEJRVzFETEVsQlFXNURMRU5CUkU0N1IwRkJTQ3hEUVVWRExFOUJRVTBzUTBGQlRpeEZRVUZSTzBGQlExQXNWMEZCVHl4TFFVRlFMRU5CUkU4N1IwRkJVanREUVVoSU96czdRVUZUUVN4VFFVRlRMR2RDUVVGVUxFTkJRVEJDTEVkQlFURkNMRVZCUVN0Q08wRkJRek5DTEZOQlFVOHNTMEZCU3l4dFFrRkJiVUlzUjBGQmJrSXNSVUZCZDBJc1QwRkJlRUlzUTBGQlowTXNhVUpCUVdoRExFVkJRVzFFTEZWQlFWTXNTMEZCVkN4RlFVRm5RaXhGUVVGb1FpeEZRVUZ2UWp0QlFVTXZSU3hYUVVGUExFOUJRVThzV1VGQlVDeERRVUZ2UWl4UFFVRlBMRVZCUVZBc1EwRkJNMElzUTBGRUswVTdSMEZCY0VJc1EwRkJlRVFzUTBGQlVDeERRVVF5UWp0RFFVRXZRanM3UVVGTlFTeFRRVUZUTEhkQ1FVRlVMRU5CUVd0RExFZEJRV3hETEVWQlFYVkRMRkZCUVhaRExFVkJRV2RFTzBGQlF6VkRMRTFCUVVrc1ZVRkJWU3hQUVVGUExFMUJRVkFzUTBGQll5eFBRVUZQTEUxQlFWQXNRMEZCWXl4SlFVRkpMRmRCUVVvc1EwRkJaMElzVTBGQmFFSXNRMEZCTlVJc1JVRkJkMFFzUjBGQmVFUXNRMEZCVml4RFFVUjNRenRCUVVVMVF5eFRRVUZQTEZGQlFWRXNVVUZCVWl4RFFVRlFMRU5CUmpSRE96dEJRVWs1UXl4VFFVRlBMRTlCUVU4c1RVRkJVQ3hEUVVGakxFOUJRV1FzUTBGQlVDeERRVW80UXp0RFFVRm9SRHM3UVVGUFFTeFRRVUZUTEZsQlFWUXNRMEZCYzBJc1IwRkJkRUlzUlVGQk1FSTdRVUZEZEVJc1RVRkJTU3hWUVVGVkxFOUJRVThzVFVGQlVDeERRVUZqTEVWQlFXUXNSVUZCYTBJc1IwRkJiRUlzUTBGQlZpeERRVVJyUWp0QlFVVjRRaXhUUVVGUExFOUJRVThzVFVGQlVDeERRVUZqTEU5QlFXUXNRMEZCVUN4RFFVWjNRanREUVVFeFFqczdRVUZMUVN4VFFVRlRMRzFDUVVGVUxFTkJRVFpDTEVkQlFUZENMRVZCUVd0RExGRkJRV3hETEVWQlFUUkRMRXRCUVRWRExFVkJRV3RFTzBGQlEyaEVMRTFCUVVrc1ZVRkJWU3hQUVVGUExFMUJRVkFzUTBGQll5eEZRVUZrTEVWQlFXdENMRWRCUVd4Q0xFTkJRVllzUTBGRU5FTTdRVUZGYUVRc1ZVRkJVU3hSUVVGU0xFbEJRVzlDTEV0QlFYQkNMRU5CUm1kRU8wRkJSMmhFTEZOQlFVOHNUMEZCVHl4TlFVRlFMRU5CUVdNc1QwRkJaQ3hEUVVGUUxFTkJTR2RFTzBOQlFXeEVPenRCUVU5QkxGTkJRVk1zVlVGQlZDeERRVUZ2UWl4SFFVRndRaXhGUVVGNVFpeFJRVUY2UWl4RlFVRnRReXhMUVVGdVF5eEZRVUY1UXp0QlFVTnlReXhOUVVGSExGbEJRVmtzWjBKQlFXZENMRWRCUVdoQ0xFTkJRVm9zUlVGQmFVTTdRVUZEYUVNc1YwRkJUeXh2UWtGQmIwSXNSMEZCY0VJc1JVRkJlVUlzVVVGQmVrSXNSVUZCYlVNc1MwRkJia01zUTBGQlVDeERRVVJuUXp0SFFVRndRenM3UVVGSlFTeFJRVUZOTEhWQ1FVRk9MRU5CVEhGRE8wTkJRWHBET3p0QlFWRkJMRk5CUVZNc1NVRkJWQ3hEUVVGakxFbEJRV1FzUlVGQmJVSTdRVUZEYWtJc1UwRkJUeXhEUVVGRExFbEJRVVFzUTBGRVZUdERRVUZ1UWpzN1FVRkpRU3hUUVVGVExFbEJRVlFzUTBGQll5eEpRVUZrTEVWQlFXOUNMRXRCUVhCQ0xFVkJRVEJDTzBGQlEzaENMRk5CUVU4c1QwRkJUeXhMUVVGUUxFTkJSR2xDTzBOQlFURkNPenRCUVVsQkxGTkJRVk1zUjBGQlZDeERRVUZoTEVsQlFXSXNSVUZCYlVJc1MwRkJia0lzUlVGQmVVSTdRVUZEZGtJc1UwRkJUeXhQUVVGUExFdEJRVkFzUTBGRVowSTdRMEZCZWtJN08wRkJTVUVzVTBGQlV5eEhRVUZVTEVOQlFXRXNTVUZCWWl4RlFVRnRRaXhMUVVGdVFpeEZRVUY1UWp0QlFVTjJRaXhUUVVGUExGRkJRVkVzUzBGQlVpeERRVVJuUWp0RFFVRjZRanM3UVVGSlFTeFRRVUZUTEVkQlFWUXNRMEZCWVN4SlFVRmlMRVZCUVcxQ0xFdEJRVzVDTEVWQlFYbENPMEZCUTNaQ0xGTkJRVThzVVVGQlVTeExRVUZTTEVOQlJHZENPME5CUVhwQ096dEJRVWxCTEZOQlFWTXNTVUZCVkN4RFFVRmpMRWxCUVdRc1JVRkJiMElzUzBGQmNFSXNSVUZCTUVJN1FVRkRlRUlzVTBGQlR5eFBRVUZQTEV0QlFWQXNRMEZFYVVJN1EwRkJNVUk3TzBGQlNVRXNVMEZCVXl4SFFVRlVMRU5CUVdFc1lVRkJZaXhGUVVFeVFqdEJRVU42UWl4TlFVRkhMR05CUVdNc1RVRkJaQ3hMUVVGNVFpeERRVUY2UWl4RlFVRXlRanRCUVVNMVFpeFhRVUZQTEU5QlFVOHNUVUZCVUN4RFFVRmpMRVZCUVdRc1EwRkJVQ3hEUVVRMFFqdEhRVUU1UWpzN1FVRkpRU3hOUVVGSkxGbEJRVmtzUlVGQldpeERRVXh4UWp0QlFVMTZRaXhOUVVGSkxHdENRVUZyUWl4alFVRmpMRU5CUVdRc1EwRkJiRUlzUTBGT2NVSTdPMEZCVVhwQ0xFOUJRVWtzU1VGQlNTeERRVUZLTEVsQlFWTXNZVUZCWWl4RlFVRXlRanRCUVVONlFpeFJRVUZITEVWQlFVVXNUVUZCUml4SFFVRlhMR1ZCUVZnc1JVRkJNa0k3UVVGRE5VSXNkMEpCUVd0Q0xFVkJRVVVzVFVGQlJpeERRVVJWTzB0QlFUbENPMGRCUkVZN08wRkJUVUVzVDBGQlNTeEpRVUZKTEVsQlFVa3NRMEZCU2l4RlFVRlBMRWxCUVVrc1pVRkJTaXhGUVVGeFFpeEhRVUZ3UXl4RlFVRjNRenRCUVVOMFF5eFJRVUZKTEdkQ1FVRm5RaXhGUVVGb1FpeERRVVJyUXp0QlFVVjBReXhUUVVGSkxFbEJRVWtzU1VGQlNTeERRVUZLTEVWQlFVOHNTVUZCU1N4alFVRmpMRTFCUVdRc1JVRkJjMElzUjBGQmVrTXNSVUZCTmtNN1FVRkRNME1zYjBKQlFXTXNTVUZCWkN4RFFVRnRRaXhqUVVGakxFTkJRV1FzUlVGQmFVSXNRMEZCYWtJc1EwRkJia0lzUlVGRU1rTTdTMEZCTjBNN08wRkJTVUVzWTBGQlZTeEpRVUZXTEVOQlFXVXNTVUZCU1N4TFFVRktMRU5CUVZVc1IwRkJSeXhoUVVGSUxFTkJRWHBDTEVWQlRuTkRPMGRCUVhoRE96dEJRVk5CTEZOQlFVOHNUMEZCVHl4TlFVRlFMRU5CUVdNc1UwRkJaQ3hEUVVGUUxFTkJka0o1UWp0RFFVRXpRanM3UVVFd1FrRXNVMEZCVXl4WlFVRlVMRU5CUVhOQ0xFbEJRWFJDTEVWQlFUUkNPMEZCUXpGQ0xFMUJRVWM3UVVGRFJDeFRRVUZMTEVsQlFVd3NSVUZFUXp0QlFVVkVMRmRCUVU4c1NVRkJVQ3hEUVVaRE8wZEJRVWdzUTBGSFF5eFBRVUZOTEVOQlFVNHNSVUZCVVR0QlFVTlFMRmRCUVU4c1MwRkJVQ3hEUVVSUE8wZEJRVkk3UTBGS1NEczdRVUZUUVN4VFFVRlRMR2RDUVVGVUxFTkJRVEJDTEVsQlFURkNMRVZCUVdkRExFOUJRV2hETEVWQlFYZERPMEZCUTNCRExFMUJRVWtzVVVGQlVTeExRVUZTTEVOQlJHZERPenRCUVVkd1F5eFRRVUZQTEV0QlFVc3NUVUZCVEN4RFFVRlpMRkZCUVZVN1FVRkRla0lzVVVGQlJ5eERRVUZETEV0QlFVUXNTVUZCVlN4VFFVRlRMRTlCUVZRc1JVRkJhVUk3UVVGRE1VSXNZMEZCVVN4SlFVRlNMRU5CUkRCQ08wRkJSVEZDTEdGQlFVOHNTMEZCVUN4RFFVWXdRanRMUVVFNVFqczdRVUZMUVN4WFFVRlBMRWxCUVZBc1EwRk9lVUk3UjBGQlZpeERRVUZ1UWl4RFFVaHZRenREUVVGNFF6czdRVUZoUVN4VFFVRlRMRXRCUVZRc1EwRkJaU3hIUVVGbUxFVkJRVzlDTEVkQlFYQkNMRVZCUVhsQ0xFbEJRWHBDTEVWQlFUaENPMEZCUXpGQ0xFMUJRVWtzVDBGQlR5eEhRVUZRTEVOQlJITkNPenRCUVVjeFFpeFBRVUZKTEUxQlFVMHNSVUZCVGl4SlFVRlpMRWxCUVdoQ0xFVkJRWEZDTzBGQlEycENMRmRCUVU4c1NVRkJTU3hGUVVGS0xFVkJRVkVzU1VGQlVpeERRVUZRTEVOQlJHbENPMGRCUVhKQ096dEJRVWxCTEZOQlFVOHNTVUZCVUN4RFFWQXdRanREUVVFNVFqczdRVUZYUVN4VFFVRlRMRXRCUVZRc1EwRkJaU3hIUVVGbUxFVkJRVzlDTEVkQlFYQkNMRVZCUVhsQ0xFbEJRWHBDTEVWQlFUaENPMEZCUXpGQ0xFMUJRVWtzVDBGQlR5eEhRVUZRTEVOQlJITkNPenRCUVVjeFFpeFBRVUZKTEVsQlFVa3NTVUZCU1N4TFFVRkxMRTFCUVV3c1IwRkJZeXhEUVVGa0xFVkJRV2xDTEV0QlFVc3NRMEZCVEN4RlFVRlJMRWRCUVhKRExFVkJRWGxETzBGQlEzSkRMRmRCUVU4c1NVRkJTU3hMUVVGTExFTkJRVXdzUTBGQlNpeEZRVUZoTEVsQlFXSXNRMEZCVUN4RFFVUnhRenRIUVVGNlF6czdRVUZKUVN4VFFVRlBMRWxCUVZBc1EwRlFNRUk3UTBGQk9VSTdPMEZCVlVFc1UwRkJVeXhQUVVGVUxFTkJRV2xDTEVkQlFXcENMRVZCUVhOQ0xFTkJRWFJDTEVWQlFYbENMRk5CUVhwQ0xFVkJRVzFET3p0QlFVVnFReXhQUVVGSkxFbEJRVWtzU1VGQlNTeFZRVUZWTEUxQlFWWXNSMEZCYlVJc1EwRkJia0lzUlVGQmMwSXNTMEZCU3l4RFFVRk1MRVZCUVZFc1IwRkJNVU1zUlVGQk9FTTdRVUZETlVNc1VVRkJSeXhWUVVGVkxFTkJRVllzUlVGQllTeEhRVUZpTEVOQlFXbENMRU5CUVdwQ0xFMUJRWGRDTEVkQlFYaENMRVZCUVRSQ08wRkJRemRDTEdGQlFVOHNWVUZCVlN4RFFVRldMRU5CUVZBc1EwRkVOa0k3UzBGQkwwSTdSMEZFUmpzN1FVRk5RU3hUUVVGUExFdEJRVkFzUTBGU2FVTTdRMEZCYmtNN08wRkJWMEVzVTBGQlV5eFRRVUZVTEVOQlFXMUNMRWRCUVc1Q0xFVkJRWGRDTEVOQlFYaENMRVZCUVRKQ0xGTkJRVE5DTEVWQlFYRkRPenRCUVVWcVF5eFBRVUZKTEVsQlFVa3NTVUZCU1N4VlFVRlZMRTFCUVZZc1IwRkJiVUlzUTBGQmJrSXNSVUZCYzBJc1MwRkJTeXhEUVVGTUxFVkJRVkVzUjBGQk1VTXNSVUZCT0VNN1FVRkRNVU1zVVVGQlJ5eFZRVUZWTEVOQlFWWXNSVUZCWVN4SFFVRmlMRU5CUVdsQ0xFTkJRV3BDTEUxQlFYZENMRWRCUVhoQ0xFVkJRVFJDTzBGQlF6TkNMR0ZCUVU4c1ZVRkJWU3hOUVVGV0xFTkJRV2xDTEVWQlFXcENMRVZCUVhGQ0xFMUJRWEpDTEVOQlFUUkNMRU5CUVRWQ0xFVkJRU3RDTEVOQlFTOUNMRU5CUVZBc1EwRkVNa0k3UzBGQkwwSTdSMEZFU2pzN1FVRk5RU3hUUVVGUExGTkJRVkFzUTBGU2FVTTdRMEZCY2tNN08wRkJWMEVzVTBGQlV5eFJRVUZVTEVOQlFXdENMRWRCUVd4Q0xFVkJRWFZDTEVOQlFYWkNMRVZCUVRCQ0xFbEJRVEZDTEVWQlFXZERMRkZCUVdoRExFVkJRWGxETzBGQlEzSkRMRTlCUVVrc1NVRkJTU3hKUVVGSkxFdEJRVXNzVFVGQlRDeEhRVUZqTEVOQlFXUXNSVUZCYVVJc1MwRkJTeXhEUVVGTUxFVkJRVkVzUjBGQmNrTXNSVUZCZVVNN1FVRkRja01zVVVGQlJ5eExRVUZMTEVOQlFVd3NSVUZCVVN4SFFVRlNMRU5CUVZrc1EwRkJXaXhOUVVGdFFpeEhRVUZ1UWl4RlFVRjFRanRCUVVOMFFpeGhRVUZQTEV0QlFVc3NUVUZCVEN4RFFVRlpMRVZCUVZvc1JVRkJaMElzVFVGQmFFSXNRMEZCZFVJc1EwRkJka0lzUlVGQk1FSXNRMEZCTVVJc1JVRkJOa0lzVVVGQk4wSXNRMEZCVUN4RFFVUnpRanRMUVVFeFFqdEhRVVJLT3p0QlFVMUdMRk5CUVU4c1MwRkJTeXhOUVVGTUxFTkJRVmtzUlVGQldpeEZRVUZuUWl4SlFVRm9RaXhEUVVGeFFpeFJRVUZ5UWl4RFFVRlFMRU5CVUhWRE8wTkJRWHBET3p0QlFWVkJMRk5CUVZNc1UwRkJWQ3hEUVVGdFFpeEhRVUZ1UWl4RlFVRjNRaXhEUVVGNFFpeEZRVUV5UWl4SlFVRXpRaXhGUVVGblF6dEJRVU01UWl4UFFVRkpMRWxCUVVrc1NVRkJTU3hMUVVGTExFMUJRVXdzUjBGQll5eERRVUZrTEVWQlFXbENMRXRCUVVzc1EwRkJUQ3hGUVVGUkxFZEJRWEpETEVWQlFYbERPMEZCUTNaRExGRkJRVWNzUzBGQlN5eERRVUZNTEVWQlFWRXNSMEZCVWl4RFFVRlpMRU5CUVZvc1RVRkJiVUlzUjBGQmJrSXNSVUZCZFVJN1FVRkRlRUlzWVVGQlR5eEpRVUZRTEVOQlJIZENPMHRCUVRGQ08wZEJSRVk3TzBGQlRVRXNVMEZCVHl4TFFVRlFMRU5CVURoQ08wTkJRV2hET3p0QlFWVkJMRk5CUVZNc1QwRkJWQ3hEUVVGcFFpeEhRVUZxUWl4RlFVRnpRaXhEUVVGMFFpeEZRVUY1UWl4SlFVRjZRaXhGUVVFNFFqdEJRVU0xUWl4TlFVRkhMRU5CUVVNc1ZVRkJWU3hIUVVGV0xFVkJRV1VzUTBGQlppeEZRVUZyUWl4SlFVRnNRaXhEUVVGRUxFVkJRWGxDTzBGQlF6RkNMRmRCUVU4c1MwRkJVQ3hEUVVRd1FqdEhRVUUxUWpzN1FVRkpRU3hOUVVGSkxGRkJRVkVzVVVGQlVTeEhRVUZTTEVWQlFXRXNRMEZCWWl4RlFVRm5RaXhKUVVGb1FpeERRVUZTTEVOQlRIZENPenRCUVU4MVFpeFRRVUZQTEVsQlFVa3NTMEZCU2l4RFFVRlZMRTFCUVUwc1IwRkJUaXhEUVVGVkxFTkJRVllzUTBGQlZpeEZRVUYzUWl4TFFVRjRRaXhGUVVFclFpeFZRVUZWTEVkQlFWWXNSVUZCWlN4RFFVRm1MRVZCUVd0Q0xFbEJRV3hDTEVOQlFTOUNMRU5CUVZBc1EwRlFORUk3UTBGQk9VSTdPMEZCVlVFc1UwRkJVeXhWUVVGVUxFTkJRVzlDTEVkQlFYQkNMRVZCUVhsQ0xFTkJRWHBDTEVWQlFUUkNMRWxCUVRWQ0xFVkJRV3RETEZGQlFXeERMRVZCUVRKRE96dEJRVVY2UXl4UFFVRkpMRWxCUVVrc1NVRkJTU3hWUVVGVkxFMUJRVllzUjBGQmJVSXNRMEZCYmtJc1JVRkJjMElzUzBGQlN5eERRVUZNTEVWQlFWRXNSMEZCTVVNc1JVRkJPRU03UVVGRE5VTXNVVUZCUnl4VlFVRlZMRU5CUVZZc1JVRkJZU3hIUVVGaUxFTkJRV2xDTEVOQlFXcENMRTFCUVhkQ0xFZEJRWGhDTEVWQlFUUkNPMEZCUXpkQ0xHRkJRVThzVlVGQlZTeE5RVUZXTEVOQlFXbENMRVZCUVdwQ0xFVkJRWEZDTEUxQlFYSkNMRU5CUVRSQ0xFTkJRVFZDTEVWQlFTdENMRU5CUVM5Q0xFVkJRV3RETEZGQlFXeERMRU5CUVZBc1EwRkVOa0k3UzBGQkwwSTdSMEZFUmpzN1FVRk5RU3hUUVVGUExGTkJRVkFzUTBGU2VVTTdRMEZCTTBNN08wRkJXVUVzVTBGQlV5eFBRVUZVTEVOQlFXbENMRWxCUVdwQ0xFVkJRWE5DTzBGQlEyeENMRk5CUVU4c1MwRkJTeXhOUVVGTUxFTkJRVmtzUlVGQldpeEZRVUZuUWl4UFFVRm9RaXhGUVVGUUxFTkJSR3RDTzBOQlFYUkNPenRCUVVsQkxGTkJRVk1zVTBGQlZDeERRVUZ0UWl4SFFVRnVRaXhGUVVGM1FpeEhRVUY0UWl4RlFVRTBRanRCUVVONFFpeE5RVUZITEU5QlFVOHNaMEpCUVdkQ0xFZEJRV2hDTEVOQlFWQXNSVUZCTkVJN1FVRkRNMElzVjBGQlR5eEpRVUZKTEV0QlFVb3NRMEZCVlN4UFFVRlBMRWRCUVZBc1EwRkJWeXhKUVVGWUxFTkJRVllzUlVGQk5FSXNTVUZCU1N4SFFVRktMRU5CUVRWQ0xFTkJRVkFzUTBGRU1rSTdSMEZCTDBJc1RVRkZTenRCUVVORUxGZEJRVThzVDBGQlR5eEhRVUZRTEVOQlFWY3NUMEZCV0N4RFFVRlFMRU5CUkVNN1IwRkdURHREUVVSS096dEJRVkZCTEZOQlFWTXNUMEZCVkN4RFFVRnBRaXhKUVVGcVFpeEZRVUYxUWl4UFFVRlBMRVZCUVZBc1JVRkJWenRCUVVOb1F5eE5RVUZKTEZkQlFWY3NSVUZCV0N4RFFVUTBRanM3UVVGSGFFTXNUMEZCU1N4SlFVRkpMRU5CUVVvc1NVRkJVeXhKUVVGaUxFVkJRV3RDTzBGQlEyaENMRkZCUVVjc1VVRkJVU3hEUVVGU0xFTkJRVWdzUlVGQll6dEJRVU5hTEdsQ1FVRlhMRk5CUVZNc1RVRkJWQ3hEUVVGblFpeFJRVUZSTEVOQlFWSXNRMEZCYUVJc1EwRkJXQ3hEUVVSWk8wdEJRV1FzVFVGRlN6dEJRVU5JTEdWQlFWTXNTVUZCVkN4RFFVRmpMRU5CUVdRc1JVRkVSenRMUVVaTU8wZEJSRVk3TzBGQlVVRXNVMEZCVHl4UFFVRlBMRTFCUVZBc1EwRkJZeXhUUVVGVExFMUJRVlFzUTBGQlowSXNTVUZCYUVJc1EwRkJaQ3hEUVVGUUxFTkJXR2RETzBOQlFXeERPenRCUVdOQkxGTkJRVk1zVTBGQlZDeERRVUZ0UWl4RFFVRnVRaXhGUVVGelFpeEpRVUYwUWl4RlFVRXlRanRCUVVONlFpeE5RVUZKTEU5QlFVOHNSVUZCVUN4RFFVUnhRanM3UVVGSGVrSXNUMEZCU1N4SlFVRkpMRWxCUVVrc1EwRkJTaXhGUVVGUExFbEJRVWtzUTBGQlNpeEZRVUZQTEVkQlFYUkNMRVZCUVRCQ08wRkJRM2hDTEZOQlFVc3NTVUZCVEN4RFFVRlZMRWxCUVZZc1JVRkVkMEk3UjBGQk1VSTdPMEZCU1VFc1UwRkJUeXhQUVVGUExFMUJRVkFzUTBGQll5eEpRVUZrTEVOQlFWQXNRMEZRZVVJN1EwRkJNMEk3TzBGQlZVRXNVMEZCVXl4UlFVRlVMRU5CUVd0Q0xFZEJRV3hDTEVWQlFYVkNMRWRCUVhaQ0xFVkJRVFJDTEVsQlFUVkNMRVZCUVdsRE8wRkJReTlDTEUxQlFVa3NWVUZCVlN4RlFVRldMRU5CUkRKQ096dEJRVWN2UWl4UFFVRkpMRWxCUVVrc1EwRkJTaXhKUVVGVExFbEJRV0lzUlVGQmEwSTdRVUZEYUVJc1VVRkJTU3hOUVVGTkxFbEJRVWtzUTBGQlNpeEZRVUZQTEVkQlFWQXNRMEZCVGl4RFFVUlpPMEZCUldoQ0xGbEJRVkVzU1VGQlVpeERRVUZoTEVsQlFVa3NSMEZCU2l4RFFVRlJMRU5CUVZJc1EwRkJZaXhGUVVablFqdEJRVWRvUWl4VlFVRk5MRWxCUVVrc1IwRkJTaXhEUVVGUkxFTkJRVklzUTBGQlRpeERRVWhuUWp0SFFVRnNRanM3UVVGUFFTeFRRVUZQTEVsQlFVa3NTMEZCU2l4RFFVRlZMRTlCUVU4c1RVRkJVQ3hEUVVGakxFOUJRV1FzUTBGQlZpeEZRVUZyUXl4SFFVRnNReXhEUVVGUUxFTkJWaXRDTzBOQlFXcERPenRCUVdGQkxGTkJRVk1zVTBGQlZDeERRVUZ0UWl4SFFVRnVRaXhGUVVGM1FpeEpRVUY0UWl4RlFVRTJRanRCUVVNelFpeE5RVUZKTEZWQlFWVXNSVUZCVml4RFFVUjFRanM3UVVGSE0wSXNUMEZCU1N4RFFVRktMRWxCUVZNc1NVRkJWQ3hGUVVGak8wRkJRMW9zVVVGQlNTeFRRVUZUTEVsQlFVa3NRMEZCU2l4RFFVRlVMRU5CUkZFN08wRkJSMW9zVVVGQlJ5eFhRVUZYTEVsQlFWZ3NSVUZCWjBJN1FVRkRha0lzWTBGQlVTeEpRVUZTTEVOQlFXRXNRMEZCWWl4RlFVUnBRanRMUVVGdVFpeE5RVVZOTEVsQlFVY3NhMEpCUVd0Q0xFdEJRV3hDTEVWQlFYZENPMEZCUXk5Q0xHTkJRVkVzU1VGQlVpeERRVUZoTEU5QlFVOHNSMEZCVUN4RFFVRlhMRU5CUVZnc1EwRkJZaXhGUVVRclFqdExRVUV6UWp0SFFVeFNPenRCUVZWQkxGTkJRVThzVDBGQlR5eE5RVUZRTEVOQlFXTXNUMEZCWkN4RFFVRlFMRU5CWWpKQ08wTkJRVGRDT3p0QlFXZENRU3hUUVVGVExGTkJRVlFzUTBGQmJVSXNSMEZCYmtJc1JVRkJkMElzUjBGQmVFSXNSVUZCTmtJc1IwRkJOMElzUlVGQmFVTTdRVUZETDBJc1RVRkJTU3hQUVVGUExFZEJRVkFzUTBGRU1rSTdPMEZCUnk5Q0xFOUJRVWtzU1VGQlNTeERRVUZLTEVsQlFWTXNaMEpCUVdkQ0xFZEJRV2hDTEVOQlFXSXNSVUZCYTBNN1FVRkRhRU1zVjBGQlR5eEpRVUZKTEVOQlFVb3NSVUZCVHl4SlFVRkpMRU5CUVVvc1EwRkJVQ3hGUVVGbExFbEJRV1lzUTBGQlVDeERRVVJuUXp0SFFVRnNRenM3UVVGSlFTeFRRVUZQTEVsQlFWQXNRMEZRSzBJN1EwRkJha003TzBGQlZVRXNVMEZCVXl4alFVRlVMRU5CUVhkQ0xFbEJRWGhDTEVWQlFUWkNPMEZCUXpOQ0xFMUJRVWtzU1VGQlNTeEZRVUZLTEVOQlJIVkNPenRCUVVjelFpeFBRVUZKTEVOQlFVb3NTVUZCVXl4SlFVRlVMRVZCUVdNN1FVRkRXaXhOUVVGRkxFVkJRVVVzUjBGQlJpeERRVUZOTEVOQlFVNHNRMEZCUml4SlFVRmpMRVZCUVVVc1IwRkJSaXhEUVVGTkxFTkJRVTRzUTBGQlpDeERRVVJaTzBkQlFXUTdPMEZCU1VFc1UwRkJUeXhQUVVGUExFMUJRVkFzUTBGQll5eERRVUZrTEVOQlFWQXNRMEZRTWtJN1EwRkJOMEk3TzBGQlZVRXNaVUZCWlR0QlFVTmlMR1ZCUkdFN1FVRkZZaXhQUVVaaE8wRkJSMklzVlVGSVlUdEJRVWxpTEZsQlNtRTdRVUZMWWl4WFFVeGhPMEZCVFdJc1kwRk9ZVHRCUVU5aUxHRkJVR0U3UVVGUllpeFRRVkpoTzBGQlUySXNhVUpCVkdFN1FVRlZZaXh2UWtGV1lUdEJRVmRpTEd0Q1FWaGhPMEZCV1dJc01FSkJXbUU3UVVGaFlpeHhRa0ZpWVR0QlFXTmlMR05CWkdFN1FVRmxZaXhqUVdaaE8wRkJaMEppTEUxQmFFSmhPMEZCYVVKaUxFMUJha0poTzBGQmEwSmlMRXRCYkVKaE8wRkJiVUppTEV0QmJrSmhPMEZCYjBKaUxFdEJjRUpoTzBGQmNVSmlMRTFCY2tKaE8wRkJjMEppTEV0QmRFSmhPMEZCZFVKaUxFOUJka0poTzBGQmQwSmlMRTlCZUVKaE8wRkJlVUppTEd0Q1FYcENZVHRCUVRCQ1lpeFhRVEZDWVR0QlFUSkNZaXhWUVROQ1lUdEJRVFJDWWl4VFFUVkNZVHRCUVRaQ1lpeFRRVGRDWVR0QlFUaENZaXhaUVRsQ1lUdEJRU3RDWWl4VFFTOUNZVHRCUVdkRFlpeFpRV2hEWVR0QlFXbERZaXhYUVdwRFlUdEJRV3REWWl4VFFXeERZVHRCUVcxRFlpeFhRVzVEWVR0QlFXOURZaXhWUVhCRFlUdEJRWEZEWWl4WFFYSkRZVHRCUVhORFlpeFhRWFJEWVR0RFFVRm1JaXdpWm1sc1pTSTZJbXhwWWk5amIzSmxMMloxYm1OMGFXOXVjeTVxY3lJc0luTnZkWEpqWlhORGIyNTBaVzUwSWpwYkltbHRjRzl5ZENCN0lGUjFjR3hsSUgwZ1puSnZiU0FuTGk5d2NtbHRhWFJwZG1Wekp6dGNibWx0Y0c5eWRDQkNhWFJUZEhKcGJtY2dabkp2YlNBbkxpOWlhWFJmYzNSeWFXNW5KenRjYm1sdGNHOXlkQ0JRWVhSMFpYSnVjeUJtY205dElDY3VMM0JoZEhSbGNtNXpKenRjYm1sdGNHOXlkQ0JRY205MGIyTnZiQ0JtY205dElDY3VMM0J5YjNSdlkyOXNKenRjYmx4dVpuVnVZM1JwYjI0Z1kyRnNiRjl3Y205d1pYSjBlU2hwZEdWdExDQndjbTl3WlhKMGVTbDdYRzRnSUd4bGRDQndjbTl3SUQwZ2JuVnNiRHRjYmx4dUlDQnBaaWgwZVhCbGIyWWdhWFJsYlNBOVBUMGdYQ0p1ZFcxaVpYSmNJaUI4ZkNCMGVYQmxiMllnYVhSbGJTQTlQVDBnWENKemVXMWliMnhjSWlCOGZDQjBlWEJsYjJZZ2FYUmxiU0E5UFQwZ1hDSmliMjlzWldGdVhDSWdmSHdnZEhsd1pXOW1JR2wwWlcwZ1BUMDlJRndpYzNSeWFXNW5YQ0lwZTF4dUlDQWdJR2xtS0dsMFpXMWJjSEp2Y0dWeWRIbGRJQ0U5UFNCMWJtUmxabWx1WldRcGUxeHVJQ0FnSUNBZ2NISnZjQ0E5SUhCeWIzQmxjblI1TzF4dUlDQWdJSDFsYkhObElHbG1LR2wwWlcxYlUzbHRZbTlzTG1admNpaHdjbTl3WlhKMGVTbGRJQ0U5UFNCMWJtUmxabWx1WldRcGUxeHVJQ0FnSUNBZ2NISnZjQ0E5SUZONWJXSnZiQzVtYjNJb2NISnZjR1Z5ZEhrcE8xeHVJQ0FnSUgxY2JpQWdmU0JsYkhObElIdGNiaUFnSUNCcFppaHdjbTl3WlhKMGVTQnBiaUJwZEdWdEtYdGNiaUFnSUNBZ0lIQnliM0FnUFNCd2NtOXdaWEowZVR0Y2JpQWdJQ0I5Wld4elpTQnBaaWhUZVcxaWIyd3VabTl5S0hCeWIzQmxjblI1S1NCcGJpQnBkR1Z0S1h0Y2JpQWdJQ0FnSUhCeWIzQWdQU0JUZVcxaWIyd3VabTl5S0hCeWIzQmxjblI1S1R0Y2JpQWdJQ0I5WEc0Z0lIMWNibHh1SUNCcFppaHdjbTl3SUQwOVBTQnVkV3hzS1h0Y2JpQWdJQ0IwYUhKdmR5QnVaWGNnUlhKeWIzSW9ZRkJ5YjNCbGNuUjVJQ1I3SUhCeWIzQmxjblI1SUgwZ2JtOTBJR1p2ZFc1a0lHbHVJQ1I3SUdsMFpXMGdmV0FwT3lCY2JpQWdmVnh1WEc0Z0lHbG1LR2wwWlcxYmNISnZjRjBnYVc1emRHRnVZMlZ2WmlCR2RXNWpkR2x2YmlsN1hHNGdJQ0FnY21WMGRYSnVJR2wwWlcxYmNISnZjRjBvS1R0Y2JpQWdmV1ZzYzJWN1hHNGdJQ0FnY21WMGRYSnVJR2wwWlcxYmNISnZjRjA3WEc0Z0lIMWNibjFjYmx4dVpuVnVZM1JwYjI0Z1lYQndiSGtvTGk0dVlYSm5jeWw3WEc0Z0lHbG1LR0Z5WjNNdWJHVnVaM1JvSUQwOVBTQXlLWHRjYmlBZ0lDQmhjbWR6V3pCZExtRndjR3g1S0c1MWJHd3NJR0Z5WjNNdWMyeHBZMlVvTVNrcE8xeHVJQ0I5Wld4elpYdGNiaUFnSUNCaGNtZHpXekJkVzJGeVozTmJNVjFkTG1Gd2NHeDVLRzUxYkd3c0lHRnlaM011YzJ4cFkyVW9NaWtwTzF4dUlDQjlYRzU5WEc1Y2JtWjFibU4wYVc5dUlHTnZiblJoYVc1ektHeGxablFzSUhKcFoyaDBLWHRjYmlBZ1ptOXlLR3hsZENCNElHOW1JSEpwWjJoMEtYdGNiaUFnSUNCcFppaFFZWFIwWlhKdWN5NXRZWFJqYUY5dWIxOTBhSEp2ZHloc1pXWjBMQ0I0S1NBaFBTQnVkV3hzS1h0Y2JpQWdJQ0FnSUhKbGRIVnliaUIwY25WbE8xeHVJQ0FnSUgxY2JpQWdmVnh1WEc0Z0lISmxkSFZ5YmlCbVlXeHpaVHRjYm4xY2JseHVablZ1WTNScGIyNGdaMlYwWDJkc2IySmhiQ2dwZTF4dUlDQnBaaWgwZVhCbGIyWW9jMlZzWmlrZ0lUMDlJRndpZFc1a1pXWnBibVZrWENJcGUxeHVJQ0FnSUhKbGRIVnliaUJ6Wld4bU8xeHVJQ0I5Wld4elpTQnBaaWgwZVhCbGIyWW9kMmx1Wkc5M0tTQWhQVDBnWENKMWJtUmxabWx1WldSY0lpbDdYRzRnSUNBZ2NtVjBkWEp1SUhkcGJtUnZkenRjYmlBZ2ZXVnNjMlVnYVdZb2RIbHdaVzltS0dkc2IySmhiQ2tnSVQwOUlGd2lkVzVrWldacGJtVmtYQ0lwZTF4dUlDQWdJSEpsZEhWeWJpQm5iRzlpWVd3N1hHNGdJSDFjYmx4dUlDQjBhSEp2ZHlCdVpYY2dSWEp5YjNJb1hDSk9ieUJuYkc5aVlXd2djM1JoZEdVZ1ptOTFibVJjSWlrN1hHNTlYRzVjYm1aMWJtTjBhVzl1SUdSbFpuTjBjblZqZENoa1pXWmhkV3gwY3lsN1hHNGdJSEpsZEhWeWJpQmpiR0Z6Y3lCN1hHNGdJQ0FnWTI5dWMzUnlkV04wYjNJb2RYQmtZWFJsSUQwZ2UzMHBlMXh1SUNBZ0lDQWdiR1YwSUhSb1pWOTJZV3gxWlhNZ1BTQlBZbXBsWTNRdVlYTnphV2R1S0dSbFptRjFiSFJ6TENCMWNHUmhkR1VwTzF4dUlDQWdJQ0FnVDJKcVpXTjBMbUZ6YzJsbmJpaDBhR2x6TENCMGFHVmZkbUZzZFdWektUdGNiaUFnSUNCOVhHNWNiaUFnSUNCemRHRjBhV01nWTNKbFlYUmxLSFZ3WkdGMFpYTWdQU0I3ZlNsN1hHNGdJQ0FnSUNCc1pYUWdlQ0E5SUc1bGR5QjBhR2x6S0hWd1pHRjBaWE1wTzF4dUlDQWdJQ0FnY21WMGRYSnVJRTlpYW1WamRDNW1jbVZsZW1Vb2VDazdYRzRnSUNBZ2ZWeHVJQ0I5TzF4dWZWeHVYRzVjYm1aMWJtTjBhVzl1SUdSbFptVjRZMlZ3ZEdsdmJpaGtaV1poZFd4MGN5bDdYRzRnSUhKbGRIVnliaUJqYkdGemN5QmxlSFJsYm1SeklFVnljbTl5SUh0Y2JpQWdJQ0JqYjI1emRISjFZM1J2Y2loMWNHUmhkR1VnUFNCN2ZTbDdYRzRnSUNBZ0lDQnNaWFFnYldWemMyRm5aU0E5SUhWd1pHRjBaUzV0WlhOellXZGxJSHg4SUZ3aVhDSTdYRzRnSUNBZ0lDQnpkWEJsY2lodFpYTnpZV2RsS1R0Y2JseHVJQ0FnSUNBZ2JHVjBJSFJvWlY5MllXeDFaWE1nUFNCUFltcGxZM1F1WVhOemFXZHVLR1JsWm1GMWJIUnpMQ0IxY0dSaGRHVXBPMXh1SUNBZ0lDQWdUMkpxWldOMExtRnpjMmxuYmloMGFHbHpMQ0IwYUdWZmRtRnNkV1Z6S1R0Y2JseHVJQ0FnSUNBZ2RHaHBjeTV1WVcxbElEMGdkR2hwY3k1amIyNXpkSEoxWTNSdmNpNXVZVzFsTzF4dUlDQWdJQ0FnZEdocGN5NXRaWE56WVdkbElEMGdiV1Z6YzJGblpUdGNiaUFnSUNBZ0lIUm9hWE5iVTNCbFkybGhiRVp2Y20xekxtRjBiMjBvWENKZlgyVjRZMlZ3ZEdsdmJsOWZYQ0lwWFNBOUlIUnlkV1U3WEc0Z0lDQWdJQ0JGY25KdmNpNWpZWEIwZFhKbFUzUmhZMnRVY21GalpTaDBhR2x6TENCMGFHbHpMbU52Ym5OMGNuVmpkRzl5TG01aGJXVXBPMXh1SUNBZ0lIMWNibHh1SUNBZ0lITjBZWFJwWXlCamNtVmhkR1VvZFhCa1lYUmxjeUE5SUh0OUtYdGNiaUFnSUNBZ0lHeGxkQ0I0SUQwZ2JtVjNJSFJvYVhNb2RYQmtZWFJsY3lrN1hHNGdJQ0FnSUNCeVpYUjFjbTRnVDJKcVpXTjBMbVp5WldWNlpTaDRLVHRjYmlBZ0lDQjlYRzRnSUgwN1hHNTlYRzVjYm1aMWJtTjBhVzl1SUdSbFpuQnliM1J2WTI5c0tITndaV01wZTF4dUlDQnlaWFIxY200Z2JtVjNJRkJ5YjNSdlkyOXNLSE53WldNcE8xeHVmVnh1WEc1bWRXNWpkR2x2YmlCa1pXWnBiWEJzS0hCeWIzUnZZMjlzTENCMGVYQmxMQ0JwYlhCc0tYdGNiaUFnY0hKdmRHOWpiMnd1YVcxd2JHVnRaVzUwWVhScGIyNG9kSGx3WlN3Z2FXMXdiQ2s3WEc1OVhHNWNibVoxYm1OMGFXOXVJR2RsZEY5dlltcGxZM1JmYTJWNWN5aHZZbW9wZTF4dUlDQWdJSEpsZEhWeWJpQlBZbXBsWTNRdWEyVjVjeWh2WW1vcExtTnZibU5oZENoUFltcGxZM1F1WjJWMFQzZHVVSEp2Y0dWeWRIbFRlVzFpYjJ4ektHOWlhaWtwTzF4dWZWeHVYRzVtZFc1amRHbHZiaUJwYzE5MllXeHBaRjlqYUdGeVlXTjBaWElvWTI5a1pYQnZhVzUwS1h0Y2JpQWdkSEo1ZTF4dUlDQWdJSEpsZEhWeWJpQlRkSEpwYm1jdVpuSnZiVU52WkdWUWIybHVkQ2hqYjJSbGNHOXBiblFwSUNFOUlHNTFiR3c3WEc0Z0lIMWpZWFJqYUNobEtYdGNiaUFnSUNCeVpYUjFjbTRnWm1Gc2MyVTdYRzRnSUgxY2JuMWNibHh1THk5b2RIUndjem92TDJSbGRtVnNiM0JsY2k1dGIzcHBiR3hoTG05eVp5OWxiaTFWVXk5a2IyTnpMMWRsWWk5QlVFa3ZWMmx1Wkc5M1FtRnpaVFkwTDBKaGMyVTJORjlsYm1OdlpHbHVaMTloYm1SZlpHVmpiMlJwYm1jalUyOXNkWFJwYjI1Zk1sOGxSVElsT0RBbE9UTmZjbVYzY21sMFpWOTBhR1ZmUkU5TmMxOWhkRzlpS0NsZllXNWtYMkowYjJFb0tWOTFjMmx1WjE5S1lYWmhVMk55YVhCMEozTmZWSGx3WldSQmNuSmhlWE5mWVc1a1gxVlVSaTA0WEc1bWRXNWpkR2x2YmlCaU5qUkZibU52WkdWVmJtbGpiMlJsS0hOMGNpa2dlMXh1SUNBZ0lISmxkSFZ5YmlCaWRHOWhLR1Z1WTI5a1pWVlNTVU52YlhCdmJtVnVkQ2h6ZEhJcExuSmxjR3hoWTJVb0x5VW9XekF0T1VFdFJsMTdNbjBwTDJjc0lHWjFibU4wYVc5dUtHMWhkR05vTENCd01Ta2dlMXh1SUNBZ0lDQWdJQ0J5WlhSMWNtNGdVM1J5YVc1bkxtWnliMjFEYUdGeVEyOWtaU2duTUhnbklDc2djREVwTzF4dUlDQWdJSDBwS1R0Y2JuMWNibHh1Wm5WdVkzUnBiMjRnWkdWc1pYUmxYM0J5YjNCbGNuUjVYMlp5YjIxZmJXRndLRzFoY0N3Z2NISnZjR1Z5ZEhrcGUxeHVJQ0FnSUd4bGRDQnVaWGRmYldGd0lEMGdUMkpxWldOMExtRnpjMmxuYmloUFltcGxZM1F1WTNKbFlYUmxLRzFoY0M1amIyNXpkSEoxWTNSdmNpNXdjbTkwYjNSNWNHVXBMQ0J0WVhBcE8xeHVJQ0FnSUdSbGJHVjBaU0J1WlhkZmJXRndXM0J5YjNCbGNuUjVYVHRjYmx4dUlDQnlaWFIxY200Z1QySnFaV04wTG1aeVpXVjZaU2h1WlhkZmJXRndLVHRjYm4xY2JseHVablZ1WTNScGIyNGdZMnhoYzNOZmRHOWZiMkpxS0cxaGNDbDdYRzRnSUNBZ2JHVjBJRzVsZDE5dFlYQWdQU0JQWW1wbFkzUXVZWE56YVdkdUtIdDlMQ0J0WVhBcE8xeHVJQ0J5WlhSMWNtNGdUMkpxWldOMExtWnlaV1Y2WlNodVpYZGZiV0Z3S1R0Y2JuMWNibHh1Wm5WdVkzUnBiMjRnWVdSa1gzQnliM0JsY25SNVgzUnZYMjFoY0NodFlYQXNJSEJ5YjNCbGNuUjVMQ0IyWVd4MVpTbDdYRzRnSUd4bGRDQnVaWGRmYldGd0lEMGdUMkpxWldOMExtRnpjMmxuYmloN2ZTd2diV0Z3S1R0Y2JpQWdibVYzWDIxaGNGdHdjbTl3WlhKMGVWMGdQU0IyWVd4MVpUdGNiaUFnY21WMGRYSnVJRTlpYW1WamRDNW1jbVZsZW1Vb2JtVjNYMjFoY0NrN1hHNTlYRzVjYmx4dVpuVnVZM1JwYjI0Z2RYQmtZWFJsWDIxaGNDaHRZWEFzSUhCeWIzQmxjblI1TENCMllXeDFaU2w3WEc0Z0lDQWdhV1lvY0hKdmNHVnlkSGtnYVc0Z1oyVjBYMjlpYW1WamRGOXJaWGx6S0cxaGNDa3BlMXh1SUNBZ0lDQWdJQ0J5WlhSMWNtNGdZV1JrWDNCeWIzQmxjblI1WDNSdlgyMWhjQ2h0WVhBc0lIQnliM0JsY25SNUxDQjJZV3gxWlNrN1hHNGdJQ0FnZlZ4dVhHNGdJQ0FnZEdoeWIzY2dYQ0p0WVhBZ1pHOWxjeUJ1YjNRZ2FHRjJaU0JyWlhsY0lqdGNibjFjYmx4dVpuVnVZM1JwYjI0Z1ltNXZkQ2hsZUhCeUtYdGNiaUFnY21WMGRYSnVJSDVsZUhCeU8xeHVmVnh1WEc1bWRXNWpkR2x2YmlCaVlXNWtLR3hsWm5Rc0lISnBaMmgwS1h0Y2JpQWdjbVYwZFhKdUlHeGxablFnSmlCeWFXZG9kRHRjYm4xY2JseHVablZ1WTNScGIyNGdZbTl5S0d4bFpuUXNJSEpwWjJoMEtYdGNiaUFnY21WMGRYSnVJR3hsWm5RZ2ZDQnlhV2RvZER0Y2JuMWNibHh1Wm5WdVkzUnBiMjRnWW5Oc0tHeGxablFzSUhKcFoyaDBLWHRjYmlBZ2NtVjBkWEp1SUd4bFpuUWdQRHdnY21sbmFIUTdYRzU5WEc1Y2JtWjFibU4wYVc5dUlHSnpjaWhzWldaMExDQnlhV2RvZENsN1hHNGdJSEpsZEhWeWJpQnNaV1owSUQ0K0lISnBaMmgwTzF4dWZWeHVYRzVtZFc1amRHbHZiaUJpZUc5eUtHeGxablFzSUhKcFoyaDBLWHRjYmlBZ2NtVjBkWEp1SUd4bFpuUWdYaUJ5YVdkb2REdGNibjFjYmx4dVpuVnVZM1JwYjI0Z2VtbHdLR3hwYzNSZmIyWmZiR2x6ZEhNcGUxeHVJQ0JwWmloc2FYTjBYMjltWDJ4cGMzUnpMbXhsYm1kMGFDQTlQVDBnTUNsN1hHNGdJQ0FnY21WMGRYSnVJRTlpYW1WamRDNW1jbVZsZW1Vb1cxMHBPMXh1SUNCOVhHNWNiaUFnYkdWMElHNWxkMTkyWVd4MVpTQTlJRnRkTzF4dUlDQnNaWFFnYzIxaGJHeGxjM1JmYkdWdVozUm9JRDBnYkdsemRGOXZabDlzYVhOMGMxc3dYVHRjYmx4dUlDQm1iM0lvYkdWMElIZ2diMllnYkdsemRGOXZabDlzYVhOMGN5bDdYRzRnSUNBZ2FXWW9lQzVzWlc1bmRHZ2dQQ0J6YldGc2JHVnpkRjlzWlc1bmRHZ3BlMXh1SUNBZ0lDQWdjMjFoYkd4bGMzUmZiR1Z1WjNSb0lEMGdlQzVzWlc1bmRHZzdYRzRnSUNBZ2ZWeHVJQ0I5WEc1Y2JpQWdabTl5S0d4bGRDQnBJRDBnTURzZ2FTQThJSE50WVd4c1pYTjBYMnhsYm1kMGFEc2dhU3NyS1h0Y2JpQWdJQ0JzWlhRZ1kzVnljbVZ1ZEY5MllXeDFaU0E5SUZ0ZE8xeHVJQ0FnSUdadmNpaHNaWFFnYWlBOUlEQTdJR29nUENCc2FYTjBYMjltWDJ4cGMzUnpMbXhsYm1kMGFEc2dhaXNyS1h0Y2JpQWdJQ0FnSUdOMWNuSmxiblJmZG1Gc2RXVXVjSFZ6YUNoc2FYTjBYMjltWDJ4cGMzUnpXMnBkVzJsZEtUdGNiaUFnSUNCOVhHNWNiaUFnSUNCdVpYZGZkbUZzZFdVdWNIVnphQ2h1WlhjZ1ZIVndiR1VvTGk0dVkzVnljbVZ1ZEY5MllXeDFaU2twTzF4dUlDQjlYRzVjYmlBZ2NtVjBkWEp1SUU5aWFtVmpkQzVtY21WbGVtVW9ibVYzWDNaaGJIVmxLVHRjYm4xY2JseHVablZ1WTNScGIyNGdZMkZ1WDJSbFkyOWtaVFkwS0dSaGRHRXBJSHRjYmlBZ2RISjVlMXh1SUNBZ0lHRjBiMklvWkdGMFlTazdYRzRnSUNBZ2NtVjBkWEp1SUhSeWRXVTdYRzRnSUgxallYUmphQ2hsS1h0Y2JpQWdJQ0J5WlhSMWNtNGdabUZzYzJVN1hHNGdJSDFjYm4xY2JseHVablZ1WTNScGIyNGdjbVZ0YjNabFgyWnliMjFmYkdsemRDaHNhWE4wTENCbGJHVnRaVzUwS1h0Y2JpQWdJQ0JzWlhRZ1ptOTFibVFnUFNCbVlXeHpaVHRjYmx4dUlDQWdJSEpsZEhWeWJpQnNhWE4wTG1acGJIUmxjaWdvWld4bGJTa2dQVDRnZTF4dUlDQWdJQ0FnSUNCcFppZ2habTkxYm1RZ0ppWWdaV3hsYlNBOVBUMGdaV3hsYldWdWRDbDdYRzRnSUNBZ0lDQWdJQ0FnSUNCbWIzVnVaQ0E5SUhSeWRXVTdYRzRnSUNBZ0lDQWdJQ0FnSUNCeVpYUjFjbTRnWm1Gc2MyVTdYRzRnSUNBZ0lDQWdJSDFjYmx4dUlDQWdJQ0FnSUNCeVpYUjFjbTRnZEhKMVpUdGNiaUFnSUNCOUtUdGNibjFjYmx4dVpuVnVZM1JwYjI0Z1ptOXNaR3dvWm5WdUxDQmhZMk1zSUd4cGMzUXBlMXh1SUNBZ0lHeGxkQ0JoWTJNeElEMGdZV05qTzF4dVhHNGdJQ0FnWm05eUtHTnZibk4wSUdWc0lHOW1JR3hwYzNRcGUxeHVJQ0FnSUNBZ0lDQmhZMk14SUQwZ1puVnVLR1ZzTENCaFkyTXhLVHRjYmlBZ0lDQjlYRzVjYmlBZ0lDQnlaWFIxY200Z1lXTmpNVHRjYm4xY2JseHVYRzVtZFc1amRHbHZiaUJtYjJ4a2NpaG1kVzRzSUdGall5d2diR2x6ZENsN1hHNGdJQ0FnYkdWMElHRmpZekVnUFNCaFkyTTdYRzVjYmlBZ0lDQm1iM0lvYkdWMElHa2dQU0JzYVhOMExteGxibWQwYUNBdElERTdJR2tnUGowZ01Ec2dhUzB0S1h0Y2JpQWdJQ0FnSUNBZ1lXTmpNU0E5SUdaMWJpaHNhWE4wVzJsZExDQmhZMk14S1R0Y2JpQWdJQ0I5WEc1Y2JpQWdJQ0J5WlhSMWNtNGdZV05qTVR0Y2JuMWNibHh1Wm5WdVkzUnBiMjRnYTJWNVptbHVaQ2hyWlhrc0lHNHNJSFIxY0d4bGJHbHpkQ2w3WEc1Y2JpQWdabTl5S0d4bGRDQnBJRDBnZEhWd2JHVnNhWE4wTG14bGJtZDBhQ0F0SURFN0lHa2dQajBnTURzZ2FTMHRLWHRjYmlBZ0lDQnBaaWgwZFhCc1pXeHBjM1JiYVYwdVoyVjBLRzRwSUQwOVBTQnJaWGtwZTF4dUlDQWdJQ0FnY21WMGRYSnVJSFIxY0d4bGJHbHpkRnRwWFR0Y2JpQWdJQ0I5WEc0Z0lIMWNibHh1SUNCeVpYUjFjbTRnWm1Gc2MyVTdYRzU5WEc1Y2JtWjFibU4wYVc5dUlHdGxlV1JsYkdWMFpTaHJaWGtzSUc0c0lIUjFjR3hsYkdsemRDbDdYRzVjYmlBZ0lDQm1iM0lvYkdWMElHa2dQU0IwZFhCc1pXeHBjM1F1YkdWdVozUm9JQzBnTVRzZ2FTQStQU0F3T3lCcExTMHBlMXh1SUNBZ0lDQWdJQ0JwWmloMGRYQnNaV3hwYzNSYmFWMHVaMlYwS0c0cElEMDlQU0JyWlhrcGUxeHVJQ0FnSUNBZ0lDQWdJQ0FnY21WMGRYSnVJSFIxY0d4bGJHbHpkQzVqYjI1allYUW9XMTBwTG5Od2JHbGpaU2hwTENBeEtUdGNiaUFnSUNBZ0lDQWdmVnh1SUNBZ0lIMWNibHh1SUNBZ0lISmxkSFZ5YmlCMGRYQnNaV3hwYzNRN1hHNTlYRzVjYm1aMWJtTjBhVzl1SUd0bGVYTjBiM0psS0d0bGVTd2diaXdnYkdsemRDd2dibVYzZEhWd2JHVXBlMXh1SUNBZ0lHWnZjaWhzWlhRZ2FTQTlJR3hwYzNRdWJHVnVaM1JvSUMwZ01Uc2dhU0ErUFNBd095QnBMUzBwZTF4dUlDQWdJQ0FnSUNCcFppaHNhWE4wVzJsZExtZGxkQ2h1S1NBOVBUMGdhMlY1S1h0Y2JpQWdJQ0FnSUNBZ0lDQWdJSEpsZEhWeWJpQnNhWE4wTG1OdmJtTmhkQ2hiWFNrdWMzQnNhV05sS0drc0lERXNJRzVsZDNSMWNHeGxLVHRjYmlBZ0lDQWdJQ0FnZlZ4dUlDQWdJSDFjYmx4dUlDQnlaWFIxY200Z2JHbHpkQzVqYjI1allYUW9XMTBwTG5CMWMyZ29ibVYzZEhWd2JHVXBPMXh1ZlZ4dVhHNW1kVzVqZEdsdmJpQnJaWGx0WlcxaVpYSW9hMlY1TENCdUxDQnNhWE4wS1h0Y2JpQWdabTl5S0d4bGRDQnBJRDBnYkdsemRDNXNaVzVuZEdnZ0xTQXhPeUJwSUQ0OUlEQTdJR2t0TFNsN1hHNGdJQ0FnYVdZb2JHbHpkRnRwWFM1blpYUW9iaWtnUFQwOUlHdGxlU2w3WEc0Z0lDQWdJQ0J5WlhSMWNtNGdkSEoxWlR0Y2JpQWdJQ0I5WEc0Z0lIMWNibHh1SUNCeVpYUjFjbTRnWm1Gc2MyVTdYRzU5WEc1Y2JtWjFibU4wYVc5dUlHdGxlWFJoYTJVb2EyVjVMQ0J1TENCc2FYTjBLWHRjYmlBZ2FXWW9JV3RsZVcxbGJXSmxjaWhyWlhrc0lHNHNJR3hwYzNRcEtYdGNiaUFnSUNCeVpYUjFjbTRnWm1Gc2MyVTdYRzRnSUgxY2JseHVJQ0JzWlhRZ2RIVndiR1VnUFNCclpYbG1hVzVrS0d0bGVTd2diaXdnYkdsemRDazdYRzVjYmlBZ2NtVjBkWEp1SUc1bGR5QlVkWEJzWlNoMGRYQnNaUzVuWlhRb2Jpa3NJSFIxY0d4bExDQnJaWGxrWld4bGRHVW9hMlY1TENCdUxDQnNhWE4wS1NrN1hHNTlYRzVjYm1aMWJtTjBhVzl1SUd0bGVYSmxjR3hoWTJVb2EyVjVMQ0J1TENCc2FYTjBMQ0J1WlhkMGRYQnNaU2w3WEc0Z0lGeHVJQ0JtYjNJb2JHVjBJR2tnUFNCMGRYQnNaV3hwYzNRdWJHVnVaM1JvSUMwZ01Uc2dhU0ErUFNBd095QnBMUzBwZTF4dUlDQWdJR2xtS0hSMWNHeGxiR2x6ZEZ0cFhTNW5aWFFvYmlrZ1BUMDlJR3RsZVNsN1hHNGdJQ0FnSUNCeVpYUjFjbTRnZEhWd2JHVnNhWE4wTG1OdmJtTmhkQ2hiWFNrdWMzQnNhV05sS0drc0lERXNJRzVsZDNSMWNHeGxLVHRjYmlBZ0lDQjlYRzRnSUgxY2JseHVJQ0J5WlhSMWNtNGdkSFZ3YkdWc2FYTjBPMXh1ZlZ4dVhHNWNibVoxYm1OMGFXOXVJSEpsZG1WeWMyVW9iR2x6ZENsN1hHNGdJQ0FnY21WMGRYSnVJR3hwYzNRdVkyOXVZMkYwS0Z0ZEtTNXlaWFpsY25ObEtDazdYRzU5WEc1Y2JtWjFibU4wYVc5dUlHMWhjSE5mWm1sdVpDaHJaWGtzSUcxaGNDbDdYRzRnSUNBZ2FXWW9hMlY1SUdsdUlHZGxkRjl2WW1wbFkzUmZhMlY1Y3lodFlYQXBLWHRjYmlBZ0lDQWdJQ0FnY21WMGRYSnVJRzVsZHlCVWRYQnNaU2hUZVcxaWIyd3VabTl5S0Z3aWIydGNJaWtzSUcxaGNGdHJaWGxkS1R0Y2JpQWdJQ0I5Wld4elpYdGNiaUFnSUNBZ0lDQWdjbVYwZFhKdUlGTjViV0p2YkM1bWIzSW9YQ0psY25KdmNsd2lLVHRjYmlBZ0lDQjlYRzU5WEc1Y2JtWjFibU4wYVc5dUlHWnNZWFIwWlc0b2JHbHpkQ3dnZEdGcGJDQTlJRnRkS1NCN1hHNGdJR3hsZENCdVpYZGZiR2x6ZENBOUlGdGRPMXh1WEc0Z0lHWnZjaWhzWlhRZ1pTQnZaaUJzYVhOMEtYdGNiaUFnSUNCcFppaHBjMEZ5Y21GNUtHVXBLWHRjYmlBZ0lDQWdJRzVsZDE5c2FYTjBJRDBnYm1WM1gyeHBjM1F1WTI5dVkyRjBLR1pzWVhSMFpXNG9aU2twTzF4dUlDQWdJSDFsYkhObGUxeHVJQ0FnSUNBZ2JtVjNYMnhwYzNRdWNIVnphQ2hsS1R0Y2JpQWdJQ0I5WEc0Z0lIMWNibHh1SUNCeVpYUjFjbTRnVDJKcVpXTjBMbVp5WldWNlpTaHVaWGRmYkdsemRDNWpiMjVqWVhRb2RHRnBiQ2twTzF4dWZWeHVYRzVtZFc1amRHbHZiaUJrZFhCc2FXTmhkR1VvYml3Z1pXeGxiU2w3WEc0Z0lHeGxkQ0JzYVhOMElEMGdXMTA3WEc1Y2JpQWdabTl5S0d4bGRDQnBJRDBnTURzZ2FTQThJRzQ3SUdrckt5bDdYRzRnSUNBZ2JHbHpkQzV3ZFhOb0tHVnNaVzBwTzF4dUlDQjlYRzVjYmlBZ2NtVjBkWEp1SUU5aWFtVmpkQzVtY21WbGVtVW9iR2x6ZENrN1hHNTlYRzVjYm1aMWJtTjBhVzl1SUcxaGNHWnZiR1JzS0daMWJpd2dZV05qTENCc2FYTjBLWHRjYmlBZ2JHVjBJRzVsZDJ4cGMzUWdQU0JiWFR0Y2JseHVJQ0JtYjNJb2JHVjBJSGdnYjJZZ2JHbHpkQ2w3WEc0Z0lDQWdiR1YwSUhSMWNDQTlJR1oxYmloNExDQmhZMk1wTzF4dUlDQWdJRzVsZDJ4cGMzUXVjSFZ6YUNoMGRYQXVaMlYwS0RBcEtUdGNiaUFnSUNCaFkyTWdQU0IwZFhBdVoyVjBLREVwTzF4dUlDQjlYRzVjYmx4dUlDQnlaWFIxY200Z2JtVjNJRlIxY0d4bEtFOWlhbVZqZEM1bWNtVmxlbVVvYm1WM2JHbHpkQ2tzSUdGall5azdYRzU5WEc1Y2JtWjFibU4wYVc5dUlHWnBiSFJsY20xaGNDaG1kVzRzSUd4cGMzUXBlMXh1SUNCc1pYUWdibVYzYkdsemRDQTlJRnRkTzF4dVhHNGdJR1p2Y2loNElHOW1JR3hwYzNRcGUxeHVJQ0FnSUd4bGRDQnlaWE4xYkhRZ1BTQm1kVzRvZUNrN1hHNWNiaUFnSUNCcFppaHlaWE4xYkhRZ1BUMDlJSFJ5ZFdVcGUxeHVJQ0FnSUNBZ2JtVjNiR2x6ZEM1d2RYTm9LSGdwTzF4dUlDQWdJSDFsYkhObElHbG1LSEpsYzNWc2RDQnBibk4wWVc1alpXOW1JRlIxY0d4bEtYdGNiaUFnSUNBZ0lHNWxkMnhwYzNRdWNIVnphQ2h5WlhOMWJIUXVaMlYwS0RFcEtUdGNiaUFnSUNCOVhHNGdJSDFjYmx4dUlDQnlaWFIxY200Z1QySnFaV04wTG1aeVpXVjZaU2h1Wlhkc2FYTjBLVHRjYm4xY2JseHVablZ1WTNScGIyNGdiV0Z3YzE5bWIyeGtLR1oxYml3Z1lXTmpMQ0J0WVhBcGUxeHVJQ0JzWlhRZ1lXTmpNU0E5SUdGall6dGNibHh1SUNCbWIzSW9iR1YwSUdzZ2IyWWdaMlYwWDI5aWFtVmpkRjlyWlhsektHMWhjQ2twZTF4dUlDQWdJR0ZqWXpFZ1BTQm1kVzRvYXl3Z2JXRndXMnRkTENCaFkyTXhLVHRjYmlBZ2ZWeHVYRzRnSUhKbGRIVnliaUJoWTJNeE8xeHVmVnh1WEc1bWRXNWpkR2x2YmlCdFlYQnpYMlp5YjIxZmJHbHpkQ2hzYVhOMEtYdGNiaUFnYkdWMElHMGdQU0I3ZlR0Y2JseHVJQ0JtYjNJb2VDQnZaaUJzYVhOMEtYdGNiaUFnSUNCdFczZ3VaMlYwS0RBcFhTQTlJSGd1WjJWMEtERXBPMXh1SUNCOVhHNWNiaUFnY21WMGRYSnVJRTlpYW1WamRDNW1jbVZsZW1Vb2JTazdYRzU5WEc1Y2JtVjRjRzl5ZENCa1pXWmhkV3gwSUh0Y2JpQWdZMkZzYkY5d2NtOXdaWEowZVN4Y2JpQWdZWEJ3Ykhrc1hHNGdJR052Ym5SaGFXNXpMRnh1SUNCblpYUmZaMnh2WW1Gc0xGeHVJQ0JrWldaemRISjFZM1FzWEc0Z0lHUmxabVY0WTJWd2RHbHZiaXhjYmlBZ1pHVm1jSEp2ZEc5amIyd3NYRzRnSUdSbFptbHRjR3dzWEc0Z0lHZGxkRjl2WW1wbFkzUmZhMlY1Y3l4Y2JpQWdhWE5mZG1Gc2FXUmZZMmhoY21GamRHVnlMRnh1SUNCaU5qUkZibU52WkdWVmJtbGpiMlJsTEZ4dUlDQmtaV3hsZEdWZmNISnZjR1Z5ZEhsZlpuSnZiVjl0WVhBc1hHNGdJR0ZrWkY5d2NtOXdaWEowZVY5MGIxOXRZWEFzWEc0Z0lHTnNZWE56WDNSdlgyOWlhaXhjYmlBZ1kyRnVYMlJsWTI5a1pUWTBMRnh1SUNCaWJtOTBMRnh1SUNCaVlXNWtMRnh1SUNCaWIzSXNYRzRnSUdKemJDeGNiaUFnWW5OeUxGeHVJQ0JpZUc5eUxGeHVJQ0I2YVhBc1hHNGdJR1p2YkdSc0xGeHVJQ0JtYjJ4a2NpeGNiaUFnY21WdGIzWmxYMlp5YjIxZmJHbHpkQ3hjYmlBZ2EyVjVaR1ZzWlhSbExGeHVJQ0JyWlhsemRHOXlaU3hjYmlBZ2EyVjVabWx1WkN4Y2JpQWdhMlY1ZEdGclpTeGNiaUFnYTJWNWNtVndiR0ZqWlN4Y2JpQWdjbVYyWlhKelpTeGNiaUFnZFhCa1lYUmxYMjFoY0N4Y2JpQWdiV0Z3YzE5bWFXNWtMRnh1SUNCbWJHRjBkR1Z1TEZ4dUlDQmtkWEJzYVdOaGRHVXNYRzRnSUcxaGNHWnZiR1JzTEZ4dUlDQm1hV3gwWlhKdFlYQXNYRzRnSUcxaGNITmZabTlzWkZ4dWZUdGNiaUpkTENKemIzVnlZMlZTYjI5MElqb2lMM052ZFhKalpTOGlmUT09XG4iLCJpbXBvcnQgQml0U3RyaW5nIGZyb20gJy4vYml0X3N0cmluZyc7XG5pbXBvcnQgUGF0dGVybnMgZnJvbSAnLi9wYXR0ZXJucyc7XG5pbXBvcnQgeyBUdXBsZSB9IGZyb20gJy4vcHJpbWl0aXZlcyc7XG5cbmZ1bmN0aW9uIF9jYXNlKGNvbmRpdGlvbiwgY2xhdXNlcykge1xuICByZXR1cm4gUGF0dGVybnMuZGVmbWF0Y2goLi4uY2xhdXNlcykoY29uZGl0aW9uKTtcbn1cblxuZnVuY3Rpb24gY29uZChjbGF1c2VzKSB7XG4gIGZvciAobGV0IGNsYXVzZSBvZiBjbGF1c2VzKSB7XG4gICAgaWYgKGNsYXVzZVswXSkge1xuICAgICAgcmV0dXJuIGNsYXVzZVsxXSgpO1xuICAgIH1cbiAgfVxuXG4gIHRocm93IG5ldyBFcnJvcigpO1xufVxuXG5mdW5jdGlvbiBtYXBfdXBkYXRlKG1hcCwgdmFsdWVzKSB7XG4gIHJldHVybiBPYmplY3QuZnJlZXplKE9iamVjdC5hc3NpZ24oT2JqZWN0LmNyZWF0ZShtYXAuY29uc3RydWN0b3IucHJvdG90eXBlKSwgbWFwLCB2YWx1ZXMpKTtcbn1cblxuZnVuY3Rpb24gX2Zvcihjb2xsZWN0aW9ucywgZnVuLCBmaWx0ZXIgPSAoKSA9PiB0cnVlLCBpbnRvID0gW10sIHByZXZpb3VzVmFsdWVzID0gW10pIHtcbiAgbGV0IHBhdHRlcm4gPSBjb2xsZWN0aW9uc1swXVswXTtcbiAgbGV0IGNvbGxlY3Rpb24gPSBjb2xsZWN0aW9uc1swXVsxXTtcblxuICBpZiAoY29sbGVjdGlvbnMubGVuZ3RoID09PSAxKSB7XG4gICAgaWYgKGNvbGxlY3Rpb24gaW5zdGFuY2VvZiBCaXRTdHJpbmcpIHtcbiAgICAgIGxldCBic1NsaWNlID0gY29sbGVjdGlvbi5zbGljZSgwLCBwYXR0ZXJuLmJ5dGVfc2l6ZSgpKTtcbiAgICAgIGxldCBpID0gMTtcblxuICAgICAgd2hpbGUgKGJzU2xpY2UuYnl0ZV9zaXplID09IHBhdHRlcm4uYnl0ZV9zaXplKCkpIHtcbiAgICAgICAgbGV0IHIgPSBQYXR0ZXJucy5tYXRjaF9ub190aHJvdyhwYXR0ZXJuLCBic1NsaWNlKTtcbiAgICAgICAgbGV0IGFyZ3MgPSBwcmV2aW91c1ZhbHVlcy5jb25jYXQocik7XG5cbiAgICAgICAgaWYgKHIgJiYgZmlsdGVyLmFwcGx5KHRoaXMsIGFyZ3MpKSB7XG4gICAgICAgICAgaW50byA9IGludG8uY29uY2F0KFtmdW4uYXBwbHkodGhpcywgYXJncyldKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGJzU2xpY2UgPSBjb2xsZWN0aW9uLnNsaWNlKHBhdHRlcm4uYnl0ZV9zaXplKCkgKiBpLCBwYXR0ZXJuLmJ5dGVfc2l6ZSgpICogKGkgKyAxKSk7XG4gICAgICAgIGkrKztcbiAgICAgIH1cblxuICAgICAgcmV0dXJuIGludG87XG4gICAgfSBlbHNlIHtcbiAgICAgIGZvciAobGV0IGVsZW0gb2YgY29sbGVjdGlvbikge1xuICAgICAgICBsZXQgciA9IFBhdHRlcm5zLm1hdGNoX25vX3Rocm93KHBhdHRlcm4sIGVsZW0pO1xuICAgICAgICBsZXQgYXJncyA9IHByZXZpb3VzVmFsdWVzLmNvbmNhdChyKTtcblxuICAgICAgICBpZiAociAmJiBmaWx0ZXIuYXBwbHkodGhpcywgYXJncykpIHtcbiAgICAgICAgICBpbnRvID0gaW50by5jb25jYXQoW2Z1bi5hcHBseSh0aGlzLCBhcmdzKV0pO1xuICAgICAgICB9XG4gICAgICB9XG5cbiAgICAgIHJldHVybiBpbnRvO1xuICAgIH1cbiAgfSBlbHNlIHtcbiAgICBsZXQgX2ludG8gPSBbXTtcblxuICAgIGlmIChjb2xsZWN0aW9uIGluc3RhbmNlb2YgQml0U3RyaW5nKSB7XG4gICAgICBsZXQgYnNTbGljZSA9IGNvbGxlY3Rpb24uc2xpY2UoMCwgcGF0dGVybi5ieXRlX3NpemUoKSk7XG4gICAgICBsZXQgaSA9IDE7XG5cbiAgICAgIHdoaWxlIChic1NsaWNlLmJ5dGVfc2l6ZSA9PSBwYXR0ZXJuLmJ5dGVfc2l6ZSgpKSB7XG4gICAgICAgIGxldCByID0gUGF0dGVybnMubWF0Y2hfbm9fdGhyb3cocGF0dGVybiwgYnNTbGljZSk7XG4gICAgICAgIGlmIChyKSB7XG4gICAgICAgICAgX2ludG8gPSBpbnRvLmNvbmNhdCh0aGlzLl9mb3IoY29sbGVjdGlvbnMuc2xpY2UoMSksIGZ1biwgZmlsdGVyLCBfaW50bywgcHJldmlvdXNWYWx1ZXMuY29uY2F0KHIpKSk7XG4gICAgICAgIH1cblxuICAgICAgICBic1NsaWNlID0gY29sbGVjdGlvbi5zbGljZShwYXR0ZXJuLmJ5dGVfc2l6ZSgpICogaSwgcGF0dGVybi5ieXRlX3NpemUoKSAqIChpICsgMSkpO1xuICAgICAgICBpKys7XG4gICAgICB9XG4gICAgfSBlbHNlIHtcbiAgICAgIGZvciAobGV0IGVsZW0gb2YgY29sbGVjdGlvbikge1xuICAgICAgICBsZXQgciA9IFBhdHRlcm5zLm1hdGNoX25vX3Rocm93KHBhdHRlcm4sIGVsZW0pO1xuICAgICAgICBpZiAocikge1xuICAgICAgICAgIF9pbnRvID0gaW50by5jb25jYXQodGhpcy5fZm9yKGNvbGxlY3Rpb25zLnNsaWNlKDEpLCBmdW4sIGZpbHRlciwgX2ludG8sIHByZXZpb3VzVmFsdWVzLmNvbmNhdChyKSkpO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgfVxuXG4gICAgcmV0dXJuIF9pbnRvO1xuICB9XG59XG5cbmZ1bmN0aW9uIF90cnkoZG9fZnVuLCByZXNjdWVfZnVuY3Rpb24sIGNhdGNoX2Z1biwgZWxzZV9mdW5jdGlvbiwgYWZ0ZXJfZnVuY3Rpb24pIHtcbiAgbGV0IHJlc3VsdCA9IG51bGw7XG5cbiAgdHJ5IHtcbiAgICByZXN1bHQgPSBkb19mdW4oKTtcbiAgfSBjYXRjaCAoZSkge1xuICAgIGxldCBleF9yZXN1bHQgPSBudWxsO1xuXG4gICAgaWYgKHJlc2N1ZV9mdW5jdGlvbikge1xuICAgICAgdHJ5IHtcbiAgICAgICAgZXhfcmVzdWx0ID0gcmVzY3VlX2Z1bmN0aW9uKGUpO1xuICAgICAgICByZXR1cm4gZXhfcmVzdWx0O1xuICAgICAgfSBjYXRjaCAoZXgpIHtcbiAgICAgICAgaWYgKGV4IGluc3RhbmNlb2YgUGF0dGVybnMuTWF0Y2hFcnJvcikge1xuICAgICAgICAgIHRocm93IGV4O1xuICAgICAgICB9XG4gICAgICB9XG4gICAgfVxuXG4gICAgaWYgKGNhdGNoX2Z1bikge1xuICAgICAgdHJ5IHtcbiAgICAgICAgZXhfcmVzdWx0ID0gY2F0Y2hfZnVuKGUpO1xuICAgICAgICByZXR1cm4gZXhfcmVzdWx0O1xuICAgICAgfSBjYXRjaCAoZXgpIHtcbiAgICAgICAgaWYgKGV4IGluc3RhbmNlb2YgUGF0dGVybnMuTWF0Y2hFcnJvcikge1xuICAgICAgICAgIHRocm93IGV4O1xuICAgICAgICB9XG4gICAgICB9XG4gICAgfVxuXG4gICAgdGhyb3cgZTtcbiAgfSBmaW5hbGx5IHtcbiAgICBpZiAoYWZ0ZXJfZnVuY3Rpb24pIHtcbiAgICAgIGFmdGVyX2Z1bmN0aW9uKCk7XG4gICAgfVxuICB9XG5cbiAgaWYgKGVsc2VfZnVuY3Rpb24pIHtcbiAgICB0cnkge1xuICAgICAgcmV0dXJuIGVsc2VfZnVuY3Rpb24ocmVzdWx0KTtcbiAgICB9IGNhdGNoIChleCkge1xuICAgICAgaWYgKGV4IGluc3RhbmNlb2YgUGF0dGVybnMuTWF0Y2hFcnJvcikge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoXCJObyBNYXRjaCBGb3VuZCBpbiBFbHNlXCIpO1xuICAgICAgfVxuXG4gICAgICB0aHJvdyBleDtcbiAgICB9XG4gIH0gZWxzZSB7XG4gICAgcmV0dXJuIHJlc3VsdDtcbiAgfVxufVxuXG5mdW5jdGlvbiBfd2l0aCguLi5hcmdzKSB7XG4gIGxldCBhcmdzVG9QYXNzID0gW107XG5cbiAgZm9yIChsZXQgaSA9IDA7IGkgPCBhcmdzLmxlbmd0aDsgaSsrKSB7XG4gICAgaWYgKGkgPT09IGFyZ3MubGVuZ3RoIC0gMSkge1xuICAgICAgcmV0dXJuIGFyZ3NbaV0uYXBwbHkobnVsbCwgYXJnc1RvUGFzcyk7XG4gICAgfSBlbHNlIHtcbiAgICAgIGxldCBbcGF0dGVybiwgZnVuY10gPSBhcmdzW2ldO1xuXG4gICAgICBsZXQgcmVzdWx0ID0gZnVuYy5hcHBseShudWxsLCBhcmdzVG9QYXNzKTtcblxuICAgICAgbGV0IHBhdHRlcm5SZXN1bHQgPSBQYXR0ZXJucy5tYXRjaF9ub190aHJvdyhwYXR0ZXJuLCByZXN1bHQpO1xuXG4gICAgICBpZiAocGF0dGVyblJlc3VsdCA9PSBudWxsKSB7XG4gICAgICAgIHJldHVybiByZXN1bHQ7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBhcmdzVG9QYXNzID0gYXJnc1RvUGFzcy5jb25jYXQocGF0dGVyblJlc3VsdCk7XG4gICAgICB9XG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIG51bGw7XG59XG5cbmV4cG9ydCBkZWZhdWx0IHtcbiAgX2Nhc2UsXG4gIGNvbmQsXG4gIG1hcF91cGRhdGUsXG4gIF9mb3IsXG4gIF90cnksXG4gIF93aXRoXG59O1xuLy8jIHNvdXJjZU1hcHBpbmdVUkw9ZGF0YTphcHBsaWNhdGlvbi9qc29uO2Jhc2U2NCxleUoyWlhKemFXOXVJam96TENKemIzVnlZMlZ6SWpwYklteHBZaTlqYjNKbEwzTndaV05wWVd4ZlptOXliWE11YW5NaVhTd2libUZ0WlhNaU9sdGRMQ0p0WVhCd2FXNW5jeUk2SWtGQlFVRXNUMEZCVHl4VFFVRlFMRTFCUVhOQ0xHTkJRWFJDTzBGQlEwRXNUMEZCVHl4UlFVRlFMRTFCUVhGQ0xGbEJRWEpDTzBGQlEwRXNVMEZCVXl4TFFVRlVMRkZCUVhOQ0xHTkJRWFJDT3p0QlFVVkJMRk5CUVZNc1MwRkJWQ3hEUVVGbExGTkJRV1lzUlVGQk1FSXNUMEZCTVVJc1JVRkJhME03UVVGRGFFTXNVMEZCVHl4VFFVRlRMRkZCUVZRc1EwRkJhMElzUjBGQlJ5eFBRVUZJTEVOQlFXeENMRU5CUVRoQ0xGTkJRVGxDTEVOQlFWQXNRMEZFWjBNN1EwRkJiRU03TzBGQlNVRXNVMEZCVXl4SlFVRlVMRU5CUVdNc1QwRkJaQ3hGUVVGelFqdEJRVU53UWl4UFFVRkpMRWxCUVVrc1RVRkJTaXhKUVVGakxFOUJRV3hDTEVWQlFUQkNPMEZCUTNoQ0xGRkJRVWNzVDBGQlR5eERRVUZRTEVOQlFVZ3NSVUZCWVR0QlFVTllMR0ZCUVU4c1QwRkJUeXhEUVVGUUxFZEJRVkFzUTBGRVZ6dExRVUZpTzBkQlJFWTdPMEZCVFVFc1VVRkJUU3hKUVVGSkxFdEJRVW9zUlVGQlRpeERRVkJ2UWp0RFFVRjBRanM3UVVGVlFTeFRRVUZUTEZWQlFWUXNRMEZCYjBJc1IwRkJjRUlzUlVGQmVVSXNUVUZCZWtJc1JVRkJaME03UVVGRE9VSXNVMEZCVHl4UFFVRlBMRTFCUVZBc1EwRkRUQ3hQUVVGUExFMUJRVkFzUTBGRFJTeFBRVUZQTEUxQlFWQXNRMEZCWXl4SlFVRkpMRmRCUVVvc1EwRkJaMElzVTBGQmFFSXNRMEZFYUVJc1JVRkRORU1zUjBGRU5VTXNSVUZEYVVRc1RVRkVha1FzUTBGRVN5eERRVUZRTEVOQlJEaENPME5CUVdoRE96dEJRVkZCTEZOQlFWTXNTVUZCVkN4RFFVRmpMRmRCUVdRc1JVRkJNa0lzUjBGQk0wSXNSVUZCWjBNc1UwRkJVeXhOUVVGTkxFbEJRVTRzUlVGQldTeFBRVUZQTEVWQlFWQXNSVUZCVnl4cFFrRkJhVUlzUlVGQmFrSXNSVUZCYjBJN1FVRkRiRVlzVFVGQlNTeFZRVUZWTEZsQlFWa3NRMEZCV2l4RlFVRmxMRU5CUVdZc1EwRkJWaXhEUVVRNFJUdEJRVVZzUml4TlFVRkpMR0ZCUVdFc1dVRkJXU3hEUVVGYUxFVkJRV1VzUTBGQlppeERRVUZpTEVOQlJqaEZPenRCUVVsc1JpeE5RVUZITEZsQlFWa3NUVUZCV2l4TFFVRjFRaXhEUVVGMlFpeEZRVUY1UWp0QlFVTXhRaXhSUVVGSExITkNRVUZ6UWl4VFFVRjBRaXhGUVVGblF6dEJRVU5xUXl4VlFVRkpMRlZCUVZVc1YwRkJWeXhMUVVGWUxFTkJRV2xDTEVOQlFXcENMRVZCUVc5Q0xGRkJRVkVzVTBGQlVpeEZRVUZ3UWl4RFFVRldMRU5CUkRaQ08wRkJSV3BETEZWQlFVa3NTVUZCU1N4RFFVRktMRU5CUmpaQ096dEJRVWxxUXl4aFFVRk5MRkZCUVZFc1UwRkJVaXhKUVVGeFFpeFJRVUZSTEZOQlFWSXNSVUZCY2tJc1JVRkJlVU03UVVGRE4wTXNXVUZCU1N4SlFVRkpMRk5CUVZNc1kwRkJWQ3hEUVVGM1FpeFBRVUY0UWl4RlFVRnBReXhQUVVGcVF5eERRVUZLTEVOQlJIbERPMEZCUlRkRExGbEJRVWtzVDBGQlR5eGxRVUZsTEUxQlFXWXNRMEZCYzBJc1EwRkJkRUlzUTBGQlVDeERRVVo1UXpzN1FVRkpOME1zV1VGQlJ5eExRVUZMTEU5QlFVOHNTMEZCVUN4RFFVRmhMRWxCUVdJc1JVRkJiVUlzU1VGQmJrSXNRMEZCVEN4RlFVRTRRanRCUVVNdlFpeHBRa0ZCVHl4TFFVRkxMRTFCUVV3c1EwRkJXU3hEUVVGRExFbEJRVWtzUzBGQlNpeERRVUZWTEVsQlFWWXNSVUZCWjBJc1NVRkJhRUlzUTBGQlJDeERRVUZhTEVOQlFWQXNRMEZFSzBJN1UwRkJha003TzBGQlNVRXNhMEpCUVZVc1YwRkJWeXhMUVVGWUxFTkJRV2xDTEZGQlFWRXNVMEZCVWl4TFFVRnpRaXhEUVVGMFFpeEZRVUY1UWl4UlFVRlJMRk5CUVZJc1RVRkJkVUlzU1VGQlNTeERRVUZLTEVOQlFYWkNMRU5CUVhCRUxFTkJValpETzBGQlV6ZERMRmxCVkRaRE8wOUJRUzlET3p0QlFWbEJMR0ZCUVU4c1NVRkJVQ3hEUVdoQ2FVTTdTMEZCYmtNc1RVRnBRa3M3UVVGRFNDeFhRVUZKTEVsQlFVa3NTVUZCU2l4SlFVRlpMRlZCUVdoQ0xFVkJRVEpDTzBGQlEzcENMRmxCUVVrc1NVRkJTU3hUUVVGVExHTkJRVlFzUTBGQmQwSXNUMEZCZUVJc1JVRkJhVU1zU1VGQmFrTXNRMEZCU2l4RFFVUnhRanRCUVVWNlFpeFpRVUZKTEU5QlFVOHNaVUZCWlN4TlFVRm1MRU5CUVhOQ0xFTkJRWFJDTEVOQlFWQXNRMEZHY1VJN08wRkJTWHBDTEZsQlFVY3NTMEZCU3l4UFFVRlBMRXRCUVZBc1EwRkJZU3hKUVVGaUxFVkJRVzFDTEVsQlFXNUNMRU5CUVV3c1JVRkJPRUk3UVVGREwwSXNhVUpCUVU4c1MwRkJTeXhOUVVGTUxFTkJRVmtzUTBGQlF5eEpRVUZKTEV0QlFVb3NRMEZCVlN4SlFVRldMRVZCUVdkQ0xFbEJRV2hDTEVOQlFVUXNRMEZCV2l4RFFVRlFMRU5CUkN0Q08xTkJRV3BETzA5QlNrWTdPMEZCVTBFc1lVRkJUeXhKUVVGUUxFTkJWa2M3UzBGcVFrdzdSMEZFUml4TlFUaENTenRCUVVOSUxGRkJRVWtzVVVGQlVTeEZRVUZTTEVOQlJFUTdPMEZCUjBnc1VVRkJSeXh6UWtGQmMwSXNVMEZCZEVJc1JVRkJaME03UVVGRGFrTXNWVUZCU1N4VlFVRlZMRmRCUVZjc1MwRkJXQ3hEUVVGcFFpeERRVUZxUWl4RlFVRnZRaXhSUVVGUkxGTkJRVklzUlVGQmNFSXNRMEZCVml4RFFVUTJRanRCUVVWcVF5eFZRVUZKTEVsQlFVa3NRMEZCU2l4RFFVWTJRanM3UVVGSmFrTXNZVUZCVFN4UlFVRlJMRk5CUVZJc1NVRkJjVUlzVVVGQlVTeFRRVUZTTEVWQlFYSkNMRVZCUVhsRE8wRkJRemRETEZsQlFVa3NTVUZCU1N4VFFVRlRMR05CUVZRc1EwRkJkMElzVDBGQmVFSXNSVUZCYVVNc1QwRkJha01zUTBGQlNpeERRVVI1UXp0QlFVVTNReXhaUVVGSExFTkJRVWdzUlVGQlN6dEJRVU5JTEd0Q1FVRlJMRXRCUVVzc1RVRkJUQ3hEUVVGWkxFdEJRVXNzU1VGQlRDeERRVUZWTEZsQlFWa3NTMEZCV2l4RFFVRnJRaXhEUVVGc1FpeERRVUZXTEVWQlFXZERMRWRCUVdoRExFVkJRWEZETEUxQlFYSkRMRVZCUVRaRExFdEJRVGRETEVWQlFXOUVMR1ZCUVdVc1RVRkJaaXhEUVVGelFpeERRVUYwUWl4RFFVRndSQ3hEUVVGYUxFTkJRVklzUTBGRVJ6dFRRVUZNT3p0QlFVbEJMR3RDUVVGVkxGZEJRVmNzUzBGQldDeERRVUZwUWl4UlFVRlJMRk5CUVZJc1MwRkJjMElzUTBGQmRFSXNSVUZCZVVJc1VVRkJVU3hUUVVGU0xFMUJRWFZDTEVsQlFVa3NRMEZCU2l4RFFVRjJRaXhEUVVGd1JDeERRVTQyUXp0QlFVODNReXhaUVZBMlF6dFBRVUV2UXp0TFFVcEdMRTFCWVVzN1FVRkRTQ3hYUVVGSkxFbEJRVWtzU1VGQlNpeEpRVUZaTEZWQlFXaENMRVZCUVRKQ08wRkJRM3BDTEZsQlFVa3NTVUZCU1N4VFFVRlRMR05CUVZRc1EwRkJkMElzVDBGQmVFSXNSVUZCYVVNc1NVRkJha01zUTBGQlNpeERRVVJ4UWp0QlFVVjZRaXhaUVVGSExFTkJRVWdzUlVGQlN6dEJRVU5JTEd0Q1FVRlJMRXRCUVVzc1RVRkJUQ3hEUVVGWkxFdEJRVXNzU1VGQlRDeERRVUZWTEZsQlFWa3NTMEZCV2l4RFFVRnJRaXhEUVVGc1FpeERRVUZXTEVWQlFXZERMRWRCUVdoRExFVkJRWEZETEUxQlFYSkRMRVZCUVRaRExFdEJRVGRETEVWQlFXOUVMR1ZCUVdVc1RVRkJaaXhEUVVGelFpeERRVUYwUWl4RFFVRndSQ3hEUVVGYUxFTkJRVklzUTBGRVJ6dFRRVUZNTzA5QlJrWTdTMEZrUmpzN1FVRnpRa0VzVjBGQlR5eExRVUZRTEVOQmVrSkhPMGRCT1VKTU8wTkJTa1k3TzBGQkswUkJMRk5CUVZNc1NVRkJWQ3hEUVVGakxFMUJRV1FzUlVGQmMwSXNaVUZCZEVJc1JVRkJkVU1zVTBGQmRrTXNSVUZCYTBRc1lVRkJiRVFzUlVGQmFVVXNZMEZCYWtVc1JVRkJaMFk3UVVGRE9VVXNUVUZCU1N4VFFVRlRMRWxCUVZRc1EwRkVNRVU3TzBGQlJ6bEZMRTFCUVVjN1FVRkRSQ3hoUVVGVExGRkJRVlFzUTBGRVF6dEhRVUZJTEVOQlJVTXNUMEZCVFN4RFFVRk9MRVZCUVZFN1FVRkRVQ3hSUVVGSkxGbEJRVmtzU1VGQldpeERRVVJIT3p0QlFVZFFMRkZCUVVjc1pVRkJTQ3hGUVVGdFFqdEJRVU5xUWl4VlFVRkhPMEZCUTBRc2IwSkJRVmtzWjBKQlFXZENMRU5CUVdoQ0xFTkJRVm9zUTBGRVF6dEJRVVZFTEdWQlFVOHNVMEZCVUN4RFFVWkRPMDlCUVVnc1EwRkhReXhQUVVGTkxFVkJRVTRzUlVGQlV6dEJRVU5TTEZsQlFVY3NZMEZCWXl4VFFVRlRMRlZCUVZRc1JVRkJiMEk3UVVGRGJrTXNaMEpCUVUwc1JVRkJUaXhEUVVSdFF6dFRRVUZ5UXp0UFFVUkVPMHRCU2tnN08wRkJWMEVzVVVGQlJ5eFRRVUZJTEVWQlFXRTdRVUZEV0N4VlFVRkhPMEZCUTBRc2IwSkJRVmtzVlVGQlZTeERRVUZXTEVOQlFWb3NRMEZFUXp0QlFVVkVMR1ZCUVU4c1UwRkJVQ3hEUVVaRE8wOUJRVWdzUTBGSFF5eFBRVUZOTEVWQlFVNHNSVUZCVXp0QlFVTlNMRmxCUVVjc1kwRkJZeXhUUVVGVExGVkJRVlFzUlVGQmIwSTdRVUZEYmtNc1owSkJRVTBzUlVGQlRpeERRVVJ0UXp0VFFVRnlRenRQUVVSRU8wdEJTa2c3TzBGQlYwRXNWVUZCVFN4RFFVRk9MRU5CZWtKUE8wZEJRVklzVTBFeVFrODdRVUZEVGl4UlFVRkhMR05CUVVnc1JVRkJhMEk3UVVGRGFFSXNkVUpCUkdkQ08wdEJRV3hDTzBkQk9VSkdPenRCUVcxRFFTeE5RVUZITEdGQlFVZ3NSVUZCYVVJN1FVRkRaaXhSUVVGSE8wRkJRMFFzWVVGQlR5eGpRVUZqTEUxQlFXUXNRMEZCVUN4RFFVUkRPMHRCUVVnc1EwRkZReXhQUVVGTkxFVkJRVTRzUlVGQlV6dEJRVU5PTEZWQlFVY3NZMEZCWXl4VFFVRlRMRlZCUVZRc1JVRkJiMEk3UVVGRGJrTXNZMEZCVFN4SlFVRkpMRXRCUVVvc1EwRkJWU3gzUWtGQlZpeERRVUZPTEVOQlJHMURPMDlCUVhKRE96dEJRVWxHTEZsQlFVMHNSVUZCVGl4RFFVeFJPMHRCUVZRN1IwRklTQ3hOUVZWTE8wRkJRMGdzVjBGQlR5eE5RVUZRTEVOQlJFYzdSMEZXVER0RFFYUkRSanM3UVVGeFJFRXNVMEZCVXl4TFFVRlVMRU5CUVdVc1IwRkJSeXhKUVVGSUxFVkJRVkU3UVVGRGNrSXNUVUZCU1N4aFFVRmhMRVZCUVdJc1EwRkVhVUk3TzBGQlIzSkNMRTlCUVVrc1NVRkJTU3hKUVVGSkxFTkJRVW9zUlVGQlR5eEpRVUZKTEV0QlFVc3NUVUZCVEN4RlFVRmhMRWRCUVdoRExFVkJRVzlETzBGQlEyeERMRkZCUVVjc1RVRkJUU3hMUVVGTExFMUJRVXdzUjBGQll5eERRVUZrTEVWQlFXZENPMEZCUTNaQ0xHRkJRVThzUzBGQlN5eERRVUZNTEVWQlFWRXNTMEZCVWl4RFFVRmpMRWxCUVdRc1JVRkJiMElzVlVGQmNFSXNRMEZCVUN4RFFVUjFRanRMUVVGNlFpeE5RVVZMTzBGQlEwZ3NWVUZCU1N4RFFVRkRMRTlCUVVRc1JVRkJWU3hKUVVGV0xFbEJRV3RDTEV0QlFVc3NRMEZCVEN4RFFVRnNRaXhEUVVSRU96dEJRVWRJTEZWQlFVa3NVMEZCVXl4TFFVRkxMRXRCUVV3c1EwRkJWeXhKUVVGWUxFVkJRV2xDTEZWQlFXcENMRU5CUVZRc1EwRklSRHM3UVVGTFNDeFZRVUZKTEdkQ1FVRm5RaXhUUVVGVExHTkJRVlFzUTBGQmQwSXNUMEZCZUVJc1JVRkJhVU1zVFVGQmFrTXNRMEZCYUVJc1EwRk1SRHM3UVVGUFNDeFZRVUZITEdsQ1FVRnBRaXhKUVVGcVFpeEZRVUZ6UWp0QlFVTjJRaXhsUVVGUExFMUJRVkFzUTBGRWRVSTdUMEZCZWtJc1RVRkZTenRCUVVOSUxIRkNRVUZoTEZkQlFWY3NUVUZCV0N4RFFVRnJRaXhoUVVGc1FpeERRVUZpTEVOQlJFYzdUMEZHVER0TFFWUkdPMGRCUkVZN08wRkJhMEpCTEZOQlFVOHNTVUZCVUN4RFFYSkNjVUk3UTBGQmRrSTdPMEZCZDBKQkxHVkJRV1U3UVVGRFlpeFBRVVJoTzBGQlJXSXNUVUZHWVR0QlFVZGlMRmxCU0dFN1FVRkpZaXhOUVVwaE8wRkJTMklzVFVGTVlUdEJRVTFpTEU5QlRtRTdRMEZCWmlJc0ltWnBiR1VpT2lKc2FXSXZZMjl5WlM5emNHVmphV0ZzWDJadmNtMXpMbXB6SWl3aWMyOTFjbU5sYzBOdmJuUmxiblFpT2xzaWFXMXdiM0owSUVKcGRGTjBjbWx1WnlCbWNtOXRJQ2N1TDJKcGRGOXpkSEpwYm1jbk8xeHVhVzF3YjNKMElGQmhkSFJsY201eklHWnliMjBnSnk0dmNHRjBkR1Z5Ym5Nbk8xeHVhVzF3YjNKMElIc2dWSFZ3YkdVZ2ZTQm1jbTl0SUNjdUwzQnlhVzFwZEdsMlpYTW5PMXh1WEc1bWRXNWpkR2x2YmlCZlkyRnpaU2hqYjI1a2FYUnBiMjRzSUdOc1lYVnpaWE1wZTF4dUlDQnlaWFIxY200Z1VHRjBkR1Z5Ym5NdVpHVm1iV0YwWTJnb0xpNHVZMnhoZFhObGN5a29ZMjl1WkdsMGFXOXVLVHRjYm4xY2JseHVablZ1WTNScGIyNGdZMjl1WkNoamJHRjFjMlZ6S1h0Y2JpQWdabTl5S0d4bGRDQmpiR0YxYzJVZ2IyWWdZMnhoZFhObGN5bDdYRzRnSUNBZ2FXWW9ZMnhoZFhObFd6QmRLWHRjYmlBZ0lDQWdJSEpsZEhWeWJpQmpiR0YxYzJWYk1WMG9LVHRjYmlBZ0lDQjlYRzRnSUgxY2JseHVJQ0IwYUhKdmR5QnVaWGNnUlhKeWIzSW9LVHRjYm4xY2JseHVablZ1WTNScGIyNGdiV0Z3WDNWd1pHRjBaU2h0WVhBc0lIWmhiSFZsY3lsN1hHNGdJSEpsZEhWeWJpQlBZbXBsWTNRdVpuSmxaWHBsS0Z4dUlDQWdJRTlpYW1WamRDNWhjM05wWjI0b1hHNGdJQ0FnSUNCUFltcGxZM1F1WTNKbFlYUmxLRzFoY0M1amIyNXpkSEoxWTNSdmNpNXdjbTkwYjNSNWNHVXBMQ0J0WVhBc0lIWmhiSFZsYzF4dUlDQWdJQ2xjYmlBZ0tUdGNibjFjYmx4dVpuVnVZM1JwYjI0Z1gyWnZjaWhqYjJ4c1pXTjBhVzl1Y3l3Z1puVnVMQ0JtYVd4MFpYSWdQU0FvS1NBOVBpQjBjblZsTENCcGJuUnZJRDBnVzEwc0lIQnlaWFpwYjNWelZtRnNkV1Z6SUQwZ1cxMHBlMXh1SUNCc1pYUWdjR0YwZEdWeWJpQTlJR052Ykd4bFkzUnBiMjV6V3pCZFd6QmRPMXh1SUNCc1pYUWdZMjlzYkdWamRHbHZiaUE5SUdOdmJHeGxZM1JwYjI1eld6QmRXekZkTzF4dVhHNGdJR2xtS0dOdmJHeGxZM1JwYjI1ekxteGxibWQwYUNBOVBUMGdNU2w3WEc0Z0lDQWdhV1lvWTI5c2JHVmpkR2x2YmlCcGJuTjBZVzVqWlc5bUlFSnBkRk4wY21sdVp5bDdYRzRnSUNBZ0lDQnNaWFFnWW5OVGJHbGpaU0E5SUdOdmJHeGxZM1JwYjI0dWMyeHBZMlVvTUN3Z2NHRjBkR1Z5Ymk1aWVYUmxYM05wZW1Vb0tTazdYRzRnSUNBZ0lDQnNaWFFnYVNBOUlERTdYRzVjYmlBZ0lDQWdJSGRvYVd4bEtHSnpVMnhwWTJVdVlubDBaVjl6YVhwbElEMDlJSEJoZEhSbGNtNHVZbmwwWlY5emFYcGxLQ2twZTF4dUlDQWdJQ0FnSUNCc1pYUWdjaUE5SUZCaGRIUmxjbTV6TG0xaGRHTm9YMjV2WDNSb2NtOTNLSEJoZEhSbGNtNHNJR0p6VTJ4cFkyVXBPMXh1SUNBZ0lDQWdJQ0JzWlhRZ1lYSm5jeUE5SUhCeVpYWnBiM1Z6Vm1Gc2RXVnpMbU52Ym1OaGRDaHlLVHRjYmx4dUlDQWdJQ0FnSUNCcFppaHlJQ1ltSUdacGJIUmxjaTVoY0hCc2VTaDBhR2x6TENCaGNtZHpLU2w3WEc0Z0lDQWdJQ0FnSUNBZ2FXNTBieUE5SUdsdWRHOHVZMjl1WTJGMEtGdG1kVzR1WVhCd2JIa29kR2hwY3l3Z1lYSm5jeWxkS1R0Y2JpQWdJQ0FnSUNBZ2ZWeHVYRzRnSUNBZ0lDQWdJR0p6VTJ4cFkyVWdQU0JqYjJ4c1pXTjBhVzl1TG5Oc2FXTmxLSEJoZEhSbGNtNHVZbmwwWlY5emFYcGxLQ2tnS2lCcExDQndZWFIwWlhKdUxtSjVkR1ZmYzJsNlpTZ3BJQ29nS0drZ0t5QXhLU2s3WEc0Z0lDQWdJQ0FnSUdrckt6dGNiaUFnSUNBZ0lIMWNibHh1SUNBZ0lDQWdjbVYwZFhKdUlHbHVkRzg3WEc0Z0lDQWdmV1ZzYzJWN1hHNGdJQ0FnSUNCbWIzSW9iR1YwSUdWc1pXMGdiMllnWTI5c2JHVmpkR2x2YmlsN1hHNGdJQ0FnSUNBZ0lHeGxkQ0J5SUQwZ1VHRjBkR1Z5Ym5NdWJXRjBZMmhmYm05ZmRHaHliM2NvY0dGMGRHVnliaXdnWld4bGJTazdYRzRnSUNBZ0lDQWdJR3hsZENCaGNtZHpJRDBnY0hKbGRtbHZkWE5XWVd4MVpYTXVZMjl1WTJGMEtISXBPMXh1WEc0Z0lDQWdJQ0FnSUdsbUtISWdKaVlnWm1sc2RHVnlMbUZ3Y0d4NUtIUm9hWE1zSUdGeVozTXBLWHRjYmlBZ0lDQWdJQ0FnSUNCcGJuUnZJRDBnYVc1MGJ5NWpiMjVqWVhRb1cyWjFiaTVoY0hCc2VTaDBhR2x6TENCaGNtZHpLVjBwTzF4dUlDQWdJQ0FnSUNCOVhHNGdJQ0FnSUNCOVhHNWNiaUFnSUNBZ0lISmxkSFZ5YmlCcGJuUnZPMXh1SUNBZ0lIMWNiaUFnZldWc2MyVjdYRzRnSUNBZ2JHVjBJRjlwYm5SdklEMGdXMTA3WEc1Y2JpQWdJQ0JwWmloamIyeHNaV04wYVc5dUlHbHVjM1JoYm1ObGIyWWdRbWwwVTNSeWFXNW5LWHRjYmlBZ0lDQWdJR3hsZENCaWMxTnNhV05sSUQwZ1kyOXNiR1ZqZEdsdmJpNXpiR2xqWlNnd0xDQndZWFIwWlhKdUxtSjVkR1ZmYzJsNlpTZ3BLVHRjYmlBZ0lDQWdJR3hsZENCcElEMGdNVHRjYmx4dUlDQWdJQ0FnZDJocGJHVW9Zbk5UYkdsalpTNWllWFJsWDNOcGVtVWdQVDBnY0dGMGRHVnliaTVpZVhSbFgzTnBlbVVvS1NsN1hHNGdJQ0FnSUNBZ0lHeGxkQ0J5SUQwZ1VHRjBkR1Z5Ym5NdWJXRjBZMmhmYm05ZmRHaHliM2NvY0dGMGRHVnliaXdnWW5OVGJHbGpaU2s3WEc0Z0lDQWdJQ0FnSUdsbUtISXBlMXh1SUNBZ0lDQWdJQ0FnSUY5cGJuUnZJRDBnYVc1MGJ5NWpiMjVqWVhRb2RHaHBjeTVmWm05eUtHTnZiR3hsWTNScGIyNXpMbk5zYVdObEtERXBMQ0JtZFc0c0lHWnBiSFJsY2l3Z1gybHVkRzhzSUhCeVpYWnBiM1Z6Vm1Gc2RXVnpMbU52Ym1OaGRDaHlLU2twTzF4dUlDQWdJQ0FnSUNCOVhHNWNiaUFnSUNBZ0lDQWdZbk5UYkdsalpTQTlJR052Ykd4bFkzUnBiMjR1YzJ4cFkyVW9jR0YwZEdWeWJpNWllWFJsWDNOcGVtVW9LU0FxSUdrc0lIQmhkSFJsY200dVlubDBaVjl6YVhwbEtDa2dLaUFvYVNBcklERXBLVHRjYmlBZ0lDQWdJQ0FnYVNzck8xeHVJQ0FnSUNBZ2ZWeHVJQ0FnSUgxbGJITmxlMXh1SUNBZ0lDQWdabTl5S0d4bGRDQmxiR1Z0SUc5bUlHTnZiR3hsWTNScGIyNHBlMXh1SUNBZ0lDQWdJQ0JzWlhRZ2NpQTlJRkJoZEhSbGNtNXpMbTFoZEdOb1gyNXZYM1JvY205M0tIQmhkSFJsY200c0lHVnNaVzBwTzF4dUlDQWdJQ0FnSUNCcFppaHlLWHRjYmlBZ0lDQWdJQ0FnSUNCZmFXNTBieUE5SUdsdWRHOHVZMjl1WTJGMEtIUm9hWE11WDJadmNpaGpiMnhzWldOMGFXOXVjeTV6YkdsalpTZ3hLU3dnWm5WdUxDQm1hV3gwWlhJc0lGOXBiblJ2TENCd2NtVjJhVzkxYzFaaGJIVmxjeTVqYjI1allYUW9jaWtwS1R0Y2JpQWdJQ0FnSUNBZ2ZWeHVJQ0FnSUNBZ2ZTQmNiaUFnSUNCOVhHNWNiaUFnSUNCeVpYUjFjbTRnWDJsdWRHODdYRzRnSUgxY2JuMWNibHh1Wm5WdVkzUnBiMjRnWDNSeWVTaGtiMTltZFc0c0lISmxjMk4xWlY5bWRXNWpkR2x2Yml3Z1kyRjBZMmhmWm5WdUxDQmxiSE5sWDJaMWJtTjBhVzl1TENCaFpuUmxjbDltZFc1amRHbHZiaWw3WEc0Z0lHeGxkQ0J5WlhOMWJIUWdQU0J1ZFd4c08xeHVYRzRnSUhSeWVYdGNiaUFnSUNCeVpYTjFiSFFnUFNCa2IxOW1kVzRvS1R0Y2JpQWdmV05oZEdOb0tHVXBlMXh1SUNBZ0lHeGxkQ0JsZUY5eVpYTjFiSFFnUFNCdWRXeHNPMXh1WEc0Z0lDQWdhV1lvY21WelkzVmxYMloxYm1OMGFXOXVLWHRjYmlBZ0lDQWdJSFJ5ZVh0Y2JpQWdJQ0FnSUNBZ1pYaGZjbVZ6ZFd4MElEMGdjbVZ6WTNWbFgyWjFibU4wYVc5dUtHVXBPMXh1SUNBZ0lDQWdJQ0J5WlhSMWNtNGdaWGhmY21WemRXeDBPMXh1SUNBZ0lDQWdmV05oZEdOb0tHVjRLWHRjYmlBZ0lDQWdJQ0FnYVdZb1pYZ2dhVzV6ZEdGdVkyVnZaaUJRWVhSMFpYSnVjeTVOWVhSamFFVnljbTl5S1h0Y2JpQWdJQ0FnSUNBZ0lDQjBhSEp2ZHlCbGVEdGNiaUFnSUNBZ0lDQWdmVnh1SUNBZ0lDQWdmVnh1SUNBZ0lIMWNibHh1SUNBZ0lHbG1LR05oZEdOb1gyWjFiaWw3WEc0Z0lDQWdJQ0IwY25sN1hHNGdJQ0FnSUNBZ0lHVjRYM0psYzNWc2RDQTlJR05oZEdOb1gyWjFiaWhsS1R0Y2JpQWdJQ0FnSUNBZ2NtVjBkWEp1SUdWNFgzSmxjM1ZzZER0Y2JpQWdJQ0FnSUgxallYUmphQ2hsZUNsN1hHNGdJQ0FnSUNBZ0lHbG1LR1Y0SUdsdWMzUmhibU5sYjJZZ1VHRjBkR1Z5Ym5NdVRXRjBZMmhGY25KdmNpbDdYRzRnSUNBZ0lDQWdJQ0FnZEdoeWIzY2daWGc3WEc0Z0lDQWdJQ0FnSUgxY2JpQWdJQ0FnSUgxY2JpQWdJQ0I5WEc1Y2JpQWdJQ0IwYUhKdmR5QmxPMXh1WEc0Z0lIMW1hVzVoYkd4NWUxeHVJQ0FnSUdsbUtHRm1kR1Z5WDJaMWJtTjBhVzl1S1h0Y2JpQWdJQ0FnSUdGbWRHVnlYMloxYm1OMGFXOXVLQ2s3WEc0Z0lDQWdmVnh1SUNCOVhHNWNiaUFnYVdZb1pXeHpaVjltZFc1amRHbHZiaWw3WEc0Z0lDQWdkSEo1ZTF4dUlDQWdJQ0FnY21WMGRYSnVJR1ZzYzJWZlpuVnVZM1JwYjI0b2NtVnpkV3gwS1R0Y2JpQWdJQ0I5WTJGMFkyZ29aWGdwZTF4dUlDQWdJQ0FnSUNCcFppaGxlQ0JwYm5OMFlXNWpaVzltSUZCaGRIUmxjbTV6TGsxaGRHTm9SWEp5YjNJcGUxeHVJQ0FnSUNBZ0lDQWdJSFJvY205M0lHNWxkeUJGY25KdmNpaGNJazV2SUUxaGRHTm9JRVp2ZFc1a0lHbHVJRVZzYzJWY0lpazdYRzRnSUNBZ0lDQWdJSDFjYmx4dUlDQWdJQ0FnZEdoeWIzY2daWGc3WEc0Z0lDQWdmVnh1SUNCOVpXeHpaWHRjYmlBZ0lDQnlaWFIxY200Z2NtVnpkV3gwTzF4dUlDQjlYRzU5WEc1Y2JtWjFibU4wYVc5dUlGOTNhWFJvS0M0dUxtRnlaM01wZTF4dUlDQnNaWFFnWVhKbmMxUnZVR0Z6Y3lBOUlGdGRPMXh1WEc0Z0lHWnZjaWhzWlhRZ2FTQTlJREE3SUdrZ1BDQmhjbWR6TG14bGJtZDBhRHNnYVNzcktYdGNiaUFnSUNCcFppaHBJRDA5UFNCaGNtZHpMbXhsYm1kMGFDQXRJREVwZTF4dUlDQWdJQ0FnY21WMGRYSnVJR0Z5WjNOYmFWMHVZWEJ3Ykhrb2JuVnNiQ3dnWVhKbmMxUnZVR0Z6Y3lrN1hHNGdJQ0FnZldWc2MyVjdYRzRnSUNBZ0lDQnNaWFFnVzNCaGRIUmxjbTRzSUdaMWJtTmRJRDBnWVhKbmMxdHBYVHRjYmx4dUlDQWdJQ0FnYkdWMElISmxjM1ZzZENBOUlHWjFibU11WVhCd2JIa29iblZzYkN3Z1lYSm5jMVJ2VUdGemN5azdYRzVjYmlBZ0lDQWdJR3hsZENCd1lYUjBaWEp1VW1WemRXeDBJRDBnVUdGMGRHVnlibk11YldGMFkyaGZibTlmZEdoeWIzY29jR0YwZEdWeWJpd2djbVZ6ZFd4MEtUdGNibHh1SUNBZ0lDQWdhV1lvY0dGMGRHVnlibEpsYzNWc2RDQTlQU0J1ZFd4c0tYdGNiaUFnSUNBZ0lDQWdjbVYwZFhKdUlISmxjM1ZzZER0Y2JpQWdJQ0FnSUgxbGJITmxlMXh1SUNBZ0lDQWdJQ0JoY21kelZHOVFZWE56SUQwZ1lYSm5jMVJ2VUdGemN5NWpiMjVqWVhRb2NHRjBkR1Z5YmxKbGMzVnNkQ2s3WEc0Z0lDQWdJQ0I5WEc0Z0lDQWdmVnh1SUNCOVhHNWNiaUFnY21WMGRYSnVJRzUxYkd3N1hHNTlYRzVjYm1WNGNHOXlkQ0JrWldaaGRXeDBJSHRjYmlBZ1gyTmhjMlVzWEc0Z0lHTnZibVFzWEc0Z0lHMWhjRjkxY0dSaGRHVXNYRzRnSUY5bWIzSXNYRzRnSUY5MGNua3NYRzRnSUY5M2FYUm9YRzU5TzF4dUlsMHNJbk52ZFhKalpWSnZiM1FpT2lJdmMyOTFjbU5sTHlKOVxuIiwiaW1wb3J0IFByb2Nlc3NTeXN0ZW0gZnJvbSAnLi9jb3JlL3Byb2Nlc3Nlcy9wcm9jZXNzX3N5c3RlbSc7XG5pbXBvcnQgeyBUdXBsZSwgUElELCBJbnRlZ2VyLCBGbG9hdCB9IGZyb20gJy4vY29yZS9wcmltaXRpdmVzJztcbmltcG9ydCBCaXRTdHJpbmcgZnJvbSAnLi9jb3JlL2JpdF9zdHJpbmcnO1xuaW1wb3J0IFBhdHRlcm5zIGZyb20gJy4vY29yZS9wYXR0ZXJucyc7XG5pbXBvcnQgRnVuY3Rpb25zIGZyb20gJy4vY29yZS9mdW5jdGlvbnMnO1xuaW1wb3J0IFNwZWNpYWxGb3JtcyBmcm9tICcuL2NvcmUvc3BlY2lhbF9mb3Jtcyc7XG5cbkZ1bmN0aW9ucy5nZXRfZ2xvYmFsKCkucHJvY2Vzc2VzID0gRnVuY3Rpb25zLmdldF9nbG9iYWwoKS5wcm9jZXNzZXMgfHwgbmV3IFByb2Nlc3NTeXN0ZW0oKTtcblxuZXhwb3J0IGRlZmF1bHQge1xuICBQcm9jZXNzU3lzdGVtLFxuICBUdXBsZSxcbiAgUElELFxuICBCaXRTdHJpbmcsXG4gIFBhdHRlcm5zLFxuICBJbnRlZ2VyLFxuICBGbG9hdCxcbiAgRnVuY3Rpb25zLFxuICBTcGVjaWFsRm9ybXNcbn07XG4vLyMgc291cmNlTWFwcGluZ1VSTD1kYXRhOmFwcGxpY2F0aW9uL2pzb247YmFzZTY0LGV5SjJaWEp6YVc5dUlqb3pMQ0p6YjNWeVkyVnpJanBiSW14cFlpOWpiM0psTG1weklsMHNJbTVoYldWeklqcGJYU3dpYldGd2NHbHVaM01pT2lKQlFVRkJMRTlCUVU4c1lVRkJVQ3hOUVVFd1FpeHBRMEZCTVVJN1FVRkRRU3hUUVVGVExFdEJRVlFzUlVGQlowSXNSMEZCYUVJc1JVRkJjVUlzVDBGQmNrSXNSVUZCT0VJc1MwRkJPVUlzVVVGQk1rTXNiVUpCUVRORE8wRkJRMEVzVDBGQlR5eFRRVUZRTEUxQlFYTkNMRzFDUVVGMFFqdEJRVU5CTEU5QlFVOHNVVUZCVUN4TlFVRnhRaXhwUWtGQmNrSTdRVUZEUVN4UFFVRlBMRk5CUVZBc1RVRkJjMElzYTBKQlFYUkNPMEZCUTBFc1QwRkJUeXhaUVVGUUxFMUJRWGxDTEhOQ1FVRjZRanM3UVVGRlFTeFZRVUZWTEZWQlFWWXNSMEZCZFVJc1UwRkJka0lzUjBGQmJVTXNWVUZCVlN4VlFVRldMRWRCUVhWQ0xGTkJRWFpDTEVsQlFXOURMRWxCUVVrc1lVRkJTaXhGUVVGd1F6czdRVUZGYmtNc1pVRkJaVHRCUVVOaUxHVkJSR0U3UVVGRllpeFBRVVpoTzBGQlIySXNTMEZJWVR0QlFVbGlMRmRCU21FN1FVRkxZaXhWUVV4aE8wRkJUV0lzVTBGT1lUdEJRVTlpTEU5QlVHRTdRVUZSWWl4WFFWSmhPMEZCVTJJc1kwRlVZVHREUVVGbUlpd2labWxzWlNJNklteHBZaTlqYjNKbExtcHpJaXdpYzI5MWNtTmxjME52Ym5SbGJuUWlPbHNpYVcxd2IzSjBJRkJ5YjJObGMzTlRlWE4wWlcwZ1puSnZiU0FuTGk5amIzSmxMM0J5YjJObGMzTmxjeTl3Y205alpYTnpYM041YzNSbGJTYzdYRzVwYlhCdmNuUWdleUJVZFhCc1pTd2dVRWxFTENCSmJuUmxaMlZ5TENCR2JHOWhkQ0I5SUdaeWIyMGdKeTR2WTI5eVpTOXdjbWx0YVhScGRtVnpKenRjYm1sdGNHOXlkQ0JDYVhSVGRISnBibWNnWm5KdmJTQW5MaTlqYjNKbEwySnBkRjl6ZEhKcGJtY25PMXh1YVcxd2IzSjBJRkJoZEhSbGNtNXpJR1p5YjIwZ0p5NHZZMjl5WlM5d1lYUjBaWEp1Y3ljN1hHNXBiWEJ2Y25RZ1JuVnVZM1JwYjI1eklHWnliMjBnSnk0dlkyOXlaUzltZFc1amRHbHZibk1uTzF4dWFXMXdiM0owSUZOd1pXTnBZV3hHYjNKdGN5Qm1jbTl0SUNjdUwyTnZjbVV2YzNCbFkybGhiRjltYjNKdGN5YzdYRzVjYmtaMWJtTjBhVzl1Y3k1blpYUmZaMnh2WW1Gc0tDa3VjSEp2WTJWemMyVnpJRDBnUm5WdVkzUnBiMjV6TG1kbGRGOW5iRzlpWVd3b0tTNXdjbTlqWlhOelpYTWdmSHdnYm1WM0lGQnliMk5sYzNOVGVYTjBaVzBvS1R0Y2JseHVaWGh3YjNKMElHUmxabUYxYkhRZ2UxeHVJQ0JRY205alpYTnpVM2x6ZEdWdExGeHVJQ0JVZFhCc1pTeGNiaUFnVUVsRUxGeHVJQ0JDYVhSVGRISnBibWNzWEc0Z0lGQmhkSFJsY201ekxGeHVJQ0JKYm5SbFoyVnlMRnh1SUNCR2JHOWhkQ3hjYmlBZ1JuVnVZM1JwYjI1ekxGeHVJQ0JUY0dWamFXRnNSbTl5YlhOY2JuMWNiaUpkTENKemIzVnlZMlZTYjI5MElqb2lMM052ZFhKalpTOGlmUT09XG4iLCJpbXBvcnQgQ29yZSBmcm9tICcuL2NvcmUnO1xuXG5sZXQgRW51bSA9IHtcblxuICBhbGxfX3FtYXJrX186IGZ1bmN0aW9uIChjb2xsZWN0aW9uLCBmdW4gPSB4ID0+IHgpIHtcbiAgICBmb3IgKGxldCBlbGVtIG9mIGNvbGxlY3Rpb24pIHtcbiAgICAgIGlmICghZnVuKGVsZW0pKSB7XG4gICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICByZXR1cm4gdHJ1ZTtcbiAgfSxcblxuICBhbnlfX3FtYXJrX186IGZ1bmN0aW9uIChjb2xsZWN0aW9uLCBmdW4gPSB4ID0+IHgpIHtcbiAgICBmb3IgKGxldCBlbGVtIG9mIGNvbGxlY3Rpb24pIHtcbiAgICAgIGlmIChmdW4oZWxlbSkpIHtcbiAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICB9XG4gICAgfVxuXG4gICAgcmV0dXJuIGZhbHNlO1xuICB9LFxuXG4gIGF0OiBmdW5jdGlvbiAoY29sbGVjdGlvbiwgbiwgdGhlX2RlZmF1bHQgPSBudWxsKSB7XG4gICAgaWYgKG4gPiB0aGlzLmNvdW50KGNvbGxlY3Rpb24pIHx8IG4gPCAwKSB7XG4gICAgICByZXR1cm4gdGhlX2RlZmF1bHQ7XG4gICAgfVxuXG4gICAgcmV0dXJuIGNvbGxlY3Rpb25bbl07XG4gIH0sXG5cbiAgY29uY2F0OiBmdW5jdGlvbiAoLi4uZW51bWFibGVzKSB7XG4gICAgcmV0dXJuIGVudW1hYmxlc1swXS5jb25jYXQoZW51bWFibGVzWzFdKTtcbiAgfSxcblxuICBjb3VudDogZnVuY3Rpb24gKGNvbGxlY3Rpb24sIGZ1biA9IG51bGwpIHtcbiAgICBpZiAoZnVuID09IG51bGwpIHtcbiAgICAgIHJldHVybiBjb2xsZWN0aW9uLmxlbmd0aDtcbiAgICB9IGVsc2Uge1xuICAgICAgcmV0dXJuIGNvbGxlY3Rpb24uZmlsdGVyKGZ1bikubGVuZ3RoO1xuICAgIH1cbiAgfSxcblxuICBkcm9wOiBmdW5jdGlvbiAoY29sbGVjdGlvbiwgY291bnQpIHtcbiAgICByZXR1cm4gY29sbGVjdGlvbi5zbGljZShjb3VudCk7XG4gIH0sXG5cbiAgZHJvcF93aGlsZTogZnVuY3Rpb24gKGNvbGxlY3Rpb24sIGZ1bikge1xuICAgIGxldCBjb3VudCA9IDA7XG5cbiAgICBmb3IgKGxldCBlbGVtIG9mIGNvbGxlY3Rpb24pIHtcbiAgICAgIGlmIChmdW4oZWxlbSkpIHtcbiAgICAgICAgY291bnQgPSBjb3VudCArIDE7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBicmVhaztcbiAgICAgIH1cbiAgICB9XG5cbiAgICByZXR1cm4gY29sbGVjdGlvbi5zbGljZShjb3VudCk7XG4gIH0sXG5cbiAgZWFjaDogZnVuY3Rpb24gKGNvbGxlY3Rpb24sIGZ1bikge1xuICAgIGZvciAobGV0IGVsZW0gb2YgY29sbGVjdGlvbikge1xuICAgICAgZnVuKGVsZW0pO1xuICAgIH1cbiAgfSxcblxuICBlbXB0eV9fcW1hcmtfXzogZnVuY3Rpb24gKGNvbGxlY3Rpb24pIHtcbiAgICByZXR1cm4gY29sbGVjdGlvbi5sZW5ndGggPT09IDA7XG4gIH0sXG5cbiAgZmV0Y2g6IGZ1bmN0aW9uIChjb2xsZWN0aW9uLCBuKSB7XG4gICAgaWYgKEFycmF5LmlzQXJyYXkoY29sbGVjdGlvbikpIHtcbiAgICAgIGlmIChuIDwgdGhpcy5jb3VudChjb2xsZWN0aW9uKSAmJiBuID49IDApIHtcbiAgICAgICAgcmV0dXJuIG5ldyBDb3JlLlR1cGxlKFN5bWJvbC5mb3IoXCJva1wiKSwgY29sbGVjdGlvbltuXSk7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICByZXR1cm4gU3ltYm9sLmZvcihcImVycm9yXCIpO1xuICAgICAgfVxuICAgIH1cblxuICAgIHRocm93IG5ldyBFcnJvcihcImNvbGxlY3Rpb24gaXMgbm90IGFuIEVudW1lcmFibGVcIik7XG4gIH0sXG5cbiAgZmV0Y2hfX2VtYXJrX186IGZ1bmN0aW9uIChjb2xsZWN0aW9uLCBuKSB7XG4gICAgaWYgKEFycmF5LmlzQXJyYXkoY29sbGVjdGlvbikpIHtcbiAgICAgIGlmIChuIDwgdGhpcy5jb3VudChjb2xsZWN0aW9uKSAmJiBuID49IDApIHtcbiAgICAgICAgcmV0dXJuIGNvbGxlY3Rpb25bbl07XG4gICAgICB9IGVsc2Uge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoXCJvdXQgb2YgYm91bmRzIGVycm9yXCIpO1xuICAgICAgfVxuICAgIH1cblxuICAgIHRocm93IG5ldyBFcnJvcihcImNvbGxlY3Rpb24gaXMgbm90IGFuIEVudW1lcmFibGVcIik7XG4gIH0sXG5cbiAgZmlsdGVyOiBmdW5jdGlvbiAoY29sbGVjdGlvbiwgZnVuKSB7XG4gICAgbGV0IHJlc3VsdCA9IFtdO1xuXG4gICAgZm9yIChsZXQgZWxlbSBvZiBjb2xsZWN0aW9uKSB7XG4gICAgICBpZiAoZnVuKGVsZW0pKSB7XG4gICAgICAgIHJlc3VsdC5wdXNoKGVsZW0pO1xuICAgICAgfVxuICAgIH1cblxuICAgIHJldHVybiByZXN1bHQ7XG4gIH0sXG5cbiAgZmlsdGVyX21hcDogZnVuY3Rpb24gKGNvbGxlY3Rpb24sIGZpbHRlciwgbWFwcGVyKSB7XG4gICAgcmV0dXJuIEVudW0ubWFwKEVudW0uZmlsdGVyKGNvbGxlY3Rpb24sIGZpbHRlciksIG1hcHBlcik7XG4gIH0sXG5cbiAgZmluZDogZnVuY3Rpb24gKGNvbGxlY3Rpb24sIGlmX25vbmUgPSBudWxsLCBmdW4pIHtcbiAgICBmb3IgKGxldCBlbGVtIG9mIGNvbGxlY3Rpb24pIHtcbiAgICAgIGlmIChmdW4oZWxlbSkpIHtcbiAgICAgICAgcmV0dXJuIGVsZW07XG4gICAgICB9XG4gICAgfVxuXG4gICAgcmV0dXJuIGlmX25vbmU7XG4gIH0sXG5cbiAgaW50bzogZnVuY3Rpb24gKGNvbGxlY3Rpb24sIGxpc3QpIHtcbiAgICByZXR1cm4gbGlzdC5jb25jYXQoY29sbGVjdGlvbik7XG4gIH0sXG5cbiAgbWFwOiBmdW5jdGlvbiAoY29sbGVjdGlvbiwgZnVuKSB7XG4gICAgbGV0IHJlc3VsdCA9IFtdO1xuXG4gICAgZm9yIChsZXQgZWxlbSBvZiBjb2xsZWN0aW9uKSB7XG4gICAgICByZXN1bHQucHVzaChmdW4oZWxlbSkpO1xuICAgIH1cblxuICAgIHJldHVybiByZXN1bHQ7XG4gIH0sXG5cbiAgbWFwX3JlZHVjZTogZnVuY3Rpb24gKGNvbGxlY3Rpb24sIGFjYywgZnVuKSB7XG4gICAgbGV0IG1hcHBlZCA9IE9iamVjdC5mcmVlemUoW10pO1xuICAgIGxldCB0aGVfYWNjID0gYWNjO1xuXG4gICAgZm9yICh2YXIgaSA9IDA7IGkgPCB0aGlzLmNvdW50KGNvbGxlY3Rpb24pOyBpKyspIHtcbiAgICAgIGxldCB0dXBsZSA9IGZ1bihjb2xsZWN0aW9uW2ldLCB0aGVfYWNjKTtcblxuICAgICAgdGhlX2FjYyA9IHR1cGxlLmdldCgxKTtcbiAgICAgIG1hcHBlZCA9IE9iamVjdC5mcmVlemUobWFwcGVkLmNvbmNhdChbdHVwbGUuZ2V0KDApXSkpO1xuICAgIH1cblxuICAgIHJldHVybiBuZXcgQ29yZS5UdXBsZShtYXBwZWQsIHRoZV9hY2MpO1xuICB9LFxuXG4gIG1lbWJlcl9fcW1hcmtfXzogZnVuY3Rpb24gKGNvbGxlY3Rpb24sIHZhbHVlKSB7XG4gICAgcmV0dXJuIGNvbGxlY3Rpb24uaW5jbHVkZXModmFsdWUpO1xuICB9LFxuXG4gIHJlZHVjZTogZnVuY3Rpb24gKGNvbGxlY3Rpb24sIGFjYywgZnVuKSB7XG4gICAgbGV0IHRoZV9hY2MgPSBhY2M7XG5cbiAgICBmb3IgKHZhciBpID0gMDsgaSA8IHRoaXMuY291bnQoY29sbGVjdGlvbik7IGkrKykge1xuICAgICAgbGV0IHR1cGxlID0gZnVuKGNvbGxlY3Rpb25baV0sIHRoZV9hY2MpO1xuXG4gICAgICB0aGVfYWNjID0gdHVwbGUuZ2V0KDEpO1xuICAgIH1cblxuICAgIHJldHVybiB0aGVfYWNjO1xuICB9LFxuXG4gIHRha2U6IGZ1bmN0aW9uIChjb2xsZWN0aW9uLCBjb3VudCkge1xuICAgIHJldHVybiBjb2xsZWN0aW9uLnNsaWNlKDAsIGNvdW50KTtcbiAgfSxcblxuICB0YWtlX2V2ZXJ5OiBmdW5jdGlvbiAoY29sbGVjdGlvbiwgbnRoKSB7XG4gICAgbGV0IHJlc3VsdCA9IFtdO1xuICAgIGxldCBpbmRleCA9IDA7XG5cbiAgICBmb3IgKGxldCBlbGVtIG9mIGNvbGxlY3Rpb24pIHtcbiAgICAgIGlmIChpbmRleCAlIG50aCA9PT0gMCkge1xuICAgICAgICByZXN1bHQucHVzaChlbGVtKTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICByZXR1cm4gT2JqZWN0LmZyZWV6ZShyZXN1bHQpO1xuICB9LFxuXG4gIHRha2Vfd2hpbGU6IGZ1bmN0aW9uIChjb2xsZWN0aW9uLCBmdW4pIHtcbiAgICBsZXQgY291bnQgPSAwO1xuXG4gICAgZm9yIChsZXQgZWxlbSBvZiBjb2xsZWN0aW9uKSB7XG4gICAgICBpZiAoZnVuKGVsZW0pKSB7XG4gICAgICAgIGNvdW50ID0gY291bnQgKyAxO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgYnJlYWs7XG4gICAgICB9XG4gICAgfVxuXG4gICAgcmV0dXJuIGNvbGxlY3Rpb24uc2xpY2UoMCwgY291bnQpO1xuICB9LFxuXG4gIHRvX2xpc3Q6IGZ1bmN0aW9uIChjb2xsZWN0aW9uKSB7XG4gICAgcmV0dXJuIGNvbGxlY3Rpb247XG4gIH1cbn07XG5cbmV4cG9ydCBkZWZhdWx0IEVudW07XG4vLyMgc291cmNlTWFwcGluZ1VSTD1kYXRhOmFwcGxpY2F0aW9uL2pzb247YmFzZTY0LGV5SjJaWEp6YVc5dUlqb3pMQ0p6YjNWeVkyVnpJanBiSW14cFlpOWxiblZ0TG1weklsMHNJbTVoYldWeklqcGJYU3dpYldGd2NHbHVaM01pT2lKQlFVRkJMRTlCUVU4c1NVRkJVQ3hOUVVGcFFpeFJRVUZxUWpzN1FVRkZRU3hKUVVGSkxFOUJRVTg3TzBGQlJWUXNaMEpCUVdNc1ZVRkJVeXhWUVVGVUxFVkJRWEZDTEUxQlFVMHNTMEZCVHl4RFFVRlFMRVZCUVZNN1FVRkRhRVFzVTBGQlNTeEpRVUZKTEVsQlFVb3NTVUZCV1N4VlFVRm9RaXhGUVVFeVFqdEJRVU42UWl4VlFVRkhMRU5CUVVNc1NVRkJTU3hKUVVGS0xFTkJRVVFzUlVGQlZ6dEJRVU5hTEdWQlFVOHNTMEZCVUN4RFFVUlpPMDlCUVdRN1MwRkVSanM3UVVGTlFTeFhRVUZQTEVsQlFWQXNRMEZRWjBRN1IwRkJjRU03TzBGQlZXUXNaMEpCUVdNc1ZVRkJVeXhWUVVGVUxFVkJRWEZDTEUxQlFVMHNTMEZCVHl4RFFVRlFMRVZCUVZNN1FVRkRhRVFzVTBGQlNTeEpRVUZKTEVsQlFVb3NTVUZCV1N4VlFVRm9RaXhGUVVFeVFqdEJRVU42UWl4VlFVRkhMRWxCUVVrc1NVRkJTaXhEUVVGSUxFVkJRV0U3UVVGRFdDeGxRVUZQTEVsQlFWQXNRMEZFVnp0UFFVRmlPMHRCUkVZN08wRkJUVUVzVjBGQlR5eExRVUZRTEVOQlVHZEVPMGRCUVhCRE96dEJRVlZrTEUxQlFVa3NWVUZCVXl4VlFVRlVMRVZCUVhGQ0xFTkJRWEpDTEVWQlFYZENMR05CUVdNc1NVRkJaQ3hGUVVGdFFqdEJRVU0zUXl4UlFVRkhMRWxCUVVrc1MwRkJTeXhMUVVGTUxFTkJRVmNzVlVGQldDeERRVUZLTEVsQlFUaENMRWxCUVVrc1EwRkJTaXhGUVVGTk8wRkJRM0pETEdGQlFVOHNWMEZCVUN4RFFVUnhRenRMUVVGMlF6czdRVUZKUVN4WFFVRlBMRmRCUVZjc1EwRkJXQ3hEUVVGUUxFTkJURFpETzBkQlFUTkRPenRCUVZGS0xGVkJRVkVzVlVGQlV5eEhRVUZITEZOQlFVZ3NSVUZCWVR0QlFVTTFRaXhYUVVGUExGVkJRVlVzUTBGQlZpeEZRVUZoTEUxQlFXSXNRMEZCYjBJc1ZVRkJWU3hEUVVGV0xFTkJRWEJDTEVOQlFWQXNRMEZFTkVJN1IwRkJkRUk3TzBGQlNWSXNVMEZCVHl4VlFVRlRMRlZCUVZRc1JVRkJjVUlzVFVGQlRTeEpRVUZPTEVWQlFWYzdRVUZEY2tNc1VVRkJSeXhQUVVGUExFbEJRVkFzUlVGQldUdEJRVU5pTEdGQlFVOHNWMEZCVnl4TlFVRllMRU5CUkUwN1MwRkJaaXhOUVVWUE8wRkJRMHdzWVVGQlR5eFhRVUZYTEUxQlFWZ3NRMEZCYTBJc1IwRkJiRUlzUlVGQmRVSXNUVUZCZGtJc1EwRkVSanRMUVVaUU8wZEJSRXM3TzBGQlVWQXNVVUZCVFN4VlFVRlRMRlZCUVZRc1JVRkJjVUlzUzBGQmNrSXNSVUZCTWtJN1FVRkRMMElzVjBGQlR5eFhRVUZYTEV0QlFWZ3NRMEZCYVVJc1MwRkJha0lzUTBGQlVDeERRVVFyUWp0SFFVRXpRanM3UVVGSlRpeGpRVUZaTEZWQlFWTXNWVUZCVkN4RlFVRnhRaXhIUVVGeVFpeEZRVUY1UWp0QlFVTnVReXhSUVVGSkxGRkJRVkVzUTBGQlVpeERRVVFyUWpzN1FVRkhia01zVTBGQlNTeEpRVUZKTEVsQlFVb3NTVUZCV1N4VlFVRm9RaXhGUVVFeVFqdEJRVU42UWl4VlFVRkhMRWxCUVVrc1NVRkJTaXhEUVVGSUxFVkJRV0U3UVVGRFdDeG5Ra0ZCVVN4UlFVRlJMRU5CUVZJc1EwRkVSenRQUVVGaUxFMUJSVXM3UVVGRFNDeGpRVVJITzA5QlJrdzdTMEZFUmpzN1FVRlJRU3hYUVVGUExGZEJRVmNzUzBGQldDeERRVUZwUWl4TFFVRnFRaXhEUVVGUUxFTkJXRzFETzBkQlFYcENPenRCUVdOYUxGRkJRVTBzVlVGQlV5eFZRVUZVTEVWQlFYRkNMRWRCUVhKQ0xFVkJRWGxDTzBGQlF6ZENMRk5CUVVrc1NVRkJTU3hKUVVGS0xFbEJRVmtzVlVGQmFFSXNSVUZCTWtJN1FVRkRla0lzVlVGQlNTeEpRVUZLTEVWQlJIbENPMHRCUVROQ08wZEJSRWs3TzBGQlRVNHNhMEpCUVdkQ0xGVkJRVk1zVlVGQlZDeEZRVUZ2UWp0QlFVTnNReXhYUVVGUExGZEJRVmNzVFVGQldDeExRVUZ6UWl4RFFVRjBRaXhEUVVReVFqdEhRVUZ3UWpzN1FVRkphRUlzVTBGQlR5eFZRVUZUTEZWQlFWUXNSVUZCY1VJc1EwRkJja0lzUlVGQmRVSTdRVUZETlVJc1VVRkJSeXhOUVVGTkxFOUJRVTRzUTBGQll5eFZRVUZrTEVOQlFVZ3NSVUZCTmtJN1FVRkRNMElzVlVGQlJ5eEpRVUZKTEV0QlFVc3NTMEZCVEN4RFFVRlhMRlZCUVZnc1EwRkJTaXhKUVVFNFFpeExRVUZMTEVOQlFVd3NSVUZCVHp0QlFVTjBReXhsUVVGUExFbEJRVWtzUzBGQlN5eExRVUZNTEVOQlFWY3NUMEZCVHl4SFFVRlFMRU5CUVZjc1NVRkJXQ3hEUVVGbUxFVkJRV2xETEZkQlFWY3NRMEZCV0N4RFFVRnFReXhEUVVGUUxFTkJSSE5ETzA5QlFYaERMRTFCUlVzN1FVRkRTQ3hsUVVGUExFOUJRVThzUjBGQlVDeERRVUZYTEU5QlFWZ3NRMEZCVUN4RFFVUkhPMDlCUmt3N1MwRkVSanM3UVVGUlFTeFZRVUZOTEVsQlFVa3NTMEZCU2l4RFFVRlZMR2xEUVVGV0xFTkJRVTRzUTBGVU5FSTdSMEZCZGtJN08wRkJXVkFzYTBKQlFXZENMRlZCUVZNc1ZVRkJWQ3hGUVVGeFFpeERRVUZ5UWl4RlFVRjFRanRCUVVOeVF5eFJRVUZITEUxQlFVMHNUMEZCVGl4RFFVRmpMRlZCUVdRc1EwRkJTQ3hGUVVFMlFqdEJRVU16UWl4VlFVRkhMRWxCUVVrc1MwRkJTeXhMUVVGTUxFTkJRVmNzVlVGQldDeERRVUZLTEVsQlFUaENMRXRCUVVzc1EwRkJUQ3hGUVVGUE8wRkJRM1JETEdWQlFVOHNWMEZCVnl4RFFVRllMRU5CUVZBc1EwRkVjME03VDBGQmVFTXNUVUZGU3p0QlFVTklMR05CUVUwc1NVRkJTU3hMUVVGS0xFTkJRVlVzY1VKQlFWWXNRMEZCVGl4RFFVUkhPMDlCUmt3N1MwRkVSanM3UVVGUlFTeFZRVUZOTEVsQlFVa3NTMEZCU2l4RFFVRlZMR2xEUVVGV0xFTkJRVTRzUTBGVWNVTTdSMEZCZGtJN08wRkJXV2hDTEZWQlFWRXNWVUZCVXl4VlFVRlVMRVZCUVhGQ0xFZEJRWEpDTEVWQlFYbENPMEZCUXk5Q0xGRkJRVWtzVTBGQlV5eEZRVUZVTEVOQlJESkNPenRCUVVjdlFpeFRRVUZKTEVsQlFVa3NTVUZCU2l4SlFVRlpMRlZCUVdoQ0xFVkJRVEpDTzBGQlEzcENMRlZCUVVjc1NVRkJTU3hKUVVGS0xFTkJRVWdzUlVGQllUdEJRVU5ZTEdWQlFVOHNTVUZCVUN4RFFVRlpMRWxCUVZvc1JVRkVWenRQUVVGaU8wdEJSRVk3TzBGQlRVRXNWMEZCVHl4TlFVRlFMRU5CVkN0Q08wZEJRWHBDT3p0QlFWbFNMR05CUVZrc1ZVRkJVeXhWUVVGVUxFVkJRWEZDTEUxQlFYSkNMRVZCUVRaQ0xFMUJRVGRDTEVWQlFXOURPMEZCUXpsRExGZEJRVThzUzBGQlN5eEhRVUZNTEVOQlFWTXNTMEZCU3l4TlFVRk1MRU5CUVZrc1ZVRkJXaXhGUVVGM1FpeE5RVUY0UWl4RFFVRlVMRVZCUVRCRExFMUJRVEZETEVOQlFWQXNRMEZFT0VNN1IwRkJjRU03TzBGQlNWb3NVVUZCVFN4VlFVRlRMRlZCUVZRc1JVRkJjVUlzVlVGQlZTeEpRVUZXTEVWQlFXZENMRWRCUVhKRExFVkJRWGxETzBGQlF6ZERMRk5CUVVrc1NVRkJTU3hKUVVGS0xFbEJRVmtzVlVGQmFFSXNSVUZCTWtJN1FVRkRla0lzVlVGQlJ5eEpRVUZKTEVsQlFVb3NRMEZCU0N4RlFVRmhPMEZCUTFnc1pVRkJUeXhKUVVGUUxFTkJSRmM3VDBGQllqdExRVVJHT3p0QlFVMUJMRmRCUVU4c1QwRkJVQ3hEUVZBMlF6dEhRVUY2UXpzN1FVRlZUaXhSUVVGTkxGVkJRVk1zVlVGQlZDeEZRVUZ4UWl4SlFVRnlRaXhGUVVFd1FqdEJRVU01UWl4WFFVRlBMRXRCUVVzc1RVRkJUQ3hEUVVGWkxGVkJRVm9zUTBGQlVDeERRVVE0UWp0SFFVRXhRanM3UVVGSlRpeFBRVUZMTEZWQlFWTXNWVUZCVkN4RlFVRnhRaXhIUVVGeVFpeEZRVUY1UWp0QlFVTTFRaXhSUVVGSkxGTkJRVk1zUlVGQlZDeERRVVIzUWpzN1FVRkhOVUlzVTBGQlNTeEpRVUZKTEVsQlFVb3NTVUZCV1N4VlFVRm9RaXhGUVVFeVFqdEJRVU42UWl4aFFVRlBMRWxCUVZBc1EwRkJXU3hKUVVGSkxFbEJRVW9zUTBGQldpeEZRVVI1UWp0TFFVRXpRanM3UVVGSlFTeFhRVUZQTEUxQlFWQXNRMEZRTkVJN1IwRkJla0k3TzBGQlZVd3NZMEZCV1N4VlFVRlRMRlZCUVZRc1JVRkJjVUlzUjBGQmNrSXNSVUZCTUVJc1IwRkJNVUlzUlVGQk9FSTdRVUZEZUVNc1VVRkJTU3hUUVVGVExFOUJRVThzVFVGQlVDeERRVUZqTEVWQlFXUXNRMEZCVkN4RFFVUnZRenRCUVVWNFF5eFJRVUZKTEZWQlFWVXNSMEZCVml4RFFVWnZRenM3UVVGSmVFTXNVMEZCU3l4SlFVRkpMRWxCUVVrc1EwRkJTaXhGUVVGUExFbEJRVWtzUzBGQlN5eExRVUZNTEVOQlFWY3NWVUZCV0N4RFFVRktMRVZCUVRSQ0xFZEJRVFZETEVWQlFXbEVPMEZCUXk5RExGVkJRVWtzVVVGQlVTeEpRVUZKTEZkQlFWY3NRMEZCV0N4RFFVRktMRVZCUVcxQ0xFOUJRVzVDTEVOQlFWSXNRMEZFTWtNN08wRkJSeTlETEdkQ1FVRlZMRTFCUVUwc1IwRkJUaXhEUVVGVkxFTkJRVllzUTBGQlZpeERRVWdyUXp0QlFVa3ZReXhsUVVGVExFOUJRVThzVFVGQlVDeERRVUZqTEU5QlFVOHNUVUZCVUN4RFFVRmpMRU5CUVVNc1RVRkJUU3hIUVVGT0xFTkJRVlVzUTBGQlZpeERRVUZFTEVOQlFXUXNRMEZCWkN4RFFVRlVMRU5CU2l0RE8wdEJRV3BFT3p0QlFVOUJMRmRCUVU4c1NVRkJTU3hMUVVGTExFdEJRVXdzUTBGQlZ5eE5RVUZtTEVWQlFYVkNMRTlCUVhaQ0xFTkJRVkFzUTBGWWQwTTdSMEZCT1VJN08wRkJZMW9zYlVKQlFXbENMRlZCUVZNc1ZVRkJWQ3hGUVVGeFFpeExRVUZ5UWl4RlFVRXlRanRCUVVNeFF5eFhRVUZQTEZkQlFWY3NVVUZCV0N4RFFVRnZRaXhMUVVGd1FpeERRVUZRTEVOQlJEQkRPMGRCUVROQ096dEJRVWxxUWl4VlFVRlJMRlZCUVZNc1ZVRkJWQ3hGUVVGeFFpeEhRVUZ5UWl4RlFVRXdRaXhIUVVFeFFpeEZRVUU0UWp0QlFVTndReXhSUVVGSkxGVkJRVlVzUjBGQlZpeERRVVJuUXpzN1FVRkhjRU1zVTBGQlN5eEpRVUZKTEVsQlFVa3NRMEZCU2l4RlFVRlBMRWxCUVVrc1MwRkJTeXhMUVVGTUxFTkJRVmNzVlVGQldDeERRVUZLTEVWQlFUUkNMRWRCUVRWRExFVkJRV2xFTzBGQlF5OURMRlZCUVVrc1VVRkJVU3hKUVVGSkxGZEJRVmNzUTBGQldDeERRVUZLTEVWQlFXMUNMRTlCUVc1Q0xFTkJRVklzUTBGRU1rTTdPMEZCUnk5RExHZENRVUZWTEUxQlFVMHNSMEZCVGl4RFFVRlZMRU5CUVZZc1EwRkJWaXhEUVVnclF6dExRVUZxUkRzN1FVRk5RU3hYUVVGUExFOUJRVkFzUTBGVWIwTTdSMEZCT1VJN08wRkJXVklzVVVGQlRTeFZRVUZUTEZWQlFWUXNSVUZCY1VJc1MwRkJja0lzUlVGQk1rSTdRVUZETDBJc1YwRkJUeXhYUVVGWExFdEJRVmdzUTBGQmFVSXNRMEZCYWtJc1JVRkJiMElzUzBGQmNFSXNRMEZCVUN4RFFVUXJRanRIUVVFelFqczdRVUZKVGl4alFVRlpMRlZCUVZNc1ZVRkJWQ3hGUVVGeFFpeEhRVUZ5UWl4RlFVRjVRanRCUVVOdVF5eFJRVUZKTEZOQlFWTXNSVUZCVkN4RFFVUXJRanRCUVVWdVF5eFJRVUZKTEZGQlFWRXNRMEZCVWl4RFFVWXJRanM3UVVGSmJrTXNVMEZCU1N4SlFVRkpMRWxCUVVvc1NVRkJXU3hWUVVGb1FpeEZRVUV5UWp0QlFVTjZRaXhWUVVGSExGRkJRVkVzUjBGQlVpeExRVUZuUWl4RFFVRm9RaXhGUVVGclFqdEJRVU51UWl4bFFVRlBMRWxCUVZBc1EwRkJXU3hKUVVGYUxFVkJSRzFDTzA5QlFYSkNPMHRCUkVZN08wRkJUVUVzVjBGQlR5eFBRVUZQTEUxQlFWQXNRMEZCWXl4TlFVRmtMRU5CUVZBc1EwRldiVU03UjBGQmVrSTdPMEZCWVZvc1kwRkJXU3hWUVVGVExGVkJRVlFzUlVGQmNVSXNSMEZCY2tJc1JVRkJlVUk3UVVGRGJrTXNVVUZCU1N4UlFVRlJMRU5CUVZJc1EwRkVLMEk3TzBGQlIyNURMRk5CUVVrc1NVRkJTU3hKUVVGS0xFbEJRVmtzVlVGQmFFSXNSVUZCTWtJN1FVRkRla0lzVlVGQlJ5eEpRVUZKTEVsQlFVb3NRMEZCU0N4RlFVRmhPMEZCUTFnc1owSkJRVkVzVVVGQlVTeERRVUZTTEVOQlJFYzdUMEZCWWl4TlFVVkxPMEZCUTBnc1kwRkVSenRQUVVaTU8wdEJSRVk3TzBGQlVVRXNWMEZCVHl4WFFVRlhMRXRCUVZnc1EwRkJhVUlzUTBGQmFrSXNSVUZCYjBJc1MwRkJjRUlzUTBGQlVDeERRVmh0UXp0SFFVRjZRanM3UVVGaldpeFhRVUZUTEZWQlFWTXNWVUZCVkN4RlFVRnZRanRCUVVNelFpeFhRVUZQTEZWQlFWQXNRMEZFTWtJN1IwRkJjRUk3UTBGdVRWQTdPMEZCZDAxS0xHVkJRV1VzU1VGQlppSXNJbVpwYkdVaU9pSnNhV0l2Wlc1MWJTNXFjeUlzSW5OdmRYSmpaWE5EYjI1MFpXNTBJanBiSW1sdGNHOXlkQ0JEYjNKbElHWnliMjBnSnk0dlkyOXlaU2M3WEc1Y2JteGxkQ0JGYm5WdElEMGdlMXh1WEc0Z0lHRnNiRjlmY1cxaGNtdGZYem9nWm5WdVkzUnBiMjRvWTI5c2JHVmpkR2x2Yml3Z1puVnVJRDBnS0hncElEMCtJSGdwZTF4dUlDQWdJR1p2Y2loc1pYUWdaV3hsYlNCdlppQmpiMnhzWldOMGFXOXVLWHRjYmlBZ0lDQWdJR2xtS0NGbWRXNG9aV3hsYlNrcGUxeHVJQ0FnSUNBZ0lDQnlaWFIxY200Z1ptRnNjMlU3WEc0Z0lDQWdJQ0I5WEc0Z0lDQWdmVnh1WEc0Z0lDQWdjbVYwZFhKdUlIUnlkV1U3WEc0Z0lIMHNYRzVjYmlBZ1lXNTVYMTl4YldGeWExOWZPaUJtZFc1amRHbHZiaWhqYjJ4c1pXTjBhVzl1TENCbWRXNGdQU0FvZUNrZ1BUNGdlQ2w3WEc0Z0lDQWdabTl5S0d4bGRDQmxiR1Z0SUc5bUlHTnZiR3hsWTNScGIyNHBlMXh1SUNBZ0lDQWdhV1lvWm5WdUtHVnNaVzBwS1h0Y2JpQWdJQ0FnSUNBZ2NtVjBkWEp1SUhSeWRXVTdYRzRnSUNBZ0lDQjlYRzRnSUNBZ2ZWeHVYRzRnSUNBZ2NtVjBkWEp1SUdaaGJITmxPMXh1SUNCOUxGeHVYRzRnSUdGME9pQm1kVzVqZEdsdmJpaGpiMnhzWldOMGFXOXVMQ0J1TENCMGFHVmZaR1ZtWVhWc2RDQTlJRzUxYkd3cGUxeHVJQ0FnSUdsbUtHNGdQaUIwYUdsekxtTnZkVzUwS0dOdmJHeGxZM1JwYjI0cElIeDhJRzRnUENBd0tYdGNiaUFnSUNBZ0lISmxkSFZ5YmlCMGFHVmZaR1ZtWVhWc2REdGNiaUFnSUNCOVhHNWNiaUFnSUNCeVpYUjFjbTRnWTI5c2JHVmpkR2x2Ymx0dVhUdGNiaUFnZlN4Y2JseHVJQ0JqYjI1allYUTZJR1oxYm1OMGFXOXVLQzR1TG1WdWRXMWhZbXhsY3lsN1hHNGdJQ0FnY21WMGRYSnVJR1Z1ZFcxaFlteGxjMXN3WFM1amIyNWpZWFFvWlc1MWJXRmliR1Z6V3pGZEtUdGNiaUFnZlN4Y2JseHVJQ0JqYjNWdWREb2dablZ1WTNScGIyNG9ZMjlzYkdWamRHbHZiaXdnWm5WdUlEMGdiblZzYkNsN1hHNGdJQ0FnYVdZb1puVnVJRDA5SUc1MWJHd3BlMXh1SUNBZ0lDQWdjbVYwZFhKdUlHTnZiR3hsWTNScGIyNHViR1Z1WjNSb08xeHVJQ0FnSUgwZ1pXeHpaU0I3WEc0Z0lDQWdJQ0J5WlhSMWNtNGdZMjlzYkdWamRHbHZiaTVtYVd4MFpYSW9ablZ1S1M1c1pXNW5kR2c3WEc0Z0lDQWdmVnh1SUNCOUxGeHVYRzRnSUdSeWIzQTZJR1oxYm1OMGFXOXVLR052Ykd4bFkzUnBiMjRzSUdOdmRXNTBLWHRjYmlBZ0lDQnlaWFIxY200Z1kyOXNiR1ZqZEdsdmJpNXpiR2xqWlNoamIzVnVkQ2s3WEc0Z0lIMHNYRzVjYmlBZ1pISnZjRjkzYUdsc1pUb2dablZ1WTNScGIyNG9ZMjlzYkdWamRHbHZiaXdnWm5WdUtYdGNiaUFnSUNCc1pYUWdZMjkxYm5RZ1BTQXdPMXh1WEc0Z0lDQWdabTl5S0d4bGRDQmxiR1Z0SUc5bUlHTnZiR3hsWTNScGIyNHBlMXh1SUNBZ0lDQWdhV1lvWm5WdUtHVnNaVzBwS1h0Y2JpQWdJQ0FnSUNBZ1kyOTFiblFnUFNCamIzVnVkQ0FySURFN1hHNGdJQ0FnSUNCOVpXeHpaWHRjYmlBZ0lDQWdJQ0FnWW5KbFlXczdYRzRnSUNBZ0lDQjlYRzRnSUNBZ2ZWeHVYRzRnSUNBZ2NtVjBkWEp1SUdOdmJHeGxZM1JwYjI0dWMyeHBZMlVvWTI5MWJuUXBPMXh1SUNCOUxGeHVYRzRnSUdWaFkyZzZJR1oxYm1OMGFXOXVLR052Ykd4bFkzUnBiMjRzSUdaMWJpbDdYRzRnSUNBZ1ptOXlLR3hsZENCbGJHVnRJRzltSUdOdmJHeGxZM1JwYjI0cGUxeHVJQ0FnSUNBZ1puVnVLR1ZzWlcwcE8xeHVJQ0FnSUgxY2JpQWdmU3hjYmx4dUlDQmxiWEIwZVY5ZmNXMWhjbXRmWHpvZ1puVnVZM1JwYjI0b1kyOXNiR1ZqZEdsdmJpbDdYRzRnSUNBZ2NtVjBkWEp1SUdOdmJHeGxZM1JwYjI0dWJHVnVaM1JvSUQwOVBTQXdPMXh1SUNCOUxGeHVYRzRnSUdabGRHTm9PaUJtZFc1amRHbHZiaWhqYjJ4c1pXTjBhVzl1TENCdUtYdGNiaUFnSUNCcFppaEJjbkpoZVM1cGMwRnljbUY1S0dOdmJHeGxZM1JwYjI0cEtYdGNiaUFnSUNBZ0lHbG1LRzRnUENCMGFHbHpMbU52ZFc1MEtHTnZiR3hsWTNScGIyNHBJQ1ltSUc0Z1BqMGdNQ2w3WEc0Z0lDQWdJQ0FnSUhKbGRIVnliaUJ1WlhjZ1EyOXlaUzVVZFhCc1pTaFRlVzFpYjJ3dVptOXlLRndpYjJ0Y0lpa3NJR052Ykd4bFkzUnBiMjViYmwwcE8xeHVJQ0FnSUNBZ2ZXVnNjMlY3WEc0Z0lDQWdJQ0FnSUhKbGRIVnliaUJUZVcxaWIyd3VabTl5S0Z3aVpYSnliM0pjSWlrN1hHNGdJQ0FnSUNCOVhHNGdJQ0FnZlZ4dVhHNGdJQ0FnZEdoeWIzY2dibVYzSUVWeWNtOXlLRndpWTI5c2JHVmpkR2x2YmlCcGN5QnViM1FnWVc0Z1JXNTFiV1Z5WVdKc1pWd2lLVHRjYmlBZ2ZTeGNibHh1SUNCbVpYUmphRjlmWlcxaGNtdGZYem9nWm5WdVkzUnBiMjRvWTI5c2JHVmpkR2x2Yml3Z2JpbDdYRzRnSUNBZ2FXWW9RWEp5WVhrdWFYTkJjbkpoZVNoamIyeHNaV04wYVc5dUtTbDdYRzRnSUNBZ0lDQnBaaWh1SUR3Z2RHaHBjeTVqYjNWdWRDaGpiMnhzWldOMGFXOXVLU0FtSmlCdUlENDlJREFwZTF4dUlDQWdJQ0FnSUNCeVpYUjFjbTRnWTI5c2JHVmpkR2x2Ymx0dVhUdGNiaUFnSUNBZ0lIMWxiSE5sZTF4dUlDQWdJQ0FnSUNCMGFISnZkeUJ1WlhjZ1JYSnliM0lvWENKdmRYUWdiMllnWW05MWJtUnpJR1Z5Y205eVhDSXBPMXh1SUNBZ0lDQWdmVnh1SUNBZ0lIMWNibHh1SUNBZ0lIUm9jbTkzSUc1bGR5QkZjbkp2Y2loY0ltTnZiR3hsWTNScGIyNGdhWE1nYm05MElHRnVJRVZ1ZFcxbGNtRmliR1ZjSWlrN1hHNGdJSDBzWEc1Y2JpQWdabWxzZEdWeU9pQm1kVzVqZEdsdmJpaGpiMnhzWldOMGFXOXVMQ0JtZFc0cGUxeHVJQ0FnSUd4bGRDQnlaWE4xYkhRZ1BTQmJYVHRjYmx4dUlDQWdJR1p2Y2loc1pYUWdaV3hsYlNCdlppQmpiMnhzWldOMGFXOXVLWHRjYmlBZ0lDQWdJR2xtS0daMWJpaGxiR1Z0S1NsN1hHNGdJQ0FnSUNBZ0lISmxjM1ZzZEM1d2RYTm9LR1ZzWlcwcE8xeHVJQ0FnSUNBZ2ZWeHVJQ0FnSUgxY2JseHVJQ0FnSUhKbGRIVnliaUJ5WlhOMWJIUTdYRzRnSUgwc1hHNWNiaUFnWm1sc2RHVnlYMjFoY0RvZ1puVnVZM1JwYjI0b1kyOXNiR1ZqZEdsdmJpd2dabWxzZEdWeUxDQnRZWEJ3WlhJcGUxeHVJQ0FnSUhKbGRIVnliaUJGYm5WdExtMWhjQ2hGYm5WdExtWnBiSFJsY2loamIyeHNaV04wYVc5dUxDQm1hV3gwWlhJcExDQnRZWEJ3WlhJcE8xeHVJQ0I5TEZ4dVhHNGdJR1pwYm1RNklHWjFibU4wYVc5dUtHTnZiR3hsWTNScGIyNHNJR2xtWDI1dmJtVWdQU0J1ZFd4c0xDQm1kVzRwZTF4dUlDQWdJR1p2Y2loc1pYUWdaV3hsYlNCdlppQmpiMnhzWldOMGFXOXVLWHRjYmlBZ0lDQWdJR2xtS0daMWJpaGxiR1Z0S1NsN1hHNGdJQ0FnSUNBZ0lISmxkSFZ5YmlCbGJHVnRPMXh1SUNBZ0lDQWdmVnh1SUNBZ0lIMWNibHh1SUNBZ0lISmxkSFZ5YmlCcFpsOXViMjVsTzF4dUlDQjlMRnh1WEc0Z0lHbHVkRzg2SUdaMWJtTjBhVzl1S0dOdmJHeGxZM1JwYjI0c0lHeHBjM1FwZTF4dUlDQWdJSEpsZEhWeWJpQnNhWE4wTG1OdmJtTmhkQ2hqYjJ4c1pXTjBhVzl1S1R0Y2JpQWdmU3hjYmx4dUlDQnRZWEE2SUdaMWJtTjBhVzl1S0dOdmJHeGxZM1JwYjI0c0lHWjFiaWw3WEc0Z0lDQWdiR1YwSUhKbGMzVnNkQ0E5SUZ0ZE8xeHVYRzRnSUNBZ1ptOXlLR3hsZENCbGJHVnRJRzltSUdOdmJHeGxZM1JwYjI0cGUxeHVJQ0FnSUNBZ2NtVnpkV3gwTG5CMWMyZ29ablZ1S0dWc1pXMHBLVHRjYmlBZ0lDQjlYRzVjYmlBZ0lDQnlaWFIxY200Z2NtVnpkV3gwTzF4dUlDQjlMRnh1WEc0Z0lHMWhjRjl5WldSMVkyVTZJR1oxYm1OMGFXOXVLR052Ykd4bFkzUnBiMjRzSUdGall5d2dablZ1S1h0Y2JpQWdJQ0JzWlhRZ2JXRndjR1ZrSUQwZ1QySnFaV04wTG1aeVpXVjZaU2hiWFNrN1hHNGdJQ0FnYkdWMElIUm9aVjloWTJNZ1BTQmhZMk03WEc1Y2JpQWdJQ0JtYjNJZ0tIWmhjaUJwSUQwZ01Ec2dhU0E4SUhSb2FYTXVZMjkxYm5Rb1kyOXNiR1ZqZEdsdmJpazdJR2tyS3lrZ2UxeHVJQ0FnSUNBZ2JHVjBJSFIxY0d4bElEMGdablZ1S0dOdmJHeGxZM1JwYjI1YmFWMHNJSFJvWlY5aFkyTXBPMXh1WEc0Z0lDQWdJQ0IwYUdWZllXTmpJRDBnZEhWd2JHVXVaMlYwS0RFcE8xeHVJQ0FnSUNBZ2JXRndjR1ZrSUQwZ1QySnFaV04wTG1aeVpXVjZaU2h0WVhCd1pXUXVZMjl1WTJGMEtGdDBkWEJzWlM1blpYUW9NQ2xkS1NrN1hHNGdJQ0FnZlZ4dVhHNGdJQ0FnY21WMGRYSnVJRzVsZHlCRGIzSmxMbFIxY0d4bEtHMWhjSEJsWkN3Z2RHaGxYMkZqWXlrN1hHNGdJSDBzWEc1Y2JpQWdiV1Z0WW1WeVgxOXhiV0Z5YTE5Zk9pQm1kVzVqZEdsdmJpaGpiMnhzWldOMGFXOXVMQ0IyWVd4MVpTbDdYRzRnSUNBZ2NtVjBkWEp1SUdOdmJHeGxZM1JwYjI0dWFXNWpiSFZrWlhNb2RtRnNkV1VwTzF4dUlDQjlMRnh1WEc0Z0lISmxaSFZqWlRvZ1puVnVZM1JwYjI0b1kyOXNiR1ZqZEdsdmJpd2dZV05qTENCbWRXNHBlMXh1SUNBZ0lHeGxkQ0IwYUdWZllXTmpJRDBnWVdOak8xeHVYRzRnSUNBZ1ptOXlJQ2gyWVhJZ2FTQTlJREE3SUdrZ1BDQjBhR2x6TG1OdmRXNTBLR052Ykd4bFkzUnBiMjRwT3lCcEt5c3BJSHRjYmlBZ0lDQWdJR3hsZENCMGRYQnNaU0E5SUdaMWJpaGpiMnhzWldOMGFXOXVXMmxkTENCMGFHVmZZV05qS1R0Y2JseHVJQ0FnSUNBZ2RHaGxYMkZqWXlBOUlIUjFjR3hsTG1kbGRDZ3hLVHRjYmlBZ0lDQjlYRzVjYmlBZ0lDQnlaWFIxY200Z2RHaGxYMkZqWXp0Y2JpQWdmU3hjYmx4dUlDQjBZV3RsT2lCbWRXNWpkR2x2YmloamIyeHNaV04wYVc5dUxDQmpiM1Z1ZENsN1hHNGdJQ0FnY21WMGRYSnVJR052Ykd4bFkzUnBiMjR1YzJ4cFkyVW9NQ3dnWTI5MWJuUXBPMXh1SUNCOUxGeHVYRzRnSUhSaGEyVmZaWFpsY25rNklHWjFibU4wYVc5dUtHTnZiR3hsWTNScGIyNHNJRzUwYUNsN1hHNGdJQ0FnYkdWMElISmxjM1ZzZENBOUlGdGRPMXh1SUNBZ0lHeGxkQ0JwYm1SbGVDQTlJREE3WEc1Y2JpQWdJQ0JtYjNJb2JHVjBJR1ZzWlcwZ2IyWWdZMjlzYkdWamRHbHZiaWw3WEc0Z0lDQWdJQ0JwWmlocGJtUmxlQ0FsSUc1MGFDQTlQVDBnTUNsN1hHNGdJQ0FnSUNBZ0lISmxjM1ZzZEM1d2RYTm9LR1ZzWlcwcE8xeHVJQ0FnSUNBZ2ZWeHVJQ0FnSUgxY2JseHVJQ0FnSUhKbGRIVnliaUJQWW1wbFkzUXVabkpsWlhwbEtISmxjM1ZzZENrN1hHNGdJSDBzWEc1Y2JpQWdkR0ZyWlY5M2FHbHNaVG9nWm5WdVkzUnBiMjRvWTI5c2JHVmpkR2x2Yml3Z1puVnVLWHRjYmlBZ0lDQnNaWFFnWTI5MWJuUWdQU0F3TzF4dVhHNGdJQ0FnWm05eUtHeGxkQ0JsYkdWdElHOW1JR052Ykd4bFkzUnBiMjRwZTF4dUlDQWdJQ0FnYVdZb1puVnVLR1ZzWlcwcEtYdGNiaUFnSUNBZ0lDQWdZMjkxYm5RZ1BTQmpiM1Z1ZENBcklERTdYRzRnSUNBZ0lDQjlaV3h6Wlh0Y2JpQWdJQ0FnSUNBZ1luSmxZV3M3WEc0Z0lDQWdJQ0I5WEc0Z0lDQWdmVnh1WEc0Z0lDQWdjbVYwZFhKdUlHTnZiR3hsWTNScGIyNHVjMnhwWTJVb01Dd2dZMjkxYm5RcE8xeHVJQ0I5TEZ4dVhHNGdJSFJ2WDJ4cGMzUTZJR1oxYm1OMGFXOXVLR052Ykd4bFkzUnBiMjRwZTF4dUlDQWdJSEpsZEhWeWJpQmpiMnhzWldOMGFXOXVPMXh1SUNCOVhHNTlPMXh1WEc1bGVIQnZjblFnWkdWbVlYVnNkQ0JGYm5WdE8xeHVJbDBzSW5OdmRYSmpaVkp2YjNRaU9pSXZjMjkxY21ObEx5SjlcbiIsImxldCBWaXJ0dWFsRE9NID0gZnVuY3Rpb24gKGUpIHtcbiAgICByZXR1cm4gZSgpO1xufShmdW5jdGlvbiAoKSB7XG4gICAgdmFyIGRlZmluZSwgbW9kdWxlLCBleHBvcnRzO1xuICAgIHJldHVybiBmdW5jdGlvbiBlKHQsIG4sIHIpIHtcbiAgICAgICAgZnVuY3Rpb24gcyhvLCB1KSB7XG4gICAgICAgICAgICBpZiAoIW5bb10pIHtcbiAgICAgICAgICAgICAgICBpZiAoIXRbb10pIHtcbiAgICAgICAgICAgICAgICAgICAgdmFyIGEgPSB0eXBlb2YgcmVxdWlyZSA9PSBcImZ1bmN0aW9uXCIgJiYgcmVxdWlyZTtcbiAgICAgICAgICAgICAgICAgICAgaWYgKCF1ICYmIGEpIHJldHVybiBhKG8sICEwKTtcbiAgICAgICAgICAgICAgICAgICAgaWYgKGkpIHJldHVybiBpKG8sICEwKTtcbiAgICAgICAgICAgICAgICAgICAgdmFyIGYgPSBuZXcgRXJyb3IoXCJDYW5ub3QgZmluZCBtb2R1bGUgJ1wiICsgbyArIFwiJ1wiKTtcbiAgICAgICAgICAgICAgICAgICAgdGhyb3cgZi5jb2RlID0gXCJNT0RVTEVfTk9UX0ZPVU5EXCIsIGY7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHZhciBsID0gbltvXSA9IHtcbiAgICAgICAgICAgICAgICAgICAgZXhwb3J0czoge31cbiAgICAgICAgICAgICAgICB9O1xuICAgICAgICAgICAgICAgIHRbb11bMF0uY2FsbChsLmV4cG9ydHMsIGZ1bmN0aW9uIChlKSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciBuID0gdFtvXVsxXVtlXTtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHMobiA/IG4gOiBlKTtcbiAgICAgICAgICAgICAgICB9LCBsLCBsLmV4cG9ydHMsIGUsIHQsIG4sIHIpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmV0dXJuIG5bb10uZXhwb3J0cztcbiAgICAgICAgfVxuICAgICAgICB2YXIgaSA9IHR5cGVvZiByZXF1aXJlID09IFwiZnVuY3Rpb25cIiAmJiByZXF1aXJlO1xuICAgICAgICBmb3IgKHZhciBvID0gMDsgbyA8IHIubGVuZ3RoOyBvKyspIHMocltvXSk7XG4gICAgICAgIHJldHVybiBzO1xuICAgIH0oe1xuICAgICAgICAxOiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge1xuXG4gICAgICAgICAgICB2YXIgY3JlYXRlRWxlbWVudCA9IHJlcXVpcmUoXCIuL3Zkb20vY3JlYXRlLWVsZW1lbnQuanNcIik7XG5cbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gY3JlYXRlRWxlbWVudDtcbiAgICAgICAgfSwgeyBcIi4vdmRvbS9jcmVhdGUtZWxlbWVudC5qc1wiOiAxNSB9XSwgMjogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHtcbiAgICAgICAgICAgIHZhciBkaWZmID0gcmVxdWlyZShcIi4vdnRyZWUvZGlmZi5qc1wiKTtcblxuICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBkaWZmO1xuICAgICAgICB9LCB7IFwiLi92dHJlZS9kaWZmLmpzXCI6IDM1IH1dLCAzOiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge1xuICAgICAgICAgICAgdmFyIGggPSByZXF1aXJlKFwiLi92aXJ0dWFsLWh5cGVyc2NyaXB0L2luZGV4LmpzXCIpO1xuXG4gICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IGg7XG4gICAgICAgIH0sIHsgXCIuL3ZpcnR1YWwtaHlwZXJzY3JpcHQvaW5kZXguanNcIjogMjIgfV0sIDQ6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICB2YXIgZGlmZiA9IHJlcXVpcmUoXCIuL2RpZmYuanNcIik7XG4gICAgICAgICAgICB2YXIgcGF0Y2ggPSByZXF1aXJlKFwiLi9wYXRjaC5qc1wiKTtcbiAgICAgICAgICAgIHZhciBoID0gcmVxdWlyZShcIi4vaC5qc1wiKTtcbiAgICAgICAgICAgIHZhciBjcmVhdGUgPSByZXF1aXJlKFwiLi9jcmVhdGUtZWxlbWVudC5qc1wiKTtcbiAgICAgICAgICAgIHZhciBWTm9kZSA9IHJlcXVpcmUoJy4vdm5vZGUvdm5vZGUuanMnKTtcbiAgICAgICAgICAgIHZhciBWVGV4dCA9IHJlcXVpcmUoJy4vdm5vZGUvdnRleHQuanMnKTtcblxuICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSB7XG4gICAgICAgICAgICAgICAgZGlmZjogZGlmZixcbiAgICAgICAgICAgICAgICBwYXRjaDogcGF0Y2gsXG4gICAgICAgICAgICAgICAgaDogaCxcbiAgICAgICAgICAgICAgICBjcmVhdGU6IGNyZWF0ZSxcbiAgICAgICAgICAgICAgICBWTm9kZTogVk5vZGUsXG4gICAgICAgICAgICAgICAgVlRleHQ6IFZUZXh0XG4gICAgICAgICAgICB9O1xuICAgICAgICB9LCB7IFwiLi9jcmVhdGUtZWxlbWVudC5qc1wiOiAxLCBcIi4vZGlmZi5qc1wiOiAyLCBcIi4vaC5qc1wiOiAzLCBcIi4vcGF0Y2guanNcIjogMTMsIFwiLi92bm9kZS92bm9kZS5qc1wiOiAzMSwgXCIuL3Zub2RlL3Z0ZXh0LmpzXCI6IDMzIH1dLCA1OiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge1xuICAgICAgICAgICAgLyohXG4gICAgICAgICAgICAgKiBDcm9zcy1Ccm93c2VyIFNwbGl0IDEuMS4xXG4gICAgICAgICAgICAgKiBDb3B5cmlnaHQgMjAwNy0yMDEyIFN0ZXZlbiBMZXZpdGhhbiA8c3RldmVubGV2aXRoYW4uY29tPlxuICAgICAgICAgICAgICogQXZhaWxhYmxlIHVuZGVyIHRoZSBNSVQgTGljZW5zZVxuICAgICAgICAgICAgICogRUNNQVNjcmlwdCBjb21wbGlhbnQsIHVuaWZvcm0gY3Jvc3MtYnJvd3NlciBzcGxpdCBtZXRob2RcbiAgICAgICAgICAgICAqL1xuXG4gICAgICAgICAgICAvKipcbiAgICAgICAgICAgICAqIFNwbGl0cyBhIHN0cmluZyBpbnRvIGFuIGFycmF5IG9mIHN0cmluZ3MgdXNpbmcgYSByZWdleCBvciBzdHJpbmcgc2VwYXJhdG9yLiBNYXRjaGVzIG9mIHRoZVxuICAgICAgICAgICAgICogc2VwYXJhdG9yIGFyZSBub3QgaW5jbHVkZWQgaW4gdGhlIHJlc3VsdCBhcnJheS4gSG93ZXZlciwgaWYgYHNlcGFyYXRvcmAgaXMgYSByZWdleCB0aGF0IGNvbnRhaW5zXG4gICAgICAgICAgICAgKiBjYXB0dXJpbmcgZ3JvdXBzLCBiYWNrcmVmZXJlbmNlcyBhcmUgc3BsaWNlZCBpbnRvIHRoZSByZXN1bHQgZWFjaCB0aW1lIGBzZXBhcmF0b3JgIGlzIG1hdGNoZWQuXG4gICAgICAgICAgICAgKiBGaXhlcyBicm93c2VyIGJ1Z3MgY29tcGFyZWQgdG8gdGhlIG5hdGl2ZSBgU3RyaW5nLnByb3RvdHlwZS5zcGxpdGAgYW5kIGNhbiBiZSB1c2VkIHJlbGlhYmx5XG4gICAgICAgICAgICAgKiBjcm9zcy1icm93c2VyLlxuICAgICAgICAgICAgICogQHBhcmFtIHtTdHJpbmd9IHN0ciBTdHJpbmcgdG8gc3BsaXQuXG4gICAgICAgICAgICAgKiBAcGFyYW0ge1JlZ0V4cHxTdHJpbmd9IHNlcGFyYXRvciBSZWdleCBvciBzdHJpbmcgdG8gdXNlIGZvciBzZXBhcmF0aW5nIHRoZSBzdHJpbmcuXG4gICAgICAgICAgICAgKiBAcGFyYW0ge051bWJlcn0gW2xpbWl0XSBNYXhpbXVtIG51bWJlciBvZiBpdGVtcyB0byBpbmNsdWRlIGluIHRoZSByZXN1bHQgYXJyYXkuXG4gICAgICAgICAgICAgKiBAcmV0dXJucyB7QXJyYXl9IEFycmF5IG9mIHN1YnN0cmluZ3MuXG4gICAgICAgICAgICAgKiBAZXhhbXBsZVxuICAgICAgICAgICAgICpcbiAgICAgICAgICAgICAqIC8vIEJhc2ljIHVzZVxuICAgICAgICAgICAgICogc3BsaXQoJ2EgYiBjIGQnLCAnICcpO1xuICAgICAgICAgICAgICogLy8gLT4gWydhJywgJ2InLCAnYycsICdkJ11cbiAgICAgICAgICAgICAqXG4gICAgICAgICAgICAgKiAvLyBXaXRoIGxpbWl0XG4gICAgICAgICAgICAgKiBzcGxpdCgnYSBiIGMgZCcsICcgJywgMik7XG4gICAgICAgICAgICAgKiAvLyAtPiBbJ2EnLCAnYiddXG4gICAgICAgICAgICAgKlxuICAgICAgICAgICAgICogLy8gQmFja3JlZmVyZW5jZXMgaW4gcmVzdWx0IGFycmF5XG4gICAgICAgICAgICAgKiBzcGxpdCgnLi53b3JkMSB3b3JkMi4uJywgLyhbYS16XSspKFxcZCspL2kpO1xuICAgICAgICAgICAgICogLy8gLT4gWycuLicsICd3b3JkJywgJzEnLCAnICcsICd3b3JkJywgJzInLCAnLi4nXVxuICAgICAgICAgICAgICovXG4gICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uIHNwbGl0KHVuZGVmKSB7XG5cbiAgICAgICAgICAgICAgICB2YXIgbmF0aXZlU3BsaXQgPSBTdHJpbmcucHJvdG90eXBlLnNwbGl0LFxuICAgICAgICAgICAgICAgICAgICBjb21wbGlhbnRFeGVjTnBjZyA9IC8oKT8/Ly5leGVjKFwiXCIpWzFdID09PSB1bmRlZixcblxuICAgICAgICAgICAgICAgIC8vIE5QQ0c6IG5vbnBhcnRpY2lwYXRpbmcgY2FwdHVyaW5nIGdyb3VwXG4gICAgICAgICAgICAgICAgc2VsZjtcblxuICAgICAgICAgICAgICAgIHNlbGYgPSBmdW5jdGlvbiAoc3RyLCBzZXBhcmF0b3IsIGxpbWl0KSB7XG4gICAgICAgICAgICAgICAgICAgIC8vIElmIGBzZXBhcmF0b3JgIGlzIG5vdCBhIHJlZ2V4LCB1c2UgYG5hdGl2ZVNwbGl0YFxuICAgICAgICAgICAgICAgICAgICBpZiAoT2JqZWN0LnByb3RvdHlwZS50b1N0cmluZy5jYWxsKHNlcGFyYXRvcikgIT09IFwiW29iamVjdCBSZWdFeHBdXCIpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBuYXRpdmVTcGxpdC5jYWxsKHN0ciwgc2VwYXJhdG9yLCBsaW1pdCk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgdmFyIG91dHB1dCA9IFtdLFxuICAgICAgICAgICAgICAgICAgICAgICAgZmxhZ3MgPSAoc2VwYXJhdG9yLmlnbm9yZUNhc2UgPyBcImlcIiA6IFwiXCIpICsgKHNlcGFyYXRvci5tdWx0aWxpbmUgPyBcIm1cIiA6IFwiXCIpICsgKHNlcGFyYXRvci5leHRlbmRlZCA/IFwieFwiIDogXCJcIikgKyAoIC8vIFByb3Bvc2VkIGZvciBFUzZcbiAgICAgICAgICAgICAgICAgICAgc2VwYXJhdG9yLnN0aWNreSA/IFwieVwiIDogXCJcIiksXG5cbiAgICAgICAgICAgICAgICAgICAgLy8gRmlyZWZveCAzK1xuICAgICAgICAgICAgICAgICAgICBsYXN0TGFzdEluZGV4ID0gMCxcblxuICAgICAgICAgICAgICAgICAgICAvLyBNYWtlIGBnbG9iYWxgIGFuZCBhdm9pZCBgbGFzdEluZGV4YCBpc3N1ZXMgYnkgd29ya2luZyB3aXRoIGEgY29weVxuICAgICAgICAgICAgICAgICAgICBzZXBhcmF0b3IgPSBuZXcgUmVnRXhwKHNlcGFyYXRvci5zb3VyY2UsIGZsYWdzICsgXCJnXCIpLFxuICAgICAgICAgICAgICAgICAgICAgICAgc2VwYXJhdG9yMixcbiAgICAgICAgICAgICAgICAgICAgICAgIG1hdGNoLFxuICAgICAgICAgICAgICAgICAgICAgICAgbGFzdEluZGV4LFxuICAgICAgICAgICAgICAgICAgICAgICAgbGFzdExlbmd0aDtcbiAgICAgICAgICAgICAgICAgICAgc3RyICs9IFwiXCI7IC8vIFR5cGUtY29udmVydFxuICAgICAgICAgICAgICAgICAgICBpZiAoIWNvbXBsaWFudEV4ZWNOcGNnKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAvLyBEb2Vzbid0IG5lZWQgZmxhZ3MgZ3ksIGJ1dCB0aGV5IGRvbid0IGh1cnRcbiAgICAgICAgICAgICAgICAgICAgICAgIHNlcGFyYXRvcjIgPSBuZXcgUmVnRXhwKFwiXlwiICsgc2VwYXJhdG9yLnNvdXJjZSArIFwiJCg/IVxcXFxzKVwiLCBmbGFncyk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgLyogVmFsdWVzIGZvciBgbGltaXRgLCBwZXIgdGhlIHNwZWM6XG4gICAgICAgICAgICAgICAgICAgICAqIElmIHVuZGVmaW5lZDogNDI5NDk2NzI5NSAvLyBNYXRoLnBvdygyLCAzMikgLSAxXG4gICAgICAgICAgICAgICAgICAgICAqIElmIDAsIEluZmluaXR5LCBvciBOYU46IDBcbiAgICAgICAgICAgICAgICAgICAgICogSWYgcG9zaXRpdmUgbnVtYmVyOiBsaW1pdCA9IE1hdGguZmxvb3IobGltaXQpOyBpZiAobGltaXQgPiA0Mjk0OTY3Mjk1KSBsaW1pdCAtPSA0Mjk0OTY3Mjk2O1xuICAgICAgICAgICAgICAgICAgICAgKiBJZiBuZWdhdGl2ZSBudW1iZXI6IDQyOTQ5NjcyOTYgLSBNYXRoLmZsb29yKE1hdGguYWJzKGxpbWl0KSlcbiAgICAgICAgICAgICAgICAgICAgICogSWYgb3RoZXI6IFR5cGUtY29udmVydCwgdGhlbiB1c2UgdGhlIGFib3ZlIHJ1bGVzXG4gICAgICAgICAgICAgICAgICAgICAqL1xuICAgICAgICAgICAgICAgICAgICBsaW1pdCA9IGxpbWl0ID09PSB1bmRlZiA/IC0xID4+PiAwIDogLy8gTWF0aC5wb3coMiwgMzIpIC0gMVxuICAgICAgICAgICAgICAgICAgICBsaW1pdCA+Pj4gMDsgLy8gVG9VaW50MzIobGltaXQpXG4gICAgICAgICAgICAgICAgICAgIHdoaWxlIChtYXRjaCA9IHNlcGFyYXRvci5leGVjKHN0cikpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIGBzZXBhcmF0b3IubGFzdEluZGV4YCBpcyBub3QgcmVsaWFibGUgY3Jvc3MtYnJvd3NlclxuICAgICAgICAgICAgICAgICAgICAgICAgbGFzdEluZGV4ID0gbWF0Y2guaW5kZXggKyBtYXRjaFswXS5sZW5ndGg7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAobGFzdEluZGV4ID4gbGFzdExhc3RJbmRleCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIG91dHB1dC5wdXNoKHN0ci5zbGljZShsYXN0TGFzdEluZGV4LCBtYXRjaC5pbmRleCkpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIEZpeCBicm93c2VycyB3aG9zZSBgZXhlY2AgbWV0aG9kcyBkb24ndCBjb25zaXN0ZW50bHkgcmV0dXJuIGB1bmRlZmluZWRgIGZvclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIG5vbnBhcnRpY2lwYXRpbmcgY2FwdHVyaW5nIGdyb3Vwc1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmICghY29tcGxpYW50RXhlY05wY2cgJiYgbWF0Y2gubGVuZ3RoID4gMSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBtYXRjaFswXS5yZXBsYWNlKHNlcGFyYXRvcjIsIGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZvciAodmFyIGkgPSAxOyBpIDwgYXJndW1lbnRzLmxlbmd0aCAtIDI7IGkrKykge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChhcmd1bWVudHNbaV0gPT09IHVuZGVmKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1hdGNoW2ldID0gdW5kZWY7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKG1hdGNoLmxlbmd0aCA+IDEgJiYgbWF0Y2guaW5kZXggPCBzdHIubGVuZ3RoKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIEFycmF5LnByb3RvdHlwZS5wdXNoLmFwcGx5KG91dHB1dCwgbWF0Y2guc2xpY2UoMSkpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBsYXN0TGVuZ3RoID0gbWF0Y2hbMF0ubGVuZ3RoO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxhc3RMYXN0SW5kZXggPSBsYXN0SW5kZXg7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKG91dHB1dC5sZW5ndGggPj0gbGltaXQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHNlcGFyYXRvci5sYXN0SW5kZXggPT09IG1hdGNoLmluZGV4KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgc2VwYXJhdG9yLmxhc3RJbmRleCsrOyAvLyBBdm9pZCBhbiBpbmZpbml0ZSBsb29wXG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgaWYgKGxhc3RMYXN0SW5kZXggPT09IHN0ci5sZW5ndGgpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChsYXN0TGVuZ3RoIHx8ICFzZXBhcmF0b3IudGVzdChcIlwiKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIG91dHB1dC5wdXNoKFwiXCIpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgb3V0cHV0LnB1c2goc3RyLnNsaWNlKGxhc3RMYXN0SW5kZXgpKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICByZXR1cm4gb3V0cHV0Lmxlbmd0aCA+IGxpbWl0ID8gb3V0cHV0LnNsaWNlKDAsIGxpbWl0KSA6IG91dHB1dDtcbiAgICAgICAgICAgICAgICB9O1xuXG4gICAgICAgICAgICAgICAgcmV0dXJuIHNlbGY7XG4gICAgICAgICAgICB9KCk7XG4gICAgICAgIH0sIHt9XSwgNjogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHt9LCB7fV0sIDc6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICAndXNlIHN0cmljdCc7XG5cbiAgICAgICAgICAgIHZhciBPbmVWZXJzaW9uQ29uc3RyYWludCA9IHJlcXVpcmUoJ2luZGl2aWR1YWwvb25lLXZlcnNpb24nKTtcblxuICAgICAgICAgICAgdmFyIE1ZX1ZFUlNJT04gPSAnNyc7XG4gICAgICAgICAgICBPbmVWZXJzaW9uQ29uc3RyYWludCgnZXYtc3RvcmUnLCBNWV9WRVJTSU9OKTtcblxuICAgICAgICAgICAgdmFyIGhhc2hLZXkgPSAnX19FVl9TVE9SRV9LRVlAJyArIE1ZX1ZFUlNJT047XG5cbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gRXZTdG9yZTtcblxuICAgICAgICAgICAgZnVuY3Rpb24gRXZTdG9yZShlbGVtKSB7XG4gICAgICAgICAgICAgICAgdmFyIGhhc2ggPSBlbGVtW2hhc2hLZXldO1xuXG4gICAgICAgICAgICAgICAgaWYgKCFoYXNoKSB7XG4gICAgICAgICAgICAgICAgICAgIGhhc2ggPSBlbGVtW2hhc2hLZXldID0ge307XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgcmV0dXJuIGhhc2g7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0sIHsgXCJpbmRpdmlkdWFsL29uZS12ZXJzaW9uXCI6IDkgfV0sIDg6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICAoZnVuY3Rpb24gKGdsb2JhbCkge1xuICAgICAgICAgICAgICAgICd1c2Ugc3RyaWN0JztcblxuICAgICAgICAgICAgICAgIC8qZ2xvYmFsIHdpbmRvdywgZ2xvYmFsKi9cblxuICAgICAgICAgICAgICAgIHZhciByb290ID0gdHlwZW9mIHdpbmRvdyAhPT0gJ3VuZGVmaW5lZCcgPyB3aW5kb3cgOiB0eXBlb2YgZ2xvYmFsICE9PSAndW5kZWZpbmVkJyA/IGdsb2JhbCA6IHt9O1xuXG4gICAgICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBJbmRpdmlkdWFsO1xuXG4gICAgICAgICAgICAgICAgZnVuY3Rpb24gSW5kaXZpZHVhbChrZXksIHZhbHVlKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmIChrZXkgaW4gcm9vdCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHJvb3Rba2V5XTtcbiAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgIHJvb3Rba2V5XSA9IHZhbHVlO1xuXG4gICAgICAgICAgICAgICAgICAgIHJldHVybiB2YWx1ZTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9KS5jYWxsKHRoaXMsIHR5cGVvZiBnbG9iYWwgIT09IFwidW5kZWZpbmVkXCIgPyBnbG9iYWwgOiB0eXBlb2Ygc2VsZiAhPT0gXCJ1bmRlZmluZWRcIiA/IHNlbGYgOiB0eXBlb2Ygd2luZG93ICE9PSBcInVuZGVmaW5lZFwiID8gd2luZG93IDoge30pO1xuICAgICAgICB9LCB7fV0sIDk6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICAndXNlIHN0cmljdCc7XG5cbiAgICAgICAgICAgIHZhciBJbmRpdmlkdWFsID0gcmVxdWlyZSgnLi9pbmRleC5qcycpO1xuXG4gICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IE9uZVZlcnNpb247XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIE9uZVZlcnNpb24obW9kdWxlTmFtZSwgdmVyc2lvbiwgZGVmYXVsdFZhbHVlKSB7XG4gICAgICAgICAgICAgICAgdmFyIGtleSA9ICdfX0lORElWSURVQUxfT05FX1ZFUlNJT05fJyArIG1vZHVsZU5hbWU7XG4gICAgICAgICAgICAgICAgdmFyIGVuZm9yY2VLZXkgPSBrZXkgKyAnX0VORk9SQ0VfU0lOR0xFVE9OJztcblxuICAgICAgICAgICAgICAgIHZhciB2ZXJzaW9uVmFsdWUgPSBJbmRpdmlkdWFsKGVuZm9yY2VLZXksIHZlcnNpb24pO1xuXG4gICAgICAgICAgICAgICAgaWYgKHZlcnNpb25WYWx1ZSAhPT0gdmVyc2lvbikge1xuICAgICAgICAgICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ0NhbiBvbmx5IGhhdmUgb25lIGNvcHkgb2YgJyArIG1vZHVsZU5hbWUgKyAnLlxcbicgKyAnWW91IGFscmVhZHkgaGF2ZSB2ZXJzaW9uICcgKyB2ZXJzaW9uVmFsdWUgKyAnIGluc3RhbGxlZC5cXG4nICsgJ1RoaXMgbWVhbnMgeW91IGNhbm5vdCBpbnN0YWxsIHZlcnNpb24gJyArIHZlcnNpb24pO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHJldHVybiBJbmRpdmlkdWFsKGtleSwgZGVmYXVsdFZhbHVlKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSwgeyBcIi4vaW5kZXguanNcIjogOCB9XSwgMTA6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICAoZnVuY3Rpb24gKGdsb2JhbCkge1xuICAgICAgICAgICAgICAgIHZhciB0b3BMZXZlbCA9IHR5cGVvZiBnbG9iYWwgIT09ICd1bmRlZmluZWQnID8gZ2xvYmFsIDogdHlwZW9mIHdpbmRvdyAhPT0gJ3VuZGVmaW5lZCcgPyB3aW5kb3cgOiB7fTtcbiAgICAgICAgICAgICAgICB2YXIgbWluRG9jID0gcmVxdWlyZSgnbWluLWRvY3VtZW50Jyk7XG5cbiAgICAgICAgICAgICAgICBpZiAodHlwZW9mIGRvY3VtZW50ICE9PSAndW5kZWZpbmVkJykge1xuICAgICAgICAgICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IGRvY3VtZW50O1xuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciBkb2NjeSA9IHRvcExldmVsWydfX0dMT0JBTF9ET0NVTUVOVF9DQUNIRUA0J107XG5cbiAgICAgICAgICAgICAgICAgICAgaWYgKCFkb2NjeSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgZG9jY3kgPSB0b3BMZXZlbFsnX19HTE9CQUxfRE9DVU1FTlRfQ0FDSEVANCddID0gbWluRG9jO1xuICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBkb2NjeTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9KS5jYWxsKHRoaXMsIHR5cGVvZiBnbG9iYWwgIT09IFwidW5kZWZpbmVkXCIgPyBnbG9iYWwgOiB0eXBlb2Ygc2VsZiAhPT0gXCJ1bmRlZmluZWRcIiA/IHNlbGYgOiB0eXBlb2Ygd2luZG93ICE9PSBcInVuZGVmaW5lZFwiID8gd2luZG93IDoge30pO1xuICAgICAgICB9LCB7IFwibWluLWRvY3VtZW50XCI6IDYgfV0sIDExOiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge1xuICAgICAgICAgICAgXCJ1c2Ugc3RyaWN0XCI7XG5cbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gaXNPYmplY3QoeCkge1xuICAgICAgICAgICAgICAgIHJldHVybiB0eXBlb2YgeCA9PT0gXCJvYmplY3RcIiAmJiB4ICE9PSBudWxsO1xuICAgICAgICAgICAgfTtcbiAgICAgICAgfSwge31dLCAxMjogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHtcbiAgICAgICAgICAgIHZhciBuYXRpdmVJc0FycmF5ID0gQXJyYXkuaXNBcnJheTtcbiAgICAgICAgICAgIHZhciB0b1N0cmluZyA9IE9iamVjdC5wcm90b3R5cGUudG9TdHJpbmc7XG5cbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gbmF0aXZlSXNBcnJheSB8fCBpc0FycmF5O1xuXG4gICAgICAgICAgICBmdW5jdGlvbiBpc0FycmF5KG9iaikge1xuICAgICAgICAgICAgICAgIHJldHVybiB0b1N0cmluZy5jYWxsKG9iaikgPT09IFwiW29iamVjdCBBcnJheV1cIjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSwge31dLCAxMzogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHtcbiAgICAgICAgICAgIHZhciBwYXRjaCA9IHJlcXVpcmUoXCIuL3Zkb20vcGF0Y2guanNcIik7XG5cbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gcGF0Y2g7XG4gICAgICAgIH0sIHsgXCIuL3Zkb20vcGF0Y2guanNcIjogMTggfV0sIDE0OiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge1xuICAgICAgICAgICAgdmFyIGlzT2JqZWN0ID0gcmVxdWlyZShcImlzLW9iamVjdFwiKTtcbiAgICAgICAgICAgIHZhciBpc0hvb2sgPSByZXF1aXJlKFwiLi4vdm5vZGUvaXMtdmhvb2suanNcIik7XG5cbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gYXBwbHlQcm9wZXJ0aWVzO1xuXG4gICAgICAgICAgICBmdW5jdGlvbiBhcHBseVByb3BlcnRpZXMobm9kZSwgcHJvcHMsIHByZXZpb3VzKSB7XG4gICAgICAgICAgICAgICAgZm9yICh2YXIgcHJvcE5hbWUgaW4gcHJvcHMpIHtcbiAgICAgICAgICAgICAgICAgICAgdmFyIHByb3BWYWx1ZSA9IHByb3BzW3Byb3BOYW1lXTtcblxuICAgICAgICAgICAgICAgICAgICBpZiAocHJvcFZhbHVlID09PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJlbW92ZVByb3BlcnR5KG5vZGUsIHByb3BOYW1lLCBwcm9wVmFsdWUsIHByZXZpb3VzKTtcbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIGlmIChpc0hvb2socHJvcFZhbHVlKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgcmVtb3ZlUHJvcGVydHkobm9kZSwgcHJvcE5hbWUsIHByb3BWYWx1ZSwgcHJldmlvdXMpO1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHByb3BWYWx1ZS5ob29rKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcHJvcFZhbHVlLmhvb2sobm9kZSwgcHJvcE5hbWUsIHByZXZpb3VzID8gcHJldmlvdXNbcHJvcE5hbWVdIDogdW5kZWZpbmVkKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChpc09iamVjdChwcm9wVmFsdWUpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcGF0Y2hPYmplY3Qobm9kZSwgcHJvcHMsIHByZXZpb3VzLCBwcm9wTmFtZSwgcHJvcFZhbHVlKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgbm9kZVtwcm9wTmFtZV0gPSBwcm9wVmFsdWU7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIHJlbW92ZVByb3BlcnR5KG5vZGUsIHByb3BOYW1lLCBwcm9wVmFsdWUsIHByZXZpb3VzKSB7XG4gICAgICAgICAgICAgICAgaWYgKHByZXZpb3VzKSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciBwcmV2aW91c1ZhbHVlID0gcHJldmlvdXNbcHJvcE5hbWVdO1xuXG4gICAgICAgICAgICAgICAgICAgIGlmICghaXNIb29rKHByZXZpb3VzVmFsdWUpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAocHJvcE5hbWUgPT09IFwiYXR0cmlidXRlc1wiKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgZm9yICh2YXIgYXR0ck5hbWUgaW4gcHJldmlvdXNWYWx1ZSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBub2RlLnJlbW92ZUF0dHJpYnV0ZShhdHRyTmFtZSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIGlmIChwcm9wTmFtZSA9PT0gXCJzdHlsZVwiKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgZm9yICh2YXIgaSBpbiBwcmV2aW91c1ZhbHVlKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG5vZGUuc3R5bGVbaV0gPSBcIlwiO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAodHlwZW9mIHByZXZpb3VzVmFsdWUgPT09IFwic3RyaW5nXCIpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBub2RlW3Byb3BOYW1lXSA9IFwiXCI7XG4gICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIG5vZGVbcHJvcE5hbWVdID0gbnVsbDtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIGlmIChwcmV2aW91c1ZhbHVlLnVuaG9vaykge1xuICAgICAgICAgICAgICAgICAgICAgICAgcHJldmlvdXNWYWx1ZS51bmhvb2sobm9kZSwgcHJvcE5hbWUsIHByb3BWYWx1ZSk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIHBhdGNoT2JqZWN0KG5vZGUsIHByb3BzLCBwcmV2aW91cywgcHJvcE5hbWUsIHByb3BWYWx1ZSkge1xuICAgICAgICAgICAgICAgIHZhciBwcmV2aW91c1ZhbHVlID0gcHJldmlvdXMgPyBwcmV2aW91c1twcm9wTmFtZV0gOiB1bmRlZmluZWQ7XG5cbiAgICAgICAgICAgICAgICAvLyBTZXQgYXR0cmlidXRlc1xuICAgICAgICAgICAgICAgIGlmIChwcm9wTmFtZSA9PT0gXCJhdHRyaWJ1dGVzXCIpIHtcbiAgICAgICAgICAgICAgICAgICAgZm9yICh2YXIgYXR0ck5hbWUgaW4gcHJvcFZhbHVlKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICB2YXIgYXR0clZhbHVlID0gcHJvcFZhbHVlW2F0dHJOYW1lXTtcblxuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGF0dHJWYWx1ZSA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgbm9kZS5yZW1vdmVBdHRyaWJ1dGUoYXR0ck5hbWUpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBub2RlLnNldEF0dHJpYnV0ZShhdHRyTmFtZSwgYXR0clZhbHVlKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICBpZiAocHJldmlvdXNWYWx1ZSAmJiBpc09iamVjdChwcmV2aW91c1ZhbHVlKSAmJiBnZXRQcm90b3R5cGUocHJldmlvdXNWYWx1ZSkgIT09IGdldFByb3RvdHlwZShwcm9wVmFsdWUpKSB7XG4gICAgICAgICAgICAgICAgICAgIG5vZGVbcHJvcE5hbWVdID0gcHJvcFZhbHVlO1xuICAgICAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgaWYgKCFpc09iamVjdChub2RlW3Byb3BOYW1lXSkpIHtcbiAgICAgICAgICAgICAgICAgICAgbm9kZVtwcm9wTmFtZV0gPSB7fTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICB2YXIgcmVwbGFjZXIgPSBwcm9wTmFtZSA9PT0gXCJzdHlsZVwiID8gXCJcIiA6IHVuZGVmaW5lZDtcblxuICAgICAgICAgICAgICAgIGZvciAodmFyIGsgaW4gcHJvcFZhbHVlKSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciB2YWx1ZSA9IHByb3BWYWx1ZVtrXTtcbiAgICAgICAgICAgICAgICAgICAgbm9kZVtwcm9wTmFtZV1ba10gPSB2YWx1ZSA9PT0gdW5kZWZpbmVkID8gcmVwbGFjZXIgOiB2YWx1ZTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIGdldFByb3RvdHlwZSh2YWx1ZSkge1xuICAgICAgICAgICAgICAgIGlmIChPYmplY3QuZ2V0UHJvdG90eXBlT2YpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIE9iamVjdC5nZXRQcm90b3R5cGVPZih2YWx1ZSk7XG4gICAgICAgICAgICAgICAgfSBlbHNlIGlmICh2YWx1ZS5fX3Byb3RvX18pIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHZhbHVlLl9fcHJvdG9fXztcbiAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKHZhbHVlLmNvbnN0cnVjdG9yKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiB2YWx1ZS5jb25zdHJ1Y3Rvci5wcm90b3R5cGU7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9LCB7IFwiLi4vdm5vZGUvaXMtdmhvb2suanNcIjogMjYsIFwiaXMtb2JqZWN0XCI6IDExIH1dLCAxNTogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHtcbiAgICAgICAgICAgIHZhciBkb2N1bWVudCA9IHJlcXVpcmUoXCJnbG9iYWwvZG9jdW1lbnRcIik7XG5cbiAgICAgICAgICAgIHZhciBhcHBseVByb3BlcnRpZXMgPSByZXF1aXJlKFwiLi9hcHBseS1wcm9wZXJ0aWVzXCIpO1xuXG4gICAgICAgICAgICB2YXIgaXNWTm9kZSA9IHJlcXVpcmUoXCIuLi92bm9kZS9pcy12bm9kZS5qc1wiKTtcbiAgICAgICAgICAgIHZhciBpc1ZUZXh0ID0gcmVxdWlyZShcIi4uL3Zub2RlL2lzLXZ0ZXh0LmpzXCIpO1xuICAgICAgICAgICAgdmFyIGlzV2lkZ2V0ID0gcmVxdWlyZShcIi4uL3Zub2RlL2lzLXdpZGdldC5qc1wiKTtcbiAgICAgICAgICAgIHZhciBoYW5kbGVUaHVuayA9IHJlcXVpcmUoXCIuLi92bm9kZS9oYW5kbGUtdGh1bmsuanNcIik7XG5cbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gY3JlYXRlRWxlbWVudDtcblxuICAgICAgICAgICAgZnVuY3Rpb24gY3JlYXRlRWxlbWVudCh2bm9kZSwgb3B0cykge1xuICAgICAgICAgICAgICAgIHZhciBkb2MgPSBvcHRzID8gb3B0cy5kb2N1bWVudCB8fCBkb2N1bWVudCA6IGRvY3VtZW50O1xuICAgICAgICAgICAgICAgIHZhciB3YXJuID0gb3B0cyA/IG9wdHMud2FybiA6IG51bGw7XG5cbiAgICAgICAgICAgICAgICB2bm9kZSA9IGhhbmRsZVRodW5rKHZub2RlKS5hO1xuXG4gICAgICAgICAgICAgICAgaWYgKGlzV2lkZ2V0KHZub2RlKSkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gdm5vZGUuaW5pdCgpO1xuICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoaXNWVGV4dCh2bm9kZSkpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGRvYy5jcmVhdGVUZXh0Tm9kZSh2bm9kZS50ZXh0KTtcbiAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKCFpc1ZOb2RlKHZub2RlKSkge1xuICAgICAgICAgICAgICAgICAgICBpZiAod2Fybikge1xuICAgICAgICAgICAgICAgICAgICAgICAgd2FybihcIkl0ZW0gaXMgbm90IGEgdmFsaWQgdmlydHVhbCBkb20gbm9kZVwiLCB2bm9kZSk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIG51bGw7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgdmFyIG5vZGUgPSB2bm9kZS5uYW1lc3BhY2UgPT09IG51bGwgPyBkb2MuY3JlYXRlRWxlbWVudCh2bm9kZS50YWdOYW1lKSA6IGRvYy5jcmVhdGVFbGVtZW50TlModm5vZGUubmFtZXNwYWNlLCB2bm9kZS50YWdOYW1lKTtcblxuICAgICAgICAgICAgICAgIHZhciBwcm9wcyA9IHZub2RlLnByb3BlcnRpZXM7XG4gICAgICAgICAgICAgICAgYXBwbHlQcm9wZXJ0aWVzKG5vZGUsIHByb3BzKTtcblxuICAgICAgICAgICAgICAgIHZhciBjaGlsZHJlbiA9IHZub2RlLmNoaWxkcmVuO1xuXG4gICAgICAgICAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCBjaGlsZHJlbi5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgICAgICAgICB2YXIgY2hpbGROb2RlID0gY3JlYXRlRWxlbWVudChjaGlsZHJlbltpXSwgb3B0cyk7XG4gICAgICAgICAgICAgICAgICAgIGlmIChjaGlsZE5vZGUpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIG5vZGUuYXBwZW5kQ2hpbGQoY2hpbGROb2RlKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHJldHVybiBub2RlO1xuICAgICAgICAgICAgfVxuICAgICAgICB9LCB7IFwiLi4vdm5vZGUvaGFuZGxlLXRodW5rLmpzXCI6IDI0LCBcIi4uL3Zub2RlL2lzLXZub2RlLmpzXCI6IDI3LCBcIi4uL3Zub2RlL2lzLXZ0ZXh0LmpzXCI6IDI4LCBcIi4uL3Zub2RlL2lzLXdpZGdldC5qc1wiOiAyOSwgXCIuL2FwcGx5LXByb3BlcnRpZXNcIjogMTQsIFwiZ2xvYmFsL2RvY3VtZW50XCI6IDEwIH1dLCAxNjogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHtcbiAgICAgICAgICAgIC8vIE1hcHMgYSB2aXJ0dWFsIERPTSB0cmVlIG9udG8gYSByZWFsIERPTSB0cmVlIGluIGFuIGVmZmljaWVudCBtYW5uZXIuXG4gICAgICAgICAgICAvLyBXZSBkb24ndCB3YW50IHRvIHJlYWQgYWxsIG9mIHRoZSBET00gbm9kZXMgaW4gdGhlIHRyZWUgc28gd2UgdXNlXG4gICAgICAgICAgICAvLyB0aGUgaW4tb3JkZXIgdHJlZSBpbmRleGluZyB0byBlbGltaW5hdGUgcmVjdXJzaW9uIGRvd24gY2VydGFpbiBicmFuY2hlcy5cbiAgICAgICAgICAgIC8vIFdlIG9ubHkgcmVjdXJzZSBpbnRvIGEgRE9NIG5vZGUgaWYgd2Uga25vdyB0aGF0IGl0IGNvbnRhaW5zIGEgY2hpbGQgb2ZcbiAgICAgICAgICAgIC8vIGludGVyZXN0LlxuXG4gICAgICAgICAgICB2YXIgbm9DaGlsZCA9IHt9O1xuXG4gICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IGRvbUluZGV4O1xuXG4gICAgICAgICAgICBmdW5jdGlvbiBkb21JbmRleChyb290Tm9kZSwgdHJlZSwgaW5kaWNlcywgbm9kZXMpIHtcbiAgICAgICAgICAgICAgICBpZiAoIWluZGljZXMgfHwgaW5kaWNlcy5sZW5ndGggPT09IDApIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHt9O1xuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIGluZGljZXMuc29ydChhc2NlbmRpbmcpO1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gcmVjdXJzZShyb290Tm9kZSwgdHJlZSwgaW5kaWNlcywgbm9kZXMsIDApO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZnVuY3Rpb24gcmVjdXJzZShyb290Tm9kZSwgdHJlZSwgaW5kaWNlcywgbm9kZXMsIHJvb3RJbmRleCkge1xuICAgICAgICAgICAgICAgIG5vZGVzID0gbm9kZXMgfHwge307XG5cbiAgICAgICAgICAgICAgICBpZiAocm9vdE5vZGUpIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKGluZGV4SW5SYW5nZShpbmRpY2VzLCByb290SW5kZXgsIHJvb3RJbmRleCkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIG5vZGVzW3Jvb3RJbmRleF0gPSByb290Tm9kZTtcbiAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgIHZhciB2Q2hpbGRyZW4gPSB0cmVlLmNoaWxkcmVuO1xuXG4gICAgICAgICAgICAgICAgICAgIGlmICh2Q2hpbGRyZW4pIHtcblxuICAgICAgICAgICAgICAgICAgICAgICAgdmFyIGNoaWxkTm9kZXMgPSByb290Tm9kZS5jaGlsZE5vZGVzO1xuXG4gICAgICAgICAgICAgICAgICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IHRyZWUuY2hpbGRyZW4ubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICByb290SW5kZXggKz0gMTtcblxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZhciB2Q2hpbGQgPSB2Q2hpbGRyZW5baV0gfHwgbm9DaGlsZDtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB2YXIgbmV4dEluZGV4ID0gcm9vdEluZGV4ICsgKHZDaGlsZC5jb3VudCB8fCAwKTtcblxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIHNraXAgcmVjdXJzaW9uIGRvd24gdGhlIHRyZWUgaWYgdGhlcmUgYXJlIG5vIG5vZGVzIGRvd24gaGVyZVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChpbmRleEluUmFuZ2UoaW5kaWNlcywgcm9vdEluZGV4LCBuZXh0SW5kZXgpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlY3Vyc2UoY2hpbGROb2Rlc1tpXSwgdkNoaWxkLCBpbmRpY2VzLCBub2Rlcywgcm9vdEluZGV4KTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICByb290SW5kZXggPSBuZXh0SW5kZXg7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICByZXR1cm4gbm9kZXM7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIC8vIEJpbmFyeSBzZWFyY2ggZm9yIGFuIGluZGV4IGluIHRoZSBpbnRlcnZhbCBbbGVmdCwgcmlnaHRdXG4gICAgICAgICAgICBmdW5jdGlvbiBpbmRleEluUmFuZ2UoaW5kaWNlcywgbGVmdCwgcmlnaHQpIHtcbiAgICAgICAgICAgICAgICBpZiAoaW5kaWNlcy5sZW5ndGggPT09IDApIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHZhciBtaW5JbmRleCA9IDA7XG4gICAgICAgICAgICAgICAgdmFyIG1heEluZGV4ID0gaW5kaWNlcy5sZW5ndGggLSAxO1xuICAgICAgICAgICAgICAgIHZhciBjdXJyZW50SW5kZXg7XG4gICAgICAgICAgICAgICAgdmFyIGN1cnJlbnRJdGVtO1xuXG4gICAgICAgICAgICAgICAgd2hpbGUgKG1pbkluZGV4IDw9IG1heEluZGV4KSB7XG4gICAgICAgICAgICAgICAgICAgIGN1cnJlbnRJbmRleCA9IChtYXhJbmRleCArIG1pbkluZGV4KSAvIDIgPj4gMDtcbiAgICAgICAgICAgICAgICAgICAgY3VycmVudEl0ZW0gPSBpbmRpY2VzW2N1cnJlbnRJbmRleF07XG5cbiAgICAgICAgICAgICAgICAgICAgaWYgKG1pbkluZGV4ID09PSBtYXhJbmRleCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGN1cnJlbnRJdGVtID49IGxlZnQgJiYgY3VycmVudEl0ZW0gPD0gcmlnaHQ7XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoY3VycmVudEl0ZW0gPCBsZWZ0KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBtaW5JbmRleCA9IGN1cnJlbnRJbmRleCArIDE7XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoY3VycmVudEl0ZW0gPiByaWdodCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgbWF4SW5kZXggPSBjdXJyZW50SW5kZXggLSAxO1xuICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIGFzY2VuZGluZyhhLCBiKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGEgPiBiID8gMSA6IC0xO1xuICAgICAgICAgICAgfVxuICAgICAgICB9LCB7fV0sIDE3OiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge1xuICAgICAgICAgICAgdmFyIGFwcGx5UHJvcGVydGllcyA9IHJlcXVpcmUoXCIuL2FwcGx5LXByb3BlcnRpZXNcIik7XG5cbiAgICAgICAgICAgIHZhciBpc1dpZGdldCA9IHJlcXVpcmUoXCIuLi92bm9kZS9pcy13aWRnZXQuanNcIik7XG4gICAgICAgICAgICB2YXIgVlBhdGNoID0gcmVxdWlyZShcIi4uL3Zub2RlL3ZwYXRjaC5qc1wiKTtcblxuICAgICAgICAgICAgdmFyIHVwZGF0ZVdpZGdldCA9IHJlcXVpcmUoXCIuL3VwZGF0ZS13aWRnZXRcIik7XG5cbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gYXBwbHlQYXRjaDtcblxuICAgICAgICAgICAgZnVuY3Rpb24gYXBwbHlQYXRjaCh2cGF0Y2gsIGRvbU5vZGUsIHJlbmRlck9wdGlvbnMpIHtcbiAgICAgICAgICAgICAgICB2YXIgdHlwZSA9IHZwYXRjaC50eXBlO1xuICAgICAgICAgICAgICAgIHZhciB2Tm9kZSA9IHZwYXRjaC52Tm9kZTtcbiAgICAgICAgICAgICAgICB2YXIgcGF0Y2ggPSB2cGF0Y2gucGF0Y2g7XG5cbiAgICAgICAgICAgICAgICBzd2l0Y2ggKHR5cGUpIHtcbiAgICAgICAgICAgICAgICAgICAgY2FzZSBWUGF0Y2guUkVNT1ZFOlxuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHJlbW92ZU5vZGUoZG9tTm9kZSwgdk5vZGUpO1xuICAgICAgICAgICAgICAgICAgICBjYXNlIFZQYXRjaC5JTlNFUlQ6XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gaW5zZXJ0Tm9kZShkb21Ob2RlLCBwYXRjaCwgcmVuZGVyT3B0aW9ucyk7XG4gICAgICAgICAgICAgICAgICAgIGNhc2UgVlBhdGNoLlZURVhUOlxuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHN0cmluZ1BhdGNoKGRvbU5vZGUsIHZOb2RlLCBwYXRjaCwgcmVuZGVyT3B0aW9ucyk7XG4gICAgICAgICAgICAgICAgICAgIGNhc2UgVlBhdGNoLldJREdFVDpcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiB3aWRnZXRQYXRjaChkb21Ob2RlLCB2Tm9kZSwgcGF0Y2gsIHJlbmRlck9wdGlvbnMpO1xuICAgICAgICAgICAgICAgICAgICBjYXNlIFZQYXRjaC5WTk9ERTpcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiB2Tm9kZVBhdGNoKGRvbU5vZGUsIHZOb2RlLCBwYXRjaCwgcmVuZGVyT3B0aW9ucyk7XG4gICAgICAgICAgICAgICAgICAgIGNhc2UgVlBhdGNoLk9SREVSOlxuICAgICAgICAgICAgICAgICAgICAgICAgcmVvcmRlckNoaWxkcmVuKGRvbU5vZGUsIHBhdGNoKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBkb21Ob2RlO1xuICAgICAgICAgICAgICAgICAgICBjYXNlIFZQYXRjaC5QUk9QUzpcbiAgICAgICAgICAgICAgICAgICAgICAgIGFwcGx5UHJvcGVydGllcyhkb21Ob2RlLCBwYXRjaCwgdk5vZGUucHJvcGVydGllcyk7XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gZG9tTm9kZTtcbiAgICAgICAgICAgICAgICAgICAgY2FzZSBWUGF0Y2guVEhVTks6XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gcmVwbGFjZVJvb3QoZG9tTm9kZSwgcmVuZGVyT3B0aW9ucy5wYXRjaChkb21Ob2RlLCBwYXRjaCwgcmVuZGVyT3B0aW9ucykpO1xuICAgICAgICAgICAgICAgICAgICBkZWZhdWx0OlxuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGRvbU5vZGU7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBmdW5jdGlvbiByZW1vdmVOb2RlKGRvbU5vZGUsIHZOb2RlKSB7XG4gICAgICAgICAgICAgICAgdmFyIHBhcmVudE5vZGUgPSBkb21Ob2RlLnBhcmVudE5vZGU7XG5cbiAgICAgICAgICAgICAgICBpZiAocGFyZW50Tm9kZSkge1xuICAgICAgICAgICAgICAgICAgICBwYXJlbnROb2RlLnJlbW92ZUNoaWxkKGRvbU5vZGUpO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIGRlc3Ryb3lXaWRnZXQoZG9tTm9kZSwgdk5vZGUpO1xuXG4gICAgICAgICAgICAgICAgcmV0dXJuIG51bGw7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIGluc2VydE5vZGUocGFyZW50Tm9kZSwgdk5vZGUsIHJlbmRlck9wdGlvbnMpIHtcbiAgICAgICAgICAgICAgICB2YXIgbmV3Tm9kZSA9IHJlbmRlck9wdGlvbnMucmVuZGVyKHZOb2RlLCByZW5kZXJPcHRpb25zKTtcblxuICAgICAgICAgICAgICAgIGlmIChwYXJlbnROb2RlKSB7XG4gICAgICAgICAgICAgICAgICAgIHBhcmVudE5vZGUuYXBwZW5kQ2hpbGQobmV3Tm9kZSk7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgcmV0dXJuIHBhcmVudE5vZGU7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIHN0cmluZ1BhdGNoKGRvbU5vZGUsIGxlZnRWTm9kZSwgdlRleHQsIHJlbmRlck9wdGlvbnMpIHtcbiAgICAgICAgICAgICAgICB2YXIgbmV3Tm9kZTtcblxuICAgICAgICAgICAgICAgIGlmIChkb21Ob2RlLm5vZGVUeXBlID09PSAzKSB7XG4gICAgICAgICAgICAgICAgICAgIGRvbU5vZGUucmVwbGFjZURhdGEoMCwgZG9tTm9kZS5sZW5ndGgsIHZUZXh0LnRleHQpO1xuICAgICAgICAgICAgICAgICAgICBuZXdOb2RlID0gZG9tTm9kZTtcbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICB2YXIgcGFyZW50Tm9kZSA9IGRvbU5vZGUucGFyZW50Tm9kZTtcbiAgICAgICAgICAgICAgICAgICAgbmV3Tm9kZSA9IHJlbmRlck9wdGlvbnMucmVuZGVyKHZUZXh0LCByZW5kZXJPcHRpb25zKTtcblxuICAgICAgICAgICAgICAgICAgICBpZiAocGFyZW50Tm9kZSAmJiBuZXdOb2RlICE9PSBkb21Ob2RlKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBwYXJlbnROb2RlLnJlcGxhY2VDaGlsZChuZXdOb2RlLCBkb21Ob2RlKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHJldHVybiBuZXdOb2RlO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBmdW5jdGlvbiB3aWRnZXRQYXRjaChkb21Ob2RlLCBsZWZ0Vk5vZGUsIHdpZGdldCwgcmVuZGVyT3B0aW9ucykge1xuICAgICAgICAgICAgICAgIHZhciB1cGRhdGluZyA9IHVwZGF0ZVdpZGdldChsZWZ0Vk5vZGUsIHdpZGdldCk7XG4gICAgICAgICAgICAgICAgdmFyIG5ld05vZGU7XG5cbiAgICAgICAgICAgICAgICBpZiAodXBkYXRpbmcpIHtcbiAgICAgICAgICAgICAgICAgICAgbmV3Tm9kZSA9IHdpZGdldC51cGRhdGUobGVmdFZOb2RlLCBkb21Ob2RlKSB8fCBkb21Ob2RlO1xuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIG5ld05vZGUgPSByZW5kZXJPcHRpb25zLnJlbmRlcih3aWRnZXQsIHJlbmRlck9wdGlvbnMpO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHZhciBwYXJlbnROb2RlID0gZG9tTm9kZS5wYXJlbnROb2RlO1xuXG4gICAgICAgICAgICAgICAgaWYgKHBhcmVudE5vZGUgJiYgbmV3Tm9kZSAhPT0gZG9tTm9kZSkge1xuICAgICAgICAgICAgICAgICAgICBwYXJlbnROb2RlLnJlcGxhY2VDaGlsZChuZXdOb2RlLCBkb21Ob2RlKTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICBpZiAoIXVwZGF0aW5nKSB7XG4gICAgICAgICAgICAgICAgICAgIGRlc3Ryb3lXaWRnZXQoZG9tTm9kZSwgbGVmdFZOb2RlKTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICByZXR1cm4gbmV3Tm9kZTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZnVuY3Rpb24gdk5vZGVQYXRjaChkb21Ob2RlLCBsZWZ0Vk5vZGUsIHZOb2RlLCByZW5kZXJPcHRpb25zKSB7XG4gICAgICAgICAgICAgICAgdmFyIHBhcmVudE5vZGUgPSBkb21Ob2RlLnBhcmVudE5vZGU7XG4gICAgICAgICAgICAgICAgdmFyIG5ld05vZGUgPSByZW5kZXJPcHRpb25zLnJlbmRlcih2Tm9kZSwgcmVuZGVyT3B0aW9ucyk7XG5cbiAgICAgICAgICAgICAgICBpZiAocGFyZW50Tm9kZSAmJiBuZXdOb2RlICE9PSBkb21Ob2RlKSB7XG4gICAgICAgICAgICAgICAgICAgIHBhcmVudE5vZGUucmVwbGFjZUNoaWxkKG5ld05vZGUsIGRvbU5vZGUpO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHJldHVybiBuZXdOb2RlO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBmdW5jdGlvbiBkZXN0cm95V2lkZ2V0KGRvbU5vZGUsIHcpIHtcbiAgICAgICAgICAgICAgICBpZiAodHlwZW9mIHcuZGVzdHJveSA9PT0gXCJmdW5jdGlvblwiICYmIGlzV2lkZ2V0KHcpKSB7XG4gICAgICAgICAgICAgICAgICAgIHcuZGVzdHJveShkb21Ob2RlKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIHJlb3JkZXJDaGlsZHJlbihkb21Ob2RlLCBtb3Zlcykge1xuICAgICAgICAgICAgICAgIHZhciBjaGlsZE5vZGVzID0gZG9tTm9kZS5jaGlsZE5vZGVzO1xuICAgICAgICAgICAgICAgIHZhciBrZXlNYXAgPSB7fTtcbiAgICAgICAgICAgICAgICB2YXIgbm9kZTtcbiAgICAgICAgICAgICAgICB2YXIgcmVtb3ZlO1xuICAgICAgICAgICAgICAgIHZhciBpbnNlcnQ7XG5cbiAgICAgICAgICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IG1vdmVzLnJlbW92ZXMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgICAgICAgICAgcmVtb3ZlID0gbW92ZXMucmVtb3Zlc1tpXTtcbiAgICAgICAgICAgICAgICAgICAgbm9kZSA9IGNoaWxkTm9kZXNbcmVtb3ZlLmZyb21dO1xuICAgICAgICAgICAgICAgICAgICBpZiAocmVtb3ZlLmtleSkge1xuICAgICAgICAgICAgICAgICAgICAgICAga2V5TWFwW3JlbW92ZS5rZXldID0gbm9kZTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICBkb21Ob2RlLnJlbW92ZUNoaWxkKG5vZGUpO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHZhciBsZW5ndGggPSBjaGlsZE5vZGVzLmxlbmd0aDtcbiAgICAgICAgICAgICAgICBmb3IgKHZhciBqID0gMDsgaiA8IG1vdmVzLmluc2VydHMubGVuZ3RoOyBqKyspIHtcbiAgICAgICAgICAgICAgICAgICAgaW5zZXJ0ID0gbW92ZXMuaW5zZXJ0c1tqXTtcbiAgICAgICAgICAgICAgICAgICAgbm9kZSA9IGtleU1hcFtpbnNlcnQua2V5XTtcbiAgICAgICAgICAgICAgICAgICAgLy8gdGhpcyBpcyB0aGUgd2VpcmRlc3QgYnVnIGkndmUgZXZlciBzZWVuIGluIHdlYmtpdFxuICAgICAgICAgICAgICAgICAgICBkb21Ob2RlLmluc2VydEJlZm9yZShub2RlLCBpbnNlcnQudG8gPj0gbGVuZ3RoKysgPyBudWxsIDogY2hpbGROb2Rlc1tpbnNlcnQudG9dKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIHJlcGxhY2VSb290KG9sZFJvb3QsIG5ld1Jvb3QpIHtcbiAgICAgICAgICAgICAgICBpZiAob2xkUm9vdCAmJiBuZXdSb290ICYmIG9sZFJvb3QgIT09IG5ld1Jvb3QgJiYgb2xkUm9vdC5wYXJlbnROb2RlKSB7XG4gICAgICAgICAgICAgICAgICAgIG9sZFJvb3QucGFyZW50Tm9kZS5yZXBsYWNlQ2hpbGQobmV3Um9vdCwgb2xkUm9vdCk7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgcmV0dXJuIG5ld1Jvb3Q7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0sIHsgXCIuLi92bm9kZS9pcy13aWRnZXQuanNcIjogMjksIFwiLi4vdm5vZGUvdnBhdGNoLmpzXCI6IDMyLCBcIi4vYXBwbHktcHJvcGVydGllc1wiOiAxNCwgXCIuL3VwZGF0ZS13aWRnZXRcIjogMTkgfV0sIDE4OiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge1xuICAgICAgICAgICAgdmFyIGRvY3VtZW50ID0gcmVxdWlyZShcImdsb2JhbC9kb2N1bWVudFwiKTtcbiAgICAgICAgICAgIHZhciBpc0FycmF5ID0gcmVxdWlyZShcIngtaXMtYXJyYXlcIik7XG5cbiAgICAgICAgICAgIHZhciByZW5kZXIgPSByZXF1aXJlKFwiLi9jcmVhdGUtZWxlbWVudFwiKTtcbiAgICAgICAgICAgIHZhciBkb21JbmRleCA9IHJlcXVpcmUoXCIuL2RvbS1pbmRleFwiKTtcbiAgICAgICAgICAgIHZhciBwYXRjaE9wID0gcmVxdWlyZShcIi4vcGF0Y2gtb3BcIik7XG4gICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IHBhdGNoO1xuXG4gICAgICAgICAgICBmdW5jdGlvbiBwYXRjaChyb290Tm9kZSwgcGF0Y2hlcywgcmVuZGVyT3B0aW9ucykge1xuICAgICAgICAgICAgICAgIHJlbmRlck9wdGlvbnMgPSByZW5kZXJPcHRpb25zIHx8IHt9O1xuICAgICAgICAgICAgICAgIHJlbmRlck9wdGlvbnMucGF0Y2ggPSByZW5kZXJPcHRpb25zLnBhdGNoICYmIHJlbmRlck9wdGlvbnMucGF0Y2ggIT09IHBhdGNoID8gcmVuZGVyT3B0aW9ucy5wYXRjaCA6IHBhdGNoUmVjdXJzaXZlO1xuICAgICAgICAgICAgICAgIHJlbmRlck9wdGlvbnMucmVuZGVyID0gcmVuZGVyT3B0aW9ucy5yZW5kZXIgfHwgcmVuZGVyO1xuXG4gICAgICAgICAgICAgICAgcmV0dXJuIHJlbmRlck9wdGlvbnMucGF0Y2gocm9vdE5vZGUsIHBhdGNoZXMsIHJlbmRlck9wdGlvbnMpO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBmdW5jdGlvbiBwYXRjaFJlY3Vyc2l2ZShyb290Tm9kZSwgcGF0Y2hlcywgcmVuZGVyT3B0aW9ucykge1xuICAgICAgICAgICAgICAgIHZhciBpbmRpY2VzID0gcGF0Y2hJbmRpY2VzKHBhdGNoZXMpO1xuXG4gICAgICAgICAgICAgICAgaWYgKGluZGljZXMubGVuZ3RoID09PSAwKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiByb290Tm9kZTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICB2YXIgaW5kZXggPSBkb21JbmRleChyb290Tm9kZSwgcGF0Y2hlcy5hLCBpbmRpY2VzKTtcbiAgICAgICAgICAgICAgICB2YXIgb3duZXJEb2N1bWVudCA9IHJvb3ROb2RlLm93bmVyRG9jdW1lbnQ7XG5cbiAgICAgICAgICAgICAgICBpZiAoIXJlbmRlck9wdGlvbnMuZG9jdW1lbnQgJiYgb3duZXJEb2N1bWVudCAhPT0gZG9jdW1lbnQpIHtcbiAgICAgICAgICAgICAgICAgICAgcmVuZGVyT3B0aW9ucy5kb2N1bWVudCA9IG93bmVyRG9jdW1lbnQ7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCBpbmRpY2VzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciBub2RlSW5kZXggPSBpbmRpY2VzW2ldO1xuICAgICAgICAgICAgICAgICAgICByb290Tm9kZSA9IGFwcGx5UGF0Y2gocm9vdE5vZGUsIGluZGV4W25vZGVJbmRleF0sIHBhdGNoZXNbbm9kZUluZGV4XSwgcmVuZGVyT3B0aW9ucyk7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgcmV0dXJuIHJvb3ROb2RlO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBmdW5jdGlvbiBhcHBseVBhdGNoKHJvb3ROb2RlLCBkb21Ob2RlLCBwYXRjaExpc3QsIHJlbmRlck9wdGlvbnMpIHtcbiAgICAgICAgICAgICAgICBpZiAoIWRvbU5vZGUpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHJvb3ROb2RlO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHZhciBuZXdOb2RlO1xuXG4gICAgICAgICAgICAgICAgaWYgKGlzQXJyYXkocGF0Y2hMaXN0KSkge1xuICAgICAgICAgICAgICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IHBhdGNoTGlzdC5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgICAgICAgICAgICAgbmV3Tm9kZSA9IHBhdGNoT3AocGF0Y2hMaXN0W2ldLCBkb21Ob2RlLCByZW5kZXJPcHRpb25zKTtcblxuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGRvbU5vZGUgPT09IHJvb3ROb2RlKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcm9vdE5vZGUgPSBuZXdOb2RlO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgbmV3Tm9kZSA9IHBhdGNoT3AocGF0Y2hMaXN0LCBkb21Ob2RlLCByZW5kZXJPcHRpb25zKTtcblxuICAgICAgICAgICAgICAgICAgICBpZiAoZG9tTm9kZSA9PT0gcm9vdE5vZGUpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJvb3ROb2RlID0gbmV3Tm9kZTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHJldHVybiByb290Tm9kZTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZnVuY3Rpb24gcGF0Y2hJbmRpY2VzKHBhdGNoZXMpIHtcbiAgICAgICAgICAgICAgICB2YXIgaW5kaWNlcyA9IFtdO1xuXG4gICAgICAgICAgICAgICAgZm9yICh2YXIga2V5IGluIHBhdGNoZXMpIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKGtleSAhPT0gXCJhXCIpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGluZGljZXMucHVzaChOdW1iZXIoa2V5KSk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICByZXR1cm4gaW5kaWNlcztcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSwgeyBcIi4vY3JlYXRlLWVsZW1lbnRcIjogMTUsIFwiLi9kb20taW5kZXhcIjogMTYsIFwiLi9wYXRjaC1vcFwiOiAxNywgXCJnbG9iYWwvZG9jdW1lbnRcIjogMTAsIFwieC1pcy1hcnJheVwiOiAxMiB9XSwgMTk6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICB2YXIgaXNXaWRnZXQgPSByZXF1aXJlKFwiLi4vdm5vZGUvaXMtd2lkZ2V0LmpzXCIpO1xuXG4gICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IHVwZGF0ZVdpZGdldDtcblxuICAgICAgICAgICAgZnVuY3Rpb24gdXBkYXRlV2lkZ2V0KGEsIGIpIHtcbiAgICAgICAgICAgICAgICBpZiAoaXNXaWRnZXQoYSkgJiYgaXNXaWRnZXQoYikpIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKFwibmFtZVwiIGluIGEgJiYgXCJuYW1lXCIgaW4gYikge1xuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGEuaWQgPT09IGIuaWQ7XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gYS5pbml0ID09PSBiLmluaXQ7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0sIHsgXCIuLi92bm9kZS9pcy13aWRnZXQuanNcIjogMjkgfV0sIDIwOiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge1xuICAgICAgICAgICAgJ3VzZSBzdHJpY3QnO1xuXG4gICAgICAgICAgICB2YXIgRXZTdG9yZSA9IHJlcXVpcmUoJ2V2LXN0b3JlJyk7XG5cbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gRXZIb29rO1xuXG4gICAgICAgICAgICBmdW5jdGlvbiBFdkhvb2sodmFsdWUpIHtcbiAgICAgICAgICAgICAgICBpZiAoISh0aGlzIGluc3RhbmNlb2YgRXZIb29rKSkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gbmV3IEV2SG9vayh2YWx1ZSk7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgdGhpcy52YWx1ZSA9IHZhbHVlO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBFdkhvb2sucHJvdG90eXBlLmhvb2sgPSBmdW5jdGlvbiAobm9kZSwgcHJvcGVydHlOYW1lKSB7XG4gICAgICAgICAgICAgICAgdmFyIGVzID0gRXZTdG9yZShub2RlKTtcbiAgICAgICAgICAgICAgICB2YXIgcHJvcE5hbWUgPSBwcm9wZXJ0eU5hbWUuc3Vic3RyKDMpO1xuXG4gICAgICAgICAgICAgICAgZXNbcHJvcE5hbWVdID0gdGhpcy52YWx1ZTtcbiAgICAgICAgICAgIH07XG5cbiAgICAgICAgICAgIEV2SG9vay5wcm90b3R5cGUudW5ob29rID0gZnVuY3Rpb24gKG5vZGUsIHByb3BlcnR5TmFtZSkge1xuICAgICAgICAgICAgICAgIHZhciBlcyA9IEV2U3RvcmUobm9kZSk7XG4gICAgICAgICAgICAgICAgdmFyIHByb3BOYW1lID0gcHJvcGVydHlOYW1lLnN1YnN0cigzKTtcblxuICAgICAgICAgICAgICAgIGVzW3Byb3BOYW1lXSA9IHVuZGVmaW5lZDtcbiAgICAgICAgICAgIH07XG4gICAgICAgIH0sIHsgXCJldi1zdG9yZVwiOiA3IH1dLCAyMTogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHtcbiAgICAgICAgICAgICd1c2Ugc3RyaWN0JztcblxuICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBTb2Z0U2V0SG9vaztcblxuICAgICAgICAgICAgZnVuY3Rpb24gU29mdFNldEhvb2sodmFsdWUpIHtcbiAgICAgICAgICAgICAgICBpZiAoISh0aGlzIGluc3RhbmNlb2YgU29mdFNldEhvb2spKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBuZXcgU29mdFNldEhvb2sodmFsdWUpO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHRoaXMudmFsdWUgPSB2YWx1ZTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgU29mdFNldEhvb2sucHJvdG90eXBlLmhvb2sgPSBmdW5jdGlvbiAobm9kZSwgcHJvcGVydHlOYW1lKSB7XG4gICAgICAgICAgICAgICAgaWYgKG5vZGVbcHJvcGVydHlOYW1lXSAhPT0gdGhpcy52YWx1ZSkge1xuICAgICAgICAgICAgICAgICAgICBub2RlW3Byb3BlcnR5TmFtZV0gPSB0aGlzLnZhbHVlO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH07XG4gICAgICAgIH0sIHt9XSwgMjI6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICAndXNlIHN0cmljdCc7XG5cbiAgICAgICAgICAgIHZhciBpc0FycmF5ID0gcmVxdWlyZSgneC1pcy1hcnJheScpO1xuXG4gICAgICAgICAgICB2YXIgVk5vZGUgPSByZXF1aXJlKCcuLi92bm9kZS92bm9kZS5qcycpO1xuICAgICAgICAgICAgdmFyIFZUZXh0ID0gcmVxdWlyZSgnLi4vdm5vZGUvdnRleHQuanMnKTtcbiAgICAgICAgICAgIHZhciBpc1ZOb2RlID0gcmVxdWlyZSgnLi4vdm5vZGUvaXMtdm5vZGUnKTtcbiAgICAgICAgICAgIHZhciBpc1ZUZXh0ID0gcmVxdWlyZSgnLi4vdm5vZGUvaXMtdnRleHQnKTtcbiAgICAgICAgICAgIHZhciBpc1dpZGdldCA9IHJlcXVpcmUoJy4uL3Zub2RlL2lzLXdpZGdldCcpO1xuICAgICAgICAgICAgdmFyIGlzSG9vayA9IHJlcXVpcmUoJy4uL3Zub2RlL2lzLXZob29rJyk7XG4gICAgICAgICAgICB2YXIgaXNWVGh1bmsgPSByZXF1aXJlKCcuLi92bm9kZS9pcy10aHVuaycpO1xuXG4gICAgICAgICAgICB2YXIgcGFyc2VUYWcgPSByZXF1aXJlKCcuL3BhcnNlLXRhZy5qcycpO1xuICAgICAgICAgICAgdmFyIHNvZnRTZXRIb29rID0gcmVxdWlyZSgnLi9ob29rcy9zb2Z0LXNldC1ob29rLmpzJyk7XG4gICAgICAgICAgICB2YXIgZXZIb29rID0gcmVxdWlyZSgnLi9ob29rcy9ldi1ob29rLmpzJyk7XG5cbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gaDtcblxuICAgICAgICAgICAgZnVuY3Rpb24gaCh0YWdOYW1lLCBwcm9wZXJ0aWVzLCBjaGlsZHJlbikge1xuICAgICAgICAgICAgICAgIHZhciBjaGlsZE5vZGVzID0gW107XG4gICAgICAgICAgICAgICAgdmFyIHRhZywgcHJvcHMsIGtleSwgbmFtZXNwYWNlO1xuXG4gICAgICAgICAgICAgICAgaWYgKCFjaGlsZHJlbiAmJiBpc0NoaWxkcmVuKHByb3BlcnRpZXMpKSB7XG4gICAgICAgICAgICAgICAgICAgIGNoaWxkcmVuID0gcHJvcGVydGllcztcbiAgICAgICAgICAgICAgICAgICAgcHJvcHMgPSB7fTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICBwcm9wcyA9IHByb3BzIHx8IHByb3BlcnRpZXMgfHwge307XG4gICAgICAgICAgICAgICAgdGFnID0gcGFyc2VUYWcodGFnTmFtZSwgcHJvcHMpO1xuXG4gICAgICAgICAgICAgICAgLy8gc3VwcG9ydCBrZXlzXG4gICAgICAgICAgICAgICAgaWYgKHByb3BzLmhhc093blByb3BlcnR5KCdrZXknKSkge1xuICAgICAgICAgICAgICAgICAgICBrZXkgPSBwcm9wcy5rZXk7XG4gICAgICAgICAgICAgICAgICAgIHByb3BzLmtleSA9IHVuZGVmaW5lZDtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAvLyBzdXBwb3J0IG5hbWVzcGFjZVxuICAgICAgICAgICAgICAgIGlmIChwcm9wcy5oYXNPd25Qcm9wZXJ0eSgnbmFtZXNwYWNlJykpIHtcbiAgICAgICAgICAgICAgICAgICAgbmFtZXNwYWNlID0gcHJvcHMubmFtZXNwYWNlO1xuICAgICAgICAgICAgICAgICAgICBwcm9wcy5uYW1lc3BhY2UgPSB1bmRlZmluZWQ7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgLy8gZml4IGN1cnNvciBidWdcbiAgICAgICAgICAgICAgICBpZiAodGFnID09PSAnSU5QVVQnICYmICFuYW1lc3BhY2UgJiYgcHJvcHMuaGFzT3duUHJvcGVydHkoJ3ZhbHVlJykgJiYgcHJvcHMudmFsdWUgIT09IHVuZGVmaW5lZCAmJiAhaXNIb29rKHByb3BzLnZhbHVlKSkge1xuICAgICAgICAgICAgICAgICAgICBwcm9wcy52YWx1ZSA9IHNvZnRTZXRIb29rKHByb3BzLnZhbHVlKTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICB0cmFuc2Zvcm1Qcm9wZXJ0aWVzKHByb3BzKTtcblxuICAgICAgICAgICAgICAgIGlmIChjaGlsZHJlbiAhPT0gdW5kZWZpbmVkICYmIGNoaWxkcmVuICE9PSBudWxsKSB7XG4gICAgICAgICAgICAgICAgICAgIGFkZENoaWxkKGNoaWxkcmVuLCBjaGlsZE5vZGVzLCB0YWcsIHByb3BzKTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICByZXR1cm4gbmV3IFZOb2RlKHRhZywgcHJvcHMsIGNoaWxkTm9kZXMsIGtleSwgbmFtZXNwYWNlKTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZnVuY3Rpb24gYWRkQ2hpbGQoYywgY2hpbGROb2RlcywgdGFnLCBwcm9wcykge1xuICAgICAgICAgICAgICAgIGlmICh0eXBlb2YgYyA9PT0gJ3N0cmluZycpIHtcbiAgICAgICAgICAgICAgICAgICAgY2hpbGROb2Rlcy5wdXNoKG5ldyBWVGV4dChjKSk7XG4gICAgICAgICAgICAgICAgfSBlbHNlIGlmICh0eXBlb2YgYyA9PT0gJ251bWJlcicpIHtcbiAgICAgICAgICAgICAgICAgICAgY2hpbGROb2Rlcy5wdXNoKG5ldyBWVGV4dChTdHJpbmcoYykpKTtcbiAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKGlzQ2hpbGQoYykpIHtcbiAgICAgICAgICAgICAgICAgICAgY2hpbGROb2Rlcy5wdXNoKGMpO1xuICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoaXNBcnJheShjKSkge1xuICAgICAgICAgICAgICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IGMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGFkZENoaWxkKGNbaV0sIGNoaWxkTm9kZXMsIHRhZywgcHJvcHMpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfSBlbHNlIGlmIChjID09PSBudWxsIHx8IGMgPT09IHVuZGVmaW5lZCkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgdGhyb3cgVW5leHBlY3RlZFZpcnR1YWxFbGVtZW50KHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGZvcmVpZ25PYmplY3Q6IGMsXG4gICAgICAgICAgICAgICAgICAgICAgICBwYXJlbnRWbm9kZToge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRhZ05hbWU6IHRhZyxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBwcm9wZXJ0aWVzOiBwcm9wc1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIHRyYW5zZm9ybVByb3BlcnRpZXMocHJvcHMpIHtcbiAgICAgICAgICAgICAgICBmb3IgKHZhciBwcm9wTmFtZSBpbiBwcm9wcykge1xuICAgICAgICAgICAgICAgICAgICBpZiAocHJvcHMuaGFzT3duUHJvcGVydHkocHJvcE5hbWUpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICB2YXIgdmFsdWUgPSBwcm9wc1twcm9wTmFtZV07XG5cbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChpc0hvb2sodmFsdWUpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgY29udGludWU7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChwcm9wTmFtZS5zdWJzdHIoMCwgMykgPT09ICdldi0nKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gYWRkIGV2LWZvbyBzdXBwb3J0XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcHJvcHNbcHJvcE5hbWVdID0gZXZIb29rKHZhbHVlKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZnVuY3Rpb24gaXNDaGlsZCh4KSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGlzVk5vZGUoeCkgfHwgaXNWVGV4dCh4KSB8fCBpc1dpZGdldCh4KSB8fCBpc1ZUaHVuayh4KTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZnVuY3Rpb24gaXNDaGlsZHJlbih4KSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHR5cGVvZiB4ID09PSAnc3RyaW5nJyB8fCBpc0FycmF5KHgpIHx8IGlzQ2hpbGQoeCk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIFVuZXhwZWN0ZWRWaXJ0dWFsRWxlbWVudChkYXRhKSB7XG4gICAgICAgICAgICAgICAgdmFyIGVyciA9IG5ldyBFcnJvcigpO1xuXG4gICAgICAgICAgICAgICAgZXJyLnR5cGUgPSAndmlydHVhbC1oeXBlcnNjcmlwdC51bmV4cGVjdGVkLnZpcnR1YWwtZWxlbWVudCc7XG4gICAgICAgICAgICAgICAgZXJyLm1lc3NhZ2UgPSAnVW5leHBlY3RlZCB2aXJ0dWFsIGNoaWxkIHBhc3NlZCB0byBoKCkuXFxuJyArICdFeHBlY3RlZCBhIFZOb2RlIC8gVnRodW5rIC8gVldpZGdldCAvIHN0cmluZyBidXQ6XFxuJyArICdnb3Q6XFxuJyArIGVycm9yU3RyaW5nKGRhdGEuZm9yZWlnbk9iamVjdCkgKyAnLlxcbicgKyAnVGhlIHBhcmVudCB2bm9kZSBpczpcXG4nICsgZXJyb3JTdHJpbmcoZGF0YS5wYXJlbnRWbm9kZSk7XG4gICAgICAgICAgICAgICAgJ1xcbicgKyAnU3VnZ2VzdGVkIGZpeDogY2hhbmdlIHlvdXIgYGgoLi4uLCBbIC4uLiBdKWAgY2FsbHNpdGUuJztcbiAgICAgICAgICAgICAgICBlcnIuZm9yZWlnbk9iamVjdCA9IGRhdGEuZm9yZWlnbk9iamVjdDtcbiAgICAgICAgICAgICAgICBlcnIucGFyZW50Vm5vZGUgPSBkYXRhLnBhcmVudFZub2RlO1xuXG4gICAgICAgICAgICAgICAgcmV0dXJuIGVycjtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZnVuY3Rpb24gZXJyb3JTdHJpbmcob2JqKSB7XG4gICAgICAgICAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIEpTT04uc3RyaW5naWZ5KG9iaiwgbnVsbCwgJyAgICAnKTtcbiAgICAgICAgICAgICAgICB9IGNhdGNoIChlKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBTdHJpbmcob2JqKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH0sIHsgXCIuLi92bm9kZS9pcy10aHVua1wiOiAyNSwgXCIuLi92bm9kZS9pcy12aG9va1wiOiAyNiwgXCIuLi92bm9kZS9pcy12bm9kZVwiOiAyNywgXCIuLi92bm9kZS9pcy12dGV4dFwiOiAyOCwgXCIuLi92bm9kZS9pcy13aWRnZXRcIjogMjksIFwiLi4vdm5vZGUvdm5vZGUuanNcIjogMzEsIFwiLi4vdm5vZGUvdnRleHQuanNcIjogMzMsIFwiLi9ob29rcy9ldi1ob29rLmpzXCI6IDIwLCBcIi4vaG9va3Mvc29mdC1zZXQtaG9vay5qc1wiOiAyMSwgXCIuL3BhcnNlLXRhZy5qc1wiOiAyMywgXCJ4LWlzLWFycmF5XCI6IDEyIH1dLCAyMzogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHtcbiAgICAgICAgICAgICd1c2Ugc3RyaWN0JztcblxuICAgICAgICAgICAgdmFyIHNwbGl0ID0gcmVxdWlyZSgnYnJvd3Nlci1zcGxpdCcpO1xuXG4gICAgICAgICAgICB2YXIgY2xhc3NJZFNwbGl0ID0gLyhbXFwuI10/W2EtekEtWjAtOVxcdTAwN0YtXFx1RkZGRl86LV0rKS87XG4gICAgICAgICAgICB2YXIgbm90Q2xhc3NJZCA9IC9eXFwufCMvO1xuXG4gICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IHBhcnNlVGFnO1xuXG4gICAgICAgICAgICBmdW5jdGlvbiBwYXJzZVRhZyh0YWcsIHByb3BzKSB7XG4gICAgICAgICAgICAgICAgaWYgKCF0YWcpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuICdESVYnO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHZhciBub0lkID0gIXByb3BzLmhhc093blByb3BlcnR5KCdpZCcpO1xuXG4gICAgICAgICAgICAgICAgdmFyIHRhZ1BhcnRzID0gc3BsaXQodGFnLCBjbGFzc0lkU3BsaXQpO1xuICAgICAgICAgICAgICAgIHZhciB0YWdOYW1lID0gbnVsbDtcblxuICAgICAgICAgICAgICAgIGlmIChub3RDbGFzc0lkLnRlc3QodGFnUGFydHNbMV0pKSB7XG4gICAgICAgICAgICAgICAgICAgIHRhZ05hbWUgPSAnRElWJztcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICB2YXIgY2xhc3NlcywgcGFydCwgdHlwZSwgaTtcblxuICAgICAgICAgICAgICAgIGZvciAoaSA9IDA7IGkgPCB0YWdQYXJ0cy5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgICAgICAgICBwYXJ0ID0gdGFnUGFydHNbaV07XG5cbiAgICAgICAgICAgICAgICAgICAgaWYgKCFwYXJ0KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBjb250aW51ZTtcbiAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgIHR5cGUgPSBwYXJ0LmNoYXJBdCgwKTtcblxuICAgICAgICAgICAgICAgICAgICBpZiAoIXRhZ05hbWUpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHRhZ05hbWUgPSBwYXJ0O1xuICAgICAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKHR5cGUgPT09ICcuJykge1xuICAgICAgICAgICAgICAgICAgICAgICAgY2xhc3NlcyA9IGNsYXNzZXMgfHwgW107XG4gICAgICAgICAgICAgICAgICAgICAgICBjbGFzc2VzLnB1c2gocGFydC5zdWJzdHJpbmcoMSwgcGFydC5sZW5ndGgpKTtcbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIGlmICh0eXBlID09PSAnIycgJiYgbm9JZCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgcHJvcHMuaWQgPSBwYXJ0LnN1YnN0cmluZygxLCBwYXJ0Lmxlbmd0aCk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICBpZiAoY2xhc3Nlcykge1xuICAgICAgICAgICAgICAgICAgICBpZiAocHJvcHMuY2xhc3NOYW1lKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBjbGFzc2VzLnB1c2gocHJvcHMuY2xhc3NOYW1lKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgIHByb3BzLmNsYXNzTmFtZSA9IGNsYXNzZXMuam9pbignICcpO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHJldHVybiBwcm9wcy5uYW1lc3BhY2UgPyB0YWdOYW1lIDogdGFnTmFtZS50b1VwcGVyQ2FzZSgpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9LCB7IFwiYnJvd3Nlci1zcGxpdFwiOiA1IH1dLCAyNDogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHtcbiAgICAgICAgICAgIHZhciBpc1ZOb2RlID0gcmVxdWlyZShcIi4vaXMtdm5vZGVcIik7XG4gICAgICAgICAgICB2YXIgaXNWVGV4dCA9IHJlcXVpcmUoXCIuL2lzLXZ0ZXh0XCIpO1xuICAgICAgICAgICAgdmFyIGlzV2lkZ2V0ID0gcmVxdWlyZShcIi4vaXMtd2lkZ2V0XCIpO1xuICAgICAgICAgICAgdmFyIGlzVGh1bmsgPSByZXF1aXJlKFwiLi9pcy10aHVua1wiKTtcblxuICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBoYW5kbGVUaHVuaztcblxuICAgICAgICAgICAgZnVuY3Rpb24gaGFuZGxlVGh1bmsoYSwgYikge1xuICAgICAgICAgICAgICAgIHZhciByZW5kZXJlZEEgPSBhO1xuICAgICAgICAgICAgICAgIHZhciByZW5kZXJlZEIgPSBiO1xuXG4gICAgICAgICAgICAgICAgaWYgKGlzVGh1bmsoYikpIHtcbiAgICAgICAgICAgICAgICAgICAgcmVuZGVyZWRCID0gcmVuZGVyVGh1bmsoYiwgYSk7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgaWYgKGlzVGh1bmsoYSkpIHtcbiAgICAgICAgICAgICAgICAgICAgcmVuZGVyZWRBID0gcmVuZGVyVGh1bmsoYSwgbnVsbCk7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgICAgICAgICAgYTogcmVuZGVyZWRBLFxuICAgICAgICAgICAgICAgICAgICBiOiByZW5kZXJlZEJcbiAgICAgICAgICAgICAgICB9O1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBmdW5jdGlvbiByZW5kZXJUaHVuayh0aHVuaywgcHJldmlvdXMpIHtcbiAgICAgICAgICAgICAgICB2YXIgcmVuZGVyZWRUaHVuayA9IHRodW5rLnZub2RlO1xuXG4gICAgICAgICAgICAgICAgaWYgKCFyZW5kZXJlZFRodW5rKSB7XG4gICAgICAgICAgICAgICAgICAgIHJlbmRlcmVkVGh1bmsgPSB0aHVuay52bm9kZSA9IHRodW5rLnJlbmRlcihwcmV2aW91cyk7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgaWYgKCEoaXNWTm9kZShyZW5kZXJlZFRodW5rKSB8fCBpc1ZUZXh0KHJlbmRlcmVkVGh1bmspIHx8IGlzV2lkZ2V0KHJlbmRlcmVkVGh1bmspKSkge1xuICAgICAgICAgICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoXCJ0aHVuayBkaWQgbm90IHJldHVybiBhIHZhbGlkIG5vZGVcIik7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgcmV0dXJuIHJlbmRlcmVkVGh1bms7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0sIHsgXCIuL2lzLXRodW5rXCI6IDI1LCBcIi4vaXMtdm5vZGVcIjogMjcsIFwiLi9pcy12dGV4dFwiOiAyOCwgXCIuL2lzLXdpZGdldFwiOiAyOSB9XSwgMjU6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IGlzVGh1bms7XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIGlzVGh1bmsodCkge1xuICAgICAgICAgICAgICAgIHJldHVybiB0ICYmIHQudHlwZSA9PT0gXCJUaHVua1wiO1xuICAgICAgICAgICAgfVxuICAgICAgICB9LCB7fV0sIDI2OiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge1xuICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBpc0hvb2s7XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIGlzSG9vayhob29rKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGhvb2sgJiYgKHR5cGVvZiBob29rLmhvb2sgPT09IFwiZnVuY3Rpb25cIiAmJiAhaG9vay5oYXNPd25Qcm9wZXJ0eShcImhvb2tcIikgfHwgdHlwZW9mIGhvb2sudW5ob29rID09PSBcImZ1bmN0aW9uXCIgJiYgIWhvb2suaGFzT3duUHJvcGVydHkoXCJ1bmhvb2tcIikpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9LCB7fV0sIDI3OiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge1xuICAgICAgICAgICAgdmFyIHZlcnNpb24gPSByZXF1aXJlKFwiLi92ZXJzaW9uXCIpO1xuXG4gICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IGlzVmlydHVhbE5vZGU7XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIGlzVmlydHVhbE5vZGUoeCkge1xuICAgICAgICAgICAgICAgIHJldHVybiB4ICYmIHgudHlwZSA9PT0gXCJWaXJ0dWFsTm9kZVwiICYmIHgudmVyc2lvbiA9PT0gdmVyc2lvbjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSwgeyBcIi4vdmVyc2lvblwiOiAzMCB9XSwgMjg6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICB2YXIgdmVyc2lvbiA9IHJlcXVpcmUoXCIuL3ZlcnNpb25cIik7XG5cbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gaXNWaXJ0dWFsVGV4dDtcblxuICAgICAgICAgICAgZnVuY3Rpb24gaXNWaXJ0dWFsVGV4dCh4KSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHggJiYgeC50eXBlID09PSBcIlZpcnR1YWxUZXh0XCIgJiYgeC52ZXJzaW9uID09PSB2ZXJzaW9uO1xuICAgICAgICAgICAgfVxuICAgICAgICB9LCB7IFwiLi92ZXJzaW9uXCI6IDMwIH1dLCAyOTogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHtcbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gaXNXaWRnZXQ7XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIGlzV2lkZ2V0KHcpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gdyAmJiB3LnR5cGUgPT09IFwiV2lkZ2V0XCI7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0sIHt9XSwgMzA6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IFwiMlwiO1xuICAgICAgICB9LCB7fV0sIDMxOiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge1xuICAgICAgICAgICAgdmFyIHZlcnNpb24gPSByZXF1aXJlKFwiLi92ZXJzaW9uXCIpO1xuICAgICAgICAgICAgdmFyIGlzVk5vZGUgPSByZXF1aXJlKFwiLi9pcy12bm9kZVwiKTtcbiAgICAgICAgICAgIHZhciBpc1dpZGdldCA9IHJlcXVpcmUoXCIuL2lzLXdpZGdldFwiKTtcbiAgICAgICAgICAgIHZhciBpc1RodW5rID0gcmVxdWlyZShcIi4vaXMtdGh1bmtcIik7XG4gICAgICAgICAgICB2YXIgaXNWSG9vayA9IHJlcXVpcmUoXCIuL2lzLXZob29rXCIpO1xuXG4gICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IFZpcnR1YWxOb2RlO1xuXG4gICAgICAgICAgICB2YXIgbm9Qcm9wZXJ0aWVzID0ge307XG4gICAgICAgICAgICB2YXIgbm9DaGlsZHJlbiA9IFtdO1xuXG4gICAgICAgICAgICBmdW5jdGlvbiBWaXJ0dWFsTm9kZSh0YWdOYW1lLCBwcm9wZXJ0aWVzLCBjaGlsZHJlbiwga2V5LCBuYW1lc3BhY2UpIHtcbiAgICAgICAgICAgICAgICB0aGlzLnRhZ05hbWUgPSB0YWdOYW1lO1xuICAgICAgICAgICAgICAgIHRoaXMucHJvcGVydGllcyA9IHByb3BlcnRpZXMgfHwgbm9Qcm9wZXJ0aWVzO1xuICAgICAgICAgICAgICAgIHRoaXMuY2hpbGRyZW4gPSBjaGlsZHJlbiB8fCBub0NoaWxkcmVuO1xuICAgICAgICAgICAgICAgIHRoaXMua2V5ID0ga2V5ICE9IG51bGwgPyBTdHJpbmcoa2V5KSA6IHVuZGVmaW5lZDtcbiAgICAgICAgICAgICAgICB0aGlzLm5hbWVzcGFjZSA9IHR5cGVvZiBuYW1lc3BhY2UgPT09IFwic3RyaW5nXCIgPyBuYW1lc3BhY2UgOiBudWxsO1xuXG4gICAgICAgICAgICAgICAgdmFyIGNvdW50ID0gY2hpbGRyZW4gJiYgY2hpbGRyZW4ubGVuZ3RoIHx8IDA7XG4gICAgICAgICAgICAgICAgdmFyIGRlc2NlbmRhbnRzID0gMDtcbiAgICAgICAgICAgICAgICB2YXIgaGFzV2lkZ2V0cyA9IGZhbHNlO1xuICAgICAgICAgICAgICAgIHZhciBoYXNUaHVua3MgPSBmYWxzZTtcbiAgICAgICAgICAgICAgICB2YXIgZGVzY2VuZGFudEhvb2tzID0gZmFsc2U7XG4gICAgICAgICAgICAgICAgdmFyIGhvb2tzO1xuXG4gICAgICAgICAgICAgICAgZm9yICh2YXIgcHJvcE5hbWUgaW4gcHJvcGVydGllcykge1xuICAgICAgICAgICAgICAgICAgICBpZiAocHJvcGVydGllcy5oYXNPd25Qcm9wZXJ0eShwcm9wTmFtZSkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHZhciBwcm9wZXJ0eSA9IHByb3BlcnRpZXNbcHJvcE5hbWVdO1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGlzVkhvb2socHJvcGVydHkpICYmIHByb3BlcnR5LnVuaG9vaykge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmICghaG9va3MpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaG9va3MgPSB7fTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBob29rc1twcm9wTmFtZV0gPSBwcm9wZXJ0eTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgY291bnQ7IGkrKykge1xuICAgICAgICAgICAgICAgICAgICB2YXIgY2hpbGQgPSBjaGlsZHJlbltpXTtcbiAgICAgICAgICAgICAgICAgICAgaWYgKGlzVk5vZGUoY2hpbGQpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBkZXNjZW5kYW50cyArPSBjaGlsZC5jb3VudCB8fCAwO1xuXG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoIWhhc1dpZGdldHMgJiYgY2hpbGQuaGFzV2lkZ2V0cykge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGhhc1dpZGdldHMgPSB0cnVlO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoIWhhc1RodW5rcyAmJiBjaGlsZC5oYXNUaHVua3MpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBoYXNUaHVua3MgPSB0cnVlO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoIWRlc2NlbmRhbnRIb29rcyAmJiAoY2hpbGQuaG9va3MgfHwgY2hpbGQuZGVzY2VuZGFudEhvb2tzKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRlc2NlbmRhbnRIb29rcyA9IHRydWU7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoIWhhc1dpZGdldHMgJiYgaXNXaWRnZXQoY2hpbGQpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAodHlwZW9mIGNoaWxkLmRlc3Ryb3kgPT09IFwiZnVuY3Rpb25cIikge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGhhc1dpZGdldHMgPSB0cnVlO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKCFoYXNUaHVua3MgJiYgaXNUaHVuayhjaGlsZCkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGhhc1RodW5rcyA9IHRydWU7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICB0aGlzLmNvdW50ID0gY291bnQgKyBkZXNjZW5kYW50cztcbiAgICAgICAgICAgICAgICB0aGlzLmhhc1dpZGdldHMgPSBoYXNXaWRnZXRzO1xuICAgICAgICAgICAgICAgIHRoaXMuaGFzVGh1bmtzID0gaGFzVGh1bmtzO1xuICAgICAgICAgICAgICAgIHRoaXMuaG9va3MgPSBob29rcztcbiAgICAgICAgICAgICAgICB0aGlzLmRlc2NlbmRhbnRIb29rcyA9IGRlc2NlbmRhbnRIb29rcztcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgVmlydHVhbE5vZGUucHJvdG90eXBlLnZlcnNpb24gPSB2ZXJzaW9uO1xuICAgICAgICAgICAgVmlydHVhbE5vZGUucHJvdG90eXBlLnR5cGUgPSBcIlZpcnR1YWxOb2RlXCI7XG4gICAgICAgIH0sIHsgXCIuL2lzLXRodW5rXCI6IDI1LCBcIi4vaXMtdmhvb2tcIjogMjYsIFwiLi9pcy12bm9kZVwiOiAyNywgXCIuL2lzLXdpZGdldFwiOiAyOSwgXCIuL3ZlcnNpb25cIjogMzAgfV0sIDMyOiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge1xuICAgICAgICAgICAgdmFyIHZlcnNpb24gPSByZXF1aXJlKFwiLi92ZXJzaW9uXCIpO1xuXG4gICAgICAgICAgICBWaXJ0dWFsUGF0Y2guTk9ORSA9IDA7XG4gICAgICAgICAgICBWaXJ0dWFsUGF0Y2guVlRFWFQgPSAxO1xuICAgICAgICAgICAgVmlydHVhbFBhdGNoLlZOT0RFID0gMjtcbiAgICAgICAgICAgIFZpcnR1YWxQYXRjaC5XSURHRVQgPSAzO1xuICAgICAgICAgICAgVmlydHVhbFBhdGNoLlBST1BTID0gNDtcbiAgICAgICAgICAgIFZpcnR1YWxQYXRjaC5PUkRFUiA9IDU7XG4gICAgICAgICAgICBWaXJ0dWFsUGF0Y2guSU5TRVJUID0gNjtcbiAgICAgICAgICAgIFZpcnR1YWxQYXRjaC5SRU1PVkUgPSA3O1xuICAgICAgICAgICAgVmlydHVhbFBhdGNoLlRIVU5LID0gODtcblxuICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBWaXJ0dWFsUGF0Y2g7XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIFZpcnR1YWxQYXRjaCh0eXBlLCB2Tm9kZSwgcGF0Y2gpIHtcbiAgICAgICAgICAgICAgICB0aGlzLnR5cGUgPSBOdW1iZXIodHlwZSk7XG4gICAgICAgICAgICAgICAgdGhpcy52Tm9kZSA9IHZOb2RlO1xuICAgICAgICAgICAgICAgIHRoaXMucGF0Y2ggPSBwYXRjaDtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgVmlydHVhbFBhdGNoLnByb3RvdHlwZS52ZXJzaW9uID0gdmVyc2lvbjtcbiAgICAgICAgICAgIFZpcnR1YWxQYXRjaC5wcm90b3R5cGUudHlwZSA9IFwiVmlydHVhbFBhdGNoXCI7XG4gICAgICAgIH0sIHsgXCIuL3ZlcnNpb25cIjogMzAgfV0sIDMzOiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge1xuICAgICAgICAgICAgdmFyIHZlcnNpb24gPSByZXF1aXJlKFwiLi92ZXJzaW9uXCIpO1xuXG4gICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IFZpcnR1YWxUZXh0O1xuXG4gICAgICAgICAgICBmdW5jdGlvbiBWaXJ0dWFsVGV4dCh0ZXh0KSB7XG4gICAgICAgICAgICAgICAgdGhpcy50ZXh0ID0gU3RyaW5nKHRleHQpO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBWaXJ0dWFsVGV4dC5wcm90b3R5cGUudmVyc2lvbiA9IHZlcnNpb247XG4gICAgICAgICAgICBWaXJ0dWFsVGV4dC5wcm90b3R5cGUudHlwZSA9IFwiVmlydHVhbFRleHRcIjtcbiAgICAgICAgfSwgeyBcIi4vdmVyc2lvblwiOiAzMCB9XSwgMzQ6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICB2YXIgaXNPYmplY3QgPSByZXF1aXJlKFwiaXMtb2JqZWN0XCIpO1xuICAgICAgICAgICAgdmFyIGlzSG9vayA9IHJlcXVpcmUoXCIuLi92bm9kZS9pcy12aG9va1wiKTtcblxuICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBkaWZmUHJvcHM7XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIGRpZmZQcm9wcyhhLCBiKSB7XG4gICAgICAgICAgICAgICAgdmFyIGRpZmY7XG5cbiAgICAgICAgICAgICAgICBmb3IgKHZhciBhS2V5IGluIGEpIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKCEoYUtleSBpbiBiKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgZGlmZiA9IGRpZmYgfHwge307XG4gICAgICAgICAgICAgICAgICAgICAgICBkaWZmW2FLZXldID0gdW5kZWZpbmVkO1xuICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgdmFyIGFWYWx1ZSA9IGFbYUtleV07XG4gICAgICAgICAgICAgICAgICAgIHZhciBiVmFsdWUgPSBiW2FLZXldO1xuXG4gICAgICAgICAgICAgICAgICAgIGlmIChhVmFsdWUgPT09IGJWYWx1ZSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgY29udGludWU7XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoaXNPYmplY3QoYVZhbHVlKSAmJiBpc09iamVjdChiVmFsdWUpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoZ2V0UHJvdG90eXBlKGJWYWx1ZSkgIT09IGdldFByb3RvdHlwZShhVmFsdWUpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgZGlmZiA9IGRpZmYgfHwge307XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgZGlmZlthS2V5XSA9IGJWYWx1ZTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoaXNIb29rKGJWYWx1ZSkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBkaWZmID0gZGlmZiB8fCB7fTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBkaWZmW2FLZXldID0gYlZhbHVlO1xuICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB2YXIgb2JqZWN0RGlmZiA9IGRpZmZQcm9wcyhhVmFsdWUsIGJWYWx1ZSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKG9iamVjdERpZmYpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZGlmZiA9IGRpZmYgfHwge307XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRpZmZbYUtleV0gPSBvYmplY3REaWZmO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGRpZmYgPSBkaWZmIHx8IHt9O1xuICAgICAgICAgICAgICAgICAgICAgICAgZGlmZlthS2V5XSA9IGJWYWx1ZTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIGZvciAodmFyIGJLZXkgaW4gYikge1xuICAgICAgICAgICAgICAgICAgICBpZiAoIShiS2V5IGluIGEpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBkaWZmID0gZGlmZiB8fCB7fTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGRpZmZbYktleV0gPSBiW2JLZXldO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgcmV0dXJuIGRpZmY7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIGdldFByb3RvdHlwZSh2YWx1ZSkge1xuICAgICAgICAgICAgICAgIGlmIChPYmplY3QuZ2V0UHJvdG90eXBlT2YpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIE9iamVjdC5nZXRQcm90b3R5cGVPZih2YWx1ZSk7XG4gICAgICAgICAgICAgICAgfSBlbHNlIGlmICh2YWx1ZS5fX3Byb3RvX18pIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHZhbHVlLl9fcHJvdG9fXztcbiAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKHZhbHVlLmNvbnN0cnVjdG9yKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiB2YWx1ZS5jb25zdHJ1Y3Rvci5wcm90b3R5cGU7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9LCB7IFwiLi4vdm5vZGUvaXMtdmhvb2tcIjogMjYsIFwiaXMtb2JqZWN0XCI6IDExIH1dLCAzNTogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHtcbiAgICAgICAgICAgIHZhciBpc0FycmF5ID0gcmVxdWlyZShcIngtaXMtYXJyYXlcIik7XG5cbiAgICAgICAgICAgIHZhciBWUGF0Y2ggPSByZXF1aXJlKFwiLi4vdm5vZGUvdnBhdGNoXCIpO1xuICAgICAgICAgICAgdmFyIGlzVk5vZGUgPSByZXF1aXJlKFwiLi4vdm5vZGUvaXMtdm5vZGVcIik7XG4gICAgICAgICAgICB2YXIgaXNWVGV4dCA9IHJlcXVpcmUoXCIuLi92bm9kZS9pcy12dGV4dFwiKTtcbiAgICAgICAgICAgIHZhciBpc1dpZGdldCA9IHJlcXVpcmUoXCIuLi92bm9kZS9pcy13aWRnZXRcIik7XG4gICAgICAgICAgICB2YXIgaXNUaHVuayA9IHJlcXVpcmUoXCIuLi92bm9kZS9pcy10aHVua1wiKTtcbiAgICAgICAgICAgIHZhciBoYW5kbGVUaHVuayA9IHJlcXVpcmUoXCIuLi92bm9kZS9oYW5kbGUtdGh1bmtcIik7XG5cbiAgICAgICAgICAgIHZhciBkaWZmUHJvcHMgPSByZXF1aXJlKFwiLi9kaWZmLXByb3BzXCIpO1xuXG4gICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IGRpZmY7XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIGRpZmYoYSwgYikge1xuICAgICAgICAgICAgICAgIHZhciBwYXRjaCA9IHsgYTogYSB9O1xuICAgICAgICAgICAgICAgIHdhbGsoYSwgYiwgcGF0Y2gsIDApO1xuICAgICAgICAgICAgICAgIHJldHVybiBwYXRjaDtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZnVuY3Rpb24gd2FsayhhLCBiLCBwYXRjaCwgaW5kZXgpIHtcbiAgICAgICAgICAgICAgICBpZiAoYSA9PT0gYikge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgdmFyIGFwcGx5ID0gcGF0Y2hbaW5kZXhdO1xuICAgICAgICAgICAgICAgIHZhciBhcHBseUNsZWFyID0gZmFsc2U7XG5cbiAgICAgICAgICAgICAgICBpZiAoaXNUaHVuayhhKSB8fCBpc1RodW5rKGIpKSB7XG4gICAgICAgICAgICAgICAgICAgIHRodW5rcyhhLCBiLCBwYXRjaCwgaW5kZXgpO1xuICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoYiA9PSBudWxsKSB7XG5cbiAgICAgICAgICAgICAgICAgICAgLy8gSWYgYSBpcyBhIHdpZGdldCB3ZSB3aWxsIGFkZCBhIHJlbW92ZSBwYXRjaCBmb3IgaXRcbiAgICAgICAgICAgICAgICAgICAgLy8gT3RoZXJ3aXNlIGFueSBjaGlsZCB3aWRnZXRzL2hvb2tzIG11c3QgYmUgZGVzdHJveWVkLlxuICAgICAgICAgICAgICAgICAgICAvLyBUaGlzIHByZXZlbnRzIGFkZGluZyB0d28gcmVtb3ZlIHBhdGNoZXMgZm9yIGEgd2lkZ2V0LlxuICAgICAgICAgICAgICAgICAgICBpZiAoIWlzV2lkZ2V0KGEpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBjbGVhclN0YXRlKGEsIHBhdGNoLCBpbmRleCk7XG4gICAgICAgICAgICAgICAgICAgICAgICBhcHBseSA9IHBhdGNoW2luZGV4XTtcbiAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgIGFwcGx5ID0gYXBwZW5kUGF0Y2goYXBwbHksIG5ldyBWUGF0Y2goVlBhdGNoLlJFTU9WRSwgYSwgYikpO1xuICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoaXNWTm9kZShiKSkge1xuICAgICAgICAgICAgICAgICAgICBpZiAoaXNWTm9kZShhKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGEudGFnTmFtZSA9PT0gYi50YWdOYW1lICYmIGEubmFtZXNwYWNlID09PSBiLm5hbWVzcGFjZSAmJiBhLmtleSA9PT0gYi5rZXkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB2YXIgcHJvcHNQYXRjaCA9IGRpZmZQcm9wcyhhLnByb3BlcnRpZXMsIGIucHJvcGVydGllcyk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHByb3BzUGF0Y2gpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYXBwbHkgPSBhcHBlbmRQYXRjaChhcHBseSwgbmV3IFZQYXRjaChWUGF0Y2guUFJPUFMsIGEsIHByb3BzUGF0Y2gpKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgYXBwbHkgPSBkaWZmQ2hpbGRyZW4oYSwgYiwgcGF0Y2gsIGFwcGx5LCBpbmRleCk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGFwcGx5ID0gYXBwZW5kUGF0Y2goYXBwbHksIG5ldyBWUGF0Y2goVlBhdGNoLlZOT0RFLCBhLCBiKSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgYXBwbHlDbGVhciA9IHRydWU7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBhcHBseSA9IGFwcGVuZFBhdGNoKGFwcGx5LCBuZXcgVlBhdGNoKFZQYXRjaC5WTk9ERSwgYSwgYikpO1xuICAgICAgICAgICAgICAgICAgICAgICAgYXBwbHlDbGVhciA9IHRydWU7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKGlzVlRleHQoYikpIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKCFpc1ZUZXh0KGEpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBhcHBseSA9IGFwcGVuZFBhdGNoKGFwcGx5LCBuZXcgVlBhdGNoKFZQYXRjaC5WVEVYVCwgYSwgYikpO1xuICAgICAgICAgICAgICAgICAgICAgICAgYXBwbHlDbGVhciA9IHRydWU7XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoYS50ZXh0ICE9PSBiLnRleHQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGFwcGx5ID0gYXBwZW5kUGF0Y2goYXBwbHksIG5ldyBWUGF0Y2goVlBhdGNoLlZURVhULCBhLCBiKSk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKGlzV2lkZ2V0KGIpKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmICghaXNXaWRnZXQoYSkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGFwcGx5Q2xlYXIgPSB0cnVlO1xuICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgYXBwbHkgPSBhcHBlbmRQYXRjaChhcHBseSwgbmV3IFZQYXRjaChWUGF0Y2guV0lER0VULCBhLCBiKSk7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgaWYgKGFwcGx5KSB7XG4gICAgICAgICAgICAgICAgICAgIHBhdGNoW2luZGV4XSA9IGFwcGx5O1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIGlmIChhcHBseUNsZWFyKSB7XG4gICAgICAgICAgICAgICAgICAgIGNsZWFyU3RhdGUoYSwgcGF0Y2gsIGluZGV4KTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIGRpZmZDaGlsZHJlbihhLCBiLCBwYXRjaCwgYXBwbHksIGluZGV4KSB7XG4gICAgICAgICAgICAgICAgdmFyIGFDaGlsZHJlbiA9IGEuY2hpbGRyZW47XG4gICAgICAgICAgICAgICAgdmFyIG9yZGVyZWRTZXQgPSByZW9yZGVyKGFDaGlsZHJlbiwgYi5jaGlsZHJlbik7XG4gICAgICAgICAgICAgICAgdmFyIGJDaGlsZHJlbiA9IG9yZGVyZWRTZXQuY2hpbGRyZW47XG5cbiAgICAgICAgICAgICAgICB2YXIgYUxlbiA9IGFDaGlsZHJlbi5sZW5ndGg7XG4gICAgICAgICAgICAgICAgdmFyIGJMZW4gPSBiQ2hpbGRyZW4ubGVuZ3RoO1xuICAgICAgICAgICAgICAgIHZhciBsZW4gPSBhTGVuID4gYkxlbiA/IGFMZW4gOiBiTGVuO1xuXG4gICAgICAgICAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCBsZW47IGkrKykge1xuICAgICAgICAgICAgICAgICAgICB2YXIgbGVmdE5vZGUgPSBhQ2hpbGRyZW5baV07XG4gICAgICAgICAgICAgICAgICAgIHZhciByaWdodE5vZGUgPSBiQ2hpbGRyZW5baV07XG4gICAgICAgICAgICAgICAgICAgIGluZGV4ICs9IDE7XG5cbiAgICAgICAgICAgICAgICAgICAgaWYgKCFsZWZ0Tm9kZSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHJpZ2h0Tm9kZSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIEV4Y2VzcyBub2RlcyBpbiBiIG5lZWQgdG8gYmUgYWRkZWRcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBhcHBseSA9IGFwcGVuZFBhdGNoKGFwcGx5LCBuZXcgVlBhdGNoKFZQYXRjaC5JTlNFUlQsIG51bGwsIHJpZ2h0Tm9kZSkpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgd2FsayhsZWZ0Tm9kZSwgcmlnaHROb2RlLCBwYXRjaCwgaW5kZXgpO1xuICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgaWYgKGlzVk5vZGUobGVmdE5vZGUpICYmIGxlZnROb2RlLmNvdW50KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBpbmRleCArPSBsZWZ0Tm9kZS5jb3VudDtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIGlmIChvcmRlcmVkU2V0Lm1vdmVzKSB7XG4gICAgICAgICAgICAgICAgICAgIC8vIFJlb3JkZXIgbm9kZXMgbGFzdFxuICAgICAgICAgICAgICAgICAgICBhcHBseSA9IGFwcGVuZFBhdGNoKGFwcGx5LCBuZXcgVlBhdGNoKFZQYXRjaC5PUkRFUiwgYSwgb3JkZXJlZFNldC5tb3ZlcykpO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHJldHVybiBhcHBseTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZnVuY3Rpb24gY2xlYXJTdGF0ZSh2Tm9kZSwgcGF0Y2gsIGluZGV4KSB7XG4gICAgICAgICAgICAgICAgLy8gVE9ETzogTWFrZSB0aGlzIGEgc2luZ2xlIHdhbGssIG5vdCB0d29cbiAgICAgICAgICAgICAgICB1bmhvb2sodk5vZGUsIHBhdGNoLCBpbmRleCk7XG4gICAgICAgICAgICAgICAgZGVzdHJveVdpZGdldHModk5vZGUsIHBhdGNoLCBpbmRleCk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIC8vIFBhdGNoIHJlY29yZHMgZm9yIGFsbCBkZXN0cm95ZWQgd2lkZ2V0cyBtdXN0IGJlIGFkZGVkIGJlY2F1c2Ugd2UgbmVlZFxuICAgICAgICAgICAgLy8gYSBET00gbm9kZSByZWZlcmVuY2UgZm9yIHRoZSBkZXN0cm95IGZ1bmN0aW9uXG4gICAgICAgICAgICBmdW5jdGlvbiBkZXN0cm95V2lkZ2V0cyh2Tm9kZSwgcGF0Y2gsIGluZGV4KSB7XG4gICAgICAgICAgICAgICAgaWYgKGlzV2lkZ2V0KHZOb2RlKSkge1xuICAgICAgICAgICAgICAgICAgICBpZiAodHlwZW9mIHZOb2RlLmRlc3Ryb3kgPT09IFwiZnVuY3Rpb25cIikge1xuICAgICAgICAgICAgICAgICAgICAgICAgcGF0Y2hbaW5kZXhdID0gYXBwZW5kUGF0Y2gocGF0Y2hbaW5kZXhdLCBuZXcgVlBhdGNoKFZQYXRjaC5SRU1PVkUsIHZOb2RlLCBudWxsKSk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKGlzVk5vZGUodk5vZGUpICYmICh2Tm9kZS5oYXNXaWRnZXRzIHx8IHZOb2RlLmhhc1RodW5rcykpIHtcbiAgICAgICAgICAgICAgICAgICAgdmFyIGNoaWxkcmVuID0gdk5vZGUuY2hpbGRyZW47XG4gICAgICAgICAgICAgICAgICAgIHZhciBsZW4gPSBjaGlsZHJlbi5sZW5ndGg7XG4gICAgICAgICAgICAgICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgbGVuOyBpKyspIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHZhciBjaGlsZCA9IGNoaWxkcmVuW2ldO1xuICAgICAgICAgICAgICAgICAgICAgICAgaW5kZXggKz0gMTtcblxuICAgICAgICAgICAgICAgICAgICAgICAgZGVzdHJveVdpZGdldHMoY2hpbGQsIHBhdGNoLCBpbmRleCk7XG5cbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChpc1ZOb2RlKGNoaWxkKSAmJiBjaGlsZC5jb3VudCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGluZGV4ICs9IGNoaWxkLmNvdW50O1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfSBlbHNlIGlmIChpc1RodW5rKHZOb2RlKSkge1xuICAgICAgICAgICAgICAgICAgICB0aHVua3Modk5vZGUsIG51bGwsIHBhdGNoLCBpbmRleCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAvLyBDcmVhdGUgYSBzdWItcGF0Y2ggZm9yIHRodW5rc1xuICAgICAgICAgICAgZnVuY3Rpb24gdGh1bmtzKGEsIGIsIHBhdGNoLCBpbmRleCkge1xuICAgICAgICAgICAgICAgIHZhciBub2RlcyA9IGhhbmRsZVRodW5rKGEsIGIpO1xuICAgICAgICAgICAgICAgIHZhciB0aHVua1BhdGNoID0gZGlmZihub2Rlcy5hLCBub2Rlcy5iKTtcbiAgICAgICAgICAgICAgICBpZiAoaGFzUGF0Y2hlcyh0aHVua1BhdGNoKSkge1xuICAgICAgICAgICAgICAgICAgICBwYXRjaFtpbmRleF0gPSBuZXcgVlBhdGNoKFZQYXRjaC5USFVOSywgbnVsbCwgdGh1bmtQYXRjaCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBmdW5jdGlvbiBoYXNQYXRjaGVzKHBhdGNoKSB7XG4gICAgICAgICAgICAgICAgZm9yICh2YXIgaW5kZXggaW4gcGF0Y2gpIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKGluZGV4ICE9PSBcImFcIikge1xuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIC8vIEV4ZWN1dGUgaG9va3Mgd2hlbiB0d28gbm9kZXMgYXJlIGlkZW50aWNhbFxuICAgICAgICAgICAgZnVuY3Rpb24gdW5ob29rKHZOb2RlLCBwYXRjaCwgaW5kZXgpIHtcbiAgICAgICAgICAgICAgICBpZiAoaXNWTm9kZSh2Tm9kZSkpIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKHZOb2RlLmhvb2tzKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBwYXRjaFtpbmRleF0gPSBhcHBlbmRQYXRjaChwYXRjaFtpbmRleF0sIG5ldyBWUGF0Y2goVlBhdGNoLlBST1BTLCB2Tm9kZSwgdW5kZWZpbmVkS2V5cyh2Tm9kZS5ob29rcykpKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgIGlmICh2Tm9kZS5kZXNjZW5kYW50SG9va3MgfHwgdk5vZGUuaGFzVGh1bmtzKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICB2YXIgY2hpbGRyZW4gPSB2Tm9kZS5jaGlsZHJlbjtcbiAgICAgICAgICAgICAgICAgICAgICAgIHZhciBsZW4gPSBjaGlsZHJlbi5sZW5ndGg7XG4gICAgICAgICAgICAgICAgICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IGxlbjsgaSsrKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdmFyIGNoaWxkID0gY2hpbGRyZW5baV07XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaW5kZXggKz0gMTtcblxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHVuaG9vayhjaGlsZCwgcGF0Y2gsIGluZGV4KTtcblxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChpc1ZOb2RlKGNoaWxkKSAmJiBjaGlsZC5jb3VudCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpbmRleCArPSBjaGlsZC5jb3VudDtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKGlzVGh1bmsodk5vZGUpKSB7XG4gICAgICAgICAgICAgICAgICAgIHRodW5rcyh2Tm9kZSwgbnVsbCwgcGF0Y2gsIGluZGV4KTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIHVuZGVmaW5lZEtleXMob2JqKSB7XG4gICAgICAgICAgICAgICAgdmFyIHJlc3VsdCA9IHt9O1xuXG4gICAgICAgICAgICAgICAgZm9yICh2YXIga2V5IGluIG9iaikge1xuICAgICAgICAgICAgICAgICAgICByZXN1bHRba2V5XSA9IHVuZGVmaW5lZDtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICByZXR1cm4gcmVzdWx0O1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAvLyBMaXN0IGRpZmYsIG5haXZlIGxlZnQgdG8gcmlnaHQgcmVvcmRlcmluZ1xuICAgICAgICAgICAgZnVuY3Rpb24gcmVvcmRlcihhQ2hpbGRyZW4sIGJDaGlsZHJlbikge1xuICAgICAgICAgICAgICAgIC8vIE8oTSkgdGltZSwgTyhNKSBtZW1vcnlcbiAgICAgICAgICAgICAgICB2YXIgYkNoaWxkSW5kZXggPSBrZXlJbmRleChiQ2hpbGRyZW4pO1xuICAgICAgICAgICAgICAgIHZhciBiS2V5cyA9IGJDaGlsZEluZGV4LmtleXM7XG4gICAgICAgICAgICAgICAgdmFyIGJGcmVlID0gYkNoaWxkSW5kZXguZnJlZTtcblxuICAgICAgICAgICAgICAgIGlmIChiRnJlZS5sZW5ndGggPT09IGJDaGlsZHJlbi5sZW5ndGgpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGNoaWxkcmVuOiBiQ2hpbGRyZW4sXG4gICAgICAgICAgICAgICAgICAgICAgICBtb3ZlczogbnVsbFxuICAgICAgICAgICAgICAgICAgICB9O1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIC8vIE8oTikgdGltZSwgTyhOKSBtZW1vcnlcbiAgICAgICAgICAgICAgICB2YXIgYUNoaWxkSW5kZXggPSBrZXlJbmRleChhQ2hpbGRyZW4pO1xuICAgICAgICAgICAgICAgIHZhciBhS2V5cyA9IGFDaGlsZEluZGV4LmtleXM7XG4gICAgICAgICAgICAgICAgdmFyIGFGcmVlID0gYUNoaWxkSW5kZXguZnJlZTtcblxuICAgICAgICAgICAgICAgIGlmIChhRnJlZS5sZW5ndGggPT09IGFDaGlsZHJlbi5sZW5ndGgpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGNoaWxkcmVuOiBiQ2hpbGRyZW4sXG4gICAgICAgICAgICAgICAgICAgICAgICBtb3ZlczogbnVsbFxuICAgICAgICAgICAgICAgICAgICB9O1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIC8vIE8oTUFYKE4sIE0pKSBtZW1vcnlcbiAgICAgICAgICAgICAgICB2YXIgbmV3Q2hpbGRyZW4gPSBbXTtcblxuICAgICAgICAgICAgICAgIHZhciBmcmVlSW5kZXggPSAwO1xuICAgICAgICAgICAgICAgIHZhciBmcmVlQ291bnQgPSBiRnJlZS5sZW5ndGg7XG4gICAgICAgICAgICAgICAgdmFyIGRlbGV0ZWRJdGVtcyA9IDA7XG5cbiAgICAgICAgICAgICAgICAvLyBJdGVyYXRlIHRocm91Z2ggYSBhbmQgbWF0Y2ggYSBub2RlIGluIGJcbiAgICAgICAgICAgICAgICAvLyBPKE4pIHRpbWUsXG4gICAgICAgICAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCBhQ2hpbGRyZW4ubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgICAgICAgICAgdmFyIGFJdGVtID0gYUNoaWxkcmVuW2ldO1xuICAgICAgICAgICAgICAgICAgICB2YXIgaXRlbUluZGV4O1xuXG4gICAgICAgICAgICAgICAgICAgIGlmIChhSXRlbS5rZXkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChiS2V5cy5oYXNPd25Qcm9wZXJ0eShhSXRlbS5rZXkpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gTWF0Y2ggdXAgdGhlIG9sZCBrZXlzXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaXRlbUluZGV4ID0gYktleXNbYUl0ZW0ua2V5XTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBuZXdDaGlsZHJlbi5wdXNoKGJDaGlsZHJlbltpdGVtSW5kZXhdKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gUmVtb3ZlIG9sZCBrZXllZCBpdGVtc1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGl0ZW1JbmRleCA9IGkgLSBkZWxldGVkSXRlbXMrKztcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBuZXdDaGlsZHJlbi5wdXNoKG51bGwpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgLy8gTWF0Y2ggdGhlIGl0ZW0gaW4gYSB3aXRoIHRoZSBuZXh0IGZyZWUgaXRlbSBpbiBiXG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoZnJlZUluZGV4IDwgZnJlZUNvdW50KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaXRlbUluZGV4ID0gYkZyZWVbZnJlZUluZGV4KytdO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIG5ld0NoaWxkcmVuLnB1c2goYkNoaWxkcmVuW2l0ZW1JbmRleF0pO1xuICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBUaGVyZSBhcmUgbm8gZnJlZSBpdGVtcyBpbiBiIHRvIG1hdGNoIHdpdGhcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyB0aGUgZnJlZSBpdGVtcyBpbiBhLCBzbyB0aGUgZXh0cmEgZnJlZSBub2Rlc1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIGFyZSBkZWxldGVkLlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGl0ZW1JbmRleCA9IGkgLSBkZWxldGVkSXRlbXMrKztcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBuZXdDaGlsZHJlbi5wdXNoKG51bGwpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgdmFyIGxhc3RGcmVlSW5kZXggPSBmcmVlSW5kZXggPj0gYkZyZWUubGVuZ3RoID8gYkNoaWxkcmVuLmxlbmd0aCA6IGJGcmVlW2ZyZWVJbmRleF07XG5cbiAgICAgICAgICAgICAgICAvLyBJdGVyYXRlIHRocm91Z2ggYiBhbmQgYXBwZW5kIGFueSBuZXcga2V5c1xuICAgICAgICAgICAgICAgIC8vIE8oTSkgdGltZVxuICAgICAgICAgICAgICAgIGZvciAodmFyIGogPSAwOyBqIDwgYkNoaWxkcmVuLmxlbmd0aDsgaisrKSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciBuZXdJdGVtID0gYkNoaWxkcmVuW2pdO1xuXG4gICAgICAgICAgICAgICAgICAgIGlmIChuZXdJdGVtLmtleSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKCFhS2V5cy5oYXNPd25Qcm9wZXJ0eShuZXdJdGVtLmtleSkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBBZGQgYW55IG5ldyBrZXllZCBpdGVtc1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIFdlIGFyZSBhZGRpbmcgbmV3IGl0ZW1zIHRvIHRoZSBlbmQgYW5kIHRoZW4gc29ydGluZyB0aGVtXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gaW4gcGxhY2UuIEluIGZ1dHVyZSB3ZSBzaG91bGQgaW5zZXJ0IG5ldyBpdGVtcyBpbiBwbGFjZS5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBuZXdDaGlsZHJlbi5wdXNoKG5ld0l0ZW0pO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKGogPj0gbGFzdEZyZWVJbmRleCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgLy8gQWRkIGFueSBsZWZ0b3ZlciBub24ta2V5ZWQgaXRlbXNcbiAgICAgICAgICAgICAgICAgICAgICAgIG5ld0NoaWxkcmVuLnB1c2gobmV3SXRlbSk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICB2YXIgc2ltdWxhdGUgPSBuZXdDaGlsZHJlbi5zbGljZSgpO1xuICAgICAgICAgICAgICAgIHZhciBzaW11bGF0ZUluZGV4ID0gMDtcbiAgICAgICAgICAgICAgICB2YXIgcmVtb3ZlcyA9IFtdO1xuICAgICAgICAgICAgICAgIHZhciBpbnNlcnRzID0gW107XG4gICAgICAgICAgICAgICAgdmFyIHNpbXVsYXRlSXRlbTtcblxuICAgICAgICAgICAgICAgIGZvciAodmFyIGsgPSAwOyBrIDwgYkNoaWxkcmVuLmxlbmd0aDspIHtcbiAgICAgICAgICAgICAgICAgICAgdmFyIHdhbnRlZEl0ZW0gPSBiQ2hpbGRyZW5ba107XG4gICAgICAgICAgICAgICAgICAgIHNpbXVsYXRlSXRlbSA9IHNpbXVsYXRlW3NpbXVsYXRlSW5kZXhdO1xuXG4gICAgICAgICAgICAgICAgICAgIC8vIHJlbW92ZSBpdGVtc1xuICAgICAgICAgICAgICAgICAgICB3aGlsZSAoc2ltdWxhdGVJdGVtID09PSBudWxsICYmIHNpbXVsYXRlLmxlbmd0aCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgcmVtb3Zlcy5wdXNoKHJlbW92ZShzaW11bGF0ZSwgc2ltdWxhdGVJbmRleCwgbnVsbCkpO1xuICAgICAgICAgICAgICAgICAgICAgICAgc2ltdWxhdGVJdGVtID0gc2ltdWxhdGVbc2ltdWxhdGVJbmRleF07XG4gICAgICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgICAgICBpZiAoIXNpbXVsYXRlSXRlbSB8fCBzaW11bGF0ZUl0ZW0ua2V5ICE9PSB3YW50ZWRJdGVtLmtleSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgLy8gaWYgd2UgbmVlZCBhIGtleSBpbiB0aGlzIHBvc2l0aW9uLi4uXG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAod2FudGVkSXRlbS5rZXkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoc2ltdWxhdGVJdGVtICYmIHNpbXVsYXRlSXRlbS5rZXkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gaWYgYW4gaW5zZXJ0IGRvZXNuJ3QgcHV0IHRoaXMga2V5IGluIHBsYWNlLCBpdCBuZWVkcyB0byBtb3ZlXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChiS2V5c1tzaW11bGF0ZUl0ZW0ua2V5XSAhPT0gayArIDEpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlbW92ZXMucHVzaChyZW1vdmUoc2ltdWxhdGUsIHNpbXVsYXRlSW5kZXgsIHNpbXVsYXRlSXRlbS5rZXkpKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNpbXVsYXRlSXRlbSA9IHNpbXVsYXRlW3NpbXVsYXRlSW5kZXhdO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gaWYgdGhlIHJlbW92ZSBkaWRuJ3QgcHV0IHRoZSB3YW50ZWQgaXRlbSBpbiBwbGFjZSwgd2UgbmVlZCB0byBpbnNlcnQgaXRcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmICghc2ltdWxhdGVJdGVtIHx8IHNpbXVsYXRlSXRlbS5rZXkgIT09IHdhbnRlZEl0ZW0ua2V5KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaW5zZXJ0cy5wdXNoKHsga2V5OiB3YW50ZWRJdGVtLmtleSwgdG86IGsgfSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBpdGVtcyBhcmUgbWF0Y2hpbmcsIHNvIHNraXAgYWhlYWRcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzaW11bGF0ZUluZGV4Kys7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaW5zZXJ0cy5wdXNoKHsga2V5OiB3YW50ZWRJdGVtLmtleSwgdG86IGsgfSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpbnNlcnRzLnB1c2goeyBrZXk6IHdhbnRlZEl0ZW0ua2V5LCB0bzogayB9KTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaysrO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgLy8gYSBrZXkgaW4gc2ltdWxhdGUgaGFzIG5vIG1hdGNoaW5nIHdhbnRlZCBrZXksIHJlbW92ZSBpdFxuICAgICAgICAgICAgICAgICAgICAgICAgZWxzZSBpZiAoc2ltdWxhdGVJdGVtICYmIHNpbXVsYXRlSXRlbS5rZXkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmVtb3Zlcy5wdXNoKHJlbW92ZShzaW11bGF0ZSwgc2ltdWxhdGVJbmRleCwgc2ltdWxhdGVJdGVtLmtleSkpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHNpbXVsYXRlSW5kZXgrKztcbiAgICAgICAgICAgICAgICAgICAgICAgIGsrKztcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIC8vIHJlbW92ZSBhbGwgdGhlIHJlbWFpbmluZyBub2RlcyBmcm9tIHNpbXVsYXRlXG4gICAgICAgICAgICAgICAgd2hpbGUgKHNpbXVsYXRlSW5kZXggPCBzaW11bGF0ZS5sZW5ndGgpIHtcbiAgICAgICAgICAgICAgICAgICAgc2ltdWxhdGVJdGVtID0gc2ltdWxhdGVbc2ltdWxhdGVJbmRleF07XG4gICAgICAgICAgICAgICAgICAgIHJlbW92ZXMucHVzaChyZW1vdmUoc2ltdWxhdGUsIHNpbXVsYXRlSW5kZXgsIHNpbXVsYXRlSXRlbSAmJiBzaW11bGF0ZUl0ZW0ua2V5KSk7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgLy8gSWYgdGhlIG9ubHkgbW92ZXMgd2UgaGF2ZSBhcmUgZGVsZXRlcyB0aGVuIHdlIGNhbiBqdXN0XG4gICAgICAgICAgICAgICAgLy8gbGV0IHRoZSBkZWxldGUgcGF0Y2ggcmVtb3ZlIHRoZXNlIGl0ZW1zLlxuICAgICAgICAgICAgICAgIGlmIChyZW1vdmVzLmxlbmd0aCA9PT0gZGVsZXRlZEl0ZW1zICYmICFpbnNlcnRzLmxlbmd0aCkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgICAgICAgICAgICAgY2hpbGRyZW46IG5ld0NoaWxkcmVuLFxuICAgICAgICAgICAgICAgICAgICAgICAgbW92ZXM6IG51bGxcbiAgICAgICAgICAgICAgICAgICAgfTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgICAgICAgICBjaGlsZHJlbjogbmV3Q2hpbGRyZW4sXG4gICAgICAgICAgICAgICAgICAgIG1vdmVzOiB7XG4gICAgICAgICAgICAgICAgICAgICAgICByZW1vdmVzOiByZW1vdmVzLFxuICAgICAgICAgICAgICAgICAgICAgICAgaW5zZXJ0czogaW5zZXJ0c1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZnVuY3Rpb24gcmVtb3ZlKGFyciwgaW5kZXgsIGtleSkge1xuICAgICAgICAgICAgICAgIGFyci5zcGxpY2UoaW5kZXgsIDEpO1xuXG4gICAgICAgICAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgICAgICAgICAgZnJvbTogaW5kZXgsXG4gICAgICAgICAgICAgICAgICAgIGtleToga2V5XG4gICAgICAgICAgICAgICAgfTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZnVuY3Rpb24ga2V5SW5kZXgoY2hpbGRyZW4pIHtcbiAgICAgICAgICAgICAgICB2YXIga2V5cyA9IHt9O1xuICAgICAgICAgICAgICAgIHZhciBmcmVlID0gW107XG4gICAgICAgICAgICAgICAgdmFyIGxlbmd0aCA9IGNoaWxkcmVuLmxlbmd0aDtcblxuICAgICAgICAgICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgbGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgICAgICAgICAgdmFyIGNoaWxkID0gY2hpbGRyZW5baV07XG5cbiAgICAgICAgICAgICAgICAgICAgaWYgKGNoaWxkLmtleSkge1xuICAgICAgICAgICAgICAgICAgICAgICAga2V5c1tjaGlsZC5rZXldID0gaTtcbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGZyZWUucHVzaChpKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHJldHVybiB7XG4gICAgICAgICAgICAgICAgICAgIGtleXM6IGtleXMsIC8vIEEgaGFzaCBvZiBrZXkgbmFtZSB0byBpbmRleFxuICAgICAgICAgICAgICAgICAgICBmcmVlOiBmcmVlIC8vIEFuIGFycmF5IG9mIHVua2V5ZWQgaXRlbSBpbmRpY2VzXG4gICAgICAgICAgICAgICAgfTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZnVuY3Rpb24gYXBwZW5kUGF0Y2goYXBwbHksIHBhdGNoKSB7XG4gICAgICAgICAgICAgICAgaWYgKGFwcGx5KSB7XG4gICAgICAgICAgICAgICAgICAgIGlmIChpc0FycmF5KGFwcGx5KSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgYXBwbHkucHVzaChwYXRjaCk7XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBhcHBseSA9IFthcHBseSwgcGF0Y2hdO1xuICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGFwcGx5O1xuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBwYXRjaDtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH0sIHsgXCIuLi92bm9kZS9oYW5kbGUtdGh1bmtcIjogMjQsIFwiLi4vdm5vZGUvaXMtdGh1bmtcIjogMjUsIFwiLi4vdm5vZGUvaXMtdm5vZGVcIjogMjcsIFwiLi4vdm5vZGUvaXMtdnRleHRcIjogMjgsIFwiLi4vdm5vZGUvaXMtd2lkZ2V0XCI6IDI5LCBcIi4uL3Zub2RlL3ZwYXRjaFwiOiAzMiwgXCIuL2RpZmYtcHJvcHNcIjogMzQsIFwieC1pcy1hcnJheVwiOiAxMiB9XSB9LCB7fSwgWzRdKSg0KTtcbn0pO1xuXG5leHBvcnQgZGVmYXVsdCBWaXJ0dWFsRE9NO1xuLy8jIHNvdXJjZU1hcHBpbmdVUkw9ZGF0YTphcHBsaWNhdGlvbi9qc29uO2Jhc2U2NCxleUoyWlhKemFXOXVJam96TENKemIzVnlZMlZ6SWpwYklteHBZaTkyYVhKMGRXRnNMV1J2YlM1cWN5SmRMQ0p1WVcxbGN5STZXMTBzSW0xaGNIQnBibWR6SWpvaVFVRkJRU3hKUVVGSkxHRkJRV0VzVlVGQlV5eERRVUZVTEVWQlFWazdRVUZETTBJc1YwRkJUeXhIUVVGUUxFTkJSREpDTzBOQlFWb3NRMEZGWml4WlFVRlhPMEZCUTB3c1VVRkJTU3hOUVVGS0xFVkJRVmtzVFVGQldpeEZRVUZ2UWl4UFFVRndRaXhEUVVSTE8wRkJSVXdzVjBGQlR5eFRRVUZWTEVOQlFWUXNRMEZCVnl4RFFVRllMRVZCUVdNc1EwRkJaQ3hGUVVGcFFpeERRVUZxUWl4RlFVRnZRanRCUVVOd1FpeHBRa0ZCVXl4RFFVRlVMRU5CUVZjc1EwRkJXQ3hGUVVGakxFTkJRV1FzUlVGQmFVSTdRVUZEWWl4blFrRkJTU3hEUVVGRExFVkJRVVVzUTBGQlJpeERRVUZFTEVWQlFVODdRVUZEVUN4dlFrRkJTU3hEUVVGRExFVkJRVVVzUTBGQlJpeERRVUZFTEVWQlFVODdRVUZEVUN4M1FrRkJTU3hKUVVGSkxFOUJRVThzVDBGQlVDeEpRVUZyUWl4VlFVRnNRaXhKUVVGblF5eFBRVUZvUXl4RFFVUkVPMEZCUlZBc2QwSkJRVWtzUTBGQlF5eERRVUZFTEVsQlFVMHNRMEZCVGl4RlFVRlRMRTlCUVU4c1JVRkJSU3hEUVVGR0xFVkJRVXNzUTBGQlF5eERRVUZFTEVOQlFWb3NRMEZCWWp0QlFVTkJMSGRDUVVGSkxFTkJRVW9zUlVGQlR5eFBRVUZQTEVWQlFVVXNRMEZCUml4RlFVRkxMRU5CUVVNc1EwRkJSQ3hEUVVGYUxFTkJRVkE3UVVGRFFTeDNRa0ZCU1N4SlFVRkpMRWxCUVVrc1MwRkJTaXhEUVVGVkxIbENRVUY1UWl4RFFVRjZRaXhIUVVFMlFpeEhRVUUzUWl4RFFVRmtMRU5CU2tjN1FVRkxVQ3d3UWtGQlRTeEZRVUZGTEVsQlFVWXNSMEZCVXl4clFrRkJWQ3hGUVVFMlFpeERRVUUzUWl4RFFVeERPMmxDUVVGWU8wRkJUMEVzYjBKQlFVa3NTVUZCU1N4RlFVRkZMRU5CUVVZc1NVRkJUenRCUVVOWUxEWkNRVUZUTEVWQlFWUTdhVUpCUkVrc1EwRlNSRHRCUVZkUUxHdENRVUZGTEVOQlFVWXNSVUZCU3l4RFFVRk1MRVZCUVZFc1NVRkJVaXhEUVVGaExFVkJRVVVzVDBGQlJpeEZRVUZYTEZWQlFWTXNRMEZCVkN4RlFVRlpPMEZCUTJoRExIZENRVUZKTEVsQlFVa3NSVUZCUlN4RFFVRkdMRVZCUVVzc1EwRkJUQ3hGUVVGUkxFTkJRVklzUTBGQlNpeERRVVEwUWp0QlFVVm9ReXd5UWtGQlR5eEZRVUZGTEVsQlFVa3NRMEZCU2l4SFFVRlJMRU5CUVZJc1EwRkJWQ3hEUVVablF6dHBRa0ZCV2l4RlFVZHlRaXhEUVVoSUxFVkJSMDBzUlVGQlJTeFBRVUZHTEVWQlFWY3NRMEZJYWtJc1JVRkhiMElzUTBGSWNFSXNSVUZIZFVJc1EwRklka0lzUlVGSE1FSXNRMEZJTVVJc1JVRllUenRoUVVGWU8wRkJaMEpCTEcxQ1FVRlBMRVZCUVVVc1EwRkJSaXhGUVVGTExFOUJRVXdzUTBGcVFrMDdVMEZCYWtJN1FVRnRRa0VzV1VGQlNTeEpRVUZKTEU5QlFVOHNUMEZCVUN4SlFVRnJRaXhWUVVGc1FpeEpRVUZuUXl4UFFVRm9ReXhEUVhCQ1dUdEJRWEZDY0VJc1lVRkJTeXhKUVVGSkxFbEJRVWtzUTBGQlNpeEZRVUZQTEVsQlFVa3NSVUZCUlN4TlFVRkdMRVZCUVZVc1IwRkJPVUlzUlVGQmJVTXNSVUZCUlN4RlFVRkZMRU5CUVVZc1EwRkJSaXhGUVVGdVF6dEJRVU5CTEdWQlFVOHNRMEZCVUN4RFFYUkNiMEk3UzBGQmNFSXNRMEYxUWtRN1FVRkRTeXhYUVVGSExFTkJRVU1zVlVGQlV5eFBRVUZVTEVWQlFXdENMRTFCUVd4Q0xFVkJRVEJDTEU5QlFURkNMRVZCUVcxRE96dEJRVVV6UkN4blFrRkJTU3huUWtGQlowSXNVVUZCVVN3d1FrRkJVaXhEUVVGb1FpeERRVVoxUkRzN1FVRkpNMFFzYlVKQlFVOHNUMEZCVUN4SFFVRnBRaXhoUVVGcVFpeERRVW95UkR0VFFVRnVReXhGUVUxMFFpeEZRVUZETERSQ1FVRXlRaXhGUVVFelFpeEZRVTV2UWl4RFFVRklMRVZCVFdVc1IwRkJSU3hEUVVGRExGVkJRVk1zVDBGQlZDeEZRVUZwUWl4TlFVRnFRaXhGUVVGM1FpeFBRVUY0UWl4RlFVRm5RenRCUVVOMFJTeG5Ra0ZCU1N4UFFVRlBMRkZCUVZFc2FVSkJRVklzUTBGQlVDeERRVVJyUlRzN1FVRkhkRVVzYlVKQlFVOHNUMEZCVUN4SFFVRnBRaXhKUVVGcVFpeERRVWh6UlR0VFFVRm9ReXhGUVV0d1F5eEZRVUZETEcxQ1FVRnJRaXhGUVVGc1FpeEZRVXhyUXl4RFFVRkdMRVZCUzFRc1IwRkJSU3hEUVVGRExGVkJRVk1zVDBGQlZDeEZRVUZwUWl4TlFVRnFRaXhGUVVGM1FpeFBRVUY0UWl4RlFVRm5RenRCUVVNM1JDeG5Ra0ZCU1N4SlFVRkpMRkZCUVZFc1owTkJRVklzUTBGQlNpeERRVVI1UkRzN1FVRkhOMFFzYlVKQlFVOHNUMEZCVUN4SFFVRnBRaXhEUVVGcVFpeERRVWcyUkR0VFFVRm9ReXhGUVVzelFpeEZRVUZETEd0RFFVRnBReXhGUVVGcVF5eEZRVXg1UWl4RFFVRkdMRVZCUzJVc1IwRkJSU3hEUVVGRExGVkJRVk1zVDBGQlZDeEZRVUZwUWl4TlFVRnFRaXhGUVVGM1FpeFBRVUY0UWl4RlFVRm5RenRCUVVNMVJTeG5Ra0ZCU1N4UFFVRlBMRkZCUVZFc1YwRkJVaXhEUVVGUUxFTkJSSGRGTzBGQlJUVkZMR2RDUVVGSkxGRkJRVkVzVVVGQlVTeFpRVUZTTEVOQlFWSXNRMEZHZDBVN1FVRkhOVVVzWjBKQlFVa3NTVUZCU1N4UlFVRlJMRkZCUVZJc1EwRkJTaXhEUVVoM1JUdEJRVWsxUlN4blFrRkJTU3hUUVVGVExGRkJRVkVzY1VKQlFWSXNRMEZCVkN4RFFVcDNSVHRCUVVzMVJTeG5Ra0ZCU1N4UlFVRlJMRkZCUVZFc2EwSkJRVklzUTBGQlVpeERRVXgzUlR0QlFVMDFSU3huUWtGQlNTeFJRVUZSTEZGQlFWRXNhMEpCUVZJc1EwRkJVaXhEUVU1M1JUczdRVUZSTlVVc2JVSkJRVThzVDBGQlVDeEhRVUZwUWp0QlFVTmlMSE5DUVVGTkxFbEJRVTQ3UVVGRFFTeDFRa0ZCVHl4TFFVRlFPMEZCUTBFc2JVSkJRVWNzUTBGQlNEdEJRVU5CTEhkQ1FVRlJMRTFCUVZJN1FVRkRRU3gxUWtGQlR5eExRVUZRTzBGQlEwRXNkVUpCUVU4c1MwRkJVRHRoUVU1S0xFTkJValJGTzFOQlFXaERMRVZCYVVJeFF5eEZRVUZETEhWQ1FVRnpRaXhEUVVGMFFpeEZRVUYzUWl4aFFVRlpMRU5CUVZvc1JVRkJZeXhWUVVGVExFTkJRVlFzUlVGQlZ5eGpRVUZoTEVWQlFXSXNSVUZCWjBJc2IwSkJRVzFDTEVWQlFXNUNMRVZCUVhOQ0xHOUNRVUZ0UWl4RlFVRnVRaXhGUVdwQ0wwTXNRMEZCUml4RlFXbENlVVVzUjBGQlJTeERRVUZETEZWQlFWTXNUMEZCVkN4RlFVRnBRaXhOUVVGcVFpeEZRVUYzUWl4UFFVRjRRaXhGUVVGblF6czdPenM3T3pzN096czdPenM3T3pzN096czdPenM3T3pzN096czdPenM3UVVGblEzSktMRzFDUVVGUExFOUJRVkFzUjBGQmFVSXNVMEZCVlN4TFFVRlVMRU5CUVdVc1MwRkJaaXhGUVVGelFqczdRVUZGZEVNc2IwSkJRVWtzWTBGQll5eFBRVUZQTEZOQlFWQXNRMEZCYVVJc1MwRkJha0k3YjBKQlEyaENMRzlDUVVGdlFpeFBRVUZQTEVsQlFWQXNRMEZCV1N4RlFVRmFMRVZCUVdkQ0xFTkJRV2hDTEUxQlFYVkNMRXRCUVhaQ096czdRVUZGY0VJc2IwSkJTRVlzUTBGR2MwTTdPMEZCVDNSRExIVkNRVUZQTEZWQlFWTXNSMEZCVkN4RlFVRmpMRk5CUVdRc1JVRkJlVUlzUzBGQmVrSXNSVUZCWjBNN08wRkJSWEpETEhkQ1FVRkpMRTlCUVU4c1UwRkJVQ3hEUVVGcFFpeFJRVUZxUWl4RFFVRXdRaXhKUVVFeFFpeERRVUVyUWl4VFFVRXZRaXhOUVVFNFF5eHBRa0ZCT1VNc1JVRkJhVVU3UVVGRGJrVXNLMEpCUVU4c1dVRkJXU3hKUVVGYUxFTkJRV2xDTEVkQlFXcENMRVZCUVhOQ0xGTkJRWFJDTEVWQlFXbERMRXRCUVdwRExFTkJRVkFzUTBGRWJVVTdjVUpCUVhKRk8wRkJSMEVzZDBKQlFVa3NVMEZCVXl4RlFVRlVPM2RDUVVOR0xGRkJRVkVzUTBGQlF5eFZRVUZWTEZWQlFWWXNSMEZCZFVJc1IwRkJka0lzUjBGQk5rSXNSVUZCTjBJc1EwRkJSQ3hKUVVGeFF5eFZRVUZWTEZOQlFWWXNSMEZCYzBJc1IwRkJkRUlzUjBGQk5FSXNSVUZCTlVJc1EwRkJja01zU1VGQmQwVXNWVUZCVlN4UlFVRldMRWRCUVhGQ0xFZEJRWEpDTEVkQlFUSkNMRVZCUVROQ0xFTkJRWGhGTzBGQlExQXNPRUpCUVZVc1RVRkJWaXhIUVVGdFFpeEhRVUZ1UWl4SFFVRjVRaXhGUVVGNlFpeERRVVJQT3pzN1FVRkhVaXh2UTBGQlowSXNRMEZCYUVJN096dEJRVVZCTEdkRFFVRlpMRWxCUVVrc1RVRkJTaXhEUVVGWExGVkJRVlVzVFVGQlZpeEZRVUZyUWl4UlFVRlJMRWRCUVZJc1EwRkJla003ZDBKQlEwRXNWVUZRUmp0M1FrRlBZeXhMUVZCa08zZENRVTl4UWl4VFFWQnlRanQzUWtGUFowTXNWVUZRYUVNc1EwRk1jVU03UVVGaGNrTXNNa0pCUVU4c1JVRkJVRHRCUVdKeFF5eDNRa0ZqYWtNc1EwRkJReXhwUWtGQlJDeEZRVUZ2UWpzN1FVRkZkRUlzY1VOQlFXRXNTVUZCU1N4TlFVRktMRU5CUVZjc1RVRkJUU3hWUVVGVkxFMUJRVllzUjBGQmJVSXNWVUZCZWtJc1JVRkJjVU1zUzBGQmFFUXNRMEZCWWl4RFFVWnpRanR4UWtGQmVFSTdPenM3T3pzN08wRkJaSEZETEhsQ1FYbENja01zUjBGQlVTeFZRVUZWTEV0QlFWWXNSMEZCYTBJc1EwRkJReXhEUVVGRUxFdEJRVThzUTBGQlVEdEJRVU14UWl3NFFrRkJWU3hEUVVGV08wRkJNVUp4UXl3eVFrRXlRamxDTEZGQlFWRXNWVUZCVlN4SlFVRldMRU5CUVdVc1IwRkJaaXhEUVVGU0xFVkJRVFpDT3p0QlFVVnNReXh2UTBGQldTeE5RVUZOTEV0QlFVNHNSMEZCWXl4TlFVRk5MRU5CUVU0c1JVRkJVeXhOUVVGVUxFTkJSbEU3UVVGSGJFTXNORUpCUVVrc1dVRkJXU3hoUVVGYUxFVkJRVEpDTzBGQlF6ZENMRzFEUVVGUExFbEJRVkFzUTBGQldTeEpRVUZKTEV0QlFVb3NRMEZCVlN4aFFVRldMRVZCUVhsQ0xFMUJRVTBzUzBGQlRpeERRVUZ5UXpzN08wRkJSRFpDTEdkRFFVbDZRaXhEUVVGRExHbENRVUZFTEVsQlFYTkNMRTFCUVUwc1RVRkJUaXhIUVVGbExFTkJRV1lzUlVGQmEwSTdRVUZETVVNc2MwTkJRVTBzUTBGQlRpeEZRVUZUTEU5QlFWUXNRMEZCYVVJc1ZVRkJha0lzUlVGQk5rSXNXVUZCVnp0QlFVTjBReXg1UTBGQlN5eEpRVUZKTEVsQlFVa3NRMEZCU2l4RlFVRlBMRWxCUVVrc1ZVRkJWU3hOUVVGV0xFZEJRVzFDTEVOQlFXNUNMRVZCUVhOQ0xFZEJRVEZETEVWQlFTdERPMEZCUXpkRExEUkRRVUZKTEZWQlFWVXNRMEZCVml4TlFVRnBRaXhMUVVGcVFpeEZRVUYzUWp0QlFVTXhRaXhyUkVGQlRTeERRVUZPTEVsQlFWY3NTMEZCV0N4RFFVUXdRanQ1UTBGQk5VSTdjVU5CUkVZN2FVTkJSREpDTEVOQlFUZENMRU5CUkRCRE96WkNRVUUxUXp0QlFWTkJMR2REUVVGSkxFMUJRVTBzVFVGQlRpeEhRVUZsTEVOQlFXWXNTVUZCYjBJc1RVRkJUU3hMUVVGT0xFZEJRV01zU1VGQlNTeE5RVUZLTEVWQlFWazdRVUZEYUVRc2MwTkJRVTBzVTBGQlRpeERRVUZuUWl4SlFVRm9RaXhEUVVGeFFpeExRVUZ5UWl4RFFVRXlRaXhOUVVFelFpeEZRVUZ0UXl4TlFVRk5MRXRCUVU0c1EwRkJXU3hEUVVGYUxFTkJRVzVETEVWQlJHZEVPelpDUVVGc1JEdEJRVWRCTEhsRFFVRmhMRTFCUVUwc1EwRkJUaXhGUVVGVExFMUJRVlFzUTBGb1FtZENPMEZCYVVJM1FpdzBRMEZCWjBJc1UwRkJhRUlzUTBGcVFqWkNPMEZCYTBJM1FpeG5RMEZCU1N4UFFVRlBMRTFCUVZBc1NVRkJhVUlzUzBGQmFrSXNSVUZCZDBJN1FVRkRNVUlzYzBOQlJEQkNPelpDUVVFMVFqdDVRa0ZzUWtZN1FVRnpRa0VzTkVKQlFVa3NWVUZCVlN4VFFVRldMRXRCUVhkQ0xFMUJRVTBzUzBGQlRpeEZRVUZoTzBGQlEzWkRMSE5EUVVGVkxGTkJRVlk3UVVGRWRVTXNlVUpCUVhwRE8zRkNRWHBDUmp0QlFUWkNRU3gzUWtGQlNTeHJRa0ZCYTBJc1NVRkJTU3hOUVVGS0xFVkJRVms3UVVGRGFFTXNORUpCUVVrc1kwRkJZeXhEUVVGRExGVkJRVlVzU1VGQlZpeERRVUZsTEVWQlFXWXNRMEZCUkN4RlFVRnhRanRCUVVOeVF5eHRRMEZCVHl4SlFVRlFMRU5CUVZrc1JVRkJXaXhGUVVSeFF6dDVRa0ZCZGtNN2NVSkJSRVlzVFVGSlR6dEJRVU5NTEN0Q1FVRlBMRWxCUVZBc1EwRkJXU3hKUVVGSkxFdEJRVW9zUTBGQlZTeGhRVUZXTEVOQlFWb3NSVUZFU3p0eFFrRktVRHRCUVU5QkxESkNRVUZQTEU5QlFVOHNUVUZCVUN4SFFVRm5RaXhMUVVGb1FpeEhRVUYzUWl4UFFVRlBMRXRCUVZBc1EwRkJZU3hEUVVGaUxFVkJRV2RDTEV0QlFXaENMRU5CUVhoQ0xFZEJRV2xFTEUxQlFXcEVMRU5CTDBRNFFqdHBRa0ZCYUVNc1EwRlFLMEk3TzBGQmVVVjBReXgxUWtGQlR5eEpRVUZRTEVOQmVrVnpRenRoUVVGMFFpeEZRVUZzUWl4RFFXaERjVW83VTBGQmFFTXNSVUUwUjI1SUxFVkJOVWRyU0N4RFFVRkdMRVZCTkVjMVJ5eEhRVUZGTEVOQlFVTXNWVUZCVXl4UFFVRlVMRVZCUVdsQ0xFMUJRV3BDTEVWQlFYZENMRTlCUVhoQ0xFVkJRV2RETEVWQlFXaERMRVZCUlZBc1JVRkdUU3hEUVVGR0xFVkJSVUVzUjBGQlJTeERRVUZETEZWQlFWTXNUMEZCVkN4RlFVRnBRaXhOUVVGcVFpeEZRVUYzUWl4UFFVRjRRaXhGUVVGblF6dEJRVU42UXl4NVFrRkVlVU03TzBGQlIzcERMR2RDUVVGSkxIVkNRVUYxUWl4UlFVRlJMSGRDUVVGU0xFTkJRWFpDTEVOQlNIRkRPenRCUVV0NlF5eG5Ra0ZCU1N4aFFVRmhMRWRCUVdJc1EwRk1jVU03UVVGTmVrTXNhVU5CUVhGQ0xGVkJRWEpDTEVWQlFXbERMRlZCUVdwRExFVkJUbmxET3p0QlFWRjZReXhuUWtGQlNTeFZRVUZWTEc5Q1FVRnZRaXhWUVVGd1FpeERRVkl5UWpzN1FVRlZla01zYlVKQlFVOHNUMEZCVUN4SFFVRnBRaXhQUVVGcVFpeERRVlo1UXpzN1FVRlpla01zY1VKQlFWTXNUMEZCVkN4RFFVRnBRaXhKUVVGcVFpeEZRVUYxUWp0QlFVTnVRaXh2UWtGQlNTeFBRVUZQTEV0QlFVc3NUMEZCVEN4RFFVRlFMRU5CUkdVN08wRkJSMjVDTEc5Q1FVRkpMRU5CUVVNc1NVRkJSQ3hGUVVGUE8wRkJRMUFzTWtKQlFVOHNTMEZCU3l4UFFVRk1MRWxCUVdkQ0xFVkJRV2hDTEVOQlJFRTdhVUpCUVZnN08wRkJTVUVzZFVKQlFVOHNTVUZCVUN4RFFWQnRRanRoUVVGMlFqdFRRVnBUTEVWQmMwSlFMRVZCUVVNc01FSkJRWGxDTEVOQlFYcENMRVZCZEVKTExFTkJRVVlzUlVGelFqQkNMRWRCUVVVc1EwRkJReXhWUVVGVExFOUJRVlFzUlVGQmFVSXNUVUZCYWtJc1JVRkJkMElzVDBGQmVFSXNSVUZCWjBNN1FVRkRia1VzWVVGQlF5eFZRVUZWTEUxQlFWWXNSVUZCYVVJN1FVRkRiRUk3T3pzN1FVRkVhMElzYjBKQlMyUXNUMEZCVHl4UFFVRlBMRTFCUVZBc1MwRkJhMElzVjBGQmJFSXNSMEZEVUN4TlFVUlBMRWRCUTBVc1QwRkJUeXhOUVVGUUxFdEJRV3RDTEZkQlFXeENMRWRCUTFRc1RVRkVVeXhIUVVOQkxFVkJSRUVzUTBGT1N6czdRVUZUYkVJc2RVSkJRVThzVDBGQlVDeEhRVUZwUWl4VlFVRnFRaXhEUVZSclFqczdRVUZYYkVJc2VVSkJRVk1zVlVGQlZDeERRVUZ2UWl4SFFVRndRaXhGUVVGNVFpeExRVUY2UWl4RlFVRm5RenRCUVVNMVFpeDNRa0ZCU1N4UFFVRlBMRWxCUVZBc1JVRkJZVHRCUVVOaUxDdENRVUZQTEV0QlFVc3NSMEZCVEN4RFFVRlFMRU5CUkdFN2NVSkJRV3BDT3p0QlFVbEJMSGxDUVVGTExFZEJRVXdzU1VGQldTeExRVUZhTEVOQlREUkNPenRCUVU4MVFpd3lRa0ZCVHl4TFFVRlFMRU5CVURSQ08ybENRVUZvUXp0aFFWaERMRU5CUVVRc1EwRnhRa2NzU1VGeVFrZ3NRMEZ4UWxFc1NVRnlRbElzUlVGeFFtRXNUMEZCVHl4TlFVRlFMRXRCUVd0Q0xGZEJRV3hDTEVkQlFXZERMRTFCUVdoRExFZEJRWGxETEU5QlFVOHNTVUZCVUN4TFFVRm5RaXhYUVVGb1FpeEhRVUU0UWl4SlFVRTVRaXhIUVVGeFF5eFBRVUZQTEUxQlFWQXNTMEZCYTBJc1YwRkJiRUlzUjBGQlowTXNUVUZCYUVNc1IwRkJlVU1zUlVGQmVrTXNRMEZ5UWpOR0xFTkJSRzFGTzFOQlFXaERMRVZCZFVKcVF5eEZRWFpDWjBNc1EwRkJSaXhGUVhWQ01VSXNSMEZCUlN4RFFVRkRMRlZCUVZNc1QwRkJWQ3hGUVVGcFFpeE5RVUZxUWl4RlFVRjNRaXhQUVVGNFFpeEZRVUZuUXp0QlFVTjZReXg1UWtGRWVVTTdPMEZCUjNwRExHZENRVUZKTEdGQlFXRXNVVUZCVVN4WlFVRlNMRU5CUVdJc1EwRkljVU03TzBGQlMzcERMRzFDUVVGUExFOUJRVkFzUjBGQmFVSXNWVUZCYWtJc1EwRk1lVU03TzBGQlQzcERMSEZDUVVGVExGVkJRVlFzUTBGQmIwSXNWVUZCY0VJc1JVRkJaME1zVDBGQmFFTXNSVUZCZVVNc1dVRkJla01zUlVGQmRVUTdRVUZEYmtRc2IwSkJRVWtzVFVGQlRTdzRRa0ZCT0VJc1ZVRkJPVUlzUTBGRWVVTTdRVUZGYmtRc2IwSkJRVWtzWVVGQllTeE5RVUZOTEc5Q1FVRk9MRU5CUm10RE96dEJRVWx1UkN4dlFrRkJTU3hsUVVGbExGZEJRVmNzVlVGQldDeEZRVUYxUWl4UFFVRjJRaXhEUVVGbUxFTkJTaXRET3p0QlFVMXVSQ3h2UWtGQlNTeHBRa0ZCYVVJc1QwRkJha0lzUlVGQk1FSTdRVUZETVVJc01FSkJRVTBzU1VGQlNTeExRVUZLTEVOQlFWVXNLMEpCUTFvc1ZVRkVXU3hIUVVORExFdEJSRVFzUjBGRldpd3lRa0ZHV1N4SFFVVnJRaXhaUVVac1FpeEhRVWRhTEdWQlNGa3NSMEZKV2l4M1EwRktXU3hIUVVrclFpeFBRVW92UWl4RFFVRm9RaXhEUVVRd1FqdHBRa0ZCT1VJN08wRkJVVUVzZFVKQlFVOHNWMEZCVnl4SFFVRllMRVZCUVdkQ0xGbEJRV2hDTEVOQlFWQXNRMEZrYlVRN1lVRkJka1E3VTBGUVV5eEZRWGRDVUN4RlFVRkRMR05CUVdFc1EwRkJZaXhGUVhoQ1N5eERRVUZHTEVWQmQwSmpMRWxCUVVjc1EwRkJReXhWUVVGVExFOUJRVlFzUlVGQmFVSXNUVUZCYWtJc1JVRkJkMElzVDBGQmVFSXNSVUZCWjBNN1FVRkRlRVFzWVVGQlF5eFZRVUZWTEUxQlFWWXNSVUZCYVVJN1FVRkRiRUlzYjBKQlFVa3NWMEZCVnl4UFFVRlBMRTFCUVZBc1MwRkJhMElzVjBGQmJFSXNSMEZCWjBNc1RVRkJhRU1zUjBGRFdDeFBRVUZQTEUxQlFWQXNTMEZCYTBJc1YwRkJiRUlzUjBGQlowTXNUVUZCYUVNc1IwRkJlVU1zUlVGQmVrTXNRMEZHWXp0QlFVZHNRaXh2UWtGQlNTeFRRVUZUTEZGQlFWRXNZMEZCVWl4RFFVRlVMRU5CU0dNN08wRkJTMnhDTEc5Q1FVRkpMRTlCUVU4c1VVRkJVQ3hMUVVGdlFpeFhRVUZ3UWl4RlFVRnBRenRCUVVOcVF5d3lRa0ZCVHl4UFFVRlFMRWRCUVdsQ0xGRkJRV3BDTEVOQlJHbERPMmxDUVVGeVF5eE5RVVZQTzBGQlEwZ3NkMEpCUVVrc1VVRkJVU3hUUVVGVExESkNRVUZVTEVOQlFWSXNRMEZFUkRzN1FVRkhTQ3gzUWtGQlNTeERRVUZETEV0QlFVUXNSVUZCVVR0QlFVTlNMR2REUVVGUkxGTkJRVk1zTWtKQlFWUXNTVUZCZDBNc1RVRkJlRU1zUTBGRVFUdHhRa0ZCV2pzN1FVRkpRU3d5UWtGQlR5eFBRVUZRTEVkQlFXbENMRXRCUVdwQ0xFTkJVRWM3YVVKQlJsQTdZVUZNUXl4RFFVRkVMRU5CYVVKSExFbEJha0pJTEVOQmFVSlJMRWxCYWtKU0xFVkJhVUpoTEU5QlFVOHNUVUZCVUN4TFFVRnJRaXhYUVVGc1FpeEhRVUZuUXl4TlFVRm9ReXhIUVVGNVF5eFBRVUZQTEVsQlFWQXNTMEZCWjBJc1YwRkJhRUlzUjBGQk9FSXNTVUZCT1VJc1IwRkJjVU1zVDBGQlR5eE5RVUZRTEV0QlFXdENMRmRCUVd4Q0xFZEJRV2RETEUxQlFXaERMRWRCUVhsRExFVkJRWHBETEVOQmFrSXpSaXhEUVVSM1JEdFRRVUZvUXl4RlFXMUNkRUlzUlVGQlF5eG5Ra0ZCWlN4RFFVRm1MRVZCYmtKdlFpeERRVUZJTEVWQmJVSkZMRWxCUVVjc1EwRkJReXhWUVVGVExFOUJRVlFzUlVGQmFVSXNUVUZCYWtJc1JVRkJkMElzVDBGQmVFSXNSVUZCWjBNN1FVRkRNVVFzZVVKQlJEQkVPenRCUVVjeFJDeHRRa0ZCVHl4UFFVRlFMRWRCUVdsQ0xGTkJRVk1zVVVGQlZDeERRVUZyUWl4RFFVRnNRaXhGUVVGeFFqdEJRVU55UXl4MVFrRkJUeXhQUVVGUExFTkJRVkFzUzBGQllTeFJRVUZpTEVsQlFYbENMRTFCUVUwc1NVRkJUaXhEUVVSTE8yRkJRWEpDTEVOQlNIbERPMU5CUVdoRExFVkJUM2hDTEVWQlVIVkNMRU5CUVVnc1JVRlBhRUlzU1VGQlJ5eERRVUZETEZWQlFWTXNUMEZCVkN4RlFVRnBRaXhOUVVGcVFpeEZRVUYzUWl4UFFVRjRRaXhGUVVGblF6dEJRVU14UXl4blFrRkJTU3huUWtGQlowSXNUVUZCVFN4UFFVRk9MRU5CUkhOQ08wRkJSVEZETEdkQ1FVRkpMRmRCUVZjc1QwRkJUeXhUUVVGUUxFTkJRV2xDTEZGQlFXcENMRU5CUmpKQ096dEJRVWt4UXl4dFFrRkJUeXhQUVVGUUxFZEJRV2xDTEdsQ1FVRnBRaXhQUVVGcVFpeERRVXA1UWpzN1FVRk5NVU1zY1VKQlFWTXNUMEZCVkN4RFFVRnBRaXhIUVVGcVFpeEZRVUZ6UWp0QlFVTnNRaXgxUWtGQlR5eFRRVUZUTEVsQlFWUXNRMEZCWXl4SFFVRmtMRTFCUVhWQ0xHZENRVUYyUWl4RFFVUlhPMkZCUVhSQ08xTkJUbFVzUlVGVlVpeEZRVlpQTEVOQlFVZ3NSVUZWUVN4SlFVRkhMRU5CUVVNc1ZVRkJVeXhQUVVGVUxFVkJRV2xDTEUxQlFXcENMRVZCUVhkQ0xFOUJRWGhDTEVWQlFXZERPMEZCUXpGRExHZENRVUZKTEZGQlFWRXNVVUZCVVN4cFFrRkJVaXhEUVVGU0xFTkJSSE5ET3p0QlFVY3hReXh0UWtGQlR5eFBRVUZRTEVkQlFXbENMRXRCUVdwQ0xFTkJTREJETzFOQlFXaERMRVZCUzFJc1JVRkJReXh0UWtGQmEwSXNSVUZCYkVJc1JVRk1UU3hEUVVGSUxFVkJTMjlDTEVsQlFVY3NRMEZCUXl4VlFVRlRMRTlCUVZRc1JVRkJhVUlzVFVGQmFrSXNSVUZCZDBJc1QwRkJlRUlzUlVGQlowTTdRVUZET1VRc1owSkJRVWtzVjBGQlZ5eFJRVUZSTEZkQlFWSXNRMEZCV0N4RFFVUXdSRHRCUVVVNVJDeG5Ra0ZCU1N4VFFVRlRMRkZCUVZFc2MwSkJRVklzUTBGQlZDeERRVVl3UkRzN1FVRkpPVVFzYlVKQlFVOHNUMEZCVUN4SFFVRnBRaXhsUVVGcVFpeERRVW80UkRzN1FVRk5PVVFzY1VKQlFWTXNaVUZCVkN4RFFVRjVRaXhKUVVGNlFpeEZRVUVyUWl4TFFVRXZRaXhGUVVGelF5eFJRVUYwUXl4RlFVRm5SRHRCUVVNMVF5eHhRa0ZCU3l4SlFVRkpMRkZCUVVvc1NVRkJaMElzUzBGQmNrSXNSVUZCTkVJN1FVRkRlRUlzZDBKQlFVa3NXVUZCV1N4TlFVRk5MRkZCUVU0c1EwRkJXaXhEUVVSdlFqczdRVUZIZUVJc2QwSkJRVWtzWTBGQll5eFRRVUZrTEVWQlFYbENPMEZCUTNwQ0xIVkRRVUZsTEVsQlFXWXNSVUZCY1VJc1VVRkJja0lzUlVGQkswSXNVMEZCTDBJc1JVRkJNRU1zVVVGQk1VTXNSVUZFZVVJN2NVSkJRVGRDTEUxQlJVOHNTVUZCU1N4UFFVRlBMRk5CUVZBc1EwRkJTaXhGUVVGMVFqdEJRVU14UWl4MVEwRkJaU3hKUVVGbUxFVkJRWEZDTEZGQlFYSkNMRVZCUVN0Q0xGTkJRUzlDTEVWQlFUQkRMRkZCUVRGRExFVkJSREJDTzBGQlJURkNMRFJDUVVGSkxGVkJRVlVzU1VGQlZpeEZRVUZuUWp0QlFVTm9RaXh6UTBGQlZTeEpRVUZXTEVOQlFXVXNTVUZCWml4RlFVTkpMRkZCUkVvc1JVRkZTU3hYUVVGWExGTkJRVk1zVVVGQlZDeERRVUZZTEVkQlFXZERMRk5CUVdoRExFTkJSa29zUTBGRVowSTdlVUpCUVhCQ08zRkNRVVpITEUxQlQwRTdRVUZEU0N3MFFrRkJTU3hUUVVGVExGTkJRVlFzUTBGQlNpeEZRVUY1UWp0QlFVTnlRaXgzUTBGQldTeEpRVUZhTEVWQlFXdENMRXRCUVd4Q0xFVkJRWGxDTEZGQlFYcENMRVZCUVcxRExGRkJRVzVETEVWQlFUWkRMRk5CUVRkRExFVkJSSEZDTzNsQ1FVRjZRaXhOUVVWUE8wRkJRMGdzYVVOQlFVc3NVVUZCVEN4SlFVRnBRaXhUUVVGcVFpeERRVVJITzNsQ1FVWlFPM0ZDUVZKSE8ybENRVXhZTzJGQlJFbzdPMEZCZFVKQkxIRkNRVUZUTEdOQlFWUXNRMEZCZDBJc1NVRkJlRUlzUlVGQk9FSXNVVUZCT1VJc1JVRkJkME1zVTBGQmVFTXNSVUZCYlVRc1VVRkJia1FzUlVGQk5rUTdRVUZEZWtRc2IwSkJRVWtzVVVGQlNpeEZRVUZqTzBGQlExWXNkMEpCUVVrc1owSkJRV2RDTEZOQlFWTXNVVUZCVkN4RFFVRm9RaXhEUVVSTk96dEJRVWRXTEhkQ1FVRkpMRU5CUVVNc1QwRkJUeXhoUVVGUUxFTkJRVVFzUlVGQmQwSTdRVUZEZUVJc05FSkJRVWtzWVVGQllTeFpRVUZpTEVWQlFUSkNPMEZCUXpOQ0xHbERRVUZMTEVsQlFVa3NVVUZCU2l4SlFVRm5RaXhoUVVGeVFpeEZRVUZ2UXp0QlFVTm9ReXh4UTBGQlN5eGxRVUZNTEVOQlFYRkNMRkZCUVhKQ0xFVkJSR2RET3paQ1FVRndRenQ1UWtGRVNpeE5RVWxQTEVsQlFVa3NZVUZCWVN4UFFVRmlMRVZCUVhOQ08wRkJRemRDTEdsRFFVRkxMRWxCUVVrc1EwRkJTaXhKUVVGVExHRkJRV1FzUlVGQk5rSTdRVUZEZWtJc2NVTkJRVXNzUzBGQlRDeERRVUZYTEVOQlFWZ3NTVUZCWjBJc1JVRkJhRUlzUTBGRWVVSTdOa0pCUVRkQ08zbENRVVJITEUxQlNVRXNTVUZCU1N4UFFVRlBMR0ZCUVZBc1MwRkJlVUlzVVVGQmVrSXNSVUZCYlVNN1FVRkRNVU1zYVVOQlFVc3NVVUZCVEN4SlFVRnBRaXhGUVVGcVFpeERRVVF3UXp0NVFrRkJka01zVFVGRlFUdEJRVU5JTEdsRFFVRkxMRkZCUVV3c1NVRkJhVUlzU1VGQmFrSXNRMEZFUnp0NVFrRkdRVHR4UWtGVVdDeE5RV05QTEVsQlFVa3NZMEZCWXl4TlFVRmtMRVZCUVhOQ08wRkJRemRDTEhORFFVRmpMRTFCUVdRc1EwRkJjVUlzU1VGQmNrSXNSVUZCTWtJc1VVRkJNMElzUlVGQmNVTXNVMEZCY2tNc1JVRkVOa0k3Y1VKQlFURkNPMmxDUVdwQ1dEdGhRVVJLT3p0QlFYZENRU3h4UWtGQlV5eFhRVUZVTEVOQlFYRkNMRWxCUVhKQ0xFVkJRVEpDTEV0QlFUTkNMRVZCUVd0RExGRkJRV3hETEVWQlFUUkRMRkZCUVRWRExFVkJRWE5FTEZOQlFYUkVMRVZCUVdsRk8wRkJRemRFTEc5Q1FVRkpMR2RDUVVGblFpeFhRVUZYTEZOQlFWTXNVVUZCVkN4RFFVRllMRWRCUVdkRExGTkJRV2hET3pzN1FVRkVlVU1zYjBKQlNYcEVMR0ZCUVdFc1dVRkJZaXhGUVVFeVFqdEJRVU16UWl4NVFrRkJTeXhKUVVGSkxGRkJRVW9zU1VGQlowSXNVMEZCY2tJc1JVRkJaME03UVVGRE5VSXNORUpCUVVrc1dVRkJXU3hWUVVGVkxGRkJRVllzUTBGQldpeERRVVIzUWpzN1FVRkhOVUlzTkVKQlFVa3NZMEZCWXl4VFFVRmtMRVZCUVhsQ08wRkJRM3BDTEdsRFFVRkxMR1ZCUVV3c1EwRkJjVUlzVVVGQmNrSXNSVUZFZVVJN2VVSkJRVGRDTEUxQlJVODdRVUZEU0N4cFEwRkJTeXhaUVVGTUxFTkJRV3RDTEZGQlFXeENMRVZCUVRSQ0xGTkJRVFZDTEVWQlJFYzdlVUpCUmxBN2NVSkJTRW83TzBGQlZVRXNNa0pCV0RKQ08ybENRVUV2UWpzN1FVRmpRU3h2UWtGQlJ5eHBRa0ZCYVVJc1UwRkJVeXhoUVVGVUxFTkJRV3BDTEVsQlEwTXNZVUZCWVN4aFFVRmlMRTFCUVdkRExHRkJRV0VzVTBGQllpeERRVUZvUXl4RlFVRjVSRHRCUVVONlJDeDVRa0ZCU3l4UlFVRk1MRWxCUVdsQ0xGTkJRV3BDTEVOQlJIbEVPMEZCUlhwRUxESkNRVVo1UkR0cFFrRkVOMFE3TzBGQlRVRXNiMEpCUVVrc1EwRkJReXhUUVVGVExFdEJRVXNzVVVGQlRDeERRVUZVTEVOQlFVUXNSVUZCTWtJN1FVRkRNMElzZVVKQlFVc3NVVUZCVEN4SlFVRnBRaXhGUVVGcVFpeERRVVF5UWp0cFFrRkJMMEk3TzBGQlNVRXNiMEpCUVVrc1YwRkJWeXhoUVVGaExFOUJRV0lzUjBGQmRVSXNSVUZCZGtJc1IwRkJORUlzVTBGQk5VSXNRMEUxUWpoRE96dEJRVGhDTjBRc2NVSkJRVXNzU1VGQlNTeERRVUZLTEVsQlFWTXNVMEZCWkN4RlFVRjVRanRCUVVOeVFpeDNRa0ZCU1N4UlFVRlJMRlZCUVZVc1EwRkJWaXhEUVVGU0xFTkJSR2xDTzBGQlJYSkNMSGxDUVVGTExGRkJRVXdzUlVGQlpTeERRVUZtTEVsQlFXOUNMRXRCUVVNc1MwRkJWU3hUUVVGV0xFZEJRWFZDTEZGQlFYaENMRWRCUVcxRExFdEJRVzVETEVOQlJrTTdhVUpCUVhwQ08yRkJPVUpLT3p0QlFXOURRU3h4UWtGQlV5eFpRVUZVTEVOQlFYTkNMRXRCUVhSQ0xFVkJRVFpDTzBGQlEzcENMRzlDUVVGSkxFOUJRVThzWTBGQlVDeEZRVUYxUWp0QlFVTjJRaXd5UWtGQlR5eFBRVUZQTEdOQlFWQXNRMEZCYzBJc1MwRkJkRUlzUTBGQlVDeERRVVIxUWp0cFFrRkJNMElzVFVGRlR5eEpRVUZKTEUxQlFVMHNVMEZCVGl4RlFVRnBRanRCUVVONFFpd3lRa0ZCVHl4TlFVRk5MRk5CUVU0c1EwRkVhVUk3YVVKQlFYSkNMRTFCUlVFc1NVRkJTU3hOUVVGTkxGZEJRVTRzUlVGQmJVSTdRVUZETVVJc01rSkJRVThzVFVGQlRTeFhRVUZPTEVOQlFXdENMRk5CUVd4Q0xFTkJSRzFDTzJsQ1FVRjJRanRoUVV4WU8xTkJla1k0UWl4RlFXMUhOVUlzUlVGQlF5eDNRa0ZCZFVJc1JVRkJka0lzUlVGQk1FSXNZVUZCV1N4RlFVRmFMRVZCYmtkQkxFTkJRVWdzUlVGdFIyOUNMRWxCUVVjc1EwRkJReXhWUVVGVExFOUJRVlFzUlVGQmFVSXNUVUZCYWtJc1JVRkJkMElzVDBGQmVFSXNSVUZCWjBNN1FVRkRiRVlzWjBKQlFVa3NWMEZCVnl4UlFVRlJMR2xDUVVGU0xFTkJRVmdzUTBGRU9FVTdPMEZCUjJ4R0xHZENRVUZKTEd0Q1FVRnJRaXhSUVVGUkxHOUNRVUZTTEVOQlFXeENMRU5CU0RoRk96dEJRVXRzUml4blFrRkJTU3hWUVVGVkxGRkJRVkVzYzBKQlFWSXNRMEZCVml4RFFVdzRSVHRCUVUxc1JpeG5Ra0ZCU1N4VlFVRlZMRkZCUVZFc2MwSkJRVklzUTBGQlZpeERRVTQ0UlR0QlFVOXNSaXhuUWtGQlNTeFhRVUZYTEZGQlFWRXNkVUpCUVZJc1EwRkJXQ3hEUVZBNFJUdEJRVkZzUml4blFrRkJTU3hqUVVGakxGRkJRVkVzTUVKQlFWSXNRMEZCWkN4RFFWSTRSVHM3UVVGVmJFWXNiVUpCUVU4c1QwRkJVQ3hIUVVGcFFpeGhRVUZxUWl4RFFWWnJSanM3UVVGWmJFWXNjVUpCUVZNc1lVRkJWQ3hEUVVGMVFpeExRVUYyUWl4RlFVRTRRaXhKUVVFNVFpeEZRVUZ2UXp0QlFVTm9ReXh2UWtGQlNTeE5RVUZOTEU5QlFVOHNTMEZCU3l4UlFVRk1MRWxCUVdsQ0xGRkJRV3BDTEVkQlFUUkNMRkZCUVc1RExFTkJSSE5DTzBGQlJXaERMRzlDUVVGSkxFOUJRVThzVDBGQlR5eExRVUZMTEVsQlFVd3NSMEZCV1N4SlFVRnVRaXhEUVVaeFFqczdRVUZKYUVNc2QwSkJRVkVzV1VGQldTeExRVUZhTEVWQlFXMUNMRU5CUVc1Q0xFTkJTbmRDT3p0QlFVMW9ReXh2UWtGQlNTeFRRVUZUTEV0QlFWUXNRMEZCU2l4RlFVRnhRanRCUVVOcVFpd3lRa0ZCVHl4TlFVRk5MRWxCUVU0c1JVRkJVQ3hEUVVScFFqdHBRa0ZCY2tJc1RVRkZUeXhKUVVGSkxGRkJRVkVzUzBGQlVpeERRVUZLTEVWQlFXOUNPMEZCUTNaQ0xESkNRVUZQTEVsQlFVa3NZMEZCU2l4RFFVRnRRaXhOUVVGTkxFbEJRVTRzUTBGQk1VSXNRMEZFZFVJN2FVSkJRWEJDTEUxQlJVRXNTVUZCU1N4RFFVRkRMRkZCUVZFc1MwRkJVaXhEUVVGRUxFVkJRV2xDTzBGQlEzaENMSGRDUVVGSkxFbEJRVW9zUlVGQlZUdEJRVU5PTERaQ1FVRkxMSE5EUVVGTUxFVkJRVFpETEV0QlFUZERMRVZCUkUwN2NVSkJRVlk3UVVGSFFTd3lRa0ZCVHl4SlFVRlFMRU5CU25kQ08ybENRVUZ5UWpzN1FVRlBVQ3h2UWtGQlNTeFBRVUZQTEV0QlFVTXNRMEZCVFN4VFFVRk9MRXRCUVc5Q0xFbEJRWEJDTEVkQlExSXNTVUZCU1N4aFFVRktMRU5CUVd0Q0xFMUJRVTBzVDBGQlRpeERRVVJZTEVkQlJWQXNTVUZCU1N4bFFVRktMRU5CUVc5Q0xFMUJRVTBzVTBGQlRpeEZRVUZwUWl4TlFVRk5MRTlCUVU0c1EwRkdPVUlzUTBGcVFuRkNPenRCUVhGQ2FFTXNiMEpCUVVrc1VVRkJVU3hOUVVGTkxGVkJRVTRzUTBGeVFtOUNPMEZCYzBKb1F5eG5RMEZCWjBJc1NVRkJhRUlzUlVGQmMwSXNTMEZCZEVJc1JVRjBRbWRET3p0QlFYZENhRU1zYjBKQlFVa3NWMEZCVnl4TlFVRk5MRkZCUVU0c1EwRjRRbWxDT3p0QlFUQkNhRU1zY1VKQlFVc3NTVUZCU1N4SlFVRkpMRU5CUVVvc1JVRkJUeXhKUVVGSkxGTkJRVk1zVFVGQlZDeEZRVUZwUWl4SFFVRnlReXhGUVVFd1F6dEJRVU4wUXl4M1FrRkJTU3haUVVGWkxHTkJRV01zVTBGQlV5eERRVUZVTEVOQlFXUXNSVUZCTWtJc1NVRkJNMElzUTBGQldpeERRVVJyUXp0QlFVVjBReXgzUWtGQlNTeFRRVUZLTEVWQlFXVTdRVUZEV0N3MlFrRkJTeXhYUVVGTUxFTkJRV2xDTEZOQlFXcENMRVZCUkZjN2NVSkJRV1k3YVVKQlJrbzdPMEZCVDBFc2RVSkJRVThzU1VGQlVDeERRV3BEWjBNN1lVRkJjRU03VTBGYWEwUXNSVUZuUkdoRUxFVkJRVU1zTkVKQlFUSkNMRVZCUVROQ0xFVkJRVGhDTEhkQ1FVRjFRaXhGUVVGMlFpeEZRVUV3UWl4M1FrRkJkVUlzUlVGQmRrSXNSVUZCTUVJc2VVSkJRWGRDTEVWQlFYaENMRVZCUVRKQ0xITkNRVUZ4UWl4RlFVRnlRaXhGUVVGM1FpeHRRa0ZCYTBJc1JVRkJiRUlzUlVGb1JIWkdMRU5CUVVnc1JVRm5SR2xJTEVsQlFVY3NRMEZCUXl4VlFVRlRMRTlCUVZRc1JVRkJhVUlzVFVGQmFrSXNSVUZCZDBJc1QwRkJlRUlzUlVGQlowTTdPenM3T3pzN1FVRlBiazBzWjBKQlFVa3NWVUZCVlN4RlFVRldMRU5CVUN0TU96dEJRVk51VFN4dFFrRkJUeXhQUVVGUUxFZEJRV2xDTEZGQlFXcENMRU5CVkcxTk96dEJRVmR1VFN4eFFrRkJVeXhSUVVGVUxFTkJRV3RDTEZGQlFXeENMRVZCUVRSQ0xFbEJRVFZDTEVWQlFXdERMRTlCUVd4RExFVkJRVEpETEV0QlFUTkRMRVZCUVd0RU8wRkJRemxETEc5Q1FVRkpMRU5CUVVNc1QwRkJSQ3hKUVVGWkxGRkJRVkVzVFVGQlVpeExRVUZ0UWl4RFFVRnVRaXhGUVVGelFqdEJRVU5zUXl3eVFrRkJUeXhGUVVGUUxFTkJSR3RETzJsQ1FVRjBReXhOUVVWUE8wRkJRMGdzTkVKQlFWRXNTVUZCVWl4RFFVRmhMRk5CUVdJc1JVRkVSenRCUVVWSUxESkNRVUZQTEZGQlFWRXNVVUZCVWl4RlFVRnJRaXhKUVVGc1FpeEZRVUYzUWl4UFFVRjRRaXhGUVVGcFF5eExRVUZxUXl4RlFVRjNReXhEUVVGNFF5eERRVUZRTEVOQlJrYzdhVUpCUmxBN1lVRkVTanM3UVVGVFFTeHhRa0ZCVXl4UFFVRlVMRU5CUVdsQ0xGRkJRV3BDTEVWQlFUSkNMRWxCUVROQ0xFVkJRV2xETEU5QlFXcERMRVZCUVRCRExFdEJRVEZETEVWQlFXbEVMRk5CUVdwRUxFVkJRVFJFTzBGQlEzaEVMSGRDUVVGUkxGTkJRVk1zUlVGQlZDeERRVVJuUkRzN1FVRkplRVFzYjBKQlFVa3NVVUZCU2l4RlFVRmpPMEZCUTFZc2QwSkJRVWtzWVVGQllTeFBRVUZpTEVWQlFYTkNMRk5CUVhSQ0xFVkJRV2xETEZOQlFXcERMRU5CUVVvc1JVRkJhVVE3UVVGRE4wTXNPRUpCUVUwc1UwRkJUaXhKUVVGdFFpeFJRVUZ1UWl4RFFVUTJRenR4UWtGQmFrUTdPMEZCU1VFc2QwSkJRVWtzV1VGQldTeExRVUZMTEZGQlFVd3NRMEZNVGpzN1FVRlBWaXgzUWtGQlNTeFRRVUZLTEVWQlFXVTdPMEZCUlZnc05FSkJRVWtzWVVGQllTeFRRVUZUTEZWQlFWUXNRMEZHVGpzN1FVRkpXQ3cyUWtGQlN5eEpRVUZKTEVsQlFVa3NRMEZCU2l4RlFVRlBMRWxCUVVrc1MwRkJTeXhSUVVGTUxFTkJRV01zVFVGQlpDeEZRVUZ6UWl4SFFVRXhReXhGUVVFclF6dEJRVU16UXl4NVEwRkJZU3hEUVVGaUxFTkJSREpET3p0QlFVY3pReXhuUTBGQlNTeFRRVUZUTEZWQlFWVXNRMEZCVml4TFFVRm5RaXhQUVVGb1FpeERRVWc0UWp0QlFVa3pReXhuUTBGQlNTeFpRVUZaTEdGQlFXRXNUMEZCVHl4TFFVRlFMRWxCUVdkQ0xFTkJRV2hDTEVOQlFXSTdPenRCUVVveVFpeG5RMEZQZGtNc1lVRkJZU3hQUVVGaUxFVkJRWE5DTEZOQlFYUkNMRVZCUVdsRExGTkJRV3BETEVOQlFVb3NSVUZCYVVRN1FVRkROME1zZDBOQlFWRXNWMEZCVnl4RFFVRllMRU5CUVZJc1JVRkJkVUlzVFVGQmRrSXNSVUZCSzBJc1QwRkJMMElzUlVGQmQwTXNTMEZCZUVNc1JVRkJLME1zVTBGQkwwTXNSVUZFTmtNN05rSkJRV3BFT3p0QlFVbEJMSGREUVVGWkxGTkJRVm9zUTBGWU1rTTdlVUpCUVM5RE8zRkNRVXBLTzJsQ1FWQktPenRCUVRKQ1FTeDFRa0ZCVHl4TFFVRlFMRU5CTDBKM1JEdGhRVUUxUkRzN08wRkJjRUp0VFN4eFFrRjFSREZNTEZsQlFWUXNRMEZCYzBJc1QwRkJkRUlzUlVGQkswSXNTVUZCTDBJc1JVRkJjVU1zUzBGQmNrTXNSVUZCTkVNN1FVRkRlRU1zYjBKQlFVa3NVVUZCVVN4TlFVRlNMRXRCUVcxQ0xFTkJRVzVDTEVWQlFYTkNPMEZCUTNSQ0xESkNRVUZQTEV0QlFWQXNRMEZFYzBJN2FVSkJRVEZDT3p0QlFVbEJMRzlDUVVGSkxGZEJRVmNzUTBGQldDeERRVXh2UXp0QlFVMTRReXh2UWtGQlNTeFhRVUZYTEZGQlFWRXNUVUZCVWl4SFFVRnBRaXhEUVVGcVFpeERRVTU1UWp0QlFVOTRReXh2UWtGQlNTeFpRVUZLTEVOQlVIZERPMEZCVVhoRExHOUNRVUZKTEZkQlFVb3NRMEZTZDBNN08wRkJWWGhETEhWQ1FVRlBMRmxCUVZrc1VVRkJXaXhGUVVGelFqdEJRVU42UWl4dFEwRkJaU3hEUVVGRkxGZEJRVmNzVVVGQldDeERRVUZFTEVkQlFYZENMRU5CUVhoQ0xFbEJRVGhDTEVOQlFTOUNMRU5CUkZVN1FVRkZla0lzYTBOQlFXTXNVVUZCVVN4WlFVRlNMRU5CUVdRc1EwRkdlVUk3TzBGQlNYcENMSGRDUVVGSkxHRkJRV0VzVVVGQllpeEZRVUYxUWp0QlFVTjJRaXdyUWtGQlR5eGxRVUZsTEVsQlFXWXNTVUZCZFVJc1pVRkJaU3hMUVVGbUxFTkJSRkE3Y1VKQlFUTkNMRTFCUlU4c1NVRkJTU3hqUVVGakxFbEJRV1FzUlVGQmIwSTdRVUZETTBJc2JVTkJRVmNzWlVGQlpTeERRVUZtTEVOQlJHZENPM0ZDUVVGNFFpeE5RVVZETEVsQlFVa3NZMEZCWXl4TFFVRmtMRVZCUVhGQ08wRkJRemRDTEcxRFFVRlhMR1ZCUVdVc1EwRkJaaXhEUVVSclFqdHhRa0ZCZWtJc1RVRkZSRHRCUVVOSUxDdENRVUZQTEVsQlFWQXNRMEZFUnp0eFFrRkdRenRwUWtGU1dqczdRVUZsUVN4MVFrRkJUeXhMUVVGUUxFTkJla0ozUXp0aFFVRTFRenM3UVVFMFFrRXNjVUpCUVZNc1UwRkJWQ3hEUVVGdFFpeERRVUZ1UWl4RlFVRnpRaXhEUVVGMFFpeEZRVUY1UWp0QlFVTnlRaXgxUWtGQlR5eEpRVUZKTEVOQlFVb3NSMEZCVVN4RFFVRlNMRWRCUVZrc1EwRkJReXhEUVVGRUxFTkJSRVU3WVVGQmVrSTdVMEZ1Um0xTExFVkJkVVpxU3l4RlFYWkdaMHNzUTBGQlNDeEZRWFZHZWtvc1NVRkJSeXhEUVVGRExGVkJRVk1zVDBGQlZDeEZRVUZwUWl4TlFVRnFRaXhGUVVGM1FpeFBRVUY0UWl4RlFVRm5RenRCUVVNeFF5eG5Ra0ZCU1N4clFrRkJhMElzVVVGQlVTeHZRa0ZCVWl4RFFVRnNRaXhEUVVSelF6czdRVUZITVVNc1owSkJRVWtzVjBGQlZ5eFJRVUZSTEhWQ1FVRlNMRU5CUVZnc1EwRkljME03UVVGSk1VTXNaMEpCUVVrc1UwRkJVeXhSUVVGUkxHOUNRVUZTTEVOQlFWUXNRMEZLYzBNN08wRkJUVEZETEdkQ1FVRkpMR1ZCUVdVc1VVRkJVU3hwUWtGQlVpeERRVUZtTEVOQlRuTkRPenRCUVZFeFF5eHRRa0ZCVHl4UFFVRlFMRWRCUVdsQ0xGVkJRV3BDTEVOQlVqQkRPenRCUVZVeFF5eHhRa0ZCVXl4VlFVRlVMRU5CUVc5Q0xFMUJRWEJDTEVWQlFUUkNMRTlCUVRWQ0xFVkJRWEZETEdGQlFYSkRMRVZCUVc5RU8wRkJRMmhFTEc5Q1FVRkpMRTlCUVU4c1QwRkJUeXhKUVVGUUxFTkJSSEZETzBGQlJXaEVMRzlDUVVGSkxGRkJRVkVzVDBGQlR5eExRVUZRTEVOQlJtOURPMEZCUjJoRUxHOUNRVUZKTEZGQlFWRXNUMEZCVHl4TFFVRlFMRU5CU0c5RE96dEJRVXRvUkN4M1FrRkJVU3hKUVVGU08wRkJRMGtzZVVKQlFVc3NUMEZCVHl4TlFVRlFPMEZCUTBRc0swSkJRVThzVjBGQlZ5eFBRVUZZTEVWQlFXOUNMRXRCUVhCQ0xFTkJRVkFzUTBGRVNqdEJRVVJLTEhsQ1FVZFRMRTlCUVU4c1RVRkJVRHRCUVVORUxDdENRVUZQTEZkQlFWY3NUMEZCV0N4RlFVRnZRaXhMUVVGd1FpeEZRVUV5UWl4aFFVRXpRaXhEUVVGUUxFTkJSRW83UVVGSVNpeDVRa0ZMVXl4UFFVRlBMRXRCUVZBN1FVRkRSQ3dyUWtGQlR5eFpRVUZaTEU5QlFWb3NSVUZCY1VJc1MwRkJja0lzUlVGQk5FSXNTMEZCTlVJc1JVRkJiVU1zWVVGQmJrTXNRMEZCVUN4RFFVUktPMEZCVEVvc2VVSkJUMU1zVDBGQlR5eE5RVUZRTzBGQlEwUXNLMEpCUVU4c1dVRkJXU3hQUVVGYUxFVkJRWEZDTEV0QlFYSkNMRVZCUVRSQ0xFdEJRVFZDTEVWQlFXMURMR0ZCUVc1RExFTkJRVkFzUTBGRVNqdEJRVkJLTEhsQ1FWTlRMRTlCUVU4c1MwRkJVRHRCUVVORUxDdENRVUZQTEZkQlFWY3NUMEZCV0N4RlFVRnZRaXhMUVVGd1FpeEZRVUV5UWl4TFFVRXpRaXhGUVVGclF5eGhRVUZzUXl4RFFVRlFMRU5CUkVvN1FVRlVTaXg1UWtGWFV5eFBRVUZQTEV0QlFWQTdRVUZEUkN4M1EwRkJaMElzVDBGQmFFSXNSVUZCZVVJc1MwRkJla0lzUlVGRVNqdEJRVVZKTEN0Q1FVRlBMRTlCUVZBc1EwRkdTanRCUVZoS0xIbENRV05UTEU5QlFVOHNTMEZCVUR0QlFVTkVMSGREUVVGblFpeFBRVUZvUWl4RlFVRjVRaXhMUVVGNlFpeEZRVUZuUXl4TlFVRk5MRlZCUVU0c1EwRkJhRU1zUTBGRVNqdEJRVVZKTEN0Q1FVRlBMRTlCUVZBc1EwRkdTanRCUVdSS0xIbENRV2xDVXl4UFFVRlBMRXRCUVZBN1FVRkRSQ3dyUWtGQlR5eFpRVUZaTEU5QlFWb3NSVUZEU0N4alFVRmpMRXRCUVdRc1EwRkJiMElzVDBGQmNFSXNSVUZCTmtJc1MwRkJOMElzUlVGQmIwTXNZVUZCY0VNc1EwRkVSeXhEUVVGUUxFTkJSRW83UVVGcVFrbzdRVUZ4UWxFc0swSkJRVThzVDBGQlVDeERRVVJLTzBGQmNFSktMR2xDUVV4blJEdGhRVUZ3UkRzN1FVRTRRa0VzY1VKQlFWTXNWVUZCVkN4RFFVRnZRaXhQUVVGd1FpeEZRVUUyUWl4TFFVRTNRaXhGUVVGdlF6dEJRVU5vUXl4dlFrRkJTU3hoUVVGaExGRkJRVkVzVlVGQlVpeERRVVJsT3p0QlFVZG9ReXh2UWtGQlNTeFZRVUZLTEVWQlFXZENPMEZCUTFvc0swSkJRVmNzVjBGQldDeERRVUYxUWl4UFFVRjJRaXhGUVVSWk8ybENRVUZvUWpzN1FVRkpRU3c0UWtGQll5eFBRVUZrTEVWQlFYVkNMRXRCUVhaQ0xFVkJVR2RET3p0QlFWTm9ReXgxUWtGQlR5eEpRVUZRTEVOQlZHZERPMkZCUVhCRE96dEJRVmxCTEhGQ1FVRlRMRlZCUVZRc1EwRkJiMElzVlVGQmNFSXNSVUZCWjBNc1MwRkJhRU1zUlVGQmRVTXNZVUZCZGtNc1JVRkJjMFE3UVVGRGJFUXNiMEpCUVVrc1ZVRkJWU3hqUVVGakxFMUJRV1FzUTBGQmNVSXNTMEZCY2tJc1JVRkJORUlzWVVGQk5VSXNRMEZCVml4RFFVUTRRenM3UVVGSGJFUXNiMEpCUVVrc1ZVRkJTaXhGUVVGblFqdEJRVU5hTEN0Q1FVRlhMRmRCUVZnc1EwRkJkVUlzVDBGQmRrSXNSVUZFV1R0cFFrRkJhRUk3TzBGQlNVRXNkVUpCUVU4c1ZVRkJVQ3hEUVZCclJEdGhRVUYwUkRzN1FVRlZRU3h4UWtGQlV5eFhRVUZVTEVOQlFYRkNMRTlCUVhKQ0xFVkJRVGhDTEZOQlFUbENMRVZCUVhsRExFdEJRWHBETEVWQlFXZEVMR0ZCUVdoRUxFVkJRU3RFTzBGQlF6TkVMRzlDUVVGSkxFOUJRVW9zUTBGRU1rUTdPMEZCUnpORUxHOUNRVUZKTEZGQlFWRXNVVUZCVWl4TFFVRnhRaXhEUVVGeVFpeEZRVUYzUWp0QlFVTjRRaXcwUWtGQlVTeFhRVUZTTEVOQlFXOUNMRU5CUVhCQ0xFVkJRWFZDTEZGQlFWRXNUVUZCVWl4RlFVRm5RaXhOUVVGTkxFbEJRVTRzUTBGQmRrTXNRMEZFZDBJN1FVRkZlRUlzT0VKQlFWVXNUMEZCVml4RFFVWjNRanRwUWtGQk5VSXNUVUZIVHp0QlFVTklMSGRDUVVGSkxHRkJRV0VzVVVGQlVTeFZRVUZTTEVOQlJHUTdRVUZGU0N3NFFrRkJWU3hqUVVGakxFMUJRV1FzUTBGQmNVSXNTMEZCY2tJc1JVRkJORUlzWVVGQk5VSXNRMEZCVml4RFFVWkhPenRCUVVsSUxIZENRVUZKTEdOQlFXTXNXVUZCV1N4UFFVRmFMRVZCUVhGQ08wRkJRMjVETEcxRFFVRlhMRmxCUVZnc1EwRkJkMElzVDBGQmVFSXNSVUZCYVVNc1QwRkJha01zUlVGRWJVTTdjVUpCUVhaRE8ybENRVkJLT3p0QlFWbEJMSFZDUVVGUExFOUJRVkFzUTBGbU1rUTdZVUZCTDBRN08wRkJhMEpCTEhGQ1FVRlRMRmRCUVZRc1EwRkJjVUlzVDBGQmNrSXNSVUZCT0VJc1UwRkJPVUlzUlVGQmVVTXNUVUZCZWtNc1JVRkJhVVFzWVVGQmFrUXNSVUZCWjBVN1FVRkROVVFzYjBKQlFVa3NWMEZCVnl4aFFVRmhMRk5CUVdJc1JVRkJkMElzVFVGQmVFSXNRMEZCV0N4RFFVUjNSRHRCUVVVMVJDeHZRa0ZCU1N4UFFVRktMRU5CUmpSRU96dEJRVWsxUkN4dlFrRkJTU3hSUVVGS0xFVkJRV003UVVGRFZpdzRRa0ZCVlN4UFFVRlBMRTFCUVZBc1EwRkJZeXhUUVVGa0xFVkJRWGxDTEU5QlFYcENMRXRCUVhGRExFOUJRWEpETEVOQlJFRTdhVUpCUVdRc1RVRkZUenRCUVVOSUxEaENRVUZWTEdOQlFXTXNUVUZCWkN4RFFVRnhRaXhOUVVGeVFpeEZRVUUyUWl4aFFVRTNRaXhEUVVGV0xFTkJSRWM3YVVKQlJsQTdPMEZCVFVFc2IwSkJRVWtzWVVGQllTeFJRVUZSTEZWQlFWSXNRMEZXTWtNN08wRkJXVFZFTEc5Q1FVRkpMR05CUVdNc1dVRkJXU3hQUVVGYUxFVkJRWEZDTzBGQlEyNURMQ3RDUVVGWExGbEJRVmdzUTBGQmQwSXNUMEZCZUVJc1JVRkJhVU1zVDBGQmFrTXNSVUZFYlVNN2FVSkJRWFpET3p0QlFVbEJMRzlDUVVGSkxFTkJRVU1zVVVGQlJDeEZRVUZYTzBGQlExZ3NhME5CUVdNc1QwRkJaQ3hGUVVGMVFpeFRRVUYyUWl4RlFVUlhPMmxDUVVGbU96dEJRVWxCTEhWQ1FVRlBMRTlCUVZBc1EwRndRalJFTzJGQlFXaEZPenRCUVhWQ1FTeHhRa0ZCVXl4VlFVRlVMRU5CUVc5Q0xFOUJRWEJDTEVWQlFUWkNMRk5CUVRkQ0xFVkJRWGRETEV0QlFYaERMRVZCUVN0RExHRkJRUzlETEVWQlFUaEVPMEZCUXpGRUxHOUNRVUZKTEdGQlFXRXNVVUZCVVN4VlFVRlNMRU5CUkhsRE8wRkJSVEZFTEc5Q1FVRkpMRlZCUVZVc1kwRkJZeXhOUVVGa0xFTkJRWEZDTEV0QlFYSkNMRVZCUVRSQ0xHRkJRVFZDTEVOQlFWWXNRMEZHYzBRN08wRkJTVEZFTEc5Q1FVRkpMR05CUVdNc1dVRkJXU3hQUVVGYUxFVkJRWEZDTzBGQlEyNURMQ3RDUVVGWExGbEJRVmdzUTBGQmQwSXNUMEZCZUVJc1JVRkJhVU1zVDBGQmFrTXNSVUZFYlVNN2FVSkJRWFpET3p0QlFVbEJMSFZDUVVGUExFOUJRVkFzUTBGU01FUTdZVUZCT1VRN08wRkJWMEVzY1VKQlFWTXNZVUZCVkN4RFFVRjFRaXhQUVVGMlFpeEZRVUZuUXl4RFFVRm9ReXhGUVVGdFF6dEJRVU12UWl4dlFrRkJTU3hQUVVGUExFVkJRVVVzVDBGQlJpeExRVUZqTEZWQlFYSkNMRWxCUVcxRExGTkJRVk1zUTBGQlZDeERRVUZ1UXl4RlFVRm5SRHRCUVVOb1JDeHpRa0ZCUlN4UFFVRkdMRU5CUVZVc1QwRkJWaXhGUVVSblJEdHBRa0ZCY0VRN1lVRkVTanM3UVVGTlFTeHhRa0ZCVXl4bFFVRlVMRU5CUVhsQ0xFOUJRWHBDTEVWQlFXdERMRXRCUVd4RExFVkJRWGxETzBGQlEzSkRMRzlDUVVGSkxHRkJRV0VzVVVGQlVTeFZRVUZTTEVOQlJHOUNPMEZCUlhKRExHOUNRVUZKTEZOQlFWTXNSVUZCVkN4RFFVWnBRenRCUVVkeVF5eHZRa0ZCU1N4SlFVRktMRU5CU0hGRE8wRkJTWEpETEc5Q1FVRkpMRTFCUVVvc1EwRktjVU03UVVGTGNrTXNiMEpCUVVrc1RVRkJTaXhEUVV4eFF6czdRVUZQY2tNc2NVSkJRVXNzU1VGQlNTeEpRVUZKTEVOQlFVb3NSVUZCVHl4SlFVRkpMRTFCUVUwc1QwRkJUaXhEUVVGakxFMUJRV1FzUlVGQmMwSXNSMEZCTVVNc1JVRkJLME03UVVGRE0wTXNOa0pCUVZNc1RVRkJUU3hQUVVGT0xFTkJRV01zUTBGQlpDeERRVUZVTEVOQlJESkRPMEZCUlRORExESkNRVUZQTEZkQlFWY3NUMEZCVHl4SlFVRlFMRU5CUVd4Q0xFTkJSakpETzBGQlJ6TkRMSGRDUVVGSkxFOUJRVThzUjBGQlVDeEZRVUZaTzBGQlExb3NLMEpCUVU4c1QwRkJUeXhIUVVGUUxFTkJRVkFzUjBGQmNVSXNTVUZCY2tJc1EwRkVXVHR4UWtGQmFFSTdRVUZIUVN3MFFrRkJVU3hYUVVGU0xFTkJRVzlDTEVsQlFYQkNMRVZCVGpKRE8ybENRVUV2UXpzN1FVRlRRU3h2UWtGQlNTeFRRVUZUTEZkQlFWY3NUVUZCV0N4RFFXaENkMEk3UVVGcFFuSkRMSEZDUVVGTExFbEJRVWtzU1VGQlNTeERRVUZLTEVWQlFVOHNTVUZCU1N4TlFVRk5MRTlCUVU0c1EwRkJZeXhOUVVGa0xFVkJRWE5DTEVkQlFURkRMRVZCUVN0RE8wRkJRek5ETERaQ1FVRlRMRTFCUVUwc1QwRkJUaXhEUVVGakxFTkJRV1FzUTBGQlZDeERRVVF5UXp0QlFVVXpReXd5UWtGQlR5eFBRVUZQTEU5QlFVOHNSMEZCVUN4RFFVRmtPenRCUVVZeVF5d3lRa0ZKTTBNc1EwRkJVU3haUVVGU0xFTkJRWEZDTEVsQlFYSkNMRVZCUVRKQ0xFOUJRVThzUlVGQlVDeEpRVUZoTEZGQlFXSXNSMEZCZDBJc1NVRkJlRUlzUjBGQkswSXNWMEZCVnl4UFFVRlBMRVZCUVZBc1EwRkJNVU1zUTBGQk0wSXNRMEZLTWtNN2FVSkJRUzlETzJGQmFrSktPenRCUVhsQ1FTeHhRa0ZCVXl4WFFVRlVMRU5CUVhGQ0xFOUJRWEpDTEVWQlFUaENMRTlCUVRsQ0xFVkJRWFZETzBGQlEyNURMRzlDUVVGSkxGZEJRVmNzVDBGQldDeEpRVUZ6UWl4WlFVRlpMRTlCUVZvc1NVRkJkVUlzVVVGQlVTeFZRVUZTTEVWQlFXOUNPMEZCUTJwRkxEUkNRVUZSTEZWQlFWSXNRMEZCYlVJc1dVRkJia0lzUTBGQlowTXNUMEZCYUVNc1JVRkJlVU1zVDBGQmVrTXNSVUZFYVVVN2FVSkJRWEpGT3p0QlFVbEJMSFZDUVVGUExFOUJRVkFzUTBGTWJVTTdZVUZCZGtNN1UwRnFTbFVzUlVGNVNsSXNSVUZCUXl4NVFrRkJkMElzUlVGQmVFSXNSVUZCTWtJc2MwSkJRWEZDTEVWQlFYSkNMRVZCUVhkQ0xITkNRVUZ4UWl4RlFVRnlRaXhGUVVGM1FpeHRRa0ZCYTBJc1JVRkJiRUlzUlVGNlNuSkZMRU5CUVVnc1JVRjVTaXRHTEVsQlFVY3NRMEZCUXl4VlFVRlRMRTlCUVZRc1JVRkJhVUlzVFVGQmFrSXNSVUZCZDBJc1QwRkJlRUlzUlVGQlowTTdRVUZEZWtrc1owSkJRVWtzVjBGQlZ5eFJRVUZSTEdsQ1FVRlNMRU5CUVZnc1EwRkVjVWs3UVVGRmVra3NaMEpCUVVrc1ZVRkJWU3hSUVVGUkxGbEJRVklzUTBGQlZpeERRVVp4U1RzN1FVRkpla2tzWjBKQlFVa3NVMEZCVXl4UlFVRlJMR3RDUVVGU0xFTkJRVlFzUTBGS2NVazdRVUZMZWtrc1owSkJRVWtzVjBGQlZ5eFJRVUZSTEdGQlFWSXNRMEZCV0N4RFFVeHhTVHRCUVUxNlNTeG5Ra0ZCU1N4VlFVRlZMRkZCUVZFc1dVRkJVaXhEUVVGV0xFTkJUbkZKTzBGQlQzcEpMRzFDUVVGUExFOUJRVkFzUjBGQmFVSXNTMEZCYWtJc1EwRlFlVWs3TzBGQlUzcEpMSEZDUVVGVExFdEJRVlFzUTBGQlpTeFJRVUZtTEVWQlFYbENMRTlCUVhwQ0xFVkJRV3RETEdGQlFXeERMRVZCUVdsRU8wRkJRemRETEdkRFFVRm5RaXhwUWtGQmFVSXNSVUZCYWtJc1EwRkVOa0k3UVVGRk4wTXNPRUpCUVdNc1MwRkJaQ3hIUVVGelFpeGpRVUZqTEV0QlFXUXNTVUZCZFVJc1kwRkJZeXhMUVVGa0xFdEJRWGRDTEV0QlFYaENMRWRCUTNaRExHTkJRV01zUzBGQlpDeEhRVU5CTEdOQlJtZENMRU5CUm5WQ08wRkJTemRETERoQ1FVRmpMRTFCUVdRc1IwRkJkVUlzWTBGQll5eE5RVUZrTEVsQlFYZENMRTFCUVhoQ0xFTkJUSE5DT3p0QlFVODNReXgxUWtGQlR5eGpRVUZqTEV0QlFXUXNRMEZCYjBJc1VVRkJjRUlzUlVGQk9FSXNUMEZCT1VJc1JVRkJkVU1zWVVGQmRrTXNRMEZCVUN4RFFWQTJRenRoUVVGcVJEczdRVUZWUVN4eFFrRkJVeXhqUVVGVUxFTkJRWGRDTEZGQlFYaENMRVZCUVd0RExFOUJRV3hETEVWQlFUSkRMR0ZCUVRORExFVkJRVEJFTzBGQlEzUkVMRzlDUVVGSkxGVkJRVlVzWVVGQllTeFBRVUZpTEVOQlFWWXNRMEZFYTBRN08wRkJSM1JFTEc5Q1FVRkpMRkZCUVZFc1RVRkJVaXhMUVVGdFFpeERRVUZ1UWl4RlFVRnpRanRCUVVOMFFpd3lRa0ZCVHl4UlFVRlFMRU5CUkhOQ08ybENRVUV4UWpzN1FVRkpRU3h2UWtGQlNTeFJRVUZSTEZOQlFWTXNVVUZCVkN4RlFVRnRRaXhSUVVGUkxFTkJRVklzUlVGQlZ5eFBRVUU1UWl4RFFVRlNMRU5CVUd0RU8wRkJVWFJFTEc5Q1FVRkpMR2RDUVVGblFpeFRRVUZUTEdGQlFWUXNRMEZTYTBNN08wRkJWWFJFTEc5Q1FVRkpMRU5CUVVNc1kwRkJZeXhSUVVGa0xFbEJRVEJDTEd0Q1FVRnJRaXhSUVVGc1FpeEZRVUUwUWp0QlFVTjJSQ3hyUTBGQll5eFJRVUZrTEVkQlFYbENMR0ZCUVhwQ0xFTkJSSFZFTzJsQ1FVRXpSRHM3UVVGSlFTeHhRa0ZCU3l4SlFVRkpMRWxCUVVrc1EwRkJTaXhGUVVGUExFbEJRVWtzVVVGQlVTeE5RVUZTTEVWQlFXZENMRWRCUVhCRExFVkJRWGxETzBGQlEzSkRMSGRDUVVGSkxGbEJRVmtzVVVGQlVTeERRVUZTTEVOQlFWb3NRMEZFYVVNN1FVRkZja01zSzBKQlFWY3NWMEZCVnl4UlFVRllMRVZCUTFBc1RVRkJUU3hUUVVGT0xFTkJSRThzUlVGRlVDeFJRVUZSTEZOQlFWSXNRMEZHVHl4RlFVZFFMR0ZCU0U4c1EwRkJXQ3hEUVVaeFF6dHBRa0ZCZWtNN08wRkJVVUVzZFVKQlFVOHNVVUZCVUN4RFFYUkNjMFE3WVVGQk1VUTdPMEZCZVVKQkxIRkNRVUZUTEZWQlFWUXNRMEZCYjBJc1VVRkJjRUlzUlVGQk9FSXNUMEZCT1VJc1JVRkJkVU1zVTBGQmRrTXNSVUZCYTBRc1lVRkJiRVFzUlVGQmFVVTdRVUZETjBRc2IwSkJRVWtzUTBGQlF5eFBRVUZFTEVWQlFWVTdRVUZEVml3eVFrRkJUeXhSUVVGUUxFTkJSRlU3YVVKQlFXUTdPMEZCU1VFc2IwSkJRVWtzVDBGQlNpeERRVXcyUkRzN1FVRlBOMFFzYjBKQlFVa3NVVUZCVVN4VFFVRlNMRU5CUVVvc1JVRkJkMEk3UVVGRGNFSXNlVUpCUVVzc1NVRkJTU3hKUVVGSkxFTkJRVW9zUlVGQlR5eEpRVUZKTEZWQlFWVXNUVUZCVml4RlFVRnJRaXhIUVVGMFF5eEZRVUV5UXp0QlFVTjJReXhyUTBGQlZTeFJRVUZSTEZWQlFWVXNRMEZCVml4RFFVRlNMRVZCUVhOQ0xFOUJRWFJDTEVWQlFTdENMR0ZCUVM5Q0xFTkJRVllzUTBGRWRVTTdPMEZCUjNaRExEUkNRVUZKTEZsQlFWa3NVVUZCV2l4RlFVRnpRanRCUVVOMFFpeDFRMEZCVnl4UFFVRllMRU5CUkhOQ08zbENRVUV4UWp0eFFrRklTanRwUWtGRVNpeE5RVkZQTzBGQlEwZ3NPRUpCUVZVc1VVRkJVU3hUUVVGU0xFVkJRVzFDTEU5QlFXNUNMRVZCUVRSQ0xHRkJRVFZDTEVOQlFWWXNRMEZFUnpzN1FVRkhTQ3gzUWtGQlNTeFpRVUZaTEZGQlFWb3NSVUZCYzBJN1FVRkRkRUlzYlVOQlFWY3NUMEZCV0N4RFFVUnpRanR4UWtGQk1VSTdhVUpCV0VvN08wRkJaMEpCTEhWQ1FVRlBMRkZCUVZBc1EwRjJRalpFTzJGQlFXcEZPenRCUVRCQ1FTeHhRa0ZCVXl4WlFVRlVMRU5CUVhOQ0xFOUJRWFJDTEVWQlFTdENPMEZCUXpOQ0xHOUNRVUZKTEZWQlFWVXNSVUZCVml4RFFVUjFRanM3UVVGSE0wSXNjVUpCUVVzc1NVRkJTU3hIUVVGS0xFbEJRVmNzVDBGQmFFSXNSVUZCZVVJN1FVRkRja0lzZDBKQlFVa3NVVUZCVVN4SFFVRlNMRVZCUVdFN1FVRkRZaXhuUTBGQlVTeEpRVUZTTEVOQlFXRXNUMEZCVHl4SFFVRlFMRU5CUVdJc1JVRkVZVHR4UWtGQmFrSTdhVUpCUkVvN08wRkJUVUVzZFVKQlFVOHNUMEZCVUN4RFFWUXlRanRoUVVFdlFqdFRRWFJGZVVjc1JVRnJSblpITEVWQlFVTXNiMEpCUVcxQ0xFVkJRVzVDTEVWQlFYTkNMR1ZCUVdNc1JVRkJaQ3hGUVVGcFFpeGpRVUZoTEVWQlFXSXNSVUZCWjBJc2JVSkJRV3RDTEVWQlFXeENMRVZCUVhGQ0xHTkJRV0VzUlVGQllpeEZRV3hHZVVJc1EwRkJTQ3hGUVd0R1NpeEpRVUZITEVOQlFVTXNWVUZCVXl4UFFVRlVMRVZCUVdsQ0xFMUJRV3BDTEVWQlFYZENMRTlCUVhoQ0xFVkJRV2RETzBGQlEzSkpMR2RDUVVGSkxGZEJRVmNzVVVGQlVTeDFRa0ZCVWl4RFFVRllMRU5CUkdsSk96dEJRVWR5U1N4dFFrRkJUeXhQUVVGUUxFZEJRV2xDTEZsQlFXcENMRU5CU0hGSk96dEJRVXR5U1N4eFFrRkJVeXhaUVVGVUxFTkJRWE5DTEVOQlFYUkNMRVZCUVhsQ0xFTkJRWHBDTEVWQlFUUkNPMEZCUTNoQ0xHOUNRVUZKTEZOQlFWTXNRMEZCVkN4TFFVRmxMRk5CUVZNc1EwRkJWQ3hEUVVGbUxFVkJRVFJDTzBGQlF6VkNMSGRDUVVGSkxGVkJRVlVzUTBGQlZpeEpRVUZsTEZWQlFWVXNRMEZCVml4RlFVRmhPMEZCUXpWQ0xDdENRVUZQTEVWQlFVVXNSVUZCUml4TFFVRlRMRVZCUVVVc1JVRkJSaXhEUVVSWk8zRkNRVUZvUXl4TlFVVlBPMEZCUTBnc0swSkJRVThzUlVGQlJTeEpRVUZHTEV0QlFWY3NSVUZCUlN4SlFVRkdMRU5CUkdZN2NVSkJSbEE3YVVKQlJFbzdPMEZCVVVFc2RVSkJRVThzUzBGQlVDeERRVlIzUWp0aFFVRTFRanRUUVV4eFJ5eEZRV2xDYmtjc1JVRkJReXg1UWtGQmQwSXNSVUZCZUVJc1JVRnFRbWxITEVOQlFVZ3NSVUZwUW1wRkxFbEJRVWNzUTBGQlF5eFZRVUZUTEU5QlFWUXNSVUZCYVVJc1RVRkJha0lzUlVGQmQwSXNUMEZCZUVJc1JVRkJaME03UVVGRGNFVXNlVUpCUkc5Rk96dEJRVWR3UlN4blFrRkJTU3hWUVVGVkxGRkJRVkVzVlVGQlVpeERRVUZXTEVOQlNHZEZPenRCUVV0d1JTeHRRa0ZCVHl4UFFVRlFMRWRCUVdsQ0xFMUJRV3BDTEVOQlRHOUZPenRCUVU5d1JTeHhRa0ZCVXl4TlFVRlVMRU5CUVdkQ0xFdEJRV2hDTEVWQlFYVkNPMEZCUTI1Q0xHOUNRVUZKTEVWQlFVVXNaMEpCUVdkQ0xFMUJRV2hDTEVOQlFVWXNSVUZCTWtJN1FVRkRNMElzTWtKQlFVOHNTVUZCU1N4TlFVRktMRU5CUVZjc1MwRkJXQ3hEUVVGUUxFTkJSREpDTzJsQ1FVRXZRanM3UVVGSlFTeHhRa0ZCU3l4TFFVRk1MRWRCUVdFc1MwRkJZaXhEUVV4dFFqdGhRVUYyUWpzN1FVRlJRU3h0UWtGQlR5eFRRVUZRTEVOQlFXbENMRWxCUVdwQ0xFZEJRWGRDTEZWQlFWVXNTVUZCVml4RlFVRm5RaXhaUVVGb1FpeEZRVUU0UWp0QlFVTnNSQ3h2UWtGQlNTeExRVUZMTEZGQlFWRXNTVUZCVWl4RFFVRk1MRU5CUkRoRE8wRkJSV3hFTEc5Q1FVRkpMRmRCUVZjc1lVRkJZU3hOUVVGaUxFTkJRVzlDTEVOQlFYQkNMRU5CUVZnc1EwRkdPRU03TzBGQlNXeEVMRzFDUVVGSExGRkJRVWdzU1VGQlpTeExRVUZMTEV0QlFVd3NRMEZLYlVNN1lVRkJPVUlzUTBGbU5FTTdPMEZCYzBKd1JTeHRRa0ZCVHl4VFFVRlFMRU5CUVdsQ0xFMUJRV3BDTEVkQlFUQkNMRlZCUVZNc1NVRkJWQ3hGUVVGbExGbEJRV1lzUlVGQk5rSTdRVUZEYmtRc2IwSkJRVWtzUzBGQlN5eFJRVUZSTEVsQlFWSXNRMEZCVEN4RFFVUXJRenRCUVVWdVJDeHZRa0ZCU1N4WFFVRlhMR0ZCUVdFc1RVRkJZaXhEUVVGdlFpeERRVUZ3UWl4RFFVRllMRU5CUml0RE96dEJRVWx1UkN4dFFrRkJSeXhSUVVGSUxFbEJRV1VzVTBGQlppeERRVXB0UkR0aFFVRTNRaXhEUVhSQ01FTTdVMEZCYUVNc1JVRTJRbXhETEVWQlFVTXNXVUZCVnl4RFFVRllMRVZCTjBKblF5eERRVUZJTEVWQk5rSmtMRWxCUVVjc1EwRkJReXhWUVVGVExFOUJRVlFzUlVGQmFVSXNUVUZCYWtJc1JVRkJkMElzVDBGQmVFSXNSVUZCWjBNN1FVRkRkRVFzZVVKQlJITkVPenRCUVVkMFJDeHRRa0ZCVHl4UFFVRlFMRWRCUVdsQ0xGZEJRV3BDTEVOQlNITkVPenRCUVV0MFJDeHhRa0ZCVXl4WFFVRlVMRU5CUVhGQ0xFdEJRWEpDTEVWQlFUUkNPMEZCUTNoQ0xHOUNRVUZKTEVWQlFVVXNaMEpCUVdkQ0xGZEJRV2hDTEVOQlFVWXNSVUZCWjBNN1FVRkRhRU1zTWtKQlFVOHNTVUZCU1N4WFFVRktMRU5CUVdkQ0xFdEJRV2hDTEVOQlFWQXNRMEZFWjBNN2FVSkJRWEJET3p0QlFVbEJMSEZDUVVGTExFdEJRVXdzUjBGQllTeExRVUZpTEVOQlRIZENPMkZCUVRWQ096dEJRVkZCTEhkQ1FVRlpMRk5CUVZvc1EwRkJjMElzU1VGQmRFSXNSMEZCTmtJc1ZVRkJWU3hKUVVGV0xFVkJRV2RDTEZsQlFXaENMRVZCUVRoQ08wRkJRM1pFTEc5Q1FVRkpMRXRCUVVzc1dVRkJUQ3hOUVVGMVFpeExRVUZMTEV0QlFVd3NSVUZCV1R0QlFVTnVReXg1UWtGQlN5eFpRVUZNTEVsQlFYRkNMRXRCUVVzc1MwRkJUQ3hEUVVSak8ybENRVUYyUXp0aFFVUjVRaXhEUVdKNVFqdFRRVUZvUXl4RlFXMUNjRUlzUlVGdVFtMUNMRU5CUVVnc1JVRnRRbG9zU1VGQlJ5eERRVUZETEZWQlFWTXNUMEZCVkN4RlFVRnBRaXhOUVVGcVFpeEZRVUYzUWl4UFFVRjRRaXhGUVVGblF6dEJRVU14UXl4NVFrRkVNRU03TzBGQlJ6RkRMR2RDUVVGSkxGVkJRVlVzVVVGQlVTeFpRVUZTTEVOQlFWWXNRMEZJYzBNN08wRkJTekZETEdkQ1FVRkpMRkZCUVZFc1VVRkJVU3h0UWtGQlVpeERRVUZTTEVOQlRITkRPMEZCVFRGRExHZENRVUZKTEZGQlFWRXNVVUZCVVN4dFFrRkJVaXhEUVVGU0xFTkJUbk5ETzBGQlR6RkRMR2RDUVVGSkxGVkJRVlVzVVVGQlVTeHRRa0ZCVWl4RFFVRldMRU5CVUhORE8wRkJVVEZETEdkQ1FVRkpMRlZCUVZVc1VVRkJVU3h0UWtGQlVpeERRVUZXTEVOQlVuTkRPMEZCVXpGRExHZENRVUZKTEZkQlFWY3NVVUZCVVN4dlFrRkJVaXhEUVVGWUxFTkJWSE5ETzBGQlZURkRMR2RDUVVGSkxGTkJRVk1zVVVGQlVTeHRRa0ZCVWl4RFFVRlVMRU5CVm5ORE8wRkJWekZETEdkQ1FVRkpMRmRCUVZjc1VVRkJVU3h0UWtGQlVpeERRVUZZTEVOQldITkRPenRCUVdFeFF5eG5Ra0ZCU1N4WFFVRlhMRkZCUVZFc1owSkJRVklzUTBGQldDeERRV0p6UXp0QlFXTXhReXhuUWtGQlNTeGpRVUZqTEZGQlFWRXNNRUpCUVZJc1EwRkJaQ3hEUVdSelF6dEJRV1V4UXl4blFrRkJTU3hUUVVGVExGRkJRVkVzYjBKQlFWSXNRMEZCVkN4RFFXWnpRenM3UVVGcFFqRkRMRzFDUVVGUExFOUJRVkFzUjBGQmFVSXNRMEZCYWtJc1EwRnFRakJET3p0QlFXMUNNVU1zY1VKQlFWTXNRMEZCVkN4RFFVRlhMRTlCUVZnc1JVRkJiMElzVlVGQmNFSXNSVUZCWjBNc1VVRkJhRU1zUlVGQk1FTTdRVUZEZEVNc2IwSkJRVWtzWVVGQllTeEZRVUZpTEVOQlJHdERPMEZCUlhSRExHOUNRVUZKTEVkQlFVb3NSVUZCVXl4TFFVRlVMRVZCUVdkQ0xFZEJRV2hDTEVWQlFYRkNMRk5CUVhKQ0xFTkJSbk5ET3p0QlFVbDBReXh2UWtGQlNTeERRVUZETEZGQlFVUXNTVUZCWVN4WFFVRlhMRlZCUVZnc1EwRkJZaXhGUVVGeFF6dEJRVU55UXl3clFrRkJWeXhWUVVGWUxFTkJSSEZETzBGQlJYSkRMRFJDUVVGUkxFVkJRVklzUTBGR2NVTTdhVUpCUVhwRE96dEJRVXRCTEhkQ1FVRlJMRk5CUVZNc1ZVRkJWQ3hKUVVGMVFpeEZRVUYyUWl4RFFWUTRRanRCUVZWMFF5eHpRa0ZCVFN4VFFVRlRMRTlCUVZRc1JVRkJhMElzUzBGQmJFSXNRMEZCVGpzN08wRkJWbk5ETEc5Q1FXRnNReXhOUVVGTkxHTkJRVTRzUTBGQmNVSXNTMEZCY2tJc1EwRkJTaXhGUVVGcFF6dEJRVU0zUWl3d1FrRkJUU3hOUVVGTkxFZEJRVTRzUTBGRWRVSTdRVUZGTjBJc01FSkJRVTBzUjBGQlRpeEhRVUZaTEZOQlFWb3NRMEZHTmtJN2FVSkJRV3BET3pzN1FVRmljME1zYjBKQmJVSnNReXhOUVVGTkxHTkJRVTRzUTBGQmNVSXNWMEZCY2tJc1EwRkJTaXhGUVVGMVF6dEJRVU51UXl4blEwRkJXU3hOUVVGTkxGTkJRVTRzUTBGRWRVSTdRVUZGYmtNc01FSkJRVTBzVTBGQlRpeEhRVUZyUWl4VFFVRnNRaXhEUVVadFF6dHBRa0ZCZGtNN096dEJRVzVDYzBNc2IwSkJlVUpzUXl4UlFVRlJMRTlCUVZJc1NVRkRRU3hEUVVGRExGTkJRVVFzU1VGRFFTeE5RVUZOTEdOQlFVNHNRMEZCY1VJc1QwRkJja0lzUTBGR1FTeEpRVWRCTEUxQlFVMHNTMEZCVGl4TFFVRm5RaXhUUVVGb1FpeEpRVU5CTEVOQlFVTXNUMEZCVHl4TlFVRk5MRXRCUVU0c1EwRkJVaXhGUVVOR08wRkJRMFVzTUVKQlFVMHNTMEZCVGl4SFFVRmpMRmxCUVZrc1RVRkJUU3hMUVVGT0xFTkJRVEZDTEVOQlJFWTdhVUpCVEVZN08wRkJVMEVzYjBOQlFXOUNMRXRCUVhCQ0xFVkJiRU56UXpzN1FVRnZRM1JETEc5Q1FVRkpMR0ZCUVdFc1UwRkJZaXhKUVVFd1FpeGhRVUZoTEVsQlFXSXNSVUZCYlVJN1FVRkROME1zTmtKQlFWTXNVVUZCVkN4RlFVRnRRaXhWUVVGdVFpeEZRVUVyUWl4SFFVRXZRaXhGUVVGdlF5eExRVUZ3UXl4RlFVUTJRenRwUWtGQmFrUTdPMEZCUzBFc2RVSkJRVThzU1VGQlNTeExRVUZLTEVOQlFWVXNSMEZCVml4RlFVRmxMRXRCUVdZc1JVRkJjMElzVlVGQmRFSXNSVUZCYTBNc1IwRkJiRU1zUlVGQmRVTXNVMEZCZGtNc1EwRkJVQ3hEUVhwRGMwTTdZVUZCTVVNN08wRkJORU5CTEhGQ1FVRlRMRkZCUVZRc1EwRkJhMElzUTBGQmJFSXNSVUZCY1VJc1ZVRkJja0lzUlVGQmFVTXNSMEZCYWtNc1JVRkJjME1zUzBGQmRFTXNSVUZCTmtNN1FVRkRla01zYjBKQlFVa3NUMEZCVHl4RFFVRlFMRXRCUVdFc1VVRkJZaXhGUVVGMVFqdEJRVU4yUWl3clFrRkJWeXhKUVVGWUxFTkJRV2RDTEVsQlFVa3NTMEZCU2l4RFFVRlZMRU5CUVZZc1EwRkJhRUlzUlVGRWRVSTdhVUpCUVROQ0xFMUJSVThzU1VGQlNTeFBRVUZQTEVOQlFWQXNTMEZCWVN4UlFVRmlMRVZCUVhWQ08wRkJRemxDTEN0Q1FVRlhMRWxCUVZnc1EwRkJaMElzU1VGQlNTeExRVUZLTEVOQlFWVXNUMEZCVHl4RFFVRlFMRU5CUVZZc1EwRkJhRUlzUlVGRU9FSTdhVUpCUVROQ0xFMUJSVUVzU1VGQlNTeFJRVUZSTEVOQlFWSXNRMEZCU2l4RlFVRm5RanRCUVVOdVFpd3JRa0ZCVnl4SlFVRllMRU5CUVdkQ0xFTkJRV2hDTEVWQlJHMUNPMmxDUVVGb1FpeE5RVVZCTEVsQlFVa3NVVUZCVVN4RFFVRlNMRU5CUVVvc1JVRkJaMEk3UVVGRGJrSXNlVUpCUVVzc1NVRkJTU3hKUVVGSkxFTkJRVW9zUlVGQlR5eEpRVUZKTEVWQlFVVXNUVUZCUml4RlFVRlZMRWRCUVRsQ0xFVkJRVzFETzBGQlF5OUNMR2xEUVVGVExFVkJRVVVzUTBGQlJpeERRVUZVTEVWQlFXVXNWVUZCWml4RlFVRXlRaXhIUVVFelFpeEZRVUZuUXl4TFFVRm9ReXhGUVVRclFqdHhRa0ZCYmtNN2FVSkJSRWNzVFVGSlFTeEpRVUZKTEUxQlFVMHNTVUZCVGl4SlFVRmpMRTFCUVUwc1UwRkJUaXhGUVVGcFFqdEJRVU4wUXl3eVFrRkVjME03YVVKQlFXNURMRTFCUlVFN1FVRkRTQ3d3UWtGQlRTeDVRa0ZCZVVJN1FVRkRNMElzZFVOQlFXVXNRMEZCWmp0QlFVTkJMSEZEUVVGaE8wRkJRMVFzY1VOQlFWTXNSMEZCVkR0QlFVTkJMSGREUVVGWkxFdEJRVm83ZVVKQlJrbzdjVUpCUmtVc1EwRkJUaXhEUVVSSE8ybENRVVpCTzJGQldGZzdPMEZCZDBKQkxIRkNRVUZUTEcxQ1FVRlVMRU5CUVRaQ0xFdEJRVGRDTEVWQlFXOURPMEZCUTJoRExIRkNRVUZMTEVsQlFVa3NVVUZCU2l4SlFVRm5RaXhMUVVGeVFpeEZRVUUwUWp0QlFVTjRRaXgzUWtGQlNTeE5RVUZOTEdOQlFVNHNRMEZCY1VJc1VVRkJja0lzUTBGQlNpeEZRVUZ2UXp0QlFVTm9ReXcwUWtGQlNTeFJRVUZSTEUxQlFVMHNVVUZCVGl4RFFVRlNMRU5CUkRSQ096dEJRVWRvUXl3MFFrRkJTU3hQUVVGUExFdEJRVkFzUTBGQlNpeEZRVUZ0UWp0QlFVTm1MSEZEUVVSbE8zbENRVUZ1UWpzN1FVRkpRU3cwUWtGQlNTeFRRVUZUTEUxQlFWUXNRMEZCWjBJc1EwRkJhRUlzUlVGQmJVSXNRMEZCYmtJc1RVRkJNRUlzUzBGQk1VSXNSVUZCYVVNN08wRkJSV3BETEd0RFFVRk5MRkZCUVU0c1NVRkJhMElzVDBGQlR5eExRVUZRTEVOQlFXeENMRU5CUm1sRE8zbENRVUZ5UXp0eFFrRlFTanRwUWtGRVNqdGhRVVJLT3p0QlFXbENRU3h4UWtGQlV5eFBRVUZVTEVOQlFXbENMRU5CUVdwQ0xFVkJRVzlDTzBGQlEyaENMSFZDUVVGUExGRkJRVkVzUTBGQlVpeExRVUZqTEZGQlFWRXNRMEZCVWl4RFFVRmtMRWxCUVRSQ0xGTkJRVk1zUTBGQlZDeERRVUUxUWl4SlFVRXlReXhUUVVGVExFTkJRVlFzUTBGQk0wTXNRMEZFVXp0aFFVRndRanM3UVVGSlFTeHhRa0ZCVXl4VlFVRlVMRU5CUVc5Q0xFTkJRWEJDTEVWQlFYVkNPMEZCUTI1Q0xIVkNRVUZQTEU5QlFVOHNRMEZCVUN4TFFVRmhMRkZCUVdJc1NVRkJlVUlzVVVGQlVTeERRVUZTTEVOQlFYcENMRWxCUVhWRExGRkJRVkVzUTBGQlVpeERRVUYyUXl4RFFVUlpPMkZCUVhaQ096dEJRVWxCTEhGQ1FVRlRMSGRDUVVGVUxFTkJRV3RETEVsQlFXeERMRVZCUVhkRE8wRkJRM0JETEc5Q1FVRkpMRTFCUVUwc1NVRkJTU3hMUVVGS0xFVkJRVTRzUTBGRVowTTdPMEZCUjNCRExHOUNRVUZKTEVsQlFVb3NSMEZCVnl4blJFRkJXQ3hEUVVodlF6dEJRVWx3UXl4dlFrRkJTU3hQUVVGS0xFZEJRV01zT0VOQlExWXNjVVJCUkZVc1IwRkZWaXhSUVVaVkxFZEJSMVlzV1VGQldTeExRVUZMTEdGQlFVd3NRMEZJUml4SFFVbFdMRXRCU2xVc1IwRkxWaXgzUWtGTVZTeEhRVTFXTEZsQlFWa3NTMEZCU3l4WFFVRk1MRU5CVGtZc1EwRktjMEk3UVVGWGFFTXNkVUpCUTBFc2QwUkJSRUVzUTBGWVowTTdRVUZoY0VNc2IwSkJRVWtzWVVGQlNpeEhRVUZ2UWl4TFFVRkxMR0ZCUVV3c1EwRmlaMEk3UVVGamNFTXNiMEpCUVVrc1YwRkJTaXhIUVVGclFpeExRVUZMTEZkQlFVd3NRMEZrYTBJN08wRkJaMEp3UXl4MVFrRkJUeXhIUVVGUUxFTkJhRUp2UXp0aFFVRjRRenM3UVVGdFFrRXNjVUpCUVZNc1YwRkJWQ3hEUVVGeFFpeEhRVUZ5UWl4RlFVRXdRanRCUVVOMFFpeHZRa0ZCU1R0QlFVTkJMREpDUVVGUExFdEJRVXNzVTBGQlRDeERRVUZsTEVkQlFXWXNSVUZCYjBJc1NVRkJjRUlzUlVGQk1FSXNUVUZCTVVJc1EwRkJVQ3hEUVVSQk8ybENRVUZLTEVOQlJVVXNUMEZCVHl4RFFVRlFMRVZCUVZVN1FVRkRVaXd5UWtGQlR5eFBRVUZQTEVkQlFWQXNRMEZCVUN4RFFVUlJPMmxDUVVGV08yRkJTRTQ3VTBGdVNWVXNSVUV5U1ZJc1JVRkJReXh4UWtGQmIwSXNSVUZCY0VJc1JVRkJkVUlzY1VKQlFXOUNMRVZCUVhCQ0xFVkJRWFZDTEhGQ1FVRnZRaXhGUVVGd1FpeEZRVUYxUWl4eFFrRkJiMElzUlVGQmNFSXNSVUZCZFVJc2MwSkJRWEZDTEVWQlFYSkNMRVZCUVhkQ0xIRkNRVUZ2UWl4RlFVRndRaXhGUVVGMVFpeHhRa0ZCYjBJc1JVRkJjRUlzUlVGQmRVSXNjMEpCUVhGQ0xFVkJRWEpDTEVWQlFYZENMRFJDUVVFeVFpeEZRVUV6UWl4RlFVRTRRaXhyUWtGQmFVSXNSVUZCYWtJc1JVRkJiMElzWTBGQllTeEZRVUZpTEVWQk0wbDBUeXhEUVVGSUxFVkJNa2t5VUN4SlFVRkhMRU5CUVVNc1ZVRkJVeXhQUVVGVUxFVkJRV2xDTEUxQlFXcENMRVZCUVhkQ0xFOUJRWGhDTEVWQlFXZERPMEZCUTNKVExIbENRVVJ4VXpzN1FVRkhjbE1zWjBKQlFVa3NVVUZCVVN4UlFVRlJMR1ZCUVZJc1EwRkJVaXhEUVVocFV6czdRVUZMY2xNc1owSkJRVWtzWlVGQlpTeHpRMEZCWml4RFFVeHBVenRCUVUxeVV5eG5Ra0ZCU1N4aFFVRmhMRTlCUVdJc1EwRk9hVk03TzBGQlVYSlRMRzFDUVVGUExFOUJRVkFzUjBGQmFVSXNVVUZCYWtJc1EwRlNjVk03TzBGQlZYSlRMSEZDUVVGVExGRkJRVlFzUTBGQmEwSXNSMEZCYkVJc1JVRkJkVUlzUzBGQmRrSXNSVUZCT0VJN1FVRkRNVUlzYjBKQlFVa3NRMEZCUXl4SFFVRkVMRVZCUVUwN1FVRkRUaXd5UWtGQlR5eExRVUZRTEVOQlJFMDdhVUpCUVZZN08wRkJTVUVzYjBKQlFVa3NUMEZCVHl4RFFVRkZMRTFCUVUwc1kwRkJUaXhEUVVGeFFpeEpRVUZ5UWl4RFFVRkdMRU5CVEdVN08wRkJUekZDTEc5Q1FVRkpMRmRCUVZjc1RVRkJUU3hIUVVGT0xFVkJRVmNzV1VGQldDeERRVUZZTEVOQlVITkNPMEZCVVRGQ0xHOUNRVUZKTEZWQlFWVXNTVUZCVml4RFFWSnpRanM3UVVGVk1VSXNiMEpCUVVrc1YwRkJWeXhKUVVGWUxFTkJRV2RDTEZOQlFWTXNRMEZCVkN4RFFVRm9RaXhEUVVGS0xFVkJRV3RETzBGQlF6bENMRGhDUVVGVkxFdEJRVllzUTBGRU9FSTdhVUpCUVd4RE96dEJRVWxCTEc5Q1FVRkpMRTlCUVVvc1JVRkJZU3hKUVVGaUxFVkJRVzFDTEVsQlFXNUNMRVZCUVhsQ0xFTkJRWHBDTEVOQlpEQkNPenRCUVdkQ01VSXNjVUpCUVVzc1NVRkJTU3hEUVVGS0xFVkJRVThzU1VGQlNTeFRRVUZUTEUxQlFWUXNSVUZCYVVJc1IwRkJha01zUlVGQmMwTTdRVUZEYkVNc01rSkJRVThzVTBGQlV5eERRVUZVTEVOQlFWQXNRMEZFYTBNN08wRkJSMnhETEhkQ1FVRkpMRU5CUVVNc1NVRkJSQ3hGUVVGUE8wRkJRMUFzYVVOQlJFODdjVUpCUVZnN08wRkJTVUVzTWtKQlFVOHNTMEZCU3l4TlFVRk1MRU5CUVZrc1EwRkJXaXhEUVVGUUxFTkJVR3RET3p0QlFWTnNReXgzUWtGQlNTeERRVUZETEU5QlFVUXNSVUZCVlR0QlFVTldMR3REUVVGVkxFbEJRVllzUTBGRVZUdHhRa0ZCWkN4TlFVVlBMRWxCUVVrc1UwRkJVeXhIUVVGVUxFVkJRV003UVVGRGNrSXNhME5CUVZVc1YwRkJWeXhGUVVGWUxFTkJSRmM3UVVGRmNrSXNaME5CUVZFc1NVRkJVaXhEUVVGaExFdEJRVXNzVTBGQlRDeERRVUZsTEVOQlFXWXNSVUZCYTBJc1MwRkJTeXhOUVVGTUxFTkJRUzlDTEVWQlJuRkNPM0ZDUVVGc1FpeE5RVWRCTEVsQlFVa3NVMEZCVXl4SFFVRlVMRWxCUVdkQ0xFbEJRV2hDTEVWQlFYTkNPMEZCUXpkQ0xEaENRVUZOTEVWQlFVNHNSMEZCVnl4TFFVRkxMRk5CUVV3c1EwRkJaU3hEUVVGbUxFVkJRV3RDTEV0QlFVc3NUVUZCVEN4RFFVRTNRaXhEUVVRMlFqdHhRa0ZCTVVJN2FVSkJaRmc3TzBGQmJVSkJMRzlDUVVGSkxFOUJRVW9zUlVGQllUdEJRVU5VTEhkQ1FVRkpMRTFCUVUwc1UwRkJUaXhGUVVGcFFqdEJRVU5xUWl4blEwRkJVU3hKUVVGU0xFTkJRV0VzVFVGQlRTeFRRVUZPTEVOQlFXSXNRMEZFYVVJN2NVSkJRWEpDT3p0QlFVbEJMREJDUVVGTkxGTkJRVTRzUjBGQmEwSXNVVUZCVVN4SlFVRlNMRU5CUVdFc1IwRkJZaXhEUVVGc1FpeERRVXhUTzJsQ1FVRmlPenRCUVZGQkxIVkNRVUZQTEUxQlFVMHNVMEZCVGl4SFFVRnJRaXhQUVVGc1FpeEhRVUUwUWl4UlFVRlJMRmRCUVZJc1JVRkJOVUlzUTBFelEyMUNPMkZCUVRsQ08xTkJWbkZSTEVWQmQwUnVVU3hGUVVGRExHbENRVUZuUWl4RFFVRm9RaXhGUVhoRWFWRXNRMEZCU0N4RlFYZEVNVThzU1VGQlJ5eERRVUZETEZWQlFWTXNUMEZCVkN4RlFVRnBRaXhOUVVGcVFpeEZRVUYzUWl4UFFVRjRRaXhGUVVGblF6dEJRVU16UkN4blFrRkJTU3hWUVVGVkxGRkJRVkVzV1VGQlVpeERRVUZXTEVOQlJIVkVPMEZCUlRORUxHZENRVUZKTEZWQlFWVXNVVUZCVVN4WlFVRlNMRU5CUVZZc1EwRkdkVVE3UVVGSE0wUXNaMEpCUVVrc1YwRkJWeXhSUVVGUkxHRkJRVklzUTBGQldDeERRVWgxUkR0QlFVa3pSQ3huUWtGQlNTeFZRVUZWTEZGQlFWRXNXVUZCVWl4RFFVRldMRU5CU25WRU96dEJRVTB6UkN4dFFrRkJUeXhQUVVGUUxFZEJRV2xDTEZkQlFXcENMRU5CVGpKRU96dEJRVkV6UkN4eFFrRkJVeXhYUVVGVUxFTkJRWEZDTEVOQlFYSkNMRVZCUVhkQ0xFTkJRWGhDTEVWQlFUSkNPMEZCUTNaQ0xHOUNRVUZKTEZsQlFWa3NRMEZCV2l4RFFVUnRRanRCUVVWMlFpeHZRa0ZCU1N4WlFVRlpMRU5CUVZvc1EwRkdiVUk3TzBGQlNYWkNMRzlDUVVGSkxGRkJRVkVzUTBGQlVpeERRVUZLTEVWQlFXZENPMEZCUTFvc1owTkJRVmtzV1VGQldTeERRVUZhTEVWQlFXVXNRMEZCWml4RFFVRmFMRU5CUkZrN2FVSkJRV2hDT3p0QlFVbEJMRzlDUVVGSkxGRkJRVkVzUTBGQlVpeERRVUZLTEVWQlFXZENPMEZCUTFvc1owTkJRVmtzV1VGQldTeERRVUZhTEVWQlFXVXNTVUZCWml4RFFVRmFMRU5CUkZrN2FVSkJRV2hDT3p0QlFVbEJMSFZDUVVGUE8wRkJRMGdzZFVKQlFVY3NVMEZCU0R0QlFVTkJMSFZDUVVGSExGTkJRVWc3YVVKQlJrb3NRMEZhZFVJN1lVRkJNMEk3TzBGQmEwSkJMSEZDUVVGVExGZEJRVlFzUTBGQmNVSXNTMEZCY2tJc1JVRkJORUlzVVVGQk5VSXNSVUZCYzBNN1FVRkRiRU1zYjBKQlFVa3NaMEpCUVdkQ0xFMUJRVTBzUzBGQlRpeERRVVJqT3p0QlFVZHNReXh2UWtGQlNTeERRVUZETEdGQlFVUXNSVUZCWjBJN1FVRkRhRUlzYjBOQlFXZENMRTFCUVUwc1MwRkJUaXhIUVVGakxFMUJRVTBzVFVGQlRpeERRVUZoTEZGQlFXSXNRMEZCWkN4RFFVUkJPMmxDUVVGd1FqczdRVUZKUVN4dlFrRkJTU3hGUVVGRkxGRkJRVkVzWVVGQlVpeExRVU5GTEZGQlFWRXNZVUZCVWl4RFFVUkdMRWxCUlVVc1UwRkJVeXhoUVVGVUxFTkJSa1lzUTBGQlJpeEZRVVU0UWp0QlFVTTVRaXd3UWtGQlRTeEpRVUZKTEV0QlFVb3NRMEZCVlN4dFEwRkJWaXhEUVVGT0xFTkJSRGhDTzJsQ1FVWnNRenM3UVVGTlFTeDFRa0ZCVHl4aFFVRlFMRU5CWW10RE8yRkJRWFJETzFOQk1VSXlRaXhGUVRCRGVrSXNSVUZCUXl4alFVRmhMRVZCUVdJc1JVRkJaMElzWTBGQllTeEZRVUZpTEVWQlFXZENMR05CUVdFc1JVRkJZaXhGUVVGblFpeGxRVUZqTEVWQlFXUXNSVUV4UTNwQ0xFTkJRVWdzUlVFd1F5dERMRWxCUVVjc1EwRkJReXhWUVVGVExFOUJRVlFzUlVGQmFVSXNUVUZCYWtJc1JVRkJkMElzVDBGQmVFSXNSVUZCWjBNN1FVRkRNVWNzYlVKQlFVOHNUMEZCVUN4SFFVRnBRaXhQUVVGcVFpeERRVVF3UnpzN1FVRkhNVWNzY1VKQlFWTXNUMEZCVkN4RFFVRnBRaXhEUVVGcVFpeEZRVUZ2UWp0QlFVTm9RaXgxUWtGQlR5eExRVUZMTEVWQlFVVXNTVUZCUml4TFFVRlhMRTlCUVZnc1EwRkVTVHRoUVVGd1FqdFRRVWd3UlN4RlFVOTRSU3hGUVZCMVJTeERRVUZJTEVWQlQyaEZMRWxCUVVjc1EwRkJReXhWUVVGVExFOUJRVlFzUlVGQmFVSXNUVUZCYWtJc1JVRkJkMElzVDBGQmVFSXNSVUZCWjBNN1FVRkRNVU1zYlVKQlFVOHNUMEZCVUN4SFFVRnBRaXhOUVVGcVFpeERRVVF3UXpzN1FVRkhNVU1zY1VKQlFWTXNUVUZCVkN4RFFVRm5RaXhKUVVGb1FpeEZRVUZ6UWp0QlFVTnNRaXgxUWtGQlR5eFRRVU5LTEU5QlFVOHNTMEZCU3l4SlFVRk1MRXRCUVdNc1ZVRkJja0lzU1VGQmJVTXNRMEZCUXl4TFFVRkxMR05CUVV3c1EwRkJiMElzVFVGQmNFSXNRMEZCUkN4SlFVTnVReXhQUVVGUExFdEJRVXNzVFVGQlRDeExRVUZuUWl4VlFVRjJRaXhKUVVGeFF5eERRVUZETEV0QlFVc3NZMEZCVEN4RFFVRnZRaXhSUVVGd1FpeERRVUZFTEVOQlJtcERMRU5CUkZjN1lVRkJkRUk3VTBGSVZTeEZRVk5TTEVWQlZFOHNRMEZCU0N4RlFWTkJMRWxCUVVjc1EwRkJReXhWUVVGVExFOUJRVlFzUlVGQmFVSXNUVUZCYWtJc1JVRkJkMElzVDBGQmVFSXNSVUZCWjBNN1FVRkRNVU1zWjBKQlFVa3NWVUZCVlN4UlFVRlJMRmRCUVZJc1EwRkJWaXhEUVVSelF6czdRVUZITVVNc2JVSkJRVThzVDBGQlVDeEhRVUZwUWl4aFFVRnFRaXhEUVVnd1F6czdRVUZMTVVNc2NVSkJRVk1zWVVGQlZDeERRVUYxUWl4RFFVRjJRaXhGUVVFd1FqdEJRVU4wUWl4MVFrRkJUeXhMUVVGTExFVkJRVVVzU1VGQlJpeExRVUZYTEdGQlFWZ3NTVUZCTkVJc1JVRkJSU3hQUVVGR0xFdEJRV01zVDBGQlpDeERRVVJzUWp0aFFVRXhRanRUUVV4VkxFVkJVMUlzUlVGQlF5eGhRVUZaTEVWQlFWb3NSVUZVVFN4RFFVRklMRVZCVTJNc1NVRkJSeXhEUVVGRExGVkJRVk1zVDBGQlZDeEZRVUZwUWl4TlFVRnFRaXhGUVVGM1FpeFBRVUY0UWl4RlFVRm5RenRCUVVONFJDeG5Ra0ZCU1N4VlFVRlZMRkZCUVZFc1YwRkJVaXhEUVVGV0xFTkJSRzlFT3p0QlFVZDRSQ3h0UWtGQlR5eFBRVUZRTEVkQlFXbENMR0ZCUVdwQ0xFTkJTSGRFT3p0QlFVdDRSQ3h4UWtGQlV5eGhRVUZVTEVOQlFYVkNMRU5CUVhaQ0xFVkJRVEJDTzBGQlEzUkNMSFZDUVVGUExFdEJRVXNzUlVGQlJTeEpRVUZHTEV0QlFWY3NZVUZCV0N4SlFVRTBRaXhGUVVGRkxFOUJRVVlzUzBGQll5eFBRVUZrTEVOQlJHeENPMkZCUVRGQ08xTkJUSGRDTEVWQlUzUkNMRVZCUVVNc1lVRkJXU3hGUVVGYUxFVkJWRzlDTEVOQlFVZ3NSVUZUUVN4SlFVRkhMRU5CUVVNc1ZVRkJVeXhQUVVGVUxFVkJRV2xDTEUxQlFXcENMRVZCUVhkQ0xFOUJRWGhDTEVWQlFXZERPMEZCUTNoRUxHMUNRVUZQTEU5QlFWQXNSMEZCYVVJc1VVRkJha0lzUTBGRWQwUTdPMEZCUjNoRUxIRkNRVUZUTEZGQlFWUXNRMEZCYTBJc1EwRkJiRUlzUlVGQmNVSTdRVUZEYWtJc2RVSkJRVThzUzBGQlN5eEZRVUZGTEVsQlFVWXNTMEZCVnl4UlFVRllMRU5CUkVzN1lVRkJja0k3VTBGSWQwSXNSVUZQZEVJc1JVRlFjVUlzUTBGQlNDeEZRVTlrTEVsQlFVY3NRMEZCUXl4VlFVRlRMRTlCUVZRc1JVRkJhVUlzVFVGQmFrSXNSVUZCZDBJc1QwRkJlRUlzUlVGQlowTTdRVUZETVVNc2JVSkJRVThzVDBGQlVDeEhRVUZwUWl4SFFVRnFRaXhEUVVRd1F6dFRRVUZvUXl4RlFVZFNMRVZCU0U4c1EwRkJTQ3hGUVVkQkxFbEJRVWNzUTBGQlF5eFZRVUZUTEU5QlFWUXNSVUZCYVVJc1RVRkJha0lzUlVGQmQwSXNUMEZCZUVJc1JVRkJaME03UVVGRE1VTXNaMEpCUVVrc1ZVRkJWU3hSUVVGUkxGZEJRVklzUTBGQlZpeERRVVJ6UXp0QlFVVXhReXhuUWtGQlNTeFZRVUZWTEZGQlFWRXNXVUZCVWl4RFFVRldMRU5CUm5ORE8wRkJSekZETEdkQ1FVRkpMRmRCUVZjc1VVRkJVU3hoUVVGU0xFTkJRVmdzUTBGSWMwTTdRVUZKTVVNc1owSkJRVWtzVlVGQlZTeFJRVUZSTEZsQlFWSXNRMEZCVml4RFFVcHpRenRCUVVzeFF5eG5Ra0ZCU1N4VlFVRlZMRkZCUVZFc1dVRkJVaXhEUVVGV0xFTkJUSE5ET3p0QlFVOHhReXh0UWtGQlR5eFBRVUZRTEVkQlFXbENMRmRCUVdwQ0xFTkJVREJET3p0QlFWTXhReXhuUWtGQlNTeGxRVUZsTEVWQlFXWXNRMEZVYzBNN1FVRlZNVU1zWjBKQlFVa3NZVUZCWVN4RlFVRmlMRU5CVm5ORE96dEJRVmt4UXl4eFFrRkJVeXhYUVVGVUxFTkJRWEZDTEU5QlFYSkNMRVZCUVRoQ0xGVkJRVGxDTEVWQlFUQkRMRkZCUVRGRExFVkJRVzlFTEVkQlFYQkVMRVZCUVhsRUxGTkJRWHBFTEVWQlFXOUZPMEZCUTJoRkxIRkNRVUZMTEU5QlFVd3NSMEZCWlN4UFFVRm1MRU5CUkdkRk8wRkJSV2hGTEhGQ1FVRkxMRlZCUVV3c1IwRkJhMElzWTBGQll5eFpRVUZrTEVOQlJqaERPMEZCUjJoRkxIRkNRVUZMTEZGQlFVd3NSMEZCWjBJc1dVRkJXU3hWUVVGYUxFTkJTR2RFTzBGQlNXaEZMSEZDUVVGTExFZEJRVXdzUjBGQlZ5eFBRVUZQTEVsQlFWQXNSMEZCWXl4UFFVRlBMRWRCUVZBc1EwRkJaQ3hIUVVFMFFpeFRRVUUxUWl4RFFVcHhSRHRCUVV0b1JTeHhRa0ZCU3l4VFFVRk1MRWRCUVdsQ0xFOUJRVkVzVTBGQlVDeExRVUZ4UWl4UlFVRnlRaXhIUVVGcFF5eFRRVUZzUXl4SFFVRTRReXhKUVVFNVF5eERRVXdyUXpzN1FVRlBhRVVzYjBKQlFVa3NVVUZCVVN4UlFVRkRMRWxCUVZrc1UwRkJVeXhOUVVGVUxFbEJRVzlDTEVOQlFXcERMRU5CVUc5RU8wRkJVV2hGTEc5Q1FVRkpMR05CUVdNc1EwRkJaQ3hEUVZJMFJEdEJRVk5vUlN4dlFrRkJTU3hoUVVGaExFdEJRV0lzUTBGVU5FUTdRVUZWYUVVc2IwSkJRVWtzV1VGQldTeExRVUZhTEVOQlZqUkVPMEZCVjJoRkxHOUNRVUZKTEd0Q1FVRnJRaXhMUVVGc1FpeERRVmcwUkR0QlFWbG9SU3h2UWtGQlNTeExRVUZLTEVOQldtZEZPenRCUVdOb1JTeHhRa0ZCU3l4SlFVRkpMRkZCUVVvc1NVRkJaMElzVlVGQmNrSXNSVUZCYVVNN1FVRkROMElzZDBKQlFVa3NWMEZCVnl4alFVRllMRU5CUVRCQ0xGRkJRVEZDTEVOQlFVb3NSVUZCZVVNN1FVRkRja01zTkVKQlFVa3NWMEZCVnl4WFFVRlhMRkZCUVZnc1EwRkJXQ3hEUVVScFF6dEJRVVZ5UXl3MFFrRkJTU3hSUVVGUkxGRkJRVklzUzBGQmNVSXNVMEZCVXl4TlFVRlVMRVZCUVdsQ08wRkJRM1JETEdkRFFVRkpMRU5CUVVNc1MwRkJSQ3hGUVVGUk8wRkJRMUlzZDBOQlFWRXNSVUZCVWl4RFFVUlJPelpDUVVGYU96dEJRVWxCTEd0RFFVRk5MRkZCUVU0c1NVRkJhMElzVVVGQmJFSXNRMEZNYzBNN2VVSkJRVEZETzNGQ1FVWktPMmxDUVVSS096dEJRV0ZCTEhGQ1FVRkxMRWxCUVVrc1NVRkJTU3hEUVVGS0xFVkJRVThzU1VGQlNTeExRVUZLTEVWQlFWY3NSMEZCTTBJc1JVRkJaME03UVVGRE5VSXNkMEpCUVVrc1VVRkJVU3hUUVVGVExFTkJRVlFzUTBGQlVpeERRVVIzUWp0QlFVVTFRaXgzUWtGQlNTeFJRVUZSTEV0QlFWSXNRMEZCU2l4RlFVRnZRanRCUVVOb1FpeDFRMEZCWlN4TlFVRk5MRXRCUVU0c1NVRkJaU3hEUVVGbUxFTkJSRU03TzBGQlIyaENMRFJDUVVGSkxFTkJRVU1zVlVGQlJDeEpRVUZsTEUxQlFVMHNWVUZCVGl4RlFVRnJRanRCUVVOcVF5eDVRMEZCWVN4SlFVRmlMRU5CUkdsRE8zbENRVUZ5UXpzN1FVRkpRU3cwUWtGQlNTeERRVUZETEZOQlFVUXNTVUZCWXl4TlFVRk5MRk5CUVU0c1JVRkJhVUk3UVVGREwwSXNkME5CUVZrc1NVRkJXaXhEUVVRclFqdDVRa0ZCYmtNN08wRkJTVUVzTkVKQlFVa3NRMEZCUXl4bFFVRkVMRXRCUVhGQ0xFMUJRVTBzUzBGQlRpeEpRVUZsTEUxQlFVMHNaVUZCVGl4RFFVRndReXhGUVVFMFJEdEJRVU0xUkN3NFEwRkJhMElzU1VGQmJFSXNRMEZFTkVRN2VVSkJRV2hGTzNGQ1FWaEtMRTFCWTA4c1NVRkJTU3hEUVVGRExGVkJRVVFzU1VGQlpTeFRRVUZUTEV0QlFWUXNRMEZCWml4RlFVRm5RenRCUVVOMlF5dzBRa0ZCU1N4UFFVRlBMRTFCUVUwc1QwRkJUaXhMUVVGclFpeFZRVUY2UWl4RlFVRnhRenRCUVVOeVF5eDVRMEZCWVN4SlFVRmlMRU5CUkhGRE8zbENRVUY2UXp0eFFrRkVSeXhOUVVsQkxFbEJRVWtzUTBGQlF5eFRRVUZFTEVsQlFXTXNVVUZCVVN4TFFVRlNMRU5CUVdRc1JVRkJPRUk3UVVGRGNrTXNiME5CUVZrc1NVRkJXaXhEUVVSeFF6dHhRa0ZCYkVNN2FVSkJjRUpZT3p0QlFYbENRU3h4UWtGQlN5eExRVUZNTEVkQlFXRXNVVUZCVVN4WFFVRlNMRU5CY0VSdFJEdEJRWEZFYUVVc2NVSkJRVXNzVlVGQlRDeEhRVUZyUWl4VlFVRnNRaXhEUVhKRVowVTdRVUZ6UkdoRkxIRkNRVUZMTEZOQlFVd3NSMEZCYVVJc1UwRkJha0lzUTBGMFJHZEZPMEZCZFVSb1JTeHhRa0ZCU3l4TFFVRk1MRWRCUVdFc1MwRkJZaXhEUVhaRVowVTdRVUYzUkdoRkxIRkNRVUZMTEdWQlFVd3NSMEZCZFVJc1pVRkJka0lzUTBGNFJHZEZPMkZCUVhCRk96dEJRVEpFUVN4M1FrRkJXU3hUUVVGYUxFTkJRWE5DTEU5QlFYUkNMRWRCUVdkRExFOUJRV2hETEVOQmRrVXdRenRCUVhkRk1VTXNkMEpCUVZrc1UwRkJXaXhEUVVGelFpeEpRVUYwUWl4SFFVRTJRaXhoUVVFM1FpeERRWGhGTUVNN1UwRkJhRU1zUlVFd1JWSXNSVUZCUXl4alFVRmhMRVZCUVdJc1JVRkJaMElzWTBGQllTeEZRVUZpTEVWQlFXZENMR05CUVdFc1JVRkJZaXhGUVVGblFpeGxRVUZqTEVWQlFXUXNSVUZCYVVJc1lVRkJXU3hGUVVGYUxFVkJNVVV6UkN4RFFVRklMRVZCTUVVclJTeEpRVUZITEVOQlFVTXNWVUZCVXl4UFFVRlVMRVZCUVdsQ0xFMUJRV3BDTEVWQlFYZENMRTlCUVhoQ0xFVkJRV2RETzBGQlEzcElMR2RDUVVGSkxGVkJRVlVzVVVGQlVTeFhRVUZTTEVOQlFWWXNRMEZFY1VnN08wRkJSM3BJTEhsQ1FVRmhMRWxCUVdJc1IwRkJiMElzUTBGQmNFSXNRMEZJZVVnN1FVRkpla2dzZVVKQlFXRXNTMEZCWWl4SFFVRnhRaXhEUVVGeVFpeERRVXA1U0R0QlFVdDZTQ3g1UWtGQllTeExRVUZpTEVkQlFYRkNMRU5CUVhKQ0xFTkJUSGxJTzBGQlRYcElMSGxDUVVGaExFMUJRV0lzUjBGQmMwSXNRMEZCZEVJc1EwRk9lVWc3UVVGUGVrZ3NlVUpCUVdFc1MwRkJZaXhIUVVGeFFpeERRVUZ5UWl4RFFWQjVTRHRCUVZGNlNDeDVRa0ZCWVN4TFFVRmlMRWRCUVhGQ0xFTkJRWEpDTEVOQlVubElPMEZCVTNwSUxIbENRVUZoTEUxQlFXSXNSMEZCYzBJc1EwRkJkRUlzUTBGVWVVZzdRVUZWZWtnc2VVSkJRV0VzVFVGQllpeEhRVUZ6UWl4RFFVRjBRaXhEUVZaNVNEdEJRVmQ2U0N4NVFrRkJZU3hMUVVGaUxFZEJRWEZDTEVOQlFYSkNMRU5CV0hsSU96dEJRV0Y2U0N4dFFrRkJUeXhQUVVGUUxFZEJRV2xDTEZsQlFXcENMRU5CWW5sSU96dEJRV1Y2U0N4eFFrRkJVeXhaUVVGVUxFTkJRWE5DTEVsQlFYUkNMRVZCUVRSQ0xFdEJRVFZDTEVWQlFXMURMRXRCUVc1RExFVkJRVEJETzBGQlEzUkRMSEZDUVVGTExFbEJRVXdzUjBGQldTeFBRVUZQTEVsQlFWQXNRMEZCV2l4RFFVUnpRenRCUVVWMFF5eHhRa0ZCU3l4TFFVRk1MRWRCUVdFc1MwRkJZaXhEUVVaelF6dEJRVWQwUXl4eFFrRkJTeXhMUVVGTUxFZEJRV0VzUzBGQllpeERRVWh6UXp0aFFVRXhRenM3UVVGTlFTeDVRa0ZCWVN4VFFVRmlMRU5CUVhWQ0xFOUJRWFpDTEVkQlFXbERMRTlCUVdwRExFTkJja0o1U0R0QlFYTkNla2dzZVVKQlFXRXNVMEZCWWl4RFFVRjFRaXhKUVVGMlFpeEhRVUU0UWl4alFVRTVRaXhEUVhSQ2VVZzdVMEZCYUVNc1JVRjNRblpHTEVWQlFVTXNZVUZCV1N4RlFVRmFMRVZCZUVKeFJpeERRVUZJTEVWQmQwSnFSU3hKUVVGSExFTkJRVU1zVlVGQlV5eFBRVUZVTEVWQlFXbENMRTFCUVdwQ0xFVkJRWGRDTEU5QlFYaENMRVZCUVdkRE8wRkJRM2hFTEdkQ1FVRkpMRlZCUVZVc1VVRkJVU3hYUVVGU0xFTkJRVllzUTBGRWIwUTdPMEZCUjNoRUxHMUNRVUZQTEU5QlFWQXNSMEZCYVVJc1YwRkJha0lzUTBGSWQwUTdPMEZCUzNoRUxIRkNRVUZUTEZkQlFWUXNRMEZCY1VJc1NVRkJja0lzUlVGQk1rSTdRVUZEZGtJc2NVSkJRVXNzU1VGQlRDeEhRVUZaTEU5QlFVOHNTVUZCVUN4RFFVRmFMRU5CUkhWQ08yRkJRVE5DT3p0QlFVbEJMSGRDUVVGWkxGTkJRVm9zUTBGQmMwSXNUMEZCZEVJc1IwRkJaME1zVDBGQmFFTXNRMEZVZDBRN1FVRlZlRVFzZDBKQlFWa3NVMEZCV2l4RFFVRnpRaXhKUVVGMFFpeEhRVUUyUWl4aFFVRTNRaXhEUVZaM1JEdFRRVUZvUXl4RlFWbDBRaXhGUVVGRExHRkJRVmtzUlVGQldpeEZRVnB2UWl4RFFVRklMRVZCV1VFc1NVRkJSeXhEUVVGRExGVkJRVk1zVDBGQlZDeEZRVUZwUWl4TlFVRnFRaXhGUVVGM1FpeFBRVUY0UWl4RlFVRm5RenRCUVVONFJDeG5Ra0ZCU1N4WFFVRlhMRkZCUVZFc1YwRkJVaXhEUVVGWUxFTkJSRzlFTzBGQlJYaEVMR2RDUVVGSkxGTkJRVk1zVVVGQlVTeHRRa0ZCVWl4RFFVRlVMRU5CUm05RU96dEJRVWw0UkN4dFFrRkJUeXhQUVVGUUxFZEJRV2xDTEZOQlFXcENMRU5CU25kRU96dEJRVTE0UkN4eFFrRkJVeXhUUVVGVUxFTkJRVzFDTEVOQlFXNUNMRVZCUVhOQ0xFTkJRWFJDTEVWQlFYbENPMEZCUTNKQ0xHOUNRVUZKTEVsQlFVb3NRMEZFY1VJN08wRkJSM0pDTEhGQ1FVRkxMRWxCUVVrc1NVRkJTaXhKUVVGWkxFTkJRV3BDTEVWQlFXOUNPMEZCUTJoQ0xIZENRVUZKTEVWQlFVVXNVVUZCVVN4RFFVRlNMRU5CUVVZc1JVRkJZenRCUVVOa0xDdENRVUZQTEZGQlFWRXNSVUZCVWl4RFFVUlBPMEZCUldRc05rSkJRVXNzU1VGQlRDeEpRVUZoTEZOQlFXSXNRMEZHWXp0eFFrRkJiRUk3TzBGQlMwRXNkMEpCUVVrc1UwRkJVeXhGUVVGRkxFbEJRVVlzUTBGQlZDeERRVTVaTzBGQlQyaENMSGRDUVVGSkxGTkJRVk1zUlVGQlJTeEpRVUZHTEVOQlFWUXNRMEZRV1RzN1FVRlRhRUlzZDBKQlFVa3NWMEZCVnl4TlFVRllMRVZCUVcxQ08wRkJRMjVDTEdsRFFVUnRRanR4UWtGQmRrSXNUVUZGVHl4SlFVRkpMRk5CUVZNc1RVRkJWQ3hMUVVGdlFpeFRRVUZUTEUxQlFWUXNRMEZCY0VJc1JVRkJjME03UVVGRE4wTXNORUpCUVVrc1lVRkJZU3hOUVVGaUxFMUJRWGxDTEdGQlFXRXNUVUZCWWl4RFFVRjZRaXhGUVVFclF6dEJRVU12UXl4dFEwRkJUeXhSUVVGUkxFVkJRVklzUTBGRWQwTTdRVUZGTDBNc2FVTkJRVXNzU1VGQlRDeEpRVUZoTEUxQlFXSXNRMEZHSzBNN2VVSkJRVzVFTEUxQlIwOHNTVUZCU1N4UFFVRlBMRTFCUVZBc1EwRkJTaXhGUVVGdlFqdEJRVU4wUWl4dFEwRkJUeXhSUVVGUkxFVkJRVklzUTBGRVpUdEJRVVYwUWl4cFEwRkJTeXhKUVVGTUxFbEJRV0VzVFVGQllpeERRVVp6UWp0NVFrRkJjRUlzVFVGSFFUdEJRVU5JTEdkRFFVRkpMR0ZCUVdFc1ZVRkJWU3hOUVVGV0xFVkJRV3RDTEUxQlFXeENMRU5CUVdJc1EwRkVSRHRCUVVWSUxHZERRVUZKTEZWQlFVb3NSVUZCWjBJN1FVRkRXaXgxUTBGQlR5eFJRVUZSTEVWQlFWSXNRMEZFU3p0QlFVVmFMSEZEUVVGTExFbEJRVXdzU1VGQllTeFZRVUZpTEVOQlJsazdOa0pCUVdoQ08zbENRVXhITzNGQ1FVcEtMRTFCWTBFN1FVRkRTQ3dyUWtGQlR5eFJRVUZSTEVWQlFWSXNRMEZFU2p0QlFVVklMRFpDUVVGTExFbEJRVXdzU1VGQllTeE5RVUZpTEVOQlJrYzdjVUpCWkVFN2FVSkJXRmc3TzBGQkswSkJMSEZDUVVGTExFbEJRVWtzU1VGQlNpeEpRVUZaTEVOQlFXcENMRVZCUVc5Q08wRkJRMmhDTEhkQ1FVRkpMRVZCUVVVc1VVRkJVU3hEUVVGU0xFTkJRVVlzUlVGQll6dEJRVU5rTEN0Q1FVRlBMRkZCUVZFc1JVRkJVaXhEUVVSUE8wRkJSV1FzTmtKQlFVc3NTVUZCVEN4SlFVRmhMRVZCUVVVc1NVRkJSaXhEUVVGaUxFTkJSbU03Y1VKQlFXeENPMmxDUVVSS096dEJRVTlCTEhWQ1FVRlBMRWxCUVZBc1EwRjZRM0ZDTzJGQlFYcENPenRCUVRSRFFTeHhRa0ZCVXl4WlFVRlVMRU5CUVhOQ0xFdEJRWFJDTEVWQlFUWkNPMEZCUXpOQ0xHOUNRVUZKTEU5QlFVOHNZMEZCVUN4RlFVRjFRanRCUVVONlFpd3lRa0ZCVHl4UFFVRlBMR05CUVZBc1EwRkJjMElzUzBGQmRFSXNRMEZCVUN4RFFVUjVRanRwUWtGQk0wSXNUVUZGVHl4SlFVRkpMRTFCUVUwc1UwRkJUaXhGUVVGcFFqdEJRVU14UWl3eVFrRkJUeXhOUVVGTkxGTkJRVTRzUTBGRWJVSTdhVUpCUVhKQ0xFMUJSVUVzU1VGQlNTeE5RVUZOTEZkQlFVNHNSVUZCYlVJN1FVRkROVUlzTWtKQlFVOHNUVUZCVFN4WFFVRk9MRU5CUVd0Q0xGTkJRV3hDTEVOQlJIRkNPMmxDUVVGMlFqdGhRVXhVTzFOQmJFUjNRaXhGUVRSRWRFSXNSVUZCUXl4eFFrRkJiMElzUlVGQmNFSXNSVUZCZFVJc1lVRkJXU3hGUVVGYUxFVkJOVVJJTEVOQlFVZ3NSVUUwUkhWQ0xFbEJRVWNzUTBGQlF5eFZRVUZUTEU5QlFWUXNSVUZCYVVJc1RVRkJha0lzUlVGQmQwSXNUMEZCZUVJc1JVRkJaME03UVVGREwwVXNaMEpCUVVrc1ZVRkJWU3hSUVVGUkxGbEJRVklzUTBGQlZpeERRVVF5UlRzN1FVRkhMMFVzWjBKQlFVa3NVMEZCVXl4UlFVRlJMR2xDUVVGU0xFTkJRVlFzUTBGSU1rVTdRVUZKTDBVc1owSkJRVWtzVlVGQlZTeFJRVUZSTEcxQ1FVRlNMRU5CUVZZc1EwRktNa1U3UVVGTEwwVXNaMEpCUVVrc1ZVRkJWU3hSUVVGUkxHMUNRVUZTTEVOQlFWWXNRMEZNTWtVN1FVRk5MMFVzWjBKQlFVa3NWMEZCVnl4UlFVRlJMRzlDUVVGU0xFTkJRVmdzUTBGT01rVTdRVUZQTDBVc1owSkJRVWtzVlVGQlZTeFJRVUZSTEcxQ1FVRlNMRU5CUVZZc1EwRlFNa1U3UVVGUkwwVXNaMEpCUVVrc1kwRkJZeXhSUVVGUkxIVkNRVUZTTEVOQlFXUXNRMEZTTWtVN08wRkJWUzlGTEdkQ1FVRkpMRmxCUVZrc1VVRkJVU3hqUVVGU0xFTkJRVm9zUTBGV01rVTdPMEZCV1M5RkxHMUNRVUZQTEU5QlFWQXNSMEZCYVVJc1NVRkJha0lzUTBGYUswVTdPMEZCWXk5RkxIRkNRVUZUTEVsQlFWUXNRMEZCWXl4RFFVRmtMRVZCUVdsQ0xFTkJRV3BDTEVWQlFXOUNPMEZCUTJoQ0xHOUNRVUZKTEZGQlFWRXNSVUZCUlN4SFFVRkhMRU5CUVVnc1JVRkJWaXhEUVVSWk8wRkJSV2hDTEhGQ1FVRkxMRU5CUVV3c1JVRkJVU3hEUVVGU0xFVkJRVmNzUzBGQldDeEZRVUZyUWl4RFFVRnNRaXhGUVVablFqdEJRVWRvUWl4MVFrRkJUeXhMUVVGUUxFTkJTR2RDTzJGQlFYQkNPenRCUVUxQkxIRkNRVUZUTEVsQlFWUXNRMEZCWXl4RFFVRmtMRVZCUVdsQ0xFTkJRV3BDTEVWQlFXOUNMRXRCUVhCQ0xFVkJRVEpDTEV0QlFUTkNMRVZCUVd0RE8wRkJRemxDTEc5Q1FVRkpMRTFCUVUwc1EwRkJUaXhGUVVGVE8wRkJRMVFzTWtKQlJGTTdhVUpCUVdJN08wRkJTVUVzYjBKQlFVa3NVVUZCVVN4TlFVRk5MRXRCUVU0c1EwRkJVaXhEUVV3d1FqdEJRVTA1UWl4dlFrRkJTU3hoUVVGaExFdEJRV0lzUTBGT01FSTdPMEZCVVRsQ0xHOUNRVUZKTEZGQlFWRXNRMEZCVWl4TFFVRmpMRkZCUVZFc1EwRkJVaXhEUVVGa0xFVkJRVEJDTzBGQlF6RkNMREpDUVVGUExFTkJRVkFzUlVGQlZTeERRVUZXTEVWQlFXRXNTMEZCWWl4RlFVRnZRaXhMUVVGd1FpeEZRVVF3UWp0cFFrRkJPVUlzVFVGRlR5eEpRVUZKTEV0QlFVc3NTVUZCVEN4RlFVRlhPenM3T3p0QlFVdHNRaXgzUWtGQlNTeERRVUZETEZOQlFWTXNRMEZCVkN4RFFVRkVMRVZCUVdNN1FVRkRaQ3h0UTBGQlZ5eERRVUZZTEVWQlFXTXNTMEZCWkN4RlFVRnhRaXhMUVVGeVFpeEZRVVJqTzBGQlJXUXNaME5CUVZFc1RVRkJUU3hMUVVGT0xFTkJRVklzUTBGR1l6dHhRa0ZCYkVJN08wRkJTMEVzTkVKQlFWRXNXVUZCV1N4TFFVRmFMRVZCUVcxQ0xFbEJRVWtzVFVGQlNpeERRVUZYTEU5QlFVOHNUVUZCVUN4RlFVRmxMRU5CUVRGQ0xFVkJRVFpDTEVOQlFUZENMRU5CUVc1Q0xFTkJRVklzUTBGV2EwSTdhVUpCUVdZc1RVRlhRU3hKUVVGSkxGRkJRVkVzUTBGQlVpeERRVUZLTEVWQlFXZENPMEZCUTI1Q0xIZENRVUZKTEZGQlFWRXNRMEZCVWl4RFFVRktMRVZCUVdkQ08wRkJRMW9zTkVKQlFVa3NSVUZCUlN4UFFVRkdMRXRCUVdNc1JVRkJSU3hQUVVGR0xFbEJRMlFzUlVGQlJTeFRRVUZHTEV0QlFXZENMRVZCUVVVc1UwRkJSaXhKUVVOb1FpeEZRVUZGTEVkQlFVWXNTMEZCVlN4RlFVRkZMRWRCUVVZc1JVRkJUenRCUVVOcVFpeG5RMEZCU1N4aFFVRmhMRlZCUVZVc1JVRkJSU3hWUVVGR0xFVkJRV01zUlVGQlJTeFZRVUZHTEVOQlFYSkRMRU5CUkdFN1FVRkZha0lzWjBOQlFVa3NWVUZCU2l4RlFVRm5RanRCUVVOYUxIZERRVUZSTEZsQlFWa3NTMEZCV2l4RlFVTktMRWxCUVVrc1RVRkJTaXhEUVVGWExFOUJRVThzUzBGQlVDeEZRVUZqTEVOQlFYcENMRVZCUVRSQ0xGVkJRVFZDTEVOQlJFa3NRMEZCVWl4RFFVUlpPelpDUVVGb1FqdEJRVWxCTEc5RFFVRlJMR0ZCUVdFc1EwRkJZaXhGUVVGblFpeERRVUZvUWl4RlFVRnRRaXhMUVVGdVFpeEZRVUV3UWl4TFFVRXhRaXhGUVVGcFF5eExRVUZxUXl4RFFVRlNMRU5CVG1sQ08zbENRVVp5UWl4TlFWTlBPMEZCUTBnc2IwTkJRVkVzV1VGQldTeExRVUZhTEVWQlFXMUNMRWxCUVVrc1RVRkJTaXhEUVVGWExFOUJRVThzUzBGQlVDeEZRVUZqTEVOQlFYcENMRVZCUVRSQ0xFTkJRVFZDTEVOQlFXNUNMRU5CUVZJc1EwRkVSenRCUVVWSUxIbERRVUZoTEVsQlFXSXNRMEZHUnp0NVFrRlVVRHR4UWtGRVNpeE5RV05QTzBGQlEwZ3NaME5CUVZFc1dVRkJXU3hMUVVGYUxFVkJRVzFDTEVsQlFVa3NUVUZCU2l4RFFVRlhMRTlCUVU4c1MwRkJVQ3hGUVVGakxFTkJRWHBDTEVWQlFUUkNMRU5CUVRWQ0xFTkJRVzVDTEVOQlFWSXNRMEZFUnp0QlFVVklMSEZEUVVGaExFbEJRV0lzUTBGR1J6dHhRa0ZrVUR0cFFrRkVSeXhOUVcxQ1FTeEpRVUZKTEZGQlFWRXNRMEZCVWl4RFFVRktMRVZCUVdkQ08wRkJRMjVDTEhkQ1FVRkpMRU5CUVVNc1VVRkJVU3hEUVVGU0xFTkJRVVFzUlVGQllUdEJRVU5pTEdkRFFVRlJMRmxCUVZrc1MwRkJXaXhGUVVGdFFpeEpRVUZKTEUxQlFVb3NRMEZCVnl4UFFVRlBMRXRCUVZBc1JVRkJZeXhEUVVGNlFpeEZRVUUwUWl4RFFVRTFRaXhEUVVGdVFpeERRVUZTTEVOQlJHRTdRVUZGWWl4eFEwRkJZU3hKUVVGaUxFTkJSbUU3Y1VKQlFXcENMRTFCUjA4c1NVRkJTU3hGUVVGRkxFbEJRVVlzUzBGQlZ5eEZRVUZGTEVsQlFVWXNSVUZCVVR0QlFVTXhRaXhuUTBGQlVTeFpRVUZaTEV0QlFWb3NSVUZCYlVJc1NVRkJTU3hOUVVGS0xFTkJRVmNzVDBGQlR5eExRVUZRTEVWQlFXTXNRMEZCZWtJc1JVRkJORUlzUTBGQk5VSXNRMEZCYmtJc1EwRkJVaXhEUVVRd1FqdHhRa0ZCZGtJN2FVSkJTa29zVFVGUFFTeEpRVUZKTEZOQlFWTXNRMEZCVkN4RFFVRktMRVZCUVdsQ08wRkJRM0JDTEhkQ1FVRkpMRU5CUVVNc1UwRkJVeXhEUVVGVUxFTkJRVVFzUlVGQll6dEJRVU5rTEhGRFFVRmhMRWxCUVdJc1EwRkVZenR4UWtGQmJFSTdPMEZCU1VFc05FSkJRVkVzV1VGQldTeExRVUZhTEVWQlFXMUNMRWxCUVVrc1RVRkJTaXhEUVVGWExFOUJRVThzVFVGQlVDeEZRVUZsTEVOQlFURkNMRVZCUVRaQ0xFTkJRVGRDTEVOQlFXNUNMRU5CUVZJc1EwRk1iMEk3YVVKQlFXcENPenRCUVZGUUxHOUNRVUZKTEV0QlFVb3NSVUZCVnp0QlFVTlFMREJDUVVGTkxFdEJRVTRzU1VGQlpTeExRVUZtTEVOQlJFODdhVUpCUVZnN08wRkJTVUVzYjBKQlFVa3NWVUZCU2l4RlFVRm5RanRCUVVOYUxDdENRVUZYTEVOQlFWZ3NSVUZCWXl4TFFVRmtMRVZCUVhGQ0xFdEJRWEpDTEVWQlJGazdhVUpCUVdoQ08yRkJNMFJLT3p0QlFXZEZRU3h4UWtGQlV5eFpRVUZVTEVOQlFYTkNMRU5CUVhSQ0xFVkJRWGxDTEVOQlFYcENMRVZCUVRSQ0xFdEJRVFZDTEVWQlFXMURMRXRCUVc1RExFVkJRVEJETEV0QlFURkRMRVZCUVdsRU8wRkJRemRETEc5Q1FVRkpMRmxCUVZrc1JVRkJSU3hSUVVGR0xFTkJSRFpDTzBGQlJUZERMRzlDUVVGSkxHRkJRV0VzVVVGQlVTeFRRVUZTTEVWQlFXMUNMRVZCUVVVc1VVRkJSaXhEUVVGb1F5eERRVVo1UXp0QlFVYzNReXh2UWtGQlNTeFpRVUZaTEZkQlFWY3NVVUZCV0N4RFFVZzJRanM3UVVGTE4wTXNiMEpCUVVrc1QwRkJUeXhWUVVGVkxFMUJRVllzUTBGTWEwTTdRVUZOTjBNc2IwSkJRVWtzVDBGQlR5eFZRVUZWTEUxQlFWWXNRMEZPYTBNN1FVRlBOME1zYjBKQlFVa3NUVUZCVFN4UFFVRlBMRWxCUVZBc1IwRkJZeXhKUVVGa0xFZEJRWEZDTEVsQlFYSkNMRU5CVUcxRE96dEJRVk0zUXl4eFFrRkJTeXhKUVVGSkxFbEJRVWtzUTBGQlNpeEZRVUZQTEVsQlFVa3NSMEZCU2l4RlFVRlRMRWRCUVhwQ0xFVkJRVGhDTzBGQlF6RkNMSGRDUVVGSkxGZEJRVmNzVlVGQlZTeERRVUZXTEVOQlFWZ3NRMEZFYzBJN1FVRkZNVUlzZDBKQlFVa3NXVUZCV1N4VlFVRlZMRU5CUVZZc1EwRkJXaXhEUVVaelFqdEJRVWN4UWl3MlFrRkJVeXhEUVVGVUxFTkJTREJDT3p0QlFVc3hRaXgzUWtGQlNTeERRVUZETEZGQlFVUXNSVUZCVnp0QlFVTllMRFJDUVVGSkxGTkJRVW9zUlVGQlpUczdRVUZGV0N4dlEwRkJVU3haUVVGWkxFdEJRVm9zUlVGRFNpeEpRVUZKTEUxQlFVb3NRMEZCVnl4UFFVRlBMRTFCUVZBc1JVRkJaU3hKUVVFeFFpeEZRVUZuUXl4VFFVRm9ReXhEUVVSSkxFTkJRVklzUTBGR1Z6dDVRa0ZCWmp0eFFrRkVTaXhOUVUxUE8wRkJRMGdzTmtKQlFVc3NVVUZCVEN4RlFVRmxMRk5CUVdZc1JVRkJNRUlzUzBGQk1VSXNSVUZCYVVNc1MwRkJha01zUlVGRVJ6dHhRa0ZPVURzN1FVRlZRU3gzUWtGQlNTeFJRVUZSTEZGQlFWSXNTMEZCY1VJc1UwRkJVeXhMUVVGVUxFVkJRV2RDTzBGQlEzSkRMR2xEUVVGVExGTkJRVk1zUzBGQlZDeERRVVEwUWp0eFFrRkJla003YVVKQlprbzdPMEZCYjBKQkxHOUNRVUZKTEZkQlFWY3NTMEZCV0N4RlFVRnJRanM3UVVGRmJFSXNORUpCUVZFc1dVRkJXU3hMUVVGYUxFVkJRVzFDTEVsQlFVa3NUVUZCU2l4RFFVTjJRaXhQUVVGUExFdEJRVkFzUlVGRFFTeERRVVoxUWl4RlFVZDJRaXhYUVVGWExFdEJRVmdzUTBGSVNTeERRVUZTTEVOQlJtdENPMmxDUVVGMFFqczdRVUZUUVN4MVFrRkJUeXhMUVVGUUxFTkJkRU0yUXp0aFFVRnFSRHM3UVVGNVEwRXNjVUpCUVZNc1ZVRkJWQ3hEUVVGdlFpeExRVUZ3UWl4RlFVRXlRaXhMUVVFelFpeEZRVUZyUXl4TFFVRnNReXhGUVVGNVF6czdRVUZGY2tNc2RVSkJRVThzUzBGQlVDeEZRVUZqTEV0QlFXUXNSVUZCY1VJc1MwRkJja0lzUlVGR2NVTTdRVUZIY2tNc0swSkJRV1VzUzBGQlppeEZRVUZ6UWl4TFFVRjBRaXhGUVVFMlFpeExRVUUzUWl4RlFVaHhRenRoUVVGNlF6czdPenRCUVRkSUswVXNjVUpCY1VsMFJTeGpRVUZVTEVOQlFYZENMRXRCUVhoQ0xFVkJRU3RDTEV0QlFTOUNMRVZCUVhORExFdEJRWFJETEVWQlFUWkRPMEZCUTNwRExHOUNRVUZKTEZOQlFWTXNTMEZCVkN4RFFVRktMRVZCUVhGQ08wRkJRMnBDTEhkQ1FVRkpMRTlCUVU4c1RVRkJUU3hQUVVGT0xFdEJRV3RDTEZWQlFYcENMRVZCUVhGRE8wRkJRM0pETERoQ1FVRk5MRXRCUVU0c1NVRkJaU3haUVVOWUxFMUJRVTBzUzBGQlRpeERRVVJYTEVWQlJWZ3NTVUZCU1N4TlFVRktMRU5CUVZjc1QwRkJUeXhOUVVGUUxFVkJRV1VzUzBGQk1VSXNSVUZCYVVNc1NVRkJha01zUTBGR1Z5eERRVUZtTEVOQlJIRkRPM0ZDUVVGNlF6dHBRa0ZFU2l4TlFVOVBMRWxCUVVrc1VVRkJVU3hMUVVGU0xFMUJRVzFDTEUxQlFVMHNWVUZCVGl4SlFVRnZRaXhOUVVGTkxGTkJRVTRzUTBGQmRrTXNSVUZCZVVRN1FVRkRhRVVzZDBKQlFVa3NWMEZCVnl4TlFVRk5MRkZCUVU0c1EwRkVhVVE3UVVGRmFFVXNkMEpCUVVrc1RVRkJUU3hUUVVGVExFMUJRVlFzUTBGR2MwUTdRVUZIYUVVc2VVSkJRVXNzU1VGQlNTeEpRVUZKTEVOQlFVb3NSVUZCVHl4SlFVRkpMRWRCUVVvc1JVRkJVeXhIUVVGNlFpeEZRVUU0UWp0QlFVTXhRaXcwUWtGQlNTeFJRVUZSTEZOQlFWTXNRMEZCVkN4RFFVRlNMRU5CUkhOQ08wRkJSVEZDTEdsRFFVRlRMRU5CUVZRc1EwRkdNRUk3TzBGQlNURkNMSFZEUVVGbExFdEJRV1lzUlVGQmMwSXNTMEZCZEVJc1JVRkJOa0lzUzBGQk4wSXNSVUZLTUVJN08wRkJUVEZDTERSQ1FVRkpMRkZCUVZFc1MwRkJVaXhMUVVGclFpeE5RVUZOTEV0QlFVNHNSVUZCWVR0QlFVTXZRaXh4UTBGQlV5eE5RVUZOTEV0QlFVNHNRMEZFYzBJN2VVSkJRVzVETzNGQ1FVNUtPMmxDUVVoSExFMUJZVUVzU1VGQlNTeFJRVUZSTEV0QlFWSXNRMEZCU2l4RlFVRnZRanRCUVVOMlFpd3lRa0ZCVHl4TFFVRlFMRVZCUVdNc1NVRkJaQ3hGUVVGdlFpeExRVUZ3UWl4RlFVRXlRaXhMUVVFelFpeEZRVVIxUWp0cFFrRkJjRUk3WVVGeVFsZzdPenRCUVhKSkswVXNjVUpCWjB0MFJTeE5RVUZVTEVOQlFXZENMRU5CUVdoQ0xFVkJRVzFDTEVOQlFXNUNMRVZCUVhOQ0xFdEJRWFJDTEVWQlFUWkNMRXRCUVRkQ0xFVkJRVzlETzBGQlEyaERMRzlDUVVGSkxGRkJRVkVzV1VGQldTeERRVUZhTEVWQlFXVXNRMEZCWml4RFFVRlNMRU5CUkRSQ08wRkJSV2hETEc5Q1FVRkpMR0ZCUVdFc1MwRkJTeXhOUVVGTkxFTkJRVTRzUlVGQlV5eE5RVUZOTEVOQlFVNHNRMEZCTTBJc1EwRkdORUk3UVVGSGFFTXNiMEpCUVVrc1YwRkJWeXhWUVVGWUxFTkJRVW9zUlVGQk5FSTdRVUZEZUVJc01FSkJRVTBzUzBGQlRpeEpRVUZsTEVsQlFVa3NUVUZCU2l4RFFVRlhMRTlCUVU4c1MwRkJVQ3hGUVVGakxFbEJRWHBDTEVWQlFTdENMRlZCUVM5Q0xFTkJRV1lzUTBGRWQwSTdhVUpCUVRWQ08yRkJTRW83TzBGQlVVRXNjVUpCUVZNc1ZVRkJWQ3hEUVVGdlFpeExRVUZ3UWl4RlFVRXlRanRCUVVOMlFpeHhRa0ZCU3l4SlFVRkpMRXRCUVVvc1NVRkJZU3hMUVVGc1FpeEZRVUY1UWp0QlFVTnlRaXgzUWtGQlNTeFZRVUZWTEVkQlFWWXNSVUZCWlR0QlFVTm1MQ3RDUVVGUExFbEJRVkFzUTBGRVpUdHhRa0ZCYmtJN2FVSkJSRW83TzBGQlRVRXNkVUpCUVU4c1MwRkJVQ3hEUVZCMVFqdGhRVUV6UWpzN08wRkJlRXNyUlN4eFFrRnRUSFJGTEUxQlFWUXNRMEZCWjBJc1MwRkJhRUlzUlVGQmRVSXNTMEZCZGtJc1JVRkJPRUlzUzBGQk9VSXNSVUZCY1VNN1FVRkRha01zYjBKQlFVa3NVVUZCVVN4TFFVRlNMRU5CUVVvc1JVRkJiMEk3UVVGRGFFSXNkMEpCUVVrc1RVRkJUU3hMUVVGT0xFVkJRV0U3UVVGRFlpdzRRa0ZCVFN4TFFVRk9MRWxCUVdVc1dVRkRXQ3hOUVVGTkxFdEJRVTRzUTBGRVZ5eEZRVVZZTEVsQlFVa3NUVUZCU2l4RFFVTkpMRTlCUVU4c1MwRkJVQ3hGUVVOQkxFdEJSa29zUlVGSFNTeGpRVUZqTEUxQlFVMHNTMEZCVGl4RFFVaHNRaXhEUVVaWExFTkJRV1lzUTBGRVlUdHhRa0ZCYWtJN08wRkJWMEVzZDBKQlFVa3NUVUZCVFN4bFFVRk9MRWxCUVhsQ0xFMUJRVTBzVTBGQlRpeEZRVUZwUWp0QlFVTXhReXcwUWtGQlNTeFhRVUZYTEUxQlFVMHNVVUZCVGl4RFFVUXlRanRCUVVVeFF5dzBRa0ZCU1N4TlFVRk5MRk5CUVZNc1RVRkJWQ3hEUVVablF6dEJRVWN4UXl3MlFrRkJTeXhKUVVGSkxFbEJRVWtzUTBGQlNpeEZRVUZQTEVsQlFVa3NSMEZCU2l4RlFVRlRMRWRCUVhwQ0xFVkJRVGhDTzBGQlF6RkNMR2REUVVGSkxGRkJRVkVzVTBGQlV5eERRVUZVTEVOQlFWSXNRMEZFYzBJN1FVRkZNVUlzY1VOQlFWTXNRMEZCVkN4RFFVWXdRanM3UVVGSk1VSXNiVU5CUVU4c1MwRkJVQ3hGUVVGakxFdEJRV1FzUlVGQmNVSXNTMEZCY2tJc1JVRktNRUk3TzBGQlRURkNMR2REUVVGSkxGRkJRVkVzUzBGQlVpeExRVUZyUWl4TlFVRk5MRXRCUVU0c1JVRkJZVHRCUVVNdlFpeDVRMEZCVXl4TlFVRk5MRXRCUVU0c1EwRkVjMEk3TmtKQlFXNURPM2xDUVU1S08zRkNRVWhLTzJsQ1FWcEtMRTFCTUVKUExFbEJRVWtzVVVGQlVTeExRVUZTTEVOQlFVb3NSVUZCYjBJN1FVRkRka0lzTWtKQlFVOHNTMEZCVUN4RlFVRmpMRWxCUVdRc1JVRkJiMElzUzBGQmNFSXNSVUZCTWtJc1MwRkJNMElzUlVGRWRVSTdhVUpCUVhCQ08yRkJNMEpZT3p0QlFXZERRU3h4UWtGQlV5eGhRVUZVTEVOQlFYVkNMRWRCUVhaQ0xFVkJRVFJDTzBGQlEzaENMRzlDUVVGSkxGTkJRVk1zUlVGQlZDeERRVVJ2UWpzN1FVRkhlRUlzY1VKQlFVc3NTVUZCU1N4SFFVRktMRWxCUVZjc1IwRkJhRUlzUlVGQmNVSTdRVUZEYWtJc01rSkJRVThzUjBGQlVDeEpRVUZqTEZOQlFXUXNRMEZFYVVJN2FVSkJRWEpDT3p0QlFVbEJMSFZDUVVGUExFMUJRVkFzUTBGUWQwSTdZVUZCTlVJN096dEJRVzVPSzBVc2NVSkJPRTUwUlN4UFFVRlVMRU5CUVdsQ0xGTkJRV3BDTEVWQlFUUkNMRk5CUVRWQ0xFVkJRWFZET3p0QlFVVnVReXh2UWtGQlNTeGpRVUZqTEZOQlFWTXNVMEZCVkN4RFFVRmtMRU5CUml0Q08wRkJSMjVETEc5Q1FVRkpMRkZCUVZFc1dVRkJXU3hKUVVGYUxFTkJTSFZDTzBGQlNXNURMRzlDUVVGSkxGRkJRVkVzV1VGQldTeEpRVUZhTEVOQlNuVkNPenRCUVUxdVF5eHZRa0ZCU1N4TlFVRk5MRTFCUVU0c1MwRkJhVUlzVlVGQlZTeE5RVUZXTEVWQlFXdENPMEZCUTI1RExESkNRVUZQTzBGQlEwZ3NhME5CUVZVc1UwRkJWanRCUVVOQkxDdENRVUZQTEVsQlFWQTdjVUpCUmtvc1EwRkViVU03YVVKQlFYWkRPenM3UVVGT2JVTXNiMEpCWXk5Q0xHTkJRV01zVTBGQlV5eFRRVUZVTEVOQlFXUXNRMEZrSzBJN1FVRmxia01zYjBKQlFVa3NVVUZCVVN4WlFVRlpMRWxCUVZvc1EwRm1kVUk3UVVGblFtNURMRzlDUVVGSkxGRkJRVkVzV1VGQldTeEpRVUZhTEVOQmFFSjFRanM3UVVGclFtNURMRzlDUVVGSkxFMUJRVTBzVFVGQlRpeExRVUZwUWl4VlFVRlZMRTFCUVZZc1JVRkJhMEk3UVVGRGJrTXNNa0pCUVU4N1FVRkRTQ3hyUTBGQlZTeFRRVUZXTzBGQlEwRXNLMEpCUVU4c1NVRkJVRHR4UWtGR1NpeERRVVJ0UXp0cFFrRkJka003T3p0QlFXeENiVU1zYjBKQk1FSXZRaXhqUVVGakxFVkJRV1FzUTBFeFFpdENPenRCUVRSQ2JrTXNiMEpCUVVrc1dVRkJXU3hEUVVGYUxFTkJOVUlyUWp0QlFUWkNia01zYjBKQlFVa3NXVUZCV1N4TlFVRk5MRTFCUVU0c1EwRTNRbTFDTzBGQk9FSnVReXh2UWtGQlNTeGxRVUZsTEVOQlFXWTdPenM3UVVFNVFpdENMSEZDUVd0RE9VSXNTVUZCU1N4SlFVRkpMRU5CUVVvc1JVRkJVU3hKUVVGSkxGVkJRVlVzVFVGQlZpeEZRVUZyUWl4SFFVRjJReXhGUVVFMFF6dEJRVU40UXl4M1FrRkJTU3hSUVVGUkxGVkJRVlVzUTBGQlZpeERRVUZTTEVOQlJHOURPMEZCUlhoRExIZENRVUZKTEZOQlFVb3NRMEZHZDBNN08wRkJTWGhETEhkQ1FVRkpMRTFCUVUwc1IwRkJUaXhGUVVGWE8wRkJRMWdzTkVKQlFVa3NUVUZCVFN4alFVRk9MRU5CUVhGQ0xFMUJRVTBzUjBGQlRpeERRVUY2UWl4RlFVRnhRenM3UVVGRmFrTXNkME5CUVZrc1RVRkJUU3hOUVVGTkxFZEJRVTRzUTBGQmJFSXNRMEZHYVVNN1FVRkhha01zZDBOQlFWa3NTVUZCV2l4RFFVRnBRaXhWUVVGVkxGTkJRVllzUTBGQmFrSXNSVUZJYVVNN2VVSkJRWEpETEUxQlMwODdPMEZCUlVnc2QwTkJRVmtzU1VGQlNTeGpRVUZLTEVOQlJsUTdRVUZIU0N4M1EwRkJXU3hKUVVGYUxFTkJRV2xDTEVsQlFXcENMRVZCU0VjN2VVSkJURkE3Y1VKQlJFb3NUVUZYVHpzN1FVRkZTQ3cwUWtGQlNTeFpRVUZaTEZOQlFWb3NSVUZCZFVJN1FVRkRka0lzZDBOQlFWa3NUVUZCVFN4WFFVRk9MRU5CUVZvc1EwRkVkVUk3UVVGRmRrSXNkME5CUVZrc1NVRkJXaXhEUVVGcFFpeFZRVUZWTEZOQlFWWXNRMEZCYWtJc1JVRkdkVUk3ZVVKQlFUTkNMRTFCUjA4N096czdRVUZKU0N4M1EwRkJXU3hKUVVGSkxHTkJRVW9zUTBGS1ZEdEJRVXRJTEhkRFFVRlpMRWxCUVZvc1EwRkJhVUlzU1VGQmFrSXNSVUZNUnp0NVFrRklVRHR4UWtGaVNqdHBRa0ZLU2pzN1FVRTRRa0VzYjBKQlFVa3NaMEpCUVdkQ0xHRkJRV0VzVFVGQlRTeE5RVUZPTEVkQlF6ZENMRlZCUVZVc1RVRkJWaXhIUVVOQkxFMUJRVTBzVTBGQlRpeERRVVpuUWpzN096dEJRV2hGWlN4eFFrRnpSVGxDTEVsQlFVa3NTVUZCU1N4RFFVRktMRVZCUVU4c1NVRkJTU3hWUVVGVkxFMUJRVllzUlVGQmEwSXNSMEZCZEVNc1JVRkJNa003UVVGRGRrTXNkMEpCUVVrc1ZVRkJWU3hWUVVGVkxFTkJRVllzUTBGQlZpeERRVVJ0UXpzN1FVRkhka01zZDBKQlFVa3NVVUZCVVN4SFFVRlNMRVZCUVdFN1FVRkRZaXcwUWtGQlNTeERRVUZETEUxQlFVMHNZMEZCVGl4RFFVRnhRaXhSUVVGUkxFZEJRVklzUTBGQmRFSXNSVUZCYjBNN096czdRVUZKY0VNc2QwTkJRVmtzU1VGQldpeERRVUZwUWl4UFFVRnFRaXhGUVVwdlF6dDVRa0ZCZUVNN2NVSkJSRW9zVFVGUFR5eEpRVUZKTEV0QlFVc3NZVUZCVEN4RlFVRnZRanM3UVVGRk0wSXNiME5CUVZrc1NVRkJXaXhEUVVGcFFpeFBRVUZxUWl4RlFVWXlRanR4UWtGQmVFSTdhVUpCVmxnN08wRkJaMEpCTEc5Q1FVRkpMRmRCUVZjc1dVRkJXU3hMUVVGYUxFVkJRVmdzUTBGMFJpdENPMEZCZFVadVF5eHZRa0ZCU1N4blFrRkJaMElzUTBGQmFFSXNRMEYyUml0Q08wRkJkMFp1UXl4dlFrRkJTU3hWUVVGVkxFVkJRVllzUTBGNFJpdENPMEZCZVVadVF5eHZRa0ZCU1N4VlFVRlZMRVZCUVZZc1EwRjZSaXRDTzBGQk1FWnVReXh2UWtGQlNTeFpRVUZLTEVOQk1VWnRRenM3UVVFMFJtNURMSEZDUVVGTExFbEJRVWtzU1VGQlNTeERRVUZLTEVWQlFVOHNTVUZCU1N4VlFVRlZMRTFCUVZZc1IwRkJiVUk3UVVGRGJrTXNkMEpCUVVrc1lVRkJZU3hWUVVGVkxFTkJRVllzUTBGQllpeERRVVFyUWp0QlFVVnVReXh0UTBGQlpTeFRRVUZUTEdGQlFWUXNRMEZCWmpzN08wRkJSbTFETERKQ1FVczFRaXhwUWtGQmFVSXNTVUZCYWtJc1NVRkJlVUlzVTBGQlV5eE5RVUZVTEVWQlFXbENPMEZCUXpkRExHZERRVUZSTEVsQlFWSXNRMEZCWVN4UFFVRlBMRkZCUVZBc1JVRkJhVUlzWVVGQmFrSXNSVUZCWjBNc1NVRkJhRU1zUTBGQllpeEZRVVEyUXp0QlFVVTNReXgxUTBGQlpTeFRRVUZUTEdGQlFWUXNRMEZCWml4RFFVWTJRenR4UWtGQmFrUTdPMEZCUzBFc2QwSkJRVWtzUTBGQlF5eFpRVUZFTEVsQlFXbENMR0ZCUVdFc1IwRkJZaXhMUVVGeFFpeFhRVUZYTEVkQlFWZ3NSVUZCWjBJN08wRkJSWFJFTERSQ1FVRkpMRmRCUVZjc1IwRkJXQ3hGUVVGblFqdEJRVU5vUWl4blEwRkJTU3huUWtGQlowSXNZVUZCWVN4SFFVRmlMRVZCUVd0Q096dEJRVVZzUXl4dlEwRkJTU3hOUVVGTkxHRkJRV0VzUjBGQllpeERRVUZPTEV0QlFUUkNMRWxCUVVrc1EwRkJTaXhGUVVGUE8wRkJRMjVETERSRFFVRlJMRWxCUVZJc1EwRkJZU3hQUVVGUExGRkJRVkFzUlVGQmFVSXNZVUZCYWtJc1JVRkJaME1zWVVGQllTeEhRVUZpTEVOQlFUZERMRVZCUkcxRE8wRkJSVzVETEcxRVFVRmxMRk5CUVZNc1lVRkJWQ3hEUVVGbU96dEJRVVp0UXl4M1EwRkpMMElzUTBGQlF5eFpRVUZFTEVsQlFXbENMR0ZCUVdFc1IwRkJZaXhMUVVGeFFpeFhRVUZYTEVkQlFWZ3NSVUZCWjBJN1FVRkRkRVFzWjBSQlFWRXNTVUZCVWl4RFFVRmhMRVZCUVVNc1MwRkJTeXhYUVVGWExFZEJRVmdzUlVGQlowSXNTVUZCU1N4RFFVRktMRVZCUVc1RExFVkJSSE5FT3pzN1FVRkJNVVFzZVVOQlNVczdRVUZEUkN3MFJFRkVRenQ1UTBGS1REdHBRMEZLU2l4TlFWbExPMEZCUTBRc05FTkJRVkVzU1VGQlVpeERRVUZoTEVWQlFVTXNTMEZCU3l4WFFVRlhMRWRCUVZnc1JVRkJaMElzU1VGQlNTeERRVUZLTEVWQlFXNURMRVZCUkVNN2FVTkJXa3c3TmtKQlJrb3NUVUZyUWtzN1FVRkRSQ3gzUTBGQlVTeEpRVUZTTEVOQlFXRXNSVUZCUXl4TFFVRkxMRmRCUVZjc1IwRkJXQ3hGUVVGblFpeEpRVUZKTEVOQlFVb3NSVUZCYmtNc1JVRkVRenMyUWtGc1FrdzdRVUZ4UWtFc1owTkJkRUpuUWpzN08wRkJRWEJDTERaQ1FYbENTeXhKUVVGSkxHZENRVUZuUWl4aFFVRmhMRWRCUVdJc1JVRkJhMEk3UVVGRGRrTXNkME5CUVZFc1NVRkJVaXhEUVVGaExFOUJRVThzVVVGQlVDeEZRVUZwUWl4aFFVRnFRaXhGUVVGblF5eGhRVUZoTEVkQlFXSXNRMEZCTjBNc1JVRkVkVU03TmtKQlFYUkRPM0ZDUVROQ1ZDeE5RU3RDU3p0QlFVTkVMSGREUVVSRE8wRkJSVVFzTkVKQlJrTTdjVUpCTDBKTU8ybENRVlpLT3pzN1FVRTFSbTFETEhWQ1FUUkpOMElzWjBKQlFXZENMRk5CUVZNc1RVRkJWQ3hGUVVGcFFqdEJRVU51UXl4dFEwRkJaU3hUUVVGVExHRkJRVlFzUTBGQlppeERRVVJ0UXp0QlFVVnVReXcwUWtGQlVTeEpRVUZTTEVOQlFXRXNUMEZCVHl4UlFVRlFMRVZCUVdsQ0xHRkJRV3BDTEVWQlFXZERMR2RDUVVGblFpeGhRVUZoTEVkQlFXSXNRMEZCTjBRc1JVRkdiVU03YVVKQlFYWkRPenM3TzBGQk5VbHRReXh2UWtGdFNpOUNMRkZCUVZFc1RVRkJVaXhMUVVGdFFpeFpRVUZ1UWl4SlFVRnRReXhEUVVGRExGRkJRVkVzVFVGQlVpeEZRVUZuUWp0QlFVTndSQ3d5UWtGQlR6dEJRVU5JTEd0RFFVRlZMRmRCUVZZN1FVRkRRU3dyUWtGQlR5eEpRVUZRTzNGQ1FVWktMRU5CUkc5RU8ybENRVUY0UkRzN1FVRlBRU3gxUWtGQlR6dEJRVU5JTERoQ1FVRlZMRmRCUVZZN1FVRkRRU3d5UWtGQlR6dEJRVU5JTEdsRFFVRlRMRTlCUVZRN1FVRkRRU3hwUTBGQlV5eFBRVUZVTzNGQ1FVWktPMmxDUVVaS0xFTkJNVXB0UXp0aFFVRjJRenM3UVVGdFMwRXNjVUpCUVZNc1RVRkJWQ3hEUVVGblFpeEhRVUZvUWl4RlFVRnhRaXhMUVVGeVFpeEZRVUUwUWl4SFFVRTFRaXhGUVVGcFF6dEJRVU0zUWl4dlFrRkJTU3hOUVVGS0xFTkJRVmNzUzBGQldDeEZRVUZyUWl4RFFVRnNRaXhGUVVRMlFqczdRVUZITjBJc2RVSkJRVTg3UVVGRFNDd3dRa0ZCVFN4TFFVRk9PMEZCUTBFc2VVSkJRVXNzUjBGQlREdHBRa0ZHU2l4RFFVZzJRanRoUVVGcVF6czdRVUZUUVN4eFFrRkJVeXhSUVVGVUxFTkJRV3RDTEZGQlFXeENMRVZCUVRSQ08wRkJRM2hDTEc5Q1FVRkpMRTlCUVU4c1JVRkJVQ3hEUVVSdlFqdEJRVVY0UWl4dlFrRkJTU3hQUVVGUExFVkJRVkFzUTBGR2IwSTdRVUZIZUVJc2IwSkJRVWtzVTBGQlV5eFRRVUZUTEUxQlFWUXNRMEZJVnpzN1FVRkxlRUlzY1VKQlFVc3NTVUZCU1N4SlFVRkpMRU5CUVVvc1JVRkJUeXhKUVVGSkxFMUJRVW9zUlVGQldTeEhRVUUxUWl4RlFVRnBRenRCUVVNM1FpeDNRa0ZCU1N4UlFVRlJMRk5CUVZNc1EwRkJWQ3hEUVVGU0xFTkJSSGxDT3p0QlFVYzNRaXgzUWtGQlNTeE5RVUZOTEVkQlFVNHNSVUZCVnp0QlFVTllMRFpDUVVGTExFMUJRVTBzUjBGQlRpeERRVUZNTEVkQlFXdENMRU5CUVd4Q0xFTkJSRmM3Y1VKQlFXWXNUVUZGVHp0QlFVTklMRFpDUVVGTExFbEJRVXdzUTBGQlZTeERRVUZXTEVWQlJFYzdjVUpCUmxBN2FVSkJTRW83TzBGQlZVRXNkVUpCUVU4N1FVRkRTQ3d3UWtGQlRTeEpRVUZPTzBGQlEwRXNNRUpCUVUwc1NVRkJUanRCUVVaSExHbENRVUZRTEVOQlpuZENPMkZCUVRWQ096dEJRWEZDUVN4eFFrRkJVeXhYUVVGVUxFTkJRWEZDTEV0QlFYSkNMRVZCUVRSQ0xFdEJRVFZDTEVWQlFXMURPMEZCUXk5Q0xHOUNRVUZKTEV0QlFVb3NSVUZCVnp0QlFVTlFMSGRDUVVGSkxGRkJRVkVzUzBGQlVpeERRVUZLTEVWQlFXOUNPMEZCUTJoQ0xEaENRVUZOTEVsQlFVNHNRMEZCVnl4TFFVRllMRVZCUkdkQ08zRkNRVUZ3UWl4TlFVVlBPMEZCUTBnc1owTkJRVkVzUTBGQlF5eExRVUZFTEVWQlFWRXNTMEZCVWl4RFFVRlNMRU5CUkVjN2NVSkJSbEE3TzBGQlRVRXNNa0pCUVU4c1MwRkJVQ3hEUVZCUE8ybENRVUZZTEUxQlVVODdRVUZEU0N3eVFrRkJUeXhMUVVGUUxFTkJSRWM3YVVKQlVsQTdZVUZFU2p0VFFTOWFLME1zUlVFMllUZERMRVZCUVVNc2VVSkJRWGRDTEVWQlFYaENMRVZCUVRKQ0xIRkNRVUZ2UWl4RlFVRndRaXhGUVVGMVFpeHhRa0ZCYjBJc1JVRkJjRUlzUlVGQmRVSXNjVUpCUVc5Q0xFVkJRWEJDTEVWQlFYVkNMSE5DUVVGeFFpeEZRVUZ5UWl4RlFVRjNRaXh0UWtGQmEwSXNSVUZCYkVJc1JVRkJjVUlzWjBKQlFXVXNSVUZCWml4RlFVRnJRaXhqUVVGaExFVkJRV0lzUlVFM1lYQklMRU5CUVVnc1JVRTVkVU0xUWl4RlFUSndSSE5MTEVWQk0zQkVkRXNzUlVFeWNFUjVTeXhEUVVGRExFTkJRVVFzUTBFemNFUjZTeXhGUVRKd1JEaExMRU5CTTNCRU9Vc3NRMEZCVUN4RFFVWkxPME5CUVZnc1EwRkdSVHM3UVVGcmNVUktMR1ZCUVdVc1ZVRkJaaUlzSW1acGJHVWlPaUpzYVdJdmRtbHlkSFZoYkMxa2IyMHVhbk1pTENKemIzVnlZMlZ6UTI5dWRHVnVkQ0k2V3lKc1pYUWdWbWx5ZEhWaGJFUlBUU0E5SUdaMWJtTjBhVzl1S0dVcElIdGNiaUFnY21WMGRYSnVJR1VvS1R0Y2JuMG9ablZ1WTNScGIyNG9LU0I3WEc0Z0lDQWdJQ0FnSUhaaGNpQmtaV1pwYm1Vc0lHMXZaSFZzWlN3Z1pYaHdiM0owY3p0Y2JpQWdJQ0FnSUNBZ2NtVjBkWEp1SUNobWRXNWpkR2x2YmlCbEtIUXNJRzRzSUhJcElIdGNiaUFnSUNBZ0lDQWdJQ0FnSUNBZ0lDQm1kVzVqZEdsdmJpQnpLRzhzSUhVcElIdGNiaUFnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnYVdZZ0tDRnVXMjlkS1NCN1hHNGdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNCcFppQW9JWFJiYjEwcElIdGNiaUFnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0IyWVhJZ1lTQTlJSFI1Y0dWdlppQnlaWEYxYVhKbElEMDlJRndpWm5WdVkzUnBiMjVjSWlBbUppQnlaWEYxYVhKbE8xeHVJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJR2xtSUNnaGRTQW1KaUJoS1NCeVpYUjFjbTRnWVNodkxDQWhNQ2s3WEc0Z0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ2FXWWdLR2twSUhKbGRIVnliaUJwS0c4c0lDRXdLVHRjYmlBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNCMllYSWdaaUE5SUc1bGR5QkZjbkp2Y2loY0lrTmhibTV2ZENCbWFXNWtJRzF2WkhWc1pTQW5YQ0lnS3lCdklDc2dYQ0luWENJcE8xeHVJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJSFJvY205M0lHWXVZMjlrWlNBOUlGd2lUVTlFVlV4RlgwNVBWRjlHVDFWT1JGd2lMQ0JtWEc0Z0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0I5WEc0Z0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0IyWVhJZ2JDQTlJRzViYjEwZ1BTQjdYRzRnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnWlhod2IzSjBjem9nZTMxY2JpQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUgwN1hHNGdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNCMFcyOWRXekJkTG1OaGJHd29iQzVsZUhCdmNuUnpMQ0JtZFc1amRHbHZiaWhsS1NCN1hHNGdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdkbUZ5SUc0Z1BTQjBXMjlkV3pGZFcyVmRPMXh1SUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUhKbGRIVnliaUJ6S0c0Z1B5QnVJRG9nWlNsY2JpQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUgwc0lHd3NJR3d1Wlhod2IzSjBjeXdnWlN3Z2RDd2diaXdnY2lsY2JpQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdmVnh1SUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNCeVpYUjFjbTRnYmx0dlhTNWxlSEJ2Y25SelhHNGdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ2ZWeHVJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lIWmhjaUJwSUQwZ2RIbHdaVzltSUhKbGNYVnBjbVVnUFQwZ1hDSm1kVzVqZEdsdmJsd2lJQ1ltSUhKbGNYVnBjbVU3WEc0Z0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnWm05eUlDaDJZWElnYnlBOUlEQTdJRzhnUENCeUxteGxibWQwYURzZ2J5c3JLU0J6S0hKYmIxMHBPMXh1SUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJSEpsZEhWeWJpQnpYRzRnSUNBZ0lDQWdJQ0FnSUNCOUtTaDdYRzRnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSURFNklGdG1kVzVqZEdsdmJpaHlaWEYxYVhKbExDQnRiMlIxYkdVc0lHVjRjRzl5ZEhNcElIdGNibHh1ZG1GeUlHTnlaV0YwWlVWc1pXMWxiblFnUFNCeVpYRjFhWEpsS0Z3aUxpOTJaRzl0TDJOeVpXRjBaUzFsYkdWdFpXNTBMbXB6WENJcFhHNWNibTF2WkhWc1pTNWxlSEJ2Y25SeklEMGdZM0psWVhSbFJXeGxiV1Z1ZEZ4dVhHNTlMSHRjSWk0dmRtUnZiUzlqY21WaGRHVXRaV3hsYldWdWRDNXFjMXdpT2pFMWZWMHNNanBiWm5WdVkzUnBiMjRvY21WeGRXbHlaU3h0YjJSMWJHVXNaWGh3YjNKMGN5bDdYRzUyWVhJZ1pHbG1aaUE5SUhKbGNYVnBjbVVvWENJdUwzWjBjbVZsTDJScFptWXVhbk5jSWlsY2JseHViVzlrZFd4bExtVjRjRzl5ZEhNZ1BTQmthV1ptWEc1Y2JuMHNlMXdpTGk5MmRISmxaUzlrYVdabUxtcHpYQ0k2TXpWOVhTd3pPbHRtZFc1amRHbHZiaWh5WlhGMWFYSmxMRzF2WkhWc1pTeGxlSEJ2Y25SektYdGNiblpoY2lCb0lEMGdjbVZ4ZFdseVpTaGNJaTR2ZG1seWRIVmhiQzFvZVhCbGNuTmpjbWx3ZEM5cGJtUmxlQzVxYzF3aUtWeHVYRzV0YjJSMWJHVXVaWGh3YjNKMGN5QTlJR2hjYmx4dWZTeDdYQ0l1TDNacGNuUjFZV3d0YUhsd1pYSnpZM0pwY0hRdmFXNWtaWGd1YW5OY0lqb3lNbjFkTERRNlcyWjFibU4wYVc5dUtISmxjWFZwY21Vc2JXOWtkV3hsTEdWNGNHOXlkSE1wZTF4dWRtRnlJR1JwWm1ZZ1BTQnlaWEYxYVhKbEtGd2lMaTlrYVdabUxtcHpYQ0lwWEc1MllYSWdjR0YwWTJnZ1BTQnlaWEYxYVhKbEtGd2lMaTl3WVhSamFDNXFjMXdpS1Z4dWRtRnlJR2dnUFNCeVpYRjFhWEpsS0Z3aUxpOW9MbXB6WENJcFhHNTJZWElnWTNKbFlYUmxJRDBnY21WeGRXbHlaU2hjSWk0dlkzSmxZWFJsTFdWc1pXMWxiblF1YW5OY0lpbGNiblpoY2lCV1RtOWtaU0E5SUhKbGNYVnBjbVVvSnk0dmRtNXZaR1V2ZG01dlpHVXVhbk1uS1Z4dWRtRnlJRlpVWlhoMElEMGdjbVZ4ZFdseVpTZ25MaTkyYm05a1pTOTJkR1Y0ZEM1cWN5Y3BYRzVjYm0xdlpIVnNaUzVsZUhCdmNuUnpJRDBnZTF4dUlDQWdJR1JwWm1ZNklHUnBabVlzWEc0Z0lDQWdjR0YwWTJnNklIQmhkR05vTEZ4dUlDQWdJR2c2SUdnc1hHNGdJQ0FnWTNKbFlYUmxPaUJqY21WaGRHVXNYRzRnSUNBZ1ZrNXZaR1U2SUZaT2IyUmxMRnh1SUNBZ0lGWlVaWGgwT2lCV1ZHVjRkRnh1ZlZ4dVhHNTlMSHRjSWk0dlkzSmxZWFJsTFdWc1pXMWxiblF1YW5OY0lqb3hMRndpTGk5a2FXWm1MbXB6WENJNk1peGNJaTR2YUM1cWMxd2lPak1zWENJdUwzQmhkR05vTG1welhDSTZNVE1zWENJdUwzWnViMlJsTDNadWIyUmxMbXB6WENJNk16RXNYQ0l1TDNadWIyUmxMM1owWlhoMExtcHpYQ0k2TXpOOVhTdzFPbHRtZFc1amRHbHZiaWh5WlhGMWFYSmxMRzF2WkhWc1pTeGxlSEJ2Y25SektYdGNiaThxSVZ4dUlDb2dRM0p2YzNNdFFuSnZkM05sY2lCVGNHeHBkQ0F4TGpFdU1WeHVJQ29nUTI5d2VYSnBaMmgwSURJd01EY3RNakF4TWlCVGRHVjJaVzRnVEdWMmFYUm9ZVzRnUEhOMFpYWmxibXhsZG1sMGFHRnVMbU52YlQ1Y2JpQXFJRUYyWVdsc1lXSnNaU0IxYm1SbGNpQjBhR1VnVFVsVUlFeHBZMlZ1YzJWY2JpQXFJRVZEVFVGVFkzSnBjSFFnWTI5dGNHeHBZVzUwTENCMWJtbG1iM0p0SUdOeWIzTnpMV0p5YjNkelpYSWdjM0JzYVhRZ2JXVjBhRzlrWEc0Z0tpOWNibHh1THlvcVhHNGdLaUJUY0d4cGRITWdZU0J6ZEhKcGJtY2dhVzUwYnlCaGJpQmhjbkpoZVNCdlppQnpkSEpwYm1keklIVnphVzVuSUdFZ2NtVm5aWGdnYjNJZ2MzUnlhVzVuSUhObGNHRnlZWFJ2Y2k0Z1RXRjBZMmhsY3lCdlppQjBhR1ZjYmlBcUlITmxjR0Z5WVhSdmNpQmhjbVVnYm05MElHbHVZMngxWkdWa0lHbHVJSFJvWlNCeVpYTjFiSFFnWVhKeVlYa3VJRWh2ZDJWMlpYSXNJR2xtSUdCelpYQmhjbUYwYjNKZ0lHbHpJR0VnY21WblpYZ2dkR2hoZENCamIyNTBZV2x1YzF4dUlDb2dZMkZ3ZEhWeWFXNW5JR2R5YjNWd2N5d2dZbUZqYTNKbFptVnlaVzVqWlhNZ1lYSmxJSE53YkdsalpXUWdhVzUwYnlCMGFHVWdjbVZ6ZFd4MElHVmhZMmdnZEdsdFpTQmdjMlZ3WVhKaGRHOXlZQ0JwY3lCdFlYUmphR1ZrTGx4dUlDb2dSbWw0WlhNZ1luSnZkM05sY2lCaWRXZHpJR052YlhCaGNtVmtJSFJ2SUhSb1pTQnVZWFJwZG1VZ1lGTjBjbWx1Wnk1d2NtOTBiM1I1Y0dVdWMzQnNhWFJnSUdGdVpDQmpZVzRnWW1VZ2RYTmxaQ0J5Wld4cFlXSnNlVnh1SUNvZ1kzSnZjM010WW5KdmQzTmxjaTVjYmlBcUlFQndZWEpoYlNCN1UzUnlhVzVuZlNCemRISWdVM1J5YVc1bklIUnZJSE53YkdsMExseHVJQ29nUUhCaGNtRnRJSHRTWldkRmVIQjhVM1J5YVc1bmZTQnpaWEJoY21GMGIzSWdVbVZuWlhnZ2IzSWdjM1J5YVc1bklIUnZJSFZ6WlNCbWIzSWdjMlZ3WVhKaGRHbHVaeUIwYUdVZ2MzUnlhVzVuTGx4dUlDb2dRSEJoY21GdElIdE9kVzFpWlhKOUlGdHNhVzFwZEYwZ1RXRjRhVzExYlNCdWRXMWlaWElnYjJZZ2FYUmxiWE1nZEc4Z2FXNWpiSFZrWlNCcGJpQjBhR1VnY21WemRXeDBJR0Z5Y21GNUxseHVJQ29nUUhKbGRIVnlibk1nZTBGeWNtRjVmU0JCY25KaGVTQnZaaUJ6ZFdKemRISnBibWR6TGx4dUlDb2dRR1Y0WVcxd2JHVmNiaUFxWEc0Z0tpQXZMeUJDWVhOcFl5QjFjMlZjYmlBcUlITndiR2wwS0NkaElHSWdZeUJrSnl3Z0p5QW5LVHRjYmlBcUlDOHZJQzArSUZzbllTY3NJQ2RpSnl3Z0oyTW5MQ0FuWkNkZFhHNGdLbHh1SUNvZ0x5OGdWMmwwYUNCc2FXMXBkRnh1SUNvZ2MzQnNhWFFvSjJFZ1lpQmpJR1FuTENBbklDY3NJRElwTzF4dUlDb2dMeThnTFQ0Z1d5ZGhKeXdnSjJJblhWeHVJQ3BjYmlBcUlDOHZJRUpoWTJ0eVpXWmxjbVZ1WTJWeklHbHVJSEpsYzNWc2RDQmhjbkpoZVZ4dUlDb2djM0JzYVhRb0p5NHVkMjl5WkRFZ2QyOXlaREl1TGljc0lDOG9XMkV0ZWwwcktTaGNYR1FyS1M5cEtUdGNiaUFxSUM4dklDMCtJRnNuTGk0bkxDQW5kMjl5WkNjc0lDY3hKeXdnSnlBbkxDQW5kMjl5WkNjc0lDY3lKeXdnSnk0dUoxMWNiaUFxTDF4dWJXOWtkV3hsTG1WNGNHOXlkSE1nUFNBb1puVnVZM1JwYjI0Z2MzQnNhWFFvZFc1a1pXWXBJSHRjYmx4dUlDQjJZWElnYm1GMGFYWmxVM0JzYVhRZ1BTQlRkSEpwYm1jdWNISnZkRzkwZVhCbExuTndiR2wwTEZ4dUlDQWdJR052YlhCc2FXRnVkRVY0WldOT2NHTm5JRDBnTHlncFB6OHZMbVY0WldNb1hDSmNJaWxiTVYwZ1BUMDlJSFZ1WkdWbUxGeHVJQ0FnSUM4dklFNVFRMGM2SUc1dmJuQmhjblJwWTJsd1lYUnBibWNnWTJGd2RIVnlhVzVuSUdkeWIzVndYRzRnSUNBZ2MyVnNaanRjYmx4dUlDQnpaV3htSUQwZ1puVnVZM1JwYjI0b2MzUnlMQ0J6WlhCaGNtRjBiM0lzSUd4cGJXbDBLU0I3WEc0Z0lDQWdMeThnU1dZZ1lITmxjR0Z5WVhSdmNtQWdhWE1nYm05MElHRWdjbVZuWlhnc0lIVnpaU0JnYm1GMGFYWmxVM0JzYVhSZ1hHNGdJQ0FnYVdZZ0tFOWlhbVZqZEM1d2NtOTBiM1I1Y0dVdWRHOVRkSEpwYm1jdVkyRnNiQ2h6WlhCaGNtRjBiM0lwSUNFOVBTQmNJbHR2WW1wbFkzUWdVbVZuUlhod1hWd2lLU0I3WEc0Z0lDQWdJQ0J5WlhSMWNtNGdibUYwYVhabFUzQnNhWFF1WTJGc2JDaHpkSElzSUhObGNHRnlZWFJ2Y2l3Z2JHbHRhWFFwTzF4dUlDQWdJSDFjYmlBZ0lDQjJZWElnYjNWMGNIVjBJRDBnVzEwc1hHNGdJQ0FnSUNCbWJHRm5jeUE5SUNoelpYQmhjbUYwYjNJdWFXZHViM0psUTJGelpTQS9JRndpYVZ3aUlEb2dYQ0pjSWlrZ0t5QW9jMlZ3WVhKaGRHOXlMbTExYkhScGJHbHVaU0EvSUZ3aWJWd2lJRG9nWENKY0lpa2dLeUFvYzJWd1lYSmhkRzl5TG1WNGRHVnVaR1ZrSUQ4Z1hDSjRYQ0lnT2lCY0lsd2lLU0FySUM4dklGQnliM0J2YzJWa0lHWnZjaUJGVXpaY2JpQWdJQ0FnSUNoelpYQmhjbUYwYjNJdWMzUnBZMnQ1SUQ4Z1hDSjVYQ0lnT2lCY0lsd2lLU3hjYmlBZ0lDQWdJQzh2SUVacGNtVm1iM2dnTXl0Y2JpQWdJQ0FnSUd4aGMzUk1ZWE4wU1c1a1pYZ2dQU0F3TEZ4dUlDQWdJQ0FnTHk4Z1RXRnJaU0JnWjJ4dlltRnNZQ0JoYm1RZ1lYWnZhV1FnWUd4aGMzUkpibVJsZUdBZ2FYTnpkV1Z6SUdKNUlIZHZjbXRwYm1jZ2QybDBhQ0JoSUdOdmNIbGNiaUFnSUNBZ0lITmxjR0Z5WVhSdmNpQTlJRzVsZHlCU1pXZEZlSEFvYzJWd1lYSmhkRzl5TG5OdmRYSmpaU3dnWm14aFozTWdLeUJjSW1kY0lpa3NYRzRnSUNBZ0lDQnpaWEJoY21GMGIzSXlMQ0J0WVhSamFDd2diR0Z6ZEVsdVpHVjRMQ0JzWVhOMFRHVnVaM1JvTzF4dUlDQWdJSE4wY2lBclBTQmNJbHdpT3lBdkx5QlVlWEJsTFdOdmJuWmxjblJjYmlBZ0lDQnBaaUFvSVdOdmJYQnNhV0Z1ZEVWNFpXTk9jR05uS1NCN1hHNGdJQ0FnSUNBdkx5QkViMlZ6YmlkMElHNWxaV1FnWm14aFozTWdaM2tzSUdKMWRDQjBhR1Y1SUdSdmJpZDBJR2gxY25SY2JpQWdJQ0FnSUhObGNHRnlZWFJ2Y2pJZ1BTQnVaWGNnVW1WblJYaHdLRndpWGx3aUlDc2djMlZ3WVhKaGRHOXlMbk52ZFhKalpTQXJJRndpSkNnL0lWeGNYRnh6S1Z3aUxDQm1iR0ZuY3lrN1hHNGdJQ0FnZlZ4dUlDQWdJQzhxSUZaaGJIVmxjeUJtYjNJZ1lHeHBiV2wwWUN3Z2NHVnlJSFJvWlNCemNHVmpPbHh1SUNBZ0lDQXFJRWxtSUhWdVpHVm1hVzVsWkRvZ05ESTVORGsyTnpJNU5TQXZMeUJOWVhSb0xuQnZkeWd5TENBek1pa2dMU0F4WEc0Z0lDQWdJQ29nU1dZZ01Dd2dTVzVtYVc1cGRIa3NJRzl5SUU1aFRqb2dNRnh1SUNBZ0lDQXFJRWxtSUhCdmMybDBhWFpsSUc1MWJXSmxjam9nYkdsdGFYUWdQU0JOWVhSb0xtWnNiMjl5S0d4cGJXbDBLVHNnYVdZZ0tHeHBiV2wwSUQ0Z05ESTVORGsyTnpJNU5Ta2diR2x0YVhRZ0xUMGdOREk1TkRrMk56STVOanRjYmlBZ0lDQWdLaUJKWmlCdVpXZGhkR2wyWlNCdWRXMWlaWEk2SURReU9UUTVOamN5T1RZZ0xTQk5ZWFJvTG1ac2IyOXlLRTFoZEdndVlXSnpLR3hwYldsMEtTbGNiaUFnSUNBZ0tpQkpaaUJ2ZEdobGNqb2dWSGx3WlMxamIyNTJaWEowTENCMGFHVnVJSFZ6WlNCMGFHVWdZV0p2ZG1VZ2NuVnNaWE5jYmlBZ0lDQWdLaTljYmlBZ0lDQnNhVzFwZENBOUlHeHBiV2wwSUQwOVBTQjFibVJsWmlBL0lDMHhJRDQrUGlBd0lEb2dMeThnVFdGMGFDNXdiM2NvTWl3Z016SXBJQzBnTVZ4dUlDQWdJR3hwYldsMElENCtQaUF3T3lBdkx5QlViMVZwYm5Rek1paHNhVzFwZENsY2JpQWdJQ0IzYUdsc1pTQW9iV0YwWTJnZ1BTQnpaWEJoY21GMGIzSXVaWGhsWXloemRISXBLU0I3WEc0Z0lDQWdJQ0F2THlCZ2MyVndZWEpoZEc5eUxteGhjM1JKYm1SbGVHQWdhWE1nYm05MElISmxiR2xoWW14bElHTnliM056TFdKeWIzZHpaWEpjYmlBZ0lDQWdJR3hoYzNSSmJtUmxlQ0E5SUcxaGRHTm9MbWx1WkdWNElDc2diV0YwWTJoYk1GMHViR1Z1WjNSb08xeHVJQ0FnSUNBZ2FXWWdLR3hoYzNSSmJtUmxlQ0ErSUd4aGMzUk1ZWE4wU1c1a1pYZ3BJSHRjYmlBZ0lDQWdJQ0FnYjNWMGNIVjBMbkIxYzJnb2MzUnlMbk5zYVdObEtHeGhjM1JNWVhOMFNXNWtaWGdzSUcxaGRHTm9MbWx1WkdWNEtTazdYRzRnSUNBZ0lDQWdJQzh2SUVacGVDQmljbTkzYzJWeWN5QjNhRzl6WlNCZ1pYaGxZMkFnYldWMGFHOWtjeUJrYjI0bmRDQmpiMjV6YVhOMFpXNTBiSGtnY21WMGRYSnVJR0IxYm1SbFptbHVaV1JnSUdadmNseHVJQ0FnSUNBZ0lDQXZMeUJ1YjI1d1lYSjBhV05wY0dGMGFXNW5JR05oY0hSMWNtbHVaeUJuY205MWNITmNiaUFnSUNBZ0lDQWdhV1lnS0NGamIyMXdiR2xoYm5SRmVHVmpUbkJqWnlBbUppQnRZWFJqYUM1c1pXNW5kR2dnUGlBeEtTQjdYRzRnSUNBZ0lDQWdJQ0FnYldGMFkyaGJNRjB1Y21Wd2JHRmpaU2h6WlhCaGNtRjBiM0l5TENCbWRXNWpkR2x2YmlncElIdGNiaUFnSUNBZ0lDQWdJQ0FnSUdadmNpQW9kbUZ5SUdrZ1BTQXhPeUJwSUR3Z1lYSm5kVzFsYm5SekxteGxibWQwYUNBdElESTdJR2tyS3lrZ2UxeHVJQ0FnSUNBZ0lDQWdJQ0FnSUNCcFppQW9ZWEpuZFcxbGJuUnpXMmxkSUQwOVBTQjFibVJsWmlrZ2UxeHVJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lHMWhkR05vVzJsZElEMGdkVzVrWldZN1hHNGdJQ0FnSUNBZ0lDQWdJQ0FnSUgxY2JpQWdJQ0FnSUNBZ0lDQWdJSDFjYmlBZ0lDQWdJQ0FnSUNCOUtUdGNiaUFnSUNBZ0lDQWdmVnh1SUNBZ0lDQWdJQ0JwWmlBb2JXRjBZMmd1YkdWdVozUm9JRDRnTVNBbUppQnRZWFJqYUM1cGJtUmxlQ0E4SUhOMGNpNXNaVzVuZEdncElIdGNiaUFnSUNBZ0lDQWdJQ0JCY25KaGVTNXdjbTkwYjNSNWNHVXVjSFZ6YUM1aGNIQnNlU2h2ZFhSd2RYUXNJRzFoZEdOb0xuTnNhV05sS0RFcEtUdGNiaUFnSUNBZ0lDQWdmVnh1SUNBZ0lDQWdJQ0JzWVhOMFRHVnVaM1JvSUQwZ2JXRjBZMmhiTUYwdWJHVnVaM1JvTzF4dUlDQWdJQ0FnSUNCc1lYTjBUR0Z6ZEVsdVpHVjRJRDBnYkdGemRFbHVaR1Y0TzF4dUlDQWdJQ0FnSUNCcFppQW9iM1YwY0hWMExteGxibWQwYUNBK1BTQnNhVzFwZENrZ2UxeHVJQ0FnSUNBZ0lDQWdJR0p5WldGck8xeHVJQ0FnSUNBZ0lDQjlYRzRnSUNBZ0lDQjlYRzRnSUNBZ0lDQnBaaUFvYzJWd1lYSmhkRzl5TG14aGMzUkpibVJsZUNBOVBUMGdiV0YwWTJndWFXNWtaWGdwSUh0Y2JpQWdJQ0FnSUNBZ2MyVndZWEpoZEc5eUxteGhjM1JKYm1SbGVDc3JPeUF2THlCQmRtOXBaQ0JoYmlCcGJtWnBibWwwWlNCc2IyOXdYRzRnSUNBZ0lDQjlYRzRnSUNBZ2ZWeHVJQ0FnSUdsbUlDaHNZWE4wVEdGemRFbHVaR1Y0SUQwOVBTQnpkSEl1YkdWdVozUm9LU0I3WEc0Z0lDQWdJQ0JwWmlBb2JHRnpkRXhsYm1kMGFDQjhmQ0FoYzJWd1lYSmhkRzl5TG5SbGMzUW9YQ0pjSWlrcElIdGNiaUFnSUNBZ0lDQWdiM1YwY0hWMExuQjFjMmdvWENKY0lpazdYRzRnSUNBZ0lDQjlYRzRnSUNBZ2ZTQmxiSE5sSUh0Y2JpQWdJQ0FnSUc5MWRIQjFkQzV3ZFhOb0tITjBjaTV6YkdsalpTaHNZWE4wVEdGemRFbHVaR1Y0S1NrN1hHNGdJQ0FnZlZ4dUlDQWdJSEpsZEhWeWJpQnZkWFJ3ZFhRdWJHVnVaM1JvSUQ0Z2JHbHRhWFFnUHlCdmRYUndkWFF1YzJ4cFkyVW9NQ3dnYkdsdGFYUXBJRG9nYjNWMGNIVjBPMXh1SUNCOU8xeHVYRzRnSUhKbGRIVnliaUJ6Wld4bU8xeHVmU2tvS1R0Y2JseHVmU3g3ZlYwc05qcGJablZ1WTNScGIyNG9jbVZ4ZFdseVpTeHRiMlIxYkdVc1pYaHdiM0owY3lsN1hHNWNibjBzZTMxZExEYzZXMloxYm1OMGFXOXVLSEpsY1hWcGNtVXNiVzlrZFd4bExHVjRjRzl5ZEhNcGUxeHVKM1Z6WlNCemRISnBZM1FuTzF4dVhHNTJZWElnVDI1bFZtVnljMmx2YmtOdmJuTjBjbUZwYm5RZ1BTQnlaWEYxYVhKbEtDZHBibVJwZG1sa2RXRnNMMjl1WlMxMlpYSnphVzl1SnlrN1hHNWNiblpoY2lCTldWOVdSVkpUU1U5T0lEMGdKemNuTzF4dVQyNWxWbVZ5YzJsdmJrTnZibk4wY21GcGJuUW9KMlYyTFhOMGIzSmxKeXdnVFZsZlZrVlNVMGxQVGlrN1hHNWNiblpoY2lCb1lYTm9TMlY1SUQwZ0oxOWZSVlpmVTFSUFVrVmZTMFZaUUNjZ0t5Qk5XVjlXUlZKVFNVOU9PMXh1WEc1dGIyUjFiR1V1Wlhod2IzSjBjeUE5SUVWMlUzUnZjbVU3WEc1Y2JtWjFibU4wYVc5dUlFVjJVM1J2Y21Vb1pXeGxiU2tnZTF4dUlDQWdJSFpoY2lCb1lYTm9JRDBnWld4bGJWdG9ZWE5vUzJWNVhUdGNibHh1SUNBZ0lHbG1JQ2doYUdGemFDa2dlMXh1SUNBZ0lDQWdJQ0JvWVhOb0lEMGdaV3hsYlZ0b1lYTm9TMlY1WFNBOUlIdDlPMXh1SUNBZ0lIMWNibHh1SUNBZ0lISmxkSFZ5YmlCb1lYTm9PMXh1ZlZ4dVhHNTlMSHRjSW1sdVpHbDJhV1IxWVd3dmIyNWxMWFpsY25OcGIyNWNJam81ZlYwc09EcGJablZ1WTNScGIyNG9jbVZ4ZFdseVpTeHRiMlIxYkdVc1pYaHdiM0owY3lsN1hHNG9ablZ1WTNScGIyNGdLR2RzYjJKaGJDbDdYRzRuZFhObElITjBjbWxqZENjN1hHNWNiaThxWjJ4dlltRnNJSGRwYm1SdmR5d2daMnh2WW1Gc0tpOWNibHh1ZG1GeUlISnZiM1FnUFNCMGVYQmxiMllnZDJsdVpHOTNJQ0U5UFNBbmRXNWtaV1pwYm1Wa0p5QS9YRzRnSUNBZ2QybHVaRzkzSURvZ2RIbHdaVzltSUdkc2IySmhiQ0FoUFQwZ0ozVnVaR1ZtYVc1bFpDY2dQMXh1SUNBZ0lHZHNiMkpoYkNBNklIdDlPMXh1WEc1dGIyUjFiR1V1Wlhod2IzSjBjeUE5SUVsdVpHbDJhV1IxWVd3N1hHNWNibVoxYm1OMGFXOXVJRWx1WkdsMmFXUjFZV3dvYTJWNUxDQjJZV3gxWlNrZ2UxeHVJQ0FnSUdsbUlDaHJaWGtnYVc0Z2NtOXZkQ2tnZTF4dUlDQWdJQ0FnSUNCeVpYUjFjbTRnY205dmRGdHJaWGxkTzF4dUlDQWdJSDFjYmx4dUlDQWdJSEp2YjNSYmEyVjVYU0E5SUhaaGJIVmxPMXh1WEc0Z0lDQWdjbVYwZFhKdUlIWmhiSFZsTzF4dWZWeHVYRzU5S1M1allXeHNLSFJvYVhNc2RIbHdaVzltSUdkc2IySmhiQ0FoUFQwZ1hDSjFibVJsWm1sdVpXUmNJaUEvSUdkc2IySmhiQ0E2SUhSNWNHVnZaaUJ6Wld4bUlDRTlQU0JjSW5WdVpHVm1hVzVsWkZ3aUlEOGdjMlZzWmlBNklIUjVjR1Z2WmlCM2FXNWtiM2NnSVQwOUlGd2lkVzVrWldacGJtVmtYQ0lnUHlCM2FXNWtiM2NnT2lCN2ZTbGNibjBzZTMxZExEazZXMloxYm1OMGFXOXVLSEpsY1hWcGNtVXNiVzlrZFd4bExHVjRjRzl5ZEhNcGUxeHVKM1Z6WlNCemRISnBZM1FuTzF4dVhHNTJZWElnU1c1a2FYWnBaSFZoYkNBOUlISmxjWFZwY21Vb0p5NHZhVzVrWlhndWFuTW5LVHRjYmx4dWJXOWtkV3hsTG1WNGNHOXlkSE1nUFNCUGJtVldaWEp6YVc5dU8xeHVYRzVtZFc1amRHbHZiaUJQYm1WV1pYSnphVzl1S0cxdlpIVnNaVTVoYldVc0lIWmxjbk5wYjI0c0lHUmxabUYxYkhSV1lXeDFaU2tnZTF4dUlDQWdJSFpoY2lCclpYa2dQU0FuWDE5SlRrUkpWa2xFVlVGTVgwOU9SVjlXUlZKVFNVOU9YeWNnS3lCdGIyUjFiR1ZPWVcxbE8xeHVJQ0FnSUhaaGNpQmxibVp2Y21ObFMyVjVJRDBnYTJWNUlDc2dKMTlGVGtaUFVrTkZYMU5KVGtkTVJWUlBUaWM3WEc1Y2JpQWdJQ0IyWVhJZ2RtVnljMmx2YmxaaGJIVmxJRDBnU1c1a2FYWnBaSFZoYkNobGJtWnZjbU5sUzJWNUxDQjJaWEp6YVc5dUtUdGNibHh1SUNBZ0lHbG1JQ2gyWlhKemFXOXVWbUZzZFdVZ0lUMDlJSFpsY25OcGIyNHBJSHRjYmlBZ0lDQWdJQ0FnZEdoeWIzY2dibVYzSUVWeWNtOXlLQ2REWVc0Z2IyNXNlU0JvWVhabElHOXVaU0JqYjNCNUlHOW1JQ2NnSzF4dUlDQWdJQ0FnSUNBZ0lDQWdiVzlrZFd4bFRtRnRaU0FySUNjdVhGeHVKeUFyWEc0Z0lDQWdJQ0FnSUNBZ0lDQW5XVzkxSUdGc2NtVmhaSGtnYUdGMlpTQjJaWEp6YVc5dUlDY2dLeUIyWlhKemFXOXVWbUZzZFdVZ0sxeHVJQ0FnSUNBZ0lDQWdJQ0FnSnlCcGJuTjBZV3hzWldRdVhGeHVKeUFyWEc0Z0lDQWdJQ0FnSUNBZ0lDQW5WR2hwY3lCdFpXRnVjeUI1YjNVZ1kyRnVibTkwSUdsdWMzUmhiR3dnZG1WeWMybHZiaUFuSUNzZ2RtVnljMmx2YmlrN1hHNGdJQ0FnZlZ4dVhHNGdJQ0FnY21WMGRYSnVJRWx1WkdsMmFXUjFZV3dvYTJWNUxDQmtaV1poZFd4MFZtRnNkV1VwTzF4dWZWeHVYRzU5TEh0Y0lpNHZhVzVrWlhndWFuTmNJam80ZlYwc01UQTZXMloxYm1OMGFXOXVLSEpsY1hWcGNtVXNiVzlrZFd4bExHVjRjRzl5ZEhNcGUxeHVLR1oxYm1OMGFXOXVJQ2huYkc5aVlXd3BlMXh1ZG1GeUlIUnZjRXhsZG1Wc0lEMGdkSGx3Wlc5bUlHZHNiMkpoYkNBaFBUMGdKM1Z1WkdWbWFXNWxaQ2NnUHlCbmJHOWlZV3dnT2x4dUlDQWdJSFI1Y0dWdlppQjNhVzVrYjNjZ0lUMDlJQ2QxYm1SbFptbHVaV1FuSUQ4Z2QybHVaRzkzSURvZ2UzMWNiblpoY2lCdGFXNUViMk1nUFNCeVpYRjFhWEpsS0NkdGFXNHRaRzlqZFcxbGJuUW5LVHRjYmx4dWFXWWdLSFI1Y0dWdlppQmtiMk4xYldWdWRDQWhQVDBnSjNWdVpHVm1hVzVsWkNjcElIdGNiaUFnSUNCdGIyUjFiR1V1Wlhod2IzSjBjeUE5SUdSdlkzVnRaVzUwTzF4dWZTQmxiSE5sSUh0Y2JpQWdJQ0IyWVhJZ1pHOWpZM2tnUFNCMGIzQk1aWFpsYkZzblgxOUhURTlDUVV4ZlJFOURWVTFGVGxSZlEwRkRTRVZBTkNkZE8xeHVYRzRnSUNBZ2FXWWdLQ0ZrYjJOamVTa2dlMXh1SUNBZ0lDQWdJQ0JrYjJOamVTQTlJSFJ2Y0V4bGRtVnNXeWRmWDBkTVQwSkJURjlFVDBOVlRVVk9WRjlEUVVOSVJVQTBKMTBnUFNCdGFXNUViMk03WEc0Z0lDQWdmVnh1WEc0Z0lDQWdiVzlrZFd4bExtVjRjRzl5ZEhNZ1BTQmtiMk5qZVR0Y2JuMWNibHh1ZlNrdVkyRnNiQ2gwYUdsekxIUjVjR1Z2WmlCbmJHOWlZV3dnSVQwOUlGd2lkVzVrWldacGJtVmtYQ0lnUHlCbmJHOWlZV3dnT2lCMGVYQmxiMllnYzJWc1ppQWhQVDBnWENKMWJtUmxabWx1WldSY0lpQS9JSE5sYkdZZ09pQjBlWEJsYjJZZ2QybHVaRzkzSUNFOVBTQmNJblZ1WkdWbWFXNWxaRndpSUQ4Z2QybHVaRzkzSURvZ2UzMHBYRzU5TEh0Y0ltMXBiaTFrYjJOMWJXVnVkRndpT2paOVhTd3hNVHBiWm5WdVkzUnBiMjRvY21WeGRXbHlaU3h0YjJSMWJHVXNaWGh3YjNKMGN5bDdYRzVjSW5WelpTQnpkSEpwWTNSY0lqdGNibHh1Ylc5a2RXeGxMbVY0Y0c5eWRITWdQU0JtZFc1amRHbHZiaUJwYzA5aWFtVmpkQ2g0S1NCN1hHNWNkSEpsZEhWeWJpQjBlWEJsYjJZZ2VDQTlQVDBnWENKdlltcGxZM1JjSWlBbUppQjRJQ0U5UFNCdWRXeHNPMXh1ZlR0Y2JseHVmU3g3ZlYwc01USTZXMloxYm1OMGFXOXVLSEpsY1hWcGNtVXNiVzlrZFd4bExHVjRjRzl5ZEhNcGUxeHVkbUZ5SUc1aGRHbDJaVWx6UVhKeVlYa2dQU0JCY25KaGVTNXBjMEZ5Y21GNVhHNTJZWElnZEc5VGRISnBibWNnUFNCUFltcGxZM1F1Y0hKdmRHOTBlWEJsTG5SdlUzUnlhVzVuWEc1Y2JtMXZaSFZzWlM1bGVIQnZjblJ6SUQwZ2JtRjBhWFpsU1hOQmNuSmhlU0I4ZkNCcGMwRnljbUY1WEc1Y2JtWjFibU4wYVc5dUlHbHpRWEp5WVhrb2IySnFLU0I3WEc0Z0lDQWdjbVYwZFhKdUlIUnZVM1J5YVc1bkxtTmhiR3dvYjJKcUtTQTlQVDBnWENKYmIySnFaV04wSUVGeWNtRjVYVndpWEc1OVhHNWNibjBzZTMxZExERXpPbHRtZFc1amRHbHZiaWh5WlhGMWFYSmxMRzF2WkhWc1pTeGxlSEJ2Y25SektYdGNiblpoY2lCd1lYUmphQ0E5SUhKbGNYVnBjbVVvWENJdUwzWmtiMjB2Y0dGMFkyZ3Vhbk5jSWlsY2JseHViVzlrZFd4bExtVjRjRzl5ZEhNZ1BTQndZWFJqYUZ4dVhHNTlMSHRjSWk0dmRtUnZiUzl3WVhSamFDNXFjMXdpT2pFNGZWMHNNVFE2VzJaMWJtTjBhVzl1S0hKbGNYVnBjbVVzYlc5a2RXeGxMR1Y0Y0c5eWRITXBlMXh1ZG1GeUlHbHpUMkpxWldOMElEMGdjbVZ4ZFdseVpTaGNJbWx6TFc5aWFtVmpkRndpS1Z4dWRtRnlJR2x6U0c5dmF5QTlJSEpsY1hWcGNtVW9YQ0l1TGk5MmJtOWtaUzlwY3kxMmFHOXZheTVxYzF3aUtWeHVYRzV0YjJSMWJHVXVaWGh3YjNKMGN5QTlJR0Z3Y0d4NVVISnZjR1Z5ZEdsbGMxeHVYRzVtZFc1amRHbHZiaUJoY0hCc2VWQnliM0JsY25ScFpYTW9ibTlrWlN3Z2NISnZjSE1zSUhCeVpYWnBiM1Z6S1NCN1hHNGdJQ0FnWm05eUlDaDJZWElnY0hKdmNFNWhiV1VnYVc0Z2NISnZjSE1wSUh0Y2JpQWdJQ0FnSUNBZ2RtRnlJSEJ5YjNCV1lXeDFaU0E5SUhCeWIzQnpXM0J5YjNCT1lXMWxYVnh1WEc0Z0lDQWdJQ0FnSUdsbUlDaHdjbTl3Vm1Gc2RXVWdQVDA5SUhWdVpHVm1hVzVsWkNrZ2UxeHVJQ0FnSUNBZ0lDQWdJQ0FnY21WdGIzWmxVSEp2Y0dWeWRIa29ibTlrWlN3Z2NISnZjRTVoYldVc0lIQnliM0JXWVd4MVpTd2djSEpsZG1sdmRYTXBPMXh1SUNBZ0lDQWdJQ0I5SUdWc2MyVWdhV1lnS0dselNHOXZheWh3Y205d1ZtRnNkV1VwS1NCN1hHNGdJQ0FnSUNBZ0lDQWdJQ0J5WlcxdmRtVlFjbTl3WlhKMGVTaHViMlJsTENCd2NtOXdUbUZ0WlN3Z2NISnZjRlpoYkhWbExDQndjbVYyYVc5MWN5bGNiaUFnSUNBZ0lDQWdJQ0FnSUdsbUlDaHdjbTl3Vm1Gc2RXVXVhRzl2YXlrZ2UxeHVJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lIQnliM0JXWVd4MVpTNW9iMjlyS0c1dlpHVXNYRzRnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUhCeWIzQk9ZVzFsTEZ4dUlDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQndjbVYyYVc5MWN5QS9JSEJ5WlhacGIzVnpXM0J5YjNCT1lXMWxYU0E2SUhWdVpHVm1hVzVsWkNsY2JpQWdJQ0FnSUNBZ0lDQWdJSDFjYmlBZ0lDQWdJQ0FnZlNCbGJITmxJSHRjYmlBZ0lDQWdJQ0FnSUNBZ0lHbG1JQ2hwYzA5aWFtVmpkQ2h3Y205d1ZtRnNkV1VwS1NCN1hHNGdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ2NHRjBZMmhQWW1wbFkzUW9ibTlrWlN3Z2NISnZjSE1zSUhCeVpYWnBiM1Z6TENCd2NtOXdUbUZ0WlN3Z2NISnZjRlpoYkhWbEtUdGNiaUFnSUNBZ0lDQWdJQ0FnSUgwZ1pXeHpaU0I3WEc0Z0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnYm05a1pWdHdjbTl3VG1GdFpWMGdQU0J3Y205d1ZtRnNkV1ZjYmlBZ0lDQWdJQ0FnSUNBZ0lIMWNiaUFnSUNBZ0lDQWdmVnh1SUNBZ0lIMWNibjFjYmx4dVpuVnVZM1JwYjI0Z2NtVnRiM1psVUhKdmNHVnlkSGtvYm05a1pTd2djSEp2Y0U1aGJXVXNJSEJ5YjNCV1lXeDFaU3dnY0hKbGRtbHZkWE1wSUh0Y2JpQWdJQ0JwWmlBb2NISmxkbWx2ZFhNcElIdGNiaUFnSUNBZ0lDQWdkbUZ5SUhCeVpYWnBiM1Z6Vm1Gc2RXVWdQU0J3Y21WMmFXOTFjMXR3Y205d1RtRnRaVjFjYmx4dUlDQWdJQ0FnSUNCcFppQW9JV2x6U0c5dmF5aHdjbVYyYVc5MWMxWmhiSFZsS1NrZ2UxeHVJQ0FnSUNBZ0lDQWdJQ0FnYVdZZ0tIQnliM0JPWVcxbElEMDlQU0JjSW1GMGRISnBZblYwWlhOY0lpa2dlMXh1SUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJR1p2Y2lBb2RtRnlJR0YwZEhKT1lXMWxJR2x1SUhCeVpYWnBiM1Z6Vm1Gc2RXVXBJSHRjYmlBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ2JtOWtaUzV5WlcxdmRtVkJkSFJ5YVdKMWRHVW9ZWFIwY2s1aGJXVXBYRzRnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdmVnh1SUNBZ0lDQWdJQ0FnSUNBZ2ZTQmxiSE5sSUdsbUlDaHdjbTl3VG1GdFpTQTlQVDBnWENKemRIbHNaVndpS1NCN1hHNGdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ1ptOXlJQ2gyWVhJZ2FTQnBiaUJ3Y21WMmFXOTFjMVpoYkhWbEtTQjdYRzRnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUc1dlpHVXVjM1I1YkdWYmFWMGdQU0JjSWx3aVhHNGdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ2ZWeHVJQ0FnSUNBZ0lDQWdJQ0FnZlNCbGJITmxJR2xtSUNoMGVYQmxiMllnY0hKbGRtbHZkWE5XWVd4MVpTQTlQVDBnWENKemRISnBibWRjSWlrZ2UxeHVJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lHNXZaR1ZiY0hKdmNFNWhiV1ZkSUQwZ1hDSmNJbHh1SUNBZ0lDQWdJQ0FnSUNBZ2ZTQmxiSE5sSUh0Y2JpQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNCdWIyUmxXM0J5YjNCT1lXMWxYU0E5SUc1MWJHeGNiaUFnSUNBZ0lDQWdJQ0FnSUgxY2JpQWdJQ0FnSUNBZ2ZTQmxiSE5sSUdsbUlDaHdjbVYyYVc5MWMxWmhiSFZsTG5WdWFHOXZheWtnZTF4dUlDQWdJQ0FnSUNBZ0lDQWdjSEpsZG1sdmRYTldZV3gxWlM1MWJtaHZiMnNvYm05a1pTd2djSEp2Y0U1aGJXVXNJSEJ5YjNCV1lXeDFaU2xjYmlBZ0lDQWdJQ0FnZlZ4dUlDQWdJSDFjYm4xY2JseHVablZ1WTNScGIyNGdjR0YwWTJoUFltcGxZM1FvYm05a1pTd2djSEp2Y0hNc0lIQnlaWFpwYjNWekxDQndjbTl3VG1GdFpTd2djSEp2Y0ZaaGJIVmxLU0I3WEc0Z0lDQWdkbUZ5SUhCeVpYWnBiM1Z6Vm1Gc2RXVWdQU0J3Y21WMmFXOTFjeUEvSUhCeVpYWnBiM1Z6VzNCeWIzQk9ZVzFsWFNBNklIVnVaR1ZtYVc1bFpGeHVYRzRnSUNBZ0x5OGdVMlYwSUdGMGRISnBZblYwWlhOY2JpQWdJQ0JwWmlBb2NISnZjRTVoYldVZ1BUMDlJRndpWVhSMGNtbGlkWFJsYzF3aUtTQjdYRzRnSUNBZ0lDQWdJR1p2Y2lBb2RtRnlJR0YwZEhKT1lXMWxJR2x1SUhCeWIzQldZV3gxWlNrZ2UxeHVJQ0FnSUNBZ0lDQWdJQ0FnZG1GeUlHRjBkSEpXWVd4MVpTQTlJSEJ5YjNCV1lXeDFaVnRoZEhSeVRtRnRaVjFjYmx4dUlDQWdJQ0FnSUNBZ0lDQWdhV1lnS0dGMGRISldZV3gxWlNBOVBUMGdkVzVrWldacGJtVmtLU0I3WEc0Z0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnYm05a1pTNXlaVzF2ZG1WQmRIUnlhV0oxZEdVb1lYUjBjazVoYldVcFhHNGdJQ0FnSUNBZ0lDQWdJQ0I5SUdWc2MyVWdlMXh1SUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJRzV2WkdVdWMyVjBRWFIwY21saWRYUmxLR0YwZEhKT1lXMWxMQ0JoZEhSeVZtRnNkV1VwWEc0Z0lDQWdJQ0FnSUNBZ0lDQjlYRzRnSUNBZ0lDQWdJSDFjYmx4dUlDQWdJQ0FnSUNCeVpYUjFjbTVjYmlBZ0lDQjlYRzVjYmlBZ0lDQnBaaWh3Y21WMmFXOTFjMVpoYkhWbElDWW1JR2x6VDJKcVpXTjBLSEJ5WlhacGIzVnpWbUZzZFdVcElDWW1YRzRnSUNBZ0lDQWdJR2RsZEZCeWIzUnZkSGx3WlNod2NtVjJhVzkxYzFaaGJIVmxLU0FoUFQwZ1oyVjBVSEp2ZEc5MGVYQmxLSEJ5YjNCV1lXeDFaU2twSUh0Y2JpQWdJQ0FnSUNBZ2JtOWtaVnR3Y205d1RtRnRaVjBnUFNCd2NtOXdWbUZzZFdWY2JpQWdJQ0FnSUNBZ2NtVjBkWEp1WEc0Z0lDQWdmVnh1WEc0Z0lDQWdhV1lnS0NGcGMwOWlhbVZqZENodWIyUmxXM0J5YjNCT1lXMWxYU2twSUh0Y2JpQWdJQ0FnSUNBZ2JtOWtaVnR3Y205d1RtRnRaVjBnUFNCN2ZWeHVJQ0FnSUgxY2JseHVJQ0FnSUhaaGNpQnlaWEJzWVdObGNpQTlJSEJ5YjNCT1lXMWxJRDA5UFNCY0luTjBlV3hsWENJZ1B5QmNJbHdpSURvZ2RXNWtaV1pwYm1Wa1hHNWNiaUFnSUNCbWIzSWdLSFpoY2lCcklHbHVJSEJ5YjNCV1lXeDFaU2tnZTF4dUlDQWdJQ0FnSUNCMllYSWdkbUZzZFdVZ1BTQndjbTl3Vm1Gc2RXVmJhMTFjYmlBZ0lDQWdJQ0FnYm05a1pWdHdjbTl3VG1GdFpWMWJhMTBnUFNBb2RtRnNkV1VnUFQwOUlIVnVaR1ZtYVc1bFpDa2dQeUJ5WlhCc1lXTmxjaUE2SUhaaGJIVmxYRzRnSUNBZ2ZWeHVmVnh1WEc1bWRXNWpkR2x2YmlCblpYUlFjbTkwYjNSNWNHVW9kbUZzZFdVcElIdGNiaUFnSUNCcFppQW9UMkpxWldOMExtZGxkRkJ5YjNSdmRIbHdaVTltS1NCN1hHNGdJQ0FnSUNBZ0lISmxkSFZ5YmlCUFltcGxZM1F1WjJWMFVISnZkRzkwZVhCbFQyWW9kbUZzZFdVcFhHNGdJQ0FnZlNCbGJITmxJR2xtSUNoMllXeDFaUzVmWDNCeWIzUnZYMThwSUh0Y2JpQWdJQ0FnSUNBZ2NtVjBkWEp1SUhaaGJIVmxMbDlmY0hKdmRHOWZYMXh1SUNBZ0lIMGdaV3h6WlNCcFppQW9kbUZzZFdVdVkyOXVjM1J5ZFdOMGIzSXBJSHRjYmlBZ0lDQWdJQ0FnY21WMGRYSnVJSFpoYkhWbExtTnZibk4wY25WamRHOXlMbkJ5YjNSdmRIbHdaVnh1SUNBZ0lIMWNibjFjYmx4dWZTeDdYQ0l1TGk5MmJtOWtaUzlwY3kxMmFHOXZheTVxYzF3aU9qSTJMRndpYVhNdGIySnFaV04wWENJNk1URjlYU3d4TlRwYlpuVnVZM1JwYjI0b2NtVnhkV2x5WlN4dGIyUjFiR1VzWlhod2IzSjBjeWw3WEc1MllYSWdaRzlqZFcxbGJuUWdQU0J5WlhGMWFYSmxLRndpWjJ4dlltRnNMMlJ2WTNWdFpXNTBYQ0lwWEc1Y2JuWmhjaUJoY0hCc2VWQnliM0JsY25ScFpYTWdQU0J5WlhGMWFYSmxLRndpTGk5aGNIQnNlUzF3Y205d1pYSjBhV1Z6WENJcFhHNWNiblpoY2lCcGMxWk9iMlJsSUQwZ2NtVnhkV2x5WlNoY0lpNHVMM1p1YjJSbEwybHpMWFp1YjJSbExtcHpYQ0lwWEc1MllYSWdhWE5XVkdWNGRDQTlJSEpsY1hWcGNtVW9YQ0l1TGk5MmJtOWtaUzlwY3kxMmRHVjRkQzVxYzF3aUtWeHVkbUZ5SUdselYybGtaMlYwSUQwZ2NtVnhkV2x5WlNoY0lpNHVMM1p1YjJSbEwybHpMWGRwWkdkbGRDNXFjMXdpS1Z4dWRtRnlJR2hoYm1Sc1pWUm9kVzVySUQwZ2NtVnhkV2x5WlNoY0lpNHVMM1p1YjJSbEwyaGhibVJzWlMxMGFIVnVheTVxYzF3aUtWeHVYRzV0YjJSMWJHVXVaWGh3YjNKMGN5QTlJR055WldGMFpVVnNaVzFsYm5SY2JseHVablZ1WTNScGIyNGdZM0psWVhSbFJXeGxiV1Z1ZENoMmJtOWtaU3dnYjNCMGN5a2dlMXh1SUNBZ0lIWmhjaUJrYjJNZ1BTQnZjSFJ6SUQ4Z2IzQjBjeTVrYjJOMWJXVnVkQ0I4ZkNCa2IyTjFiV1Z1ZENBNklHUnZZM1Z0Wlc1MFhHNGdJQ0FnZG1GeUlIZGhjbTRnUFNCdmNIUnpJRDhnYjNCMGN5NTNZWEp1SURvZ2JuVnNiRnh1WEc0Z0lDQWdkbTV2WkdVZ1BTQm9ZVzVrYkdWVWFIVnVheWgyYm05a1pTa3VZVnh1WEc0Z0lDQWdhV1lnS0dselYybGtaMlYwS0hadWIyUmxLU2tnZTF4dUlDQWdJQ0FnSUNCeVpYUjFjbTRnZG01dlpHVXVhVzVwZENncFhHNGdJQ0FnZlNCbGJITmxJR2xtSUNocGMxWlVaWGgwS0hadWIyUmxLU2tnZTF4dUlDQWdJQ0FnSUNCeVpYUjFjbTRnWkc5akxtTnlaV0YwWlZSbGVIUk9iMlJsS0hadWIyUmxMblJsZUhRcFhHNGdJQ0FnZlNCbGJITmxJR2xtSUNnaGFYTldUbTlrWlNoMmJtOWtaU2twSUh0Y2JpQWdJQ0FnSUNBZ2FXWWdLSGRoY200cElIdGNiaUFnSUNBZ0lDQWdJQ0FnSUhkaGNtNG9YQ0pKZEdWdElHbHpJRzV2ZENCaElIWmhiR2xrSUhacGNuUjFZV3dnWkc5dElHNXZaR1ZjSWl3Z2RtNXZaR1VwWEc0Z0lDQWdJQ0FnSUgxY2JpQWdJQ0FnSUNBZ2NtVjBkWEp1SUc1MWJHeGNiaUFnSUNCOVhHNWNiaUFnSUNCMllYSWdibTlrWlNBOUlDaDJibTlrWlM1dVlXMWxjM0JoWTJVZ1BUMDlJRzUxYkd3cElEOWNiaUFnSUNBZ0lDQWdaRzlqTG1OeVpXRjBaVVZzWlcxbGJuUW9kbTV2WkdVdWRHRm5UbUZ0WlNrZ09seHVJQ0FnSUNBZ0lDQmtiMk11WTNKbFlYUmxSV3hsYldWdWRFNVRLSFp1YjJSbExtNWhiV1Z6Y0dGalpTd2dkbTV2WkdVdWRHRm5UbUZ0WlNsY2JseHVJQ0FnSUhaaGNpQndjbTl3Y3lBOUlIWnViMlJsTG5CeWIzQmxjblJwWlhOY2JpQWdJQ0JoY0hCc2VWQnliM0JsY25ScFpYTW9ibTlrWlN3Z2NISnZjSE1wWEc1Y2JpQWdJQ0IyWVhJZ1kyaHBiR1J5Wlc0Z1BTQjJibTlrWlM1amFHbHNaSEpsYmx4dVhHNGdJQ0FnWm05eUlDaDJZWElnYVNBOUlEQTdJR2tnUENCamFHbHNaSEpsYmk1c1pXNW5kR2c3SUdrckt5a2dlMXh1SUNBZ0lDQWdJQ0IyWVhJZ1kyaHBiR1JPYjJSbElEMGdZM0psWVhSbFJXeGxiV1Z1ZENoamFHbHNaSEpsYmx0cFhTd2diM0IwY3lsY2JpQWdJQ0FnSUNBZ2FXWWdLR05vYVd4a1RtOWtaU2tnZTF4dUlDQWdJQ0FnSUNBZ0lDQWdibTlrWlM1aGNIQmxibVJEYUdsc1pDaGphR2xzWkU1dlpHVXBYRzRnSUNBZ0lDQWdJSDFjYmlBZ0lDQjlYRzVjYmlBZ0lDQnlaWFIxY200Z2JtOWtaVnh1ZlZ4dVhHNTlMSHRjSWk0dUwzWnViMlJsTDJoaGJtUnNaUzEwYUhWdWF5NXFjMXdpT2pJMExGd2lMaTR2ZG01dlpHVXZhWE10ZG01dlpHVXVhbk5jSWpveU55eGNJaTR1TDNadWIyUmxMMmx6TFhaMFpYaDBMbXB6WENJNk1qZ3NYQ0l1TGk5MmJtOWtaUzlwY3kxM2FXUm5aWFF1YW5OY0lqb3lPU3hjSWk0dllYQndiSGt0Y0hKdmNHVnlkR2xsYzF3aU9qRTBMRndpWjJ4dlltRnNMMlJ2WTNWdFpXNTBYQ0k2TVRCOVhTd3hOanBiWm5WdVkzUnBiMjRvY21WeGRXbHlaU3h0YjJSMWJHVXNaWGh3YjNKMGN5bDdYRzR2THlCTllYQnpJR0VnZG1seWRIVmhiQ0JFVDAwZ2RISmxaU0J2Ym5SdklHRWdjbVZoYkNCRVQwMGdkSEpsWlNCcGJpQmhiaUJsWm1acFkybGxiblFnYldGdWJtVnlMbHh1THk4Z1YyVWdaRzl1SjNRZ2QyRnVkQ0IwYnlCeVpXRmtJR0ZzYkNCdlppQjBhR1VnUkU5TklHNXZaR1Z6SUdsdUlIUm9aU0IwY21WbElITnZJSGRsSUhWelpWeHVMeThnZEdobElHbHVMVzl5WkdWeUlIUnlaV1VnYVc1a1pYaHBibWNnZEc4Z1pXeHBiV2x1WVhSbElISmxZM1Z5YzJsdmJpQmtiM2R1SUdObGNuUmhhVzRnWW5KaGJtTm9aWE11WEc0dkx5QlhaU0J2Ym14NUlISmxZM1Z5YzJVZ2FXNTBieUJoSUVSUFRTQnViMlJsSUdsbUlIZGxJR3R1YjNjZ2RHaGhkQ0JwZENCamIyNTBZV2x1Y3lCaElHTm9hV3hrSUc5bVhHNHZMeUJwYm5SbGNtVnpkQzVjYmx4dWRtRnlJRzV2UTJocGJHUWdQU0I3ZlZ4dVhHNXRiMlIxYkdVdVpYaHdiM0owY3lBOUlHUnZiVWx1WkdWNFhHNWNibVoxYm1OMGFXOXVJR1J2YlVsdVpHVjRLSEp2YjNST2IyUmxMQ0IwY21WbExDQnBibVJwWTJWekxDQnViMlJsY3lrZ2UxeHVJQ0FnSUdsbUlDZ2hhVzVrYVdObGN5QjhmQ0JwYm1ScFkyVnpMbXhsYm1kMGFDQTlQVDBnTUNrZ2UxeHVJQ0FnSUNBZ0lDQnlaWFIxY200Z2UzMWNiaUFnSUNCOUlHVnNjMlVnZTF4dUlDQWdJQ0FnSUNCcGJtUnBZMlZ6TG5OdmNuUW9ZWE5qWlc1a2FXNW5LVnh1SUNBZ0lDQWdJQ0J5WlhSMWNtNGdjbVZqZFhKelpTaHliMjkwVG05a1pTd2dkSEpsWlN3Z2FXNWthV05sY3l3Z2JtOWtaWE1zSURBcFhHNGdJQ0FnZlZ4dWZWeHVYRzVtZFc1amRHbHZiaUJ5WldOMWNuTmxLSEp2YjNST2IyUmxMQ0IwY21WbExDQnBibVJwWTJWekxDQnViMlJsY3l3Z2NtOXZkRWx1WkdWNEtTQjdYRzRnSUNBZ2JtOWtaWE1nUFNCdWIyUmxjeUI4ZkNCN2ZWeHVYRzVjYmlBZ0lDQnBaaUFvY205dmRFNXZaR1VwSUh0Y2JpQWdJQ0FnSUNBZ2FXWWdLR2x1WkdWNFNXNVNZVzVuWlNocGJtUnBZMlZ6TENCeWIyOTBTVzVrWlhnc0lISnZiM1JKYm1SbGVDa3BJSHRjYmlBZ0lDQWdJQ0FnSUNBZ0lHNXZaR1Z6VzNKdmIzUkpibVJsZUYwZ1BTQnliMjkwVG05a1pWeHVJQ0FnSUNBZ0lDQjlYRzVjYmlBZ0lDQWdJQ0FnZG1GeUlIWkRhR2xzWkhKbGJpQTlJSFJ5WldVdVkyaHBiR1J5Wlc1Y2JseHVJQ0FnSUNBZ0lDQnBaaUFvZGtOb2FXeGtjbVZ1S1NCN1hHNWNiaUFnSUNBZ0lDQWdJQ0FnSUhaaGNpQmphR2xzWkU1dlpHVnpJRDBnY205dmRFNXZaR1V1WTJocGJHUk9iMlJsYzF4dVhHNGdJQ0FnSUNBZ0lDQWdJQ0JtYjNJZ0tIWmhjaUJwSUQwZ01Ec2dhU0E4SUhSeVpXVXVZMmhwYkdSeVpXNHViR1Z1WjNSb095QnBLeXNwSUh0Y2JpQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNCeWIyOTBTVzVrWlhnZ0t6MGdNVnh1WEc0Z0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnZG1GeUlIWkRhR2xzWkNBOUlIWkRhR2xzWkhKbGJsdHBYU0I4ZkNCdWIwTm9hV3hrWEc0Z0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnZG1GeUlHNWxlSFJKYm1SbGVDQTlJSEp2YjNSSmJtUmxlQ0FySUNoMlEyaHBiR1F1WTI5MWJuUWdmSHdnTUNsY2JseHVJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDOHZJSE5yYVhBZ2NtVmpkWEp6YVc5dUlHUnZkMjRnZEdobElIUnlaV1VnYVdZZ2RHaGxjbVVnWVhKbElHNXZJRzV2WkdWeklHUnZkMjRnYUdWeVpWeHVJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lHbG1JQ2hwYm1SbGVFbHVVbUZ1WjJVb2FXNWthV05sY3l3Z2NtOXZkRWx1WkdWNExDQnVaWGgwU1c1a1pYZ3BLU0I3WEc0Z0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lISmxZM1Z5YzJVb1kyaHBiR1JPYjJSbGMxdHBYU3dnZGtOb2FXeGtMQ0JwYm1ScFkyVnpMQ0J1YjJSbGN5d2djbTl2ZEVsdVpHVjRLVnh1SUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJSDFjYmx4dUlDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUhKdmIzUkpibVJsZUNBOUlHNWxlSFJKYm1SbGVGeHVJQ0FnSUNBZ0lDQWdJQ0FnZlZ4dUlDQWdJQ0FnSUNCOVhHNGdJQ0FnZlZ4dVhHNGdJQ0FnY21WMGRYSnVJRzV2WkdWelhHNTlYRzVjYmk4dklFSnBibUZ5ZVNCelpXRnlZMmdnWm05eUlHRnVJR2x1WkdWNElHbHVJSFJvWlNCcGJuUmxjblpoYkNCYmJHVm1kQ3dnY21sbmFIUmRYRzVtZFc1amRHbHZiaUJwYm1SbGVFbHVVbUZ1WjJVb2FXNWthV05sY3l3Z2JHVm1kQ3dnY21sbmFIUXBJSHRjYmlBZ0lDQnBaaUFvYVc1a2FXTmxjeTVzWlc1bmRHZ2dQVDA5SURBcElIdGNiaUFnSUNBZ0lDQWdjbVYwZFhKdUlHWmhiSE5sWEc0Z0lDQWdmVnh1WEc0Z0lDQWdkbUZ5SUcxcGJrbHVaR1Y0SUQwZ01GeHVJQ0FnSUhaaGNpQnRZWGhKYm1SbGVDQTlJR2x1WkdsalpYTXViR1Z1WjNSb0lDMGdNVnh1SUNBZ0lIWmhjaUJqZFhKeVpXNTBTVzVrWlhoY2JpQWdJQ0IyWVhJZ1kzVnljbVZ1ZEVsMFpXMWNibHh1SUNBZ0lIZG9hV3hsSUNodGFXNUpibVJsZUNBOFBTQnRZWGhKYm1SbGVDa2dlMXh1SUNBZ0lDQWdJQ0JqZFhKeVpXNTBTVzVrWlhnZ1BTQW9LRzFoZUVsdVpHVjRJQ3NnYldsdVNXNWtaWGdwSUM4Z01pa2dQajRnTUZ4dUlDQWdJQ0FnSUNCamRYSnlaVzUwU1hSbGJTQTlJR2x1WkdsalpYTmJZM1Z5Y21WdWRFbHVaR1Y0WFZ4dVhHNGdJQ0FnSUNBZ0lHbG1JQ2h0YVc1SmJtUmxlQ0E5UFQwZ2JXRjRTVzVrWlhncElIdGNiaUFnSUNBZ0lDQWdJQ0FnSUhKbGRIVnliaUJqZFhKeVpXNTBTWFJsYlNBK1BTQnNaV1owSUNZbUlHTjFjbkpsYm5SSmRHVnRJRHc5SUhKcFoyaDBYRzRnSUNBZ0lDQWdJSDBnWld4elpTQnBaaUFvWTNWeWNtVnVkRWwwWlcwZ1BDQnNaV1owS1NCN1hHNGdJQ0FnSUNBZ0lDQWdJQ0J0YVc1SmJtUmxlQ0E5SUdOMWNuSmxiblJKYm1SbGVDQXJJREZjYmlBZ0lDQWdJQ0FnZlNCbGJITmxJQ0JwWmlBb1kzVnljbVZ1ZEVsMFpXMGdQaUJ5YVdkb2RDa2dlMXh1SUNBZ0lDQWdJQ0FnSUNBZ2JXRjRTVzVrWlhnZ1BTQmpkWEp5Wlc1MFNXNWtaWGdnTFNBeFhHNGdJQ0FnSUNBZ0lIMGdaV3h6WlNCN1hHNGdJQ0FnSUNBZ0lDQWdJQ0J5WlhSMWNtNGdkSEoxWlZ4dUlDQWdJQ0FnSUNCOVhHNGdJQ0FnZlZ4dVhHNGdJQ0FnY21WMGRYSnVJR1poYkhObE8xeHVmVnh1WEc1bWRXNWpkR2x2YmlCaGMyTmxibVJwYm1jb1lTd2dZaWtnZTF4dUlDQWdJSEpsZEhWeWJpQmhJRDRnWWlBL0lERWdPaUF0TVZ4dWZWeHVYRzU5TEh0OVhTd3hOenBiWm5WdVkzUnBiMjRvY21WeGRXbHlaU3h0YjJSMWJHVXNaWGh3YjNKMGN5bDdYRzUyWVhJZ1lYQndiSGxRY205d1pYSjBhV1Z6SUQwZ2NtVnhkV2x5WlNoY0lpNHZZWEJ3YkhrdGNISnZjR1Z5ZEdsbGMxd2lLVnh1WEc1MllYSWdhWE5YYVdSblpYUWdQU0J5WlhGMWFYSmxLRndpTGk0dmRtNXZaR1V2YVhNdGQybGtaMlYwTG1welhDSXBYRzUyWVhJZ1ZsQmhkR05vSUQwZ2NtVnhkV2x5WlNoY0lpNHVMM1p1YjJSbEwzWndZWFJqYUM1cWMxd2lLVnh1WEc1MllYSWdkWEJrWVhSbFYybGtaMlYwSUQwZ2NtVnhkV2x5WlNoY0lpNHZkWEJrWVhSbExYZHBaR2RsZEZ3aUtWeHVYRzV0YjJSMWJHVXVaWGh3YjNKMGN5QTlJR0Z3Y0d4NVVHRjBZMmhjYmx4dVpuVnVZM1JwYjI0Z1lYQndiSGxRWVhSamFDaDJjR0YwWTJnc0lHUnZiVTV2WkdVc0lISmxibVJsY2s5d2RHbHZibk1wSUh0Y2JpQWdJQ0IyWVhJZ2RIbHdaU0E5SUhad1lYUmphQzUwZVhCbFhHNGdJQ0FnZG1GeUlIWk9iMlJsSUQwZ2RuQmhkR05vTG5aT2IyUmxYRzRnSUNBZ2RtRnlJSEJoZEdOb0lEMGdkbkJoZEdOb0xuQmhkR05vWEc1Y2JpQWdJQ0J6ZDJsMFkyZ2dLSFI1Y0dVcElIdGNiaUFnSUNBZ0lDQWdZMkZ6WlNCV1VHRjBZMmd1VWtWTlQxWkZPbHh1SUNBZ0lDQWdJQ0FnSUNBZ2NtVjBkWEp1SUhKbGJXOTJaVTV2WkdVb1pHOXRUbTlrWlN3Z2RrNXZaR1VwWEc0Z0lDQWdJQ0FnSUdOaGMyVWdWbEJoZEdOb0xrbE9VMFZTVkRwY2JpQWdJQ0FnSUNBZ0lDQWdJSEpsZEhWeWJpQnBibk5sY25ST2IyUmxLR1J2YlU1dlpHVXNJSEJoZEdOb0xDQnlaVzVrWlhKUGNIUnBiMjV6S1Z4dUlDQWdJQ0FnSUNCallYTmxJRlpRWVhSamFDNVdWRVZZVkRwY2JpQWdJQ0FnSUNBZ0lDQWdJSEpsZEhWeWJpQnpkSEpwYm1kUVlYUmphQ2hrYjIxT2IyUmxMQ0IyVG05a1pTd2djR0YwWTJnc0lISmxibVJsY2s5d2RHbHZibk1wWEc0Z0lDQWdJQ0FnSUdOaGMyVWdWbEJoZEdOb0xsZEpSRWRGVkRwY2JpQWdJQ0FnSUNBZ0lDQWdJSEpsZEhWeWJpQjNhV1JuWlhSUVlYUmphQ2hrYjIxT2IyUmxMQ0IyVG05a1pTd2djR0YwWTJnc0lISmxibVJsY2s5d2RHbHZibk1wWEc0Z0lDQWdJQ0FnSUdOaGMyVWdWbEJoZEdOb0xsWk9UMFJGT2x4dUlDQWdJQ0FnSUNBZ0lDQWdjbVYwZFhKdUlIWk9iMlJsVUdGMFkyZ29aRzl0VG05a1pTd2dkazV2WkdVc0lIQmhkR05vTENCeVpXNWtaWEpQY0hScGIyNXpLVnh1SUNBZ0lDQWdJQ0JqWVhObElGWlFZWFJqYUM1UFVrUkZVanBjYmlBZ0lDQWdJQ0FnSUNBZ0lISmxiM0prWlhKRGFHbHNaSEpsYmloa2IyMU9iMlJsTENCd1lYUmphQ2xjYmlBZ0lDQWdJQ0FnSUNBZ0lISmxkSFZ5YmlCa2IyMU9iMlJsWEc0Z0lDQWdJQ0FnSUdOaGMyVWdWbEJoZEdOb0xsQlNUMUJUT2x4dUlDQWdJQ0FnSUNBZ0lDQWdZWEJ3YkhsUWNtOXdaWEowYVdWektHUnZiVTV2WkdVc0lIQmhkR05vTENCMlRtOWtaUzV3Y205d1pYSjBhV1Z6S1Z4dUlDQWdJQ0FnSUNBZ0lDQWdjbVYwZFhKdUlHUnZiVTV2WkdWY2JpQWdJQ0FnSUNBZ1kyRnpaU0JXVUdGMFkyZ3VWRWhWVGtzNlhHNGdJQ0FnSUNBZ0lDQWdJQ0J5WlhSMWNtNGdjbVZ3YkdGalpWSnZiM1FvWkc5dFRtOWtaU3hjYmlBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0J5Wlc1a1pYSlBjSFJwYjI1ekxuQmhkR05vS0dSdmJVNXZaR1VzSUhCaGRHTm9MQ0J5Wlc1a1pYSlBjSFJwYjI1ektTbGNiaUFnSUNBZ0lDQWdaR1ZtWVhWc2REcGNiaUFnSUNBZ0lDQWdJQ0FnSUhKbGRIVnliaUJrYjIxT2IyUmxYRzRnSUNBZ2ZWeHVmVnh1WEc1bWRXNWpkR2x2YmlCeVpXMXZkbVZPYjJSbEtHUnZiVTV2WkdVc0lIWk9iMlJsS1NCN1hHNGdJQ0FnZG1GeUlIQmhjbVZ1ZEU1dlpHVWdQU0JrYjIxT2IyUmxMbkJoY21WdWRFNXZaR1ZjYmx4dUlDQWdJR2xtSUNod1lYSmxiblJPYjJSbEtTQjdYRzRnSUNBZ0lDQWdJSEJoY21WdWRFNXZaR1V1Y21WdGIzWmxRMmhwYkdRb1pHOXRUbTlrWlNsY2JpQWdJQ0I5WEc1Y2JpQWdJQ0JrWlhOMGNtOTVWMmxrWjJWMEtHUnZiVTV2WkdVc0lIWk9iMlJsS1R0Y2JseHVJQ0FnSUhKbGRIVnliaUJ1ZFd4c1hHNTlYRzVjYm1aMWJtTjBhVzl1SUdsdWMyVnlkRTV2WkdVb2NHRnlaVzUwVG05a1pTd2dkazV2WkdVc0lISmxibVJsY2s5d2RHbHZibk1wSUh0Y2JpQWdJQ0IyWVhJZ2JtVjNUbTlrWlNBOUlISmxibVJsY2s5d2RHbHZibk11Y21WdVpHVnlLSFpPYjJSbExDQnlaVzVrWlhKUGNIUnBiMjV6S1Z4dVhHNGdJQ0FnYVdZZ0tIQmhjbVZ1ZEU1dlpHVXBJSHRjYmlBZ0lDQWdJQ0FnY0dGeVpXNTBUbTlrWlM1aGNIQmxibVJEYUdsc1pDaHVaWGRPYjJSbEtWeHVJQ0FnSUgxY2JseHVJQ0FnSUhKbGRIVnliaUJ3WVhKbGJuUk9iMlJsWEc1OVhHNWNibVoxYm1OMGFXOXVJSE4wY21sdVoxQmhkR05vS0dSdmJVNXZaR1VzSUd4bFpuUldUbTlrWlN3Z2RsUmxlSFFzSUhKbGJtUmxjazl3ZEdsdmJuTXBJSHRjYmlBZ0lDQjJZWElnYm1WM1RtOWtaVnh1WEc0Z0lDQWdhV1lnS0dSdmJVNXZaR1V1Ym05a1pWUjVjR1VnUFQwOUlETXBJSHRjYmlBZ0lDQWdJQ0FnWkc5dFRtOWtaUzV5WlhCc1lXTmxSR0YwWVNnd0xDQmtiMjFPYjJSbExteGxibWQwYUN3Z2RsUmxlSFF1ZEdWNGRDbGNiaUFnSUNBZ0lDQWdibVYzVG05a1pTQTlJR1J2YlU1dlpHVmNiaUFnSUNCOUlHVnNjMlVnZTF4dUlDQWdJQ0FnSUNCMllYSWdjR0Z5Wlc1MFRtOWtaU0E5SUdSdmJVNXZaR1V1Y0dGeVpXNTBUbTlrWlZ4dUlDQWdJQ0FnSUNCdVpYZE9iMlJsSUQwZ2NtVnVaR1Z5VDNCMGFXOXVjeTV5Wlc1a1pYSW9kbFJsZUhRc0lISmxibVJsY2s5d2RHbHZibk1wWEc1Y2JpQWdJQ0FnSUNBZ2FXWWdLSEJoY21WdWRFNXZaR1VnSmlZZ2JtVjNUbTlrWlNBaFBUMGdaRzl0VG05a1pTa2dlMXh1SUNBZ0lDQWdJQ0FnSUNBZ2NHRnlaVzUwVG05a1pTNXlaWEJzWVdObFEyaHBiR1FvYm1WM1RtOWtaU3dnWkc5dFRtOWtaU2xjYmlBZ0lDQWdJQ0FnZlZ4dUlDQWdJSDFjYmx4dUlDQWdJSEpsZEhWeWJpQnVaWGRPYjJSbFhHNTlYRzVjYm1aMWJtTjBhVzl1SUhkcFpHZGxkRkJoZEdOb0tHUnZiVTV2WkdVc0lHeGxablJXVG05a1pTd2dkMmxrWjJWMExDQnlaVzVrWlhKUGNIUnBiMjV6S1NCN1hHNGdJQ0FnZG1GeUlIVndaR0YwYVc1bklEMGdkWEJrWVhSbFYybGtaMlYwS0d4bFpuUldUbTlrWlN3Z2QybGtaMlYwS1Z4dUlDQWdJSFpoY2lCdVpYZE9iMlJsWEc1Y2JpQWdJQ0JwWmlBb2RYQmtZWFJwYm1jcElIdGNiaUFnSUNBZ0lDQWdibVYzVG05a1pTQTlJSGRwWkdkbGRDNTFjR1JoZEdVb2JHVm1kRlpPYjJSbExDQmtiMjFPYjJSbEtTQjhmQ0JrYjIxT2IyUmxYRzRnSUNBZ2ZTQmxiSE5sSUh0Y2JpQWdJQ0FnSUNBZ2JtVjNUbTlrWlNBOUlISmxibVJsY2s5d2RHbHZibk11Y21WdVpHVnlLSGRwWkdkbGRDd2djbVZ1WkdWeVQzQjBhVzl1Y3lsY2JpQWdJQ0I5WEc1Y2JpQWdJQ0IyWVhJZ2NHRnlaVzUwVG05a1pTQTlJR1J2YlU1dlpHVXVjR0Z5Wlc1MFRtOWtaVnh1WEc0Z0lDQWdhV1lnS0hCaGNtVnVkRTV2WkdVZ0ppWWdibVYzVG05a1pTQWhQVDBnWkc5dFRtOWtaU2tnZTF4dUlDQWdJQ0FnSUNCd1lYSmxiblJPYjJSbExuSmxjR3hoWTJWRGFHbHNaQ2h1WlhkT2IyUmxMQ0JrYjIxT2IyUmxLVnh1SUNBZ0lIMWNibHh1SUNBZ0lHbG1JQ2doZFhCa1lYUnBibWNwSUh0Y2JpQWdJQ0FnSUNBZ1pHVnpkSEp2ZVZkcFpHZGxkQ2hrYjIxT2IyUmxMQ0JzWldaMFZrNXZaR1VwWEc0Z0lDQWdmVnh1WEc0Z0lDQWdjbVYwZFhKdUlHNWxkMDV2WkdWY2JuMWNibHh1Wm5WdVkzUnBiMjRnZGs1dlpHVlFZWFJqYUNoa2IyMU9iMlJsTENCc1pXWjBWazV2WkdVc0lIWk9iMlJsTENCeVpXNWtaWEpQY0hScGIyNXpLU0I3WEc0Z0lDQWdkbUZ5SUhCaGNtVnVkRTV2WkdVZ1BTQmtiMjFPYjJSbExuQmhjbVZ1ZEU1dlpHVmNiaUFnSUNCMllYSWdibVYzVG05a1pTQTlJSEpsYm1SbGNrOXdkR2x2Ym5NdWNtVnVaR1Z5S0haT2IyUmxMQ0J5Wlc1a1pYSlBjSFJwYjI1ektWeHVYRzRnSUNBZ2FXWWdLSEJoY21WdWRFNXZaR1VnSmlZZ2JtVjNUbTlrWlNBaFBUMGdaRzl0VG05a1pTa2dlMXh1SUNBZ0lDQWdJQ0J3WVhKbGJuUk9iMlJsTG5KbGNHeGhZMlZEYUdsc1pDaHVaWGRPYjJSbExDQmtiMjFPYjJSbEtWeHVJQ0FnSUgxY2JseHVJQ0FnSUhKbGRIVnliaUJ1WlhkT2IyUmxYRzU5WEc1Y2JtWjFibU4wYVc5dUlHUmxjM1J5YjNsWGFXUm5aWFFvWkc5dFRtOWtaU3dnZHlrZ2UxeHVJQ0FnSUdsbUlDaDBlWEJsYjJZZ2R5NWtaWE4wY205NUlEMDlQU0JjSW1aMWJtTjBhVzl1WENJZ0ppWWdhWE5YYVdSblpYUW9keWtwSUh0Y2JpQWdJQ0FnSUNBZ2R5NWtaWE4wY205NUtHUnZiVTV2WkdVcFhHNGdJQ0FnZlZ4dWZWeHVYRzVtZFc1amRHbHZiaUJ5Wlc5eVpHVnlRMmhwYkdSeVpXNG9aRzl0VG05a1pTd2diVzkyWlhNcElIdGNiaUFnSUNCMllYSWdZMmhwYkdST2IyUmxjeUE5SUdSdmJVNXZaR1V1WTJocGJHUk9iMlJsYzF4dUlDQWdJSFpoY2lCclpYbE5ZWEFnUFNCN2ZWeHVJQ0FnSUhaaGNpQnViMlJsWEc0Z0lDQWdkbUZ5SUhKbGJXOTJaVnh1SUNBZ0lIWmhjaUJwYm5ObGNuUmNibHh1SUNBZ0lHWnZjaUFvZG1GeUlHa2dQU0F3T3lCcElEd2diVzkyWlhNdWNtVnRiM1psY3k1c1pXNW5kR2c3SUdrckt5a2dlMXh1SUNBZ0lDQWdJQ0J5WlcxdmRtVWdQU0J0YjNabGN5NXlaVzF2ZG1WelcybGRYRzRnSUNBZ0lDQWdJRzV2WkdVZ1BTQmphR2xzWkU1dlpHVnpXM0psYlc5MlpTNW1jbTl0WFZ4dUlDQWdJQ0FnSUNCcFppQW9jbVZ0YjNabExtdGxlU2tnZTF4dUlDQWdJQ0FnSUNBZ0lDQWdhMlY1VFdGd1czSmxiVzkyWlM1clpYbGRJRDBnYm05a1pWeHVJQ0FnSUNBZ0lDQjlYRzRnSUNBZ0lDQWdJR1J2YlU1dlpHVXVjbVZ0YjNabFEyaHBiR1FvYm05a1pTbGNiaUFnSUNCOVhHNWNiaUFnSUNCMllYSWdiR1Z1WjNSb0lEMGdZMmhwYkdST2IyUmxjeTVzWlc1bmRHaGNiaUFnSUNCbWIzSWdLSFpoY2lCcUlEMGdNRHNnYWlBOElHMXZkbVZ6TG1sdWMyVnlkSE11YkdWdVozUm9PeUJxS3lzcElIdGNiaUFnSUNBZ0lDQWdhVzV6WlhKMElEMGdiVzkyWlhNdWFXNXpaWEowYzF0cVhWeHVJQ0FnSUNBZ0lDQnViMlJsSUQwZ2EyVjVUV0Z3VzJsdWMyVnlkQzVyWlhsZFhHNGdJQ0FnSUNBZ0lDOHZJSFJvYVhNZ2FYTWdkR2hsSUhkbGFYSmtaWE4wSUdKMVp5QnBKM1psSUdWMlpYSWdjMlZsYmlCcGJpQjNaV0pyYVhSY2JpQWdJQ0FnSUNBZ1pHOXRUbTlrWlM1cGJuTmxjblJDWldadmNtVW9ibTlrWlN3Z2FXNXpaWEowTG5SdklENDlJR3hsYm1kMGFDc3JJRDhnYm5Wc2JDQTZJR05vYVd4a1RtOWtaWE5iYVc1elpYSjBMblJ2WFNsY2JpQWdJQ0I5WEc1OVhHNWNibVoxYm1OMGFXOXVJSEpsY0d4aFkyVlNiMjkwS0c5c1pGSnZiM1FzSUc1bGQxSnZiM1FwSUh0Y2JpQWdJQ0JwWmlBb2IyeGtVbTl2ZENBbUppQnVaWGRTYjI5MElDWW1JRzlzWkZKdmIzUWdJVDA5SUc1bGQxSnZiM1FnSmlZZ2IyeGtVbTl2ZEM1d1lYSmxiblJPYjJSbEtTQjdYRzRnSUNBZ0lDQWdJRzlzWkZKdmIzUXVjR0Z5Wlc1MFRtOWtaUzV5WlhCc1lXTmxRMmhwYkdRb2JtVjNVbTl2ZEN3Z2IyeGtVbTl2ZENsY2JpQWdJQ0I5WEc1Y2JpQWdJQ0J5WlhSMWNtNGdibVYzVW05dmREdGNibjFjYmx4dWZTeDdYQ0l1TGk5MmJtOWtaUzlwY3kxM2FXUm5aWFF1YW5OY0lqb3lPU3hjSWk0dUwzWnViMlJsTDNad1lYUmphQzVxYzF3aU9qTXlMRndpTGk5aGNIQnNlUzF3Y205d1pYSjBhV1Z6WENJNk1UUXNYQ0l1TDNWd1pHRjBaUzEzYVdSblpYUmNJam94T1gxZExERTRPbHRtZFc1amRHbHZiaWh5WlhGMWFYSmxMRzF2WkhWc1pTeGxlSEJ2Y25SektYdGNiblpoY2lCa2IyTjFiV1Z1ZENBOUlISmxjWFZwY21Vb1hDSm5iRzlpWVd3dlpHOWpkVzFsYm5SY0lpbGNiblpoY2lCcGMwRnljbUY1SUQwZ2NtVnhkV2x5WlNoY0luZ3RhWE10WVhKeVlYbGNJaWxjYmx4dWRtRnlJSEpsYm1SbGNpQTlJSEpsY1hWcGNtVW9YQ0l1TDJOeVpXRjBaUzFsYkdWdFpXNTBYQ0lwWEc1MllYSWdaRzl0U1c1a1pYZ2dQU0J5WlhGMWFYSmxLRndpTGk5a2IyMHRhVzVrWlhoY0lpbGNiblpoY2lCd1lYUmphRTl3SUQwZ2NtVnhkV2x5WlNoY0lpNHZjR0YwWTJndGIzQmNJaWxjYm0xdlpIVnNaUzVsZUhCdmNuUnpJRDBnY0dGMFkyaGNibHh1Wm5WdVkzUnBiMjRnY0dGMFkyZ29jbTl2ZEU1dlpHVXNJSEJoZEdOb1pYTXNJSEpsYm1SbGNrOXdkR2x2Ym5NcElIdGNiaUFnSUNCeVpXNWtaWEpQY0hScGIyNXpJRDBnY21WdVpHVnlUM0IwYVc5dWN5QjhmQ0I3ZlZ4dUlDQWdJSEpsYm1SbGNrOXdkR2x2Ym5NdWNHRjBZMmdnUFNCeVpXNWtaWEpQY0hScGIyNXpMbkJoZEdOb0lDWW1JSEpsYm1SbGNrOXdkR2x2Ym5NdWNHRjBZMmdnSVQwOUlIQmhkR05vWEc0Z0lDQWdJQ0FnSUQ4Z2NtVnVaR1Z5VDNCMGFXOXVjeTV3WVhSamFGeHVJQ0FnSUNBZ0lDQTZJSEJoZEdOb1VtVmpkWEp6YVhabFhHNGdJQ0FnY21WdVpHVnlUM0IwYVc5dWN5NXlaVzVrWlhJZ1BTQnlaVzVrWlhKUGNIUnBiMjV6TG5KbGJtUmxjaUI4ZkNCeVpXNWtaWEpjYmx4dUlDQWdJSEpsZEhWeWJpQnlaVzVrWlhKUGNIUnBiMjV6TG5CaGRHTm9LSEp2YjNST2IyUmxMQ0J3WVhSamFHVnpMQ0J5Wlc1a1pYSlBjSFJwYjI1ektWeHVmVnh1WEc1bWRXNWpkR2x2YmlCd1lYUmphRkpsWTNWeWMybDJaU2h5YjI5MFRtOWtaU3dnY0dGMFkyaGxjeXdnY21WdVpHVnlUM0IwYVc5dWN5a2dlMXh1SUNBZ0lIWmhjaUJwYm1ScFkyVnpJRDBnY0dGMFkyaEpibVJwWTJWektIQmhkR05vWlhNcFhHNWNiaUFnSUNCcFppQW9hVzVrYVdObGN5NXNaVzVuZEdnZ1BUMDlJREFwSUh0Y2JpQWdJQ0FnSUNBZ2NtVjBkWEp1SUhKdmIzUk9iMlJsWEc0Z0lDQWdmVnh1WEc0Z0lDQWdkbUZ5SUdsdVpHVjRJRDBnWkc5dFNXNWtaWGdvY205dmRFNXZaR1VzSUhCaGRHTm9aWE11WVN3Z2FXNWthV05sY3lsY2JpQWdJQ0IyWVhJZ2IzZHVaWEpFYjJOMWJXVnVkQ0E5SUhKdmIzUk9iMlJsTG05M2JtVnlSRzlqZFcxbGJuUmNibHh1SUNBZ0lHbG1JQ2doY21WdVpHVnlUM0IwYVc5dWN5NWtiMk4xYldWdWRDQW1KaUJ2ZDI1bGNrUnZZM1Z0Wlc1MElDRTlQU0JrYjJOMWJXVnVkQ2tnZTF4dUlDQWdJQ0FnSUNCeVpXNWtaWEpQY0hScGIyNXpMbVJ2WTNWdFpXNTBJRDBnYjNkdVpYSkViMk4xYldWdWRGeHVJQ0FnSUgxY2JseHVJQ0FnSUdadmNpQW9kbUZ5SUdrZ1BTQXdPeUJwSUR3Z2FXNWthV05sY3k1c1pXNW5kR2c3SUdrckt5a2dlMXh1SUNBZ0lDQWdJQ0IyWVhJZ2JtOWtaVWx1WkdWNElEMGdhVzVrYVdObGMxdHBYVnh1SUNBZ0lDQWdJQ0J5YjI5MFRtOWtaU0E5SUdGd2NHeDVVR0YwWTJnb2NtOXZkRTV2WkdVc1hHNGdJQ0FnSUNBZ0lDQWdJQ0JwYm1SbGVGdHViMlJsU1c1a1pYaGRMRnh1SUNBZ0lDQWdJQ0FnSUNBZ2NHRjBZMmhsYzF0dWIyUmxTVzVrWlhoZExGeHVJQ0FnSUNBZ0lDQWdJQ0FnY21WdVpHVnlUM0IwYVc5dWN5bGNiaUFnSUNCOVhHNWNiaUFnSUNCeVpYUjFjbTRnY205dmRFNXZaR1ZjYm4xY2JseHVablZ1WTNScGIyNGdZWEJ3YkhsUVlYUmphQ2h5YjI5MFRtOWtaU3dnWkc5dFRtOWtaU3dnY0dGMFkyaE1hWE4wTENCeVpXNWtaWEpQY0hScGIyNXpLU0I3WEc0Z0lDQWdhV1lnS0NGa2IyMU9iMlJsS1NCN1hHNGdJQ0FnSUNBZ0lISmxkSFZ5YmlCeWIyOTBUbTlrWlZ4dUlDQWdJSDFjYmx4dUlDQWdJSFpoY2lCdVpYZE9iMlJsWEc1Y2JpQWdJQ0JwWmlBb2FYTkJjbkpoZVNod1lYUmphRXhwYzNRcEtTQjdYRzRnSUNBZ0lDQWdJR1p2Y2lBb2RtRnlJR2tnUFNBd095QnBJRHdnY0dGMFkyaE1hWE4wTG14bGJtZDBhRHNnYVNzcktTQjdYRzRnSUNBZ0lDQWdJQ0FnSUNCdVpYZE9iMlJsSUQwZ2NHRjBZMmhQY0Nod1lYUmphRXhwYzNSYmFWMHNJR1J2YlU1dlpHVXNJSEpsYm1SbGNrOXdkR2x2Ym5NcFhHNWNiaUFnSUNBZ0lDQWdJQ0FnSUdsbUlDaGtiMjFPYjJSbElEMDlQU0J5YjI5MFRtOWtaU2tnZTF4dUlDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUhKdmIzUk9iMlJsSUQwZ2JtVjNUbTlrWlZ4dUlDQWdJQ0FnSUNBZ0lDQWdmVnh1SUNBZ0lDQWdJQ0I5WEc0Z0lDQWdmU0JsYkhObElIdGNiaUFnSUNBZ0lDQWdibVYzVG05a1pTQTlJSEJoZEdOb1QzQW9jR0YwWTJoTWFYTjBMQ0JrYjIxT2IyUmxMQ0J5Wlc1a1pYSlBjSFJwYjI1ektWeHVYRzRnSUNBZ0lDQWdJR2xtSUNoa2IyMU9iMlJsSUQwOVBTQnliMjkwVG05a1pTa2dlMXh1SUNBZ0lDQWdJQ0FnSUNBZ2NtOXZkRTV2WkdVZ1BTQnVaWGRPYjJSbFhHNGdJQ0FnSUNBZ0lIMWNiaUFnSUNCOVhHNWNiaUFnSUNCeVpYUjFjbTRnY205dmRFNXZaR1ZjYm4xY2JseHVablZ1WTNScGIyNGdjR0YwWTJoSmJtUnBZMlZ6S0hCaGRHTm9aWE1wSUh0Y2JpQWdJQ0IyWVhJZ2FXNWthV05sY3lBOUlGdGRYRzVjYmlBZ0lDQm1iM0lnS0haaGNpQnJaWGtnYVc0Z2NHRjBZMmhsY3lrZ2UxeHVJQ0FnSUNBZ0lDQnBaaUFvYTJWNUlDRTlQU0JjSW1GY0lpa2dlMXh1SUNBZ0lDQWdJQ0FnSUNBZ2FXNWthV05sY3k1d2RYTm9LRTUxYldKbGNpaHJaWGtwS1Z4dUlDQWdJQ0FnSUNCOVhHNGdJQ0FnZlZ4dVhHNGdJQ0FnY21WMGRYSnVJR2x1WkdsalpYTmNibjFjYmx4dWZTeDdYQ0l1TDJOeVpXRjBaUzFsYkdWdFpXNTBYQ0k2TVRVc1hDSXVMMlJ2YlMxcGJtUmxlRndpT2pFMkxGd2lMaTl3WVhSamFDMXZjRndpT2pFM0xGd2laMnh2WW1Gc0wyUnZZM1Z0Wlc1MFhDSTZNVEFzWENKNExXbHpMV0Z5Y21GNVhDSTZNVEo5WFN3eE9UcGJablZ1WTNScGIyNG9jbVZ4ZFdseVpTeHRiMlIxYkdVc1pYaHdiM0owY3lsN1hHNTJZWElnYVhOWGFXUm5aWFFnUFNCeVpYRjFhWEpsS0Z3aUxpNHZkbTV2WkdVdmFYTXRkMmxrWjJWMExtcHpYQ0lwWEc1Y2JtMXZaSFZzWlM1bGVIQnZjblJ6SUQwZ2RYQmtZWFJsVjJsa1oyVjBYRzVjYm1aMWJtTjBhVzl1SUhWd1pHRjBaVmRwWkdkbGRDaGhMQ0JpS1NCN1hHNGdJQ0FnYVdZZ0tHbHpWMmxrWjJWMEtHRXBJQ1ltSUdselYybGtaMlYwS0dJcEtTQjdYRzRnSUNBZ0lDQWdJR2xtSUNoY0ltNWhiV1ZjSWlCcGJpQmhJQ1ltSUZ3aWJtRnRaVndpSUdsdUlHSXBJSHRjYmlBZ0lDQWdJQ0FnSUNBZ0lISmxkSFZ5YmlCaExtbGtJRDA5UFNCaUxtbGtYRzRnSUNBZ0lDQWdJSDBnWld4elpTQjdYRzRnSUNBZ0lDQWdJQ0FnSUNCeVpYUjFjbTRnWVM1cGJtbDBJRDA5UFNCaUxtbHVhWFJjYmlBZ0lDQWdJQ0FnZlZ4dUlDQWdJSDFjYmx4dUlDQWdJSEpsZEhWeWJpQm1ZV3h6WlZ4dWZWeHVYRzU5TEh0Y0lpNHVMM1p1YjJSbEwybHpMWGRwWkdkbGRDNXFjMXdpT2pJNWZWMHNNakE2VzJaMWJtTjBhVzl1S0hKbGNYVnBjbVVzYlc5a2RXeGxMR1Y0Y0c5eWRITXBlMXh1SjNWelpTQnpkSEpwWTNRbk8xeHVYRzUyWVhJZ1JYWlRkRzl5WlNBOUlISmxjWFZwY21Vb0oyVjJMWE4wYjNKbEp5azdYRzVjYm0xdlpIVnNaUzVsZUhCdmNuUnpJRDBnUlhaSWIyOXJPMXh1WEc1bWRXNWpkR2x2YmlCRmRraHZiMnNvZG1Gc2RXVXBJSHRjYmlBZ0lDQnBaaUFvSVNoMGFHbHpJR2x1YzNSaGJtTmxiMllnUlhaSWIyOXJLU2tnZTF4dUlDQWdJQ0FnSUNCeVpYUjFjbTRnYm1WM0lFVjJTRzl2YXloMllXeDFaU2s3WEc0Z0lDQWdmVnh1WEc0Z0lDQWdkR2hwY3k1MllXeDFaU0E5SUhaaGJIVmxPMXh1ZlZ4dVhHNUZka2h2YjJzdWNISnZkRzkwZVhCbExtaHZiMnNnUFNCbWRXNWpkR2x2YmlBb2JtOWtaU3dnY0hKdmNHVnlkSGxPWVcxbEtTQjdYRzRnSUNBZ2RtRnlJR1Z6SUQwZ1JYWlRkRzl5WlNodWIyUmxLVHRjYmlBZ0lDQjJZWElnY0hKdmNFNWhiV1VnUFNCd2NtOXdaWEowZVU1aGJXVXVjM1ZpYzNSeUtETXBPMXh1WEc0Z0lDQWdaWE5iY0hKdmNFNWhiV1ZkSUQwZ2RHaHBjeTUyWVd4MVpUdGNibjA3WEc1Y2JrVjJTRzl2YXk1d2NtOTBiM1I1Y0dVdWRXNW9iMjlySUQwZ1puVnVZM1JwYjI0b2JtOWtaU3dnY0hKdmNHVnlkSGxPWVcxbEtTQjdYRzRnSUNBZ2RtRnlJR1Z6SUQwZ1JYWlRkRzl5WlNodWIyUmxLVHRjYmlBZ0lDQjJZWElnY0hKdmNFNWhiV1VnUFNCd2NtOXdaWEowZVU1aGJXVXVjM1ZpYzNSeUtETXBPMXh1WEc0Z0lDQWdaWE5iY0hKdmNFNWhiV1ZkSUQwZ2RXNWtaV1pwYm1Wa08xeHVmVHRjYmx4dWZTeDdYQ0psZGkxemRHOXlaVndpT2pkOVhTd3lNVHBiWm5WdVkzUnBiMjRvY21WeGRXbHlaU3h0YjJSMWJHVXNaWGh3YjNKMGN5bDdYRzRuZFhObElITjBjbWxqZENjN1hHNWNibTF2WkhWc1pTNWxlSEJ2Y25SeklEMGdVMjltZEZObGRFaHZiMnM3WEc1Y2JtWjFibU4wYVc5dUlGTnZablJUWlhSSWIyOXJLSFpoYkhWbEtTQjdYRzRnSUNBZ2FXWWdLQ0VvZEdocGN5QnBibk4wWVc1alpXOW1JRk52Wm5SVFpYUkliMjlyS1NrZ2UxeHVJQ0FnSUNBZ0lDQnlaWFIxY200Z2JtVjNJRk52Wm5SVFpYUkliMjlyS0haaGJIVmxLVHRjYmlBZ0lDQjlYRzVjYmlBZ0lDQjBhR2x6TG5aaGJIVmxJRDBnZG1Gc2RXVTdYRzU5WEc1Y2JsTnZablJUWlhSSWIyOXJMbkJ5YjNSdmRIbHdaUzVvYjI5cklEMGdablZ1WTNScGIyNGdLRzV2WkdVc0lIQnliM0JsY25SNVRtRnRaU2tnZTF4dUlDQWdJR2xtSUNodWIyUmxXM0J5YjNCbGNuUjVUbUZ0WlYwZ0lUMDlJSFJvYVhNdWRtRnNkV1VwSUh0Y2JpQWdJQ0FnSUNBZ2JtOWtaVnR3Y205d1pYSjBlVTVoYldWZElEMGdkR2hwY3k1MllXeDFaVHRjYmlBZ0lDQjlYRzU5TzF4dVhHNTlMSHQ5WFN3eU1qcGJablZ1WTNScGIyNG9jbVZ4ZFdseVpTeHRiMlIxYkdVc1pYaHdiM0owY3lsN1hHNG5kWE5sSUhOMGNtbGpkQ2M3WEc1Y2JuWmhjaUJwYzBGeWNtRjVJRDBnY21WeGRXbHlaU2duZUMxcGN5MWhjbkpoZVNjcE8xeHVYRzUyWVhJZ1ZrNXZaR1VnUFNCeVpYRjFhWEpsS0NjdUxpOTJibTlrWlM5MmJtOWtaUzVxY3ljcE8xeHVkbUZ5SUZaVVpYaDBJRDBnY21WeGRXbHlaU2duTGk0dmRtNXZaR1V2ZG5SbGVIUXVhbk1uS1R0Y2JuWmhjaUJwYzFaT2IyUmxJRDBnY21WeGRXbHlaU2duTGk0dmRtNXZaR1V2YVhNdGRtNXZaR1VuS1R0Y2JuWmhjaUJwYzFaVVpYaDBJRDBnY21WeGRXbHlaU2duTGk0dmRtNXZaR1V2YVhNdGRuUmxlSFFuS1R0Y2JuWmhjaUJwYzFkcFpHZGxkQ0E5SUhKbGNYVnBjbVVvSnk0dUwzWnViMlJsTDJsekxYZHBaR2RsZENjcE8xeHVkbUZ5SUdselNHOXZheUE5SUhKbGNYVnBjbVVvSnk0dUwzWnViMlJsTDJsekxYWm9iMjlySnlrN1hHNTJZWElnYVhOV1ZHaDFibXNnUFNCeVpYRjFhWEpsS0NjdUxpOTJibTlrWlM5cGN5MTBhSFZ1YXljcE8xeHVYRzUyWVhJZ2NHRnljMlZVWVdjZ1BTQnlaWEYxYVhKbEtDY3VMM0JoY25ObExYUmhaeTVxY3ljcE8xeHVkbUZ5SUhOdlpuUlRaWFJJYjI5cklEMGdjbVZ4ZFdseVpTZ25MaTlvYjI5cmN5OXpiMlowTFhObGRDMW9iMjlyTG1wekp5azdYRzUyWVhJZ1pYWkliMjlySUQwZ2NtVnhkV2x5WlNnbkxpOW9iMjlyY3k5bGRpMW9iMjlyTG1wekp5azdYRzVjYm0xdlpIVnNaUzVsZUhCdmNuUnpJRDBnYUR0Y2JseHVablZ1WTNScGIyNGdhQ2gwWVdkT1lXMWxMQ0J3Y205d1pYSjBhV1Z6TENCamFHbHNaSEpsYmlrZ2UxeHVJQ0FnSUhaaGNpQmphR2xzWkU1dlpHVnpJRDBnVzEwN1hHNGdJQ0FnZG1GeUlIUmhaeXdnY0hKdmNITXNJR3RsZVN3Z2JtRnRaWE53WVdObE8xeHVYRzRnSUNBZ2FXWWdLQ0ZqYUdsc1pISmxiaUFtSmlCcGMwTm9hV3hrY21WdUtIQnliM0JsY25ScFpYTXBLU0I3WEc0Z0lDQWdJQ0FnSUdOb2FXeGtjbVZ1SUQwZ2NISnZjR1Z5ZEdsbGN6dGNiaUFnSUNBZ0lDQWdjSEp2Y0hNZ1BTQjdmVHRjYmlBZ0lDQjlYRzVjYmlBZ0lDQndjbTl3Y3lBOUlIQnliM0J6SUh4OElIQnliM0JsY25ScFpYTWdmSHdnZTMwN1hHNGdJQ0FnZEdGbklEMGdjR0Z5YzJWVVlXY29kR0ZuVG1GdFpTd2djSEp2Y0hNcE8xeHVYRzRnSUNBZ0x5OGdjM1Z3Y0c5eWRDQnJaWGx6WEc0Z0lDQWdhV1lnS0hCeWIzQnpMbWhoYzA5M2JsQnliM0JsY25SNUtDZHJaWGtuS1NrZ2UxeHVJQ0FnSUNBZ0lDQnJaWGtnUFNCd2NtOXdjeTVyWlhrN1hHNGdJQ0FnSUNBZ0lIQnliM0J6TG10bGVTQTlJSFZ1WkdWbWFXNWxaRHRjYmlBZ0lDQjlYRzVjYmlBZ0lDQXZMeUJ6ZFhCd2IzSjBJRzVoYldWemNHRmpaVnh1SUNBZ0lHbG1JQ2h3Y205d2N5NW9ZWE5QZDI1UWNtOXdaWEowZVNnbmJtRnRaWE53WVdObEp5a3BJSHRjYmlBZ0lDQWdJQ0FnYm1GdFpYTndZV05sSUQwZ2NISnZjSE11Ym1GdFpYTndZV05sTzF4dUlDQWdJQ0FnSUNCd2NtOXdjeTV1WVcxbGMzQmhZMlVnUFNCMWJtUmxabWx1WldRN1hHNGdJQ0FnZlZ4dVhHNGdJQ0FnTHk4Z1ptbDRJR04xY25OdmNpQmlkV2RjYmlBZ0lDQnBaaUFvZEdGbklEMDlQU0FuU1U1UVZWUW5JQ1ltWEc0Z0lDQWdJQ0FnSUNGdVlXMWxjM0JoWTJVZ0ppWmNiaUFnSUNBZ0lDQWdjSEp2Y0hNdWFHRnpUM2R1VUhKdmNHVnlkSGtvSjNaaGJIVmxKeWtnSmlaY2JpQWdJQ0FnSUNBZ2NISnZjSE11ZG1Gc2RXVWdJVDA5SUhWdVpHVm1hVzVsWkNBbUpseHVJQ0FnSUNBZ0lDQWhhWE5JYjI5cktIQnliM0J6TG5aaGJIVmxLVnh1SUNBZ0lDa2dlMXh1SUNBZ0lDQWdJQ0J3Y205d2N5NTJZV3gxWlNBOUlITnZablJUWlhSSWIyOXJLSEJ5YjNCekxuWmhiSFZsS1R0Y2JpQWdJQ0I5WEc1Y2JpQWdJQ0IwY21GdWMyWnZjbTFRY205d1pYSjBhV1Z6S0hCeWIzQnpLVHRjYmx4dUlDQWdJR2xtSUNoamFHbHNaSEpsYmlBaFBUMGdkVzVrWldacGJtVmtJQ1ltSUdOb2FXeGtjbVZ1SUNFOVBTQnVkV3hzS1NCN1hHNGdJQ0FnSUNBZ0lHRmtaRU5vYVd4a0tHTm9hV3hrY21WdUxDQmphR2xzWkU1dlpHVnpMQ0IwWVdjc0lIQnliM0J6S1R0Y2JpQWdJQ0I5WEc1Y2JseHVJQ0FnSUhKbGRIVnliaUJ1WlhjZ1ZrNXZaR1VvZEdGbkxDQndjbTl3Y3l3Z1kyaHBiR1JPYjJSbGN5d2dhMlY1TENCdVlXMWxjM0JoWTJVcE8xeHVmVnh1WEc1bWRXNWpkR2x2YmlCaFpHUkRhR2xzWkNoakxDQmphR2xzWkU1dlpHVnpMQ0IwWVdjc0lIQnliM0J6S1NCN1hHNGdJQ0FnYVdZZ0tIUjVjR1Z2WmlCaklEMDlQU0FuYzNSeWFXNW5KeWtnZTF4dUlDQWdJQ0FnSUNCamFHbHNaRTV2WkdWekxuQjFjMmdvYm1WM0lGWlVaWGgwS0dNcEtUdGNiaUFnSUNCOUlHVnNjMlVnYVdZZ0tIUjVjR1Z2WmlCaklEMDlQU0FuYm5WdFltVnlKeWtnZTF4dUlDQWdJQ0FnSUNCamFHbHNaRTV2WkdWekxuQjFjMmdvYm1WM0lGWlVaWGgwS0ZOMGNtbHVaeWhqS1NrcE8xeHVJQ0FnSUgwZ1pXeHpaU0JwWmlBb2FYTkRhR2xzWkNoaktTa2dlMXh1SUNBZ0lDQWdJQ0JqYUdsc1pFNXZaR1Z6TG5CMWMyZ29ZeWs3WEc0Z0lDQWdmU0JsYkhObElHbG1JQ2hwYzBGeWNtRjVLR01wS1NCN1hHNGdJQ0FnSUNBZ0lHWnZjaUFvZG1GeUlHa2dQU0F3T3lCcElEd2dZeTVzWlc1bmRHZzdJR2tyS3lrZ2UxeHVJQ0FnSUNBZ0lDQWdJQ0FnWVdSa1EyaHBiR1FvWTF0cFhTd2dZMmhwYkdST2IyUmxjeXdnZEdGbkxDQndjbTl3Y3lrN1hHNGdJQ0FnSUNBZ0lIMWNiaUFnSUNCOUlHVnNjMlVnYVdZZ0tHTWdQVDA5SUc1MWJHd2dmSHdnWXlBOVBUMGdkVzVrWldacGJtVmtLU0I3WEc0Z0lDQWdJQ0FnSUhKbGRIVnlianRjYmlBZ0lDQjlJR1ZzYzJVZ2UxeHVJQ0FnSUNBZ0lDQjBhSEp2ZHlCVmJtVjRjR1ZqZEdWa1ZtbHlkSFZoYkVWc1pXMWxiblFvZTF4dUlDQWdJQ0FnSUNBZ0lDQWdabTl5WldsbmJrOWlhbVZqZERvZ1l5eGNiaUFnSUNBZ0lDQWdJQ0FnSUhCaGNtVnVkRlp1YjJSbE9pQjdYRzRnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdkR0ZuVG1GdFpUb2dkR0ZuTEZ4dUlDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUhCeWIzQmxjblJwWlhNNklIQnliM0J6WEc0Z0lDQWdJQ0FnSUNBZ0lDQjlYRzRnSUNBZ0lDQWdJSDBwTzF4dUlDQWdJSDFjYm4xY2JseHVablZ1WTNScGIyNGdkSEpoYm5ObWIzSnRVSEp2Y0dWeWRHbGxjeWh3Y205d2N5a2dlMXh1SUNBZ0lHWnZjaUFvZG1GeUlIQnliM0JPWVcxbElHbHVJSEJ5YjNCektTQjdYRzRnSUNBZ0lDQWdJR2xtSUNod2NtOXdjeTVvWVhOUGQyNVFjbTl3WlhKMGVTaHdjbTl3VG1GdFpTa3BJSHRjYmlBZ0lDQWdJQ0FnSUNBZ0lIWmhjaUIyWVd4MVpTQTlJSEJ5YjNCelczQnliM0JPWVcxbFhUdGNibHh1SUNBZ0lDQWdJQ0FnSUNBZ2FXWWdLR2x6U0c5dmF5aDJZV3gxWlNrcElIdGNiaUFnSUNBZ0lDQWdJQ0FnSUNBZ0lDQmpiMjUwYVc1MVpUdGNiaUFnSUNBZ0lDQWdJQ0FnSUgxY2JseHVJQ0FnSUNBZ0lDQWdJQ0FnYVdZZ0tIQnliM0JPWVcxbExuTjFZbk4wY2lnd0xDQXpLU0E5UFQwZ0oyVjJMU2NwSUh0Y2JpQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBdkx5QmhaR1FnWlhZdFptOXZJSE4xY0hCdmNuUmNiaUFnSUNBZ0lDQWdJQ0FnSUNBZ0lDQndjbTl3YzF0d2NtOXdUbUZ0WlYwZ1BTQmxka2h2YjJzb2RtRnNkV1VwTzF4dUlDQWdJQ0FnSUNBZ0lDQWdmVnh1SUNBZ0lDQWdJQ0I5WEc0Z0lDQWdmVnh1ZlZ4dVhHNW1kVzVqZEdsdmJpQnBjME5vYVd4a0tIZ3BJSHRjYmlBZ0lDQnlaWFIxY200Z2FYTldUbTlrWlNoNEtTQjhmQ0JwYzFaVVpYaDBLSGdwSUh4OElHbHpWMmxrWjJWMEtIZ3BJSHg4SUdselZsUm9kVzVyS0hncE8xeHVmVnh1WEc1bWRXNWpkR2x2YmlCcGMwTm9hV3hrY21WdUtIZ3BJSHRjYmlBZ0lDQnlaWFIxY200Z2RIbHdaVzltSUhnZ1BUMDlJQ2R6ZEhKcGJtY25JSHg4SUdselFYSnlZWGtvZUNrZ2ZId2dhWE5EYUdsc1pDaDRLVHRjYm4xY2JseHVablZ1WTNScGIyNGdWVzVsZUhCbFkzUmxaRlpwY25SMVlXeEZiR1Z0Wlc1MEtHUmhkR0VwSUh0Y2JpQWdJQ0IyWVhJZ1pYSnlJRDBnYm1WM0lFVnljbTl5S0NrN1hHNWNiaUFnSUNCbGNuSXVkSGx3WlNBOUlDZDJhWEowZFdGc0xXaDVjR1Z5YzJOeWFYQjBMblZ1Wlhod1pXTjBaV1F1ZG1seWRIVmhiQzFsYkdWdFpXNTBKenRjYmlBZ0lDQmxjbkl1YldWemMyRm5aU0E5SUNkVmJtVjRjR1ZqZEdWa0lIWnBjblIxWVd3Z1kyaHBiR1FnY0dGemMyVmtJSFJ2SUdnb0tTNWNYRzRuSUN0Y2JpQWdJQ0FnSUNBZ0owVjRjR1ZqZEdWa0lHRWdWazV2WkdVZ0x5QldkR2gxYm1zZ0x5QldWMmxrWjJWMElDOGdjM1J5YVc1bklHSjFkRHBjWEc0bklDdGNiaUFnSUNBZ0lDQWdKMmR2ZERwY1hHNG5JQ3RjYmlBZ0lDQWdJQ0FnWlhKeWIzSlRkSEpwYm1jb1pHRjBZUzVtYjNKbGFXZHVUMkpxWldOMEtTQXJYRzRnSUNBZ0lDQWdJQ2N1WEZ4dUp5QXJYRzRnSUNBZ0lDQWdJQ2RVYUdVZ2NHRnlaVzUwSUhadWIyUmxJR2x6T2x4Y2JpY2dLMXh1SUNBZ0lDQWdJQ0JsY25KdmNsTjBjbWx1Wnloa1lYUmhMbkJoY21WdWRGWnViMlJsS1Z4dUlDQWdJQ0FnSUNBblhGeHVKeUFyWEc0Z0lDQWdJQ0FnSUNkVGRXZG5aWE4wWldRZ1ptbDRPaUJqYUdGdVoyVWdlVzkxY2lCZ2FDZ3VMaTRzSUZzZ0xpNHVJRjBwWUNCallXeHNjMmwwWlM0bk8xeHVJQ0FnSUdWeWNpNW1iM0psYVdkdVQySnFaV04wSUQwZ1pHRjBZUzVtYjNKbGFXZHVUMkpxWldOME8xeHVJQ0FnSUdWeWNpNXdZWEpsYm5SV2JtOWtaU0E5SUdSaGRHRXVjR0Z5Wlc1MFZtNXZaR1U3WEc1Y2JpQWdJQ0J5WlhSMWNtNGdaWEp5TzF4dWZWeHVYRzVtZFc1amRHbHZiaUJsY25KdmNsTjBjbWx1Wnlodlltb3BJSHRjYmlBZ0lDQjBjbmtnZTF4dUlDQWdJQ0FnSUNCeVpYUjFjbTRnU2xOUFRpNXpkSEpwYm1kcFpua29iMkpxTENCdWRXeHNMQ0FuSUNBZ0lDY3BPMXh1SUNBZ0lIMGdZMkYwWTJnZ0tHVXBJSHRjYmlBZ0lDQWdJQ0FnY21WMGRYSnVJRk4wY21sdVp5aHZZbW9wTzF4dUlDQWdJSDFjYm4xY2JseHVmU3g3WENJdUxpOTJibTlrWlM5cGN5MTBhSFZ1YTF3aU9qSTFMRndpTGk0dmRtNXZaR1V2YVhNdGRtaHZiMnRjSWpveU5peGNJaTR1TDNadWIyUmxMMmx6TFhadWIyUmxYQ0k2TWpjc1hDSXVMaTkyYm05a1pTOXBjeTEyZEdWNGRGd2lPakk0TEZ3aUxpNHZkbTV2WkdVdmFYTXRkMmxrWjJWMFhDSTZNamtzWENJdUxpOTJibTlrWlM5MmJtOWtaUzVxYzF3aU9qTXhMRndpTGk0dmRtNXZaR1V2ZG5SbGVIUXVhbk5jSWpvek15eGNJaTR2YUc5dmEzTXZaWFl0YUc5dmF5NXFjMXdpT2pJd0xGd2lMaTlvYjI5cmN5OXpiMlowTFhObGRDMW9iMjlyTG1welhDSTZNakVzWENJdUwzQmhjbk5sTFhSaFp5NXFjMXdpT2pJekxGd2llQzFwY3kxaGNuSmhlVndpT2pFeWZWMHNNak02VzJaMWJtTjBhVzl1S0hKbGNYVnBjbVVzYlc5a2RXeGxMR1Y0Y0c5eWRITXBlMXh1SjNWelpTQnpkSEpwWTNRbk8xeHVYRzUyWVhJZ2MzQnNhWFFnUFNCeVpYRjFhWEpsS0NkaWNtOTNjMlZ5TFhOd2JHbDBKeWs3WEc1Y2JuWmhjaUJqYkdGemMwbGtVM0JzYVhRZ1BTQXZLRnRjWEM0alhUOWJZUzE2UVMxYU1DMDVYRngxTURBM1JpMWNYSFZHUmtaR1h6b3RYU3NwTHp0Y2JuWmhjaUJ1YjNSRGJHRnpjMGxrSUQwZ0wxNWNYQzU4SXk4N1hHNWNibTF2WkhWc1pTNWxlSEJ2Y25SeklEMGdjR0Z5YzJWVVlXYzdYRzVjYm1aMWJtTjBhVzl1SUhCaGNuTmxWR0ZuS0hSaFp5d2djSEp2Y0hNcElIdGNiaUFnSUNCcFppQW9JWFJoWnlrZ2UxeHVJQ0FnSUNBZ0lDQnlaWFIxY200Z0owUkpWaWM3WEc0Z0lDQWdmVnh1WEc0Z0lDQWdkbUZ5SUc1dlNXUWdQU0FoS0hCeWIzQnpMbWhoYzA5M2JsQnliM0JsY25SNUtDZHBaQ2NwS1R0Y2JseHVJQ0FnSUhaaGNpQjBZV2RRWVhKMGN5QTlJSE53YkdsMEtIUmhaeXdnWTJ4aGMzTkpaRk53YkdsMEtUdGNiaUFnSUNCMllYSWdkR0ZuVG1GdFpTQTlJRzUxYkd3N1hHNWNiaUFnSUNCcFppQW9ibTkwUTJ4aGMzTkpaQzUwWlhOMEtIUmhaMUJoY25Seld6RmRLU2tnZTF4dUlDQWdJQ0FnSUNCMFlXZE9ZVzFsSUQwZ0owUkpWaWM3WEc0Z0lDQWdmVnh1WEc0Z0lDQWdkbUZ5SUdOc1lYTnpaWE1zSUhCaGNuUXNJSFI1Y0dVc0lHazdYRzVjYmlBZ0lDQm1iM0lnS0drZ1BTQXdPeUJwSUR3Z2RHRm5VR0Z5ZEhNdWJHVnVaM1JvT3lCcEt5c3BJSHRjYmlBZ0lDQWdJQ0FnY0dGeWRDQTlJSFJoWjFCaGNuUnpXMmxkTzF4dVhHNGdJQ0FnSUNBZ0lHbG1JQ2doY0dGeWRDa2dlMXh1SUNBZ0lDQWdJQ0FnSUNBZ1kyOXVkR2x1ZFdVN1hHNGdJQ0FnSUNBZ0lIMWNibHh1SUNBZ0lDQWdJQ0IwZVhCbElEMGdjR0Z5ZEM1amFHRnlRWFFvTUNrN1hHNWNiaUFnSUNBZ0lDQWdhV1lnS0NGMFlXZE9ZVzFsS1NCN1hHNGdJQ0FnSUNBZ0lDQWdJQ0IwWVdkT1lXMWxJRDBnY0dGeWREdGNiaUFnSUNBZ0lDQWdmU0JsYkhObElHbG1JQ2gwZVhCbElEMDlQU0FuTGljcElIdGNiaUFnSUNBZ0lDQWdJQ0FnSUdOc1lYTnpaWE1nUFNCamJHRnpjMlZ6SUh4OElGdGRPMXh1SUNBZ0lDQWdJQ0FnSUNBZ1kyeGhjM05sY3k1d2RYTm9LSEJoY25RdWMzVmljM1J5YVc1bktERXNJSEJoY25RdWJHVnVaM1JvS1NrN1hHNGdJQ0FnSUNBZ0lIMGdaV3h6WlNCcFppQW9kSGx3WlNBOVBUMGdKeU1uSUNZbUlHNXZTV1FwSUh0Y2JpQWdJQ0FnSUNBZ0lDQWdJSEJ5YjNCekxtbGtJRDBnY0dGeWRDNXpkV0p6ZEhKcGJtY29NU3dnY0dGeWRDNXNaVzVuZEdncE8xeHVJQ0FnSUNBZ0lDQjlYRzRnSUNBZ2ZWeHVYRzRnSUNBZ2FXWWdLR05zWVhOelpYTXBJSHRjYmlBZ0lDQWdJQ0FnYVdZZ0tIQnliM0J6TG1Oc1lYTnpUbUZ0WlNrZ2UxeHVJQ0FnSUNBZ0lDQWdJQ0FnWTJ4aGMzTmxjeTV3ZFhOb0tIQnliM0J6TG1Oc1lYTnpUbUZ0WlNrN1hHNGdJQ0FnSUNBZ0lIMWNibHh1SUNBZ0lDQWdJQ0J3Y205d2N5NWpiR0Z6YzA1aGJXVWdQU0JqYkdGemMyVnpMbXB2YVc0b0p5QW5LVHRjYmlBZ0lDQjlYRzVjYmlBZ0lDQnlaWFIxY200Z2NISnZjSE11Ym1GdFpYTndZV05sSUQ4Z2RHRm5UbUZ0WlNBNklIUmhaMDVoYldVdWRHOVZjSEJsY2tOaGMyVW9LVHRjYm4xY2JseHVmU3g3WENKaWNtOTNjMlZ5TFhOd2JHbDBYQ0k2TlgxZExESTBPbHRtZFc1amRHbHZiaWh5WlhGMWFYSmxMRzF2WkhWc1pTeGxlSEJ2Y25SektYdGNiblpoY2lCcGMxWk9iMlJsSUQwZ2NtVnhkV2x5WlNoY0lpNHZhWE10ZG01dlpHVmNJaWxjYm5aaGNpQnBjMVpVWlhoMElEMGdjbVZ4ZFdseVpTaGNJaTR2YVhNdGRuUmxlSFJjSWlsY2JuWmhjaUJwYzFkcFpHZGxkQ0E5SUhKbGNYVnBjbVVvWENJdUwybHpMWGRwWkdkbGRGd2lLVnh1ZG1GeUlHbHpWR2gxYm1zZ1BTQnlaWEYxYVhKbEtGd2lMaTlwY3kxMGFIVnVhMXdpS1Z4dVhHNXRiMlIxYkdVdVpYaHdiM0owY3lBOUlHaGhibVJzWlZSb2RXNXJYRzVjYm1aMWJtTjBhVzl1SUdoaGJtUnNaVlJvZFc1cktHRXNJR0lwSUh0Y2JpQWdJQ0IyWVhJZ2NtVnVaR1Z5WldSQklEMGdZVnh1SUNBZ0lIWmhjaUJ5Wlc1a1pYSmxaRUlnUFNCaVhHNWNiaUFnSUNCcFppQW9hWE5VYUhWdWF5aGlLU2tnZTF4dUlDQWdJQ0FnSUNCeVpXNWtaWEpsWkVJZ1BTQnlaVzVrWlhKVWFIVnVheWhpTENCaEtWeHVJQ0FnSUgxY2JseHVJQ0FnSUdsbUlDaHBjMVJvZFc1cktHRXBLU0I3WEc0Z0lDQWdJQ0FnSUhKbGJtUmxjbVZrUVNBOUlISmxibVJsY2xSb2RXNXJLR0VzSUc1MWJHd3BYRzRnSUNBZ2ZWeHVYRzRnSUNBZ2NtVjBkWEp1SUh0Y2JpQWdJQ0FnSUNBZ1lUb2djbVZ1WkdWeVpXUkJMRnh1SUNBZ0lDQWdJQ0JpT2lCeVpXNWtaWEpsWkVKY2JpQWdJQ0I5WEc1OVhHNWNibVoxYm1OMGFXOXVJSEpsYm1SbGNsUm9kVzVyS0hSb2RXNXJMQ0J3Y21WMmFXOTFjeWtnZTF4dUlDQWdJSFpoY2lCeVpXNWtaWEpsWkZSb2RXNXJJRDBnZEdoMWJtc3VkbTV2WkdWY2JseHVJQ0FnSUdsbUlDZ2hjbVZ1WkdWeVpXUlVhSFZ1YXlrZ2UxeHVJQ0FnSUNBZ0lDQnlaVzVrWlhKbFpGUm9kVzVySUQwZ2RHaDFibXN1ZG01dlpHVWdQU0IwYUhWdWF5NXlaVzVrWlhJb2NISmxkbWx2ZFhNcFhHNGdJQ0FnZlZ4dVhHNGdJQ0FnYVdZZ0tDRW9hWE5XVG05a1pTaHlaVzVrWlhKbFpGUm9kVzVyS1NCOGZGeHVJQ0FnSUNBZ0lDQWdJQ0FnYVhOV1ZHVjRkQ2h5Wlc1a1pYSmxaRlJvZFc1cktTQjhmRnh1SUNBZ0lDQWdJQ0FnSUNBZ2FYTlhhV1JuWlhRb2NtVnVaR1Z5WldSVWFIVnVheWtwS1NCN1hHNGdJQ0FnSUNBZ0lIUm9jbTkzSUc1bGR5QkZjbkp2Y2loY0luUm9kVzVySUdScFpDQnViM1FnY21WMGRYSnVJR0VnZG1Gc2FXUWdibTlrWlZ3aUtUdGNiaUFnSUNCOVhHNWNiaUFnSUNCeVpYUjFjbTRnY21WdVpHVnlaV1JVYUhWdWExeHVmVnh1WEc1OUxIdGNJaTR2YVhNdGRHaDFibXRjSWpveU5TeGNJaTR2YVhNdGRtNXZaR1ZjSWpveU55eGNJaTR2YVhNdGRuUmxlSFJjSWpveU9DeGNJaTR2YVhNdGQybGtaMlYwWENJNk1qbDlYU3d5TlRwYlpuVnVZM1JwYjI0b2NtVnhkV2x5WlN4dGIyUjFiR1VzWlhod2IzSjBjeWw3WEc1dGIyUjFiR1V1Wlhod2IzSjBjeUE5SUdselZHaDFibXRjYmx4dVpuVnVZM1JwYjI0Z2FYTlVhSFZ1YXloMEtTQjdYRzRnSUNBZ2NtVjBkWEp1SUhRZ0ppWWdkQzUwZVhCbElEMDlQU0JjSWxSb2RXNXJYQ0pjYm4xY2JseHVmU3g3ZlYwc01qWTZXMloxYm1OMGFXOXVLSEpsY1hWcGNtVXNiVzlrZFd4bExHVjRjRzl5ZEhNcGUxeHViVzlrZFd4bExtVjRjRzl5ZEhNZ1BTQnBjMGh2YjJ0Y2JseHVablZ1WTNScGIyNGdhWE5JYjI5cktHaHZiMnNwSUh0Y2JpQWdJQ0J5WlhSMWNtNGdhRzl2YXlBbUpseHVJQ0FnSUNBZ0tIUjVjR1Z2WmlCb2IyOXJMbWh2YjJzZ1BUMDlJRndpWm5WdVkzUnBiMjVjSWlBbUppQWhhRzl2YXk1b1lYTlBkMjVRY205d1pYSjBlU2hjSW1odmIydGNJaWtnZkh4Y2JpQWdJQ0FnSUNCMGVYQmxiMllnYUc5dmF5NTFibWh2YjJzZ1BUMDlJRndpWm5WdVkzUnBiMjVjSWlBbUppQWhhRzl2YXk1b1lYTlBkMjVRY205d1pYSjBlU2hjSW5WdWFHOXZhMXdpS1NsY2JuMWNibHh1ZlN4N2ZWMHNNamM2VzJaMWJtTjBhVzl1S0hKbGNYVnBjbVVzYlc5a2RXeGxMR1Y0Y0c5eWRITXBlMXh1ZG1GeUlIWmxjbk5wYjI0Z1BTQnlaWEYxYVhKbEtGd2lMaTkyWlhKemFXOXVYQ0lwWEc1Y2JtMXZaSFZzWlM1bGVIQnZjblJ6SUQwZ2FYTldhWEowZFdGc1RtOWtaVnh1WEc1bWRXNWpkR2x2YmlCcGMxWnBjblIxWVd4T2IyUmxLSGdwSUh0Y2JpQWdJQ0J5WlhSMWNtNGdlQ0FtSmlCNExuUjVjR1VnUFQwOUlGd2lWbWx5ZEhWaGJFNXZaR1ZjSWlBbUppQjRMblpsY25OcGIyNGdQVDA5SUhabGNuTnBiMjVjYm4xY2JseHVmU3g3WENJdUwzWmxjbk5wYjI1Y0lqb3pNSDFkTERJNE9sdG1kVzVqZEdsdmJpaHlaWEYxYVhKbExHMXZaSFZzWlN4bGVIQnZjblJ6S1h0Y2JuWmhjaUIyWlhKemFXOXVJRDBnY21WeGRXbHlaU2hjSWk0dmRtVnljMmx2Ymx3aUtWeHVYRzV0YjJSMWJHVXVaWGh3YjNKMGN5QTlJR2x6Vm1seWRIVmhiRlJsZUhSY2JseHVablZ1WTNScGIyNGdhWE5XYVhKMGRXRnNWR1Y0ZENoNEtTQjdYRzRnSUNBZ2NtVjBkWEp1SUhnZ0ppWWdlQzUwZVhCbElEMDlQU0JjSWxacGNuUjFZV3hVWlhoMFhDSWdKaVlnZUM1MlpYSnphVzl1SUQwOVBTQjJaWEp6YVc5dVhHNTlYRzVjYm4wc2Uxd2lMaTkyWlhKemFXOXVYQ0k2TXpCOVhTd3lPVHBiWm5WdVkzUnBiMjRvY21WeGRXbHlaU3h0YjJSMWJHVXNaWGh3YjNKMGN5bDdYRzV0YjJSMWJHVXVaWGh3YjNKMGN5QTlJR2x6VjJsa1oyVjBYRzVjYm1aMWJtTjBhVzl1SUdselYybGtaMlYwS0hjcElIdGNiaUFnSUNCeVpYUjFjbTRnZHlBbUppQjNMblI1Y0dVZ1BUMDlJRndpVjJsa1oyVjBYQ0pjYm4xY2JseHVmU3g3ZlYwc016QTZXMloxYm1OMGFXOXVLSEpsY1hWcGNtVXNiVzlrZFd4bExHVjRjRzl5ZEhNcGUxeHViVzlrZFd4bExtVjRjRzl5ZEhNZ1BTQmNJakpjSWx4dVhHNTlMSHQ5WFN3ek1UcGJablZ1WTNScGIyNG9jbVZ4ZFdseVpTeHRiMlIxYkdVc1pYaHdiM0owY3lsN1hHNTJZWElnZG1WeWMybHZiaUE5SUhKbGNYVnBjbVVvWENJdUwzWmxjbk5wYjI1Y0lpbGNiblpoY2lCcGMxWk9iMlJsSUQwZ2NtVnhkV2x5WlNoY0lpNHZhWE10ZG01dlpHVmNJaWxjYm5aaGNpQnBjMWRwWkdkbGRDQTlJSEpsY1hWcGNtVW9YQ0l1TDJsekxYZHBaR2RsZEZ3aUtWeHVkbUZ5SUdselZHaDFibXNnUFNCeVpYRjFhWEpsS0Z3aUxpOXBjeTEwYUhWdWExd2lLVnh1ZG1GeUlHbHpWa2h2YjJzZ1BTQnlaWEYxYVhKbEtGd2lMaTlwY3kxMmFHOXZhMXdpS1Z4dVhHNXRiMlIxYkdVdVpYaHdiM0owY3lBOUlGWnBjblIxWVd4T2IyUmxYRzVjYm5aaGNpQnViMUJ5YjNCbGNuUnBaWE1nUFNCN2ZWeHVkbUZ5SUc1dlEyaHBiR1J5Wlc0Z1BTQmJYVnh1WEc1bWRXNWpkR2x2YmlCV2FYSjBkV0ZzVG05a1pTaDBZV2RPWVcxbExDQndjbTl3WlhKMGFXVnpMQ0JqYUdsc1pISmxiaXdnYTJWNUxDQnVZVzFsYzNCaFkyVXBJSHRjYmlBZ0lDQjBhR2x6TG5SaFowNWhiV1VnUFNCMFlXZE9ZVzFsWEc0Z0lDQWdkR2hwY3k1d2NtOXdaWEowYVdWeklEMGdjSEp2Y0dWeWRHbGxjeUI4ZkNCdWIxQnliM0JsY25ScFpYTmNiaUFnSUNCMGFHbHpMbU5vYVd4a2NtVnVJRDBnWTJocGJHUnlaVzRnZkh3Z2JtOURhR2xzWkhKbGJseHVJQ0FnSUhSb2FYTXVhMlY1SUQwZ2EyVjVJQ0U5SUc1MWJHd2dQeUJUZEhKcGJtY29hMlY1S1NBNklIVnVaR1ZtYVc1bFpGeHVJQ0FnSUhSb2FYTXVibUZ0WlhOd1lXTmxJRDBnS0hSNWNHVnZaaUJ1WVcxbGMzQmhZMlVnUFQwOUlGd2ljM1J5YVc1blhDSXBJRDhnYm1GdFpYTndZV05sSURvZ2JuVnNiRnh1WEc0Z0lDQWdkbUZ5SUdOdmRXNTBJRDBnS0dOb2FXeGtjbVZ1SUNZbUlHTm9hV3hrY21WdUxteGxibWQwYUNrZ2ZId2dNRnh1SUNBZ0lIWmhjaUJrWlhOalpXNWtZVzUwY3lBOUlEQmNiaUFnSUNCMllYSWdhR0Z6VjJsa1oyVjBjeUE5SUdaaGJITmxYRzRnSUNBZ2RtRnlJR2hoYzFSb2RXNXJjeUE5SUdaaGJITmxYRzRnSUNBZ2RtRnlJR1JsYzJObGJtUmhiblJJYjI5cmN5QTlJR1poYkhObFhHNGdJQ0FnZG1GeUlHaHZiMnR6WEc1Y2JpQWdJQ0JtYjNJZ0tIWmhjaUJ3Y205d1RtRnRaU0JwYmlCd2NtOXdaWEowYVdWektTQjdYRzRnSUNBZ0lDQWdJR2xtSUNod2NtOXdaWEowYVdWekxtaGhjMDkzYmxCeWIzQmxjblI1S0hCeWIzQk9ZVzFsS1NrZ2UxeHVJQ0FnSUNBZ0lDQWdJQ0FnZG1GeUlIQnliM0JsY25SNUlEMGdjSEp2Y0dWeWRHbGxjMXR3Y205d1RtRnRaVjFjYmlBZ0lDQWdJQ0FnSUNBZ0lHbG1JQ2hwYzFaSWIyOXJLSEJ5YjNCbGNuUjVLU0FtSmlCd2NtOXdaWEowZVM1MWJtaHZiMnNwSUh0Y2JpQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNCcFppQW9JV2h2YjJ0ektTQjdYRzRnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUdodmIydHpJRDBnZTMxY2JpQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNCOVhHNWNiaUFnSUNBZ0lDQWdJQ0FnSUNBZ0lDQm9iMjlyYzF0d2NtOXdUbUZ0WlYwZ1BTQndjbTl3WlhKMGVWeHVJQ0FnSUNBZ0lDQWdJQ0FnZlZ4dUlDQWdJQ0FnSUNCOVhHNGdJQ0FnZlZ4dVhHNGdJQ0FnWm05eUlDaDJZWElnYVNBOUlEQTdJR2tnUENCamIzVnVkRHNnYVNzcktTQjdYRzRnSUNBZ0lDQWdJSFpoY2lCamFHbHNaQ0E5SUdOb2FXeGtjbVZ1VzJsZFhHNGdJQ0FnSUNBZ0lHbG1JQ2hwYzFaT2IyUmxLR05vYVd4a0tTa2dlMXh1SUNBZ0lDQWdJQ0FnSUNBZ1pHVnpZMlZ1WkdGdWRITWdLejBnWTJocGJHUXVZMjkxYm5RZ2ZId2dNRnh1WEc0Z0lDQWdJQ0FnSUNBZ0lDQnBaaUFvSVdoaGMxZHBaR2RsZEhNZ0ppWWdZMmhwYkdRdWFHRnpWMmxrWjJWMGN5a2dlMXh1SUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJR2hoYzFkcFpHZGxkSE1nUFNCMGNuVmxYRzRnSUNBZ0lDQWdJQ0FnSUNCOVhHNWNiaUFnSUNBZ0lDQWdJQ0FnSUdsbUlDZ2hhR0Z6VkdoMWJtdHpJQ1ltSUdOb2FXeGtMbWhoYzFSb2RXNXJjeWtnZTF4dUlDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUdoaGMxUm9kVzVyY3lBOUlIUnlkV1ZjYmlBZ0lDQWdJQ0FnSUNBZ0lIMWNibHh1SUNBZ0lDQWdJQ0FnSUNBZ2FXWWdLQ0ZrWlhOalpXNWtZVzUwU0c5dmEzTWdKaVlnS0dOb2FXeGtMbWh2YjJ0eklIeDhJR05vYVd4a0xtUmxjMk5sYm1SaGJuUkliMjlyY3lrcElIdGNiaUFnSUNBZ0lDQWdJQ0FnSUNBZ0lDQmtaWE5qWlc1a1lXNTBTRzl2YTNNZ1BTQjBjblZsWEc0Z0lDQWdJQ0FnSUNBZ0lDQjlYRzRnSUNBZ0lDQWdJSDBnWld4elpTQnBaaUFvSVdoaGMxZHBaR2RsZEhNZ0ppWWdhWE5YYVdSblpYUW9ZMmhwYkdRcEtTQjdYRzRnSUNBZ0lDQWdJQ0FnSUNCcFppQW9kSGx3Wlc5bUlHTm9hV3hrTG1SbGMzUnliM2tnUFQwOUlGd2lablZ1WTNScGIyNWNJaWtnZTF4dUlDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUdoaGMxZHBaR2RsZEhNZ1BTQjBjblZsWEc0Z0lDQWdJQ0FnSUNBZ0lDQjlYRzRnSUNBZ0lDQWdJSDBnWld4elpTQnBaaUFvSVdoaGMxUm9kVzVyY3lBbUppQnBjMVJvZFc1cktHTm9hV3hrS1NrZ2UxeHVJQ0FnSUNBZ0lDQWdJQ0FnYUdGelZHaDFibXR6SUQwZ2RISjFaVHRjYmlBZ0lDQWdJQ0FnZlZ4dUlDQWdJSDFjYmx4dUlDQWdJSFJvYVhNdVkyOTFiblFnUFNCamIzVnVkQ0FySUdSbGMyTmxibVJoYm5SelhHNGdJQ0FnZEdocGN5NW9ZWE5YYVdSblpYUnpJRDBnYUdGelYybGtaMlYwYzF4dUlDQWdJSFJvYVhNdWFHRnpWR2gxYm10eklEMGdhR0Z6VkdoMWJtdHpYRzRnSUNBZ2RHaHBjeTVvYjI5cmN5QTlJR2h2YjJ0elhHNGdJQ0FnZEdocGN5NWtaWE5qWlc1a1lXNTBTRzl2YTNNZ1BTQmtaWE5qWlc1a1lXNTBTRzl2YTNOY2JuMWNibHh1Vm1seWRIVmhiRTV2WkdVdWNISnZkRzkwZVhCbExuWmxjbk5wYjI0Z1BTQjJaWEp6YVc5dVhHNVdhWEowZFdGc1RtOWtaUzV3Y205MGIzUjVjR1V1ZEhsd1pTQTlJRndpVm1seWRIVmhiRTV2WkdWY0lseHVYRzU5TEh0Y0lpNHZhWE10ZEdoMWJtdGNJam95TlN4Y0lpNHZhWE10ZG1odmIydGNJam95Tml4Y0lpNHZhWE10ZG01dlpHVmNJam95Tnl4Y0lpNHZhWE10ZDJsa1oyVjBYQ0k2TWprc1hDSXVMM1psY25OcGIyNWNJam96TUgxZExETXlPbHRtZFc1amRHbHZiaWh5WlhGMWFYSmxMRzF2WkhWc1pTeGxlSEJ2Y25SektYdGNiblpoY2lCMlpYSnphVzl1SUQwZ2NtVnhkV2x5WlNoY0lpNHZkbVZ5YzJsdmJsd2lLVnh1WEc1V2FYSjBkV0ZzVUdGMFkyZ3VUazlPUlNBOUlEQmNibFpwY25SMVlXeFFZWFJqYUM1V1ZFVllWQ0E5SURGY2JsWnBjblIxWVd4UVlYUmphQzVXVGs5RVJTQTlJREpjYmxacGNuUjFZV3hRWVhSamFDNVhTVVJIUlZRZ1BTQXpYRzVXYVhKMGRXRnNVR0YwWTJndVVGSlBVRk1nUFNBMFhHNVdhWEowZFdGc1VHRjBZMmd1VDFKRVJWSWdQU0ExWEc1V2FYSjBkV0ZzVUdGMFkyZ3VTVTVUUlZKVUlEMGdObHh1Vm1seWRIVmhiRkJoZEdOb0xsSkZUVTlXUlNBOUlEZGNibFpwY25SMVlXeFFZWFJqYUM1VVNGVk9TeUE5SURoY2JseHViVzlrZFd4bExtVjRjRzl5ZEhNZ1BTQldhWEowZFdGc1VHRjBZMmhjYmx4dVpuVnVZM1JwYjI0Z1ZtbHlkSFZoYkZCaGRHTm9LSFI1Y0dVc0lIWk9iMlJsTENCd1lYUmphQ2tnZTF4dUlDQWdJSFJvYVhNdWRIbHdaU0E5SUU1MWJXSmxjaWgwZVhCbEtWeHVJQ0FnSUhSb2FYTXVkazV2WkdVZ1BTQjJUbTlrWlZ4dUlDQWdJSFJvYVhNdWNHRjBZMmdnUFNCd1lYUmphRnh1ZlZ4dVhHNVdhWEowZFdGc1VHRjBZMmd1Y0hKdmRHOTBlWEJsTG5abGNuTnBiMjRnUFNCMlpYSnphVzl1WEc1V2FYSjBkV0ZzVUdGMFkyZ3VjSEp2ZEc5MGVYQmxMblI1Y0dVZ1BTQmNJbFpwY25SMVlXeFFZWFJqYUZ3aVhHNWNibjBzZTF3aUxpOTJaWEp6YVc5dVhDSTZNekI5WFN3ek16cGJablZ1WTNScGIyNG9jbVZ4ZFdseVpTeHRiMlIxYkdVc1pYaHdiM0owY3lsN1hHNTJZWElnZG1WeWMybHZiaUE5SUhKbGNYVnBjbVVvWENJdUwzWmxjbk5wYjI1Y0lpbGNibHh1Ylc5a2RXeGxMbVY0Y0c5eWRITWdQU0JXYVhKMGRXRnNWR1Y0ZEZ4dVhHNW1kVzVqZEdsdmJpQldhWEowZFdGc1ZHVjRkQ2gwWlhoMEtTQjdYRzRnSUNBZ2RHaHBjeTUwWlhoMElEMGdVM1J5YVc1bktIUmxlSFFwWEc1OVhHNWNibFpwY25SMVlXeFVaWGgwTG5CeWIzUnZkSGx3WlM1MlpYSnphVzl1SUQwZ2RtVnljMmx2Ymx4dVZtbHlkSFZoYkZSbGVIUXVjSEp2ZEc5MGVYQmxMblI1Y0dVZ1BTQmNJbFpwY25SMVlXeFVaWGgwWENKY2JseHVmU3g3WENJdUwzWmxjbk5wYjI1Y0lqb3pNSDFkTERNME9sdG1kVzVqZEdsdmJpaHlaWEYxYVhKbExHMXZaSFZzWlN4bGVIQnZjblJ6S1h0Y2JuWmhjaUJwYzA5aWFtVmpkQ0E5SUhKbGNYVnBjbVVvWENKcGN5MXZZbXBsWTNSY0lpbGNiblpoY2lCcGMwaHZiMnNnUFNCeVpYRjFhWEpsS0Z3aUxpNHZkbTV2WkdVdmFYTXRkbWh2YjJ0Y0lpbGNibHh1Ylc5a2RXeGxMbVY0Y0c5eWRITWdQU0JrYVdabVVISnZjSE5jYmx4dVpuVnVZM1JwYjI0Z1pHbG1abEJ5YjNCektHRXNJR0lwSUh0Y2JpQWdJQ0IyWVhJZ1pHbG1abHh1WEc0Z0lDQWdabTl5SUNoMllYSWdZVXRsZVNCcGJpQmhLU0I3WEc0Z0lDQWdJQ0FnSUdsbUlDZ2hLR0ZMWlhrZ2FXNGdZaWtwSUh0Y2JpQWdJQ0FnSUNBZ0lDQWdJR1JwWm1ZZ1BTQmthV1ptSUh4OElIdDlYRzRnSUNBZ0lDQWdJQ0FnSUNCa2FXWm1XMkZMWlhsZElEMGdkVzVrWldacGJtVmtYRzRnSUNBZ0lDQWdJSDFjYmx4dUlDQWdJQ0FnSUNCMllYSWdZVlpoYkhWbElEMGdZVnRoUzJWNVhWeHVJQ0FnSUNBZ0lDQjJZWElnWWxaaGJIVmxJRDBnWWx0aFMyVjVYVnh1WEc0Z0lDQWdJQ0FnSUdsbUlDaGhWbUZzZFdVZ1BUMDlJR0pXWVd4MVpTa2dlMXh1SUNBZ0lDQWdJQ0FnSUNBZ1kyOXVkR2x1ZFdWY2JpQWdJQ0FnSUNBZ2ZTQmxiSE5sSUdsbUlDaHBjMDlpYW1WamRDaGhWbUZzZFdVcElDWW1JR2x6VDJKcVpXTjBLR0pXWVd4MVpTa3BJSHRjYmlBZ0lDQWdJQ0FnSUNBZ0lHbG1JQ2huWlhSUWNtOTBiM1I1Y0dVb1lsWmhiSFZsS1NBaFBUMGdaMlYwVUhKdmRHOTBlWEJsS0dGV1lXeDFaU2twSUh0Y2JpQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNCa2FXWm1JRDBnWkdsbVppQjhmQ0I3ZlZ4dUlDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUdScFptWmJZVXRsZVYwZ1BTQmlWbUZzZFdWY2JpQWdJQ0FnSUNBZ0lDQWdJSDBnWld4elpTQnBaaUFvYVhOSWIyOXJLR0pXWVd4MVpTa3BJSHRjYmlBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnWkdsbVppQTlJR1JwWm1ZZ2ZId2dlMzFjYmlBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnWkdsbVpsdGhTMlY1WFNBOUlHSldZV3gxWlZ4dUlDQWdJQ0FnSUNBZ0lDQWdmU0JsYkhObElIdGNiaUFnSUNBZ0lDQWdJQ0FnSUNBZ0lDQjJZWElnYjJKcVpXTjBSR2xtWmlBOUlHUnBabVpRY205d2N5aGhWbUZzZFdVc0lHSldZV3gxWlNsY2JpQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNCcFppQW9iMkpxWldOMFJHbG1aaWtnZTF4dUlDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQmthV1ptSUQwZ1pHbG1aaUI4ZkNCN2ZWeHVJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0JrYVdabVcyRkxaWGxkSUQwZ2IySnFaV04wUkdsbVpseHVJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lIMWNiaUFnSUNBZ0lDQWdJQ0FnSUgxY2JpQWdJQ0FnSUNBZ2ZTQmxiSE5sSUh0Y2JpQWdJQ0FnSUNBZ0lDQWdJR1JwWm1ZZ1BTQmthV1ptSUh4OElIdDlYRzRnSUNBZ0lDQWdJQ0FnSUNCa2FXWm1XMkZMWlhsZElEMGdZbFpoYkhWbFhHNGdJQ0FnSUNBZ0lIMWNiaUFnSUNCOVhHNWNiaUFnSUNCbWIzSWdLSFpoY2lCaVMyVjVJR2x1SUdJcElIdGNiaUFnSUNBZ0lDQWdhV1lnS0NFb1lrdGxlU0JwYmlCaEtTa2dlMXh1SUNBZ0lDQWdJQ0FnSUNBZ1pHbG1aaUE5SUdScFptWWdmSHdnZTMxY2JpQWdJQ0FnSUNBZ0lDQWdJR1JwWm1aYllrdGxlVjBnUFNCaVcySkxaWGxkWEc0Z0lDQWdJQ0FnSUgxY2JpQWdJQ0I5WEc1Y2JpQWdJQ0J5WlhSMWNtNGdaR2xtWmx4dWZWeHVYRzVtZFc1amRHbHZiaUJuWlhSUWNtOTBiM1I1Y0dVb2RtRnNkV1VwSUh0Y2JpQWdhV1lnS0U5aWFtVmpkQzVuWlhSUWNtOTBiM1I1Y0dWUFppa2dlMXh1SUNBZ0lISmxkSFZ5YmlCUFltcGxZM1F1WjJWMFVISnZkRzkwZVhCbFQyWW9kbUZzZFdVcFhHNGdJSDBnWld4elpTQnBaaUFvZG1Gc2RXVXVYMTl3Y205MGIxOWZLU0I3WEc0Z0lDQWdjbVYwZFhKdUlIWmhiSFZsTGw5ZmNISnZkRzlmWDF4dUlDQjlJR1ZzYzJVZ2FXWWdLSFpoYkhWbExtTnZibk4wY25WamRHOXlLU0I3WEc0Z0lDQWdjbVYwZFhKdUlIWmhiSFZsTG1OdmJuTjBjblZqZEc5eUxuQnliM1J2ZEhsd1pWeHVJQ0I5WEc1OVhHNWNibjBzZTF3aUxpNHZkbTV2WkdVdmFYTXRkbWh2YjJ0Y0lqb3lOaXhjSW1sekxXOWlhbVZqZEZ3aU9qRXhmVjBzTXpVNlcyWjFibU4wYVc5dUtISmxjWFZwY21Vc2JXOWtkV3hsTEdWNGNHOXlkSE1wZTF4dWRtRnlJR2x6UVhKeVlYa2dQU0J5WlhGMWFYSmxLRndpZUMxcGN5MWhjbkpoZVZ3aUtWeHVYRzUyWVhJZ1ZsQmhkR05vSUQwZ2NtVnhkV2x5WlNoY0lpNHVMM1p1YjJSbEwzWndZWFJqYUZ3aUtWeHVkbUZ5SUdselZrNXZaR1VnUFNCeVpYRjFhWEpsS0Z3aUxpNHZkbTV2WkdVdmFYTXRkbTV2WkdWY0lpbGNiblpoY2lCcGMxWlVaWGgwSUQwZ2NtVnhkV2x5WlNoY0lpNHVMM1p1YjJSbEwybHpMWFowWlhoMFhDSXBYRzUyWVhJZ2FYTlhhV1JuWlhRZ1BTQnlaWEYxYVhKbEtGd2lMaTR2ZG01dlpHVXZhWE10ZDJsa1oyVjBYQ0lwWEc1MllYSWdhWE5VYUhWdWF5QTlJSEpsY1hWcGNtVW9YQ0l1TGk5MmJtOWtaUzlwY3kxMGFIVnVhMXdpS1Z4dWRtRnlJR2hoYm1Sc1pWUm9kVzVySUQwZ2NtVnhkV2x5WlNoY0lpNHVMM1p1YjJSbEwyaGhibVJzWlMxMGFIVnVhMXdpS1Z4dVhHNTJZWElnWkdsbVpsQnliM0J6SUQwZ2NtVnhkV2x5WlNoY0lpNHZaR2xtWmkxd2NtOXdjMXdpS1Z4dVhHNXRiMlIxYkdVdVpYaHdiM0owY3lBOUlHUnBabVpjYmx4dVpuVnVZM1JwYjI0Z1pHbG1aaWhoTENCaUtTQjdYRzRnSUNBZ2RtRnlJSEJoZEdOb0lEMGdleUJoT2lCaElIMWNiaUFnSUNCM1lXeHJLR0VzSUdJc0lIQmhkR05vTENBd0tWeHVJQ0FnSUhKbGRIVnliaUJ3WVhSamFGeHVmVnh1WEc1bWRXNWpkR2x2YmlCM1lXeHJLR0VzSUdJc0lIQmhkR05vTENCcGJtUmxlQ2tnZTF4dUlDQWdJR2xtSUNoaElEMDlQU0JpS1NCN1hHNGdJQ0FnSUNBZ0lISmxkSFZ5Ymx4dUlDQWdJSDFjYmx4dUlDQWdJSFpoY2lCaGNIQnNlU0E5SUhCaGRHTm9XMmx1WkdWNFhWeHVJQ0FnSUhaaGNpQmhjSEJzZVVOc1pXRnlJRDBnWm1Gc2MyVmNibHh1SUNBZ0lHbG1JQ2hwYzFSb2RXNXJLR0VwSUh4OElHbHpWR2gxYm1zb1lpa3BJSHRjYmlBZ0lDQWdJQ0FnZEdoMWJtdHpLR0VzSUdJc0lIQmhkR05vTENCcGJtUmxlQ2xjYmlBZ0lDQjlJR1ZzYzJVZ2FXWWdLR0lnUFQwZ2JuVnNiQ2tnZTF4dVhHNGdJQ0FnSUNBZ0lDOHZJRWxtSUdFZ2FYTWdZU0IzYVdSblpYUWdkMlVnZDJsc2JDQmhaR1FnWVNCeVpXMXZkbVVnY0dGMFkyZ2dabTl5SUdsMFhHNGdJQ0FnSUNBZ0lDOHZJRTkwYUdWeWQybHpaU0JoYm5rZ1kyaHBiR1FnZDJsa1oyVjBjeTlvYjI5cmN5QnRkWE4wSUdKbElHUmxjM1J5YjNsbFpDNWNiaUFnSUNBZ0lDQWdMeThnVkdocGN5QndjbVYyWlc1MGN5QmhaR1JwYm1jZ2RIZHZJSEpsYlc5MlpTQndZWFJqYUdWeklHWnZjaUJoSUhkcFpHZGxkQzVjYmlBZ0lDQWdJQ0FnYVdZZ0tDRnBjMWRwWkdkbGRDaGhLU2tnZTF4dUlDQWdJQ0FnSUNBZ0lDQWdZMnhsWVhKVGRHRjBaU2hoTENCd1lYUmphQ3dnYVc1a1pYZ3BYRzRnSUNBZ0lDQWdJQ0FnSUNCaGNIQnNlU0E5SUhCaGRHTm9XMmx1WkdWNFhWeHVJQ0FnSUNBZ0lDQjlYRzVjYmlBZ0lDQWdJQ0FnWVhCd2JIa2dQU0JoY0hCbGJtUlFZWFJqYUNoaGNIQnNlU3dnYm1WM0lGWlFZWFJqYUNoV1VHRjBZMmd1VWtWTlQxWkZMQ0JoTENCaUtTbGNiaUFnSUNCOUlHVnNjMlVnYVdZZ0tHbHpWazV2WkdVb1lpa3BJSHRjYmlBZ0lDQWdJQ0FnYVdZZ0tHbHpWazV2WkdVb1lTa3BJSHRjYmlBZ0lDQWdJQ0FnSUNBZ0lHbG1JQ2hoTG5SaFowNWhiV1VnUFQwOUlHSXVkR0ZuVG1GdFpTQW1KbHh1SUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJR0V1Ym1GdFpYTndZV05sSUQwOVBTQmlMbTVoYldWemNHRmpaU0FtSmx4dUlDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUdFdWEyVjVJRDA5UFNCaUxtdGxlU2tnZTF4dUlDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUhaaGNpQndjbTl3YzFCaGRHTm9JRDBnWkdsbVpsQnliM0J6S0dFdWNISnZjR1Z5ZEdsbGN5d2dZaTV3Y205d1pYSjBhV1Z6S1Z4dUlDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUdsbUlDaHdjbTl3YzFCaGRHTm9LU0I3WEc0Z0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lHRndjR3g1SUQwZ1lYQndaVzVrVUdGMFkyZ29ZWEJ3Ykhrc1hHNGdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNCdVpYY2dWbEJoZEdOb0tGWlFZWFJqYUM1UVVrOVFVeXdnWVN3Z2NISnZjSE5RWVhSamFDa3BYRzRnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdmVnh1SUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJR0Z3Y0d4NUlEMGdaR2xtWmtOb2FXeGtjbVZ1S0dFc0lHSXNJSEJoZEdOb0xDQmhjSEJzZVN3Z2FXNWtaWGdwWEc0Z0lDQWdJQ0FnSUNBZ0lDQjlJR1ZzYzJVZ2UxeHVJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lHRndjR3g1SUQwZ1lYQndaVzVrVUdGMFkyZ29ZWEJ3Ykhrc0lHNWxkeUJXVUdGMFkyZ29WbEJoZEdOb0xsWk9UMFJGTENCaExDQmlLU2xjYmlBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0JoY0hCc2VVTnNaV0Z5SUQwZ2RISjFaVnh1SUNBZ0lDQWdJQ0FnSUNBZ2ZWeHVJQ0FnSUNBZ0lDQjlJR1ZzYzJVZ2UxeHVJQ0FnSUNBZ0lDQWdJQ0FnWVhCd2JIa2dQU0JoY0hCbGJtUlFZWFJqYUNoaGNIQnNlU3dnYm1WM0lGWlFZWFJqYUNoV1VHRjBZMmd1Vms1UFJFVXNJR0VzSUdJcEtWeHVJQ0FnSUNBZ0lDQWdJQ0FnWVhCd2JIbERiR1ZoY2lBOUlIUnlkV1ZjYmlBZ0lDQWdJQ0FnZlZ4dUlDQWdJSDBnWld4elpTQnBaaUFvYVhOV1ZHVjRkQ2hpS1NrZ2UxeHVJQ0FnSUNBZ0lDQnBaaUFvSVdselZsUmxlSFFvWVNrcElIdGNiaUFnSUNBZ0lDQWdJQ0FnSUdGd2NHeDVJRDBnWVhCd1pXNWtVR0YwWTJnb1lYQndiSGtzSUc1bGR5QldVR0YwWTJnb1ZsQmhkR05vTGxaVVJWaFVMQ0JoTENCaUtTbGNiaUFnSUNBZ0lDQWdJQ0FnSUdGd2NHeDVRMnhsWVhJZ1BTQjBjblZsWEc0Z0lDQWdJQ0FnSUgwZ1pXeHpaU0JwWmlBb1lTNTBaWGgwSUNFOVBTQmlMblJsZUhRcElIdGNiaUFnSUNBZ0lDQWdJQ0FnSUdGd2NHeDVJRDBnWVhCd1pXNWtVR0YwWTJnb1lYQndiSGtzSUc1bGR5QldVR0YwWTJnb1ZsQmhkR05vTGxaVVJWaFVMQ0JoTENCaUtTbGNiaUFnSUNBZ0lDQWdmVnh1SUNBZ0lIMGdaV3h6WlNCcFppQW9hWE5YYVdSblpYUW9ZaWtwSUh0Y2JpQWdJQ0FnSUNBZ2FXWWdLQ0ZwYzFkcFpHZGxkQ2hoS1NrZ2UxeHVJQ0FnSUNBZ0lDQWdJQ0FnWVhCd2JIbERiR1ZoY2lBOUlIUnlkV1ZjYmlBZ0lDQWdJQ0FnZlZ4dVhHNGdJQ0FnSUNBZ0lHRndjR3g1SUQwZ1lYQndaVzVrVUdGMFkyZ29ZWEJ3Ykhrc0lHNWxkeUJXVUdGMFkyZ29WbEJoZEdOb0xsZEpSRWRGVkN3Z1lTd2dZaWtwWEc0Z0lDQWdmVnh1WEc0Z0lDQWdhV1lnS0dGd2NHeDVLU0I3WEc0Z0lDQWdJQ0FnSUhCaGRHTm9XMmx1WkdWNFhTQTlJR0Z3Y0d4NVhHNGdJQ0FnZlZ4dVhHNGdJQ0FnYVdZZ0tHRndjR3g1UTJ4bFlYSXBJSHRjYmlBZ0lDQWdJQ0FnWTJ4bFlYSlRkR0YwWlNoaExDQndZWFJqYUN3Z2FXNWtaWGdwWEc0Z0lDQWdmVnh1ZlZ4dVhHNW1kVzVqZEdsdmJpQmthV1ptUTJocGJHUnlaVzRvWVN3Z1lpd2djR0YwWTJnc0lHRndjR3g1TENCcGJtUmxlQ2tnZTF4dUlDQWdJSFpoY2lCaFEyaHBiR1J5Wlc0Z1BTQmhMbU5vYVd4a2NtVnVYRzRnSUNBZ2RtRnlJRzl5WkdWeVpXUlRaWFFnUFNCeVpXOXlaR1Z5S0dGRGFHbHNaSEpsYml3Z1lpNWphR2xzWkhKbGJpbGNiaUFnSUNCMllYSWdZa05vYVd4a2NtVnVJRDBnYjNKa1pYSmxaRk5sZEM1amFHbHNaSEpsYmx4dVhHNGdJQ0FnZG1GeUlHRk1aVzRnUFNCaFEyaHBiR1J5Wlc0dWJHVnVaM1JvWEc0Z0lDQWdkbUZ5SUdKTVpXNGdQU0JpUTJocGJHUnlaVzR1YkdWdVozUm9YRzRnSUNBZ2RtRnlJR3hsYmlBOUlHRk1aVzRnUGlCaVRHVnVJRDhnWVV4bGJpQTZJR0pNWlc1Y2JseHVJQ0FnSUdadmNpQW9kbUZ5SUdrZ1BTQXdPeUJwSUR3Z2JHVnVPeUJwS3lzcElIdGNiaUFnSUNBZ0lDQWdkbUZ5SUd4bFpuUk9iMlJsSUQwZ1lVTm9hV3hrY21WdVcybGRYRzRnSUNBZ0lDQWdJSFpoY2lCeWFXZG9kRTV2WkdVZ1BTQmlRMmhwYkdSeVpXNWJhVjFjYmlBZ0lDQWdJQ0FnYVc1a1pYZ2dLejBnTVZ4dVhHNGdJQ0FnSUNBZ0lHbG1JQ2doYkdWbWRFNXZaR1VwSUh0Y2JpQWdJQ0FnSUNBZ0lDQWdJR2xtSUNoeWFXZG9kRTV2WkdVcElIdGNiaUFnSUNBZ0lDQWdJQ0FnSUNBZ0lDQXZMeUJGZUdObGMzTWdibTlrWlhNZ2FXNGdZaUJ1WldWa0lIUnZJR0psSUdGa1pHVmtYRzRnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdZWEJ3YkhrZ1BTQmhjSEJsYm1SUVlYUmphQ2hoY0hCc2VTeGNiaUFnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnYm1WM0lGWlFZWFJqYUNoV1VHRjBZMmd1U1U1VFJWSlVMQ0J1ZFd4c0xDQnlhV2RvZEU1dlpHVXBLVnh1SUNBZ0lDQWdJQ0FnSUNBZ2ZWeHVJQ0FnSUNBZ0lDQjlJR1ZzYzJVZ2UxeHVJQ0FnSUNBZ0lDQWdJQ0FnZDJGc2F5aHNaV1owVG05a1pTd2djbWxuYUhST2IyUmxMQ0J3WVhSamFDd2dhVzVrWlhncFhHNGdJQ0FnSUNBZ0lIMWNibHh1SUNBZ0lDQWdJQ0JwWmlBb2FYTldUbTlrWlNoc1pXWjBUbTlrWlNrZ0ppWWdiR1ZtZEU1dlpHVXVZMjkxYm5RcElIdGNiaUFnSUNBZ0lDQWdJQ0FnSUdsdVpHVjRJQ3M5SUd4bFpuUk9iMlJsTG1OdmRXNTBYRzRnSUNBZ0lDQWdJSDFjYmlBZ0lDQjlYRzVjYmlBZ0lDQnBaaUFvYjNKa1pYSmxaRk5sZEM1dGIzWmxjeWtnZTF4dUlDQWdJQ0FnSUNBdkx5QlNaVzl5WkdWeUlHNXZaR1Z6SUd4aGMzUmNiaUFnSUNBZ0lDQWdZWEJ3YkhrZ1BTQmhjSEJsYm1SUVlYUmphQ2hoY0hCc2VTd2dibVYzSUZaUVlYUmphQ2hjYmlBZ0lDQWdJQ0FnSUNBZ0lGWlFZWFJqYUM1UFVrUkZVaXhjYmlBZ0lDQWdJQ0FnSUNBZ0lHRXNYRzRnSUNBZ0lDQWdJQ0FnSUNCdmNtUmxjbVZrVTJWMExtMXZkbVZ6WEc0Z0lDQWdJQ0FnSUNrcFhHNGdJQ0FnZlZ4dVhHNGdJQ0FnY21WMGRYSnVJR0Z3Y0d4NVhHNTlYRzVjYm1aMWJtTjBhVzl1SUdOc1pXRnlVM1JoZEdVb2RrNXZaR1VzSUhCaGRHTm9MQ0JwYm1SbGVDa2dlMXh1SUNBZ0lDOHZJRlJQUkU4NklFMWhhMlVnZEdocGN5QmhJSE5wYm1kc1pTQjNZV3hyTENCdWIzUWdkSGR2WEc0Z0lDQWdkVzVvYjI5cktIWk9iMlJsTENCd1lYUmphQ3dnYVc1a1pYZ3BYRzRnSUNBZ1pHVnpkSEp2ZVZkcFpHZGxkSE1vZGs1dlpHVXNJSEJoZEdOb0xDQnBibVJsZUNsY2JuMWNibHh1THk4Z1VHRjBZMmdnY21WamIzSmtjeUJtYjNJZ1lXeHNJR1JsYzNSeWIzbGxaQ0IzYVdSblpYUnpJRzExYzNRZ1ltVWdZV1JrWldRZ1ltVmpZWFZ6WlNCM1pTQnVaV1ZrWEc0dkx5QmhJRVJQVFNCdWIyUmxJSEpsWm1WeVpXNWpaU0JtYjNJZ2RHaGxJR1JsYzNSeWIza2dablZ1WTNScGIyNWNibVoxYm1OMGFXOXVJR1JsYzNSeWIzbFhhV1JuWlhSektIWk9iMlJsTENCd1lYUmphQ3dnYVc1a1pYZ3BJSHRjYmlBZ0lDQnBaaUFvYVhOWGFXUm5aWFFvZGs1dlpHVXBLU0I3WEc0Z0lDQWdJQ0FnSUdsbUlDaDBlWEJsYjJZZ2RrNXZaR1V1WkdWemRISnZlU0E5UFQwZ1hDSm1kVzVqZEdsdmJsd2lLU0I3WEc0Z0lDQWdJQ0FnSUNBZ0lDQndZWFJqYUZ0cGJtUmxlRjBnUFNCaGNIQmxibVJRWVhSamFDaGNiaUFnSUNBZ0lDQWdJQ0FnSUNBZ0lDQndZWFJqYUZ0cGJtUmxlRjBzWEc0Z0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnYm1WM0lGWlFZWFJqYUNoV1VHRjBZMmd1VWtWTlQxWkZMQ0IyVG05a1pTd2diblZzYkNsY2JpQWdJQ0FnSUNBZ0lDQWdJQ2xjYmlBZ0lDQWdJQ0FnZlZ4dUlDQWdJSDBnWld4elpTQnBaaUFvYVhOV1RtOWtaU2gyVG05a1pTa2dKaVlnS0haT2IyUmxMbWhoYzFkcFpHZGxkSE1nZkh3Z2RrNXZaR1V1YUdGelZHaDFibXR6S1NrZ2UxeHVJQ0FnSUNBZ0lDQjJZWElnWTJocGJHUnlaVzRnUFNCMlRtOWtaUzVqYUdsc1pISmxibHh1SUNBZ0lDQWdJQ0IyWVhJZ2JHVnVJRDBnWTJocGJHUnlaVzR1YkdWdVozUm9YRzRnSUNBZ0lDQWdJR1p2Y2lBb2RtRnlJR2tnUFNBd095QnBJRHdnYkdWdU95QnBLeXNwSUh0Y2JpQWdJQ0FnSUNBZ0lDQWdJSFpoY2lCamFHbHNaQ0E5SUdOb2FXeGtjbVZ1VzJsZFhHNGdJQ0FnSUNBZ0lDQWdJQ0JwYm1SbGVDQXJQU0F4WEc1Y2JpQWdJQ0FnSUNBZ0lDQWdJR1JsYzNSeWIzbFhhV1JuWlhSektHTm9hV3hrTENCd1lYUmphQ3dnYVc1a1pYZ3BYRzVjYmlBZ0lDQWdJQ0FnSUNBZ0lHbG1JQ2hwYzFaT2IyUmxLR05vYVd4a0tTQW1KaUJqYUdsc1pDNWpiM1Z1ZENrZ2UxeHVJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lHbHVaR1Y0SUNzOUlHTm9hV3hrTG1OdmRXNTBYRzRnSUNBZ0lDQWdJQ0FnSUNCOVhHNGdJQ0FnSUNBZ0lIMWNiaUFnSUNCOUlHVnNjMlVnYVdZZ0tHbHpWR2gxYm1zb2RrNXZaR1VwS1NCN1hHNGdJQ0FnSUNBZ0lIUm9kVzVyY3loMlRtOWtaU3dnYm5Wc2JDd2djR0YwWTJnc0lHbHVaR1Y0S1Z4dUlDQWdJSDFjYm4xY2JseHVMeThnUTNKbFlYUmxJR0VnYzNWaUxYQmhkR05vSUdadmNpQjBhSFZ1YTNOY2JtWjFibU4wYVc5dUlIUm9kVzVyY3loaExDQmlMQ0J3WVhSamFDd2dhVzVrWlhncElIdGNiaUFnSUNCMllYSWdibTlrWlhNZ1BTQm9ZVzVrYkdWVWFIVnVheWhoTENCaUtWeHVJQ0FnSUhaaGNpQjBhSFZ1YTFCaGRHTm9JRDBnWkdsbVppaHViMlJsY3k1aExDQnViMlJsY3k1aUtWeHVJQ0FnSUdsbUlDaG9ZWE5RWVhSamFHVnpLSFJvZFc1clVHRjBZMmdwS1NCN1hHNGdJQ0FnSUNBZ0lIQmhkR05vVzJsdVpHVjRYU0E5SUc1bGR5QldVR0YwWTJnb1ZsQmhkR05vTGxSSVZVNUxMQ0J1ZFd4c0xDQjBhSFZ1YTFCaGRHTm9LVnh1SUNBZ0lIMWNibjFjYmx4dVpuVnVZM1JwYjI0Z2FHRnpVR0YwWTJobGN5aHdZWFJqYUNrZ2UxeHVJQ0FnSUdadmNpQW9kbUZ5SUdsdVpHVjRJR2x1SUhCaGRHTm9LU0I3WEc0Z0lDQWdJQ0FnSUdsbUlDaHBibVJsZUNBaFBUMGdYQ0poWENJcElIdGNiaUFnSUNBZ0lDQWdJQ0FnSUhKbGRIVnliaUIwY25WbFhHNGdJQ0FnSUNBZ0lIMWNiaUFnSUNCOVhHNWNiaUFnSUNCeVpYUjFjbTRnWm1Gc2MyVmNibjFjYmx4dUx5OGdSWGhsWTNWMFpTQm9iMjlyY3lCM2FHVnVJSFIzYnlCdWIyUmxjeUJoY21VZ2FXUmxiblJwWTJGc1hHNW1kVzVqZEdsdmJpQjFibWh2YjJzb2RrNXZaR1VzSUhCaGRHTm9MQ0JwYm1SbGVDa2dlMXh1SUNBZ0lHbG1JQ2hwYzFaT2IyUmxLSFpPYjJSbEtTa2dlMXh1SUNBZ0lDQWdJQ0JwWmlBb2RrNXZaR1V1YUc5dmEzTXBJSHRjYmlBZ0lDQWdJQ0FnSUNBZ0lIQmhkR05vVzJsdVpHVjRYU0E5SUdGd2NHVnVaRkJoZEdOb0tGeHVJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lIQmhkR05vVzJsdVpHVjRYU3hjYmlBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0J1WlhjZ1ZsQmhkR05vS0Z4dUlDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQldVR0YwWTJndVVGSlBVRk1zWEc0Z0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lIWk9iMlJsTEZ4dUlDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQjFibVJsWm1sdVpXUkxaWGx6S0haT2IyUmxMbWh2YjJ0ektWeHVJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDbGNiaUFnSUNBZ0lDQWdJQ0FnSUNsY2JpQWdJQ0FnSUNBZ2ZWeHVYRzRnSUNBZ0lDQWdJR2xtSUNoMlRtOWtaUzVrWlhOalpXNWtZVzUwU0c5dmEzTWdmSHdnZGs1dlpHVXVhR0Z6VkdoMWJtdHpLU0I3WEc0Z0lDQWdJQ0FnSUNBZ0lDQjJZWElnWTJocGJHUnlaVzRnUFNCMlRtOWtaUzVqYUdsc1pISmxibHh1SUNBZ0lDQWdJQ0FnSUNBZ2RtRnlJR3hsYmlBOUlHTm9hV3hrY21WdUxteGxibWQwYUZ4dUlDQWdJQ0FnSUNBZ0lDQWdabTl5SUNoMllYSWdhU0E5SURBN0lHa2dQQ0JzWlc0N0lHa3JLeWtnZTF4dUlDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUhaaGNpQmphR2xzWkNBOUlHTm9hV3hrY21WdVcybGRYRzRnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdhVzVrWlhnZ0t6MGdNVnh1WEc0Z0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnZFc1b2IyOXJLR05vYVd4a0xDQndZWFJqYUN3Z2FXNWtaWGdwWEc1Y2JpQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNCcFppQW9hWE5XVG05a1pTaGphR2xzWkNrZ0ppWWdZMmhwYkdRdVkyOTFiblFwSUh0Y2JpQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdhVzVrWlhnZ0t6MGdZMmhwYkdRdVkyOTFiblJjYmlBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0I5WEc0Z0lDQWdJQ0FnSUNBZ0lDQjlYRzRnSUNBZ0lDQWdJSDFjYmlBZ0lDQjlJR1ZzYzJVZ2FXWWdLR2x6VkdoMWJtc29kazV2WkdVcEtTQjdYRzRnSUNBZ0lDQWdJSFJvZFc1cmN5aDJUbTlrWlN3Z2JuVnNiQ3dnY0dGMFkyZ3NJR2x1WkdWNEtWeHVJQ0FnSUgxY2JuMWNibHh1Wm5WdVkzUnBiMjRnZFc1a1pXWnBibVZrUzJWNWN5aHZZbW9wSUh0Y2JpQWdJQ0IyWVhJZ2NtVnpkV3gwSUQwZ2UzMWNibHh1SUNBZ0lHWnZjaUFvZG1GeUlHdGxlU0JwYmlCdlltb3BJSHRjYmlBZ0lDQWdJQ0FnY21WemRXeDBXMnRsZVYwZ1BTQjFibVJsWm1sdVpXUmNiaUFnSUNCOVhHNWNiaUFnSUNCeVpYUjFjbTRnY21WemRXeDBYRzU5WEc1Y2JpOHZJRXhwYzNRZ1pHbG1aaXdnYm1GcGRtVWdiR1ZtZENCMGJ5QnlhV2RvZENCeVpXOXlaR1Z5YVc1blhHNW1kVzVqZEdsdmJpQnlaVzl5WkdWeUtHRkRhR2xzWkhKbGJpd2dZa05vYVd4a2NtVnVLU0I3WEc0Z0lDQWdMeThnVHloTktTQjBhVzFsTENCUEtFMHBJRzFsYlc5eWVWeHVJQ0FnSUhaaGNpQmlRMmhwYkdSSmJtUmxlQ0E5SUd0bGVVbHVaR1Y0S0dKRGFHbHNaSEpsYmlsY2JpQWdJQ0IyWVhJZ1lrdGxlWE1nUFNCaVEyaHBiR1JKYm1SbGVDNXJaWGx6WEc0Z0lDQWdkbUZ5SUdKR2NtVmxJRDBnWWtOb2FXeGtTVzVrWlhndVpuSmxaVnh1WEc0Z0lDQWdhV1lnS0dKR2NtVmxMbXhsYm1kMGFDQTlQVDBnWWtOb2FXeGtjbVZ1TG14bGJtZDBhQ2tnZTF4dUlDQWdJQ0FnSUNCeVpYUjFjbTRnZTF4dUlDQWdJQ0FnSUNBZ0lDQWdZMmhwYkdSeVpXNDZJR0pEYUdsc1pISmxiaXhjYmlBZ0lDQWdJQ0FnSUNBZ0lHMXZkbVZ6T2lCdWRXeHNYRzRnSUNBZ0lDQWdJSDFjYmlBZ0lDQjlYRzVjYmlBZ0lDQXZMeUJQS0U0cElIUnBiV1VzSUU4b1Rpa2diV1Z0YjNKNVhHNGdJQ0FnZG1GeUlHRkRhR2xzWkVsdVpHVjRJRDBnYTJWNVNXNWtaWGdvWVVOb2FXeGtjbVZ1S1Z4dUlDQWdJSFpoY2lCaFMyVjVjeUE5SUdGRGFHbHNaRWx1WkdWNExtdGxlWE5jYmlBZ0lDQjJZWElnWVVaeVpXVWdQU0JoUTJocGJHUkpibVJsZUM1bWNtVmxYRzVjYmlBZ0lDQnBaaUFvWVVaeVpXVXViR1Z1WjNSb0lEMDlQU0JoUTJocGJHUnlaVzR1YkdWdVozUm9LU0I3WEc0Z0lDQWdJQ0FnSUhKbGRIVnliaUI3WEc0Z0lDQWdJQ0FnSUNBZ0lDQmphR2xzWkhKbGJqb2dZa05vYVd4a2NtVnVMRnh1SUNBZ0lDQWdJQ0FnSUNBZ2JXOTJaWE02SUc1MWJHeGNiaUFnSUNBZ0lDQWdmVnh1SUNBZ0lIMWNibHh1SUNBZ0lDOHZJRThvVFVGWUtFNHNJRTBwS1NCdFpXMXZjbmxjYmlBZ0lDQjJZWElnYm1WM1EyaHBiR1J5Wlc0Z1BTQmJYVnh1WEc0Z0lDQWdkbUZ5SUdaeVpXVkpibVJsZUNBOUlEQmNiaUFnSUNCMllYSWdabkpsWlVOdmRXNTBJRDBnWWtaeVpXVXViR1Z1WjNSb1hHNGdJQ0FnZG1GeUlHUmxiR1YwWldSSmRHVnRjeUE5SURCY2JseHVJQ0FnSUM4dklFbDBaWEpoZEdVZ2RHaHliM1ZuYUNCaElHRnVaQ0J0WVhSamFDQmhJRzV2WkdVZ2FXNGdZbHh1SUNBZ0lDOHZJRThvVGlrZ2RHbHRaU3hjYmlBZ0lDQm1iM0lnS0haaGNpQnBJRDBnTUNBN0lHa2dQQ0JoUTJocGJHUnlaVzR1YkdWdVozUm9PeUJwS3lzcElIdGNiaUFnSUNBZ0lDQWdkbUZ5SUdGSmRHVnRJRDBnWVVOb2FXeGtjbVZ1VzJsZFhHNGdJQ0FnSUNBZ0lIWmhjaUJwZEdWdFNXNWtaWGhjYmx4dUlDQWdJQ0FnSUNCcFppQW9ZVWwwWlcwdWEyVjVLU0I3WEc0Z0lDQWdJQ0FnSUNBZ0lDQnBaaUFvWWt0bGVYTXVhR0Z6VDNkdVVISnZjR1Z5ZEhrb1lVbDBaVzB1YTJWNUtTa2dlMXh1SUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQzh2SUUxaGRHTm9JSFZ3SUhSb1pTQnZiR1FnYTJWNWMxeHVJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lHbDBaVzFKYm1SbGVDQTlJR0pMWlhselcyRkpkR1Z0TG10bGVWMWNiaUFnSUNBZ0lDQWdJQ0FnSUNBZ0lDQnVaWGREYUdsc1pISmxiaTV3ZFhOb0tHSkRhR2xzWkhKbGJsdHBkR1Z0U1c1a1pYaGRLVnh1WEc0Z0lDQWdJQ0FnSUNBZ0lDQjlJR1ZzYzJVZ2UxeHVJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDOHZJRkpsYlc5MlpTQnZiR1FnYTJWNVpXUWdhWFJsYlhOY2JpQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNCcGRHVnRTVzVrWlhnZ1BTQnBJQzBnWkdWc1pYUmxaRWwwWlcxekt5dGNiaUFnSUNBZ0lDQWdJQ0FnSUNBZ0lDQnVaWGREYUdsc1pISmxiaTV3ZFhOb0tHNTFiR3dwWEc0Z0lDQWdJQ0FnSUNBZ0lDQjlYRzRnSUNBZ0lDQWdJSDBnWld4elpTQjdYRzRnSUNBZ0lDQWdJQ0FnSUNBdkx5Qk5ZWFJqYUNCMGFHVWdhWFJsYlNCcGJpQmhJSGRwZEdnZ2RHaGxJRzVsZUhRZ1puSmxaU0JwZEdWdElHbHVJR0pjYmlBZ0lDQWdJQ0FnSUNBZ0lHbG1JQ2htY21WbFNXNWtaWGdnUENCbWNtVmxRMjkxYm5RcElIdGNiaUFnSUNBZ0lDQWdJQ0FnSUNBZ0lDQnBkR1Z0U1c1a1pYZ2dQU0JpUm5KbFpWdG1jbVZsU1c1a1pYZ3JLMTFjYmlBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0J1WlhkRGFHbHNaSEpsYmk1d2RYTm9LR0pEYUdsc1pISmxibHRwZEdWdFNXNWtaWGhkS1Z4dUlDQWdJQ0FnSUNBZ0lDQWdmU0JsYkhObElIdGNiaUFnSUNBZ0lDQWdJQ0FnSUNBZ0lDQXZMeUJVYUdWeVpTQmhjbVVnYm04Z1puSmxaU0JwZEdWdGN5QnBiaUJpSUhSdklHMWhkR05vSUhkcGRHaGNiaUFnSUNBZ0lDQWdJQ0FnSUNBZ0lDQXZMeUIwYUdVZ1puSmxaU0JwZEdWdGN5QnBiaUJoTENCemJ5QjBhR1VnWlhoMGNtRWdabkpsWlNCdWIyUmxjMXh1SUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQzh2SUdGeVpTQmtaV3hsZEdWa0xseHVJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lHbDBaVzFKYm1SbGVDQTlJR2tnTFNCa1pXeGxkR1ZrU1hSbGJYTXJLMXh1SUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJRzVsZDBOb2FXeGtjbVZ1TG5CMWMyZ29iblZzYkNsY2JpQWdJQ0FnSUNBZ0lDQWdJSDFjYmlBZ0lDQWdJQ0FnZlZ4dUlDQWdJSDFjYmx4dUlDQWdJSFpoY2lCc1lYTjBSbkpsWlVsdVpHVjRJRDBnWm5KbFpVbHVaR1Y0SUQ0OUlHSkdjbVZsTG14bGJtZDBhQ0EvWEc0Z0lDQWdJQ0FnSUdKRGFHbHNaSEpsYmk1c1pXNW5kR2dnT2x4dUlDQWdJQ0FnSUNCaVJuSmxaVnRtY21WbFNXNWtaWGhkWEc1Y2JpQWdJQ0F2THlCSmRHVnlZWFJsSUhSb2NtOTFaMmdnWWlCaGJtUWdZWEJ3Wlc1a0lHRnVlU0J1WlhjZ2EyVjVjMXh1SUNBZ0lDOHZJRThvVFNrZ2RHbHRaVnh1SUNBZ0lHWnZjaUFvZG1GeUlHb2dQU0F3T3lCcUlEd2dZa05vYVd4a2NtVnVMbXhsYm1kMGFEc2dhaXNyS1NCN1hHNGdJQ0FnSUNBZ0lIWmhjaUJ1WlhkSmRHVnRJRDBnWWtOb2FXeGtjbVZ1VzJwZFhHNWNiaUFnSUNBZ0lDQWdhV1lnS0c1bGQwbDBaVzB1YTJWNUtTQjdYRzRnSUNBZ0lDQWdJQ0FnSUNCcFppQW9JV0ZMWlhsekxtaGhjMDkzYmxCeWIzQmxjblI1S0c1bGQwbDBaVzB1YTJWNUtTa2dlMXh1SUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQzh2SUVGa1pDQmhibmtnYm1WM0lHdGxlV1ZrSUdsMFpXMXpYRzRnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdMeThnVjJVZ1lYSmxJR0ZrWkdsdVp5QnVaWGNnYVhSbGJYTWdkRzhnZEdobElHVnVaQ0JoYm1RZ2RHaGxiaUJ6YjNKMGFXNW5JSFJvWlcxY2JpQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBdkx5QnBiaUJ3YkdGalpTNGdTVzRnWm5WMGRYSmxJSGRsSUhOb2IzVnNaQ0JwYm5ObGNuUWdibVYzSUdsMFpXMXpJR2x1SUhCc1lXTmxMbHh1SUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJRzVsZDBOb2FXeGtjbVZ1TG5CMWMyZ29ibVYzU1hSbGJTbGNiaUFnSUNBZ0lDQWdJQ0FnSUgxY2JpQWdJQ0FnSUNBZ2ZTQmxiSE5sSUdsbUlDaHFJRDQ5SUd4aGMzUkdjbVZsU1c1a1pYZ3BJSHRjYmlBZ0lDQWdJQ0FnSUNBZ0lDOHZJRUZrWkNCaGJua2diR1ZtZEc5MlpYSWdibTl1TFd0bGVXVmtJR2wwWlcxelhHNGdJQ0FnSUNBZ0lDQWdJQ0J1WlhkRGFHbHNaSEpsYmk1d2RYTm9LRzVsZDBsMFpXMHBYRzRnSUNBZ0lDQWdJSDFjYmlBZ0lDQjlYRzVjYmlBZ0lDQjJZWElnYzJsdGRXeGhkR1VnUFNCdVpYZERhR2xzWkhKbGJpNXpiR2xqWlNncFhHNGdJQ0FnZG1GeUlITnBiWFZzWVhSbFNXNWtaWGdnUFNBd1hHNGdJQ0FnZG1GeUlISmxiVzkyWlhNZ1BTQmJYVnh1SUNBZ0lIWmhjaUJwYm5ObGNuUnpJRDBnVzExY2JpQWdJQ0IyWVhJZ2MybHRkV3hoZEdWSmRHVnRYRzVjYmlBZ0lDQm1iM0lnS0haaGNpQnJJRDBnTURzZ2F5QThJR0pEYUdsc1pISmxiaTVzWlc1bmRHZzdLU0I3WEc0Z0lDQWdJQ0FnSUhaaGNpQjNZVzUwWldSSmRHVnRJRDBnWWtOb2FXeGtjbVZ1VzJ0ZFhHNGdJQ0FnSUNBZ0lITnBiWFZzWVhSbFNYUmxiU0E5SUhOcGJYVnNZWFJsVzNOcGJYVnNZWFJsU1c1a1pYaGRYRzVjYmlBZ0lDQWdJQ0FnTHk4Z2NtVnRiM1psSUdsMFpXMXpYRzRnSUNBZ0lDQWdJSGRvYVd4bElDaHphVzExYkdGMFpVbDBaVzBnUFQwOUlHNTFiR3dnSmlZZ2MybHRkV3hoZEdVdWJHVnVaM1JvS1NCN1hHNGdJQ0FnSUNBZ0lDQWdJQ0J5WlcxdmRtVnpMbkIxYzJnb2NtVnRiM1psS0hOcGJYVnNZWFJsTENCemFXMTFiR0YwWlVsdVpHVjRMQ0J1ZFd4c0tTbGNiaUFnSUNBZ0lDQWdJQ0FnSUhOcGJYVnNZWFJsU1hSbGJTQTlJSE5wYlhWc1lYUmxXM05wYlhWc1lYUmxTVzVrWlhoZFhHNGdJQ0FnSUNBZ0lIMWNibHh1SUNBZ0lDQWdJQ0JwWmlBb0lYTnBiWFZzWVhSbFNYUmxiU0I4ZkNCemFXMTFiR0YwWlVsMFpXMHVhMlY1SUNFOVBTQjNZVzUwWldSSmRHVnRMbXRsZVNrZ2UxeHVJQ0FnSUNBZ0lDQWdJQ0FnTHk4Z2FXWWdkMlVnYm1WbFpDQmhJR3RsZVNCcGJpQjBhR2x6SUhCdmMybDBhVzl1TGk0dVhHNGdJQ0FnSUNBZ0lDQWdJQ0JwWmlBb2QyRnVkR1ZrU1hSbGJTNXJaWGtwSUh0Y2JpQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNCcFppQW9jMmx0ZFd4aGRHVkpkR1Z0SUNZbUlITnBiWFZzWVhSbFNYUmxiUzVyWlhrcElIdGNiaUFnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnTHk4Z2FXWWdZVzRnYVc1elpYSjBJR1J2WlhOdUozUWdjSFYwSUhSb2FYTWdhMlY1SUdsdUlIQnNZV05sTENCcGRDQnVaV1ZrY3lCMGJ5QnRiM1psWEc0Z0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lHbG1JQ2hpUzJWNWMxdHphVzExYkdGMFpVbDBaVzB1YTJWNVhTQWhQVDBnYXlBcklERXBJSHRjYmlBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJSEpsYlc5MlpYTXVjSFZ6YUNoeVpXMXZkbVVvYzJsdGRXeGhkR1VzSUhOcGJYVnNZWFJsU1c1a1pYZ3NJSE5wYlhWc1lYUmxTWFJsYlM1clpYa3BLVnh1SUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdjMmx0ZFd4aGRHVkpkR1Z0SUQwZ2MybHRkV3hoZEdWYmMybHRkV3hoZEdWSmJtUmxlRjFjYmlBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQzh2SUdsbUlIUm9aU0J5WlcxdmRtVWdaR2xrYmlkMElIQjFkQ0IwYUdVZ2QyRnVkR1ZrSUdsMFpXMGdhVzRnY0d4aFkyVXNJSGRsSUc1bFpXUWdkRzhnYVc1elpYSjBJR2wwWEc0Z0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0JwWmlBb0lYTnBiWFZzWVhSbFNYUmxiU0I4ZkNCemFXMTFiR0YwWlVsMFpXMHVhMlY1SUNFOVBTQjNZVzUwWldSSmRHVnRMbXRsZVNrZ2UxeHVJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJR2x1YzJWeWRITXVjSFZ6YUNoN2EyVjVPaUIzWVc1MFpXUkpkR1Z0TG10bGVTd2dkRzg2SUd0OUtWeHVJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ2ZWeHVJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0x5OGdhWFJsYlhNZ1lYSmxJRzFoZEdOb2FXNW5MQ0J6YnlCemEybHdJR0ZvWldGa1hHNGdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNCbGJITmxJSHRjYmlBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNCemFXMTFiR0YwWlVsdVpHVjRLeXRjYmlBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJSDFjYmlBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ2ZWeHVJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0JsYkhObElIdGNiaUFnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lHbHVjMlZ5ZEhNdWNIVnphQ2g3YTJWNU9pQjNZVzUwWldSSmRHVnRMbXRsZVN3Z2RHODZJR3Q5S1Z4dUlDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQjlYRzRnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdmVnh1SUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJR1ZzYzJVZ2UxeHVJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0JwYm5ObGNuUnpMbkIxYzJnb2UydGxlVG9nZDJGdWRHVmtTWFJsYlM1clpYa3NJSFJ2T2lCcmZTbGNiaUFnSUNBZ0lDQWdJQ0FnSUNBZ0lDQjlYRzRnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdheXNyWEc0Z0lDQWdJQ0FnSUNBZ0lDQjlYRzRnSUNBZ0lDQWdJQ0FnSUNBdkx5QmhJR3RsZVNCcGJpQnphVzExYkdGMFpTQm9ZWE1nYm04Z2JXRjBZMmhwYm1jZ2QyRnVkR1ZrSUd0bGVTd2djbVZ0YjNabElHbDBYRzRnSUNBZ0lDQWdJQ0FnSUNCbGJITmxJR2xtSUNoemFXMTFiR0YwWlVsMFpXMGdKaVlnYzJsdGRXeGhkR1ZKZEdWdExtdGxlU2tnZTF4dUlDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUhKbGJXOTJaWE11Y0hWemFDaHlaVzF2ZG1Vb2MybHRkV3hoZEdVc0lITnBiWFZzWVhSbFNXNWtaWGdzSUhOcGJYVnNZWFJsU1hSbGJTNXJaWGtwS1Z4dUlDQWdJQ0FnSUNBZ0lDQWdmVnh1SUNBZ0lDQWdJQ0I5WEc0Z0lDQWdJQ0FnSUdWc2MyVWdlMXh1SUNBZ0lDQWdJQ0FnSUNBZ2MybHRkV3hoZEdWSmJtUmxlQ3NyWEc0Z0lDQWdJQ0FnSUNBZ0lDQnJLeXRjYmlBZ0lDQWdJQ0FnZlZ4dUlDQWdJSDFjYmx4dUlDQWdJQzh2SUhKbGJXOTJaU0JoYkd3Z2RHaGxJSEpsYldGcGJtbHVaeUJ1YjJSbGN5Qm1jbTl0SUhOcGJYVnNZWFJsWEc0Z0lDQWdkMmhwYkdVb2MybHRkV3hoZEdWSmJtUmxlQ0E4SUhOcGJYVnNZWFJsTG14bGJtZDBhQ2tnZTF4dUlDQWdJQ0FnSUNCemFXMTFiR0YwWlVsMFpXMGdQU0J6YVcxMWJHRjBaVnR6YVcxMWJHRjBaVWx1WkdWNFhWeHVJQ0FnSUNBZ0lDQnlaVzF2ZG1WekxuQjFjMmdvY21WdGIzWmxLSE5wYlhWc1lYUmxMQ0J6YVcxMWJHRjBaVWx1WkdWNExDQnphVzExYkdGMFpVbDBaVzBnSmlZZ2MybHRkV3hoZEdWSmRHVnRMbXRsZVNrcFhHNGdJQ0FnZlZ4dVhHNGdJQ0FnTHk4Z1NXWWdkR2hsSUc5dWJIa2diVzkyWlhNZ2QyVWdhR0YyWlNCaGNtVWdaR1ZzWlhSbGN5QjBhR1Z1SUhkbElHTmhiaUJxZFhOMFhHNGdJQ0FnTHk4Z2JHVjBJSFJvWlNCa1pXeGxkR1VnY0dGMFkyZ2djbVZ0YjNabElIUm9aWE5sSUdsMFpXMXpMbHh1SUNBZ0lHbG1JQ2h5WlcxdmRtVnpMbXhsYm1kMGFDQTlQVDBnWkdWc1pYUmxaRWwwWlcxeklDWW1JQ0ZwYm5ObGNuUnpMbXhsYm1kMGFDa2dlMXh1SUNBZ0lDQWdJQ0J5WlhSMWNtNGdlMXh1SUNBZ0lDQWdJQ0FnSUNBZ1kyaHBiR1J5Wlc0NklHNWxkME5vYVd4a2NtVnVMRnh1SUNBZ0lDQWdJQ0FnSUNBZ2JXOTJaWE02SUc1MWJHeGNiaUFnSUNBZ0lDQWdmVnh1SUNBZ0lIMWNibHh1SUNBZ0lISmxkSFZ5YmlCN1hHNGdJQ0FnSUNBZ0lHTm9hV3hrY21WdU9pQnVaWGREYUdsc1pISmxiaXhjYmlBZ0lDQWdJQ0FnYlc5MlpYTTZJSHRjYmlBZ0lDQWdJQ0FnSUNBZ0lISmxiVzkyWlhNNklISmxiVzkyWlhNc1hHNGdJQ0FnSUNBZ0lDQWdJQ0JwYm5ObGNuUnpPaUJwYm5ObGNuUnpYRzRnSUNBZ0lDQWdJSDFjYmlBZ0lDQjlYRzU5WEc1Y2JtWjFibU4wYVc5dUlISmxiVzkyWlNoaGNuSXNJR2x1WkdWNExDQnJaWGtwSUh0Y2JpQWdJQ0JoY25JdWMzQnNhV05sS0dsdVpHVjRMQ0F4S1Z4dVhHNGdJQ0FnY21WMGRYSnVJSHRjYmlBZ0lDQWdJQ0FnWm5KdmJUb2dhVzVrWlhnc1hHNGdJQ0FnSUNBZ0lHdGxlVG9nYTJWNVhHNGdJQ0FnZlZ4dWZWeHVYRzVtZFc1amRHbHZiaUJyWlhsSmJtUmxlQ2hqYUdsc1pISmxiaWtnZTF4dUlDQWdJSFpoY2lCclpYbHpJRDBnZTMxY2JpQWdJQ0IyWVhJZ1puSmxaU0E5SUZ0ZFhHNGdJQ0FnZG1GeUlHeGxibWQwYUNBOUlHTm9hV3hrY21WdUxteGxibWQwYUZ4dVhHNGdJQ0FnWm05eUlDaDJZWElnYVNBOUlEQTdJR2tnUENCc1pXNW5kR2c3SUdrckt5a2dlMXh1SUNBZ0lDQWdJQ0IyWVhJZ1kyaHBiR1FnUFNCamFHbHNaSEpsYmx0cFhWeHVYRzRnSUNBZ0lDQWdJR2xtSUNoamFHbHNaQzVyWlhrcElIdGNiaUFnSUNBZ0lDQWdJQ0FnSUd0bGVYTmJZMmhwYkdRdWEyVjVYU0E5SUdsY2JpQWdJQ0FnSUNBZ2ZTQmxiSE5sSUh0Y2JpQWdJQ0FnSUNBZ0lDQWdJR1p5WldVdWNIVnphQ2hwS1Z4dUlDQWdJQ0FnSUNCOVhHNGdJQ0FnZlZ4dVhHNGdJQ0FnY21WMGRYSnVJSHRjYmlBZ0lDQWdJQ0FnYTJWNWN6b2dhMlY1Y3l3Z0lDQWdJQzh2SUVFZ2FHRnphQ0J2WmlCclpYa2dibUZ0WlNCMGJ5QnBibVJsZUZ4dUlDQWdJQ0FnSUNCbWNtVmxPaUJtY21WbElDQWdJQ0FnTHk4Z1FXNGdZWEp5WVhrZ2IyWWdkVzVyWlhsbFpDQnBkR1Z0SUdsdVpHbGpaWE5jYmlBZ0lDQjlYRzU5WEc1Y2JtWjFibU4wYVc5dUlHRndjR1Z1WkZCaGRHTm9LR0Z3Y0d4NUxDQndZWFJqYUNrZ2UxeHVJQ0FnSUdsbUlDaGhjSEJzZVNrZ2UxeHVJQ0FnSUNBZ0lDQnBaaUFvYVhOQmNuSmhlU2hoY0hCc2VTa3BJSHRjYmlBZ0lDQWdJQ0FnSUNBZ0lHRndjR3g1TG5CMWMyZ29jR0YwWTJncFhHNGdJQ0FnSUNBZ0lIMGdaV3h6WlNCN1hHNGdJQ0FnSUNBZ0lDQWdJQ0JoY0hCc2VTQTlJRnRoY0hCc2VTd2djR0YwWTJoZFhHNGdJQ0FnSUNBZ0lIMWNibHh1SUNBZ0lDQWdJQ0J5WlhSMWNtNGdZWEJ3YkhsY2JpQWdJQ0I5SUdWc2MyVWdlMXh1SUNBZ0lDQWdJQ0J5WlhSMWNtNGdjR0YwWTJoY2JpQWdJQ0I5WEc1OVhHNWNibjBzZTF3aUxpNHZkbTV2WkdVdmFHRnVaR3hsTFhSb2RXNXJYQ0k2TWpRc1hDSXVMaTkyYm05a1pTOXBjeTEwYUhWdWExd2lPakkxTEZ3aUxpNHZkbTV2WkdVdmFYTXRkbTV2WkdWY0lqb3lOeXhjSWk0dUwzWnViMlJsTDJsekxYWjBaWGgwWENJNk1qZ3NYQ0l1TGk5MmJtOWtaUzlwY3kxM2FXUm5aWFJjSWpveU9TeGNJaTR1TDNadWIyUmxMM1p3WVhSamFGd2lPak15TEZ3aUxpOWthV1ptTFhCeWIzQnpYQ0k2TXpRc1hDSjRMV2x6TFdGeWNtRjVYQ0k2TVRKOVhYMHNlMzBzV3pSZEtTZzBLVnh1ZlNrN1hHNWNibVY0Y0c5eWRDQmtaV1poZFd4MElGWnBjblIxWVd4RVQwMDdYRzRpWFN3aWMyOTFjbU5sVW05dmRDSTZJaTl6YjNWeVkyVXZJbjA9XG4iLCJpbXBvcnQgQ29yZSBmcm9tICcuL2xpYi9jb3JlJztcbmltcG9ydCBFbnVtIGZyb20gJy4vbGliL2VudW0nO1xuaW1wb3J0IFZpcnR1YWxET00gZnJvbSAnLi9saWIvdmlydHVhbC1kb20nO1xuXG5leHBvcnQgZGVmYXVsdCB7XG4gIENvcmUsXG4gIEVudW0sXG4gIFZpcnR1YWxET01cbn07XG4vLyMgc291cmNlTWFwcGluZ1VSTD1kYXRhOmFwcGxpY2F0aW9uL2pzb247YmFzZTY0LGV5SjJaWEp6YVc5dUlqb3pMQ0p6YjNWeVkyVnpJanBiSW1Wc2FYaHBjaTVxY3lKZExDSnVZVzFsY3lJNlcxMHNJbTFoY0hCcGJtZHpJam9pUVVGQlFTeFBRVUZQTEVsQlFWQXNUVUZCYVVJc1dVRkJha0k3UVVGRFFTeFBRVUZQTEVsQlFWQXNUVUZCYVVJc1dVRkJha0k3UVVGRFFTeFBRVUZQTEZWQlFWQXNUVUZCZFVJc2JVSkJRWFpDT3p0QlFVVkJMR1ZCUVdVN1FVRkRZaXhOUVVSaE8wRkJSV0lzVFVGR1lUdEJRVWRpTEZsQlNHRTdRMEZCWmlJc0ltWnBiR1VpT2lKbGJHbDRhWEl1YW5NaUxDSnpiM1Z5WTJWelEyOXVkR1Z1ZENJNld5SnBiWEJ2Y25RZ1EyOXlaU0JtY205dElDY3VMMnhwWWk5amIzSmxKenRjYm1sdGNHOXlkQ0JGYm5WdElHWnliMjBnSnk0dmJHbGlMMlZ1ZFcwbk8xeHVhVzF3YjNKMElGWnBjblIxWVd4RVQwMGdabkp2YlNBbkxpOXNhV0l2ZG1seWRIVmhiQzFrYjIwbk8xeHVYRzVsZUhCdmNuUWdaR1ZtWVhWc2RDQjdYRzRnSUVOdmNtVXNYRzRnSUVWdWRXMHNYRzRnSUZacGNuUjFZV3hFVDAxY2JuMDdYRzRpWFN3aWMyOTFjbU5sVW05dmRDSTZJaTl6YjNWeVkyVXZJbjA9XG4iXSwibmFtZXMiOlsiUHJpbWl0aXZlcy5QSUQiLCJUeXBlcy5WYXJpYWJsZSJdLCJtYXBwaW5ncyI6IkFBRUEsTUFBTSxPQUFPLENBQUM7O0VBRVosV0FBVyxHQUFHO0lBQ1osSUFBSSxDQUFDLFFBQVEsR0FBRyxFQUFFLENBQUM7R0FDcEI7O0VBRUQsT0FBTyxDQUFDLE9BQU8sRUFBRTtJQUNmLElBQUksQ0FBQyxRQUFRLENBQUMsSUFBSSxDQUFDLE9BQU8sQ0FBQyxDQUFDO0lBQzVCLE9BQU8sT0FBTyxDQUFDO0dBQ2hCOztFQUVELEdBQUcsR0FBRztJQUNKLE9BQU8sSUFBSSxDQUFDLFFBQVEsQ0FBQztHQUN0Qjs7RUFFRCxPQUFPLEdBQUc7SUFDUixPQUFPLElBQUksQ0FBQyxRQUFRLENBQUMsTUFBTSxLQUFLLENBQUMsQ0FBQztHQUNuQzs7RUFFRCxRQUFRLENBQUMsS0FBSyxFQUFFO0lBQ2QsSUFBSSxDQUFDLFFBQVEsQ0FBQyxNQUFNLENBQUMsS0FBSyxFQUFFLENBQUMsQ0FBQyxDQUFDO0dBQ2hDO0NBQ0Y7O2FDeEJjO0VBQ2IsTUFBTSxFQUFFLE1BQU0sQ0FBQyxHQUFHLENBQUMsUUFBUSxDQUFDO0VBQzVCLElBQUksRUFBRSxNQUFNLENBQUMsR0FBRyxDQUFDLE1BQU0sQ0FBQztFQUN4QixPQUFPLEVBQUUsTUFBTSxDQUFDLEdBQUcsQ0FBQyxTQUFTLENBQUM7RUFDOUIsUUFBUSxFQUFFLE1BQU0sQ0FBQyxHQUFHLENBQUMsVUFBVSxDQUFDO0VBQ2hDLE9BQU8sRUFBRSxNQUFNLENBQUMsR0FBRyxDQUFDLFNBQVMsQ0FBQztFQUM5QixJQUFJLEVBQUUsTUFBTSxDQUFDLEdBQUcsQ0FBQyxNQUFNLENBQUM7RUFDeEIsUUFBUSxFQUFFLE1BQU0sQ0FBQyxHQUFHLENBQUMsVUFBVSxDQUFDO0VBQ2hDLE9BQU8sRUFBRSxNQUFNLENBQUMsR0FBRyxDQUFDLFNBQVMsQ0FBQztFQUM5QixTQUFTLEVBQUUsTUFBTSxDQUFDLEdBQUcsQ0FBQyxXQUFXLENBQUM7RUFDbEMsT0FBTyxFQUFFLE1BQU0sQ0FBQyxHQUFHLENBQUMsU0FBUyxDQUFDO0VBQzlCLEtBQUssRUFBRSxNQUFNLENBQUMsR0FBRyxDQUFDLE9BQU8sQ0FBQztFQUMxQixJQUFJLEVBQUUsTUFBTSxDQUFDLEdBQUcsQ0FBQyxNQUFNLENBQUM7RUFDeEIsT0FBTyxFQUFFLE1BQU0sQ0FBQyxHQUFHLENBQUMsVUFBVSxDQUFDO0NBQ2hDLENBQUM7O0FDVEYsTUFBTSxPQUFPLENBQUM7O0VBRVosV0FBVyxDQUFDLEdBQUcsRUFBRSxPQUFPLEVBQUU7SUFDeEIsSUFBSSxDQUFDLEdBQUcsR0FBRyxHQUFHLENBQUM7SUFDZixJQUFJLENBQUMsT0FBTyxHQUFHLE9BQU8sQ0FBQztJQUN2QixJQUFJLENBQUMsTUFBTSxHQUFHLE1BQU0sQ0FBQyxPQUFPLENBQUM7SUFDN0IsSUFBSSxDQUFDLElBQUksR0FBRyxFQUFFLENBQUM7R0FDaEI7Q0FDRjs7QUNiRCxNQUFNLEtBQUssQ0FBQzs7RUFFVixXQUFXLENBQUMsR0FBRyxJQUFJLEVBQUU7SUFDbkIsSUFBSSxDQUFDLE1BQU0sR0FBRyxNQUFNLENBQUMsTUFBTSxDQUFDLElBQUksQ0FBQyxDQUFDO0lBQ2xDLElBQUksQ0FBQyxNQUFNLEdBQUcsSUFBSSxDQUFDLE1BQU0sQ0FBQyxNQUFNLENBQUM7R0FDbEM7O0VBRUQsR0FBRyxDQUFDLEtBQUssRUFBRTtJQUNULE9BQU8sSUFBSSxDQUFDLE1BQU0sQ0FBQyxLQUFLLENBQUMsQ0FBQztHQUMzQjs7RUFFRCxLQUFLLEdBQUc7SUFDTixPQUFPLElBQUksQ0FBQyxNQUFNLENBQUMsTUFBTSxDQUFDO0dBQzNCOztFQUVELENBQUMsTUFBTSxDQUFDLFFBQVEsQ0FBQyxHQUFHO0lBQ2xCLE9BQU8sSUFBSSxDQUFDLE1BQU0sQ0FBQyxNQUFNLENBQUMsUUFBUSxDQUFDLEVBQUUsQ0FBQztHQUN2Qzs7RUFFRCxRQUFRLEdBQUc7SUFDVCxJQUFJLENBQUM7UUFDRCxDQUFDLEdBQUcsRUFBRSxDQUFDO0lBQ1gsS0FBSyxDQUFDLEdBQUcsQ0FBQyxFQUFFLENBQUMsR0FBRyxJQUFJLENBQUMsTUFBTSxDQUFDLE1BQU0sRUFBRSxDQUFDLEVBQUUsRUFBRTtNQUN2QyxJQUFJLENBQUMsS0FBSyxFQUFFLEVBQUU7UUFDWixDQUFDLElBQUksSUFBSSxDQUFDO09BQ1g7TUFDRCxDQUFDLElBQUksSUFBSSxDQUFDLE1BQU0sQ0FBQyxDQUFDLENBQUMsQ0FBQyxRQUFRLEVBQUUsQ0FBQztLQUNoQzs7SUFFRCxPQUFPLEdBQUcsR0FBRyxDQUFDLEdBQUcsR0FBRyxDQUFDO0dBQ3RCOztFQUVELFFBQVEsQ0FBQyxLQUFLLEVBQUUsSUFBSSxFQUFFO0lBQ3BCLElBQUksS0FBSyxLQUFLLElBQUksQ0FBQyxNQUFNLEVBQUU7TUFDekIsSUFBSSxVQUFVLEdBQUcsSUFBSSxDQUFDLE1BQU0sQ0FBQyxNQUFNLENBQUMsQ0FBQyxJQUFJLENBQUMsQ0FBQyxDQUFDO01BQzVDLE9BQU8sSUFBSSxLQUFLLENBQUMsR0FBRyxVQUFVLENBQUMsQ0FBQztLQUNqQzs7SUFFRCxJQUFJLFVBQVUsR0FBRyxJQUFJLENBQUMsTUFBTSxDQUFDLE1BQU0sQ0FBQyxFQUFFLENBQUMsQ0FBQztJQUN4QyxVQUFVLENBQUMsTUFBTSxDQUFDLEtBQUssRUFBRSxDQUFDLEVBQUUsSUFBSSxDQUFDLENBQUM7SUFDbEMsT0FBTyxJQUFJLEtBQUssQ0FBQyxHQUFHLFVBQVUsQ0FBQyxDQUFDO0dBQ2pDOztFQUVELFdBQVcsQ0FBQyxLQUFLLEVBQUU7SUFDakIsSUFBSSxVQUFVLEdBQUcsSUFBSSxDQUFDLE1BQU0sQ0FBQyxNQUFNLENBQUMsRUFBRSxDQUFDLENBQUM7SUFDeEMsVUFBVSxDQUFDLE1BQU0sQ0FBQyxLQUFLLEVBQUUsQ0FBQyxDQUFDLENBQUM7SUFDNUIsT0FBTyxJQUFJLEtBQUssQ0FBQyxHQUFHLFVBQVUsQ0FBQyxDQUFDO0dBQ2pDOztDQUVGOztBQUVELElBQUksZUFBZSxHQUFHLENBQUMsQ0FBQyxDQUFDOztBQUV6QixNQUFNLEdBQUcsQ0FBQztFQUNSLFdBQVcsR0FBRztJQUNaLGVBQWUsR0FBRyxlQUFlLEdBQUcsQ0FBQyxDQUFDO0lBQ3RDLElBQUksQ0FBQyxFQUFFLEdBQUcsZUFBZSxDQUFDO0dBQzNCOztFQUVELFFBQVEsR0FBRztJQUNULE9BQU8sU0FBUyxHQUFHLElBQUksQ0FBQyxFQUFFLEdBQUcsS0FBSyxDQUFDO0dBQ3BDO0NBQ0Y7O0FBRUQsTUFBTSxPQUFPLENBQUMsRUFBRTtBQUNoQixNQUFNLEtBQUssQ0FBQyxFQUFFOztBQ3pEZCxNQUFNLGFBQWEsQ0FBQzs7RUFFbEIsV0FBVyxHQUFHO0lBQ1osSUFBSSxDQUFDLElBQUksR0FBRyxJQUFJLEdBQUcsRUFBRSxDQUFDO0lBQ3RCLElBQUksQ0FBQyxTQUFTLEdBQUcsSUFBSSxHQUFHLEVBQUUsQ0FBQztJQUMzQixJQUFJLENBQUMsS0FBSyxHQUFHLElBQUksR0FBRyxFQUFFLENBQUM7SUFDdkIsSUFBSSxDQUFDLEtBQUssR0FBRyxJQUFJLEdBQUcsRUFBRSxDQUFDOztJQUV2QixJQUFJLENBQUMsZUFBZSxHQUFHLElBQUksQ0FBQztJQUM1QixJQUFJLENBQUMsU0FBUyxHQUFHLElBQUksR0FBRyxFQUFFLENBQUM7O0lBRTNCLElBQUksQ0FBQyxnQkFBZ0IsR0FBRyxJQUFJLENBQUMsS0FBSyxFQUFFLENBQUM7SUFDckMsSUFBSSxDQUFDLFdBQVcsQ0FBQyxJQUFJLENBQUMsZ0JBQWdCLENBQUMsQ0FBQztHQUN6Qzs7RUFFRCxLQUFLLEdBQUc7SUFDTixPQUFPLElBQUksQ0FBQyxRQUFRLENBQUMsS0FBSyxDQUFDLENBQUMsR0FBRyxDQUFDO0dBQ2pDOztFQUVELFVBQVUsR0FBRztJQUNYLE9BQU8sSUFBSSxDQUFDLFFBQVEsQ0FBQyxJQUFJLENBQUMsQ0FBQyxHQUFHLENBQUM7R0FDaEM7O0VBRUQsSUFBSSxDQUFDLEdBQUcsRUFBRTtJQUNSLElBQUksQ0FBQyxLQUFLLENBQUMsR0FBRyxDQUFDLElBQUksQ0FBQyxHQUFHLEVBQUUsQ0FBQyxDQUFDLEdBQUcsQ0FBQyxHQUFHLENBQUMsQ0FBQztJQUNwQyxJQUFJLENBQUMsS0FBSyxDQUFDLEdBQUcsQ0FBQyxHQUFHLENBQUMsQ0FBQyxHQUFHLENBQUMsSUFBSSxDQUFDLEdBQUcsRUFBRSxDQUFDLENBQUM7R0FDckM7O0VBRUQsTUFBTSxDQUFDLEdBQUcsRUFBRTtJQUNWLElBQUksQ0FBQyxLQUFLLENBQUMsR0FBRyxDQUFDLElBQUksQ0FBQyxHQUFHLEVBQUUsQ0FBQyxDQUFDLE1BQU0sQ0FBQyxHQUFHLENBQUMsQ0FBQztJQUN2QyxJQUFJLENBQUMsS0FBSyxDQUFDLEdBQUcsQ0FBQyxHQUFHLENBQUMsQ0FBQyxNQUFNLENBQUMsSUFBSSxDQUFDLEdBQUcsRUFBRSxDQUFDLENBQUM7R0FDeEM7O0VBRUQsV0FBVyxDQUFDLEVBQUUsRUFBRTtJQUNkLElBQUksR0FBRyxHQUFHLElBQUksQ0FBQyxLQUFLLENBQUMsRUFBRSxDQUFDLENBQUM7SUFDekIsSUFBSSxHQUFHLEtBQUssSUFBSSxFQUFFO01BQ2hCLElBQUksQ0FBQyxlQUFlLEdBQUcsSUFBSSxDQUFDLElBQUksQ0FBQyxHQUFHLENBQUMsR0FBRyxDQUFDLENBQUM7TUFDMUMsSUFBSSxDQUFDLGVBQWUsQ0FBQyxNQUFNLEdBQUcsTUFBTSxDQUFDLE9BQU8sQ0FBQztLQUM5QztHQUNGOztFQUVELFFBQVEsQ0FBQyxNQUFNLEVBQUU7SUFDZixJQUFJLE1BQU0sR0FBRyxJQUFJQSxHQUFjLEVBQUUsQ0FBQztJQUNsQyxJQUFJLE9BQU8sR0FBRyxJQUFJLE9BQU8sRUFBRSxDQUFDO0lBQzVCLElBQUksT0FBTyxHQUFHLElBQUksT0FBTyxDQUFDLE1BQU0sRUFBRSxPQUFPLENBQUMsQ0FBQzs7SUFFM0MsSUFBSSxDQUFDLElBQUksQ0FBQyxHQUFHLENBQUMsTUFBTSxFQUFFLE9BQU8sQ0FBQyxDQUFDO0lBQy9CLElBQUksQ0FBQyxTQUFTLENBQUMsR0FBRyxDQUFDLE1BQU0sRUFBRSxPQUFPLENBQUMsQ0FBQztJQUNwQyxJQUFJLENBQUMsS0FBSyxDQUFDLEdBQUcsQ0FBQyxNQUFNLEVBQUUsSUFBSSxHQUFHLEVBQUUsQ0FBQyxDQUFDOztJQUVsQyxJQUFJLE1BQU0sRUFBRTtNQUNWLElBQUksQ0FBQyxJQUFJLENBQUMsTUFBTSxDQUFDLENBQUM7S0FDbkI7O0lBRUQsT0FBTyxPQUFPLENBQUM7R0FDaEI7O0VBRUQsV0FBVyxDQUFDLEdBQUcsRUFBRTtJQUNmLElBQUksQ0FBQyxJQUFJLENBQUMsTUFBTSxDQUFDLEdBQUcsQ0FBQyxDQUFDO0lBQ3RCLElBQUksQ0FBQyxVQUFVLENBQUMsR0FBRyxDQUFDLENBQUM7O0lBRXJCLElBQUksSUFBSSxDQUFDLEtBQUssQ0FBQyxHQUFHLENBQUMsR0FBRyxDQUFDLEVBQUU7TUFDdkIsS0FBSyxJQUFJLE9BQU8sSUFBSSxJQUFJLENBQUMsS0FBSyxDQUFDLEdBQUcsQ0FBQyxHQUFHLENBQUMsRUFBRTtRQUN2QyxJQUFJLENBQUMsS0FBSyxDQUFDLEdBQUcsQ0FBQyxPQUFPLENBQUMsQ0FBQyxNQUFNLENBQUMsR0FBRyxDQUFDLENBQUM7T0FDckM7O01BRUQsSUFBSSxDQUFDLEtBQUssQ0FBQyxNQUFNLENBQUMsR0FBRyxDQUFDLENBQUM7S0FDeEI7R0FDRjs7RUFFRCxJQUFJLENBQUMsRUFBRSxFQUFFO0lBQ1AsSUFBSSxHQUFHLEdBQUcsSUFBSSxDQUFDLEtBQUssQ0FBQyxFQUFFLENBQUMsQ0FBQztJQUN6QixJQUFJLENBQUMsV0FBVyxDQUFDLEVBQUUsQ0FBQyxDQUFDO0dBQ3RCOztFQUVELFFBQVEsQ0FBQyxJQUFJLEVBQUUsR0FBRyxFQUFFO0lBQ2xCLElBQUksQ0FBQyxJQUFJLENBQUMsS0FBSyxDQUFDLEdBQUcsQ0FBQyxJQUFJLENBQUMsRUFBRTtNQUN6QixJQUFJLENBQUMsS0FBSyxDQUFDLEdBQUcsQ0FBQyxJQUFJLEVBQUUsR0FBRyxDQUFDLENBQUM7TUFDMUIsT0FBTyxJQUFJLENBQUM7S0FDYixNQUFNO01BQ0wsTUFBTSxJQUFJLEtBQUssQ0FBQywrQ0FBK0MsQ0FBQyxDQUFDO0tBQ2xFO0dBQ0Y7O0VBRUQsVUFBVSxDQUFDLElBQUksRUFBRTtJQUNmLE9BQU8sSUFBSSxDQUFDLEtBQUssQ0FBQyxHQUFHLENBQUMsSUFBSSxDQUFDLEdBQUcsSUFBSSxDQUFDLEtBQUssQ0FBQyxHQUFHLENBQUMsSUFBSSxDQUFDLEdBQUcsSUFBSSxDQUFDO0dBQzNEOztFQUVELFVBQVUsQ0FBQyxHQUFHLEVBQUU7SUFDZCxLQUFLLElBQUksSUFBSSxJQUFJLElBQUksQ0FBQyxLQUFLLENBQUMsSUFBSSxFQUFFLEVBQUU7TUFDbEMsSUFBSSxJQUFJLENBQUMsS0FBSyxDQUFDLEdBQUcsQ0FBQyxJQUFJLENBQUMsSUFBSSxJQUFJLENBQUMsS0FBSyxDQUFDLEdBQUcsQ0FBQyxJQUFJLENBQUMsS0FBSyxHQUFHLEVBQUU7UUFDeEQsSUFBSSxDQUFDLEtBQUssQ0FBQyxNQUFNLENBQUMsSUFBSSxDQUFDLENBQUM7T0FDekI7S0FDRjtHQUNGOztFQUVELEdBQUcsR0FBRztJQUNKLE9BQU8sSUFBSSxDQUFDLGVBQWUsQ0FBQyxHQUFHLENBQUM7R0FDakM7O0VBRUQsS0FBSyxDQUFDLEVBQUUsRUFBRTtJQUNSLElBQUksRUFBRSxZQUFZQSxHQUFjLEVBQUU7TUFDaEMsT0FBTyxJQUFJLENBQUMsSUFBSSxDQUFDLEdBQUcsQ0FBQyxFQUFFLENBQUMsR0FBRyxFQUFFLEdBQUcsSUFBSSxDQUFDO0tBQ3RDLE1BQU0sSUFBSSxFQUFFLFlBQVksT0FBTyxFQUFFO01BQ2hDLE9BQU8sRUFBRSxDQUFDLEdBQUcsQ0FBQztLQUNmLE1BQU07TUFDTCxJQUFJLEdBQUcsR0FBRyxJQUFJLENBQUMsVUFBVSxDQUFDLEVBQUUsQ0FBQyxDQUFDO01BQzlCLElBQUksR0FBRyxLQUFLLElBQUksRUFBRSxNQUFNLCtCQUErQixHQUFHLEVBQUUsR0FBRyxJQUFJLEdBQUcsT0FBTyxFQUFFLEdBQUcsR0FBRyxDQUFDO01BQ3RGLE9BQU8sR0FBRyxDQUFDO0tBQ1o7R0FDRjs7RUFFRCxHQUFHLENBQUMsRUFBRSxFQUFFLEdBQUcsRUFBRSxLQUFLLEVBQUU7SUFDbEIsSUFBSSxHQUFHLEdBQUcsSUFBSSxDQUFDLEtBQUssQ0FBQyxFQUFFLENBQUMsQ0FBQztJQUN6QixJQUFJLE9BQU8sR0FBRyxJQUFJLENBQUMsSUFBSSxDQUFDLEdBQUcsQ0FBQyxHQUFHLENBQUMsQ0FBQztJQUNqQyxPQUFPLENBQUMsSUFBSSxDQUFDLEdBQUcsQ0FBQyxHQUFHLEtBQUssQ0FBQztHQUMzQjs7RUFFRCxHQUFHLENBQUMsRUFBRSxFQUFFLEdBQUcsRUFBRTtJQUNYLElBQUksR0FBRyxHQUFHLElBQUksQ0FBQyxLQUFLLENBQUMsRUFBRSxDQUFDLENBQUM7SUFDekIsSUFBSSxPQUFPLEdBQUcsSUFBSSxDQUFDLElBQUksQ0FBQyxHQUFHLENBQUMsR0FBRyxDQUFDLENBQUM7O0lBRWpDLElBQUksR0FBRyxJQUFJLElBQUksRUFBRTtNQUNmLE9BQU8sT0FBTyxDQUFDLElBQUksQ0FBQyxHQUFHLENBQUMsQ0FBQztLQUMxQixNQUFNO01BQ0wsT0FBTyxPQUFPLENBQUMsSUFBSSxDQUFDO0tBQ3JCO0dBQ0Y7O0VBRUQsUUFBUSxDQUFDLEVBQUUsRUFBRTtJQUNYLElBQUksR0FBRyxHQUFHLElBQUksQ0FBQyxLQUFLLENBQUMsRUFBRSxDQUFDLENBQUM7SUFDekIsSUFBSSxPQUFPLEdBQUcsSUFBSSxDQUFDLElBQUksQ0FBQyxHQUFHLENBQUMsR0FBRyxDQUFDLENBQUM7O0lBRWpDLE9BQU8sTUFBTSxDQUFDLElBQUksQ0FBQyxPQUFPLENBQUMsSUFBSSxDQUFDLENBQUM7R0FDbEM7O0VBRUQsS0FBSyxDQUFDLEVBQUUsRUFBRSxHQUFHLEVBQUU7SUFDYixJQUFJLEdBQUcsR0FBRyxJQUFJLENBQUMsS0FBSyxDQUFDLEVBQUUsQ0FBQyxDQUFDO0lBQ3pCLElBQUksT0FBTyxHQUFHLElBQUksQ0FBQyxJQUFJLENBQUMsR0FBRyxDQUFDLEdBQUcsQ0FBQyxDQUFDOztJQUVqQyxJQUFJLEdBQUcsSUFBSSxJQUFJLEVBQUU7TUFDZixPQUFPLE9BQU8sQ0FBQyxJQUFJLENBQUMsR0FBRyxDQUFDLENBQUM7S0FDMUIsTUFBTTtNQUNMLE9BQU8sQ0FBQyxJQUFJLEdBQUcsRUFBRSxDQUFDO0tBQ25CO0dBQ0Y7Q0FDRjs7QUMxSkQsTUFBTSxTQUFTLENBQUM7RUFDZCxXQUFXLENBQUMsR0FBRyxJQUFJLEVBQUU7SUFDbkIsSUFBSSxDQUFDLEtBQUssR0FBRyxNQUFNLENBQUMsTUFBTSxDQUFDLElBQUksQ0FBQyxPQUFPLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQztJQUMvQyxJQUFJLENBQUMsTUFBTSxHQUFHLElBQUksQ0FBQyxLQUFLLENBQUMsTUFBTSxDQUFDO0lBQ2hDLElBQUksQ0FBQyxRQUFRLEdBQUcsSUFBSSxDQUFDLE1BQU0sR0FBRyxDQUFDLENBQUM7SUFDaEMsSUFBSSxDQUFDLFNBQVMsR0FBRyxJQUFJLENBQUMsTUFBTSxDQUFDO0dBQzlCOztFQUVELEdBQUcsQ0FBQyxLQUFLLEVBQUU7SUFDVCxPQUFPLElBQUksQ0FBQyxLQUFLLENBQUMsS0FBSyxDQUFDLENBQUM7R0FDMUI7O0VBRUQsS0FBSyxHQUFHO0lBQ04sT0FBTyxJQUFJLENBQUMsS0FBSyxDQUFDLE1BQU0sQ0FBQztHQUMxQjs7RUFFRCxLQUFLLENBQUMsS0FBSyxFQUFFLEdBQUcsR0FBRyxJQUFJLEVBQUU7SUFDdkIsSUFBSSxDQUFDLEdBQUcsSUFBSSxDQUFDLEtBQUssQ0FBQyxLQUFLLENBQUMsS0FBSyxFQUFFLEdBQUcsQ0FBQyxDQUFDO0lBQ3JDLElBQUksRUFBRSxHQUFHLENBQUMsQ0FBQyxHQUFHLENBQUMsSUFBSSxJQUFJLFNBQVMsQ0FBQyxPQUFPLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQztJQUNoRCxPQUFPLElBQUksU0FBUyxDQUFDLEdBQUcsRUFBRSxDQUFDLENBQUM7R0FDN0I7O0VBRUQsQ0FBQyxNQUFNLENBQUMsUUFBUSxDQUFDLEdBQUc7SUFDbEIsT0FBTyxJQUFJLENBQUMsS0FBSyxDQUFDLE1BQU0sQ0FBQyxRQUFRLENBQUMsRUFBRSxDQUFDO0dBQ3RDOztFQUVELFFBQVEsR0FBRztJQUNULElBQUksQ0FBQztRQUNELENBQUMsR0FBRyxFQUFFLENBQUM7SUFDWCxLQUFLLENBQUMsR0FBRyxDQUFDLEVBQUUsQ0FBQyxHQUFHLElBQUksQ0FBQyxLQUFLLEVBQUUsRUFBRSxDQUFDLEVBQUUsRUFBRTtNQUNqQyxJQUFJLENBQUMsS0FBSyxFQUFFLEVBQUU7UUFDWixDQUFDLElBQUksSUFBSSxDQUFDO09BQ1g7TUFDRCxDQUFDLElBQUksSUFBSSxDQUFDLEdBQUcsQ0FBQyxDQUFDLENBQUMsQ0FBQyxRQUFRLEVBQUUsQ0FBQztLQUM3Qjs7SUFFRCxPQUFPLElBQUksR0FBRyxDQUFDLEdBQUcsSUFBSSxDQUFDO0dBQ3hCOztFQUVELE9BQU8sQ0FBQyxjQUFjLEVBQUU7SUFDdEIsSUFBSSxnQkFBZ0IsR0FBRyxFQUFFLENBQUM7O0lBRTFCLElBQUksQ0FBQyxDQUFDO0lBQ04sS0FBSyxDQUFDLEdBQUcsQ0FBQyxFQUFFLENBQUMsR0FBRyxjQUFjLENBQUMsTUFBTSxFQUFFLENBQUMsRUFBRSxFQUFFO01BQzFDLElBQUksZUFBZSxHQUFHLElBQUksQ0FBQyxVQUFVLEdBQUcsY0FBYyxDQUFDLENBQUMsQ0FBQyxDQUFDLElBQUksQ0FBQyxDQUFDLGNBQWMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDOztNQUVuRixLQUFLLElBQUksSUFBSSxJQUFJLGNBQWMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxVQUFVLEVBQUU7UUFDN0MsZUFBZSxHQUFHLElBQUksQ0FBQyxVQUFVLEdBQUcsSUFBSSxDQUFDLENBQUMsZUFBZSxDQUFDLENBQUM7T0FDNUQ7O01BRUQsZ0JBQWdCLEdBQUcsZ0JBQWdCLENBQUMsTUFBTSxDQUFDLGVBQWUsQ0FBQyxDQUFDO0tBQzdEOztJQUVELE9BQU8sZ0JBQWdCLENBQUM7R0FDekI7O0VBRUQsZUFBZSxDQUFDLEtBQUssRUFBRTtJQUNyQixPQUFPLEtBQUssQ0FBQyxLQUFLLENBQUM7R0FDcEI7O0VBRUQsYUFBYSxDQUFDLEtBQUssRUFBRTtJQUNuQixJQUFJLEtBQUssQ0FBQyxJQUFJLEtBQUssRUFBRSxFQUFFO01BQ3JCLE9BQU8sU0FBUyxDQUFDLGNBQWMsQ0FBQyxLQUFLLENBQUMsS0FBSyxDQUFDLENBQUM7S0FDOUMsTUFBTSxJQUFJLEtBQUssQ0FBQyxJQUFJLEtBQUssRUFBRSxFQUFFO01BQzVCLE9BQU8sU0FBUyxDQUFDLGNBQWMsQ0FBQyxLQUFLLENBQUMsS0FBSyxDQUFDLENBQUM7S0FDOUM7O0lBRUQsTUFBTSxJQUFJLEtBQUssQ0FBQyx3QkFBd0IsQ0FBQyxDQUFDO0dBQzNDOztFQUVELGlCQUFpQixDQUFDLEtBQUssRUFBRTtJQUN2QixPQUFPLEtBQUssQ0FBQyxLQUFLLENBQUMsS0FBSyxDQUFDO0dBQzFCOztFQUVELGNBQWMsQ0FBQyxLQUFLLEVBQUU7SUFDcEIsT0FBTyxTQUFTLENBQUMsV0FBVyxDQUFDLEtBQUssQ0FBQyxLQUFLLENBQUMsQ0FBQztHQUMzQzs7RUFFRCxZQUFZLENBQUMsS0FBSyxFQUFFO0lBQ2xCLE9BQU8sU0FBUyxDQUFDLFdBQVcsQ0FBQyxLQUFLLENBQUMsS0FBSyxDQUFDLENBQUM7R0FDM0M7O0VBRUQsYUFBYSxDQUFDLEtBQUssRUFBRTtJQUNuQixPQUFPLFNBQVMsQ0FBQyxZQUFZLENBQUMsS0FBSyxDQUFDLEtBQUssQ0FBQyxDQUFDO0dBQzVDOztFQUVELGFBQWEsQ0FBQyxLQUFLLEVBQUU7SUFDbkIsT0FBTyxTQUFTLENBQUMsWUFBWSxDQUFDLEtBQUssQ0FBQyxLQUFLLENBQUMsQ0FBQztHQUM1Qzs7RUFFRCxjQUFjLENBQUMsS0FBSyxFQUFFO0lBQ3BCLE9BQU8sSUFBSSxVQUFVLENBQUMsQ0FBQyxLQUFLLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDO0dBQ25DOztFQUVELGdCQUFnQixDQUFDLEtBQUssRUFBRTtJQUN0QixPQUFPLEtBQUssQ0FBQztHQUNkOztFQUVELGNBQWMsQ0FBQyxLQUFLLEVBQUU7SUFDcEIsT0FBTyxLQUFLLENBQUM7R0FDZDs7RUFFRCxXQUFXLENBQUMsS0FBSyxFQUFFO0lBQ2pCLE9BQU8sS0FBSyxDQUFDO0dBQ2Q7O0VBRUQsY0FBYyxDQUFDLEtBQUssRUFBRTtJQUNwQixPQUFPLEtBQUssQ0FBQyxPQUFPLEVBQUUsQ0FBQztHQUN4Qjs7RUFFRCxZQUFZLENBQUMsS0FBSyxFQUFFO0lBQ2xCLE9BQU8sS0FBSyxDQUFDO0dBQ2Q7O0VBRUQsWUFBWSxDQUFDLEtBQUssRUFBRTtJQUNsQixPQUFPLEtBQUssQ0FBQztHQUNkOztFQUVELE9BQU8sT0FBTyxDQUFDLEtBQUssRUFBRTtJQUNwQixPQUFPLFNBQVMsQ0FBQyxJQUFJLENBQUMsS0FBSyxFQUFFLEVBQUUsTUFBTSxFQUFFLFNBQVMsRUFBRSxNQUFNLEVBQUUsQ0FBQyxFQUFFLE1BQU0sRUFBRSxDQUFDLEVBQUUsQ0FBQyxDQUFDO0dBQzNFOztFQUVELE9BQU8sS0FBSyxDQUFDLEtBQUssRUFBRTtJQUNsQixPQUFPLFNBQVMsQ0FBQyxJQUFJLENBQUMsS0FBSyxFQUFFLEVBQUUsTUFBTSxFQUFFLE9BQU8sRUFBRSxNQUFNLEVBQUUsQ0FBQyxFQUFFLE1BQU0sRUFBRSxFQUFFLEVBQUUsQ0FBQyxDQUFDO0dBQzFFOztFQUVELE9BQU8sU0FBUyxDQUFDLEtBQUssRUFBRTtJQUN0QixPQUFPLFNBQVMsQ0FBQyxJQUFJLENBQUMsS0FBSyxFQUFFLEVBQUUsTUFBTSxFQUFFLFdBQVcsRUFBRSxNQUFNLEVBQUUsQ0FBQyxFQUFFLE1BQU0sRUFBRSxLQUFLLENBQUMsUUFBUSxFQUFFLENBQUMsQ0FBQztHQUMxRjs7RUFFRCxPQUFPLElBQUksQ0FBQyxLQUFLLEVBQUU7SUFDakIsT0FBTyxTQUFTLENBQUMsU0FBUyxDQUFDLEtBQUssQ0FBQyxDQUFDO0dBQ25DOztFQUVELE9BQU8sTUFBTSxDQUFDLEtBQUssRUFBRTtJQUNuQixPQUFPLFNBQVMsQ0FBQyxJQUFJLENBQUMsS0FBSyxFQUFFLEVBQUUsTUFBTSxFQUFFLFFBQVEsRUFBRSxNQUFNLEVBQUUsQ0FBQyxFQUFFLE1BQU0sRUFBRSxLQUFLLENBQUMsTUFBTSxFQUFFLENBQUMsQ0FBQztHQUNyRjs7RUFFRCxPQUFPLEtBQUssQ0FBQyxLQUFLLEVBQUU7SUFDbEIsT0FBTyxTQUFTLENBQUMsTUFBTSxDQUFDLEtBQUssQ0FBQyxDQUFDO0dBQ2hDOztFQUVELE9BQU8sSUFBSSxDQUFDLEtBQUssRUFBRTtJQUNqQixPQUFPLFNBQVMsQ0FBQyxJQUFJLENBQUMsS0FBSyxFQUFFLEVBQUUsTUFBTSxFQUFFLE1BQU0sRUFBRSxNQUFNLEVBQUUsQ0FBQyxFQUFFLE1BQU0sRUFBRSxLQUFLLENBQUMsTUFBTSxFQUFFLENBQUMsQ0FBQztHQUNuRjs7RUFFRCxPQUFPLEtBQUssQ0FBQyxLQUFLLEVBQUU7SUFDbEIsT0FBTyxTQUFTLENBQUMsSUFBSSxDQUFDLEtBQUssRUFBRSxFQUFFLE1BQU0sRUFBRSxPQUFPLEVBQUUsTUFBTSxFQUFFLENBQUMsRUFBRSxNQUFNLEVBQUUsS0FBSyxDQUFDLE1BQU0sR0FBRyxDQUFDLEVBQUUsQ0FBQyxDQUFDO0dBQ3hGOztFQUVELE9BQU8sS0FBSyxDQUFDLEtBQUssRUFBRTtJQUNsQixPQUFPLFNBQVMsQ0FBQyxJQUFJLENBQUMsS0FBSyxFQUFFLEVBQUUsTUFBTSxFQUFFLE9BQU8sRUFBRSxNQUFNLEVBQUUsQ0FBQyxFQUFFLE1BQU0sRUFBRSxLQUFLLENBQUMsTUFBTSxHQUFHLENBQUMsRUFBRSxDQUFDLENBQUM7R0FDeEY7O0VBRUQsT0FBTyxNQUFNLENBQUMsS0FBSyxFQUFFO0lBQ25CLE9BQU8sU0FBUyxDQUFDLElBQUksQ0FBQyxLQUFLLEVBQUUsRUFBRSxFQUFFLFFBQVEsQ0FBQyxDQUFDO0dBQzVDOztFQUVELE9BQU8sUUFBUSxDQUFDLEtBQUssRUFBRTtJQUNyQixPQUFPLFNBQVMsQ0FBQyxJQUFJLENBQUMsS0FBSyxFQUFFLEVBQUUsRUFBRSxVQUFVLENBQUMsQ0FBQztHQUM5Qzs7RUFFRCxPQUFPLE1BQU0sQ0FBQyxLQUFLLEVBQUU7SUFDbkIsT0FBTyxTQUFTLENBQUMsSUFBSSxDQUFDLEtBQUssRUFBRSxFQUFFLEVBQUUsUUFBUSxDQUFDLENBQUM7R0FDNUM7O0VBRUQsT0FBTyxHQUFHLENBQUMsS0FBSyxFQUFFO0lBQ2hCLE9BQU8sU0FBUyxDQUFDLElBQUksQ0FBQyxLQUFLLEVBQUUsRUFBRSxFQUFFLEtBQUssQ0FBQyxDQUFDO0dBQ3pDOztFQUVELE9BQU8sTUFBTSxDQUFDLEtBQUssRUFBRTtJQUNuQixPQUFPLFNBQVMsQ0FBQyxJQUFJLENBQUMsS0FBSyxFQUFFLEVBQUUsRUFBRSxRQUFRLENBQUMsQ0FBQztHQUM1Qzs7RUFFRCxPQUFPLElBQUksQ0FBQyxLQUFLLEVBQUUsS0FBSyxFQUFFO0lBQ3hCLE9BQU8sU0FBUyxDQUFDLElBQUksQ0FBQyxLQUFLLEVBQUUsRUFBRSxNQUFNLEVBQUUsS0FBSyxFQUFFLENBQUMsQ0FBQztHQUNqRDs7RUFFRCxPQUFPLElBQUksQ0FBQyxLQUFLLEVBQUUsS0FBSyxFQUFFO0lBQ3hCLE9BQU8sU0FBUyxDQUFDLElBQUksQ0FBQyxLQUFLLEVBQUUsRUFBRSxNQUFNLEVBQUUsS0FBSyxFQUFFLENBQUMsQ0FBQztHQUNqRDs7RUFFRCxPQUFPLElBQUksQ0FBQyxLQUFLLEVBQUUsR0FBRyxFQUFFLGFBQWEsR0FBRyxJQUFJLEVBQUU7SUFDNUMsSUFBSSxTQUFTLEdBQUcsS0FBSyxDQUFDOztJQUV0QixJQUFJLENBQUMsQ0FBQyxLQUFLLFlBQVksTUFBTSxDQUFDLEVBQUU7TUFDOUIsU0FBUyxHQUFHLEVBQUUsT0FBTyxFQUFFLEtBQUssRUFBRSxZQUFZLEVBQUUsRUFBRSxFQUFFLENBQUM7S0FDbEQ7O0lBRUQsU0FBUyxHQUFHLE1BQU0sQ0FBQyxNQUFNLENBQUMsU0FBUyxFQUFFLEdBQUcsQ0FBQyxDQUFDOztJQUUxQyxJQUFJLGFBQWEsRUFBRTtNQUNqQixTQUFTLENBQUMsVUFBVSxDQUFDLElBQUksQ0FBQyxhQUFhLENBQUMsQ0FBQztLQUMxQzs7SUFFRCxPQUFPLFNBQVMsQ0FBQztHQUNsQjs7RUFFRCxPQUFPLFdBQVcsQ0FBQyxHQUFHLEVBQUU7SUFDdEIsSUFBSSxJQUFJLEdBQUcsRUFBRSxDQUFDO0lBQ2QsS0FBSyxJQUFJLENBQUMsR0FBRyxDQUFDLEVBQUUsQ0FBQyxHQUFHLEdBQUcsQ0FBQyxNQUFNLEVBQUUsQ0FBQyxFQUFFLEVBQUU7TUFDbkMsSUFBSSxRQUFRLEdBQUcsR0FBRyxDQUFDLFVBQVUsQ0FBQyxDQUFDLENBQUMsQ0FBQztNQUNqQyxJQUFJLFFBQVEsR0FBRyxJQUFJLEVBQUU7UUFDbkIsSUFBSSxDQUFDLElBQUksQ0FBQyxRQUFRLENBQUMsQ0FBQztPQUNyQixNQUFNLElBQUksUUFBUSxHQUFHLEtBQUssRUFBRTtRQUMzQixJQUFJLENBQUMsSUFBSSxDQUFDLElBQUksR0FBRyxRQUFRLElBQUksQ0FBQyxFQUFFLElBQUksR0FBRyxRQUFRLEdBQUcsSUFBSSxDQUFDLENBQUM7T0FDekQsTUFBTSxJQUFJLFFBQVEsR0FBRyxNQUFNLElBQUksUUFBUSxJQUFJLE1BQU0sRUFBRTtRQUNsRCxJQUFJLENBQUMsSUFBSSxDQUFDLElBQUksR0FBRyxRQUFRLElBQUksRUFBRSxFQUFFLElBQUksR0FBRyxRQUFRLElBQUksQ0FBQyxHQUFHLElBQUksRUFBRSxJQUFJLEdBQUcsUUFBUSxHQUFHLElBQUksQ0FBQyxDQUFDO09BQ3ZGOztXQUVJO1VBQ0QsQ0FBQyxFQUFFLENBQUM7Ozs7VUFJSixRQUFRLEdBQUcsT0FBTyxHQUFHLENBQUMsQ0FBQyxRQUFRLEdBQUcsS0FBSyxDQUFDLElBQUksRUFBRSxHQUFHLEdBQUcsQ0FBQyxVQUFVLENBQUMsQ0FBQyxDQUFDLEdBQUcsS0FBSyxDQUFDLENBQUM7VUFDNUUsSUFBSSxDQUFDLElBQUksQ0FBQyxJQUFJLEdBQUcsUUFBUSxJQUFJLEVBQUUsRUFBRSxJQUFJLEdBQUcsUUFBUSxJQUFJLEVBQUUsR0FBRyxJQUFJLEVBQUUsSUFBSSxHQUFHLFFBQVEsSUFBSSxDQUFDLEdBQUcsSUFBSSxFQUFFLElBQUksR0FBRyxRQUFRLEdBQUcsSUFBSSxDQUFDLENBQUM7U0FDckg7S0FDSjtJQUNELE9BQU8sSUFBSSxDQUFDO0dBQ2I7O0VBRUQsT0FBTyxZQUFZLENBQUMsR0FBRyxFQUFFO0lBQ3ZCLElBQUksS0FBSyxHQUFHLEVBQUUsQ0FBQztJQUNmLEtBQUssSUFBSSxDQUFDLEdBQUcsQ0FBQyxFQUFFLENBQUMsR0FBRyxHQUFHLENBQUMsTUFBTSxFQUFFLENBQUMsRUFBRSxFQUFFO01BQ25DLElBQUksU0FBUyxHQUFHLEdBQUcsQ0FBQyxXQUFXLENBQUMsQ0FBQyxDQUFDLENBQUM7O01BRW5DLElBQUksU0FBUyxJQUFJLEdBQUcsRUFBRTtRQUNwQixLQUFLLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQyxDQUFDO1FBQ2QsS0FBSyxDQUFDLElBQUksQ0FBQyxTQUFTLENBQUMsQ0FBQztPQUN2QixNQUFNO1FBQ0wsS0FBSyxDQUFDLElBQUksQ0FBQyxTQUFTLElBQUksQ0FBQyxHQUFHLElBQUksQ0FBQyxDQUFDO1FBQ2xDLEtBQUssQ0FBQyxJQUFJLENBQUMsU0FBUyxHQUFHLElBQUksQ0FBQyxDQUFDO09BQzlCO0tBQ0Y7SUFDRCxPQUFPLEtBQUssQ0FBQztHQUNkOztFQUVELE9BQU8sWUFBWSxDQUFDLEdBQUcsRUFBRTtJQUN2QixJQUFJLEtBQUssR0FBRyxFQUFFLENBQUM7SUFDZixLQUFLLElBQUksQ0FBQyxHQUFHLENBQUMsRUFBRSxDQUFDLEdBQUcsR0FBRyxDQUFDLE1BQU0sRUFBRSxDQUFDLEVBQUUsRUFBRTtNQUNuQyxJQUFJLFNBQVMsR0FBRyxHQUFHLENBQUMsV0FBVyxDQUFDLENBQUMsQ0FBQyxDQUFDOztNQUVuQyxJQUFJLFNBQVMsSUFBSSxHQUFHLEVBQUU7UUFDcEIsS0FBSyxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUMsQ0FBQztRQUNkLEtBQUssQ0FBQyxJQUFJLENBQUMsQ0FBQyxDQUFDLENBQUM7UUFDZCxLQUFLLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQyxDQUFDO1FBQ2QsS0FBSyxDQUFDLElBQUksQ0FBQyxTQUFTLENBQUMsQ0FBQztPQUN2QixNQUFNO1FBQ0wsS0FBSyxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUMsQ0FBQztRQUNkLEtBQUssQ0FBQyxJQUFJLENBQUMsQ0FBQyxDQUFDLENBQUM7UUFDZCxLQUFLLENBQUMsSUFBSSxDQUFDLFNBQVMsSUFBSSxDQUFDLEdBQUcsSUFBSSxDQUFDLENBQUM7UUFDbEMsS0FBSyxDQUFDLElBQUksQ0FBQyxTQUFTLEdBQUcsSUFBSSxDQUFDLENBQUM7T0FDOUI7S0FDRjtJQUNELE9BQU8sS0FBSyxDQUFDO0dBQ2Q7OztFQUdELE9BQU8sY0FBYyxDQUFDLENBQUMsRUFBRTtJQUN2QixJQUFJLEtBQUssR0FBRyxFQUFFLENBQUM7O0lBRWYsSUFBSSxHQUFHLEdBQUcsSUFBSSxXQUFXLENBQUMsQ0FBQyxDQUFDLENBQUM7SUFDN0IsSUFBSSxZQUFZLENBQUMsR0FBRyxDQUFDLENBQUMsQ0FBQyxDQUFDLEdBQUcsQ0FBQyxDQUFDOztJQUU3QixJQUFJLFVBQVUsR0FBRyxJQUFJLFdBQVcsQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQzs7SUFFekMsS0FBSyxDQUFDLElBQUksQ0FBQyxVQUFVLElBQUksRUFBRSxHQUFHLElBQUksQ0FBQyxDQUFDO0lBQ3BDLEtBQUssQ0FBQyxJQUFJLENBQUMsVUFBVSxJQUFJLEVBQUUsR0FBRyxJQUFJLENBQUMsQ0FBQztJQUNwQyxLQUFLLENBQUMsSUFBSSxDQUFDLFVBQVUsSUFBSSxDQUFDLEdBQUcsSUFBSSxDQUFDLENBQUM7SUFDbkMsS0FBSyxDQUFDLElBQUksQ0FBQyxVQUFVLEdBQUcsSUFBSSxDQUFDLENBQUM7O0lBRTlCLE9BQU8sS0FBSyxDQUFDO0dBQ2Q7O0VBRUQsT0FBTyxjQUFjLENBQUMsQ0FBQyxFQUFFO0lBQ3ZCLElBQUksS0FBSyxHQUFHLEVBQUUsQ0FBQzs7SUFFZixJQUFJLEdBQUcsR0FBRyxJQUFJLFdBQVcsQ0FBQyxDQUFDLENBQUMsQ0FBQztJQUM3QixJQUFJLFlBQVksQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDLENBQUMsR0FBRyxDQUFDLENBQUM7O0lBRTdCLElBQUksV0FBVyxHQUFHLElBQUksV0FBVyxDQUFDLEdBQUcsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDO0lBQzFDLElBQUksV0FBVyxHQUFHLElBQUksV0FBVyxDQUFDLEdBQUcsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDOztJQUUxQyxLQUFLLENBQUMsSUFBSSxDQUFDLFdBQVcsSUFBSSxFQUFFLEdBQUcsSUFBSSxDQUFDLENBQUM7SUFDckMsS0FBSyxDQUFDLElBQUksQ0FBQyxXQUFXLElBQUksRUFBRSxHQUFHLElBQUksQ0FBQyxDQUFDO0lBQ3JDLEtBQUssQ0FBQyxJQUFJLENBQUMsV0FBVyxJQUFJLENBQUMsR0FBRyxJQUFJLENBQUMsQ0FBQztJQUNwQyxLQUFLLENBQUMsSUFBSSxDQUFDLFdBQVcsR0FBRyxJQUFJLENBQUMsQ0FBQzs7SUFFL0IsS0FBSyxDQUFDLElBQUksQ0FBQyxXQUFXLElBQUksRUFBRSxHQUFHLElBQUksQ0FBQyxDQUFDO0lBQ3JDLEtBQUssQ0FBQyxJQUFJLENBQUMsV0FBVyxJQUFJLEVBQUUsR0FBRyxJQUFJLENBQUMsQ0FBQztJQUNyQyxLQUFLLENBQUMsSUFBSSxDQUFDLFdBQVcsSUFBSSxDQUFDLEdBQUcsSUFBSSxDQUFDLENBQUM7SUFDcEMsS0FBSyxDQUFDLElBQUksQ0FBQyxXQUFXLEdBQUcsSUFBSSxDQUFDLENBQUM7O0lBRS9CLE9BQU8sS0FBSyxDQUFDO0dBQ2Q7Q0FDRjs7QUN2U00sTUFBTSxRQUFRLENBQUM7O0VBRXBCLFdBQVcsQ0FBQyxhQUFhLEdBQUcsTUFBTSxDQUFDLEdBQUcsQ0FBQyx1QkFBdUIsQ0FBQyxFQUFFO0lBQy9ELElBQUksQ0FBQyxhQUFhLEdBQUcsYUFBYSxDQUFDO0dBQ3BDO0NBQ0Y7O0FBRUQsQUFBTyxNQUFNLFFBQVEsQ0FBQztFQUNwQixXQUFXLEdBQUcsRUFBRTtDQUNqQjs7QUFFRCxBQUFPLE1BQU0sVUFBVSxDQUFDOztFQUV0QixXQUFXLENBQUMsTUFBTSxFQUFFO0lBQ2xCLElBQUksQ0FBQyxNQUFNLEdBQUcsTUFBTSxDQUFDO0dBQ3RCO0NBQ0Y7O0FBRUQsQUFBTyxNQUFNLE9BQU8sQ0FBQzs7RUFFbkIsV0FBVyxDQUFDLEtBQUssRUFBRTtJQUNqQixJQUFJLENBQUMsS0FBSyxHQUFHLEtBQUssQ0FBQztHQUNwQjtDQUNGOztBQUVELEFBQU8sTUFBTSxRQUFRLENBQUM7O0VBRXBCLFdBQVcsQ0FBQyxJQUFJLEdBQUcsSUFBSSxFQUFFLElBQUksR0FBRyxJQUFJLEVBQUU7SUFDcEMsSUFBSSxDQUFDLElBQUksR0FBRyxJQUFJLENBQUM7SUFDakIsSUFBSSxDQUFDLElBQUksR0FBRyxJQUFJLENBQUM7R0FDbEI7Q0FDRjs7QUFFRCxBQUFPLE1BQU0sSUFBSSxDQUFDOztFQUVoQixXQUFXLENBQUMsSUFBSSxFQUFFLFVBQVUsR0FBRyxFQUFFLEVBQUU7SUFDakMsSUFBSSxDQUFDLElBQUksR0FBRyxJQUFJLENBQUM7SUFDakIsSUFBSSxDQUFDLFVBQVUsR0FBRyxVQUFVLENBQUM7R0FDOUI7Q0FDRjs7QUFFRCxBQUFPLE1BQU0sS0FBSyxDQUFDOztFQUVqQixXQUFXLENBQUMsS0FBSyxFQUFFO0lBQ2pCLElBQUksQ0FBQyxLQUFLLEdBQUcsS0FBSyxDQUFDO0dBQ3BCO0NBQ0Y7O0FBRUQsQUFBTyxNQUFNLGNBQWMsQ0FBQzs7RUFFMUIsV0FBVyxDQUFDLEdBQUcsTUFBTSxFQUFFO0lBQ3JCLElBQUksQ0FBQyxNQUFNLEdBQUcsTUFBTSxDQUFDO0dBQ3RCOztFQUVELE1BQU0sR0FBRztJQUNQLE9BQU8sTUFBTSxDQUFDLE1BQU0sQ0FBQztHQUN0Qjs7RUFFRCxRQUFRLEdBQUc7SUFDVCxPQUFPLElBQUksQ0FBQyxTQUFTLEVBQUUsR0FBRyxDQUFDLENBQUM7R0FDN0I7O0VBRUQsU0FBUyxHQUFHO0lBQ1YsSUFBSSxDQUFDLEdBQUcsQ0FBQyxDQUFDOztJQUVWLEtBQUssSUFBSSxHQUFHLElBQUksSUFBSSxDQUFDLE1BQU0sRUFBRTtNQUMzQixDQUFDLEdBQUcsQ0FBQyxHQUFHLEdBQUcsQ0FBQyxJQUFJLEdBQUcsR0FBRyxDQUFDLElBQUksR0FBRyxDQUFDLENBQUM7S0FDakM7O0lBRUQsT0FBTyxDQUFDLENBQUM7R0FDVjs7RUFFRCxRQUFRLENBQUMsS0FBSyxFQUFFO0lBQ2QsT0FBTyxJQUFJLENBQUMsTUFBTSxDQUFDLEtBQUssQ0FBQyxDQUFDO0dBQzNCOztFQUVELGNBQWMsQ0FBQyxLQUFLLEVBQUU7SUFDcEIsSUFBSSxHQUFHLEdBQUcsSUFBSSxDQUFDLFFBQVEsQ0FBQyxLQUFLLENBQUMsQ0FBQztJQUMvQixPQUFPLEdBQUcsQ0FBQyxJQUFJLEdBQUcsR0FBRyxDQUFDLElBQUksQ0FBQztHQUM1Qjs7RUFFRCxjQUFjLENBQUMsS0FBSyxFQUFFO0lBQ3BCLE9BQU8sSUFBSSxDQUFDLFFBQVEsQ0FBQyxLQUFLLENBQUMsQ0FBQyxJQUFJLENBQUM7R0FDbEM7Q0FDRjs7QUFFRCxBQUFPLFNBQVMsUUFBUSxDQUFDLGFBQWEsR0FBRyxNQUFNLENBQUMsR0FBRyxDQUFDLHVCQUF1QixDQUFDLEVBQUU7RUFDNUUsT0FBTyxJQUFJLFFBQVEsQ0FBQyxhQUFhLENBQUMsQ0FBQztDQUNwQzs7QUFFRCxBQUFPLFNBQVMsUUFBUSxHQUFHO0VBQ3pCLE9BQU8sSUFBSSxRQUFRLEVBQUUsQ0FBQztDQUN2Qjs7QUFFRCxBQUFPLFNBQVMsVUFBVSxDQUFDLE1BQU0sRUFBRTtFQUNqQyxPQUFPLElBQUksVUFBVSxDQUFDLE1BQU0sQ0FBQyxDQUFDO0NBQy9COztBQUVELEFBQU8sU0FBUyxPQUFPLENBQUMsS0FBSyxFQUFFO0VBQzdCLE9BQU8sSUFBSSxPQUFPLENBQUMsS0FBSyxDQUFDLENBQUM7Q0FDM0I7O0FBRUQsQUFBTyxTQUFTLFFBQVEsQ0FBQyxJQUFJLEdBQUcsSUFBSSxFQUFFLElBQUksR0FBRyxJQUFJLEVBQUU7RUFDakQsT0FBTyxJQUFJLFFBQVEsQ0FBQyxJQUFJLEVBQUUsSUFBSSxDQUFDLENBQUM7Q0FDakM7O0FBRUQsQUFBTyxTQUFTLElBQUksQ0FBQyxJQUFJLEVBQUUsVUFBVSxHQUFHLEVBQUUsRUFBRTtFQUMxQyxPQUFPLElBQUksSUFBSSxDQUFDLElBQUksRUFBRSxVQUFVLENBQUMsQ0FBQztDQUNuQzs7QUFFRCxBQUFPLFNBQVMsS0FBSyxDQUFDLEtBQUssRUFBRTtFQUMzQixPQUFPLElBQUksS0FBSyxDQUFDLEtBQUssQ0FBQyxDQUFDO0NBQ3pCOztBQUVELEFBQU8sU0FBUyxjQUFjLENBQUMsR0FBRyxNQUFNLEVBQUU7RUFDeEMsT0FBTyxJQUFJLGNBQWMsQ0FBQyxHQUFHLE1BQU0sQ0FBQyxDQUFDO0NBQ3RDOztBQ2pIRCxTQUFTLFNBQVMsQ0FBQyxLQUFLLEVBQUU7RUFDeEIsT0FBTyxPQUFPLEtBQUssS0FBSyxRQUFRLENBQUM7Q0FDbEM7O0FBRUQsU0FBUyxTQUFTLENBQUMsS0FBSyxFQUFFO0VBQ3hCLE9BQU8sT0FBTyxLQUFLLEtBQUssUUFBUSxDQUFDO0NBQ2xDOztBQUVELFNBQVMsVUFBVSxDQUFDLEtBQUssRUFBRTtFQUN6QixPQUFPLE9BQU8sS0FBSyxLQUFLLFNBQVMsQ0FBQztDQUNuQzs7QUFFRCxTQUFTLFNBQVMsQ0FBQyxLQUFLLEVBQUU7RUFDeEIsT0FBTyxPQUFPLEtBQUssS0FBSyxRQUFRLENBQUM7Q0FDbEM7O0FBRUQsU0FBUyxPQUFPLENBQUMsS0FBSyxFQUFFO0VBQ3RCLE9BQU8sS0FBSyxLQUFLLElBQUksQ0FBQztDQUN2Qjs7QUFFRCxTQUFTLFlBQVksQ0FBQyxLQUFLLEVBQUU7RUFDM0IsT0FBTyxPQUFPLEtBQUssS0FBSyxXQUFXLENBQUM7Q0FDckM7O0FBRUQsU0FBUyxXQUFXLENBQUMsS0FBSyxFQUFFO0VBQzFCLE9BQU8sTUFBTSxDQUFDLFNBQVMsQ0FBQyxRQUFRLENBQUMsSUFBSSxDQUFDLEtBQUssQ0FBQyxJQUFJLG1CQUFtQixDQUFDO0NBQ3JFOztBQUVELFNBQVMsV0FBVyxDQUFDLEtBQUssRUFBRTtFQUMxQixPQUFPLEtBQUssWUFBWSxRQUFRLENBQUM7Q0FDbEM7O0FBRUQsU0FBUyxXQUFXLENBQUMsS0FBSyxFQUFFO0VBQzFCLE9BQU8sS0FBSyxZQUFZLFFBQVEsQ0FBQztDQUNsQzs7QUFFRCxTQUFTLFdBQVcsQ0FBQyxLQUFLLEVBQUU7RUFDMUIsT0FBTyxLQUFLLFlBQVksUUFBUSxDQUFDO0NBQ2xDOztBQUVELFNBQVMsVUFBVSxDQUFDLEtBQUssRUFBRTtFQUN6QixPQUFPLEtBQUssWUFBWSxPQUFPLENBQUM7Q0FDakM7O0FBRUQsU0FBUyxPQUFPLENBQUMsS0FBSyxFQUFFO0VBQ3RCLE9BQU8sS0FBSyxZQUFZLElBQUksQ0FBQztDQUM5Qjs7QUFFRCxTQUFTLGFBQWEsQ0FBQyxLQUFLLEVBQUU7RUFDNUIsT0FBTyxLQUFLLFlBQVksVUFBVSxDQUFDO0NBQ3BDOztBQUVELFNBQVMsUUFBUSxDQUFDLEtBQUssRUFBRTtFQUN2QixPQUFPLEtBQUssWUFBWSxLQUFLLENBQUM7Q0FDL0I7O0FBRUQsU0FBUyxTQUFTLENBQUMsS0FBSyxFQUFFO0VBQ3hCLE9BQU8sT0FBTyxLQUFLLEtBQUssUUFBUSxDQUFDO0NBQ2xDOztBQUVELFNBQVMsUUFBUSxDQUFDLEtBQUssRUFBRTtFQUN2QixPQUFPLEtBQUssQ0FBQyxPQUFPLENBQUMsS0FBSyxDQUFDLENBQUM7Q0FDN0I7O0FBRUQsU0FBUyxZQUFZLENBQUMsS0FBSyxFQUFFO0VBQzNCLE9BQU8sS0FBSyxZQUFZLGNBQWMsQ0FBQztDQUN4Qzs7QUFFRCxhQUFlO0VBQ2IsU0FBUztFQUNULFNBQVM7RUFDVCxVQUFVO0VBQ1YsU0FBUztFQUNULE9BQU87RUFDUCxZQUFZO0VBQ1osV0FBVztFQUNYLFdBQVc7RUFDWCxXQUFXO0VBQ1gsV0FBVztFQUNYLFVBQVU7RUFDVixPQUFPO0VBQ1AsYUFBYTtFQUNiLFFBQVE7RUFDUixTQUFTO0VBQ1QsUUFBUTtFQUNSLFlBQVk7Q0FDYixDQUFDOztBQ25GRixTQUFTLGFBQWEsQ0FBQyxPQUFPLEVBQUU7RUFDOUIsT0FBTyxVQUFVLEtBQUssRUFBRTtJQUN0QixPQUFPLE1BQU0sQ0FBQyxTQUFTLENBQUMsS0FBSyxDQUFDLElBQUksS0FBSyxLQUFLLE9BQU8sQ0FBQztHQUNyRCxDQUFDO0NBQ0g7O0FBRUQsU0FBUyxhQUFhLENBQUMsT0FBTyxFQUFFO0VBQzlCLE9BQU8sVUFBVSxLQUFLLEVBQUU7SUFDdEIsT0FBTyxNQUFNLENBQUMsU0FBUyxDQUFDLEtBQUssQ0FBQyxJQUFJLEtBQUssS0FBSyxPQUFPLENBQUM7R0FDckQsQ0FBQztDQUNIOztBQUVELFNBQVMsYUFBYSxDQUFDLE9BQU8sRUFBRTtFQUM5QixPQUFPLFVBQVUsS0FBSyxFQUFFO0lBQ3RCLE9BQU8sTUFBTSxDQUFDLFNBQVMsQ0FBQyxLQUFLLENBQUMsSUFBSSxLQUFLLEtBQUssT0FBTyxDQUFDO0dBQ3JELENBQUM7Q0FDSDs7QUFFRCxTQUFTLGNBQWMsQ0FBQyxPQUFPLEVBQUU7RUFDL0IsT0FBTyxVQUFVLEtBQUssRUFBRTtJQUN0QixPQUFPLE1BQU0sQ0FBQyxVQUFVLENBQUMsS0FBSyxDQUFDLElBQUksS0FBSyxLQUFLLE9BQU8sQ0FBQztHQUN0RCxDQUFDO0NBQ0g7O0FBRUQsU0FBUyxlQUFlLENBQUMsT0FBTyxFQUFFO0VBQ2hDLE9BQU8sVUFBVSxLQUFLLEVBQUU7SUFDdEIsT0FBTyxNQUFNLENBQUMsV0FBVyxDQUFDLEtBQUssQ0FBQyxJQUFJLEtBQUssS0FBSyxPQUFPLENBQUM7R0FDdkQsQ0FBQztDQUNIOztBQUVELFNBQVMsV0FBVyxDQUFDLE9BQU8sRUFBRTtFQUM1QixPQUFPLFVBQVUsS0FBSyxFQUFFO0lBQ3RCLE9BQU8sTUFBTSxDQUFDLE9BQU8sQ0FBQyxLQUFLLENBQUMsQ0FBQztHQUM5QixDQUFDO0NBQ0g7O0FBRUQsU0FBUyxZQUFZLENBQUMsT0FBTyxFQUFFO0VBQzdCLE9BQU8sVUFBVSxLQUFLLEVBQUUsSUFBSSxFQUFFO0lBQzVCLElBQUksT0FBTyxLQUFLLEtBQUssT0FBTyxPQUFPLENBQUMsS0FBSyxJQUFJLEtBQUssS0FBSyxPQUFPLENBQUMsS0FBSyxFQUFFO01BQ3BFLElBQUksQ0FBQyxJQUFJLENBQUMsS0FBSyxDQUFDLENBQUM7TUFDakIsT0FBTyxJQUFJLENBQUM7S0FDYjs7SUFFRCxPQUFPLEtBQUssQ0FBQztHQUNkLENBQUM7Q0FDSDs7QUFFRCxTQUFTLGVBQWUsR0FBRztFQUN6QixPQUFPLFlBQVk7SUFDakIsT0FBTyxJQUFJLENBQUM7R0FDYixDQUFDO0NBQ0g7O0FBRUQsU0FBUyxlQUFlLEdBQUc7RUFDekIsT0FBTyxVQUFVLEtBQUssRUFBRSxJQUFJLEVBQUU7SUFDNUIsSUFBSSxDQUFDLElBQUksQ0FBQyxLQUFLLENBQUMsQ0FBQztJQUNqQixPQUFPLElBQUksQ0FBQztHQUNiLENBQUM7Q0FDSDs7QUFFRCxTQUFTLGVBQWUsQ0FBQyxPQUFPLEVBQUU7RUFDaEMsTUFBTSxXQUFXLEdBQUcsVUFBVSxDQUFDLE9BQU8sQ0FBQyxJQUFJLENBQUMsQ0FBQztFQUM3QyxNQUFNLFdBQVcsR0FBRyxVQUFVLENBQUMsT0FBTyxDQUFDLElBQUksQ0FBQyxDQUFDOztFQUU3QyxPQUFPLFVBQVUsS0FBSyxFQUFFLElBQUksRUFBRTtJQUM1QixJQUFJLENBQUMsTUFBTSxDQUFDLFFBQVEsQ0FBQyxLQUFLLENBQUMsSUFBSSxLQUFLLENBQUMsTUFBTSxHQUFHLENBQUMsRUFBRTtNQUMvQyxPQUFPLEtBQUssQ0FBQztLQUNkOztJQUVELE1BQU0sSUFBSSxHQUFHLEtBQUssQ0FBQyxDQUFDLENBQUMsQ0FBQztJQUN0QixNQUFNLElBQUksR0FBRyxLQUFLLENBQUMsS0FBSyxDQUFDLENBQUMsQ0FBQyxDQUFDOztJQUU1QixJQUFJLFdBQVcsQ0FBQyxJQUFJLEVBQUUsSUFBSSxDQUFDLElBQUksV0FBVyxDQUFDLElBQUksRUFBRSxJQUFJLENBQUMsRUFBRTtNQUN0RCxPQUFPLElBQUksQ0FBQztLQUNiO0dBQ0YsQ0FBQztDQUNIOztBQUVELFNBQVMsY0FBYyxDQUFDLE9BQU8sRUFBRTtFQUMvQixNQUFNLE9BQU8sR0FBRyxVQUFVLENBQUMsT0FBTyxDQUFDLEtBQUssQ0FBQyxDQUFDOztFQUUxQyxPQUFPLFVBQVUsS0FBSyxFQUFFLElBQUksRUFBRTtJQUM1QixJQUFJLE9BQU8sQ0FBQyxLQUFLLEVBQUUsSUFBSSxDQUFDLEVBQUU7TUFDeEIsSUFBSSxDQUFDLElBQUksQ0FBQyxLQUFLLENBQUMsQ0FBQztNQUNqQixPQUFPLElBQUksQ0FBQztLQUNiOztJQUVELE9BQU8sS0FBSyxDQUFDO0dBQ2QsQ0FBQztDQUNIOztBQUVELFNBQVMsaUJBQWlCLENBQUMsT0FBTyxFQUFFO0VBQ2xDLE1BQU0sTUFBTSxHQUFHLE9BQU8sQ0FBQyxNQUFNLENBQUM7O0VBRTlCLE9BQU8sVUFBVSxLQUFLLEVBQUUsSUFBSSxFQUFFO0lBQzVCLElBQUksTUFBTSxDQUFDLFNBQVMsQ0FBQyxLQUFLLENBQUMsSUFBSSxLQUFLLENBQUMsVUFBVSxDQUFDLE1BQU0sQ0FBQyxFQUFFO01BQ3ZELElBQUksQ0FBQyxJQUFJLENBQUMsS0FBSyxDQUFDLFNBQVMsQ0FBQyxNQUFNLENBQUMsTUFBTSxDQUFDLENBQUMsQ0FBQztNQUMxQyxPQUFPLElBQUksQ0FBQztLQUNiOztJQUVELE9BQU8sS0FBSyxDQUFDO0dBQ2QsQ0FBQztDQUNIOztBQUVELFNBQVMsV0FBVyxDQUFDLE9BQU8sRUFBRTtFQUM1QixPQUFPLFVBQVUsS0FBSyxFQUFFLElBQUksRUFBRTtJQUM1QixJQUFJLEtBQUssWUFBWSxPQUFPLENBQUMsSUFBSSxFQUFFO01BQ2pDLE1BQU0sT0FBTyxHQUFHLFVBQVUsQ0FBQyxPQUFPLENBQUMsVUFBVSxDQUFDLENBQUM7TUFDL0MsT0FBTyxPQUFPLENBQUMsS0FBSyxFQUFFLElBQUksQ0FBQyxJQUFJLElBQUksQ0FBQyxJQUFJLENBQUMsS0FBSyxDQUFDLEdBQUcsQ0FBQyxDQUFDO0tBQ3JEOztJQUVELE9BQU8sS0FBSyxDQUFDO0dBQ2QsQ0FBQztDQUNIOztBQUVELFNBQVMsWUFBWSxDQUFDLE9BQU8sRUFBRTtFQUM3QixNQUFNLE9BQU8sR0FBRyxPQUFPLENBQUMsR0FBRyxDQUFDLENBQUMsSUFBSSxVQUFVLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQzs7RUFFaEQsT0FBTyxVQUFVLEtBQUssRUFBRSxJQUFJLEVBQUU7SUFDNUIsSUFBSSxDQUFDLE1BQU0sQ0FBQyxRQUFRLENBQUMsS0FBSyxDQUFDLElBQUksS0FBSyxDQUFDLE1BQU0sSUFBSSxPQUFPLENBQUMsTUFBTSxFQUFFO01BQzdELE9BQU8sS0FBSyxDQUFDO0tBQ2Q7O0lBRUQsT0FBTyxLQUFLLENBQUMsS0FBSyxDQUFDLFVBQVUsQ0FBQyxFQUFFLENBQUMsRUFBRTtNQUNqQyxPQUFPLE9BQU8sQ0FBQyxDQUFDLENBQUMsQ0FBQyxLQUFLLENBQUMsQ0FBQyxDQUFDLEVBQUUsSUFBSSxDQUFDLENBQUM7S0FDbkMsQ0FBQyxDQUFDO0dBQ0osQ0FBQztDQUNIOztBQUVELFNBQVMsYUFBYSxDQUFDLE9BQU8sRUFBRTtFQUM5QixJQUFJLE9BQU8sR0FBRyxFQUFFLENBQUM7O0VBRWpCLEtBQUssSUFBSSxHQUFHLElBQUksTUFBTSxDQUFDLElBQUksQ0FBQyxPQUFPLENBQUMsQ0FBQyxNQUFNLENBQUMsTUFBTSxDQUFDLHFCQUFxQixDQUFDLE9BQU8sQ0FBQyxDQUFDLEVBQUU7SUFDbEYsT0FBTyxDQUFDLEdBQUcsQ0FBQyxHQUFHLFVBQVUsQ0FBQyxPQUFPLENBQUMsR0FBRyxDQUFDLENBQUMsQ0FBQztHQUN6Qzs7RUFFRCxPQUFPLFVBQVUsS0FBSyxFQUFFLElBQUksRUFBRTtJQUM1QixJQUFJLENBQUMsTUFBTSxDQUFDLFNBQVMsQ0FBQyxLQUFLLENBQUMsSUFBSSxPQUFPLENBQUMsTUFBTSxHQUFHLEtBQUssQ0FBQyxNQUFNLEVBQUU7TUFDN0QsT0FBTyxLQUFLLENBQUM7S0FDZDs7SUFFRCxLQUFLLElBQUksR0FBRyxJQUFJLE1BQU0sQ0FBQyxJQUFJLENBQUMsT0FBTyxDQUFDLENBQUMsTUFBTSxDQUFDLE1BQU0sQ0FBQyxxQkFBcUIsQ0FBQyxPQUFPLENBQUMsQ0FBQyxFQUFFO01BQ2xGLElBQUksQ0FBQyxDQUFDLEdBQUcsSUFBSSxLQUFLLENBQUMsSUFBSSxDQUFDLE9BQU8sQ0FBQyxHQUFHLENBQUMsQ0FBQyxLQUFLLENBQUMsR0FBRyxDQUFDLEVBQUUsSUFBSSxDQUFDLEVBQUU7UUFDdEQsT0FBTyxLQUFLLENBQUM7T0FDZDtLQUNGOztJQUVELE9BQU8sSUFBSSxDQUFDO0dBQ2IsQ0FBQztDQUNIOztBQUVELFNBQVMsZ0JBQWdCLENBQUMsT0FBTyxFQUFFO0VBQ2pDLElBQUksZ0JBQWdCLEdBQUcsRUFBRSxDQUFDOztFQUUxQixLQUFLLElBQUksa0JBQWtCLElBQUksT0FBTyxDQUFDLE1BQU0sRUFBRTtJQUM3QyxJQUFJLE1BQU0sQ0FBQyxXQUFXLENBQUMsa0JBQWtCLENBQUMsS0FBSyxDQUFDLEVBQUU7TUFDaEQsSUFBSSxJQUFJLEdBQUcsT0FBTyxDQUFDLGtCQUFrQixDQUFDLElBQUksRUFBRSxrQkFBa0IsQ0FBQyxJQUFJLENBQUMsQ0FBQztNQUNyRSxTQUFTLENBQUMsZ0JBQWdCLEVBQUUsSUFBSSxDQUFDLENBQUM7S0FDbkMsTUFBTTtNQUNMLGdCQUFnQixHQUFHLGdCQUFnQixDQUFDLE1BQU0sQ0FBQyxJQUFJLFNBQVMsQ0FBQyxrQkFBa0IsQ0FBQyxDQUFDLEtBQUssQ0FBQyxDQUFDO0tBQ3JGO0dBQ0Y7O0VBRUQsSUFBSSxhQUFhLEdBQUcsT0FBTyxDQUFDLE1BQU0sQ0FBQzs7RUFFbkMsT0FBTyxVQUFVLEtBQUssRUFBRSxJQUFJLEVBQUU7SUFDNUIsSUFBSSxPQUFPLEdBQUcsSUFBSSxDQUFDOztJQUVuQixJQUFJLENBQUMsTUFBTSxDQUFDLFNBQVMsQ0FBQyxLQUFLLENBQUMsSUFBSSxDQUFDLENBQUMsS0FBSyxZQUFZLFNBQVMsQ0FBQyxFQUFFO01BQzdELE9BQU8sS0FBSyxDQUFDO0tBQ2Q7O0lBRUQsSUFBSSxNQUFNLENBQUMsU0FBUyxDQUFDLEtBQUssQ0FBQyxFQUFFO01BQzNCLE9BQU8sR0FBRyxJQUFJLFNBQVMsQ0FBQyxTQUFTLENBQUMsTUFBTSxDQUFDLEtBQUssQ0FBQyxDQUFDLENBQUM7S0FDbEQsTUFBTTtNQUNMLE9BQU8sR0FBRyxLQUFLLENBQUM7S0FDakI7O0lBRUQsSUFBSSxjQUFjLEdBQUcsQ0FBQyxDQUFDOztJQUV2QixLQUFLLElBQUksQ0FBQyxHQUFHLENBQUMsRUFBRSxDQUFDLEdBQUcsYUFBYSxDQUFDLE1BQU0sRUFBRSxDQUFDLEVBQUUsRUFBRTtNQUM3QyxJQUFJLGtCQUFrQixHQUFHLGFBQWEsQ0FBQyxDQUFDLENBQUMsQ0FBQzs7TUFFMUMsSUFBSSxNQUFNLENBQUMsV0FBVyxDQUFDLGtCQUFrQixDQUFDLEtBQUssQ0FBQyxJQUFJLGtCQUFrQixDQUFDLElBQUksSUFBSSxRQUFRLElBQUksa0JBQWtCLENBQUMsSUFBSSxLQUFLLFNBQVMsSUFBSSxDQUFDLEdBQUcsYUFBYSxDQUFDLE1BQU0sR0FBRyxDQUFDLEVBQUU7UUFDaEssTUFBTSxJQUFJLEtBQUssQ0FBQyw0RUFBNEUsQ0FBQyxDQUFDO09BQy9GOztNQUVELElBQUksSUFBSSxHQUFHLENBQUMsQ0FBQztNQUNiLElBQUksZ0JBQWdCLEdBQUcsRUFBRSxDQUFDO01BQzFCLElBQUkseUJBQXlCLEdBQUcsRUFBRSxDQUFDO01BQ25DLElBQUksR0FBRyxPQUFPLENBQUMsa0JBQWtCLENBQUMsSUFBSSxFQUFFLGtCQUFrQixDQUFDLElBQUksQ0FBQyxDQUFDOztNQUVqRSxJQUFJLENBQUMsS0FBSyxhQUFhLENBQUMsTUFBTSxHQUFHLENBQUMsRUFBRTtRQUNsQyxnQkFBZ0IsR0FBRyxPQUFPLENBQUMsS0FBSyxDQUFDLEtBQUssQ0FBQyxjQUFjLENBQUMsQ0FBQztRQUN2RCx5QkFBeUIsR0FBRyxnQkFBZ0IsQ0FBQyxLQUFLLENBQUMsY0FBYyxDQUFDLENBQUM7T0FDcEUsTUFBTTtRQUNMLGdCQUFnQixHQUFHLE9BQU8sQ0FBQyxLQUFLLENBQUMsS0FBSyxDQUFDLGNBQWMsRUFBRSxjQUFjLEdBQUcsSUFBSSxDQUFDLENBQUM7UUFDOUUseUJBQXlCLEdBQUcsZ0JBQWdCLENBQUMsS0FBSyxDQUFDLGNBQWMsRUFBRSxjQUFjLEdBQUcsSUFBSSxDQUFDLENBQUM7T0FDM0Y7O01BRUQsSUFBSSxNQUFNLENBQUMsV0FBVyxDQUFDLGtCQUFrQixDQUFDLEtBQUssQ0FBQyxFQUFFO1FBQ2hELFFBQVEsa0JBQWtCLENBQUMsSUFBSTtVQUM3QixLQUFLLFNBQVM7WUFDWixJQUFJLGtCQUFrQixDQUFDLFVBQVUsSUFBSSxrQkFBa0IsQ0FBQyxVQUFVLENBQUMsT0FBTyxDQUFDLFFBQVEsQ0FBQyxJQUFJLENBQUMsQ0FBQyxFQUFFO2NBQzFGLElBQUksQ0FBQyxJQUFJLENBQUMsSUFBSSxTQUFTLENBQUMsQ0FBQyxnQkFBZ0IsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQzthQUNwRCxNQUFNO2NBQ0wsSUFBSSxDQUFDLElBQUksQ0FBQyxJQUFJLFVBQVUsQ0FBQyxDQUFDLGdCQUFnQixDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDO2FBQ3JEO1lBQ0QsTUFBTTs7VUFFUixLQUFLLE9BQU87WUFDVixJQUFJLElBQUksS0FBSyxFQUFFLEVBQUU7Y0FDZixJQUFJLENBQUMsSUFBSSxDQUFDLFlBQVksQ0FBQyxJQUFJLENBQUMsZ0JBQWdCLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDO2FBQ25ELE1BQU0sSUFBSSxJQUFJLEtBQUssRUFBRSxFQUFFO2NBQ3RCLElBQUksQ0FBQyxJQUFJLENBQUMsWUFBWSxDQUFDLElBQUksQ0FBQyxnQkFBZ0IsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUM7YUFDbkQsTUFBTTtjQUNMLE9BQU8sS0FBSyxDQUFDO2FBQ2Q7WUFDRCxNQUFNOztVQUVSLEtBQUssV0FBVztZQUNkLElBQUksQ0FBQyxJQUFJLENBQUMsZUFBZSxDQUFDLGdCQUFnQixDQUFDLENBQUMsQ0FBQztZQUM3QyxNQUFNOztVQUVSLEtBQUssUUFBUTtZQUNYLElBQUksQ0FBQyxJQUFJLENBQUMsTUFBTSxDQUFDLFlBQVksQ0FBQyxLQUFLLENBQUMsSUFBSSxFQUFFLElBQUksVUFBVSxDQUFDLGdCQUFnQixDQUFDLENBQUMsQ0FBQyxDQUFDO1lBQzdFLE1BQU07O1VBRVIsS0FBSyxNQUFNO1lBQ1QsSUFBSSxDQUFDLElBQUksQ0FBQyxNQUFNLENBQUMsWUFBWSxDQUFDLEtBQUssQ0FBQyxJQUFJLEVBQUUsSUFBSSxVQUFVLENBQUMsZ0JBQWdCLENBQUMsQ0FBQyxDQUFDLENBQUM7WUFDN0UsTUFBTTs7VUFFUixLQUFLLE9BQU87WUFDVixJQUFJLENBQUMsSUFBSSxDQUFDLE1BQU0sQ0FBQyxZQUFZLENBQUMsS0FBSyxDQUFDLElBQUksRUFBRSxJQUFJLFdBQVcsQ0FBQyxnQkFBZ0IsQ0FBQyxDQUFDLENBQUMsQ0FBQztZQUM5RSxNQUFNOztVQUVSLEtBQUssT0FBTztZQUNWLElBQUksQ0FBQyxJQUFJLENBQUMsTUFBTSxDQUFDLFlBQVksQ0FBQyxLQUFLLENBQUMsSUFBSSxFQUFFLElBQUksV0FBVyxDQUFDLGdCQUFnQixDQUFDLENBQUMsQ0FBQyxDQUFDO1lBQzlFLE1BQU07O1VBRVI7WUFDRSxPQUFPLEtBQUssQ0FBQztTQUNoQjtPQUNGLE1BQU0sSUFBSSxDQUFDLFdBQVcsQ0FBQyxnQkFBZ0IsRUFBRSx5QkFBeUIsQ0FBQyxFQUFFO1FBQ3BFLE9BQU8sS0FBSyxDQUFDO09BQ2Q7O01BRUQsY0FBYyxHQUFHLGNBQWMsR0FBRyxJQUFJLENBQUM7S0FDeEM7O0lBRUQsT0FBTyxJQUFJLENBQUM7R0FDYixDQUFDO0NBQ0g7O0FBRUQsU0FBUyxPQUFPLENBQUMsSUFBSSxFQUFFLElBQUksRUFBRTtFQUMzQixPQUFPLElBQUksR0FBRyxJQUFJLEdBQUcsQ0FBQyxDQUFDO0NBQ3hCOztBQUVELFNBQVMsV0FBVyxDQUFDLENBQUMsRUFBRSxDQUFDLEVBQUU7RUFDekIsSUFBSSxDQUFDLEtBQUssQ0FBQyxFQUFFLE9BQU8sSUFBSSxDQUFDO0VBQ3pCLElBQUksQ0FBQyxJQUFJLElBQUksSUFBSSxDQUFDLElBQUksSUFBSSxFQUFFLE9BQU8sS0FBSyxDQUFDO0VBQ3pDLElBQUksQ0FBQyxDQUFDLE1BQU0sSUFBSSxDQUFDLENBQUMsTUFBTSxFQUFFLE9BQU8sS0FBSyxDQUFDOztFQUV2QyxLQUFLLElBQUksQ0FBQyxHQUFHLENBQUMsRUFBRSxDQUFDLEdBQUcsQ0FBQyxDQUFDLE1BQU0sRUFBRSxFQUFFLENBQUMsRUFBRTtJQUNqQyxJQUFJLENBQUMsQ0FBQyxDQUFDLENBQUMsS0FBSyxDQUFDLENBQUMsQ0FBQyxDQUFDLEVBQUUsT0FBTyxLQUFLLENBQUM7R0FDakM7O0VBRUQsT0FBTyxJQUFJLENBQUM7Q0FDYjs7QUFFRCxTQUFTLFNBQVMsQ0FBQyxHQUFHLEVBQUUsR0FBRyxFQUFFO0VBQzNCLEtBQUssSUFBSSxDQUFDLEdBQUcsQ0FBQyxFQUFFLENBQUMsR0FBRyxHQUFHLEVBQUUsQ0FBQyxFQUFFLEVBQUU7SUFDNUIsR0FBRyxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUMsQ0FBQztHQUNiO0NBQ0Y7O0FBRUQsU0FBUyxlQUFlLENBQUMsR0FBRyxFQUFFO0VBQzVCLElBQUksWUFBWSxHQUFHLEdBQUcsQ0FBQyxHQUFHLENBQUMsSUFBSSxJQUFJLFNBQVMsQ0FBQyxPQUFPLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQztFQUM1RCxPQUFPLElBQUksU0FBUyxDQUFDLEdBQUcsWUFBWSxDQUFDLENBQUM7Q0FDdkM7O0FBRUQsU0FBUyxjQUFjLEdBQUc7RUFDeEIsT0FBTyxZQUFZO0lBQ2pCLE9BQU8sS0FBSyxDQUFDO0dBQ2QsQ0FBQztDQUNIOztBQUVELGdCQUFlO0VBQ2IsWUFBWTtFQUNaLGVBQWU7RUFDZixlQUFlO0VBQ2YsZUFBZTtFQUNmLGNBQWM7RUFDZCxpQkFBaUI7RUFDakIsV0FBVztFQUNYLFlBQVk7RUFDWixhQUFhO0VBQ2IsY0FBYztFQUNkLGFBQWE7RUFDYixhQUFhO0VBQ2IsYUFBYTtFQUNiLGNBQWM7RUFDZCxlQUFlO0VBQ2YsV0FBVztFQUNYLGdCQUFnQjtDQUNqQixDQUFDOztBQ3BUSyxTQUFTLFVBQVUsQ0FBQyxPQUFPLEVBQUU7O0VBRWxDLElBQUksTUFBTSxDQUFDLFdBQVcsQ0FBQyxPQUFPLENBQUMsRUFBRTtJQUMvQixPQUFPLFNBQVMsQ0FBQyxlQUFlLENBQUMsT0FBTyxDQUFDLENBQUM7R0FDM0M7O0VBRUQsSUFBSSxNQUFNLENBQUMsV0FBVyxDQUFDLE9BQU8sQ0FBQyxFQUFFO0lBQy9CLE9BQU8sU0FBUyxDQUFDLGVBQWUsQ0FBQyxPQUFPLENBQUMsQ0FBQztHQUMzQzs7RUFFRCxJQUFJLE1BQU0sQ0FBQyxZQUFZLENBQUMsT0FBTyxDQUFDLEVBQUU7SUFDaEMsT0FBTyxTQUFTLENBQUMsZUFBZSxDQUFDLE9BQU8sQ0FBQyxDQUFDO0dBQzNDOztFQUVELElBQUksTUFBTSxDQUFDLFdBQVcsQ0FBQyxPQUFPLENBQUMsRUFBRTtJQUMvQixPQUFPLFNBQVMsQ0FBQyxlQUFlLENBQUMsT0FBTyxDQUFDLENBQUM7R0FDM0M7O0VBRUQsSUFBSSxNQUFNLENBQUMsYUFBYSxDQUFDLE9BQU8sQ0FBQyxFQUFFO0lBQ2pDLE9BQU8sU0FBUyxDQUFDLGlCQUFpQixDQUFDLE9BQU8sQ0FBQyxDQUFDO0dBQzdDOztFQUVELElBQUksTUFBTSxDQUFDLFVBQVUsQ0FBQyxPQUFPLENBQUMsRUFBRTtJQUM5QixPQUFPLFNBQVMsQ0FBQyxjQUFjLENBQUMsT0FBTyxDQUFDLENBQUM7R0FDMUM7O0VBRUQsSUFBSSxNQUFNLENBQUMsUUFBUSxDQUFDLE9BQU8sQ0FBQyxFQUFFO0lBQzVCLE9BQU8sU0FBUyxDQUFDLFlBQVksQ0FBQyxPQUFPLENBQUMsQ0FBQztHQUN4Qzs7RUFFRCxJQUFJLE1BQU0sQ0FBQyxPQUFPLENBQUMsT0FBTyxDQUFDLEVBQUU7SUFDM0IsT0FBTyxTQUFTLENBQUMsV0FBVyxDQUFDLE9BQU8sQ0FBQyxDQUFDO0dBQ3ZDOztFQUVELElBQUksTUFBTSxDQUFDLFFBQVEsQ0FBQyxPQUFPLENBQUMsRUFBRTtJQUM1QixPQUFPLFNBQVMsQ0FBQyxZQUFZLENBQUMsT0FBTyxDQUFDLENBQUM7R0FDeEM7O0VBRUQsSUFBSSxNQUFNLENBQUMsU0FBUyxDQUFDLE9BQU8sQ0FBQyxFQUFFO0lBQzdCLE9BQU8sU0FBUyxDQUFDLGFBQWEsQ0FBQyxPQUFPLENBQUMsQ0FBQztHQUN6Qzs7RUFFRCxJQUFJLE1BQU0sQ0FBQyxTQUFTLENBQUMsT0FBTyxDQUFDLEVBQUU7SUFDN0IsT0FBTyxTQUFTLENBQUMsYUFBYSxDQUFDLE9BQU8sQ0FBQyxDQUFDO0dBQ3pDOztFQUVELElBQUksTUFBTSxDQUFDLFVBQVUsQ0FBQyxPQUFPLENBQUMsRUFBRTtJQUM5QixPQUFPLFNBQVMsQ0FBQyxjQUFjLENBQUMsT0FBTyxDQUFDLENBQUM7R0FDMUM7O0VBRUQsSUFBSSxNQUFNLENBQUMsU0FBUyxDQUFDLE9BQU8sQ0FBQyxFQUFFO0lBQzdCLE9BQU8sU0FBUyxDQUFDLGFBQWEsQ0FBQyxPQUFPLENBQUMsQ0FBQztHQUN6Qzs7RUFFRCxJQUFJLE1BQU0sQ0FBQyxPQUFPLENBQUMsT0FBTyxDQUFDLEVBQUU7SUFDM0IsT0FBTyxTQUFTLENBQUMsV0FBVyxDQUFDLE9BQU8sQ0FBQyxDQUFDO0dBQ3ZDOztFQUVELElBQUksTUFBTSxDQUFDLFlBQVksQ0FBQyxPQUFPLENBQUMsRUFBRTtJQUNoQyxPQUFPLFNBQVMsQ0FBQyxnQkFBZ0IsQ0FBQyxPQUFPLENBQUMsQ0FBQztHQUM1Qzs7RUFFRCxJQUFJLE1BQU0sQ0FBQyxTQUFTLENBQUMsT0FBTyxDQUFDLEVBQUU7SUFDN0IsT0FBTyxTQUFTLENBQUMsYUFBYSxDQUFDLE9BQU8sQ0FBQyxDQUFDO0dBQ3pDOztFQUVELE9BQU8sU0FBUyxDQUFDLGNBQWMsRUFBRSxDQUFDO0NBQ25DOztBQ2xFTSxNQUFNLFVBQVUsU0FBUyxLQUFLLENBQUM7RUFDcEMsV0FBVyxDQUFDLEdBQUcsRUFBRTtJQUNmLEtBQUssRUFBRSxDQUFDOztJQUVSLElBQUksT0FBTyxHQUFHLEtBQUssUUFBUSxFQUFFO01BQzNCLElBQUksQ0FBQyxPQUFPLEdBQUcsZ0JBQWdCLEdBQUcsR0FBRyxDQUFDLFFBQVEsRUFBRSxDQUFDO0tBQ2xELE1BQU0sSUFBSSxLQUFLLENBQUMsT0FBTyxDQUFDLEdBQUcsQ0FBQyxFQUFFO01BQzdCLElBQUksWUFBWSxHQUFHLEdBQUcsQ0FBQyxHQUFHLENBQUMsQ0FBQyxJQUFJLENBQUMsQ0FBQyxRQUFRLEVBQUUsQ0FBQyxDQUFDO01BQzlDLElBQUksQ0FBQyxPQUFPLEdBQUcsZ0JBQWdCLEdBQUcsWUFBWSxDQUFDO0tBQ2hELE1BQU07TUFDTCxJQUFJLENBQUMsT0FBTyxHQUFHLGdCQUFnQixHQUFHLEdBQUcsQ0FBQztLQUN2Qzs7SUFFRCxJQUFJLENBQUMsS0FBSyxHQUFHLElBQUksS0FBSyxFQUFFLENBQUMsS0FBSyxDQUFDO0lBQy9CLElBQUksQ0FBQyxJQUFJLEdBQUcsSUFBSSxDQUFDLFdBQVcsQ0FBQyxJQUFJLENBQUM7R0FDbkM7Q0FDRjs7QUFFRCxBQUFPLE1BQU0sSUFBSSxDQUFDOztFQUVoQixXQUFXLENBQUMsT0FBTyxFQUFFLEVBQUUsRUFBRSxLQUFLLEdBQUcsTUFBTSxJQUFJLEVBQUU7SUFDM0MsSUFBSSxDQUFDLE9BQU8sR0FBRyxVQUFVLENBQUMsT0FBTyxDQUFDLENBQUM7SUFDbkMsSUFBSSxDQUFDLEtBQUssR0FBRyxPQUFPLENBQUMsTUFBTSxDQUFDO0lBQzVCLElBQUksQ0FBQyxTQUFTLEdBQUcsaUJBQWlCLENBQUMsT0FBTyxDQUFDLENBQUM7SUFDNUMsSUFBSSxDQUFDLEVBQUUsR0FBRyxFQUFFLENBQUM7SUFDYixJQUFJLENBQUMsS0FBSyxHQUFHLEtBQUssQ0FBQztHQUNwQjtDQUNGOztBQUVELEFBQU8sU0FBUyxTQUFTLENBQUMsT0FBTyxFQUFFLEVBQUUsRUFBRSxLQUFLLEdBQUcsTUFBTSxJQUFJLEVBQUU7RUFDekQsT0FBTyxJQUFJLElBQUksQ0FBQyxPQUFPLEVBQUUsRUFBRSxFQUFFLEtBQUssQ0FBQyxDQUFDO0NBQ3JDOztBQUVELEFBQU8sU0FBUyxRQUFRLENBQUMsR0FBRyxLQUFLLEVBQUU7RUFDakMsT0FBTyxVQUFVLEdBQUcsSUFBSSxFQUFFO0lBQ3hCLEtBQUssSUFBSSxhQUFhLElBQUksS0FBSyxFQUFFO01BQy9CLElBQUksTUFBTSxHQUFHLEVBQUUsQ0FBQztNQUNoQixJQUFJLEdBQUcsb0JBQW9CLENBQUMsSUFBSSxFQUFFLGFBQWEsQ0FBQyxLQUFLLEVBQUUsYUFBYSxDQUFDLFNBQVMsQ0FBQyxDQUFDOztNQUVoRixJQUFJLGFBQWEsQ0FBQyxPQUFPLENBQUMsSUFBSSxFQUFFLE1BQU0sQ0FBQyxJQUFJLGFBQWEsQ0FBQyxLQUFLLENBQUMsS0FBSyxDQUFDLElBQUksRUFBRSxNQUFNLENBQUMsRUFBRTtRQUNsRixPQUFPLGFBQWEsQ0FBQyxFQUFFLENBQUMsS0FBSyxDQUFDLElBQUksRUFBRSxNQUFNLENBQUMsQ0FBQztPQUM3QztLQUNGOztJQUVELE1BQU0sSUFBSSxVQUFVLENBQUMsSUFBSSxDQUFDLENBQUM7R0FDNUIsQ0FBQztDQUNIOztBQUVELFNBQVMsaUJBQWlCLENBQUMsT0FBTyxFQUFFO0VBQ2xDLElBQUksU0FBUyxHQUFHLEVBQUUsQ0FBQzs7RUFFbkIsS0FBSyxJQUFJLENBQUMsR0FBRyxDQUFDLEVBQUUsQ0FBQyxHQUFHLE9BQU8sQ0FBQyxNQUFNLEVBQUUsQ0FBQyxFQUFFLEVBQUU7SUFDdkMsSUFBSSxPQUFPLENBQUMsQ0FBQyxDQUFDLFlBQVlDLFFBQWMsSUFBSSxPQUFPLENBQUMsQ0FBQyxDQUFDLENBQUMsYUFBYSxJQUFJLE1BQU0sQ0FBQyxHQUFHLENBQUMsdUJBQXVCLENBQUMsRUFBRTtNQUMzRyxTQUFTLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQyxFQUFFLE9BQU8sQ0FBQyxDQUFDLENBQUMsQ0FBQyxhQUFhLENBQUMsQ0FBQyxDQUFDO0tBQy9DO0dBQ0Y7O0VBRUQsT0FBTyxTQUFTLENBQUM7Q0FDbEI7O0FBRUQsU0FBUyxvQkFBb0IsQ0FBQyxJQUFJLEVBQUUsS0FBSyxFQUFFLFNBQVMsRUFBRTtFQUNwRCxJQUFJLElBQUksQ0FBQyxNQUFNLEtBQUssS0FBSyxJQUFJLFNBQVMsQ0FBQyxNQUFNLEtBQUssQ0FBQyxFQUFFO0lBQ25ELE9BQU8sSUFBSSxDQUFDO0dBQ2I7O0VBRUQsSUFBSSxJQUFJLENBQUMsTUFBTSxHQUFHLFNBQVMsQ0FBQyxNQUFNLEdBQUcsS0FBSyxFQUFFO0lBQzFDLE9BQU8sSUFBSSxDQUFDO0dBQ2I7O0VBRUQsSUFBSSx1QkFBdUIsR0FBRyxLQUFLLEdBQUcsSUFBSSxDQUFDLE1BQU0sQ0FBQztFQUNsRCxJQUFJLGlCQUFpQixHQUFHLFNBQVMsQ0FBQyxNQUFNLEdBQUcsdUJBQXVCLENBQUM7O0VBRW5FLElBQUksY0FBYyxHQUFHLFNBQVMsQ0FBQyxLQUFLLENBQUMsaUJBQWlCLENBQUMsQ0FBQzs7RUFFeEQsS0FBSyxJQUFJLENBQUMsS0FBSyxFQUFFLEtBQUssQ0FBQyxJQUFJLGNBQWMsRUFBRTtJQUN6QyxJQUFJLENBQUMsTUFBTSxDQUFDLEtBQUssRUFBRSxDQUFDLEVBQUUsS0FBSyxDQUFDLENBQUM7SUFDN0IsSUFBSSxJQUFJLENBQUMsTUFBTSxLQUFLLEtBQUssRUFBRTtNQUN6QixNQUFNO0tBQ1A7R0FDRjs7RUFFRCxPQUFPLElBQUksQ0FBQztDQUNiOztBQUVELEFBQU8sU0FBUyxLQUFLLENBQUMsT0FBTyxFQUFFLElBQUksRUFBRSxLQUFLLEdBQUcsTUFBTSxJQUFJLEVBQUU7RUFDdkQsSUFBSSxNQUFNLEdBQUcsRUFBRSxDQUFDO0VBQ2hCLElBQUksZ0JBQWdCLEdBQUcsVUFBVSxDQUFDLE9BQU8sQ0FBQyxDQUFDO0VBQzNDLElBQUksZ0JBQWdCLENBQUMsSUFBSSxFQUFFLE1BQU0sQ0FBQyxJQUFJLEtBQUssQ0FBQyxLQUFLLENBQUMsSUFBSSxFQUFFLE1BQU0sQ0FBQyxFQUFFO0lBQy9ELE9BQU8sTUFBTSxDQUFDO0dBQ2YsTUFBTTtJQUNMLE1BQU0sSUFBSSxVQUFVLENBQUMsSUFBSSxDQUFDLENBQUM7R0FDNUI7Q0FDRjs7QUFFRCxBQUFPLFNBQVMsY0FBYyxDQUFDLE9BQU8sRUFBRSxJQUFJLEVBQUUsS0FBSyxHQUFHLE1BQU0sSUFBSSxFQUFFO0VBQ2hFLElBQUk7SUFDRixPQUFPLEtBQUssQ0FBQyxPQUFPLEVBQUUsSUFBSSxFQUFFLEtBQUssQ0FBQyxDQUFDO0dBQ3BDLENBQUMsT0FBTyxDQUFDLEVBQUU7SUFDVixJQUFJLENBQUMsWUFBWSxVQUFVLElBQUksQ0FBQyxDQUFDLE9BQU8sQ0FBQyxVQUFVLENBQUMsZUFBZSxDQUFDLEVBQUU7TUFDcEUsT0FBTyxJQUFJLENBQUM7S0FDYjs7SUFFRCxNQUFNLENBQUMsQ0FBQztHQUNUO0NBQ0Y7O2VDeEdjO0VBQ2IsUUFBUSxFQUFFLEtBQUssRUFBRSxVQUFVLEVBQUUsY0FBYztFQUMzQyxRQUFRLEVBQUUsUUFBUSxFQUFFLFVBQVU7RUFDOUIsT0FBTyxFQUFFLFFBQVEsRUFBRSxJQUFJLEVBQUUsS0FBSyxFQUFFLElBQUksRUFBRSxTQUFTLEVBQUUsY0FBYztDQUNoRSxDQUFDOztBQ1BGO0FBQ0EsTUFBTSxRQUFRLENBQUM7RUFDYixXQUFXLENBQUMsSUFBSSxFQUFFO0lBQ2hCLElBQUksQ0FBQyxRQUFRLEdBQUcsSUFBSSxHQUFHLEVBQUUsQ0FBQztJQUMxQixJQUFJLENBQUMsUUFBUSxHQUFHLElBQUksQ0FBQzs7SUFFckIsS0FBSyxJQUFJLE9BQU8sSUFBSSxJQUFJLEVBQUU7TUFDeEIsSUFBSSxDQUFDLE9BQU8sQ0FBQyxHQUFHLFNBQVMsQ0FBQyxPQUFPLENBQUMsQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLENBQUM7S0FDL0M7O0lBRUQsU0FBUyxTQUFTLENBQUMsT0FBTyxFQUFFOztNQUUxQixPQUFPLFVBQVUsR0FBRyxJQUFJLEVBQUU7UUFDeEIsSUFBSSxLQUFLLEdBQUcsSUFBSSxDQUFDLENBQUMsQ0FBQyxDQUFDO1FBQ3BCLElBQUksR0FBRyxHQUFHLElBQUksQ0FBQzs7UUFFZixJQUFJLE1BQU0sQ0FBQyxTQUFTLENBQUMsS0FBSyxDQUFDLElBQUksSUFBSSxDQUFDLGlCQUFpQixDQUFDLE9BQU8sQ0FBQyxFQUFFO1VBQzlELEdBQUcsR0FBRyxJQUFJLENBQUMsUUFBUSxDQUFDLEdBQUcsQ0FBQyxPQUFPLENBQUMsQ0FBQyxPQUFPLENBQUMsQ0FBQztTQUMzQyxNQUFNLElBQUksT0FBTyxLQUFLLEtBQUssUUFBUSxJQUFJLENBQUMsTUFBTSxDQUFDLFNBQVMsQ0FBQyxLQUFLLENBQUMsSUFBSSxJQUFJLENBQUMsaUJBQWlCLENBQUMsS0FBSyxDQUFDLEVBQUU7VUFDakcsR0FBRyxHQUFHLElBQUksQ0FBQyxRQUFRLENBQUMsR0FBRyxDQUFDLEtBQUssQ0FBQyxDQUFDLE9BQU8sQ0FBQyxDQUFDO1NBQ3pDLE1BQU0sSUFBSSxJQUFJLENBQUMsaUJBQWlCLENBQUMsS0FBSyxDQUFDLEVBQUU7VUFDeEMsR0FBRyxHQUFHLElBQUksQ0FBQyxRQUFRLENBQUMsR0FBRyxDQUFDLEtBQUssQ0FBQyxXQUFXLENBQUMsQ0FBQyxPQUFPLENBQUMsQ0FBQztTQUNyRCxNQUFNLElBQUksSUFBSSxDQUFDLFFBQVEsRUFBRTtVQUN4QixHQUFHLEdBQUcsSUFBSSxDQUFDLFFBQVEsQ0FBQyxPQUFPLENBQUMsQ0FBQztTQUM5Qjs7UUFFRCxJQUFJLEdBQUcsSUFBSSxJQUFJLEVBQUU7VUFDZixJQUFJLE1BQU0sR0FBRyxHQUFHLENBQUMsS0FBSyxDQUFDLElBQUksRUFBRSxJQUFJLENBQUMsQ0FBQztVQUNuQyxPQUFPLE1BQU0sQ0FBQztTQUNmOztRQUVELE1BQU0sSUFBSSxLQUFLLENBQUMsOEJBQThCLEdBQUcsS0FBSyxDQUFDLENBQUM7T0FDekQsQ0FBQztLQUNIO0dBQ0Y7O0VBRUQsY0FBYyxDQUFDLElBQUksRUFBRSxjQUFjLEVBQUU7SUFDbkMsSUFBSSxJQUFJLEtBQUssSUFBSSxFQUFFO01BQ2pCLElBQUksQ0FBQyxRQUFRLEdBQUcsY0FBYyxDQUFDO0tBQ2hDLE1BQU07TUFDTCxJQUFJLENBQUMsUUFBUSxDQUFDLEdBQUcsQ0FBQyxJQUFJLEVBQUUsY0FBYyxDQUFDLENBQUM7S0FDekM7R0FDRjs7RUFFRCxpQkFBaUIsQ0FBQyxLQUFLLEVBQUU7SUFDdkIsSUFBSSxLQUFLLEtBQUssT0FBTyxJQUFJLEtBQUssS0FBSyxLQUFLLEVBQUU7TUFDeEMsT0FBTyxJQUFJLENBQUMsUUFBUSxDQUFDLEdBQUcsQ0FBQyxLQUFLLENBQUMsQ0FBQztLQUNqQzs7SUFFRCxPQUFPLElBQUksQ0FBQyxRQUFRLENBQUMsR0FBRyxDQUFDLEtBQUssQ0FBQyxXQUFXLENBQUMsQ0FBQztHQUM3QztDQUNGOztBQ2hERCxTQUFTLGFBQWEsQ0FBQyxJQUFJLEVBQUUsUUFBUSxFQUFFO0VBQ3JDLElBQUksSUFBSSxHQUFHLElBQUksQ0FBQzs7RUFFaEIsSUFBSSxPQUFPLElBQUksS0FBSyxRQUFRLElBQUksT0FBTyxJQUFJLEtBQUssUUFBUSxJQUFJLE9BQU8sSUFBSSxLQUFLLFNBQVMsSUFBSSxPQUFPLElBQUksS0FBSyxRQUFRLEVBQUU7SUFDakgsSUFBSSxJQUFJLENBQUMsUUFBUSxDQUFDLEtBQUssU0FBUyxFQUFFO01BQ2hDLElBQUksR0FBRyxRQUFRLENBQUM7S0FDakIsTUFBTSxJQUFJLElBQUksQ0FBQyxNQUFNLENBQUMsR0FBRyxDQUFDLFFBQVEsQ0FBQyxDQUFDLEtBQUssU0FBUyxFQUFFO01BQ25ELElBQUksR0FBRyxNQUFNLENBQUMsR0FBRyxDQUFDLFFBQVEsQ0FBQyxDQUFDO0tBQzdCO0dBQ0YsTUFBTTtJQUNMLElBQUksUUFBUSxJQUFJLElBQUksRUFBRTtNQUNwQixJQUFJLEdBQUcsUUFBUSxDQUFDO0tBQ2pCLE1BQU0sSUFBSSxNQUFNLENBQUMsR0FBRyxDQUFDLFFBQVEsQ0FBQyxJQUFJLElBQUksRUFBRTtNQUN2QyxJQUFJLEdBQUcsTUFBTSxDQUFDLEdBQUcsQ0FBQyxRQUFRLENBQUMsQ0FBQztLQUM3QjtHQUNGOztFQUVELElBQUksSUFBSSxLQUFLLElBQUksRUFBRTtJQUNqQixNQUFNLElBQUksS0FBSyxDQUFDLENBQUMsU0FBUyxHQUFHLFFBQVEsRUFBRSxjQUFjLEdBQUcsSUFBSSxFQUFFLENBQUMsQ0FBQyxDQUFDO0dBQ2xFOztFQUVELElBQUksSUFBSSxDQUFDLElBQUksQ0FBQyxZQUFZLFFBQVEsRUFBRTtJQUNsQyxPQUFPLElBQUksQ0FBQyxJQUFJLENBQUMsRUFBRSxDQUFDO0dBQ3JCLE1BQU07SUFDTCxPQUFPLElBQUksQ0FBQyxJQUFJLENBQUMsQ0FBQztHQUNuQjtDQUNGOztBQUVELFNBQVMsS0FBSyxDQUFDLEdBQUcsSUFBSSxFQUFFO0VBQ3RCLElBQUksSUFBSSxDQUFDLE1BQU0sS0FBSyxDQUFDLEVBQUU7SUFDckIsSUFBSSxDQUFDLENBQUMsQ0FBQyxDQUFDLEtBQUssQ0FBQyxJQUFJLEVBQUUsSUFBSSxDQUFDLEtBQUssQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDO0dBQ3BDLE1BQU07SUFDTCxJQUFJLENBQUMsQ0FBQyxDQUFDLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsS0FBSyxDQUFDLElBQUksRUFBRSxJQUFJLENBQUMsS0FBSyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUM7R0FDN0M7Q0FDRjs7QUFFRCxTQUFTLFFBQVEsQ0FBQyxJQUFJLEVBQUUsS0FBSyxFQUFFO0VBQzdCLEtBQUssSUFBSSxDQUFDLElBQUksS0FBSyxFQUFFO0lBQ25CLElBQUksUUFBUSxDQUFDLGNBQWMsQ0FBQyxJQUFJLEVBQUUsQ0FBQyxDQUFDLElBQUksSUFBSSxFQUFFO01BQzVDLE9BQU8sSUFBSSxDQUFDO0tBQ2I7R0FDRjs7RUFFRCxPQUFPLEtBQUssQ0FBQztDQUNkOztBQUVELFNBQVMsVUFBVSxHQUFHO0VBQ3BCLElBQUksT0FBTyxJQUFJLEtBQUssV0FBVyxFQUFFO0lBQy9CLE9BQU8sSUFBSSxDQUFDO0dBQ2IsTUFBTSxJQUFJLE9BQU8sTUFBTSxLQUFLLFdBQVcsRUFBRTtJQUN4QyxPQUFPLE1BQU0sQ0FBQztHQUNmLE1BQU0sSUFBSSxPQUFPLE1BQU0sS0FBSyxXQUFXLEVBQUU7SUFDeEMsT0FBTyxNQUFNLENBQUM7R0FDZjs7RUFFRCxNQUFNLElBQUksS0FBSyxDQUFDLHVCQUF1QixDQUFDLENBQUM7Q0FDMUM7O0FBRUQsU0FBUyxTQUFTLENBQUMsUUFBUSxFQUFFO0VBQzNCLE9BQU8sTUFBTTtJQUNYLFdBQVcsQ0FBQyxNQUFNLEdBQUcsRUFBRSxFQUFFO01BQ3ZCLElBQUksVUFBVSxHQUFHLE1BQU0sQ0FBQyxNQUFNLENBQUMsUUFBUSxFQUFFLE1BQU0sQ0FBQyxDQUFDO01BQ2pELE1BQU0sQ0FBQyxNQUFNLENBQUMsSUFBSSxFQUFFLFVBQVUsQ0FBQyxDQUFDO0tBQ2pDOztJQUVELE9BQU8sTUFBTSxDQUFDLE9BQU8sR0FBRyxFQUFFLEVBQUU7TUFDMUIsSUFBSSxDQUFDLEdBQUcsSUFBSSxJQUFJLENBQUMsT0FBTyxDQUFDLENBQUM7TUFDMUIsT0FBTyxNQUFNLENBQUMsTUFBTSxDQUFDLENBQUMsQ0FBQyxDQUFDO0tBQ3pCO0dBQ0YsQ0FBQztDQUNIOztBQUVELFNBQVMsWUFBWSxDQUFDLFFBQVEsRUFBRTtFQUM5QixPQUFPLGNBQWMsS0FBSyxDQUFDO0lBQ3pCLFdBQVcsQ0FBQyxNQUFNLEdBQUcsRUFBRSxFQUFFO01BQ3ZCLElBQUksT0FBTyxHQUFHLE1BQU0sQ0FBQyxPQUFPLElBQUksRUFBRSxDQUFDO01BQ25DLEtBQUssQ0FBQyxPQUFPLENBQUMsQ0FBQzs7TUFFZixJQUFJLFVBQVUsR0FBRyxNQUFNLENBQUMsTUFBTSxDQUFDLFFBQVEsRUFBRSxNQUFNLENBQUMsQ0FBQztNQUNqRCxNQUFNLENBQUMsTUFBTSxDQUFDLElBQUksRUFBRSxVQUFVLENBQUMsQ0FBQzs7TUFFaEMsSUFBSSxDQUFDLElBQUksR0FBRyxJQUFJLENBQUMsV0FBVyxDQUFDLElBQUksQ0FBQztNQUNsQyxJQUFJLENBQUMsT0FBTyxHQUFHLE9BQU8sQ0FBQztNQUN2QixJQUFJLENBQUMsWUFBWSxDQUFDLElBQUksQ0FBQyxlQUFlLENBQUMsQ0FBQyxHQUFHLElBQUksQ0FBQztNQUNoRCxLQUFLLENBQUMsaUJBQWlCLENBQUMsSUFBSSxFQUFFLElBQUksQ0FBQyxXQUFXLENBQUMsSUFBSSxDQUFDLENBQUM7S0FDdEQ7O0lBRUQsT0FBTyxNQUFNLENBQUMsT0FBTyxHQUFHLEVBQUUsRUFBRTtNQUMxQixJQUFJLENBQUMsR0FBRyxJQUFJLElBQUksQ0FBQyxPQUFPLENBQUMsQ0FBQztNQUMxQixPQUFPLE1BQU0sQ0FBQyxNQUFNLENBQUMsQ0FBQyxDQUFDLENBQUM7S0FDekI7R0FDRixDQUFDO0NBQ0g7O0FBRUQsU0FBUyxXQUFXLENBQUMsSUFBSSxFQUFFO0VBQ3pCLE9BQU8sSUFBSSxRQUFRLENBQUMsSUFBSSxDQUFDLENBQUM7Q0FDM0I7O0FBRUQsU0FBUyxPQUFPLENBQUMsUUFBUSxFQUFFLElBQUksRUFBRSxJQUFJLEVBQUU7RUFDckMsUUFBUSxDQUFDLGNBQWMsQ0FBQyxJQUFJLEVBQUUsSUFBSSxDQUFDLENBQUM7Q0FDckM7O0FBRUQsU0FBUyxlQUFlLENBQUMsR0FBRyxFQUFFO0VBQzVCLE9BQU8sTUFBTSxDQUFDLElBQUksQ0FBQyxHQUFHLENBQUMsQ0FBQyxNQUFNLENBQUMsTUFBTSxDQUFDLHFCQUFxQixDQUFDLEdBQUcsQ0FBQyxDQUFDLENBQUM7Q0FDbkU7O0FBRUQsU0FBUyxrQkFBa0IsQ0FBQyxTQUFTLEVBQUU7RUFDckMsSUFBSTtJQUNGLE9BQU8sTUFBTSxDQUFDLGFBQWEsQ0FBQyxTQUFTLENBQUMsSUFBSSxJQUFJLENBQUM7R0FDaEQsQ0FBQyxPQUFPLENBQUMsRUFBRTtJQUNWLE9BQU8sS0FBSyxDQUFDO0dBQ2Q7Q0FDRjs7O0FBR0QsU0FBUyxnQkFBZ0IsQ0FBQyxHQUFHLEVBQUU7RUFDN0IsT0FBTyxJQUFJLENBQUMsa0JBQWtCLENBQUMsR0FBRyxDQUFDLENBQUMsT0FBTyxDQUFDLGlCQUFpQixFQUFFLFVBQVUsS0FBSyxFQUFFLEVBQUUsRUFBRTtJQUNsRixPQUFPLE1BQU0sQ0FBQyxZQUFZLENBQUMsSUFBSSxHQUFHLEVBQUUsQ0FBQyxDQUFDO0dBQ3ZDLENBQUMsQ0FBQyxDQUFDO0NBQ0w7O0FBRUQsU0FBUyx3QkFBd0IsQ0FBQyxHQUFHLEVBQUUsUUFBUSxFQUFFO0VBQy9DLElBQUksT0FBTyxHQUFHLE1BQU0sQ0FBQyxNQUFNLENBQUMsTUFBTSxDQUFDLE1BQU0sQ0FBQyxHQUFHLENBQUMsV0FBVyxDQUFDLFNBQVMsQ0FBQyxFQUFFLEdBQUcsQ0FBQyxDQUFDO0VBQzNFLE9BQU8sT0FBTyxDQUFDLFFBQVEsQ0FBQyxDQUFDOztFQUV6QixPQUFPLE1BQU0sQ0FBQyxNQUFNLENBQUMsT0FBTyxDQUFDLENBQUM7Q0FDL0I7O0FBRUQsU0FBUyxZQUFZLENBQUMsR0FBRyxFQUFFO0VBQ3pCLElBQUksT0FBTyxHQUFHLE1BQU0sQ0FBQyxNQUFNLENBQUMsRUFBRSxFQUFFLEdBQUcsQ0FBQyxDQUFDO0VBQ3JDLE9BQU8sTUFBTSxDQUFDLE1BQU0sQ0FBQyxPQUFPLENBQUMsQ0FBQztDQUMvQjs7QUFFRCxTQUFTLG1CQUFtQixDQUFDLEdBQUcsRUFBRSxRQUFRLEVBQUUsS0FBSyxFQUFFO0VBQ2pELElBQUksT0FBTyxHQUFHLE1BQU0sQ0FBQyxNQUFNLENBQUMsRUFBRSxFQUFFLEdBQUcsQ0FBQyxDQUFDO0VBQ3JDLE9BQU8sQ0FBQyxRQUFRLENBQUMsR0FBRyxLQUFLLENBQUM7RUFDMUIsT0FBTyxNQUFNLENBQUMsTUFBTSxDQUFDLE9BQU8sQ0FBQyxDQUFDO0NBQy9COztBQUVELFNBQVMsVUFBVSxDQUFDLEdBQUcsRUFBRSxRQUFRLEVBQUUsS0FBSyxFQUFFO0VBQ3hDLElBQUksUUFBUSxJQUFJLGVBQWUsQ0FBQyxHQUFHLENBQUMsRUFBRTtJQUNwQyxPQUFPLG1CQUFtQixDQUFDLEdBQUcsRUFBRSxRQUFRLEVBQUUsS0FBSyxDQUFDLENBQUM7R0FDbEQ7O0VBRUQsTUFBTSx1QkFBdUIsQ0FBQztDQUMvQjs7QUFFRCxTQUFTLElBQUksQ0FBQyxJQUFJLEVBQUU7RUFDbEIsT0FBTyxDQUFDLElBQUksQ0FBQztDQUNkOztBQUVELFNBQVMsSUFBSSxDQUFDLElBQUksRUFBRSxLQUFLLEVBQUU7RUFDekIsT0FBTyxJQUFJLEdBQUcsS0FBSyxDQUFDO0NBQ3JCOztBQUVELFNBQVMsR0FBRyxDQUFDLElBQUksRUFBRSxLQUFLLEVBQUU7RUFDeEIsT0FBTyxJQUFJLEdBQUcsS0FBSyxDQUFDO0NBQ3JCOztBQUVELFNBQVMsR0FBRyxDQUFDLElBQUksRUFBRSxLQUFLLEVBQUU7RUFDeEIsT0FBTyxJQUFJLElBQUksS0FBSyxDQUFDO0NBQ3RCOztBQUVELFNBQVMsR0FBRyxDQUFDLElBQUksRUFBRSxLQUFLLEVBQUU7RUFDeEIsT0FBTyxJQUFJLElBQUksS0FBSyxDQUFDO0NBQ3RCOztBQUVELFNBQVMsSUFBSSxDQUFDLElBQUksRUFBRSxLQUFLLEVBQUU7RUFDekIsT0FBTyxJQUFJLEdBQUcsS0FBSyxDQUFDO0NBQ3JCOztBQUVELFNBQVMsR0FBRyxDQUFDLGFBQWEsRUFBRTtFQUMxQixJQUFJLGFBQWEsQ0FBQyxNQUFNLEtBQUssQ0FBQyxFQUFFO0lBQzlCLE9BQU8sTUFBTSxDQUFDLE1BQU0sQ0FBQyxFQUFFLENBQUMsQ0FBQztHQUMxQjs7RUFFRCxJQUFJLFNBQVMsR0FBRyxFQUFFLENBQUM7RUFDbkIsSUFBSSxlQUFlLEdBQUcsYUFBYSxDQUFDLENBQUMsQ0FBQyxDQUFDOztFQUV2QyxLQUFLLElBQUksQ0FBQyxJQUFJLGFBQWEsRUFBRTtJQUMzQixJQUFJLENBQUMsQ0FBQyxNQUFNLEdBQUcsZUFBZSxFQUFFO01BQzlCLGVBQWUsR0FBRyxDQUFDLENBQUMsTUFBTSxDQUFDO0tBQzVCO0dBQ0Y7O0VBRUQsS0FBSyxJQUFJLENBQUMsR0FBRyxDQUFDLEVBQUUsQ0FBQyxHQUFHLGVBQWUsRUFBRSxDQUFDLEVBQUUsRUFBRTtJQUN4QyxJQUFJLGFBQWEsR0FBRyxFQUFFLENBQUM7SUFDdkIsS0FBSyxJQUFJLENBQUMsR0FBRyxDQUFDLEVBQUUsQ0FBQyxHQUFHLGFBQWEsQ0FBQyxNQUFNLEVBQUUsQ0FBQyxFQUFFLEVBQUU7TUFDN0MsYUFBYSxDQUFDLElBQUksQ0FBQyxhQUFhLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQztLQUN6Qzs7SUFFRCxTQUFTLENBQUMsSUFBSSxDQUFDLElBQUksS0FBSyxDQUFDLEdBQUcsYUFBYSxDQUFDLENBQUMsQ0FBQztHQUM3Qzs7RUFFRCxPQUFPLE1BQU0sQ0FBQyxNQUFNLENBQUMsU0FBUyxDQUFDLENBQUM7Q0FDakM7O0FBRUQsU0FBUyxZQUFZLENBQUMsSUFBSSxFQUFFO0VBQzFCLElBQUk7SUFDRixJQUFJLENBQUMsSUFBSSxDQUFDLENBQUM7SUFDWCxPQUFPLElBQUksQ0FBQztHQUNiLENBQUMsT0FBTyxDQUFDLEVBQUU7SUFDVixPQUFPLEtBQUssQ0FBQztHQUNkO0NBQ0Y7O0FBRUQsU0FBUyxnQkFBZ0IsQ0FBQyxJQUFJLEVBQUUsT0FBTyxFQUFFO0VBQ3ZDLElBQUksS0FBSyxHQUFHLEtBQUssQ0FBQzs7RUFFbEIsT0FBTyxJQUFJLENBQUMsTUFBTSxDQUFDLElBQUksSUFBSTtJQUN6QixJQUFJLENBQUMsS0FBSyxJQUFJLElBQUksS0FBSyxPQUFPLEVBQUU7TUFDOUIsS0FBSyxHQUFHLElBQUksQ0FBQztNQUNiLE9BQU8sS0FBSyxDQUFDO0tBQ2Q7O0lBRUQsT0FBTyxJQUFJLENBQUM7R0FDYixDQUFDLENBQUM7Q0FDSjs7QUFFRCxTQUFTLEtBQUssQ0FBQyxHQUFHLEVBQUUsR0FBRyxFQUFFLElBQUksRUFBRTtFQUM3QixJQUFJLElBQUksR0FBRyxHQUFHLENBQUM7O0VBRWYsS0FBSyxNQUFNLEVBQUUsSUFBSSxJQUFJLEVBQUU7SUFDckIsSUFBSSxHQUFHLEdBQUcsQ0FBQyxFQUFFLEVBQUUsSUFBSSxDQUFDLENBQUM7R0FDdEI7O0VBRUQsT0FBTyxJQUFJLENBQUM7Q0FDYjs7QUFFRCxTQUFTLEtBQUssQ0FBQyxHQUFHLEVBQUUsR0FBRyxFQUFFLElBQUksRUFBRTtFQUM3QixJQUFJLElBQUksR0FBRyxHQUFHLENBQUM7O0VBRWYsS0FBSyxJQUFJLENBQUMsR0FBRyxJQUFJLENBQUMsTUFBTSxHQUFHLENBQUMsRUFBRSxDQUFDLElBQUksQ0FBQyxFQUFFLENBQUMsRUFBRSxFQUFFO0lBQ3pDLElBQUksR0FBRyxHQUFHLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQyxFQUFFLElBQUksQ0FBQyxDQUFDO0dBQzNCOztFQUVELE9BQU8sSUFBSSxDQUFDO0NBQ2I7O0FBRUQsU0FBUyxPQUFPLENBQUMsR0FBRyxFQUFFLENBQUMsRUFBRSxTQUFTLEVBQUU7O0VBRWxDLEtBQUssSUFBSSxDQUFDLEdBQUcsU0FBUyxDQUFDLE1BQU0sR0FBRyxDQUFDLEVBQUUsQ0FBQyxJQUFJLENBQUMsRUFBRSxDQUFDLEVBQUUsRUFBRTtJQUM5QyxJQUFJLFNBQVMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDLEtBQUssR0FBRyxFQUFFO01BQy9CLE9BQU8sU0FBUyxDQUFDLENBQUMsQ0FBQyxDQUFDO0tBQ3JCO0dBQ0Y7O0VBRUQsT0FBTyxLQUFLLENBQUM7Q0FDZDs7QUFFRCxTQUFTLFNBQVMsQ0FBQyxHQUFHLEVBQUUsQ0FBQyxFQUFFLFNBQVMsRUFBRTs7RUFFcEMsS0FBSyxJQUFJLENBQUMsR0FBRyxTQUFTLENBQUMsTUFBTSxHQUFHLENBQUMsRUFBRSxDQUFDLElBQUksQ0FBQyxFQUFFLENBQUMsRUFBRSxFQUFFO0lBQzlDLElBQUksU0FBUyxDQUFDLENBQUMsQ0FBQyxDQUFDLEdBQUcsQ0FBQyxDQUFDLENBQUMsS0FBSyxHQUFHLEVBQUU7TUFDL0IsT0FBTyxTQUFTLENBQUMsTUFBTSxDQUFDLEVBQUUsQ0FBQyxDQUFDLE1BQU0sQ0FBQyxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUM7S0FDMUM7R0FDRjs7RUFFRCxPQUFPLFNBQVMsQ0FBQztDQUNsQjs7QUFFRCxTQUFTLFFBQVEsQ0FBQyxHQUFHLEVBQUUsQ0FBQyxFQUFFLElBQUksRUFBRSxRQUFRLEVBQUU7RUFDeEMsS0FBSyxJQUFJLENBQUMsR0FBRyxJQUFJLENBQUMsTUFBTSxHQUFHLENBQUMsRUFBRSxDQUFDLElBQUksQ0FBQyxFQUFFLENBQUMsRUFBRSxFQUFFO0lBQ3pDLElBQUksSUFBSSxDQUFDLENBQUMsQ0FBQyxDQUFDLEdBQUcsQ0FBQyxDQUFDLENBQUMsS0FBSyxHQUFHLEVBQUU7TUFDMUIsT0FBTyxJQUFJLENBQUMsTUFBTSxDQUFDLEVBQUUsQ0FBQyxDQUFDLE1BQU0sQ0FBQyxDQUFDLEVBQUUsQ0FBQyxFQUFFLFFBQVEsQ0FBQyxDQUFDO0tBQy9DO0dBQ0Y7O0VBRUQsT0FBTyxJQUFJLENBQUMsTUFBTSxDQUFDLEVBQUUsQ0FBQyxDQUFDLElBQUksQ0FBQyxRQUFRLENBQUMsQ0FBQztDQUN2Qzs7QUFFRCxTQUFTLFNBQVMsQ0FBQyxHQUFHLEVBQUUsQ0FBQyxFQUFFLElBQUksRUFBRTtFQUMvQixLQUFLLElBQUksQ0FBQyxHQUFHLElBQUksQ0FBQyxNQUFNLEdBQUcsQ0FBQyxFQUFFLENBQUMsSUFBSSxDQUFDLEVBQUUsQ0FBQyxFQUFFLEVBQUU7SUFDekMsSUFBSSxJQUFJLENBQUMsQ0FBQyxDQUFDLENBQUMsR0FBRyxDQUFDLENBQUMsQ0FBQyxLQUFLLEdBQUcsRUFBRTtNQUMxQixPQUFPLElBQUksQ0FBQztLQUNiO0dBQ0Y7O0VBRUQsT0FBTyxLQUFLLENBQUM7Q0FDZDs7QUFFRCxTQUFTLE9BQU8sQ0FBQyxHQUFHLEVBQUUsQ0FBQyxFQUFFLElBQUksRUFBRTtFQUM3QixJQUFJLENBQUMsU0FBUyxDQUFDLEdBQUcsRUFBRSxDQUFDLEVBQUUsSUFBSSxDQUFDLEVBQUU7SUFDNUIsT0FBTyxLQUFLLENBQUM7R0FDZDs7RUFFRCxJQUFJLEtBQUssR0FBRyxPQUFPLENBQUMsR0FBRyxFQUFFLENBQUMsRUFBRSxJQUFJLENBQUMsQ0FBQzs7RUFFbEMsT0FBTyxJQUFJLEtBQUssQ0FBQyxLQUFLLENBQUMsR0FBRyxDQUFDLENBQUMsQ0FBQyxFQUFFLEtBQUssRUFBRSxTQUFTLENBQUMsR0FBRyxFQUFFLENBQUMsRUFBRSxJQUFJLENBQUMsQ0FBQyxDQUFDO0NBQ2hFOztBQUVELFNBQVMsVUFBVSxDQUFDLEdBQUcsRUFBRSxDQUFDLEVBQUUsSUFBSSxFQUFFLFFBQVEsRUFBRTs7RUFFMUMsS0FBSyxJQUFJLENBQUMsR0FBRyxTQUFTLENBQUMsTUFBTSxHQUFHLENBQUMsRUFBRSxDQUFDLElBQUksQ0FBQyxFQUFFLENBQUMsRUFBRSxFQUFFO0lBQzlDLElBQUksU0FBUyxDQUFDLENBQUMsQ0FBQyxDQUFDLEdBQUcsQ0FBQyxDQUFDLENBQUMsS0FBSyxHQUFHLEVBQUU7TUFDL0IsT0FBTyxTQUFTLENBQUMsTUFBTSxDQUFDLEVBQUUsQ0FBQyxDQUFDLE1BQU0sQ0FBQyxDQUFDLEVBQUUsQ0FBQyxFQUFFLFFBQVEsQ0FBQyxDQUFDO0tBQ3BEO0dBQ0Y7O0VBRUQsT0FBTyxTQUFTLENBQUM7Q0FDbEI7O0FBRUQsU0FBUyxPQUFPLENBQUMsSUFBSSxFQUFFO0VBQ3JCLE9BQU8sSUFBSSxDQUFDLE1BQU0sQ0FBQyxFQUFFLENBQUMsQ0FBQyxPQUFPLEVBQUUsQ0FBQztDQUNsQzs7QUFFRCxTQUFTLFNBQVMsQ0FBQyxHQUFHLEVBQUUsR0FBRyxFQUFFO0VBQzNCLElBQUksR0FBRyxJQUFJLGVBQWUsQ0FBQyxHQUFHLENBQUMsRUFBRTtJQUMvQixPQUFPLElBQUksS0FBSyxDQUFDLE1BQU0sQ0FBQyxHQUFHLENBQUMsSUFBSSxDQUFDLEVBQUUsR0FBRyxDQUFDLEdBQUcsQ0FBQyxDQUFDLENBQUM7R0FDOUMsTUFBTTtJQUNMLE9BQU8sTUFBTSxDQUFDLEdBQUcsQ0FBQyxPQUFPLENBQUMsQ0FBQztHQUM1QjtDQUNGOztBQUVELFNBQVMsT0FBTyxDQUFDLElBQUksRUFBRSxJQUFJLEdBQUcsRUFBRSxFQUFFO0VBQ2hDLElBQUksUUFBUSxHQUFHLEVBQUUsQ0FBQzs7RUFFbEIsS0FBSyxJQUFJLENBQUMsSUFBSSxJQUFJLEVBQUU7SUFDbEIsSUFBSSxPQUFPLENBQUMsQ0FBQyxDQUFDLEVBQUU7TUFDZCxRQUFRLEdBQUcsUUFBUSxDQUFDLE1BQU0sQ0FBQyxPQUFPLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQztLQUN4QyxNQUFNO01BQ0wsUUFBUSxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUMsQ0FBQztLQUNsQjtHQUNGOztFQUVELE9BQU8sTUFBTSxDQUFDLE1BQU0sQ0FBQyxRQUFRLENBQUMsTUFBTSxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUM7Q0FDN0M7O0FBRUQsU0FBUyxTQUFTLENBQUMsQ0FBQyxFQUFFLElBQUksRUFBRTtFQUMxQixJQUFJLElBQUksR0FBRyxFQUFFLENBQUM7O0VBRWQsS0FBSyxJQUFJLENBQUMsR0FBRyxDQUFDLEVBQUUsQ0FBQyxHQUFHLENBQUMsRUFBRSxDQUFDLEVBQUUsRUFBRTtJQUMxQixJQUFJLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxDQUFDO0dBQ2pCOztFQUVELE9BQU8sTUFBTSxDQUFDLE1BQU0sQ0FBQyxJQUFJLENBQUMsQ0FBQztDQUM1Qjs7QUFFRCxTQUFTLFFBQVEsQ0FBQyxHQUFHLEVBQUUsR0FBRyxFQUFFLElBQUksRUFBRTtFQUNoQyxJQUFJLE9BQU8sR0FBRyxFQUFFLENBQUM7O0VBRWpCLEtBQUssSUFBSSxDQUFDLElBQUksSUFBSSxFQUFFO0lBQ2xCLElBQUksR0FBRyxHQUFHLEdBQUcsQ0FBQyxDQUFDLEVBQUUsR0FBRyxDQUFDLENBQUM7SUFDdEIsT0FBTyxDQUFDLElBQUksQ0FBQyxHQUFHLENBQUMsR0FBRyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUM7SUFDekIsR0FBRyxHQUFHLEdBQUcsQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDLENBQUM7R0FDbEI7O0VBRUQsT0FBTyxJQUFJLEtBQUssQ0FBQyxNQUFNLENBQUMsTUFBTSxDQUFDLE9BQU8sQ0FBQyxFQUFFLEdBQUcsQ0FBQyxDQUFDO0NBQy9DOztBQUVELFNBQVMsU0FBUyxDQUFDLEdBQUcsRUFBRSxJQUFJLEVBQUU7RUFDNUIsSUFBSSxPQUFPLEdBQUcsRUFBRSxDQUFDOztFQUVqQixLQUFLLENBQUMsSUFBSSxJQUFJLEVBQUU7SUFDZCxJQUFJLE1BQU0sR0FBRyxHQUFHLENBQUMsQ0FBQyxDQUFDLENBQUM7O0lBRXBCLElBQUksTUFBTSxLQUFLLElBQUksRUFBRTtNQUNuQixPQUFPLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQyxDQUFDO0tBQ2pCLE1BQU0sSUFBSSxNQUFNLFlBQVksS0FBSyxFQUFFO01BQ2xDLE9BQU8sQ0FBQyxJQUFJLENBQUMsTUFBTSxDQUFDLEdBQUcsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDO0tBQzdCO0dBQ0Y7O0VBRUQsT0FBTyxNQUFNLENBQUMsTUFBTSxDQUFDLE9BQU8sQ0FBQyxDQUFDO0NBQy9COztBQUVELFNBQVMsU0FBUyxDQUFDLEdBQUcsRUFBRSxHQUFHLEVBQUUsR0FBRyxFQUFFO0VBQ2hDLElBQUksSUFBSSxHQUFHLEdBQUcsQ0FBQzs7RUFFZixLQUFLLElBQUksQ0FBQyxJQUFJLGVBQWUsQ0FBQyxHQUFHLENBQUMsRUFBRTtJQUNsQyxJQUFJLEdBQUcsR0FBRyxDQUFDLENBQUMsRUFBRSxHQUFHLENBQUMsQ0FBQyxDQUFDLEVBQUUsSUFBSSxDQUFDLENBQUM7R0FDN0I7O0VBRUQsT0FBTyxJQUFJLENBQUM7Q0FDYjs7QUFFRCxnQkFVZTtFQUNiLGFBQWE7RUFDYixLQUFLO0VBQ0wsUUFBUTtFQUNSLFVBQVU7RUFDVixTQUFTO0VBQ1QsWUFBWTtFQUNaLFdBQVc7RUFDWCxPQUFPO0VBQ1AsZUFBZTtFQUNmLGtCQUFrQjtFQUNsQixnQkFBZ0I7RUFDaEIsd0JBQXdCO0VBQ3hCLG1CQUFtQjtFQUNuQixZQUFZO0VBQ1osWUFBWTtFQUNaLElBQUk7RUFDSixJQUFJO0VBQ0osR0FBRztFQUNILEdBQUc7RUFDSCxHQUFHO0VBQ0gsSUFBSTtFQUNKLEdBQUc7RUFDSCxLQUFLO0VBQ0wsS0FBSztFQUNMLGdCQUFnQjtFQUNoQixTQUFTO0VBQ1QsUUFBUTtFQUNSLE9BQU87RUFDUCxPQUFPO0VBQ1AsVUFBVTtFQUNWLE9BQU87RUFDUCxVQUFVO0VBQ1YsU0FBUztFQUNULE9BQU87RUFDUCxTQUFTO0VBQ1QsUUFBUTtFQUNSLFNBQVM7RUFDVCxTQUFTO0NBQ1YsQ0FBQzs7QUMxYUYsU0FBUyxLQUFLLENBQUMsU0FBUyxFQUFFLE9BQU8sRUFBRTtFQUNqQyxPQUFPLFFBQVEsQ0FBQyxRQUFRLENBQUMsR0FBRyxPQUFPLENBQUMsQ0FBQyxTQUFTLENBQUMsQ0FBQztDQUNqRDs7QUFFRCxTQUFTLElBQUksQ0FBQyxPQUFPLEVBQUU7RUFDckIsS0FBSyxJQUFJLE1BQU0sSUFBSSxPQUFPLEVBQUU7SUFDMUIsSUFBSSxNQUFNLENBQUMsQ0FBQyxDQUFDLEVBQUU7TUFDYixPQUFPLE1BQU0sQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDO0tBQ3BCO0dBQ0Y7O0VBRUQsTUFBTSxJQUFJLEtBQUssRUFBRSxDQUFDO0NBQ25COztBQUVELFNBQVMsVUFBVSxDQUFDLEdBQUcsRUFBRSxNQUFNLEVBQUU7RUFDL0IsT0FBTyxNQUFNLENBQUMsTUFBTSxDQUFDLE1BQU0sQ0FBQyxNQUFNLENBQUMsTUFBTSxDQUFDLE1BQU0sQ0FBQyxHQUFHLENBQUMsV0FBVyxDQUFDLFNBQVMsQ0FBQyxFQUFFLEdBQUcsRUFBRSxNQUFNLENBQUMsQ0FBQyxDQUFDO0NBQzVGOztBQUVELFNBQVMsSUFBSSxDQUFDLFdBQVcsRUFBRSxHQUFHLEVBQUUsTUFBTSxHQUFHLE1BQU0sSUFBSSxFQUFFLElBQUksR0FBRyxFQUFFLEVBQUUsY0FBYyxHQUFHLEVBQUUsRUFBRTtFQUNuRixJQUFJLE9BQU8sR0FBRyxXQUFXLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUM7RUFDaEMsSUFBSSxVQUFVLEdBQUcsV0FBVyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDOztFQUVuQyxJQUFJLFdBQVcsQ0FBQyxNQUFNLEtBQUssQ0FBQyxFQUFFO0lBQzVCLElBQUksVUFBVSxZQUFZLFNBQVMsRUFBRTtNQUNuQyxJQUFJLE9BQU8sR0FBRyxVQUFVLENBQUMsS0FBSyxDQUFDLENBQUMsRUFBRSxPQUFPLENBQUMsU0FBUyxFQUFFLENBQUMsQ0FBQztNQUN2RCxJQUFJLENBQUMsR0FBRyxDQUFDLENBQUM7O01BRVYsT0FBTyxPQUFPLENBQUMsU0FBUyxJQUFJLE9BQU8sQ0FBQyxTQUFTLEVBQUUsRUFBRTtRQUMvQyxJQUFJLENBQUMsR0FBRyxRQUFRLENBQUMsY0FBYyxDQUFDLE9BQU8sRUFBRSxPQUFPLENBQUMsQ0FBQztRQUNsRCxJQUFJLElBQUksR0FBRyxjQUFjLENBQUMsTUFBTSxDQUFDLENBQUMsQ0FBQyxDQUFDOztRQUVwQyxJQUFJLENBQUMsSUFBSSxNQUFNLENBQUMsS0FBSyxDQUFDLElBQUksRUFBRSxJQUFJLENBQUMsRUFBRTtVQUNqQyxJQUFJLEdBQUcsSUFBSSxDQUFDLE1BQU0sQ0FBQyxDQUFDLEdBQUcsQ0FBQyxLQUFLLENBQUMsSUFBSSxFQUFFLElBQUksQ0FBQyxDQUFDLENBQUMsQ0FBQztTQUM3Qzs7UUFFRCxPQUFPLEdBQUcsVUFBVSxDQUFDLEtBQUssQ0FBQyxPQUFPLENBQUMsU0FBUyxFQUFFLEdBQUcsQ0FBQyxFQUFFLE9BQU8sQ0FBQyxTQUFTLEVBQUUsR0FBRyxDQUFDLENBQUMsR0FBRyxDQUFDLENBQUMsQ0FBQyxDQUFDO1FBQ25GLENBQUMsRUFBRSxDQUFDO09BQ0w7O01BRUQsT0FBTyxJQUFJLENBQUM7S0FDYixNQUFNO01BQ0wsS0FBSyxJQUFJLElBQUksSUFBSSxVQUFVLEVBQUU7UUFDM0IsSUFBSSxDQUFDLEdBQUcsUUFBUSxDQUFDLGNBQWMsQ0FBQyxPQUFPLEVBQUUsSUFBSSxDQUFDLENBQUM7UUFDL0MsSUFBSSxJQUFJLEdBQUcsY0FBYyxDQUFDLE1BQU0sQ0FBQyxDQUFDLENBQUMsQ0FBQzs7UUFFcEMsSUFBSSxDQUFDLElBQUksTUFBTSxDQUFDLEtBQUssQ0FBQyxJQUFJLEVBQUUsSUFBSSxDQUFDLEVBQUU7VUFDakMsSUFBSSxHQUFHLElBQUksQ0FBQyxNQUFNLENBQUMsQ0FBQyxHQUFHLENBQUMsS0FBSyxDQUFDLElBQUksRUFBRSxJQUFJLENBQUMsQ0FBQyxDQUFDLENBQUM7U0FDN0M7T0FDRjs7TUFFRCxPQUFPLElBQUksQ0FBQztLQUNiO0dBQ0YsTUFBTTtJQUNMLElBQUksS0FBSyxHQUFHLEVBQUUsQ0FBQzs7SUFFZixJQUFJLFVBQVUsWUFBWSxTQUFTLEVBQUU7TUFDbkMsSUFBSSxPQUFPLEdBQUcsVUFBVSxDQUFDLEtBQUssQ0FBQyxDQUFDLEVBQUUsT0FBTyxDQUFDLFNBQVMsRUFBRSxDQUFDLENBQUM7TUFDdkQsSUFBSSxDQUFDLEdBQUcsQ0FBQyxDQUFDOztNQUVWLE9BQU8sT0FBTyxDQUFDLFNBQVMsSUFBSSxPQUFPLENBQUMsU0FBUyxFQUFFLEVBQUU7UUFDL0MsSUFBSSxDQUFDLEdBQUcsUUFBUSxDQUFDLGNBQWMsQ0FBQyxPQUFPLEVBQUUsT0FBTyxDQUFDLENBQUM7UUFDbEQsSUFBSSxDQUFDLEVBQUU7VUFDTCxLQUFLLEdBQUcsSUFBSSxDQUFDLE1BQU0sQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLFdBQVcsQ0FBQyxLQUFLLENBQUMsQ0FBQyxDQUFDLEVBQUUsR0FBRyxFQUFFLE1BQU0sRUFBRSxLQUFLLEVBQUUsY0FBYyxDQUFDLE1BQU0sQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUM7U0FDcEc7O1FBRUQsT0FBTyxHQUFHLFVBQVUsQ0FBQyxLQUFLLENBQUMsT0FBTyxDQUFDLFNBQVMsRUFBRSxHQUFHLENBQUMsRUFBRSxPQUFPLENBQUMsU0FBUyxFQUFFLEdBQUcsQ0FBQyxDQUFDLEdBQUcsQ0FBQyxDQUFDLENBQUMsQ0FBQztRQUNuRixDQUFDLEVBQUUsQ0FBQztPQUNMO0tBQ0YsTUFBTTtNQUNMLEtBQUssSUFBSSxJQUFJLElBQUksVUFBVSxFQUFFO1FBQzNCLElBQUksQ0FBQyxHQUFHLFFBQVEsQ0FBQyxjQUFjLENBQUMsT0FBTyxFQUFFLElBQUksQ0FBQyxDQUFDO1FBQy9DLElBQUksQ0FBQyxFQUFFO1VBQ0wsS0FBSyxHQUFHLElBQUksQ0FBQyxNQUFNLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxXQUFXLENBQUMsS0FBSyxDQUFDLENBQUMsQ0FBQyxFQUFFLEdBQUcsRUFBRSxNQUFNLEVBQUUsS0FBSyxFQUFFLGNBQWMsQ0FBQyxNQUFNLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDO1NBQ3BHO09BQ0Y7S0FDRjs7SUFFRCxPQUFPLEtBQUssQ0FBQztHQUNkO0NBQ0Y7O0FBRUQsU0FBUyxJQUFJLENBQUMsTUFBTSxFQUFFLGVBQWUsRUFBRSxTQUFTLEVBQUUsYUFBYSxFQUFFLGNBQWMsRUFBRTtFQUMvRSxJQUFJLE1BQU0sR0FBRyxJQUFJLENBQUM7O0VBRWxCLElBQUk7SUFDRixNQUFNLEdBQUcsTUFBTSxFQUFFLENBQUM7R0FDbkIsQ0FBQyxPQUFPLENBQUMsRUFBRTtJQUNWLElBQUksU0FBUyxHQUFHLElBQUksQ0FBQzs7SUFFckIsSUFBSSxlQUFlLEVBQUU7TUFDbkIsSUFBSTtRQUNGLFNBQVMsR0FBRyxlQUFlLENBQUMsQ0FBQyxDQUFDLENBQUM7UUFDL0IsT0FBTyxTQUFTLENBQUM7T0FDbEIsQ0FBQyxPQUFPLEVBQUUsRUFBRTtRQUNYLElBQUksRUFBRSxZQUFZLFFBQVEsQ0FBQyxVQUFVLEVBQUU7VUFDckMsTUFBTSxFQUFFLENBQUM7U0FDVjtPQUNGO0tBQ0Y7O0lBRUQsSUFBSSxTQUFTLEVBQUU7TUFDYixJQUFJO1FBQ0YsU0FBUyxHQUFHLFNBQVMsQ0FBQyxDQUFDLENBQUMsQ0FBQztRQUN6QixPQUFPLFNBQVMsQ0FBQztPQUNsQixDQUFDLE9BQU8sRUFBRSxFQUFFO1FBQ1gsSUFBSSxFQUFFLFlBQVksUUFBUSxDQUFDLFVBQVUsRUFBRTtVQUNyQyxNQUFNLEVBQUUsQ0FBQztTQUNWO09BQ0Y7S0FDRjs7SUFFRCxNQUFNLENBQUMsQ0FBQztHQUNULFNBQVM7SUFDUixJQUFJLGNBQWMsRUFBRTtNQUNsQixjQUFjLEVBQUUsQ0FBQztLQUNsQjtHQUNGOztFQUVELElBQUksYUFBYSxFQUFFO0lBQ2pCLElBQUk7TUFDRixPQUFPLGFBQWEsQ0FBQyxNQUFNLENBQUMsQ0FBQztLQUM5QixDQUFDLE9BQU8sRUFBRSxFQUFFO01BQ1gsSUFBSSxFQUFFLFlBQVksUUFBUSxDQUFDLFVBQVUsRUFBRTtRQUNyQyxNQUFNLElBQUksS0FBSyxDQUFDLHdCQUF3QixDQUFDLENBQUM7T0FDM0M7O01BRUQsTUFBTSxFQUFFLENBQUM7S0FDVjtHQUNGLE1BQU07SUFDTCxPQUFPLE1BQU0sQ0FBQztHQUNmO0NBQ0Y7O0FBRUQsU0FBUyxLQUFLLENBQUMsR0FBRyxJQUFJLEVBQUU7RUFDdEIsSUFBSSxVQUFVLEdBQUcsRUFBRSxDQUFDOztFQUVwQixLQUFLLElBQUksQ0FBQyxHQUFHLENBQUMsRUFBRSxDQUFDLEdBQUcsSUFBSSxDQUFDLE1BQU0sRUFBRSxDQUFDLEVBQUUsRUFBRTtJQUNwQyxJQUFJLENBQUMsS0FBSyxJQUFJLENBQUMsTUFBTSxHQUFHLENBQUMsRUFBRTtNQUN6QixPQUFPLElBQUksQ0FBQyxDQUFDLENBQUMsQ0FBQyxLQUFLLENBQUMsSUFBSSxFQUFFLFVBQVUsQ0FBQyxDQUFDO0tBQ3hDLE1BQU07TUFDTCxJQUFJLENBQUMsT0FBTyxFQUFFLElBQUksQ0FBQyxHQUFHLElBQUksQ0FBQyxDQUFDLENBQUMsQ0FBQzs7TUFFOUIsSUFBSSxNQUFNLEdBQUcsSUFBSSxDQUFDLEtBQUssQ0FBQyxJQUFJLEVBQUUsVUFBVSxDQUFDLENBQUM7O01BRTFDLElBQUksYUFBYSxHQUFHLFFBQVEsQ0FBQyxjQUFjLENBQUMsT0FBTyxFQUFFLE1BQU0sQ0FBQyxDQUFDOztNQUU3RCxJQUFJLGFBQWEsSUFBSSxJQUFJLEVBQUU7UUFDekIsT0FBTyxNQUFNLENBQUM7T0FDZixNQUFNO1FBQ0wsVUFBVSxHQUFHLFVBQVUsQ0FBQyxNQUFNLENBQUMsYUFBYSxDQUFDLENBQUM7T0FDL0M7S0FDRjtHQUNGOztFQUVELE9BQU8sSUFBSSxDQUFDO0NBQ2I7O0FBRUQscUJBQWU7RUFDYixLQUFLO0VBQ0wsSUFBSTtFQUNKLFVBQVU7RUFDVixJQUFJO0VBQ0osSUFBSTtFQUNKLEtBQUs7Q0FDTixDQUFDOztBQ2pLRixTQUFTLENBQUMsVUFBVSxFQUFFLENBQUMsU0FBUyxHQUFHLFNBQVMsQ0FBQyxVQUFVLEVBQUUsQ0FBQyxTQUFTLElBQUksSUFBSSxhQUFhLEVBQUUsQ0FBQzs7QUFFM0YsV0FBZTtFQUNiLGFBQWE7RUFDYixLQUFLO0VBQ0wsR0FBRztFQUNILFNBQVM7RUFDVCxRQUFRO0VBQ1IsT0FBTztFQUNQLEtBQUs7RUFDTCxTQUFTO0VBQ1QsWUFBWSxnQkFBQTtDQUNiLENBQUM7O0FDakJGLElBQUksSUFBSSxHQUFHOztFQUVULFlBQVksRUFBRSxVQUFVLFVBQVUsRUFBRSxHQUFHLEdBQUcsQ0FBQyxJQUFJLENBQUMsRUFBRTtJQUNoRCxLQUFLLElBQUksSUFBSSxJQUFJLFVBQVUsRUFBRTtNQUMzQixJQUFJLENBQUMsR0FBRyxDQUFDLElBQUksQ0FBQyxFQUFFO1FBQ2QsT0FBTyxLQUFLLENBQUM7T0FDZDtLQUNGOztJQUVELE9BQU8sSUFBSSxDQUFDO0dBQ2I7O0VBRUQsWUFBWSxFQUFFLFVBQVUsVUFBVSxFQUFFLEdBQUcsR0FBRyxDQUFDLElBQUksQ0FBQyxFQUFFO0lBQ2hELEtBQUssSUFBSSxJQUFJLElBQUksVUFBVSxFQUFFO01BQzNCLElBQUksR0FBRyxDQUFDLElBQUksQ0FBQyxFQUFFO1FBQ2IsT0FBTyxJQUFJLENBQUM7T0FDYjtLQUNGOztJQUVELE9BQU8sS0FBSyxDQUFDO0dBQ2Q7O0VBRUQsRUFBRSxFQUFFLFVBQVUsVUFBVSxFQUFFLENBQUMsRUFBRSxXQUFXLEdBQUcsSUFBSSxFQUFFO0lBQy9DLElBQUksQ0FBQyxHQUFHLElBQUksQ0FBQyxLQUFLLENBQUMsVUFBVSxDQUFDLElBQUksQ0FBQyxHQUFHLENBQUMsRUFBRTtNQUN2QyxPQUFPLFdBQVcsQ0FBQztLQUNwQjs7SUFFRCxPQUFPLFVBQVUsQ0FBQyxDQUFDLENBQUMsQ0FBQztHQUN0Qjs7RUFFRCxNQUFNLEVBQUUsVUFBVSxHQUFHLFNBQVMsRUFBRTtJQUM5QixPQUFPLFNBQVMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxNQUFNLENBQUMsU0FBUyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUM7R0FDMUM7O0VBRUQsS0FBSyxFQUFFLFVBQVUsVUFBVSxFQUFFLEdBQUcsR0FBRyxJQUFJLEVBQUU7SUFDdkMsSUFBSSxHQUFHLElBQUksSUFBSSxFQUFFO01BQ2YsT0FBTyxVQUFVLENBQUMsTUFBTSxDQUFDO0tBQzFCLE1BQU07TUFDTCxPQUFPLFVBQVUsQ0FBQyxNQUFNLENBQUMsR0FBRyxDQUFDLENBQUMsTUFBTSxDQUFDO0tBQ3RDO0dBQ0Y7O0VBRUQsSUFBSSxFQUFFLFVBQVUsVUFBVSxFQUFFLEtBQUssRUFBRTtJQUNqQyxPQUFPLFVBQVUsQ0FBQyxLQUFLLENBQUMsS0FBSyxDQUFDLENBQUM7R0FDaEM7O0VBRUQsVUFBVSxFQUFFLFVBQVUsVUFBVSxFQUFFLEdBQUcsRUFBRTtJQUNyQyxJQUFJLEtBQUssR0FBRyxDQUFDLENBQUM7O0lBRWQsS0FBSyxJQUFJLElBQUksSUFBSSxVQUFVLEVBQUU7TUFDM0IsSUFBSSxHQUFHLENBQUMsSUFBSSxDQUFDLEVBQUU7UUFDYixLQUFLLEdBQUcsS0FBSyxHQUFHLENBQUMsQ0FBQztPQUNuQixNQUFNO1FBQ0wsTUFBTTtPQUNQO0tBQ0Y7O0lBRUQsT0FBTyxVQUFVLENBQUMsS0FBSyxDQUFDLEtBQUssQ0FBQyxDQUFDO0dBQ2hDOztFQUVELElBQUksRUFBRSxVQUFVLFVBQVUsRUFBRSxHQUFHLEVBQUU7SUFDL0IsS0FBSyxJQUFJLElBQUksSUFBSSxVQUFVLEVBQUU7TUFDM0IsR0FBRyxDQUFDLElBQUksQ0FBQyxDQUFDO0tBQ1g7R0FDRjs7RUFFRCxjQUFjLEVBQUUsVUFBVSxVQUFVLEVBQUU7SUFDcEMsT0FBTyxVQUFVLENBQUMsTUFBTSxLQUFLLENBQUMsQ0FBQztHQUNoQzs7RUFFRCxLQUFLLEVBQUUsVUFBVSxVQUFVLEVBQUUsQ0FBQyxFQUFFO0lBQzlCLElBQUksS0FBSyxDQUFDLE9BQU8sQ0FBQyxVQUFVLENBQUMsRUFBRTtNQUM3QixJQUFJLENBQUMsR0FBRyxJQUFJLENBQUMsS0FBSyxDQUFDLFVBQVUsQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLEVBQUU7UUFDeEMsT0FBTyxJQUFJLElBQUksQ0FBQyxLQUFLLENBQUMsTUFBTSxDQUFDLEdBQUcsQ0FBQyxJQUFJLENBQUMsRUFBRSxVQUFVLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQztPQUN4RCxNQUFNO1FBQ0wsT0FBTyxNQUFNLENBQUMsR0FBRyxDQUFDLE9BQU8sQ0FBQyxDQUFDO09BQzVCO0tBQ0Y7O0lBRUQsTUFBTSxJQUFJLEtBQUssQ0FBQyxpQ0FBaUMsQ0FBQyxDQUFDO0dBQ3BEOztFQUVELGNBQWMsRUFBRSxVQUFVLFVBQVUsRUFBRSxDQUFDLEVBQUU7SUFDdkMsSUFBSSxLQUFLLENBQUMsT0FBTyxDQUFDLFVBQVUsQ0FBQyxFQUFFO01BQzdCLElBQUksQ0FBQyxHQUFHLElBQUksQ0FBQyxLQUFLLENBQUMsVUFBVSxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsRUFBRTtRQUN4QyxPQUFPLFVBQVUsQ0FBQyxDQUFDLENBQUMsQ0FBQztPQUN0QixNQUFNO1FBQ0wsTUFBTSxJQUFJLEtBQUssQ0FBQyxxQkFBcUIsQ0FBQyxDQUFDO09BQ3hDO0tBQ0Y7O0lBRUQsTUFBTSxJQUFJLEtBQUssQ0FBQyxpQ0FBaUMsQ0FBQyxDQUFDO0dBQ3BEOztFQUVELE1BQU0sRUFBRSxVQUFVLFVBQVUsRUFBRSxHQUFHLEVBQUU7SUFDakMsSUFBSSxNQUFNLEdBQUcsRUFBRSxDQUFDOztJQUVoQixLQUFLLElBQUksSUFBSSxJQUFJLFVBQVUsRUFBRTtNQUMzQixJQUFJLEdBQUcsQ0FBQyxJQUFJLENBQUMsRUFBRTtRQUNiLE1BQU0sQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLENBQUM7T0FDbkI7S0FDRjs7SUFFRCxPQUFPLE1BQU0sQ0FBQztHQUNmOztFQUVELFVBQVUsRUFBRSxVQUFVLFVBQVUsRUFBRSxNQUFNLEVBQUUsTUFBTSxFQUFFO0lBQ2hELE9BQU8sSUFBSSxDQUFDLEdBQUcsQ0FBQyxJQUFJLENBQUMsTUFBTSxDQUFDLFVBQVUsRUFBRSxNQUFNLENBQUMsRUFBRSxNQUFNLENBQUMsQ0FBQztHQUMxRDs7RUFFRCxJQUFJLEVBQUUsVUFBVSxVQUFVLEVBQUUsT0FBTyxHQUFHLElBQUksRUFBRSxHQUFHLEVBQUU7SUFDL0MsS0FBSyxJQUFJLElBQUksSUFBSSxVQUFVLEVBQUU7TUFDM0IsSUFBSSxHQUFHLENBQUMsSUFBSSxDQUFDLEVBQUU7UUFDYixPQUFPLElBQUksQ0FBQztPQUNiO0tBQ0Y7O0lBRUQsT0FBTyxPQUFPLENBQUM7R0FDaEI7O0VBRUQsSUFBSSxFQUFFLFVBQVUsVUFBVSxFQUFFLElBQUksRUFBRTtJQUNoQyxPQUFPLElBQUksQ0FBQyxNQUFNLENBQUMsVUFBVSxDQUFDLENBQUM7R0FDaEM7O0VBRUQsR0FBRyxFQUFFLFVBQVUsVUFBVSxFQUFFLEdBQUcsRUFBRTtJQUM5QixJQUFJLE1BQU0sR0FBRyxFQUFFLENBQUM7O0lBRWhCLEtBQUssSUFBSSxJQUFJLElBQUksVUFBVSxFQUFFO01BQzNCLE1BQU0sQ0FBQyxJQUFJLENBQUMsR0FBRyxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUM7S0FDeEI7O0lBRUQsT0FBTyxNQUFNLENBQUM7R0FDZjs7RUFFRCxVQUFVLEVBQUUsVUFBVSxVQUFVLEVBQUUsR0FBRyxFQUFFLEdBQUcsRUFBRTtJQUMxQyxJQUFJLE1BQU0sR0FBRyxNQUFNLENBQUMsTUFBTSxDQUFDLEVBQUUsQ0FBQyxDQUFDO0lBQy9CLElBQUksT0FBTyxHQUFHLEdBQUcsQ0FBQzs7SUFFbEIsS0FBSyxJQUFJLENBQUMsR0FBRyxDQUFDLEVBQUUsQ0FBQyxHQUFHLElBQUksQ0FBQyxLQUFLLENBQUMsVUFBVSxDQUFDLEVBQUUsQ0FBQyxFQUFFLEVBQUU7TUFDL0MsSUFBSSxLQUFLLEdBQUcsR0FBRyxDQUFDLFVBQVUsQ0FBQyxDQUFDLENBQUMsRUFBRSxPQUFPLENBQUMsQ0FBQzs7TUFFeEMsT0FBTyxHQUFHLEtBQUssQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDLENBQUM7TUFDdkIsTUFBTSxHQUFHLE1BQU0sQ0FBQyxNQUFNLENBQUMsTUFBTSxDQUFDLE1BQU0sQ0FBQyxDQUFDLEtBQUssQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUM7S0FDdkQ7O0lBRUQsT0FBTyxJQUFJLElBQUksQ0FBQyxLQUFLLENBQUMsTUFBTSxFQUFFLE9BQU8sQ0FBQyxDQUFDO0dBQ3hDOztFQUVELGVBQWUsRUFBRSxVQUFVLFVBQVUsRUFBRSxLQUFLLEVBQUU7SUFDNUMsT0FBTyxVQUFVLENBQUMsUUFBUSxDQUFDLEtBQUssQ0FBQyxDQUFDO0dBQ25DOztFQUVELE1BQU0sRUFBRSxVQUFVLFVBQVUsRUFBRSxHQUFHLEVBQUUsR0FBRyxFQUFFO0lBQ3RDLElBQUksT0FBTyxHQUFHLEdBQUcsQ0FBQzs7SUFFbEIsS0FBSyxJQUFJLENBQUMsR0FBRyxDQUFDLEVBQUUsQ0FBQyxHQUFHLElBQUksQ0FBQyxLQUFLLENBQUMsVUFBVSxDQUFDLEVBQUUsQ0FBQyxFQUFFLEVBQUU7TUFDL0MsSUFBSSxLQUFLLEdBQUcsR0FBRyxDQUFDLFVBQVUsQ0FBQyxDQUFDLENBQUMsRUFBRSxPQUFPLENBQUMsQ0FBQzs7TUFFeEMsT0FBTyxHQUFHLEtBQUssQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDLENBQUM7S0FDeEI7O0lBRUQsT0FBTyxPQUFPLENBQUM7R0FDaEI7O0VBRUQsSUFBSSxFQUFFLFVBQVUsVUFBVSxFQUFFLEtBQUssRUFBRTtJQUNqQyxPQUFPLFVBQVUsQ0FBQyxLQUFLLENBQUMsQ0FBQyxFQUFFLEtBQUssQ0FBQyxDQUFDO0dBQ25DOztFQUVELFVBQVUsRUFBRSxVQUFVLFVBQVUsRUFBRSxHQUFHLEVBQUU7SUFDckMsSUFBSSxNQUFNLEdBQUcsRUFBRSxDQUFDO0lBQ2hCLElBQUksS0FBSyxHQUFHLENBQUMsQ0FBQzs7SUFFZCxLQUFLLElBQUksSUFBSSxJQUFJLFVBQVUsRUFBRTtNQUMzQixJQUFJLEtBQUssR0FBRyxHQUFHLEtBQUssQ0FBQyxFQUFFO1FBQ3JCLE1BQU0sQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLENBQUM7T0FDbkI7S0FDRjs7SUFFRCxPQUFPLE1BQU0sQ0FBQyxNQUFNLENBQUMsTUFBTSxDQUFDLENBQUM7R0FDOUI7O0VBRUQsVUFBVSxFQUFFLFVBQVUsVUFBVSxFQUFFLEdBQUcsRUFBRTtJQUNyQyxJQUFJLEtBQUssR0FBRyxDQUFDLENBQUM7O0lBRWQsS0FBSyxJQUFJLElBQUksSUFBSSxVQUFVLEVBQUU7TUFDM0IsSUFBSSxHQUFHLENBQUMsSUFBSSxDQUFDLEVBQUU7UUFDYixLQUFLLEdBQUcsS0FBSyxHQUFHLENBQUMsQ0FBQztPQUNuQixNQUFNO1FBQ0wsTUFBTTtPQUNQO0tBQ0Y7O0lBRUQsT0FBTyxVQUFVLENBQUMsS0FBSyxDQUFDLENBQUMsRUFBRSxLQUFLLENBQUMsQ0FBQztHQUNuQzs7RUFFRCxPQUFPLEVBQUUsVUFBVSxVQUFVLEVBQUU7SUFDN0IsT0FBTyxVQUFVLENBQUM7R0FDbkI7Q0FDRixDQUFDOztBQ3hNRixJQUFJLFVBQVUsR0FBRyxVQUFVLENBQUMsRUFBRTtJQUMxQixPQUFPLENBQUMsRUFBRSxDQUFDO0NBQ2QsQ0FBQyxZQUFZO0lBQ1YsSUFBSSxNQUFNLEVBQUUsTUFBTSxFQUFFLE9BQU8sQ0FBQztJQUM1QixPQUFPLFNBQVMsQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDLEVBQUUsQ0FBQyxFQUFFO1FBQ3ZCLFNBQVMsQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDLEVBQUU7WUFDYixJQUFJLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxFQUFFO2dCQUNQLElBQUksQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLEVBQUU7b0JBQ1AsSUFBSSxDQUFDLEdBQUcsT0FBTyxPQUFPLElBQUksVUFBVSxJQUFJLE9BQU8sQ0FBQztvQkFDaEQsSUFBSSxDQUFDLENBQUMsSUFBSSxDQUFDLEVBQUUsT0FBTyxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDLENBQUM7b0JBQzdCLElBQUksQ0FBQyxFQUFFLE9BQU8sQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQyxDQUFDO29CQUN2QixJQUFJLENBQUMsR0FBRyxJQUFJLEtBQUssQ0FBQyxzQkFBc0IsR0FBRyxDQUFDLEdBQUcsR0FBRyxDQUFDLENBQUM7b0JBQ3BELE1BQU0sQ0FBQyxDQUFDLElBQUksR0FBRyxrQkFBa0IsRUFBRSxDQUFDLENBQUM7aUJBQ3hDO2dCQUNELElBQUksQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDLENBQUMsR0FBRztvQkFDWCxPQUFPLEVBQUUsRUFBRTtpQkFDZCxDQUFDO2dCQUNGLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxJQUFJLENBQUMsQ0FBQyxDQUFDLE9BQU8sRUFBRSxVQUFVLENBQUMsRUFBRTtvQkFDakMsSUFBSSxDQUFDLEdBQUcsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDO29CQUNuQixPQUFPLENBQUMsQ0FBQyxDQUFDLEdBQUcsQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDO2lCQUN2QixFQUFFLENBQUMsRUFBRSxDQUFDLENBQUMsT0FBTyxFQUFFLENBQUMsRUFBRSxDQUFDLEVBQUUsQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDO2FBQ2hDO1lBQ0QsT0FBTyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsT0FBTyxDQUFDO1NBQ3ZCO1FBQ0QsSUFBSSxDQUFDLEdBQUcsT0FBTyxPQUFPLElBQUksVUFBVSxJQUFJLE9BQU8sQ0FBQztRQUNoRCxLQUFLLElBQUksQ0FBQyxHQUFHLENBQUMsRUFBRSxDQUFDLEdBQUcsQ0FBQyxDQUFDLE1BQU0sRUFBRSxDQUFDLEVBQUUsRUFBRSxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUM7UUFDM0MsT0FBTyxDQUFDLENBQUM7S0FDWixDQUFDO1FBQ0UsQ0FBQyxFQUFFLENBQUMsVUFBVSxPQUFPLEVBQUUsTUFBTSxFQUFFLE9BQU8sRUFBRTs7WUFFcEMsSUFBSSxhQUFhLEdBQUcsT0FBTyxDQUFDLDBCQUEwQixDQUFDLENBQUM7O1lBRXhELE1BQU0sQ0FBQyxPQUFPLEdBQUcsYUFBYSxDQUFDO1NBQ2xDLEVBQUUsRUFBRSwwQkFBMEIsRUFBRSxFQUFFLEVBQUUsQ0FBQyxFQUFFLENBQUMsRUFBRSxDQUFDLFVBQVUsT0FBTyxFQUFFLE1BQU0sRUFBRSxPQUFPLEVBQUU7WUFDNUUsSUFBSSxJQUFJLEdBQUcsT0FBTyxDQUFDLGlCQUFpQixDQUFDLENBQUM7O1lBRXRDLE1BQU0sQ0FBQyxPQUFPLEdBQUcsSUFBSSxDQUFDO1NBQ3pCLEVBQUUsRUFBRSxpQkFBaUIsRUFBRSxFQUFFLEVBQUUsQ0FBQyxFQUFFLENBQUMsRUFBRSxDQUFDLFVBQVUsT0FBTyxFQUFFLE1BQU0sRUFBRSxPQUFPLEVBQUU7WUFDbkUsSUFBSSxDQUFDLEdBQUcsT0FBTyxDQUFDLGdDQUFnQyxDQUFDLENBQUM7O1lBRWxELE1BQU0sQ0FBQyxPQUFPLEdBQUcsQ0FBQyxDQUFDO1NBQ3RCLEVBQUUsRUFBRSxnQ0FBZ0MsRUFBRSxFQUFFLEVBQUUsQ0FBQyxFQUFFLENBQUMsRUFBRSxDQUFDLFVBQVUsT0FBTyxFQUFFLE1BQU0sRUFBRSxPQUFPLEVBQUU7WUFDbEYsSUFBSSxJQUFJLEdBQUcsT0FBTyxDQUFDLFdBQVcsQ0FBQyxDQUFDO1lBQ2hDLElBQUksS0FBSyxHQUFHLE9BQU8sQ0FBQyxZQUFZLENBQUMsQ0FBQztZQUNsQyxJQUFJLENBQUMsR0FBRyxPQUFPLENBQUMsUUFBUSxDQUFDLENBQUM7WUFDMUIsSUFBSSxNQUFNLEdBQUcsT0FBTyxDQUFDLHFCQUFxQixDQUFDLENBQUM7WUFDNUMsSUFBSSxLQUFLLEdBQUcsT0FBTyxDQUFDLGtCQUFrQixDQUFDLENBQUM7WUFDeEMsSUFBSSxLQUFLLEdBQUcsT0FBTyxDQUFDLGtCQUFrQixDQUFDLENBQUM7O1lBRXhDLE1BQU0sQ0FBQyxPQUFPLEdBQUc7Z0JBQ2IsSUFBSSxFQUFFLElBQUk7Z0JBQ1YsS0FBSyxFQUFFLEtBQUs7Z0JBQ1osQ0FBQyxFQUFFLENBQUM7Z0JBQ0osTUFBTSxFQUFFLE1BQU07Z0JBQ2QsS0FBSyxFQUFFLEtBQUs7Z0JBQ1osS0FBSyxFQUFFLEtBQUs7YUFDZixDQUFDO1NBQ0wsRUFBRSxFQUFFLHFCQUFxQixFQUFFLENBQUMsRUFBRSxXQUFXLEVBQUUsQ0FBQyxFQUFFLFFBQVEsRUFBRSxDQUFDLEVBQUUsWUFBWSxFQUFFLEVBQUUsRUFBRSxrQkFBa0IsRUFBRSxFQUFFLEVBQUUsa0JBQWtCLEVBQUUsRUFBRSxFQUFFLENBQUMsRUFBRSxDQUFDLEVBQUUsQ0FBQyxVQUFVLE9BQU8sRUFBRSxNQUFNLEVBQUUsT0FBTyxFQUFFOzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7OztZQWdDckssTUFBTSxDQUFDLE9BQU8sR0FBRyxTQUFTLEtBQUssQ0FBQyxLQUFLLEVBQUU7O2dCQUVuQyxJQUFJLFdBQVcsR0FBRyxNQUFNLENBQUMsU0FBUyxDQUFDLEtBQUs7b0JBQ3BDLGlCQUFpQixHQUFHLE1BQU0sQ0FBQyxJQUFJLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQyxDQUFDLEtBQUssS0FBSzs7O2dCQUdwRCxJQUFJLENBQUM7O2dCQUVMLElBQUksR0FBRyxVQUFVLEdBQUcsRUFBRSxTQUFTLEVBQUUsS0FBSyxFQUFFOztvQkFFcEMsSUFBSSxNQUFNLENBQUMsU0FBUyxDQUFDLFFBQVEsQ0FBQyxJQUFJLENBQUMsU0FBUyxDQUFDLEtBQUssaUJBQWlCLEVBQUU7d0JBQ2pFLE9BQU8sV0FBVyxDQUFDLElBQUksQ0FBQyxHQUFHLEVBQUUsU0FBUyxFQUFFLEtBQUssQ0FBQyxDQUFDO3FCQUNsRDtvQkFDRCxJQUFJLE1BQU0sR0FBRyxFQUFFO3dCQUNYLEtBQUssR0FBRyxDQUFDLFNBQVMsQ0FBQyxVQUFVLEdBQUcsR0FBRyxHQUFHLEVBQUUsQ0FBQyxHQUFHLENBQUMsU0FBUyxDQUFDLFNBQVMsR0FBRyxHQUFHLEdBQUcsRUFBRSxDQUFDLEdBQUcsQ0FBQyxTQUFTLENBQUMsUUFBUSxHQUFHLEdBQUcsR0FBRyxFQUFFLENBQUMsR0FBRztvQkFDckgsU0FBUyxDQUFDLE1BQU0sR0FBRyxHQUFHLEdBQUcsRUFBRSxDQUFDOzs7b0JBRzVCLGFBQWEsR0FBRyxDQUFDOzs7b0JBR2pCLFNBQVMsR0FBRyxJQUFJLE1BQU0sQ0FBQyxTQUFTLENBQUMsTUFBTSxFQUFFLEtBQUssR0FBRyxHQUFHLENBQUM7d0JBQ2pELFVBQVU7d0JBQ1YsS0FBSzt3QkFDTCxTQUFTO3dCQUNULFVBQVUsQ0FBQztvQkFDZixHQUFHLElBQUksRUFBRSxDQUFDO29CQUNWLElBQUksQ0FBQyxpQkFBaUIsRUFBRTs7d0JBRXBCLFVBQVUsR0FBRyxJQUFJLE1BQU0sQ0FBQyxHQUFHLEdBQUcsU0FBUyxDQUFDLE1BQU0sR0FBRyxVQUFVLEVBQUUsS0FBSyxDQUFDLENBQUM7cUJBQ3ZFOzs7Ozs7OztvQkFRRCxLQUFLLEdBQUcsS0FBSyxLQUFLLEtBQUssR0FBRyxDQUFDLENBQUMsS0FBSyxDQUFDO29CQUNsQyxLQUFLLEtBQUssQ0FBQyxDQUFDO29CQUNaLE9BQU8sS0FBSyxHQUFHLFNBQVMsQ0FBQyxJQUFJLENBQUMsR0FBRyxDQUFDLEVBQUU7O3dCQUVoQyxTQUFTLEdBQUcsS0FBSyxDQUFDLEtBQUssR0FBRyxLQUFLLENBQUMsQ0FBQyxDQUFDLENBQUMsTUFBTSxDQUFDO3dCQUMxQyxJQUFJLFNBQVMsR0FBRyxhQUFhLEVBQUU7NEJBQzNCLE1BQU0sQ0FBQyxJQUFJLENBQUMsR0FBRyxDQUFDLEtBQUssQ0FBQyxhQUFhLEVBQUUsS0FBSyxDQUFDLEtBQUssQ0FBQyxDQUFDLENBQUM7Ozs0QkFHbkQsSUFBSSxDQUFDLGlCQUFpQixJQUFJLEtBQUssQ0FBQyxNQUFNLEdBQUcsQ0FBQyxFQUFFO2dDQUN4QyxLQUFLLENBQUMsQ0FBQyxDQUFDLENBQUMsT0FBTyxDQUFDLFVBQVUsRUFBRSxZQUFZO29DQUNyQyxLQUFLLElBQUksQ0FBQyxHQUFHLENBQUMsRUFBRSxDQUFDLEdBQUcsU0FBUyxDQUFDLE1BQU0sR0FBRyxDQUFDLEVBQUUsQ0FBQyxFQUFFLEVBQUU7d0NBQzNDLElBQUksU0FBUyxDQUFDLENBQUMsQ0FBQyxLQUFLLEtBQUssRUFBRTs0Q0FDeEIsS0FBSyxDQUFDLENBQUMsQ0FBQyxHQUFHLEtBQUssQ0FBQzt5Q0FDcEI7cUNBQ0o7aUNBQ0osQ0FBQyxDQUFDOzZCQUNOOzRCQUNELElBQUksS0FBSyxDQUFDLE1BQU0sR0FBRyxDQUFDLElBQUksS0FBSyxDQUFDLEtBQUssR0FBRyxHQUFHLENBQUMsTUFBTSxFQUFFO2dDQUM5QyxLQUFLLENBQUMsU0FBUyxDQUFDLElBQUksQ0FBQyxLQUFLLENBQUMsTUFBTSxFQUFFLEtBQUssQ0FBQyxLQUFLLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQzs2QkFDdEQ7NEJBQ0QsVUFBVSxHQUFHLEtBQUssQ0FBQyxDQUFDLENBQUMsQ0FBQyxNQUFNLENBQUM7NEJBQzdCLGFBQWEsR0FBRyxTQUFTLENBQUM7NEJBQzFCLElBQUksTUFBTSxDQUFDLE1BQU0sSUFBSSxLQUFLLEVBQUU7Z0NBQ3hCLE1BQU07NkJBQ1Q7eUJBQ0o7d0JBQ0QsSUFBSSxTQUFTLENBQUMsU0FBUyxLQUFLLEtBQUssQ0FBQyxLQUFLLEVBQUU7NEJBQ3JDLFNBQVMsQ0FBQyxTQUFTLEVBQUUsQ0FBQzt5QkFDekI7cUJBQ0o7b0JBQ0QsSUFBSSxhQUFhLEtBQUssR0FBRyxDQUFDLE1BQU0sRUFBRTt3QkFDOUIsSUFBSSxVQUFVLElBQUksQ0FBQyxTQUFTLENBQUMsSUFBSSxDQUFDLEVBQUUsQ0FBQyxFQUFFOzRCQUNuQyxNQUFNLENBQUMsSUFBSSxDQUFDLEVBQUUsQ0FBQyxDQUFDO3lCQUNuQjtxQkFDSixNQUFNO3dCQUNILE1BQU0sQ0FBQyxJQUFJLENBQUMsR0FBRyxDQUFDLEtBQUssQ0FBQyxhQUFhLENBQUMsQ0FBQyxDQUFDO3FCQUN6QztvQkFDRCxPQUFPLE1BQU0sQ0FBQyxNQUFNLEdBQUcsS0FBSyxHQUFHLE1BQU0sQ0FBQyxLQUFLLENBQUMsQ0FBQyxFQUFFLEtBQUssQ0FBQyxHQUFHLE1BQU0sQ0FBQztpQkFDbEUsQ0FBQzs7Z0JBRUYsT0FBTyxJQUFJLENBQUM7YUFDZixFQUFFLENBQUM7U0FDUCxFQUFFLEVBQUUsQ0FBQyxFQUFFLENBQUMsRUFBRSxDQUFDLFVBQVUsT0FBTyxFQUFFLE1BQU0sRUFBRSxPQUFPLEVBQUUsRUFBRSxFQUFFLEVBQUUsQ0FBQyxFQUFFLENBQUMsRUFBRSxDQUFDLFVBQVUsT0FBTyxFQUFFLE1BQU0sRUFBRSxPQUFPLEVBQUU7WUFDN0YsWUFBWSxDQUFDOztZQUViLElBQUksb0JBQW9CLEdBQUcsT0FBTyxDQUFDLHdCQUF3QixDQUFDLENBQUM7O1lBRTdELElBQUksVUFBVSxHQUFHLEdBQUcsQ0FBQztZQUNyQixvQkFBb0IsQ0FBQyxVQUFVLEVBQUUsVUFBVSxDQUFDLENBQUM7O1lBRTdDLElBQUksT0FBTyxHQUFHLGlCQUFpQixHQUFHLFVBQVUsQ0FBQzs7WUFFN0MsTUFBTSxDQUFDLE9BQU8sR0FBRyxPQUFPLENBQUM7O1lBRXpCLFNBQVMsT0FBTyxDQUFDLElBQUksRUFBRTtnQkFDbkIsSUFBSSxJQUFJLEdBQUcsSUFBSSxDQUFDLE9BQU8sQ0FBQyxDQUFDOztnQkFFekIsSUFBSSxDQUFDLElBQUksRUFBRTtvQkFDUCxJQUFJLEdBQUcsSUFBSSxDQUFDLE9BQU8sQ0FBQyxHQUFHLEVBQUUsQ0FBQztpQkFDN0I7O2dCQUVELE9BQU8sSUFBSSxDQUFDO2FBQ2Y7U0FDSixFQUFFLEVBQUUsd0JBQXdCLEVBQUUsQ0FBQyxFQUFFLENBQUMsRUFBRSxDQUFDLEVBQUUsQ0FBQyxVQUFVLE9BQU8sRUFBRSxNQUFNLEVBQUUsT0FBTyxFQUFFO1lBQ3pFLENBQUMsVUFBVSxNQUFNLEVBQUU7Z0JBQ2YsWUFBWSxDQUFDOzs7O2dCQUliLElBQUksSUFBSSxHQUFHLE9BQU8sTUFBTSxLQUFLLFdBQVcsR0FBRyxNQUFNLEdBQUcsT0FBTyxNQUFNLEtBQUssV0FBVyxHQUFHLE1BQU0sR0FBRyxFQUFFLENBQUM7O2dCQUVoRyxNQUFNLENBQUMsT0FBTyxHQUFHLFVBQVUsQ0FBQzs7Z0JBRTVCLFNBQVMsVUFBVSxDQUFDLEdBQUcsRUFBRSxLQUFLLEVBQUU7b0JBQzVCLElBQUksR0FBRyxJQUFJLElBQUksRUFBRTt3QkFDYixPQUFPLElBQUksQ0FBQyxHQUFHLENBQUMsQ0FBQztxQkFDcEI7O29CQUVELElBQUksQ0FBQyxHQUFHLENBQUMsR0FBRyxLQUFLLENBQUM7O29CQUVsQixPQUFPLEtBQUssQ0FBQztpQkFDaEI7YUFDSixDQUFDLENBQUMsSUFBSSxDQUFDLElBQUksRUFBRSxPQUFPLE1BQU0sS0FBSyxXQUFXLEdBQUcsTUFBTSxHQUFHLE9BQU8sSUFBSSxLQUFLLFdBQVcsR0FBRyxJQUFJLEdBQUcsT0FBTyxNQUFNLEtBQUssV0FBVyxHQUFHLE1BQU0sR0FBRyxFQUFFLENBQUMsQ0FBQztTQUM1SSxFQUFFLEVBQUUsQ0FBQyxFQUFFLENBQUMsRUFBRSxDQUFDLFVBQVUsT0FBTyxFQUFFLE1BQU0sRUFBRSxPQUFPLEVBQUU7WUFDNUMsWUFBWSxDQUFDOztZQUViLElBQUksVUFBVSxHQUFHLE9BQU8sQ0FBQyxZQUFZLENBQUMsQ0FBQzs7WUFFdkMsTUFBTSxDQUFDLE9BQU8sR0FBRyxVQUFVLENBQUM7O1lBRTVCLFNBQVMsVUFBVSxDQUFDLFVBQVUsRUFBRSxPQUFPLEVBQUUsWUFBWSxFQUFFO2dCQUNuRCxJQUFJLEdBQUcsR0FBRywyQkFBMkIsR0FBRyxVQUFVLENBQUM7Z0JBQ25ELElBQUksVUFBVSxHQUFHLEdBQUcsR0FBRyxvQkFBb0IsQ0FBQzs7Z0JBRTVDLElBQUksWUFBWSxHQUFHLFVBQVUsQ0FBQyxVQUFVLEVBQUUsT0FBTyxDQUFDLENBQUM7O2dCQUVuRCxJQUFJLFlBQVksS0FBSyxPQUFPLEVBQUU7b0JBQzFCLE1BQU0sSUFBSSxLQUFLLENBQUMsNEJBQTRCLEdBQUcsVUFBVSxHQUFHLEtBQUssR0FBRywyQkFBMkIsR0FBRyxZQUFZLEdBQUcsZUFBZSxHQUFHLHdDQUF3QyxHQUFHLE9BQU8sQ0FBQyxDQUFDO2lCQUMxTDs7Z0JBRUQsT0FBTyxVQUFVLENBQUMsR0FBRyxFQUFFLFlBQVksQ0FBQyxDQUFDO2FBQ3hDO1NBQ0osRUFBRSxFQUFFLFlBQVksRUFBRSxDQUFDLEVBQUUsQ0FBQyxFQUFFLEVBQUUsRUFBRSxDQUFDLFVBQVUsT0FBTyxFQUFFLE1BQU0sRUFBRSxPQUFPLEVBQUU7WUFDOUQsQ0FBQyxVQUFVLE1BQU0sRUFBRTtnQkFDZixJQUFJLFFBQVEsR0FBRyxPQUFPLE1BQU0sS0FBSyxXQUFXLEdBQUcsTUFBTSxHQUFHLE9BQU8sTUFBTSxLQUFLLFdBQVcsR0FBRyxNQUFNLEdBQUcsRUFBRSxDQUFDO2dCQUNwRyxJQUFJLE1BQU0sR0FBRyxPQUFPLENBQUMsY0FBYyxDQUFDLENBQUM7O2dCQUVyQyxJQUFJLE9BQU8sUUFBUSxLQUFLLFdBQVcsRUFBRTtvQkFDakMsTUFBTSxDQUFDLE9BQU8sR0FBRyxRQUFRLENBQUM7aUJBQzdCLE1BQU07b0JBQ0gsSUFBSSxLQUFLLEdBQUcsUUFBUSxDQUFDLDJCQUEyQixDQUFDLENBQUM7O29CQUVsRCxJQUFJLENBQUMsS0FBSyxFQUFFO3dCQUNSLEtBQUssR0FBRyxRQUFRLENBQUMsMkJBQTJCLENBQUMsR0FBRyxNQUFNLENBQUM7cUJBQzFEOztvQkFFRCxNQUFNLENBQUMsT0FBTyxHQUFHLEtBQUssQ0FBQztpQkFDMUI7YUFDSixDQUFDLENBQUMsSUFBSSxDQUFDLElBQUksRUFBRSxPQUFPLE1BQU0sS0FBSyxXQUFXLEdBQUcsTUFBTSxHQUFHLE9BQU8sSUFBSSxLQUFLLFdBQVcsR0FBRyxJQUFJLEdBQUcsT0FBTyxNQUFNLEtBQUssV0FBVyxHQUFHLE1BQU0sR0FBRyxFQUFFLENBQUMsQ0FBQztTQUM1SSxFQUFFLEVBQUUsY0FBYyxFQUFFLENBQUMsRUFBRSxDQUFDLEVBQUUsRUFBRSxFQUFFLENBQUMsVUFBVSxPQUFPLEVBQUUsTUFBTSxFQUFFLE9BQU8sRUFBRTtZQUNoRSxZQUFZLENBQUM7O1lBRWIsTUFBTSxDQUFDLE9BQU8sR0FBRyxTQUFTLFFBQVEsQ0FBQyxDQUFDLEVBQUU7Z0JBQ2xDLE9BQU8sT0FBTyxDQUFDLEtBQUssUUFBUSxJQUFJLENBQUMsS0FBSyxJQUFJLENBQUM7YUFDOUMsQ0FBQztTQUNMLEVBQUUsRUFBRSxDQUFDLEVBQUUsRUFBRSxFQUFFLENBQUMsVUFBVSxPQUFPLEVBQUUsTUFBTSxFQUFFLE9BQU8sRUFBRTtZQUM3QyxJQUFJLGFBQWEsR0FBRyxLQUFLLENBQUMsT0FBTyxDQUFDO1lBQ2xDLElBQUksUUFBUSxHQUFHLE1BQU0sQ0FBQyxTQUFTLENBQUMsUUFBUSxDQUFDOztZQUV6QyxNQUFNLENBQUMsT0FBTyxHQUFHLGFBQWEsSUFBSSxPQUFPLENBQUM7O1lBRTFDLFNBQVMsT0FBTyxDQUFDLEdBQUcsRUFBRTtnQkFDbEIsT0FBTyxRQUFRLENBQUMsSUFBSSxDQUFDLEdBQUcsQ0FBQyxLQUFLLGdCQUFnQixDQUFDO2FBQ2xEO1NBQ0osRUFBRSxFQUFFLENBQUMsRUFBRSxFQUFFLEVBQUUsQ0FBQyxVQUFVLE9BQU8sRUFBRSxNQUFNLEVBQUUsT0FBTyxFQUFFO1lBQzdDLElBQUksS0FBSyxHQUFHLE9BQU8sQ0FBQyxpQkFBaUIsQ0FBQyxDQUFDOztZQUV2QyxNQUFNLENBQUMsT0FBTyxHQUFHLEtBQUssQ0FBQztTQUMxQixFQUFFLEVBQUUsaUJBQWlCLEVBQUUsRUFBRSxFQUFFLENBQUMsRUFBRSxFQUFFLEVBQUUsQ0FBQyxVQUFVLE9BQU8sRUFBRSxNQUFNLEVBQUUsT0FBTyxFQUFFO1lBQ3BFLElBQUksUUFBUSxHQUFHLE9BQU8sQ0FBQyxXQUFXLENBQUMsQ0FBQztZQUNwQyxJQUFJLE1BQU0sR0FBRyxPQUFPLENBQUMsc0JBQXNCLENBQUMsQ0FBQzs7WUFFN0MsTUFBTSxDQUFDLE9BQU8sR0FBRyxlQUFlLENBQUM7O1lBRWpDLFNBQVMsZUFBZSxDQUFDLElBQUksRUFBRSxLQUFLLEVBQUUsUUFBUSxFQUFFO2dCQUM1QyxLQUFLLElBQUksUUFBUSxJQUFJLEtBQUssRUFBRTtvQkFDeEIsSUFBSSxTQUFTLEdBQUcsS0FBSyxDQUFDLFFBQVEsQ0FBQyxDQUFDOztvQkFFaEMsSUFBSSxTQUFTLEtBQUssU0FBUyxFQUFFO3dCQUN6QixjQUFjLENBQUMsSUFBSSxFQUFFLFFBQVEsRUFBRSxTQUFTLEVBQUUsUUFBUSxDQUFDLENBQUM7cUJBQ3ZELE1BQU0sSUFBSSxNQUFNLENBQUMsU0FBUyxDQUFDLEVBQUU7d0JBQzFCLGNBQWMsQ0FBQyxJQUFJLEVBQUUsUUFBUSxFQUFFLFNBQVMsRUFBRSxRQUFRLENBQUMsQ0FBQzt3QkFDcEQsSUFBSSxTQUFTLENBQUMsSUFBSSxFQUFFOzRCQUNoQixTQUFTLENBQUMsSUFBSSxDQUFDLElBQUksRUFBRSxRQUFRLEVBQUUsUUFBUSxHQUFHLFFBQVEsQ0FBQyxRQUFRLENBQUMsR0FBRyxTQUFTLENBQUMsQ0FBQzt5QkFDN0U7cUJBQ0osTUFBTTt3QkFDSCxJQUFJLFFBQVEsQ0FBQyxTQUFTLENBQUMsRUFBRTs0QkFDckIsV0FBVyxDQUFDLElBQUksRUFBRSxLQUFLLEVBQUUsUUFBUSxFQUFFLFFBQVEsRUFBRSxTQUFTLENBQUMsQ0FBQzt5QkFDM0QsTUFBTTs0QkFDSCxJQUFJLENBQUMsUUFBUSxDQUFDLEdBQUcsU0FBUyxDQUFDO3lCQUM5QjtxQkFDSjtpQkFDSjthQUNKOztZQUVELFNBQVMsY0FBYyxDQUFDLElBQUksRUFBRSxRQUFRLEVBQUUsU0FBUyxFQUFFLFFBQVEsRUFBRTtnQkFDekQsSUFBSSxRQUFRLEVBQUU7b0JBQ1YsSUFBSSxhQUFhLEdBQUcsUUFBUSxDQUFDLFFBQVEsQ0FBQyxDQUFDOztvQkFFdkMsSUFBSSxDQUFDLE1BQU0sQ0FBQyxhQUFhLENBQUMsRUFBRTt3QkFDeEIsSUFBSSxRQUFRLEtBQUssWUFBWSxFQUFFOzRCQUMzQixLQUFLLElBQUksUUFBUSxJQUFJLGFBQWEsRUFBRTtnQ0FDaEMsSUFBSSxDQUFDLGVBQWUsQ0FBQyxRQUFRLENBQUMsQ0FBQzs2QkFDbEM7eUJBQ0osTUFBTSxJQUFJLFFBQVEsS0FBSyxPQUFPLEVBQUU7NEJBQzdCLEtBQUssSUFBSSxDQUFDLElBQUksYUFBYSxFQUFFO2dDQUN6QixJQUFJLENBQUMsS0FBSyxDQUFDLENBQUMsQ0FBQyxHQUFHLEVBQUUsQ0FBQzs2QkFDdEI7eUJBQ0osTUFBTSxJQUFJLE9BQU8sYUFBYSxLQUFLLFFBQVEsRUFBRTs0QkFDMUMsSUFBSSxDQUFDLFFBQVEsQ0FBQyxHQUFHLEVBQUUsQ0FBQzt5QkFDdkIsTUFBTTs0QkFDSCxJQUFJLENBQUMsUUFBUSxDQUFDLEdBQUcsSUFBSSxDQUFDO3lCQUN6QjtxQkFDSixNQUFNLElBQUksYUFBYSxDQUFDLE1BQU0sRUFBRTt3QkFDN0IsYUFBYSxDQUFDLE1BQU0sQ0FBQyxJQUFJLEVBQUUsUUFBUSxFQUFFLFNBQVMsQ0FBQyxDQUFDO3FCQUNuRDtpQkFDSjthQUNKOztZQUVELFNBQVMsV0FBVyxDQUFDLElBQUksRUFBRSxLQUFLLEVBQUUsUUFBUSxFQUFFLFFBQVEsRUFBRSxTQUFTLEVBQUU7Z0JBQzdELElBQUksYUFBYSxHQUFHLFFBQVEsR0FBRyxRQUFRLENBQUMsUUFBUSxDQUFDLEdBQUcsU0FBUyxDQUFDOzs7Z0JBRzlELElBQUksUUFBUSxLQUFLLFlBQVksRUFBRTtvQkFDM0IsS0FBSyxJQUFJLFFBQVEsSUFBSSxTQUFTLEVBQUU7d0JBQzVCLElBQUksU0FBUyxHQUFHLFNBQVMsQ0FBQyxRQUFRLENBQUMsQ0FBQzs7d0JBRXBDLElBQUksU0FBUyxLQUFLLFNBQVMsRUFBRTs0QkFDekIsSUFBSSxDQUFDLGVBQWUsQ0FBQyxRQUFRLENBQUMsQ0FBQzt5QkFDbEMsTUFBTTs0QkFDSCxJQUFJLENBQUMsWUFBWSxDQUFDLFFBQVEsRUFBRSxTQUFTLENBQUMsQ0FBQzt5QkFDMUM7cUJBQ0o7O29CQUVELE9BQU87aUJBQ1Y7O2dCQUVELElBQUksYUFBYSxJQUFJLFFBQVEsQ0FBQyxhQUFhLENBQUMsSUFBSSxZQUFZLENBQUMsYUFBYSxDQUFDLEtBQUssWUFBWSxDQUFDLFNBQVMsQ0FBQyxFQUFFO29CQUNyRyxJQUFJLENBQUMsUUFBUSxDQUFDLEdBQUcsU0FBUyxDQUFDO29CQUMzQixPQUFPO2lCQUNWOztnQkFFRCxJQUFJLENBQUMsUUFBUSxDQUFDLElBQUksQ0FBQyxRQUFRLENBQUMsQ0FBQyxFQUFFO29CQUMzQixJQUFJLENBQUMsUUFBUSxDQUFDLEdBQUcsRUFBRSxDQUFDO2lCQUN2Qjs7Z0JBRUQsSUFBSSxRQUFRLEdBQUcsUUFBUSxLQUFLLE9BQU8sR0FBRyxFQUFFLEdBQUcsU0FBUyxDQUFDOztnQkFFckQsS0FBSyxJQUFJLENBQUMsSUFBSSxTQUFTLEVBQUU7b0JBQ3JCLElBQUksS0FBSyxHQUFHLFNBQVMsQ0FBQyxDQUFDLENBQUMsQ0FBQztvQkFDekIsSUFBSSxDQUFDLFFBQVEsQ0FBQyxDQUFDLENBQUMsQ0FBQyxHQUFHLEtBQUssS0FBSyxTQUFTLEdBQUcsUUFBUSxHQUFHLEtBQUssQ0FBQztpQkFDOUQ7YUFDSjs7WUFFRCxTQUFTLFlBQVksQ0FBQyxLQUFLLEVBQUU7Z0JBQ3pCLElBQUksTUFBTSxDQUFDLGNBQWMsRUFBRTtvQkFDdkIsT0FBTyxNQUFNLENBQUMsY0FBYyxDQUFDLEtBQUssQ0FBQyxDQUFDO2lCQUN2QyxNQUFNLElBQUksS0FBSyxDQUFDLFNBQVMsRUFBRTtvQkFDeEIsT0FBTyxLQUFLLENBQUMsU0FBUyxDQUFDO2lCQUMxQixNQUFNLElBQUksS0FBSyxDQUFDLFdBQVcsRUFBRTtvQkFDMUIsT0FBTyxLQUFLLENBQUMsV0FBVyxDQUFDLFNBQVMsQ0FBQztpQkFDdEM7YUFDSjtTQUNKLEVBQUUsRUFBRSxzQkFBc0IsRUFBRSxFQUFFLEVBQUUsV0FBVyxFQUFFLEVBQUUsRUFBRSxDQUFDLEVBQUUsRUFBRSxFQUFFLENBQUMsVUFBVSxPQUFPLEVBQUUsTUFBTSxFQUFFLE9BQU8sRUFBRTtZQUMxRixJQUFJLFFBQVEsR0FBRyxPQUFPLENBQUMsaUJBQWlCLENBQUMsQ0FBQzs7WUFFMUMsSUFBSSxlQUFlLEdBQUcsT0FBTyxDQUFDLG9CQUFvQixDQUFDLENBQUM7O1lBRXBELElBQUksT0FBTyxHQUFHLE9BQU8sQ0FBQyxzQkFBc0IsQ0FBQyxDQUFDO1lBQzlDLElBQUksT0FBTyxHQUFHLE9BQU8sQ0FBQyxzQkFBc0IsQ0FBQyxDQUFDO1lBQzlDLElBQUksUUFBUSxHQUFHLE9BQU8sQ0FBQyx1QkFBdUIsQ0FBQyxDQUFDO1lBQ2hELElBQUksV0FBVyxHQUFHLE9BQU8sQ0FBQywwQkFBMEIsQ0FBQyxDQUFDOztZQUV0RCxNQUFNLENBQUMsT0FBTyxHQUFHLGFBQWEsQ0FBQzs7WUFFL0IsU0FBUyxhQUFhLENBQUMsS0FBSyxFQUFFLElBQUksRUFBRTtnQkFDaEMsSUFBSSxHQUFHLEdBQUcsSUFBSSxHQUFHLElBQUksQ0FBQyxRQUFRLElBQUksUUFBUSxHQUFHLFFBQVEsQ0FBQztnQkFDdEQsSUFBSSxJQUFJLEdBQUcsSUFBSSxHQUFHLElBQUksQ0FBQyxJQUFJLEdBQUcsSUFBSSxDQUFDOztnQkFFbkMsS0FBSyxHQUFHLFdBQVcsQ0FBQyxLQUFLLENBQUMsQ0FBQyxDQUFDLENBQUM7O2dCQUU3QixJQUFJLFFBQVEsQ0FBQyxLQUFLLENBQUMsRUFBRTtvQkFDakIsT0FBTyxLQUFLLENBQUMsSUFBSSxFQUFFLENBQUM7aUJBQ3ZCLE1BQU0sSUFBSSxPQUFPLENBQUMsS0FBSyxDQUFDLEVBQUU7b0JBQ3ZCLE9BQU8sR0FBRyxDQUFDLGNBQWMsQ0FBQyxLQUFLLENBQUMsSUFBSSxDQUFDLENBQUM7aUJBQ3pDLE1BQU0sSUFBSSxDQUFDLE9BQU8sQ0FBQyxLQUFLLENBQUMsRUFBRTtvQkFDeEIsSUFBSSxJQUFJLEVBQUU7d0JBQ04sSUFBSSxDQUFDLHNDQUFzQyxFQUFFLEtBQUssQ0FBQyxDQUFDO3FCQUN2RDtvQkFDRCxPQUFPLElBQUksQ0FBQztpQkFDZjs7Z0JBRUQsSUFBSSxJQUFJLEdBQUcsS0FBSyxDQUFDLFNBQVMsS0FBSyxJQUFJLEdBQUcsR0FBRyxDQUFDLGFBQWEsQ0FBQyxLQUFLLENBQUMsT0FBTyxDQUFDLEdBQUcsR0FBRyxDQUFDLGVBQWUsQ0FBQyxLQUFLLENBQUMsU0FBUyxFQUFFLEtBQUssQ0FBQyxPQUFPLENBQUMsQ0FBQzs7Z0JBRTdILElBQUksS0FBSyxHQUFHLEtBQUssQ0FBQyxVQUFVLENBQUM7Z0JBQzdCLGVBQWUsQ0FBQyxJQUFJLEVBQUUsS0FBSyxDQUFDLENBQUM7O2dCQUU3QixJQUFJLFFBQVEsR0FBRyxLQUFLLENBQUMsUUFBUSxDQUFDOztnQkFFOUIsS0FBSyxJQUFJLENBQUMsR0FBRyxDQUFDLEVBQUUsQ0FBQyxHQUFHLFFBQVEsQ0FBQyxNQUFNLEVBQUUsQ0FBQyxFQUFFLEVBQUU7b0JBQ3RDLElBQUksU0FBUyxHQUFHLGFBQWEsQ0FBQyxRQUFRLENBQUMsQ0FBQyxDQUFDLEVBQUUsSUFBSSxDQUFDLENBQUM7b0JBQ2pELElBQUksU0FBUyxFQUFFO3dCQUNYLElBQUksQ0FBQyxXQUFXLENBQUMsU0FBUyxDQUFDLENBQUM7cUJBQy9CO2lCQUNKOztnQkFFRCxPQUFPLElBQUksQ0FBQzthQUNmO1NBQ0osRUFBRSxFQUFFLDBCQUEwQixFQUFFLEVBQUUsRUFBRSxzQkFBc0IsRUFBRSxFQUFFLEVBQUUsc0JBQXNCLEVBQUUsRUFBRSxFQUFFLHVCQUF1QixFQUFFLEVBQUUsRUFBRSxvQkFBb0IsRUFBRSxFQUFFLEVBQUUsaUJBQWlCLEVBQUUsRUFBRSxFQUFFLENBQUMsRUFBRSxFQUFFLEVBQUUsQ0FBQyxVQUFVLE9BQU8sRUFBRSxNQUFNLEVBQUUsT0FBTyxFQUFFOzs7Ozs7O1lBT25OLElBQUksT0FBTyxHQUFHLEVBQUUsQ0FBQzs7WUFFakIsTUFBTSxDQUFDLE9BQU8sR0FBRyxRQUFRLENBQUM7O1lBRTFCLFNBQVMsUUFBUSxDQUFDLFFBQVEsRUFBRSxJQUFJLEVBQUUsT0FBTyxFQUFFLEtBQUssRUFBRTtnQkFDOUMsSUFBSSxDQUFDLE9BQU8sSUFBSSxPQUFPLENBQUMsTUFBTSxLQUFLLENBQUMsRUFBRTtvQkFDbEMsT0FBTyxFQUFFLENBQUM7aUJBQ2IsTUFBTTtvQkFDSCxPQUFPLENBQUMsSUFBSSxDQUFDLFNBQVMsQ0FBQyxDQUFDO29CQUN4QixPQUFPLE9BQU8sQ0FBQyxRQUFRLEVBQUUsSUFBSSxFQUFFLE9BQU8sRUFBRSxLQUFLLEVBQUUsQ0FBQyxDQUFDLENBQUM7aUJBQ3JEO2FBQ0o7O1lBRUQsU0FBUyxPQUFPLENBQUMsUUFBUSxFQUFFLElBQUksRUFBRSxPQUFPLEVBQUUsS0FBSyxFQUFFLFNBQVMsRUFBRTtnQkFDeEQsS0FBSyxHQUFHLEtBQUssSUFBSSxFQUFFLENBQUM7O2dCQUVwQixJQUFJLFFBQVEsRUFBRTtvQkFDVixJQUFJLFlBQVksQ0FBQyxPQUFPLEVBQUUsU0FBUyxFQUFFLFNBQVMsQ0FBQyxFQUFFO3dCQUM3QyxLQUFLLENBQUMsU0FBUyxDQUFDLEdBQUcsUUFBUSxDQUFDO3FCQUMvQjs7b0JBRUQsSUFBSSxTQUFTLEdBQUcsSUFBSSxDQUFDLFFBQVEsQ0FBQzs7b0JBRTlCLElBQUksU0FBUyxFQUFFOzt3QkFFWCxJQUFJLFVBQVUsR0FBRyxRQUFRLENBQUMsVUFBVSxDQUFDOzt3QkFFckMsS0FBSyxJQUFJLENBQUMsR0FBRyxDQUFDLEVBQUUsQ0FBQyxHQUFHLElBQUksQ0FBQyxRQUFRLENBQUMsTUFBTSxFQUFFLENBQUMsRUFBRSxFQUFFOzRCQUMzQyxTQUFTLElBQUksQ0FBQyxDQUFDOzs0QkFFZixJQUFJLE1BQU0sR0FBRyxTQUFTLENBQUMsQ0FBQyxDQUFDLElBQUksT0FBTyxDQUFDOzRCQUNyQyxJQUFJLFNBQVMsR0FBRyxTQUFTLEdBQUcsQ0FBQyxNQUFNLENBQUMsS0FBSyxJQUFJLENBQUMsQ0FBQyxDQUFDOzs7NEJBR2hELElBQUksWUFBWSxDQUFDLE9BQU8sRUFBRSxTQUFTLEVBQUUsU0FBUyxDQUFDLEVBQUU7Z0NBQzdDLE9BQU8sQ0FBQyxVQUFVLENBQUMsQ0FBQyxDQUFDLEVBQUUsTUFBTSxFQUFFLE9BQU8sRUFBRSxLQUFLLEVBQUUsU0FBUyxDQUFDLENBQUM7NkJBQzdEOzs0QkFFRCxTQUFTLEdBQUcsU0FBUyxDQUFDO3lCQUN6QjtxQkFDSjtpQkFDSjs7Z0JBRUQsT0FBTyxLQUFLLENBQUM7YUFDaEI7OztZQUdELFNBQVMsWUFBWSxDQUFDLE9BQU8sRUFBRSxJQUFJLEVBQUUsS0FBSyxFQUFFO2dCQUN4QyxJQUFJLE9BQU8sQ0FBQyxNQUFNLEtBQUssQ0FBQyxFQUFFO29CQUN0QixPQUFPLEtBQUssQ0FBQztpQkFDaEI7O2dCQUVELElBQUksUUFBUSxHQUFHLENBQUMsQ0FBQztnQkFDakIsSUFBSSxRQUFRLEdBQUcsT0FBTyxDQUFDLE1BQU0sR0FBRyxDQUFDLENBQUM7Z0JBQ2xDLElBQUksWUFBWSxDQUFDO2dCQUNqQixJQUFJLFdBQVcsQ0FBQzs7Z0JBRWhCLE9BQU8sUUFBUSxJQUFJLFFBQVEsRUFBRTtvQkFDekIsWUFBWSxHQUFHLENBQUMsUUFBUSxHQUFHLFFBQVEsQ0FBQyxHQUFHLENBQUMsSUFBSSxDQUFDLENBQUM7b0JBQzlDLFdBQVcsR0FBRyxPQUFPLENBQUMsWUFBWSxDQUFDLENBQUM7O29CQUVwQyxJQUFJLFFBQVEsS0FBSyxRQUFRLEVBQUU7d0JBQ3ZCLE9BQU8sV0FBVyxJQUFJLElBQUksSUFBSSxXQUFXLElBQUksS0FBSyxDQUFDO3FCQUN0RCxNQUFNLElBQUksV0FBVyxHQUFHLElBQUksRUFBRTt3QkFDM0IsUUFBUSxHQUFHLFlBQVksR0FBRyxDQUFDLENBQUM7cUJBQy9CLE1BQU0sSUFBSSxXQUFXLEdBQUcsS0FBSyxFQUFFO3dCQUM1QixRQUFRLEdBQUcsWUFBWSxHQUFHLENBQUMsQ0FBQztxQkFDL0IsTUFBTTt3QkFDSCxPQUFPLElBQUksQ0FBQztxQkFDZjtpQkFDSjs7Z0JBRUQsT0FBTyxLQUFLLENBQUM7YUFDaEI7O1lBRUQsU0FBUyxTQUFTLENBQUMsQ0FBQyxFQUFFLENBQUMsRUFBRTtnQkFDckIsT0FBTyxDQUFDLEdBQUcsQ0FBQyxHQUFHLENBQUMsR0FBRyxDQUFDLENBQUMsQ0FBQzthQUN6QjtTQUNKLEVBQUUsRUFBRSxDQUFDLEVBQUUsRUFBRSxFQUFFLENBQUMsVUFBVSxPQUFPLEVBQUUsTUFBTSxFQUFFLE9BQU8sRUFBRTtZQUM3QyxJQUFJLGVBQWUsR0FBRyxPQUFPLENBQUMsb0JBQW9CLENBQUMsQ0FBQzs7WUFFcEQsSUFBSSxRQUFRLEdBQUcsT0FBTyxDQUFDLHVCQUF1QixDQUFDLENBQUM7WUFDaEQsSUFBSSxNQUFNLEdBQUcsT0FBTyxDQUFDLG9CQUFvQixDQUFDLENBQUM7O1lBRTNDLElBQUksWUFBWSxHQUFHLE9BQU8sQ0FBQyxpQkFBaUIsQ0FBQyxDQUFDOztZQUU5QyxNQUFNLENBQUMsT0FBTyxHQUFHLFVBQVUsQ0FBQzs7WUFFNUIsU0FBUyxVQUFVLENBQUMsTUFBTSxFQUFFLE9BQU8sRUFBRSxhQUFhLEVBQUU7Z0JBQ2hELElBQUksSUFBSSxHQUFHLE1BQU0sQ0FBQyxJQUFJLENBQUM7Z0JBQ3ZCLElBQUksS0FBSyxHQUFHLE1BQU0sQ0FBQyxLQUFLLENBQUM7Z0JBQ3pCLElBQUksS0FBSyxHQUFHLE1BQU0sQ0FBQyxLQUFLLENBQUM7O2dCQUV6QixRQUFRLElBQUk7b0JBQ1IsS0FBSyxNQUFNLENBQUMsTUFBTTt3QkFDZCxPQUFPLFVBQVUsQ0FBQyxPQUFPLEVBQUUsS0FBSyxDQUFDLENBQUM7b0JBQ3RDLEtBQUssTUFBTSxDQUFDLE1BQU07d0JBQ2QsT0FBTyxVQUFVLENBQUMsT0FBTyxFQUFFLEtBQUssRUFBRSxhQUFhLENBQUMsQ0FBQztvQkFDckQsS0FBSyxNQUFNLENBQUMsS0FBSzt3QkFDYixPQUFPLFdBQVcsQ0FBQyxPQUFPLEVBQUUsS0FBSyxFQUFFLEtBQUssRUFBRSxhQUFhLENBQUMsQ0FBQztvQkFDN0QsS0FBSyxNQUFNLENBQUMsTUFBTTt3QkFDZCxPQUFPLFdBQVcsQ0FBQyxPQUFPLEVBQUUsS0FBSyxFQUFFLEtBQUssRUFBRSxhQUFhLENBQUMsQ0FBQztvQkFDN0QsS0FBSyxNQUFNLENBQUMsS0FBSzt3QkFDYixPQUFPLFVBQVUsQ0FBQyxPQUFPLEVBQUUsS0FBSyxFQUFFLEtBQUssRUFBRSxhQUFhLENBQUMsQ0FBQztvQkFDNUQsS0FBSyxNQUFNLENBQUMsS0FBSzt3QkFDYixlQUFlLENBQUMsT0FBTyxFQUFFLEtBQUssQ0FBQyxDQUFDO3dCQUNoQyxPQUFPLE9BQU8sQ0FBQztvQkFDbkIsS0FBSyxNQUFNLENBQUMsS0FBSzt3QkFDYixlQUFlLENBQUMsT0FBTyxFQUFFLEtBQUssRUFBRSxLQUFLLENBQUMsVUFBVSxDQUFDLENBQUM7d0JBQ2xELE9BQU8sT0FBTyxDQUFDO29CQUNuQixLQUFLLE1BQU0sQ0FBQyxLQUFLO3dCQUNiLE9BQU8sV0FBVyxDQUFDLE9BQU8sRUFBRSxhQUFhLENBQUMsS0FBSyxDQUFDLE9BQU8sRUFBRSxLQUFLLEVBQUUsYUFBYSxDQUFDLENBQUMsQ0FBQztvQkFDcEY7d0JBQ0ksT0FBTyxPQUFPLENBQUM7aUJBQ3RCO2FBQ0o7O1lBRUQsU0FBUyxVQUFVLENBQUMsT0FBTyxFQUFFLEtBQUssRUFBRTtnQkFDaEMsSUFBSSxVQUFVLEdBQUcsT0FBTyxDQUFDLFVBQVUsQ0FBQzs7Z0JBRXBDLElBQUksVUFBVSxFQUFFO29CQUNaLFVBQVUsQ0FBQyxXQUFXLENBQUMsT0FBTyxDQUFDLENBQUM7aUJBQ25DOztnQkFFRCxhQUFhLENBQUMsT0FBTyxFQUFFLEtBQUssQ0FBQyxDQUFDOztnQkFFOUIsT0FBTyxJQUFJLENBQUM7YUFDZjs7WUFFRCxTQUFTLFVBQVUsQ0FBQyxVQUFVLEVBQUUsS0FBSyxFQUFFLGFBQWEsRUFBRTtnQkFDbEQsSUFBSSxPQUFPLEdBQUcsYUFBYSxDQUFDLE1BQU0sQ0FBQyxLQUFLLEVBQUUsYUFBYSxDQUFDLENBQUM7O2dCQUV6RCxJQUFJLFVBQVUsRUFBRTtvQkFDWixVQUFVLENBQUMsV0FBVyxDQUFDLE9BQU8sQ0FBQyxDQUFDO2lCQUNuQzs7Z0JBRUQsT0FBTyxVQUFVLENBQUM7YUFDckI7O1lBRUQsU0FBUyxXQUFXLENBQUMsT0FBTyxFQUFFLFNBQVMsRUFBRSxLQUFLLEVBQUUsYUFBYSxFQUFFO2dCQUMzRCxJQUFJLE9BQU8sQ0FBQzs7Z0JBRVosSUFBSSxPQUFPLENBQUMsUUFBUSxLQUFLLENBQUMsRUFBRTtvQkFDeEIsT0FBTyxDQUFDLFdBQVcsQ0FBQyxDQUFDLEVBQUUsT0FBTyxDQUFDLE1BQU0sRUFBRSxLQUFLLENBQUMsSUFBSSxDQUFDLENBQUM7b0JBQ25ELE9BQU8sR0FBRyxPQUFPLENBQUM7aUJBQ3JCLE1BQU07b0JBQ0gsSUFBSSxVQUFVLEdBQUcsT0FBTyxDQUFDLFVBQVUsQ0FBQztvQkFDcEMsT0FBTyxHQUFHLGFBQWEsQ0FBQyxNQUFNLENBQUMsS0FBSyxFQUFFLGFBQWEsQ0FBQyxDQUFDOztvQkFFckQsSUFBSSxVQUFVLElBQUksT0FBTyxLQUFLLE9BQU8sRUFBRTt3QkFDbkMsVUFBVSxDQUFDLFlBQVksQ0FBQyxPQUFPLEVBQUUsT0FBTyxDQUFDLENBQUM7cUJBQzdDO2lCQUNKOztnQkFFRCxPQUFPLE9BQU8sQ0FBQzthQUNsQjs7WUFFRCxTQUFTLFdBQVcsQ0FBQyxPQUFPLEVBQUUsU0FBUyxFQUFFLE1BQU0sRUFBRSxhQUFhLEVBQUU7Z0JBQzVELElBQUksUUFBUSxHQUFHLFlBQVksQ0FBQyxTQUFTLEVBQUUsTUFBTSxDQUFDLENBQUM7Z0JBQy9DLElBQUksT0FBTyxDQUFDOztnQkFFWixJQUFJLFFBQVEsRUFBRTtvQkFDVixPQUFPLEdBQUcsTUFBTSxDQUFDLE1BQU0sQ0FBQyxTQUFTLEVBQUUsT0FBTyxDQUFDLElBQUksT0FBTyxDQUFDO2lCQUMxRCxNQUFNO29CQUNILE9BQU8sR0FBRyxhQUFhLENBQUMsTUFBTSxDQUFDLE1BQU0sRUFBRSxhQUFhLENBQUMsQ0FBQztpQkFDekQ7O2dCQUVELElBQUksVUFBVSxHQUFHLE9BQU8sQ0FBQyxVQUFVLENBQUM7O2dCQUVwQyxJQUFJLFVBQVUsSUFBSSxPQUFPLEtBQUssT0FBTyxFQUFFO29CQUNuQyxVQUFVLENBQUMsWUFBWSxDQUFDLE9BQU8sRUFBRSxPQUFPLENBQUMsQ0FBQztpQkFDN0M7O2dCQUVELElBQUksQ0FBQyxRQUFRLEVBQUU7b0JBQ1gsYUFBYSxDQUFDLE9BQU8sRUFBRSxTQUFTLENBQUMsQ0FBQztpQkFDckM7O2dCQUVELE9BQU8sT0FBTyxDQUFDO2FBQ2xCOztZQUVELFNBQVMsVUFBVSxDQUFDLE9BQU8sRUFBRSxTQUFTLEVBQUUsS0FBSyxFQUFFLGFBQWEsRUFBRTtnQkFDMUQsSUFBSSxVQUFVLEdBQUcsT0FBTyxDQUFDLFVBQVUsQ0FBQztnQkFDcEMsSUFBSSxPQUFPLEdBQUcsYUFBYSxDQUFDLE1BQU0sQ0FBQyxLQUFLLEVBQUUsYUFBYSxDQUFDLENBQUM7O2dCQUV6RCxJQUFJLFVBQVUsSUFBSSxPQUFPLEtBQUssT0FBTyxFQUFFO29CQUNuQyxVQUFVLENBQUMsWUFBWSxDQUFDLE9BQU8sRUFBRSxPQUFPLENBQUMsQ0FBQztpQkFDN0M7O2dCQUVELE9BQU8sT0FBTyxDQUFDO2FBQ2xCOztZQUVELFNBQVMsYUFBYSxDQUFDLE9BQU8sRUFBRSxDQUFDLEVBQUU7Z0JBQy9CLElBQUksT0FBTyxDQUFDLENBQUMsT0FBTyxLQUFLLFVBQVUsSUFBSSxRQUFRLENBQUMsQ0FBQyxDQUFDLEVBQUU7b0JBQ2hELENBQUMsQ0FBQyxPQUFPLENBQUMsT0FBTyxDQUFDLENBQUM7aUJBQ3RCO2FBQ0o7O1lBRUQsU0FBUyxlQUFlLENBQUMsT0FBTyxFQUFFLEtBQUssRUFBRTtnQkFDckMsSUFBSSxVQUFVLEdBQUcsT0FBTyxDQUFDLFVBQVUsQ0FBQztnQkFDcEMsSUFBSSxNQUFNLEdBQUcsRUFBRSxDQUFDO2dCQUNoQixJQUFJLElBQUksQ0FBQztnQkFDVCxJQUFJLE1BQU0sQ0FBQztnQkFDWCxJQUFJLE1BQU0sQ0FBQzs7Z0JBRVgsS0FBSyxJQUFJLENBQUMsR0FBRyxDQUFDLEVBQUUsQ0FBQyxHQUFHLEtBQUssQ0FBQyxPQUFPLENBQUMsTUFBTSxFQUFFLENBQUMsRUFBRSxFQUFFO29CQUMzQyxNQUFNLEdBQUcsS0FBSyxDQUFDLE9BQU8sQ0FBQyxDQUFDLENBQUMsQ0FBQztvQkFDMUIsSUFBSSxHQUFHLFVBQVUsQ0FBQyxNQUFNLENBQUMsSUFBSSxDQUFDLENBQUM7b0JBQy9CLElBQUksTUFBTSxDQUFDLEdBQUcsRUFBRTt3QkFDWixNQUFNLENBQUMsTUFBTSxDQUFDLEdBQUcsQ0FBQyxHQUFHLElBQUksQ0FBQztxQkFDN0I7b0JBQ0QsT0FBTyxDQUFDLFdBQVcsQ0FBQyxJQUFJLENBQUMsQ0FBQztpQkFDN0I7O2dCQUVELElBQUksTUFBTSxHQUFHLFVBQVUsQ0FBQyxNQUFNLENBQUM7Z0JBQy9CLEtBQUssSUFBSSxDQUFDLEdBQUcsQ0FBQyxFQUFFLENBQUMsR0FBRyxLQUFLLENBQUMsT0FBTyxDQUFDLE1BQU0sRUFBRSxDQUFDLEVBQUUsRUFBRTtvQkFDM0MsTUFBTSxHQUFHLEtBQUssQ0FBQyxPQUFPLENBQUMsQ0FBQyxDQUFDLENBQUM7b0JBQzFCLElBQUksR0FBRyxNQUFNLENBQUMsTUFBTSxDQUFDLEdBQUcsQ0FBQyxDQUFDOztvQkFFMUIsT0FBTyxDQUFDLFlBQVksQ0FBQyxJQUFJLEVBQUUsTUFBTSxDQUFDLEVBQUUsSUFBSSxNQUFNLEVBQUUsR0FBRyxJQUFJLEdBQUcsVUFBVSxDQUFDLE1BQU0sQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDO2lCQUNwRjthQUNKOztZQUVELFNBQVMsV0FBVyxDQUFDLE9BQU8sRUFBRSxPQUFPLEVBQUU7Z0JBQ25DLElBQUksT0FBTyxJQUFJLE9BQU8sSUFBSSxPQUFPLEtBQUssT0FBTyxJQUFJLE9BQU8sQ0FBQyxVQUFVLEVBQUU7b0JBQ2pFLE9BQU8sQ0FBQyxVQUFVLENBQUMsWUFBWSxDQUFDLE9BQU8sRUFBRSxPQUFPLENBQUMsQ0FBQztpQkFDckQ7O2dCQUVELE9BQU8sT0FBTyxDQUFDO2FBQ2xCO1NBQ0osRUFBRSxFQUFFLHVCQUF1QixFQUFFLEVBQUUsRUFBRSxvQkFBb0IsRUFBRSxFQUFFLEVBQUUsb0JBQW9CLEVBQUUsRUFBRSxFQUFFLGlCQUFpQixFQUFFLEVBQUUsRUFBRSxDQUFDLEVBQUUsRUFBRSxFQUFFLENBQUMsVUFBVSxPQUFPLEVBQUUsTUFBTSxFQUFFLE9BQU8sRUFBRTtZQUNySixJQUFJLFFBQVEsR0FBRyxPQUFPLENBQUMsaUJBQWlCLENBQUMsQ0FBQztZQUMxQyxJQUFJLE9BQU8sR0FBRyxPQUFPLENBQUMsWUFBWSxDQUFDLENBQUM7O1lBRXBDLElBQUksTUFBTSxHQUFHLE9BQU8sQ0FBQyxrQkFBa0IsQ0FBQyxDQUFDO1lBQ3pDLElBQUksUUFBUSxHQUFHLE9BQU8sQ0FBQyxhQUFhLENBQUMsQ0FBQztZQUN0QyxJQUFJLE9BQU8sR0FBRyxPQUFPLENBQUMsWUFBWSxDQUFDLENBQUM7WUFDcEMsTUFBTSxDQUFDLE9BQU8sR0FBRyxLQUFLLENBQUM7O1lBRXZCLFNBQVMsS0FBSyxDQUFDLFFBQVEsRUFBRSxPQUFPLEVBQUUsYUFBYSxFQUFFO2dCQUM3QyxhQUFhLEdBQUcsYUFBYSxJQUFJLEVBQUUsQ0FBQztnQkFDcEMsYUFBYSxDQUFDLEtBQUssR0FBRyxhQUFhLENBQUMsS0FBSyxJQUFJLGFBQWEsQ0FBQyxLQUFLLEtBQUssS0FBSyxHQUFHLGFBQWEsQ0FBQyxLQUFLLEdBQUcsY0FBYyxDQUFDO2dCQUNsSCxhQUFhLENBQUMsTUFBTSxHQUFHLGFBQWEsQ0FBQyxNQUFNLElBQUksTUFBTSxDQUFDOztnQkFFdEQsT0FBTyxhQUFhLENBQUMsS0FBSyxDQUFDLFFBQVEsRUFBRSxPQUFPLEVBQUUsYUFBYSxDQUFDLENBQUM7YUFDaEU7O1lBRUQsU0FBUyxjQUFjLENBQUMsUUFBUSxFQUFFLE9BQU8sRUFBRSxhQUFhLEVBQUU7Z0JBQ3RELElBQUksT0FBTyxHQUFHLFlBQVksQ0FBQyxPQUFPLENBQUMsQ0FBQzs7Z0JBRXBDLElBQUksT0FBTyxDQUFDLE1BQU0sS0FBSyxDQUFDLEVBQUU7b0JBQ3RCLE9BQU8sUUFBUSxDQUFDO2lCQUNuQjs7Z0JBRUQsSUFBSSxLQUFLLEdBQUcsUUFBUSxDQUFDLFFBQVEsRUFBRSxPQUFPLENBQUMsQ0FBQyxFQUFFLE9BQU8sQ0FBQyxDQUFDO2dCQUNuRCxJQUFJLGFBQWEsR0FBRyxRQUFRLENBQUMsYUFBYSxDQUFDOztnQkFFM0MsSUFBSSxDQUFDLGFBQWEsQ0FBQyxRQUFRLElBQUksYUFBYSxLQUFLLFFBQVEsRUFBRTtvQkFDdkQsYUFBYSxDQUFDLFFBQVEsR0FBRyxhQUFhLENBQUM7aUJBQzFDOztnQkFFRCxLQUFLLElBQUksQ0FBQyxHQUFHLENBQUMsRUFBRSxDQUFDLEdBQUcsT0FBTyxDQUFDLE1BQU0sRUFBRSxDQUFDLEVBQUUsRUFBRTtvQkFDckMsSUFBSSxTQUFTLEdBQUcsT0FBTyxDQUFDLENBQUMsQ0FBQyxDQUFDO29CQUMzQixRQUFRLEdBQUcsVUFBVSxDQUFDLFFBQVEsRUFBRSxLQUFLLENBQUMsU0FBUyxDQUFDLEVBQUUsT0FBTyxDQUFDLFNBQVMsQ0FBQyxFQUFFLGFBQWEsQ0FBQyxDQUFDO2lCQUN4Rjs7Z0JBRUQsT0FBTyxRQUFRLENBQUM7YUFDbkI7O1lBRUQsU0FBUyxVQUFVLENBQUMsUUFBUSxFQUFFLE9BQU8sRUFBRSxTQUFTLEVBQUUsYUFBYSxFQUFFO2dCQUM3RCxJQUFJLENBQUMsT0FBTyxFQUFFO29CQUNWLE9BQU8sUUFBUSxDQUFDO2lCQUNuQjs7Z0JBRUQsSUFBSSxPQUFPLENBQUM7O2dCQUVaLElBQUksT0FBTyxDQUFDLFNBQVMsQ0FBQyxFQUFFO29CQUNwQixLQUFLLElBQUksQ0FBQyxHQUFHLENBQUMsRUFBRSxDQUFDLEdBQUcsU0FBUyxDQUFDLE1BQU0sRUFBRSxDQUFDLEVBQUUsRUFBRTt3QkFDdkMsT0FBTyxHQUFHLE9BQU8sQ0FBQyxTQUFTLENBQUMsQ0FBQyxDQUFDLEVBQUUsT0FBTyxFQUFFLGFBQWEsQ0FBQyxDQUFDOzt3QkFFeEQsSUFBSSxPQUFPLEtBQUssUUFBUSxFQUFFOzRCQUN0QixRQUFRLEdBQUcsT0FBTyxDQUFDO3lCQUN0QjtxQkFDSjtpQkFDSixNQUFNO29CQUNILE9BQU8sR0FBRyxPQUFPLENBQUMsU0FBUyxFQUFFLE9BQU8sRUFBRSxhQUFhLENBQUMsQ0FBQzs7b0JBRXJELElBQUksT0FBTyxLQUFLLFFBQVEsRUFBRTt3QkFDdEIsUUFBUSxHQUFHLE9BQU8sQ0FBQztxQkFDdEI7aUJBQ0o7O2dCQUVELE9BQU8sUUFBUSxDQUFDO2FBQ25COztZQUVELFNBQVMsWUFBWSxDQUFDLE9BQU8sRUFBRTtnQkFDM0IsSUFBSSxPQUFPLEdBQUcsRUFBRSxDQUFDOztnQkFFakIsS0FBSyxJQUFJLEdBQUcsSUFBSSxPQUFPLEVBQUU7b0JBQ3JCLElBQUksR0FBRyxLQUFLLEdBQUcsRUFBRTt3QkFDYixPQUFPLENBQUMsSUFBSSxDQUFDLE1BQU0sQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDO3FCQUM3QjtpQkFDSjs7Z0JBRUQsT0FBTyxPQUFPLENBQUM7YUFDbEI7U0FDSixFQUFFLEVBQUUsa0JBQWtCLEVBQUUsRUFBRSxFQUFFLGFBQWEsRUFBRSxFQUFFLEVBQUUsWUFBWSxFQUFFLEVBQUUsRUFBRSxpQkFBaUIsRUFBRSxFQUFFLEVBQUUsWUFBWSxFQUFFLEVBQUUsRUFBRSxDQUFDLEVBQUUsRUFBRSxFQUFFLENBQUMsVUFBVSxPQUFPLEVBQUUsTUFBTSxFQUFFLE9BQU8sRUFBRTtZQUNuSixJQUFJLFFBQVEsR0FBRyxPQUFPLENBQUMsdUJBQXVCLENBQUMsQ0FBQzs7WUFFaEQsTUFBTSxDQUFDLE9BQU8sR0FBRyxZQUFZLENBQUM7O1lBRTlCLFNBQVMsWUFBWSxDQUFDLENBQUMsRUFBRSxDQUFDLEVBQUU7Z0JBQ3hCLElBQUksUUFBUSxDQUFDLENBQUMsQ0FBQyxJQUFJLFFBQVEsQ0FBQyxDQUFDLENBQUMsRUFBRTtvQkFDNUIsSUFBSSxNQUFNLElBQUksQ0FBQyxJQUFJLE1BQU0sSUFBSSxDQUFDLEVBQUU7d0JBQzVCLE9BQU8sQ0FBQyxDQUFDLEVBQUUsS0FBSyxDQUFDLENBQUMsRUFBRSxDQUFDO3FCQUN4QixNQUFNO3dCQUNILE9BQU8sQ0FBQyxDQUFDLElBQUksS0FBSyxDQUFDLENBQUMsSUFBSSxDQUFDO3FCQUM1QjtpQkFDSjs7Z0JBRUQsT0FBTyxLQUFLLENBQUM7YUFDaEI7U0FDSixFQUFFLEVBQUUsdUJBQXVCLEVBQUUsRUFBRSxFQUFFLENBQUMsRUFBRSxFQUFFLEVBQUUsQ0FBQyxVQUFVLE9BQU8sRUFBRSxNQUFNLEVBQUUsT0FBTyxFQUFFO1lBQzFFLFlBQVksQ0FBQzs7WUFFYixJQUFJLE9BQU8sR0FBRyxPQUFPLENBQUMsVUFBVSxDQUFDLENBQUM7O1lBRWxDLE1BQU0sQ0FBQyxPQUFPLEdBQUcsTUFBTSxDQUFDOztZQUV4QixTQUFTLE1BQU0sQ0FBQyxLQUFLLEVBQUU7Z0JBQ25CLElBQUksQ0FBQyxDQUFDLElBQUksWUFBWSxNQUFNLENBQUMsRUFBRTtvQkFDM0IsT0FBTyxJQUFJLE1BQU0sQ0FBQyxLQUFLLENBQUMsQ0FBQztpQkFDNUI7O2dCQUVELElBQUksQ0FBQyxLQUFLLEdBQUcsS0FBSyxDQUFDO2FBQ3RCOztZQUVELE1BQU0sQ0FBQyxTQUFTLENBQUMsSUFBSSxHQUFHLFVBQVUsSUFBSSxFQUFFLFlBQVksRUFBRTtnQkFDbEQsSUFBSSxFQUFFLEdBQUcsT0FBTyxDQUFDLElBQUksQ0FBQyxDQUFDO2dCQUN2QixJQUFJLFFBQVEsR0FBRyxZQUFZLENBQUMsTUFBTSxDQUFDLENBQUMsQ0FBQyxDQUFDOztnQkFFdEMsRUFBRSxDQUFDLFFBQVEsQ0FBQyxHQUFHLElBQUksQ0FBQyxLQUFLLENBQUM7YUFDN0IsQ0FBQzs7WUFFRixNQUFNLENBQUMsU0FBUyxDQUFDLE1BQU0sR0FBRyxVQUFVLElBQUksRUFBRSxZQUFZLEVBQUU7Z0JBQ3BELElBQUksRUFBRSxHQUFHLE9BQU8sQ0FBQyxJQUFJLENBQUMsQ0FBQztnQkFDdkIsSUFBSSxRQUFRLEdBQUcsWUFBWSxDQUFDLE1BQU0sQ0FBQyxDQUFDLENBQUMsQ0FBQzs7Z0JBRXRDLEVBQUUsQ0FBQyxRQUFRLENBQUMsR0FBRyxTQUFTLENBQUM7YUFDNUIsQ0FBQztTQUNMLEVBQUUsRUFBRSxVQUFVLEVBQUUsQ0FBQyxFQUFFLENBQUMsRUFBRSxFQUFFLEVBQUUsQ0FBQyxVQUFVLE9BQU8sRUFBRSxNQUFNLEVBQUUsT0FBTyxFQUFFO1lBQzVELFlBQVksQ0FBQzs7WUFFYixNQUFNLENBQUMsT0FBTyxHQUFHLFdBQVcsQ0FBQzs7WUFFN0IsU0FBUyxXQUFXLENBQUMsS0FBSyxFQUFFO2dCQUN4QixJQUFJLENBQUMsQ0FBQyxJQUFJLFlBQVksV0FBVyxDQUFDLEVBQUU7b0JBQ2hDLE9BQU8sSUFBSSxXQUFXLENBQUMsS0FBSyxDQUFDLENBQUM7aUJBQ2pDOztnQkFFRCxJQUFJLENBQUMsS0FBSyxHQUFHLEtBQUssQ0FBQzthQUN0Qjs7WUFFRCxXQUFXLENBQUMsU0FBUyxDQUFDLElBQUksR0FBRyxVQUFVLElBQUksRUFBRSxZQUFZLEVBQUU7Z0JBQ3ZELElBQUksSUFBSSxDQUFDLFlBQVksQ0FBQyxLQUFLLElBQUksQ0FBQyxLQUFLLEVBQUU7b0JBQ25DLElBQUksQ0FBQyxZQUFZLENBQUMsR0FBRyxJQUFJLENBQUMsS0FBSyxDQUFDO2lCQUNuQzthQUNKLENBQUM7U0FDTCxFQUFFLEVBQUUsQ0FBQyxFQUFFLEVBQUUsRUFBRSxDQUFDLFVBQVUsT0FBTyxFQUFFLE1BQU0sRUFBRSxPQUFPLEVBQUU7WUFDN0MsWUFBWSxDQUFDOztZQUViLElBQUksT0FBTyxHQUFHLE9BQU8sQ0FBQyxZQUFZLENBQUMsQ0FBQzs7WUFFcEMsSUFBSSxLQUFLLEdBQUcsT0FBTyxDQUFDLG1CQUFtQixDQUFDLENBQUM7WUFDekMsSUFBSSxLQUFLLEdBQUcsT0FBTyxDQUFDLG1CQUFtQixDQUFDLENBQUM7WUFDekMsSUFBSSxPQUFPLEdBQUcsT0FBTyxDQUFDLG1CQUFtQixDQUFDLENBQUM7WUFDM0MsSUFBSSxPQUFPLEdBQUcsT0FBTyxDQUFDLG1CQUFtQixDQUFDLENBQUM7WUFDM0MsSUFBSSxRQUFRLEdBQUcsT0FBTyxDQUFDLG9CQUFvQixDQUFDLENBQUM7WUFDN0MsSUFBSSxNQUFNLEdBQUcsT0FBTyxDQUFDLG1CQUFtQixDQUFDLENBQUM7WUFDMUMsSUFBSSxRQUFRLEdBQUcsT0FBTyxDQUFDLG1CQUFtQixDQUFDLENBQUM7O1lBRTVDLElBQUksUUFBUSxHQUFHLE9BQU8sQ0FBQyxnQkFBZ0IsQ0FBQyxDQUFDO1lBQ3pDLElBQUksV0FBVyxHQUFHLE9BQU8sQ0FBQywwQkFBMEIsQ0FBQyxDQUFDO1lBQ3RELElBQUksTUFBTSxHQUFHLE9BQU8sQ0FBQyxvQkFBb0IsQ0FBQyxDQUFDOztZQUUzQyxNQUFNLENBQUMsT0FBTyxHQUFHLENBQUMsQ0FBQzs7WUFFbkIsU0FBUyxDQUFDLENBQUMsT0FBTyxFQUFFLFVBQVUsRUFBRSxRQUFRLEVBQUU7Z0JBQ3RDLElBQUksVUFBVSxHQUFHLEVBQUUsQ0FBQztnQkFDcEIsSUFBSSxHQUFHLEVBQUUsS0FBSyxFQUFFLEdBQUcsRUFBRSxTQUFTLENBQUM7O2dCQUUvQixJQUFJLENBQUMsUUFBUSxJQUFJLFVBQVUsQ0FBQyxVQUFVLENBQUMsRUFBRTtvQkFDckMsUUFBUSxHQUFHLFVBQVUsQ0FBQztvQkFDdEIsS0FBSyxHQUFHLEVBQUUsQ0FBQztpQkFDZDs7Z0JBRUQsS0FBSyxHQUFHLEtBQUssSUFBSSxVQUFVLElBQUksRUFBRSxDQUFDO2dCQUNsQyxHQUFHLEdBQUcsUUFBUSxDQUFDLE9BQU8sRUFBRSxLQUFLLENBQUMsQ0FBQzs7O2dCQUcvQixJQUFJLEtBQUssQ0FBQyxjQUFjLENBQUMsS0FBSyxDQUFDLEVBQUU7b0JBQzdCLEdBQUcsR0FBRyxLQUFLLENBQUMsR0FBRyxDQUFDO29CQUNoQixLQUFLLENBQUMsR0FBRyxHQUFHLFNBQVMsQ0FBQztpQkFDekI7OztnQkFHRCxJQUFJLEtBQUssQ0FBQyxjQUFjLENBQUMsV0FBVyxDQUFDLEVBQUU7b0JBQ25DLFNBQVMsR0FBRyxLQUFLLENBQUMsU0FBUyxDQUFDO29CQUM1QixLQUFLLENBQUMsU0FBUyxHQUFHLFNBQVMsQ0FBQztpQkFDL0I7OztnQkFHRCxJQUFJLEdBQUcsS0FBSyxPQUFPLElBQUksQ0FBQyxTQUFTLElBQUksS0FBSyxDQUFDLGNBQWMsQ0FBQyxPQUFPLENBQUMsSUFBSSxLQUFLLENBQUMsS0FBSyxLQUFLLFNBQVMsSUFBSSxDQUFDLE1BQU0sQ0FBQyxLQUFLLENBQUMsS0FBSyxDQUFDLEVBQUU7b0JBQ3JILEtBQUssQ0FBQyxLQUFLLEdBQUcsV0FBVyxDQUFDLEtBQUssQ0FBQyxLQUFLLENBQUMsQ0FBQztpQkFDMUM7O2dCQUVELG1CQUFtQixDQUFDLEtBQUssQ0FBQyxDQUFDOztnQkFFM0IsSUFBSSxRQUFRLEtBQUssU0FBUyxJQUFJLFFBQVEsS0FBSyxJQUFJLEVBQUU7b0JBQzdDLFFBQVEsQ0FBQyxRQUFRLEVBQUUsVUFBVSxFQUFFLEdBQUcsRUFBRSxLQUFLLENBQUMsQ0FBQztpQkFDOUM7O2dCQUVELE9BQU8sSUFBSSxLQUFLLENBQUMsR0FBRyxFQUFFLEtBQUssRUFBRSxVQUFVLEVBQUUsR0FBRyxFQUFFLFNBQVMsQ0FBQyxDQUFDO2FBQzVEOztZQUVELFNBQVMsUUFBUSxDQUFDLENBQUMsRUFBRSxVQUFVLEVBQUUsR0FBRyxFQUFFLEtBQUssRUFBRTtnQkFDekMsSUFBSSxPQUFPLENBQUMsS0FBSyxRQUFRLEVBQUU7b0JBQ3ZCLFVBQVUsQ0FBQyxJQUFJLENBQUMsSUFBSSxLQUFLLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQztpQkFDakMsTUFBTSxJQUFJLE9BQU8sQ0FBQyxLQUFLLFFBQVEsRUFBRTtvQkFDOUIsVUFBVSxDQUFDLElBQUksQ0FBQyxJQUFJLEtBQUssQ0FBQyxNQUFNLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDO2lCQUN6QyxNQUFNLElBQUksT0FBTyxDQUFDLENBQUMsQ0FBQyxFQUFFO29CQUNuQixVQUFVLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQyxDQUFDO2lCQUN0QixNQUFNLElBQUksT0FBTyxDQUFDLENBQUMsQ0FBQyxFQUFFO29CQUNuQixLQUFLLElBQUksQ0FBQyxHQUFHLENBQUMsRUFBRSxDQUFDLEdBQUcsQ0FBQyxDQUFDLE1BQU0sRUFBRSxDQUFDLEVBQUUsRUFBRTt3QkFDL0IsUUFBUSxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsRUFBRSxVQUFVLEVBQUUsR0FBRyxFQUFFLEtBQUssQ0FBQyxDQUFDO3FCQUMxQztpQkFDSixNQUFNLElBQUksQ0FBQyxLQUFLLElBQUksSUFBSSxDQUFDLEtBQUssU0FBUyxFQUFFO29CQUN0QyxPQUFPO2lCQUNWLE1BQU07b0JBQ0gsTUFBTSx3QkFBd0IsQ0FBQzt3QkFDM0IsYUFBYSxFQUFFLENBQUM7d0JBQ2hCLFdBQVcsRUFBRTs0QkFDVCxPQUFPLEVBQUUsR0FBRzs0QkFDWixVQUFVLEVBQUUsS0FBSzt5QkFDcEI7cUJBQ0osQ0FBQyxDQUFDO2lCQUNOO2FBQ0o7O1lBRUQsU0FBUyxtQkFBbUIsQ0FBQyxLQUFLLEVBQUU7Z0JBQ2hDLEtBQUssSUFBSSxRQUFRLElBQUksS0FBSyxFQUFFO29CQUN4QixJQUFJLEtBQUssQ0FBQyxjQUFjLENBQUMsUUFBUSxDQUFDLEVBQUU7d0JBQ2hDLElBQUksS0FBSyxHQUFHLEtBQUssQ0FBQyxRQUFRLENBQUMsQ0FBQzs7d0JBRTVCLElBQUksTUFBTSxDQUFDLEtBQUssQ0FBQyxFQUFFOzRCQUNmLFNBQVM7eUJBQ1o7O3dCQUVELElBQUksUUFBUSxDQUFDLE1BQU0sQ0FBQyxDQUFDLEVBQUUsQ0FBQyxDQUFDLEtBQUssS0FBSyxFQUFFOzs0QkFFakMsS0FBSyxDQUFDLFFBQVEsQ0FBQyxHQUFHLE1BQU0sQ0FBQyxLQUFLLENBQUMsQ0FBQzt5QkFDbkM7cUJBQ0o7aUJBQ0o7YUFDSjs7WUFFRCxTQUFTLE9BQU8sQ0FBQyxDQUFDLEVBQUU7Z0JBQ2hCLE9BQU8sT0FBTyxDQUFDLENBQUMsQ0FBQyxJQUFJLE9BQU8sQ0FBQyxDQUFDLENBQUMsSUFBSSxRQUFRLENBQUMsQ0FBQyxDQUFDLElBQUksUUFBUSxDQUFDLENBQUMsQ0FBQyxDQUFDO2FBQ2pFOztZQUVELFNBQVMsVUFBVSxDQUFDLENBQUMsRUFBRTtnQkFDbkIsT0FBTyxPQUFPLENBQUMsS0FBSyxRQUFRLElBQUksT0FBTyxDQUFDLENBQUMsQ0FBQyxJQUFJLE9BQU8sQ0FBQyxDQUFDLENBQUMsQ0FBQzthQUM1RDs7WUFFRCxTQUFTLHdCQUF3QixDQUFDLElBQUksRUFBRTtnQkFDcEMsSUFBSSxHQUFHLEdBQUcsSUFBSSxLQUFLLEVBQUUsQ0FBQzs7Z0JBRXRCLEdBQUcsQ0FBQyxJQUFJLEdBQUcsZ0RBQWdELENBQUM7Z0JBQzVELEdBQUcsQ0FBQyxPQUFPLEdBQUcsMkNBQTJDLEdBQUcscURBQXFELEdBQUcsUUFBUSxHQUFHLFdBQVcsQ0FBQyxJQUFJLENBQUMsYUFBYSxDQUFDLEdBQUcsS0FBSyxHQUFHLHdCQUF3QixHQUFHLFdBQVcsQ0FBQyxJQUFJLENBQUMsV0FBVyxDQUFDLENBQUM7Z0JBQ2xPLElBQUksR0FBRyx3REFBd0QsQ0FBQztnQkFDaEUsR0FBRyxDQUFDLGFBQWEsR0FBRyxJQUFJLENBQUMsYUFBYSxDQUFDO2dCQUN2QyxHQUFHLENBQUMsV0FBVyxHQUFHLElBQUksQ0FBQyxXQUFXLENBQUM7O2dCQUVuQyxPQUFPLEdBQUcsQ0FBQzthQUNkOztZQUVELFNBQVMsV0FBVyxDQUFDLEdBQUcsRUFBRTtnQkFDdEIsSUFBSTtvQkFDQSxPQUFPLElBQUksQ0FBQyxTQUFTLENBQUMsR0FBRyxFQUFFLElBQUksRUFBRSxNQUFNLENBQUMsQ0FBQztpQkFDNUMsQ0FBQyxPQUFPLENBQUMsRUFBRTtvQkFDUixPQUFPLE1BQU0sQ0FBQyxHQUFHLENBQUMsQ0FBQztpQkFDdEI7YUFDSjtTQUNKLEVBQUUsRUFBRSxtQkFBbUIsRUFBRSxFQUFFLEVBQUUsbUJBQW1CLEVBQUUsRUFBRSxFQUFFLG1CQUFtQixFQUFFLEVBQUUsRUFBRSxtQkFBbUIsRUFBRSxFQUFFLEVBQUUsb0JBQW9CLEVBQUUsRUFBRSxFQUFFLG1CQUFtQixFQUFFLEVBQUUsRUFBRSxtQkFBbUIsRUFBRSxFQUFFLEVBQUUsb0JBQW9CLEVBQUUsRUFBRSxFQUFFLDBCQUEwQixFQUFFLEVBQUUsRUFBRSxnQkFBZ0IsRUFBRSxFQUFFLEVBQUUsWUFBWSxFQUFFLEVBQUUsRUFBRSxDQUFDLEVBQUUsRUFBRSxFQUFFLENBQUMsVUFBVSxPQUFPLEVBQUUsTUFBTSxFQUFFLE9BQU8sRUFBRTtZQUMvVCxZQUFZLENBQUM7O1lBRWIsSUFBSSxLQUFLLEdBQUcsT0FBTyxDQUFDLGVBQWUsQ0FBQyxDQUFDOztZQUVyQyxJQUFJLFlBQVksR0FBRyxzQ0FBc0MsQ0FBQztZQUMxRCxJQUFJLFVBQVUsR0FBRyxPQUFPLENBQUM7O1lBRXpCLE1BQU0sQ0FBQyxPQUFPLEdBQUcsUUFBUSxDQUFDOztZQUUxQixTQUFTLFFBQVEsQ0FBQyxHQUFHLEVBQUUsS0FBSyxFQUFFO2dCQUMxQixJQUFJLENBQUMsR0FBRyxFQUFFO29CQUNOLE9BQU8sS0FBSyxDQUFDO2lCQUNoQjs7Z0JBRUQsSUFBSSxJQUFJLEdBQUcsQ0FBQyxLQUFLLENBQUMsY0FBYyxDQUFDLElBQUksQ0FBQyxDQUFDOztnQkFFdkMsSUFBSSxRQUFRLEdBQUcsS0FBSyxDQUFDLEdBQUcsRUFBRSxZQUFZLENBQUMsQ0FBQztnQkFDeEMsSUFBSSxPQUFPLEdBQUcsSUFBSSxDQUFDOztnQkFFbkIsSUFBSSxVQUFVLENBQUMsSUFBSSxDQUFDLFFBQVEsQ0FBQyxDQUFDLENBQUMsQ0FBQyxFQUFFO29CQUM5QixPQUFPLEdBQUcsS0FBSyxDQUFDO2lCQUNuQjs7Z0JBRUQsSUFBSSxPQUFPLEVBQUUsSUFBSSxFQUFFLElBQUksRUFBRSxDQUFDLENBQUM7O2dCQUUzQixLQUFLLENBQUMsR0FBRyxDQUFDLEVBQUUsQ0FBQyxHQUFHLFFBQVEsQ0FBQyxNQUFNLEVBQUUsQ0FBQyxFQUFFLEVBQUU7b0JBQ2xDLElBQUksR0FBRyxRQUFRLENBQUMsQ0FBQyxDQUFDLENBQUM7O29CQUVuQixJQUFJLENBQUMsSUFBSSxFQUFFO3dCQUNQLFNBQVM7cUJBQ1o7O29CQUVELElBQUksR0FBRyxJQUFJLENBQUMsTUFBTSxDQUFDLENBQUMsQ0FBQyxDQUFDOztvQkFFdEIsSUFBSSxDQUFDLE9BQU8sRUFBRTt3QkFDVixPQUFPLEdBQUcsSUFBSSxDQUFDO3FCQUNsQixNQUFNLElBQUksSUFBSSxLQUFLLEdBQUcsRUFBRTt3QkFDckIsT0FBTyxHQUFHLE9BQU8sSUFBSSxFQUFFLENBQUM7d0JBQ3hCLE9BQU8sQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLFNBQVMsQ0FBQyxDQUFDLEVBQUUsSUFBSSxDQUFDLE1BQU0sQ0FBQyxDQUFDLENBQUM7cUJBQ2hELE1BQU0sSUFBSSxJQUFJLEtBQUssR0FBRyxJQUFJLElBQUksRUFBRTt3QkFDN0IsS0FBSyxDQUFDLEVBQUUsR0FBRyxJQUFJLENBQUMsU0FBUyxDQUFDLENBQUMsRUFBRSxJQUFJLENBQUMsTUFBTSxDQUFDLENBQUM7cUJBQzdDO2lCQUNKOztnQkFFRCxJQUFJLE9BQU8sRUFBRTtvQkFDVCxJQUFJLEtBQUssQ0FBQyxTQUFTLEVBQUU7d0JBQ2pCLE9BQU8sQ0FBQyxJQUFJLENBQUMsS0FBSyxDQUFDLFNBQVMsQ0FBQyxDQUFDO3FCQUNqQzs7b0JBRUQsS0FBSyxDQUFDLFNBQVMsR0FBRyxPQUFPLENBQUMsSUFBSSxDQUFDLEdBQUcsQ0FBQyxDQUFDO2lCQUN2Qzs7Z0JBRUQsT0FBTyxLQUFLLENBQUMsU0FBUyxHQUFHLE9BQU8sR0FBRyxPQUFPLENBQUMsV0FBVyxFQUFFLENBQUM7YUFDNUQ7U0FDSixFQUFFLEVBQUUsZUFBZSxFQUFFLENBQUMsRUFBRSxDQUFDLEVBQUUsRUFBRSxFQUFFLENBQUMsVUFBVSxPQUFPLEVBQUUsTUFBTSxFQUFFLE9BQU8sRUFBRTtZQUNqRSxJQUFJLE9BQU8sR0FBRyxPQUFPLENBQUMsWUFBWSxDQUFDLENBQUM7WUFDcEMsSUFBSSxPQUFPLEdBQUcsT0FBTyxDQUFDLFlBQVksQ0FBQyxDQUFDO1lBQ3BDLElBQUksUUFBUSxHQUFHLE9BQU8sQ0FBQyxhQUFhLENBQUMsQ0FBQztZQUN0QyxJQUFJLE9BQU8sR0FBRyxPQUFPLENBQUMsWUFBWSxDQUFDLENBQUM7O1lBRXBDLE1BQU0sQ0FBQyxPQUFPLEdBQUcsV0FBVyxDQUFDOztZQUU3QixTQUFTLFdBQVcsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxFQUFFO2dCQUN2QixJQUFJLFNBQVMsR0FBRyxDQUFDLENBQUM7Z0JBQ2xCLElBQUksU0FBUyxHQUFHLENBQUMsQ0FBQzs7Z0JBRWxCLElBQUksT0FBTyxDQUFDLENBQUMsQ0FBQyxFQUFFO29CQUNaLFNBQVMsR0FBRyxXQUFXLENBQUMsQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDO2lCQUNqQzs7Z0JBRUQsSUFBSSxPQUFPLENBQUMsQ0FBQyxDQUFDLEVBQUU7b0JBQ1osU0FBUyxHQUFHLFdBQVcsQ0FBQyxDQUFDLEVBQUUsSUFBSSxDQUFDLENBQUM7aUJBQ3BDOztnQkFFRCxPQUFPO29CQUNILENBQUMsRUFBRSxTQUFTO29CQUNaLENBQUMsRUFBRSxTQUFTO2lCQUNmLENBQUM7YUFDTDs7WUFFRCxTQUFTLFdBQVcsQ0FBQyxLQUFLLEVBQUUsUUFBUSxFQUFFO2dCQUNsQyxJQUFJLGFBQWEsR0FBRyxLQUFLLENBQUMsS0FBSyxDQUFDOztnQkFFaEMsSUFBSSxDQUFDLGFBQWEsRUFBRTtvQkFDaEIsYUFBYSxHQUFHLEtBQUssQ0FBQyxLQUFLLEdBQUcsS0FBSyxDQUFDLE1BQU0sQ0FBQyxRQUFRLENBQUMsQ0FBQztpQkFDeEQ7O2dCQUVELElBQUksQ0FBQyxDQUFDLE9BQU8sQ0FBQyxhQUFhLENBQUMsSUFBSSxPQUFPLENBQUMsYUFBYSxDQUFDLElBQUksUUFBUSxDQUFDLGFBQWEsQ0FBQyxDQUFDLEVBQUU7b0JBQ2hGLE1BQU0sSUFBSSxLQUFLLENBQUMsbUNBQW1DLENBQUMsQ0FBQztpQkFDeEQ7O2dCQUVELE9BQU8sYUFBYSxDQUFDO2FBQ3hCO1NBQ0osRUFBRSxFQUFFLFlBQVksRUFBRSxFQUFFLEVBQUUsWUFBWSxFQUFFLEVBQUUsRUFBRSxZQUFZLEVBQUUsRUFBRSxFQUFFLGFBQWEsRUFBRSxFQUFFLEVBQUUsQ0FBQyxFQUFFLEVBQUUsRUFBRSxDQUFDLFVBQVUsT0FBTyxFQUFFLE1BQU0sRUFBRSxPQUFPLEVBQUU7WUFDdEgsTUFBTSxDQUFDLE9BQU8sR0FBRyxPQUFPLENBQUM7O1lBRXpCLFNBQVMsT0FBTyxDQUFDLENBQUMsRUFBRTtnQkFDaEIsT0FBTyxDQUFDLElBQUksQ0FBQyxDQUFDLElBQUksS0FBSyxPQUFPLENBQUM7YUFDbEM7U0FDSixFQUFFLEVBQUUsQ0FBQyxFQUFFLEVBQUUsRUFBRSxDQUFDLFVBQVUsT0FBTyxFQUFFLE1BQU0sRUFBRSxPQUFPLEVBQUU7WUFDN0MsTUFBTSxDQUFDLE9BQU8sR0FBRyxNQUFNLENBQUM7O1lBRXhCLFNBQVMsTUFBTSxDQUFDLElBQUksRUFBRTtnQkFDbEIsT0FBTyxJQUFJLElBQUksQ0FBQyxPQUFPLElBQUksQ0FBQyxJQUFJLEtBQUssVUFBVSxJQUFJLENBQUMsSUFBSSxDQUFDLGNBQWMsQ0FBQyxNQUFNLENBQUMsSUFBSSxPQUFPLElBQUksQ0FBQyxNQUFNLEtBQUssVUFBVSxJQUFJLENBQUMsSUFBSSxDQUFDLGNBQWMsQ0FBQyxRQUFRLENBQUMsQ0FBQyxDQUFDO2FBQzNKO1NBQ0osRUFBRSxFQUFFLENBQUMsRUFBRSxFQUFFLEVBQUUsQ0FBQyxVQUFVLE9BQU8sRUFBRSxNQUFNLEVBQUUsT0FBTyxFQUFFO1lBQzdDLElBQUksT0FBTyxHQUFHLE9BQU8sQ0FBQyxXQUFXLENBQUMsQ0FBQzs7WUFFbkMsTUFBTSxDQUFDLE9BQU8sR0FBRyxhQUFhLENBQUM7O1lBRS9CLFNBQVMsYUFBYSxDQUFDLENBQUMsRUFBRTtnQkFDdEIsT0FBTyxDQUFDLElBQUksQ0FBQyxDQUFDLElBQUksS0FBSyxhQUFhLElBQUksQ0FBQyxDQUFDLE9BQU8sS0FBSyxPQUFPLENBQUM7YUFDakU7U0FDSixFQUFFLEVBQUUsV0FBVyxFQUFFLEVBQUUsRUFBRSxDQUFDLEVBQUUsRUFBRSxFQUFFLENBQUMsVUFBVSxPQUFPLEVBQUUsTUFBTSxFQUFFLE9BQU8sRUFBRTtZQUM5RCxJQUFJLE9BQU8sR0FBRyxPQUFPLENBQUMsV0FBVyxDQUFDLENBQUM7O1lBRW5DLE1BQU0sQ0FBQyxPQUFPLEdBQUcsYUFBYSxDQUFDOztZQUUvQixTQUFTLGFBQWEsQ0FBQyxDQUFDLEVBQUU7Z0JBQ3RCLE9BQU8sQ0FBQyxJQUFJLENBQUMsQ0FBQyxJQUFJLEtBQUssYUFBYSxJQUFJLENBQUMsQ0FBQyxPQUFPLEtBQUssT0FBTyxDQUFDO2FBQ2pFO1NBQ0osRUFBRSxFQUFFLFdBQVcsRUFBRSxFQUFFLEVBQUUsQ0FBQyxFQUFFLEVBQUUsRUFBRSxDQUFDLFVBQVUsT0FBTyxFQUFFLE1BQU0sRUFBRSxPQUFPLEVBQUU7WUFDOUQsTUFBTSxDQUFDLE9BQU8sR0FBRyxRQUFRLENBQUM7O1lBRTFCLFNBQVMsUUFBUSxDQUFDLENBQUMsRUFBRTtnQkFDakIsT0FBTyxDQUFDLElBQUksQ0FBQyxDQUFDLElBQUksS0FBSyxRQUFRLENBQUM7YUFDbkM7U0FDSixFQUFFLEVBQUUsQ0FBQyxFQUFFLEVBQUUsRUFBRSxDQUFDLFVBQVUsT0FBTyxFQUFFLE1BQU0sRUFBRSxPQUFPLEVBQUU7WUFDN0MsTUFBTSxDQUFDLE9BQU8sR0FBRyxHQUFHLENBQUM7U0FDeEIsRUFBRSxFQUFFLENBQUMsRUFBRSxFQUFFLEVBQUUsQ0FBQyxVQUFVLE9BQU8sRUFBRSxNQUFNLEVBQUUsT0FBTyxFQUFFO1lBQzdDLElBQUksT0FBTyxHQUFHLE9BQU8sQ0FBQyxXQUFXLENBQUMsQ0FBQztZQUNuQyxJQUFJLE9BQU8sR0FBRyxPQUFPLENBQUMsWUFBWSxDQUFDLENBQUM7WUFDcEMsSUFBSSxRQUFRLEdBQUcsT0FBTyxDQUFDLGFBQWEsQ0FBQyxDQUFDO1lBQ3RDLElBQUksT0FBTyxHQUFHLE9BQU8sQ0FBQyxZQUFZLENBQUMsQ0FBQztZQUNwQyxJQUFJLE9BQU8sR0FBRyxPQUFPLENBQUMsWUFBWSxDQUFDLENBQUM7O1lBRXBDLE1BQU0sQ0FBQyxPQUFPLEdBQUcsV0FBVyxDQUFDOztZQUU3QixJQUFJLFlBQVksR0FBRyxFQUFFLENBQUM7WUFDdEIsSUFBSSxVQUFVLEdBQUcsRUFBRSxDQUFDOztZQUVwQixTQUFTLFdBQVcsQ0FBQyxPQUFPLEVBQUUsVUFBVSxFQUFFLFFBQVEsRUFBRSxHQUFHLEVBQUUsU0FBUyxFQUFFO2dCQUNoRSxJQUFJLENBQUMsT0FBTyxHQUFHLE9BQU8sQ0FBQztnQkFDdkIsSUFBSSxDQUFDLFVBQVUsR0FBRyxVQUFVLElBQUksWUFBWSxDQUFDO2dCQUM3QyxJQUFJLENBQUMsUUFBUSxHQUFHLFFBQVEsSUFBSSxVQUFVLENBQUM7Z0JBQ3ZDLElBQUksQ0FBQyxHQUFHLEdBQUcsR0FBRyxJQUFJLElBQUksR0FBRyxNQUFNLENBQUMsR0FBRyxDQUFDLEdBQUcsU0FBUyxDQUFDO2dCQUNqRCxJQUFJLENBQUMsU0FBUyxHQUFHLE9BQU8sU0FBUyxLQUFLLFFBQVEsR0FBRyxTQUFTLEdBQUcsSUFBSSxDQUFDOztnQkFFbEUsSUFBSSxLQUFLLEdBQUcsUUFBUSxJQUFJLFFBQVEsQ0FBQyxNQUFNLElBQUksQ0FBQyxDQUFDO2dCQUM3QyxJQUFJLFdBQVcsR0FBRyxDQUFDLENBQUM7Z0JBQ3BCLElBQUksVUFBVSxHQUFHLEtBQUssQ0FBQztnQkFDdkIsSUFBSSxTQUFTLEdBQUcsS0FBSyxDQUFDO2dCQUN0QixJQUFJLGVBQWUsR0FBRyxLQUFLLENBQUM7Z0JBQzVCLElBQUksS0FBSyxDQUFDOztnQkFFVixLQUFLLElBQUksUUFBUSxJQUFJLFVBQVUsRUFBRTtvQkFDN0IsSUFBSSxVQUFVLENBQUMsY0FBYyxDQUFDLFFBQVEsQ0FBQyxFQUFFO3dCQUNyQyxJQUFJLFFBQVEsR0FBRyxVQUFVLENBQUMsUUFBUSxDQUFDLENBQUM7d0JBQ3BDLElBQUksT0FBTyxDQUFDLFFBQVEsQ0FBQyxJQUFJLFFBQVEsQ0FBQyxNQUFNLEVBQUU7NEJBQ3RDLElBQUksQ0FBQyxLQUFLLEVBQUU7Z0NBQ1IsS0FBSyxHQUFHLEVBQUUsQ0FBQzs2QkFDZDs7NEJBRUQsS0FBSyxDQUFDLFFBQVEsQ0FBQyxHQUFHLFFBQVEsQ0FBQzt5QkFDOUI7cUJBQ0o7aUJBQ0o7O2dCQUVELEtBQUssSUFBSSxDQUFDLEdBQUcsQ0FBQyxFQUFFLENBQUMsR0FBRyxLQUFLLEVBQUUsQ0FBQyxFQUFFLEVBQUU7b0JBQzVCLElBQUksS0FBSyxHQUFHLFFBQVEsQ0FBQyxDQUFDLENBQUMsQ0FBQztvQkFDeEIsSUFBSSxPQUFPLENBQUMsS0FBSyxDQUFDLEVBQUU7d0JBQ2hCLFdBQVcsSUFBSSxLQUFLLENBQUMsS0FBSyxJQUFJLENBQUMsQ0FBQzs7d0JBRWhDLElBQUksQ0FBQyxVQUFVLElBQUksS0FBSyxDQUFDLFVBQVUsRUFBRTs0QkFDakMsVUFBVSxHQUFHLElBQUksQ0FBQzt5QkFDckI7O3dCQUVELElBQUksQ0FBQyxTQUFTLElBQUksS0FBSyxDQUFDLFNBQVMsRUFBRTs0QkFDL0IsU0FBUyxHQUFHLElBQUksQ0FBQzt5QkFDcEI7O3dCQUVELElBQUksQ0FBQyxlQUFlLElBQUksQ0FBQyxLQUFLLENBQUMsS0FBSyxJQUFJLEtBQUssQ0FBQyxlQUFlLENBQUMsRUFBRTs0QkFDNUQsZUFBZSxHQUFHLElBQUksQ0FBQzt5QkFDMUI7cUJBQ0osTUFBTSxJQUFJLENBQUMsVUFBVSxJQUFJLFFBQVEsQ0FBQyxLQUFLLENBQUMsRUFBRTt3QkFDdkMsSUFBSSxPQUFPLEtBQUssQ0FBQyxPQUFPLEtBQUssVUFBVSxFQUFFOzRCQUNyQyxVQUFVLEdBQUcsSUFBSSxDQUFDO3lCQUNyQjtxQkFDSixNQUFNLElBQUksQ0FBQyxTQUFTLElBQUksT0FBTyxDQUFDLEtBQUssQ0FBQyxFQUFFO3dCQUNyQyxTQUFTLEdBQUcsSUFBSSxDQUFDO3FCQUNwQjtpQkFDSjs7Z0JBRUQsSUFBSSxDQUFDLEtBQUssR0FBRyxLQUFLLEdBQUcsV0FBVyxDQUFDO2dCQUNqQyxJQUFJLENBQUMsVUFBVSxHQUFHLFVBQVUsQ0FBQztnQkFDN0IsSUFBSSxDQUFDLFNBQVMsR0FBRyxTQUFTLENBQUM7Z0JBQzNCLElBQUksQ0FBQyxLQUFLLEdBQUcsS0FBSyxDQUFDO2dCQUNuQixJQUFJLENBQUMsZUFBZSxHQUFHLGVBQWUsQ0FBQzthQUMxQzs7WUFFRCxXQUFXLENBQUMsU0FBUyxDQUFDLE9BQU8sR0FBRyxPQUFPLENBQUM7WUFDeEMsV0FBVyxDQUFDLFNBQVMsQ0FBQyxJQUFJLEdBQUcsYUFBYSxDQUFDO1NBQzlDLEVBQUUsRUFBRSxZQUFZLEVBQUUsRUFBRSxFQUFFLFlBQVksRUFBRSxFQUFFLEVBQUUsWUFBWSxFQUFFLEVBQUUsRUFBRSxhQUFhLEVBQUUsRUFBRSxFQUFFLFdBQVcsRUFBRSxFQUFFLEVBQUUsQ0FBQyxFQUFFLEVBQUUsRUFBRSxDQUFDLFVBQVUsT0FBTyxFQUFFLE1BQU0sRUFBRSxPQUFPLEVBQUU7WUFDdkksSUFBSSxPQUFPLEdBQUcsT0FBTyxDQUFDLFdBQVcsQ0FBQyxDQUFDOztZQUVuQyxZQUFZLENBQUMsSUFBSSxHQUFHLENBQUMsQ0FBQztZQUN0QixZQUFZLENBQUMsS0FBSyxHQUFHLENBQUMsQ0FBQztZQUN2QixZQUFZLENBQUMsS0FBSyxHQUFHLENBQUMsQ0FBQztZQUN2QixZQUFZLENBQUMsTUFBTSxHQUFHLENBQUMsQ0FBQztZQUN4QixZQUFZLENBQUMsS0FBSyxHQUFHLENBQUMsQ0FBQztZQUN2QixZQUFZLENBQUMsS0FBSyxHQUFHLENBQUMsQ0FBQztZQUN2QixZQUFZLENBQUMsTUFBTSxHQUFHLENBQUMsQ0FBQztZQUN4QixZQUFZLENBQUMsTUFBTSxHQUFHLENBQUMsQ0FBQztZQUN4QixZQUFZLENBQUMsS0FBSyxHQUFHLENBQUMsQ0FBQzs7WUFFdkIsTUFBTSxDQUFDLE9BQU8sR0FBRyxZQUFZLENBQUM7O1lBRTlCLFNBQVMsWUFBWSxDQUFDLElBQUksRUFBRSxLQUFLLEVBQUUsS0FBSyxFQUFFO2dCQUN0QyxJQUFJLENBQUMsSUFBSSxHQUFHLE1BQU0sQ0FBQyxJQUFJLENBQUMsQ0FBQztnQkFDekIsSUFBSSxDQUFDLEtBQUssR0FBRyxLQUFLLENBQUM7Z0JBQ25CLElBQUksQ0FBQyxLQUFLLEdBQUcsS0FBSyxDQUFDO2FBQ3RCOztZQUVELFlBQVksQ0FBQyxTQUFTLENBQUMsT0FBTyxHQUFHLE9BQU8sQ0FBQztZQUN6QyxZQUFZLENBQUMsU0FBUyxDQUFDLElBQUksR0FBRyxjQUFjLENBQUM7U0FDaEQsRUFBRSxFQUFFLFdBQVcsRUFBRSxFQUFFLEVBQUUsQ0FBQyxFQUFFLEVBQUUsRUFBRSxDQUFDLFVBQVUsT0FBTyxFQUFFLE1BQU0sRUFBRSxPQUFPLEVBQUU7WUFDOUQsSUFBSSxPQUFPLEdBQUcsT0FBTyxDQUFDLFdBQVcsQ0FBQyxDQUFDOztZQUVuQyxNQUFNLENBQUMsT0FBTyxHQUFHLFdBQVcsQ0FBQzs7WUFFN0IsU0FBUyxXQUFXLENBQUMsSUFBSSxFQUFFO2dCQUN2QixJQUFJLENBQUMsSUFBSSxHQUFHLE1BQU0sQ0FBQyxJQUFJLENBQUMsQ0FBQzthQUM1Qjs7WUFFRCxXQUFXLENBQUMsU0FBUyxDQUFDLE9BQU8sR0FBRyxPQUFPLENBQUM7WUFDeEMsV0FBVyxDQUFDLFNBQVMsQ0FBQyxJQUFJLEdBQUcsYUFBYSxDQUFDO1NBQzlDLEVBQUUsRUFBRSxXQUFXLEVBQUUsRUFBRSxFQUFFLENBQUMsRUFBRSxFQUFFLEVBQUUsQ0FBQyxVQUFVLE9BQU8sRUFBRSxNQUFNLEVBQUUsT0FBTyxFQUFFO1lBQzlELElBQUksUUFBUSxHQUFHLE9BQU8sQ0FBQyxXQUFXLENBQUMsQ0FBQztZQUNwQyxJQUFJLE1BQU0sR0FBRyxPQUFPLENBQUMsbUJBQW1CLENBQUMsQ0FBQzs7WUFFMUMsTUFBTSxDQUFDLE9BQU8sR0FBRyxTQUFTLENBQUM7O1lBRTNCLFNBQVMsU0FBUyxDQUFDLENBQUMsRUFBRSxDQUFDLEVBQUU7Z0JBQ3JCLElBQUksSUFBSSxDQUFDOztnQkFFVCxLQUFLLElBQUksSUFBSSxJQUFJLENBQUMsRUFBRTtvQkFDaEIsSUFBSSxDQUFDLENBQUMsSUFBSSxJQUFJLENBQUMsQ0FBQyxFQUFFO3dCQUNkLElBQUksR0FBRyxJQUFJLElBQUksRUFBRSxDQUFDO3dCQUNsQixJQUFJLENBQUMsSUFBSSxDQUFDLEdBQUcsU0FBUyxDQUFDO3FCQUMxQjs7b0JBRUQsSUFBSSxNQUFNLEdBQUcsQ0FBQyxDQUFDLElBQUksQ0FBQyxDQUFDO29CQUNyQixJQUFJLE1BQU0sR0FBRyxDQUFDLENBQUMsSUFBSSxDQUFDLENBQUM7O29CQUVyQixJQUFJLE1BQU0sS0FBSyxNQUFNLEVBQUU7d0JBQ25CLFNBQVM7cUJBQ1osTUFBTSxJQUFJLFFBQVEsQ0FBQyxNQUFNLENBQUMsSUFBSSxRQUFRLENBQUMsTUFBTSxDQUFDLEVBQUU7d0JBQzdDLElBQUksWUFBWSxDQUFDLE1BQU0sQ0FBQyxLQUFLLFlBQVksQ0FBQyxNQUFNLENBQUMsRUFBRTs0QkFDL0MsSUFBSSxHQUFHLElBQUksSUFBSSxFQUFFLENBQUM7NEJBQ2xCLElBQUksQ0FBQyxJQUFJLENBQUMsR0FBRyxNQUFNLENBQUM7eUJBQ3ZCLE1BQU0sSUFBSSxNQUFNLENBQUMsTUFBTSxDQUFDLEVBQUU7NEJBQ3ZCLElBQUksR0FBRyxJQUFJLElBQUksRUFBRSxDQUFDOzRCQUNsQixJQUFJLENBQUMsSUFBSSxDQUFDLEdBQUcsTUFBTSxDQUFDO3lCQUN2QixNQUFNOzRCQUNILElBQUksVUFBVSxHQUFHLFNBQVMsQ0FBQyxNQUFNLEVBQUUsTUFBTSxDQUFDLENBQUM7NEJBQzNDLElBQUksVUFBVSxFQUFFO2dDQUNaLElBQUksR0FBRyxJQUFJLElBQUksRUFBRSxDQUFDO2dDQUNsQixJQUFJLENBQUMsSUFBSSxDQUFDLEdBQUcsVUFBVSxDQUFDOzZCQUMzQjt5QkFDSjtxQkFDSixNQUFNO3dCQUNILElBQUksR0FBRyxJQUFJLElBQUksRUFBRSxDQUFDO3dCQUNsQixJQUFJLENBQUMsSUFBSSxDQUFDLEdBQUcsTUFBTSxDQUFDO3FCQUN2QjtpQkFDSjs7Z0JBRUQsS0FBSyxJQUFJLElBQUksSUFBSSxDQUFDLEVBQUU7b0JBQ2hCLElBQUksQ0FBQyxDQUFDLElBQUksSUFBSSxDQUFDLENBQUMsRUFBRTt3QkFDZCxJQUFJLEdBQUcsSUFBSSxJQUFJLEVBQUUsQ0FBQzt3QkFDbEIsSUFBSSxDQUFDLElBQUksQ0FBQyxHQUFHLENBQUMsQ0FBQyxJQUFJLENBQUMsQ0FBQztxQkFDeEI7aUJBQ0o7O2dCQUVELE9BQU8sSUFBSSxDQUFDO2FBQ2Y7O1lBRUQsU0FBUyxZQUFZLENBQUMsS0FBSyxFQUFFO2dCQUN6QixJQUFJLE1BQU0sQ0FBQyxjQUFjLEVBQUU7b0JBQ3ZCLE9BQU8sTUFBTSxDQUFDLGNBQWMsQ0FBQyxLQUFLLENBQUMsQ0FBQztpQkFDdkMsTUFBTSxJQUFJLEtBQUssQ0FBQyxTQUFTLEVBQUU7b0JBQ3hCLE9BQU8sS0FBSyxDQUFDLFNBQVMsQ0FBQztpQkFDMUIsTUFBTSxJQUFJLEtBQUssQ0FBQyxXQUFXLEVBQUU7b0JBQzFCLE9BQU8sS0FBSyxDQUFDLFdBQVcsQ0FBQyxTQUFTLENBQUM7aUJBQ3RDO2FBQ0o7U0FDSixFQUFFLEVBQUUsbUJBQW1CLEVBQUUsRUFBRSxFQUFFLFdBQVcsRUFBRSxFQUFFLEVBQUUsQ0FBQyxFQUFFLEVBQUUsRUFBRSxDQUFDLFVBQVUsT0FBTyxFQUFFLE1BQU0sRUFBRSxPQUFPLEVBQUU7WUFDdkYsSUFBSSxPQUFPLEdBQUcsT0FBTyxDQUFDLFlBQVksQ0FBQyxDQUFDOztZQUVwQyxJQUFJLE1BQU0sR0FBRyxPQUFPLENBQUMsaUJBQWlCLENBQUMsQ0FBQztZQUN4QyxJQUFJLE9BQU8sR0FBRyxPQUFPLENBQUMsbUJBQW1CLENBQUMsQ0FBQztZQUMzQyxJQUFJLE9BQU8sR0FBRyxPQUFPLENBQUMsbUJBQW1CLENBQUMsQ0FBQztZQUMzQyxJQUFJLFFBQVEsR0FBRyxPQUFPLENBQUMsb0JBQW9CLENBQUMsQ0FBQztZQUM3QyxJQUFJLE9BQU8sR0FBRyxPQUFPLENBQUMsbUJBQW1CLENBQUMsQ0FBQztZQUMzQyxJQUFJLFdBQVcsR0FBRyxPQUFPLENBQUMsdUJBQXVCLENBQUMsQ0FBQzs7WUFFbkQsSUFBSSxTQUFTLEdBQUcsT0FBTyxDQUFDLGNBQWMsQ0FBQyxDQUFDOztZQUV4QyxNQUFNLENBQUMsT0FBTyxHQUFHLElBQUksQ0FBQzs7WUFFdEIsU0FBUyxJQUFJLENBQUMsQ0FBQyxFQUFFLENBQUMsRUFBRTtnQkFDaEIsSUFBSSxLQUFLLEdBQUcsRUFBRSxDQUFDLEVBQUUsQ0FBQyxFQUFFLENBQUM7Z0JBQ3JCLElBQUksQ0FBQyxDQUFDLEVBQUUsQ0FBQyxFQUFFLEtBQUssRUFBRSxDQUFDLENBQUMsQ0FBQztnQkFDckIsT0FBTyxLQUFLLENBQUM7YUFDaEI7O1lBRUQsU0FBUyxJQUFJLENBQUMsQ0FBQyxFQUFFLENBQUMsRUFBRSxLQUFLLEVBQUUsS0FBSyxFQUFFO2dCQUM5QixJQUFJLENBQUMsS0FBSyxDQUFDLEVBQUU7b0JBQ1QsT0FBTztpQkFDVjs7Z0JBRUQsSUFBSSxLQUFLLEdBQUcsS0FBSyxDQUFDLEtBQUssQ0FBQyxDQUFDO2dCQUN6QixJQUFJLFVBQVUsR0FBRyxLQUFLLENBQUM7O2dCQUV2QixJQUFJLE9BQU8sQ0FBQyxDQUFDLENBQUMsSUFBSSxPQUFPLENBQUMsQ0FBQyxDQUFDLEVBQUU7b0JBQzFCLE1BQU0sQ0FBQyxDQUFDLEVBQUUsQ0FBQyxFQUFFLEtBQUssRUFBRSxLQUFLLENBQUMsQ0FBQztpQkFDOUIsTUFBTSxJQUFJLENBQUMsSUFBSSxJQUFJLEVBQUU7Ozs7O29CQUtsQixJQUFJLENBQUMsUUFBUSxDQUFDLENBQUMsQ0FBQyxFQUFFO3dCQUNkLFVBQVUsQ0FBQyxDQUFDLEVBQUUsS0FBSyxFQUFFLEtBQUssQ0FBQyxDQUFDO3dCQUM1QixLQUFLLEdBQUcsS0FBSyxDQUFDLEtBQUssQ0FBQyxDQUFDO3FCQUN4Qjs7b0JBRUQsS0FBSyxHQUFHLFdBQVcsQ0FBQyxLQUFLLEVBQUUsSUFBSSxNQUFNLENBQUMsTUFBTSxDQUFDLE1BQU0sRUFBRSxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUMsQ0FBQztpQkFDL0QsTUFBTSxJQUFJLE9BQU8sQ0FBQyxDQUFDLENBQUMsRUFBRTtvQkFDbkIsSUFBSSxPQUFPLENBQUMsQ0FBQyxDQUFDLEVBQUU7d0JBQ1osSUFBSSxDQUFDLENBQUMsT0FBTyxLQUFLLENBQUMsQ0FBQyxPQUFPLElBQUksQ0FBQyxDQUFDLFNBQVMsS0FBSyxDQUFDLENBQUMsU0FBUyxJQUFJLENBQUMsQ0FBQyxHQUFHLEtBQUssQ0FBQyxDQUFDLEdBQUcsRUFBRTs0QkFDM0UsSUFBSSxVQUFVLEdBQUcsU0FBUyxDQUFDLENBQUMsQ0FBQyxVQUFVLEVBQUUsQ0FBQyxDQUFDLFVBQVUsQ0FBQyxDQUFDOzRCQUN2RCxJQUFJLFVBQVUsRUFBRTtnQ0FDWixLQUFLLEdBQUcsV0FBVyxDQUFDLEtBQUssRUFBRSxJQUFJLE1BQU0sQ0FBQyxNQUFNLENBQUMsS0FBSyxFQUFFLENBQUMsRUFBRSxVQUFVLENBQUMsQ0FBQyxDQUFDOzZCQUN2RTs0QkFDRCxLQUFLLEdBQUcsWUFBWSxDQUFDLENBQUMsRUFBRSxDQUFDLEVBQUUsS0FBSyxFQUFFLEtBQUssRUFBRSxLQUFLLENBQUMsQ0FBQzt5QkFDbkQsTUFBTTs0QkFDSCxLQUFLLEdBQUcsV0FBVyxDQUFDLEtBQUssRUFBRSxJQUFJLE1BQU0sQ0FBQyxNQUFNLENBQUMsS0FBSyxFQUFFLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQyxDQUFDOzRCQUMzRCxVQUFVLEdBQUcsSUFBSSxDQUFDO3lCQUNyQjtxQkFDSixNQUFNO3dCQUNILEtBQUssR0FBRyxXQUFXLENBQUMsS0FBSyxFQUFFLElBQUksTUFBTSxDQUFDLE1BQU0sQ0FBQyxLQUFLLEVBQUUsQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDLENBQUM7d0JBQzNELFVBQVUsR0FBRyxJQUFJLENBQUM7cUJBQ3JCO2lCQUNKLE1BQU0sSUFBSSxPQUFPLENBQUMsQ0FBQyxDQUFDLEVBQUU7b0JBQ25CLElBQUksQ0FBQyxPQUFPLENBQUMsQ0FBQyxDQUFDLEVBQUU7d0JBQ2IsS0FBSyxHQUFHLFdBQVcsQ0FBQyxLQUFLLEVBQUUsSUFBSSxNQUFNLENBQUMsTUFBTSxDQUFDLEtBQUssRUFBRSxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUMsQ0FBQzt3QkFDM0QsVUFBVSxHQUFHLElBQUksQ0FBQztxQkFDckIsTUFBTSxJQUFJLENBQUMsQ0FBQyxJQUFJLEtBQUssQ0FBQyxDQUFDLElBQUksRUFBRTt3QkFDMUIsS0FBSyxHQUFHLFdBQVcsQ0FBQyxLQUFLLEVBQUUsSUFBSSxNQUFNLENBQUMsTUFBTSxDQUFDLEtBQUssRUFBRSxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUMsQ0FBQztxQkFDOUQ7aUJBQ0osTUFBTSxJQUFJLFFBQVEsQ0FBQyxDQUFDLENBQUMsRUFBRTtvQkFDcEIsSUFBSSxDQUFDLFFBQVEsQ0FBQyxDQUFDLENBQUMsRUFBRTt3QkFDZCxVQUFVLEdBQUcsSUFBSSxDQUFDO3FCQUNyQjs7b0JBRUQsS0FBSyxHQUFHLFdBQVcsQ0FBQyxLQUFLLEVBQUUsSUFBSSxNQUFNLENBQUMsTUFBTSxDQUFDLE1BQU0sRUFBRSxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUMsQ0FBQztpQkFDL0Q7O2dCQUVELElBQUksS0FBSyxFQUFFO29CQUNQLEtBQUssQ0FBQyxLQUFLLENBQUMsR0FBRyxLQUFLLENBQUM7aUJBQ3hCOztnQkFFRCxJQUFJLFVBQVUsRUFBRTtvQkFDWixVQUFVLENBQUMsQ0FBQyxFQUFFLEtBQUssRUFBRSxLQUFLLENBQUMsQ0FBQztpQkFDL0I7YUFDSjs7WUFFRCxTQUFTLFlBQVksQ0FBQyxDQUFDLEVBQUUsQ0FBQyxFQUFFLEtBQUssRUFBRSxLQUFLLEVBQUUsS0FBSyxFQUFFO2dCQUM3QyxJQUFJLFNBQVMsR0FBRyxDQUFDLENBQUMsUUFBUSxDQUFDO2dCQUMzQixJQUFJLFVBQVUsR0FBRyxPQUFPLENBQUMsU0FBUyxFQUFFLENBQUMsQ0FBQyxRQUFRLENBQUMsQ0FBQztnQkFDaEQsSUFBSSxTQUFTLEdBQUcsVUFBVSxDQUFDLFFBQVEsQ0FBQzs7Z0JBRXBDLElBQUksSUFBSSxHQUFHLFNBQVMsQ0FBQyxNQUFNLENBQUM7Z0JBQzVCLElBQUksSUFBSSxHQUFHLFNBQVMsQ0FBQyxNQUFNLENBQUM7Z0JBQzVCLElBQUksR0FBRyxHQUFHLElBQUksR0FBRyxJQUFJLEdBQUcsSUFBSSxHQUFHLElBQUksQ0FBQzs7Z0JBRXBDLEtBQUssSUFBSSxDQUFDLEdBQUcsQ0FBQyxFQUFFLENBQUMsR0FBRyxHQUFHLEVBQUUsQ0FBQyxFQUFFLEVBQUU7b0JBQzFCLElBQUksUUFBUSxHQUFHLFNBQVMsQ0FBQyxDQUFDLENBQUMsQ0FBQztvQkFDNUIsSUFBSSxTQUFTLEdBQUcsU0FBUyxDQUFDLENBQUMsQ0FBQyxDQUFDO29CQUM3QixLQUFLLElBQUksQ0FBQyxDQUFDOztvQkFFWCxJQUFJLENBQUMsUUFBUSxFQUFFO3dCQUNYLElBQUksU0FBUyxFQUFFOzs0QkFFWCxLQUFLLEdBQUcsV0FBVyxDQUFDLEtBQUssRUFBRSxJQUFJLE1BQU0sQ0FBQyxNQUFNLENBQUMsTUFBTSxFQUFFLElBQUksRUFBRSxTQUFTLENBQUMsQ0FBQyxDQUFDO3lCQUMxRTtxQkFDSixNQUFNO3dCQUNILElBQUksQ0FBQyxRQUFRLEVBQUUsU0FBUyxFQUFFLEtBQUssRUFBRSxLQUFLLENBQUMsQ0FBQztxQkFDM0M7O29CQUVELElBQUksT0FBTyxDQUFDLFFBQVEsQ0FBQyxJQUFJLFFBQVEsQ0FBQyxLQUFLLEVBQUU7d0JBQ3JDLEtBQUssSUFBSSxRQUFRLENBQUMsS0FBSyxDQUFDO3FCQUMzQjtpQkFDSjs7Z0JBRUQsSUFBSSxVQUFVLENBQUMsS0FBSyxFQUFFOztvQkFFbEIsS0FBSyxHQUFHLFdBQVcsQ0FBQyxLQUFLLEVBQUUsSUFBSSxNQUFNLENBQUMsTUFBTSxDQUFDLEtBQUssRUFBRSxDQUFDLEVBQUUsVUFBVSxDQUFDLEtBQUssQ0FBQyxDQUFDLENBQUM7aUJBQzdFOztnQkFFRCxPQUFPLEtBQUssQ0FBQzthQUNoQjs7WUFFRCxTQUFTLFVBQVUsQ0FBQyxLQUFLLEVBQUUsS0FBSyxFQUFFLEtBQUssRUFBRTs7Z0JBRXJDLE1BQU0sQ0FBQyxLQUFLLEVBQUUsS0FBSyxFQUFFLEtBQUssQ0FBQyxDQUFDO2dCQUM1QixjQUFjLENBQUMsS0FBSyxFQUFFLEtBQUssRUFBRSxLQUFLLENBQUMsQ0FBQzthQUN2Qzs7OztZQUlELFNBQVMsY0FBYyxDQUFDLEtBQUssRUFBRSxLQUFLLEVBQUUsS0FBSyxFQUFFO2dCQUN6QyxJQUFJLFFBQVEsQ0FBQyxLQUFLLENBQUMsRUFBRTtvQkFDakIsSUFBSSxPQUFPLEtBQUssQ0FBQyxPQUFPLEtBQUssVUFBVSxFQUFFO3dCQUNyQyxLQUFLLENBQUMsS0FBSyxDQUFDLEdBQUcsV0FBVyxDQUFDLEtBQUssQ0FBQyxLQUFLLENBQUMsRUFBRSxJQUFJLE1BQU0sQ0FBQyxNQUFNLENBQUMsTUFBTSxFQUFFLEtBQUssRUFBRSxJQUFJLENBQUMsQ0FBQyxDQUFDO3FCQUNwRjtpQkFDSixNQUFNLElBQUksT0FBTyxDQUFDLEtBQUssQ0FBQyxJQUFJLENBQUMsS0FBSyxDQUFDLFVBQVUsSUFBSSxLQUFLLENBQUMsU0FBUyxDQUFDLEVBQUU7b0JBQ2hFLElBQUksUUFBUSxHQUFHLEtBQUssQ0FBQyxRQUFRLENBQUM7b0JBQzlCLElBQUksR0FBRyxHQUFHLFFBQVEsQ0FBQyxNQUFNLENBQUM7b0JBQzFCLEtBQUssSUFBSSxDQUFDLEdBQUcsQ0FBQyxFQUFFLENBQUMsR0FBRyxHQUFHLEVBQUUsQ0FBQyxFQUFFLEVBQUU7d0JBQzFCLElBQUksS0FBSyxHQUFHLFFBQVEsQ0FBQyxDQUFDLENBQUMsQ0FBQzt3QkFDeEIsS0FBSyxJQUFJLENBQUMsQ0FBQzs7d0JBRVgsY0FBYyxDQUFDLEtBQUssRUFBRSxLQUFLLEVBQUUsS0FBSyxDQUFDLENBQUM7O3dCQUVwQyxJQUFJLE9BQU8sQ0FBQyxLQUFLLENBQUMsSUFBSSxLQUFLLENBQUMsS0FBSyxFQUFFOzRCQUMvQixLQUFLLElBQUksS0FBSyxDQUFDLEtBQUssQ0FBQzt5QkFDeEI7cUJBQ0o7aUJBQ0osTUFBTSxJQUFJLE9BQU8sQ0FBQyxLQUFLLENBQUMsRUFBRTtvQkFDdkIsTUFBTSxDQUFDLEtBQUssRUFBRSxJQUFJLEVBQUUsS0FBSyxFQUFFLEtBQUssQ0FBQyxDQUFDO2lCQUNyQzthQUNKOzs7WUFHRCxTQUFTLE1BQU0sQ0FBQyxDQUFDLEVBQUUsQ0FBQyxFQUFFLEtBQUssRUFBRSxLQUFLLEVBQUU7Z0JBQ2hDLElBQUksS0FBSyxHQUFHLFdBQVcsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUM7Z0JBQzlCLElBQUksVUFBVSxHQUFHLElBQUksQ0FBQyxLQUFLLENBQUMsQ0FBQyxFQUFFLEtBQUssQ0FBQyxDQUFDLENBQUMsQ0FBQztnQkFDeEMsSUFBSSxVQUFVLENBQUMsVUFBVSxDQUFDLEVBQUU7b0JBQ3hCLEtBQUssQ0FBQyxLQUFLLENBQUMsR0FBRyxJQUFJLE1BQU0sQ0FBQyxNQUFNLENBQUMsS0FBSyxFQUFFLElBQUksRUFBRSxVQUFVLENBQUMsQ0FBQztpQkFDN0Q7YUFDSjs7WUFFRCxTQUFTLFVBQVUsQ0FBQyxLQUFLLEVBQUU7Z0JBQ3ZCLEtBQUssSUFBSSxLQUFLLElBQUksS0FBSyxFQUFFO29CQUNyQixJQUFJLEtBQUssS0FBSyxHQUFHLEVBQUU7d0JBQ2YsT0FBTyxJQUFJLENBQUM7cUJBQ2Y7aUJBQ0o7O2dCQUVELE9BQU8sS0FBSyxDQUFDO2FBQ2hCOzs7WUFHRCxTQUFTLE1BQU0sQ0FBQyxLQUFLLEVBQUUsS0FBSyxFQUFFLEtBQUssRUFBRTtnQkFDakMsSUFBSSxPQUFPLENBQUMsS0FBSyxDQUFDLEVBQUU7b0JBQ2hCLElBQUksS0FBSyxDQUFDLEtBQUssRUFBRTt3QkFDYixLQUFLLENBQUMsS0FBSyxDQUFDLEdBQUcsV0FBVyxDQUFDLEtBQUssQ0FBQyxLQUFLLENBQUMsRUFBRSxJQUFJLE1BQU0sQ0FBQyxNQUFNLENBQUMsS0FBSyxFQUFFLEtBQUssRUFBRSxhQUFhLENBQUMsS0FBSyxDQUFDLEtBQUssQ0FBQyxDQUFDLENBQUMsQ0FBQztxQkFDekc7O29CQUVELElBQUksS0FBSyxDQUFDLGVBQWUsSUFBSSxLQUFLLENBQUMsU0FBUyxFQUFFO3dCQUMxQyxJQUFJLFFBQVEsR0FBRyxLQUFLLENBQUMsUUFBUSxDQUFDO3dCQUM5QixJQUFJLEdBQUcsR0FBRyxRQUFRLENBQUMsTUFBTSxDQUFDO3dCQUMxQixLQUFLLElBQUksQ0FBQyxHQUFHLENBQUMsRUFBRSxDQUFDLEdBQUcsR0FBRyxFQUFFLENBQUMsRUFBRSxFQUFFOzRCQUMxQixJQUFJLEtBQUssR0FBRyxRQUFRLENBQUMsQ0FBQyxDQUFDLENBQUM7NEJBQ3hCLEtBQUssSUFBSSxDQUFDLENBQUM7OzRCQUVYLE1BQU0sQ0FBQyxLQUFLLEVBQUUsS0FBSyxFQUFFLEtBQUssQ0FBQyxDQUFDOzs0QkFFNUIsSUFBSSxPQUFPLENBQUMsS0FBSyxDQUFDLElBQUksS0FBSyxDQUFDLEtBQUssRUFBRTtnQ0FDL0IsS0FBSyxJQUFJLEtBQUssQ0FBQyxLQUFLLENBQUM7NkJBQ3hCO3lCQUNKO3FCQUNKO2lCQUNKLE1BQU0sSUFBSSxPQUFPLENBQUMsS0FBSyxDQUFDLEVBQUU7b0JBQ3ZCLE1BQU0sQ0FBQyxLQUFLLEVBQUUsSUFBSSxFQUFFLEtBQUssRUFBRSxLQUFLLENBQUMsQ0FBQztpQkFDckM7YUFDSjs7WUFFRCxTQUFTLGFBQWEsQ0FBQyxHQUFHLEVBQUU7Z0JBQ3hCLElBQUksTUFBTSxHQUFHLEVBQUUsQ0FBQzs7Z0JBRWhCLEtBQUssSUFBSSxHQUFHLElBQUksR0FBRyxFQUFFO29CQUNqQixNQUFNLENBQUMsR0FBRyxDQUFDLEdBQUcsU0FBUyxDQUFDO2lCQUMzQjs7Z0JBRUQsT0FBTyxNQUFNLENBQUM7YUFDakI7OztZQUdELFNBQVMsT0FBTyxDQUFDLFNBQVMsRUFBRSxTQUFTLEVBQUU7O2dCQUVuQyxJQUFJLFdBQVcsR0FBRyxRQUFRLENBQUMsU0FBUyxDQUFDLENBQUM7Z0JBQ3RDLElBQUksS0FBSyxHQUFHLFdBQVcsQ0FBQyxJQUFJLENBQUM7Z0JBQzdCLElBQUksS0FBSyxHQUFHLFdBQVcsQ0FBQyxJQUFJLENBQUM7O2dCQUU3QixJQUFJLEtBQUssQ0FBQyxNQUFNLEtBQUssU0FBUyxDQUFDLE1BQU0sRUFBRTtvQkFDbkMsT0FBTzt3QkFDSCxRQUFRLEVBQUUsU0FBUzt3QkFDbkIsS0FBSyxFQUFFLElBQUk7cUJBQ2QsQ0FBQztpQkFDTDs7O2dCQUdELElBQUksV0FBVyxHQUFHLFFBQVEsQ0FBQyxTQUFTLENBQUMsQ0FBQztnQkFDdEMsSUFBSSxLQUFLLEdBQUcsV0FBVyxDQUFDLElBQUksQ0FBQztnQkFDN0IsSUFBSSxLQUFLLEdBQUcsV0FBVyxDQUFDLElBQUksQ0FBQzs7Z0JBRTdCLElBQUksS0FBSyxDQUFDLE1BQU0sS0FBSyxTQUFTLENBQUMsTUFBTSxFQUFFO29CQUNuQyxPQUFPO3dCQUNILFFBQVEsRUFBRSxTQUFTO3dCQUNuQixLQUFLLEVBQUUsSUFBSTtxQkFDZCxDQUFDO2lCQUNMOzs7Z0JBR0QsSUFBSSxXQUFXLEdBQUcsRUFBRSxDQUFDOztnQkFFckIsSUFBSSxTQUFTLEdBQUcsQ0FBQyxDQUFDO2dCQUNsQixJQUFJLFNBQVMsR0FBRyxLQUFLLENBQUMsTUFBTSxDQUFDO2dCQUM3QixJQUFJLFlBQVksR0FBRyxDQUFDLENBQUM7Ozs7Z0JBSXJCLEtBQUssSUFBSSxDQUFDLEdBQUcsQ0FBQyxFQUFFLENBQUMsR0FBRyxTQUFTLENBQUMsTUFBTSxFQUFFLENBQUMsRUFBRSxFQUFFO29CQUN2QyxJQUFJLEtBQUssR0FBRyxTQUFTLENBQUMsQ0FBQyxDQUFDLENBQUM7b0JBQ3pCLElBQUksU0FBUyxDQUFDOztvQkFFZCxJQUFJLEtBQUssQ0FBQyxHQUFHLEVBQUU7d0JBQ1gsSUFBSSxLQUFLLENBQUMsY0FBYyxDQUFDLEtBQUssQ0FBQyxHQUFHLENBQUMsRUFBRTs7NEJBRWpDLFNBQVMsR0FBRyxLQUFLLENBQUMsS0FBSyxDQUFDLEdBQUcsQ0FBQyxDQUFDOzRCQUM3QixXQUFXLENBQUMsSUFBSSxDQUFDLFNBQVMsQ0FBQyxTQUFTLENBQUMsQ0FBQyxDQUFDO3lCQUMxQyxNQUFNOzs0QkFFSCxTQUFTLEdBQUcsQ0FBQyxHQUFHLFlBQVksRUFBRSxDQUFDOzRCQUMvQixXQUFXLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxDQUFDO3lCQUMxQjtxQkFDSixNQUFNOzt3QkFFSCxJQUFJLFNBQVMsR0FBRyxTQUFTLEVBQUU7NEJBQ3ZCLFNBQVMsR0FBRyxLQUFLLENBQUMsU0FBUyxFQUFFLENBQUMsQ0FBQzs0QkFDL0IsV0FBVyxDQUFDLElBQUksQ0FBQyxTQUFTLENBQUMsU0FBUyxDQUFDLENBQUMsQ0FBQzt5QkFDMUMsTUFBTTs7Ozs0QkFJSCxTQUFTLEdBQUcsQ0FBQyxHQUFHLFlBQVksRUFBRSxDQUFDOzRCQUMvQixXQUFXLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxDQUFDO3lCQUMxQjtxQkFDSjtpQkFDSjs7Z0JBRUQsSUFBSSxhQUFhLEdBQUcsU0FBUyxJQUFJLEtBQUssQ0FBQyxNQUFNLEdBQUcsU0FBUyxDQUFDLE1BQU0sR0FBRyxLQUFLLENBQUMsU0FBUyxDQUFDLENBQUM7Ozs7Z0JBSXBGLEtBQUssSUFBSSxDQUFDLEdBQUcsQ0FBQyxFQUFFLENBQUMsR0FBRyxTQUFTLENBQUMsTUFBTSxFQUFFLENBQUMsRUFBRSxFQUFFO29CQUN2QyxJQUFJLE9BQU8sR0FBRyxTQUFTLENBQUMsQ0FBQyxDQUFDLENBQUM7O29CQUUzQixJQUFJLE9BQU8sQ0FBQyxHQUFHLEVBQUU7d0JBQ2IsSUFBSSxDQUFDLEtBQUssQ0FBQyxjQUFjLENBQUMsT0FBTyxDQUFDLEdBQUcsQ0FBQyxFQUFFOzs7OzRCQUlwQyxXQUFXLENBQUMsSUFBSSxDQUFDLE9BQU8sQ0FBQyxDQUFDO3lCQUM3QjtxQkFDSixNQUFNLElBQUksQ0FBQyxJQUFJLGFBQWEsRUFBRTs7d0JBRTNCLFdBQVcsQ0FBQyxJQUFJLENBQUMsT0FBTyxDQUFDLENBQUM7cUJBQzdCO2lCQUNKOztnQkFFRCxJQUFJLFFBQVEsR0FBRyxXQUFXLENBQUMsS0FBSyxFQUFFLENBQUM7Z0JBQ25DLElBQUksYUFBYSxHQUFHLENBQUMsQ0FBQztnQkFDdEIsSUFBSSxPQUFPLEdBQUcsRUFBRSxDQUFDO2dCQUNqQixJQUFJLE9BQU8sR0FBRyxFQUFFLENBQUM7Z0JBQ2pCLElBQUksWUFBWSxDQUFDOztnQkFFakIsS0FBSyxJQUFJLENBQUMsR0FBRyxDQUFDLEVBQUUsQ0FBQyxHQUFHLFNBQVMsQ0FBQyxNQUFNLEdBQUc7b0JBQ25DLElBQUksVUFBVSxHQUFHLFNBQVMsQ0FBQyxDQUFDLENBQUMsQ0FBQztvQkFDOUIsWUFBWSxHQUFHLFFBQVEsQ0FBQyxhQUFhLENBQUMsQ0FBQzs7O29CQUd2QyxPQUFPLFlBQVksS0FBSyxJQUFJLElBQUksUUFBUSxDQUFDLE1BQU0sRUFBRTt3QkFDN0MsT0FBTyxDQUFDLElBQUksQ0FBQyxNQUFNLENBQUMsUUFBUSxFQUFFLGFBQWEsRUFBRSxJQUFJLENBQUMsQ0FBQyxDQUFDO3dCQUNwRCxZQUFZLEdBQUcsUUFBUSxDQUFDLGFBQWEsQ0FBQyxDQUFDO3FCQUMxQzs7b0JBRUQsSUFBSSxDQUFDLFlBQVksSUFBSSxZQUFZLENBQUMsR0FBRyxLQUFLLFVBQVUsQ0FBQyxHQUFHLEVBQUU7O3dCQUV0RCxJQUFJLFVBQVUsQ0FBQyxHQUFHLEVBQUU7NEJBQ2hCLElBQUksWUFBWSxJQUFJLFlBQVksQ0FBQyxHQUFHLEVBQUU7O2dDQUVsQyxJQUFJLEtBQUssQ0FBQyxZQUFZLENBQUMsR0FBRyxDQUFDLEtBQUssQ0FBQyxHQUFHLENBQUMsRUFBRTtvQ0FDbkMsT0FBTyxDQUFDLElBQUksQ0FBQyxNQUFNLENBQUMsUUFBUSxFQUFFLGFBQWEsRUFBRSxZQUFZLENBQUMsR0FBRyxDQUFDLENBQUMsQ0FBQztvQ0FDaEUsWUFBWSxHQUFHLFFBQVEsQ0FBQyxhQUFhLENBQUMsQ0FBQzs7b0NBRXZDLElBQUksQ0FBQyxZQUFZLElBQUksWUFBWSxDQUFDLEdBQUcsS0FBSyxVQUFVLENBQUMsR0FBRyxFQUFFO3dDQUN0RCxPQUFPLENBQUMsSUFBSSxDQUFDLEVBQUUsR0FBRyxFQUFFLFVBQVUsQ0FBQyxHQUFHLEVBQUUsRUFBRSxFQUFFLENBQUMsRUFBRSxDQUFDLENBQUM7cUNBQ2hEOzt5Q0FFSTs0Q0FDRyxhQUFhLEVBQUUsQ0FBQzt5Q0FDbkI7aUNBQ1IsTUFBTTtvQ0FDSCxPQUFPLENBQUMsSUFBSSxDQUFDLEVBQUUsR0FBRyxFQUFFLFVBQVUsQ0FBQyxHQUFHLEVBQUUsRUFBRSxFQUFFLENBQUMsRUFBRSxDQUFDLENBQUM7aUNBQ2hEOzZCQUNKLE1BQU07Z0NBQ0gsT0FBTyxDQUFDLElBQUksQ0FBQyxFQUFFLEdBQUcsRUFBRSxVQUFVLENBQUMsR0FBRyxFQUFFLEVBQUUsRUFBRSxDQUFDLEVBQUUsQ0FBQyxDQUFDOzZCQUNoRDs0QkFDRCxDQUFDLEVBQUUsQ0FBQzt5QkFDUDs7NkJBRUksSUFBSSxZQUFZLElBQUksWUFBWSxDQUFDLEdBQUcsRUFBRTtnQ0FDbkMsT0FBTyxDQUFDLElBQUksQ0FBQyxNQUFNLENBQUMsUUFBUSxFQUFFLGFBQWEsRUFBRSxZQUFZLENBQUMsR0FBRyxDQUFDLENBQUMsQ0FBQzs2QkFDbkU7cUJBQ1IsTUFBTTt3QkFDSCxhQUFhLEVBQUUsQ0FBQzt3QkFDaEIsQ0FBQyxFQUFFLENBQUM7cUJBQ1A7aUJBQ0o7OztnQkFHRCxPQUFPLGFBQWEsR0FBRyxRQUFRLENBQUMsTUFBTSxFQUFFO29CQUNwQyxZQUFZLEdBQUcsUUFBUSxDQUFDLGFBQWEsQ0FBQyxDQUFDO29CQUN2QyxPQUFPLENBQUMsSUFBSSxDQUFDLE1BQU0sQ0FBQyxRQUFRLEVBQUUsYUFBYSxFQUFFLFlBQVksSUFBSSxZQUFZLENBQUMsR0FBRyxDQUFDLENBQUMsQ0FBQztpQkFDbkY7Ozs7Z0JBSUQsSUFBSSxPQUFPLENBQUMsTUFBTSxLQUFLLFlBQVksSUFBSSxDQUFDLE9BQU8sQ0FBQyxNQUFNLEVBQUU7b0JBQ3BELE9BQU87d0JBQ0gsUUFBUSxFQUFFLFdBQVc7d0JBQ3JCLEtBQUssRUFBRSxJQUFJO3FCQUNkLENBQUM7aUJBQ0w7O2dCQUVELE9BQU87b0JBQ0gsUUFBUSxFQUFFLFdBQVc7b0JBQ3JCLEtBQUssRUFBRTt3QkFDSCxPQUFPLEVBQUUsT0FBTzt3QkFDaEIsT0FBTyxFQUFFLE9BQU87cUJBQ25CO2lCQUNKLENBQUM7YUFDTDs7WUFFRCxTQUFTLE1BQU0sQ0FBQyxHQUFHLEVBQUUsS0FBSyxFQUFFLEdBQUcsRUFBRTtnQkFDN0IsR0FBRyxDQUFDLE1BQU0sQ0FBQyxLQUFLLEVBQUUsQ0FBQyxDQUFDLENBQUM7O2dCQUVyQixPQUFPO29CQUNILElBQUksRUFBRSxLQUFLO29CQUNYLEdBQUcsRUFBRSxHQUFHO2lCQUNYLENBQUM7YUFDTDs7WUFFRCxTQUFTLFFBQVEsQ0FBQyxRQUFRLEVBQUU7Z0JBQ3hCLElBQUksSUFBSSxHQUFHLEVBQUUsQ0FBQztnQkFDZCxJQUFJLElBQUksR0FBRyxFQUFFLENBQUM7Z0JBQ2QsSUFBSSxNQUFNLEdBQUcsUUFBUSxDQUFDLE1BQU0sQ0FBQzs7Z0JBRTdCLEtBQUssSUFBSSxDQUFDLEdBQUcsQ0FBQyxFQUFFLENBQUMsR0FBRyxNQUFNLEVBQUUsQ0FBQyxFQUFFLEVBQUU7b0JBQzdCLElBQUksS0FBSyxHQUFHLFFBQVEsQ0FBQyxDQUFDLENBQUMsQ0FBQzs7b0JBRXhCLElBQUksS0FBSyxDQUFDLEdBQUcsRUFBRTt3QkFDWCxJQUFJLENBQUMsS0FBSyxDQUFDLEdBQUcsQ0FBQyxHQUFHLENBQUMsQ0FBQztxQkFDdkIsTUFBTTt3QkFDSCxJQUFJLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQyxDQUFDO3FCQUNoQjtpQkFDSjs7Z0JBRUQsT0FBTztvQkFDSCxJQUFJLEVBQUUsSUFBSTtvQkFDVixJQUFJLEVBQUUsSUFBSTtpQkFDYixDQUFDO2FBQ0w7O1lBRUQsU0FBUyxXQUFXLENBQUMsS0FBSyxFQUFFLEtBQUssRUFBRTtnQkFDL0IsSUFBSSxLQUFLLEVBQUU7b0JBQ1AsSUFBSSxPQUFPLENBQUMsS0FBSyxDQUFDLEVBQUU7d0JBQ2hCLEtBQUssQ0FBQyxJQUFJLENBQUMsS0FBSyxDQUFDLENBQUM7cUJBQ3JCLE1BQU07d0JBQ0gsS0FBSyxHQUFHLENBQUMsS0FBSyxFQUFFLEtBQUssQ0FBQyxDQUFDO3FCQUMxQjs7b0JBRUQsT0FBTyxLQUFLLENBQUM7aUJBQ2hCLE1BQU07b0JBQ0gsT0FBTyxLQUFLLENBQUM7aUJBQ2hCO2FBQ0o7U0FDSixFQUFFLEVBQUUsdUJBQXVCLEVBQUUsRUFBRSxFQUFFLG1CQUFtQixFQUFFLEVBQUUsRUFBRSxtQkFBbUIsRUFBRSxFQUFFLEVBQUUsbUJBQW1CLEVBQUUsRUFBRSxFQUFFLG9CQUFvQixFQUFFLEVBQUUsRUFBRSxpQkFBaUIsRUFBRSxFQUFFLEVBQUUsY0FBYyxFQUFFLEVBQUUsRUFBRSxZQUFZLEVBQUUsRUFBRSxFQUFFLENBQUMsRUFBRSxFQUFFLEVBQUUsRUFBRSxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUM7Q0FDNU4sQ0FBQyxDQUFDOzthQ2xrRFk7RUFDYixJQUFJO0VBQ0osSUFBSTtFQUNKLFVBQVU7Q0FDWCxDQUFDLDs7In0= \ No newline at end of file diff --git a/src/javascript/lib/core/patterns/defmatch.js b/src/javascript/lib/core/patterns/defmatch.js index fa05c07e..28400f24 100644 --- a/src/javascript/lib/core/patterns/defmatch.js +++ b/src/javascript/lib/core/patterns/defmatch.js @@ -1,6 +1,7 @@ /* @flow */ import { buildMatch } from "./match"; +import * as Types from "./types"; export class MatchError extends Error { constructor(arg: any) { @@ -25,9 +26,13 @@ export class Case { pattern: Function; fn: Function; guard: Function; + arity: number; + optionals: Array; constructor(pattern: Array, fn: Function, guard: Function = () => true){ this.pattern = buildMatch(pattern); + this.arity = pattern.length; + this.optionals = getOptionalValues(pattern); this.fn = fn; this.guard = guard; } @@ -41,6 +46,8 @@ export function defmatch(...cases: Array): Function { return function(...args: Array): any { for (let processedCase of cases) { let result = []; + args = fillInOptionalValues(args, processedCase.arity, processedCase.optionals); + if (processedCase.pattern(args, result) && processedCase.guard.apply(this, result)) { return processedCase.fn.apply(this, result); } @@ -50,6 +57,42 @@ export function defmatch(...cases: Array): Function { }; } +function getOptionalValues(pattern: Array){ + let optionals = []; + + for(let i = 0; i < pattern.length; i++){ + if(pattern[i] instanceof Types.Variable && pattern[i].default_value != Symbol.for("elixirscript.no_value")){ + optionals.push([i, pattern[i].default_value]); + } + } + + return optionals; +} + +function fillInOptionalValues(args, arity, optionals){ + if(args.length === arity || optionals.length === 0){ + return args; + } + + if(args.length + optionals.length < arity){ + return args; + } + + let numberOfOptionalsToFill = arity - args.length; + let optionalsToRemove = optionals.length - numberOfOptionalsToFill; + + let optionalsToUse = optionals.slice(optionalsToRemove); + + for(let [index, value] of optionalsToUse){ + args.splice(index, 0, value); + if(args.length === arity){ + break; + } + } + + return args; +} + export function match(pattern: any, expr: any, guard: Function = () => true): Array { let result = []; let processedPattern = buildMatch(pattern); diff --git a/src/javascript/lib/core/patterns/types.js b/src/javascript/lib/core/patterns/types.js index 52bb4654..57cfa43b 100644 --- a/src/javascript/lib/core/patterns/types.js +++ b/src/javascript/lib/core/patterns/types.js @@ -1,9 +1,9 @@ /* @flow */ export class Variable { - name: ?string; + default_value: ?any; - constructor(name: ?string = null) { - this.name = name; + constructor(default_value: ?any = Symbol.for("elixirscript.no_value")) { + this.default_value = default_value; } } @@ -95,8 +95,8 @@ export class BitStringMatch { } } -export function variable(name: ?string = null): Variable { - return new Variable(name); +export function variable(default_value: ?any = Symbol.for("elixirscript.no_value")): Variable { + return new Variable(default_value); } export function wildcard(): Wildcard { diff --git a/src/javascript/tests/patterns/defmatch.spec.js b/src/javascript/tests/patterns/defmatch.spec.js index 486c3ed6..995c3375 100644 --- a/src/javascript/tests/patterns/defmatch.spec.js +++ b/src/javascript/tests/patterns/defmatch.spec.js @@ -235,4 +235,65 @@ describe('defmatch', () => { expect(fn(new BitString(BitString.integer(-100)))).to.equal(156); }); }); + + + describe('Optional Arguments', () => { + it('single optional argument', () => { + + let fn = Patterns.defmatch( + Patterns.make_case( + [Patterns.variable(2)], + (arg) => arg + ) + ); + + expect(fn()).to.equal(2); + expect(fn(3)).to.equal(3); + }); + + + it('single optional argument and one required argument', () => { + + let fn = Patterns.defmatch( + Patterns.make_case( + [Patterns.variable(), Patterns.variable(2)], + (arg1, arg2) => arg1 + arg2 + ) + ); + + expect(fn.bind(fn)).to.throw("No match for:"); + expect(fn(1)).to.equal(3); + expect(fn(3, 4)).to.equal(7); + }); + + it('two optional arguments and one required argument', () => { + + let fn = Patterns.defmatch( + Patterns.make_case( + [Patterns.variable(3), Patterns.variable(), Patterns.variable(2)], + (arg1, arg2, arg3) => arg1 + arg2 + arg3 + ) + ); + + expect(fn(1)).to.equal(6); + expect(fn(3, 4)).to.equal(9); + }); + + + it('two optional arguments in between 2 required', () => { + + let fn = Patterns.defmatch( + Patterns.make_case( + [Patterns.variable(), Patterns.variable(2), Patterns.variable(3), Patterns.variable()], + (arg1, arg2, arg3, arg4) => arg1 + arg2 + arg3 + arg4 + ) + ); + + expect(fn(1, 4)).to.equal(10); + expect(fn(1, 5, 4)).to.equal(13); + expect(fn(1, 5, 7, 4)).to.equal(17); + }); + }); + + }); diff --git a/test/translator/function_test.exs b/test/translator/function_test.exs index 84c195fb..6d65d96f 100644 --- a/test/translator/function_test.exs +++ b/test/translator/function_test.exs @@ -755,9 +755,9 @@ defmodule ElixirScript.Translator.Function.Test do end js_code = """ - const test1 = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable(), Elixir.Core.Patterns.variable()],function(alpha,beta = 0) { - return null; - })); + const test1 = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable(), Elixir.Core.Patterns.variable(0)],function(alpha,beta) { + return null; + })); """ assert_translation(ex_ast, js_code) @@ -768,11 +768,12 @@ defmodule ElixirScript.Translator.Function.Test do end js_code = """ - const test1 = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable()],function(alpha = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable()],function(x) { - return x; - }))) { - return null; - })); + const test1 = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable(Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable()],function(x) { + return x; + })))], + function(alpha) { + return null; + })); """ assert_translation(ex_ast, js_code) From 01444a149d1e44f70f3657dce9f5db8f8977a1dc Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Thu, 25 Feb 2016 17:54:39 -0600 Subject: [PATCH 168/860] Added Kernel.object --- CHANGELOG.md | 6 ++++++ lib/elixir_script/prelude/kernel.ex | 11 +++++++++++ test/translator/map_test.exs | 7 +++++++ 3 files changed, 24 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index f959cdee..99666f10 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,12 @@ * Functions with catch, after, else clauses * `with` special form * Pin operator in map keys and function clauses + * Added `Kernel.object/1` function to make it more natural to create a JavaScript object with string keys + Elixirscript, by default turns the following, `%{a: "b"}` into `{[Symbol.for("a")]: "b"}` in JavaScript. In order to get string keys, + one would have to do `%{"a" => "b"}` which turns into `{a: "b"}` in JavaScript. With `Kernel.object`, you can create string keyed maps + conveniently, `object(a: "b")` which turns into `{a: "b"}`. + + **NOTE**: when updating the created by, you still have to use the string form `%{ my_map | "a" => "c" }` * Bugfixes * Fixed optional parameter implementation diff --git a/lib/elixir_script/prelude/kernel.ex b/lib/elixir_script/prelude/kernel.ex index bf3b2453..099f0e10 100644 --- a/lib/elixir_script/prelude/kernel.ex +++ b/lib/elixir_script/prelude/kernel.ex @@ -192,4 +192,15 @@ defmodule ElixirScript.Kernel do %ElixirScript.Range{ first: unquote(first), last: unquote(last) } end end + + defmacro object(args) do + args = Enum.map(args, fn + { k, v } when Kernel.is_atom(k) -> + { Atom.to_string(k), v } + pair -> + pair + end) + + { :%{}, [], args } + end end diff --git a/test/translator/map_test.exs b/test/translator/map_test.exs index 2ea36e51..9dd2a3a3 100644 --- a/test/translator/map_test.exs +++ b/test/translator/map_test.exs @@ -69,4 +69,11 @@ defmodule ElixirScript.Translator.Map.Test do """ assert_translation(ex_ast, js_code) end + + test "translate object macro" do + ex_ast = quote do: object(a: b) + js_code = "Object.freeze({ a: b })" + assert_translation(ex_ast, js_code) + end + end From e14f6de81e4f4b2133dd7f3f1f6eb3312f28fb97 Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Fri, 26 Feb 2016 12:09:39 -0600 Subject: [PATCH 169/860] Update CHANGELOG.md --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 99666f10..f659583c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -13,7 +13,7 @@ **NOTE**: when updating the created by, you still have to use the string form `%{ my_map | "a" => "c" }` * Bugfixes - * Fixed optional parameter implementation + * Optional parameters should now work as expected # v0.15.2 * Enhancements From cfdae14adaf24afeb4c4cd22a03319926b60eff2 Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Fri, 26 Feb 2016 12:58:38 -0600 Subject: [PATCH 170/860] Updated docs. Added JS.update/2 --- CHANGELOG.md | 4 ++++ lib/elixir_script/prelude/js.ex | 4 ++-- lib/elixir_script/prelude/kernel.ex | 7 +++++++ lib/elixir_script/translator/js.ex | 16 ++++++---------- test/prelude/js_test.exs | 6 ++++-- 5 files changed, 23 insertions(+), 14 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 99666f10..bbde6be9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -14,6 +14,10 @@ * Bugfixes * Fixed optional parameter implementation + +* Breaking + * `JS.update(object, property, value)` has been removed and replaced with `JS.update(object, map)` + This allows you to update multiple values on a javascript object at once. # v0.15.2 * Enhancements diff --git a/lib/elixir_script/prelude/js.ex b/lib/elixir_script/prelude/js.ex index 4b7603fd..ec047e8d 100644 --- a/lib/elixir_script/prelude/js.ex +++ b/lib/elixir_script/prelude/js.ex @@ -20,9 +20,9 @@ defmodule ElixirScript.JS do Updates an existing JavaScript object. ex: - JS.update elem, "width", 100 + JS.update elem, %{"width" => 100} """ - defmacro update(object, property, value) do + defmacro update(object, map) do end diff --git a/lib/elixir_script/prelude/kernel.ex b/lib/elixir_script/prelude/kernel.ex index 099f0e10..25794b16 100644 --- a/lib/elixir_script/prelude/kernel.ex +++ b/lib/elixir_script/prelude/kernel.ex @@ -193,6 +193,13 @@ defmodule ElixirScript.Kernel do end end + @doc """ + Provides a convenient way to create a string-based map. + + Elixirscript, by default turns the following, `%{a: "b"}` into `{[Symbol.for("a")]: "b"}` in JavaScript. In order to get string keys, + one would have to do `%{"a" => "b"}` which turns into `{a: "b"}` in JavaScript. With `Kernel.object`, you can create string keyed maps + conveniently, `object(a: "b")` which turns into `{a: "b"}` + """ defmacro object(args) do args = Enum.map(args, fn { k, v } when Kernel.is_atom(k) -> diff --git a/lib/elixir_script/translator/js.ex b/lib/elixir_script/translator/js.ex index c6216b9c..2a1c3bb0 100644 --- a/lib/elixir_script/translator/js.ex +++ b/lib/elixir_script/translator/js.ex @@ -46,16 +46,12 @@ defmodule ElixirScript.Translator.JS do ) end - defp do_translate({:update, _, [object, property, value]}, env) do - Builder.assignment_expression( - :=, - Builder.member_expression( - Translator.translate!(object, env), - Translator.translate!(property, env), - true - ), - Translator.translate!(value, env) - ) + defp do_translate({:update, _, [object, map]}, env) do + quoted = quote do + Object.assign(unquote(object), unquote(map)) + end + + Translator.translate!(quoted, env) end defp do_translate({:import, _, [module_names, from]}, env) when is_list(module_names) do diff --git a/test/prelude/js_test.exs b/test/prelude/js_test.exs index fd5f800f..8673a8d8 100644 --- a/test/prelude/js_test.exs +++ b/test/prelude/js_test.exs @@ -26,11 +26,13 @@ defmodule ElixirScript.Lib.JS.Test do test "translate update" do ex_ast = quote do - JS.update A, "b", [1, 2, 3] + JS.update A, %{"b" => [1, 2, 3]} end js_code = """ - A['b'] = Object.freeze([1, 2, 3]) + Object.assign(A, Object.freeze({ + b: Object.freeze([1, 2, 3]) + })) """ assert_translation(ex_ast, js_code) From ca8b61db8054a8b477fe81d5243771d30b4405ee Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Sat, 27 Feb 2016 08:25:55 -0600 Subject: [PATCH 171/860] Added @ to imported items from Kernel in ElixirScript.Kernel --- lib/elixir_script/prelude/kernel.ex | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/elixir_script/prelude/kernel.ex b/lib/elixir_script/prelude/kernel.ex index 25794b16..fb4de196 100644 --- a/lib/elixir_script/prelude/kernel.ex +++ b/lib/elixir_script/prelude/kernel.ex @@ -1,6 +1,6 @@ defmodule ElixirScript.Kernel do import Kernel, only: [defmodule: 2, def: 1, def: 2, defp: 2, - defmacro: 1, defmacro: 2, defmacrop: 2, ||: 2, !: 1, ++: 2, in: 2, &&: 2, ===: 2] + defmacro: 1, defmacro: 2, defmacrop: 2, ||: 2, !: 1, ++: 2, in: 2, &&: 2, ===: 2, @: 1] defmacro if(condition, clauses) do build_if(condition, clauses) From 3468d1e256d2836e2585837439c1fe30ff6ba55f Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Sat, 27 Feb 2016 09:09:47 -0600 Subject: [PATCH 172/860] Removed js testing from travis config. Fixed bitstring implementation errors --- .travis.yml | 8 +++--- lib/elixir_script/translator/bitstring.ex | 27 +++++++++++++------ .../translator/pattern_matching.ex | 8 +++--- test/translator/bitstring_test.exs | 22 +++++++-------- test/translator/for_test.exs | 16 ++++++----- 5 files changed, 46 insertions(+), 35 deletions(-) diff --git a/.travis.yml b/.travis.yml index 21807e42..9fc86223 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,11 +1,11 @@ sudo: false language: elixir elixir: - - 1.2.0 + - 1.2.3 otp_release: - 18.0 -before_script: - - npm install +#before_script: +# - npm install script: - mix test - - npm test \ No newline at end of file +# - npm test \ No newline at end of file diff --git a/lib/elixir_script/translator/bitstring.ex b/lib/elixir_script/translator/bitstring.ex index a8e7b43d..d4f2d657 100644 --- a/lib/elixir_script/translator/bitstring.ex +++ b/lib/elixir_script/translator/bitstring.ex @@ -32,31 +32,42 @@ defmodule ElixirScript.Translator.Bitstring do ast end - def make_bitstring_element({:::, _, [element, {type, _, _}]}, env) when type in [:integer, :float, :bitstring, :bits, :binary, :bytes, :utf8, :utf16, :utf32] do - do_make_bitstring_element({type, Translator.translate!(element, env)}) + def make_bitstring_element({:::, _, [element, {type, _, _}]}, env) when type in [:integer, :float, :bitstring, :bits, :binary, :bytes, :utf8, :utf16, :utf32, :signed, :unsigned] do + do_make_bitstring_element({type, translate_element(element, env)}) end def make_bitstring_element({:::, _, [element, {type, _, params}]}, env) when type in [:size, :unit] do - do_make_bitstring_element({type, Translator.translate!(element, env), Enum.map(params, &Translator.translate!(&1, env))}) + do_make_bitstring_element({type, translate_element(element, env), Enum.map(params, &translate_element(&1, env))}) end def make_bitstring_element({:::, _, [element, {:*, _, [size, unit]}]}, env) do - size_ast = do_make_bitstring_element({:size, Translator.translate!(element, env), [Translator.translate!(size, env)]}) - do_make_bitstring_element({:unit, size_ast, [Translator.translate!(unit, env)]}) + size_ast = do_make_bitstring_element({:size, translate_element(element, env), [translate_element(size, env)]}) + do_make_bitstring_element({:unit, size_ast, [translate_element(unit, env)]}) end def make_bitstring_element({:::, _, [element, {:-, _, types}]}, env) do - handle_type_adjectives({:-, [], types}, Translator.translate!(element, env), env) + handle_type_adjectives({:-, [], types}, translate_element(element, env), env) end def make_bitstring_element({:::, _, [element, size]}, env) do - do_make_bitstring_element({:size, Translator.translate!(element, env), [Translator.translate!(size, env)]}) + do_make_bitstring_element({:size, translate_element(element, env), [translate_element(size, env)]}) end def make_bitstring_element(element, env) do - do_make_bitstring_element({:binary, Translator.translate!(element, env)}) + do_make_bitstring_element({:binary, translate_element(element, env)}) + end + + def translate_element(ElixirScript.Translator.PatternMatching, _) do + JS.object_expression([JS.property( + JS.literal("value"), + ElixirScript.Translator.PatternMatching.parameter() + ) + ]) end + def translate_element(element, env) do + Translator.translate!(element, env) + end defp handle_type_adjectives({:-, _, types}, ast, env) do Enum.reduce(types, ast, fn(type, current_ast) -> diff --git a/lib/elixir_script/translator/pattern_matching.ex b/lib/elixir_script/translator/pattern_matching.ex index 63bb413e..44ea9d25 100644 --- a/lib/elixir_script/translator/pattern_matching.ex +++ b/lib/elixir_script/translator/pattern_matching.ex @@ -160,17 +160,15 @@ defmodule ElixirScript.Translator.PatternMatching do defp do_build_match({:<<>>, _, elements}, env) do params = Enum.reduce(elements, [], fn - ({:::, _, [{ variable, [], params }, _]}, state) when is_atom(params) -> + ({:::, _, [{ variable, _, params }, _]}, state) when is_atom(params) -> state ++ [JS.identifier(variable)] _, state -> state end) - var = {{:., [], [{:__aliases__, [], [Elixir, :Core, :Patterns]}, :variable]}, [], []} - elements = Enum.map(elements, fn - ({:::, context, [{ variable, [], params }, options]}) when is_atom(params) -> - Bitstring.make_bitstring_element({:::, context, [{:%{}, [], [{"value", var}]}, options]}, env) + ({:::, context, [{ variable, _, params }, options]}) when is_atom(params) -> + Bitstring.make_bitstring_element({:::, context, [ElixirScript.Translator.PatternMatching, options]}, env) x -> Bitstring.make_bitstring_element(x, env) end) diff --git a/test/translator/bitstring_test.exs b/test/translator/bitstring_test.exs index 8632fb7f..9d0fdae3 100644 --- a/test/translator/bitstring_test.exs +++ b/test/translator/bitstring_test.exs @@ -43,11 +43,11 @@ defmodule ElixirScript.Translator.Bitstring.Test do test "translate pattern matching bitstring" do ex_ast = quote do: <> = <<"Frank the Walrus">> js_code = """ - let [name,species] = Elixir.Core.Patterns.match(Elixir.Core.Patterns.bitStringMatch(Elixir.Core.BitString.size(Elixir.Core.BitString.binary(Object.freeze({ - value: Elixir.Core.Functions.call_property(Elixir.Core.Patterns,'variable') - })),5),Elixir.Core.BitString.binary(' the '),Elixir.Core.BitString.binary(Object.freeze({ - value: Elixir.Core.Functions.call_property(Elixir.Core.Patterns,'variable') - }))),'Frank the Walrus'); + let [name,species] = Elixir.Core.Patterns.match(Elixir.Core.Patterns.bitStringMatch(Elixir.Core.BitString.size(Elixir.Core.BitString.binary({ + 'value': Elixir.Core.Patterns.variable() + }),5),Elixir.Core.BitString.binary(' the '),Elixir.Core.BitString.binary({ + 'value': Elixir.Core.Patterns.variable() + })),'Frank the Walrus'); """ assert_translation(ex_ast, js_code) @@ -55,9 +55,9 @@ defmodule ElixirScript.Translator.Bitstring.Test do ex_ast = quote do: <> = <<-100>> js_code = """ - let [int] = Elixir.Core.Patterns.match(Elixir.Core.Patterns.bitStringMatch(Elixir.Core.BitString.integer(Object.freeze({ - value: Elixir.Core.Functions.call_property(Elixir.Core.Patterns,'variable') - }))),new Elixir.Core.BitString(Elixir.Core.BitString.binary(-100))); + let [int] = Elixir.Core.Patterns.match(Elixir.Core.Patterns.bitStringMatch(Elixir.Core.BitString.integer({ + 'value': Elixir.Core.Patterns.variable() + })),new Elixir.Core.BitString(Elixir.Core.BitString.binary(-100))); """ assert_translation(ex_ast, js_code) @@ -65,9 +65,9 @@ defmodule ElixirScript.Translator.Bitstring.Test do ex_ast = quote do: <<-100::signed, _rest::binary>> = <<-100, "foo">> js_code = """ - let [_rest] = Elixir.Core.Patterns.match(Elixir.Core.Patterns.bitStringMatch(Elixir.Core.BitString.size(-100, signed),Elixir.Core.BitString.binary(Object.freeze({ - value: Elixir.Core.Functions.call_property(Elixir.Core.Patterns,'variable') - }))),new Elixir.Core.BitString(Elixir.Core.BitString.binary(-100),Elixir.Core.BitString.binary('foo'))); + let [_rest] = Elixir.Core.Patterns.match(Elixir.Core.Patterns.bitStringMatch(Elixir.Core.BitString.signed(-100),Elixir.Core.BitString.binary({ + 'value': Elixir.Core.Patterns.variable() + })),new Elixir.Core.BitString(Elixir.Core.BitString.binary(-100),Elixir.Core.BitString.binary('foo'))); """ assert_translation(ex_ast, js_code) diff --git a/test/translator/for_test.exs b/test/translator/for_test.exs index 4dc2b16d..945c8bd5 100644 --- a/test/translator/for_test.exs +++ b/test/translator/for_test.exs @@ -131,13 +131,15 @@ defmodule ElixirScript.Translator.For.Test do end js_code = """ - Elixir.Core.SpecialForms._for(Object.freeze([Object.freeze([Elixir.Core.Patterns.bitStringMatch(Elixir.Core.BitString.size(Object.freeze({ - value: Elixir.Core.Functions.call_property(Elixir.Core.Patterns,'variable') - }),8),Elixir.Core.BitString.size(Object.freeze({ - value: Elixir.Core.Functions.call_property(Elixir.Core.Patterns,'variable') - }),8),Elixir.Core.BitString.size(Object.freeze({ - value: Elixir.Core.Functions.call_property(Elixir.Core.Patterns,'variable') - }),8)), pixels])]), + Elixir.Core.SpecialForms._for(Object.freeze([Object.freeze([Elixir.Core.Patterns.bitStringMatch(Elixir.Core.BitString.size({ + 'value': Elixir.Core.Patterns.variable() + },8), + Elixir.Core.BitString.size({ + 'value': Elixir.Core.Patterns.variable() + },8), + Elixir.Core.BitString.size({ + 'value': Elixir.Core.Patterns.variable() + },8)), pixels])]), function(r,g,b) { return new Elixir.Core.Tuple(r,g,b); }, From 9c4fa5167005586b41f37985998beec84191773a Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Sat, 27 Feb 2016 09:13:26 -0600 Subject: [PATCH 173/860] Updated docs --- CHANGELOG.md | 2 +- GettingStarted.md | 2 +- mix.exs | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 8f6009f7..fafe8471 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,4 +1,4 @@ -# v0.16.0-dev +# v0.16.0 * Enhancements * Bitstring pattern matching * Bitstrings in for comprehensions diff --git a/GettingStarted.md b/GettingStarted.md index 751116f1..cb50ec93 100644 --- a/GettingStarted.md +++ b/GettingStarted.md @@ -97,7 +97,7 @@ The intent of this guide is to get you started with ElixirScript. It will give y The first step is getting the dependency. In your mix.exs file for your elixir project, add elixir_script to your deps. ```elixir - {:elixir_script, "~> 0.15"} + {:elixir_script, "~> 0.16"} ``` * Step 2: Now download the dep diff --git a/mix.exs b/mix.exs index 4a2dec7d..e38853b3 100644 --- a/mix.exs +++ b/mix.exs @@ -4,7 +4,7 @@ defmodule ElixirScript.Mixfile do def project do [ app: :elixir_script, - version: "0.16.0-dev", + version: "0.16.0", elixir: "~> 1.0", escript: escript_config, deps: deps, From ae49a1a43c7209a19c7c8427c915928f9f61e2c2 Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Sat, 5 Mar 2016 06:27:39 -0600 Subject: [PATCH 174/860] A look at using common js modules --- lib/elixir_script/module_systems/common.ex | 65 ++++++++++++++++++++++ lib/elixir_script/module_systems/es6.ex | 56 +++++++++++++++++++ lib/elixir_script/translator/import.ex | 34 ----------- lib/elixir_script/translator/js.ex | 39 ++----------- lib/elixir_script/translator/module.ex | 7 ++- lib/elixir_script/translator/utils.ex | 11 ++++ 6 files changed, 140 insertions(+), 72 deletions(-) create mode 100644 lib/elixir_script/module_systems/common.ex create mode 100644 lib/elixir_script/module_systems/es6.ex delete mode 100644 lib/elixir_script/translator/import.ex diff --git a/lib/elixir_script/module_systems/common.ex b/lib/elixir_script/module_systems/common.ex new file mode 100644 index 00000000..5e41195c --- /dev/null +++ b/lib/elixir_script/module_systems/common.ex @@ -0,0 +1,65 @@ +defmodule ElixirScript.ModuleSystems.Common do + alias ESTree.Tools.Builder, as: JS + alias ElixirScript.Translator + alias ElixirScript.Translator.Utils + + def import_module(module_name, from, env) do + ref_declarator = JS.variable_declarator( + Translator.translate!(module_name, env), + JS.call_expression( + JS.identifier("require"), + [JS.literal(from)] + ) + ) + + JS.variable_declaration([ref_declarator], :const) + end + + def import_module(module_name, %ElixirScript.Macro.Env{} = env) do + {from, _ } = Code.eval_quoted(module_name) + + ref_declarator = JS.variable_declarator( + Translator.translate!(module_name, env), + JS.call_expression( + JS.identifier("require"), + [JS.literal(Macro.underscore(from))] + ) + ) + + JS.variable_declaration([ref_declarator], :const) + + end + + def import_module(import_name, from) do + + ref_declarator = JS.variable_declarator( + JS.identifier(import_name), + JS.call_expression( + JS.identifier("require"), + [JS.literal(from)] + ) + ) + + JS.variable_declaration([ref_declarator], :const) + end + + defp do_import_module(import_specifiers, file_path) do + JS.import_declaration( + import_specifiers, + JS.literal(file_path) + ) + end + + def export_module(exported_object) do + JS.assignment_expression( + :=, + JS.member_expression( + JS.identifier("module"), + JS.identifier("exports") + ), + exported_object + ) + end + + +end diff --git a/lib/elixir_script/module_systems/es6.ex b/lib/elixir_script/module_systems/es6.ex new file mode 100644 index 00000000..ef5cb7a4 --- /dev/null +++ b/lib/elixir_script/module_systems/es6.ex @@ -0,0 +1,56 @@ +defmodule ElixirScript.ModuleSystems.ES6 do + alias ESTree.Tools.Builder, as: JS + alias ElixirScript.Translator + alias ElixirScript.Translator.Utils + + def import_module(module_names, from, env) when is_list(module_names) do + import_specifiers = Enum.map(module_names, fn(x) -> + JS.import_specifier( + Translator.translate!(x, env), + Translator.translate!(x, env) + ) + end) + + do_import_module(import_specifiers, from) + end + + def import_module(module_name, from, env) do + import_specifier = JS.import_default_specifier( + Translator.translate!(module_name, env), + Translator.translate!(module_name, env) + ) + + do_import_module([import_specifier], from) + end + + def import_module(module_name, %ElixirScript.Macro.Env{} = env) do + import_specifier = JS.import_default_specifier( + Translator.translate!(module_name, env), + Translator.translate!(module_name, env) + ) + + {from, _ } = Code.eval_quoted(module_name) + + do_import_module([import_specifier], Macro.underscore(from)) + end + + def import_module(import_name, from) do + import_specifier = JS.import_default_specifier( + JS.identifier(import_name) + ) + + do_import_module([import_specifier], from) + end + + defp do_import_module(import_specifiers, file_path) do + JS.import_declaration( + import_specifiers, + JS.literal(file_path) + ) + end + + def export_module(exported_object) do + JS.export_default_declaration(exported_object) + end + +end diff --git a/lib/elixir_script/translator/import.ex b/lib/elixir_script/translator/import.ex deleted file mode 100644 index 18f24580..00000000 --- a/lib/elixir_script/translator/import.ex +++ /dev/null @@ -1,34 +0,0 @@ -defmodule ElixirScript.Translator.Import do - @moduledoc false - alias ESTree.Tools.Builder, as: JS - alias ElixirScript.Translator.Utils - - def make_import(module_name) do - do_make_import(Utils.name_to_js_name(module_name), Utils.name_to_js_file_name(module_name)) - end - - def create_standard_lib_imports(std_lib_path) do - do_make_import(:Elixir, std_lib_path) - end - - defp do_make_import(import_name, file_name) do - root = ElixirScript.Translator.State.get().compiler_opts.root - - import_specifier = JS.import_default_specifier( - JS.identifier(import_name) - ) - - root = case root do - nil -> - "./" - root -> - root <> "/" - end - - JS.import_declaration( - [import_specifier], - JS.literal("#{root <> file_name}") - ) - end - -end diff --git a/lib/elixir_script/translator/js.ex b/lib/elixir_script/translator/js.ex index 2a1c3bb0..2eb81a9b 100644 --- a/lib/elixir_script/translator/js.ex +++ b/lib/elixir_script/translator/js.ex @@ -3,6 +3,7 @@ defmodule ElixirScript.Translator.JS do alias ESTree.Tools.Builder alias ElixirScript.Translator + alias ElixirScript.ModuleSystems.ES6 @doc false def translate_js_function(name, params, env) do @@ -55,47 +56,15 @@ defmodule ElixirScript.Translator.JS do end defp do_translate({:import, _, [module_names, from]}, env) when is_list(module_names) do - import_specifiers = Enum.map(module_names, fn(x) -> - Builder.import_specifier( - Translator.translate!(x, env), - Translator.translate!(x, env) - ) - end) - - build_import_declaration(import_specifiers, from) + ES6.import_module(module_names, from, env) end defp do_translate({:import, _, [module_name, from]}, env) do - - translated = Translator.translate!(module_name, env) - - import_specifier = Builder.import_default_specifier( - translated, - translated - ) - - build_import_declaration([import_specifier], from) + ES6.import_module(module_name, from, env) end defp do_translate({:import, _, [module_name]}, env) do - - translated = Translator.translate!(module_name, env) - - import_specifier = Builder.import_default_specifier( - translated, - translated - ) - - {from, _ } = Code.eval_quoted(module_name) - - build_import_declaration([import_specifier], Macro.underscore(from)) - end - - defp build_import_declaration(import_specifiers, from) do - Builder.import_declaration( - import_specifiers, - Builder.identifier("'#{from}'") - ) + ES6.import_module(module_name, env) end end diff --git a/lib/elixir_script/translator/module.ex b/lib/elixir_script/translator/module.ex index 96cff913..a7e479c5 100644 --- a/lib/elixir_script/translator/module.ex +++ b/lib/elixir_script/translator/module.ex @@ -4,6 +4,7 @@ defmodule ElixirScript.Translator.Module do alias ElixirScript.Translator alias ElixirScript.Translator.Utils alias ElixirScript.Translator.Function + alias ElixirScript.ModuleSystems.{ES6,Common} def make_module(ElixirScript.Temp, body, env) do { body, _ } = translate_body(body, env) @@ -50,7 +51,7 @@ defmodule ElixirScript.Translator.Module do exported_functions = Enum.map(exported_functions, fn({_key, value}) -> value end) private_functions = Enum.map(private_functions, fn({_key, value}) -> value end) - default = JS.export_default_declaration(exported_object) + default = Common.export_module(exported_object) result = %{ name: Utils.quoted_to_name({:__aliases__, [], module }), @@ -175,7 +176,7 @@ defmodule ElixirScript.Translator.Module do compiler_opts = ElixirScript.Translator.State.get().compiler_opts case compiler_opts.import_standard_libs do true -> - [ElixirScript.Translator.Import.create_standard_lib_imports(compiler_opts.core_path)] + [Common.import_module(:Elixir, Utils.make_local_file_path(compiler_opts.core_path))] false -> [] end @@ -208,7 +209,7 @@ defmodule ElixirScript.Translator.Module do end def make_imports(enum) do - Enum.map(enum, fn(x) -> ElixirScript.Translator.Import.make_import(x) end) + Enum.map(enum, fn(x) -> Common.import_module(Utils.name_to_js_name(x), Utils.make_local_file_path(Utils.name_to_js_file_name(x))) end) end end diff --git a/lib/elixir_script/translator/utils.ex b/lib/elixir_script/translator/utils.ex index 96020d66..78d0aca4 100644 --- a/lib/elixir_script/translator/utils.ex +++ b/lib/elixir_script/translator/utils.ex @@ -175,4 +175,15 @@ defmodule ElixirScript.Translator.Utils do Enum.join([:Elixir] ++ name, ".") end + def make_local_file_path(file_name) do + root = ElixirScript.Translator.State.get().compiler_opts.root + + case root do + nil -> + "./" <> file_name + root -> + root <> "/" <> file_name + end + end + end From 54743fa578e9f092b2c7e483d7edad4c3405df31 Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Sat, 5 Mar 2016 07:33:11 -0600 Subject: [PATCH 175/860] Abstraction of JavaScript module system --- lib/elixir_script/module_systems.ex | 27 +++++++++++++ lib/elixir_script/module_systems/common.ex | 44 ++++++++-------------- lib/elixir_script/translator/js.ex | 8 ++-- lib/elixir_script/translator/module.ex | 8 ++-- mix.exs | 2 +- mix.lock | 2 +- 6 files changed, 53 insertions(+), 38 deletions(-) create mode 100644 lib/elixir_script/module_systems.ex diff --git a/lib/elixir_script/module_systems.ex b/lib/elixir_script/module_systems.ex new file mode 100644 index 00000000..e2ea1e8e --- /dev/null +++ b/lib/elixir_script/module_systems.ex @@ -0,0 +1,27 @@ +defmodule ElixirScript.ModuleSystems do + + defp module_system() do + ElixirScript.ModuleSystems.ES6 + end + + def import_module(module_names, from, env) when is_list(module_names) do + module_system.import_module(module_names, from, env) + end + + def import_module(module_name, from, env) do + module_system.import_module(module_name, from, env) + end + + def import_module(module_name, %ElixirScript.Macro.Env{} = env) do + module_system.import_module(module_name, env) + end + + def import_module(import_name, from) do + module_system.import_module(import_name, from) + end + + def export_module(exported_object) do + module_system.export_module(exported_object) + end + +end diff --git a/lib/elixir_script/module_systems/common.ex b/lib/elixir_script/module_systems/common.ex index 5e41195c..c1a4c140 100644 --- a/lib/elixir_script/module_systems/common.ex +++ b/lib/elixir_script/module_systems/common.ex @@ -3,51 +3,39 @@ defmodule ElixirScript.ModuleSystems.Common do alias ElixirScript.Translator alias ElixirScript.Translator.Utils - def import_module(module_name, from, env) do - ref_declarator = JS.variable_declarator( - Translator.translate!(module_name, env), - JS.call_expression( - JS.identifier("require"), - [JS.literal(from)] - ) - ) + def import_module(module_names, from, env) when is_list(module_names) do + assignment_properties = Enum.map(module_names, fn(x) -> + JS.assignment_property(Translator.translate!(x, env)) + end) - JS.variable_declaration([ref_declarator], :const) + do_import_module(JS.object_pattern(assignment_properties), from) + end + + def import_module(module_name, from, env) do + do_import_module(Translator.translate!(module_name, env), from) end def import_module(module_name, %ElixirScript.Macro.Env{} = env) do {from, _ } = Code.eval_quoted(module_name) - - ref_declarator = JS.variable_declarator( - Translator.translate!(module_name, env), - JS.call_expression( - JS.identifier("require"), - [JS.literal(Macro.underscore(from))] - ) - ) - - JS.variable_declaration([ref_declarator], :const) - + do_import_module(Translator.translate!(module_name, env), Macro.underscore(from)) end def import_module(import_name, from) do + do_import_module(JS.identifier(import_name), from) + end + + defp do_import_module(ref, file_path) do ref_declarator = JS.variable_declarator( - JS.identifier(import_name), + ref, JS.call_expression( JS.identifier("require"), - [JS.literal(from)] + [JS.literal(file_path)] ) ) JS.variable_declaration([ref_declarator], :const) - end - defp do_import_module(import_specifiers, file_path) do - JS.import_declaration( - import_specifiers, - JS.literal(file_path) - ) end def export_module(exported_object) do diff --git a/lib/elixir_script/translator/js.ex b/lib/elixir_script/translator/js.ex index 2eb81a9b..c5c36b0e 100644 --- a/lib/elixir_script/translator/js.ex +++ b/lib/elixir_script/translator/js.ex @@ -3,7 +3,7 @@ defmodule ElixirScript.Translator.JS do alias ESTree.Tools.Builder alias ElixirScript.Translator - alias ElixirScript.ModuleSystems.ES6 + alias ElixirScript.ModuleSystems @doc false def translate_js_function(name, params, env) do @@ -56,15 +56,15 @@ defmodule ElixirScript.Translator.JS do end defp do_translate({:import, _, [module_names, from]}, env) when is_list(module_names) do - ES6.import_module(module_names, from, env) + ModuleSystems.import_module(module_names, from, env) end defp do_translate({:import, _, [module_name, from]}, env) do - ES6.import_module(module_name, from, env) + ModuleSystems.import_module(module_name, from, env) end defp do_translate({:import, _, [module_name]}, env) do - ES6.import_module(module_name, env) + ModuleSystems.import_module(module_name, env) end end diff --git a/lib/elixir_script/translator/module.ex b/lib/elixir_script/translator/module.ex index a7e479c5..b25233d8 100644 --- a/lib/elixir_script/translator/module.ex +++ b/lib/elixir_script/translator/module.ex @@ -4,7 +4,7 @@ defmodule ElixirScript.Translator.Module do alias ElixirScript.Translator alias ElixirScript.Translator.Utils alias ElixirScript.Translator.Function - alias ElixirScript.ModuleSystems.{ES6,Common} + alias ElixirScript.ModuleSystems def make_module(ElixirScript.Temp, body, env) do { body, _ } = translate_body(body, env) @@ -51,7 +51,7 @@ defmodule ElixirScript.Translator.Module do exported_functions = Enum.map(exported_functions, fn({_key, value}) -> value end) private_functions = Enum.map(private_functions, fn({_key, value}) -> value end) - default = Common.export_module(exported_object) + default = ModuleSystems.export_module(exported_object) result = %{ name: Utils.quoted_to_name({:__aliases__, [], module }), @@ -176,7 +176,7 @@ defmodule ElixirScript.Translator.Module do compiler_opts = ElixirScript.Translator.State.get().compiler_opts case compiler_opts.import_standard_libs do true -> - [Common.import_module(:Elixir, Utils.make_local_file_path(compiler_opts.core_path))] + [ModuleSystems.import_module(:Elixir, Utils.make_local_file_path(compiler_opts.core_path))] false -> [] end @@ -209,7 +209,7 @@ defmodule ElixirScript.Translator.Module do end def make_imports(enum) do - Enum.map(enum, fn(x) -> Common.import_module(Utils.name_to_js_name(x), Utils.make_local_file_path(Utils.name_to_js_file_name(x))) end) + Enum.map(enum, fn(x) -> ModuleSystems.import_module(Utils.name_to_js_name(x), Utils.make_local_file_path(Utils.name_to_js_file_name(x))) end) end end diff --git a/mix.exs b/mix.exs index e38853b3..635fe5b0 100644 --- a/mix.exs +++ b/mix.exs @@ -28,7 +28,7 @@ defmodule ElixirScript.Mixfile do defp deps do [ - {:estree, "~> 2.2"}, + {:estree, "~> 2.3" }, {:earmark, "~> 0.2", only: :dev }, {:ex_doc, "~> 0.11", only: :dev }, {:excoveralls, "~> 0.4", only: :test}, diff --git a/mix.lock b/mix.lock index 6b153af9..9e5f21e5 100644 --- a/mix.lock +++ b/mix.lock @@ -4,7 +4,7 @@ "credo": {:hex, :credo, "0.2.6"}, "dogma": {:hex, :dogma, "0.0.7"}, "earmark": {:hex, :earmark, "0.2.1"}, - "estree": {:hex, :estree, "2.2.0"}, + "estree": {:hex, :estree, "2.3.0"}, "ex_doc": {:hex, :ex_doc, "0.11.4"}, "excoveralls": {:hex, :excoveralls, "0.5.1"}, "exjsx": {:hex, :exjsx, "3.2.0"}, From 44ee704bbe3372167690741cc316aa9ebda8587a Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Sat, 5 Mar 2016 07:34:23 -0600 Subject: [PATCH 176/860] Next dev version --- CHANGELOG.md | 2 ++ mix.exs | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index fafe8471..ba15b37a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,5 @@ +# v0.17.0-dev + # v0.16.0 * Enhancements * Bitstring pattern matching diff --git a/mix.exs b/mix.exs index 635fe5b0..e7bd9da6 100644 --- a/mix.exs +++ b/mix.exs @@ -4,7 +4,7 @@ defmodule ElixirScript.Mixfile do def project do [ app: :elixir_script, - version: "0.16.0", + version: "0.17.0-dev", elixir: "~> 1.0", escript: escript_config, deps: deps, From 37cfff1d7da0e10806061852ac0791646bde445f Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Wed, 9 Mar 2016 14:39:30 -0600 Subject: [PATCH 177/860] Added semicolon --- src/javascript/lib/core/protocol.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/javascript/lib/core/protocol.js b/src/javascript/lib/core/protocol.js index 79b5d7e2..34e7cb0d 100644 --- a/src/javascript/lib/core/protocol.js +++ b/src/javascript/lib/core/protocol.js @@ -32,7 +32,7 @@ class Protocol{ } throw new Error("No implementation found for " + thing); - } + }; } } From b5561c03bb2a982e0c8cfb96e45705b355f7f78d Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Sat, 12 Mar 2016 11:19:16 -0600 Subject: [PATCH 178/860] split out protocol implementations into their own modules --- lib/elixir_script.ex | 6 +- lib/elixir_script/prelude/module.ex | 2 +- lib/elixir_script/translator/protocol.ex | 194 +++--------------- .../translator/protocol/implementation.ex | 121 +++++++++++ lib/elixir_script/translator/state.ex | 16 +- 5 files changed, 166 insertions(+), 173 deletions(-) create mode 100644 lib/elixir_script/translator/protocol/implementation.ex diff --git a/lib/elixir_script.ex b/lib/elixir_script.ex index 24752039..be506ac4 100644 --- a/lib/elixir_script.ex +++ b/lib/elixir_script.ex @@ -151,9 +151,11 @@ defmodule ElixirScript do module = case ast.type do :module -> - ElixirScript.Translator.Module.make_module(ast.name, ast.body, env) + ElixirScript.Translator.Module.make_module(ast.name, ast.body, env) :protocol -> - ElixirScript.Translator.Protocol.consolidate(ast, env) + ElixirScript.Translator.Protocol.make(ast.name, ast.functions, env) + :protocol_implementation -> + ElixirScript.Translator.Protocol.Implementation.make(ast.name, ast.impl_type, ast.body, env) end { path, code } = convert_to_code(module) diff --git a/lib/elixir_script/prelude/module.ex b/lib/elixir_script/prelude/module.ex index b35564df..0af8805c 100644 --- a/lib/elixir_script/prelude/module.ex +++ b/lib/elixir_script/prelude/module.ex @@ -5,6 +5,6 @@ defmodule ElixirScript.Module do functions: Keyword.new, private_functions: Keyword.new, macros: Keyword.new, private_macros: Keyword.new, body: nil, js_imports: [], module_refs: [], type: :module, - impls: HashDict.new + impls: HashDict.new, impl_type: nil end diff --git a/lib/elixir_script/translator/protocol.ex b/lib/elixir_script/translator/protocol.ex index 5dfefe20..63bba94a 100644 --- a/lib/elixir_script/translator/protocol.ex +++ b/lib/elixir_script/translator/protocol.ex @@ -10,26 +10,14 @@ defmodule ElixirScript.Translator.Protocol do @doc """ Takes a protocol and turns them into modules """ - def consolidate(protocol, env) do - name = protocol.name - functions = protocol.functions - impls = protocol.impls |> Dict.to_list - - {spec_imports, spec_body, spec} = define_spec(name, functions, env) - {impl_imports, impl_body, impls} = define_impls(name, impls, env) - - body = spec_body ++ impl_body - imports = Enum.uniq(spec_imports ++ impl_imports) - - create_module(name, spec, impls, imports, body, env) - end - - defp define_spec(name, functions, env) do + def make(name, functions, env) do { body, _ } = Module.translate_body( {:__block__, [], [] }, env) + module_refs = ElixirScript.Translator.State.get_module_references(name) + {imports, body} = Module.extract_imports_from_body(body) - imports = imports ++ Module.make_std_lib_import() ++ Module.make_imports(module_refs) + imports = imports ++ Module.make_std_lib_import() ++ Module.make_imports(module_refs) ++ [ElixirScript.ModuleSystems.import_module("Implementation", Utils.make_local_file_path(Utils.name_to_js_file_name(name) <> ".defimpl"))] object = process_spec_functions(functions) |> Enum.map(fn({key, value}) -> @@ -54,33 +42,15 @@ defmodule ElixirScript.Translator.Protocol do ) ) - {imports, body, [JS.variable_declaration([declarator], :const)]} - end - - defp define_impls(_, [], _) do - { [], [], [] } - end - - defp define_impls(name, impls, env) do - Enum.map(impls, fn({type, impl}) -> - type = map_to_js(type, env) - { body, functions } = Module.extract_functions_from_module(impl) - { body, env } = Module.translate_body(body, env) - - { exported_functions, _ } = process_functions(functions, env) - - module_refs = ElixirScript.Translator.State.get_module_references(name) - - {imports, body} = Module.extract_imports_from_body(body) - - imports = imports ++ Module.make_std_lib_import() ++ Module.make_imports(module_refs) - - object = Enum.map(exported_functions, fn({key, value}) -> - Map.make_property(JS.identifier(Utils.filter_name(key)), value) - end) - |> JS.object_expression + declaration = JS.variable_declaration([declarator], :const) - impl = JS.call_expression( + implementations = JS.for_of_statement( + JS.object_pattern([ + JS.assignment_property(JS.identifier("Type")), + JS.assignment_property(JS.identifier("Implementation")) + ]), + JS.identifier("Implementations"), + JS.call_expression( JS.member_expression( JS.identifier(:Elixir), JS.member_expression( @@ -91,27 +61,21 @@ defmodule ElixirScript.Translator.Protocol do ) ) ), - [JS.identifier(Utils.name_to_js_name(name)), type, object] + [ + JS.identifier(Utils.name_to_js_name(name)), + JS.identifier("Type"), + JS.identifier("Implementation") + ] ) + ) - {imports, body, [impl]} - - end) - |> Enum.reduce({[], [], []}, fn({impl_imports, impl_body, impl}, acc) -> - { - elem(acc, 0) ++ impl_imports, - elem(acc, 1) ++ impl_body, - elem(acc, 2) ++ impl - } - end) - end - - defp create_module(name, spec, impls, imports, body, _) do default = JS.export_default_declaration(JS.identifier(Utils.name_to_js_name(name))) + IO.inspect(imports) + %{ name: name, - body: imports ++ body ++ spec ++ impls ++ [default] + body: imports ++ body ++ [declaration] ++ [implementations] ++ [default] } end @@ -121,115 +85,23 @@ defmodule ElixirScript.Translator.Protocol do end) end - defp process_functions(%{ exported: exported, private: private }, env) do - exported_functions = Enum.map(Dict.keys(exported), fn(key) -> - functions = Dict.get(exported, key) - - { functions, _ } = Function.make_anonymous_function(functions, env) - - { key, functions } - end) - - private_functions = Enum.map(Dict.keys(private), fn(key) -> - functions = Dict.get(private, key) - { functions, _ } = Function.make_anonymous_function(functions, env) - - { key, functions } - end) - - { exported_functions, private_functions } - end - - defp map_to_js({:__aliases__, _, [:Integer]}, _) do - JS.member_expression( - JS.member_expression( - JS.identifier(:Elixir), - JS.identifier(:Core) - ), - JS.identifier(:Integer) - ) - end - - defp map_to_js({:__aliases__, _, [:Tuple]}, _) do - JS.member_expression( - JS.member_expression( - JS.identifier(:Elixir), - JS.identifier(:Core) - ), - JS.identifier(:Tuple) - ) - end - - defp map_to_js({:__aliases__, _, [:Atom]}, _) do - JS.identifier(:Symbol) - end - - defp map_to_js({:__aliases__, _, [:List]}, _) do - JS.identifier(:Array) - end - - defp map_to_js({:__aliases__, _, [:BitString]}, _) do - JS.member_expression( - JS.member_expression( - JS.identifier(:Elixir), - JS.identifier(:Core) - ), - JS.identifier(:BitString) - ) - end - - defp map_to_js({:__aliases__, _, [:Float]}, _) do - JS.member_expression( - JS.member_expression( - JS.identifier(:Elixir), - JS.identifier(:Core) - ), - JS.identifier(:Float) - ) - end - - defp map_to_js({:__aliases__, _, [:Function]}, _) do - JS.identifier(:Function) - end - - defp map_to_js({:__aliases__, _, [:PID]}, _) do - JS.member_expression( - JS.member_expression( - JS.identifier(:Elixir), - JS.identifier(:Core) - ), - JS.identifier(:PID) - ) - end - - defp map_to_js({:__aliases__, _, [:Port]}, _) do - JS.member_expression( - JS.identifier(:Elixir), - JS.identifier(:Port) - ) - end + def make_defimpl(name) do + imports = Module.make_std_lib_import() - defp map_to_js({:__aliases__, _, [:Reference]}, _) do - JS.member_expression( - JS.identifier(:Elixir), - JS.identifier(:Reference) + declarator = JS.variable_declarator( + JS.identifier("impls"), + JS.array_expression([]) ) - end - defp map_to_js({:__aliases__, _, [:Map]}, _) do - JS.identifier(:Object) - end + declaration = JS.variable_declaration([declarator], :let) - defp map_to_js({:__aliases__, _, [:Any]}, _) do - JS.identifier(:null) - end + default = JS.export_default_declaration(JS.identifier("impls")) + "Elixir." <> protocol_name = Atom.to_string(name) - defp map_to_js({:__aliases__, _, _} = module, env) do - ElixirScript.Translator.Struct.get_struct_class( - module, - env - ) + %{ + name: String.to_atom(protocol_name <> ".defimpl"), + body: imports ++ declaration ++ [default] + } end - end diff --git a/lib/elixir_script/translator/protocol/implementation.ex b/lib/elixir_script/translator/protocol/implementation.ex new file mode 100644 index 00000000..96fddb5a --- /dev/null +++ b/lib/elixir_script/translator/protocol/implementation.ex @@ -0,0 +1,121 @@ +defmodule ElixirScript.Translator.Protocol.Implementation do + alias ESTree.Tools.Builder, as: JS + alias ElixirScript.Translator.Module + + def make(name, type, body, env) do + + type = map_to_js(type, env) + module = Module.make_module(name, body, env) + + %ESTree.ExportDefaultDeclaration{ declaration: export } = List.last(module.body) + export = JS.object_expression([ + JS.property( + JS.literal("Type"), + type + ), + JS.property( + JS.literal("Implementation"), + export + ) + ]) + + body = Enum.reverse(module.body) + |> tl + |> Enum.reverse + + %{ module | body: body ++ [JS.export_default_declaration(export)] } + end + + defp map_to_js({:__aliases__, _, [:Integer]}, _) do + JS.member_expression( + JS.member_expression( + JS.identifier(:Elixir), + JS.identifier(:Core) + ), + JS.identifier(:Integer) + ) + end + + defp map_to_js({:__aliases__, _, [:Tuple]}, _) do + JS.member_expression( + JS.member_expression( + JS.identifier(:Elixir), + JS.identifier(:Core) + ), + JS.identifier(:Tuple) + ) + end + + defp map_to_js({:__aliases__, _, [:Atom]}, _) do + JS.identifier(:Symbol) + end + + defp map_to_js({:__aliases__, _, [:List]}, _) do + JS.identifier(:Array) + end + + defp map_to_js({:__aliases__, _, [:BitString]}, _) do + JS.member_expression( + JS.member_expression( + JS.identifier(:Elixir), + JS.identifier(:Core) + ), + JS.identifier(:BitString) + ) + end + + defp map_to_js({:__aliases__, _, [:Float]}, _) do + JS.member_expression( + JS.member_expression( + JS.identifier(:Elixir), + JS.identifier(:Core) + ), + JS.identifier(:Float) + ) + end + + defp map_to_js({:__aliases__, _, [:Function]}, _) do + JS.identifier(:Function) + end + + defp map_to_js({:__aliases__, _, [:PID]}, _) do + JS.member_expression( + JS.member_expression( + JS.identifier(:Elixir), + JS.identifier(:Core) + ), + JS.identifier(:PID) + ) + end + + defp map_to_js({:__aliases__, _, [:Port]}, _) do + JS.member_expression( + JS.identifier(:Elixir), + JS.identifier(:Port) + ) + end + + defp map_to_js({:__aliases__, _, [:Reference]}, _) do + JS.member_expression( + JS.identifier(:Elixir), + JS.identifier(:Reference) + ) + end + + defp map_to_js({:__aliases__, _, [:Map]}, _) do + JS.identifier(:Object) + end + + defp map_to_js({:__aliases__, _, [:Any]}, _) do + JS.identifier(:null) + end + + + defp map_to_js({:__aliases__, _, _} = module, env) do + ElixirScript.Translator.Struct.get_struct_class( + module, + env + ) + end + +end diff --git a/lib/elixir_script/translator/state.ex b/lib/elixir_script/translator/state.ex index ccd4a635..5a991f36 100644 --- a/lib/elixir_script/translator/state.ex +++ b/lib/elixir_script/translator/state.ex @@ -58,9 +58,9 @@ defmodule ElixirScript.Translator.State do proto = Map.get(state.modules, do_get_module_name(name, state)) if proto == nil do - proto = %ElixirScript.Module{ name: name, functions: functions, impls: HashDict.new, type: :protocol } + proto = %ElixirScript.Module{ name: name, functions: functions, type: :protocol } else - proto = %{proto | functions: functions, type: :protocol } + proto = %ElixirScript.Module{proto | functions: functions, type: :protocol } end %{ state | modules: Map.put(state.modules, name, proto) } @@ -75,15 +75,13 @@ defmodule ElixirScript.Translator.State do def add_protocol_impl(protocol, type, impl) do Agent.update(__MODULE__, fn state -> - proto = Map.get(state.modules, do_get_module_name(protocol, state)) + "Elixir." <> protocol_name = Atom.to_string(protocol) + "Elixir." <> type_name = Atom.to_string(Utils.quoted_to_name(type)) + module_name = String.to_atom(protocol_name <> "." <> type_name) - if proto == nil do - proto = %ElixirScript.Module{ name: protocol, impls: HashDict.new, type: :protocol } - end - - proto = %{ proto | impls: Dict.put(proto.impls, type, impl), type: :protocol } + proto_impl = %ElixirScript.Module{ name: module_name, body: impl, impl_type: type, type: :protocol_implementation } - %{ state | modules: Map.put(state.modules, protocol, proto) } + %{ state | modules: Map.put(state.modules, module_name, proto_impl) } end) end From 96cc773f1f7a3e21adde4fcacf12172ad314ea04 Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Sun, 13 Mar 2016 09:10:55 -0500 Subject: [PATCH 179/860] Output of protocols functioning --- lib/elixir_script.ex | 52 +++++++++++++++++------- lib/elixir_script/translator/protocol.ex | 27 +++++++++--- lib/elixir_script/translator/state.ex | 2 +- 3 files changed, 59 insertions(+), 22 deletions(-) diff --git a/lib/elixir_script.ex b/lib/elixir_script.ex index be506ac4..04ed3908 100644 --- a/lib/elixir_script.ex +++ b/lib/elixir_script.ex @@ -138,12 +138,20 @@ defmodule ElixirScript do state = ElixirScript.Translator.State.get - standard_lib_modules = Map.values(state.std_lib_map) + standard_lib_modules = Map.values(state.std_lib_map) |> Enum.map(&to_string(&1)) |> Enum.map(&String.replace(&1, "Elixir.", "")) result = Map.values(state.modules) - |> Enum.reject(fn(ast) -> - compiler_opts.import_standard_libs == false && ast.name in standard_lib_modules + |> Enum.reject(fn(ast) -> + name = Atom.to_string(ast.name) |> String.replace("Elixir.", "") + cond do + compiler_opts.import_standard_libs == false and name in standard_lib_modules -> + true + compiler_opts.import_standard_libs == false and ast.type == :protocol_implementation and String.starts_with?(name, standard_lib_modules) -> + true + true -> + false + end end) |> Enum.map(fn ast -> spawn_link fn -> @@ -153,24 +161,38 @@ defmodule ElixirScript do :module -> ElixirScript.Translator.Module.make_module(ast.name, ast.body, env) :protocol -> - ElixirScript.Translator.Protocol.make(ast.name, ast.functions, env) + protocol = ElixirScript.Translator.Protocol.make(ast.name, ast.functions, env) + protocol_defimpl = ElixirScript.Translator.Protocol.make_defimpl(ast.name) + [protocol, protocol_defimpl] :protocol_implementation -> ElixirScript.Translator.Protocol.Implementation.make(ast.name, ast.impl_type, ast.body, env) - end - - { path, code } = convert_to_code(module) - - result = case compiler_opts.include_path do - true -> - { path, code } - false -> - code - end + end + + + result = case module do + [protocol, protocol_defimpl] -> + protocol_result = convert_to_code(protocol) + protocol_defimpl_result = convert_to_code(protocol_defimpl) + [protocol_result, protocol_defimpl_result] + _ -> + result = convert_to_code(module) + [result] + end + + result = Enum.map(result, fn + { path, code } -> + case compiler_opts.include_path do + true -> + { path, code } + false -> + code + end + end) send parent, { self, result } end end) - |> Enum.map(fn pid -> + |> Enum.flat_map(fn pid -> receive do {^pid, result} -> result end diff --git a/lib/elixir_script/translator/protocol.ex b/lib/elixir_script/translator/protocol.ex index 63bba94a..c4ff3159 100644 --- a/lib/elixir_script/translator/protocol.ex +++ b/lib/elixir_script/translator/protocol.ex @@ -6,6 +6,7 @@ defmodule ElixirScript.Translator.Protocol do alias ElixirScript.Translator.Map alias ElixirScript.Translator.Function alias ElixirScript.Translator.Utils + alias ElixirScript.ModuleSystems @doc """ Takes a protocol and turns them into modules @@ -17,7 +18,9 @@ defmodule ElixirScript.Translator.Protocol do {imports, body} = Module.extract_imports_from_body(body) - imports = imports ++ Module.make_std_lib_import() ++ Module.make_imports(module_refs) ++ [ElixirScript.ModuleSystems.import_module("Implementation", Utils.make_local_file_path(Utils.name_to_js_file_name(name) <> ".defimpl"))] + imports = imports ++ Module.make_std_lib_import() ++ + Module.make_imports(module_refs) ++ + [ElixirScript.ModuleSystems.import_module("Implementations", Utils.make_local_file_path(Utils.name_to_js_file_name(name) <> ".Defimpl"))] object = process_spec_functions(functions) |> Enum.map(fn({key, value}) -> @@ -71,8 +74,6 @@ defmodule ElixirScript.Translator.Protocol do default = JS.export_default_declaration(JS.identifier(Utils.name_to_js_name(name))) - IO.inspect(imports) - %{ name: name, body: imports ++ body ++ [declaration] ++ [implementations] ++ [default] @@ -85,7 +86,7 @@ defmodule ElixirScript.Translator.Protocol do end) end - def make_defimpl(name) do + def make_defimpl(name, implementations \\ []) do imports = Module.make_std_lib_import() declarator = JS.variable_declarator( @@ -97,11 +98,25 @@ defmodule ElixirScript.Translator.Protocol do default = JS.export_default_declaration(JS.identifier("impls")) + body = Enum.flat_map(implementations, fn(x) -> + name = Utils.name_to_js_name(x) + imports = ModuleSystems.import_module(name, Utils.make_local_file_path(Utils.name_to_js_file_name(x))) + call = JS.call_expression( + JS.member_expression( + JS.identifier("impls"), + JS.identifier("push") + ), + [JS.identifier(name)] + ) + + [imports, call] + end) + "Elixir." <> protocol_name = Atom.to_string(name) %{ - name: String.to_atom(protocol_name <> ".defimpl"), - body: imports ++ declaration ++ [default] + name: String.to_atom(protocol_name <> ".Defimpl"), + body: imports ++ [declaration] ++ body ++ [default] } end end diff --git a/lib/elixir_script/translator/state.ex b/lib/elixir_script/translator/state.ex index 5a991f36..7af6d115 100644 --- a/lib/elixir_script/translator/state.ex +++ b/lib/elixir_script/translator/state.ex @@ -77,7 +77,7 @@ defmodule ElixirScript.Translator.State do Agent.update(__MODULE__, fn state -> "Elixir." <> protocol_name = Atom.to_string(protocol) "Elixir." <> type_name = Atom.to_string(Utils.quoted_to_name(type)) - module_name = String.to_atom(protocol_name <> "." <> type_name) + module_name = String.to_atom(protocol_name <> ".DefImpl." <> type_name) proto_impl = %ElixirScript.Module{ name: module_name, body: impl, impl_type: type, type: :protocol_implementation } From a2fad90e38e3c63ed90c1d62ff8f2d2c4d423559 Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Sun, 13 Mar 2016 11:46:40 -0500 Subject: [PATCH 180/860] Populating protocol DefImpl modules --- lib/elixir_script.ex | 61 +++++++++++-------- lib/elixir_script/translator/protocol.ex | 4 +- .../translator/protocol/implementation.ex | 3 + lib/elixir_script/translator/state.ex | 4 +- 4 files changed, 42 insertions(+), 30 deletions(-) diff --git a/lib/elixir_script.ex b/lib/elixir_script.ex index 04ed3908..6c19d2ae 100644 --- a/lib/elixir_script.ex +++ b/lib/elixir_script.ex @@ -161,41 +161,50 @@ defmodule ElixirScript do :module -> ElixirScript.Translator.Module.make_module(ast.name, ast.body, env) :protocol -> - protocol = ElixirScript.Translator.Protocol.make(ast.name, ast.functions, env) - protocol_defimpl = ElixirScript.Translator.Protocol.make_defimpl(ast.name) - [protocol, protocol_defimpl] + ElixirScript.Translator.Protocol.make(ast.name, ast.functions, env) :protocol_implementation -> ElixirScript.Translator.Protocol.Implementation.make(ast.name, ast.impl_type, ast.body, env) end - result = case module do - [protocol, protocol_defimpl] -> - protocol_result = convert_to_code(protocol) - protocol_defimpl_result = convert_to_code(protocol_defimpl) - [protocol_result, protocol_defimpl_result] - _ -> - result = convert_to_code(module) - [result] - end - - result = Enum.map(result, fn - { path, code } -> - case compiler_opts.include_path do - true -> - { path, code } - false -> - code - end - end) + result = convert_to_code(module) send parent, { self, result } end end) - |> Enum.flat_map(fn pid -> + |> Enum.map(fn pid -> receive do {^pid, result} -> result end + end) + + { result, protocols } = Enum.map_reduce(result, %{}, fn + { path, code, nil, _ }, protocols -> + {{ path, code}, protocols } + { path, code, protocol, name }, protocols -> + {{ path, code}, Map.put(protocols, protocol, Map.get(protocols, protocol, []) ++ [name]) } + end) + + defimpls = Enum.map(protocols, fn({protocol, implementations}) -> + ElixirScript.Translator.Protocol.make_defimpl(protocol, implementations) + end) + |> Enum.map(fn(module) -> + { path, code, _, _ } = convert_to_code(module) + {path, code} + end) + + result = result ++ defimpls + + IO.inspect(result) + + result = Enum.map(result, fn + { path, code } -> + case compiler_opts.include_path do + true -> + { path, code } + false -> + code + end end) result @@ -224,15 +233,15 @@ defmodule ElixirScript do defp process_module(module) do file_path = Utils.name_to_js_file_name(module.name) <> ".js" - { file_path, Builder.program(module.body) } + { file_path, Builder.program(module.body), Map.get(module, :protocol), Map.get(module, :name) } end - defp javascript_ast_to_code({path, js_ast}) do + defp javascript_ast_to_code({path, js_ast, protocol, name}) do js_code = js_ast |> prepare_js_ast |> Generator.generate - {path, js_code} + {path, js_code, protocol, name} end defp prepare_js_ast(js_ast) do diff --git a/lib/elixir_script/translator/protocol.ex b/lib/elixir_script/translator/protocol.ex index c4ff3159..1d3c4ea3 100644 --- a/lib/elixir_script/translator/protocol.ex +++ b/lib/elixir_script/translator/protocol.ex @@ -112,10 +112,10 @@ defmodule ElixirScript.Translator.Protocol do [imports, call] end) - "Elixir." <> protocol_name = Atom.to_string(name) + protocol_name = Atom.to_string(name) %{ - name: String.to_atom(protocol_name <> ".Defimpl"), + name: String.to_atom(protocol_name <> ".DefImpl"), body: imports ++ [declaration] ++ body ++ [default] } end diff --git a/lib/elixir_script/translator/protocol/implementation.ex b/lib/elixir_script/translator/protocol/implementation.ex index 96fddb5a..52fc3b3d 100644 --- a/lib/elixir_script/translator/protocol/implementation.ex +++ b/lib/elixir_script/translator/protocol/implementation.ex @@ -7,6 +7,8 @@ defmodule ElixirScript.Translator.Protocol.Implementation do type = map_to_js(type, env) module = Module.make_module(name, body, env) + protocol_name = Atom.to_string(name) |> String.split(".DefImpl.") |> hd |> String.to_atom + %ESTree.ExportDefaultDeclaration{ declaration: export } = List.last(module.body) export = JS.object_expression([ JS.property( @@ -24,6 +26,7 @@ defmodule ElixirScript.Translator.Protocol.Implementation do |> Enum.reverse %{ module | body: body ++ [JS.export_default_declaration(export)] } + |> Map.put(:protocol, protocol_name) end defp map_to_js({:__aliases__, _, [:Integer]}, _) do diff --git a/lib/elixir_script/translator/state.ex b/lib/elixir_script/translator/state.ex index 7af6d115..0b42e56a 100644 --- a/lib/elixir_script/translator/state.ex +++ b/lib/elixir_script/translator/state.ex @@ -75,8 +75,8 @@ defmodule ElixirScript.Translator.State do def add_protocol_impl(protocol, type, impl) do Agent.update(__MODULE__, fn state -> - "Elixir." <> protocol_name = Atom.to_string(protocol) - "Elixir." <> type_name = Atom.to_string(Utils.quoted_to_name(type)) + protocol_name = Atom.to_string(protocol) + type_name = Atom.to_string(Utils.quoted_to_name(type)) module_name = String.to_atom(protocol_name <> ".DefImpl." <> type_name) proto_impl = %ElixirScript.Module{ name: module_name, body: impl, impl_type: type, type: :protocol_implementation } From 38009cfe2f5cd63efdcda8bab001b719b288258a Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Sun, 13 Mar 2016 14:26:10 -0500 Subject: [PATCH 181/860] Fixed protocol errors found when testing --- lib/elixir_script.ex | 2 - lib/elixir_script/translator/protocol.ex | 17 ++++-- lib/elixir_script/translator/state.ex | 2 +- priv/Elixir.js | 2 +- test/translator/protocol_test.exs | 66 +++++++++++++++++------- 5 files changed, 62 insertions(+), 27 deletions(-) diff --git a/lib/elixir_script.ex b/lib/elixir_script.ex index 6c19d2ae..2ba9e30c 100644 --- a/lib/elixir_script.ex +++ b/lib/elixir_script.ex @@ -195,8 +195,6 @@ defmodule ElixirScript do result = result ++ defimpls - IO.inspect(result) - result = Enum.map(result, fn { path, code } -> case compiler_opts.include_path do diff --git a/lib/elixir_script/translator/protocol.ex b/lib/elixir_script/translator/protocol.ex index 1d3c4ea3..0aa0b580 100644 --- a/lib/elixir_script/translator/protocol.ex +++ b/lib/elixir_script/translator/protocol.ex @@ -9,7 +9,7 @@ defmodule ElixirScript.Translator.Protocol do alias ElixirScript.ModuleSystems @doc """ - Takes a protocol and turns them into modules + Takes a protocol and turns it into a module """ def make(name, functions, env) do { body, _ } = Module.translate_body( {:__block__, [], [] }, env) @@ -48,10 +48,13 @@ defmodule ElixirScript.Translator.Protocol do declaration = JS.variable_declaration([declarator], :const) implementations = JS.for_of_statement( - JS.object_pattern([ - JS.assignment_property(JS.identifier("Type")), - JS.assignment_property(JS.identifier("Implementation")) - ]), + JS.variable_declaration([JS.variable_declarator( + JS.object_pattern([ + JS.assignment_property(JS.identifier("Type")), + JS.assignment_property(JS.identifier("Implementation")) + ]), + nil + )], :let), JS.identifier("Implementations"), JS.call_expression( JS.member_expression( @@ -86,6 +89,10 @@ defmodule ElixirScript.Translator.Protocol do end) end + @doc """ + Makes the protocol implementation module for the given implementation name. + This is used to consolidate all of the protocol implementations. + """ def make_defimpl(name, implementations \\ []) do imports = Module.make_std_lib_import() diff --git a/lib/elixir_script/translator/state.ex b/lib/elixir_script/translator/state.ex index 0b42e56a..4ef9bfb9 100644 --- a/lib/elixir_script/translator/state.ex +++ b/lib/elixir_script/translator/state.ex @@ -75,7 +75,7 @@ defmodule ElixirScript.Translator.State do def add_protocol_impl(protocol, type, impl) do Agent.update(__MODULE__, fn state -> - protocol_name = Atom.to_string(protocol) + protocol_name = Atom.to_string(do_get_module_name(protocol, state)) type_name = Atom.to_string(Utils.quoted_to_name(type)) module_name = String.to_atom(protocol_name <> ".DefImpl." <> type_name) diff --git a/priv/Elixir.js b/priv/Elixir.js index 2eebc37c..081c30b9 100644 --- a/priv/Elixir.js +++ b/priv/Elixir.js @@ -3720,4 +3720,4 @@ var elixir = { }; export default elixir; -//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiRWxpeGlyLmpzIiwic291cmNlcyI6WyIuLi9zcmMvZWxpeGlyc2NyaXB0L2xpYi9jb3JlL3Byb2Nlc3Nlcy9tYWlsYm94LmpzIiwiLi4vc3JjL2VsaXhpcnNjcmlwdC9saWIvY29yZS9wcm9jZXNzZXMvc3RhdGVzLmpzIiwiLi4vc3JjL2VsaXhpcnNjcmlwdC9saWIvY29yZS9wcm9jZXNzZXMvcHJvY2Vzcy5qcyIsIi4uL3NyYy9lbGl4aXJzY3JpcHQvbGliL2NvcmUvcHJpbWl0aXZlcy5qcyIsIi4uL3NyYy9lbGl4aXJzY3JpcHQvbGliL2NvcmUvcHJvY2Vzc2VzL3Byb2Nlc3Nfc3lzdGVtLmpzIiwiLi4vc3JjL2VsaXhpcnNjcmlwdC9saWIvY29yZS9iaXRfc3RyaW5nLmpzIiwiLi4vc3JjL2VsaXhpcnNjcmlwdC9saWIvY29yZS9wYXR0ZXJucy90eXBlcy5qcyIsIi4uL3NyYy9lbGl4aXJzY3JpcHQvbGliL2NvcmUvcGF0dGVybnMvY2hlY2tzLmpzIiwiLi4vc3JjL2VsaXhpcnNjcmlwdC9saWIvY29yZS9wYXR0ZXJucy9yZXNvbHZlcnMuanMiLCIuLi9zcmMvZWxpeGlyc2NyaXB0L2xpYi9jb3JlL3BhdHRlcm5zL21hdGNoLmpzIiwiLi4vc3JjL2VsaXhpcnNjcmlwdC9saWIvY29yZS9wYXR0ZXJucy9kZWZtYXRjaC5qcyIsIi4uL3NyYy9lbGl4aXJzY3JpcHQvbGliL2NvcmUvcGF0dGVybnMuanMiLCIuLi9zcmMvZWxpeGlyc2NyaXB0L2xpYi9jb3JlL3Byb3RvY29sLmpzIiwiLi4vc3JjL2VsaXhpcnNjcmlwdC9saWIvY29yZS9mdW5jdGlvbnMuanMiLCIuLi9zcmMvZWxpeGlyc2NyaXB0L2xpYi9jb3JlL3NwZWNpYWxfZm9ybXMuanMiLCIuLi9zcmMvZWxpeGlyc2NyaXB0L2xpYi9jb3JlLmpzIiwiLi4vc3JjL2VsaXhpcnNjcmlwdC9saWIvZW51bS5qcyIsIi4uL3NyYy9lbGl4aXJzY3JpcHQvbGliL3ZpcnR1YWwtZG9tLmpzIiwiLi4vc3JjL2VsaXhpcnNjcmlwdC9lbGl4aXIuanMiXSwic291cmNlc0NvbnRlbnQiOlsiXCJ1c2Ugc3RyaWN0XCI7XG5cbmNsYXNzIE1haWxib3gge1xuXG4gIGNvbnN0cnVjdG9yKCkge1xuICAgIHRoaXMubWVzc2FnZXMgPSBbXTtcbiAgfVxuXG4gIGRlbGl2ZXIobWVzc2FnZSkge1xuICAgIHRoaXMubWVzc2FnZXMucHVzaChtZXNzYWdlKTtcbiAgICByZXR1cm4gbWVzc2FnZTtcbiAgfVxuXG4gIGdldCgpIHtcbiAgICByZXR1cm4gdGhpcy5tZXNzYWdlcztcbiAgfVxuXG4gIGlzRW1wdHkoKSB7XG4gICAgcmV0dXJuIHRoaXMubWVzc2FnZXMubGVuZ3RoID09PSAwO1xuICB9XG5cbiAgcmVtb3ZlQXQoaW5kZXgpIHtcbiAgICB0aGlzLm1lc3NhZ2VzLnNwbGljZShpbmRleCwgMSk7XG4gIH1cbn1cblxuZXhwb3J0IGRlZmF1bHQgTWFpbGJveDtcbi8vIyBzb3VyY2VNYXBwaW5nVVJMPWRhdGE6YXBwbGljYXRpb24vanNvbjtiYXNlNjQsZXlKMlpYSnphVzl1SWpvekxDSnpiM1Z5WTJWeklqcGJJbXhwWWk5amIzSmxMM0J5YjJObGMzTmxjeTl0WVdsc1ltOTRMbXB6SWwwc0ltNWhiV1Z6SWpwYlhTd2liV0Z3Y0dsdVozTWlPaUpCUVVGQk96dEJRVWxCTEUxQlFVMHNUMEZCVGl4RFFVRmhPenRCUVVkWUxHZENRVUZoTzBGQlExZ3NVMEZCU3l4UlFVRk1MRWRCUVdkQ0xFVkJRV2hDTEVOQlJGYzdSMEZCWWpzN1FVRkpRU3hWUVVGUkxFOUJRVklzUlVGQmNVSTdRVUZEYmtJc1UwRkJTeXhSUVVGTUxFTkJRV01zU1VGQlpDeERRVUZ0UWl4UFFVRnVRaXhGUVVSdFFqdEJRVVZ1UWl4WFFVRlBMRTlCUVZBc1EwRkdiVUk3UjBGQmNrSTdPMEZCUzBFc1VVRkJTenRCUVVOSUxGZEJRVThzUzBGQlN5eFJRVUZNTEVOQlJFbzdSMEZCVERzN1FVRkpRU3haUVVGVE8wRkJRMUFzVjBGQlR5eExRVUZMTEZGQlFVd3NRMEZCWXl4TlFVRmtMRXRCUVhsQ0xFTkJRWHBDTEVOQlJFRTdSMEZCVkRzN1FVRkpRU3hYUVVGVExFdEJRVlFzUlVGQlpUdEJRVU5pTEZOQlFVc3NVVUZCVEN4RFFVRmpMRTFCUVdRc1EwRkJjVUlzUzBGQmNrSXNSVUZCTkVJc1EwRkJOVUlzUlVGRVlUdEhRVUZtTzBOQmNFSkdPenRCUVhsQ1FTeGxRVUZsTEU5QlFXWWlMQ0ptYVd4bElqb2liR2xpTDJOdmNtVXZjSEp2WTJWemMyVnpMMjFoYVd4aWIzZ3Vhbk1pTENKemIzVnlZMlZ6UTI5dWRHVnVkQ0k2V3lKY0luVnpaU0J6ZEhKcFkzUmNJanRjYmx4dUx5b2dRR1pzYjNjZ0tpOWNibHh1WTJ4aGMzTWdUV0ZwYkdKdmVIdGNiaUFnYldWemMyRm5aWE02SUVGeWNtRjVQR0Z1ZVQ1Y2JseHVJQ0JqYjI1emRISjFZM1J2Y2lncGUxeHVJQ0FnSUhSb2FYTXViV1Z6YzJGblpYTWdQU0JiWFR0Y2JpQWdmVnh1WEc0Z0lHUmxiR2wyWlhJb2JXVnpjMkZuWlRvZ1lXNTVLWHRjYmlBZ0lDQjBhR2x6TG0xbGMzTmhaMlZ6TG5CMWMyZ29iV1Z6YzJGblpTazdYRzRnSUNBZ2NtVjBkWEp1SUcxbGMzTmhaMlU3WEc0Z0lIMWNibHh1SUNCblpYUW9LWHRjYmlBZ0lDQnlaWFIxY200Z2RHaHBjeTV0WlhOellXZGxjenRjYmlBZ2ZWeHVYRzRnSUdselJXMXdkSGtvS1h0Y2JpQWdJQ0J5WlhSMWNtNGdkR2hwY3k1dFpYTnpZV2RsY3k1c1pXNW5kR2dnUFQwOUlEQTdYRzRnSUgxY2JseHVJQ0J5WlcxdmRtVkJkQ2hwYm1SbGVDbDdYRzRnSUNBZ2RHaHBjeTV0WlhOellXZGxjeTV6Y0d4cFkyVW9hVzVrWlhnc0lERXBPMXh1SUNCOVhHNTlYRzVjYm1WNGNHOXlkQ0JrWldaaGRXeDBJRTFoYVd4aWIzZzdJbDBzSW5OdmRYSmpaVkp2YjNRaU9pSXZjMjkxY21ObEx5SjlcbiIsImV4cG9ydCBkZWZhdWx0IHtcbiAgTk9STUFMOiBTeW1ib2wuZm9yKFwibm9ybWFsXCIpLFxuICBLSUxMOiBTeW1ib2wuZm9yKFwia2lsbFwiKSxcbiAgU1VTUEVORDogU3ltYm9sLmZvcihcInN1c3BlbmRcIiksXG4gIENPTlRJTlVFOiBTeW1ib2wuZm9yKFwiY29udGludWVcIiksXG4gIFJFQ0VJVkU6IFN5bWJvbC5mb3IoXCJyZWNlaXZlXCIpLFxuICBTRU5EOiBTeW1ib2wuZm9yKFwic2VuZFwiKSxcbiAgU0xFRVBJTkc6IFN5bWJvbC5mb3IoXCJzbGVlcGluZ1wiKSxcbiAgUlVOTklORzogU3ltYm9sLmZvcihcInJ1bm5pbmdcIiksXG4gIFNVU1BFTkRFRDogU3ltYm9sLmZvcihcInN1c3BlbmRlZFwiKSxcbiAgU1RPUFBFRDogU3ltYm9sLmZvcihcInN0b3BwZWRcIiksXG4gIFNMRUVQOiBTeW1ib2wuZm9yKFwic2xlZXBcIiksXG4gIEVYSVQ6IFN5bWJvbC5mb3IoXCJleGl0XCIpLFxuICBOT01BVENIOiBTeW1ib2wuZm9yKFwibm9fbWF0Y2hcIilcbn07XG4vLyMgc291cmNlTWFwcGluZ1VSTD1kYXRhOmFwcGxpY2F0aW9uL2pzb247YmFzZTY0LGV5SjJaWEp6YVc5dUlqb3pMQ0p6YjNWeVkyVnpJanBiSW14cFlpOWpiM0psTDNCeWIyTmxjM05sY3k5emRHRjBaWE11YW5NaVhTd2libUZ0WlhNaU9sdGRMQ0p0WVhCd2FXNW5jeUk2SWtGQlFVRXNaVUZCWlR0QlFVTmlMRlZCUVZFc1QwRkJUeXhIUVVGUUxFTkJRVmNzVVVGQldDeERRVUZTTzBGQlEwRXNVVUZCVFN4UFFVRlBMRWRCUVZBc1EwRkJWeXhOUVVGWUxFTkJRVTQ3UVVGRFFTeFhRVUZUTEU5QlFVOHNSMEZCVUN4RFFVRlhMRk5CUVZnc1EwRkJWRHRCUVVOQkxGbEJRVlVzVDBGQlR5eEhRVUZRTEVOQlFWY3NWVUZCV0N4RFFVRldPMEZCUTBFc1YwRkJVeXhQUVVGUExFZEJRVkFzUTBGQlZ5eFRRVUZZTEVOQlFWUTdRVUZEUVN4UlFVRk5MRTlCUVU4c1IwRkJVQ3hEUVVGWExFMUJRVmdzUTBGQlRqdEJRVU5CTEZsQlFWVXNUMEZCVHl4SFFVRlFMRU5CUVZjc1ZVRkJXQ3hEUVVGV08wRkJRMEVzVjBGQlV5eFBRVUZQTEVkQlFWQXNRMEZCVnl4VFFVRllMRU5CUVZRN1FVRkRRU3hoUVVGWExFOUJRVThzUjBGQlVDeERRVUZYTEZkQlFWZ3NRMEZCV0R0QlFVTkJMRmRCUVZNc1QwRkJUeXhIUVVGUUxFTkJRVmNzVTBGQldDeERRVUZVTzBGQlEwRXNVMEZCVHl4UFFVRlBMRWRCUVZBc1EwRkJWeXhQUVVGWUxFTkJRVkE3UVVGRFFTeFJRVUZOTEU5QlFVOHNSMEZCVUN4RFFVRlhMRTFCUVZnc1EwRkJUanRCUVVOQkxGZEJRVk1zVDBGQlR5eEhRVUZRTEVOQlFWY3NWVUZCV0N4RFFVRlVPME5CWWtZaUxDSm1hV3hsSWpvaWJHbGlMMk52Y21VdmNISnZZMlZ6YzJWekwzTjBZWFJsY3k1cWN5SXNJbk52ZFhKalpYTkRiMjUwWlc1MElqcGJJbVY0Y0c5eWRDQmtaV1poZFd4MElIdGNiaUFnVGs5U1RVRk1PaUJUZVcxaWIyd3VabTl5S0Z3aWJtOXliV0ZzWENJcExGeHVJQ0JMU1V4TU9pQlRlVzFpYjJ3dVptOXlLRndpYTJsc2JGd2lLU3hjYmlBZ1UxVlRVRVZPUkRvZ1UzbHRZbTlzTG1admNpaGNJbk4xYzNCbGJtUmNJaWtzWEc0Z0lFTlBUbFJKVGxWRk9pQlRlVzFpYjJ3dVptOXlLRndpWTI5dWRHbHVkV1ZjSWlrc1hHNGdJRkpGUTBWSlZrVTZJRk41YldKdmJDNW1iM0lvWENKeVpXTmxhWFpsWENJcExGeHVJQ0JUUlU1RU9pQlRlVzFpYjJ3dVptOXlLRndpYzJWdVpGd2lLU3hjYmlBZ1UweEZSVkJKVGtjNklGTjViV0p2YkM1bWIzSW9YQ0p6YkdWbGNHbHVaMXdpS1N4Y2JpQWdVbFZPVGtsT1J6b2dVM2x0WW05c0xtWnZjaWhjSW5KMWJtNXBibWRjSWlrc1hHNGdJRk5WVTFCRlRrUkZSRG9nVTNsdFltOXNMbVp2Y2loY0luTjFjM0JsYm1SbFpGd2lLU3hjYmlBZ1UxUlBVRkJGUkRvZ1UzbHRZbTlzTG1admNpaGNJbk4wYjNCd1pXUmNJaWtzWEc0Z0lGTk1SVVZRT2lCVGVXMWliMnd1Wm05eUtGd2ljMnhsWlhCY0lpa3NYRzRnSUVWWVNWUTZJRk41YldKdmJDNW1iM0lvWENKbGVHbDBYQ0lwTEZ4dUlDQk9UMDFCVkVOSU9pQlRlVzFpYjJ3dVptOXlLRndpYm05ZmJXRjBZMmhjSWlsY2JuMGlYU3dpYzI5MWNtTmxVbTl2ZENJNklpOXpiM1Z5WTJVdkluMD1cbiIsIlwidXNlIHN0cmljdFwiO1xuXG5pbXBvcnQgTWFpbGJveCBmcm9tIFwiLi9tYWlsYm94XCI7XG5pbXBvcnQgU3RhdGVzIGZyb20gXCIuL3N0YXRlc1wiO1xuXG5jbGFzcyBQcm9jZXNzIHtcblxuICBjb25zdHJ1Y3RvcihwaWQsIG1haWxib3gpIHtcbiAgICB0aGlzLnBpZCA9IHBpZDtcbiAgICB0aGlzLm1haWxib3ggPSBtYWlsYm94O1xuICAgIHRoaXMuc3RhdHVzID0gU3RhdGVzLlNUT1BQRUQ7XG4gICAgdGhpcy5kaWN0ID0ge307XG4gIH1cbn1cblxuZXhwb3J0IGRlZmF1bHQgUHJvY2Vzcztcbi8vIyBzb3VyY2VNYXBwaW5nVVJMPWRhdGE6YXBwbGljYXRpb24vanNvbjtiYXNlNjQsZXlKMlpYSnphVzl1SWpvekxDSnpiM1Z5WTJWeklqcGJJbXhwWWk5amIzSmxMM0J5YjJObGMzTmxjeTl3Y205alpYTnpMbXB6SWwwc0ltNWhiV1Z6SWpwYlhTd2liV0Z3Y0dsdVozTWlPaUpCUVVGQk96dEJRVWRCTEU5QlFVOHNUMEZCVUN4TlFVRnZRaXhYUVVGd1FqdEJRVU5CTEU5QlFVOHNUVUZCVUN4TlFVRnRRaXhWUVVGdVFqczdRVUZGUVN4TlFVRk5MRTlCUVU0c1EwRkJZenM3UVVGTFdpeGpRVUZaTEVkQlFWb3NSVUZCZVVJc1QwRkJla0lzUlVGQk1FTTdRVUZEZUVNc1UwRkJTeXhIUVVGTUxFZEJRVmNzUjBGQldDeERRVVIzUXp0QlFVVjRReXhUUVVGTExFOUJRVXdzUjBGQlpTeFBRVUZtTEVOQlJuZERPMEZCUjNoRExGTkJRVXNzVFVGQlRDeEhRVUZqTEU5QlFVOHNUMEZCVUN4RFFVZ3dRanRCUVVsNFF5eFRRVUZMTEVsQlFVd3NSMEZCV1N4RlFVRmFMRU5CU25kRE8wZEJRVEZETzBOQlRFWTdPMEZCWVVFc1pVRkJaU3hQUVVGbUlpd2labWxzWlNJNklteHBZaTlqYjNKbEwzQnliMk5sYzNObGN5OXdjbTlqWlhOekxtcHpJaXdpYzI5MWNtTmxjME52Ym5SbGJuUWlPbHNpWENKMWMyVWdjM1J5YVdOMFhDSTdYRzVjYmk4cUlFQm1iRzkzSUNvdlhHNXBiWEJ2Y25RZ1RXRnBiR0p2ZUNCbWNtOXRJRndpTGk5dFlXbHNZbTk0WENJN1hHNXBiWEJ2Y25RZ1UzUmhkR1Z6SUdaeWIyMGdYQ0l1TDNOMFlYUmxjMXdpTzF4dVhHNWpiR0Z6Y3lCUWNtOWpaWE56SUh0Y2JpQWdjR2xrT2lCT2RXMWlaWEk3WEc0Z0lHMWhhV3hpYjNnNklFMWhhV3hpYjNnN1hHNGdJR1JwWTNRNklFOWlhbVZqZER0Y2JseHVJQ0JqYjI1emRISjFZM1J2Y2lod2FXUTZJRTUxYldKbGNpd2diV0ZwYkdKdmVEb2dUV0ZwYkdKdmVDbDdYRzRnSUNBZ2RHaHBjeTV3YVdRZ1BTQndhV1E3WEc0Z0lDQWdkR2hwY3k1dFlXbHNZbTk0SUQwZ2JXRnBiR0p2ZUR0Y2JpQWdJQ0IwYUdsekxuTjBZWFIxY3lBOUlGTjBZWFJsY3k1VFZFOVFVRVZFTzF4dUlDQWdJSFJvYVhNdVpHbGpkQ0E5SUh0OU8xeHVJQ0I5WEc1OVhHNWNibVY0Y0c5eWRDQmtaV1poZFd4MElGQnliMk5sYzNNN1hHNGlYU3dpYzI5MWNtTmxVbTl2ZENJNklpOXpiM1Z5WTJVdkluMD1cbiIsImNsYXNzIFR1cGxlIHtcblxuICBjb25zdHJ1Y3RvciguLi5hcmdzKSB7XG4gICAgdGhpcy52YWx1ZXMgPSBPYmplY3QuZnJlZXplKGFyZ3MpO1xuICAgIHRoaXMubGVuZ3RoID0gdGhpcy52YWx1ZXMubGVuZ3RoO1xuICB9XG5cbiAgZ2V0KGluZGV4KSB7XG4gICAgcmV0dXJuIHRoaXMudmFsdWVzW2luZGV4XTtcbiAgfVxuXG4gIGNvdW50KCkge1xuICAgIHJldHVybiB0aGlzLnZhbHVlcy5sZW5ndGg7XG4gIH1cblxuICBbU3ltYm9sLml0ZXJhdG9yXSgpIHtcbiAgICByZXR1cm4gdGhpcy52YWx1ZXNbU3ltYm9sLml0ZXJhdG9yXSgpO1xuICB9XG5cbiAgdG9TdHJpbmcoKSB7XG4gICAgdmFyIGksXG4gICAgICAgIHMgPSBcIlwiO1xuICAgIGZvciAoaSA9IDA7IGkgPCB0aGlzLnZhbHVlcy5sZW5ndGg7IGkrKykge1xuICAgICAgaWYgKHMgIT09IFwiXCIpIHtcbiAgICAgICAgcyArPSBcIiwgXCI7XG4gICAgICB9XG4gICAgICBzICs9IHRoaXMudmFsdWVzW2ldLnRvU3RyaW5nKCk7XG4gICAgfVxuXG4gICAgcmV0dXJuIFwie1wiICsgcyArIFwifVwiO1xuICB9XG5cbiAgcHV0X2VsZW0oaW5kZXgsIGVsZW0pIHtcbiAgICBpZiAoaW5kZXggPT09IHRoaXMubGVuZ3RoKSB7XG4gICAgICBsZXQgbmV3X3ZhbHVlcyA9IHRoaXMudmFsdWVzLmNvbmNhdChbZWxlbV0pO1xuICAgICAgcmV0dXJuIG5ldyBUdXBsZSguLi5uZXdfdmFsdWVzKTtcbiAgICB9XG5cbiAgICBsZXQgbmV3X3ZhbHVlcyA9IHRoaXMudmFsdWVzLmNvbmNhdChbXSk7XG4gICAgbmV3X3ZhbHVlcy5zcGxpY2UoaW5kZXgsIDAsIGVsZW0pO1xuICAgIHJldHVybiBuZXcgVHVwbGUoLi4ubmV3X3ZhbHVlcyk7XG4gIH1cblxuICByZW1vdmVfZWxlbShpbmRleCkge1xuICAgIGxldCBuZXdfdmFsdWVzID0gdGhpcy52YWx1ZXMuY29uY2F0KFtdKTtcbiAgICBuZXdfdmFsdWVzLnNwbGljZShpbmRleCwgMSk7XG4gICAgcmV0dXJuIG5ldyBUdXBsZSguLi5uZXdfdmFsdWVzKTtcbiAgfVxuXG59XG5cbmxldCBwcm9jZXNzX2NvdW50ZXIgPSAtMTtcblxuY2xhc3MgUElEIHtcbiAgY29uc3RydWN0b3IoKSB7XG4gICAgcHJvY2Vzc19jb3VudGVyID0gcHJvY2Vzc19jb3VudGVyICsgMTtcbiAgICB0aGlzLmlkID0gcHJvY2Vzc19jb3VudGVyO1xuICB9XG5cbiAgdG9TdHJpbmcoKSB7XG4gICAgcmV0dXJuIFwiUElEIzwwLlwiICsgdGhpcy5pZCArIFwiLjA+XCI7XG4gIH1cbn1cblxuY2xhc3MgSW50ZWdlciB7fVxuY2xhc3MgRmxvYXQge31cblxuZXhwb3J0IHsgUElELCBUdXBsZSwgSW50ZWdlciwgRmxvYXQgfTtcbi8vIyBzb3VyY2VNYXBwaW5nVVJMPWRhdGE6YXBwbGljYXRpb24vanNvbjtiYXNlNjQsZXlKMlpYSnphVzl1SWpvekxDSnpiM1Z5WTJWeklqcGJJbXhwWWk5amIzSmxMM0J5YVcxcGRHbDJaWE11YW5NaVhTd2libUZ0WlhNaU9sdGRMQ0p0WVhCd2FXNW5jeUk2SWtGQlFVRXNUVUZCVFN4TFFVRk9MRU5CUVZrN08wRkJSVllzWTBGQldTeEhRVUZITEVsQlFVZ3NSVUZCVVR0QlFVTnNRaXhUUVVGTExFMUJRVXdzUjBGQll5eFBRVUZQTEUxQlFWQXNRMEZCWXl4SlFVRmtMRU5CUVdRc1EwRkVhMEk3UVVGRmJFSXNVMEZCU3l4TlFVRk1MRWRCUVdNc1MwRkJTeXhOUVVGTUxFTkJRVmtzVFVGQldpeERRVVpKTzBkQlFYQkNPenRCUVV0QkxFMUJRVWtzUzBGQlNpeEZRVUZYTzBGQlExUXNWMEZCVHl4TFFVRkxMRTFCUVV3c1EwRkJXU3hMUVVGYUxFTkJRVkFzUTBGRVV6dEhRVUZZT3p0QlFVbEJMRlZCUVZFN1FVRkRUaXhYUVVGUExFdEJRVXNzVFVGQlRDeERRVUZaTEUxQlFWb3NRMEZFUkR0SFFVRlNPenRCUVVsQkxFZEJRVU1zVDBGQlR5eFJRVUZRTEVsQlFXMUNPMEZCUTJ4Q0xGZEJRVThzUzBGQlN5eE5RVUZNTEVOQlFWa3NUMEZCVHl4UlFVRlFMRU5CUVZvc1JVRkJVQ3hEUVVSclFqdEhRVUZ3UWpzN1FVRkpRU3hoUVVGWE8wRkJRMVFzVVVGQlNTeERRVUZLTzFGQlFVOHNTVUZCU1N4RlFVRktMRU5CUkVVN1FVRkZWQ3hUUVVGTExFbEJRVWtzUTBGQlNpeEZRVUZQTEVsQlFVa3NTMEZCU3l4TlFVRk1MRU5CUVZrc1RVRkJXaXhGUVVGdlFpeEhRVUZ3UXl4RlFVRjVRenRCUVVOMlF5eFZRVUZKTEUxQlFVMHNSVUZCVGl4RlFVRlZPMEZCUTFvc1lVRkJTeXhKUVVGTUxFTkJSRms3VDBGQlpEdEJRVWRCTEZkQlFVc3NTMEZCU3l4TlFVRk1MRU5CUVZrc1EwRkJXaXhGUVVGbExGRkJRV1lzUlVGQlRDeERRVXAxUXp0TFFVRjZRenM3UVVGUFFTeFhRVUZQTEUxQlFVMHNRMEZCVGl4SFFVRlZMRWRCUVZZc1EwRlVSVHRIUVVGWU96dEJRVmxCTEZkQlFWTXNTMEZCVkN4RlFVRm5RaXhKUVVGb1FpeEZRVUZ4UWp0QlFVTnVRaXhSUVVGSExGVkJRVlVzUzBGQlN5eE5RVUZNTEVWQlFWazdRVUZEZGtJc1ZVRkJTU3hoUVVGaExFdEJRVXNzVFVGQlRDeERRVUZaTEUxQlFWb3NRMEZCYlVJc1EwRkJReXhKUVVGRUxFTkJRVzVDTEVOQlFXSXNRMEZFYlVJN1FVRkZka0lzWVVGQlR5eEpRVUZKTEV0QlFVb3NRMEZCVlN4SFFVRkhMRlZCUVVnc1EwRkJha0lzUTBGR2RVSTdTMEZCZWtJN08wRkJTMEVzVVVGQlNTeGhRVUZoTEV0QlFVc3NUVUZCVEN4RFFVRlpMRTFCUVZvc1EwRkJiVUlzUlVGQmJrSXNRMEZCWWl4RFFVNWxPMEZCVDI1Q0xHVkJRVmNzVFVGQldDeERRVUZyUWl4TFFVRnNRaXhGUVVGNVFpeERRVUY2UWl4RlFVRTBRaXhKUVVFMVFpeEZRVkJ0UWp0QlFWRnVRaXhYUVVGUExFbEJRVWtzUzBGQlNpeERRVUZWTEVkQlFVY3NWVUZCU0N4RFFVRnFRaXhEUVZKdFFqdEhRVUZ5UWpzN1FVRlhRU3hqUVVGWkxFdEJRVm9zUlVGQmEwSTdRVUZEYUVJc1VVRkJTU3hoUVVGaExFdEJRVXNzVFVGQlRDeERRVUZaTEUxQlFWb3NRMEZCYlVJc1JVRkJia0lzUTBGQllpeERRVVJaTzBGQlJXaENMR1ZCUVZjc1RVRkJXQ3hEUVVGclFpeExRVUZzUWl4RlFVRjVRaXhEUVVGNlFpeEZRVVpuUWp0QlFVZG9RaXhYUVVGUExFbEJRVWtzUzBGQlNpeERRVUZWTEVkQlFVY3NWVUZCU0N4RFFVRnFRaXhEUVVoblFqdEhRVUZzUWpzN1EwRXhRMFk3TzBGQmJVUkJMRWxCUVVrc2EwSkJRV3RDTEVOQlFVTXNRMEZCUkRzN1FVRkZkRUlzVFVGQlRTeEhRVUZPTEVOQlFWVTdRVUZEVWl4blFrRkJZVHRCUVVOWUxITkNRVUZyUWl4clFrRkJhMElzUTBGQmJFSXNRMEZFVUR0QlFVVllMRk5CUVVzc1JVRkJUQ3hIUVVGVkxHVkJRVllzUTBGR1Z6dEhRVUZpT3p0QlFVdEJMR0ZCUVZVN1FVRkRVaXhYUVVGUExGbEJRVmtzUzBGQlN5eEZRVUZNTEVkQlFWVXNTMEZCZEVJc1EwRkVRenRIUVVGV08wTkJUa1k3TzBGQlYwRXNUVUZCVFN4UFFVRk9MRU5CUVdNc1JVRkJaRHRCUVVOQkxFMUJRVTBzUzBGQlRpeERRVUZaTEVWQlFWbzdPMEZCUlVFc1UwRkJVeXhIUVVGVUxFVkJRV01zUzBGQlpDeEZRVUZ4UWl4UFFVRnlRaXhGUVVFNFFpeExRVUU1UWlJc0ltWnBiR1VpT2lKc2FXSXZZMjl5WlM5d2NtbHRhWFJwZG1WekxtcHpJaXdpYzI5MWNtTmxjME52Ym5SbGJuUWlPbHNpWTJ4aGMzTWdWSFZ3YkdVZ2UxeHVYRzRnSUdOdmJuTjBjblZqZEc5eUtDNHVMbUZ5WjNNcGUxeHVJQ0FnSUhSb2FYTXVkbUZzZFdWeklEMGdUMkpxWldOMExtWnlaV1Y2WlNoaGNtZHpLVHRjYmlBZ0lDQjBhR2x6TG14bGJtZDBhQ0E5SUhSb2FYTXVkbUZzZFdWekxteGxibWQwYUR0Y2JpQWdmVnh1WEc0Z0lHZGxkQ2hwYm1SbGVDa2dlMXh1SUNBZ0lISmxkSFZ5YmlCMGFHbHpMblpoYkhWbGMxdHBibVJsZUYwN1hHNGdJSDFjYmx4dUlDQmpiM1Z1ZENncElIdGNiaUFnSUNCeVpYUjFjbTRnZEdocGN5NTJZV3gxWlhNdWJHVnVaM1JvTzF4dUlDQjlYRzVjYmlBZ1cxTjViV0p2YkM1cGRHVnlZWFJ2Y2wwb0tTQjdYRzRnSUNBZ2NtVjBkWEp1SUhSb2FYTXVkbUZzZFdWelcxTjViV0p2YkM1cGRHVnlZWFJ2Y2wwb0tUdGNiaUFnZlZ4dVhHNGdJSFJ2VTNSeWFXNW5LQ2tnZTF4dUlDQWdJSFpoY2lCcExDQnpJRDBnWENKY0lqdGNiaUFnSUNCbWIzSWdLR2tnUFNBd095QnBJRHdnZEdocGN5NTJZV3gxWlhNdWJHVnVaM1JvT3lCcEt5c3BJSHRjYmlBZ0lDQWdJR2xtSUNoeklDRTlQU0JjSWx3aUtTQjdYRzRnSUNBZ0lDQWdJSE1nS3owZ1hDSXNJRndpTzF4dUlDQWdJQ0FnZlZ4dUlDQWdJQ0FnY3lBclBTQjBhR2x6TG5aaGJIVmxjMXRwWFM1MGIxTjBjbWx1WnlncE8xeHVJQ0FnSUgxY2JseHVJQ0FnSUhKbGRIVnliaUJjSW50Y0lpQXJJSE1nS3lCY0luMWNJanRjYmlBZ2ZWeHVYRzRnSUhCMWRGOWxiR1Z0S0dsdVpHVjRMQ0JsYkdWdEtYdGNiaUFnSUNCcFppaHBibVJsZUNBOVBUMGdkR2hwY3k1c1pXNW5kR2dwZTF4dUlDQWdJQ0FnYkdWMElHNWxkMTkyWVd4MVpYTWdQU0IwYUdsekxuWmhiSFZsY3k1amIyNWpZWFFvVzJWc1pXMWRLVHRjYmlBZ0lDQWdJSEpsZEhWeWJpQnVaWGNnVkhWd2JHVW9MaTR1Ym1WM1gzWmhiSFZsY3lrN1hHNGdJQ0FnZlZ4dVhHNGdJQ0FnYkdWMElHNWxkMTkyWVd4MVpYTWdQU0IwYUdsekxuWmhiSFZsY3k1amIyNWpZWFFvVzEwcE8xeHVJQ0FnSUc1bGQxOTJZV3gxWlhNdWMzQnNhV05sS0dsdVpHVjRMQ0F3TENCbGJHVnRLVHRjYmlBZ0lDQnlaWFIxY200Z2JtVjNJRlIxY0d4bEtDNHVMbTVsZDE5MllXeDFaWE1wTzF4dUlDQjlYRzVjYmlBZ2NtVnRiM1psWDJWc1pXMG9hVzVrWlhncGUxeHVJQ0FnSUd4bGRDQnVaWGRmZG1Gc2RXVnpJRDBnZEdocGN5NTJZV3gxWlhNdVkyOXVZMkYwS0Z0ZEtUdGNiaUFnSUNCdVpYZGZkbUZzZFdWekxuTndiR2xqWlNocGJtUmxlQ3dnTVNrN1hHNGdJQ0FnY21WMGRYSnVJRzVsZHlCVWRYQnNaU2d1TGk1dVpYZGZkbUZzZFdWektUdGNiaUFnZlZ4dVhHNTlYRzVjYmx4dWJHVjBJSEJ5YjJObGMzTmZZMjkxYm5SbGNpQTlJQzB4TzF4dVhHNWpiR0Z6Y3lCUVNVUWdlMXh1SUNCamIyNXpkSEoxWTNSdmNpZ3BlMXh1SUNBZ0lIQnliMk5sYzNOZlkyOTFiblJsY2lBOUlIQnliMk5sYzNOZlkyOTFiblJsY2lBcklERTdYRzRnSUNBZ2RHaHBjeTVwWkNBOUlIQnliMk5sYzNOZlkyOTFiblJsY2p0Y2JpQWdmVnh1WEc0Z0lIUnZVM1J5YVc1bktDbDdYRzRnSUNBZ2NtVjBkWEp1SUZ3aVVFbEVJend3TGx3aUlDc2dkR2hwY3k1cFpDQXJJRndpTGpBK1hDSTdYRzRnSUgxY2JuMWNibHh1WTJ4aGMzTWdTVzUwWldkbGNpQjdmVnh1WTJ4aGMzTWdSbXh2WVhRZ2UzMWNibHh1Wlhod2IzSjBJSHNnVUVsRUxDQlVkWEJzWlN3Z1NXNTBaV2RsY2l3Z1JteHZZWFFnZlR0Y2JpSmRMQ0p6YjNWeVkyVlNiMjkwSWpvaUwzTnZkWEpqWlM4aWZRPT1cbiIsIlxuXCJ1c2Ugc3RyaWN0XCI7XG5cbmltcG9ydCBNYWlsYm94IGZyb20gXCIuL21haWxib3hcIjtcbmltcG9ydCBQcm9jZXNzIGZyb20gXCIuL3Byb2Nlc3NcIjtcbmltcG9ydCBTdGF0ZXMgZnJvbSBcIi4vc3RhdGVzXCI7XG5pbXBvcnQgKiBhcyBQcmltaXRpdmVzIGZyb20gXCIuLi9wcmltaXRpdmVzXCI7XG5cbmNsYXNzIFByb2Nlc3NTeXN0ZW0ge1xuXG4gIGNvbnN0cnVjdG9yKCkge1xuICAgIHRoaXMucGlkcyA9IG5ldyBNYXAoKTtcbiAgICB0aGlzLm1haWxib3hlcyA9IG5ldyBNYXAoKTtcbiAgICB0aGlzLm5hbWVzID0gbmV3IE1hcCgpO1xuICAgIHRoaXMubGlua3MgPSBuZXcgTWFwKCk7XG5cbiAgICB0aGlzLmN1cnJlbnRfcHJvY2VzcyA9IG51bGw7XG4gICAgdGhpcy5zdXNwZW5kZWQgPSBuZXcgTWFwKCk7XG5cbiAgICB0aGlzLm1haW5fcHJvY2Vzc19waWQgPSB0aGlzLnNwYXduKCk7XG4gICAgdGhpcy5zZXRfY3VycmVudCh0aGlzLm1haW5fcHJvY2Vzc19waWQpO1xuICB9XG5cbiAgc3Bhd24oKSB7XG4gICAgcmV0dXJuIHRoaXMuYWRkX3Byb2MoZmFsc2UpLnBpZDtcbiAgfVxuXG4gIHNwYXduX2xpbmsoKSB7XG4gICAgcmV0dXJuIHRoaXMuYWRkX3Byb2ModHJ1ZSkucGlkO1xuICB9XG5cbiAgbGluayhwaWQpIHtcbiAgICB0aGlzLmxpbmtzLmdldCh0aGlzLnBpZCgpKS5hZGQocGlkKTtcbiAgICB0aGlzLmxpbmtzLmdldChwaWQpLmFkZCh0aGlzLnBpZCgpKTtcbiAgfVxuXG4gIHVubGluayhwaWQpIHtcbiAgICB0aGlzLmxpbmtzLmdldCh0aGlzLnBpZCgpKS5kZWxldGUocGlkKTtcbiAgICB0aGlzLmxpbmtzLmdldChwaWQpLmRlbGV0ZSh0aGlzLnBpZCgpKTtcbiAgfVxuXG4gIHNldF9jdXJyZW50KGlkKSB7XG4gICAgbGV0IHBpZCA9IHRoaXMucGlkb2YoaWQpO1xuICAgIGlmIChwaWQgIT09IG51bGwpIHtcbiAgICAgIHRoaXMuY3VycmVudF9wcm9jZXNzID0gdGhpcy5waWRzLmdldChwaWQpO1xuICAgICAgdGhpcy5jdXJyZW50X3Byb2Nlc3Muc3RhdHVzID0gU3RhdGVzLlJVTk5JTkc7XG4gICAgfVxuICB9XG5cbiAgYWRkX3Byb2MobGlua2VkKSB7XG4gICAgbGV0IG5ld3BpZCA9IG5ldyBQcmltaXRpdmVzLlBJRCgpO1xuICAgIGxldCBtYWlsYm94ID0gbmV3IE1haWxib3goKTtcbiAgICBsZXQgbmV3cHJvYyA9IG5ldyBQcm9jZXNzKG5ld3BpZCwgbWFpbGJveCk7XG5cbiAgICB0aGlzLnBpZHMuc2V0KG5ld3BpZCwgbmV3cHJvYyk7XG4gICAgdGhpcy5tYWlsYm94ZXMuc2V0KG5ld3BpZCwgbWFpbGJveCk7XG4gICAgdGhpcy5saW5rcy5zZXQobmV3cGlkLCBuZXcgU2V0KCkpO1xuXG4gICAgaWYgKGxpbmtlZCkge1xuICAgICAgdGhpcy5saW5rKG5ld3BpZCk7XG4gICAgfVxuXG4gICAgcmV0dXJuIG5ld3Byb2M7XG4gIH1cblxuICByZW1vdmVfcHJvYyhwaWQpIHtcbiAgICB0aGlzLnBpZHMuZGVsZXRlKHBpZCk7XG4gICAgdGhpcy51bnJlZ2lzdGVyKHBpZCk7XG5cbiAgICBpZiAodGhpcy5saW5rcy5oYXMocGlkKSkge1xuICAgICAgZm9yIChsZXQgbGlua3BpZCBvZiB0aGlzLmxpbmtzLmdldChwaWQpKSB7XG4gICAgICAgIHRoaXMubGlua3MuZ2V0KGxpbmtwaWQpLmRlbGV0ZShwaWQpO1xuICAgICAgfVxuXG4gICAgICB0aGlzLmxpbmtzLmRlbGV0ZShwaWQpO1xuICAgIH1cbiAgfVxuXG4gIGV4aXQoaWQpIHtcbiAgICBsZXQgcGlkID0gdGhpcy5waWRvZihpZCk7XG4gICAgdGhpcy5yZW1vdmVfcHJvYyhpZCk7XG4gIH1cblxuICByZWdpc3RlcihuYW1lLCBwaWQpIHtcbiAgICBpZiAoIXRoaXMubmFtZXMuaGFzKG5hbWUpKSB7XG4gICAgICB0aGlzLm5hbWVzLnNldChuYW1lLCBwaWQpO1xuICAgICAgcmV0dXJuIG5hbWU7XG4gICAgfSBlbHNlIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcihcIk5hbWUgaXMgYWxyZWFkeSByZWdpc3RlcmVkIHRvIGFub3RoZXIgcHJvY2Vzc1wiKTtcbiAgICB9XG4gIH1cblxuICByZWdpc3RlcmVkKG5hbWUpIHtcbiAgICByZXR1cm4gdGhpcy5uYW1lcy5oYXMobmFtZSkgPyB0aGlzLm5hbWVzLmdldChuYW1lKSA6IG51bGw7XG4gIH1cblxuICB1bnJlZ2lzdGVyKHBpZCkge1xuICAgIGZvciAobGV0IG5hbWUgb2YgdGhpcy5uYW1lcy5rZXlzKCkpIHtcbiAgICAgIGlmICh0aGlzLm5hbWVzLmhhcyhuYW1lKSAmJiB0aGlzLm5hbWVzLmdldChuYW1lKSA9PT0gcGlkKSB7XG4gICAgICAgIHRoaXMubmFtZXMuZGVsZXRlKG5hbWUpO1xuICAgICAgfVxuICAgIH1cbiAgfVxuXG4gIHBpZCgpIHtcbiAgICByZXR1cm4gdGhpcy5jdXJyZW50X3Byb2Nlc3MucGlkO1xuICB9XG5cbiAgcGlkb2YoaWQpIHtcbiAgICBpZiAoaWQgaW5zdGFuY2VvZiBQcmltaXRpdmVzLlBJRCkge1xuICAgICAgcmV0dXJuIHRoaXMucGlkcy5oYXMoaWQpID8gaWQgOiBudWxsO1xuICAgIH0gZWxzZSBpZiAoaWQgaW5zdGFuY2VvZiBQcm9jZXNzKSB7XG4gICAgICByZXR1cm4gaWQucGlkO1xuICAgIH0gZWxzZSB7XG4gICAgICBsZXQgcGlkID0gdGhpcy5yZWdpc3RlcmVkKGlkKTtcbiAgICAgIGlmIChwaWQgPT09IG51bGwpIHRocm93IFwiUHJvY2VzcyBuYW1lIG5vdCByZWdpc3RlcmVkOiBcIiArIGlkICsgXCIgKFwiICsgdHlwZW9mIGlkICsgXCIpXCI7XG4gICAgICByZXR1cm4gcGlkO1xuICAgIH1cbiAgfVxuXG4gIHB1dChpZCwga2V5LCB2YWx1ZSkge1xuICAgIGxldCBwaWQgPSB0aGlzLnBpZG9mKGlkKTtcbiAgICBsZXQgcHJvY2VzcyA9IHRoaXMucGlkcy5nZXQocGlkKTtcbiAgICBwcm9jZXNzLmRpY3Rba2V5XSA9IHZhbHVlO1xuICB9XG5cbiAgZ2V0KGlkLCBrZXkpIHtcbiAgICBsZXQgcGlkID0gdGhpcy5waWRvZihpZCk7XG4gICAgbGV0IHByb2Nlc3MgPSB0aGlzLnBpZHMuZ2V0KHBpZCk7XG5cbiAgICBpZiAoa2V5ICE9IG51bGwpIHtcbiAgICAgIHJldHVybiBwcm9jZXNzLmRpY3Rba2V5XTtcbiAgICB9IGVsc2Uge1xuICAgICAgcmV0dXJuIHByb2Nlc3MuZGljdDtcbiAgICB9XG4gIH1cblxuICBnZXRfa2V5cyhpZCkge1xuICAgIGxldCBwaWQgPSB0aGlzLnBpZG9mKGlkKTtcbiAgICBsZXQgcHJvY2VzcyA9IHRoaXMucGlkcy5nZXQocGlkKTtcblxuICAgIHJldHVybiBPYmplY3Qua2V5cyhwcm9jZXNzLmRpY3QpO1xuICB9XG5cbiAgZXJhc2UoaWQsIGtleSkge1xuICAgIGxldCBwaWQgPSB0aGlzLnBpZG9mKGlkKTtcbiAgICBsZXQgcHJvY2VzcyA9IHRoaXMucGlkcy5nZXQocGlkKTtcblxuICAgIGlmIChrZXkgIT0gbnVsbCkge1xuICAgICAgZGVsZXRlIHByb2Nlc3MuZGljdFtrZXldO1xuICAgIH0gZWxzZSB7XG4gICAgICBwcm9jZXNzLmRpY3QgPSB7fTtcbiAgICB9XG4gIH1cbn1cblxuZXhwb3J0IGRlZmF1bHQgUHJvY2Vzc1N5c3RlbTtcbi8vIyBzb3VyY2VNYXBwaW5nVVJMPWRhdGE6YXBwbGljYXRpb24vanNvbjtiYXNlNjQsZXlKMlpYSnphVzl1SWpvekxDSnpiM1Z5WTJWeklqcGJJbXhwWWk5amIzSmxMM0J5YjJObGMzTmxjeTl3Y205alpYTnpYM041YzNSbGJTNXFjeUpkTENKdVlXMWxjeUk2VzEwc0ltMWhjSEJwYm1keklqb2lPMEZCUTBFN08wRkJSVUVzVDBGQlR5eFBRVUZRTEUxQlFXOUNMRmRCUVhCQ08wRkJRMEVzVDBGQlR5eFBRVUZRTEUxQlFXOUNMRmRCUVhCQ08wRkJRMEVzVDBGQlR5eE5RVUZRTEUxQlFXMUNMRlZCUVc1Q08wRkJRMEVzVDBGQlR5eExRVUZMTEZWQlFVd3NUVUZCY1VJc1pVRkJOVUk3TzBGQlJVRXNUVUZCVFN4aFFVRk9MRU5CUVc5Q096dEJRVVZzUWl4blFrRkJZVHRCUVVOWUxGTkJRVXNzU1VGQlRDeEhRVUZaTEVsQlFVa3NSMEZCU2l4RlFVRmFMRU5CUkZjN1FVRkZXQ3hUUVVGTExGTkJRVXdzUjBGQmFVSXNTVUZCU1N4SFFVRktMRVZCUVdwQ0xFTkJSbGM3UVVGSFdDeFRRVUZMTEV0QlFVd3NSMEZCWVN4SlFVRkpMRWRCUVVvc1JVRkJZaXhEUVVoWE8wRkJTVmdzVTBGQlN5eExRVUZNTEVkQlFXRXNTVUZCU1N4SFFVRktMRVZCUVdJc1EwRktWenM3UVVGTldDeFRRVUZMTEdWQlFVd3NSMEZCZFVJc1NVRkJka0lzUTBGT1Z6dEJRVTlZTEZOQlFVc3NVMEZCVEN4SFFVRnBRaXhKUVVGSkxFZEJRVW9zUlVGQmFrSXNRMEZRVnpzN1FVRlRXQ3hUUVVGTExHZENRVUZNTEVkQlFYZENMRXRCUVVzc1MwRkJUQ3hGUVVGNFFpeERRVlJYTzBGQlZWZ3NVMEZCU3l4WFFVRk1MRU5CUVdsQ0xFdEJRVXNzWjBKQlFVd3NRMEZCYWtJc1EwRldWenRIUVVGaU96dEJRV0ZCTEZWQlFVODdRVUZEVEN4WFFVRlBMRXRCUVVzc1VVRkJUQ3hEUVVGakxFdEJRV1FzUlVGQmNVSXNSMEZCY2tJc1EwRkVSanRIUVVGUU96dEJRVWxCTEdWQlFWazdRVUZEVml4WFFVRlBMRXRCUVVzc1VVRkJUQ3hEUVVGakxFbEJRV1FzUlVGQmIwSXNSMEZCY0VJc1EwRkVSenRIUVVGYU96dEJRVWxCTEU5QlFVc3NSMEZCVEN4RlFVRlRPMEZCUTFBc1UwRkJTeXhMUVVGTUxFTkJRVmNzUjBGQldDeERRVUZsTEV0QlFVc3NSMEZCVEN4RlFVRm1MRVZCUVRKQ0xFZEJRVE5DTEVOQlFTdENMRWRCUVM5Q0xFVkJSRTg3UVVGRlVDeFRRVUZMTEV0QlFVd3NRMEZCVnl4SFFVRllMRU5CUVdVc1IwRkJaaXhGUVVGdlFpeEhRVUZ3UWl4RFFVRjNRaXhMUVVGTExFZEJRVXdzUlVGQmVFSXNSVUZHVHp0SFFVRlVPenRCUVV0QkxGTkJRVThzUjBGQlVDeEZRVUZYTzBGQlExUXNVMEZCU3l4TFFVRk1MRU5CUVZjc1IwRkJXQ3hEUVVGbExFdEJRVXNzUjBGQlRDeEZRVUZtTEVWQlFUSkNMRTFCUVROQ0xFTkJRV3RETEVkQlFXeERMRVZCUkZNN1FVRkZWQ3hUUVVGTExFdEJRVXdzUTBGQlZ5eEhRVUZZTEVOQlFXVXNSMEZCWml4RlFVRnZRaXhOUVVGd1FpeERRVUV5UWl4TFFVRkxMRWRCUVV3c1JVRkJNMElzUlVGR1V6dEhRVUZZT3p0QlFVdEJMR05CUVZrc1JVRkJXaXhGUVVGbE8wRkJRMklzVVVGQlNTeE5RVUZOTEV0QlFVc3NTMEZCVEN4RFFVRlhMRVZCUVZnc1EwRkJUaXhEUVVSVE8wRkJSV0lzVVVGQlJ5eFJRVUZSTEVsQlFWSXNSVUZCWVR0QlFVTmtMRmRCUVVzc1pVRkJUQ3hIUVVGMVFpeExRVUZMTEVsQlFVd3NRMEZCVlN4SFFVRldMRU5CUVdNc1IwRkJaQ3hEUVVGMlFpeERRVVJqTzBGQlJXUXNWMEZCU3l4bFFVRk1MRU5CUVhGQ0xFMUJRWEpDTEVkQlFUaENMRTlCUVU4c1QwRkJVQ3hEUVVab1FqdExRVUZvUWp0SFFVWkdPenRCUVZGQkxGZEJRVk1zVFVGQlZDeEZRVUZuUWp0QlFVTmtMRkZCUVVrc1UwRkJVeXhKUVVGSkxGZEJRVmNzUjBGQldDeEZRVUZpTEVOQlJGVTdRVUZGWkN4UlFVRkpMRlZCUVZVc1NVRkJTU3hQUVVGS0xFVkJRVllzUTBGR1ZUdEJRVWRrTEZGQlFVa3NWVUZCVlN4SlFVRkpMRTlCUVVvc1EwRkJXU3hOUVVGYUxFVkJRVzlDTEU5QlFYQkNMRU5CUVZZc1EwRklWVHM3UVVGTFpDeFRRVUZMTEVsQlFVd3NRMEZCVlN4SFFVRldMRU5CUVdNc1RVRkJaQ3hGUVVGelFpeFBRVUYwUWl4RlFVeGpPMEZCVFdRc1UwRkJTeXhUUVVGTUxFTkJRV1VzUjBGQlppeERRVUZ0UWl4TlFVRnVRaXhGUVVFeVFpeFBRVUV6UWl4RlFVNWpPMEZCVDJRc1UwRkJTeXhMUVVGTUxFTkJRVmNzUjBGQldDeERRVUZsTEUxQlFXWXNSVUZCZFVJc1NVRkJTU3hIUVVGS0xFVkJRWFpDTEVWQlVHTTdPMEZCVTJRc1VVRkJSeXhOUVVGSUxFVkJRVlU3UVVGRFVpeFhRVUZMTEVsQlFVd3NRMEZCVlN4TlFVRldMRVZCUkZFN1MwRkJWanM3UVVGSlFTeFhRVUZQTEU5QlFWQXNRMEZpWXp0SFFVRm9RanM3UVVGblFrRXNZMEZCV1N4SFFVRmFMRVZCUVdkQ08wRkJRMlFzVTBGQlN5eEpRVUZNTEVOQlFWVXNUVUZCVml4RFFVRnBRaXhIUVVGcVFpeEZRVVJqTzBGQlJXUXNVMEZCU3l4VlFVRk1MRU5CUVdkQ0xFZEJRV2hDTEVWQlJtTTdPMEZCU1dRc1VVRkJSeXhMUVVGTExFdEJRVXdzUTBGQlZ5eEhRVUZZTEVOQlFXVXNSMEZCWml4RFFVRklMRVZCUVhWQ08wRkJRM0pDTEZkQlFVc3NTVUZCU1N4UFFVRktMRWxCUVdVc1MwRkJTeXhMUVVGTUxFTkJRVmNzUjBGQldDeERRVUZsTEVkQlFXWXNRMEZCY0VJc1JVRkJlVU03UVVGRGRrTXNZVUZCU3l4TFFVRk1MRU5CUVZjc1IwRkJXQ3hEUVVGbExFOUJRV1lzUlVGQmQwSXNUVUZCZUVJc1EwRkJLMElzUjBGQkwwSXNSVUZFZFVNN1QwRkJla003TzBGQlNVRXNWMEZCU3l4TFFVRk1MRU5CUVZjc1RVRkJXQ3hEUVVGclFpeEhRVUZzUWl4RlFVeHhRanRMUVVGMlFqdEhRVXBHT3p0QlFXRkJMRTlCUVVzc1JVRkJUQ3hGUVVGUk8wRkJRMDRzVVVGQlNTeE5RVUZOTEV0QlFVc3NTMEZCVEN4RFFVRlhMRVZCUVZnc1EwRkJUaXhEUVVSRk8wRkJSVTRzVTBGQlN5eFhRVUZNTEVOQlFXbENMRVZCUVdwQ0xFVkJSazA3UjBGQlVqczdRVUZMUVN4WFFVRlRMRWxCUVZRc1JVRkJaU3hIUVVGbUxFVkJRVzFDTzBGQlEycENMRkZCUVVjc1EwRkJReXhMUVVGTExFdEJRVXdzUTBGQlZ5eEhRVUZZTEVOQlFXVXNTVUZCWml4RFFVRkVMRVZCUVhOQ08wRkJRM1pDTEZkQlFVc3NTMEZCVEN4RFFVRlhMRWRCUVZnc1EwRkJaU3hKUVVGbUxFVkJRWEZDTEVkQlFYSkNMRVZCUkhWQ08wRkJSWFpDTEdGQlFVOHNTVUZCVUN4RFFVWjFRanRMUVVGNlFpeE5RVWRMTzBGQlEwZ3NXVUZCVFN4SlFVRkpMRXRCUVVvc1EwRkJWU3dyUTBGQlZpeERRVUZPTEVOQlJFYzdTMEZJVER0SFFVUkdPenRCUVZOQkxHRkJRVmNzU1VGQldDeEZRVUZuUWp0QlFVTmtMRmRCUVU4c1MwRkJTeXhMUVVGTUxFTkJRVmNzUjBGQldDeERRVUZsTEVsQlFXWXNTVUZCZFVJc1MwRkJTeXhMUVVGTUxFTkJRVmNzUjBGQldDeERRVUZsTEVsQlFXWXNRMEZCZGtJc1IwRkJPRU1zU1VGQk9VTXNRMEZFVHp0SFFVRm9RanM3UVVGSlFTeGhRVUZYTEVkQlFWZ3NSVUZCWlR0QlFVTmlMRk5CUVVrc1NVRkJTU3hKUVVGS0xFbEJRVmtzUzBGQlN5eExRVUZNTEVOQlFWY3NTVUZCV0N4RlFVRm9RaXhGUVVGclF6dEJRVU5vUXl4VlFVRkhMRXRCUVVzc1MwRkJUQ3hEUVVGWExFZEJRVmdzUTBGQlpTeEpRVUZtTEV0QlFYZENMRXRCUVVzc1MwRkJUQ3hEUVVGWExFZEJRVmdzUTBGQlpTeEpRVUZtTEUxQlFYbENMRWRCUVhwQ0xFVkJRVFpDTzBGQlEzUkVMR0ZCUVVzc1MwRkJUQ3hEUVVGWExFMUJRVmdzUTBGQmEwSXNTVUZCYkVJc1JVRkVjMFE3VDBGQmVFUTdTMEZFUmp0SFFVUkdPenRCUVZGQkxGRkJRVXM3UVVGRFNDeFhRVUZQTEV0QlFVc3NaVUZCVEN4RFFVRnhRaXhIUVVGeVFpeERRVVJLTzBkQlFVdzdPMEZCU1VFc1VVRkJUU3hGUVVGT0xFVkJRVk03UVVGRFVDeFJRVUZKTEdOQlFXTXNWMEZCVnl4SFFVRllMRVZCUVdkQ08wRkJReTlDTEdGQlFVOHNTMEZCU3l4SlFVRk1MRU5CUVZVc1IwRkJWaXhEUVVGakxFVkJRV1FzU1VGQmIwSXNSVUZCY0VJc1IwRkJlVUlzU1VGQmVrSXNRMEZFZDBJN1MwRkJiRU1zVFVGRlR5eEpRVUZKTEdOQlFXTXNUMEZCWkN4RlFVRjFRanRCUVVNdlFpeGhRVUZQTEVkQlFVY3NSMEZCU0N4RFFVUjNRanRMUVVFelFpeE5RVVZCTzBGQlEwb3NWVUZCU1N4TlFVRk5MRXRCUVVzc1ZVRkJUQ3hEUVVGblFpeEZRVUZvUWl4RFFVRk9MRU5CUkVFN1FVRkZTaXhWUVVGSkxGRkJRVkVzU1VGQlVpeEZRVU5FTEUxQlFVMHNhME5CUVd0RExFVkJRV3hETEVkQlFYVkRMRWxCUVhaRExFZEJRVGhETEU5QlFVOHNSVUZCVUN4SFFVRmhMRWRCUVRORUxFTkJSRlE3UVVGRlFTeGhRVUZQTEVkQlFWQXNRMEZLU1R0TFFVWkJPMGRCU0ZRN08wRkJZVUVzVFVGQlNTeEZRVUZLTEVWQlFWRXNSMEZCVWl4RlFVRmhMRXRCUVdJc1JVRkJiVUk3UVVGRGFrSXNVVUZCU1N4TlFVRk5MRXRCUVVzc1MwRkJUQ3hEUVVGWExFVkJRVmdzUTBGQlRpeERRVVJoTzBGQlJXcENMRkZCUVVrc1ZVRkJWU3hMUVVGTExFbEJRVXdzUTBGQlZTeEhRVUZXTEVOQlFXTXNSMEZCWkN4RFFVRldMRU5CUm1FN1FVRkhha0lzV1VGQlVTeEpRVUZTTEVOQlFXRXNSMEZCWWl4SlFVRnZRaXhMUVVGd1FpeERRVWhwUWp0SFFVRnVRanM3UVVGTlFTeE5RVUZKTEVWQlFVb3NSVUZCVVN4SFFVRlNMRVZCUVZrN1FVRkRWaXhSUVVGSkxFMUJRVTBzUzBGQlN5eExRVUZNTEVOQlFWY3NSVUZCV0N4RFFVRk9MRU5CUkUwN1FVRkZWaXhSUVVGSkxGVkJRVlVzUzBGQlN5eEpRVUZNTEVOQlFWVXNSMEZCVml4RFFVRmpMRWRCUVdRc1EwRkJWaXhEUVVaTk96dEJRVWxXTEZGQlFVY3NUMEZCVHl4SlFVRlFMRVZCUVZrN1FVRkRZaXhoUVVGUExGRkJRVkVzU1VGQlVpeERRVUZoTEVkQlFXSXNRMEZCVUN4RFFVUmhPMHRCUVdZc1RVRkZTenRCUVVOSUxHRkJRVThzVVVGQlVTeEpRVUZTTEVOQlJFbzdTMEZHVER0SFFVcEdPenRCUVZkQkxGZEJRVk1zUlVGQlZDeEZRVUZaTzBGQlExWXNVVUZCU1N4TlFVRk5MRXRCUVVzc1MwRkJUQ3hEUVVGWExFVkJRVmdzUTBGQlRpeERRVVJOTzBGQlJWWXNVVUZCU1N4VlFVRlZMRXRCUVVzc1NVRkJUQ3hEUVVGVkxFZEJRVllzUTBGQll5eEhRVUZrTEVOQlFWWXNRMEZHVFRzN1FVRkpWaXhYUVVGUExFOUJRVThzU1VGQlVDeERRVUZaTEZGQlFWRXNTVUZCVWl4RFFVRnVRaXhEUVVwVk8wZEJRVm83TzBGQlQwRXNVVUZCVFN4RlFVRk9MRVZCUVZVc1IwRkJWaXhGUVVGak8wRkJRMW9zVVVGQlNTeE5RVUZOTEV0QlFVc3NTMEZCVEN4RFFVRlhMRVZCUVZnc1EwRkJUaXhEUVVSUk8wRkJSVm9zVVVGQlNTeFZRVUZWTEV0QlFVc3NTVUZCVEN4RFFVRlZMRWRCUVZZc1EwRkJZeXhIUVVGa0xFTkJRVllzUTBGR1VUczdRVUZKV2l4UlFVRkhMRTlCUVU4c1NVRkJVQ3hGUVVGWk8wRkJRMklzWVVGQlR5eFJRVUZSTEVsQlFWSXNRMEZCWVN4SFFVRmlMRU5CUVZBc1EwRkVZVHRMUVVGbUxFMUJSVXM3UVVGRFNDeGpRVUZSTEVsQlFWSXNSMEZCWlN4RlFVRm1MRU5CUkVjN1MwRkdURHRIUVVwR08wTkJla2xHT3p0QlFYRktRU3hsUVVGbExHRkJRV1lpTENKbWFXeGxJam9pYkdsaUwyTnZjbVV2Y0hKdlkyVnpjMlZ6TDNCeWIyTmxjM05mYzNsemRHVnRMbXB6SWl3aWMyOTFjbU5sYzBOdmJuUmxiblFpT2xzaUx5b2dRR1pzYjNjZ0tpOWNibHdpZFhObElITjBjbWxqZEZ3aU8xeHVYRzVwYlhCdmNuUWdUV0ZwYkdKdmVDQm1jbTl0SUZ3aUxpOXRZV2xzWW05NFhDSTdYRzVwYlhCdmNuUWdVSEp2WTJWemN5Qm1jbTl0SUZ3aUxpOXdjbTlqWlhOelhDSTdYRzVwYlhCdmNuUWdVM1JoZEdWeklHWnliMjBnWENJdUwzTjBZWFJsYzF3aU8xeHVhVzF3YjNKMElDb2dZWE1nVUhKcGJXbDBhWFpsY3lCbWNtOXRJRndpTGk0dmNISnBiV2wwYVhabGMxd2lPMXh1WEc1amJHRnpjeUJRY205alpYTnpVM2x6ZEdWdElIdGNibHh1SUNCamIyNXpkSEoxWTNSdmNpZ3BlMXh1SUNBZ0lIUm9hWE11Y0dsa2N5QTlJRzVsZHlCTllYQW9LVHRjYmlBZ0lDQjBhR2x6TG0xaGFXeGliM2hsY3lBOUlHNWxkeUJOWVhBb0tUdGNiaUFnSUNCMGFHbHpMbTVoYldWeklEMGdibVYzSUUxaGNDZ3BPMXh1SUNBZ0lIUm9hWE11YkdsdWEzTWdQU0J1WlhjZ1RXRndLQ2s3WEc1Y2JpQWdJQ0IwYUdsekxtTjFjbkpsYm5SZmNISnZZMlZ6Y3lBOUlHNTFiR3c3WEc0Z0lDQWdkR2hwY3k1emRYTndaVzVrWldRZ1BTQnVaWGNnVFdGd0tDazdYRzVjYmlBZ0lDQjBhR2x6TG0xaGFXNWZjSEp2WTJWemMxOXdhV1FnUFNCMGFHbHpMbk53WVhkdUtDazdYRzRnSUNBZ2RHaHBjeTV6WlhSZlkzVnljbVZ1ZENoMGFHbHpMbTFoYVc1ZmNISnZZMlZ6YzE5d2FXUXBPMXh1SUNCOVhHNWNiaUFnYzNCaGQyNG9LWHRjYmlBZ0lDQnlaWFIxY200Z2RHaHBjeTVoWkdSZmNISnZZeWhtWVd4elpTa3VjR2xrTzF4dUlDQjlYRzVjYmlBZ2MzQmhkMjVmYkdsdWF5Z3BlMXh1SUNBZ0lISmxkSFZ5YmlCMGFHbHpMbUZrWkY5d2NtOWpLSFJ5ZFdVcExuQnBaRHRjYmlBZ2ZWeHVYRzRnSUd4cGJtc29jR2xrS1h0Y2JpQWdJQ0IwYUdsekxteHBibXR6TG1kbGRDaDBhR2x6TG5CcFpDZ3BLUzVoWkdRb2NHbGtLVHRjYmlBZ0lDQjBhR2x6TG14cGJtdHpMbWRsZENod2FXUXBMbUZrWkNoMGFHbHpMbkJwWkNncEtUdGNiaUFnZlZ4dVhHNGdJSFZ1YkdsdWF5aHdhV1FwZTF4dUlDQWdJSFJvYVhNdWJHbHVhM011WjJWMEtIUm9hWE11Y0dsa0tDa3BMbVJsYkdWMFpTaHdhV1FwTzF4dUlDQWdJSFJvYVhNdWJHbHVhM011WjJWMEtIQnBaQ2t1WkdWc1pYUmxLSFJvYVhNdWNHbGtLQ2twTzF4dUlDQjlYRzVjYmlBZ2MyVjBYMk4xY25KbGJuUW9hV1FwZTF4dUlDQWdJR3hsZENCd2FXUWdQU0IwYUdsekxuQnBaRzltS0dsa0tUdGNiaUFnSUNCcFppaHdhV1FnSVQwOUlHNTFiR3dwZTF4dUlDQWdJQ0FnZEdocGN5NWpkWEp5Wlc1MFgzQnliMk5sYzNNZ1BTQjBhR2x6TG5CcFpITXVaMlYwS0hCcFpDazdYRzRnSUNBZ0lDQjBhR2x6TG1OMWNuSmxiblJmY0hKdlkyVnpjeTV6ZEdGMGRYTWdQU0JUZEdGMFpYTXVVbFZPVGtsT1J6dGNiaUFnSUNCOVhHNGdJSDFjYmx4dUlDQmhaR1JmY0hKdll5aHNhVzVyWldRcGUxeHVJQ0FnSUd4bGRDQnVaWGR3YVdRZ1BTQnVaWGNnVUhKcGJXbDBhWFpsY3k1UVNVUW9LVHRjYmlBZ0lDQnNaWFFnYldGcGJHSnZlQ0E5SUc1bGR5Qk5ZV2xzWW05NEtDazdYRzRnSUNBZ2JHVjBJRzVsZDNCeWIyTWdQU0J1WlhjZ1VISnZZMlZ6Y3lodVpYZHdhV1FzSUcxaGFXeGliM2dwTzF4dVhHNGdJQ0FnZEdocGN5NXdhV1J6TG5ObGRDaHVaWGR3YVdRc0lHNWxkM0J5YjJNcE8xeHVJQ0FnSUhSb2FYTXViV0ZwYkdKdmVHVnpMbk5sZENodVpYZHdhV1FzSUcxaGFXeGliM2dwTzF4dUlDQWdJSFJvYVhNdWJHbHVhM011YzJWMEtHNWxkM0JwWkN3Z2JtVjNJRk5sZENncEtUdGNibHh1SUNBZ0lHbG1LR3hwYm10bFpDbDdYRzRnSUNBZ0lDQjBhR2x6TG14cGJtc29ibVYzY0dsa0tUdGNiaUFnSUNCOVhHNWNiaUFnSUNCeVpYUjFjbTRnYm1WM2NISnZZenRjYmlBZ2ZWeHVYRzRnSUhKbGJXOTJaVjl3Y205aktIQnBaQ2w3WEc0Z0lDQWdkR2hwY3k1d2FXUnpMbVJsYkdWMFpTaHdhV1FwTzF4dUlDQWdJSFJvYVhNdWRXNXlaV2RwYzNSbGNpaHdhV1FwTzF4dVhHNGdJQ0FnYVdZb2RHaHBjeTVzYVc1cmN5NW9ZWE1vY0dsa0tTbDdYRzRnSUNBZ0lDQm1iM0lnS0d4bGRDQnNhVzVyY0dsa0lHOW1JSFJvYVhNdWJHbHVhM011WjJWMEtIQnBaQ2twSUh0Y2JpQWdJQ0FnSUNBZ2RHaHBjeTVzYVc1cmN5NW5aWFFvYkdsdWEzQnBaQ2t1WkdWc1pYUmxLSEJwWkNrN1hHNGdJQ0FnSUNCOVhHNWNiaUFnSUNBZ0lIUm9hWE11YkdsdWEzTXVaR1ZzWlhSbEtIQnBaQ2s3WEc0Z0lDQWdmVnh1SUNCOVhHNWNiaUFnWlhocGRDaHBaQ2w3WEc0Z0lDQWdiR1YwSUhCcFpDQTlJSFJvYVhNdWNHbGtiMllvYVdRcE8xeHVJQ0FnSUhSb2FYTXVjbVZ0YjNabFgzQnliMk1vYVdRcE8xeHVJQ0I5WEc1Y2JpQWdjbVZuYVhOMFpYSW9ibUZ0WlN3Z2NHbGtLWHRjYmlBZ0lDQnBaaWdoZEdocGN5NXVZVzFsY3k1b1lYTW9ibUZ0WlNrcGUxeHVJQ0FnSUNBZ2RHaHBjeTV1WVcxbGN5NXpaWFFvYm1GdFpTd2djR2xrS1Z4dUlDQWdJQ0FnY21WMGRYSnVJRzVoYldVN1hHNGdJQ0FnZldWc2MyVjdYRzRnSUNBZ0lDQjBhSEp2ZHlCdVpYY2dSWEp5YjNJb1hDSk9ZVzFsSUdseklHRnNjbVZoWkhrZ2NtVm5hWE4wWlhKbFpDQjBieUJoYm05MGFHVnlJSEJ5YjJObGMzTmNJaWs3WEc0Z0lDQWdmVnh1SUNCOVhHNWNiaUFnY21WbmFYTjBaWEpsWkNodVlXMWxLWHRjYmlBZ0lDQnlaWFIxY200Z2RHaHBjeTV1WVcxbGN5NW9ZWE1vYm1GdFpTa2dQeUIwYUdsekxtNWhiV1Z6TG1kbGRDaHVZVzFsS1NBNklHNTFiR3c3WEc0Z0lIMWNibHh1SUNCMWJuSmxaMmx6ZEdWeUtIQnBaQ2w3WEc0Z0lDQWdabTl5S0d4bGRDQnVZVzFsSUc5bUlIUm9hWE11Ym1GdFpYTXVhMlY1Y3lncEtYdGNiaUFnSUNBZ0lHbG1LSFJvYVhNdWJtRnRaWE11YUdGektHNWhiV1VwSUNZbUlIUm9hWE11Ym1GdFpYTXVaMlYwS0c1aGJXVXBJRDA5UFNCd2FXUXBlMXh1SUNBZ0lDQWdJQ0IwYUdsekxtNWhiV1Z6TG1SbGJHVjBaU2h1WVcxbEtUdGNiaUFnSUNBZ0lIMWNiaUFnSUNCOVhHNGdJSDFjYmx4dUlDQndhV1FvS1h0Y2JpQWdJQ0J5WlhSMWNtNGdkR2hwY3k1amRYSnlaVzUwWDNCeWIyTmxjM011Y0dsa08xeHVJQ0I5WEc1Y2JpQWdjR2xrYjJZb2FXUXBlMXh1SUNBZ0lHbG1JQ2hwWkNCcGJuTjBZVzVqWlc5bUlGQnlhVzFwZEdsMlpYTXVVRWxFS1NCN1hHNGdJQ0FnSUNBZ2NtVjBkWEp1SUhSb2FYTXVjR2xrY3k1b1lYTW9hV1FwSUQ4Z2FXUWdPaUJ1ZFd4c08xeHVJQ0FnSUgwZ1pXeHpaU0JwWmlBb2FXUWdhVzV6ZEdGdVkyVnZaaUJRY205alpYTnpLU0I3WEc0Z0lDQWdJQ0FnY21WMGRYSnVJR2xrTG5CcFpEdGNiaUFnSUNCOUlHVnNjMlVnZTF4dUlDQWdJQ0FnSUd4bGRDQndhV1FnUFNCMGFHbHpMbkpsWjJsemRHVnlaV1FvYVdRcE8xeHVJQ0FnSUNBZ0lHbG1JQ2h3YVdRZ1BUMDlJRzUxYkd3cFhHNGdJQ0FnSUNBZ0lDQWdkR2h5YjNjb1hDSlFjbTlqWlhOeklHNWhiV1VnYm05MElISmxaMmx6ZEdWeVpXUTZJRndpSUNzZ2FXUWdLeUJjSWlBb1hDSWdLeUIwZVhCbGIyWW9hV1FwSUNzZ1hDSXBYQ0lwTzF4dUlDQWdJQ0FnSUhKbGRIVnliaUJ3YVdRN1hHNGdJQ0FnZlZ4dUlDQjlYRzVjYmlBZ2NIVjBLR2xrTENCclpYa3NJSFpoYkhWbEtYdGNiaUFnSUNCc1pYUWdjR2xrSUQwZ2RHaHBjeTV3YVdSdlppaHBaQ2s3WEc0Z0lDQWdiR1YwSUhCeWIyTmxjM01nUFNCMGFHbHpMbkJwWkhNdVoyVjBLSEJwWkNrN1hHNGdJQ0FnY0hKdlkyVnpjeTVrYVdOMFcydGxlVjBnUFNCMllXeDFaVHRjYmlBZ2ZWeHVYRzRnSUdkbGRDaHBaQ3dnYTJWNUtYdGNiaUFnSUNCc1pYUWdjR2xrSUQwZ2RHaHBjeTV3YVdSdlppaHBaQ2s3WEc0Z0lDQWdiR1YwSUhCeWIyTmxjM01nUFNCMGFHbHpMbkJwWkhNdVoyVjBLSEJwWkNrN1hHNWNiaUFnSUNCcFppaHJaWGtnSVQwZ2JuVnNiQ2w3WEc0Z0lDQWdJQ0J5WlhSMWNtNGdjSEp2WTJWemN5NWthV04wVzJ0bGVWMDdYRzRnSUNBZ2ZXVnNjMlY3WEc0Z0lDQWdJQ0J5WlhSMWNtNGdjSEp2WTJWemN5NWthV04wTzF4dUlDQWdJSDFjYmlBZ2ZWeHVYRzRnSUdkbGRGOXJaWGx6S0dsa0tYdGNiaUFnSUNCc1pYUWdjR2xrSUQwZ2RHaHBjeTV3YVdSdlppaHBaQ2s3WEc0Z0lDQWdiR1YwSUhCeWIyTmxjM01nUFNCMGFHbHpMbkJwWkhNdVoyVjBLSEJwWkNrN1hHNWNiaUFnSUNCeVpYUjFjbTRnVDJKcVpXTjBMbXRsZVhNb2NISnZZMlZ6Y3k1a2FXTjBLVHRjYmlBZ2ZWeHVYRzRnSUdWeVlYTmxLR2xrTENCclpYa3BlMXh1SUNBZ0lHeGxkQ0J3YVdRZ1BTQjBhR2x6TG5CcFpHOW1LR2xrS1R0Y2JpQWdJQ0JzWlhRZ2NISnZZMlZ6Y3lBOUlIUm9hWE11Y0dsa2N5NW5aWFFvY0dsa0tUdGNibHh1SUNBZ0lHbG1LR3RsZVNBaFBTQnVkV3hzS1h0Y2JpQWdJQ0FnSUdSbGJHVjBaU0J3Y205alpYTnpMbVJwWTNSYmEyVjVYVHRjYmlBZ0lDQjlaV3h6Wlh0Y2JpQWdJQ0FnSUhCeWIyTmxjM011WkdsamRDQTlJSHQ5TzF4dUlDQWdJSDFjYmlBZ2ZWeHVmVnh1WEc1bGVIQnZjblFnWkdWbVlYVnNkQ0JRY205alpYTnpVM2x6ZEdWdE8xeHVJbDBzSW5OdmRYSmpaVkp2YjNRaU9pSXZjMjkxY21ObEx5SjlcbiIsImNsYXNzIEJpdFN0cmluZyB7XG4gIGNvbnN0cnVjdG9yKC4uLmFyZ3MpIHtcbiAgICB0aGlzLnZhbHVlID0gT2JqZWN0LmZyZWV6ZSh0aGlzLnByb2Nlc3MoYXJncykpO1xuICAgIHRoaXMubGVuZ3RoID0gdGhpcy52YWx1ZS5sZW5ndGg7XG4gICAgdGhpcy5iaXRfc2l6ZSA9IHRoaXMubGVuZ3RoICogODtcbiAgICB0aGlzLmJ5dGVfc2l6ZSA9IHRoaXMubGVuZ3RoO1xuICB9XG5cbiAgZ2V0KGluZGV4KSB7XG4gICAgcmV0dXJuIHRoaXMudmFsdWVbaW5kZXhdO1xuICB9XG5cbiAgY291bnQoKSB7XG4gICAgcmV0dXJuIHRoaXMudmFsdWUubGVuZ3RoO1xuICB9XG5cbiAgc2xpY2Uoc3RhcnQsIGVuZCA9IG51bGwpIHtcbiAgICBsZXQgcyA9IHRoaXMudmFsdWUuc2xpY2Uoc3RhcnQsIGVuZCk7XG4gICAgbGV0IG1zID0gcy5tYXAoZWxlbSA9PiBCaXRTdHJpbmcuaW50ZWdlcihlbGVtKSk7XG4gICAgcmV0dXJuIG5ldyBCaXRTdHJpbmcoLi4ubXMpO1xuICB9XG5cbiAgW1N5bWJvbC5pdGVyYXRvcl0oKSB7XG4gICAgcmV0dXJuIHRoaXMudmFsdWVbU3ltYm9sLml0ZXJhdG9yXSgpO1xuICB9XG5cbiAgdG9TdHJpbmcoKSB7XG4gICAgdmFyIGksXG4gICAgICAgIHMgPSBcIlwiO1xuICAgIGZvciAoaSA9IDA7IGkgPCB0aGlzLmNvdW50KCk7IGkrKykge1xuICAgICAgaWYgKHMgIT09IFwiXCIpIHtcbiAgICAgICAgcyArPSBcIiwgXCI7XG4gICAgICB9XG4gICAgICBzICs9IHRoaXMuZ2V0KGkpLnRvU3RyaW5nKCk7XG4gICAgfVxuXG4gICAgcmV0dXJuIFwiPDxcIiArIHMgKyBcIj4+XCI7XG4gIH1cblxuICBwcm9jZXNzKGJpdFN0cmluZ1BhcnRzKSB7XG4gICAgbGV0IHByb2Nlc3NlZF92YWx1ZXMgPSBbXTtcblxuICAgIHZhciBpO1xuICAgIGZvciAoaSA9IDA7IGkgPCBiaXRTdHJpbmdQYXJ0cy5sZW5ndGg7IGkrKykge1xuICAgICAgbGV0IHByb2Nlc3NlZF92YWx1ZSA9IHRoaXNbJ3Byb2Nlc3NfJyArIGJpdFN0cmluZ1BhcnRzW2ldLnR5cGVdKGJpdFN0cmluZ1BhcnRzW2ldKTtcblxuICAgICAgZm9yIChsZXQgYXR0ciBvZiBiaXRTdHJpbmdQYXJ0c1tpXS5hdHRyaWJ1dGVzKSB7XG4gICAgICAgIHByb2Nlc3NlZF92YWx1ZSA9IHRoaXNbJ3Byb2Nlc3NfJyArIGF0dHJdKHByb2Nlc3NlZF92YWx1ZSk7XG4gICAgICB9XG5cbiAgICAgIHByb2Nlc3NlZF92YWx1ZXMgPSBwcm9jZXNzZWRfdmFsdWVzLmNvbmNhdChwcm9jZXNzZWRfdmFsdWUpO1xuICAgIH1cblxuICAgIHJldHVybiBwcm9jZXNzZWRfdmFsdWVzO1xuICB9XG5cbiAgcHJvY2Vzc19pbnRlZ2VyKHZhbHVlKSB7XG4gICAgcmV0dXJuIHZhbHVlLnZhbHVlO1xuICB9XG5cbiAgcHJvY2Vzc19mbG9hdCh2YWx1ZSkge1xuICAgIGlmICh2YWx1ZS5zaXplID09PSA2NCkge1xuICAgICAgcmV0dXJuIEJpdFN0cmluZy5mbG9hdDY0VG9CeXRlcyh2YWx1ZS52YWx1ZSk7XG4gICAgfSBlbHNlIGlmICh2YWx1ZS5zaXplID09PSAzMikge1xuICAgICAgcmV0dXJuIEJpdFN0cmluZy5mbG9hdDMyVG9CeXRlcyh2YWx1ZS52YWx1ZSk7XG4gICAgfVxuXG4gICAgdGhyb3cgbmV3IEVycm9yKCdJbnZhbGlkIHNpemUgZm9yIGZsb2F0Jyk7XG4gIH1cblxuICBwcm9jZXNzX2JpdHN0cmluZyh2YWx1ZSkge1xuICAgIHJldHVybiB2YWx1ZS52YWx1ZS52YWx1ZTtcbiAgfVxuXG4gIHByb2Nlc3NfYmluYXJ5KHZhbHVlKSB7XG4gICAgcmV0dXJuIEJpdFN0cmluZy50b1VURjhBcnJheSh2YWx1ZS52YWx1ZSk7XG4gIH1cblxuICBwcm9jZXNzX3V0ZjgodmFsdWUpIHtcbiAgICByZXR1cm4gQml0U3RyaW5nLnRvVVRGOEFycmF5KHZhbHVlLnZhbHVlKTtcbiAgfVxuXG4gIHByb2Nlc3NfdXRmMTYodmFsdWUpIHtcbiAgICByZXR1cm4gQml0U3RyaW5nLnRvVVRGMTZBcnJheSh2YWx1ZS52YWx1ZSk7XG4gIH1cblxuICBwcm9jZXNzX3V0ZjMyKHZhbHVlKSB7XG4gICAgcmV0dXJuIEJpdFN0cmluZy50b1VURjMyQXJyYXkodmFsdWUudmFsdWUpO1xuICB9XG5cbiAgcHJvY2Vzc19zaWduZWQodmFsdWUpIHtcbiAgICByZXR1cm4gbmV3IFVpbnQ4QXJyYXkoW3ZhbHVlXSlbMF07XG4gIH1cblxuICBwcm9jZXNzX3Vuc2lnbmVkKHZhbHVlKSB7XG4gICAgcmV0dXJuIHZhbHVlO1xuICB9XG5cbiAgcHJvY2Vzc19uYXRpdmUodmFsdWUpIHtcbiAgICByZXR1cm4gdmFsdWU7XG4gIH1cblxuICBwcm9jZXNzX2JpZyh2YWx1ZSkge1xuICAgIHJldHVybiB2YWx1ZTtcbiAgfVxuXG4gIHByb2Nlc3NfbGl0dGxlKHZhbHVlKSB7XG4gICAgcmV0dXJuIHZhbHVlLnJldmVyc2UoKTtcbiAgfVxuXG4gIHByb2Nlc3Nfc2l6ZSh2YWx1ZSkge1xuICAgIHJldHVybiB2YWx1ZTtcbiAgfVxuXG4gIHByb2Nlc3NfdW5pdCh2YWx1ZSkge1xuICAgIHJldHVybiB2YWx1ZTtcbiAgfVxuXG4gIHN0YXRpYyBpbnRlZ2VyKHZhbHVlKSB7XG4gICAgcmV0dXJuIEJpdFN0cmluZy53cmFwKHZhbHVlLCB7ICd0eXBlJzogJ2ludGVnZXInLCAndW5pdCc6IDEsICdzaXplJzogOCB9KTtcbiAgfVxuXG4gIHN0YXRpYyBmbG9hdCh2YWx1ZSkge1xuICAgIHJldHVybiBCaXRTdHJpbmcud3JhcCh2YWx1ZSwgeyAndHlwZSc6ICdmbG9hdCcsICd1bml0JzogMSwgJ3NpemUnOiA2NCB9KTtcbiAgfVxuXG4gIHN0YXRpYyBiaXRzdHJpbmcodmFsdWUpIHtcbiAgICByZXR1cm4gQml0U3RyaW5nLndyYXAodmFsdWUsIHsgJ3R5cGUnOiAnYml0c3RyaW5nJywgJ3VuaXQnOiAxLCAnc2l6ZSc6IHZhbHVlLmJpdF9zaXplIH0pO1xuICB9XG5cbiAgc3RhdGljIGJpdHModmFsdWUpIHtcbiAgICByZXR1cm4gQml0U3RyaW5nLmJpdHN0cmluZyh2YWx1ZSk7XG4gIH1cblxuICBzdGF0aWMgYmluYXJ5KHZhbHVlKSB7XG4gICAgcmV0dXJuIEJpdFN0cmluZy53cmFwKHZhbHVlLCB7ICd0eXBlJzogJ2JpbmFyeScsICd1bml0JzogOCwgJ3NpemUnOiB2YWx1ZS5sZW5ndGggfSk7XG4gIH1cblxuICBzdGF0aWMgYnl0ZXModmFsdWUpIHtcbiAgICByZXR1cm4gQml0U3RyaW5nLmJpbmFyeSh2YWx1ZSk7XG4gIH1cblxuICBzdGF0aWMgdXRmOCh2YWx1ZSkge1xuICAgIHJldHVybiBCaXRTdHJpbmcud3JhcCh2YWx1ZSwgeyAndHlwZSc6ICd1dGY4JywgJ3VuaXQnOiAxLCAnc2l6ZSc6IHZhbHVlLmxlbmd0aCB9KTtcbiAgfVxuXG4gIHN0YXRpYyB1dGYxNih2YWx1ZSkge1xuICAgIHJldHVybiBCaXRTdHJpbmcud3JhcCh2YWx1ZSwgeyAndHlwZSc6ICd1dGYxNicsICd1bml0JzogMSwgJ3NpemUnOiB2YWx1ZS5sZW5ndGggKiAyIH0pO1xuICB9XG5cbiAgc3RhdGljIHV0ZjMyKHZhbHVlKSB7XG4gICAgcmV0dXJuIEJpdFN0cmluZy53cmFwKHZhbHVlLCB7ICd0eXBlJzogJ3V0ZjMyJywgJ3VuaXQnOiAxLCAnc2l6ZSc6IHZhbHVlLmxlbmd0aCAqIDQgfSk7XG4gIH1cblxuICBzdGF0aWMgc2lnbmVkKHZhbHVlKSB7XG4gICAgcmV0dXJuIEJpdFN0cmluZy53cmFwKHZhbHVlLCB7fSwgJ3NpZ25lZCcpO1xuICB9XG5cbiAgc3RhdGljIHVuc2lnbmVkKHZhbHVlKSB7XG4gICAgcmV0dXJuIEJpdFN0cmluZy53cmFwKHZhbHVlLCB7fSwgJ3Vuc2lnbmVkJyk7XG4gIH1cblxuICBzdGF0aWMgbmF0aXZlKHZhbHVlKSB7XG4gICAgcmV0dXJuIEJpdFN0cmluZy53cmFwKHZhbHVlLCB7fSwgJ25hdGl2ZScpO1xuICB9XG5cbiAgc3RhdGljIGJpZyh2YWx1ZSkge1xuICAgIHJldHVybiBCaXRTdHJpbmcud3JhcCh2YWx1ZSwge30sICdiaWcnKTtcbiAgfVxuXG4gIHN0YXRpYyBsaXR0bGUodmFsdWUpIHtcbiAgICByZXR1cm4gQml0U3RyaW5nLndyYXAodmFsdWUsIHt9LCAnbGl0dGxlJyk7XG4gIH1cblxuICBzdGF0aWMgc2l6ZSh2YWx1ZSwgY291bnQpIHtcbiAgICByZXR1cm4gQml0U3RyaW5nLndyYXAodmFsdWUsIHsgJ3NpemUnOiBjb3VudCB9KTtcbiAgfVxuXG4gIHN0YXRpYyB1bml0KHZhbHVlLCBjb3VudCkge1xuICAgIHJldHVybiBCaXRTdHJpbmcud3JhcCh2YWx1ZSwgeyAndW5pdCc6IGNvdW50IH0pO1xuICB9XG5cbiAgc3RhdGljIHdyYXAodmFsdWUsIG9wdCwgbmV3X2F0dHJpYnV0ZSA9IG51bGwpIHtcbiAgICBsZXQgdGhlX3ZhbHVlID0gdmFsdWU7XG5cbiAgICBpZiAoISh2YWx1ZSBpbnN0YW5jZW9mIE9iamVjdCkpIHtcbiAgICAgIHRoZV92YWx1ZSA9IHsgJ3ZhbHVlJzogdmFsdWUsICdhdHRyaWJ1dGVzJzogW10gfTtcbiAgICB9XG5cbiAgICB0aGVfdmFsdWUgPSBPYmplY3QuYXNzaWduKHRoZV92YWx1ZSwgb3B0KTtcblxuICAgIGlmIChuZXdfYXR0cmlidXRlKSB7XG4gICAgICB0aGVfdmFsdWUuYXR0cmlidXRlcy5wdXNoKG5ld19hdHRyaWJ1dGUpO1xuICAgIH1cblxuICAgIHJldHVybiB0aGVfdmFsdWU7XG4gIH1cblxuICBzdGF0aWMgdG9VVEY4QXJyYXkoc3RyKSB7XG4gICAgdmFyIHV0ZjggPSBbXTtcbiAgICBmb3IgKHZhciBpID0gMDsgaSA8IHN0ci5sZW5ndGg7IGkrKykge1xuICAgICAgdmFyIGNoYXJjb2RlID0gc3RyLmNoYXJDb2RlQXQoaSk7XG4gICAgICBpZiAoY2hhcmNvZGUgPCAweDgwKSB7XG4gICAgICAgIHV0ZjgucHVzaChjaGFyY29kZSk7XG4gICAgICB9IGVsc2UgaWYgKGNoYXJjb2RlIDwgMHg4MDApIHtcbiAgICAgICAgdXRmOC5wdXNoKDB4YzAgfCBjaGFyY29kZSA+PiA2LCAweDgwIHwgY2hhcmNvZGUgJiAweDNmKTtcbiAgICAgIH0gZWxzZSBpZiAoY2hhcmNvZGUgPCAweGQ4MDAgfHwgY2hhcmNvZGUgPj0gMHhlMDAwKSB7XG4gICAgICAgIHV0ZjgucHVzaCgweGUwIHwgY2hhcmNvZGUgPj4gMTIsIDB4ODAgfCBjaGFyY29kZSA+PiA2ICYgMHgzZiwgMHg4MCB8IGNoYXJjb2RlICYgMHgzZik7XG4gICAgICB9XG4gICAgICAvLyBzdXJyb2dhdGUgcGFpclxuICAgICAgZWxzZSB7XG4gICAgICAgICAgaSsrO1xuICAgICAgICAgIC8vIFVURi0xNiBlbmNvZGVzIDB4MTAwMDAtMHgxMEZGRkYgYnlcbiAgICAgICAgICAvLyBzdWJ0cmFjdGluZyAweDEwMDAwIGFuZCBzcGxpdHRpbmcgdGhlXG4gICAgICAgICAgLy8gMjAgYml0cyBvZiAweDAtMHhGRkZGRiBpbnRvIHR3byBoYWx2ZXNcbiAgICAgICAgICBjaGFyY29kZSA9IDB4MTAwMDAgKyAoKGNoYXJjb2RlICYgMHgzZmYpIDw8IDEwIHwgc3RyLmNoYXJDb2RlQXQoaSkgJiAweDNmZik7XG4gICAgICAgICAgdXRmOC5wdXNoKDB4ZjAgfCBjaGFyY29kZSA+PiAxOCwgMHg4MCB8IGNoYXJjb2RlID4+IDEyICYgMHgzZiwgMHg4MCB8IGNoYXJjb2RlID4+IDYgJiAweDNmLCAweDgwIHwgY2hhcmNvZGUgJiAweDNmKTtcbiAgICAgICAgfVxuICAgIH1cbiAgICByZXR1cm4gdXRmODtcbiAgfVxuXG4gIHN0YXRpYyB0b1VURjE2QXJyYXkoc3RyKSB7XG4gICAgdmFyIHV0ZjE2ID0gW107XG4gICAgZm9yICh2YXIgaSA9IDA7IGkgPCBzdHIubGVuZ3RoOyBpKyspIHtcbiAgICAgIHZhciBjb2RlUG9pbnQgPSBzdHIuY29kZVBvaW50QXQoaSk7XG5cbiAgICAgIGlmIChjb2RlUG9pbnQgPD0gMjU1KSB7XG4gICAgICAgIHV0ZjE2LnB1c2goMCk7XG4gICAgICAgIHV0ZjE2LnB1c2goY29kZVBvaW50KTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHV0ZjE2LnB1c2goY29kZVBvaW50ID4+IDggJiAweEZGKTtcbiAgICAgICAgdXRmMTYucHVzaChjb2RlUG9pbnQgJiAweEZGKTtcbiAgICAgIH1cbiAgICB9XG4gICAgcmV0dXJuIHV0ZjE2O1xuICB9XG5cbiAgc3RhdGljIHRvVVRGMzJBcnJheShzdHIpIHtcbiAgICB2YXIgdXRmMzIgPSBbXTtcbiAgICBmb3IgKHZhciBpID0gMDsgaSA8IHN0ci5sZW5ndGg7IGkrKykge1xuICAgICAgdmFyIGNvZGVQb2ludCA9IHN0ci5jb2RlUG9pbnRBdChpKTtcblxuICAgICAgaWYgKGNvZGVQb2ludCA8PSAyNTUpIHtcbiAgICAgICAgdXRmMzIucHVzaCgwKTtcbiAgICAgICAgdXRmMzIucHVzaCgwKTtcbiAgICAgICAgdXRmMzIucHVzaCgwKTtcbiAgICAgICAgdXRmMzIucHVzaChjb2RlUG9pbnQpO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgdXRmMzIucHVzaCgwKTtcbiAgICAgICAgdXRmMzIucHVzaCgwKTtcbiAgICAgICAgdXRmMzIucHVzaChjb2RlUG9pbnQgPj4gOCAmIDB4RkYpO1xuICAgICAgICB1dGYzMi5wdXNoKGNvZGVQb2ludCAmIDB4RkYpO1xuICAgICAgfVxuICAgIH1cbiAgICByZXR1cm4gdXRmMzI7XG4gIH1cblxuICAvL2h0dHA6Ly9zdGFja292ZXJmbG93LmNvbS9xdWVzdGlvbnMvMjAwMzQ5My9qYXZhc2NyaXB0LWZsb2F0LWZyb20tdG8tYml0c1xuICBzdGF0aWMgZmxvYXQzMlRvQnl0ZXMoZikge1xuICAgIHZhciBieXRlcyA9IFtdO1xuXG4gICAgdmFyIGJ1ZiA9IG5ldyBBcnJheUJ1ZmZlcig0KTtcbiAgICBuZXcgRmxvYXQzMkFycmF5KGJ1ZilbMF0gPSBmO1xuXG4gICAgbGV0IGludFZlcnNpb24gPSBuZXcgVWludDMyQXJyYXkoYnVmKVswXTtcblxuICAgIGJ5dGVzLnB1c2goaW50VmVyc2lvbiA+PiAyNCAmIDB4RkYpO1xuICAgIGJ5dGVzLnB1c2goaW50VmVyc2lvbiA+PiAxNiAmIDB4RkYpO1xuICAgIGJ5dGVzLnB1c2goaW50VmVyc2lvbiA+PiA4ICYgMHhGRik7XG4gICAgYnl0ZXMucHVzaChpbnRWZXJzaW9uICYgMHhGRik7XG5cbiAgICByZXR1cm4gYnl0ZXM7XG4gIH1cblxuICBzdGF0aWMgZmxvYXQ2NFRvQnl0ZXMoZikge1xuICAgIHZhciBieXRlcyA9IFtdO1xuXG4gICAgdmFyIGJ1ZiA9IG5ldyBBcnJheUJ1ZmZlcig4KTtcbiAgICBuZXcgRmxvYXQ2NEFycmF5KGJ1ZilbMF0gPSBmO1xuXG4gICAgdmFyIGludFZlcnNpb24xID0gbmV3IFVpbnQzMkFycmF5KGJ1ZilbMF07XG4gICAgdmFyIGludFZlcnNpb24yID0gbmV3IFVpbnQzMkFycmF5KGJ1ZilbMV07XG5cbiAgICBieXRlcy5wdXNoKGludFZlcnNpb24yID4+IDI0ICYgMHhGRik7XG4gICAgYnl0ZXMucHVzaChpbnRWZXJzaW9uMiA+PiAxNiAmIDB4RkYpO1xuICAgIGJ5dGVzLnB1c2goaW50VmVyc2lvbjIgPj4gOCAmIDB4RkYpO1xuICAgIGJ5dGVzLnB1c2goaW50VmVyc2lvbjIgJiAweEZGKTtcblxuICAgIGJ5dGVzLnB1c2goaW50VmVyc2lvbjEgPj4gMjQgJiAweEZGKTtcbiAgICBieXRlcy5wdXNoKGludFZlcnNpb24xID4+IDE2ICYgMHhGRik7XG4gICAgYnl0ZXMucHVzaChpbnRWZXJzaW9uMSA+PiA4ICYgMHhGRik7XG4gICAgYnl0ZXMucHVzaChpbnRWZXJzaW9uMSAmIDB4RkYpO1xuXG4gICAgcmV0dXJuIGJ5dGVzO1xuICB9XG59XG5cbmV4cG9ydCBkZWZhdWx0IEJpdFN0cmluZztcbi8vIyBzb3VyY2VNYXBwaW5nVVJMPWRhdGE6YXBwbGljYXRpb24vanNvbjtiYXNlNjQsZXlKMlpYSnphVzl1SWpvekxDSnpiM1Z5WTJWeklqcGJJbXhwWWk5amIzSmxMMkpwZEY5emRISnBibWN1YW5NaVhTd2libUZ0WlhNaU9sdGRMQ0p0WVhCd2FXNW5jeUk2SWtGQlFVRXNUVUZCVFN4VFFVRk9MRU5CUVdkQ08wRkJRMlFzWTBGQldTeEhRVUZITEVsQlFVZ3NSVUZCVVR0QlFVTnNRaXhUUVVGTExFdEJRVXdzUjBGQllTeFBRVUZQTEUxQlFWQXNRMEZCWXl4TFFVRkxMRTlCUVV3c1EwRkJZU3hKUVVGaUxFTkJRV1FzUTBGQllpeERRVVJyUWp0QlFVVnNRaXhUUVVGTExFMUJRVXdzUjBGQll5eExRVUZMTEV0QlFVd3NRMEZCVnl4TlFVRllMRU5CUmtrN1FVRkhiRUlzVTBGQlN5eFJRVUZNTEVkQlFXZENMRXRCUVVzc1RVRkJUQ3hIUVVGakxFTkJRV1FzUTBGSVJUdEJRVWxzUWl4VFFVRkxMRk5CUVV3c1IwRkJhVUlzUzBGQlN5eE5RVUZNTEVOQlNrTTdSMEZCY0VJN08wRkJUMEVzVFVGQlNTeExRVUZLTEVWQlFWVTdRVUZEVWl4WFFVRlBMRXRCUVVzc1MwRkJUQ3hEUVVGWExFdEJRVmdzUTBGQlVDeERRVVJSTzBkQlFWWTdPMEZCU1VFc1ZVRkJUenRCUVVOTUxGZEJRVThzUzBGQlN5eExRVUZNTEVOQlFWY3NUVUZCV0N4RFFVUkdPMGRCUVZBN08wRkJTVUVzVVVGQlRTeExRVUZPTEVWQlFXRXNUVUZCVFN4SlFVRk9MRVZCUVZjN1FVRkRkRUlzVVVGQlNTeEpRVUZKTEV0QlFVc3NTMEZCVEN4RFFVRlhMRXRCUVZnc1EwRkJhVUlzUzBGQmFrSXNSVUZCZDBJc1IwRkJlRUlzUTBGQlNpeERRVVJyUWp0QlFVVjBRaXhSUVVGSkxFdEJRVXNzUlVGQlJTeEhRVUZHTEVOQlFVMHNVVUZCVlN4VlFVRlZMRTlCUVZZc1EwRkJhMElzU1VGQmJFSXNRMEZCVml4RFFVRllMRU5CUm10Q08wRkJSM1JDTEZkQlFVOHNTVUZCU1N4VFFVRktMRU5CUVdNc1IwRkJSeXhGUVVGSUxFTkJRWEpDTEVOQlNITkNPMGRCUVhoQ096dEJRVTFCTEVkQlFVTXNUMEZCVHl4UlFVRlFMRWxCUVcxQ08wRkJRMnhDTEZkQlFVOHNTMEZCU3l4TFFVRk1MRU5CUVZjc1QwRkJUeXhSUVVGUUxFTkJRVmdzUlVGQlVDeERRVVJyUWp0SFFVRndRanM3UVVGSlFTeGhRVUZWTzBGQlExSXNVVUZCU1N4RFFVRktPMUZCUVU4c1NVRkJTU3hGUVVGS0xFTkJSRU03UVVGRlVpeFRRVUZMTEVsQlFVa3NRMEZCU2l4RlFVRlBMRWxCUVVrc1MwRkJTeXhMUVVGTUxFVkJRVW9zUlVGQmEwSXNSMEZCT1VJc1JVRkJiVU03UVVGRGFrTXNWVUZCU1N4TlFVRk5MRVZCUVU0c1JVRkJWVHRCUVVOYUxHRkJRVXNzU1VGQlRDeERRVVJaTzA5QlFXUTdRVUZIUVN4WFFVRkxMRXRCUVVzc1IwRkJUQ3hEUVVGVExFTkJRVlFzUlVGQldTeFJRVUZhTEVWQlFVd3NRMEZLYVVNN1MwRkJia003TzBGQlQwRXNWMEZCVHl4UFFVRlBMRU5CUVZBc1IwRkJWeXhKUVVGWUxFTkJWRU03UjBGQlZqczdRVUZaUVN4VlFVRlJMR05CUVZJc1JVRkJkVUk3UVVGRGNrSXNVVUZCU1N4dFFrRkJiVUlzUlVGQmJrSXNRMEZFYVVJN08wRkJSM0pDTEZGQlFVa3NRMEZCU2l4RFFVaHhRanRCUVVseVFpeFRRVUZMTEVsQlFVa3NRMEZCU2l4RlFVRlBMRWxCUVVrc1pVRkJaU3hOUVVGbUxFVkJRWFZDTEVkQlFYWkRMRVZCUVRSRE8wRkJRekZETEZWQlFVa3NhMEpCUVd0Q0xFdEJRVXNzWVVGQllTeGxRVUZsTEVOQlFXWXNSVUZCYTBJc1NVRkJiRUlzUTBGQmJFSXNRMEZCTUVNc1pVRkJaU3hEUVVGbUxFTkJRVEZETEVOQlFXeENMRU5CUkhORE96dEJRVWN4UXl4WFFVRkpMRWxCUVVrc1NVRkJTaXhKUVVGWkxHVkJRV1VzUTBGQlppeEZRVUZyUWl4VlFVRnNRaXhGUVVFMlFqdEJRVU16UXl3d1FrRkJhMElzUzBGQlN5eGhRVUZoTEVsQlFXSXNRMEZCVEN4RFFVRjNRaXhsUVVGNFFpeERRVUZzUWl4RFFVUXlRenRQUVVFM1F6czdRVUZKUVN4NVFrRkJiVUlzYVVKQlFXbENMRTFCUVdwQ0xFTkJRWGRDTEdWQlFYaENMRU5CUVc1Q0xFTkJVREJETzB0QlFUVkRPenRCUVZWQkxGZEJRVThzWjBKQlFWQXNRMEZrY1VJN1IwRkJka0k3TzBGQmFVSkJMR3RDUVVGblFpeExRVUZvUWl4RlFVRnpRanRCUVVOd1FpeFhRVUZQTEUxQlFVMHNTMEZCVGl4RFFVUmhPMGRCUVhSQ096dEJRVWxCTEdkQ1FVRmpMRXRCUVdRc1JVRkJiMEk3UVVGRGJFSXNVVUZCUnl4TlFVRk5MRWxCUVU0c1MwRkJaU3hGUVVGbUxFVkJRV3RDTzBGQlEyNUNMR0ZCUVU4c1ZVRkJWU3hqUVVGV0xFTkJRWGxDTEUxQlFVMHNTMEZCVGl4RFFVRm9ReXhEUVVSdFFqdExRVUZ5UWl4TlFVVk5MRWxCUVVjc1RVRkJUU3hKUVVGT0xFdEJRV1VzUlVGQlppeEZRVUZyUWp0QlFVTjZRaXhoUVVGUExGVkJRVlVzWTBGQlZpeERRVUY1UWl4TlFVRk5MRXRCUVU0c1EwRkJhRU1zUTBGRWVVSTdTMEZCY2tJN08wRkJTVTRzVlVGQlRTeEpRVUZKTEV0QlFVb3NRMEZCVlN4M1FrRkJWaXhEUVVGT0xFTkJVR3RDTzBkQlFYQkNPenRCUVZWQkxHOUNRVUZyUWl4TFFVRnNRaXhGUVVGM1FqdEJRVU4wUWl4WFFVRlBMRTFCUVUwc1MwRkJUaXhEUVVGWkxFdEJRVm9zUTBGRVpUdEhRVUY0UWpzN1FVRkpRU3hwUWtGQlpTeExRVUZtTEVWQlFYRkNPMEZCUTI1Q0xGZEJRVThzVlVGQlZTeFhRVUZXTEVOQlFYTkNMRTFCUVUwc1MwRkJUaXhEUVVFM1FpeERRVVJ0UWp0SFFVRnlRanM3UVVGSlFTeGxRVUZoTEV0QlFXSXNSVUZCYlVJN1FVRkRha0lzVjBGQlR5eFZRVUZWTEZkQlFWWXNRMEZCYzBJc1RVRkJUU3hMUVVGT0xFTkJRVGRDTEVOQlJHbENPMGRCUVc1Q096dEJRVWxCTEdkQ1FVRmpMRXRCUVdRc1JVRkJiMEk3UVVGRGJFSXNWMEZCVHl4VlFVRlZMRmxCUVZZc1EwRkJkVUlzVFVGQlRTeExRVUZPTEVOQlFUbENMRU5CUkd0Q08wZEJRWEJDT3p0QlFVbEJMR2RDUVVGakxFdEJRV1FzUlVGQmIwSTdRVUZEYkVJc1YwRkJUeXhWUVVGVkxGbEJRVllzUTBGQmRVSXNUVUZCVFN4TFFVRk9MRU5CUVRsQ0xFTkJSR3RDTzBkQlFYQkNPenRCUVVsQkxHbENRVUZsTEV0QlFXWXNSVUZCY1VJN1FVRkRia0lzVjBGQlR5eEpRVUZMTEZWQlFVb3NRMEZCWlN4RFFVRkRMRXRCUVVRc1EwRkJaaXhEUVVGRUxFTkJRVEJDTEVOQlFURkNMRU5CUVZBc1EwRkViVUk3UjBGQmNrSTdPMEZCU1VFc2JVSkJRV2xDTEV0QlFXcENMRVZCUVhWQ08wRkJRM0pDTEZkQlFVOHNTMEZCVUN4RFFVUnhRanRIUVVGMlFqczdRVUZKUVN4cFFrRkJaU3hMUVVGbUxFVkJRWEZDTzBGQlEyNUNMRmRCUVU4c1MwRkJVQ3hEUVVSdFFqdEhRVUZ5UWpzN1FVRkpRU3hqUVVGWkxFdEJRVm9zUlVGQmEwSTdRVUZEYUVJc1YwRkJUeXhMUVVGUUxFTkJSR2RDTzBkQlFXeENPenRCUVVsQkxHbENRVUZsTEV0QlFXWXNSVUZCY1VJN1FVRkRia0lzVjBGQlR5eE5RVUZOTEU5QlFVNHNSVUZCVUN4RFFVUnRRanRIUVVGeVFqczdRVUZKUVN4bFFVRmhMRXRCUVdJc1JVRkJiVUk3UVVGRGFrSXNWMEZCVHl4TFFVRlFMRU5CUkdsQ08wZEJRVzVDT3p0QlFVbEJMR1ZCUVdFc1MwRkJZaXhGUVVGdFFqdEJRVU5xUWl4WFFVRlBMRXRCUVZBc1EwRkVhVUk3UjBGQmJrSTdPMEZCU1VFc1UwRkJUeXhQUVVGUUxFTkJRV1VzUzBGQlppeEZRVUZ4UWp0QlFVTnVRaXhYUVVGUExGVkJRVlVzU1VGQlZpeERRVUZsTEV0QlFXWXNSVUZCYzBJc1JVRkJSU3hSUVVGUkxGTkJRVklzUlVGQmJVSXNVVUZCVVN4RFFVRlNMRVZCUVZjc1VVRkJVU3hEUVVGU0xFVkJRWFJFTEVOQlFWQXNRMEZFYlVJN1IwRkJja0k3TzBGQlNVRXNVMEZCVHl4TFFVRlFMRU5CUVdFc1MwRkJZaXhGUVVGdFFqdEJRVU5xUWl4WFFVRlBMRlZCUVZVc1NVRkJWaXhEUVVGbExFdEJRV1lzUlVGQmMwSXNSVUZCUlN4UlFVRlJMRTlCUVZJc1JVRkJhVUlzVVVGQlVTeERRVUZTTEVWQlFWY3NVVUZCVVN4RlFVRlNMRVZCUVhCRUxFTkJRVkFzUTBGRWFVSTdSMEZCYmtJN08wRkJTVUVzVTBGQlR5eFRRVUZRTEVOQlFXbENMRXRCUVdwQ0xFVkJRWFZDTzBGQlEzSkNMRmRCUVU4c1ZVRkJWU3hKUVVGV0xFTkJRV1VzUzBGQlppeEZRVUZ6UWl4RlFVRkZMRkZCUVZFc1YwRkJVaXhGUVVGeFFpeFJRVUZSTEVOQlFWSXNSVUZCVnl4UlFVRlJMRTFCUVUwc1VVRkJUaXhGUVVGb1JTeERRVUZRTEVOQlJIRkNPMGRCUVhaQ096dEJRVWxCTEZOQlFVOHNTVUZCVUN4RFFVRlpMRXRCUVZvc1JVRkJhMEk3UVVGRGFFSXNWMEZCVHl4VlFVRlZMRk5CUVZZc1EwRkJiMElzUzBGQmNFSXNRMEZCVUN4RFFVUm5RanRIUVVGc1FqczdRVUZKUVN4VFFVRlBMRTFCUVZBc1EwRkJZeXhMUVVGa0xFVkJRVzlDTzBGQlEyeENMRmRCUVU4c1ZVRkJWU3hKUVVGV0xFTkJRV1VzUzBGQlppeEZRVUZ6UWl4RlFVRkZMRkZCUVZFc1VVRkJVaXhGUVVGclFpeFJRVUZSTEVOQlFWSXNSVUZCVnl4UlFVRlJMRTFCUVUwc1RVRkJUaXhGUVVFM1JDeERRVUZRTEVOQlJHdENPMGRCUVhCQ096dEJRVWxCTEZOQlFVOHNTMEZCVUN4RFFVRmhMRXRCUVdJc1JVRkJiVUk3UVVGRGFrSXNWMEZCVHl4VlFVRlZMRTFCUVZZc1EwRkJhVUlzUzBGQmFrSXNRMEZCVUN4RFFVUnBRanRIUVVGdVFqczdRVUZKUVN4VFFVRlBMRWxCUVZBc1EwRkJXU3hMUVVGYUxFVkJRV3RDTzBGQlEyaENMRmRCUVU4c1ZVRkJWU3hKUVVGV0xFTkJRV1VzUzBGQlppeEZRVUZ6UWl4RlFVRkZMRkZCUVZFc1RVRkJVaXhGUVVGblFpeFJRVUZSTEVOQlFWSXNSVUZCVnl4UlFVRlJMRTFCUVUwc1RVRkJUaXhGUVVFelJDeERRVUZRTEVOQlJHZENPMGRCUVd4Q096dEJRVWxCTEZOQlFVOHNTMEZCVUN4RFFVRmhMRXRCUVdJc1JVRkJiVUk3UVVGRGFrSXNWMEZCVHl4VlFVRlZMRWxCUVZZc1EwRkJaU3hMUVVGbUxFVkJRWE5DTEVWQlFVVXNVVUZCVVN4UFFVRlNMRVZCUVdsQ0xGRkJRVkVzUTBGQlVpeEZRVUZYTEZGQlFWRXNUVUZCVFN4TlFVRk9MRWRCUVdVc1EwRkJaaXhGUVVFMVJDeERRVUZRTEVOQlJHbENPMGRCUVc1Q096dEJRVWxCTEZOQlFVOHNTMEZCVUN4RFFVRmhMRXRCUVdJc1JVRkJiVUk3UVVGRGFrSXNWMEZCVHl4VlFVRlZMRWxCUVZZc1EwRkJaU3hMUVVGbUxFVkJRWE5DTEVWQlFVVXNVVUZCVVN4UFFVRlNMRVZCUVdsQ0xGRkJRVkVzUTBGQlVpeEZRVUZYTEZGQlFWRXNUVUZCVFN4TlFVRk9MRWRCUVdVc1EwRkJaaXhGUVVFMVJDeERRVUZRTEVOQlJHbENPMGRCUVc1Q096dEJRVWxCTEZOQlFVOHNUVUZCVUN4RFFVRmpMRXRCUVdRc1JVRkJiMEk3UVVGRGJFSXNWMEZCVHl4VlFVRlZMRWxCUVZZc1EwRkJaU3hMUVVGbUxFVkJRWE5DTEVWQlFYUkNMRVZCUVRCQ0xGRkJRVEZDTEVOQlFWQXNRMEZFYTBJN1IwRkJjRUk3TzBGQlNVRXNVMEZCVHl4UlFVRlFMRU5CUVdkQ0xFdEJRV2hDTEVWQlFYTkNPMEZCUTNCQ0xGZEJRVThzVlVGQlZTeEpRVUZXTEVOQlFXVXNTMEZCWml4RlFVRnpRaXhGUVVGMFFpeEZRVUV3UWl4VlFVRXhRaXhEUVVGUUxFTkJSRzlDTzBkQlFYUkNPenRCUVVsQkxGTkJRVThzVFVGQlVDeERRVUZqTEV0QlFXUXNSVUZCYjBJN1FVRkRiRUlzVjBGQlR5eFZRVUZWTEVsQlFWWXNRMEZCWlN4TFFVRm1MRVZCUVhOQ0xFVkJRWFJDTEVWQlFUQkNMRkZCUVRGQ0xFTkJRVkFzUTBGRWEwSTdSMEZCY0VJN08wRkJTVUVzVTBGQlR5eEhRVUZRTEVOQlFWY3NTMEZCV0N4RlFVRnBRanRCUVVObUxGZEJRVThzVlVGQlZTeEpRVUZXTEVOQlFXVXNTMEZCWml4RlFVRnpRaXhGUVVGMFFpeEZRVUV3UWl4TFFVRXhRaXhEUVVGUUxFTkJSR1U3UjBGQmFrSTdPMEZCU1VFc1UwRkJUeXhOUVVGUUxFTkJRV01zUzBGQlpDeEZRVUZ2UWp0QlFVTnNRaXhYUVVGUExGVkJRVlVzU1VGQlZpeERRVUZsTEV0QlFXWXNSVUZCYzBJc1JVRkJkRUlzUlVGQk1FSXNVVUZCTVVJc1EwRkJVQ3hEUVVSclFqdEhRVUZ3UWpzN1FVRkpRU3hUUVVGUExFbEJRVkFzUTBGQldTeExRVUZhTEVWQlFXMUNMRXRCUVc1Q0xFVkJRWGxDTzBGQlEzWkNMRmRCUVU4c1ZVRkJWU3hKUVVGV0xFTkJRV1VzUzBGQlppeEZRVUZ6UWl4RlFVRkRMRkZCUVZFc1MwRkJVaXhGUVVGMlFpeERRVUZRTEVOQlJIVkNPMGRCUVhwQ096dEJRVWxCTEZOQlFVOHNTVUZCVUN4RFFVRlpMRXRCUVZvc1JVRkJiVUlzUzBGQmJrSXNSVUZCZVVJN1FVRkRka0lzVjBGQlR5eFZRVUZWTEVsQlFWWXNRMEZCWlN4TFFVRm1MRVZCUVhOQ0xFVkJRVU1zVVVGQlVTeExRVUZTTEVWQlFYWkNMRU5CUVZBc1EwRkVkVUk3UjBGQmVrSTdPMEZCU1VFc1UwRkJUeXhKUVVGUUxFTkJRVmtzUzBGQldpeEZRVUZ0UWl4SFFVRnVRaXhGUVVGM1FpeG5Ra0ZCWjBJc1NVRkJhRUlzUlVGQmNVSTdRVUZETTBNc1VVRkJTU3haUVVGWkxFdEJRVm9zUTBGRWRVTTdPMEZCUnpORExGRkJRVWNzUlVGQlJTeHBRa0ZCYVVJc1RVRkJha0lzUTBGQlJpeEZRVUV5UWp0QlFVTTFRaXhyUWtGQldTeEZRVUZETEZOQlFWTXNTMEZCVkN4RlFVRm5RaXhqUVVGakxFVkJRV1FzUlVGQk4wSXNRMEZFTkVJN1MwRkJPVUk3TzBGQlNVRXNaMEpCUVZrc1QwRkJUeXhOUVVGUUxFTkJRV01zVTBGQlpDeEZRVUY1UWl4SFFVRjZRaXhEUVVGYUxFTkJVREpET3p0QlFWTXpReXhSUVVGSExHRkJRVWdzUlVGQmFVSTdRVUZEWml4blFrRkJWU3hWUVVGV0xFTkJRWEZDTEVsQlFYSkNMRU5CUVRCQ0xHRkJRVEZDTEVWQlJHVTdTMEZCYWtJN08wRkJTMEVzVjBGQlR5eFRRVUZRTEVOQlpESkRPMGRCUVRkRE96dEJRV2xDUVN4VFFVRlBMRmRCUVZBc1EwRkJiVUlzUjBGQmJrSXNSVUZCZDBJN1FVRkRkRUlzVVVGQlNTeFBRVUZQTEVWQlFWQXNRMEZFYTBJN1FVRkZkRUlzVTBGQlN5eEpRVUZKTEVsQlFVa3NRMEZCU2l4RlFVRlBMRWxCUVVrc1NVRkJTU3hOUVVGS0xFVkJRVmtzUjBGQmFFTXNSVUZCY1VNN1FVRkRia01zVlVGQlNTeFhRVUZYTEVsQlFVa3NWVUZCU2l4RFFVRmxMRU5CUVdZc1EwRkJXQ3hEUVVRclFqdEJRVVZ1UXl4VlFVRkpMRmRCUVZjc1NVRkJXQ3hGUVVGblFqdEJRVU5zUWl4aFFVRkxMRWxCUVV3c1EwRkJWU3hSUVVGV0xFVkJSR3RDTzA5QlFYQkNMRTFCUjBzc1NVRkJTU3hYUVVGWExFdEJRVmdzUlVGQmEwSTdRVUZEZWtJc1lVRkJTeXhKUVVGTUxFTkJRVlVzVDBGQlVTeFpRVUZaTEVOQlFWb3NSVUZEVWl4UFFVRlJMRmRCUVZjc1NVRkJXQ3hEUVVSc1FpeERRVVI1UWp0UFFVRjBRaXhOUVVsQkxFbEJRVWtzVjBGQlZ5eE5RVUZZTEVsQlFYRkNMRmxCUVZrc1RVRkJXaXhGUVVGdlFqdEJRVU5vUkN4aFFVRkxMRWxCUVV3c1EwRkJWU3hQUVVGUkxGbEJRVmtzUlVGQldpeEZRVU5TTEU5QlFWRXNVVUZCUXl4SlFVRlpMRU5CUVZvc1IwRkJhVUlzU1VGQmJFSXNSVUZEVWl4UFFVRlJMRmRCUVZjc1NVRkJXQ3hEUVVac1FpeERRVVJuUkRzN08wRkJRVGRETEZkQlRVRTdRVUZEU0RzN096dEJRVVJITEd0Q1FVdElMRWRCUVZjc1YwRkJWeXhEUVVGRkxGZEJRVmNzUzBGQldDeERRVUZFTEVsQlFYTkNMRVZCUVhSQ0xFZEJRMVlzU1VGQlNTeFZRVUZLTEVOQlFXVXNRMEZCWml4SlFVRnZRaXhMUVVGd1FpeERRVVJHTEVOQlRGSTdRVUZQU0N4bFFVRkxMRWxCUVV3c1EwRkJWU3hQUVVGUkxGbEJRVmtzUlVGQldpeEZRVU5TTEU5QlFWRXNVVUZCUXl4SlFVRlpMRVZCUVZvc1IwRkJhMElzU1VGQmJrSXNSVUZEVWl4UFFVRlJMRkZCUVVNc1NVRkJXU3hEUVVGYUxFZEJRV2xDTEVsQlFXeENMRVZCUTFJc1QwRkJVU3hYUVVGWExFbEJRVmdzUTBGSWJFSXNRMEZRUnp0VFFVNUJPMHRCVkZBN1FVRTBRa0VzVjBGQlR5eEpRVUZRTEVOQk9VSnpRanRIUVVGNFFqczdRVUZwUTBFc1UwRkJUeXhaUVVGUUxFTkJRVzlDTEVkQlFYQkNMRVZCUVhsQ08wRkJRM1pDTEZGQlFVa3NVVUZCVVN4RlFVRlNMRU5CUkcxQ08wRkJSWFpDTEZOQlFVc3NTVUZCU1N4SlFVRkpMRU5CUVVvc1JVRkJUeXhKUVVGSkxFbEJRVWtzVFVGQlNpeEZRVUZaTEVkQlFXaERMRVZCUVhGRE8wRkJRMjVETEZWQlFVa3NXVUZCV1N4SlFVRkpMRmRCUVVvc1EwRkJaMElzUTBGQmFFSXNRMEZCV2l4RFFVUXJRanM3UVVGSGJrTXNWVUZCUnl4aFFVRmhMRWRCUVdJc1JVRkJhVUk3UVVGRGJFSXNZMEZCVFN4SlFVRk9MRU5CUVZjc1EwRkJXQ3hGUVVSclFqdEJRVVZzUWl4alFVRk5MRWxCUVU0c1EwRkJWeXhUUVVGWUxFVkJSbXRDTzA5QlFYQkNMRTFCUjBzN1FVRkRTQ3hqUVVGTkxFbEJRVTRzUTBGQldTeFRRVUZETEVsQlFXRXNRMEZCWWl4SFFVRnJRaXhKUVVGdVFpeERRVUZhTEVOQlJFYzdRVUZGU0N4alFVRk5MRWxCUVU0c1EwRkJXU3haUVVGWkxFbEJRVm9zUTBGQldpeERRVVpITzA5QlNFdzdTMEZJUmp0QlFWZEJMRmRCUVU4c1MwRkJVQ3hEUVdKMVFqdEhRVUY2UWpzN1FVRnBRa0VzVTBGQlR5eFpRVUZRTEVOQlFXOUNMRWRCUVhCQ0xFVkJRWGxDTzBGQlEzWkNMRkZCUVVrc1VVRkJVU3hGUVVGU0xFTkJSRzFDTzBGQlJYWkNMRk5CUVVzc1NVRkJTU3hKUVVGSkxFTkJRVW9zUlVGQlR5eEpRVUZKTEVsQlFVa3NUVUZCU2l4RlFVRlpMRWRCUVdoRExFVkJRWEZETzBGQlEyNURMRlZCUVVrc1dVRkJXU3hKUVVGSkxGZEJRVW9zUTBGQlowSXNRMEZCYUVJc1EwRkJXaXhEUVVRclFqczdRVUZIYmtNc1ZVRkJSeXhoUVVGaExFZEJRV0lzUlVGQmFVSTdRVUZEYkVJc1kwRkJUU3hKUVVGT0xFTkJRVmNzUTBGQldDeEZRVVJyUWp0QlFVVnNRaXhqUVVGTkxFbEJRVTRzUTBGQlZ5eERRVUZZTEVWQlJtdENPMEZCUjJ4Q0xHTkJRVTBzU1VGQlRpeERRVUZYTEVOQlFWZ3NSVUZJYTBJN1FVRkpiRUlzWTBGQlRTeEpRVUZPTEVOQlFWY3NVMEZCV0N4RlFVcHJRanRQUVVGd1FpeE5RVXRMTzBGQlEwZ3NZMEZCVFN4SlFVRk9MRU5CUVZjc1EwRkJXQ3hGUVVSSE8wRkJSVWdzWTBGQlRTeEpRVUZPTEVOQlFWY3NRMEZCV0N4RlFVWkhPMEZCUjBnc1kwRkJUU3hKUVVGT0xFTkJRVmtzVTBGQlF5eEpRVUZoTEVOQlFXSXNSMEZCYTBJc1NVRkJia0lzUTBGQldpeERRVWhITzBGQlNVZ3NZMEZCVFN4SlFVRk9MRU5CUVZrc1dVRkJXU3hKUVVGYUxFTkJRVm9zUTBGS1J6dFBRVXhNTzB0QlNFWTdRVUZsUVN4WFFVRlBMRXRCUVZBc1EwRnFRblZDTzBkQlFYcENPenM3UVVGNFVHTXNVMEUyVVZBc1kwRkJVQ3hEUVVGelFpeERRVUYwUWl4RlFVRjVRanRCUVVOMlFpeFJRVUZKTEZGQlFWRXNSVUZCVWl4RFFVUnRRanM3UVVGSGRrSXNVVUZCU1N4TlFVRk5MRWxCUVVrc1YwRkJTaXhEUVVGblFpeERRVUZvUWl4RFFVRk9MRU5CU0cxQ08wRkJTWFpDTEZGQlFVc3NXVUZCU2l4RFFVRnBRaXhIUVVGcVFpeERRVUZFTEVOQlFYZENMRU5CUVhoQ0xFbEJRVFpDTEVOQlFUZENMRU5CU25WQ096dEJRVTEyUWl4UlFVRkpMR0ZCUVdFc1NVRkJTeXhYUVVGS0xFTkJRV2RDTEVkQlFXaENMRU5CUVVRc1EwRkJkVUlzUTBGQmRrSXNRMEZCWWl4RFFVNXRRanM3UVVGUmRrSXNWVUZCVFN4SlFVRk9MRU5CUVZrc1ZVRkJReXhKUVVGakxFVkJRV1FzUjBGQmIwSXNTVUZCY2tJc1EwRkJXaXhEUVZKMVFqdEJRVk4yUWl4VlFVRk5MRWxCUVU0c1EwRkJXU3hWUVVGRExFbEJRV01zUlVGQlpDeEhRVUZ2UWl4SlFVRnlRaXhEUVVGYUxFTkJWSFZDTzBGQlZYWkNMRlZCUVUwc1NVRkJUaXhEUVVGWkxGVkJRVU1zU1VGQll5eERRVUZrTEVkQlFXMUNMRWxCUVhCQ0xFTkJRVm9zUTBGV2RVSTdRVUZYZGtJc1ZVRkJUU3hKUVVGT0xFTkJRVmtzWVVGQllTeEpRVUZpTEVOQlFWb3NRMEZZZFVJN08wRkJZWFpDTEZkQlFVOHNTMEZCVUN4RFFXSjFRanRIUVVGNlFqczdRVUZuUWtFc1UwRkJUeXhqUVVGUUxFTkJRWE5DTEVOQlFYUkNMRVZCUVhsQ08wRkJRM1pDTEZGQlFVa3NVVUZCVVN4RlFVRlNMRU5CUkcxQ096dEJRVWQyUWl4UlFVRkpMRTFCUVUwc1NVRkJTU3hYUVVGS0xFTkJRV2RDTEVOQlFXaENMRU5CUVU0c1EwRkliVUk3UVVGSmRrSXNVVUZCU3l4WlFVRktMRU5CUVdsQ0xFZEJRV3BDTEVOQlFVUXNRMEZCZDBJc1EwRkJlRUlzU1VGQk5rSXNRMEZCTjBJc1EwRktkVUk3TzBGQlRYWkNMRkZCUVVrc1kwRkJZeXhKUVVGTExGZEJRVW9zUTBGQlowSXNSMEZCYUVJc1EwRkJSQ3hEUVVGMVFpeERRVUYyUWl4RFFVRmtMRU5CVG0xQ08wRkJUM1pDTEZGQlFVa3NZMEZCWXl4SlFVRkxMRmRCUVVvc1EwRkJaMElzUjBGQmFFSXNRMEZCUkN4RFFVRjFRaXhEUVVGMlFpeERRVUZrTEVOQlVHMUNPenRCUVZOMlFpeFZRVUZOTEVsQlFVNHNRMEZCV1N4WFFVRkRMRWxCUVdVc1JVRkJaaXhIUVVGeFFpeEpRVUYwUWl4RFFVRmFMRU5CVkhWQ08wRkJWWFpDTEZWQlFVMHNTVUZCVGl4RFFVRlpMRmRCUVVNc1NVRkJaU3hGUVVGbUxFZEJRWEZDTEVsQlFYUkNMRU5CUVZvc1EwRldkVUk3UVVGWGRrSXNWVUZCVFN4SlFVRk9MRU5CUVZrc1YwRkJReXhKUVVGbExFTkJRV1lzUjBGQmIwSXNTVUZCY2tJc1EwRkJXaXhEUVZoMVFqdEJRVmwyUWl4VlFVRk5MRWxCUVU0c1EwRkJXU3hqUVVGakxFbEJRV1FzUTBGQldpeERRVnAxUWpzN1FVRmpka0lzVlVGQlRTeEpRVUZPTEVOQlFWa3NWMEZCUXl4SlFVRmxMRVZCUVdZc1IwRkJjVUlzU1VGQmRFSXNRMEZCV2l4RFFXUjFRanRCUVdWMlFpeFZRVUZOTEVsQlFVNHNRMEZCV1N4WFFVRkRMRWxCUVdVc1JVRkJaaXhIUVVGeFFpeEpRVUYwUWl4RFFVRmFMRU5CWm5WQ08wRkJaMEoyUWl4VlFVRk5MRWxCUVU0c1EwRkJXU3hYUVVGRExFbEJRV1VzUTBGQlppeEhRVUZ2UWl4SlFVRnlRaXhEUVVGYUxFTkJhRUoxUWp0QlFXbENka0lzVlVGQlRTeEpRVUZPTEVOQlFWa3NZMEZCWXl4SlFVRmtMRU5CUVZvc1EwRnFRblZDT3p0QlFXMUNka0lzVjBGQlR5eExRVUZRTEVOQmJrSjFRanRIUVVGNlFqdERRVGRTUmpzN1FVRnZWRUVzWlVGQlpTeFRRVUZtSWl3aVptbHNaU0k2SW14cFlpOWpiM0psTDJKcGRGOXpkSEpwYm1jdWFuTWlMQ0p6YjNWeVkyVnpRMjl1ZEdWdWRDSTZXeUpqYkdGemN5QkNhWFJUZEhKcGJtY2dlMXh1SUNCamIyNXpkSEoxWTNSdmNpZ3VMaTVoY21kektYdGNiaUFnSUNCMGFHbHpMblpoYkhWbElEMGdUMkpxWldOMExtWnlaV1Y2WlNoMGFHbHpMbkJ5YjJObGMzTW9ZWEpuY3lrcE8xeHVJQ0FnSUhSb2FYTXViR1Z1WjNSb0lEMGdkR2hwY3k1MllXeDFaUzVzWlc1bmRHZzdYRzRnSUNBZ2RHaHBjeTVpYVhSZmMybDZaU0E5SUhSb2FYTXViR1Z1WjNSb0lDb2dPRHRjYmlBZ0lDQjBhR2x6TG1KNWRHVmZjMmw2WlNBOUlIUm9hWE11YkdWdVozUm9PMXh1SUNCOVhHNWNiaUFnWjJWMEtHbHVaR1Y0S1h0Y2JpQWdJQ0J5WlhSMWNtNGdkR2hwY3k1MllXeDFaVnRwYm1SbGVGMDdYRzRnSUgxY2JseHVJQ0JqYjNWdWRDZ3BlMXh1SUNBZ0lISmxkSFZ5YmlCMGFHbHpMblpoYkhWbExteGxibWQwYUR0Y2JpQWdmVnh1WEc0Z0lITnNhV05sS0hOMFlYSjBMQ0JsYm1RZ1BTQnVkV3hzS1h0Y2JpQWdJQ0JzWlhRZ2N5QTlJSFJvYVhNdWRtRnNkV1V1YzJ4cFkyVW9jM1JoY25Rc0lHVnVaQ2s3WEc0Z0lDQWdiR1YwSUcxeklEMGdjeTV0WVhBb0tHVnNaVzBwSUQwK0lFSnBkRk4wY21sdVp5NXBiblJsWjJWeUtHVnNaVzBwS1R0Y2JpQWdJQ0J5WlhSMWNtNGdibVYzSUVKcGRGTjBjbWx1WnlndUxpNXRjeWs3WEc0Z0lIMWNibHh1SUNCYlUzbHRZbTlzTG1sMFpYSmhkRzl5WFNncElIdGNiaUFnSUNCeVpYUjFjbTRnZEdocGN5NTJZV3gxWlZ0VGVXMWliMnd1YVhSbGNtRjBiM0pkS0NrN1hHNGdJSDFjYmx4dUlDQjBiMU4wY21sdVp5Z3BlMXh1SUNBZ0lIWmhjaUJwTENCeklEMGdYQ0pjSWp0Y2JpQWdJQ0JtYjNJZ0tHa2dQU0F3T3lCcElEd2dkR2hwY3k1amIzVnVkQ2dwT3lCcEt5c3BJSHRjYmlBZ0lDQWdJR2xtSUNoeklDRTlQU0JjSWx3aUtTQjdYRzRnSUNBZ0lDQWdJSE1nS3owZ1hDSXNJRndpTzF4dUlDQWdJQ0FnZlZ4dUlDQWdJQ0FnY3lBclBTQjBhR2x6TG1kbGRDaHBLUzUwYjFOMGNtbHVaeWdwTzF4dUlDQWdJSDFjYmx4dUlDQWdJSEpsZEhWeWJpQmNJanc4WENJZ0t5QnpJQ3NnWENJK1Bsd2lPMXh1SUNCOVhHNWNiaUFnY0hKdlkyVnpjeWhpYVhSVGRISnBibWRRWVhKMGN5bDdYRzRnSUNBZ2JHVjBJSEJ5YjJObGMzTmxaRjkyWVd4MVpYTWdQU0JiWFR0Y2JseHVJQ0FnSUhaaGNpQnBPMXh1SUNBZ0lHWnZjaUFvYVNBOUlEQTdJR2tnUENCaWFYUlRkSEpwYm1kUVlYSjBjeTVzWlc1bmRHZzdJR2tyS3lrZ2UxeHVJQ0FnSUNBZ2JHVjBJSEJ5YjJObGMzTmxaRjkyWVd4MVpTQTlJSFJvYVhOYkozQnliMk5sYzNOZkp5QXJJR0pwZEZOMGNtbHVaMUJoY25SelcybGRMblI1Y0dWZEtHSnBkRk4wY21sdVoxQmhjblJ6VzJsZEtUdGNibHh1SUNBZ0lDQWdabTl5S0d4bGRDQmhkSFJ5SUc5bUlHSnBkRk4wY21sdVoxQmhjblJ6VzJsZExtRjBkSEpwWW5WMFpYTXBlMXh1SUNBZ0lDQWdJQ0J3Y205alpYTnpaV1JmZG1Gc2RXVWdQU0IwYUdseld5ZHdjbTlqWlhOelh5Y2dLeUJoZEhSeVhTaHdjbTlqWlhOelpXUmZkbUZzZFdVcE8xeHVJQ0FnSUNBZ2ZWeHVYRzRnSUNBZ0lDQndjbTlqWlhOelpXUmZkbUZzZFdWeklEMGdjSEp2WTJWemMyVmtYM1poYkhWbGN5NWpiMjVqWVhRb2NISnZZMlZ6YzJWa1gzWmhiSFZsS1R0Y2JpQWdJQ0I5WEc1Y2JpQWdJQ0J5WlhSMWNtNGdjSEp2WTJWemMyVmtYM1poYkhWbGN6dGNiaUFnZlZ4dVhHNGdJSEJ5YjJObGMzTmZhVzUwWldkbGNpaDJZV3gxWlNsN1hHNGdJQ0FnY21WMGRYSnVJSFpoYkhWbExuWmhiSFZsTzF4dUlDQjlYRzVjYmlBZ2NISnZZMlZ6YzE5bWJHOWhkQ2gyWVd4MVpTbDdYRzRnSUNBZ2FXWW9kbUZzZFdVdWMybDZaU0E5UFQwZ05qUXBlMXh1SUNBZ0lDQWdjbVYwZFhKdUlFSnBkRk4wY21sdVp5NW1iRzloZERZMFZHOUNlWFJsY3loMllXeDFaUzUyWVd4MVpTazdYRzRnSUNBZ2ZXVnNjMlVnYVdZb2RtRnNkV1V1YzJsNlpTQTlQVDBnTXpJcGUxeHVJQ0FnSUNBZ2NtVjBkWEp1SUVKcGRGTjBjbWx1Wnk1bWJHOWhkRE15Vkc5Q2VYUmxjeWgyWVd4MVpTNTJZV3gxWlNrN1hHNGdJQ0FnZlZ4dVhHNGdJQ0FnZEdoeWIzY2dibVYzSUVWeWNtOXlLQ2RKYm5aaGJHbGtJSE5wZW1VZ1ptOXlJR1pzYjJGMEp5azdYRzRnSUgxY2JseHVJQ0J3Y205alpYTnpYMkpwZEhOMGNtbHVaeWgyWVd4MVpTbDdYRzRnSUNBZ2NtVjBkWEp1SUhaaGJIVmxMblpoYkhWbExuWmhiSFZsTzF4dUlDQjlYRzVjYmlBZ2NISnZZMlZ6YzE5aWFXNWhjbmtvZG1Gc2RXVXBlMXh1SUNBZ0lISmxkSFZ5YmlCQ2FYUlRkSEpwYm1jdWRHOVZWRVk0UVhKeVlYa29kbUZzZFdVdWRtRnNkV1VwTzF4dUlDQjlYRzVjYmlBZ2NISnZZMlZ6YzE5MWRHWTRLSFpoYkhWbEtYdGNiaUFnSUNCeVpYUjFjbTRnUW1sMFUzUnlhVzVuTG5SdlZWUkdPRUZ5Y21GNUtIWmhiSFZsTG5aaGJIVmxLVHRjYmlBZ2ZWeHVYRzRnSUhCeWIyTmxjM05mZFhSbU1UWW9kbUZzZFdVcGUxeHVJQ0FnSUhKbGRIVnliaUJDYVhSVGRISnBibWN1ZEc5VlZFWXhOa0Z5Y21GNUtIWmhiSFZsTG5aaGJIVmxLVHRjYmlBZ2ZWeHVYRzRnSUhCeWIyTmxjM05mZFhSbU16SW9kbUZzZFdVcGUxeHVJQ0FnSUhKbGRIVnliaUJDYVhSVGRISnBibWN1ZEc5VlZFWXpNa0Z5Y21GNUtIWmhiSFZsTG5aaGJIVmxLVHRjYmlBZ2ZWeHVYRzRnSUhCeWIyTmxjM05mYzJsbmJtVmtLSFpoYkhWbEtYdGNiaUFnSUNCeVpYUjFjbTRnS0c1bGR5QlZhVzUwT0VGeWNtRjVLRnQyWVd4MVpWMHBLVnN3WFR0Y2JpQWdmVnh1WEc0Z0lIQnliMk5sYzNOZmRXNXphV2R1WldRb2RtRnNkV1VwZTF4dUlDQWdJSEpsZEhWeWJpQjJZV3gxWlR0Y2JpQWdmVnh1WEc0Z0lIQnliMk5sYzNOZmJtRjBhWFpsS0haaGJIVmxLWHRjYmlBZ0lDQnlaWFIxY200Z2RtRnNkV1U3WEc0Z0lIMWNibHh1SUNCd2NtOWpaWE56WDJKcFp5aDJZV3gxWlNsN1hHNGdJQ0FnY21WMGRYSnVJSFpoYkhWbE8xeHVJQ0I5WEc1Y2JpQWdjSEp2WTJWemMxOXNhWFIwYkdVb2RtRnNkV1VwZTF4dUlDQWdJSEpsZEhWeWJpQjJZV3gxWlM1eVpYWmxjbk5sS0NrN1hHNGdJSDFjYmx4dUlDQndjbTlqWlhOelgzTnBlbVVvZG1Gc2RXVXBlMXh1SUNBZ0lISmxkSFZ5YmlCMllXeDFaVHRjYmlBZ2ZWeHVYRzRnSUhCeWIyTmxjM05mZFc1cGRDaDJZV3gxWlNsN1hHNGdJQ0FnY21WMGRYSnVJSFpoYkhWbE8xeHVJQ0I5WEc1Y2JpQWdjM1JoZEdsaklHbHVkR1ZuWlhJb2RtRnNkV1VwZTF4dUlDQWdJSEpsZEhWeWJpQkNhWFJUZEhKcGJtY3VkM0poY0NoMllXeDFaU3dnZXlBbmRIbHdaU2M2SUNkcGJuUmxaMlZ5Snl3Z0ozVnVhWFFuT2lBeExDQW5jMmw2WlNjNklEZ2dmU2s3WEc0Z0lIMWNibHh1SUNCemRHRjBhV01nWm14dllYUW9kbUZzZFdVcGUxeHVJQ0FnSUhKbGRIVnliaUJDYVhSVGRISnBibWN1ZDNKaGNDaDJZV3gxWlN3Z2V5QW5kSGx3WlNjNklDZG1iRzloZENjc0lDZDFibWwwSnpvZ01Td2dKM05wZW1Vbk9pQTJOQ0I5S1R0Y2JpQWdmVnh1WEc0Z0lITjBZWFJwWXlCaWFYUnpkSEpwYm1jb2RtRnNkV1VwZTF4dUlDQWdJSEpsZEhWeWJpQkNhWFJUZEhKcGJtY3VkM0poY0NoMllXeDFaU3dnZXlBbmRIbHdaU2M2SUNkaWFYUnpkSEpwYm1jbkxDQW5kVzVwZENjNklERXNJQ2R6YVhwbEp6b2dkbUZzZFdVdVltbDBYM05wZW1VZ2ZTazdYRzRnSUgxY2JseHVJQ0J6ZEdGMGFXTWdZbWwwY3loMllXeDFaU2w3WEc0Z0lDQWdjbVYwZFhKdUlFSnBkRk4wY21sdVp5NWlhWFJ6ZEhKcGJtY29kbUZzZFdVcE8xeHVJQ0I5WEc1Y2JpQWdjM1JoZEdsaklHSnBibUZ5ZVNoMllXeDFaU2w3WEc0Z0lDQWdjbVYwZFhKdUlFSnBkRk4wY21sdVp5NTNjbUZ3S0haaGJIVmxMQ0I3SUNkMGVYQmxKem9nSjJKcGJtRnllU2NzSUNkMWJtbDBKem9nT0N3Z0ozTnBlbVVuT2lCMllXeDFaUzVzWlc1bmRHZ2dmU2s3WEc0Z0lIMWNibHh1SUNCemRHRjBhV01nWW5sMFpYTW9kbUZzZFdVcGUxeHVJQ0FnSUhKbGRIVnliaUJDYVhSVGRISnBibWN1WW1sdVlYSjVLSFpoYkhWbEtUdGNiaUFnZlZ4dVhHNGdJSE4wWVhScFl5QjFkR1k0S0haaGJIVmxLWHRjYmlBZ0lDQnlaWFIxY200Z1FtbDBVM1J5YVc1bkxuZHlZWEFvZG1Gc2RXVXNJSHNnSjNSNWNHVW5PaUFuZFhSbU9DY3NJQ2QxYm1sMEp6b2dNU3dnSjNOcGVtVW5PaUIyWVd4MVpTNXNaVzVuZEdnZ0lIMHBPMXh1SUNCOVhHNWNiaUFnYzNSaGRHbGpJSFYwWmpFMktIWmhiSFZsS1h0Y2JpQWdJQ0J5WlhSMWNtNGdRbWwwVTNSeWFXNW5MbmR5WVhBb2RtRnNkV1VzSUhzZ0ozUjVjR1VuT2lBbmRYUm1NVFluTENBbmRXNXBkQ2M2SURFc0lDZHphWHBsSnpvZ2RtRnNkV1V1YkdWdVozUm9JQ29nTWlCOUtUdGNiaUFnZlZ4dVhHNGdJSE4wWVhScFl5QjFkR1l6TWloMllXeDFaU2w3WEc0Z0lDQWdjbVYwZFhKdUlFSnBkRk4wY21sdVp5NTNjbUZ3S0haaGJIVmxMQ0I3SUNkMGVYQmxKem9nSjNWMFpqTXlKeXdnSjNWdWFYUW5PaUF4TENBbmMybDZaU2M2SUhaaGJIVmxMbXhsYm1kMGFDQXFJRFFnZlNrN1hHNGdJSDFjYmx4dUlDQnpkR0YwYVdNZ2MybG5ibVZrS0haaGJIVmxLWHRjYmlBZ0lDQnlaWFIxY200Z1FtbDBVM1J5YVc1bkxuZHlZWEFvZG1Gc2RXVXNJSHQ5TENBbmMybG5ibVZrSnlrN1hHNGdJSDFjYmx4dUlDQnpkR0YwYVdNZ2RXNXphV2R1WldRb2RtRnNkV1VwZTF4dUlDQWdJSEpsZEhWeWJpQkNhWFJUZEhKcGJtY3VkM0poY0NoMllXeDFaU3dnZTMwc0lDZDFibk5wWjI1bFpDY3BPMXh1SUNCOVhHNWNiaUFnYzNSaGRHbGpJRzVoZEdsMlpTaDJZV3gxWlNsN1hHNGdJQ0FnY21WMGRYSnVJRUpwZEZOMGNtbHVaeTUzY21Gd0tIWmhiSFZsTENCN2ZTd2dKMjVoZEdsMlpTY3BPMXh1SUNCOVhHNWNiaUFnYzNSaGRHbGpJR0pwWnloMllXeDFaU2w3WEc0Z0lDQWdjbVYwZFhKdUlFSnBkRk4wY21sdVp5NTNjbUZ3S0haaGJIVmxMQ0I3ZlN3Z0oySnBaeWNwTzF4dUlDQjlYRzVjYmlBZ2MzUmhkR2xqSUd4cGRIUnNaU2gyWVd4MVpTbDdYRzRnSUNBZ2NtVjBkWEp1SUVKcGRGTjBjbWx1Wnk1M2NtRndLSFpoYkhWbExDQjdmU3dnSjJ4cGRIUnNaU2NwTzF4dUlDQjlYRzVjYmlBZ2MzUmhkR2xqSUhOcGVtVW9kbUZzZFdVc0lHTnZkVzUwS1h0Y2JpQWdJQ0J5WlhSMWNtNGdRbWwwVTNSeWFXNW5MbmR5WVhBb2RtRnNkV1VzSUhzbmMybDZaU2M2SUdOdmRXNTBmU2s3WEc0Z0lIMWNibHh1SUNCemRHRjBhV01nZFc1cGRDaDJZV3gxWlN3Z1kyOTFiblFwZTF4dUlDQWdJSEpsZEhWeWJpQkNhWFJUZEhKcGJtY3VkM0poY0NoMllXeDFaU3dnZXlkMWJtbDBKem9nWTI5MWJuUjlLVHRjYmlBZ2ZWeHVYRzRnSUhOMFlYUnBZeUIzY21Gd0tIWmhiSFZsTENCdmNIUXNJRzVsZDE5aGRIUnlhV0oxZEdVZ1BTQnVkV3hzS1h0Y2JpQWdJQ0JzWlhRZ2RHaGxYM1poYkhWbElEMGdkbUZzZFdVN1hHNWNiaUFnSUNCcFppZ2hLSFpoYkhWbElHbHVjM1JoYm1ObGIyWWdUMkpxWldOMEtTbDdYRzRnSUNBZ0lDQjBhR1ZmZG1Gc2RXVWdQU0I3SjNaaGJIVmxKem9nZG1Gc2RXVXNJQ2RoZEhSeWFXSjFkR1Z6SnpvZ1cxMTlPMXh1SUNBZ0lIMWNibHh1SUNBZ0lIUm9aVjkyWVd4MVpTQTlJRTlpYW1WamRDNWhjM05wWjI0b2RHaGxYM1poYkhWbExDQnZjSFFwTzF4dVhHNGdJQ0FnYVdZb2JtVjNYMkYwZEhKcFluVjBaU2w3WEc0Z0lDQWdJQ0IwYUdWZmRtRnNkV1V1WVhSMGNtbGlkWFJsY3k1d2RYTm9LRzVsZDE5aGRIUnlhV0oxZEdVcE8xeHVJQ0FnSUgxY2JseHVYRzRnSUNBZ2NtVjBkWEp1SUhSb1pWOTJZV3gxWlR0Y2JpQWdmVnh1WEc0Z0lITjBZWFJwWXlCMGIxVlVSamhCY25KaGVTaHpkSElwSUh0Y2JpQWdJQ0IyWVhJZ2RYUm1PQ0E5SUZ0ZE8xeHVJQ0FnSUdadmNpQW9kbUZ5SUdrZ1BTQXdPeUJwSUR3Z2MzUnlMbXhsYm1kMGFEc2dhU3NyS1NCN1hHNGdJQ0FnSUNCMllYSWdZMmhoY21OdlpHVWdQU0J6ZEhJdVkyaGhja052WkdWQmRDaHBLVHRjYmlBZ0lDQWdJR2xtSUNoamFHRnlZMjlrWlNBOElEQjRPREFwZTF4dUlDQWdJQ0FnSUNCMWRHWTRMbkIxYzJnb1kyaGhjbU52WkdVcE8xeHVJQ0FnSUNBZ2ZWeHVJQ0FnSUNBZ1pXeHpaU0JwWmlBb1kyaGhjbU52WkdVZ1BDQXdlRGd3TUNrZ2UxeHVJQ0FnSUNBZ0lDQjFkR1k0TG5CMWMyZ29NSGhqTUNCOElDaGphR0Z5WTI5a1pTQStQaUEyS1N4Y2JpQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lEQjRPREFnZkNBb1kyaGhjbU52WkdVZ0ppQXdlRE5tS1NrN1hHNGdJQ0FnSUNCOVhHNGdJQ0FnSUNCbGJITmxJR2xtSUNoamFHRnlZMjlrWlNBOElEQjRaRGd3TUNCOGZDQmphR0Z5WTI5a1pTQStQU0F3ZUdVd01EQXBJSHRjYmlBZ0lDQWdJQ0FnZFhSbU9DNXdkWE5vS0RCNFpUQWdmQ0FvWTJoaGNtTnZaR1VnUGo0Z01USXBMRnh1SUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnTUhnNE1DQjhJQ2dvWTJoaGNtTnZaR1VnUGo0Z05pa2dKaUF3ZURObUtTeGNiaUFnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJREI0T0RBZ2ZDQW9ZMmhoY21OdlpHVWdKaUF3ZURObUtTazdYRzRnSUNBZ0lDQjlYRzRnSUNBZ0lDQXZMeUJ6ZFhKeWIyZGhkR1VnY0dGcGNseHVJQ0FnSUNBZ1pXeHpaU0I3WEc0Z0lDQWdJQ0FnSUdrckt6dGNiaUFnSUNBZ0lDQWdMeThnVlZSR0xURTJJR1Z1WTI5a1pYTWdNSGd4TURBd01DMHdlREV3UmtaR1JpQmllVnh1SUNBZ0lDQWdJQ0F2THlCemRXSjBjbUZqZEdsdVp5QXdlREV3TURBd0lHRnVaQ0J6Y0d4cGRIUnBibWNnZEdobFhHNGdJQ0FnSUNBZ0lDOHZJREl3SUdKcGRITWdiMllnTUhnd0xUQjRSa1pHUmtZZ2FXNTBieUIwZDI4Z2FHRnNkbVZ6WEc0Z0lDQWdJQ0FnSUdOb1lYSmpiMlJsSUQwZ01IZ3hNREF3TUNBcklDZ29LR05vWVhKamIyUmxJQ1lnTUhnelptWXBJRHc4SURFd0tWeHVJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdmQ0FvYzNSeUxtTm9ZWEpEYjJSbFFYUW9hU2tnSmlBd2VETm1aaWtwTzF4dUlDQWdJQ0FnSUNCMWRHWTRMbkIxYzJnb01IaG1NQ0I4SUNoamFHRnlZMjlrWlNBK1BpQXhPQ2tzWEc0Z0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBd2VEZ3dJSHdnS0NoamFHRnlZMjlrWlNBK1BpQXhNaWtnSmlBd2VETm1LU3hjYmlBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSURCNE9EQWdmQ0FvS0dOb1lYSmpiMlJsSUQ0K0lEWXBJQ1lnTUhnelppa3NYRzRnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0F3ZURnd0lId2dLR05vWVhKamIyUmxJQ1lnTUhnelppa3BPMXh1SUNBZ0lDQWdmVnh1SUNBZ0lIMWNiaUFnSUNCeVpYUjFjbTRnZFhSbU9EdGNiaUFnZlZ4dVhHNGdJSE4wWVhScFl5QjBiMVZVUmpFMlFYSnlZWGtvYzNSeUtTQjdYRzRnSUNBZ2RtRnlJSFYwWmpFMklEMGdXMTA3WEc0Z0lDQWdabTl5SUNoMllYSWdhU0E5SURBN0lHa2dQQ0J6ZEhJdWJHVnVaM1JvT3lCcEt5c3BJSHRjYmlBZ0lDQWdJSFpoY2lCamIyUmxVRzlwYm5RZ1BTQnpkSEl1WTI5a1pWQnZhVzUwUVhRb2FTazdYRzVjYmlBZ0lDQWdJR2xtS0dOdlpHVlFiMmx1ZENBOFBTQXlOVFVwZTF4dUlDQWdJQ0FnSUNCMWRHWXhOaTV3ZFhOb0tEQXBPMXh1SUNBZ0lDQWdJQ0IxZEdZeE5pNXdkWE5vS0dOdlpHVlFiMmx1ZENrN1hHNGdJQ0FnSUNCOVpXeHpaWHRjYmlBZ0lDQWdJQ0FnZFhSbU1UWXVjSFZ6YUNnb0tHTnZaR1ZRYjJsdWRDQStQaUE0S1NBbUlEQjRSa1lwS1R0Y2JpQWdJQ0FnSUNBZ2RYUm1NVFl1Y0hWemFDZ29ZMjlrWlZCdmFXNTBJQ1lnTUhoR1Jpa3BPMXh1SUNBZ0lDQWdmVnh1SUNBZ0lIMWNiaUFnSUNCeVpYUjFjbTRnZFhSbU1UWTdYRzRnSUgxY2JseHVYRzRnSUhOMFlYUnBZeUIwYjFWVVJqTXlRWEp5WVhrb2MzUnlLU0I3WEc0Z0lDQWdkbUZ5SUhWMFpqTXlJRDBnVzEwN1hHNGdJQ0FnWm05eUlDaDJZWElnYVNBOUlEQTdJR2tnUENCemRISXViR1Z1WjNSb095QnBLeXNwSUh0Y2JpQWdJQ0FnSUhaaGNpQmpiMlJsVUc5cGJuUWdQU0J6ZEhJdVkyOWtaVkJ2YVc1MFFYUW9hU2s3WEc1Y2JpQWdJQ0FnSUdsbUtHTnZaR1ZRYjJsdWRDQThQU0F5TlRVcGUxeHVJQ0FnSUNBZ0lDQjFkR1l6TWk1d2RYTm9LREFwTzF4dUlDQWdJQ0FnSUNCMWRHWXpNaTV3ZFhOb0tEQXBPMXh1SUNBZ0lDQWdJQ0IxZEdZek1pNXdkWE5vS0RBcE8xeHVJQ0FnSUNBZ0lDQjFkR1l6TWk1d2RYTm9LR052WkdWUWIybHVkQ2s3WEc0Z0lDQWdJQ0I5Wld4elpYdGNiaUFnSUNBZ0lDQWdkWFJtTXpJdWNIVnphQ2d3S1R0Y2JpQWdJQ0FnSUNBZ2RYUm1Nekl1Y0hWemFDZ3dLVHRjYmlBZ0lDQWdJQ0FnZFhSbU16SXVjSFZ6YUNnb0tHTnZaR1ZRYjJsdWRDQStQaUE0S1NBbUlEQjRSa1lwS1R0Y2JpQWdJQ0FnSUNBZ2RYUm1Nekl1Y0hWemFDZ29ZMjlrWlZCdmFXNTBJQ1lnTUhoR1Jpa3BPMXh1SUNBZ0lDQWdmVnh1SUNBZ0lIMWNiaUFnSUNCeVpYUjFjbTRnZFhSbU16STdYRzRnSUgxY2JseHVJQ0F2TDJoMGRIQTZMeTl6ZEdGamEyOTJaWEptYkc5M0xtTnZiUzl4ZFdWemRHbHZibk12TWpBd016UTVNeTlxWVhaaGMyTnlhWEIwTFdac2IyRjBMV1p5YjIwdGRHOHRZbWwwYzF4dUlDQnpkR0YwYVdNZ1pteHZZWFF6TWxSdlFubDBaWE1vWmlrZ2UxeHVJQ0FnSUhaaGNpQmllWFJsY3lBOUlGdGRPMXh1WEc0Z0lDQWdkbUZ5SUdKMVppQTlJRzVsZHlCQmNuSmhlVUoxWm1abGNpZzBLVHRjYmlBZ0lDQW9ibVYzSUVac2IyRjBNekpCY25KaGVTaGlkV1lwS1Zzd1hTQTlJR1k3WEc1Y2JpQWdJQ0JzWlhRZ2FXNTBWbVZ5YzJsdmJpQTlJQ2h1WlhjZ1ZXbHVkRE15UVhKeVlYa29ZblZtS1NsYk1GMDdYRzVjYmlBZ0lDQmllWFJsY3k1d2RYTm9LQ2dvYVc1MFZtVnljMmx2YmlBK1BpQXlOQ2tnSmlBd2VFWkdLU2s3WEc0Z0lDQWdZbmwwWlhNdWNIVnphQ2dvS0dsdWRGWmxjbk5wYjI0Z1BqNGdNVFlwSUNZZ01IaEdSaWtwTzF4dUlDQWdJR0o1ZEdWekxuQjFjMmdvS0NocGJuUldaWEp6YVc5dUlENCtJRGdwSUNZZ01IaEdSaWtwTzF4dUlDQWdJR0o1ZEdWekxuQjFjMmdvS0dsdWRGWmxjbk5wYjI0Z0ppQXdlRVpHS1NrN1hHNWNiaUFnSUNCeVpYUjFjbTRnWW5sMFpYTTdYRzRnSUgxY2JseHVJQ0J6ZEdGMGFXTWdabXh2WVhRMk5GUnZRbmwwWlhNb1ppa2dlMXh1SUNBZ0lIWmhjaUJpZVhSbGN5QTlJRnRkTzF4dVhHNGdJQ0FnZG1GeUlHSjFaaUE5SUc1bGR5QkJjbkpoZVVKMVptWmxjaWc0S1R0Y2JpQWdJQ0FvYm1WM0lFWnNiMkYwTmpSQmNuSmhlU2hpZFdZcEtWc3dYU0E5SUdZN1hHNWNiaUFnSUNCMllYSWdhVzUwVm1WeWMybHZiakVnUFNBb2JtVjNJRlZwYm5Rek1rRnljbUY1S0dKMVppa3BXekJkTzF4dUlDQWdJSFpoY2lCcGJuUldaWEp6YVc5dU1pQTlJQ2h1WlhjZ1ZXbHVkRE15UVhKeVlYa29ZblZtS1NsYk1WMDdYRzVjYmlBZ0lDQmllWFJsY3k1d2RYTm9LQ2dvYVc1MFZtVnljMmx2YmpJZ1BqNGdNalFwSUNZZ01IaEdSaWtwTzF4dUlDQWdJR0o1ZEdWekxuQjFjMmdvS0NocGJuUldaWEp6YVc5dU1pQStQaUF4TmlrZ0ppQXdlRVpHS1NrN1hHNGdJQ0FnWW5sMFpYTXVjSFZ6YUNnb0tHbHVkRlpsY25OcGIyNHlJRDQrSURncElDWWdNSGhHUmlrcE8xeHVJQ0FnSUdKNWRHVnpMbkIxYzJnb0tHbHVkRlpsY25OcGIyNHlJQ1lnTUhoR1Jpa3BPMXh1WEc0Z0lDQWdZbmwwWlhNdWNIVnphQ2dvS0dsdWRGWmxjbk5wYjI0eElENCtJREkwS1NBbUlEQjRSa1lwS1R0Y2JpQWdJQ0JpZVhSbGN5NXdkWE5vS0Nnb2FXNTBWbVZ5YzJsdmJqRWdQajRnTVRZcElDWWdNSGhHUmlrcE8xeHVJQ0FnSUdKNWRHVnpMbkIxYzJnb0tDaHBiblJXWlhKemFXOXVNU0ErUGlBNEtTQW1JREI0UmtZcEtUdGNiaUFnSUNCaWVYUmxjeTV3ZFhOb0tDaHBiblJXWlhKemFXOXVNU0FtSURCNFJrWXBLVHRjYmx4dUlDQWdJSEpsZEhWeWJpQmllWFJsY3p0Y2JpQWdmVnh1ZlZ4dVhHNWxlSEJ2Y25RZ1pHVm1ZWFZzZENCQ2FYUlRkSEpwYm1jN1hHNGlYU3dpYzI5MWNtTmxVbTl2ZENJNklpOXpiM1Z5WTJVdkluMD1cbiIsIlxuZXhwb3J0IGNsYXNzIFZhcmlhYmxlIHtcblxuICBjb25zdHJ1Y3RvcihkZWZhdWx0X3ZhbHVlID0gU3ltYm9sLmZvcihcImVsaXhpcnNjcmlwdC5ub192YWx1ZVwiKSkge1xuICAgIHRoaXMuZGVmYXVsdF92YWx1ZSA9IGRlZmF1bHRfdmFsdWU7XG4gIH1cbn1cblxuZXhwb3J0IGNsYXNzIFdpbGRjYXJkIHtcbiAgY29uc3RydWN0b3IoKSB7fVxufVxuXG5leHBvcnQgY2xhc3MgU3RhcnRzV2l0aCB7XG5cbiAgY29uc3RydWN0b3IocHJlZml4KSB7XG4gICAgdGhpcy5wcmVmaXggPSBwcmVmaXg7XG4gIH1cbn1cblxuZXhwb3J0IGNsYXNzIENhcHR1cmUge1xuXG4gIGNvbnN0cnVjdG9yKHZhbHVlKSB7XG4gICAgdGhpcy52YWx1ZSA9IHZhbHVlO1xuICB9XG59XG5cbmV4cG9ydCBjbGFzcyBIZWFkVGFpbCB7XG5cbiAgY29uc3RydWN0b3IoaGVhZCA9IG51bGwsIHRhaWwgPSBudWxsKSB7XG4gICAgdGhpcy5oZWFkID0gaGVhZDtcbiAgICB0aGlzLnRhaWwgPSB0YWlsO1xuICB9XG59XG5cbmV4cG9ydCBjbGFzcyBUeXBlIHtcblxuICBjb25zdHJ1Y3Rvcih0eXBlLCBvYmpQYXR0ZXJuID0ge30pIHtcbiAgICB0aGlzLnR5cGUgPSB0eXBlO1xuICAgIHRoaXMub2JqUGF0dGVybiA9IG9ialBhdHRlcm47XG4gIH1cbn1cblxuZXhwb3J0IGNsYXNzIEJvdW5kIHtcblxuICBjb25zdHJ1Y3Rvcih2YWx1ZSkge1xuICAgIHRoaXMudmFsdWUgPSB2YWx1ZTtcbiAgfVxufVxuXG5leHBvcnQgY2xhc3MgQml0U3RyaW5nTWF0Y2gge1xuXG4gIGNvbnN0cnVjdG9yKC4uLnZhbHVlcykge1xuICAgIHRoaXMudmFsdWVzID0gdmFsdWVzO1xuICB9XG5cbiAgbGVuZ3RoKCkge1xuICAgIHJldHVybiB2YWx1ZXMubGVuZ3RoO1xuICB9XG5cbiAgYml0X3NpemUoKSB7XG4gICAgcmV0dXJuIHRoaXMuYnl0ZV9zaXplKCkgKiA4O1xuICB9XG5cbiAgYnl0ZV9zaXplKCkge1xuICAgIGxldCBzID0gMDtcblxuICAgIGZvciAobGV0IHZhbCBvZiB0aGlzLnZhbHVlcykge1xuICAgICAgcyA9IHMgKyB2YWwudW5pdCAqIHZhbC5zaXplIC8gODtcbiAgICB9XG5cbiAgICByZXR1cm4gcztcbiAgfVxuXG4gIGdldFZhbHVlKGluZGV4KSB7XG4gICAgcmV0dXJuIHRoaXMudmFsdWVzKGluZGV4KTtcbiAgfVxuXG4gIGdldFNpemVPZlZhbHVlKGluZGV4KSB7XG4gICAgbGV0IHZhbCA9IHRoaXMuZ2V0VmFsdWUoaW5kZXgpO1xuICAgIHJldHVybiB2YWwudW5pdCAqIHZhbC5zaXplO1xuICB9XG5cbiAgZ2V0VHlwZU9mVmFsdWUoaW5kZXgpIHtcbiAgICByZXR1cm4gdGhpcy5nZXRWYWx1ZShpbmRleCkudHlwZTtcbiAgfVxufVxuXG5leHBvcnQgZnVuY3Rpb24gdmFyaWFibGUoZGVmYXVsdF92YWx1ZSA9IFN5bWJvbC5mb3IoXCJlbGl4aXJzY3JpcHQubm9fdmFsdWVcIikpIHtcbiAgcmV0dXJuIG5ldyBWYXJpYWJsZShkZWZhdWx0X3ZhbHVlKTtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIHdpbGRjYXJkKCkge1xuICByZXR1cm4gbmV3IFdpbGRjYXJkKCk7XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBzdGFydHNXaXRoKHByZWZpeCkge1xuICByZXR1cm4gbmV3IFN0YXJ0c1dpdGgocHJlZml4KTtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIGNhcHR1cmUodmFsdWUpIHtcbiAgcmV0dXJuIG5ldyBDYXB0dXJlKHZhbHVlKTtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIGhlYWRUYWlsKGhlYWQgPSBudWxsLCB0YWlsID0gbnVsbCkge1xuICByZXR1cm4gbmV3IEhlYWRUYWlsKGhlYWQsIHRhaWwpO1xufVxuXG5leHBvcnQgZnVuY3Rpb24gdHlwZSh0eXBlLCBvYmpQYXR0ZXJuID0ge30pIHtcbiAgcmV0dXJuIG5ldyBUeXBlKHR5cGUsIG9ialBhdHRlcm4pO1xufVxuXG5leHBvcnQgZnVuY3Rpb24gYm91bmQodmFsdWUpIHtcbiAgcmV0dXJuIG5ldyBCb3VuZCh2YWx1ZSk7XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBiaXRTdHJpbmdNYXRjaCguLi52YWx1ZXMpIHtcbiAgcmV0dXJuIG5ldyBCaXRTdHJpbmdNYXRjaCguLi52YWx1ZXMpO1xufVxuLy8jIHNvdXJjZU1hcHBpbmdVUkw9ZGF0YTphcHBsaWNhdGlvbi9qc29uO2Jhc2U2NCxleUoyWlhKemFXOXVJam96TENKemIzVnlZMlZ6SWpwYklteHBZaTlqYjNKbEwzQmhkSFJsY201ekwzUjVjR1Z6TG1weklsMHNJbTVoYldWeklqcGJYU3dpYldGd2NHbHVaM01pT2lJN1FVRkRRU3hQUVVGUExFMUJRVTBzVVVGQlRpeERRVUZsT3p0QlFVZHdRaXhqUVVGblF5eG5Ra0ZCUlN4UFFVRlBMRWRCUVZBc1EwRkJWeXgxUWtGQldDeERRVUZHTEVWQlFYVkRPMEZCUTNKRkxGTkJRVXNzWVVGQlRDeEhRVUZ4UWl4aFFVRnlRaXhEUVVSeFJUdEhRVUYyUlR0RFFVaExPenRCUVZGUUxFOUJRVThzVFVGQlRTeFJRVUZPTEVOQlFXVTdRVUZEY0VJc1owSkJRV01zUlVGQlpEdERRVVJMT3p0QlFVdFFMRTlCUVU4c1RVRkJUU3hWUVVGT0xFTkJRV2xDT3p0QlFVZDBRaXhqUVVGWkxFMUJRVm9zUlVGQk5FSTdRVUZETVVJc1UwRkJTeXhOUVVGTUxFZEJRV01zVFVGQlpDeERRVVF3UWp0SFFVRTFRanREUVVoTE96dEJRVkZRTEU5QlFVOHNUVUZCVFN4UFFVRk9MRU5CUVdNN08wRkJSMjVDTEdOQlFWa3NTMEZCV2l4RlFVRjNRanRCUVVOMFFpeFRRVUZMTEV0QlFVd3NSMEZCWVN4TFFVRmlMRU5CUkhOQ08wZEJRWGhDTzBOQlNFczdPMEZCVVZBc1QwRkJUeXhOUVVGTkxGRkJRVTRzUTBGQlpUczdRVUZKY0VJc1kwRkJjMElzVDBGQlJTeEpRVUZHTEVWQlFXdENMRTlCUVVVc1NVRkJSaXhGUVVGUk8wRkJRemxETEZOQlFVc3NTVUZCVEN4SFFVRlpMRWxCUVZvc1EwRkVPRU03UVVGRk9VTXNVMEZCU3l4SlFVRk1MRWRCUVZrc1NVRkJXaXhEUVVZNFF6dEhRVUZvUkR0RFFVcExPenRCUVZWUUxFOUJRVThzVFVGQlRTeEpRVUZPTEVOQlFWYzdPMEZCU1doQ0xHTkJRVmtzU1VGQldpeEZRVUV3UXl4aFFVRkZMRVZCUVVZc1JVRkJUVHRCUVVNNVF5eFRRVUZMTEVsQlFVd3NSMEZCV1N4SlFVRmFMRU5CUkRoRE8wRkJSVGxETEZOQlFVc3NWVUZCVEN4SFFVRnJRaXhWUVVGc1FpeERRVVk0UXp0SFFVRm9SRHREUVVwTE96dEJRVlZRTEU5QlFVOHNUVUZCVFN4TFFVRk9MRU5CUVZrN08wRkJSMnBDTEdOQlFWa3NTMEZCV2l4RlFVRjNRanRCUVVOMFFpeFRRVUZMTEV0QlFVd3NSMEZCWVN4TFFVRmlMRU5CUkhOQ08wZEJRWGhDTzBOQlNFczdPMEZCVVZBc1QwRkJUeXhOUVVGTkxHTkJRVTRzUTBGQmNVSTdPMEZCUnpGQ0xHTkJRVmtzUjBGQlJ5eE5RVUZJTEVWQlFYbENPMEZCUTI1RExGTkJRVXNzVFVGQlRDeEhRVUZqTEUxQlFXUXNRMEZFYlVNN1IwRkJja003TzBGQlNVRXNWMEZCVXp0QlFVTlFMRmRCUVU4c1QwRkJUeXhOUVVGUUxFTkJSRUU3UjBGQlZEczdRVUZKUVN4aFFVRlhPMEZCUTFRc1YwRkJUeXhMUVVGTExGTkJRVXdzUzBGQmJVSXNRMEZCYmtJc1EwRkVSVHRIUVVGWU96dEJRVWxCTEdOQlFWYzdRVUZEVkN4UlFVRkpMRWxCUVVrc1EwRkJTaXhEUVVSTE96dEJRVWRVTEZOQlFVa3NTVUZCU1N4SFFVRktMRWxCUVZjc1MwRkJTeXhOUVVGTUxFVkJRVms3UVVGRGVrSXNWVUZCU1N4SlFVRkxMRWRCUVVNc1EwRkJTU3hKUVVGS0xFZEJRVmNzU1VGQlNTeEpRVUZLTEVkQlFWVXNRMEZCZEVJc1EwRkVaMEk3UzBGQk0wSTdPMEZCU1VFc1YwRkJUeXhEUVVGUUxFTkJVRk03UjBGQldEczdRVUZWUVN4WFFVRlRMRXRCUVZRc1JVRkJaVHRCUVVOaUxGZEJRVThzUzBGQlN5eE5RVUZNTEVOQlFWa3NTMEZCV2l4RFFVRlFMRU5CUkdFN1IwRkJaanM3UVVGSlFTeHBRa0ZCWlN4TFFVRm1MRVZCUVhGQ08wRkJRMjVDTEZGQlFVa3NUVUZCVFN4TFFVRkxMRkZCUVV3c1EwRkJZeXhMUVVGa0xFTkJRVTRzUTBGRVpUdEJRVVZ1UWl4WFFVRlBMRWxCUVVrc1NVRkJTaXhIUVVGWExFbEJRVWtzU1VGQlNpeERRVVpETzBkQlFYSkNPenRCUVV0QkxHbENRVUZsTEV0QlFXWXNSVUZCY1VJN1FVRkRia0lzVjBGQlR5eExRVUZMTEZGQlFVd3NRMEZCWXl4TFFVRmtMRVZCUVhGQ0xFbEJRWEpDTEVOQlJGazdSMEZCY2tJN1EwRnNRMHM3TzBGQmRVTlFMRTlCUVU4c1UwRkJVeXhSUVVGVUxFTkJRWE5ETEdkQ1FVRkZMRTlCUVU4c1IwRkJVQ3hEUVVGWExIVkNRVUZZTEVOQlFVWXNSVUZCYVVRN1FVRkROVVlzVTBGQlR5eEpRVUZKTEZGQlFVb3NRMEZCWVN4aFFVRmlMRU5CUVZBc1EwRkVORVk3UTBGQmRrWTdPMEZCU1ZBc1QwRkJUeXhUUVVGVExGRkJRVlFzUjBGQk9FSTdRVUZEYmtNc1UwRkJUeXhKUVVGSkxGRkJRVW9zUlVGQlVDeERRVVJ0UXp0RFFVRTVRanM3UVVGSlVDeFBRVUZQTEZOQlFWTXNWVUZCVkN4RFFVRnZRaXhOUVVGd1FpeEZRVUZuUkR0QlFVTnlSQ3hUUVVGUExFbEJRVWtzVlVGQlNpeERRVUZsTEUxQlFXWXNRMEZCVUN4RFFVUnhSRHREUVVGb1JEczdRVUZKVUN4UFFVRlBMRk5CUVZNc1QwRkJWQ3hEUVVGcFFpeExRVUZxUWl4RlFVRnpRenRCUVVNelF5eFRRVUZQTEVsQlFVa3NUMEZCU2l4RFFVRlpMRXRCUVZvc1EwRkJVQ3hEUVVReVF6dERRVUYwUXpzN1FVRkpVQ3hQUVVGUExGTkJRVk1zVVVGQlZDeERRVUUwUWl4UFFVRkZMRWxCUVVZc1JVRkJhMElzVDBGQlJTeEpRVUZHTEVWQlFXdENPMEZCUTNKRkxGTkJRVThzU1VGQlNTeFJRVUZLTEVOQlFXRXNTVUZCWWl4RlFVRnRRaXhKUVVGdVFpeERRVUZRTEVOQlJIRkZPME5CUVdoRk96dEJRVWxRTEU5QlFVOHNVMEZCVXl4SlFVRlVMRU5CUVdNc1NVRkJaQ3hGUVVFMFF5eGhRVUZGTEVWQlFVWXNSVUZCV1R0QlFVTTNSQ3hUUVVGUExFbEJRVWtzU1VGQlNpeERRVUZUTEVsQlFWUXNSVUZCWlN4VlFVRm1MRU5CUVZBc1EwRkVOa1E3UTBGQmVFUTdPMEZCU1ZBc1QwRkJUeXhUUVVGVExFdEJRVlFzUTBGQlpTeExRVUZtTEVWQlFXdERPMEZCUTNaRExGTkJRVThzU1VGQlNTeExRVUZLTEVOQlFWVXNTMEZCVml4RFFVRlFMRU5CUkhWRE8wTkJRV3hET3p0QlFVbFFMRTlCUVU4c1UwRkJVeXhqUVVGVUxFTkJRWGRDTEVkQlFVY3NUVUZCU0N4RlFVRjVRanRCUVVOMFJDeFRRVUZQTEVsQlFVa3NZMEZCU2l4RFFVRnRRaXhIUVVGSExFMUJRVWdzUTBGQk1VSXNRMEZFYzBRN1EwRkJha1FpTENKbWFXeGxJam9pYkdsaUwyTnZjbVV2Y0dGMGRHVnlibk12ZEhsd1pYTXVhbk1pTENKemIzVnlZMlZ6UTI5dWRHVnVkQ0k2V3lJdktpQkFabXh2ZHlBcUwxeHVaWGh3YjNKMElHTnNZWE56SUZaaGNtbGhZbXhsSUh0Y2JpQWdaR1ZtWVhWc2RGOTJZV3gxWlRvZ1AyRnVlVHRjYmx4dUlDQmpiMjV6ZEhKMVkzUnZjaWhrWldaaGRXeDBYM1poYkhWbE9pQS9ZVzU1SUQwZ1UzbHRZbTlzTG1admNpaGNJbVZzYVhocGNuTmpjbWx3ZEM1dWIxOTJZV3gxWlZ3aUtTa2dlMXh1SUNBZ0lIUm9hWE11WkdWbVlYVnNkRjkyWVd4MVpTQTlJR1JsWm1GMWJIUmZkbUZzZFdVN1hHNGdJSDFjYm4xY2JseHVaWGh3YjNKMElHTnNZWE56SUZkcGJHUmpZWEprSUh0Y2JpQWdZMjl1YzNSeWRXTjBiM0lvS1NCN1hHNGdJSDFjYm4xY2JseHVaWGh3YjNKMElHTnNZWE56SUZOMFlYSjBjMWRwZEdnZ2UxeHVJQ0J3Y21WbWFYZzZJSE4wY21sdVp6dGNibHh1SUNCamIyNXpkSEoxWTNSdmNpaHdjbVZtYVhnNklITjBjbWx1WnlrZ2UxeHVJQ0FnSUhSb2FYTXVjSEpsWm1sNElEMGdjSEpsWm1sNE8xeHVJQ0I5WEc1OVhHNWNibVY0Y0c5eWRDQmpiR0Z6Y3lCRFlYQjBkWEpsSUh0Y2JpQWdkbUZzZFdVNklHRnVlVHRjYmx4dUlDQmpiMjV6ZEhKMVkzUnZjaWgyWVd4MVpUb2dZVzU1S1NCN1hHNGdJQ0FnZEdocGN5NTJZV3gxWlNBOUlIWmhiSFZsTzF4dUlDQjlYRzU5WEc1Y2JtVjRjRzl5ZENCamJHRnpjeUJJWldGa1ZHRnBiQ0I3WEc0Z0lHaGxZV1E2SUdGdWVUdGNiaUFnZEdGcGJEb2dZVzU1TzF4dVhHNGdJR052Ym5OMGNuVmpkRzl5S0dobFlXUTZJR0Z1ZVNBOUlHNTFiR3dzSUhSaGFXdzZJR0Z1ZVNBOUlHNTFiR3dwSUh0Y2JpQWdJQ0IwYUdsekxtaGxZV1FnUFNCb1pXRmtPMXh1SUNBZ0lIUm9hWE11ZEdGcGJDQTlJSFJoYVd3N1hHNGdJSDFjYm4xY2JseHVaWGh3YjNKMElHTnNZWE56SUZSNWNHVWdlMXh1SUNCMGVYQmxPaUJoYm5rN1hHNGdJRzlpYWxCaGRIUmxjbTQ2SUU5aWFtVmpkRHRjYmx4dUlDQmpiMjV6ZEhKMVkzUnZjaWgwZVhCbE9pQmhibmtzSUc5aWFsQmhkSFJsY200NklFOWlhbVZqZENBOUlIdDlLU0I3WEc0Z0lDQWdkR2hwY3k1MGVYQmxJRDBnZEhsd1pWeHVJQ0FnSUhSb2FYTXViMkpxVUdGMGRHVnliaUE5SUc5aWFsQmhkSFJsY201Y2JpQWdmVnh1ZlZ4dVhHNWxlSEJ2Y25RZ1kyeGhjM01nUW05MWJtUWdlMXh1SUNCMllXeDFaVG9nWVc1NU8xeHVYRzRnSUdOdmJuTjBjblZqZEc5eUtIWmhiSFZsT2lCaGJua3BJSHRjYmlBZ0lDQjBhR2x6TG5aaGJIVmxJRDBnZG1Gc2RXVTdYRzRnSUgxY2JuMWNibHh1Wlhod2IzSjBJR05zWVhOeklFSnBkRk4wY21sdVowMWhkR05vSUh0Y2JpQWdkbUZzZFdWek9pQkJjbkpoZVR4UFltcGxZM1ErWEc1Y2JpQWdZMjl1YzNSeWRXTjBiM0lvTGk0dWRtRnNkV1Z6T2lCQmNuSmhlVHhQWW1wbFkzUStLWHRjYmlBZ0lDQjBhR2x6TG5aaGJIVmxjeUE5SUhaaGJIVmxjenRjYmlBZ2ZWeHVYRzRnSUd4bGJtZDBhQ2dwSUh0Y2JpQWdJQ0J5WlhSMWNtNGdkbUZzZFdWekxteGxibWQwYUR0Y2JpQWdmVnh1WEc0Z0lHSnBkRjl6YVhwbEtDa2dlMXh1SUNBZ0lISmxkSFZ5YmlCMGFHbHpMbUo1ZEdWZmMybDZaU2dwSUNvZ09EdGNiaUFnZlZ4dVhHNGdJR0o1ZEdWZmMybDZaU2dwZTF4dUlDQWdJR3hsZENCeklEMGdNRHRjYmx4dUlDQWdJR1p2Y2loc1pYUWdkbUZzSUc5bUlIUm9hWE11ZG1Gc2RXVnpLWHRjYmlBZ0lDQWdJSE1nUFNCeklDc2dLQ2gyWVd3dWRXNXBkQ0FxSUhaaGJDNXphWHBsS1M4NEtUdGNiaUFnSUNCOVhHNWNiaUFnSUNCeVpYUjFjbTRnY3p0Y2JpQWdmVnh1WEc0Z0lHZGxkRlpoYkhWbEtHbHVaR1Y0S1h0Y2JpQWdJQ0J5WlhSMWNtNGdkR2hwY3k1MllXeDFaWE1vYVc1a1pYZ3BPMXh1SUNCOVhHNWNiaUFnWjJWMFUybDZaVTltVm1Gc2RXVW9hVzVrWlhncGUxeHVJQ0FnSUd4bGRDQjJZV3dnUFNCMGFHbHpMbWRsZEZaaGJIVmxLR2x1WkdWNEtUdGNiaUFnSUNCeVpYUjFjbTRnZG1Gc0xuVnVhWFFnS2lCMllXd3VjMmw2WlR0Y2JpQWdmVnh1WEc0Z0lHZGxkRlI1Y0dWUFpsWmhiSFZsS0dsdVpHVjRLWHRjYmlBZ0lDQnlaWFIxY200Z2RHaHBjeTVuWlhSV1lXeDFaU2hwYm1SbGVDa3VkSGx3WlR0Y2JpQWdmVnh1ZlZ4dVhHNWxlSEJ2Y25RZ1puVnVZM1JwYjI0Z2RtRnlhV0ZpYkdVb1pHVm1ZWFZzZEY5MllXeDFaVG9nUDJGdWVTQTlJRk41YldKdmJDNW1iM0lvWENKbGJHbDRhWEp6WTNKcGNIUXVibTlmZG1Gc2RXVmNJaWtwT2lCV1lYSnBZV0pzWlNCN1hHNGdJSEpsZEhWeWJpQnVaWGNnVm1GeWFXRmliR1VvWkdWbVlYVnNkRjkyWVd4MVpTazdYRzU5WEc1Y2JtVjRjRzl5ZENCbWRXNWpkR2x2YmlCM2FXeGtZMkZ5WkNncE9pQlhhV3hrWTJGeVpDQjdYRzRnSUhKbGRIVnliaUJ1WlhjZ1YybHNaR05oY21Rb0tUdGNibjFjYmx4dVpYaHdiM0owSUdaMWJtTjBhVzl1SUhOMFlYSjBjMWRwZEdnb2NISmxabWw0T2lCemRISnBibWNwT2lCVGRHRnlkSE5YYVhSb0lIdGNiaUFnY21WMGRYSnVJRzVsZHlCVGRHRnlkSE5YYVhSb0tIQnlaV1pwZUNrN1hHNTlYRzVjYm1WNGNHOXlkQ0JtZFc1amRHbHZiaUJqWVhCMGRYSmxLSFpoYkhWbE9pQmhibmtwT2lCRFlYQjBkWEpsSUh0Y2JpQWdjbVYwZFhKdUlHNWxkeUJEWVhCMGRYSmxLSFpoYkhWbEtUdGNibjFjYmx4dVpYaHdiM0owSUdaMWJtTjBhVzl1SUdobFlXUlVZV2xzS0dobFlXUTZJR0Z1ZVNBOUlHNTFiR3dzSUhSaGFXdzZJR0Z1ZVNBOUlHNTFiR3dwT2lCSVpXRmtWR0ZwYkNCN1hHNGdJSEpsZEhWeWJpQnVaWGNnU0dWaFpGUmhhV3dvYUdWaFpDd2dkR0ZwYkNrN1hHNTlYRzVjYm1WNGNHOXlkQ0JtZFc1amRHbHZiaUIwZVhCbEtIUjVjR1U2SUdGdWVTd2diMkpxVUdGMGRHVnliam9nVDJKcVpXTjBJRDBnZTMwcE9pQlVlWEJsSUh0Y2JpQWdjbVYwZFhKdUlHNWxkeUJVZVhCbEtIUjVjR1VzSUc5aWFsQmhkSFJsY200cE8xeHVmVnh1WEc1bGVIQnZjblFnWm5WdVkzUnBiMjRnWW05MWJtUW9kbUZzZFdVNklHRnVlU2s2SUVKdmRXNWtJSHRjYmlBZ2NtVjBkWEp1SUc1bGR5QkNiM1Z1WkNoMllXeDFaU2s3WEc1OVhHNWNibVY0Y0c5eWRDQm1kVzVqZEdsdmJpQmlhWFJUZEhKcGJtZE5ZWFJqYUNndUxpNTJZV3gxWlhNNklFRnljbUY1UEU5aWFtVmpkRDRwZTF4dUlDQnlaWFIxY200Z2JtVjNJRUpwZEZOMGNtbHVaMDFoZEdOb0tDNHVMblpoYkhWbGN5azdYRzU5WEc0aVhTd2ljMjkxY21ObFVtOXZkQ0k2SWk5emIzVnlZMlV2SW4wPVxuIiwiXG5cbmltcG9ydCB7IFZhcmlhYmxlLCBXaWxkY2FyZCwgSGVhZFRhaWwsIENhcHR1cmUsIFR5cGUsIFN0YXJ0c1dpdGgsIEJvdW5kLCBCaXRTdHJpbmdNYXRjaCB9IGZyb20gXCIuL3R5cGVzXCI7XG5cbmZ1bmN0aW9uIGlzX251bWJlcih2YWx1ZSkge1xuICByZXR1cm4gdHlwZW9mIHZhbHVlID09PSAnbnVtYmVyJztcbn1cblxuZnVuY3Rpb24gaXNfc3RyaW5nKHZhbHVlKSB7XG4gIHJldHVybiB0eXBlb2YgdmFsdWUgPT09ICdzdHJpbmcnO1xufVxuXG5mdW5jdGlvbiBpc19ib29sZWFuKHZhbHVlKSB7XG4gIHJldHVybiB0eXBlb2YgdmFsdWUgPT09ICdib29sZWFuJztcbn1cblxuZnVuY3Rpb24gaXNfc3ltYm9sKHZhbHVlKSB7XG4gIHJldHVybiB0eXBlb2YgdmFsdWUgPT09ICdzeW1ib2wnO1xufVxuXG5mdW5jdGlvbiBpc19udWxsKHZhbHVlKSB7XG4gIHJldHVybiB2YWx1ZSA9PT0gbnVsbDtcbn1cblxuZnVuY3Rpb24gaXNfdW5kZWZpbmVkKHZhbHVlKSB7XG4gIHJldHVybiB0eXBlb2YgdmFsdWUgPT09ICd1bmRlZmluZWQnO1xufVxuXG5mdW5jdGlvbiBpc19mdW5jdGlvbih2YWx1ZSkge1xuICByZXR1cm4gT2JqZWN0LnByb3RvdHlwZS50b1N0cmluZy5jYWxsKHZhbHVlKSA9PSAnW29iamVjdCBGdW5jdGlvbl0nO1xufVxuXG5mdW5jdGlvbiBpc192YXJpYWJsZSh2YWx1ZSkge1xuICByZXR1cm4gdmFsdWUgaW5zdGFuY2VvZiBWYXJpYWJsZTtcbn1cblxuZnVuY3Rpb24gaXNfd2lsZGNhcmQodmFsdWUpIHtcbiAgcmV0dXJuIHZhbHVlIGluc3RhbmNlb2YgV2lsZGNhcmQ7XG59XG5cbmZ1bmN0aW9uIGlzX2hlYWRUYWlsKHZhbHVlKSB7XG4gIHJldHVybiB2YWx1ZSBpbnN0YW5jZW9mIEhlYWRUYWlsO1xufVxuXG5mdW5jdGlvbiBpc19jYXB0dXJlKHZhbHVlKSB7XG4gIHJldHVybiB2YWx1ZSBpbnN0YW5jZW9mIENhcHR1cmU7XG59XG5cbmZ1bmN0aW9uIGlzX3R5cGUodmFsdWUpIHtcbiAgcmV0dXJuIHZhbHVlIGluc3RhbmNlb2YgVHlwZTtcbn1cblxuZnVuY3Rpb24gaXNfc3RhcnRzV2l0aCh2YWx1ZSkge1xuICByZXR1cm4gdmFsdWUgaW5zdGFuY2VvZiBTdGFydHNXaXRoO1xufVxuXG5mdW5jdGlvbiBpc19ib3VuZCh2YWx1ZSkge1xuICByZXR1cm4gdmFsdWUgaW5zdGFuY2VvZiBCb3VuZDtcbn1cblxuZnVuY3Rpb24gaXNfb2JqZWN0KHZhbHVlKSB7XG4gIHJldHVybiB0eXBlb2YgdmFsdWUgPT09ICdvYmplY3QnO1xufVxuXG5mdW5jdGlvbiBpc19hcnJheSh2YWx1ZSkge1xuICByZXR1cm4gQXJyYXkuaXNBcnJheSh2YWx1ZSk7XG59XG5cbmZ1bmN0aW9uIGlzX2JpdHN0cmluZyh2YWx1ZSkge1xuICByZXR1cm4gdmFsdWUgaW5zdGFuY2VvZiBCaXRTdHJpbmdNYXRjaDtcbn1cblxuZXhwb3J0IGRlZmF1bHQge1xuICBpc19udW1iZXIsXG4gIGlzX3N0cmluZyxcbiAgaXNfYm9vbGVhbixcbiAgaXNfc3ltYm9sLFxuICBpc19udWxsLFxuICBpc191bmRlZmluZWQsXG4gIGlzX2Z1bmN0aW9uLFxuICBpc192YXJpYWJsZSxcbiAgaXNfd2lsZGNhcmQsXG4gIGlzX2hlYWRUYWlsLFxuICBpc19jYXB0dXJlLFxuICBpc190eXBlLFxuICBpc19zdGFydHNXaXRoLFxuICBpc19ib3VuZCxcbiAgaXNfb2JqZWN0LFxuICBpc19hcnJheSxcbiAgaXNfYml0c3RyaW5nXG59O1xuLy8jIHNvdXJjZU1hcHBpbmdVUkw9ZGF0YTphcHBsaWNhdGlvbi9qc29uO2Jhc2U2NCxleUoyWlhKemFXOXVJam96TENKemIzVnlZMlZ6SWpwYklteHBZaTlqYjNKbEwzQmhkSFJsY201ekwyTm9aV05yY3k1cWN5SmRMQ0p1WVcxbGN5STZXMTBzSW0xaGNIQnBibWR6SWpvaU96dEJRVVZCTEZOQlFWTXNVVUZCVkN4RlFVRnRRaXhSUVVGdVFpeEZRVUUyUWl4UlFVRTNRaXhGUVVGMVF5eFBRVUYyUXl4RlFVRm5SQ3hKUVVGb1JDeEZRVUZ6UkN4VlFVRjBSQ3hGUVVGclJTeExRVUZzUlN4RlFVRjVSU3hqUVVGNlJTeFJRVUVyUml4VFFVRXZSanM3UVVGRlFTeFRRVUZUTEZOQlFWUXNRMEZCYlVJc1MwRkJia0lzUlVGQmQwTTdRVUZEZEVNc1UwRkJUeXhQUVVGUExFdEJRVkFzUzBGQmFVSXNVVUZCYWtJc1EwRkVLMEk3UTBGQmVFTTdPMEZCU1VFc1UwRkJVeXhUUVVGVUxFTkJRVzFDTEV0QlFXNUNMRVZCUVhWRE8wRkJRM0pETEZOQlFVOHNUMEZCVHl4TFFVRlFMRXRCUVdsQ0xGRkJRV3BDTEVOQlJEaENPME5CUVhaRE96dEJRVWxCTEZOQlFWTXNWVUZCVkN4RFFVRnZRaXhMUVVGd1FpeEZRVUY1UXp0QlFVTjJReXhUUVVGUExFOUJRVThzUzBGQlVDeExRVUZwUWl4VFFVRnFRaXhEUVVSblF6dERRVUY2UXpzN1FVRkpRU3hUUVVGVExGTkJRVlFzUTBGQmJVSXNTMEZCYmtJc1JVRkJkME03UVVGRGRFTXNVMEZCVHl4UFFVRlBMRXRCUVZBc1MwRkJhVUlzVVVGQmFrSXNRMEZFSzBJN1EwRkJlRU03TzBGQlNVRXNVMEZCVXl4UFFVRlVMRU5CUVdsQ0xFdEJRV3BDTEVWQlFYTkRPMEZCUTNCRExGTkJRVThzVlVGQlZTeEpRVUZXTEVOQlJEWkNPME5CUVhSRE96dEJRVWxCTEZOQlFWTXNXVUZCVkN4RFFVRnpRaXhMUVVGMFFpeEZRVUV5UXp0QlFVTjZReXhUUVVGUExFOUJRVThzUzBGQlVDeExRVUZwUWl4WFFVRnFRaXhEUVVSclF6dERRVUV6UXpzN1FVRkpRU3hUUVVGVExGZEJRVlFzUTBGQmNVSXNTMEZCY2tJc1JVRkJNRU03UVVGRGVFTXNVMEZCVHl4UFFVRlBMRk5CUVZBc1EwRkJhVUlzVVVGQmFrSXNRMEZCTUVJc1NVRkJNVUlzUTBGQkswSXNTMEZCTDBJc1MwRkJlVU1zYlVKQlFYcERMRU5CUkdsRE8wTkJRVEZET3p0QlFVbEJMRk5CUVZNc1YwRkJWQ3hEUVVGeFFpeExRVUZ5UWl4RlFVRXdRenRCUVVONFF5eFRRVUZQTEdsQ1FVRnBRaXhSUVVGcVFpeERRVVJwUXp0RFFVRXhRenM3UVVGSlFTeFRRVUZUTEZkQlFWUXNRMEZCY1VJc1MwRkJja0lzUlVGQk1FTTdRVUZEZUVNc1UwRkJUeXhwUWtGQmFVSXNVVUZCYWtJc1EwRkVhVU03UTBGQk1VTTdPMEZCU1VFc1UwRkJVeXhYUVVGVUxFTkJRWEZDTEV0QlFYSkNMRVZCUVRCRE8wRkJRM2hETEZOQlFVOHNhVUpCUVdsQ0xGRkJRV3BDTEVOQlJHbERPME5CUVRGRE96dEJRVWxCTEZOQlFWTXNWVUZCVkN4RFFVRnZRaXhMUVVGd1FpeEZRVUY1UXp0QlFVTjJReXhUUVVGUExHbENRVUZwUWl4UFFVRnFRaXhEUVVSblF6dERRVUY2UXpzN1FVRkpRU3hUUVVGVExFOUJRVlFzUTBGQmFVSXNTMEZCYWtJc1JVRkJjME03UVVGRGNFTXNVMEZCVHl4cFFrRkJhVUlzU1VGQmFrSXNRMEZFTmtJN1EwRkJkRU03TzBGQlNVRXNVMEZCVXl4aFFVRlVMRU5CUVhWQ0xFdEJRWFpDTEVWQlFUUkRPMEZCUXpGRExGTkJRVThzYVVKQlFXbENMRlZCUVdwQ0xFTkJSRzFETzBOQlFUVkRPenRCUVVsQkxGTkJRVk1zVVVGQlZDeERRVUZyUWl4TFFVRnNRaXhGUVVGMVF6dEJRVU55UXl4VFFVRlBMR2xDUVVGcFFpeExRVUZxUWl4RFFVUTRRanREUVVGMlF6czdRVUZKUVN4VFFVRlRMRk5CUVZRc1EwRkJiVUlzUzBGQmJrSXNSVUZCZDBNN1FVRkRkRU1zVTBGQlR5eFBRVUZQTEV0QlFWQXNTMEZCYVVJc1VVRkJha0lzUTBGRUswSTdRMEZCZUVNN08wRkJTVUVzVTBGQlV5eFJRVUZVTEVOQlFXdENMRXRCUVd4Q0xFVkJRWFZETzBGQlEzSkRMRk5CUVU4c1RVRkJUU3hQUVVGT0xFTkJRV01zUzBGQlpDeERRVUZRTEVOQlJIRkRPME5CUVhaRE96dEJRVWxCTEZOQlFWTXNXVUZCVkN4RFFVRnpRaXhMUVVGMFFpeEZRVUV5UXp0QlFVTjZReXhUUVVGUExHbENRVUZwUWl4alFVRnFRaXhEUVVSclF6dERRVUV6UXpzN1FVRkxRU3hsUVVGbE8wRkJRMklzVjBGRVlUdEJRVVZpTEZkQlJtRTdRVUZIWWl4WlFVaGhPMEZCU1dJc1YwRktZVHRCUVV0aUxGTkJUR0U3UVVGTllpeGpRVTVoTzBGQlQySXNZVUZRWVR0QlFWRmlMR0ZCVW1FN1FVRlRZaXhoUVZSaE8wRkJWV0lzWVVGV1lUdEJRVmRpTEZsQldHRTdRVUZaWWl4VFFWcGhPMEZCWVdJc1pVRmlZVHRCUVdOaUxGVkJaR0U3UVVGbFlpeFhRV1poTzBGQlowSmlMRlZCYUVKaE8wRkJhVUppTEdOQmFrSmhPME5CUVdZaUxDSm1hV3hsSWpvaWJHbGlMMk52Y21VdmNHRjBkR1Z5Ym5NdlkyaGxZMnR6TG1weklpd2ljMjkxY21ObGMwTnZiblJsYm5RaU9sc2lMeW9nUUdac2IzY2dLaTljYmx4dWFXMXdiM0owSUhzZ1ZtRnlhV0ZpYkdVc0lGZHBiR1JqWVhKa0xDQklaV0ZrVkdGcGJDd2dRMkZ3ZEhWeVpTd2dWSGx3WlN3Z1UzUmhjblJ6VjJsMGFDd2dRbTkxYm1Rc0lFSnBkRk4wY21sdVowMWhkR05vSUgwZ1puSnZiU0JjSWk0dmRIbHdaWE5jSWp0Y2JseHVablZ1WTNScGIyNGdhWE5mYm5WdFltVnlLSFpoYkhWbE9pQmhibmtwT2lCaWIyOXNaV0Z1SUh0Y2JpQWdjbVYwZFhKdUlIUjVjR1Z2WmlCMllXeDFaU0E5UFQwZ0oyNTFiV0psY2ljN1hHNTlYRzVjYm1aMWJtTjBhVzl1SUdselgzTjBjbWx1WnloMllXeDFaVG9nWVc1NUtUb2dZbTl2YkdWaGJudGNiaUFnY21WMGRYSnVJSFI1Y0dWdlppQjJZV3gxWlNBOVBUMGdKM04wY21sdVp5YzdYRzU5WEc1Y2JtWjFibU4wYVc5dUlHbHpYMkp2YjJ4bFlXNG9kbUZzZFdVNklHRnVlU2s2SUdKdmIyeGxZVzRnZTF4dUlDQnlaWFIxY200Z2RIbHdaVzltSUhaaGJIVmxJRDA5UFNBblltOXZiR1ZoYmljN1hHNTlYRzVjYm1aMWJtTjBhVzl1SUdselgzTjViV0p2YkNoMllXeDFaVG9nWVc1NUtUb2dZbTl2YkdWaGJpQjdYRzRnSUhKbGRIVnliaUIwZVhCbGIyWWdkbUZzZFdVZ1BUMDlJQ2R6ZVcxaWIyd25PMXh1ZlZ4dVhHNW1kVzVqZEdsdmJpQnBjMTl1ZFd4c0tIWmhiSFZsT2lCaGJua3BPaUJpYjI5c1pXRnVJSHRjYmlBZ2NtVjBkWEp1SUhaaGJIVmxJRDA5UFNCdWRXeHNPMXh1ZlZ4dVhHNW1kVzVqZEdsdmJpQnBjMTkxYm1SbFptbHVaV1FvZG1Gc2RXVTZJR0Z1ZVNrNklHSnZiMnhsWVc0Z2UxeHVJQ0J5WlhSMWNtNGdkSGx3Wlc5bUlIWmhiSFZsSUQwOVBTQW5kVzVrWldacGJtVmtKenRjYm4xY2JseHVablZ1WTNScGIyNGdhWE5mWm5WdVkzUnBiMjRvZG1Gc2RXVTZJR0Z1ZVNrNklHSnZiMnhsWVc0Z2UxeHVJQ0J5WlhSMWNtNGdUMkpxWldOMExuQnliM1J2ZEhsd1pTNTBiMU4wY21sdVp5NWpZV3hzS0haaGJIVmxLU0E5UFNBblcyOWlhbVZqZENCR2RXNWpkR2x2Ymwwbk8xeHVmVnh1WEc1bWRXNWpkR2x2YmlCcGMxOTJZWEpwWVdKc1pTaDJZV3gxWlRvZ1lXNTVLVG9nWW05dmJHVmhiaUI3WEc0Z0lISmxkSFZ5YmlCMllXeDFaU0JwYm5OMFlXNWpaVzltSUZaaGNtbGhZbXhsTzF4dWZWeHVYRzVtZFc1amRHbHZiaUJwYzE5M2FXeGtZMkZ5WkNoMllXeDFaVG9nWVc1NUtUb2dZbTl2YkdWaGJpQjdYRzRnSUhKbGRIVnliaUIyWVd4MVpTQnBibk4wWVc1alpXOW1JRmRwYkdSallYSmtPMXh1ZlZ4dVhHNW1kVzVqZEdsdmJpQnBjMTlvWldGa1ZHRnBiQ2gyWVd4MVpUb2dZVzU1S1RvZ1ltOXZiR1ZoYmlCN1hHNGdJSEpsZEhWeWJpQjJZV3gxWlNCcGJuTjBZVzVqWlc5bUlFaGxZV1JVWVdsc08xeHVmVnh1WEc1bWRXNWpkR2x2YmlCcGMxOWpZWEIwZFhKbEtIWmhiSFZsT2lCaGJua3BPaUJpYjI5c1pXRnVJSHRjYmlBZ2NtVjBkWEp1SUhaaGJIVmxJR2x1YzNSaGJtTmxiMllnUTJGd2RIVnlaVHRjYm4xY2JseHVablZ1WTNScGIyNGdhWE5mZEhsd1pTaDJZV3gxWlRvZ1lXNTVLVG9nWW05dmJHVmhiaUI3WEc0Z0lISmxkSFZ5YmlCMllXeDFaU0JwYm5OMFlXNWpaVzltSUZSNWNHVTdYRzU5WEc1Y2JtWjFibU4wYVc5dUlHbHpYM04wWVhKMGMxZHBkR2dvZG1Gc2RXVTZJR0Z1ZVNrNklHSnZiMnhsWVc0Z2UxeHVJQ0J5WlhSMWNtNGdkbUZzZFdVZ2FXNXpkR0Z1WTJWdlppQlRkR0Z5ZEhOWGFYUm9PMXh1ZlZ4dVhHNW1kVzVqZEdsdmJpQnBjMTlpYjNWdVpDaDJZV3gxWlRvZ1lXNTVLVG9nWW05dmJHVmhiaUI3WEc0Z0lISmxkSFZ5YmlCMllXeDFaU0JwYm5OMFlXNWpaVzltSUVKdmRXNWtPMXh1ZlZ4dVhHNW1kVzVqZEdsdmJpQnBjMTl2WW1wbFkzUW9kbUZzZFdVNklHRnVlU2s2SUdKdmIyeGxZVzRnZTF4dUlDQnlaWFIxY200Z2RIbHdaVzltSUhaaGJIVmxJRDA5UFNBbmIySnFaV04wSnp0Y2JuMWNibHh1Wm5WdVkzUnBiMjRnYVhOZllYSnlZWGtvZG1Gc2RXVTZJR0Z1ZVNrNklHSnZiMnhsWVc0Z2UxeHVJQ0J5WlhSMWNtNGdRWEp5WVhrdWFYTkJjbkpoZVNoMllXeDFaU2s3WEc1OVhHNWNibVoxYm1OMGFXOXVJR2x6WDJKcGRITjBjbWx1WnloMllXeDFaVG9nWVc1NUtUb2dZbTl2YkdWaGJpQjdYRzRnSUhKbGRIVnliaUIyWVd4MVpTQnBibk4wWVc1alpXOW1JRUpwZEZOMGNtbHVaMDFoZEdOb08xeHVmVnh1WEc1Y2JtVjRjRzl5ZENCa1pXWmhkV3gwSUh0Y2JpQWdhWE5mYm5WdFltVnlMRnh1SUNCcGMxOXpkSEpwYm1jc1hHNGdJR2x6WDJKdmIyeGxZVzRzWEc0Z0lHbHpYM041YldKdmJDeGNiaUFnYVhOZmJuVnNiQ3hjYmlBZ2FYTmZkVzVrWldacGJtVmtMRnh1SUNCcGMxOW1kVzVqZEdsdmJpeGNiaUFnYVhOZmRtRnlhV0ZpYkdVc1hHNGdJR2x6WDNkcGJHUmpZWEprTEZ4dUlDQnBjMTlvWldGa1ZHRnBiQ3hjYmlBZ2FYTmZZMkZ3ZEhWeVpTeGNiaUFnYVhOZmRIbHdaU3hjYmlBZ2FYTmZjM1JoY25SelYybDBhQ3hjYmlBZ2FYTmZZbTkxYm1Rc1hHNGdJR2x6WDI5aWFtVmpkQ3hjYmlBZ2FYTmZZWEp5WVhrc1hHNGdJR2x6WDJKcGRITjBjbWx1WjF4dWZUdGNiaUpkTENKemIzVnlZMlZTYjI5MElqb2lMM052ZFhKalpTOGlmUT09XG4iLCJcblxuaW1wb3J0IENoZWNrcyBmcm9tIFwiLi9jaGVja3NcIjtcbmltcG9ydCAqIGFzIFR5cGVzIGZyb20gXCIuL3R5cGVzXCI7XG5pbXBvcnQgeyBidWlsZE1hdGNoIH0gZnJvbSBcIi4vbWF0Y2hcIjtcbmltcG9ydCBCaXRTdHJpbmcgZnJvbSBcIi4uL2JpdF9zdHJpbmdcIjtcblxuZnVuY3Rpb24gcmVzb2x2ZVN5bWJvbChwYXR0ZXJuKSB7XG4gIHJldHVybiBmdW5jdGlvbiAodmFsdWUpIHtcbiAgICByZXR1cm4gQ2hlY2tzLmlzX3N5bWJvbCh2YWx1ZSkgJiYgdmFsdWUgPT09IHBhdHRlcm47XG4gIH07XG59XG5cbmZ1bmN0aW9uIHJlc29sdmVTdHJpbmcocGF0dGVybikge1xuICByZXR1cm4gZnVuY3Rpb24gKHZhbHVlKSB7XG4gICAgcmV0dXJuIENoZWNrcy5pc19zdHJpbmcodmFsdWUpICYmIHZhbHVlID09PSBwYXR0ZXJuO1xuICB9O1xufVxuXG5mdW5jdGlvbiByZXNvbHZlTnVtYmVyKHBhdHRlcm4pIHtcbiAgcmV0dXJuIGZ1bmN0aW9uICh2YWx1ZSkge1xuICAgIHJldHVybiBDaGVja3MuaXNfbnVtYmVyKHZhbHVlKSAmJiB2YWx1ZSA9PT0gcGF0dGVybjtcbiAgfTtcbn1cblxuZnVuY3Rpb24gcmVzb2x2ZUJvb2xlYW4ocGF0dGVybikge1xuICByZXR1cm4gZnVuY3Rpb24gKHZhbHVlKSB7XG4gICAgcmV0dXJuIENoZWNrcy5pc19ib29sZWFuKHZhbHVlKSAmJiB2YWx1ZSA9PT0gcGF0dGVybjtcbiAgfTtcbn1cblxuZnVuY3Rpb24gcmVzb2x2ZUZ1bmN0aW9uKHBhdHRlcm4pIHtcbiAgcmV0dXJuIGZ1bmN0aW9uICh2YWx1ZSkge1xuICAgIHJldHVybiBDaGVja3MuaXNfZnVuY3Rpb24odmFsdWUpICYmIHZhbHVlID09PSBwYXR0ZXJuO1xuICB9O1xufVxuXG5mdW5jdGlvbiByZXNvbHZlTnVsbChwYXR0ZXJuKSB7XG4gIHJldHVybiBmdW5jdGlvbiAodmFsdWUpIHtcbiAgICByZXR1cm4gQ2hlY2tzLmlzX251bGwodmFsdWUpO1xuICB9O1xufVxuXG5mdW5jdGlvbiByZXNvbHZlQm91bmQocGF0dGVybikge1xuICByZXR1cm4gZnVuY3Rpb24gKHZhbHVlLCBhcmdzKSB7XG4gICAgaWYgKHR5cGVvZiB2YWx1ZSA9PT0gdHlwZW9mIHBhdHRlcm4udmFsdWUgJiYgdmFsdWUgPT09IHBhdHRlcm4udmFsdWUpIHtcbiAgICAgIGFyZ3MucHVzaCh2YWx1ZSk7XG4gICAgICByZXR1cm4gdHJ1ZTtcbiAgICB9XG5cbiAgICByZXR1cm4gZmFsc2U7XG4gIH07XG59XG5cbmZ1bmN0aW9uIHJlc29sdmVXaWxkY2FyZCgpIHtcbiAgcmV0dXJuIGZ1bmN0aW9uICgpIHtcbiAgICByZXR1cm4gdHJ1ZTtcbiAgfTtcbn1cblxuZnVuY3Rpb24gcmVzb2x2ZVZhcmlhYmxlKCkge1xuICByZXR1cm4gZnVuY3Rpb24gKHZhbHVlLCBhcmdzKSB7XG4gICAgYXJncy5wdXNoKHZhbHVlKTtcbiAgICByZXR1cm4gdHJ1ZTtcbiAgfTtcbn1cblxuZnVuY3Rpb24gcmVzb2x2ZUhlYWRUYWlsKHBhdHRlcm4pIHtcbiAgY29uc3QgaGVhZE1hdGNoZXMgPSBidWlsZE1hdGNoKHBhdHRlcm4uaGVhZCk7XG4gIGNvbnN0IHRhaWxNYXRjaGVzID0gYnVpbGRNYXRjaChwYXR0ZXJuLnRhaWwpO1xuXG4gIHJldHVybiBmdW5jdGlvbiAodmFsdWUsIGFyZ3MpIHtcbiAgICBpZiAoIUNoZWNrcy5pc19hcnJheSh2YWx1ZSkgfHwgdmFsdWUubGVuZ3RoIDwgMikge1xuICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH1cblxuICAgIGNvbnN0IGhlYWQgPSB2YWx1ZVswXTtcbiAgICBjb25zdCB0YWlsID0gdmFsdWUuc2xpY2UoMSk7XG5cbiAgICBpZiAoaGVhZE1hdGNoZXMoaGVhZCwgYXJncykgJiYgdGFpbE1hdGNoZXModGFpbCwgYXJncykpIHtcbiAgICAgIHJldHVybiB0cnVlO1xuICAgIH1cbiAgfTtcbn1cblxuZnVuY3Rpb24gcmVzb2x2ZUNhcHR1cmUocGF0dGVybikge1xuICBjb25zdCBtYXRjaGVzID0gYnVpbGRNYXRjaChwYXR0ZXJuLnZhbHVlKTtcblxuICByZXR1cm4gZnVuY3Rpb24gKHZhbHVlLCBhcmdzKSB7XG4gICAgaWYgKG1hdGNoZXModmFsdWUsIGFyZ3MpKSB7XG4gICAgICBhcmdzLnB1c2godmFsdWUpO1xuICAgICAgcmV0dXJuIHRydWU7XG4gICAgfVxuXG4gICAgcmV0dXJuIGZhbHNlO1xuICB9O1xufVxuXG5mdW5jdGlvbiByZXNvbHZlU3RhcnRzV2l0aChwYXR0ZXJuKSB7XG4gIGNvbnN0IHByZWZpeCA9IHBhdHRlcm4ucHJlZml4O1xuXG4gIHJldHVybiBmdW5jdGlvbiAodmFsdWUsIGFyZ3MpIHtcbiAgICBpZiAoQ2hlY2tzLmlzX3N0cmluZyh2YWx1ZSkgJiYgdmFsdWUuc3RhcnRzV2l0aChwcmVmaXgpKSB7XG4gICAgICBhcmdzLnB1c2godmFsdWUuc3Vic3RyaW5nKHByZWZpeC5sZW5ndGgpKTtcbiAgICAgIHJldHVybiB0cnVlO1xuICAgIH1cblxuICAgIHJldHVybiBmYWxzZTtcbiAgfTtcbn1cblxuZnVuY3Rpb24gcmVzb2x2ZVR5cGUocGF0dGVybikge1xuICByZXR1cm4gZnVuY3Rpb24gKHZhbHVlLCBhcmdzKSB7XG4gICAgaWYgKHZhbHVlIGluc3RhbmNlb2YgcGF0dGVybi50eXBlKSB7XG4gICAgICBjb25zdCBtYXRjaGVzID0gYnVpbGRNYXRjaChwYXR0ZXJuLm9ialBhdHRlcm4pO1xuICAgICAgcmV0dXJuIG1hdGNoZXModmFsdWUsIGFyZ3MpICYmIGFyZ3MucHVzaCh2YWx1ZSkgPiAwO1xuICAgIH1cblxuICAgIHJldHVybiBmYWxzZTtcbiAgfTtcbn1cblxuZnVuY3Rpb24gcmVzb2x2ZUFycmF5KHBhdHRlcm4pIHtcbiAgY29uc3QgbWF0Y2hlcyA9IHBhdHRlcm4ubWFwKHggPT4gYnVpbGRNYXRjaCh4KSk7XG5cbiAgcmV0dXJuIGZ1bmN0aW9uICh2YWx1ZSwgYXJncykge1xuICAgIGlmICghQ2hlY2tzLmlzX2FycmF5KHZhbHVlKSB8fCB2YWx1ZS5sZW5ndGggIT0gcGF0dGVybi5sZW5ndGgpIHtcbiAgICAgIHJldHVybiBmYWxzZTtcbiAgICB9XG5cbiAgICByZXR1cm4gdmFsdWUuZXZlcnkoZnVuY3Rpb24gKHYsIGkpIHtcbiAgICAgIHJldHVybiBtYXRjaGVzW2ldKHZhbHVlW2ldLCBhcmdzKTtcbiAgICB9KTtcbiAgfTtcbn1cblxuZnVuY3Rpb24gcmVzb2x2ZU9iamVjdChwYXR0ZXJuKSB7XG4gIGxldCBtYXRjaGVzID0ge307XG5cbiAgZm9yIChsZXQga2V5IG9mIE9iamVjdC5rZXlzKHBhdHRlcm4pLmNvbmNhdChPYmplY3QuZ2V0T3duUHJvcGVydHlTeW1ib2xzKHBhdHRlcm4pKSkge1xuICAgIG1hdGNoZXNba2V5XSA9IGJ1aWxkTWF0Y2gocGF0dGVybltrZXldKTtcbiAgfVxuXG4gIHJldHVybiBmdW5jdGlvbiAodmFsdWUsIGFyZ3MpIHtcbiAgICBpZiAoIUNoZWNrcy5pc19vYmplY3QodmFsdWUpIHx8IHBhdHRlcm4ubGVuZ3RoID4gdmFsdWUubGVuZ3RoKSB7XG4gICAgICByZXR1cm4gZmFsc2U7XG4gICAgfVxuXG4gICAgZm9yIChsZXQga2V5IG9mIE9iamVjdC5rZXlzKHBhdHRlcm4pLmNvbmNhdChPYmplY3QuZ2V0T3duUHJvcGVydHlTeW1ib2xzKHBhdHRlcm4pKSkge1xuICAgICAgaWYgKCEoa2V5IGluIHZhbHVlKSB8fCAhbWF0Y2hlc1trZXldKHZhbHVlW2tleV0sIGFyZ3MpKSB7XG4gICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICByZXR1cm4gdHJ1ZTtcbiAgfTtcbn1cblxuZnVuY3Rpb24gcmVzb2x2ZUJpdFN0cmluZyhwYXR0ZXJuKSB7XG4gIGxldCBwYXR0ZXJuQml0U3RyaW5nID0gW107XG5cbiAgZm9yIChsZXQgYml0c3RyaW5nTWF0Y2hQYXJ0IG9mIHBhdHRlcm4udmFsdWVzKSB7XG4gICAgaWYgKENoZWNrcy5pc192YXJpYWJsZShiaXRzdHJpbmdNYXRjaFBhcnQudmFsdWUpKSB7XG4gICAgICBsZXQgc2l6ZSA9IGdldFNpemUoYml0c3RyaW5nTWF0Y2hQYXJ0LnVuaXQsIGJpdHN0cmluZ01hdGNoUGFydC5zaXplKTtcbiAgICAgIGZpbGxBcnJheShwYXR0ZXJuQml0U3RyaW5nLCBzaXplKTtcbiAgICB9IGVsc2Uge1xuICAgICAgcGF0dGVybkJpdFN0cmluZyA9IHBhdHRlcm5CaXRTdHJpbmcuY29uY2F0KG5ldyBCaXRTdHJpbmcoYml0c3RyaW5nTWF0Y2hQYXJ0KS52YWx1ZSk7XG4gICAgfVxuICB9XG5cbiAgbGV0IHBhdHRlcm5WYWx1ZXMgPSBwYXR0ZXJuLnZhbHVlcztcblxuICByZXR1cm4gZnVuY3Rpb24gKHZhbHVlLCBhcmdzKSB7XG4gICAgbGV0IGJzVmFsdWUgPSBudWxsO1xuXG4gICAgaWYgKCFDaGVja3MuaXNfc3RyaW5nKHZhbHVlKSAmJiAhKHZhbHVlIGluc3RhbmNlb2YgQml0U3RyaW5nKSkge1xuICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH1cblxuICAgIGlmIChDaGVja3MuaXNfc3RyaW5nKHZhbHVlKSkge1xuICAgICAgYnNWYWx1ZSA9IG5ldyBCaXRTdHJpbmcoQml0U3RyaW5nLmJpbmFyeSh2YWx1ZSkpO1xuICAgIH0gZWxzZSB7XG4gICAgICBic1ZhbHVlID0gdmFsdWU7XG4gICAgfVxuXG4gICAgbGV0IGJlZ2lubmluZ0luZGV4ID0gMDtcblxuICAgIGZvciAobGV0IGkgPSAwOyBpIDwgcGF0dGVyblZhbHVlcy5sZW5ndGg7IGkrKykge1xuICAgICAgbGV0IGJpdHN0cmluZ01hdGNoUGFydCA9IHBhdHRlcm5WYWx1ZXNbaV07XG5cbiAgICAgIGlmIChDaGVja3MuaXNfdmFyaWFibGUoYml0c3RyaW5nTWF0Y2hQYXJ0LnZhbHVlKSAmJiBiaXRzdHJpbmdNYXRjaFBhcnQudHlwZSA9PSAnYmluYXJ5JyAmJiBiaXRzdHJpbmdNYXRjaFBhcnQuc2l6ZSA9PT0gdW5kZWZpbmVkICYmIGkgPCBwYXR0ZXJuVmFsdWVzLmxlbmd0aCAtIDEpIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKFwiYSBiaW5hcnkgZmllbGQgd2l0aG91dCBzaXplIGlzIG9ubHkgYWxsb3dlZCBhdCB0aGUgZW5kIG9mIGEgYmluYXJ5IHBhdHRlcm5cIik7XG4gICAgICB9XG5cbiAgICAgIGxldCBzaXplID0gMDtcbiAgICAgIGxldCBic1ZhbHVlQXJyYXlQYXJ0ID0gW107XG4gICAgICBsZXQgcGF0dGVybkJpdFN0cmluZ0FycmF5UGFydCA9IFtdO1xuICAgICAgc2l6ZSA9IGdldFNpemUoYml0c3RyaW5nTWF0Y2hQYXJ0LnVuaXQsIGJpdHN0cmluZ01hdGNoUGFydC5zaXplKTtcblxuICAgICAgaWYgKGkgPT09IHBhdHRlcm5WYWx1ZXMubGVuZ3RoIC0gMSkge1xuICAgICAgICBic1ZhbHVlQXJyYXlQYXJ0ID0gYnNWYWx1ZS52YWx1ZS5zbGljZShiZWdpbm5pbmdJbmRleCk7XG4gICAgICAgIHBhdHRlcm5CaXRTdHJpbmdBcnJheVBhcnQgPSBwYXR0ZXJuQml0U3RyaW5nLnNsaWNlKGJlZ2lubmluZ0luZGV4KTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIGJzVmFsdWVBcnJheVBhcnQgPSBic1ZhbHVlLnZhbHVlLnNsaWNlKGJlZ2lubmluZ0luZGV4LCBiZWdpbm5pbmdJbmRleCArIHNpemUpO1xuICAgICAgICBwYXR0ZXJuQml0U3RyaW5nQXJyYXlQYXJ0ID0gcGF0dGVybkJpdFN0cmluZy5zbGljZShiZWdpbm5pbmdJbmRleCwgYmVnaW5uaW5nSW5kZXggKyBzaXplKTtcbiAgICAgIH1cblxuICAgICAgaWYgKENoZWNrcy5pc192YXJpYWJsZShiaXRzdHJpbmdNYXRjaFBhcnQudmFsdWUpKSB7XG4gICAgICAgIHN3aXRjaCAoYml0c3RyaW5nTWF0Y2hQYXJ0LnR5cGUpIHtcbiAgICAgICAgICBjYXNlICdpbnRlZ2VyJzpcbiAgICAgICAgICAgIGlmIChiaXRzdHJpbmdNYXRjaFBhcnQuYXR0cmlidXRlcyAmJiBiaXRzdHJpbmdNYXRjaFBhcnQuYXR0cmlidXRlcy5pbmRleE9mKFwic2lnbmVkXCIpICE9IC0xKSB7XG4gICAgICAgICAgICAgIGFyZ3MucHVzaChuZXcgSW50OEFycmF5KFtic1ZhbHVlQXJyYXlQYXJ0WzBdXSlbMF0pO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgYXJncy5wdXNoKG5ldyBVaW50OEFycmF5KFtic1ZhbHVlQXJyYXlQYXJ0WzBdXSlbMF0pO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgYnJlYWs7XG5cbiAgICAgICAgICBjYXNlICdmbG9hdCc6XG4gICAgICAgICAgICBpZiAoc2l6ZSA9PT0gNjQpIHtcbiAgICAgICAgICAgICAgYXJncy5wdXNoKEZsb2F0NjRBcnJheS5mcm9tKGJzVmFsdWVBcnJheVBhcnQpWzBdKTtcbiAgICAgICAgICAgIH0gZWxzZSBpZiAoc2l6ZSA9PT0gMzIpIHtcbiAgICAgICAgICAgICAgYXJncy5wdXNoKEZsb2F0MzJBcnJheS5mcm9tKGJzVmFsdWVBcnJheVBhcnQpWzBdKTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGJyZWFrO1xuXG4gICAgICAgICAgY2FzZSAnYml0c3RyaW5nJzpcbiAgICAgICAgICAgIGFyZ3MucHVzaChjcmVhdGVCaXRTdHJpbmcoYnNWYWx1ZUFycmF5UGFydCkpO1xuICAgICAgICAgICAgYnJlYWs7XG5cbiAgICAgICAgICBjYXNlICdiaW5hcnknOlxuICAgICAgICAgICAgYXJncy5wdXNoKFN0cmluZy5mcm9tQ2hhckNvZGUuYXBwbHkobnVsbCwgbmV3IFVpbnQ4QXJyYXkoYnNWYWx1ZUFycmF5UGFydCkpKTtcbiAgICAgICAgICAgIGJyZWFrO1xuXG4gICAgICAgICAgY2FzZSAndXRmOCc6XG4gICAgICAgICAgICBhcmdzLnB1c2goU3RyaW5nLmZyb21DaGFyQ29kZS5hcHBseShudWxsLCBuZXcgVWludDhBcnJheShic1ZhbHVlQXJyYXlQYXJ0KSkpO1xuICAgICAgICAgICAgYnJlYWs7XG5cbiAgICAgICAgICBjYXNlICd1dGYxNic6XG4gICAgICAgICAgICBhcmdzLnB1c2goU3RyaW5nLmZyb21DaGFyQ29kZS5hcHBseShudWxsLCBuZXcgVWludDE2QXJyYXkoYnNWYWx1ZUFycmF5UGFydCkpKTtcbiAgICAgICAgICAgIGJyZWFrO1xuXG4gICAgICAgICAgY2FzZSAndXRmMzInOlxuICAgICAgICAgICAgYXJncy5wdXNoKFN0cmluZy5mcm9tQ2hhckNvZGUuYXBwbHkobnVsbCwgbmV3IFVpbnQzMkFycmF5KGJzVmFsdWVBcnJheVBhcnQpKSk7XG4gICAgICAgICAgICBicmVhaztcblxuICAgICAgICAgIGRlZmF1bHQ6XG4gICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgIH1cbiAgICAgIH0gZWxzZSBpZiAoIWFycmF5c0VxdWFsKGJzVmFsdWVBcnJheVBhcnQsIHBhdHRlcm5CaXRTdHJpbmdBcnJheVBhcnQpKSB7XG4gICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgIH1cblxuICAgICAgYmVnaW5uaW5nSW5kZXggPSBiZWdpbm5pbmdJbmRleCArIHNpemU7XG4gICAgfVxuXG4gICAgcmV0dXJuIHRydWU7XG4gIH07XG59XG5cbmZ1bmN0aW9uIGdldFNpemUodW5pdCwgc2l6ZSkge1xuICByZXR1cm4gdW5pdCAqIHNpemUgLyA4O1xufVxuXG5mdW5jdGlvbiBhcnJheXNFcXVhbChhLCBiKSB7XG4gIGlmIChhID09PSBiKSByZXR1cm4gdHJ1ZTtcbiAgaWYgKGEgPT0gbnVsbCB8fCBiID09IG51bGwpIHJldHVybiBmYWxzZTtcbiAgaWYgKGEubGVuZ3RoICE9IGIubGVuZ3RoKSByZXR1cm4gZmFsc2U7XG5cbiAgZm9yICh2YXIgaSA9IDA7IGkgPCBhLmxlbmd0aDsgKytpKSB7XG4gICAgaWYgKGFbaV0gIT09IGJbaV0pIHJldHVybiBmYWxzZTtcbiAgfVxuXG4gIHJldHVybiB0cnVlO1xufVxuXG5mdW5jdGlvbiBmaWxsQXJyYXkoYXJyLCBudW0pIHtcbiAgZm9yIChsZXQgaSA9IDA7IGkgPCBudW07IGkrKykge1xuICAgIGFyci5wdXNoKDApO1xuICB9XG59XG5cbmZ1bmN0aW9uIGNyZWF0ZUJpdFN0cmluZyhhcnIpIHtcbiAgbGV0IGludGVnZXJQYXJ0cyA9IGFyci5tYXAoZWxlbSA9PiBCaXRTdHJpbmcuaW50ZWdlcihlbGVtKSk7XG4gIHJldHVybiBuZXcgQml0U3RyaW5nKC4uLmludGVnZXJQYXJ0cyk7XG59XG5cbmZ1bmN0aW9uIHJlc29sdmVOb01hdGNoKCkge1xuICByZXR1cm4gZnVuY3Rpb24gKCkge1xuICAgIHJldHVybiBmYWxzZTtcbiAgfTtcbn1cblxuZXhwb3J0IGRlZmF1bHQge1xuICByZXNvbHZlQm91bmQsXG4gIHJlc29sdmVXaWxkY2FyZCxcbiAgcmVzb2x2ZVZhcmlhYmxlLFxuICByZXNvbHZlSGVhZFRhaWwsXG4gIHJlc29sdmVDYXB0dXJlLFxuICByZXNvbHZlU3RhcnRzV2l0aCxcbiAgcmVzb2x2ZVR5cGUsXG4gIHJlc29sdmVBcnJheSxcbiAgcmVzb2x2ZU9iamVjdCxcbiAgcmVzb2x2ZU5vTWF0Y2gsXG4gIHJlc29sdmVTeW1ib2wsXG4gIHJlc29sdmVTdHJpbmcsXG4gIHJlc29sdmVOdW1iZXIsXG4gIHJlc29sdmVCb29sZWFuLFxuICByZXNvbHZlRnVuY3Rpb24sXG4gIHJlc29sdmVOdWxsLFxuICByZXNvbHZlQml0U3RyaW5nXG59O1xuLy8jIHNvdXJjZU1hcHBpbmdVUkw9ZGF0YTphcHBsaWNhdGlvbi9qc29uO2Jhc2U2NCxleUoyWlhKemFXOXVJam96TENKemIzVnlZMlZ6SWpwYklteHBZaTlqYjNKbEwzQmhkSFJsY201ekwzSmxjMjlzZG1WeWN5NXFjeUpkTENKdVlXMWxjeUk2VzEwc0ltMWhjSEJwYm1keklqb2lPenRCUVVWQkxFOUJRVThzVFVGQlVDeE5RVUZ0UWl4VlFVRnVRanRCUVVOQkxFOUJRVThzUzBGQlN5eExRVUZNTEUxQlFXZENMRk5CUVhaQ08wRkJRMEVzVTBGQlV5eFZRVUZVTEZGQlFUSkNMRk5CUVROQ08wRkJRMEVzVDBGQlR5eFRRVUZRTEUxQlFYTkNMR1ZCUVhSQ096dEJRVVZCTEZOQlFWTXNZVUZCVkN4RFFVRjFRaXhQUVVGMlFpeEZRVUVyUXp0QlFVTTNReXhUUVVGUExGVkJRVk1zUzBGQlZDeEZRVUU0UWp0QlFVTnVReXhYUVVGUExFOUJRVThzVTBGQlVDeERRVUZwUWl4TFFVRnFRaXhMUVVFeVFpeFZRVUZWTEU5QlFWWXNRMEZFUXp0SFFVRTVRaXhEUVVSelF6dERRVUV2UXpzN1FVRk5RU3hUUVVGVExHRkJRVlFzUTBGQmRVSXNUMEZCZGtJc1JVRkJLME03UVVGRE4wTXNVMEZCVHl4VlFVRlRMRXRCUVZRc1JVRkJPRUk3UVVGRGJrTXNWMEZCVHl4UFFVRlBMRk5CUVZBc1EwRkJhVUlzUzBGQmFrSXNTMEZCTWtJc1ZVRkJWU3hQUVVGV0xFTkJSRU03UjBGQk9VSXNRMEZFYzBNN1EwRkJMME03TzBGQlRVRXNVMEZCVXl4aFFVRlVMRU5CUVhWQ0xFOUJRWFpDTEVWQlFTdERPMEZCUXpkRExGTkJRVThzVlVGQlV5eExRVUZVTEVWQlFUaENPMEZCUTI1RExGZEJRVThzVDBGQlR5eFRRVUZRTEVOQlFXbENMRXRCUVdwQ0xFdEJRVEpDTEZWQlFWVXNUMEZCVml4RFFVUkRPMGRCUVRsQ0xFTkJSSE5ETzBOQlFTOURPenRCUVUxQkxGTkJRVk1zWTBGQlZDeERRVUYzUWl4UFFVRjRRaXhGUVVGblJEdEJRVU01UXl4VFFVRlBMRlZCUVZNc1MwRkJWQ3hGUVVFNFFqdEJRVU51UXl4WFFVRlBMRTlCUVU4c1ZVRkJVQ3hEUVVGclFpeExRVUZzUWl4TFFVRTBRaXhWUVVGVkxFOUJRVllzUTBGRVFUdEhRVUU1UWl4RFFVUjFRenREUVVGb1JEczdRVUZOUVN4VFFVRlRMR1ZCUVZRc1EwRkJlVUlzVDBGQmVrSXNSVUZCYVVRN1FVRkRMME1zVTBGQlR5eFZRVUZUTEV0QlFWUXNSVUZCT0VJN1FVRkRia01zVjBGQlR5eFBRVUZQTEZkQlFWQXNRMEZCYlVJc1MwRkJia0lzUzBGQk5rSXNWVUZCVlN4UFFVRldMRU5CUkVRN1IwRkJPVUlzUTBGRWQwTTdRMEZCYWtRN08wRkJUVUVzVTBGQlV5eFhRVUZVTEVOQlFYRkNMRTlCUVhKQ0xFVkJRVFpETzBGQlF6TkRMRk5CUVU4c1ZVRkJVeXhMUVVGVUxFVkJRVGhDTzBGQlEyNURMRmRCUVU4c1QwRkJUeXhQUVVGUUxFTkJRV1VzUzBGQlppeERRVUZRTEVOQlJHMURPMGRCUVRsQ0xFTkJSRzlETzBOQlFUZERPenRCUVUxQkxGTkJRVk1zV1VGQlZDeERRVUZ6UWl4UFFVRjBRaXhGUVVGelJEdEJRVU53UkN4VFFVRlBMRlZCUVZNc1MwRkJWQ3hGUVVGeFFpeEpRVUZ5UWl4RlFVRm5SRHRCUVVOeVJDeFJRVUZITEU5QlFVOHNTMEZCVUN4TFFVRnBRaXhQUVVGUExGRkJRVkVzUzBGQlVpeEpRVUZwUWl4VlFVRlZMRkZCUVZFc1MwRkJVaXhGUVVGak8wRkJRMnhGTEZkQlFVc3NTVUZCVEN4RFFVRlZMRXRCUVZZc1JVRkVhMFU3UVVGRmJFVXNZVUZCVHl4SlFVRlFMRU5CUm10Rk8wdEJRWEJGT3p0QlFVdEJMRmRCUVU4c1MwRkJVQ3hEUVU1eFJEdEhRVUZvUkN4RFFVUTJRenREUVVGMFJEczdRVUZYUVN4VFFVRlRMR1ZCUVZRc1IwRkJjVU03UVVGRGJrTXNVMEZCVHl4WlFVRnZRanRCUVVONlFpeFhRVUZQTEVsQlFWQXNRMEZFZVVJN1IwRkJjRUlzUTBGRU5FSTdRMEZCY2tNN08wRkJUVUVzVTBGQlV5eGxRVUZVTEVkQlFYRkRPMEZCUTI1RExGTkJRVThzVlVGQlV5eExRVUZVTEVWQlFYRkNMRWxCUVhKQ0xFVkJRV2RFTzBGQlEzSkVMRk5CUVVzc1NVRkJUQ3hEUVVGVkxFdEJRVllzUlVGRWNVUTdRVUZGY2tRc1YwRkJUeXhKUVVGUUxFTkJSbkZFTzBkQlFXaEVMRU5CUkRSQ08wTkJRWEpET3p0QlFVOUJMRk5CUVZNc1pVRkJWQ3hEUVVGNVFpeFBRVUY2UWl4RlFVRTBSRHRCUVVNeFJDeFJRVUZOTEdOQlFXTXNWMEZCVnl4UlFVRlJMRWxCUVZJc1EwRkJla0lzUTBGRWIwUTdRVUZGTVVRc1VVRkJUU3hqUVVGakxGZEJRVmNzVVVGQlVTeEpRVUZTTEVOQlFYcENMRU5CUm05RU96dEJRVWt4UkN4VFFVRlBMRlZCUVZNc1MwRkJWQ3hGUVVGeFFpeEpRVUZ5UWl4RlFVRm5SRHRCUVVOeVJDeFJRVUZITEVOQlFVTXNUMEZCVHl4UlFVRlFMRU5CUVdkQ0xFdEJRV2hDTEVOQlFVUXNTVUZCTWtJc1RVRkJUU3hOUVVGT0xFZEJRV1VzUTBGQlppeEZRVUZwUWp0QlFVTTNReXhoUVVGUExFdEJRVkFzUTBGRU5rTTdTMEZCTDBNN08wRkJTVUVzVlVGQlRTeFBRVUZQTEUxQlFVMHNRMEZCVGl4RFFVRlFMRU5CVEN0RE8wRkJUWEpFTEZWQlFVMHNUMEZCVHl4TlFVRk5MRXRCUVU0c1EwRkJXU3hEUVVGYUxFTkJRVkFzUTBGT0swTTdPMEZCVVhKRUxGRkJRVWNzV1VGQldTeEpRVUZhTEVWQlFXdENMRWxCUVd4Q0xFdEJRVEpDTEZsQlFWa3NTVUZCV2l4RlFVRnJRaXhKUVVGc1FpeERRVUV6UWl4RlFVRnRSRHRCUVVOd1JDeGhRVUZQTEVsQlFWQXNRMEZFYjBRN1MwRkJkRVE3UjBGU1N5eERRVXB0UkR0RFFVRTFSRHM3UVVGclFrRXNVMEZCVXl4alFVRlVMRU5CUVhkQ0xFOUJRWGhDTEVWQlFUQkVPMEZCUTNoRUxGRkJRVTBzVlVGQlZTeFhRVUZYTEZGQlFWRXNTMEZCVWl4RFFVRnlRaXhEUVVSclJEczdRVUZIZUVRc1UwRkJUeXhWUVVGVExFdEJRVlFzUlVGQmNVSXNTVUZCY2tJc1JVRkJaMFE3UVVGRGNrUXNVVUZCUnl4UlFVRlJMRXRCUVZJc1JVRkJaU3hKUVVGbUxFTkJRVWdzUlVGQmQwSTdRVUZEZEVJc1YwRkJTeXhKUVVGTUxFTkJRVlVzUzBGQlZpeEZRVVJ6UWp0QlFVVjBRaXhoUVVGUExFbEJRVkFzUTBGR2MwSTdTMEZCZUVJN08wRkJTMEVzVjBGQlR5eExRVUZRTEVOQlRuRkVPMGRCUVdoRUxFTkJTR2xFTzBOQlFURkVPenRCUVdGQkxGTkJRVk1zYVVKQlFWUXNRMEZCTWtJc1QwRkJNMElzUlVGQlowVTdRVUZET1VRc1VVRkJUU3hUUVVGVExGRkJRVkVzVFVGQlVpeERRVVFyUXpzN1FVRkhPVVFzVTBGQlR5eFZRVUZUTEV0QlFWUXNSVUZCY1VJc1NVRkJja0lzUlVGQlowUTdRVUZEY2tRc1VVRkJSeXhQUVVGUExGTkJRVkFzUTBGQmFVSXNTMEZCYWtJc1MwRkJNa0lzVFVGQlRTeFZRVUZPTEVOQlFXbENMRTFCUVdwQ0xFTkJRVE5DTEVWQlFXOUVPMEZCUTNKRUxGZEJRVXNzU1VGQlRDeERRVUZWTEUxQlFVMHNVMEZCVGl4RFFVRm5RaXhQUVVGUExFMUJRVkFzUTBGQk1VSXNSVUZFY1VRN1FVRkZja1FzWVVGQlR5eEpRVUZRTEVOQlJuRkVPMHRCUVhaRU96dEJRVXRCTEZkQlFVOHNTMEZCVUN4RFFVNXhSRHRIUVVGb1JDeERRVWgxUkR0RFFVRm9SVHM3UVVGaFFTeFRRVUZUTEZkQlFWUXNRMEZCY1VJc1QwRkJja0lzUlVGQmIwUTdRVUZEYkVRc1UwRkJUeXhWUVVGVExFdEJRVlFzUlVGQmNVSXNTVUZCY2tJc1JVRkJaMFE3UVVGRGNrUXNVVUZCUnl4cFFrRkJhVUlzVVVGQlVTeEpRVUZTTEVWQlFXRTdRVUZETDBJc1dVRkJUU3hWUVVGVkxGZEJRVmNzVVVGQlVTeFZRVUZTTEVOQlFYSkNMRU5CUkhsQ08wRkJSUzlDTEdGQlFVOHNVVUZCVVN4TFFVRlNMRVZCUVdVc1NVRkJaaXhMUVVGM1FpeExRVUZMTEVsQlFVd3NRMEZCVlN4TFFVRldMRWxCUVcxQ0xFTkJRVzVDTEVOQlJrRTdTMEZCYWtNN08wRkJTMEVzVjBGQlR5eExRVUZRTEVOQlRuRkVPMGRCUVdoRUxFTkJSREpETzBOQlFYQkVPenRCUVZkQkxGTkJRVk1zV1VGQlZDeERRVUZ6UWl4UFFVRjBRaXhGUVVGeFJEdEJRVU51UkN4UlFVRk5MRlZCUVZVc1VVRkJVU3hIUVVGU0xFTkJRVmtzUzBGQlN5eFhRVUZYTEVOQlFWZ3NRMEZCVEN4RFFVRjBRaXhEUVVRMlF6czdRVUZIYmtRc1UwRkJUeXhWUVVGVExFdEJRVlFzUlVGQmNVSXNTVUZCY2tJc1JVRkJaMFE3UVVGRGNrUXNVVUZCUnl4RFFVRkRMRTlCUVU4c1VVRkJVQ3hEUVVGblFpeExRVUZvUWl4RFFVRkVMRWxCUVRKQ0xFMUJRVTBzVFVGQlRpeEpRVUZuUWl4UlFVRlJMRTFCUVZJc1JVRkJaVHRCUVVNelJDeGhRVUZQTEV0QlFWQXNRMEZFTWtRN1MwRkJOMFE3TzBGQlNVRXNWMEZCVHl4TlFVRk5MRXRCUVU0c1EwRkJXU3hWUVVGVExFTkJRVlFzUlVGQldTeERRVUZhTEVWQlFXVTdRVUZEYUVNc1lVRkJUeXhSUVVGUkxFTkJRVklzUlVGQlZ5eE5RVUZOTEVOQlFVNHNRMEZCV0N4RlFVRnhRaXhKUVVGeVFpeERRVUZRTEVOQlJHZERPMHRCUVdZc1EwRkJia0lzUTBGTWNVUTdSMEZCYUVRc1EwRklORU03UTBGQmNrUTdPMEZCWTBFc1UwRkJVeXhoUVVGVUxFTkJRWFZDTEU5QlFYWkNMRVZCUVd0RU8wRkJRMmhFTEUxQlFVa3NWVUZCVlN4RlFVRldMRU5CUkRSRE96dEJRVWRvUkN4UFFVRkpMRWxCUVVrc1IwRkJTaXhKUVVGWExFOUJRVThzU1VGQlVDeERRVUZaTEU5QlFWb3NSVUZCY1VJc1RVRkJja0lzUTBGQk5FSXNUMEZCVHl4eFFrRkJVQ3hEUVVFMlFpeFBRVUUzUWl4RFFVRTFRaXhEUVVGbUxFVkJRV3RHTzBGQlEyaEdMRmxCUVZFc1IwRkJVaXhKUVVGbExGZEJRVmNzVVVGQlVTeEhRVUZTTEVOQlFWZ3NRMEZCWml4RFFVUm5SanRIUVVGc1JqczdRVUZKUVN4VFFVRlBMRlZCUVZNc1MwRkJWQ3hGUVVGeFFpeEpRVUZ5UWl4RlFVRm5SRHRCUVVOeVJDeFJRVUZITEVOQlFVTXNUMEZCVHl4VFFVRlFMRU5CUVdsQ0xFdEJRV3BDTEVOQlFVUXNTVUZCTkVJc1VVRkJVU3hOUVVGU0xFZEJRV2xDTEUxQlFVMHNUVUZCVGl4RlFVRmhPMEZCUXpORUxHRkJRVThzUzBGQlVDeERRVVF5UkR0TFFVRTNSRHM3UVVGSlFTeFRRVUZKTEVsQlFVa3NSMEZCU2l4SlFVRlhMRTlCUVU4c1NVRkJVQ3hEUVVGWkxFOUJRVm9zUlVGQmNVSXNUVUZCY2tJc1EwRkJORUlzVDBGQlR5eHhRa0ZCVUN4RFFVRTJRaXhQUVVFM1FpeERRVUUxUWl4RFFVRm1MRVZCUVd0R08wRkJRMmhHTEZWQlFVY3NSVUZCUlN4UFFVRlBMRXRCUVZBc1EwRkJSaXhKUVVGdFFpeERRVUZETEZGQlFWRXNSMEZCVWl4RlFVRmhMRTFCUVUwc1IwRkJUaXhEUVVGaUxFVkJRWGxDTEVsQlFYcENMRU5CUVVRc1JVRkJhVU03UVVGRGNrUXNaVUZCVHl4TFFVRlFMRU5CUkhGRU8wOUJRWFpFTzB0QlJFWTdPMEZCVFVFc1YwRkJUeXhKUVVGUUxFTkJXSEZFTzBkQlFXaEVMRU5CVUhsRE8wTkJRV3hFT3p0QlFYTkNRU3hUUVVGVExHZENRVUZVTEVOQlFUQkNMRTlCUVRGQ0xFVkJRVzFGTzBGQlEycEZMRTFCUVVrc2JVSkJRVzFDTEVWQlFXNUNMRU5CUkRaRU96dEJRVWRxUlN4UFFVRkpMRWxCUVVrc2EwSkJRVW9zU1VGQk1FSXNVVUZCVVN4TlFVRlNMRVZCUVdVN1FVRkRNME1zVVVGQlJ5eFBRVUZQTEZkQlFWQXNRMEZCYlVJc2JVSkJRVzFDTEV0QlFXNUNMRU5CUVhSQ0xFVkJRV2RFTzBGQlF6bERMRlZCUVVrc1QwRkJUeXhSUVVGUkxHMUNRVUZ0UWl4SlFVRnVRaXhGUVVGNVFpeHRRa0ZCYlVJc1NVRkJia0lzUTBGQmVFTXNRMEZFTUVNN1FVRkZPVU1zWjBKQlFWVXNaMEpCUVZZc1JVRkJORUlzU1VGQk5VSXNSVUZHT0VNN1MwRkJhRVFzVFVGSFN6dEJRVU5JTEhsQ1FVRnRRaXhwUWtGQmFVSXNUVUZCYWtJc1EwRkJkMElzU1VGQlNTeFRRVUZLTEVOQlFXTXNhMEpCUVdRc1JVRkJhME1zUzBGQmJFTXNRMEZCTTBNc1EwRkVSenRMUVVoTU8wZEJSRVk3TzBGQlUwRXNUVUZCU1N4blFrRkJaMElzVVVGQlVTeE5RVUZTTEVOQldqWkRPenRCUVdOcVJTeFRRVUZQTEZWQlFWTXNTMEZCVkN4RlFVRnhRaXhKUVVGeVFpeEZRVUZuUkR0QlFVTnlSQ3hSUVVGSkxGVkJRVlVzU1VGQlZpeERRVVJwUkRzN1FVRkhja1FzVVVGQlJ5eERRVUZETEU5QlFVOHNVMEZCVUN4RFFVRnBRaXhMUVVGcVFpeERRVUZFTEVsQlFUUkNMRVZCUVVVc2FVSkJRV2xDTEZOQlFXcENMRU5CUVVZc1JVRkJLMEk3UVVGRE5VUXNZVUZCVHl4TFFVRlFMRU5CUkRSRU8wdEJRVGxFT3p0QlFVbEJMRkZCUVVjc1QwRkJUeXhUUVVGUUxFTkJRV2xDTEV0QlFXcENMRU5CUVVnc1JVRkJNa0k3UVVGRGVrSXNaMEpCUVZVc1NVRkJTU3hUUVVGS0xFTkJRV01zVlVGQlZTeE5RVUZXTEVOQlFXbENMRXRCUVdwQ0xFTkJRV1FzUTBGQlZpeERRVVI1UWp0TFFVRXpRaXhOUVVWTE8wRkJRMGdzWjBKQlFWVXNTMEZCVml4RFFVUkhPMHRCUmt3N08wRkJUVUVzVVVGQlNTeHBRa0ZCYVVJc1EwRkJha0lzUTBGaWFVUTdPMEZCWlhKRUxGTkJRVWtzU1VGQlNTeEpRVUZKTEVOQlFVb3NSVUZCVHl4SlFVRkpMR05CUVdNc1RVRkJaQ3hGUVVGelFpeEhRVUY2UXl4RlFVRTJRenRCUVVNelF5eFZRVUZKTEhGQ1FVRnhRaXhqUVVGakxFTkJRV1FzUTBGQmNrSXNRMEZFZFVNN08wRkJSek5ETEZWQlFVY3NUMEZCVHl4WFFVRlFMRU5CUVcxQ0xHMUNRVUZ0UWl4TFFVRnVRaXhEUVVGdVFpeEpRVU5CTEcxQ1FVRnRRaXhKUVVGdVFpeEpRVUV5UWl4UlFVRXpRaXhKUVVOQkxHMUNRVUZ0UWl4SlFVRnVRaXhMUVVFMFFpeFRRVUUxUWl4SlFVTkJMRWxCUVVrc1kwRkJZeXhOUVVGa0xFZEJRWFZDTEVOQlFYWkNMRVZCUVhsQ08wRkJRemxDTEdOQlFVMHNTVUZCU1N4TFFVRktMRU5CUVZVc05FVkJRVllzUTBGQlRpeERRVVE0UWp0UFFVaG9RenM3UVVGUFFTeFZRVUZKTEU5QlFVOHNRMEZCVUN4RFFWWjFRenRCUVZjelF5eFZRVUZKTEcxQ1FVRnRRaXhGUVVGdVFpeERRVmgxUXp0QlFWa3pReXhWUVVGSkxEUkNRVUUwUWl4RlFVRTFRaXhEUVZwMVF6dEJRV0V6UXl4aFFVRlBMRkZCUVZFc2JVSkJRVzFDTEVsQlFXNUNMRVZCUVhsQ0xHMUNRVUZ0UWl4SlFVRnVRaXhEUVVGNFF5eERRV0l5UXpzN1FVRmxNME1zVlVGQlJ5eE5RVUZOTEdOQlFXTXNUVUZCWkN4SFFVRjFRaXhEUVVGMlFpeEZRVUY1UWp0QlFVTm9ReXd5UWtGQmJVSXNVVUZCVVN4TFFVRlNMRU5CUVdNc1MwRkJaQ3hEUVVGdlFpeGpRVUZ3UWl4RFFVRnVRaXhEUVVSblF6dEJRVVZvUXl4dlEwRkJORUlzYVVKQlFXbENMRXRCUVdwQ0xFTkJRWFZDTEdOQlFYWkNMRU5CUVRWQ0xFTkJSbWRETzA5QlFXeERMRTFCUjA4N1FVRkRUQ3d5UWtGQmJVSXNVVUZCVVN4TFFVRlNMRU5CUVdNc1MwRkJaQ3hEUVVGdlFpeGpRVUZ3UWl4RlFVRnZReXhwUWtGQmFVSXNTVUZCYWtJc1EwRkJka1FzUTBGRVN6dEJRVVZNTEc5RFFVRTBRaXhwUWtGQmFVSXNTMEZCYWtJc1EwRkJkVUlzWTBGQmRrSXNSVUZCZFVNc2FVSkJRV2xDTEVsQlFXcENMRU5CUVc1RkxFTkJSa3M3VDBGSVVEczdRVUZSUVN4VlFVRkhMRTlCUVU4c1YwRkJVQ3hEUVVGdFFpeHRRa0ZCYlVJc1MwRkJia0lzUTBGQmRFSXNSVUZCWjBRN1FVRkRPVU1zWjBKQlFVOHNiVUpCUVcxQ0xFbEJRVzVDTzBGQlExQXNaVUZCU3l4VFFVRk1PMEZCUTBVc1owSkJRVWNzYlVKQlFXMUNMRlZCUVc1Q0xFbEJRV2xETEcxQ1FVRnRRaXhWUVVGdVFpeERRVUU0UWl4UFFVRTVRaXhEUVVGelF5eFJRVUYwUXl4TFFVRnRSQ3hEUVVGRExFTkJRVVFzUlVGQlJ6dEJRVU40Uml4dFFrRkJTeXhKUVVGTUxFTkJRVlVzU1VGQlNTeFRRVUZLTEVOQlFXTXNRMEZCUXl4cFFrRkJhVUlzUTBGQmFrSXNRMEZCUkN4RFFVRmtMRVZCUVhGRExFTkJRWEpETEVOQlFWWXNSVUZFZDBZN1lVRkJNVVlzVFVGRlR6dEJRVU5NTEcxQ1FVRkxMRWxCUVV3c1EwRkJWU3hKUVVGSkxGVkJRVW9zUTBGQlpTeERRVUZETEdsQ1FVRnBRaXhEUVVGcVFpeERRVUZFTEVOQlFXWXNSVUZCYzBNc1EwRkJkRU1zUTBGQlZpeEZRVVJMTzJGQlJsQTdRVUZMUVN4clFrRk9SanM3UVVGRVFTeGxRVk5MTEU5QlFVdzdRVUZEUlN4blFrRkJSeXhUUVVGVExFVkJRVlFzUlVGQldUdEJRVU5pTEcxQ1FVRkxMRWxCUVV3c1EwRkJWU3hoUVVGaExFbEJRV0lzUTBGQmEwSXNaMEpCUVd4Q0xFVkJRVzlETEVOQlFYQkRMRU5CUVZZc1JVRkVZVHRoUVVGbUxFMUJSVThzU1VGQlJ5eFRRVUZUTEVWQlFWUXNSVUZCV1R0QlFVTndRaXh0UWtGQlN5eEpRVUZNTEVOQlFWVXNZVUZCWVN4SlFVRmlMRU5CUVd0Q0xHZENRVUZzUWl4RlFVRnZReXhEUVVGd1F5eERRVUZXTEVWQlJHOUNPMkZCUVdZc1RVRkZSanRCUVVOSUxIRkNRVUZQTEV0QlFWQXNRMEZFUnp0aFFVWkZPMEZCUzFBc2EwSkJVa1k3TzBGQlZFRXNaVUZ0UWtzc1YwRkJURHRCUVVORkxHbENRVUZMTEVsQlFVd3NRMEZCVlN4blFrRkJaMElzWjBKQlFXaENMRU5CUVZZc1JVRkVSanRCUVVWRkxHdENRVVpHT3p0QlFXNUNRU3hsUVhWQ1N5eFJRVUZNTzBGQlEwVXNhVUpCUVVzc1NVRkJUQ3hEUVVGVkxFOUJRVThzV1VGQlVDeERRVUZ2UWl4TFFVRndRaXhEUVVFd1FpeEpRVUV4UWl4RlFVRm5ReXhKUVVGSkxGVkJRVW9zUTBGQlpTeG5Ra0ZCWml4RFFVRm9ReXhEUVVGV0xFVkJSRVk3UVVGRlJTeHJRa0ZHUmpzN1FVRjJRa0VzWlVFeVFrc3NUVUZCVER0QlFVTkZMR2xDUVVGTExFbEJRVXdzUTBGQlZTeFBRVUZQTEZsQlFWQXNRMEZCYjBJc1MwRkJjRUlzUTBGQk1FSXNTVUZCTVVJc1JVRkJaME1zU1VGQlNTeFZRVUZLTEVOQlFXVXNaMEpCUVdZc1EwRkJhRU1zUTBGQlZpeEZRVVJHTzBGQlJVVXNhMEpCUmtZN08wRkJNMEpCTEdWQkswSkxMRTlCUVV3N1FVRkRSU3hwUWtGQlN5eEpRVUZNTEVOQlFWVXNUMEZCVHl4WlFVRlFMRU5CUVc5Q0xFdEJRWEJDTEVOQlFUQkNMRWxCUVRGQ0xFVkJRV2RETEVsQlFVa3NWMEZCU2l4RFFVRm5RaXhuUWtGQmFFSXNRMEZCYUVNc1EwRkJWaXhGUVVSR08wRkJSVVVzYTBKQlJrWTdPMEZCTDBKQkxHVkJiVU5MTEU5QlFVdzdRVUZEUlN4cFFrRkJTeXhKUVVGTUxFTkJRVlVzVDBGQlR5eFpRVUZRTEVOQlFXOUNMRXRCUVhCQ0xFTkJRVEJDTEVsQlFURkNMRVZCUVdkRExFbEJRVWtzVjBGQlNpeERRVUZuUWl4blFrRkJhRUlzUTBGQmFFTXNRMEZCVml4RlFVUkdPMEZCUlVVc2EwSkJSa1k3TzBGQmJrTkJPMEZCZDBORkxHMUNRVUZQTEV0QlFWQXNRMEZFUmp0QlFYWkRRU3hUUVVRNFF6dFBRVUZvUkN4TlFUSkRUU3hKUVVGSExFTkJRVU1zV1VGQldTeG5Ra0ZCV2l4RlFVRTRRaXg1UWtGQk9VSXNRMEZCUkN4RlFVRXlSRHRCUVVOc1JTeGxRVUZQTEV0QlFWQXNRMEZFYTBVN1QwRkJPVVE3TzBGQlNVNHNkVUpCUVdsQ0xHbENRVUZwUWl4SlFVRnFRaXhEUVhSRk1FSTdTMEZCTjBNN08wRkJlVVZCTEZkQlFVOHNTVUZCVUN4RFFYaEdjVVE3UjBGQmFFUXNRMEZrTUVRN1EwRkJia1U3TzBGQk1rZEJMRk5CUVZNc1QwRkJWQ3hEUVVGcFFpeEpRVUZxUWl4RlFVRjFRaXhKUVVGMlFpeEZRVUUwUWp0QlFVTXhRaXhUUVVGUExFbEJRVU1zUjBGQlR5eEpRVUZRTEVkQlFXVXNRMEZCYUVJc1EwRkViVUk3UTBGQk5VSTdPMEZCU1VFc1UwRkJVeXhYUVVGVUxFTkJRWEZDTEVOQlFYSkNMRVZCUVhkQ0xFTkJRWGhDTEVWQlFUSkNPMEZCUTNwQ0xFMUJRVWtzVFVGQlRTeERRVUZPTEVWQlFWTXNUMEZCVHl4SlFVRlFMRU5CUVdJN1FVRkRRU3hOUVVGSkxFdEJRVXNzU1VGQlRDeEpRVUZoTEV0QlFVc3NTVUZCVEN4RlFVRlhMRTlCUVU4c1MwRkJVQ3hEUVVFMVFqdEJRVU5CTEUxQlFVa3NSVUZCUlN4TlFVRkdMRWxCUVZrc1JVRkJSU3hOUVVGR0xFVkJRVlVzVDBGQlR5eExRVUZRTEVOQlFURkNPenRCUVVWQkxFOUJRVXNzU1VGQlNTeEpRVUZKTEVOQlFVb3NSVUZCVHl4SlFVRkpMRVZCUVVVc1RVRkJSaXhGUVVGVkxFVkJRVVVzUTBGQlJpeEZRVUZMTzBGQlEycERMRkZCUVVrc1JVRkJSU3hEUVVGR0xFMUJRVk1zUlVGQlJTeERRVUZHTEVOQlFWUXNSVUZCWlN4UFFVRlBMRXRCUVZBc1EwRkJia0k3UjBGRVJqczdRVUZKUVN4VFFVRlBMRWxCUVZBc1EwRlVlVUk3UTBGQk0wSTdPMEZCV1VFc1UwRkJVeXhUUVVGVUxFTkJRVzFDTEVkQlFXNUNMRVZCUVhkQ0xFZEJRWGhDTEVWQlFUUkNPMEZCUXpGQ0xFOUJRVWtzU1VGQlNTeEpRVUZKTEVOQlFVb3NSVUZCVHl4SlFVRkpMRWRCUVVvc1JVRkJVeXhIUVVGNFFpeEZRVUUwUWp0QlFVTXhRaXhSUVVGSkxFbEJRVW9zUTBGQlV5eERRVUZVTEVWQlJEQkNPMGRCUVRWQ08wTkJSRVk3TzBGQlRVRXNVMEZCVXl4bFFVRlVMRU5CUVhsQ0xFZEJRWHBDTEVWQlFUWkNPMEZCUXpOQ0xFMUJRVWtzWlVGQlpTeEpRVUZKTEVkQlFVb3NRMEZCVVN4UlFVRlZMRlZCUVZVc1QwRkJWaXhEUVVGclFpeEpRVUZzUWl4RFFVRldMRU5CUVhaQ0xFTkJSSFZDTzBGQlJUTkNMRk5CUVU4c1NVRkJTU3hUUVVGS0xFTkJRV01zUjBGQlJ5eFpRVUZJTEVOQlFYSkNMRU5CUmpKQ08wTkJRVGRDT3p0QlFVdEJMRk5CUVZNc1kwRkJWQ3hIUVVGdlF6dEJRVU5zUXl4VFFVRlBMRmxCUVc5Q08wRkJRM3BDTEZkQlFVOHNTMEZCVUN4RFFVUjVRanRIUVVGd1FpeERRVVF5UWp0RFFVRndRenM3UVVGTlFTeGxRVUZsTzBGQlEySXNZMEZFWVR0QlFVVmlMR2xDUVVaaE8wRkJSMklzYVVKQlNHRTdRVUZKWWl4cFFrRktZVHRCUVV0aUxHZENRVXhoTzBGQlRXSXNiVUpCVG1FN1FVRlBZaXhoUVZCaE8wRkJVV0lzWTBGU1lUdEJRVk5pTEdWQlZHRTdRVUZWWWl4blFrRldZVHRCUVZkaUxHVkJXR0U3UVVGWllpeGxRVnBoTzBGQllXSXNaVUZpWVR0QlFXTmlMR2RDUVdSaE8wRkJaV0lzYVVKQlptRTdRVUZuUW1Jc1lVRm9RbUU3UVVGcFFtSXNhMEpCYWtKaE8wTkJRV1lpTENKbWFXeGxJam9pYkdsaUwyTnZjbVV2Y0dGMGRHVnlibk12Y21WemIyeDJaWEp6TG1weklpd2ljMjkxY21ObGMwTnZiblJsYm5RaU9sc2lMeW9nUUdac2IzY2dLaTljYmx4dWFXMXdiM0owSUVOb1pXTnJjeUJtY205dElGd2lMaTlqYUdWamEzTmNJanRjYm1sdGNHOXlkQ0FxSUdGeklGUjVjR1Z6SUdaeWIyMGdYQ0l1TDNSNWNHVnpYQ0k3WEc1cGJYQnZjblFnZXlCaWRXbHNaRTFoZEdOb0lIMGdabkp2YlNCY0lpNHZiV0YwWTJoY0lqdGNibWx0Y0c5eWRDQkNhWFJUZEhKcGJtY2dabkp2YlNCY0lpNHVMMkpwZEY5emRISnBibWRjSWp0Y2JseHVablZ1WTNScGIyNGdjbVZ6YjJ4MlpWTjViV0p2YkNod1lYUjBaWEp1T2lCaGJua3BPaUJHZFc1amRHbHZiaUI3WEc0Z0lISmxkSFZ5YmlCbWRXNWpkR2x2YmloMllXeDFaVG9nWVc1NUtUb2dZbTl2YkdWaGJpQjdYRzRnSUNBZ2NtVjBkWEp1SUVOb1pXTnJjeTVwYzE5emVXMWliMndvZG1Gc2RXVXBJQ1ltSUhaaGJIVmxJRDA5UFNCd1lYUjBaWEp1TzF4dUlDQjlPMXh1ZlZ4dVhHNW1kVzVqZEdsdmJpQnlaWE52YkhabFUzUnlhVzVuS0hCaGRIUmxjbTQ2SUdGdWVTazZJRVoxYm1OMGFXOXVJSHRjYmlBZ2NtVjBkWEp1SUdaMWJtTjBhVzl1S0haaGJIVmxPaUJoYm5rcE9pQmliMjlzWldGdUlIdGNiaUFnSUNCeVpYUjFjbTRnUTJobFkydHpMbWx6WDNOMGNtbHVaeWgyWVd4MVpTa2dKaVlnZG1Gc2RXVWdQVDA5SUhCaGRIUmxjbTQ3WEc0Z0lIMDdYRzU5WEc1Y2JtWjFibU4wYVc5dUlISmxjMjlzZG1WT2RXMWlaWElvY0dGMGRHVnliam9nWVc1NUtUb2dSblZ1WTNScGIyNGdlMXh1SUNCeVpYUjFjbTRnWm5WdVkzUnBiMjRvZG1Gc2RXVTZJR0Z1ZVNrNklHSnZiMnhsWVc0Z2UxeHVJQ0FnSUhKbGRIVnliaUJEYUdWamEzTXVhWE5mYm5WdFltVnlLSFpoYkhWbEtTQW1KaUIyWVd4MVpTQTlQVDBnY0dGMGRHVnlianRjYmlBZ2ZUdGNibjFjYmx4dVpuVnVZM1JwYjI0Z2NtVnpiMngyWlVKdmIyeGxZVzRvY0dGMGRHVnliam9nWVc1NUtUb2dSblZ1WTNScGIyNGdlMXh1SUNCeVpYUjFjbTRnWm5WdVkzUnBiMjRvZG1Gc2RXVTZJR0Z1ZVNrNklHSnZiMnhsWVc0Z2UxeHVJQ0FnSUhKbGRIVnliaUJEYUdWamEzTXVhWE5mWW05dmJHVmhiaWgyWVd4MVpTa2dKaVlnZG1Gc2RXVWdQVDA5SUhCaGRIUmxjbTQ3WEc0Z0lIMDdYRzU5WEc1Y2JtWjFibU4wYVc5dUlISmxjMjlzZG1WR2RXNWpkR2x2Ymlod1lYUjBaWEp1T2lCaGJua3BPaUJHZFc1amRHbHZiaUI3WEc0Z0lISmxkSFZ5YmlCbWRXNWpkR2x2YmloMllXeDFaVG9nWVc1NUtUb2dZbTl2YkdWaGJpQjdYRzRnSUNBZ2NtVjBkWEp1SUVOb1pXTnJjeTVwYzE5bWRXNWpkR2x2YmloMllXeDFaU2tnSmlZZ2RtRnNkV1VnUFQwOUlIQmhkSFJsY200N1hHNGdJSDA3WEc1OVhHNWNibVoxYm1OMGFXOXVJSEpsYzI5c2RtVk9kV3hzS0hCaGRIUmxjbTQ2SUdGdWVTazZJRVoxYm1OMGFXOXVJSHRjYmlBZ2NtVjBkWEp1SUdaMWJtTjBhVzl1S0haaGJIVmxPaUJoYm5rcE9pQmliMjlzWldGdUlIdGNiaUFnSUNCeVpYUjFjbTRnUTJobFkydHpMbWx6WDI1MWJHd29kbUZzZFdVcE8xeHVJQ0I5TzF4dWZWeHVYRzVtZFc1amRHbHZiaUJ5WlhOdmJIWmxRbTkxYm1Rb2NHRjBkR1Z5YmpvZ1ZIbHdaWE11UW05MWJtUXBPaUJHZFc1amRHbHZiaUI3WEc0Z0lISmxkSFZ5YmlCbWRXNWpkR2x2YmloMllXeDFaVG9nWVc1NUxDQmhjbWR6T2lCQmNuSmhlVHhoYm5rK0tUb2dZbTl2YkdWaGJpQjdYRzRnSUNBZ2FXWW9kSGx3Wlc5bUlIWmhiSFZsSUQwOVBTQjBlWEJsYjJZZ2NHRjBkR1Z5Ymk1MllXeDFaU0FtSmlCMllXeDFaU0E5UFQwZ2NHRjBkR1Z5Ymk1MllXeDFaU2w3WEc0Z0lDQWdJQ0JoY21kekxuQjFjMmdvZG1Gc2RXVXBPMXh1SUNBZ0lDQWdjbVYwZFhKdUlIUnlkV1U3WEc0Z0lDQWdmVnh1WEc0Z0lDQWdjbVYwZFhKdUlHWmhiSE5sTzF4dUlDQjlPMXh1ZlZ4dVhHNW1kVzVqZEdsdmJpQnlaWE52YkhabFYybHNaR05oY21Rb0tUb2dSblZ1WTNScGIyNGdlMXh1SUNCeVpYUjFjbTRnWm5WdVkzUnBiMjRvS1RvZ1ltOXZiR1ZoYmlCN1hHNGdJQ0FnY21WMGRYSnVJSFJ5ZFdVN1hHNGdJSDA3WEc1OVhHNWNibVoxYm1OMGFXOXVJSEpsYzI5c2RtVldZWEpwWVdKc1pTZ3BPaUJHZFc1amRHbHZiaUI3WEc0Z0lISmxkSFZ5YmlCbWRXNWpkR2x2YmloMllXeDFaVG9nWVc1NUxDQmhjbWR6T2lCQmNuSmhlVHhoYm5rK0tUb2dZbTl2YkdWaGJpQjdYRzRnSUNBZ1lYSm5jeTV3ZFhOb0tIWmhiSFZsS1R0Y2JpQWdJQ0J5WlhSMWNtNGdkSEoxWlR0Y2JpQWdmVHRjYm4xY2JseHVablZ1WTNScGIyNGdjbVZ6YjJ4MlpVaGxZV1JVWVdsc0tIQmhkSFJsY200NklGUjVjR1Z6TGtobFlXUlVZV2xzS1RvZ1JuVnVZM1JwYjI0Z2UxeHVJQ0JqYjI1emRDQm9aV0ZrVFdGMFkyaGxjeUE5SUdKMWFXeGtUV0YwWTJnb2NHRjBkR1Z5Ymk1b1pXRmtLVHRjYmlBZ1kyOXVjM1FnZEdGcGJFMWhkR05vWlhNZ1BTQmlkV2xzWkUxaGRHTm9LSEJoZEhSbGNtNHVkR0ZwYkNrN1hHNWNiaUFnY21WMGRYSnVJR1oxYm1OMGFXOXVLSFpoYkhWbE9pQmhibmtzSUdGeVozTTZJRUZ5Y21GNVBHRnVlVDRwT2lCaWIyOXNaV0Z1SUh0Y2JpQWdJQ0JwWmlnaFEyaGxZMnR6TG1selgyRnljbUY1S0haaGJIVmxLU0I4ZkNCMllXeDFaUzVzWlc1bmRHZ2dQQ0F5S1h0Y2JpQWdJQ0FnSUhKbGRIVnliaUJtWVd4elpUdGNiaUFnSUNCOVhHNWNiaUFnSUNCamIyNXpkQ0JvWldGa0lEMGdkbUZzZFdWYk1GMDdYRzRnSUNBZ1kyOXVjM1FnZEdGcGJDQTlJSFpoYkhWbExuTnNhV05sS0RFcE8xeHVYRzRnSUNBZ2FXWW9hR1ZoWkUxaGRHTm9aWE1vYUdWaFpDd2dZWEpuY3lrZ0ppWWdkR0ZwYkUxaGRHTm9aWE1vZEdGcGJDd2dZWEpuY3lrcGUxeHVJQ0FnSUNBZ2NtVjBkWEp1SUhSeWRXVTdYRzRnSUNBZ2ZWeHVJQ0I5TzF4dWZWeHVYRzVtZFc1amRHbHZiaUJ5WlhOdmJIWmxRMkZ3ZEhWeVpTaHdZWFIwWlhKdU9pQlVlWEJsY3k1RFlYQjBkWEpsS1RvZ1JuVnVZM1JwYjI0Z2UxeHVJQ0JqYjI1emRDQnRZWFJqYUdWeklEMGdZblZwYkdSTllYUmphQ2h3WVhSMFpYSnVMblpoYkhWbEtUdGNibHh1SUNCeVpYUjFjbTRnWm5WdVkzUnBiMjRvZG1Gc2RXVTZJR0Z1ZVN3Z1lYSm5jem9nUVhKeVlYazhZVzU1UGlrNklHSnZiMnhsWVc0Z2UxeHVJQ0FnSUdsbUtHMWhkR05vWlhNb2RtRnNkV1VzSUdGeVozTXBLWHRjYmlBZ0lDQWdJR0Z5WjNNdWNIVnphQ2gyWVd4MVpTazdYRzRnSUNBZ0lDQnlaWFIxY200Z2RISjFaVHRjYmlBZ0lDQjlYRzVjYmlBZ0lDQnlaWFIxY200Z1ptRnNjMlU3WEc0Z0lIMDdYRzU5WEc1Y2JtWjFibU4wYVc5dUlISmxjMjlzZG1WVGRHRnlkSE5YYVhSb0tIQmhkSFJsY200NklGUjVjR1Z6TGxOMFlYSjBjMWRwZEdncE9pQkdkVzVqZEdsdmJpQjdYRzRnSUdOdmJuTjBJSEJ5WldacGVDQTlJSEJoZEhSbGNtNHVjSEpsWm1sNE8xeHVYRzRnSUhKbGRIVnliaUJtZFc1amRHbHZiaWgyWVd4MVpUb2dZVzU1TENCaGNtZHpPaUJCY25KaGVUeGhibmsrS1RvZ1ltOXZiR1ZoYmlCN1hHNGdJQ0FnYVdZb1EyaGxZMnR6TG1selgzTjBjbWx1WnloMllXeDFaU2tnSmlZZ2RtRnNkV1V1YzNSaGNuUnpWMmwwYUNod2NtVm1hWGdwS1h0Y2JpQWdJQ0FnSUdGeVozTXVjSFZ6YUNoMllXeDFaUzV6ZFdKemRISnBibWNvY0hKbFptbDRMbXhsYm1kMGFDa3BPMXh1SUNBZ0lDQWdjbVYwZFhKdUlIUnlkV1U3WEc0Z0lDQWdmVnh1WEc0Z0lDQWdjbVYwZFhKdUlHWmhiSE5sTzF4dUlDQjlPMXh1ZlZ4dVhHNW1kVzVqZEdsdmJpQnlaWE52YkhabFZIbHdaU2h3WVhSMFpYSnVPaUJVZVhCbGN5NVVlWEJsS1RvZ1JuVnVZM1JwYjI0Z2UxeHVJQ0J5WlhSMWNtNGdablZ1WTNScGIyNG9kbUZzZFdVNklHRnVlU3dnWVhKbmN6b2dRWEp5WVhrOFlXNTVQaWs2SUdKdmIyeGxZVzRnZTF4dUlDQWdJR2xtS0haaGJIVmxJR2x1YzNSaGJtTmxiMllnY0dGMGRHVnliaTUwZVhCbEtYdGNiaUFnSUNBZ0lHTnZibk4wSUcxaGRHTm9aWE1nUFNCaWRXbHNaRTFoZEdOb0tIQmhkSFJsY200dWIySnFVR0YwZEdWeWJpazdYRzRnSUNBZ0lDQnlaWFIxY200Z2JXRjBZMmhsY3loMllXeDFaU3dnWVhKbmN5a2dKaVlnWVhKbmN5NXdkWE5vS0haaGJIVmxLU0ErSURBN1hHNGdJQ0FnZlZ4dVhHNGdJQ0FnY21WMGRYSnVJR1poYkhObE8xeHVJQ0I5TzF4dWZWeHVYRzVtZFc1amRHbHZiaUJ5WlhOdmJIWmxRWEp5WVhrb2NHRjBkR1Z5YmpvZ1FYSnlZWGs4WVc1NVBpazZJRVoxYm1OMGFXOXVJSHRjYmlBZ1kyOXVjM1FnYldGMFkyaGxjeUE5SUhCaGRIUmxjbTR1YldGd0tIZ2dQVDRnWW5WcGJHUk5ZWFJqYUNoNEtTazdYRzVjYmlBZ2NtVjBkWEp1SUdaMWJtTjBhVzl1S0haaGJIVmxPaUJoYm5rc0lHRnlaM002SUVGeWNtRjVQR0Z1ZVQ0cE9pQmliMjlzWldGdUlIdGNiaUFnSUNCcFppZ2hRMmhsWTJ0ekxtbHpYMkZ5Y21GNUtIWmhiSFZsS1NCOGZDQjJZV3gxWlM1c1pXNW5kR2dnSVQwZ2NHRjBkR1Z5Ymk1c1pXNW5kR2dwZTF4dUlDQWdJQ0FnY21WMGRYSnVJR1poYkhObE8xeHVJQ0FnSUgxY2JseHVJQ0FnSUhKbGRIVnliaUIyWVd4MVpTNWxkbVZ5ZVNobWRXNWpkR2x2YmloMkxDQnBLU0I3WEc0Z0lDQWdJQ0J5WlhSMWNtNGdiV0YwWTJobGMxdHBYU2gyWVd4MVpWdHBYU3dnWVhKbmN5azdYRzRnSUNBZ2ZTazdYRzRnSUgwN1hHNTlYRzVjYm1aMWJtTjBhVzl1SUhKbGMyOXNkbVZQWW1wbFkzUW9jR0YwZEdWeWJqb2dUMkpxWldOMEtUb2dSblZ1WTNScGIyNGdlMXh1SUNCc1pYUWdiV0YwWTJobGN5QTlJSHQ5TzF4dVhHNGdJR1p2Y2loc1pYUWdhMlY1SUc5bUlFOWlhbVZqZEM1clpYbHpLSEJoZEhSbGNtNHBMbU52Ym1OaGRDaFBZbXBsWTNRdVoyVjBUM2R1VUhKdmNHVnlkSGxUZVcxaWIyeHpLSEJoZEhSbGNtNHBLU2w3WEc0Z0lDQWdiV0YwWTJobGMxdHJaWGxkSUQwZ1luVnBiR1JOWVhSamFDaHdZWFIwWlhKdVcydGxlVjBwTzF4dUlDQjlYRzVjYmlBZ2NtVjBkWEp1SUdaMWJtTjBhVzl1S0haaGJIVmxPaUJoYm5rc0lHRnlaM002SUVGeWNtRjVQR0Z1ZVQ0cE9pQmliMjlzWldGdUlIdGNiaUFnSUNCcFppZ2hRMmhsWTJ0ekxtbHpYMjlpYW1WamRDaDJZV3gxWlNrZ2ZId2djR0YwZEdWeWJpNXNaVzVuZEdnZ1BpQjJZV3gxWlM1c1pXNW5kR2dwZTF4dUlDQWdJQ0FnY21WMGRYSnVJR1poYkhObE8xeHVJQ0FnSUgxY2JseHVJQ0FnSUdadmNpaHNaWFFnYTJWNUlHOW1JRTlpYW1WamRDNXJaWGx6S0hCaGRIUmxjbTRwTG1OdmJtTmhkQ2hQWW1wbFkzUXVaMlYwVDNkdVVISnZjR1Z5ZEhsVGVXMWliMnh6S0hCaGRIUmxjbTRwS1NsN1hHNGdJQ0FnSUNCcFppZ2hLR3RsZVNCcGJpQjJZV3gxWlNrZ2ZId2dJVzFoZEdOb1pYTmJhMlY1WFNoMllXeDFaVnRyWlhsZExDQmhjbWR6S1NBcGUxeHVJQ0FnSUNBZ0lDQnlaWFIxY200Z1ptRnNjMlU3WEc0Z0lDQWdJQ0I5WEc0Z0lDQWdmVnh1WEc0Z0lDQWdjbVYwZFhKdUlIUnlkV1U3WEc0Z0lIMDdYRzU5WEc1Y2JtWjFibU4wYVc5dUlISmxjMjlzZG1WQ2FYUlRkSEpwYm1jb2NHRjBkR1Z5YmpvZ1ZIbHdaWE11UW1sMFUzUnlhVzVuVFdGMFkyZ3BPaUJHZFc1amRHbHZiaUI3WEc0Z0lHeGxkQ0J3WVhSMFpYSnVRbWwwVTNSeWFXNW5JRDBnVzEwN1hHNWNiaUFnWm05eUtHeGxkQ0JpYVhSemRISnBibWROWVhSamFGQmhjblFnYjJZZ2NHRjBkR1Z5Ymk1MllXeDFaWE1wZTF4dUlDQWdJR2xtS0VOb1pXTnJjeTVwYzE5MllYSnBZV0pzWlNoaWFYUnpkSEpwYm1kTllYUmphRkJoY25RdWRtRnNkV1VwS1h0Y2JpQWdJQ0FnSUd4bGRDQnphWHBsSUQwZ1oyVjBVMmw2WlNoaWFYUnpkSEpwYm1kTllYUmphRkJoY25RdWRXNXBkQ3dnWW1sMGMzUnlhVzVuVFdGMFkyaFFZWEowTG5OcGVtVXBPMXh1SUNBZ0lDQWdabWxzYkVGeWNtRjVLSEJoZEhSbGNtNUNhWFJUZEhKcGJtY3NJSE5wZW1VcE8xeHVJQ0FnSUgxbGJITmxlMXh1SUNBZ0lDQWdjR0YwZEdWeWJrSnBkRk4wY21sdVp5QTlJSEJoZEhSbGNtNUNhWFJUZEhKcGJtY3VZMjl1WTJGMEtHNWxkeUJDYVhSVGRISnBibWNvWW1sMGMzUnlhVzVuVFdGMFkyaFFZWEowS1M1MllXeDFaU2s3WEc0Z0lDQWdmVnh1SUNCOVhHNWNiaUFnYkdWMElIQmhkSFJsY201V1lXeDFaWE1nUFNCd1lYUjBaWEp1TG5aaGJIVmxjenRjYmx4dUlDQnlaWFIxY200Z1puVnVZM1JwYjI0b2RtRnNkV1U2SUdGdWVTd2dZWEpuY3pvZ1FYSnlZWGs4WVc1NVBpazZJR0p2YjJ4bFlXNGdlMXh1SUNBZ0lHeGxkQ0JpYzFaaGJIVmxJRDBnYm5Wc2JEdGNibHh1SUNBZ0lHbG1LQ0ZEYUdWamEzTXVhWE5mYzNSeWFXNW5LSFpoYkhWbEtTQW1KaUFoS0haaGJIVmxJR2x1YzNSaGJtTmxiMllnUW1sMFUzUnlhVzVuS1NBcGUxeHVJQ0FnSUNBZ2NtVjBkWEp1SUdaaGJITmxPMXh1SUNBZ0lIMWNibHh1SUNBZ0lHbG1LRU5vWldOcmN5NXBjMTl6ZEhKcGJtY29kbUZzZFdVcEtYdGNiaUFnSUNBZ0lHSnpWbUZzZFdVZ1BTQnVaWGNnUW1sMFUzUnlhVzVuS0VKcGRGTjBjbWx1Wnk1aWFXNWhjbmtvZG1Gc2RXVXBLVHRjYmlBZ0lDQjlaV3h6Wlh0Y2JpQWdJQ0FnSUdKelZtRnNkV1VnUFNCMllXeDFaVHRjYmlBZ0lDQjlYRzVjYmlBZ0lDQnNaWFFnWW1WbmFXNXVhVzVuU1c1a1pYZ2dQU0F3TzF4dVhHNGdJQ0FnWm05eUtHeGxkQ0JwSUQwZ01Ec2dhU0E4SUhCaGRIUmxjbTVXWVd4MVpYTXViR1Z1WjNSb095QnBLeXNwZTF4dUlDQWdJQ0FnYkdWMElHSnBkSE4wY21sdVowMWhkR05vVUdGeWRDQTlJSEJoZEhSbGNtNVdZV3gxWlhOYmFWMDdYRzVjYmlBZ0lDQWdJR2xtS0VOb1pXTnJjeTVwYzE5MllYSnBZV0pzWlNoaWFYUnpkSEpwYm1kTllYUmphRkJoY25RdWRtRnNkV1VwSUNZbVhHNGdJQ0FnSUNBZ0lDQmlhWFJ6ZEhKcGJtZE5ZWFJqYUZCaGNuUXVkSGx3WlNBOVBTQW5ZbWx1WVhKNUp5QW1KbHh1SUNBZ0lDQWdJQ0FnWW1sMGMzUnlhVzVuVFdGMFkyaFFZWEowTG5OcGVtVWdQVDA5SUhWdVpHVm1hVzVsWkNBbUpseHVJQ0FnSUNBZ0lDQWdhU0E4SUhCaGRIUmxjbTVXWVd4MVpYTXViR1Z1WjNSb0lDMGdNU2w3WEc0Z0lDQWdJQ0FnSUhSb2NtOTNJRzVsZHlCRmNuSnZjaWhjSW1FZ1ltbHVZWEo1SUdacFpXeGtJSGRwZEdodmRYUWdjMmw2WlNCcGN5QnZibXg1SUdGc2JHOTNaV1FnWVhRZ2RHaGxJR1Z1WkNCdlppQmhJR0pwYm1GeWVTQndZWFIwWlhKdVhDSXBPMXh1SUNBZ0lDQWdmVnh1WEc0Z0lDQWdJQ0JzWlhRZ2MybDZaU0E5SURBN1hHNGdJQ0FnSUNCc1pYUWdZbk5XWVd4MVpVRnljbUY1VUdGeWRDQTlJRnRkTzF4dUlDQWdJQ0FnYkdWMElIQmhkSFJsY201Q2FYUlRkSEpwYm1kQmNuSmhlVkJoY25RZ1BTQmJYVHRjYmlBZ0lDQWdJSE5wZW1VZ1BTQm5aWFJUYVhwbEtHSnBkSE4wY21sdVowMWhkR05vVUdGeWRDNTFibWwwTENCaWFYUnpkSEpwYm1kTllYUmphRkJoY25RdWMybDZaU2s3WEc1Y2JpQWdJQ0FnSUdsbUtHa2dQVDA5SUhCaGRIUmxjbTVXWVd4MVpYTXViR1Z1WjNSb0lDMGdNU2w3WEc0Z0lDQWdJQ0FnSUdKelZtRnNkV1ZCY25KaGVWQmhjblFnUFNCaWMxWmhiSFZsTG5aaGJIVmxMbk5zYVdObEtHSmxaMmx1Ym1sdVowbHVaR1Y0S1R0Y2JpQWdJQ0FnSUNBZ2NHRjBkR1Z5YmtKcGRGTjBjbWx1WjBGeWNtRjVVR0Z5ZENBOUlIQmhkSFJsY201Q2FYUlRkSEpwYm1jdWMyeHBZMlVvWW1WbmFXNXVhVzVuU1c1a1pYZ3BPMXh1SUNBZ0lDQWdmU0JsYkhObElIdGNiaUFnSUNBZ0lDQWdZbk5XWVd4MVpVRnljbUY1VUdGeWRDQTlJR0p6Vm1Gc2RXVXVkbUZzZFdVdWMyeHBZMlVvWW1WbmFXNXVhVzVuU1c1a1pYZ3NJR0psWjJsdWJtbHVaMGx1WkdWNElDc2djMmw2WlNrN1hHNGdJQ0FnSUNBZ0lIQmhkSFJsY201Q2FYUlRkSEpwYm1kQmNuSmhlVkJoY25RZ1BTQndZWFIwWlhKdVFtbDBVM1J5YVc1bkxuTnNhV05sS0dKbFoybHVibWx1WjBsdVpHVjRMQ0JpWldkcGJtNXBibWRKYm1SbGVDQXJJSE5wZW1VcE8xeHVJQ0FnSUNBZ2ZWeHVYRzRnSUNBZ0lDQnBaaWhEYUdWamEzTXVhWE5mZG1GeWFXRmliR1VvWW1sMGMzUnlhVzVuVFdGMFkyaFFZWEowTG5aaGJIVmxLU2w3WEc0Z0lDQWdJQ0FnSUhOM2FYUmphQ2hpYVhSemRISnBibWROWVhSamFGQmhjblF1ZEhsd1pTa2dlMXh1SUNBZ0lDQWdJQ0JqWVhObElDZHBiblJsWjJWeUp6cGNiaUFnSUNBZ0lDQWdJQ0JwWmloaWFYUnpkSEpwYm1kTllYUmphRkJoY25RdVlYUjBjbWxpZFhSbGN5QW1KaUJpYVhSemRISnBibWROWVhSamFGQmhjblF1WVhSMGNtbGlkWFJsY3k1cGJtUmxlRTltS0Z3aWMybG5ibVZrWENJcElDRTlJQzB4S1h0Y2JpQWdJQ0FnSUNBZ0lDQWdJR0Z5WjNNdWNIVnphQ2h1WlhjZ1NXNTBPRUZ5Y21GNUtGdGljMVpoYkhWbFFYSnlZWGxRWVhKMFd6QmRYU2xiTUYwcE8xeHVJQ0FnSUNBZ0lDQWdJSDBnWld4elpTQjdYRzRnSUNBZ0lDQWdJQ0FnSUNCaGNtZHpMbkIxYzJnb2JtVjNJRlZwYm5RNFFYSnlZWGtvVzJKelZtRnNkV1ZCY25KaGVWQmhjblJiTUYxZEtWc3dYU2s3WEc0Z0lDQWdJQ0FnSUNBZ2ZWeHVJQ0FnSUNBZ0lDQWdJR0p5WldGck8xeHVYRzRnSUNBZ0lDQWdJR05oYzJVZ0oyWnNiMkYwSnpwY2JpQWdJQ0FnSUNBZ0lDQnBaaWh6YVhwbElEMDlQU0EyTkNsN1hHNGdJQ0FnSUNBZ0lDQWdJQ0JoY21kekxuQjFjMmdvUm14dllYUTJORUZ5Y21GNUxtWnliMjBvWW5OV1lXeDFaVUZ5Y21GNVVHRnlkQ2xiTUYwcE8xeHVJQ0FnSUNBZ0lDQWdJSDBnWld4elpTQnBaaWh6YVhwbElEMDlQU0F6TWlsN1hHNGdJQ0FnSUNBZ0lDQWdJQ0JoY21kekxuQjFjMmdvUm14dllYUXpNa0Z5Y21GNUxtWnliMjBvWW5OV1lXeDFaVUZ5Y21GNVVHRnlkQ2xiTUYwcE8xeHVJQ0FnSUNBZ0lDQWdJSDFsYkhObGUxeHVJQ0FnSUNBZ0lDQWdJQ0FnY21WMGRYSnVJR1poYkhObE8xeHVJQ0FnSUNBZ0lDQWdJSDFjYmlBZ0lDQWdJQ0FnSUNCaWNtVmhhenRjYmx4dUlDQWdJQ0FnSUNCallYTmxJQ2RpYVhSemRISnBibWNuT2x4dUlDQWdJQ0FnSUNBZ0lHRnlaM011Y0hWemFDaGpjbVZoZEdWQ2FYUlRkSEpwYm1jb1luTldZV3gxWlVGeWNtRjVVR0Z5ZENrcE8xeHVJQ0FnSUNBZ0lDQWdJR0p5WldGck8xeHVYRzRnSUNBZ0lDQWdJR05oYzJVZ0oySnBibUZ5ZVNjNlhHNGdJQ0FnSUNBZ0lDQWdZWEpuY3k1d2RYTm9LRk4wY21sdVp5NW1jbTl0UTJoaGNrTnZaR1V1WVhCd2JIa29iblZzYkN3Z2JtVjNJRlZwYm5RNFFYSnlZWGtvWW5OV1lXeDFaVUZ5Y21GNVVHRnlkQ2twS1R0Y2JpQWdJQ0FnSUNBZ0lDQmljbVZoYXp0Y2JseHVJQ0FnSUNBZ0lDQmpZWE5sSUNkMWRHWTRKenBjYmlBZ0lDQWdJQ0FnSUNCaGNtZHpMbkIxYzJnb1UzUnlhVzVuTG1aeWIyMURhR0Z5UTI5a1pTNWhjSEJzZVNodWRXeHNMQ0J1WlhjZ1ZXbHVkRGhCY25KaGVTaGljMVpoYkhWbFFYSnlZWGxRWVhKMEtTa3BPMXh1SUNBZ0lDQWdJQ0FnSUdKeVpXRnJPMXh1WEc0Z0lDQWdJQ0FnSUdOaGMyVWdKM1YwWmpFMkp6cGNiaUFnSUNBZ0lDQWdJQ0JoY21kekxuQjFjMmdvVTNSeWFXNW5MbVp5YjIxRGFHRnlRMjlrWlM1aGNIQnNlU2h1ZFd4c0xDQnVaWGNnVldsdWRERTJRWEp5WVhrb1luTldZV3gxWlVGeWNtRjVVR0Z5ZENrcEtUdGNiaUFnSUNBZ0lDQWdJQ0JpY21WaGF6dGNibHh1SUNBZ0lDQWdJQ0JqWVhObElDZDFkR1l6TWljNlhHNGdJQ0FnSUNBZ0lDQWdZWEpuY3k1d2RYTm9LRk4wY21sdVp5NW1jbTl0UTJoaGNrTnZaR1V1WVhCd2JIa29iblZzYkN3Z2JtVjNJRlZwYm5Rek1rRnljbUY1S0dKelZtRnNkV1ZCY25KaGVWQmhjblFwS1NrN1hHNGdJQ0FnSUNBZ0lDQWdZbkpsWVdzN1hHNWNiaUFnSUNBZ0lDQWdaR1ZtWVhWc2REcGNiaUFnSUNBZ0lDQWdJQ0J5WlhSMWNtNGdabUZzYzJVN1hHNGdJQ0FnSUNBZ0lIMWNiaUFnSUNBZ0lIMWxiSE5sSUdsbUtDRmhjbkpoZVhORmNYVmhiQ2hpYzFaaGJIVmxRWEp5WVhsUVlYSjBMQ0J3WVhSMFpYSnVRbWwwVTNSeWFXNW5RWEp5WVhsUVlYSjBLU2tnZTF4dUlDQWdJQ0FnSUNCeVpYUjFjbTRnWm1Gc2MyVTdYRzRnSUNBZ0lDQjlYRzVjYmlBZ0lDQWdJR0psWjJsdWJtbHVaMGx1WkdWNElEMGdZbVZuYVc1dWFXNW5TVzVrWlhnZ0t5QnphWHBsTzF4dUlDQWdJSDFjYmx4dUlDQWdJSEpsZEhWeWJpQjBjblZsTzF4dUlDQjlYRzVjYm4xY2JseHVablZ1WTNScGIyNGdaMlYwVTJsNlpTaDFibWwwTENCemFYcGxLWHRjYmlBZ2NtVjBkWEp1SUNoMWJtbDBJQ29nYzJsNlpTa2dMeUE0TzF4dWZWeHVYRzVtZFc1amRHbHZiaUJoY25KaGVYTkZjWFZoYkNoaExDQmlLU0I3WEc0Z0lHbG1JQ2hoSUQwOVBTQmlLU0J5WlhSMWNtNGdkSEoxWlR0Y2JpQWdhV1lnS0dFZ1BUMGdiblZzYkNCOGZDQmlJRDA5SUc1MWJHd3BJSEpsZEhWeWJpQm1ZV3h6WlR0Y2JpQWdhV1lnS0dFdWJHVnVaM1JvSUNFOUlHSXViR1Z1WjNSb0tTQnlaWFIxY200Z1ptRnNjMlU3WEc1Y2JpQWdabTl5SUNoMllYSWdhU0E5SURBN0lHa2dQQ0JoTG14bGJtZDBhRHNnS3l0cEtTQjdYRzRnSUNBZ2FXWWdLR0ZiYVYwZ0lUMDlJR0piYVYwcElISmxkSFZ5YmlCbVlXeHpaVHRjYmlBZ2ZWeHVYRzRnSUhKbGRIVnliaUIwY25WbE8xeHVmVnh1WEc1bWRXNWpkR2x2YmlCbWFXeHNRWEp5WVhrb1lYSnlMQ0J1ZFcwcGUxeHVJQ0JtYjNJb2JHVjBJR2tnUFNBd095QnBJRHdnYm5WdE95QnBLeXNwZTF4dUlDQWdJR0Z5Y2k1d2RYTm9LREFwTzF4dUlDQjlYRzU5WEc1Y2JtWjFibU4wYVc5dUlHTnlaV0YwWlVKcGRGTjBjbWx1WnloaGNuSXBlMXh1SUNCc1pYUWdhVzUwWldkbGNsQmhjblJ6SUQwZ1lYSnlMbTFoY0Nnb1pXeGxiU2tnUFQ0Z1FtbDBVM1J5YVc1bkxtbHVkR1ZuWlhJb1pXeGxiU2twTzF4dUlDQnlaWFIxY200Z2JtVjNJRUpwZEZOMGNtbHVaeWd1TGk1cGJuUmxaMlZ5VUdGeWRITXBPMXh1ZlZ4dVhHNW1kVzVqZEdsdmJpQnlaWE52YkhabFRtOU5ZWFJqYUNncE9pQkdkVzVqZEdsdmJpQjdYRzRnSUhKbGRIVnliaUJtZFc1amRHbHZiaWdwT2lCaWIyOXNaV0Z1SUh0Y2JpQWdJQ0J5WlhSMWNtNGdabUZzYzJVN1hHNGdJSDFjYm4xY2JseHVaWGh3YjNKMElHUmxabUYxYkhRZ2UxeHVJQ0J5WlhOdmJIWmxRbTkxYm1Rc1hHNGdJSEpsYzI5c2RtVlhhV3hrWTJGeVpDeGNiaUFnY21WemIyeDJaVlpoY21saFlteGxMRnh1SUNCeVpYTnZiSFpsU0dWaFpGUmhhV3dzWEc0Z0lISmxjMjlzZG1WRFlYQjBkWEpsTEZ4dUlDQnlaWE52YkhabFUzUmhjblJ6VjJsMGFDeGNiaUFnY21WemIyeDJaVlI1Y0dVc1hHNGdJSEpsYzI5c2RtVkJjbkpoZVN4Y2JpQWdjbVZ6YjJ4MlpVOWlhbVZqZEN4Y2JpQWdjbVZ6YjJ4MlpVNXZUV0YwWTJnc1hHNGdJSEpsYzI5c2RtVlRlVzFpYjJ3c1hHNGdJSEpsYzI5c2RtVlRkSEpwYm1jc1hHNGdJSEpsYzI5c2RtVk9kVzFpWlhJc1hHNGdJSEpsYzI5c2RtVkNiMjlzWldGdUxGeHVJQ0J5WlhOdmJIWmxSblZ1WTNScGIyNHNYRzRnSUhKbGMyOXNkbVZPZFd4c0xGeHVJQ0J5WlhOdmJIWmxRbWwwVTNSeWFXNW5YRzU5WEc0aVhTd2ljMjkxY21ObFVtOXZkQ0k2SWk5emIzVnlZMlV2SW4wPVxuIiwiXG5pbXBvcnQgQ2hlY2tzIGZyb20gXCIuL2NoZWNrc1wiO1xuaW1wb3J0IFJlc29sdmVycyBmcm9tIFwiLi9yZXNvbHZlcnNcIjtcblxuZXhwb3J0IGZ1bmN0aW9uIGJ1aWxkTWF0Y2gocGF0dGVybikge1xuXG4gIGlmIChDaGVja3MuaXNfdmFyaWFibGUocGF0dGVybikpIHtcbiAgICByZXR1cm4gUmVzb2x2ZXJzLnJlc29sdmVWYXJpYWJsZShwYXR0ZXJuKTtcbiAgfVxuXG4gIGlmIChDaGVja3MuaXNfd2lsZGNhcmQocGF0dGVybikpIHtcbiAgICByZXR1cm4gUmVzb2x2ZXJzLnJlc29sdmVXaWxkY2FyZChwYXR0ZXJuKTtcbiAgfVxuXG4gIGlmIChDaGVja3MuaXNfdW5kZWZpbmVkKHBhdHRlcm4pKSB7XG4gICAgcmV0dXJuIFJlc29sdmVycy5yZXNvbHZlV2lsZGNhcmQocGF0dGVybik7XG4gIH1cblxuICBpZiAoQ2hlY2tzLmlzX2hlYWRUYWlsKHBhdHRlcm4pKSB7XG4gICAgcmV0dXJuIFJlc29sdmVycy5yZXNvbHZlSGVhZFRhaWwocGF0dGVybik7XG4gIH1cblxuICBpZiAoQ2hlY2tzLmlzX3N0YXJ0c1dpdGgocGF0dGVybikpIHtcbiAgICByZXR1cm4gUmVzb2x2ZXJzLnJlc29sdmVTdGFydHNXaXRoKHBhdHRlcm4pO1xuICB9XG5cbiAgaWYgKENoZWNrcy5pc19jYXB0dXJlKHBhdHRlcm4pKSB7XG4gICAgcmV0dXJuIFJlc29sdmVycy5yZXNvbHZlQ2FwdHVyZShwYXR0ZXJuKTtcbiAgfVxuXG4gIGlmIChDaGVja3MuaXNfYm91bmQocGF0dGVybikpIHtcbiAgICByZXR1cm4gUmVzb2x2ZXJzLnJlc29sdmVCb3VuZChwYXR0ZXJuKTtcbiAgfVxuXG4gIGlmIChDaGVja3MuaXNfdHlwZShwYXR0ZXJuKSkge1xuICAgIHJldHVybiBSZXNvbHZlcnMucmVzb2x2ZVR5cGUocGF0dGVybik7XG4gIH1cblxuICBpZiAoQ2hlY2tzLmlzX2FycmF5KHBhdHRlcm4pKSB7XG4gICAgcmV0dXJuIFJlc29sdmVycy5yZXNvbHZlQXJyYXkocGF0dGVybik7XG4gIH1cblxuICBpZiAoQ2hlY2tzLmlzX251bWJlcihwYXR0ZXJuKSkge1xuICAgIHJldHVybiBSZXNvbHZlcnMucmVzb2x2ZU51bWJlcihwYXR0ZXJuKTtcbiAgfVxuXG4gIGlmIChDaGVja3MuaXNfc3RyaW5nKHBhdHRlcm4pKSB7XG4gICAgcmV0dXJuIFJlc29sdmVycy5yZXNvbHZlU3RyaW5nKHBhdHRlcm4pO1xuICB9XG5cbiAgaWYgKENoZWNrcy5pc19ib29sZWFuKHBhdHRlcm4pKSB7XG4gICAgcmV0dXJuIFJlc29sdmVycy5yZXNvbHZlQm9vbGVhbihwYXR0ZXJuKTtcbiAgfVxuXG4gIGlmIChDaGVja3MuaXNfc3ltYm9sKHBhdHRlcm4pKSB7XG4gICAgcmV0dXJuIFJlc29sdmVycy5yZXNvbHZlU3ltYm9sKHBhdHRlcm4pO1xuICB9XG5cbiAgaWYgKENoZWNrcy5pc19udWxsKHBhdHRlcm4pKSB7XG4gICAgcmV0dXJuIFJlc29sdmVycy5yZXNvbHZlTnVsbChwYXR0ZXJuKTtcbiAgfVxuXG4gIGlmIChDaGVja3MuaXNfYml0c3RyaW5nKHBhdHRlcm4pKSB7XG4gICAgcmV0dXJuIFJlc29sdmVycy5yZXNvbHZlQml0U3RyaW5nKHBhdHRlcm4pO1xuICB9XG5cbiAgaWYgKENoZWNrcy5pc19vYmplY3QocGF0dGVybikpIHtcbiAgICByZXR1cm4gUmVzb2x2ZXJzLnJlc29sdmVPYmplY3QocGF0dGVybik7XG4gIH1cblxuICByZXR1cm4gUmVzb2x2ZXJzLnJlc29sdmVOb01hdGNoKCk7XG59XG4vLyMgc291cmNlTWFwcGluZ1VSTD1kYXRhOmFwcGxpY2F0aW9uL2pzb247YmFzZTY0LGV5SjJaWEp6YVc5dUlqb3pMQ0p6YjNWeVkyVnpJanBiSW14cFlpOWpiM0psTDNCaGRIUmxjbTV6TDIxaGRHTm9MbXB6SWwwc0ltNWhiV1Z6SWpwYlhTd2liV0Z3Y0dsdVozTWlPaUk3UVVGRFFTeFBRVUZQTEUxQlFWQXNUVUZCYlVJc1ZVRkJia0k3UVVGRFFTeFBRVUZQTEZOQlFWQXNUVUZCYzBJc1lVRkJkRUk3TzBGQlJVRXNUMEZCVHl4VFFVRlRMRlZCUVZRc1EwRkJiMElzVDBGQmNFSXNSVUZCTkVNN08wRkJSV3BFTEUxQlFVY3NUMEZCVHl4WFFVRlFMRU5CUVcxQ0xFOUJRVzVDTEVOQlFVZ3NSVUZCSzBJN1FVRkROMElzVjBGQlR5eFZRVUZWTEdWQlFWWXNRMEZCTUVJc1QwRkJNVUlzUTBGQlVDeERRVVEyUWp0SFFVRXZRanM3UVVGSlFTeE5RVUZITEU5QlFVOHNWMEZCVUN4RFFVRnRRaXhQUVVGdVFpeERRVUZJTEVWQlFTdENPMEZCUXpkQ0xGZEJRVThzVlVGQlZTeGxRVUZXTEVOQlFUQkNMRTlCUVRGQ0xFTkJRVkFzUTBGRU5rSTdSMEZCTDBJN08wRkJTVUVzVFVGQlJ5eFBRVUZQTEZsQlFWQXNRMEZCYjBJc1QwRkJjRUlzUTBGQlNDeEZRVUZuUXp0QlFVTTVRaXhYUVVGUExGVkJRVlVzWlVGQlZpeERRVUV3UWl4UFFVRXhRaXhEUVVGUUxFTkJSRGhDTzBkQlFXaERPenRCUVVsQkxFMUJRVWNzVDBGQlR5eFhRVUZRTEVOQlFXMUNMRTlCUVc1Q0xFTkJRVWdzUlVGQkswSTdRVUZETjBJc1YwRkJUeXhWUVVGVkxHVkJRVllzUTBGQk1FSXNUMEZCTVVJc1EwRkJVQ3hEUVVRMlFqdEhRVUV2UWpzN1FVRkpRU3hOUVVGSExFOUJRVThzWVVGQlVDeERRVUZ4UWl4UFFVRnlRaXhEUVVGSUxFVkJRV2xETzBGQlF5OUNMRmRCUVU4c1ZVRkJWU3hwUWtGQlZpeERRVUUwUWl4UFFVRTFRaXhEUVVGUUxFTkJSQ3RDTzBkQlFXcERPenRCUVVsQkxFMUJRVWNzVDBGQlR5eFZRVUZRTEVOQlFXdENMRTlCUVd4Q0xFTkJRVWdzUlVGQk9FSTdRVUZETlVJc1YwRkJUeXhWUVVGVkxHTkJRVllzUTBGQmVVSXNUMEZCZWtJc1EwRkJVQ3hEUVVRMFFqdEhRVUU1UWpzN1FVRkpRU3hOUVVGSExFOUJRVThzVVVGQlVDeERRVUZuUWl4UFFVRm9RaXhEUVVGSUxFVkJRVFJDTzBGQlF6RkNMRmRCUVU4c1ZVRkJWU3haUVVGV0xFTkJRWFZDTEU5QlFYWkNMRU5CUVZBc1EwRkVNRUk3UjBGQk5VSTdPMEZCU1VFc1RVRkJSeXhQUVVGUExFOUJRVkFzUTBGQlpTeFBRVUZtTEVOQlFVZ3NSVUZCTWtJN1FVRkRla0lzVjBGQlR5eFZRVUZWTEZkQlFWWXNRMEZCYzBJc1QwRkJkRUlzUTBGQlVDeERRVVI1UWp0SFFVRXpRanM3UVVGSlFTeE5RVUZITEU5QlFVOHNVVUZCVUN4RFFVRm5RaXhQUVVGb1FpeERRVUZJTEVWQlFUUkNPMEZCUXpGQ0xGZEJRVThzVlVGQlZTeFpRVUZXTEVOQlFYVkNMRTlCUVhaQ0xFTkJRVkFzUTBGRU1FSTdSMEZCTlVJN08wRkJTVUVzVFVGQlJ5eFBRVUZQTEZOQlFWQXNRMEZCYVVJc1QwRkJha0lzUTBGQlNDeEZRVUUyUWp0QlFVTXpRaXhYUVVGUExGVkJRVlVzWVVGQlZpeERRVUYzUWl4UFFVRjRRaXhEUVVGUUxFTkJSREpDTzBkQlFUZENPenRCUVVsQkxFMUJRVWNzVDBGQlR5eFRRVUZRTEVOQlFXbENMRTlCUVdwQ0xFTkJRVWdzUlVGQk5rSTdRVUZETTBJc1YwRkJUeXhWUVVGVkxHRkJRVllzUTBGQmQwSXNUMEZCZUVJc1EwRkJVQ3hEUVVReVFqdEhRVUUzUWpzN1FVRkpRU3hOUVVGSExFOUJRVThzVlVGQlVDeERRVUZyUWl4UFFVRnNRaXhEUVVGSUxFVkJRVGhDTzBGQlF6VkNMRmRCUVU4c1ZVRkJWU3hqUVVGV0xFTkJRWGxDTEU5QlFYcENMRU5CUVZBc1EwRkVORUk3UjBGQk9VSTdPMEZCU1VFc1RVRkJSeXhQUVVGUExGTkJRVkFzUTBGQmFVSXNUMEZCYWtJc1EwRkJTQ3hGUVVFMlFqdEJRVU16UWl4WFFVRlBMRlZCUVZVc1lVRkJWaXhEUVVGM1FpeFBRVUY0UWl4RFFVRlFMRU5CUkRKQ08wZEJRVGRDT3p0QlFVbEJMRTFCUVVjc1QwRkJUeXhQUVVGUUxFTkJRV1VzVDBGQlppeERRVUZJTEVWQlFUSkNPMEZCUTNwQ0xGZEJRVThzVlVGQlZTeFhRVUZXTEVOQlFYTkNMRTlCUVhSQ0xFTkJRVkFzUTBGRWVVSTdSMEZCTTBJN08wRkJTVUVzVFVGQlJ5eFBRVUZQTEZsQlFWQXNRMEZCYjBJc1QwRkJjRUlzUTBGQlNDeEZRVUZuUXp0QlFVTTVRaXhYUVVGUExGVkJRVlVzWjBKQlFWWXNRMEZCTWtJc1QwRkJNMElzUTBGQlVDeERRVVE0UWp0SFFVRm9RenM3UVVGSlFTeE5RVUZITEU5QlFVOHNVMEZCVUN4RFFVRnBRaXhQUVVGcVFpeERRVUZJTEVWQlFUWkNPMEZCUXpOQ0xGZEJRVThzVlVGQlZTeGhRVUZXTEVOQlFYZENMRTlCUVhoQ0xFTkJRVkFzUTBGRU1rSTdSMEZCTjBJN08wRkJTVUVzVTBGQlR5eFZRVUZWTEdOQlFWWXNSVUZCVUN4RFFXeEZhVVE3UTBGQk5VTWlMQ0ptYVd4bElqb2liR2xpTDJOdmNtVXZjR0YwZEdWeWJuTXZiV0YwWTJndWFuTWlMQ0p6YjNWeVkyVnpRMjl1ZEdWdWRDSTZXeUl2S2lCQVpteHZkeUFxTDF4dWFXMXdiM0owSUVOb1pXTnJjeUJtY205dElGd2lMaTlqYUdWamEzTmNJanRjYm1sdGNHOXlkQ0JTWlhOdmJIWmxjbk1nWm5KdmJTQmNJaTR2Y21WemIyeDJaWEp6WENJN1hHNWNibVY0Y0c5eWRDQm1kVzVqZEdsdmJpQmlkV2xzWkUxaGRHTm9LSEJoZEhSbGNtNDZJR0Z1ZVNrNklFWjFibU4wYVc5dUlIdGNibHh1SUNCcFppaERhR1ZqYTNNdWFYTmZkbUZ5YVdGaWJHVW9jR0YwZEdWeWJpa3BlMXh1SUNBZ0lISmxkSFZ5YmlCU1pYTnZiSFpsY25NdWNtVnpiMngyWlZaaGNtbGhZbXhsS0hCaGRIUmxjbTRwTzF4dUlDQjlYRzVjYmlBZ2FXWW9RMmhsWTJ0ekxtbHpYM2RwYkdSallYSmtLSEJoZEhSbGNtNHBLWHRjYmlBZ0lDQnlaWFIxY200Z1VtVnpiMngyWlhKekxuSmxjMjlzZG1WWGFXeGtZMkZ5WkNod1lYUjBaWEp1S1R0Y2JpQWdmVnh1WEc0Z0lHbG1LRU5vWldOcmN5NXBjMTkxYm1SbFptbHVaV1FvY0dGMGRHVnliaWtwZTF4dUlDQWdJSEpsZEhWeWJpQlNaWE52YkhabGNuTXVjbVZ6YjJ4MlpWZHBiR1JqWVhKa0tIQmhkSFJsY200cE8xeHVJQ0I5WEc1Y2JpQWdhV1lvUTJobFkydHpMbWx6WDJobFlXUlVZV2xzS0hCaGRIUmxjbTRwS1h0Y2JpQWdJQ0J5WlhSMWNtNGdVbVZ6YjJ4MlpYSnpMbkpsYzI5c2RtVklaV0ZrVkdGcGJDaHdZWFIwWlhKdUtUdGNiaUFnZlZ4dVhHNGdJR2xtS0VOb1pXTnJjeTVwYzE5emRHRnlkSE5YYVhSb0tIQmhkSFJsY200cEtYdGNiaUFnSUNCeVpYUjFjbTRnVW1WemIyeDJaWEp6TG5KbGMyOXNkbVZUZEdGeWRITlhhWFJvS0hCaGRIUmxjbTRwTzF4dUlDQjlYRzVjYmlBZ2FXWW9RMmhsWTJ0ekxtbHpYMk5oY0hSMWNtVW9jR0YwZEdWeWJpa3BlMXh1SUNBZ0lISmxkSFZ5YmlCU1pYTnZiSFpsY25NdWNtVnpiMngyWlVOaGNIUjFjbVVvY0dGMGRHVnliaWs3WEc0Z0lIMWNibHh1SUNCcFppaERhR1ZqYTNNdWFYTmZZbTkxYm1Rb2NHRjBkR1Z5YmlrcGUxeHVJQ0FnSUhKbGRIVnliaUJTWlhOdmJIWmxjbk11Y21WemIyeDJaVUp2ZFc1a0tIQmhkSFJsY200cE8xeHVJQ0I5WEc1Y2JpQWdhV1lvUTJobFkydHpMbWx6WDNSNWNHVW9jR0YwZEdWeWJpa3BlMXh1SUNBZ0lISmxkSFZ5YmlCU1pYTnZiSFpsY25NdWNtVnpiMngyWlZSNWNHVW9jR0YwZEdWeWJpazdYRzRnSUgxY2JseHVJQ0JwWmloRGFHVmphM011YVhOZllYSnlZWGtvY0dGMGRHVnliaWtwZTF4dUlDQWdJSEpsZEhWeWJpQlNaWE52YkhabGNuTXVjbVZ6YjJ4MlpVRnljbUY1S0hCaGRIUmxjbTRwTzF4dUlDQjlYRzVjYmlBZ2FXWW9RMmhsWTJ0ekxtbHpYMjUxYldKbGNpaHdZWFIwWlhKdUtTbDdYRzRnSUNBZ2NtVjBkWEp1SUZKbGMyOXNkbVZ5Y3k1eVpYTnZiSFpsVG5WdFltVnlLSEJoZEhSbGNtNHBPMXh1SUNCOVhHNWNiaUFnYVdZb1EyaGxZMnR6TG1selgzTjBjbWx1Wnlod1lYUjBaWEp1S1NsN1hHNGdJQ0FnY21WMGRYSnVJRkpsYzI5c2RtVnljeTV5WlhOdmJIWmxVM1J5YVc1bktIQmhkSFJsY200cE8xeHVJQ0I5WEc1Y2JpQWdhV1lvUTJobFkydHpMbWx6WDJKdmIyeGxZVzRvY0dGMGRHVnliaWtwZTF4dUlDQWdJSEpsZEhWeWJpQlNaWE52YkhabGNuTXVjbVZ6YjJ4MlpVSnZiMnhsWVc0b2NHRjBkR1Z5YmlrN1hHNGdJSDFjYmx4dUlDQnBaaWhEYUdWamEzTXVhWE5mYzNsdFltOXNLSEJoZEhSbGNtNHBLWHRjYmlBZ0lDQnlaWFIxY200Z1VtVnpiMngyWlhKekxuSmxjMjlzZG1WVGVXMWliMndvY0dGMGRHVnliaWs3WEc0Z0lIMWNibHh1SUNCcFppaERhR1ZqYTNNdWFYTmZiblZzYkNod1lYUjBaWEp1S1NsN1hHNGdJQ0FnY21WMGRYSnVJRkpsYzI5c2RtVnljeTV5WlhOdmJIWmxUblZzYkNod1lYUjBaWEp1S1R0Y2JpQWdmVnh1WEc0Z0lHbG1LRU5vWldOcmN5NXBjMTlpYVhSemRISnBibWNvY0dGMGRHVnliaWtwZTF4dUlDQWdJSEpsZEhWeWJpQlNaWE52YkhabGNuTXVjbVZ6YjJ4MlpVSnBkRk4wY21sdVp5aHdZWFIwWlhKdUtUdGNiaUFnZlZ4dVhHNGdJR2xtS0VOb1pXTnJjeTVwYzE5dlltcGxZM1FvY0dGMGRHVnliaWtwZTF4dUlDQWdJSEpsZEhWeWJpQlNaWE52YkhabGNuTXVjbVZ6YjJ4MlpVOWlhbVZqZENod1lYUjBaWEp1S1R0Y2JpQWdmVnh1WEc0Z0lISmxkSFZ5YmlCU1pYTnZiSFpsY25NdWNtVnpiMngyWlU1dlRXRjBZMmdvS1R0Y2JuMWNiaUpkTENKemIzVnlZMlZTYjI5MElqb2lMM052ZFhKalpTOGlmUT09XG4iLCJcblxuaW1wb3J0IHsgYnVpbGRNYXRjaCB9IGZyb20gXCIuL21hdGNoXCI7XG5pbXBvcnQgKiBhcyBUeXBlcyBmcm9tIFwiLi90eXBlc1wiO1xuXG5leHBvcnQgY2xhc3MgTWF0Y2hFcnJvciBleHRlbmRzIEVycm9yIHtcbiAgY29uc3RydWN0b3IoYXJnKSB7XG4gICAgc3VwZXIoKTtcblxuICAgIGlmICh0eXBlb2YgYXJnID09PSAnc3ltYm9sJykge1xuICAgICAgdGhpcy5tZXNzYWdlID0gJ05vIG1hdGNoIGZvcjogJyArIGFyZy50b1N0cmluZygpO1xuICAgIH0gZWxzZSBpZiAoQXJyYXkuaXNBcnJheShhcmcpKSB7XG4gICAgICBsZXQgbWFwcGVkVmFsdWVzID0gYXJnLm1hcCh4ID0+IHgudG9TdHJpbmcoKSk7XG4gICAgICB0aGlzLm1lc3NhZ2UgPSAnTm8gbWF0Y2ggZm9yOiAnICsgbWFwcGVkVmFsdWVzO1xuICAgIH0gZWxzZSB7XG4gICAgICB0aGlzLm1lc3NhZ2UgPSAnTm8gbWF0Y2ggZm9yOiAnICsgYXJnO1xuICAgIH1cblxuICAgIHRoaXMuc3RhY2sgPSBuZXcgRXJyb3IoKS5zdGFjaztcbiAgICB0aGlzLm5hbWUgPSB0aGlzLmNvbnN0cnVjdG9yLm5hbWU7XG4gIH1cbn1cblxuZXhwb3J0IGNsYXNzIENhc2Uge1xuXG4gIGNvbnN0cnVjdG9yKHBhdHRlcm4sIGZuLCBndWFyZCA9ICgpID0+IHRydWUpIHtcbiAgICB0aGlzLnBhdHRlcm4gPSBidWlsZE1hdGNoKHBhdHRlcm4pO1xuICAgIHRoaXMuYXJpdHkgPSBwYXR0ZXJuLmxlbmd0aDtcbiAgICB0aGlzLm9wdGlvbmFscyA9IGdldE9wdGlvbmFsVmFsdWVzKHBhdHRlcm4pO1xuICAgIHRoaXMuZm4gPSBmbjtcbiAgICB0aGlzLmd1YXJkID0gZ3VhcmQ7XG4gIH1cbn1cblxuZXhwb3J0IGZ1bmN0aW9uIG1ha2VfY2FzZShwYXR0ZXJuLCBmbiwgZ3VhcmQgPSAoKSA9PiB0cnVlKSB7XG4gIHJldHVybiBuZXcgQ2FzZShwYXR0ZXJuLCBmbiwgZ3VhcmQpO1xufVxuXG5leHBvcnQgZnVuY3Rpb24gZGVmbWF0Y2goLi4uY2FzZXMpIHtcbiAgcmV0dXJuIGZ1bmN0aW9uICguLi5hcmdzKSB7XG4gICAgZm9yIChsZXQgcHJvY2Vzc2VkQ2FzZSBvZiBjYXNlcykge1xuICAgICAgbGV0IHJlc3VsdCA9IFtdO1xuICAgICAgYXJncyA9IGZpbGxJbk9wdGlvbmFsVmFsdWVzKGFyZ3MsIHByb2Nlc3NlZENhc2UuYXJpdHksIHByb2Nlc3NlZENhc2Uub3B0aW9uYWxzKTtcblxuICAgICAgaWYgKHByb2Nlc3NlZENhc2UucGF0dGVybihhcmdzLCByZXN1bHQpICYmIHByb2Nlc3NlZENhc2UuZ3VhcmQuYXBwbHkodGhpcywgcmVzdWx0KSkge1xuICAgICAgICByZXR1cm4gcHJvY2Vzc2VkQ2FzZS5mbi5hcHBseSh0aGlzLCByZXN1bHQpO1xuICAgICAgfVxuICAgIH1cblxuICAgIHRocm93IG5ldyBNYXRjaEVycm9yKGFyZ3MpO1xuICB9O1xufVxuXG5mdW5jdGlvbiBnZXRPcHRpb25hbFZhbHVlcyhwYXR0ZXJuKSB7XG4gIGxldCBvcHRpb25hbHMgPSBbXTtcblxuICBmb3IgKGxldCBpID0gMDsgaSA8IHBhdHRlcm4ubGVuZ3RoOyBpKyspIHtcbiAgICBpZiAocGF0dGVybltpXSBpbnN0YW5jZW9mIFR5cGVzLlZhcmlhYmxlICYmIHBhdHRlcm5baV0uZGVmYXVsdF92YWx1ZSAhPSBTeW1ib2wuZm9yKFwiZWxpeGlyc2NyaXB0Lm5vX3ZhbHVlXCIpKSB7XG4gICAgICBvcHRpb25hbHMucHVzaChbaSwgcGF0dGVybltpXS5kZWZhdWx0X3ZhbHVlXSk7XG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIG9wdGlvbmFscztcbn1cblxuZnVuY3Rpb24gZmlsbEluT3B0aW9uYWxWYWx1ZXMoYXJncywgYXJpdHksIG9wdGlvbmFscykge1xuICBpZiAoYXJncy5sZW5ndGggPT09IGFyaXR5IHx8IG9wdGlvbmFscy5sZW5ndGggPT09IDApIHtcbiAgICByZXR1cm4gYXJncztcbiAgfVxuXG4gIGlmIChhcmdzLmxlbmd0aCArIG9wdGlvbmFscy5sZW5ndGggPCBhcml0eSkge1xuICAgIHJldHVybiBhcmdzO1xuICB9XG5cbiAgbGV0IG51bWJlck9mT3B0aW9uYWxzVG9GaWxsID0gYXJpdHkgLSBhcmdzLmxlbmd0aDtcbiAgbGV0IG9wdGlvbmFsc1RvUmVtb3ZlID0gb3B0aW9uYWxzLmxlbmd0aCAtIG51bWJlck9mT3B0aW9uYWxzVG9GaWxsO1xuXG4gIGxldCBvcHRpb25hbHNUb1VzZSA9IG9wdGlvbmFscy5zbGljZShvcHRpb25hbHNUb1JlbW92ZSk7XG5cbiAgZm9yIChsZXQgW2luZGV4LCB2YWx1ZV0gb2Ygb3B0aW9uYWxzVG9Vc2UpIHtcbiAgICBhcmdzLnNwbGljZShpbmRleCwgMCwgdmFsdWUpO1xuICAgIGlmIChhcmdzLmxlbmd0aCA9PT0gYXJpdHkpIHtcbiAgICAgIGJyZWFrO1xuICAgIH1cbiAgfVxuXG4gIHJldHVybiBhcmdzO1xufVxuXG5leHBvcnQgZnVuY3Rpb24gbWF0Y2gocGF0dGVybiwgZXhwciwgZ3VhcmQgPSAoKSA9PiB0cnVlKSB7XG4gIGxldCByZXN1bHQgPSBbXTtcbiAgbGV0IHByb2Nlc3NlZFBhdHRlcm4gPSBidWlsZE1hdGNoKHBhdHRlcm4pO1xuICBpZiAocHJvY2Vzc2VkUGF0dGVybihleHByLCByZXN1bHQpICYmIGd1YXJkLmFwcGx5KHRoaXMsIHJlc3VsdCkpIHtcbiAgICByZXR1cm4gcmVzdWx0O1xuICB9IGVsc2Uge1xuICAgIHRocm93IG5ldyBNYXRjaEVycm9yKGV4cHIpO1xuICB9XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBtYXRjaF9ub190aHJvdyhwYXR0ZXJuLCBleHByLCBndWFyZCA9ICgpID0+IHRydWUpIHtcbiAgdHJ5IHtcbiAgICByZXR1cm4gbWF0Y2gocGF0dGVybiwgZXhwciwgZ3VhcmQpO1xuICB9IGNhdGNoIChlKSB7XG4gICAgaWYgKGUgaW5zdGFuY2VvZiBNYXRjaEVycm9yIHx8IGUubWVzc2FnZS5zdGFydHNXaXRoKCdObyBtYXRjaCBmb3I6JykpIHtcbiAgICAgIHJldHVybiBudWxsO1xuICAgIH1cblxuICAgIHRocm93IGU7XG4gIH1cbn1cblxuZXhwb3J0IGZ1bmN0aW9uIHBhdHRlcm5NYXAoY29sbGVjdGlvbiwgcGF0dGVybiwgZnVuLCBndWFyZCA9ICgpID0+IHRydWUpIHtcbiAgbGV0IHJldCA9IFtdO1xuXG4gIGZvciAobGV0IGVsZW0gb2YgY29sbGVjdGlvbikge1xuICAgIHRyeSB7XG4gICAgICBsZXQgcmVzdWx0ID0gZnVuLmFwcGx5KHRoaXMsIG1hdGNoKHBhdHRlcm4sIGVsZW0sIGd1YXJkKSk7XG4gICAgICByZXQgPSByZXQuY29uY2F0KHJlc3VsdCk7XG4gICAgfSBjYXRjaCAoZSkge1xuICAgICAgaWYgKCEoZSBpbnN0YW5jZW9mIE1hdGNoRXJyb3IpKSB7XG4gICAgICAgIHRocm93IGU7XG4gICAgICB9XG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIHJldDtcbn1cbi8vIyBzb3VyY2VNYXBwaW5nVVJMPWRhdGE6YXBwbGljYXRpb24vanNvbjtiYXNlNjQsZXlKMlpYSnphVzl1SWpvekxDSnpiM1Z5WTJWeklqcGJJbXhwWWk5amIzSmxMM0JoZEhSbGNtNXpMMlJsWm0xaGRHTm9MbXB6SWwwc0ltNWhiV1Z6SWpwYlhTd2liV0Z3Y0dsdVozTWlPaUk3TzBGQlJVRXNVMEZCVXl4VlFVRlVMRkZCUVRKQ0xGTkJRVE5DTzBGQlEwRXNUMEZCVHl4TFFVRkxMRXRCUVV3c1RVRkJaMElzVTBGQmRrSTdPMEZCUlVFc1QwRkJUeXhOUVVGTkxGVkJRVTRzVTBGQmVVSXNTMEZCZWtJc1EwRkJLMEk3UVVGRGNFTXNZMEZCV1N4SFFVRmFMRVZCUVhOQ08wRkJRM0JDTEZsQlJHOUNPenRCUVVkd1FpeFJRVUZITEU5QlFVOHNSMEZCVUN4TFFVRmxMRkZCUVdZc1JVRkJkMEk3UVVGRGVrSXNWMEZCU3l4UFFVRk1MRWRCUVdVc2JVSkJRVzFDTEVsQlFVa3NVVUZCU2l4RlFVRnVRaXhEUVVSVk8wdEJRVE5DTEUxQlJVOHNTVUZCUnl4TlFVRk5MRTlCUVU0c1EwRkJZeXhIUVVGa0xFTkJRVWdzUlVGQmMwSTdRVUZETTBJc1ZVRkJTU3hsUVVGbExFbEJRVWtzUjBGQlNpeERRVUZSTEV0QlFVOHNSVUZCUlN4UlFVRkdMRVZCUVZBc1EwRkJka0lzUTBGRWRVSTdRVUZGTTBJc1YwRkJTeXhQUVVGTUxFZEJRV1VzYlVKQlFXMUNMRmxCUVc1Q0xFTkJSbGs3UzBGQmRFSXNUVUZIUmp0QlFVTklMRmRCUVVzc1QwRkJUQ3hIUVVGbExHMUNRVUZ0UWl4SFFVRnVRaXhEUVVSYU8wdEJTRVU3TzBGQlQxQXNVMEZCU3l4TFFVRk1MRWRCUVdFc1NVRkJTeXhMUVVGS0xFVkJRVVFzUTBGQll5eExRVUZrTEVOQldrODdRVUZoY0VJc1UwRkJTeXhKUVVGTUxFZEJRVmtzUzBGQlN5eFhRVUZNTEVOQlFXbENMRWxCUVdwQ0xFTkJZbEU3UjBGQmRFSTdRMEZFU3pzN1FVRnRRbEFzVDBGQlR5eE5RVUZOTEVsQlFVNHNRMEZCVnpzN1FVRlBhRUlzWTBGQldTeFBRVUZhTEVWQlFXbERMRVZCUVdwRExFVkJRU3RFTEZGQlFVVXNUVUZCVFN4SlFVRk9MRVZCUVZjN1FVRkRNVVVzVTBGQlN5eFBRVUZNTEVkQlFXVXNWMEZCVnl4UFFVRllMRU5CUVdZc1EwRkVNRVU3UVVGRk1VVXNVMEZCU3l4TFFVRk1MRWRCUVdFc1VVRkJVU3hOUVVGU0xFTkJSalpFTzBGQlJ6RkZMRk5CUVVzc1UwRkJUQ3hIUVVGcFFpeHJRa0ZCYTBJc1QwRkJiRUlzUTBGQmFrSXNRMEZJTUVVN1FVRkpNVVVzVTBGQlN5eEZRVUZNTEVkQlFWVXNSVUZCVml4RFFVb3dSVHRCUVVzeFJTeFRRVUZMTEV0QlFVd3NSMEZCWVN4TFFVRmlMRU5CVERCRk8wZEJRVFZGTzBOQlVFczdPMEZCWjBKUUxFOUJRVThzVTBGQlV5eFRRVUZVTEVOQlFXMUNMRTlCUVc1Q0xFVkJRWGRETEVWQlFYaERMRVZCUVhORkxGRkJRVVVzVFVGQlRTeEpRVUZPTEVWQlFXdENPMEZCUXk5R0xGTkJRVThzU1VGQlNTeEpRVUZLTEVOQlFWTXNUMEZCVkN4RlFVRnJRaXhGUVVGc1FpeEZRVUZ6UWl4TFFVRjBRaXhEUVVGUUxFTkJSQ3RHTzBOQlFURkdPenRCUVVsUUxFOUJRVThzVTBGQlV5eFJRVUZVTEVOQlFXdENMRWRCUVVjc1MwRkJTQ3hGUVVGcFF6dEJRVU40UkN4VFFVRlBMRlZCUVZNc1IwRkJSeXhKUVVGSUxFVkJRVEJDTzBGQlEzaERMRk5CUVVzc1NVRkJTU3hoUVVGS0xFbEJRWEZDTEV0QlFURkNMRVZCUVdsRE8wRkJReTlDTEZWQlFVa3NVMEZCVXl4RlFVRlVMRU5CUkRKQ08wRkJSUzlDTEdGQlFVOHNjVUpCUVhGQ0xFbEJRWEpDTEVWQlFUSkNMR05CUVdNc1MwRkJaQ3hGUVVGeFFpeGpRVUZqTEZOQlFXUXNRMEZCZGtRc1EwRkdLMEk3TzBGQlNTOUNMRlZCUVVrc1kwRkJZeXhQUVVGa0xFTkJRWE5DTEVsQlFYUkNMRVZCUVRSQ0xFMUJRVFZDTEV0QlFYVkRMR05CUVdNc1MwRkJaQ3hEUVVGdlFpeExRVUZ3UWl4RFFVRXdRaXhKUVVFeFFpeEZRVUZuUXl4TlFVRm9ReXhEUVVGMlF5eEZRVUZuUmp0QlFVTnNSaXhsUVVGUExHTkJRV01zUlVGQlpDeERRVUZwUWl4TFFVRnFRaXhEUVVGMVFpeEpRVUYyUWl4RlFVRTJRaXhOUVVFM1FpeERRVUZRTEVOQlJHdEdPMDlCUVhCR08wdEJTa1k3TzBGQlUwRXNWVUZCVFN4SlFVRkpMRlZCUVVvc1EwRkJaU3hKUVVGbUxFTkJRVTRzUTBGV2QwTTdSMEZCYmtNc1EwRkVhVVE3UTBGQmJrUTdPMEZCWlZBc1UwRkJVeXhwUWtGQlZDeERRVUV5UWl4UFFVRXpRaXhGUVVFclF6dEJRVU0zUXl4TlFVRkpMRmxCUVZrc1JVRkJXaXhEUVVSNVF6czdRVUZITjBNc1QwRkJTU3hKUVVGSkxFbEJRVWtzUTBGQlNpeEZRVUZQTEVsQlFVa3NVVUZCVVN4TlFVRlNMRVZCUVdkQ0xFZEJRVzVETEVWQlFYVkRPMEZCUTNKRExGRkJRVWNzVVVGQlVTeERRVUZTTEdGQlFYTkNMRTFCUVUwc1VVRkJUaXhKUVVGclFpeFJRVUZSTEVOQlFWSXNSVUZCVnl4aFFVRllMRWxCUVRSQ0xFOUJRVThzUjBGQlVDeERRVUZYTEhWQ1FVRllMRU5CUVRWQ0xFVkJRV2RGTzBGQlEzcEhMR2RDUVVGVkxFbEJRVllzUTBGQlpTeERRVUZETEVOQlFVUXNSVUZCU1N4UlFVRlJMRU5CUVZJc1JVRkJWeXhoUVVGWUxFTkJRVzVDTEVWQlJIbEhPMHRCUVROSE8wZEJSRVk3TzBGQlRVRXNVMEZCVHl4VFFVRlFMRU5CVkRaRE8wTkJRUzlET3p0QlFWbEJMRk5CUVZNc2IwSkJRVlFzUTBGQk9FSXNTVUZCT1VJc1JVRkJiME1zUzBGQmNFTXNSVUZCTWtNc1UwRkJNME1zUlVGQmNVUTdRVUZEYmtRc1RVRkJSeXhMUVVGTExFMUJRVXdzUzBGQlowSXNTMEZCYUVJc1NVRkJlVUlzVlVGQlZTeE5RVUZXTEV0QlFYRkNMRU5CUVhKQ0xFVkJRWFZDTzBGQlEycEVMRmRCUVU4c1NVRkJVQ3hEUVVScFJEdEhRVUZ1UkRzN1FVRkpRU3hOUVVGSExFdEJRVXNzVFVGQlRDeEhRVUZqTEZWQlFWVXNUVUZCVml4SFFVRnRRaXhMUVVGcVF5eEZRVUYxUXp0QlFVTjRReXhYUVVGUExFbEJRVkFzUTBGRWQwTTdSMEZCTVVNN08wRkJTVUVzVFVGQlNTd3dRa0ZCTUVJc1VVRkJVU3hMUVVGTExFMUJRVXdzUTBGVVlUdEJRVlZ1UkN4TlFVRkpMRzlDUVVGdlFpeFZRVUZWTEUxQlFWWXNSMEZCYlVJc2RVSkJRVzVDTEVOQlZqSkNPenRCUVZsdVJDeE5RVUZKTEdsQ1FVRnBRaXhWUVVGVkxFdEJRVllzUTBGQlowSXNhVUpCUVdoQ0xFTkJRV3BDTEVOQldpdERPenRCUVdOdVJDeFBRVUZKTEVsQlFVa3NRMEZCUXl4TFFVRkVMRVZCUVZFc1MwRkJVaXhEUVVGS0xFbEJRWE5DTEdOQlFURkNMRVZCUVhsRE8wRkJRM1pETEZOQlFVc3NUVUZCVEN4RFFVRlpMRXRCUVZvc1JVRkJiVUlzUTBGQmJrSXNSVUZCYzBJc1MwRkJkRUlzUlVGRWRVTTdRVUZGZGtNc1VVRkJSeXhMUVVGTExFMUJRVXdzUzBGQlowSXNTMEZCYUVJc1JVRkJjMEk3UVVGRGRrSXNXVUZFZFVJN1MwRkJla0k3UjBGR1JqczdRVUZQUVN4VFFVRlBMRWxCUVZBc1EwRnlRbTFFTzBOQlFYSkVPenRCUVhkQ1FTeFBRVUZQTEZOQlFWTXNTMEZCVkN4RFFVRmxMRTlCUVdZc1JVRkJOa0lzU1VGQk4wSXNSVUZCZDBRc1VVRkJSU3hOUVVGTkxFbEJRVTRzUlVGQmQwSTdRVUZEZGtZc1RVRkJTU3hUUVVGVExFVkJRVlFzUTBGRWJVWTdRVUZGZGtZc1RVRkJTU3h0UWtGQmJVSXNWMEZCVnl4UFFVRllMRU5CUVc1Q0xFTkJSbTFHTzBGQlIzWkdMRTFCUVVrc2FVSkJRV2xDTEVsQlFXcENMRVZCUVhWQ0xFMUJRWFpDTEV0QlFXdERMRTFCUVUwc1MwRkJUaXhEUVVGWkxFbEJRVm9zUlVGQmEwSXNUVUZCYkVJc1EwRkJiRU1zUlVGQk5FUTdRVUZET1VRc1YwRkJUeXhOUVVGUUxFTkJSRGhFTzBkQlFXaEZMRTFCUlVzN1FVRkRTQ3hWUVVGTkxFbEJRVWtzVlVGQlNpeERRVUZsTEVsQlFXWXNRMEZCVGl4RFFVUkhPMGRCUmt3N1EwRklTenM3UVVGVlVDeFBRVUZQTEZOQlFWTXNZMEZCVkN4RFFVRjNRaXhQUVVGNFFpeEZRVUZ6UXl4SlFVRjBReXhGUVVGcFJTeFJRVUZGTEUxQlFVMHNTVUZCVGl4RlFVRjVRanRCUVVOcVJ5eE5RVUZITzBGQlEwUXNWMEZCVHl4TlFVRk5MRTlCUVU0c1JVRkJaU3hKUVVGbUxFVkJRWEZDTEV0QlFYSkNMRU5CUVZBc1EwRkVRenRIUVVGSUxFTkJSVU1zVDBGQlRTeERRVUZPTEVWQlFWRTdRVUZEVUN4UlFVRkhMR0ZCUVdFc1ZVRkJZaXhKUVVFeVFpeEZRVUZGTEU5QlFVWXNRMEZCVlN4VlFVRldMRU5CUVhGQ0xHVkJRWEpDTEVOQlFUTkNMRVZCUVdsRk8wRkJRMnhGTEdGQlFVOHNTVUZCVUN4RFFVUnJSVHRMUVVGd1JUczdRVUZKUVN4VlFVRk5MRU5CUVU0c1EwRk1UenRIUVVGU08wTkJTRWs3TzBGQldWQXNUMEZCVHl4VFFVRlRMRlZCUVZRc1EwRkJiMElzVlVGQmNFSXNSVUZCTkVNc1QwRkJOVU1zUlVGQk1FUXNSMEZCTVVRc1JVRkJlVVlzVVVGQlJTeE5RVUZOTEVsQlFVNHNSVUZCZDBJN1FVRkRlRWdzVFVGQlNTeE5RVUZOTEVWQlFVNHNRMEZFYjBnN08wRkJSM2hJTEU5QlFVa3NTVUZCU1N4SlFVRktMRWxCUVZrc1ZVRkJhRUlzUlVGQk1rSTdRVUZEZWtJc1VVRkJSenRCUVVORUxGVkJRVWtzVTBGQlV5eEpRVUZKTEV0QlFVb3NRMEZCVlN4SlFVRldMRVZCUVdkQ0xFMUJRVTBzVDBGQlRpeEZRVUZsTEVsQlFXWXNSVUZCY1VJc1MwRkJja0lzUTBGQmFFSXNRMEZCVkN4RFFVUklPMEZCUlVRc1dVRkJUU3hKUVVGSkxFMUJRVW9zUTBGQlZ5eE5RVUZZTEVOQlFVNHNRMEZHUXp0TFFVRklMRU5CUjBNc1QwRkJUU3hEUVVGT0xFVkJRVkU3UVVGRFZDeFZRVUZITEVWQlFVVXNZVUZCWVN4VlFVRmlMRU5CUVVZc1JVRkJNa0k3UVVGRE1VSXNZMEZCVFN4RFFVRk9MRU5CUkRCQ08wOUJRVGxDTzB0QlJFTTdSMEZLU0RzN1FVRlhRU3hUUVVGUExFZEJRVkFzUTBGa2QwZzdRMEZCYmtnaUxDSm1hV3hsSWpvaWJHbGlMMk52Y21VdmNHRjBkR1Z5Ym5NdlpHVm1iV0YwWTJndWFuTWlMQ0p6YjNWeVkyVnpRMjl1ZEdWdWRDSTZXeUl2S2lCQVpteHZkeUFxTDF4dVhHNXBiWEJ2Y25RZ2V5QmlkV2xzWkUxaGRHTm9JSDBnWm5KdmJTQmNJaTR2YldGMFkyaGNJanRjYm1sdGNHOXlkQ0FxSUdGeklGUjVjR1Z6SUdaeWIyMGdYQ0l1TDNSNWNHVnpYQ0k3WEc1Y2JtVjRjRzl5ZENCamJHRnpjeUJOWVhSamFFVnljbTl5SUdWNGRHVnVaSE1nUlhKeWIzSWdlMXh1SUNCamIyNXpkSEoxWTNSdmNpaGhjbWM2SUdGdWVTa2dlMXh1SUNBZ0lITjFjR1Z5S0NrN1hHNWNiaUFnSUNCcFppaDBlWEJsYjJZZ1lYSm5JRDA5UFNBbmMzbHRZbTlzSnlsN1hHNGdJQ0FnSUNCMGFHbHpMbTFsYzNOaFoyVWdQU0FuVG04Z2JXRjBZMmdnWm05eU9pQW5JQ3NnWVhKbkxuUnZVM1J5YVc1bktDazdYRzRnSUNBZ2ZTQmxiSE5sSUdsbUtFRnljbUY1TG1selFYSnlZWGtvWVhKbktTbDdYRzRnSUNBZ0lDQnNaWFFnYldGd2NHVmtWbUZzZFdWeklEMGdZWEpuTG0xaGNDZ29lQ2tnUFQ0Z2VDNTBiMU4wY21sdVp5Z3BLVHRjYmlBZ0lDQWdJSFJvYVhNdWJXVnpjMkZuWlNBOUlDZE9ieUJ0WVhSamFDQm1iM0k2SUNjZ0t5QnRZWEJ3WldSV1lXeDFaWE03WEc0Z0lDQWdmV1ZzYzJWN1hHNGdJQ0FnSUNCMGFHbHpMbTFsYzNOaFoyVWdQU0FuVG04Z2JXRjBZMmdnWm05eU9pQW5JQ3NnWVhKbk8xeHVJQ0FnSUgxY2JseHVJQ0FnSUhSb2FYTXVjM1JoWTJzZ1BTQW9ibVYzSUVWeWNtOXlLQ2twTG5OMFlXTnJPMXh1SUNBZ0lIUm9hWE11Ym1GdFpTQTlJSFJvYVhNdVkyOXVjM1J5ZFdOMGIzSXVibUZ0WlR0Y2JpQWdmVnh1ZlZ4dVhHNWNibVY0Y0c5eWRDQmpiR0Z6Y3lCRFlYTmxJSHRjYmlBZ2NHRjBkR1Z5YmpvZ1JuVnVZM1JwYjI0N1hHNGdJR1p1T2lCR2RXNWpkR2x2Ymp0Y2JpQWdaM1ZoY21RNklFWjFibU4wYVc5dU8xeHVJQ0JoY21sMGVUb2diblZ0WW1WeU8xeHVJQ0J2Y0hScGIyNWhiSE02SUVGeWNtRjVQR0Z1ZVQ0N1hHNWNiaUFnWTI5dWMzUnlkV04wYjNJb2NHRjBkR1Z5YmpvZ1FYSnlZWGs4WVc1NVBpd2dabTQ2SUVaMWJtTjBhVzl1TENCbmRXRnlaRG9nUm5WdVkzUnBiMjRnUFNBb0tTQTlQaUIwY25WbEtYdGNiaUFnSUNCMGFHbHpMbkJoZEhSbGNtNGdQU0JpZFdsc1pFMWhkR05vS0hCaGRIUmxjbTRwTzF4dUlDQWdJSFJvYVhNdVlYSnBkSGtnUFNCd1lYUjBaWEp1TG14bGJtZDBhRHRjYmlBZ0lDQjBhR2x6TG05d2RHbHZibUZzY3lBOUlHZGxkRTl3ZEdsdmJtRnNWbUZzZFdWektIQmhkSFJsY200cE8xeHVJQ0FnSUhSb2FYTXVabTRnUFNCbWJqdGNiaUFnSUNCMGFHbHpMbWQxWVhKa0lEMGdaM1ZoY21RN1hHNGdJSDFjYm4xY2JseHVaWGh3YjNKMElHWjFibU4wYVc5dUlHMWhhMlZmWTJGelpTaHdZWFIwWlhKdU9pQkJjbkpoZVR4aGJuaytMQ0JtYmpvZ1JuVnVZM1JwYjI0c0lHZDFZWEprT2lCR2RXNWpkR2x2YmlBOUlDZ3BJRDArSUhSeWRXVXBPaUJEWVhObElIdGNiaUFnY21WMGRYSnVJRzVsZHlCRFlYTmxLSEJoZEhSbGNtNHNJR1p1TENCbmRXRnlaQ2s3WEc1OVhHNWNibVY0Y0c5eWRDQm1kVzVqZEdsdmJpQmtaV1p0WVhSamFDZ3VMaTVqWVhObGN6b2dRWEp5WVhrOFEyRnpaVDRwT2lCR2RXNWpkR2x2YmlCN1hHNGdJSEpsZEhWeWJpQm1kVzVqZEdsdmJpZ3VMaTVoY21kek9pQkJjbkpoZVR4aGJuaytLVG9nWVc1NUlIdGNiaUFnSUNCbWIzSWdLR3hsZENCd2NtOWpaWE56WldSRFlYTmxJRzltSUdOaGMyVnpLU0I3WEc0Z0lDQWdJQ0JzWlhRZ2NtVnpkV3gwSUQwZ1cxMDdYRzRnSUNBZ0lDQmhjbWR6SUQwZ1ptbHNiRWx1VDNCMGFXOXVZV3hXWVd4MVpYTW9ZWEpuY3l3Z2NISnZZMlZ6YzJWa1EyRnpaUzVoY21sMGVTd2djSEp2WTJWemMyVmtRMkZ6WlM1dmNIUnBiMjVoYkhNcE8xeHVYRzRnSUNBZ0lDQnBaaUFvY0hKdlkyVnpjMlZrUTJGelpTNXdZWFIwWlhKdUtHRnlaM01zSUhKbGMzVnNkQ2tnSmlZZ2NISnZZMlZ6YzJWa1EyRnpaUzVuZFdGeVpDNWhjSEJzZVNoMGFHbHpMQ0J5WlhOMWJIUXBLU0I3WEc0Z0lDQWdJQ0FnSUhKbGRIVnliaUJ3Y205alpYTnpaV1JEWVhObExtWnVMbUZ3Y0d4NUtIUm9hWE1zSUhKbGMzVnNkQ2s3WEc0Z0lDQWdJQ0I5WEc0Z0lDQWdmVnh1WEc0Z0lDQWdkR2h5YjNjZ2JtVjNJRTFoZEdOb1JYSnliM0lvWVhKbmN5azdYRzRnSUgwN1hHNTlYRzVjYm1aMWJtTjBhVzl1SUdkbGRFOXdkR2x2Ym1Gc1ZtRnNkV1Z6S0hCaGRIUmxjbTQ2SUVGeWNtRjVQR0Z1ZVQ0cGUxeHVJQ0JzWlhRZ2IzQjBhVzl1WVd4eklEMGdXMTA3WEc1Y2JpQWdabTl5S0d4bGRDQnBJRDBnTURzZ2FTQThJSEJoZEhSbGNtNHViR1Z1WjNSb095QnBLeXNwZTF4dUlDQWdJR2xtS0hCaGRIUmxjbTViYVYwZ2FXNXpkR0Z1WTJWdlppQlVlWEJsY3k1V1lYSnBZV0pzWlNBbUppQndZWFIwWlhKdVcybGRMbVJsWm1GMWJIUmZkbUZzZFdVZ0lUMGdVM2x0WW05c0xtWnZjaWhjSW1Wc2FYaHBjbk5qY21sd2RDNXViMTkyWVd4MVpWd2lLU2w3WEc0Z0lDQWdJQ0J2Y0hScGIyNWhiSE11Y0hWemFDaGJhU3dnY0dGMGRHVnlibHRwWFM1a1pXWmhkV3gwWDNaaGJIVmxYU2s3WEc0Z0lDQWdmVnh1SUNCOVhHNWNiaUFnY21WMGRYSnVJRzl3ZEdsdmJtRnNjenRjYm4xY2JseHVablZ1WTNScGIyNGdabWxzYkVsdVQzQjBhVzl1WVd4V1lXeDFaWE1vWVhKbmN5d2dZWEpwZEhrc0lHOXdkR2x2Ym1Gc2N5bDdYRzRnSUdsbUtHRnlaM011YkdWdVozUm9JRDA5UFNCaGNtbDBlU0I4ZkNCdmNIUnBiMjVoYkhNdWJHVnVaM1JvSUQwOVBTQXdLWHRjYmlBZ0lDQnlaWFIxY200Z1lYSm5jenRjYmlBZ2ZWeHVYRzRnSUdsbUtHRnlaM011YkdWdVozUm9JQ3NnYjNCMGFXOXVZV3h6TG14bGJtZDBhQ0E4SUdGeWFYUjVLWHRjYmlBZ0lDQnlaWFIxY200Z1lYSm5jenRjYmlBZ2ZWeHVYRzRnSUd4bGRDQnVkVzFpWlhKUFprOXdkR2x2Ym1Gc2MxUnZSbWxzYkNBOUlHRnlhWFI1SUMwZ1lYSm5jeTVzWlc1bmRHZzdYRzRnSUd4bGRDQnZjSFJwYjI1aGJITlViMUpsYlc5MlpTQTlJRzl3ZEdsdmJtRnNjeTVzWlc1bmRHZ2dMU0J1ZFcxaVpYSlBaazl3ZEdsdmJtRnNjMVJ2Um1sc2JEdGNibHh1SUNCc1pYUWdiM0IwYVc5dVlXeHpWRzlWYzJVZ1BTQnZjSFJwYjI1aGJITXVjMnhwWTJVb2IzQjBhVzl1WVd4elZHOVNaVzF2ZG1VcE8xeHVYRzRnSUdadmNpaHNaWFFnVzJsdVpHVjRMQ0IyWVd4MVpWMGdiMllnYjNCMGFXOXVZV3h6Vkc5VmMyVXBlMXh1SUNBZ0lHRnlaM011YzNCc2FXTmxLR2x1WkdWNExDQXdMQ0IyWVd4MVpTazdYRzRnSUNBZ2FXWW9ZWEpuY3k1c1pXNW5kR2dnUFQwOUlHRnlhWFI1S1h0Y2JpQWdJQ0FnSUdKeVpXRnJPMXh1SUNBZ0lIMWNiaUFnZlZ4dVhHNGdJSEpsZEhWeWJpQmhjbWR6TzF4dWZWeHVYRzVsZUhCdmNuUWdablZ1WTNScGIyNGdiV0YwWTJnb2NHRjBkR1Z5YmpvZ1lXNTVMQ0JsZUhCeU9pQmhibmtzSUdkMVlYSmtPaUJHZFc1amRHbHZiaUE5SUNncElEMCtJSFJ5ZFdVcE9pQkJjbkpoZVR4aGJuaytJSHRjYmlBZ2JHVjBJSEpsYzNWc2RDQTlJRnRkTzF4dUlDQnNaWFFnY0hKdlkyVnpjMlZrVUdGMGRHVnliaUE5SUdKMWFXeGtUV0YwWTJnb2NHRjBkR1Z5YmlrN1hHNGdJR2xtSUNod2NtOWpaWE56WldSUVlYUjBaWEp1S0dWNGNISXNJSEpsYzNWc2RDa2dKaVlnWjNWaGNtUXVZWEJ3Ykhrb2RHaHBjeXdnY21WemRXeDBLU2w3WEc0Z0lDQWdjbVYwZFhKdUlISmxjM1ZzZER0Y2JpQWdmV1ZzYzJWN1hHNGdJQ0FnZEdoeWIzY2dibVYzSUUxaGRHTm9SWEp5YjNJb1pYaHdjaWs3WEc0Z0lIMWNibjFjYmx4dVpYaHdiM0owSUdaMWJtTjBhVzl1SUcxaGRHTm9YMjV2WDNSb2NtOTNLSEJoZEhSbGNtNDZJR0Z1ZVN3Z1pYaHdjam9nWVc1NUxDQm5kV0Z5WkRvZ1JuVnVZM1JwYjI0Z1BTQW9LU0E5UGlCMGNuVmxLVG9nUDBGeWNtRjVQR0Z1ZVQ0Z2UxeHVJQ0IwY25sN1hHNGdJQ0FnY21WMGRYSnVJRzFoZEdOb0tIQmhkSFJsY200c0lHVjRjSElzSUdkMVlYSmtLVHRjYmlBZ2ZXTmhkR05vS0dVcGUxeHVJQ0FnSUdsbUtHVWdhVzV6ZEdGdVkyVnZaaUJOWVhSamFFVnljbTl5SUh4OElHVXViV1Z6YzJGblpTNXpkR0Z5ZEhOWGFYUm9LQ2RPYnlCdFlYUmphQ0JtYjNJNkp5a3BlMXh1SUNBZ0lDQWdjbVYwZFhKdUlHNTFiR3c3WEc0Z0lDQWdmVnh1WEc0Z0lDQWdkR2h5YjNjZ1pUdGNiaUFnZlZ4dWZWeHVYRzVsZUhCdmNuUWdablZ1WTNScGIyNGdjR0YwZEdWeWJrMWhjQ2hqYjJ4c1pXTjBhVzl1T2lCQmNuSmhlVHhoYm5rK0xDQndZWFIwWlhKdU9pQmhibmtzSUdaMWJqb2dSblZ1WTNScGIyNHNJR2QxWVhKa09pQkdkVzVqZEdsdmJpQTlJQ2dwSUQwK0lIUnlkV1VwT2lCQmNuSmhlVHhoYm5rK0lIdGNiaUFnYkdWMElISmxkQ0E5SUZ0ZE8xeHVYRzRnSUdadmNpaHNaWFFnWld4bGJTQnZaaUJqYjJ4c1pXTjBhVzl1S1h0Y2JpQWdJQ0IwY25sN1hHNGdJQ0FnSUNCc1pYUWdjbVZ6ZFd4MElEMGdablZ1TG1Gd2NHeDVLSFJvYVhNc0lHMWhkR05vS0hCaGRIUmxjbTRzSUdWc1pXMHNJR2QxWVhKa0tTazdYRzRnSUNBZ0lDQnlaWFFnUFNCeVpYUXVZMjl1WTJGMEtISmxjM1ZzZENrN1hHNGdJQ0FnZldOaGRHTm9LR1VwZTF4dUlDQWdJR2xtS0NFb1pTQnBibk4wWVc1alpXOW1JRTFoZEdOb1JYSnliM0lwS1h0Y2JpQWdJQ0FnSUNBZ2RHaHliM2NnWlR0Y2JpQWdJQ0FnSUgxY2JpQWdJQ0I5WEc0Z0lIMWNibHh1SUNCeVpYUjFjbTRnY21WME8xeHVmVnh1SWwwc0luTnZkWEpqWlZKdmIzUWlPaUl2YzI5MWNtTmxMeUo5XG4iLCJcblxuaW1wb3J0IHsgZGVmbWF0Y2gsIG1hdGNoLCBNYXRjaEVycm9yLCBtYXRjaF9ub190aHJvdywgcGF0dGVybk1hcCwgQ2FzZSwgbWFrZV9jYXNlIH0gZnJvbSBcIi4vcGF0dGVybnMvZGVmbWF0Y2hcIjtcbmltcG9ydCB7IHZhcmlhYmxlLCB3aWxkY2FyZCwgc3RhcnRzV2l0aCwgY2FwdHVyZSwgaGVhZFRhaWwsIHR5cGUsIGJvdW5kLCBiaXRTdHJpbmdNYXRjaCB9IGZyb20gXCIuL3BhdHRlcm5zL3R5cGVzXCI7XG5cbmV4cG9ydCBkZWZhdWx0IHtcbiAgZGVmbWF0Y2gsIG1hdGNoLCBNYXRjaEVycm9yLCBtYXRjaF9ub190aHJvdyxcbiAgdmFyaWFibGUsIHdpbGRjYXJkLCBzdGFydHNXaXRoLFxuICBjYXB0dXJlLCBoZWFkVGFpbCwgdHlwZSwgYm91bmQsIENhc2UsIG1ha2VfY2FzZSwgYml0U3RyaW5nTWF0Y2hcbn07XG4vLyMgc291cmNlTWFwcGluZ1VSTD1kYXRhOmFwcGxpY2F0aW9uL2pzb247YmFzZTY0LGV5SjJaWEp6YVc5dUlqb3pMQ0p6YjNWeVkyVnpJanBiSW14cFlpOWpiM0psTDNCaGRIUmxjbTV6TG1weklsMHNJbTVoYldWeklqcGJYU3dpYldGd2NHbHVaM01pT2lJN08wRkJSVUVzVTBGQlV5eFJRVUZVTEVWQlFXMUNMRXRCUVc1Q0xFVkJRVEJDTEZWQlFURkNMRVZCUVhORExHTkJRWFJETEVWQlFYTkVMRlZCUVhSRUxFVkJRV3RGTEVsQlFXeEZMRVZCUVhkRkxGTkJRWGhGTEZGQlFYbEdMSEZDUVVGNlJqdEJRVU5CTEZOQlFWTXNVVUZCVkN4RlFVRnRRaXhSUVVGdVFpeEZRVUUyUWl4VlFVRTNRaXhGUVVGNVF5eFBRVUY2UXl4RlFVRnJSQ3hSUVVGc1JDeEZRVUUwUkN4SlFVRTFSQ3hGUVVGclJTeExRVUZzUlN4RlFVRjVSU3hqUVVGNlJTeFJRVUVyUml4clFrRkJMMFk3TzBGQlIwRXNaVUZCWlR0QlFVTmlMRlZCUkdFc1JVRkRTQ3hMUVVSSExFVkJRMGtzVlVGRVNpeEZRVU5uUWl4alFVUm9RanRCUVVWaUxGVkJSbUVzUlVGRlNDeFJRVVpITEVWQlJVOHNWVUZHVUR0QlFVZGlMRk5CU0dFc1JVRkhTaXhSUVVoSkxFVkJSMDBzU1VGSVRpeEZRVWRaTEV0QlNGb3NSVUZIYlVJc1NVRklia0lzUlVGSGVVSXNVMEZJZWtJc1JVRkhiME1zWTBGSWNFTTdRMEZCWmlJc0ltWnBiR1VpT2lKc2FXSXZZMjl5WlM5d1lYUjBaWEp1Y3k1cWN5SXNJbk52ZFhKalpYTkRiMjUwWlc1MElqcGJJaThxSUVCbWJHOTNJQ292WEc1Y2JtbHRjRzl5ZENCN0lHUmxabTFoZEdOb0xDQnRZWFJqYUN3Z1RXRjBZMmhGY25KdmNpd2diV0YwWTJoZmJtOWZkR2h5YjNjc0lIQmhkSFJsY201TllYQXNJRU5oYzJVc0lHMWhhMlZmWTJGelpTQjlJR1p5YjIwZ1hDSXVMM0JoZEhSbGNtNXpMMlJsWm0xaGRHTm9YQ0k3WEc1cGJYQnZjblFnZXlCMllYSnBZV0pzWlN3Z2QybHNaR05oY21Rc0lITjBZWEowYzFkcGRHZ3NJR05oY0hSMWNtVXNJR2hsWVdSVVlXbHNMQ0IwZVhCbExDQmliM1Z1WkN3Z1ltbDBVM1J5YVc1blRXRjBZMmdnZlNCbWNtOXRJRndpTGk5d1lYUjBaWEp1Y3k5MGVYQmxjMXdpTzF4dVhHNWNibVY0Y0c5eWRDQmtaV1poZFd4MElIdGNiaUFnWkdWbWJXRjBZMmdzSUcxaGRHTm9MQ0JOWVhSamFFVnljbTl5TENCdFlYUmphRjl1YjE5MGFISnZkeXhjYmlBZ2RtRnlhV0ZpYkdVc0lIZHBiR1JqWVhKa0xDQnpkR0Z5ZEhOWGFYUm9MRnh1SUNCallYQjBkWEpsTENCb1pXRmtWR0ZwYkN3Z2RIbHdaU3dnWW05MWJtUXNJRU5oYzJVc0lHMWhhMlZmWTJGelpTd2dZbWwwVTNSeWFXNW5UV0YwWTJoY2JuMDdYRzRpWFN3aWMyOTFjbU5sVW05dmRDSTZJaTl6YjNWeVkyVXZJbjA9XG4iLCJpbXBvcnQgeyBJbnRlZ2VyLCBGbG9hdCB9IGZyb20gJy4vcHJpbWl0aXZlcyc7XG5cbi8vaHR0cHM6Ly9naXRodWIuY29tL2FpcnBvcnR5aC9wcm90b21vcnBoaXNtXG5jbGFzcyBQcm90b2NvbCB7XG4gIGNvbnN0cnVjdG9yKHNwZWMpIHtcbiAgICB0aGlzLnJlZ2lzdHJ5ID0gbmV3IE1hcCgpO1xuICAgIHRoaXMuZmFsbGJhY2sgPSBudWxsO1xuXG4gICAgZm9yIChsZXQgZnVuTmFtZSBpbiBzcGVjKSB7XG4gICAgICB0aGlzW2Z1bk5hbWVdID0gY3JlYXRlRnVuKGZ1bk5hbWUpLmJpbmQodGhpcyk7XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gY3JlYXRlRnVuKGZ1bk5hbWUpIHtcblxuICAgICAgcmV0dXJuIGZ1bmN0aW9uICguLi5hcmdzKSB7XG4gICAgICAgIGxldCB0aGluZyA9IGFyZ3NbMF07XG4gICAgICAgIGxldCBmdW4gPSBudWxsO1xuXG4gICAgICAgIGlmIChOdW1iZXIuaXNJbnRlZ2VyKHRoaW5nKSAmJiB0aGlzLmhhc0ltcGxlbWVudGF0aW9uKEludGVnZXIpKSB7XG4gICAgICAgICAgZnVuID0gdGhpcy5yZWdpc3RyeS5nZXQoSW50ZWdlcilbZnVuTmFtZV07XG4gICAgICAgIH0gZWxzZSBpZiAodHlwZW9mIHRoaW5nID09PSBcIm51bWJlclwiICYmICFOdW1iZXIuaXNJbnRlZ2VyKHRoaW5nKSAmJiB0aGlzLmhhc0ltcGxlbWVudGF0aW9uKEZsb2F0KSkge1xuICAgICAgICAgIGZ1biA9IHRoaXMucmVnaXN0cnkuZ2V0KEZsb2F0KVtmdW5OYW1lXTtcbiAgICAgICAgfSBlbHNlIGlmICh0aGlzLmhhc0ltcGxlbWVudGF0aW9uKHRoaW5nKSkge1xuICAgICAgICAgIGZ1biA9IHRoaXMucmVnaXN0cnkuZ2V0KHRoaW5nLmNvbnN0cnVjdG9yKVtmdW5OYW1lXTtcbiAgICAgICAgfSBlbHNlIGlmICh0aGlzLmZhbGxiYWNrKSB7XG4gICAgICAgICAgZnVuID0gdGhpcy5mYWxsYmFja1tmdW5OYW1lXTtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmIChmdW4gIT0gbnVsbCkge1xuICAgICAgICAgIGxldCByZXR2YWwgPSBmdW4uYXBwbHkodGhpcywgYXJncyk7XG4gICAgICAgICAgcmV0dXJuIHJldHZhbDtcbiAgICAgICAgfVxuXG4gICAgICAgIHRocm93IG5ldyBFcnJvcihcIk5vIGltcGxlbWVudGF0aW9uIGZvdW5kIGZvciBcIiArIHRoaW5nKTtcbiAgICAgIH07XG4gICAgfVxuICB9XG5cbiAgaW1wbGVtZW50YXRpb24odHlwZSwgaW1wbGVtZW50YXRpb24pIHtcbiAgICBpZiAodHlwZSA9PT0gbnVsbCkge1xuICAgICAgdGhpcy5mYWxsYmFjayA9IGltcGxlbWVudGF0aW9uO1xuICAgIH0gZWxzZSB7XG4gICAgICB0aGlzLnJlZ2lzdHJ5LnNldCh0eXBlLCBpbXBsZW1lbnRhdGlvbik7XG4gICAgfVxuICB9XG5cbiAgaGFzSW1wbGVtZW50YXRpb24odGhpbmcpIHtcbiAgICBpZiAodGhpbmcgPT09IEludGVnZXIgfHwgdGhpbmcgPT09IEZsb2F0KSB7XG4gICAgICByZXR1cm4gdGhpcy5yZWdpc3RyeS5oYXModGhpbmcpO1xuICAgIH1cblxuICAgIHJldHVybiB0aGlzLnJlZ2lzdHJ5Lmhhcyh0aGluZy5jb25zdHJ1Y3Rvcik7XG4gIH1cbn1cblxuZXhwb3J0IGRlZmF1bHQgUHJvdG9jb2w7XG4vLyMgc291cmNlTWFwcGluZ1VSTD1kYXRhOmFwcGxpY2F0aW9uL2pzb247YmFzZTY0LGV5SjJaWEp6YVc5dUlqb3pMQ0p6YjNWeVkyVnpJanBiSW14cFlpOWpiM0psTDNCeWIzUnZZMjlzTG1weklsMHNJbTVoYldWeklqcGJYU3dpYldGd2NHbHVaM01pT2lKQlFVRkJMRk5CUVZNc1QwRkJWQ3hGUVVGclFpeExRVUZzUWl4UlFVRXJRaXhqUVVFdlFqczdPMEZCUjBFc1RVRkJUU3hSUVVGT0xFTkJRV003UVVGRFdpeGpRVUZaTEVsQlFWb3NSVUZCYVVJN1FVRkRaaXhUUVVGTExGRkJRVXdzUjBGQlowSXNTVUZCU1N4SFFVRktMRVZCUVdoQ0xFTkJSR1U3UVVGRlppeFRRVUZMTEZGQlFVd3NSMEZCWjBJc1NVRkJhRUlzUTBGR1pUczdRVUZKWml4VFFVRkxMRWxCUVVrc1QwRkJTaXhKUVVGbExFbEJRWEJDTEVWQlFYbENPMEZCUTNaQ0xGZEJRVXNzVDBGQlRDeEpRVUZuUWl4VlFVRlZMRTlCUVZZc1JVRkJiVUlzU1VGQmJrSXNRMEZCZDBJc1NVRkJlRUlzUTBGQmFFSXNRMEZFZFVJN1MwRkJla0k3TzBGQlNVRXNZVUZCVXl4VFFVRlVMRU5CUVcxQ0xFOUJRVzVDTEVWQlFUSkNPenRCUVVWNlFpeGhRVUZQTEZWQlFWTXNSMEZCUnl4SlFVRklMRVZCUVZNN1FVRkRka0lzV1VGQlNTeFJRVUZSTEV0QlFVc3NRMEZCVEN4RFFVRlNMRU5CUkcxQ08wRkJSWFpDTEZsQlFVa3NUVUZCVFN4SlFVRk9MRU5CUm0xQ096dEJRVWwyUWl4WlFVRkhMRTlCUVU4c1UwRkJVQ3hEUVVGcFFpeExRVUZxUWl4TFFVRXlRaXhMUVVGTExHbENRVUZNTEVOQlFYVkNMRTlCUVhaQ0xFTkJRVE5DTEVWQlFUSkVPMEZCUXpWRUxHZENRVUZOTEV0QlFVc3NVVUZCVEN4RFFVRmpMRWRCUVdRc1EwRkJhMElzVDBGQmJFSXNSVUZCTWtJc1QwRkJNMElzUTBGQlRpeERRVVEwUkR0VFFVRTVSQ3hOUVVWTkxFbEJRVWNzVDBGQlR5eExRVUZRTEV0QlFXbENMRkZCUVdwQ0xFbEJRVFpDTEVOQlFVTXNUMEZCVHl4VFFVRlFMRU5CUVdsQ0xFdEJRV3BDTEVOQlFVUXNTVUZCTkVJc1MwRkJTeXhwUWtGQlRDeERRVUYxUWl4TFFVRjJRaXhEUVVGNlJDeEZRVUYxUmp0QlFVTTVSaXhuUWtGQlRTeExRVUZMTEZGQlFVd3NRMEZCWXl4SFFVRmtMRU5CUVd0Q0xFdEJRV3hDTEVWQlFYbENMRTlCUVhwQ0xFTkJRVTRzUTBGRU9FWTdVMEZCTVVZc1RVRkZRU3hKUVVGSExFdEJRVXNzYVVKQlFVd3NRMEZCZFVJc1MwRkJka0lzUTBGQlNDeEZRVUZwUXp0QlFVTnlReXhuUWtGQlRTeExRVUZMTEZGQlFVd3NRMEZCWXl4SFFVRmtMRU5CUVd0Q0xFMUJRVTBzVjBGQlRpeERRVUZzUWl4RFFVRnhReXhQUVVGeVF5eERRVUZPTEVOQlJIRkRPMU5CUVdwRExFMUJSVUVzU1VGQlJ5eExRVUZMTEZGQlFVd3NSVUZCWXp0QlFVTnlRaXhuUWtGQlRTeExRVUZMTEZGQlFVd3NRMEZCWXl4UFFVRmtMRU5CUVU0c1EwRkVjVUk3VTBGQmFrSTdPMEZCU1U0c1dVRkJSeXhQUVVGUExFbEJRVkFzUlVGQldUdEJRVU5pTEdOQlFVa3NVMEZCVXl4SlFVRkpMRXRCUVVvc1EwRkJWU3hKUVVGV0xFVkJRV2RDTEVsQlFXaENMRU5CUVZRc1EwRkVVenRCUVVWaUxHbENRVUZQTEUxQlFWQXNRMEZHWVR0VFFVRm1PenRCUVV0QkxHTkJRVTBzU1VGQlNTeExRVUZLTEVOQlFWVXNhVU5CUVdsRExFdEJRV3BETEVOQlFXaENMRU5CYmtKMVFqdFBRVUZzUWl4RFFVWnJRanRMUVVFelFqdEhRVkpHT3p0QlFXdERRU3hwUWtGQlpTeEpRVUZtTEVWQlFYRkNMR05CUVhKQ0xFVkJRVzlETzBGQlEyeERMRkZCUVVjc1UwRkJVeXhKUVVGVUxFVkJRV003UVVGRFppeFhRVUZMTEZGQlFVd3NSMEZCWjBJc1kwRkJhRUlzUTBGRVpUdExRVUZxUWl4TlFVVkxPMEZCUTBnc1YwRkJTeXhSUVVGTUxFTkJRV01zUjBGQlpDeERRVUZyUWl4SlFVRnNRaXhGUVVGM1FpeGpRVUY0UWl4RlFVUkhPMHRCUmt3N1IwRkVSanM3UVVGUlFTeHZRa0ZCYTBJc1MwRkJiRUlzUlVGQmVVSTdRVUZEZGtJc1VVRkJTU3hWUVVGVkxFOUJRVllzU1VGQmNVSXNWVUZCVlN4TFFVRldMRVZCUVdkQ08wRkJRM1pETEdGQlFVOHNTMEZCU3l4UlFVRk1MRU5CUVdNc1IwRkJaQ3hEUVVGclFpeExRVUZzUWl4RFFVRlFMRU5CUkhWRE8wdEJRWHBET3p0QlFVbEJMRmRCUVU4c1MwRkJTeXhSUVVGTUxFTkJRV01zUjBGQlpDeERRVUZyUWl4TlFVRk5MRmRCUVU0c1EwRkJla0lzUTBGTWRVSTdSMEZCZWtJN1EwRXpRMFk3TzBGQmNVUkJMR1ZCUVdVc1VVRkJaaUlzSW1acGJHVWlPaUpzYVdJdlkyOXlaUzl3Y205MGIyTnZiQzVxY3lJc0luTnZkWEpqWlhORGIyNTBaVzUwSWpwYkltbHRjRzl5ZENCN0lFbHVkR1ZuWlhJc0lFWnNiMkYwSUgwZ1puSnZiU0FuTGk5d2NtbHRhWFJwZG1Wekp6dGNibHh1THk5b2RIUndjem92TDJkcGRHaDFZaTVqYjIwdllXbHljRzl5ZEhsb0wzQnliM1J2Ylc5eWNHaHBjMjFjYm1Oc1lYTnpJRkJ5YjNSdlkyOXNlMXh1SUNCamIyNXpkSEoxWTNSdmNpaHpjR1ZqS1h0Y2JpQWdJQ0IwYUdsekxuSmxaMmx6ZEhKNUlEMGdibVYzSUUxaGNDZ3BPMXh1SUNBZ0lIUm9hWE11Wm1Gc2JHSmhZMnNnUFNCdWRXeHNPMXh1WEc0Z0lDQWdabTl5SUNoc1pYUWdablZ1VG1GdFpTQnBiaUJ6Y0dWaktYdGNiaUFnSUNBZ0lIUm9hWE5iWm5WdVRtRnRaVjBnUFNCamNtVmhkR1ZHZFc0b1puVnVUbUZ0WlNrdVltbHVaQ2gwYUdsektUdGNiaUFnSUNCOVhHNWNiaUFnSUNCbWRXNWpkR2x2YmlCamNtVmhkR1ZHZFc0b1puVnVUbUZ0WlNsN1hHNWNiaUFnSUNBZ0lISmxkSFZ5YmlCbWRXNWpkR2x2YmlndUxpNWhjbWR6S1NCN1hHNGdJQ0FnSUNBZ0lHeGxkQ0IwYUdsdVp5QTlJR0Z5WjNOYk1GMDdYRzRnSUNBZ0lDQWdJR3hsZENCbWRXNGdQU0J1ZFd4c08xeHVYRzRnSUNBZ0lDQWdJR2xtS0U1MWJXSmxjaTVwYzBsdWRHVm5aWElvZEdocGJtY3BJQ1ltSUhSb2FYTXVhR0Z6U1cxd2JHVnRaVzUwWVhScGIyNG9TVzUwWldkbGNpa3BlMXh1SUNBZ0lDQWdJQ0FnSUdaMWJpQTlJSFJvYVhNdWNtVm5hWE4wY25rdVoyVjBLRWx1ZEdWblpYSXBXMloxYms1aGJXVmRPMXh1SUNBZ0lDQWdJQ0I5Wld4elpTQnBaaWgwZVhCbGIyWWdkR2hwYm1jZ1BUMDlJRndpYm5WdFltVnlYQ0lnSmlZZ0lVNTFiV0psY2k1cGMwbHVkR1ZuWlhJb2RHaHBibWNwSUNZbUlIUm9hWE11YUdGelNXMXdiR1Z0Wlc1MFlYUnBiMjRvUm14dllYUXBLWHRjYmlBZ0lDQWdJQ0FnSUNCbWRXNGdQU0IwYUdsekxuSmxaMmx6ZEhKNUxtZGxkQ2hHYkc5aGRDbGJablZ1VG1GdFpWMDdYRzRnSUNBZ0lDQWdJSDFsYkhObElHbG1LSFJvYVhNdWFHRnpTVzF3YkdWdFpXNTBZWFJwYjI0b2RHaHBibWNwS1h0Y2JpQWdJQ0FnSUNBZ0lDQm1kVzRnUFNCMGFHbHpMbkpsWjJsemRISjVMbWRsZENoMGFHbHVaeTVqYjI1emRISjFZM1J2Y2lsYlpuVnVUbUZ0WlYwN1hHNGdJQ0FnSUNBZ0lIMWxiSE5sSUdsbUtIUm9hWE11Wm1Gc2JHSmhZMnNwZTF4dUlDQWdJQ0FnSUNBZ0lHWjFiaUE5SUhSb2FYTXVabUZzYkdKaFkydGJablZ1VG1GdFpWMDdYRzRnSUNBZ0lDQWdJSDFjYmx4dUlDQWdJQ0FnSUNCcFppaG1kVzRnSVQwZ2JuVnNiQ2w3WEc0Z0lDQWdJQ0FnSUNBZ2JHVjBJSEpsZEhaaGJDQTlJR1oxYmk1aGNIQnNlU2gwYUdsekxDQmhjbWR6S1R0Y2JpQWdJQ0FnSUNBZ0lDQnlaWFIxY200Z2NtVjBkbUZzTzF4dUlDQWdJQ0FnSUNCOVhHNWNiaUFnSUNBZ0lDQWdkR2h5YjNjZ2JtVjNJRVZ5Y205eUtGd2lUbThnYVcxd2JHVnRaVzUwWVhScGIyNGdabTkxYm1RZ1ptOXlJRndpSUNzZ2RHaHBibWNwTzF4dUlDQWdJQ0FnZlZ4dUlDQWdJSDFjYmlBZ2ZWeHVYRzRnSUdsdGNHeGxiV1Z1ZEdGMGFXOXVLSFI1Y0dVc0lHbHRjR3hsYldWdWRHRjBhVzl1S1h0Y2JpQWdJQ0JwWmloMGVYQmxJRDA5UFNCdWRXeHNLWHRjYmlBZ0lDQWdJSFJvYVhNdVptRnNiR0poWTJzZ1BTQnBiWEJzWlcxbGJuUmhkR2x2Ymp0Y2JpQWdJQ0I5Wld4elpYdGNiaUFnSUNBZ0lIUm9hWE11Y21WbmFYTjBjbmt1YzJWMEtIUjVjR1VzSUdsdGNHeGxiV1Z1ZEdGMGFXOXVLVHRjYmlBZ0lDQjlYRzRnSUgxY2JseHVJQ0JvWVhOSmJYQnNaVzFsYm5SaGRHbHZiaWgwYUdsdVp5a2dlMXh1SUNBZ0lHbG1JQ2gwYUdsdVp5QTlQVDBnU1c1MFpXZGxjaUI4ZkNCMGFHbHVaeUE5UFQwZ1JteHZZWFFwZTF4dUlDQWdJQ0FnY21WMGRYSnVJSFJvYVhNdWNtVm5hWE4wY25rdWFHRnpLSFJvYVc1bktUdGNiaUFnSUNCOVhHNWNiaUFnSUNCeVpYUjFjbTRnZEdocGN5NXlaV2RwYzNSeWVTNW9ZWE1vZEdocGJtY3VZMjl1YzNSeWRXTjBiM0lwTzF4dUlDQjlYRzU5WEc1Y2JseHVaWGh3YjNKMElHUmxabUYxYkhRZ1VISnZkRzlqYjJ3N1hHNGlYU3dpYzI5MWNtTmxVbTl2ZENJNklpOXpiM1Z5WTJVdkluMD1cbiIsImltcG9ydCB7IFR1cGxlIH0gZnJvbSAnLi9wcmltaXRpdmVzJztcbmltcG9ydCBCaXRTdHJpbmcgZnJvbSAnLi9iaXRfc3RyaW5nJztcbmltcG9ydCBQYXR0ZXJucyBmcm9tICcuL3BhdHRlcm5zJztcbmltcG9ydCBQcm90b2NvbCBmcm9tICcuL3Byb3RvY29sJztcblxuZnVuY3Rpb24gY2FsbF9wcm9wZXJ0eShpdGVtLCBwcm9wZXJ0eSkge1xuICBsZXQgcHJvcCA9IG51bGw7XG5cbiAgaWYgKHR5cGVvZiBpdGVtID09PSBcIm51bWJlclwiIHx8IHR5cGVvZiBpdGVtID09PSBcInN5bWJvbFwiIHx8IHR5cGVvZiBpdGVtID09PSBcImJvb2xlYW5cIiB8fCB0eXBlb2YgaXRlbSA9PT0gXCJzdHJpbmdcIikge1xuICAgIGlmIChpdGVtW3Byb3BlcnR5XSAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICBwcm9wID0gcHJvcGVydHk7XG4gICAgfSBlbHNlIGlmIChpdGVtW1N5bWJvbC5mb3IocHJvcGVydHkpXSAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICBwcm9wID0gU3ltYm9sLmZvcihwcm9wZXJ0eSk7XG4gICAgfVxuICB9IGVsc2Uge1xuICAgIGlmIChwcm9wZXJ0eSBpbiBpdGVtKSB7XG4gICAgICBwcm9wID0gcHJvcGVydHk7XG4gICAgfSBlbHNlIGlmIChTeW1ib2wuZm9yKHByb3BlcnR5KSBpbiBpdGVtKSB7XG4gICAgICBwcm9wID0gU3ltYm9sLmZvcihwcm9wZXJ0eSk7XG4gICAgfVxuICB9XG5cbiAgaWYgKHByb3AgPT09IG51bGwpIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoYFByb3BlcnR5ICR7IHByb3BlcnR5IH0gbm90IGZvdW5kIGluICR7IGl0ZW0gfWApO1xuICB9XG5cbiAgaWYgKGl0ZW1bcHJvcF0gaW5zdGFuY2VvZiBGdW5jdGlvbikge1xuICAgIHJldHVybiBpdGVtW3Byb3BdKCk7XG4gIH0gZWxzZSB7XG4gICAgcmV0dXJuIGl0ZW1bcHJvcF07XG4gIH1cbn1cblxuZnVuY3Rpb24gYXBwbHkoLi4uYXJncykge1xuICBpZiAoYXJncy5sZW5ndGggPT09IDIpIHtcbiAgICBhcmdzWzBdLmFwcGx5KG51bGwsIGFyZ3Muc2xpY2UoMSkpO1xuICB9IGVsc2Uge1xuICAgIGFyZ3NbMF1bYXJnc1sxXV0uYXBwbHkobnVsbCwgYXJncy5zbGljZSgyKSk7XG4gIH1cbn1cblxuZnVuY3Rpb24gY29udGFpbnMobGVmdCwgcmlnaHQpIHtcbiAgZm9yIChsZXQgeCBvZiByaWdodCkge1xuICAgIGlmIChQYXR0ZXJucy5tYXRjaF9ub190aHJvdyhsZWZ0LCB4KSAhPSBudWxsKSB7XG4gICAgICByZXR1cm4gdHJ1ZTtcbiAgICB9XG4gIH1cblxuICByZXR1cm4gZmFsc2U7XG59XG5cbmZ1bmN0aW9uIGdldF9nbG9iYWwoKSB7XG4gIGlmICh0eXBlb2Ygc2VsZiAhPT0gXCJ1bmRlZmluZWRcIikge1xuICAgIHJldHVybiBzZWxmO1xuICB9IGVsc2UgaWYgKHR5cGVvZiB3aW5kb3cgIT09IFwidW5kZWZpbmVkXCIpIHtcbiAgICByZXR1cm4gd2luZG93O1xuICB9IGVsc2UgaWYgKHR5cGVvZiBnbG9iYWwgIT09IFwidW5kZWZpbmVkXCIpIHtcbiAgICByZXR1cm4gZ2xvYmFsO1xuICB9XG5cbiAgdGhyb3cgbmV3IEVycm9yKFwiTm8gZ2xvYmFsIHN0YXRlIGZvdW5kXCIpO1xufVxuXG5mdW5jdGlvbiBkZWZzdHJ1Y3QoZGVmYXVsdHMpIHtcbiAgcmV0dXJuIGNsYXNzIHtcbiAgICBjb25zdHJ1Y3Rvcih1cGRhdGUgPSB7fSkge1xuICAgICAgbGV0IHRoZV92YWx1ZXMgPSBPYmplY3QuYXNzaWduKGRlZmF1bHRzLCB1cGRhdGUpO1xuICAgICAgT2JqZWN0LmFzc2lnbih0aGlzLCB0aGVfdmFsdWVzKTtcbiAgICB9XG5cbiAgICBzdGF0aWMgY3JlYXRlKHVwZGF0ZXMgPSB7fSkge1xuICAgICAgbGV0IHggPSBuZXcgdGhpcyh1cGRhdGVzKTtcbiAgICAgIHJldHVybiBPYmplY3QuZnJlZXplKHgpO1xuICAgIH1cbiAgfTtcbn1cblxuZnVuY3Rpb24gZGVmZXhjZXB0aW9uKGRlZmF1bHRzKSB7XG4gIHJldHVybiBjbGFzcyBleHRlbmRzIEVycm9yIHtcbiAgICBjb25zdHJ1Y3Rvcih1cGRhdGUgPSB7fSkge1xuICAgICAgbGV0IG1lc3NhZ2UgPSB1cGRhdGUubWVzc2FnZSB8fCBcIlwiO1xuICAgICAgc3VwZXIobWVzc2FnZSk7XG5cbiAgICAgIGxldCB0aGVfdmFsdWVzID0gT2JqZWN0LmFzc2lnbihkZWZhdWx0cywgdXBkYXRlKTtcbiAgICAgIE9iamVjdC5hc3NpZ24odGhpcywgdGhlX3ZhbHVlcyk7XG5cbiAgICAgIHRoaXMubmFtZSA9IHRoaXMuY29uc3RydWN0b3IubmFtZTtcbiAgICAgIHRoaXMubWVzc2FnZSA9IG1lc3NhZ2U7XG4gICAgICB0aGlzW1NwZWNpYWxGb3Jtcy5hdG9tKFwiX19leGNlcHRpb25fX1wiKV0gPSB0cnVlO1xuICAgICAgRXJyb3IuY2FwdHVyZVN0YWNrVHJhY2UodGhpcywgdGhpcy5jb25zdHJ1Y3Rvci5uYW1lKTtcbiAgICB9XG5cbiAgICBzdGF0aWMgY3JlYXRlKHVwZGF0ZXMgPSB7fSkge1xuICAgICAgbGV0IHggPSBuZXcgdGhpcyh1cGRhdGVzKTtcbiAgICAgIHJldHVybiBPYmplY3QuZnJlZXplKHgpO1xuICAgIH1cbiAgfTtcbn1cblxuZnVuY3Rpb24gZGVmcHJvdG9jb2woc3BlYykge1xuICByZXR1cm4gbmV3IFByb3RvY29sKHNwZWMpO1xufVxuXG5mdW5jdGlvbiBkZWZpbXBsKHByb3RvY29sLCB0eXBlLCBpbXBsKSB7XG4gIHByb3RvY29sLmltcGxlbWVudGF0aW9uKHR5cGUsIGltcGwpO1xufVxuXG5mdW5jdGlvbiBnZXRfb2JqZWN0X2tleXMob2JqKSB7XG4gIHJldHVybiBPYmplY3Qua2V5cyhvYmopLmNvbmNhdChPYmplY3QuZ2V0T3duUHJvcGVydHlTeW1ib2xzKG9iaikpO1xufVxuXG5mdW5jdGlvbiBpc192YWxpZF9jaGFyYWN0ZXIoY29kZXBvaW50KSB7XG4gIHRyeSB7XG4gICAgcmV0dXJuIFN0cmluZy5mcm9tQ29kZVBvaW50KGNvZGVwb2ludCkgIT0gbnVsbDtcbiAgfSBjYXRjaCAoZSkge1xuICAgIHJldHVybiBmYWxzZTtcbiAgfVxufVxuXG4vL2h0dHBzOi8vZGV2ZWxvcGVyLm1vemlsbGEub3JnL2VuLVVTL2RvY3MvV2ViL0FQSS9XaW5kb3dCYXNlNjQvQmFzZTY0X2VuY29kaW5nX2FuZF9kZWNvZGluZyNTb2x1dGlvbl8yXyVFMiU4MCU5M19yZXdyaXRlX3RoZV9ET01zX2F0b2IoKV9hbmRfYnRvYSgpX3VzaW5nX0phdmFTY3JpcHQnc19UeXBlZEFycmF5c19hbmRfVVRGLThcbmZ1bmN0aW9uIGI2NEVuY29kZVVuaWNvZGUoc3RyKSB7XG4gIHJldHVybiBidG9hKGVuY29kZVVSSUNvbXBvbmVudChzdHIpLnJlcGxhY2UoLyUoWzAtOUEtRl17Mn0pL2csIGZ1bmN0aW9uIChtYXRjaCwgcDEpIHtcbiAgICByZXR1cm4gU3RyaW5nLmZyb21DaGFyQ29kZSgnMHgnICsgcDEpO1xuICB9KSk7XG59XG5cbmZ1bmN0aW9uIGRlbGV0ZV9wcm9wZXJ0eV9mcm9tX21hcChtYXAsIHByb3BlcnR5KSB7XG4gIGxldCBuZXdfbWFwID0gT2JqZWN0LmFzc2lnbihPYmplY3QuY3JlYXRlKG1hcC5jb25zdHJ1Y3Rvci5wcm90b3R5cGUpLCBtYXApO1xuICBkZWxldGUgbmV3X21hcFtwcm9wZXJ0eV07XG5cbiAgcmV0dXJuIE9iamVjdC5mcmVlemUobmV3X21hcCk7XG59XG5cbmZ1bmN0aW9uIGNsYXNzX3RvX29iaihtYXApIHtcbiAgbGV0IG5ld19tYXAgPSBPYmplY3QuYXNzaWduKHt9LCBtYXApO1xuICByZXR1cm4gT2JqZWN0LmZyZWV6ZShuZXdfbWFwKTtcbn1cblxuZnVuY3Rpb24gYWRkX3Byb3BlcnR5X3RvX21hcChtYXAsIHByb3BlcnR5LCB2YWx1ZSkge1xuICBsZXQgbmV3X21hcCA9IE9iamVjdC5hc3NpZ24oe30sIG1hcCk7XG4gIG5ld19tYXBbcHJvcGVydHldID0gdmFsdWU7XG4gIHJldHVybiBPYmplY3QuZnJlZXplKG5ld19tYXApO1xufVxuXG5mdW5jdGlvbiB1cGRhdGVfbWFwKG1hcCwgcHJvcGVydHksIHZhbHVlKSB7XG4gIGlmIChwcm9wZXJ0eSBpbiBnZXRfb2JqZWN0X2tleXMobWFwKSkge1xuICAgIHJldHVybiBhZGRfcHJvcGVydHlfdG9fbWFwKG1hcCwgcHJvcGVydHksIHZhbHVlKTtcbiAgfVxuXG4gIHRocm93IFwibWFwIGRvZXMgbm90IGhhdmUga2V5XCI7XG59XG5cbmZ1bmN0aW9uIGJub3QoZXhwcikge1xuICByZXR1cm4gfmV4cHI7XG59XG5cbmZ1bmN0aW9uIGJhbmQobGVmdCwgcmlnaHQpIHtcbiAgcmV0dXJuIGxlZnQgJiByaWdodDtcbn1cblxuZnVuY3Rpb24gYm9yKGxlZnQsIHJpZ2h0KSB7XG4gIHJldHVybiBsZWZ0IHwgcmlnaHQ7XG59XG5cbmZ1bmN0aW9uIGJzbChsZWZ0LCByaWdodCkge1xuICByZXR1cm4gbGVmdCA8PCByaWdodDtcbn1cblxuZnVuY3Rpb24gYnNyKGxlZnQsIHJpZ2h0KSB7XG4gIHJldHVybiBsZWZ0ID4+IHJpZ2h0O1xufVxuXG5mdW5jdGlvbiBieG9yKGxlZnQsIHJpZ2h0KSB7XG4gIHJldHVybiBsZWZ0IF4gcmlnaHQ7XG59XG5cbmZ1bmN0aW9uIHppcChsaXN0X29mX2xpc3RzKSB7XG4gIGlmIChsaXN0X29mX2xpc3RzLmxlbmd0aCA9PT0gMCkge1xuICAgIHJldHVybiBPYmplY3QuZnJlZXplKFtdKTtcbiAgfVxuXG4gIGxldCBuZXdfdmFsdWUgPSBbXTtcbiAgbGV0IHNtYWxsZXN0X2xlbmd0aCA9IGxpc3Rfb2ZfbGlzdHNbMF07XG5cbiAgZm9yIChsZXQgeCBvZiBsaXN0X29mX2xpc3RzKSB7XG4gICAgaWYgKHgubGVuZ3RoIDwgc21hbGxlc3RfbGVuZ3RoKSB7XG4gICAgICBzbWFsbGVzdF9sZW5ndGggPSB4Lmxlbmd0aDtcbiAgICB9XG4gIH1cblxuICBmb3IgKGxldCBpID0gMDsgaSA8IHNtYWxsZXN0X2xlbmd0aDsgaSsrKSB7XG4gICAgbGV0IGN1cnJlbnRfdmFsdWUgPSBbXTtcbiAgICBmb3IgKGxldCBqID0gMDsgaiA8IGxpc3Rfb2ZfbGlzdHMubGVuZ3RoOyBqKyspIHtcbiAgICAgIGN1cnJlbnRfdmFsdWUucHVzaChsaXN0X29mX2xpc3RzW2pdW2ldKTtcbiAgICB9XG5cbiAgICBuZXdfdmFsdWUucHVzaChuZXcgVHVwbGUoLi4uY3VycmVudF92YWx1ZSkpO1xuICB9XG5cbiAgcmV0dXJuIE9iamVjdC5mcmVlemUobmV3X3ZhbHVlKTtcbn1cblxuZnVuY3Rpb24gY2FuX2RlY29kZTY0KGRhdGEpIHtcbiAgdHJ5IHtcbiAgICBhdG9iKGRhdGEpO1xuICAgIHJldHVybiB0cnVlO1xuICB9IGNhdGNoIChlKSB7XG4gICAgcmV0dXJuIGZhbHNlO1xuICB9XG59XG5cbmZ1bmN0aW9uIHJlbW92ZV9mcm9tX2xpc3QobGlzdCwgZWxlbWVudCkge1xuICBsZXQgZm91bmQgPSBmYWxzZTtcblxuICByZXR1cm4gbGlzdC5maWx0ZXIoZWxlbSA9PiB7XG4gICAgaWYgKCFmb3VuZCAmJiBlbGVtID09PSBlbGVtZW50KSB7XG4gICAgICBmb3VuZCA9IHRydWU7XG4gICAgICByZXR1cm4gZmFsc2U7XG4gICAgfVxuXG4gICAgcmV0dXJuIHRydWU7XG4gIH0pO1xufVxuXG5mdW5jdGlvbiBmb2xkbChmdW4sIGFjYywgbGlzdCkge1xuICBsZXQgYWNjMSA9IGFjYztcblxuICBmb3IgKGNvbnN0IGVsIG9mIGxpc3QpIHtcbiAgICBhY2MxID0gZnVuKGVsLCBhY2MxKTtcbiAgfVxuXG4gIHJldHVybiBhY2MxO1xufVxuXG5mdW5jdGlvbiBmb2xkcihmdW4sIGFjYywgbGlzdCkge1xuICBsZXQgYWNjMSA9IGFjYztcblxuICBmb3IgKGxldCBpID0gbGlzdC5sZW5ndGggLSAxOyBpID49IDA7IGktLSkge1xuICAgIGFjYzEgPSBmdW4obGlzdFtpXSwgYWNjMSk7XG4gIH1cblxuICByZXR1cm4gYWNjMTtcbn1cblxuZnVuY3Rpb24ga2V5ZmluZChrZXksIG4sIHR1cGxlbGlzdCkge1xuXG4gIGZvciAobGV0IGkgPSB0dXBsZWxpc3QubGVuZ3RoIC0gMTsgaSA+PSAwOyBpLS0pIHtcbiAgICBpZiAodHVwbGVsaXN0W2ldLmdldChuKSA9PT0ga2V5KSB7XG4gICAgICByZXR1cm4gdHVwbGVsaXN0W2ldO1xuICAgIH1cbiAgfVxuXG4gIHJldHVybiBmYWxzZTtcbn1cblxuZnVuY3Rpb24ga2V5ZGVsZXRlKGtleSwgbiwgdHVwbGVsaXN0KSB7XG5cbiAgZm9yIChsZXQgaSA9IHR1cGxlbGlzdC5sZW5ndGggLSAxOyBpID49IDA7IGktLSkge1xuICAgIGlmICh0dXBsZWxpc3RbaV0uZ2V0KG4pID09PSBrZXkpIHtcbiAgICAgIHJldHVybiB0dXBsZWxpc3QuY29uY2F0KFtdKS5zcGxpY2UoaSwgMSk7XG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIHR1cGxlbGlzdDtcbn1cblxuZnVuY3Rpb24ga2V5c3RvcmUoa2V5LCBuLCBsaXN0LCBuZXd0dXBsZSkge1xuICBmb3IgKGxldCBpID0gbGlzdC5sZW5ndGggLSAxOyBpID49IDA7IGktLSkge1xuICAgIGlmIChsaXN0W2ldLmdldChuKSA9PT0ga2V5KSB7XG4gICAgICByZXR1cm4gbGlzdC5jb25jYXQoW10pLnNwbGljZShpLCAxLCBuZXd0dXBsZSk7XG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIGxpc3QuY29uY2F0KFtdKS5wdXNoKG5ld3R1cGxlKTtcbn1cblxuZnVuY3Rpb24ga2V5bWVtYmVyKGtleSwgbiwgbGlzdCkge1xuICBmb3IgKGxldCBpID0gbGlzdC5sZW5ndGggLSAxOyBpID49IDA7IGktLSkge1xuICAgIGlmIChsaXN0W2ldLmdldChuKSA9PT0ga2V5KSB7XG4gICAgICByZXR1cm4gdHJ1ZTtcbiAgICB9XG4gIH1cblxuICByZXR1cm4gZmFsc2U7XG59XG5cbmZ1bmN0aW9uIGtleXRha2Uoa2V5LCBuLCBsaXN0KSB7XG4gIGlmICgha2V5bWVtYmVyKGtleSwgbiwgbGlzdCkpIHtcbiAgICByZXR1cm4gZmFsc2U7XG4gIH1cblxuICBsZXQgdHVwbGUgPSBrZXlmaW5kKGtleSwgbiwgbGlzdCk7XG5cbiAgcmV0dXJuIG5ldyBUdXBsZSh0dXBsZS5nZXQobiksIHR1cGxlLCBrZXlkZWxldGUoa2V5LCBuLCBsaXN0KSk7XG59XG5cbmZ1bmN0aW9uIGtleXJlcGxhY2Uoa2V5LCBuLCBsaXN0LCBuZXd0dXBsZSkge1xuXG4gIGZvciAobGV0IGkgPSB0dXBsZWxpc3QubGVuZ3RoIC0gMTsgaSA+PSAwOyBpLS0pIHtcbiAgICBpZiAodHVwbGVsaXN0W2ldLmdldChuKSA9PT0ga2V5KSB7XG4gICAgICByZXR1cm4gdHVwbGVsaXN0LmNvbmNhdChbXSkuc3BsaWNlKGksIDEsIG5ld3R1cGxlKTtcbiAgICB9XG4gIH1cblxuICByZXR1cm4gdHVwbGVsaXN0O1xufVxuXG5mdW5jdGlvbiByZXZlcnNlKGxpc3QpIHtcbiAgcmV0dXJuIGxpc3QuY29uY2F0KFtdKS5yZXZlcnNlKCk7XG59XG5cbmZ1bmN0aW9uIG1hcHNfZmluZChrZXksIG1hcCkge1xuICBpZiAoa2V5IGluIGdldF9vYmplY3Rfa2V5cyhtYXApKSB7XG4gICAgcmV0dXJuIG5ldyBUdXBsZShTeW1ib2wuZm9yKFwib2tcIiksIG1hcFtrZXldKTtcbiAgfSBlbHNlIHtcbiAgICByZXR1cm4gU3ltYm9sLmZvcihcImVycm9yXCIpO1xuICB9XG59XG5cbmZ1bmN0aW9uIGZsYXR0ZW4obGlzdCwgdGFpbCA9IFtdKSB7XG4gIGxldCBuZXdfbGlzdCA9IFtdO1xuXG4gIGZvciAobGV0IGUgb2YgbGlzdCkge1xuICAgIGlmIChpc0FycmF5KGUpKSB7XG4gICAgICBuZXdfbGlzdCA9IG5ld19saXN0LmNvbmNhdChmbGF0dGVuKGUpKTtcbiAgICB9IGVsc2Uge1xuICAgICAgbmV3X2xpc3QucHVzaChlKTtcbiAgICB9XG4gIH1cblxuICByZXR1cm4gT2JqZWN0LmZyZWV6ZShuZXdfbGlzdC5jb25jYXQodGFpbCkpO1xufVxuXG5mdW5jdGlvbiBkdXBsaWNhdGUobiwgZWxlbSkge1xuICBsZXQgbGlzdCA9IFtdO1xuXG4gIGZvciAobGV0IGkgPSAwOyBpIDwgbjsgaSsrKSB7XG4gICAgbGlzdC5wdXNoKGVsZW0pO1xuICB9XG5cbiAgcmV0dXJuIE9iamVjdC5mcmVlemUobGlzdCk7XG59XG5cbmZ1bmN0aW9uIG1hcGZvbGRsKGZ1biwgYWNjLCBsaXN0KSB7XG4gIGxldCBuZXdsaXN0ID0gW107XG5cbiAgZm9yIChsZXQgeCBvZiBsaXN0KSB7XG4gICAgbGV0IHR1cCA9IGZ1bih4LCBhY2MpO1xuICAgIG5ld2xpc3QucHVzaCh0dXAuZ2V0KDApKTtcbiAgICBhY2MgPSB0dXAuZ2V0KDEpO1xuICB9XG5cbiAgcmV0dXJuIG5ldyBUdXBsZShPYmplY3QuZnJlZXplKG5ld2xpc3QpLCBhY2MpO1xufVxuXG5mdW5jdGlvbiBmaWx0ZXJtYXAoZnVuLCBsaXN0KSB7XG4gIGxldCBuZXdsaXN0ID0gW107XG5cbiAgZm9yICh4IG9mIGxpc3QpIHtcbiAgICBsZXQgcmVzdWx0ID0gZnVuKHgpO1xuXG4gICAgaWYgKHJlc3VsdCA9PT0gdHJ1ZSkge1xuICAgICAgbmV3bGlzdC5wdXNoKHgpO1xuICAgIH0gZWxzZSBpZiAocmVzdWx0IGluc3RhbmNlb2YgVHVwbGUpIHtcbiAgICAgIG5ld2xpc3QucHVzaChyZXN1bHQuZ2V0KDEpKTtcbiAgICB9XG4gIH1cblxuICByZXR1cm4gT2JqZWN0LmZyZWV6ZShuZXdsaXN0KTtcbn1cblxuZnVuY3Rpb24gbWFwc19mb2xkKGZ1biwgYWNjLCBtYXApIHtcbiAgbGV0IGFjYzEgPSBhY2M7XG5cbiAgZm9yIChsZXQgayBvZiBnZXRfb2JqZWN0X2tleXMobWFwKSkge1xuICAgIGFjYzEgPSBmdW4oaywgbWFwW2tdLCBhY2MxKTtcbiAgfVxuXG4gIHJldHVybiBhY2MxO1xufVxuXG5mdW5jdGlvbiBtYXBzX2Zyb21fbGlzdChsaXN0KSB7XG4gIGxldCBtID0ge307XG5cbiAgZm9yICh4IG9mIGxpc3QpIHtcbiAgICBtW3guZ2V0KDApXSA9IHguZ2V0KDEpO1xuICB9XG5cbiAgcmV0dXJuIE9iamVjdC5mcmVlemUobSk7XG59XG5cbmV4cG9ydCBkZWZhdWx0IHtcbiAgY2FsbF9wcm9wZXJ0eSxcbiAgYXBwbHksXG4gIGNvbnRhaW5zLFxuICBnZXRfZ2xvYmFsLFxuICBkZWZzdHJ1Y3QsXG4gIGRlZmV4Y2VwdGlvbixcbiAgZGVmcHJvdG9jb2wsXG4gIGRlZmltcGwsXG4gIGdldF9vYmplY3Rfa2V5cyxcbiAgaXNfdmFsaWRfY2hhcmFjdGVyLFxuICBiNjRFbmNvZGVVbmljb2RlLFxuICBkZWxldGVfcHJvcGVydHlfZnJvbV9tYXAsXG4gIGFkZF9wcm9wZXJ0eV90b19tYXAsXG4gIGNsYXNzX3RvX29iaixcbiAgY2FuX2RlY29kZTY0LFxuICBibm90LFxuICBiYW5kLFxuICBib3IsXG4gIGJzbCxcbiAgYnNyLFxuICBieG9yLFxuICB6aXAsXG4gIGZvbGRsLFxuICBmb2xkcixcbiAgcmVtb3ZlX2Zyb21fbGlzdCxcbiAga2V5ZGVsZXRlLFxuICBrZXlzdG9yZSxcbiAga2V5ZmluZCxcbiAga2V5dGFrZSxcbiAga2V5cmVwbGFjZSxcbiAgcmV2ZXJzZSxcbiAgdXBkYXRlX21hcCxcbiAgbWFwc19maW5kLFxuICBmbGF0dGVuLFxuICBkdXBsaWNhdGUsXG4gIG1hcGZvbGRsLFxuICBmaWx0ZXJtYXAsXG4gIG1hcHNfZm9sZFxufTtcbi8vIyBzb3VyY2VNYXBwaW5nVVJMPWRhdGE6YXBwbGljYXRpb24vanNvbjtiYXNlNjQsZXlKMlpYSnphVzl1SWpvekxDSnpiM1Z5WTJWeklqcGJJbXhwWWk5amIzSmxMMloxYm1OMGFXOXVjeTVxY3lKZExDSnVZVzFsY3lJNlcxMHNJbTFoY0hCcGJtZHpJam9pUVVGQlFTeFRRVUZUTEV0QlFWUXNVVUZCYzBJc1kwRkJkRUk3UVVGRFFTeFBRVUZQTEZOQlFWQXNUVUZCYzBJc1kwRkJkRUk3UVVGRFFTeFBRVUZQTEZGQlFWQXNUVUZCY1VJc1dVRkJja0k3UVVGRFFTeFBRVUZQTEZGQlFWQXNUVUZCY1VJc1dVRkJja0k3TzBGQlJVRXNVMEZCVXl4aFFVRlVMRU5CUVhWQ0xFbEJRWFpDTEVWQlFUWkNMRkZCUVRkQ0xFVkJRWE5ETzBGQlEzQkRMRTFCUVVrc1QwRkJUeXhKUVVGUUxFTkJSR2RET3p0QlFVZHdReXhOUVVGSExFOUJRVThzU1VGQlVDeExRVUZuUWl4UlFVRm9RaXhKUVVFMFFpeFBRVUZQTEVsQlFWQXNTMEZCWjBJc1VVRkJhRUlzU1VGQk5FSXNUMEZCVHl4SlFVRlFMRXRCUVdkQ0xGTkJRV2hDTEVsQlFUWkNMRTlCUVU4c1NVRkJVQ3hMUVVGblFpeFJRVUZvUWl4RlFVRjVRanRCUVVNdlJ5eFJRVUZITEV0QlFVc3NVVUZCVEN4TlFVRnRRaXhUUVVGdVFpeEZRVUUyUWp0QlFVTTVRaXhoUVVGUExGRkJRVkFzUTBGRU9FSTdTMEZCYUVNc1RVRkZUU3hKUVVGSExFdEJRVXNzVDBGQlR5eEhRVUZRTEVOQlFWY3NVVUZCV0N4RFFVRk1MRTFCUVN0Q0xGTkJRUzlDTEVWQlFYbERPMEZCUTJoRUxHRkJRVThzVDBGQlR5eEhRVUZRTEVOQlFWY3NVVUZCV0N4RFFVRlFMRU5CUkdkRU8wdEJRVFZETzBkQlNGSXNUVUZOVHp0QlFVTk1MRkZCUVVjc1dVRkJXU3hKUVVGYUxFVkJRV2xDTzBGQlEyeENMR0ZCUVU4c1VVRkJVQ3hEUVVSclFqdExRVUZ3UWl4TlFVVk5MRWxCUVVjc1QwRkJUeXhIUVVGUUxFTkJRVmNzVVVGQldDeExRVUYzUWl4SlFVRjRRaXhGUVVFMlFqdEJRVU53UXl4aFFVRlBMRTlCUVU4c1IwRkJVQ3hEUVVGWExGRkJRVmdzUTBGQlVDeERRVVJ2UXp0TFFVRm9RenRIUVZSU096dEJRV05CTEUxQlFVY3NVMEZCVXl4SlFVRlVMRVZCUVdNN1FVRkRaaXhWUVVGTkxFbEJRVWtzUzBGQlNpeERRVUZWTEVOQlFVTXNVMEZCUkN4SFFVRmhMRkZCUVdJc1JVRkJkVUlzWTBGQmRrSXNSMEZCZDBNc1NVRkJlRU1zUlVGQk9FTXNRMEZCZUVRc1EwRkJUaXhEUVVSbE8wZEJRV3BDT3p0QlFVbEJMRTFCUVVjc1MwRkJTeXhKUVVGTUxHRkJRWE5DTEZGQlFYUkNMRVZCUVN0Q08wRkJRMmhETEZkQlFVOHNTMEZCU3l4SlFVRk1MRWRCUVZBc1EwRkVaME03UjBGQmJFTXNUVUZGU3p0QlFVTklMRmRCUVU4c1MwRkJTeXhKUVVGTUxFTkJRVkFzUTBGRVJ6dEhRVVpNTzBOQmNrSkdPenRCUVRSQ1FTeFRRVUZUTEV0QlFWUXNRMEZCWlN4SFFVRkhMRWxCUVVnc1JVRkJVVHRCUVVOeVFpeE5RVUZITEV0QlFVc3NUVUZCVEN4TFFVRm5RaXhEUVVGb1FpeEZRVUZyUWp0QlFVTnVRaXhUUVVGTExFTkJRVXdzUlVGQlVTeExRVUZTTEVOQlFXTXNTVUZCWkN4RlFVRnZRaXhMUVVGTExFdEJRVXdzUTBGQlZ5eERRVUZZTEVOQlFYQkNMRVZCUkcxQ08wZEJRWEpDTEUxQlJVczdRVUZEU0N4VFFVRkxMRU5CUVV3c1JVRkJVU3hMUVVGTExFTkJRVXdzUTBGQlVpeEZRVUZwUWl4TFFVRnFRaXhEUVVGMVFpeEpRVUYyUWl4RlFVRTJRaXhMUVVGTExFdEJRVXdzUTBGQlZ5eERRVUZZTEVOQlFUZENMRVZCUkVjN1IwRkdURHREUVVSR096dEJRVkZCTEZOQlFWTXNVVUZCVkN4RFFVRnJRaXhKUVVGc1FpeEZRVUYzUWl4TFFVRjRRaXhGUVVFNFFqdEJRVU0xUWl4UFFVRkpMRWxCUVVrc1EwRkJTaXhKUVVGVExFdEJRV0lzUlVGQmJVSTdRVUZEYWtJc1VVRkJSeXhUUVVGVExHTkJRVlFzUTBGQmQwSXNTVUZCZUVJc1JVRkJPRUlzUTBGQk9VSXNTMEZCYjBNc1NVRkJjRU1zUlVGQmVVTTdRVUZETVVNc1lVRkJUeXhKUVVGUUxFTkJSREJETzB0QlFUVkRPMGRCUkVZN08wRkJUVUVzVTBGQlR5eExRVUZRTEVOQlVEUkNPME5CUVRsQ096dEJRVlZCTEZOQlFWTXNWVUZCVkN4SFFVRnhRanRCUVVOdVFpeE5RVUZITEU5QlFVOHNTVUZCVUN4TFFVRnBRaXhYUVVGcVFpeEZRVUUyUWp0QlFVTTVRaXhYUVVGUExFbEJRVkFzUTBGRU9FSTdSMEZCYUVNc1RVRkZUU3hKUVVGSExFOUJRVThzVFVGQlVDeExRVUZ0UWl4WFFVRnVRaXhGUVVFclFqdEJRVU4wUXl4WFFVRlBMRTFCUVZBc1EwRkVjME03UjBGQmJFTXNUVUZGUVN4SlFVRkhMRTlCUVU4c1RVRkJVQ3hMUVVGdFFpeFhRVUZ1UWl4RlFVRXJRanRCUVVOMFF5eFhRVUZQTEUxQlFWQXNRMEZFYzBNN1IwRkJiRU03TzBGQlNVNHNVVUZCVFN4SlFVRkpMRXRCUVVvc1EwRkJWU3gxUWtGQlZpeERRVUZPTEVOQlZHMUNPME5CUVhKQ096dEJRVmxCTEZOQlFWTXNVMEZCVkN4RFFVRnRRaXhSUVVGdVFpeEZRVUUwUWp0QlFVTXhRaXhUUVVGUExFMUJRVTA3UVVGRFdDeG5Ra0ZCV1N4VFFVRlRMRVZCUVZRc1JVRkJXVHRCUVVOMFFpeFZRVUZKTEdGQlFXRXNUMEZCVHl4TlFVRlFMRU5CUVdNc1VVRkJaQ3hGUVVGM1FpeE5RVUY0UWl4RFFVRmlMRU5CUkd0Q08wRkJSWFJDTEdGQlFVOHNUVUZCVUN4RFFVRmpMRWxCUVdRc1JVRkJiMElzVlVGQmNFSXNSVUZHYzBJN1MwRkJlRUk3TzBGQlMwRXNWMEZCVHl4TlFVRlFMRU5CUVdNc1ZVRkJWU3hGUVVGV0xFVkJRV0U3UVVGRGVrSXNWVUZCU1N4SlFVRkpMRWxCUVVrc1NVRkJTaXhEUVVGVExFOUJRVlFzUTBGQlNpeERRVVJ4UWp0QlFVVjZRaXhoUVVGUExFOUJRVThzVFVGQlVDeERRVUZqTEVOQlFXUXNRMEZCVUN4RFFVWjVRanRMUVVFelFqdEhRVTVMTEVOQlJHMUNPME5CUVRWQ096dEJRV1ZCTEZOQlFWTXNXVUZCVkN4RFFVRnpRaXhSUVVGMFFpeEZRVUVyUWp0QlFVTTNRaXhUUVVGUExHTkJRV01zUzBGQlpDeERRVUZ2UWp0QlFVTjZRaXhuUWtGQldTeFRRVUZUTEVWQlFWUXNSVUZCV1R0QlFVTjBRaXhWUVVGSkxGVkJRVlVzVDBGQlR5eFBRVUZRTEVsQlFXdENMRVZCUVd4Q0xFTkJSRkU3UVVGRmRFSXNXVUZCVFN4UFFVRk9MRVZCUm5OQ096dEJRVWwwUWl4VlFVRkpMR0ZCUVdFc1QwRkJUeXhOUVVGUUxFTkJRV01zVVVGQlpDeEZRVUYzUWl4TlFVRjRRaXhEUVVGaUxFTkJTbXRDTzBGQlMzUkNMR0ZCUVU4c1RVRkJVQ3hEUVVGakxFbEJRV1FzUlVGQmIwSXNWVUZCY0VJc1JVRk1jMEk3TzBGQlQzUkNMRmRCUVVzc1NVRkJUQ3hIUVVGWkxFdEJRVXNzVjBGQlRDeERRVUZwUWl4SlFVRnFRaXhEUVZCVk8wRkJVWFJDTEZkQlFVc3NUMEZCVEN4SFFVRmxMRTlCUVdZc1EwRlNjMEk3UVVGVGRFSXNWMEZCU3l4aFFVRmhMRWxCUVdJc1EwRkJhMElzWlVGQmJFSXNRMEZCVEN4SlFVRXlReXhKUVVFelF5eERRVlJ6UWp0QlFWVjBRaXhaUVVGTkxHbENRVUZPTEVOQlFYZENMRWxCUVhoQ0xFVkJRVGhDTEV0QlFVc3NWMEZCVEN4RFFVRnBRaXhKUVVGcVFpeERRVUU1UWl4RFFWWnpRanRMUVVGNFFqczdRVUZoUVN4WFFVRlBMRTFCUVZBc1EwRkJZeXhWUVVGVkxFVkJRVllzUlVGQllUdEJRVU42UWl4VlFVRkpMRWxCUVVrc1NVRkJTU3hKUVVGS0xFTkJRVk1zVDBGQlZDeERRVUZLTEVOQlJIRkNPMEZCUlhwQ0xHRkJRVThzVDBGQlR5eE5RVUZRTEVOQlFXTXNRMEZCWkN4RFFVRlFMRU5CUm5sQ08wdEJRVE5DTzBkQlpFc3NRMEZFYzBJN1EwRkJMMEk3TzBGQmMwSkJMRk5CUVZNc1YwRkJWQ3hEUVVGeFFpeEpRVUZ5UWl4RlFVRXdRanRCUVVONFFpeFRRVUZQTEVsQlFVa3NVVUZCU2l4RFFVRmhMRWxCUVdJc1EwRkJVQ3hEUVVSM1FqdERRVUV4UWpzN1FVRkpRU3hUUVVGVExFOUJRVlFzUTBGQmFVSXNVVUZCYWtJc1JVRkJNa0lzU1VGQk0wSXNSVUZCYVVNc1NVRkJha01zUlVGQmMwTTdRVUZEY0VNc1YwRkJVeXhqUVVGVUxFTkJRWGRDTEVsQlFYaENMRVZCUVRoQ0xFbEJRVGxDTEVWQlJHOURPME5CUVhSRE96dEJRVWxCTEZOQlFWTXNaVUZCVkN4RFFVRjVRaXhIUVVGNlFpeEZRVUUyUWp0QlFVTjZRaXhUUVVGUExFOUJRVThzU1VGQlVDeERRVUZaTEVkQlFWb3NSVUZCYVVJc1RVRkJha0lzUTBGQmQwSXNUMEZCVHl4eFFrRkJVQ3hEUVVFMlFpeEhRVUUzUWl4RFFVRjRRaXhEUVVGUUxFTkJSSGxDTzBOQlFUZENPenRCUVVsQkxGTkJRVk1zYTBKQlFWUXNRMEZCTkVJc1UwRkJOVUlzUlVGQmMwTTdRVUZEY0VNc1RVRkJSenRCUVVORUxGZEJRVThzVDBGQlR5eGhRVUZRTEVOQlFYRkNMRk5CUVhKQ0xFdEJRVzFETEVsQlFXNURMRU5CUkU0N1IwRkJTQ3hEUVVWRExFOUJRVTBzUTBGQlRpeEZRVUZSTzBGQlExQXNWMEZCVHl4TFFVRlFMRU5CUkU4N1IwRkJVanREUVVoSU96czdRVUZUUVN4VFFVRlRMR2RDUVVGVUxFTkJRVEJDTEVkQlFURkNMRVZCUVN0Q08wRkJRek5DTEZOQlFVOHNTMEZCU3l4dFFrRkJiVUlzUjBGQmJrSXNSVUZCZDBJc1QwRkJlRUlzUTBGQlowTXNhVUpCUVdoRExFVkJRVzFFTEZWQlFWTXNTMEZCVkN4RlFVRm5RaXhGUVVGb1FpeEZRVUZ2UWp0QlFVTXZSU3hYUVVGUExFOUJRVThzV1VGQlVDeERRVUZ2UWl4UFFVRlBMRVZCUVZBc1EwRkJNMElzUTBGRUswVTdSMEZCY0VJc1EwRkJlRVFzUTBGQlVDeERRVVF5UWp0RFFVRXZRanM3UVVGTlFTeFRRVUZUTEhkQ1FVRlVMRU5CUVd0RExFZEJRV3hETEVWQlFYVkRMRkZCUVhaRExFVkJRV2RFTzBGQlF6VkRMRTFCUVVrc1ZVRkJWU3hQUVVGUExFMUJRVkFzUTBGQll5eFBRVUZQTEUxQlFWQXNRMEZCWXl4SlFVRkpMRmRCUVVvc1EwRkJaMElzVTBGQmFFSXNRMEZCTlVJc1JVRkJkMFFzUjBGQmVFUXNRMEZCVml4RFFVUjNRenRCUVVVMVF5eFRRVUZQTEZGQlFWRXNVVUZCVWl4RFFVRlFMRU5CUmpSRE96dEJRVWs1UXl4VFFVRlBMRTlCUVU4c1RVRkJVQ3hEUVVGakxFOUJRV1FzUTBGQlVDeERRVW80UXp0RFFVRm9SRHM3UVVGUFFTeFRRVUZUTEZsQlFWUXNRMEZCYzBJc1IwRkJkRUlzUlVGQk1FSTdRVUZEZEVJc1RVRkJTU3hWUVVGVkxFOUJRVThzVFVGQlVDeERRVUZqTEVWQlFXUXNSVUZCYTBJc1IwRkJiRUlzUTBGQlZpeERRVVJyUWp0QlFVVjRRaXhUUVVGUExFOUJRVThzVFVGQlVDeERRVUZqTEU5QlFXUXNRMEZCVUN4RFFVWjNRanREUVVFeFFqczdRVUZMUVN4VFFVRlRMRzFDUVVGVUxFTkJRVFpDTEVkQlFUZENMRVZCUVd0RExGRkJRV3hETEVWQlFUUkRMRXRCUVRWRExFVkJRV3RFTzBGQlEyaEVMRTFCUVVrc1ZVRkJWU3hQUVVGUExFMUJRVkFzUTBGQll5eEZRVUZrTEVWQlFXdENMRWRCUVd4Q0xFTkJRVllzUTBGRU5FTTdRVUZGYUVRc1ZVRkJVU3hSUVVGU0xFbEJRVzlDTEV0QlFYQkNMRU5CUm1kRU8wRkJSMmhFTEZOQlFVOHNUMEZCVHl4TlFVRlFMRU5CUVdNc1QwRkJaQ3hEUVVGUUxFTkJTR2RFTzBOQlFXeEVPenRCUVU5QkxGTkJRVk1zVlVGQlZDeERRVUZ2UWl4SFFVRndRaXhGUVVGNVFpeFJRVUY2UWl4RlFVRnRReXhMUVVGdVF5eEZRVUY1UXp0QlFVTnlReXhOUVVGSExGbEJRVmtzWjBKQlFXZENMRWRCUVdoQ0xFTkJRVm9zUlVGQmFVTTdRVUZEYUVNc1YwRkJUeXh2UWtGQmIwSXNSMEZCY0VJc1JVRkJlVUlzVVVGQmVrSXNSVUZCYlVNc1MwRkJia01zUTBGQlVDeERRVVJuUXp0SFFVRndRenM3UVVGSlFTeFJRVUZOTEhWQ1FVRk9MRU5CVEhGRE8wTkJRWHBET3p0QlFWRkJMRk5CUVZNc1NVRkJWQ3hEUVVGakxFbEJRV1FzUlVGQmJVSTdRVUZEYWtJc1UwRkJUeXhEUVVGRExFbEJRVVFzUTBGRVZUdERRVUZ1UWpzN1FVRkpRU3hUUVVGVExFbEJRVlFzUTBGQll5eEpRVUZrTEVWQlFXOUNMRXRCUVhCQ0xFVkJRVEJDTzBGQlEzaENMRk5CUVU4c1QwRkJUeXhMUVVGUUxFTkJSR2xDTzBOQlFURkNPenRCUVVsQkxGTkJRVk1zUjBGQlZDeERRVUZoTEVsQlFXSXNSVUZCYlVJc1MwRkJia0lzUlVGQmVVSTdRVUZEZGtJc1UwRkJUeXhQUVVGUExFdEJRVkFzUTBGRVowSTdRMEZCZWtJN08wRkJTVUVzVTBGQlV5eEhRVUZVTEVOQlFXRXNTVUZCWWl4RlFVRnRRaXhMUVVGdVFpeEZRVUY1UWp0QlFVTjJRaXhUUVVGUExGRkJRVkVzUzBGQlVpeERRVVJuUWp0RFFVRjZRanM3UVVGSlFTeFRRVUZUTEVkQlFWUXNRMEZCWVN4SlFVRmlMRVZCUVcxQ0xFdEJRVzVDTEVWQlFYbENPMEZCUTNaQ0xGTkJRVThzVVVGQlVTeExRVUZTTEVOQlJHZENPME5CUVhwQ096dEJRVWxCTEZOQlFWTXNTVUZCVkN4RFFVRmpMRWxCUVdRc1JVRkJiMElzUzBGQmNFSXNSVUZCTUVJN1FVRkRlRUlzVTBGQlR5eFBRVUZQTEV0QlFWQXNRMEZFYVVJN1EwRkJNVUk3TzBGQlNVRXNVMEZCVXl4SFFVRlVMRU5CUVdFc1lVRkJZaXhGUVVFeVFqdEJRVU42UWl4TlFVRkhMR05CUVdNc1RVRkJaQ3hMUVVGNVFpeERRVUY2UWl4RlFVRXlRanRCUVVNMVFpeFhRVUZQTEU5QlFVOHNUVUZCVUN4RFFVRmpMRVZCUVdRc1EwRkJVQ3hEUVVRMFFqdEhRVUU1UWpzN1FVRkpRU3hOUVVGSkxGbEJRVmtzUlVGQldpeERRVXh4UWp0QlFVMTZRaXhOUVVGSkxHdENRVUZyUWl4alFVRmpMRU5CUVdRc1EwRkJiRUlzUTBGT2NVSTdPMEZCVVhwQ0xFOUJRVWtzU1VGQlNTeERRVUZLTEVsQlFWTXNZVUZCWWl4RlFVRXlRanRCUVVONlFpeFJRVUZITEVWQlFVVXNUVUZCUml4SFFVRlhMR1ZCUVZnc1JVRkJNa0k3UVVGRE5VSXNkMEpCUVd0Q0xFVkJRVVVzVFVGQlJpeERRVVJWTzB0QlFUbENPMGRCUkVZN08wRkJUVUVzVDBGQlNTeEpRVUZKTEVsQlFVa3NRMEZCU2l4RlFVRlBMRWxCUVVrc1pVRkJTaXhGUVVGeFFpeEhRVUZ3UXl4RlFVRjNRenRCUVVOMFF5eFJRVUZKTEdkQ1FVRm5RaXhGUVVGb1FpeERRVVJyUXp0QlFVVjBReXhUUVVGSkxFbEJRVWtzU1VGQlNTeERRVUZLTEVWQlFVOHNTVUZCU1N4alFVRmpMRTFCUVdRc1JVRkJjMElzUjBGQmVrTXNSVUZCTmtNN1FVRkRNME1zYjBKQlFXTXNTVUZCWkN4RFFVRnRRaXhqUVVGakxFTkJRV1FzUlVGQmFVSXNRMEZCYWtJc1EwRkJia0lzUlVGRU1rTTdTMEZCTjBNN08wRkJTVUVzWTBGQlZTeEpRVUZXTEVOQlFXVXNTVUZCU1N4TFFVRktMRU5CUVZVc1IwRkJSeXhoUVVGSUxFTkJRWHBDTEVWQlRuTkRPMGRCUVhoRE96dEJRVk5CTEZOQlFVOHNUMEZCVHl4TlFVRlFMRU5CUVdNc1UwRkJaQ3hEUVVGUUxFTkJka0o1UWp0RFFVRXpRanM3UVVFd1FrRXNVMEZCVXl4WlFVRlVMRU5CUVhOQ0xFbEJRWFJDTEVWQlFUUkNPMEZCUXpGQ0xFMUJRVWM3UVVGRFJDeFRRVUZMTEVsQlFVd3NSVUZFUXp0QlFVVkVMRmRCUVU4c1NVRkJVQ3hEUVVaRE8wZEJRVWdzUTBGSFF5eFBRVUZOTEVOQlFVNHNSVUZCVVR0QlFVTlFMRmRCUVU4c1MwRkJVQ3hEUVVSUE8wZEJRVkk3UTBGS1NEczdRVUZUUVN4VFFVRlRMR2RDUVVGVUxFTkJRVEJDTEVsQlFURkNMRVZCUVdkRExFOUJRV2hETEVWQlFYZERPMEZCUTNCRExFMUJRVWtzVVVGQlVTeExRVUZTTEVOQlJHZERPenRCUVVkd1F5eFRRVUZQTEV0QlFVc3NUVUZCVEN4RFFVRlpMRkZCUVZVN1FVRkRla0lzVVVGQlJ5eERRVUZETEV0QlFVUXNTVUZCVlN4VFFVRlRMRTlCUVZRc1JVRkJhVUk3UVVGRE1VSXNZMEZCVVN4SlFVRlNMRU5CUkRCQ08wRkJSVEZDTEdGQlFVOHNTMEZCVUN4RFFVWXdRanRMUVVFNVFqczdRVUZMUVN4WFFVRlBMRWxCUVZBc1EwRk9lVUk3UjBGQlZpeERRVUZ1UWl4RFFVaHZRenREUVVGNFF6czdRVUZoUVN4VFFVRlRMRXRCUVZRc1EwRkJaU3hIUVVGbUxFVkJRVzlDTEVkQlFYQkNMRVZCUVhsQ0xFbEJRWHBDTEVWQlFUaENPMEZCUXpGQ0xFMUJRVWtzVDBGQlR5eEhRVUZRTEVOQlJITkNPenRCUVVjeFFpeFBRVUZKTEUxQlFVMHNSVUZCVGl4SlFVRlpMRWxCUVdoQ0xFVkJRWEZDTzBGQlEycENMRmRCUVU4c1NVRkJTU3hGUVVGS0xFVkJRVkVzU1VGQlVpeERRVUZRTEVOQlJHbENPMGRCUVhKQ096dEJRVWxCTEZOQlFVOHNTVUZCVUN4RFFWQXdRanREUVVFNVFqczdRVUZYUVN4VFFVRlRMRXRCUVZRc1EwRkJaU3hIUVVGbUxFVkJRVzlDTEVkQlFYQkNMRVZCUVhsQ0xFbEJRWHBDTEVWQlFUaENPMEZCUXpGQ0xFMUJRVWtzVDBGQlR5eEhRVUZRTEVOQlJITkNPenRCUVVjeFFpeFBRVUZKTEVsQlFVa3NTVUZCU1N4TFFVRkxMRTFCUVV3c1IwRkJZeXhEUVVGa0xFVkJRV2xDTEV0QlFVc3NRMEZCVEN4RlFVRlJMRWRCUVhKRExFVkJRWGxETzBGQlEzSkRMRmRCUVU4c1NVRkJTU3hMUVVGTExFTkJRVXdzUTBGQlNpeEZRVUZoTEVsQlFXSXNRMEZCVUN4RFFVUnhRenRIUVVGNlF6czdRVUZKUVN4VFFVRlBMRWxCUVZBc1EwRlFNRUk3UTBGQk9VSTdPMEZCVlVFc1UwRkJVeXhQUVVGVUxFTkJRV2xDTEVkQlFXcENMRVZCUVhOQ0xFTkJRWFJDTEVWQlFYbENMRk5CUVhwQ0xFVkJRVzFET3p0QlFVVnFReXhQUVVGSkxFbEJRVWtzU1VGQlNTeFZRVUZWTEUxQlFWWXNSMEZCYlVJc1EwRkJia0lzUlVGQmMwSXNTMEZCU3l4RFFVRk1MRVZCUVZFc1IwRkJNVU1zUlVGQk9FTTdRVUZETlVNc1VVRkJSeXhWUVVGVkxFTkJRVllzUlVGQllTeEhRVUZpTEVOQlFXbENMRU5CUVdwQ0xFMUJRWGRDTEVkQlFYaENMRVZCUVRSQ08wRkJRemRDTEdGQlFVOHNWVUZCVlN4RFFVRldMRU5CUVZBc1EwRkVOa0k3UzBGQkwwSTdSMEZFUmpzN1FVRk5RU3hUUVVGUExFdEJRVkFzUTBGU2FVTTdRMEZCYmtNN08wRkJWMEVzVTBGQlV5eFRRVUZVTEVOQlFXMUNMRWRCUVc1Q0xFVkJRWGRDTEVOQlFYaENMRVZCUVRKQ0xGTkJRVE5DTEVWQlFYRkRPenRCUVVWcVF5eFBRVUZKTEVsQlFVa3NTVUZCU1N4VlFVRlZMRTFCUVZZc1IwRkJiVUlzUTBGQmJrSXNSVUZCYzBJc1MwRkJTeXhEUVVGTUxFVkJRVkVzUjBGQk1VTXNSVUZCT0VNN1FVRkRNVU1zVVVGQlJ5eFZRVUZWTEVOQlFWWXNSVUZCWVN4SFFVRmlMRU5CUVdsQ0xFTkJRV3BDTEUxQlFYZENMRWRCUVhoQ0xFVkJRVFJDTzBGQlF6TkNMR0ZCUVU4c1ZVRkJWU3hOUVVGV0xFTkJRV2xDTEVWQlFXcENMRVZCUVhGQ0xFMUJRWEpDTEVOQlFUUkNMRU5CUVRWQ0xFVkJRU3RDTEVOQlFTOUNMRU5CUVZBc1EwRkVNa0k3UzBGQkwwSTdSMEZFU2pzN1FVRk5RU3hUUVVGUExGTkJRVkFzUTBGU2FVTTdRMEZCY2tNN08wRkJWMEVzVTBGQlV5eFJRVUZVTEVOQlFXdENMRWRCUVd4Q0xFVkJRWFZDTEVOQlFYWkNMRVZCUVRCQ0xFbEJRVEZDTEVWQlFXZERMRkZCUVdoRExFVkJRWGxETzBGQlEzSkRMRTlCUVVrc1NVRkJTU3hKUVVGSkxFdEJRVXNzVFVGQlRDeEhRVUZqTEVOQlFXUXNSVUZCYVVJc1MwRkJTeXhEUVVGTUxFVkJRVkVzUjBGQmNrTXNSVUZCZVVNN1FVRkRja01zVVVGQlJ5eExRVUZMTEVOQlFVd3NSVUZCVVN4SFFVRlNMRU5CUVZrc1EwRkJXaXhOUVVGdFFpeEhRVUZ1UWl4RlFVRjFRanRCUVVOMFFpeGhRVUZQTEV0QlFVc3NUVUZCVEN4RFFVRlpMRVZCUVZvc1JVRkJaMElzVFVGQmFFSXNRMEZCZFVJc1EwRkJka0lzUlVGQk1FSXNRMEZCTVVJc1JVRkJOa0lzVVVGQk4wSXNRMEZCVUN4RFFVUnpRanRMUVVFeFFqdEhRVVJLT3p0QlFVMUdMRk5CUVU4c1MwRkJTeXhOUVVGTUxFTkJRVmtzUlVGQldpeEZRVUZuUWl4SlFVRm9RaXhEUVVGeFFpeFJRVUZ5UWl4RFFVRlFMRU5CVUhWRE8wTkJRWHBET3p0QlFWVkJMRk5CUVZNc1UwRkJWQ3hEUVVGdFFpeEhRVUZ1UWl4RlFVRjNRaXhEUVVGNFFpeEZRVUV5UWl4SlFVRXpRaXhGUVVGblF6dEJRVU01UWl4UFFVRkpMRWxCUVVrc1NVRkJTU3hMUVVGTExFMUJRVXdzUjBGQll5eERRVUZrTEVWQlFXbENMRXRCUVVzc1EwRkJUQ3hGUVVGUkxFZEJRWEpETEVWQlFYbERPMEZCUTNaRExGRkJRVWNzUzBGQlN5eERRVUZNTEVWQlFWRXNSMEZCVWl4RFFVRlpMRU5CUVZvc1RVRkJiVUlzUjBGQmJrSXNSVUZCZFVJN1FVRkRlRUlzWVVGQlR5eEpRVUZRTEVOQlJIZENPMHRCUVRGQ08wZEJSRVk3TzBGQlRVRXNVMEZCVHl4TFFVRlFMRU5CVURoQ08wTkJRV2hET3p0QlFWVkJMRk5CUVZNc1QwRkJWQ3hEUVVGcFFpeEhRVUZxUWl4RlFVRnpRaXhEUVVGMFFpeEZRVUY1UWl4SlFVRjZRaXhGUVVFNFFqdEJRVU0xUWl4TlFVRkhMRU5CUVVNc1ZVRkJWU3hIUVVGV0xFVkJRV1VzUTBGQlppeEZRVUZyUWl4SlFVRnNRaXhEUVVGRUxFVkJRWGxDTzBGQlF6RkNMRmRCUVU4c1MwRkJVQ3hEUVVRd1FqdEhRVUUxUWpzN1FVRkpRU3hOUVVGSkxGRkJRVkVzVVVGQlVTeEhRVUZTTEVWQlFXRXNRMEZCWWl4RlFVRm5RaXhKUVVGb1FpeERRVUZTTEVOQlRIZENPenRCUVU4MVFpeFRRVUZQTEVsQlFVa3NTMEZCU2l4RFFVRlZMRTFCUVUwc1IwRkJUaXhEUVVGVkxFTkJRVllzUTBGQlZpeEZRVUYzUWl4TFFVRjRRaXhGUVVFclFpeFZRVUZWTEVkQlFWWXNSVUZCWlN4RFFVRm1MRVZCUVd0Q0xFbEJRV3hDTEVOQlFTOUNMRU5CUVZBc1EwRlFORUk3UTBGQk9VSTdPMEZCVlVFc1UwRkJVeXhWUVVGVUxFTkJRVzlDTEVkQlFYQkNMRVZCUVhsQ0xFTkJRWHBDTEVWQlFUUkNMRWxCUVRWQ0xFVkJRV3RETEZGQlFXeERMRVZCUVRKRE96dEJRVVY2UXl4UFFVRkpMRWxCUVVrc1NVRkJTU3hWUVVGVkxFMUJRVllzUjBGQmJVSXNRMEZCYmtJc1JVRkJjMElzUzBGQlN5eERRVUZNTEVWQlFWRXNSMEZCTVVNc1JVRkJPRU03UVVGRE5VTXNVVUZCUnl4VlFVRlZMRU5CUVZZc1JVRkJZU3hIUVVGaUxFTkJRV2xDTEVOQlFXcENMRTFCUVhkQ0xFZEJRWGhDTEVWQlFUUkNPMEZCUXpkQ0xHRkJRVThzVlVGQlZTeE5RVUZXTEVOQlFXbENMRVZCUVdwQ0xFVkJRWEZDTEUxQlFYSkNMRU5CUVRSQ0xFTkJRVFZDTEVWQlFTdENMRU5CUVM5Q0xFVkJRV3RETEZGQlFXeERMRU5CUVZBc1EwRkVOa0k3UzBGQkwwSTdSMEZFUmpzN1FVRk5RU3hUUVVGUExGTkJRVkFzUTBGU2VVTTdRMEZCTTBNN08wRkJXVUVzVTBGQlV5eFBRVUZVTEVOQlFXbENMRWxCUVdwQ0xFVkJRWE5DTzBGQlEyeENMRk5CUVU4c1MwRkJTeXhOUVVGTUxFTkJRVmtzUlVGQldpeEZRVUZuUWl4UFFVRm9RaXhGUVVGUUxFTkJSR3RDTzBOQlFYUkNPenRCUVVsQkxGTkJRVk1zVTBGQlZDeERRVUZ0UWl4SFFVRnVRaXhGUVVGM1FpeEhRVUY0UWl4RlFVRTBRanRCUVVONFFpeE5RVUZITEU5QlFVOHNaMEpCUVdkQ0xFZEJRV2hDTEVOQlFWQXNSVUZCTkVJN1FVRkRNMElzVjBGQlR5eEpRVUZKTEV0QlFVb3NRMEZCVlN4UFFVRlBMRWRCUVZBc1EwRkJWeXhKUVVGWUxFTkJRVllzUlVGQk5FSXNTVUZCU1N4SFFVRktMRU5CUVRWQ0xFTkJRVkFzUTBGRU1rSTdSMEZCTDBJc1RVRkZTenRCUVVORUxGZEJRVThzVDBGQlR5eEhRVUZRTEVOQlFWY3NUMEZCV0N4RFFVRlFMRU5CUkVNN1IwRkdURHREUVVSS096dEJRVkZCTEZOQlFWTXNUMEZCVkN4RFFVRnBRaXhKUVVGcVFpeEZRVUYxUWl4UFFVRlBMRVZCUVZBc1JVRkJWenRCUVVOb1F5eE5RVUZKTEZkQlFWY3NSVUZCV0N4RFFVUTBRanM3UVVGSGFFTXNUMEZCU1N4SlFVRkpMRU5CUVVvc1NVRkJVeXhKUVVGaUxFVkJRV3RDTzBGQlEyaENMRkZCUVVjc1VVRkJVU3hEUVVGU0xFTkJRVWdzUlVGQll6dEJRVU5hTEdsQ1FVRlhMRk5CUVZNc1RVRkJWQ3hEUVVGblFpeFJRVUZSTEVOQlFWSXNRMEZCYUVJc1EwRkJXQ3hEUVVSWk8wdEJRV1FzVFVGRlN6dEJRVU5JTEdWQlFWTXNTVUZCVkN4RFFVRmpMRU5CUVdRc1JVRkVSenRMUVVaTU8wZEJSRVk3TzBGQlVVRXNVMEZCVHl4UFFVRlBMRTFCUVZBc1EwRkJZeXhUUVVGVExFMUJRVlFzUTBGQlowSXNTVUZCYUVJc1EwRkJaQ3hEUVVGUUxFTkJXR2RETzBOQlFXeERPenRCUVdOQkxGTkJRVk1zVTBGQlZDeERRVUZ0UWl4RFFVRnVRaXhGUVVGelFpeEpRVUYwUWl4RlFVRXlRanRCUVVONlFpeE5RVUZKTEU5QlFVOHNSVUZCVUN4RFFVUnhRanM3UVVGSGVrSXNUMEZCU1N4SlFVRkpMRWxCUVVrc1EwRkJTaXhGUVVGUExFbEJRVWtzUTBGQlNpeEZRVUZQTEVkQlFYUkNMRVZCUVRCQ08wRkJRM2hDTEZOQlFVc3NTVUZCVEN4RFFVRlZMRWxCUVZZc1JVRkVkMEk3UjBGQk1VSTdPMEZCU1VFc1UwRkJUeXhQUVVGUExFMUJRVkFzUTBGQll5eEpRVUZrTEVOQlFWQXNRMEZRZVVJN1EwRkJNMEk3TzBGQlZVRXNVMEZCVXl4UlFVRlVMRU5CUVd0Q0xFZEJRV3hDTEVWQlFYVkNMRWRCUVhaQ0xFVkJRVFJDTEVsQlFUVkNMRVZCUVdsRE8wRkJReTlDTEUxQlFVa3NWVUZCVlN4RlFVRldMRU5CUkRKQ096dEJRVWN2UWl4UFFVRkpMRWxCUVVrc1EwRkJTaXhKUVVGVExFbEJRV0lzUlVGQmEwSTdRVUZEYUVJc1VVRkJTU3hOUVVGTkxFbEJRVWtzUTBGQlNpeEZRVUZQTEVkQlFWQXNRMEZCVGl4RFFVUlpPMEZCUldoQ0xGbEJRVkVzU1VGQlVpeERRVUZoTEVsQlFVa3NSMEZCU2l4RFFVRlJMRU5CUVZJc1EwRkJZaXhGUVVablFqdEJRVWRvUWl4VlFVRk5MRWxCUVVrc1IwRkJTaXhEUVVGUkxFTkJRVklzUTBGQlRpeERRVWhuUWp0SFFVRnNRanM3UVVGUFFTeFRRVUZQTEVsQlFVa3NTMEZCU2l4RFFVRlZMRTlCUVU4c1RVRkJVQ3hEUVVGakxFOUJRV1FzUTBGQlZpeEZRVUZyUXl4SFFVRnNReXhEUVVGUUxFTkJWaXRDTzBOQlFXcERPenRCUVdGQkxGTkJRVk1zVTBGQlZDeERRVUZ0UWl4SFFVRnVRaXhGUVVGM1FpeEpRVUY0UWl4RlFVRTJRanRCUVVNelFpeE5RVUZKTEZWQlFWVXNSVUZCVml4RFFVUjFRanM3UVVGSE0wSXNUMEZCU1N4RFFVRktMRWxCUVZNc1NVRkJWQ3hGUVVGak8wRkJRMW9zVVVGQlNTeFRRVUZUTEVsQlFVa3NRMEZCU2l4RFFVRlVMRU5CUkZFN08wRkJSMW9zVVVGQlJ5eFhRVUZYTEVsQlFWZ3NSVUZCWjBJN1FVRkRha0lzWTBGQlVTeEpRVUZTTEVOQlFXRXNRMEZCWWl4RlFVUnBRanRMUVVGdVFpeE5RVVZOTEVsQlFVY3NhMEpCUVd0Q0xFdEJRV3hDTEVWQlFYZENPMEZCUXk5Q0xHTkJRVkVzU1VGQlVpeERRVUZoTEU5QlFVOHNSMEZCVUN4RFFVRlhMRU5CUVZnc1EwRkJZaXhGUVVRclFqdExRVUV6UWp0SFFVeFNPenRCUVZWQkxGTkJRVThzVDBGQlR5eE5RVUZRTEVOQlFXTXNUMEZCWkN4RFFVRlFMRU5CWWpKQ08wTkJRVGRDT3p0QlFXZENRU3hUUVVGVExGTkJRVlFzUTBGQmJVSXNSMEZCYmtJc1JVRkJkMElzUjBGQmVFSXNSVUZCTmtJc1IwRkJOMElzUlVGQmFVTTdRVUZETDBJc1RVRkJTU3hQUVVGUExFZEJRVkFzUTBGRU1rSTdPMEZCUnk5Q0xFOUJRVWtzU1VGQlNTeERRVUZLTEVsQlFWTXNaMEpCUVdkQ0xFZEJRV2hDTEVOQlFXSXNSVUZCYTBNN1FVRkRhRU1zVjBGQlR5eEpRVUZKTEVOQlFVb3NSVUZCVHl4SlFVRkpMRU5CUVVvc1EwRkJVQ3hGUVVGbExFbEJRV1lzUTBGQlVDeERRVVJuUXp0SFFVRnNRenM3UVVGSlFTeFRRVUZQTEVsQlFWQXNRMEZRSzBJN1EwRkJha003TzBGQlZVRXNVMEZCVXl4alFVRlVMRU5CUVhkQ0xFbEJRWGhDTEVWQlFUWkNPMEZCUXpOQ0xFMUJRVWtzU1VGQlNTeEZRVUZLTEVOQlJIVkNPenRCUVVjelFpeFBRVUZKTEVOQlFVb3NTVUZCVXl4SlFVRlVMRVZCUVdNN1FVRkRXaXhOUVVGRkxFVkJRVVVzUjBGQlJpeERRVUZOTEVOQlFVNHNRMEZCUml4SlFVRmpMRVZCUVVVc1IwRkJSaXhEUVVGTkxFTkJRVTRzUTBGQlpDeERRVVJaTzBkQlFXUTdPMEZCU1VFc1UwRkJUeXhQUVVGUExFMUJRVkFzUTBGQll5eERRVUZrTEVOQlFWQXNRMEZRTWtJN1EwRkJOMEk3TzBGQlZVRXNaVUZCWlR0QlFVTmlMR1ZCUkdFN1FVRkZZaXhQUVVaaE8wRkJSMklzVlVGSVlUdEJRVWxpTEZsQlNtRTdRVUZMWWl4WFFVeGhPMEZCVFdJc1kwRk9ZVHRCUVU5aUxHRkJVR0U3UVVGUllpeFRRVkpoTzBGQlUySXNhVUpCVkdFN1FVRlZZaXh2UWtGV1lUdEJRVmRpTEd0Q1FWaGhPMEZCV1dJc01FSkJXbUU3UVVGaFlpeHhRa0ZpWVR0QlFXTmlMR05CWkdFN1FVRmxZaXhqUVdaaE8wRkJaMEppTEUxQmFFSmhPMEZCYVVKaUxFMUJha0poTzBGQmEwSmlMRXRCYkVKaE8wRkJiVUppTEV0QmJrSmhPMEZCYjBKaUxFdEJjRUpoTzBGQmNVSmlMRTFCY2tKaE8wRkJjMEppTEV0QmRFSmhPMEZCZFVKaUxFOUJka0poTzBGQmQwSmlMRTlCZUVKaE8wRkJlVUppTEd0Q1FYcENZVHRCUVRCQ1lpeFhRVEZDWVR0QlFUSkNZaXhWUVROQ1lUdEJRVFJDWWl4VFFUVkNZVHRCUVRaQ1lpeFRRVGRDWVR0QlFUaENZaXhaUVRsQ1lUdEJRU3RDWWl4VFFTOUNZVHRCUVdkRFlpeFpRV2hEWVR0QlFXbERZaXhYUVdwRFlUdEJRV3REWWl4VFFXeERZVHRCUVcxRFlpeFhRVzVEWVR0QlFXOURZaXhWUVhCRFlUdEJRWEZEWWl4WFFYSkRZVHRCUVhORFlpeFhRWFJEWVR0RFFVRm1JaXdpWm1sc1pTSTZJbXhwWWk5amIzSmxMMloxYm1OMGFXOXVjeTVxY3lJc0luTnZkWEpqWlhORGIyNTBaVzUwSWpwYkltbHRjRzl5ZENCN0lGUjFjR3hsSUgwZ1puSnZiU0FuTGk5d2NtbHRhWFJwZG1Wekp6dGNibWx0Y0c5eWRDQkNhWFJUZEhKcGJtY2dabkp2YlNBbkxpOWlhWFJmYzNSeWFXNW5KenRjYm1sdGNHOXlkQ0JRWVhSMFpYSnVjeUJtY205dElDY3VMM0JoZEhSbGNtNXpKenRjYm1sdGNHOXlkQ0JRY205MGIyTnZiQ0JtY205dElDY3VMM0J5YjNSdlkyOXNKenRjYmx4dVpuVnVZM1JwYjI0Z1kyRnNiRjl3Y205d1pYSjBlU2hwZEdWdExDQndjbTl3WlhKMGVTbDdYRzRnSUd4bGRDQndjbTl3SUQwZ2JuVnNiRHRjYmx4dUlDQnBaaWgwZVhCbGIyWWdhWFJsYlNBOVBUMGdYQ0p1ZFcxaVpYSmNJaUI4ZkNCMGVYQmxiMllnYVhSbGJTQTlQVDBnWENKemVXMWliMnhjSWlCOGZDQjBlWEJsYjJZZ2FYUmxiU0E5UFQwZ1hDSmliMjlzWldGdVhDSWdmSHdnZEhsd1pXOW1JR2wwWlcwZ1BUMDlJRndpYzNSeWFXNW5YQ0lwZTF4dUlDQWdJR2xtS0dsMFpXMWJjSEp2Y0dWeWRIbGRJQ0U5UFNCMWJtUmxabWx1WldRcGUxeHVJQ0FnSUNBZ2NISnZjQ0E5SUhCeWIzQmxjblI1TzF4dUlDQWdJSDFsYkhObElHbG1LR2wwWlcxYlUzbHRZbTlzTG1admNpaHdjbTl3WlhKMGVTbGRJQ0U5UFNCMWJtUmxabWx1WldRcGUxeHVJQ0FnSUNBZ2NISnZjQ0E5SUZONWJXSnZiQzVtYjNJb2NISnZjR1Z5ZEhrcE8xeHVJQ0FnSUgxY2JpQWdmU0JsYkhObElIdGNiaUFnSUNCcFppaHdjbTl3WlhKMGVTQnBiaUJwZEdWdEtYdGNiaUFnSUNBZ0lIQnliM0FnUFNCd2NtOXdaWEowZVR0Y2JpQWdJQ0I5Wld4elpTQnBaaWhUZVcxaWIyd3VabTl5S0hCeWIzQmxjblI1S1NCcGJpQnBkR1Z0S1h0Y2JpQWdJQ0FnSUhCeWIzQWdQU0JUZVcxaWIyd3VabTl5S0hCeWIzQmxjblI1S1R0Y2JpQWdJQ0I5WEc0Z0lIMWNibHh1SUNCcFppaHdjbTl3SUQwOVBTQnVkV3hzS1h0Y2JpQWdJQ0IwYUhKdmR5QnVaWGNnUlhKeWIzSW9ZRkJ5YjNCbGNuUjVJQ1I3SUhCeWIzQmxjblI1SUgwZ2JtOTBJR1p2ZFc1a0lHbHVJQ1I3SUdsMFpXMGdmV0FwT3lCY2JpQWdmVnh1WEc0Z0lHbG1LR2wwWlcxYmNISnZjRjBnYVc1emRHRnVZMlZ2WmlCR2RXNWpkR2x2YmlsN1hHNGdJQ0FnY21WMGRYSnVJR2wwWlcxYmNISnZjRjBvS1R0Y2JpQWdmV1ZzYzJWN1hHNGdJQ0FnY21WMGRYSnVJR2wwWlcxYmNISnZjRjA3WEc0Z0lIMWNibjFjYmx4dVpuVnVZM1JwYjI0Z1lYQndiSGtvTGk0dVlYSm5jeWw3WEc0Z0lHbG1LR0Z5WjNNdWJHVnVaM1JvSUQwOVBTQXlLWHRjYmlBZ0lDQmhjbWR6V3pCZExtRndjR3g1S0c1MWJHd3NJR0Z5WjNNdWMyeHBZMlVvTVNrcE8xeHVJQ0I5Wld4elpYdGNiaUFnSUNCaGNtZHpXekJkVzJGeVozTmJNVjFkTG1Gd2NHeDVLRzUxYkd3c0lHRnlaM011YzJ4cFkyVW9NaWtwTzF4dUlDQjlYRzU5WEc1Y2JtWjFibU4wYVc5dUlHTnZiblJoYVc1ektHeGxablFzSUhKcFoyaDBLWHRjYmlBZ1ptOXlLR3hsZENCNElHOW1JSEpwWjJoMEtYdGNiaUFnSUNCcFppaFFZWFIwWlhKdWN5NXRZWFJqYUY5dWIxOTBhSEp2ZHloc1pXWjBMQ0I0S1NBaFBTQnVkV3hzS1h0Y2JpQWdJQ0FnSUhKbGRIVnliaUIwY25WbE8xeHVJQ0FnSUgxY2JpQWdmVnh1WEc0Z0lISmxkSFZ5YmlCbVlXeHpaVHRjYm4xY2JseHVablZ1WTNScGIyNGdaMlYwWDJkc2IySmhiQ2dwZTF4dUlDQnBaaWgwZVhCbGIyWW9jMlZzWmlrZ0lUMDlJRndpZFc1a1pXWnBibVZrWENJcGUxeHVJQ0FnSUhKbGRIVnliaUJ6Wld4bU8xeHVJQ0I5Wld4elpTQnBaaWgwZVhCbGIyWW9kMmx1Wkc5M0tTQWhQVDBnWENKMWJtUmxabWx1WldSY0lpbDdYRzRnSUNBZ2NtVjBkWEp1SUhkcGJtUnZkenRjYmlBZ2ZXVnNjMlVnYVdZb2RIbHdaVzltS0dkc2IySmhiQ2tnSVQwOUlGd2lkVzVrWldacGJtVmtYQ0lwZTF4dUlDQWdJSEpsZEhWeWJpQm5iRzlpWVd3N1hHNGdJSDFjYmx4dUlDQjBhSEp2ZHlCdVpYY2dSWEp5YjNJb1hDSk9ieUJuYkc5aVlXd2djM1JoZEdVZ1ptOTFibVJjSWlrN1hHNTlYRzVjYm1aMWJtTjBhVzl1SUdSbFpuTjBjblZqZENoa1pXWmhkV3gwY3lsN1hHNGdJSEpsZEhWeWJpQmpiR0Z6Y3lCN1hHNGdJQ0FnWTI5dWMzUnlkV04wYjNJb2RYQmtZWFJsSUQwZ2UzMHBlMXh1SUNBZ0lDQWdiR1YwSUhSb1pWOTJZV3gxWlhNZ1BTQlBZbXBsWTNRdVlYTnphV2R1S0dSbFptRjFiSFJ6TENCMWNHUmhkR1VwTzF4dUlDQWdJQ0FnVDJKcVpXTjBMbUZ6YzJsbmJpaDBhR2x6TENCMGFHVmZkbUZzZFdWektUdGNiaUFnSUNCOVhHNWNiaUFnSUNCemRHRjBhV01nWTNKbFlYUmxLSFZ3WkdGMFpYTWdQU0I3ZlNsN1hHNGdJQ0FnSUNCc1pYUWdlQ0E5SUc1bGR5QjBhR2x6S0hWd1pHRjBaWE1wTzF4dUlDQWdJQ0FnY21WMGRYSnVJRTlpYW1WamRDNW1jbVZsZW1Vb2VDazdYRzRnSUNBZ2ZWeHVJQ0I5TzF4dWZWeHVYRzVjYm1aMWJtTjBhVzl1SUdSbFptVjRZMlZ3ZEdsdmJpaGtaV1poZFd4MGN5bDdYRzRnSUhKbGRIVnliaUJqYkdGemN5QmxlSFJsYm1SeklFVnljbTl5SUh0Y2JpQWdJQ0JqYjI1emRISjFZM1J2Y2loMWNHUmhkR1VnUFNCN2ZTbDdYRzRnSUNBZ0lDQnNaWFFnYldWemMyRm5aU0E5SUhWd1pHRjBaUzV0WlhOellXZGxJSHg4SUZ3aVhDSTdYRzRnSUNBZ0lDQnpkWEJsY2lodFpYTnpZV2RsS1R0Y2JseHVJQ0FnSUNBZ2JHVjBJSFJvWlY5MllXeDFaWE1nUFNCUFltcGxZM1F1WVhOemFXZHVLR1JsWm1GMWJIUnpMQ0IxY0dSaGRHVXBPMXh1SUNBZ0lDQWdUMkpxWldOMExtRnpjMmxuYmloMGFHbHpMQ0IwYUdWZmRtRnNkV1Z6S1R0Y2JseHVJQ0FnSUNBZ2RHaHBjeTV1WVcxbElEMGdkR2hwY3k1amIyNXpkSEoxWTNSdmNpNXVZVzFsTzF4dUlDQWdJQ0FnZEdocGN5NXRaWE56WVdkbElEMGdiV1Z6YzJGblpUdGNiaUFnSUNBZ0lIUm9hWE5iVTNCbFkybGhiRVp2Y20xekxtRjBiMjBvWENKZlgyVjRZMlZ3ZEdsdmJsOWZYQ0lwWFNBOUlIUnlkV1U3WEc0Z0lDQWdJQ0JGY25KdmNpNWpZWEIwZFhKbFUzUmhZMnRVY21GalpTaDBhR2x6TENCMGFHbHpMbU52Ym5OMGNuVmpkRzl5TG01aGJXVXBPMXh1SUNBZ0lIMWNibHh1SUNBZ0lITjBZWFJwWXlCamNtVmhkR1VvZFhCa1lYUmxjeUE5SUh0OUtYdGNiaUFnSUNBZ0lHeGxkQ0I0SUQwZ2JtVjNJSFJvYVhNb2RYQmtZWFJsY3lrN1hHNGdJQ0FnSUNCeVpYUjFjbTRnVDJKcVpXTjBMbVp5WldWNlpTaDRLVHRjYmlBZ0lDQjlYRzRnSUgwN1hHNTlYRzVjYm1aMWJtTjBhVzl1SUdSbFpuQnliM1J2WTI5c0tITndaV01wZTF4dUlDQnlaWFIxY200Z2JtVjNJRkJ5YjNSdlkyOXNLSE53WldNcE8xeHVmVnh1WEc1bWRXNWpkR2x2YmlCa1pXWnBiWEJzS0hCeWIzUnZZMjlzTENCMGVYQmxMQ0JwYlhCc0tYdGNiaUFnY0hKdmRHOWpiMnd1YVcxd2JHVnRaVzUwWVhScGIyNG9kSGx3WlN3Z2FXMXdiQ2s3WEc1OVhHNWNibVoxYm1OMGFXOXVJR2RsZEY5dlltcGxZM1JmYTJWNWN5aHZZbW9wZTF4dUlDQWdJSEpsZEhWeWJpQlBZbXBsWTNRdWEyVjVjeWh2WW1vcExtTnZibU5oZENoUFltcGxZM1F1WjJWMFQzZHVVSEp2Y0dWeWRIbFRlVzFpYjJ4ektHOWlhaWtwTzF4dWZWeHVYRzVtZFc1amRHbHZiaUJwYzE5MllXeHBaRjlqYUdGeVlXTjBaWElvWTI5a1pYQnZhVzUwS1h0Y2JpQWdkSEo1ZTF4dUlDQWdJSEpsZEhWeWJpQlRkSEpwYm1jdVpuSnZiVU52WkdWUWIybHVkQ2hqYjJSbGNHOXBiblFwSUNFOUlHNTFiR3c3WEc0Z0lIMWpZWFJqYUNobEtYdGNiaUFnSUNCeVpYUjFjbTRnWm1Gc2MyVTdYRzRnSUgxY2JuMWNibHh1THk5b2RIUndjem92TDJSbGRtVnNiM0JsY2k1dGIzcHBiR3hoTG05eVp5OWxiaTFWVXk5a2IyTnpMMWRsWWk5QlVFa3ZWMmx1Wkc5M1FtRnpaVFkwTDBKaGMyVTJORjlsYm1OdlpHbHVaMTloYm1SZlpHVmpiMlJwYm1jalUyOXNkWFJwYjI1Zk1sOGxSVElsT0RBbE9UTmZjbVYzY21sMFpWOTBhR1ZmUkU5TmMxOWhkRzlpS0NsZllXNWtYMkowYjJFb0tWOTFjMmx1WjE5S1lYWmhVMk55YVhCMEozTmZWSGx3WldSQmNuSmhlWE5mWVc1a1gxVlVSaTA0WEc1bWRXNWpkR2x2YmlCaU5qUkZibU52WkdWVmJtbGpiMlJsS0hOMGNpa2dlMXh1SUNBZ0lISmxkSFZ5YmlCaWRHOWhLR1Z1WTI5a1pWVlNTVU52YlhCdmJtVnVkQ2h6ZEhJcExuSmxjR3hoWTJVb0x5VW9XekF0T1VFdFJsMTdNbjBwTDJjc0lHWjFibU4wYVc5dUtHMWhkR05vTENCd01Ta2dlMXh1SUNBZ0lDQWdJQ0J5WlhSMWNtNGdVM1J5YVc1bkxtWnliMjFEYUdGeVEyOWtaU2duTUhnbklDc2djREVwTzF4dUlDQWdJSDBwS1R0Y2JuMWNibHh1Wm5WdVkzUnBiMjRnWkdWc1pYUmxYM0J5YjNCbGNuUjVYMlp5YjIxZmJXRndLRzFoY0N3Z2NISnZjR1Z5ZEhrcGUxeHVJQ0FnSUd4bGRDQnVaWGRmYldGd0lEMGdUMkpxWldOMExtRnpjMmxuYmloUFltcGxZM1F1WTNKbFlYUmxLRzFoY0M1amIyNXpkSEoxWTNSdmNpNXdjbTkwYjNSNWNHVXBMQ0J0WVhBcE8xeHVJQ0FnSUdSbGJHVjBaU0J1WlhkZmJXRndXM0J5YjNCbGNuUjVYVHRjYmx4dUlDQnlaWFIxY200Z1QySnFaV04wTG1aeVpXVjZaU2h1WlhkZmJXRndLVHRjYm4xY2JseHVablZ1WTNScGIyNGdZMnhoYzNOZmRHOWZiMkpxS0cxaGNDbDdYRzRnSUNBZ2JHVjBJRzVsZDE5dFlYQWdQU0JQWW1wbFkzUXVZWE56YVdkdUtIdDlMQ0J0WVhBcE8xeHVJQ0J5WlhSMWNtNGdUMkpxWldOMExtWnlaV1Y2WlNodVpYZGZiV0Z3S1R0Y2JuMWNibHh1Wm5WdVkzUnBiMjRnWVdSa1gzQnliM0JsY25SNVgzUnZYMjFoY0NodFlYQXNJSEJ5YjNCbGNuUjVMQ0IyWVd4MVpTbDdYRzRnSUd4bGRDQnVaWGRmYldGd0lEMGdUMkpxWldOMExtRnpjMmxuYmloN2ZTd2diV0Z3S1R0Y2JpQWdibVYzWDIxaGNGdHdjbTl3WlhKMGVWMGdQU0IyWVd4MVpUdGNiaUFnY21WMGRYSnVJRTlpYW1WamRDNW1jbVZsZW1Vb2JtVjNYMjFoY0NrN1hHNTlYRzVjYmx4dVpuVnVZM1JwYjI0Z2RYQmtZWFJsWDIxaGNDaHRZWEFzSUhCeWIzQmxjblI1TENCMllXeDFaU2w3WEc0Z0lDQWdhV1lvY0hKdmNHVnlkSGtnYVc0Z1oyVjBYMjlpYW1WamRGOXJaWGx6S0cxaGNDa3BlMXh1SUNBZ0lDQWdJQ0J5WlhSMWNtNGdZV1JrWDNCeWIzQmxjblI1WDNSdlgyMWhjQ2h0WVhBc0lIQnliM0JsY25SNUxDQjJZV3gxWlNrN1hHNGdJQ0FnZlZ4dVhHNGdJQ0FnZEdoeWIzY2dYQ0p0WVhBZ1pHOWxjeUJ1YjNRZ2FHRjJaU0JyWlhsY0lqdGNibjFjYmx4dVpuVnVZM1JwYjI0Z1ltNXZkQ2hsZUhCeUtYdGNiaUFnY21WMGRYSnVJSDVsZUhCeU8xeHVmVnh1WEc1bWRXNWpkR2x2YmlCaVlXNWtLR3hsWm5Rc0lISnBaMmgwS1h0Y2JpQWdjbVYwZFhKdUlHeGxablFnSmlCeWFXZG9kRHRjYm4xY2JseHVablZ1WTNScGIyNGdZbTl5S0d4bFpuUXNJSEpwWjJoMEtYdGNiaUFnY21WMGRYSnVJR3hsWm5RZ2ZDQnlhV2RvZER0Y2JuMWNibHh1Wm5WdVkzUnBiMjRnWW5Oc0tHeGxablFzSUhKcFoyaDBLWHRjYmlBZ2NtVjBkWEp1SUd4bFpuUWdQRHdnY21sbmFIUTdYRzU5WEc1Y2JtWjFibU4wYVc5dUlHSnpjaWhzWldaMExDQnlhV2RvZENsN1hHNGdJSEpsZEhWeWJpQnNaV1owSUQ0K0lISnBaMmgwTzF4dWZWeHVYRzVtZFc1amRHbHZiaUJpZUc5eUtHeGxablFzSUhKcFoyaDBLWHRjYmlBZ2NtVjBkWEp1SUd4bFpuUWdYaUJ5YVdkb2REdGNibjFjYmx4dVpuVnVZM1JwYjI0Z2VtbHdLR3hwYzNSZmIyWmZiR2x6ZEhNcGUxeHVJQ0JwWmloc2FYTjBYMjltWDJ4cGMzUnpMbXhsYm1kMGFDQTlQVDBnTUNsN1hHNGdJQ0FnY21WMGRYSnVJRTlpYW1WamRDNW1jbVZsZW1Vb1cxMHBPMXh1SUNCOVhHNWNiaUFnYkdWMElHNWxkMTkyWVd4MVpTQTlJRnRkTzF4dUlDQnNaWFFnYzIxaGJHeGxjM1JmYkdWdVozUm9JRDBnYkdsemRGOXZabDlzYVhOMGMxc3dYVHRjYmx4dUlDQm1iM0lvYkdWMElIZ2diMllnYkdsemRGOXZabDlzYVhOMGN5bDdYRzRnSUNBZ2FXWW9lQzVzWlc1bmRHZ2dQQ0J6YldGc2JHVnpkRjlzWlc1bmRHZ3BlMXh1SUNBZ0lDQWdjMjFoYkd4bGMzUmZiR1Z1WjNSb0lEMGdlQzVzWlc1bmRHZzdYRzRnSUNBZ2ZWeHVJQ0I5WEc1Y2JpQWdabTl5S0d4bGRDQnBJRDBnTURzZ2FTQThJSE50WVd4c1pYTjBYMnhsYm1kMGFEc2dhU3NyS1h0Y2JpQWdJQ0JzWlhRZ1kzVnljbVZ1ZEY5MllXeDFaU0E5SUZ0ZE8xeHVJQ0FnSUdadmNpaHNaWFFnYWlBOUlEQTdJR29nUENCc2FYTjBYMjltWDJ4cGMzUnpMbXhsYm1kMGFEc2dhaXNyS1h0Y2JpQWdJQ0FnSUdOMWNuSmxiblJmZG1Gc2RXVXVjSFZ6YUNoc2FYTjBYMjltWDJ4cGMzUnpXMnBkVzJsZEtUdGNiaUFnSUNCOVhHNWNiaUFnSUNCdVpYZGZkbUZzZFdVdWNIVnphQ2h1WlhjZ1ZIVndiR1VvTGk0dVkzVnljbVZ1ZEY5MllXeDFaU2twTzF4dUlDQjlYRzVjYmlBZ2NtVjBkWEp1SUU5aWFtVmpkQzVtY21WbGVtVW9ibVYzWDNaaGJIVmxLVHRjYm4xY2JseHVablZ1WTNScGIyNGdZMkZ1WDJSbFkyOWtaVFkwS0dSaGRHRXBJSHRjYmlBZ2RISjVlMXh1SUNBZ0lHRjBiMklvWkdGMFlTazdYRzRnSUNBZ2NtVjBkWEp1SUhSeWRXVTdYRzRnSUgxallYUmphQ2hsS1h0Y2JpQWdJQ0J5WlhSMWNtNGdabUZzYzJVN1hHNGdJSDFjYm4xY2JseHVablZ1WTNScGIyNGdjbVZ0YjNabFgyWnliMjFmYkdsemRDaHNhWE4wTENCbGJHVnRaVzUwS1h0Y2JpQWdJQ0JzWlhRZ1ptOTFibVFnUFNCbVlXeHpaVHRjYmx4dUlDQWdJSEpsZEhWeWJpQnNhWE4wTG1acGJIUmxjaWdvWld4bGJTa2dQVDRnZTF4dUlDQWdJQ0FnSUNCcFppZ2habTkxYm1RZ0ppWWdaV3hsYlNBOVBUMGdaV3hsYldWdWRDbDdYRzRnSUNBZ0lDQWdJQ0FnSUNCbWIzVnVaQ0E5SUhSeWRXVTdYRzRnSUNBZ0lDQWdJQ0FnSUNCeVpYUjFjbTRnWm1Gc2MyVTdYRzRnSUNBZ0lDQWdJSDFjYmx4dUlDQWdJQ0FnSUNCeVpYUjFjbTRnZEhKMVpUdGNiaUFnSUNCOUtUdGNibjFjYmx4dVpuVnVZM1JwYjI0Z1ptOXNaR3dvWm5WdUxDQmhZMk1zSUd4cGMzUXBlMXh1SUNBZ0lHeGxkQ0JoWTJNeElEMGdZV05qTzF4dVhHNGdJQ0FnWm05eUtHTnZibk4wSUdWc0lHOW1JR3hwYzNRcGUxeHVJQ0FnSUNBZ0lDQmhZMk14SUQwZ1puVnVLR1ZzTENCaFkyTXhLVHRjYmlBZ0lDQjlYRzVjYmlBZ0lDQnlaWFIxY200Z1lXTmpNVHRjYm4xY2JseHVYRzVtZFc1amRHbHZiaUJtYjJ4a2NpaG1kVzRzSUdGall5d2diR2x6ZENsN1hHNGdJQ0FnYkdWMElHRmpZekVnUFNCaFkyTTdYRzVjYmlBZ0lDQm1iM0lvYkdWMElHa2dQU0JzYVhOMExteGxibWQwYUNBdElERTdJR2tnUGowZ01Ec2dhUzB0S1h0Y2JpQWdJQ0FnSUNBZ1lXTmpNU0E5SUdaMWJpaHNhWE4wVzJsZExDQmhZMk14S1R0Y2JpQWdJQ0I5WEc1Y2JpQWdJQ0J5WlhSMWNtNGdZV05qTVR0Y2JuMWNibHh1Wm5WdVkzUnBiMjRnYTJWNVptbHVaQ2hyWlhrc0lHNHNJSFIxY0d4bGJHbHpkQ2w3WEc1Y2JpQWdabTl5S0d4bGRDQnBJRDBnZEhWd2JHVnNhWE4wTG14bGJtZDBhQ0F0SURFN0lHa2dQajBnTURzZ2FTMHRLWHRjYmlBZ0lDQnBaaWgwZFhCc1pXeHBjM1JiYVYwdVoyVjBLRzRwSUQwOVBTQnJaWGtwZTF4dUlDQWdJQ0FnY21WMGRYSnVJSFIxY0d4bGJHbHpkRnRwWFR0Y2JpQWdJQ0I5WEc0Z0lIMWNibHh1SUNCeVpYUjFjbTRnWm1Gc2MyVTdYRzU5WEc1Y2JtWjFibU4wYVc5dUlHdGxlV1JsYkdWMFpTaHJaWGtzSUc0c0lIUjFjR3hsYkdsemRDbDdYRzVjYmlBZ0lDQm1iM0lvYkdWMElHa2dQU0IwZFhCc1pXeHBjM1F1YkdWdVozUm9JQzBnTVRzZ2FTQStQU0F3T3lCcExTMHBlMXh1SUNBZ0lDQWdJQ0JwWmloMGRYQnNaV3hwYzNSYmFWMHVaMlYwS0c0cElEMDlQU0JyWlhrcGUxeHVJQ0FnSUNBZ0lDQWdJQ0FnY21WMGRYSnVJSFIxY0d4bGJHbHpkQzVqYjI1allYUW9XMTBwTG5Od2JHbGpaU2hwTENBeEtUdGNiaUFnSUNBZ0lDQWdmVnh1SUNBZ0lIMWNibHh1SUNBZ0lISmxkSFZ5YmlCMGRYQnNaV3hwYzNRN1hHNTlYRzVjYm1aMWJtTjBhVzl1SUd0bGVYTjBiM0psS0d0bGVTd2diaXdnYkdsemRDd2dibVYzZEhWd2JHVXBlMXh1SUNBZ0lHWnZjaWhzWlhRZ2FTQTlJR3hwYzNRdWJHVnVaM1JvSUMwZ01Uc2dhU0ErUFNBd095QnBMUzBwZTF4dUlDQWdJQ0FnSUNCcFppaHNhWE4wVzJsZExtZGxkQ2h1S1NBOVBUMGdhMlY1S1h0Y2JpQWdJQ0FnSUNBZ0lDQWdJSEpsZEhWeWJpQnNhWE4wTG1OdmJtTmhkQ2hiWFNrdWMzQnNhV05sS0drc0lERXNJRzVsZDNSMWNHeGxLVHRjYmlBZ0lDQWdJQ0FnZlZ4dUlDQWdJSDFjYmx4dUlDQnlaWFIxY200Z2JHbHpkQzVqYjI1allYUW9XMTBwTG5CMWMyZ29ibVYzZEhWd2JHVXBPMXh1ZlZ4dVhHNW1kVzVqZEdsdmJpQnJaWGx0WlcxaVpYSW9hMlY1TENCdUxDQnNhWE4wS1h0Y2JpQWdabTl5S0d4bGRDQnBJRDBnYkdsemRDNXNaVzVuZEdnZ0xTQXhPeUJwSUQ0OUlEQTdJR2t0TFNsN1hHNGdJQ0FnYVdZb2JHbHpkRnRwWFM1blpYUW9iaWtnUFQwOUlHdGxlU2w3WEc0Z0lDQWdJQ0J5WlhSMWNtNGdkSEoxWlR0Y2JpQWdJQ0I5WEc0Z0lIMWNibHh1SUNCeVpYUjFjbTRnWm1Gc2MyVTdYRzU5WEc1Y2JtWjFibU4wYVc5dUlHdGxlWFJoYTJVb2EyVjVMQ0J1TENCc2FYTjBLWHRjYmlBZ2FXWW9JV3RsZVcxbGJXSmxjaWhyWlhrc0lHNHNJR3hwYzNRcEtYdGNiaUFnSUNCeVpYUjFjbTRnWm1Gc2MyVTdYRzRnSUgxY2JseHVJQ0JzWlhRZ2RIVndiR1VnUFNCclpYbG1hVzVrS0d0bGVTd2diaXdnYkdsemRDazdYRzVjYmlBZ2NtVjBkWEp1SUc1bGR5QlVkWEJzWlNoMGRYQnNaUzVuWlhRb2Jpa3NJSFIxY0d4bExDQnJaWGxrWld4bGRHVW9hMlY1TENCdUxDQnNhWE4wS1NrN1hHNTlYRzVjYm1aMWJtTjBhVzl1SUd0bGVYSmxjR3hoWTJVb2EyVjVMQ0J1TENCc2FYTjBMQ0J1WlhkMGRYQnNaU2w3WEc0Z0lGeHVJQ0JtYjNJb2JHVjBJR2tnUFNCMGRYQnNaV3hwYzNRdWJHVnVaM1JvSUMwZ01Uc2dhU0ErUFNBd095QnBMUzBwZTF4dUlDQWdJR2xtS0hSMWNHeGxiR2x6ZEZ0cFhTNW5aWFFvYmlrZ1BUMDlJR3RsZVNsN1hHNGdJQ0FnSUNCeVpYUjFjbTRnZEhWd2JHVnNhWE4wTG1OdmJtTmhkQ2hiWFNrdWMzQnNhV05sS0drc0lERXNJRzVsZDNSMWNHeGxLVHRjYmlBZ0lDQjlYRzRnSUgxY2JseHVJQ0J5WlhSMWNtNGdkSFZ3YkdWc2FYTjBPMXh1ZlZ4dVhHNWNibVoxYm1OMGFXOXVJSEpsZG1WeWMyVW9iR2x6ZENsN1hHNGdJQ0FnY21WMGRYSnVJR3hwYzNRdVkyOXVZMkYwS0Z0ZEtTNXlaWFpsY25ObEtDazdYRzU5WEc1Y2JtWjFibU4wYVc5dUlHMWhjSE5mWm1sdVpDaHJaWGtzSUcxaGNDbDdYRzRnSUNBZ2FXWW9hMlY1SUdsdUlHZGxkRjl2WW1wbFkzUmZhMlY1Y3lodFlYQXBLWHRjYmlBZ0lDQWdJQ0FnY21WMGRYSnVJRzVsZHlCVWRYQnNaU2hUZVcxaWIyd3VabTl5S0Z3aWIydGNJaWtzSUcxaGNGdHJaWGxkS1R0Y2JpQWdJQ0I5Wld4elpYdGNiaUFnSUNBZ0lDQWdjbVYwZFhKdUlGTjViV0p2YkM1bWIzSW9YQ0psY25KdmNsd2lLVHRjYmlBZ0lDQjlYRzU5WEc1Y2JtWjFibU4wYVc5dUlHWnNZWFIwWlc0b2JHbHpkQ3dnZEdGcGJDQTlJRnRkS1NCN1hHNGdJR3hsZENCdVpYZGZiR2x6ZENBOUlGdGRPMXh1WEc0Z0lHWnZjaWhzWlhRZ1pTQnZaaUJzYVhOMEtYdGNiaUFnSUNCcFppaHBjMEZ5Y21GNUtHVXBLWHRjYmlBZ0lDQWdJRzVsZDE5c2FYTjBJRDBnYm1WM1gyeHBjM1F1WTI5dVkyRjBLR1pzWVhSMFpXNG9aU2twTzF4dUlDQWdJSDFsYkhObGUxeHVJQ0FnSUNBZ2JtVjNYMnhwYzNRdWNIVnphQ2hsS1R0Y2JpQWdJQ0I5WEc0Z0lIMWNibHh1SUNCeVpYUjFjbTRnVDJKcVpXTjBMbVp5WldWNlpTaHVaWGRmYkdsemRDNWpiMjVqWVhRb2RHRnBiQ2twTzF4dWZWeHVYRzVtZFc1amRHbHZiaUJrZFhCc2FXTmhkR1VvYml3Z1pXeGxiU2w3WEc0Z0lHeGxkQ0JzYVhOMElEMGdXMTA3WEc1Y2JpQWdabTl5S0d4bGRDQnBJRDBnTURzZ2FTQThJRzQ3SUdrckt5bDdYRzRnSUNBZ2JHbHpkQzV3ZFhOb0tHVnNaVzBwTzF4dUlDQjlYRzVjYmlBZ2NtVjBkWEp1SUU5aWFtVmpkQzVtY21WbGVtVW9iR2x6ZENrN1hHNTlYRzVjYm1aMWJtTjBhVzl1SUcxaGNHWnZiR1JzS0daMWJpd2dZV05qTENCc2FYTjBLWHRjYmlBZ2JHVjBJRzVsZDJ4cGMzUWdQU0JiWFR0Y2JseHVJQ0JtYjNJb2JHVjBJSGdnYjJZZ2JHbHpkQ2w3WEc0Z0lDQWdiR1YwSUhSMWNDQTlJR1oxYmloNExDQmhZMk1wTzF4dUlDQWdJRzVsZDJ4cGMzUXVjSFZ6YUNoMGRYQXVaMlYwS0RBcEtUdGNiaUFnSUNCaFkyTWdQU0IwZFhBdVoyVjBLREVwTzF4dUlDQjlYRzVjYmx4dUlDQnlaWFIxY200Z2JtVjNJRlIxY0d4bEtFOWlhbVZqZEM1bWNtVmxlbVVvYm1WM2JHbHpkQ2tzSUdGall5azdYRzU5WEc1Y2JtWjFibU4wYVc5dUlHWnBiSFJsY20xaGNDaG1kVzRzSUd4cGMzUXBlMXh1SUNCc1pYUWdibVYzYkdsemRDQTlJRnRkTzF4dVhHNGdJR1p2Y2loNElHOW1JR3hwYzNRcGUxeHVJQ0FnSUd4bGRDQnlaWE4xYkhRZ1BTQm1kVzRvZUNrN1hHNWNiaUFnSUNCcFppaHlaWE4xYkhRZ1BUMDlJSFJ5ZFdVcGUxeHVJQ0FnSUNBZ2JtVjNiR2x6ZEM1d2RYTm9LSGdwTzF4dUlDQWdJSDFsYkhObElHbG1LSEpsYzNWc2RDQnBibk4wWVc1alpXOW1JRlIxY0d4bEtYdGNiaUFnSUNBZ0lHNWxkMnhwYzNRdWNIVnphQ2h5WlhOMWJIUXVaMlYwS0RFcEtUdGNiaUFnSUNCOVhHNGdJSDFjYmx4dUlDQnlaWFIxY200Z1QySnFaV04wTG1aeVpXVjZaU2h1Wlhkc2FYTjBLVHRjYm4xY2JseHVablZ1WTNScGIyNGdiV0Z3YzE5bWIyeGtLR1oxYml3Z1lXTmpMQ0J0WVhBcGUxeHVJQ0JzWlhRZ1lXTmpNU0E5SUdGall6dGNibHh1SUNCbWIzSW9iR1YwSUdzZ2IyWWdaMlYwWDI5aWFtVmpkRjlyWlhsektHMWhjQ2twZTF4dUlDQWdJR0ZqWXpFZ1BTQm1kVzRvYXl3Z2JXRndXMnRkTENCaFkyTXhLVHRjYmlBZ2ZWeHVYRzRnSUhKbGRIVnliaUJoWTJNeE8xeHVmVnh1WEc1bWRXNWpkR2x2YmlCdFlYQnpYMlp5YjIxZmJHbHpkQ2hzYVhOMEtYdGNiaUFnYkdWMElHMGdQU0I3ZlR0Y2JseHVJQ0JtYjNJb2VDQnZaaUJzYVhOMEtYdGNiaUFnSUNCdFczZ3VaMlYwS0RBcFhTQTlJSGd1WjJWMEtERXBPMXh1SUNCOVhHNWNiaUFnY21WMGRYSnVJRTlpYW1WamRDNW1jbVZsZW1Vb2JTazdYRzU5WEc1Y2JtVjRjRzl5ZENCa1pXWmhkV3gwSUh0Y2JpQWdZMkZzYkY5d2NtOXdaWEowZVN4Y2JpQWdZWEJ3Ykhrc1hHNGdJR052Ym5SaGFXNXpMRnh1SUNCblpYUmZaMnh2WW1Gc0xGeHVJQ0JrWldaemRISjFZM1FzWEc0Z0lHUmxabVY0WTJWd2RHbHZiaXhjYmlBZ1pHVm1jSEp2ZEc5amIyd3NYRzRnSUdSbFptbHRjR3dzWEc0Z0lHZGxkRjl2WW1wbFkzUmZhMlY1Y3l4Y2JpQWdhWE5mZG1Gc2FXUmZZMmhoY21GamRHVnlMRnh1SUNCaU5qUkZibU52WkdWVmJtbGpiMlJsTEZ4dUlDQmtaV3hsZEdWZmNISnZjR1Z5ZEhsZlpuSnZiVjl0WVhBc1hHNGdJR0ZrWkY5d2NtOXdaWEowZVY5MGIxOXRZWEFzWEc0Z0lHTnNZWE56WDNSdlgyOWlhaXhjYmlBZ1kyRnVYMlJsWTI5a1pUWTBMRnh1SUNCaWJtOTBMRnh1SUNCaVlXNWtMRnh1SUNCaWIzSXNYRzRnSUdKemJDeGNiaUFnWW5OeUxGeHVJQ0JpZUc5eUxGeHVJQ0I2YVhBc1hHNGdJR1p2YkdSc0xGeHVJQ0JtYjJ4a2NpeGNiaUFnY21WdGIzWmxYMlp5YjIxZmJHbHpkQ3hjYmlBZ2EyVjVaR1ZzWlhSbExGeHVJQ0JyWlhsemRHOXlaU3hjYmlBZ2EyVjVabWx1WkN4Y2JpQWdhMlY1ZEdGclpTeGNiaUFnYTJWNWNtVndiR0ZqWlN4Y2JpQWdjbVYyWlhKelpTeGNiaUFnZFhCa1lYUmxYMjFoY0N4Y2JpQWdiV0Z3YzE5bWFXNWtMRnh1SUNCbWJHRjBkR1Z1TEZ4dUlDQmtkWEJzYVdOaGRHVXNYRzRnSUcxaGNHWnZiR1JzTEZ4dUlDQm1hV3gwWlhKdFlYQXNYRzRnSUcxaGNITmZabTlzWkZ4dWZUdGNiaUpkTENKemIzVnlZMlZTYjI5MElqb2lMM052ZFhKalpTOGlmUT09XG4iLCJpbXBvcnQgQml0U3RyaW5nIGZyb20gJy4vYml0X3N0cmluZyc7XG5pbXBvcnQgUGF0dGVybnMgZnJvbSAnLi9wYXR0ZXJucyc7XG5pbXBvcnQgeyBUdXBsZSB9IGZyb20gJy4vcHJpbWl0aXZlcyc7XG5cbmZ1bmN0aW9uIF9jYXNlKGNvbmRpdGlvbiwgY2xhdXNlcykge1xuICByZXR1cm4gUGF0dGVybnMuZGVmbWF0Y2goLi4uY2xhdXNlcykoY29uZGl0aW9uKTtcbn1cblxuZnVuY3Rpb24gY29uZChjbGF1c2VzKSB7XG4gIGZvciAobGV0IGNsYXVzZSBvZiBjbGF1c2VzKSB7XG4gICAgaWYgKGNsYXVzZVswXSkge1xuICAgICAgcmV0dXJuIGNsYXVzZVsxXSgpO1xuICAgIH1cbiAgfVxuXG4gIHRocm93IG5ldyBFcnJvcigpO1xufVxuXG5mdW5jdGlvbiBtYXBfdXBkYXRlKG1hcCwgdmFsdWVzKSB7XG4gIHJldHVybiBPYmplY3QuZnJlZXplKE9iamVjdC5hc3NpZ24oT2JqZWN0LmNyZWF0ZShtYXAuY29uc3RydWN0b3IucHJvdG90eXBlKSwgbWFwLCB2YWx1ZXMpKTtcbn1cblxuZnVuY3Rpb24gX2Zvcihjb2xsZWN0aW9ucywgZnVuLCBmaWx0ZXIgPSAoKSA9PiB0cnVlLCBpbnRvID0gW10sIHByZXZpb3VzVmFsdWVzID0gW10pIHtcbiAgbGV0IHBhdHRlcm4gPSBjb2xsZWN0aW9uc1swXVswXTtcbiAgbGV0IGNvbGxlY3Rpb24gPSBjb2xsZWN0aW9uc1swXVsxXTtcblxuICBpZiAoY29sbGVjdGlvbnMubGVuZ3RoID09PSAxKSB7XG4gICAgaWYgKGNvbGxlY3Rpb24gaW5zdGFuY2VvZiBCaXRTdHJpbmcpIHtcbiAgICAgIGxldCBic1NsaWNlID0gY29sbGVjdGlvbi5zbGljZSgwLCBwYXR0ZXJuLmJ5dGVfc2l6ZSgpKTtcbiAgICAgIGxldCBpID0gMTtcblxuICAgICAgd2hpbGUgKGJzU2xpY2UuYnl0ZV9zaXplID09IHBhdHRlcm4uYnl0ZV9zaXplKCkpIHtcbiAgICAgICAgbGV0IHIgPSBQYXR0ZXJucy5tYXRjaF9ub190aHJvdyhwYXR0ZXJuLCBic1NsaWNlKTtcbiAgICAgICAgbGV0IGFyZ3MgPSBwcmV2aW91c1ZhbHVlcy5jb25jYXQocik7XG5cbiAgICAgICAgaWYgKHIgJiYgZmlsdGVyLmFwcGx5KHRoaXMsIGFyZ3MpKSB7XG4gICAgICAgICAgaW50byA9IGludG8uY29uY2F0KFtmdW4uYXBwbHkodGhpcywgYXJncyldKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGJzU2xpY2UgPSBjb2xsZWN0aW9uLnNsaWNlKHBhdHRlcm4uYnl0ZV9zaXplKCkgKiBpLCBwYXR0ZXJuLmJ5dGVfc2l6ZSgpICogKGkgKyAxKSk7XG4gICAgICAgIGkrKztcbiAgICAgIH1cblxuICAgICAgcmV0dXJuIGludG87XG4gICAgfSBlbHNlIHtcbiAgICAgIGZvciAobGV0IGVsZW0gb2YgY29sbGVjdGlvbikge1xuICAgICAgICBsZXQgciA9IFBhdHRlcm5zLm1hdGNoX25vX3Rocm93KHBhdHRlcm4sIGVsZW0pO1xuICAgICAgICBsZXQgYXJncyA9IHByZXZpb3VzVmFsdWVzLmNvbmNhdChyKTtcblxuICAgICAgICBpZiAociAmJiBmaWx0ZXIuYXBwbHkodGhpcywgYXJncykpIHtcbiAgICAgICAgICBpbnRvID0gaW50by5jb25jYXQoW2Z1bi5hcHBseSh0aGlzLCBhcmdzKV0pO1xuICAgICAgICB9XG4gICAgICB9XG5cbiAgICAgIHJldHVybiBpbnRvO1xuICAgIH1cbiAgfSBlbHNlIHtcbiAgICBsZXQgX2ludG8gPSBbXTtcblxuICAgIGlmIChjb2xsZWN0aW9uIGluc3RhbmNlb2YgQml0U3RyaW5nKSB7XG4gICAgICBsZXQgYnNTbGljZSA9IGNvbGxlY3Rpb24uc2xpY2UoMCwgcGF0dGVybi5ieXRlX3NpemUoKSk7XG4gICAgICBsZXQgaSA9IDE7XG5cbiAgICAgIHdoaWxlIChic1NsaWNlLmJ5dGVfc2l6ZSA9PSBwYXR0ZXJuLmJ5dGVfc2l6ZSgpKSB7XG4gICAgICAgIGxldCByID0gUGF0dGVybnMubWF0Y2hfbm9fdGhyb3cocGF0dGVybiwgYnNTbGljZSk7XG4gICAgICAgIGlmIChyKSB7XG4gICAgICAgICAgX2ludG8gPSBpbnRvLmNvbmNhdCh0aGlzLl9mb3IoY29sbGVjdGlvbnMuc2xpY2UoMSksIGZ1biwgZmlsdGVyLCBfaW50bywgcHJldmlvdXNWYWx1ZXMuY29uY2F0KHIpKSk7XG4gICAgICAgIH1cblxuICAgICAgICBic1NsaWNlID0gY29sbGVjdGlvbi5zbGljZShwYXR0ZXJuLmJ5dGVfc2l6ZSgpICogaSwgcGF0dGVybi5ieXRlX3NpemUoKSAqIChpICsgMSkpO1xuICAgICAgICBpKys7XG4gICAgICB9XG4gICAgfSBlbHNlIHtcbiAgICAgIGZvciAobGV0IGVsZW0gb2YgY29sbGVjdGlvbikge1xuICAgICAgICBsZXQgciA9IFBhdHRlcm5zLm1hdGNoX25vX3Rocm93KHBhdHRlcm4sIGVsZW0pO1xuICAgICAgICBpZiAocikge1xuICAgICAgICAgIF9pbnRvID0gaW50by5jb25jYXQodGhpcy5fZm9yKGNvbGxlY3Rpb25zLnNsaWNlKDEpLCBmdW4sIGZpbHRlciwgX2ludG8sIHByZXZpb3VzVmFsdWVzLmNvbmNhdChyKSkpO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgfVxuXG4gICAgcmV0dXJuIF9pbnRvO1xuICB9XG59XG5cbmZ1bmN0aW9uIF90cnkoZG9fZnVuLCByZXNjdWVfZnVuY3Rpb24sIGNhdGNoX2Z1biwgZWxzZV9mdW5jdGlvbiwgYWZ0ZXJfZnVuY3Rpb24pIHtcbiAgbGV0IHJlc3VsdCA9IG51bGw7XG5cbiAgdHJ5IHtcbiAgICByZXN1bHQgPSBkb19mdW4oKTtcbiAgfSBjYXRjaCAoZSkge1xuICAgIGxldCBleF9yZXN1bHQgPSBudWxsO1xuXG4gICAgaWYgKHJlc2N1ZV9mdW5jdGlvbikge1xuICAgICAgdHJ5IHtcbiAgICAgICAgZXhfcmVzdWx0ID0gcmVzY3VlX2Z1bmN0aW9uKGUpO1xuICAgICAgICByZXR1cm4gZXhfcmVzdWx0O1xuICAgICAgfSBjYXRjaCAoZXgpIHtcbiAgICAgICAgaWYgKGV4IGluc3RhbmNlb2YgUGF0dGVybnMuTWF0Y2hFcnJvcikge1xuICAgICAgICAgIHRocm93IGV4O1xuICAgICAgICB9XG4gICAgICB9XG4gICAgfVxuXG4gICAgaWYgKGNhdGNoX2Z1bikge1xuICAgICAgdHJ5IHtcbiAgICAgICAgZXhfcmVzdWx0ID0gY2F0Y2hfZnVuKGUpO1xuICAgICAgICByZXR1cm4gZXhfcmVzdWx0O1xuICAgICAgfSBjYXRjaCAoZXgpIHtcbiAgICAgICAgaWYgKGV4IGluc3RhbmNlb2YgUGF0dGVybnMuTWF0Y2hFcnJvcikge1xuICAgICAgICAgIHRocm93IGV4O1xuICAgICAgICB9XG4gICAgICB9XG4gICAgfVxuXG4gICAgdGhyb3cgZTtcbiAgfSBmaW5hbGx5IHtcbiAgICBpZiAoYWZ0ZXJfZnVuY3Rpb24pIHtcbiAgICAgIGFmdGVyX2Z1bmN0aW9uKCk7XG4gICAgfVxuICB9XG5cbiAgaWYgKGVsc2VfZnVuY3Rpb24pIHtcbiAgICB0cnkge1xuICAgICAgcmV0dXJuIGVsc2VfZnVuY3Rpb24ocmVzdWx0KTtcbiAgICB9IGNhdGNoIChleCkge1xuICAgICAgaWYgKGV4IGluc3RhbmNlb2YgUGF0dGVybnMuTWF0Y2hFcnJvcikge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoXCJObyBNYXRjaCBGb3VuZCBpbiBFbHNlXCIpO1xuICAgICAgfVxuXG4gICAgICB0aHJvdyBleDtcbiAgICB9XG4gIH0gZWxzZSB7XG4gICAgcmV0dXJuIHJlc3VsdDtcbiAgfVxufVxuXG5mdW5jdGlvbiBfd2l0aCguLi5hcmdzKSB7XG4gIGxldCBhcmdzVG9QYXNzID0gW107XG5cbiAgZm9yIChsZXQgaSA9IDA7IGkgPCBhcmdzLmxlbmd0aDsgaSsrKSB7XG4gICAgaWYgKGkgPT09IGFyZ3MubGVuZ3RoIC0gMSkge1xuICAgICAgcmV0dXJuIGFyZ3NbaV0uYXBwbHkobnVsbCwgYXJnc1RvUGFzcyk7XG4gICAgfSBlbHNlIHtcbiAgICAgIGxldCBbcGF0dGVybiwgZnVuY10gPSBhcmdzW2ldO1xuXG4gICAgICBsZXQgcmVzdWx0ID0gZnVuYy5hcHBseShudWxsLCBhcmdzVG9QYXNzKTtcblxuICAgICAgbGV0IHBhdHRlcm5SZXN1bHQgPSBQYXR0ZXJucy5tYXRjaF9ub190aHJvdyhwYXR0ZXJuLCByZXN1bHQpO1xuXG4gICAgICBpZiAocGF0dGVyblJlc3VsdCA9PSBudWxsKSB7XG4gICAgICAgIHJldHVybiByZXN1bHQ7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBhcmdzVG9QYXNzID0gYXJnc1RvUGFzcy5jb25jYXQocGF0dGVyblJlc3VsdCk7XG4gICAgICB9XG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIG51bGw7XG59XG5cbmV4cG9ydCBkZWZhdWx0IHtcbiAgX2Nhc2UsXG4gIGNvbmQsXG4gIG1hcF91cGRhdGUsXG4gIF9mb3IsXG4gIF90cnksXG4gIF93aXRoXG59O1xuLy8jIHNvdXJjZU1hcHBpbmdVUkw9ZGF0YTphcHBsaWNhdGlvbi9qc29uO2Jhc2U2NCxleUoyWlhKemFXOXVJam96TENKemIzVnlZMlZ6SWpwYklteHBZaTlqYjNKbEwzTndaV05wWVd4ZlptOXliWE11YW5NaVhTd2libUZ0WlhNaU9sdGRMQ0p0WVhCd2FXNW5jeUk2SWtGQlFVRXNUMEZCVHl4VFFVRlFMRTFCUVhOQ0xHTkJRWFJDTzBGQlEwRXNUMEZCVHl4UlFVRlFMRTFCUVhGQ0xGbEJRWEpDTzBGQlEwRXNVMEZCVXl4TFFVRlVMRkZCUVhOQ0xHTkJRWFJDT3p0QlFVVkJMRk5CUVZNc1MwRkJWQ3hEUVVGbExGTkJRV1lzUlVGQk1FSXNUMEZCTVVJc1JVRkJhME03UVVGRGFFTXNVMEZCVHl4VFFVRlRMRkZCUVZRc1EwRkJhMElzUjBGQlJ5eFBRVUZJTEVOQlFXeENMRU5CUVRoQ0xGTkJRVGxDTEVOQlFWQXNRMEZFWjBNN1EwRkJiRU03TzBGQlNVRXNVMEZCVXl4SlFVRlVMRU5CUVdNc1QwRkJaQ3hGUVVGelFqdEJRVU53UWl4UFFVRkpMRWxCUVVrc1RVRkJTaXhKUVVGakxFOUJRV3hDTEVWQlFUQkNPMEZCUTNoQ0xGRkJRVWNzVDBGQlR5eERRVUZRTEVOQlFVZ3NSVUZCWVR0QlFVTllMR0ZCUVU4c1QwRkJUeXhEUVVGUUxFZEJRVkFzUTBGRVZ6dExRVUZpTzBkQlJFWTdPMEZCVFVFc1VVRkJUU3hKUVVGSkxFdEJRVW9zUlVGQlRpeERRVkJ2UWp0RFFVRjBRanM3UVVGVlFTeFRRVUZUTEZWQlFWUXNRMEZCYjBJc1IwRkJjRUlzUlVGQmVVSXNUVUZCZWtJc1JVRkJaME03UVVGRE9VSXNVMEZCVHl4UFFVRlBMRTFCUVZBc1EwRkRUQ3hQUVVGUExFMUJRVkFzUTBGRFJTeFBRVUZQTEUxQlFWQXNRMEZCWXl4SlFVRkpMRmRCUVVvc1EwRkJaMElzVTBGQmFFSXNRMEZFYUVJc1JVRkRORU1zUjBGRU5VTXNSVUZEYVVRc1RVRkVha1FzUTBGRVN5eERRVUZRTEVOQlJEaENPME5CUVdoRE96dEJRVkZCTEZOQlFWTXNTVUZCVkN4RFFVRmpMRmRCUVdRc1JVRkJNa0lzUjBGQk0wSXNSVUZCWjBNc1UwRkJVeXhOUVVGTkxFbEJRVTRzUlVGQldTeFBRVUZQTEVWQlFWQXNSVUZCVnl4cFFrRkJhVUlzUlVGQmFrSXNSVUZCYjBJN1FVRkRiRVlzVFVGQlNTeFZRVUZWTEZsQlFWa3NRMEZCV2l4RlFVRmxMRU5CUVdZc1EwRkJWaXhEUVVRNFJUdEJRVVZzUml4TlFVRkpMR0ZCUVdFc1dVRkJXU3hEUVVGYUxFVkJRV1VzUTBGQlppeERRVUZpTEVOQlJqaEZPenRCUVVsc1JpeE5RVUZITEZsQlFWa3NUVUZCV2l4TFFVRjFRaXhEUVVGMlFpeEZRVUY1UWp0QlFVTXhRaXhSUVVGSExITkNRVUZ6UWl4VFFVRjBRaXhGUVVGblF6dEJRVU5xUXl4VlFVRkpMRlZCUVZVc1YwRkJWeXhMUVVGWUxFTkJRV2xDTEVOQlFXcENMRVZCUVc5Q0xGRkJRVkVzVTBGQlVpeEZRVUZ3UWl4RFFVRldMRU5CUkRaQ08wRkJSV3BETEZWQlFVa3NTVUZCU1N4RFFVRktMRU5CUmpaQ096dEJRVWxxUXl4aFFVRk5MRkZCUVZFc1UwRkJVaXhKUVVGeFFpeFJRVUZSTEZOQlFWSXNSVUZCY2tJc1JVRkJlVU03UVVGRE4wTXNXVUZCU1N4SlFVRkpMRk5CUVZNc1kwRkJWQ3hEUVVGM1FpeFBRVUY0UWl4RlFVRnBReXhQUVVGcVF5eERRVUZLTEVOQlJIbERPMEZCUlRkRExGbEJRVWtzVDBGQlR5eGxRVUZsTEUxQlFXWXNRMEZCYzBJc1EwRkJkRUlzUTBGQlVDeERRVVo1UXpzN1FVRkpOME1zV1VGQlJ5eExRVUZMTEU5QlFVOHNTMEZCVUN4RFFVRmhMRWxCUVdJc1JVRkJiVUlzU1VGQmJrSXNRMEZCVEN4RlFVRTRRanRCUVVNdlFpeHBRa0ZCVHl4TFFVRkxMRTFCUVV3c1EwRkJXU3hEUVVGRExFbEJRVWtzUzBGQlNpeERRVUZWTEVsQlFWWXNSVUZCWjBJc1NVRkJhRUlzUTBGQlJDeERRVUZhTEVOQlFWQXNRMEZFSzBJN1UwRkJha003TzBGQlNVRXNhMEpCUVZVc1YwRkJWeXhMUVVGWUxFTkJRV2xDTEZGQlFWRXNVMEZCVWl4TFFVRnpRaXhEUVVGMFFpeEZRVUY1UWl4UlFVRlJMRk5CUVZJc1RVRkJkVUlzU1VGQlNTeERRVUZLTEVOQlFYWkNMRU5CUVhCRUxFTkJValpETzBGQlV6ZERMRmxCVkRaRE8wOUJRUzlET3p0QlFWbEJMR0ZCUVU4c1NVRkJVQ3hEUVdoQ2FVTTdTMEZCYmtNc1RVRnBRa3M3UVVGRFNDeFhRVUZKTEVsQlFVa3NTVUZCU2l4SlFVRlpMRlZCUVdoQ0xFVkJRVEpDTzBGQlEzcENMRmxCUVVrc1NVRkJTU3hUUVVGVExHTkJRVlFzUTBGQmQwSXNUMEZCZUVJc1JVRkJhVU1zU1VGQmFrTXNRMEZCU2l4RFFVUnhRanRCUVVWNlFpeFpRVUZKTEU5QlFVOHNaVUZCWlN4TlFVRm1MRU5CUVhOQ0xFTkJRWFJDTEVOQlFWQXNRMEZHY1VJN08wRkJTWHBDTEZsQlFVY3NTMEZCU3l4UFFVRlBMRXRCUVZBc1EwRkJZU3hKUVVGaUxFVkJRVzFDTEVsQlFXNUNMRU5CUVV3c1JVRkJPRUk3UVVGREwwSXNhVUpCUVU4c1MwRkJTeXhOUVVGTUxFTkJRVmtzUTBGQlF5eEpRVUZKTEV0QlFVb3NRMEZCVlN4SlFVRldMRVZCUVdkQ0xFbEJRV2hDTEVOQlFVUXNRMEZCV2l4RFFVRlFMRU5CUkN0Q08xTkJRV3BETzA5QlNrWTdPMEZCVTBFc1lVRkJUeXhKUVVGUUxFTkJWa2M3UzBGcVFrdzdSMEZFUml4TlFUaENTenRCUVVOSUxGRkJRVWtzVVVGQlVTeEZRVUZTTEVOQlJFUTdPMEZCUjBnc1VVRkJSeXh6UWtGQmMwSXNVMEZCZEVJc1JVRkJaME03UVVGRGFrTXNWVUZCU1N4VlFVRlZMRmRCUVZjc1MwRkJXQ3hEUVVGcFFpeERRVUZxUWl4RlFVRnZRaXhSUVVGUkxGTkJRVklzUlVGQmNFSXNRMEZCVml4RFFVUTJRanRCUVVWcVF5eFZRVUZKTEVsQlFVa3NRMEZCU2l4RFFVWTJRanM3UVVGSmFrTXNZVUZCVFN4UlFVRlJMRk5CUVZJc1NVRkJjVUlzVVVGQlVTeFRRVUZTTEVWQlFYSkNMRVZCUVhsRE8wRkJRemRETEZsQlFVa3NTVUZCU1N4VFFVRlRMR05CUVZRc1EwRkJkMElzVDBGQmVFSXNSVUZCYVVNc1QwRkJha01zUTBGQlNpeERRVVI1UXp0QlFVVTNReXhaUVVGSExFTkJRVWdzUlVGQlN6dEJRVU5JTEd0Q1FVRlJMRXRCUVVzc1RVRkJUQ3hEUVVGWkxFdEJRVXNzU1VGQlRDeERRVUZWTEZsQlFWa3NTMEZCV2l4RFFVRnJRaXhEUVVGc1FpeERRVUZXTEVWQlFXZERMRWRCUVdoRExFVkJRWEZETEUxQlFYSkRMRVZCUVRaRExFdEJRVGRETEVWQlFXOUVMR1ZCUVdVc1RVRkJaaXhEUVVGelFpeERRVUYwUWl4RFFVRndSQ3hEUVVGYUxFTkJRVklzUTBGRVJ6dFRRVUZNT3p0QlFVbEJMR3RDUVVGVkxGZEJRVmNzUzBGQldDeERRVUZwUWl4UlFVRlJMRk5CUVZJc1MwRkJjMElzUTBGQmRFSXNSVUZCZVVJc1VVRkJVU3hUUVVGU0xFMUJRWFZDTEVsQlFVa3NRMEZCU2l4RFFVRjJRaXhEUVVGd1JDeERRVTQyUXp0QlFVODNReXhaUVZBMlF6dFBRVUV2UXp0TFFVcEdMRTFCWVVzN1FVRkRTQ3hYUVVGSkxFbEJRVWtzU1VGQlNpeEpRVUZaTEZWQlFXaENMRVZCUVRKQ08wRkJRM3BDTEZsQlFVa3NTVUZCU1N4VFFVRlRMR05CUVZRc1EwRkJkMElzVDBGQmVFSXNSVUZCYVVNc1NVRkJha01zUTBGQlNpeERRVVJ4UWp0QlFVVjZRaXhaUVVGSExFTkJRVWdzUlVGQlN6dEJRVU5JTEd0Q1FVRlJMRXRCUVVzc1RVRkJUQ3hEUVVGWkxFdEJRVXNzU1VGQlRDeERRVUZWTEZsQlFWa3NTMEZCV2l4RFFVRnJRaXhEUVVGc1FpeERRVUZXTEVWQlFXZERMRWRCUVdoRExFVkJRWEZETEUxQlFYSkRMRVZCUVRaRExFdEJRVGRETEVWQlFXOUVMR1ZCUVdVc1RVRkJaaXhEUVVGelFpeERRVUYwUWl4RFFVRndSQ3hEUVVGYUxFTkJRVklzUTBGRVJ6dFRRVUZNTzA5QlJrWTdTMEZrUmpzN1FVRnpRa0VzVjBGQlR5eExRVUZRTEVOQmVrSkhPMGRCT1VKTU8wTkJTa1k3TzBGQkswUkJMRk5CUVZNc1NVRkJWQ3hEUVVGakxFMUJRV1FzUlVGQmMwSXNaVUZCZEVJc1JVRkJkVU1zVTBGQmRrTXNSVUZCYTBRc1lVRkJiRVFzUlVGQmFVVXNZMEZCYWtVc1JVRkJaMFk3UVVGRE9VVXNUVUZCU1N4VFFVRlRMRWxCUVZRc1EwRkVNRVU3TzBGQlJ6bEZMRTFCUVVjN1FVRkRSQ3hoUVVGVExGRkJRVlFzUTBGRVF6dEhRVUZJTEVOQlJVTXNUMEZCVFN4RFFVRk9MRVZCUVZFN1FVRkRVQ3hSUVVGSkxGbEJRVmtzU1VGQldpeERRVVJIT3p0QlFVZFFMRkZCUVVjc1pVRkJTQ3hGUVVGdFFqdEJRVU5xUWl4VlFVRkhPMEZCUTBRc2IwSkJRVmtzWjBKQlFXZENMRU5CUVdoQ0xFTkJRVm9zUTBGRVF6dEJRVVZFTEdWQlFVOHNVMEZCVUN4RFFVWkRPMDlCUVVnc1EwRkhReXhQUVVGTkxFVkJRVTRzUlVGQlV6dEJRVU5TTEZsQlFVY3NZMEZCWXl4VFFVRlRMRlZCUVZRc1JVRkJiMEk3UVVGRGJrTXNaMEpCUVUwc1JVRkJUaXhEUVVSdFF6dFRRVUZ5UXp0UFFVUkVPMHRCU2tnN08wRkJWMEVzVVVGQlJ5eFRRVUZJTEVWQlFXRTdRVUZEV0N4VlFVRkhPMEZCUTBRc2IwSkJRVmtzVlVGQlZTeERRVUZXTEVOQlFWb3NRMEZFUXp0QlFVVkVMR1ZCUVU4c1UwRkJVQ3hEUVVaRE8wOUJRVWdzUTBGSFF5eFBRVUZOTEVWQlFVNHNSVUZCVXp0QlFVTlNMRmxCUVVjc1kwRkJZeXhUUVVGVExGVkJRVlFzUlVGQmIwSTdRVUZEYmtNc1owSkJRVTBzUlVGQlRpeERRVVJ0UXp0VFFVRnlRenRQUVVSRU8wdEJTa2c3TzBGQlYwRXNWVUZCVFN4RFFVRk9MRU5CZWtKUE8wZEJRVklzVTBFeVFrODdRVUZEVGl4UlFVRkhMR05CUVVnc1JVRkJhMEk3UVVGRGFFSXNkVUpCUkdkQ08wdEJRV3hDTzBkQk9VSkdPenRCUVcxRFFTeE5RVUZITEdGQlFVZ3NSVUZCYVVJN1FVRkRaaXhSUVVGSE8wRkJRMFFzWVVGQlR5eGpRVUZqTEUxQlFXUXNRMEZCVUN4RFFVUkRPMHRCUVVnc1EwRkZReXhQUVVGTkxFVkJRVTRzUlVGQlV6dEJRVU5PTEZWQlFVY3NZMEZCWXl4VFFVRlRMRlZCUVZRc1JVRkJiMEk3UVVGRGJrTXNZMEZCVFN4SlFVRkpMRXRCUVVvc1EwRkJWU3gzUWtGQlZpeERRVUZPTEVOQlJHMURPMDlCUVhKRE96dEJRVWxHTEZsQlFVMHNSVUZCVGl4RFFVeFJPMHRCUVZRN1IwRklTQ3hOUVZWTE8wRkJRMGdzVjBGQlR5eE5RVUZRTEVOQlJFYzdSMEZXVER0RFFYUkRSanM3UVVGeFJFRXNVMEZCVXl4TFFVRlVMRU5CUVdVc1IwRkJSeXhKUVVGSUxFVkJRVkU3UVVGRGNrSXNUVUZCU1N4aFFVRmhMRVZCUVdJc1EwRkVhVUk3TzBGQlIzSkNMRTlCUVVrc1NVRkJTU3hKUVVGSkxFTkJRVW9zUlVGQlR5eEpRVUZKTEV0QlFVc3NUVUZCVEN4RlFVRmhMRWRCUVdoRExFVkJRVzlETzBGQlEyeERMRkZCUVVjc1RVRkJUU3hMUVVGTExFMUJRVXdzUjBGQll5eERRVUZrTEVWQlFXZENPMEZCUTNaQ0xHRkJRVThzUzBGQlN5eERRVUZNTEVWQlFWRXNTMEZCVWl4RFFVRmpMRWxCUVdRc1JVRkJiMElzVlVGQmNFSXNRMEZCVUN4RFFVUjFRanRMUVVGNlFpeE5RVVZMTzBGQlEwZ3NWVUZCU1N4RFFVRkRMRTlCUVVRc1JVRkJWU3hKUVVGV0xFbEJRV3RDTEV0QlFVc3NRMEZCVEN4RFFVRnNRaXhEUVVSRU96dEJRVWRJTEZWQlFVa3NVMEZCVXl4TFFVRkxMRXRCUVV3c1EwRkJWeXhKUVVGWUxFVkJRV2xDTEZWQlFXcENMRU5CUVZRc1EwRklSRHM3UVVGTFNDeFZRVUZKTEdkQ1FVRm5RaXhUUVVGVExHTkJRVlFzUTBGQmQwSXNUMEZCZUVJc1JVRkJhVU1zVFVGQmFrTXNRMEZCYUVJc1EwRk1SRHM3UVVGUFNDeFZRVUZITEdsQ1FVRnBRaXhKUVVGcVFpeEZRVUZ6UWp0QlFVTjJRaXhsUVVGUExFMUJRVkFzUTBGRWRVSTdUMEZCZWtJc1RVRkZTenRCUVVOSUxIRkNRVUZoTEZkQlFWY3NUVUZCV0N4RFFVRnJRaXhoUVVGc1FpeERRVUZpTEVOQlJFYzdUMEZHVER0TFFWUkdPMGRCUkVZN08wRkJhMEpCTEZOQlFVOHNTVUZCVUN4RFFYSkNjVUk3UTBGQmRrSTdPMEZCZDBKQkxHVkJRV1U3UVVGRFlpeFBRVVJoTzBGQlJXSXNUVUZHWVR0QlFVZGlMRmxCU0dFN1FVRkpZaXhOUVVwaE8wRkJTMklzVFVGTVlUdEJRVTFpTEU5QlRtRTdRMEZCWmlJc0ltWnBiR1VpT2lKc2FXSXZZMjl5WlM5emNHVmphV0ZzWDJadmNtMXpMbXB6SWl3aWMyOTFjbU5sYzBOdmJuUmxiblFpT2xzaWFXMXdiM0owSUVKcGRGTjBjbWx1WnlCbWNtOXRJQ2N1TDJKcGRGOXpkSEpwYm1jbk8xeHVhVzF3YjNKMElGQmhkSFJsY201eklHWnliMjBnSnk0dmNHRjBkR1Z5Ym5Nbk8xeHVhVzF3YjNKMElIc2dWSFZ3YkdVZ2ZTQm1jbTl0SUNjdUwzQnlhVzFwZEdsMlpYTW5PMXh1WEc1bWRXNWpkR2x2YmlCZlkyRnpaU2hqYjI1a2FYUnBiMjRzSUdOc1lYVnpaWE1wZTF4dUlDQnlaWFIxY200Z1VHRjBkR1Z5Ym5NdVpHVm1iV0YwWTJnb0xpNHVZMnhoZFhObGN5a29ZMjl1WkdsMGFXOXVLVHRjYm4xY2JseHVablZ1WTNScGIyNGdZMjl1WkNoamJHRjFjMlZ6S1h0Y2JpQWdabTl5S0d4bGRDQmpiR0YxYzJVZ2IyWWdZMnhoZFhObGN5bDdYRzRnSUNBZ2FXWW9ZMnhoZFhObFd6QmRLWHRjYmlBZ0lDQWdJSEpsZEhWeWJpQmpiR0YxYzJWYk1WMG9LVHRjYmlBZ0lDQjlYRzRnSUgxY2JseHVJQ0IwYUhKdmR5QnVaWGNnUlhKeWIzSW9LVHRjYm4xY2JseHVablZ1WTNScGIyNGdiV0Z3WDNWd1pHRjBaU2h0WVhBc0lIWmhiSFZsY3lsN1hHNGdJSEpsZEhWeWJpQlBZbXBsWTNRdVpuSmxaWHBsS0Z4dUlDQWdJRTlpYW1WamRDNWhjM05wWjI0b1hHNGdJQ0FnSUNCUFltcGxZM1F1WTNKbFlYUmxLRzFoY0M1amIyNXpkSEoxWTNSdmNpNXdjbTkwYjNSNWNHVXBMQ0J0WVhBc0lIWmhiSFZsYzF4dUlDQWdJQ2xjYmlBZ0tUdGNibjFjYmx4dVpuVnVZM1JwYjI0Z1gyWnZjaWhqYjJ4c1pXTjBhVzl1Y3l3Z1puVnVMQ0JtYVd4MFpYSWdQU0FvS1NBOVBpQjBjblZsTENCcGJuUnZJRDBnVzEwc0lIQnlaWFpwYjNWelZtRnNkV1Z6SUQwZ1cxMHBlMXh1SUNCc1pYUWdjR0YwZEdWeWJpQTlJR052Ykd4bFkzUnBiMjV6V3pCZFd6QmRPMXh1SUNCc1pYUWdZMjlzYkdWamRHbHZiaUE5SUdOdmJHeGxZM1JwYjI1eld6QmRXekZkTzF4dVhHNGdJR2xtS0dOdmJHeGxZM1JwYjI1ekxteGxibWQwYUNBOVBUMGdNU2w3WEc0Z0lDQWdhV1lvWTI5c2JHVmpkR2x2YmlCcGJuTjBZVzVqWlc5bUlFSnBkRk4wY21sdVp5bDdYRzRnSUNBZ0lDQnNaWFFnWW5OVGJHbGpaU0E5SUdOdmJHeGxZM1JwYjI0dWMyeHBZMlVvTUN3Z2NHRjBkR1Z5Ymk1aWVYUmxYM05wZW1Vb0tTazdYRzRnSUNBZ0lDQnNaWFFnYVNBOUlERTdYRzVjYmlBZ0lDQWdJSGRvYVd4bEtHSnpVMnhwWTJVdVlubDBaVjl6YVhwbElEMDlJSEJoZEhSbGNtNHVZbmwwWlY5emFYcGxLQ2twZTF4dUlDQWdJQ0FnSUNCc1pYUWdjaUE5SUZCaGRIUmxjbTV6TG0xaGRHTm9YMjV2WDNSb2NtOTNLSEJoZEhSbGNtNHNJR0p6VTJ4cFkyVXBPMXh1SUNBZ0lDQWdJQ0JzWlhRZ1lYSm5jeUE5SUhCeVpYWnBiM1Z6Vm1Gc2RXVnpMbU52Ym1OaGRDaHlLVHRjYmx4dUlDQWdJQ0FnSUNCcFppaHlJQ1ltSUdacGJIUmxjaTVoY0hCc2VTaDBhR2x6TENCaGNtZHpLU2w3WEc0Z0lDQWdJQ0FnSUNBZ2FXNTBieUE5SUdsdWRHOHVZMjl1WTJGMEtGdG1kVzR1WVhCd2JIa29kR2hwY3l3Z1lYSm5jeWxkS1R0Y2JpQWdJQ0FnSUNBZ2ZWeHVYRzRnSUNBZ0lDQWdJR0p6VTJ4cFkyVWdQU0JqYjJ4c1pXTjBhVzl1TG5Oc2FXTmxLSEJoZEhSbGNtNHVZbmwwWlY5emFYcGxLQ2tnS2lCcExDQndZWFIwWlhKdUxtSjVkR1ZmYzJsNlpTZ3BJQ29nS0drZ0t5QXhLU2s3WEc0Z0lDQWdJQ0FnSUdrckt6dGNiaUFnSUNBZ0lIMWNibHh1SUNBZ0lDQWdjbVYwZFhKdUlHbHVkRzg3WEc0Z0lDQWdmV1ZzYzJWN1hHNGdJQ0FnSUNCbWIzSW9iR1YwSUdWc1pXMGdiMllnWTI5c2JHVmpkR2x2YmlsN1hHNGdJQ0FnSUNBZ0lHeGxkQ0J5SUQwZ1VHRjBkR1Z5Ym5NdWJXRjBZMmhmYm05ZmRHaHliM2NvY0dGMGRHVnliaXdnWld4bGJTazdYRzRnSUNBZ0lDQWdJR3hsZENCaGNtZHpJRDBnY0hKbGRtbHZkWE5XWVd4MVpYTXVZMjl1WTJGMEtISXBPMXh1WEc0Z0lDQWdJQ0FnSUdsbUtISWdKaVlnWm1sc2RHVnlMbUZ3Y0d4NUtIUm9hWE1zSUdGeVozTXBLWHRjYmlBZ0lDQWdJQ0FnSUNCcGJuUnZJRDBnYVc1MGJ5NWpiMjVqWVhRb1cyWjFiaTVoY0hCc2VTaDBhR2x6TENCaGNtZHpLVjBwTzF4dUlDQWdJQ0FnSUNCOVhHNGdJQ0FnSUNCOVhHNWNiaUFnSUNBZ0lISmxkSFZ5YmlCcGJuUnZPMXh1SUNBZ0lIMWNiaUFnZldWc2MyVjdYRzRnSUNBZ2JHVjBJRjlwYm5SdklEMGdXMTA3WEc1Y2JpQWdJQ0JwWmloamIyeHNaV04wYVc5dUlHbHVjM1JoYm1ObGIyWWdRbWwwVTNSeWFXNW5LWHRjYmlBZ0lDQWdJR3hsZENCaWMxTnNhV05sSUQwZ1kyOXNiR1ZqZEdsdmJpNXpiR2xqWlNnd0xDQndZWFIwWlhKdUxtSjVkR1ZmYzJsNlpTZ3BLVHRjYmlBZ0lDQWdJR3hsZENCcElEMGdNVHRjYmx4dUlDQWdJQ0FnZDJocGJHVW9Zbk5UYkdsalpTNWllWFJsWDNOcGVtVWdQVDBnY0dGMGRHVnliaTVpZVhSbFgzTnBlbVVvS1NsN1hHNGdJQ0FnSUNBZ0lHeGxkQ0J5SUQwZ1VHRjBkR1Z5Ym5NdWJXRjBZMmhmYm05ZmRHaHliM2NvY0dGMGRHVnliaXdnWW5OVGJHbGpaU2s3WEc0Z0lDQWdJQ0FnSUdsbUtISXBlMXh1SUNBZ0lDQWdJQ0FnSUY5cGJuUnZJRDBnYVc1MGJ5NWpiMjVqWVhRb2RHaHBjeTVmWm05eUtHTnZiR3hsWTNScGIyNXpMbk5zYVdObEtERXBMQ0JtZFc0c0lHWnBiSFJsY2l3Z1gybHVkRzhzSUhCeVpYWnBiM1Z6Vm1Gc2RXVnpMbU52Ym1OaGRDaHlLU2twTzF4dUlDQWdJQ0FnSUNCOVhHNWNiaUFnSUNBZ0lDQWdZbk5UYkdsalpTQTlJR052Ykd4bFkzUnBiMjR1YzJ4cFkyVW9jR0YwZEdWeWJpNWllWFJsWDNOcGVtVW9LU0FxSUdrc0lIQmhkSFJsY200dVlubDBaVjl6YVhwbEtDa2dLaUFvYVNBcklERXBLVHRjYmlBZ0lDQWdJQ0FnYVNzck8xeHVJQ0FnSUNBZ2ZWeHVJQ0FnSUgxbGJITmxlMXh1SUNBZ0lDQWdabTl5S0d4bGRDQmxiR1Z0SUc5bUlHTnZiR3hsWTNScGIyNHBlMXh1SUNBZ0lDQWdJQ0JzWlhRZ2NpQTlJRkJoZEhSbGNtNXpMbTFoZEdOb1gyNXZYM1JvY205M0tIQmhkSFJsY200c0lHVnNaVzBwTzF4dUlDQWdJQ0FnSUNCcFppaHlLWHRjYmlBZ0lDQWdJQ0FnSUNCZmFXNTBieUE5SUdsdWRHOHVZMjl1WTJGMEtIUm9hWE11WDJadmNpaGpiMnhzWldOMGFXOXVjeTV6YkdsalpTZ3hLU3dnWm5WdUxDQm1hV3gwWlhJc0lGOXBiblJ2TENCd2NtVjJhVzkxYzFaaGJIVmxjeTVqYjI1allYUW9jaWtwS1R0Y2JpQWdJQ0FnSUNBZ2ZWeHVJQ0FnSUNBZ2ZTQmNiaUFnSUNCOVhHNWNiaUFnSUNCeVpYUjFjbTRnWDJsdWRHODdYRzRnSUgxY2JuMWNibHh1Wm5WdVkzUnBiMjRnWDNSeWVTaGtiMTltZFc0c0lISmxjMk4xWlY5bWRXNWpkR2x2Yml3Z1kyRjBZMmhmWm5WdUxDQmxiSE5sWDJaMWJtTjBhVzl1TENCaFpuUmxjbDltZFc1amRHbHZiaWw3WEc0Z0lHeGxkQ0J5WlhOMWJIUWdQU0J1ZFd4c08xeHVYRzRnSUhSeWVYdGNiaUFnSUNCeVpYTjFiSFFnUFNCa2IxOW1kVzRvS1R0Y2JpQWdmV05oZEdOb0tHVXBlMXh1SUNBZ0lHeGxkQ0JsZUY5eVpYTjFiSFFnUFNCdWRXeHNPMXh1WEc0Z0lDQWdhV1lvY21WelkzVmxYMloxYm1OMGFXOXVLWHRjYmlBZ0lDQWdJSFJ5ZVh0Y2JpQWdJQ0FnSUNBZ1pYaGZjbVZ6ZFd4MElEMGdjbVZ6WTNWbFgyWjFibU4wYVc5dUtHVXBPMXh1SUNBZ0lDQWdJQ0J5WlhSMWNtNGdaWGhmY21WemRXeDBPMXh1SUNBZ0lDQWdmV05oZEdOb0tHVjRLWHRjYmlBZ0lDQWdJQ0FnYVdZb1pYZ2dhVzV6ZEdGdVkyVnZaaUJRWVhSMFpYSnVjeTVOWVhSamFFVnljbTl5S1h0Y2JpQWdJQ0FnSUNBZ0lDQjBhSEp2ZHlCbGVEdGNiaUFnSUNBZ0lDQWdmVnh1SUNBZ0lDQWdmVnh1SUNBZ0lIMWNibHh1SUNBZ0lHbG1LR05oZEdOb1gyWjFiaWw3WEc0Z0lDQWdJQ0IwY25sN1hHNGdJQ0FnSUNBZ0lHVjRYM0psYzNWc2RDQTlJR05oZEdOb1gyWjFiaWhsS1R0Y2JpQWdJQ0FnSUNBZ2NtVjBkWEp1SUdWNFgzSmxjM1ZzZER0Y2JpQWdJQ0FnSUgxallYUmphQ2hsZUNsN1hHNGdJQ0FnSUNBZ0lHbG1LR1Y0SUdsdWMzUmhibU5sYjJZZ1VHRjBkR1Z5Ym5NdVRXRjBZMmhGY25KdmNpbDdYRzRnSUNBZ0lDQWdJQ0FnZEdoeWIzY2daWGc3WEc0Z0lDQWdJQ0FnSUgxY2JpQWdJQ0FnSUgxY2JpQWdJQ0I5WEc1Y2JpQWdJQ0IwYUhKdmR5QmxPMXh1WEc0Z0lIMW1hVzVoYkd4NWUxeHVJQ0FnSUdsbUtHRm1kR1Z5WDJaMWJtTjBhVzl1S1h0Y2JpQWdJQ0FnSUdGbWRHVnlYMloxYm1OMGFXOXVLQ2s3WEc0Z0lDQWdmVnh1SUNCOVhHNWNiaUFnYVdZb1pXeHpaVjltZFc1amRHbHZiaWw3WEc0Z0lDQWdkSEo1ZTF4dUlDQWdJQ0FnY21WMGRYSnVJR1ZzYzJWZlpuVnVZM1JwYjI0b2NtVnpkV3gwS1R0Y2JpQWdJQ0I5WTJGMFkyZ29aWGdwZTF4dUlDQWdJQ0FnSUNCcFppaGxlQ0JwYm5OMFlXNWpaVzltSUZCaGRIUmxjbTV6TGsxaGRHTm9SWEp5YjNJcGUxeHVJQ0FnSUNBZ0lDQWdJSFJvY205M0lHNWxkeUJGY25KdmNpaGNJazV2SUUxaGRHTm9JRVp2ZFc1a0lHbHVJRVZzYzJWY0lpazdYRzRnSUNBZ0lDQWdJSDFjYmx4dUlDQWdJQ0FnZEdoeWIzY2daWGc3WEc0Z0lDQWdmVnh1SUNCOVpXeHpaWHRjYmlBZ0lDQnlaWFIxY200Z2NtVnpkV3gwTzF4dUlDQjlYRzU5WEc1Y2JtWjFibU4wYVc5dUlGOTNhWFJvS0M0dUxtRnlaM01wZTF4dUlDQnNaWFFnWVhKbmMxUnZVR0Z6Y3lBOUlGdGRPMXh1WEc0Z0lHWnZjaWhzWlhRZ2FTQTlJREE3SUdrZ1BDQmhjbWR6TG14bGJtZDBhRHNnYVNzcktYdGNiaUFnSUNCcFppaHBJRDA5UFNCaGNtZHpMbXhsYm1kMGFDQXRJREVwZTF4dUlDQWdJQ0FnY21WMGRYSnVJR0Z5WjNOYmFWMHVZWEJ3Ykhrb2JuVnNiQ3dnWVhKbmMxUnZVR0Z6Y3lrN1hHNGdJQ0FnZldWc2MyVjdYRzRnSUNBZ0lDQnNaWFFnVzNCaGRIUmxjbTRzSUdaMWJtTmRJRDBnWVhKbmMxdHBYVHRjYmx4dUlDQWdJQ0FnYkdWMElISmxjM1ZzZENBOUlHWjFibU11WVhCd2JIa29iblZzYkN3Z1lYSm5jMVJ2VUdGemN5azdYRzVjYmlBZ0lDQWdJR3hsZENCd1lYUjBaWEp1VW1WemRXeDBJRDBnVUdGMGRHVnlibk11YldGMFkyaGZibTlmZEdoeWIzY29jR0YwZEdWeWJpd2djbVZ6ZFd4MEtUdGNibHh1SUNBZ0lDQWdhV1lvY0dGMGRHVnlibEpsYzNWc2RDQTlQU0J1ZFd4c0tYdGNiaUFnSUNBZ0lDQWdjbVYwZFhKdUlISmxjM1ZzZER0Y2JpQWdJQ0FnSUgxbGJITmxlMXh1SUNBZ0lDQWdJQ0JoY21kelZHOVFZWE56SUQwZ1lYSm5jMVJ2VUdGemN5NWpiMjVqWVhRb2NHRjBkR1Z5YmxKbGMzVnNkQ2s3WEc0Z0lDQWdJQ0I5WEc0Z0lDQWdmVnh1SUNCOVhHNWNiaUFnY21WMGRYSnVJRzUxYkd3N1hHNTlYRzVjYm1WNGNHOXlkQ0JrWldaaGRXeDBJSHRjYmlBZ1gyTmhjMlVzWEc0Z0lHTnZibVFzWEc0Z0lHMWhjRjkxY0dSaGRHVXNYRzRnSUY5bWIzSXNYRzRnSUY5MGNua3NYRzRnSUY5M2FYUm9YRzU5TzF4dUlsMHNJbk52ZFhKalpWSnZiM1FpT2lJdmMyOTFjbU5sTHlKOVxuIiwiaW1wb3J0IFByb2Nlc3NTeXN0ZW0gZnJvbSAnLi9jb3JlL3Byb2Nlc3Nlcy9wcm9jZXNzX3N5c3RlbSc7XG5pbXBvcnQgeyBUdXBsZSwgUElELCBJbnRlZ2VyLCBGbG9hdCB9IGZyb20gJy4vY29yZS9wcmltaXRpdmVzJztcbmltcG9ydCBCaXRTdHJpbmcgZnJvbSAnLi9jb3JlL2JpdF9zdHJpbmcnO1xuaW1wb3J0IFBhdHRlcm5zIGZyb20gJy4vY29yZS9wYXR0ZXJucyc7XG5pbXBvcnQgRnVuY3Rpb25zIGZyb20gJy4vY29yZS9mdW5jdGlvbnMnO1xuaW1wb3J0IFNwZWNpYWxGb3JtcyBmcm9tICcuL2NvcmUvc3BlY2lhbF9mb3Jtcyc7XG5cbkZ1bmN0aW9ucy5nZXRfZ2xvYmFsKCkucHJvY2Vzc2VzID0gRnVuY3Rpb25zLmdldF9nbG9iYWwoKS5wcm9jZXNzZXMgfHwgbmV3IFByb2Nlc3NTeXN0ZW0oKTtcblxuZXhwb3J0IGRlZmF1bHQge1xuICBQcm9jZXNzU3lzdGVtLFxuICBUdXBsZSxcbiAgUElELFxuICBCaXRTdHJpbmcsXG4gIFBhdHRlcm5zLFxuICBJbnRlZ2VyLFxuICBGbG9hdCxcbiAgRnVuY3Rpb25zLFxuICBTcGVjaWFsRm9ybXNcbn07XG4vLyMgc291cmNlTWFwcGluZ1VSTD1kYXRhOmFwcGxpY2F0aW9uL2pzb247YmFzZTY0LGV5SjJaWEp6YVc5dUlqb3pMQ0p6YjNWeVkyVnpJanBiSW14cFlpOWpiM0psTG1weklsMHNJbTVoYldWeklqcGJYU3dpYldGd2NHbHVaM01pT2lKQlFVRkJMRTlCUVU4c1lVRkJVQ3hOUVVFd1FpeHBRMEZCTVVJN1FVRkRRU3hUUVVGVExFdEJRVlFzUlVGQlowSXNSMEZCYUVJc1JVRkJjVUlzVDBGQmNrSXNSVUZCT0VJc1MwRkJPVUlzVVVGQk1rTXNiVUpCUVRORE8wRkJRMEVzVDBGQlR5eFRRVUZRTEUxQlFYTkNMRzFDUVVGMFFqdEJRVU5CTEU5QlFVOHNVVUZCVUN4TlFVRnhRaXhwUWtGQmNrSTdRVUZEUVN4UFFVRlBMRk5CUVZBc1RVRkJjMElzYTBKQlFYUkNPMEZCUTBFc1QwRkJUeXhaUVVGUUxFMUJRWGxDTEhOQ1FVRjZRanM3UVVGRlFTeFZRVUZWTEZWQlFWWXNSMEZCZFVJc1UwRkJka0lzUjBGQmJVTXNWVUZCVlN4VlFVRldMRWRCUVhWQ0xGTkJRWFpDTEVsQlFXOURMRWxCUVVrc1lVRkJTaXhGUVVGd1F6czdRVUZGYmtNc1pVRkJaVHRCUVVOaUxHVkJSR0U3UVVGRllpeFBRVVpoTzBGQlIySXNTMEZJWVR0QlFVbGlMRmRCU21FN1FVRkxZaXhWUVV4aE8wRkJUV0lzVTBGT1lUdEJRVTlpTEU5QlVHRTdRVUZSWWl4WFFWSmhPMEZCVTJJc1kwRlVZVHREUVVGbUlpd2labWxzWlNJNklteHBZaTlqYjNKbExtcHpJaXdpYzI5MWNtTmxjME52Ym5SbGJuUWlPbHNpYVcxd2IzSjBJRkJ5YjJObGMzTlRlWE4wWlcwZ1puSnZiU0FuTGk5amIzSmxMM0J5YjJObGMzTmxjeTl3Y205alpYTnpYM041YzNSbGJTYzdYRzVwYlhCdmNuUWdleUJVZFhCc1pTd2dVRWxFTENCSmJuUmxaMlZ5TENCR2JHOWhkQ0I5SUdaeWIyMGdKeTR2WTI5eVpTOXdjbWx0YVhScGRtVnpKenRjYm1sdGNHOXlkQ0JDYVhSVGRISnBibWNnWm5KdmJTQW5MaTlqYjNKbEwySnBkRjl6ZEhKcGJtY25PMXh1YVcxd2IzSjBJRkJoZEhSbGNtNXpJR1p5YjIwZ0p5NHZZMjl5WlM5d1lYUjBaWEp1Y3ljN1hHNXBiWEJ2Y25RZ1JuVnVZM1JwYjI1eklHWnliMjBnSnk0dlkyOXlaUzltZFc1amRHbHZibk1uTzF4dWFXMXdiM0owSUZOd1pXTnBZV3hHYjNKdGN5Qm1jbTl0SUNjdUwyTnZjbVV2YzNCbFkybGhiRjltYjNKdGN5YzdYRzVjYmtaMWJtTjBhVzl1Y3k1blpYUmZaMnh2WW1Gc0tDa3VjSEp2WTJWemMyVnpJRDBnUm5WdVkzUnBiMjV6TG1kbGRGOW5iRzlpWVd3b0tTNXdjbTlqWlhOelpYTWdmSHdnYm1WM0lGQnliMk5sYzNOVGVYTjBaVzBvS1R0Y2JseHVaWGh3YjNKMElHUmxabUYxYkhRZ2UxeHVJQ0JRY205alpYTnpVM2x6ZEdWdExGeHVJQ0JVZFhCc1pTeGNiaUFnVUVsRUxGeHVJQ0JDYVhSVGRISnBibWNzWEc0Z0lGQmhkSFJsY201ekxGeHVJQ0JKYm5SbFoyVnlMRnh1SUNCR2JHOWhkQ3hjYmlBZ1JuVnVZM1JwYjI1ekxGeHVJQ0JUY0dWamFXRnNSbTl5YlhOY2JuMWNiaUpkTENKemIzVnlZMlZTYjI5MElqb2lMM052ZFhKalpTOGlmUT09XG4iLCJpbXBvcnQgQ29yZSBmcm9tICcuL2NvcmUnO1xuXG5sZXQgRW51bSA9IHtcblxuICBhbGxfX3FtYXJrX186IGZ1bmN0aW9uIChjb2xsZWN0aW9uLCBmdW4gPSB4ID0+IHgpIHtcbiAgICBmb3IgKGxldCBlbGVtIG9mIGNvbGxlY3Rpb24pIHtcbiAgICAgIGlmICghZnVuKGVsZW0pKSB7XG4gICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICByZXR1cm4gdHJ1ZTtcbiAgfSxcblxuICBhbnlfX3FtYXJrX186IGZ1bmN0aW9uIChjb2xsZWN0aW9uLCBmdW4gPSB4ID0+IHgpIHtcbiAgICBmb3IgKGxldCBlbGVtIG9mIGNvbGxlY3Rpb24pIHtcbiAgICAgIGlmIChmdW4oZWxlbSkpIHtcbiAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICB9XG4gICAgfVxuXG4gICAgcmV0dXJuIGZhbHNlO1xuICB9LFxuXG4gIGF0OiBmdW5jdGlvbiAoY29sbGVjdGlvbiwgbiwgdGhlX2RlZmF1bHQgPSBudWxsKSB7XG4gICAgaWYgKG4gPiB0aGlzLmNvdW50KGNvbGxlY3Rpb24pIHx8IG4gPCAwKSB7XG4gICAgICByZXR1cm4gdGhlX2RlZmF1bHQ7XG4gICAgfVxuXG4gICAgcmV0dXJuIGNvbGxlY3Rpb25bbl07XG4gIH0sXG5cbiAgY29uY2F0OiBmdW5jdGlvbiAoLi4uZW51bWFibGVzKSB7XG4gICAgcmV0dXJuIGVudW1hYmxlc1swXS5jb25jYXQoZW51bWFibGVzWzFdKTtcbiAgfSxcblxuICBjb3VudDogZnVuY3Rpb24gKGNvbGxlY3Rpb24sIGZ1biA9IG51bGwpIHtcbiAgICBpZiAoZnVuID09IG51bGwpIHtcbiAgICAgIHJldHVybiBjb2xsZWN0aW9uLmxlbmd0aDtcbiAgICB9IGVsc2Uge1xuICAgICAgcmV0dXJuIGNvbGxlY3Rpb24uZmlsdGVyKGZ1bikubGVuZ3RoO1xuICAgIH1cbiAgfSxcblxuICBkcm9wOiBmdW5jdGlvbiAoY29sbGVjdGlvbiwgY291bnQpIHtcbiAgICByZXR1cm4gY29sbGVjdGlvbi5zbGljZShjb3VudCk7XG4gIH0sXG5cbiAgZHJvcF93aGlsZTogZnVuY3Rpb24gKGNvbGxlY3Rpb24sIGZ1bikge1xuICAgIGxldCBjb3VudCA9IDA7XG5cbiAgICBmb3IgKGxldCBlbGVtIG9mIGNvbGxlY3Rpb24pIHtcbiAgICAgIGlmIChmdW4oZWxlbSkpIHtcbiAgICAgICAgY291bnQgPSBjb3VudCArIDE7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBicmVhaztcbiAgICAgIH1cbiAgICB9XG5cbiAgICByZXR1cm4gY29sbGVjdGlvbi5zbGljZShjb3VudCk7XG4gIH0sXG5cbiAgZWFjaDogZnVuY3Rpb24gKGNvbGxlY3Rpb24sIGZ1bikge1xuICAgIGZvciAobGV0IGVsZW0gb2YgY29sbGVjdGlvbikge1xuICAgICAgZnVuKGVsZW0pO1xuICAgIH1cbiAgfSxcblxuICBlbXB0eV9fcW1hcmtfXzogZnVuY3Rpb24gKGNvbGxlY3Rpb24pIHtcbiAgICByZXR1cm4gY29sbGVjdGlvbi5sZW5ndGggPT09IDA7XG4gIH0sXG5cbiAgZmV0Y2g6IGZ1bmN0aW9uIChjb2xsZWN0aW9uLCBuKSB7XG4gICAgaWYgKEFycmF5LmlzQXJyYXkoY29sbGVjdGlvbikpIHtcbiAgICAgIGlmIChuIDwgdGhpcy5jb3VudChjb2xsZWN0aW9uKSAmJiBuID49IDApIHtcbiAgICAgICAgcmV0dXJuIG5ldyBDb3JlLlR1cGxlKFN5bWJvbC5mb3IoXCJva1wiKSwgY29sbGVjdGlvbltuXSk7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICByZXR1cm4gU3ltYm9sLmZvcihcImVycm9yXCIpO1xuICAgICAgfVxuICAgIH1cblxuICAgIHRocm93IG5ldyBFcnJvcihcImNvbGxlY3Rpb24gaXMgbm90IGFuIEVudW1lcmFibGVcIik7XG4gIH0sXG5cbiAgZmV0Y2hfX2VtYXJrX186IGZ1bmN0aW9uIChjb2xsZWN0aW9uLCBuKSB7XG4gICAgaWYgKEFycmF5LmlzQXJyYXkoY29sbGVjdGlvbikpIHtcbiAgICAgIGlmIChuIDwgdGhpcy5jb3VudChjb2xsZWN0aW9uKSAmJiBuID49IDApIHtcbiAgICAgICAgcmV0dXJuIGNvbGxlY3Rpb25bbl07XG4gICAgICB9IGVsc2Uge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoXCJvdXQgb2YgYm91bmRzIGVycm9yXCIpO1xuICAgICAgfVxuICAgIH1cblxuICAgIHRocm93IG5ldyBFcnJvcihcImNvbGxlY3Rpb24gaXMgbm90IGFuIEVudW1lcmFibGVcIik7XG4gIH0sXG5cbiAgZmlsdGVyOiBmdW5jdGlvbiAoY29sbGVjdGlvbiwgZnVuKSB7XG4gICAgbGV0IHJlc3VsdCA9IFtdO1xuXG4gICAgZm9yIChsZXQgZWxlbSBvZiBjb2xsZWN0aW9uKSB7XG4gICAgICBpZiAoZnVuKGVsZW0pKSB7XG4gICAgICAgIHJlc3VsdC5wdXNoKGVsZW0pO1xuICAgICAgfVxuICAgIH1cblxuICAgIHJldHVybiByZXN1bHQ7XG4gIH0sXG5cbiAgZmlsdGVyX21hcDogZnVuY3Rpb24gKGNvbGxlY3Rpb24sIGZpbHRlciwgbWFwcGVyKSB7XG4gICAgcmV0dXJuIEVudW0ubWFwKEVudW0uZmlsdGVyKGNvbGxlY3Rpb24sIGZpbHRlciksIG1hcHBlcik7XG4gIH0sXG5cbiAgZmluZDogZnVuY3Rpb24gKGNvbGxlY3Rpb24sIGlmX25vbmUgPSBudWxsLCBmdW4pIHtcbiAgICBmb3IgKGxldCBlbGVtIG9mIGNvbGxlY3Rpb24pIHtcbiAgICAgIGlmIChmdW4oZWxlbSkpIHtcbiAgICAgICAgcmV0dXJuIGVsZW07XG4gICAgICB9XG4gICAgfVxuXG4gICAgcmV0dXJuIGlmX25vbmU7XG4gIH0sXG5cbiAgaW50bzogZnVuY3Rpb24gKGNvbGxlY3Rpb24sIGxpc3QpIHtcbiAgICByZXR1cm4gbGlzdC5jb25jYXQoY29sbGVjdGlvbik7XG4gIH0sXG5cbiAgbWFwOiBmdW5jdGlvbiAoY29sbGVjdGlvbiwgZnVuKSB7XG4gICAgbGV0IHJlc3VsdCA9IFtdO1xuXG4gICAgZm9yIChsZXQgZWxlbSBvZiBjb2xsZWN0aW9uKSB7XG4gICAgICByZXN1bHQucHVzaChmdW4oZWxlbSkpO1xuICAgIH1cblxuICAgIHJldHVybiByZXN1bHQ7XG4gIH0sXG5cbiAgbWFwX3JlZHVjZTogZnVuY3Rpb24gKGNvbGxlY3Rpb24sIGFjYywgZnVuKSB7XG4gICAgbGV0IG1hcHBlZCA9IE9iamVjdC5mcmVlemUoW10pO1xuICAgIGxldCB0aGVfYWNjID0gYWNjO1xuXG4gICAgZm9yICh2YXIgaSA9IDA7IGkgPCB0aGlzLmNvdW50KGNvbGxlY3Rpb24pOyBpKyspIHtcbiAgICAgIGxldCB0dXBsZSA9IGZ1bihjb2xsZWN0aW9uW2ldLCB0aGVfYWNjKTtcblxuICAgICAgdGhlX2FjYyA9IHR1cGxlLmdldCgxKTtcbiAgICAgIG1hcHBlZCA9IE9iamVjdC5mcmVlemUobWFwcGVkLmNvbmNhdChbdHVwbGUuZ2V0KDApXSkpO1xuICAgIH1cblxuICAgIHJldHVybiBuZXcgQ29yZS5UdXBsZShtYXBwZWQsIHRoZV9hY2MpO1xuICB9LFxuXG4gIG1lbWJlcl9fcW1hcmtfXzogZnVuY3Rpb24gKGNvbGxlY3Rpb24sIHZhbHVlKSB7XG4gICAgcmV0dXJuIGNvbGxlY3Rpb24uaW5jbHVkZXModmFsdWUpO1xuICB9LFxuXG4gIHJlZHVjZTogZnVuY3Rpb24gKGNvbGxlY3Rpb24sIGFjYywgZnVuKSB7XG4gICAgbGV0IHRoZV9hY2MgPSBhY2M7XG5cbiAgICBmb3IgKHZhciBpID0gMDsgaSA8IHRoaXMuY291bnQoY29sbGVjdGlvbik7IGkrKykge1xuICAgICAgbGV0IHR1cGxlID0gZnVuKGNvbGxlY3Rpb25baV0sIHRoZV9hY2MpO1xuXG4gICAgICB0aGVfYWNjID0gdHVwbGUuZ2V0KDEpO1xuICAgIH1cblxuICAgIHJldHVybiB0aGVfYWNjO1xuICB9LFxuXG4gIHRha2U6IGZ1bmN0aW9uIChjb2xsZWN0aW9uLCBjb3VudCkge1xuICAgIHJldHVybiBjb2xsZWN0aW9uLnNsaWNlKDAsIGNvdW50KTtcbiAgfSxcblxuICB0YWtlX2V2ZXJ5OiBmdW5jdGlvbiAoY29sbGVjdGlvbiwgbnRoKSB7XG4gICAgbGV0IHJlc3VsdCA9IFtdO1xuICAgIGxldCBpbmRleCA9IDA7XG5cbiAgICBmb3IgKGxldCBlbGVtIG9mIGNvbGxlY3Rpb24pIHtcbiAgICAgIGlmIChpbmRleCAlIG50aCA9PT0gMCkge1xuICAgICAgICByZXN1bHQucHVzaChlbGVtKTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICByZXR1cm4gT2JqZWN0LmZyZWV6ZShyZXN1bHQpO1xuICB9LFxuXG4gIHRha2Vfd2hpbGU6IGZ1bmN0aW9uIChjb2xsZWN0aW9uLCBmdW4pIHtcbiAgICBsZXQgY291bnQgPSAwO1xuXG4gICAgZm9yIChsZXQgZWxlbSBvZiBjb2xsZWN0aW9uKSB7XG4gICAgICBpZiAoZnVuKGVsZW0pKSB7XG4gICAgICAgIGNvdW50ID0gY291bnQgKyAxO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgYnJlYWs7XG4gICAgICB9XG4gICAgfVxuXG4gICAgcmV0dXJuIGNvbGxlY3Rpb24uc2xpY2UoMCwgY291bnQpO1xuICB9LFxuXG4gIHRvX2xpc3Q6IGZ1bmN0aW9uIChjb2xsZWN0aW9uKSB7XG4gICAgcmV0dXJuIGNvbGxlY3Rpb247XG4gIH1cbn07XG5cbmV4cG9ydCBkZWZhdWx0IEVudW07XG4vLyMgc291cmNlTWFwcGluZ1VSTD1kYXRhOmFwcGxpY2F0aW9uL2pzb247YmFzZTY0LGV5SjJaWEp6YVc5dUlqb3pMQ0p6YjNWeVkyVnpJanBiSW14cFlpOWxiblZ0TG1weklsMHNJbTVoYldWeklqcGJYU3dpYldGd2NHbHVaM01pT2lKQlFVRkJMRTlCUVU4c1NVRkJVQ3hOUVVGcFFpeFJRVUZxUWpzN1FVRkZRU3hKUVVGSkxFOUJRVTg3TzBGQlJWUXNaMEpCUVdNc1ZVRkJVeXhWUVVGVUxFVkJRWEZDTEUxQlFVMHNTMEZCVHl4RFFVRlFMRVZCUVZNN1FVRkRhRVFzVTBGQlNTeEpRVUZKTEVsQlFVb3NTVUZCV1N4VlFVRm9RaXhGUVVFeVFqdEJRVU42UWl4VlFVRkhMRU5CUVVNc1NVRkJTU3hKUVVGS0xFTkJRVVFzUlVGQlZ6dEJRVU5hTEdWQlFVOHNTMEZCVUN4RFFVUlpPMDlCUVdRN1MwRkVSanM3UVVGTlFTeFhRVUZQTEVsQlFWQXNRMEZRWjBRN1IwRkJjRU03TzBGQlZXUXNaMEpCUVdNc1ZVRkJVeXhWUVVGVUxFVkJRWEZDTEUxQlFVMHNTMEZCVHl4RFFVRlFMRVZCUVZNN1FVRkRhRVFzVTBGQlNTeEpRVUZKTEVsQlFVb3NTVUZCV1N4VlFVRm9RaXhGUVVFeVFqdEJRVU42UWl4VlFVRkhMRWxCUVVrc1NVRkJTaXhEUVVGSUxFVkJRV0U3UVVGRFdDeGxRVUZQTEVsQlFWQXNRMEZFVnp0UFFVRmlPMHRCUkVZN08wRkJUVUVzVjBGQlR5eExRVUZRTEVOQlVHZEVPMGRCUVhCRE96dEJRVlZrTEUxQlFVa3NWVUZCVXl4VlFVRlVMRVZCUVhGQ0xFTkJRWEpDTEVWQlFYZENMR05CUVdNc1NVRkJaQ3hGUVVGdFFqdEJRVU0zUXl4UlFVRkhMRWxCUVVrc1MwRkJTeXhMUVVGTUxFTkJRVmNzVlVGQldDeERRVUZLTEVsQlFUaENMRWxCUVVrc1EwRkJTaXhGUVVGTk8wRkJRM0pETEdGQlFVOHNWMEZCVUN4RFFVUnhRenRMUVVGMlF6czdRVUZKUVN4WFFVRlBMRmRCUVZjc1EwRkJXQ3hEUVVGUUxFTkJURFpETzBkQlFUTkRPenRCUVZGS0xGVkJRVkVzVlVGQlV5eEhRVUZITEZOQlFVZ3NSVUZCWVR0QlFVTTFRaXhYUVVGUExGVkJRVlVzUTBGQlZpeEZRVUZoTEUxQlFXSXNRMEZCYjBJc1ZVRkJWU3hEUVVGV0xFTkJRWEJDTEVOQlFWQXNRMEZFTkVJN1IwRkJkRUk3TzBGQlNWSXNVMEZCVHl4VlFVRlRMRlZCUVZRc1JVRkJjVUlzVFVGQlRTeEpRVUZPTEVWQlFWYzdRVUZEY2tNc1VVRkJSeXhQUVVGUExFbEJRVkFzUlVGQldUdEJRVU5pTEdGQlFVOHNWMEZCVnl4TlFVRllMRU5CUkUwN1MwRkJaaXhOUVVWUE8wRkJRMHdzWVVGQlR5eFhRVUZYTEUxQlFWZ3NRMEZCYTBJc1IwRkJiRUlzUlVGQmRVSXNUVUZCZGtJc1EwRkVSanRMUVVaUU8wZEJSRXM3TzBGQlVWQXNVVUZCVFN4VlFVRlRMRlZCUVZRc1JVRkJjVUlzUzBGQmNrSXNSVUZCTWtJN1FVRkRMMElzVjBGQlR5eFhRVUZYTEV0QlFWZ3NRMEZCYVVJc1MwRkJha0lzUTBGQlVDeERRVVFyUWp0SFFVRXpRanM3UVVGSlRpeGpRVUZaTEZWQlFWTXNWVUZCVkN4RlFVRnhRaXhIUVVGeVFpeEZRVUY1UWp0QlFVTnVReXhSUVVGSkxGRkJRVkVzUTBGQlVpeERRVVFyUWpzN1FVRkhia01zVTBGQlNTeEpRVUZKTEVsQlFVb3NTVUZCV1N4VlFVRm9RaXhGUVVFeVFqdEJRVU42UWl4VlFVRkhMRWxCUVVrc1NVRkJTaXhEUVVGSUxFVkJRV0U3UVVGRFdDeG5Ra0ZCVVN4UlFVRlJMRU5CUVZJc1EwRkVSenRQUVVGaUxFMUJSVXM3UVVGRFNDeGpRVVJITzA5QlJrdzdTMEZFUmpzN1FVRlJRU3hYUVVGUExGZEJRVmNzUzBGQldDeERRVUZwUWl4TFFVRnFRaXhEUVVGUUxFTkJXRzFETzBkQlFYcENPenRCUVdOYUxGRkJRVTBzVlVGQlV5eFZRVUZVTEVWQlFYRkNMRWRCUVhKQ0xFVkJRWGxDTzBGQlF6ZENMRk5CUVVrc1NVRkJTU3hKUVVGS0xFbEJRVmtzVlVGQmFFSXNSVUZCTWtJN1FVRkRla0lzVlVGQlNTeEpRVUZLTEVWQlJIbENPMHRCUVROQ08wZEJSRWs3TzBGQlRVNHNhMEpCUVdkQ0xGVkJRVk1zVlVGQlZDeEZRVUZ2UWp0QlFVTnNReXhYUVVGUExGZEJRVmNzVFVGQldDeExRVUZ6UWl4RFFVRjBRaXhEUVVReVFqdEhRVUZ3UWpzN1FVRkphRUlzVTBGQlR5eFZRVUZUTEZWQlFWUXNSVUZCY1VJc1EwRkJja0lzUlVGQmRVSTdRVUZETlVJc1VVRkJSeXhOUVVGTkxFOUJRVTRzUTBGQll5eFZRVUZrTEVOQlFVZ3NSVUZCTmtJN1FVRkRNMElzVlVGQlJ5eEpRVUZKTEV0QlFVc3NTMEZCVEN4RFFVRlhMRlZCUVZnc1EwRkJTaXhKUVVFNFFpeExRVUZMTEVOQlFVd3NSVUZCVHp0QlFVTjBReXhsUVVGUExFbEJRVWtzUzBGQlN5eExRVUZNTEVOQlFWY3NUMEZCVHl4SFFVRlFMRU5CUVZjc1NVRkJXQ3hEUVVGbUxFVkJRV2xETEZkQlFWY3NRMEZCV0N4RFFVRnFReXhEUVVGUUxFTkJSSE5ETzA5QlFYaERMRTFCUlVzN1FVRkRTQ3hsUVVGUExFOUJRVThzUjBGQlVDeERRVUZYTEU5QlFWZ3NRMEZCVUN4RFFVUkhPMDlCUmt3N1MwRkVSanM3UVVGUlFTeFZRVUZOTEVsQlFVa3NTMEZCU2l4RFFVRlZMR2xEUVVGV0xFTkJRVTRzUTBGVU5FSTdSMEZCZGtJN08wRkJXVkFzYTBKQlFXZENMRlZCUVZNc1ZVRkJWQ3hGUVVGeFFpeERRVUZ5UWl4RlFVRjFRanRCUVVOeVF5eFJRVUZITEUxQlFVMHNUMEZCVGl4RFFVRmpMRlZCUVdRc1EwRkJTQ3hGUVVFMlFqdEJRVU16UWl4VlFVRkhMRWxCUVVrc1MwRkJTeXhMUVVGTUxFTkJRVmNzVlVGQldDeERRVUZLTEVsQlFUaENMRXRCUVVzc1EwRkJUQ3hGUVVGUE8wRkJRM1JETEdWQlFVOHNWMEZCVnl4RFFVRllMRU5CUVZBc1EwRkVjME03VDBGQmVFTXNUVUZGU3p0QlFVTklMR05CUVUwc1NVRkJTU3hMUVVGS0xFTkJRVlVzY1VKQlFWWXNRMEZCVGl4RFFVUkhPMDlCUmt3N1MwRkVSanM3UVVGUlFTeFZRVUZOTEVsQlFVa3NTMEZCU2l4RFFVRlZMR2xEUVVGV0xFTkJRVTRzUTBGVWNVTTdSMEZCZGtJN08wRkJXV2hDTEZWQlFWRXNWVUZCVXl4VlFVRlVMRVZCUVhGQ0xFZEJRWEpDTEVWQlFYbENPMEZCUXk5Q0xGRkJRVWtzVTBGQlV5eEZRVUZVTEVOQlJESkNPenRCUVVjdlFpeFRRVUZKTEVsQlFVa3NTVUZCU2l4SlFVRlpMRlZCUVdoQ0xFVkJRVEpDTzBGQlEzcENMRlZCUVVjc1NVRkJTU3hKUVVGS0xFTkJRVWdzUlVGQllUdEJRVU5ZTEdWQlFVOHNTVUZCVUN4RFFVRlpMRWxCUVZvc1JVRkVWenRQUVVGaU8wdEJSRVk3TzBGQlRVRXNWMEZCVHl4TlFVRlFMRU5CVkN0Q08wZEJRWHBDT3p0QlFWbFNMR05CUVZrc1ZVRkJVeXhWUVVGVUxFVkJRWEZDTEUxQlFYSkNMRVZCUVRaQ0xFMUJRVGRDTEVWQlFXOURPMEZCUXpsRExGZEJRVThzUzBGQlN5eEhRVUZNTEVOQlFWTXNTMEZCU3l4TlFVRk1MRU5CUVZrc1ZVRkJXaXhGUVVGM1FpeE5RVUY0UWl4RFFVRlVMRVZCUVRCRExFMUJRVEZETEVOQlFWQXNRMEZFT0VNN1IwRkJjRU03TzBGQlNWb3NVVUZCVFN4VlFVRlRMRlZCUVZRc1JVRkJjVUlzVlVGQlZTeEpRVUZXTEVWQlFXZENMRWRCUVhKRExFVkJRWGxETzBGQlF6ZERMRk5CUVVrc1NVRkJTU3hKUVVGS0xFbEJRVmtzVlVGQmFFSXNSVUZCTWtJN1FVRkRla0lzVlVGQlJ5eEpRVUZKTEVsQlFVb3NRMEZCU0N4RlFVRmhPMEZCUTFnc1pVRkJUeXhKUVVGUUxFTkJSRmM3VDBGQllqdExRVVJHT3p0QlFVMUJMRmRCUVU4c1QwRkJVQ3hEUVZBMlF6dEhRVUY2UXpzN1FVRlZUaXhSUVVGTkxGVkJRVk1zVlVGQlZDeEZRVUZ4UWl4SlFVRnlRaXhGUVVFd1FqdEJRVU01UWl4WFFVRlBMRXRCUVVzc1RVRkJUQ3hEUVVGWkxGVkJRVm9zUTBGQlVDeERRVVE0UWp0SFFVRXhRanM3UVVGSlRpeFBRVUZMTEZWQlFWTXNWVUZCVkN4RlFVRnhRaXhIUVVGeVFpeEZRVUY1UWp0QlFVTTFRaXhSUVVGSkxGTkJRVk1zUlVGQlZDeERRVVIzUWpzN1FVRkhOVUlzVTBGQlNTeEpRVUZKTEVsQlFVb3NTVUZCV1N4VlFVRm9RaXhGUVVFeVFqdEJRVU42UWl4aFFVRlBMRWxCUVZBc1EwRkJXU3hKUVVGSkxFbEJRVW9zUTBGQldpeEZRVVI1UWp0TFFVRXpRanM3UVVGSlFTeFhRVUZQTEUxQlFWQXNRMEZRTkVJN1IwRkJla0k3TzBGQlZVd3NZMEZCV1N4VlFVRlRMRlZCUVZRc1JVRkJjVUlzUjBGQmNrSXNSVUZCTUVJc1IwRkJNVUlzUlVGQk9FSTdRVUZEZUVNc1VVRkJTU3hUUVVGVExFOUJRVThzVFVGQlVDeERRVUZqTEVWQlFXUXNRMEZCVkN4RFFVUnZRenRCUVVWNFF5eFJRVUZKTEZWQlFWVXNSMEZCVml4RFFVWnZRenM3UVVGSmVFTXNVMEZCU3l4SlFVRkpMRWxCUVVrc1EwRkJTaXhGUVVGUExFbEJRVWtzUzBGQlN5eExRVUZNTEVOQlFWY3NWVUZCV0N4RFFVRktMRVZCUVRSQ0xFZEJRVFZETEVWQlFXbEVPMEZCUXk5RExGVkJRVWtzVVVGQlVTeEpRVUZKTEZkQlFWY3NRMEZCV0N4RFFVRktMRVZCUVcxQ0xFOUJRVzVDTEVOQlFWSXNRMEZFTWtNN08wRkJSeTlETEdkQ1FVRlZMRTFCUVUwc1IwRkJUaXhEUVVGVkxFTkJRVllzUTBGQlZpeERRVWdyUXp0QlFVa3ZReXhsUVVGVExFOUJRVThzVFVGQlVDeERRVUZqTEU5QlFVOHNUVUZCVUN4RFFVRmpMRU5CUVVNc1RVRkJUU3hIUVVGT0xFTkJRVlVzUTBGQlZpeERRVUZFTEVOQlFXUXNRMEZCWkN4RFFVRlVMRU5CU2l0RE8wdEJRV3BFT3p0QlFVOUJMRmRCUVU4c1NVRkJTU3hMUVVGTExFdEJRVXdzUTBGQlZ5eE5RVUZtTEVWQlFYVkNMRTlCUVhaQ0xFTkJRVkFzUTBGWWQwTTdSMEZCT1VJN08wRkJZMW9zYlVKQlFXbENMRlZCUVZNc1ZVRkJWQ3hGUVVGeFFpeExRVUZ5UWl4RlFVRXlRanRCUVVNeFF5eFhRVUZQTEZkQlFWY3NVVUZCV0N4RFFVRnZRaXhMUVVGd1FpeERRVUZRTEVOQlJEQkRPMGRCUVROQ096dEJRVWxxUWl4VlFVRlJMRlZCUVZNc1ZVRkJWQ3hGUVVGeFFpeEhRVUZ5UWl4RlFVRXdRaXhIUVVFeFFpeEZRVUU0UWp0QlFVTndReXhSUVVGSkxGVkJRVlVzUjBGQlZpeERRVVJuUXpzN1FVRkhjRU1zVTBGQlN5eEpRVUZKTEVsQlFVa3NRMEZCU2l4RlFVRlBMRWxCUVVrc1MwRkJTeXhMUVVGTUxFTkJRVmNzVlVGQldDeERRVUZLTEVWQlFUUkNMRWRCUVRWRExFVkJRV2xFTzBGQlF5OURMRlZCUVVrc1VVRkJVU3hKUVVGSkxGZEJRVmNzUTBGQldDeERRVUZLTEVWQlFXMUNMRTlCUVc1Q0xFTkJRVklzUTBGRU1rTTdPMEZCUnk5RExHZENRVUZWTEUxQlFVMHNSMEZCVGl4RFFVRlZMRU5CUVZZc1EwRkJWaXhEUVVnclF6dExRVUZxUkRzN1FVRk5RU3hYUVVGUExFOUJRVkFzUTBGVWIwTTdSMEZCT1VJN08wRkJXVklzVVVGQlRTeFZRVUZUTEZWQlFWUXNSVUZCY1VJc1MwRkJja0lzUlVGQk1rSTdRVUZETDBJc1YwRkJUeXhYUVVGWExFdEJRVmdzUTBGQmFVSXNRMEZCYWtJc1JVRkJiMElzUzBGQmNFSXNRMEZCVUN4RFFVUXJRanRIUVVFelFqczdRVUZKVGl4alFVRlpMRlZCUVZNc1ZVRkJWQ3hGUVVGeFFpeEhRVUZ5UWl4RlFVRjVRanRCUVVOdVF5eFJRVUZKTEZOQlFWTXNSVUZCVkN4RFFVUXJRanRCUVVWdVF5eFJRVUZKTEZGQlFWRXNRMEZCVWl4RFFVWXJRanM3UVVGSmJrTXNVMEZCU1N4SlFVRkpMRWxCUVVvc1NVRkJXU3hWUVVGb1FpeEZRVUV5UWp0QlFVTjZRaXhWUVVGSExGRkJRVkVzUjBGQlVpeExRVUZuUWl4RFFVRm9RaXhGUVVGclFqdEJRVU51UWl4bFFVRlBMRWxCUVZBc1EwRkJXU3hKUVVGYUxFVkJSRzFDTzA5QlFYSkNPMHRCUkVZN08wRkJUVUVzVjBGQlR5eFBRVUZQTEUxQlFWQXNRMEZCWXl4TlFVRmtMRU5CUVZBc1EwRldiVU03UjBGQmVrSTdPMEZCWVZvc1kwRkJXU3hWUVVGVExGVkJRVlFzUlVGQmNVSXNSMEZCY2tJc1JVRkJlVUk3UVVGRGJrTXNVVUZCU1N4UlFVRlJMRU5CUVZJc1EwRkVLMEk3TzBGQlIyNURMRk5CUVVrc1NVRkJTU3hKUVVGS0xFbEJRVmtzVlVGQmFFSXNSVUZCTWtJN1FVRkRla0lzVlVGQlJ5eEpRVUZKTEVsQlFVb3NRMEZCU0N4RlFVRmhPMEZCUTFnc1owSkJRVkVzVVVGQlVTeERRVUZTTEVOQlJFYzdUMEZCWWl4TlFVVkxPMEZCUTBnc1kwRkVSenRQUVVaTU8wdEJSRVk3TzBGQlVVRXNWMEZCVHl4WFFVRlhMRXRCUVZnc1EwRkJhVUlzUTBGQmFrSXNSVUZCYjBJc1MwRkJjRUlzUTBGQlVDeERRVmh0UXp0SFFVRjZRanM3UVVGaldpeFhRVUZUTEZWQlFWTXNWVUZCVkN4RlFVRnZRanRCUVVNelFpeFhRVUZQTEZWQlFWQXNRMEZFTWtJN1IwRkJjRUk3UTBGdVRWQTdPMEZCZDAxS0xHVkJRV1VzU1VGQlppSXNJbVpwYkdVaU9pSnNhV0l2Wlc1MWJTNXFjeUlzSW5OdmRYSmpaWE5EYjI1MFpXNTBJanBiSW1sdGNHOXlkQ0JEYjNKbElHWnliMjBnSnk0dlkyOXlaU2M3WEc1Y2JteGxkQ0JGYm5WdElEMGdlMXh1WEc0Z0lHRnNiRjlmY1cxaGNtdGZYem9nWm5WdVkzUnBiMjRvWTI5c2JHVmpkR2x2Yml3Z1puVnVJRDBnS0hncElEMCtJSGdwZTF4dUlDQWdJR1p2Y2loc1pYUWdaV3hsYlNCdlppQmpiMnhzWldOMGFXOXVLWHRjYmlBZ0lDQWdJR2xtS0NGbWRXNG9aV3hsYlNrcGUxeHVJQ0FnSUNBZ0lDQnlaWFIxY200Z1ptRnNjMlU3WEc0Z0lDQWdJQ0I5WEc0Z0lDQWdmVnh1WEc0Z0lDQWdjbVYwZFhKdUlIUnlkV1U3WEc0Z0lIMHNYRzVjYmlBZ1lXNTVYMTl4YldGeWExOWZPaUJtZFc1amRHbHZiaWhqYjJ4c1pXTjBhVzl1TENCbWRXNGdQU0FvZUNrZ1BUNGdlQ2w3WEc0Z0lDQWdabTl5S0d4bGRDQmxiR1Z0SUc5bUlHTnZiR3hsWTNScGIyNHBlMXh1SUNBZ0lDQWdhV1lvWm5WdUtHVnNaVzBwS1h0Y2JpQWdJQ0FnSUNBZ2NtVjBkWEp1SUhSeWRXVTdYRzRnSUNBZ0lDQjlYRzRnSUNBZ2ZWeHVYRzRnSUNBZ2NtVjBkWEp1SUdaaGJITmxPMXh1SUNCOUxGeHVYRzRnSUdGME9pQm1kVzVqZEdsdmJpaGpiMnhzWldOMGFXOXVMQ0J1TENCMGFHVmZaR1ZtWVhWc2RDQTlJRzUxYkd3cGUxeHVJQ0FnSUdsbUtHNGdQaUIwYUdsekxtTnZkVzUwS0dOdmJHeGxZM1JwYjI0cElIeDhJRzRnUENBd0tYdGNiaUFnSUNBZ0lISmxkSFZ5YmlCMGFHVmZaR1ZtWVhWc2REdGNiaUFnSUNCOVhHNWNiaUFnSUNCeVpYUjFjbTRnWTI5c2JHVmpkR2x2Ymx0dVhUdGNiaUFnZlN4Y2JseHVJQ0JqYjI1allYUTZJR1oxYm1OMGFXOXVLQzR1TG1WdWRXMWhZbXhsY3lsN1hHNGdJQ0FnY21WMGRYSnVJR1Z1ZFcxaFlteGxjMXN3WFM1amIyNWpZWFFvWlc1MWJXRmliR1Z6V3pGZEtUdGNiaUFnZlN4Y2JseHVJQ0JqYjNWdWREb2dablZ1WTNScGIyNG9ZMjlzYkdWamRHbHZiaXdnWm5WdUlEMGdiblZzYkNsN1hHNGdJQ0FnYVdZb1puVnVJRDA5SUc1MWJHd3BlMXh1SUNBZ0lDQWdjbVYwZFhKdUlHTnZiR3hsWTNScGIyNHViR1Z1WjNSb08xeHVJQ0FnSUgwZ1pXeHpaU0I3WEc0Z0lDQWdJQ0J5WlhSMWNtNGdZMjlzYkdWamRHbHZiaTVtYVd4MFpYSW9ablZ1S1M1c1pXNW5kR2c3WEc0Z0lDQWdmVnh1SUNCOUxGeHVYRzRnSUdSeWIzQTZJR1oxYm1OMGFXOXVLR052Ykd4bFkzUnBiMjRzSUdOdmRXNTBLWHRjYmlBZ0lDQnlaWFIxY200Z1kyOXNiR1ZqZEdsdmJpNXpiR2xqWlNoamIzVnVkQ2s3WEc0Z0lIMHNYRzVjYmlBZ1pISnZjRjkzYUdsc1pUb2dablZ1WTNScGIyNG9ZMjlzYkdWamRHbHZiaXdnWm5WdUtYdGNiaUFnSUNCc1pYUWdZMjkxYm5RZ1BTQXdPMXh1WEc0Z0lDQWdabTl5S0d4bGRDQmxiR1Z0SUc5bUlHTnZiR3hsWTNScGIyNHBlMXh1SUNBZ0lDQWdhV1lvWm5WdUtHVnNaVzBwS1h0Y2JpQWdJQ0FnSUNBZ1kyOTFiblFnUFNCamIzVnVkQ0FySURFN1hHNGdJQ0FnSUNCOVpXeHpaWHRjYmlBZ0lDQWdJQ0FnWW5KbFlXczdYRzRnSUNBZ0lDQjlYRzRnSUNBZ2ZWeHVYRzRnSUNBZ2NtVjBkWEp1SUdOdmJHeGxZM1JwYjI0dWMyeHBZMlVvWTI5MWJuUXBPMXh1SUNCOUxGeHVYRzRnSUdWaFkyZzZJR1oxYm1OMGFXOXVLR052Ykd4bFkzUnBiMjRzSUdaMWJpbDdYRzRnSUNBZ1ptOXlLR3hsZENCbGJHVnRJRzltSUdOdmJHeGxZM1JwYjI0cGUxeHVJQ0FnSUNBZ1puVnVLR1ZzWlcwcE8xeHVJQ0FnSUgxY2JpQWdmU3hjYmx4dUlDQmxiWEIwZVY5ZmNXMWhjbXRmWHpvZ1puVnVZM1JwYjI0b1kyOXNiR1ZqZEdsdmJpbDdYRzRnSUNBZ2NtVjBkWEp1SUdOdmJHeGxZM1JwYjI0dWJHVnVaM1JvSUQwOVBTQXdPMXh1SUNCOUxGeHVYRzRnSUdabGRHTm9PaUJtZFc1amRHbHZiaWhqYjJ4c1pXTjBhVzl1TENCdUtYdGNiaUFnSUNCcFppaEJjbkpoZVM1cGMwRnljbUY1S0dOdmJHeGxZM1JwYjI0cEtYdGNiaUFnSUNBZ0lHbG1LRzRnUENCMGFHbHpMbU52ZFc1MEtHTnZiR3hsWTNScGIyNHBJQ1ltSUc0Z1BqMGdNQ2w3WEc0Z0lDQWdJQ0FnSUhKbGRIVnliaUJ1WlhjZ1EyOXlaUzVVZFhCc1pTaFRlVzFpYjJ3dVptOXlLRndpYjJ0Y0lpa3NJR052Ykd4bFkzUnBiMjViYmwwcE8xeHVJQ0FnSUNBZ2ZXVnNjMlY3WEc0Z0lDQWdJQ0FnSUhKbGRIVnliaUJUZVcxaWIyd3VabTl5S0Z3aVpYSnliM0pjSWlrN1hHNGdJQ0FnSUNCOVhHNGdJQ0FnZlZ4dVhHNGdJQ0FnZEdoeWIzY2dibVYzSUVWeWNtOXlLRndpWTI5c2JHVmpkR2x2YmlCcGN5QnViM1FnWVc0Z1JXNTFiV1Z5WVdKc1pWd2lLVHRjYmlBZ2ZTeGNibHh1SUNCbVpYUmphRjlmWlcxaGNtdGZYem9nWm5WdVkzUnBiMjRvWTI5c2JHVmpkR2x2Yml3Z2JpbDdYRzRnSUNBZ2FXWW9RWEp5WVhrdWFYTkJjbkpoZVNoamIyeHNaV04wYVc5dUtTbDdYRzRnSUNBZ0lDQnBaaWh1SUR3Z2RHaHBjeTVqYjNWdWRDaGpiMnhzWldOMGFXOXVLU0FtSmlCdUlENDlJREFwZTF4dUlDQWdJQ0FnSUNCeVpYUjFjbTRnWTI5c2JHVmpkR2x2Ymx0dVhUdGNiaUFnSUNBZ0lIMWxiSE5sZTF4dUlDQWdJQ0FnSUNCMGFISnZkeUJ1WlhjZ1JYSnliM0lvWENKdmRYUWdiMllnWW05MWJtUnpJR1Z5Y205eVhDSXBPMXh1SUNBZ0lDQWdmVnh1SUNBZ0lIMWNibHh1SUNBZ0lIUm9jbTkzSUc1bGR5QkZjbkp2Y2loY0ltTnZiR3hsWTNScGIyNGdhWE1nYm05MElHRnVJRVZ1ZFcxbGNtRmliR1ZjSWlrN1hHNGdJSDBzWEc1Y2JpQWdabWxzZEdWeU9pQm1kVzVqZEdsdmJpaGpiMnhzWldOMGFXOXVMQ0JtZFc0cGUxeHVJQ0FnSUd4bGRDQnlaWE4xYkhRZ1BTQmJYVHRjYmx4dUlDQWdJR1p2Y2loc1pYUWdaV3hsYlNCdlppQmpiMnhzWldOMGFXOXVLWHRjYmlBZ0lDQWdJR2xtS0daMWJpaGxiR1Z0S1NsN1hHNGdJQ0FnSUNBZ0lISmxjM1ZzZEM1d2RYTm9LR1ZzWlcwcE8xeHVJQ0FnSUNBZ2ZWeHVJQ0FnSUgxY2JseHVJQ0FnSUhKbGRIVnliaUJ5WlhOMWJIUTdYRzRnSUgwc1hHNWNiaUFnWm1sc2RHVnlYMjFoY0RvZ1puVnVZM1JwYjI0b1kyOXNiR1ZqZEdsdmJpd2dabWxzZEdWeUxDQnRZWEJ3WlhJcGUxeHVJQ0FnSUhKbGRIVnliaUJGYm5WdExtMWhjQ2hGYm5WdExtWnBiSFJsY2loamIyeHNaV04wYVc5dUxDQm1hV3gwWlhJcExDQnRZWEJ3WlhJcE8xeHVJQ0I5TEZ4dVhHNGdJR1pwYm1RNklHWjFibU4wYVc5dUtHTnZiR3hsWTNScGIyNHNJR2xtWDI1dmJtVWdQU0J1ZFd4c0xDQm1kVzRwZTF4dUlDQWdJR1p2Y2loc1pYUWdaV3hsYlNCdlppQmpiMnhzWldOMGFXOXVLWHRjYmlBZ0lDQWdJR2xtS0daMWJpaGxiR1Z0S1NsN1hHNGdJQ0FnSUNBZ0lISmxkSFZ5YmlCbGJHVnRPMXh1SUNBZ0lDQWdmVnh1SUNBZ0lIMWNibHh1SUNBZ0lISmxkSFZ5YmlCcFpsOXViMjVsTzF4dUlDQjlMRnh1WEc0Z0lHbHVkRzg2SUdaMWJtTjBhVzl1S0dOdmJHeGxZM1JwYjI0c0lHeHBjM1FwZTF4dUlDQWdJSEpsZEhWeWJpQnNhWE4wTG1OdmJtTmhkQ2hqYjJ4c1pXTjBhVzl1S1R0Y2JpQWdmU3hjYmx4dUlDQnRZWEE2SUdaMWJtTjBhVzl1S0dOdmJHeGxZM1JwYjI0c0lHWjFiaWw3WEc0Z0lDQWdiR1YwSUhKbGMzVnNkQ0E5SUZ0ZE8xeHVYRzRnSUNBZ1ptOXlLR3hsZENCbGJHVnRJRzltSUdOdmJHeGxZM1JwYjI0cGUxeHVJQ0FnSUNBZ2NtVnpkV3gwTG5CMWMyZ29ablZ1S0dWc1pXMHBLVHRjYmlBZ0lDQjlYRzVjYmlBZ0lDQnlaWFIxY200Z2NtVnpkV3gwTzF4dUlDQjlMRnh1WEc0Z0lHMWhjRjl5WldSMVkyVTZJR1oxYm1OMGFXOXVLR052Ykd4bFkzUnBiMjRzSUdGall5d2dablZ1S1h0Y2JpQWdJQ0JzWlhRZ2JXRndjR1ZrSUQwZ1QySnFaV04wTG1aeVpXVjZaU2hiWFNrN1hHNGdJQ0FnYkdWMElIUm9aVjloWTJNZ1BTQmhZMk03WEc1Y2JpQWdJQ0JtYjNJZ0tIWmhjaUJwSUQwZ01Ec2dhU0E4SUhSb2FYTXVZMjkxYm5Rb1kyOXNiR1ZqZEdsdmJpazdJR2tyS3lrZ2UxeHVJQ0FnSUNBZ2JHVjBJSFIxY0d4bElEMGdablZ1S0dOdmJHeGxZM1JwYjI1YmFWMHNJSFJvWlY5aFkyTXBPMXh1WEc0Z0lDQWdJQ0IwYUdWZllXTmpJRDBnZEhWd2JHVXVaMlYwS0RFcE8xeHVJQ0FnSUNBZ2JXRndjR1ZrSUQwZ1QySnFaV04wTG1aeVpXVjZaU2h0WVhCd1pXUXVZMjl1WTJGMEtGdDBkWEJzWlM1blpYUW9NQ2xkS1NrN1hHNGdJQ0FnZlZ4dVhHNGdJQ0FnY21WMGRYSnVJRzVsZHlCRGIzSmxMbFIxY0d4bEtHMWhjSEJsWkN3Z2RHaGxYMkZqWXlrN1hHNGdJSDBzWEc1Y2JpQWdiV1Z0WW1WeVgxOXhiV0Z5YTE5Zk9pQm1kVzVqZEdsdmJpaGpiMnhzWldOMGFXOXVMQ0IyWVd4MVpTbDdYRzRnSUNBZ2NtVjBkWEp1SUdOdmJHeGxZM1JwYjI0dWFXNWpiSFZrWlhNb2RtRnNkV1VwTzF4dUlDQjlMRnh1WEc0Z0lISmxaSFZqWlRvZ1puVnVZM1JwYjI0b1kyOXNiR1ZqZEdsdmJpd2dZV05qTENCbWRXNHBlMXh1SUNBZ0lHeGxkQ0IwYUdWZllXTmpJRDBnWVdOak8xeHVYRzRnSUNBZ1ptOXlJQ2gyWVhJZ2FTQTlJREE3SUdrZ1BDQjBhR2x6TG1OdmRXNTBLR052Ykd4bFkzUnBiMjRwT3lCcEt5c3BJSHRjYmlBZ0lDQWdJR3hsZENCMGRYQnNaU0E5SUdaMWJpaGpiMnhzWldOMGFXOXVXMmxkTENCMGFHVmZZV05qS1R0Y2JseHVJQ0FnSUNBZ2RHaGxYMkZqWXlBOUlIUjFjR3hsTG1kbGRDZ3hLVHRjYmlBZ0lDQjlYRzVjYmlBZ0lDQnlaWFIxY200Z2RHaGxYMkZqWXp0Y2JpQWdmU3hjYmx4dUlDQjBZV3RsT2lCbWRXNWpkR2x2YmloamIyeHNaV04wYVc5dUxDQmpiM1Z1ZENsN1hHNGdJQ0FnY21WMGRYSnVJR052Ykd4bFkzUnBiMjR1YzJ4cFkyVW9NQ3dnWTI5MWJuUXBPMXh1SUNCOUxGeHVYRzRnSUhSaGEyVmZaWFpsY25rNklHWjFibU4wYVc5dUtHTnZiR3hsWTNScGIyNHNJRzUwYUNsN1hHNGdJQ0FnYkdWMElISmxjM1ZzZENBOUlGdGRPMXh1SUNBZ0lHeGxkQ0JwYm1SbGVDQTlJREE3WEc1Y2JpQWdJQ0JtYjNJb2JHVjBJR1ZzWlcwZ2IyWWdZMjlzYkdWamRHbHZiaWw3WEc0Z0lDQWdJQ0JwWmlocGJtUmxlQ0FsSUc1MGFDQTlQVDBnTUNsN1hHNGdJQ0FnSUNBZ0lISmxjM1ZzZEM1d2RYTm9LR1ZzWlcwcE8xeHVJQ0FnSUNBZ2ZWeHVJQ0FnSUgxY2JseHVJQ0FnSUhKbGRIVnliaUJQWW1wbFkzUXVabkpsWlhwbEtISmxjM1ZzZENrN1hHNGdJSDBzWEc1Y2JpQWdkR0ZyWlY5M2FHbHNaVG9nWm5WdVkzUnBiMjRvWTI5c2JHVmpkR2x2Yml3Z1puVnVLWHRjYmlBZ0lDQnNaWFFnWTI5MWJuUWdQU0F3TzF4dVhHNGdJQ0FnWm05eUtHeGxkQ0JsYkdWdElHOW1JR052Ykd4bFkzUnBiMjRwZTF4dUlDQWdJQ0FnYVdZb1puVnVLR1ZzWlcwcEtYdGNiaUFnSUNBZ0lDQWdZMjkxYm5RZ1BTQmpiM1Z1ZENBcklERTdYRzRnSUNBZ0lDQjlaV3h6Wlh0Y2JpQWdJQ0FnSUNBZ1luSmxZV3M3WEc0Z0lDQWdJQ0I5WEc0Z0lDQWdmVnh1WEc0Z0lDQWdjbVYwZFhKdUlHTnZiR3hsWTNScGIyNHVjMnhwWTJVb01Dd2dZMjkxYm5RcE8xeHVJQ0I5TEZ4dVhHNGdJSFJ2WDJ4cGMzUTZJR1oxYm1OMGFXOXVLR052Ykd4bFkzUnBiMjRwZTF4dUlDQWdJSEpsZEhWeWJpQmpiMnhzWldOMGFXOXVPMXh1SUNCOVhHNTlPMXh1WEc1bGVIQnZjblFnWkdWbVlYVnNkQ0JGYm5WdE8xeHVJbDBzSW5OdmRYSmpaVkp2YjNRaU9pSXZjMjkxY21ObEx5SjlcbiIsImxldCBWaXJ0dWFsRE9NID0gZnVuY3Rpb24gKGUpIHtcbiAgICByZXR1cm4gZSgpO1xufShmdW5jdGlvbiAoKSB7XG4gICAgdmFyIGRlZmluZSwgbW9kdWxlLCBleHBvcnRzO1xuICAgIHJldHVybiBmdW5jdGlvbiBlKHQsIG4sIHIpIHtcbiAgICAgICAgZnVuY3Rpb24gcyhvLCB1KSB7XG4gICAgICAgICAgICBpZiAoIW5bb10pIHtcbiAgICAgICAgICAgICAgICBpZiAoIXRbb10pIHtcbiAgICAgICAgICAgICAgICAgICAgdmFyIGEgPSB0eXBlb2YgcmVxdWlyZSA9PSBcImZ1bmN0aW9uXCIgJiYgcmVxdWlyZTtcbiAgICAgICAgICAgICAgICAgICAgaWYgKCF1ICYmIGEpIHJldHVybiBhKG8sICEwKTtcbiAgICAgICAgICAgICAgICAgICAgaWYgKGkpIHJldHVybiBpKG8sICEwKTtcbiAgICAgICAgICAgICAgICAgICAgdmFyIGYgPSBuZXcgRXJyb3IoXCJDYW5ub3QgZmluZCBtb2R1bGUgJ1wiICsgbyArIFwiJ1wiKTtcbiAgICAgICAgICAgICAgICAgICAgdGhyb3cgZi5jb2RlID0gXCJNT0RVTEVfTk9UX0ZPVU5EXCIsIGY7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHZhciBsID0gbltvXSA9IHtcbiAgICAgICAgICAgICAgICAgICAgZXhwb3J0czoge31cbiAgICAgICAgICAgICAgICB9O1xuICAgICAgICAgICAgICAgIHRbb11bMF0uY2FsbChsLmV4cG9ydHMsIGZ1bmN0aW9uIChlKSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciBuID0gdFtvXVsxXVtlXTtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHMobiA/IG4gOiBlKTtcbiAgICAgICAgICAgICAgICB9LCBsLCBsLmV4cG9ydHMsIGUsIHQsIG4sIHIpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmV0dXJuIG5bb10uZXhwb3J0cztcbiAgICAgICAgfVxuICAgICAgICB2YXIgaSA9IHR5cGVvZiByZXF1aXJlID09IFwiZnVuY3Rpb25cIiAmJiByZXF1aXJlO1xuICAgICAgICBmb3IgKHZhciBvID0gMDsgbyA8IHIubGVuZ3RoOyBvKyspIHMocltvXSk7XG4gICAgICAgIHJldHVybiBzO1xuICAgIH0oe1xuICAgICAgICAxOiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge1xuXG4gICAgICAgICAgICB2YXIgY3JlYXRlRWxlbWVudCA9IHJlcXVpcmUoXCIuL3Zkb20vY3JlYXRlLWVsZW1lbnQuanNcIik7XG5cbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gY3JlYXRlRWxlbWVudDtcbiAgICAgICAgfSwgeyBcIi4vdmRvbS9jcmVhdGUtZWxlbWVudC5qc1wiOiAxNSB9XSwgMjogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHtcbiAgICAgICAgICAgIHZhciBkaWZmID0gcmVxdWlyZShcIi4vdnRyZWUvZGlmZi5qc1wiKTtcblxuICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBkaWZmO1xuICAgICAgICB9LCB7IFwiLi92dHJlZS9kaWZmLmpzXCI6IDM1IH1dLCAzOiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge1xuICAgICAgICAgICAgdmFyIGggPSByZXF1aXJlKFwiLi92aXJ0dWFsLWh5cGVyc2NyaXB0L2luZGV4LmpzXCIpO1xuXG4gICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IGg7XG4gICAgICAgIH0sIHsgXCIuL3ZpcnR1YWwtaHlwZXJzY3JpcHQvaW5kZXguanNcIjogMjIgfV0sIDQ6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICB2YXIgZGlmZiA9IHJlcXVpcmUoXCIuL2RpZmYuanNcIik7XG4gICAgICAgICAgICB2YXIgcGF0Y2ggPSByZXF1aXJlKFwiLi9wYXRjaC5qc1wiKTtcbiAgICAgICAgICAgIHZhciBoID0gcmVxdWlyZShcIi4vaC5qc1wiKTtcbiAgICAgICAgICAgIHZhciBjcmVhdGUgPSByZXF1aXJlKFwiLi9jcmVhdGUtZWxlbWVudC5qc1wiKTtcbiAgICAgICAgICAgIHZhciBWTm9kZSA9IHJlcXVpcmUoJy4vdm5vZGUvdm5vZGUuanMnKTtcbiAgICAgICAgICAgIHZhciBWVGV4dCA9IHJlcXVpcmUoJy4vdm5vZGUvdnRleHQuanMnKTtcblxuICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSB7XG4gICAgICAgICAgICAgICAgZGlmZjogZGlmZixcbiAgICAgICAgICAgICAgICBwYXRjaDogcGF0Y2gsXG4gICAgICAgICAgICAgICAgaDogaCxcbiAgICAgICAgICAgICAgICBjcmVhdGU6IGNyZWF0ZSxcbiAgICAgICAgICAgICAgICBWTm9kZTogVk5vZGUsXG4gICAgICAgICAgICAgICAgVlRleHQ6IFZUZXh0XG4gICAgICAgICAgICB9O1xuICAgICAgICB9LCB7IFwiLi9jcmVhdGUtZWxlbWVudC5qc1wiOiAxLCBcIi4vZGlmZi5qc1wiOiAyLCBcIi4vaC5qc1wiOiAzLCBcIi4vcGF0Y2guanNcIjogMTMsIFwiLi92bm9kZS92bm9kZS5qc1wiOiAzMSwgXCIuL3Zub2RlL3Z0ZXh0LmpzXCI6IDMzIH1dLCA1OiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge1xuICAgICAgICAgICAgLyohXG4gICAgICAgICAgICAgKiBDcm9zcy1Ccm93c2VyIFNwbGl0IDEuMS4xXG4gICAgICAgICAgICAgKiBDb3B5cmlnaHQgMjAwNy0yMDEyIFN0ZXZlbiBMZXZpdGhhbiA8c3RldmVubGV2aXRoYW4uY29tPlxuICAgICAgICAgICAgICogQXZhaWxhYmxlIHVuZGVyIHRoZSBNSVQgTGljZW5zZVxuICAgICAgICAgICAgICogRUNNQVNjcmlwdCBjb21wbGlhbnQsIHVuaWZvcm0gY3Jvc3MtYnJvd3NlciBzcGxpdCBtZXRob2RcbiAgICAgICAgICAgICAqL1xuXG4gICAgICAgICAgICAvKipcbiAgICAgICAgICAgICAqIFNwbGl0cyBhIHN0cmluZyBpbnRvIGFuIGFycmF5IG9mIHN0cmluZ3MgdXNpbmcgYSByZWdleCBvciBzdHJpbmcgc2VwYXJhdG9yLiBNYXRjaGVzIG9mIHRoZVxuICAgICAgICAgICAgICogc2VwYXJhdG9yIGFyZSBub3QgaW5jbHVkZWQgaW4gdGhlIHJlc3VsdCBhcnJheS4gSG93ZXZlciwgaWYgYHNlcGFyYXRvcmAgaXMgYSByZWdleCB0aGF0IGNvbnRhaW5zXG4gICAgICAgICAgICAgKiBjYXB0dXJpbmcgZ3JvdXBzLCBiYWNrcmVmZXJlbmNlcyBhcmUgc3BsaWNlZCBpbnRvIHRoZSByZXN1bHQgZWFjaCB0aW1lIGBzZXBhcmF0b3JgIGlzIG1hdGNoZWQuXG4gICAgICAgICAgICAgKiBGaXhlcyBicm93c2VyIGJ1Z3MgY29tcGFyZWQgdG8gdGhlIG5hdGl2ZSBgU3RyaW5nLnByb3RvdHlwZS5zcGxpdGAgYW5kIGNhbiBiZSB1c2VkIHJlbGlhYmx5XG4gICAgICAgICAgICAgKiBjcm9zcy1icm93c2VyLlxuICAgICAgICAgICAgICogQHBhcmFtIHtTdHJpbmd9IHN0ciBTdHJpbmcgdG8gc3BsaXQuXG4gICAgICAgICAgICAgKiBAcGFyYW0ge1JlZ0V4cHxTdHJpbmd9IHNlcGFyYXRvciBSZWdleCBvciBzdHJpbmcgdG8gdXNlIGZvciBzZXBhcmF0aW5nIHRoZSBzdHJpbmcuXG4gICAgICAgICAgICAgKiBAcGFyYW0ge051bWJlcn0gW2xpbWl0XSBNYXhpbXVtIG51bWJlciBvZiBpdGVtcyB0byBpbmNsdWRlIGluIHRoZSByZXN1bHQgYXJyYXkuXG4gICAgICAgICAgICAgKiBAcmV0dXJucyB7QXJyYXl9IEFycmF5IG9mIHN1YnN0cmluZ3MuXG4gICAgICAgICAgICAgKiBAZXhhbXBsZVxuICAgICAgICAgICAgICpcbiAgICAgICAgICAgICAqIC8vIEJhc2ljIHVzZVxuICAgICAgICAgICAgICogc3BsaXQoJ2EgYiBjIGQnLCAnICcpO1xuICAgICAgICAgICAgICogLy8gLT4gWydhJywgJ2InLCAnYycsICdkJ11cbiAgICAgICAgICAgICAqXG4gICAgICAgICAgICAgKiAvLyBXaXRoIGxpbWl0XG4gICAgICAgICAgICAgKiBzcGxpdCgnYSBiIGMgZCcsICcgJywgMik7XG4gICAgICAgICAgICAgKiAvLyAtPiBbJ2EnLCAnYiddXG4gICAgICAgICAgICAgKlxuICAgICAgICAgICAgICogLy8gQmFja3JlZmVyZW5jZXMgaW4gcmVzdWx0IGFycmF5XG4gICAgICAgICAgICAgKiBzcGxpdCgnLi53b3JkMSB3b3JkMi4uJywgLyhbYS16XSspKFxcZCspL2kpO1xuICAgICAgICAgICAgICogLy8gLT4gWycuLicsICd3b3JkJywgJzEnLCAnICcsICd3b3JkJywgJzInLCAnLi4nXVxuICAgICAgICAgICAgICovXG4gICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uIHNwbGl0KHVuZGVmKSB7XG5cbiAgICAgICAgICAgICAgICB2YXIgbmF0aXZlU3BsaXQgPSBTdHJpbmcucHJvdG90eXBlLnNwbGl0LFxuICAgICAgICAgICAgICAgICAgICBjb21wbGlhbnRFeGVjTnBjZyA9IC8oKT8/Ly5leGVjKFwiXCIpWzFdID09PSB1bmRlZixcblxuICAgICAgICAgICAgICAgIC8vIE5QQ0c6IG5vbnBhcnRpY2lwYXRpbmcgY2FwdHVyaW5nIGdyb3VwXG4gICAgICAgICAgICAgICAgc2VsZjtcblxuICAgICAgICAgICAgICAgIHNlbGYgPSBmdW5jdGlvbiAoc3RyLCBzZXBhcmF0b3IsIGxpbWl0KSB7XG4gICAgICAgICAgICAgICAgICAgIC8vIElmIGBzZXBhcmF0b3JgIGlzIG5vdCBhIHJlZ2V4LCB1c2UgYG5hdGl2ZVNwbGl0YFxuICAgICAgICAgICAgICAgICAgICBpZiAoT2JqZWN0LnByb3RvdHlwZS50b1N0cmluZy5jYWxsKHNlcGFyYXRvcikgIT09IFwiW29iamVjdCBSZWdFeHBdXCIpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBuYXRpdmVTcGxpdC5jYWxsKHN0ciwgc2VwYXJhdG9yLCBsaW1pdCk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgdmFyIG91dHB1dCA9IFtdLFxuICAgICAgICAgICAgICAgICAgICAgICAgZmxhZ3MgPSAoc2VwYXJhdG9yLmlnbm9yZUNhc2UgPyBcImlcIiA6IFwiXCIpICsgKHNlcGFyYXRvci5tdWx0aWxpbmUgPyBcIm1cIiA6IFwiXCIpICsgKHNlcGFyYXRvci5leHRlbmRlZCA/IFwieFwiIDogXCJcIikgKyAoIC8vIFByb3Bvc2VkIGZvciBFUzZcbiAgICAgICAgICAgICAgICAgICAgc2VwYXJhdG9yLnN0aWNreSA/IFwieVwiIDogXCJcIiksXG5cbiAgICAgICAgICAgICAgICAgICAgLy8gRmlyZWZveCAzK1xuICAgICAgICAgICAgICAgICAgICBsYXN0TGFzdEluZGV4ID0gMCxcblxuICAgICAgICAgICAgICAgICAgICAvLyBNYWtlIGBnbG9iYWxgIGFuZCBhdm9pZCBgbGFzdEluZGV4YCBpc3N1ZXMgYnkgd29ya2luZyB3aXRoIGEgY29weVxuICAgICAgICAgICAgICAgICAgICBzZXBhcmF0b3IgPSBuZXcgUmVnRXhwKHNlcGFyYXRvci5zb3VyY2UsIGZsYWdzICsgXCJnXCIpLFxuICAgICAgICAgICAgICAgICAgICAgICAgc2VwYXJhdG9yMixcbiAgICAgICAgICAgICAgICAgICAgICAgIG1hdGNoLFxuICAgICAgICAgICAgICAgICAgICAgICAgbGFzdEluZGV4LFxuICAgICAgICAgICAgICAgICAgICAgICAgbGFzdExlbmd0aDtcbiAgICAgICAgICAgICAgICAgICAgc3RyICs9IFwiXCI7IC8vIFR5cGUtY29udmVydFxuICAgICAgICAgICAgICAgICAgICBpZiAoIWNvbXBsaWFudEV4ZWNOcGNnKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAvLyBEb2Vzbid0IG5lZWQgZmxhZ3MgZ3ksIGJ1dCB0aGV5IGRvbid0IGh1cnRcbiAgICAgICAgICAgICAgICAgICAgICAgIHNlcGFyYXRvcjIgPSBuZXcgUmVnRXhwKFwiXlwiICsgc2VwYXJhdG9yLnNvdXJjZSArIFwiJCg/IVxcXFxzKVwiLCBmbGFncyk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgLyogVmFsdWVzIGZvciBgbGltaXRgLCBwZXIgdGhlIHNwZWM6XG4gICAgICAgICAgICAgICAgICAgICAqIElmIHVuZGVmaW5lZDogNDI5NDk2NzI5NSAvLyBNYXRoLnBvdygyLCAzMikgLSAxXG4gICAgICAgICAgICAgICAgICAgICAqIElmIDAsIEluZmluaXR5LCBvciBOYU46IDBcbiAgICAgICAgICAgICAgICAgICAgICogSWYgcG9zaXRpdmUgbnVtYmVyOiBsaW1pdCA9IE1hdGguZmxvb3IobGltaXQpOyBpZiAobGltaXQgPiA0Mjk0OTY3Mjk1KSBsaW1pdCAtPSA0Mjk0OTY3Mjk2O1xuICAgICAgICAgICAgICAgICAgICAgKiBJZiBuZWdhdGl2ZSBudW1iZXI6IDQyOTQ5NjcyOTYgLSBNYXRoLmZsb29yKE1hdGguYWJzKGxpbWl0KSlcbiAgICAgICAgICAgICAgICAgICAgICogSWYgb3RoZXI6IFR5cGUtY29udmVydCwgdGhlbiB1c2UgdGhlIGFib3ZlIHJ1bGVzXG4gICAgICAgICAgICAgICAgICAgICAqL1xuICAgICAgICAgICAgICAgICAgICBsaW1pdCA9IGxpbWl0ID09PSB1bmRlZiA/IC0xID4+PiAwIDogLy8gTWF0aC5wb3coMiwgMzIpIC0gMVxuICAgICAgICAgICAgICAgICAgICBsaW1pdCA+Pj4gMDsgLy8gVG9VaW50MzIobGltaXQpXG4gICAgICAgICAgICAgICAgICAgIHdoaWxlIChtYXRjaCA9IHNlcGFyYXRvci5leGVjKHN0cikpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIGBzZXBhcmF0b3IubGFzdEluZGV4YCBpcyBub3QgcmVsaWFibGUgY3Jvc3MtYnJvd3NlclxuICAgICAgICAgICAgICAgICAgICAgICAgbGFzdEluZGV4ID0gbWF0Y2guaW5kZXggKyBtYXRjaFswXS5sZW5ndGg7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAobGFzdEluZGV4ID4gbGFzdExhc3RJbmRleCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIG91dHB1dC5wdXNoKHN0ci5zbGljZShsYXN0TGFzdEluZGV4LCBtYXRjaC5pbmRleCkpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIEZpeCBicm93c2VycyB3aG9zZSBgZXhlY2AgbWV0aG9kcyBkb24ndCBjb25zaXN0ZW50bHkgcmV0dXJuIGB1bmRlZmluZWRgIGZvclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIG5vbnBhcnRpY2lwYXRpbmcgY2FwdHVyaW5nIGdyb3Vwc1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmICghY29tcGxpYW50RXhlY05wY2cgJiYgbWF0Y2gubGVuZ3RoID4gMSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBtYXRjaFswXS5yZXBsYWNlKHNlcGFyYXRvcjIsIGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZvciAodmFyIGkgPSAxOyBpIDwgYXJndW1lbnRzLmxlbmd0aCAtIDI7IGkrKykge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChhcmd1bWVudHNbaV0gPT09IHVuZGVmKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1hdGNoW2ldID0gdW5kZWY7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKG1hdGNoLmxlbmd0aCA+IDEgJiYgbWF0Y2guaW5kZXggPCBzdHIubGVuZ3RoKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIEFycmF5LnByb3RvdHlwZS5wdXNoLmFwcGx5KG91dHB1dCwgbWF0Y2guc2xpY2UoMSkpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBsYXN0TGVuZ3RoID0gbWF0Y2hbMF0ubGVuZ3RoO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxhc3RMYXN0SW5kZXggPSBsYXN0SW5kZXg7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKG91dHB1dC5sZW5ndGggPj0gbGltaXQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHNlcGFyYXRvci5sYXN0SW5kZXggPT09IG1hdGNoLmluZGV4KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgc2VwYXJhdG9yLmxhc3RJbmRleCsrOyAvLyBBdm9pZCBhbiBpbmZpbml0ZSBsb29wXG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgaWYgKGxhc3RMYXN0SW5kZXggPT09IHN0ci5sZW5ndGgpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChsYXN0TGVuZ3RoIHx8ICFzZXBhcmF0b3IudGVzdChcIlwiKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIG91dHB1dC5wdXNoKFwiXCIpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgb3V0cHV0LnB1c2goc3RyLnNsaWNlKGxhc3RMYXN0SW5kZXgpKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICByZXR1cm4gb3V0cHV0Lmxlbmd0aCA+IGxpbWl0ID8gb3V0cHV0LnNsaWNlKDAsIGxpbWl0KSA6IG91dHB1dDtcbiAgICAgICAgICAgICAgICB9O1xuXG4gICAgICAgICAgICAgICAgcmV0dXJuIHNlbGY7XG4gICAgICAgICAgICB9KCk7XG4gICAgICAgIH0sIHt9XSwgNjogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHt9LCB7fV0sIDc6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICAndXNlIHN0cmljdCc7XG5cbiAgICAgICAgICAgIHZhciBPbmVWZXJzaW9uQ29uc3RyYWludCA9IHJlcXVpcmUoJ2luZGl2aWR1YWwvb25lLXZlcnNpb24nKTtcblxuICAgICAgICAgICAgdmFyIE1ZX1ZFUlNJT04gPSAnNyc7XG4gICAgICAgICAgICBPbmVWZXJzaW9uQ29uc3RyYWludCgnZXYtc3RvcmUnLCBNWV9WRVJTSU9OKTtcblxuICAgICAgICAgICAgdmFyIGhhc2hLZXkgPSAnX19FVl9TVE9SRV9LRVlAJyArIE1ZX1ZFUlNJT047XG5cbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gRXZTdG9yZTtcblxuICAgICAgICAgICAgZnVuY3Rpb24gRXZTdG9yZShlbGVtKSB7XG4gICAgICAgICAgICAgICAgdmFyIGhhc2ggPSBlbGVtW2hhc2hLZXldO1xuXG4gICAgICAgICAgICAgICAgaWYgKCFoYXNoKSB7XG4gICAgICAgICAgICAgICAgICAgIGhhc2ggPSBlbGVtW2hhc2hLZXldID0ge307XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgcmV0dXJuIGhhc2g7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0sIHsgXCJpbmRpdmlkdWFsL29uZS12ZXJzaW9uXCI6IDkgfV0sIDg6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICAoZnVuY3Rpb24gKGdsb2JhbCkge1xuICAgICAgICAgICAgICAgICd1c2Ugc3RyaWN0JztcblxuICAgICAgICAgICAgICAgIC8qZ2xvYmFsIHdpbmRvdywgZ2xvYmFsKi9cblxuICAgICAgICAgICAgICAgIHZhciByb290ID0gdHlwZW9mIHdpbmRvdyAhPT0gJ3VuZGVmaW5lZCcgPyB3aW5kb3cgOiB0eXBlb2YgZ2xvYmFsICE9PSAndW5kZWZpbmVkJyA/IGdsb2JhbCA6IHt9O1xuXG4gICAgICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBJbmRpdmlkdWFsO1xuXG4gICAgICAgICAgICAgICAgZnVuY3Rpb24gSW5kaXZpZHVhbChrZXksIHZhbHVlKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmIChrZXkgaW4gcm9vdCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHJvb3Rba2V5XTtcbiAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgIHJvb3Rba2V5XSA9IHZhbHVlO1xuXG4gICAgICAgICAgICAgICAgICAgIHJldHVybiB2YWx1ZTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9KS5jYWxsKHRoaXMsIHR5cGVvZiBnbG9iYWwgIT09IFwidW5kZWZpbmVkXCIgPyBnbG9iYWwgOiB0eXBlb2Ygc2VsZiAhPT0gXCJ1bmRlZmluZWRcIiA/IHNlbGYgOiB0eXBlb2Ygd2luZG93ICE9PSBcInVuZGVmaW5lZFwiID8gd2luZG93IDoge30pO1xuICAgICAgICB9LCB7fV0sIDk6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICAndXNlIHN0cmljdCc7XG5cbiAgICAgICAgICAgIHZhciBJbmRpdmlkdWFsID0gcmVxdWlyZSgnLi9pbmRleC5qcycpO1xuXG4gICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IE9uZVZlcnNpb247XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIE9uZVZlcnNpb24obW9kdWxlTmFtZSwgdmVyc2lvbiwgZGVmYXVsdFZhbHVlKSB7XG4gICAgICAgICAgICAgICAgdmFyIGtleSA9ICdfX0lORElWSURVQUxfT05FX1ZFUlNJT05fJyArIG1vZHVsZU5hbWU7XG4gICAgICAgICAgICAgICAgdmFyIGVuZm9yY2VLZXkgPSBrZXkgKyAnX0VORk9SQ0VfU0lOR0xFVE9OJztcblxuICAgICAgICAgICAgICAgIHZhciB2ZXJzaW9uVmFsdWUgPSBJbmRpdmlkdWFsKGVuZm9yY2VLZXksIHZlcnNpb24pO1xuXG4gICAgICAgICAgICAgICAgaWYgKHZlcnNpb25WYWx1ZSAhPT0gdmVyc2lvbikge1xuICAgICAgICAgICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ0NhbiBvbmx5IGhhdmUgb25lIGNvcHkgb2YgJyArIG1vZHVsZU5hbWUgKyAnLlxcbicgKyAnWW91IGFscmVhZHkgaGF2ZSB2ZXJzaW9uICcgKyB2ZXJzaW9uVmFsdWUgKyAnIGluc3RhbGxlZC5cXG4nICsgJ1RoaXMgbWVhbnMgeW91IGNhbm5vdCBpbnN0YWxsIHZlcnNpb24gJyArIHZlcnNpb24pO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHJldHVybiBJbmRpdmlkdWFsKGtleSwgZGVmYXVsdFZhbHVlKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSwgeyBcIi4vaW5kZXguanNcIjogOCB9XSwgMTA6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICAoZnVuY3Rpb24gKGdsb2JhbCkge1xuICAgICAgICAgICAgICAgIHZhciB0b3BMZXZlbCA9IHR5cGVvZiBnbG9iYWwgIT09ICd1bmRlZmluZWQnID8gZ2xvYmFsIDogdHlwZW9mIHdpbmRvdyAhPT0gJ3VuZGVmaW5lZCcgPyB3aW5kb3cgOiB7fTtcbiAgICAgICAgICAgICAgICB2YXIgbWluRG9jID0gcmVxdWlyZSgnbWluLWRvY3VtZW50Jyk7XG5cbiAgICAgICAgICAgICAgICBpZiAodHlwZW9mIGRvY3VtZW50ICE9PSAndW5kZWZpbmVkJykge1xuICAgICAgICAgICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IGRvY3VtZW50O1xuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciBkb2NjeSA9IHRvcExldmVsWydfX0dMT0JBTF9ET0NVTUVOVF9DQUNIRUA0J107XG5cbiAgICAgICAgICAgICAgICAgICAgaWYgKCFkb2NjeSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgZG9jY3kgPSB0b3BMZXZlbFsnX19HTE9CQUxfRE9DVU1FTlRfQ0FDSEVANCddID0gbWluRG9jO1xuICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBkb2NjeTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9KS5jYWxsKHRoaXMsIHR5cGVvZiBnbG9iYWwgIT09IFwidW5kZWZpbmVkXCIgPyBnbG9iYWwgOiB0eXBlb2Ygc2VsZiAhPT0gXCJ1bmRlZmluZWRcIiA/IHNlbGYgOiB0eXBlb2Ygd2luZG93ICE9PSBcInVuZGVmaW5lZFwiID8gd2luZG93IDoge30pO1xuICAgICAgICB9LCB7IFwibWluLWRvY3VtZW50XCI6IDYgfV0sIDExOiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge1xuICAgICAgICAgICAgXCJ1c2Ugc3RyaWN0XCI7XG5cbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gaXNPYmplY3QoeCkge1xuICAgICAgICAgICAgICAgIHJldHVybiB0eXBlb2YgeCA9PT0gXCJvYmplY3RcIiAmJiB4ICE9PSBudWxsO1xuICAgICAgICAgICAgfTtcbiAgICAgICAgfSwge31dLCAxMjogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHtcbiAgICAgICAgICAgIHZhciBuYXRpdmVJc0FycmF5ID0gQXJyYXkuaXNBcnJheTtcbiAgICAgICAgICAgIHZhciB0b1N0cmluZyA9IE9iamVjdC5wcm90b3R5cGUudG9TdHJpbmc7XG5cbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gbmF0aXZlSXNBcnJheSB8fCBpc0FycmF5O1xuXG4gICAgICAgICAgICBmdW5jdGlvbiBpc0FycmF5KG9iaikge1xuICAgICAgICAgICAgICAgIHJldHVybiB0b1N0cmluZy5jYWxsKG9iaikgPT09IFwiW29iamVjdCBBcnJheV1cIjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSwge31dLCAxMzogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHtcbiAgICAgICAgICAgIHZhciBwYXRjaCA9IHJlcXVpcmUoXCIuL3Zkb20vcGF0Y2guanNcIik7XG5cbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gcGF0Y2g7XG4gICAgICAgIH0sIHsgXCIuL3Zkb20vcGF0Y2guanNcIjogMTggfV0sIDE0OiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge1xuICAgICAgICAgICAgdmFyIGlzT2JqZWN0ID0gcmVxdWlyZShcImlzLW9iamVjdFwiKTtcbiAgICAgICAgICAgIHZhciBpc0hvb2sgPSByZXF1aXJlKFwiLi4vdm5vZGUvaXMtdmhvb2suanNcIik7XG5cbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gYXBwbHlQcm9wZXJ0aWVzO1xuXG4gICAgICAgICAgICBmdW5jdGlvbiBhcHBseVByb3BlcnRpZXMobm9kZSwgcHJvcHMsIHByZXZpb3VzKSB7XG4gICAgICAgICAgICAgICAgZm9yICh2YXIgcHJvcE5hbWUgaW4gcHJvcHMpIHtcbiAgICAgICAgICAgICAgICAgICAgdmFyIHByb3BWYWx1ZSA9IHByb3BzW3Byb3BOYW1lXTtcblxuICAgICAgICAgICAgICAgICAgICBpZiAocHJvcFZhbHVlID09PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJlbW92ZVByb3BlcnR5KG5vZGUsIHByb3BOYW1lLCBwcm9wVmFsdWUsIHByZXZpb3VzKTtcbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIGlmIChpc0hvb2socHJvcFZhbHVlKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgcmVtb3ZlUHJvcGVydHkobm9kZSwgcHJvcE5hbWUsIHByb3BWYWx1ZSwgcHJldmlvdXMpO1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHByb3BWYWx1ZS5ob29rKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcHJvcFZhbHVlLmhvb2sobm9kZSwgcHJvcE5hbWUsIHByZXZpb3VzID8gcHJldmlvdXNbcHJvcE5hbWVdIDogdW5kZWZpbmVkKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChpc09iamVjdChwcm9wVmFsdWUpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcGF0Y2hPYmplY3Qobm9kZSwgcHJvcHMsIHByZXZpb3VzLCBwcm9wTmFtZSwgcHJvcFZhbHVlKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgbm9kZVtwcm9wTmFtZV0gPSBwcm9wVmFsdWU7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIHJlbW92ZVByb3BlcnR5KG5vZGUsIHByb3BOYW1lLCBwcm9wVmFsdWUsIHByZXZpb3VzKSB7XG4gICAgICAgICAgICAgICAgaWYgKHByZXZpb3VzKSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciBwcmV2aW91c1ZhbHVlID0gcHJldmlvdXNbcHJvcE5hbWVdO1xuXG4gICAgICAgICAgICAgICAgICAgIGlmICghaXNIb29rKHByZXZpb3VzVmFsdWUpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAocHJvcE5hbWUgPT09IFwiYXR0cmlidXRlc1wiKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgZm9yICh2YXIgYXR0ck5hbWUgaW4gcHJldmlvdXNWYWx1ZSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBub2RlLnJlbW92ZUF0dHJpYnV0ZShhdHRyTmFtZSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIGlmIChwcm9wTmFtZSA9PT0gXCJzdHlsZVwiKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgZm9yICh2YXIgaSBpbiBwcmV2aW91c1ZhbHVlKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG5vZGUuc3R5bGVbaV0gPSBcIlwiO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAodHlwZW9mIHByZXZpb3VzVmFsdWUgPT09IFwic3RyaW5nXCIpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBub2RlW3Byb3BOYW1lXSA9IFwiXCI7XG4gICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIG5vZGVbcHJvcE5hbWVdID0gbnVsbDtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIGlmIChwcmV2aW91c1ZhbHVlLnVuaG9vaykge1xuICAgICAgICAgICAgICAgICAgICAgICAgcHJldmlvdXNWYWx1ZS51bmhvb2sobm9kZSwgcHJvcE5hbWUsIHByb3BWYWx1ZSk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIHBhdGNoT2JqZWN0KG5vZGUsIHByb3BzLCBwcmV2aW91cywgcHJvcE5hbWUsIHByb3BWYWx1ZSkge1xuICAgICAgICAgICAgICAgIHZhciBwcmV2aW91c1ZhbHVlID0gcHJldmlvdXMgPyBwcmV2aW91c1twcm9wTmFtZV0gOiB1bmRlZmluZWQ7XG5cbiAgICAgICAgICAgICAgICAvLyBTZXQgYXR0cmlidXRlc1xuICAgICAgICAgICAgICAgIGlmIChwcm9wTmFtZSA9PT0gXCJhdHRyaWJ1dGVzXCIpIHtcbiAgICAgICAgICAgICAgICAgICAgZm9yICh2YXIgYXR0ck5hbWUgaW4gcHJvcFZhbHVlKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICB2YXIgYXR0clZhbHVlID0gcHJvcFZhbHVlW2F0dHJOYW1lXTtcblxuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGF0dHJWYWx1ZSA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgbm9kZS5yZW1vdmVBdHRyaWJ1dGUoYXR0ck5hbWUpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBub2RlLnNldEF0dHJpYnV0ZShhdHRyTmFtZSwgYXR0clZhbHVlKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICBpZiAocHJldmlvdXNWYWx1ZSAmJiBpc09iamVjdChwcmV2aW91c1ZhbHVlKSAmJiBnZXRQcm90b3R5cGUocHJldmlvdXNWYWx1ZSkgIT09IGdldFByb3RvdHlwZShwcm9wVmFsdWUpKSB7XG4gICAgICAgICAgICAgICAgICAgIG5vZGVbcHJvcE5hbWVdID0gcHJvcFZhbHVlO1xuICAgICAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgaWYgKCFpc09iamVjdChub2RlW3Byb3BOYW1lXSkpIHtcbiAgICAgICAgICAgICAgICAgICAgbm9kZVtwcm9wTmFtZV0gPSB7fTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICB2YXIgcmVwbGFjZXIgPSBwcm9wTmFtZSA9PT0gXCJzdHlsZVwiID8gXCJcIiA6IHVuZGVmaW5lZDtcblxuICAgICAgICAgICAgICAgIGZvciAodmFyIGsgaW4gcHJvcFZhbHVlKSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciB2YWx1ZSA9IHByb3BWYWx1ZVtrXTtcbiAgICAgICAgICAgICAgICAgICAgbm9kZVtwcm9wTmFtZV1ba10gPSB2YWx1ZSA9PT0gdW5kZWZpbmVkID8gcmVwbGFjZXIgOiB2YWx1ZTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIGdldFByb3RvdHlwZSh2YWx1ZSkge1xuICAgICAgICAgICAgICAgIGlmIChPYmplY3QuZ2V0UHJvdG90eXBlT2YpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIE9iamVjdC5nZXRQcm90b3R5cGVPZih2YWx1ZSk7XG4gICAgICAgICAgICAgICAgfSBlbHNlIGlmICh2YWx1ZS5fX3Byb3RvX18pIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHZhbHVlLl9fcHJvdG9fXztcbiAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKHZhbHVlLmNvbnN0cnVjdG9yKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiB2YWx1ZS5jb25zdHJ1Y3Rvci5wcm90b3R5cGU7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9LCB7IFwiLi4vdm5vZGUvaXMtdmhvb2suanNcIjogMjYsIFwiaXMtb2JqZWN0XCI6IDExIH1dLCAxNTogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHtcbiAgICAgICAgICAgIHZhciBkb2N1bWVudCA9IHJlcXVpcmUoXCJnbG9iYWwvZG9jdW1lbnRcIik7XG5cbiAgICAgICAgICAgIHZhciBhcHBseVByb3BlcnRpZXMgPSByZXF1aXJlKFwiLi9hcHBseS1wcm9wZXJ0aWVzXCIpO1xuXG4gICAgICAgICAgICB2YXIgaXNWTm9kZSA9IHJlcXVpcmUoXCIuLi92bm9kZS9pcy12bm9kZS5qc1wiKTtcbiAgICAgICAgICAgIHZhciBpc1ZUZXh0ID0gcmVxdWlyZShcIi4uL3Zub2RlL2lzLXZ0ZXh0LmpzXCIpO1xuICAgICAgICAgICAgdmFyIGlzV2lkZ2V0ID0gcmVxdWlyZShcIi4uL3Zub2RlL2lzLXdpZGdldC5qc1wiKTtcbiAgICAgICAgICAgIHZhciBoYW5kbGVUaHVuayA9IHJlcXVpcmUoXCIuLi92bm9kZS9oYW5kbGUtdGh1bmsuanNcIik7XG5cbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gY3JlYXRlRWxlbWVudDtcblxuICAgICAgICAgICAgZnVuY3Rpb24gY3JlYXRlRWxlbWVudCh2bm9kZSwgb3B0cykge1xuICAgICAgICAgICAgICAgIHZhciBkb2MgPSBvcHRzID8gb3B0cy5kb2N1bWVudCB8fCBkb2N1bWVudCA6IGRvY3VtZW50O1xuICAgICAgICAgICAgICAgIHZhciB3YXJuID0gb3B0cyA/IG9wdHMud2FybiA6IG51bGw7XG5cbiAgICAgICAgICAgICAgICB2bm9kZSA9IGhhbmRsZVRodW5rKHZub2RlKS5hO1xuXG4gICAgICAgICAgICAgICAgaWYgKGlzV2lkZ2V0KHZub2RlKSkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gdm5vZGUuaW5pdCgpO1xuICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoaXNWVGV4dCh2bm9kZSkpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGRvYy5jcmVhdGVUZXh0Tm9kZSh2bm9kZS50ZXh0KTtcbiAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKCFpc1ZOb2RlKHZub2RlKSkge1xuICAgICAgICAgICAgICAgICAgICBpZiAod2Fybikge1xuICAgICAgICAgICAgICAgICAgICAgICAgd2FybihcIkl0ZW0gaXMgbm90IGEgdmFsaWQgdmlydHVhbCBkb20gbm9kZVwiLCB2bm9kZSk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIG51bGw7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgdmFyIG5vZGUgPSB2bm9kZS5uYW1lc3BhY2UgPT09IG51bGwgPyBkb2MuY3JlYXRlRWxlbWVudCh2bm9kZS50YWdOYW1lKSA6IGRvYy5jcmVhdGVFbGVtZW50TlModm5vZGUubmFtZXNwYWNlLCB2bm9kZS50YWdOYW1lKTtcblxuICAgICAgICAgICAgICAgIHZhciBwcm9wcyA9IHZub2RlLnByb3BlcnRpZXM7XG4gICAgICAgICAgICAgICAgYXBwbHlQcm9wZXJ0aWVzKG5vZGUsIHByb3BzKTtcblxuICAgICAgICAgICAgICAgIHZhciBjaGlsZHJlbiA9IHZub2RlLmNoaWxkcmVuO1xuXG4gICAgICAgICAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCBjaGlsZHJlbi5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgICAgICAgICB2YXIgY2hpbGROb2RlID0gY3JlYXRlRWxlbWVudChjaGlsZHJlbltpXSwgb3B0cyk7XG4gICAgICAgICAgICAgICAgICAgIGlmIChjaGlsZE5vZGUpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIG5vZGUuYXBwZW5kQ2hpbGQoY2hpbGROb2RlKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHJldHVybiBub2RlO1xuICAgICAgICAgICAgfVxuICAgICAgICB9LCB7IFwiLi4vdm5vZGUvaGFuZGxlLXRodW5rLmpzXCI6IDI0LCBcIi4uL3Zub2RlL2lzLXZub2RlLmpzXCI6IDI3LCBcIi4uL3Zub2RlL2lzLXZ0ZXh0LmpzXCI6IDI4LCBcIi4uL3Zub2RlL2lzLXdpZGdldC5qc1wiOiAyOSwgXCIuL2FwcGx5LXByb3BlcnRpZXNcIjogMTQsIFwiZ2xvYmFsL2RvY3VtZW50XCI6IDEwIH1dLCAxNjogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHtcbiAgICAgICAgICAgIC8vIE1hcHMgYSB2aXJ0dWFsIERPTSB0cmVlIG9udG8gYSByZWFsIERPTSB0cmVlIGluIGFuIGVmZmljaWVudCBtYW5uZXIuXG4gICAgICAgICAgICAvLyBXZSBkb24ndCB3YW50IHRvIHJlYWQgYWxsIG9mIHRoZSBET00gbm9kZXMgaW4gdGhlIHRyZWUgc28gd2UgdXNlXG4gICAgICAgICAgICAvLyB0aGUgaW4tb3JkZXIgdHJlZSBpbmRleGluZyB0byBlbGltaW5hdGUgcmVjdXJzaW9uIGRvd24gY2VydGFpbiBicmFuY2hlcy5cbiAgICAgICAgICAgIC8vIFdlIG9ubHkgcmVjdXJzZSBpbnRvIGEgRE9NIG5vZGUgaWYgd2Uga25vdyB0aGF0IGl0IGNvbnRhaW5zIGEgY2hpbGQgb2ZcbiAgICAgICAgICAgIC8vIGludGVyZXN0LlxuXG4gICAgICAgICAgICB2YXIgbm9DaGlsZCA9IHt9O1xuXG4gICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IGRvbUluZGV4O1xuXG4gICAgICAgICAgICBmdW5jdGlvbiBkb21JbmRleChyb290Tm9kZSwgdHJlZSwgaW5kaWNlcywgbm9kZXMpIHtcbiAgICAgICAgICAgICAgICBpZiAoIWluZGljZXMgfHwgaW5kaWNlcy5sZW5ndGggPT09IDApIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHt9O1xuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIGluZGljZXMuc29ydChhc2NlbmRpbmcpO1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gcmVjdXJzZShyb290Tm9kZSwgdHJlZSwgaW5kaWNlcywgbm9kZXMsIDApO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZnVuY3Rpb24gcmVjdXJzZShyb290Tm9kZSwgdHJlZSwgaW5kaWNlcywgbm9kZXMsIHJvb3RJbmRleCkge1xuICAgICAgICAgICAgICAgIG5vZGVzID0gbm9kZXMgfHwge307XG5cbiAgICAgICAgICAgICAgICBpZiAocm9vdE5vZGUpIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKGluZGV4SW5SYW5nZShpbmRpY2VzLCByb290SW5kZXgsIHJvb3RJbmRleCkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIG5vZGVzW3Jvb3RJbmRleF0gPSByb290Tm9kZTtcbiAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgIHZhciB2Q2hpbGRyZW4gPSB0cmVlLmNoaWxkcmVuO1xuXG4gICAgICAgICAgICAgICAgICAgIGlmICh2Q2hpbGRyZW4pIHtcblxuICAgICAgICAgICAgICAgICAgICAgICAgdmFyIGNoaWxkTm9kZXMgPSByb290Tm9kZS5jaGlsZE5vZGVzO1xuXG4gICAgICAgICAgICAgICAgICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IHRyZWUuY2hpbGRyZW4ubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICByb290SW5kZXggKz0gMTtcblxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZhciB2Q2hpbGQgPSB2Q2hpbGRyZW5baV0gfHwgbm9DaGlsZDtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB2YXIgbmV4dEluZGV4ID0gcm9vdEluZGV4ICsgKHZDaGlsZC5jb3VudCB8fCAwKTtcblxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIHNraXAgcmVjdXJzaW9uIGRvd24gdGhlIHRyZWUgaWYgdGhlcmUgYXJlIG5vIG5vZGVzIGRvd24gaGVyZVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChpbmRleEluUmFuZ2UoaW5kaWNlcywgcm9vdEluZGV4LCBuZXh0SW5kZXgpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlY3Vyc2UoY2hpbGROb2Rlc1tpXSwgdkNoaWxkLCBpbmRpY2VzLCBub2Rlcywgcm9vdEluZGV4KTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICByb290SW5kZXggPSBuZXh0SW5kZXg7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICByZXR1cm4gbm9kZXM7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIC8vIEJpbmFyeSBzZWFyY2ggZm9yIGFuIGluZGV4IGluIHRoZSBpbnRlcnZhbCBbbGVmdCwgcmlnaHRdXG4gICAgICAgICAgICBmdW5jdGlvbiBpbmRleEluUmFuZ2UoaW5kaWNlcywgbGVmdCwgcmlnaHQpIHtcbiAgICAgICAgICAgICAgICBpZiAoaW5kaWNlcy5sZW5ndGggPT09IDApIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHZhciBtaW5JbmRleCA9IDA7XG4gICAgICAgICAgICAgICAgdmFyIG1heEluZGV4ID0gaW5kaWNlcy5sZW5ndGggLSAxO1xuICAgICAgICAgICAgICAgIHZhciBjdXJyZW50SW5kZXg7XG4gICAgICAgICAgICAgICAgdmFyIGN1cnJlbnRJdGVtO1xuXG4gICAgICAgICAgICAgICAgd2hpbGUgKG1pbkluZGV4IDw9IG1heEluZGV4KSB7XG4gICAgICAgICAgICAgICAgICAgIGN1cnJlbnRJbmRleCA9IChtYXhJbmRleCArIG1pbkluZGV4KSAvIDIgPj4gMDtcbiAgICAgICAgICAgICAgICAgICAgY3VycmVudEl0ZW0gPSBpbmRpY2VzW2N1cnJlbnRJbmRleF07XG5cbiAgICAgICAgICAgICAgICAgICAgaWYgKG1pbkluZGV4ID09PSBtYXhJbmRleCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGN1cnJlbnRJdGVtID49IGxlZnQgJiYgY3VycmVudEl0ZW0gPD0gcmlnaHQ7XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoY3VycmVudEl0ZW0gPCBsZWZ0KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBtaW5JbmRleCA9IGN1cnJlbnRJbmRleCArIDE7XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoY3VycmVudEl0ZW0gPiByaWdodCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgbWF4SW5kZXggPSBjdXJyZW50SW5kZXggLSAxO1xuICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIGFzY2VuZGluZyhhLCBiKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGEgPiBiID8gMSA6IC0xO1xuICAgICAgICAgICAgfVxuICAgICAgICB9LCB7fV0sIDE3OiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge1xuICAgICAgICAgICAgdmFyIGFwcGx5UHJvcGVydGllcyA9IHJlcXVpcmUoXCIuL2FwcGx5LXByb3BlcnRpZXNcIik7XG5cbiAgICAgICAgICAgIHZhciBpc1dpZGdldCA9IHJlcXVpcmUoXCIuLi92bm9kZS9pcy13aWRnZXQuanNcIik7XG4gICAgICAgICAgICB2YXIgVlBhdGNoID0gcmVxdWlyZShcIi4uL3Zub2RlL3ZwYXRjaC5qc1wiKTtcblxuICAgICAgICAgICAgdmFyIHVwZGF0ZVdpZGdldCA9IHJlcXVpcmUoXCIuL3VwZGF0ZS13aWRnZXRcIik7XG5cbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gYXBwbHlQYXRjaDtcblxuICAgICAgICAgICAgZnVuY3Rpb24gYXBwbHlQYXRjaCh2cGF0Y2gsIGRvbU5vZGUsIHJlbmRlck9wdGlvbnMpIHtcbiAgICAgICAgICAgICAgICB2YXIgdHlwZSA9IHZwYXRjaC50eXBlO1xuICAgICAgICAgICAgICAgIHZhciB2Tm9kZSA9IHZwYXRjaC52Tm9kZTtcbiAgICAgICAgICAgICAgICB2YXIgcGF0Y2ggPSB2cGF0Y2gucGF0Y2g7XG5cbiAgICAgICAgICAgICAgICBzd2l0Y2ggKHR5cGUpIHtcbiAgICAgICAgICAgICAgICAgICAgY2FzZSBWUGF0Y2guUkVNT1ZFOlxuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHJlbW92ZU5vZGUoZG9tTm9kZSwgdk5vZGUpO1xuICAgICAgICAgICAgICAgICAgICBjYXNlIFZQYXRjaC5JTlNFUlQ6XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gaW5zZXJ0Tm9kZShkb21Ob2RlLCBwYXRjaCwgcmVuZGVyT3B0aW9ucyk7XG4gICAgICAgICAgICAgICAgICAgIGNhc2UgVlBhdGNoLlZURVhUOlxuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHN0cmluZ1BhdGNoKGRvbU5vZGUsIHZOb2RlLCBwYXRjaCwgcmVuZGVyT3B0aW9ucyk7XG4gICAgICAgICAgICAgICAgICAgIGNhc2UgVlBhdGNoLldJREdFVDpcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiB3aWRnZXRQYXRjaChkb21Ob2RlLCB2Tm9kZSwgcGF0Y2gsIHJlbmRlck9wdGlvbnMpO1xuICAgICAgICAgICAgICAgICAgICBjYXNlIFZQYXRjaC5WTk9ERTpcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiB2Tm9kZVBhdGNoKGRvbU5vZGUsIHZOb2RlLCBwYXRjaCwgcmVuZGVyT3B0aW9ucyk7XG4gICAgICAgICAgICAgICAgICAgIGNhc2UgVlBhdGNoLk9SREVSOlxuICAgICAgICAgICAgICAgICAgICAgICAgcmVvcmRlckNoaWxkcmVuKGRvbU5vZGUsIHBhdGNoKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBkb21Ob2RlO1xuICAgICAgICAgICAgICAgICAgICBjYXNlIFZQYXRjaC5QUk9QUzpcbiAgICAgICAgICAgICAgICAgICAgICAgIGFwcGx5UHJvcGVydGllcyhkb21Ob2RlLCBwYXRjaCwgdk5vZGUucHJvcGVydGllcyk7XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gZG9tTm9kZTtcbiAgICAgICAgICAgICAgICAgICAgY2FzZSBWUGF0Y2guVEhVTks6XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gcmVwbGFjZVJvb3QoZG9tTm9kZSwgcmVuZGVyT3B0aW9ucy5wYXRjaChkb21Ob2RlLCBwYXRjaCwgcmVuZGVyT3B0aW9ucykpO1xuICAgICAgICAgICAgICAgICAgICBkZWZhdWx0OlxuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGRvbU5vZGU7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBmdW5jdGlvbiByZW1vdmVOb2RlKGRvbU5vZGUsIHZOb2RlKSB7XG4gICAgICAgICAgICAgICAgdmFyIHBhcmVudE5vZGUgPSBkb21Ob2RlLnBhcmVudE5vZGU7XG5cbiAgICAgICAgICAgICAgICBpZiAocGFyZW50Tm9kZSkge1xuICAgICAgICAgICAgICAgICAgICBwYXJlbnROb2RlLnJlbW92ZUNoaWxkKGRvbU5vZGUpO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIGRlc3Ryb3lXaWRnZXQoZG9tTm9kZSwgdk5vZGUpO1xuXG4gICAgICAgICAgICAgICAgcmV0dXJuIG51bGw7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIGluc2VydE5vZGUocGFyZW50Tm9kZSwgdk5vZGUsIHJlbmRlck9wdGlvbnMpIHtcbiAgICAgICAgICAgICAgICB2YXIgbmV3Tm9kZSA9IHJlbmRlck9wdGlvbnMucmVuZGVyKHZOb2RlLCByZW5kZXJPcHRpb25zKTtcblxuICAgICAgICAgICAgICAgIGlmIChwYXJlbnROb2RlKSB7XG4gICAgICAgICAgICAgICAgICAgIHBhcmVudE5vZGUuYXBwZW5kQ2hpbGQobmV3Tm9kZSk7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgcmV0dXJuIHBhcmVudE5vZGU7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIHN0cmluZ1BhdGNoKGRvbU5vZGUsIGxlZnRWTm9kZSwgdlRleHQsIHJlbmRlck9wdGlvbnMpIHtcbiAgICAgICAgICAgICAgICB2YXIgbmV3Tm9kZTtcblxuICAgICAgICAgICAgICAgIGlmIChkb21Ob2RlLm5vZGVUeXBlID09PSAzKSB7XG4gICAgICAgICAgICAgICAgICAgIGRvbU5vZGUucmVwbGFjZURhdGEoMCwgZG9tTm9kZS5sZW5ndGgsIHZUZXh0LnRleHQpO1xuICAgICAgICAgICAgICAgICAgICBuZXdOb2RlID0gZG9tTm9kZTtcbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICB2YXIgcGFyZW50Tm9kZSA9IGRvbU5vZGUucGFyZW50Tm9kZTtcbiAgICAgICAgICAgICAgICAgICAgbmV3Tm9kZSA9IHJlbmRlck9wdGlvbnMucmVuZGVyKHZUZXh0LCByZW5kZXJPcHRpb25zKTtcblxuICAgICAgICAgICAgICAgICAgICBpZiAocGFyZW50Tm9kZSAmJiBuZXdOb2RlICE9PSBkb21Ob2RlKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBwYXJlbnROb2RlLnJlcGxhY2VDaGlsZChuZXdOb2RlLCBkb21Ob2RlKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHJldHVybiBuZXdOb2RlO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBmdW5jdGlvbiB3aWRnZXRQYXRjaChkb21Ob2RlLCBsZWZ0Vk5vZGUsIHdpZGdldCwgcmVuZGVyT3B0aW9ucykge1xuICAgICAgICAgICAgICAgIHZhciB1cGRhdGluZyA9IHVwZGF0ZVdpZGdldChsZWZ0Vk5vZGUsIHdpZGdldCk7XG4gICAgICAgICAgICAgICAgdmFyIG5ld05vZGU7XG5cbiAgICAgICAgICAgICAgICBpZiAodXBkYXRpbmcpIHtcbiAgICAgICAgICAgICAgICAgICAgbmV3Tm9kZSA9IHdpZGdldC51cGRhdGUobGVmdFZOb2RlLCBkb21Ob2RlKSB8fCBkb21Ob2RlO1xuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIG5ld05vZGUgPSByZW5kZXJPcHRpb25zLnJlbmRlcih3aWRnZXQsIHJlbmRlck9wdGlvbnMpO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHZhciBwYXJlbnROb2RlID0gZG9tTm9kZS5wYXJlbnROb2RlO1xuXG4gICAgICAgICAgICAgICAgaWYgKHBhcmVudE5vZGUgJiYgbmV3Tm9kZSAhPT0gZG9tTm9kZSkge1xuICAgICAgICAgICAgICAgICAgICBwYXJlbnROb2RlLnJlcGxhY2VDaGlsZChuZXdOb2RlLCBkb21Ob2RlKTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICBpZiAoIXVwZGF0aW5nKSB7XG4gICAgICAgICAgICAgICAgICAgIGRlc3Ryb3lXaWRnZXQoZG9tTm9kZSwgbGVmdFZOb2RlKTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICByZXR1cm4gbmV3Tm9kZTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZnVuY3Rpb24gdk5vZGVQYXRjaChkb21Ob2RlLCBsZWZ0Vk5vZGUsIHZOb2RlLCByZW5kZXJPcHRpb25zKSB7XG4gICAgICAgICAgICAgICAgdmFyIHBhcmVudE5vZGUgPSBkb21Ob2RlLnBhcmVudE5vZGU7XG4gICAgICAgICAgICAgICAgdmFyIG5ld05vZGUgPSByZW5kZXJPcHRpb25zLnJlbmRlcih2Tm9kZSwgcmVuZGVyT3B0aW9ucyk7XG5cbiAgICAgICAgICAgICAgICBpZiAocGFyZW50Tm9kZSAmJiBuZXdOb2RlICE9PSBkb21Ob2RlKSB7XG4gICAgICAgICAgICAgICAgICAgIHBhcmVudE5vZGUucmVwbGFjZUNoaWxkKG5ld05vZGUsIGRvbU5vZGUpO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHJldHVybiBuZXdOb2RlO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBmdW5jdGlvbiBkZXN0cm95V2lkZ2V0KGRvbU5vZGUsIHcpIHtcbiAgICAgICAgICAgICAgICBpZiAodHlwZW9mIHcuZGVzdHJveSA9PT0gXCJmdW5jdGlvblwiICYmIGlzV2lkZ2V0KHcpKSB7XG4gICAgICAgICAgICAgICAgICAgIHcuZGVzdHJveShkb21Ob2RlKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIHJlb3JkZXJDaGlsZHJlbihkb21Ob2RlLCBtb3Zlcykge1xuICAgICAgICAgICAgICAgIHZhciBjaGlsZE5vZGVzID0gZG9tTm9kZS5jaGlsZE5vZGVzO1xuICAgICAgICAgICAgICAgIHZhciBrZXlNYXAgPSB7fTtcbiAgICAgICAgICAgICAgICB2YXIgbm9kZTtcbiAgICAgICAgICAgICAgICB2YXIgcmVtb3ZlO1xuICAgICAgICAgICAgICAgIHZhciBpbnNlcnQ7XG5cbiAgICAgICAgICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IG1vdmVzLnJlbW92ZXMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgICAgICAgICAgcmVtb3ZlID0gbW92ZXMucmVtb3Zlc1tpXTtcbiAgICAgICAgICAgICAgICAgICAgbm9kZSA9IGNoaWxkTm9kZXNbcmVtb3ZlLmZyb21dO1xuICAgICAgICAgICAgICAgICAgICBpZiAocmVtb3ZlLmtleSkge1xuICAgICAgICAgICAgICAgICAgICAgICAga2V5TWFwW3JlbW92ZS5rZXldID0gbm9kZTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICBkb21Ob2RlLnJlbW92ZUNoaWxkKG5vZGUpO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHZhciBsZW5ndGggPSBjaGlsZE5vZGVzLmxlbmd0aDtcbiAgICAgICAgICAgICAgICBmb3IgKHZhciBqID0gMDsgaiA8IG1vdmVzLmluc2VydHMubGVuZ3RoOyBqKyspIHtcbiAgICAgICAgICAgICAgICAgICAgaW5zZXJ0ID0gbW92ZXMuaW5zZXJ0c1tqXTtcbiAgICAgICAgICAgICAgICAgICAgbm9kZSA9IGtleU1hcFtpbnNlcnQua2V5XTtcbiAgICAgICAgICAgICAgICAgICAgLy8gdGhpcyBpcyB0aGUgd2VpcmRlc3QgYnVnIGkndmUgZXZlciBzZWVuIGluIHdlYmtpdFxuICAgICAgICAgICAgICAgICAgICBkb21Ob2RlLmluc2VydEJlZm9yZShub2RlLCBpbnNlcnQudG8gPj0gbGVuZ3RoKysgPyBudWxsIDogY2hpbGROb2Rlc1tpbnNlcnQudG9dKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIHJlcGxhY2VSb290KG9sZFJvb3QsIG5ld1Jvb3QpIHtcbiAgICAgICAgICAgICAgICBpZiAob2xkUm9vdCAmJiBuZXdSb290ICYmIG9sZFJvb3QgIT09IG5ld1Jvb3QgJiYgb2xkUm9vdC5wYXJlbnROb2RlKSB7XG4gICAgICAgICAgICAgICAgICAgIG9sZFJvb3QucGFyZW50Tm9kZS5yZXBsYWNlQ2hpbGQobmV3Um9vdCwgb2xkUm9vdCk7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgcmV0dXJuIG5ld1Jvb3Q7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0sIHsgXCIuLi92bm9kZS9pcy13aWRnZXQuanNcIjogMjksIFwiLi4vdm5vZGUvdnBhdGNoLmpzXCI6IDMyLCBcIi4vYXBwbHktcHJvcGVydGllc1wiOiAxNCwgXCIuL3VwZGF0ZS13aWRnZXRcIjogMTkgfV0sIDE4OiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge1xuICAgICAgICAgICAgdmFyIGRvY3VtZW50ID0gcmVxdWlyZShcImdsb2JhbC9kb2N1bWVudFwiKTtcbiAgICAgICAgICAgIHZhciBpc0FycmF5ID0gcmVxdWlyZShcIngtaXMtYXJyYXlcIik7XG5cbiAgICAgICAgICAgIHZhciByZW5kZXIgPSByZXF1aXJlKFwiLi9jcmVhdGUtZWxlbWVudFwiKTtcbiAgICAgICAgICAgIHZhciBkb21JbmRleCA9IHJlcXVpcmUoXCIuL2RvbS1pbmRleFwiKTtcbiAgICAgICAgICAgIHZhciBwYXRjaE9wID0gcmVxdWlyZShcIi4vcGF0Y2gtb3BcIik7XG4gICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IHBhdGNoO1xuXG4gICAgICAgICAgICBmdW5jdGlvbiBwYXRjaChyb290Tm9kZSwgcGF0Y2hlcywgcmVuZGVyT3B0aW9ucykge1xuICAgICAgICAgICAgICAgIHJlbmRlck9wdGlvbnMgPSByZW5kZXJPcHRpb25zIHx8IHt9O1xuICAgICAgICAgICAgICAgIHJlbmRlck9wdGlvbnMucGF0Y2ggPSByZW5kZXJPcHRpb25zLnBhdGNoICYmIHJlbmRlck9wdGlvbnMucGF0Y2ggIT09IHBhdGNoID8gcmVuZGVyT3B0aW9ucy5wYXRjaCA6IHBhdGNoUmVjdXJzaXZlO1xuICAgICAgICAgICAgICAgIHJlbmRlck9wdGlvbnMucmVuZGVyID0gcmVuZGVyT3B0aW9ucy5yZW5kZXIgfHwgcmVuZGVyO1xuXG4gICAgICAgICAgICAgICAgcmV0dXJuIHJlbmRlck9wdGlvbnMucGF0Y2gocm9vdE5vZGUsIHBhdGNoZXMsIHJlbmRlck9wdGlvbnMpO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBmdW5jdGlvbiBwYXRjaFJlY3Vyc2l2ZShyb290Tm9kZSwgcGF0Y2hlcywgcmVuZGVyT3B0aW9ucykge1xuICAgICAgICAgICAgICAgIHZhciBpbmRpY2VzID0gcGF0Y2hJbmRpY2VzKHBhdGNoZXMpO1xuXG4gICAgICAgICAgICAgICAgaWYgKGluZGljZXMubGVuZ3RoID09PSAwKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiByb290Tm9kZTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICB2YXIgaW5kZXggPSBkb21JbmRleChyb290Tm9kZSwgcGF0Y2hlcy5hLCBpbmRpY2VzKTtcbiAgICAgICAgICAgICAgICB2YXIgb3duZXJEb2N1bWVudCA9IHJvb3ROb2RlLm93bmVyRG9jdW1lbnQ7XG5cbiAgICAgICAgICAgICAgICBpZiAoIXJlbmRlck9wdGlvbnMuZG9jdW1lbnQgJiYgb3duZXJEb2N1bWVudCAhPT0gZG9jdW1lbnQpIHtcbiAgICAgICAgICAgICAgICAgICAgcmVuZGVyT3B0aW9ucy5kb2N1bWVudCA9IG93bmVyRG9jdW1lbnQ7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCBpbmRpY2VzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciBub2RlSW5kZXggPSBpbmRpY2VzW2ldO1xuICAgICAgICAgICAgICAgICAgICByb290Tm9kZSA9IGFwcGx5UGF0Y2gocm9vdE5vZGUsIGluZGV4W25vZGVJbmRleF0sIHBhdGNoZXNbbm9kZUluZGV4XSwgcmVuZGVyT3B0aW9ucyk7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgcmV0dXJuIHJvb3ROb2RlO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBmdW5jdGlvbiBhcHBseVBhdGNoKHJvb3ROb2RlLCBkb21Ob2RlLCBwYXRjaExpc3QsIHJlbmRlck9wdGlvbnMpIHtcbiAgICAgICAgICAgICAgICBpZiAoIWRvbU5vZGUpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHJvb3ROb2RlO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHZhciBuZXdOb2RlO1xuXG4gICAgICAgICAgICAgICAgaWYgKGlzQXJyYXkocGF0Y2hMaXN0KSkge1xuICAgICAgICAgICAgICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IHBhdGNoTGlzdC5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgICAgICAgICAgICAgbmV3Tm9kZSA9IHBhdGNoT3AocGF0Y2hMaXN0W2ldLCBkb21Ob2RlLCByZW5kZXJPcHRpb25zKTtcblxuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGRvbU5vZGUgPT09IHJvb3ROb2RlKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcm9vdE5vZGUgPSBuZXdOb2RlO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgbmV3Tm9kZSA9IHBhdGNoT3AocGF0Y2hMaXN0LCBkb21Ob2RlLCByZW5kZXJPcHRpb25zKTtcblxuICAgICAgICAgICAgICAgICAgICBpZiAoZG9tTm9kZSA9PT0gcm9vdE5vZGUpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJvb3ROb2RlID0gbmV3Tm9kZTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHJldHVybiByb290Tm9kZTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZnVuY3Rpb24gcGF0Y2hJbmRpY2VzKHBhdGNoZXMpIHtcbiAgICAgICAgICAgICAgICB2YXIgaW5kaWNlcyA9IFtdO1xuXG4gICAgICAgICAgICAgICAgZm9yICh2YXIga2V5IGluIHBhdGNoZXMpIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKGtleSAhPT0gXCJhXCIpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGluZGljZXMucHVzaChOdW1iZXIoa2V5KSk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICByZXR1cm4gaW5kaWNlcztcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSwgeyBcIi4vY3JlYXRlLWVsZW1lbnRcIjogMTUsIFwiLi9kb20taW5kZXhcIjogMTYsIFwiLi9wYXRjaC1vcFwiOiAxNywgXCJnbG9iYWwvZG9jdW1lbnRcIjogMTAsIFwieC1pcy1hcnJheVwiOiAxMiB9XSwgMTk6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICB2YXIgaXNXaWRnZXQgPSByZXF1aXJlKFwiLi4vdm5vZGUvaXMtd2lkZ2V0LmpzXCIpO1xuXG4gICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IHVwZGF0ZVdpZGdldDtcblxuICAgICAgICAgICAgZnVuY3Rpb24gdXBkYXRlV2lkZ2V0KGEsIGIpIHtcbiAgICAgICAgICAgICAgICBpZiAoaXNXaWRnZXQoYSkgJiYgaXNXaWRnZXQoYikpIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKFwibmFtZVwiIGluIGEgJiYgXCJuYW1lXCIgaW4gYikge1xuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGEuaWQgPT09IGIuaWQ7XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gYS5pbml0ID09PSBiLmluaXQ7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0sIHsgXCIuLi92bm9kZS9pcy13aWRnZXQuanNcIjogMjkgfV0sIDIwOiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge1xuICAgICAgICAgICAgJ3VzZSBzdHJpY3QnO1xuXG4gICAgICAgICAgICB2YXIgRXZTdG9yZSA9IHJlcXVpcmUoJ2V2LXN0b3JlJyk7XG5cbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gRXZIb29rO1xuXG4gICAgICAgICAgICBmdW5jdGlvbiBFdkhvb2sodmFsdWUpIHtcbiAgICAgICAgICAgICAgICBpZiAoISh0aGlzIGluc3RhbmNlb2YgRXZIb29rKSkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gbmV3IEV2SG9vayh2YWx1ZSk7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgdGhpcy52YWx1ZSA9IHZhbHVlO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBFdkhvb2sucHJvdG90eXBlLmhvb2sgPSBmdW5jdGlvbiAobm9kZSwgcHJvcGVydHlOYW1lKSB7XG4gICAgICAgICAgICAgICAgdmFyIGVzID0gRXZTdG9yZShub2RlKTtcbiAgICAgICAgICAgICAgICB2YXIgcHJvcE5hbWUgPSBwcm9wZXJ0eU5hbWUuc3Vic3RyKDMpO1xuXG4gICAgICAgICAgICAgICAgZXNbcHJvcE5hbWVdID0gdGhpcy52YWx1ZTtcbiAgICAgICAgICAgIH07XG5cbiAgICAgICAgICAgIEV2SG9vay5wcm90b3R5cGUudW5ob29rID0gZnVuY3Rpb24gKG5vZGUsIHByb3BlcnR5TmFtZSkge1xuICAgICAgICAgICAgICAgIHZhciBlcyA9IEV2U3RvcmUobm9kZSk7XG4gICAgICAgICAgICAgICAgdmFyIHByb3BOYW1lID0gcHJvcGVydHlOYW1lLnN1YnN0cigzKTtcblxuICAgICAgICAgICAgICAgIGVzW3Byb3BOYW1lXSA9IHVuZGVmaW5lZDtcbiAgICAgICAgICAgIH07XG4gICAgICAgIH0sIHsgXCJldi1zdG9yZVwiOiA3IH1dLCAyMTogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHtcbiAgICAgICAgICAgICd1c2Ugc3RyaWN0JztcblxuICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBTb2Z0U2V0SG9vaztcblxuICAgICAgICAgICAgZnVuY3Rpb24gU29mdFNldEhvb2sodmFsdWUpIHtcbiAgICAgICAgICAgICAgICBpZiAoISh0aGlzIGluc3RhbmNlb2YgU29mdFNldEhvb2spKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBuZXcgU29mdFNldEhvb2sodmFsdWUpO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHRoaXMudmFsdWUgPSB2YWx1ZTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgU29mdFNldEhvb2sucHJvdG90eXBlLmhvb2sgPSBmdW5jdGlvbiAobm9kZSwgcHJvcGVydHlOYW1lKSB7XG4gICAgICAgICAgICAgICAgaWYgKG5vZGVbcHJvcGVydHlOYW1lXSAhPT0gdGhpcy52YWx1ZSkge1xuICAgICAgICAgICAgICAgICAgICBub2RlW3Byb3BlcnR5TmFtZV0gPSB0aGlzLnZhbHVlO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH07XG4gICAgICAgIH0sIHt9XSwgMjI6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICAndXNlIHN0cmljdCc7XG5cbiAgICAgICAgICAgIHZhciBpc0FycmF5ID0gcmVxdWlyZSgneC1pcy1hcnJheScpO1xuXG4gICAgICAgICAgICB2YXIgVk5vZGUgPSByZXF1aXJlKCcuLi92bm9kZS92bm9kZS5qcycpO1xuICAgICAgICAgICAgdmFyIFZUZXh0ID0gcmVxdWlyZSgnLi4vdm5vZGUvdnRleHQuanMnKTtcbiAgICAgICAgICAgIHZhciBpc1ZOb2RlID0gcmVxdWlyZSgnLi4vdm5vZGUvaXMtdm5vZGUnKTtcbiAgICAgICAgICAgIHZhciBpc1ZUZXh0ID0gcmVxdWlyZSgnLi4vdm5vZGUvaXMtdnRleHQnKTtcbiAgICAgICAgICAgIHZhciBpc1dpZGdldCA9IHJlcXVpcmUoJy4uL3Zub2RlL2lzLXdpZGdldCcpO1xuICAgICAgICAgICAgdmFyIGlzSG9vayA9IHJlcXVpcmUoJy4uL3Zub2RlL2lzLXZob29rJyk7XG4gICAgICAgICAgICB2YXIgaXNWVGh1bmsgPSByZXF1aXJlKCcuLi92bm9kZS9pcy10aHVuaycpO1xuXG4gICAgICAgICAgICB2YXIgcGFyc2VUYWcgPSByZXF1aXJlKCcuL3BhcnNlLXRhZy5qcycpO1xuICAgICAgICAgICAgdmFyIHNvZnRTZXRIb29rID0gcmVxdWlyZSgnLi9ob29rcy9zb2Z0LXNldC1ob29rLmpzJyk7XG4gICAgICAgICAgICB2YXIgZXZIb29rID0gcmVxdWlyZSgnLi9ob29rcy9ldi1ob29rLmpzJyk7XG5cbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gaDtcblxuICAgICAgICAgICAgZnVuY3Rpb24gaCh0YWdOYW1lLCBwcm9wZXJ0aWVzLCBjaGlsZHJlbikge1xuICAgICAgICAgICAgICAgIHZhciBjaGlsZE5vZGVzID0gW107XG4gICAgICAgICAgICAgICAgdmFyIHRhZywgcHJvcHMsIGtleSwgbmFtZXNwYWNlO1xuXG4gICAgICAgICAgICAgICAgaWYgKCFjaGlsZHJlbiAmJiBpc0NoaWxkcmVuKHByb3BlcnRpZXMpKSB7XG4gICAgICAgICAgICAgICAgICAgIGNoaWxkcmVuID0gcHJvcGVydGllcztcbiAgICAgICAgICAgICAgICAgICAgcHJvcHMgPSB7fTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICBwcm9wcyA9IHByb3BzIHx8IHByb3BlcnRpZXMgfHwge307XG4gICAgICAgICAgICAgICAgdGFnID0gcGFyc2VUYWcodGFnTmFtZSwgcHJvcHMpO1xuXG4gICAgICAgICAgICAgICAgLy8gc3VwcG9ydCBrZXlzXG4gICAgICAgICAgICAgICAgaWYgKHByb3BzLmhhc093blByb3BlcnR5KCdrZXknKSkge1xuICAgICAgICAgICAgICAgICAgICBrZXkgPSBwcm9wcy5rZXk7XG4gICAgICAgICAgICAgICAgICAgIHByb3BzLmtleSA9IHVuZGVmaW5lZDtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAvLyBzdXBwb3J0IG5hbWVzcGFjZVxuICAgICAgICAgICAgICAgIGlmIChwcm9wcy5oYXNPd25Qcm9wZXJ0eSgnbmFtZXNwYWNlJykpIHtcbiAgICAgICAgICAgICAgICAgICAgbmFtZXNwYWNlID0gcHJvcHMubmFtZXNwYWNlO1xuICAgICAgICAgICAgICAgICAgICBwcm9wcy5uYW1lc3BhY2UgPSB1bmRlZmluZWQ7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgLy8gZml4IGN1cnNvciBidWdcbiAgICAgICAgICAgICAgICBpZiAodGFnID09PSAnSU5QVVQnICYmICFuYW1lc3BhY2UgJiYgcHJvcHMuaGFzT3duUHJvcGVydHkoJ3ZhbHVlJykgJiYgcHJvcHMudmFsdWUgIT09IHVuZGVmaW5lZCAmJiAhaXNIb29rKHByb3BzLnZhbHVlKSkge1xuICAgICAgICAgICAgICAgICAgICBwcm9wcy52YWx1ZSA9IHNvZnRTZXRIb29rKHByb3BzLnZhbHVlKTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICB0cmFuc2Zvcm1Qcm9wZXJ0aWVzKHByb3BzKTtcblxuICAgICAgICAgICAgICAgIGlmIChjaGlsZHJlbiAhPT0gdW5kZWZpbmVkICYmIGNoaWxkcmVuICE9PSBudWxsKSB7XG4gICAgICAgICAgICAgICAgICAgIGFkZENoaWxkKGNoaWxkcmVuLCBjaGlsZE5vZGVzLCB0YWcsIHByb3BzKTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICByZXR1cm4gbmV3IFZOb2RlKHRhZywgcHJvcHMsIGNoaWxkTm9kZXMsIGtleSwgbmFtZXNwYWNlKTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZnVuY3Rpb24gYWRkQ2hpbGQoYywgY2hpbGROb2RlcywgdGFnLCBwcm9wcykge1xuICAgICAgICAgICAgICAgIGlmICh0eXBlb2YgYyA9PT0gJ3N0cmluZycpIHtcbiAgICAgICAgICAgICAgICAgICAgY2hpbGROb2Rlcy5wdXNoKG5ldyBWVGV4dChjKSk7XG4gICAgICAgICAgICAgICAgfSBlbHNlIGlmICh0eXBlb2YgYyA9PT0gJ251bWJlcicpIHtcbiAgICAgICAgICAgICAgICAgICAgY2hpbGROb2Rlcy5wdXNoKG5ldyBWVGV4dChTdHJpbmcoYykpKTtcbiAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKGlzQ2hpbGQoYykpIHtcbiAgICAgICAgICAgICAgICAgICAgY2hpbGROb2Rlcy5wdXNoKGMpO1xuICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoaXNBcnJheShjKSkge1xuICAgICAgICAgICAgICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IGMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGFkZENoaWxkKGNbaV0sIGNoaWxkTm9kZXMsIHRhZywgcHJvcHMpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfSBlbHNlIGlmIChjID09PSBudWxsIHx8IGMgPT09IHVuZGVmaW5lZCkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgdGhyb3cgVW5leHBlY3RlZFZpcnR1YWxFbGVtZW50KHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGZvcmVpZ25PYmplY3Q6IGMsXG4gICAgICAgICAgICAgICAgICAgICAgICBwYXJlbnRWbm9kZToge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRhZ05hbWU6IHRhZyxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBwcm9wZXJ0aWVzOiBwcm9wc1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIHRyYW5zZm9ybVByb3BlcnRpZXMocHJvcHMpIHtcbiAgICAgICAgICAgICAgICBmb3IgKHZhciBwcm9wTmFtZSBpbiBwcm9wcykge1xuICAgICAgICAgICAgICAgICAgICBpZiAocHJvcHMuaGFzT3duUHJvcGVydHkocHJvcE5hbWUpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICB2YXIgdmFsdWUgPSBwcm9wc1twcm9wTmFtZV07XG5cbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChpc0hvb2sodmFsdWUpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgY29udGludWU7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChwcm9wTmFtZS5zdWJzdHIoMCwgMykgPT09ICdldi0nKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gYWRkIGV2LWZvbyBzdXBwb3J0XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcHJvcHNbcHJvcE5hbWVdID0gZXZIb29rKHZhbHVlKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZnVuY3Rpb24gaXNDaGlsZCh4KSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGlzVk5vZGUoeCkgfHwgaXNWVGV4dCh4KSB8fCBpc1dpZGdldCh4KSB8fCBpc1ZUaHVuayh4KTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZnVuY3Rpb24gaXNDaGlsZHJlbih4KSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHR5cGVvZiB4ID09PSAnc3RyaW5nJyB8fCBpc0FycmF5KHgpIHx8IGlzQ2hpbGQoeCk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIFVuZXhwZWN0ZWRWaXJ0dWFsRWxlbWVudChkYXRhKSB7XG4gICAgICAgICAgICAgICAgdmFyIGVyciA9IG5ldyBFcnJvcigpO1xuXG4gICAgICAgICAgICAgICAgZXJyLnR5cGUgPSAndmlydHVhbC1oeXBlcnNjcmlwdC51bmV4cGVjdGVkLnZpcnR1YWwtZWxlbWVudCc7XG4gICAgICAgICAgICAgICAgZXJyLm1lc3NhZ2UgPSAnVW5leHBlY3RlZCB2aXJ0dWFsIGNoaWxkIHBhc3NlZCB0byBoKCkuXFxuJyArICdFeHBlY3RlZCBhIFZOb2RlIC8gVnRodW5rIC8gVldpZGdldCAvIHN0cmluZyBidXQ6XFxuJyArICdnb3Q6XFxuJyArIGVycm9yU3RyaW5nKGRhdGEuZm9yZWlnbk9iamVjdCkgKyAnLlxcbicgKyAnVGhlIHBhcmVudCB2bm9kZSBpczpcXG4nICsgZXJyb3JTdHJpbmcoZGF0YS5wYXJlbnRWbm9kZSk7XG4gICAgICAgICAgICAgICAgJ1xcbicgKyAnU3VnZ2VzdGVkIGZpeDogY2hhbmdlIHlvdXIgYGgoLi4uLCBbIC4uLiBdKWAgY2FsbHNpdGUuJztcbiAgICAgICAgICAgICAgICBlcnIuZm9yZWlnbk9iamVjdCA9IGRhdGEuZm9yZWlnbk9iamVjdDtcbiAgICAgICAgICAgICAgICBlcnIucGFyZW50Vm5vZGUgPSBkYXRhLnBhcmVudFZub2RlO1xuXG4gICAgICAgICAgICAgICAgcmV0dXJuIGVycjtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZnVuY3Rpb24gZXJyb3JTdHJpbmcob2JqKSB7XG4gICAgICAgICAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIEpTT04uc3RyaW5naWZ5KG9iaiwgbnVsbCwgJyAgICAnKTtcbiAgICAgICAgICAgICAgICB9IGNhdGNoIChlKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBTdHJpbmcob2JqKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH0sIHsgXCIuLi92bm9kZS9pcy10aHVua1wiOiAyNSwgXCIuLi92bm9kZS9pcy12aG9va1wiOiAyNiwgXCIuLi92bm9kZS9pcy12bm9kZVwiOiAyNywgXCIuLi92bm9kZS9pcy12dGV4dFwiOiAyOCwgXCIuLi92bm9kZS9pcy13aWRnZXRcIjogMjksIFwiLi4vdm5vZGUvdm5vZGUuanNcIjogMzEsIFwiLi4vdm5vZGUvdnRleHQuanNcIjogMzMsIFwiLi9ob29rcy9ldi1ob29rLmpzXCI6IDIwLCBcIi4vaG9va3Mvc29mdC1zZXQtaG9vay5qc1wiOiAyMSwgXCIuL3BhcnNlLXRhZy5qc1wiOiAyMywgXCJ4LWlzLWFycmF5XCI6IDEyIH1dLCAyMzogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHtcbiAgICAgICAgICAgICd1c2Ugc3RyaWN0JztcblxuICAgICAgICAgICAgdmFyIHNwbGl0ID0gcmVxdWlyZSgnYnJvd3Nlci1zcGxpdCcpO1xuXG4gICAgICAgICAgICB2YXIgY2xhc3NJZFNwbGl0ID0gLyhbXFwuI10/W2EtekEtWjAtOVxcdTAwN0YtXFx1RkZGRl86LV0rKS87XG4gICAgICAgICAgICB2YXIgbm90Q2xhc3NJZCA9IC9eXFwufCMvO1xuXG4gICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IHBhcnNlVGFnO1xuXG4gICAgICAgICAgICBmdW5jdGlvbiBwYXJzZVRhZyh0YWcsIHByb3BzKSB7XG4gICAgICAgICAgICAgICAgaWYgKCF0YWcpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuICdESVYnO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHZhciBub0lkID0gIXByb3BzLmhhc093blByb3BlcnR5KCdpZCcpO1xuXG4gICAgICAgICAgICAgICAgdmFyIHRhZ1BhcnRzID0gc3BsaXQodGFnLCBjbGFzc0lkU3BsaXQpO1xuICAgICAgICAgICAgICAgIHZhciB0YWdOYW1lID0gbnVsbDtcblxuICAgICAgICAgICAgICAgIGlmIChub3RDbGFzc0lkLnRlc3QodGFnUGFydHNbMV0pKSB7XG4gICAgICAgICAgICAgICAgICAgIHRhZ05hbWUgPSAnRElWJztcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICB2YXIgY2xhc3NlcywgcGFydCwgdHlwZSwgaTtcblxuICAgICAgICAgICAgICAgIGZvciAoaSA9IDA7IGkgPCB0YWdQYXJ0cy5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgICAgICAgICBwYXJ0ID0gdGFnUGFydHNbaV07XG5cbiAgICAgICAgICAgICAgICAgICAgaWYgKCFwYXJ0KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBjb250aW51ZTtcbiAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgIHR5cGUgPSBwYXJ0LmNoYXJBdCgwKTtcblxuICAgICAgICAgICAgICAgICAgICBpZiAoIXRhZ05hbWUpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHRhZ05hbWUgPSBwYXJ0O1xuICAgICAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKHR5cGUgPT09ICcuJykge1xuICAgICAgICAgICAgICAgICAgICAgICAgY2xhc3NlcyA9IGNsYXNzZXMgfHwgW107XG4gICAgICAgICAgICAgICAgICAgICAgICBjbGFzc2VzLnB1c2gocGFydC5zdWJzdHJpbmcoMSwgcGFydC5sZW5ndGgpKTtcbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIGlmICh0eXBlID09PSAnIycgJiYgbm9JZCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgcHJvcHMuaWQgPSBwYXJ0LnN1YnN0cmluZygxLCBwYXJ0Lmxlbmd0aCk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICBpZiAoY2xhc3Nlcykge1xuICAgICAgICAgICAgICAgICAgICBpZiAocHJvcHMuY2xhc3NOYW1lKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBjbGFzc2VzLnB1c2gocHJvcHMuY2xhc3NOYW1lKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgIHByb3BzLmNsYXNzTmFtZSA9IGNsYXNzZXMuam9pbignICcpO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHJldHVybiBwcm9wcy5uYW1lc3BhY2UgPyB0YWdOYW1lIDogdGFnTmFtZS50b1VwcGVyQ2FzZSgpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9LCB7IFwiYnJvd3Nlci1zcGxpdFwiOiA1IH1dLCAyNDogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHtcbiAgICAgICAgICAgIHZhciBpc1ZOb2RlID0gcmVxdWlyZShcIi4vaXMtdm5vZGVcIik7XG4gICAgICAgICAgICB2YXIgaXNWVGV4dCA9IHJlcXVpcmUoXCIuL2lzLXZ0ZXh0XCIpO1xuICAgICAgICAgICAgdmFyIGlzV2lkZ2V0ID0gcmVxdWlyZShcIi4vaXMtd2lkZ2V0XCIpO1xuICAgICAgICAgICAgdmFyIGlzVGh1bmsgPSByZXF1aXJlKFwiLi9pcy10aHVua1wiKTtcblxuICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBoYW5kbGVUaHVuaztcblxuICAgICAgICAgICAgZnVuY3Rpb24gaGFuZGxlVGh1bmsoYSwgYikge1xuICAgICAgICAgICAgICAgIHZhciByZW5kZXJlZEEgPSBhO1xuICAgICAgICAgICAgICAgIHZhciByZW5kZXJlZEIgPSBiO1xuXG4gICAgICAgICAgICAgICAgaWYgKGlzVGh1bmsoYikpIHtcbiAgICAgICAgICAgICAgICAgICAgcmVuZGVyZWRCID0gcmVuZGVyVGh1bmsoYiwgYSk7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgaWYgKGlzVGh1bmsoYSkpIHtcbiAgICAgICAgICAgICAgICAgICAgcmVuZGVyZWRBID0gcmVuZGVyVGh1bmsoYSwgbnVsbCk7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgICAgICAgICAgYTogcmVuZGVyZWRBLFxuICAgICAgICAgICAgICAgICAgICBiOiByZW5kZXJlZEJcbiAgICAgICAgICAgICAgICB9O1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBmdW5jdGlvbiByZW5kZXJUaHVuayh0aHVuaywgcHJldmlvdXMpIHtcbiAgICAgICAgICAgICAgICB2YXIgcmVuZGVyZWRUaHVuayA9IHRodW5rLnZub2RlO1xuXG4gICAgICAgICAgICAgICAgaWYgKCFyZW5kZXJlZFRodW5rKSB7XG4gICAgICAgICAgICAgICAgICAgIHJlbmRlcmVkVGh1bmsgPSB0aHVuay52bm9kZSA9IHRodW5rLnJlbmRlcihwcmV2aW91cyk7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgaWYgKCEoaXNWTm9kZShyZW5kZXJlZFRodW5rKSB8fCBpc1ZUZXh0KHJlbmRlcmVkVGh1bmspIHx8IGlzV2lkZ2V0KHJlbmRlcmVkVGh1bmspKSkge1xuICAgICAgICAgICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoXCJ0aHVuayBkaWQgbm90IHJldHVybiBhIHZhbGlkIG5vZGVcIik7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgcmV0dXJuIHJlbmRlcmVkVGh1bms7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0sIHsgXCIuL2lzLXRodW5rXCI6IDI1LCBcIi4vaXMtdm5vZGVcIjogMjcsIFwiLi9pcy12dGV4dFwiOiAyOCwgXCIuL2lzLXdpZGdldFwiOiAyOSB9XSwgMjU6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IGlzVGh1bms7XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIGlzVGh1bmsodCkge1xuICAgICAgICAgICAgICAgIHJldHVybiB0ICYmIHQudHlwZSA9PT0gXCJUaHVua1wiO1xuICAgICAgICAgICAgfVxuICAgICAgICB9LCB7fV0sIDI2OiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge1xuICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBpc0hvb2s7XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIGlzSG9vayhob29rKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGhvb2sgJiYgKHR5cGVvZiBob29rLmhvb2sgPT09IFwiZnVuY3Rpb25cIiAmJiAhaG9vay5oYXNPd25Qcm9wZXJ0eShcImhvb2tcIikgfHwgdHlwZW9mIGhvb2sudW5ob29rID09PSBcImZ1bmN0aW9uXCIgJiYgIWhvb2suaGFzT3duUHJvcGVydHkoXCJ1bmhvb2tcIikpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9LCB7fV0sIDI3OiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge1xuICAgICAgICAgICAgdmFyIHZlcnNpb24gPSByZXF1aXJlKFwiLi92ZXJzaW9uXCIpO1xuXG4gICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IGlzVmlydHVhbE5vZGU7XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIGlzVmlydHVhbE5vZGUoeCkge1xuICAgICAgICAgICAgICAgIHJldHVybiB4ICYmIHgudHlwZSA9PT0gXCJWaXJ0dWFsTm9kZVwiICYmIHgudmVyc2lvbiA9PT0gdmVyc2lvbjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSwgeyBcIi4vdmVyc2lvblwiOiAzMCB9XSwgMjg6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICB2YXIgdmVyc2lvbiA9IHJlcXVpcmUoXCIuL3ZlcnNpb25cIik7XG5cbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gaXNWaXJ0dWFsVGV4dDtcblxuICAgICAgICAgICAgZnVuY3Rpb24gaXNWaXJ0dWFsVGV4dCh4KSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHggJiYgeC50eXBlID09PSBcIlZpcnR1YWxUZXh0XCIgJiYgeC52ZXJzaW9uID09PSB2ZXJzaW9uO1xuICAgICAgICAgICAgfVxuICAgICAgICB9LCB7IFwiLi92ZXJzaW9uXCI6IDMwIH1dLCAyOTogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHtcbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gaXNXaWRnZXQ7XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIGlzV2lkZ2V0KHcpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gdyAmJiB3LnR5cGUgPT09IFwiV2lkZ2V0XCI7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0sIHt9XSwgMzA6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IFwiMlwiO1xuICAgICAgICB9LCB7fV0sIDMxOiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge1xuICAgICAgICAgICAgdmFyIHZlcnNpb24gPSByZXF1aXJlKFwiLi92ZXJzaW9uXCIpO1xuICAgICAgICAgICAgdmFyIGlzVk5vZGUgPSByZXF1aXJlKFwiLi9pcy12bm9kZVwiKTtcbiAgICAgICAgICAgIHZhciBpc1dpZGdldCA9IHJlcXVpcmUoXCIuL2lzLXdpZGdldFwiKTtcbiAgICAgICAgICAgIHZhciBpc1RodW5rID0gcmVxdWlyZShcIi4vaXMtdGh1bmtcIik7XG4gICAgICAgICAgICB2YXIgaXNWSG9vayA9IHJlcXVpcmUoXCIuL2lzLXZob29rXCIpO1xuXG4gICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IFZpcnR1YWxOb2RlO1xuXG4gICAgICAgICAgICB2YXIgbm9Qcm9wZXJ0aWVzID0ge307XG4gICAgICAgICAgICB2YXIgbm9DaGlsZHJlbiA9IFtdO1xuXG4gICAgICAgICAgICBmdW5jdGlvbiBWaXJ0dWFsTm9kZSh0YWdOYW1lLCBwcm9wZXJ0aWVzLCBjaGlsZHJlbiwga2V5LCBuYW1lc3BhY2UpIHtcbiAgICAgICAgICAgICAgICB0aGlzLnRhZ05hbWUgPSB0YWdOYW1lO1xuICAgICAgICAgICAgICAgIHRoaXMucHJvcGVydGllcyA9IHByb3BlcnRpZXMgfHwgbm9Qcm9wZXJ0aWVzO1xuICAgICAgICAgICAgICAgIHRoaXMuY2hpbGRyZW4gPSBjaGlsZHJlbiB8fCBub0NoaWxkcmVuO1xuICAgICAgICAgICAgICAgIHRoaXMua2V5ID0ga2V5ICE9IG51bGwgPyBTdHJpbmcoa2V5KSA6IHVuZGVmaW5lZDtcbiAgICAgICAgICAgICAgICB0aGlzLm5hbWVzcGFjZSA9IHR5cGVvZiBuYW1lc3BhY2UgPT09IFwic3RyaW5nXCIgPyBuYW1lc3BhY2UgOiBudWxsO1xuXG4gICAgICAgICAgICAgICAgdmFyIGNvdW50ID0gY2hpbGRyZW4gJiYgY2hpbGRyZW4ubGVuZ3RoIHx8IDA7XG4gICAgICAgICAgICAgICAgdmFyIGRlc2NlbmRhbnRzID0gMDtcbiAgICAgICAgICAgICAgICB2YXIgaGFzV2lkZ2V0cyA9IGZhbHNlO1xuICAgICAgICAgICAgICAgIHZhciBoYXNUaHVua3MgPSBmYWxzZTtcbiAgICAgICAgICAgICAgICB2YXIgZGVzY2VuZGFudEhvb2tzID0gZmFsc2U7XG4gICAgICAgICAgICAgICAgdmFyIGhvb2tzO1xuXG4gICAgICAgICAgICAgICAgZm9yICh2YXIgcHJvcE5hbWUgaW4gcHJvcGVydGllcykge1xuICAgICAgICAgICAgICAgICAgICBpZiAocHJvcGVydGllcy5oYXNPd25Qcm9wZXJ0eShwcm9wTmFtZSkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHZhciBwcm9wZXJ0eSA9IHByb3BlcnRpZXNbcHJvcE5hbWVdO1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGlzVkhvb2socHJvcGVydHkpICYmIHByb3BlcnR5LnVuaG9vaykge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmICghaG9va3MpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaG9va3MgPSB7fTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBob29rc1twcm9wTmFtZV0gPSBwcm9wZXJ0eTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgY291bnQ7IGkrKykge1xuICAgICAgICAgICAgICAgICAgICB2YXIgY2hpbGQgPSBjaGlsZHJlbltpXTtcbiAgICAgICAgICAgICAgICAgICAgaWYgKGlzVk5vZGUoY2hpbGQpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBkZXNjZW5kYW50cyArPSBjaGlsZC5jb3VudCB8fCAwO1xuXG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoIWhhc1dpZGdldHMgJiYgY2hpbGQuaGFzV2lkZ2V0cykge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGhhc1dpZGdldHMgPSB0cnVlO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoIWhhc1RodW5rcyAmJiBjaGlsZC5oYXNUaHVua3MpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBoYXNUaHVua3MgPSB0cnVlO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoIWRlc2NlbmRhbnRIb29rcyAmJiAoY2hpbGQuaG9va3MgfHwgY2hpbGQuZGVzY2VuZGFudEhvb2tzKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRlc2NlbmRhbnRIb29rcyA9IHRydWU7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoIWhhc1dpZGdldHMgJiYgaXNXaWRnZXQoY2hpbGQpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAodHlwZW9mIGNoaWxkLmRlc3Ryb3kgPT09IFwiZnVuY3Rpb25cIikge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGhhc1dpZGdldHMgPSB0cnVlO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKCFoYXNUaHVua3MgJiYgaXNUaHVuayhjaGlsZCkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGhhc1RodW5rcyA9IHRydWU7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICB0aGlzLmNvdW50ID0gY291bnQgKyBkZXNjZW5kYW50cztcbiAgICAgICAgICAgICAgICB0aGlzLmhhc1dpZGdldHMgPSBoYXNXaWRnZXRzO1xuICAgICAgICAgICAgICAgIHRoaXMuaGFzVGh1bmtzID0gaGFzVGh1bmtzO1xuICAgICAgICAgICAgICAgIHRoaXMuaG9va3MgPSBob29rcztcbiAgICAgICAgICAgICAgICB0aGlzLmRlc2NlbmRhbnRIb29rcyA9IGRlc2NlbmRhbnRIb29rcztcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgVmlydHVhbE5vZGUucHJvdG90eXBlLnZlcnNpb24gPSB2ZXJzaW9uO1xuICAgICAgICAgICAgVmlydHVhbE5vZGUucHJvdG90eXBlLnR5cGUgPSBcIlZpcnR1YWxOb2RlXCI7XG4gICAgICAgIH0sIHsgXCIuL2lzLXRodW5rXCI6IDI1LCBcIi4vaXMtdmhvb2tcIjogMjYsIFwiLi9pcy12bm9kZVwiOiAyNywgXCIuL2lzLXdpZGdldFwiOiAyOSwgXCIuL3ZlcnNpb25cIjogMzAgfV0sIDMyOiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge1xuICAgICAgICAgICAgdmFyIHZlcnNpb24gPSByZXF1aXJlKFwiLi92ZXJzaW9uXCIpO1xuXG4gICAgICAgICAgICBWaXJ0dWFsUGF0Y2guTk9ORSA9IDA7XG4gICAgICAgICAgICBWaXJ0dWFsUGF0Y2guVlRFWFQgPSAxO1xuICAgICAgICAgICAgVmlydHVhbFBhdGNoLlZOT0RFID0gMjtcbiAgICAgICAgICAgIFZpcnR1YWxQYXRjaC5XSURHRVQgPSAzO1xuICAgICAgICAgICAgVmlydHVhbFBhdGNoLlBST1BTID0gNDtcbiAgICAgICAgICAgIFZpcnR1YWxQYXRjaC5PUkRFUiA9IDU7XG4gICAgICAgICAgICBWaXJ0dWFsUGF0Y2guSU5TRVJUID0gNjtcbiAgICAgICAgICAgIFZpcnR1YWxQYXRjaC5SRU1PVkUgPSA3O1xuICAgICAgICAgICAgVmlydHVhbFBhdGNoLlRIVU5LID0gODtcblxuICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBWaXJ0dWFsUGF0Y2g7XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIFZpcnR1YWxQYXRjaCh0eXBlLCB2Tm9kZSwgcGF0Y2gpIHtcbiAgICAgICAgICAgICAgICB0aGlzLnR5cGUgPSBOdW1iZXIodHlwZSk7XG4gICAgICAgICAgICAgICAgdGhpcy52Tm9kZSA9IHZOb2RlO1xuICAgICAgICAgICAgICAgIHRoaXMucGF0Y2ggPSBwYXRjaDtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgVmlydHVhbFBhdGNoLnByb3RvdHlwZS52ZXJzaW9uID0gdmVyc2lvbjtcbiAgICAgICAgICAgIFZpcnR1YWxQYXRjaC5wcm90b3R5cGUudHlwZSA9IFwiVmlydHVhbFBhdGNoXCI7XG4gICAgICAgIH0sIHsgXCIuL3ZlcnNpb25cIjogMzAgfV0sIDMzOiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge1xuICAgICAgICAgICAgdmFyIHZlcnNpb24gPSByZXF1aXJlKFwiLi92ZXJzaW9uXCIpO1xuXG4gICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IFZpcnR1YWxUZXh0O1xuXG4gICAgICAgICAgICBmdW5jdGlvbiBWaXJ0dWFsVGV4dCh0ZXh0KSB7XG4gICAgICAgICAgICAgICAgdGhpcy50ZXh0ID0gU3RyaW5nKHRleHQpO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBWaXJ0dWFsVGV4dC5wcm90b3R5cGUudmVyc2lvbiA9IHZlcnNpb247XG4gICAgICAgICAgICBWaXJ0dWFsVGV4dC5wcm90b3R5cGUudHlwZSA9IFwiVmlydHVhbFRleHRcIjtcbiAgICAgICAgfSwgeyBcIi4vdmVyc2lvblwiOiAzMCB9XSwgMzQ6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICB2YXIgaXNPYmplY3QgPSByZXF1aXJlKFwiaXMtb2JqZWN0XCIpO1xuICAgICAgICAgICAgdmFyIGlzSG9vayA9IHJlcXVpcmUoXCIuLi92bm9kZS9pcy12aG9va1wiKTtcblxuICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBkaWZmUHJvcHM7XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIGRpZmZQcm9wcyhhLCBiKSB7XG4gICAgICAgICAgICAgICAgdmFyIGRpZmY7XG5cbiAgICAgICAgICAgICAgICBmb3IgKHZhciBhS2V5IGluIGEpIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKCEoYUtleSBpbiBiKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgZGlmZiA9IGRpZmYgfHwge307XG4gICAgICAgICAgICAgICAgICAgICAgICBkaWZmW2FLZXldID0gdW5kZWZpbmVkO1xuICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgdmFyIGFWYWx1ZSA9IGFbYUtleV07XG4gICAgICAgICAgICAgICAgICAgIHZhciBiVmFsdWUgPSBiW2FLZXldO1xuXG4gICAgICAgICAgICAgICAgICAgIGlmIChhVmFsdWUgPT09IGJWYWx1ZSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgY29udGludWU7XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoaXNPYmplY3QoYVZhbHVlKSAmJiBpc09iamVjdChiVmFsdWUpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoZ2V0UHJvdG90eXBlKGJWYWx1ZSkgIT09IGdldFByb3RvdHlwZShhVmFsdWUpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgZGlmZiA9IGRpZmYgfHwge307XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgZGlmZlthS2V5XSA9IGJWYWx1ZTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoaXNIb29rKGJWYWx1ZSkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBkaWZmID0gZGlmZiB8fCB7fTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBkaWZmW2FLZXldID0gYlZhbHVlO1xuICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB2YXIgb2JqZWN0RGlmZiA9IGRpZmZQcm9wcyhhVmFsdWUsIGJWYWx1ZSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKG9iamVjdERpZmYpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZGlmZiA9IGRpZmYgfHwge307XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRpZmZbYUtleV0gPSBvYmplY3REaWZmO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGRpZmYgPSBkaWZmIHx8IHt9O1xuICAgICAgICAgICAgICAgICAgICAgICAgZGlmZlthS2V5XSA9IGJWYWx1ZTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIGZvciAodmFyIGJLZXkgaW4gYikge1xuICAgICAgICAgICAgICAgICAgICBpZiAoIShiS2V5IGluIGEpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBkaWZmID0gZGlmZiB8fCB7fTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGRpZmZbYktleV0gPSBiW2JLZXldO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgcmV0dXJuIGRpZmY7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIGdldFByb3RvdHlwZSh2YWx1ZSkge1xuICAgICAgICAgICAgICAgIGlmIChPYmplY3QuZ2V0UHJvdG90eXBlT2YpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIE9iamVjdC5nZXRQcm90b3R5cGVPZih2YWx1ZSk7XG4gICAgICAgICAgICAgICAgfSBlbHNlIGlmICh2YWx1ZS5fX3Byb3RvX18pIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHZhbHVlLl9fcHJvdG9fXztcbiAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKHZhbHVlLmNvbnN0cnVjdG9yKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiB2YWx1ZS5jb25zdHJ1Y3Rvci5wcm90b3R5cGU7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9LCB7IFwiLi4vdm5vZGUvaXMtdmhvb2tcIjogMjYsIFwiaXMtb2JqZWN0XCI6IDExIH1dLCAzNTogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHtcbiAgICAgICAgICAgIHZhciBpc0FycmF5ID0gcmVxdWlyZShcIngtaXMtYXJyYXlcIik7XG5cbiAgICAgICAgICAgIHZhciBWUGF0Y2ggPSByZXF1aXJlKFwiLi4vdm5vZGUvdnBhdGNoXCIpO1xuICAgICAgICAgICAgdmFyIGlzVk5vZGUgPSByZXF1aXJlKFwiLi4vdm5vZGUvaXMtdm5vZGVcIik7XG4gICAgICAgICAgICB2YXIgaXNWVGV4dCA9IHJlcXVpcmUoXCIuLi92bm9kZS9pcy12dGV4dFwiKTtcbiAgICAgICAgICAgIHZhciBpc1dpZGdldCA9IHJlcXVpcmUoXCIuLi92bm9kZS9pcy13aWRnZXRcIik7XG4gICAgICAgICAgICB2YXIgaXNUaHVuayA9IHJlcXVpcmUoXCIuLi92bm9kZS9pcy10aHVua1wiKTtcbiAgICAgICAgICAgIHZhciBoYW5kbGVUaHVuayA9IHJlcXVpcmUoXCIuLi92bm9kZS9oYW5kbGUtdGh1bmtcIik7XG5cbiAgICAgICAgICAgIHZhciBkaWZmUHJvcHMgPSByZXF1aXJlKFwiLi9kaWZmLXByb3BzXCIpO1xuXG4gICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IGRpZmY7XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIGRpZmYoYSwgYikge1xuICAgICAgICAgICAgICAgIHZhciBwYXRjaCA9IHsgYTogYSB9O1xuICAgICAgICAgICAgICAgIHdhbGsoYSwgYiwgcGF0Y2gsIDApO1xuICAgICAgICAgICAgICAgIHJldHVybiBwYXRjaDtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZnVuY3Rpb24gd2FsayhhLCBiLCBwYXRjaCwgaW5kZXgpIHtcbiAgICAgICAgICAgICAgICBpZiAoYSA9PT0gYikge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgdmFyIGFwcGx5ID0gcGF0Y2hbaW5kZXhdO1xuICAgICAgICAgICAgICAgIHZhciBhcHBseUNsZWFyID0gZmFsc2U7XG5cbiAgICAgICAgICAgICAgICBpZiAoaXNUaHVuayhhKSB8fCBpc1RodW5rKGIpKSB7XG4gICAgICAgICAgICAgICAgICAgIHRodW5rcyhhLCBiLCBwYXRjaCwgaW5kZXgpO1xuICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoYiA9PSBudWxsKSB7XG5cbiAgICAgICAgICAgICAgICAgICAgLy8gSWYgYSBpcyBhIHdpZGdldCB3ZSB3aWxsIGFkZCBhIHJlbW92ZSBwYXRjaCBmb3IgaXRcbiAgICAgICAgICAgICAgICAgICAgLy8gT3RoZXJ3aXNlIGFueSBjaGlsZCB3aWRnZXRzL2hvb2tzIG11c3QgYmUgZGVzdHJveWVkLlxuICAgICAgICAgICAgICAgICAgICAvLyBUaGlzIHByZXZlbnRzIGFkZGluZyB0d28gcmVtb3ZlIHBhdGNoZXMgZm9yIGEgd2lkZ2V0LlxuICAgICAgICAgICAgICAgICAgICBpZiAoIWlzV2lkZ2V0KGEpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBjbGVhclN0YXRlKGEsIHBhdGNoLCBpbmRleCk7XG4gICAgICAgICAgICAgICAgICAgICAgICBhcHBseSA9IHBhdGNoW2luZGV4XTtcbiAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgIGFwcGx5ID0gYXBwZW5kUGF0Y2goYXBwbHksIG5ldyBWUGF0Y2goVlBhdGNoLlJFTU9WRSwgYSwgYikpO1xuICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoaXNWTm9kZShiKSkge1xuICAgICAgICAgICAgICAgICAgICBpZiAoaXNWTm9kZShhKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGEudGFnTmFtZSA9PT0gYi50YWdOYW1lICYmIGEubmFtZXNwYWNlID09PSBiLm5hbWVzcGFjZSAmJiBhLmtleSA9PT0gYi5rZXkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB2YXIgcHJvcHNQYXRjaCA9IGRpZmZQcm9wcyhhLnByb3BlcnRpZXMsIGIucHJvcGVydGllcyk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHByb3BzUGF0Y2gpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYXBwbHkgPSBhcHBlbmRQYXRjaChhcHBseSwgbmV3IFZQYXRjaChWUGF0Y2guUFJPUFMsIGEsIHByb3BzUGF0Y2gpKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgYXBwbHkgPSBkaWZmQ2hpbGRyZW4oYSwgYiwgcGF0Y2gsIGFwcGx5LCBpbmRleCk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGFwcGx5ID0gYXBwZW5kUGF0Y2goYXBwbHksIG5ldyBWUGF0Y2goVlBhdGNoLlZOT0RFLCBhLCBiKSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgYXBwbHlDbGVhciA9IHRydWU7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBhcHBseSA9IGFwcGVuZFBhdGNoKGFwcGx5LCBuZXcgVlBhdGNoKFZQYXRjaC5WTk9ERSwgYSwgYikpO1xuICAgICAgICAgICAgICAgICAgICAgICAgYXBwbHlDbGVhciA9IHRydWU7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKGlzVlRleHQoYikpIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKCFpc1ZUZXh0KGEpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBhcHBseSA9IGFwcGVuZFBhdGNoKGFwcGx5LCBuZXcgVlBhdGNoKFZQYXRjaC5WVEVYVCwgYSwgYikpO1xuICAgICAgICAgICAgICAgICAgICAgICAgYXBwbHlDbGVhciA9IHRydWU7XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoYS50ZXh0ICE9PSBiLnRleHQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGFwcGx5ID0gYXBwZW5kUGF0Y2goYXBwbHksIG5ldyBWUGF0Y2goVlBhdGNoLlZURVhULCBhLCBiKSk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKGlzV2lkZ2V0KGIpKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmICghaXNXaWRnZXQoYSkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGFwcGx5Q2xlYXIgPSB0cnVlO1xuICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgYXBwbHkgPSBhcHBlbmRQYXRjaChhcHBseSwgbmV3IFZQYXRjaChWUGF0Y2guV0lER0VULCBhLCBiKSk7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgaWYgKGFwcGx5KSB7XG4gICAgICAgICAgICAgICAgICAgIHBhdGNoW2luZGV4XSA9IGFwcGx5O1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIGlmIChhcHBseUNsZWFyKSB7XG4gICAgICAgICAgICAgICAgICAgIGNsZWFyU3RhdGUoYSwgcGF0Y2gsIGluZGV4KTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIGRpZmZDaGlsZHJlbihhLCBiLCBwYXRjaCwgYXBwbHksIGluZGV4KSB7XG4gICAgICAgICAgICAgICAgdmFyIGFDaGlsZHJlbiA9IGEuY2hpbGRyZW47XG4gICAgICAgICAgICAgICAgdmFyIG9yZGVyZWRTZXQgPSByZW9yZGVyKGFDaGlsZHJlbiwgYi5jaGlsZHJlbik7XG4gICAgICAgICAgICAgICAgdmFyIGJDaGlsZHJlbiA9IG9yZGVyZWRTZXQuY2hpbGRyZW47XG5cbiAgICAgICAgICAgICAgICB2YXIgYUxlbiA9IGFDaGlsZHJlbi5sZW5ndGg7XG4gICAgICAgICAgICAgICAgdmFyIGJMZW4gPSBiQ2hpbGRyZW4ubGVuZ3RoO1xuICAgICAgICAgICAgICAgIHZhciBsZW4gPSBhTGVuID4gYkxlbiA/IGFMZW4gOiBiTGVuO1xuXG4gICAgICAgICAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCBsZW47IGkrKykge1xuICAgICAgICAgICAgICAgICAgICB2YXIgbGVmdE5vZGUgPSBhQ2hpbGRyZW5baV07XG4gICAgICAgICAgICAgICAgICAgIHZhciByaWdodE5vZGUgPSBiQ2hpbGRyZW5baV07XG4gICAgICAgICAgICAgICAgICAgIGluZGV4ICs9IDE7XG5cbiAgICAgICAgICAgICAgICAgICAgaWYgKCFsZWZ0Tm9kZSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHJpZ2h0Tm9kZSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIEV4Y2VzcyBub2RlcyBpbiBiIG5lZWQgdG8gYmUgYWRkZWRcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBhcHBseSA9IGFwcGVuZFBhdGNoKGFwcGx5LCBuZXcgVlBhdGNoKFZQYXRjaC5JTlNFUlQsIG51bGwsIHJpZ2h0Tm9kZSkpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgd2FsayhsZWZ0Tm9kZSwgcmlnaHROb2RlLCBwYXRjaCwgaW5kZXgpO1xuICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgaWYgKGlzVk5vZGUobGVmdE5vZGUpICYmIGxlZnROb2RlLmNvdW50KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBpbmRleCArPSBsZWZ0Tm9kZS5jb3VudDtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIGlmIChvcmRlcmVkU2V0Lm1vdmVzKSB7XG4gICAgICAgICAgICAgICAgICAgIC8vIFJlb3JkZXIgbm9kZXMgbGFzdFxuICAgICAgICAgICAgICAgICAgICBhcHBseSA9IGFwcGVuZFBhdGNoKGFwcGx5LCBuZXcgVlBhdGNoKFZQYXRjaC5PUkRFUiwgYSwgb3JkZXJlZFNldC5tb3ZlcykpO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHJldHVybiBhcHBseTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZnVuY3Rpb24gY2xlYXJTdGF0ZSh2Tm9kZSwgcGF0Y2gsIGluZGV4KSB7XG4gICAgICAgICAgICAgICAgLy8gVE9ETzogTWFrZSB0aGlzIGEgc2luZ2xlIHdhbGssIG5vdCB0d29cbiAgICAgICAgICAgICAgICB1bmhvb2sodk5vZGUsIHBhdGNoLCBpbmRleCk7XG4gICAgICAgICAgICAgICAgZGVzdHJveVdpZGdldHModk5vZGUsIHBhdGNoLCBpbmRleCk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIC8vIFBhdGNoIHJlY29yZHMgZm9yIGFsbCBkZXN0cm95ZWQgd2lkZ2V0cyBtdXN0IGJlIGFkZGVkIGJlY2F1c2Ugd2UgbmVlZFxuICAgICAgICAgICAgLy8gYSBET00gbm9kZSByZWZlcmVuY2UgZm9yIHRoZSBkZXN0cm95IGZ1bmN0aW9uXG4gICAgICAgICAgICBmdW5jdGlvbiBkZXN0cm95V2lkZ2V0cyh2Tm9kZSwgcGF0Y2gsIGluZGV4KSB7XG4gICAgICAgICAgICAgICAgaWYgKGlzV2lkZ2V0KHZOb2RlKSkge1xuICAgICAgICAgICAgICAgICAgICBpZiAodHlwZW9mIHZOb2RlLmRlc3Ryb3kgPT09IFwiZnVuY3Rpb25cIikge1xuICAgICAgICAgICAgICAgICAgICAgICAgcGF0Y2hbaW5kZXhdID0gYXBwZW5kUGF0Y2gocGF0Y2hbaW5kZXhdLCBuZXcgVlBhdGNoKFZQYXRjaC5SRU1PVkUsIHZOb2RlLCBudWxsKSk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKGlzVk5vZGUodk5vZGUpICYmICh2Tm9kZS5oYXNXaWRnZXRzIHx8IHZOb2RlLmhhc1RodW5rcykpIHtcbiAgICAgICAgICAgICAgICAgICAgdmFyIGNoaWxkcmVuID0gdk5vZGUuY2hpbGRyZW47XG4gICAgICAgICAgICAgICAgICAgIHZhciBsZW4gPSBjaGlsZHJlbi5sZW5ndGg7XG4gICAgICAgICAgICAgICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgbGVuOyBpKyspIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHZhciBjaGlsZCA9IGNoaWxkcmVuW2ldO1xuICAgICAgICAgICAgICAgICAgICAgICAgaW5kZXggKz0gMTtcblxuICAgICAgICAgICAgICAgICAgICAgICAgZGVzdHJveVdpZGdldHMoY2hpbGQsIHBhdGNoLCBpbmRleCk7XG5cbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChpc1ZOb2RlKGNoaWxkKSAmJiBjaGlsZC5jb3VudCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGluZGV4ICs9IGNoaWxkLmNvdW50O1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfSBlbHNlIGlmIChpc1RodW5rKHZOb2RlKSkge1xuICAgICAgICAgICAgICAgICAgICB0aHVua3Modk5vZGUsIG51bGwsIHBhdGNoLCBpbmRleCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAvLyBDcmVhdGUgYSBzdWItcGF0Y2ggZm9yIHRodW5rc1xuICAgICAgICAgICAgZnVuY3Rpb24gdGh1bmtzKGEsIGIsIHBhdGNoLCBpbmRleCkge1xuICAgICAgICAgICAgICAgIHZhciBub2RlcyA9IGhhbmRsZVRodW5rKGEsIGIpO1xuICAgICAgICAgICAgICAgIHZhciB0aHVua1BhdGNoID0gZGlmZihub2Rlcy5hLCBub2Rlcy5iKTtcbiAgICAgICAgICAgICAgICBpZiAoaGFzUGF0Y2hlcyh0aHVua1BhdGNoKSkge1xuICAgICAgICAgICAgICAgICAgICBwYXRjaFtpbmRleF0gPSBuZXcgVlBhdGNoKFZQYXRjaC5USFVOSywgbnVsbCwgdGh1bmtQYXRjaCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBmdW5jdGlvbiBoYXNQYXRjaGVzKHBhdGNoKSB7XG4gICAgICAgICAgICAgICAgZm9yICh2YXIgaW5kZXggaW4gcGF0Y2gpIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKGluZGV4ICE9PSBcImFcIikge1xuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIC8vIEV4ZWN1dGUgaG9va3Mgd2hlbiB0d28gbm9kZXMgYXJlIGlkZW50aWNhbFxuICAgICAgICAgICAgZnVuY3Rpb24gdW5ob29rKHZOb2RlLCBwYXRjaCwgaW5kZXgpIHtcbiAgICAgICAgICAgICAgICBpZiAoaXNWTm9kZSh2Tm9kZSkpIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKHZOb2RlLmhvb2tzKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBwYXRjaFtpbmRleF0gPSBhcHBlbmRQYXRjaChwYXRjaFtpbmRleF0sIG5ldyBWUGF0Y2goVlBhdGNoLlBST1BTLCB2Tm9kZSwgdW5kZWZpbmVkS2V5cyh2Tm9kZS5ob29rcykpKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgIGlmICh2Tm9kZS5kZXNjZW5kYW50SG9va3MgfHwgdk5vZGUuaGFzVGh1bmtzKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICB2YXIgY2hpbGRyZW4gPSB2Tm9kZS5jaGlsZHJlbjtcbiAgICAgICAgICAgICAgICAgICAgICAgIHZhciBsZW4gPSBjaGlsZHJlbi5sZW5ndGg7XG4gICAgICAgICAgICAgICAgICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IGxlbjsgaSsrKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdmFyIGNoaWxkID0gY2hpbGRyZW5baV07XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaW5kZXggKz0gMTtcblxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHVuaG9vayhjaGlsZCwgcGF0Y2gsIGluZGV4KTtcblxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChpc1ZOb2RlKGNoaWxkKSAmJiBjaGlsZC5jb3VudCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpbmRleCArPSBjaGlsZC5jb3VudDtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKGlzVGh1bmsodk5vZGUpKSB7XG4gICAgICAgICAgICAgICAgICAgIHRodW5rcyh2Tm9kZSwgbnVsbCwgcGF0Y2gsIGluZGV4KTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIHVuZGVmaW5lZEtleXMob2JqKSB7XG4gICAgICAgICAgICAgICAgdmFyIHJlc3VsdCA9IHt9O1xuXG4gICAgICAgICAgICAgICAgZm9yICh2YXIga2V5IGluIG9iaikge1xuICAgICAgICAgICAgICAgICAgICByZXN1bHRba2V5XSA9IHVuZGVmaW5lZDtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICByZXR1cm4gcmVzdWx0O1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAvLyBMaXN0IGRpZmYsIG5haXZlIGxlZnQgdG8gcmlnaHQgcmVvcmRlcmluZ1xuICAgICAgICAgICAgZnVuY3Rpb24gcmVvcmRlcihhQ2hpbGRyZW4sIGJDaGlsZHJlbikge1xuICAgICAgICAgICAgICAgIC8vIE8oTSkgdGltZSwgTyhNKSBtZW1vcnlcbiAgICAgICAgICAgICAgICB2YXIgYkNoaWxkSW5kZXggPSBrZXlJbmRleChiQ2hpbGRyZW4pO1xuICAgICAgICAgICAgICAgIHZhciBiS2V5cyA9IGJDaGlsZEluZGV4LmtleXM7XG4gICAgICAgICAgICAgICAgdmFyIGJGcmVlID0gYkNoaWxkSW5kZXguZnJlZTtcblxuICAgICAgICAgICAgICAgIGlmIChiRnJlZS5sZW5ndGggPT09IGJDaGlsZHJlbi5sZW5ndGgpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGNoaWxkcmVuOiBiQ2hpbGRyZW4sXG4gICAgICAgICAgICAgICAgICAgICAgICBtb3ZlczogbnVsbFxuICAgICAgICAgICAgICAgICAgICB9O1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIC8vIE8oTikgdGltZSwgTyhOKSBtZW1vcnlcbiAgICAgICAgICAgICAgICB2YXIgYUNoaWxkSW5kZXggPSBrZXlJbmRleChhQ2hpbGRyZW4pO1xuICAgICAgICAgICAgICAgIHZhciBhS2V5cyA9IGFDaGlsZEluZGV4LmtleXM7XG4gICAgICAgICAgICAgICAgdmFyIGFGcmVlID0gYUNoaWxkSW5kZXguZnJlZTtcblxuICAgICAgICAgICAgICAgIGlmIChhRnJlZS5sZW5ndGggPT09IGFDaGlsZHJlbi5sZW5ndGgpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGNoaWxkcmVuOiBiQ2hpbGRyZW4sXG4gICAgICAgICAgICAgICAgICAgICAgICBtb3ZlczogbnVsbFxuICAgICAgICAgICAgICAgICAgICB9O1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIC8vIE8oTUFYKE4sIE0pKSBtZW1vcnlcbiAgICAgICAgICAgICAgICB2YXIgbmV3Q2hpbGRyZW4gPSBbXTtcblxuICAgICAgICAgICAgICAgIHZhciBmcmVlSW5kZXggPSAwO1xuICAgICAgICAgICAgICAgIHZhciBmcmVlQ291bnQgPSBiRnJlZS5sZW5ndGg7XG4gICAgICAgICAgICAgICAgdmFyIGRlbGV0ZWRJdGVtcyA9IDA7XG5cbiAgICAgICAgICAgICAgICAvLyBJdGVyYXRlIHRocm91Z2ggYSBhbmQgbWF0Y2ggYSBub2RlIGluIGJcbiAgICAgICAgICAgICAgICAvLyBPKE4pIHRpbWUsXG4gICAgICAgICAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCBhQ2hpbGRyZW4ubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgICAgICAgICAgdmFyIGFJdGVtID0gYUNoaWxkcmVuW2ldO1xuICAgICAgICAgICAgICAgICAgICB2YXIgaXRlbUluZGV4O1xuXG4gICAgICAgICAgICAgICAgICAgIGlmIChhSXRlbS5rZXkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChiS2V5cy5oYXNPd25Qcm9wZXJ0eShhSXRlbS5rZXkpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gTWF0Y2ggdXAgdGhlIG9sZCBrZXlzXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaXRlbUluZGV4ID0gYktleXNbYUl0ZW0ua2V5XTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBuZXdDaGlsZHJlbi5wdXNoKGJDaGlsZHJlbltpdGVtSW5kZXhdKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gUmVtb3ZlIG9sZCBrZXllZCBpdGVtc1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGl0ZW1JbmRleCA9IGkgLSBkZWxldGVkSXRlbXMrKztcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBuZXdDaGlsZHJlbi5wdXNoKG51bGwpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgLy8gTWF0Y2ggdGhlIGl0ZW0gaW4gYSB3aXRoIHRoZSBuZXh0IGZyZWUgaXRlbSBpbiBiXG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoZnJlZUluZGV4IDwgZnJlZUNvdW50KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaXRlbUluZGV4ID0gYkZyZWVbZnJlZUluZGV4KytdO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIG5ld0NoaWxkcmVuLnB1c2goYkNoaWxkcmVuW2l0ZW1JbmRleF0pO1xuICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBUaGVyZSBhcmUgbm8gZnJlZSBpdGVtcyBpbiBiIHRvIG1hdGNoIHdpdGhcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyB0aGUgZnJlZSBpdGVtcyBpbiBhLCBzbyB0aGUgZXh0cmEgZnJlZSBub2Rlc1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIGFyZSBkZWxldGVkLlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGl0ZW1JbmRleCA9IGkgLSBkZWxldGVkSXRlbXMrKztcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBuZXdDaGlsZHJlbi5wdXNoKG51bGwpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgdmFyIGxhc3RGcmVlSW5kZXggPSBmcmVlSW5kZXggPj0gYkZyZWUubGVuZ3RoID8gYkNoaWxkcmVuLmxlbmd0aCA6IGJGcmVlW2ZyZWVJbmRleF07XG5cbiAgICAgICAgICAgICAgICAvLyBJdGVyYXRlIHRocm91Z2ggYiBhbmQgYXBwZW5kIGFueSBuZXcga2V5c1xuICAgICAgICAgICAgICAgIC8vIE8oTSkgdGltZVxuICAgICAgICAgICAgICAgIGZvciAodmFyIGogPSAwOyBqIDwgYkNoaWxkcmVuLmxlbmd0aDsgaisrKSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciBuZXdJdGVtID0gYkNoaWxkcmVuW2pdO1xuXG4gICAgICAgICAgICAgICAgICAgIGlmIChuZXdJdGVtLmtleSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKCFhS2V5cy5oYXNPd25Qcm9wZXJ0eShuZXdJdGVtLmtleSkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBBZGQgYW55IG5ldyBrZXllZCBpdGVtc1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIFdlIGFyZSBhZGRpbmcgbmV3IGl0ZW1zIHRvIHRoZSBlbmQgYW5kIHRoZW4gc29ydGluZyB0aGVtXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gaW4gcGxhY2UuIEluIGZ1dHVyZSB3ZSBzaG91bGQgaW5zZXJ0IG5ldyBpdGVtcyBpbiBwbGFjZS5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBuZXdDaGlsZHJlbi5wdXNoKG5ld0l0ZW0pO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKGogPj0gbGFzdEZyZWVJbmRleCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgLy8gQWRkIGFueSBsZWZ0b3ZlciBub24ta2V5ZWQgaXRlbXNcbiAgICAgICAgICAgICAgICAgICAgICAgIG5ld0NoaWxkcmVuLnB1c2gobmV3SXRlbSk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICB2YXIgc2ltdWxhdGUgPSBuZXdDaGlsZHJlbi5zbGljZSgpO1xuICAgICAgICAgICAgICAgIHZhciBzaW11bGF0ZUluZGV4ID0gMDtcbiAgICAgICAgICAgICAgICB2YXIgcmVtb3ZlcyA9IFtdO1xuICAgICAgICAgICAgICAgIHZhciBpbnNlcnRzID0gW107XG4gICAgICAgICAgICAgICAgdmFyIHNpbXVsYXRlSXRlbTtcblxuICAgICAgICAgICAgICAgIGZvciAodmFyIGsgPSAwOyBrIDwgYkNoaWxkcmVuLmxlbmd0aDspIHtcbiAgICAgICAgICAgICAgICAgICAgdmFyIHdhbnRlZEl0ZW0gPSBiQ2hpbGRyZW5ba107XG4gICAgICAgICAgICAgICAgICAgIHNpbXVsYXRlSXRlbSA9IHNpbXVsYXRlW3NpbXVsYXRlSW5kZXhdO1xuXG4gICAgICAgICAgICAgICAgICAgIC8vIHJlbW92ZSBpdGVtc1xuICAgICAgICAgICAgICAgICAgICB3aGlsZSAoc2ltdWxhdGVJdGVtID09PSBudWxsICYmIHNpbXVsYXRlLmxlbmd0aCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgcmVtb3Zlcy5wdXNoKHJlbW92ZShzaW11bGF0ZSwgc2ltdWxhdGVJbmRleCwgbnVsbCkpO1xuICAgICAgICAgICAgICAgICAgICAgICAgc2ltdWxhdGVJdGVtID0gc2ltdWxhdGVbc2ltdWxhdGVJbmRleF07XG4gICAgICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgICAgICBpZiAoIXNpbXVsYXRlSXRlbSB8fCBzaW11bGF0ZUl0ZW0ua2V5ICE9PSB3YW50ZWRJdGVtLmtleSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgLy8gaWYgd2UgbmVlZCBhIGtleSBpbiB0aGlzIHBvc2l0aW9uLi4uXG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAod2FudGVkSXRlbS5rZXkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoc2ltdWxhdGVJdGVtICYmIHNpbXVsYXRlSXRlbS5rZXkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gaWYgYW4gaW5zZXJ0IGRvZXNuJ3QgcHV0IHRoaXMga2V5IGluIHBsYWNlLCBpdCBuZWVkcyB0byBtb3ZlXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChiS2V5c1tzaW11bGF0ZUl0ZW0ua2V5XSAhPT0gayArIDEpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlbW92ZXMucHVzaChyZW1vdmUoc2ltdWxhdGUsIHNpbXVsYXRlSW5kZXgsIHNpbXVsYXRlSXRlbS5rZXkpKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNpbXVsYXRlSXRlbSA9IHNpbXVsYXRlW3NpbXVsYXRlSW5kZXhdO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gaWYgdGhlIHJlbW92ZSBkaWRuJ3QgcHV0IHRoZSB3YW50ZWQgaXRlbSBpbiBwbGFjZSwgd2UgbmVlZCB0byBpbnNlcnQgaXRcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmICghc2ltdWxhdGVJdGVtIHx8IHNpbXVsYXRlSXRlbS5rZXkgIT09IHdhbnRlZEl0ZW0ua2V5KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaW5zZXJ0cy5wdXNoKHsga2V5OiB3YW50ZWRJdGVtLmtleSwgdG86IGsgfSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBpdGVtcyBhcmUgbWF0Y2hpbmcsIHNvIHNraXAgYWhlYWRcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzaW11bGF0ZUluZGV4Kys7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaW5zZXJ0cy5wdXNoKHsga2V5OiB3YW50ZWRJdGVtLmtleSwgdG86IGsgfSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpbnNlcnRzLnB1c2goeyBrZXk6IHdhbnRlZEl0ZW0ua2V5LCB0bzogayB9KTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaysrO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgLy8gYSBrZXkgaW4gc2ltdWxhdGUgaGFzIG5vIG1hdGNoaW5nIHdhbnRlZCBrZXksIHJlbW92ZSBpdFxuICAgICAgICAgICAgICAgICAgICAgICAgZWxzZSBpZiAoc2ltdWxhdGVJdGVtICYmIHNpbXVsYXRlSXRlbS5rZXkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmVtb3Zlcy5wdXNoKHJlbW92ZShzaW11bGF0ZSwgc2ltdWxhdGVJbmRleCwgc2ltdWxhdGVJdGVtLmtleSkpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHNpbXVsYXRlSW5kZXgrKztcbiAgICAgICAgICAgICAgICAgICAgICAgIGsrKztcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIC8vIHJlbW92ZSBhbGwgdGhlIHJlbWFpbmluZyBub2RlcyBmcm9tIHNpbXVsYXRlXG4gICAgICAgICAgICAgICAgd2hpbGUgKHNpbXVsYXRlSW5kZXggPCBzaW11bGF0ZS5sZW5ndGgpIHtcbiAgICAgICAgICAgICAgICAgICAgc2ltdWxhdGVJdGVtID0gc2ltdWxhdGVbc2ltdWxhdGVJbmRleF07XG4gICAgICAgICAgICAgICAgICAgIHJlbW92ZXMucHVzaChyZW1vdmUoc2ltdWxhdGUsIHNpbXVsYXRlSW5kZXgsIHNpbXVsYXRlSXRlbSAmJiBzaW11bGF0ZUl0ZW0ua2V5KSk7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgLy8gSWYgdGhlIG9ubHkgbW92ZXMgd2UgaGF2ZSBhcmUgZGVsZXRlcyB0aGVuIHdlIGNhbiBqdXN0XG4gICAgICAgICAgICAgICAgLy8gbGV0IHRoZSBkZWxldGUgcGF0Y2ggcmVtb3ZlIHRoZXNlIGl0ZW1zLlxuICAgICAgICAgICAgICAgIGlmIChyZW1vdmVzLmxlbmd0aCA9PT0gZGVsZXRlZEl0ZW1zICYmICFpbnNlcnRzLmxlbmd0aCkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgICAgICAgICAgICAgY2hpbGRyZW46IG5ld0NoaWxkcmVuLFxuICAgICAgICAgICAgICAgICAgICAgICAgbW92ZXM6IG51bGxcbiAgICAgICAgICAgICAgICAgICAgfTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgICAgICAgICBjaGlsZHJlbjogbmV3Q2hpbGRyZW4sXG4gICAgICAgICAgICAgICAgICAgIG1vdmVzOiB7XG4gICAgICAgICAgICAgICAgICAgICAgICByZW1vdmVzOiByZW1vdmVzLFxuICAgICAgICAgICAgICAgICAgICAgICAgaW5zZXJ0czogaW5zZXJ0c1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZnVuY3Rpb24gcmVtb3ZlKGFyciwgaW5kZXgsIGtleSkge1xuICAgICAgICAgICAgICAgIGFyci5zcGxpY2UoaW5kZXgsIDEpO1xuXG4gICAgICAgICAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgICAgICAgICAgZnJvbTogaW5kZXgsXG4gICAgICAgICAgICAgICAgICAgIGtleToga2V5XG4gICAgICAgICAgICAgICAgfTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZnVuY3Rpb24ga2V5SW5kZXgoY2hpbGRyZW4pIHtcbiAgICAgICAgICAgICAgICB2YXIga2V5cyA9IHt9O1xuICAgICAgICAgICAgICAgIHZhciBmcmVlID0gW107XG4gICAgICAgICAgICAgICAgdmFyIGxlbmd0aCA9IGNoaWxkcmVuLmxlbmd0aDtcblxuICAgICAgICAgICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgbGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgICAgICAgICAgdmFyIGNoaWxkID0gY2hpbGRyZW5baV07XG5cbiAgICAgICAgICAgICAgICAgICAgaWYgKGNoaWxkLmtleSkge1xuICAgICAgICAgICAgICAgICAgICAgICAga2V5c1tjaGlsZC5rZXldID0gaTtcbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGZyZWUucHVzaChpKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHJldHVybiB7XG4gICAgICAgICAgICAgICAgICAgIGtleXM6IGtleXMsIC8vIEEgaGFzaCBvZiBrZXkgbmFtZSB0byBpbmRleFxuICAgICAgICAgICAgICAgICAgICBmcmVlOiBmcmVlIC8vIEFuIGFycmF5IG9mIHVua2V5ZWQgaXRlbSBpbmRpY2VzXG4gICAgICAgICAgICAgICAgfTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZnVuY3Rpb24gYXBwZW5kUGF0Y2goYXBwbHksIHBhdGNoKSB7XG4gICAgICAgICAgICAgICAgaWYgKGFwcGx5KSB7XG4gICAgICAgICAgICAgICAgICAgIGlmIChpc0FycmF5KGFwcGx5KSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgYXBwbHkucHVzaChwYXRjaCk7XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBhcHBseSA9IFthcHBseSwgcGF0Y2hdO1xuICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGFwcGx5O1xuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBwYXRjaDtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH0sIHsgXCIuLi92bm9kZS9oYW5kbGUtdGh1bmtcIjogMjQsIFwiLi4vdm5vZGUvaXMtdGh1bmtcIjogMjUsIFwiLi4vdm5vZGUvaXMtdm5vZGVcIjogMjcsIFwiLi4vdm5vZGUvaXMtdnRleHRcIjogMjgsIFwiLi4vdm5vZGUvaXMtd2lkZ2V0XCI6IDI5LCBcIi4uL3Zub2RlL3ZwYXRjaFwiOiAzMiwgXCIuL2RpZmYtcHJvcHNcIjogMzQsIFwieC1pcy1hcnJheVwiOiAxMiB9XSB9LCB7fSwgWzRdKSg0KTtcbn0pO1xuXG5leHBvcnQgZGVmYXVsdCBWaXJ0dWFsRE9NO1xuLy8jIHNvdXJjZU1hcHBpbmdVUkw9ZGF0YTphcHBsaWNhdGlvbi9qc29uO2Jhc2U2NCxleUoyWlhKemFXOXVJam96TENKemIzVnlZMlZ6SWpwYklteHBZaTkyYVhKMGRXRnNMV1J2YlM1cWN5SmRMQ0p1WVcxbGN5STZXMTBzSW0xaGNIQnBibWR6SWpvaVFVRkJRU3hKUVVGSkxHRkJRV0VzVlVGQlV5eERRVUZVTEVWQlFWazdRVUZETTBJc1YwRkJUeXhIUVVGUUxFTkJSREpDTzBOQlFWb3NRMEZGWml4WlFVRlhPMEZCUTB3c1VVRkJTU3hOUVVGS0xFVkJRVmtzVFVGQldpeEZRVUZ2UWl4UFFVRndRaXhEUVVSTE8wRkJSVXdzVjBGQlR5eFRRVUZWTEVOQlFWUXNRMEZCVnl4RFFVRllMRVZCUVdNc1EwRkJaQ3hGUVVGcFFpeERRVUZxUWl4RlFVRnZRanRCUVVOd1FpeHBRa0ZCVXl4RFFVRlVMRU5CUVZjc1EwRkJXQ3hGUVVGakxFTkJRV1FzUlVGQmFVSTdRVUZEWWl4blFrRkJTU3hEUVVGRExFVkJRVVVzUTBGQlJpeERRVUZFTEVWQlFVODdRVUZEVUN4dlFrRkJTU3hEUVVGRExFVkJRVVVzUTBGQlJpeERRVUZFTEVWQlFVODdRVUZEVUN4M1FrRkJTU3hKUVVGSkxFOUJRVThzVDBGQlVDeEpRVUZyUWl4VlFVRnNRaXhKUVVGblF5eFBRVUZvUXl4RFFVUkVPMEZCUlZBc2QwSkJRVWtzUTBGQlF5eERRVUZFTEVsQlFVMHNRMEZCVGl4RlFVRlRMRTlCUVU4c1JVRkJSU3hEUVVGR0xFVkJRVXNzUTBGQlF5eERRVUZFTEVOQlFWb3NRMEZCWWp0QlFVTkJMSGRDUVVGSkxFTkJRVW9zUlVGQlR5eFBRVUZQTEVWQlFVVXNRMEZCUml4RlFVRkxMRU5CUVVNc1EwRkJSQ3hEUVVGYUxFTkJRVkE3UVVGRFFTeDNRa0ZCU1N4SlFVRkpMRWxCUVVrc1MwRkJTaXhEUVVGVkxIbENRVUY1UWl4RFFVRjZRaXhIUVVFMlFpeEhRVUUzUWl4RFFVRmtMRU5CU2tjN1FVRkxVQ3d3UWtGQlRTeEZRVUZGTEVsQlFVWXNSMEZCVXl4clFrRkJWQ3hGUVVFMlFpeERRVUUzUWl4RFFVeERPMmxDUVVGWU8wRkJUMEVzYjBKQlFVa3NTVUZCU1N4RlFVRkZMRU5CUVVZc1NVRkJUenRCUVVOWUxEWkNRVUZUTEVWQlFWUTdhVUpCUkVrc1EwRlNSRHRCUVZkUUxHdENRVUZGTEVOQlFVWXNSVUZCU3l4RFFVRk1MRVZCUVZFc1NVRkJVaXhEUVVGaExFVkJRVVVzVDBGQlJpeEZRVUZYTEZWQlFWTXNRMEZCVkN4RlFVRlpPMEZCUTJoRExIZENRVUZKTEVsQlFVa3NSVUZCUlN4RFFVRkdMRVZCUVVzc1EwRkJUQ3hGUVVGUkxFTkJRVklzUTBGQlNpeERRVVEwUWp0QlFVVm9ReXd5UWtGQlR5eEZRVUZGTEVsQlFVa3NRMEZCU2l4SFFVRlJMRU5CUVZJc1EwRkJWQ3hEUVVablF6dHBRa0ZCV2l4RlFVZHlRaXhEUVVoSUxFVkJSMDBzUlVGQlJTeFBRVUZHTEVWQlFWY3NRMEZJYWtJc1JVRkhiMElzUTBGSWNFSXNSVUZIZFVJc1EwRklka0lzUlVGSE1FSXNRMEZJTVVJc1JVRllUenRoUVVGWU8wRkJaMEpCTEcxQ1FVRlBMRVZCUVVVc1EwRkJSaXhGUVVGTExFOUJRVXdzUTBGcVFrMDdVMEZCYWtJN1FVRnRRa0VzV1VGQlNTeEpRVUZKTEU5QlFVOHNUMEZCVUN4SlFVRnJRaXhWUVVGc1FpeEpRVUZuUXl4UFFVRm9ReXhEUVhCQ1dUdEJRWEZDY0VJc1lVRkJTeXhKUVVGSkxFbEJRVWtzUTBGQlNpeEZRVUZQTEVsQlFVa3NSVUZCUlN4TlFVRkdMRVZCUVZVc1IwRkJPVUlzUlVGQmJVTXNSVUZCUlN4RlFVRkZMRU5CUVVZc1EwRkJSaXhGUVVGdVF6dEJRVU5CTEdWQlFVOHNRMEZCVUN4RFFYUkNiMEk3UzBGQmNFSXNRMEYxUWtRN1FVRkRTeXhYUVVGSExFTkJRVU1zVlVGQlV5eFBRVUZVTEVWQlFXdENMRTFCUVd4Q0xFVkJRVEJDTEU5QlFURkNMRVZCUVcxRE96dEJRVVV6UkN4blFrRkJTU3huUWtGQlowSXNVVUZCVVN3d1FrRkJVaXhEUVVGb1FpeERRVVoxUkRzN1FVRkpNMFFzYlVKQlFVOHNUMEZCVUN4SFFVRnBRaXhoUVVGcVFpeERRVW95UkR0VFFVRnVReXhGUVUxMFFpeEZRVUZETERSQ1FVRXlRaXhGUVVFelFpeEZRVTV2UWl4RFFVRklMRVZCVFdVc1IwRkJSU3hEUVVGRExGVkJRVk1zVDBGQlZDeEZRVUZwUWl4TlFVRnFRaXhGUVVGM1FpeFBRVUY0UWl4RlFVRm5RenRCUVVOMFJTeG5Ra0ZCU1N4UFFVRlBMRkZCUVZFc2FVSkJRVklzUTBGQlVDeERRVVJyUlRzN1FVRkhkRVVzYlVKQlFVOHNUMEZCVUN4SFFVRnBRaXhKUVVGcVFpeERRVWh6UlR0VFFVRm9ReXhGUVV0d1F5eEZRVUZETEcxQ1FVRnJRaXhGUVVGc1FpeEZRVXhyUXl4RFFVRkdMRVZCUzFRc1IwRkJSU3hEUVVGRExGVkJRVk1zVDBGQlZDeEZRVUZwUWl4TlFVRnFRaXhGUVVGM1FpeFBRVUY0UWl4RlFVRm5RenRCUVVNM1JDeG5Ra0ZCU1N4SlFVRkpMRkZCUVZFc1owTkJRVklzUTBGQlNpeERRVVI1UkRzN1FVRkhOMFFzYlVKQlFVOHNUMEZCVUN4SFFVRnBRaXhEUVVGcVFpeERRVWcyUkR0VFFVRm9ReXhGUVVzelFpeEZRVUZETEd0RFFVRnBReXhGUVVGcVF5eEZRVXg1UWl4RFFVRkdMRVZCUzJVc1IwRkJSU3hEUVVGRExGVkJRVk1zVDBGQlZDeEZRVUZwUWl4TlFVRnFRaXhGUVVGM1FpeFBRVUY0UWl4RlFVRm5RenRCUVVNMVJTeG5Ra0ZCU1N4UFFVRlBMRkZCUVZFc1YwRkJVaXhEUVVGUUxFTkJSSGRGTzBGQlJUVkZMR2RDUVVGSkxGRkJRVkVzVVVGQlVTeFpRVUZTTEVOQlFWSXNRMEZHZDBVN1FVRkhOVVVzWjBKQlFVa3NTVUZCU1N4UlFVRlJMRkZCUVZJc1EwRkJTaXhEUVVoM1JUdEJRVWsxUlN4blFrRkJTU3hUUVVGVExGRkJRVkVzY1VKQlFWSXNRMEZCVkN4RFFVcDNSVHRCUVVzMVJTeG5Ra0ZCU1N4UlFVRlJMRkZCUVZFc2EwSkJRVklzUTBGQlVpeERRVXgzUlR0QlFVMDFSU3huUWtGQlNTeFJRVUZSTEZGQlFWRXNhMEpCUVZJc1EwRkJVaXhEUVU1M1JUczdRVUZSTlVVc2JVSkJRVThzVDBGQlVDeEhRVUZwUWp0QlFVTmlMSE5DUVVGTkxFbEJRVTQ3UVVGRFFTeDFRa0ZCVHl4TFFVRlFPMEZCUTBFc2JVSkJRVWNzUTBGQlNEdEJRVU5CTEhkQ1FVRlJMRTFCUVZJN1FVRkRRU3gxUWtGQlR5eExRVUZRTzBGQlEwRXNkVUpCUVU4c1MwRkJVRHRoUVU1S0xFTkJValJGTzFOQlFXaERMRVZCYVVJeFF5eEZRVUZETEhWQ1FVRnpRaXhEUVVGMFFpeEZRVUYzUWl4aFFVRlpMRU5CUVZvc1JVRkJZeXhWUVVGVExFTkJRVlFzUlVGQlZ5eGpRVUZoTEVWQlFXSXNSVUZCWjBJc2IwSkJRVzFDTEVWQlFXNUNMRVZCUVhOQ0xHOUNRVUZ0UWl4RlFVRnVRaXhGUVdwQ0wwTXNRMEZCUml4RlFXbENlVVVzUjBGQlJTeERRVUZETEZWQlFWTXNUMEZCVkN4RlFVRnBRaXhOUVVGcVFpeEZRVUYzUWl4UFFVRjRRaXhGUVVGblF6czdPenM3T3pzN096czdPenM3T3pzN096czdPenM3T3pzN096czdPenM3UVVGblEzSktMRzFDUVVGUExFOUJRVkFzUjBGQmFVSXNVMEZCVlN4TFFVRlVMRU5CUVdVc1MwRkJaaXhGUVVGelFqczdRVUZGZEVNc2IwSkJRVWtzWTBGQll5eFBRVUZQTEZOQlFWQXNRMEZCYVVJc1MwRkJha0k3YjBKQlEyaENMRzlDUVVGdlFpeFBRVUZQTEVsQlFWQXNRMEZCV1N4RlFVRmFMRVZCUVdkQ0xFTkJRV2hDTEUxQlFYVkNMRXRCUVhaQ096czdRVUZGY0VJc2IwSkJTRVlzUTBGR2MwTTdPMEZCVDNSRExIVkNRVUZQTEZWQlFWTXNSMEZCVkN4RlFVRmpMRk5CUVdRc1JVRkJlVUlzUzBGQmVrSXNSVUZCWjBNN08wRkJSWEpETEhkQ1FVRkpMRTlCUVU4c1UwRkJVQ3hEUVVGcFFpeFJRVUZxUWl4RFFVRXdRaXhKUVVFeFFpeERRVUVyUWl4VFFVRXZRaXhOUVVFNFF5eHBRa0ZCT1VNc1JVRkJhVVU3UVVGRGJrVXNLMEpCUVU4c1dVRkJXU3hKUVVGYUxFTkJRV2xDTEVkQlFXcENMRVZCUVhOQ0xGTkJRWFJDTEVWQlFXbERMRXRCUVdwRExFTkJRVkFzUTBGRWJVVTdjVUpCUVhKRk8wRkJSMEVzZDBKQlFVa3NVMEZCVXl4RlFVRlVPM2RDUVVOR0xGRkJRVkVzUTBGQlF5eFZRVUZWTEZWQlFWWXNSMEZCZFVJc1IwRkJka0lzUjBGQk5rSXNSVUZCTjBJc1EwRkJSQ3hKUVVGeFF5eFZRVUZWTEZOQlFWWXNSMEZCYzBJc1IwRkJkRUlzUjBGQk5FSXNSVUZCTlVJc1EwRkJja01zU1VGQmQwVXNWVUZCVlN4UlFVRldMRWRCUVhGQ0xFZEJRWEpDTEVkQlFUSkNMRVZCUVROQ0xFTkJRWGhGTzBGQlExQXNPRUpCUVZVc1RVRkJWaXhIUVVGdFFpeEhRVUZ1UWl4SFFVRjVRaXhGUVVGNlFpeERRVVJQT3pzN1FVRkhVaXh2UTBGQlowSXNRMEZCYUVJN096dEJRVVZCTEdkRFFVRlpMRWxCUVVrc1RVRkJTaXhEUVVGWExGVkJRVlVzVFVGQlZpeEZRVUZyUWl4UlFVRlJMRWRCUVZJc1EwRkJla003ZDBKQlEwRXNWVUZRUmp0M1FrRlBZeXhMUVZCa08zZENRVTl4UWl4VFFWQnlRanQzUWtGUFowTXNWVUZRYUVNc1EwRk1jVU03UVVGaGNrTXNNa0pCUVU4c1JVRkJVRHRCUVdKeFF5eDNRa0ZqYWtNc1EwRkJReXhwUWtGQlJDeEZRVUZ2UWpzN1FVRkZkRUlzY1VOQlFXRXNTVUZCU1N4TlFVRktMRU5CUVZjc1RVRkJUU3hWUVVGVkxFMUJRVllzUjBGQmJVSXNWVUZCZWtJc1JVRkJjVU1zUzBGQmFFUXNRMEZCWWl4RFFVWnpRanR4UWtGQmVFSTdPenM3T3pzN08wRkJaSEZETEhsQ1FYbENja01zUjBGQlVTeFZRVUZWTEV0QlFWWXNSMEZCYTBJc1EwRkJReXhEUVVGRUxFdEJRVThzUTBGQlVEdEJRVU14UWl3NFFrRkJWU3hEUVVGV08wRkJNVUp4UXl3eVFrRXlRamxDTEZGQlFWRXNWVUZCVlN4SlFVRldMRU5CUVdVc1IwRkJaaXhEUVVGU0xFVkJRVFpDT3p0QlFVVnNReXh2UTBGQldTeE5RVUZOTEV0QlFVNHNSMEZCWXl4TlFVRk5MRU5CUVU0c1JVRkJVeXhOUVVGVUxFTkJSbEU3UVVGSGJFTXNORUpCUVVrc1dVRkJXU3hoUVVGYUxFVkJRVEpDTzBGQlF6ZENMRzFEUVVGUExFbEJRVkFzUTBGQldTeEpRVUZKTEV0QlFVb3NRMEZCVlN4aFFVRldMRVZCUVhsQ0xFMUJRVTBzUzBGQlRpeERRVUZ5UXpzN08wRkJSRFpDTEdkRFFVbDZRaXhEUVVGRExHbENRVUZFTEVsQlFYTkNMRTFCUVUwc1RVRkJUaXhIUVVGbExFTkJRV1lzUlVGQmEwSTdRVUZETVVNc2MwTkJRVTBzUTBGQlRpeEZRVUZUTEU5QlFWUXNRMEZCYVVJc1ZVRkJha0lzUlVGQk5rSXNXVUZCVnp0QlFVTjBReXg1UTBGQlN5eEpRVUZKTEVsQlFVa3NRMEZCU2l4RlFVRlBMRWxCUVVrc1ZVRkJWU3hOUVVGV0xFZEJRVzFDTEVOQlFXNUNMRVZCUVhOQ0xFZEJRVEZETEVWQlFTdERPMEZCUXpkRExEUkRRVUZKTEZWQlFWVXNRMEZCVml4TlFVRnBRaXhMUVVGcVFpeEZRVUYzUWp0QlFVTXhRaXhyUkVGQlRTeERRVUZPTEVsQlFWY3NTMEZCV0N4RFFVUXdRanQ1UTBGQk5VSTdjVU5CUkVZN2FVTkJSREpDTEVOQlFUZENMRU5CUkRCRE96WkNRVUUxUXp0QlFWTkJMR2REUVVGSkxFMUJRVTBzVFVGQlRpeEhRVUZsTEVOQlFXWXNTVUZCYjBJc1RVRkJUU3hMUVVGT0xFZEJRV01zU1VGQlNTeE5RVUZLTEVWQlFWazdRVUZEYUVRc2MwTkJRVTBzVTBGQlRpeERRVUZuUWl4SlFVRm9RaXhEUVVGeFFpeExRVUZ5UWl4RFFVRXlRaXhOUVVFelFpeEZRVUZ0UXl4TlFVRk5MRXRCUVU0c1EwRkJXU3hEUVVGYUxFTkJRVzVETEVWQlJHZEVPelpDUVVGc1JEdEJRVWRCTEhsRFFVRmhMRTFCUVUwc1EwRkJUaXhGUVVGVExFMUJRVlFzUTBGb1FtZENPMEZCYVVJM1FpdzBRMEZCWjBJc1UwRkJhRUlzUTBGcVFqWkNPMEZCYTBJM1FpeG5RMEZCU1N4UFFVRlBMRTFCUVZBc1NVRkJhVUlzUzBGQmFrSXNSVUZCZDBJN1FVRkRNVUlzYzBOQlJEQkNPelpDUVVFMVFqdDVRa0ZzUWtZN1FVRnpRa0VzTkVKQlFVa3NWVUZCVlN4VFFVRldMRXRCUVhkQ0xFMUJRVTBzUzBGQlRpeEZRVUZoTzBGQlEzWkRMSE5EUVVGVkxGTkJRVlk3UVVGRWRVTXNlVUpCUVhwRE8zRkNRWHBDUmp0QlFUWkNRU3gzUWtGQlNTeHJRa0ZCYTBJc1NVRkJTU3hOUVVGS0xFVkJRVms3UVVGRGFFTXNORUpCUVVrc1kwRkJZeXhEUVVGRExGVkJRVlVzU1VGQlZpeERRVUZsTEVWQlFXWXNRMEZCUkN4RlFVRnhRanRCUVVOeVF5eHRRMEZCVHl4SlFVRlFMRU5CUVZrc1JVRkJXaXhGUVVSeFF6dDVRa0ZCZGtNN2NVSkJSRVlzVFVGSlR6dEJRVU5NTEN0Q1FVRlBMRWxCUVZBc1EwRkJXU3hKUVVGSkxFdEJRVW9zUTBGQlZTeGhRVUZXTEVOQlFWb3NSVUZFU3p0eFFrRktVRHRCUVU5QkxESkNRVUZQTEU5QlFVOHNUVUZCVUN4SFFVRm5RaXhMUVVGb1FpeEhRVUYzUWl4UFFVRlBMRXRCUVZBc1EwRkJZU3hEUVVGaUxFVkJRV2RDTEV0QlFXaENMRU5CUVhoQ0xFZEJRV2xFTEUxQlFXcEVMRU5CTDBRNFFqdHBRa0ZCYUVNc1EwRlFLMEk3TzBGQmVVVjBReXgxUWtGQlR5eEpRVUZRTEVOQmVrVnpRenRoUVVGMFFpeEZRVUZzUWl4RFFXaERjVW83VTBGQmFFTXNSVUUwUjI1SUxFVkJOVWRyU0N4RFFVRkdMRVZCTkVjMVJ5eEhRVUZGTEVOQlFVTXNWVUZCVXl4UFFVRlVMRVZCUVdsQ0xFMUJRV3BDTEVWQlFYZENMRTlCUVhoQ0xFVkJRV2RETEVWQlFXaERMRVZCUlZBc1JVRkdUU3hEUVVGR0xFVkJSVUVzUjBGQlJTeERRVUZETEZWQlFWTXNUMEZCVkN4RlFVRnBRaXhOUVVGcVFpeEZRVUYzUWl4UFFVRjRRaXhGUVVGblF6dEJRVU42UXl4NVFrRkVlVU03TzBGQlIzcERMR2RDUVVGSkxIVkNRVUYxUWl4UlFVRlJMSGRDUVVGU0xFTkJRWFpDTEVOQlNIRkRPenRCUVV0NlF5eG5Ra0ZCU1N4aFFVRmhMRWRCUVdJc1EwRk1jVU03UVVGTmVrTXNhVU5CUVhGQ0xGVkJRWEpDTEVWQlFXbERMRlZCUVdwRExFVkJUbmxET3p0QlFWRjZReXhuUWtGQlNTeFZRVUZWTEc5Q1FVRnZRaXhWUVVGd1FpeERRVkl5UWpzN1FVRlZla01zYlVKQlFVOHNUMEZCVUN4SFFVRnBRaXhQUVVGcVFpeERRVlo1UXpzN1FVRlpla01zY1VKQlFWTXNUMEZCVkN4RFFVRnBRaXhKUVVGcVFpeEZRVUYxUWp0QlFVTnVRaXh2UWtGQlNTeFBRVUZQTEV0QlFVc3NUMEZCVEN4RFFVRlFMRU5CUkdVN08wRkJSMjVDTEc5Q1FVRkpMRU5CUVVNc1NVRkJSQ3hGUVVGUE8wRkJRMUFzTWtKQlFVOHNTMEZCU3l4UFFVRk1MRWxCUVdkQ0xFVkJRV2hDTEVOQlJFRTdhVUpCUVZnN08wRkJTVUVzZFVKQlFVOHNTVUZCVUN4RFFWQnRRanRoUVVGMlFqdFRRVnBUTEVWQmMwSlFMRVZCUVVNc01FSkJRWGxDTEVOQlFYcENMRVZCZEVKTExFTkJRVVlzUlVGelFqQkNMRWRCUVVVc1EwRkJReXhWUVVGVExFOUJRVlFzUlVGQmFVSXNUVUZCYWtJc1JVRkJkMElzVDBGQmVFSXNSVUZCWjBNN1FVRkRia1VzWVVGQlF5eFZRVUZWTEUxQlFWWXNSVUZCYVVJN1FVRkRiRUk3T3pzN1FVRkVhMElzYjBKQlMyUXNUMEZCVHl4UFFVRlBMRTFCUVZBc1MwRkJhMElzVjBGQmJFSXNSMEZEVUN4TlFVUlBMRWRCUTBVc1QwRkJUeXhOUVVGUUxFdEJRV3RDTEZkQlFXeENMRWRCUTFRc1RVRkVVeXhIUVVOQkxFVkJSRUVzUTBGT1N6czdRVUZUYkVJc2RVSkJRVThzVDBGQlVDeEhRVUZwUWl4VlFVRnFRaXhEUVZSclFqczdRVUZYYkVJc2VVSkJRVk1zVlVGQlZDeERRVUZ2UWl4SFFVRndRaXhGUVVGNVFpeExRVUY2UWl4RlFVRm5RenRCUVVNMVFpeDNRa0ZCU1N4UFFVRlBMRWxCUVZBc1JVRkJZVHRCUVVOaUxDdENRVUZQTEV0QlFVc3NSMEZCVEN4RFFVRlFMRU5CUkdFN2NVSkJRV3BDT3p0QlFVbEJMSGxDUVVGTExFZEJRVXdzU1VGQldTeExRVUZhTEVOQlREUkNPenRCUVU4MVFpd3lRa0ZCVHl4TFFVRlFMRU5CVURSQ08ybENRVUZvUXp0aFFWaERMRU5CUVVRc1EwRnhRa2NzU1VGeVFrZ3NRMEZ4UWxFc1NVRnlRbElzUlVGeFFtRXNUMEZCVHl4TlFVRlFMRXRCUVd0Q0xGZEJRV3hDTEVkQlFXZERMRTFCUVdoRExFZEJRWGxETEU5QlFVOHNTVUZCVUN4TFFVRm5RaXhYUVVGb1FpeEhRVUU0UWl4SlFVRTVRaXhIUVVGeFF5eFBRVUZQTEUxQlFWQXNTMEZCYTBJc1YwRkJiRUlzUjBGQlowTXNUVUZCYUVNc1IwRkJlVU1zUlVGQmVrTXNRMEZ5UWpOR0xFTkJSRzFGTzFOQlFXaERMRVZCZFVKcVF5eEZRWFpDWjBNc1EwRkJSaXhGUVhWQ01VSXNSMEZCUlN4RFFVRkRMRlZCUVZNc1QwRkJWQ3hGUVVGcFFpeE5RVUZxUWl4RlFVRjNRaXhQUVVGNFFpeEZRVUZuUXp0QlFVTjZReXg1UWtGRWVVTTdPMEZCUjNwRExHZENRVUZKTEdGQlFXRXNVVUZCVVN4WlFVRlNMRU5CUVdJc1EwRkljVU03TzBGQlMzcERMRzFDUVVGUExFOUJRVkFzUjBGQmFVSXNWVUZCYWtJc1EwRk1lVU03TzBGQlQzcERMSEZDUVVGVExGVkJRVlFzUTBGQmIwSXNWVUZCY0VJc1JVRkJaME1zVDBGQmFFTXNSVUZCZVVNc1dVRkJla01zUlVGQmRVUTdRVUZEYmtRc2IwSkJRVWtzVFVGQlRTdzRRa0ZCT0VJc1ZVRkJPVUlzUTBGRWVVTTdRVUZGYmtRc2IwSkJRVWtzWVVGQllTeE5RVUZOTEc5Q1FVRk9MRU5CUm10RE96dEJRVWx1UkN4dlFrRkJTU3hsUVVGbExGZEJRVmNzVlVGQldDeEZRVUYxUWl4UFFVRjJRaXhEUVVGbUxFTkJTaXRET3p0QlFVMXVSQ3h2UWtGQlNTeHBRa0ZCYVVJc1QwRkJha0lzUlVGQk1FSTdRVUZETVVJc01FSkJRVTBzU1VGQlNTeExRVUZLTEVOQlFWVXNLMEpCUTFvc1ZVRkVXU3hIUVVORExFdEJSRVFzUjBGRldpd3lRa0ZHV1N4SFFVVnJRaXhaUVVac1FpeEhRVWRhTEdWQlNGa3NSMEZKV2l4M1EwRktXU3hIUVVrclFpeFBRVW92UWl4RFFVRm9RaXhEUVVRd1FqdHBRa0ZCT1VJN08wRkJVVUVzZFVKQlFVOHNWMEZCVnl4SFFVRllMRVZCUVdkQ0xGbEJRV2hDTEVOQlFWQXNRMEZrYlVRN1lVRkJka1E3VTBGUVV5eEZRWGRDVUN4RlFVRkRMR05CUVdFc1EwRkJZaXhGUVhoQ1N5eERRVUZHTEVWQmQwSmpMRWxCUVVjc1EwRkJReXhWUVVGVExFOUJRVlFzUlVGQmFVSXNUVUZCYWtJc1JVRkJkMElzVDBGQmVFSXNSVUZCWjBNN1FVRkRlRVFzWVVGQlF5eFZRVUZWTEUxQlFWWXNSVUZCYVVJN1FVRkRiRUlzYjBKQlFVa3NWMEZCVnl4UFFVRlBMRTFCUVZBc1MwRkJhMElzVjBGQmJFSXNSMEZCWjBNc1RVRkJhRU1zUjBGRFdDeFBRVUZQTEUxQlFWQXNTMEZCYTBJc1YwRkJiRUlzUjBGQlowTXNUVUZCYUVNc1IwRkJlVU1zUlVGQmVrTXNRMEZHWXp0QlFVZHNRaXh2UWtGQlNTeFRRVUZUTEZGQlFWRXNZMEZCVWl4RFFVRlVMRU5CU0dNN08wRkJTMnhDTEc5Q1FVRkpMRTlCUVU4c1VVRkJVQ3hMUVVGdlFpeFhRVUZ3UWl4RlFVRnBRenRCUVVOcVF5d3lRa0ZCVHl4UFFVRlFMRWRCUVdsQ0xGRkJRV3BDTEVOQlJHbERPMmxDUVVGeVF5eE5RVVZQTzBGQlEwZ3NkMEpCUVVrc1VVRkJVU3hUUVVGVExESkNRVUZVTEVOQlFWSXNRMEZFUkRzN1FVRkhTQ3gzUWtGQlNTeERRVUZETEV0QlFVUXNSVUZCVVR0QlFVTlNMR2REUVVGUkxGTkJRVk1zTWtKQlFWUXNTVUZCZDBNc1RVRkJlRU1zUTBGRVFUdHhRa0ZCV2pzN1FVRkpRU3d5UWtGQlR5eFBRVUZRTEVkQlFXbENMRXRCUVdwQ0xFTkJVRWM3YVVKQlJsQTdZVUZNUXl4RFFVRkVMRU5CYVVKSExFbEJha0pJTEVOQmFVSlJMRWxCYWtKU0xFVkJhVUpoTEU5QlFVOHNUVUZCVUN4TFFVRnJRaXhYUVVGc1FpeEhRVUZuUXl4TlFVRm9ReXhIUVVGNVF5eFBRVUZQTEVsQlFWQXNTMEZCWjBJc1YwRkJhRUlzUjBGQk9FSXNTVUZCT1VJc1IwRkJjVU1zVDBGQlR5eE5RVUZRTEV0QlFXdENMRmRCUVd4Q0xFZEJRV2RETEUxQlFXaERMRWRCUVhsRExFVkJRWHBETEVOQmFrSXpSaXhEUVVSM1JEdFRRVUZvUXl4RlFXMUNkRUlzUlVGQlF5eG5Ra0ZCWlN4RFFVRm1MRVZCYmtKdlFpeERRVUZJTEVWQmJVSkZMRWxCUVVjc1EwRkJReXhWUVVGVExFOUJRVlFzUlVGQmFVSXNUVUZCYWtJc1JVRkJkMElzVDBGQmVFSXNSVUZCWjBNN1FVRkRNVVFzZVVKQlJEQkVPenRCUVVjeFJDeHRRa0ZCVHl4UFFVRlFMRWRCUVdsQ0xGTkJRVk1zVVVGQlZDeERRVUZyUWl4RFFVRnNRaXhGUVVGeFFqdEJRVU55UXl4MVFrRkJUeXhQUVVGUExFTkJRVkFzUzBGQllTeFJRVUZpTEVsQlFYbENMRTFCUVUwc1NVRkJUaXhEUVVSTE8yRkJRWEpDTEVOQlNIbERPMU5CUVdoRExFVkJUM2hDTEVWQlVIVkNMRU5CUVVnc1JVRlBhRUlzU1VGQlJ5eERRVUZETEZWQlFWTXNUMEZCVkN4RlFVRnBRaXhOUVVGcVFpeEZRVUYzUWl4UFFVRjRRaXhGUVVGblF6dEJRVU14UXl4blFrRkJTU3huUWtGQlowSXNUVUZCVFN4UFFVRk9MRU5CUkhOQ08wRkJSVEZETEdkQ1FVRkpMRmRCUVZjc1QwRkJUeXhUUVVGUUxFTkJRV2xDTEZGQlFXcENMRU5CUmpKQ096dEJRVWt4UXl4dFFrRkJUeXhQUVVGUUxFZEJRV2xDTEdsQ1FVRnBRaXhQUVVGcVFpeERRVXA1UWpzN1FVRk5NVU1zY1VKQlFWTXNUMEZCVkN4RFFVRnBRaXhIUVVGcVFpeEZRVUZ6UWp0QlFVTnNRaXgxUWtGQlR5eFRRVUZUTEVsQlFWUXNRMEZCWXl4SFFVRmtMRTFCUVhWQ0xHZENRVUYyUWl4RFFVUlhPMkZCUVhSQ08xTkJUbFVzUlVGVlVpeEZRVlpQTEVOQlFVZ3NSVUZWUVN4SlFVRkhMRU5CUVVNc1ZVRkJVeXhQUVVGVUxFVkJRV2xDTEUxQlFXcENMRVZCUVhkQ0xFOUJRWGhDTEVWQlFXZERPMEZCUXpGRExHZENRVUZKTEZGQlFWRXNVVUZCVVN4cFFrRkJVaXhEUVVGU0xFTkJSSE5ET3p0QlFVY3hReXh0UWtGQlR5eFBRVUZRTEVkQlFXbENMRXRCUVdwQ0xFTkJTREJETzFOQlFXaERMRVZCUzFJc1JVRkJReXh0UWtGQmEwSXNSVUZCYkVJc1JVRk1UU3hEUVVGSUxFVkJTMjlDTEVsQlFVY3NRMEZCUXl4VlFVRlRMRTlCUVZRc1JVRkJhVUlzVFVGQmFrSXNSVUZCZDBJc1QwRkJlRUlzUlVGQlowTTdRVUZET1VRc1owSkJRVWtzVjBGQlZ5eFJRVUZSTEZkQlFWSXNRMEZCV0N4RFFVUXdSRHRCUVVVNVJDeG5Ra0ZCU1N4VFFVRlRMRkZCUVZFc2MwSkJRVklzUTBGQlZDeERRVVl3UkRzN1FVRkpPVVFzYlVKQlFVOHNUMEZCVUN4SFFVRnBRaXhsUVVGcVFpeERRVW80UkRzN1FVRk5PVVFzY1VKQlFWTXNaVUZCVkN4RFFVRjVRaXhKUVVGNlFpeEZRVUVyUWl4TFFVRXZRaXhGUVVGelF5eFJRVUYwUXl4RlFVRm5SRHRCUVVNMVF5eHhRa0ZCU3l4SlFVRkpMRkZCUVVvc1NVRkJaMElzUzBGQmNrSXNSVUZCTkVJN1FVRkRlRUlzZDBKQlFVa3NXVUZCV1N4TlFVRk5MRkZCUVU0c1EwRkJXaXhEUVVSdlFqczdRVUZIZUVJc2QwSkJRVWtzWTBGQll5eFRRVUZrTEVWQlFYbENPMEZCUTNwQ0xIVkRRVUZsTEVsQlFXWXNSVUZCY1VJc1VVRkJja0lzUlVGQkswSXNVMEZCTDBJc1JVRkJNRU1zVVVGQk1VTXNSVUZFZVVJN2NVSkJRVGRDTEUxQlJVOHNTVUZCU1N4UFFVRlBMRk5CUVZBc1EwRkJTaXhGUVVGMVFqdEJRVU14UWl4MVEwRkJaU3hKUVVGbUxFVkJRWEZDTEZGQlFYSkNMRVZCUVN0Q0xGTkJRUzlDTEVWQlFUQkRMRkZCUVRGRExFVkJSREJDTzBGQlJURkNMRFJDUVVGSkxGVkJRVlVzU1VGQlZpeEZRVUZuUWp0QlFVTm9RaXh6UTBGQlZTeEpRVUZXTEVOQlFXVXNTVUZCWml4RlFVTkpMRkZCUkVvc1JVRkZTU3hYUVVGWExGTkJRVk1zVVVGQlZDeERRVUZZTEVkQlFXZERMRk5CUVdoRExFTkJSa29zUTBGRVowSTdlVUpCUVhCQ08zRkNRVVpITEUxQlQwRTdRVUZEU0N3MFFrRkJTU3hUUVVGVExGTkJRVlFzUTBGQlNpeEZRVUY1UWp0QlFVTnlRaXgzUTBGQldTeEpRVUZhTEVWQlFXdENMRXRCUVd4Q0xFVkJRWGxDTEZGQlFYcENMRVZCUVcxRExGRkJRVzVETEVWQlFUWkRMRk5CUVRkRExFVkJSSEZDTzNsQ1FVRjZRaXhOUVVWUE8wRkJRMGdzYVVOQlFVc3NVVUZCVEN4SlFVRnBRaXhUUVVGcVFpeERRVVJITzNsQ1FVWlFPM0ZDUVZKSE8ybENRVXhZTzJGQlJFbzdPMEZCZFVKQkxIRkNRVUZUTEdOQlFWUXNRMEZCZDBJc1NVRkJlRUlzUlVGQk9FSXNVVUZCT1VJc1JVRkJkME1zVTBGQmVFTXNSVUZCYlVRc1VVRkJia1FzUlVGQk5rUTdRVUZEZWtRc2IwSkJRVWtzVVVGQlNpeEZRVUZqTzBGQlExWXNkMEpCUVVrc1owSkJRV2RDTEZOQlFWTXNVVUZCVkN4RFFVRm9RaXhEUVVSTk96dEJRVWRXTEhkQ1FVRkpMRU5CUVVNc1QwRkJUeXhoUVVGUUxFTkJRVVFzUlVGQmQwSTdRVUZEZUVJc05FSkJRVWtzWVVGQllTeFpRVUZpTEVWQlFUSkNPMEZCUXpOQ0xHbERRVUZMTEVsQlFVa3NVVUZCU2l4SlFVRm5RaXhoUVVGeVFpeEZRVUZ2UXp0QlFVTm9ReXh4UTBGQlN5eGxRVUZNTEVOQlFYRkNMRkZCUVhKQ0xFVkJSR2RET3paQ1FVRndRenQ1UWtGRVNpeE5RVWxQTEVsQlFVa3NZVUZCWVN4UFFVRmlMRVZCUVhOQ08wRkJRemRDTEdsRFFVRkxMRWxCUVVrc1EwRkJTaXhKUVVGVExHRkJRV1FzUlVGQk5rSTdRVUZEZWtJc2NVTkJRVXNzUzBGQlRDeERRVUZYTEVOQlFWZ3NTVUZCWjBJc1JVRkJhRUlzUTBGRWVVSTdOa0pCUVRkQ08zbENRVVJITEUxQlNVRXNTVUZCU1N4UFFVRlBMR0ZCUVZBc1MwRkJlVUlzVVVGQmVrSXNSVUZCYlVNN1FVRkRNVU1zYVVOQlFVc3NVVUZCVEN4SlFVRnBRaXhGUVVGcVFpeERRVVF3UXp0NVFrRkJka01zVFVGRlFUdEJRVU5JTEdsRFFVRkxMRkZCUVV3c1NVRkJhVUlzU1VGQmFrSXNRMEZFUnp0NVFrRkdRVHR4UWtGVVdDeE5RV05QTEVsQlFVa3NZMEZCWXl4TlFVRmtMRVZCUVhOQ08wRkJRemRDTEhORFFVRmpMRTFCUVdRc1EwRkJjVUlzU1VGQmNrSXNSVUZCTWtJc1VVRkJNMElzUlVGQmNVTXNVMEZCY2tNc1JVRkVOa0k3Y1VKQlFURkNPMmxDUVdwQ1dEdGhRVVJLT3p0QlFYZENRU3h4UWtGQlV5eFhRVUZVTEVOQlFYRkNMRWxCUVhKQ0xFVkJRVEpDTEV0QlFUTkNMRVZCUVd0RExGRkJRV3hETEVWQlFUUkRMRkZCUVRWRExFVkJRWE5FTEZOQlFYUkVMRVZCUVdsRk8wRkJRemRFTEc5Q1FVRkpMR2RDUVVGblFpeFhRVUZYTEZOQlFWTXNVVUZCVkN4RFFVRllMRWRCUVdkRExGTkJRV2hET3pzN1FVRkVlVU1zYjBKQlNYcEVMR0ZCUVdFc1dVRkJZaXhGUVVFeVFqdEJRVU16UWl4NVFrRkJTeXhKUVVGSkxGRkJRVW9zU1VGQlowSXNVMEZCY2tJc1JVRkJaME03UVVGRE5VSXNORUpCUVVrc1dVRkJXU3hWUVVGVkxGRkJRVllzUTBGQldpeERRVVIzUWpzN1FVRkhOVUlzTkVKQlFVa3NZMEZCWXl4VFFVRmtMRVZCUVhsQ08wRkJRM3BDTEdsRFFVRkxMR1ZCUVV3c1EwRkJjVUlzVVVGQmNrSXNSVUZFZVVJN2VVSkJRVGRDTEUxQlJVODdRVUZEU0N4cFEwRkJTeXhaUVVGTUxFTkJRV3RDTEZGQlFXeENMRVZCUVRSQ0xGTkJRVFZDTEVWQlJFYzdlVUpCUmxBN2NVSkJTRW83TzBGQlZVRXNNa0pCV0RKQ08ybENRVUV2UWpzN1FVRmpRU3h2UWtGQlJ5eHBRa0ZCYVVJc1UwRkJVeXhoUVVGVUxFTkJRV3BDTEVsQlEwTXNZVUZCWVN4aFFVRmlMRTFCUVdkRExHRkJRV0VzVTBGQllpeERRVUZvUXl4RlFVRjVSRHRCUVVONlJDeDVRa0ZCU3l4UlFVRk1MRWxCUVdsQ0xGTkJRV3BDTEVOQlJIbEVPMEZCUlhwRUxESkNRVVo1UkR0cFFrRkVOMFE3TzBGQlRVRXNiMEpCUVVrc1EwRkJReXhUUVVGVExFdEJRVXNzVVVGQlRDeERRVUZVTEVOQlFVUXNSVUZCTWtJN1FVRkRNMElzZVVKQlFVc3NVVUZCVEN4SlFVRnBRaXhGUVVGcVFpeERRVVF5UWp0cFFrRkJMMEk3TzBGQlNVRXNiMEpCUVVrc1YwRkJWeXhoUVVGaExFOUJRV0lzUjBGQmRVSXNSVUZCZGtJc1IwRkJORUlzVTBGQk5VSXNRMEUxUWpoRE96dEJRVGhDTjBRc2NVSkJRVXNzU1VGQlNTeERRVUZLTEVsQlFWTXNVMEZCWkN4RlFVRjVRanRCUVVOeVFpeDNRa0ZCU1N4UlFVRlJMRlZCUVZVc1EwRkJWaXhEUVVGU0xFTkJSR2xDTzBGQlJYSkNMSGxDUVVGTExGRkJRVXdzUlVGQlpTeERRVUZtTEVsQlFXOUNMRXRCUVVNc1MwRkJWU3hUUVVGV0xFZEJRWFZDTEZGQlFYaENMRWRCUVcxRExFdEJRVzVETEVOQlJrTTdhVUpCUVhwQ08yRkJPVUpLT3p0QlFXOURRU3h4UWtGQlV5eFpRVUZVTEVOQlFYTkNMRXRCUVhSQ0xFVkJRVFpDTzBGQlEzcENMRzlDUVVGSkxFOUJRVThzWTBGQlVDeEZRVUYxUWp0QlFVTjJRaXd5UWtGQlR5eFBRVUZQTEdOQlFWQXNRMEZCYzBJc1MwRkJkRUlzUTBGQlVDeERRVVIxUWp0cFFrRkJNMElzVFVGRlR5eEpRVUZKTEUxQlFVMHNVMEZCVGl4RlFVRnBRanRCUVVONFFpd3lRa0ZCVHl4TlFVRk5MRk5CUVU0c1EwRkVhVUk3YVVKQlFYSkNMRTFCUlVFc1NVRkJTU3hOUVVGTkxGZEJRVTRzUlVGQmJVSTdRVUZETVVJc01rSkJRVThzVFVGQlRTeFhRVUZPTEVOQlFXdENMRk5CUVd4Q0xFTkJSRzFDTzJsQ1FVRjJRanRoUVV4WU8xTkJla1k0UWl4RlFXMUhOVUlzUlVGQlF5eDNRa0ZCZFVJc1JVRkJka0lzUlVGQk1FSXNZVUZCV1N4RlFVRmFMRVZCYmtkQkxFTkJRVWdzUlVGdFIyOUNMRWxCUVVjc1EwRkJReXhWUVVGVExFOUJRVlFzUlVGQmFVSXNUVUZCYWtJc1JVRkJkMElzVDBGQmVFSXNSVUZCWjBNN1FVRkRiRVlzWjBKQlFVa3NWMEZCVnl4UlFVRlJMR2xDUVVGU0xFTkJRVmdzUTBGRU9FVTdPMEZCUjJ4R0xHZENRVUZKTEd0Q1FVRnJRaXhSUVVGUkxHOUNRVUZTTEVOQlFXeENMRU5CU0RoRk96dEJRVXRzUml4blFrRkJTU3hWUVVGVkxGRkJRVkVzYzBKQlFWSXNRMEZCVml4RFFVdzRSVHRCUVUxc1JpeG5Ra0ZCU1N4VlFVRlZMRkZCUVZFc2MwSkJRVklzUTBGQlZpeERRVTQ0UlR0QlFVOXNSaXhuUWtGQlNTeFhRVUZYTEZGQlFWRXNkVUpCUVZJc1EwRkJXQ3hEUVZBNFJUdEJRVkZzUml4blFrRkJTU3hqUVVGakxGRkJRVkVzTUVKQlFWSXNRMEZCWkN4RFFWSTRSVHM3UVVGVmJFWXNiVUpCUVU4c1QwRkJVQ3hIUVVGcFFpeGhRVUZxUWl4RFFWWnJSanM3UVVGWmJFWXNjVUpCUVZNc1lVRkJWQ3hEUVVGMVFpeExRVUYyUWl4RlFVRTRRaXhKUVVFNVFpeEZRVUZ2UXp0QlFVTm9ReXh2UWtGQlNTeE5RVUZOTEU5QlFVOHNTMEZCU3l4UlFVRk1MRWxCUVdsQ0xGRkJRV3BDTEVkQlFUUkNMRkZCUVc1RExFTkJSSE5DTzBGQlJXaERMRzlDUVVGSkxFOUJRVThzVDBGQlR5eExRVUZMTEVsQlFVd3NSMEZCV1N4SlFVRnVRaXhEUVVaeFFqczdRVUZKYUVNc2QwSkJRVkVzV1VGQldTeExRVUZhTEVWQlFXMUNMRU5CUVc1Q0xFTkJTbmRDT3p0QlFVMW9ReXh2UWtGQlNTeFRRVUZUTEV0QlFWUXNRMEZCU2l4RlFVRnhRanRCUVVOcVFpd3lRa0ZCVHl4TlFVRk5MRWxCUVU0c1JVRkJVQ3hEUVVScFFqdHBRa0ZCY2tJc1RVRkZUeXhKUVVGSkxGRkJRVkVzUzBGQlVpeERRVUZLTEVWQlFXOUNPMEZCUTNaQ0xESkNRVUZQTEVsQlFVa3NZMEZCU2l4RFFVRnRRaXhOUVVGTkxFbEJRVTRzUTBGQk1VSXNRMEZFZFVJN2FVSkJRWEJDTEUxQlJVRXNTVUZCU1N4RFFVRkRMRkZCUVZFc1MwRkJVaXhEUVVGRUxFVkJRV2xDTzBGQlEzaENMSGRDUVVGSkxFbEJRVW9zUlVGQlZUdEJRVU5PTERaQ1FVRkxMSE5EUVVGTUxFVkJRVFpETEV0QlFUZERMRVZCUkUwN2NVSkJRVlk3UVVGSFFTd3lRa0ZCVHl4SlFVRlFMRU5CU25kQ08ybENRVUZ5UWpzN1FVRlBVQ3h2UWtGQlNTeFBRVUZQTEV0QlFVTXNRMEZCVFN4VFFVRk9MRXRCUVc5Q0xFbEJRWEJDTEVkQlExSXNTVUZCU1N4aFFVRktMRU5CUVd0Q0xFMUJRVTBzVDBGQlRpeERRVVJZTEVkQlJWQXNTVUZCU1N4bFFVRktMRU5CUVc5Q0xFMUJRVTBzVTBGQlRpeEZRVUZwUWl4TlFVRk5MRTlCUVU0c1EwRkdPVUlzUTBGcVFuRkNPenRCUVhGQ2FFTXNiMEpCUVVrc1VVRkJVU3hOUVVGTkxGVkJRVTRzUTBGeVFtOUNPMEZCYzBKb1F5eG5RMEZCWjBJc1NVRkJhRUlzUlVGQmMwSXNTMEZCZEVJc1JVRjBRbWRET3p0QlFYZENhRU1zYjBKQlFVa3NWMEZCVnl4TlFVRk5MRkZCUVU0c1EwRjRRbWxDT3p0QlFUQkNhRU1zY1VKQlFVc3NTVUZCU1N4SlFVRkpMRU5CUVVvc1JVRkJUeXhKUVVGSkxGTkJRVk1zVFVGQlZDeEZRVUZwUWl4SFFVRnlReXhGUVVFd1F6dEJRVU4wUXl4M1FrRkJTU3haUVVGWkxHTkJRV01zVTBGQlV5eERRVUZVTEVOQlFXUXNSVUZCTWtJc1NVRkJNMElzUTBGQldpeERRVVJyUXp0QlFVVjBReXgzUWtGQlNTeFRRVUZLTEVWQlFXVTdRVUZEV0N3MlFrRkJTeXhYUVVGTUxFTkJRV2xDTEZOQlFXcENMRVZCUkZjN2NVSkJRV1k3YVVKQlJrbzdPMEZCVDBFc2RVSkJRVThzU1VGQlVDeERRV3BEWjBNN1lVRkJjRU03VTBGYWEwUXNSVUZuUkdoRUxFVkJRVU1zTkVKQlFUSkNMRVZCUVROQ0xFVkJRVGhDTEhkQ1FVRjFRaXhGUVVGMlFpeEZRVUV3UWl4M1FrRkJkVUlzUlVGQmRrSXNSVUZCTUVJc2VVSkJRWGRDTEVWQlFYaENMRVZCUVRKQ0xITkNRVUZ4UWl4RlFVRnlRaXhGUVVGM1FpeHRRa0ZCYTBJc1JVRkJiRUlzUlVGb1JIWkdMRU5CUVVnc1JVRm5SR2xJTEVsQlFVY3NRMEZCUXl4VlFVRlRMRTlCUVZRc1JVRkJhVUlzVFVGQmFrSXNSVUZCZDBJc1QwRkJlRUlzUlVGQlowTTdPenM3T3pzN1FVRlBiazBzWjBKQlFVa3NWVUZCVlN4RlFVRldMRU5CVUN0TU96dEJRVk51VFN4dFFrRkJUeXhQUVVGUUxFZEJRV2xDTEZGQlFXcENMRU5CVkcxTk96dEJRVmR1VFN4eFFrRkJVeXhSUVVGVUxFTkJRV3RDTEZGQlFXeENMRVZCUVRSQ0xFbEJRVFZDTEVWQlFXdERMRTlCUVd4RExFVkJRVEpETEV0QlFUTkRMRVZCUVd0RU8wRkJRemxETEc5Q1FVRkpMRU5CUVVNc1QwRkJSQ3hKUVVGWkxGRkJRVkVzVFVGQlVpeExRVUZ0UWl4RFFVRnVRaXhGUVVGelFqdEJRVU5zUXl3eVFrRkJUeXhGUVVGUUxFTkJSR3RETzJsQ1FVRjBReXhOUVVWUE8wRkJRMGdzTkVKQlFWRXNTVUZCVWl4RFFVRmhMRk5CUVdJc1JVRkVSenRCUVVWSUxESkNRVUZQTEZGQlFWRXNVVUZCVWl4RlFVRnJRaXhKUVVGc1FpeEZRVUYzUWl4UFFVRjRRaXhGUVVGcFF5eExRVUZxUXl4RlFVRjNReXhEUVVGNFF5eERRVUZRTEVOQlJrYzdhVUpCUmxBN1lVRkVTanM3UVVGVFFTeHhRa0ZCVXl4UFFVRlVMRU5CUVdsQ0xGRkJRV3BDTEVWQlFUSkNMRWxCUVROQ0xFVkJRV2xETEU5QlFXcERMRVZCUVRCRExFdEJRVEZETEVWQlFXbEVMRk5CUVdwRUxFVkJRVFJFTzBGQlEzaEVMSGRDUVVGUkxGTkJRVk1zUlVGQlZDeERRVVJuUkRzN1FVRkplRVFzYjBKQlFVa3NVVUZCU2l4RlFVRmpPMEZCUTFZc2QwSkJRVWtzWVVGQllTeFBRVUZpTEVWQlFYTkNMRk5CUVhSQ0xFVkJRV2xETEZOQlFXcERMRU5CUVVvc1JVRkJhVVE3UVVGRE4wTXNPRUpCUVUwc1UwRkJUaXhKUVVGdFFpeFJRVUZ1UWl4RFFVUTJRenR4UWtGQmFrUTdPMEZCU1VFc2QwSkJRVWtzV1VGQldTeExRVUZMTEZGQlFVd3NRMEZNVGpzN1FVRlBWaXgzUWtGQlNTeFRRVUZLTEVWQlFXVTdPMEZCUlZnc05FSkJRVWtzWVVGQllTeFRRVUZUTEZWQlFWUXNRMEZHVGpzN1FVRkpXQ3cyUWtGQlN5eEpRVUZKTEVsQlFVa3NRMEZCU2l4RlFVRlBMRWxCUVVrc1MwRkJTeXhSUVVGTUxFTkJRV01zVFVGQlpDeEZRVUZ6UWl4SFFVRXhReXhGUVVFclF6dEJRVU16UXl4NVEwRkJZU3hEUVVGaUxFTkJSREpET3p0QlFVY3pReXhuUTBGQlNTeFRRVUZUTEZWQlFWVXNRMEZCVml4TFFVRm5RaXhQUVVGb1FpeERRVWc0UWp0QlFVa3pReXhuUTBGQlNTeFpRVUZaTEdGQlFXRXNUMEZCVHl4TFFVRlFMRWxCUVdkQ0xFTkJRV2hDTEVOQlFXSTdPenRCUVVveVFpeG5RMEZQZGtNc1lVRkJZU3hQUVVGaUxFVkJRWE5DTEZOQlFYUkNMRVZCUVdsRExGTkJRV3BETEVOQlFVb3NSVUZCYVVRN1FVRkROME1zZDBOQlFWRXNWMEZCVnl4RFFVRllMRU5CUVZJc1JVRkJkVUlzVFVGQmRrSXNSVUZCSzBJc1QwRkJMMElzUlVGQmQwTXNTMEZCZUVNc1JVRkJLME1zVTBGQkwwTXNSVUZFTmtNN05rSkJRV3BFT3p0QlFVbEJMSGREUVVGWkxGTkJRVm9zUTBGWU1rTTdlVUpCUVM5RE8zRkNRVXBLTzJsQ1FWQktPenRCUVRKQ1FTeDFRa0ZCVHl4TFFVRlFMRU5CTDBKM1JEdGhRVUUxUkRzN08wRkJjRUp0VFN4eFFrRjFSREZNTEZsQlFWUXNRMEZCYzBJc1QwRkJkRUlzUlVGQkswSXNTVUZCTDBJc1JVRkJjVU1zUzBGQmNrTXNSVUZCTkVNN1FVRkRlRU1zYjBKQlFVa3NVVUZCVVN4TlFVRlNMRXRCUVcxQ0xFTkJRVzVDTEVWQlFYTkNPMEZCUTNSQ0xESkNRVUZQTEV0QlFWQXNRMEZFYzBJN2FVSkJRVEZDT3p0QlFVbEJMRzlDUVVGSkxGZEJRVmNzUTBGQldDeERRVXh2UXp0QlFVMTRReXh2UWtGQlNTeFhRVUZYTEZGQlFWRXNUVUZCVWl4SFFVRnBRaXhEUVVGcVFpeERRVTU1UWp0QlFVOTRReXh2UWtGQlNTeFpRVUZLTEVOQlVIZERPMEZCVVhoRExHOUNRVUZKTEZkQlFVb3NRMEZTZDBNN08wRkJWWGhETEhWQ1FVRlBMRmxCUVZrc1VVRkJXaXhGUVVGelFqdEJRVU42UWl4dFEwRkJaU3hEUVVGRkxGZEJRVmNzVVVGQldDeERRVUZFTEVkQlFYZENMRU5CUVhoQ0xFbEJRVGhDTEVOQlFTOUNMRU5CUkZVN1FVRkZla0lzYTBOQlFXTXNVVUZCVVN4WlFVRlNMRU5CUVdRc1EwRkdlVUk3TzBGQlNYcENMSGRDUVVGSkxHRkJRV0VzVVVGQllpeEZRVUYxUWp0QlFVTjJRaXdyUWtGQlR5eGxRVUZsTEVsQlFXWXNTVUZCZFVJc1pVRkJaU3hMUVVGbUxFTkJSRkE3Y1VKQlFUTkNMRTFCUlU4c1NVRkJTU3hqUVVGakxFbEJRV1FzUlVGQmIwSTdRVUZETTBJc2JVTkJRVmNzWlVGQlpTeERRVUZtTEVOQlJHZENPM0ZDUVVGNFFpeE5RVVZETEVsQlFVa3NZMEZCWXl4TFFVRmtMRVZCUVhGQ08wRkJRemRDTEcxRFFVRlhMR1ZCUVdVc1EwRkJaaXhEUVVSclFqdHhRa0ZCZWtJc1RVRkZSRHRCUVVOSUxDdENRVUZQTEVsQlFWQXNRMEZFUnp0eFFrRkdRenRwUWtGU1dqczdRVUZsUVN4MVFrRkJUeXhMUVVGUUxFTkJla0ozUXp0aFFVRTFRenM3UVVFMFFrRXNjVUpCUVZNc1UwRkJWQ3hEUVVGdFFpeERRVUZ1UWl4RlFVRnpRaXhEUVVGMFFpeEZRVUY1UWp0QlFVTnlRaXgxUWtGQlR5eEpRVUZKTEVOQlFVb3NSMEZCVVN4RFFVRlNMRWRCUVZrc1EwRkJReXhEUVVGRUxFTkJSRVU3WVVGQmVrSTdVMEZ1Um0xTExFVkJkVVpxU3l4RlFYWkdaMHNzUTBGQlNDeEZRWFZHZWtvc1NVRkJSeXhEUVVGRExGVkJRVk1zVDBGQlZDeEZRVUZwUWl4TlFVRnFRaXhGUVVGM1FpeFBRVUY0UWl4RlFVRm5RenRCUVVNeFF5eG5Ra0ZCU1N4clFrRkJhMElzVVVGQlVTeHZRa0ZCVWl4RFFVRnNRaXhEUVVSelF6czdRVUZITVVNc1owSkJRVWtzVjBGQlZ5eFJRVUZSTEhWQ1FVRlNMRU5CUVZnc1EwRkljME03UVVGSk1VTXNaMEpCUVVrc1UwRkJVeXhSUVVGUkxHOUNRVUZTTEVOQlFWUXNRMEZLYzBNN08wRkJUVEZETEdkQ1FVRkpMR1ZCUVdVc1VVRkJVU3hwUWtGQlVpeERRVUZtTEVOQlRuTkRPenRCUVZFeFF5eHRRa0ZCVHl4UFFVRlFMRWRCUVdsQ0xGVkJRV3BDTEVOQlVqQkRPenRCUVZVeFF5eHhRa0ZCVXl4VlFVRlVMRU5CUVc5Q0xFMUJRWEJDTEVWQlFUUkNMRTlCUVRWQ0xFVkJRWEZETEdGQlFYSkRMRVZCUVc5RU8wRkJRMmhFTEc5Q1FVRkpMRTlCUVU4c1QwRkJUeXhKUVVGUUxFTkJSSEZETzBGQlJXaEVMRzlDUVVGSkxGRkJRVkVzVDBGQlR5eExRVUZRTEVOQlJtOURPMEZCUjJoRUxHOUNRVUZKTEZGQlFWRXNUMEZCVHl4TFFVRlFMRU5CU0c5RE96dEJRVXRvUkN4M1FrRkJVU3hKUVVGU08wRkJRMGtzZVVKQlFVc3NUMEZCVHl4TlFVRlFPMEZCUTBRc0swSkJRVThzVjBGQlZ5eFBRVUZZTEVWQlFXOUNMRXRCUVhCQ0xFTkJRVkFzUTBGRVNqdEJRVVJLTEhsQ1FVZFRMRTlCUVU4c1RVRkJVRHRCUVVORUxDdENRVUZQTEZkQlFWY3NUMEZCV0N4RlFVRnZRaXhMUVVGd1FpeEZRVUV5UWl4aFFVRXpRaXhEUVVGUUxFTkJSRW83UVVGSVNpeDVRa0ZMVXl4UFFVRlBMRXRCUVZBN1FVRkRSQ3dyUWtGQlR5eFpRVUZaTEU5QlFWb3NSVUZCY1VJc1MwRkJja0lzUlVGQk5FSXNTMEZCTlVJc1JVRkJiVU1zWVVGQmJrTXNRMEZCVUN4RFFVUktPMEZCVEVvc2VVSkJUMU1zVDBGQlR5eE5RVUZRTzBGQlEwUXNLMEpCUVU4c1dVRkJXU3hQUVVGYUxFVkJRWEZDTEV0QlFYSkNMRVZCUVRSQ0xFdEJRVFZDTEVWQlFXMURMR0ZCUVc1RExFTkJRVkFzUTBGRVNqdEJRVkJLTEhsQ1FWTlRMRTlCUVU4c1MwRkJVRHRCUVVORUxDdENRVUZQTEZkQlFWY3NUMEZCV0N4RlFVRnZRaXhMUVVGd1FpeEZRVUV5UWl4TFFVRXpRaXhGUVVGclF5eGhRVUZzUXl4RFFVRlFMRU5CUkVvN1FVRlVTaXg1UWtGWFV5eFBRVUZQTEV0QlFWQTdRVUZEUkN4M1EwRkJaMElzVDBGQmFFSXNSVUZCZVVJc1MwRkJla0lzUlVGRVNqdEJRVVZKTEN0Q1FVRlBMRTlCUVZBc1EwRkdTanRCUVZoS0xIbENRV05UTEU5QlFVOHNTMEZCVUR0QlFVTkVMSGREUVVGblFpeFBRVUZvUWl4RlFVRjVRaXhMUVVGNlFpeEZRVUZuUXl4TlFVRk5MRlZCUVU0c1EwRkJhRU1zUTBGRVNqdEJRVVZKTEN0Q1FVRlBMRTlCUVZBc1EwRkdTanRCUVdSS0xIbENRV2xDVXl4UFFVRlBMRXRCUVZBN1FVRkRSQ3dyUWtGQlR5eFpRVUZaTEU5QlFWb3NSVUZEU0N4alFVRmpMRXRCUVdRc1EwRkJiMElzVDBGQmNFSXNSVUZCTmtJc1MwRkJOMElzUlVGQmIwTXNZVUZCY0VNc1EwRkVSeXhEUVVGUUxFTkJSRW83UVVGcVFrbzdRVUZ4UWxFc0swSkJRVThzVDBGQlVDeERRVVJLTzBGQmNFSktMR2xDUVV4blJEdGhRVUZ3UkRzN1FVRTRRa0VzY1VKQlFWTXNWVUZCVkN4RFFVRnZRaXhQUVVGd1FpeEZRVUUyUWl4TFFVRTNRaXhGUVVGdlF6dEJRVU5vUXl4dlFrRkJTU3hoUVVGaExGRkJRVkVzVlVGQlVpeERRVVJsT3p0QlFVZG9ReXh2UWtGQlNTeFZRVUZLTEVWQlFXZENPMEZCUTFvc0swSkJRVmNzVjBGQldDeERRVUYxUWl4UFFVRjJRaXhGUVVSWk8ybENRVUZvUWpzN1FVRkpRU3c0UWtGQll5eFBRVUZrTEVWQlFYVkNMRXRCUVhaQ0xFVkJVR2RET3p0QlFWTm9ReXgxUWtGQlR5eEpRVUZRTEVOQlZHZERPMkZCUVhCRE96dEJRVmxCTEhGQ1FVRlRMRlZCUVZRc1EwRkJiMElzVlVGQmNFSXNSVUZCWjBNc1MwRkJhRU1zUlVGQmRVTXNZVUZCZGtNc1JVRkJjMFE3UVVGRGJFUXNiMEpCUVVrc1ZVRkJWU3hqUVVGakxFMUJRV1FzUTBGQmNVSXNTMEZCY2tJc1JVRkJORUlzWVVGQk5VSXNRMEZCVml4RFFVUTRRenM3UVVGSGJFUXNiMEpCUVVrc1ZVRkJTaXhGUVVGblFqdEJRVU5hTEN0Q1FVRlhMRmRCUVZnc1EwRkJkVUlzVDBGQmRrSXNSVUZFV1R0cFFrRkJhRUk3TzBGQlNVRXNkVUpCUVU4c1ZVRkJVQ3hEUVZCclJEdGhRVUYwUkRzN1FVRlZRU3h4UWtGQlV5eFhRVUZVTEVOQlFYRkNMRTlCUVhKQ0xFVkJRVGhDTEZOQlFUbENMRVZCUVhsRExFdEJRWHBETEVWQlFXZEVMR0ZCUVdoRUxFVkJRU3RFTzBGQlF6TkVMRzlDUVVGSkxFOUJRVW9zUTBGRU1rUTdPMEZCUnpORUxHOUNRVUZKTEZGQlFWRXNVVUZCVWl4TFFVRnhRaXhEUVVGeVFpeEZRVUYzUWp0QlFVTjRRaXcwUWtGQlVTeFhRVUZTTEVOQlFXOUNMRU5CUVhCQ0xFVkJRWFZDTEZGQlFWRXNUVUZCVWl4RlFVRm5RaXhOUVVGTkxFbEJRVTRzUTBGQmRrTXNRMEZFZDBJN1FVRkZlRUlzT0VKQlFWVXNUMEZCVml4RFFVWjNRanRwUWtGQk5VSXNUVUZIVHp0QlFVTklMSGRDUVVGSkxHRkJRV0VzVVVGQlVTeFZRVUZTTEVOQlJHUTdRVUZGU0N3NFFrRkJWU3hqUVVGakxFMUJRV1FzUTBGQmNVSXNTMEZCY2tJc1JVRkJORUlzWVVGQk5VSXNRMEZCVml4RFFVWkhPenRCUVVsSUxIZENRVUZKTEdOQlFXTXNXVUZCV1N4UFFVRmFMRVZCUVhGQ08wRkJRMjVETEcxRFFVRlhMRmxCUVZnc1EwRkJkMElzVDBGQmVFSXNSVUZCYVVNc1QwRkJha01zUlVGRWJVTTdjVUpCUVhaRE8ybENRVkJLT3p0QlFWbEJMSFZDUVVGUExFOUJRVkFzUTBGbU1rUTdZVUZCTDBRN08wRkJhMEpCTEhGQ1FVRlRMRmRCUVZRc1EwRkJjVUlzVDBGQmNrSXNSVUZCT0VJc1UwRkJPVUlzUlVGQmVVTXNUVUZCZWtNc1JVRkJhVVFzWVVGQmFrUXNSVUZCWjBVN1FVRkROVVFzYjBKQlFVa3NWMEZCVnl4aFFVRmhMRk5CUVdJc1JVRkJkMElzVFVGQmVFSXNRMEZCV0N4RFFVUjNSRHRCUVVVMVJDeHZRa0ZCU1N4UFFVRktMRU5CUmpSRU96dEJRVWsxUkN4dlFrRkJTU3hSUVVGS0xFVkJRV003UVVGRFZpdzRRa0ZCVlN4UFFVRlBMRTFCUVZBc1EwRkJZeXhUUVVGa0xFVkJRWGxDTEU5QlFYcENMRXRCUVhGRExFOUJRWEpETEVOQlJFRTdhVUpCUVdRc1RVRkZUenRCUVVOSUxEaENRVUZWTEdOQlFXTXNUVUZCWkN4RFFVRnhRaXhOUVVGeVFpeEZRVUUyUWl4aFFVRTNRaXhEUVVGV0xFTkJSRWM3YVVKQlJsQTdPMEZCVFVFc2IwSkJRVWtzWVVGQllTeFJRVUZSTEZWQlFWSXNRMEZXTWtNN08wRkJXVFZFTEc5Q1FVRkpMR05CUVdNc1dVRkJXU3hQUVVGYUxFVkJRWEZDTzBGQlEyNURMQ3RDUVVGWExGbEJRVmdzUTBGQmQwSXNUMEZCZUVJc1JVRkJhVU1zVDBGQmFrTXNSVUZFYlVNN2FVSkJRWFpET3p0QlFVbEJMRzlDUVVGSkxFTkJRVU1zVVVGQlJDeEZRVUZYTzBGQlExZ3NhME5CUVdNc1QwRkJaQ3hGUVVGMVFpeFRRVUYyUWl4RlFVUlhPMmxDUVVGbU96dEJRVWxCTEhWQ1FVRlBMRTlCUVZBc1EwRndRalJFTzJGQlFXaEZPenRCUVhWQ1FTeHhRa0ZCVXl4VlFVRlVMRU5CUVc5Q0xFOUJRWEJDTEVWQlFUWkNMRk5CUVRkQ0xFVkJRWGRETEV0QlFYaERMRVZCUVN0RExHRkJRUzlETEVWQlFUaEVPMEZCUXpGRUxHOUNRVUZKTEdGQlFXRXNVVUZCVVN4VlFVRlNMRU5CUkhsRE8wRkJSVEZFTEc5Q1FVRkpMRlZCUVZVc1kwRkJZeXhOUVVGa0xFTkJRWEZDTEV0QlFYSkNMRVZCUVRSQ0xHRkJRVFZDTEVOQlFWWXNRMEZHYzBRN08wRkJTVEZFTEc5Q1FVRkpMR05CUVdNc1dVRkJXU3hQUVVGYUxFVkJRWEZDTzBGQlEyNURMQ3RDUVVGWExGbEJRVmdzUTBGQmQwSXNUMEZCZUVJc1JVRkJhVU1zVDBGQmFrTXNSVUZFYlVNN2FVSkJRWFpET3p0QlFVbEJMSFZDUVVGUExFOUJRVkFzUTBGU01FUTdZVUZCT1VRN08wRkJWMEVzY1VKQlFWTXNZVUZCVkN4RFFVRjFRaXhQUVVGMlFpeEZRVUZuUXl4RFFVRm9ReXhGUVVGdFF6dEJRVU12UWl4dlFrRkJTU3hQUVVGUExFVkJRVVVzVDBGQlJpeExRVUZqTEZWQlFYSkNMRWxCUVcxRExGTkJRVk1zUTBGQlZDeERRVUZ1UXl4RlFVRm5SRHRCUVVOb1JDeHpRa0ZCUlN4UFFVRkdMRU5CUVZVc1QwRkJWaXhGUVVSblJEdHBRa0ZCY0VRN1lVRkVTanM3UVVGTlFTeHhRa0ZCVXl4bFFVRlVMRU5CUVhsQ0xFOUJRWHBDTEVWQlFXdERMRXRCUVd4RExFVkJRWGxETzBGQlEzSkRMRzlDUVVGSkxHRkJRV0VzVVVGQlVTeFZRVUZTTEVOQlJHOUNPMEZCUlhKRExHOUNRVUZKTEZOQlFWTXNSVUZCVkN4RFFVWnBRenRCUVVkeVF5eHZRa0ZCU1N4SlFVRktMRU5CU0hGRE8wRkJTWEpETEc5Q1FVRkpMRTFCUVVvc1EwRktjVU03UVVGTGNrTXNiMEpCUVVrc1RVRkJTaXhEUVV4eFF6czdRVUZQY2tNc2NVSkJRVXNzU1VGQlNTeEpRVUZKTEVOQlFVb3NSVUZCVHl4SlFVRkpMRTFCUVUwc1QwRkJUaXhEUVVGakxFMUJRV1FzUlVGQmMwSXNSMEZCTVVNc1JVRkJLME03UVVGRE0wTXNOa0pCUVZNc1RVRkJUU3hQUVVGT0xFTkJRV01zUTBGQlpDeERRVUZVTEVOQlJESkRPMEZCUlRORExESkNRVUZQTEZkQlFWY3NUMEZCVHl4SlFVRlFMRU5CUVd4Q0xFTkJSakpETzBGQlJ6TkRMSGRDUVVGSkxFOUJRVThzUjBGQlVDeEZRVUZaTzBGQlExb3NLMEpCUVU4c1QwRkJUeXhIUVVGUUxFTkJRVkFzUjBGQmNVSXNTVUZCY2tJc1EwRkVXVHR4UWtGQmFFSTdRVUZIUVN3MFFrRkJVU3hYUVVGU0xFTkJRVzlDTEVsQlFYQkNMRVZCVGpKRE8ybENRVUV2UXpzN1FVRlRRU3h2UWtGQlNTeFRRVUZUTEZkQlFWY3NUVUZCV0N4RFFXaENkMEk3UVVGcFFuSkRMSEZDUVVGTExFbEJRVWtzU1VGQlNTeERRVUZLTEVWQlFVOHNTVUZCU1N4TlFVRk5MRTlCUVU0c1EwRkJZeXhOUVVGa0xFVkJRWE5DTEVkQlFURkRMRVZCUVN0RE8wRkJRek5ETERaQ1FVRlRMRTFCUVUwc1QwRkJUaXhEUVVGakxFTkJRV1FzUTBGQlZDeERRVVF5UXp0QlFVVXpReXd5UWtGQlR5eFBRVUZQTEU5QlFVOHNSMEZCVUN4RFFVRmtPenRCUVVZeVF5d3lRa0ZKTTBNc1EwRkJVU3haUVVGU0xFTkJRWEZDTEVsQlFYSkNMRVZCUVRKQ0xFOUJRVThzUlVGQlVDeEpRVUZoTEZGQlFXSXNSMEZCZDBJc1NVRkJlRUlzUjBGQkswSXNWMEZCVnl4UFFVRlBMRVZCUVZBc1EwRkJNVU1zUTBGQk0wSXNRMEZLTWtNN2FVSkJRUzlETzJGQmFrSktPenRCUVhsQ1FTeHhRa0ZCVXl4WFFVRlVMRU5CUVhGQ0xFOUJRWEpDTEVWQlFUaENMRTlCUVRsQ0xFVkJRWFZETzBGQlEyNURMRzlDUVVGSkxGZEJRVmNzVDBGQldDeEpRVUZ6UWl4WlFVRlpMRTlCUVZvc1NVRkJkVUlzVVVGQlVTeFZRVUZTTEVWQlFXOUNPMEZCUTJwRkxEUkNRVUZSTEZWQlFWSXNRMEZCYlVJc1dVRkJia0lzUTBGQlowTXNUMEZCYUVNc1JVRkJlVU1zVDBGQmVrTXNSVUZFYVVVN2FVSkJRWEpGT3p0QlFVbEJMSFZDUVVGUExFOUJRVkFzUTBGTWJVTTdZVUZCZGtNN1UwRnFTbFVzUlVGNVNsSXNSVUZCUXl4NVFrRkJkMElzUlVGQmVFSXNSVUZCTWtJc2MwSkJRWEZDTEVWQlFYSkNMRVZCUVhkQ0xITkNRVUZ4UWl4RlFVRnlRaXhGUVVGM1FpeHRRa0ZCYTBJc1JVRkJiRUlzUlVGNlNuSkZMRU5CUVVnc1JVRjVTaXRHTEVsQlFVY3NRMEZCUXl4VlFVRlRMRTlCUVZRc1JVRkJhVUlzVFVGQmFrSXNSVUZCZDBJc1QwRkJlRUlzUlVGQlowTTdRVUZEZWtrc1owSkJRVWtzVjBGQlZ5eFJRVUZSTEdsQ1FVRlNMRU5CUVZnc1EwRkVjVWs3UVVGRmVra3NaMEpCUVVrc1ZVRkJWU3hSUVVGUkxGbEJRVklzUTBGQlZpeERRVVp4U1RzN1FVRkpla2tzWjBKQlFVa3NVMEZCVXl4UlFVRlJMR3RDUVVGU0xFTkJRVlFzUTBGS2NVazdRVUZMZWtrc1owSkJRVWtzVjBGQlZ5eFJRVUZSTEdGQlFWSXNRMEZCV0N4RFFVeHhTVHRCUVUxNlNTeG5Ra0ZCU1N4VlFVRlZMRkZCUVZFc1dVRkJVaXhEUVVGV0xFTkJUbkZKTzBGQlQzcEpMRzFDUVVGUExFOUJRVkFzUjBGQmFVSXNTMEZCYWtJc1EwRlFlVWs3TzBGQlUzcEpMSEZDUVVGVExFdEJRVlFzUTBGQlpTeFJRVUZtTEVWQlFYbENMRTlCUVhwQ0xFVkJRV3RETEdGQlFXeERMRVZCUVdsRU8wRkJRemRETEdkRFFVRm5RaXhwUWtGQmFVSXNSVUZCYWtJc1EwRkVOa0k3UVVGRk4wTXNPRUpCUVdNc1MwRkJaQ3hIUVVGelFpeGpRVUZqTEV0QlFXUXNTVUZCZFVJc1kwRkJZeXhMUVVGa0xFdEJRWGRDTEV0QlFYaENMRWRCUTNaRExHTkJRV01zUzBGQlpDeEhRVU5CTEdOQlJtZENMRU5CUm5WQ08wRkJTemRETERoQ1FVRmpMRTFCUVdRc1IwRkJkVUlzWTBGQll5eE5RVUZrTEVsQlFYZENMRTFCUVhoQ0xFTkJUSE5DT3p0QlFVODNReXgxUWtGQlR5eGpRVUZqTEV0QlFXUXNRMEZCYjBJc1VVRkJjRUlzUlVGQk9FSXNUMEZCT1VJc1JVRkJkVU1zWVVGQmRrTXNRMEZCVUN4RFFWQTJRenRoUVVGcVJEczdRVUZWUVN4eFFrRkJVeXhqUVVGVUxFTkJRWGRDTEZGQlFYaENMRVZCUVd0RExFOUJRV3hETEVWQlFUSkRMR0ZCUVRORExFVkJRVEJFTzBGQlEzUkVMRzlDUVVGSkxGVkJRVlVzWVVGQllTeFBRVUZpTEVOQlFWWXNRMEZFYTBRN08wRkJSM1JFTEc5Q1FVRkpMRkZCUVZFc1RVRkJVaXhMUVVGdFFpeERRVUZ1UWl4RlFVRnpRanRCUVVOMFFpd3lRa0ZCVHl4UlFVRlFMRU5CUkhOQ08ybENRVUV4UWpzN1FVRkpRU3h2UWtGQlNTeFJRVUZSTEZOQlFWTXNVVUZCVkN4RlFVRnRRaXhSUVVGUkxFTkJRVklzUlVGQlZ5eFBRVUU1UWl4RFFVRlNMRU5CVUd0RU8wRkJVWFJFTEc5Q1FVRkpMR2RDUVVGblFpeFRRVUZUTEdGQlFWUXNRMEZTYTBNN08wRkJWWFJFTEc5Q1FVRkpMRU5CUVVNc1kwRkJZeXhSUVVGa0xFbEJRVEJDTEd0Q1FVRnJRaXhSUVVGc1FpeEZRVUUwUWp0QlFVTjJSQ3hyUTBGQll5eFJRVUZrTEVkQlFYbENMR0ZCUVhwQ0xFTkJSSFZFTzJsQ1FVRXpSRHM3UVVGSlFTeHhRa0ZCU3l4SlFVRkpMRWxCUVVrc1EwRkJTaXhGUVVGUExFbEJRVWtzVVVGQlVTeE5RVUZTTEVWQlFXZENMRWRCUVhCRExFVkJRWGxETzBGQlEzSkRMSGRDUVVGSkxGbEJRVmtzVVVGQlVTeERRVUZTTEVOQlFWb3NRMEZFYVVNN1FVRkZja01zSzBKQlFWY3NWMEZCVnl4UlFVRllMRVZCUTFBc1RVRkJUU3hUUVVGT0xFTkJSRThzUlVGRlVDeFJRVUZSTEZOQlFWSXNRMEZHVHl4RlFVZFFMR0ZCU0U4c1EwRkJXQ3hEUVVaeFF6dHBRa0ZCZWtNN08wRkJVVUVzZFVKQlFVOHNVVUZCVUN4RFFYUkNjMFE3WVVGQk1VUTdPMEZCZVVKQkxIRkNRVUZUTEZWQlFWUXNRMEZCYjBJc1VVRkJjRUlzUlVGQk9FSXNUMEZCT1VJc1JVRkJkVU1zVTBGQmRrTXNSVUZCYTBRc1lVRkJiRVFzUlVGQmFVVTdRVUZETjBRc2IwSkJRVWtzUTBGQlF5eFBRVUZFTEVWQlFWVTdRVUZEVml3eVFrRkJUeXhSUVVGUUxFTkJSRlU3YVVKQlFXUTdPMEZCU1VFc2IwSkJRVWtzVDBGQlNpeERRVXcyUkRzN1FVRlBOMFFzYjBKQlFVa3NVVUZCVVN4VFFVRlNMRU5CUVVvc1JVRkJkMEk3UVVGRGNFSXNlVUpCUVVzc1NVRkJTU3hKUVVGSkxFTkJRVW9zUlVGQlR5eEpRVUZKTEZWQlFWVXNUVUZCVml4RlFVRnJRaXhIUVVGMFF5eEZRVUV5UXp0QlFVTjJReXhyUTBGQlZTeFJRVUZSTEZWQlFWVXNRMEZCVml4RFFVRlNMRVZCUVhOQ0xFOUJRWFJDTEVWQlFTdENMR0ZCUVM5Q0xFTkJRVllzUTBGRWRVTTdPMEZCUjNaRExEUkNRVUZKTEZsQlFWa3NVVUZCV2l4RlFVRnpRanRCUVVOMFFpeDFRMEZCVnl4UFFVRllMRU5CUkhOQ08zbENRVUV4UWp0eFFrRklTanRwUWtGRVNpeE5RVkZQTzBGQlEwZ3NPRUpCUVZVc1VVRkJVU3hUUVVGU0xFVkJRVzFDTEU5QlFXNUNMRVZCUVRSQ0xHRkJRVFZDTEVOQlFWWXNRMEZFUnpzN1FVRkhTQ3gzUWtGQlNTeFpRVUZaTEZGQlFWb3NSVUZCYzBJN1FVRkRkRUlzYlVOQlFWY3NUMEZCV0N4RFFVUnpRanR4UWtGQk1VSTdhVUpCV0VvN08wRkJaMEpCTEhWQ1FVRlBMRkZCUVZBc1EwRjJRalpFTzJGQlFXcEZPenRCUVRCQ1FTeHhRa0ZCVXl4WlFVRlVMRU5CUVhOQ0xFOUJRWFJDTEVWQlFTdENPMEZCUXpOQ0xHOUNRVUZKTEZWQlFWVXNSVUZCVml4RFFVUjFRanM3UVVGSE0wSXNjVUpCUVVzc1NVRkJTU3hIUVVGS0xFbEJRVmNzVDBGQmFFSXNSVUZCZVVJN1FVRkRja0lzZDBKQlFVa3NVVUZCVVN4SFFVRlNMRVZCUVdFN1FVRkRZaXhuUTBGQlVTeEpRVUZTTEVOQlFXRXNUMEZCVHl4SFFVRlFMRU5CUVdJc1JVRkVZVHR4UWtGQmFrSTdhVUpCUkVvN08wRkJUVUVzZFVKQlFVOHNUMEZCVUN4RFFWUXlRanRoUVVFdlFqdFRRWFJGZVVjc1JVRnJSblpITEVWQlFVTXNiMEpCUVcxQ0xFVkJRVzVDTEVWQlFYTkNMR1ZCUVdNc1JVRkJaQ3hGUVVGcFFpeGpRVUZoTEVWQlFXSXNSVUZCWjBJc2JVSkJRV3RDTEVWQlFXeENMRVZCUVhGQ0xHTkJRV0VzUlVGQllpeEZRV3hHZVVJc1EwRkJTQ3hGUVd0R1NpeEpRVUZITEVOQlFVTXNWVUZCVXl4UFFVRlVMRVZCUVdsQ0xFMUJRV3BDTEVWQlFYZENMRTlCUVhoQ0xFVkJRV2RETzBGQlEzSkpMR2RDUVVGSkxGZEJRVmNzVVVGQlVTeDFRa0ZCVWl4RFFVRllMRU5CUkdsSk96dEJRVWR5U1N4dFFrRkJUeXhQUVVGUUxFZEJRV2xDTEZsQlFXcENMRU5CU0hGSk96dEJRVXR5U1N4eFFrRkJVeXhaUVVGVUxFTkJRWE5DTEVOQlFYUkNMRVZCUVhsQ0xFTkJRWHBDTEVWQlFUUkNPMEZCUTNoQ0xHOUNRVUZKTEZOQlFWTXNRMEZCVkN4TFFVRmxMRk5CUVZNc1EwRkJWQ3hEUVVGbUxFVkJRVFJDTzBGQlF6VkNMSGRDUVVGSkxGVkJRVlVzUTBGQlZpeEpRVUZsTEZWQlFWVXNRMEZCVml4RlFVRmhPMEZCUXpWQ0xDdENRVUZQTEVWQlFVVXNSVUZCUml4TFFVRlRMRVZCUVVVc1JVRkJSaXhEUVVSWk8zRkNRVUZvUXl4TlFVVlBPMEZCUTBnc0swSkJRVThzUlVGQlJTeEpRVUZHTEV0QlFWY3NSVUZCUlN4SlFVRkdMRU5CUkdZN2NVSkJSbEE3YVVKQlJFbzdPMEZCVVVFc2RVSkJRVThzUzBGQlVDeERRVlIzUWp0aFFVRTFRanRUUVV4eFJ5eEZRV2xDYmtjc1JVRkJReXg1UWtGQmQwSXNSVUZCZUVJc1JVRnFRbWxITEVOQlFVZ3NSVUZwUW1wRkxFbEJRVWNzUTBGQlF5eFZRVUZUTEU5QlFWUXNSVUZCYVVJc1RVRkJha0lzUlVGQmQwSXNUMEZCZUVJc1JVRkJaME03UVVGRGNFVXNlVUpCUkc5Rk96dEJRVWR3UlN4blFrRkJTU3hWUVVGVkxGRkJRVkVzVlVGQlVpeERRVUZXTEVOQlNHZEZPenRCUVV0d1JTeHRRa0ZCVHl4UFFVRlFMRWRCUVdsQ0xFMUJRV3BDTEVOQlRHOUZPenRCUVU5d1JTeHhRa0ZCVXl4TlFVRlVMRU5CUVdkQ0xFdEJRV2hDTEVWQlFYVkNPMEZCUTI1Q0xHOUNRVUZKTEVWQlFVVXNaMEpCUVdkQ0xFMUJRV2hDTEVOQlFVWXNSVUZCTWtJN1FVRkRNMElzTWtKQlFVOHNTVUZCU1N4TlFVRktMRU5CUVZjc1MwRkJXQ3hEUVVGUUxFTkJSREpDTzJsQ1FVRXZRanM3UVVGSlFTeHhRa0ZCU3l4TFFVRk1MRWRCUVdFc1MwRkJZaXhEUVV4dFFqdGhRVUYyUWpzN1FVRlJRU3h0UWtGQlR5eFRRVUZRTEVOQlFXbENMRWxCUVdwQ0xFZEJRWGRDTEZWQlFWVXNTVUZCVml4RlFVRm5RaXhaUVVGb1FpeEZRVUU0UWp0QlFVTnNSQ3h2UWtGQlNTeExRVUZMTEZGQlFWRXNTVUZCVWl4RFFVRk1MRU5CUkRoRE8wRkJSV3hFTEc5Q1FVRkpMRmRCUVZjc1lVRkJZU3hOUVVGaUxFTkJRVzlDTEVOQlFYQkNMRU5CUVZnc1EwRkdPRU03TzBGQlNXeEVMRzFDUVVGSExGRkJRVWdzU1VGQlpTeExRVUZMTEV0QlFVd3NRMEZLYlVNN1lVRkJPVUlzUTBGbU5FTTdPMEZCYzBKd1JTeHRRa0ZCVHl4VFFVRlFMRU5CUVdsQ0xFMUJRV3BDTEVkQlFUQkNMRlZCUVZNc1NVRkJWQ3hGUVVGbExGbEJRV1lzUlVGQk5rSTdRVUZEYmtRc2IwSkJRVWtzUzBGQlN5eFJRVUZSTEVsQlFWSXNRMEZCVEN4RFFVUXJRenRCUVVWdVJDeHZRa0ZCU1N4WFFVRlhMR0ZCUVdFc1RVRkJZaXhEUVVGdlFpeERRVUZ3UWl4RFFVRllMRU5CUml0RE96dEJRVWx1UkN4dFFrRkJSeXhSUVVGSUxFbEJRV1VzVTBGQlppeERRVXB0UkR0aFFVRTNRaXhEUVhSQ01FTTdVMEZCYUVNc1JVRTJRbXhETEVWQlFVTXNXVUZCVnl4RFFVRllMRVZCTjBKblF5eERRVUZJTEVWQk5rSmtMRWxCUVVjc1EwRkJReXhWUVVGVExFOUJRVlFzUlVGQmFVSXNUVUZCYWtJc1JVRkJkMElzVDBGQmVFSXNSVUZCWjBNN1FVRkRkRVFzZVVKQlJITkVPenRCUVVkMFJDeHRRa0ZCVHl4UFFVRlFMRWRCUVdsQ0xGZEJRV3BDTEVOQlNITkVPenRCUVV0MFJDeHhRa0ZCVXl4WFFVRlVMRU5CUVhGQ0xFdEJRWEpDTEVWQlFUUkNPMEZCUTNoQ0xHOUNRVUZKTEVWQlFVVXNaMEpCUVdkQ0xGZEJRV2hDTEVOQlFVWXNSVUZCWjBNN1FVRkRhRU1zTWtKQlFVOHNTVUZCU1N4WFFVRktMRU5CUVdkQ0xFdEJRV2hDTEVOQlFWQXNRMEZFWjBNN2FVSkJRWEJET3p0QlFVbEJMSEZDUVVGTExFdEJRVXdzUjBGQllTeExRVUZpTEVOQlRIZENPMkZCUVRWQ096dEJRVkZCTEhkQ1FVRlpMRk5CUVZvc1EwRkJjMElzU1VGQmRFSXNSMEZCTmtJc1ZVRkJWU3hKUVVGV0xFVkJRV2RDTEZsQlFXaENMRVZCUVRoQ08wRkJRM1pFTEc5Q1FVRkpMRXRCUVVzc1dVRkJUQ3hOUVVGMVFpeExRVUZMTEV0QlFVd3NSVUZCV1R0QlFVTnVReXg1UWtGQlN5eFpRVUZNTEVsQlFYRkNMRXRCUVVzc1MwRkJUQ3hEUVVSak8ybENRVUYyUXp0aFFVUjVRaXhEUVdKNVFqdFRRVUZvUXl4RlFXMUNjRUlzUlVGdVFtMUNMRU5CUVVnc1JVRnRRbG9zU1VGQlJ5eERRVUZETEZWQlFWTXNUMEZCVkN4RlFVRnBRaXhOUVVGcVFpeEZRVUYzUWl4UFFVRjRRaXhGUVVGblF6dEJRVU14UXl4NVFrRkVNRU03TzBGQlJ6RkRMR2RDUVVGSkxGVkJRVlVzVVVGQlVTeFpRVUZTTEVOQlFWWXNRMEZJYzBNN08wRkJTekZETEdkQ1FVRkpMRkZCUVZFc1VVRkJVU3h0UWtGQlVpeERRVUZTTEVOQlRITkRPMEZCVFRGRExHZENRVUZKTEZGQlFWRXNVVUZCVVN4dFFrRkJVaXhEUVVGU0xFTkJUbk5ETzBGQlR6RkRMR2RDUVVGSkxGVkJRVlVzVVVGQlVTeHRRa0ZCVWl4RFFVRldMRU5CVUhORE8wRkJVVEZETEdkQ1FVRkpMRlZCUVZVc1VVRkJVU3h0UWtGQlVpeERRVUZXTEVOQlVuTkRPMEZCVXpGRExHZENRVUZKTEZkQlFWY3NVVUZCVVN4dlFrRkJVaXhEUVVGWUxFTkJWSE5ETzBGQlZURkRMR2RDUVVGSkxGTkJRVk1zVVVGQlVTeHRRa0ZCVWl4RFFVRlVMRU5CVm5ORE8wRkJWekZETEdkQ1FVRkpMRmRCUVZjc1VVRkJVU3h0UWtGQlVpeERRVUZZTEVOQldITkRPenRCUVdFeFF5eG5Ra0ZCU1N4WFFVRlhMRkZCUVZFc1owSkJRVklzUTBGQldDeERRV0p6UXp0QlFXTXhReXhuUWtGQlNTeGpRVUZqTEZGQlFWRXNNRUpCUVZJc1EwRkJaQ3hEUVdSelF6dEJRV1V4UXl4blFrRkJTU3hUUVVGVExGRkJRVkVzYjBKQlFWSXNRMEZCVkN4RFFXWnpRenM3UVVGcFFqRkRMRzFDUVVGUExFOUJRVkFzUjBGQmFVSXNRMEZCYWtJc1EwRnFRakJET3p0QlFXMUNNVU1zY1VKQlFWTXNRMEZCVkN4RFFVRlhMRTlCUVZnc1JVRkJiMElzVlVGQmNFSXNSVUZCWjBNc1VVRkJhRU1zUlVGQk1FTTdRVUZEZEVNc2IwSkJRVWtzWVVGQllTeEZRVUZpTEVOQlJHdERPMEZCUlhSRExHOUNRVUZKTEVkQlFVb3NSVUZCVXl4TFFVRlVMRVZCUVdkQ0xFZEJRV2hDTEVWQlFYRkNMRk5CUVhKQ0xFTkJSbk5ET3p0QlFVbDBReXh2UWtGQlNTeERRVUZETEZGQlFVUXNTVUZCWVN4WFFVRlhMRlZCUVZnc1EwRkJZaXhGUVVGeFF6dEJRVU55UXl3clFrRkJWeXhWUVVGWUxFTkJSSEZETzBGQlJYSkRMRFJDUVVGUkxFVkJRVklzUTBGR2NVTTdhVUpCUVhwRE96dEJRVXRCTEhkQ1FVRlJMRk5CUVZNc1ZVRkJWQ3hKUVVGMVFpeEZRVUYyUWl4RFFWUTRRanRCUVZWMFF5eHpRa0ZCVFN4VFFVRlRMRTlCUVZRc1JVRkJhMElzUzBGQmJFSXNRMEZCVGpzN08wRkJWbk5ETEc5Q1FXRnNReXhOUVVGTkxHTkJRVTRzUTBGQmNVSXNTMEZCY2tJc1EwRkJTaXhGUVVGcFF6dEJRVU0zUWl3d1FrRkJUU3hOUVVGTkxFZEJRVTRzUTBGRWRVSTdRVUZGTjBJc01FSkJRVTBzUjBGQlRpeEhRVUZaTEZOQlFWb3NRMEZHTmtJN2FVSkJRV3BET3pzN1FVRmljME1zYjBKQmJVSnNReXhOUVVGTkxHTkJRVTRzUTBGQmNVSXNWMEZCY2tJc1EwRkJTaXhGUVVGMVF6dEJRVU51UXl4blEwRkJXU3hOUVVGTkxGTkJRVTRzUTBGRWRVSTdRVUZGYmtNc01FSkJRVTBzVTBGQlRpeEhRVUZyUWl4VFFVRnNRaXhEUVVadFF6dHBRa0ZCZGtNN096dEJRVzVDYzBNc2IwSkJlVUpzUXl4UlFVRlJMRTlCUVZJc1NVRkRRU3hEUVVGRExGTkJRVVFzU1VGRFFTeE5RVUZOTEdOQlFVNHNRMEZCY1VJc1QwRkJja0lzUTBGR1FTeEpRVWRCTEUxQlFVMHNTMEZCVGl4TFFVRm5RaXhUUVVGb1FpeEpRVU5CTEVOQlFVTXNUMEZCVHl4TlFVRk5MRXRCUVU0c1EwRkJVaXhGUVVOR08wRkJRMFVzTUVKQlFVMHNTMEZCVGl4SFFVRmpMRmxCUVZrc1RVRkJUU3hMUVVGT0xFTkJRVEZDTEVOQlJFWTdhVUpCVEVZN08wRkJVMEVzYjBOQlFXOUNMRXRCUVhCQ0xFVkJiRU56UXpzN1FVRnZRM1JETEc5Q1FVRkpMR0ZCUVdFc1UwRkJZaXhKUVVFd1FpeGhRVUZoTEVsQlFXSXNSVUZCYlVJN1FVRkROME1zTmtKQlFWTXNVVUZCVkN4RlFVRnRRaXhWUVVGdVFpeEZRVUVyUWl4SFFVRXZRaXhGUVVGdlF5eExRVUZ3UXl4RlFVUTJRenRwUWtGQmFrUTdPMEZCUzBFc2RVSkJRVThzU1VGQlNTeExRVUZLTEVOQlFWVXNSMEZCVml4RlFVRmxMRXRCUVdZc1JVRkJjMElzVlVGQmRFSXNSVUZCYTBNc1IwRkJiRU1zUlVGQmRVTXNVMEZCZGtNc1EwRkJVQ3hEUVhwRGMwTTdZVUZCTVVNN08wRkJORU5CTEhGQ1FVRlRMRkZCUVZRc1EwRkJhMElzUTBGQmJFSXNSVUZCY1VJc1ZVRkJja0lzUlVGQmFVTXNSMEZCYWtNc1JVRkJjME1zUzBGQmRFTXNSVUZCTmtNN1FVRkRla01zYjBKQlFVa3NUMEZCVHl4RFFVRlFMRXRCUVdFc1VVRkJZaXhGUVVGMVFqdEJRVU4yUWl3clFrRkJWeXhKUVVGWUxFTkJRV2RDTEVsQlFVa3NTMEZCU2l4RFFVRlZMRU5CUVZZc1EwRkJhRUlzUlVGRWRVSTdhVUpCUVROQ0xFMUJSVThzU1VGQlNTeFBRVUZQTEVOQlFWQXNTMEZCWVN4UlFVRmlMRVZCUVhWQ08wRkJRemxDTEN0Q1FVRlhMRWxCUVZnc1EwRkJaMElzU1VGQlNTeExRVUZLTEVOQlFWVXNUMEZCVHl4RFFVRlFMRU5CUVZZc1EwRkJhRUlzUlVGRU9FSTdhVUpCUVROQ0xFMUJSVUVzU1VGQlNTeFJRVUZSTEVOQlFWSXNRMEZCU2l4RlFVRm5RanRCUVVOdVFpd3JRa0ZCVnl4SlFVRllMRU5CUVdkQ0xFTkJRV2hDTEVWQlJHMUNPMmxDUVVGb1FpeE5RVVZCTEVsQlFVa3NVVUZCVVN4RFFVRlNMRU5CUVVvc1JVRkJaMEk3UVVGRGJrSXNlVUpCUVVzc1NVRkJTU3hKUVVGSkxFTkJRVW9zUlVGQlR5eEpRVUZKTEVWQlFVVXNUVUZCUml4RlFVRlZMRWRCUVRsQ0xFVkJRVzFETzBGQlF5OUNMR2xEUVVGVExFVkJRVVVzUTBGQlJpeERRVUZVTEVWQlFXVXNWVUZCWml4RlFVRXlRaXhIUVVFelFpeEZRVUZuUXl4TFFVRm9ReXhGUVVRclFqdHhRa0ZCYmtNN2FVSkJSRWNzVFVGSlFTeEpRVUZKTEUxQlFVMHNTVUZCVGl4SlFVRmpMRTFCUVUwc1UwRkJUaXhGUVVGcFFqdEJRVU4wUXl3eVFrRkVjME03YVVKQlFXNURMRTFCUlVFN1FVRkRTQ3d3UWtGQlRTeDVRa0ZCZVVJN1FVRkRNMElzZFVOQlFXVXNRMEZCWmp0QlFVTkJMSEZEUVVGaE8wRkJRMVFzY1VOQlFWTXNSMEZCVkR0QlFVTkJMSGREUVVGWkxFdEJRVm83ZVVKQlJrbzdjVUpCUmtVc1EwRkJUaXhEUVVSSE8ybENRVVpCTzJGQldGZzdPMEZCZDBKQkxIRkNRVUZUTEcxQ1FVRlVMRU5CUVRaQ0xFdEJRVGRDTEVWQlFXOURPMEZCUTJoRExIRkNRVUZMTEVsQlFVa3NVVUZCU2l4SlFVRm5RaXhMUVVGeVFpeEZRVUUwUWp0QlFVTjRRaXgzUWtGQlNTeE5RVUZOTEdOQlFVNHNRMEZCY1VJc1VVRkJja0lzUTBGQlNpeEZRVUZ2UXp0QlFVTm9ReXcwUWtGQlNTeFJRVUZSTEUxQlFVMHNVVUZCVGl4RFFVRlNMRU5CUkRSQ096dEJRVWRvUXl3MFFrRkJTU3hQUVVGUExFdEJRVkFzUTBGQlNpeEZRVUZ0UWp0QlFVTm1MSEZEUVVSbE8zbENRVUZ1UWpzN1FVRkpRU3cwUWtGQlNTeFRRVUZUTEUxQlFWUXNRMEZCWjBJc1EwRkJhRUlzUlVGQmJVSXNRMEZCYmtJc1RVRkJNRUlzUzBGQk1VSXNSVUZCYVVNN08wRkJSV3BETEd0RFFVRk5MRkZCUVU0c1NVRkJhMElzVDBGQlR5eExRVUZRTEVOQlFXeENMRU5CUm1sRE8zbENRVUZ5UXp0eFFrRlFTanRwUWtGRVNqdGhRVVJLT3p0QlFXbENRU3h4UWtGQlV5eFBRVUZVTEVOQlFXbENMRU5CUVdwQ0xFVkJRVzlDTzBGQlEyaENMSFZDUVVGUExGRkJRVkVzUTBGQlVpeExRVUZqTEZGQlFWRXNRMEZCVWl4RFFVRmtMRWxCUVRSQ0xGTkJRVk1zUTBGQlZDeERRVUUxUWl4SlFVRXlReXhUUVVGVExFTkJRVlFzUTBGQk0wTXNRMEZFVXp0aFFVRndRanM3UVVGSlFTeHhRa0ZCVXl4VlFVRlVMRU5CUVc5Q0xFTkJRWEJDTEVWQlFYVkNPMEZCUTI1Q0xIVkNRVUZQTEU5QlFVOHNRMEZCVUN4TFFVRmhMRkZCUVdJc1NVRkJlVUlzVVVGQlVTeERRVUZTTEVOQlFYcENMRWxCUVhWRExGRkJRVkVzUTBGQlVpeERRVUYyUXl4RFFVUlpPMkZCUVhaQ096dEJRVWxCTEhGQ1FVRlRMSGRDUVVGVUxFTkJRV3RETEVsQlFXeERMRVZCUVhkRE8wRkJRM0JETEc5Q1FVRkpMRTFCUVUwc1NVRkJTU3hMUVVGS0xFVkJRVTRzUTBGRVowTTdPMEZCUjNCRExHOUNRVUZKTEVsQlFVb3NSMEZCVnl4blJFRkJXQ3hEUVVodlF6dEJRVWx3UXl4dlFrRkJTU3hQUVVGS0xFZEJRV01zT0VOQlExWXNjVVJCUkZVc1IwRkZWaXhSUVVaVkxFZEJSMVlzV1VGQldTeExRVUZMTEdGQlFVd3NRMEZJUml4SFFVbFdMRXRCU2xVc1IwRkxWaXgzUWtGTVZTeEhRVTFXTEZsQlFWa3NTMEZCU3l4WFFVRk1MRU5CVGtZc1EwRktjMEk3UVVGWGFFTXNkVUpCUTBFc2QwUkJSRUVzUTBGWVowTTdRVUZoY0VNc2IwSkJRVWtzWVVGQlNpeEhRVUZ2UWl4TFFVRkxMR0ZCUVV3c1EwRmlaMEk3UVVGamNFTXNiMEpCUVVrc1YwRkJTaXhIUVVGclFpeExRVUZMTEZkQlFVd3NRMEZrYTBJN08wRkJaMEp3UXl4MVFrRkJUeXhIUVVGUUxFTkJhRUp2UXp0aFFVRjRRenM3UVVGdFFrRXNjVUpCUVZNc1YwRkJWQ3hEUVVGeFFpeEhRVUZ5UWl4RlFVRXdRanRCUVVOMFFpeHZRa0ZCU1R0QlFVTkJMREpDUVVGUExFdEJRVXNzVTBGQlRDeERRVUZsTEVkQlFXWXNSVUZCYjBJc1NVRkJjRUlzUlVGQk1FSXNUVUZCTVVJc1EwRkJVQ3hEUVVSQk8ybENRVUZLTEVOQlJVVXNUMEZCVHl4RFFVRlFMRVZCUVZVN1FVRkRVaXd5UWtGQlR5eFBRVUZQTEVkQlFWQXNRMEZCVUN4RFFVUlJPMmxDUVVGV08yRkJTRTQ3VTBGdVNWVXNSVUV5U1ZJc1JVRkJReXh4UWtGQmIwSXNSVUZCY0VJc1JVRkJkVUlzY1VKQlFXOUNMRVZCUVhCQ0xFVkJRWFZDTEhGQ1FVRnZRaXhGUVVGd1FpeEZRVUYxUWl4eFFrRkJiMElzUlVGQmNFSXNSVUZCZFVJc2MwSkJRWEZDTEVWQlFYSkNMRVZCUVhkQ0xIRkNRVUZ2UWl4RlFVRndRaXhGUVVGMVFpeHhRa0ZCYjBJc1JVRkJjRUlzUlVGQmRVSXNjMEpCUVhGQ0xFVkJRWEpDTEVWQlFYZENMRFJDUVVFeVFpeEZRVUV6UWl4RlFVRTRRaXhyUWtGQmFVSXNSVUZCYWtJc1JVRkJiMElzWTBGQllTeEZRVUZpTEVWQk0wbDBUeXhEUVVGSUxFVkJNa2t5VUN4SlFVRkhMRU5CUVVNc1ZVRkJVeXhQUVVGVUxFVkJRV2xDTEUxQlFXcENMRVZCUVhkQ0xFOUJRWGhDTEVWQlFXZERPMEZCUTNKVExIbENRVVJ4VXpzN1FVRkhjbE1zWjBKQlFVa3NVVUZCVVN4UlFVRlJMR1ZCUVZJc1EwRkJVaXhEUVVocFV6czdRVUZMY2xNc1owSkJRVWtzWlVGQlpTeHpRMEZCWml4RFFVeHBVenRCUVUxeVV5eG5Ra0ZCU1N4aFFVRmhMRTlCUVdJc1EwRk9hVk03TzBGQlVYSlRMRzFDUVVGUExFOUJRVkFzUjBGQmFVSXNVVUZCYWtJc1EwRlNjVk03TzBGQlZYSlRMSEZDUVVGVExGRkJRVlFzUTBGQmEwSXNSMEZCYkVJc1JVRkJkVUlzUzBGQmRrSXNSVUZCT0VJN1FVRkRNVUlzYjBKQlFVa3NRMEZCUXl4SFFVRkVMRVZCUVUwN1FVRkRUaXd5UWtGQlR5eExRVUZRTEVOQlJFMDdhVUpCUVZZN08wRkJTVUVzYjBKQlFVa3NUMEZCVHl4RFFVRkZMRTFCUVUwc1kwRkJUaXhEUVVGeFFpeEpRVUZ5UWl4RFFVRkdMRU5CVEdVN08wRkJUekZDTEc5Q1FVRkpMRmRCUVZjc1RVRkJUU3hIUVVGT0xFVkJRVmNzV1VGQldDeERRVUZZTEVOQlVITkNPMEZCVVRGQ0xHOUNRVUZKTEZWQlFWVXNTVUZCVml4RFFWSnpRanM3UVVGVk1VSXNiMEpCUVVrc1YwRkJWeXhKUVVGWUxFTkJRV2RDTEZOQlFWTXNRMEZCVkN4RFFVRm9RaXhEUVVGS0xFVkJRV3RETzBGQlF6bENMRGhDUVVGVkxFdEJRVllzUTBGRU9FSTdhVUpCUVd4RE96dEJRVWxCTEc5Q1FVRkpMRTlCUVVvc1JVRkJZU3hKUVVGaUxFVkJRVzFDTEVsQlFXNUNMRVZCUVhsQ0xFTkJRWHBDTEVOQlpEQkNPenRCUVdkQ01VSXNjVUpCUVVzc1NVRkJTU3hEUVVGS0xFVkJRVThzU1VGQlNTeFRRVUZUTEUxQlFWUXNSVUZCYVVJc1IwRkJha01zUlVGQmMwTTdRVUZEYkVNc01rSkJRVThzVTBGQlV5eERRVUZVTEVOQlFWQXNRMEZFYTBNN08wRkJSMnhETEhkQ1FVRkpMRU5CUVVNc1NVRkJSQ3hGUVVGUE8wRkJRMUFzYVVOQlJFODdjVUpCUVZnN08wRkJTVUVzTWtKQlFVOHNTMEZCU3l4TlFVRk1MRU5CUVZrc1EwRkJXaXhEUVVGUUxFTkJVR3RET3p0QlFWTnNReXgzUWtGQlNTeERRVUZETEU5QlFVUXNSVUZCVlR0QlFVTldMR3REUVVGVkxFbEJRVllzUTBGRVZUdHhRa0ZCWkN4TlFVVlBMRWxCUVVrc1UwRkJVeXhIUVVGVUxFVkJRV003UVVGRGNrSXNhME5CUVZVc1YwRkJWeXhGUVVGWUxFTkJSRmM3UVVGRmNrSXNaME5CUVZFc1NVRkJVaXhEUVVGaExFdEJRVXNzVTBGQlRDeERRVUZsTEVOQlFXWXNSVUZCYTBJc1MwRkJTeXhOUVVGTUxFTkJRUzlDTEVWQlJuRkNPM0ZDUVVGc1FpeE5RVWRCTEVsQlFVa3NVMEZCVXl4SFFVRlVMRWxCUVdkQ0xFbEJRV2hDTEVWQlFYTkNPMEZCUXpkQ0xEaENRVUZOTEVWQlFVNHNSMEZCVnl4TFFVRkxMRk5CUVV3c1EwRkJaU3hEUVVGbUxFVkJRV3RDTEV0QlFVc3NUVUZCVEN4RFFVRTNRaXhEUVVRMlFqdHhRa0ZCTVVJN2FVSkJaRmc3TzBGQmJVSkJMRzlDUVVGSkxFOUJRVW9zUlVGQllUdEJRVU5VTEhkQ1FVRkpMRTFCUVUwc1UwRkJUaXhGUVVGcFFqdEJRVU5xUWl4blEwRkJVU3hKUVVGU0xFTkJRV0VzVFVGQlRTeFRRVUZPTEVOQlFXSXNRMEZFYVVJN2NVSkJRWEpDT3p0QlFVbEJMREJDUVVGTkxGTkJRVTRzUjBGQmEwSXNVVUZCVVN4SlFVRlNMRU5CUVdFc1IwRkJZaXhEUVVGc1FpeERRVXhUTzJsQ1FVRmlPenRCUVZGQkxIVkNRVUZQTEUxQlFVMHNVMEZCVGl4SFFVRnJRaXhQUVVGc1FpeEhRVUUwUWl4UlFVRlJMRmRCUVZJc1JVRkJOVUlzUTBFelEyMUNPMkZCUVRsQ08xTkJWbkZSTEVWQmQwUnVVU3hGUVVGRExHbENRVUZuUWl4RFFVRm9RaXhGUVhoRWFWRXNRMEZCU0N4RlFYZEVNVThzU1VGQlJ5eERRVUZETEZWQlFWTXNUMEZCVkN4RlFVRnBRaXhOUVVGcVFpeEZRVUYzUWl4UFFVRjRRaXhGUVVGblF6dEJRVU16UkN4blFrRkJTU3hWUVVGVkxGRkJRVkVzV1VGQlVpeERRVUZXTEVOQlJIVkVPMEZCUlRORUxHZENRVUZKTEZWQlFWVXNVVUZCVVN4WlFVRlNMRU5CUVZZc1EwRkdkVVE3UVVGSE0wUXNaMEpCUVVrc1YwRkJWeXhSUVVGUkxHRkJRVklzUTBGQldDeERRVWgxUkR0QlFVa3pSQ3huUWtGQlNTeFZRVUZWTEZGQlFWRXNXVUZCVWl4RFFVRldMRU5CU25WRU96dEJRVTB6UkN4dFFrRkJUeXhQUVVGUUxFZEJRV2xDTEZkQlFXcENMRU5CVGpKRU96dEJRVkV6UkN4eFFrRkJVeXhYUVVGVUxFTkJRWEZDTEVOQlFYSkNMRVZCUVhkQ0xFTkJRWGhDTEVWQlFUSkNPMEZCUTNaQ0xHOUNRVUZKTEZsQlFWa3NRMEZCV2l4RFFVUnRRanRCUVVWMlFpeHZRa0ZCU1N4WlFVRlpMRU5CUVZvc1EwRkdiVUk3TzBGQlNYWkNMRzlDUVVGSkxGRkJRVkVzUTBGQlVpeERRVUZLTEVWQlFXZENPMEZCUTFvc1owTkJRVmtzV1VGQldTeERRVUZhTEVWQlFXVXNRMEZCWml4RFFVRmFMRU5CUkZrN2FVSkJRV2hDT3p0QlFVbEJMRzlDUVVGSkxGRkJRVkVzUTBGQlVpeERRVUZLTEVWQlFXZENPMEZCUTFvc1owTkJRVmtzV1VGQldTeERRVUZhTEVWQlFXVXNTVUZCWml4RFFVRmFMRU5CUkZrN2FVSkJRV2hDT3p0QlFVbEJMSFZDUVVGUE8wRkJRMGdzZFVKQlFVY3NVMEZCU0R0QlFVTkJMSFZDUVVGSExGTkJRVWc3YVVKQlJrb3NRMEZhZFVJN1lVRkJNMEk3TzBGQmEwSkJMSEZDUVVGVExGZEJRVlFzUTBGQmNVSXNTMEZCY2tJc1JVRkJORUlzVVVGQk5VSXNSVUZCYzBNN1FVRkRiRU1zYjBKQlFVa3NaMEpCUVdkQ0xFMUJRVTBzUzBGQlRpeERRVVJqT3p0QlFVZHNReXh2UWtGQlNTeERRVUZETEdGQlFVUXNSVUZCWjBJN1FVRkRhRUlzYjBOQlFXZENMRTFCUVUwc1MwRkJUaXhIUVVGakxFMUJRVTBzVFVGQlRpeERRVUZoTEZGQlFXSXNRMEZCWkN4RFFVUkJPMmxDUVVGd1FqczdRVUZKUVN4dlFrRkJTU3hGUVVGRkxGRkJRVkVzWVVGQlVpeExRVU5GTEZGQlFWRXNZVUZCVWl4RFFVUkdMRWxCUlVVc1UwRkJVeXhoUVVGVUxFTkJSa1lzUTBGQlJpeEZRVVU0UWp0QlFVTTVRaXd3UWtGQlRTeEpRVUZKTEV0QlFVb3NRMEZCVlN4dFEwRkJWaXhEUVVGT0xFTkJSRGhDTzJsQ1FVWnNRenM3UVVGTlFTeDFRa0ZCVHl4aFFVRlFMRU5CWW10RE8yRkJRWFJETzFOQk1VSXlRaXhGUVRCRGVrSXNSVUZCUXl4alFVRmhMRVZCUVdJc1JVRkJaMElzWTBGQllTeEZRVUZpTEVWQlFXZENMR05CUVdFc1JVRkJZaXhGUVVGblFpeGxRVUZqTEVWQlFXUXNSVUV4UTNwQ0xFTkJRVWdzUlVFd1F5dERMRWxCUVVjc1EwRkJReXhWUVVGVExFOUJRVlFzUlVGQmFVSXNUVUZCYWtJc1JVRkJkMElzVDBGQmVFSXNSVUZCWjBNN1FVRkRNVWNzYlVKQlFVOHNUMEZCVUN4SFFVRnBRaXhQUVVGcVFpeERRVVF3UnpzN1FVRkhNVWNzY1VKQlFWTXNUMEZCVkN4RFFVRnBRaXhEUVVGcVFpeEZRVUZ2UWp0QlFVTm9RaXgxUWtGQlR5eExRVUZMTEVWQlFVVXNTVUZCUml4TFFVRlhMRTlCUVZnc1EwRkVTVHRoUVVGd1FqdFRRVWd3UlN4RlFVOTRSU3hGUVZCMVJTeERRVUZJTEVWQlQyaEZMRWxCUVVjc1EwRkJReXhWUVVGVExFOUJRVlFzUlVGQmFVSXNUVUZCYWtJc1JVRkJkMElzVDBGQmVFSXNSVUZCWjBNN1FVRkRNVU1zYlVKQlFVOHNUMEZCVUN4SFFVRnBRaXhOUVVGcVFpeERRVVF3UXpzN1FVRkhNVU1zY1VKQlFWTXNUVUZCVkN4RFFVRm5RaXhKUVVGb1FpeEZRVUZ6UWp0QlFVTnNRaXgxUWtGQlR5eFRRVU5LTEU5QlFVOHNTMEZCU3l4SlFVRk1MRXRCUVdNc1ZVRkJja0lzU1VGQmJVTXNRMEZCUXl4TFFVRkxMR05CUVV3c1EwRkJiMElzVFVGQmNFSXNRMEZCUkN4SlFVTnVReXhQUVVGUExFdEJRVXNzVFVGQlRDeExRVUZuUWl4VlFVRjJRaXhKUVVGeFF5eERRVUZETEV0QlFVc3NZMEZCVEN4RFFVRnZRaXhSUVVGd1FpeERRVUZFTEVOQlJtcERMRU5CUkZjN1lVRkJkRUk3VTBGSVZTeEZRVk5TTEVWQlZFOHNRMEZCU0N4RlFWTkJMRWxCUVVjc1EwRkJReXhWUVVGVExFOUJRVlFzUlVGQmFVSXNUVUZCYWtJc1JVRkJkMElzVDBGQmVFSXNSVUZCWjBNN1FVRkRNVU1zWjBKQlFVa3NWVUZCVlN4UlFVRlJMRmRCUVZJc1EwRkJWaXhEUVVSelF6czdRVUZITVVNc2JVSkJRVThzVDBGQlVDeEhRVUZwUWl4aFFVRnFRaXhEUVVnd1F6czdRVUZMTVVNc2NVSkJRVk1zWVVGQlZDeERRVUYxUWl4RFFVRjJRaXhGUVVFd1FqdEJRVU4wUWl4MVFrRkJUeXhMUVVGTExFVkJRVVVzU1VGQlJpeExRVUZYTEdGQlFWZ3NTVUZCTkVJc1JVRkJSU3hQUVVGR0xFdEJRV01zVDBGQlpDeERRVVJzUWp0aFFVRXhRanRUUVV4VkxFVkJVMUlzUlVGQlF5eGhRVUZaTEVWQlFWb3NSVUZVVFN4RFFVRklMRVZCVTJNc1NVRkJSeXhEUVVGRExGVkJRVk1zVDBGQlZDeEZRVUZwUWl4TlFVRnFRaXhGUVVGM1FpeFBRVUY0UWl4RlFVRm5RenRCUVVONFJDeG5Ra0ZCU1N4VlFVRlZMRkZCUVZFc1YwRkJVaXhEUVVGV0xFTkJSRzlFT3p0QlFVZDRSQ3h0UWtGQlR5eFBRVUZRTEVkQlFXbENMR0ZCUVdwQ0xFTkJTSGRFT3p0QlFVdDRSQ3h4UWtGQlV5eGhRVUZVTEVOQlFYVkNMRU5CUVhaQ0xFVkJRVEJDTzBGQlEzUkNMSFZDUVVGUExFdEJRVXNzUlVGQlJTeEpRVUZHTEV0QlFWY3NZVUZCV0N4SlFVRTBRaXhGUVVGRkxFOUJRVVlzUzBGQll5eFBRVUZrTEVOQlJHeENPMkZCUVRGQ08xTkJUSGRDTEVWQlUzUkNMRVZCUVVNc1lVRkJXU3hGUVVGYUxFVkJWRzlDTEVOQlFVZ3NSVUZUUVN4SlFVRkhMRU5CUVVNc1ZVRkJVeXhQUVVGVUxFVkJRV2xDTEUxQlFXcENMRVZCUVhkQ0xFOUJRWGhDTEVWQlFXZERPMEZCUTNoRUxHMUNRVUZQTEU5QlFWQXNSMEZCYVVJc1VVRkJha0lzUTBGRWQwUTdPMEZCUjNoRUxIRkNRVUZUTEZGQlFWUXNRMEZCYTBJc1EwRkJiRUlzUlVGQmNVSTdRVUZEYWtJc2RVSkJRVThzUzBGQlN5eEZRVUZGTEVsQlFVWXNTMEZCVnl4UlFVRllMRU5CUkVzN1lVRkJja0k3VTBGSWQwSXNSVUZQZEVJc1JVRlFjVUlzUTBGQlNDeEZRVTlrTEVsQlFVY3NRMEZCUXl4VlFVRlRMRTlCUVZRc1JVRkJhVUlzVFVGQmFrSXNSVUZCZDBJc1QwRkJlRUlzUlVGQlowTTdRVUZETVVNc2JVSkJRVThzVDBGQlVDeEhRVUZwUWl4SFFVRnFRaXhEUVVRd1F6dFRRVUZvUXl4RlFVZFNMRVZCU0U4c1EwRkJTQ3hGUVVkQkxFbEJRVWNzUTBGQlF5eFZRVUZUTEU5QlFWUXNSVUZCYVVJc1RVRkJha0lzUlVGQmQwSXNUMEZCZUVJc1JVRkJaME03UVVGRE1VTXNaMEpCUVVrc1ZVRkJWU3hSUVVGUkxGZEJRVklzUTBGQlZpeERRVVJ6UXp0QlFVVXhReXhuUWtGQlNTeFZRVUZWTEZGQlFWRXNXVUZCVWl4RFFVRldMRU5CUm5ORE8wRkJSekZETEdkQ1FVRkpMRmRCUVZjc1VVRkJVU3hoUVVGU0xFTkJRVmdzUTBGSWMwTTdRVUZKTVVNc1owSkJRVWtzVlVGQlZTeFJRVUZSTEZsQlFWSXNRMEZCVml4RFFVcHpRenRCUVVzeFF5eG5Ra0ZCU1N4VlFVRlZMRkZCUVZFc1dVRkJVaXhEUVVGV0xFTkJUSE5ET3p0QlFVOHhReXh0UWtGQlR5eFBRVUZRTEVkQlFXbENMRmRCUVdwQ0xFTkJVREJET3p0QlFWTXhReXhuUWtGQlNTeGxRVUZsTEVWQlFXWXNRMEZVYzBNN1FVRlZNVU1zWjBKQlFVa3NZVUZCWVN4RlFVRmlMRU5CVm5ORE96dEJRVmt4UXl4eFFrRkJVeXhYUVVGVUxFTkJRWEZDTEU5QlFYSkNMRVZCUVRoQ0xGVkJRVGxDTEVWQlFUQkRMRkZCUVRGRExFVkJRVzlFTEVkQlFYQkVMRVZCUVhsRUxGTkJRWHBFTEVWQlFXOUZPMEZCUTJoRkxIRkNRVUZMTEU5QlFVd3NSMEZCWlN4UFFVRm1MRU5CUkdkRk8wRkJSV2hGTEhGQ1FVRkxMRlZCUVV3c1IwRkJhMElzWTBGQll5eFpRVUZrTEVOQlJqaERPMEZCUjJoRkxIRkNRVUZMTEZGQlFVd3NSMEZCWjBJc1dVRkJXU3hWUVVGYUxFTkJTR2RFTzBGQlNXaEZMSEZDUVVGTExFZEJRVXdzUjBGQlZ5eFBRVUZQTEVsQlFWQXNSMEZCWXl4UFFVRlBMRWRCUVZBc1EwRkJaQ3hIUVVFMFFpeFRRVUUxUWl4RFFVcHhSRHRCUVV0b1JTeHhRa0ZCU3l4VFFVRk1MRWRCUVdsQ0xFOUJRVkVzVTBGQlVDeExRVUZ4UWl4UlFVRnlRaXhIUVVGcFF5eFRRVUZzUXl4SFFVRTRReXhKUVVFNVF5eERRVXdyUXpzN1FVRlBhRVVzYjBKQlFVa3NVVUZCVVN4UlFVRkRMRWxCUVZrc1UwRkJVeXhOUVVGVUxFbEJRVzlDTEVOQlFXcERMRU5CVUc5RU8wRkJVV2hGTEc5Q1FVRkpMR05CUVdNc1EwRkJaQ3hEUVZJMFJEdEJRVk5vUlN4dlFrRkJTU3hoUVVGaExFdEJRV0lzUTBGVU5FUTdRVUZWYUVVc2IwSkJRVWtzV1VGQldTeExRVUZhTEVOQlZqUkVPMEZCVjJoRkxHOUNRVUZKTEd0Q1FVRnJRaXhMUVVGc1FpeERRVmcwUkR0QlFWbG9SU3h2UWtGQlNTeExRVUZLTEVOQldtZEZPenRCUVdOb1JTeHhRa0ZCU3l4SlFVRkpMRkZCUVVvc1NVRkJaMElzVlVGQmNrSXNSVUZCYVVNN1FVRkROMElzZDBKQlFVa3NWMEZCVnl4alFVRllMRU5CUVRCQ0xGRkJRVEZDTEVOQlFVb3NSVUZCZVVNN1FVRkRja01zTkVKQlFVa3NWMEZCVnl4WFFVRlhMRkZCUVZnc1EwRkJXQ3hEUVVScFF6dEJRVVZ5UXl3MFFrRkJTU3hSUVVGUkxGRkJRVklzUzBGQmNVSXNVMEZCVXl4TlFVRlVMRVZCUVdsQ08wRkJRM1JETEdkRFFVRkpMRU5CUVVNc1MwRkJSQ3hGUVVGUk8wRkJRMUlzZDBOQlFWRXNSVUZCVWl4RFFVUlJPelpDUVVGYU96dEJRVWxCTEd0RFFVRk5MRkZCUVU0c1NVRkJhMElzVVVGQmJFSXNRMEZNYzBNN2VVSkJRVEZETzNGQ1FVWktPMmxDUVVSS096dEJRV0ZCTEhGQ1FVRkxMRWxCUVVrc1NVRkJTU3hEUVVGS0xFVkJRVThzU1VGQlNTeExRVUZLTEVWQlFWY3NSMEZCTTBJc1JVRkJaME03UVVGRE5VSXNkMEpCUVVrc1VVRkJVU3hUUVVGVExFTkJRVlFzUTBGQlVpeERRVVIzUWp0QlFVVTFRaXgzUWtGQlNTeFJRVUZSTEV0QlFWSXNRMEZCU2l4RlFVRnZRanRCUVVOb1FpeDFRMEZCWlN4TlFVRk5MRXRCUVU0c1NVRkJaU3hEUVVGbUxFTkJSRU03TzBGQlIyaENMRFJDUVVGSkxFTkJRVU1zVlVGQlJDeEpRVUZsTEUxQlFVMHNWVUZCVGl4RlFVRnJRanRCUVVOcVF5eDVRMEZCWVN4SlFVRmlMRU5CUkdsRE8zbENRVUZ5UXpzN1FVRkpRU3cwUWtGQlNTeERRVUZETEZOQlFVUXNTVUZCWXl4TlFVRk5MRk5CUVU0c1JVRkJhVUk3UVVGREwwSXNkME5CUVZrc1NVRkJXaXhEUVVRclFqdDVRa0ZCYmtNN08wRkJTVUVzTkVKQlFVa3NRMEZCUXl4bFFVRkVMRXRCUVhGQ0xFMUJRVTBzUzBGQlRpeEpRVUZsTEUxQlFVMHNaVUZCVGl4RFFVRndReXhGUVVFMFJEdEJRVU0xUkN3NFEwRkJhMElzU1VGQmJFSXNRMEZFTkVRN2VVSkJRV2hGTzNGQ1FWaEtMRTFCWTA4c1NVRkJTU3hEUVVGRExGVkJRVVFzU1VGQlpTeFRRVUZUTEV0QlFWUXNRMEZCWml4RlFVRm5RenRCUVVOMlF5dzBRa0ZCU1N4UFFVRlBMRTFCUVUwc1QwRkJUaXhMUVVGclFpeFZRVUY2UWl4RlFVRnhRenRCUVVOeVF5eDVRMEZCWVN4SlFVRmlMRU5CUkhGRE8zbENRVUY2UXp0eFFrRkVSeXhOUVVsQkxFbEJRVWtzUTBGQlF5eFRRVUZFTEVsQlFXTXNVVUZCVVN4TFFVRlNMRU5CUVdRc1JVRkJPRUk3UVVGRGNrTXNiME5CUVZrc1NVRkJXaXhEUVVSeFF6dHhRa0ZCYkVNN2FVSkJjRUpZT3p0QlFYbENRU3h4UWtGQlN5eExRVUZNTEVkQlFXRXNVVUZCVVN4WFFVRlNMRU5CY0VSdFJEdEJRWEZFYUVVc2NVSkJRVXNzVlVGQlRDeEhRVUZyUWl4VlFVRnNRaXhEUVhKRVowVTdRVUZ6UkdoRkxIRkNRVUZMTEZOQlFVd3NSMEZCYVVJc1UwRkJha0lzUTBGMFJHZEZPMEZCZFVSb1JTeHhRa0ZCU3l4TFFVRk1MRWRCUVdFc1MwRkJZaXhEUVhaRVowVTdRVUYzUkdoRkxIRkNRVUZMTEdWQlFVd3NSMEZCZFVJc1pVRkJka0lzUTBGNFJHZEZPMkZCUVhCRk96dEJRVEpFUVN4M1FrRkJXU3hUUVVGYUxFTkJRWE5DTEU5QlFYUkNMRWRCUVdkRExFOUJRV2hETEVOQmRrVXdRenRCUVhkRk1VTXNkMEpCUVZrc1UwRkJXaXhEUVVGelFpeEpRVUYwUWl4SFFVRTJRaXhoUVVFM1FpeERRWGhGTUVNN1UwRkJhRU1zUlVFd1JWSXNSVUZCUXl4alFVRmhMRVZCUVdJc1JVRkJaMElzWTBGQllTeEZRVUZpTEVWQlFXZENMR05CUVdFc1JVRkJZaXhGUVVGblFpeGxRVUZqTEVWQlFXUXNSVUZCYVVJc1lVRkJXU3hGUVVGYUxFVkJNVVV6UkN4RFFVRklMRVZCTUVVclJTeEpRVUZITEVOQlFVTXNWVUZCVXl4UFFVRlVMRVZCUVdsQ0xFMUJRV3BDTEVWQlFYZENMRTlCUVhoQ0xFVkJRV2RETzBGQlEzcElMR2RDUVVGSkxGVkJRVlVzVVVGQlVTeFhRVUZTTEVOQlFWWXNRMEZFY1VnN08wRkJSM3BJTEhsQ1FVRmhMRWxCUVdJc1IwRkJiMElzUTBGQmNFSXNRMEZJZVVnN1FVRkpla2dzZVVKQlFXRXNTMEZCWWl4SFFVRnhRaXhEUVVGeVFpeERRVXA1U0R0QlFVdDZTQ3g1UWtGQllTeExRVUZpTEVkQlFYRkNMRU5CUVhKQ0xFTkJUSGxJTzBGQlRYcElMSGxDUVVGaExFMUJRV0lzUjBGQmMwSXNRMEZCZEVJc1EwRk9lVWc3UVVGUGVrZ3NlVUpCUVdFc1MwRkJZaXhIUVVGeFFpeERRVUZ5UWl4RFFWQjVTRHRCUVZGNlNDeDVRa0ZCWVN4TFFVRmlMRWRCUVhGQ0xFTkJRWEpDTEVOQlVubElPMEZCVTNwSUxIbENRVUZoTEUxQlFXSXNSMEZCYzBJc1EwRkJkRUlzUTBGVWVVZzdRVUZWZWtnc2VVSkJRV0VzVFVGQllpeEhRVUZ6UWl4RFFVRjBRaXhEUVZaNVNEdEJRVmQ2U0N4NVFrRkJZU3hMUVVGaUxFZEJRWEZDTEVOQlFYSkNMRU5CV0hsSU96dEJRV0Y2U0N4dFFrRkJUeXhQUVVGUUxFZEJRV2xDTEZsQlFXcENMRU5CWW5sSU96dEJRV1Y2U0N4eFFrRkJVeXhaUVVGVUxFTkJRWE5DTEVsQlFYUkNMRVZCUVRSQ0xFdEJRVFZDTEVWQlFXMURMRXRCUVc1RExFVkJRVEJETzBGQlEzUkRMSEZDUVVGTExFbEJRVXdzUjBGQldTeFBRVUZQTEVsQlFWQXNRMEZCV2l4RFFVUnpRenRCUVVWMFF5eHhRa0ZCU3l4TFFVRk1MRWRCUVdFc1MwRkJZaXhEUVVaelF6dEJRVWQwUXl4eFFrRkJTeXhMUVVGTUxFZEJRV0VzUzBGQllpeERRVWh6UXp0aFFVRXhRenM3UVVGTlFTeDVRa0ZCWVN4VFFVRmlMRU5CUVhWQ0xFOUJRWFpDTEVkQlFXbERMRTlCUVdwRExFTkJja0o1U0R0QlFYTkNla2dzZVVKQlFXRXNVMEZCWWl4RFFVRjFRaXhKUVVGMlFpeEhRVUU0UWl4alFVRTVRaXhEUVhSQ2VVZzdVMEZCYUVNc1JVRjNRblpHTEVWQlFVTXNZVUZCV1N4RlFVRmFMRVZCZUVKeFJpeERRVUZJTEVWQmQwSnFSU3hKUVVGSExFTkJRVU1zVlVGQlV5eFBRVUZVTEVWQlFXbENMRTFCUVdwQ0xFVkJRWGRDTEU5QlFYaENMRVZCUVdkRE8wRkJRM2hFTEdkQ1FVRkpMRlZCUVZVc1VVRkJVU3hYUVVGU0xFTkJRVllzUTBGRWIwUTdPMEZCUjNoRUxHMUNRVUZQTEU5QlFWQXNSMEZCYVVJc1YwRkJha0lzUTBGSWQwUTdPMEZCUzNoRUxIRkNRVUZUTEZkQlFWUXNRMEZCY1VJc1NVRkJja0lzUlVGQk1rSTdRVUZEZGtJc2NVSkJRVXNzU1VGQlRDeEhRVUZaTEU5QlFVOHNTVUZCVUN4RFFVRmFMRU5CUkhWQ08yRkJRVE5DT3p0QlFVbEJMSGRDUVVGWkxGTkJRVm9zUTBGQmMwSXNUMEZCZEVJc1IwRkJaME1zVDBGQmFFTXNRMEZVZDBRN1FVRlZlRVFzZDBKQlFWa3NVMEZCV2l4RFFVRnpRaXhKUVVGMFFpeEhRVUUyUWl4aFFVRTNRaXhEUVZaM1JEdFRRVUZvUXl4RlFWbDBRaXhGUVVGRExHRkJRVmtzUlVGQldpeEZRVnB2UWl4RFFVRklMRVZCV1VFc1NVRkJSeXhEUVVGRExGVkJRVk1zVDBGQlZDeEZRVUZwUWl4TlFVRnFRaXhGUVVGM1FpeFBRVUY0UWl4RlFVRm5RenRCUVVONFJDeG5Ra0ZCU1N4WFFVRlhMRkZCUVZFc1YwRkJVaXhEUVVGWUxFTkJSRzlFTzBGQlJYaEVMR2RDUVVGSkxGTkJRVk1zVVVGQlVTeHRRa0ZCVWl4RFFVRlVMRU5CUm05RU96dEJRVWw0UkN4dFFrRkJUeXhQUVVGUUxFZEJRV2xDTEZOQlFXcENMRU5CU25kRU96dEJRVTE0UkN4eFFrRkJVeXhUUVVGVUxFTkJRVzFDTEVOQlFXNUNMRVZCUVhOQ0xFTkJRWFJDTEVWQlFYbENPMEZCUTNKQ0xHOUNRVUZKTEVsQlFVb3NRMEZFY1VJN08wRkJSM0pDTEhGQ1FVRkxMRWxCUVVrc1NVRkJTaXhKUVVGWkxFTkJRV3BDTEVWQlFXOUNPMEZCUTJoQ0xIZENRVUZKTEVWQlFVVXNVVUZCVVN4RFFVRlNMRU5CUVVZc1JVRkJZenRCUVVOa0xDdENRVUZQTEZGQlFWRXNSVUZCVWl4RFFVUlBPMEZCUldRc05rSkJRVXNzU1VGQlRDeEpRVUZoTEZOQlFXSXNRMEZHWXp0eFFrRkJiRUk3TzBGQlMwRXNkMEpCUVVrc1UwRkJVeXhGUVVGRkxFbEJRVVlzUTBGQlZDeERRVTVaTzBGQlQyaENMSGRDUVVGSkxGTkJRVk1zUlVGQlJTeEpRVUZHTEVOQlFWUXNRMEZRV1RzN1FVRlRhRUlzZDBKQlFVa3NWMEZCVnl4TlFVRllMRVZCUVcxQ08wRkJRMjVDTEdsRFFVUnRRanR4UWtGQmRrSXNUVUZGVHl4SlFVRkpMRk5CUVZNc1RVRkJWQ3hMUVVGdlFpeFRRVUZUTEUxQlFWUXNRMEZCY0VJc1JVRkJjME03UVVGRE4wTXNORUpCUVVrc1lVRkJZU3hOUVVGaUxFMUJRWGxDTEdGQlFXRXNUVUZCWWl4RFFVRjZRaXhGUVVFclF6dEJRVU12UXl4dFEwRkJUeXhSUVVGUkxFVkJRVklzUTBGRWQwTTdRVUZGTDBNc2FVTkJRVXNzU1VGQlRDeEpRVUZoTEUxQlFXSXNRMEZHSzBNN2VVSkJRVzVFTEUxQlIwOHNTVUZCU1N4UFFVRlBMRTFCUVZBc1EwRkJTaXhGUVVGdlFqdEJRVU4wUWl4dFEwRkJUeXhSUVVGUkxFVkJRVklzUTBGRVpUdEJRVVYwUWl4cFEwRkJTeXhKUVVGTUxFbEJRV0VzVFVGQllpeERRVVp6UWp0NVFrRkJjRUlzVFVGSFFUdEJRVU5JTEdkRFFVRkpMR0ZCUVdFc1ZVRkJWU3hOUVVGV0xFVkJRV3RDTEUxQlFXeENMRU5CUVdJc1EwRkVSRHRCUVVWSUxHZERRVUZKTEZWQlFVb3NSVUZCWjBJN1FVRkRXaXgxUTBGQlR5eFJRVUZSTEVWQlFWSXNRMEZFU3p0QlFVVmFMSEZEUVVGTExFbEJRVXdzU1VGQllTeFZRVUZpTEVOQlJsazdOa0pCUVdoQ08zbENRVXhITzNGQ1FVcEtMRTFCWTBFN1FVRkRTQ3dyUWtGQlR5eFJRVUZSTEVWQlFWSXNRMEZFU2p0QlFVVklMRFpDUVVGTExFbEJRVXdzU1VGQllTeE5RVUZpTEVOQlJrYzdjVUpCWkVFN2FVSkJXRmc3TzBGQkswSkJMSEZDUVVGTExFbEJRVWtzU1VGQlNpeEpRVUZaTEVOQlFXcENMRVZCUVc5Q08wRkJRMmhDTEhkQ1FVRkpMRVZCUVVVc1VVRkJVU3hEUVVGU0xFTkJRVVlzUlVGQll6dEJRVU5rTEN0Q1FVRlBMRkZCUVZFc1JVRkJVaXhEUVVSUE8wRkJSV1FzTmtKQlFVc3NTVUZCVEN4SlFVRmhMRVZCUVVVc1NVRkJSaXhEUVVGaUxFTkJSbU03Y1VKQlFXeENPMmxDUVVSS096dEJRVTlCTEhWQ1FVRlBMRWxCUVZBc1EwRjZRM0ZDTzJGQlFYcENPenRCUVRSRFFTeHhRa0ZCVXl4WlFVRlVMRU5CUVhOQ0xFdEJRWFJDTEVWQlFUWkNPMEZCUXpOQ0xHOUNRVUZKTEU5QlFVOHNZMEZCVUN4RlFVRjFRanRCUVVONlFpd3lRa0ZCVHl4UFFVRlBMR05CUVZBc1EwRkJjMElzUzBGQmRFSXNRMEZCVUN4RFFVUjVRanRwUWtGQk0wSXNUVUZGVHl4SlFVRkpMRTFCUVUwc1UwRkJUaXhGUVVGcFFqdEJRVU14UWl3eVFrRkJUeXhOUVVGTkxGTkJRVTRzUTBGRWJVSTdhVUpCUVhKQ0xFMUJSVUVzU1VGQlNTeE5RVUZOTEZkQlFVNHNSVUZCYlVJN1FVRkROVUlzTWtKQlFVOHNUVUZCVFN4WFFVRk9MRU5CUVd0Q0xGTkJRV3hDTEVOQlJIRkNPMmxDUVVGMlFqdGhRVXhVTzFOQmJFUjNRaXhGUVRSRWRFSXNSVUZCUXl4eFFrRkJiMElzUlVGQmNFSXNSVUZCZFVJc1lVRkJXU3hGUVVGYUxFVkJOVVJJTEVOQlFVZ3NSVUUwUkhWQ0xFbEJRVWNzUTBGQlF5eFZRVUZUTEU5QlFWUXNSVUZCYVVJc1RVRkJha0lzUlVGQmQwSXNUMEZCZUVJc1JVRkJaME03UVVGREwwVXNaMEpCUVVrc1ZVRkJWU3hSUVVGUkxGbEJRVklzUTBGQlZpeERRVVF5UlRzN1FVRkhMMFVzWjBKQlFVa3NVMEZCVXl4UlFVRlJMR2xDUVVGU0xFTkJRVlFzUTBGSU1rVTdRVUZKTDBVc1owSkJRVWtzVlVGQlZTeFJRVUZSTEcxQ1FVRlNMRU5CUVZZc1EwRktNa1U3UVVGTEwwVXNaMEpCUVVrc1ZVRkJWU3hSUVVGUkxHMUNRVUZTTEVOQlFWWXNRMEZNTWtVN1FVRk5MMFVzWjBKQlFVa3NWMEZCVnl4UlFVRlJMRzlDUVVGU0xFTkJRVmdzUTBGT01rVTdRVUZQTDBVc1owSkJRVWtzVlVGQlZTeFJRVUZSTEcxQ1FVRlNMRU5CUVZZc1EwRlFNa1U3UVVGUkwwVXNaMEpCUVVrc1kwRkJZeXhSUVVGUkxIVkNRVUZTTEVOQlFXUXNRMEZTTWtVN08wRkJWUzlGTEdkQ1FVRkpMRmxCUVZrc1VVRkJVU3hqUVVGU0xFTkJRVm9zUTBGV01rVTdPMEZCV1M5RkxHMUNRVUZQTEU5QlFWQXNSMEZCYVVJc1NVRkJha0lzUTBGYUswVTdPMEZCWXk5RkxIRkNRVUZUTEVsQlFWUXNRMEZCWXl4RFFVRmtMRVZCUVdsQ0xFTkJRV3BDTEVWQlFXOUNPMEZCUTJoQ0xHOUNRVUZKTEZGQlFWRXNSVUZCUlN4SFFVRkhMRU5CUVVnc1JVRkJWaXhEUVVSWk8wRkJSV2hDTEhGQ1FVRkxMRU5CUVV3c1JVRkJVU3hEUVVGU0xFVkJRVmNzUzBGQldDeEZRVUZyUWl4RFFVRnNRaXhGUVVablFqdEJRVWRvUWl4MVFrRkJUeXhMUVVGUUxFTkJTR2RDTzJGQlFYQkNPenRCUVUxQkxIRkNRVUZUTEVsQlFWUXNRMEZCWXl4RFFVRmtMRVZCUVdsQ0xFTkJRV3BDTEVWQlFXOUNMRXRCUVhCQ0xFVkJRVEpDTEV0QlFUTkNMRVZCUVd0RE8wRkJRemxDTEc5Q1FVRkpMRTFCUVUwc1EwRkJUaXhGUVVGVE8wRkJRMVFzTWtKQlJGTTdhVUpCUVdJN08wRkJTVUVzYjBKQlFVa3NVVUZCVVN4TlFVRk5MRXRCUVU0c1EwRkJVaXhEUVV3d1FqdEJRVTA1UWl4dlFrRkJTU3hoUVVGaExFdEJRV0lzUTBGT01FSTdPMEZCVVRsQ0xHOUNRVUZKTEZGQlFWRXNRMEZCVWl4TFFVRmpMRkZCUVZFc1EwRkJVaXhEUVVGa0xFVkJRVEJDTzBGQlF6RkNMREpDUVVGUExFTkJRVkFzUlVGQlZTeERRVUZXTEVWQlFXRXNTMEZCWWl4RlFVRnZRaXhMUVVGd1FpeEZRVVF3UWp0cFFrRkJPVUlzVFVGRlR5eEpRVUZKTEV0QlFVc3NTVUZCVEN4RlFVRlhPenM3T3p0QlFVdHNRaXgzUWtGQlNTeERRVUZETEZOQlFWTXNRMEZCVkN4RFFVRkVMRVZCUVdNN1FVRkRaQ3h0UTBGQlZ5eERRVUZZTEVWQlFXTXNTMEZCWkN4RlFVRnhRaXhMUVVGeVFpeEZRVVJqTzBGQlJXUXNaME5CUVZFc1RVRkJUU3hMUVVGT0xFTkJRVklzUTBGR1l6dHhRa0ZCYkVJN08wRkJTMEVzTkVKQlFWRXNXVUZCV1N4TFFVRmFMRVZCUVcxQ0xFbEJRVWtzVFVGQlNpeERRVUZYTEU5QlFVOHNUVUZCVUN4RlFVRmxMRU5CUVRGQ0xFVkJRVFpDTEVOQlFUZENMRU5CUVc1Q0xFTkJRVklzUTBGV2EwSTdhVUpCUVdZc1RVRlhRU3hKUVVGSkxGRkJRVkVzUTBGQlVpeERRVUZLTEVWQlFXZENPMEZCUTI1Q0xIZENRVUZKTEZGQlFWRXNRMEZCVWl4RFFVRktMRVZCUVdkQ08wRkJRMW9zTkVKQlFVa3NSVUZCUlN4UFFVRkdMRXRCUVdNc1JVRkJSU3hQUVVGR0xFbEJRMlFzUlVGQlJTeFRRVUZHTEV0QlFXZENMRVZCUVVVc1UwRkJSaXhKUVVOb1FpeEZRVUZGTEVkQlFVWXNTMEZCVlN4RlFVRkZMRWRCUVVZc1JVRkJUenRCUVVOcVFpeG5RMEZCU1N4aFFVRmhMRlZCUVZVc1JVRkJSU3hWUVVGR0xFVkJRV01zUlVGQlJTeFZRVUZHTEVOQlFYSkRMRU5CUkdFN1FVRkZha0lzWjBOQlFVa3NWVUZCU2l4RlFVRm5RanRCUVVOYUxIZERRVUZSTEZsQlFWa3NTMEZCV2l4RlFVTktMRWxCUVVrc1RVRkJTaXhEUVVGWExFOUJRVThzUzBGQlVDeEZRVUZqTEVOQlFYcENMRVZCUVRSQ0xGVkJRVFZDTEVOQlJFa3NRMEZCVWl4RFFVUlpPelpDUVVGb1FqdEJRVWxCTEc5RFFVRlJMR0ZCUVdFc1EwRkJZaXhGUVVGblFpeERRVUZvUWl4RlFVRnRRaXhMUVVGdVFpeEZRVUV3UWl4TFFVRXhRaXhGUVVGcFF5eExRVUZxUXl4RFFVRlNMRU5CVG1sQ08zbENRVVp5UWl4TlFWTlBPMEZCUTBnc2IwTkJRVkVzV1VGQldTeExRVUZhTEVWQlFXMUNMRWxCUVVrc1RVRkJTaXhEUVVGWExFOUJRVThzUzBGQlVDeEZRVUZqTEVOQlFYcENMRVZCUVRSQ0xFTkJRVFZDTEVOQlFXNUNMRU5CUVZJc1EwRkVSenRCUVVWSUxIbERRVUZoTEVsQlFXSXNRMEZHUnp0NVFrRlVVRHR4UWtGRVNpeE5RV05QTzBGQlEwZ3NaME5CUVZFc1dVRkJXU3hMUVVGYUxFVkJRVzFDTEVsQlFVa3NUVUZCU2l4RFFVRlhMRTlCUVU4c1MwRkJVQ3hGUVVGakxFTkJRWHBDTEVWQlFUUkNMRU5CUVRWQ0xFTkJRVzVDTEVOQlFWSXNRMEZFUnp0QlFVVklMSEZEUVVGaExFbEJRV0lzUTBGR1J6dHhRa0ZrVUR0cFFrRkVSeXhOUVcxQ1FTeEpRVUZKTEZGQlFWRXNRMEZCVWl4RFFVRktMRVZCUVdkQ08wRkJRMjVDTEhkQ1FVRkpMRU5CUVVNc1VVRkJVU3hEUVVGU0xFTkJRVVFzUlVGQllUdEJRVU5pTEdkRFFVRlJMRmxCUVZrc1MwRkJXaXhGUVVGdFFpeEpRVUZKTEUxQlFVb3NRMEZCVnl4UFFVRlBMRXRCUVZBc1JVRkJZeXhEUVVGNlFpeEZRVUUwUWl4RFFVRTFRaXhEUVVGdVFpeERRVUZTTEVOQlJHRTdRVUZGWWl4eFEwRkJZU3hKUVVGaUxFTkJSbUU3Y1VKQlFXcENMRTFCUjA4c1NVRkJTU3hGUVVGRkxFbEJRVVlzUzBGQlZ5eEZRVUZGTEVsQlFVWXNSVUZCVVR0QlFVTXhRaXhuUTBGQlVTeFpRVUZaTEV0QlFWb3NSVUZCYlVJc1NVRkJTU3hOUVVGS0xFTkJRVmNzVDBGQlR5eExRVUZRTEVWQlFXTXNRMEZCZWtJc1JVRkJORUlzUTBGQk5VSXNRMEZCYmtJc1EwRkJVaXhEUVVRd1FqdHhRa0ZCZGtJN2FVSkJTa29zVFVGUFFTeEpRVUZKTEZOQlFWTXNRMEZCVkN4RFFVRktMRVZCUVdsQ08wRkJRM0JDTEhkQ1FVRkpMRU5CUVVNc1UwRkJVeXhEUVVGVUxFTkJRVVFzUlVGQll6dEJRVU5rTEhGRFFVRmhMRWxCUVdJc1EwRkVZenR4UWtGQmJFSTdPMEZCU1VFc05FSkJRVkVzV1VGQldTeExRVUZhTEVWQlFXMUNMRWxCUVVrc1RVRkJTaXhEUVVGWExFOUJRVThzVFVGQlVDeEZRVUZsTEVOQlFURkNMRVZCUVRaQ0xFTkJRVGRDTEVOQlFXNUNMRU5CUVZJc1EwRk1iMEk3YVVKQlFXcENPenRCUVZGUUxHOUNRVUZKTEV0QlFVb3NSVUZCVnp0QlFVTlFMREJDUVVGTkxFdEJRVTRzU1VGQlpTeExRVUZtTEVOQlJFODdhVUpCUVZnN08wRkJTVUVzYjBKQlFVa3NWVUZCU2l4RlFVRm5RanRCUVVOYUxDdENRVUZYTEVOQlFWZ3NSVUZCWXl4TFFVRmtMRVZCUVhGQ0xFdEJRWEpDTEVWQlJGazdhVUpCUVdoQ08yRkJNMFJLT3p0QlFXZEZRU3h4UWtGQlV5eFpRVUZVTEVOQlFYTkNMRU5CUVhSQ0xFVkJRWGxDTEVOQlFYcENMRVZCUVRSQ0xFdEJRVFZDTEVWQlFXMURMRXRCUVc1RExFVkJRVEJETEV0QlFURkRMRVZCUVdsRU8wRkJRemRETEc5Q1FVRkpMRmxCUVZrc1JVRkJSU3hSUVVGR0xFTkJSRFpDTzBGQlJUZERMRzlDUVVGSkxHRkJRV0VzVVVGQlVTeFRRVUZTTEVWQlFXMUNMRVZCUVVVc1VVRkJSaXhEUVVGb1F5eERRVVo1UXp0QlFVYzNReXh2UWtGQlNTeFpRVUZaTEZkQlFWY3NVVUZCV0N4RFFVZzJRanM3UVVGTE4wTXNiMEpCUVVrc1QwRkJUeXhWUVVGVkxFMUJRVllzUTBGTWEwTTdRVUZOTjBNc2IwSkJRVWtzVDBGQlR5eFZRVUZWTEUxQlFWWXNRMEZPYTBNN1FVRlBOME1zYjBKQlFVa3NUVUZCVFN4UFFVRlBMRWxCUVZBc1IwRkJZeXhKUVVGa0xFZEJRWEZDTEVsQlFYSkNMRU5CVUcxRE96dEJRVk0zUXl4eFFrRkJTeXhKUVVGSkxFbEJRVWtzUTBGQlNpeEZRVUZQTEVsQlFVa3NSMEZCU2l4RlFVRlRMRWRCUVhwQ0xFVkJRVGhDTzBGQlF6RkNMSGRDUVVGSkxGZEJRVmNzVlVGQlZTeERRVUZXTEVOQlFWZ3NRMEZFYzBJN1FVRkZNVUlzZDBKQlFVa3NXVUZCV1N4VlFVRlZMRU5CUVZZc1EwRkJXaXhEUVVaelFqdEJRVWN4UWl3MlFrRkJVeXhEUVVGVUxFTkJTREJDT3p0QlFVc3hRaXgzUWtGQlNTeERRVUZETEZGQlFVUXNSVUZCVnp0QlFVTllMRFJDUVVGSkxGTkJRVW9zUlVGQlpUczdRVUZGV0N4dlEwRkJVU3haUVVGWkxFdEJRVm9zUlVGRFNpeEpRVUZKTEUxQlFVb3NRMEZCVnl4UFFVRlBMRTFCUVZBc1JVRkJaU3hKUVVFeFFpeEZRVUZuUXl4VFFVRm9ReXhEUVVSSkxFTkJRVklzUTBGR1Z6dDVRa0ZCWmp0eFFrRkVTaXhOUVUxUE8wRkJRMGdzTmtKQlFVc3NVVUZCVEN4RlFVRmxMRk5CUVdZc1JVRkJNRUlzUzBGQk1VSXNSVUZCYVVNc1MwRkJha01zUlVGRVJ6dHhRa0ZPVURzN1FVRlZRU3gzUWtGQlNTeFJRVUZSTEZGQlFWSXNTMEZCY1VJc1UwRkJVeXhMUVVGVUxFVkJRV2RDTzBGQlEzSkRMR2xEUVVGVExGTkJRVk1zUzBGQlZDeERRVVEwUWp0eFFrRkJla003YVVKQlprbzdPMEZCYjBKQkxHOUNRVUZKTEZkQlFWY3NTMEZCV0N4RlFVRnJRanM3UVVGRmJFSXNORUpCUVZFc1dVRkJXU3hMUVVGYUxFVkJRVzFDTEVsQlFVa3NUVUZCU2l4RFFVTjJRaXhQUVVGUExFdEJRVkFzUlVGRFFTeERRVVoxUWl4RlFVZDJRaXhYUVVGWExFdEJRVmdzUTBGSVNTeERRVUZTTEVOQlJtdENPMmxDUVVGMFFqczdRVUZUUVN4MVFrRkJUeXhMUVVGUUxFTkJkRU0yUXp0aFFVRnFSRHM3UVVGNVEwRXNjVUpCUVZNc1ZVRkJWQ3hEUVVGdlFpeExRVUZ3UWl4RlFVRXlRaXhMUVVFelFpeEZRVUZyUXl4TFFVRnNReXhGUVVGNVF6czdRVUZGY2tNc2RVSkJRVThzUzBGQlVDeEZRVUZqTEV0QlFXUXNSVUZCY1VJc1MwRkJja0lzUlVGR2NVTTdRVUZIY2tNc0swSkJRV1VzUzBGQlppeEZRVUZ6UWl4TFFVRjBRaXhGUVVFMlFpeExRVUUzUWl4RlFVaHhRenRoUVVGNlF6czdPenRCUVRkSUswVXNjVUpCY1VsMFJTeGpRVUZVTEVOQlFYZENMRXRCUVhoQ0xFVkJRU3RDTEV0QlFTOUNMRVZCUVhORExFdEJRWFJETEVWQlFUWkRPMEZCUTNwRExHOUNRVUZKTEZOQlFWTXNTMEZCVkN4RFFVRktMRVZCUVhGQ08wRkJRMnBDTEhkQ1FVRkpMRTlCUVU4c1RVRkJUU3hQUVVGT0xFdEJRV3RDTEZWQlFYcENMRVZCUVhGRE8wRkJRM0pETERoQ1FVRk5MRXRCUVU0c1NVRkJaU3haUVVOWUxFMUJRVTBzUzBGQlRpeERRVVJYTEVWQlJWZ3NTVUZCU1N4TlFVRktMRU5CUVZjc1QwRkJUeXhOUVVGUUxFVkJRV1VzUzBGQk1VSXNSVUZCYVVNc1NVRkJha01zUTBGR1Z5eERRVUZtTEVOQlJIRkRPM0ZDUVVGNlF6dHBRa0ZFU2l4TlFVOVBMRWxCUVVrc1VVRkJVU3hMUVVGU0xFMUJRVzFDTEUxQlFVMHNWVUZCVGl4SlFVRnZRaXhOUVVGTkxGTkJRVTRzUTBGQmRrTXNSVUZCZVVRN1FVRkRhRVVzZDBKQlFVa3NWMEZCVnl4TlFVRk5MRkZCUVU0c1EwRkVhVVE3UVVGRmFFVXNkMEpCUVVrc1RVRkJUU3hUUVVGVExFMUJRVlFzUTBGR2MwUTdRVUZIYUVVc2VVSkJRVXNzU1VGQlNTeEpRVUZKTEVOQlFVb3NSVUZCVHl4SlFVRkpMRWRCUVVvc1JVRkJVeXhIUVVGNlFpeEZRVUU0UWp0QlFVTXhRaXcwUWtGQlNTeFJRVUZSTEZOQlFWTXNRMEZCVkN4RFFVRlNMRU5CUkhOQ08wRkJSVEZDTEdsRFFVRlRMRU5CUVZRc1EwRkdNRUk3TzBGQlNURkNMSFZEUVVGbExFdEJRV1lzUlVGQmMwSXNTMEZCZEVJc1JVRkJOa0lzUzBGQk4wSXNSVUZLTUVJN08wRkJUVEZDTERSQ1FVRkpMRkZCUVZFc1MwRkJVaXhMUVVGclFpeE5RVUZOTEV0QlFVNHNSVUZCWVR0QlFVTXZRaXh4UTBGQlV5eE5RVUZOTEV0QlFVNHNRMEZFYzBJN2VVSkJRVzVETzNGQ1FVNUtPMmxDUVVoSExFMUJZVUVzU1VGQlNTeFJRVUZSTEV0QlFWSXNRMEZCU2l4RlFVRnZRanRCUVVOMlFpd3lRa0ZCVHl4TFFVRlFMRVZCUVdNc1NVRkJaQ3hGUVVGdlFpeExRVUZ3UWl4RlFVRXlRaXhMUVVFelFpeEZRVVIxUWp0cFFrRkJjRUk3WVVGeVFsZzdPenRCUVhKSkswVXNjVUpCWjB0MFJTeE5RVUZVTEVOQlFXZENMRU5CUVdoQ0xFVkJRVzFDTEVOQlFXNUNMRVZCUVhOQ0xFdEJRWFJDTEVWQlFUWkNMRXRCUVRkQ0xFVkJRVzlETzBGQlEyaERMRzlDUVVGSkxGRkJRVkVzV1VGQldTeERRVUZhTEVWQlFXVXNRMEZCWml4RFFVRlNMRU5CUkRSQ08wRkJSV2hETEc5Q1FVRkpMR0ZCUVdFc1MwRkJTeXhOUVVGTkxFTkJRVTRzUlVGQlV5eE5RVUZOTEVOQlFVNHNRMEZCTTBJc1EwRkdORUk3UVVGSGFFTXNiMEpCUVVrc1YwRkJWeXhWUVVGWUxFTkJRVW9zUlVGQk5FSTdRVUZEZUVJc01FSkJRVTBzUzBGQlRpeEpRVUZsTEVsQlFVa3NUVUZCU2l4RFFVRlhMRTlCUVU4c1MwRkJVQ3hGUVVGakxFbEJRWHBDTEVWQlFTdENMRlZCUVM5Q0xFTkJRV1lzUTBGRWQwSTdhVUpCUVRWQ08yRkJTRW83TzBGQlVVRXNjVUpCUVZNc1ZVRkJWQ3hEUVVGdlFpeExRVUZ3UWl4RlFVRXlRanRCUVVOMlFpeHhRa0ZCU3l4SlFVRkpMRXRCUVVvc1NVRkJZU3hMUVVGc1FpeEZRVUY1UWp0QlFVTnlRaXgzUWtGQlNTeFZRVUZWTEVkQlFWWXNSVUZCWlR0QlFVTm1MQ3RDUVVGUExFbEJRVkFzUTBGRVpUdHhRa0ZCYmtJN2FVSkJSRW83TzBGQlRVRXNkVUpCUVU4c1MwRkJVQ3hEUVZCMVFqdGhRVUV6UWpzN08wRkJlRXNyUlN4eFFrRnRUSFJGTEUxQlFWUXNRMEZCWjBJc1MwRkJhRUlzUlVGQmRVSXNTMEZCZGtJc1JVRkJPRUlzUzBGQk9VSXNSVUZCY1VNN1FVRkRha01zYjBKQlFVa3NVVUZCVVN4TFFVRlNMRU5CUVVvc1JVRkJiMEk3UVVGRGFFSXNkMEpCUVVrc1RVRkJUU3hMUVVGT0xFVkJRV0U3UVVGRFlpdzRRa0ZCVFN4TFFVRk9MRWxCUVdVc1dVRkRXQ3hOUVVGTkxFdEJRVTRzUTBGRVZ5eEZRVVZZTEVsQlFVa3NUVUZCU2l4RFFVTkpMRTlCUVU4c1MwRkJVQ3hGUVVOQkxFdEJSa29zUlVGSFNTeGpRVUZqTEUxQlFVMHNTMEZCVGl4RFFVaHNRaXhEUVVaWExFTkJRV1lzUTBGRVlUdHhRa0ZCYWtJN08wRkJWMEVzZDBKQlFVa3NUVUZCVFN4bFFVRk9MRWxCUVhsQ0xFMUJRVTBzVTBGQlRpeEZRVUZwUWp0QlFVTXhReXcwUWtGQlNTeFhRVUZYTEUxQlFVMHNVVUZCVGl4RFFVUXlRanRCUVVVeFF5dzBRa0ZCU1N4TlFVRk5MRk5CUVZNc1RVRkJWQ3hEUVVablF6dEJRVWN4UXl3MlFrRkJTeXhKUVVGSkxFbEJRVWtzUTBGQlNpeEZRVUZQTEVsQlFVa3NSMEZCU2l4RlFVRlRMRWRCUVhwQ0xFVkJRVGhDTzBGQlF6RkNMR2REUVVGSkxGRkJRVkVzVTBGQlV5eERRVUZVTEVOQlFWSXNRMEZFYzBJN1FVRkZNVUlzY1VOQlFWTXNRMEZCVkN4RFFVWXdRanM3UVVGSk1VSXNiVU5CUVU4c1MwRkJVQ3hGUVVGakxFdEJRV1FzUlVGQmNVSXNTMEZCY2tJc1JVRktNRUk3TzBGQlRURkNMR2REUVVGSkxGRkJRVkVzUzBGQlVpeExRVUZyUWl4TlFVRk5MRXRCUVU0c1JVRkJZVHRCUVVNdlFpeDVRMEZCVXl4TlFVRk5MRXRCUVU0c1EwRkVjMEk3TmtKQlFXNURPM2xDUVU1S08zRkNRVWhLTzJsQ1FWcEtMRTFCTUVKUExFbEJRVWtzVVVGQlVTeExRVUZTTEVOQlFVb3NSVUZCYjBJN1FVRkRka0lzTWtKQlFVOHNTMEZCVUN4RlFVRmpMRWxCUVdRc1JVRkJiMElzUzBGQmNFSXNSVUZCTWtJc1MwRkJNMElzUlVGRWRVSTdhVUpCUVhCQ08yRkJNMEpZT3p0QlFXZERRU3h4UWtGQlV5eGhRVUZVTEVOQlFYVkNMRWRCUVhaQ0xFVkJRVFJDTzBGQlEzaENMRzlDUVVGSkxGTkJRVk1zUlVGQlZDeERRVVJ2UWpzN1FVRkhlRUlzY1VKQlFVc3NTVUZCU1N4SFFVRktMRWxCUVZjc1IwRkJhRUlzUlVGQmNVSTdRVUZEYWtJc01rSkJRVThzUjBGQlVDeEpRVUZqTEZOQlFXUXNRMEZFYVVJN2FVSkJRWEpDT3p0QlFVbEJMSFZDUVVGUExFMUJRVkFzUTBGUWQwSTdZVUZCTlVJN096dEJRVzVPSzBVc2NVSkJPRTUwUlN4UFFVRlVMRU5CUVdsQ0xGTkJRV3BDTEVWQlFUUkNMRk5CUVRWQ0xFVkJRWFZET3p0QlFVVnVReXh2UWtGQlNTeGpRVUZqTEZOQlFWTXNVMEZCVkN4RFFVRmtMRU5CUml0Q08wRkJSMjVETEc5Q1FVRkpMRkZCUVZFc1dVRkJXU3hKUVVGYUxFTkJTSFZDTzBGQlNXNURMRzlDUVVGSkxGRkJRVkVzV1VGQldTeEpRVUZhTEVOQlNuVkNPenRCUVUxdVF5eHZRa0ZCU1N4TlFVRk5MRTFCUVU0c1MwRkJhVUlzVlVGQlZTeE5RVUZXTEVWQlFXdENPMEZCUTI1RExESkNRVUZQTzBGQlEwZ3NhME5CUVZVc1UwRkJWanRCUVVOQkxDdENRVUZQTEVsQlFWQTdjVUpCUmtvc1EwRkViVU03YVVKQlFYWkRPenM3UVVGT2JVTXNiMEpCWXk5Q0xHTkJRV01zVTBGQlV5eFRRVUZVTEVOQlFXUXNRMEZrSzBJN1FVRmxia01zYjBKQlFVa3NVVUZCVVN4WlFVRlpMRWxCUVZvc1EwRm1kVUk3UVVGblFtNURMRzlDUVVGSkxGRkJRVkVzV1VGQldTeEpRVUZhTEVOQmFFSjFRanM3UVVGclFtNURMRzlDUVVGSkxFMUJRVTBzVFVGQlRpeExRVUZwUWl4VlFVRlZMRTFCUVZZc1JVRkJhMEk3UVVGRGJrTXNNa0pCUVU4N1FVRkRTQ3hyUTBGQlZTeFRRVUZXTzBGQlEwRXNLMEpCUVU4c1NVRkJVRHR4UWtGR1NpeERRVVJ0UXp0cFFrRkJka003T3p0QlFXeENiVU1zYjBKQk1FSXZRaXhqUVVGakxFVkJRV1FzUTBFeFFpdENPenRCUVRSQ2JrTXNiMEpCUVVrc1dVRkJXU3hEUVVGYUxFTkJOVUlyUWp0QlFUWkNia01zYjBKQlFVa3NXVUZCV1N4TlFVRk5MRTFCUVU0c1EwRTNRbTFDTzBGQk9FSnVReXh2UWtGQlNTeGxRVUZsTEVOQlFXWTdPenM3UVVFNVFpdENMSEZDUVd0RE9VSXNTVUZCU1N4SlFVRkpMRU5CUVVvc1JVRkJVU3hKUVVGSkxGVkJRVlVzVFVGQlZpeEZRVUZyUWl4SFFVRjJReXhGUVVFMFF6dEJRVU40UXl4M1FrRkJTU3hSUVVGUkxGVkJRVlVzUTBGQlZpeERRVUZTTEVOQlJHOURPMEZCUlhoRExIZENRVUZKTEZOQlFVb3NRMEZHZDBNN08wRkJTWGhETEhkQ1FVRkpMRTFCUVUwc1IwRkJUaXhGUVVGWE8wRkJRMWdzTkVKQlFVa3NUVUZCVFN4alFVRk9MRU5CUVhGQ0xFMUJRVTBzUjBGQlRpeERRVUY2UWl4RlFVRnhRenM3UVVGRmFrTXNkME5CUVZrc1RVRkJUU3hOUVVGTkxFZEJRVTRzUTBGQmJFSXNRMEZHYVVNN1FVRkhha01zZDBOQlFWa3NTVUZCV2l4RFFVRnBRaXhWUVVGVkxGTkJRVllzUTBGQmFrSXNSVUZJYVVNN2VVSkJRWEpETEUxQlMwODdPMEZCUlVnc2QwTkJRVmtzU1VGQlNTeGpRVUZLTEVOQlJsUTdRVUZIU0N4M1EwRkJXU3hKUVVGYUxFTkJRV2xDTEVsQlFXcENMRVZCU0VjN2VVSkJURkE3Y1VKQlJFb3NUVUZYVHpzN1FVRkZTQ3cwUWtGQlNTeFpRVUZaTEZOQlFWb3NSVUZCZFVJN1FVRkRka0lzZDBOQlFWa3NUVUZCVFN4WFFVRk9MRU5CUVZvc1EwRkVkVUk3UVVGRmRrSXNkME5CUVZrc1NVRkJXaXhEUVVGcFFpeFZRVUZWTEZOQlFWWXNRMEZCYWtJc1JVRkdkVUk3ZVVKQlFUTkNMRTFCUjA4N096czdRVUZKU0N4M1EwRkJXU3hKUVVGSkxHTkJRVW9zUTBGS1ZEdEJRVXRJTEhkRFFVRlpMRWxCUVZvc1EwRkJhVUlzU1VGQmFrSXNSVUZNUnp0NVFrRklVRHR4UWtGaVNqdHBRa0ZLU2pzN1FVRTRRa0VzYjBKQlFVa3NaMEpCUVdkQ0xHRkJRV0VzVFVGQlRTeE5RVUZPTEVkQlF6ZENMRlZCUVZVc1RVRkJWaXhIUVVOQkxFMUJRVTBzVTBGQlRpeERRVVpuUWpzN096dEJRV2hGWlN4eFFrRnpSVGxDTEVsQlFVa3NTVUZCU1N4RFFVRktMRVZCUVU4c1NVRkJTU3hWUVVGVkxFMUJRVllzUlVGQmEwSXNSMEZCZEVNc1JVRkJNa003UVVGRGRrTXNkMEpCUVVrc1ZVRkJWU3hWUVVGVkxFTkJRVllzUTBGQlZpeERRVVJ0UXpzN1FVRkhka01zZDBKQlFVa3NVVUZCVVN4SFFVRlNMRVZCUVdFN1FVRkRZaXcwUWtGQlNTeERRVUZETEUxQlFVMHNZMEZCVGl4RFFVRnhRaXhSUVVGUkxFZEJRVklzUTBGQmRFSXNSVUZCYjBNN096czdRVUZKY0VNc2QwTkJRVmtzU1VGQldpeERRVUZwUWl4UFFVRnFRaXhGUVVwdlF6dDVRa0ZCZUVNN2NVSkJSRW9zVFVGUFR5eEpRVUZKTEV0QlFVc3NZVUZCVEN4RlFVRnZRanM3UVVGRk0wSXNiME5CUVZrc1NVRkJXaXhEUVVGcFFpeFBRVUZxUWl4RlFVWXlRanR4UWtGQmVFSTdhVUpCVmxnN08wRkJaMEpCTEc5Q1FVRkpMRmRCUVZjc1dVRkJXU3hMUVVGYUxFVkJRVmdzUTBGMFJpdENPMEZCZFVadVF5eHZRa0ZCU1N4blFrRkJaMElzUTBGQmFFSXNRMEYyUml0Q08wRkJkMFp1UXl4dlFrRkJTU3hWUVVGVkxFVkJRVllzUTBGNFJpdENPMEZCZVVadVF5eHZRa0ZCU1N4VlFVRlZMRVZCUVZZc1EwRjZSaXRDTzBGQk1FWnVReXh2UWtGQlNTeFpRVUZLTEVOQk1VWnRRenM3UVVFMFJtNURMSEZDUVVGTExFbEJRVWtzU1VGQlNTeERRVUZLTEVWQlFVOHNTVUZCU1N4VlFVRlZMRTFCUVZZc1IwRkJiVUk3UVVGRGJrTXNkMEpCUVVrc1lVRkJZU3hWUVVGVkxFTkJRVllzUTBGQllpeERRVVFyUWp0QlFVVnVReXh0UTBGQlpTeFRRVUZUTEdGQlFWUXNRMEZCWmpzN08wRkJSbTFETERKQ1FVczFRaXhwUWtGQmFVSXNTVUZCYWtJc1NVRkJlVUlzVTBGQlV5eE5RVUZVTEVWQlFXbENPMEZCUXpkRExHZERRVUZSTEVsQlFWSXNRMEZCWVN4UFFVRlBMRkZCUVZBc1JVRkJhVUlzWVVGQmFrSXNSVUZCWjBNc1NVRkJhRU1zUTBGQllpeEZRVVEyUXp0QlFVVTNReXgxUTBGQlpTeFRRVUZUTEdGQlFWUXNRMEZCWml4RFFVWTJRenR4UWtGQmFrUTdPMEZCUzBFc2QwSkJRVWtzUTBGQlF5eFpRVUZFTEVsQlFXbENMR0ZCUVdFc1IwRkJZaXhMUVVGeFFpeFhRVUZYTEVkQlFWZ3NSVUZCWjBJN08wRkJSWFJFTERSQ1FVRkpMRmRCUVZjc1IwRkJXQ3hGUVVGblFqdEJRVU5vUWl4blEwRkJTU3huUWtGQlowSXNZVUZCWVN4SFFVRmlMRVZCUVd0Q096dEJRVVZzUXl4dlEwRkJTU3hOUVVGTkxHRkJRV0VzUjBGQllpeERRVUZPTEV0QlFUUkNMRWxCUVVrc1EwRkJTaXhGUVVGUE8wRkJRMjVETERSRFFVRlJMRWxCUVZJc1EwRkJZU3hQUVVGUExGRkJRVkFzUlVGQmFVSXNZVUZCYWtJc1JVRkJaME1zWVVGQllTeEhRVUZpTEVOQlFUZERMRVZCUkcxRE8wRkJSVzVETEcxRVFVRmxMRk5CUVZNc1lVRkJWQ3hEUVVGbU96dEJRVVp0UXl4M1EwRkpMMElzUTBGQlF5eFpRVUZFTEVsQlFXbENMR0ZCUVdFc1IwRkJZaXhMUVVGeFFpeFhRVUZYTEVkQlFWZ3NSVUZCWjBJN1FVRkRkRVFzWjBSQlFWRXNTVUZCVWl4RFFVRmhMRVZCUVVNc1MwRkJTeXhYUVVGWExFZEJRVmdzUlVGQlowSXNTVUZCU1N4RFFVRktMRVZCUVc1RExFVkJSSE5FT3pzN1FVRkJNVVFzZVVOQlNVczdRVUZEUkN3MFJFRkVRenQ1UTBGS1REdHBRMEZLU2l4TlFWbExPMEZCUTBRc05FTkJRVkVzU1VGQlVpeERRVUZoTEVWQlFVTXNTMEZCU3l4WFFVRlhMRWRCUVZnc1JVRkJaMElzU1VGQlNTeERRVUZLTEVWQlFXNURMRVZCUkVNN2FVTkJXa3c3TmtKQlJrb3NUVUZyUWtzN1FVRkRSQ3gzUTBGQlVTeEpRVUZTTEVOQlFXRXNSVUZCUXl4TFFVRkxMRmRCUVZjc1IwRkJXQ3hGUVVGblFpeEpRVUZKTEVOQlFVb3NSVUZCYmtNc1JVRkVRenMyUWtGc1FrdzdRVUZ4UWtFc1owTkJkRUpuUWpzN08wRkJRWEJDTERaQ1FYbENTeXhKUVVGSkxHZENRVUZuUWl4aFFVRmhMRWRCUVdJc1JVRkJhMEk3UVVGRGRrTXNkME5CUVZFc1NVRkJVaXhEUVVGaExFOUJRVThzVVVGQlVDeEZRVUZwUWl4aFFVRnFRaXhGUVVGblF5eGhRVUZoTEVkQlFXSXNRMEZCTjBNc1JVRkVkVU03TmtKQlFYUkRPM0ZDUVROQ1ZDeE5RU3RDU3p0QlFVTkVMSGREUVVSRE8wRkJSVVFzTkVKQlJrTTdjVUpCTDBKTU8ybENRVlpLT3pzN1FVRTFSbTFETEhWQ1FUUkpOMElzWjBKQlFXZENMRk5CUVZNc1RVRkJWQ3hGUVVGcFFqdEJRVU51UXl4dFEwRkJaU3hUUVVGVExHRkJRVlFzUTBGQlppeERRVVJ0UXp0QlFVVnVReXcwUWtGQlVTeEpRVUZTTEVOQlFXRXNUMEZCVHl4UlFVRlFMRVZCUVdsQ0xHRkJRV3BDTEVWQlFXZERMR2RDUVVGblFpeGhRVUZoTEVkQlFXSXNRMEZCTjBRc1JVRkdiVU03YVVKQlFYWkRPenM3TzBGQk5VbHRReXh2UWtGdFNpOUNMRkZCUVZFc1RVRkJVaXhMUVVGdFFpeFpRVUZ1UWl4SlFVRnRReXhEUVVGRExGRkJRVkVzVFVGQlVpeEZRVUZuUWp0QlFVTndSQ3d5UWtGQlR6dEJRVU5JTEd0RFFVRlZMRmRCUVZZN1FVRkRRU3dyUWtGQlR5eEpRVUZRTzNGQ1FVWktMRU5CUkc5RU8ybENRVUY0UkRzN1FVRlBRU3gxUWtGQlR6dEJRVU5JTERoQ1FVRlZMRmRCUVZZN1FVRkRRU3d5UWtGQlR6dEJRVU5JTEdsRFFVRlRMRTlCUVZRN1FVRkRRU3hwUTBGQlV5eFBRVUZVTzNGQ1FVWktPMmxDUVVaS0xFTkJNVXB0UXp0aFFVRjJRenM3UVVGdFMwRXNjVUpCUVZNc1RVRkJWQ3hEUVVGblFpeEhRVUZvUWl4RlFVRnhRaXhMUVVGeVFpeEZRVUUwUWl4SFFVRTFRaXhGUVVGcFF6dEJRVU0zUWl4dlFrRkJTU3hOUVVGS0xFTkJRVmNzUzBGQldDeEZRVUZyUWl4RFFVRnNRaXhGUVVRMlFqczdRVUZITjBJc2RVSkJRVTg3UVVGRFNDd3dRa0ZCVFN4TFFVRk9PMEZCUTBFc2VVSkJRVXNzUjBGQlREdHBRa0ZHU2l4RFFVZzJRanRoUVVGcVF6czdRVUZUUVN4eFFrRkJVeXhSUVVGVUxFTkJRV3RDTEZGQlFXeENMRVZCUVRSQ08wRkJRM2hDTEc5Q1FVRkpMRTlCUVU4c1JVRkJVQ3hEUVVSdlFqdEJRVVY0UWl4dlFrRkJTU3hQUVVGUExFVkJRVkFzUTBGR2IwSTdRVUZIZUVJc2IwSkJRVWtzVTBGQlV5eFRRVUZUTEUxQlFWUXNRMEZJVnpzN1FVRkxlRUlzY1VKQlFVc3NTVUZCU1N4SlFVRkpMRU5CUVVvc1JVRkJUeXhKUVVGSkxFMUJRVW9zUlVGQldTeEhRVUUxUWl4RlFVRnBRenRCUVVNM1FpeDNRa0ZCU1N4UlFVRlJMRk5CUVZNc1EwRkJWQ3hEUVVGU0xFTkJSSGxDT3p0QlFVYzNRaXgzUWtGQlNTeE5RVUZOTEVkQlFVNHNSVUZCVnp0QlFVTllMRFpDUVVGTExFMUJRVTBzUjBGQlRpeERRVUZNTEVkQlFXdENMRU5CUVd4Q0xFTkJSRmM3Y1VKQlFXWXNUVUZGVHp0QlFVTklMRFpDUVVGTExFbEJRVXdzUTBGQlZTeERRVUZXTEVWQlJFYzdjVUpCUmxBN2FVSkJTRW83TzBGQlZVRXNkVUpCUVU4N1FVRkRTQ3d3UWtGQlRTeEpRVUZPTzBGQlEwRXNNRUpCUVUwc1NVRkJUanRCUVVaSExHbENRVUZRTEVOQlpuZENPMkZCUVRWQ096dEJRWEZDUVN4eFFrRkJVeXhYUVVGVUxFTkJRWEZDTEV0QlFYSkNMRVZCUVRSQ0xFdEJRVFZDTEVWQlFXMURPMEZCUXk5Q0xHOUNRVUZKTEV0QlFVb3NSVUZCVnp0QlFVTlFMSGRDUVVGSkxGRkJRVkVzUzBGQlVpeERRVUZLTEVWQlFXOUNPMEZCUTJoQ0xEaENRVUZOTEVsQlFVNHNRMEZCVnl4TFFVRllMRVZCUkdkQ08zRkNRVUZ3UWl4TlFVVlBPMEZCUTBnc1owTkJRVkVzUTBGQlF5eExRVUZFTEVWQlFWRXNTMEZCVWl4RFFVRlNMRU5CUkVjN2NVSkJSbEE3TzBGQlRVRXNNa0pCUVU4c1MwRkJVQ3hEUVZCUE8ybENRVUZZTEUxQlVVODdRVUZEU0N3eVFrRkJUeXhMUVVGUUxFTkJSRWM3YVVKQlVsQTdZVUZFU2p0VFFTOWFLME1zUlVFMllUZERMRVZCUVVNc2VVSkJRWGRDTEVWQlFYaENMRVZCUVRKQ0xIRkNRVUZ2UWl4RlFVRndRaXhGUVVGMVFpeHhRa0ZCYjBJc1JVRkJjRUlzUlVGQmRVSXNjVUpCUVc5Q0xFVkJRWEJDTEVWQlFYVkNMSE5DUVVGeFFpeEZRVUZ5UWl4RlFVRjNRaXh0UWtGQmEwSXNSVUZCYkVJc1JVRkJjVUlzWjBKQlFXVXNSVUZCWml4RlFVRnJRaXhqUVVGaExFVkJRV0lzUlVFM1lYQklMRU5CUVVnc1JVRTVkVU0xUWl4RlFUSndSSE5MTEVWQk0zQkVkRXNzUlVFeWNFUjVTeXhEUVVGRExFTkJRVVFzUTBFemNFUjZTeXhGUVRKd1JEaExMRU5CTTNCRU9Vc3NRMEZCVUN4RFFVWkxPME5CUVZnc1EwRkdSVHM3UVVGcmNVUktMR1ZCUVdVc1ZVRkJaaUlzSW1acGJHVWlPaUpzYVdJdmRtbHlkSFZoYkMxa2IyMHVhbk1pTENKemIzVnlZMlZ6UTI5dWRHVnVkQ0k2V3lKc1pYUWdWbWx5ZEhWaGJFUlBUU0E5SUdaMWJtTjBhVzl1S0dVcElIdGNiaUFnY21WMGRYSnVJR1VvS1R0Y2JuMG9ablZ1WTNScGIyNG9LU0I3WEc0Z0lDQWdJQ0FnSUhaaGNpQmtaV1pwYm1Vc0lHMXZaSFZzWlN3Z1pYaHdiM0owY3p0Y2JpQWdJQ0FnSUNBZ2NtVjBkWEp1SUNobWRXNWpkR2x2YmlCbEtIUXNJRzRzSUhJcElIdGNiaUFnSUNBZ0lDQWdJQ0FnSUNBZ0lDQm1kVzVqZEdsdmJpQnpLRzhzSUhVcElIdGNiaUFnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnYVdZZ0tDRnVXMjlkS1NCN1hHNGdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNCcFppQW9JWFJiYjEwcElIdGNiaUFnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0IyWVhJZ1lTQTlJSFI1Y0dWdlppQnlaWEYxYVhKbElEMDlJRndpWm5WdVkzUnBiMjVjSWlBbUppQnlaWEYxYVhKbE8xeHVJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJR2xtSUNnaGRTQW1KaUJoS1NCeVpYUjFjbTRnWVNodkxDQWhNQ2s3WEc0Z0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ2FXWWdLR2twSUhKbGRIVnliaUJwS0c4c0lDRXdLVHRjYmlBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNCMllYSWdaaUE5SUc1bGR5QkZjbkp2Y2loY0lrTmhibTV2ZENCbWFXNWtJRzF2WkhWc1pTQW5YQ0lnS3lCdklDc2dYQ0luWENJcE8xeHVJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJSFJvY205M0lHWXVZMjlrWlNBOUlGd2lUVTlFVlV4RlgwNVBWRjlHVDFWT1JGd2lMQ0JtWEc0Z0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0I5WEc0Z0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0IyWVhJZ2JDQTlJRzViYjEwZ1BTQjdYRzRnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnWlhod2IzSjBjem9nZTMxY2JpQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUgwN1hHNGdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNCMFcyOWRXekJkTG1OaGJHd29iQzVsZUhCdmNuUnpMQ0JtZFc1amRHbHZiaWhsS1NCN1hHNGdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdkbUZ5SUc0Z1BTQjBXMjlkV3pGZFcyVmRPMXh1SUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUhKbGRIVnliaUJ6S0c0Z1B5QnVJRG9nWlNsY2JpQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUgwc0lHd3NJR3d1Wlhod2IzSjBjeXdnWlN3Z2RDd2diaXdnY2lsY2JpQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdmVnh1SUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNCeVpYUjFjbTRnYmx0dlhTNWxlSEJ2Y25SelhHNGdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ2ZWeHVJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lIWmhjaUJwSUQwZ2RIbHdaVzltSUhKbGNYVnBjbVVnUFQwZ1hDSm1kVzVqZEdsdmJsd2lJQ1ltSUhKbGNYVnBjbVU3WEc0Z0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnWm05eUlDaDJZWElnYnlBOUlEQTdJRzhnUENCeUxteGxibWQwYURzZ2J5c3JLU0J6S0hKYmIxMHBPMXh1SUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJSEpsZEhWeWJpQnpYRzRnSUNBZ0lDQWdJQ0FnSUNCOUtTaDdYRzRnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSURFNklGdG1kVzVqZEdsdmJpaHlaWEYxYVhKbExDQnRiMlIxYkdVc0lHVjRjRzl5ZEhNcElIdGNibHh1ZG1GeUlHTnlaV0YwWlVWc1pXMWxiblFnUFNCeVpYRjFhWEpsS0Z3aUxpOTJaRzl0TDJOeVpXRjBaUzFsYkdWdFpXNTBMbXB6WENJcFhHNWNibTF2WkhWc1pTNWxlSEJ2Y25SeklEMGdZM0psWVhSbFJXeGxiV1Z1ZEZ4dVhHNTlMSHRjSWk0dmRtUnZiUzlqY21WaGRHVXRaV3hsYldWdWRDNXFjMXdpT2pFMWZWMHNNanBiWm5WdVkzUnBiMjRvY21WeGRXbHlaU3h0YjJSMWJHVXNaWGh3YjNKMGN5bDdYRzUyWVhJZ1pHbG1aaUE5SUhKbGNYVnBjbVVvWENJdUwzWjBjbVZsTDJScFptWXVhbk5jSWlsY2JseHViVzlrZFd4bExtVjRjRzl5ZEhNZ1BTQmthV1ptWEc1Y2JuMHNlMXdpTGk5MmRISmxaUzlrYVdabUxtcHpYQ0k2TXpWOVhTd3pPbHRtZFc1amRHbHZiaWh5WlhGMWFYSmxMRzF2WkhWc1pTeGxlSEJ2Y25SektYdGNiblpoY2lCb0lEMGdjbVZ4ZFdseVpTaGNJaTR2ZG1seWRIVmhiQzFvZVhCbGNuTmpjbWx3ZEM5cGJtUmxlQzVxYzF3aUtWeHVYRzV0YjJSMWJHVXVaWGh3YjNKMGN5QTlJR2hjYmx4dWZTeDdYQ0l1TDNacGNuUjFZV3d0YUhsd1pYSnpZM0pwY0hRdmFXNWtaWGd1YW5OY0lqb3lNbjFkTERRNlcyWjFibU4wYVc5dUtISmxjWFZwY21Vc2JXOWtkV3hsTEdWNGNHOXlkSE1wZTF4dWRtRnlJR1JwWm1ZZ1BTQnlaWEYxYVhKbEtGd2lMaTlrYVdabUxtcHpYQ0lwWEc1MllYSWdjR0YwWTJnZ1BTQnlaWEYxYVhKbEtGd2lMaTl3WVhSamFDNXFjMXdpS1Z4dWRtRnlJR2dnUFNCeVpYRjFhWEpsS0Z3aUxpOW9MbXB6WENJcFhHNTJZWElnWTNKbFlYUmxJRDBnY21WeGRXbHlaU2hjSWk0dlkzSmxZWFJsTFdWc1pXMWxiblF1YW5OY0lpbGNiblpoY2lCV1RtOWtaU0E5SUhKbGNYVnBjbVVvSnk0dmRtNXZaR1V2ZG01dlpHVXVhbk1uS1Z4dWRtRnlJRlpVWlhoMElEMGdjbVZ4ZFdseVpTZ25MaTkyYm05a1pTOTJkR1Y0ZEM1cWN5Y3BYRzVjYm0xdlpIVnNaUzVsZUhCdmNuUnpJRDBnZTF4dUlDQWdJR1JwWm1ZNklHUnBabVlzWEc0Z0lDQWdjR0YwWTJnNklIQmhkR05vTEZ4dUlDQWdJR2c2SUdnc1hHNGdJQ0FnWTNKbFlYUmxPaUJqY21WaGRHVXNYRzRnSUNBZ1ZrNXZaR1U2SUZaT2IyUmxMRnh1SUNBZ0lGWlVaWGgwT2lCV1ZHVjRkRnh1ZlZ4dVhHNTlMSHRjSWk0dlkzSmxZWFJsTFdWc1pXMWxiblF1YW5OY0lqb3hMRndpTGk5a2FXWm1MbXB6WENJNk1peGNJaTR2YUM1cWMxd2lPak1zWENJdUwzQmhkR05vTG1welhDSTZNVE1zWENJdUwzWnViMlJsTDNadWIyUmxMbXB6WENJNk16RXNYQ0l1TDNadWIyUmxMM1owWlhoMExtcHpYQ0k2TXpOOVhTdzFPbHRtZFc1amRHbHZiaWh5WlhGMWFYSmxMRzF2WkhWc1pTeGxlSEJ2Y25SektYdGNiaThxSVZ4dUlDb2dRM0p2YzNNdFFuSnZkM05sY2lCVGNHeHBkQ0F4TGpFdU1WeHVJQ29nUTI5d2VYSnBaMmgwSURJd01EY3RNakF4TWlCVGRHVjJaVzRnVEdWMmFYUm9ZVzRnUEhOMFpYWmxibXhsZG1sMGFHRnVMbU52YlQ1Y2JpQXFJRUYyWVdsc1lXSnNaU0IxYm1SbGNpQjBhR1VnVFVsVUlFeHBZMlZ1YzJWY2JpQXFJRVZEVFVGVFkzSnBjSFFnWTI5dGNHeHBZVzUwTENCMWJtbG1iM0p0SUdOeWIzTnpMV0p5YjNkelpYSWdjM0JzYVhRZ2JXVjBhRzlrWEc0Z0tpOWNibHh1THlvcVhHNGdLaUJUY0d4cGRITWdZU0J6ZEhKcGJtY2dhVzUwYnlCaGJpQmhjbkpoZVNCdlppQnpkSEpwYm1keklIVnphVzVuSUdFZ2NtVm5aWGdnYjNJZ2MzUnlhVzVuSUhObGNHRnlZWFJ2Y2k0Z1RXRjBZMmhsY3lCdlppQjBhR1ZjYmlBcUlITmxjR0Z5WVhSdmNpQmhjbVVnYm05MElHbHVZMngxWkdWa0lHbHVJSFJvWlNCeVpYTjFiSFFnWVhKeVlYa3VJRWh2ZDJWMlpYSXNJR2xtSUdCelpYQmhjbUYwYjNKZ0lHbHpJR0VnY21WblpYZ2dkR2hoZENCamIyNTBZV2x1YzF4dUlDb2dZMkZ3ZEhWeWFXNW5JR2R5YjNWd2N5d2dZbUZqYTNKbFptVnlaVzVqWlhNZ1lYSmxJSE53YkdsalpXUWdhVzUwYnlCMGFHVWdjbVZ6ZFd4MElHVmhZMmdnZEdsdFpTQmdjMlZ3WVhKaGRHOXlZQ0JwY3lCdFlYUmphR1ZrTGx4dUlDb2dSbWw0WlhNZ1luSnZkM05sY2lCaWRXZHpJR052YlhCaGNtVmtJSFJ2SUhSb1pTQnVZWFJwZG1VZ1lGTjBjbWx1Wnk1d2NtOTBiM1I1Y0dVdWMzQnNhWFJnSUdGdVpDQmpZVzRnWW1VZ2RYTmxaQ0J5Wld4cFlXSnNlVnh1SUNvZ1kzSnZjM010WW5KdmQzTmxjaTVjYmlBcUlFQndZWEpoYlNCN1UzUnlhVzVuZlNCemRISWdVM1J5YVc1bklIUnZJSE53YkdsMExseHVJQ29nUUhCaGNtRnRJSHRTWldkRmVIQjhVM1J5YVc1bmZTQnpaWEJoY21GMGIzSWdVbVZuWlhnZ2IzSWdjM1J5YVc1bklIUnZJSFZ6WlNCbWIzSWdjMlZ3WVhKaGRHbHVaeUIwYUdVZ2MzUnlhVzVuTGx4dUlDb2dRSEJoY21GdElIdE9kVzFpWlhKOUlGdHNhVzFwZEYwZ1RXRjRhVzExYlNCdWRXMWlaWElnYjJZZ2FYUmxiWE1nZEc4Z2FXNWpiSFZrWlNCcGJpQjBhR1VnY21WemRXeDBJR0Z5Y21GNUxseHVJQ29nUUhKbGRIVnlibk1nZTBGeWNtRjVmU0JCY25KaGVTQnZaaUJ6ZFdKemRISnBibWR6TGx4dUlDb2dRR1Y0WVcxd2JHVmNiaUFxWEc0Z0tpQXZMeUJDWVhOcFl5QjFjMlZjYmlBcUlITndiR2wwS0NkaElHSWdZeUJrSnl3Z0p5QW5LVHRjYmlBcUlDOHZJQzArSUZzbllTY3NJQ2RpSnl3Z0oyTW5MQ0FuWkNkZFhHNGdLbHh1SUNvZ0x5OGdWMmwwYUNCc2FXMXBkRnh1SUNvZ2MzQnNhWFFvSjJFZ1lpQmpJR1FuTENBbklDY3NJRElwTzF4dUlDb2dMeThnTFQ0Z1d5ZGhKeXdnSjJJblhWeHVJQ3BjYmlBcUlDOHZJRUpoWTJ0eVpXWmxjbVZ1WTJWeklHbHVJSEpsYzNWc2RDQmhjbkpoZVZ4dUlDb2djM0JzYVhRb0p5NHVkMjl5WkRFZ2QyOXlaREl1TGljc0lDOG9XMkV0ZWwwcktTaGNYR1FyS1M5cEtUdGNiaUFxSUM4dklDMCtJRnNuTGk0bkxDQW5kMjl5WkNjc0lDY3hKeXdnSnlBbkxDQW5kMjl5WkNjc0lDY3lKeXdnSnk0dUoxMWNiaUFxTDF4dWJXOWtkV3hsTG1WNGNHOXlkSE1nUFNBb1puVnVZM1JwYjI0Z2MzQnNhWFFvZFc1a1pXWXBJSHRjYmx4dUlDQjJZWElnYm1GMGFYWmxVM0JzYVhRZ1BTQlRkSEpwYm1jdWNISnZkRzkwZVhCbExuTndiR2wwTEZ4dUlDQWdJR052YlhCc2FXRnVkRVY0WldOT2NHTm5JRDBnTHlncFB6OHZMbVY0WldNb1hDSmNJaWxiTVYwZ1BUMDlJSFZ1WkdWbUxGeHVJQ0FnSUM4dklFNVFRMGM2SUc1dmJuQmhjblJwWTJsd1lYUnBibWNnWTJGd2RIVnlhVzVuSUdkeWIzVndYRzRnSUNBZ2MyVnNaanRjYmx4dUlDQnpaV3htSUQwZ1puVnVZM1JwYjI0b2MzUnlMQ0J6WlhCaGNtRjBiM0lzSUd4cGJXbDBLU0I3WEc0Z0lDQWdMeThnU1dZZ1lITmxjR0Z5WVhSdmNtQWdhWE1nYm05MElHRWdjbVZuWlhnc0lIVnpaU0JnYm1GMGFYWmxVM0JzYVhSZ1hHNGdJQ0FnYVdZZ0tFOWlhbVZqZEM1d2NtOTBiM1I1Y0dVdWRHOVRkSEpwYm1jdVkyRnNiQ2h6WlhCaGNtRjBiM0lwSUNFOVBTQmNJbHR2WW1wbFkzUWdVbVZuUlhod1hWd2lLU0I3WEc0Z0lDQWdJQ0J5WlhSMWNtNGdibUYwYVhabFUzQnNhWFF1WTJGc2JDaHpkSElzSUhObGNHRnlZWFJ2Y2l3Z2JHbHRhWFFwTzF4dUlDQWdJSDFjYmlBZ0lDQjJZWElnYjNWMGNIVjBJRDBnVzEwc1hHNGdJQ0FnSUNCbWJHRm5jeUE5SUNoelpYQmhjbUYwYjNJdWFXZHViM0psUTJGelpTQS9JRndpYVZ3aUlEb2dYQ0pjSWlrZ0t5QW9jMlZ3WVhKaGRHOXlMbTExYkhScGJHbHVaU0EvSUZ3aWJWd2lJRG9nWENKY0lpa2dLeUFvYzJWd1lYSmhkRzl5TG1WNGRHVnVaR1ZrSUQ4Z1hDSjRYQ0lnT2lCY0lsd2lLU0FySUM4dklGQnliM0J2YzJWa0lHWnZjaUJGVXpaY2JpQWdJQ0FnSUNoelpYQmhjbUYwYjNJdWMzUnBZMnQ1SUQ4Z1hDSjVYQ0lnT2lCY0lsd2lLU3hjYmlBZ0lDQWdJQzh2SUVacGNtVm1iM2dnTXl0Y2JpQWdJQ0FnSUd4aGMzUk1ZWE4wU1c1a1pYZ2dQU0F3TEZ4dUlDQWdJQ0FnTHk4Z1RXRnJaU0JnWjJ4dlltRnNZQ0JoYm1RZ1lYWnZhV1FnWUd4aGMzUkpibVJsZUdBZ2FYTnpkV1Z6SUdKNUlIZHZjbXRwYm1jZ2QybDBhQ0JoSUdOdmNIbGNiaUFnSUNBZ0lITmxjR0Z5WVhSdmNpQTlJRzVsZHlCU1pXZEZlSEFvYzJWd1lYSmhkRzl5TG5OdmRYSmpaU3dnWm14aFozTWdLeUJjSW1kY0lpa3NYRzRnSUNBZ0lDQnpaWEJoY21GMGIzSXlMQ0J0WVhSamFDd2diR0Z6ZEVsdVpHVjRMQ0JzWVhOMFRHVnVaM1JvTzF4dUlDQWdJSE4wY2lBclBTQmNJbHdpT3lBdkx5QlVlWEJsTFdOdmJuWmxjblJjYmlBZ0lDQnBaaUFvSVdOdmJYQnNhV0Z1ZEVWNFpXTk9jR05uS1NCN1hHNGdJQ0FnSUNBdkx5QkViMlZ6YmlkMElHNWxaV1FnWm14aFozTWdaM2tzSUdKMWRDQjBhR1Y1SUdSdmJpZDBJR2gxY25SY2JpQWdJQ0FnSUhObGNHRnlZWFJ2Y2pJZ1BTQnVaWGNnVW1WblJYaHdLRndpWGx3aUlDc2djMlZ3WVhKaGRHOXlMbk52ZFhKalpTQXJJRndpSkNnL0lWeGNYRnh6S1Z3aUxDQm1iR0ZuY3lrN1hHNGdJQ0FnZlZ4dUlDQWdJQzhxSUZaaGJIVmxjeUJtYjNJZ1lHeHBiV2wwWUN3Z2NHVnlJSFJvWlNCemNHVmpPbHh1SUNBZ0lDQXFJRWxtSUhWdVpHVm1hVzVsWkRvZ05ESTVORGsyTnpJNU5TQXZMeUJOWVhSb0xuQnZkeWd5TENBek1pa2dMU0F4WEc0Z0lDQWdJQ29nU1dZZ01Dd2dTVzVtYVc1cGRIa3NJRzl5SUU1aFRqb2dNRnh1SUNBZ0lDQXFJRWxtSUhCdmMybDBhWFpsSUc1MWJXSmxjam9nYkdsdGFYUWdQU0JOWVhSb0xtWnNiMjl5S0d4cGJXbDBLVHNnYVdZZ0tHeHBiV2wwSUQ0Z05ESTVORGsyTnpJNU5Ta2diR2x0YVhRZ0xUMGdOREk1TkRrMk56STVOanRjYmlBZ0lDQWdLaUJKWmlCdVpXZGhkR2wyWlNCdWRXMWlaWEk2SURReU9UUTVOamN5T1RZZ0xTQk5ZWFJvTG1ac2IyOXlLRTFoZEdndVlXSnpLR3hwYldsMEtTbGNiaUFnSUNBZ0tpQkpaaUJ2ZEdobGNqb2dWSGx3WlMxamIyNTJaWEowTENCMGFHVnVJSFZ6WlNCMGFHVWdZV0p2ZG1VZ2NuVnNaWE5jYmlBZ0lDQWdLaTljYmlBZ0lDQnNhVzFwZENBOUlHeHBiV2wwSUQwOVBTQjFibVJsWmlBL0lDMHhJRDQrUGlBd0lEb2dMeThnVFdGMGFDNXdiM2NvTWl3Z016SXBJQzBnTVZ4dUlDQWdJR3hwYldsMElENCtQaUF3T3lBdkx5QlViMVZwYm5Rek1paHNhVzFwZENsY2JpQWdJQ0IzYUdsc1pTQW9iV0YwWTJnZ1BTQnpaWEJoY21GMGIzSXVaWGhsWXloemRISXBLU0I3WEc0Z0lDQWdJQ0F2THlCZ2MyVndZWEpoZEc5eUxteGhjM1JKYm1SbGVHQWdhWE1nYm05MElISmxiR2xoWW14bElHTnliM056TFdKeWIzZHpaWEpjYmlBZ0lDQWdJR3hoYzNSSmJtUmxlQ0E5SUcxaGRHTm9MbWx1WkdWNElDc2diV0YwWTJoYk1GMHViR1Z1WjNSb08xeHVJQ0FnSUNBZ2FXWWdLR3hoYzNSSmJtUmxlQ0ErSUd4aGMzUk1ZWE4wU1c1a1pYZ3BJSHRjYmlBZ0lDQWdJQ0FnYjNWMGNIVjBMbkIxYzJnb2MzUnlMbk5zYVdObEtHeGhjM1JNWVhOMFNXNWtaWGdzSUcxaGRHTm9MbWx1WkdWNEtTazdYRzRnSUNBZ0lDQWdJQzh2SUVacGVDQmljbTkzYzJWeWN5QjNhRzl6WlNCZ1pYaGxZMkFnYldWMGFHOWtjeUJrYjI0bmRDQmpiMjV6YVhOMFpXNTBiSGtnY21WMGRYSnVJR0IxYm1SbFptbHVaV1JnSUdadmNseHVJQ0FnSUNBZ0lDQXZMeUJ1YjI1d1lYSjBhV05wY0dGMGFXNW5JR05oY0hSMWNtbHVaeUJuY205MWNITmNiaUFnSUNBZ0lDQWdhV1lnS0NGamIyMXdiR2xoYm5SRmVHVmpUbkJqWnlBbUppQnRZWFJqYUM1c1pXNW5kR2dnUGlBeEtTQjdYRzRnSUNBZ0lDQWdJQ0FnYldGMFkyaGJNRjB1Y21Wd2JHRmpaU2h6WlhCaGNtRjBiM0l5TENCbWRXNWpkR2x2YmlncElIdGNiaUFnSUNBZ0lDQWdJQ0FnSUdadmNpQW9kbUZ5SUdrZ1BTQXhPeUJwSUR3Z1lYSm5kVzFsYm5SekxteGxibWQwYUNBdElESTdJR2tyS3lrZ2UxeHVJQ0FnSUNBZ0lDQWdJQ0FnSUNCcFppQW9ZWEpuZFcxbGJuUnpXMmxkSUQwOVBTQjFibVJsWmlrZ2UxeHVJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lHMWhkR05vVzJsZElEMGdkVzVrWldZN1hHNGdJQ0FnSUNBZ0lDQWdJQ0FnSUgxY2JpQWdJQ0FnSUNBZ0lDQWdJSDFjYmlBZ0lDQWdJQ0FnSUNCOUtUdGNiaUFnSUNBZ0lDQWdmVnh1SUNBZ0lDQWdJQ0JwWmlBb2JXRjBZMmd1YkdWdVozUm9JRDRnTVNBbUppQnRZWFJqYUM1cGJtUmxlQ0E4SUhOMGNpNXNaVzVuZEdncElIdGNiaUFnSUNBZ0lDQWdJQ0JCY25KaGVTNXdjbTkwYjNSNWNHVXVjSFZ6YUM1aGNIQnNlU2h2ZFhSd2RYUXNJRzFoZEdOb0xuTnNhV05sS0RFcEtUdGNiaUFnSUNBZ0lDQWdmVnh1SUNBZ0lDQWdJQ0JzWVhOMFRHVnVaM1JvSUQwZ2JXRjBZMmhiTUYwdWJHVnVaM1JvTzF4dUlDQWdJQ0FnSUNCc1lYTjBUR0Z6ZEVsdVpHVjRJRDBnYkdGemRFbHVaR1Y0TzF4dUlDQWdJQ0FnSUNCcFppQW9iM1YwY0hWMExteGxibWQwYUNBK1BTQnNhVzFwZENrZ2UxeHVJQ0FnSUNBZ0lDQWdJR0p5WldGck8xeHVJQ0FnSUNBZ0lDQjlYRzRnSUNBZ0lDQjlYRzRnSUNBZ0lDQnBaaUFvYzJWd1lYSmhkRzl5TG14aGMzUkpibVJsZUNBOVBUMGdiV0YwWTJndWFXNWtaWGdwSUh0Y2JpQWdJQ0FnSUNBZ2MyVndZWEpoZEc5eUxteGhjM1JKYm1SbGVDc3JPeUF2THlCQmRtOXBaQ0JoYmlCcGJtWnBibWwwWlNCc2IyOXdYRzRnSUNBZ0lDQjlYRzRnSUNBZ2ZWeHVJQ0FnSUdsbUlDaHNZWE4wVEdGemRFbHVaR1Y0SUQwOVBTQnpkSEl1YkdWdVozUm9LU0I3WEc0Z0lDQWdJQ0JwWmlBb2JHRnpkRXhsYm1kMGFDQjhmQ0FoYzJWd1lYSmhkRzl5TG5SbGMzUW9YQ0pjSWlrcElIdGNiaUFnSUNBZ0lDQWdiM1YwY0hWMExuQjFjMmdvWENKY0lpazdYRzRnSUNBZ0lDQjlYRzRnSUNBZ2ZTQmxiSE5sSUh0Y2JpQWdJQ0FnSUc5MWRIQjFkQzV3ZFhOb0tITjBjaTV6YkdsalpTaHNZWE4wVEdGemRFbHVaR1Y0S1NrN1hHNGdJQ0FnZlZ4dUlDQWdJSEpsZEhWeWJpQnZkWFJ3ZFhRdWJHVnVaM1JvSUQ0Z2JHbHRhWFFnUHlCdmRYUndkWFF1YzJ4cFkyVW9NQ3dnYkdsdGFYUXBJRG9nYjNWMGNIVjBPMXh1SUNCOU8xeHVYRzRnSUhKbGRIVnliaUJ6Wld4bU8xeHVmU2tvS1R0Y2JseHVmU3g3ZlYwc05qcGJablZ1WTNScGIyNG9jbVZ4ZFdseVpTeHRiMlIxYkdVc1pYaHdiM0owY3lsN1hHNWNibjBzZTMxZExEYzZXMloxYm1OMGFXOXVLSEpsY1hWcGNtVXNiVzlrZFd4bExHVjRjRzl5ZEhNcGUxeHVKM1Z6WlNCemRISnBZM1FuTzF4dVhHNTJZWElnVDI1bFZtVnljMmx2YmtOdmJuTjBjbUZwYm5RZ1BTQnlaWEYxYVhKbEtDZHBibVJwZG1sa2RXRnNMMjl1WlMxMlpYSnphVzl1SnlrN1hHNWNiblpoY2lCTldWOVdSVkpUU1U5T0lEMGdKemNuTzF4dVQyNWxWbVZ5YzJsdmJrTnZibk4wY21GcGJuUW9KMlYyTFhOMGIzSmxKeXdnVFZsZlZrVlNVMGxQVGlrN1hHNWNiblpoY2lCb1lYTm9TMlY1SUQwZ0oxOWZSVlpmVTFSUFVrVmZTMFZaUUNjZ0t5Qk5XVjlXUlZKVFNVOU9PMXh1WEc1dGIyUjFiR1V1Wlhod2IzSjBjeUE5SUVWMlUzUnZjbVU3WEc1Y2JtWjFibU4wYVc5dUlFVjJVM1J2Y21Vb1pXeGxiU2tnZTF4dUlDQWdJSFpoY2lCb1lYTm9JRDBnWld4bGJWdG9ZWE5vUzJWNVhUdGNibHh1SUNBZ0lHbG1JQ2doYUdGemFDa2dlMXh1SUNBZ0lDQWdJQ0JvWVhOb0lEMGdaV3hsYlZ0b1lYTm9TMlY1WFNBOUlIdDlPMXh1SUNBZ0lIMWNibHh1SUNBZ0lISmxkSFZ5YmlCb1lYTm9PMXh1ZlZ4dVhHNTlMSHRjSW1sdVpHbDJhV1IxWVd3dmIyNWxMWFpsY25OcGIyNWNJam81ZlYwc09EcGJablZ1WTNScGIyNG9jbVZ4ZFdseVpTeHRiMlIxYkdVc1pYaHdiM0owY3lsN1hHNG9ablZ1WTNScGIyNGdLR2RzYjJKaGJDbDdYRzRuZFhObElITjBjbWxqZENjN1hHNWNiaThxWjJ4dlltRnNJSGRwYm1SdmR5d2daMnh2WW1Gc0tpOWNibHh1ZG1GeUlISnZiM1FnUFNCMGVYQmxiMllnZDJsdVpHOTNJQ0U5UFNBbmRXNWtaV1pwYm1Wa0p5QS9YRzRnSUNBZ2QybHVaRzkzSURvZ2RIbHdaVzltSUdkc2IySmhiQ0FoUFQwZ0ozVnVaR1ZtYVc1bFpDY2dQMXh1SUNBZ0lHZHNiMkpoYkNBNklIdDlPMXh1WEc1dGIyUjFiR1V1Wlhod2IzSjBjeUE5SUVsdVpHbDJhV1IxWVd3N1hHNWNibVoxYm1OMGFXOXVJRWx1WkdsMmFXUjFZV3dvYTJWNUxDQjJZV3gxWlNrZ2UxeHVJQ0FnSUdsbUlDaHJaWGtnYVc0Z2NtOXZkQ2tnZTF4dUlDQWdJQ0FnSUNCeVpYUjFjbTRnY205dmRGdHJaWGxkTzF4dUlDQWdJSDFjYmx4dUlDQWdJSEp2YjNSYmEyVjVYU0E5SUhaaGJIVmxPMXh1WEc0Z0lDQWdjbVYwZFhKdUlIWmhiSFZsTzF4dWZWeHVYRzU5S1M1allXeHNLSFJvYVhNc2RIbHdaVzltSUdkc2IySmhiQ0FoUFQwZ1hDSjFibVJsWm1sdVpXUmNJaUEvSUdkc2IySmhiQ0E2SUhSNWNHVnZaaUJ6Wld4bUlDRTlQU0JjSW5WdVpHVm1hVzVsWkZ3aUlEOGdjMlZzWmlBNklIUjVjR1Z2WmlCM2FXNWtiM2NnSVQwOUlGd2lkVzVrWldacGJtVmtYQ0lnUHlCM2FXNWtiM2NnT2lCN2ZTbGNibjBzZTMxZExEazZXMloxYm1OMGFXOXVLSEpsY1hWcGNtVXNiVzlrZFd4bExHVjRjRzl5ZEhNcGUxeHVKM1Z6WlNCemRISnBZM1FuTzF4dVhHNTJZWElnU1c1a2FYWnBaSFZoYkNBOUlISmxjWFZwY21Vb0p5NHZhVzVrWlhndWFuTW5LVHRjYmx4dWJXOWtkV3hsTG1WNGNHOXlkSE1nUFNCUGJtVldaWEp6YVc5dU8xeHVYRzVtZFc1amRHbHZiaUJQYm1WV1pYSnphVzl1S0cxdlpIVnNaVTVoYldVc0lIWmxjbk5wYjI0c0lHUmxabUYxYkhSV1lXeDFaU2tnZTF4dUlDQWdJSFpoY2lCclpYa2dQU0FuWDE5SlRrUkpWa2xFVlVGTVgwOU9SVjlXUlZKVFNVOU9YeWNnS3lCdGIyUjFiR1ZPWVcxbE8xeHVJQ0FnSUhaaGNpQmxibVp2Y21ObFMyVjVJRDBnYTJWNUlDc2dKMTlGVGtaUFVrTkZYMU5KVGtkTVJWUlBUaWM3WEc1Y2JpQWdJQ0IyWVhJZ2RtVnljMmx2YmxaaGJIVmxJRDBnU1c1a2FYWnBaSFZoYkNobGJtWnZjbU5sUzJWNUxDQjJaWEp6YVc5dUtUdGNibHh1SUNBZ0lHbG1JQ2gyWlhKemFXOXVWbUZzZFdVZ0lUMDlJSFpsY25OcGIyNHBJSHRjYmlBZ0lDQWdJQ0FnZEdoeWIzY2dibVYzSUVWeWNtOXlLQ2REWVc0Z2IyNXNlU0JvWVhabElHOXVaU0JqYjNCNUlHOW1JQ2NnSzF4dUlDQWdJQ0FnSUNBZ0lDQWdiVzlrZFd4bFRtRnRaU0FySUNjdVhGeHVKeUFyWEc0Z0lDQWdJQ0FnSUNBZ0lDQW5XVzkxSUdGc2NtVmhaSGtnYUdGMlpTQjJaWEp6YVc5dUlDY2dLeUIyWlhKemFXOXVWbUZzZFdVZ0sxeHVJQ0FnSUNBZ0lDQWdJQ0FnSnlCcGJuTjBZV3hzWldRdVhGeHVKeUFyWEc0Z0lDQWdJQ0FnSUNBZ0lDQW5WR2hwY3lCdFpXRnVjeUI1YjNVZ1kyRnVibTkwSUdsdWMzUmhiR3dnZG1WeWMybHZiaUFuSUNzZ2RtVnljMmx2YmlrN1hHNGdJQ0FnZlZ4dVhHNGdJQ0FnY21WMGRYSnVJRWx1WkdsMmFXUjFZV3dvYTJWNUxDQmtaV1poZFd4MFZtRnNkV1VwTzF4dWZWeHVYRzU5TEh0Y0lpNHZhVzVrWlhndWFuTmNJam80ZlYwc01UQTZXMloxYm1OMGFXOXVLSEpsY1hWcGNtVXNiVzlrZFd4bExHVjRjRzl5ZEhNcGUxeHVLR1oxYm1OMGFXOXVJQ2huYkc5aVlXd3BlMXh1ZG1GeUlIUnZjRXhsZG1Wc0lEMGdkSGx3Wlc5bUlHZHNiMkpoYkNBaFBUMGdKM1Z1WkdWbWFXNWxaQ2NnUHlCbmJHOWlZV3dnT2x4dUlDQWdJSFI1Y0dWdlppQjNhVzVrYjNjZ0lUMDlJQ2QxYm1SbFptbHVaV1FuSUQ4Z2QybHVaRzkzSURvZ2UzMWNiblpoY2lCdGFXNUViMk1nUFNCeVpYRjFhWEpsS0NkdGFXNHRaRzlqZFcxbGJuUW5LVHRjYmx4dWFXWWdLSFI1Y0dWdlppQmtiMk4xYldWdWRDQWhQVDBnSjNWdVpHVm1hVzVsWkNjcElIdGNiaUFnSUNCdGIyUjFiR1V1Wlhod2IzSjBjeUE5SUdSdlkzVnRaVzUwTzF4dWZTQmxiSE5sSUh0Y2JpQWdJQ0IyWVhJZ1pHOWpZM2tnUFNCMGIzQk1aWFpsYkZzblgxOUhURTlDUVV4ZlJFOURWVTFGVGxSZlEwRkRTRVZBTkNkZE8xeHVYRzRnSUNBZ2FXWWdLQ0ZrYjJOamVTa2dlMXh1SUNBZ0lDQWdJQ0JrYjJOamVTQTlJSFJ2Y0V4bGRtVnNXeWRmWDBkTVQwSkJURjlFVDBOVlRVVk9WRjlEUVVOSVJVQTBKMTBnUFNCdGFXNUViMk03WEc0Z0lDQWdmVnh1WEc0Z0lDQWdiVzlrZFd4bExtVjRjRzl5ZEhNZ1BTQmtiMk5qZVR0Y2JuMWNibHh1ZlNrdVkyRnNiQ2gwYUdsekxIUjVjR1Z2WmlCbmJHOWlZV3dnSVQwOUlGd2lkVzVrWldacGJtVmtYQ0lnUHlCbmJHOWlZV3dnT2lCMGVYQmxiMllnYzJWc1ppQWhQVDBnWENKMWJtUmxabWx1WldSY0lpQS9JSE5sYkdZZ09pQjBlWEJsYjJZZ2QybHVaRzkzSUNFOVBTQmNJblZ1WkdWbWFXNWxaRndpSUQ4Z2QybHVaRzkzSURvZ2UzMHBYRzU5TEh0Y0ltMXBiaTFrYjJOMWJXVnVkRndpT2paOVhTd3hNVHBiWm5WdVkzUnBiMjRvY21WeGRXbHlaU3h0YjJSMWJHVXNaWGh3YjNKMGN5bDdYRzVjSW5WelpTQnpkSEpwWTNSY0lqdGNibHh1Ylc5a2RXeGxMbVY0Y0c5eWRITWdQU0JtZFc1amRHbHZiaUJwYzA5aWFtVmpkQ2g0S1NCN1hHNWNkSEpsZEhWeWJpQjBlWEJsYjJZZ2VDQTlQVDBnWENKdlltcGxZM1JjSWlBbUppQjRJQ0U5UFNCdWRXeHNPMXh1ZlR0Y2JseHVmU3g3ZlYwc01USTZXMloxYm1OMGFXOXVLSEpsY1hWcGNtVXNiVzlrZFd4bExHVjRjRzl5ZEhNcGUxeHVkbUZ5SUc1aGRHbDJaVWx6UVhKeVlYa2dQU0JCY25KaGVTNXBjMEZ5Y21GNVhHNTJZWElnZEc5VGRISnBibWNnUFNCUFltcGxZM1F1Y0hKdmRHOTBlWEJsTG5SdlUzUnlhVzVuWEc1Y2JtMXZaSFZzWlM1bGVIQnZjblJ6SUQwZ2JtRjBhWFpsU1hOQmNuSmhlU0I4ZkNCcGMwRnljbUY1WEc1Y2JtWjFibU4wYVc5dUlHbHpRWEp5WVhrb2IySnFLU0I3WEc0Z0lDQWdjbVYwZFhKdUlIUnZVM1J5YVc1bkxtTmhiR3dvYjJKcUtTQTlQVDBnWENKYmIySnFaV04wSUVGeWNtRjVYVndpWEc1OVhHNWNibjBzZTMxZExERXpPbHRtZFc1amRHbHZiaWh5WlhGMWFYSmxMRzF2WkhWc1pTeGxlSEJ2Y25SektYdGNiblpoY2lCd1lYUmphQ0E5SUhKbGNYVnBjbVVvWENJdUwzWmtiMjB2Y0dGMFkyZ3Vhbk5jSWlsY2JseHViVzlrZFd4bExtVjRjRzl5ZEhNZ1BTQndZWFJqYUZ4dVhHNTlMSHRjSWk0dmRtUnZiUzl3WVhSamFDNXFjMXdpT2pFNGZWMHNNVFE2VzJaMWJtTjBhVzl1S0hKbGNYVnBjbVVzYlc5a2RXeGxMR1Y0Y0c5eWRITXBlMXh1ZG1GeUlHbHpUMkpxWldOMElEMGdjbVZ4ZFdseVpTaGNJbWx6TFc5aWFtVmpkRndpS1Z4dWRtRnlJR2x6U0c5dmF5QTlJSEpsY1hWcGNtVW9YQ0l1TGk5MmJtOWtaUzlwY3kxMmFHOXZheTVxYzF3aUtWeHVYRzV0YjJSMWJHVXVaWGh3YjNKMGN5QTlJR0Z3Y0d4NVVISnZjR1Z5ZEdsbGMxeHVYRzVtZFc1amRHbHZiaUJoY0hCc2VWQnliM0JsY25ScFpYTW9ibTlrWlN3Z2NISnZjSE1zSUhCeVpYWnBiM1Z6S1NCN1hHNGdJQ0FnWm05eUlDaDJZWElnY0hKdmNFNWhiV1VnYVc0Z2NISnZjSE1wSUh0Y2JpQWdJQ0FnSUNBZ2RtRnlJSEJ5YjNCV1lXeDFaU0E5SUhCeWIzQnpXM0J5YjNCT1lXMWxYVnh1WEc0Z0lDQWdJQ0FnSUdsbUlDaHdjbTl3Vm1Gc2RXVWdQVDA5SUhWdVpHVm1hVzVsWkNrZ2UxeHVJQ0FnSUNBZ0lDQWdJQ0FnY21WdGIzWmxVSEp2Y0dWeWRIa29ibTlrWlN3Z2NISnZjRTVoYldVc0lIQnliM0JXWVd4MVpTd2djSEpsZG1sdmRYTXBPMXh1SUNBZ0lDQWdJQ0I5SUdWc2MyVWdhV1lnS0dselNHOXZheWh3Y205d1ZtRnNkV1VwS1NCN1hHNGdJQ0FnSUNBZ0lDQWdJQ0J5WlcxdmRtVlFjbTl3WlhKMGVTaHViMlJsTENCd2NtOXdUbUZ0WlN3Z2NISnZjRlpoYkhWbExDQndjbVYyYVc5MWN5bGNiaUFnSUNBZ0lDQWdJQ0FnSUdsbUlDaHdjbTl3Vm1Gc2RXVXVhRzl2YXlrZ2UxeHVJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lIQnliM0JXWVd4MVpTNW9iMjlyS0c1dlpHVXNYRzRnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUhCeWIzQk9ZVzFsTEZ4dUlDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQndjbVYyYVc5MWN5QS9JSEJ5WlhacGIzVnpXM0J5YjNCT1lXMWxYU0E2SUhWdVpHVm1hVzVsWkNsY2JpQWdJQ0FnSUNBZ0lDQWdJSDFjYmlBZ0lDQWdJQ0FnZlNCbGJITmxJSHRjYmlBZ0lDQWdJQ0FnSUNBZ0lHbG1JQ2hwYzA5aWFtVmpkQ2h3Y205d1ZtRnNkV1VwS1NCN1hHNGdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ2NHRjBZMmhQWW1wbFkzUW9ibTlrWlN3Z2NISnZjSE1zSUhCeVpYWnBiM1Z6TENCd2NtOXdUbUZ0WlN3Z2NISnZjRlpoYkhWbEtUdGNiaUFnSUNBZ0lDQWdJQ0FnSUgwZ1pXeHpaU0I3WEc0Z0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnYm05a1pWdHdjbTl3VG1GdFpWMGdQU0J3Y205d1ZtRnNkV1ZjYmlBZ0lDQWdJQ0FnSUNBZ0lIMWNiaUFnSUNBZ0lDQWdmVnh1SUNBZ0lIMWNibjFjYmx4dVpuVnVZM1JwYjI0Z2NtVnRiM1psVUhKdmNHVnlkSGtvYm05a1pTd2djSEp2Y0U1aGJXVXNJSEJ5YjNCV1lXeDFaU3dnY0hKbGRtbHZkWE1wSUh0Y2JpQWdJQ0JwWmlBb2NISmxkbWx2ZFhNcElIdGNiaUFnSUNBZ0lDQWdkbUZ5SUhCeVpYWnBiM1Z6Vm1Gc2RXVWdQU0J3Y21WMmFXOTFjMXR3Y205d1RtRnRaVjFjYmx4dUlDQWdJQ0FnSUNCcFppQW9JV2x6U0c5dmF5aHdjbVYyYVc5MWMxWmhiSFZsS1NrZ2UxeHVJQ0FnSUNBZ0lDQWdJQ0FnYVdZZ0tIQnliM0JPWVcxbElEMDlQU0JjSW1GMGRISnBZblYwWlhOY0lpa2dlMXh1SUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJR1p2Y2lBb2RtRnlJR0YwZEhKT1lXMWxJR2x1SUhCeVpYWnBiM1Z6Vm1Gc2RXVXBJSHRjYmlBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ2JtOWtaUzV5WlcxdmRtVkJkSFJ5YVdKMWRHVW9ZWFIwY2s1aGJXVXBYRzRnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdmVnh1SUNBZ0lDQWdJQ0FnSUNBZ2ZTQmxiSE5sSUdsbUlDaHdjbTl3VG1GdFpTQTlQVDBnWENKemRIbHNaVndpS1NCN1hHNGdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ1ptOXlJQ2gyWVhJZ2FTQnBiaUJ3Y21WMmFXOTFjMVpoYkhWbEtTQjdYRzRnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUc1dlpHVXVjM1I1YkdWYmFWMGdQU0JjSWx3aVhHNGdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ2ZWeHVJQ0FnSUNBZ0lDQWdJQ0FnZlNCbGJITmxJR2xtSUNoMGVYQmxiMllnY0hKbGRtbHZkWE5XWVd4MVpTQTlQVDBnWENKemRISnBibWRjSWlrZ2UxeHVJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lHNXZaR1ZiY0hKdmNFNWhiV1ZkSUQwZ1hDSmNJbHh1SUNBZ0lDQWdJQ0FnSUNBZ2ZTQmxiSE5sSUh0Y2JpQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNCdWIyUmxXM0J5YjNCT1lXMWxYU0E5SUc1MWJHeGNiaUFnSUNBZ0lDQWdJQ0FnSUgxY2JpQWdJQ0FnSUNBZ2ZTQmxiSE5sSUdsbUlDaHdjbVYyYVc5MWMxWmhiSFZsTG5WdWFHOXZheWtnZTF4dUlDQWdJQ0FnSUNBZ0lDQWdjSEpsZG1sdmRYTldZV3gxWlM1MWJtaHZiMnNvYm05a1pTd2djSEp2Y0U1aGJXVXNJSEJ5YjNCV1lXeDFaU2xjYmlBZ0lDQWdJQ0FnZlZ4dUlDQWdJSDFjYm4xY2JseHVablZ1WTNScGIyNGdjR0YwWTJoUFltcGxZM1FvYm05a1pTd2djSEp2Y0hNc0lIQnlaWFpwYjNWekxDQndjbTl3VG1GdFpTd2djSEp2Y0ZaaGJIVmxLU0I3WEc0Z0lDQWdkbUZ5SUhCeVpYWnBiM1Z6Vm1Gc2RXVWdQU0J3Y21WMmFXOTFjeUEvSUhCeVpYWnBiM1Z6VzNCeWIzQk9ZVzFsWFNBNklIVnVaR1ZtYVc1bFpGeHVYRzRnSUNBZ0x5OGdVMlYwSUdGMGRISnBZblYwWlhOY2JpQWdJQ0JwWmlBb2NISnZjRTVoYldVZ1BUMDlJRndpWVhSMGNtbGlkWFJsYzF3aUtTQjdYRzRnSUNBZ0lDQWdJR1p2Y2lBb2RtRnlJR0YwZEhKT1lXMWxJR2x1SUhCeWIzQldZV3gxWlNrZ2UxeHVJQ0FnSUNBZ0lDQWdJQ0FnZG1GeUlHRjBkSEpXWVd4MVpTQTlJSEJ5YjNCV1lXeDFaVnRoZEhSeVRtRnRaVjFjYmx4dUlDQWdJQ0FnSUNBZ0lDQWdhV1lnS0dGMGRISldZV3gxWlNBOVBUMGdkVzVrWldacGJtVmtLU0I3WEc0Z0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnYm05a1pTNXlaVzF2ZG1WQmRIUnlhV0oxZEdVb1lYUjBjazVoYldVcFhHNGdJQ0FnSUNBZ0lDQWdJQ0I5SUdWc2MyVWdlMXh1SUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJRzV2WkdVdWMyVjBRWFIwY21saWRYUmxLR0YwZEhKT1lXMWxMQ0JoZEhSeVZtRnNkV1VwWEc0Z0lDQWdJQ0FnSUNBZ0lDQjlYRzRnSUNBZ0lDQWdJSDFjYmx4dUlDQWdJQ0FnSUNCeVpYUjFjbTVjYmlBZ0lDQjlYRzVjYmlBZ0lDQnBaaWh3Y21WMmFXOTFjMVpoYkhWbElDWW1JR2x6VDJKcVpXTjBLSEJ5WlhacGIzVnpWbUZzZFdVcElDWW1YRzRnSUNBZ0lDQWdJR2RsZEZCeWIzUnZkSGx3WlNod2NtVjJhVzkxYzFaaGJIVmxLU0FoUFQwZ1oyVjBVSEp2ZEc5MGVYQmxLSEJ5YjNCV1lXeDFaU2twSUh0Y2JpQWdJQ0FnSUNBZ2JtOWtaVnR3Y205d1RtRnRaVjBnUFNCd2NtOXdWbUZzZFdWY2JpQWdJQ0FnSUNBZ2NtVjBkWEp1WEc0Z0lDQWdmVnh1WEc0Z0lDQWdhV1lnS0NGcGMwOWlhbVZqZENodWIyUmxXM0J5YjNCT1lXMWxYU2twSUh0Y2JpQWdJQ0FnSUNBZ2JtOWtaVnR3Y205d1RtRnRaVjBnUFNCN2ZWeHVJQ0FnSUgxY2JseHVJQ0FnSUhaaGNpQnlaWEJzWVdObGNpQTlJSEJ5YjNCT1lXMWxJRDA5UFNCY0luTjBlV3hsWENJZ1B5QmNJbHdpSURvZ2RXNWtaV1pwYm1Wa1hHNWNiaUFnSUNCbWIzSWdLSFpoY2lCcklHbHVJSEJ5YjNCV1lXeDFaU2tnZTF4dUlDQWdJQ0FnSUNCMllYSWdkbUZzZFdVZ1BTQndjbTl3Vm1Gc2RXVmJhMTFjYmlBZ0lDQWdJQ0FnYm05a1pWdHdjbTl3VG1GdFpWMWJhMTBnUFNBb2RtRnNkV1VnUFQwOUlIVnVaR1ZtYVc1bFpDa2dQeUJ5WlhCc1lXTmxjaUE2SUhaaGJIVmxYRzRnSUNBZ2ZWeHVmVnh1WEc1bWRXNWpkR2x2YmlCblpYUlFjbTkwYjNSNWNHVW9kbUZzZFdVcElIdGNiaUFnSUNCcFppQW9UMkpxWldOMExtZGxkRkJ5YjNSdmRIbHdaVTltS1NCN1hHNGdJQ0FnSUNBZ0lISmxkSFZ5YmlCUFltcGxZM1F1WjJWMFVISnZkRzkwZVhCbFQyWW9kbUZzZFdVcFhHNGdJQ0FnZlNCbGJITmxJR2xtSUNoMllXeDFaUzVmWDNCeWIzUnZYMThwSUh0Y2JpQWdJQ0FnSUNBZ2NtVjBkWEp1SUhaaGJIVmxMbDlmY0hKdmRHOWZYMXh1SUNBZ0lIMGdaV3h6WlNCcFppQW9kbUZzZFdVdVkyOXVjM1J5ZFdOMGIzSXBJSHRjYmlBZ0lDQWdJQ0FnY21WMGRYSnVJSFpoYkhWbExtTnZibk4wY25WamRHOXlMbkJ5YjNSdmRIbHdaVnh1SUNBZ0lIMWNibjFjYmx4dWZTeDdYQ0l1TGk5MmJtOWtaUzlwY3kxMmFHOXZheTVxYzF3aU9qSTJMRndpYVhNdGIySnFaV04wWENJNk1URjlYU3d4TlRwYlpuVnVZM1JwYjI0b2NtVnhkV2x5WlN4dGIyUjFiR1VzWlhod2IzSjBjeWw3WEc1MllYSWdaRzlqZFcxbGJuUWdQU0J5WlhGMWFYSmxLRndpWjJ4dlltRnNMMlJ2WTNWdFpXNTBYQ0lwWEc1Y2JuWmhjaUJoY0hCc2VWQnliM0JsY25ScFpYTWdQU0J5WlhGMWFYSmxLRndpTGk5aGNIQnNlUzF3Y205d1pYSjBhV1Z6WENJcFhHNWNiblpoY2lCcGMxWk9iMlJsSUQwZ2NtVnhkV2x5WlNoY0lpNHVMM1p1YjJSbEwybHpMWFp1YjJSbExtcHpYQ0lwWEc1MllYSWdhWE5XVkdWNGRDQTlJSEpsY1hWcGNtVW9YQ0l1TGk5MmJtOWtaUzlwY3kxMmRHVjRkQzVxYzF3aUtWeHVkbUZ5SUdselYybGtaMlYwSUQwZ2NtVnhkV2x5WlNoY0lpNHVMM1p1YjJSbEwybHpMWGRwWkdkbGRDNXFjMXdpS1Z4dWRtRnlJR2hoYm1Sc1pWUm9kVzVySUQwZ2NtVnhkV2x5WlNoY0lpNHVMM1p1YjJSbEwyaGhibVJzWlMxMGFIVnVheTVxYzF3aUtWeHVYRzV0YjJSMWJHVXVaWGh3YjNKMGN5QTlJR055WldGMFpVVnNaVzFsYm5SY2JseHVablZ1WTNScGIyNGdZM0psWVhSbFJXeGxiV1Z1ZENoMmJtOWtaU3dnYjNCMGN5a2dlMXh1SUNBZ0lIWmhjaUJrYjJNZ1BTQnZjSFJ6SUQ4Z2IzQjBjeTVrYjJOMWJXVnVkQ0I4ZkNCa2IyTjFiV1Z1ZENBNklHUnZZM1Z0Wlc1MFhHNGdJQ0FnZG1GeUlIZGhjbTRnUFNCdmNIUnpJRDhnYjNCMGN5NTNZWEp1SURvZ2JuVnNiRnh1WEc0Z0lDQWdkbTV2WkdVZ1BTQm9ZVzVrYkdWVWFIVnVheWgyYm05a1pTa3VZVnh1WEc0Z0lDQWdhV1lnS0dselYybGtaMlYwS0hadWIyUmxLU2tnZTF4dUlDQWdJQ0FnSUNCeVpYUjFjbTRnZG01dlpHVXVhVzVwZENncFhHNGdJQ0FnZlNCbGJITmxJR2xtSUNocGMxWlVaWGgwS0hadWIyUmxLU2tnZTF4dUlDQWdJQ0FnSUNCeVpYUjFjbTRnWkc5akxtTnlaV0YwWlZSbGVIUk9iMlJsS0hadWIyUmxMblJsZUhRcFhHNGdJQ0FnZlNCbGJITmxJR2xtSUNnaGFYTldUbTlrWlNoMmJtOWtaU2twSUh0Y2JpQWdJQ0FnSUNBZ2FXWWdLSGRoY200cElIdGNiaUFnSUNBZ0lDQWdJQ0FnSUhkaGNtNG9YQ0pKZEdWdElHbHpJRzV2ZENCaElIWmhiR2xrSUhacGNuUjFZV3dnWkc5dElHNXZaR1ZjSWl3Z2RtNXZaR1VwWEc0Z0lDQWdJQ0FnSUgxY2JpQWdJQ0FnSUNBZ2NtVjBkWEp1SUc1MWJHeGNiaUFnSUNCOVhHNWNiaUFnSUNCMllYSWdibTlrWlNBOUlDaDJibTlrWlM1dVlXMWxjM0JoWTJVZ1BUMDlJRzUxYkd3cElEOWNiaUFnSUNBZ0lDQWdaRzlqTG1OeVpXRjBaVVZzWlcxbGJuUW9kbTV2WkdVdWRHRm5UbUZ0WlNrZ09seHVJQ0FnSUNBZ0lDQmtiMk11WTNKbFlYUmxSV3hsYldWdWRFNVRLSFp1YjJSbExtNWhiV1Z6Y0dGalpTd2dkbTV2WkdVdWRHRm5UbUZ0WlNsY2JseHVJQ0FnSUhaaGNpQndjbTl3Y3lBOUlIWnViMlJsTG5CeWIzQmxjblJwWlhOY2JpQWdJQ0JoY0hCc2VWQnliM0JsY25ScFpYTW9ibTlrWlN3Z2NISnZjSE1wWEc1Y2JpQWdJQ0IyWVhJZ1kyaHBiR1J5Wlc0Z1BTQjJibTlrWlM1amFHbHNaSEpsYmx4dVhHNGdJQ0FnWm05eUlDaDJZWElnYVNBOUlEQTdJR2tnUENCamFHbHNaSEpsYmk1c1pXNW5kR2c3SUdrckt5a2dlMXh1SUNBZ0lDQWdJQ0IyWVhJZ1kyaHBiR1JPYjJSbElEMGdZM0psWVhSbFJXeGxiV1Z1ZENoamFHbHNaSEpsYmx0cFhTd2diM0IwY3lsY2JpQWdJQ0FnSUNBZ2FXWWdLR05vYVd4a1RtOWtaU2tnZTF4dUlDQWdJQ0FnSUNBZ0lDQWdibTlrWlM1aGNIQmxibVJEYUdsc1pDaGphR2xzWkU1dlpHVXBYRzRnSUNBZ0lDQWdJSDFjYmlBZ0lDQjlYRzVjYmlBZ0lDQnlaWFIxY200Z2JtOWtaVnh1ZlZ4dVhHNTlMSHRjSWk0dUwzWnViMlJsTDJoaGJtUnNaUzEwYUhWdWF5NXFjMXdpT2pJMExGd2lMaTR2ZG01dlpHVXZhWE10ZG01dlpHVXVhbk5jSWpveU55eGNJaTR1TDNadWIyUmxMMmx6TFhaMFpYaDBMbXB6WENJNk1qZ3NYQ0l1TGk5MmJtOWtaUzlwY3kxM2FXUm5aWFF1YW5OY0lqb3lPU3hjSWk0dllYQndiSGt0Y0hKdmNHVnlkR2xsYzF3aU9qRTBMRndpWjJ4dlltRnNMMlJ2WTNWdFpXNTBYQ0k2TVRCOVhTd3hOanBiWm5WdVkzUnBiMjRvY21WeGRXbHlaU3h0YjJSMWJHVXNaWGh3YjNKMGN5bDdYRzR2THlCTllYQnpJR0VnZG1seWRIVmhiQ0JFVDAwZ2RISmxaU0J2Ym5SdklHRWdjbVZoYkNCRVQwMGdkSEpsWlNCcGJpQmhiaUJsWm1acFkybGxiblFnYldGdWJtVnlMbHh1THk4Z1YyVWdaRzl1SjNRZ2QyRnVkQ0IwYnlCeVpXRmtJR0ZzYkNCdlppQjBhR1VnUkU5TklHNXZaR1Z6SUdsdUlIUm9aU0IwY21WbElITnZJSGRsSUhWelpWeHVMeThnZEdobElHbHVMVzl5WkdWeUlIUnlaV1VnYVc1a1pYaHBibWNnZEc4Z1pXeHBiV2x1WVhSbElISmxZM1Z5YzJsdmJpQmtiM2R1SUdObGNuUmhhVzRnWW5KaGJtTm9aWE11WEc0dkx5QlhaU0J2Ym14NUlISmxZM1Z5YzJVZ2FXNTBieUJoSUVSUFRTQnViMlJsSUdsbUlIZGxJR3R1YjNjZ2RHaGhkQ0JwZENCamIyNTBZV2x1Y3lCaElHTm9hV3hrSUc5bVhHNHZMeUJwYm5SbGNtVnpkQzVjYmx4dWRtRnlJRzV2UTJocGJHUWdQU0I3ZlZ4dVhHNXRiMlIxYkdVdVpYaHdiM0owY3lBOUlHUnZiVWx1WkdWNFhHNWNibVoxYm1OMGFXOXVJR1J2YlVsdVpHVjRLSEp2YjNST2IyUmxMQ0IwY21WbExDQnBibVJwWTJWekxDQnViMlJsY3lrZ2UxeHVJQ0FnSUdsbUlDZ2hhVzVrYVdObGN5QjhmQ0JwYm1ScFkyVnpMbXhsYm1kMGFDQTlQVDBnTUNrZ2UxeHVJQ0FnSUNBZ0lDQnlaWFIxY200Z2UzMWNiaUFnSUNCOUlHVnNjMlVnZTF4dUlDQWdJQ0FnSUNCcGJtUnBZMlZ6TG5OdmNuUW9ZWE5qWlc1a2FXNW5LVnh1SUNBZ0lDQWdJQ0J5WlhSMWNtNGdjbVZqZFhKelpTaHliMjkwVG05a1pTd2dkSEpsWlN3Z2FXNWthV05sY3l3Z2JtOWtaWE1zSURBcFhHNGdJQ0FnZlZ4dWZWeHVYRzVtZFc1amRHbHZiaUJ5WldOMWNuTmxLSEp2YjNST2IyUmxMQ0IwY21WbExDQnBibVJwWTJWekxDQnViMlJsY3l3Z2NtOXZkRWx1WkdWNEtTQjdYRzRnSUNBZ2JtOWtaWE1nUFNCdWIyUmxjeUI4ZkNCN2ZWeHVYRzVjYmlBZ0lDQnBaaUFvY205dmRFNXZaR1VwSUh0Y2JpQWdJQ0FnSUNBZ2FXWWdLR2x1WkdWNFNXNVNZVzVuWlNocGJtUnBZMlZ6TENCeWIyOTBTVzVrWlhnc0lISnZiM1JKYm1SbGVDa3BJSHRjYmlBZ0lDQWdJQ0FnSUNBZ0lHNXZaR1Z6VzNKdmIzUkpibVJsZUYwZ1BTQnliMjkwVG05a1pWeHVJQ0FnSUNBZ0lDQjlYRzVjYmlBZ0lDQWdJQ0FnZG1GeUlIWkRhR2xzWkhKbGJpQTlJSFJ5WldVdVkyaHBiR1J5Wlc1Y2JseHVJQ0FnSUNBZ0lDQnBaaUFvZGtOb2FXeGtjbVZ1S1NCN1hHNWNiaUFnSUNBZ0lDQWdJQ0FnSUhaaGNpQmphR2xzWkU1dlpHVnpJRDBnY205dmRFNXZaR1V1WTJocGJHUk9iMlJsYzF4dVhHNGdJQ0FnSUNBZ0lDQWdJQ0JtYjNJZ0tIWmhjaUJwSUQwZ01Ec2dhU0E4SUhSeVpXVXVZMmhwYkdSeVpXNHViR1Z1WjNSb095QnBLeXNwSUh0Y2JpQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNCeWIyOTBTVzVrWlhnZ0t6MGdNVnh1WEc0Z0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnZG1GeUlIWkRhR2xzWkNBOUlIWkRhR2xzWkhKbGJsdHBYU0I4ZkNCdWIwTm9hV3hrWEc0Z0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnZG1GeUlHNWxlSFJKYm1SbGVDQTlJSEp2YjNSSmJtUmxlQ0FySUNoMlEyaHBiR1F1WTI5MWJuUWdmSHdnTUNsY2JseHVJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDOHZJSE5yYVhBZ2NtVmpkWEp6YVc5dUlHUnZkMjRnZEdobElIUnlaV1VnYVdZZ2RHaGxjbVVnWVhKbElHNXZJRzV2WkdWeklHUnZkMjRnYUdWeVpWeHVJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lHbG1JQ2hwYm1SbGVFbHVVbUZ1WjJVb2FXNWthV05sY3l3Z2NtOXZkRWx1WkdWNExDQnVaWGgwU1c1a1pYZ3BLU0I3WEc0Z0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lISmxZM1Z5YzJVb1kyaHBiR1JPYjJSbGMxdHBYU3dnZGtOb2FXeGtMQ0JwYm1ScFkyVnpMQ0J1YjJSbGN5d2djbTl2ZEVsdVpHVjRLVnh1SUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJSDFjYmx4dUlDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUhKdmIzUkpibVJsZUNBOUlHNWxlSFJKYm1SbGVGeHVJQ0FnSUNBZ0lDQWdJQ0FnZlZ4dUlDQWdJQ0FnSUNCOVhHNGdJQ0FnZlZ4dVhHNGdJQ0FnY21WMGRYSnVJRzV2WkdWelhHNTlYRzVjYmk4dklFSnBibUZ5ZVNCelpXRnlZMmdnWm05eUlHRnVJR2x1WkdWNElHbHVJSFJvWlNCcGJuUmxjblpoYkNCYmJHVm1kQ3dnY21sbmFIUmRYRzVtZFc1amRHbHZiaUJwYm1SbGVFbHVVbUZ1WjJVb2FXNWthV05sY3l3Z2JHVm1kQ3dnY21sbmFIUXBJSHRjYmlBZ0lDQnBaaUFvYVc1a2FXTmxjeTVzWlc1bmRHZ2dQVDA5SURBcElIdGNiaUFnSUNBZ0lDQWdjbVYwZFhKdUlHWmhiSE5sWEc0Z0lDQWdmVnh1WEc0Z0lDQWdkbUZ5SUcxcGJrbHVaR1Y0SUQwZ01GeHVJQ0FnSUhaaGNpQnRZWGhKYm1SbGVDQTlJR2x1WkdsalpYTXViR1Z1WjNSb0lDMGdNVnh1SUNBZ0lIWmhjaUJqZFhKeVpXNTBTVzVrWlhoY2JpQWdJQ0IyWVhJZ1kzVnljbVZ1ZEVsMFpXMWNibHh1SUNBZ0lIZG9hV3hsSUNodGFXNUpibVJsZUNBOFBTQnRZWGhKYm1SbGVDa2dlMXh1SUNBZ0lDQWdJQ0JqZFhKeVpXNTBTVzVrWlhnZ1BTQW9LRzFoZUVsdVpHVjRJQ3NnYldsdVNXNWtaWGdwSUM4Z01pa2dQajRnTUZ4dUlDQWdJQ0FnSUNCamRYSnlaVzUwU1hSbGJTQTlJR2x1WkdsalpYTmJZM1Z5Y21WdWRFbHVaR1Y0WFZ4dVhHNGdJQ0FnSUNBZ0lHbG1JQ2h0YVc1SmJtUmxlQ0E5UFQwZ2JXRjRTVzVrWlhncElIdGNiaUFnSUNBZ0lDQWdJQ0FnSUhKbGRIVnliaUJqZFhKeVpXNTBTWFJsYlNBK1BTQnNaV1owSUNZbUlHTjFjbkpsYm5SSmRHVnRJRHc5SUhKcFoyaDBYRzRnSUNBZ0lDQWdJSDBnWld4elpTQnBaaUFvWTNWeWNtVnVkRWwwWlcwZ1BDQnNaV1owS1NCN1hHNGdJQ0FnSUNBZ0lDQWdJQ0J0YVc1SmJtUmxlQ0E5SUdOMWNuSmxiblJKYm1SbGVDQXJJREZjYmlBZ0lDQWdJQ0FnZlNCbGJITmxJQ0JwWmlBb1kzVnljbVZ1ZEVsMFpXMGdQaUJ5YVdkb2RDa2dlMXh1SUNBZ0lDQWdJQ0FnSUNBZ2JXRjRTVzVrWlhnZ1BTQmpkWEp5Wlc1MFNXNWtaWGdnTFNBeFhHNGdJQ0FnSUNBZ0lIMGdaV3h6WlNCN1hHNGdJQ0FnSUNBZ0lDQWdJQ0J5WlhSMWNtNGdkSEoxWlZ4dUlDQWdJQ0FnSUNCOVhHNGdJQ0FnZlZ4dVhHNGdJQ0FnY21WMGRYSnVJR1poYkhObE8xeHVmVnh1WEc1bWRXNWpkR2x2YmlCaGMyTmxibVJwYm1jb1lTd2dZaWtnZTF4dUlDQWdJSEpsZEhWeWJpQmhJRDRnWWlBL0lERWdPaUF0TVZ4dWZWeHVYRzU5TEh0OVhTd3hOenBiWm5WdVkzUnBiMjRvY21WeGRXbHlaU3h0YjJSMWJHVXNaWGh3YjNKMGN5bDdYRzUyWVhJZ1lYQndiSGxRY205d1pYSjBhV1Z6SUQwZ2NtVnhkV2x5WlNoY0lpNHZZWEJ3YkhrdGNISnZjR1Z5ZEdsbGMxd2lLVnh1WEc1MllYSWdhWE5YYVdSblpYUWdQU0J5WlhGMWFYSmxLRndpTGk0dmRtNXZaR1V2YVhNdGQybGtaMlYwTG1welhDSXBYRzUyWVhJZ1ZsQmhkR05vSUQwZ2NtVnhkV2x5WlNoY0lpNHVMM1p1YjJSbEwzWndZWFJqYUM1cWMxd2lLVnh1WEc1MllYSWdkWEJrWVhSbFYybGtaMlYwSUQwZ2NtVnhkV2x5WlNoY0lpNHZkWEJrWVhSbExYZHBaR2RsZEZ3aUtWeHVYRzV0YjJSMWJHVXVaWGh3YjNKMGN5QTlJR0Z3Y0d4NVVHRjBZMmhjYmx4dVpuVnVZM1JwYjI0Z1lYQndiSGxRWVhSamFDaDJjR0YwWTJnc0lHUnZiVTV2WkdVc0lISmxibVJsY2s5d2RHbHZibk1wSUh0Y2JpQWdJQ0IyWVhJZ2RIbHdaU0E5SUhad1lYUmphQzUwZVhCbFhHNGdJQ0FnZG1GeUlIWk9iMlJsSUQwZ2RuQmhkR05vTG5aT2IyUmxYRzRnSUNBZ2RtRnlJSEJoZEdOb0lEMGdkbkJoZEdOb0xuQmhkR05vWEc1Y2JpQWdJQ0J6ZDJsMFkyZ2dLSFI1Y0dVcElIdGNiaUFnSUNBZ0lDQWdZMkZ6WlNCV1VHRjBZMmd1VWtWTlQxWkZPbHh1SUNBZ0lDQWdJQ0FnSUNBZ2NtVjBkWEp1SUhKbGJXOTJaVTV2WkdVb1pHOXRUbTlrWlN3Z2RrNXZaR1VwWEc0Z0lDQWdJQ0FnSUdOaGMyVWdWbEJoZEdOb0xrbE9VMFZTVkRwY2JpQWdJQ0FnSUNBZ0lDQWdJSEpsZEhWeWJpQnBibk5sY25ST2IyUmxLR1J2YlU1dlpHVXNJSEJoZEdOb0xDQnlaVzVrWlhKUGNIUnBiMjV6S1Z4dUlDQWdJQ0FnSUNCallYTmxJRlpRWVhSamFDNVdWRVZZVkRwY2JpQWdJQ0FnSUNBZ0lDQWdJSEpsZEhWeWJpQnpkSEpwYm1kUVlYUmphQ2hrYjIxT2IyUmxMQ0IyVG05a1pTd2djR0YwWTJnc0lISmxibVJsY2s5d2RHbHZibk1wWEc0Z0lDQWdJQ0FnSUdOaGMyVWdWbEJoZEdOb0xsZEpSRWRGVkRwY2JpQWdJQ0FnSUNBZ0lDQWdJSEpsZEhWeWJpQjNhV1JuWlhSUVlYUmphQ2hrYjIxT2IyUmxMQ0IyVG05a1pTd2djR0YwWTJnc0lISmxibVJsY2s5d2RHbHZibk1wWEc0Z0lDQWdJQ0FnSUdOaGMyVWdWbEJoZEdOb0xsWk9UMFJGT2x4dUlDQWdJQ0FnSUNBZ0lDQWdjbVYwZFhKdUlIWk9iMlJsVUdGMFkyZ29aRzl0VG05a1pTd2dkazV2WkdVc0lIQmhkR05vTENCeVpXNWtaWEpQY0hScGIyNXpLVnh1SUNBZ0lDQWdJQ0JqWVhObElGWlFZWFJqYUM1UFVrUkZVanBjYmlBZ0lDQWdJQ0FnSUNBZ0lISmxiM0prWlhKRGFHbHNaSEpsYmloa2IyMU9iMlJsTENCd1lYUmphQ2xjYmlBZ0lDQWdJQ0FnSUNBZ0lISmxkSFZ5YmlCa2IyMU9iMlJsWEc0Z0lDQWdJQ0FnSUdOaGMyVWdWbEJoZEdOb0xsQlNUMUJUT2x4dUlDQWdJQ0FnSUNBZ0lDQWdZWEJ3YkhsUWNtOXdaWEowYVdWektHUnZiVTV2WkdVc0lIQmhkR05vTENCMlRtOWtaUzV3Y205d1pYSjBhV1Z6S1Z4dUlDQWdJQ0FnSUNBZ0lDQWdjbVYwZFhKdUlHUnZiVTV2WkdWY2JpQWdJQ0FnSUNBZ1kyRnpaU0JXVUdGMFkyZ3VWRWhWVGtzNlhHNGdJQ0FnSUNBZ0lDQWdJQ0J5WlhSMWNtNGdjbVZ3YkdGalpWSnZiM1FvWkc5dFRtOWtaU3hjYmlBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0J5Wlc1a1pYSlBjSFJwYjI1ekxuQmhkR05vS0dSdmJVNXZaR1VzSUhCaGRHTm9MQ0J5Wlc1a1pYSlBjSFJwYjI1ektTbGNiaUFnSUNBZ0lDQWdaR1ZtWVhWc2REcGNiaUFnSUNBZ0lDQWdJQ0FnSUhKbGRIVnliaUJrYjIxT2IyUmxYRzRnSUNBZ2ZWeHVmVnh1WEc1bWRXNWpkR2x2YmlCeVpXMXZkbVZPYjJSbEtHUnZiVTV2WkdVc0lIWk9iMlJsS1NCN1hHNGdJQ0FnZG1GeUlIQmhjbVZ1ZEU1dlpHVWdQU0JrYjIxT2IyUmxMbkJoY21WdWRFNXZaR1ZjYmx4dUlDQWdJR2xtSUNod1lYSmxiblJPYjJSbEtTQjdYRzRnSUNBZ0lDQWdJSEJoY21WdWRFNXZaR1V1Y21WdGIzWmxRMmhwYkdRb1pHOXRUbTlrWlNsY2JpQWdJQ0I5WEc1Y2JpQWdJQ0JrWlhOMGNtOTVWMmxrWjJWMEtHUnZiVTV2WkdVc0lIWk9iMlJsS1R0Y2JseHVJQ0FnSUhKbGRIVnliaUJ1ZFd4c1hHNTlYRzVjYm1aMWJtTjBhVzl1SUdsdWMyVnlkRTV2WkdVb2NHRnlaVzUwVG05a1pTd2dkazV2WkdVc0lISmxibVJsY2s5d2RHbHZibk1wSUh0Y2JpQWdJQ0IyWVhJZ2JtVjNUbTlrWlNBOUlISmxibVJsY2s5d2RHbHZibk11Y21WdVpHVnlLSFpPYjJSbExDQnlaVzVrWlhKUGNIUnBiMjV6S1Z4dVhHNGdJQ0FnYVdZZ0tIQmhjbVZ1ZEU1dlpHVXBJSHRjYmlBZ0lDQWdJQ0FnY0dGeVpXNTBUbTlrWlM1aGNIQmxibVJEYUdsc1pDaHVaWGRPYjJSbEtWeHVJQ0FnSUgxY2JseHVJQ0FnSUhKbGRIVnliaUJ3WVhKbGJuUk9iMlJsWEc1OVhHNWNibVoxYm1OMGFXOXVJSE4wY21sdVoxQmhkR05vS0dSdmJVNXZaR1VzSUd4bFpuUldUbTlrWlN3Z2RsUmxlSFFzSUhKbGJtUmxjazl3ZEdsdmJuTXBJSHRjYmlBZ0lDQjJZWElnYm1WM1RtOWtaVnh1WEc0Z0lDQWdhV1lnS0dSdmJVNXZaR1V1Ym05a1pWUjVjR1VnUFQwOUlETXBJSHRjYmlBZ0lDQWdJQ0FnWkc5dFRtOWtaUzV5WlhCc1lXTmxSR0YwWVNnd0xDQmtiMjFPYjJSbExteGxibWQwYUN3Z2RsUmxlSFF1ZEdWNGRDbGNiaUFnSUNBZ0lDQWdibVYzVG05a1pTQTlJR1J2YlU1dlpHVmNiaUFnSUNCOUlHVnNjMlVnZTF4dUlDQWdJQ0FnSUNCMllYSWdjR0Z5Wlc1MFRtOWtaU0E5SUdSdmJVNXZaR1V1Y0dGeVpXNTBUbTlrWlZ4dUlDQWdJQ0FnSUNCdVpYZE9iMlJsSUQwZ2NtVnVaR1Z5VDNCMGFXOXVjeTV5Wlc1a1pYSW9kbFJsZUhRc0lISmxibVJsY2s5d2RHbHZibk1wWEc1Y2JpQWdJQ0FnSUNBZ2FXWWdLSEJoY21WdWRFNXZaR1VnSmlZZ2JtVjNUbTlrWlNBaFBUMGdaRzl0VG05a1pTa2dlMXh1SUNBZ0lDQWdJQ0FnSUNBZ2NHRnlaVzUwVG05a1pTNXlaWEJzWVdObFEyaHBiR1FvYm1WM1RtOWtaU3dnWkc5dFRtOWtaU2xjYmlBZ0lDQWdJQ0FnZlZ4dUlDQWdJSDFjYmx4dUlDQWdJSEpsZEhWeWJpQnVaWGRPYjJSbFhHNTlYRzVjYm1aMWJtTjBhVzl1SUhkcFpHZGxkRkJoZEdOb0tHUnZiVTV2WkdVc0lHeGxablJXVG05a1pTd2dkMmxrWjJWMExDQnlaVzVrWlhKUGNIUnBiMjV6S1NCN1hHNGdJQ0FnZG1GeUlIVndaR0YwYVc1bklEMGdkWEJrWVhSbFYybGtaMlYwS0d4bFpuUldUbTlrWlN3Z2QybGtaMlYwS1Z4dUlDQWdJSFpoY2lCdVpYZE9iMlJsWEc1Y2JpQWdJQ0JwWmlBb2RYQmtZWFJwYm1jcElIdGNiaUFnSUNBZ0lDQWdibVYzVG05a1pTQTlJSGRwWkdkbGRDNTFjR1JoZEdVb2JHVm1kRlpPYjJSbExDQmtiMjFPYjJSbEtTQjhmQ0JrYjIxT2IyUmxYRzRnSUNBZ2ZTQmxiSE5sSUh0Y2JpQWdJQ0FnSUNBZ2JtVjNUbTlrWlNBOUlISmxibVJsY2s5d2RHbHZibk11Y21WdVpHVnlLSGRwWkdkbGRDd2djbVZ1WkdWeVQzQjBhVzl1Y3lsY2JpQWdJQ0I5WEc1Y2JpQWdJQ0IyWVhJZ2NHRnlaVzUwVG05a1pTQTlJR1J2YlU1dlpHVXVjR0Z5Wlc1MFRtOWtaVnh1WEc0Z0lDQWdhV1lnS0hCaGNtVnVkRTV2WkdVZ0ppWWdibVYzVG05a1pTQWhQVDBnWkc5dFRtOWtaU2tnZTF4dUlDQWdJQ0FnSUNCd1lYSmxiblJPYjJSbExuSmxjR3hoWTJWRGFHbHNaQ2h1WlhkT2IyUmxMQ0JrYjIxT2IyUmxLVnh1SUNBZ0lIMWNibHh1SUNBZ0lHbG1JQ2doZFhCa1lYUnBibWNwSUh0Y2JpQWdJQ0FnSUNBZ1pHVnpkSEp2ZVZkcFpHZGxkQ2hrYjIxT2IyUmxMQ0JzWldaMFZrNXZaR1VwWEc0Z0lDQWdmVnh1WEc0Z0lDQWdjbVYwZFhKdUlHNWxkMDV2WkdWY2JuMWNibHh1Wm5WdVkzUnBiMjRnZGs1dlpHVlFZWFJqYUNoa2IyMU9iMlJsTENCc1pXWjBWazV2WkdVc0lIWk9iMlJsTENCeVpXNWtaWEpQY0hScGIyNXpLU0I3WEc0Z0lDQWdkbUZ5SUhCaGNtVnVkRTV2WkdVZ1BTQmtiMjFPYjJSbExuQmhjbVZ1ZEU1dlpHVmNiaUFnSUNCMllYSWdibVYzVG05a1pTQTlJSEpsYm1SbGNrOXdkR2x2Ym5NdWNtVnVaR1Z5S0haT2IyUmxMQ0J5Wlc1a1pYSlBjSFJwYjI1ektWeHVYRzRnSUNBZ2FXWWdLSEJoY21WdWRFNXZaR1VnSmlZZ2JtVjNUbTlrWlNBaFBUMGdaRzl0VG05a1pTa2dlMXh1SUNBZ0lDQWdJQ0J3WVhKbGJuUk9iMlJsTG5KbGNHeGhZMlZEYUdsc1pDaHVaWGRPYjJSbExDQmtiMjFPYjJSbEtWeHVJQ0FnSUgxY2JseHVJQ0FnSUhKbGRIVnliaUJ1WlhkT2IyUmxYRzU5WEc1Y2JtWjFibU4wYVc5dUlHUmxjM1J5YjNsWGFXUm5aWFFvWkc5dFRtOWtaU3dnZHlrZ2UxeHVJQ0FnSUdsbUlDaDBlWEJsYjJZZ2R5NWtaWE4wY205NUlEMDlQU0JjSW1aMWJtTjBhVzl1WENJZ0ppWWdhWE5YYVdSblpYUW9keWtwSUh0Y2JpQWdJQ0FnSUNBZ2R5NWtaWE4wY205NUtHUnZiVTV2WkdVcFhHNGdJQ0FnZlZ4dWZWeHVYRzVtZFc1amRHbHZiaUJ5Wlc5eVpHVnlRMmhwYkdSeVpXNG9aRzl0VG05a1pTd2diVzkyWlhNcElIdGNiaUFnSUNCMllYSWdZMmhwYkdST2IyUmxjeUE5SUdSdmJVNXZaR1V1WTJocGJHUk9iMlJsYzF4dUlDQWdJSFpoY2lCclpYbE5ZWEFnUFNCN2ZWeHVJQ0FnSUhaaGNpQnViMlJsWEc0Z0lDQWdkbUZ5SUhKbGJXOTJaVnh1SUNBZ0lIWmhjaUJwYm5ObGNuUmNibHh1SUNBZ0lHWnZjaUFvZG1GeUlHa2dQU0F3T3lCcElEd2diVzkyWlhNdWNtVnRiM1psY3k1c1pXNW5kR2c3SUdrckt5a2dlMXh1SUNBZ0lDQWdJQ0J5WlcxdmRtVWdQU0J0YjNabGN5NXlaVzF2ZG1WelcybGRYRzRnSUNBZ0lDQWdJRzV2WkdVZ1BTQmphR2xzWkU1dlpHVnpXM0psYlc5MlpTNW1jbTl0WFZ4dUlDQWdJQ0FnSUNCcFppQW9jbVZ0YjNabExtdGxlU2tnZTF4dUlDQWdJQ0FnSUNBZ0lDQWdhMlY1VFdGd1czSmxiVzkyWlM1clpYbGRJRDBnYm05a1pWeHVJQ0FnSUNBZ0lDQjlYRzRnSUNBZ0lDQWdJR1J2YlU1dlpHVXVjbVZ0YjNabFEyaHBiR1FvYm05a1pTbGNiaUFnSUNCOVhHNWNiaUFnSUNCMllYSWdiR1Z1WjNSb0lEMGdZMmhwYkdST2IyUmxjeTVzWlc1bmRHaGNiaUFnSUNCbWIzSWdLSFpoY2lCcUlEMGdNRHNnYWlBOElHMXZkbVZ6TG1sdWMyVnlkSE11YkdWdVozUm9PeUJxS3lzcElIdGNiaUFnSUNBZ0lDQWdhVzV6WlhKMElEMGdiVzkyWlhNdWFXNXpaWEowYzF0cVhWeHVJQ0FnSUNBZ0lDQnViMlJsSUQwZ2EyVjVUV0Z3VzJsdWMyVnlkQzVyWlhsZFhHNGdJQ0FnSUNBZ0lDOHZJSFJvYVhNZ2FYTWdkR2hsSUhkbGFYSmtaWE4wSUdKMVp5QnBKM1psSUdWMlpYSWdjMlZsYmlCcGJpQjNaV0pyYVhSY2JpQWdJQ0FnSUNBZ1pHOXRUbTlrWlM1cGJuTmxjblJDWldadmNtVW9ibTlrWlN3Z2FXNXpaWEowTG5SdklENDlJR3hsYm1kMGFDc3JJRDhnYm5Wc2JDQTZJR05vYVd4a1RtOWtaWE5iYVc1elpYSjBMblJ2WFNsY2JpQWdJQ0I5WEc1OVhHNWNibVoxYm1OMGFXOXVJSEpsY0d4aFkyVlNiMjkwS0c5c1pGSnZiM1FzSUc1bGQxSnZiM1FwSUh0Y2JpQWdJQ0JwWmlBb2IyeGtVbTl2ZENBbUppQnVaWGRTYjI5MElDWW1JRzlzWkZKdmIzUWdJVDA5SUc1bGQxSnZiM1FnSmlZZ2IyeGtVbTl2ZEM1d1lYSmxiblJPYjJSbEtTQjdYRzRnSUNBZ0lDQWdJRzlzWkZKdmIzUXVjR0Z5Wlc1MFRtOWtaUzV5WlhCc1lXTmxRMmhwYkdRb2JtVjNVbTl2ZEN3Z2IyeGtVbTl2ZENsY2JpQWdJQ0I5WEc1Y2JpQWdJQ0J5WlhSMWNtNGdibVYzVW05dmREdGNibjFjYmx4dWZTeDdYQ0l1TGk5MmJtOWtaUzlwY3kxM2FXUm5aWFF1YW5OY0lqb3lPU3hjSWk0dUwzWnViMlJsTDNad1lYUmphQzVxYzF3aU9qTXlMRndpTGk5aGNIQnNlUzF3Y205d1pYSjBhV1Z6WENJNk1UUXNYQ0l1TDNWd1pHRjBaUzEzYVdSblpYUmNJam94T1gxZExERTRPbHRtZFc1amRHbHZiaWh5WlhGMWFYSmxMRzF2WkhWc1pTeGxlSEJ2Y25SektYdGNiblpoY2lCa2IyTjFiV1Z1ZENBOUlISmxjWFZwY21Vb1hDSm5iRzlpWVd3dlpHOWpkVzFsYm5SY0lpbGNiblpoY2lCcGMwRnljbUY1SUQwZ2NtVnhkV2x5WlNoY0luZ3RhWE10WVhKeVlYbGNJaWxjYmx4dWRtRnlJSEpsYm1SbGNpQTlJSEpsY1hWcGNtVW9YQ0l1TDJOeVpXRjBaUzFsYkdWdFpXNTBYQ0lwWEc1MllYSWdaRzl0U1c1a1pYZ2dQU0J5WlhGMWFYSmxLRndpTGk5a2IyMHRhVzVrWlhoY0lpbGNiblpoY2lCd1lYUmphRTl3SUQwZ2NtVnhkV2x5WlNoY0lpNHZjR0YwWTJndGIzQmNJaWxjYm0xdlpIVnNaUzVsZUhCdmNuUnpJRDBnY0dGMFkyaGNibHh1Wm5WdVkzUnBiMjRnY0dGMFkyZ29jbTl2ZEU1dlpHVXNJSEJoZEdOb1pYTXNJSEpsYm1SbGNrOXdkR2x2Ym5NcElIdGNiaUFnSUNCeVpXNWtaWEpQY0hScGIyNXpJRDBnY21WdVpHVnlUM0IwYVc5dWN5QjhmQ0I3ZlZ4dUlDQWdJSEpsYm1SbGNrOXdkR2x2Ym5NdWNHRjBZMmdnUFNCeVpXNWtaWEpQY0hScGIyNXpMbkJoZEdOb0lDWW1JSEpsYm1SbGNrOXdkR2x2Ym5NdWNHRjBZMmdnSVQwOUlIQmhkR05vWEc0Z0lDQWdJQ0FnSUQ4Z2NtVnVaR1Z5VDNCMGFXOXVjeTV3WVhSamFGeHVJQ0FnSUNBZ0lDQTZJSEJoZEdOb1VtVmpkWEp6YVhabFhHNGdJQ0FnY21WdVpHVnlUM0IwYVc5dWN5NXlaVzVrWlhJZ1BTQnlaVzVrWlhKUGNIUnBiMjV6TG5KbGJtUmxjaUI4ZkNCeVpXNWtaWEpjYmx4dUlDQWdJSEpsZEhWeWJpQnlaVzVrWlhKUGNIUnBiMjV6TG5CaGRHTm9LSEp2YjNST2IyUmxMQ0J3WVhSamFHVnpMQ0J5Wlc1a1pYSlBjSFJwYjI1ektWeHVmVnh1WEc1bWRXNWpkR2x2YmlCd1lYUmphRkpsWTNWeWMybDJaU2h5YjI5MFRtOWtaU3dnY0dGMFkyaGxjeXdnY21WdVpHVnlUM0IwYVc5dWN5a2dlMXh1SUNBZ0lIWmhjaUJwYm1ScFkyVnpJRDBnY0dGMFkyaEpibVJwWTJWektIQmhkR05vWlhNcFhHNWNiaUFnSUNCcFppQW9hVzVrYVdObGN5NXNaVzVuZEdnZ1BUMDlJREFwSUh0Y2JpQWdJQ0FnSUNBZ2NtVjBkWEp1SUhKdmIzUk9iMlJsWEc0Z0lDQWdmVnh1WEc0Z0lDQWdkbUZ5SUdsdVpHVjRJRDBnWkc5dFNXNWtaWGdvY205dmRFNXZaR1VzSUhCaGRHTm9aWE11WVN3Z2FXNWthV05sY3lsY2JpQWdJQ0IyWVhJZ2IzZHVaWEpFYjJOMWJXVnVkQ0E5SUhKdmIzUk9iMlJsTG05M2JtVnlSRzlqZFcxbGJuUmNibHh1SUNBZ0lHbG1JQ2doY21WdVpHVnlUM0IwYVc5dWN5NWtiMk4xYldWdWRDQW1KaUJ2ZDI1bGNrUnZZM1Z0Wlc1MElDRTlQU0JrYjJOMWJXVnVkQ2tnZTF4dUlDQWdJQ0FnSUNCeVpXNWtaWEpQY0hScGIyNXpMbVJ2WTNWdFpXNTBJRDBnYjNkdVpYSkViMk4xYldWdWRGeHVJQ0FnSUgxY2JseHVJQ0FnSUdadmNpQW9kbUZ5SUdrZ1BTQXdPeUJwSUR3Z2FXNWthV05sY3k1c1pXNW5kR2c3SUdrckt5a2dlMXh1SUNBZ0lDQWdJQ0IyWVhJZ2JtOWtaVWx1WkdWNElEMGdhVzVrYVdObGMxdHBYVnh1SUNBZ0lDQWdJQ0J5YjI5MFRtOWtaU0E5SUdGd2NHeDVVR0YwWTJnb2NtOXZkRTV2WkdVc1hHNGdJQ0FnSUNBZ0lDQWdJQ0JwYm1SbGVGdHViMlJsU1c1a1pYaGRMRnh1SUNBZ0lDQWdJQ0FnSUNBZ2NHRjBZMmhsYzF0dWIyUmxTVzVrWlhoZExGeHVJQ0FnSUNBZ0lDQWdJQ0FnY21WdVpHVnlUM0IwYVc5dWN5bGNiaUFnSUNCOVhHNWNiaUFnSUNCeVpYUjFjbTRnY205dmRFNXZaR1ZjYm4xY2JseHVablZ1WTNScGIyNGdZWEJ3YkhsUVlYUmphQ2h5YjI5MFRtOWtaU3dnWkc5dFRtOWtaU3dnY0dGMFkyaE1hWE4wTENCeVpXNWtaWEpQY0hScGIyNXpLU0I3WEc0Z0lDQWdhV1lnS0NGa2IyMU9iMlJsS1NCN1hHNGdJQ0FnSUNBZ0lISmxkSFZ5YmlCeWIyOTBUbTlrWlZ4dUlDQWdJSDFjYmx4dUlDQWdJSFpoY2lCdVpYZE9iMlJsWEc1Y2JpQWdJQ0JwWmlBb2FYTkJjbkpoZVNod1lYUmphRXhwYzNRcEtTQjdYRzRnSUNBZ0lDQWdJR1p2Y2lBb2RtRnlJR2tnUFNBd095QnBJRHdnY0dGMFkyaE1hWE4wTG14bGJtZDBhRHNnYVNzcktTQjdYRzRnSUNBZ0lDQWdJQ0FnSUNCdVpYZE9iMlJsSUQwZ2NHRjBZMmhQY0Nod1lYUmphRXhwYzNSYmFWMHNJR1J2YlU1dlpHVXNJSEpsYm1SbGNrOXdkR2x2Ym5NcFhHNWNiaUFnSUNBZ0lDQWdJQ0FnSUdsbUlDaGtiMjFPYjJSbElEMDlQU0J5YjI5MFRtOWtaU2tnZTF4dUlDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUhKdmIzUk9iMlJsSUQwZ2JtVjNUbTlrWlZ4dUlDQWdJQ0FnSUNBZ0lDQWdmVnh1SUNBZ0lDQWdJQ0I5WEc0Z0lDQWdmU0JsYkhObElIdGNiaUFnSUNBZ0lDQWdibVYzVG05a1pTQTlJSEJoZEdOb1QzQW9jR0YwWTJoTWFYTjBMQ0JrYjIxT2IyUmxMQ0J5Wlc1a1pYSlBjSFJwYjI1ektWeHVYRzRnSUNBZ0lDQWdJR2xtSUNoa2IyMU9iMlJsSUQwOVBTQnliMjkwVG05a1pTa2dlMXh1SUNBZ0lDQWdJQ0FnSUNBZ2NtOXZkRTV2WkdVZ1BTQnVaWGRPYjJSbFhHNGdJQ0FnSUNBZ0lIMWNiaUFnSUNCOVhHNWNiaUFnSUNCeVpYUjFjbTRnY205dmRFNXZaR1ZjYm4xY2JseHVablZ1WTNScGIyNGdjR0YwWTJoSmJtUnBZMlZ6S0hCaGRHTm9aWE1wSUh0Y2JpQWdJQ0IyWVhJZ2FXNWthV05sY3lBOUlGdGRYRzVjYmlBZ0lDQm1iM0lnS0haaGNpQnJaWGtnYVc0Z2NHRjBZMmhsY3lrZ2UxeHVJQ0FnSUNBZ0lDQnBaaUFvYTJWNUlDRTlQU0JjSW1GY0lpa2dlMXh1SUNBZ0lDQWdJQ0FnSUNBZ2FXNWthV05sY3k1d2RYTm9LRTUxYldKbGNpaHJaWGtwS1Z4dUlDQWdJQ0FnSUNCOVhHNGdJQ0FnZlZ4dVhHNGdJQ0FnY21WMGRYSnVJR2x1WkdsalpYTmNibjFjYmx4dWZTeDdYQ0l1TDJOeVpXRjBaUzFsYkdWdFpXNTBYQ0k2TVRVc1hDSXVMMlJ2YlMxcGJtUmxlRndpT2pFMkxGd2lMaTl3WVhSamFDMXZjRndpT2pFM0xGd2laMnh2WW1Gc0wyUnZZM1Z0Wlc1MFhDSTZNVEFzWENKNExXbHpMV0Z5Y21GNVhDSTZNVEo5WFN3eE9UcGJablZ1WTNScGIyNG9jbVZ4ZFdseVpTeHRiMlIxYkdVc1pYaHdiM0owY3lsN1hHNTJZWElnYVhOWGFXUm5aWFFnUFNCeVpYRjFhWEpsS0Z3aUxpNHZkbTV2WkdVdmFYTXRkMmxrWjJWMExtcHpYQ0lwWEc1Y2JtMXZaSFZzWlM1bGVIQnZjblJ6SUQwZ2RYQmtZWFJsVjJsa1oyVjBYRzVjYm1aMWJtTjBhVzl1SUhWd1pHRjBaVmRwWkdkbGRDaGhMQ0JpS1NCN1hHNGdJQ0FnYVdZZ0tHbHpWMmxrWjJWMEtHRXBJQ1ltSUdselYybGtaMlYwS0dJcEtTQjdYRzRnSUNBZ0lDQWdJR2xtSUNoY0ltNWhiV1ZjSWlCcGJpQmhJQ1ltSUZ3aWJtRnRaVndpSUdsdUlHSXBJSHRjYmlBZ0lDQWdJQ0FnSUNBZ0lISmxkSFZ5YmlCaExtbGtJRDA5UFNCaUxtbGtYRzRnSUNBZ0lDQWdJSDBnWld4elpTQjdYRzRnSUNBZ0lDQWdJQ0FnSUNCeVpYUjFjbTRnWVM1cGJtbDBJRDA5UFNCaUxtbHVhWFJjYmlBZ0lDQWdJQ0FnZlZ4dUlDQWdJSDFjYmx4dUlDQWdJSEpsZEhWeWJpQm1ZV3h6WlZ4dWZWeHVYRzU5TEh0Y0lpNHVMM1p1YjJSbEwybHpMWGRwWkdkbGRDNXFjMXdpT2pJNWZWMHNNakE2VzJaMWJtTjBhVzl1S0hKbGNYVnBjbVVzYlc5a2RXeGxMR1Y0Y0c5eWRITXBlMXh1SjNWelpTQnpkSEpwWTNRbk8xeHVYRzUyWVhJZ1JYWlRkRzl5WlNBOUlISmxjWFZwY21Vb0oyVjJMWE4wYjNKbEp5azdYRzVjYm0xdlpIVnNaUzVsZUhCdmNuUnpJRDBnUlhaSWIyOXJPMXh1WEc1bWRXNWpkR2x2YmlCRmRraHZiMnNvZG1Gc2RXVXBJSHRjYmlBZ0lDQnBaaUFvSVNoMGFHbHpJR2x1YzNSaGJtTmxiMllnUlhaSWIyOXJLU2tnZTF4dUlDQWdJQ0FnSUNCeVpYUjFjbTRnYm1WM0lFVjJTRzl2YXloMllXeDFaU2s3WEc0Z0lDQWdmVnh1WEc0Z0lDQWdkR2hwY3k1MllXeDFaU0E5SUhaaGJIVmxPMXh1ZlZ4dVhHNUZka2h2YjJzdWNISnZkRzkwZVhCbExtaHZiMnNnUFNCbWRXNWpkR2x2YmlBb2JtOWtaU3dnY0hKdmNHVnlkSGxPWVcxbEtTQjdYRzRnSUNBZ2RtRnlJR1Z6SUQwZ1JYWlRkRzl5WlNodWIyUmxLVHRjYmlBZ0lDQjJZWElnY0hKdmNFNWhiV1VnUFNCd2NtOXdaWEowZVU1aGJXVXVjM1ZpYzNSeUtETXBPMXh1WEc0Z0lDQWdaWE5iY0hKdmNFNWhiV1ZkSUQwZ2RHaHBjeTUyWVd4MVpUdGNibjA3WEc1Y2JrVjJTRzl2YXk1d2NtOTBiM1I1Y0dVdWRXNW9iMjlySUQwZ1puVnVZM1JwYjI0b2JtOWtaU3dnY0hKdmNHVnlkSGxPWVcxbEtTQjdYRzRnSUNBZ2RtRnlJR1Z6SUQwZ1JYWlRkRzl5WlNodWIyUmxLVHRjYmlBZ0lDQjJZWElnY0hKdmNFNWhiV1VnUFNCd2NtOXdaWEowZVU1aGJXVXVjM1ZpYzNSeUtETXBPMXh1WEc0Z0lDQWdaWE5iY0hKdmNFNWhiV1ZkSUQwZ2RXNWtaV1pwYm1Wa08xeHVmVHRjYmx4dWZTeDdYQ0psZGkxemRHOXlaVndpT2pkOVhTd3lNVHBiWm5WdVkzUnBiMjRvY21WeGRXbHlaU3h0YjJSMWJHVXNaWGh3YjNKMGN5bDdYRzRuZFhObElITjBjbWxqZENjN1hHNWNibTF2WkhWc1pTNWxlSEJ2Y25SeklEMGdVMjltZEZObGRFaHZiMnM3WEc1Y2JtWjFibU4wYVc5dUlGTnZablJUWlhSSWIyOXJLSFpoYkhWbEtTQjdYRzRnSUNBZ2FXWWdLQ0VvZEdocGN5QnBibk4wWVc1alpXOW1JRk52Wm5SVFpYUkliMjlyS1NrZ2UxeHVJQ0FnSUNBZ0lDQnlaWFIxY200Z2JtVjNJRk52Wm5SVFpYUkliMjlyS0haaGJIVmxLVHRjYmlBZ0lDQjlYRzVjYmlBZ0lDQjBhR2x6TG5aaGJIVmxJRDBnZG1Gc2RXVTdYRzU5WEc1Y2JsTnZablJUWlhSSWIyOXJMbkJ5YjNSdmRIbHdaUzVvYjI5cklEMGdablZ1WTNScGIyNGdLRzV2WkdVc0lIQnliM0JsY25SNVRtRnRaU2tnZTF4dUlDQWdJR2xtSUNodWIyUmxXM0J5YjNCbGNuUjVUbUZ0WlYwZ0lUMDlJSFJvYVhNdWRtRnNkV1VwSUh0Y2JpQWdJQ0FnSUNBZ2JtOWtaVnR3Y205d1pYSjBlVTVoYldWZElEMGdkR2hwY3k1MllXeDFaVHRjYmlBZ0lDQjlYRzU5TzF4dVhHNTlMSHQ5WFN3eU1qcGJablZ1WTNScGIyNG9jbVZ4ZFdseVpTeHRiMlIxYkdVc1pYaHdiM0owY3lsN1hHNG5kWE5sSUhOMGNtbGpkQ2M3WEc1Y2JuWmhjaUJwYzBGeWNtRjVJRDBnY21WeGRXbHlaU2duZUMxcGN5MWhjbkpoZVNjcE8xeHVYRzUyWVhJZ1ZrNXZaR1VnUFNCeVpYRjFhWEpsS0NjdUxpOTJibTlrWlM5MmJtOWtaUzVxY3ljcE8xeHVkbUZ5SUZaVVpYaDBJRDBnY21WeGRXbHlaU2duTGk0dmRtNXZaR1V2ZG5SbGVIUXVhbk1uS1R0Y2JuWmhjaUJwYzFaT2IyUmxJRDBnY21WeGRXbHlaU2duTGk0dmRtNXZaR1V2YVhNdGRtNXZaR1VuS1R0Y2JuWmhjaUJwYzFaVVpYaDBJRDBnY21WeGRXbHlaU2duTGk0dmRtNXZaR1V2YVhNdGRuUmxlSFFuS1R0Y2JuWmhjaUJwYzFkcFpHZGxkQ0E5SUhKbGNYVnBjbVVvSnk0dUwzWnViMlJsTDJsekxYZHBaR2RsZENjcE8xeHVkbUZ5SUdselNHOXZheUE5SUhKbGNYVnBjbVVvSnk0dUwzWnViMlJsTDJsekxYWm9iMjlySnlrN1hHNTJZWElnYVhOV1ZHaDFibXNnUFNCeVpYRjFhWEpsS0NjdUxpOTJibTlrWlM5cGN5MTBhSFZ1YXljcE8xeHVYRzUyWVhJZ2NHRnljMlZVWVdjZ1BTQnlaWEYxYVhKbEtDY3VMM0JoY25ObExYUmhaeTVxY3ljcE8xeHVkbUZ5SUhOdlpuUlRaWFJJYjI5cklEMGdjbVZ4ZFdseVpTZ25MaTlvYjI5cmN5OXpiMlowTFhObGRDMW9iMjlyTG1wekp5azdYRzUyWVhJZ1pYWkliMjlySUQwZ2NtVnhkV2x5WlNnbkxpOW9iMjlyY3k5bGRpMW9iMjlyTG1wekp5azdYRzVjYm0xdlpIVnNaUzVsZUhCdmNuUnpJRDBnYUR0Y2JseHVablZ1WTNScGIyNGdhQ2gwWVdkT1lXMWxMQ0J3Y205d1pYSjBhV1Z6TENCamFHbHNaSEpsYmlrZ2UxeHVJQ0FnSUhaaGNpQmphR2xzWkU1dlpHVnpJRDBnVzEwN1hHNGdJQ0FnZG1GeUlIUmhaeXdnY0hKdmNITXNJR3RsZVN3Z2JtRnRaWE53WVdObE8xeHVYRzRnSUNBZ2FXWWdLQ0ZqYUdsc1pISmxiaUFtSmlCcGMwTm9hV3hrY21WdUtIQnliM0JsY25ScFpYTXBLU0I3WEc0Z0lDQWdJQ0FnSUdOb2FXeGtjbVZ1SUQwZ2NISnZjR1Z5ZEdsbGN6dGNiaUFnSUNBZ0lDQWdjSEp2Y0hNZ1BTQjdmVHRjYmlBZ0lDQjlYRzVjYmlBZ0lDQndjbTl3Y3lBOUlIQnliM0J6SUh4OElIQnliM0JsY25ScFpYTWdmSHdnZTMwN1hHNGdJQ0FnZEdGbklEMGdjR0Z5YzJWVVlXY29kR0ZuVG1GdFpTd2djSEp2Y0hNcE8xeHVYRzRnSUNBZ0x5OGdjM1Z3Y0c5eWRDQnJaWGx6WEc0Z0lDQWdhV1lnS0hCeWIzQnpMbWhoYzA5M2JsQnliM0JsY25SNUtDZHJaWGtuS1NrZ2UxeHVJQ0FnSUNBZ0lDQnJaWGtnUFNCd2NtOXdjeTVyWlhrN1hHNGdJQ0FnSUNBZ0lIQnliM0J6TG10bGVTQTlJSFZ1WkdWbWFXNWxaRHRjYmlBZ0lDQjlYRzVjYmlBZ0lDQXZMeUJ6ZFhCd2IzSjBJRzVoYldWemNHRmpaVnh1SUNBZ0lHbG1JQ2h3Y205d2N5NW9ZWE5QZDI1UWNtOXdaWEowZVNnbmJtRnRaWE53WVdObEp5a3BJSHRjYmlBZ0lDQWdJQ0FnYm1GdFpYTndZV05sSUQwZ2NISnZjSE11Ym1GdFpYTndZV05sTzF4dUlDQWdJQ0FnSUNCd2NtOXdjeTV1WVcxbGMzQmhZMlVnUFNCMWJtUmxabWx1WldRN1hHNGdJQ0FnZlZ4dVhHNGdJQ0FnTHk4Z1ptbDRJR04xY25OdmNpQmlkV2RjYmlBZ0lDQnBaaUFvZEdGbklEMDlQU0FuU1U1UVZWUW5JQ1ltWEc0Z0lDQWdJQ0FnSUNGdVlXMWxjM0JoWTJVZ0ppWmNiaUFnSUNBZ0lDQWdjSEp2Y0hNdWFHRnpUM2R1VUhKdmNHVnlkSGtvSjNaaGJIVmxKeWtnSmlaY2JpQWdJQ0FnSUNBZ2NISnZjSE11ZG1Gc2RXVWdJVDA5SUhWdVpHVm1hVzVsWkNBbUpseHVJQ0FnSUNBZ0lDQWhhWE5JYjI5cktIQnliM0J6TG5aaGJIVmxLVnh1SUNBZ0lDa2dlMXh1SUNBZ0lDQWdJQ0J3Y205d2N5NTJZV3gxWlNBOUlITnZablJUWlhSSWIyOXJLSEJ5YjNCekxuWmhiSFZsS1R0Y2JpQWdJQ0I5WEc1Y2JpQWdJQ0IwY21GdWMyWnZjbTFRY205d1pYSjBhV1Z6S0hCeWIzQnpLVHRjYmx4dUlDQWdJR2xtSUNoamFHbHNaSEpsYmlBaFBUMGdkVzVrWldacGJtVmtJQ1ltSUdOb2FXeGtjbVZ1SUNFOVBTQnVkV3hzS1NCN1hHNGdJQ0FnSUNBZ0lHRmtaRU5vYVd4a0tHTm9hV3hrY21WdUxDQmphR2xzWkU1dlpHVnpMQ0IwWVdjc0lIQnliM0J6S1R0Y2JpQWdJQ0I5WEc1Y2JseHVJQ0FnSUhKbGRIVnliaUJ1WlhjZ1ZrNXZaR1VvZEdGbkxDQndjbTl3Y3l3Z1kyaHBiR1JPYjJSbGN5d2dhMlY1TENCdVlXMWxjM0JoWTJVcE8xeHVmVnh1WEc1bWRXNWpkR2x2YmlCaFpHUkRhR2xzWkNoakxDQmphR2xzWkU1dlpHVnpMQ0IwWVdjc0lIQnliM0J6S1NCN1hHNGdJQ0FnYVdZZ0tIUjVjR1Z2WmlCaklEMDlQU0FuYzNSeWFXNW5KeWtnZTF4dUlDQWdJQ0FnSUNCamFHbHNaRTV2WkdWekxuQjFjMmdvYm1WM0lGWlVaWGgwS0dNcEtUdGNiaUFnSUNCOUlHVnNjMlVnYVdZZ0tIUjVjR1Z2WmlCaklEMDlQU0FuYm5WdFltVnlKeWtnZTF4dUlDQWdJQ0FnSUNCamFHbHNaRTV2WkdWekxuQjFjMmdvYm1WM0lGWlVaWGgwS0ZOMGNtbHVaeWhqS1NrcE8xeHVJQ0FnSUgwZ1pXeHpaU0JwWmlBb2FYTkRhR2xzWkNoaktTa2dlMXh1SUNBZ0lDQWdJQ0JqYUdsc1pFNXZaR1Z6TG5CMWMyZ29ZeWs3WEc0Z0lDQWdmU0JsYkhObElHbG1JQ2hwYzBGeWNtRjVLR01wS1NCN1hHNGdJQ0FnSUNBZ0lHWnZjaUFvZG1GeUlHa2dQU0F3T3lCcElEd2dZeTVzWlc1bmRHZzdJR2tyS3lrZ2UxeHVJQ0FnSUNBZ0lDQWdJQ0FnWVdSa1EyaHBiR1FvWTF0cFhTd2dZMmhwYkdST2IyUmxjeXdnZEdGbkxDQndjbTl3Y3lrN1hHNGdJQ0FnSUNBZ0lIMWNiaUFnSUNCOUlHVnNjMlVnYVdZZ0tHTWdQVDA5SUc1MWJHd2dmSHdnWXlBOVBUMGdkVzVrWldacGJtVmtLU0I3WEc0Z0lDQWdJQ0FnSUhKbGRIVnlianRjYmlBZ0lDQjlJR1ZzYzJVZ2UxeHVJQ0FnSUNBZ0lDQjBhSEp2ZHlCVmJtVjRjR1ZqZEdWa1ZtbHlkSFZoYkVWc1pXMWxiblFvZTF4dUlDQWdJQ0FnSUNBZ0lDQWdabTl5WldsbmJrOWlhbVZqZERvZ1l5eGNiaUFnSUNBZ0lDQWdJQ0FnSUhCaGNtVnVkRlp1YjJSbE9pQjdYRzRnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdkR0ZuVG1GdFpUb2dkR0ZuTEZ4dUlDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUhCeWIzQmxjblJwWlhNNklIQnliM0J6WEc0Z0lDQWdJQ0FnSUNBZ0lDQjlYRzRnSUNBZ0lDQWdJSDBwTzF4dUlDQWdJSDFjYm4xY2JseHVablZ1WTNScGIyNGdkSEpoYm5ObWIzSnRVSEp2Y0dWeWRHbGxjeWh3Y205d2N5a2dlMXh1SUNBZ0lHWnZjaUFvZG1GeUlIQnliM0JPWVcxbElHbHVJSEJ5YjNCektTQjdYRzRnSUNBZ0lDQWdJR2xtSUNod2NtOXdjeTVvWVhOUGQyNVFjbTl3WlhKMGVTaHdjbTl3VG1GdFpTa3BJSHRjYmlBZ0lDQWdJQ0FnSUNBZ0lIWmhjaUIyWVd4MVpTQTlJSEJ5YjNCelczQnliM0JPWVcxbFhUdGNibHh1SUNBZ0lDQWdJQ0FnSUNBZ2FXWWdLR2x6U0c5dmF5aDJZV3gxWlNrcElIdGNiaUFnSUNBZ0lDQWdJQ0FnSUNBZ0lDQmpiMjUwYVc1MVpUdGNiaUFnSUNBZ0lDQWdJQ0FnSUgxY2JseHVJQ0FnSUNBZ0lDQWdJQ0FnYVdZZ0tIQnliM0JPWVcxbExuTjFZbk4wY2lnd0xDQXpLU0E5UFQwZ0oyVjJMU2NwSUh0Y2JpQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBdkx5QmhaR1FnWlhZdFptOXZJSE4xY0hCdmNuUmNiaUFnSUNBZ0lDQWdJQ0FnSUNBZ0lDQndjbTl3YzF0d2NtOXdUbUZ0WlYwZ1BTQmxka2h2YjJzb2RtRnNkV1VwTzF4dUlDQWdJQ0FnSUNBZ0lDQWdmVnh1SUNBZ0lDQWdJQ0I5WEc0Z0lDQWdmVnh1ZlZ4dVhHNW1kVzVqZEdsdmJpQnBjME5vYVd4a0tIZ3BJSHRjYmlBZ0lDQnlaWFIxY200Z2FYTldUbTlrWlNoNEtTQjhmQ0JwYzFaVVpYaDBLSGdwSUh4OElHbHpWMmxrWjJWMEtIZ3BJSHg4SUdselZsUm9kVzVyS0hncE8xeHVmVnh1WEc1bWRXNWpkR2x2YmlCcGMwTm9hV3hrY21WdUtIZ3BJSHRjYmlBZ0lDQnlaWFIxY200Z2RIbHdaVzltSUhnZ1BUMDlJQ2R6ZEhKcGJtY25JSHg4SUdselFYSnlZWGtvZUNrZ2ZId2dhWE5EYUdsc1pDaDRLVHRjYm4xY2JseHVablZ1WTNScGIyNGdWVzVsZUhCbFkzUmxaRlpwY25SMVlXeEZiR1Z0Wlc1MEtHUmhkR0VwSUh0Y2JpQWdJQ0IyWVhJZ1pYSnlJRDBnYm1WM0lFVnljbTl5S0NrN1hHNWNiaUFnSUNCbGNuSXVkSGx3WlNBOUlDZDJhWEowZFdGc0xXaDVjR1Z5YzJOeWFYQjBMblZ1Wlhod1pXTjBaV1F1ZG1seWRIVmhiQzFsYkdWdFpXNTBKenRjYmlBZ0lDQmxjbkl1YldWemMyRm5aU0E5SUNkVmJtVjRjR1ZqZEdWa0lIWnBjblIxWVd3Z1kyaHBiR1FnY0dGemMyVmtJSFJ2SUdnb0tTNWNYRzRuSUN0Y2JpQWdJQ0FnSUNBZ0owVjRjR1ZqZEdWa0lHRWdWazV2WkdVZ0x5QldkR2gxYm1zZ0x5QldWMmxrWjJWMElDOGdjM1J5YVc1bklHSjFkRHBjWEc0bklDdGNiaUFnSUNBZ0lDQWdKMmR2ZERwY1hHNG5JQ3RjYmlBZ0lDQWdJQ0FnWlhKeWIzSlRkSEpwYm1jb1pHRjBZUzVtYjNKbGFXZHVUMkpxWldOMEtTQXJYRzRnSUNBZ0lDQWdJQ2N1WEZ4dUp5QXJYRzRnSUNBZ0lDQWdJQ2RVYUdVZ2NHRnlaVzUwSUhadWIyUmxJR2x6T2x4Y2JpY2dLMXh1SUNBZ0lDQWdJQ0JsY25KdmNsTjBjbWx1Wnloa1lYUmhMbkJoY21WdWRGWnViMlJsS1Z4dUlDQWdJQ0FnSUNBblhGeHVKeUFyWEc0Z0lDQWdJQ0FnSUNkVGRXZG5aWE4wWldRZ1ptbDRPaUJqYUdGdVoyVWdlVzkxY2lCZ2FDZ3VMaTRzSUZzZ0xpNHVJRjBwWUNCallXeHNjMmwwWlM0bk8xeHVJQ0FnSUdWeWNpNW1iM0psYVdkdVQySnFaV04wSUQwZ1pHRjBZUzVtYjNKbGFXZHVUMkpxWldOME8xeHVJQ0FnSUdWeWNpNXdZWEpsYm5SV2JtOWtaU0E5SUdSaGRHRXVjR0Z5Wlc1MFZtNXZaR1U3WEc1Y2JpQWdJQ0J5WlhSMWNtNGdaWEp5TzF4dWZWeHVYRzVtZFc1amRHbHZiaUJsY25KdmNsTjBjbWx1Wnlodlltb3BJSHRjYmlBZ0lDQjBjbmtnZTF4dUlDQWdJQ0FnSUNCeVpYUjFjbTRnU2xOUFRpNXpkSEpwYm1kcFpua29iMkpxTENCdWRXeHNMQ0FuSUNBZ0lDY3BPMXh1SUNBZ0lIMGdZMkYwWTJnZ0tHVXBJSHRjYmlBZ0lDQWdJQ0FnY21WMGRYSnVJRk4wY21sdVp5aHZZbW9wTzF4dUlDQWdJSDFjYm4xY2JseHVmU3g3WENJdUxpOTJibTlrWlM5cGN5MTBhSFZ1YTF3aU9qSTFMRndpTGk0dmRtNXZaR1V2YVhNdGRtaHZiMnRjSWpveU5peGNJaTR1TDNadWIyUmxMMmx6TFhadWIyUmxYQ0k2TWpjc1hDSXVMaTkyYm05a1pTOXBjeTEyZEdWNGRGd2lPakk0TEZ3aUxpNHZkbTV2WkdVdmFYTXRkMmxrWjJWMFhDSTZNamtzWENJdUxpOTJibTlrWlM5MmJtOWtaUzVxYzF3aU9qTXhMRndpTGk0dmRtNXZaR1V2ZG5SbGVIUXVhbk5jSWpvek15eGNJaTR2YUc5dmEzTXZaWFl0YUc5dmF5NXFjMXdpT2pJd0xGd2lMaTlvYjI5cmN5OXpiMlowTFhObGRDMW9iMjlyTG1welhDSTZNakVzWENJdUwzQmhjbk5sTFhSaFp5NXFjMXdpT2pJekxGd2llQzFwY3kxaGNuSmhlVndpT2pFeWZWMHNNak02VzJaMWJtTjBhVzl1S0hKbGNYVnBjbVVzYlc5a2RXeGxMR1Y0Y0c5eWRITXBlMXh1SjNWelpTQnpkSEpwWTNRbk8xeHVYRzUyWVhJZ2MzQnNhWFFnUFNCeVpYRjFhWEpsS0NkaWNtOTNjMlZ5TFhOd2JHbDBKeWs3WEc1Y2JuWmhjaUJqYkdGemMwbGtVM0JzYVhRZ1BTQXZLRnRjWEM0alhUOWJZUzE2UVMxYU1DMDVYRngxTURBM1JpMWNYSFZHUmtaR1h6b3RYU3NwTHp0Y2JuWmhjaUJ1YjNSRGJHRnpjMGxrSUQwZ0wxNWNYQzU4SXk4N1hHNWNibTF2WkhWc1pTNWxlSEJ2Y25SeklEMGdjR0Z5YzJWVVlXYzdYRzVjYm1aMWJtTjBhVzl1SUhCaGNuTmxWR0ZuS0hSaFp5d2djSEp2Y0hNcElIdGNiaUFnSUNCcFppQW9JWFJoWnlrZ2UxeHVJQ0FnSUNBZ0lDQnlaWFIxY200Z0owUkpWaWM3WEc0Z0lDQWdmVnh1WEc0Z0lDQWdkbUZ5SUc1dlNXUWdQU0FoS0hCeWIzQnpMbWhoYzA5M2JsQnliM0JsY25SNUtDZHBaQ2NwS1R0Y2JseHVJQ0FnSUhaaGNpQjBZV2RRWVhKMGN5QTlJSE53YkdsMEtIUmhaeXdnWTJ4aGMzTkpaRk53YkdsMEtUdGNiaUFnSUNCMllYSWdkR0ZuVG1GdFpTQTlJRzUxYkd3N1hHNWNiaUFnSUNCcFppQW9ibTkwUTJ4aGMzTkpaQzUwWlhOMEtIUmhaMUJoY25Seld6RmRLU2tnZTF4dUlDQWdJQ0FnSUNCMFlXZE9ZVzFsSUQwZ0owUkpWaWM3WEc0Z0lDQWdmVnh1WEc0Z0lDQWdkbUZ5SUdOc1lYTnpaWE1zSUhCaGNuUXNJSFI1Y0dVc0lHazdYRzVjYmlBZ0lDQm1iM0lnS0drZ1BTQXdPeUJwSUR3Z2RHRm5VR0Z5ZEhNdWJHVnVaM1JvT3lCcEt5c3BJSHRjYmlBZ0lDQWdJQ0FnY0dGeWRDQTlJSFJoWjFCaGNuUnpXMmxkTzF4dVhHNGdJQ0FnSUNBZ0lHbG1JQ2doY0dGeWRDa2dlMXh1SUNBZ0lDQWdJQ0FnSUNBZ1kyOXVkR2x1ZFdVN1hHNGdJQ0FnSUNBZ0lIMWNibHh1SUNBZ0lDQWdJQ0IwZVhCbElEMGdjR0Z5ZEM1amFHRnlRWFFvTUNrN1hHNWNiaUFnSUNBZ0lDQWdhV1lnS0NGMFlXZE9ZVzFsS1NCN1hHNGdJQ0FnSUNBZ0lDQWdJQ0IwWVdkT1lXMWxJRDBnY0dGeWREdGNiaUFnSUNBZ0lDQWdmU0JsYkhObElHbG1JQ2gwZVhCbElEMDlQU0FuTGljcElIdGNiaUFnSUNBZ0lDQWdJQ0FnSUdOc1lYTnpaWE1nUFNCamJHRnpjMlZ6SUh4OElGdGRPMXh1SUNBZ0lDQWdJQ0FnSUNBZ1kyeGhjM05sY3k1d2RYTm9LSEJoY25RdWMzVmljM1J5YVc1bktERXNJSEJoY25RdWJHVnVaM1JvS1NrN1hHNGdJQ0FnSUNBZ0lIMGdaV3h6WlNCcFppQW9kSGx3WlNBOVBUMGdKeU1uSUNZbUlHNXZTV1FwSUh0Y2JpQWdJQ0FnSUNBZ0lDQWdJSEJ5YjNCekxtbGtJRDBnY0dGeWRDNXpkV0p6ZEhKcGJtY29NU3dnY0dGeWRDNXNaVzVuZEdncE8xeHVJQ0FnSUNBZ0lDQjlYRzRnSUNBZ2ZWeHVYRzRnSUNBZ2FXWWdLR05zWVhOelpYTXBJSHRjYmlBZ0lDQWdJQ0FnYVdZZ0tIQnliM0J6TG1Oc1lYTnpUbUZ0WlNrZ2UxeHVJQ0FnSUNBZ0lDQWdJQ0FnWTJ4aGMzTmxjeTV3ZFhOb0tIQnliM0J6TG1Oc1lYTnpUbUZ0WlNrN1hHNGdJQ0FnSUNBZ0lIMWNibHh1SUNBZ0lDQWdJQ0J3Y205d2N5NWpiR0Z6YzA1aGJXVWdQU0JqYkdGemMyVnpMbXB2YVc0b0p5QW5LVHRjYmlBZ0lDQjlYRzVjYmlBZ0lDQnlaWFIxY200Z2NISnZjSE11Ym1GdFpYTndZV05sSUQ4Z2RHRm5UbUZ0WlNBNklIUmhaMDVoYldVdWRHOVZjSEJsY2tOaGMyVW9LVHRjYm4xY2JseHVmU3g3WENKaWNtOTNjMlZ5TFhOd2JHbDBYQ0k2TlgxZExESTBPbHRtZFc1amRHbHZiaWh5WlhGMWFYSmxMRzF2WkhWc1pTeGxlSEJ2Y25SektYdGNiblpoY2lCcGMxWk9iMlJsSUQwZ2NtVnhkV2x5WlNoY0lpNHZhWE10ZG01dlpHVmNJaWxjYm5aaGNpQnBjMVpVWlhoMElEMGdjbVZ4ZFdseVpTaGNJaTR2YVhNdGRuUmxlSFJjSWlsY2JuWmhjaUJwYzFkcFpHZGxkQ0E5SUhKbGNYVnBjbVVvWENJdUwybHpMWGRwWkdkbGRGd2lLVnh1ZG1GeUlHbHpWR2gxYm1zZ1BTQnlaWEYxYVhKbEtGd2lMaTlwY3kxMGFIVnVhMXdpS1Z4dVhHNXRiMlIxYkdVdVpYaHdiM0owY3lBOUlHaGhibVJzWlZSb2RXNXJYRzVjYm1aMWJtTjBhVzl1SUdoaGJtUnNaVlJvZFc1cktHRXNJR0lwSUh0Y2JpQWdJQ0IyWVhJZ2NtVnVaR1Z5WldSQklEMGdZVnh1SUNBZ0lIWmhjaUJ5Wlc1a1pYSmxaRUlnUFNCaVhHNWNiaUFnSUNCcFppQW9hWE5VYUhWdWF5aGlLU2tnZTF4dUlDQWdJQ0FnSUNCeVpXNWtaWEpsWkVJZ1BTQnlaVzVrWlhKVWFIVnVheWhpTENCaEtWeHVJQ0FnSUgxY2JseHVJQ0FnSUdsbUlDaHBjMVJvZFc1cktHRXBLU0I3WEc0Z0lDQWdJQ0FnSUhKbGJtUmxjbVZrUVNBOUlISmxibVJsY2xSb2RXNXJLR0VzSUc1MWJHd3BYRzRnSUNBZ2ZWeHVYRzRnSUNBZ2NtVjBkWEp1SUh0Y2JpQWdJQ0FnSUNBZ1lUb2djbVZ1WkdWeVpXUkJMRnh1SUNBZ0lDQWdJQ0JpT2lCeVpXNWtaWEpsWkVKY2JpQWdJQ0I5WEc1OVhHNWNibVoxYm1OMGFXOXVJSEpsYm1SbGNsUm9kVzVyS0hSb2RXNXJMQ0J3Y21WMmFXOTFjeWtnZTF4dUlDQWdJSFpoY2lCeVpXNWtaWEpsWkZSb2RXNXJJRDBnZEdoMWJtc3VkbTV2WkdWY2JseHVJQ0FnSUdsbUlDZ2hjbVZ1WkdWeVpXUlVhSFZ1YXlrZ2UxeHVJQ0FnSUNBZ0lDQnlaVzVrWlhKbFpGUm9kVzVySUQwZ2RHaDFibXN1ZG01dlpHVWdQU0IwYUhWdWF5NXlaVzVrWlhJb2NISmxkbWx2ZFhNcFhHNGdJQ0FnZlZ4dVhHNGdJQ0FnYVdZZ0tDRW9hWE5XVG05a1pTaHlaVzVrWlhKbFpGUm9kVzVyS1NCOGZGeHVJQ0FnSUNBZ0lDQWdJQ0FnYVhOV1ZHVjRkQ2h5Wlc1a1pYSmxaRlJvZFc1cktTQjhmRnh1SUNBZ0lDQWdJQ0FnSUNBZ2FYTlhhV1JuWlhRb2NtVnVaR1Z5WldSVWFIVnVheWtwS1NCN1hHNGdJQ0FnSUNBZ0lIUm9jbTkzSUc1bGR5QkZjbkp2Y2loY0luUm9kVzVySUdScFpDQnViM1FnY21WMGRYSnVJR0VnZG1Gc2FXUWdibTlrWlZ3aUtUdGNiaUFnSUNCOVhHNWNiaUFnSUNCeVpYUjFjbTRnY21WdVpHVnlaV1JVYUhWdWExeHVmVnh1WEc1OUxIdGNJaTR2YVhNdGRHaDFibXRjSWpveU5TeGNJaTR2YVhNdGRtNXZaR1ZjSWpveU55eGNJaTR2YVhNdGRuUmxlSFJjSWpveU9DeGNJaTR2YVhNdGQybGtaMlYwWENJNk1qbDlYU3d5TlRwYlpuVnVZM1JwYjI0b2NtVnhkV2x5WlN4dGIyUjFiR1VzWlhod2IzSjBjeWw3WEc1dGIyUjFiR1V1Wlhod2IzSjBjeUE5SUdselZHaDFibXRjYmx4dVpuVnVZM1JwYjI0Z2FYTlVhSFZ1YXloMEtTQjdYRzRnSUNBZ2NtVjBkWEp1SUhRZ0ppWWdkQzUwZVhCbElEMDlQU0JjSWxSb2RXNXJYQ0pjYm4xY2JseHVmU3g3ZlYwc01qWTZXMloxYm1OMGFXOXVLSEpsY1hWcGNtVXNiVzlrZFd4bExHVjRjRzl5ZEhNcGUxeHViVzlrZFd4bExtVjRjRzl5ZEhNZ1BTQnBjMGh2YjJ0Y2JseHVablZ1WTNScGIyNGdhWE5JYjI5cktHaHZiMnNwSUh0Y2JpQWdJQ0J5WlhSMWNtNGdhRzl2YXlBbUpseHVJQ0FnSUNBZ0tIUjVjR1Z2WmlCb2IyOXJMbWh2YjJzZ1BUMDlJRndpWm5WdVkzUnBiMjVjSWlBbUppQWhhRzl2YXk1b1lYTlBkMjVRY205d1pYSjBlU2hjSW1odmIydGNJaWtnZkh4Y2JpQWdJQ0FnSUNCMGVYQmxiMllnYUc5dmF5NTFibWh2YjJzZ1BUMDlJRndpWm5WdVkzUnBiMjVjSWlBbUppQWhhRzl2YXk1b1lYTlBkMjVRY205d1pYSjBlU2hjSW5WdWFHOXZhMXdpS1NsY2JuMWNibHh1ZlN4N2ZWMHNNamM2VzJaMWJtTjBhVzl1S0hKbGNYVnBjbVVzYlc5a2RXeGxMR1Y0Y0c5eWRITXBlMXh1ZG1GeUlIWmxjbk5wYjI0Z1BTQnlaWEYxYVhKbEtGd2lMaTkyWlhKemFXOXVYQ0lwWEc1Y2JtMXZaSFZzWlM1bGVIQnZjblJ6SUQwZ2FYTldhWEowZFdGc1RtOWtaVnh1WEc1bWRXNWpkR2x2YmlCcGMxWnBjblIxWVd4T2IyUmxLSGdwSUh0Y2JpQWdJQ0J5WlhSMWNtNGdlQ0FtSmlCNExuUjVjR1VnUFQwOUlGd2lWbWx5ZEhWaGJFNXZaR1ZjSWlBbUppQjRMblpsY25OcGIyNGdQVDA5SUhabGNuTnBiMjVjYm4xY2JseHVmU3g3WENJdUwzWmxjbk5wYjI1Y0lqb3pNSDFkTERJNE9sdG1kVzVqZEdsdmJpaHlaWEYxYVhKbExHMXZaSFZzWlN4bGVIQnZjblJ6S1h0Y2JuWmhjaUIyWlhKemFXOXVJRDBnY21WeGRXbHlaU2hjSWk0dmRtVnljMmx2Ymx3aUtWeHVYRzV0YjJSMWJHVXVaWGh3YjNKMGN5QTlJR2x6Vm1seWRIVmhiRlJsZUhSY2JseHVablZ1WTNScGIyNGdhWE5XYVhKMGRXRnNWR1Y0ZENoNEtTQjdYRzRnSUNBZ2NtVjBkWEp1SUhnZ0ppWWdlQzUwZVhCbElEMDlQU0JjSWxacGNuUjFZV3hVWlhoMFhDSWdKaVlnZUM1MlpYSnphVzl1SUQwOVBTQjJaWEp6YVc5dVhHNTlYRzVjYm4wc2Uxd2lMaTkyWlhKemFXOXVYQ0k2TXpCOVhTd3lPVHBiWm5WdVkzUnBiMjRvY21WeGRXbHlaU3h0YjJSMWJHVXNaWGh3YjNKMGN5bDdYRzV0YjJSMWJHVXVaWGh3YjNKMGN5QTlJR2x6VjJsa1oyVjBYRzVjYm1aMWJtTjBhVzl1SUdselYybGtaMlYwS0hjcElIdGNiaUFnSUNCeVpYUjFjbTRnZHlBbUppQjNMblI1Y0dVZ1BUMDlJRndpVjJsa1oyVjBYQ0pjYm4xY2JseHVmU3g3ZlYwc016QTZXMloxYm1OMGFXOXVLSEpsY1hWcGNtVXNiVzlrZFd4bExHVjRjRzl5ZEhNcGUxeHViVzlrZFd4bExtVjRjRzl5ZEhNZ1BTQmNJakpjSWx4dVhHNTlMSHQ5WFN3ek1UcGJablZ1WTNScGIyNG9jbVZ4ZFdseVpTeHRiMlIxYkdVc1pYaHdiM0owY3lsN1hHNTJZWElnZG1WeWMybHZiaUE5SUhKbGNYVnBjbVVvWENJdUwzWmxjbk5wYjI1Y0lpbGNiblpoY2lCcGMxWk9iMlJsSUQwZ2NtVnhkV2x5WlNoY0lpNHZhWE10ZG01dlpHVmNJaWxjYm5aaGNpQnBjMWRwWkdkbGRDQTlJSEpsY1hWcGNtVW9YQ0l1TDJsekxYZHBaR2RsZEZ3aUtWeHVkbUZ5SUdselZHaDFibXNnUFNCeVpYRjFhWEpsS0Z3aUxpOXBjeTEwYUhWdWExd2lLVnh1ZG1GeUlHbHpWa2h2YjJzZ1BTQnlaWEYxYVhKbEtGd2lMaTlwY3kxMmFHOXZhMXdpS1Z4dVhHNXRiMlIxYkdVdVpYaHdiM0owY3lBOUlGWnBjblIxWVd4T2IyUmxYRzVjYm5aaGNpQnViMUJ5YjNCbGNuUnBaWE1nUFNCN2ZWeHVkbUZ5SUc1dlEyaHBiR1J5Wlc0Z1BTQmJYVnh1WEc1bWRXNWpkR2x2YmlCV2FYSjBkV0ZzVG05a1pTaDBZV2RPWVcxbExDQndjbTl3WlhKMGFXVnpMQ0JqYUdsc1pISmxiaXdnYTJWNUxDQnVZVzFsYzNCaFkyVXBJSHRjYmlBZ0lDQjBhR2x6TG5SaFowNWhiV1VnUFNCMFlXZE9ZVzFsWEc0Z0lDQWdkR2hwY3k1d2NtOXdaWEowYVdWeklEMGdjSEp2Y0dWeWRHbGxjeUI4ZkNCdWIxQnliM0JsY25ScFpYTmNiaUFnSUNCMGFHbHpMbU5vYVd4a2NtVnVJRDBnWTJocGJHUnlaVzRnZkh3Z2JtOURhR2xzWkhKbGJseHVJQ0FnSUhSb2FYTXVhMlY1SUQwZ2EyVjVJQ0U5SUc1MWJHd2dQeUJUZEhKcGJtY29hMlY1S1NBNklIVnVaR1ZtYVc1bFpGeHVJQ0FnSUhSb2FYTXVibUZ0WlhOd1lXTmxJRDBnS0hSNWNHVnZaaUJ1WVcxbGMzQmhZMlVnUFQwOUlGd2ljM1J5YVc1blhDSXBJRDhnYm1GdFpYTndZV05sSURvZ2JuVnNiRnh1WEc0Z0lDQWdkbUZ5SUdOdmRXNTBJRDBnS0dOb2FXeGtjbVZ1SUNZbUlHTm9hV3hrY21WdUxteGxibWQwYUNrZ2ZId2dNRnh1SUNBZ0lIWmhjaUJrWlhOalpXNWtZVzUwY3lBOUlEQmNiaUFnSUNCMllYSWdhR0Z6VjJsa1oyVjBjeUE5SUdaaGJITmxYRzRnSUNBZ2RtRnlJR2hoYzFSb2RXNXJjeUE5SUdaaGJITmxYRzRnSUNBZ2RtRnlJR1JsYzJObGJtUmhiblJJYjI5cmN5QTlJR1poYkhObFhHNGdJQ0FnZG1GeUlHaHZiMnR6WEc1Y2JpQWdJQ0JtYjNJZ0tIWmhjaUJ3Y205d1RtRnRaU0JwYmlCd2NtOXdaWEowYVdWektTQjdYRzRnSUNBZ0lDQWdJR2xtSUNod2NtOXdaWEowYVdWekxtaGhjMDkzYmxCeWIzQmxjblI1S0hCeWIzQk9ZVzFsS1NrZ2UxeHVJQ0FnSUNBZ0lDQWdJQ0FnZG1GeUlIQnliM0JsY25SNUlEMGdjSEp2Y0dWeWRHbGxjMXR3Y205d1RtRnRaVjFjYmlBZ0lDQWdJQ0FnSUNBZ0lHbG1JQ2hwYzFaSWIyOXJLSEJ5YjNCbGNuUjVLU0FtSmlCd2NtOXdaWEowZVM1MWJtaHZiMnNwSUh0Y2JpQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNCcFppQW9JV2h2YjJ0ektTQjdYRzRnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUdodmIydHpJRDBnZTMxY2JpQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNCOVhHNWNiaUFnSUNBZ0lDQWdJQ0FnSUNBZ0lDQm9iMjlyYzF0d2NtOXdUbUZ0WlYwZ1BTQndjbTl3WlhKMGVWeHVJQ0FnSUNBZ0lDQWdJQ0FnZlZ4dUlDQWdJQ0FnSUNCOVhHNGdJQ0FnZlZ4dVhHNGdJQ0FnWm05eUlDaDJZWElnYVNBOUlEQTdJR2tnUENCamIzVnVkRHNnYVNzcktTQjdYRzRnSUNBZ0lDQWdJSFpoY2lCamFHbHNaQ0E5SUdOb2FXeGtjbVZ1VzJsZFhHNGdJQ0FnSUNBZ0lHbG1JQ2hwYzFaT2IyUmxLR05vYVd4a0tTa2dlMXh1SUNBZ0lDQWdJQ0FnSUNBZ1pHVnpZMlZ1WkdGdWRITWdLejBnWTJocGJHUXVZMjkxYm5RZ2ZId2dNRnh1WEc0Z0lDQWdJQ0FnSUNBZ0lDQnBaaUFvSVdoaGMxZHBaR2RsZEhNZ0ppWWdZMmhwYkdRdWFHRnpWMmxrWjJWMGN5a2dlMXh1SUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJR2hoYzFkcFpHZGxkSE1nUFNCMGNuVmxYRzRnSUNBZ0lDQWdJQ0FnSUNCOVhHNWNiaUFnSUNBZ0lDQWdJQ0FnSUdsbUlDZ2hhR0Z6VkdoMWJtdHpJQ1ltSUdOb2FXeGtMbWhoYzFSb2RXNXJjeWtnZTF4dUlDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUdoaGMxUm9kVzVyY3lBOUlIUnlkV1ZjYmlBZ0lDQWdJQ0FnSUNBZ0lIMWNibHh1SUNBZ0lDQWdJQ0FnSUNBZ2FXWWdLQ0ZrWlhOalpXNWtZVzUwU0c5dmEzTWdKaVlnS0dOb2FXeGtMbWh2YjJ0eklIeDhJR05vYVd4a0xtUmxjMk5sYm1SaGJuUkliMjlyY3lrcElIdGNiaUFnSUNBZ0lDQWdJQ0FnSUNBZ0lDQmtaWE5qWlc1a1lXNTBTRzl2YTNNZ1BTQjBjblZsWEc0Z0lDQWdJQ0FnSUNBZ0lDQjlYRzRnSUNBZ0lDQWdJSDBnWld4elpTQnBaaUFvSVdoaGMxZHBaR2RsZEhNZ0ppWWdhWE5YYVdSblpYUW9ZMmhwYkdRcEtTQjdYRzRnSUNBZ0lDQWdJQ0FnSUNCcFppQW9kSGx3Wlc5bUlHTm9hV3hrTG1SbGMzUnliM2tnUFQwOUlGd2lablZ1WTNScGIyNWNJaWtnZTF4dUlDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUdoaGMxZHBaR2RsZEhNZ1BTQjBjblZsWEc0Z0lDQWdJQ0FnSUNBZ0lDQjlYRzRnSUNBZ0lDQWdJSDBnWld4elpTQnBaaUFvSVdoaGMxUm9kVzVyY3lBbUppQnBjMVJvZFc1cktHTm9hV3hrS1NrZ2UxeHVJQ0FnSUNBZ0lDQWdJQ0FnYUdGelZHaDFibXR6SUQwZ2RISjFaVHRjYmlBZ0lDQWdJQ0FnZlZ4dUlDQWdJSDFjYmx4dUlDQWdJSFJvYVhNdVkyOTFiblFnUFNCamIzVnVkQ0FySUdSbGMyTmxibVJoYm5SelhHNGdJQ0FnZEdocGN5NW9ZWE5YYVdSblpYUnpJRDBnYUdGelYybGtaMlYwYzF4dUlDQWdJSFJvYVhNdWFHRnpWR2gxYm10eklEMGdhR0Z6VkdoMWJtdHpYRzRnSUNBZ2RHaHBjeTVvYjI5cmN5QTlJR2h2YjJ0elhHNGdJQ0FnZEdocGN5NWtaWE5qWlc1a1lXNTBTRzl2YTNNZ1BTQmtaWE5qWlc1a1lXNTBTRzl2YTNOY2JuMWNibHh1Vm1seWRIVmhiRTV2WkdVdWNISnZkRzkwZVhCbExuWmxjbk5wYjI0Z1BTQjJaWEp6YVc5dVhHNVdhWEowZFdGc1RtOWtaUzV3Y205MGIzUjVjR1V1ZEhsd1pTQTlJRndpVm1seWRIVmhiRTV2WkdWY0lseHVYRzU5TEh0Y0lpNHZhWE10ZEdoMWJtdGNJam95TlN4Y0lpNHZhWE10ZG1odmIydGNJam95Tml4Y0lpNHZhWE10ZG01dlpHVmNJam95Tnl4Y0lpNHZhWE10ZDJsa1oyVjBYQ0k2TWprc1hDSXVMM1psY25OcGIyNWNJam96TUgxZExETXlPbHRtZFc1amRHbHZiaWh5WlhGMWFYSmxMRzF2WkhWc1pTeGxlSEJ2Y25SektYdGNiblpoY2lCMlpYSnphVzl1SUQwZ2NtVnhkV2x5WlNoY0lpNHZkbVZ5YzJsdmJsd2lLVnh1WEc1V2FYSjBkV0ZzVUdGMFkyZ3VUazlPUlNBOUlEQmNibFpwY25SMVlXeFFZWFJqYUM1V1ZFVllWQ0E5SURGY2JsWnBjblIxWVd4UVlYUmphQzVXVGs5RVJTQTlJREpjYmxacGNuUjFZV3hRWVhSamFDNVhTVVJIUlZRZ1BTQXpYRzVXYVhKMGRXRnNVR0YwWTJndVVGSlBVRk1nUFNBMFhHNVdhWEowZFdGc1VHRjBZMmd1VDFKRVJWSWdQU0ExWEc1V2FYSjBkV0ZzVUdGMFkyZ3VTVTVUUlZKVUlEMGdObHh1Vm1seWRIVmhiRkJoZEdOb0xsSkZUVTlXUlNBOUlEZGNibFpwY25SMVlXeFFZWFJqYUM1VVNGVk9TeUE5SURoY2JseHViVzlrZFd4bExtVjRjRzl5ZEhNZ1BTQldhWEowZFdGc1VHRjBZMmhjYmx4dVpuVnVZM1JwYjI0Z1ZtbHlkSFZoYkZCaGRHTm9LSFI1Y0dVc0lIWk9iMlJsTENCd1lYUmphQ2tnZTF4dUlDQWdJSFJvYVhNdWRIbHdaU0E5SUU1MWJXSmxjaWgwZVhCbEtWeHVJQ0FnSUhSb2FYTXVkazV2WkdVZ1BTQjJUbTlrWlZ4dUlDQWdJSFJvYVhNdWNHRjBZMmdnUFNCd1lYUmphRnh1ZlZ4dVhHNVdhWEowZFdGc1VHRjBZMmd1Y0hKdmRHOTBlWEJsTG5abGNuTnBiMjRnUFNCMlpYSnphVzl1WEc1V2FYSjBkV0ZzVUdGMFkyZ3VjSEp2ZEc5MGVYQmxMblI1Y0dVZ1BTQmNJbFpwY25SMVlXeFFZWFJqYUZ3aVhHNWNibjBzZTF3aUxpOTJaWEp6YVc5dVhDSTZNekI5WFN3ek16cGJablZ1WTNScGIyNG9jbVZ4ZFdseVpTeHRiMlIxYkdVc1pYaHdiM0owY3lsN1hHNTJZWElnZG1WeWMybHZiaUE5SUhKbGNYVnBjbVVvWENJdUwzWmxjbk5wYjI1Y0lpbGNibHh1Ylc5a2RXeGxMbVY0Y0c5eWRITWdQU0JXYVhKMGRXRnNWR1Y0ZEZ4dVhHNW1kVzVqZEdsdmJpQldhWEowZFdGc1ZHVjRkQ2gwWlhoMEtTQjdYRzRnSUNBZ2RHaHBjeTUwWlhoMElEMGdVM1J5YVc1bktIUmxlSFFwWEc1OVhHNWNibFpwY25SMVlXeFVaWGgwTG5CeWIzUnZkSGx3WlM1MlpYSnphVzl1SUQwZ2RtVnljMmx2Ymx4dVZtbHlkSFZoYkZSbGVIUXVjSEp2ZEc5MGVYQmxMblI1Y0dVZ1BTQmNJbFpwY25SMVlXeFVaWGgwWENKY2JseHVmU3g3WENJdUwzWmxjbk5wYjI1Y0lqb3pNSDFkTERNME9sdG1kVzVqZEdsdmJpaHlaWEYxYVhKbExHMXZaSFZzWlN4bGVIQnZjblJ6S1h0Y2JuWmhjaUJwYzA5aWFtVmpkQ0E5SUhKbGNYVnBjbVVvWENKcGN5MXZZbXBsWTNSY0lpbGNiblpoY2lCcGMwaHZiMnNnUFNCeVpYRjFhWEpsS0Z3aUxpNHZkbTV2WkdVdmFYTXRkbWh2YjJ0Y0lpbGNibHh1Ylc5a2RXeGxMbVY0Y0c5eWRITWdQU0JrYVdabVVISnZjSE5jYmx4dVpuVnVZM1JwYjI0Z1pHbG1abEJ5YjNCektHRXNJR0lwSUh0Y2JpQWdJQ0IyWVhJZ1pHbG1abHh1WEc0Z0lDQWdabTl5SUNoMllYSWdZVXRsZVNCcGJpQmhLU0I3WEc0Z0lDQWdJQ0FnSUdsbUlDZ2hLR0ZMWlhrZ2FXNGdZaWtwSUh0Y2JpQWdJQ0FnSUNBZ0lDQWdJR1JwWm1ZZ1BTQmthV1ptSUh4OElIdDlYRzRnSUNBZ0lDQWdJQ0FnSUNCa2FXWm1XMkZMWlhsZElEMGdkVzVrWldacGJtVmtYRzRnSUNBZ0lDQWdJSDFjYmx4dUlDQWdJQ0FnSUNCMllYSWdZVlpoYkhWbElEMGdZVnRoUzJWNVhWeHVJQ0FnSUNBZ0lDQjJZWElnWWxaaGJIVmxJRDBnWWx0aFMyVjVYVnh1WEc0Z0lDQWdJQ0FnSUdsbUlDaGhWbUZzZFdVZ1BUMDlJR0pXWVd4MVpTa2dlMXh1SUNBZ0lDQWdJQ0FnSUNBZ1kyOXVkR2x1ZFdWY2JpQWdJQ0FnSUNBZ2ZTQmxiSE5sSUdsbUlDaHBjMDlpYW1WamRDaGhWbUZzZFdVcElDWW1JR2x6VDJKcVpXTjBLR0pXWVd4MVpTa3BJSHRjYmlBZ0lDQWdJQ0FnSUNBZ0lHbG1JQ2huWlhSUWNtOTBiM1I1Y0dVb1lsWmhiSFZsS1NBaFBUMGdaMlYwVUhKdmRHOTBlWEJsS0dGV1lXeDFaU2twSUh0Y2JpQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNCa2FXWm1JRDBnWkdsbVppQjhmQ0I3ZlZ4dUlDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUdScFptWmJZVXRsZVYwZ1BTQmlWbUZzZFdWY2JpQWdJQ0FnSUNBZ0lDQWdJSDBnWld4elpTQnBaaUFvYVhOSWIyOXJLR0pXWVd4MVpTa3BJSHRjYmlBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnWkdsbVppQTlJR1JwWm1ZZ2ZId2dlMzFjYmlBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnWkdsbVpsdGhTMlY1WFNBOUlHSldZV3gxWlZ4dUlDQWdJQ0FnSUNBZ0lDQWdmU0JsYkhObElIdGNiaUFnSUNBZ0lDQWdJQ0FnSUNBZ0lDQjJZWElnYjJKcVpXTjBSR2xtWmlBOUlHUnBabVpRY205d2N5aGhWbUZzZFdVc0lHSldZV3gxWlNsY2JpQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNCcFppQW9iMkpxWldOMFJHbG1aaWtnZTF4dUlDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQmthV1ptSUQwZ1pHbG1aaUI4ZkNCN2ZWeHVJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0JrYVdabVcyRkxaWGxkSUQwZ2IySnFaV04wUkdsbVpseHVJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lIMWNiaUFnSUNBZ0lDQWdJQ0FnSUgxY2JpQWdJQ0FnSUNBZ2ZTQmxiSE5sSUh0Y2JpQWdJQ0FnSUNBZ0lDQWdJR1JwWm1ZZ1BTQmthV1ptSUh4OElIdDlYRzRnSUNBZ0lDQWdJQ0FnSUNCa2FXWm1XMkZMWlhsZElEMGdZbFpoYkhWbFhHNGdJQ0FnSUNBZ0lIMWNiaUFnSUNCOVhHNWNiaUFnSUNCbWIzSWdLSFpoY2lCaVMyVjVJR2x1SUdJcElIdGNiaUFnSUNBZ0lDQWdhV1lnS0NFb1lrdGxlU0JwYmlCaEtTa2dlMXh1SUNBZ0lDQWdJQ0FnSUNBZ1pHbG1aaUE5SUdScFptWWdmSHdnZTMxY2JpQWdJQ0FnSUNBZ0lDQWdJR1JwWm1aYllrdGxlVjBnUFNCaVcySkxaWGxkWEc0Z0lDQWdJQ0FnSUgxY2JpQWdJQ0I5WEc1Y2JpQWdJQ0J5WlhSMWNtNGdaR2xtWmx4dWZWeHVYRzVtZFc1amRHbHZiaUJuWlhSUWNtOTBiM1I1Y0dVb2RtRnNkV1VwSUh0Y2JpQWdhV1lnS0U5aWFtVmpkQzVuWlhSUWNtOTBiM1I1Y0dWUFppa2dlMXh1SUNBZ0lISmxkSFZ5YmlCUFltcGxZM1F1WjJWMFVISnZkRzkwZVhCbFQyWW9kbUZzZFdVcFhHNGdJSDBnWld4elpTQnBaaUFvZG1Gc2RXVXVYMTl3Y205MGIxOWZLU0I3WEc0Z0lDQWdjbVYwZFhKdUlIWmhiSFZsTGw5ZmNISnZkRzlmWDF4dUlDQjlJR1ZzYzJVZ2FXWWdLSFpoYkhWbExtTnZibk4wY25WamRHOXlLU0I3WEc0Z0lDQWdjbVYwZFhKdUlIWmhiSFZsTG1OdmJuTjBjblZqZEc5eUxuQnliM1J2ZEhsd1pWeHVJQ0I5WEc1OVhHNWNibjBzZTF3aUxpNHZkbTV2WkdVdmFYTXRkbWh2YjJ0Y0lqb3lOaXhjSW1sekxXOWlhbVZqZEZ3aU9qRXhmVjBzTXpVNlcyWjFibU4wYVc5dUtISmxjWFZwY21Vc2JXOWtkV3hsTEdWNGNHOXlkSE1wZTF4dWRtRnlJR2x6UVhKeVlYa2dQU0J5WlhGMWFYSmxLRndpZUMxcGN5MWhjbkpoZVZ3aUtWeHVYRzUyWVhJZ1ZsQmhkR05vSUQwZ2NtVnhkV2x5WlNoY0lpNHVMM1p1YjJSbEwzWndZWFJqYUZ3aUtWeHVkbUZ5SUdselZrNXZaR1VnUFNCeVpYRjFhWEpsS0Z3aUxpNHZkbTV2WkdVdmFYTXRkbTV2WkdWY0lpbGNiblpoY2lCcGMxWlVaWGgwSUQwZ2NtVnhkV2x5WlNoY0lpNHVMM1p1YjJSbEwybHpMWFowWlhoMFhDSXBYRzUyWVhJZ2FYTlhhV1JuWlhRZ1BTQnlaWEYxYVhKbEtGd2lMaTR2ZG01dlpHVXZhWE10ZDJsa1oyVjBYQ0lwWEc1MllYSWdhWE5VYUhWdWF5QTlJSEpsY1hWcGNtVW9YQ0l1TGk5MmJtOWtaUzlwY3kxMGFIVnVhMXdpS1Z4dWRtRnlJR2hoYm1Sc1pWUm9kVzVySUQwZ2NtVnhkV2x5WlNoY0lpNHVMM1p1YjJSbEwyaGhibVJzWlMxMGFIVnVhMXdpS1Z4dVhHNTJZWElnWkdsbVpsQnliM0J6SUQwZ2NtVnhkV2x5WlNoY0lpNHZaR2xtWmkxd2NtOXdjMXdpS1Z4dVhHNXRiMlIxYkdVdVpYaHdiM0owY3lBOUlHUnBabVpjYmx4dVpuVnVZM1JwYjI0Z1pHbG1aaWhoTENCaUtTQjdYRzRnSUNBZ2RtRnlJSEJoZEdOb0lEMGdleUJoT2lCaElIMWNiaUFnSUNCM1lXeHJLR0VzSUdJc0lIQmhkR05vTENBd0tWeHVJQ0FnSUhKbGRIVnliaUJ3WVhSamFGeHVmVnh1WEc1bWRXNWpkR2x2YmlCM1lXeHJLR0VzSUdJc0lIQmhkR05vTENCcGJtUmxlQ2tnZTF4dUlDQWdJR2xtSUNoaElEMDlQU0JpS1NCN1hHNGdJQ0FnSUNBZ0lISmxkSFZ5Ymx4dUlDQWdJSDFjYmx4dUlDQWdJSFpoY2lCaGNIQnNlU0E5SUhCaGRHTm9XMmx1WkdWNFhWeHVJQ0FnSUhaaGNpQmhjSEJzZVVOc1pXRnlJRDBnWm1Gc2MyVmNibHh1SUNBZ0lHbG1JQ2hwYzFSb2RXNXJLR0VwSUh4OElHbHpWR2gxYm1zb1lpa3BJSHRjYmlBZ0lDQWdJQ0FnZEdoMWJtdHpLR0VzSUdJc0lIQmhkR05vTENCcGJtUmxlQ2xjYmlBZ0lDQjlJR1ZzYzJVZ2FXWWdLR0lnUFQwZ2JuVnNiQ2tnZTF4dVhHNGdJQ0FnSUNBZ0lDOHZJRWxtSUdFZ2FYTWdZU0IzYVdSblpYUWdkMlVnZDJsc2JDQmhaR1FnWVNCeVpXMXZkbVVnY0dGMFkyZ2dabTl5SUdsMFhHNGdJQ0FnSUNBZ0lDOHZJRTkwYUdWeWQybHpaU0JoYm5rZ1kyaHBiR1FnZDJsa1oyVjBjeTlvYjI5cmN5QnRkWE4wSUdKbElHUmxjM1J5YjNsbFpDNWNiaUFnSUNBZ0lDQWdMeThnVkdocGN5QndjbVYyWlc1MGN5QmhaR1JwYm1jZ2RIZHZJSEpsYlc5MlpTQndZWFJqYUdWeklHWnZjaUJoSUhkcFpHZGxkQzVjYmlBZ0lDQWdJQ0FnYVdZZ0tDRnBjMWRwWkdkbGRDaGhLU2tnZTF4dUlDQWdJQ0FnSUNBZ0lDQWdZMnhsWVhKVGRHRjBaU2hoTENCd1lYUmphQ3dnYVc1a1pYZ3BYRzRnSUNBZ0lDQWdJQ0FnSUNCaGNIQnNlU0E5SUhCaGRHTm9XMmx1WkdWNFhWeHVJQ0FnSUNBZ0lDQjlYRzVjYmlBZ0lDQWdJQ0FnWVhCd2JIa2dQU0JoY0hCbGJtUlFZWFJqYUNoaGNIQnNlU3dnYm1WM0lGWlFZWFJqYUNoV1VHRjBZMmd1VWtWTlQxWkZMQ0JoTENCaUtTbGNiaUFnSUNCOUlHVnNjMlVnYVdZZ0tHbHpWazV2WkdVb1lpa3BJSHRjYmlBZ0lDQWdJQ0FnYVdZZ0tHbHpWazV2WkdVb1lTa3BJSHRjYmlBZ0lDQWdJQ0FnSUNBZ0lHbG1JQ2hoTG5SaFowNWhiV1VnUFQwOUlHSXVkR0ZuVG1GdFpTQW1KbHh1SUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJR0V1Ym1GdFpYTndZV05sSUQwOVBTQmlMbTVoYldWemNHRmpaU0FtSmx4dUlDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUdFdWEyVjVJRDA5UFNCaUxtdGxlU2tnZTF4dUlDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUhaaGNpQndjbTl3YzFCaGRHTm9JRDBnWkdsbVpsQnliM0J6S0dFdWNISnZjR1Z5ZEdsbGN5d2dZaTV3Y205d1pYSjBhV1Z6S1Z4dUlDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUdsbUlDaHdjbTl3YzFCaGRHTm9LU0I3WEc0Z0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lHRndjR3g1SUQwZ1lYQndaVzVrVUdGMFkyZ29ZWEJ3Ykhrc1hHNGdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNCdVpYY2dWbEJoZEdOb0tGWlFZWFJqYUM1UVVrOVFVeXdnWVN3Z2NISnZjSE5RWVhSamFDa3BYRzRnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdmVnh1SUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJR0Z3Y0d4NUlEMGdaR2xtWmtOb2FXeGtjbVZ1S0dFc0lHSXNJSEJoZEdOb0xDQmhjSEJzZVN3Z2FXNWtaWGdwWEc0Z0lDQWdJQ0FnSUNBZ0lDQjlJR1ZzYzJVZ2UxeHVJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lHRndjR3g1SUQwZ1lYQndaVzVrVUdGMFkyZ29ZWEJ3Ykhrc0lHNWxkeUJXVUdGMFkyZ29WbEJoZEdOb0xsWk9UMFJGTENCaExDQmlLU2xjYmlBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0JoY0hCc2VVTnNaV0Z5SUQwZ2RISjFaVnh1SUNBZ0lDQWdJQ0FnSUNBZ2ZWeHVJQ0FnSUNBZ0lDQjlJR1ZzYzJVZ2UxeHVJQ0FnSUNBZ0lDQWdJQ0FnWVhCd2JIa2dQU0JoY0hCbGJtUlFZWFJqYUNoaGNIQnNlU3dnYm1WM0lGWlFZWFJqYUNoV1VHRjBZMmd1Vms1UFJFVXNJR0VzSUdJcEtWeHVJQ0FnSUNBZ0lDQWdJQ0FnWVhCd2JIbERiR1ZoY2lBOUlIUnlkV1ZjYmlBZ0lDQWdJQ0FnZlZ4dUlDQWdJSDBnWld4elpTQnBaaUFvYVhOV1ZHVjRkQ2hpS1NrZ2UxeHVJQ0FnSUNBZ0lDQnBaaUFvSVdselZsUmxlSFFvWVNrcElIdGNiaUFnSUNBZ0lDQWdJQ0FnSUdGd2NHeDVJRDBnWVhCd1pXNWtVR0YwWTJnb1lYQndiSGtzSUc1bGR5QldVR0YwWTJnb1ZsQmhkR05vTGxaVVJWaFVMQ0JoTENCaUtTbGNiaUFnSUNBZ0lDQWdJQ0FnSUdGd2NHeDVRMnhsWVhJZ1BTQjBjblZsWEc0Z0lDQWdJQ0FnSUgwZ1pXeHpaU0JwWmlBb1lTNTBaWGgwSUNFOVBTQmlMblJsZUhRcElIdGNiaUFnSUNBZ0lDQWdJQ0FnSUdGd2NHeDVJRDBnWVhCd1pXNWtVR0YwWTJnb1lYQndiSGtzSUc1bGR5QldVR0YwWTJnb1ZsQmhkR05vTGxaVVJWaFVMQ0JoTENCaUtTbGNiaUFnSUNBZ0lDQWdmVnh1SUNBZ0lIMGdaV3h6WlNCcFppQW9hWE5YYVdSblpYUW9ZaWtwSUh0Y2JpQWdJQ0FnSUNBZ2FXWWdLQ0ZwYzFkcFpHZGxkQ2hoS1NrZ2UxeHVJQ0FnSUNBZ0lDQWdJQ0FnWVhCd2JIbERiR1ZoY2lBOUlIUnlkV1ZjYmlBZ0lDQWdJQ0FnZlZ4dVhHNGdJQ0FnSUNBZ0lHRndjR3g1SUQwZ1lYQndaVzVrVUdGMFkyZ29ZWEJ3Ykhrc0lHNWxkeUJXVUdGMFkyZ29WbEJoZEdOb0xsZEpSRWRGVkN3Z1lTd2dZaWtwWEc0Z0lDQWdmVnh1WEc0Z0lDQWdhV1lnS0dGd2NHeDVLU0I3WEc0Z0lDQWdJQ0FnSUhCaGRHTm9XMmx1WkdWNFhTQTlJR0Z3Y0d4NVhHNGdJQ0FnZlZ4dVhHNGdJQ0FnYVdZZ0tHRndjR3g1UTJ4bFlYSXBJSHRjYmlBZ0lDQWdJQ0FnWTJ4bFlYSlRkR0YwWlNoaExDQndZWFJqYUN3Z2FXNWtaWGdwWEc0Z0lDQWdmVnh1ZlZ4dVhHNW1kVzVqZEdsdmJpQmthV1ptUTJocGJHUnlaVzRvWVN3Z1lpd2djR0YwWTJnc0lHRndjR3g1TENCcGJtUmxlQ2tnZTF4dUlDQWdJSFpoY2lCaFEyaHBiR1J5Wlc0Z1BTQmhMbU5vYVd4a2NtVnVYRzRnSUNBZ2RtRnlJRzl5WkdWeVpXUlRaWFFnUFNCeVpXOXlaR1Z5S0dGRGFHbHNaSEpsYml3Z1lpNWphR2xzWkhKbGJpbGNiaUFnSUNCMllYSWdZa05vYVd4a2NtVnVJRDBnYjNKa1pYSmxaRk5sZEM1amFHbHNaSEpsYmx4dVhHNGdJQ0FnZG1GeUlHRk1aVzRnUFNCaFEyaHBiR1J5Wlc0dWJHVnVaM1JvWEc0Z0lDQWdkbUZ5SUdKTVpXNGdQU0JpUTJocGJHUnlaVzR1YkdWdVozUm9YRzRnSUNBZ2RtRnlJR3hsYmlBOUlHRk1aVzRnUGlCaVRHVnVJRDhnWVV4bGJpQTZJR0pNWlc1Y2JseHVJQ0FnSUdadmNpQW9kbUZ5SUdrZ1BTQXdPeUJwSUR3Z2JHVnVPeUJwS3lzcElIdGNiaUFnSUNBZ0lDQWdkbUZ5SUd4bFpuUk9iMlJsSUQwZ1lVTm9hV3hrY21WdVcybGRYRzRnSUNBZ0lDQWdJSFpoY2lCeWFXZG9kRTV2WkdVZ1BTQmlRMmhwYkdSeVpXNWJhVjFjYmlBZ0lDQWdJQ0FnYVc1a1pYZ2dLejBnTVZ4dVhHNGdJQ0FnSUNBZ0lHbG1JQ2doYkdWbWRFNXZaR1VwSUh0Y2JpQWdJQ0FnSUNBZ0lDQWdJR2xtSUNoeWFXZG9kRTV2WkdVcElIdGNiaUFnSUNBZ0lDQWdJQ0FnSUNBZ0lDQXZMeUJGZUdObGMzTWdibTlrWlhNZ2FXNGdZaUJ1WldWa0lIUnZJR0psSUdGa1pHVmtYRzRnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdZWEJ3YkhrZ1BTQmhjSEJsYm1SUVlYUmphQ2hoY0hCc2VTeGNiaUFnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnYm1WM0lGWlFZWFJqYUNoV1VHRjBZMmd1U1U1VFJWSlVMQ0J1ZFd4c0xDQnlhV2RvZEU1dlpHVXBLVnh1SUNBZ0lDQWdJQ0FnSUNBZ2ZWeHVJQ0FnSUNBZ0lDQjlJR1ZzYzJVZ2UxeHVJQ0FnSUNBZ0lDQWdJQ0FnZDJGc2F5aHNaV1owVG05a1pTd2djbWxuYUhST2IyUmxMQ0J3WVhSamFDd2dhVzVrWlhncFhHNGdJQ0FnSUNBZ0lIMWNibHh1SUNBZ0lDQWdJQ0JwWmlBb2FYTldUbTlrWlNoc1pXWjBUbTlrWlNrZ0ppWWdiR1ZtZEU1dlpHVXVZMjkxYm5RcElIdGNiaUFnSUNBZ0lDQWdJQ0FnSUdsdVpHVjRJQ3M5SUd4bFpuUk9iMlJsTG1OdmRXNTBYRzRnSUNBZ0lDQWdJSDFjYmlBZ0lDQjlYRzVjYmlBZ0lDQnBaaUFvYjNKa1pYSmxaRk5sZEM1dGIzWmxjeWtnZTF4dUlDQWdJQ0FnSUNBdkx5QlNaVzl5WkdWeUlHNXZaR1Z6SUd4aGMzUmNiaUFnSUNBZ0lDQWdZWEJ3YkhrZ1BTQmhjSEJsYm1SUVlYUmphQ2hoY0hCc2VTd2dibVYzSUZaUVlYUmphQ2hjYmlBZ0lDQWdJQ0FnSUNBZ0lGWlFZWFJqYUM1UFVrUkZVaXhjYmlBZ0lDQWdJQ0FnSUNBZ0lHRXNYRzRnSUNBZ0lDQWdJQ0FnSUNCdmNtUmxjbVZrVTJWMExtMXZkbVZ6WEc0Z0lDQWdJQ0FnSUNrcFhHNGdJQ0FnZlZ4dVhHNGdJQ0FnY21WMGRYSnVJR0Z3Y0d4NVhHNTlYRzVjYm1aMWJtTjBhVzl1SUdOc1pXRnlVM1JoZEdVb2RrNXZaR1VzSUhCaGRHTm9MQ0JwYm1SbGVDa2dlMXh1SUNBZ0lDOHZJRlJQUkU4NklFMWhhMlVnZEdocGN5QmhJSE5wYm1kc1pTQjNZV3hyTENCdWIzUWdkSGR2WEc0Z0lDQWdkVzVvYjI5cktIWk9iMlJsTENCd1lYUmphQ3dnYVc1a1pYZ3BYRzRnSUNBZ1pHVnpkSEp2ZVZkcFpHZGxkSE1vZGs1dlpHVXNJSEJoZEdOb0xDQnBibVJsZUNsY2JuMWNibHh1THk4Z1VHRjBZMmdnY21WamIzSmtjeUJtYjNJZ1lXeHNJR1JsYzNSeWIzbGxaQ0IzYVdSblpYUnpJRzExYzNRZ1ltVWdZV1JrWldRZ1ltVmpZWFZ6WlNCM1pTQnVaV1ZrWEc0dkx5QmhJRVJQVFNCdWIyUmxJSEpsWm1WeVpXNWpaU0JtYjNJZ2RHaGxJR1JsYzNSeWIza2dablZ1WTNScGIyNWNibVoxYm1OMGFXOXVJR1JsYzNSeWIzbFhhV1JuWlhSektIWk9iMlJsTENCd1lYUmphQ3dnYVc1a1pYZ3BJSHRjYmlBZ0lDQnBaaUFvYVhOWGFXUm5aWFFvZGs1dlpHVXBLU0I3WEc0Z0lDQWdJQ0FnSUdsbUlDaDBlWEJsYjJZZ2RrNXZaR1V1WkdWemRISnZlU0E5UFQwZ1hDSm1kVzVqZEdsdmJsd2lLU0I3WEc0Z0lDQWdJQ0FnSUNBZ0lDQndZWFJqYUZ0cGJtUmxlRjBnUFNCaGNIQmxibVJRWVhSamFDaGNiaUFnSUNBZ0lDQWdJQ0FnSUNBZ0lDQndZWFJqYUZ0cGJtUmxlRjBzWEc0Z0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnYm1WM0lGWlFZWFJqYUNoV1VHRjBZMmd1VWtWTlQxWkZMQ0IyVG05a1pTd2diblZzYkNsY2JpQWdJQ0FnSUNBZ0lDQWdJQ2xjYmlBZ0lDQWdJQ0FnZlZ4dUlDQWdJSDBnWld4elpTQnBaaUFvYVhOV1RtOWtaU2gyVG05a1pTa2dKaVlnS0haT2IyUmxMbWhoYzFkcFpHZGxkSE1nZkh3Z2RrNXZaR1V1YUdGelZHaDFibXR6S1NrZ2UxeHVJQ0FnSUNBZ0lDQjJZWElnWTJocGJHUnlaVzRnUFNCMlRtOWtaUzVqYUdsc1pISmxibHh1SUNBZ0lDQWdJQ0IyWVhJZ2JHVnVJRDBnWTJocGJHUnlaVzR1YkdWdVozUm9YRzRnSUNBZ0lDQWdJR1p2Y2lBb2RtRnlJR2tnUFNBd095QnBJRHdnYkdWdU95QnBLeXNwSUh0Y2JpQWdJQ0FnSUNBZ0lDQWdJSFpoY2lCamFHbHNaQ0E5SUdOb2FXeGtjbVZ1VzJsZFhHNGdJQ0FnSUNBZ0lDQWdJQ0JwYm1SbGVDQXJQU0F4WEc1Y2JpQWdJQ0FnSUNBZ0lDQWdJR1JsYzNSeWIzbFhhV1JuWlhSektHTm9hV3hrTENCd1lYUmphQ3dnYVc1a1pYZ3BYRzVjYmlBZ0lDQWdJQ0FnSUNBZ0lHbG1JQ2hwYzFaT2IyUmxLR05vYVd4a0tTQW1KaUJqYUdsc1pDNWpiM1Z1ZENrZ2UxeHVJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lHbHVaR1Y0SUNzOUlHTm9hV3hrTG1OdmRXNTBYRzRnSUNBZ0lDQWdJQ0FnSUNCOVhHNGdJQ0FnSUNBZ0lIMWNiaUFnSUNCOUlHVnNjMlVnYVdZZ0tHbHpWR2gxYm1zb2RrNXZaR1VwS1NCN1hHNGdJQ0FnSUNBZ0lIUm9kVzVyY3loMlRtOWtaU3dnYm5Wc2JDd2djR0YwWTJnc0lHbHVaR1Y0S1Z4dUlDQWdJSDFjYm4xY2JseHVMeThnUTNKbFlYUmxJR0VnYzNWaUxYQmhkR05vSUdadmNpQjBhSFZ1YTNOY2JtWjFibU4wYVc5dUlIUm9kVzVyY3loaExDQmlMQ0J3WVhSamFDd2dhVzVrWlhncElIdGNiaUFnSUNCMllYSWdibTlrWlhNZ1BTQm9ZVzVrYkdWVWFIVnVheWhoTENCaUtWeHVJQ0FnSUhaaGNpQjBhSFZ1YTFCaGRHTm9JRDBnWkdsbVppaHViMlJsY3k1aExDQnViMlJsY3k1aUtWeHVJQ0FnSUdsbUlDaG9ZWE5RWVhSamFHVnpLSFJvZFc1clVHRjBZMmdwS1NCN1hHNGdJQ0FnSUNBZ0lIQmhkR05vVzJsdVpHVjRYU0E5SUc1bGR5QldVR0YwWTJnb1ZsQmhkR05vTGxSSVZVNUxMQ0J1ZFd4c0xDQjBhSFZ1YTFCaGRHTm9LVnh1SUNBZ0lIMWNibjFjYmx4dVpuVnVZM1JwYjI0Z2FHRnpVR0YwWTJobGN5aHdZWFJqYUNrZ2UxeHVJQ0FnSUdadmNpQW9kbUZ5SUdsdVpHVjRJR2x1SUhCaGRHTm9LU0I3WEc0Z0lDQWdJQ0FnSUdsbUlDaHBibVJsZUNBaFBUMGdYQ0poWENJcElIdGNiaUFnSUNBZ0lDQWdJQ0FnSUhKbGRIVnliaUIwY25WbFhHNGdJQ0FnSUNBZ0lIMWNiaUFnSUNCOVhHNWNiaUFnSUNCeVpYUjFjbTRnWm1Gc2MyVmNibjFjYmx4dUx5OGdSWGhsWTNWMFpTQm9iMjlyY3lCM2FHVnVJSFIzYnlCdWIyUmxjeUJoY21VZ2FXUmxiblJwWTJGc1hHNW1kVzVqZEdsdmJpQjFibWh2YjJzb2RrNXZaR1VzSUhCaGRHTm9MQ0JwYm1SbGVDa2dlMXh1SUNBZ0lHbG1JQ2hwYzFaT2IyUmxLSFpPYjJSbEtTa2dlMXh1SUNBZ0lDQWdJQ0JwWmlBb2RrNXZaR1V1YUc5dmEzTXBJSHRjYmlBZ0lDQWdJQ0FnSUNBZ0lIQmhkR05vVzJsdVpHVjRYU0E5SUdGd2NHVnVaRkJoZEdOb0tGeHVJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lIQmhkR05vVzJsdVpHVjRYU3hjYmlBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0J1WlhjZ1ZsQmhkR05vS0Z4dUlDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQldVR0YwWTJndVVGSlBVRk1zWEc0Z0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lIWk9iMlJsTEZ4dUlDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQjFibVJsWm1sdVpXUkxaWGx6S0haT2IyUmxMbWh2YjJ0ektWeHVJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDbGNiaUFnSUNBZ0lDQWdJQ0FnSUNsY2JpQWdJQ0FnSUNBZ2ZWeHVYRzRnSUNBZ0lDQWdJR2xtSUNoMlRtOWtaUzVrWlhOalpXNWtZVzUwU0c5dmEzTWdmSHdnZGs1dlpHVXVhR0Z6VkdoMWJtdHpLU0I3WEc0Z0lDQWdJQ0FnSUNBZ0lDQjJZWElnWTJocGJHUnlaVzRnUFNCMlRtOWtaUzVqYUdsc1pISmxibHh1SUNBZ0lDQWdJQ0FnSUNBZ2RtRnlJR3hsYmlBOUlHTm9hV3hrY21WdUxteGxibWQwYUZ4dUlDQWdJQ0FnSUNBZ0lDQWdabTl5SUNoMllYSWdhU0E5SURBN0lHa2dQQ0JzWlc0N0lHa3JLeWtnZTF4dUlDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUhaaGNpQmphR2xzWkNBOUlHTm9hV3hrY21WdVcybGRYRzRnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdhVzVrWlhnZ0t6MGdNVnh1WEc0Z0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnZFc1b2IyOXJLR05vYVd4a0xDQndZWFJqYUN3Z2FXNWtaWGdwWEc1Y2JpQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNCcFppQW9hWE5XVG05a1pTaGphR2xzWkNrZ0ppWWdZMmhwYkdRdVkyOTFiblFwSUh0Y2JpQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdhVzVrWlhnZ0t6MGdZMmhwYkdRdVkyOTFiblJjYmlBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0I5WEc0Z0lDQWdJQ0FnSUNBZ0lDQjlYRzRnSUNBZ0lDQWdJSDFjYmlBZ0lDQjlJR1ZzYzJVZ2FXWWdLR2x6VkdoMWJtc29kazV2WkdVcEtTQjdYRzRnSUNBZ0lDQWdJSFJvZFc1cmN5aDJUbTlrWlN3Z2JuVnNiQ3dnY0dGMFkyZ3NJR2x1WkdWNEtWeHVJQ0FnSUgxY2JuMWNibHh1Wm5WdVkzUnBiMjRnZFc1a1pXWnBibVZrUzJWNWN5aHZZbW9wSUh0Y2JpQWdJQ0IyWVhJZ2NtVnpkV3gwSUQwZ2UzMWNibHh1SUNBZ0lHWnZjaUFvZG1GeUlHdGxlU0JwYmlCdlltb3BJSHRjYmlBZ0lDQWdJQ0FnY21WemRXeDBXMnRsZVYwZ1BTQjFibVJsWm1sdVpXUmNiaUFnSUNCOVhHNWNiaUFnSUNCeVpYUjFjbTRnY21WemRXeDBYRzU5WEc1Y2JpOHZJRXhwYzNRZ1pHbG1aaXdnYm1GcGRtVWdiR1ZtZENCMGJ5QnlhV2RvZENCeVpXOXlaR1Z5YVc1blhHNW1kVzVqZEdsdmJpQnlaVzl5WkdWeUtHRkRhR2xzWkhKbGJpd2dZa05vYVd4a2NtVnVLU0I3WEc0Z0lDQWdMeThnVHloTktTQjBhVzFsTENCUEtFMHBJRzFsYlc5eWVWeHVJQ0FnSUhaaGNpQmlRMmhwYkdSSmJtUmxlQ0E5SUd0bGVVbHVaR1Y0S0dKRGFHbHNaSEpsYmlsY2JpQWdJQ0IyWVhJZ1lrdGxlWE1nUFNCaVEyaHBiR1JKYm1SbGVDNXJaWGx6WEc0Z0lDQWdkbUZ5SUdKR2NtVmxJRDBnWWtOb2FXeGtTVzVrWlhndVpuSmxaVnh1WEc0Z0lDQWdhV1lnS0dKR2NtVmxMbXhsYm1kMGFDQTlQVDBnWWtOb2FXeGtjbVZ1TG14bGJtZDBhQ2tnZTF4dUlDQWdJQ0FnSUNCeVpYUjFjbTRnZTF4dUlDQWdJQ0FnSUNBZ0lDQWdZMmhwYkdSeVpXNDZJR0pEYUdsc1pISmxiaXhjYmlBZ0lDQWdJQ0FnSUNBZ0lHMXZkbVZ6T2lCdWRXeHNYRzRnSUNBZ0lDQWdJSDFjYmlBZ0lDQjlYRzVjYmlBZ0lDQXZMeUJQS0U0cElIUnBiV1VzSUU4b1Rpa2diV1Z0YjNKNVhHNGdJQ0FnZG1GeUlHRkRhR2xzWkVsdVpHVjRJRDBnYTJWNVNXNWtaWGdvWVVOb2FXeGtjbVZ1S1Z4dUlDQWdJSFpoY2lCaFMyVjVjeUE5SUdGRGFHbHNaRWx1WkdWNExtdGxlWE5jYmlBZ0lDQjJZWElnWVVaeVpXVWdQU0JoUTJocGJHUkpibVJsZUM1bWNtVmxYRzVjYmlBZ0lDQnBaaUFvWVVaeVpXVXViR1Z1WjNSb0lEMDlQU0JoUTJocGJHUnlaVzR1YkdWdVozUm9LU0I3WEc0Z0lDQWdJQ0FnSUhKbGRIVnliaUI3WEc0Z0lDQWdJQ0FnSUNBZ0lDQmphR2xzWkhKbGJqb2dZa05vYVd4a2NtVnVMRnh1SUNBZ0lDQWdJQ0FnSUNBZ2JXOTJaWE02SUc1MWJHeGNiaUFnSUNBZ0lDQWdmVnh1SUNBZ0lIMWNibHh1SUNBZ0lDOHZJRThvVFVGWUtFNHNJRTBwS1NCdFpXMXZjbmxjYmlBZ0lDQjJZWElnYm1WM1EyaHBiR1J5Wlc0Z1BTQmJYVnh1WEc0Z0lDQWdkbUZ5SUdaeVpXVkpibVJsZUNBOUlEQmNiaUFnSUNCMllYSWdabkpsWlVOdmRXNTBJRDBnWWtaeVpXVXViR1Z1WjNSb1hHNGdJQ0FnZG1GeUlHUmxiR1YwWldSSmRHVnRjeUE5SURCY2JseHVJQ0FnSUM4dklFbDBaWEpoZEdVZ2RHaHliM1ZuYUNCaElHRnVaQ0J0WVhSamFDQmhJRzV2WkdVZ2FXNGdZbHh1SUNBZ0lDOHZJRThvVGlrZ2RHbHRaU3hjYmlBZ0lDQm1iM0lnS0haaGNpQnBJRDBnTUNBN0lHa2dQQ0JoUTJocGJHUnlaVzR1YkdWdVozUm9PeUJwS3lzcElIdGNiaUFnSUNBZ0lDQWdkbUZ5SUdGSmRHVnRJRDBnWVVOb2FXeGtjbVZ1VzJsZFhHNGdJQ0FnSUNBZ0lIWmhjaUJwZEdWdFNXNWtaWGhjYmx4dUlDQWdJQ0FnSUNCcFppQW9ZVWwwWlcwdWEyVjVLU0I3WEc0Z0lDQWdJQ0FnSUNBZ0lDQnBaaUFvWWt0bGVYTXVhR0Z6VDNkdVVISnZjR1Z5ZEhrb1lVbDBaVzB1YTJWNUtTa2dlMXh1SUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQzh2SUUxaGRHTm9JSFZ3SUhSb1pTQnZiR1FnYTJWNWMxeHVJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lHbDBaVzFKYm1SbGVDQTlJR0pMWlhselcyRkpkR1Z0TG10bGVWMWNiaUFnSUNBZ0lDQWdJQ0FnSUNBZ0lDQnVaWGREYUdsc1pISmxiaTV3ZFhOb0tHSkRhR2xzWkhKbGJsdHBkR1Z0U1c1a1pYaGRLVnh1WEc0Z0lDQWdJQ0FnSUNBZ0lDQjlJR1ZzYzJVZ2UxeHVJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDOHZJRkpsYlc5MlpTQnZiR1FnYTJWNVpXUWdhWFJsYlhOY2JpQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNCcGRHVnRTVzVrWlhnZ1BTQnBJQzBnWkdWc1pYUmxaRWwwWlcxekt5dGNiaUFnSUNBZ0lDQWdJQ0FnSUNBZ0lDQnVaWGREYUdsc1pISmxiaTV3ZFhOb0tHNTFiR3dwWEc0Z0lDQWdJQ0FnSUNBZ0lDQjlYRzRnSUNBZ0lDQWdJSDBnWld4elpTQjdYRzRnSUNBZ0lDQWdJQ0FnSUNBdkx5Qk5ZWFJqYUNCMGFHVWdhWFJsYlNCcGJpQmhJSGRwZEdnZ2RHaGxJRzVsZUhRZ1puSmxaU0JwZEdWdElHbHVJR0pjYmlBZ0lDQWdJQ0FnSUNBZ0lHbG1JQ2htY21WbFNXNWtaWGdnUENCbWNtVmxRMjkxYm5RcElIdGNiaUFnSUNBZ0lDQWdJQ0FnSUNBZ0lDQnBkR1Z0U1c1a1pYZ2dQU0JpUm5KbFpWdG1jbVZsU1c1a1pYZ3JLMTFjYmlBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0J1WlhkRGFHbHNaSEpsYmk1d2RYTm9LR0pEYUdsc1pISmxibHRwZEdWdFNXNWtaWGhkS1Z4dUlDQWdJQ0FnSUNBZ0lDQWdmU0JsYkhObElIdGNiaUFnSUNBZ0lDQWdJQ0FnSUNBZ0lDQXZMeUJVYUdWeVpTQmhjbVVnYm04Z1puSmxaU0JwZEdWdGN5QnBiaUJpSUhSdklHMWhkR05vSUhkcGRHaGNiaUFnSUNBZ0lDQWdJQ0FnSUNBZ0lDQXZMeUIwYUdVZ1puSmxaU0JwZEdWdGN5QnBiaUJoTENCemJ5QjBhR1VnWlhoMGNtRWdabkpsWlNCdWIyUmxjMXh1SUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQzh2SUdGeVpTQmtaV3hsZEdWa0xseHVJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lHbDBaVzFKYm1SbGVDQTlJR2tnTFNCa1pXeGxkR1ZrU1hSbGJYTXJLMXh1SUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJRzVsZDBOb2FXeGtjbVZ1TG5CMWMyZ29iblZzYkNsY2JpQWdJQ0FnSUNBZ0lDQWdJSDFjYmlBZ0lDQWdJQ0FnZlZ4dUlDQWdJSDFjYmx4dUlDQWdJSFpoY2lCc1lYTjBSbkpsWlVsdVpHVjRJRDBnWm5KbFpVbHVaR1Y0SUQ0OUlHSkdjbVZsTG14bGJtZDBhQ0EvWEc0Z0lDQWdJQ0FnSUdKRGFHbHNaSEpsYmk1c1pXNW5kR2dnT2x4dUlDQWdJQ0FnSUNCaVJuSmxaVnRtY21WbFNXNWtaWGhkWEc1Y2JpQWdJQ0F2THlCSmRHVnlZWFJsSUhSb2NtOTFaMmdnWWlCaGJtUWdZWEJ3Wlc1a0lHRnVlU0J1WlhjZ2EyVjVjMXh1SUNBZ0lDOHZJRThvVFNrZ2RHbHRaVnh1SUNBZ0lHWnZjaUFvZG1GeUlHb2dQU0F3T3lCcUlEd2dZa05vYVd4a2NtVnVMbXhsYm1kMGFEc2dhaXNyS1NCN1hHNGdJQ0FnSUNBZ0lIWmhjaUJ1WlhkSmRHVnRJRDBnWWtOb2FXeGtjbVZ1VzJwZFhHNWNiaUFnSUNBZ0lDQWdhV1lnS0c1bGQwbDBaVzB1YTJWNUtTQjdYRzRnSUNBZ0lDQWdJQ0FnSUNCcFppQW9JV0ZMWlhsekxtaGhjMDkzYmxCeWIzQmxjblI1S0c1bGQwbDBaVzB1YTJWNUtTa2dlMXh1SUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQzh2SUVGa1pDQmhibmtnYm1WM0lHdGxlV1ZrSUdsMFpXMXpYRzRnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdMeThnVjJVZ1lYSmxJR0ZrWkdsdVp5QnVaWGNnYVhSbGJYTWdkRzhnZEdobElHVnVaQ0JoYm1RZ2RHaGxiaUJ6YjNKMGFXNW5JSFJvWlcxY2JpQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBdkx5QnBiaUJ3YkdGalpTNGdTVzRnWm5WMGRYSmxJSGRsSUhOb2IzVnNaQ0JwYm5ObGNuUWdibVYzSUdsMFpXMXpJR2x1SUhCc1lXTmxMbHh1SUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJRzVsZDBOb2FXeGtjbVZ1TG5CMWMyZ29ibVYzU1hSbGJTbGNiaUFnSUNBZ0lDQWdJQ0FnSUgxY2JpQWdJQ0FnSUNBZ2ZTQmxiSE5sSUdsbUlDaHFJRDQ5SUd4aGMzUkdjbVZsU1c1a1pYZ3BJSHRjYmlBZ0lDQWdJQ0FnSUNBZ0lDOHZJRUZrWkNCaGJua2diR1ZtZEc5MlpYSWdibTl1TFd0bGVXVmtJR2wwWlcxelhHNGdJQ0FnSUNBZ0lDQWdJQ0J1WlhkRGFHbHNaSEpsYmk1d2RYTm9LRzVsZDBsMFpXMHBYRzRnSUNBZ0lDQWdJSDFjYmlBZ0lDQjlYRzVjYmlBZ0lDQjJZWElnYzJsdGRXeGhkR1VnUFNCdVpYZERhR2xzWkhKbGJpNXpiR2xqWlNncFhHNGdJQ0FnZG1GeUlITnBiWFZzWVhSbFNXNWtaWGdnUFNBd1hHNGdJQ0FnZG1GeUlISmxiVzkyWlhNZ1BTQmJYVnh1SUNBZ0lIWmhjaUJwYm5ObGNuUnpJRDBnVzExY2JpQWdJQ0IyWVhJZ2MybHRkV3hoZEdWSmRHVnRYRzVjYmlBZ0lDQm1iM0lnS0haaGNpQnJJRDBnTURzZ2F5QThJR0pEYUdsc1pISmxiaTVzWlc1bmRHZzdLU0I3WEc0Z0lDQWdJQ0FnSUhaaGNpQjNZVzUwWldSSmRHVnRJRDBnWWtOb2FXeGtjbVZ1VzJ0ZFhHNGdJQ0FnSUNBZ0lITnBiWFZzWVhSbFNYUmxiU0E5SUhOcGJYVnNZWFJsVzNOcGJYVnNZWFJsU1c1a1pYaGRYRzVjYmlBZ0lDQWdJQ0FnTHk4Z2NtVnRiM1psSUdsMFpXMXpYRzRnSUNBZ0lDQWdJSGRvYVd4bElDaHphVzExYkdGMFpVbDBaVzBnUFQwOUlHNTFiR3dnSmlZZ2MybHRkV3hoZEdVdWJHVnVaM1JvS1NCN1hHNGdJQ0FnSUNBZ0lDQWdJQ0J5WlcxdmRtVnpMbkIxYzJnb2NtVnRiM1psS0hOcGJYVnNZWFJsTENCemFXMTFiR0YwWlVsdVpHVjRMQ0J1ZFd4c0tTbGNiaUFnSUNBZ0lDQWdJQ0FnSUhOcGJYVnNZWFJsU1hSbGJTQTlJSE5wYlhWc1lYUmxXM05wYlhWc1lYUmxTVzVrWlhoZFhHNGdJQ0FnSUNBZ0lIMWNibHh1SUNBZ0lDQWdJQ0JwWmlBb0lYTnBiWFZzWVhSbFNYUmxiU0I4ZkNCemFXMTFiR0YwWlVsMFpXMHVhMlY1SUNFOVBTQjNZVzUwWldSSmRHVnRMbXRsZVNrZ2UxeHVJQ0FnSUNBZ0lDQWdJQ0FnTHk4Z2FXWWdkMlVnYm1WbFpDQmhJR3RsZVNCcGJpQjBhR2x6SUhCdmMybDBhVzl1TGk0dVhHNGdJQ0FnSUNBZ0lDQWdJQ0JwWmlBb2QyRnVkR1ZrU1hSbGJTNXJaWGtwSUh0Y2JpQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNCcFppQW9jMmx0ZFd4aGRHVkpkR1Z0SUNZbUlITnBiWFZzWVhSbFNYUmxiUzVyWlhrcElIdGNiaUFnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnTHk4Z2FXWWdZVzRnYVc1elpYSjBJR1J2WlhOdUozUWdjSFYwSUhSb2FYTWdhMlY1SUdsdUlIQnNZV05sTENCcGRDQnVaV1ZrY3lCMGJ5QnRiM1psWEc0Z0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lHbG1JQ2hpUzJWNWMxdHphVzExYkdGMFpVbDBaVzB1YTJWNVhTQWhQVDBnYXlBcklERXBJSHRjYmlBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJSEpsYlc5MlpYTXVjSFZ6YUNoeVpXMXZkbVVvYzJsdGRXeGhkR1VzSUhOcGJYVnNZWFJsU1c1a1pYZ3NJSE5wYlhWc1lYUmxTWFJsYlM1clpYa3BLVnh1SUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdjMmx0ZFd4aGRHVkpkR1Z0SUQwZ2MybHRkV3hoZEdWYmMybHRkV3hoZEdWSmJtUmxlRjFjYmlBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQzh2SUdsbUlIUm9aU0J5WlcxdmRtVWdaR2xrYmlkMElIQjFkQ0IwYUdVZ2QyRnVkR1ZrSUdsMFpXMGdhVzRnY0d4aFkyVXNJSGRsSUc1bFpXUWdkRzhnYVc1elpYSjBJR2wwWEc0Z0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0JwWmlBb0lYTnBiWFZzWVhSbFNYUmxiU0I4ZkNCemFXMTFiR0YwWlVsMFpXMHVhMlY1SUNFOVBTQjNZVzUwWldSSmRHVnRMbXRsZVNrZ2UxeHVJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJR2x1YzJWeWRITXVjSFZ6YUNoN2EyVjVPaUIzWVc1MFpXUkpkR1Z0TG10bGVTd2dkRzg2SUd0OUtWeHVJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ2ZWeHVJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0x5OGdhWFJsYlhNZ1lYSmxJRzFoZEdOb2FXNW5MQ0J6YnlCemEybHdJR0ZvWldGa1hHNGdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNCbGJITmxJSHRjYmlBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNCemFXMTFiR0YwWlVsdVpHVjRLeXRjYmlBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJSDFjYmlBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ2ZWeHVJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0JsYkhObElIdGNiaUFnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lHbHVjMlZ5ZEhNdWNIVnphQ2g3YTJWNU9pQjNZVzUwWldSSmRHVnRMbXRsZVN3Z2RHODZJR3Q5S1Z4dUlDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQjlYRzRnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdmVnh1SUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJR1ZzYzJVZ2UxeHVJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0JwYm5ObGNuUnpMbkIxYzJnb2UydGxlVG9nZDJGdWRHVmtTWFJsYlM1clpYa3NJSFJ2T2lCcmZTbGNiaUFnSUNBZ0lDQWdJQ0FnSUNBZ0lDQjlYRzRnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdheXNyWEc0Z0lDQWdJQ0FnSUNBZ0lDQjlYRzRnSUNBZ0lDQWdJQ0FnSUNBdkx5QmhJR3RsZVNCcGJpQnphVzExYkdGMFpTQm9ZWE1nYm04Z2JXRjBZMmhwYm1jZ2QyRnVkR1ZrSUd0bGVTd2djbVZ0YjNabElHbDBYRzRnSUNBZ0lDQWdJQ0FnSUNCbGJITmxJR2xtSUNoemFXMTFiR0YwWlVsMFpXMGdKaVlnYzJsdGRXeGhkR1ZKZEdWdExtdGxlU2tnZTF4dUlDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUhKbGJXOTJaWE11Y0hWemFDaHlaVzF2ZG1Vb2MybHRkV3hoZEdVc0lITnBiWFZzWVhSbFNXNWtaWGdzSUhOcGJYVnNZWFJsU1hSbGJTNXJaWGtwS1Z4dUlDQWdJQ0FnSUNBZ0lDQWdmVnh1SUNBZ0lDQWdJQ0I5WEc0Z0lDQWdJQ0FnSUdWc2MyVWdlMXh1SUNBZ0lDQWdJQ0FnSUNBZ2MybHRkV3hoZEdWSmJtUmxlQ3NyWEc0Z0lDQWdJQ0FnSUNBZ0lDQnJLeXRjYmlBZ0lDQWdJQ0FnZlZ4dUlDQWdJSDFjYmx4dUlDQWdJQzh2SUhKbGJXOTJaU0JoYkd3Z2RHaGxJSEpsYldGcGJtbHVaeUJ1YjJSbGN5Qm1jbTl0SUhOcGJYVnNZWFJsWEc0Z0lDQWdkMmhwYkdVb2MybHRkV3hoZEdWSmJtUmxlQ0E4SUhOcGJYVnNZWFJsTG14bGJtZDBhQ2tnZTF4dUlDQWdJQ0FnSUNCemFXMTFiR0YwWlVsMFpXMGdQU0J6YVcxMWJHRjBaVnR6YVcxMWJHRjBaVWx1WkdWNFhWeHVJQ0FnSUNBZ0lDQnlaVzF2ZG1WekxuQjFjMmdvY21WdGIzWmxLSE5wYlhWc1lYUmxMQ0J6YVcxMWJHRjBaVWx1WkdWNExDQnphVzExYkdGMFpVbDBaVzBnSmlZZ2MybHRkV3hoZEdWSmRHVnRMbXRsZVNrcFhHNGdJQ0FnZlZ4dVhHNGdJQ0FnTHk4Z1NXWWdkR2hsSUc5dWJIa2diVzkyWlhNZ2QyVWdhR0YyWlNCaGNtVWdaR1ZzWlhSbGN5QjBhR1Z1SUhkbElHTmhiaUJxZFhOMFhHNGdJQ0FnTHk4Z2JHVjBJSFJvWlNCa1pXeGxkR1VnY0dGMFkyZ2djbVZ0YjNabElIUm9aWE5sSUdsMFpXMXpMbHh1SUNBZ0lHbG1JQ2h5WlcxdmRtVnpMbXhsYm1kMGFDQTlQVDBnWkdWc1pYUmxaRWwwWlcxeklDWW1JQ0ZwYm5ObGNuUnpMbXhsYm1kMGFDa2dlMXh1SUNBZ0lDQWdJQ0J5WlhSMWNtNGdlMXh1SUNBZ0lDQWdJQ0FnSUNBZ1kyaHBiR1J5Wlc0NklHNWxkME5vYVd4a2NtVnVMRnh1SUNBZ0lDQWdJQ0FnSUNBZ2JXOTJaWE02SUc1MWJHeGNiaUFnSUNBZ0lDQWdmVnh1SUNBZ0lIMWNibHh1SUNBZ0lISmxkSFZ5YmlCN1hHNGdJQ0FnSUNBZ0lHTm9hV3hrY21WdU9pQnVaWGREYUdsc1pISmxiaXhjYmlBZ0lDQWdJQ0FnYlc5MlpYTTZJSHRjYmlBZ0lDQWdJQ0FnSUNBZ0lISmxiVzkyWlhNNklISmxiVzkyWlhNc1hHNGdJQ0FnSUNBZ0lDQWdJQ0JwYm5ObGNuUnpPaUJwYm5ObGNuUnpYRzRnSUNBZ0lDQWdJSDFjYmlBZ0lDQjlYRzU5WEc1Y2JtWjFibU4wYVc5dUlISmxiVzkyWlNoaGNuSXNJR2x1WkdWNExDQnJaWGtwSUh0Y2JpQWdJQ0JoY25JdWMzQnNhV05sS0dsdVpHVjRMQ0F4S1Z4dVhHNGdJQ0FnY21WMGRYSnVJSHRjYmlBZ0lDQWdJQ0FnWm5KdmJUb2dhVzVrWlhnc1hHNGdJQ0FnSUNBZ0lHdGxlVG9nYTJWNVhHNGdJQ0FnZlZ4dWZWeHVYRzVtZFc1amRHbHZiaUJyWlhsSmJtUmxlQ2hqYUdsc1pISmxiaWtnZTF4dUlDQWdJSFpoY2lCclpYbHpJRDBnZTMxY2JpQWdJQ0IyWVhJZ1puSmxaU0E5SUZ0ZFhHNGdJQ0FnZG1GeUlHeGxibWQwYUNBOUlHTm9hV3hrY21WdUxteGxibWQwYUZ4dVhHNGdJQ0FnWm05eUlDaDJZWElnYVNBOUlEQTdJR2tnUENCc1pXNW5kR2c3SUdrckt5a2dlMXh1SUNBZ0lDQWdJQ0IyWVhJZ1kyaHBiR1FnUFNCamFHbHNaSEpsYmx0cFhWeHVYRzRnSUNBZ0lDQWdJR2xtSUNoamFHbHNaQzVyWlhrcElIdGNiaUFnSUNBZ0lDQWdJQ0FnSUd0bGVYTmJZMmhwYkdRdWEyVjVYU0E5SUdsY2JpQWdJQ0FnSUNBZ2ZTQmxiSE5sSUh0Y2JpQWdJQ0FnSUNBZ0lDQWdJR1p5WldVdWNIVnphQ2hwS1Z4dUlDQWdJQ0FnSUNCOVhHNGdJQ0FnZlZ4dVhHNGdJQ0FnY21WMGRYSnVJSHRjYmlBZ0lDQWdJQ0FnYTJWNWN6b2dhMlY1Y3l3Z0lDQWdJQzh2SUVFZ2FHRnphQ0J2WmlCclpYa2dibUZ0WlNCMGJ5QnBibVJsZUZ4dUlDQWdJQ0FnSUNCbWNtVmxPaUJtY21WbElDQWdJQ0FnTHk4Z1FXNGdZWEp5WVhrZ2IyWWdkVzVyWlhsbFpDQnBkR1Z0SUdsdVpHbGpaWE5jYmlBZ0lDQjlYRzU5WEc1Y2JtWjFibU4wYVc5dUlHRndjR1Z1WkZCaGRHTm9LR0Z3Y0d4NUxDQndZWFJqYUNrZ2UxeHVJQ0FnSUdsbUlDaGhjSEJzZVNrZ2UxeHVJQ0FnSUNBZ0lDQnBaaUFvYVhOQmNuSmhlU2hoY0hCc2VTa3BJSHRjYmlBZ0lDQWdJQ0FnSUNBZ0lHRndjR3g1TG5CMWMyZ29jR0YwWTJncFhHNGdJQ0FnSUNBZ0lIMGdaV3h6WlNCN1hHNGdJQ0FnSUNBZ0lDQWdJQ0JoY0hCc2VTQTlJRnRoY0hCc2VTd2djR0YwWTJoZFhHNGdJQ0FnSUNBZ0lIMWNibHh1SUNBZ0lDQWdJQ0J5WlhSMWNtNGdZWEJ3YkhsY2JpQWdJQ0I5SUdWc2MyVWdlMXh1SUNBZ0lDQWdJQ0J5WlhSMWNtNGdjR0YwWTJoY2JpQWdJQ0I5WEc1OVhHNWNibjBzZTF3aUxpNHZkbTV2WkdVdmFHRnVaR3hsTFhSb2RXNXJYQ0k2TWpRc1hDSXVMaTkyYm05a1pTOXBjeTEwYUhWdWExd2lPakkxTEZ3aUxpNHZkbTV2WkdVdmFYTXRkbTV2WkdWY0lqb3lOeXhjSWk0dUwzWnViMlJsTDJsekxYWjBaWGgwWENJNk1qZ3NYQ0l1TGk5MmJtOWtaUzlwY3kxM2FXUm5aWFJjSWpveU9TeGNJaTR1TDNadWIyUmxMM1p3WVhSamFGd2lPak15TEZ3aUxpOWthV1ptTFhCeWIzQnpYQ0k2TXpRc1hDSjRMV2x6TFdGeWNtRjVYQ0k2TVRKOVhYMHNlMzBzV3pSZEtTZzBLVnh1ZlNrN1hHNWNibVY0Y0c5eWRDQmtaV1poZFd4MElGWnBjblIxWVd4RVQwMDdYRzRpWFN3aWMyOTFjbU5sVW05dmRDSTZJaTl6YjNWeVkyVXZJbjA9XG4iLCJpbXBvcnQgQ29yZSBmcm9tICcuL2xpYi9jb3JlJztcbmltcG9ydCBFbnVtIGZyb20gJy4vbGliL2VudW0nO1xuaW1wb3J0IFZpcnR1YWxET00gZnJvbSAnLi9saWIvdmlydHVhbC1kb20nO1xuXG5leHBvcnQgZGVmYXVsdCB7XG4gIENvcmUsXG4gIEVudW0sXG4gIFZpcnR1YWxET01cbn07XG4vLyMgc291cmNlTWFwcGluZ1VSTD1kYXRhOmFwcGxpY2F0aW9uL2pzb247YmFzZTY0LGV5SjJaWEp6YVc5dUlqb3pMQ0p6YjNWeVkyVnpJanBiSW1Wc2FYaHBjaTVxY3lKZExDSnVZVzFsY3lJNlcxMHNJbTFoY0hCcGJtZHpJam9pUVVGQlFTeFBRVUZQTEVsQlFWQXNUVUZCYVVJc1dVRkJha0k3UVVGRFFTeFBRVUZQTEVsQlFWQXNUVUZCYVVJc1dVRkJha0k3UVVGRFFTeFBRVUZQTEZWQlFWQXNUVUZCZFVJc2JVSkJRWFpDT3p0QlFVVkJMR1ZCUVdVN1FVRkRZaXhOUVVSaE8wRkJSV0lzVFVGR1lUdEJRVWRpTEZsQlNHRTdRMEZCWmlJc0ltWnBiR1VpT2lKbGJHbDRhWEl1YW5NaUxDSnpiM1Z5WTJWelEyOXVkR1Z1ZENJNld5SnBiWEJ2Y25RZ1EyOXlaU0JtY205dElDY3VMMnhwWWk5amIzSmxKenRjYm1sdGNHOXlkQ0JGYm5WdElHWnliMjBnSnk0dmJHbGlMMlZ1ZFcwbk8xeHVhVzF3YjNKMElGWnBjblIxWVd4RVQwMGdabkp2YlNBbkxpOXNhV0l2ZG1seWRIVmhiQzFrYjIwbk8xeHVYRzVsZUhCdmNuUWdaR1ZtWVhWc2RDQjdYRzRnSUVOdmNtVXNYRzRnSUVWdWRXMHNYRzRnSUZacGNuUjFZV3hFVDAxY2JuMDdYRzRpWFN3aWMyOTFjbU5sVW05dmRDSTZJaTl6YjNWeVkyVXZJbjA9XG4iXSwibmFtZXMiOlsiUHJpbWl0aXZlcy5QSUQiLCJUeXBlcy5WYXJpYWJsZSJdLCJtYXBwaW5ncyI6IkFBRUEsTUFBTSxPQUFPLENBQUM7O0VBRVosV0FBVyxHQUFHO0lBQ1osSUFBSSxDQUFDLFFBQVEsR0FBRyxFQUFFLENBQUM7R0FDcEI7O0VBRUQsT0FBTyxDQUFDLE9BQU8sRUFBRTtJQUNmLElBQUksQ0FBQyxRQUFRLENBQUMsSUFBSSxDQUFDLE9BQU8sQ0FBQyxDQUFDO0lBQzVCLE9BQU8sT0FBTyxDQUFDO0dBQ2hCOztFQUVELEdBQUcsR0FBRztJQUNKLE9BQU8sSUFBSSxDQUFDLFFBQVEsQ0FBQztHQUN0Qjs7RUFFRCxPQUFPLEdBQUc7SUFDUixPQUFPLElBQUksQ0FBQyxRQUFRLENBQUMsTUFBTSxLQUFLLENBQUMsQ0FBQztHQUNuQzs7RUFFRCxRQUFRLENB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 \ No newline at end of file +//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiRWxpeGlyLmpzIiwic291cmNlcyI6WyIuLi9zcmMvZWxpeGlyc2NyaXB0L2xpYi9jb3JlL3Byb2Nlc3Nlcy9tYWlsYm94LmpzIiwiLi4vc3JjL2VsaXhpcnNjcmlwdC9saWIvY29yZS9wcm9jZXNzZXMvc3RhdGVzLmpzIiwiLi4vc3JjL2VsaXhpcnNjcmlwdC9saWIvY29yZS9wcm9jZXNzZXMvcHJvY2Vzcy5qcyIsIi4uL3NyYy9lbGl4aXJzY3JpcHQvbGliL2NvcmUvcHJpbWl0aXZlcy5qcyIsIi4uL3NyYy9lbGl4aXJzY3JpcHQvbGliL2NvcmUvcHJvY2Vzc2VzL3Byb2Nlc3Nfc3lzdGVtLmpzIiwiLi4vc3JjL2VsaXhpcnNjcmlwdC9saWIvY29yZS9iaXRfc3RyaW5nLmpzIiwiLi4vc3JjL2VsaXhpcnNjcmlwdC9saWIvY29yZS9wYXR0ZXJucy90eXBlcy5qcyIsIi4uL3NyYy9lbGl4aXJzY3JpcHQvbGliL2NvcmUvcGF0dGVybnMvY2hlY2tzLmpzIiwiLi4vc3JjL2VsaXhpcnNjcmlwdC9saWIvY29yZS9wYXR0ZXJucy9yZXNvbHZlcnMuanMiLCIuLi9zcmMvZWxpeGlyc2NyaXB0L2xpYi9jb3JlL3BhdHRlcm5zL21hdGNoLmpzIiwiLi4vc3JjL2VsaXhpcnNjcmlwdC9saWIvY29yZS9wYXR0ZXJucy9kZWZtYXRjaC5qcyIsIi4uL3NyYy9lbGl4aXJzY3JpcHQvbGliL2NvcmUvcGF0dGVybnMuanMiLCIuLi9zcmMvZWxpeGlyc2NyaXB0L2xpYi9jb3JlL3Byb3RvY29sLmpzIiwiLi4vc3JjL2VsaXhpcnNjcmlwdC9saWIvY29yZS9mdW5jdGlvbnMuanMiLCIuLi9zcmMvZWxpeGlyc2NyaXB0L2xpYi9jb3JlL3NwZWNpYWxfZm9ybXMuanMiLCIuLi9zcmMvZWxpeGlyc2NyaXB0L2xpYi9jb3JlLmpzIiwiLi4vc3JjL2VsaXhpcnNjcmlwdC9saWIvZW51bS5qcyIsIi4uL3NyYy9lbGl4aXJzY3JpcHQvbGliL3ZpcnR1YWwtZG9tLmpzIiwiLi4vc3JjL2VsaXhpcnNjcmlwdC9lbGl4aXIuanMiXSwic291cmNlc0NvbnRlbnQiOlsiXCJ1c2Ugc3RyaWN0XCI7XG5cbmNsYXNzIE1haWxib3gge1xuXG4gIGNvbnN0cnVjdG9yKCkge1xuICAgIHRoaXMubWVzc2FnZXMgPSBbXTtcbiAgfVxuXG4gIGRlbGl2ZXIobWVzc2FnZSkge1xuICAgIHRoaXMubWVzc2FnZXMucHVzaChtZXNzYWdlKTtcbiAgICByZXR1cm4gbWVzc2FnZTtcbiAgfVxuXG4gIGdldCgpIHtcbiAgICByZXR1cm4gdGhpcy5tZXNzYWdlcztcbiAgfVxuXG4gIGlzRW1wdHkoKSB7XG4gICAgcmV0dXJuIHRoaXMubWVzc2FnZXMubGVuZ3RoID09PSAwO1xuICB9XG5cbiAgcmVtb3ZlQXQoaW5kZXgpIHtcbiAgICB0aGlzLm1lc3NhZ2VzLnNwbGljZShpbmRleCwgMSk7XG4gIH1cbn1cblxuZXhwb3J0IGRlZmF1bHQgTWFpbGJveDtcbi8vIyBzb3VyY2VNYXBwaW5nVVJMPWRhdGE6YXBwbGljYXRpb24vanNvbjtiYXNlNjQsZXlKMlpYSnphVzl1SWpvekxDSnpiM1Z5WTJWeklqcGJJbXhwWWk5amIzSmxMM0J5YjJObGMzTmxjeTl0WVdsc1ltOTRMbXB6SWwwc0ltNWhiV1Z6SWpwYlhTd2liV0Z3Y0dsdVozTWlPaUpCUVVGQk96dEJRVWxCTEUxQlFVMHNUMEZCVGl4RFFVRmhPenRCUVVkWUxHZENRVUZoTzBGQlExZ3NVMEZCU3l4UlFVRk1MRWRCUVdkQ0xFVkJRV2hDTEVOQlJGYzdSMEZCWWpzN1FVRkpRU3hWUVVGUkxFOUJRVklzUlVGQmNVSTdRVUZEYmtJc1UwRkJTeXhSUVVGTUxFTkJRV01zU1VGQlpDeERRVUZ0UWl4UFFVRnVRaXhGUVVSdFFqdEJRVVZ1UWl4WFFVRlBMRTlCUVZBc1EwRkdiVUk3UjBGQmNrSTdPMEZCUzBFc1VVRkJTenRCUVVOSUxGZEJRVThzUzBGQlN5eFJRVUZNTEVOQlJFbzdSMEZCVERzN1FVRkpRU3haUVVGVE8wRkJRMUFzVjBGQlR5eExRVUZMTEZGQlFVd3NRMEZCWXl4TlFVRmtMRXRCUVhsQ0xFTkJRWHBDTEVOQlJFRTdSMEZCVkRzN1FVRkpRU3hYUVVGVExFdEJRVlFzUlVGQlpUdEJRVU5pTEZOQlFVc3NVVUZCVEN4RFFVRmpMRTFCUVdRc1EwRkJjVUlzUzBGQmNrSXNSVUZCTkVJc1EwRkJOVUlzUlVGRVlUdEhRVUZtTzBOQmNFSkdPenRCUVhsQ1FTeGxRVUZsTEU5QlFXWWlMQ0ptYVd4bElqb2liR2xpTDJOdmNtVXZjSEp2WTJWemMyVnpMMjFoYVd4aWIzZ3Vhbk1pTENKemIzVnlZMlZ6UTI5dWRHVnVkQ0k2V3lKY0luVnpaU0J6ZEhKcFkzUmNJanRjYmx4dUx5b2dRR1pzYjNjZ0tpOWNibHh1WTJ4aGMzTWdUV0ZwYkdKdmVIdGNiaUFnYldWemMyRm5aWE02SUVGeWNtRjVQR0Z1ZVQ1Y2JseHVJQ0JqYjI1emRISjFZM1J2Y2lncGUxeHVJQ0FnSUhSb2FYTXViV1Z6YzJGblpYTWdQU0JiWFR0Y2JpQWdmVnh1WEc0Z0lHUmxiR2wyWlhJb2JXVnpjMkZuWlRvZ1lXNTVLWHRjYmlBZ0lDQjBhR2x6TG0xbGMzTmhaMlZ6TG5CMWMyZ29iV1Z6YzJGblpTazdYRzRnSUNBZ2NtVjBkWEp1SUcxbGMzTmhaMlU3WEc0Z0lIMWNibHh1SUNCblpYUW9LWHRjYmlBZ0lDQnlaWFIxY200Z2RHaHBjeTV0WlhOellXZGxjenRjYmlBZ2ZWeHVYRzRnSUdselJXMXdkSGtvS1h0Y2JpQWdJQ0J5WlhSMWNtNGdkR2hwY3k1dFpYTnpZV2RsY3k1c1pXNW5kR2dnUFQwOUlEQTdYRzRnSUgxY2JseHVJQ0J5WlcxdmRtVkJkQ2hwYm1SbGVDbDdYRzRnSUNBZ2RHaHBjeTV0WlhOellXZGxjeTV6Y0d4cFkyVW9hVzVrWlhnc0lERXBPMXh1SUNCOVhHNTlYRzVjYm1WNGNHOXlkQ0JrWldaaGRXeDBJRTFoYVd4aWIzZzdJbDBzSW5OdmRYSmpaVkp2YjNRaU9pSXZjMjkxY21ObEx5SjlcbiIsImV4cG9ydCBkZWZhdWx0IHtcbiAgTk9STUFMOiBTeW1ib2wuZm9yKFwibm9ybWFsXCIpLFxuICBLSUxMOiBTeW1ib2wuZm9yKFwia2lsbFwiKSxcbiAgU1VTUEVORDogU3ltYm9sLmZvcihcInN1c3BlbmRcIiksXG4gIENPTlRJTlVFOiBTeW1ib2wuZm9yKFwiY29udGludWVcIiksXG4gIFJFQ0VJVkU6IFN5bWJvbC5mb3IoXCJyZWNlaXZlXCIpLFxuICBTRU5EOiBTeW1ib2wuZm9yKFwic2VuZFwiKSxcbiAgU0xFRVBJTkc6IFN5bWJvbC5mb3IoXCJzbGVlcGluZ1wiKSxcbiAgUlVOTklORzogU3ltYm9sLmZvcihcInJ1bm5pbmdcIiksXG4gIFNVU1BFTkRFRDogU3ltYm9sLmZvcihcInN1c3BlbmRlZFwiKSxcbiAgU1RPUFBFRDogU3ltYm9sLmZvcihcInN0b3BwZWRcIiksXG4gIFNMRUVQOiBTeW1ib2wuZm9yKFwic2xlZXBcIiksXG4gIEVYSVQ6IFN5bWJvbC5mb3IoXCJleGl0XCIpLFxuICBOT01BVENIOiBTeW1ib2wuZm9yKFwibm9fbWF0Y2hcIilcbn07XG4vLyMgc291cmNlTWFwcGluZ1VSTD1kYXRhOmFwcGxpY2F0aW9uL2pzb247YmFzZTY0LGV5SjJaWEp6YVc5dUlqb3pMQ0p6YjNWeVkyVnpJanBiSW14cFlpOWpiM0psTDNCeWIyTmxjM05sY3k5emRHRjBaWE11YW5NaVhTd2libUZ0WlhNaU9sdGRMQ0p0WVhCd2FXNW5jeUk2SWtGQlFVRXNaVUZCWlR0QlFVTmlMRlZCUVZFc1QwRkJUeXhIUVVGUUxFTkJRVmNzVVVGQldDeERRVUZTTzBGQlEwRXNVVUZCVFN4UFFVRlBMRWRCUVZBc1EwRkJWeXhOUVVGWUxFTkJRVTQ3UVVGRFFTeFhRVUZUTEU5QlFVOHNSMEZCVUN4RFFVRlhMRk5CUVZnc1EwRkJWRHRCUVVOQkxGbEJRVlVzVDBGQlR5eEhRVUZRTEVOQlFWY3NWVUZCV0N4RFFVRldPMEZCUTBFc1YwRkJVeXhQUVVGUExFZEJRVkFzUTBGQlZ5eFRRVUZZTEVOQlFWUTdRVUZEUVN4UlFVRk5MRTlCUVU4c1IwRkJVQ3hEUVVGWExFMUJRVmdzUTBGQlRqdEJRVU5CTEZsQlFWVXNUMEZCVHl4SFFVRlFMRU5CUVZjc1ZVRkJXQ3hEUVVGV08wRkJRMEVzVjBGQlV5eFBRVUZQTEVkQlFWQXNRMEZCVnl4VFFVRllMRU5CUVZRN1FVRkRRU3hoUVVGWExFOUJRVThzUjBGQlVDeERRVUZYTEZkQlFWZ3NRMEZCV0R0QlFVTkJMRmRCUVZNc1QwRkJUeXhIUVVGUUxFTkJRVmNzVTBGQldDeERRVUZVTzBGQlEwRXNVMEZCVHl4UFFVRlBMRWRCUVZBc1EwRkJWeXhQUVVGWUxFTkJRVkE3UVVGRFFTeFJRVUZOTEU5QlFVOHNSMEZCVUN4RFFVRlhMRTFCUVZnc1EwRkJUanRCUVVOQkxGZEJRVk1zVDBGQlR5eEhRVUZRTEVOQlFWY3NWVUZCV0N4RFFVRlVPME5CWWtZaUxDSm1hV3hsSWpvaWJHbGlMMk52Y21VdmNISnZZMlZ6YzJWekwzTjBZWFJsY3k1cWN5SXNJbk52ZFhKalpYTkRiMjUwWlc1MElqcGJJbVY0Y0c5eWRDQmtaV1poZFd4MElIdGNiaUFnVGs5U1RVRk1PaUJUZVcxaWIyd3VabTl5S0Z3aWJtOXliV0ZzWENJcExGeHVJQ0JMU1V4TU9pQlRlVzFpYjJ3dVptOXlLRndpYTJsc2JGd2lLU3hjYmlBZ1UxVlRVRVZPUkRvZ1UzbHRZbTlzTG1admNpaGNJbk4xYzNCbGJtUmNJaWtzWEc0Z0lFTlBUbFJKVGxWRk9pQlRlVzFpYjJ3dVptOXlLRndpWTI5dWRHbHVkV1ZjSWlrc1hHNGdJRkpGUTBWSlZrVTZJRk41YldKdmJDNW1iM0lvWENKeVpXTmxhWFpsWENJcExGeHVJQ0JUUlU1RU9pQlRlVzFpYjJ3dVptOXlLRndpYzJWdVpGd2lLU3hjYmlBZ1UweEZSVkJKVGtjNklGTjViV0p2YkM1bWIzSW9YQ0p6YkdWbGNHbHVaMXdpS1N4Y2JpQWdVbFZPVGtsT1J6b2dVM2x0WW05c0xtWnZjaWhjSW5KMWJtNXBibWRjSWlrc1hHNGdJRk5WVTFCRlRrUkZSRG9nVTNsdFltOXNMbVp2Y2loY0luTjFjM0JsYm1SbFpGd2lLU3hjYmlBZ1UxUlBVRkJGUkRvZ1UzbHRZbTlzTG1admNpaGNJbk4wYjNCd1pXUmNJaWtzWEc0Z0lGTk1SVVZRT2lCVGVXMWliMnd1Wm05eUtGd2ljMnhsWlhCY0lpa3NYRzRnSUVWWVNWUTZJRk41YldKdmJDNW1iM0lvWENKbGVHbDBYQ0lwTEZ4dUlDQk9UMDFCVkVOSU9pQlRlVzFpYjJ3dVptOXlLRndpYm05ZmJXRjBZMmhjSWlsY2JuMGlYU3dpYzI5MWNtTmxVbTl2ZENJNklpOXpiM1Z5WTJVdkluMD1cbiIsIlwidXNlIHN0cmljdFwiO1xuXG5pbXBvcnQgTWFpbGJveCBmcm9tIFwiLi9tYWlsYm94XCI7XG5pbXBvcnQgU3RhdGVzIGZyb20gXCIuL3N0YXRlc1wiO1xuXG5jbGFzcyBQcm9jZXNzIHtcblxuICBjb25zdHJ1Y3RvcihwaWQsIG1haWxib3gpIHtcbiAgICB0aGlzLnBpZCA9IHBpZDtcbiAgICB0aGlzLm1haWxib3ggPSBtYWlsYm94O1xuICAgIHRoaXMuc3RhdHVzID0gU3RhdGVzLlNUT1BQRUQ7XG4gICAgdGhpcy5kaWN0ID0ge307XG4gIH1cbn1cblxuZXhwb3J0IGRlZmF1bHQgUHJvY2Vzcztcbi8vIyBzb3VyY2VNYXBwaW5nVVJMPWRhdGE6YXBwbGljYXRpb24vanNvbjtiYXNlNjQsZXlKMlpYSnphVzl1SWpvekxDSnpiM1Z5WTJWeklqcGJJbXhwWWk5amIzSmxMM0J5YjJObGMzTmxjeTl3Y205alpYTnpMbXB6SWwwc0ltNWhiV1Z6SWpwYlhTd2liV0Z3Y0dsdVozTWlPaUpCUVVGQk96dEJRVWRCTEU5QlFVOHNUMEZCVUN4TlFVRnZRaXhYUVVGd1FqdEJRVU5CTEU5QlFVOHNUVUZCVUN4TlFVRnRRaXhWUVVGdVFqczdRVUZGUVN4TlFVRk5MRTlCUVU0c1EwRkJZenM3UVVGTFdpeGpRVUZaTEVkQlFWb3NSVUZCZVVJc1QwRkJla0lzUlVGQk1FTTdRVUZEZUVNc1UwRkJTeXhIUVVGTUxFZEJRVmNzUjBGQldDeERRVVIzUXp0QlFVVjRReXhUUVVGTExFOUJRVXdzUjBGQlpTeFBRVUZtTEVOQlJuZERPMEZCUjNoRExGTkJRVXNzVFVGQlRDeEhRVUZqTEU5QlFVOHNUMEZCVUN4RFFVZ3dRanRCUVVsNFF5eFRRVUZMTEVsQlFVd3NSMEZCV1N4RlFVRmFMRU5CU25kRE8wZEJRVEZETzBOQlRFWTdPMEZCWVVFc1pVRkJaU3hQUVVGbUlpd2labWxzWlNJNklteHBZaTlqYjNKbEwzQnliMk5sYzNObGN5OXdjbTlqWlhOekxtcHpJaXdpYzI5MWNtTmxjME52Ym5SbGJuUWlPbHNpWENKMWMyVWdjM1J5YVdOMFhDSTdYRzVjYmk4cUlFQm1iRzkzSUNvdlhHNXBiWEJ2Y25RZ1RXRnBiR0p2ZUNCbWNtOXRJRndpTGk5dFlXbHNZbTk0WENJN1hHNXBiWEJ2Y25RZ1UzUmhkR1Z6SUdaeWIyMGdYQ0l1TDNOMFlYUmxjMXdpTzF4dVhHNWpiR0Z6Y3lCUWNtOWpaWE56SUh0Y2JpQWdjR2xrT2lCT2RXMWlaWEk3WEc0Z0lHMWhhV3hpYjNnNklFMWhhV3hpYjNnN1hHNGdJR1JwWTNRNklFOWlhbVZqZER0Y2JseHVJQ0JqYjI1emRISjFZM1J2Y2lod2FXUTZJRTUxYldKbGNpd2diV0ZwYkdKdmVEb2dUV0ZwYkdKdmVDbDdYRzRnSUNBZ2RHaHBjeTV3YVdRZ1BTQndhV1E3WEc0Z0lDQWdkR2hwY3k1dFlXbHNZbTk0SUQwZ2JXRnBiR0p2ZUR0Y2JpQWdJQ0IwYUdsekxuTjBZWFIxY3lBOUlGTjBZWFJsY3k1VFZFOVFVRVZFTzF4dUlDQWdJSFJvYVhNdVpHbGpkQ0E5SUh0OU8xeHVJQ0I5WEc1OVhHNWNibVY0Y0c5eWRDQmtaV1poZFd4MElGQnliMk5sYzNNN1hHNGlYU3dpYzI5MWNtTmxVbTl2ZENJNklpOXpiM1Z5WTJVdkluMD1cbiIsImNsYXNzIFR1cGxlIHtcblxuICBjb25zdHJ1Y3RvciguLi5hcmdzKSB7XG4gICAgdGhpcy52YWx1ZXMgPSBPYmplY3QuZnJlZXplKGFyZ3MpO1xuICAgIHRoaXMubGVuZ3RoID0gdGhpcy52YWx1ZXMubGVuZ3RoO1xuICB9XG5cbiAgZ2V0KGluZGV4KSB7XG4gICAgcmV0dXJuIHRoaXMudmFsdWVzW2luZGV4XTtcbiAgfVxuXG4gIGNvdW50KCkge1xuICAgIHJldHVybiB0aGlzLnZhbHVlcy5sZW5ndGg7XG4gIH1cblxuICBbU3ltYm9sLml0ZXJhdG9yXSgpIHtcbiAgICByZXR1cm4gdGhpcy52YWx1ZXNbU3ltYm9sLml0ZXJhdG9yXSgpO1xuICB9XG5cbiAgdG9TdHJpbmcoKSB7XG4gICAgdmFyIGksXG4gICAgICAgIHMgPSBcIlwiO1xuICAgIGZvciAoaSA9IDA7IGkgPCB0aGlzLnZhbHVlcy5sZW5ndGg7IGkrKykge1xuICAgICAgaWYgKHMgIT09IFwiXCIpIHtcbiAgICAgICAgcyArPSBcIiwgXCI7XG4gICAgICB9XG4gICAgICBzICs9IHRoaXMudmFsdWVzW2ldLnRvU3RyaW5nKCk7XG4gICAgfVxuXG4gICAgcmV0dXJuIFwie1wiICsgcyArIFwifVwiO1xuICB9XG5cbiAgcHV0X2VsZW0oaW5kZXgsIGVsZW0pIHtcbiAgICBpZiAoaW5kZXggPT09IHRoaXMubGVuZ3RoKSB7XG4gICAgICBsZXQgbmV3X3ZhbHVlcyA9IHRoaXMudmFsdWVzLmNvbmNhdChbZWxlbV0pO1xuICAgICAgcmV0dXJuIG5ldyBUdXBsZSguLi5uZXdfdmFsdWVzKTtcbiAgICB9XG5cbiAgICBsZXQgbmV3X3ZhbHVlcyA9IHRoaXMudmFsdWVzLmNvbmNhdChbXSk7XG4gICAgbmV3X3ZhbHVlcy5zcGxpY2UoaW5kZXgsIDAsIGVsZW0pO1xuICAgIHJldHVybiBuZXcgVHVwbGUoLi4ubmV3X3ZhbHVlcyk7XG4gIH1cblxuICByZW1vdmVfZWxlbShpbmRleCkge1xuICAgIGxldCBuZXdfdmFsdWVzID0gdGhpcy52YWx1ZXMuY29uY2F0KFtdKTtcbiAgICBuZXdfdmFsdWVzLnNwbGljZShpbmRleCwgMSk7XG4gICAgcmV0dXJuIG5ldyBUdXBsZSguLi5uZXdfdmFsdWVzKTtcbiAgfVxuXG59XG5cbmxldCBwcm9jZXNzX2NvdW50ZXIgPSAtMTtcblxuY2xhc3MgUElEIHtcbiAgY29uc3RydWN0b3IoKSB7XG4gICAgcHJvY2Vzc19jb3VudGVyID0gcHJvY2Vzc19jb3VudGVyICsgMTtcbiAgICB0aGlzLmlkID0gcHJvY2Vzc19jb3VudGVyO1xuICB9XG5cbiAgdG9TdHJpbmcoKSB7XG4gICAgcmV0dXJuIFwiUElEIzwwLlwiICsgdGhpcy5pZCArIFwiLjA+XCI7XG4gIH1cbn1cblxuY2xhc3MgSW50ZWdlciB7fVxuY2xhc3MgRmxvYXQge31cblxuZXhwb3J0IHsgUElELCBUdXBsZSwgSW50ZWdlciwgRmxvYXQgfTtcbi8vIyBzb3VyY2VNYXBwaW5nVVJMPWRhdGE6YXBwbGljYXRpb24vanNvbjtiYXNlNjQsZXlKMlpYSnphVzl1SWpvekxDSnpiM1Z5WTJWeklqcGJJbXhwWWk5amIzSmxMM0J5YVcxcGRHbDJaWE11YW5NaVhTd2libUZ0WlhNaU9sdGRMQ0p0WVhCd2FXNW5jeUk2SWtGQlFVRXNUVUZCVFN4TFFVRk9MRU5CUVZrN08wRkJSVllzWTBGQldTeEhRVUZITEVsQlFVZ3NSVUZCVVR0QlFVTnNRaXhUUVVGTExFMUJRVXdzUjBGQll5eFBRVUZQTEUxQlFWQXNRMEZCWXl4SlFVRmtMRU5CUVdRc1EwRkVhMEk3UVVGRmJFSXNVMEZCU3l4TlFVRk1MRWRCUVdNc1MwRkJTeXhOUVVGTUxFTkJRVmtzVFVGQldpeERRVVpKTzBkQlFYQkNPenRCUVV0QkxFMUJRVWtzUzBGQlNpeEZRVUZYTzBGQlExUXNWMEZCVHl4TFFVRkxMRTFCUVV3c1EwRkJXU3hMUVVGYUxFTkJRVkFzUTBGRVV6dEhRVUZZT3p0QlFVbEJMRlZCUVZFN1FVRkRUaXhYUVVGUExFdEJRVXNzVFVGQlRDeERRVUZaTEUxQlFWb3NRMEZFUkR0SFFVRlNPenRCUVVsQkxFZEJRVU1zVDBGQlR5eFJRVUZRTEVsQlFXMUNPMEZCUTJ4Q0xGZEJRVThzUzBGQlN5eE5RVUZNTEVOQlFWa3NUMEZCVHl4UlFVRlFMRU5CUVZvc1JVRkJVQ3hEUVVSclFqdEhRVUZ3UWpzN1FVRkpRU3hoUVVGWE8wRkJRMVFzVVVGQlNTeERRVUZLTzFGQlFVOHNTVUZCU1N4RlFVRktMRU5CUkVVN1FVRkZWQ3hUUVVGTExFbEJRVWtzUTBGQlNpeEZRVUZQTEVsQlFVa3NTMEZCU3l4TlFVRk1MRU5CUVZrc1RVRkJXaXhGUVVGdlFpeEhRVUZ3UXl4RlFVRjVRenRCUVVOMlF5eFZRVUZKTEUxQlFVMHNSVUZCVGl4RlFVRlZPMEZCUTFvc1lVRkJTeXhKUVVGTUxFTkJSRms3VDBGQlpEdEJRVWRCTEZkQlFVc3NTMEZCU3l4TlFVRk1MRU5CUVZrc1EwRkJXaXhGUVVGbExGRkJRV1lzUlVGQlRDeERRVXAxUXp0TFFVRjZRenM3UVVGUFFTeFhRVUZQTEUxQlFVMHNRMEZCVGl4SFFVRlZMRWRCUVZZc1EwRlVSVHRIUVVGWU96dEJRVmxCTEZkQlFWTXNTMEZCVkN4RlFVRm5RaXhKUVVGb1FpeEZRVUZ4UWp0QlFVTnVRaXhSUVVGSExGVkJRVlVzUzBGQlN5eE5RVUZNTEVWQlFWazdRVUZEZGtJc1ZVRkJTU3hoUVVGaExFdEJRVXNzVFVGQlRDeERRVUZaTEUxQlFWb3NRMEZCYlVJc1EwRkJReXhKUVVGRUxFTkJRVzVDTEVOQlFXSXNRMEZFYlVJN1FVRkZka0lzWVVGQlR5eEpRVUZKTEV0QlFVb3NRMEZCVlN4SFFVRkhMRlZCUVVnc1EwRkJha0lzUTBGR2RVSTdTMEZCZWtJN08wRkJTMEVzVVVGQlNTeGhRVUZoTEV0QlFVc3NUVUZCVEN4RFFVRlpMRTFCUVZvc1EwRkJiVUlzUlVGQmJrSXNRMEZCWWl4RFFVNWxPMEZCVDI1Q0xHVkJRVmNzVFVGQldDeERRVUZyUWl4TFFVRnNRaXhGUVVGNVFpeERRVUY2UWl4RlFVRTBRaXhKUVVFMVFpeEZRVkJ0UWp0QlFWRnVRaXhYUVVGUExFbEJRVWtzUzBGQlNpeERRVUZWTEVkQlFVY3NWVUZCU0N4RFFVRnFRaXhEUVZKdFFqdEhRVUZ5UWpzN1FVRlhRU3hqUVVGWkxFdEJRVm9zUlVGQmEwSTdRVUZEYUVJc1VVRkJTU3hoUVVGaExFdEJRVXNzVFVGQlRDeERRVUZaTEUxQlFWb3NRMEZCYlVJc1JVRkJia0lzUTBGQllpeERRVVJaTzBGQlJXaENMR1ZCUVZjc1RVRkJXQ3hEUVVGclFpeExRVUZzUWl4RlFVRjVRaXhEUVVGNlFpeEZRVVpuUWp0QlFVZG9RaXhYUVVGUExFbEJRVWtzUzBGQlNpeERRVUZWTEVkQlFVY3NWVUZCU0N4RFFVRnFRaXhEUVVoblFqdEhRVUZzUWpzN1EwRXhRMFk3TzBGQmJVUkJMRWxCUVVrc2EwSkJRV3RDTEVOQlFVTXNRMEZCUkRzN1FVRkZkRUlzVFVGQlRTeEhRVUZPTEVOQlFWVTdRVUZEVWl4blFrRkJZVHRCUVVOWUxITkNRVUZyUWl4clFrRkJhMElzUTBGQmJFSXNRMEZFVUR0QlFVVllMRk5CUVVzc1JVRkJUQ3hIUVVGVkxHVkJRVllzUTBGR1Z6dEhRVUZpT3p0QlFVdEJMR0ZCUVZVN1FVRkRVaXhYUVVGUExGbEJRVmtzUzBGQlN5eEZRVUZNTEVkQlFWVXNTMEZCZEVJc1EwRkVRenRIUVVGV08wTkJUa1k3TzBGQlYwRXNUVUZCVFN4UFFVRk9MRU5CUVdNc1JVRkJaRHRCUVVOQkxFMUJRVTBzUzBGQlRpeERRVUZaTEVWQlFWbzdPMEZCUlVFc1UwRkJVeXhIUVVGVUxFVkJRV01zUzBGQlpDeEZRVUZ4UWl4UFFVRnlRaXhGUVVFNFFpeExRVUU1UWlJc0ltWnBiR1VpT2lKc2FXSXZZMjl5WlM5d2NtbHRhWFJwZG1WekxtcHpJaXdpYzI5MWNtTmxjME52Ym5SbGJuUWlPbHNpWTJ4aGMzTWdWSFZ3YkdVZ2UxeHVYRzRnSUdOdmJuTjBjblZqZEc5eUtDNHVMbUZ5WjNNcGUxeHVJQ0FnSUhSb2FYTXVkbUZzZFdWeklEMGdUMkpxWldOMExtWnlaV1Y2WlNoaGNtZHpLVHRjYmlBZ0lDQjBhR2x6TG14bGJtZDBhQ0E5SUhSb2FYTXVkbUZzZFdWekxteGxibWQwYUR0Y2JpQWdmVnh1WEc0Z0lHZGxkQ2hwYm1SbGVDa2dlMXh1SUNBZ0lISmxkSFZ5YmlCMGFHbHpMblpoYkhWbGMxdHBibVJsZUYwN1hHNGdJSDFjYmx4dUlDQmpiM1Z1ZENncElIdGNiaUFnSUNCeVpYUjFjbTRnZEdocGN5NTJZV3gxWlhNdWJHVnVaM1JvTzF4dUlDQjlYRzVjYmlBZ1cxTjViV0p2YkM1cGRHVnlZWFJ2Y2wwb0tTQjdYRzRnSUNBZ2NtVjBkWEp1SUhSb2FYTXVkbUZzZFdWelcxTjViV0p2YkM1cGRHVnlZWFJ2Y2wwb0tUdGNiaUFnZlZ4dVhHNGdJSFJ2VTNSeWFXNW5LQ2tnZTF4dUlDQWdJSFpoY2lCcExDQnpJRDBnWENKY0lqdGNiaUFnSUNCbWIzSWdLR2tnUFNBd095QnBJRHdnZEdocGN5NTJZV3gxWlhNdWJHVnVaM1JvT3lCcEt5c3BJSHRjYmlBZ0lDQWdJR2xtSUNoeklDRTlQU0JjSWx3aUtTQjdYRzRnSUNBZ0lDQWdJSE1nS3owZ1hDSXNJRndpTzF4dUlDQWdJQ0FnZlZ4dUlDQWdJQ0FnY3lBclBTQjBhR2x6TG5aaGJIVmxjMXRwWFM1MGIxTjBjbWx1WnlncE8xeHVJQ0FnSUgxY2JseHVJQ0FnSUhKbGRIVnliaUJjSW50Y0lpQXJJSE1nS3lCY0luMWNJanRjYmlBZ2ZWeHVYRzRnSUhCMWRGOWxiR1Z0S0dsdVpHVjRMQ0JsYkdWdEtYdGNiaUFnSUNCcFppaHBibVJsZUNBOVBUMGdkR2hwY3k1c1pXNW5kR2dwZTF4dUlDQWdJQ0FnYkdWMElHNWxkMTkyWVd4MVpYTWdQU0IwYUdsekxuWmhiSFZsY3k1amIyNWpZWFFvVzJWc1pXMWRLVHRjYmlBZ0lDQWdJSEpsZEhWeWJpQnVaWGNnVkhWd2JHVW9MaTR1Ym1WM1gzWmhiSFZsY3lrN1hHNGdJQ0FnZlZ4dVhHNGdJQ0FnYkdWMElHNWxkMTkyWVd4MVpYTWdQU0IwYUdsekxuWmhiSFZsY3k1amIyNWpZWFFvVzEwcE8xeHVJQ0FnSUc1bGQxOTJZV3gxWlhNdWMzQnNhV05sS0dsdVpHVjRMQ0F3TENCbGJHVnRLVHRjYmlBZ0lDQnlaWFIxY200Z2JtVjNJRlIxY0d4bEtDNHVMbTVsZDE5MllXeDFaWE1wTzF4dUlDQjlYRzVjYmlBZ2NtVnRiM1psWDJWc1pXMG9hVzVrWlhncGUxeHVJQ0FnSUd4bGRDQnVaWGRmZG1Gc2RXVnpJRDBnZEdocGN5NTJZV3gxWlhNdVkyOXVZMkYwS0Z0ZEtUdGNiaUFnSUNCdVpYZGZkbUZzZFdWekxuTndiR2xqWlNocGJtUmxlQ3dnTVNrN1hHNGdJQ0FnY21WMGRYSnVJRzVsZHlCVWRYQnNaU2d1TGk1dVpYZGZkbUZzZFdWektUdGNiaUFnZlZ4dVhHNTlYRzVjYmx4dWJHVjBJSEJ5YjJObGMzTmZZMjkxYm5SbGNpQTlJQzB4TzF4dVhHNWpiR0Z6Y3lCUVNVUWdlMXh1SUNCamIyNXpkSEoxWTNSdmNpZ3BlMXh1SUNBZ0lIQnliMk5sYzNOZlkyOTFiblJsY2lBOUlIQnliMk5sYzNOZlkyOTFiblJsY2lBcklERTdYRzRnSUNBZ2RHaHBjeTVwWkNBOUlIQnliMk5sYzNOZlkyOTFiblJsY2p0Y2JpQWdmVnh1WEc0Z0lIUnZVM1J5YVc1bktDbDdYRzRnSUNBZ2NtVjBkWEp1SUZ3aVVFbEVJend3TGx3aUlDc2dkR2hwY3k1cFpDQXJJRndpTGpBK1hDSTdYRzRnSUgxY2JuMWNibHh1WTJ4aGMzTWdTVzUwWldkbGNpQjdmVnh1WTJ4aGMzTWdSbXh2WVhRZ2UzMWNibHh1Wlhod2IzSjBJSHNnVUVsRUxDQlVkWEJzWlN3Z1NXNTBaV2RsY2l3Z1JteHZZWFFnZlR0Y2JpSmRMQ0p6YjNWeVkyVlNiMjkwSWpvaUwzTnZkWEpqWlM4aWZRPT1cbiIsIlxuXCJ1c2Ugc3RyaWN0XCI7XG5cbmltcG9ydCBNYWlsYm94IGZyb20gXCIuL21haWxib3hcIjtcbmltcG9ydCBQcm9jZXNzIGZyb20gXCIuL3Byb2Nlc3NcIjtcbmltcG9ydCBTdGF0ZXMgZnJvbSBcIi4vc3RhdGVzXCI7XG5pbXBvcnQgKiBhcyBQcmltaXRpdmVzIGZyb20gXCIuLi9wcmltaXRpdmVzXCI7XG5cbmNsYXNzIFByb2Nlc3NTeXN0ZW0ge1xuXG4gIGNvbnN0cnVjdG9yKCkge1xuICAgIHRoaXMucGlkcyA9IG5ldyBNYXAoKTtcbiAgICB0aGlzLm1haWxib3hlcyA9IG5ldyBNYXAoKTtcbiAgICB0aGlzLm5hbWVzID0gbmV3IE1hcCgpO1xuICAgIHRoaXMubGlua3MgPSBuZXcgTWFwKCk7XG5cbiAgICB0aGlzLmN1cnJlbnRfcHJvY2VzcyA9IG51bGw7XG4gICAgdGhpcy5zdXNwZW5kZWQgPSBuZXcgTWFwKCk7XG5cbiAgICB0aGlzLm1haW5fcHJvY2Vzc19waWQgPSB0aGlzLnNwYXduKCk7XG4gICAgdGhpcy5zZXRfY3VycmVudCh0aGlzLm1haW5fcHJvY2Vzc19waWQpO1xuICB9XG5cbiAgc3Bhd24oKSB7XG4gICAgcmV0dXJuIHRoaXMuYWRkX3Byb2MoZmFsc2UpLnBpZDtcbiAgfVxuXG4gIHNwYXduX2xpbmsoKSB7XG4gICAgcmV0dXJuIHRoaXMuYWRkX3Byb2ModHJ1ZSkucGlkO1xuICB9XG5cbiAgbGluayhwaWQpIHtcbiAgICB0aGlzLmxpbmtzLmdldCh0aGlzLnBpZCgpKS5hZGQocGlkKTtcbiAgICB0aGlzLmxpbmtzLmdldChwaWQpLmFkZCh0aGlzLnBpZCgpKTtcbiAgfVxuXG4gIHVubGluayhwaWQpIHtcbiAgICB0aGlzLmxpbmtzLmdldCh0aGlzLnBpZCgpKS5kZWxldGUocGlkKTtcbiAgICB0aGlzLmxpbmtzLmdldChwaWQpLmRlbGV0ZSh0aGlzLnBpZCgpKTtcbiAgfVxuXG4gIHNldF9jdXJyZW50KGlkKSB7XG4gICAgbGV0IHBpZCA9IHRoaXMucGlkb2YoaWQpO1xuICAgIGlmIChwaWQgIT09IG51bGwpIHtcbiAgICAgIHRoaXMuY3VycmVudF9wcm9jZXNzID0gdGhpcy5waWRzLmdldChwaWQpO1xuICAgICAgdGhpcy5jdXJyZW50X3Byb2Nlc3Muc3RhdHVzID0gU3RhdGVzLlJVTk5JTkc7XG4gICAgfVxuICB9XG5cbiAgYWRkX3Byb2MobGlua2VkKSB7XG4gICAgbGV0IG5ld3BpZCA9IG5ldyBQcmltaXRpdmVzLlBJRCgpO1xuICAgIGxldCBtYWlsYm94ID0gbmV3IE1haWxib3goKTtcbiAgICBsZXQgbmV3cHJvYyA9IG5ldyBQcm9jZXNzKG5ld3BpZCwgbWFpbGJveCk7XG5cbiAgICB0aGlzLnBpZHMuc2V0KG5ld3BpZCwgbmV3cHJvYyk7XG4gICAgdGhpcy5tYWlsYm94ZXMuc2V0KG5ld3BpZCwgbWFpbGJveCk7XG4gICAgdGhpcy5saW5rcy5zZXQobmV3cGlkLCBuZXcgU2V0KCkpO1xuXG4gICAgaWYgKGxpbmtlZCkge1xuICAgICAgdGhpcy5saW5rKG5ld3BpZCk7XG4gICAgfVxuXG4gICAgcmV0dXJuIG5ld3Byb2M7XG4gIH1cblxuICByZW1vdmVfcHJvYyhwaWQpIHtcbiAgICB0aGlzLnBpZHMuZGVsZXRlKHBpZCk7XG4gICAgdGhpcy51bnJlZ2lzdGVyKHBpZCk7XG5cbiAgICBpZiAodGhpcy5saW5rcy5oYXMocGlkKSkge1xuICAgICAgZm9yIChsZXQgbGlua3BpZCBvZiB0aGlzLmxpbmtzLmdldChwaWQpKSB7XG4gICAgICAgIHRoaXMubGlua3MuZ2V0KGxpbmtwaWQpLmRlbGV0ZShwaWQpO1xuICAgICAgfVxuXG4gICAgICB0aGlzLmxpbmtzLmRlbGV0ZShwaWQpO1xuICAgIH1cbiAgfVxuXG4gIGV4aXQoaWQpIHtcbiAgICBsZXQgcGlkID0gdGhpcy5waWRvZihpZCk7XG4gICAgdGhpcy5yZW1vdmVfcHJvYyhpZCk7XG4gIH1cblxuICByZWdpc3RlcihuYW1lLCBwaWQpIHtcbiAgICBpZiAoIXRoaXMubmFtZXMuaGFzKG5hbWUpKSB7XG4gICAgICB0aGlzLm5hbWVzLnNldChuYW1lLCBwaWQpO1xuICAgICAgcmV0dXJuIG5hbWU7XG4gICAgfSBlbHNlIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcihcIk5hbWUgaXMgYWxyZWFkeSByZWdpc3RlcmVkIHRvIGFub3RoZXIgcHJvY2Vzc1wiKTtcbiAgICB9XG4gIH1cblxuICByZWdpc3RlcmVkKG5hbWUpIHtcbiAgICByZXR1cm4gdGhpcy5uYW1lcy5oYXMobmFtZSkgPyB0aGlzLm5hbWVzLmdldChuYW1lKSA6IG51bGw7XG4gIH1cblxuICB1bnJlZ2lzdGVyKHBpZCkge1xuICAgIGZvciAobGV0IG5hbWUgb2YgdGhpcy5uYW1lcy5rZXlzKCkpIHtcbiAgICAgIGlmICh0aGlzLm5hbWVzLmhhcyhuYW1lKSAmJiB0aGlzLm5hbWVzLmdldChuYW1lKSA9PT0gcGlkKSB7XG4gICAgICAgIHRoaXMubmFtZXMuZGVsZXRlKG5hbWUpO1xuICAgICAgfVxuICAgIH1cbiAgfVxuXG4gIHBpZCgpIHtcbiAgICByZXR1cm4gdGhpcy5jdXJyZW50X3Byb2Nlc3MucGlkO1xuICB9XG5cbiAgcGlkb2YoaWQpIHtcbiAgICBpZiAoaWQgaW5zdGFuY2VvZiBQcmltaXRpdmVzLlBJRCkge1xuICAgICAgcmV0dXJuIHRoaXMucGlkcy5oYXMoaWQpID8gaWQgOiBudWxsO1xuICAgIH0gZWxzZSBpZiAoaWQgaW5zdGFuY2VvZiBQcm9jZXNzKSB7XG4gICAgICByZXR1cm4gaWQucGlkO1xuICAgIH0gZWxzZSB7XG4gICAgICBsZXQgcGlkID0gdGhpcy5yZWdpc3RlcmVkKGlkKTtcbiAgICAgIGlmIChwaWQgPT09IG51bGwpIHRocm93IFwiUHJvY2VzcyBuYW1lIG5vdCByZWdpc3RlcmVkOiBcIiArIGlkICsgXCIgKFwiICsgdHlwZW9mIGlkICsgXCIpXCI7XG4gICAgICByZXR1cm4gcGlkO1xuICAgIH1cbiAgfVxuXG4gIHB1dChpZCwga2V5LCB2YWx1ZSkge1xuICAgIGxldCBwaWQgPSB0aGlzLnBpZG9mKGlkKTtcbiAgICBsZXQgcHJvY2VzcyA9IHRoaXMucGlkcy5nZXQocGlkKTtcbiAgICBwcm9jZXNzLmRpY3Rba2V5XSA9IHZhbHVlO1xuICB9XG5cbiAgZ2V0KGlkLCBrZXkpIHtcbiAgICBsZXQgcGlkID0gdGhpcy5waWRvZihpZCk7XG4gICAgbGV0IHByb2Nlc3MgPSB0aGlzLnBpZHMuZ2V0KHBpZCk7XG5cbiAgICBpZiAoa2V5ICE9IG51bGwpIHtcbiAgICAgIHJldHVybiBwcm9jZXNzLmRpY3Rba2V5XTtcbiAgICB9IGVsc2Uge1xuICAgICAgcmV0dXJuIHByb2Nlc3MuZGljdDtcbiAgICB9XG4gIH1cblxuICBnZXRfa2V5cyhpZCkge1xuICAgIGxldCBwaWQgPSB0aGlzLnBpZG9mKGlkKTtcbiAgICBsZXQgcHJvY2VzcyA9IHRoaXMucGlkcy5nZXQocGlkKTtcblxuICAgIHJldHVybiBPYmplY3Qua2V5cyhwcm9jZXNzLmRpY3QpO1xuICB9XG5cbiAgZXJhc2UoaWQsIGtleSkge1xuICAgIGxldCBwaWQgPSB0aGlzLnBpZG9mKGlkKTtcbiAgICBsZXQgcHJvY2VzcyA9IHRoaXMucGlkcy5nZXQocGlkKTtcblxuICAgIGlmIChrZXkgIT0gbnVsbCkge1xuICAgICAgZGVsZXRlIHByb2Nlc3MuZGljdFtrZXldO1xuICAgIH0gZWxzZSB7XG4gICAgICBwcm9jZXNzLmRpY3QgPSB7fTtcbiAgICB9XG4gIH1cbn1cblxuZXhwb3J0IGRlZmF1bHQgUHJvY2Vzc1N5c3RlbTtcbi8vIyBzb3VyY2VNYXBwaW5nVVJMPWRhdGE6YXBwbGljYXRpb24vanNvbjtiYXNlNjQsZXlKMlpYSnphVzl1SWpvekxDSnpiM1Z5WTJWeklqcGJJbXhwWWk5amIzSmxMM0J5YjJObGMzTmxjeTl3Y205alpYTnpYM041YzNSbGJTNXFjeUpkTENKdVlXMWxjeUk2VzEwc0ltMWhjSEJwYm1keklqb2lPMEZCUTBFN08wRkJSVUVzVDBGQlR5eFBRVUZRTEUxQlFXOUNMRmRCUVhCQ08wRkJRMEVzVDBGQlR5eFBRVUZRTEUxQlFXOUNMRmRCUVhCQ08wRkJRMEVzVDBGQlR5eE5RVUZRTEUxQlFXMUNMRlZCUVc1Q08wRkJRMEVzVDBGQlR5eExRVUZMTEZWQlFVd3NUVUZCY1VJc1pVRkJOVUk3TzBGQlJVRXNUVUZCVFN4aFFVRk9MRU5CUVc5Q096dEJRVVZzUWl4blFrRkJZVHRCUVVOWUxGTkJRVXNzU1VGQlRDeEhRVUZaTEVsQlFVa3NSMEZCU2l4RlFVRmFMRU5CUkZjN1FVRkZXQ3hUUVVGTExGTkJRVXdzUjBGQmFVSXNTVUZCU1N4SFFVRktMRVZCUVdwQ0xFTkJSbGM3UVVGSFdDeFRRVUZMTEV0QlFVd3NSMEZCWVN4SlFVRkpMRWRCUVVvc1JVRkJZaXhEUVVoWE8wRkJTVmdzVTBGQlN5eExRVUZNTEVkQlFXRXNTVUZCU1N4SFFVRktMRVZCUVdJc1EwRktWenM3UVVGTldDeFRRVUZMTEdWQlFVd3NSMEZCZFVJc1NVRkJka0lzUTBGT1Z6dEJRVTlZTEZOQlFVc3NVMEZCVEN4SFFVRnBRaXhKUVVGSkxFZEJRVW9zUlVGQmFrSXNRMEZRVnpzN1FVRlRXQ3hUUVVGTExHZENRVUZNTEVkQlFYZENMRXRCUVVzc1MwRkJUQ3hGUVVGNFFpeERRVlJYTzBGQlZWZ3NVMEZCU3l4WFFVRk1MRU5CUVdsQ0xFdEJRVXNzWjBKQlFVd3NRMEZCYWtJc1EwRldWenRIUVVGaU96dEJRV0ZCTEZWQlFVODdRVUZEVEN4WFFVRlBMRXRCUVVzc1VVRkJUQ3hEUVVGakxFdEJRV1FzUlVGQmNVSXNSMEZCY2tJc1EwRkVSanRIUVVGUU96dEJRVWxCTEdWQlFWazdRVUZEVml4WFFVRlBMRXRCUVVzc1VVRkJUQ3hEUVVGakxFbEJRV1FzUlVGQmIwSXNSMEZCY0VJc1EwRkVSenRIUVVGYU96dEJRVWxCTEU5QlFVc3NSMEZCVEN4RlFVRlRPMEZCUTFBc1UwRkJTeXhMUVVGTUxFTkJRVmNzUjBGQldDeERRVUZsTEV0QlFVc3NSMEZCVEN4RlFVRm1MRVZCUVRKQ0xFZEJRVE5DTEVOQlFTdENMRWRCUVM5Q0xFVkJSRTg3UVVGRlVDeFRRVUZMTEV0QlFVd3NRMEZCVnl4SFFVRllMRU5CUVdVc1IwRkJaaXhGUVVGdlFpeEhRVUZ3UWl4RFFVRjNRaXhMUVVGTExFZEJRVXdzUlVGQmVFSXNSVUZHVHp0SFFVRlVPenRCUVV0QkxGTkJRVThzUjBGQlVDeEZRVUZYTzBGQlExUXNVMEZCU3l4TFFVRk1MRU5CUVZjc1IwRkJXQ3hEUVVGbExFdEJRVXNzUjBGQlRDeEZRVUZtTEVWQlFUSkNMRTFCUVROQ0xFTkJRV3RETEVkQlFXeERMRVZCUkZNN1FVRkZWQ3hUUVVGTExFdEJRVXdzUTBGQlZ5eEhRVUZZTEVOQlFXVXNSMEZCWml4RlFVRnZRaXhOUVVGd1FpeERRVUV5UWl4TFFVRkxMRWRCUVV3c1JVRkJNMElzUlVGR1V6dEhRVUZZT3p0QlFVdEJMR05CUVZrc1JVRkJXaXhGUVVGbE8wRkJRMklzVVVGQlNTeE5RVUZOTEV0QlFVc3NTMEZCVEN4RFFVRlhMRVZCUVZnc1EwRkJUaXhEUVVSVE8wRkJSV0lzVVVGQlJ5eFJRVUZSTEVsQlFWSXNSVUZCWVR0QlFVTmtMRmRCUVVzc1pVRkJUQ3hIUVVGMVFpeExRVUZMTEVsQlFVd3NRMEZCVlN4SFFVRldMRU5CUVdNc1IwRkJaQ3hEUVVGMlFpeERRVVJqTzBGQlJXUXNWMEZCU3l4bFFVRk1MRU5CUVhGQ0xFMUJRWEpDTEVkQlFUaENMRTlCUVU4c1QwRkJVQ3hEUVVab1FqdExRVUZvUWp0SFFVWkdPenRCUVZGQkxGZEJRVk1zVFVGQlZDeEZRVUZuUWp0QlFVTmtMRkZCUVVrc1UwRkJVeXhKUVVGSkxGZEJRVmNzUjBGQldDeEZRVUZpTEVOQlJGVTdRVUZGWkN4UlFVRkpMRlZCUVZVc1NVRkJTU3hQUVVGS0xFVkJRVllzUTBGR1ZUdEJRVWRrTEZGQlFVa3NWVUZCVlN4SlFVRkpMRTlCUVVvc1EwRkJXU3hOUVVGYUxFVkJRVzlDTEU5QlFYQkNMRU5CUVZZc1EwRklWVHM3UVVGTFpDeFRRVUZMTEVsQlFVd3NRMEZCVlN4SFFVRldMRU5CUVdNc1RVRkJaQ3hGUVVGelFpeFBRVUYwUWl4RlFVeGpPMEZCVFdRc1UwRkJTeXhUUVVGTUxFTkJRV1VzUjBGQlppeERRVUZ0UWl4TlFVRnVRaXhGUVVFeVFpeFBRVUV6UWl4RlFVNWpPMEZCVDJRc1UwRkJTeXhMUVVGTUxFTkJRVmNzUjBGQldDeERRVUZsTEUxQlFXWXNSVUZCZFVJc1NVRkJTU3hIUVVGS0xFVkJRWFpDTEVWQlVHTTdPMEZCVTJRc1VVRkJSeXhOUVVGSUxFVkJRVlU3UVVGRFVpeFhRVUZMTEVsQlFVd3NRMEZCVlN4TlFVRldMRVZCUkZFN1MwRkJWanM3UVVGSlFTeFhRVUZQTEU5QlFWQXNRMEZpWXp0SFFVRm9RanM3UVVGblFrRXNZMEZCV1N4SFFVRmFMRVZCUVdkQ08wRkJRMlFzVTBGQlN5eEpRVUZNTEVOQlFWVXNUVUZCVml4RFFVRnBRaXhIUVVGcVFpeEZRVVJqTzBGQlJXUXNVMEZCU3l4VlFVRk1MRU5CUVdkQ0xFZEJRV2hDTEVWQlJtTTdPMEZCU1dRc1VVRkJSeXhMUVVGTExFdEJRVXdzUTBGQlZ5eEhRVUZZTEVOQlFXVXNSMEZCWml4RFFVRklMRVZCUVhWQ08wRkJRM0pDTEZkQlFVc3NTVUZCU1N4UFFVRktMRWxCUVdVc1MwRkJTeXhMUVVGTUxFTkJRVmNzUjBGQldDeERRVUZsTEVkQlFXWXNRMEZCY0VJc1JVRkJlVU03UVVGRGRrTXNZVUZCU3l4TFFVRk1MRU5CUVZjc1IwRkJXQ3hEUVVGbExFOUJRV1lzUlVGQmQwSXNUVUZCZUVJc1EwRkJLMElzUjBGQkwwSXNSVUZFZFVNN1QwRkJla003TzBGQlNVRXNWMEZCU3l4TFFVRk1MRU5CUVZjc1RVRkJXQ3hEUVVGclFpeEhRVUZzUWl4RlFVeHhRanRMUVVGMlFqdEhRVXBHT3p0QlFXRkJMRTlCUVVzc1JVRkJUQ3hGUVVGUk8wRkJRMDRzVVVGQlNTeE5RVUZOTEV0QlFVc3NTMEZCVEN4RFFVRlhMRVZCUVZnc1EwRkJUaXhEUVVSRk8wRkJSVTRzVTBGQlN5eFhRVUZNTEVOQlFXbENMRVZCUVdwQ0xFVkJSazA3UjBGQlVqczdRVUZMUVN4WFFVRlRMRWxCUVZRc1JVRkJaU3hIUVVGbUxFVkJRVzFDTzBGQlEycENMRkZCUVVjc1EwRkJReXhMUVVGTExFdEJRVXdzUTBGQlZ5eEhRVUZZTEVOQlFXVXNTVUZCWml4RFFVRkVMRVZCUVhOQ08wRkJRM1pDTEZkQlFVc3NTMEZCVEN4RFFVRlhMRWRCUVZnc1EwRkJaU3hKUVVGbUxFVkJRWEZDTEVkQlFYSkNMRVZCUkhWQ08wRkJSWFpDTEdGQlFVOHNTVUZCVUN4RFFVWjFRanRMUVVGNlFpeE5RVWRMTzBGQlEwZ3NXVUZCVFN4SlFVRkpMRXRCUVVvc1EwRkJWU3dyUTBGQlZpeERRVUZPTEVOQlJFYzdTMEZJVER0SFFVUkdPenRCUVZOQkxHRkJRVmNzU1VGQldDeEZRVUZuUWp0QlFVTmtMRmRCUVU4c1MwRkJTeXhMUVVGTUxFTkJRVmNzUjBGQldDeERRVUZsTEVsQlFXWXNTVUZCZFVJc1MwRkJTeXhMUVVGTUxFTkJRVmNzUjBGQldDeERRVUZsTEVsQlFXWXNRMEZCZGtJc1IwRkJPRU1zU1VGQk9VTXNRMEZFVHp0SFFVRm9RanM3UVVGSlFTeGhRVUZYTEVkQlFWZ3NSVUZCWlR0QlFVTmlMRk5CUVVrc1NVRkJTU3hKUVVGS0xFbEJRVmtzUzBGQlN5eExRVUZNTEVOQlFWY3NTVUZCV0N4RlFVRm9RaXhGUVVGclF6dEJRVU5vUXl4VlFVRkhMRXRCUVVzc1MwRkJUQ3hEUVVGWExFZEJRVmdzUTBGQlpTeEpRVUZtTEV0QlFYZENMRXRCUVVzc1MwRkJUQ3hEUVVGWExFZEJRVmdzUTBGQlpTeEpRVUZtTEUxQlFYbENMRWRCUVhwQ0xFVkJRVFpDTzBGQlEzUkVMR0ZCUVVzc1MwRkJUQ3hEUVVGWExFMUJRVmdzUTBGQmEwSXNTVUZCYkVJc1JVRkVjMFE3VDBGQmVFUTdTMEZFUmp0SFFVUkdPenRCUVZGQkxGRkJRVXM3UVVGRFNDeFhRVUZQTEV0QlFVc3NaVUZCVEN4RFFVRnhRaXhIUVVGeVFpeERRVVJLTzBkQlFVdzdPMEZCU1VFc1VVRkJUU3hGUVVGT0xFVkJRVk03UVVGRFVDeFJRVUZKTEdOQlFXTXNWMEZCVnl4SFFVRllMRVZCUVdkQ08wRkJReTlDTEdGQlFVOHNTMEZCU3l4SlFVRk1MRU5CUVZVc1IwRkJWaXhEUVVGakxFVkJRV1FzU1VGQmIwSXNSVUZCY0VJc1IwRkJlVUlzU1VGQmVrSXNRMEZFZDBJN1MwRkJiRU1zVFVGRlR5eEpRVUZKTEdOQlFXTXNUMEZCWkN4RlFVRjFRanRCUVVNdlFpeGhRVUZQTEVkQlFVY3NSMEZCU0N4RFFVUjNRanRMUVVFelFpeE5RVVZCTzBGQlEwb3NWVUZCU1N4TlFVRk5MRXRCUVVzc1ZVRkJUQ3hEUVVGblFpeEZRVUZvUWl4RFFVRk9MRU5CUkVFN1FVRkZTaXhWUVVGSkxGRkJRVkVzU1VGQlVpeEZRVU5FTEUxQlFVMHNhME5CUVd0RExFVkJRV3hETEVkQlFYVkRMRWxCUVhaRExFZEJRVGhETEU5QlFVOHNSVUZCVUN4SFFVRmhMRWRCUVRORUxFTkJSRlE3UVVGRlFTeGhRVUZQTEVkQlFWQXNRMEZLU1R0TFFVWkJPMGRCU0ZRN08wRkJZVUVzVFVGQlNTeEZRVUZLTEVWQlFWRXNSMEZCVWl4RlFVRmhMRXRCUVdJc1JVRkJiVUk3UVVGRGFrSXNVVUZCU1N4TlFVRk5MRXRCUVVzc1MwRkJUQ3hEUVVGWExFVkJRVmdzUTBGQlRpeERRVVJoTzBGQlJXcENMRkZCUVVrc1ZVRkJWU3hMUVVGTExFbEJRVXdzUTBGQlZTeEhRVUZXTEVOQlFXTXNSMEZCWkN4RFFVRldMRU5CUm1FN1FVRkhha0lzV1VGQlVTeEpRVUZTTEVOQlFXRXNSMEZCWWl4SlFVRnZRaXhMUVVGd1FpeERRVWhwUWp0SFFVRnVRanM3UVVGTlFTeE5RVUZKTEVWQlFVb3NSVUZCVVN4SFFVRlNMRVZCUVZrN1FVRkRWaXhSUVVGSkxFMUJRVTBzUzBGQlN5eExRVUZNTEVOQlFWY3NSVUZCV0N4RFFVRk9MRU5CUkUwN1FVRkZWaXhSUVVGSkxGVkJRVlVzUzBGQlN5eEpRVUZNTEVOQlFWVXNSMEZCVml4RFFVRmpMRWRCUVdRc1EwRkJWaXhEUVVaTk96dEJRVWxXTEZGQlFVY3NUMEZCVHl4SlFVRlFMRVZCUVZrN1FVRkRZaXhoUVVGUExGRkJRVkVzU1VGQlVpeERRVUZoTEVkQlFXSXNRMEZCVUN4RFFVUmhPMHRCUVdZc1RVRkZTenRCUVVOSUxHRkJRVThzVVVGQlVTeEpRVUZTTEVOQlJFbzdTMEZHVER0SFFVcEdPenRCUVZkQkxGZEJRVk1zUlVGQlZDeEZRVUZaTzBGQlExWXNVVUZCU1N4TlFVRk5MRXRCUVVzc1MwRkJUQ3hEUVVGWExFVkJRVmdzUTBGQlRpeERRVVJOTzBGQlJWWXNVVUZCU1N4VlFVRlZMRXRCUVVzc1NVRkJUQ3hEUVVGVkxFZEJRVllzUTBGQll5eEhRVUZrTEVOQlFWWXNRMEZHVFRzN1FVRkpWaXhYUVVGUExFOUJRVThzU1VGQlVDeERRVUZaTEZGQlFWRXNTVUZCVWl4RFFVRnVRaXhEUVVwVk8wZEJRVm83TzBGQlQwRXNVVUZCVFN4RlFVRk9MRVZCUVZVc1IwRkJWaXhGUVVGak8wRkJRMW9zVVVGQlNTeE5RVUZOTEV0QlFVc3NTMEZCVEN4RFFVRlhMRVZCUVZnc1EwRkJUaXhEUVVSUk8wRkJSVm9zVVVGQlNTeFZRVUZWTEV0QlFVc3NTVUZCVEN4RFFVRlZMRWRCUVZZc1EwRkJZeXhIUVVGa0xFTkJRVllzUTBGR1VUczdRVUZKV2l4UlFVRkhMRTlCUVU4c1NVRkJVQ3hGUVVGWk8wRkJRMklzWVVGQlR5eFJRVUZSTEVsQlFWSXNRMEZCWVN4SFFVRmlMRU5CUVZBc1EwRkVZVHRMUVVGbUxFMUJSVXM3UVVGRFNDeGpRVUZSTEVsQlFWSXNSMEZCWlN4RlFVRm1MRU5CUkVjN1MwRkdURHRIUVVwR08wTkJla2xHT3p0QlFYRktRU3hsUVVGbExHRkJRV1lpTENKbWFXeGxJam9pYkdsaUwyTnZjbVV2Y0hKdlkyVnpjMlZ6TDNCeWIyTmxjM05mYzNsemRHVnRMbXB6SWl3aWMyOTFjbU5sYzBOdmJuUmxiblFpT2xzaUx5b2dRR1pzYjNjZ0tpOWNibHdpZFhObElITjBjbWxqZEZ3aU8xeHVYRzVwYlhCdmNuUWdUV0ZwYkdKdmVDQm1jbTl0SUZ3aUxpOXRZV2xzWW05NFhDSTdYRzVwYlhCdmNuUWdVSEp2WTJWemN5Qm1jbTl0SUZ3aUxpOXdjbTlqWlhOelhDSTdYRzVwYlhCdmNuUWdVM1JoZEdWeklHWnliMjBnWENJdUwzTjBZWFJsYzF3aU8xeHVhVzF3YjNKMElDb2dZWE1nVUhKcGJXbDBhWFpsY3lCbWNtOXRJRndpTGk0dmNISnBiV2wwYVhabGMxd2lPMXh1WEc1amJHRnpjeUJRY205alpYTnpVM2x6ZEdWdElIdGNibHh1SUNCamIyNXpkSEoxWTNSdmNpZ3BlMXh1SUNBZ0lIUm9hWE11Y0dsa2N5QTlJRzVsZHlCTllYQW9LVHRjYmlBZ0lDQjBhR2x6TG0xaGFXeGliM2hsY3lBOUlHNWxkeUJOWVhBb0tUdGNiaUFnSUNCMGFHbHpMbTVoYldWeklEMGdibVYzSUUxaGNDZ3BPMXh1SUNBZ0lIUm9hWE11YkdsdWEzTWdQU0J1WlhjZ1RXRndLQ2s3WEc1Y2JpQWdJQ0IwYUdsekxtTjFjbkpsYm5SZmNISnZZMlZ6Y3lBOUlHNTFiR3c3WEc0Z0lDQWdkR2hwY3k1emRYTndaVzVrWldRZ1BTQnVaWGNnVFdGd0tDazdYRzVjYmlBZ0lDQjBhR2x6TG0xaGFXNWZjSEp2WTJWemMxOXdhV1FnUFNCMGFHbHpMbk53WVhkdUtDazdYRzRnSUNBZ2RHaHBjeTV6WlhSZlkzVnljbVZ1ZENoMGFHbHpMbTFoYVc1ZmNISnZZMlZ6YzE5d2FXUXBPMXh1SUNCOVhHNWNiaUFnYzNCaGQyNG9LWHRjYmlBZ0lDQnlaWFIxY200Z2RHaHBjeTVoWkdSZmNISnZZeWhtWVd4elpTa3VjR2xrTzF4dUlDQjlYRzVjYmlBZ2MzQmhkMjVmYkdsdWF5Z3BlMXh1SUNBZ0lISmxkSFZ5YmlCMGFHbHpMbUZrWkY5d2NtOWpLSFJ5ZFdVcExuQnBaRHRjYmlBZ2ZWeHVYRzRnSUd4cGJtc29jR2xrS1h0Y2JpQWdJQ0IwYUdsekxteHBibXR6TG1kbGRDaDBhR2x6TG5CcFpDZ3BLUzVoWkdRb2NHbGtLVHRjYmlBZ0lDQjBhR2x6TG14cGJtdHpMbWRsZENod2FXUXBMbUZrWkNoMGFHbHpMbkJwWkNncEtUdGNiaUFnZlZ4dVhHNGdJSFZ1YkdsdWF5aHdhV1FwZTF4dUlDQWdJSFJvYVhNdWJHbHVhM011WjJWMEtIUm9hWE11Y0dsa0tDa3BMbVJsYkdWMFpTaHdhV1FwTzF4dUlDQWdJSFJvYVhNdWJHbHVhM011WjJWMEtIQnBaQ2t1WkdWc1pYUmxLSFJvYVhNdWNHbGtLQ2twTzF4dUlDQjlYRzVjYmlBZ2MyVjBYMk4xY25KbGJuUW9hV1FwZTF4dUlDQWdJR3hsZENCd2FXUWdQU0IwYUdsekxuQnBaRzltS0dsa0tUdGNiaUFnSUNCcFppaHdhV1FnSVQwOUlHNTFiR3dwZTF4dUlDQWdJQ0FnZEdocGN5NWpkWEp5Wlc1MFgzQnliMk5sYzNNZ1BTQjBhR2x6TG5CcFpITXVaMlYwS0hCcFpDazdYRzRnSUNBZ0lDQjBhR2x6TG1OMWNuSmxiblJmY0hKdlkyVnpjeTV6ZEdGMGRYTWdQU0JUZEdGMFpYTXVVbFZPVGtsT1J6dGNiaUFnSUNCOVhHNGdJSDFjYmx4dUlDQmhaR1JmY0hKdll5aHNhVzVyWldRcGUxeHVJQ0FnSUd4bGRDQnVaWGR3YVdRZ1BTQnVaWGNnVUhKcGJXbDBhWFpsY3k1UVNVUW9LVHRjYmlBZ0lDQnNaWFFnYldGcGJHSnZlQ0E5SUc1bGR5Qk5ZV2xzWW05NEtDazdYRzRnSUNBZ2JHVjBJRzVsZDNCeWIyTWdQU0J1WlhjZ1VISnZZMlZ6Y3lodVpYZHdhV1FzSUcxaGFXeGliM2dwTzF4dVhHNGdJQ0FnZEdocGN5NXdhV1J6TG5ObGRDaHVaWGR3YVdRc0lHNWxkM0J5YjJNcE8xeHVJQ0FnSUhSb2FYTXViV0ZwYkdKdmVHVnpMbk5sZENodVpYZHdhV1FzSUcxaGFXeGliM2dwTzF4dUlDQWdJSFJvYVhNdWJHbHVhM011YzJWMEtHNWxkM0JwWkN3Z2JtVjNJRk5sZENncEtUdGNibHh1SUNBZ0lHbG1LR3hwYm10bFpDbDdYRzRnSUNBZ0lDQjBhR2x6TG14cGJtc29ibVYzY0dsa0tUdGNiaUFnSUNCOVhHNWNiaUFnSUNCeVpYUjFjbTRnYm1WM2NISnZZenRjYmlBZ2ZWeHVYRzRnSUhKbGJXOTJaVjl3Y205aktIQnBaQ2w3WEc0Z0lDQWdkR2hwY3k1d2FXUnpMbVJsYkdWMFpTaHdhV1FwTzF4dUlDQWdJSFJvYVhNdWRXNXlaV2RwYzNSbGNpaHdhV1FwTzF4dVhHNGdJQ0FnYVdZb2RHaHBjeTVzYVc1cmN5NW9ZWE1vY0dsa0tTbDdYRzRnSUNBZ0lDQm1iM0lnS0d4bGRDQnNhVzVyY0dsa0lHOW1JSFJvYVhNdWJHbHVhM011WjJWMEtIQnBaQ2twSUh0Y2JpQWdJQ0FnSUNBZ2RHaHBjeTVzYVc1cmN5NW5aWFFvYkdsdWEzQnBaQ2t1WkdWc1pYUmxLSEJwWkNrN1hHNGdJQ0FnSUNCOVhHNWNiaUFnSUNBZ0lIUm9hWE11YkdsdWEzTXVaR1ZzWlhSbEtIQnBaQ2s3WEc0Z0lDQWdmVnh1SUNCOVhHNWNiaUFnWlhocGRDaHBaQ2w3WEc0Z0lDQWdiR1YwSUhCcFpDQTlJSFJvYVhNdWNHbGtiMllvYVdRcE8xeHVJQ0FnSUhSb2FYTXVjbVZ0YjNabFgzQnliMk1vYVdRcE8xeHVJQ0I5WEc1Y2JpQWdjbVZuYVhOMFpYSW9ibUZ0WlN3Z2NHbGtLWHRjYmlBZ0lDQnBaaWdoZEdocGN5NXVZVzFsY3k1b1lYTW9ibUZ0WlNrcGUxeHVJQ0FnSUNBZ2RHaHBjeTV1WVcxbGN5NXpaWFFvYm1GdFpTd2djR2xrS1Z4dUlDQWdJQ0FnY21WMGRYSnVJRzVoYldVN1hHNGdJQ0FnZldWc2MyVjdYRzRnSUNBZ0lDQjBhSEp2ZHlCdVpYY2dSWEp5YjNJb1hDSk9ZVzFsSUdseklHRnNjbVZoWkhrZ2NtVm5hWE4wWlhKbFpDQjBieUJoYm05MGFHVnlJSEJ5YjJObGMzTmNJaWs3WEc0Z0lDQWdmVnh1SUNCOVhHNWNiaUFnY21WbmFYTjBaWEpsWkNodVlXMWxLWHRjYmlBZ0lDQnlaWFIxY200Z2RHaHBjeTV1WVcxbGN5NW9ZWE1vYm1GdFpTa2dQeUIwYUdsekxtNWhiV1Z6TG1kbGRDaHVZVzFsS1NBNklHNTFiR3c3WEc0Z0lIMWNibHh1SUNCMWJuSmxaMmx6ZEdWeUtIQnBaQ2w3WEc0Z0lDQWdabTl5S0d4bGRDQnVZVzFsSUc5bUlIUm9hWE11Ym1GdFpYTXVhMlY1Y3lncEtYdGNiaUFnSUNBZ0lHbG1LSFJvYVhNdWJtRnRaWE11YUdGektHNWhiV1VwSUNZbUlIUm9hWE11Ym1GdFpYTXVaMlYwS0c1aGJXVXBJRDA5UFNCd2FXUXBlMXh1SUNBZ0lDQWdJQ0IwYUdsekxtNWhiV1Z6TG1SbGJHVjBaU2h1WVcxbEtUdGNiaUFnSUNBZ0lIMWNiaUFnSUNCOVhHNGdJSDFjYmx4dUlDQndhV1FvS1h0Y2JpQWdJQ0J5WlhSMWNtNGdkR2hwY3k1amRYSnlaVzUwWDNCeWIyTmxjM011Y0dsa08xeHVJQ0I5WEc1Y2JpQWdjR2xrYjJZb2FXUXBlMXh1SUNBZ0lHbG1JQ2hwWkNCcGJuTjBZVzVqWlc5bUlGQnlhVzFwZEdsMlpYTXVVRWxFS1NCN1hHNGdJQ0FnSUNBZ2NtVjBkWEp1SUhSb2FYTXVjR2xrY3k1b1lYTW9hV1FwSUQ4Z2FXUWdPaUJ1ZFd4c08xeHVJQ0FnSUgwZ1pXeHpaU0JwWmlBb2FXUWdhVzV6ZEdGdVkyVnZaaUJRY205alpYTnpLU0I3WEc0Z0lDQWdJQ0FnY21WMGRYSnVJR2xrTG5CcFpEdGNiaUFnSUNCOUlHVnNjMlVnZTF4dUlDQWdJQ0FnSUd4bGRDQndhV1FnUFNCMGFHbHpMbkpsWjJsemRHVnlaV1FvYVdRcE8xeHVJQ0FnSUNBZ0lHbG1JQ2h3YVdRZ1BUMDlJRzUxYkd3cFhHNGdJQ0FnSUNBZ0lDQWdkR2h5YjNjb1hDSlFjbTlqWlhOeklHNWhiV1VnYm05MElISmxaMmx6ZEdWeVpXUTZJRndpSUNzZ2FXUWdLeUJjSWlBb1hDSWdLeUIwZVhCbGIyWW9hV1FwSUNzZ1hDSXBYQ0lwTzF4dUlDQWdJQ0FnSUhKbGRIVnliaUJ3YVdRN1hHNGdJQ0FnZlZ4dUlDQjlYRzVjYmlBZ2NIVjBLR2xrTENCclpYa3NJSFpoYkhWbEtYdGNiaUFnSUNCc1pYUWdjR2xrSUQwZ2RHaHBjeTV3YVdSdlppaHBaQ2s3WEc0Z0lDQWdiR1YwSUhCeWIyTmxjM01nUFNCMGFHbHpMbkJwWkhNdVoyVjBLSEJwWkNrN1hHNGdJQ0FnY0hKdlkyVnpjeTVrYVdOMFcydGxlVjBnUFNCMllXeDFaVHRjYmlBZ2ZWeHVYRzRnSUdkbGRDaHBaQ3dnYTJWNUtYdGNiaUFnSUNCc1pYUWdjR2xrSUQwZ2RHaHBjeTV3YVdSdlppaHBaQ2s3WEc0Z0lDQWdiR1YwSUhCeWIyTmxjM01nUFNCMGFHbHpMbkJwWkhNdVoyVjBLSEJwWkNrN1hHNWNiaUFnSUNCcFppaHJaWGtnSVQwZ2JuVnNiQ2w3WEc0Z0lDQWdJQ0J5WlhSMWNtNGdjSEp2WTJWemN5NWthV04wVzJ0bGVWMDdYRzRnSUNBZ2ZXVnNjMlY3WEc0Z0lDQWdJQ0J5WlhSMWNtNGdjSEp2WTJWemN5NWthV04wTzF4dUlDQWdJSDFjYmlBZ2ZWeHVYRzRnSUdkbGRGOXJaWGx6S0dsa0tYdGNiaUFnSUNCc1pYUWdjR2xrSUQwZ2RHaHBjeTV3YVdSdlppaHBaQ2s3WEc0Z0lDQWdiR1YwSUhCeWIyTmxjM01nUFNCMGFHbHpMbkJwWkhNdVoyVjBLSEJwWkNrN1hHNWNiaUFnSUNCeVpYUjFjbTRnVDJKcVpXTjBMbXRsZVhNb2NISnZZMlZ6Y3k1a2FXTjBLVHRjYmlBZ2ZWeHVYRzRnSUdWeVlYTmxLR2xrTENCclpYa3BlMXh1SUNBZ0lHeGxkQ0J3YVdRZ1BTQjBhR2x6TG5CcFpHOW1LR2xrS1R0Y2JpQWdJQ0JzWlhRZ2NISnZZMlZ6Y3lBOUlIUm9hWE11Y0dsa2N5NW5aWFFvY0dsa0tUdGNibHh1SUNBZ0lHbG1LR3RsZVNBaFBTQnVkV3hzS1h0Y2JpQWdJQ0FnSUdSbGJHVjBaU0J3Y205alpYTnpMbVJwWTNSYmEyVjVYVHRjYmlBZ0lDQjlaV3h6Wlh0Y2JpQWdJQ0FnSUhCeWIyTmxjM011WkdsamRDQTlJSHQ5TzF4dUlDQWdJSDFjYmlBZ2ZWeHVmVnh1WEc1bGVIQnZjblFnWkdWbVlYVnNkQ0JRY205alpYTnpVM2x6ZEdWdE8xeHVJbDBzSW5OdmRYSmpaVkp2YjNRaU9pSXZjMjkxY21ObEx5SjlcbiIsImNsYXNzIEJpdFN0cmluZyB7XG4gIGNvbnN0cnVjdG9yKC4uLmFyZ3MpIHtcbiAgICB0aGlzLnZhbHVlID0gT2JqZWN0LmZyZWV6ZSh0aGlzLnByb2Nlc3MoYXJncykpO1xuICAgIHRoaXMubGVuZ3RoID0gdGhpcy52YWx1ZS5sZW5ndGg7XG4gICAgdGhpcy5iaXRfc2l6ZSA9IHRoaXMubGVuZ3RoICogODtcbiAgICB0aGlzLmJ5dGVfc2l6ZSA9IHRoaXMubGVuZ3RoO1xuICB9XG5cbiAgZ2V0KGluZGV4KSB7XG4gICAgcmV0dXJuIHRoaXMudmFsdWVbaW5kZXhdO1xuICB9XG5cbiAgY291bnQoKSB7XG4gICAgcmV0dXJuIHRoaXMudmFsdWUubGVuZ3RoO1xuICB9XG5cbiAgc2xpY2Uoc3RhcnQsIGVuZCA9IG51bGwpIHtcbiAgICBsZXQgcyA9IHRoaXMudmFsdWUuc2xpY2Uoc3RhcnQsIGVuZCk7XG4gICAgbGV0IG1zID0gcy5tYXAoZWxlbSA9PiBCaXRTdHJpbmcuaW50ZWdlcihlbGVtKSk7XG4gICAgcmV0dXJuIG5ldyBCaXRTdHJpbmcoLi4ubXMpO1xuICB9XG5cbiAgW1N5bWJvbC5pdGVyYXRvcl0oKSB7XG4gICAgcmV0dXJuIHRoaXMudmFsdWVbU3ltYm9sLml0ZXJhdG9yXSgpO1xuICB9XG5cbiAgdG9TdHJpbmcoKSB7XG4gICAgdmFyIGksXG4gICAgICAgIHMgPSBcIlwiO1xuICAgIGZvciAoaSA9IDA7IGkgPCB0aGlzLmNvdW50KCk7IGkrKykge1xuICAgICAgaWYgKHMgIT09IFwiXCIpIHtcbiAgICAgICAgcyArPSBcIiwgXCI7XG4gICAgICB9XG4gICAgICBzICs9IHRoaXMuZ2V0KGkpLnRvU3RyaW5nKCk7XG4gICAgfVxuXG4gICAgcmV0dXJuIFwiPDxcIiArIHMgKyBcIj4+XCI7XG4gIH1cblxuICBwcm9jZXNzKGJpdFN0cmluZ1BhcnRzKSB7XG4gICAgbGV0IHByb2Nlc3NlZF92YWx1ZXMgPSBbXTtcblxuICAgIHZhciBpO1xuICAgIGZvciAoaSA9IDA7IGkgPCBiaXRTdHJpbmdQYXJ0cy5sZW5ndGg7IGkrKykge1xuICAgICAgbGV0IHByb2Nlc3NlZF92YWx1ZSA9IHRoaXNbJ3Byb2Nlc3NfJyArIGJpdFN0cmluZ1BhcnRzW2ldLnR5cGVdKGJpdFN0cmluZ1BhcnRzW2ldKTtcblxuICAgICAgZm9yIChsZXQgYXR0ciBvZiBiaXRTdHJpbmdQYXJ0c1tpXS5hdHRyaWJ1dGVzKSB7XG4gICAgICAgIHByb2Nlc3NlZF92YWx1ZSA9IHRoaXNbJ3Byb2Nlc3NfJyArIGF0dHJdKHByb2Nlc3NlZF92YWx1ZSk7XG4gICAgICB9XG5cbiAgICAgIHByb2Nlc3NlZF92YWx1ZXMgPSBwcm9jZXNzZWRfdmFsdWVzLmNvbmNhdChwcm9jZXNzZWRfdmFsdWUpO1xuICAgIH1cblxuICAgIHJldHVybiBwcm9jZXNzZWRfdmFsdWVzO1xuICB9XG5cbiAgcHJvY2Vzc19pbnRlZ2VyKHZhbHVlKSB7XG4gICAgcmV0dXJuIHZhbHVlLnZhbHVlO1xuICB9XG5cbiAgcHJvY2Vzc19mbG9hdCh2YWx1ZSkge1xuICAgIGlmICh2YWx1ZS5zaXplID09PSA2NCkge1xuICAgICAgcmV0dXJuIEJpdFN0cmluZy5mbG9hdDY0VG9CeXRlcyh2YWx1ZS52YWx1ZSk7XG4gICAgfSBlbHNlIGlmICh2YWx1ZS5zaXplID09PSAzMikge1xuICAgICAgcmV0dXJuIEJpdFN0cmluZy5mbG9hdDMyVG9CeXRlcyh2YWx1ZS52YWx1ZSk7XG4gICAgfVxuXG4gICAgdGhyb3cgbmV3IEVycm9yKCdJbnZhbGlkIHNpemUgZm9yIGZsb2F0Jyk7XG4gIH1cblxuICBwcm9jZXNzX2JpdHN0cmluZyh2YWx1ZSkge1xuICAgIHJldHVybiB2YWx1ZS52YWx1ZS52YWx1ZTtcbiAgfVxuXG4gIHByb2Nlc3NfYmluYXJ5KHZhbHVlKSB7XG4gICAgcmV0dXJuIEJpdFN0cmluZy50b1VURjhBcnJheSh2YWx1ZS52YWx1ZSk7XG4gIH1cblxuICBwcm9jZXNzX3V0ZjgodmFsdWUpIHtcbiAgICByZXR1cm4gQml0U3RyaW5nLnRvVVRGOEFycmF5KHZhbHVlLnZhbHVlKTtcbiAgfVxuXG4gIHByb2Nlc3NfdXRmMTYodmFsdWUpIHtcbiAgICByZXR1cm4gQml0U3RyaW5nLnRvVVRGMTZBcnJheSh2YWx1ZS52YWx1ZSk7XG4gIH1cblxuICBwcm9jZXNzX3V0ZjMyKHZhbHVlKSB7XG4gICAgcmV0dXJuIEJpdFN0cmluZy50b1VURjMyQXJyYXkodmFsdWUudmFsdWUpO1xuICB9XG5cbiAgcHJvY2Vzc19zaWduZWQodmFsdWUpIHtcbiAgICByZXR1cm4gbmV3IFVpbnQ4QXJyYXkoW3ZhbHVlXSlbMF07XG4gIH1cblxuICBwcm9jZXNzX3Vuc2lnbmVkKHZhbHVlKSB7XG4gICAgcmV0dXJuIHZhbHVlO1xuICB9XG5cbiAgcHJvY2Vzc19uYXRpdmUodmFsdWUpIHtcbiAgICByZXR1cm4gdmFsdWU7XG4gIH1cblxuICBwcm9jZXNzX2JpZyh2YWx1ZSkge1xuICAgIHJldHVybiB2YWx1ZTtcbiAgfVxuXG4gIHByb2Nlc3NfbGl0dGxlKHZhbHVlKSB7XG4gICAgcmV0dXJuIHZhbHVlLnJldmVyc2UoKTtcbiAgfVxuXG4gIHByb2Nlc3Nfc2l6ZSh2YWx1ZSkge1xuICAgIHJldHVybiB2YWx1ZTtcbiAgfVxuXG4gIHByb2Nlc3NfdW5pdCh2YWx1ZSkge1xuICAgIHJldHVybiB2YWx1ZTtcbiAgfVxuXG4gIHN0YXRpYyBpbnRlZ2VyKHZhbHVlKSB7XG4gICAgcmV0dXJuIEJpdFN0cmluZy53cmFwKHZhbHVlLCB7ICd0eXBlJzogJ2ludGVnZXInLCAndW5pdCc6IDEsICdzaXplJzogOCB9KTtcbiAgfVxuXG4gIHN0YXRpYyBmbG9hdCh2YWx1ZSkge1xuICAgIHJldHVybiBCaXRTdHJpbmcud3JhcCh2YWx1ZSwgeyAndHlwZSc6ICdmbG9hdCcsICd1bml0JzogMSwgJ3NpemUnOiA2NCB9KTtcbiAgfVxuXG4gIHN0YXRpYyBiaXRzdHJpbmcodmFsdWUpIHtcbiAgICByZXR1cm4gQml0U3RyaW5nLndyYXAodmFsdWUsIHsgJ3R5cGUnOiAnYml0c3RyaW5nJywgJ3VuaXQnOiAxLCAnc2l6ZSc6IHZhbHVlLmJpdF9zaXplIH0pO1xuICB9XG5cbiAgc3RhdGljIGJpdHModmFsdWUpIHtcbiAgICByZXR1cm4gQml0U3RyaW5nLmJpdHN0cmluZyh2YWx1ZSk7XG4gIH1cblxuICBzdGF0aWMgYmluYXJ5KHZhbHVlKSB7XG4gICAgcmV0dXJuIEJpdFN0cmluZy53cmFwKHZhbHVlLCB7ICd0eXBlJzogJ2JpbmFyeScsICd1bml0JzogOCwgJ3NpemUnOiB2YWx1ZS5sZW5ndGggfSk7XG4gIH1cblxuICBzdGF0aWMgYnl0ZXModmFsdWUpIHtcbiAgICByZXR1cm4gQml0U3RyaW5nLmJpbmFyeSh2YWx1ZSk7XG4gIH1cblxuICBzdGF0aWMgdXRmOCh2YWx1ZSkge1xuICAgIHJldHVybiBCaXRTdHJpbmcud3JhcCh2YWx1ZSwgeyAndHlwZSc6ICd1dGY4JywgJ3VuaXQnOiAxLCAnc2l6ZSc6IHZhbHVlLmxlbmd0aCB9KTtcbiAgfVxuXG4gIHN0YXRpYyB1dGYxNih2YWx1ZSkge1xuICAgIHJldHVybiBCaXRTdHJpbmcud3JhcCh2YWx1ZSwgeyAndHlwZSc6ICd1dGYxNicsICd1bml0JzogMSwgJ3NpemUnOiB2YWx1ZS5sZW5ndGggKiAyIH0pO1xuICB9XG5cbiAgc3RhdGljIHV0ZjMyKHZhbHVlKSB7XG4gICAgcmV0dXJuIEJpdFN0cmluZy53cmFwKHZhbHVlLCB7ICd0eXBlJzogJ3V0ZjMyJywgJ3VuaXQnOiAxLCAnc2l6ZSc6IHZhbHVlLmxlbmd0aCAqIDQgfSk7XG4gIH1cblxuICBzdGF0aWMgc2lnbmVkKHZhbHVlKSB7XG4gICAgcmV0dXJuIEJpdFN0cmluZy53cmFwKHZhbHVlLCB7fSwgJ3NpZ25lZCcpO1xuICB9XG5cbiAgc3RhdGljIHVuc2lnbmVkKHZhbHVlKSB7XG4gICAgcmV0dXJuIEJpdFN0cmluZy53cmFwKHZhbHVlLCB7fSwgJ3Vuc2lnbmVkJyk7XG4gIH1cblxuICBzdGF0aWMgbmF0aXZlKHZhbHVlKSB7XG4gICAgcmV0dXJuIEJpdFN0cmluZy53cmFwKHZhbHVlLCB7fSwgJ25hdGl2ZScpO1xuICB9XG5cbiAgc3RhdGljIGJpZyh2YWx1ZSkge1xuICAgIHJldHVybiBCaXRTdHJpbmcud3JhcCh2YWx1ZSwge30sICdiaWcnKTtcbiAgfVxuXG4gIHN0YXRpYyBsaXR0bGUodmFsdWUpIHtcbiAgICByZXR1cm4gQml0U3RyaW5nLndyYXAodmFsdWUsIHt9LCAnbGl0dGxlJyk7XG4gIH1cblxuICBzdGF0aWMgc2l6ZSh2YWx1ZSwgY291bnQpIHtcbiAgICByZXR1cm4gQml0U3RyaW5nLndyYXAodmFsdWUsIHsgJ3NpemUnOiBjb3VudCB9KTtcbiAgfVxuXG4gIHN0YXRpYyB1bml0KHZhbHVlLCBjb3VudCkge1xuICAgIHJldHVybiBCaXRTdHJpbmcud3JhcCh2YWx1ZSwgeyAndW5pdCc6IGNvdW50IH0pO1xuICB9XG5cbiAgc3RhdGljIHdyYXAodmFsdWUsIG9wdCwgbmV3X2F0dHJpYnV0ZSA9IG51bGwpIHtcbiAgICBsZXQgdGhlX3ZhbHVlID0gdmFsdWU7XG5cbiAgICBpZiAoISh2YWx1ZSBpbnN0YW5jZW9mIE9iamVjdCkpIHtcbiAgICAgIHRoZV92YWx1ZSA9IHsgJ3ZhbHVlJzogdmFsdWUsICdhdHRyaWJ1dGVzJzogW10gfTtcbiAgICB9XG5cbiAgICB0aGVfdmFsdWUgPSBPYmplY3QuYXNzaWduKHRoZV92YWx1ZSwgb3B0KTtcblxuICAgIGlmIChuZXdfYXR0cmlidXRlKSB7XG4gICAgICB0aGVfdmFsdWUuYXR0cmlidXRlcy5wdXNoKG5ld19hdHRyaWJ1dGUpO1xuICAgIH1cblxuICAgIHJldHVybiB0aGVfdmFsdWU7XG4gIH1cblxuICBzdGF0aWMgdG9VVEY4QXJyYXkoc3RyKSB7XG4gICAgdmFyIHV0ZjggPSBbXTtcbiAgICBmb3IgKHZhciBpID0gMDsgaSA8IHN0ci5sZW5ndGg7IGkrKykge1xuICAgICAgdmFyIGNoYXJjb2RlID0gc3RyLmNoYXJDb2RlQXQoaSk7XG4gICAgICBpZiAoY2hhcmNvZGUgPCAweDgwKSB7XG4gICAgICAgIHV0ZjgucHVzaChjaGFyY29kZSk7XG4gICAgICB9IGVsc2UgaWYgKGNoYXJjb2RlIDwgMHg4MDApIHtcbiAgICAgICAgdXRmOC5wdXNoKDB4YzAgfCBjaGFyY29kZSA+PiA2LCAweDgwIHwgY2hhcmNvZGUgJiAweDNmKTtcbiAgICAgIH0gZWxzZSBpZiAoY2hhcmNvZGUgPCAweGQ4MDAgfHwgY2hhcmNvZGUgPj0gMHhlMDAwKSB7XG4gICAgICAgIHV0ZjgucHVzaCgweGUwIHwgY2hhcmNvZGUgPj4gMTIsIDB4ODAgfCBjaGFyY29kZSA+PiA2ICYgMHgzZiwgMHg4MCB8IGNoYXJjb2RlICYgMHgzZik7XG4gICAgICB9XG4gICAgICAvLyBzdXJyb2dhdGUgcGFpclxuICAgICAgZWxzZSB7XG4gICAgICAgICAgaSsrO1xuICAgICAgICAgIC8vIFVURi0xNiBlbmNvZGVzIDB4MTAwMDAtMHgxMEZGRkYgYnlcbiAgICAgICAgICAvLyBzdWJ0cmFjdGluZyAweDEwMDAwIGFuZCBzcGxpdHRpbmcgdGhlXG4gICAgICAgICAgLy8gMjAgYml0cyBvZiAweDAtMHhGRkZGRiBpbnRvIHR3byBoYWx2ZXNcbiAgICAgICAgICBjaGFyY29kZSA9IDB4MTAwMDAgKyAoKGNoYXJjb2RlICYgMHgzZmYpIDw8IDEwIHwgc3RyLmNoYXJDb2RlQXQoaSkgJiAweDNmZik7XG4gICAgICAgICAgdXRmOC5wdXNoKDB4ZjAgfCBjaGFyY29kZSA+PiAxOCwgMHg4MCB8IGNoYXJjb2RlID4+IDEyICYgMHgzZiwgMHg4MCB8IGNoYXJjb2RlID4+IDYgJiAweDNmLCAweDgwIHwgY2hhcmNvZGUgJiAweDNmKTtcbiAgICAgICAgfVxuICAgIH1cbiAgICByZXR1cm4gdXRmODtcbiAgfVxuXG4gIHN0YXRpYyB0b1VURjE2QXJyYXkoc3RyKSB7XG4gICAgdmFyIHV0ZjE2ID0gW107XG4gICAgZm9yICh2YXIgaSA9IDA7IGkgPCBzdHIubGVuZ3RoOyBpKyspIHtcbiAgICAgIHZhciBjb2RlUG9pbnQgPSBzdHIuY29kZVBvaW50QXQoaSk7XG5cbiAgICAgIGlmIChjb2RlUG9pbnQgPD0gMjU1KSB7XG4gICAgICAgIHV0ZjE2LnB1c2goMCk7XG4gICAgICAgIHV0ZjE2LnB1c2goY29kZVBvaW50KTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHV0ZjE2LnB1c2goY29kZVBvaW50ID4+IDggJiAweEZGKTtcbiAgICAgICAgdXRmMTYucHVzaChjb2RlUG9pbnQgJiAweEZGKTtcbiAgICAgIH1cbiAgICB9XG4gICAgcmV0dXJuIHV0ZjE2O1xuICB9XG5cbiAgc3RhdGljIHRvVVRGMzJBcnJheShzdHIpIHtcbiAgICB2YXIgdXRmMzIgPSBbXTtcbiAgICBmb3IgKHZhciBpID0gMDsgaSA8IHN0ci5sZW5ndGg7IGkrKykge1xuICAgICAgdmFyIGNvZGVQb2ludCA9IHN0ci5jb2RlUG9pbnRBdChpKTtcblxuICAgICAgaWYgKGNvZGVQb2ludCA8PSAyNTUpIHtcbiAgICAgICAgdXRmMzIucHVzaCgwKTtcbiAgICAgICAgdXRmMzIucHVzaCgwKTtcbiAgICAgICAgdXRmMzIucHVzaCgwKTtcbiAgICAgICAgdXRmMzIucHVzaChjb2RlUG9pbnQpO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgdXRmMzIucHVzaCgwKTtcbiAgICAgICAgdXRmMzIucHVzaCgwKTtcbiAgICAgICAgdXRmMzIucHVzaChjb2RlUG9pbnQgPj4gOCAmIDB4RkYpO1xuICAgICAgICB1dGYzMi5wdXNoKGNvZGVQb2ludCAmIDB4RkYpO1xuICAgICAgfVxuICAgIH1cbiAgICByZXR1cm4gdXRmMzI7XG4gIH1cblxuICAvL2h0dHA6Ly9zdGFja292ZXJmbG93LmNvbS9xdWVzdGlvbnMvMjAwMzQ5My9qYXZhc2NyaXB0LWZsb2F0LWZyb20tdG8tYml0c1xuICBzdGF0aWMgZmxvYXQzMlRvQnl0ZXMoZikge1xuICAgIHZhciBieXRlcyA9IFtdO1xuXG4gICAgdmFyIGJ1ZiA9IG5ldyBBcnJheUJ1ZmZlcig0KTtcbiAgICBuZXcgRmxvYXQzMkFycmF5KGJ1ZilbMF0gPSBmO1xuXG4gICAgbGV0IGludFZlcnNpb24gPSBuZXcgVWludDMyQXJyYXkoYnVmKVswXTtcblxuICAgIGJ5dGVzLnB1c2goaW50VmVyc2lvbiA+PiAyNCAmIDB4RkYpO1xuICAgIGJ5dGVzLnB1c2goaW50VmVyc2lvbiA+PiAxNiAmIDB4RkYpO1xuICAgIGJ5dGVzLnB1c2goaW50VmVyc2lvbiA+PiA4ICYgMHhGRik7XG4gICAgYnl0ZXMucHVzaChpbnRWZXJzaW9uICYgMHhGRik7XG5cbiAgICByZXR1cm4gYnl0ZXM7XG4gIH1cblxuICBzdGF0aWMgZmxvYXQ2NFRvQnl0ZXMoZikge1xuICAgIHZhciBieXRlcyA9IFtdO1xuXG4gICAgdmFyIGJ1ZiA9IG5ldyBBcnJheUJ1ZmZlcig4KTtcbiAgICBuZXcgRmxvYXQ2NEFycmF5KGJ1ZilbMF0gPSBmO1xuXG4gICAgdmFyIGludFZlcnNpb24xID0gbmV3IFVpbnQzMkFycmF5KGJ1ZilbMF07XG4gICAgdmFyIGludFZlcnNpb24yID0gbmV3IFVpbnQzMkFycmF5KGJ1ZilbMV07XG5cbiAgICBieXRlcy5wdXNoKGludFZlcnNpb24yID4+IDI0ICYgMHhGRik7XG4gICAgYnl0ZXMucHVzaChpbnRWZXJzaW9uMiA+PiAxNiAmIDB4RkYpO1xuICAgIGJ5dGVzLnB1c2goaW50VmVyc2lvbjIgPj4gOCAmIDB4RkYpO1xuICAgIGJ5dGVzLnB1c2goaW50VmVyc2lvbjIgJiAweEZGKTtcblxuICAgIGJ5dGVzLnB1c2goaW50VmVyc2lvbjEgPj4gMjQgJiAweEZGKTtcbiAgICBieXRlcy5wdXNoKGludFZlcnNpb24xID4+IDE2ICYgMHhGRik7XG4gICAgYnl0ZXMucHVzaChpbnRWZXJzaW9uMSA+PiA4ICYgMHhGRik7XG4gICAgYnl0ZXMucHVzaChpbnRWZXJzaW9uMSAmIDB4RkYpO1xuXG4gICAgcmV0dXJuIGJ5dGVzO1xuICB9XG59XG5cbmV4cG9ydCBkZWZhdWx0IEJpdFN0cmluZztcbi8vIyBzb3VyY2VNYXBwaW5nVVJMPWRhdGE6YXBwbGljYXRpb24vanNvbjtiYXNlNjQsZXlKMlpYSnphVzl1SWpvekxDSnpiM1Z5WTJWeklqcGJJbXhwWWk5amIzSmxMMkpwZEY5emRISnBibWN1YW5NaVhTd2libUZ0WlhNaU9sdGRMQ0p0WVhCd2FXNW5jeUk2SWtGQlFVRXNUVUZCVFN4VFFVRk9MRU5CUVdkQ08wRkJRMlFzWTBGQldTeEhRVUZITEVsQlFVZ3NSVUZCVVR0QlFVTnNRaXhUUVVGTExFdEJRVXdzUjBGQllTeFBRVUZQTEUxQlFWQXNRMEZCWXl4TFFVRkxMRTlCUVV3c1EwRkJZU3hKUVVGaUxFTkJRV1FzUTBGQllpeERRVVJyUWp0QlFVVnNRaXhUUVVGTExFMUJRVXdzUjBGQll5eExRVUZMTEV0QlFVd3NRMEZCVnl4TlFVRllMRU5CUmtrN1FVRkhiRUlzVTBGQlN5eFJRVUZNTEVkQlFXZENMRXRCUVVzc1RVRkJUQ3hIUVVGakxFTkJRV1FzUTBGSVJUdEJRVWxzUWl4VFFVRkxMRk5CUVV3c1IwRkJhVUlzUzBGQlN5eE5RVUZNTEVOQlNrTTdSMEZCY0VJN08wRkJUMEVzVFVGQlNTeExRVUZLTEVWQlFWVTdRVUZEVWl4WFFVRlBMRXRCUVVzc1MwRkJUQ3hEUVVGWExFdEJRVmdzUTBGQlVDeERRVVJSTzBkQlFWWTdPMEZCU1VFc1ZVRkJUenRCUVVOTUxGZEJRVThzUzBGQlN5eExRVUZNTEVOQlFWY3NUVUZCV0N4RFFVUkdPMGRCUVZBN08wRkJTVUVzVVVGQlRTeExRVUZPTEVWQlFXRXNUVUZCVFN4SlFVRk9MRVZCUVZjN1FVRkRkRUlzVVVGQlNTeEpRVUZKTEV0QlFVc3NTMEZCVEN4RFFVRlhMRXRCUVZnc1EwRkJhVUlzUzBGQmFrSXNSVUZCZDBJc1IwRkJlRUlzUTBGQlNpeERRVVJyUWp0QlFVVjBRaXhSUVVGSkxFdEJRVXNzUlVGQlJTeEhRVUZHTEVOQlFVMHNVVUZCVlN4VlFVRlZMRTlCUVZZc1EwRkJhMElzU1VGQmJFSXNRMEZCVml4RFFVRllMRU5CUm10Q08wRkJSM1JDTEZkQlFVOHNTVUZCU1N4VFFVRktMRU5CUVdNc1IwRkJSeXhGUVVGSUxFTkJRWEpDTEVOQlNITkNPMGRCUVhoQ096dEJRVTFCTEVkQlFVTXNUMEZCVHl4UlFVRlFMRWxCUVcxQ08wRkJRMnhDTEZkQlFVOHNTMEZCU3l4TFFVRk1MRU5CUVZjc1QwRkJUeXhSUVVGUUxFTkJRVmdzUlVGQlVDeERRVVJyUWp0SFFVRndRanM3UVVGSlFTeGhRVUZWTzBGQlExSXNVVUZCU1N4RFFVRktPMUZCUVU4c1NVRkJTU3hGUVVGS0xFTkJSRU03UVVGRlVpeFRRVUZMTEVsQlFVa3NRMEZCU2l4RlFVRlBMRWxCUVVrc1MwRkJTeXhMUVVGTUxFVkJRVW9zUlVGQmEwSXNSMEZCT1VJc1JVRkJiVU03UVVGRGFrTXNWVUZCU1N4TlFVRk5MRVZCUVU0c1JVRkJWVHRCUVVOYUxHRkJRVXNzU1VGQlRDeERRVVJaTzA5QlFXUTdRVUZIUVN4WFFVRkxMRXRCUVVzc1IwRkJUQ3hEUVVGVExFTkJRVlFzUlVGQldTeFJRVUZhTEVWQlFVd3NRMEZLYVVNN1MwRkJia003TzBGQlQwRXNWMEZCVHl4UFFVRlBMRU5CUVZBc1IwRkJWeXhKUVVGWUxFTkJWRU03UjBGQlZqczdRVUZaUVN4VlFVRlJMR05CUVZJc1JVRkJkVUk3UVVGRGNrSXNVVUZCU1N4dFFrRkJiVUlzUlVGQmJrSXNRMEZFYVVJN08wRkJSM0pDTEZGQlFVa3NRMEZCU2l4RFFVaHhRanRCUVVseVFpeFRRVUZMTEVsQlFVa3NRMEZCU2l4RlFVRlBMRWxCUVVrc1pVRkJaU3hOUVVGbUxFVkJRWFZDTEVkQlFYWkRMRVZCUVRSRE8wRkJRekZETEZWQlFVa3NhMEpCUVd0Q0xFdEJRVXNzWVVGQllTeGxRVUZsTEVOQlFXWXNSVUZCYTBJc1NVRkJiRUlzUTBGQmJFSXNRMEZCTUVNc1pVRkJaU3hEUVVGbUxFTkJRVEZETEVOQlFXeENMRU5CUkhORE96dEJRVWN4UXl4WFFVRkpMRWxCUVVrc1NVRkJTaXhKUVVGWkxHVkJRV1VzUTBGQlppeEZRVUZyUWl4VlFVRnNRaXhGUVVFMlFqdEJRVU16UXl3d1FrRkJhMElzUzBGQlN5eGhRVUZoTEVsQlFXSXNRMEZCVEN4RFFVRjNRaXhsUVVGNFFpeERRVUZzUWl4RFFVUXlRenRQUVVFM1F6czdRVUZKUVN4NVFrRkJiVUlzYVVKQlFXbENMRTFCUVdwQ0xFTkJRWGRDTEdWQlFYaENMRU5CUVc1Q0xFTkJVREJETzB0QlFUVkRPenRCUVZWQkxGZEJRVThzWjBKQlFWQXNRMEZrY1VJN1IwRkJka0k3TzBGQmFVSkJMR3RDUVVGblFpeExRVUZvUWl4RlFVRnpRanRCUVVOd1FpeFhRVUZQTEUxQlFVMHNTMEZCVGl4RFFVUmhPMGRCUVhSQ096dEJRVWxCTEdkQ1FVRmpMRXRCUVdRc1JVRkJiMEk3UVVGRGJFSXNVVUZCUnl4TlFVRk5MRWxCUVU0c1MwRkJaU3hGUVVGbUxFVkJRV3RDTzBGQlEyNUNMR0ZCUVU4c1ZVRkJWU3hqUVVGV0xFTkJRWGxDTEUxQlFVMHNTMEZCVGl4RFFVRm9ReXhEUVVSdFFqdExRVUZ5UWl4TlFVVk5MRWxCUVVjc1RVRkJUU3hKUVVGT0xFdEJRV1VzUlVGQlppeEZRVUZyUWp0QlFVTjZRaXhoUVVGUExGVkJRVlVzWTBGQlZpeERRVUY1UWl4TlFVRk5MRXRCUVU0c1EwRkJhRU1zUTBGRWVVSTdTMEZCY2tJN08wRkJTVTRzVlVGQlRTeEpRVUZKTEV0QlFVb3NRMEZCVlN4M1FrRkJWaXhEUVVGT0xFTkJVR3RDTzBkQlFYQkNPenRCUVZWQkxHOUNRVUZyUWl4TFFVRnNRaXhGUVVGM1FqdEJRVU4wUWl4WFFVRlBMRTFCUVUwc1MwRkJUaXhEUVVGWkxFdEJRVm9zUTBGRVpUdEhRVUY0UWpzN1FVRkpRU3hwUWtGQlpTeExRVUZtTEVWQlFYRkNPMEZCUTI1Q0xGZEJRVThzVlVGQlZTeFhRVUZXTEVOQlFYTkNMRTFCUVUwc1MwRkJUaXhEUVVFM1FpeERRVVJ0UWp0SFFVRnlRanM3UVVGSlFTeGxRVUZoTEV0QlFXSXNSVUZCYlVJN1FVRkRha0lzVjBGQlR5eFZRVUZWTEZkQlFWWXNRMEZCYzBJc1RVRkJUU3hMUVVGT0xFTkJRVGRDTEVOQlJHbENPMGRCUVc1Q096dEJRVWxCTEdkQ1FVRmpMRXRCUVdRc1JVRkJiMEk3UVVGRGJFSXNWMEZCVHl4VlFVRlZMRmxCUVZZc1EwRkJkVUlzVFVGQlRTeExRVUZPTEVOQlFUbENMRU5CUkd0Q08wZEJRWEJDT3p0QlFVbEJMR2RDUVVGakxFdEJRV1FzUlVGQmIwSTdRVUZEYkVJc1YwRkJUeXhWUVVGVkxGbEJRVllzUTBGQmRVSXNUVUZCVFN4TFFVRk9MRU5CUVRsQ0xFTkJSR3RDTzBkQlFYQkNPenRCUVVsQkxHbENRVUZsTEV0QlFXWXNSVUZCY1VJN1FVRkRia0lzVjBGQlR5eEpRVUZMTEZWQlFVb3NRMEZCWlN4RFFVRkRMRXRCUVVRc1EwRkJaaXhEUVVGRUxFTkJRVEJDTEVOQlFURkNMRU5CUVZBc1EwRkViVUk3UjBGQmNrSTdPMEZCU1VFc2JVSkJRV2xDTEV0QlFXcENMRVZCUVhWQ08wRkJRM0pDTEZkQlFVOHNTMEZCVUN4RFFVUnhRanRIUVVGMlFqczdRVUZKUVN4cFFrRkJaU3hMUVVGbUxFVkJRWEZDTzBGQlEyNUNMRmRCUVU4c1MwRkJVQ3hEUVVSdFFqdEhRVUZ5UWpzN1FVRkpRU3hqUVVGWkxFdEJRVm9zUlVGQmEwSTdRVUZEYUVJc1YwRkJUeXhMUVVGUUxFTkJSR2RDTzBkQlFXeENPenRCUVVsQkxHbENRVUZsTEV0QlFXWXNSVUZCY1VJN1FVRkRia0lzVjBGQlR5eE5RVUZOTEU5QlFVNHNSVUZCVUN4RFFVUnRRanRIUVVGeVFqczdRVUZKUVN4bFFVRmhMRXRCUVdJc1JVRkJiVUk3UVVGRGFrSXNWMEZCVHl4TFFVRlFMRU5CUkdsQ08wZEJRVzVDT3p0QlFVbEJMR1ZCUVdFc1MwRkJZaXhGUVVGdFFqdEJRVU5xUWl4WFFVRlBMRXRCUVZBc1EwRkVhVUk3UjBGQmJrSTdPMEZCU1VFc1UwRkJUeXhQUVVGUUxFTkJRV1VzUzBGQlppeEZRVUZ4UWp0QlFVTnVRaXhYUVVGUExGVkJRVlVzU1VGQlZpeERRVUZsTEV0QlFXWXNSVUZCYzBJc1JVRkJSU3hSUVVGUkxGTkJRVklzUlVGQmJVSXNVVUZCVVN4RFFVRlNMRVZCUVZjc1VVRkJVU3hEUVVGU0xFVkJRWFJFTEVOQlFWQXNRMEZFYlVJN1IwRkJja0k3TzBGQlNVRXNVMEZCVHl4TFFVRlFMRU5CUVdFc1MwRkJZaXhGUVVGdFFqdEJRVU5xUWl4WFFVRlBMRlZCUVZVc1NVRkJWaXhEUVVGbExFdEJRV1lzUlVGQmMwSXNSVUZCUlN4UlFVRlJMRTlCUVZJc1JVRkJhVUlzVVVGQlVTeERRVUZTTEVWQlFWY3NVVUZCVVN4RlFVRlNMRVZCUVhCRUxFTkJRVkFzUTBGRWFVSTdSMEZCYmtJN08wRkJTVUVzVTBGQlR5eFRRVUZRTEVOQlFXbENMRXRCUVdwQ0xFVkJRWFZDTzBGQlEzSkNMRmRCUVU4c1ZVRkJWU3hKUVVGV0xFTkJRV1VzUzBGQlppeEZRVUZ6UWl4RlFVRkZMRkZCUVZFc1YwRkJVaXhGUVVGeFFpeFJRVUZSTEVOQlFWSXNSVUZCVnl4UlFVRlJMRTFCUVUwc1VVRkJUaXhGUVVGb1JTeERRVUZRTEVOQlJIRkNPMGRCUVhaQ096dEJRVWxCTEZOQlFVOHNTVUZCVUN4RFFVRlpMRXRCUVZvc1JVRkJhMEk3UVVGRGFFSXNWMEZCVHl4VlFVRlZMRk5CUVZZc1EwRkJiMElzUzBGQmNFSXNRMEZCVUN4RFFVUm5RanRIUVVGc1FqczdRVUZKUVN4VFFVRlBMRTFCUVZBc1EwRkJZeXhMUVVGa0xFVkJRVzlDTzBGQlEyeENMRmRCUVU4c1ZVRkJWU3hKUVVGV0xFTkJRV1VzUzBGQlppeEZRVUZ6UWl4RlFVRkZMRkZCUVZFc1VVRkJVaXhGUVVGclFpeFJRVUZSTEVOQlFWSXNSVUZCVnl4UlFVRlJMRTFCUVUwc1RVRkJUaXhGUVVFM1JDeERRVUZRTEVOQlJHdENPMGRCUVhCQ096dEJRVWxCTEZOQlFVOHNTMEZCVUN4RFFVRmhMRXRCUVdJc1JVRkJiVUk3UVVGRGFrSXNWMEZCVHl4VlFVRlZMRTFCUVZZc1EwRkJhVUlzUzBGQmFrSXNRMEZCVUN4RFFVUnBRanRIUVVGdVFqczdRVUZKUVN4VFFVRlBMRWxCUVZBc1EwRkJXU3hMUVVGYUxFVkJRV3RDTzBGQlEyaENMRmRCUVU4c1ZVRkJWU3hKUVVGV0xFTkJRV1VzUzBGQlppeEZRVUZ6UWl4RlFVRkZMRkZCUVZFc1RVRkJVaXhGUVVGblFpeFJRVUZSTEVOQlFWSXNSVUZCVnl4UlFVRlJMRTFCUVUwc1RVRkJUaXhGUVVFelJDeERRVUZRTEVOQlJHZENPMGRCUVd4Q096dEJRVWxCTEZOQlFVOHNTMEZCVUN4RFFVRmhMRXRCUVdJc1JVRkJiVUk3UVVGRGFrSXNWMEZCVHl4VlFVRlZMRWxCUVZZc1EwRkJaU3hMUVVGbUxFVkJRWE5DTEVWQlFVVXNVVUZCVVN4UFFVRlNMRVZCUVdsQ0xGRkJRVkVzUTBGQlVpeEZRVUZYTEZGQlFWRXNUVUZCVFN4TlFVRk9MRWRCUVdVc1EwRkJaaXhGUVVFMVJDeERRVUZRTEVOQlJHbENPMGRCUVc1Q096dEJRVWxCTEZOQlFVOHNTMEZCVUN4RFFVRmhMRXRCUVdJc1JVRkJiVUk3UVVGRGFrSXNWMEZCVHl4VlFVRlZMRWxCUVZZc1EwRkJaU3hMUVVGbUxFVkJRWE5DTEVWQlFVVXNVVUZCVVN4UFFVRlNMRVZCUVdsQ0xGRkJRVkVzUTBGQlVpeEZRVUZYTEZGQlFWRXNUVUZCVFN4TlFVRk9MRWRCUVdVc1EwRkJaaXhGUVVFMVJDeERRVUZRTEVOQlJHbENPMGRCUVc1Q096dEJRVWxCTEZOQlFVOHNUVUZCVUN4RFFVRmpMRXRCUVdRc1JVRkJiMEk3UVVGRGJFSXNWMEZCVHl4VlFVRlZMRWxCUVZZc1EwRkJaU3hMUVVGbUxFVkJRWE5DTEVWQlFYUkNMRVZCUVRCQ0xGRkJRVEZDTEVOQlFWQXNRMEZFYTBJN1IwRkJjRUk3TzBGQlNVRXNVMEZCVHl4UlFVRlFMRU5CUVdkQ0xFdEJRV2hDTEVWQlFYTkNPMEZCUTNCQ0xGZEJRVThzVlVGQlZTeEpRVUZXTEVOQlFXVXNTMEZCWml4RlFVRnpRaXhGUVVGMFFpeEZRVUV3UWl4VlFVRXhRaXhEUVVGUUxFTkJSRzlDTzBkQlFYUkNPenRCUVVsQkxGTkJRVThzVFVGQlVDeERRVUZqTEV0QlFXUXNSVUZCYjBJN1FVRkRiRUlzVjBGQlR5eFZRVUZWTEVsQlFWWXNRMEZCWlN4TFFVRm1MRVZCUVhOQ0xFVkJRWFJDTEVWQlFUQkNMRkZCUVRGQ0xFTkJRVkFzUTBGRWEwSTdSMEZCY0VJN08wRkJTVUVzVTBGQlR5eEhRVUZRTEVOQlFWY3NTMEZCV0N4RlFVRnBRanRCUVVObUxGZEJRVThzVlVGQlZTeEpRVUZXTEVOQlFXVXNTMEZCWml4RlFVRnpRaXhGUVVGMFFpeEZRVUV3UWl4TFFVRXhRaXhEUVVGUUxFTkJSR1U3UjBGQmFrSTdPMEZCU1VFc1UwRkJUeXhOUVVGUUxFTkJRV01zUzBGQlpDeEZRVUZ2UWp0QlFVTnNRaXhYUVVGUExGVkJRVlVzU1VGQlZpeERRVUZsTEV0QlFXWXNSVUZCYzBJc1JVRkJkRUlzUlVGQk1FSXNVVUZCTVVJc1EwRkJVQ3hEUVVSclFqdEhRVUZ3UWpzN1FVRkpRU3hUUVVGUExFbEJRVkFzUTBGQldTeExRVUZhTEVWQlFXMUNMRXRCUVc1Q0xFVkJRWGxDTzBGQlEzWkNMRmRCUVU4c1ZVRkJWU3hKUVVGV0xFTkJRV1VzUzBGQlppeEZRVUZ6UWl4RlFVRkRMRkZCUVZFc1MwRkJVaXhGUVVGMlFpeERRVUZRTEVOQlJIVkNPMGRCUVhwQ096dEJRVWxCTEZOQlFVOHNTVUZCVUN4RFFVRlpMRXRCUVZvc1JVRkJiVUlzUzBGQmJrSXNSVUZCZVVJN1FVRkRka0lzVjBGQlR5eFZRVUZWTEVsQlFWWXNRMEZCWlN4TFFVRm1MRVZCUVhOQ0xFVkJRVU1zVVVGQlVTeExRVUZTTEVWQlFYWkNMRU5CUVZBc1EwRkVkVUk3UjBGQmVrSTdPMEZCU1VFc1UwRkJUeXhKUVVGUUxFTkJRVmtzUzBGQldpeEZRVUZ0UWl4SFFVRnVRaXhGUVVGM1FpeG5Ra0ZCWjBJc1NVRkJhRUlzUlVGQmNVSTdRVUZETTBNc1VVRkJTU3haUVVGWkxFdEJRVm9zUTBGRWRVTTdPMEZCUnpORExGRkJRVWNzUlVGQlJTeHBRa0ZCYVVJc1RVRkJha0lzUTBGQlJpeEZRVUV5UWp0QlFVTTFRaXhyUWtGQldTeEZRVUZETEZOQlFWTXNTMEZCVkN4RlFVRm5RaXhqUVVGakxFVkJRV1FzUlVGQk4wSXNRMEZFTkVJN1MwRkJPVUk3TzBGQlNVRXNaMEpCUVZrc1QwRkJUeXhOUVVGUUxFTkJRV01zVTBGQlpDeEZRVUY1UWl4SFFVRjZRaXhEUVVGYUxFTkJVREpET3p0QlFWTXpReXhSUVVGSExHRkJRVWdzUlVGQmFVSTdRVUZEWml4blFrRkJWU3hWUVVGV0xFTkJRWEZDTEVsQlFYSkNMRU5CUVRCQ0xHRkJRVEZDTEVWQlJHVTdTMEZCYWtJN08wRkJTMEVzVjBGQlR5eFRRVUZRTEVOQlpESkRPMGRCUVRkRE96dEJRV2xDUVN4VFFVRlBMRmRCUVZBc1EwRkJiVUlzUjBGQmJrSXNSVUZCZDBJN1FVRkRkRUlzVVVGQlNTeFBRVUZQTEVWQlFWQXNRMEZFYTBJN1FVRkZkRUlzVTBGQlN5eEpRVUZKTEVsQlFVa3NRMEZCU2l4RlFVRlBMRWxCUVVrc1NVRkJTU3hOUVVGS0xFVkJRVmtzUjBGQmFFTXNSVUZCY1VNN1FVRkRia01zVlVGQlNTeFhRVUZYTEVsQlFVa3NWVUZCU2l4RFFVRmxMRU5CUVdZc1EwRkJXQ3hEUVVRclFqdEJRVVZ1UXl4VlFVRkpMRmRCUVZjc1NVRkJXQ3hGUVVGblFqdEJRVU5zUWl4aFFVRkxMRWxCUVV3c1EwRkJWU3hSUVVGV0xFVkJSR3RDTzA5QlFYQkNMRTFCUjBzc1NVRkJTU3hYUVVGWExFdEJRVmdzUlVGQmEwSTdRVUZEZWtJc1lVRkJTeXhKUVVGTUxFTkJRVlVzVDBGQlVTeFpRVUZaTEVOQlFWb3NSVUZEVWl4UFFVRlJMRmRCUVZjc1NVRkJXQ3hEUVVSc1FpeERRVVI1UWp0UFFVRjBRaXhOUVVsQkxFbEJRVWtzVjBGQlZ5eE5RVUZZTEVsQlFYRkNMRmxCUVZrc1RVRkJXaXhGUVVGdlFqdEJRVU5vUkN4aFFVRkxMRWxCUVV3c1EwRkJWU3hQUVVGUkxGbEJRVmtzUlVGQldpeEZRVU5TTEU5QlFWRXNVVUZCUXl4SlFVRlpMRU5CUVZvc1IwRkJhVUlzU1VGQmJFSXNSVUZEVWl4UFFVRlJMRmRCUVZjc1NVRkJXQ3hEUVVac1FpeERRVVJuUkRzN08wRkJRVGRETEZkQlRVRTdRVUZEU0RzN096dEJRVVJITEd0Q1FVdElMRWRCUVZjc1YwRkJWeXhEUVVGRkxGZEJRVmNzUzBGQldDeERRVUZFTEVsQlFYTkNMRVZCUVhSQ0xFZEJRMVlzU1VGQlNTeFZRVUZLTEVOQlFXVXNRMEZCWml4SlFVRnZRaXhMUVVGd1FpeERRVVJHTEVOQlRGSTdRVUZQU0N4bFFVRkxMRWxCUVV3c1EwRkJWU3hQUVVGUkxGbEJRVmtzUlVGQldpeEZRVU5TTEU5QlFWRXNVVUZCUXl4SlFVRlpMRVZCUVZvc1IwRkJhMElzU1VGQmJrSXNSVUZEVWl4UFFVRlJMRkZCUVVNc1NVRkJXU3hEUVVGYUxFZEJRV2xDTEVsQlFXeENMRVZCUTFJc1QwRkJVU3hYUVVGWExFbEJRVmdzUTBGSWJFSXNRMEZRUnp0VFFVNUJPMHRCVkZBN1FVRTBRa0VzVjBGQlR5eEpRVUZRTEVOQk9VSnpRanRIUVVGNFFqczdRVUZwUTBFc1UwRkJUeXhaUVVGUUxFTkJRVzlDTEVkQlFYQkNMRVZCUVhsQ08wRkJRM1pDTEZGQlFVa3NVVUZCVVN4RlFVRlNMRU5CUkcxQ08wRkJSWFpDTEZOQlFVc3NTVUZCU1N4SlFVRkpMRU5CUVVvc1JVRkJUeXhKUVVGSkxFbEJRVWtzVFVGQlNpeEZRVUZaTEVkQlFXaERMRVZCUVhGRE8wRkJRMjVETEZWQlFVa3NXVUZCV1N4SlFVRkpMRmRCUVVvc1EwRkJaMElzUTBGQmFFSXNRMEZCV2l4RFFVUXJRanM3UVVGSGJrTXNWVUZCUnl4aFFVRmhMRWRCUVdJc1JVRkJhVUk3UVVGRGJFSXNZMEZCVFN4SlFVRk9MRU5CUVZjc1EwRkJXQ3hGUVVSclFqdEJRVVZzUWl4alFVRk5MRWxCUVU0c1EwRkJWeXhUUVVGWUxFVkJSbXRDTzA5QlFYQkNMRTFCUjBzN1FVRkRTQ3hqUVVGTkxFbEJRVTRzUTBGQldTeFRRVUZETEVsQlFXRXNRMEZCWWl4SFFVRnJRaXhKUVVGdVFpeERRVUZhTEVOQlJFYzdRVUZGU0N4alFVRk5MRWxCUVU0c1EwRkJXU3haUVVGWkxFbEJRVm9zUTBGQldpeERRVVpITzA5QlNFdzdTMEZJUmp0QlFWZEJMRmRCUVU4c1MwRkJVQ3hEUVdKMVFqdEhRVUY2UWpzN1FVRnBRa0VzVTBGQlR5eFpRVUZRTEVOQlFXOUNMRWRCUVhCQ0xFVkJRWGxDTzBGQlEzWkNMRkZCUVVrc1VVRkJVU3hGUVVGU0xFTkJSRzFDTzBGQlJYWkNMRk5CUVVzc1NVRkJTU3hKUVVGSkxFTkJRVW9zUlVGQlR5eEpRVUZKTEVsQlFVa3NUVUZCU2l4RlFVRlpMRWRCUVdoRExFVkJRWEZETzBGQlEyNURMRlZCUVVrc1dVRkJXU3hKUVVGSkxGZEJRVW9zUTBGQlowSXNRMEZCYUVJc1EwRkJXaXhEUVVRclFqczdRVUZIYmtNc1ZVRkJSeXhoUVVGaExFZEJRV0lzUlVGQmFVSTdRVUZEYkVJc1kwRkJUU3hKUVVGT0xFTkJRVmNzUTBGQldDeEZRVVJyUWp0QlFVVnNRaXhqUVVGTkxFbEJRVTRzUTBGQlZ5eERRVUZZTEVWQlJtdENPMEZCUjJ4Q0xHTkJRVTBzU1VGQlRpeERRVUZYTEVOQlFWZ3NSVUZJYTBJN1FVRkpiRUlzWTBGQlRTeEpRVUZPTEVOQlFWY3NVMEZCV0N4RlFVcHJRanRQUVVGd1FpeE5RVXRMTzBGQlEwZ3NZMEZCVFN4SlFVRk9MRU5CUVZjc1EwRkJXQ3hGUVVSSE8wRkJSVWdzWTBGQlRTeEpRVUZPTEVOQlFWY3NRMEZCV0N4RlFVWkhPMEZCUjBnc1kwRkJUU3hKUVVGT0xFTkJRVmtzVTBGQlF5eEpRVUZoTEVOQlFXSXNSMEZCYTBJc1NVRkJia0lzUTBGQldpeERRVWhITzBGQlNVZ3NZMEZCVFN4SlFVRk9MRU5CUVZrc1dVRkJXU3hKUVVGYUxFTkJRVm9zUTBGS1J6dFBRVXhNTzB0QlNFWTdRVUZsUVN4WFFVRlBMRXRCUVZBc1EwRnFRblZDTzBkQlFYcENPenM3UVVGNFVHTXNVMEUyVVZBc1kwRkJVQ3hEUVVGelFpeERRVUYwUWl4RlFVRjVRanRCUVVOMlFpeFJRVUZKTEZGQlFWRXNSVUZCVWl4RFFVUnRRanM3UVVGSGRrSXNVVUZCU1N4TlFVRk5MRWxCUVVrc1YwRkJTaXhEUVVGblFpeERRVUZvUWl4RFFVRk9MRU5CU0cxQ08wRkJTWFpDTEZGQlFVc3NXVUZCU2l4RFFVRnBRaXhIUVVGcVFpeERRVUZFTEVOQlFYZENMRU5CUVhoQ0xFbEJRVFpDTEVOQlFUZENMRU5CU25WQ096dEJRVTEyUWl4UlFVRkpMR0ZCUVdFc1NVRkJTeXhYUVVGS0xFTkJRV2RDTEVkQlFXaENMRU5CUVVRc1EwRkJkVUlzUTBGQmRrSXNRMEZCWWl4RFFVNXRRanM3UVVGUmRrSXNWVUZCVFN4SlFVRk9MRU5CUVZrc1ZVRkJReXhKUVVGakxFVkJRV1FzUjBGQmIwSXNTVUZCY2tJc1EwRkJXaXhEUVZKMVFqdEJRVk4yUWl4VlFVRk5MRWxCUVU0c1EwRkJXU3hWUVVGRExFbEJRV01zUlVGQlpDeEhRVUZ2UWl4SlFVRnlRaXhEUVVGYUxFTkJWSFZDTzBGQlZYWkNMRlZCUVUwc1NVRkJUaXhEUVVGWkxGVkJRVU1zU1VGQll5eERRVUZrTEVkQlFXMUNMRWxCUVhCQ0xFTkJRVm9zUTBGV2RVSTdRVUZYZGtJc1ZVRkJUU3hKUVVGT0xFTkJRVmtzWVVGQllTeEpRVUZpTEVOQlFWb3NRMEZZZFVJN08wRkJZWFpDTEZkQlFVOHNTMEZCVUN4RFFXSjFRanRIUVVGNlFqczdRVUZuUWtFc1UwRkJUeXhqUVVGUUxFTkJRWE5DTEVOQlFYUkNMRVZCUVhsQ08wRkJRM1pDTEZGQlFVa3NVVUZCVVN4RlFVRlNMRU5CUkcxQ096dEJRVWQyUWl4UlFVRkpMRTFCUVUwc1NVRkJTU3hYUVVGS0xFTkJRV2RDTEVOQlFXaENMRU5CUVU0c1EwRkliVUk3UVVGSmRrSXNVVUZCU3l4WlFVRktMRU5CUVdsQ0xFZEJRV3BDTEVOQlFVUXNRMEZCZDBJc1EwRkJlRUlzU1VGQk5rSXNRMEZCTjBJc1EwRktkVUk3TzBGQlRYWkNMRkZCUVVrc1kwRkJZeXhKUVVGTExGZEJRVW9zUTBGQlowSXNSMEZCYUVJc1EwRkJSQ3hEUVVGMVFpeERRVUYyUWl4RFFVRmtMRU5CVG0xQ08wRkJUM1pDTEZGQlFVa3NZMEZCWXl4SlFVRkxMRmRCUVVvc1EwRkJaMElzUjBGQmFFSXNRMEZCUkN4RFFVRjFRaXhEUVVGMlFpeERRVUZrTEVOQlVHMUNPenRCUVZOMlFpeFZRVUZOTEVsQlFVNHNRMEZCV1N4WFFVRkRMRWxCUVdVc1JVRkJaaXhIUVVGeFFpeEpRVUYwUWl4RFFVRmFMRU5CVkhWQ08wRkJWWFpDTEZWQlFVMHNTVUZCVGl4RFFVRlpMRmRCUVVNc1NVRkJaU3hGUVVGbUxFZEJRWEZDTEVsQlFYUkNMRU5CUVZvc1EwRldkVUk3UVVGWGRrSXNWVUZCVFN4SlFVRk9MRU5CUVZrc1YwRkJReXhKUVVGbExFTkJRV1lzUjBGQmIwSXNTVUZCY2tJc1EwRkJXaXhEUVZoMVFqdEJRVmwyUWl4VlFVRk5MRWxCUVU0c1EwRkJXU3hqUVVGakxFbEJRV1FzUTBGQldpeERRVnAxUWpzN1FVRmpka0lzVlVGQlRTeEpRVUZPTEVOQlFWa3NWMEZCUXl4SlFVRmxMRVZCUVdZc1IwRkJjVUlzU1VGQmRFSXNRMEZCV2l4RFFXUjFRanRCUVdWMlFpeFZRVUZOTEVsQlFVNHNRMEZCV1N4WFFVRkRMRWxCUVdVc1JVRkJaaXhIUVVGeFFpeEpRVUYwUWl4RFFVRmFMRU5CWm5WQ08wRkJaMEoyUWl4VlFVRk5MRWxCUVU0c1EwRkJXU3hYUVVGRExFbEJRV1VzUTBGQlppeEhRVUZ2UWl4SlFVRnlRaXhEUVVGYUxFTkJhRUoxUWp0QlFXbENka0lzVlVGQlRTeEpRVUZPTEVOQlFWa3NZMEZCWXl4SlFVRmtMRU5CUVZvc1EwRnFRblZDT3p0QlFXMUNka0lzVjBGQlR5eExRVUZRTEVOQmJrSjFRanRIUVVGNlFqdERRVGRTUmpzN1FVRnZWRUVzWlVGQlpTeFRRVUZtSWl3aVptbHNaU0k2SW14cFlpOWpiM0psTDJKcGRGOXpkSEpwYm1jdWFuTWlMQ0p6YjNWeVkyVnpRMjl1ZEdWdWRDSTZXeUpqYkdGemN5QkNhWFJUZEhKcGJtY2dlMXh1SUNCamIyNXpkSEoxWTNSdmNpZ3VMaTVoY21kektYdGNiaUFnSUNCMGFHbHpMblpoYkhWbElEMGdUMkpxWldOMExtWnlaV1Y2WlNoMGFHbHpMbkJ5YjJObGMzTW9ZWEpuY3lrcE8xeHVJQ0FnSUhSb2FYTXViR1Z1WjNSb0lEMGdkR2hwY3k1MllXeDFaUzVzWlc1bmRHZzdYRzRnSUNBZ2RHaHBjeTVpYVhSZmMybDZaU0E5SUhSb2FYTXViR1Z1WjNSb0lDb2dPRHRjYmlBZ0lDQjBhR2x6TG1KNWRHVmZjMmw2WlNBOUlIUm9hWE11YkdWdVozUm9PMXh1SUNCOVhHNWNiaUFnWjJWMEtHbHVaR1Y0S1h0Y2JpQWdJQ0J5WlhSMWNtNGdkR2hwY3k1MllXeDFaVnRwYm1SbGVGMDdYRzRnSUgxY2JseHVJQ0JqYjNWdWRDZ3BlMXh1SUNBZ0lISmxkSFZ5YmlCMGFHbHpMblpoYkhWbExteGxibWQwYUR0Y2JpQWdmVnh1WEc0Z0lITnNhV05sS0hOMFlYSjBMQ0JsYm1RZ1BTQnVkV3hzS1h0Y2JpQWdJQ0JzWlhRZ2N5QTlJSFJvYVhNdWRtRnNkV1V1YzJ4cFkyVW9jM1JoY25Rc0lHVnVaQ2s3WEc0Z0lDQWdiR1YwSUcxeklEMGdjeTV0WVhBb0tHVnNaVzBwSUQwK0lFSnBkRk4wY21sdVp5NXBiblJsWjJWeUtHVnNaVzBwS1R0Y2JpQWdJQ0J5WlhSMWNtNGdibVYzSUVKcGRGTjBjbWx1WnlndUxpNXRjeWs3WEc0Z0lIMWNibHh1SUNCYlUzbHRZbTlzTG1sMFpYSmhkRzl5WFNncElIdGNiaUFnSUNCeVpYUjFjbTRnZEdocGN5NTJZV3gxWlZ0VGVXMWliMnd1YVhSbGNtRjBiM0pkS0NrN1hHNGdJSDFjYmx4dUlDQjBiMU4wY21sdVp5Z3BlMXh1SUNBZ0lIWmhjaUJwTENCeklEMGdYQ0pjSWp0Y2JpQWdJQ0JtYjNJZ0tHa2dQU0F3T3lCcElEd2dkR2hwY3k1amIzVnVkQ2dwT3lCcEt5c3BJSHRjYmlBZ0lDQWdJR2xtSUNoeklDRTlQU0JjSWx3aUtTQjdYRzRnSUNBZ0lDQWdJSE1nS3owZ1hDSXNJRndpTzF4dUlDQWdJQ0FnZlZ4dUlDQWdJQ0FnY3lBclBTQjBhR2x6TG1kbGRDaHBLUzUwYjFOMGNtbHVaeWdwTzF4dUlDQWdJSDFjYmx4dUlDQWdJSEpsZEhWeWJpQmNJanc4WENJZ0t5QnpJQ3NnWENJK1Bsd2lPMXh1SUNCOVhHNWNiaUFnY0hKdlkyVnpjeWhpYVhSVGRISnBibWRRWVhKMGN5bDdYRzRnSUNBZ2JHVjBJSEJ5YjJObGMzTmxaRjkyWVd4MVpYTWdQU0JiWFR0Y2JseHVJQ0FnSUhaaGNpQnBPMXh1SUNBZ0lHWnZjaUFvYVNBOUlEQTdJR2tnUENCaWFYUlRkSEpwYm1kUVlYSjBjeTVzWlc1bmRHZzdJR2tyS3lrZ2UxeHVJQ0FnSUNBZ2JHVjBJSEJ5YjJObGMzTmxaRjkyWVd4MVpTQTlJSFJvYVhOYkozQnliMk5sYzNOZkp5QXJJR0pwZEZOMGNtbHVaMUJoY25SelcybGRMblI1Y0dWZEtHSnBkRk4wY21sdVoxQmhjblJ6VzJsZEtUdGNibHh1SUNBZ0lDQWdabTl5S0d4bGRDQmhkSFJ5SUc5bUlHSnBkRk4wY21sdVoxQmhjblJ6VzJsZExtRjBkSEpwWW5WMFpYTXBlMXh1SUNBZ0lDQWdJQ0J3Y205alpYTnpaV1JmZG1Gc2RXVWdQU0IwYUdseld5ZHdjbTlqWlhOelh5Y2dLeUJoZEhSeVhTaHdjbTlqWlhOelpXUmZkbUZzZFdVcE8xeHVJQ0FnSUNBZ2ZWeHVYRzRnSUNBZ0lDQndjbTlqWlhOelpXUmZkbUZzZFdWeklEMGdjSEp2WTJWemMyVmtYM1poYkhWbGN5NWpiMjVqWVhRb2NISnZZMlZ6YzJWa1gzWmhiSFZsS1R0Y2JpQWdJQ0I5WEc1Y2JpQWdJQ0J5WlhSMWNtNGdjSEp2WTJWemMyVmtYM1poYkhWbGN6dGNiaUFnZlZ4dVhHNGdJSEJ5YjJObGMzTmZhVzUwWldkbGNpaDJZV3gxWlNsN1hHNGdJQ0FnY21WMGRYSnVJSFpoYkhWbExuWmhiSFZsTzF4dUlDQjlYRzVjYmlBZ2NISnZZMlZ6YzE5bWJHOWhkQ2gyWVd4MVpTbDdYRzRnSUNBZ2FXWW9kbUZzZFdVdWMybDZaU0E5UFQwZ05qUXBlMXh1SUNBZ0lDQWdjbVYwZFhKdUlFSnBkRk4wY21sdVp5NW1iRzloZERZMFZHOUNlWFJsY3loMllXeDFaUzUyWVd4MVpTazdYRzRnSUNBZ2ZXVnNjMlVnYVdZb2RtRnNkV1V1YzJsNlpTQTlQVDBnTXpJcGUxeHVJQ0FnSUNBZ2NtVjBkWEp1SUVKcGRGTjBjbWx1Wnk1bWJHOWhkRE15Vkc5Q2VYUmxjeWgyWVd4MVpTNTJZV3gxWlNrN1hHNGdJQ0FnZlZ4dVhHNGdJQ0FnZEdoeWIzY2dibVYzSUVWeWNtOXlLQ2RKYm5aaGJHbGtJSE5wZW1VZ1ptOXlJR1pzYjJGMEp5azdYRzRnSUgxY2JseHVJQ0J3Y205alpYTnpYMkpwZEhOMGNtbHVaeWgyWVd4MVpTbDdYRzRnSUNBZ2NtVjBkWEp1SUhaaGJIVmxMblpoYkhWbExuWmhiSFZsTzF4dUlDQjlYRzVjYmlBZ2NISnZZMlZ6YzE5aWFXNWhjbmtvZG1Gc2RXVXBlMXh1SUNBZ0lISmxkSFZ5YmlCQ2FYUlRkSEpwYm1jdWRHOVZWRVk0UVhKeVlYa29kbUZzZFdVdWRtRnNkV1VwTzF4dUlDQjlYRzVjYmlBZ2NISnZZMlZ6YzE5MWRHWTRLSFpoYkhWbEtYdGNiaUFnSUNCeVpYUjFjbTRnUW1sMFUzUnlhVzVuTG5SdlZWUkdPRUZ5Y21GNUtIWmhiSFZsTG5aaGJIVmxLVHRjYmlBZ2ZWeHVYRzRnSUhCeWIyTmxjM05mZFhSbU1UWW9kbUZzZFdVcGUxeHVJQ0FnSUhKbGRIVnliaUJDYVhSVGRISnBibWN1ZEc5VlZFWXhOa0Z5Y21GNUtIWmhiSFZsTG5aaGJIVmxLVHRjYmlBZ2ZWeHVYRzRnSUhCeWIyTmxjM05mZFhSbU16SW9kbUZzZFdVcGUxeHVJQ0FnSUhKbGRIVnliaUJDYVhSVGRISnBibWN1ZEc5VlZFWXpNa0Z5Y21GNUtIWmhiSFZsTG5aaGJIVmxLVHRjYmlBZ2ZWeHVYRzRnSUhCeWIyTmxjM05mYzJsbmJtVmtLSFpoYkhWbEtYdGNiaUFnSUNCeVpYUjFjbTRnS0c1bGR5QlZhVzUwT0VGeWNtRjVLRnQyWVd4MVpWMHBLVnN3WFR0Y2JpQWdmVnh1WEc0Z0lIQnliMk5sYzNOZmRXNXphV2R1WldRb2RtRnNkV1VwZTF4dUlDQWdJSEpsZEhWeWJpQjJZV3gxWlR0Y2JpQWdmVnh1WEc0Z0lIQnliMk5sYzNOZmJtRjBhWFpsS0haaGJIVmxLWHRjYmlBZ0lDQnlaWFIxY200Z2RtRnNkV1U3WEc0Z0lIMWNibHh1SUNCd2NtOWpaWE56WDJKcFp5aDJZV3gxWlNsN1hHNGdJQ0FnY21WMGRYSnVJSFpoYkhWbE8xeHVJQ0I5WEc1Y2JpQWdjSEp2WTJWemMxOXNhWFIwYkdVb2RtRnNkV1VwZTF4dUlDQWdJSEpsZEhWeWJpQjJZV3gxWlM1eVpYWmxjbk5sS0NrN1hHNGdJSDFjYmx4dUlDQndjbTlqWlhOelgzTnBlbVVvZG1Gc2RXVXBlMXh1SUNBZ0lISmxkSFZ5YmlCMllXeDFaVHRjYmlBZ2ZWeHVYRzRnSUhCeWIyTmxjM05mZFc1cGRDaDJZV3gxWlNsN1hHNGdJQ0FnY21WMGRYSnVJSFpoYkhWbE8xeHVJQ0I5WEc1Y2JpQWdjM1JoZEdsaklHbHVkR1ZuWlhJb2RtRnNkV1VwZTF4dUlDQWdJSEpsZEhWeWJpQkNhWFJUZEhKcGJtY3VkM0poY0NoMllXeDFaU3dnZXlBbmRIbHdaU2M2SUNkcGJuUmxaMlZ5Snl3Z0ozVnVhWFFuT2lBeExDQW5jMmw2WlNjNklEZ2dmU2s3WEc0Z0lIMWNibHh1SUNCemRHRjBhV01nWm14dllYUW9kbUZzZFdVcGUxeHVJQ0FnSUhKbGRIVnliaUJDYVhSVGRISnBibWN1ZDNKaGNDaDJZV3gxWlN3Z2V5QW5kSGx3WlNjNklDZG1iRzloZENjc0lDZDFibWwwSnpvZ01Td2dKM05wZW1Vbk9pQTJOQ0I5S1R0Y2JpQWdmVnh1WEc0Z0lITjBZWFJwWXlCaWFYUnpkSEpwYm1jb2RtRnNkV1VwZTF4dUlDQWdJSEpsZEhWeWJpQkNhWFJUZEhKcGJtY3VkM0poY0NoMllXeDFaU3dnZXlBbmRIbHdaU2M2SUNkaWFYUnpkSEpwYm1jbkxDQW5kVzVwZENjNklERXNJQ2R6YVhwbEp6b2dkbUZzZFdVdVltbDBYM05wZW1VZ2ZTazdYRzRnSUgxY2JseHVJQ0J6ZEdGMGFXTWdZbWwwY3loMllXeDFaU2w3WEc0Z0lDQWdjbVYwZFhKdUlFSnBkRk4wY21sdVp5NWlhWFJ6ZEhKcGJtY29kbUZzZFdVcE8xeHVJQ0I5WEc1Y2JpQWdjM1JoZEdsaklHSnBibUZ5ZVNoMllXeDFaU2w3WEc0Z0lDQWdjbVYwZFhKdUlFSnBkRk4wY21sdVp5NTNjbUZ3S0haaGJIVmxMQ0I3SUNkMGVYQmxKem9nSjJKcGJtRnllU2NzSUNkMWJtbDBKem9nT0N3Z0ozTnBlbVVuT2lCMllXeDFaUzVzWlc1bmRHZ2dmU2s3WEc0Z0lIMWNibHh1SUNCemRHRjBhV01nWW5sMFpYTW9kbUZzZFdVcGUxeHVJQ0FnSUhKbGRIVnliaUJDYVhSVGRISnBibWN1WW1sdVlYSjVLSFpoYkhWbEtUdGNiaUFnZlZ4dVhHNGdJSE4wWVhScFl5QjFkR1k0S0haaGJIVmxLWHRjYmlBZ0lDQnlaWFIxY200Z1FtbDBVM1J5YVc1bkxuZHlZWEFvZG1Gc2RXVXNJSHNnSjNSNWNHVW5PaUFuZFhSbU9DY3NJQ2QxYm1sMEp6b2dNU3dnSjNOcGVtVW5PaUIyWVd4MVpTNXNaVzVuZEdnZ0lIMHBPMXh1SUNCOVhHNWNiaUFnYzNSaGRHbGpJSFYwWmpFMktIWmhiSFZsS1h0Y2JpQWdJQ0J5WlhSMWNtNGdRbWwwVTNSeWFXNW5MbmR5WVhBb2RtRnNkV1VzSUhzZ0ozUjVjR1VuT2lBbmRYUm1NVFluTENBbmRXNXBkQ2M2SURFc0lDZHphWHBsSnpvZ2RtRnNkV1V1YkdWdVozUm9JQ29nTWlCOUtUdGNiaUFnZlZ4dVhHNGdJSE4wWVhScFl5QjFkR1l6TWloMllXeDFaU2w3WEc0Z0lDQWdjbVYwZFhKdUlFSnBkRk4wY21sdVp5NTNjbUZ3S0haaGJIVmxMQ0I3SUNkMGVYQmxKem9nSjNWMFpqTXlKeXdnSjNWdWFYUW5PaUF4TENBbmMybDZaU2M2SUhaaGJIVmxMbXhsYm1kMGFDQXFJRFFnZlNrN1hHNGdJSDFjYmx4dUlDQnpkR0YwYVdNZ2MybG5ibVZrS0haaGJIVmxLWHRjYmlBZ0lDQnlaWFIxY200Z1FtbDBVM1J5YVc1bkxuZHlZWEFvZG1Gc2RXVXNJSHQ5TENBbmMybG5ibVZrSnlrN1hHNGdJSDFjYmx4dUlDQnpkR0YwYVdNZ2RXNXphV2R1WldRb2RtRnNkV1VwZTF4dUlDQWdJSEpsZEhWeWJpQkNhWFJUZEhKcGJtY3VkM0poY0NoMllXeDFaU3dnZTMwc0lDZDFibk5wWjI1bFpDY3BPMXh1SUNCOVhHNWNiaUFnYzNSaGRHbGpJRzVoZEdsMlpTaDJZV3gxWlNsN1hHNGdJQ0FnY21WMGRYSnVJRUpwZEZOMGNtbHVaeTUzY21Gd0tIWmhiSFZsTENCN2ZTd2dKMjVoZEdsMlpTY3BPMXh1SUNCOVhHNWNiaUFnYzNSaGRHbGpJR0pwWnloMllXeDFaU2w3WEc0Z0lDQWdjbVYwZFhKdUlFSnBkRk4wY21sdVp5NTNjbUZ3S0haaGJIVmxMQ0I3ZlN3Z0oySnBaeWNwTzF4dUlDQjlYRzVjYmlBZ2MzUmhkR2xqSUd4cGRIUnNaU2gyWVd4MVpTbDdYRzRnSUNBZ2NtVjBkWEp1SUVKcGRGTjBjbWx1Wnk1M2NtRndLSFpoYkhWbExDQjdmU3dnSjJ4cGRIUnNaU2NwTzF4dUlDQjlYRzVjYmlBZ2MzUmhkR2xqSUhOcGVtVW9kbUZzZFdVc0lHTnZkVzUwS1h0Y2JpQWdJQ0J5WlhSMWNtNGdRbWwwVTNSeWFXNW5MbmR5WVhBb2RtRnNkV1VzSUhzbmMybDZaU2M2SUdOdmRXNTBmU2s3WEc0Z0lIMWNibHh1SUNCemRHRjBhV01nZFc1cGRDaDJZV3gxWlN3Z1kyOTFiblFwZTF4dUlDQWdJSEpsZEhWeWJpQkNhWFJUZEhKcGJtY3VkM0poY0NoMllXeDFaU3dnZXlkMWJtbDBKem9nWTI5MWJuUjlLVHRjYmlBZ2ZWeHVYRzRnSUhOMFlYUnBZeUIzY21Gd0tIWmhiSFZsTENCdmNIUXNJRzVsZDE5aGRIUnlhV0oxZEdVZ1BTQnVkV3hzS1h0Y2JpQWdJQ0JzWlhRZ2RHaGxYM1poYkhWbElEMGdkbUZzZFdVN1hHNWNiaUFnSUNCcFppZ2hLSFpoYkhWbElHbHVjM1JoYm1ObGIyWWdUMkpxWldOMEtTbDdYRzRnSUNBZ0lDQjBhR1ZmZG1Gc2RXVWdQU0I3SjNaaGJIVmxKem9nZG1Gc2RXVXNJQ2RoZEhSeWFXSjFkR1Z6SnpvZ1cxMTlPMXh1SUNBZ0lIMWNibHh1SUNBZ0lIUm9aVjkyWVd4MVpTQTlJRTlpYW1WamRDNWhjM05wWjI0b2RHaGxYM1poYkhWbExDQnZjSFFwTzF4dVhHNGdJQ0FnYVdZb2JtVjNYMkYwZEhKcFluVjBaU2w3WEc0Z0lDQWdJQ0IwYUdWZmRtRnNkV1V1WVhSMGNtbGlkWFJsY3k1d2RYTm9LRzVsZDE5aGRIUnlhV0oxZEdVcE8xeHVJQ0FnSUgxY2JseHVYRzRnSUNBZ2NtVjBkWEp1SUhSb1pWOTJZV3gxWlR0Y2JpQWdmVnh1WEc0Z0lITjBZWFJwWXlCMGIxVlVSamhCY25KaGVTaHpkSElwSUh0Y2JpQWdJQ0IyWVhJZ2RYUm1PQ0E5SUZ0ZE8xeHVJQ0FnSUdadmNpQW9kbUZ5SUdrZ1BTQXdPeUJwSUR3Z2MzUnlMbXhsYm1kMGFEc2dhU3NyS1NCN1hHNGdJQ0FnSUNCMllYSWdZMmhoY21OdlpHVWdQU0J6ZEhJdVkyaGhja052WkdWQmRDaHBLVHRjYmlBZ0lDQWdJR2xtSUNoamFHRnlZMjlrWlNBOElEQjRPREFwZTF4dUlDQWdJQ0FnSUNCMWRHWTRMbkIxYzJnb1kyaGhjbU52WkdVcE8xeHVJQ0FnSUNBZ2ZWeHVJQ0FnSUNBZ1pXeHpaU0JwWmlBb1kyaGhjbU52WkdVZ1BDQXdlRGd3TUNrZ2UxeHVJQ0FnSUNBZ0lDQjFkR1k0TG5CMWMyZ29NSGhqTUNCOElDaGphR0Z5WTI5a1pTQStQaUEyS1N4Y2JpQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lEQjRPREFnZkNBb1kyaGhjbU52WkdVZ0ppQXdlRE5tS1NrN1hHNGdJQ0FnSUNCOVhHNGdJQ0FnSUNCbGJITmxJR2xtSUNoamFHRnlZMjlrWlNBOElEQjRaRGd3TUNCOGZDQmphR0Z5WTI5a1pTQStQU0F3ZUdVd01EQXBJSHRjYmlBZ0lDQWdJQ0FnZFhSbU9DNXdkWE5vS0RCNFpUQWdmQ0FvWTJoaGNtTnZaR1VnUGo0Z01USXBMRnh1SUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnTUhnNE1DQjhJQ2dvWTJoaGNtTnZaR1VnUGo0Z05pa2dKaUF3ZURObUtTeGNiaUFnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJREI0T0RBZ2ZDQW9ZMmhoY21OdlpHVWdKaUF3ZURObUtTazdYRzRnSUNBZ0lDQjlYRzRnSUNBZ0lDQXZMeUJ6ZFhKeWIyZGhkR1VnY0dGcGNseHVJQ0FnSUNBZ1pXeHpaU0I3WEc0Z0lDQWdJQ0FnSUdrckt6dGNiaUFnSUNBZ0lDQWdMeThnVlZSR0xURTJJR1Z1WTI5a1pYTWdNSGd4TURBd01DMHdlREV3UmtaR1JpQmllVnh1SUNBZ0lDQWdJQ0F2THlCemRXSjBjbUZqZEdsdVp5QXdlREV3TURBd0lHRnVaQ0J6Y0d4cGRIUnBibWNnZEdobFhHNGdJQ0FnSUNBZ0lDOHZJREl3SUdKcGRITWdiMllnTUhnd0xUQjRSa1pHUmtZZ2FXNTBieUIwZDI4Z2FHRnNkbVZ6WEc0Z0lDQWdJQ0FnSUdOb1lYSmpiMlJsSUQwZ01IZ3hNREF3TUNBcklDZ29LR05vWVhKamIyUmxJQ1lnTUhnelptWXBJRHc4SURFd0tWeHVJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdmQ0FvYzNSeUxtTm9ZWEpEYjJSbFFYUW9hU2tnSmlBd2VETm1aaWtwTzF4dUlDQWdJQ0FnSUNCMWRHWTRMbkIxYzJnb01IaG1NQ0I4SUNoamFHRnlZMjlrWlNBK1BpQXhPQ2tzWEc0Z0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBd2VEZ3dJSHdnS0NoamFHRnlZMjlrWlNBK1BpQXhNaWtnSmlBd2VETm1LU3hjYmlBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSURCNE9EQWdmQ0FvS0dOb1lYSmpiMlJsSUQ0K0lEWXBJQ1lnTUhnelppa3NYRzRnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0F3ZURnd0lId2dLR05vWVhKamIyUmxJQ1lnTUhnelppa3BPMXh1SUNBZ0lDQWdmVnh1SUNBZ0lIMWNiaUFnSUNCeVpYUjFjbTRnZFhSbU9EdGNiaUFnZlZ4dVhHNGdJSE4wWVhScFl5QjBiMVZVUmpFMlFYSnlZWGtvYzNSeUtTQjdYRzRnSUNBZ2RtRnlJSFYwWmpFMklEMGdXMTA3WEc0Z0lDQWdabTl5SUNoMllYSWdhU0E5SURBN0lHa2dQQ0J6ZEhJdWJHVnVaM1JvT3lCcEt5c3BJSHRjYmlBZ0lDQWdJSFpoY2lCamIyUmxVRzlwYm5RZ1BTQnpkSEl1WTI5a1pWQnZhVzUwUVhRb2FTazdYRzVjYmlBZ0lDQWdJR2xtS0dOdlpHVlFiMmx1ZENBOFBTQXlOVFVwZTF4dUlDQWdJQ0FnSUNCMWRHWXhOaTV3ZFhOb0tEQXBPMXh1SUNBZ0lDQWdJQ0IxZEdZeE5pNXdkWE5vS0dOdlpHVlFiMmx1ZENrN1hHNGdJQ0FnSUNCOVpXeHpaWHRjYmlBZ0lDQWdJQ0FnZFhSbU1UWXVjSFZ6YUNnb0tHTnZaR1ZRYjJsdWRDQStQaUE0S1NBbUlEQjRSa1lwS1R0Y2JpQWdJQ0FnSUNBZ2RYUm1NVFl1Y0hWemFDZ29ZMjlrWlZCdmFXNTBJQ1lnTUhoR1Jpa3BPMXh1SUNBZ0lDQWdmVnh1SUNBZ0lIMWNiaUFnSUNCeVpYUjFjbTRnZFhSbU1UWTdYRzRnSUgxY2JseHVYRzRnSUhOMFlYUnBZeUIwYjFWVVJqTXlRWEp5WVhrb2MzUnlLU0I3WEc0Z0lDQWdkbUZ5SUhWMFpqTXlJRDBnVzEwN1hHNGdJQ0FnWm05eUlDaDJZWElnYVNBOUlEQTdJR2tnUENCemRISXViR1Z1WjNSb095QnBLeXNwSUh0Y2JpQWdJQ0FnSUhaaGNpQmpiMlJsVUc5cGJuUWdQU0J6ZEhJdVkyOWtaVkJ2YVc1MFFYUW9hU2s3WEc1Y2JpQWdJQ0FnSUdsbUtHTnZaR1ZRYjJsdWRDQThQU0F5TlRVcGUxeHVJQ0FnSUNBZ0lDQjFkR1l6TWk1d2RYTm9LREFwTzF4dUlDQWdJQ0FnSUNCMWRHWXpNaTV3ZFhOb0tEQXBPMXh1SUNBZ0lDQWdJQ0IxZEdZek1pNXdkWE5vS0RBcE8xeHVJQ0FnSUNBZ0lDQjFkR1l6TWk1d2RYTm9LR052WkdWUWIybHVkQ2s3WEc0Z0lDQWdJQ0I5Wld4elpYdGNiaUFnSUNBZ0lDQWdkWFJtTXpJdWNIVnphQ2d3S1R0Y2JpQWdJQ0FnSUNBZ2RYUm1Nekl1Y0hWemFDZ3dLVHRjYmlBZ0lDQWdJQ0FnZFhSbU16SXVjSFZ6YUNnb0tHTnZaR1ZRYjJsdWRDQStQaUE0S1NBbUlEQjRSa1lwS1R0Y2JpQWdJQ0FnSUNBZ2RYUm1Nekl1Y0hWemFDZ29ZMjlrWlZCdmFXNTBJQ1lnTUhoR1Jpa3BPMXh1SUNBZ0lDQWdmVnh1SUNBZ0lIMWNiaUFnSUNCeVpYUjFjbTRnZFhSbU16STdYRzRnSUgxY2JseHVJQ0F2TDJoMGRIQTZMeTl6ZEdGamEyOTJaWEptYkc5M0xtTnZiUzl4ZFdWemRHbHZibk12TWpBd016UTVNeTlxWVhaaGMyTnlhWEIwTFdac2IyRjBMV1p5YjIwdGRHOHRZbWwwYzF4dUlDQnpkR0YwYVdNZ1pteHZZWFF6TWxSdlFubDBaWE1vWmlrZ2UxeHVJQ0FnSUhaaGNpQmllWFJsY3lBOUlGdGRPMXh1WEc0Z0lDQWdkbUZ5SUdKMVppQTlJRzVsZHlCQmNuSmhlVUoxWm1abGNpZzBLVHRjYmlBZ0lDQW9ibVYzSUVac2IyRjBNekpCY25KaGVTaGlkV1lwS1Zzd1hTQTlJR1k3WEc1Y2JpQWdJQ0JzWlhRZ2FXNTBWbVZ5YzJsdmJpQTlJQ2h1WlhjZ1ZXbHVkRE15UVhKeVlYa29ZblZtS1NsYk1GMDdYRzVjYmlBZ0lDQmllWFJsY3k1d2RYTm9LQ2dvYVc1MFZtVnljMmx2YmlBK1BpQXlOQ2tnSmlBd2VFWkdLU2s3WEc0Z0lDQWdZbmwwWlhNdWNIVnphQ2dvS0dsdWRGWmxjbk5wYjI0Z1BqNGdNVFlwSUNZZ01IaEdSaWtwTzF4dUlDQWdJR0o1ZEdWekxuQjFjMmdvS0NocGJuUldaWEp6YVc5dUlENCtJRGdwSUNZZ01IaEdSaWtwTzF4dUlDQWdJR0o1ZEdWekxuQjFjMmdvS0dsdWRGWmxjbk5wYjI0Z0ppQXdlRVpHS1NrN1hHNWNiaUFnSUNCeVpYUjFjbTRnWW5sMFpYTTdYRzRnSUgxY2JseHVJQ0J6ZEdGMGFXTWdabXh2WVhRMk5GUnZRbmwwWlhNb1ppa2dlMXh1SUNBZ0lIWmhjaUJpZVhSbGN5QTlJRnRkTzF4dVhHNGdJQ0FnZG1GeUlHSjFaaUE5SUc1bGR5QkJjbkpoZVVKMVptWmxjaWc0S1R0Y2JpQWdJQ0FvYm1WM0lFWnNiMkYwTmpSQmNuSmhlU2hpZFdZcEtWc3dYU0E5SUdZN1hHNWNiaUFnSUNCMllYSWdhVzUwVm1WeWMybHZiakVnUFNBb2JtVjNJRlZwYm5Rek1rRnljbUY1S0dKMVppa3BXekJkTzF4dUlDQWdJSFpoY2lCcGJuUldaWEp6YVc5dU1pQTlJQ2h1WlhjZ1ZXbHVkRE15UVhKeVlYa29ZblZtS1NsYk1WMDdYRzVjYmlBZ0lDQmllWFJsY3k1d2RYTm9LQ2dvYVc1MFZtVnljMmx2YmpJZ1BqNGdNalFwSUNZZ01IaEdSaWtwTzF4dUlDQWdJR0o1ZEdWekxuQjFjMmdvS0NocGJuUldaWEp6YVc5dU1pQStQaUF4TmlrZ0ppQXdlRVpHS1NrN1hHNGdJQ0FnWW5sMFpYTXVjSFZ6YUNnb0tHbHVkRlpsY25OcGIyNHlJRDQrSURncElDWWdNSGhHUmlrcE8xeHVJQ0FnSUdKNWRHVnpMbkIxYzJnb0tHbHVkRlpsY25OcGIyNHlJQ1lnTUhoR1Jpa3BPMXh1WEc0Z0lDQWdZbmwwWlhNdWNIVnphQ2dvS0dsdWRGWmxjbk5wYjI0eElENCtJREkwS1NBbUlEQjRSa1lwS1R0Y2JpQWdJQ0JpZVhSbGN5NXdkWE5vS0Nnb2FXNTBWbVZ5YzJsdmJqRWdQajRnTVRZcElDWWdNSGhHUmlrcE8xeHVJQ0FnSUdKNWRHVnpMbkIxYzJnb0tDaHBiblJXWlhKemFXOXVNU0ErUGlBNEtTQW1JREI0UmtZcEtUdGNiaUFnSUNCaWVYUmxjeTV3ZFhOb0tDaHBiblJXWlhKemFXOXVNU0FtSURCNFJrWXBLVHRjYmx4dUlDQWdJSEpsZEhWeWJpQmllWFJsY3p0Y2JpQWdmVnh1ZlZ4dVhHNWxlSEJ2Y25RZ1pHVm1ZWFZzZENCQ2FYUlRkSEpwYm1jN1hHNGlYU3dpYzI5MWNtTmxVbTl2ZENJNklpOXpiM1Z5WTJVdkluMD1cbiIsIlxuZXhwb3J0IGNsYXNzIFZhcmlhYmxlIHtcblxuICBjb25zdHJ1Y3RvcihkZWZhdWx0X3ZhbHVlID0gU3ltYm9sLmZvcihcImVsaXhpcnNjcmlwdC5ub192YWx1ZVwiKSkge1xuICAgIHRoaXMuZGVmYXVsdF92YWx1ZSA9IGRlZmF1bHRfdmFsdWU7XG4gIH1cbn1cblxuZXhwb3J0IGNsYXNzIFdpbGRjYXJkIHtcbiAgY29uc3RydWN0b3IoKSB7fVxufVxuXG5leHBvcnQgY2xhc3MgU3RhcnRzV2l0aCB7XG5cbiAgY29uc3RydWN0b3IocHJlZml4KSB7XG4gICAgdGhpcy5wcmVmaXggPSBwcmVmaXg7XG4gIH1cbn1cblxuZXhwb3J0IGNsYXNzIENhcHR1cmUge1xuXG4gIGNvbnN0cnVjdG9yKHZhbHVlKSB7XG4gICAgdGhpcy52YWx1ZSA9IHZhbHVlO1xuICB9XG59XG5cbmV4cG9ydCBjbGFzcyBIZWFkVGFpbCB7XG5cbiAgY29uc3RydWN0b3IoaGVhZCA9IG51bGwsIHRhaWwgPSBudWxsKSB7XG4gICAgdGhpcy5oZWFkID0gaGVhZDtcbiAgICB0aGlzLnRhaWwgPSB0YWlsO1xuICB9XG59XG5cbmV4cG9ydCBjbGFzcyBUeXBlIHtcblxuICBjb25zdHJ1Y3Rvcih0eXBlLCBvYmpQYXR0ZXJuID0ge30pIHtcbiAgICB0aGlzLnR5cGUgPSB0eXBlO1xuICAgIHRoaXMub2JqUGF0dGVybiA9IG9ialBhdHRlcm47XG4gIH1cbn1cblxuZXhwb3J0IGNsYXNzIEJvdW5kIHtcblxuICBjb25zdHJ1Y3Rvcih2YWx1ZSkge1xuICAgIHRoaXMudmFsdWUgPSB2YWx1ZTtcbiAgfVxufVxuXG5leHBvcnQgY2xhc3MgQml0U3RyaW5nTWF0Y2gge1xuXG4gIGNvbnN0cnVjdG9yKC4uLnZhbHVlcykge1xuICAgIHRoaXMudmFsdWVzID0gdmFsdWVzO1xuICB9XG5cbiAgbGVuZ3RoKCkge1xuICAgIHJldHVybiB2YWx1ZXMubGVuZ3RoO1xuICB9XG5cbiAgYml0X3NpemUoKSB7XG4gICAgcmV0dXJuIHRoaXMuYnl0ZV9zaXplKCkgKiA4O1xuICB9XG5cbiAgYnl0ZV9zaXplKCkge1xuICAgIGxldCBzID0gMDtcblxuICAgIGZvciAobGV0IHZhbCBvZiB0aGlzLnZhbHVlcykge1xuICAgICAgcyA9IHMgKyB2YWwudW5pdCAqIHZhbC5zaXplIC8gODtcbiAgICB9XG5cbiAgICByZXR1cm4gcztcbiAgfVxuXG4gIGdldFZhbHVlKGluZGV4KSB7XG4gICAgcmV0dXJuIHRoaXMudmFsdWVzKGluZGV4KTtcbiAgfVxuXG4gIGdldFNpemVPZlZhbHVlKGluZGV4KSB7XG4gICAgbGV0IHZhbCA9IHRoaXMuZ2V0VmFsdWUoaW5kZXgpO1xuICAgIHJldHVybiB2YWwudW5pdCAqIHZhbC5zaXplO1xuICB9XG5cbiAgZ2V0VHlwZU9mVmFsdWUoaW5kZXgpIHtcbiAgICByZXR1cm4gdGhpcy5nZXRWYWx1ZShpbmRleCkudHlwZTtcbiAgfVxufVxuXG5leHBvcnQgZnVuY3Rpb24gdmFyaWFibGUoZGVmYXVsdF92YWx1ZSA9IFN5bWJvbC5mb3IoXCJlbGl4aXJzY3JpcHQubm9fdmFsdWVcIikpIHtcbiAgcmV0dXJuIG5ldyBWYXJpYWJsZShkZWZhdWx0X3ZhbHVlKTtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIHdpbGRjYXJkKCkge1xuICByZXR1cm4gbmV3IFdpbGRjYXJkKCk7XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBzdGFydHNXaXRoKHByZWZpeCkge1xuICByZXR1cm4gbmV3IFN0YXJ0c1dpdGgocHJlZml4KTtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIGNhcHR1cmUodmFsdWUpIHtcbiAgcmV0dXJuIG5ldyBDYXB0dXJlKHZhbHVlKTtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIGhlYWRUYWlsKGhlYWQgPSBudWxsLCB0YWlsID0gbnVsbCkge1xuICByZXR1cm4gbmV3IEhlYWRUYWlsKGhlYWQsIHRhaWwpO1xufVxuXG5leHBvcnQgZnVuY3Rpb24gdHlwZSh0eXBlLCBvYmpQYXR0ZXJuID0ge30pIHtcbiAgcmV0dXJuIG5ldyBUeXBlKHR5cGUsIG9ialBhdHRlcm4pO1xufVxuXG5leHBvcnQgZnVuY3Rpb24gYm91bmQodmFsdWUpIHtcbiAgcmV0dXJuIG5ldyBCb3VuZCh2YWx1ZSk7XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBiaXRTdHJpbmdNYXRjaCguLi52YWx1ZXMpIHtcbiAgcmV0dXJuIG5ldyBCaXRTdHJpbmdNYXRjaCguLi52YWx1ZXMpO1xufVxuLy8jIHNvdXJjZU1hcHBpbmdVUkw9ZGF0YTphcHBsaWNhdGlvbi9qc29uO2Jhc2U2NCxleUoyWlhKemFXOXVJam96TENKemIzVnlZMlZ6SWpwYklteHBZaTlqYjNKbEwzQmhkSFJsY201ekwzUjVjR1Z6TG1weklsMHNJbTVoYldWeklqcGJYU3dpYldGd2NHbHVaM01pT2lJN1FVRkRRU3hQUVVGUExFMUJRVTBzVVVGQlRpeERRVUZsT3p0QlFVZHdRaXhqUVVGblF5eG5Ra0ZCUlN4UFFVRlBMRWRCUVZBc1EwRkJWeXgxUWtGQldDeERRVUZHTEVWQlFYVkRPMEZCUTNKRkxGTkJRVXNzWVVGQlRDeEhRVUZ4UWl4aFFVRnlRaXhEUVVSeFJUdEhRVUYyUlR0RFFVaExPenRCUVZGUUxFOUJRVThzVFVGQlRTeFJRVUZPTEVOQlFXVTdRVUZEY0VJc1owSkJRV01zUlVGQlpEdERRVVJMT3p0QlFVdFFMRTlCUVU4c1RVRkJUU3hWUVVGT0xFTkJRV2xDT3p0QlFVZDBRaXhqUVVGWkxFMUJRVm9zUlVGQk5FSTdRVUZETVVJc1UwRkJTeXhOUVVGTUxFZEJRV01zVFVGQlpDeERRVVF3UWp0SFFVRTFRanREUVVoTE96dEJRVkZRTEU5QlFVOHNUVUZCVFN4UFFVRk9MRU5CUVdNN08wRkJSMjVDTEdOQlFWa3NTMEZCV2l4RlFVRjNRanRCUVVOMFFpeFRRVUZMTEV0QlFVd3NSMEZCWVN4TFFVRmlMRU5CUkhOQ08wZEJRWGhDTzBOQlNFczdPMEZCVVZBc1QwRkJUeXhOUVVGTkxGRkJRVTRzUTBGQlpUczdRVUZKY0VJc1kwRkJjMElzVDBGQlJTeEpRVUZHTEVWQlFXdENMRTlCUVVVc1NVRkJSaXhGUVVGUk8wRkJRemxETEZOQlFVc3NTVUZCVEN4SFFVRlpMRWxCUVZvc1EwRkVPRU03UVVGRk9VTXNVMEZCU3l4SlFVRk1MRWRCUVZrc1NVRkJXaXhEUVVZNFF6dEhRVUZvUkR0RFFVcExPenRCUVZWUUxFOUJRVThzVFVGQlRTeEpRVUZPTEVOQlFWYzdPMEZCU1doQ0xHTkJRVmtzU1VGQldpeEZRVUV3UXl4aFFVRkZMRVZCUVVZc1JVRkJUVHRCUVVNNVF5eFRRVUZMTEVsQlFVd3NSMEZCV1N4SlFVRmFMRU5CUkRoRE8wRkJSVGxETEZOQlFVc3NWVUZCVEN4SFFVRnJRaXhWUVVGc1FpeERRVVk0UXp0SFFVRm9SRHREUVVwTE96dEJRVlZRTEU5QlFVOHNUVUZCVFN4TFFVRk9MRU5CUVZrN08wRkJSMnBDTEdOQlFWa3NTMEZCV2l4RlFVRjNRanRCUVVOMFFpeFRRVUZMTEV0QlFVd3NSMEZCWVN4TFFVRmlMRU5CUkhOQ08wZEJRWGhDTzBOQlNFczdPMEZCVVZBc1QwRkJUeXhOUVVGTkxHTkJRVTRzUTBGQmNVSTdPMEZCUnpGQ0xHTkJRVmtzUjBGQlJ5eE5RVUZJTEVWQlFYbENPMEZCUTI1RExGTkJRVXNzVFVGQlRDeEhRVUZqTEUxQlFXUXNRMEZFYlVNN1IwRkJja003TzBGQlNVRXNWMEZCVXp0QlFVTlFMRmRCUVU4c1QwRkJUeXhOUVVGUUxFTkJSRUU3UjBGQlZEczdRVUZKUVN4aFFVRlhPMEZCUTFRc1YwRkJUeXhMUVVGTExGTkJRVXdzUzBGQmJVSXNRMEZCYmtJc1EwRkVSVHRIUVVGWU96dEJRVWxCTEdOQlFWYzdRVUZEVkN4UlFVRkpMRWxCUVVrc1EwRkJTaXhEUVVSTE96dEJRVWRVTEZOQlFVa3NTVUZCU1N4SFFVRktMRWxCUVZjc1MwRkJTeXhOUVVGTUxFVkJRVms3UVVGRGVrSXNWVUZCU1N4SlFVRkxMRWRCUVVNc1EwRkJTU3hKUVVGS0xFZEJRVmNzU1VGQlNTeEpRVUZLTEVkQlFWVXNRMEZCZEVJc1EwRkVaMEk3UzBGQk0wSTdPMEZCU1VFc1YwRkJUeXhEUVVGUUxFTkJVRk03UjBGQldEczdRVUZWUVN4WFFVRlRMRXRCUVZRc1JVRkJaVHRCUVVOaUxGZEJRVThzUzBGQlN5eE5RVUZNTEVOQlFWa3NTMEZCV2l4RFFVRlFMRU5CUkdFN1IwRkJaanM3UVVGSlFTeHBRa0ZCWlN4TFFVRm1MRVZCUVhGQ08wRkJRMjVDTEZGQlFVa3NUVUZCVFN4TFFVRkxMRkZCUVV3c1EwRkJZeXhMUVVGa0xFTkJRVTRzUTBGRVpUdEJRVVZ1UWl4WFFVRlBMRWxCUVVrc1NVRkJTaXhIUVVGWExFbEJRVWtzU1VGQlNpeERRVVpETzBkQlFYSkNPenRCUVV0QkxHbENRVUZsTEV0QlFXWXNSVUZCY1VJN1FVRkRia0lzVjBGQlR5eExRVUZMTEZGQlFVd3NRMEZCWXl4TFFVRmtMRVZCUVhGQ0xFbEJRWEpDTEVOQlJGazdSMEZCY2tJN1EwRnNRMHM3TzBGQmRVTlFMRTlCUVU4c1UwRkJVeXhSUVVGVUxFTkJRWE5ETEdkQ1FVRkZMRTlCUVU4c1IwRkJVQ3hEUVVGWExIVkNRVUZZTEVOQlFVWXNSVUZCYVVRN1FVRkROVVlzVTBGQlR5eEpRVUZKTEZGQlFVb3NRMEZCWVN4aFFVRmlMRU5CUVZBc1EwRkVORVk3UTBGQmRrWTdPMEZCU1ZBc1QwRkJUeXhUUVVGVExGRkJRVlFzUjBGQk9FSTdRVUZEYmtNc1UwRkJUeXhKUVVGSkxGRkJRVW9zUlVGQlVDeERRVVJ0UXp0RFFVRTVRanM3UVVGSlVDeFBRVUZQTEZOQlFWTXNWVUZCVkN4RFFVRnZRaXhOUVVGd1FpeEZRVUZuUkR0QlFVTnlSQ3hUUVVGUExFbEJRVWtzVlVGQlNpeERRVUZsTEUxQlFXWXNRMEZCVUN4RFFVUnhSRHREUVVGb1JEczdRVUZKVUN4UFFVRlBMRk5CUVZNc1QwRkJWQ3hEUVVGcFFpeExRVUZxUWl4RlFVRnpRenRCUVVNelF5eFRRVUZQTEVsQlFVa3NUMEZCU2l4RFFVRlpMRXRCUVZvc1EwRkJVQ3hEUVVReVF6dERRVUYwUXpzN1FVRkpVQ3hQUVVGUExGTkJRVk1zVVVGQlZDeERRVUUwUWl4UFFVRkZMRWxCUVVZc1JVRkJhMElzVDBGQlJTeEpRVUZHTEVWQlFXdENPMEZCUTNKRkxGTkJRVThzU1VGQlNTeFJRVUZLTEVOQlFXRXNTVUZCWWl4RlFVRnRRaXhKUVVGdVFpeERRVUZRTEVOQlJIRkZPME5CUVdoRk96dEJRVWxRTEU5QlFVOHNVMEZCVXl4SlFVRlVMRU5CUVdNc1NVRkJaQ3hGUVVFMFF5eGhRVUZGTEVWQlFVWXNSVUZCV1R0QlFVTTNSQ3hUUVVGUExFbEJRVWtzU1VGQlNpeERRVUZUTEVsQlFWUXNSVUZCWlN4VlFVRm1MRU5CUVZBc1EwRkVOa1E3UTBGQmVFUTdPMEZCU1ZBc1QwRkJUeXhUUVVGVExFdEJRVlFzUTBGQlpTeExRVUZtTEVWQlFXdERPMEZCUTNaRExGTkJRVThzU1VGQlNTeExRVUZLTEVOQlFWVXNTMEZCVml4RFFVRlFMRU5CUkhWRE8wTkJRV3hET3p0QlFVbFFMRTlCUVU4c1UwRkJVeXhqUVVGVUxFTkJRWGRDTEVkQlFVY3NUVUZCU0N4RlFVRjVRanRCUVVOMFJDeFRRVUZQTEVsQlFVa3NZMEZCU2l4RFFVRnRRaXhIUVVGSExFMUJRVWdzUTBGQk1VSXNRMEZFYzBRN1EwRkJha1FpTENKbWFXeGxJam9pYkdsaUwyTnZjbVV2Y0dGMGRHVnlibk12ZEhsd1pYTXVhbk1pTENKemIzVnlZMlZ6UTI5dWRHVnVkQ0k2V3lJdktpQkFabXh2ZHlBcUwxeHVaWGh3YjNKMElHTnNZWE56SUZaaGNtbGhZbXhsSUh0Y2JpQWdaR1ZtWVhWc2RGOTJZV3gxWlRvZ1AyRnVlVHRjYmx4dUlDQmpiMjV6ZEhKMVkzUnZjaWhrWldaaGRXeDBYM1poYkhWbE9pQS9ZVzU1SUQwZ1UzbHRZbTlzTG1admNpaGNJbVZzYVhocGNuTmpjbWx3ZEM1dWIxOTJZV3gxWlZ3aUtTa2dlMXh1SUNBZ0lIUm9hWE11WkdWbVlYVnNkRjkyWVd4MVpTQTlJR1JsWm1GMWJIUmZkbUZzZFdVN1hHNGdJSDFjYm4xY2JseHVaWGh3YjNKMElHTnNZWE56SUZkcGJHUmpZWEprSUh0Y2JpQWdZMjl1YzNSeWRXTjBiM0lvS1NCN1hHNGdJSDFjYm4xY2JseHVaWGh3YjNKMElHTnNZWE56SUZOMFlYSjBjMWRwZEdnZ2UxeHVJQ0J3Y21WbWFYZzZJSE4wY21sdVp6dGNibHh1SUNCamIyNXpkSEoxWTNSdmNpaHdjbVZtYVhnNklITjBjbWx1WnlrZ2UxeHVJQ0FnSUhSb2FYTXVjSEpsWm1sNElEMGdjSEpsWm1sNE8xeHVJQ0I5WEc1OVhHNWNibVY0Y0c5eWRDQmpiR0Z6Y3lCRFlYQjBkWEpsSUh0Y2JpQWdkbUZzZFdVNklHRnVlVHRjYmx4dUlDQmpiMjV6ZEhKMVkzUnZjaWgyWVd4MVpUb2dZVzU1S1NCN1hHNGdJQ0FnZEdocGN5NTJZV3gxWlNBOUlIWmhiSFZsTzF4dUlDQjlYRzU5WEc1Y2JtVjRjRzl5ZENCamJHRnpjeUJJWldGa1ZHRnBiQ0I3WEc0Z0lHaGxZV1E2SUdGdWVUdGNiaUFnZEdGcGJEb2dZVzU1TzF4dVhHNGdJR052Ym5OMGNuVmpkRzl5S0dobFlXUTZJR0Z1ZVNBOUlHNTFiR3dzSUhSaGFXdzZJR0Z1ZVNBOUlHNTFiR3dwSUh0Y2JpQWdJQ0IwYUdsekxtaGxZV1FnUFNCb1pXRmtPMXh1SUNBZ0lIUm9hWE11ZEdGcGJDQTlJSFJoYVd3N1hHNGdJSDFjYm4xY2JseHVaWGh3YjNKMElHTnNZWE56SUZSNWNHVWdlMXh1SUNCMGVYQmxPaUJoYm5rN1hHNGdJRzlpYWxCaGRIUmxjbTQ2SUU5aWFtVmpkRHRjYmx4dUlDQmpiMjV6ZEhKMVkzUnZjaWgwZVhCbE9pQmhibmtzSUc5aWFsQmhkSFJsY200NklFOWlhbVZqZENBOUlIdDlLU0I3WEc0Z0lDQWdkR2hwY3k1MGVYQmxJRDBnZEhsd1pWeHVJQ0FnSUhSb2FYTXViMkpxVUdGMGRHVnliaUE5SUc5aWFsQmhkSFJsY201Y2JpQWdmVnh1ZlZ4dVhHNWxlSEJ2Y25RZ1kyeGhjM01nUW05MWJtUWdlMXh1SUNCMllXeDFaVG9nWVc1NU8xeHVYRzRnSUdOdmJuTjBjblZqZEc5eUtIWmhiSFZsT2lCaGJua3BJSHRjYmlBZ0lDQjBhR2x6TG5aaGJIVmxJRDBnZG1Gc2RXVTdYRzRnSUgxY2JuMWNibHh1Wlhod2IzSjBJR05zWVhOeklFSnBkRk4wY21sdVowMWhkR05vSUh0Y2JpQWdkbUZzZFdWek9pQkJjbkpoZVR4UFltcGxZM1ErWEc1Y2JpQWdZMjl1YzNSeWRXTjBiM0lvTGk0dWRtRnNkV1Z6T2lCQmNuSmhlVHhQWW1wbFkzUStLWHRjYmlBZ0lDQjBhR2x6TG5aaGJIVmxjeUE5SUhaaGJIVmxjenRjYmlBZ2ZWeHVYRzRnSUd4bGJtZDBhQ2dwSUh0Y2JpQWdJQ0J5WlhSMWNtNGdkbUZzZFdWekxteGxibWQwYUR0Y2JpQWdmVnh1WEc0Z0lHSnBkRjl6YVhwbEtDa2dlMXh1SUNBZ0lISmxkSFZ5YmlCMGFHbHpMbUo1ZEdWZmMybDZaU2dwSUNvZ09EdGNiaUFnZlZ4dVhHNGdJR0o1ZEdWZmMybDZaU2dwZTF4dUlDQWdJR3hsZENCeklEMGdNRHRjYmx4dUlDQWdJR1p2Y2loc1pYUWdkbUZzSUc5bUlIUm9hWE11ZG1Gc2RXVnpLWHRjYmlBZ0lDQWdJSE1nUFNCeklDc2dLQ2gyWVd3dWRXNXBkQ0FxSUhaaGJDNXphWHBsS1M4NEtUdGNiaUFnSUNCOVhHNWNiaUFnSUNCeVpYUjFjbTRnY3p0Y2JpQWdmVnh1WEc0Z0lHZGxkRlpoYkhWbEtHbHVaR1Y0S1h0Y2JpQWdJQ0J5WlhSMWNtNGdkR2hwY3k1MllXeDFaWE1vYVc1a1pYZ3BPMXh1SUNCOVhHNWNiaUFnWjJWMFUybDZaVTltVm1Gc2RXVW9hVzVrWlhncGUxeHVJQ0FnSUd4bGRDQjJZV3dnUFNCMGFHbHpMbWRsZEZaaGJIVmxLR2x1WkdWNEtUdGNiaUFnSUNCeVpYUjFjbTRnZG1Gc0xuVnVhWFFnS2lCMllXd3VjMmw2WlR0Y2JpQWdmVnh1WEc0Z0lHZGxkRlI1Y0dWUFpsWmhiSFZsS0dsdVpHVjRLWHRjYmlBZ0lDQnlaWFIxY200Z2RHaHBjeTVuWlhSV1lXeDFaU2hwYm1SbGVDa3VkSGx3WlR0Y2JpQWdmVnh1ZlZ4dVhHNWxlSEJ2Y25RZ1puVnVZM1JwYjI0Z2RtRnlhV0ZpYkdVb1pHVm1ZWFZzZEY5MllXeDFaVG9nUDJGdWVTQTlJRk41YldKdmJDNW1iM0lvWENKbGJHbDRhWEp6WTNKcGNIUXVibTlmZG1Gc2RXVmNJaWtwT2lCV1lYSnBZV0pzWlNCN1hHNGdJSEpsZEhWeWJpQnVaWGNnVm1GeWFXRmliR1VvWkdWbVlYVnNkRjkyWVd4MVpTazdYRzU5WEc1Y2JtVjRjRzl5ZENCbWRXNWpkR2x2YmlCM2FXeGtZMkZ5WkNncE9pQlhhV3hrWTJGeVpDQjdYRzRnSUhKbGRIVnliaUJ1WlhjZ1YybHNaR05oY21Rb0tUdGNibjFjYmx4dVpYaHdiM0owSUdaMWJtTjBhVzl1SUhOMFlYSjBjMWRwZEdnb2NISmxabWw0T2lCemRISnBibWNwT2lCVGRHRnlkSE5YYVhSb0lIdGNiaUFnY21WMGRYSnVJRzVsZHlCVGRHRnlkSE5YYVhSb0tIQnlaV1pwZUNrN1hHNTlYRzVjYm1WNGNHOXlkQ0JtZFc1amRHbHZiaUJqWVhCMGRYSmxLSFpoYkhWbE9pQmhibmtwT2lCRFlYQjBkWEpsSUh0Y2JpQWdjbVYwZFhKdUlHNWxkeUJEWVhCMGRYSmxLSFpoYkhWbEtUdGNibjFjYmx4dVpYaHdiM0owSUdaMWJtTjBhVzl1SUdobFlXUlVZV2xzS0dobFlXUTZJR0Z1ZVNBOUlHNTFiR3dzSUhSaGFXdzZJR0Z1ZVNBOUlHNTFiR3dwT2lCSVpXRmtWR0ZwYkNCN1hHNGdJSEpsZEhWeWJpQnVaWGNnU0dWaFpGUmhhV3dvYUdWaFpDd2dkR0ZwYkNrN1hHNTlYRzVjYm1WNGNHOXlkQ0JtZFc1amRHbHZiaUIwZVhCbEtIUjVjR1U2SUdGdWVTd2diMkpxVUdGMGRHVnliam9nVDJKcVpXTjBJRDBnZTMwcE9pQlVlWEJsSUh0Y2JpQWdjbVYwZFhKdUlHNWxkeUJVZVhCbEtIUjVjR1VzSUc5aWFsQmhkSFJsY200cE8xeHVmVnh1WEc1bGVIQnZjblFnWm5WdVkzUnBiMjRnWW05MWJtUW9kbUZzZFdVNklHRnVlU2s2SUVKdmRXNWtJSHRjYmlBZ2NtVjBkWEp1SUc1bGR5QkNiM1Z1WkNoMllXeDFaU2s3WEc1OVhHNWNibVY0Y0c5eWRDQm1kVzVqZEdsdmJpQmlhWFJUZEhKcGJtZE5ZWFJqYUNndUxpNTJZV3gxWlhNNklFRnljbUY1UEU5aWFtVmpkRDRwZTF4dUlDQnlaWFIxY200Z2JtVjNJRUpwZEZOMGNtbHVaMDFoZEdOb0tDNHVMblpoYkhWbGN5azdYRzU5WEc0aVhTd2ljMjkxY21ObFVtOXZkQ0k2SWk5emIzVnlZMlV2SW4wPVxuIiwiXG5cbmltcG9ydCB7IFZhcmlhYmxlLCBXaWxkY2FyZCwgSGVhZFRhaWwsIENhcHR1cmUsIFR5cGUsIFN0YXJ0c1dpdGgsIEJvdW5kLCBCaXRTdHJpbmdNYXRjaCB9IGZyb20gXCIuL3R5cGVzXCI7XG5cbmZ1bmN0aW9uIGlzX251bWJlcih2YWx1ZSkge1xuICByZXR1cm4gdHlwZW9mIHZhbHVlID09PSAnbnVtYmVyJztcbn1cblxuZnVuY3Rpb24gaXNfc3RyaW5nKHZhbHVlKSB7XG4gIHJldHVybiB0eXBlb2YgdmFsdWUgPT09ICdzdHJpbmcnO1xufVxuXG5mdW5jdGlvbiBpc19ib29sZWFuKHZhbHVlKSB7XG4gIHJldHVybiB0eXBlb2YgdmFsdWUgPT09ICdib29sZWFuJztcbn1cblxuZnVuY3Rpb24gaXNfc3ltYm9sKHZhbHVlKSB7XG4gIHJldHVybiB0eXBlb2YgdmFsdWUgPT09ICdzeW1ib2wnO1xufVxuXG5mdW5jdGlvbiBpc19udWxsKHZhbHVlKSB7XG4gIHJldHVybiB2YWx1ZSA9PT0gbnVsbDtcbn1cblxuZnVuY3Rpb24gaXNfdW5kZWZpbmVkKHZhbHVlKSB7XG4gIHJldHVybiB0eXBlb2YgdmFsdWUgPT09ICd1bmRlZmluZWQnO1xufVxuXG5mdW5jdGlvbiBpc19mdW5jdGlvbih2YWx1ZSkge1xuICByZXR1cm4gT2JqZWN0LnByb3RvdHlwZS50b1N0cmluZy5jYWxsKHZhbHVlKSA9PSAnW29iamVjdCBGdW5jdGlvbl0nO1xufVxuXG5mdW5jdGlvbiBpc192YXJpYWJsZSh2YWx1ZSkge1xuICByZXR1cm4gdmFsdWUgaW5zdGFuY2VvZiBWYXJpYWJsZTtcbn1cblxuZnVuY3Rpb24gaXNfd2lsZGNhcmQodmFsdWUpIHtcbiAgcmV0dXJuIHZhbHVlIGluc3RhbmNlb2YgV2lsZGNhcmQ7XG59XG5cbmZ1bmN0aW9uIGlzX2hlYWRUYWlsKHZhbHVlKSB7XG4gIHJldHVybiB2YWx1ZSBpbnN0YW5jZW9mIEhlYWRUYWlsO1xufVxuXG5mdW5jdGlvbiBpc19jYXB0dXJlKHZhbHVlKSB7XG4gIHJldHVybiB2YWx1ZSBpbnN0YW5jZW9mIENhcHR1cmU7XG59XG5cbmZ1bmN0aW9uIGlzX3R5cGUodmFsdWUpIHtcbiAgcmV0dXJuIHZhbHVlIGluc3RhbmNlb2YgVHlwZTtcbn1cblxuZnVuY3Rpb24gaXNfc3RhcnRzV2l0aCh2YWx1ZSkge1xuICByZXR1cm4gdmFsdWUgaW5zdGFuY2VvZiBTdGFydHNXaXRoO1xufVxuXG5mdW5jdGlvbiBpc19ib3VuZCh2YWx1ZSkge1xuICByZXR1cm4gdmFsdWUgaW5zdGFuY2VvZiBCb3VuZDtcbn1cblxuZnVuY3Rpb24gaXNfb2JqZWN0KHZhbHVlKSB7XG4gIHJldHVybiB0eXBlb2YgdmFsdWUgPT09ICdvYmplY3QnO1xufVxuXG5mdW5jdGlvbiBpc19hcnJheSh2YWx1ZSkge1xuICByZXR1cm4gQXJyYXkuaXNBcnJheSh2YWx1ZSk7XG59XG5cbmZ1bmN0aW9uIGlzX2JpdHN0cmluZyh2YWx1ZSkge1xuICByZXR1cm4gdmFsdWUgaW5zdGFuY2VvZiBCaXRTdHJpbmdNYXRjaDtcbn1cblxuZXhwb3J0IGRlZmF1bHQge1xuICBpc19udW1iZXIsXG4gIGlzX3N0cmluZyxcbiAgaXNfYm9vbGVhbixcbiAgaXNfc3ltYm9sLFxuICBpc19udWxsLFxuICBpc191bmRlZmluZWQsXG4gIGlzX2Z1bmN0aW9uLFxuICBpc192YXJpYWJsZSxcbiAgaXNfd2lsZGNhcmQsXG4gIGlzX2hlYWRUYWlsLFxuICBpc19jYXB0dXJlLFxuICBpc190eXBlLFxuICBpc19zdGFydHNXaXRoLFxuICBpc19ib3VuZCxcbiAgaXNfb2JqZWN0LFxuICBpc19hcnJheSxcbiAgaXNfYml0c3RyaW5nXG59O1xuLy8jIHNvdXJjZU1hcHBpbmdVUkw9ZGF0YTphcHBsaWNhdGlvbi9qc29uO2Jhc2U2NCxleUoyWlhKemFXOXVJam96TENKemIzVnlZMlZ6SWpwYklteHBZaTlqYjNKbEwzQmhkSFJsY201ekwyTm9aV05yY3k1cWN5SmRMQ0p1WVcxbGN5STZXMTBzSW0xaGNIQnBibWR6SWpvaU96dEJRVVZCTEZOQlFWTXNVVUZCVkN4RlFVRnRRaXhSUVVGdVFpeEZRVUUyUWl4UlFVRTNRaXhGUVVGMVF5eFBRVUYyUXl4RlFVRm5SQ3hKUVVGb1JDeEZRVUZ6UkN4VlFVRjBSQ3hGUVVGclJTeExRVUZzUlN4RlFVRjVSU3hqUVVGNlJTeFJRVUVyUml4VFFVRXZSanM3UVVGRlFTeFRRVUZUTEZOQlFWUXNRMEZCYlVJc1MwRkJia0lzUlVGQmQwTTdRVUZEZEVNc1UwRkJUeXhQUVVGUExFdEJRVkFzUzBGQmFVSXNVVUZCYWtJc1EwRkVLMEk3UTBGQmVFTTdPMEZCU1VFc1UwRkJVeXhUUVVGVUxFTkJRVzFDTEV0QlFXNUNMRVZCUVhWRE8wRkJRM0pETEZOQlFVOHNUMEZCVHl4TFFVRlFMRXRCUVdsQ0xGRkJRV3BDTEVOQlJEaENPME5CUVhaRE96dEJRVWxCTEZOQlFWTXNWVUZCVkN4RFFVRnZRaXhMUVVGd1FpeEZRVUY1UXp0QlFVTjJReXhUUVVGUExFOUJRVThzUzBGQlVDeExRVUZwUWl4VFFVRnFRaXhEUVVSblF6dERRVUY2UXpzN1FVRkpRU3hUUVVGVExGTkJRVlFzUTBGQmJVSXNTMEZCYmtJc1JVRkJkME03UVVGRGRFTXNVMEZCVHl4UFFVRlBMRXRCUVZBc1MwRkJhVUlzVVVGQmFrSXNRMEZFSzBJN1EwRkJlRU03TzBGQlNVRXNVMEZCVXl4UFFVRlVMRU5CUVdsQ0xFdEJRV3BDTEVWQlFYTkRPMEZCUTNCRExGTkJRVThzVlVGQlZTeEpRVUZXTEVOQlJEWkNPME5CUVhSRE96dEJRVWxCTEZOQlFWTXNXVUZCVkN4RFFVRnpRaXhMUVVGMFFpeEZRVUV5UXp0QlFVTjZReXhUUVVGUExFOUJRVThzUzBGQlVDeExRVUZwUWl4WFFVRnFRaXhEUVVSclF6dERRVUV6UXpzN1FVRkpRU3hUUVVGVExGZEJRVlFzUTBGQmNVSXNTMEZCY2tJc1JVRkJNRU03UVVGRGVFTXNVMEZCVHl4UFFVRlBMRk5CUVZBc1EwRkJhVUlzVVVGQmFrSXNRMEZCTUVJc1NVRkJNVUlzUTBGQkswSXNTMEZCTDBJc1MwRkJlVU1zYlVKQlFYcERMRU5CUkdsRE8wTkJRVEZET3p0QlFVbEJMRk5CUVZNc1YwRkJWQ3hEUVVGeFFpeExRVUZ5UWl4RlFVRXdRenRCUVVONFF5eFRRVUZQTEdsQ1FVRnBRaXhSUVVGcVFpeERRVVJwUXp0RFFVRXhRenM3UVVGSlFTeFRRVUZUTEZkQlFWUXNRMEZCY1VJc1MwRkJja0lzUlVGQk1FTTdRVUZEZUVNc1UwRkJUeXhwUWtGQmFVSXNVVUZCYWtJc1EwRkVhVU03UTBGQk1VTTdPMEZCU1VFc1UwRkJVeXhYUVVGVUxFTkJRWEZDTEV0QlFYSkNMRVZCUVRCRE8wRkJRM2hETEZOQlFVOHNhVUpCUVdsQ0xGRkJRV3BDTEVOQlJHbERPME5CUVRGRE96dEJRVWxCTEZOQlFWTXNWVUZCVkN4RFFVRnZRaXhMUVVGd1FpeEZRVUY1UXp0QlFVTjJReXhUUVVGUExHbENRVUZwUWl4UFFVRnFRaXhEUVVSblF6dERRVUY2UXpzN1FVRkpRU3hUUVVGVExFOUJRVlFzUTBGQmFVSXNTMEZCYWtJc1JVRkJjME03UVVGRGNFTXNVMEZCVHl4cFFrRkJhVUlzU1VGQmFrSXNRMEZFTmtJN1EwRkJkRU03TzBGQlNVRXNVMEZCVXl4aFFVRlVMRU5CUVhWQ0xFdEJRWFpDTEVWQlFUUkRPMEZCUXpGRExGTkJRVThzYVVKQlFXbENMRlZCUVdwQ0xFTkJSRzFETzBOQlFUVkRPenRCUVVsQkxGTkJRVk1zVVVGQlZDeERRVUZyUWl4TFFVRnNRaXhGUVVGMVF6dEJRVU55UXl4VFFVRlBMR2xDUVVGcFFpeExRVUZxUWl4RFFVUTRRanREUVVGMlF6czdRVUZKUVN4VFFVRlRMRk5CUVZRc1EwRkJiVUlzUzBGQmJrSXNSVUZCZDBNN1FVRkRkRU1zVTBGQlR5eFBRVUZQTEV0QlFWQXNTMEZCYVVJc1VVRkJha0lzUTBGRUswSTdRMEZCZUVNN08wRkJTVUVzVTBGQlV5eFJRVUZVTEVOQlFXdENMRXRCUVd4Q0xFVkJRWFZETzBGQlEzSkRMRk5CUVU4c1RVRkJUU3hQUVVGT0xFTkJRV01zUzBGQlpDeERRVUZRTEVOQlJIRkRPME5CUVhaRE96dEJRVWxCTEZOQlFWTXNXVUZCVkN4RFFVRnpRaXhMUVVGMFFpeEZRVUV5UXp0QlFVTjZReXhUUVVGUExHbENRVUZwUWl4alFVRnFRaXhEUVVSclF6dERRVUV6UXpzN1FVRkxRU3hsUVVGbE8wRkJRMklzVjBGRVlUdEJRVVZpTEZkQlJtRTdRVUZIWWl4WlFVaGhPMEZCU1dJc1YwRktZVHRCUVV0aUxGTkJUR0U3UVVGTllpeGpRVTVoTzBGQlQySXNZVUZRWVR0QlFWRmlMR0ZCVW1FN1FVRlRZaXhoUVZSaE8wRkJWV0lzWVVGV1lUdEJRVmRpTEZsQldHRTdRVUZaWWl4VFFWcGhPMEZCWVdJc1pVRmlZVHRCUVdOaUxGVkJaR0U3UVVGbFlpeFhRV1poTzBGQlowSmlMRlZCYUVKaE8wRkJhVUppTEdOQmFrSmhPME5CUVdZaUxDSm1hV3hsSWpvaWJHbGlMMk52Y21VdmNHRjBkR1Z5Ym5NdlkyaGxZMnR6TG1weklpd2ljMjkxY21ObGMwTnZiblJsYm5RaU9sc2lMeW9nUUdac2IzY2dLaTljYmx4dWFXMXdiM0owSUhzZ1ZtRnlhV0ZpYkdVc0lGZHBiR1JqWVhKa0xDQklaV0ZrVkdGcGJDd2dRMkZ3ZEhWeVpTd2dWSGx3WlN3Z1UzUmhjblJ6VjJsMGFDd2dRbTkxYm1Rc0lFSnBkRk4wY21sdVowMWhkR05vSUgwZ1puSnZiU0JjSWk0dmRIbHdaWE5jSWp0Y2JseHVablZ1WTNScGIyNGdhWE5mYm5WdFltVnlLSFpoYkhWbE9pQmhibmtwT2lCaWIyOXNaV0Z1SUh0Y2JpQWdjbVYwZFhKdUlIUjVjR1Z2WmlCMllXeDFaU0E5UFQwZ0oyNTFiV0psY2ljN1hHNTlYRzVjYm1aMWJtTjBhVzl1SUdselgzTjBjbWx1WnloMllXeDFaVG9nWVc1NUtUb2dZbTl2YkdWaGJudGNiaUFnY21WMGRYSnVJSFI1Y0dWdlppQjJZV3gxWlNBOVBUMGdKM04wY21sdVp5YzdYRzU5WEc1Y2JtWjFibU4wYVc5dUlHbHpYMkp2YjJ4bFlXNG9kbUZzZFdVNklHRnVlU2s2SUdKdmIyeGxZVzRnZTF4dUlDQnlaWFIxY200Z2RIbHdaVzltSUhaaGJIVmxJRDA5UFNBblltOXZiR1ZoYmljN1hHNTlYRzVjYm1aMWJtTjBhVzl1SUdselgzTjViV0p2YkNoMllXeDFaVG9nWVc1NUtUb2dZbTl2YkdWaGJpQjdYRzRnSUhKbGRIVnliaUIwZVhCbGIyWWdkbUZzZFdVZ1BUMDlJQ2R6ZVcxaWIyd25PMXh1ZlZ4dVhHNW1kVzVqZEdsdmJpQnBjMTl1ZFd4c0tIWmhiSFZsT2lCaGJua3BPaUJpYjI5c1pXRnVJSHRjYmlBZ2NtVjBkWEp1SUhaaGJIVmxJRDA5UFNCdWRXeHNPMXh1ZlZ4dVhHNW1kVzVqZEdsdmJpQnBjMTkxYm1SbFptbHVaV1FvZG1Gc2RXVTZJR0Z1ZVNrNklHSnZiMnhsWVc0Z2UxeHVJQ0J5WlhSMWNtNGdkSGx3Wlc5bUlIWmhiSFZsSUQwOVBTQW5kVzVrWldacGJtVmtKenRjYm4xY2JseHVablZ1WTNScGIyNGdhWE5mWm5WdVkzUnBiMjRvZG1Gc2RXVTZJR0Z1ZVNrNklHSnZiMnhsWVc0Z2UxeHVJQ0J5WlhSMWNtNGdUMkpxWldOMExuQnliM1J2ZEhsd1pTNTBiMU4wY21sdVp5NWpZV3hzS0haaGJIVmxLU0E5UFNBblcyOWlhbVZqZENCR2RXNWpkR2x2Ymwwbk8xeHVmVnh1WEc1bWRXNWpkR2x2YmlCcGMxOTJZWEpwWVdKc1pTaDJZV3gxWlRvZ1lXNTVLVG9nWW05dmJHVmhiaUI3WEc0Z0lISmxkSFZ5YmlCMllXeDFaU0JwYm5OMFlXNWpaVzltSUZaaGNtbGhZbXhsTzF4dWZWeHVYRzVtZFc1amRHbHZiaUJwYzE5M2FXeGtZMkZ5WkNoMllXeDFaVG9nWVc1NUtUb2dZbTl2YkdWaGJpQjdYRzRnSUhKbGRIVnliaUIyWVd4MVpTQnBibk4wWVc1alpXOW1JRmRwYkdSallYSmtPMXh1ZlZ4dVhHNW1kVzVqZEdsdmJpQnBjMTlvWldGa1ZHRnBiQ2gyWVd4MVpUb2dZVzU1S1RvZ1ltOXZiR1ZoYmlCN1hHNGdJSEpsZEhWeWJpQjJZV3gxWlNCcGJuTjBZVzVqWlc5bUlFaGxZV1JVWVdsc08xeHVmVnh1WEc1bWRXNWpkR2x2YmlCcGMxOWpZWEIwZFhKbEtIWmhiSFZsT2lCaGJua3BPaUJpYjI5c1pXRnVJSHRjYmlBZ2NtVjBkWEp1SUhaaGJIVmxJR2x1YzNSaGJtTmxiMllnUTJGd2RIVnlaVHRjYm4xY2JseHVablZ1WTNScGIyNGdhWE5mZEhsd1pTaDJZV3gxWlRvZ1lXNTVLVG9nWW05dmJHVmhiaUI3WEc0Z0lISmxkSFZ5YmlCMllXeDFaU0JwYm5OMFlXNWpaVzltSUZSNWNHVTdYRzU5WEc1Y2JtWjFibU4wYVc5dUlHbHpYM04wWVhKMGMxZHBkR2dvZG1Gc2RXVTZJR0Z1ZVNrNklHSnZiMnhsWVc0Z2UxeHVJQ0J5WlhSMWNtNGdkbUZzZFdVZ2FXNXpkR0Z1WTJWdlppQlRkR0Z5ZEhOWGFYUm9PMXh1ZlZ4dVhHNW1kVzVqZEdsdmJpQnBjMTlpYjNWdVpDaDJZV3gxWlRvZ1lXNTVLVG9nWW05dmJHVmhiaUI3WEc0Z0lISmxkSFZ5YmlCMllXeDFaU0JwYm5OMFlXNWpaVzltSUVKdmRXNWtPMXh1ZlZ4dVhHNW1kVzVqZEdsdmJpQnBjMTl2WW1wbFkzUW9kbUZzZFdVNklHRnVlU2s2SUdKdmIyeGxZVzRnZTF4dUlDQnlaWFIxY200Z2RIbHdaVzltSUhaaGJIVmxJRDA5UFNBbmIySnFaV04wSnp0Y2JuMWNibHh1Wm5WdVkzUnBiMjRnYVhOZllYSnlZWGtvZG1Gc2RXVTZJR0Z1ZVNrNklHSnZiMnhsWVc0Z2UxeHVJQ0J5WlhSMWNtNGdRWEp5WVhrdWFYTkJjbkpoZVNoMllXeDFaU2s3WEc1OVhHNWNibVoxYm1OMGFXOXVJR2x6WDJKcGRITjBjbWx1WnloMllXeDFaVG9nWVc1NUtUb2dZbTl2YkdWaGJpQjdYRzRnSUhKbGRIVnliaUIyWVd4MVpTQnBibk4wWVc1alpXOW1JRUpwZEZOMGNtbHVaMDFoZEdOb08xeHVmVnh1WEc1Y2JtVjRjRzl5ZENCa1pXWmhkV3gwSUh0Y2JpQWdhWE5mYm5WdFltVnlMRnh1SUNCcGMxOXpkSEpwYm1jc1hHNGdJR2x6WDJKdmIyeGxZVzRzWEc0Z0lHbHpYM041YldKdmJDeGNiaUFnYVhOZmJuVnNiQ3hjYmlBZ2FYTmZkVzVrWldacGJtVmtMRnh1SUNCcGMxOW1kVzVqZEdsdmJpeGNiaUFnYVhOZmRtRnlhV0ZpYkdVc1hHNGdJR2x6WDNkcGJHUmpZWEprTEZ4dUlDQnBjMTlvWldGa1ZHRnBiQ3hjYmlBZ2FYTmZZMkZ3ZEhWeVpTeGNiaUFnYVhOZmRIbHdaU3hjYmlBZ2FYTmZjM1JoY25SelYybDBhQ3hjYmlBZ2FYTmZZbTkxYm1Rc1hHNGdJR2x6WDI5aWFtVmpkQ3hjYmlBZ2FYTmZZWEp5WVhrc1hHNGdJR2x6WDJKcGRITjBjbWx1WjF4dWZUdGNiaUpkTENKemIzVnlZMlZTYjI5MElqb2lMM052ZFhKalpTOGlmUT09XG4iLCJcblxuaW1wb3J0IENoZWNrcyBmcm9tIFwiLi9jaGVja3NcIjtcbmltcG9ydCAqIGFzIFR5cGVzIGZyb20gXCIuL3R5cGVzXCI7XG5pbXBvcnQgeyBidWlsZE1hdGNoIH0gZnJvbSBcIi4vbWF0Y2hcIjtcbmltcG9ydCBCaXRTdHJpbmcgZnJvbSBcIi4uL2JpdF9zdHJpbmdcIjtcblxuZnVuY3Rpb24gcmVzb2x2ZVN5bWJvbChwYXR0ZXJuKSB7XG4gIHJldHVybiBmdW5jdGlvbiAodmFsdWUpIHtcbiAgICByZXR1cm4gQ2hlY2tzLmlzX3N5bWJvbCh2YWx1ZSkgJiYgdmFsdWUgPT09IHBhdHRlcm47XG4gIH07XG59XG5cbmZ1bmN0aW9uIHJlc29sdmVTdHJpbmcocGF0dGVybikge1xuICByZXR1cm4gZnVuY3Rpb24gKHZhbHVlKSB7XG4gICAgcmV0dXJuIENoZWNrcy5pc19zdHJpbmcodmFsdWUpICYmIHZhbHVlID09PSBwYXR0ZXJuO1xuICB9O1xufVxuXG5mdW5jdGlvbiByZXNvbHZlTnVtYmVyKHBhdHRlcm4pIHtcbiAgcmV0dXJuIGZ1bmN0aW9uICh2YWx1ZSkge1xuICAgIHJldHVybiBDaGVja3MuaXNfbnVtYmVyKHZhbHVlKSAmJiB2YWx1ZSA9PT0gcGF0dGVybjtcbiAgfTtcbn1cblxuZnVuY3Rpb24gcmVzb2x2ZUJvb2xlYW4ocGF0dGVybikge1xuICByZXR1cm4gZnVuY3Rpb24gKHZhbHVlKSB7XG4gICAgcmV0dXJuIENoZWNrcy5pc19ib29sZWFuKHZhbHVlKSAmJiB2YWx1ZSA9PT0gcGF0dGVybjtcbiAgfTtcbn1cblxuZnVuY3Rpb24gcmVzb2x2ZUZ1bmN0aW9uKHBhdHRlcm4pIHtcbiAgcmV0dXJuIGZ1bmN0aW9uICh2YWx1ZSkge1xuICAgIHJldHVybiBDaGVja3MuaXNfZnVuY3Rpb24odmFsdWUpICYmIHZhbHVlID09PSBwYXR0ZXJuO1xuICB9O1xufVxuXG5mdW5jdGlvbiByZXNvbHZlTnVsbChwYXR0ZXJuKSB7XG4gIHJldHVybiBmdW5jdGlvbiAodmFsdWUpIHtcbiAgICByZXR1cm4gQ2hlY2tzLmlzX251bGwodmFsdWUpO1xuICB9O1xufVxuXG5mdW5jdGlvbiByZXNvbHZlQm91bmQocGF0dGVybikge1xuICByZXR1cm4gZnVuY3Rpb24gKHZhbHVlLCBhcmdzKSB7XG4gICAgaWYgKHR5cGVvZiB2YWx1ZSA9PT0gdHlwZW9mIHBhdHRlcm4udmFsdWUgJiYgdmFsdWUgPT09IHBhdHRlcm4udmFsdWUpIHtcbiAgICAgIGFyZ3MucHVzaCh2YWx1ZSk7XG4gICAgICByZXR1cm4gdHJ1ZTtcbiAgICB9XG5cbiAgICByZXR1cm4gZmFsc2U7XG4gIH07XG59XG5cbmZ1bmN0aW9uIHJlc29sdmVXaWxkY2FyZCgpIHtcbiAgcmV0dXJuIGZ1bmN0aW9uICgpIHtcbiAgICByZXR1cm4gdHJ1ZTtcbiAgfTtcbn1cblxuZnVuY3Rpb24gcmVzb2x2ZVZhcmlhYmxlKCkge1xuICByZXR1cm4gZnVuY3Rpb24gKHZhbHVlLCBhcmdzKSB7XG4gICAgYXJncy5wdXNoKHZhbHVlKTtcbiAgICByZXR1cm4gdHJ1ZTtcbiAgfTtcbn1cblxuZnVuY3Rpb24gcmVzb2x2ZUhlYWRUYWlsKHBhdHRlcm4pIHtcbiAgY29uc3QgaGVhZE1hdGNoZXMgPSBidWlsZE1hdGNoKHBhdHRlcm4uaGVhZCk7XG4gIGNvbnN0IHRhaWxNYXRjaGVzID0gYnVpbGRNYXRjaChwYXR0ZXJuLnRhaWwpO1xuXG4gIHJldHVybiBmdW5jdGlvbiAodmFsdWUsIGFyZ3MpIHtcbiAgICBpZiAoIUNoZWNrcy5pc19hcnJheSh2YWx1ZSkgfHwgdmFsdWUubGVuZ3RoIDwgMikge1xuICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH1cblxuICAgIGNvbnN0IGhlYWQgPSB2YWx1ZVswXTtcbiAgICBjb25zdCB0YWlsID0gdmFsdWUuc2xpY2UoMSk7XG5cbiAgICBpZiAoaGVhZE1hdGNoZXMoaGVhZCwgYXJncykgJiYgdGFpbE1hdGNoZXModGFpbCwgYXJncykpIHtcbiAgICAgIHJldHVybiB0cnVlO1xuICAgIH1cbiAgfTtcbn1cblxuZnVuY3Rpb24gcmVzb2x2ZUNhcHR1cmUocGF0dGVybikge1xuICBjb25zdCBtYXRjaGVzID0gYnVpbGRNYXRjaChwYXR0ZXJuLnZhbHVlKTtcblxuICByZXR1cm4gZnVuY3Rpb24gKHZhbHVlLCBhcmdzKSB7XG4gICAgaWYgKG1hdGNoZXModmFsdWUsIGFyZ3MpKSB7XG4gICAgICBhcmdzLnB1c2godmFsdWUpO1xuICAgICAgcmV0dXJuIHRydWU7XG4gICAgfVxuXG4gICAgcmV0dXJuIGZhbHNlO1xuICB9O1xufVxuXG5mdW5jdGlvbiByZXNvbHZlU3RhcnRzV2l0aChwYXR0ZXJuKSB7XG4gIGNvbnN0IHByZWZpeCA9IHBhdHRlcm4ucHJlZml4O1xuXG4gIHJldHVybiBmdW5jdGlvbiAodmFsdWUsIGFyZ3MpIHtcbiAgICBpZiAoQ2hlY2tzLmlzX3N0cmluZyh2YWx1ZSkgJiYgdmFsdWUuc3RhcnRzV2l0aChwcmVmaXgpKSB7XG4gICAgICBhcmdzLnB1c2godmFsdWUuc3Vic3RyaW5nKHByZWZpeC5sZW5ndGgpKTtcbiAgICAgIHJldHVybiB0cnVlO1xuICAgIH1cblxuICAgIHJldHVybiBmYWxzZTtcbiAgfTtcbn1cblxuZnVuY3Rpb24gcmVzb2x2ZVR5cGUocGF0dGVybikge1xuICByZXR1cm4gZnVuY3Rpb24gKHZhbHVlLCBhcmdzKSB7XG4gICAgaWYgKHZhbHVlIGluc3RhbmNlb2YgcGF0dGVybi50eXBlKSB7XG4gICAgICBjb25zdCBtYXRjaGVzID0gYnVpbGRNYXRjaChwYXR0ZXJuLm9ialBhdHRlcm4pO1xuICAgICAgcmV0dXJuIG1hdGNoZXModmFsdWUsIGFyZ3MpICYmIGFyZ3MucHVzaCh2YWx1ZSkgPiAwO1xuICAgIH1cblxuICAgIHJldHVybiBmYWxzZTtcbiAgfTtcbn1cblxuZnVuY3Rpb24gcmVzb2x2ZUFycmF5KHBhdHRlcm4pIHtcbiAgY29uc3QgbWF0Y2hlcyA9IHBhdHRlcm4ubWFwKHggPT4gYnVpbGRNYXRjaCh4KSk7XG5cbiAgcmV0dXJuIGZ1bmN0aW9uICh2YWx1ZSwgYXJncykge1xuICAgIGlmICghQ2hlY2tzLmlzX2FycmF5KHZhbHVlKSB8fCB2YWx1ZS5sZW5ndGggIT0gcGF0dGVybi5sZW5ndGgpIHtcbiAgICAgIHJldHVybiBmYWxzZTtcbiAgICB9XG5cbiAgICByZXR1cm4gdmFsdWUuZXZlcnkoZnVuY3Rpb24gKHYsIGkpIHtcbiAgICAgIHJldHVybiBtYXRjaGVzW2ldKHZhbHVlW2ldLCBhcmdzKTtcbiAgICB9KTtcbiAgfTtcbn1cblxuZnVuY3Rpb24gcmVzb2x2ZU9iamVjdChwYXR0ZXJuKSB7XG4gIGxldCBtYXRjaGVzID0ge307XG5cbiAgZm9yIChsZXQga2V5IG9mIE9iamVjdC5rZXlzKHBhdHRlcm4pLmNvbmNhdChPYmplY3QuZ2V0T3duUHJvcGVydHlTeW1ib2xzKHBhdHRlcm4pKSkge1xuICAgIG1hdGNoZXNba2V5XSA9IGJ1aWxkTWF0Y2gocGF0dGVybltrZXldKTtcbiAgfVxuXG4gIHJldHVybiBmdW5jdGlvbiAodmFsdWUsIGFyZ3MpIHtcbiAgICBpZiAoIUNoZWNrcy5pc19vYmplY3QodmFsdWUpIHx8IHBhdHRlcm4ubGVuZ3RoID4gdmFsdWUubGVuZ3RoKSB7XG4gICAgICByZXR1cm4gZmFsc2U7XG4gICAgfVxuXG4gICAgZm9yIChsZXQga2V5IG9mIE9iamVjdC5rZXlzKHBhdHRlcm4pLmNvbmNhdChPYmplY3QuZ2V0T3duUHJvcGVydHlTeW1ib2xzKHBhdHRlcm4pKSkge1xuICAgICAgaWYgKCEoa2V5IGluIHZhbHVlKSB8fCAhbWF0Y2hlc1trZXldKHZhbHVlW2tleV0sIGFyZ3MpKSB7XG4gICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICByZXR1cm4gdHJ1ZTtcbiAgfTtcbn1cblxuZnVuY3Rpb24gcmVzb2x2ZUJpdFN0cmluZyhwYXR0ZXJuKSB7XG4gIGxldCBwYXR0ZXJuQml0U3RyaW5nID0gW107XG5cbiAgZm9yIChsZXQgYml0c3RyaW5nTWF0Y2hQYXJ0IG9mIHBhdHRlcm4udmFsdWVzKSB7XG4gICAgaWYgKENoZWNrcy5pc192YXJpYWJsZShiaXRzdHJpbmdNYXRjaFBhcnQudmFsdWUpKSB7XG4gICAgICBsZXQgc2l6ZSA9IGdldFNpemUoYml0c3RyaW5nTWF0Y2hQYXJ0LnVuaXQsIGJpdHN0cmluZ01hdGNoUGFydC5zaXplKTtcbiAgICAgIGZpbGxBcnJheShwYXR0ZXJuQml0U3RyaW5nLCBzaXplKTtcbiAgICB9IGVsc2Uge1xuICAgICAgcGF0dGVybkJpdFN0cmluZyA9IHBhdHRlcm5CaXRTdHJpbmcuY29uY2F0KG5ldyBCaXRTdHJpbmcoYml0c3RyaW5nTWF0Y2hQYXJ0KS52YWx1ZSk7XG4gICAgfVxuICB9XG5cbiAgbGV0IHBhdHRlcm5WYWx1ZXMgPSBwYXR0ZXJuLnZhbHVlcztcblxuICByZXR1cm4gZnVuY3Rpb24gKHZhbHVlLCBhcmdzKSB7XG4gICAgbGV0IGJzVmFsdWUgPSBudWxsO1xuXG4gICAgaWYgKCFDaGVja3MuaXNfc3RyaW5nKHZhbHVlKSAmJiAhKHZhbHVlIGluc3RhbmNlb2YgQml0U3RyaW5nKSkge1xuICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH1cblxuICAgIGlmIChDaGVja3MuaXNfc3RyaW5nKHZhbHVlKSkge1xuICAgICAgYnNWYWx1ZSA9IG5ldyBCaXRTdHJpbmcoQml0U3RyaW5nLmJpbmFyeSh2YWx1ZSkpO1xuICAgIH0gZWxzZSB7XG4gICAgICBic1ZhbHVlID0gdmFsdWU7XG4gICAgfVxuXG4gICAgbGV0IGJlZ2lubmluZ0luZGV4ID0gMDtcblxuICAgIGZvciAobGV0IGkgPSAwOyBpIDwgcGF0dGVyblZhbHVlcy5sZW5ndGg7IGkrKykge1xuICAgICAgbGV0IGJpdHN0cmluZ01hdGNoUGFydCA9IHBhdHRlcm5WYWx1ZXNbaV07XG5cbiAgICAgIGlmIChDaGVja3MuaXNfdmFyaWFibGUoYml0c3RyaW5nTWF0Y2hQYXJ0LnZhbHVlKSAmJiBiaXRzdHJpbmdNYXRjaFBhcnQudHlwZSA9PSAnYmluYXJ5JyAmJiBiaXRzdHJpbmdNYXRjaFBhcnQuc2l6ZSA9PT0gdW5kZWZpbmVkICYmIGkgPCBwYXR0ZXJuVmFsdWVzLmxlbmd0aCAtIDEpIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKFwiYSBiaW5hcnkgZmllbGQgd2l0aG91dCBzaXplIGlzIG9ubHkgYWxsb3dlZCBhdCB0aGUgZW5kIG9mIGEgYmluYXJ5IHBhdHRlcm5cIik7XG4gICAgICB9XG5cbiAgICAgIGxldCBzaXplID0gMDtcbiAgICAgIGxldCBic1ZhbHVlQXJyYXlQYXJ0ID0gW107XG4gICAgICBsZXQgcGF0dGVybkJpdFN0cmluZ0FycmF5UGFydCA9IFtdO1xuICAgICAgc2l6ZSA9IGdldFNpemUoYml0c3RyaW5nTWF0Y2hQYXJ0LnVuaXQsIGJpdHN0cmluZ01hdGNoUGFydC5zaXplKTtcblxuICAgICAgaWYgKGkgPT09IHBhdHRlcm5WYWx1ZXMubGVuZ3RoIC0gMSkge1xuICAgICAgICBic1ZhbHVlQXJyYXlQYXJ0ID0gYnNWYWx1ZS52YWx1ZS5zbGljZShiZWdpbm5pbmdJbmRleCk7XG4gICAgICAgIHBhdHRlcm5CaXRTdHJpbmdBcnJheVBhcnQgPSBwYXR0ZXJuQml0U3RyaW5nLnNsaWNlKGJlZ2lubmluZ0luZGV4KTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIGJzVmFsdWVBcnJheVBhcnQgPSBic1ZhbHVlLnZhbHVlLnNsaWNlKGJlZ2lubmluZ0luZGV4LCBiZWdpbm5pbmdJbmRleCArIHNpemUpO1xuICAgICAgICBwYXR0ZXJuQml0U3RyaW5nQXJyYXlQYXJ0ID0gcGF0dGVybkJpdFN0cmluZy5zbGljZShiZWdpbm5pbmdJbmRleCwgYmVnaW5uaW5nSW5kZXggKyBzaXplKTtcbiAgICAgIH1cblxuICAgICAgaWYgKENoZWNrcy5pc192YXJpYWJsZShiaXRzdHJpbmdNYXRjaFBhcnQudmFsdWUpKSB7XG4gICAgICAgIHN3aXRjaCAoYml0c3RyaW5nTWF0Y2hQYXJ0LnR5cGUpIHtcbiAgICAgICAgICBjYXNlICdpbnRlZ2VyJzpcbiAgICAgICAgICAgIGlmIChiaXRzdHJpbmdNYXRjaFBhcnQuYXR0cmlidXRlcyAmJiBiaXRzdHJpbmdNYXRjaFBhcnQuYXR0cmlidXRlcy5pbmRleE9mKFwic2lnbmVkXCIpICE9IC0xKSB7XG4gICAgICAgICAgICAgIGFyZ3MucHVzaChuZXcgSW50OEFycmF5KFtic1ZhbHVlQXJyYXlQYXJ0WzBdXSlbMF0pO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgYXJncy5wdXNoKG5ldyBVaW50OEFycmF5KFtic1ZhbHVlQXJyYXlQYXJ0WzBdXSlbMF0pO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgYnJlYWs7XG5cbiAgICAgICAgICBjYXNlICdmbG9hdCc6XG4gICAgICAgICAgICBpZiAoc2l6ZSA9PT0gNjQpIHtcbiAgICAgICAgICAgICAgYXJncy5wdXNoKEZsb2F0NjRBcnJheS5mcm9tKGJzVmFsdWVBcnJheVBhcnQpWzBdKTtcbiAgICAgICAgICAgIH0gZWxzZSBpZiAoc2l6ZSA9PT0gMzIpIHtcbiAgICAgICAgICAgICAgYXJncy5wdXNoKEZsb2F0MzJBcnJheS5mcm9tKGJzVmFsdWVBcnJheVBhcnQpWzBdKTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGJyZWFrO1xuXG4gICAgICAgICAgY2FzZSAnYml0c3RyaW5nJzpcbiAgICAgICAgICAgIGFyZ3MucHVzaChjcmVhdGVCaXRTdHJpbmcoYnNWYWx1ZUFycmF5UGFydCkpO1xuICAgICAgICAgICAgYnJlYWs7XG5cbiAgICAgICAgICBjYXNlICdiaW5hcnknOlxuICAgICAgICAgICAgYXJncy5wdXNoKFN0cmluZy5mcm9tQ2hhckNvZGUuYXBwbHkobnVsbCwgbmV3IFVpbnQ4QXJyYXkoYnNWYWx1ZUFycmF5UGFydCkpKTtcbiAgICAgICAgICAgIGJyZWFrO1xuXG4gICAgICAgICAgY2FzZSAndXRmOCc6XG4gICAgICAgICAgICBhcmdzLnB1c2goU3RyaW5nLmZyb21DaGFyQ29kZS5hcHBseShudWxsLCBuZXcgVWludDhBcnJheShic1ZhbHVlQXJyYXlQYXJ0KSkpO1xuICAgICAgICAgICAgYnJlYWs7XG5cbiAgICAgICAgICBjYXNlICd1dGYxNic6XG4gICAgICAgICAgICBhcmdzLnB1c2goU3RyaW5nLmZyb21DaGFyQ29kZS5hcHBseShudWxsLCBuZXcgVWludDE2QXJyYXkoYnNWYWx1ZUFycmF5UGFydCkpKTtcbiAgICAgICAgICAgIGJyZWFrO1xuXG4gICAgICAgICAgY2FzZSAndXRmMzInOlxuICAgICAgICAgICAgYXJncy5wdXNoKFN0cmluZy5mcm9tQ2hhckNvZGUuYXBwbHkobnVsbCwgbmV3IFVpbnQzMkFycmF5KGJzVmFsdWVBcnJheVBhcnQpKSk7XG4gICAgICAgICAgICBicmVhaztcblxuICAgICAgICAgIGRlZmF1bHQ6XG4gICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgIH1cbiAgICAgIH0gZWxzZSBpZiAoIWFycmF5c0VxdWFsKGJzVmFsdWVBcnJheVBhcnQsIHBhdHRlcm5CaXRTdHJpbmdBcnJheVBhcnQpKSB7XG4gICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgIH1cblxuICAgICAgYmVnaW5uaW5nSW5kZXggPSBiZWdpbm5pbmdJbmRleCArIHNpemU7XG4gICAgfVxuXG4gICAgcmV0dXJuIHRydWU7XG4gIH07XG59XG5cbmZ1bmN0aW9uIGdldFNpemUodW5pdCwgc2l6ZSkge1xuICByZXR1cm4gdW5pdCAqIHNpemUgLyA4O1xufVxuXG5mdW5jdGlvbiBhcnJheXNFcXVhbChhLCBiKSB7XG4gIGlmIChhID09PSBiKSByZXR1cm4gdHJ1ZTtcbiAgaWYgKGEgPT0gbnVsbCB8fCBiID09IG51bGwpIHJldHVybiBmYWxzZTtcbiAgaWYgKGEubGVuZ3RoICE9IGIubGVuZ3RoKSByZXR1cm4gZmFsc2U7XG5cbiAgZm9yICh2YXIgaSA9IDA7IGkgPCBhLmxlbmd0aDsgKytpKSB7XG4gICAgaWYgKGFbaV0gIT09IGJbaV0pIHJldHVybiBmYWxzZTtcbiAgfVxuXG4gIHJldHVybiB0cnVlO1xufVxuXG5mdW5jdGlvbiBmaWxsQXJyYXkoYXJyLCBudW0pIHtcbiAgZm9yIChsZXQgaSA9IDA7IGkgPCBudW07IGkrKykge1xuICAgIGFyci5wdXNoKDApO1xuICB9XG59XG5cbmZ1bmN0aW9uIGNyZWF0ZUJpdFN0cmluZyhhcnIpIHtcbiAgbGV0IGludGVnZXJQYXJ0cyA9IGFyci5tYXAoZWxlbSA9PiBCaXRTdHJpbmcuaW50ZWdlcihlbGVtKSk7XG4gIHJldHVybiBuZXcgQml0U3RyaW5nKC4uLmludGVnZXJQYXJ0cyk7XG59XG5cbmZ1bmN0aW9uIHJlc29sdmVOb01hdGNoKCkge1xuICByZXR1cm4gZnVuY3Rpb24gKCkge1xuICAgIHJldHVybiBmYWxzZTtcbiAgfTtcbn1cblxuZXhwb3J0IGRlZmF1bHQge1xuICByZXNvbHZlQm91bmQsXG4gIHJlc29sdmVXaWxkY2FyZCxcbiAgcmVzb2x2ZVZhcmlhYmxlLFxuICByZXNvbHZlSGVhZFRhaWwsXG4gIHJlc29sdmVDYXB0dXJlLFxuICByZXNvbHZlU3RhcnRzV2l0aCxcbiAgcmVzb2x2ZVR5cGUsXG4gIHJlc29sdmVBcnJheSxcbiAgcmVzb2x2ZU9iamVjdCxcbiAgcmVzb2x2ZU5vTWF0Y2gsXG4gIHJlc29sdmVTeW1ib2wsXG4gIHJlc29sdmVTdHJpbmcsXG4gIHJlc29sdmVOdW1iZXIsXG4gIHJlc29sdmVCb29sZWFuLFxuICByZXNvbHZlRnVuY3Rpb24sXG4gIHJlc29sdmVOdWxsLFxuICByZXNvbHZlQml0U3RyaW5nXG59O1xuLy8jIHNvdXJjZU1hcHBpbmdVUkw9ZGF0YTphcHBsaWNhdGlvbi9qc29uO2Jhc2U2NCxleUoyWlhKemFXOXVJam96TENKemIzVnlZMlZ6SWpwYklteHBZaTlqYjNKbEwzQmhkSFJsY201ekwzSmxjMjlzZG1WeWN5NXFjeUpkTENKdVlXMWxjeUk2VzEwc0ltMWhjSEJwYm1keklqb2lPenRCUVVWQkxFOUJRVThzVFVGQlVDeE5RVUZ0UWl4VlFVRnVRanRCUVVOQkxFOUJRVThzUzBGQlN5eExRVUZNTEUxQlFXZENMRk5CUVhaQ08wRkJRMEVzVTBGQlV5eFZRVUZVTEZGQlFUSkNMRk5CUVROQ08wRkJRMEVzVDBGQlR5eFRRVUZRTEUxQlFYTkNMR1ZCUVhSQ096dEJRVVZCTEZOQlFWTXNZVUZCVkN4RFFVRjFRaXhQUVVGMlFpeEZRVUVyUXp0QlFVTTNReXhUUVVGUExGVkJRVk1zUzBGQlZDeEZRVUU0UWp0QlFVTnVReXhYUVVGUExFOUJRVThzVTBGQlVDeERRVUZwUWl4TFFVRnFRaXhMUVVFeVFpeFZRVUZWTEU5QlFWWXNRMEZFUXp0SFFVRTVRaXhEUVVSelF6dERRVUV2UXpzN1FVRk5RU3hUUVVGVExHRkJRVlFzUTBGQmRVSXNUMEZCZGtJc1JVRkJLME03UVVGRE4wTXNVMEZCVHl4VlFVRlRMRXRCUVZRc1JVRkJPRUk3UVVGRGJrTXNWMEZCVHl4UFFVRlBMRk5CUVZBc1EwRkJhVUlzUzBGQmFrSXNTMEZCTWtJc1ZVRkJWU3hQUVVGV0xFTkJSRU03UjBGQk9VSXNRMEZFYzBNN1EwRkJMME03TzBGQlRVRXNVMEZCVXl4aFFVRlVMRU5CUVhWQ0xFOUJRWFpDTEVWQlFTdERPMEZCUXpkRExGTkJRVThzVlVGQlV5eExRVUZVTEVWQlFUaENPMEZCUTI1RExGZEJRVThzVDBGQlR5eFRRVUZRTEVOQlFXbENMRXRCUVdwQ0xFdEJRVEpDTEZWQlFWVXNUMEZCVml4RFFVUkRPMGRCUVRsQ0xFTkJSSE5ETzBOQlFTOURPenRCUVUxQkxGTkJRVk1zWTBGQlZDeERRVUYzUWl4UFFVRjRRaXhGUVVGblJEdEJRVU01UXl4VFFVRlBMRlZCUVZNc1MwRkJWQ3hGUVVFNFFqdEJRVU51UXl4WFFVRlBMRTlCUVU4c1ZVRkJVQ3hEUVVGclFpeExRVUZzUWl4TFFVRTBRaXhWUVVGVkxFOUJRVllzUTBGRVFUdEhRVUU1UWl4RFFVUjFRenREUVVGb1JEczdRVUZOUVN4VFFVRlRMR1ZCUVZRc1EwRkJlVUlzVDBGQmVrSXNSVUZCYVVRN1FVRkRMME1zVTBGQlR5eFZRVUZUTEV0QlFWUXNSVUZCT0VJN1FVRkRia01zVjBGQlR5eFBRVUZQTEZkQlFWQXNRMEZCYlVJc1MwRkJia0lzUzBGQk5rSXNWVUZCVlN4UFFVRldMRU5CUkVRN1IwRkJPVUlzUTBGRWQwTTdRMEZCYWtRN08wRkJUVUVzVTBGQlV5eFhRVUZVTEVOQlFYRkNMRTlCUVhKQ0xFVkJRVFpETzBGQlF6TkRMRk5CUVU4c1ZVRkJVeXhMUVVGVUxFVkJRVGhDTzBGQlEyNURMRmRCUVU4c1QwRkJUeXhQUVVGUUxFTkJRV1VzUzBGQlppeERRVUZRTEVOQlJHMURPMGRCUVRsQ0xFTkJSRzlETzBOQlFUZERPenRCUVUxQkxGTkJRVk1zV1VGQlZDeERRVUZ6UWl4UFFVRjBRaXhGUVVGelJEdEJRVU53UkN4VFFVRlBMRlZCUVZNc1MwRkJWQ3hGUVVGeFFpeEpRVUZ5UWl4RlFVRm5SRHRCUVVOeVJDeFJRVUZITEU5QlFVOHNTMEZCVUN4TFFVRnBRaXhQUVVGUExGRkJRVkVzUzBGQlVpeEpRVUZwUWl4VlFVRlZMRkZCUVZFc1MwRkJVaXhGUVVGak8wRkJRMnhGTEZkQlFVc3NTVUZCVEN4RFFVRlZMRXRCUVZZc1JVRkVhMFU3UVVGRmJFVXNZVUZCVHl4SlFVRlFMRU5CUm10Rk8wdEJRWEJGT3p0QlFVdEJMRmRCUVU4c1MwRkJVQ3hEUVU1eFJEdEhRVUZvUkN4RFFVUTJRenREUVVGMFJEczdRVUZYUVN4VFFVRlRMR1ZCUVZRc1IwRkJjVU03UVVGRGJrTXNVMEZCVHl4WlFVRnZRanRCUVVONlFpeFhRVUZQTEVsQlFWQXNRMEZFZVVJN1IwRkJjRUlzUTBGRU5FSTdRMEZCY2tNN08wRkJUVUVzVTBGQlV5eGxRVUZVTEVkQlFYRkRPMEZCUTI1RExGTkJRVThzVlVGQlV5eExRVUZVTEVWQlFYRkNMRWxCUVhKQ0xFVkJRV2RFTzBGQlEzSkVMRk5CUVVzc1NVRkJUQ3hEUVVGVkxFdEJRVllzUlVGRWNVUTdRVUZGY2tRc1YwRkJUeXhKUVVGUUxFTkJSbkZFTzBkQlFXaEVMRU5CUkRSQ08wTkJRWEpET3p0QlFVOUJMRk5CUVZNc1pVRkJWQ3hEUVVGNVFpeFBRVUY2UWl4RlFVRTBSRHRCUVVNeFJDeFJRVUZOTEdOQlFXTXNWMEZCVnl4UlFVRlJMRWxCUVZJc1EwRkJla0lzUTBGRWIwUTdRVUZGTVVRc1VVRkJUU3hqUVVGakxGZEJRVmNzVVVGQlVTeEpRVUZTTEVOQlFYcENMRU5CUm05RU96dEJRVWt4UkN4VFFVRlBMRlZCUVZNc1MwRkJWQ3hGUVVGeFFpeEpRVUZ5UWl4RlFVRm5SRHRCUVVOeVJDeFJRVUZITEVOQlFVTXNUMEZCVHl4UlFVRlFMRU5CUVdkQ0xFdEJRV2hDTEVOQlFVUXNTVUZCTWtJc1RVRkJUU3hOUVVGT0xFZEJRV1VzUTBGQlppeEZRVUZwUWp0QlFVTTNReXhoUVVGUExFdEJRVkFzUTBGRU5rTTdTMEZCTDBNN08wRkJTVUVzVlVGQlRTeFBRVUZQTEUxQlFVMHNRMEZCVGl4RFFVRlFMRU5CVEN0RE8wRkJUWEpFTEZWQlFVMHNUMEZCVHl4TlFVRk5MRXRCUVU0c1EwRkJXU3hEUVVGYUxFTkJRVkFzUTBGT0swTTdPMEZCVVhKRUxGRkJRVWNzV1VGQldTeEpRVUZhTEVWQlFXdENMRWxCUVd4Q0xFdEJRVEpDTEZsQlFWa3NTVUZCV2l4RlFVRnJRaXhKUVVGc1FpeERRVUV6UWl4RlFVRnRSRHRCUVVOd1JDeGhRVUZQTEVsQlFWQXNRMEZFYjBRN1MwRkJkRVE3UjBGU1N5eERRVXB0UkR0RFFVRTFSRHM3UVVGclFrRXNVMEZCVXl4alFVRlVMRU5CUVhkQ0xFOUJRWGhDTEVWQlFUQkVPMEZCUTNoRUxGRkJRVTBzVlVGQlZTeFhRVUZYTEZGQlFWRXNTMEZCVWl4RFFVRnlRaXhEUVVSclJEczdRVUZIZUVRc1UwRkJUeXhWUVVGVExFdEJRVlFzUlVGQmNVSXNTVUZCY2tJc1JVRkJaMFE3UVVGRGNrUXNVVUZCUnl4UlFVRlJMRXRCUVZJc1JVRkJaU3hKUVVGbUxFTkJRVWdzUlVGQmQwSTdRVUZEZEVJc1YwRkJTeXhKUVVGTUxFTkJRVlVzUzBGQlZpeEZRVVJ6UWp0QlFVVjBRaXhoUVVGUExFbEJRVkFzUTBGR2MwSTdTMEZCZUVJN08wRkJTMEVzVjBGQlR5eExRVUZRTEVOQlRuRkVPMGRCUVdoRUxFTkJTR2xFTzBOQlFURkVPenRCUVdGQkxGTkJRVk1zYVVKQlFWUXNRMEZCTWtJc1QwRkJNMElzUlVGQlowVTdRVUZET1VRc1VVRkJUU3hUUVVGVExGRkJRVkVzVFVGQlVpeERRVVFyUXpzN1FVRkhPVVFzVTBGQlR5eFZRVUZUTEV0QlFWUXNSVUZCY1VJc1NVRkJja0lzUlVGQlowUTdRVUZEY2tRc1VVRkJSeXhQUVVGUExGTkJRVkFzUTBGQmFVSXNTMEZCYWtJc1MwRkJNa0lzVFVGQlRTeFZRVUZPTEVOQlFXbENMRTFCUVdwQ0xFTkJRVE5DTEVWQlFXOUVPMEZCUTNKRUxGZEJRVXNzU1VGQlRDeERRVUZWTEUxQlFVMHNVMEZCVGl4RFFVRm5RaXhQUVVGUExFMUJRVkFzUTBGQk1VSXNSVUZFY1VRN1FVRkZja1FzWVVGQlR5eEpRVUZRTEVOQlJuRkVPMHRCUVhaRU96dEJRVXRCTEZkQlFVOHNTMEZCVUN4RFFVNXhSRHRIUVVGb1JDeERRVWgxUkR0RFFVRm9SVHM3UVVGaFFTeFRRVUZUTEZkQlFWUXNRMEZCY1VJc1QwRkJja0lzUlVGQmIwUTdRVUZEYkVRc1UwRkJUeXhWUVVGVExFdEJRVlFzUlVGQmNVSXNTVUZCY2tJc1JVRkJaMFE3UVVGRGNrUXNVVUZCUnl4cFFrRkJhVUlzVVVGQlVTeEpRVUZTTEVWQlFXRTdRVUZETDBJc1dVRkJUU3hWUVVGVkxGZEJRVmNzVVVGQlVTeFZRVUZTTEVOQlFYSkNMRU5CUkhsQ08wRkJSUzlDTEdGQlFVOHNVVUZCVVN4TFFVRlNMRVZCUVdVc1NVRkJaaXhMUVVGM1FpeExRVUZMTEVsQlFVd3NRMEZCVlN4TFFVRldMRWxCUVcxQ0xFTkJRVzVDTEVOQlJrRTdTMEZCYWtNN08wRkJTMEVzVjBGQlR5eExRVUZRTEVOQlRuRkVPMGRCUVdoRUxFTkJSREpETzBOQlFYQkVPenRCUVZkQkxGTkJRVk1zV1VGQlZDeERRVUZ6UWl4UFFVRjBRaXhGUVVGeFJEdEJRVU51UkN4UlFVRk5MRlZCUVZVc1VVRkJVU3hIUVVGU0xFTkJRVmtzUzBGQlN5eFhRVUZYTEVOQlFWZ3NRMEZCVEN4RFFVRjBRaXhEUVVRMlF6czdRVUZIYmtRc1UwRkJUeXhWUVVGVExFdEJRVlFzUlVGQmNVSXNTVUZCY2tJc1JVRkJaMFE3UVVGRGNrUXNVVUZCUnl4RFFVRkRMRTlCUVU4c1VVRkJVQ3hEUVVGblFpeExRVUZvUWl4RFFVRkVMRWxCUVRKQ0xFMUJRVTBzVFVGQlRpeEpRVUZuUWl4UlFVRlJMRTFCUVZJc1JVRkJaVHRCUVVNelJDeGhRVUZQTEV0QlFWQXNRMEZFTWtRN1MwRkJOMFE3TzBGQlNVRXNWMEZCVHl4TlFVRk5MRXRCUVU0c1EwRkJXU3hWUVVGVExFTkJRVlFzUlVGQldTeERRVUZhTEVWQlFXVTdRVUZEYUVNc1lVRkJUeXhSUVVGUkxFTkJRVklzUlVGQlZ5eE5RVUZOTEVOQlFVNHNRMEZCV0N4RlFVRnhRaXhKUVVGeVFpeERRVUZRTEVOQlJHZERPMHRCUVdZc1EwRkJia0lzUTBGTWNVUTdSMEZCYUVRc1EwRklORU03UTBGQmNrUTdPMEZCWTBFc1UwRkJVeXhoUVVGVUxFTkJRWFZDTEU5QlFYWkNMRVZCUVd0RU8wRkJRMmhFTEUxQlFVa3NWVUZCVlN4RlFVRldMRU5CUkRSRE96dEJRVWRvUkN4UFFVRkpMRWxCUVVrc1IwRkJTaXhKUVVGWExFOUJRVThzU1VGQlVDeERRVUZaTEU5QlFWb3NSVUZCY1VJc1RVRkJja0lzUTBGQk5FSXNUMEZCVHl4eFFrRkJVQ3hEUVVFMlFpeFBRVUUzUWl4RFFVRTFRaXhEUVVGbUxFVkJRV3RHTzBGQlEyaEdMRmxCUVZFc1IwRkJVaXhKUVVGbExGZEJRVmNzVVVGQlVTeEhRVUZTTEVOQlFWZ3NRMEZCWml4RFFVUm5SanRIUVVGc1JqczdRVUZKUVN4VFFVRlBMRlZCUVZNc1MwRkJWQ3hGUVVGeFFpeEpRVUZ5UWl4RlFVRm5SRHRCUVVOeVJDeFJRVUZITEVOQlFVTXNUMEZCVHl4VFFVRlFMRU5CUVdsQ0xFdEJRV3BDTEVOQlFVUXNTVUZCTkVJc1VVRkJVU3hOUVVGU0xFZEJRV2xDTEUxQlFVMHNUVUZCVGl4RlFVRmhPMEZCUXpORUxHRkJRVThzUzBGQlVDeERRVVF5UkR0TFFVRTNSRHM3UVVGSlFTeFRRVUZKTEVsQlFVa3NSMEZCU2l4SlFVRlhMRTlCUVU4c1NVRkJVQ3hEUVVGWkxFOUJRVm9zUlVGQmNVSXNUVUZCY2tJc1EwRkJORUlzVDBGQlR5eHhRa0ZCVUN4RFFVRTJRaXhQUVVFM1FpeERRVUUxUWl4RFFVRm1MRVZCUVd0R08wRkJRMmhHTEZWQlFVY3NSVUZCUlN4UFFVRlBMRXRCUVZBc1EwRkJSaXhKUVVGdFFpeERRVUZETEZGQlFWRXNSMEZCVWl4RlFVRmhMRTFCUVUwc1IwRkJUaXhEUVVGaUxFVkJRWGxDTEVsQlFYcENMRU5CUVVRc1JVRkJhVU03UVVGRGNrUXNaVUZCVHl4TFFVRlFMRU5CUkhGRU8wOUJRWFpFTzB0QlJFWTdPMEZCVFVFc1YwRkJUeXhKUVVGUUxFTkJXSEZFTzBkQlFXaEVMRU5CVUhsRE8wTkJRV3hFT3p0QlFYTkNRU3hUUVVGVExHZENRVUZVTEVOQlFUQkNMRTlCUVRGQ0xFVkJRVzFGTzBGQlEycEZMRTFCUVVrc2JVSkJRVzFDTEVWQlFXNUNMRU5CUkRaRU96dEJRVWRxUlN4UFFVRkpMRWxCUVVrc2EwSkJRVW9zU1VGQk1FSXNVVUZCVVN4TlFVRlNMRVZCUVdVN1FVRkRNME1zVVVGQlJ5eFBRVUZQTEZkQlFWQXNRMEZCYlVJc2JVSkJRVzFDTEV0QlFXNUNMRU5CUVhSQ0xFVkJRV2RFTzBGQlF6bERMRlZCUVVrc1QwRkJUeXhSUVVGUkxHMUNRVUZ0UWl4SlFVRnVRaXhGUVVGNVFpeHRRa0ZCYlVJc1NVRkJia0lzUTBGQmVFTXNRMEZFTUVNN1FVRkZPVU1zWjBKQlFWVXNaMEpCUVZZc1JVRkJORUlzU1VGQk5VSXNSVUZHT0VNN1MwRkJhRVFzVFVGSFN6dEJRVU5JTEhsQ1FVRnRRaXhwUWtGQmFVSXNUVUZCYWtJc1EwRkJkMElzU1VGQlNTeFRRVUZLTEVOQlFXTXNhMEpCUVdRc1JVRkJhME1zUzBGQmJFTXNRMEZCTTBNc1EwRkVSenRMUVVoTU8wZEJSRVk3TzBGQlUwRXNUVUZCU1N4blFrRkJaMElzVVVGQlVTeE5RVUZTTEVOQldqWkRPenRCUVdOcVJTeFRRVUZQTEZWQlFWTXNTMEZCVkN4RlFVRnhRaXhKUVVGeVFpeEZRVUZuUkR0QlFVTnlSQ3hSUVVGSkxGVkJRVlVzU1VGQlZpeERRVVJwUkRzN1FVRkhja1FzVVVGQlJ5eERRVUZETEU5QlFVOHNVMEZCVUN4RFFVRnBRaXhMUVVGcVFpeERRVUZFTEVsQlFUUkNMRVZCUVVVc2FVSkJRV2xDTEZOQlFXcENMRU5CUVVZc1JVRkJLMEk3UVVGRE5VUXNZVUZCVHl4TFFVRlFMRU5CUkRSRU8wdEJRVGxFT3p0QlFVbEJMRkZCUVVjc1QwRkJUeXhUUVVGUUxFTkJRV2xDTEV0QlFXcENMRU5CUVVnc1JVRkJNa0k3UVVGRGVrSXNaMEpCUVZVc1NVRkJTU3hUUVVGS0xFTkJRV01zVlVGQlZTeE5RVUZXTEVOQlFXbENMRXRCUVdwQ0xFTkJRV1FzUTBGQlZpeERRVVI1UWp0TFFVRXpRaXhOUVVWTE8wRkJRMGdzWjBKQlFWVXNTMEZCVml4RFFVUkhPMHRCUmt3N08wRkJUVUVzVVVGQlNTeHBRa0ZCYVVJc1EwRkJha0lzUTBGaWFVUTdPMEZCWlhKRUxGTkJRVWtzU1VGQlNTeEpRVUZKTEVOQlFVb3NSVUZCVHl4SlFVRkpMR05CUVdNc1RVRkJaQ3hGUVVGelFpeEhRVUY2UXl4RlFVRTJRenRCUVVNelF5eFZRVUZKTEhGQ1FVRnhRaXhqUVVGakxFTkJRV1FzUTBGQmNrSXNRMEZFZFVNN08wRkJSek5ETEZWQlFVY3NUMEZCVHl4WFFVRlFMRU5CUVcxQ0xHMUNRVUZ0UWl4TFFVRnVRaXhEUVVGdVFpeEpRVU5CTEcxQ1FVRnRRaXhKUVVGdVFpeEpRVUV5UWl4UlFVRXpRaXhKUVVOQkxHMUNRVUZ0UWl4SlFVRnVRaXhMUVVFMFFpeFRRVUUxUWl4SlFVTkJMRWxCUVVrc1kwRkJZeXhOUVVGa0xFZEJRWFZDTEVOQlFYWkNMRVZCUVhsQ08wRkJRemxDTEdOQlFVMHNTVUZCU1N4TFFVRktMRU5CUVZVc05FVkJRVllzUTBGQlRpeERRVVE0UWp0UFFVaG9RenM3UVVGUFFTeFZRVUZKTEU5QlFVOHNRMEZCVUN4RFFWWjFRenRCUVZjelF5eFZRVUZKTEcxQ1FVRnRRaXhGUVVGdVFpeERRVmgxUXp0QlFWa3pReXhWUVVGSkxEUkNRVUUwUWl4RlFVRTFRaXhEUVZwMVF6dEJRV0V6UXl4aFFVRlBMRkZCUVZFc2JVSkJRVzFDTEVsQlFXNUNMRVZCUVhsQ0xHMUNRVUZ0UWl4SlFVRnVRaXhEUVVGNFF5eERRV0l5UXpzN1FVRmxNME1zVlVGQlJ5eE5RVUZOTEdOQlFXTXNUVUZCWkN4SFFVRjFRaXhEUVVGMlFpeEZRVUY1UWp0QlFVTm9ReXd5UWtGQmJVSXNVVUZCVVN4TFFVRlNMRU5CUVdNc1MwRkJaQ3hEUVVGdlFpeGpRVUZ3UWl4RFFVRnVRaXhEUVVSblF6dEJRVVZvUXl4dlEwRkJORUlzYVVKQlFXbENMRXRCUVdwQ0xFTkJRWFZDTEdOQlFYWkNMRU5CUVRWQ0xFTkJSbWRETzA5QlFXeERMRTFCUjA4N1FVRkRUQ3d5UWtGQmJVSXNVVUZCVVN4TFFVRlNMRU5CUVdNc1MwRkJaQ3hEUVVGdlFpeGpRVUZ3UWl4RlFVRnZReXhwUWtGQmFVSXNTVUZCYWtJc1EwRkJka1FzUTBGRVN6dEJRVVZNTEc5RFFVRTBRaXhwUWtGQmFVSXNTMEZCYWtJc1EwRkJkVUlzWTBGQmRrSXNSVUZCZFVNc2FVSkJRV2xDTEVsQlFXcENMRU5CUVc1RkxFTkJSa3M3VDBGSVVEczdRVUZSUVN4VlFVRkhMRTlCUVU4c1YwRkJVQ3hEUVVGdFFpeHRRa0ZCYlVJc1MwRkJia0lzUTBGQmRFSXNSVUZCWjBRN1FVRkRPVU1zWjBKQlFVOHNiVUpCUVcxQ0xFbEJRVzVDTzBGQlExQXNaVUZCU3l4VFFVRk1PMEZCUTBVc1owSkJRVWNzYlVKQlFXMUNMRlZCUVc1Q0xFbEJRV2xETEcxQ1FVRnRRaXhWUVVGdVFpeERRVUU0UWl4UFFVRTVRaXhEUVVGelF5eFJRVUYwUXl4TFFVRnRSQ3hEUVVGRExFTkJRVVFzUlVGQlJ6dEJRVU40Uml4dFFrRkJTeXhKUVVGTUxFTkJRVlVzU1VGQlNTeFRRVUZLTEVOQlFXTXNRMEZCUXl4cFFrRkJhVUlzUTBGQmFrSXNRMEZCUkN4RFFVRmtMRVZCUVhGRExFTkJRWEpETEVOQlFWWXNSVUZFZDBZN1lVRkJNVVlzVFVGRlR6dEJRVU5NTEcxQ1FVRkxMRWxCUVV3c1EwRkJWU3hKUVVGSkxGVkJRVW9zUTBGQlpTeERRVUZETEdsQ1FVRnBRaXhEUVVGcVFpeERRVUZFTEVOQlFXWXNSVUZCYzBNc1EwRkJkRU1zUTBGQlZpeEZRVVJMTzJGQlJsQTdRVUZMUVN4clFrRk9SanM3UVVGRVFTeGxRVk5MTEU5QlFVdzdRVUZEUlN4blFrRkJSeXhUUVVGVExFVkJRVlFzUlVGQldUdEJRVU5pTEcxQ1FVRkxMRWxCUVV3c1EwRkJWU3hoUVVGaExFbEJRV0lzUTBGQmEwSXNaMEpCUVd4Q0xFVkJRVzlETEVOQlFYQkRMRU5CUVZZc1JVRkVZVHRoUVVGbUxFMUJSVThzU1VGQlJ5eFRRVUZUTEVWQlFWUXNSVUZCV1R0QlFVTndRaXh0UWtGQlN5eEpRVUZNTEVOQlFWVXNZVUZCWVN4SlFVRmlMRU5CUVd0Q0xHZENRVUZzUWl4RlFVRnZReXhEUVVGd1F5eERRVUZXTEVWQlJHOUNPMkZCUVdZc1RVRkZSanRCUVVOSUxIRkNRVUZQTEV0QlFWQXNRMEZFUnp0aFFVWkZPMEZCUzFBc2EwSkJVa1k3TzBGQlZFRXNaVUZ0UWtzc1YwRkJURHRCUVVORkxHbENRVUZMTEVsQlFVd3NRMEZCVlN4blFrRkJaMElzWjBKQlFXaENMRU5CUVZZc1JVRkVSanRCUVVWRkxHdENRVVpHT3p0QlFXNUNRU3hsUVhWQ1N5eFJRVUZNTzBGQlEwVXNhVUpCUVVzc1NVRkJUQ3hEUVVGVkxFOUJRVThzV1VGQlVDeERRVUZ2UWl4TFFVRndRaXhEUVVFd1FpeEpRVUV4UWl4RlFVRm5ReXhKUVVGSkxGVkJRVW9zUTBGQlpTeG5Ra0ZCWml4RFFVRm9ReXhEUVVGV0xFVkJSRVk3UVVGRlJTeHJRa0ZHUmpzN1FVRjJRa0VzWlVFeVFrc3NUVUZCVER0QlFVTkZMR2xDUVVGTExFbEJRVXdzUTBGQlZTeFBRVUZQTEZsQlFWQXNRMEZCYjBJc1MwRkJjRUlzUTBGQk1FSXNTVUZCTVVJc1JVRkJaME1zU1VGQlNTeFZRVUZLTEVOQlFXVXNaMEpCUVdZc1EwRkJhRU1zUTBGQlZpeEZRVVJHTzBGQlJVVXNhMEpCUmtZN08wRkJNMEpCTEdWQkswSkxMRTlCUVV3N1FVRkRSU3hwUWtGQlN5eEpRVUZNTEVOQlFWVXNUMEZCVHl4WlFVRlFMRU5CUVc5Q0xFdEJRWEJDTEVOQlFUQkNMRWxCUVRGQ0xFVkJRV2RETEVsQlFVa3NWMEZCU2l4RFFVRm5RaXhuUWtGQmFFSXNRMEZCYUVNc1EwRkJWaXhGUVVSR08wRkJSVVVzYTBKQlJrWTdPMEZCTDBKQkxHVkJiVU5MTEU5QlFVdzdRVUZEUlN4cFFrRkJTeXhKUVVGTUxFTkJRVlVzVDBGQlR5eFpRVUZRTEVOQlFXOUNMRXRCUVhCQ0xFTkJRVEJDTEVsQlFURkNMRVZCUVdkRExFbEJRVWtzVjBGQlNpeERRVUZuUWl4blFrRkJhRUlzUTBGQmFFTXNRMEZCVml4RlFVUkdPMEZCUlVVc2EwSkJSa1k3TzBGQmJrTkJPMEZCZDBORkxHMUNRVUZQTEV0QlFWQXNRMEZFUmp0QlFYWkRRU3hUUVVRNFF6dFBRVUZvUkN4TlFUSkRUU3hKUVVGSExFTkJRVU1zV1VGQldTeG5Ra0ZCV2l4RlFVRTRRaXg1UWtGQk9VSXNRMEZCUkN4RlFVRXlSRHRCUVVOc1JTeGxRVUZQTEV0QlFWQXNRMEZFYTBVN1QwRkJPVVE3TzBGQlNVNHNkVUpCUVdsQ0xHbENRVUZwUWl4SlFVRnFRaXhEUVhSRk1FSTdTMEZCTjBNN08wRkJlVVZCTEZkQlFVOHNTVUZCVUN4RFFYaEdjVVE3UjBGQmFFUXNRMEZrTUVRN1EwRkJia1U3TzBGQk1rZEJMRk5CUVZNc1QwRkJWQ3hEUVVGcFFpeEpRVUZxUWl4RlFVRjFRaXhKUVVGMlFpeEZRVUUwUWp0QlFVTXhRaXhUUVVGUExFbEJRVU1zUjBGQlR5eEpRVUZRTEVkQlFXVXNRMEZCYUVJc1EwRkViVUk3UTBGQk5VSTdPMEZCU1VFc1UwRkJVeXhYUVVGVUxFTkJRWEZDTEVOQlFYSkNMRVZCUVhkQ0xFTkJRWGhDTEVWQlFUSkNPMEZCUTNwQ0xFMUJRVWtzVFVGQlRTeERRVUZPTEVWQlFWTXNUMEZCVHl4SlFVRlFMRU5CUVdJN1FVRkRRU3hOUVVGSkxFdEJRVXNzU1VGQlRDeEpRVUZoTEV0QlFVc3NTVUZCVEN4RlFVRlhMRTlCUVU4c1MwRkJVQ3hEUVVFMVFqdEJRVU5CTEUxQlFVa3NSVUZCUlN4TlFVRkdMRWxCUVZrc1JVRkJSU3hOUVVGR0xFVkJRVlVzVDBGQlR5eExRVUZRTEVOQlFURkNPenRCUVVWQkxFOUJRVXNzU1VGQlNTeEpRVUZKTEVOQlFVb3NSVUZCVHl4SlFVRkpMRVZCUVVVc1RVRkJSaXhGUVVGVkxFVkJRVVVzUTBGQlJpeEZRVUZMTzBGQlEycERMRkZCUVVrc1JVRkJSU3hEUVVGR0xFMUJRVk1zUlVGQlJTeERRVUZHTEVOQlFWUXNSVUZCWlN4UFFVRlBMRXRCUVZBc1EwRkJia0k3UjBGRVJqczdRVUZKUVN4VFFVRlBMRWxCUVZBc1EwRlVlVUk3UTBGQk0wSTdPMEZCV1VFc1UwRkJVeXhUUVVGVUxFTkJRVzFDTEVkQlFXNUNMRVZCUVhkQ0xFZEJRWGhDTEVWQlFUUkNPMEZCUXpGQ0xFOUJRVWtzU1VGQlNTeEpRVUZKTEVOQlFVb3NSVUZCVHl4SlFVRkpMRWRCUVVvc1JVRkJVeXhIUVVGNFFpeEZRVUUwUWp0QlFVTXhRaXhSUVVGSkxFbEJRVW9zUTBGQlV5eERRVUZVTEVWQlJEQkNPMGRCUVRWQ08wTkJSRVk3TzBGQlRVRXNVMEZCVXl4bFFVRlVMRU5CUVhsQ0xFZEJRWHBDTEVWQlFUWkNPMEZCUXpOQ0xFMUJRVWtzWlVGQlpTeEpRVUZKTEVkQlFVb3NRMEZCVVN4UlFVRlZMRlZCUVZVc1QwRkJWaXhEUVVGclFpeEpRVUZzUWl4RFFVRldMRU5CUVhaQ0xFTkJSSFZDTzBGQlJUTkNMRk5CUVU4c1NVRkJTU3hUUVVGS0xFTkJRV01zUjBGQlJ5eFpRVUZJTEVOQlFYSkNMRU5CUmpKQ08wTkJRVGRDT3p0QlFVdEJMRk5CUVZNc1kwRkJWQ3hIUVVGdlF6dEJRVU5zUXl4VFFVRlBMRmxCUVc5Q08wRkJRM3BDTEZkQlFVOHNTMEZCVUN4RFFVUjVRanRIUVVGd1FpeERRVVF5UWp0RFFVRndRenM3UVVGTlFTeGxRVUZsTzBGQlEySXNZMEZFWVR0QlFVVmlMR2xDUVVaaE8wRkJSMklzYVVKQlNHRTdRVUZKWWl4cFFrRktZVHRCUVV0aUxHZENRVXhoTzBGQlRXSXNiVUpCVG1FN1FVRlBZaXhoUVZCaE8wRkJVV0lzWTBGU1lUdEJRVk5pTEdWQlZHRTdRVUZWWWl4blFrRldZVHRCUVZkaUxHVkJXR0U3UVVGWllpeGxRVnBoTzBGQllXSXNaVUZpWVR0QlFXTmlMR2RDUVdSaE8wRkJaV0lzYVVKQlptRTdRVUZuUW1Jc1lVRm9RbUU3UVVGcFFtSXNhMEpCYWtKaE8wTkJRV1lpTENKbWFXeGxJam9pYkdsaUwyTnZjbVV2Y0dGMGRHVnlibk12Y21WemIyeDJaWEp6TG1weklpd2ljMjkxY21ObGMwTnZiblJsYm5RaU9sc2lMeW9nUUdac2IzY2dLaTljYmx4dWFXMXdiM0owSUVOb1pXTnJjeUJtY205dElGd2lMaTlqYUdWamEzTmNJanRjYm1sdGNHOXlkQ0FxSUdGeklGUjVjR1Z6SUdaeWIyMGdYQ0l1TDNSNWNHVnpYQ0k3WEc1cGJYQnZjblFnZXlCaWRXbHNaRTFoZEdOb0lIMGdabkp2YlNCY0lpNHZiV0YwWTJoY0lqdGNibWx0Y0c5eWRDQkNhWFJUZEhKcGJtY2dabkp2YlNCY0lpNHVMMkpwZEY5emRISnBibWRjSWp0Y2JseHVablZ1WTNScGIyNGdjbVZ6YjJ4MlpWTjViV0p2YkNod1lYUjBaWEp1T2lCaGJua3BPaUJHZFc1amRHbHZiaUI3WEc0Z0lISmxkSFZ5YmlCbWRXNWpkR2x2YmloMllXeDFaVG9nWVc1NUtUb2dZbTl2YkdWaGJpQjdYRzRnSUNBZ2NtVjBkWEp1SUVOb1pXTnJjeTVwYzE5emVXMWliMndvZG1Gc2RXVXBJQ1ltSUhaaGJIVmxJRDA5UFNCd1lYUjBaWEp1TzF4dUlDQjlPMXh1ZlZ4dVhHNW1kVzVqZEdsdmJpQnlaWE52YkhabFUzUnlhVzVuS0hCaGRIUmxjbTQ2SUdGdWVTazZJRVoxYm1OMGFXOXVJSHRjYmlBZ2NtVjBkWEp1SUdaMWJtTjBhVzl1S0haaGJIVmxPaUJoYm5rcE9pQmliMjlzWldGdUlIdGNiaUFnSUNCeVpYUjFjbTRnUTJobFkydHpMbWx6WDNOMGNtbHVaeWgyWVd4MVpTa2dKaVlnZG1Gc2RXVWdQVDA5SUhCaGRIUmxjbTQ3WEc0Z0lIMDdYRzU5WEc1Y2JtWjFibU4wYVc5dUlISmxjMjlzZG1WT2RXMWlaWElvY0dGMGRHVnliam9nWVc1NUtUb2dSblZ1WTNScGIyNGdlMXh1SUNCeVpYUjFjbTRnWm5WdVkzUnBiMjRvZG1Gc2RXVTZJR0Z1ZVNrNklHSnZiMnhsWVc0Z2UxeHVJQ0FnSUhKbGRIVnliaUJEYUdWamEzTXVhWE5mYm5WdFltVnlLSFpoYkhWbEtTQW1KaUIyWVd4MVpTQTlQVDBnY0dGMGRHVnlianRjYmlBZ2ZUdGNibjFjYmx4dVpuVnVZM1JwYjI0Z2NtVnpiMngyWlVKdmIyeGxZVzRvY0dGMGRHVnliam9nWVc1NUtUb2dSblZ1WTNScGIyNGdlMXh1SUNCeVpYUjFjbTRnWm5WdVkzUnBiMjRvZG1Gc2RXVTZJR0Z1ZVNrNklHSnZiMnhsWVc0Z2UxeHVJQ0FnSUhKbGRIVnliaUJEYUdWamEzTXVhWE5mWW05dmJHVmhiaWgyWVd4MVpTa2dKaVlnZG1Gc2RXVWdQVDA5SUhCaGRIUmxjbTQ3WEc0Z0lIMDdYRzU5WEc1Y2JtWjFibU4wYVc5dUlISmxjMjlzZG1WR2RXNWpkR2x2Ymlod1lYUjBaWEp1T2lCaGJua3BPaUJHZFc1amRHbHZiaUI3WEc0Z0lISmxkSFZ5YmlCbWRXNWpkR2x2YmloMllXeDFaVG9nWVc1NUtUb2dZbTl2YkdWaGJpQjdYRzRnSUNBZ2NtVjBkWEp1SUVOb1pXTnJjeTVwYzE5bWRXNWpkR2x2YmloMllXeDFaU2tnSmlZZ2RtRnNkV1VnUFQwOUlIQmhkSFJsY200N1hHNGdJSDA3WEc1OVhHNWNibVoxYm1OMGFXOXVJSEpsYzI5c2RtVk9kV3hzS0hCaGRIUmxjbTQ2SUdGdWVTazZJRVoxYm1OMGFXOXVJSHRjYmlBZ2NtVjBkWEp1SUdaMWJtTjBhVzl1S0haaGJIVmxPaUJoYm5rcE9pQmliMjlzWldGdUlIdGNiaUFnSUNCeVpYUjFjbTRnUTJobFkydHpMbWx6WDI1MWJHd29kbUZzZFdVcE8xeHVJQ0I5TzF4dWZWeHVYRzVtZFc1amRHbHZiaUJ5WlhOdmJIWmxRbTkxYm1Rb2NHRjBkR1Z5YmpvZ1ZIbHdaWE11UW05MWJtUXBPaUJHZFc1amRHbHZiaUI3WEc0Z0lISmxkSFZ5YmlCbWRXNWpkR2x2YmloMllXeDFaVG9nWVc1NUxDQmhjbWR6T2lCQmNuSmhlVHhoYm5rK0tUb2dZbTl2YkdWaGJpQjdYRzRnSUNBZ2FXWW9kSGx3Wlc5bUlIWmhiSFZsSUQwOVBTQjBlWEJsYjJZZ2NHRjBkR1Z5Ymk1MllXeDFaU0FtSmlCMllXeDFaU0E5UFQwZ2NHRjBkR1Z5Ymk1MllXeDFaU2w3WEc0Z0lDQWdJQ0JoY21kekxuQjFjMmdvZG1Gc2RXVXBPMXh1SUNBZ0lDQWdjbVYwZFhKdUlIUnlkV1U3WEc0Z0lDQWdmVnh1WEc0Z0lDQWdjbVYwZFhKdUlHWmhiSE5sTzF4dUlDQjlPMXh1ZlZ4dVhHNW1kVzVqZEdsdmJpQnlaWE52YkhabFYybHNaR05oY21Rb0tUb2dSblZ1WTNScGIyNGdlMXh1SUNCeVpYUjFjbTRnWm5WdVkzUnBiMjRvS1RvZ1ltOXZiR1ZoYmlCN1hHNGdJQ0FnY21WMGRYSnVJSFJ5ZFdVN1hHNGdJSDA3WEc1OVhHNWNibVoxYm1OMGFXOXVJSEpsYzI5c2RtVldZWEpwWVdKc1pTZ3BPaUJHZFc1amRHbHZiaUI3WEc0Z0lISmxkSFZ5YmlCbWRXNWpkR2x2YmloMllXeDFaVG9nWVc1NUxDQmhjbWR6T2lCQmNuSmhlVHhoYm5rK0tUb2dZbTl2YkdWaGJpQjdYRzRnSUNBZ1lYSm5jeTV3ZFhOb0tIWmhiSFZsS1R0Y2JpQWdJQ0J5WlhSMWNtNGdkSEoxWlR0Y2JpQWdmVHRjYm4xY2JseHVablZ1WTNScGIyNGdjbVZ6YjJ4MlpVaGxZV1JVWVdsc0tIQmhkSFJsY200NklGUjVjR1Z6TGtobFlXUlVZV2xzS1RvZ1JuVnVZM1JwYjI0Z2UxeHVJQ0JqYjI1emRDQm9aV0ZrVFdGMFkyaGxjeUE5SUdKMWFXeGtUV0YwWTJnb2NHRjBkR1Z5Ymk1b1pXRmtLVHRjYmlBZ1kyOXVjM1FnZEdGcGJFMWhkR05vWlhNZ1BTQmlkV2xzWkUxaGRHTm9LSEJoZEhSbGNtNHVkR0ZwYkNrN1hHNWNiaUFnY21WMGRYSnVJR1oxYm1OMGFXOXVLSFpoYkhWbE9pQmhibmtzSUdGeVozTTZJRUZ5Y21GNVBHRnVlVDRwT2lCaWIyOXNaV0Z1SUh0Y2JpQWdJQ0JwWmlnaFEyaGxZMnR6TG1selgyRnljbUY1S0haaGJIVmxLU0I4ZkNCMllXeDFaUzVzWlc1bmRHZ2dQQ0F5S1h0Y2JpQWdJQ0FnSUhKbGRIVnliaUJtWVd4elpUdGNiaUFnSUNCOVhHNWNiaUFnSUNCamIyNXpkQ0JvWldGa0lEMGdkbUZzZFdWYk1GMDdYRzRnSUNBZ1kyOXVjM1FnZEdGcGJDQTlJSFpoYkhWbExuTnNhV05sS0RFcE8xeHVYRzRnSUNBZ2FXWW9hR1ZoWkUxaGRHTm9aWE1vYUdWaFpDd2dZWEpuY3lrZ0ppWWdkR0ZwYkUxaGRHTm9aWE1vZEdGcGJDd2dZWEpuY3lrcGUxeHVJQ0FnSUNBZ2NtVjBkWEp1SUhSeWRXVTdYRzRnSUNBZ2ZWeHVJQ0I5TzF4dWZWeHVYRzVtZFc1amRHbHZiaUJ5WlhOdmJIWmxRMkZ3ZEhWeVpTaHdZWFIwWlhKdU9pQlVlWEJsY3k1RFlYQjBkWEpsS1RvZ1JuVnVZM1JwYjI0Z2UxeHVJQ0JqYjI1emRDQnRZWFJqYUdWeklEMGdZblZwYkdSTllYUmphQ2h3WVhSMFpYSnVMblpoYkhWbEtUdGNibHh1SUNCeVpYUjFjbTRnWm5WdVkzUnBiMjRvZG1Gc2RXVTZJR0Z1ZVN3Z1lYSm5jem9nUVhKeVlYazhZVzU1UGlrNklHSnZiMnhsWVc0Z2UxeHVJQ0FnSUdsbUtHMWhkR05vWlhNb2RtRnNkV1VzSUdGeVozTXBLWHRjYmlBZ0lDQWdJR0Z5WjNNdWNIVnphQ2gyWVd4MVpTazdYRzRnSUNBZ0lDQnlaWFIxY200Z2RISjFaVHRjYmlBZ0lDQjlYRzVjYmlBZ0lDQnlaWFIxY200Z1ptRnNjMlU3WEc0Z0lIMDdYRzU5WEc1Y2JtWjFibU4wYVc5dUlISmxjMjlzZG1WVGRHRnlkSE5YYVhSb0tIQmhkSFJsY200NklGUjVjR1Z6TGxOMFlYSjBjMWRwZEdncE9pQkdkVzVqZEdsdmJpQjdYRzRnSUdOdmJuTjBJSEJ5WldacGVDQTlJSEJoZEhSbGNtNHVjSEpsWm1sNE8xeHVYRzRnSUhKbGRIVnliaUJtZFc1amRHbHZiaWgyWVd4MVpUb2dZVzU1TENCaGNtZHpPaUJCY25KaGVUeGhibmsrS1RvZ1ltOXZiR1ZoYmlCN1hHNGdJQ0FnYVdZb1EyaGxZMnR6TG1selgzTjBjbWx1WnloMllXeDFaU2tnSmlZZ2RtRnNkV1V1YzNSaGNuUnpWMmwwYUNod2NtVm1hWGdwS1h0Y2JpQWdJQ0FnSUdGeVozTXVjSFZ6YUNoMllXeDFaUzV6ZFdKemRISnBibWNvY0hKbFptbDRMbXhsYm1kMGFDa3BPMXh1SUNBZ0lDQWdjbVYwZFhKdUlIUnlkV1U3WEc0Z0lDQWdmVnh1WEc0Z0lDQWdjbVYwZFhKdUlHWmhiSE5sTzF4dUlDQjlPMXh1ZlZ4dVhHNW1kVzVqZEdsdmJpQnlaWE52YkhabFZIbHdaU2h3WVhSMFpYSnVPaUJVZVhCbGN5NVVlWEJsS1RvZ1JuVnVZM1JwYjI0Z2UxeHVJQ0J5WlhSMWNtNGdablZ1WTNScGIyNG9kbUZzZFdVNklHRnVlU3dnWVhKbmN6b2dRWEp5WVhrOFlXNTVQaWs2SUdKdmIyeGxZVzRnZTF4dUlDQWdJR2xtS0haaGJIVmxJR2x1YzNSaGJtTmxiMllnY0dGMGRHVnliaTUwZVhCbEtYdGNiaUFnSUNBZ0lHTnZibk4wSUcxaGRHTm9aWE1nUFNCaWRXbHNaRTFoZEdOb0tIQmhkSFJsY200dWIySnFVR0YwZEdWeWJpazdYRzRnSUNBZ0lDQnlaWFIxY200Z2JXRjBZMmhsY3loMllXeDFaU3dnWVhKbmN5a2dKaVlnWVhKbmN5NXdkWE5vS0haaGJIVmxLU0ErSURBN1hHNGdJQ0FnZlZ4dVhHNGdJQ0FnY21WMGRYSnVJR1poYkhObE8xeHVJQ0I5TzF4dWZWeHVYRzVtZFc1amRHbHZiaUJ5WlhOdmJIWmxRWEp5WVhrb2NHRjBkR1Z5YmpvZ1FYSnlZWGs4WVc1NVBpazZJRVoxYm1OMGFXOXVJSHRjYmlBZ1kyOXVjM1FnYldGMFkyaGxjeUE5SUhCaGRIUmxjbTR1YldGd0tIZ2dQVDRnWW5WcGJHUk5ZWFJqYUNoNEtTazdYRzVjYmlBZ2NtVjBkWEp1SUdaMWJtTjBhVzl1S0haaGJIVmxPaUJoYm5rc0lHRnlaM002SUVGeWNtRjVQR0Z1ZVQ0cE9pQmliMjlzWldGdUlIdGNiaUFnSUNCcFppZ2hRMmhsWTJ0ekxtbHpYMkZ5Y21GNUtIWmhiSFZsS1NCOGZDQjJZV3gxWlM1c1pXNW5kR2dnSVQwZ2NHRjBkR1Z5Ymk1c1pXNW5kR2dwZTF4dUlDQWdJQ0FnY21WMGRYSnVJR1poYkhObE8xeHVJQ0FnSUgxY2JseHVJQ0FnSUhKbGRIVnliaUIyWVd4MVpTNWxkbVZ5ZVNobWRXNWpkR2x2YmloMkxDQnBLU0I3WEc0Z0lDQWdJQ0J5WlhSMWNtNGdiV0YwWTJobGMxdHBYU2gyWVd4MVpWdHBYU3dnWVhKbmN5azdYRzRnSUNBZ2ZTazdYRzRnSUgwN1hHNTlYRzVjYm1aMWJtTjBhVzl1SUhKbGMyOXNkbVZQWW1wbFkzUW9jR0YwZEdWeWJqb2dUMkpxWldOMEtUb2dSblZ1WTNScGIyNGdlMXh1SUNCc1pYUWdiV0YwWTJobGN5QTlJSHQ5TzF4dVhHNGdJR1p2Y2loc1pYUWdhMlY1SUc5bUlFOWlhbVZqZEM1clpYbHpLSEJoZEhSbGNtNHBMbU52Ym1OaGRDaFBZbXBsWTNRdVoyVjBUM2R1VUhKdmNHVnlkSGxUZVcxaWIyeHpLSEJoZEhSbGNtNHBLU2w3WEc0Z0lDQWdiV0YwWTJobGMxdHJaWGxkSUQwZ1luVnBiR1JOWVhSamFDaHdZWFIwWlhKdVcydGxlVjBwTzF4dUlDQjlYRzVjYmlBZ2NtVjBkWEp1SUdaMWJtTjBhVzl1S0haaGJIVmxPaUJoYm5rc0lHRnlaM002SUVGeWNtRjVQR0Z1ZVQ0cE9pQmliMjlzWldGdUlIdGNiaUFnSUNCcFppZ2hRMmhsWTJ0ekxtbHpYMjlpYW1WamRDaDJZV3gxWlNrZ2ZId2djR0YwZEdWeWJpNXNaVzVuZEdnZ1BpQjJZV3gxWlM1c1pXNW5kR2dwZTF4dUlDQWdJQ0FnY21WMGRYSnVJR1poYkhObE8xeHVJQ0FnSUgxY2JseHVJQ0FnSUdadmNpaHNaWFFnYTJWNUlHOW1JRTlpYW1WamRDNXJaWGx6S0hCaGRIUmxjbTRwTG1OdmJtTmhkQ2hQWW1wbFkzUXVaMlYwVDNkdVVISnZjR1Z5ZEhsVGVXMWliMnh6S0hCaGRIUmxjbTRwS1NsN1hHNGdJQ0FnSUNCcFppZ2hLR3RsZVNCcGJpQjJZV3gxWlNrZ2ZId2dJVzFoZEdOb1pYTmJhMlY1WFNoMllXeDFaVnRyWlhsZExDQmhjbWR6S1NBcGUxeHVJQ0FnSUNBZ0lDQnlaWFIxY200Z1ptRnNjMlU3WEc0Z0lDQWdJQ0I5WEc0Z0lDQWdmVnh1WEc0Z0lDQWdjbVYwZFhKdUlIUnlkV1U3WEc0Z0lIMDdYRzU5WEc1Y2JtWjFibU4wYVc5dUlISmxjMjlzZG1WQ2FYUlRkSEpwYm1jb2NHRjBkR1Z5YmpvZ1ZIbHdaWE11UW1sMFUzUnlhVzVuVFdGMFkyZ3BPaUJHZFc1amRHbHZiaUI3WEc0Z0lHeGxkQ0J3WVhSMFpYSnVRbWwwVTNSeWFXNW5JRDBnVzEwN1hHNWNiaUFnWm05eUtHeGxkQ0JpYVhSemRISnBibWROWVhSamFGQmhjblFnYjJZZ2NHRjBkR1Z5Ymk1MllXeDFaWE1wZTF4dUlDQWdJR2xtS0VOb1pXTnJjeTVwYzE5MllYSnBZV0pzWlNoaWFYUnpkSEpwYm1kTllYUmphRkJoY25RdWRtRnNkV1VwS1h0Y2JpQWdJQ0FnSUd4bGRDQnphWHBsSUQwZ1oyVjBVMmw2WlNoaWFYUnpkSEpwYm1kTllYUmphRkJoY25RdWRXNXBkQ3dnWW1sMGMzUnlhVzVuVFdGMFkyaFFZWEowTG5OcGVtVXBPMXh1SUNBZ0lDQWdabWxzYkVGeWNtRjVLSEJoZEhSbGNtNUNhWFJUZEhKcGJtY3NJSE5wZW1VcE8xeHVJQ0FnSUgxbGJITmxlMXh1SUNBZ0lDQWdjR0YwZEdWeWJrSnBkRk4wY21sdVp5QTlJSEJoZEhSbGNtNUNhWFJUZEhKcGJtY3VZMjl1WTJGMEtHNWxkeUJDYVhSVGRISnBibWNvWW1sMGMzUnlhVzVuVFdGMFkyaFFZWEowS1M1MllXeDFaU2s3WEc0Z0lDQWdmVnh1SUNCOVhHNWNiaUFnYkdWMElIQmhkSFJsY201V1lXeDFaWE1nUFNCd1lYUjBaWEp1TG5aaGJIVmxjenRjYmx4dUlDQnlaWFIxY200Z1puVnVZM1JwYjI0b2RtRnNkV1U2SUdGdWVTd2dZWEpuY3pvZ1FYSnlZWGs4WVc1NVBpazZJR0p2YjJ4bFlXNGdlMXh1SUNBZ0lHeGxkQ0JpYzFaaGJIVmxJRDBnYm5Wc2JEdGNibHh1SUNBZ0lHbG1LQ0ZEYUdWamEzTXVhWE5mYzNSeWFXNW5LSFpoYkhWbEtTQW1KaUFoS0haaGJIVmxJR2x1YzNSaGJtTmxiMllnUW1sMFUzUnlhVzVuS1NBcGUxeHVJQ0FnSUNBZ2NtVjBkWEp1SUdaaGJITmxPMXh1SUNBZ0lIMWNibHh1SUNBZ0lHbG1LRU5vWldOcmN5NXBjMTl6ZEhKcGJtY29kbUZzZFdVcEtYdGNiaUFnSUNBZ0lHSnpWbUZzZFdVZ1BTQnVaWGNnUW1sMFUzUnlhVzVuS0VKcGRGTjBjbWx1Wnk1aWFXNWhjbmtvZG1Gc2RXVXBLVHRjYmlBZ0lDQjlaV3h6Wlh0Y2JpQWdJQ0FnSUdKelZtRnNkV1VnUFNCMllXeDFaVHRjYmlBZ0lDQjlYRzVjYmlBZ0lDQnNaWFFnWW1WbmFXNXVhVzVuU1c1a1pYZ2dQU0F3TzF4dVhHNGdJQ0FnWm05eUtHeGxkQ0JwSUQwZ01Ec2dhU0E4SUhCaGRIUmxjbTVXWVd4MVpYTXViR1Z1WjNSb095QnBLeXNwZTF4dUlDQWdJQ0FnYkdWMElHSnBkSE4wY21sdVowMWhkR05vVUdGeWRDQTlJSEJoZEhSbGNtNVdZV3gxWlhOYmFWMDdYRzVjYmlBZ0lDQWdJR2xtS0VOb1pXTnJjeTVwYzE5MllYSnBZV0pzWlNoaWFYUnpkSEpwYm1kTllYUmphRkJoY25RdWRtRnNkV1VwSUNZbVhHNGdJQ0FnSUNBZ0lDQmlhWFJ6ZEhKcGJtZE5ZWFJqYUZCaGNuUXVkSGx3WlNBOVBTQW5ZbWx1WVhKNUp5QW1KbHh1SUNBZ0lDQWdJQ0FnWW1sMGMzUnlhVzVuVFdGMFkyaFFZWEowTG5OcGVtVWdQVDA5SUhWdVpHVm1hVzVsWkNBbUpseHVJQ0FnSUNBZ0lDQWdhU0E4SUhCaGRIUmxjbTVXWVd4MVpYTXViR1Z1WjNSb0lDMGdNU2w3WEc0Z0lDQWdJQ0FnSUhSb2NtOTNJRzVsZHlCRmNuSnZjaWhjSW1FZ1ltbHVZWEo1SUdacFpXeGtJSGRwZEdodmRYUWdjMmw2WlNCcGN5QnZibXg1SUdGc2JHOTNaV1FnWVhRZ2RHaGxJR1Z1WkNCdlppQmhJR0pwYm1GeWVTQndZWFIwWlhKdVhDSXBPMXh1SUNBZ0lDQWdmVnh1WEc0Z0lDQWdJQ0JzWlhRZ2MybDZaU0E5SURBN1hHNGdJQ0FnSUNCc1pYUWdZbk5XWVd4MVpVRnljbUY1VUdGeWRDQTlJRnRkTzF4dUlDQWdJQ0FnYkdWMElIQmhkSFJsY201Q2FYUlRkSEpwYm1kQmNuSmhlVkJoY25RZ1BTQmJYVHRjYmlBZ0lDQWdJSE5wZW1VZ1BTQm5aWFJUYVhwbEtHSnBkSE4wY21sdVowMWhkR05vVUdGeWRDNTFibWwwTENCaWFYUnpkSEpwYm1kTllYUmphRkJoY25RdWMybDZaU2s3WEc1Y2JpQWdJQ0FnSUdsbUtHa2dQVDA5SUhCaGRIUmxjbTVXWVd4MVpYTXViR1Z1WjNSb0lDMGdNU2w3WEc0Z0lDQWdJQ0FnSUdKelZtRnNkV1ZCY25KaGVWQmhjblFnUFNCaWMxWmhiSFZsTG5aaGJIVmxMbk5zYVdObEtHSmxaMmx1Ym1sdVowbHVaR1Y0S1R0Y2JpQWdJQ0FnSUNBZ2NHRjBkR1Z5YmtKcGRGTjBjbWx1WjBGeWNtRjVVR0Z5ZENBOUlIQmhkSFJsY201Q2FYUlRkSEpwYm1jdWMyeHBZMlVvWW1WbmFXNXVhVzVuU1c1a1pYZ3BPMXh1SUNBZ0lDQWdmU0JsYkhObElIdGNiaUFnSUNBZ0lDQWdZbk5XWVd4MVpVRnljbUY1VUdGeWRDQTlJR0p6Vm1Gc2RXVXVkbUZzZFdVdWMyeHBZMlVvWW1WbmFXNXVhVzVuU1c1a1pYZ3NJR0psWjJsdWJtbHVaMGx1WkdWNElDc2djMmw2WlNrN1hHNGdJQ0FnSUNBZ0lIQmhkSFJsY201Q2FYUlRkSEpwYm1kQmNuSmhlVkJoY25RZ1BTQndZWFIwWlhKdVFtbDBVM1J5YVc1bkxuTnNhV05sS0dKbFoybHVibWx1WjBsdVpHVjRMQ0JpWldkcGJtNXBibWRKYm1SbGVDQXJJSE5wZW1VcE8xeHVJQ0FnSUNBZ2ZWeHVYRzRnSUNBZ0lDQnBaaWhEYUdWamEzTXVhWE5mZG1GeWFXRmliR1VvWW1sMGMzUnlhVzVuVFdGMFkyaFFZWEowTG5aaGJIVmxLU2w3WEc0Z0lDQWdJQ0FnSUhOM2FYUmphQ2hpYVhSemRISnBibWROWVhSamFGQmhjblF1ZEhsd1pTa2dlMXh1SUNBZ0lDQWdJQ0JqWVhObElDZHBiblJsWjJWeUp6cGNiaUFnSUNBZ0lDQWdJQ0JwWmloaWFYUnpkSEpwYm1kTllYUmphRkJoY25RdVlYUjBjbWxpZFhSbGN5QW1KaUJpYVhSemRISnBibWROWVhSamFGQmhjblF1WVhSMGNtbGlkWFJsY3k1cGJtUmxlRTltS0Z3aWMybG5ibVZrWENJcElDRTlJQzB4S1h0Y2JpQWdJQ0FnSUNBZ0lDQWdJR0Z5WjNNdWNIVnphQ2h1WlhjZ1NXNTBPRUZ5Y21GNUtGdGljMVpoYkhWbFFYSnlZWGxRWVhKMFd6QmRYU2xiTUYwcE8xeHVJQ0FnSUNBZ0lDQWdJSDBnWld4elpTQjdYRzRnSUNBZ0lDQWdJQ0FnSUNCaGNtZHpMbkIxYzJnb2JtVjNJRlZwYm5RNFFYSnlZWGtvVzJKelZtRnNkV1ZCY25KaGVWQmhjblJiTUYxZEtWc3dYU2s3WEc0Z0lDQWdJQ0FnSUNBZ2ZWeHVJQ0FnSUNBZ0lDQWdJR0p5WldGck8xeHVYRzRnSUNBZ0lDQWdJR05oYzJVZ0oyWnNiMkYwSnpwY2JpQWdJQ0FnSUNBZ0lDQnBaaWh6YVhwbElEMDlQU0EyTkNsN1hHNGdJQ0FnSUNBZ0lDQWdJQ0JoY21kekxuQjFjMmdvUm14dllYUTJORUZ5Y21GNUxtWnliMjBvWW5OV1lXeDFaVUZ5Y21GNVVHRnlkQ2xiTUYwcE8xeHVJQ0FnSUNBZ0lDQWdJSDBnWld4elpTQnBaaWh6YVhwbElEMDlQU0F6TWlsN1hHNGdJQ0FnSUNBZ0lDQWdJQ0JoY21kekxuQjFjMmdvUm14dllYUXpNa0Z5Y21GNUxtWnliMjBvWW5OV1lXeDFaVUZ5Y21GNVVHRnlkQ2xiTUYwcE8xeHVJQ0FnSUNBZ0lDQWdJSDFsYkhObGUxeHVJQ0FnSUNBZ0lDQWdJQ0FnY21WMGRYSnVJR1poYkhObE8xeHVJQ0FnSUNBZ0lDQWdJSDFjYmlBZ0lDQWdJQ0FnSUNCaWNtVmhhenRjYmx4dUlDQWdJQ0FnSUNCallYTmxJQ2RpYVhSemRISnBibWNuT2x4dUlDQWdJQ0FnSUNBZ0lHRnlaM011Y0hWemFDaGpjbVZoZEdWQ2FYUlRkSEpwYm1jb1luTldZV3gxWlVGeWNtRjVVR0Z5ZENrcE8xeHVJQ0FnSUNBZ0lDQWdJR0p5WldGck8xeHVYRzRnSUNBZ0lDQWdJR05oYzJVZ0oySnBibUZ5ZVNjNlhHNGdJQ0FnSUNBZ0lDQWdZWEpuY3k1d2RYTm9LRk4wY21sdVp5NW1jbTl0UTJoaGNrTnZaR1V1WVhCd2JIa29iblZzYkN3Z2JtVjNJRlZwYm5RNFFYSnlZWGtvWW5OV1lXeDFaVUZ5Y21GNVVHRnlkQ2twS1R0Y2JpQWdJQ0FnSUNBZ0lDQmljbVZoYXp0Y2JseHVJQ0FnSUNBZ0lDQmpZWE5sSUNkMWRHWTRKenBjYmlBZ0lDQWdJQ0FnSUNCaGNtZHpMbkIxYzJnb1UzUnlhVzVuTG1aeWIyMURhR0Z5UTI5a1pTNWhjSEJzZVNodWRXeHNMQ0J1WlhjZ1ZXbHVkRGhCY25KaGVTaGljMVpoYkhWbFFYSnlZWGxRWVhKMEtTa3BPMXh1SUNBZ0lDQWdJQ0FnSUdKeVpXRnJPMXh1WEc0Z0lDQWdJQ0FnSUdOaGMyVWdKM1YwWmpFMkp6cGNiaUFnSUNBZ0lDQWdJQ0JoY21kekxuQjFjMmdvVTNSeWFXNW5MbVp5YjIxRGFHRnlRMjlrWlM1aGNIQnNlU2h1ZFd4c0xDQnVaWGNnVldsdWRERTJRWEp5WVhrb1luTldZV3gxWlVGeWNtRjVVR0Z5ZENrcEtUdGNiaUFnSUNBZ0lDQWdJQ0JpY21WaGF6dGNibHh1SUNBZ0lDQWdJQ0JqWVhObElDZDFkR1l6TWljNlhHNGdJQ0FnSUNBZ0lDQWdZWEpuY3k1d2RYTm9LRk4wY21sdVp5NW1jbTl0UTJoaGNrTnZaR1V1WVhCd2JIa29iblZzYkN3Z2JtVjNJRlZwYm5Rek1rRnljbUY1S0dKelZtRnNkV1ZCY25KaGVWQmhjblFwS1NrN1hHNGdJQ0FnSUNBZ0lDQWdZbkpsWVdzN1hHNWNiaUFnSUNBZ0lDQWdaR1ZtWVhWc2REcGNiaUFnSUNBZ0lDQWdJQ0J5WlhSMWNtNGdabUZzYzJVN1hHNGdJQ0FnSUNBZ0lIMWNiaUFnSUNBZ0lIMWxiSE5sSUdsbUtDRmhjbkpoZVhORmNYVmhiQ2hpYzFaaGJIVmxRWEp5WVhsUVlYSjBMQ0J3WVhSMFpYSnVRbWwwVTNSeWFXNW5RWEp5WVhsUVlYSjBLU2tnZTF4dUlDQWdJQ0FnSUNCeVpYUjFjbTRnWm1Gc2MyVTdYRzRnSUNBZ0lDQjlYRzVjYmlBZ0lDQWdJR0psWjJsdWJtbHVaMGx1WkdWNElEMGdZbVZuYVc1dWFXNW5TVzVrWlhnZ0t5QnphWHBsTzF4dUlDQWdJSDFjYmx4dUlDQWdJSEpsZEhWeWJpQjBjblZsTzF4dUlDQjlYRzVjYm4xY2JseHVablZ1WTNScGIyNGdaMlYwVTJsNlpTaDFibWwwTENCemFYcGxLWHRjYmlBZ2NtVjBkWEp1SUNoMWJtbDBJQ29nYzJsNlpTa2dMeUE0TzF4dWZWeHVYRzVtZFc1amRHbHZiaUJoY25KaGVYTkZjWFZoYkNoaExDQmlLU0I3WEc0Z0lHbG1JQ2hoSUQwOVBTQmlLU0J5WlhSMWNtNGdkSEoxWlR0Y2JpQWdhV1lnS0dFZ1BUMGdiblZzYkNCOGZDQmlJRDA5SUc1MWJHd3BJSEpsZEhWeWJpQm1ZV3h6WlR0Y2JpQWdhV1lnS0dFdWJHVnVaM1JvSUNFOUlHSXViR1Z1WjNSb0tTQnlaWFIxY200Z1ptRnNjMlU3WEc1Y2JpQWdabTl5SUNoMllYSWdhU0E5SURBN0lHa2dQQ0JoTG14bGJtZDBhRHNnS3l0cEtTQjdYRzRnSUNBZ2FXWWdLR0ZiYVYwZ0lUMDlJR0piYVYwcElISmxkSFZ5YmlCbVlXeHpaVHRjYmlBZ2ZWeHVYRzRnSUhKbGRIVnliaUIwY25WbE8xeHVmVnh1WEc1bWRXNWpkR2x2YmlCbWFXeHNRWEp5WVhrb1lYSnlMQ0J1ZFcwcGUxeHVJQ0JtYjNJb2JHVjBJR2tnUFNBd095QnBJRHdnYm5WdE95QnBLeXNwZTF4dUlDQWdJR0Z5Y2k1d2RYTm9LREFwTzF4dUlDQjlYRzU5WEc1Y2JtWjFibU4wYVc5dUlHTnlaV0YwWlVKcGRGTjBjbWx1WnloaGNuSXBlMXh1SUNCc1pYUWdhVzUwWldkbGNsQmhjblJ6SUQwZ1lYSnlMbTFoY0Nnb1pXeGxiU2tnUFQ0Z1FtbDBVM1J5YVc1bkxtbHVkR1ZuWlhJb1pXeGxiU2twTzF4dUlDQnlaWFIxY200Z2JtVjNJRUpwZEZOMGNtbHVaeWd1TGk1cGJuUmxaMlZ5VUdGeWRITXBPMXh1ZlZ4dVhHNW1kVzVqZEdsdmJpQnlaWE52YkhabFRtOU5ZWFJqYUNncE9pQkdkVzVqZEdsdmJpQjdYRzRnSUhKbGRIVnliaUJtZFc1amRHbHZiaWdwT2lCaWIyOXNaV0Z1SUh0Y2JpQWdJQ0J5WlhSMWNtNGdabUZzYzJVN1hHNGdJSDFjYm4xY2JseHVaWGh3YjNKMElHUmxabUYxYkhRZ2UxeHVJQ0J5WlhOdmJIWmxRbTkxYm1Rc1hHNGdJSEpsYzI5c2RtVlhhV3hrWTJGeVpDeGNiaUFnY21WemIyeDJaVlpoY21saFlteGxMRnh1SUNCeVpYTnZiSFpsU0dWaFpGUmhhV3dzWEc0Z0lISmxjMjlzZG1WRFlYQjBkWEpsTEZ4dUlDQnlaWE52YkhabFUzUmhjblJ6VjJsMGFDeGNiaUFnY21WemIyeDJaVlI1Y0dVc1hHNGdJSEpsYzI5c2RtVkJjbkpoZVN4Y2JpQWdjbVZ6YjJ4MlpVOWlhbVZqZEN4Y2JpQWdjbVZ6YjJ4MlpVNXZUV0YwWTJnc1hHNGdJSEpsYzI5c2RtVlRlVzFpYjJ3c1hHNGdJSEpsYzI5c2RtVlRkSEpwYm1jc1hHNGdJSEpsYzI5c2RtVk9kVzFpWlhJc1hHNGdJSEpsYzI5c2RtVkNiMjlzWldGdUxGeHVJQ0J5WlhOdmJIWmxSblZ1WTNScGIyNHNYRzRnSUhKbGMyOXNkbVZPZFd4c0xGeHVJQ0J5WlhOdmJIWmxRbWwwVTNSeWFXNW5YRzU5WEc0aVhTd2ljMjkxY21ObFVtOXZkQ0k2SWk5emIzVnlZMlV2SW4wPVxuIiwiXG5pbXBvcnQgQ2hlY2tzIGZyb20gXCIuL2NoZWNrc1wiO1xuaW1wb3J0IFJlc29sdmVycyBmcm9tIFwiLi9yZXNvbHZlcnNcIjtcblxuZXhwb3J0IGZ1bmN0aW9uIGJ1aWxkTWF0Y2gocGF0dGVybikge1xuXG4gIGlmIChDaGVja3MuaXNfdmFyaWFibGUocGF0dGVybikpIHtcbiAgICByZXR1cm4gUmVzb2x2ZXJzLnJlc29sdmVWYXJpYWJsZShwYXR0ZXJuKTtcbiAgfVxuXG4gIGlmIChDaGVja3MuaXNfd2lsZGNhcmQocGF0dGVybikpIHtcbiAgICByZXR1cm4gUmVzb2x2ZXJzLnJlc29sdmVXaWxkY2FyZChwYXR0ZXJuKTtcbiAgfVxuXG4gIGlmIChDaGVja3MuaXNfdW5kZWZpbmVkKHBhdHRlcm4pKSB7XG4gICAgcmV0dXJuIFJlc29sdmVycy5yZXNvbHZlV2lsZGNhcmQocGF0dGVybik7XG4gIH1cblxuICBpZiAoQ2hlY2tzLmlzX2hlYWRUYWlsKHBhdHRlcm4pKSB7XG4gICAgcmV0dXJuIFJlc29sdmVycy5yZXNvbHZlSGVhZFRhaWwocGF0dGVybik7XG4gIH1cblxuICBpZiAoQ2hlY2tzLmlzX3N0YXJ0c1dpdGgocGF0dGVybikpIHtcbiAgICByZXR1cm4gUmVzb2x2ZXJzLnJlc29sdmVTdGFydHNXaXRoKHBhdHRlcm4pO1xuICB9XG5cbiAgaWYgKENoZWNrcy5pc19jYXB0dXJlKHBhdHRlcm4pKSB7XG4gICAgcmV0dXJuIFJlc29sdmVycy5yZXNvbHZlQ2FwdHVyZShwYXR0ZXJuKTtcbiAgfVxuXG4gIGlmIChDaGVja3MuaXNfYm91bmQocGF0dGVybikpIHtcbiAgICByZXR1cm4gUmVzb2x2ZXJzLnJlc29sdmVCb3VuZChwYXR0ZXJuKTtcbiAgfVxuXG4gIGlmIChDaGVja3MuaXNfdHlwZShwYXR0ZXJuKSkge1xuICAgIHJldHVybiBSZXNvbHZlcnMucmVzb2x2ZVR5cGUocGF0dGVybik7XG4gIH1cblxuICBpZiAoQ2hlY2tzLmlzX2FycmF5KHBhdHRlcm4pKSB7XG4gICAgcmV0dXJuIFJlc29sdmVycy5yZXNvbHZlQXJyYXkocGF0dGVybik7XG4gIH1cblxuICBpZiAoQ2hlY2tzLmlzX251bWJlcihwYXR0ZXJuKSkge1xuICAgIHJldHVybiBSZXNvbHZlcnMucmVzb2x2ZU51bWJlcihwYXR0ZXJuKTtcbiAgfVxuXG4gIGlmIChDaGVja3MuaXNfc3RyaW5nKHBhdHRlcm4pKSB7XG4gICAgcmV0dXJuIFJlc29sdmVycy5yZXNvbHZlU3RyaW5nKHBhdHRlcm4pO1xuICB9XG5cbiAgaWYgKENoZWNrcy5pc19ib29sZWFuKHBhdHRlcm4pKSB7XG4gICAgcmV0dXJuIFJlc29sdmVycy5yZXNvbHZlQm9vbGVhbihwYXR0ZXJuKTtcbiAgfVxuXG4gIGlmIChDaGVja3MuaXNfc3ltYm9sKHBhdHRlcm4pKSB7XG4gICAgcmV0dXJuIFJlc29sdmVycy5yZXNvbHZlU3ltYm9sKHBhdHRlcm4pO1xuICB9XG5cbiAgaWYgKENoZWNrcy5pc19udWxsKHBhdHRlcm4pKSB7XG4gICAgcmV0dXJuIFJlc29sdmVycy5yZXNvbHZlTnVsbChwYXR0ZXJuKTtcbiAgfVxuXG4gIGlmIChDaGVja3MuaXNfYml0c3RyaW5nKHBhdHRlcm4pKSB7XG4gICAgcmV0dXJuIFJlc29sdmVycy5yZXNvbHZlQml0U3RyaW5nKHBhdHRlcm4pO1xuICB9XG5cbiAgaWYgKENoZWNrcy5pc19vYmplY3QocGF0dGVybikpIHtcbiAgICByZXR1cm4gUmVzb2x2ZXJzLnJlc29sdmVPYmplY3QocGF0dGVybik7XG4gIH1cblxuICByZXR1cm4gUmVzb2x2ZXJzLnJlc29sdmVOb01hdGNoKCk7XG59XG4vLyMgc291cmNlTWFwcGluZ1VSTD1kYXRhOmFwcGxpY2F0aW9uL2pzb247YmFzZTY0LGV5SjJaWEp6YVc5dUlqb3pMQ0p6YjNWeVkyVnpJanBiSW14cFlpOWpiM0psTDNCaGRIUmxjbTV6TDIxaGRHTm9MbXB6SWwwc0ltNWhiV1Z6SWpwYlhTd2liV0Z3Y0dsdVozTWlPaUk3UVVGRFFTeFBRVUZQTEUxQlFWQXNUVUZCYlVJc1ZVRkJia0k3UVVGRFFTeFBRVUZQTEZOQlFWQXNUVUZCYzBJc1lVRkJkRUk3TzBGQlJVRXNUMEZCVHl4VFFVRlRMRlZCUVZRc1EwRkJiMElzVDBGQmNFSXNSVUZCTkVNN08wRkJSV3BFTEUxQlFVY3NUMEZCVHl4WFFVRlFMRU5CUVcxQ0xFOUJRVzVDTEVOQlFVZ3NSVUZCSzBJN1FVRkROMElzVjBGQlR5eFZRVUZWTEdWQlFWWXNRMEZCTUVJc1QwRkJNVUlzUTBGQlVDeERRVVEyUWp0SFFVRXZRanM3UVVGSlFTeE5RVUZITEU5QlFVOHNWMEZCVUN4RFFVRnRRaXhQUVVGdVFpeERRVUZJTEVWQlFTdENPMEZCUXpkQ0xGZEJRVThzVlVGQlZTeGxRVUZXTEVOQlFUQkNMRTlCUVRGQ0xFTkJRVkFzUTBGRU5rSTdSMEZCTDBJN08wRkJTVUVzVFVGQlJ5eFBRVUZQTEZsQlFWQXNRMEZCYjBJc1QwRkJjRUlzUTBGQlNDeEZRVUZuUXp0QlFVTTVRaXhYUVVGUExGVkJRVlVzWlVGQlZpeERRVUV3UWl4UFFVRXhRaXhEUVVGUUxFTkJSRGhDTzBkQlFXaERPenRCUVVsQkxFMUJRVWNzVDBGQlR5eFhRVUZRTEVOQlFXMUNMRTlCUVc1Q0xFTkJRVWdzUlVGQkswSTdRVUZETjBJc1YwRkJUeXhWUVVGVkxHVkJRVllzUTBGQk1FSXNUMEZCTVVJc1EwRkJVQ3hEUVVRMlFqdEhRVUV2UWpzN1FVRkpRU3hOUVVGSExFOUJRVThzWVVGQlVDeERRVUZ4UWl4UFFVRnlRaXhEUVVGSUxFVkJRV2xETzBGQlF5OUNMRmRCUVU4c1ZVRkJWU3hwUWtGQlZpeERRVUUwUWl4UFFVRTFRaXhEUVVGUUxFTkJSQ3RDTzBkQlFXcERPenRCUVVsQkxFMUJRVWNzVDBGQlR5eFZRVUZRTEVOQlFXdENMRTlCUVd4Q0xFTkJRVWdzUlVGQk9FSTdRVUZETlVJc1YwRkJUeXhWUVVGVkxHTkJRVllzUTBGQmVVSXNUMEZCZWtJc1EwRkJVQ3hEUVVRMFFqdEhRVUU1UWpzN1FVRkpRU3hOUVVGSExFOUJRVThzVVVGQlVDeERRVUZuUWl4UFFVRm9RaXhEUVVGSUxFVkJRVFJDTzBGQlF6RkNMRmRCUVU4c1ZVRkJWU3haUVVGV0xFTkJRWFZDTEU5QlFYWkNMRU5CUVZBc1EwRkVNRUk3UjBGQk5VSTdPMEZCU1VFc1RVRkJSeXhQUVVGUExFOUJRVkFzUTBGQlpTeFBRVUZtTEVOQlFVZ3NSVUZCTWtJN1FVRkRla0lzVjBGQlR5eFZRVUZWTEZkQlFWWXNRMEZCYzBJc1QwRkJkRUlzUTBGQlVDeERRVVI1UWp0SFFVRXpRanM3UVVGSlFTeE5RVUZITEU5QlFVOHNVVUZCVUN4RFFVRm5RaXhQUVVGb1FpeERRVUZJTEVWQlFUUkNPMEZCUXpGQ0xGZEJRVThzVlVGQlZTeFpRVUZXTEVOQlFYVkNMRTlCUVhaQ0xFTkJRVkFzUTBGRU1FSTdSMEZCTlVJN08wRkJTVUVzVFVGQlJ5eFBRVUZQTEZOQlFWQXNRMEZCYVVJc1QwRkJha0lzUTBGQlNDeEZRVUUyUWp0QlFVTXpRaXhYUVVGUExGVkJRVlVzWVVGQlZpeERRVUYzUWl4UFFVRjRRaXhEUVVGUUxFTkJSREpDTzBkQlFUZENPenRCUVVsQkxFMUJRVWNzVDBGQlR5eFRRVUZRTEVOQlFXbENMRTlCUVdwQ0xFTkJRVWdzUlVGQk5rSTdRVUZETTBJc1YwRkJUeXhWUVVGVkxHRkJRVllzUTBGQmQwSXNUMEZCZUVJc1EwRkJVQ3hEUVVReVFqdEhRVUUzUWpzN1FVRkpRU3hOUVVGSExFOUJRVThzVlVGQlVDeERRVUZyUWl4UFFVRnNRaXhEUVVGSUxFVkJRVGhDTzBGQlF6VkNMRmRCUVU4c1ZVRkJWU3hqUVVGV0xFTkJRWGxDTEU5QlFYcENMRU5CUVZBc1EwRkVORUk3UjBGQk9VSTdPMEZCU1VFc1RVRkJSeXhQUVVGUExGTkJRVkFzUTBGQmFVSXNUMEZCYWtJc1EwRkJTQ3hGUVVFMlFqdEJRVU16UWl4WFFVRlBMRlZCUVZVc1lVRkJWaXhEUVVGM1FpeFBRVUY0UWl4RFFVRlFMRU5CUkRKQ08wZEJRVGRDT3p0QlFVbEJMRTFCUVVjc1QwRkJUeXhQUVVGUUxFTkJRV1VzVDBGQlppeERRVUZJTEVWQlFUSkNPMEZCUTNwQ0xGZEJRVThzVlVGQlZTeFhRVUZXTEVOQlFYTkNMRTlCUVhSQ0xFTkJRVkFzUTBGRWVVSTdSMEZCTTBJN08wRkJTVUVzVFVGQlJ5eFBRVUZQTEZsQlFWQXNRMEZCYjBJc1QwRkJjRUlzUTBGQlNDeEZRVUZuUXp0QlFVTTVRaXhYUVVGUExGVkJRVlVzWjBKQlFWWXNRMEZCTWtJc1QwRkJNMElzUTBGQlVDeERRVVE0UWp0SFFVRm9RenM3UVVGSlFTeE5RVUZITEU5QlFVOHNVMEZCVUN4RFFVRnBRaXhQUVVGcVFpeERRVUZJTEVWQlFUWkNPMEZCUXpOQ0xGZEJRVThzVlVGQlZTeGhRVUZXTEVOQlFYZENMRTlCUVhoQ0xFTkJRVkFzUTBGRU1rSTdSMEZCTjBJN08wRkJTVUVzVTBGQlR5eFZRVUZWTEdOQlFWWXNSVUZCVUN4RFFXeEZhVVE3UTBGQk5VTWlMQ0ptYVd4bElqb2liR2xpTDJOdmNtVXZjR0YwZEdWeWJuTXZiV0YwWTJndWFuTWlMQ0p6YjNWeVkyVnpRMjl1ZEdWdWRDSTZXeUl2S2lCQVpteHZkeUFxTDF4dWFXMXdiM0owSUVOb1pXTnJjeUJtY205dElGd2lMaTlqYUdWamEzTmNJanRjYm1sdGNHOXlkQ0JTWlhOdmJIWmxjbk1nWm5KdmJTQmNJaTR2Y21WemIyeDJaWEp6WENJN1hHNWNibVY0Y0c5eWRDQm1kVzVqZEdsdmJpQmlkV2xzWkUxaGRHTm9LSEJoZEhSbGNtNDZJR0Z1ZVNrNklFWjFibU4wYVc5dUlIdGNibHh1SUNCcFppaERhR1ZqYTNNdWFYTmZkbUZ5YVdGaWJHVW9jR0YwZEdWeWJpa3BlMXh1SUNBZ0lISmxkSFZ5YmlCU1pYTnZiSFpsY25NdWNtVnpiMngyWlZaaGNtbGhZbXhsS0hCaGRIUmxjbTRwTzF4dUlDQjlYRzVjYmlBZ2FXWW9RMmhsWTJ0ekxtbHpYM2RwYkdSallYSmtLSEJoZEhSbGNtNHBLWHRjYmlBZ0lDQnlaWFIxY200Z1VtVnpiMngyWlhKekxuSmxjMjlzZG1WWGFXeGtZMkZ5WkNod1lYUjBaWEp1S1R0Y2JpQWdmVnh1WEc0Z0lHbG1LRU5vWldOcmN5NXBjMTkxYm1SbFptbHVaV1FvY0dGMGRHVnliaWtwZTF4dUlDQWdJSEpsZEhWeWJpQlNaWE52YkhabGNuTXVjbVZ6YjJ4MlpWZHBiR1JqWVhKa0tIQmhkSFJsY200cE8xeHVJQ0I5WEc1Y2JpQWdhV1lvUTJobFkydHpMbWx6WDJobFlXUlVZV2xzS0hCaGRIUmxjbTRwS1h0Y2JpQWdJQ0J5WlhSMWNtNGdVbVZ6YjJ4MlpYSnpMbkpsYzI5c2RtVklaV0ZrVkdGcGJDaHdZWFIwWlhKdUtUdGNiaUFnZlZ4dVhHNGdJR2xtS0VOb1pXTnJjeTVwYzE5emRHRnlkSE5YYVhSb0tIQmhkSFJsY200cEtYdGNiaUFnSUNCeVpYUjFjbTRnVW1WemIyeDJaWEp6TG5KbGMyOXNkbVZUZEdGeWRITlhhWFJvS0hCaGRIUmxjbTRwTzF4dUlDQjlYRzVjYmlBZ2FXWW9RMmhsWTJ0ekxtbHpYMk5oY0hSMWNtVW9jR0YwZEdWeWJpa3BlMXh1SUNBZ0lISmxkSFZ5YmlCU1pYTnZiSFpsY25NdWNtVnpiMngyWlVOaGNIUjFjbVVvY0dGMGRHVnliaWs3WEc0Z0lIMWNibHh1SUNCcFppaERhR1ZqYTNNdWFYTmZZbTkxYm1Rb2NHRjBkR1Z5YmlrcGUxeHVJQ0FnSUhKbGRIVnliaUJTWlhOdmJIWmxjbk11Y21WemIyeDJaVUp2ZFc1a0tIQmhkSFJsY200cE8xeHVJQ0I5WEc1Y2JpQWdhV1lvUTJobFkydHpMbWx6WDNSNWNHVW9jR0YwZEdWeWJpa3BlMXh1SUNBZ0lISmxkSFZ5YmlCU1pYTnZiSFpsY25NdWNtVnpiMngyWlZSNWNHVW9jR0YwZEdWeWJpazdYRzRnSUgxY2JseHVJQ0JwWmloRGFHVmphM011YVhOZllYSnlZWGtvY0dGMGRHVnliaWtwZTF4dUlDQWdJSEpsZEhWeWJpQlNaWE52YkhabGNuTXVjbVZ6YjJ4MlpVRnljbUY1S0hCaGRIUmxjbTRwTzF4dUlDQjlYRzVjYmlBZ2FXWW9RMmhsWTJ0ekxtbHpYMjUxYldKbGNpaHdZWFIwWlhKdUtTbDdYRzRnSUNBZ2NtVjBkWEp1SUZKbGMyOXNkbVZ5Y3k1eVpYTnZiSFpsVG5WdFltVnlLSEJoZEhSbGNtNHBPMXh1SUNCOVhHNWNiaUFnYVdZb1EyaGxZMnR6TG1selgzTjBjbWx1Wnlod1lYUjBaWEp1S1NsN1hHNGdJQ0FnY21WMGRYSnVJRkpsYzI5c2RtVnljeTV5WlhOdmJIWmxVM1J5YVc1bktIQmhkSFJsY200cE8xeHVJQ0I5WEc1Y2JpQWdhV1lvUTJobFkydHpMbWx6WDJKdmIyeGxZVzRvY0dGMGRHVnliaWtwZTF4dUlDQWdJSEpsZEhWeWJpQlNaWE52YkhabGNuTXVjbVZ6YjJ4MlpVSnZiMnhsWVc0b2NHRjBkR1Z5YmlrN1hHNGdJSDFjYmx4dUlDQnBaaWhEYUdWamEzTXVhWE5mYzNsdFltOXNLSEJoZEhSbGNtNHBLWHRjYmlBZ0lDQnlaWFIxY200Z1VtVnpiMngyWlhKekxuSmxjMjlzZG1WVGVXMWliMndvY0dGMGRHVnliaWs3WEc0Z0lIMWNibHh1SUNCcFppaERhR1ZqYTNNdWFYTmZiblZzYkNod1lYUjBaWEp1S1NsN1hHNGdJQ0FnY21WMGRYSnVJRkpsYzI5c2RtVnljeTV5WlhOdmJIWmxUblZzYkNod1lYUjBaWEp1S1R0Y2JpQWdmVnh1WEc0Z0lHbG1LRU5vWldOcmN5NXBjMTlpYVhSemRISnBibWNvY0dGMGRHVnliaWtwZTF4dUlDQWdJSEpsZEhWeWJpQlNaWE52YkhabGNuTXVjbVZ6YjJ4MlpVSnBkRk4wY21sdVp5aHdZWFIwWlhKdUtUdGNiaUFnZlZ4dVhHNGdJR2xtS0VOb1pXTnJjeTVwYzE5dlltcGxZM1FvY0dGMGRHVnliaWtwZTF4dUlDQWdJSEpsZEhWeWJpQlNaWE52YkhabGNuTXVjbVZ6YjJ4MlpVOWlhbVZqZENod1lYUjBaWEp1S1R0Y2JpQWdmVnh1WEc0Z0lISmxkSFZ5YmlCU1pYTnZiSFpsY25NdWNtVnpiMngyWlU1dlRXRjBZMmdvS1R0Y2JuMWNiaUpkTENKemIzVnlZMlZTYjI5MElqb2lMM052ZFhKalpTOGlmUT09XG4iLCJcblxuaW1wb3J0IHsgYnVpbGRNYXRjaCB9IGZyb20gXCIuL21hdGNoXCI7XG5pbXBvcnQgKiBhcyBUeXBlcyBmcm9tIFwiLi90eXBlc1wiO1xuXG5leHBvcnQgY2xhc3MgTWF0Y2hFcnJvciBleHRlbmRzIEVycm9yIHtcbiAgY29uc3RydWN0b3IoYXJnKSB7XG4gICAgc3VwZXIoKTtcblxuICAgIGlmICh0eXBlb2YgYXJnID09PSAnc3ltYm9sJykge1xuICAgICAgdGhpcy5tZXNzYWdlID0gJ05vIG1hdGNoIGZvcjogJyArIGFyZy50b1N0cmluZygpO1xuICAgIH0gZWxzZSBpZiAoQXJyYXkuaXNBcnJheShhcmcpKSB7XG4gICAgICBsZXQgbWFwcGVkVmFsdWVzID0gYXJnLm1hcCh4ID0+IHgudG9TdHJpbmcoKSk7XG4gICAgICB0aGlzLm1lc3NhZ2UgPSAnTm8gbWF0Y2ggZm9yOiAnICsgbWFwcGVkVmFsdWVzO1xuICAgIH0gZWxzZSB7XG4gICAgICB0aGlzLm1lc3NhZ2UgPSAnTm8gbWF0Y2ggZm9yOiAnICsgYXJnO1xuICAgIH1cblxuICAgIHRoaXMuc3RhY2sgPSBuZXcgRXJyb3IoKS5zdGFjaztcbiAgICB0aGlzLm5hbWUgPSB0aGlzLmNvbnN0cnVjdG9yLm5hbWU7XG4gIH1cbn1cblxuZXhwb3J0IGNsYXNzIENhc2Uge1xuXG4gIGNvbnN0cnVjdG9yKHBhdHRlcm4sIGZuLCBndWFyZCA9ICgpID0+IHRydWUpIHtcbiAgICB0aGlzLnBhdHRlcm4gPSBidWlsZE1hdGNoKHBhdHRlcm4pO1xuICAgIHRoaXMuYXJpdHkgPSBwYXR0ZXJuLmxlbmd0aDtcbiAgICB0aGlzLm9wdGlvbmFscyA9IGdldE9wdGlvbmFsVmFsdWVzKHBhdHRlcm4pO1xuICAgIHRoaXMuZm4gPSBmbjtcbiAgICB0aGlzLmd1YXJkID0gZ3VhcmQ7XG4gIH1cbn1cblxuZXhwb3J0IGZ1bmN0aW9uIG1ha2VfY2FzZShwYXR0ZXJuLCBmbiwgZ3VhcmQgPSAoKSA9PiB0cnVlKSB7XG4gIHJldHVybiBuZXcgQ2FzZShwYXR0ZXJuLCBmbiwgZ3VhcmQpO1xufVxuXG5leHBvcnQgZnVuY3Rpb24gZGVmbWF0Y2goLi4uY2FzZXMpIHtcbiAgcmV0dXJuIGZ1bmN0aW9uICguLi5hcmdzKSB7XG4gICAgZm9yIChsZXQgcHJvY2Vzc2VkQ2FzZSBvZiBjYXNlcykge1xuICAgICAgbGV0IHJlc3VsdCA9IFtdO1xuICAgICAgYXJncyA9IGZpbGxJbk9wdGlvbmFsVmFsdWVzKGFyZ3MsIHByb2Nlc3NlZENhc2UuYXJpdHksIHByb2Nlc3NlZENhc2Uub3B0aW9uYWxzKTtcblxuICAgICAgaWYgKHByb2Nlc3NlZENhc2UucGF0dGVybihhcmdzLCByZXN1bHQpICYmIHByb2Nlc3NlZENhc2UuZ3VhcmQuYXBwbHkodGhpcywgcmVzdWx0KSkge1xuICAgICAgICByZXR1cm4gcHJvY2Vzc2VkQ2FzZS5mbi5hcHBseSh0aGlzLCByZXN1bHQpO1xuICAgICAgfVxuICAgIH1cblxuICAgIHRocm93IG5ldyBNYXRjaEVycm9yKGFyZ3MpO1xuICB9O1xufVxuXG5mdW5jdGlvbiBnZXRPcHRpb25hbFZhbHVlcyhwYXR0ZXJuKSB7XG4gIGxldCBvcHRpb25hbHMgPSBbXTtcblxuICBmb3IgKGxldCBpID0gMDsgaSA8IHBhdHRlcm4ubGVuZ3RoOyBpKyspIHtcbiAgICBpZiAocGF0dGVybltpXSBpbnN0YW5jZW9mIFR5cGVzLlZhcmlhYmxlICYmIHBhdHRlcm5baV0uZGVmYXVsdF92YWx1ZSAhPSBTeW1ib2wuZm9yKFwiZWxpeGlyc2NyaXB0Lm5vX3ZhbHVlXCIpKSB7XG4gICAgICBvcHRpb25hbHMucHVzaChbaSwgcGF0dGVybltpXS5kZWZhdWx0X3ZhbHVlXSk7XG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIG9wdGlvbmFscztcbn1cblxuZnVuY3Rpb24gZmlsbEluT3B0aW9uYWxWYWx1ZXMoYXJncywgYXJpdHksIG9wdGlvbmFscykge1xuICBpZiAoYXJncy5sZW5ndGggPT09IGFyaXR5IHx8IG9wdGlvbmFscy5sZW5ndGggPT09IDApIHtcbiAgICByZXR1cm4gYXJncztcbiAgfVxuXG4gIGlmIChhcmdzLmxlbmd0aCArIG9wdGlvbmFscy5sZW5ndGggPCBhcml0eSkge1xuICAgIHJldHVybiBhcmdzO1xuICB9XG5cbiAgbGV0IG51bWJlck9mT3B0aW9uYWxzVG9GaWxsID0gYXJpdHkgLSBhcmdzLmxlbmd0aDtcbiAgbGV0IG9wdGlvbmFsc1RvUmVtb3ZlID0gb3B0aW9uYWxzLmxlbmd0aCAtIG51bWJlck9mT3B0aW9uYWxzVG9GaWxsO1xuXG4gIGxldCBvcHRpb25hbHNUb1VzZSA9IG9wdGlvbmFscy5zbGljZShvcHRpb25hbHNUb1JlbW92ZSk7XG5cbiAgZm9yIChsZXQgW2luZGV4LCB2YWx1ZV0gb2Ygb3B0aW9uYWxzVG9Vc2UpIHtcbiAgICBhcmdzLnNwbGljZShpbmRleCwgMCwgdmFsdWUpO1xuICAgIGlmIChhcmdzLmxlbmd0aCA9PT0gYXJpdHkpIHtcbiAgICAgIGJyZWFrO1xuICAgIH1cbiAgfVxuXG4gIHJldHVybiBhcmdzO1xufVxuXG5leHBvcnQgZnVuY3Rpb24gbWF0Y2gocGF0dGVybiwgZXhwciwgZ3VhcmQgPSAoKSA9PiB0cnVlKSB7XG4gIGxldCByZXN1bHQgPSBbXTtcbiAgbGV0IHByb2Nlc3NlZFBhdHRlcm4gPSBidWlsZE1hdGNoKHBhdHRlcm4pO1xuICBpZiAocHJvY2Vzc2VkUGF0dGVybihleHByLCByZXN1bHQpICYmIGd1YXJkLmFwcGx5KHRoaXMsIHJlc3VsdCkpIHtcbiAgICByZXR1cm4gcmVzdWx0O1xuICB9IGVsc2Uge1xuICAgIHRocm93IG5ldyBNYXRjaEVycm9yKGV4cHIpO1xuICB9XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBtYXRjaF9ub190aHJvdyhwYXR0ZXJuLCBleHByLCBndWFyZCA9ICgpID0+IHRydWUpIHtcbiAgdHJ5IHtcbiAgICByZXR1cm4gbWF0Y2gocGF0dGVybiwgZXhwciwgZ3VhcmQpO1xuICB9IGNhdGNoIChlKSB7XG4gICAgaWYgKGUgaW5zdGFuY2VvZiBNYXRjaEVycm9yIHx8IGUubWVzc2FnZS5zdGFydHNXaXRoKCdObyBtYXRjaCBmb3I6JykpIHtcbiAgICAgIHJldHVybiBudWxsO1xuICAgIH1cblxuICAgIHRocm93IGU7XG4gIH1cbn1cblxuZXhwb3J0IGZ1bmN0aW9uIHBhdHRlcm5NYXAoY29sbGVjdGlvbiwgcGF0dGVybiwgZnVuLCBndWFyZCA9ICgpID0+IHRydWUpIHtcbiAgbGV0IHJldCA9IFtdO1xuXG4gIGZvciAobGV0IGVsZW0gb2YgY29sbGVjdGlvbikge1xuICAgIHRyeSB7XG4gICAgICBsZXQgcmVzdWx0ID0gZnVuLmFwcGx5KHRoaXMsIG1hdGNoKHBhdHRlcm4sIGVsZW0sIGd1YXJkKSk7XG4gICAgICByZXQgPSByZXQuY29uY2F0KHJlc3VsdCk7XG4gICAgfSBjYXRjaCAoZSkge1xuICAgICAgaWYgKCEoZSBpbnN0YW5jZW9mIE1hdGNoRXJyb3IpKSB7XG4gICAgICAgIHRocm93IGU7XG4gICAgICB9XG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIHJldDtcbn1cbi8vIyBzb3VyY2VNYXBwaW5nVVJMPWRhdGE6YXBwbGljYXRpb24vanNvbjtiYXNlNjQsZXlKMlpYSnphVzl1SWpvekxDSnpiM1Z5WTJWeklqcGJJbXhwWWk5amIzSmxMM0JoZEhSbGNtNXpMMlJsWm0xaGRHTm9MbXB6SWwwc0ltNWhiV1Z6SWpwYlhTd2liV0Z3Y0dsdVozTWlPaUk3TzBGQlJVRXNVMEZCVXl4VlFVRlVMRkZCUVRKQ0xGTkJRVE5DTzBGQlEwRXNUMEZCVHl4TFFVRkxMRXRCUVV3c1RVRkJaMElzVTBGQmRrSTdPMEZCUlVFc1QwRkJUeXhOUVVGTkxGVkJRVTRzVTBGQmVVSXNTMEZCZWtJc1EwRkJLMEk3UVVGRGNFTXNZMEZCV1N4SFFVRmFMRVZCUVhOQ08wRkJRM0JDTEZsQlJHOUNPenRCUVVkd1FpeFJRVUZITEU5QlFVOHNSMEZCVUN4TFFVRmxMRkZCUVdZc1JVRkJkMEk3UVVGRGVrSXNWMEZCU3l4UFFVRk1MRWRCUVdVc2JVSkJRVzFDTEVsQlFVa3NVVUZCU2l4RlFVRnVRaXhEUVVSVk8wdEJRVE5DTEUxQlJVOHNTVUZCUnl4TlFVRk5MRTlCUVU0c1EwRkJZeXhIUVVGa0xFTkJRVWdzUlVGQmMwSTdRVUZETTBJc1ZVRkJTU3hsUVVGbExFbEJRVWtzUjBGQlNpeERRVUZSTEV0QlFVOHNSVUZCUlN4UlFVRkdMRVZCUVZBc1EwRkJka0lzUTBGRWRVSTdRVUZGTTBJc1YwRkJTeXhQUVVGTUxFZEJRV1VzYlVKQlFXMUNMRmxCUVc1Q0xFTkJSbGs3UzBGQmRFSXNUVUZIUmp0QlFVTklMRmRCUVVzc1QwRkJUQ3hIUVVGbExHMUNRVUZ0UWl4SFFVRnVRaXhEUVVSYU8wdEJTRVU3TzBGQlQxQXNVMEZCU3l4TFFVRk1MRWRCUVdFc1NVRkJTeXhMUVVGS0xFVkJRVVFzUTBGQll5eExRVUZrTEVOQldrODdRVUZoY0VJc1UwRkJTeXhKUVVGTUxFZEJRVmtzUzBGQlN5eFhRVUZNTEVOQlFXbENMRWxCUVdwQ0xFTkJZbEU3UjBGQmRFSTdRMEZFU3pzN1FVRnRRbEFzVDBGQlR5eE5RVUZOTEVsQlFVNHNRMEZCVnpzN1FVRlBhRUlzWTBGQldTeFBRVUZhTEVWQlFXbERMRVZCUVdwRExFVkJRU3RFTEZGQlFVVXNUVUZCVFN4SlFVRk9MRVZCUVZjN1FVRkRNVVVzVTBGQlN5eFBRVUZNTEVkQlFXVXNWMEZCVnl4UFFVRllMRU5CUVdZc1EwRkVNRVU3UVVGRk1VVXNVMEZCU3l4TFFVRk1MRWRCUVdFc1VVRkJVU3hOUVVGU0xFTkJSalpFTzBGQlJ6RkZMRk5CUVVzc1UwRkJUQ3hIUVVGcFFpeHJRa0ZCYTBJc1QwRkJiRUlzUTBGQmFrSXNRMEZJTUVVN1FVRkpNVVVzVTBGQlN5eEZRVUZNTEVkQlFWVXNSVUZCVml4RFFVb3dSVHRCUVVzeFJTeFRRVUZMTEV0QlFVd3NSMEZCWVN4TFFVRmlMRU5CVERCRk8wZEJRVFZGTzBOQlVFczdPMEZCWjBKUUxFOUJRVThzVTBGQlV5eFRRVUZVTEVOQlFXMUNMRTlCUVc1Q0xFVkJRWGRETEVWQlFYaERMRVZCUVhORkxGRkJRVVVzVFVGQlRTeEpRVUZPTEVWQlFXdENPMEZCUXk5R0xGTkJRVThzU1VGQlNTeEpRVUZLTEVOQlFWTXNUMEZCVkN4RlFVRnJRaXhGUVVGc1FpeEZRVUZ6UWl4TFFVRjBRaXhEUVVGUUxFTkJSQ3RHTzBOQlFURkdPenRCUVVsUUxFOUJRVThzVTBGQlV5eFJRVUZVTEVOQlFXdENMRWRCUVVjc1MwRkJTQ3hGUVVGcFF6dEJRVU40UkN4VFFVRlBMRlZCUVZNc1IwRkJSeXhKUVVGSUxFVkJRVEJDTzBGQlEzaERMRk5CUVVzc1NVRkJTU3hoUVVGS0xFbEJRWEZDTEV0QlFURkNMRVZCUVdsRE8wRkJReTlDTEZWQlFVa3NVMEZCVXl4RlFVRlVMRU5CUkRKQ08wRkJSUzlDTEdGQlFVOHNjVUpCUVhGQ0xFbEJRWEpDTEVWQlFUSkNMR05CUVdNc1MwRkJaQ3hGUVVGeFFpeGpRVUZqTEZOQlFXUXNRMEZCZGtRc1EwRkdLMEk3TzBGQlNTOUNMRlZCUVVrc1kwRkJZeXhQUVVGa0xFTkJRWE5DTEVsQlFYUkNMRVZCUVRSQ0xFMUJRVFZDTEV0QlFYVkRMR05CUVdNc1MwRkJaQ3hEUVVGdlFpeExRVUZ3UWl4RFFVRXdRaXhKUVVFeFFpeEZRVUZuUXl4TlFVRm9ReXhEUVVGMlF5eEZRVUZuUmp0QlFVTnNSaXhsUVVGUExHTkJRV01zUlVGQlpDeERRVUZwUWl4TFFVRnFRaXhEUVVGMVFpeEpRVUYyUWl4RlFVRTJRaXhOUVVFM1FpeERRVUZRTEVOQlJHdEdPMDlCUVhCR08wdEJTa1k3TzBGQlUwRXNWVUZCVFN4SlFVRkpMRlZCUVVvc1EwRkJaU3hKUVVGbUxFTkJRVTRzUTBGV2QwTTdSMEZCYmtNc1EwRkVhVVE3UTBGQmJrUTdPMEZCWlZBc1UwRkJVeXhwUWtGQlZDeERRVUV5UWl4UFFVRXpRaXhGUVVFclF6dEJRVU0zUXl4TlFVRkpMRmxCUVZrc1JVRkJXaXhEUVVSNVF6czdRVUZITjBNc1QwRkJTU3hKUVVGSkxFbEJRVWtzUTBGQlNpeEZRVUZQTEVsQlFVa3NVVUZCVVN4TlFVRlNMRVZCUVdkQ0xFZEJRVzVETEVWQlFYVkRPMEZCUTNKRExGRkJRVWNzVVVGQlVTeERRVUZTTEdGQlFYTkNMRTFCUVUwc1VVRkJUaXhKUVVGclFpeFJRVUZSTEVOQlFWSXNSVUZCVnl4aFFVRllMRWxCUVRSQ0xFOUJRVThzUjBGQlVDeERRVUZYTEhWQ1FVRllMRU5CUVRWQ0xFVkJRV2RGTzBGQlEzcEhMR2RDUVVGVkxFbEJRVllzUTBGQlpTeERRVUZETEVOQlFVUXNSVUZCU1N4UlFVRlJMRU5CUVZJc1JVRkJWeXhoUVVGWUxFTkJRVzVDTEVWQlJIbEhPMHRCUVROSE8wZEJSRVk3TzBGQlRVRXNVMEZCVHl4VFFVRlFMRU5CVkRaRE8wTkJRUzlET3p0QlFWbEJMRk5CUVZNc2IwSkJRVlFzUTBGQk9FSXNTVUZCT1VJc1JVRkJiME1zUzBGQmNFTXNSVUZCTWtNc1UwRkJNME1zUlVGQmNVUTdRVUZEYmtRc1RVRkJSeXhMUVVGTExFMUJRVXdzUzBGQlowSXNTMEZCYUVJc1NVRkJlVUlzVlVGQlZTeE5RVUZXTEV0QlFYRkNMRU5CUVhKQ0xFVkJRWFZDTzBGQlEycEVMRmRCUVU4c1NVRkJVQ3hEUVVScFJEdEhRVUZ1UkRzN1FVRkpRU3hOUVVGSExFdEJRVXNzVFVGQlRDeEhRVUZqTEZWQlFWVXNUVUZCVml4SFFVRnRRaXhMUVVGcVF5eEZRVUYxUXp0QlFVTjRReXhYUVVGUExFbEJRVkFzUTBGRWQwTTdSMEZCTVVNN08wRkJTVUVzVFVGQlNTd3dRa0ZCTUVJc1VVRkJVU3hMUVVGTExFMUJRVXdzUTBGVVlUdEJRVlZ1UkN4TlFVRkpMRzlDUVVGdlFpeFZRVUZWTEUxQlFWWXNSMEZCYlVJc2RVSkJRVzVDTEVOQlZqSkNPenRCUVZsdVJDeE5RVUZKTEdsQ1FVRnBRaXhWUVVGVkxFdEJRVllzUTBGQlowSXNhVUpCUVdoQ0xFTkJRV3BDTEVOQldpdERPenRCUVdOdVJDeFBRVUZKTEVsQlFVa3NRMEZCUXl4TFFVRkVMRVZCUVZFc1MwRkJVaXhEUVVGS0xFbEJRWE5DTEdOQlFURkNMRVZCUVhsRE8wRkJRM1pETEZOQlFVc3NUVUZCVEN4RFFVRlpMRXRCUVZvc1JVRkJiVUlzUTBGQmJrSXNSVUZCYzBJc1MwRkJkRUlzUlVGRWRVTTdRVUZGZGtNc1VVRkJSeXhMUVVGTExFMUJRVXdzUzBGQlowSXNTMEZCYUVJc1JVRkJjMEk3UVVGRGRrSXNXVUZFZFVJN1MwRkJla0k3UjBGR1JqczdRVUZQUVN4VFFVRlBMRWxCUVZBc1EwRnlRbTFFTzBOQlFYSkVPenRCUVhkQ1FTeFBRVUZQTEZOQlFWTXNTMEZCVkN4RFFVRmxMRTlCUVdZc1JVRkJOa0lzU1VGQk4wSXNSVUZCZDBRc1VVRkJSU3hOUVVGTkxFbEJRVTRzUlVGQmQwSTdRVUZEZGtZc1RVRkJTU3hUUVVGVExFVkJRVlFzUTBGRWJVWTdRVUZGZGtZc1RVRkJTU3h0UWtGQmJVSXNWMEZCVnl4UFFVRllMRU5CUVc1Q0xFTkJSbTFHTzBGQlIzWkdMRTFCUVVrc2FVSkJRV2xDTEVsQlFXcENMRVZCUVhWQ0xFMUJRWFpDTEV0QlFXdERMRTFCUVUwc1MwRkJUaXhEUVVGWkxFbEJRVm9zUlVGQmEwSXNUVUZCYkVJc1EwRkJiRU1zUlVGQk5FUTdRVUZET1VRc1YwRkJUeXhOUVVGUUxFTkJSRGhFTzBkQlFXaEZMRTFCUlVzN1FVRkRTQ3hWUVVGTkxFbEJRVWtzVlVGQlNpeERRVUZsTEVsQlFXWXNRMEZCVGl4RFFVUkhPMGRCUmt3N1EwRklTenM3UVVGVlVDeFBRVUZQTEZOQlFWTXNZMEZCVkN4RFFVRjNRaXhQUVVGNFFpeEZRVUZ6UXl4SlFVRjBReXhGUVVGcFJTeFJRVUZGTEUxQlFVMHNTVUZCVGl4RlFVRjVRanRCUVVOcVJ5eE5RVUZITzBGQlEwUXNWMEZCVHl4TlFVRk5MRTlCUVU0c1JVRkJaU3hKUVVGbUxFVkJRWEZDTEV0QlFYSkNMRU5CUVZBc1EwRkVRenRIUVVGSUxFTkJSVU1zVDBGQlRTeERRVUZPTEVWQlFWRTdRVUZEVUN4UlFVRkhMR0ZCUVdFc1ZVRkJZaXhKUVVFeVFpeEZRVUZGTEU5QlFVWXNRMEZCVlN4VlFVRldMRU5CUVhGQ0xHVkJRWEpDTEVOQlFUTkNMRVZCUVdsRk8wRkJRMnhGTEdGQlFVOHNTVUZCVUN4RFFVUnJSVHRMUVVGd1JUczdRVUZKUVN4VlFVRk5MRU5CUVU0c1EwRk1UenRIUVVGU08wTkJTRWs3TzBGQldWQXNUMEZCVHl4VFFVRlRMRlZCUVZRc1EwRkJiMElzVlVGQmNFSXNSVUZCTkVNc1QwRkJOVU1zUlVGQk1FUXNSMEZCTVVRc1JVRkJlVVlzVVVGQlJTeE5RVUZOTEVsQlFVNHNSVUZCZDBJN1FVRkRlRWdzVFVGQlNTeE5RVUZOTEVWQlFVNHNRMEZFYjBnN08wRkJSM2hJTEU5QlFVa3NTVUZCU1N4SlFVRktMRWxCUVZrc1ZVRkJhRUlzUlVGQk1rSTdRVUZEZWtJc1VVRkJSenRCUVVORUxGVkJRVWtzVTBGQlV5eEpRVUZKTEV0QlFVb3NRMEZCVlN4SlFVRldMRVZCUVdkQ0xFMUJRVTBzVDBGQlRpeEZRVUZsTEVsQlFXWXNSVUZCY1VJc1MwRkJja0lzUTBGQmFFSXNRMEZCVkN4RFFVUklPMEZCUlVRc1dVRkJUU3hKUVVGSkxFMUJRVW9zUTBGQlZ5eE5RVUZZTEVOQlFVNHNRMEZHUXp0TFFVRklMRU5CUjBNc1QwRkJUU3hEUVVGT0xFVkJRVkU3UVVGRFZDeFZRVUZITEVWQlFVVXNZVUZCWVN4VlFVRmlMRU5CUVVZc1JVRkJNa0k3UVVGRE1VSXNZMEZCVFN4RFFVRk9MRU5CUkRCQ08wOUJRVGxDTzB0QlJFTTdSMEZLU0RzN1FVRlhRU3hUUVVGUExFZEJRVkFzUTBGa2QwZzdRMEZCYmtnaUxDSm1hV3hsSWpvaWJHbGlMMk52Y21VdmNHRjBkR1Z5Ym5NdlpHVm1iV0YwWTJndWFuTWlMQ0p6YjNWeVkyVnpRMjl1ZEdWdWRDSTZXeUl2S2lCQVpteHZkeUFxTDF4dVhHNXBiWEJ2Y25RZ2V5QmlkV2xzWkUxaGRHTm9JSDBnWm5KdmJTQmNJaTR2YldGMFkyaGNJanRjYm1sdGNHOXlkQ0FxSUdGeklGUjVjR1Z6SUdaeWIyMGdYQ0l1TDNSNWNHVnpYQ0k3WEc1Y2JtVjRjRzl5ZENCamJHRnpjeUJOWVhSamFFVnljbTl5SUdWNGRHVnVaSE1nUlhKeWIzSWdlMXh1SUNCamIyNXpkSEoxWTNSdmNpaGhjbWM2SUdGdWVTa2dlMXh1SUNBZ0lITjFjR1Z5S0NrN1hHNWNiaUFnSUNCcFppaDBlWEJsYjJZZ1lYSm5JRDA5UFNBbmMzbHRZbTlzSnlsN1hHNGdJQ0FnSUNCMGFHbHpMbTFsYzNOaFoyVWdQU0FuVG04Z2JXRjBZMmdnWm05eU9pQW5JQ3NnWVhKbkxuUnZVM1J5YVc1bktDazdYRzRnSUNBZ2ZTQmxiSE5sSUdsbUtFRnljbUY1TG1selFYSnlZWGtvWVhKbktTbDdYRzRnSUNBZ0lDQnNaWFFnYldGd2NHVmtWbUZzZFdWeklEMGdZWEpuTG0xaGNDZ29lQ2tnUFQ0Z2VDNTBiMU4wY21sdVp5Z3BLVHRjYmlBZ0lDQWdJSFJvYVhNdWJXVnpjMkZuWlNBOUlDZE9ieUJ0WVhSamFDQm1iM0k2SUNjZ0t5QnRZWEJ3WldSV1lXeDFaWE03WEc0Z0lDQWdmV1ZzYzJWN1hHNGdJQ0FnSUNCMGFHbHpMbTFsYzNOaFoyVWdQU0FuVG04Z2JXRjBZMmdnWm05eU9pQW5JQ3NnWVhKbk8xeHVJQ0FnSUgxY2JseHVJQ0FnSUhSb2FYTXVjM1JoWTJzZ1BTQW9ibVYzSUVWeWNtOXlLQ2twTG5OMFlXTnJPMXh1SUNBZ0lIUm9hWE11Ym1GdFpTQTlJSFJvYVhNdVkyOXVjM1J5ZFdOMGIzSXVibUZ0WlR0Y2JpQWdmVnh1ZlZ4dVhHNWNibVY0Y0c5eWRDQmpiR0Z6Y3lCRFlYTmxJSHRjYmlBZ2NHRjBkR1Z5YmpvZ1JuVnVZM1JwYjI0N1hHNGdJR1p1T2lCR2RXNWpkR2x2Ymp0Y2JpQWdaM1ZoY21RNklFWjFibU4wYVc5dU8xeHVJQ0JoY21sMGVUb2diblZ0WW1WeU8xeHVJQ0J2Y0hScGIyNWhiSE02SUVGeWNtRjVQR0Z1ZVQ0N1hHNWNiaUFnWTI5dWMzUnlkV04wYjNJb2NHRjBkR1Z5YmpvZ1FYSnlZWGs4WVc1NVBpd2dabTQ2SUVaMWJtTjBhVzl1TENCbmRXRnlaRG9nUm5WdVkzUnBiMjRnUFNBb0tTQTlQaUIwY25WbEtYdGNiaUFnSUNCMGFHbHpMbkJoZEhSbGNtNGdQU0JpZFdsc1pFMWhkR05vS0hCaGRIUmxjbTRwTzF4dUlDQWdJSFJvYVhNdVlYSnBkSGtnUFNCd1lYUjBaWEp1TG14bGJtZDBhRHRjYmlBZ0lDQjBhR2x6TG05d2RHbHZibUZzY3lBOUlHZGxkRTl3ZEdsdmJtRnNWbUZzZFdWektIQmhkSFJsY200cE8xeHVJQ0FnSUhSb2FYTXVabTRnUFNCbWJqdGNiaUFnSUNCMGFHbHpMbWQxWVhKa0lEMGdaM1ZoY21RN1hHNGdJSDFjYm4xY2JseHVaWGh3YjNKMElHWjFibU4wYVc5dUlHMWhhMlZmWTJGelpTaHdZWFIwWlhKdU9pQkJjbkpoZVR4aGJuaytMQ0JtYmpvZ1JuVnVZM1JwYjI0c0lHZDFZWEprT2lCR2RXNWpkR2x2YmlBOUlDZ3BJRDArSUhSeWRXVXBPaUJEWVhObElIdGNiaUFnY21WMGRYSnVJRzVsZHlCRFlYTmxLSEJoZEhSbGNtNHNJR1p1TENCbmRXRnlaQ2s3WEc1OVhHNWNibVY0Y0c5eWRDQm1kVzVqZEdsdmJpQmtaV1p0WVhSamFDZ3VMaTVqWVhObGN6b2dRWEp5WVhrOFEyRnpaVDRwT2lCR2RXNWpkR2x2YmlCN1hHNGdJSEpsZEhWeWJpQm1kVzVqZEdsdmJpZ3VMaTVoY21kek9pQkJjbkpoZVR4aGJuaytLVG9nWVc1NUlIdGNiaUFnSUNCbWIzSWdLR3hsZENCd2NtOWpaWE56WldSRFlYTmxJRzltSUdOaGMyVnpLU0I3WEc0Z0lDQWdJQ0JzWlhRZ2NtVnpkV3gwSUQwZ1cxMDdYRzRnSUNBZ0lDQmhjbWR6SUQwZ1ptbHNiRWx1VDNCMGFXOXVZV3hXWVd4MVpYTW9ZWEpuY3l3Z2NISnZZMlZ6YzJWa1EyRnpaUzVoY21sMGVTd2djSEp2WTJWemMyVmtRMkZ6WlM1dmNIUnBiMjVoYkhNcE8xeHVYRzRnSUNBZ0lDQnBaaUFvY0hKdlkyVnpjMlZrUTJGelpTNXdZWFIwWlhKdUtHRnlaM01zSUhKbGMzVnNkQ2tnSmlZZ2NISnZZMlZ6YzJWa1EyRnpaUzVuZFdGeVpDNWhjSEJzZVNoMGFHbHpMQ0J5WlhOMWJIUXBLU0I3WEc0Z0lDQWdJQ0FnSUhKbGRIVnliaUJ3Y205alpYTnpaV1JEWVhObExtWnVMbUZ3Y0d4NUtIUm9hWE1zSUhKbGMzVnNkQ2s3WEc0Z0lDQWdJQ0I5WEc0Z0lDQWdmVnh1WEc0Z0lDQWdkR2h5YjNjZ2JtVjNJRTFoZEdOb1JYSnliM0lvWVhKbmN5azdYRzRnSUgwN1hHNTlYRzVjYm1aMWJtTjBhVzl1SUdkbGRFOXdkR2x2Ym1Gc1ZtRnNkV1Z6S0hCaGRIUmxjbTQ2SUVGeWNtRjVQR0Z1ZVQ0cGUxeHVJQ0JzWlhRZ2IzQjBhVzl1WVd4eklEMGdXMTA3WEc1Y2JpQWdabTl5S0d4bGRDQnBJRDBnTURzZ2FTQThJSEJoZEhSbGNtNHViR1Z1WjNSb095QnBLeXNwZTF4dUlDQWdJR2xtS0hCaGRIUmxjbTViYVYwZ2FXNXpkR0Z1WTJWdlppQlVlWEJsY3k1V1lYSnBZV0pzWlNBbUppQndZWFIwWlhKdVcybGRMbVJsWm1GMWJIUmZkbUZzZFdVZ0lUMGdVM2x0WW05c0xtWnZjaWhjSW1Wc2FYaHBjbk5qY21sd2RDNXViMTkyWVd4MVpWd2lLU2w3WEc0Z0lDQWdJQ0J2Y0hScGIyNWhiSE11Y0hWemFDaGJhU3dnY0dGMGRHVnlibHRwWFM1a1pXWmhkV3gwWDNaaGJIVmxYU2s3WEc0Z0lDQWdmVnh1SUNCOVhHNWNiaUFnY21WMGRYSnVJRzl3ZEdsdmJtRnNjenRjYm4xY2JseHVablZ1WTNScGIyNGdabWxzYkVsdVQzQjBhVzl1WVd4V1lXeDFaWE1vWVhKbmN5d2dZWEpwZEhrc0lHOXdkR2x2Ym1Gc2N5bDdYRzRnSUdsbUtHRnlaM011YkdWdVozUm9JRDA5UFNCaGNtbDBlU0I4ZkNCdmNIUnBiMjVoYkhNdWJHVnVaM1JvSUQwOVBTQXdLWHRjYmlBZ0lDQnlaWFIxY200Z1lYSm5jenRjYmlBZ2ZWeHVYRzRnSUdsbUtHRnlaM011YkdWdVozUm9JQ3NnYjNCMGFXOXVZV3h6TG14bGJtZDBhQ0E4SUdGeWFYUjVLWHRjYmlBZ0lDQnlaWFIxY200Z1lYSm5jenRjYmlBZ2ZWeHVYRzRnSUd4bGRDQnVkVzFpWlhKUFprOXdkR2x2Ym1Gc2MxUnZSbWxzYkNBOUlHRnlhWFI1SUMwZ1lYSm5jeTVzWlc1bmRHZzdYRzRnSUd4bGRDQnZjSFJwYjI1aGJITlViMUpsYlc5MlpTQTlJRzl3ZEdsdmJtRnNjeTVzWlc1bmRHZ2dMU0J1ZFcxaVpYSlBaazl3ZEdsdmJtRnNjMVJ2Um1sc2JEdGNibHh1SUNCc1pYUWdiM0IwYVc5dVlXeHpWRzlWYzJVZ1BTQnZjSFJwYjI1aGJITXVjMnhwWTJVb2IzQjBhVzl1WVd4elZHOVNaVzF2ZG1VcE8xeHVYRzRnSUdadmNpaHNaWFFnVzJsdVpHVjRMQ0IyWVd4MVpWMGdiMllnYjNCMGFXOXVZV3h6Vkc5VmMyVXBlMXh1SUNBZ0lHRnlaM011YzNCc2FXTmxLR2x1WkdWNExDQXdMQ0IyWVd4MVpTazdYRzRnSUNBZ2FXWW9ZWEpuY3k1c1pXNW5kR2dnUFQwOUlHRnlhWFI1S1h0Y2JpQWdJQ0FnSUdKeVpXRnJPMXh1SUNBZ0lIMWNiaUFnZlZ4dVhHNGdJSEpsZEhWeWJpQmhjbWR6TzF4dWZWeHVYRzVsZUhCdmNuUWdablZ1WTNScGIyNGdiV0YwWTJnb2NHRjBkR1Z5YmpvZ1lXNTVMQ0JsZUhCeU9pQmhibmtzSUdkMVlYSmtPaUJHZFc1amRHbHZiaUE5SUNncElEMCtJSFJ5ZFdVcE9pQkJjbkpoZVR4aGJuaytJSHRjYmlBZ2JHVjBJSEpsYzNWc2RDQTlJRnRkTzF4dUlDQnNaWFFnY0hKdlkyVnpjMlZrVUdGMGRHVnliaUE5SUdKMWFXeGtUV0YwWTJnb2NHRjBkR1Z5YmlrN1hHNGdJR2xtSUNod2NtOWpaWE56WldSUVlYUjBaWEp1S0dWNGNISXNJSEpsYzNWc2RDa2dKaVlnWjNWaGNtUXVZWEJ3Ykhrb2RHaHBjeXdnY21WemRXeDBLU2w3WEc0Z0lDQWdjbVYwZFhKdUlISmxjM1ZzZER0Y2JpQWdmV1ZzYzJWN1hHNGdJQ0FnZEdoeWIzY2dibVYzSUUxaGRHTm9SWEp5YjNJb1pYaHdjaWs3WEc0Z0lIMWNibjFjYmx4dVpYaHdiM0owSUdaMWJtTjBhVzl1SUcxaGRHTm9YMjV2WDNSb2NtOTNLSEJoZEhSbGNtNDZJR0Z1ZVN3Z1pYaHdjam9nWVc1NUxDQm5kV0Z5WkRvZ1JuVnVZM1JwYjI0Z1BTQW9LU0E5UGlCMGNuVmxLVG9nUDBGeWNtRjVQR0Z1ZVQ0Z2UxeHVJQ0IwY25sN1hHNGdJQ0FnY21WMGRYSnVJRzFoZEdOb0tIQmhkSFJsY200c0lHVjRjSElzSUdkMVlYSmtLVHRjYmlBZ2ZXTmhkR05vS0dVcGUxeHVJQ0FnSUdsbUtHVWdhVzV6ZEdGdVkyVnZaaUJOWVhSamFFVnljbTl5SUh4OElHVXViV1Z6YzJGblpTNXpkR0Z5ZEhOWGFYUm9LQ2RPYnlCdFlYUmphQ0JtYjNJNkp5a3BlMXh1SUNBZ0lDQWdjbVYwZFhKdUlHNTFiR3c3WEc0Z0lDQWdmVnh1WEc0Z0lDQWdkR2h5YjNjZ1pUdGNiaUFnZlZ4dWZWeHVYRzVsZUhCdmNuUWdablZ1WTNScGIyNGdjR0YwZEdWeWJrMWhjQ2hqYjJ4c1pXTjBhVzl1T2lCQmNuSmhlVHhoYm5rK0xDQndZWFIwWlhKdU9pQmhibmtzSUdaMWJqb2dSblZ1WTNScGIyNHNJR2QxWVhKa09pQkdkVzVqZEdsdmJpQTlJQ2dwSUQwK0lIUnlkV1VwT2lCQmNuSmhlVHhoYm5rK0lIdGNiaUFnYkdWMElISmxkQ0E5SUZ0ZE8xeHVYRzRnSUdadmNpaHNaWFFnWld4bGJTQnZaaUJqYjJ4c1pXTjBhVzl1S1h0Y2JpQWdJQ0IwY25sN1hHNGdJQ0FnSUNCc1pYUWdjbVZ6ZFd4MElEMGdablZ1TG1Gd2NHeDVLSFJvYVhNc0lHMWhkR05vS0hCaGRIUmxjbTRzSUdWc1pXMHNJR2QxWVhKa0tTazdYRzRnSUNBZ0lDQnlaWFFnUFNCeVpYUXVZMjl1WTJGMEtISmxjM1ZzZENrN1hHNGdJQ0FnZldOaGRHTm9LR1VwZTF4dUlDQWdJR2xtS0NFb1pTQnBibk4wWVc1alpXOW1JRTFoZEdOb1JYSnliM0lwS1h0Y2JpQWdJQ0FnSUNBZ2RHaHliM2NnWlR0Y2JpQWdJQ0FnSUgxY2JpQWdJQ0I5WEc0Z0lIMWNibHh1SUNCeVpYUjFjbTRnY21WME8xeHVmVnh1SWwwc0luTnZkWEpqWlZKdmIzUWlPaUl2YzI5MWNtTmxMeUo5XG4iLCJcblxuaW1wb3J0IHsgZGVmbWF0Y2gsIG1hdGNoLCBNYXRjaEVycm9yLCBtYXRjaF9ub190aHJvdywgcGF0dGVybk1hcCwgQ2FzZSwgbWFrZV9jYXNlIH0gZnJvbSBcIi4vcGF0dGVybnMvZGVmbWF0Y2hcIjtcbmltcG9ydCB7IHZhcmlhYmxlLCB3aWxkY2FyZCwgc3RhcnRzV2l0aCwgY2FwdHVyZSwgaGVhZFRhaWwsIHR5cGUsIGJvdW5kLCBiaXRTdHJpbmdNYXRjaCB9IGZyb20gXCIuL3BhdHRlcm5zL3R5cGVzXCI7XG5cbmV4cG9ydCBkZWZhdWx0IHtcbiAgZGVmbWF0Y2gsIG1hdGNoLCBNYXRjaEVycm9yLCBtYXRjaF9ub190aHJvdyxcbiAgdmFyaWFibGUsIHdpbGRjYXJkLCBzdGFydHNXaXRoLFxuICBjYXB0dXJlLCBoZWFkVGFpbCwgdHlwZSwgYm91bmQsIENhc2UsIG1ha2VfY2FzZSwgYml0U3RyaW5nTWF0Y2hcbn07XG4vLyMgc291cmNlTWFwcGluZ1VSTD1kYXRhOmFwcGxpY2F0aW9uL2pzb247YmFzZTY0LGV5SjJaWEp6YVc5dUlqb3pMQ0p6YjNWeVkyVnpJanBiSW14cFlpOWpiM0psTDNCaGRIUmxjbTV6TG1weklsMHNJbTVoYldWeklqcGJYU3dpYldGd2NHbHVaM01pT2lJN08wRkJSVUVzVTBGQlV5eFJRVUZVTEVWQlFXMUNMRXRCUVc1Q0xFVkJRVEJDTEZWQlFURkNMRVZCUVhORExHTkJRWFJETEVWQlFYTkVMRlZCUVhSRUxFVkJRV3RGTEVsQlFXeEZMRVZCUVhkRkxGTkJRWGhGTEZGQlFYbEdMSEZDUVVGNlJqdEJRVU5CTEZOQlFWTXNVVUZCVkN4RlFVRnRRaXhSUVVGdVFpeEZRVUUyUWl4VlFVRTNRaXhGUVVGNVF5eFBRVUY2UXl4RlFVRnJSQ3hSUVVGc1JDeEZRVUUwUkN4SlFVRTFSQ3hGUVVGclJTeExRVUZzUlN4RlFVRjVSU3hqUVVGNlJTeFJRVUVyUml4clFrRkJMMFk3TzBGQlIwRXNaVUZCWlR0QlFVTmlMRlZCUkdFc1JVRkRTQ3hMUVVSSExFVkJRMGtzVlVGRVNpeEZRVU5uUWl4alFVUm9RanRCUVVWaUxGVkJSbUVzUlVGRlNDeFJRVVpITEVWQlJVOHNWVUZHVUR0QlFVZGlMRk5CU0dFc1JVRkhTaXhSUVVoSkxFVkJSMDBzU1VGSVRpeEZRVWRaTEV0QlNGb3NSVUZIYlVJc1NVRklia0lzUlVGSGVVSXNVMEZJZWtJc1JVRkhiME1zWTBGSWNFTTdRMEZCWmlJc0ltWnBiR1VpT2lKc2FXSXZZMjl5WlM5d1lYUjBaWEp1Y3k1cWN5SXNJbk52ZFhKalpYTkRiMjUwWlc1MElqcGJJaThxSUVCbWJHOTNJQ292WEc1Y2JtbHRjRzl5ZENCN0lHUmxabTFoZEdOb0xDQnRZWFJqYUN3Z1RXRjBZMmhGY25KdmNpd2diV0YwWTJoZmJtOWZkR2h5YjNjc0lIQmhkSFJsY201TllYQXNJRU5oYzJVc0lHMWhhMlZmWTJGelpTQjlJR1p5YjIwZ1hDSXVMM0JoZEhSbGNtNXpMMlJsWm0xaGRHTm9YQ0k3WEc1cGJYQnZjblFnZXlCMllYSnBZV0pzWlN3Z2QybHNaR05oY21Rc0lITjBZWEowYzFkcGRHZ3NJR05oY0hSMWNtVXNJR2hsWVdSVVlXbHNMQ0IwZVhCbExDQmliM1Z1WkN3Z1ltbDBVM1J5YVc1blRXRjBZMmdnZlNCbWNtOXRJRndpTGk5d1lYUjBaWEp1Y3k5MGVYQmxjMXdpTzF4dVhHNWNibVY0Y0c5eWRDQmtaV1poZFd4MElIdGNiaUFnWkdWbWJXRjBZMmdzSUcxaGRHTm9MQ0JOWVhSamFFVnljbTl5TENCdFlYUmphRjl1YjE5MGFISnZkeXhjYmlBZ2RtRnlhV0ZpYkdVc0lIZHBiR1JqWVhKa0xDQnpkR0Z5ZEhOWGFYUm9MRnh1SUNCallYQjBkWEpsTENCb1pXRmtWR0ZwYkN3Z2RIbHdaU3dnWW05MWJtUXNJRU5oYzJVc0lHMWhhMlZmWTJGelpTd2dZbWwwVTNSeWFXNW5UV0YwWTJoY2JuMDdYRzRpWFN3aWMyOTFjbU5sVW05dmRDSTZJaTl6YjNWeVkyVXZJbjA9XG4iLCJpbXBvcnQgeyBJbnRlZ2VyLCBGbG9hdCB9IGZyb20gJy4vcHJpbWl0aXZlcyc7XG5cbi8vaHR0cHM6Ly9naXRodWIuY29tL2FpcnBvcnR5aC9wcm90b21vcnBoaXNtXG5jbGFzcyBQcm90b2NvbCB7XG4gIGNvbnN0cnVjdG9yKHNwZWMpIHtcbiAgICB0aGlzLnJlZ2lzdHJ5ID0gbmV3IE1hcCgpO1xuICAgIHRoaXMuZmFsbGJhY2sgPSBudWxsO1xuXG4gICAgZm9yIChsZXQgZnVuTmFtZSBpbiBzcGVjKSB7XG4gICAgICB0aGlzW2Z1bk5hbWVdID0gY3JlYXRlRnVuKGZ1bk5hbWUpLmJpbmQodGhpcyk7XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gY3JlYXRlRnVuKGZ1bk5hbWUpIHtcblxuICAgICAgcmV0dXJuIGZ1bmN0aW9uICguLi5hcmdzKSB7XG4gICAgICAgIGxldCB0aGluZyA9IGFyZ3NbMF07XG4gICAgICAgIGxldCBmdW4gPSBudWxsO1xuXG4gICAgICAgIGlmIChOdW1iZXIuaXNJbnRlZ2VyKHRoaW5nKSAmJiB0aGlzLmhhc0ltcGxlbWVudGF0aW9uKEludGVnZXIpKSB7XG4gICAgICAgICAgZnVuID0gdGhpcy5yZWdpc3RyeS5nZXQoSW50ZWdlcilbZnVuTmFtZV07XG4gICAgICAgIH0gZWxzZSBpZiAodHlwZW9mIHRoaW5nID09PSBcIm51bWJlclwiICYmICFOdW1iZXIuaXNJbnRlZ2VyKHRoaW5nKSAmJiB0aGlzLmhhc0ltcGxlbWVudGF0aW9uKEZsb2F0KSkge1xuICAgICAgICAgIGZ1biA9IHRoaXMucmVnaXN0cnkuZ2V0KEZsb2F0KVtmdW5OYW1lXTtcbiAgICAgICAgfSBlbHNlIGlmICh0aGlzLmhhc0ltcGxlbWVudGF0aW9uKHRoaW5nKSkge1xuICAgICAgICAgIGZ1biA9IHRoaXMucmVnaXN0cnkuZ2V0KHRoaW5nLmNvbnN0cnVjdG9yKVtmdW5OYW1lXTtcbiAgICAgICAgfSBlbHNlIGlmICh0aGlzLmZhbGxiYWNrKSB7XG4gICAgICAgICAgZnVuID0gdGhpcy5mYWxsYmFja1tmdW5OYW1lXTtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmIChmdW4gIT0gbnVsbCkge1xuICAgICAgICAgIGxldCByZXR2YWwgPSBmdW4uYXBwbHkodGhpcywgYXJncyk7XG4gICAgICAgICAgcmV0dXJuIHJldHZhbDtcbiAgICAgICAgfVxuXG4gICAgICAgIHRocm93IG5ldyBFcnJvcihcIk5vIGltcGxlbWVudGF0aW9uIGZvdW5kIGZvciBcIiArIHRoaW5nKTtcbiAgICAgIH07XG4gICAgfVxuICB9XG5cbiAgaW1wbGVtZW50YXRpb24odHlwZSwgaW1wbGVtZW50YXRpb24pIHtcbiAgICBpZiAodHlwZSA9PT0gbnVsbCkge1xuICAgICAgdGhpcy5mYWxsYmFjayA9IGltcGxlbWVudGF0aW9uO1xuICAgIH0gZWxzZSB7XG4gICAgICB0aGlzLnJlZ2lzdHJ5LnNldCh0eXBlLCBpbXBsZW1lbnRhdGlvbik7XG4gICAgfVxuICB9XG5cbiAgaGFzSW1wbGVtZW50YXRpb24odGhpbmcpIHtcbiAgICBpZiAodGhpbmcgPT09IEludGVnZXIgfHwgdGhpbmcgPT09IEZsb2F0KSB7XG4gICAgICByZXR1cm4gdGhpcy5yZWdpc3RyeS5oYXModGhpbmcpO1xuICAgIH1cblxuICAgIHJldHVybiB0aGlzLnJlZ2lzdHJ5Lmhhcyh0aGluZy5jb25zdHJ1Y3Rvcik7XG4gIH1cbn1cblxuZXhwb3J0IGRlZmF1bHQgUHJvdG9jb2w7XG4vLyMgc291cmNlTWFwcGluZ1VSTD1kYXRhOmFwcGxpY2F0aW9uL2pzb247YmFzZTY0LGV5SjJaWEp6YVc5dUlqb3pMQ0p6YjNWeVkyVnpJanBiSW14cFlpOWpiM0psTDNCeWIzUnZZMjlzTG1weklsMHNJbTVoYldWeklqcGJYU3dpYldGd2NHbHVaM01pT2lKQlFVRkJMRk5CUVZNc1QwRkJWQ3hGUVVGclFpeExRVUZzUWl4UlFVRXJRaXhqUVVFdlFqczdPMEZCUjBFc1RVRkJUU3hSUVVGT0xFTkJRV003UVVGRFdpeGpRVUZaTEVsQlFWb3NSVUZCYVVJN1FVRkRaaXhUUVVGTExGRkJRVXdzUjBGQlowSXNTVUZCU1N4SFFVRktMRVZCUVdoQ0xFTkJSR1U3UVVGRlppeFRRVUZMTEZGQlFVd3NSMEZCWjBJc1NVRkJhRUlzUTBGR1pUczdRVUZKWml4VFFVRkxMRWxCUVVrc1QwRkJTaXhKUVVGbExFbEJRWEJDTEVWQlFYbENPMEZCUTNaQ0xGZEJRVXNzVDBGQlRDeEpRVUZuUWl4VlFVRlZMRTlCUVZZc1JVRkJiVUlzU1VGQmJrSXNRMEZCZDBJc1NVRkJlRUlzUTBGQmFFSXNRMEZFZFVJN1MwRkJla0k3TzBGQlNVRXNZVUZCVXl4VFFVRlVMRU5CUVcxQ0xFOUJRVzVDTEVWQlFUSkNPenRCUVVWNlFpeGhRVUZQTEZWQlFWTXNSMEZCUnl4SlFVRklMRVZCUVZNN1FVRkRka0lzV1VGQlNTeFJRVUZSTEV0QlFVc3NRMEZCVEN4RFFVRlNMRU5CUkcxQ08wRkJSWFpDTEZsQlFVa3NUVUZCVFN4SlFVRk9MRU5CUm0xQ096dEJRVWwyUWl4WlFVRkhMRTlCUVU4c1UwRkJVQ3hEUVVGcFFpeExRVUZxUWl4TFFVRXlRaXhMUVVGTExHbENRVUZNTEVOQlFYVkNMRTlCUVhaQ0xFTkJRVE5DTEVWQlFUSkVPMEZCUXpWRUxHZENRVUZOTEV0QlFVc3NVVUZCVEN4RFFVRmpMRWRCUVdRc1EwRkJhMElzVDBGQmJFSXNSVUZCTWtJc1QwRkJNMElzUTBGQlRpeERRVVEwUkR0VFFVRTVSQ3hOUVVWTkxFbEJRVWNzVDBGQlR5eExRVUZRTEV0QlFXbENMRkZCUVdwQ0xFbEJRVFpDTEVOQlFVTXNUMEZCVHl4VFFVRlFMRU5CUVdsQ0xFdEJRV3BDTEVOQlFVUXNTVUZCTkVJc1MwRkJTeXhwUWtGQlRDeERRVUYxUWl4TFFVRjJRaXhEUVVGNlJDeEZRVUYxUmp0QlFVTTVSaXhuUWtGQlRTeExRVUZMTEZGQlFVd3NRMEZCWXl4SFFVRmtMRU5CUVd0Q0xFdEJRV3hDTEVWQlFYbENMRTlCUVhwQ0xFTkJRVTRzUTBGRU9FWTdVMEZCTVVZc1RVRkZRU3hKUVVGSExFdEJRVXNzYVVKQlFVd3NRMEZCZFVJc1MwRkJka0lzUTBGQlNDeEZRVUZwUXp0QlFVTnlReXhuUWtGQlRTeExRVUZMTEZGQlFVd3NRMEZCWXl4SFFVRmtMRU5CUVd0Q0xFMUJRVTBzVjBGQlRpeERRVUZzUWl4RFFVRnhReXhQUVVGeVF5eERRVUZPTEVOQlJIRkRPMU5CUVdwRExFMUJSVUVzU1VGQlJ5eExRVUZMTEZGQlFVd3NSVUZCWXp0QlFVTnlRaXhuUWtGQlRTeExRVUZMTEZGQlFVd3NRMEZCWXl4UFFVRmtMRU5CUVU0c1EwRkVjVUk3VTBGQmFrSTdPMEZCU1U0c1dVRkJSeXhQUVVGUExFbEJRVkFzUlVGQldUdEJRVU5pTEdOQlFVa3NVMEZCVXl4SlFVRkpMRXRCUVVvc1EwRkJWU3hKUVVGV0xFVkJRV2RDTEVsQlFXaENMRU5CUVZRc1EwRkVVenRCUVVWaUxHbENRVUZQTEUxQlFWQXNRMEZHWVR0VFFVRm1PenRCUVV0QkxHTkJRVTBzU1VGQlNTeExRVUZLTEVOQlFWVXNhVU5CUVdsRExFdEJRV3BETEVOQlFXaENMRU5CYmtKMVFqdFBRVUZzUWl4RFFVWnJRanRMUVVFelFqdEhRVkpHT3p0QlFXdERRU3hwUWtGQlpTeEpRVUZtTEVWQlFYRkNMR05CUVhKQ0xFVkJRVzlETzBGQlEyeERMRkZCUVVjc1UwRkJVeXhKUVVGVUxFVkJRV003UVVGRFppeFhRVUZMTEZGQlFVd3NSMEZCWjBJc1kwRkJhRUlzUTBGRVpUdExRVUZxUWl4TlFVVkxPMEZCUTBnc1YwRkJTeXhSUVVGTUxFTkJRV01zUjBGQlpDeERRVUZyUWl4SlFVRnNRaXhGUVVGM1FpeGpRVUY0UWl4RlFVUkhPMHRCUmt3N1IwRkVSanM3UVVGUlFTeHZRa0ZCYTBJc1MwRkJiRUlzUlVGQmVVSTdRVUZEZGtJc1VVRkJTU3hWUVVGVkxFOUJRVllzU1VGQmNVSXNWVUZCVlN4TFFVRldMRVZCUVdkQ08wRkJRM1pETEdGQlFVOHNTMEZCU3l4UlFVRk1MRU5CUVdNc1IwRkJaQ3hEUVVGclFpeExRVUZzUWl4RFFVRlFMRU5CUkhWRE8wdEJRWHBET3p0QlFVbEJMRmRCUVU4c1MwRkJTeXhSUVVGTUxFTkJRV01zUjBGQlpDeERRVUZyUWl4TlFVRk5MRmRCUVU0c1EwRkJla0lzUTBGTWRVSTdSMEZCZWtJN1EwRXpRMFk3TzBGQmNVUkJMR1ZCUVdVc1VVRkJaaUlzSW1acGJHVWlPaUpzYVdJdlkyOXlaUzl3Y205MGIyTnZiQzVxY3lJc0luTnZkWEpqWlhORGIyNTBaVzUwSWpwYkltbHRjRzl5ZENCN0lFbHVkR1ZuWlhJc0lFWnNiMkYwSUgwZ1puSnZiU0FuTGk5d2NtbHRhWFJwZG1Wekp6dGNibHh1THk5b2RIUndjem92TDJkcGRHaDFZaTVqYjIwdllXbHljRzl5ZEhsb0wzQnliM1J2Ylc5eWNHaHBjMjFjYm1Oc1lYTnpJRkJ5YjNSdlkyOXNlMXh1SUNCamIyNXpkSEoxWTNSdmNpaHpjR1ZqS1h0Y2JpQWdJQ0IwYUdsekxuSmxaMmx6ZEhKNUlEMGdibVYzSUUxaGNDZ3BPMXh1SUNBZ0lIUm9hWE11Wm1Gc2JHSmhZMnNnUFNCdWRXeHNPMXh1WEc0Z0lDQWdabTl5SUNoc1pYUWdablZ1VG1GdFpTQnBiaUJ6Y0dWaktYdGNiaUFnSUNBZ0lIUm9hWE5iWm5WdVRtRnRaVjBnUFNCamNtVmhkR1ZHZFc0b1puVnVUbUZ0WlNrdVltbHVaQ2gwYUdsektUdGNiaUFnSUNCOVhHNWNiaUFnSUNCbWRXNWpkR2x2YmlCamNtVmhkR1ZHZFc0b1puVnVUbUZ0WlNsN1hHNWNiaUFnSUNBZ0lISmxkSFZ5YmlCbWRXNWpkR2x2YmlndUxpNWhjbWR6S1NCN1hHNGdJQ0FnSUNBZ0lHeGxkQ0IwYUdsdVp5QTlJR0Z5WjNOYk1GMDdYRzRnSUNBZ0lDQWdJR3hsZENCbWRXNGdQU0J1ZFd4c08xeHVYRzRnSUNBZ0lDQWdJR2xtS0U1MWJXSmxjaTVwYzBsdWRHVm5aWElvZEdocGJtY3BJQ1ltSUhSb2FYTXVhR0Z6U1cxd2JHVnRaVzUwWVhScGIyNG9TVzUwWldkbGNpa3BlMXh1SUNBZ0lDQWdJQ0FnSUdaMWJpQTlJSFJvYVhNdWNtVm5hWE4wY25rdVoyVjBLRWx1ZEdWblpYSXBXMloxYms1aGJXVmRPMXh1SUNBZ0lDQWdJQ0I5Wld4elpTQnBaaWgwZVhCbGIyWWdkR2hwYm1jZ1BUMDlJRndpYm5WdFltVnlYQ0lnSmlZZ0lVNTFiV0psY2k1cGMwbHVkR1ZuWlhJb2RHaHBibWNwSUNZbUlIUm9hWE11YUdGelNXMXdiR1Z0Wlc1MFlYUnBiMjRvUm14dllYUXBLWHRjYmlBZ0lDQWdJQ0FnSUNCbWRXNGdQU0IwYUdsekxuSmxaMmx6ZEhKNUxtZGxkQ2hHYkc5aGRDbGJablZ1VG1GdFpWMDdYRzRnSUNBZ0lDQWdJSDFsYkhObElHbG1LSFJvYVhNdWFHRnpTVzF3YkdWdFpXNTBZWFJwYjI0b2RHaHBibWNwS1h0Y2JpQWdJQ0FnSUNBZ0lDQm1kVzRnUFNCMGFHbHpMbkpsWjJsemRISjVMbWRsZENoMGFHbHVaeTVqYjI1emRISjFZM1J2Y2lsYlpuVnVUbUZ0WlYwN1hHNGdJQ0FnSUNBZ0lIMWxiSE5sSUdsbUtIUm9hWE11Wm1Gc2JHSmhZMnNwZTF4dUlDQWdJQ0FnSUNBZ0lHWjFiaUE5SUhSb2FYTXVabUZzYkdKaFkydGJablZ1VG1GdFpWMDdYRzRnSUNBZ0lDQWdJSDFjYmx4dUlDQWdJQ0FnSUNCcFppaG1kVzRnSVQwZ2JuVnNiQ2w3WEc0Z0lDQWdJQ0FnSUNBZ2JHVjBJSEpsZEhaaGJDQTlJR1oxYmk1aGNIQnNlU2gwYUdsekxDQmhjbWR6S1R0Y2JpQWdJQ0FnSUNBZ0lDQnlaWFIxY200Z2NtVjBkbUZzTzF4dUlDQWdJQ0FnSUNCOVhHNWNiaUFnSUNBZ0lDQWdkR2h5YjNjZ2JtVjNJRVZ5Y205eUtGd2lUbThnYVcxd2JHVnRaVzUwWVhScGIyNGdabTkxYm1RZ1ptOXlJRndpSUNzZ2RHaHBibWNwTzF4dUlDQWdJQ0FnZlR0Y2JpQWdJQ0I5WEc0Z0lIMWNibHh1SUNCcGJYQnNaVzFsYm5SaGRHbHZiaWgwZVhCbExDQnBiWEJzWlcxbGJuUmhkR2x2YmlsN1hHNGdJQ0FnYVdZb2RIbHdaU0E5UFQwZ2JuVnNiQ2w3WEc0Z0lDQWdJQ0IwYUdsekxtWmhiR3hpWVdOcklEMGdhVzF3YkdWdFpXNTBZWFJwYjI0N1hHNGdJQ0FnZldWc2MyVjdYRzRnSUNBZ0lDQjBhR2x6TG5KbFoybHpkSEo1TG5ObGRDaDBlWEJsTENCcGJYQnNaVzFsYm5SaGRHbHZiaWs3WEc0Z0lDQWdmVnh1SUNCOVhHNWNiaUFnYUdGelNXMXdiR1Z0Wlc1MFlYUnBiMjRvZEdocGJtY3BJSHRjYmlBZ0lDQnBaaUFvZEdocGJtY2dQVDA5SUVsdWRHVm5aWElnZkh3Z2RHaHBibWNnUFQwOUlFWnNiMkYwS1h0Y2JpQWdJQ0FnSUhKbGRIVnliaUIwYUdsekxuSmxaMmx6ZEhKNUxtaGhjeWgwYUdsdVp5azdYRzRnSUNBZ2ZWeHVYRzRnSUNBZ2NtVjBkWEp1SUhSb2FYTXVjbVZuYVhOMGNua3VhR0Z6S0hSb2FXNW5MbU52Ym5OMGNuVmpkRzl5S1R0Y2JpQWdmVnh1ZlZ4dVhHNWNibVY0Y0c5eWRDQmtaV1poZFd4MElGQnliM1J2WTI5c08xeHVJbDBzSW5OdmRYSmpaVkp2YjNRaU9pSXZjMjkxY21ObEx5SjlcbiIsImltcG9ydCB7IFR1cGxlIH0gZnJvbSAnLi9wcmltaXRpdmVzJztcbmltcG9ydCBCaXRTdHJpbmcgZnJvbSAnLi9iaXRfc3RyaW5nJztcbmltcG9ydCBQYXR0ZXJucyBmcm9tICcuL3BhdHRlcm5zJztcbmltcG9ydCBQcm90b2NvbCBmcm9tICcuL3Byb3RvY29sJztcblxuZnVuY3Rpb24gY2FsbF9wcm9wZXJ0eShpdGVtLCBwcm9wZXJ0eSkge1xuICBsZXQgcHJvcCA9IG51bGw7XG5cbiAgaWYgKHR5cGVvZiBpdGVtID09PSBcIm51bWJlclwiIHx8IHR5cGVvZiBpdGVtID09PSBcInN5bWJvbFwiIHx8IHR5cGVvZiBpdGVtID09PSBcImJvb2xlYW5cIiB8fCB0eXBlb2YgaXRlbSA9PT0gXCJzdHJpbmdcIikge1xuICAgIGlmIChpdGVtW3Byb3BlcnR5XSAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICBwcm9wID0gcHJvcGVydHk7XG4gICAgfSBlbHNlIGlmIChpdGVtW1N5bWJvbC5mb3IocHJvcGVydHkpXSAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICBwcm9wID0gU3ltYm9sLmZvcihwcm9wZXJ0eSk7XG4gICAgfVxuICB9IGVsc2Uge1xuICAgIGlmIChwcm9wZXJ0eSBpbiBpdGVtKSB7XG4gICAgICBwcm9wID0gcHJvcGVydHk7XG4gICAgfSBlbHNlIGlmIChTeW1ib2wuZm9yKHByb3BlcnR5KSBpbiBpdGVtKSB7XG4gICAgICBwcm9wID0gU3ltYm9sLmZvcihwcm9wZXJ0eSk7XG4gICAgfVxuICB9XG5cbiAgaWYgKHByb3AgPT09IG51bGwpIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoYFByb3BlcnR5ICR7IHByb3BlcnR5IH0gbm90IGZvdW5kIGluICR7IGl0ZW0gfWApO1xuICB9XG5cbiAgaWYgKGl0ZW1bcHJvcF0gaW5zdGFuY2VvZiBGdW5jdGlvbikge1xuICAgIHJldHVybiBpdGVtW3Byb3BdKCk7XG4gIH0gZWxzZSB7XG4gICAgcmV0dXJuIGl0ZW1bcHJvcF07XG4gIH1cbn1cblxuZnVuY3Rpb24gYXBwbHkoLi4uYXJncykge1xuICBpZiAoYXJncy5sZW5ndGggPT09IDIpIHtcbiAgICBhcmdzWzBdLmFwcGx5KG51bGwsIGFyZ3Muc2xpY2UoMSkpO1xuICB9IGVsc2Uge1xuICAgIGFyZ3NbMF1bYXJnc1sxXV0uYXBwbHkobnVsbCwgYXJncy5zbGljZSgyKSk7XG4gIH1cbn1cblxuZnVuY3Rpb24gY29udGFpbnMobGVmdCwgcmlnaHQpIHtcbiAgZm9yIChsZXQgeCBvZiByaWdodCkge1xuICAgIGlmIChQYXR0ZXJucy5tYXRjaF9ub190aHJvdyhsZWZ0LCB4KSAhPSBudWxsKSB7XG4gICAgICByZXR1cm4gdHJ1ZTtcbiAgICB9XG4gIH1cblxuICByZXR1cm4gZmFsc2U7XG59XG5cbmZ1bmN0aW9uIGdldF9nbG9iYWwoKSB7XG4gIGlmICh0eXBlb2Ygc2VsZiAhPT0gXCJ1bmRlZmluZWRcIikge1xuICAgIHJldHVybiBzZWxmO1xuICB9IGVsc2UgaWYgKHR5cGVvZiB3aW5kb3cgIT09IFwidW5kZWZpbmVkXCIpIHtcbiAgICByZXR1cm4gd2luZG93O1xuICB9IGVsc2UgaWYgKHR5cGVvZiBnbG9iYWwgIT09IFwidW5kZWZpbmVkXCIpIHtcbiAgICByZXR1cm4gZ2xvYmFsO1xuICB9XG5cbiAgdGhyb3cgbmV3IEVycm9yKFwiTm8gZ2xvYmFsIHN0YXRlIGZvdW5kXCIpO1xufVxuXG5mdW5jdGlvbiBkZWZzdHJ1Y3QoZGVmYXVsdHMpIHtcbiAgcmV0dXJuIGNsYXNzIHtcbiAgICBjb25zdHJ1Y3Rvcih1cGRhdGUgPSB7fSkge1xuICAgICAgbGV0IHRoZV92YWx1ZXMgPSBPYmplY3QuYXNzaWduKGRlZmF1bHRzLCB1cGRhdGUpO1xuICAgICAgT2JqZWN0LmFzc2lnbih0aGlzLCB0aGVfdmFsdWVzKTtcbiAgICB9XG5cbiAgICBzdGF0aWMgY3JlYXRlKHVwZGF0ZXMgPSB7fSkge1xuICAgICAgbGV0IHggPSBuZXcgdGhpcyh1cGRhdGVzKTtcbiAgICAgIHJldHVybiBPYmplY3QuZnJlZXplKHgpO1xuICAgIH1cbiAgfTtcbn1cblxuZnVuY3Rpb24gZGVmZXhjZXB0aW9uKGRlZmF1bHRzKSB7XG4gIHJldHVybiBjbGFzcyBleHRlbmRzIEVycm9yIHtcbiAgICBjb25zdHJ1Y3Rvcih1cGRhdGUgPSB7fSkge1xuICAgICAgbGV0IG1lc3NhZ2UgPSB1cGRhdGUubWVzc2FnZSB8fCBcIlwiO1xuICAgICAgc3VwZXIobWVzc2FnZSk7XG5cbiAgICAgIGxldCB0aGVfdmFsdWVzID0gT2JqZWN0LmFzc2lnbihkZWZhdWx0cywgdXBkYXRlKTtcbiAgICAgIE9iamVjdC5hc3NpZ24odGhpcywgdGhlX3ZhbHVlcyk7XG5cbiAgICAgIHRoaXMubmFtZSA9IHRoaXMuY29uc3RydWN0b3IubmFtZTtcbiAgICAgIHRoaXMubWVzc2FnZSA9IG1lc3NhZ2U7XG4gICAgICB0aGlzW1NwZWNpYWxGb3Jtcy5hdG9tKFwiX19leGNlcHRpb25fX1wiKV0gPSB0cnVlO1xuICAgICAgRXJyb3IuY2FwdHVyZVN0YWNrVHJhY2UodGhpcywgdGhpcy5jb25zdHJ1Y3Rvci5uYW1lKTtcbiAgICB9XG5cbiAgICBzdGF0aWMgY3JlYXRlKHVwZGF0ZXMgPSB7fSkge1xuICAgICAgbGV0IHggPSBuZXcgdGhpcyh1cGRhdGVzKTtcbiAgICAgIHJldHVybiBPYmplY3QuZnJlZXplKHgpO1xuICAgIH1cbiAgfTtcbn1cblxuZnVuY3Rpb24gZGVmcHJvdG9jb2woc3BlYykge1xuICByZXR1cm4gbmV3IFByb3RvY29sKHNwZWMpO1xufVxuXG5mdW5jdGlvbiBkZWZpbXBsKHByb3RvY29sLCB0eXBlLCBpbXBsKSB7XG4gIHByb3RvY29sLmltcGxlbWVudGF0aW9uKHR5cGUsIGltcGwpO1xufVxuXG5mdW5jdGlvbiBnZXRfb2JqZWN0X2tleXMob2JqKSB7XG4gIHJldHVybiBPYmplY3Qua2V5cyhvYmopLmNvbmNhdChPYmplY3QuZ2V0T3duUHJvcGVydHlTeW1ib2xzKG9iaikpO1xufVxuXG5mdW5jdGlvbiBpc192YWxpZF9jaGFyYWN0ZXIoY29kZXBvaW50KSB7XG4gIHRyeSB7XG4gICAgcmV0dXJuIFN0cmluZy5mcm9tQ29kZVBvaW50KGNvZGVwb2ludCkgIT0gbnVsbDtcbiAgfSBjYXRjaCAoZSkge1xuICAgIHJldHVybiBmYWxzZTtcbiAgfVxufVxuXG4vL2h0dHBzOi8vZGV2ZWxvcGVyLm1vemlsbGEub3JnL2VuLVVTL2RvY3MvV2ViL0FQSS9XaW5kb3dCYXNlNjQvQmFzZTY0X2VuY29kaW5nX2FuZF9kZWNvZGluZyNTb2x1dGlvbl8yXyVFMiU4MCU5M19yZXdyaXRlX3RoZV9ET01zX2F0b2IoKV9hbmRfYnRvYSgpX3VzaW5nX0phdmFTY3JpcHQnc19UeXBlZEFycmF5c19hbmRfVVRGLThcbmZ1bmN0aW9uIGI2NEVuY29kZVVuaWNvZGUoc3RyKSB7XG4gIHJldHVybiBidG9hKGVuY29kZVVSSUNvbXBvbmVudChzdHIpLnJlcGxhY2UoLyUoWzAtOUEtRl17Mn0pL2csIGZ1bmN0aW9uIChtYXRjaCwgcDEpIHtcbiAgICByZXR1cm4gU3RyaW5nLmZyb21DaGFyQ29kZSgnMHgnICsgcDEpO1xuICB9KSk7XG59XG5cbmZ1bmN0aW9uIGRlbGV0ZV9wcm9wZXJ0eV9mcm9tX21hcChtYXAsIHByb3BlcnR5KSB7XG4gIGxldCBuZXdfbWFwID0gT2JqZWN0LmFzc2lnbihPYmplY3QuY3JlYXRlKG1hcC5jb25zdHJ1Y3Rvci5wcm90b3R5cGUpLCBtYXApO1xuICBkZWxldGUgbmV3X21hcFtwcm9wZXJ0eV07XG5cbiAgcmV0dXJuIE9iamVjdC5mcmVlemUobmV3X21hcCk7XG59XG5cbmZ1bmN0aW9uIGNsYXNzX3RvX29iaihtYXApIHtcbiAgbGV0IG5ld19tYXAgPSBPYmplY3QuYXNzaWduKHt9LCBtYXApO1xuICByZXR1cm4gT2JqZWN0LmZyZWV6ZShuZXdfbWFwKTtcbn1cblxuZnVuY3Rpb24gYWRkX3Byb3BlcnR5X3RvX21hcChtYXAsIHByb3BlcnR5LCB2YWx1ZSkge1xuICBsZXQgbmV3X21hcCA9IE9iamVjdC5hc3NpZ24oe30sIG1hcCk7XG4gIG5ld19tYXBbcHJvcGVydHldID0gdmFsdWU7XG4gIHJldHVybiBPYmplY3QuZnJlZXplKG5ld19tYXApO1xufVxuXG5mdW5jdGlvbiB1cGRhdGVfbWFwKG1hcCwgcHJvcGVydHksIHZhbHVlKSB7XG4gIGlmIChwcm9wZXJ0eSBpbiBnZXRfb2JqZWN0X2tleXMobWFwKSkge1xuICAgIHJldHVybiBhZGRfcHJvcGVydHlfdG9fbWFwKG1hcCwgcHJvcGVydHksIHZhbHVlKTtcbiAgfVxuXG4gIHRocm93IFwibWFwIGRvZXMgbm90IGhhdmUga2V5XCI7XG59XG5cbmZ1bmN0aW9uIGJub3QoZXhwcikge1xuICByZXR1cm4gfmV4cHI7XG59XG5cbmZ1bmN0aW9uIGJhbmQobGVmdCwgcmlnaHQpIHtcbiAgcmV0dXJuIGxlZnQgJiByaWdodDtcbn1cblxuZnVuY3Rpb24gYm9yKGxlZnQsIHJpZ2h0KSB7XG4gIHJldHVybiBsZWZ0IHwgcmlnaHQ7XG59XG5cbmZ1bmN0aW9uIGJzbChsZWZ0LCByaWdodCkge1xuICByZXR1cm4gbGVmdCA8PCByaWdodDtcbn1cblxuZnVuY3Rpb24gYnNyKGxlZnQsIHJpZ2h0KSB7XG4gIHJldHVybiBsZWZ0ID4+IHJpZ2h0O1xufVxuXG5mdW5jdGlvbiBieG9yKGxlZnQsIHJpZ2h0KSB7XG4gIHJldHVybiBsZWZ0IF4gcmlnaHQ7XG59XG5cbmZ1bmN0aW9uIHppcChsaXN0X29mX2xpc3RzKSB7XG4gIGlmIChsaXN0X29mX2xpc3RzLmxlbmd0aCA9PT0gMCkge1xuICAgIHJldHVybiBPYmplY3QuZnJlZXplKFtdKTtcbiAgfVxuXG4gIGxldCBuZXdfdmFsdWUgPSBbXTtcbiAgbGV0IHNtYWxsZXN0X2xlbmd0aCA9IGxpc3Rfb2ZfbGlzdHNbMF07XG5cbiAgZm9yIChsZXQgeCBvZiBsaXN0X29mX2xpc3RzKSB7XG4gICAgaWYgKHgubGVuZ3RoIDwgc21hbGxlc3RfbGVuZ3RoKSB7XG4gICAgICBzbWFsbGVzdF9sZW5ndGggPSB4Lmxlbmd0aDtcbiAgICB9XG4gIH1cblxuICBmb3IgKGxldCBpID0gMDsgaSA8IHNtYWxsZXN0X2xlbmd0aDsgaSsrKSB7XG4gICAgbGV0IGN1cnJlbnRfdmFsdWUgPSBbXTtcbiAgICBmb3IgKGxldCBqID0gMDsgaiA8IGxpc3Rfb2ZfbGlzdHMubGVuZ3RoOyBqKyspIHtcbiAgICAgIGN1cnJlbnRfdmFsdWUucHVzaChsaXN0X29mX2xpc3RzW2pdW2ldKTtcbiAgICB9XG5cbiAgICBuZXdfdmFsdWUucHVzaChuZXcgVHVwbGUoLi4uY3VycmVudF92YWx1ZSkpO1xuICB9XG5cbiAgcmV0dXJuIE9iamVjdC5mcmVlemUobmV3X3ZhbHVlKTtcbn1cblxuZnVuY3Rpb24gY2FuX2RlY29kZTY0KGRhdGEpIHtcbiAgdHJ5IHtcbiAgICBhdG9iKGRhdGEpO1xuICAgIHJldHVybiB0cnVlO1xuICB9IGNhdGNoIChlKSB7XG4gICAgcmV0dXJuIGZhbHNlO1xuICB9XG59XG5cbmZ1bmN0aW9uIHJlbW92ZV9mcm9tX2xpc3QobGlzdCwgZWxlbWVudCkge1xuICBsZXQgZm91bmQgPSBmYWxzZTtcblxuICByZXR1cm4gbGlzdC5maWx0ZXIoZWxlbSA9PiB7XG4gICAgaWYgKCFmb3VuZCAmJiBlbGVtID09PSBlbGVtZW50KSB7XG4gICAgICBmb3VuZCA9IHRydWU7XG4gICAgICByZXR1cm4gZmFsc2U7XG4gICAgfVxuXG4gICAgcmV0dXJuIHRydWU7XG4gIH0pO1xufVxuXG5mdW5jdGlvbiBmb2xkbChmdW4sIGFjYywgbGlzdCkge1xuICBsZXQgYWNjMSA9IGFjYztcblxuICBmb3IgKGNvbnN0IGVsIG9mIGxpc3QpIHtcbiAgICBhY2MxID0gZnVuKGVsLCBhY2MxKTtcbiAgfVxuXG4gIHJldHVybiBhY2MxO1xufVxuXG5mdW5jdGlvbiBmb2xkcihmdW4sIGFjYywgbGlzdCkge1xuICBsZXQgYWNjMSA9IGFjYztcblxuICBmb3IgKGxldCBpID0gbGlzdC5sZW5ndGggLSAxOyBpID49IDA7IGktLSkge1xuICAgIGFjYzEgPSBmdW4obGlzdFtpXSwgYWNjMSk7XG4gIH1cblxuICByZXR1cm4gYWNjMTtcbn1cblxuZnVuY3Rpb24ga2V5ZmluZChrZXksIG4sIHR1cGxlbGlzdCkge1xuXG4gIGZvciAobGV0IGkgPSB0dXBsZWxpc3QubGVuZ3RoIC0gMTsgaSA+PSAwOyBpLS0pIHtcbiAgICBpZiAodHVwbGVsaXN0W2ldLmdldChuKSA9PT0ga2V5KSB7XG4gICAgICByZXR1cm4gdHVwbGVsaXN0W2ldO1xuICAgIH1cbiAgfVxuXG4gIHJldHVybiBmYWxzZTtcbn1cblxuZnVuY3Rpb24ga2V5ZGVsZXRlKGtleSwgbiwgdHVwbGVsaXN0KSB7XG5cbiAgZm9yIChsZXQgaSA9IHR1cGxlbGlzdC5sZW5ndGggLSAxOyBpID49IDA7IGktLSkge1xuICAgIGlmICh0dXBsZWxpc3RbaV0uZ2V0KG4pID09PSBrZXkpIHtcbiAgICAgIHJldHVybiB0dXBsZWxpc3QuY29uY2F0KFtdKS5zcGxpY2UoaSwgMSk7XG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIHR1cGxlbGlzdDtcbn1cblxuZnVuY3Rpb24ga2V5c3RvcmUoa2V5LCBuLCBsaXN0LCBuZXd0dXBsZSkge1xuICBmb3IgKGxldCBpID0gbGlzdC5sZW5ndGggLSAxOyBpID49IDA7IGktLSkge1xuICAgIGlmIChsaXN0W2ldLmdldChuKSA9PT0ga2V5KSB7XG4gICAgICByZXR1cm4gbGlzdC5jb25jYXQoW10pLnNwbGljZShpLCAxLCBuZXd0dXBsZSk7XG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIGxpc3QuY29uY2F0KFtdKS5wdXNoKG5ld3R1cGxlKTtcbn1cblxuZnVuY3Rpb24ga2V5bWVtYmVyKGtleSwgbiwgbGlzdCkge1xuICBmb3IgKGxldCBpID0gbGlzdC5sZW5ndGggLSAxOyBpID49IDA7IGktLSkge1xuICAgIGlmIChsaXN0W2ldLmdldChuKSA9PT0ga2V5KSB7XG4gICAgICByZXR1cm4gdHJ1ZTtcbiAgICB9XG4gIH1cblxuICByZXR1cm4gZmFsc2U7XG59XG5cbmZ1bmN0aW9uIGtleXRha2Uoa2V5LCBuLCBsaXN0KSB7XG4gIGlmICgha2V5bWVtYmVyKGtleSwgbiwgbGlzdCkpIHtcbiAgICByZXR1cm4gZmFsc2U7XG4gIH1cblxuICBsZXQgdHVwbGUgPSBrZXlmaW5kKGtleSwgbiwgbGlzdCk7XG5cbiAgcmV0dXJuIG5ldyBUdXBsZSh0dXBsZS5nZXQobiksIHR1cGxlLCBrZXlkZWxldGUoa2V5LCBuLCBsaXN0KSk7XG59XG5cbmZ1bmN0aW9uIGtleXJlcGxhY2Uoa2V5LCBuLCBsaXN0LCBuZXd0dXBsZSkge1xuXG4gIGZvciAobGV0IGkgPSB0dXBsZWxpc3QubGVuZ3RoIC0gMTsgaSA+PSAwOyBpLS0pIHtcbiAgICBpZiAodHVwbGVsaXN0W2ldLmdldChuKSA9PT0ga2V5KSB7XG4gICAgICByZXR1cm4gdHVwbGVsaXN0LmNvbmNhdChbXSkuc3BsaWNlKGksIDEsIG5ld3R1cGxlKTtcbiAgICB9XG4gIH1cblxuICByZXR1cm4gdHVwbGVsaXN0O1xufVxuXG5mdW5jdGlvbiByZXZlcnNlKGxpc3QpIHtcbiAgcmV0dXJuIGxpc3QuY29uY2F0KFtdKS5yZXZlcnNlKCk7XG59XG5cbmZ1bmN0aW9uIG1hcHNfZmluZChrZXksIG1hcCkge1xuICBpZiAoa2V5IGluIGdldF9vYmplY3Rfa2V5cyhtYXApKSB7XG4gICAgcmV0dXJuIG5ldyBUdXBsZShTeW1ib2wuZm9yKFwib2tcIiksIG1hcFtrZXldKTtcbiAgfSBlbHNlIHtcbiAgICByZXR1cm4gU3ltYm9sLmZvcihcImVycm9yXCIpO1xuICB9XG59XG5cbmZ1bmN0aW9uIGZsYXR0ZW4obGlzdCwgdGFpbCA9IFtdKSB7XG4gIGxldCBuZXdfbGlzdCA9IFtdO1xuXG4gIGZvciAobGV0IGUgb2YgbGlzdCkge1xuICAgIGlmIChpc0FycmF5KGUpKSB7XG4gICAgICBuZXdfbGlzdCA9IG5ld19saXN0LmNvbmNhdChmbGF0dGVuKGUpKTtcbiAgICB9IGVsc2Uge1xuICAgICAgbmV3X2xpc3QucHVzaChlKTtcbiAgICB9XG4gIH1cblxuICByZXR1cm4gT2JqZWN0LmZyZWV6ZShuZXdfbGlzdC5jb25jYXQodGFpbCkpO1xufVxuXG5mdW5jdGlvbiBkdXBsaWNhdGUobiwgZWxlbSkge1xuICBsZXQgbGlzdCA9IFtdO1xuXG4gIGZvciAobGV0IGkgPSAwOyBpIDwgbjsgaSsrKSB7XG4gICAgbGlzdC5wdXNoKGVsZW0pO1xuICB9XG5cbiAgcmV0dXJuIE9iamVjdC5mcmVlemUobGlzdCk7XG59XG5cbmZ1bmN0aW9uIG1hcGZvbGRsKGZ1biwgYWNjLCBsaXN0KSB7XG4gIGxldCBuZXdsaXN0ID0gW107XG5cbiAgZm9yIChsZXQgeCBvZiBsaXN0KSB7XG4gICAgbGV0IHR1cCA9IGZ1bih4LCBhY2MpO1xuICAgIG5ld2xpc3QucHVzaCh0dXAuZ2V0KDApKTtcbiAgICBhY2MgPSB0dXAuZ2V0KDEpO1xuICB9XG5cbiAgcmV0dXJuIG5ldyBUdXBsZShPYmplY3QuZnJlZXplKG5ld2xpc3QpLCBhY2MpO1xufVxuXG5mdW5jdGlvbiBmaWx0ZXJtYXAoZnVuLCBsaXN0KSB7XG4gIGxldCBuZXdsaXN0ID0gW107XG5cbiAgZm9yICh4IG9mIGxpc3QpIHtcbiAgICBsZXQgcmVzdWx0ID0gZnVuKHgpO1xuXG4gICAgaWYgKHJlc3VsdCA9PT0gdHJ1ZSkge1xuICAgICAgbmV3bGlzdC5wdXNoKHgpO1xuICAgIH0gZWxzZSBpZiAocmVzdWx0IGluc3RhbmNlb2YgVHVwbGUpIHtcbiAgICAgIG5ld2xpc3QucHVzaChyZXN1bHQuZ2V0KDEpKTtcbiAgICB9XG4gIH1cblxuICByZXR1cm4gT2JqZWN0LmZyZWV6ZShuZXdsaXN0KTtcbn1cblxuZnVuY3Rpb24gbWFwc19mb2xkKGZ1biwgYWNjLCBtYXApIHtcbiAgbGV0IGFjYzEgPSBhY2M7XG5cbiAgZm9yIChsZXQgayBvZiBnZXRfb2JqZWN0X2tleXMobWFwKSkge1xuICAgIGFjYzEgPSBmdW4oaywgbWFwW2tdLCBhY2MxKTtcbiAgfVxuXG4gIHJldHVybiBhY2MxO1xufVxuXG5mdW5jdGlvbiBtYXBzX2Zyb21fbGlzdChsaXN0KSB7XG4gIGxldCBtID0ge307XG5cbiAgZm9yICh4IG9mIGxpc3QpIHtcbiAgICBtW3guZ2V0KDApXSA9IHguZ2V0KDEpO1xuICB9XG5cbiAgcmV0dXJuIE9iamVjdC5mcmVlemUobSk7XG59XG5cbmV4cG9ydCBkZWZhdWx0IHtcbiAgY2FsbF9wcm9wZXJ0eSxcbiAgYXBwbHksXG4gIGNvbnRhaW5zLFxuICBnZXRfZ2xvYmFsLFxuICBkZWZzdHJ1Y3QsXG4gIGRlZmV4Y2VwdGlvbixcbiAgZGVmcHJvdG9jb2wsXG4gIGRlZmltcGwsXG4gIGdldF9vYmplY3Rfa2V5cyxcbiAgaXNfdmFsaWRfY2hhcmFjdGVyLFxuICBiNjRFbmNvZGVVbmljb2RlLFxuICBkZWxldGVfcHJvcGVydHlfZnJvbV9tYXAsXG4gIGFkZF9wcm9wZXJ0eV90b19tYXAsXG4gIGNsYXNzX3RvX29iaixcbiAgY2FuX2RlY29kZTY0LFxuICBibm90LFxuICBiYW5kLFxuICBib3IsXG4gIGJzbCxcbiAgYnNyLFxuICBieG9yLFxuICB6aXAsXG4gIGZvbGRsLFxuICBmb2xkcixcbiAgcmVtb3ZlX2Zyb21fbGlzdCxcbiAga2V5ZGVsZXRlLFxuICBrZXlzdG9yZSxcbiAga2V5ZmluZCxcbiAga2V5dGFrZSxcbiAga2V5cmVwbGFjZSxcbiAgcmV2ZXJzZSxcbiAgdXBkYXRlX21hcCxcbiAgbWFwc19maW5kLFxuICBmbGF0dGVuLFxuICBkdXBsaWNhdGUsXG4gIG1hcGZvbGRsLFxuICBmaWx0ZXJtYXAsXG4gIG1hcHNfZm9sZFxufTtcbi8vIyBzb3VyY2VNYXBwaW5nVVJMPWRhdGE6YXBwbGljYXRpb24vanNvbjtiYXNlNjQsZXlKMlpYSnphVzl1SWpvekxDSnpiM1Z5WTJWeklqcGJJbXhwWWk5amIzSmxMMloxYm1OMGFXOXVjeTVxY3lKZExDSnVZVzFsY3lJNlcxMHNJbTFoY0hCcGJtZHpJam9pUVVGQlFTeFRRVUZUTEV0QlFWUXNVVUZCYzBJc1kwRkJkRUk3UVVGRFFTeFBRVUZQTEZOQlFWQXNUVUZCYzBJc1kwRkJkRUk3UVVGRFFTeFBRVUZQTEZGQlFWQXNUVUZCY1VJc1dVRkJja0k3UVVGRFFTeFBRVUZQTEZGQlFWQXNUVUZCY1VJc1dVRkJja0k3TzBGQlJVRXNVMEZCVXl4aFFVRlVMRU5CUVhWQ0xFbEJRWFpDTEVWQlFUWkNMRkZCUVRkQ0xFVkJRWE5ETzBGQlEzQkRMRTFCUVVrc1QwRkJUeXhKUVVGUUxFTkJSR2RET3p0QlFVZHdReXhOUVVGSExFOUJRVThzU1VGQlVDeExRVUZuUWl4UlFVRm9RaXhKUVVFMFFpeFBRVUZQTEVsQlFWQXNTMEZCWjBJc1VVRkJhRUlzU1VGQk5FSXNUMEZCVHl4SlFVRlFMRXRCUVdkQ0xGTkJRV2hDTEVsQlFUWkNMRTlCUVU4c1NVRkJVQ3hMUVVGblFpeFJRVUZvUWl4RlFVRjVRanRCUVVNdlJ5eFJRVUZITEV0QlFVc3NVVUZCVEN4TlFVRnRRaXhUUVVGdVFpeEZRVUUyUWp0QlFVTTVRaXhoUVVGUExGRkJRVkFzUTBGRU9FSTdTMEZCYUVNc1RVRkZUU3hKUVVGSExFdEJRVXNzVDBGQlR5eEhRVUZRTEVOQlFWY3NVVUZCV0N4RFFVRk1MRTFCUVN0Q0xGTkJRUzlDTEVWQlFYbERPMEZCUTJoRUxHRkJRVThzVDBGQlR5eEhRVUZRTEVOQlFWY3NVVUZCV0N4RFFVRlFMRU5CUkdkRU8wdEJRVFZETzBkQlNGSXNUVUZOVHp0QlFVTk1MRkZCUVVjc1dVRkJXU3hKUVVGYUxFVkJRV2xDTzBGQlEyeENMR0ZCUVU4c1VVRkJVQ3hEUVVSclFqdExRVUZ3UWl4TlFVVk5MRWxCUVVjc1QwRkJUeXhIUVVGUUxFTkJRVmNzVVVGQldDeExRVUYzUWl4SlFVRjRRaXhGUVVFMlFqdEJRVU53UXl4aFFVRlBMRTlCUVU4c1IwRkJVQ3hEUVVGWExGRkJRVmdzUTBGQlVDeERRVVJ2UXp0TFFVRm9RenRIUVZSU096dEJRV05CTEUxQlFVY3NVMEZCVXl4SlFVRlVMRVZCUVdNN1FVRkRaaXhWUVVGTkxFbEJRVWtzUzBGQlNpeERRVUZWTEVOQlFVTXNVMEZCUkN4SFFVRmhMRkZCUVdJc1JVRkJkVUlzWTBGQmRrSXNSMEZCZDBNc1NVRkJlRU1zUlVGQk9FTXNRMEZCZUVRc1EwRkJUaXhEUVVSbE8wZEJRV3BDT3p0QlFVbEJMRTFCUVVjc1MwRkJTeXhKUVVGTUxHRkJRWE5DTEZGQlFYUkNMRVZCUVN0Q08wRkJRMmhETEZkQlFVOHNTMEZCU3l4SlFVRk1MRWRCUVZBc1EwRkVaME03UjBGQmJFTXNUVUZGU3p0QlFVTklMRmRCUVU4c1MwRkJTeXhKUVVGTUxFTkJRVkFzUTBGRVJ6dEhRVVpNTzBOQmNrSkdPenRCUVRSQ1FTeFRRVUZUTEV0QlFWUXNRMEZCWlN4SFFVRkhMRWxCUVVnc1JVRkJVVHRCUVVOeVFpeE5RVUZITEV0QlFVc3NUVUZCVEN4TFFVRm5RaXhEUVVGb1FpeEZRVUZyUWp0QlFVTnVRaXhUUVVGTExFTkJRVXdzUlVGQlVTeExRVUZTTEVOQlFXTXNTVUZCWkN4RlFVRnZRaXhMUVVGTExFdEJRVXdzUTBGQlZ5eERRVUZZTEVOQlFYQkNMRVZCUkcxQ08wZEJRWEpDTEUxQlJVczdRVUZEU0N4VFFVRkxMRU5CUVV3c1JVRkJVU3hMUVVGTExFTkJRVXdzUTBGQlVpeEZRVUZwUWl4TFFVRnFRaXhEUVVGMVFpeEpRVUYyUWl4RlFVRTJRaXhMUVVGTExFdEJRVXdzUTBGQlZ5eERRVUZZTEVOQlFUZENMRVZCUkVjN1IwRkdURHREUVVSR096dEJRVkZCTEZOQlFWTXNVVUZCVkN4RFFVRnJRaXhKUVVGc1FpeEZRVUYzUWl4TFFVRjRRaXhGUVVFNFFqdEJRVU0xUWl4UFFVRkpMRWxCUVVrc1EwRkJTaXhKUVVGVExFdEJRV0lzUlVGQmJVSTdRVUZEYWtJc1VVRkJSeXhUUVVGVExHTkJRVlFzUTBGQmQwSXNTVUZCZUVJc1JVRkJPRUlzUTBGQk9VSXNTMEZCYjBNc1NVRkJjRU1zUlVGQmVVTTdRVUZETVVNc1lVRkJUeXhKUVVGUUxFTkJSREJETzB0QlFUVkRPMGRCUkVZN08wRkJUVUVzVTBGQlR5eExRVUZRTEVOQlVEUkNPME5CUVRsQ096dEJRVlZCTEZOQlFWTXNWVUZCVkN4SFFVRnhRanRCUVVOdVFpeE5RVUZITEU5QlFVOHNTVUZCVUN4TFFVRnBRaXhYUVVGcVFpeEZRVUUyUWp0QlFVTTVRaXhYUVVGUExFbEJRVkFzUTBGRU9FSTdSMEZCYUVNc1RVRkZUU3hKUVVGSExFOUJRVThzVFVGQlVDeExRVUZ0UWl4WFFVRnVRaXhGUVVFclFqdEJRVU4wUXl4WFFVRlBMRTFCUVZBc1EwRkVjME03UjBGQmJFTXNUVUZGUVN4SlFVRkhMRTlCUVU4c1RVRkJVQ3hMUVVGdFFpeFhRVUZ1UWl4RlFVRXJRanRCUVVOMFF5eFhRVUZQTEUxQlFWQXNRMEZFYzBNN1IwRkJiRU03TzBGQlNVNHNVVUZCVFN4SlFVRkpMRXRCUVVvc1EwRkJWU3gxUWtGQlZpeERRVUZPTEVOQlZHMUNPME5CUVhKQ096dEJRVmxCTEZOQlFWTXNVMEZCVkN4RFFVRnRRaXhSUVVGdVFpeEZRVUUwUWp0QlFVTXhRaXhUUVVGUExFMUJRVTA3UVVGRFdDeG5Ra0ZCV1N4VFFVRlRMRVZCUVZRc1JVRkJXVHRCUVVOMFFpeFZRVUZKTEdGQlFXRXNUMEZCVHl4TlFVRlFMRU5CUVdNc1VVRkJaQ3hGUVVGM1FpeE5RVUY0UWl4RFFVRmlMRU5CUkd0Q08wRkJSWFJDTEdGQlFVOHNUVUZCVUN4RFFVRmpMRWxCUVdRc1JVRkJiMElzVlVGQmNFSXNSVUZHYzBJN1MwRkJlRUk3TzBGQlMwRXNWMEZCVHl4TlFVRlFMRU5CUVdNc1ZVRkJWU3hGUVVGV0xFVkJRV0U3UVVGRGVrSXNWVUZCU1N4SlFVRkpMRWxCUVVrc1NVRkJTaXhEUVVGVExFOUJRVlFzUTBGQlNpeERRVVJ4UWp0QlFVVjZRaXhoUVVGUExFOUJRVThzVFVGQlVDeERRVUZqTEVOQlFXUXNRMEZCVUN4RFFVWjVRanRMUVVFelFqdEhRVTVMTEVOQlJHMUNPME5CUVRWQ096dEJRV1ZCTEZOQlFWTXNXVUZCVkN4RFFVRnpRaXhSUVVGMFFpeEZRVUVyUWp0QlFVTTNRaXhUUVVGUExHTkJRV01zUzBGQlpDeERRVUZ2UWp0QlFVTjZRaXhuUWtGQldTeFRRVUZUTEVWQlFWUXNSVUZCV1R0QlFVTjBRaXhWUVVGSkxGVkJRVlVzVDBGQlR5eFBRVUZRTEVsQlFXdENMRVZCUVd4Q0xFTkJSRkU3UVVGRmRFSXNXVUZCVFN4UFFVRk9MRVZCUm5OQ096dEJRVWwwUWl4VlFVRkpMR0ZCUVdFc1QwRkJUeXhOUVVGUUxFTkJRV01zVVVGQlpDeEZRVUYzUWl4TlFVRjRRaXhEUVVGaUxFTkJTbXRDTzBGQlMzUkNMR0ZCUVU4c1RVRkJVQ3hEUVVGakxFbEJRV1FzUlVGQmIwSXNWVUZCY0VJc1JVRk1jMEk3TzBGQlQzUkNMRmRCUVVzc1NVRkJUQ3hIUVVGWkxFdEJRVXNzVjBGQlRDeERRVUZwUWl4SlFVRnFRaXhEUVZCVk8wRkJVWFJDTEZkQlFVc3NUMEZCVEN4SFFVRmxMRTlCUVdZc1EwRlNjMEk3UVVGVGRFSXNWMEZCU3l4aFFVRmhMRWxCUVdJc1EwRkJhMElzWlVGQmJFSXNRMEZCVEN4SlFVRXlReXhKUVVFelF5eERRVlJ6UWp0QlFWVjBRaXhaUVVGTkxHbENRVUZPTEVOQlFYZENMRWxCUVhoQ0xFVkJRVGhDTEV0QlFVc3NWMEZCVEN4RFFVRnBRaXhKUVVGcVFpeERRVUU1UWl4RFFWWnpRanRMUVVGNFFqczdRVUZoUVN4WFFVRlBMRTFCUVZBc1EwRkJZeXhWUVVGVkxFVkJRVllzUlVGQllUdEJRVU42UWl4VlFVRkpMRWxCUVVrc1NVRkJTU3hKUVVGS0xFTkJRVk1zVDBGQlZDeERRVUZLTEVOQlJIRkNPMEZCUlhwQ0xHRkJRVThzVDBGQlR5eE5RVUZRTEVOQlFXTXNRMEZCWkN4RFFVRlFMRU5CUm5sQ08wdEJRVE5DTzBkQlpFc3NRMEZFYzBJN1EwRkJMMEk3TzBGQmMwSkJMRk5CUVZNc1YwRkJWQ3hEUVVGeFFpeEpRVUZ5UWl4RlFVRXdRanRCUVVONFFpeFRRVUZQTEVsQlFVa3NVVUZCU2l4RFFVRmhMRWxCUVdJc1EwRkJVQ3hEUVVSM1FqdERRVUV4UWpzN1FVRkpRU3hUUVVGVExFOUJRVlFzUTBGQmFVSXNVVUZCYWtJc1JVRkJNa0lzU1VGQk0wSXNSVUZCYVVNc1NVRkJha01zUlVGQmMwTTdRVUZEY0VNc1YwRkJVeXhqUVVGVUxFTkJRWGRDTEVsQlFYaENMRVZCUVRoQ0xFbEJRVGxDTEVWQlJHOURPME5CUVhSRE96dEJRVWxCTEZOQlFWTXNaVUZCVkN4RFFVRjVRaXhIUVVGNlFpeEZRVUUyUWp0QlFVTjZRaXhUUVVGUExFOUJRVThzU1VGQlVDeERRVUZaTEVkQlFWb3NSVUZCYVVJc1RVRkJha0lzUTBGQmQwSXNUMEZCVHl4eFFrRkJVQ3hEUVVFMlFpeEhRVUUzUWl4RFFVRjRRaXhEUVVGUUxFTkJSSGxDTzBOQlFUZENPenRCUVVsQkxGTkJRVk1zYTBKQlFWUXNRMEZCTkVJc1UwRkJOVUlzUlVGQmMwTTdRVUZEY0VNc1RVRkJSenRCUVVORUxGZEJRVThzVDBGQlR5eGhRVUZRTEVOQlFYRkNMRk5CUVhKQ0xFdEJRVzFETEVsQlFXNURMRU5CUkU0N1IwRkJTQ3hEUVVWRExFOUJRVTBzUTBGQlRpeEZRVUZSTzBGQlExQXNWMEZCVHl4TFFVRlFMRU5CUkU4N1IwRkJVanREUVVoSU96czdRVUZUUVN4VFFVRlRMR2RDUVVGVUxFTkJRVEJDTEVkQlFURkNMRVZCUVN0Q08wRkJRek5DTEZOQlFVOHNTMEZCU3l4dFFrRkJiVUlzUjBGQmJrSXNSVUZCZDBJc1QwRkJlRUlzUTBGQlowTXNhVUpCUVdoRExFVkJRVzFFTEZWQlFWTXNTMEZCVkN4RlFVRm5RaXhGUVVGb1FpeEZRVUZ2UWp0QlFVTXZSU3hYUVVGUExFOUJRVThzV1VGQlVDeERRVUZ2UWl4UFFVRlBMRVZCUVZBc1EwRkJNMElzUTBGRUswVTdSMEZCY0VJc1EwRkJlRVFzUTBGQlVDeERRVVF5UWp0RFFVRXZRanM3UVVGTlFTeFRRVUZUTEhkQ1FVRlVMRU5CUVd0RExFZEJRV3hETEVWQlFYVkRMRkZCUVhaRExFVkJRV2RFTzBGQlF6VkRMRTFCUVVrc1ZVRkJWU3hQUVVGUExFMUJRVkFzUTBGQll5eFBRVUZQTEUxQlFWQXNRMEZCWXl4SlFVRkpMRmRCUVVvc1EwRkJaMElzVTBGQmFFSXNRMEZCTlVJc1JVRkJkMFFzUjBGQmVFUXNRMEZCVml4RFFVUjNRenRCUVVVMVF5eFRRVUZQTEZGQlFWRXNVVUZCVWl4RFFVRlFMRU5CUmpSRE96dEJRVWs1UXl4VFFVRlBMRTlCUVU4c1RVRkJVQ3hEUVVGakxFOUJRV1FzUTBGQlVDeERRVW80UXp0RFFVRm9SRHM3UVVGUFFTeFRRVUZUTEZsQlFWUXNRMEZCYzBJc1IwRkJkRUlzUlVGQk1FSTdRVUZEZEVJc1RVRkJTU3hWUVVGVkxFOUJRVThzVFVGQlVDeERRVUZqTEVWQlFXUXNSVUZCYTBJc1IwRkJiRUlzUTBGQlZpeERRVVJyUWp0QlFVVjRRaXhUUVVGUExFOUJRVThzVFVGQlVDeERRVUZqTEU5QlFXUXNRMEZCVUN4RFFVWjNRanREUVVFeFFqczdRVUZMUVN4VFFVRlRMRzFDUVVGVUxFTkJRVFpDTEVkQlFUZENMRVZCUVd0RExGRkJRV3hETEVWQlFUUkRMRXRCUVRWRExFVkJRV3RFTzBGQlEyaEVMRTFCUVVrc1ZVRkJWU3hQUVVGUExFMUJRVkFzUTBGQll5eEZRVUZrTEVWQlFXdENMRWRCUVd4Q0xFTkJRVllzUTBGRU5FTTdRVUZGYUVRc1ZVRkJVU3hSUVVGU0xFbEJRVzlDTEV0QlFYQkNMRU5CUm1kRU8wRkJSMmhFTEZOQlFVOHNUMEZCVHl4TlFVRlFMRU5CUVdNc1QwRkJaQ3hEUVVGUUxFTkJTR2RFTzBOQlFXeEVPenRCUVU5QkxGTkJRVk1zVlVGQlZDeERRVUZ2UWl4SFFVRndRaXhGUVVGNVFpeFJRVUY2UWl4RlFVRnRReXhMUVVGdVF5eEZRVUY1UXp0QlFVTnlReXhOUVVGSExGbEJRVmtzWjBKQlFXZENMRWRCUVdoQ0xFTkJRVm9zUlVGQmFVTTdRVUZEYUVNc1YwRkJUeXh2UWtGQmIwSXNSMEZCY0VJc1JVRkJlVUlzVVVGQmVrSXNSVUZCYlVNc1MwRkJia01zUTBGQlVDeERRVVJuUXp0SFFVRndRenM3UVVGSlFTeFJRVUZOTEhWQ1FVRk9MRU5CVEhGRE8wTkJRWHBET3p0QlFWRkJMRk5CUVZNc1NVRkJWQ3hEUVVGakxFbEJRV1FzUlVGQmJVSTdRVUZEYWtJc1UwRkJUeXhEUVVGRExFbEJRVVFzUTBGRVZUdERRVUZ1UWpzN1FVRkpRU3hUUVVGVExFbEJRVlFzUTBGQll5eEpRVUZrTEVWQlFXOUNMRXRCUVhCQ0xFVkJRVEJDTzBGQlEzaENMRk5CUVU4c1QwRkJUeXhMUVVGUUxFTkJSR2xDTzBOQlFURkNPenRCUVVsQkxGTkJRVk1zUjBGQlZDeERRVUZoTEVsQlFXSXNSVUZCYlVJc1MwRkJia0lzUlVGQmVVSTdRVUZEZGtJc1UwRkJUeXhQUVVGUExFdEJRVkFzUTBGRVowSTdRMEZCZWtJN08wRkJTVUVzVTBGQlV5eEhRVUZVTEVOQlFXRXNTVUZCWWl4RlFVRnRRaXhMUVVGdVFpeEZRVUY1UWp0QlFVTjJRaXhUUVVGUExGRkJRVkVzUzBGQlVpeERRVVJuUWp0RFFVRjZRanM3UVVGSlFTeFRRVUZUTEVkQlFWUXNRMEZCWVN4SlFVRmlMRVZCUVcxQ0xFdEJRVzVDTEVWQlFYbENPMEZCUTNaQ0xGTkJRVThzVVVGQlVTeExRVUZTTEVOQlJHZENPME5CUVhwQ096dEJRVWxCTEZOQlFWTXNTVUZCVkN4RFFVRmpMRWxCUVdRc1JVRkJiMElzUzBGQmNFSXNSVUZCTUVJN1FVRkRlRUlzVTBGQlR5eFBRVUZQTEV0QlFWQXNRMEZFYVVJN1EwRkJNVUk3TzBGQlNVRXNVMEZCVXl4SFFVRlVMRU5CUVdFc1lVRkJZaXhGUVVFeVFqdEJRVU42UWl4TlFVRkhMR05CUVdNc1RVRkJaQ3hMUVVGNVFpeERRVUY2UWl4RlFVRXlRanRCUVVNMVFpeFhRVUZQTEU5QlFVOHNUVUZCVUN4RFFVRmpMRVZCUVdRc1EwRkJVQ3hEUVVRMFFqdEhRVUU1UWpzN1FVRkpRU3hOUVVGSkxGbEJRVmtzUlVGQldpeERRVXh4UWp0QlFVMTZRaXhOUVVGSkxHdENRVUZyUWl4alFVRmpMRU5CUVdRc1EwRkJiRUlzUTBGT2NVSTdPMEZCVVhwQ0xFOUJRVWtzU1VGQlNTeERRVUZLTEVsQlFWTXNZVUZCWWl4RlFVRXlRanRCUVVONlFpeFJRVUZITEVWQlFVVXNUVUZCUml4SFFVRlhMR1ZCUVZnc1JVRkJNa0k3UVVGRE5VSXNkMEpCUVd0Q0xFVkJRVVVzVFVGQlJpeERRVVJWTzB0QlFUbENPMGRCUkVZN08wRkJUVUVzVDBGQlNTeEpRVUZKTEVsQlFVa3NRMEZCU2l4RlFVRlBMRWxCUVVrc1pVRkJTaXhGUVVGeFFpeEhRVUZ3UXl4RlFVRjNRenRCUVVOMFF5eFJRVUZKTEdkQ1FVRm5RaXhGUVVGb1FpeERRVVJyUXp0QlFVVjBReXhUUVVGSkxFbEJRVWtzU1VGQlNTeERRVUZLTEVWQlFVOHNTVUZCU1N4alFVRmpMRTFCUVdRc1JVRkJjMElzUjBGQmVrTXNSVUZCTmtNN1FVRkRNME1zYjBKQlFXTXNTVUZCWkN4RFFVRnRRaXhqUVVGakxFTkJRV1FzUlVGQmFVSXNRMEZCYWtJc1EwRkJia0lzUlVGRU1rTTdTMEZCTjBNN08wRkJTVUVzWTBGQlZTeEpRVUZXTEVOQlFXVXNTVUZCU1N4TFFVRktMRU5CUVZVc1IwRkJSeXhoUVVGSUxFTkJRWHBDTEVWQlRuTkRPMGRCUVhoRE96dEJRVk5CTEZOQlFVOHNUMEZCVHl4TlFVRlFMRU5CUVdNc1UwRkJaQ3hEUVVGUUxFTkJka0o1UWp0RFFVRXpRanM3UVVFd1FrRXNVMEZCVXl4WlFVRlVMRU5CUVhOQ0xFbEJRWFJDTEVWQlFUUkNPMEZCUXpGQ0xFMUJRVWM3UVVGRFJDeFRRVUZMTEVsQlFVd3NSVUZFUXp0QlFVVkVMRmRCUVU4c1NVRkJVQ3hEUVVaRE8wZEJRVWdzUTBGSFF5eFBRVUZOTEVOQlFVNHNSVUZCVVR0QlFVTlFMRmRCUVU4c1MwRkJVQ3hEUVVSUE8wZEJRVkk3UTBGS1NEczdRVUZUUVN4VFFVRlRMR2RDUVVGVUxFTkJRVEJDTEVsQlFURkNMRVZCUVdkRExFOUJRV2hETEVWQlFYZERPMEZCUTNCRExFMUJRVWtzVVVGQlVTeExRVUZTTEVOQlJHZERPenRCUVVkd1F5eFRRVUZQTEV0QlFVc3NUVUZCVEN4RFFVRlpMRkZCUVZVN1FVRkRla0lzVVVGQlJ5eERRVUZETEV0QlFVUXNTVUZCVlN4VFFVRlRMRTlCUVZRc1JVRkJhVUk3UVVGRE1VSXNZMEZCVVN4SlFVRlNMRU5CUkRCQ08wRkJSVEZDTEdGQlFVOHNTMEZCVUN4RFFVWXdRanRMUVVFNVFqczdRVUZMUVN4WFFVRlBMRWxCUVZBc1EwRk9lVUk3UjBGQlZpeERRVUZ1UWl4RFFVaHZRenREUVVGNFF6czdRVUZoUVN4VFFVRlRMRXRCUVZRc1EwRkJaU3hIUVVGbUxFVkJRVzlDTEVkQlFYQkNMRVZCUVhsQ0xFbEJRWHBDTEVWQlFUaENPMEZCUXpGQ0xFMUJRVWtzVDBGQlR5eEhRVUZRTEVOQlJITkNPenRCUVVjeFFpeFBRVUZKTEUxQlFVMHNSVUZCVGl4SlFVRlpMRWxCUVdoQ0xFVkJRWEZDTzBGQlEycENMRmRCUVU4c1NVRkJTU3hGUVVGS0xFVkJRVkVzU1VGQlVpeERRVUZRTEVOQlJHbENPMGRCUVhKQ096dEJRVWxCTEZOQlFVOHNTVUZCVUN4RFFWQXdRanREUVVFNVFqczdRVUZYUVN4VFFVRlRMRXRCUVZRc1EwRkJaU3hIUVVGbUxFVkJRVzlDTEVkQlFYQkNMRVZCUVhsQ0xFbEJRWHBDTEVWQlFUaENPMEZCUXpGQ0xFMUJRVWtzVDBGQlR5eEhRVUZRTEVOQlJITkNPenRCUVVjeFFpeFBRVUZKTEVsQlFVa3NTVUZCU1N4TFFVRkxMRTFCUVV3c1IwRkJZeXhEUVVGa0xFVkJRV2xDTEV0QlFVc3NRMEZCVEN4RlFVRlJMRWRCUVhKRExFVkJRWGxETzBGQlEzSkRMRmRCUVU4c1NVRkJTU3hMUVVGTExFTkJRVXdzUTBGQlNpeEZRVUZoTEVsQlFXSXNRMEZCVUN4RFFVUnhRenRIUVVGNlF6czdRVUZKUVN4VFFVRlBMRWxCUVZBc1EwRlFNRUk3UTBGQk9VSTdPMEZCVlVFc1UwRkJVeXhQUVVGVUxFTkJRV2xDTEVkQlFXcENMRVZCUVhOQ0xFTkJRWFJDTEVWQlFYbENMRk5CUVhwQ0xFVkJRVzFET3p0QlFVVnFReXhQUVVGSkxFbEJRVWtzU1VGQlNTeFZRVUZWTEUxQlFWWXNSMEZCYlVJc1EwRkJia0lzUlVGQmMwSXNTMEZCU3l4RFFVRk1MRVZCUVZFc1IwRkJNVU1zUlVGQk9FTTdRVUZETlVNc1VVRkJSeXhWUVVGVkxFTkJRVllzUlVGQllTeEhRVUZpTEVOQlFXbENMRU5CUVdwQ0xFMUJRWGRDTEVkQlFYaENMRVZCUVRSQ08wRkJRemRDTEdGQlFVOHNWVUZCVlN4RFFVRldMRU5CUVZBc1EwRkVOa0k3UzBGQkwwSTdSMEZFUmpzN1FVRk5RU3hUUVVGUExFdEJRVkFzUTBGU2FVTTdRMEZCYmtNN08wRkJWMEVzVTBGQlV5eFRRVUZVTEVOQlFXMUNMRWRCUVc1Q0xFVkJRWGRDTEVOQlFYaENMRVZCUVRKQ0xGTkJRVE5DTEVWQlFYRkRPenRCUVVWcVF5eFBRVUZKTEVsQlFVa3NTVUZCU1N4VlFVRlZMRTFCUVZZc1IwRkJiVUlzUTBGQmJrSXNSVUZCYzBJc1MwRkJTeXhEUVVGTUxFVkJRVkVzUjBGQk1VTXNSVUZCT0VNN1FVRkRNVU1zVVVGQlJ5eFZRVUZWTEVOQlFWWXNSVUZCWVN4SFFVRmlMRU5CUVdsQ0xFTkJRV3BDTEUxQlFYZENMRWRCUVhoQ0xFVkJRVFJDTzBGQlF6TkNMR0ZCUVU4c1ZVRkJWU3hOUVVGV0xFTkJRV2xDTEVWQlFXcENMRVZCUVhGQ0xFMUJRWEpDTEVOQlFUUkNMRU5CUVRWQ0xFVkJRU3RDTEVOQlFTOUNMRU5CUVZBc1EwRkVNa0k3UzBGQkwwSTdSMEZFU2pzN1FVRk5RU3hUUVVGUExGTkJRVkFzUTBGU2FVTTdRMEZCY2tNN08wRkJWMEVzVTBGQlV5eFJRVUZVTEVOQlFXdENMRWRCUVd4Q0xFVkJRWFZDTEVOQlFYWkNMRVZCUVRCQ0xFbEJRVEZDTEVWQlFXZERMRkZCUVdoRExFVkJRWGxETzBGQlEzSkRMRTlCUVVrc1NVRkJTU3hKUVVGSkxFdEJRVXNzVFVGQlRDeEhRVUZqTEVOQlFXUXNSVUZCYVVJc1MwRkJTeXhEUVVGTUxFVkJRVkVzUjBGQmNrTXNSVUZCZVVNN1FVRkRja01zVVVGQlJ5eExRVUZMTEVOQlFVd3NSVUZCVVN4SFFVRlNMRU5CUVZrc1EwRkJXaXhOUVVGdFFpeEhRVUZ1UWl4RlFVRjFRanRCUVVOMFFpeGhRVUZQTEV0QlFVc3NUVUZCVEN4RFFVRlpMRVZCUVZvc1JVRkJaMElzVFVGQmFFSXNRMEZCZFVJc1EwRkJka0lzUlVGQk1FSXNRMEZCTVVJc1JVRkJOa0lzVVVGQk4wSXNRMEZCVUN4RFFVUnpRanRMUVVFeFFqdEhRVVJLT3p0QlFVMUdMRk5CUVU4c1MwRkJTeXhOUVVGTUxFTkJRVmtzUlVGQldpeEZRVUZuUWl4SlFVRm9RaXhEUVVGeFFpeFJRVUZ5UWl4RFFVRlFMRU5CVUhWRE8wTkJRWHBET3p0QlFWVkJMRk5CUVZNc1UwRkJWQ3hEUVVGdFFpeEhRVUZ1UWl4RlFVRjNRaXhEUVVGNFFpeEZRVUV5UWl4SlFVRXpRaXhGUVVGblF6dEJRVU01UWl4UFFVRkpMRWxCUVVrc1NVRkJTU3hMUVVGTExFMUJRVXdzUjBGQll5eERRVUZrTEVWQlFXbENMRXRCUVVzc1EwRkJUQ3hGUVVGUkxFZEJRWEpETEVWQlFYbERPMEZCUTNaRExGRkJRVWNzUzBGQlN5eERRVUZNTEVWQlFWRXNSMEZCVWl4RFFVRlpMRU5CUVZvc1RVRkJiVUlzUjBGQmJrSXNSVUZCZFVJN1FVRkRlRUlzWVVGQlR5eEpRVUZRTEVOQlJIZENPMHRCUVRGQ08wZEJSRVk3TzBGQlRVRXNVMEZCVHl4TFFVRlFMRU5CVURoQ08wTkJRV2hET3p0QlFWVkJMRk5CUVZNc1QwRkJWQ3hEUVVGcFFpeEhRVUZxUWl4RlFVRnpRaXhEUVVGMFFpeEZRVUY1UWl4SlFVRjZRaXhGUVVFNFFqdEJRVU0xUWl4TlFVRkhMRU5CUVVNc1ZVRkJWU3hIUVVGV0xFVkJRV1VzUTBGQlppeEZRVUZyUWl4SlFVRnNRaXhEUVVGRUxFVkJRWGxDTzBGQlF6RkNMRmRCUVU4c1MwRkJVQ3hEUVVRd1FqdEhRVUUxUWpzN1FVRkpRU3hOUVVGSkxGRkJRVkVzVVVGQlVTeEhRVUZTTEVWQlFXRXNRMEZCWWl4RlFVRm5RaXhKUVVGb1FpeERRVUZTTEVOQlRIZENPenRCUVU4MVFpeFRRVUZQTEVsQlFVa3NTMEZCU2l4RFFVRlZMRTFCUVUwc1IwRkJUaXhEUVVGVkxFTkJRVllzUTBGQlZpeEZRVUYzUWl4TFFVRjRRaXhGUVVFclFpeFZRVUZWTEVkQlFWWXNSVUZCWlN4RFFVRm1MRVZCUVd0Q0xFbEJRV3hDTEVOQlFTOUNMRU5CUVZBc1EwRlFORUk3UTBGQk9VSTdPMEZCVlVFc1UwRkJVeXhWUVVGVUxFTkJRVzlDTEVkQlFYQkNMRVZCUVhsQ0xFTkJRWHBDTEVWQlFUUkNMRWxCUVRWQ0xFVkJRV3RETEZGQlFXeERMRVZCUVRKRE96dEJRVVY2UXl4UFFVRkpMRWxCUVVrc1NVRkJTU3hWUVVGVkxFMUJRVllzUjBGQmJVSXNRMEZCYmtJc1JVRkJjMElzUzBGQlN5eERRVUZNTEVWQlFWRXNSMEZCTVVNc1JVRkJPRU03UVVGRE5VTXNVVUZCUnl4VlFVRlZMRU5CUVZZc1JVRkJZU3hIUVVGaUxFTkJRV2xDTEVOQlFXcENMRTFCUVhkQ0xFZEJRWGhDTEVWQlFUUkNPMEZCUXpkQ0xHRkJRVThzVlVGQlZTeE5RVUZXTEVOQlFXbENMRVZCUVdwQ0xFVkJRWEZDTEUxQlFYSkNMRU5CUVRSQ0xFTkJRVFZDTEVWQlFTdENMRU5CUVM5Q0xFVkJRV3RETEZGQlFXeERMRU5CUVZBc1EwRkVOa0k3UzBGQkwwSTdSMEZFUmpzN1FVRk5RU3hUUVVGUExGTkJRVkFzUTBGU2VVTTdRMEZCTTBNN08wRkJXVUVzVTBGQlV5eFBRVUZVTEVOQlFXbENMRWxCUVdwQ0xFVkJRWE5DTzBGQlEyeENMRk5CUVU4c1MwRkJTeXhOUVVGTUxFTkJRVmtzUlVGQldpeEZRVUZuUWl4UFFVRm9RaXhGUVVGUUxFTkJSR3RDTzBOQlFYUkNPenRCUVVsQkxGTkJRVk1zVTBGQlZDeERRVUZ0UWl4SFFVRnVRaXhGUVVGM1FpeEhRVUY0UWl4RlFVRTBRanRCUVVONFFpeE5RVUZITEU5QlFVOHNaMEpCUVdkQ0xFZEJRV2hDTEVOQlFWQXNSVUZCTkVJN1FVRkRNMElzVjBGQlR5eEpRVUZKTEV0QlFVb3NRMEZCVlN4UFFVRlBMRWRCUVZBc1EwRkJWeXhKUVVGWUxFTkJRVllzUlVGQk5FSXNTVUZCU1N4SFFVRktMRU5CUVRWQ0xFTkJRVkFzUTBGRU1rSTdSMEZCTDBJc1RVRkZTenRCUVVORUxGZEJRVThzVDBGQlR5eEhRVUZRTEVOQlFWY3NUMEZCV0N4RFFVRlFMRU5CUkVNN1IwRkdURHREUVVSS096dEJRVkZCTEZOQlFWTXNUMEZCVkN4RFFVRnBRaXhKUVVGcVFpeEZRVUYxUWl4UFFVRlBMRVZCUVZBc1JVRkJWenRCUVVOb1F5eE5RVUZKTEZkQlFWY3NSVUZCV0N4RFFVUTBRanM3UVVGSGFFTXNUMEZCU1N4SlFVRkpMRU5CUVVvc1NVRkJVeXhKUVVGaUxFVkJRV3RDTzBGQlEyaENMRkZCUVVjc1VVRkJVU3hEUVVGU0xFTkJRVWdzUlVGQll6dEJRVU5hTEdsQ1FVRlhMRk5CUVZNc1RVRkJWQ3hEUVVGblFpeFJRVUZSTEVOQlFWSXNRMEZCYUVJc1EwRkJXQ3hEUVVSWk8wdEJRV1FzVFVGRlN6dEJRVU5JTEdWQlFWTXNTVUZCVkN4RFFVRmpMRU5CUVdRc1JVRkVSenRMUVVaTU8wZEJSRVk3TzBGQlVVRXNVMEZCVHl4UFFVRlBMRTFCUVZBc1EwRkJZeXhUUVVGVExFMUJRVlFzUTBGQlowSXNTVUZCYUVJc1EwRkJaQ3hEUVVGUUxFTkJXR2RETzBOQlFXeERPenRCUVdOQkxGTkJRVk1zVTBGQlZDeERRVUZ0UWl4RFFVRnVRaXhGUVVGelFpeEpRVUYwUWl4RlFVRXlRanRCUVVONlFpeE5RVUZKTEU5QlFVOHNSVUZCVUN4RFFVUnhRanM3UVVGSGVrSXNUMEZCU1N4SlFVRkpMRWxCUVVrc1EwRkJTaXhGUVVGUExFbEJRVWtzUTBGQlNpeEZRVUZQTEVkQlFYUkNMRVZCUVRCQ08wRkJRM2hDTEZOQlFVc3NTVUZCVEN4RFFVRlZMRWxCUVZZc1JVRkVkMEk3UjBGQk1VSTdPMEZCU1VFc1UwRkJUeXhQUVVGUExFMUJRVkFzUTBGQll5eEpRVUZrTEVOQlFWQXNRMEZRZVVJN1EwRkJNMEk3TzBGQlZVRXNVMEZCVXl4UlFVRlVMRU5CUVd0Q0xFZEJRV3hDTEVWQlFYVkNMRWRCUVhaQ0xFVkJRVFJDTEVsQlFUVkNMRVZCUVdsRE8wRkJReTlDTEUxQlFVa3NWVUZCVlN4RlFVRldMRU5CUkRKQ096dEJRVWN2UWl4UFFVRkpMRWxCUVVrc1EwRkJTaXhKUVVGVExFbEJRV0lzUlVGQmEwSTdRVUZEYUVJc1VVRkJTU3hOUVVGTkxFbEJRVWtzUTBGQlNpeEZRVUZQTEVkQlFWQXNRMEZCVGl4RFFVUlpPMEZCUldoQ0xGbEJRVkVzU1VGQlVpeERRVUZoTEVsQlFVa3NSMEZCU2l4RFFVRlJMRU5CUVZJc1EwRkJZaXhGUVVablFqdEJRVWRvUWl4VlFVRk5MRWxCUVVrc1IwRkJTaXhEUVVGUkxFTkJRVklzUTBGQlRpeERRVWhuUWp0SFFVRnNRanM3UVVGUFFTeFRRVUZQTEVsQlFVa3NTMEZCU2l4RFFVRlZMRTlCUVU4c1RVRkJVQ3hEUVVGakxFOUJRV1FzUTBGQlZpeEZRVUZyUXl4SFFVRnNReXhEUVVGUUxFTkJWaXRDTzBOQlFXcERPenRCUVdGQkxGTkJRVk1zVTBGQlZDeERRVUZ0UWl4SFFVRnVRaXhGUVVGM1FpeEpRVUY0UWl4RlFVRTJRanRCUVVNelFpeE5RVUZKTEZWQlFWVXNSVUZCVml4RFFVUjFRanM3UVVGSE0wSXNUMEZCU1N4RFFVRktMRWxCUVZNc1NVRkJWQ3hGUVVGak8wRkJRMW9zVVVGQlNTeFRRVUZUTEVsQlFVa3NRMEZCU2l4RFFVRlVMRU5CUkZFN08wRkJSMW9zVVVGQlJ5eFhRVUZYTEVsQlFWZ3NSVUZCWjBJN1FVRkRha0lzWTBGQlVTeEpRVUZTTEVOQlFXRXNRMEZCWWl4RlFVUnBRanRMUVVGdVFpeE5RVVZOTEVsQlFVY3NhMEpCUVd0Q0xFdEJRV3hDTEVWQlFYZENPMEZCUXk5Q0xHTkJRVkVzU1VGQlVpeERRVUZoTEU5QlFVOHNSMEZCVUN4RFFVRlhMRU5CUVZnc1EwRkJZaXhGUVVRclFqdExRVUV6UWp0SFFVeFNPenRCUVZWQkxGTkJRVThzVDBGQlR5eE5RVUZRTEVOQlFXTXNUMEZCWkN4RFFVRlFMRU5CWWpKQ08wTkJRVGRDT3p0QlFXZENRU3hUUVVGVExGTkJRVlFzUTBGQmJVSXNSMEZCYmtJc1JVRkJkMElzUjBGQmVFSXNSVUZCTmtJc1IwRkJOMElzUlVGQmFVTTdRVUZETDBJc1RVRkJTU3hQUVVGUExFZEJRVkFzUTBGRU1rSTdPMEZCUnk5Q0xFOUJRVWtzU1VGQlNTeERRVUZLTEVsQlFWTXNaMEpCUVdkQ0xFZEJRV2hDTEVOQlFXSXNSVUZCYTBNN1FVRkRhRU1zVjBGQlR5eEpRVUZKTEVOQlFVb3NSVUZCVHl4SlFVRkpMRU5CUVVvc1EwRkJVQ3hGUVVGbExFbEJRV1lzUTBGQlVDeERRVVJuUXp0SFFVRnNRenM3UVVGSlFTeFRRVUZQTEVsQlFWQXNRMEZRSzBJN1EwRkJha003TzBGQlZVRXNVMEZCVXl4alFVRlVMRU5CUVhkQ0xFbEJRWGhDTEVWQlFUWkNPMEZCUXpOQ0xFMUJRVWtzU1VGQlNTeEZRVUZLTEVOQlJIVkNPenRCUVVjelFpeFBRVUZKTEVOQlFVb3NTVUZCVXl4SlFVRlVMRVZCUVdNN1FVRkRXaXhOUVVGRkxFVkJRVVVzUjBGQlJpeERRVUZOTEVOQlFVNHNRMEZCUml4SlFVRmpMRVZCUVVVc1IwRkJSaXhEUVVGTkxFTkJRVTRzUTBGQlpDeERRVVJaTzBkQlFXUTdPMEZCU1VFc1UwRkJUeXhQUVVGUExFMUJRVkFzUTBGQll5eERRVUZrTEVOQlFWQXNRMEZRTWtJN1EwRkJOMEk3TzBGQlZVRXNaVUZCWlR0QlFVTmlMR1ZCUkdFN1FVRkZZaXhQUVVaaE8wRkJSMklzVlVGSVlUdEJRVWxpTEZsQlNtRTdRVUZMWWl4WFFVeGhPMEZCVFdJc1kwRk9ZVHRCUVU5aUxHRkJVR0U3UVVGUllpeFRRVkpoTzBGQlUySXNhVUpCVkdFN1FVRlZZaXh2UWtGV1lUdEJRVmRpTEd0Q1FWaGhPMEZCV1dJc01FSkJXbUU3UVVGaFlpeHhRa0ZpWVR0QlFXTmlMR05CWkdFN1FVRmxZaXhqUVdaaE8wRkJaMEppTEUxQmFFSmhPMEZCYVVKaUxFMUJha0poTzBGQmEwSmlMRXRCYkVKaE8wRkJiVUppTEV0QmJrSmhPMEZCYjBKaUxFdEJjRUpoTzBGQmNVSmlMRTFCY2tKaE8wRkJjMEppTEV0QmRFSmhPMEZCZFVKaUxFOUJka0poTzBGQmQwSmlMRTlCZUVKaE8wRkJlVUppTEd0Q1FYcENZVHRCUVRCQ1lpeFhRVEZDWVR0QlFUSkNZaXhWUVROQ1lUdEJRVFJDWWl4VFFUVkNZVHRCUVRaQ1lpeFRRVGRDWVR0QlFUaENZaXhaUVRsQ1lUdEJRU3RDWWl4VFFTOUNZVHRCUVdkRFlpeFpRV2hEWVR0QlFXbERZaXhYUVdwRFlUdEJRV3REWWl4VFFXeERZVHRCUVcxRFlpeFhRVzVEWVR0QlFXOURZaXhWUVhCRFlUdEJRWEZEWWl4WFFYSkRZVHRCUVhORFlpeFhRWFJEWVR0RFFVRm1JaXdpWm1sc1pTSTZJbXhwWWk5amIzSmxMMloxYm1OMGFXOXVjeTVxY3lJc0luTnZkWEpqWlhORGIyNTBaVzUwSWpwYkltbHRjRzl5ZENCN0lGUjFjR3hsSUgwZ1puSnZiU0FuTGk5d2NtbHRhWFJwZG1Wekp6dGNibWx0Y0c5eWRDQkNhWFJUZEhKcGJtY2dabkp2YlNBbkxpOWlhWFJmYzNSeWFXNW5KenRjYm1sdGNHOXlkQ0JRWVhSMFpYSnVjeUJtY205dElDY3VMM0JoZEhSbGNtNXpKenRjYm1sdGNHOXlkQ0JRY205MGIyTnZiQ0JtY205dElDY3VMM0J5YjNSdlkyOXNKenRjYmx4dVpuVnVZM1JwYjI0Z1kyRnNiRjl3Y205d1pYSjBlU2hwZEdWdExDQndjbTl3WlhKMGVTbDdYRzRnSUd4bGRDQndjbTl3SUQwZ2JuVnNiRHRjYmx4dUlDQnBaaWgwZVhCbGIyWWdhWFJsYlNBOVBUMGdYQ0p1ZFcxaVpYSmNJaUI4ZkNCMGVYQmxiMllnYVhSbGJTQTlQVDBnWENKemVXMWliMnhjSWlCOGZDQjBlWEJsYjJZZ2FYUmxiU0E5UFQwZ1hDSmliMjlzWldGdVhDSWdmSHdnZEhsd1pXOW1JR2wwWlcwZ1BUMDlJRndpYzNSeWFXNW5YQ0lwZTF4dUlDQWdJR2xtS0dsMFpXMWJjSEp2Y0dWeWRIbGRJQ0U5UFNCMWJtUmxabWx1WldRcGUxeHVJQ0FnSUNBZ2NISnZjQ0E5SUhCeWIzQmxjblI1TzF4dUlDQWdJSDFsYkhObElHbG1LR2wwWlcxYlUzbHRZbTlzTG1admNpaHdjbTl3WlhKMGVTbGRJQ0U5UFNCMWJtUmxabWx1WldRcGUxeHVJQ0FnSUNBZ2NISnZjQ0E5SUZONWJXSnZiQzVtYjNJb2NISnZjR1Z5ZEhrcE8xeHVJQ0FnSUgxY2JpQWdmU0JsYkhObElIdGNiaUFnSUNCcFppaHdjbTl3WlhKMGVTQnBiaUJwZEdWdEtYdGNiaUFnSUNBZ0lIQnliM0FnUFNCd2NtOXdaWEowZVR0Y2JpQWdJQ0I5Wld4elpTQnBaaWhUZVcxaWIyd3VabTl5S0hCeWIzQmxjblI1S1NCcGJpQnBkR1Z0S1h0Y2JpQWdJQ0FnSUhCeWIzQWdQU0JUZVcxaWIyd3VabTl5S0hCeWIzQmxjblI1S1R0Y2JpQWdJQ0I5WEc0Z0lIMWNibHh1SUNCcFppaHdjbTl3SUQwOVBTQnVkV3hzS1h0Y2JpQWdJQ0IwYUhKdmR5QnVaWGNnUlhKeWIzSW9ZRkJ5YjNCbGNuUjVJQ1I3SUhCeWIzQmxjblI1SUgwZ2JtOTBJR1p2ZFc1a0lHbHVJQ1I3SUdsMFpXMGdmV0FwT3lCY2JpQWdmVnh1WEc0Z0lHbG1LR2wwWlcxYmNISnZjRjBnYVc1emRHRnVZMlZ2WmlCR2RXNWpkR2x2YmlsN1hHNGdJQ0FnY21WMGRYSnVJR2wwWlcxYmNISnZjRjBvS1R0Y2JpQWdmV1ZzYzJWN1hHNGdJQ0FnY21WMGRYSnVJR2wwWlcxYmNISnZjRjA3WEc0Z0lIMWNibjFjYmx4dVpuVnVZM1JwYjI0Z1lYQndiSGtvTGk0dVlYSm5jeWw3WEc0Z0lHbG1LR0Z5WjNNdWJHVnVaM1JvSUQwOVBTQXlLWHRjYmlBZ0lDQmhjbWR6V3pCZExtRndjR3g1S0c1MWJHd3NJR0Z5WjNNdWMyeHBZMlVvTVNrcE8xeHVJQ0I5Wld4elpYdGNiaUFnSUNCaGNtZHpXekJkVzJGeVozTmJNVjFkTG1Gd2NHeDVLRzUxYkd3c0lHRnlaM011YzJ4cFkyVW9NaWtwTzF4dUlDQjlYRzU5WEc1Y2JtWjFibU4wYVc5dUlHTnZiblJoYVc1ektHeGxablFzSUhKcFoyaDBLWHRjYmlBZ1ptOXlLR3hsZENCNElHOW1JSEpwWjJoMEtYdGNiaUFnSUNCcFppaFFZWFIwWlhKdWN5NXRZWFJqYUY5dWIxOTBhSEp2ZHloc1pXWjBMQ0I0S1NBaFBTQnVkV3hzS1h0Y2JpQWdJQ0FnSUhKbGRIVnliaUIwY25WbE8xeHVJQ0FnSUgxY2JpQWdmVnh1WEc0Z0lISmxkSFZ5YmlCbVlXeHpaVHRjYm4xY2JseHVablZ1WTNScGIyNGdaMlYwWDJkc2IySmhiQ2dwZTF4dUlDQnBaaWgwZVhCbGIyWW9jMlZzWmlrZ0lUMDlJRndpZFc1a1pXWnBibVZrWENJcGUxeHVJQ0FnSUhKbGRIVnliaUJ6Wld4bU8xeHVJQ0I5Wld4elpTQnBaaWgwZVhCbGIyWW9kMmx1Wkc5M0tTQWhQVDBnWENKMWJtUmxabWx1WldSY0lpbDdYRzRnSUNBZ2NtVjBkWEp1SUhkcGJtUnZkenRjYmlBZ2ZXVnNjMlVnYVdZb2RIbHdaVzltS0dkc2IySmhiQ2tnSVQwOUlGd2lkVzVrWldacGJtVmtYQ0lwZTF4dUlDQWdJSEpsZEhWeWJpQm5iRzlpWVd3N1hHNGdJSDFjYmx4dUlDQjBhSEp2ZHlCdVpYY2dSWEp5YjNJb1hDSk9ieUJuYkc5aVlXd2djM1JoZEdVZ1ptOTFibVJjSWlrN1hHNTlYRzVjYm1aMWJtTjBhVzl1SUdSbFpuTjBjblZqZENoa1pXWmhkV3gwY3lsN1hHNGdJSEpsZEhWeWJpQmpiR0Z6Y3lCN1hHNGdJQ0FnWTI5dWMzUnlkV04wYjNJb2RYQmtZWFJsSUQwZ2UzMHBlMXh1SUNBZ0lDQWdiR1YwSUhSb1pWOTJZV3gxWlhNZ1BTQlBZbXBsWTNRdVlYTnphV2R1S0dSbFptRjFiSFJ6TENCMWNHUmhkR1VwTzF4dUlDQWdJQ0FnVDJKcVpXTjBMbUZ6YzJsbmJpaDBhR2x6TENCMGFHVmZkbUZzZFdWektUdGNiaUFnSUNCOVhHNWNiaUFnSUNCemRHRjBhV01nWTNKbFlYUmxLSFZ3WkdGMFpYTWdQU0I3ZlNsN1hHNGdJQ0FnSUNCc1pYUWdlQ0E5SUc1bGR5QjBhR2x6S0hWd1pHRjBaWE1wTzF4dUlDQWdJQ0FnY21WMGRYSnVJRTlpYW1WamRDNW1jbVZsZW1Vb2VDazdYRzRnSUNBZ2ZWeHVJQ0I5TzF4dWZWeHVYRzVjYm1aMWJtTjBhVzl1SUdSbFptVjRZMlZ3ZEdsdmJpaGtaV1poZFd4MGN5bDdYRzRnSUhKbGRIVnliaUJqYkdGemN5QmxlSFJsYm1SeklFVnljbTl5SUh0Y2JpQWdJQ0JqYjI1emRISjFZM1J2Y2loMWNHUmhkR1VnUFNCN2ZTbDdYRzRnSUNBZ0lDQnNaWFFnYldWemMyRm5aU0E5SUhWd1pHRjBaUzV0WlhOellXZGxJSHg4SUZ3aVhDSTdYRzRnSUNBZ0lDQnpkWEJsY2lodFpYTnpZV2RsS1R0Y2JseHVJQ0FnSUNBZ2JHVjBJSFJvWlY5MllXeDFaWE1nUFNCUFltcGxZM1F1WVhOemFXZHVLR1JsWm1GMWJIUnpMQ0IxY0dSaGRHVXBPMXh1SUNBZ0lDQWdUMkpxWldOMExtRnpjMmxuYmloMGFHbHpMQ0IwYUdWZmRtRnNkV1Z6S1R0Y2JseHVJQ0FnSUNBZ2RHaHBjeTV1WVcxbElEMGdkR2hwY3k1amIyNXpkSEoxWTNSdmNpNXVZVzFsTzF4dUlDQWdJQ0FnZEdocGN5NXRaWE56WVdkbElEMGdiV1Z6YzJGblpUdGNiaUFnSUNBZ0lIUm9hWE5iVTNCbFkybGhiRVp2Y20xekxtRjBiMjBvWENKZlgyVjRZMlZ3ZEdsdmJsOWZYQ0lwWFNBOUlIUnlkV1U3WEc0Z0lDQWdJQ0JGY25KdmNpNWpZWEIwZFhKbFUzUmhZMnRVY21GalpTaDBhR2x6TENCMGFHbHpMbU52Ym5OMGNuVmpkRzl5TG01aGJXVXBPMXh1SUNBZ0lIMWNibHh1SUNBZ0lITjBZWFJwWXlCamNtVmhkR1VvZFhCa1lYUmxjeUE5SUh0OUtYdGNiaUFnSUNBZ0lHeGxkQ0I0SUQwZ2JtVjNJSFJvYVhNb2RYQmtZWFJsY3lrN1hHNGdJQ0FnSUNCeVpYUjFjbTRnVDJKcVpXTjBMbVp5WldWNlpTaDRLVHRjYmlBZ0lDQjlYRzRnSUgwN1hHNTlYRzVjYm1aMWJtTjBhVzl1SUdSbFpuQnliM1J2WTI5c0tITndaV01wZTF4dUlDQnlaWFIxY200Z2JtVjNJRkJ5YjNSdlkyOXNLSE53WldNcE8xeHVmVnh1WEc1bWRXNWpkR2x2YmlCa1pXWnBiWEJzS0hCeWIzUnZZMjlzTENCMGVYQmxMQ0JwYlhCc0tYdGNiaUFnY0hKdmRHOWpiMnd1YVcxd2JHVnRaVzUwWVhScGIyNG9kSGx3WlN3Z2FXMXdiQ2s3WEc1OVhHNWNibVoxYm1OMGFXOXVJR2RsZEY5dlltcGxZM1JmYTJWNWN5aHZZbW9wZTF4dUlDQWdJSEpsZEhWeWJpQlBZbXBsWTNRdWEyVjVjeWh2WW1vcExtTnZibU5oZENoUFltcGxZM1F1WjJWMFQzZHVVSEp2Y0dWeWRIbFRlVzFpYjJ4ektHOWlhaWtwTzF4dWZWeHVYRzVtZFc1amRHbHZiaUJwYzE5MllXeHBaRjlqYUdGeVlXTjBaWElvWTI5a1pYQnZhVzUwS1h0Y2JpQWdkSEo1ZTF4dUlDQWdJSEpsZEhWeWJpQlRkSEpwYm1jdVpuSnZiVU52WkdWUWIybHVkQ2hqYjJSbGNHOXBiblFwSUNFOUlHNTFiR3c3WEc0Z0lIMWpZWFJqYUNobEtYdGNiaUFnSUNCeVpYUjFjbTRnWm1Gc2MyVTdYRzRnSUgxY2JuMWNibHh1THk5b2RIUndjem92TDJSbGRtVnNiM0JsY2k1dGIzcHBiR3hoTG05eVp5OWxiaTFWVXk5a2IyTnpMMWRsWWk5QlVFa3ZWMmx1Wkc5M1FtRnpaVFkwTDBKaGMyVTJORjlsYm1OdlpHbHVaMTloYm1SZlpHVmpiMlJwYm1jalUyOXNkWFJwYjI1Zk1sOGxSVElsT0RBbE9UTmZjbVYzY21sMFpWOTBhR1ZmUkU5TmMxOWhkRzlpS0NsZllXNWtYMkowYjJFb0tWOTFjMmx1WjE5S1lYWmhVMk55YVhCMEozTmZWSGx3WldSQmNuSmhlWE5mWVc1a1gxVlVSaTA0WEc1bWRXNWpkR2x2YmlCaU5qUkZibU52WkdWVmJtbGpiMlJsS0hOMGNpa2dlMXh1SUNBZ0lISmxkSFZ5YmlCaWRHOWhLR1Z1WTI5a1pWVlNTVU52YlhCdmJtVnVkQ2h6ZEhJcExuSmxjR3hoWTJVb0x5VW9XekF0T1VFdFJsMTdNbjBwTDJjc0lHWjFibU4wYVc5dUtHMWhkR05vTENCd01Ta2dlMXh1SUNBZ0lDQWdJQ0J5WlhSMWNtNGdVM1J5YVc1bkxtWnliMjFEYUdGeVEyOWtaU2duTUhnbklDc2djREVwTzF4dUlDQWdJSDBwS1R0Y2JuMWNibHh1Wm5WdVkzUnBiMjRnWkdWc1pYUmxYM0J5YjNCbGNuUjVYMlp5YjIxZmJXRndLRzFoY0N3Z2NISnZjR1Z5ZEhrcGUxeHVJQ0FnSUd4bGRDQnVaWGRmYldGd0lEMGdUMkpxWldOMExtRnpjMmxuYmloUFltcGxZM1F1WTNKbFlYUmxLRzFoY0M1amIyNXpkSEoxWTNSdmNpNXdjbTkwYjNSNWNHVXBMQ0J0WVhBcE8xeHVJQ0FnSUdSbGJHVjBaU0J1WlhkZmJXRndXM0J5YjNCbGNuUjVYVHRjYmx4dUlDQnlaWFIxY200Z1QySnFaV04wTG1aeVpXVjZaU2h1WlhkZmJXRndLVHRjYm4xY2JseHVablZ1WTNScGIyNGdZMnhoYzNOZmRHOWZiMkpxS0cxaGNDbDdYRzRnSUNBZ2JHVjBJRzVsZDE5dFlYQWdQU0JQWW1wbFkzUXVZWE56YVdkdUtIdDlMQ0J0WVhBcE8xeHVJQ0J5WlhSMWNtNGdUMkpxWldOMExtWnlaV1Y2WlNodVpYZGZiV0Z3S1R0Y2JuMWNibHh1Wm5WdVkzUnBiMjRnWVdSa1gzQnliM0JsY25SNVgzUnZYMjFoY0NodFlYQXNJSEJ5YjNCbGNuUjVMQ0IyWVd4MVpTbDdYRzRnSUd4bGRDQnVaWGRmYldGd0lEMGdUMkpxWldOMExtRnpjMmxuYmloN2ZTd2diV0Z3S1R0Y2JpQWdibVYzWDIxaGNGdHdjbTl3WlhKMGVWMGdQU0IyWVd4MVpUdGNiaUFnY21WMGRYSnVJRTlpYW1WamRDNW1jbVZsZW1Vb2JtVjNYMjFoY0NrN1hHNTlYRzVjYmx4dVpuVnVZM1JwYjI0Z2RYQmtZWFJsWDIxaGNDaHRZWEFzSUhCeWIzQmxjblI1TENCMllXeDFaU2w3WEc0Z0lDQWdhV1lvY0hKdmNHVnlkSGtnYVc0Z1oyVjBYMjlpYW1WamRGOXJaWGx6S0cxaGNDa3BlMXh1SUNBZ0lDQWdJQ0J5WlhSMWNtNGdZV1JrWDNCeWIzQmxjblI1WDNSdlgyMWhjQ2h0WVhBc0lIQnliM0JsY25SNUxDQjJZV3gxWlNrN1hHNGdJQ0FnZlZ4dVhHNGdJQ0FnZEdoeWIzY2dYQ0p0WVhBZ1pHOWxjeUJ1YjNRZ2FHRjJaU0JyWlhsY0lqdGNibjFjYmx4dVpuVnVZM1JwYjI0Z1ltNXZkQ2hsZUhCeUtYdGNiaUFnY21WMGRYSnVJSDVsZUhCeU8xeHVmVnh1WEc1bWRXNWpkR2x2YmlCaVlXNWtLR3hsWm5Rc0lISnBaMmgwS1h0Y2JpQWdjbVYwZFhKdUlHeGxablFnSmlCeWFXZG9kRHRjYm4xY2JseHVablZ1WTNScGIyNGdZbTl5S0d4bFpuUXNJSEpwWjJoMEtYdGNiaUFnY21WMGRYSnVJR3hsWm5RZ2ZDQnlhV2RvZER0Y2JuMWNibHh1Wm5WdVkzUnBiMjRnWW5Oc0tHeGxablFzSUhKcFoyaDBLWHRjYmlBZ2NtVjBkWEp1SUd4bFpuUWdQRHdnY21sbmFIUTdYRzU5WEc1Y2JtWjFibU4wYVc5dUlHSnpjaWhzWldaMExDQnlhV2RvZENsN1hHNGdJSEpsZEhWeWJpQnNaV1owSUQ0K0lISnBaMmgwTzF4dWZWeHVYRzVtZFc1amRHbHZiaUJpZUc5eUtHeGxablFzSUhKcFoyaDBLWHRjYmlBZ2NtVjBkWEp1SUd4bFpuUWdYaUJ5YVdkb2REdGNibjFjYmx4dVpuVnVZM1JwYjI0Z2VtbHdLR3hwYzNSZmIyWmZiR2x6ZEhNcGUxeHVJQ0JwWmloc2FYTjBYMjltWDJ4cGMzUnpMbXhsYm1kMGFDQTlQVDBnTUNsN1hHNGdJQ0FnY21WMGRYSnVJRTlpYW1WamRDNW1jbVZsZW1Vb1cxMHBPMXh1SUNCOVhHNWNiaUFnYkdWMElHNWxkMTkyWVd4MVpTQTlJRnRkTzF4dUlDQnNaWFFnYzIxaGJHeGxjM1JmYkdWdVozUm9JRDBnYkdsemRGOXZabDlzYVhOMGMxc3dYVHRjYmx4dUlDQm1iM0lvYkdWMElIZ2diMllnYkdsemRGOXZabDlzYVhOMGN5bDdYRzRnSUNBZ2FXWW9lQzVzWlc1bmRHZ2dQQ0J6YldGc2JHVnpkRjlzWlc1bmRHZ3BlMXh1SUNBZ0lDQWdjMjFoYkd4bGMzUmZiR1Z1WjNSb0lEMGdlQzVzWlc1bmRHZzdYRzRnSUNBZ2ZWeHVJQ0I5WEc1Y2JpQWdabTl5S0d4bGRDQnBJRDBnTURzZ2FTQThJSE50WVd4c1pYTjBYMnhsYm1kMGFEc2dhU3NyS1h0Y2JpQWdJQ0JzWlhRZ1kzVnljbVZ1ZEY5MllXeDFaU0E5SUZ0ZE8xeHVJQ0FnSUdadmNpaHNaWFFnYWlBOUlEQTdJR29nUENCc2FYTjBYMjltWDJ4cGMzUnpMbXhsYm1kMGFEc2dhaXNyS1h0Y2JpQWdJQ0FnSUdOMWNuSmxiblJmZG1Gc2RXVXVjSFZ6YUNoc2FYTjBYMjltWDJ4cGMzUnpXMnBkVzJsZEtUdGNiaUFnSUNCOVhHNWNiaUFnSUNCdVpYZGZkbUZzZFdVdWNIVnphQ2h1WlhjZ1ZIVndiR1VvTGk0dVkzVnljbVZ1ZEY5MllXeDFaU2twTzF4dUlDQjlYRzVjYmlBZ2NtVjBkWEp1SUU5aWFtVmpkQzVtY21WbGVtVW9ibVYzWDNaaGJIVmxLVHRjYm4xY2JseHVablZ1WTNScGIyNGdZMkZ1WDJSbFkyOWtaVFkwS0dSaGRHRXBJSHRjYmlBZ2RISjVlMXh1SUNBZ0lHRjBiMklvWkdGMFlTazdYRzRnSUNBZ2NtVjBkWEp1SUhSeWRXVTdYRzRnSUgxallYUmphQ2hsS1h0Y2JpQWdJQ0J5WlhSMWNtNGdabUZzYzJVN1hHNGdJSDFjYm4xY2JseHVablZ1WTNScGIyNGdjbVZ0YjNabFgyWnliMjFmYkdsemRDaHNhWE4wTENCbGJHVnRaVzUwS1h0Y2JpQWdJQ0JzWlhRZ1ptOTFibVFnUFNCbVlXeHpaVHRjYmx4dUlDQWdJSEpsZEhWeWJpQnNhWE4wTG1acGJIUmxjaWdvWld4bGJTa2dQVDRnZTF4dUlDQWdJQ0FnSUNCcFppZ2habTkxYm1RZ0ppWWdaV3hsYlNBOVBUMGdaV3hsYldWdWRDbDdYRzRnSUNBZ0lDQWdJQ0FnSUNCbWIzVnVaQ0E5SUhSeWRXVTdYRzRnSUNBZ0lDQWdJQ0FnSUNCeVpYUjFjbTRnWm1Gc2MyVTdYRzRnSUNBZ0lDQWdJSDFjYmx4dUlDQWdJQ0FnSUNCeVpYUjFjbTRnZEhKMVpUdGNiaUFnSUNCOUtUdGNibjFjYmx4dVpuVnVZM1JwYjI0Z1ptOXNaR3dvWm5WdUxDQmhZMk1zSUd4cGMzUXBlMXh1SUNBZ0lHeGxkQ0JoWTJNeElEMGdZV05qTzF4dVhHNGdJQ0FnWm05eUtHTnZibk4wSUdWc0lHOW1JR3hwYzNRcGUxeHVJQ0FnSUNBZ0lDQmhZMk14SUQwZ1puVnVLR1ZzTENCaFkyTXhLVHRjYmlBZ0lDQjlYRzVjYmlBZ0lDQnlaWFIxY200Z1lXTmpNVHRjYm4xY2JseHVYRzVtZFc1amRHbHZiaUJtYjJ4a2NpaG1kVzRzSUdGall5d2diR2x6ZENsN1hHNGdJQ0FnYkdWMElHRmpZekVnUFNCaFkyTTdYRzVjYmlBZ0lDQm1iM0lvYkdWMElHa2dQU0JzYVhOMExteGxibWQwYUNBdElERTdJR2tnUGowZ01Ec2dhUzB0S1h0Y2JpQWdJQ0FnSUNBZ1lXTmpNU0E5SUdaMWJpaHNhWE4wVzJsZExDQmhZMk14S1R0Y2JpQWdJQ0I5WEc1Y2JpQWdJQ0J5WlhSMWNtNGdZV05qTVR0Y2JuMWNibHh1Wm5WdVkzUnBiMjRnYTJWNVptbHVaQ2hyWlhrc0lHNHNJSFIxY0d4bGJHbHpkQ2w3WEc1Y2JpQWdabTl5S0d4bGRDQnBJRDBnZEhWd2JHVnNhWE4wTG14bGJtZDBhQ0F0SURFN0lHa2dQajBnTURzZ2FTMHRLWHRjYmlBZ0lDQnBaaWgwZFhCc1pXeHBjM1JiYVYwdVoyVjBLRzRwSUQwOVBTQnJaWGtwZTF4dUlDQWdJQ0FnY21WMGRYSnVJSFIxY0d4bGJHbHpkRnRwWFR0Y2JpQWdJQ0I5WEc0Z0lIMWNibHh1SUNCeVpYUjFjbTRnWm1Gc2MyVTdYRzU5WEc1Y2JtWjFibU4wYVc5dUlHdGxlV1JsYkdWMFpTaHJaWGtzSUc0c0lIUjFjR3hsYkdsemRDbDdYRzVjYmlBZ0lDQm1iM0lvYkdWMElHa2dQU0IwZFhCc1pXeHBjM1F1YkdWdVozUm9JQzBnTVRzZ2FTQStQU0F3T3lCcExTMHBlMXh1SUNBZ0lDQWdJQ0JwWmloMGRYQnNaV3hwYzNSYmFWMHVaMlYwS0c0cElEMDlQU0JyWlhrcGUxeHVJQ0FnSUNBZ0lDQWdJQ0FnY21WMGRYSnVJSFIxY0d4bGJHbHpkQzVqYjI1allYUW9XMTBwTG5Od2JHbGpaU2hwTENBeEtUdGNiaUFnSUNBZ0lDQWdmVnh1SUNBZ0lIMWNibHh1SUNBZ0lISmxkSFZ5YmlCMGRYQnNaV3hwYzNRN1hHNTlYRzVjYm1aMWJtTjBhVzl1SUd0bGVYTjBiM0psS0d0bGVTd2diaXdnYkdsemRDd2dibVYzZEhWd2JHVXBlMXh1SUNBZ0lHWnZjaWhzWlhRZ2FTQTlJR3hwYzNRdWJHVnVaM1JvSUMwZ01Uc2dhU0ErUFNBd095QnBMUzBwZTF4dUlDQWdJQ0FnSUNCcFppaHNhWE4wVzJsZExtZGxkQ2h1S1NBOVBUMGdhMlY1S1h0Y2JpQWdJQ0FnSUNBZ0lDQWdJSEpsZEhWeWJpQnNhWE4wTG1OdmJtTmhkQ2hiWFNrdWMzQnNhV05sS0drc0lERXNJRzVsZDNSMWNHeGxLVHRjYmlBZ0lDQWdJQ0FnZlZ4dUlDQWdJSDFjYmx4dUlDQnlaWFIxY200Z2JHbHpkQzVqYjI1allYUW9XMTBwTG5CMWMyZ29ibVYzZEhWd2JHVXBPMXh1ZlZ4dVhHNW1kVzVqZEdsdmJpQnJaWGx0WlcxaVpYSW9hMlY1TENCdUxDQnNhWE4wS1h0Y2JpQWdabTl5S0d4bGRDQnBJRDBnYkdsemRDNXNaVzVuZEdnZ0xTQXhPeUJwSUQ0OUlEQTdJR2t0TFNsN1hHNGdJQ0FnYVdZb2JHbHpkRnRwWFM1blpYUW9iaWtnUFQwOUlHdGxlU2w3WEc0Z0lDQWdJQ0J5WlhSMWNtNGdkSEoxWlR0Y2JpQWdJQ0I5WEc0Z0lIMWNibHh1SUNCeVpYUjFjbTRnWm1Gc2MyVTdYRzU5WEc1Y2JtWjFibU4wYVc5dUlHdGxlWFJoYTJVb2EyVjVMQ0J1TENCc2FYTjBLWHRjYmlBZ2FXWW9JV3RsZVcxbGJXSmxjaWhyWlhrc0lHNHNJR3hwYzNRcEtYdGNiaUFnSUNCeVpYUjFjbTRnWm1Gc2MyVTdYRzRnSUgxY2JseHVJQ0JzWlhRZ2RIVndiR1VnUFNCclpYbG1hVzVrS0d0bGVTd2diaXdnYkdsemRDazdYRzVjYmlBZ2NtVjBkWEp1SUc1bGR5QlVkWEJzWlNoMGRYQnNaUzVuWlhRb2Jpa3NJSFIxY0d4bExDQnJaWGxrWld4bGRHVW9hMlY1TENCdUxDQnNhWE4wS1NrN1hHNTlYRzVjYm1aMWJtTjBhVzl1SUd0bGVYSmxjR3hoWTJVb2EyVjVMQ0J1TENCc2FYTjBMQ0J1WlhkMGRYQnNaU2w3WEc0Z0lGeHVJQ0JtYjNJb2JHVjBJR2tnUFNCMGRYQnNaV3hwYzNRdWJHVnVaM1JvSUMwZ01Uc2dhU0ErUFNBd095QnBMUzBwZTF4dUlDQWdJR2xtS0hSMWNHeGxiR2x6ZEZ0cFhTNW5aWFFvYmlrZ1BUMDlJR3RsZVNsN1hHNGdJQ0FnSUNCeVpYUjFjbTRnZEhWd2JHVnNhWE4wTG1OdmJtTmhkQ2hiWFNrdWMzQnNhV05sS0drc0lERXNJRzVsZDNSMWNHeGxLVHRjYmlBZ0lDQjlYRzRnSUgxY2JseHVJQ0J5WlhSMWNtNGdkSFZ3YkdWc2FYTjBPMXh1ZlZ4dVhHNWNibVoxYm1OMGFXOXVJSEpsZG1WeWMyVW9iR2x6ZENsN1hHNGdJQ0FnY21WMGRYSnVJR3hwYzNRdVkyOXVZMkYwS0Z0ZEtTNXlaWFpsY25ObEtDazdYRzU5WEc1Y2JtWjFibU4wYVc5dUlHMWhjSE5mWm1sdVpDaHJaWGtzSUcxaGNDbDdYRzRnSUNBZ2FXWW9hMlY1SUdsdUlHZGxkRjl2WW1wbFkzUmZhMlY1Y3lodFlYQXBLWHRjYmlBZ0lDQWdJQ0FnY21WMGRYSnVJRzVsZHlCVWRYQnNaU2hUZVcxaWIyd3VabTl5S0Z3aWIydGNJaWtzSUcxaGNGdHJaWGxkS1R0Y2JpQWdJQ0I5Wld4elpYdGNiaUFnSUNBZ0lDQWdjbVYwZFhKdUlGTjViV0p2YkM1bWIzSW9YQ0psY25KdmNsd2lLVHRjYmlBZ0lDQjlYRzU5WEc1Y2JtWjFibU4wYVc5dUlHWnNZWFIwWlc0b2JHbHpkQ3dnZEdGcGJDQTlJRnRkS1NCN1hHNGdJR3hsZENCdVpYZGZiR2x6ZENBOUlGdGRPMXh1WEc0Z0lHWnZjaWhzWlhRZ1pTQnZaaUJzYVhOMEtYdGNiaUFnSUNCcFppaHBjMEZ5Y21GNUtHVXBLWHRjYmlBZ0lDQWdJRzVsZDE5c2FYTjBJRDBnYm1WM1gyeHBjM1F1WTI5dVkyRjBLR1pzWVhSMFpXNG9aU2twTzF4dUlDQWdJSDFsYkhObGUxeHVJQ0FnSUNBZ2JtVjNYMnhwYzNRdWNIVnphQ2hsS1R0Y2JpQWdJQ0I5WEc0Z0lIMWNibHh1SUNCeVpYUjFjbTRnVDJKcVpXTjBMbVp5WldWNlpTaHVaWGRmYkdsemRDNWpiMjVqWVhRb2RHRnBiQ2twTzF4dWZWeHVYRzVtZFc1amRHbHZiaUJrZFhCc2FXTmhkR1VvYml3Z1pXeGxiU2w3WEc0Z0lHeGxkQ0JzYVhOMElEMGdXMTA3WEc1Y2JpQWdabTl5S0d4bGRDQnBJRDBnTURzZ2FTQThJRzQ3SUdrckt5bDdYRzRnSUNBZ2JHbHpkQzV3ZFhOb0tHVnNaVzBwTzF4dUlDQjlYRzVjYmlBZ2NtVjBkWEp1SUU5aWFtVmpkQzVtY21WbGVtVW9iR2x6ZENrN1hHNTlYRzVjYm1aMWJtTjBhVzl1SUcxaGNHWnZiR1JzS0daMWJpd2dZV05qTENCc2FYTjBLWHRjYmlBZ2JHVjBJRzVsZDJ4cGMzUWdQU0JiWFR0Y2JseHVJQ0JtYjNJb2JHVjBJSGdnYjJZZ2JHbHpkQ2w3WEc0Z0lDQWdiR1YwSUhSMWNDQTlJR1oxYmloNExDQmhZMk1wTzF4dUlDQWdJRzVsZDJ4cGMzUXVjSFZ6YUNoMGRYQXVaMlYwS0RBcEtUdGNiaUFnSUNCaFkyTWdQU0IwZFhBdVoyVjBLREVwTzF4dUlDQjlYRzVjYmx4dUlDQnlaWFIxY200Z2JtVjNJRlIxY0d4bEtFOWlhbVZqZEM1bWNtVmxlbVVvYm1WM2JHbHpkQ2tzSUdGall5azdYRzU5WEc1Y2JtWjFibU4wYVc5dUlHWnBiSFJsY20xaGNDaG1kVzRzSUd4cGMzUXBlMXh1SUNCc1pYUWdibVYzYkdsemRDQTlJRnRkTzF4dVhHNGdJR1p2Y2loNElHOW1JR3hwYzNRcGUxeHVJQ0FnSUd4bGRDQnlaWE4xYkhRZ1BTQm1kVzRvZUNrN1hHNWNiaUFnSUNCcFppaHlaWE4xYkhRZ1BUMDlJSFJ5ZFdVcGUxeHVJQ0FnSUNBZ2JtVjNiR2x6ZEM1d2RYTm9LSGdwTzF4dUlDQWdJSDFsYkhObElHbG1LSEpsYzNWc2RDQnBibk4wWVc1alpXOW1JRlIxY0d4bEtYdGNiaUFnSUNBZ0lHNWxkMnhwYzNRdWNIVnphQ2h5WlhOMWJIUXVaMlYwS0RFcEtUdGNiaUFnSUNCOVhHNGdJSDFjYmx4dUlDQnlaWFIxY200Z1QySnFaV04wTG1aeVpXVjZaU2h1Wlhkc2FYTjBLVHRjYm4xY2JseHVablZ1WTNScGIyNGdiV0Z3YzE5bWIyeGtLR1oxYml3Z1lXTmpMQ0J0WVhBcGUxeHVJQ0JzWlhRZ1lXTmpNU0E5SUdGall6dGNibHh1SUNCbWIzSW9iR1YwSUdzZ2IyWWdaMlYwWDI5aWFtVmpkRjlyWlhsektHMWhjQ2twZTF4dUlDQWdJR0ZqWXpFZ1BTQm1kVzRvYXl3Z2JXRndXMnRkTENCaFkyTXhLVHRjYmlBZ2ZWeHVYRzRnSUhKbGRIVnliaUJoWTJNeE8xeHVmVnh1WEc1bWRXNWpkR2x2YmlCdFlYQnpYMlp5YjIxZmJHbHpkQ2hzYVhOMEtYdGNiaUFnYkdWMElHMGdQU0I3ZlR0Y2JseHVJQ0JtYjNJb2VDQnZaaUJzYVhOMEtYdGNiaUFnSUNCdFczZ3VaMlYwS0RBcFhTQTlJSGd1WjJWMEtERXBPMXh1SUNCOVhHNWNiaUFnY21WMGRYSnVJRTlpYW1WamRDNW1jbVZsZW1Vb2JTazdYRzU5WEc1Y2JtVjRjRzl5ZENCa1pXWmhkV3gwSUh0Y2JpQWdZMkZzYkY5d2NtOXdaWEowZVN4Y2JpQWdZWEJ3Ykhrc1hHNGdJR052Ym5SaGFXNXpMRnh1SUNCblpYUmZaMnh2WW1Gc0xGeHVJQ0JrWldaemRISjFZM1FzWEc0Z0lHUmxabVY0WTJWd2RHbHZiaXhjYmlBZ1pHVm1jSEp2ZEc5amIyd3NYRzRnSUdSbFptbHRjR3dzWEc0Z0lHZGxkRjl2WW1wbFkzUmZhMlY1Y3l4Y2JpQWdhWE5mZG1Gc2FXUmZZMmhoY21GamRHVnlMRnh1SUNCaU5qUkZibU52WkdWVmJtbGpiMlJsTEZ4dUlDQmtaV3hsZEdWZmNISnZjR1Z5ZEhsZlpuSnZiVjl0WVhBc1hHNGdJR0ZrWkY5d2NtOXdaWEowZVY5MGIxOXRZWEFzWEc0Z0lHTnNZWE56WDNSdlgyOWlhaXhjYmlBZ1kyRnVYMlJsWTI5a1pUWTBMRnh1SUNCaWJtOTBMRnh1SUNCaVlXNWtMRnh1SUNCaWIzSXNYRzRnSUdKemJDeGNiaUFnWW5OeUxGeHVJQ0JpZUc5eUxGeHVJQ0I2YVhBc1hHNGdJR1p2YkdSc0xGeHVJQ0JtYjJ4a2NpeGNiaUFnY21WdGIzWmxYMlp5YjIxZmJHbHpkQ3hjYmlBZ2EyVjVaR1ZzWlhSbExGeHVJQ0JyWlhsemRHOXlaU3hjYmlBZ2EyVjVabWx1WkN4Y2JpQWdhMlY1ZEdGclpTeGNiaUFnYTJWNWNtVndiR0ZqWlN4Y2JpQWdjbVYyWlhKelpTeGNiaUFnZFhCa1lYUmxYMjFoY0N4Y2JpQWdiV0Z3YzE5bWFXNWtMRnh1SUNCbWJHRjBkR1Z1TEZ4dUlDQmtkWEJzYVdOaGRHVXNYRzRnSUcxaGNHWnZiR1JzTEZ4dUlDQm1hV3gwWlhKdFlYQXNYRzRnSUcxaGNITmZabTlzWkZ4dWZUdGNiaUpkTENKemIzVnlZMlZTYjI5MElqb2lMM052ZFhKalpTOGlmUT09XG4iLCJpbXBvcnQgQml0U3RyaW5nIGZyb20gJy4vYml0X3N0cmluZyc7XG5pbXBvcnQgUGF0dGVybnMgZnJvbSAnLi9wYXR0ZXJucyc7XG5pbXBvcnQgeyBUdXBsZSB9IGZyb20gJy4vcHJpbWl0aXZlcyc7XG5cbmZ1bmN0aW9uIF9jYXNlKGNvbmRpdGlvbiwgY2xhdXNlcykge1xuICByZXR1cm4gUGF0dGVybnMuZGVmbWF0Y2goLi4uY2xhdXNlcykoY29uZGl0aW9uKTtcbn1cblxuZnVuY3Rpb24gY29uZChjbGF1c2VzKSB7XG4gIGZvciAobGV0IGNsYXVzZSBvZiBjbGF1c2VzKSB7XG4gICAgaWYgKGNsYXVzZVswXSkge1xuICAgICAgcmV0dXJuIGNsYXVzZVsxXSgpO1xuICAgIH1cbiAgfVxuXG4gIHRocm93IG5ldyBFcnJvcigpO1xufVxuXG5mdW5jdGlvbiBtYXBfdXBkYXRlKG1hcCwgdmFsdWVzKSB7XG4gIHJldHVybiBPYmplY3QuZnJlZXplKE9iamVjdC5hc3NpZ24oT2JqZWN0LmNyZWF0ZShtYXAuY29uc3RydWN0b3IucHJvdG90eXBlKSwgbWFwLCB2YWx1ZXMpKTtcbn1cblxuZnVuY3Rpb24gX2Zvcihjb2xsZWN0aW9ucywgZnVuLCBmaWx0ZXIgPSAoKSA9PiB0cnVlLCBpbnRvID0gW10sIHByZXZpb3VzVmFsdWVzID0gW10pIHtcbiAgbGV0IHBhdHRlcm4gPSBjb2xsZWN0aW9uc1swXVswXTtcbiAgbGV0IGNvbGxlY3Rpb24gPSBjb2xsZWN0aW9uc1swXVsxXTtcblxuICBpZiAoY29sbGVjdGlvbnMubGVuZ3RoID09PSAxKSB7XG4gICAgaWYgKGNvbGxlY3Rpb24gaW5zdGFuY2VvZiBCaXRTdHJpbmcpIHtcbiAgICAgIGxldCBic1NsaWNlID0gY29sbGVjdGlvbi5zbGljZSgwLCBwYXR0ZXJuLmJ5dGVfc2l6ZSgpKTtcbiAgICAgIGxldCBpID0gMTtcblxuICAgICAgd2hpbGUgKGJzU2xpY2UuYnl0ZV9zaXplID09IHBhdHRlcm4uYnl0ZV9zaXplKCkpIHtcbiAgICAgICAgbGV0IHIgPSBQYXR0ZXJucy5tYXRjaF9ub190aHJvdyhwYXR0ZXJuLCBic1NsaWNlKTtcbiAgICAgICAgbGV0IGFyZ3MgPSBwcmV2aW91c1ZhbHVlcy5jb25jYXQocik7XG5cbiAgICAgICAgaWYgKHIgJiYgZmlsdGVyLmFwcGx5KHRoaXMsIGFyZ3MpKSB7XG4gICAgICAgICAgaW50byA9IGludG8uY29uY2F0KFtmdW4uYXBwbHkodGhpcywgYXJncyldKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGJzU2xpY2UgPSBjb2xsZWN0aW9uLnNsaWNlKHBhdHRlcm4uYnl0ZV9zaXplKCkgKiBpLCBwYXR0ZXJuLmJ5dGVfc2l6ZSgpICogKGkgKyAxKSk7XG4gICAgICAgIGkrKztcbiAgICAgIH1cblxuICAgICAgcmV0dXJuIGludG87XG4gICAgfSBlbHNlIHtcbiAgICAgIGZvciAobGV0IGVsZW0gb2YgY29sbGVjdGlvbikge1xuICAgICAgICBsZXQgciA9IFBhdHRlcm5zLm1hdGNoX25vX3Rocm93KHBhdHRlcm4sIGVsZW0pO1xuICAgICAgICBsZXQgYXJncyA9IHByZXZpb3VzVmFsdWVzLmNvbmNhdChyKTtcblxuICAgICAgICBpZiAociAmJiBmaWx0ZXIuYXBwbHkodGhpcywgYXJncykpIHtcbiAgICAgICAgICBpbnRvID0gaW50by5jb25jYXQoW2Z1bi5hcHBseSh0aGlzLCBhcmdzKV0pO1xuICAgICAgICB9XG4gICAgICB9XG5cbiAgICAgIHJldHVybiBpbnRvO1xuICAgIH1cbiAgfSBlbHNlIHtcbiAgICBsZXQgX2ludG8gPSBbXTtcblxuICAgIGlmIChjb2xsZWN0aW9uIGluc3RhbmNlb2YgQml0U3RyaW5nKSB7XG4gICAgICBsZXQgYnNTbGljZSA9IGNvbGxlY3Rpb24uc2xpY2UoMCwgcGF0dGVybi5ieXRlX3NpemUoKSk7XG4gICAgICBsZXQgaSA9IDE7XG5cbiAgICAgIHdoaWxlIChic1NsaWNlLmJ5dGVfc2l6ZSA9PSBwYXR0ZXJuLmJ5dGVfc2l6ZSgpKSB7XG4gICAgICAgIGxldCByID0gUGF0dGVybnMubWF0Y2hfbm9fdGhyb3cocGF0dGVybiwgYnNTbGljZSk7XG4gICAgICAgIGlmIChyKSB7XG4gICAgICAgICAgX2ludG8gPSBpbnRvLmNvbmNhdCh0aGlzLl9mb3IoY29sbGVjdGlvbnMuc2xpY2UoMSksIGZ1biwgZmlsdGVyLCBfaW50bywgcHJldmlvdXNWYWx1ZXMuY29uY2F0KHIpKSk7XG4gICAgICAgIH1cblxuICAgICAgICBic1NsaWNlID0gY29sbGVjdGlvbi5zbGljZShwYXR0ZXJuLmJ5dGVfc2l6ZSgpICogaSwgcGF0dGVybi5ieXRlX3NpemUoKSAqIChpICsgMSkpO1xuICAgICAgICBpKys7XG4gICAgICB9XG4gICAgfSBlbHNlIHtcbiAgICAgIGZvciAobGV0IGVsZW0gb2YgY29sbGVjdGlvbikge1xuICAgICAgICBsZXQgciA9IFBhdHRlcm5zLm1hdGNoX25vX3Rocm93KHBhdHRlcm4sIGVsZW0pO1xuICAgICAgICBpZiAocikge1xuICAgICAgICAgIF9pbnRvID0gaW50by5jb25jYXQodGhpcy5fZm9yKGNvbGxlY3Rpb25zLnNsaWNlKDEpLCBmdW4sIGZpbHRlciwgX2ludG8sIHByZXZpb3VzVmFsdWVzLmNvbmNhdChyKSkpO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgfVxuXG4gICAgcmV0dXJuIF9pbnRvO1xuICB9XG59XG5cbmZ1bmN0aW9uIF90cnkoZG9fZnVuLCByZXNjdWVfZnVuY3Rpb24sIGNhdGNoX2Z1biwgZWxzZV9mdW5jdGlvbiwgYWZ0ZXJfZnVuY3Rpb24pIHtcbiAgbGV0IHJlc3VsdCA9IG51bGw7XG5cbiAgdHJ5IHtcbiAgICByZXN1bHQgPSBkb19mdW4oKTtcbiAgfSBjYXRjaCAoZSkge1xuICAgIGxldCBleF9yZXN1bHQgPSBudWxsO1xuXG4gICAgaWYgKHJlc2N1ZV9mdW5jdGlvbikge1xuICAgICAgdHJ5IHtcbiAgICAgICAgZXhfcmVzdWx0ID0gcmVzY3VlX2Z1bmN0aW9uKGUpO1xuICAgICAgICByZXR1cm4gZXhfcmVzdWx0O1xuICAgICAgfSBjYXRjaCAoZXgpIHtcbiAgICAgICAgaWYgKGV4IGluc3RhbmNlb2YgUGF0dGVybnMuTWF0Y2hFcnJvcikge1xuICAgICAgICAgIHRocm93IGV4O1xuICAgICAgICB9XG4gICAgICB9XG4gICAgfVxuXG4gICAgaWYgKGNhdGNoX2Z1bikge1xuICAgICAgdHJ5IHtcbiAgICAgICAgZXhfcmVzdWx0ID0gY2F0Y2hfZnVuKGUpO1xuICAgICAgICByZXR1cm4gZXhfcmVzdWx0O1xuICAgICAgfSBjYXRjaCAoZXgpIHtcbiAgICAgICAgaWYgKGV4IGluc3RhbmNlb2YgUGF0dGVybnMuTWF0Y2hFcnJvcikge1xuICAgICAgICAgIHRocm93IGV4O1xuICAgICAgICB9XG4gICAgICB9XG4gICAgfVxuXG4gICAgdGhyb3cgZTtcbiAgfSBmaW5hbGx5IHtcbiAgICBpZiAoYWZ0ZXJfZnVuY3Rpb24pIHtcbiAgICAgIGFmdGVyX2Z1bmN0aW9uKCk7XG4gICAgfVxuICB9XG5cbiAgaWYgKGVsc2VfZnVuY3Rpb24pIHtcbiAgICB0cnkge1xuICAgICAgcmV0dXJuIGVsc2VfZnVuY3Rpb24ocmVzdWx0KTtcbiAgICB9IGNhdGNoIChleCkge1xuICAgICAgaWYgKGV4IGluc3RhbmNlb2YgUGF0dGVybnMuTWF0Y2hFcnJvcikge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoXCJObyBNYXRjaCBGb3VuZCBpbiBFbHNlXCIpO1xuICAgICAgfVxuXG4gICAgICB0aHJvdyBleDtcbiAgICB9XG4gIH0gZWxzZSB7XG4gICAgcmV0dXJuIHJlc3VsdDtcbiAgfVxufVxuXG5mdW5jdGlvbiBfd2l0aCguLi5hcmdzKSB7XG4gIGxldCBhcmdzVG9QYXNzID0gW107XG5cbiAgZm9yIChsZXQgaSA9IDA7IGkgPCBhcmdzLmxlbmd0aDsgaSsrKSB7XG4gICAgaWYgKGkgPT09IGFyZ3MubGVuZ3RoIC0gMSkge1xuICAgICAgcmV0dXJuIGFyZ3NbaV0uYXBwbHkobnVsbCwgYXJnc1RvUGFzcyk7XG4gICAgfSBlbHNlIHtcbiAgICAgIGxldCBbcGF0dGVybiwgZnVuY10gPSBhcmdzW2ldO1xuXG4gICAgICBsZXQgcmVzdWx0ID0gZnVuYy5hcHBseShudWxsLCBhcmdzVG9QYXNzKTtcblxuICAgICAgbGV0IHBhdHRlcm5SZXN1bHQgPSBQYXR0ZXJucy5tYXRjaF9ub190aHJvdyhwYXR0ZXJuLCByZXN1bHQpO1xuXG4gICAgICBpZiAocGF0dGVyblJlc3VsdCA9PSBudWxsKSB7XG4gICAgICAgIHJldHVybiByZXN1bHQ7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBhcmdzVG9QYXNzID0gYXJnc1RvUGFzcy5jb25jYXQocGF0dGVyblJlc3VsdCk7XG4gICAgICB9XG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIG51bGw7XG59XG5cbmV4cG9ydCBkZWZhdWx0IHtcbiAgX2Nhc2UsXG4gIGNvbmQsXG4gIG1hcF91cGRhdGUsXG4gIF9mb3IsXG4gIF90cnksXG4gIF93aXRoXG59O1xuLy8jIHNvdXJjZU1hcHBpbmdVUkw9ZGF0YTphcHBsaWNhdGlvbi9qc29uO2Jhc2U2NCxleUoyWlhKemFXOXVJam96TENKemIzVnlZMlZ6SWpwYklteHBZaTlqYjNKbEwzTndaV05wWVd4ZlptOXliWE11YW5NaVhTd2libUZ0WlhNaU9sdGRMQ0p0WVhCd2FXNW5jeUk2SWtGQlFVRXNUMEZCVHl4VFFVRlFMRTFCUVhOQ0xHTkJRWFJDTzBGQlEwRXNUMEZCVHl4UlFVRlFMRTFCUVhGQ0xGbEJRWEpDTzBGQlEwRXNVMEZCVXl4TFFVRlVMRkZCUVhOQ0xHTkJRWFJDT3p0QlFVVkJMRk5CUVZNc1MwRkJWQ3hEUVVGbExGTkJRV1lzUlVGQk1FSXNUMEZCTVVJc1JVRkJhME03UVVGRGFFTXNVMEZCVHl4VFFVRlRMRkZCUVZRc1EwRkJhMElzUjBGQlJ5eFBRVUZJTEVOQlFXeENMRU5CUVRoQ0xGTkJRVGxDTEVOQlFWQXNRMEZFWjBNN1EwRkJiRU03TzBGQlNVRXNVMEZCVXl4SlFVRlVMRU5CUVdNc1QwRkJaQ3hGUVVGelFqdEJRVU53UWl4UFFVRkpMRWxCUVVrc1RVRkJTaXhKUVVGakxFOUJRV3hDTEVWQlFUQkNPMEZCUTNoQ0xGRkJRVWNzVDBGQlR5eERRVUZRTEVOQlFVZ3NSVUZCWVR0QlFVTllMR0ZCUVU4c1QwRkJUeXhEUVVGUUxFZEJRVkFzUTBGRVZ6dExRVUZpTzBkQlJFWTdPMEZCVFVFc1VVRkJUU3hKUVVGSkxFdEJRVW9zUlVGQlRpeERRVkJ2UWp0RFFVRjBRanM3UVVGVlFTeFRRVUZUTEZWQlFWUXNRMEZCYjBJc1IwRkJjRUlzUlVGQmVVSXNUVUZCZWtJc1JVRkJaME03UVVGRE9VSXNVMEZCVHl4UFFVRlBMRTFCUVZBc1EwRkRUQ3hQUVVGUExFMUJRVkFzUTBGRFJTeFBRVUZQTEUxQlFWQXNRMEZCWXl4SlFVRkpMRmRCUVVvc1EwRkJaMElzVTBGQmFFSXNRMEZFYUVJc1JVRkRORU1zUjBGRU5VTXNSVUZEYVVRc1RVRkVha1FzUTBGRVN5eERRVUZRTEVOQlJEaENPME5CUVdoRE96dEJRVkZCTEZOQlFWTXNTVUZCVkN4RFFVRmpMRmRCUVdRc1JVRkJNa0lzUjBGQk0wSXNSVUZCWjBNc1UwRkJVeXhOUVVGTkxFbEJRVTRzUlVGQldTeFBRVUZQTEVWQlFWQXNSVUZCVnl4cFFrRkJhVUlzUlVGQmFrSXNSVUZCYjBJN1FVRkRiRVlzVFVGQlNTeFZRVUZWTEZsQlFWa3NRMEZCV2l4RlFVRmxMRU5CUVdZc1EwRkJWaXhEUVVRNFJUdEJRVVZzUml4TlFVRkpMR0ZCUVdFc1dVRkJXU3hEUVVGYUxFVkJRV1VzUTBGQlppeERRVUZpTEVOQlJqaEZPenRCUVVsc1JpeE5RVUZITEZsQlFWa3NUVUZCV2l4TFFVRjFRaXhEUVVGMlFpeEZRVUY1UWp0QlFVTXhRaXhSUVVGSExITkNRVUZ6UWl4VFFVRjBRaXhGUVVGblF6dEJRVU5xUXl4VlFVRkpMRlZCUVZVc1YwRkJWeXhMUVVGWUxFTkJRV2xDTEVOQlFXcENMRVZCUVc5Q0xGRkJRVkVzVTBGQlVpeEZRVUZ3UWl4RFFVRldMRU5CUkRaQ08wRkJSV3BETEZWQlFVa3NTVUZCU1N4RFFVRktMRU5CUmpaQ096dEJRVWxxUXl4aFFVRk5MRkZCUVZFc1UwRkJVaXhKUVVGeFFpeFJRVUZSTEZOQlFWSXNSVUZCY2tJc1JVRkJlVU03UVVGRE4wTXNXVUZCU1N4SlFVRkpMRk5CUVZNc1kwRkJWQ3hEUVVGM1FpeFBRVUY0UWl4RlFVRnBReXhQUVVGcVF5eERRVUZLTEVOQlJIbERPMEZCUlRkRExGbEJRVWtzVDBGQlR5eGxRVUZsTEUxQlFXWXNRMEZCYzBJc1EwRkJkRUlzUTBGQlVDeERRVVo1UXpzN1FVRkpOME1zV1VGQlJ5eExRVUZMTEU5QlFVOHNTMEZCVUN4RFFVRmhMRWxCUVdJc1JVRkJiVUlzU1VGQmJrSXNRMEZCVEN4RlFVRTRRanRCUVVNdlFpeHBRa0ZCVHl4TFFVRkxMRTFCUVV3c1EwRkJXU3hEUVVGRExFbEJRVWtzUzBGQlNpeERRVUZWTEVsQlFWWXNSVUZCWjBJc1NVRkJhRUlzUTBGQlJDeERRVUZhTEVOQlFWQXNRMEZFSzBJN1UwRkJha003TzBGQlNVRXNhMEpCUVZVc1YwRkJWeXhMUVVGWUxFTkJRV2xDTEZGQlFWRXNVMEZCVWl4TFFVRnpRaXhEUVVGMFFpeEZRVUY1UWl4UlFVRlJMRk5CUVZJc1RVRkJkVUlzU1VGQlNTeERRVUZLTEVOQlFYWkNMRU5CUVhCRUxFTkJValpETzBGQlV6ZERMRmxCVkRaRE8wOUJRUzlET3p0QlFWbEJMR0ZCUVU4c1NVRkJVQ3hEUVdoQ2FVTTdTMEZCYmtNc1RVRnBRa3M3UVVGRFNDeFhRVUZKTEVsQlFVa3NTVUZCU2l4SlFVRlpMRlZCUVdoQ0xFVkJRVEpDTzBGQlEzcENMRmxCUVVrc1NVRkJTU3hUUVVGVExHTkJRVlFzUTBGQmQwSXNUMEZCZUVJc1JVRkJhVU1zU1VGQmFrTXNRMEZCU2l4RFFVUnhRanRCUVVWNlFpeFpRVUZKTEU5QlFVOHNaVUZCWlN4TlFVRm1MRU5CUVhOQ0xFTkJRWFJDTEVOQlFWQXNRMEZHY1VJN08wRkJTWHBDTEZsQlFVY3NTMEZCU3l4UFFVRlBMRXRCUVZBc1EwRkJZU3hKUVVGaUxFVkJRVzFDTEVsQlFXNUNMRU5CUVV3c1JVRkJPRUk3UVVGREwwSXNhVUpCUVU4c1MwRkJTeXhOUVVGTUxFTkJRVmtzUTBGQlF5eEpRVUZKTEV0QlFVb3NRMEZCVlN4SlFVRldMRVZCUVdkQ0xFbEJRV2hDTEVOQlFVUXNRMEZCV2l4RFFVRlFMRU5CUkN0Q08xTkJRV3BETzA5QlNrWTdPMEZCVTBFc1lVRkJUeXhKUVVGUUxFTkJWa2M3UzBGcVFrdzdSMEZFUml4TlFUaENTenRCUVVOSUxGRkJRVWtzVVVGQlVTeEZRVUZTTEVOQlJFUTdPMEZCUjBnc1VVRkJSeXh6UWtGQmMwSXNVMEZCZEVJc1JVRkJaME03UVVGRGFrTXNWVUZCU1N4VlFVRlZMRmRCUVZjc1MwRkJXQ3hEUVVGcFFpeERRVUZxUWl4RlFVRnZRaXhSUVVGUkxGTkJRVklzUlVGQmNFSXNRMEZCVml4RFFVUTJRanRCUVVWcVF5eFZRVUZKTEVsQlFVa3NRMEZCU2l4RFFVWTJRanM3UVVGSmFrTXNZVUZCVFN4UlFVRlJMRk5CUVZJc1NVRkJjVUlzVVVGQlVTeFRRVUZTTEVWQlFYSkNMRVZCUVhsRE8wRkJRemRETEZsQlFVa3NTVUZCU1N4VFFVRlRMR05CUVZRc1EwRkJkMElzVDBGQmVFSXNSVUZCYVVNc1QwRkJha01zUTBGQlNpeERRVVI1UXp0QlFVVTNReXhaUVVGSExFTkJRVWdzUlVGQlN6dEJRVU5JTEd0Q1FVRlJMRXRCUVVzc1RVRkJUQ3hEUVVGWkxFdEJRVXNzU1VGQlRDeERRVUZWTEZsQlFWa3NTMEZCV2l4RFFVRnJRaXhEUVVGc1FpeERRVUZXTEVWQlFXZERMRWRCUVdoRExFVkJRWEZETEUxQlFYSkRMRVZCUVRaRExFdEJRVGRETEVWQlFXOUVMR1ZCUVdVc1RVRkJaaXhEUVVGelFpeERRVUYwUWl4RFFVRndSQ3hEUVVGYUxFTkJRVklzUTBGRVJ6dFRRVUZNT3p0QlFVbEJMR3RDUVVGVkxGZEJRVmNzUzBGQldDeERRVUZwUWl4UlFVRlJMRk5CUVZJc1MwRkJjMElzUTBGQmRFSXNSVUZCZVVJc1VVRkJVU3hUUVVGU0xFMUJRWFZDTEVsQlFVa3NRMEZCU2l4RFFVRjJRaXhEUVVGd1JDeERRVTQyUXp0QlFVODNReXhaUVZBMlF6dFBRVUV2UXp0TFFVcEdMRTFCWVVzN1FVRkRTQ3hYUVVGSkxFbEJRVWtzU1VGQlNpeEpRVUZaTEZWQlFXaENMRVZCUVRKQ08wRkJRM3BDTEZsQlFVa3NTVUZCU1N4VFFVRlRMR05CUVZRc1EwRkJkMElzVDBGQmVFSXNSVUZCYVVNc1NVRkJha01zUTBGQlNpeERRVVJ4UWp0QlFVVjZRaXhaUVVGSExFTkJRVWdzUlVGQlN6dEJRVU5JTEd0Q1FVRlJMRXRCUVVzc1RVRkJUQ3hEUVVGWkxFdEJRVXNzU1VGQlRDeERRVUZWTEZsQlFWa3NTMEZCV2l4RFFVRnJRaXhEUVVGc1FpeERRVUZXTEVWQlFXZERMRWRCUVdoRExFVkJRWEZETEUxQlFYSkRMRVZCUVRaRExFdEJRVGRETEVWQlFXOUVMR1ZCUVdVc1RVRkJaaXhEUVVGelFpeERRVUYwUWl4RFFVRndSQ3hEUVVGYUxFTkJRVklzUTBGRVJ6dFRRVUZNTzA5QlJrWTdTMEZrUmpzN1FVRnpRa0VzVjBGQlR5eExRVUZRTEVOQmVrSkhPMGRCT1VKTU8wTkJTa1k3TzBGQkswUkJMRk5CUVZNc1NVRkJWQ3hEUVVGakxFMUJRV1FzUlVGQmMwSXNaVUZCZEVJc1JVRkJkVU1zVTBGQmRrTXNSVUZCYTBRc1lVRkJiRVFzUlVGQmFVVXNZMEZCYWtVc1JVRkJaMFk3UVVGRE9VVXNUVUZCU1N4VFFVRlRMRWxCUVZRc1EwRkVNRVU3TzBGQlJ6bEZMRTFCUVVjN1FVRkRSQ3hoUVVGVExGRkJRVlFzUTBGRVF6dEhRVUZJTEVOQlJVTXNUMEZCVFN4RFFVRk9MRVZCUVZFN1FVRkRVQ3hSUVVGSkxGbEJRVmtzU1VGQldpeERRVVJIT3p0QlFVZFFMRkZCUVVjc1pVRkJTQ3hGUVVGdFFqdEJRVU5xUWl4VlFVRkhPMEZCUTBRc2IwSkJRVmtzWjBKQlFXZENMRU5CUVdoQ0xFTkJRVm9zUTBGRVF6dEJRVVZFTEdWQlFVOHNVMEZCVUN4RFFVWkRPMDlCUVVnc1EwRkhReXhQUVVGTkxFVkJRVTRzUlVGQlV6dEJRVU5TTEZsQlFVY3NZMEZCWXl4VFFVRlRMRlZCUVZRc1JVRkJiMEk3UVVGRGJrTXNaMEpCUVUwc1JVRkJUaXhEUVVSdFF6dFRRVUZ5UXp0UFFVUkVPMHRCU2tnN08wRkJWMEVzVVVGQlJ5eFRRVUZJTEVWQlFXRTdRVUZEV0N4VlFVRkhPMEZCUTBRc2IwSkJRVmtzVlVGQlZTeERRVUZXTEVOQlFWb3NRMEZFUXp0QlFVVkVMR1ZCUVU4c1UwRkJVQ3hEUVVaRE8wOUJRVWdzUTBGSFF5eFBRVUZOTEVWQlFVNHNSVUZCVXp0QlFVTlNMRmxCUVVjc1kwRkJZeXhUUVVGVExGVkJRVlFzUlVGQmIwSTdRVUZEYmtNc1owSkJRVTBzUlVGQlRpeERRVVJ0UXp0VFFVRnlRenRQUVVSRU8wdEJTa2c3TzBGQlYwRXNWVUZCVFN4RFFVRk9MRU5CZWtKUE8wZEJRVklzVTBFeVFrODdRVUZEVGl4UlFVRkhMR05CUVVnc1JVRkJhMEk3UVVGRGFFSXNkVUpCUkdkQ08wdEJRV3hDTzBkQk9VSkdPenRCUVcxRFFTeE5RVUZITEdGQlFVZ3NSVUZCYVVJN1FVRkRaaXhSUVVGSE8wRkJRMFFzWVVGQlR5eGpRVUZqTEUxQlFXUXNRMEZCVUN4RFFVUkRPMHRCUVVnc1EwRkZReXhQUVVGTkxFVkJRVTRzUlVGQlV6dEJRVU5PTEZWQlFVY3NZMEZCWXl4VFFVRlRMRlZCUVZRc1JVRkJiMEk3UVVGRGJrTXNZMEZCVFN4SlFVRkpMRXRCUVVvc1EwRkJWU3gzUWtGQlZpeERRVUZPTEVOQlJHMURPMDlCUVhKRE96dEJRVWxHTEZsQlFVMHNSVUZCVGl4RFFVeFJPMHRCUVZRN1IwRklTQ3hOUVZWTE8wRkJRMGdzVjBGQlR5eE5RVUZRTEVOQlJFYzdSMEZXVER0RFFYUkRSanM3UVVGeFJFRXNVMEZCVXl4TFFVRlVMRU5CUVdVc1IwRkJSeXhKUVVGSUxFVkJRVkU3UVVGRGNrSXNUVUZCU1N4aFFVRmhMRVZCUVdJc1EwRkVhVUk3TzBGQlIzSkNMRTlCUVVrc1NVRkJTU3hKUVVGSkxFTkJRVW9zUlVGQlR5eEpRVUZKTEV0QlFVc3NUVUZCVEN4RlFVRmhMRWRCUVdoRExFVkJRVzlETzBGQlEyeERMRkZCUVVjc1RVRkJUU3hMUVVGTExFMUJRVXdzUjBGQll5eERRVUZrTEVWQlFXZENPMEZCUTNaQ0xHRkJRVThzUzBGQlN5eERRVUZNTEVWQlFWRXNTMEZCVWl4RFFVRmpMRWxCUVdRc1JVRkJiMElzVlVGQmNFSXNRMEZCVUN4RFFVUjFRanRMUVVGNlFpeE5RVVZMTzBGQlEwZ3NWVUZCU1N4RFFVRkRMRTlCUVVRc1JVRkJWU3hKUVVGV0xFbEJRV3RDTEV0QlFVc3NRMEZCVEN4RFFVRnNRaXhEUVVSRU96dEJRVWRJTEZWQlFVa3NVMEZCVXl4TFFVRkxMRXRCUVV3c1EwRkJWeXhKUVVGWUxFVkJRV2xDTEZWQlFXcENMRU5CUVZRc1EwRklSRHM3UVVGTFNDeFZRVUZKTEdkQ1FVRm5RaXhUUVVGVExHTkJRVlFzUTBGQmQwSXNUMEZCZUVJc1JVRkJhVU1zVFVGQmFrTXNRMEZCYUVJc1EwRk1SRHM3UVVGUFNDeFZRVUZITEdsQ1FVRnBRaXhKUVVGcVFpeEZRVUZ6UWp0QlFVTjJRaXhsUVVGUExFMUJRVkFzUTBGRWRVSTdUMEZCZWtJc1RVRkZTenRCUVVOSUxIRkNRVUZoTEZkQlFWY3NUVUZCV0N4RFFVRnJRaXhoUVVGc1FpeERRVUZpTEVOQlJFYzdUMEZHVER0TFFWUkdPMGRCUkVZN08wRkJhMEpCTEZOQlFVOHNTVUZCVUN4RFFYSkNjVUk3UTBGQmRrSTdPMEZCZDBKQkxHVkJRV1U3UVVGRFlpeFBRVVJoTzBGQlJXSXNUVUZHWVR0QlFVZGlMRmxCU0dFN1FVRkpZaXhOUVVwaE8wRkJTMklzVFVGTVlUdEJRVTFpTEU5QlRtRTdRMEZCWmlJc0ltWnBiR1VpT2lKc2FXSXZZMjl5WlM5emNHVmphV0ZzWDJadmNtMXpMbXB6SWl3aWMyOTFjbU5sYzBOdmJuUmxiblFpT2xzaWFXMXdiM0owSUVKcGRGTjBjbWx1WnlCbWNtOXRJQ2N1TDJKcGRGOXpkSEpwYm1jbk8xeHVhVzF3YjNKMElGQmhkSFJsY201eklHWnliMjBnSnk0dmNHRjBkR1Z5Ym5Nbk8xeHVhVzF3YjNKMElIc2dWSFZ3YkdVZ2ZTQm1jbTl0SUNjdUwzQnlhVzFwZEdsMlpYTW5PMXh1WEc1bWRXNWpkR2x2YmlCZlkyRnpaU2hqYjI1a2FYUnBiMjRzSUdOc1lYVnpaWE1wZTF4dUlDQnlaWFIxY200Z1VHRjBkR1Z5Ym5NdVpHVm1iV0YwWTJnb0xpNHVZMnhoZFhObGN5a29ZMjl1WkdsMGFXOXVLVHRjYm4xY2JseHVablZ1WTNScGIyNGdZMjl1WkNoamJHRjFjMlZ6S1h0Y2JpQWdabTl5S0d4bGRDQmpiR0YxYzJVZ2IyWWdZMnhoZFhObGN5bDdYRzRnSUNBZ2FXWW9ZMnhoZFhObFd6QmRLWHRjYmlBZ0lDQWdJSEpsZEhWeWJpQmpiR0YxYzJWYk1WMG9LVHRjYmlBZ0lDQjlYRzRnSUgxY2JseHVJQ0IwYUhKdmR5QnVaWGNnUlhKeWIzSW9LVHRjYm4xY2JseHVablZ1WTNScGIyNGdiV0Z3WDNWd1pHRjBaU2h0WVhBc0lIWmhiSFZsY3lsN1hHNGdJSEpsZEhWeWJpQlBZbXBsWTNRdVpuSmxaWHBsS0Z4dUlDQWdJRTlpYW1WamRDNWhjM05wWjI0b1hHNGdJQ0FnSUNCUFltcGxZM1F1WTNKbFlYUmxLRzFoY0M1amIyNXpkSEoxWTNSdmNpNXdjbTkwYjNSNWNHVXBMQ0J0WVhBc0lIWmhiSFZsYzF4dUlDQWdJQ2xjYmlBZ0tUdGNibjFjYmx4dVpuVnVZM1JwYjI0Z1gyWnZjaWhqYjJ4c1pXTjBhVzl1Y3l3Z1puVnVMQ0JtYVd4MFpYSWdQU0FvS1NBOVBpQjBjblZsTENCcGJuUnZJRDBnVzEwc0lIQnlaWFpwYjNWelZtRnNkV1Z6SUQwZ1cxMHBlMXh1SUNCc1pYUWdjR0YwZEdWeWJpQTlJR052Ykd4bFkzUnBiMjV6V3pCZFd6QmRPMXh1SUNCc1pYUWdZMjlzYkdWamRHbHZiaUE5SUdOdmJHeGxZM1JwYjI1eld6QmRXekZkTzF4dVhHNGdJR2xtS0dOdmJHeGxZM1JwYjI1ekxteGxibWQwYUNBOVBUMGdNU2w3WEc0Z0lDQWdhV1lvWTI5c2JHVmpkR2x2YmlCcGJuTjBZVzVqWlc5bUlFSnBkRk4wY21sdVp5bDdYRzRnSUNBZ0lDQnNaWFFnWW5OVGJHbGpaU0E5SUdOdmJHeGxZM1JwYjI0dWMyeHBZMlVvTUN3Z2NHRjBkR1Z5Ymk1aWVYUmxYM05wZW1Vb0tTazdYRzRnSUNBZ0lDQnNaWFFnYVNBOUlERTdYRzVjYmlBZ0lDQWdJSGRvYVd4bEtHSnpVMnhwWTJVdVlubDBaVjl6YVhwbElEMDlJSEJoZEhSbGNtNHVZbmwwWlY5emFYcGxLQ2twZTF4dUlDQWdJQ0FnSUNCc1pYUWdjaUE5SUZCaGRIUmxjbTV6TG0xaGRHTm9YMjV2WDNSb2NtOTNLSEJoZEhSbGNtNHNJR0p6VTJ4cFkyVXBPMXh1SUNBZ0lDQWdJQ0JzWlhRZ1lYSm5jeUE5SUhCeVpYWnBiM1Z6Vm1Gc2RXVnpMbU52Ym1OaGRDaHlLVHRjYmx4dUlDQWdJQ0FnSUNCcFppaHlJQ1ltSUdacGJIUmxjaTVoY0hCc2VTaDBhR2x6TENCaGNtZHpLU2w3WEc0Z0lDQWdJQ0FnSUNBZ2FXNTBieUE5SUdsdWRHOHVZMjl1WTJGMEtGdG1kVzR1WVhCd2JIa29kR2hwY3l3Z1lYSm5jeWxkS1R0Y2JpQWdJQ0FnSUNBZ2ZWeHVYRzRnSUNBZ0lDQWdJR0p6VTJ4cFkyVWdQU0JqYjJ4c1pXTjBhVzl1TG5Oc2FXTmxLSEJoZEhSbGNtNHVZbmwwWlY5emFYcGxLQ2tnS2lCcExDQndZWFIwWlhKdUxtSjVkR1ZmYzJsNlpTZ3BJQ29nS0drZ0t5QXhLU2s3WEc0Z0lDQWdJQ0FnSUdrckt6dGNiaUFnSUNBZ0lIMWNibHh1SUNBZ0lDQWdjbVYwZFhKdUlHbHVkRzg3WEc0Z0lDQWdmV1ZzYzJWN1hHNGdJQ0FnSUNCbWIzSW9iR1YwSUdWc1pXMGdiMllnWTI5c2JHVmpkR2x2YmlsN1hHNGdJQ0FnSUNBZ0lHeGxkQ0J5SUQwZ1VHRjBkR1Z5Ym5NdWJXRjBZMmhmYm05ZmRHaHliM2NvY0dGMGRHVnliaXdnWld4bGJTazdYRzRnSUNBZ0lDQWdJR3hsZENCaGNtZHpJRDBnY0hKbGRtbHZkWE5XWVd4MVpYTXVZMjl1WTJGMEtISXBPMXh1WEc0Z0lDQWdJQ0FnSUdsbUtISWdKaVlnWm1sc2RHVnlMbUZ3Y0d4NUtIUm9hWE1zSUdGeVozTXBLWHRjYmlBZ0lDQWdJQ0FnSUNCcGJuUnZJRDBnYVc1MGJ5NWpiMjVqWVhRb1cyWjFiaTVoY0hCc2VTaDBhR2x6TENCaGNtZHpLVjBwTzF4dUlDQWdJQ0FnSUNCOVhHNGdJQ0FnSUNCOVhHNWNiaUFnSUNBZ0lISmxkSFZ5YmlCcGJuUnZPMXh1SUNBZ0lIMWNiaUFnZldWc2MyVjdYRzRnSUNBZ2JHVjBJRjlwYm5SdklEMGdXMTA3WEc1Y2JpQWdJQ0JwWmloamIyeHNaV04wYVc5dUlHbHVjM1JoYm1ObGIyWWdRbWwwVTNSeWFXNW5LWHRjYmlBZ0lDQWdJR3hsZENCaWMxTnNhV05sSUQwZ1kyOXNiR1ZqZEdsdmJpNXpiR2xqWlNnd0xDQndZWFIwWlhKdUxtSjVkR1ZmYzJsNlpTZ3BLVHRjYmlBZ0lDQWdJR3hsZENCcElEMGdNVHRjYmx4dUlDQWdJQ0FnZDJocGJHVW9Zbk5UYkdsalpTNWllWFJsWDNOcGVtVWdQVDBnY0dGMGRHVnliaTVpZVhSbFgzTnBlbVVvS1NsN1hHNGdJQ0FnSUNBZ0lHeGxkQ0J5SUQwZ1VHRjBkR1Z5Ym5NdWJXRjBZMmhmYm05ZmRHaHliM2NvY0dGMGRHVnliaXdnWW5OVGJHbGpaU2s3WEc0Z0lDQWdJQ0FnSUdsbUtISXBlMXh1SUNBZ0lDQWdJQ0FnSUY5cGJuUnZJRDBnYVc1MGJ5NWpiMjVqWVhRb2RHaHBjeTVmWm05eUtHTnZiR3hsWTNScGIyNXpMbk5zYVdObEtERXBMQ0JtZFc0c0lHWnBiSFJsY2l3Z1gybHVkRzhzSUhCeVpYWnBiM1Z6Vm1Gc2RXVnpMbU52Ym1OaGRDaHlLU2twTzF4dUlDQWdJQ0FnSUNCOVhHNWNiaUFnSUNBZ0lDQWdZbk5UYkdsalpTQTlJR052Ykd4bFkzUnBiMjR1YzJ4cFkyVW9jR0YwZEdWeWJpNWllWFJsWDNOcGVtVW9LU0FxSUdrc0lIQmhkSFJsY200dVlubDBaVjl6YVhwbEtDa2dLaUFvYVNBcklERXBLVHRjYmlBZ0lDQWdJQ0FnYVNzck8xeHVJQ0FnSUNBZ2ZWeHVJQ0FnSUgxbGJITmxlMXh1SUNBZ0lDQWdabTl5S0d4bGRDQmxiR1Z0SUc5bUlHTnZiR3hsWTNScGIyNHBlMXh1SUNBZ0lDQWdJQ0JzWlhRZ2NpQTlJRkJoZEhSbGNtNXpMbTFoZEdOb1gyNXZYM1JvY205M0tIQmhkSFJsY200c0lHVnNaVzBwTzF4dUlDQWdJQ0FnSUNCcFppaHlLWHRjYmlBZ0lDQWdJQ0FnSUNCZmFXNTBieUE5SUdsdWRHOHVZMjl1WTJGMEtIUm9hWE11WDJadmNpaGpiMnhzWldOMGFXOXVjeTV6YkdsalpTZ3hLU3dnWm5WdUxDQm1hV3gwWlhJc0lGOXBiblJ2TENCd2NtVjJhVzkxYzFaaGJIVmxjeTVqYjI1allYUW9jaWtwS1R0Y2JpQWdJQ0FnSUNBZ2ZWeHVJQ0FnSUNBZ2ZTQmNiaUFnSUNCOVhHNWNiaUFnSUNCeVpYUjFjbTRnWDJsdWRHODdYRzRnSUgxY2JuMWNibHh1Wm5WdVkzUnBiMjRnWDNSeWVTaGtiMTltZFc0c0lISmxjMk4xWlY5bWRXNWpkR2x2Yml3Z1kyRjBZMmhmWm5WdUxDQmxiSE5sWDJaMWJtTjBhVzl1TENCaFpuUmxjbDltZFc1amRHbHZiaWw3WEc0Z0lHeGxkQ0J5WlhOMWJIUWdQU0J1ZFd4c08xeHVYRzRnSUhSeWVYdGNiaUFnSUNCeVpYTjFiSFFnUFNCa2IxOW1kVzRvS1R0Y2JpQWdmV05oZEdOb0tHVXBlMXh1SUNBZ0lHeGxkQ0JsZUY5eVpYTjFiSFFnUFNCdWRXeHNPMXh1WEc0Z0lDQWdhV1lvY21WelkzVmxYMloxYm1OMGFXOXVLWHRjYmlBZ0lDQWdJSFJ5ZVh0Y2JpQWdJQ0FnSUNBZ1pYaGZjbVZ6ZFd4MElEMGdjbVZ6WTNWbFgyWjFibU4wYVc5dUtHVXBPMXh1SUNBZ0lDQWdJQ0J5WlhSMWNtNGdaWGhmY21WemRXeDBPMXh1SUNBZ0lDQWdmV05oZEdOb0tHVjRLWHRjYmlBZ0lDQWdJQ0FnYVdZb1pYZ2dhVzV6ZEdGdVkyVnZaaUJRWVhSMFpYSnVjeTVOWVhSamFFVnljbTl5S1h0Y2JpQWdJQ0FnSUNBZ0lDQjBhSEp2ZHlCbGVEdGNiaUFnSUNBZ0lDQWdmVnh1SUNBZ0lDQWdmVnh1SUNBZ0lIMWNibHh1SUNBZ0lHbG1LR05oZEdOb1gyWjFiaWw3WEc0Z0lDQWdJQ0IwY25sN1hHNGdJQ0FnSUNBZ0lHVjRYM0psYzNWc2RDQTlJR05oZEdOb1gyWjFiaWhsS1R0Y2JpQWdJQ0FnSUNBZ2NtVjBkWEp1SUdWNFgzSmxjM1ZzZER0Y2JpQWdJQ0FnSUgxallYUmphQ2hsZUNsN1hHNGdJQ0FnSUNBZ0lHbG1LR1Y0SUdsdWMzUmhibU5sYjJZZ1VHRjBkR1Z5Ym5NdVRXRjBZMmhGY25KdmNpbDdYRzRnSUNBZ0lDQWdJQ0FnZEdoeWIzY2daWGc3WEc0Z0lDQWdJQ0FnSUgxY2JpQWdJQ0FnSUgxY2JpQWdJQ0I5WEc1Y2JpQWdJQ0IwYUhKdmR5QmxPMXh1WEc0Z0lIMW1hVzVoYkd4NWUxeHVJQ0FnSUdsbUtHRm1kR1Z5WDJaMWJtTjBhVzl1S1h0Y2JpQWdJQ0FnSUdGbWRHVnlYMloxYm1OMGFXOXVLQ2s3WEc0Z0lDQWdmVnh1SUNCOVhHNWNiaUFnYVdZb1pXeHpaVjltZFc1amRHbHZiaWw3WEc0Z0lDQWdkSEo1ZTF4dUlDQWdJQ0FnY21WMGRYSnVJR1ZzYzJWZlpuVnVZM1JwYjI0b2NtVnpkV3gwS1R0Y2JpQWdJQ0I5WTJGMFkyZ29aWGdwZTF4dUlDQWdJQ0FnSUNCcFppaGxlQ0JwYm5OMFlXNWpaVzltSUZCaGRIUmxjbTV6TGsxaGRHTm9SWEp5YjNJcGUxeHVJQ0FnSUNBZ0lDQWdJSFJvY205M0lHNWxkeUJGY25KdmNpaGNJazV2SUUxaGRHTm9JRVp2ZFc1a0lHbHVJRVZzYzJWY0lpazdYRzRnSUNBZ0lDQWdJSDFjYmx4dUlDQWdJQ0FnZEdoeWIzY2daWGc3WEc0Z0lDQWdmVnh1SUNCOVpXeHpaWHRjYmlBZ0lDQnlaWFIxY200Z2NtVnpkV3gwTzF4dUlDQjlYRzU5WEc1Y2JtWjFibU4wYVc5dUlGOTNhWFJvS0M0dUxtRnlaM01wZTF4dUlDQnNaWFFnWVhKbmMxUnZVR0Z6Y3lBOUlGdGRPMXh1WEc0Z0lHWnZjaWhzWlhRZ2FTQTlJREE3SUdrZ1BDQmhjbWR6TG14bGJtZDBhRHNnYVNzcktYdGNiaUFnSUNCcFppaHBJRDA5UFNCaGNtZHpMbXhsYm1kMGFDQXRJREVwZTF4dUlDQWdJQ0FnY21WMGRYSnVJR0Z5WjNOYmFWMHVZWEJ3Ykhrb2JuVnNiQ3dnWVhKbmMxUnZVR0Z6Y3lrN1hHNGdJQ0FnZldWc2MyVjdYRzRnSUNBZ0lDQnNaWFFnVzNCaGRIUmxjbTRzSUdaMWJtTmRJRDBnWVhKbmMxdHBYVHRjYmx4dUlDQWdJQ0FnYkdWMElISmxjM1ZzZENBOUlHWjFibU11WVhCd2JIa29iblZzYkN3Z1lYSm5jMVJ2VUdGemN5azdYRzVjYmlBZ0lDQWdJR3hsZENCd1lYUjBaWEp1VW1WemRXeDBJRDBnVUdGMGRHVnlibk11YldGMFkyaGZibTlmZEdoeWIzY29jR0YwZEdWeWJpd2djbVZ6ZFd4MEtUdGNibHh1SUNBZ0lDQWdhV1lvY0dGMGRHVnlibEpsYzNWc2RDQTlQU0J1ZFd4c0tYdGNiaUFnSUNBZ0lDQWdjbVYwZFhKdUlISmxjM1ZzZER0Y2JpQWdJQ0FnSUgxbGJITmxlMXh1SUNBZ0lDQWdJQ0JoY21kelZHOVFZWE56SUQwZ1lYSm5jMVJ2VUdGemN5NWpiMjVqWVhRb2NHRjBkR1Z5YmxKbGMzVnNkQ2s3WEc0Z0lDQWdJQ0I5WEc0Z0lDQWdmVnh1SUNCOVhHNWNiaUFnY21WMGRYSnVJRzUxYkd3N1hHNTlYRzVjYm1WNGNHOXlkQ0JrWldaaGRXeDBJSHRjYmlBZ1gyTmhjMlVzWEc0Z0lHTnZibVFzWEc0Z0lHMWhjRjkxY0dSaGRHVXNYRzRnSUY5bWIzSXNYRzRnSUY5MGNua3NYRzRnSUY5M2FYUm9YRzU5TzF4dUlsMHNJbk52ZFhKalpWSnZiM1FpT2lJdmMyOTFjbU5sTHlKOVxuIiwiaW1wb3J0IFByb2Nlc3NTeXN0ZW0gZnJvbSAnLi9jb3JlL3Byb2Nlc3Nlcy9wcm9jZXNzX3N5c3RlbSc7XG5pbXBvcnQgeyBUdXBsZSwgUElELCBJbnRlZ2VyLCBGbG9hdCB9IGZyb20gJy4vY29yZS9wcmltaXRpdmVzJztcbmltcG9ydCBCaXRTdHJpbmcgZnJvbSAnLi9jb3JlL2JpdF9zdHJpbmcnO1xuaW1wb3J0IFBhdHRlcm5zIGZyb20gJy4vY29yZS9wYXR0ZXJucyc7XG5pbXBvcnQgRnVuY3Rpb25zIGZyb20gJy4vY29yZS9mdW5jdGlvbnMnO1xuaW1wb3J0IFNwZWNpYWxGb3JtcyBmcm9tICcuL2NvcmUvc3BlY2lhbF9mb3Jtcyc7XG5cbkZ1bmN0aW9ucy5nZXRfZ2xvYmFsKCkucHJvY2Vzc2VzID0gRnVuY3Rpb25zLmdldF9nbG9iYWwoKS5wcm9jZXNzZXMgfHwgbmV3IFByb2Nlc3NTeXN0ZW0oKTtcblxuZXhwb3J0IGRlZmF1bHQge1xuICBQcm9jZXNzU3lzdGVtLFxuICBUdXBsZSxcbiAgUElELFxuICBCaXRTdHJpbmcsXG4gIFBhdHRlcm5zLFxuICBJbnRlZ2VyLFxuICBGbG9hdCxcbiAgRnVuY3Rpb25zLFxuICBTcGVjaWFsRm9ybXNcbn07XG4vLyMgc291cmNlTWFwcGluZ1VSTD1kYXRhOmFwcGxpY2F0aW9uL2pzb247YmFzZTY0LGV5SjJaWEp6YVc5dUlqb3pMQ0p6YjNWeVkyVnpJanBiSW14cFlpOWpiM0psTG1weklsMHNJbTVoYldWeklqcGJYU3dpYldGd2NHbHVaM01pT2lKQlFVRkJMRTlCUVU4c1lVRkJVQ3hOUVVFd1FpeHBRMEZCTVVJN1FVRkRRU3hUUVVGVExFdEJRVlFzUlVGQlowSXNSMEZCYUVJc1JVRkJjVUlzVDBGQmNrSXNSVUZCT0VJc1MwRkJPVUlzVVVGQk1rTXNiVUpCUVRORE8wRkJRMEVzVDBGQlR5eFRRVUZRTEUxQlFYTkNMRzFDUVVGMFFqdEJRVU5CTEU5QlFVOHNVVUZCVUN4TlFVRnhRaXhwUWtGQmNrSTdRVUZEUVN4UFFVRlBMRk5CUVZBc1RVRkJjMElzYTBKQlFYUkNPMEZCUTBFc1QwRkJUeXhaUVVGUUxFMUJRWGxDTEhOQ1FVRjZRanM3UVVGRlFTeFZRVUZWTEZWQlFWWXNSMEZCZFVJc1UwRkJka0lzUjBGQmJVTXNWVUZCVlN4VlFVRldMRWRCUVhWQ0xGTkJRWFpDTEVsQlFXOURMRWxCUVVrc1lVRkJTaXhGUVVGd1F6czdRVUZGYmtNc1pVRkJaVHRCUVVOaUxHVkJSR0U3UVVGRllpeFBRVVpoTzBGQlIySXNTMEZJWVR0QlFVbGlMRmRCU21FN1FVRkxZaXhWUVV4aE8wRkJUV0lzVTBGT1lUdEJRVTlpTEU5QlVHRTdRVUZSWWl4WFFWSmhPMEZCVTJJc1kwRlVZVHREUVVGbUlpd2labWxzWlNJNklteHBZaTlqYjNKbExtcHpJaXdpYzI5MWNtTmxjME52Ym5SbGJuUWlPbHNpYVcxd2IzSjBJRkJ5YjJObGMzTlRlWE4wWlcwZ1puSnZiU0FuTGk5amIzSmxMM0J5YjJObGMzTmxjeTl3Y205alpYTnpYM041YzNSbGJTYzdYRzVwYlhCdmNuUWdleUJVZFhCc1pTd2dVRWxFTENCSmJuUmxaMlZ5TENCR2JHOWhkQ0I5SUdaeWIyMGdKeTR2WTI5eVpTOXdjbWx0YVhScGRtVnpKenRjYm1sdGNHOXlkQ0JDYVhSVGRISnBibWNnWm5KdmJTQW5MaTlqYjNKbEwySnBkRjl6ZEhKcGJtY25PMXh1YVcxd2IzSjBJRkJoZEhSbGNtNXpJR1p5YjIwZ0p5NHZZMjl5WlM5d1lYUjBaWEp1Y3ljN1hHNXBiWEJ2Y25RZ1JuVnVZM1JwYjI1eklHWnliMjBnSnk0dlkyOXlaUzltZFc1amRHbHZibk1uTzF4dWFXMXdiM0owSUZOd1pXTnBZV3hHYjNKdGN5Qm1jbTl0SUNjdUwyTnZjbVV2YzNCbFkybGhiRjltYjNKdGN5YzdYRzVjYmtaMWJtTjBhVzl1Y3k1blpYUmZaMnh2WW1Gc0tDa3VjSEp2WTJWemMyVnpJRDBnUm5WdVkzUnBiMjV6TG1kbGRGOW5iRzlpWVd3b0tTNXdjbTlqWlhOelpYTWdmSHdnYm1WM0lGQnliMk5sYzNOVGVYTjBaVzBvS1R0Y2JseHVaWGh3YjNKMElHUmxabUYxYkhRZ2UxeHVJQ0JRY205alpYTnpVM2x6ZEdWdExGeHVJQ0JVZFhCc1pTeGNiaUFnVUVsRUxGeHVJQ0JDYVhSVGRISnBibWNzWEc0Z0lGQmhkSFJsY201ekxGeHVJQ0JKYm5SbFoyVnlMRnh1SUNCR2JHOWhkQ3hjYmlBZ1JuVnVZM1JwYjI1ekxGeHVJQ0JUY0dWamFXRnNSbTl5YlhOY2JuMWNiaUpkTENKemIzVnlZMlZTYjI5MElqb2lMM052ZFhKalpTOGlmUT09XG4iLCJpbXBvcnQgQ29yZSBmcm9tICcuL2NvcmUnO1xuXG5sZXQgRW51bSA9IHtcblxuICBhbGxfX3FtYXJrX186IGZ1bmN0aW9uIChjb2xsZWN0aW9uLCBmdW4gPSB4ID0+IHgpIHtcbiAgICBmb3IgKGxldCBlbGVtIG9mIGNvbGxlY3Rpb24pIHtcbiAgICAgIGlmICghZnVuKGVsZW0pKSB7XG4gICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICByZXR1cm4gdHJ1ZTtcbiAgfSxcblxuICBhbnlfX3FtYXJrX186IGZ1bmN0aW9uIChjb2xsZWN0aW9uLCBmdW4gPSB4ID0+IHgpIHtcbiAgICBmb3IgKGxldCBlbGVtIG9mIGNvbGxlY3Rpb24pIHtcbiAgICAgIGlmIChmdW4oZWxlbSkpIHtcbiAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICB9XG4gICAgfVxuXG4gICAgcmV0dXJuIGZhbHNlO1xuICB9LFxuXG4gIGF0OiBmdW5jdGlvbiAoY29sbGVjdGlvbiwgbiwgdGhlX2RlZmF1bHQgPSBudWxsKSB7XG4gICAgaWYgKG4gPiB0aGlzLmNvdW50KGNvbGxlY3Rpb24pIHx8IG4gPCAwKSB7XG4gICAgICByZXR1cm4gdGhlX2RlZmF1bHQ7XG4gICAgfVxuXG4gICAgcmV0dXJuIGNvbGxlY3Rpb25bbl07XG4gIH0sXG5cbiAgY29uY2F0OiBmdW5jdGlvbiAoLi4uZW51bWFibGVzKSB7XG4gICAgcmV0dXJuIGVudW1hYmxlc1swXS5jb25jYXQoZW51bWFibGVzWzFdKTtcbiAgfSxcblxuICBjb3VudDogZnVuY3Rpb24gKGNvbGxlY3Rpb24sIGZ1biA9IG51bGwpIHtcbiAgICBpZiAoZnVuID09IG51bGwpIHtcbiAgICAgIHJldHVybiBjb2xsZWN0aW9uLmxlbmd0aDtcbiAgICB9IGVsc2Uge1xuICAgICAgcmV0dXJuIGNvbGxlY3Rpb24uZmlsdGVyKGZ1bikubGVuZ3RoO1xuICAgIH1cbiAgfSxcblxuICBkcm9wOiBmdW5jdGlvbiAoY29sbGVjdGlvbiwgY291bnQpIHtcbiAgICByZXR1cm4gY29sbGVjdGlvbi5zbGljZShjb3VudCk7XG4gIH0sXG5cbiAgZHJvcF93aGlsZTogZnVuY3Rpb24gKGNvbGxlY3Rpb24sIGZ1bikge1xuICAgIGxldCBjb3VudCA9IDA7XG5cbiAgICBmb3IgKGxldCBlbGVtIG9mIGNvbGxlY3Rpb24pIHtcbiAgICAgIGlmIChmdW4oZWxlbSkpIHtcbiAgICAgICAgY291bnQgPSBjb3VudCArIDE7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBicmVhaztcbiAgICAgIH1cbiAgICB9XG5cbiAgICByZXR1cm4gY29sbGVjdGlvbi5zbGljZShjb3VudCk7XG4gIH0sXG5cbiAgZWFjaDogZnVuY3Rpb24gKGNvbGxlY3Rpb24sIGZ1bikge1xuICAgIGZvciAobGV0IGVsZW0gb2YgY29sbGVjdGlvbikge1xuICAgICAgZnVuKGVsZW0pO1xuICAgIH1cbiAgfSxcblxuICBlbXB0eV9fcW1hcmtfXzogZnVuY3Rpb24gKGNvbGxlY3Rpb24pIHtcbiAgICByZXR1cm4gY29sbGVjdGlvbi5sZW5ndGggPT09IDA7XG4gIH0sXG5cbiAgZmV0Y2g6IGZ1bmN0aW9uIChjb2xsZWN0aW9uLCBuKSB7XG4gICAgaWYgKEFycmF5LmlzQXJyYXkoY29sbGVjdGlvbikpIHtcbiAgICAgIGlmIChuIDwgdGhpcy5jb3VudChjb2xsZWN0aW9uKSAmJiBuID49IDApIHtcbiAgICAgICAgcmV0dXJuIG5ldyBDb3JlLlR1cGxlKFN5bWJvbC5mb3IoXCJva1wiKSwgY29sbGVjdGlvbltuXSk7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICByZXR1cm4gU3ltYm9sLmZvcihcImVycm9yXCIpO1xuICAgICAgfVxuICAgIH1cblxuICAgIHRocm93IG5ldyBFcnJvcihcImNvbGxlY3Rpb24gaXMgbm90IGFuIEVudW1lcmFibGVcIik7XG4gIH0sXG5cbiAgZmV0Y2hfX2VtYXJrX186IGZ1bmN0aW9uIChjb2xsZWN0aW9uLCBuKSB7XG4gICAgaWYgKEFycmF5LmlzQXJyYXkoY29sbGVjdGlvbikpIHtcbiAgICAgIGlmIChuIDwgdGhpcy5jb3VudChjb2xsZWN0aW9uKSAmJiBuID49IDApIHtcbiAgICAgICAgcmV0dXJuIGNvbGxlY3Rpb25bbl07XG4gICAgICB9IGVsc2Uge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoXCJvdXQgb2YgYm91bmRzIGVycm9yXCIpO1xuICAgICAgfVxuICAgIH1cblxuICAgIHRocm93IG5ldyBFcnJvcihcImNvbGxlY3Rpb24gaXMgbm90IGFuIEVudW1lcmFibGVcIik7XG4gIH0sXG5cbiAgZmlsdGVyOiBmdW5jdGlvbiAoY29sbGVjdGlvbiwgZnVuKSB7XG4gICAgbGV0IHJlc3VsdCA9IFtdO1xuXG4gICAgZm9yIChsZXQgZWxlbSBvZiBjb2xsZWN0aW9uKSB7XG4gICAgICBpZiAoZnVuKGVsZW0pKSB7XG4gICAgICAgIHJlc3VsdC5wdXNoKGVsZW0pO1xuICAgICAgfVxuICAgIH1cblxuICAgIHJldHVybiByZXN1bHQ7XG4gIH0sXG5cbiAgZmlsdGVyX21hcDogZnVuY3Rpb24gKGNvbGxlY3Rpb24sIGZpbHRlciwgbWFwcGVyKSB7XG4gICAgcmV0dXJuIEVudW0ubWFwKEVudW0uZmlsdGVyKGNvbGxlY3Rpb24sIGZpbHRlciksIG1hcHBlcik7XG4gIH0sXG5cbiAgZmluZDogZnVuY3Rpb24gKGNvbGxlY3Rpb24sIGlmX25vbmUgPSBudWxsLCBmdW4pIHtcbiAgICBmb3IgKGxldCBlbGVtIG9mIGNvbGxlY3Rpb24pIHtcbiAgICAgIGlmIChmdW4oZWxlbSkpIHtcbiAgICAgICAgcmV0dXJuIGVsZW07XG4gICAgICB9XG4gICAgfVxuXG4gICAgcmV0dXJuIGlmX25vbmU7XG4gIH0sXG5cbiAgaW50bzogZnVuY3Rpb24gKGNvbGxlY3Rpb24sIGxpc3QpIHtcbiAgICByZXR1cm4gbGlzdC5jb25jYXQoY29sbGVjdGlvbik7XG4gIH0sXG5cbiAgbWFwOiBmdW5jdGlvbiAoY29sbGVjdGlvbiwgZnVuKSB7XG4gICAgbGV0IHJlc3VsdCA9IFtdO1xuXG4gICAgZm9yIChsZXQgZWxlbSBvZiBjb2xsZWN0aW9uKSB7XG4gICAgICByZXN1bHQucHVzaChmdW4oZWxlbSkpO1xuICAgIH1cblxuICAgIHJldHVybiByZXN1bHQ7XG4gIH0sXG5cbiAgbWFwX3JlZHVjZTogZnVuY3Rpb24gKGNvbGxlY3Rpb24sIGFjYywgZnVuKSB7XG4gICAgbGV0IG1hcHBlZCA9IE9iamVjdC5mcmVlemUoW10pO1xuICAgIGxldCB0aGVfYWNjID0gYWNjO1xuXG4gICAgZm9yICh2YXIgaSA9IDA7IGkgPCB0aGlzLmNvdW50KGNvbGxlY3Rpb24pOyBpKyspIHtcbiAgICAgIGxldCB0dXBsZSA9IGZ1bihjb2xsZWN0aW9uW2ldLCB0aGVfYWNjKTtcblxuICAgICAgdGhlX2FjYyA9IHR1cGxlLmdldCgxKTtcbiAgICAgIG1hcHBlZCA9IE9iamVjdC5mcmVlemUobWFwcGVkLmNvbmNhdChbdHVwbGUuZ2V0KDApXSkpO1xuICAgIH1cblxuICAgIHJldHVybiBuZXcgQ29yZS5UdXBsZShtYXBwZWQsIHRoZV9hY2MpO1xuICB9LFxuXG4gIG1lbWJlcl9fcW1hcmtfXzogZnVuY3Rpb24gKGNvbGxlY3Rpb24sIHZhbHVlKSB7XG4gICAgcmV0dXJuIGNvbGxlY3Rpb24uaW5jbHVkZXModmFsdWUpO1xuICB9LFxuXG4gIHJlZHVjZTogZnVuY3Rpb24gKGNvbGxlY3Rpb24sIGFjYywgZnVuKSB7XG4gICAgbGV0IHRoZV9hY2MgPSBhY2M7XG5cbiAgICBmb3IgKHZhciBpID0gMDsgaSA8IHRoaXMuY291bnQoY29sbGVjdGlvbik7IGkrKykge1xuICAgICAgbGV0IHR1cGxlID0gZnVuKGNvbGxlY3Rpb25baV0sIHRoZV9hY2MpO1xuXG4gICAgICB0aGVfYWNjID0gdHVwbGUuZ2V0KDEpO1xuICAgIH1cblxuICAgIHJldHVybiB0aGVfYWNjO1xuICB9LFxuXG4gIHRha2U6IGZ1bmN0aW9uIChjb2xsZWN0aW9uLCBjb3VudCkge1xuICAgIHJldHVybiBjb2xsZWN0aW9uLnNsaWNlKDAsIGNvdW50KTtcbiAgfSxcblxuICB0YWtlX2V2ZXJ5OiBmdW5jdGlvbiAoY29sbGVjdGlvbiwgbnRoKSB7XG4gICAgbGV0IHJlc3VsdCA9IFtdO1xuICAgIGxldCBpbmRleCA9IDA7XG5cbiAgICBmb3IgKGxldCBlbGVtIG9mIGNvbGxlY3Rpb24pIHtcbiAgICAgIGlmIChpbmRleCAlIG50aCA9PT0gMCkge1xuICAgICAgICByZXN1bHQucHVzaChlbGVtKTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICByZXR1cm4gT2JqZWN0LmZyZWV6ZShyZXN1bHQpO1xuICB9LFxuXG4gIHRha2Vfd2hpbGU6IGZ1bmN0aW9uIChjb2xsZWN0aW9uLCBmdW4pIHtcbiAgICBsZXQgY291bnQgPSAwO1xuXG4gICAgZm9yIChsZXQgZWxlbSBvZiBjb2xsZWN0aW9uKSB7XG4gICAgICBpZiAoZnVuKGVsZW0pKSB7XG4gICAgICAgIGNvdW50ID0gY291bnQgKyAxO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgYnJlYWs7XG4gICAgICB9XG4gICAgfVxuXG4gICAgcmV0dXJuIGNvbGxlY3Rpb24uc2xpY2UoMCwgY291bnQpO1xuICB9LFxuXG4gIHRvX2xpc3Q6IGZ1bmN0aW9uIChjb2xsZWN0aW9uKSB7XG4gICAgcmV0dXJuIGNvbGxlY3Rpb247XG4gIH1cbn07XG5cbmV4cG9ydCBkZWZhdWx0IEVudW07XG4vLyMgc291cmNlTWFwcGluZ1VSTD1kYXRhOmFwcGxpY2F0aW9uL2pzb247YmFzZTY0LGV5SjJaWEp6YVc5dUlqb3pMQ0p6YjNWeVkyVnpJanBiSW14cFlpOWxiblZ0TG1weklsMHNJbTVoYldWeklqcGJYU3dpYldGd2NHbHVaM01pT2lKQlFVRkJMRTlCUVU4c1NVRkJVQ3hOUVVGcFFpeFJRVUZxUWpzN1FVRkZRU3hKUVVGSkxFOUJRVTg3TzBGQlJWUXNaMEpCUVdNc1ZVRkJVeXhWUVVGVUxFVkJRWEZDTEUxQlFVMHNTMEZCVHl4RFFVRlFMRVZCUVZNN1FVRkRhRVFzVTBGQlNTeEpRVUZKTEVsQlFVb3NTVUZCV1N4VlFVRm9RaXhGUVVFeVFqdEJRVU42UWl4VlFVRkhMRU5CUVVNc1NVRkJTU3hKUVVGS0xFTkJRVVFzUlVGQlZ6dEJRVU5hTEdWQlFVOHNTMEZCVUN4RFFVUlpPMDlCUVdRN1MwRkVSanM3UVVGTlFTeFhRVUZQTEVsQlFWQXNRMEZRWjBRN1IwRkJjRU03TzBGQlZXUXNaMEpCUVdNc1ZVRkJVeXhWUVVGVUxFVkJRWEZDTEUxQlFVMHNTMEZCVHl4RFFVRlFMRVZCUVZNN1FVRkRhRVFzVTBGQlNTeEpRVUZKTEVsQlFVb3NTVUZCV1N4VlFVRm9RaXhGUVVFeVFqdEJRVU42UWl4VlFVRkhMRWxCUVVrc1NVRkJTaXhEUVVGSUxFVkJRV0U3UVVGRFdDeGxRVUZQTEVsQlFWQXNRMEZFVnp0UFFVRmlPMHRCUkVZN08wRkJUVUVzVjBGQlR5eExRVUZRTEVOQlVHZEVPMGRCUVhCRE96dEJRVlZrTEUxQlFVa3NWVUZCVXl4VlFVRlVMRVZCUVhGQ0xFTkJRWEpDTEVWQlFYZENMR05CUVdNc1NVRkJaQ3hGUVVGdFFqdEJRVU0zUXl4UlFVRkhMRWxCUVVrc1MwRkJTeXhMUVVGTUxFTkJRVmNzVlVGQldDeERRVUZLTEVsQlFUaENMRWxCUVVrc1EwRkJTaXhGUVVGTk8wRkJRM0pETEdGQlFVOHNWMEZCVUN4RFFVUnhRenRMUVVGMlF6czdRVUZKUVN4WFFVRlBMRmRCUVZjc1EwRkJXQ3hEUVVGUUxFTkJURFpETzBkQlFUTkRPenRCUVZGS0xGVkJRVkVzVlVGQlV5eEhRVUZITEZOQlFVZ3NSVUZCWVR0QlFVTTFRaXhYUVVGUExGVkJRVlVzUTBGQlZpeEZRVUZoTEUxQlFXSXNRMEZCYjBJc1ZVRkJWU3hEUVVGV0xFTkJRWEJDTEVOQlFWQXNRMEZFTkVJN1IwRkJkRUk3TzBGQlNWSXNVMEZCVHl4VlFVRlRMRlZCUVZRc1JVRkJjVUlzVFVGQlRTeEpRVUZPTEVWQlFWYzdRVUZEY2tNc1VVRkJSeXhQUVVGUExFbEJRVkFzUlVGQldUdEJRVU5pTEdGQlFVOHNWMEZCVnl4TlFVRllMRU5CUkUwN1MwRkJaaXhOUVVWUE8wRkJRMHdzWVVGQlR5eFhRVUZYTEUxQlFWZ3NRMEZCYTBJc1IwRkJiRUlzUlVGQmRVSXNUVUZCZGtJc1EwRkVSanRMUVVaUU8wZEJSRXM3TzBGQlVWQXNVVUZCVFN4VlFVRlRMRlZCUVZRc1JVRkJjVUlzUzBGQmNrSXNSVUZCTWtJN1FVRkRMMElzVjBGQlR5eFhRVUZYTEV0QlFWZ3NRMEZCYVVJc1MwRkJha0lzUTBGQlVDeERRVVFyUWp0SFFVRXpRanM3UVVGSlRpeGpRVUZaTEZWQlFWTXNWVUZCVkN4RlFVRnhRaXhIUVVGeVFpeEZRVUY1UWp0QlFVTnVReXhSUVVGSkxGRkJRVkVzUTBGQlVpeERRVVFyUWpzN1FVRkhia01zVTBGQlNTeEpRVUZKTEVsQlFVb3NTVUZCV1N4VlFVRm9RaXhGUVVFeVFqdEJRVU42UWl4VlFVRkhMRWxCUVVrc1NVRkJTaXhEUVVGSUxFVkJRV0U3UVVGRFdDeG5Ra0ZCVVN4UlFVRlJMRU5CUVZJc1EwRkVSenRQUVVGaUxFMUJSVXM3UVVGRFNDeGpRVVJITzA5QlJrdzdTMEZFUmpzN1FVRlJRU3hYUVVGUExGZEJRVmNzUzBGQldDeERRVUZwUWl4TFFVRnFRaXhEUVVGUUxFTkJXRzFETzBkQlFYcENPenRCUVdOYUxGRkJRVTBzVlVGQlV5eFZRVUZVTEVWQlFYRkNMRWRCUVhKQ0xFVkJRWGxDTzBGQlF6ZENMRk5CUVVrc1NVRkJTU3hKUVVGS0xFbEJRVmtzVlVGQmFFSXNSVUZCTWtJN1FVRkRla0lzVlVGQlNTeEpRVUZLTEVWQlJIbENPMHRCUVROQ08wZEJSRWs3TzBGQlRVNHNhMEpCUVdkQ0xGVkJRVk1zVlVGQlZDeEZRVUZ2UWp0QlFVTnNReXhYUVVGUExGZEJRVmNzVFVGQldDeExRVUZ6UWl4RFFVRjBRaXhEUVVReVFqdEhRVUZ3UWpzN1FVRkphRUlzVTBGQlR5eFZRVUZUTEZWQlFWUXNSVUZCY1VJc1EwRkJja0lzUlVGQmRVSTdRVUZETlVJc1VVRkJSeXhOUVVGTkxFOUJRVTRzUTBGQll5eFZRVUZrTEVOQlFVZ3NSVUZCTmtJN1FVRkRNMElzVlVGQlJ5eEpRVUZKTEV0QlFVc3NTMEZCVEN4RFFVRlhMRlZCUVZnc1EwRkJTaXhKUVVFNFFpeExRVUZMTEVOQlFVd3NSVUZCVHp0QlFVTjBReXhsUVVGUExFbEJRVWtzUzBGQlN5eExRVUZNTEVOQlFWY3NUMEZCVHl4SFFVRlFMRU5CUVZjc1NVRkJXQ3hEUVVGbUxFVkJRV2xETEZkQlFWY3NRMEZCV0N4RFFVRnFReXhEUVVGUUxFTkJSSE5ETzA5QlFYaERMRTFCUlVzN1FVRkRTQ3hsUVVGUExFOUJRVThzUjBGQlVDeERRVUZYTEU5QlFWZ3NRMEZCVUN4RFFVUkhPMDlCUmt3N1MwRkVSanM3UVVGUlFTeFZRVUZOTEVsQlFVa3NTMEZCU2l4RFFVRlZMR2xEUVVGV0xFTkJRVTRzUTBGVU5FSTdSMEZCZGtJN08wRkJXVkFzYTBKQlFXZENMRlZCUVZNc1ZVRkJWQ3hGUVVGeFFpeERRVUZ5UWl4RlFVRjFRanRCUVVOeVF5eFJRVUZITEUxQlFVMHNUMEZCVGl4RFFVRmpMRlZCUVdRc1EwRkJTQ3hGUVVFMlFqdEJRVU16UWl4VlFVRkhMRWxCUVVrc1MwRkJTeXhMUVVGTUxFTkJRVmNzVlVGQldDeERRVUZLTEVsQlFUaENMRXRCUVVzc1EwRkJUQ3hGUVVGUE8wRkJRM1JETEdWQlFVOHNWMEZCVnl4RFFVRllMRU5CUVZBc1EwRkVjME03VDBGQmVFTXNUVUZGU3p0QlFVTklMR05CUVUwc1NVRkJTU3hMUVVGS0xFTkJRVlVzY1VKQlFWWXNRMEZCVGl4RFFVUkhPMDlCUmt3N1MwRkVSanM3UVVGUlFTeFZRVUZOTEVsQlFVa3NTMEZCU2l4RFFVRlZMR2xEUVVGV0xFTkJRVTRzUTBGVWNVTTdSMEZCZGtJN08wRkJXV2hDTEZWQlFWRXNWVUZCVXl4VlFVRlVMRVZCUVhGQ0xFZEJRWEpDTEVWQlFYbENPMEZCUXk5Q0xGRkJRVWtzVTBGQlV5eEZRVUZVTEVOQlJESkNPenRCUVVjdlFpeFRRVUZKTEVsQlFVa3NTVUZCU2l4SlFVRlpMRlZCUVdoQ0xFVkJRVEpDTzBGQlEzcENMRlZCUVVjc1NVRkJTU3hKUVVGS0xFTkJRVWdzUlVGQllUdEJRVU5ZTEdWQlFVOHNTVUZCVUN4RFFVRlpMRWxCUVZvc1JVRkVWenRQUVVGaU8wdEJSRVk3TzBGQlRVRXNWMEZCVHl4TlFVRlFMRU5CVkN0Q08wZEJRWHBDT3p0QlFWbFNMR05CUVZrc1ZVRkJVeXhWUVVGVUxFVkJRWEZDTEUxQlFYSkNMRVZCUVRaQ0xFMUJRVGRDTEVWQlFXOURPMEZCUXpsRExGZEJRVThzUzBGQlN5eEhRVUZNTEVOQlFWTXNTMEZCU3l4TlFVRk1MRU5CUVZrc1ZVRkJXaXhGUVVGM1FpeE5RVUY0UWl4RFFVRlVMRVZCUVRCRExFMUJRVEZETEVOQlFWQXNRMEZFT0VNN1IwRkJjRU03TzBGQlNWb3NVVUZCVFN4VlFVRlRMRlZCUVZRc1JVRkJjVUlzVlVGQlZTeEpRVUZXTEVWQlFXZENMRWRCUVhKRExFVkJRWGxETzBGQlF6ZERMRk5CUVVrc1NVRkJTU3hKUVVGS0xFbEJRVmtzVlVGQmFFSXNSVUZCTWtJN1FVRkRla0lzVlVGQlJ5eEpRVUZKTEVsQlFVb3NRMEZCU0N4RlFVRmhPMEZCUTFnc1pVRkJUeXhKUVVGUUxFTkJSRmM3VDBGQllqdExRVVJHT3p0QlFVMUJMRmRCUVU4c1QwRkJVQ3hEUVZBMlF6dEhRVUY2UXpzN1FVRlZUaXhSUVVGTkxGVkJRVk1zVlVGQlZDeEZRVUZ4UWl4SlFVRnlRaXhGUVVFd1FqdEJRVU01UWl4WFFVRlBMRXRCUVVzc1RVRkJUQ3hEUVVGWkxGVkJRVm9zUTBGQlVDeERRVVE0UWp0SFFVRXhRanM3UVVGSlRpeFBRVUZMTEZWQlFWTXNWVUZCVkN4RlFVRnhRaXhIUVVGeVFpeEZRVUY1UWp0QlFVTTFRaXhSUVVGSkxGTkJRVk1zUlVGQlZDeERRVVIzUWpzN1FVRkhOVUlzVTBGQlNTeEpRVUZKTEVsQlFVb3NTVUZCV1N4VlFVRm9RaXhGUVVFeVFqdEJRVU42UWl4aFFVRlBMRWxCUVZBc1EwRkJXU3hKUVVGSkxFbEJRVW9zUTBGQldpeEZRVVI1UWp0TFFVRXpRanM3UVVGSlFTeFhRVUZQTEUxQlFWQXNRMEZRTkVJN1IwRkJla0k3TzBGQlZVd3NZMEZCV1N4VlFVRlRMRlZCUVZRc1JVRkJjVUlzUjBGQmNrSXNSVUZCTUVJc1IwRkJNVUlzUlVGQk9FSTdRVUZEZUVNc1VVRkJTU3hUUVVGVExFOUJRVThzVFVGQlVDeERRVUZqTEVWQlFXUXNRMEZCVkN4RFFVUnZRenRCUVVWNFF5eFJRVUZKTEZWQlFWVXNSMEZCVml4RFFVWnZRenM3UVVGSmVFTXNVMEZCU3l4SlFVRkpMRWxCUVVrc1EwRkJTaXhGUVVGUExFbEJRVWtzUzBGQlN5eExRVUZNTEVOQlFWY3NWVUZCV0N4RFFVRktMRVZCUVRSQ0xFZEJRVFZETEVWQlFXbEVPMEZCUXk5RExGVkJRVWtzVVVGQlVTeEpRVUZKTEZkQlFWY3NRMEZCV0N4RFFVRktMRVZCUVcxQ0xFOUJRVzVDTEVOQlFWSXNRMEZFTWtNN08wRkJSeTlETEdkQ1FVRlZMRTFCUVUwc1IwRkJUaXhEUVVGVkxFTkJRVllzUTBGQlZpeERRVWdyUXp0QlFVa3ZReXhsUVVGVExFOUJRVThzVFVGQlVDeERRVUZqTEU5QlFVOHNUVUZCVUN4RFFVRmpMRU5CUVVNc1RVRkJUU3hIUVVGT0xFTkJRVlVzUTBGQlZpeERRVUZFTEVOQlFXUXNRMEZCWkN4RFFVRlVMRU5CU2l0RE8wdEJRV3BFT3p0QlFVOUJMRmRCUVU4c1NVRkJTU3hMUVVGTExFdEJRVXdzUTBGQlZ5eE5RVUZtTEVWQlFYVkNMRTlCUVhaQ0xFTkJRVkFzUTBGWWQwTTdSMEZCT1VJN08wRkJZMW9zYlVKQlFXbENMRlZCUVZNc1ZVRkJWQ3hGUVVGeFFpeExRVUZ5UWl4RlFVRXlRanRCUVVNeFF5eFhRVUZQTEZkQlFWY3NVVUZCV0N4RFFVRnZRaXhMUVVGd1FpeERRVUZRTEVOQlJEQkRPMGRCUVROQ096dEJRVWxxUWl4VlFVRlJMRlZCUVZNc1ZVRkJWQ3hGUVVGeFFpeEhRVUZ5UWl4RlFVRXdRaXhIUVVFeFFpeEZRVUU0UWp0QlFVTndReXhSUVVGSkxGVkJRVlVzUjBGQlZpeERRVVJuUXpzN1FVRkhjRU1zVTBGQlN5eEpRVUZKTEVsQlFVa3NRMEZCU2l4RlFVRlBMRWxCUVVrc1MwRkJTeXhMUVVGTUxFTkJRVmNzVlVGQldDeERRVUZLTEVWQlFUUkNMRWRCUVRWRExFVkJRV2xFTzBGQlF5OURMRlZCUVVrc1VVRkJVU3hKUVVGSkxGZEJRVmNzUTBGQldDeERRVUZLTEVWQlFXMUNMRTlCUVc1Q0xFTkJRVklzUTBGRU1rTTdPMEZCUnk5RExHZENRVUZWTEUxQlFVMHNSMEZCVGl4RFFVRlZMRU5CUVZZc1EwRkJWaXhEUVVnclF6dExRVUZxUkRzN1FVRk5RU3hYUVVGUExFOUJRVkFzUTBGVWIwTTdSMEZCT1VJN08wRkJXVklzVVVGQlRTeFZRVUZUTEZWQlFWUXNSVUZCY1VJc1MwRkJja0lzUlVGQk1rSTdRVUZETDBJc1YwRkJUeXhYUVVGWExFdEJRVmdzUTBGQmFVSXNRMEZCYWtJc1JVRkJiMElzUzBGQmNFSXNRMEZCVUN4RFFVUXJRanRIUVVFelFqczdRVUZKVGl4alFVRlpMRlZCUVZNc1ZVRkJWQ3hGUVVGeFFpeEhRVUZ5UWl4RlFVRjVRanRCUVVOdVF5eFJRVUZKTEZOQlFWTXNSVUZCVkN4RFFVUXJRanRCUVVWdVF5eFJRVUZKTEZGQlFWRXNRMEZCVWl4RFFVWXJRanM3UVVGSmJrTXNVMEZCU1N4SlFVRkpMRWxCUVVvc1NVRkJXU3hWUVVGb1FpeEZRVUV5UWp0QlFVTjZRaXhWUVVGSExGRkJRVkVzUjBGQlVpeExRVUZuUWl4RFFVRm9RaXhGUVVGclFqdEJRVU51UWl4bFFVRlBMRWxCUVZBc1EwRkJXU3hKUVVGYUxFVkJSRzFDTzA5QlFYSkNPMHRCUkVZN08wRkJUVUVzVjBGQlR5eFBRVUZQTEUxQlFWQXNRMEZCWXl4TlFVRmtMRU5CUVZBc1EwRldiVU03UjBGQmVrSTdPMEZCWVZvc1kwRkJXU3hWUVVGVExGVkJRVlFzUlVGQmNVSXNSMEZCY2tJc1JVRkJlVUk3UVVGRGJrTXNVVUZCU1N4UlFVRlJMRU5CUVZJc1EwRkVLMEk3TzBGQlIyNURMRk5CUVVrc1NVRkJTU3hKUVVGS0xFbEJRVmtzVlVGQmFFSXNSVUZCTWtJN1FVRkRla0lzVlVGQlJ5eEpRVUZKTEVsQlFVb3NRMEZCU0N4RlFVRmhPMEZCUTFnc1owSkJRVkVzVVVGQlVTeERRVUZTTEVOQlJFYzdUMEZCWWl4TlFVVkxPMEZCUTBnc1kwRkVSenRQUVVaTU8wdEJSRVk3TzBGQlVVRXNWMEZCVHl4WFFVRlhMRXRCUVZnc1EwRkJhVUlzUTBGQmFrSXNSVUZCYjBJc1MwRkJjRUlzUTBGQlVDeERRVmh0UXp0SFFVRjZRanM3UVVGaldpeFhRVUZUTEZWQlFWTXNWVUZCVkN4RlFVRnZRanRCUVVNelFpeFhRVUZQTEZWQlFWQXNRMEZFTWtJN1IwRkJjRUk3UTBGdVRWQTdPMEZCZDAxS0xHVkJRV1VzU1VGQlppSXNJbVpwYkdVaU9pSnNhV0l2Wlc1MWJTNXFjeUlzSW5OdmRYSmpaWE5EYjI1MFpXNTBJanBiSW1sdGNHOXlkQ0JEYjNKbElHWnliMjBnSnk0dlkyOXlaU2M3WEc1Y2JteGxkQ0JGYm5WdElEMGdlMXh1WEc0Z0lHRnNiRjlmY1cxaGNtdGZYem9nWm5WdVkzUnBiMjRvWTI5c2JHVmpkR2x2Yml3Z1puVnVJRDBnS0hncElEMCtJSGdwZTF4dUlDQWdJR1p2Y2loc1pYUWdaV3hsYlNCdlppQmpiMnhzWldOMGFXOXVLWHRjYmlBZ0lDQWdJR2xtS0NGbWRXNG9aV3hsYlNrcGUxeHVJQ0FnSUNBZ0lDQnlaWFIxY200Z1ptRnNjMlU3WEc0Z0lDQWdJQ0I5WEc0Z0lDQWdmVnh1WEc0Z0lDQWdjbVYwZFhKdUlIUnlkV1U3WEc0Z0lIMHNYRzVjYmlBZ1lXNTVYMTl4YldGeWExOWZPaUJtZFc1amRHbHZiaWhqYjJ4c1pXTjBhVzl1TENCbWRXNGdQU0FvZUNrZ1BUNGdlQ2w3WEc0Z0lDQWdabTl5S0d4bGRDQmxiR1Z0SUc5bUlHTnZiR3hsWTNScGIyNHBlMXh1SUNBZ0lDQWdhV1lvWm5WdUtHVnNaVzBwS1h0Y2JpQWdJQ0FnSUNBZ2NtVjBkWEp1SUhSeWRXVTdYRzRnSUNBZ0lDQjlYRzRnSUNBZ2ZWeHVYRzRnSUNBZ2NtVjBkWEp1SUdaaGJITmxPMXh1SUNCOUxGeHVYRzRnSUdGME9pQm1kVzVqZEdsdmJpaGpiMnhzWldOMGFXOXVMQ0J1TENCMGFHVmZaR1ZtWVhWc2RDQTlJRzUxYkd3cGUxeHVJQ0FnSUdsbUtHNGdQaUIwYUdsekxtTnZkVzUwS0dOdmJHeGxZM1JwYjI0cElIeDhJRzRnUENBd0tYdGNiaUFnSUNBZ0lISmxkSFZ5YmlCMGFHVmZaR1ZtWVhWc2REdGNiaUFnSUNCOVhHNWNiaUFnSUNCeVpYUjFjbTRnWTI5c2JHVmpkR2x2Ymx0dVhUdGNiaUFnZlN4Y2JseHVJQ0JqYjI1allYUTZJR1oxYm1OMGFXOXVLQzR1TG1WdWRXMWhZbXhsY3lsN1hHNGdJQ0FnY21WMGRYSnVJR1Z1ZFcxaFlteGxjMXN3WFM1amIyNWpZWFFvWlc1MWJXRmliR1Z6V3pGZEtUdGNiaUFnZlN4Y2JseHVJQ0JqYjNWdWREb2dablZ1WTNScGIyNG9ZMjlzYkdWamRHbHZiaXdnWm5WdUlEMGdiblZzYkNsN1hHNGdJQ0FnYVdZb1puVnVJRDA5SUc1MWJHd3BlMXh1SUNBZ0lDQWdjbVYwZFhKdUlHTnZiR3hsWTNScGIyNHViR1Z1WjNSb08xeHVJQ0FnSUgwZ1pXeHpaU0I3WEc0Z0lDQWdJQ0J5WlhSMWNtNGdZMjlzYkdWamRHbHZiaTVtYVd4MFpYSW9ablZ1S1M1c1pXNW5kR2c3WEc0Z0lDQWdmVnh1SUNCOUxGeHVYRzRnSUdSeWIzQTZJR1oxYm1OMGFXOXVLR052Ykd4bFkzUnBiMjRzSUdOdmRXNTBLWHRjYmlBZ0lDQnlaWFIxY200Z1kyOXNiR1ZqZEdsdmJpNXpiR2xqWlNoamIzVnVkQ2s3WEc0Z0lIMHNYRzVjYmlBZ1pISnZjRjkzYUdsc1pUb2dablZ1WTNScGIyNG9ZMjlzYkdWamRHbHZiaXdnWm5WdUtYdGNiaUFnSUNCc1pYUWdZMjkxYm5RZ1BTQXdPMXh1WEc0Z0lDQWdabTl5S0d4bGRDQmxiR1Z0SUc5bUlHTnZiR3hsWTNScGIyNHBlMXh1SUNBZ0lDQWdhV1lvWm5WdUtHVnNaVzBwS1h0Y2JpQWdJQ0FnSUNBZ1kyOTFiblFnUFNCamIzVnVkQ0FySURFN1hHNGdJQ0FnSUNCOVpXeHpaWHRjYmlBZ0lDQWdJQ0FnWW5KbFlXczdYRzRnSUNBZ0lDQjlYRzRnSUNBZ2ZWeHVYRzRnSUNBZ2NtVjBkWEp1SUdOdmJHeGxZM1JwYjI0dWMyeHBZMlVvWTI5MWJuUXBPMXh1SUNCOUxGeHVYRzRnSUdWaFkyZzZJR1oxYm1OMGFXOXVLR052Ykd4bFkzUnBiMjRzSUdaMWJpbDdYRzRnSUNBZ1ptOXlLR3hsZENCbGJHVnRJRzltSUdOdmJHeGxZM1JwYjI0cGUxeHVJQ0FnSUNBZ1puVnVLR1ZzWlcwcE8xeHVJQ0FnSUgxY2JpQWdmU3hjYmx4dUlDQmxiWEIwZVY5ZmNXMWhjbXRmWHpvZ1puVnVZM1JwYjI0b1kyOXNiR1ZqZEdsdmJpbDdYRzRnSUNBZ2NtVjBkWEp1SUdOdmJHeGxZM1JwYjI0dWJHVnVaM1JvSUQwOVBTQXdPMXh1SUNCOUxGeHVYRzRnSUdabGRHTm9PaUJtZFc1amRHbHZiaWhqYjJ4c1pXTjBhVzl1TENCdUtYdGNiaUFnSUNCcFppaEJjbkpoZVM1cGMwRnljbUY1S0dOdmJHeGxZM1JwYjI0cEtYdGNiaUFnSUNBZ0lHbG1LRzRnUENCMGFHbHpMbU52ZFc1MEtHTnZiR3hsWTNScGIyNHBJQ1ltSUc0Z1BqMGdNQ2w3WEc0Z0lDQWdJQ0FnSUhKbGRIVnliaUJ1WlhjZ1EyOXlaUzVVZFhCc1pTaFRlVzFpYjJ3dVptOXlLRndpYjJ0Y0lpa3NJR052Ykd4bFkzUnBiMjViYmwwcE8xeHVJQ0FnSUNBZ2ZXVnNjMlY3WEc0Z0lDQWdJQ0FnSUhKbGRIVnliaUJUZVcxaWIyd3VabTl5S0Z3aVpYSnliM0pjSWlrN1hHNGdJQ0FnSUNCOVhHNGdJQ0FnZlZ4dVhHNGdJQ0FnZEdoeWIzY2dibVYzSUVWeWNtOXlLRndpWTI5c2JHVmpkR2x2YmlCcGN5QnViM1FnWVc0Z1JXNTFiV1Z5WVdKc1pWd2lLVHRjYmlBZ2ZTeGNibHh1SUNCbVpYUmphRjlmWlcxaGNtdGZYem9nWm5WdVkzUnBiMjRvWTI5c2JHVmpkR2x2Yml3Z2JpbDdYRzRnSUNBZ2FXWW9RWEp5WVhrdWFYTkJjbkpoZVNoamIyeHNaV04wYVc5dUtTbDdYRzRnSUNBZ0lDQnBaaWh1SUR3Z2RHaHBjeTVqYjNWdWRDaGpiMnhzWldOMGFXOXVLU0FtSmlCdUlENDlJREFwZTF4dUlDQWdJQ0FnSUNCeVpYUjFjbTRnWTI5c2JHVmpkR2x2Ymx0dVhUdGNiaUFnSUNBZ0lIMWxiSE5sZTF4dUlDQWdJQ0FnSUNCMGFISnZkeUJ1WlhjZ1JYSnliM0lvWENKdmRYUWdiMllnWW05MWJtUnpJR1Z5Y205eVhDSXBPMXh1SUNBZ0lDQWdmVnh1SUNBZ0lIMWNibHh1SUNBZ0lIUm9jbTkzSUc1bGR5QkZjbkp2Y2loY0ltTnZiR3hsWTNScGIyNGdhWE1nYm05MElHRnVJRVZ1ZFcxbGNtRmliR1ZjSWlrN1hHNGdJSDBzWEc1Y2JpQWdabWxzZEdWeU9pQm1kVzVqZEdsdmJpaGpiMnhzWldOMGFXOXVMQ0JtZFc0cGUxeHVJQ0FnSUd4bGRDQnlaWE4xYkhRZ1BTQmJYVHRjYmx4dUlDQWdJR1p2Y2loc1pYUWdaV3hsYlNCdlppQmpiMnhzWldOMGFXOXVLWHRjYmlBZ0lDQWdJR2xtS0daMWJpaGxiR1Z0S1NsN1hHNGdJQ0FnSUNBZ0lISmxjM1ZzZEM1d2RYTm9LR1ZzWlcwcE8xeHVJQ0FnSUNBZ2ZWeHVJQ0FnSUgxY2JseHVJQ0FnSUhKbGRIVnliaUJ5WlhOMWJIUTdYRzRnSUgwc1hHNWNiaUFnWm1sc2RHVnlYMjFoY0RvZ1puVnVZM1JwYjI0b1kyOXNiR1ZqZEdsdmJpd2dabWxzZEdWeUxDQnRZWEJ3WlhJcGUxeHVJQ0FnSUhKbGRIVnliaUJGYm5WdExtMWhjQ2hGYm5WdExtWnBiSFJsY2loamIyeHNaV04wYVc5dUxDQm1hV3gwWlhJcExDQnRZWEJ3WlhJcE8xeHVJQ0I5TEZ4dVhHNGdJR1pwYm1RNklHWjFibU4wYVc5dUtHTnZiR3hsWTNScGIyNHNJR2xtWDI1dmJtVWdQU0J1ZFd4c0xDQm1kVzRwZTF4dUlDQWdJR1p2Y2loc1pYUWdaV3hsYlNCdlppQmpiMnhzWldOMGFXOXVLWHRjYmlBZ0lDQWdJR2xtS0daMWJpaGxiR1Z0S1NsN1hHNGdJQ0FnSUNBZ0lISmxkSFZ5YmlCbGJHVnRPMXh1SUNBZ0lDQWdmVnh1SUNBZ0lIMWNibHh1SUNBZ0lISmxkSFZ5YmlCcFpsOXViMjVsTzF4dUlDQjlMRnh1WEc0Z0lHbHVkRzg2SUdaMWJtTjBhVzl1S0dOdmJHeGxZM1JwYjI0c0lHeHBjM1FwZTF4dUlDQWdJSEpsZEhWeWJpQnNhWE4wTG1OdmJtTmhkQ2hqYjJ4c1pXTjBhVzl1S1R0Y2JpQWdmU3hjYmx4dUlDQnRZWEE2SUdaMWJtTjBhVzl1S0dOdmJHeGxZM1JwYjI0c0lHWjFiaWw3WEc0Z0lDQWdiR1YwSUhKbGMzVnNkQ0E5SUZ0ZE8xeHVYRzRnSUNBZ1ptOXlLR3hsZENCbGJHVnRJRzltSUdOdmJHeGxZM1JwYjI0cGUxeHVJQ0FnSUNBZ2NtVnpkV3gwTG5CMWMyZ29ablZ1S0dWc1pXMHBLVHRjYmlBZ0lDQjlYRzVjYmlBZ0lDQnlaWFIxY200Z2NtVnpkV3gwTzF4dUlDQjlMRnh1WEc0Z0lHMWhjRjl5WldSMVkyVTZJR1oxYm1OMGFXOXVLR052Ykd4bFkzUnBiMjRzSUdGall5d2dablZ1S1h0Y2JpQWdJQ0JzWlhRZ2JXRndjR1ZrSUQwZ1QySnFaV04wTG1aeVpXVjZaU2hiWFNrN1hHNGdJQ0FnYkdWMElIUm9aVjloWTJNZ1BTQmhZMk03WEc1Y2JpQWdJQ0JtYjNJZ0tIWmhjaUJwSUQwZ01Ec2dhU0E4SUhSb2FYTXVZMjkxYm5Rb1kyOXNiR1ZqZEdsdmJpazdJR2tyS3lrZ2UxeHVJQ0FnSUNBZ2JHVjBJSFIxY0d4bElEMGdablZ1S0dOdmJHeGxZM1JwYjI1YmFWMHNJSFJvWlY5aFkyTXBPMXh1WEc0Z0lDQWdJQ0IwYUdWZllXTmpJRDBnZEhWd2JHVXVaMlYwS0RFcE8xeHVJQ0FnSUNBZ2JXRndjR1ZrSUQwZ1QySnFaV04wTG1aeVpXVjZaU2h0WVhCd1pXUXVZMjl1WTJGMEtGdDBkWEJzWlM1blpYUW9NQ2xkS1NrN1hHNGdJQ0FnZlZ4dVhHNGdJQ0FnY21WMGRYSnVJRzVsZHlCRGIzSmxMbFIxY0d4bEtHMWhjSEJsWkN3Z2RHaGxYMkZqWXlrN1hHNGdJSDBzWEc1Y2JpQWdiV1Z0WW1WeVgxOXhiV0Z5YTE5Zk9pQm1kVzVqZEdsdmJpaGpiMnhzWldOMGFXOXVMQ0IyWVd4MVpTbDdYRzRnSUNBZ2NtVjBkWEp1SUdOdmJHeGxZM1JwYjI0dWFXNWpiSFZrWlhNb2RtRnNkV1VwTzF4dUlDQjlMRnh1WEc0Z0lISmxaSFZqWlRvZ1puVnVZM1JwYjI0b1kyOXNiR1ZqZEdsdmJpd2dZV05qTENCbWRXNHBlMXh1SUNBZ0lHeGxkQ0IwYUdWZllXTmpJRDBnWVdOak8xeHVYRzRnSUNBZ1ptOXlJQ2gyWVhJZ2FTQTlJREE3SUdrZ1BDQjBhR2x6TG1OdmRXNTBLR052Ykd4bFkzUnBiMjRwT3lCcEt5c3BJSHRjYmlBZ0lDQWdJR3hsZENCMGRYQnNaU0E5SUdaMWJpaGpiMnhzWldOMGFXOXVXMmxkTENCMGFHVmZZV05qS1R0Y2JseHVJQ0FnSUNBZ2RHaGxYMkZqWXlBOUlIUjFjR3hsTG1kbGRDZ3hLVHRjYmlBZ0lDQjlYRzVjYmlBZ0lDQnlaWFIxY200Z2RHaGxYMkZqWXp0Y2JpQWdmU3hjYmx4dUlDQjBZV3RsT2lCbWRXNWpkR2x2YmloamIyeHNaV04wYVc5dUxDQmpiM1Z1ZENsN1hHNGdJQ0FnY21WMGRYSnVJR052Ykd4bFkzUnBiMjR1YzJ4cFkyVW9NQ3dnWTI5MWJuUXBPMXh1SUNCOUxGeHVYRzRnSUhSaGEyVmZaWFpsY25rNklHWjFibU4wYVc5dUtHTnZiR3hsWTNScGIyNHNJRzUwYUNsN1hHNGdJQ0FnYkdWMElISmxjM1ZzZENBOUlGdGRPMXh1SUNBZ0lHeGxkQ0JwYm1SbGVDQTlJREE3WEc1Y2JpQWdJQ0JtYjNJb2JHVjBJR1ZzWlcwZ2IyWWdZMjlzYkdWamRHbHZiaWw3WEc0Z0lDQWdJQ0JwWmlocGJtUmxlQ0FsSUc1MGFDQTlQVDBnTUNsN1hHNGdJQ0FnSUNBZ0lISmxjM1ZzZEM1d2RYTm9LR1ZzWlcwcE8xeHVJQ0FnSUNBZ2ZWeHVJQ0FnSUgxY2JseHVJQ0FnSUhKbGRIVnliaUJQWW1wbFkzUXVabkpsWlhwbEtISmxjM1ZzZENrN1hHNGdJSDBzWEc1Y2JpQWdkR0ZyWlY5M2FHbHNaVG9nWm5WdVkzUnBiMjRvWTI5c2JHVmpkR2x2Yml3Z1puVnVLWHRjYmlBZ0lDQnNaWFFnWTI5MWJuUWdQU0F3TzF4dVhHNGdJQ0FnWm05eUtHeGxkQ0JsYkdWdElHOW1JR052Ykd4bFkzUnBiMjRwZTF4dUlDQWdJQ0FnYVdZb1puVnVLR1ZzWlcwcEtYdGNiaUFnSUNBZ0lDQWdZMjkxYm5RZ1BTQmpiM1Z1ZENBcklERTdYRzRnSUNBZ0lDQjlaV3h6Wlh0Y2JpQWdJQ0FnSUNBZ1luSmxZV3M3WEc0Z0lDQWdJQ0I5WEc0Z0lDQWdmVnh1WEc0Z0lDQWdjbVYwZFhKdUlHTnZiR3hsWTNScGIyNHVjMnhwWTJVb01Dd2dZMjkxYm5RcE8xeHVJQ0I5TEZ4dVhHNGdJSFJ2WDJ4cGMzUTZJR1oxYm1OMGFXOXVLR052Ykd4bFkzUnBiMjRwZTF4dUlDQWdJSEpsZEhWeWJpQmpiMnhzWldOMGFXOXVPMXh1SUNCOVhHNTlPMXh1WEc1bGVIQnZjblFnWkdWbVlYVnNkQ0JGYm5WdE8xeHVJbDBzSW5OdmRYSmpaVkp2YjNRaU9pSXZjMjkxY21ObEx5SjlcbiIsImxldCBWaXJ0dWFsRE9NID0gZnVuY3Rpb24gKGUpIHtcbiAgICByZXR1cm4gZSgpO1xufShmdW5jdGlvbiAoKSB7XG4gICAgdmFyIGRlZmluZSwgbW9kdWxlLCBleHBvcnRzO1xuICAgIHJldHVybiBmdW5jdGlvbiBlKHQsIG4sIHIpIHtcbiAgICAgICAgZnVuY3Rpb24gcyhvLCB1KSB7XG4gICAgICAgICAgICBpZiAoIW5bb10pIHtcbiAgICAgICAgICAgICAgICBpZiAoIXRbb10pIHtcbiAgICAgICAgICAgICAgICAgICAgdmFyIGEgPSB0eXBlb2YgcmVxdWlyZSA9PSBcImZ1bmN0aW9uXCIgJiYgcmVxdWlyZTtcbiAgICAgICAgICAgICAgICAgICAgaWYgKCF1ICYmIGEpIHJldHVybiBhKG8sICEwKTtcbiAgICAgICAgICAgICAgICAgICAgaWYgKGkpIHJldHVybiBpKG8sICEwKTtcbiAgICAgICAgICAgICAgICAgICAgdmFyIGYgPSBuZXcgRXJyb3IoXCJDYW5ub3QgZmluZCBtb2R1bGUgJ1wiICsgbyArIFwiJ1wiKTtcbiAgICAgICAgICAgICAgICAgICAgdGhyb3cgZi5jb2RlID0gXCJNT0RVTEVfTk9UX0ZPVU5EXCIsIGY7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHZhciBsID0gbltvXSA9IHtcbiAgICAgICAgICAgICAgICAgICAgZXhwb3J0czoge31cbiAgICAgICAgICAgICAgICB9O1xuICAgICAgICAgICAgICAgIHRbb11bMF0uY2FsbChsLmV4cG9ydHMsIGZ1bmN0aW9uIChlKSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciBuID0gdFtvXVsxXVtlXTtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHMobiA/IG4gOiBlKTtcbiAgICAgICAgICAgICAgICB9LCBsLCBsLmV4cG9ydHMsIGUsIHQsIG4sIHIpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmV0dXJuIG5bb10uZXhwb3J0cztcbiAgICAgICAgfVxuICAgICAgICB2YXIgaSA9IHR5cGVvZiByZXF1aXJlID09IFwiZnVuY3Rpb25cIiAmJiByZXF1aXJlO1xuICAgICAgICBmb3IgKHZhciBvID0gMDsgbyA8IHIubGVuZ3RoOyBvKyspIHMocltvXSk7XG4gICAgICAgIHJldHVybiBzO1xuICAgIH0oe1xuICAgICAgICAxOiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge1xuXG4gICAgICAgICAgICB2YXIgY3JlYXRlRWxlbWVudCA9IHJlcXVpcmUoXCIuL3Zkb20vY3JlYXRlLWVsZW1lbnQuanNcIik7XG5cbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gY3JlYXRlRWxlbWVudDtcbiAgICAgICAgfSwgeyBcIi4vdmRvbS9jcmVhdGUtZWxlbWVudC5qc1wiOiAxNSB9XSwgMjogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHtcbiAgICAgICAgICAgIHZhciBkaWZmID0gcmVxdWlyZShcIi4vdnRyZWUvZGlmZi5qc1wiKTtcblxuICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBkaWZmO1xuICAgICAgICB9LCB7IFwiLi92dHJlZS9kaWZmLmpzXCI6IDM1IH1dLCAzOiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge1xuICAgICAgICAgICAgdmFyIGggPSByZXF1aXJlKFwiLi92aXJ0dWFsLWh5cGVyc2NyaXB0L2luZGV4LmpzXCIpO1xuXG4gICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IGg7XG4gICAgICAgIH0sIHsgXCIuL3ZpcnR1YWwtaHlwZXJzY3JpcHQvaW5kZXguanNcIjogMjIgfV0sIDQ6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICB2YXIgZGlmZiA9IHJlcXVpcmUoXCIuL2RpZmYuanNcIik7XG4gICAgICAgICAgICB2YXIgcGF0Y2ggPSByZXF1aXJlKFwiLi9wYXRjaC5qc1wiKTtcbiAgICAgICAgICAgIHZhciBoID0gcmVxdWlyZShcIi4vaC5qc1wiKTtcbiAgICAgICAgICAgIHZhciBjcmVhdGUgPSByZXF1aXJlKFwiLi9jcmVhdGUtZWxlbWVudC5qc1wiKTtcbiAgICAgICAgICAgIHZhciBWTm9kZSA9IHJlcXVpcmUoJy4vdm5vZGUvdm5vZGUuanMnKTtcbiAgICAgICAgICAgIHZhciBWVGV4dCA9IHJlcXVpcmUoJy4vdm5vZGUvdnRleHQuanMnKTtcblxuICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSB7XG4gICAgICAgICAgICAgICAgZGlmZjogZGlmZixcbiAgICAgICAgICAgICAgICBwYXRjaDogcGF0Y2gsXG4gICAgICAgICAgICAgICAgaDogaCxcbiAgICAgICAgICAgICAgICBjcmVhdGU6IGNyZWF0ZSxcbiAgICAgICAgICAgICAgICBWTm9kZTogVk5vZGUsXG4gICAgICAgICAgICAgICAgVlRleHQ6IFZUZXh0XG4gICAgICAgICAgICB9O1xuICAgICAgICB9LCB7IFwiLi9jcmVhdGUtZWxlbWVudC5qc1wiOiAxLCBcIi4vZGlmZi5qc1wiOiAyLCBcIi4vaC5qc1wiOiAzLCBcIi4vcGF0Y2guanNcIjogMTMsIFwiLi92bm9kZS92bm9kZS5qc1wiOiAzMSwgXCIuL3Zub2RlL3Z0ZXh0LmpzXCI6IDMzIH1dLCA1OiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge1xuICAgICAgICAgICAgLyohXG4gICAgICAgICAgICAgKiBDcm9zcy1Ccm93c2VyIFNwbGl0IDEuMS4xXG4gICAgICAgICAgICAgKiBDb3B5cmlnaHQgMjAwNy0yMDEyIFN0ZXZlbiBMZXZpdGhhbiA8c3RldmVubGV2aXRoYW4uY29tPlxuICAgICAgICAgICAgICogQXZhaWxhYmxlIHVuZGVyIHRoZSBNSVQgTGljZW5zZVxuICAgICAgICAgICAgICogRUNNQVNjcmlwdCBjb21wbGlhbnQsIHVuaWZvcm0gY3Jvc3MtYnJvd3NlciBzcGxpdCBtZXRob2RcbiAgICAgICAgICAgICAqL1xuXG4gICAgICAgICAgICAvKipcbiAgICAgICAgICAgICAqIFNwbGl0cyBhIHN0cmluZyBpbnRvIGFuIGFycmF5IG9mIHN0cmluZ3MgdXNpbmcgYSByZWdleCBvciBzdHJpbmcgc2VwYXJhdG9yLiBNYXRjaGVzIG9mIHRoZVxuICAgICAgICAgICAgICogc2VwYXJhdG9yIGFyZSBub3QgaW5jbHVkZWQgaW4gdGhlIHJlc3VsdCBhcnJheS4gSG93ZXZlciwgaWYgYHNlcGFyYXRvcmAgaXMgYSByZWdleCB0aGF0IGNvbnRhaW5zXG4gICAgICAgICAgICAgKiBjYXB0dXJpbmcgZ3JvdXBzLCBiYWNrcmVmZXJlbmNlcyBhcmUgc3BsaWNlZCBpbnRvIHRoZSByZXN1bHQgZWFjaCB0aW1lIGBzZXBhcmF0b3JgIGlzIG1hdGNoZWQuXG4gICAgICAgICAgICAgKiBGaXhlcyBicm93c2VyIGJ1Z3MgY29tcGFyZWQgdG8gdGhlIG5hdGl2ZSBgU3RyaW5nLnByb3RvdHlwZS5zcGxpdGAgYW5kIGNhbiBiZSB1c2VkIHJlbGlhYmx5XG4gICAgICAgICAgICAgKiBjcm9zcy1icm93c2VyLlxuICAgICAgICAgICAgICogQHBhcmFtIHtTdHJpbmd9IHN0ciBTdHJpbmcgdG8gc3BsaXQuXG4gICAgICAgICAgICAgKiBAcGFyYW0ge1JlZ0V4cHxTdHJpbmd9IHNlcGFyYXRvciBSZWdleCBvciBzdHJpbmcgdG8gdXNlIGZvciBzZXBhcmF0aW5nIHRoZSBzdHJpbmcuXG4gICAgICAgICAgICAgKiBAcGFyYW0ge051bWJlcn0gW2xpbWl0XSBNYXhpbXVtIG51bWJlciBvZiBpdGVtcyB0byBpbmNsdWRlIGluIHRoZSByZXN1bHQgYXJyYXkuXG4gICAgICAgICAgICAgKiBAcmV0dXJucyB7QXJyYXl9IEFycmF5IG9mIHN1YnN0cmluZ3MuXG4gICAgICAgICAgICAgKiBAZXhhbXBsZVxuICAgICAgICAgICAgICpcbiAgICAgICAgICAgICAqIC8vIEJhc2ljIHVzZVxuICAgICAgICAgICAgICogc3BsaXQoJ2EgYiBjIGQnLCAnICcpO1xuICAgICAgICAgICAgICogLy8gLT4gWydhJywgJ2InLCAnYycsICdkJ11cbiAgICAgICAgICAgICAqXG4gICAgICAgICAgICAgKiAvLyBXaXRoIGxpbWl0XG4gICAgICAgICAgICAgKiBzcGxpdCgnYSBiIGMgZCcsICcgJywgMik7XG4gICAgICAgICAgICAgKiAvLyAtPiBbJ2EnLCAnYiddXG4gICAgICAgICAgICAgKlxuICAgICAgICAgICAgICogLy8gQmFja3JlZmVyZW5jZXMgaW4gcmVzdWx0IGFycmF5XG4gICAgICAgICAgICAgKiBzcGxpdCgnLi53b3JkMSB3b3JkMi4uJywgLyhbYS16XSspKFxcZCspL2kpO1xuICAgICAgICAgICAgICogLy8gLT4gWycuLicsICd3b3JkJywgJzEnLCAnICcsICd3b3JkJywgJzInLCAnLi4nXVxuICAgICAgICAgICAgICovXG4gICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uIHNwbGl0KHVuZGVmKSB7XG5cbiAgICAgICAgICAgICAgICB2YXIgbmF0aXZlU3BsaXQgPSBTdHJpbmcucHJvdG90eXBlLnNwbGl0LFxuICAgICAgICAgICAgICAgICAgICBjb21wbGlhbnRFeGVjTnBjZyA9IC8oKT8/Ly5leGVjKFwiXCIpWzFdID09PSB1bmRlZixcblxuICAgICAgICAgICAgICAgIC8vIE5QQ0c6IG5vbnBhcnRpY2lwYXRpbmcgY2FwdHVyaW5nIGdyb3VwXG4gICAgICAgICAgICAgICAgc2VsZjtcblxuICAgICAgICAgICAgICAgIHNlbGYgPSBmdW5jdGlvbiAoc3RyLCBzZXBhcmF0b3IsIGxpbWl0KSB7XG4gICAgICAgICAgICAgICAgICAgIC8vIElmIGBzZXBhcmF0b3JgIGlzIG5vdCBhIHJlZ2V4LCB1c2UgYG5hdGl2ZVNwbGl0YFxuICAgICAgICAgICAgICAgICAgICBpZiAoT2JqZWN0LnByb3RvdHlwZS50b1N0cmluZy5jYWxsKHNlcGFyYXRvcikgIT09IFwiW29iamVjdCBSZWdFeHBdXCIpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBuYXRpdmVTcGxpdC5jYWxsKHN0ciwgc2VwYXJhdG9yLCBsaW1pdCk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgdmFyIG91dHB1dCA9IFtdLFxuICAgICAgICAgICAgICAgICAgICAgICAgZmxhZ3MgPSAoc2VwYXJhdG9yLmlnbm9yZUNhc2UgPyBcImlcIiA6IFwiXCIpICsgKHNlcGFyYXRvci5tdWx0aWxpbmUgPyBcIm1cIiA6IFwiXCIpICsgKHNlcGFyYXRvci5leHRlbmRlZCA/IFwieFwiIDogXCJcIikgKyAoIC8vIFByb3Bvc2VkIGZvciBFUzZcbiAgICAgICAgICAgICAgICAgICAgc2VwYXJhdG9yLnN0aWNreSA/IFwieVwiIDogXCJcIiksXG5cbiAgICAgICAgICAgICAgICAgICAgLy8gRmlyZWZveCAzK1xuICAgICAgICAgICAgICAgICAgICBsYXN0TGFzdEluZGV4ID0gMCxcblxuICAgICAgICAgICAgICAgICAgICAvLyBNYWtlIGBnbG9iYWxgIGFuZCBhdm9pZCBgbGFzdEluZGV4YCBpc3N1ZXMgYnkgd29ya2luZyB3aXRoIGEgY29weVxuICAgICAgICAgICAgICAgICAgICBzZXBhcmF0b3IgPSBuZXcgUmVnRXhwKHNlcGFyYXRvci5zb3VyY2UsIGZsYWdzICsgXCJnXCIpLFxuICAgICAgICAgICAgICAgICAgICAgICAgc2VwYXJhdG9yMixcbiAgICAgICAgICAgICAgICAgICAgICAgIG1hdGNoLFxuICAgICAgICAgICAgICAgICAgICAgICAgbGFzdEluZGV4LFxuICAgICAgICAgICAgICAgICAgICAgICAgbGFzdExlbmd0aDtcbiAgICAgICAgICAgICAgICAgICAgc3RyICs9IFwiXCI7IC8vIFR5cGUtY29udmVydFxuICAgICAgICAgICAgICAgICAgICBpZiAoIWNvbXBsaWFudEV4ZWNOcGNnKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAvLyBEb2Vzbid0IG5lZWQgZmxhZ3MgZ3ksIGJ1dCB0aGV5IGRvbid0IGh1cnRcbiAgICAgICAgICAgICAgICAgICAgICAgIHNlcGFyYXRvcjIgPSBuZXcgUmVnRXhwKFwiXlwiICsgc2VwYXJhdG9yLnNvdXJjZSArIFwiJCg/IVxcXFxzKVwiLCBmbGFncyk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgLyogVmFsdWVzIGZvciBgbGltaXRgLCBwZXIgdGhlIHNwZWM6XG4gICAgICAgICAgICAgICAgICAgICAqIElmIHVuZGVmaW5lZDogNDI5NDk2NzI5NSAvLyBNYXRoLnBvdygyLCAzMikgLSAxXG4gICAgICAgICAgICAgICAgICAgICAqIElmIDAsIEluZmluaXR5LCBvciBOYU46IDBcbiAgICAgICAgICAgICAgICAgICAgICogSWYgcG9zaXRpdmUgbnVtYmVyOiBsaW1pdCA9IE1hdGguZmxvb3IobGltaXQpOyBpZiAobGltaXQgPiA0Mjk0OTY3Mjk1KSBsaW1pdCAtPSA0Mjk0OTY3Mjk2O1xuICAgICAgICAgICAgICAgICAgICAgKiBJZiBuZWdhdGl2ZSBudW1iZXI6IDQyOTQ5NjcyOTYgLSBNYXRoLmZsb29yKE1hdGguYWJzKGxpbWl0KSlcbiAgICAgICAgICAgICAgICAgICAgICogSWYgb3RoZXI6IFR5cGUtY29udmVydCwgdGhlbiB1c2UgdGhlIGFib3ZlIHJ1bGVzXG4gICAgICAgICAgICAgICAgICAgICAqL1xuICAgICAgICAgICAgICAgICAgICBsaW1pdCA9IGxpbWl0ID09PSB1bmRlZiA/IC0xID4+PiAwIDogLy8gTWF0aC5wb3coMiwgMzIpIC0gMVxuICAgICAgICAgICAgICAgICAgICBsaW1pdCA+Pj4gMDsgLy8gVG9VaW50MzIobGltaXQpXG4gICAgICAgICAgICAgICAgICAgIHdoaWxlIChtYXRjaCA9IHNlcGFyYXRvci5leGVjKHN0cikpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIGBzZXBhcmF0b3IubGFzdEluZGV4YCBpcyBub3QgcmVsaWFibGUgY3Jvc3MtYnJvd3NlclxuICAgICAgICAgICAgICAgICAgICAgICAgbGFzdEluZGV4ID0gbWF0Y2guaW5kZXggKyBtYXRjaFswXS5sZW5ndGg7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAobGFzdEluZGV4ID4gbGFzdExhc3RJbmRleCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIG91dHB1dC5wdXNoKHN0ci5zbGljZShsYXN0TGFzdEluZGV4LCBtYXRjaC5pbmRleCkpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIEZpeCBicm93c2VycyB3aG9zZSBgZXhlY2AgbWV0aG9kcyBkb24ndCBjb25zaXN0ZW50bHkgcmV0dXJuIGB1bmRlZmluZWRgIGZvclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIG5vbnBhcnRpY2lwYXRpbmcgY2FwdHVyaW5nIGdyb3Vwc1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmICghY29tcGxpYW50RXhlY05wY2cgJiYgbWF0Y2gubGVuZ3RoID4gMSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBtYXRjaFswXS5yZXBsYWNlKHNlcGFyYXRvcjIsIGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZvciAodmFyIGkgPSAxOyBpIDwgYXJndW1lbnRzLmxlbmd0aCAtIDI7IGkrKykge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChhcmd1bWVudHNbaV0gPT09IHVuZGVmKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1hdGNoW2ldID0gdW5kZWY7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKG1hdGNoLmxlbmd0aCA+IDEgJiYgbWF0Y2guaW5kZXggPCBzdHIubGVuZ3RoKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIEFycmF5LnByb3RvdHlwZS5wdXNoLmFwcGx5KG91dHB1dCwgbWF0Y2guc2xpY2UoMSkpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBsYXN0TGVuZ3RoID0gbWF0Y2hbMF0ubGVuZ3RoO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxhc3RMYXN0SW5kZXggPSBsYXN0SW5kZXg7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKG91dHB1dC5sZW5ndGggPj0gbGltaXQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHNlcGFyYXRvci5sYXN0SW5kZXggPT09IG1hdGNoLmluZGV4KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgc2VwYXJhdG9yLmxhc3RJbmRleCsrOyAvLyBBdm9pZCBhbiBpbmZpbml0ZSBsb29wXG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgaWYgKGxhc3RMYXN0SW5kZXggPT09IHN0ci5sZW5ndGgpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChsYXN0TGVuZ3RoIHx8ICFzZXBhcmF0b3IudGVzdChcIlwiKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIG91dHB1dC5wdXNoKFwiXCIpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgb3V0cHV0LnB1c2goc3RyLnNsaWNlKGxhc3RMYXN0SW5kZXgpKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICByZXR1cm4gb3V0cHV0Lmxlbmd0aCA+IGxpbWl0ID8gb3V0cHV0LnNsaWNlKDAsIGxpbWl0KSA6IG91dHB1dDtcbiAgICAgICAgICAgICAgICB9O1xuXG4gICAgICAgICAgICAgICAgcmV0dXJuIHNlbGY7XG4gICAgICAgICAgICB9KCk7XG4gICAgICAgIH0sIHt9XSwgNjogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHt9LCB7fV0sIDc6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICAndXNlIHN0cmljdCc7XG5cbiAgICAgICAgICAgIHZhciBPbmVWZXJzaW9uQ29uc3RyYWludCA9IHJlcXVpcmUoJ2luZGl2aWR1YWwvb25lLXZlcnNpb24nKTtcblxuICAgICAgICAgICAgdmFyIE1ZX1ZFUlNJT04gPSAnNyc7XG4gICAgICAgICAgICBPbmVWZXJzaW9uQ29uc3RyYWludCgnZXYtc3RvcmUnLCBNWV9WRVJTSU9OKTtcblxuICAgICAgICAgICAgdmFyIGhhc2hLZXkgPSAnX19FVl9TVE9SRV9LRVlAJyArIE1ZX1ZFUlNJT047XG5cbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gRXZTdG9yZTtcblxuICAgICAgICAgICAgZnVuY3Rpb24gRXZTdG9yZShlbGVtKSB7XG4gICAgICAgICAgICAgICAgdmFyIGhhc2ggPSBlbGVtW2hhc2hLZXldO1xuXG4gICAgICAgICAgICAgICAgaWYgKCFoYXNoKSB7XG4gICAgICAgICAgICAgICAgICAgIGhhc2ggPSBlbGVtW2hhc2hLZXldID0ge307XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgcmV0dXJuIGhhc2g7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0sIHsgXCJpbmRpdmlkdWFsL29uZS12ZXJzaW9uXCI6IDkgfV0sIDg6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICAoZnVuY3Rpb24gKGdsb2JhbCkge1xuICAgICAgICAgICAgICAgICd1c2Ugc3RyaWN0JztcblxuICAgICAgICAgICAgICAgIC8qZ2xvYmFsIHdpbmRvdywgZ2xvYmFsKi9cblxuICAgICAgICAgICAgICAgIHZhciByb290ID0gdHlwZW9mIHdpbmRvdyAhPT0gJ3VuZGVmaW5lZCcgPyB3aW5kb3cgOiB0eXBlb2YgZ2xvYmFsICE9PSAndW5kZWZpbmVkJyA/IGdsb2JhbCA6IHt9O1xuXG4gICAgICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBJbmRpdmlkdWFsO1xuXG4gICAgICAgICAgICAgICAgZnVuY3Rpb24gSW5kaXZpZHVhbChrZXksIHZhbHVlKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmIChrZXkgaW4gcm9vdCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHJvb3Rba2V5XTtcbiAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgIHJvb3Rba2V5XSA9IHZhbHVlO1xuXG4gICAgICAgICAgICAgICAgICAgIHJldHVybiB2YWx1ZTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9KS5jYWxsKHRoaXMsIHR5cGVvZiBnbG9iYWwgIT09IFwidW5kZWZpbmVkXCIgPyBnbG9iYWwgOiB0eXBlb2Ygc2VsZiAhPT0gXCJ1bmRlZmluZWRcIiA/IHNlbGYgOiB0eXBlb2Ygd2luZG93ICE9PSBcInVuZGVmaW5lZFwiID8gd2luZG93IDoge30pO1xuICAgICAgICB9LCB7fV0sIDk6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICAndXNlIHN0cmljdCc7XG5cbiAgICAgICAgICAgIHZhciBJbmRpdmlkdWFsID0gcmVxdWlyZSgnLi9pbmRleC5qcycpO1xuXG4gICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IE9uZVZlcnNpb247XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIE9uZVZlcnNpb24obW9kdWxlTmFtZSwgdmVyc2lvbiwgZGVmYXVsdFZhbHVlKSB7XG4gICAgICAgICAgICAgICAgdmFyIGtleSA9ICdfX0lORElWSURVQUxfT05FX1ZFUlNJT05fJyArIG1vZHVsZU5hbWU7XG4gICAgICAgICAgICAgICAgdmFyIGVuZm9yY2VLZXkgPSBrZXkgKyAnX0VORk9SQ0VfU0lOR0xFVE9OJztcblxuICAgICAgICAgICAgICAgIHZhciB2ZXJzaW9uVmFsdWUgPSBJbmRpdmlkdWFsKGVuZm9yY2VLZXksIHZlcnNpb24pO1xuXG4gICAgICAgICAgICAgICAgaWYgKHZlcnNpb25WYWx1ZSAhPT0gdmVyc2lvbikge1xuICAgICAgICAgICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ0NhbiBvbmx5IGhhdmUgb25lIGNvcHkgb2YgJyArIG1vZHVsZU5hbWUgKyAnLlxcbicgKyAnWW91IGFscmVhZHkgaGF2ZSB2ZXJzaW9uICcgKyB2ZXJzaW9uVmFsdWUgKyAnIGluc3RhbGxlZC5cXG4nICsgJ1RoaXMgbWVhbnMgeW91IGNhbm5vdCBpbnN0YWxsIHZlcnNpb24gJyArIHZlcnNpb24pO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHJldHVybiBJbmRpdmlkdWFsKGtleSwgZGVmYXVsdFZhbHVlKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSwgeyBcIi4vaW5kZXguanNcIjogOCB9XSwgMTA6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICAoZnVuY3Rpb24gKGdsb2JhbCkge1xuICAgICAgICAgICAgICAgIHZhciB0b3BMZXZlbCA9IHR5cGVvZiBnbG9iYWwgIT09ICd1bmRlZmluZWQnID8gZ2xvYmFsIDogdHlwZW9mIHdpbmRvdyAhPT0gJ3VuZGVmaW5lZCcgPyB3aW5kb3cgOiB7fTtcbiAgICAgICAgICAgICAgICB2YXIgbWluRG9jID0gcmVxdWlyZSgnbWluLWRvY3VtZW50Jyk7XG5cbiAgICAgICAgICAgICAgICBpZiAodHlwZW9mIGRvY3VtZW50ICE9PSAndW5kZWZpbmVkJykge1xuICAgICAgICAgICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IGRvY3VtZW50O1xuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciBkb2NjeSA9IHRvcExldmVsWydfX0dMT0JBTF9ET0NVTUVOVF9DQUNIRUA0J107XG5cbiAgICAgICAgICAgICAgICAgICAgaWYgKCFkb2NjeSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgZG9jY3kgPSB0b3BMZXZlbFsnX19HTE9CQUxfRE9DVU1FTlRfQ0FDSEVANCddID0gbWluRG9jO1xuICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBkb2NjeTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9KS5jYWxsKHRoaXMsIHR5cGVvZiBnbG9iYWwgIT09IFwidW5kZWZpbmVkXCIgPyBnbG9iYWwgOiB0eXBlb2Ygc2VsZiAhPT0gXCJ1bmRlZmluZWRcIiA/IHNlbGYgOiB0eXBlb2Ygd2luZG93ICE9PSBcInVuZGVmaW5lZFwiID8gd2luZG93IDoge30pO1xuICAgICAgICB9LCB7IFwibWluLWRvY3VtZW50XCI6IDYgfV0sIDExOiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge1xuICAgICAgICAgICAgXCJ1c2Ugc3RyaWN0XCI7XG5cbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gaXNPYmplY3QoeCkge1xuICAgICAgICAgICAgICAgIHJldHVybiB0eXBlb2YgeCA9PT0gXCJvYmplY3RcIiAmJiB4ICE9PSBudWxsO1xuICAgICAgICAgICAgfTtcbiAgICAgICAgfSwge31dLCAxMjogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHtcbiAgICAgICAgICAgIHZhciBuYXRpdmVJc0FycmF5ID0gQXJyYXkuaXNBcnJheTtcbiAgICAgICAgICAgIHZhciB0b1N0cmluZyA9IE9iamVjdC5wcm90b3R5cGUudG9TdHJpbmc7XG5cbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gbmF0aXZlSXNBcnJheSB8fCBpc0FycmF5O1xuXG4gICAgICAgICAgICBmdW5jdGlvbiBpc0FycmF5KG9iaikge1xuICAgICAgICAgICAgICAgIHJldHVybiB0b1N0cmluZy5jYWxsKG9iaikgPT09IFwiW29iamVjdCBBcnJheV1cIjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSwge31dLCAxMzogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHtcbiAgICAgICAgICAgIHZhciBwYXRjaCA9IHJlcXVpcmUoXCIuL3Zkb20vcGF0Y2guanNcIik7XG5cbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gcGF0Y2g7XG4gICAgICAgIH0sIHsgXCIuL3Zkb20vcGF0Y2guanNcIjogMTggfV0sIDE0OiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge1xuICAgICAgICAgICAgdmFyIGlzT2JqZWN0ID0gcmVxdWlyZShcImlzLW9iamVjdFwiKTtcbiAgICAgICAgICAgIHZhciBpc0hvb2sgPSByZXF1aXJlKFwiLi4vdm5vZGUvaXMtdmhvb2suanNcIik7XG5cbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gYXBwbHlQcm9wZXJ0aWVzO1xuXG4gICAgICAgICAgICBmdW5jdGlvbiBhcHBseVByb3BlcnRpZXMobm9kZSwgcHJvcHMsIHByZXZpb3VzKSB7XG4gICAgICAgICAgICAgICAgZm9yICh2YXIgcHJvcE5hbWUgaW4gcHJvcHMpIHtcbiAgICAgICAgICAgICAgICAgICAgdmFyIHByb3BWYWx1ZSA9IHByb3BzW3Byb3BOYW1lXTtcblxuICAgICAgICAgICAgICAgICAgICBpZiAocHJvcFZhbHVlID09PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJlbW92ZVByb3BlcnR5KG5vZGUsIHByb3BOYW1lLCBwcm9wVmFsdWUsIHByZXZpb3VzKTtcbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIGlmIChpc0hvb2socHJvcFZhbHVlKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgcmVtb3ZlUHJvcGVydHkobm9kZSwgcHJvcE5hbWUsIHByb3BWYWx1ZSwgcHJldmlvdXMpO1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHByb3BWYWx1ZS5ob29rKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcHJvcFZhbHVlLmhvb2sobm9kZSwgcHJvcE5hbWUsIHByZXZpb3VzID8gcHJldmlvdXNbcHJvcE5hbWVdIDogdW5kZWZpbmVkKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChpc09iamVjdChwcm9wVmFsdWUpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcGF0Y2hPYmplY3Qobm9kZSwgcHJvcHMsIHByZXZpb3VzLCBwcm9wTmFtZSwgcHJvcFZhbHVlKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgbm9kZVtwcm9wTmFtZV0gPSBwcm9wVmFsdWU7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIHJlbW92ZVByb3BlcnR5KG5vZGUsIHByb3BOYW1lLCBwcm9wVmFsdWUsIHByZXZpb3VzKSB7XG4gICAgICAgICAgICAgICAgaWYgKHByZXZpb3VzKSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciBwcmV2aW91c1ZhbHVlID0gcHJldmlvdXNbcHJvcE5hbWVdO1xuXG4gICAgICAgICAgICAgICAgICAgIGlmICghaXNIb29rKHByZXZpb3VzVmFsdWUpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAocHJvcE5hbWUgPT09IFwiYXR0cmlidXRlc1wiKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgZm9yICh2YXIgYXR0ck5hbWUgaW4gcHJldmlvdXNWYWx1ZSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBub2RlLnJlbW92ZUF0dHJpYnV0ZShhdHRyTmFtZSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIGlmIChwcm9wTmFtZSA9PT0gXCJzdHlsZVwiKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgZm9yICh2YXIgaSBpbiBwcmV2aW91c1ZhbHVlKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG5vZGUuc3R5bGVbaV0gPSBcIlwiO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAodHlwZW9mIHByZXZpb3VzVmFsdWUgPT09IFwic3RyaW5nXCIpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBub2RlW3Byb3BOYW1lXSA9IFwiXCI7XG4gICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIG5vZGVbcHJvcE5hbWVdID0gbnVsbDtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIGlmIChwcmV2aW91c1ZhbHVlLnVuaG9vaykge1xuICAgICAgICAgICAgICAgICAgICAgICAgcHJldmlvdXNWYWx1ZS51bmhvb2sobm9kZSwgcHJvcE5hbWUsIHByb3BWYWx1ZSk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIHBhdGNoT2JqZWN0KG5vZGUsIHByb3BzLCBwcmV2aW91cywgcHJvcE5hbWUsIHByb3BWYWx1ZSkge1xuICAgICAgICAgICAgICAgIHZhciBwcmV2aW91c1ZhbHVlID0gcHJldmlvdXMgPyBwcmV2aW91c1twcm9wTmFtZV0gOiB1bmRlZmluZWQ7XG5cbiAgICAgICAgICAgICAgICAvLyBTZXQgYXR0cmlidXRlc1xuICAgICAgICAgICAgICAgIGlmIChwcm9wTmFtZSA9PT0gXCJhdHRyaWJ1dGVzXCIpIHtcbiAgICAgICAgICAgICAgICAgICAgZm9yICh2YXIgYXR0ck5hbWUgaW4gcHJvcFZhbHVlKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICB2YXIgYXR0clZhbHVlID0gcHJvcFZhbHVlW2F0dHJOYW1lXTtcblxuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGF0dHJWYWx1ZSA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgbm9kZS5yZW1vdmVBdHRyaWJ1dGUoYXR0ck5hbWUpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBub2RlLnNldEF0dHJpYnV0ZShhdHRyTmFtZSwgYXR0clZhbHVlKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICBpZiAocHJldmlvdXNWYWx1ZSAmJiBpc09iamVjdChwcmV2aW91c1ZhbHVlKSAmJiBnZXRQcm90b3R5cGUocHJldmlvdXNWYWx1ZSkgIT09IGdldFByb3RvdHlwZShwcm9wVmFsdWUpKSB7XG4gICAgICAgICAgICAgICAgICAgIG5vZGVbcHJvcE5hbWVdID0gcHJvcFZhbHVlO1xuICAgICAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgaWYgKCFpc09iamVjdChub2RlW3Byb3BOYW1lXSkpIHtcbiAgICAgICAgICAgICAgICAgICAgbm9kZVtwcm9wTmFtZV0gPSB7fTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICB2YXIgcmVwbGFjZXIgPSBwcm9wTmFtZSA9PT0gXCJzdHlsZVwiID8gXCJcIiA6IHVuZGVmaW5lZDtcblxuICAgICAgICAgICAgICAgIGZvciAodmFyIGsgaW4gcHJvcFZhbHVlKSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciB2YWx1ZSA9IHByb3BWYWx1ZVtrXTtcbiAgICAgICAgICAgICAgICAgICAgbm9kZVtwcm9wTmFtZV1ba10gPSB2YWx1ZSA9PT0gdW5kZWZpbmVkID8gcmVwbGFjZXIgOiB2YWx1ZTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIGdldFByb3RvdHlwZSh2YWx1ZSkge1xuICAgICAgICAgICAgICAgIGlmIChPYmplY3QuZ2V0UHJvdG90eXBlT2YpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIE9iamVjdC5nZXRQcm90b3R5cGVPZih2YWx1ZSk7XG4gICAgICAgICAgICAgICAgfSBlbHNlIGlmICh2YWx1ZS5fX3Byb3RvX18pIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHZhbHVlLl9fcHJvdG9fXztcbiAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKHZhbHVlLmNvbnN0cnVjdG9yKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiB2YWx1ZS5jb25zdHJ1Y3Rvci5wcm90b3R5cGU7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9LCB7IFwiLi4vdm5vZGUvaXMtdmhvb2suanNcIjogMjYsIFwiaXMtb2JqZWN0XCI6IDExIH1dLCAxNTogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHtcbiAgICAgICAgICAgIHZhciBkb2N1bWVudCA9IHJlcXVpcmUoXCJnbG9iYWwvZG9jdW1lbnRcIik7XG5cbiAgICAgICAgICAgIHZhciBhcHBseVByb3BlcnRpZXMgPSByZXF1aXJlKFwiLi9hcHBseS1wcm9wZXJ0aWVzXCIpO1xuXG4gICAgICAgICAgICB2YXIgaXNWTm9kZSA9IHJlcXVpcmUoXCIuLi92bm9kZS9pcy12bm9kZS5qc1wiKTtcbiAgICAgICAgICAgIHZhciBpc1ZUZXh0ID0gcmVxdWlyZShcIi4uL3Zub2RlL2lzLXZ0ZXh0LmpzXCIpO1xuICAgICAgICAgICAgdmFyIGlzV2lkZ2V0ID0gcmVxdWlyZShcIi4uL3Zub2RlL2lzLXdpZGdldC5qc1wiKTtcbiAgICAgICAgICAgIHZhciBoYW5kbGVUaHVuayA9IHJlcXVpcmUoXCIuLi92bm9kZS9oYW5kbGUtdGh1bmsuanNcIik7XG5cbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gY3JlYXRlRWxlbWVudDtcblxuICAgICAgICAgICAgZnVuY3Rpb24gY3JlYXRlRWxlbWVudCh2bm9kZSwgb3B0cykge1xuICAgICAgICAgICAgICAgIHZhciBkb2MgPSBvcHRzID8gb3B0cy5kb2N1bWVudCB8fCBkb2N1bWVudCA6IGRvY3VtZW50O1xuICAgICAgICAgICAgICAgIHZhciB3YXJuID0gb3B0cyA/IG9wdHMud2FybiA6IG51bGw7XG5cbiAgICAgICAgICAgICAgICB2bm9kZSA9IGhhbmRsZVRodW5rKHZub2RlKS5hO1xuXG4gICAgICAgICAgICAgICAgaWYgKGlzV2lkZ2V0KHZub2RlKSkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gdm5vZGUuaW5pdCgpO1xuICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoaXNWVGV4dCh2bm9kZSkpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGRvYy5jcmVhdGVUZXh0Tm9kZSh2bm9kZS50ZXh0KTtcbiAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKCFpc1ZOb2RlKHZub2RlKSkge1xuICAgICAgICAgICAgICAgICAgICBpZiAod2Fybikge1xuICAgICAgICAgICAgICAgICAgICAgICAgd2FybihcIkl0ZW0gaXMgbm90IGEgdmFsaWQgdmlydHVhbCBkb20gbm9kZVwiLCB2bm9kZSk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIG51bGw7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgdmFyIG5vZGUgPSB2bm9kZS5uYW1lc3BhY2UgPT09IG51bGwgPyBkb2MuY3JlYXRlRWxlbWVudCh2bm9kZS50YWdOYW1lKSA6IGRvYy5jcmVhdGVFbGVtZW50TlModm5vZGUubmFtZXNwYWNlLCB2bm9kZS50YWdOYW1lKTtcblxuICAgICAgICAgICAgICAgIHZhciBwcm9wcyA9IHZub2RlLnByb3BlcnRpZXM7XG4gICAgICAgICAgICAgICAgYXBwbHlQcm9wZXJ0aWVzKG5vZGUsIHByb3BzKTtcblxuICAgICAgICAgICAgICAgIHZhciBjaGlsZHJlbiA9IHZub2RlLmNoaWxkcmVuO1xuXG4gICAgICAgICAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCBjaGlsZHJlbi5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgICAgICAgICB2YXIgY2hpbGROb2RlID0gY3JlYXRlRWxlbWVudChjaGlsZHJlbltpXSwgb3B0cyk7XG4gICAgICAgICAgICAgICAgICAgIGlmIChjaGlsZE5vZGUpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIG5vZGUuYXBwZW5kQ2hpbGQoY2hpbGROb2RlKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHJldHVybiBub2RlO1xuICAgICAgICAgICAgfVxuICAgICAgICB9LCB7IFwiLi4vdm5vZGUvaGFuZGxlLXRodW5rLmpzXCI6IDI0LCBcIi4uL3Zub2RlL2lzLXZub2RlLmpzXCI6IDI3LCBcIi4uL3Zub2RlL2lzLXZ0ZXh0LmpzXCI6IDI4LCBcIi4uL3Zub2RlL2lzLXdpZGdldC5qc1wiOiAyOSwgXCIuL2FwcGx5LXByb3BlcnRpZXNcIjogMTQsIFwiZ2xvYmFsL2RvY3VtZW50XCI6IDEwIH1dLCAxNjogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHtcbiAgICAgICAgICAgIC8vIE1hcHMgYSB2aXJ0dWFsIERPTSB0cmVlIG9udG8gYSByZWFsIERPTSB0cmVlIGluIGFuIGVmZmljaWVudCBtYW5uZXIuXG4gICAgICAgICAgICAvLyBXZSBkb24ndCB3YW50IHRvIHJlYWQgYWxsIG9mIHRoZSBET00gbm9kZXMgaW4gdGhlIHRyZWUgc28gd2UgdXNlXG4gICAgICAgICAgICAvLyB0aGUgaW4tb3JkZXIgdHJlZSBpbmRleGluZyB0byBlbGltaW5hdGUgcmVjdXJzaW9uIGRvd24gY2VydGFpbiBicmFuY2hlcy5cbiAgICAgICAgICAgIC8vIFdlIG9ubHkgcmVjdXJzZSBpbnRvIGEgRE9NIG5vZGUgaWYgd2Uga25vdyB0aGF0IGl0IGNvbnRhaW5zIGEgY2hpbGQgb2ZcbiAgICAgICAgICAgIC8vIGludGVyZXN0LlxuXG4gICAgICAgICAgICB2YXIgbm9DaGlsZCA9IHt9O1xuXG4gICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IGRvbUluZGV4O1xuXG4gICAgICAgICAgICBmdW5jdGlvbiBkb21JbmRleChyb290Tm9kZSwgdHJlZSwgaW5kaWNlcywgbm9kZXMpIHtcbiAgICAgICAgICAgICAgICBpZiAoIWluZGljZXMgfHwgaW5kaWNlcy5sZW5ndGggPT09IDApIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHt9O1xuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIGluZGljZXMuc29ydChhc2NlbmRpbmcpO1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gcmVjdXJzZShyb290Tm9kZSwgdHJlZSwgaW5kaWNlcywgbm9kZXMsIDApO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZnVuY3Rpb24gcmVjdXJzZShyb290Tm9kZSwgdHJlZSwgaW5kaWNlcywgbm9kZXMsIHJvb3RJbmRleCkge1xuICAgICAgICAgICAgICAgIG5vZGVzID0gbm9kZXMgfHwge307XG5cbiAgICAgICAgICAgICAgICBpZiAocm9vdE5vZGUpIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKGluZGV4SW5SYW5nZShpbmRpY2VzLCByb290SW5kZXgsIHJvb3RJbmRleCkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIG5vZGVzW3Jvb3RJbmRleF0gPSByb290Tm9kZTtcbiAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgIHZhciB2Q2hpbGRyZW4gPSB0cmVlLmNoaWxkcmVuO1xuXG4gICAgICAgICAgICAgICAgICAgIGlmICh2Q2hpbGRyZW4pIHtcblxuICAgICAgICAgICAgICAgICAgICAgICAgdmFyIGNoaWxkTm9kZXMgPSByb290Tm9kZS5jaGlsZE5vZGVzO1xuXG4gICAgICAgICAgICAgICAgICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IHRyZWUuY2hpbGRyZW4ubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICByb290SW5kZXggKz0gMTtcblxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZhciB2Q2hpbGQgPSB2Q2hpbGRyZW5baV0gfHwgbm9DaGlsZDtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB2YXIgbmV4dEluZGV4ID0gcm9vdEluZGV4ICsgKHZDaGlsZC5jb3VudCB8fCAwKTtcblxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIHNraXAgcmVjdXJzaW9uIGRvd24gdGhlIHRyZWUgaWYgdGhlcmUgYXJlIG5vIG5vZGVzIGRvd24gaGVyZVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChpbmRleEluUmFuZ2UoaW5kaWNlcywgcm9vdEluZGV4LCBuZXh0SW5kZXgpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlY3Vyc2UoY2hpbGROb2Rlc1tpXSwgdkNoaWxkLCBpbmRpY2VzLCBub2Rlcywgcm9vdEluZGV4KTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICByb290SW5kZXggPSBuZXh0SW5kZXg7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICByZXR1cm4gbm9kZXM7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIC8vIEJpbmFyeSBzZWFyY2ggZm9yIGFuIGluZGV4IGluIHRoZSBpbnRlcnZhbCBbbGVmdCwgcmlnaHRdXG4gICAgICAgICAgICBmdW5jdGlvbiBpbmRleEluUmFuZ2UoaW5kaWNlcywgbGVmdCwgcmlnaHQpIHtcbiAgICAgICAgICAgICAgICBpZiAoaW5kaWNlcy5sZW5ndGggPT09IDApIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHZhciBtaW5JbmRleCA9IDA7XG4gICAgICAgICAgICAgICAgdmFyIG1heEluZGV4ID0gaW5kaWNlcy5sZW5ndGggLSAxO1xuICAgICAgICAgICAgICAgIHZhciBjdXJyZW50SW5kZXg7XG4gICAgICAgICAgICAgICAgdmFyIGN1cnJlbnRJdGVtO1xuXG4gICAgICAgICAgICAgICAgd2hpbGUgKG1pbkluZGV4IDw9IG1heEluZGV4KSB7XG4gICAgICAgICAgICAgICAgICAgIGN1cnJlbnRJbmRleCA9IChtYXhJbmRleCArIG1pbkluZGV4KSAvIDIgPj4gMDtcbiAgICAgICAgICAgICAgICAgICAgY3VycmVudEl0ZW0gPSBpbmRpY2VzW2N1cnJlbnRJbmRleF07XG5cbiAgICAgICAgICAgICAgICAgICAgaWYgKG1pbkluZGV4ID09PSBtYXhJbmRleCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGN1cnJlbnRJdGVtID49IGxlZnQgJiYgY3VycmVudEl0ZW0gPD0gcmlnaHQ7XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoY3VycmVudEl0ZW0gPCBsZWZ0KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBtaW5JbmRleCA9IGN1cnJlbnRJbmRleCArIDE7XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoY3VycmVudEl0ZW0gPiByaWdodCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgbWF4SW5kZXggPSBjdXJyZW50SW5kZXggLSAxO1xuICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIGFzY2VuZGluZyhhLCBiKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGEgPiBiID8gMSA6IC0xO1xuICAgICAgICAgICAgfVxuICAgICAgICB9LCB7fV0sIDE3OiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge1xuICAgICAgICAgICAgdmFyIGFwcGx5UHJvcGVydGllcyA9IHJlcXVpcmUoXCIuL2FwcGx5LXByb3BlcnRpZXNcIik7XG5cbiAgICAgICAgICAgIHZhciBpc1dpZGdldCA9IHJlcXVpcmUoXCIuLi92bm9kZS9pcy13aWRnZXQuanNcIik7XG4gICAgICAgICAgICB2YXIgVlBhdGNoID0gcmVxdWlyZShcIi4uL3Zub2RlL3ZwYXRjaC5qc1wiKTtcblxuICAgICAgICAgICAgdmFyIHVwZGF0ZVdpZGdldCA9IHJlcXVpcmUoXCIuL3VwZGF0ZS13aWRnZXRcIik7XG5cbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gYXBwbHlQYXRjaDtcblxuICAgICAgICAgICAgZnVuY3Rpb24gYXBwbHlQYXRjaCh2cGF0Y2gsIGRvbU5vZGUsIHJlbmRlck9wdGlvbnMpIHtcbiAgICAgICAgICAgICAgICB2YXIgdHlwZSA9IHZwYXRjaC50eXBlO1xuICAgICAgICAgICAgICAgIHZhciB2Tm9kZSA9IHZwYXRjaC52Tm9kZTtcbiAgICAgICAgICAgICAgICB2YXIgcGF0Y2ggPSB2cGF0Y2gucGF0Y2g7XG5cbiAgICAgICAgICAgICAgICBzd2l0Y2ggKHR5cGUpIHtcbiAgICAgICAgICAgICAgICAgICAgY2FzZSBWUGF0Y2guUkVNT1ZFOlxuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHJlbW92ZU5vZGUoZG9tTm9kZSwgdk5vZGUpO1xuICAgICAgICAgICAgICAgICAgICBjYXNlIFZQYXRjaC5JTlNFUlQ6XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gaW5zZXJ0Tm9kZShkb21Ob2RlLCBwYXRjaCwgcmVuZGVyT3B0aW9ucyk7XG4gICAgICAgICAgICAgICAgICAgIGNhc2UgVlBhdGNoLlZURVhUOlxuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHN0cmluZ1BhdGNoKGRvbU5vZGUsIHZOb2RlLCBwYXRjaCwgcmVuZGVyT3B0aW9ucyk7XG4gICAgICAgICAgICAgICAgICAgIGNhc2UgVlBhdGNoLldJREdFVDpcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiB3aWRnZXRQYXRjaChkb21Ob2RlLCB2Tm9kZSwgcGF0Y2gsIHJlbmRlck9wdGlvbnMpO1xuICAgICAgICAgICAgICAgICAgICBjYXNlIFZQYXRjaC5WTk9ERTpcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiB2Tm9kZVBhdGNoKGRvbU5vZGUsIHZOb2RlLCBwYXRjaCwgcmVuZGVyT3B0aW9ucyk7XG4gICAgICAgICAgICAgICAgICAgIGNhc2UgVlBhdGNoLk9SREVSOlxuICAgICAgICAgICAgICAgICAgICAgICAgcmVvcmRlckNoaWxkcmVuKGRvbU5vZGUsIHBhdGNoKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBkb21Ob2RlO1xuICAgICAgICAgICAgICAgICAgICBjYXNlIFZQYXRjaC5QUk9QUzpcbiAgICAgICAgICAgICAgICAgICAgICAgIGFwcGx5UHJvcGVydGllcyhkb21Ob2RlLCBwYXRjaCwgdk5vZGUucHJvcGVydGllcyk7XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gZG9tTm9kZTtcbiAgICAgICAgICAgICAgICAgICAgY2FzZSBWUGF0Y2guVEhVTks6XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gcmVwbGFjZVJvb3QoZG9tTm9kZSwgcmVuZGVyT3B0aW9ucy5wYXRjaChkb21Ob2RlLCBwYXRjaCwgcmVuZGVyT3B0aW9ucykpO1xuICAgICAgICAgICAgICAgICAgICBkZWZhdWx0OlxuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGRvbU5vZGU7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBmdW5jdGlvbiByZW1vdmVOb2RlKGRvbU5vZGUsIHZOb2RlKSB7XG4gICAgICAgICAgICAgICAgdmFyIHBhcmVudE5vZGUgPSBkb21Ob2RlLnBhcmVudE5vZGU7XG5cbiAgICAgICAgICAgICAgICBpZiAocGFyZW50Tm9kZSkge1xuICAgICAgICAgICAgICAgICAgICBwYXJlbnROb2RlLnJlbW92ZUNoaWxkKGRvbU5vZGUpO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIGRlc3Ryb3lXaWRnZXQoZG9tTm9kZSwgdk5vZGUpO1xuXG4gICAgICAgICAgICAgICAgcmV0dXJuIG51bGw7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIGluc2VydE5vZGUocGFyZW50Tm9kZSwgdk5vZGUsIHJlbmRlck9wdGlvbnMpIHtcbiAgICAgICAgICAgICAgICB2YXIgbmV3Tm9kZSA9IHJlbmRlck9wdGlvbnMucmVuZGVyKHZOb2RlLCByZW5kZXJPcHRpb25zKTtcblxuICAgICAgICAgICAgICAgIGlmIChwYXJlbnROb2RlKSB7XG4gICAgICAgICAgICAgICAgICAgIHBhcmVudE5vZGUuYXBwZW5kQ2hpbGQobmV3Tm9kZSk7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgcmV0dXJuIHBhcmVudE5vZGU7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIHN0cmluZ1BhdGNoKGRvbU5vZGUsIGxlZnRWTm9kZSwgdlRleHQsIHJlbmRlck9wdGlvbnMpIHtcbiAgICAgICAgICAgICAgICB2YXIgbmV3Tm9kZTtcblxuICAgICAgICAgICAgICAgIGlmIChkb21Ob2RlLm5vZGVUeXBlID09PSAzKSB7XG4gICAgICAgICAgICAgICAgICAgIGRvbU5vZGUucmVwbGFjZURhdGEoMCwgZG9tTm9kZS5sZW5ndGgsIHZUZXh0LnRleHQpO1xuICAgICAgICAgICAgICAgICAgICBuZXdOb2RlID0gZG9tTm9kZTtcbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICB2YXIgcGFyZW50Tm9kZSA9IGRvbU5vZGUucGFyZW50Tm9kZTtcbiAgICAgICAgICAgICAgICAgICAgbmV3Tm9kZSA9IHJlbmRlck9wdGlvbnMucmVuZGVyKHZUZXh0LCByZW5kZXJPcHRpb25zKTtcblxuICAgICAgICAgICAgICAgICAgICBpZiAocGFyZW50Tm9kZSAmJiBuZXdOb2RlICE9PSBkb21Ob2RlKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBwYXJlbnROb2RlLnJlcGxhY2VDaGlsZChuZXdOb2RlLCBkb21Ob2RlKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHJldHVybiBuZXdOb2RlO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBmdW5jdGlvbiB3aWRnZXRQYXRjaChkb21Ob2RlLCBsZWZ0Vk5vZGUsIHdpZGdldCwgcmVuZGVyT3B0aW9ucykge1xuICAgICAgICAgICAgICAgIHZhciB1cGRhdGluZyA9IHVwZGF0ZVdpZGdldChsZWZ0Vk5vZGUsIHdpZGdldCk7XG4gICAgICAgICAgICAgICAgdmFyIG5ld05vZGU7XG5cbiAgICAgICAgICAgICAgICBpZiAodXBkYXRpbmcpIHtcbiAgICAgICAgICAgICAgICAgICAgbmV3Tm9kZSA9IHdpZGdldC51cGRhdGUobGVmdFZOb2RlLCBkb21Ob2RlKSB8fCBkb21Ob2RlO1xuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIG5ld05vZGUgPSByZW5kZXJPcHRpb25zLnJlbmRlcih3aWRnZXQsIHJlbmRlck9wdGlvbnMpO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHZhciBwYXJlbnROb2RlID0gZG9tTm9kZS5wYXJlbnROb2RlO1xuXG4gICAgICAgICAgICAgICAgaWYgKHBhcmVudE5vZGUgJiYgbmV3Tm9kZSAhPT0gZG9tTm9kZSkge1xuICAgICAgICAgICAgICAgICAgICBwYXJlbnROb2RlLnJlcGxhY2VDaGlsZChuZXdOb2RlLCBkb21Ob2RlKTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICBpZiAoIXVwZGF0aW5nKSB7XG4gICAgICAgICAgICAgICAgICAgIGRlc3Ryb3lXaWRnZXQoZG9tTm9kZSwgbGVmdFZOb2RlKTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICByZXR1cm4gbmV3Tm9kZTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZnVuY3Rpb24gdk5vZGVQYXRjaChkb21Ob2RlLCBsZWZ0Vk5vZGUsIHZOb2RlLCByZW5kZXJPcHRpb25zKSB7XG4gICAgICAgICAgICAgICAgdmFyIHBhcmVudE5vZGUgPSBkb21Ob2RlLnBhcmVudE5vZGU7XG4gICAgICAgICAgICAgICAgdmFyIG5ld05vZGUgPSByZW5kZXJPcHRpb25zLnJlbmRlcih2Tm9kZSwgcmVuZGVyT3B0aW9ucyk7XG5cbiAgICAgICAgICAgICAgICBpZiAocGFyZW50Tm9kZSAmJiBuZXdOb2RlICE9PSBkb21Ob2RlKSB7XG4gICAgICAgICAgICAgICAgICAgIHBhcmVudE5vZGUucmVwbGFjZUNoaWxkKG5ld05vZGUsIGRvbU5vZGUpO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHJldHVybiBuZXdOb2RlO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBmdW5jdGlvbiBkZXN0cm95V2lkZ2V0KGRvbU5vZGUsIHcpIHtcbiAgICAgICAgICAgICAgICBpZiAodHlwZW9mIHcuZGVzdHJveSA9PT0gXCJmdW5jdGlvblwiICYmIGlzV2lkZ2V0KHcpKSB7XG4gICAgICAgICAgICAgICAgICAgIHcuZGVzdHJveShkb21Ob2RlKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIHJlb3JkZXJDaGlsZHJlbihkb21Ob2RlLCBtb3Zlcykge1xuICAgICAgICAgICAgICAgIHZhciBjaGlsZE5vZGVzID0gZG9tTm9kZS5jaGlsZE5vZGVzO1xuICAgICAgICAgICAgICAgIHZhciBrZXlNYXAgPSB7fTtcbiAgICAgICAgICAgICAgICB2YXIgbm9kZTtcbiAgICAgICAgICAgICAgICB2YXIgcmVtb3ZlO1xuICAgICAgICAgICAgICAgIHZhciBpbnNlcnQ7XG5cbiAgICAgICAgICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IG1vdmVzLnJlbW92ZXMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgICAgICAgICAgcmVtb3ZlID0gbW92ZXMucmVtb3Zlc1tpXTtcbiAgICAgICAgICAgICAgICAgICAgbm9kZSA9IGNoaWxkTm9kZXNbcmVtb3ZlLmZyb21dO1xuICAgICAgICAgICAgICAgICAgICBpZiAocmVtb3ZlLmtleSkge1xuICAgICAgICAgICAgICAgICAgICAgICAga2V5TWFwW3JlbW92ZS5rZXldID0gbm9kZTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICBkb21Ob2RlLnJlbW92ZUNoaWxkKG5vZGUpO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHZhciBsZW5ndGggPSBjaGlsZE5vZGVzLmxlbmd0aDtcbiAgICAgICAgICAgICAgICBmb3IgKHZhciBqID0gMDsgaiA8IG1vdmVzLmluc2VydHMubGVuZ3RoOyBqKyspIHtcbiAgICAgICAgICAgICAgICAgICAgaW5zZXJ0ID0gbW92ZXMuaW5zZXJ0c1tqXTtcbiAgICAgICAgICAgICAgICAgICAgbm9kZSA9IGtleU1hcFtpbnNlcnQua2V5XTtcbiAgICAgICAgICAgICAgICAgICAgLy8gdGhpcyBpcyB0aGUgd2VpcmRlc3QgYnVnIGkndmUgZXZlciBzZWVuIGluIHdlYmtpdFxuICAgICAgICAgICAgICAgICAgICBkb21Ob2RlLmluc2VydEJlZm9yZShub2RlLCBpbnNlcnQudG8gPj0gbGVuZ3RoKysgPyBudWxsIDogY2hpbGROb2Rlc1tpbnNlcnQudG9dKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIHJlcGxhY2VSb290KG9sZFJvb3QsIG5ld1Jvb3QpIHtcbiAgICAgICAgICAgICAgICBpZiAob2xkUm9vdCAmJiBuZXdSb290ICYmIG9sZFJvb3QgIT09IG5ld1Jvb3QgJiYgb2xkUm9vdC5wYXJlbnROb2RlKSB7XG4gICAgICAgICAgICAgICAgICAgIG9sZFJvb3QucGFyZW50Tm9kZS5yZXBsYWNlQ2hpbGQobmV3Um9vdCwgb2xkUm9vdCk7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgcmV0dXJuIG5ld1Jvb3Q7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0sIHsgXCIuLi92bm9kZS9pcy13aWRnZXQuanNcIjogMjksIFwiLi4vdm5vZGUvdnBhdGNoLmpzXCI6IDMyLCBcIi4vYXBwbHktcHJvcGVydGllc1wiOiAxNCwgXCIuL3VwZGF0ZS13aWRnZXRcIjogMTkgfV0sIDE4OiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge1xuICAgICAgICAgICAgdmFyIGRvY3VtZW50ID0gcmVxdWlyZShcImdsb2JhbC9kb2N1bWVudFwiKTtcbiAgICAgICAgICAgIHZhciBpc0FycmF5ID0gcmVxdWlyZShcIngtaXMtYXJyYXlcIik7XG5cbiAgICAgICAgICAgIHZhciByZW5kZXIgPSByZXF1aXJlKFwiLi9jcmVhdGUtZWxlbWVudFwiKTtcbiAgICAgICAgICAgIHZhciBkb21JbmRleCA9IHJlcXVpcmUoXCIuL2RvbS1pbmRleFwiKTtcbiAgICAgICAgICAgIHZhciBwYXRjaE9wID0gcmVxdWlyZShcIi4vcGF0Y2gtb3BcIik7XG4gICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IHBhdGNoO1xuXG4gICAgICAgICAgICBmdW5jdGlvbiBwYXRjaChyb290Tm9kZSwgcGF0Y2hlcywgcmVuZGVyT3B0aW9ucykge1xuICAgICAgICAgICAgICAgIHJlbmRlck9wdGlvbnMgPSByZW5kZXJPcHRpb25zIHx8IHt9O1xuICAgICAgICAgICAgICAgIHJlbmRlck9wdGlvbnMucGF0Y2ggPSByZW5kZXJPcHRpb25zLnBhdGNoICYmIHJlbmRlck9wdGlvbnMucGF0Y2ggIT09IHBhdGNoID8gcmVuZGVyT3B0aW9ucy5wYXRjaCA6IHBhdGNoUmVjdXJzaXZlO1xuICAgICAgICAgICAgICAgIHJlbmRlck9wdGlvbnMucmVuZGVyID0gcmVuZGVyT3B0aW9ucy5yZW5kZXIgfHwgcmVuZGVyO1xuXG4gICAgICAgICAgICAgICAgcmV0dXJuIHJlbmRlck9wdGlvbnMucGF0Y2gocm9vdE5vZGUsIHBhdGNoZXMsIHJlbmRlck9wdGlvbnMpO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBmdW5jdGlvbiBwYXRjaFJlY3Vyc2l2ZShyb290Tm9kZSwgcGF0Y2hlcywgcmVuZGVyT3B0aW9ucykge1xuICAgICAgICAgICAgICAgIHZhciBpbmRpY2VzID0gcGF0Y2hJbmRpY2VzKHBhdGNoZXMpO1xuXG4gICAgICAgICAgICAgICAgaWYgKGluZGljZXMubGVuZ3RoID09PSAwKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiByb290Tm9kZTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICB2YXIgaW5kZXggPSBkb21JbmRleChyb290Tm9kZSwgcGF0Y2hlcy5hLCBpbmRpY2VzKTtcbiAgICAgICAgICAgICAgICB2YXIgb3duZXJEb2N1bWVudCA9IHJvb3ROb2RlLm93bmVyRG9jdW1lbnQ7XG5cbiAgICAgICAgICAgICAgICBpZiAoIXJlbmRlck9wdGlvbnMuZG9jdW1lbnQgJiYgb3duZXJEb2N1bWVudCAhPT0gZG9jdW1lbnQpIHtcbiAgICAgICAgICAgICAgICAgICAgcmVuZGVyT3B0aW9ucy5kb2N1bWVudCA9IG93bmVyRG9jdW1lbnQ7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCBpbmRpY2VzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciBub2RlSW5kZXggPSBpbmRpY2VzW2ldO1xuICAgICAgICAgICAgICAgICAgICByb290Tm9kZSA9IGFwcGx5UGF0Y2gocm9vdE5vZGUsIGluZGV4W25vZGVJbmRleF0sIHBhdGNoZXNbbm9kZUluZGV4XSwgcmVuZGVyT3B0aW9ucyk7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgcmV0dXJuIHJvb3ROb2RlO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBmdW5jdGlvbiBhcHBseVBhdGNoKHJvb3ROb2RlLCBkb21Ob2RlLCBwYXRjaExpc3QsIHJlbmRlck9wdGlvbnMpIHtcbiAgICAgICAgICAgICAgICBpZiAoIWRvbU5vZGUpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHJvb3ROb2RlO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHZhciBuZXdOb2RlO1xuXG4gICAgICAgICAgICAgICAgaWYgKGlzQXJyYXkocGF0Y2hMaXN0KSkge1xuICAgICAgICAgICAgICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IHBhdGNoTGlzdC5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgICAgICAgICAgICAgbmV3Tm9kZSA9IHBhdGNoT3AocGF0Y2hMaXN0W2ldLCBkb21Ob2RlLCByZW5kZXJPcHRpb25zKTtcblxuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGRvbU5vZGUgPT09IHJvb3ROb2RlKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcm9vdE5vZGUgPSBuZXdOb2RlO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgbmV3Tm9kZSA9IHBhdGNoT3AocGF0Y2hMaXN0LCBkb21Ob2RlLCByZW5kZXJPcHRpb25zKTtcblxuICAgICAgICAgICAgICAgICAgICBpZiAoZG9tTm9kZSA9PT0gcm9vdE5vZGUpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJvb3ROb2RlID0gbmV3Tm9kZTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHJldHVybiByb290Tm9kZTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZnVuY3Rpb24gcGF0Y2hJbmRpY2VzKHBhdGNoZXMpIHtcbiAgICAgICAgICAgICAgICB2YXIgaW5kaWNlcyA9IFtdO1xuXG4gICAgICAgICAgICAgICAgZm9yICh2YXIga2V5IGluIHBhdGNoZXMpIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKGtleSAhPT0gXCJhXCIpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGluZGljZXMucHVzaChOdW1iZXIoa2V5KSk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICByZXR1cm4gaW5kaWNlcztcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSwgeyBcIi4vY3JlYXRlLWVsZW1lbnRcIjogMTUsIFwiLi9kb20taW5kZXhcIjogMTYsIFwiLi9wYXRjaC1vcFwiOiAxNywgXCJnbG9iYWwvZG9jdW1lbnRcIjogMTAsIFwieC1pcy1hcnJheVwiOiAxMiB9XSwgMTk6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICB2YXIgaXNXaWRnZXQgPSByZXF1aXJlKFwiLi4vdm5vZGUvaXMtd2lkZ2V0LmpzXCIpO1xuXG4gICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IHVwZGF0ZVdpZGdldDtcblxuICAgICAgICAgICAgZnVuY3Rpb24gdXBkYXRlV2lkZ2V0KGEsIGIpIHtcbiAgICAgICAgICAgICAgICBpZiAoaXNXaWRnZXQoYSkgJiYgaXNXaWRnZXQoYikpIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKFwibmFtZVwiIGluIGEgJiYgXCJuYW1lXCIgaW4gYikge1xuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGEuaWQgPT09IGIuaWQ7XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gYS5pbml0ID09PSBiLmluaXQ7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0sIHsgXCIuLi92bm9kZS9pcy13aWRnZXQuanNcIjogMjkgfV0sIDIwOiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge1xuICAgICAgICAgICAgJ3VzZSBzdHJpY3QnO1xuXG4gICAgICAgICAgICB2YXIgRXZTdG9yZSA9IHJlcXVpcmUoJ2V2LXN0b3JlJyk7XG5cbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gRXZIb29rO1xuXG4gICAgICAgICAgICBmdW5jdGlvbiBFdkhvb2sodmFsdWUpIHtcbiAgICAgICAgICAgICAgICBpZiAoISh0aGlzIGluc3RhbmNlb2YgRXZIb29rKSkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gbmV3IEV2SG9vayh2YWx1ZSk7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgdGhpcy52YWx1ZSA9IHZhbHVlO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBFdkhvb2sucHJvdG90eXBlLmhvb2sgPSBmdW5jdGlvbiAobm9kZSwgcHJvcGVydHlOYW1lKSB7XG4gICAgICAgICAgICAgICAgdmFyIGVzID0gRXZTdG9yZShub2RlKTtcbiAgICAgICAgICAgICAgICB2YXIgcHJvcE5hbWUgPSBwcm9wZXJ0eU5hbWUuc3Vic3RyKDMpO1xuXG4gICAgICAgICAgICAgICAgZXNbcHJvcE5hbWVdID0gdGhpcy52YWx1ZTtcbiAgICAgICAgICAgIH07XG5cbiAgICAgICAgICAgIEV2SG9vay5wcm90b3R5cGUudW5ob29rID0gZnVuY3Rpb24gKG5vZGUsIHByb3BlcnR5TmFtZSkge1xuICAgICAgICAgICAgICAgIHZhciBlcyA9IEV2U3RvcmUobm9kZSk7XG4gICAgICAgICAgICAgICAgdmFyIHByb3BOYW1lID0gcHJvcGVydHlOYW1lLnN1YnN0cigzKTtcblxuICAgICAgICAgICAgICAgIGVzW3Byb3BOYW1lXSA9IHVuZGVmaW5lZDtcbiAgICAgICAgICAgIH07XG4gICAgICAgIH0sIHsgXCJldi1zdG9yZVwiOiA3IH1dLCAyMTogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHtcbiAgICAgICAgICAgICd1c2Ugc3RyaWN0JztcblxuICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBTb2Z0U2V0SG9vaztcblxuICAgICAgICAgICAgZnVuY3Rpb24gU29mdFNldEhvb2sodmFsdWUpIHtcbiAgICAgICAgICAgICAgICBpZiAoISh0aGlzIGluc3RhbmNlb2YgU29mdFNldEhvb2spKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBuZXcgU29mdFNldEhvb2sodmFsdWUpO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHRoaXMudmFsdWUgPSB2YWx1ZTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgU29mdFNldEhvb2sucHJvdG90eXBlLmhvb2sgPSBmdW5jdGlvbiAobm9kZSwgcHJvcGVydHlOYW1lKSB7XG4gICAgICAgICAgICAgICAgaWYgKG5vZGVbcHJvcGVydHlOYW1lXSAhPT0gdGhpcy52YWx1ZSkge1xuICAgICAgICAgICAgICAgICAgICBub2RlW3Byb3BlcnR5TmFtZV0gPSB0aGlzLnZhbHVlO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH07XG4gICAgICAgIH0sIHt9XSwgMjI6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICAndXNlIHN0cmljdCc7XG5cbiAgICAgICAgICAgIHZhciBpc0FycmF5ID0gcmVxdWlyZSgneC1pcy1hcnJheScpO1xuXG4gICAgICAgICAgICB2YXIgVk5vZGUgPSByZXF1aXJlKCcuLi92bm9kZS92bm9kZS5qcycpO1xuICAgICAgICAgICAgdmFyIFZUZXh0ID0gcmVxdWlyZSgnLi4vdm5vZGUvdnRleHQuanMnKTtcbiAgICAgICAgICAgIHZhciBpc1ZOb2RlID0gcmVxdWlyZSgnLi4vdm5vZGUvaXMtdm5vZGUnKTtcbiAgICAgICAgICAgIHZhciBpc1ZUZXh0ID0gcmVxdWlyZSgnLi4vdm5vZGUvaXMtdnRleHQnKTtcbiAgICAgICAgICAgIHZhciBpc1dpZGdldCA9IHJlcXVpcmUoJy4uL3Zub2RlL2lzLXdpZGdldCcpO1xuICAgICAgICAgICAgdmFyIGlzSG9vayA9IHJlcXVpcmUoJy4uL3Zub2RlL2lzLXZob29rJyk7XG4gICAgICAgICAgICB2YXIgaXNWVGh1bmsgPSByZXF1aXJlKCcuLi92bm9kZS9pcy10aHVuaycpO1xuXG4gICAgICAgICAgICB2YXIgcGFyc2VUYWcgPSByZXF1aXJlKCcuL3BhcnNlLXRhZy5qcycpO1xuICAgICAgICAgICAgdmFyIHNvZnRTZXRIb29rID0gcmVxdWlyZSgnLi9ob29rcy9zb2Z0LXNldC1ob29rLmpzJyk7XG4gICAgICAgICAgICB2YXIgZXZIb29rID0gcmVxdWlyZSgnLi9ob29rcy9ldi1ob29rLmpzJyk7XG5cbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gaDtcblxuICAgICAgICAgICAgZnVuY3Rpb24gaCh0YWdOYW1lLCBwcm9wZXJ0aWVzLCBjaGlsZHJlbikge1xuICAgICAgICAgICAgICAgIHZhciBjaGlsZE5vZGVzID0gW107XG4gICAgICAgICAgICAgICAgdmFyIHRhZywgcHJvcHMsIGtleSwgbmFtZXNwYWNlO1xuXG4gICAgICAgICAgICAgICAgaWYgKCFjaGlsZHJlbiAmJiBpc0NoaWxkcmVuKHByb3BlcnRpZXMpKSB7XG4gICAgICAgICAgICAgICAgICAgIGNoaWxkcmVuID0gcHJvcGVydGllcztcbiAgICAgICAgICAgICAgICAgICAgcHJvcHMgPSB7fTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICBwcm9wcyA9IHByb3BzIHx8IHByb3BlcnRpZXMgfHwge307XG4gICAgICAgICAgICAgICAgdGFnID0gcGFyc2VUYWcodGFnTmFtZSwgcHJvcHMpO1xuXG4gICAgICAgICAgICAgICAgLy8gc3VwcG9ydCBrZXlzXG4gICAgICAgICAgICAgICAgaWYgKHByb3BzLmhhc093blByb3BlcnR5KCdrZXknKSkge1xuICAgICAgICAgICAgICAgICAgICBrZXkgPSBwcm9wcy5rZXk7XG4gICAgICAgICAgICAgICAgICAgIHByb3BzLmtleSA9IHVuZGVmaW5lZDtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAvLyBzdXBwb3J0IG5hbWVzcGFjZVxuICAgICAgICAgICAgICAgIGlmIChwcm9wcy5oYXNPd25Qcm9wZXJ0eSgnbmFtZXNwYWNlJykpIHtcbiAgICAgICAgICAgICAgICAgICAgbmFtZXNwYWNlID0gcHJvcHMubmFtZXNwYWNlO1xuICAgICAgICAgICAgICAgICAgICBwcm9wcy5uYW1lc3BhY2UgPSB1bmRlZmluZWQ7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgLy8gZml4IGN1cnNvciBidWdcbiAgICAgICAgICAgICAgICBpZiAodGFnID09PSAnSU5QVVQnICYmICFuYW1lc3BhY2UgJiYgcHJvcHMuaGFzT3duUHJvcGVydHkoJ3ZhbHVlJykgJiYgcHJvcHMudmFsdWUgIT09IHVuZGVmaW5lZCAmJiAhaXNIb29rKHByb3BzLnZhbHVlKSkge1xuICAgICAgICAgICAgICAgICAgICBwcm9wcy52YWx1ZSA9IHNvZnRTZXRIb29rKHByb3BzLnZhbHVlKTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICB0cmFuc2Zvcm1Qcm9wZXJ0aWVzKHByb3BzKTtcblxuICAgICAgICAgICAgICAgIGlmIChjaGlsZHJlbiAhPT0gdW5kZWZpbmVkICYmIGNoaWxkcmVuICE9PSBudWxsKSB7XG4gICAgICAgICAgICAgICAgICAgIGFkZENoaWxkKGNoaWxkcmVuLCBjaGlsZE5vZGVzLCB0YWcsIHByb3BzKTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICByZXR1cm4gbmV3IFZOb2RlKHRhZywgcHJvcHMsIGNoaWxkTm9kZXMsIGtleSwgbmFtZXNwYWNlKTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZnVuY3Rpb24gYWRkQ2hpbGQoYywgY2hpbGROb2RlcywgdGFnLCBwcm9wcykge1xuICAgICAgICAgICAgICAgIGlmICh0eXBlb2YgYyA9PT0gJ3N0cmluZycpIHtcbiAgICAgICAgICAgICAgICAgICAgY2hpbGROb2Rlcy5wdXNoKG5ldyBWVGV4dChjKSk7XG4gICAgICAgICAgICAgICAgfSBlbHNlIGlmICh0eXBlb2YgYyA9PT0gJ251bWJlcicpIHtcbiAgICAgICAgICAgICAgICAgICAgY2hpbGROb2Rlcy5wdXNoKG5ldyBWVGV4dChTdHJpbmcoYykpKTtcbiAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKGlzQ2hpbGQoYykpIHtcbiAgICAgICAgICAgICAgICAgICAgY2hpbGROb2Rlcy5wdXNoKGMpO1xuICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoaXNBcnJheShjKSkge1xuICAgICAgICAgICAgICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IGMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGFkZENoaWxkKGNbaV0sIGNoaWxkTm9kZXMsIHRhZywgcHJvcHMpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfSBlbHNlIGlmIChjID09PSBudWxsIHx8IGMgPT09IHVuZGVmaW5lZCkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgdGhyb3cgVW5leHBlY3RlZFZpcnR1YWxFbGVtZW50KHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGZvcmVpZ25PYmplY3Q6IGMsXG4gICAgICAgICAgICAgICAgICAgICAgICBwYXJlbnRWbm9kZToge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRhZ05hbWU6IHRhZyxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBwcm9wZXJ0aWVzOiBwcm9wc1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIHRyYW5zZm9ybVByb3BlcnRpZXMocHJvcHMpIHtcbiAgICAgICAgICAgICAgICBmb3IgKHZhciBwcm9wTmFtZSBpbiBwcm9wcykge1xuICAgICAgICAgICAgICAgICAgICBpZiAocHJvcHMuaGFzT3duUHJvcGVydHkocHJvcE5hbWUpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICB2YXIgdmFsdWUgPSBwcm9wc1twcm9wTmFtZV07XG5cbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChpc0hvb2sodmFsdWUpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgY29udGludWU7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChwcm9wTmFtZS5zdWJzdHIoMCwgMykgPT09ICdldi0nKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gYWRkIGV2LWZvbyBzdXBwb3J0XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcHJvcHNbcHJvcE5hbWVdID0gZXZIb29rKHZhbHVlKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZnVuY3Rpb24gaXNDaGlsZCh4KSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGlzVk5vZGUoeCkgfHwgaXNWVGV4dCh4KSB8fCBpc1dpZGdldCh4KSB8fCBpc1ZUaHVuayh4KTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZnVuY3Rpb24gaXNDaGlsZHJlbih4KSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHR5cGVvZiB4ID09PSAnc3RyaW5nJyB8fCBpc0FycmF5KHgpIHx8IGlzQ2hpbGQoeCk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIFVuZXhwZWN0ZWRWaXJ0dWFsRWxlbWVudChkYXRhKSB7XG4gICAgICAgICAgICAgICAgdmFyIGVyciA9IG5ldyBFcnJvcigpO1xuXG4gICAgICAgICAgICAgICAgZXJyLnR5cGUgPSAndmlydHVhbC1oeXBlcnNjcmlwdC51bmV4cGVjdGVkLnZpcnR1YWwtZWxlbWVudCc7XG4gICAgICAgICAgICAgICAgZXJyLm1lc3NhZ2UgPSAnVW5leHBlY3RlZCB2aXJ0dWFsIGNoaWxkIHBhc3NlZCB0byBoKCkuXFxuJyArICdFeHBlY3RlZCBhIFZOb2RlIC8gVnRodW5rIC8gVldpZGdldCAvIHN0cmluZyBidXQ6XFxuJyArICdnb3Q6XFxuJyArIGVycm9yU3RyaW5nKGRhdGEuZm9yZWlnbk9iamVjdCkgKyAnLlxcbicgKyAnVGhlIHBhcmVudCB2bm9kZSBpczpcXG4nICsgZXJyb3JTdHJpbmcoZGF0YS5wYXJlbnRWbm9kZSk7XG4gICAgICAgICAgICAgICAgJ1xcbicgKyAnU3VnZ2VzdGVkIGZpeDogY2hhbmdlIHlvdXIgYGgoLi4uLCBbIC4uLiBdKWAgY2FsbHNpdGUuJztcbiAgICAgICAgICAgICAgICBlcnIuZm9yZWlnbk9iamVjdCA9IGRhdGEuZm9yZWlnbk9iamVjdDtcbiAgICAgICAgICAgICAgICBlcnIucGFyZW50Vm5vZGUgPSBkYXRhLnBhcmVudFZub2RlO1xuXG4gICAgICAgICAgICAgICAgcmV0dXJuIGVycjtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZnVuY3Rpb24gZXJyb3JTdHJpbmcob2JqKSB7XG4gICAgICAgICAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIEpTT04uc3RyaW5naWZ5KG9iaiwgbnVsbCwgJyAgICAnKTtcbiAgICAgICAgICAgICAgICB9IGNhdGNoIChlKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBTdHJpbmcob2JqKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH0sIHsgXCIuLi92bm9kZS9pcy10aHVua1wiOiAyNSwgXCIuLi92bm9kZS9pcy12aG9va1wiOiAyNiwgXCIuLi92bm9kZS9pcy12bm9kZVwiOiAyNywgXCIuLi92bm9kZS9pcy12dGV4dFwiOiAyOCwgXCIuLi92bm9kZS9pcy13aWRnZXRcIjogMjksIFwiLi4vdm5vZGUvdm5vZGUuanNcIjogMzEsIFwiLi4vdm5vZGUvdnRleHQuanNcIjogMzMsIFwiLi9ob29rcy9ldi1ob29rLmpzXCI6IDIwLCBcIi4vaG9va3Mvc29mdC1zZXQtaG9vay5qc1wiOiAyMSwgXCIuL3BhcnNlLXRhZy5qc1wiOiAyMywgXCJ4LWlzLWFycmF5XCI6IDEyIH1dLCAyMzogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHtcbiAgICAgICAgICAgICd1c2Ugc3RyaWN0JztcblxuICAgICAgICAgICAgdmFyIHNwbGl0ID0gcmVxdWlyZSgnYnJvd3Nlci1zcGxpdCcpO1xuXG4gICAgICAgICAgICB2YXIgY2xhc3NJZFNwbGl0ID0gLyhbXFwuI10/W2EtekEtWjAtOVxcdTAwN0YtXFx1RkZGRl86LV0rKS87XG4gICAgICAgICAgICB2YXIgbm90Q2xhc3NJZCA9IC9eXFwufCMvO1xuXG4gICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IHBhcnNlVGFnO1xuXG4gICAgICAgICAgICBmdW5jdGlvbiBwYXJzZVRhZyh0YWcsIHByb3BzKSB7XG4gICAgICAgICAgICAgICAgaWYgKCF0YWcpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuICdESVYnO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHZhciBub0lkID0gIXByb3BzLmhhc093blByb3BlcnR5KCdpZCcpO1xuXG4gICAgICAgICAgICAgICAgdmFyIHRhZ1BhcnRzID0gc3BsaXQodGFnLCBjbGFzc0lkU3BsaXQpO1xuICAgICAgICAgICAgICAgIHZhciB0YWdOYW1lID0gbnVsbDtcblxuICAgICAgICAgICAgICAgIGlmIChub3RDbGFzc0lkLnRlc3QodGFnUGFydHNbMV0pKSB7XG4gICAgICAgICAgICAgICAgICAgIHRhZ05hbWUgPSAnRElWJztcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICB2YXIgY2xhc3NlcywgcGFydCwgdHlwZSwgaTtcblxuICAgICAgICAgICAgICAgIGZvciAoaSA9IDA7IGkgPCB0YWdQYXJ0cy5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgICAgICAgICBwYXJ0ID0gdGFnUGFydHNbaV07XG5cbiAgICAgICAgICAgICAgICAgICAgaWYgKCFwYXJ0KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBjb250aW51ZTtcbiAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgIHR5cGUgPSBwYXJ0LmNoYXJBdCgwKTtcblxuICAgICAgICAgICAgICAgICAgICBpZiAoIXRhZ05hbWUpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHRhZ05hbWUgPSBwYXJ0O1xuICAgICAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKHR5cGUgPT09ICcuJykge1xuICAgICAgICAgICAgICAgICAgICAgICAgY2xhc3NlcyA9IGNsYXNzZXMgfHwgW107XG4gICAgICAgICAgICAgICAgICAgICAgICBjbGFzc2VzLnB1c2gocGFydC5zdWJzdHJpbmcoMSwgcGFydC5sZW5ndGgpKTtcbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIGlmICh0eXBlID09PSAnIycgJiYgbm9JZCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgcHJvcHMuaWQgPSBwYXJ0LnN1YnN0cmluZygxLCBwYXJ0Lmxlbmd0aCk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICBpZiAoY2xhc3Nlcykge1xuICAgICAgICAgICAgICAgICAgICBpZiAocHJvcHMuY2xhc3NOYW1lKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBjbGFzc2VzLnB1c2gocHJvcHMuY2xhc3NOYW1lKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgIHByb3BzLmNsYXNzTmFtZSA9IGNsYXNzZXMuam9pbignICcpO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHJldHVybiBwcm9wcy5uYW1lc3BhY2UgPyB0YWdOYW1lIDogdGFnTmFtZS50b1VwcGVyQ2FzZSgpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9LCB7IFwiYnJvd3Nlci1zcGxpdFwiOiA1IH1dLCAyNDogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHtcbiAgICAgICAgICAgIHZhciBpc1ZOb2RlID0gcmVxdWlyZShcIi4vaXMtdm5vZGVcIik7XG4gICAgICAgICAgICB2YXIgaXNWVGV4dCA9IHJlcXVpcmUoXCIuL2lzLXZ0ZXh0XCIpO1xuICAgICAgICAgICAgdmFyIGlzV2lkZ2V0ID0gcmVxdWlyZShcIi4vaXMtd2lkZ2V0XCIpO1xuICAgICAgICAgICAgdmFyIGlzVGh1bmsgPSByZXF1aXJlKFwiLi9pcy10aHVua1wiKTtcblxuICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBoYW5kbGVUaHVuaztcblxuICAgICAgICAgICAgZnVuY3Rpb24gaGFuZGxlVGh1bmsoYSwgYikge1xuICAgICAgICAgICAgICAgIHZhciByZW5kZXJlZEEgPSBhO1xuICAgICAgICAgICAgICAgIHZhciByZW5kZXJlZEIgPSBiO1xuXG4gICAgICAgICAgICAgICAgaWYgKGlzVGh1bmsoYikpIHtcbiAgICAgICAgICAgICAgICAgICAgcmVuZGVyZWRCID0gcmVuZGVyVGh1bmsoYiwgYSk7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgaWYgKGlzVGh1bmsoYSkpIHtcbiAgICAgICAgICAgICAgICAgICAgcmVuZGVyZWRBID0gcmVuZGVyVGh1bmsoYSwgbnVsbCk7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgICAgICAgICAgYTogcmVuZGVyZWRBLFxuICAgICAgICAgICAgICAgICAgICBiOiByZW5kZXJlZEJcbiAgICAgICAgICAgICAgICB9O1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBmdW5jdGlvbiByZW5kZXJUaHVuayh0aHVuaywgcHJldmlvdXMpIHtcbiAgICAgICAgICAgICAgICB2YXIgcmVuZGVyZWRUaHVuayA9IHRodW5rLnZub2RlO1xuXG4gICAgICAgICAgICAgICAgaWYgKCFyZW5kZXJlZFRodW5rKSB7XG4gICAgICAgICAgICAgICAgICAgIHJlbmRlcmVkVGh1bmsgPSB0aHVuay52bm9kZSA9IHRodW5rLnJlbmRlcihwcmV2aW91cyk7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgaWYgKCEoaXNWTm9kZShyZW5kZXJlZFRodW5rKSB8fCBpc1ZUZXh0KHJlbmRlcmVkVGh1bmspIHx8IGlzV2lkZ2V0KHJlbmRlcmVkVGh1bmspKSkge1xuICAgICAgICAgICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoXCJ0aHVuayBkaWQgbm90IHJldHVybiBhIHZhbGlkIG5vZGVcIik7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgcmV0dXJuIHJlbmRlcmVkVGh1bms7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0sIHsgXCIuL2lzLXRodW5rXCI6IDI1LCBcIi4vaXMtdm5vZGVcIjogMjcsIFwiLi9pcy12dGV4dFwiOiAyOCwgXCIuL2lzLXdpZGdldFwiOiAyOSB9XSwgMjU6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IGlzVGh1bms7XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIGlzVGh1bmsodCkge1xuICAgICAgICAgICAgICAgIHJldHVybiB0ICYmIHQudHlwZSA9PT0gXCJUaHVua1wiO1xuICAgICAgICAgICAgfVxuICAgICAgICB9LCB7fV0sIDI2OiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge1xuICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBpc0hvb2s7XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIGlzSG9vayhob29rKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGhvb2sgJiYgKHR5cGVvZiBob29rLmhvb2sgPT09IFwiZnVuY3Rpb25cIiAmJiAhaG9vay5oYXNPd25Qcm9wZXJ0eShcImhvb2tcIikgfHwgdHlwZW9mIGhvb2sudW5ob29rID09PSBcImZ1bmN0aW9uXCIgJiYgIWhvb2suaGFzT3duUHJvcGVydHkoXCJ1bmhvb2tcIikpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9LCB7fV0sIDI3OiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge1xuICAgICAgICAgICAgdmFyIHZlcnNpb24gPSByZXF1aXJlKFwiLi92ZXJzaW9uXCIpO1xuXG4gICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IGlzVmlydHVhbE5vZGU7XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIGlzVmlydHVhbE5vZGUoeCkge1xuICAgICAgICAgICAgICAgIHJldHVybiB4ICYmIHgudHlwZSA9PT0gXCJWaXJ0dWFsTm9kZVwiICYmIHgudmVyc2lvbiA9PT0gdmVyc2lvbjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSwgeyBcIi4vdmVyc2lvblwiOiAzMCB9XSwgMjg6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICB2YXIgdmVyc2lvbiA9IHJlcXVpcmUoXCIuL3ZlcnNpb25cIik7XG5cbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gaXNWaXJ0dWFsVGV4dDtcblxuICAgICAgICAgICAgZnVuY3Rpb24gaXNWaXJ0dWFsVGV4dCh4KSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHggJiYgeC50eXBlID09PSBcIlZpcnR1YWxUZXh0XCIgJiYgeC52ZXJzaW9uID09PSB2ZXJzaW9uO1xuICAgICAgICAgICAgfVxuICAgICAgICB9LCB7IFwiLi92ZXJzaW9uXCI6IDMwIH1dLCAyOTogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHtcbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gaXNXaWRnZXQ7XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIGlzV2lkZ2V0KHcpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gdyAmJiB3LnR5cGUgPT09IFwiV2lkZ2V0XCI7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0sIHt9XSwgMzA6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IFwiMlwiO1xuICAgICAgICB9LCB7fV0sIDMxOiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge1xuICAgICAgICAgICAgdmFyIHZlcnNpb24gPSByZXF1aXJlKFwiLi92ZXJzaW9uXCIpO1xuICAgICAgICAgICAgdmFyIGlzVk5vZGUgPSByZXF1aXJlKFwiLi9pcy12bm9kZVwiKTtcbiAgICAgICAgICAgIHZhciBpc1dpZGdldCA9IHJlcXVpcmUoXCIuL2lzLXdpZGdldFwiKTtcbiAgICAgICAgICAgIHZhciBpc1RodW5rID0gcmVxdWlyZShcIi4vaXMtdGh1bmtcIik7XG4gICAgICAgICAgICB2YXIgaXNWSG9vayA9IHJlcXVpcmUoXCIuL2lzLXZob29rXCIpO1xuXG4gICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IFZpcnR1YWxOb2RlO1xuXG4gICAgICAgICAgICB2YXIgbm9Qcm9wZXJ0aWVzID0ge307XG4gICAgICAgICAgICB2YXIgbm9DaGlsZHJlbiA9IFtdO1xuXG4gICAgICAgICAgICBmdW5jdGlvbiBWaXJ0dWFsTm9kZSh0YWdOYW1lLCBwcm9wZXJ0aWVzLCBjaGlsZHJlbiwga2V5LCBuYW1lc3BhY2UpIHtcbiAgICAgICAgICAgICAgICB0aGlzLnRhZ05hbWUgPSB0YWdOYW1lO1xuICAgICAgICAgICAgICAgIHRoaXMucHJvcGVydGllcyA9IHByb3BlcnRpZXMgfHwgbm9Qcm9wZXJ0aWVzO1xuICAgICAgICAgICAgICAgIHRoaXMuY2hpbGRyZW4gPSBjaGlsZHJlbiB8fCBub0NoaWxkcmVuO1xuICAgICAgICAgICAgICAgIHRoaXMua2V5ID0ga2V5ICE9IG51bGwgPyBTdHJpbmcoa2V5KSA6IHVuZGVmaW5lZDtcbiAgICAgICAgICAgICAgICB0aGlzLm5hbWVzcGFjZSA9IHR5cGVvZiBuYW1lc3BhY2UgPT09IFwic3RyaW5nXCIgPyBuYW1lc3BhY2UgOiBudWxsO1xuXG4gICAgICAgICAgICAgICAgdmFyIGNvdW50ID0gY2hpbGRyZW4gJiYgY2hpbGRyZW4ubGVuZ3RoIHx8IDA7XG4gICAgICAgICAgICAgICAgdmFyIGRlc2NlbmRhbnRzID0gMDtcbiAgICAgICAgICAgICAgICB2YXIgaGFzV2lkZ2V0cyA9IGZhbHNlO1xuICAgICAgICAgICAgICAgIHZhciBoYXNUaHVua3MgPSBmYWxzZTtcbiAgICAgICAgICAgICAgICB2YXIgZGVzY2VuZGFudEhvb2tzID0gZmFsc2U7XG4gICAgICAgICAgICAgICAgdmFyIGhvb2tzO1xuXG4gICAgICAgICAgICAgICAgZm9yICh2YXIgcHJvcE5hbWUgaW4gcHJvcGVydGllcykge1xuICAgICAgICAgICAgICAgICAgICBpZiAocHJvcGVydGllcy5oYXNPd25Qcm9wZXJ0eShwcm9wTmFtZSkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHZhciBwcm9wZXJ0eSA9IHByb3BlcnRpZXNbcHJvcE5hbWVdO1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGlzVkhvb2socHJvcGVydHkpICYmIHByb3BlcnR5LnVuaG9vaykge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmICghaG9va3MpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaG9va3MgPSB7fTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBob29rc1twcm9wTmFtZV0gPSBwcm9wZXJ0eTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgY291bnQ7IGkrKykge1xuICAgICAgICAgICAgICAgICAgICB2YXIgY2hpbGQgPSBjaGlsZHJlbltpXTtcbiAgICAgICAgICAgICAgICAgICAgaWYgKGlzVk5vZGUoY2hpbGQpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBkZXNjZW5kYW50cyArPSBjaGlsZC5jb3VudCB8fCAwO1xuXG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoIWhhc1dpZGdldHMgJiYgY2hpbGQuaGFzV2lkZ2V0cykge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGhhc1dpZGdldHMgPSB0cnVlO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoIWhhc1RodW5rcyAmJiBjaGlsZC5oYXNUaHVua3MpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBoYXNUaHVua3MgPSB0cnVlO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoIWRlc2NlbmRhbnRIb29rcyAmJiAoY2hpbGQuaG9va3MgfHwgY2hpbGQuZGVzY2VuZGFudEhvb2tzKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRlc2NlbmRhbnRIb29rcyA9IHRydWU7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoIWhhc1dpZGdldHMgJiYgaXNXaWRnZXQoY2hpbGQpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAodHlwZW9mIGNoaWxkLmRlc3Ryb3kgPT09IFwiZnVuY3Rpb25cIikge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGhhc1dpZGdldHMgPSB0cnVlO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKCFoYXNUaHVua3MgJiYgaXNUaHVuayhjaGlsZCkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGhhc1RodW5rcyA9IHRydWU7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICB0aGlzLmNvdW50ID0gY291bnQgKyBkZXNjZW5kYW50cztcbiAgICAgICAgICAgICAgICB0aGlzLmhhc1dpZGdldHMgPSBoYXNXaWRnZXRzO1xuICAgICAgICAgICAgICAgIHRoaXMuaGFzVGh1bmtzID0gaGFzVGh1bmtzO1xuICAgICAgICAgICAgICAgIHRoaXMuaG9va3MgPSBob29rcztcbiAgICAgICAgICAgICAgICB0aGlzLmRlc2NlbmRhbnRIb29rcyA9IGRlc2NlbmRhbnRIb29rcztcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgVmlydHVhbE5vZGUucHJvdG90eXBlLnZlcnNpb24gPSB2ZXJzaW9uO1xuICAgICAgICAgICAgVmlydHVhbE5vZGUucHJvdG90eXBlLnR5cGUgPSBcIlZpcnR1YWxOb2RlXCI7XG4gICAgICAgIH0sIHsgXCIuL2lzLXRodW5rXCI6IDI1LCBcIi4vaXMtdmhvb2tcIjogMjYsIFwiLi9pcy12bm9kZVwiOiAyNywgXCIuL2lzLXdpZGdldFwiOiAyOSwgXCIuL3ZlcnNpb25cIjogMzAgfV0sIDMyOiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge1xuICAgICAgICAgICAgdmFyIHZlcnNpb24gPSByZXF1aXJlKFwiLi92ZXJzaW9uXCIpO1xuXG4gICAgICAgICAgICBWaXJ0dWFsUGF0Y2guTk9ORSA9IDA7XG4gICAgICAgICAgICBWaXJ0dWFsUGF0Y2guVlRFWFQgPSAxO1xuICAgICAgICAgICAgVmlydHVhbFBhdGNoLlZOT0RFID0gMjtcbiAgICAgICAgICAgIFZpcnR1YWxQYXRjaC5XSURHRVQgPSAzO1xuICAgICAgICAgICAgVmlydHVhbFBhdGNoLlBST1BTID0gNDtcbiAgICAgICAgICAgIFZpcnR1YWxQYXRjaC5PUkRFUiA9IDU7XG4gICAgICAgICAgICBWaXJ0dWFsUGF0Y2guSU5TRVJUID0gNjtcbiAgICAgICAgICAgIFZpcnR1YWxQYXRjaC5SRU1PVkUgPSA3O1xuICAgICAgICAgICAgVmlydHVhbFBhdGNoLlRIVU5LID0gODtcblxuICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBWaXJ0dWFsUGF0Y2g7XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIFZpcnR1YWxQYXRjaCh0eXBlLCB2Tm9kZSwgcGF0Y2gpIHtcbiAgICAgICAgICAgICAgICB0aGlzLnR5cGUgPSBOdW1iZXIodHlwZSk7XG4gICAgICAgICAgICAgICAgdGhpcy52Tm9kZSA9IHZOb2RlO1xuICAgICAgICAgICAgICAgIHRoaXMucGF0Y2ggPSBwYXRjaDtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgVmlydHVhbFBhdGNoLnByb3RvdHlwZS52ZXJzaW9uID0gdmVyc2lvbjtcbiAgICAgICAgICAgIFZpcnR1YWxQYXRjaC5wcm90b3R5cGUudHlwZSA9IFwiVmlydHVhbFBhdGNoXCI7XG4gICAgICAgIH0sIHsgXCIuL3ZlcnNpb25cIjogMzAgfV0sIDMzOiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge1xuICAgICAgICAgICAgdmFyIHZlcnNpb24gPSByZXF1aXJlKFwiLi92ZXJzaW9uXCIpO1xuXG4gICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IFZpcnR1YWxUZXh0O1xuXG4gICAgICAgICAgICBmdW5jdGlvbiBWaXJ0dWFsVGV4dCh0ZXh0KSB7XG4gICAgICAgICAgICAgICAgdGhpcy50ZXh0ID0gU3RyaW5nKHRleHQpO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBWaXJ0dWFsVGV4dC5wcm90b3R5cGUudmVyc2lvbiA9IHZlcnNpb247XG4gICAgICAgICAgICBWaXJ0dWFsVGV4dC5wcm90b3R5cGUudHlwZSA9IFwiVmlydHVhbFRleHRcIjtcbiAgICAgICAgfSwgeyBcIi4vdmVyc2lvblwiOiAzMCB9XSwgMzQ6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICB2YXIgaXNPYmplY3QgPSByZXF1aXJlKFwiaXMtb2JqZWN0XCIpO1xuICAgICAgICAgICAgdmFyIGlzSG9vayA9IHJlcXVpcmUoXCIuLi92bm9kZS9pcy12aG9va1wiKTtcblxuICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBkaWZmUHJvcHM7XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIGRpZmZQcm9wcyhhLCBiKSB7XG4gICAgICAgICAgICAgICAgdmFyIGRpZmY7XG5cbiAgICAgICAgICAgICAgICBmb3IgKHZhciBhS2V5IGluIGEpIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKCEoYUtleSBpbiBiKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgZGlmZiA9IGRpZmYgfHwge307XG4gICAgICAgICAgICAgICAgICAgICAgICBkaWZmW2FLZXldID0gdW5kZWZpbmVkO1xuICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgdmFyIGFWYWx1ZSA9IGFbYUtleV07XG4gICAgICAgICAgICAgICAgICAgIHZhciBiVmFsdWUgPSBiW2FLZXldO1xuXG4gICAgICAgICAgICAgICAgICAgIGlmIChhVmFsdWUgPT09IGJWYWx1ZSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgY29udGludWU7XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoaXNPYmplY3QoYVZhbHVlKSAmJiBpc09iamVjdChiVmFsdWUpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoZ2V0UHJvdG90eXBlKGJWYWx1ZSkgIT09IGdldFByb3RvdHlwZShhVmFsdWUpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgZGlmZiA9IGRpZmYgfHwge307XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgZGlmZlthS2V5XSA9IGJWYWx1ZTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoaXNIb29rKGJWYWx1ZSkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBkaWZmID0gZGlmZiB8fCB7fTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBkaWZmW2FLZXldID0gYlZhbHVlO1xuICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB2YXIgb2JqZWN0RGlmZiA9IGRpZmZQcm9wcyhhVmFsdWUsIGJWYWx1ZSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKG9iamVjdERpZmYpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZGlmZiA9IGRpZmYgfHwge307XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRpZmZbYUtleV0gPSBvYmplY3REaWZmO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGRpZmYgPSBkaWZmIHx8IHt9O1xuICAgICAgICAgICAgICAgICAgICAgICAgZGlmZlthS2V5XSA9IGJWYWx1ZTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIGZvciAodmFyIGJLZXkgaW4gYikge1xuICAgICAgICAgICAgICAgICAgICBpZiAoIShiS2V5IGluIGEpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBkaWZmID0gZGlmZiB8fCB7fTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGRpZmZbYktleV0gPSBiW2JLZXldO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgcmV0dXJuIGRpZmY7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIGdldFByb3RvdHlwZSh2YWx1ZSkge1xuICAgICAgICAgICAgICAgIGlmIChPYmplY3QuZ2V0UHJvdG90eXBlT2YpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIE9iamVjdC5nZXRQcm90b3R5cGVPZih2YWx1ZSk7XG4gICAgICAgICAgICAgICAgfSBlbHNlIGlmICh2YWx1ZS5fX3Byb3RvX18pIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHZhbHVlLl9fcHJvdG9fXztcbiAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKHZhbHVlLmNvbnN0cnVjdG9yKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiB2YWx1ZS5jb25zdHJ1Y3Rvci5wcm90b3R5cGU7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9LCB7IFwiLi4vdm5vZGUvaXMtdmhvb2tcIjogMjYsIFwiaXMtb2JqZWN0XCI6IDExIH1dLCAzNTogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHtcbiAgICAgICAgICAgIHZhciBpc0FycmF5ID0gcmVxdWlyZShcIngtaXMtYXJyYXlcIik7XG5cbiAgICAgICAgICAgIHZhciBWUGF0Y2ggPSByZXF1aXJlKFwiLi4vdm5vZGUvdnBhdGNoXCIpO1xuICAgICAgICAgICAgdmFyIGlzVk5vZGUgPSByZXF1aXJlKFwiLi4vdm5vZGUvaXMtdm5vZGVcIik7XG4gICAgICAgICAgICB2YXIgaXNWVGV4dCA9IHJlcXVpcmUoXCIuLi92bm9kZS9pcy12dGV4dFwiKTtcbiAgICAgICAgICAgIHZhciBpc1dpZGdldCA9IHJlcXVpcmUoXCIuLi92bm9kZS9pcy13aWRnZXRcIik7XG4gICAgICAgICAgICB2YXIgaXNUaHVuayA9IHJlcXVpcmUoXCIuLi92bm9kZS9pcy10aHVua1wiKTtcbiAgICAgICAgICAgIHZhciBoYW5kbGVUaHVuayA9IHJlcXVpcmUoXCIuLi92bm9kZS9oYW5kbGUtdGh1bmtcIik7XG5cbiAgICAgICAgICAgIHZhciBkaWZmUHJvcHMgPSByZXF1aXJlKFwiLi9kaWZmLXByb3BzXCIpO1xuXG4gICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IGRpZmY7XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIGRpZmYoYSwgYikge1xuICAgICAgICAgICAgICAgIHZhciBwYXRjaCA9IHsgYTogYSB9O1xuICAgICAgICAgICAgICAgIHdhbGsoYSwgYiwgcGF0Y2gsIDApO1xuICAgICAgICAgICAgICAgIHJldHVybiBwYXRjaDtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZnVuY3Rpb24gd2FsayhhLCBiLCBwYXRjaCwgaW5kZXgpIHtcbiAgICAgICAgICAgICAgICBpZiAoYSA9PT0gYikge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgdmFyIGFwcGx5ID0gcGF0Y2hbaW5kZXhdO1xuICAgICAgICAgICAgICAgIHZhciBhcHBseUNsZWFyID0gZmFsc2U7XG5cbiAgICAgICAgICAgICAgICBpZiAoaXNUaHVuayhhKSB8fCBpc1RodW5rKGIpKSB7XG4gICAgICAgICAgICAgICAgICAgIHRodW5rcyhhLCBiLCBwYXRjaCwgaW5kZXgpO1xuICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoYiA9PSBudWxsKSB7XG5cbiAgICAgICAgICAgICAgICAgICAgLy8gSWYgYSBpcyBhIHdpZGdldCB3ZSB3aWxsIGFkZCBhIHJlbW92ZSBwYXRjaCBmb3IgaXRcbiAgICAgICAgICAgICAgICAgICAgLy8gT3RoZXJ3aXNlIGFueSBjaGlsZCB3aWRnZXRzL2hvb2tzIG11c3QgYmUgZGVzdHJveWVkLlxuICAgICAgICAgICAgICAgICAgICAvLyBUaGlzIHByZXZlbnRzIGFkZGluZyB0d28gcmVtb3ZlIHBhdGNoZXMgZm9yIGEgd2lkZ2V0LlxuICAgICAgICAgICAgICAgICAgICBpZiAoIWlzV2lkZ2V0KGEpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBjbGVhclN0YXRlKGEsIHBhdGNoLCBpbmRleCk7XG4gICAgICAgICAgICAgICAgICAgICAgICBhcHBseSA9IHBhdGNoW2luZGV4XTtcbiAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgIGFwcGx5ID0gYXBwZW5kUGF0Y2goYXBwbHksIG5ldyBWUGF0Y2goVlBhdGNoLlJFTU9WRSwgYSwgYikpO1xuICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoaXNWTm9kZShiKSkge1xuICAgICAgICAgICAgICAgICAgICBpZiAoaXNWTm9kZShhKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGEudGFnTmFtZSA9PT0gYi50YWdOYW1lICYmIGEubmFtZXNwYWNlID09PSBiLm5hbWVzcGFjZSAmJiBhLmtleSA9PT0gYi5rZXkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB2YXIgcHJvcHNQYXRjaCA9IGRpZmZQcm9wcyhhLnByb3BlcnRpZXMsIGIucHJvcGVydGllcyk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHByb3BzUGF0Y2gpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYXBwbHkgPSBhcHBlbmRQYXRjaChhcHBseSwgbmV3IFZQYXRjaChWUGF0Y2guUFJPUFMsIGEsIHByb3BzUGF0Y2gpKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgYXBwbHkgPSBkaWZmQ2hpbGRyZW4oYSwgYiwgcGF0Y2gsIGFwcGx5LCBpbmRleCk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGFwcGx5ID0gYXBwZW5kUGF0Y2goYXBwbHksIG5ldyBWUGF0Y2goVlBhdGNoLlZOT0RFLCBhLCBiKSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgYXBwbHlDbGVhciA9IHRydWU7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBhcHBseSA9IGFwcGVuZFBhdGNoKGFwcGx5LCBuZXcgVlBhdGNoKFZQYXRjaC5WTk9ERSwgYSwgYikpO1xuICAgICAgICAgICAgICAgICAgICAgICAgYXBwbHlDbGVhciA9IHRydWU7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKGlzVlRleHQoYikpIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKCFpc1ZUZXh0KGEpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBhcHBseSA9IGFwcGVuZFBhdGNoKGFwcGx5LCBuZXcgVlBhdGNoKFZQYXRjaC5WVEVYVCwgYSwgYikpO1xuICAgICAgICAgICAgICAgICAgICAgICAgYXBwbHlDbGVhciA9IHRydWU7XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoYS50ZXh0ICE9PSBiLnRleHQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGFwcGx5ID0gYXBwZW5kUGF0Y2goYXBwbHksIG5ldyBWUGF0Y2goVlBhdGNoLlZURVhULCBhLCBiKSk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKGlzV2lkZ2V0KGIpKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmICghaXNXaWRnZXQoYSkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGFwcGx5Q2xlYXIgPSB0cnVlO1xuICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgYXBwbHkgPSBhcHBlbmRQYXRjaChhcHBseSwgbmV3IFZQYXRjaChWUGF0Y2guV0lER0VULCBhLCBiKSk7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgaWYgKGFwcGx5KSB7XG4gICAgICAgICAgICAgICAgICAgIHBhdGNoW2luZGV4XSA9IGFwcGx5O1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIGlmIChhcHBseUNsZWFyKSB7XG4gICAgICAgICAgICAgICAgICAgIGNsZWFyU3RhdGUoYSwgcGF0Y2gsIGluZGV4KTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIGRpZmZDaGlsZHJlbihhLCBiLCBwYXRjaCwgYXBwbHksIGluZGV4KSB7XG4gICAgICAgICAgICAgICAgdmFyIGFDaGlsZHJlbiA9IGEuY2hpbGRyZW47XG4gICAgICAgICAgICAgICAgdmFyIG9yZGVyZWRTZXQgPSByZW9yZGVyKGFDaGlsZHJlbiwgYi5jaGlsZHJlbik7XG4gICAgICAgICAgICAgICAgdmFyIGJDaGlsZHJlbiA9IG9yZGVyZWRTZXQuY2hpbGRyZW47XG5cbiAgICAgICAgICAgICAgICB2YXIgYUxlbiA9IGFDaGlsZHJlbi5sZW5ndGg7XG4gICAgICAgICAgICAgICAgdmFyIGJMZW4gPSBiQ2hpbGRyZW4ubGVuZ3RoO1xuICAgICAgICAgICAgICAgIHZhciBsZW4gPSBhTGVuID4gYkxlbiA/IGFMZW4gOiBiTGVuO1xuXG4gICAgICAgICAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCBsZW47IGkrKykge1xuICAgICAgICAgICAgICAgICAgICB2YXIgbGVmdE5vZGUgPSBhQ2hpbGRyZW5baV07XG4gICAgICAgICAgICAgICAgICAgIHZhciByaWdodE5vZGUgPSBiQ2hpbGRyZW5baV07XG4gICAgICAgICAgICAgICAgICAgIGluZGV4ICs9IDE7XG5cbiAgICAgICAgICAgICAgICAgICAgaWYgKCFsZWZ0Tm9kZSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHJpZ2h0Tm9kZSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIEV4Y2VzcyBub2RlcyBpbiBiIG5lZWQgdG8gYmUgYWRkZWRcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBhcHBseSA9IGFwcGVuZFBhdGNoKGFwcGx5LCBuZXcgVlBhdGNoKFZQYXRjaC5JTlNFUlQsIG51bGwsIHJpZ2h0Tm9kZSkpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgd2FsayhsZWZ0Tm9kZSwgcmlnaHROb2RlLCBwYXRjaCwgaW5kZXgpO1xuICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgaWYgKGlzVk5vZGUobGVmdE5vZGUpICYmIGxlZnROb2RlLmNvdW50KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBpbmRleCArPSBsZWZ0Tm9kZS5jb3VudDtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIGlmIChvcmRlcmVkU2V0Lm1vdmVzKSB7XG4gICAgICAgICAgICAgICAgICAgIC8vIFJlb3JkZXIgbm9kZXMgbGFzdFxuICAgICAgICAgICAgICAgICAgICBhcHBseSA9IGFwcGVuZFBhdGNoKGFwcGx5LCBuZXcgVlBhdGNoKFZQYXRjaC5PUkRFUiwgYSwgb3JkZXJlZFNldC5tb3ZlcykpO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHJldHVybiBhcHBseTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZnVuY3Rpb24gY2xlYXJTdGF0ZSh2Tm9kZSwgcGF0Y2gsIGluZGV4KSB7XG4gICAgICAgICAgICAgICAgLy8gVE9ETzogTWFrZSB0aGlzIGEgc2luZ2xlIHdhbGssIG5vdCB0d29cbiAgICAgICAgICAgICAgICB1bmhvb2sodk5vZGUsIHBhdGNoLCBpbmRleCk7XG4gICAgICAgICAgICAgICAgZGVzdHJveVdpZGdldHModk5vZGUsIHBhdGNoLCBpbmRleCk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIC8vIFBhdGNoIHJlY29yZHMgZm9yIGFsbCBkZXN0cm95ZWQgd2lkZ2V0cyBtdXN0IGJlIGFkZGVkIGJlY2F1c2Ugd2UgbmVlZFxuICAgICAgICAgICAgLy8gYSBET00gbm9kZSByZWZlcmVuY2UgZm9yIHRoZSBkZXN0cm95IGZ1bmN0aW9uXG4gICAgICAgICAgICBmdW5jdGlvbiBkZXN0cm95V2lkZ2V0cyh2Tm9kZSwgcGF0Y2gsIGluZGV4KSB7XG4gICAgICAgICAgICAgICAgaWYgKGlzV2lkZ2V0KHZOb2RlKSkge1xuICAgICAgICAgICAgICAgICAgICBpZiAodHlwZW9mIHZOb2RlLmRlc3Ryb3kgPT09IFwiZnVuY3Rpb25cIikge1xuICAgICAgICAgICAgICAgICAgICAgICAgcGF0Y2hbaW5kZXhdID0gYXBwZW5kUGF0Y2gocGF0Y2hbaW5kZXhdLCBuZXcgVlBhdGNoKFZQYXRjaC5SRU1PVkUsIHZOb2RlLCBudWxsKSk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKGlzVk5vZGUodk5vZGUpICYmICh2Tm9kZS5oYXNXaWRnZXRzIHx8IHZOb2RlLmhhc1RodW5rcykpIHtcbiAgICAgICAgICAgICAgICAgICAgdmFyIGNoaWxkcmVuID0gdk5vZGUuY2hpbGRyZW47XG4gICAgICAgICAgICAgICAgICAgIHZhciBsZW4gPSBjaGlsZHJlbi5sZW5ndGg7XG4gICAgICAgICAgICAgICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgbGVuOyBpKyspIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHZhciBjaGlsZCA9IGNoaWxkcmVuW2ldO1xuICAgICAgICAgICAgICAgICAgICAgICAgaW5kZXggKz0gMTtcblxuICAgICAgICAgICAgICAgICAgICAgICAgZGVzdHJveVdpZGdldHMoY2hpbGQsIHBhdGNoLCBpbmRleCk7XG5cbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChpc1ZOb2RlKGNoaWxkKSAmJiBjaGlsZC5jb3VudCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGluZGV4ICs9IGNoaWxkLmNvdW50O1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfSBlbHNlIGlmIChpc1RodW5rKHZOb2RlKSkge1xuICAgICAgICAgICAgICAgICAgICB0aHVua3Modk5vZGUsIG51bGwsIHBhdGNoLCBpbmRleCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAvLyBDcmVhdGUgYSBzdWItcGF0Y2ggZm9yIHRodW5rc1xuICAgICAgICAgICAgZnVuY3Rpb24gdGh1bmtzKGEsIGIsIHBhdGNoLCBpbmRleCkge1xuICAgICAgICAgICAgICAgIHZhciBub2RlcyA9IGhhbmRsZVRodW5rKGEsIGIpO1xuICAgICAgICAgICAgICAgIHZhciB0aHVua1BhdGNoID0gZGlmZihub2Rlcy5hLCBub2Rlcy5iKTtcbiAgICAgICAgICAgICAgICBpZiAoaGFzUGF0Y2hlcyh0aHVua1BhdGNoKSkge1xuICAgICAgICAgICAgICAgICAgICBwYXRjaFtpbmRleF0gPSBuZXcgVlBhdGNoKFZQYXRjaC5USFVOSywgbnVsbCwgdGh1bmtQYXRjaCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBmdW5jdGlvbiBoYXNQYXRjaGVzKHBhdGNoKSB7XG4gICAgICAgICAgICAgICAgZm9yICh2YXIgaW5kZXggaW4gcGF0Y2gpIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKGluZGV4ICE9PSBcImFcIikge1xuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIC8vIEV4ZWN1dGUgaG9va3Mgd2hlbiB0d28gbm9kZXMgYXJlIGlkZW50aWNhbFxuICAgICAgICAgICAgZnVuY3Rpb24gdW5ob29rKHZOb2RlLCBwYXRjaCwgaW5kZXgpIHtcbiAgICAgICAgICAgICAgICBpZiAoaXNWTm9kZSh2Tm9kZSkpIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKHZOb2RlLmhvb2tzKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBwYXRjaFtpbmRleF0gPSBhcHBlbmRQYXRjaChwYXRjaFtpbmRleF0sIG5ldyBWUGF0Y2goVlBhdGNoLlBST1BTLCB2Tm9kZSwgdW5kZWZpbmVkS2V5cyh2Tm9kZS5ob29rcykpKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgIGlmICh2Tm9kZS5kZXNjZW5kYW50SG9va3MgfHwgdk5vZGUuaGFzVGh1bmtzKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICB2YXIgY2hpbGRyZW4gPSB2Tm9kZS5jaGlsZHJlbjtcbiAgICAgICAgICAgICAgICAgICAgICAgIHZhciBsZW4gPSBjaGlsZHJlbi5sZW5ndGg7XG4gICAgICAgICAgICAgICAgICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IGxlbjsgaSsrKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdmFyIGNoaWxkID0gY2hpbGRyZW5baV07XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaW5kZXggKz0gMTtcblxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHVuaG9vayhjaGlsZCwgcGF0Y2gsIGluZGV4KTtcblxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChpc1ZOb2RlKGNoaWxkKSAmJiBjaGlsZC5jb3VudCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpbmRleCArPSBjaGlsZC5jb3VudDtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKGlzVGh1bmsodk5vZGUpKSB7XG4gICAgICAgICAgICAgICAgICAgIHRodW5rcyh2Tm9kZSwgbnVsbCwgcGF0Y2gsIGluZGV4KTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIHVuZGVmaW5lZEtleXMob2JqKSB7XG4gICAgICAgICAgICAgICAgdmFyIHJlc3VsdCA9IHt9O1xuXG4gICAgICAgICAgICAgICAgZm9yICh2YXIga2V5IGluIG9iaikge1xuICAgICAgICAgICAgICAgICAgICByZXN1bHRba2V5XSA9IHVuZGVmaW5lZDtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICByZXR1cm4gcmVzdWx0O1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAvLyBMaXN0IGRpZmYsIG5haXZlIGxlZnQgdG8gcmlnaHQgcmVvcmRlcmluZ1xuICAgICAgICAgICAgZnVuY3Rpb24gcmVvcmRlcihhQ2hpbGRyZW4sIGJDaGlsZHJlbikge1xuICAgICAgICAgICAgICAgIC8vIE8oTSkgdGltZSwgTyhNKSBtZW1vcnlcbiAgICAgICAgICAgICAgICB2YXIgYkNoaWxkSW5kZXggPSBrZXlJbmRleChiQ2hpbGRyZW4pO1xuICAgICAgICAgICAgICAgIHZhciBiS2V5cyA9IGJDaGlsZEluZGV4LmtleXM7XG4gICAgICAgICAgICAgICAgdmFyIGJGcmVlID0gYkNoaWxkSW5kZXguZnJlZTtcblxuICAgICAgICAgICAgICAgIGlmIChiRnJlZS5sZW5ndGggPT09IGJDaGlsZHJlbi5sZW5ndGgpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGNoaWxkcmVuOiBiQ2hpbGRyZW4sXG4gICAgICAgICAgICAgICAgICAgICAgICBtb3ZlczogbnVsbFxuICAgICAgICAgICAgICAgICAgICB9O1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIC8vIE8oTikgdGltZSwgTyhOKSBtZW1vcnlcbiAgICAgICAgICAgICAgICB2YXIgYUNoaWxkSW5kZXggPSBrZXlJbmRleChhQ2hpbGRyZW4pO1xuICAgICAgICAgICAgICAgIHZhciBhS2V5cyA9IGFDaGlsZEluZGV4LmtleXM7XG4gICAgICAgICAgICAgICAgdmFyIGFGcmVlID0gYUNoaWxkSW5kZXguZnJlZTtcblxuICAgICAgICAgICAgICAgIGlmIChhRnJlZS5sZW5ndGggPT09IGFDaGlsZHJlbi5sZW5ndGgpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGNoaWxkcmVuOiBiQ2hpbGRyZW4sXG4gICAgICAgICAgICAgICAgICAgICAgICBtb3ZlczogbnVsbFxuICAgICAgICAgICAgICAgICAgICB9O1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIC8vIE8oTUFYKE4sIE0pKSBtZW1vcnlcbiAgICAgICAgICAgICAgICB2YXIgbmV3Q2hpbGRyZW4gPSBbXTtcblxuICAgICAgICAgICAgICAgIHZhciBmcmVlSW5kZXggPSAwO1xuICAgICAgICAgICAgICAgIHZhciBmcmVlQ291bnQgPSBiRnJlZS5sZW5ndGg7XG4gICAgICAgICAgICAgICAgdmFyIGRlbGV0ZWRJdGVtcyA9IDA7XG5cbiAgICAgICAgICAgICAgICAvLyBJdGVyYXRlIHRocm91Z2ggYSBhbmQgbWF0Y2ggYSBub2RlIGluIGJcbiAgICAgICAgICAgICAgICAvLyBPKE4pIHRpbWUsXG4gICAgICAgICAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCBhQ2hpbGRyZW4ubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgICAgICAgICAgdmFyIGFJdGVtID0gYUNoaWxkcmVuW2ldO1xuICAgICAgICAgICAgICAgICAgICB2YXIgaXRlbUluZGV4O1xuXG4gICAgICAgICAgICAgICAgICAgIGlmIChhSXRlbS5rZXkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChiS2V5cy5oYXNPd25Qcm9wZXJ0eShhSXRlbS5rZXkpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gTWF0Y2ggdXAgdGhlIG9sZCBrZXlzXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaXRlbUluZGV4ID0gYktleXNbYUl0ZW0ua2V5XTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBuZXdDaGlsZHJlbi5wdXNoKGJDaGlsZHJlbltpdGVtSW5kZXhdKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gUmVtb3ZlIG9sZCBrZXllZCBpdGVtc1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGl0ZW1JbmRleCA9IGkgLSBkZWxldGVkSXRlbXMrKztcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBuZXdDaGlsZHJlbi5wdXNoKG51bGwpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgLy8gTWF0Y2ggdGhlIGl0ZW0gaW4gYSB3aXRoIHRoZSBuZXh0IGZyZWUgaXRlbSBpbiBiXG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoZnJlZUluZGV4IDwgZnJlZUNvdW50KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaXRlbUluZGV4ID0gYkZyZWVbZnJlZUluZGV4KytdO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIG5ld0NoaWxkcmVuLnB1c2goYkNoaWxkcmVuW2l0ZW1JbmRleF0pO1xuICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBUaGVyZSBhcmUgbm8gZnJlZSBpdGVtcyBpbiBiIHRvIG1hdGNoIHdpdGhcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyB0aGUgZnJlZSBpdGVtcyBpbiBhLCBzbyB0aGUgZXh0cmEgZnJlZSBub2Rlc1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIGFyZSBkZWxldGVkLlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGl0ZW1JbmRleCA9IGkgLSBkZWxldGVkSXRlbXMrKztcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBuZXdDaGlsZHJlbi5wdXNoKG51bGwpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgdmFyIGxhc3RGcmVlSW5kZXggPSBmcmVlSW5kZXggPj0gYkZyZWUubGVuZ3RoID8gYkNoaWxkcmVuLmxlbmd0aCA6IGJGcmVlW2ZyZWVJbmRleF07XG5cbiAgICAgICAgICAgICAgICAvLyBJdGVyYXRlIHRocm91Z2ggYiBhbmQgYXBwZW5kIGFueSBuZXcga2V5c1xuICAgICAgICAgICAgICAgIC8vIE8oTSkgdGltZVxuICAgICAgICAgICAgICAgIGZvciAodmFyIGogPSAwOyBqIDwgYkNoaWxkcmVuLmxlbmd0aDsgaisrKSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciBuZXdJdGVtID0gYkNoaWxkcmVuW2pdO1xuXG4gICAgICAgICAgICAgICAgICAgIGlmIChuZXdJdGVtLmtleSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKCFhS2V5cy5oYXNPd25Qcm9wZXJ0eShuZXdJdGVtLmtleSkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBBZGQgYW55IG5ldyBrZXllZCBpdGVtc1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIFdlIGFyZSBhZGRpbmcgbmV3IGl0ZW1zIHRvIHRoZSBlbmQgYW5kIHRoZW4gc29ydGluZyB0aGVtXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gaW4gcGxhY2UuIEluIGZ1dHVyZSB3ZSBzaG91bGQgaW5zZXJ0IG5ldyBpdGVtcyBpbiBwbGFjZS5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBuZXdDaGlsZHJlbi5wdXNoKG5ld0l0ZW0pO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKGogPj0gbGFzdEZyZWVJbmRleCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgLy8gQWRkIGFueSBsZWZ0b3ZlciBub24ta2V5ZWQgaXRlbXNcbiAgICAgICAgICAgICAgICAgICAgICAgIG5ld0NoaWxkcmVuLnB1c2gobmV3SXRlbSk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICB2YXIgc2ltdWxhdGUgPSBuZXdDaGlsZHJlbi5zbGljZSgpO1xuICAgICAgICAgICAgICAgIHZhciBzaW11bGF0ZUluZGV4ID0gMDtcbiAgICAgICAgICAgICAgICB2YXIgcmVtb3ZlcyA9IFtdO1xuICAgICAgICAgICAgICAgIHZhciBpbnNlcnRzID0gW107XG4gICAgICAgICAgICAgICAgdmFyIHNpbXVsYXRlSXRlbTtcblxuICAgICAgICAgICAgICAgIGZvciAodmFyIGsgPSAwOyBrIDwgYkNoaWxkcmVuLmxlbmd0aDspIHtcbiAgICAgICAgICAgICAgICAgICAgdmFyIHdhbnRlZEl0ZW0gPSBiQ2hpbGRyZW5ba107XG4gICAgICAgICAgICAgICAgICAgIHNpbXVsYXRlSXRlbSA9IHNpbXVsYXRlW3NpbXVsYXRlSW5kZXhdO1xuXG4gICAgICAgICAgICAgICAgICAgIC8vIHJlbW92ZSBpdGVtc1xuICAgICAgICAgICAgICAgICAgICB3aGlsZSAoc2ltdWxhdGVJdGVtID09PSBudWxsICYmIHNpbXVsYXRlLmxlbmd0aCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgcmVtb3Zlcy5wdXNoKHJlbW92ZShzaW11bGF0ZSwgc2ltdWxhdGVJbmRleCwgbnVsbCkpO1xuICAgICAgICAgICAgICAgICAgICAgICAgc2ltdWxhdGVJdGVtID0gc2ltdWxhdGVbc2ltdWxhdGVJbmRleF07XG4gICAgICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgICAgICBpZiAoIXNpbXVsYXRlSXRlbSB8fCBzaW11bGF0ZUl0ZW0ua2V5ICE9PSB3YW50ZWRJdGVtLmtleSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgLy8gaWYgd2UgbmVlZCBhIGtleSBpbiB0aGlzIHBvc2l0aW9uLi4uXG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAod2FudGVkSXRlbS5rZXkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoc2ltdWxhdGVJdGVtICYmIHNpbXVsYXRlSXRlbS5rZXkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gaWYgYW4gaW5zZXJ0IGRvZXNuJ3QgcHV0IHRoaXMga2V5IGluIHBsYWNlLCBpdCBuZWVkcyB0byBtb3ZlXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChiS2V5c1tzaW11bGF0ZUl0ZW0ua2V5XSAhPT0gayArIDEpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlbW92ZXMucHVzaChyZW1vdmUoc2ltdWxhdGUsIHNpbXVsYXRlSW5kZXgsIHNpbXVsYXRlSXRlbS5rZXkpKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNpbXVsYXRlSXRlbSA9IHNpbXVsYXRlW3NpbXVsYXRlSW5kZXhdO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gaWYgdGhlIHJlbW92ZSBkaWRuJ3QgcHV0IHRoZSB3YW50ZWQgaXRlbSBpbiBwbGFjZSwgd2UgbmVlZCB0byBpbnNlcnQgaXRcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmICghc2ltdWxhdGVJdGVtIHx8IHNpbXVsYXRlSXRlbS5rZXkgIT09IHdhbnRlZEl0ZW0ua2V5KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaW5zZXJ0cy5wdXNoKHsga2V5OiB3YW50ZWRJdGVtLmtleSwgdG86IGsgfSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBpdGVtcyBhcmUgbWF0Y2hpbmcsIHNvIHNraXAgYWhlYWRcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzaW11bGF0ZUluZGV4Kys7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaW5zZXJ0cy5wdXNoKHsga2V5OiB3YW50ZWRJdGVtLmtleSwgdG86IGsgfSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpbnNlcnRzLnB1c2goeyBrZXk6IHdhbnRlZEl0ZW0ua2V5LCB0bzogayB9KTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaysrO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgLy8gYSBrZXkgaW4gc2ltdWxhdGUgaGFzIG5vIG1hdGNoaW5nIHdhbnRlZCBrZXksIHJlbW92ZSBpdFxuICAgICAgICAgICAgICAgICAgICAgICAgZWxzZSBpZiAoc2ltdWxhdGVJdGVtICYmIHNpbXVsYXRlSXRlbS5rZXkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmVtb3Zlcy5wdXNoKHJlbW92ZShzaW11bGF0ZSwgc2ltdWxhdGVJbmRleCwgc2ltdWxhdGVJdGVtLmtleSkpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHNpbXVsYXRlSW5kZXgrKztcbiAgICAgICAgICAgICAgICAgICAgICAgIGsrKztcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIC8vIHJlbW92ZSBhbGwgdGhlIHJlbWFpbmluZyBub2RlcyBmcm9tIHNpbXVsYXRlXG4gICAgICAgICAgICAgICAgd2hpbGUgKHNpbXVsYXRlSW5kZXggPCBzaW11bGF0ZS5sZW5ndGgpIHtcbiAgICAgICAgICAgICAgICAgICAgc2ltdWxhdGVJdGVtID0gc2ltdWxhdGVbc2ltdWxhdGVJbmRleF07XG4gICAgICAgICAgICAgICAgICAgIHJlbW92ZXMucHVzaChyZW1vdmUoc2ltdWxhdGUsIHNpbXVsYXRlSW5kZXgsIHNpbXVsYXRlSXRlbSAmJiBzaW11bGF0ZUl0ZW0ua2V5KSk7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgLy8gSWYgdGhlIG9ubHkgbW92ZXMgd2UgaGF2ZSBhcmUgZGVsZXRlcyB0aGVuIHdlIGNhbiBqdXN0XG4gICAgICAgICAgICAgICAgLy8gbGV0IHRoZSBkZWxldGUgcGF0Y2ggcmVtb3ZlIHRoZXNlIGl0ZW1zLlxuICAgICAgICAgICAgICAgIGlmIChyZW1vdmVzLmxlbmd0aCA9PT0gZGVsZXRlZEl0ZW1zICYmICFpbnNlcnRzLmxlbmd0aCkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgICAgICAgICAgICAgY2hpbGRyZW46IG5ld0NoaWxkcmVuLFxuICAgICAgICAgICAgICAgICAgICAgICAgbW92ZXM6IG51bGxcbiAgICAgICAgICAgICAgICAgICAgfTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgICAgICAgICBjaGlsZHJlbjogbmV3Q2hpbGRyZW4sXG4gICAgICAgICAgICAgICAgICAgIG1vdmVzOiB7XG4gICAgICAgICAgICAgICAgICAgICAgICByZW1vdmVzOiByZW1vdmVzLFxuICAgICAgICAgICAgICAgICAgICAgICAgaW5zZXJ0czogaW5zZXJ0c1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZnVuY3Rpb24gcmVtb3ZlKGFyciwgaW5kZXgsIGtleSkge1xuICAgICAgICAgICAgICAgIGFyci5zcGxpY2UoaW5kZXgsIDEpO1xuXG4gICAgICAgICAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgICAgICAgICAgZnJvbTogaW5kZXgsXG4gICAgICAgICAgICAgICAgICAgIGtleToga2V5XG4gICAgICAgICAgICAgICAgfTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZnVuY3Rpb24ga2V5SW5kZXgoY2hpbGRyZW4pIHtcbiAgICAgICAgICAgICAgICB2YXIga2V5cyA9IHt9O1xuICAgICAgICAgICAgICAgIHZhciBmcmVlID0gW107XG4gICAgICAgICAgICAgICAgdmFyIGxlbmd0aCA9IGNoaWxkcmVuLmxlbmd0aDtcblxuICAgICAgICAgICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgbGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgICAgICAgICAgdmFyIGNoaWxkID0gY2hpbGRyZW5baV07XG5cbiAgICAgICAgICAgICAgICAgICAgaWYgKGNoaWxkLmtleSkge1xuICAgICAgICAgICAgICAgICAgICAgICAga2V5c1tjaGlsZC5rZXldID0gaTtcbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGZyZWUucHVzaChpKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHJldHVybiB7XG4gICAgICAgICAgICAgICAgICAgIGtleXM6IGtleXMsIC8vIEEgaGFzaCBvZiBrZXkgbmFtZSB0byBpbmRleFxuICAgICAgICAgICAgICAgICAgICBmcmVlOiBmcmVlIC8vIEFuIGFycmF5IG9mIHVua2V5ZWQgaXRlbSBpbmRpY2VzXG4gICAgICAgICAgICAgICAgfTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZnVuY3Rpb24gYXBwZW5kUGF0Y2goYXBwbHksIHBhdGNoKSB7XG4gICAgICAgICAgICAgICAgaWYgKGFwcGx5KSB7XG4gICAgICAgICAgICAgICAgICAgIGlmIChpc0FycmF5KGFwcGx5KSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgYXBwbHkucHVzaChwYXRjaCk7XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBhcHBseSA9IFthcHBseSwgcGF0Y2hdO1xuICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGFwcGx5O1xuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBwYXRjaDtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH0sIHsgXCIuLi92bm9kZS9oYW5kbGUtdGh1bmtcIjogMjQsIFwiLi4vdm5vZGUvaXMtdGh1bmtcIjogMjUsIFwiLi4vdm5vZGUvaXMtdm5vZGVcIjogMjcsIFwiLi4vdm5vZGUvaXMtdnRleHRcIjogMjgsIFwiLi4vdm5vZGUvaXMtd2lkZ2V0XCI6IDI5LCBcIi4uL3Zub2RlL3ZwYXRjaFwiOiAzMiwgXCIuL2RpZmYtcHJvcHNcIjogMzQsIFwieC1pcy1hcnJheVwiOiAxMiB9XSB9LCB7fSwgWzRdKSg0KTtcbn0pO1xuXG5leHBvcnQgZGVmYXVsdCBWaXJ0dWFsRE9NO1xuLy8jIHNvdXJjZU1hcHBpbmdVUkw9ZGF0YTphcHBsaWNhdGlvbi9qc29uO2Jhc2U2NCxleUoyWlhKemFXOXVJam96TENKemIzVnlZMlZ6SWpwYklteHBZaTkyYVhKMGRXRnNMV1J2YlM1cWN5SmRMQ0p1WVcxbGN5STZXMTBzSW0xaGNIQnBibWR6SWpvaVFVRkJRU3hKUVVGSkxHRkJRV0VzVlVGQlV5eERRVUZVTEVWQlFWazdRVUZETTBJc1YwRkJUeXhIUVVGUUxFTkJSREpDTzBOQlFWb3NRMEZGWml4WlFVRlhPMEZCUTB3c1VVRkJTU3hOUVVGS0xFVkJRVmtzVFVGQldpeEZRVUZ2UWl4UFFVRndRaXhEUVVSTE8wRkJSVXdzVjBGQlR5eFRRVUZWTEVOQlFWUXNRMEZCVnl4RFFVRllMRVZCUVdNc1EwRkJaQ3hGUVVGcFFpeERRVUZxUWl4RlFVRnZRanRCUVVOd1FpeHBRa0ZCVXl4RFFVRlVMRU5CUVZjc1EwRkJXQ3hGUVVGakxFTkJRV1FzUlVGQmFVSTdRVUZEWWl4blFrRkJTU3hEUVVGRExFVkJRVVVzUTBGQlJpeERRVUZFTEVWQlFVODdRVUZEVUN4dlFrRkJTU3hEUVVGRExFVkJRVVVzUTBGQlJpeERRVUZFTEVWQlFVODdRVUZEVUN4M1FrRkJTU3hKUVVGSkxFOUJRVThzVDBGQlVDeEpRVUZyUWl4VlFVRnNRaXhKUVVGblF5eFBRVUZvUXl4RFFVUkVPMEZCUlZBc2QwSkJRVWtzUTBGQlF5eERRVUZFTEVsQlFVMHNRMEZCVGl4RlFVRlRMRTlCUVU4c1JVRkJSU3hEUVVGR0xFVkJRVXNzUTBGQlF5eERRVUZFTEVOQlFWb3NRMEZCWWp0QlFVTkJMSGRDUVVGSkxFTkJRVW9zUlVGQlR5eFBRVUZQTEVWQlFVVXNRMEZCUml4RlFVRkxMRU5CUVVNc1EwRkJSQ3hEUVVGYUxFTkJRVkE3UVVGRFFTeDNRa0ZCU1N4SlFVRkpMRWxCUVVrc1MwRkJTaXhEUVVGVkxIbENRVUY1UWl4RFFVRjZRaXhIUVVFMlFpeEhRVUUzUWl4RFFVRmtMRU5CU2tjN1FVRkxVQ3d3UWtGQlRTeEZRVUZGTEVsQlFVWXNSMEZCVXl4clFrRkJWQ3hGUVVFMlFpeERRVUUzUWl4RFFVeERPMmxDUVVGWU8wRkJUMEVzYjBKQlFVa3NTVUZCU1N4RlFVRkZMRU5CUVVZc1NVRkJUenRCUVVOWUxEWkNRVUZUTEVWQlFWUTdhVUpCUkVrc1EwRlNSRHRCUVZkUUxHdENRVUZGTEVOQlFVWXNSVUZCU3l4RFFVRk1MRVZCUVZFc1NVRkJVaXhEUVVGaExFVkJRVVVzVDBGQlJpeEZRVUZYTEZWQlFWTXNRMEZCVkN4RlFVRlpPMEZCUTJoRExIZENRVUZKTEVsQlFVa3NSVUZCUlN4RFFVRkdMRVZCUVVzc1EwRkJUQ3hGUVVGUkxFTkJRVklzUTBGQlNpeERRVVEwUWp0QlFVVm9ReXd5UWtGQlR5eEZRVUZGTEVsQlFVa3NRMEZCU2l4SFFVRlJMRU5CUVZJc1EwRkJWQ3hEUVVablF6dHBRa0ZCV2l4RlFVZHlRaXhEUVVoSUxFVkJSMDBzUlVGQlJTeFBRVUZHTEVWQlFWY3NRMEZJYWtJc1JVRkhiMElzUTBGSWNFSXNSVUZIZFVJc1EwRklka0lzUlVGSE1FSXNRMEZJTVVJc1JVRllUenRoUVVGWU8wRkJaMEpCTEcxQ1FVRlBMRVZCUVVVc1EwRkJSaXhGUVVGTExFOUJRVXdzUTBGcVFrMDdVMEZCYWtJN1FVRnRRa0VzV1VGQlNTeEpRVUZKTEU5QlFVOHNUMEZCVUN4SlFVRnJRaXhWUVVGc1FpeEpRVUZuUXl4UFFVRm9ReXhEUVhCQ1dUdEJRWEZDY0VJc1lVRkJTeXhKUVVGSkxFbEJRVWtzUTBGQlNpeEZRVUZQTEVsQlFVa3NSVUZCUlN4TlFVRkdMRVZCUVZVc1IwRkJPVUlzUlVGQmJVTXNSVUZCUlN4RlFVRkZMRU5CUVVZc1EwRkJSaXhGUVVGdVF6dEJRVU5CTEdWQlFVOHNRMEZCVUN4RFFYUkNiMEk3UzBGQmNFSXNRMEYxUWtRN1FVRkRTeXhYUVVGSExFTkJRVU1zVlVGQlV5eFBRVUZVTEVWQlFXdENMRTFCUVd4Q0xFVkJRVEJDTEU5QlFURkNMRVZCUVcxRE96dEJRVVV6UkN4blFrRkJTU3huUWtGQlowSXNVVUZCVVN3d1FrRkJVaXhEUVVGb1FpeERRVVoxUkRzN1FVRkpNMFFzYlVKQlFVOHNUMEZCVUN4SFFVRnBRaXhoUVVGcVFpeERRVW95UkR0VFFVRnVReXhGUVUxMFFpeEZRVUZETERSQ1FVRXlRaXhGUVVFelFpeEZRVTV2UWl4RFFVRklMRVZCVFdVc1IwRkJSU3hEUVVGRExGVkJRVk1zVDBGQlZDeEZRVUZwUWl4TlFVRnFRaXhGUVVGM1FpeFBRVUY0UWl4RlFVRm5RenRCUVVOMFJTeG5Ra0ZCU1N4UFFVRlBMRkZCUVZFc2FVSkJRVklzUTBGQlVDeERRVVJyUlRzN1FVRkhkRVVzYlVKQlFVOHNUMEZCVUN4SFFVRnBRaXhKUVVGcVFpeERRVWh6UlR0VFFVRm9ReXhGUVV0d1F5eEZRVUZETEcxQ1FVRnJRaXhGUVVGc1FpeEZRVXhyUXl4RFFVRkdMRVZCUzFRc1IwRkJSU3hEUVVGRExGVkJRVk1zVDBGQlZDeEZRVUZwUWl4TlFVRnFRaXhGUVVGM1FpeFBRVUY0UWl4RlFVRm5RenRCUVVNM1JDeG5Ra0ZCU1N4SlFVRkpMRkZCUVZFc1owTkJRVklzUTBGQlNpeERRVVI1UkRzN1FVRkhOMFFzYlVKQlFVOHNUMEZCVUN4SFFVRnBRaXhEUVVGcVFpeERRVWcyUkR0VFFVRm9ReXhGUVVzelFpeEZRVUZETEd0RFFVRnBReXhGUVVGcVF5eEZRVXg1UWl4RFFVRkdMRVZCUzJVc1IwRkJSU3hEUVVGRExGVkJRVk1zVDBGQlZDeEZRVUZwUWl4TlFVRnFRaXhGUVVGM1FpeFBRVUY0UWl4RlFVRm5RenRCUVVNMVJTeG5Ra0ZCU1N4UFFVRlBMRkZCUVZFc1YwRkJVaXhEUVVGUUxFTkJSSGRGTzBGQlJUVkZMR2RDUVVGSkxGRkJRVkVzVVVGQlVTeFpRVUZTTEVOQlFWSXNRMEZHZDBVN1FVRkhOVVVzWjBKQlFVa3NTVUZCU1N4UlFVRlJMRkZCUVZJc1EwRkJTaXhEUVVoM1JUdEJRVWsxUlN4blFrRkJTU3hUUVVGVExGRkJRVkVzY1VKQlFWSXNRMEZCVkN4RFFVcDNSVHRCUVVzMVJTeG5Ra0ZCU1N4UlFVRlJMRkZCUVZFc2EwSkJRVklzUTBGQlVpeERRVXgzUlR0QlFVMDFSU3huUWtGQlNTeFJRVUZSTEZGQlFWRXNhMEpCUVZJc1EwRkJVaXhEUVU1M1JUczdRVUZSTlVVc2JVSkJRVThzVDBGQlVDeEhRVUZwUWp0QlFVTmlMSE5DUVVGTkxFbEJRVTQ3UVVGRFFTeDFRa0ZCVHl4TFFVRlFPMEZCUTBFc2JVSkJRVWNzUTBGQlNEdEJRVU5CTEhkQ1FVRlJMRTFCUVZJN1FVRkRRU3gxUWtGQlR5eExRVUZRTzBGQlEwRXNkVUpCUVU4c1MwRkJVRHRoUVU1S0xFTkJValJGTzFOQlFXaERMRVZCYVVJeFF5eEZRVUZETEhWQ1FVRnpRaXhEUVVGMFFpeEZRVUYzUWl4aFFVRlpMRU5CUVZvc1JVRkJZeXhWUVVGVExFTkJRVlFzUlVGQlZ5eGpRVUZoTEVWQlFXSXNSVUZCWjBJc2IwSkJRVzFDTEVWQlFXNUNMRVZCUVhOQ0xHOUNRVUZ0UWl4RlFVRnVRaXhGUVdwQ0wwTXNRMEZCUml4RlFXbENlVVVzUjBGQlJTeERRVUZETEZWQlFWTXNUMEZCVkN4RlFVRnBRaXhOUVVGcVFpeEZRVUYzUWl4UFFVRjRRaXhGUVVGblF6czdPenM3T3pzN096czdPenM3T3pzN096czdPenM3T3pzN096czdPenM3UVVGblEzSktMRzFDUVVGUExFOUJRVkFzUjBGQmFVSXNVMEZCVlN4TFFVRlVMRU5CUVdVc1MwRkJaaXhGUVVGelFqczdRVUZGZEVNc2IwSkJRVWtzWTBGQll5eFBRVUZQTEZOQlFWQXNRMEZCYVVJc1MwRkJha0k3YjBKQlEyaENMRzlDUVVGdlFpeFBRVUZQTEVsQlFWQXNRMEZCV1N4RlFVRmFMRVZCUVdkQ0xFTkJRV2hDTEUxQlFYVkNMRXRCUVhaQ096czdRVUZGY0VJc2IwSkJTRVlzUTBGR2MwTTdPMEZCVDNSRExIVkNRVUZQTEZWQlFWTXNSMEZCVkN4RlFVRmpMRk5CUVdRc1JVRkJlVUlzUzBGQmVrSXNSVUZCWjBNN08wRkJSWEpETEhkQ1FVRkpMRTlCUVU4c1UwRkJVQ3hEUVVGcFFpeFJRVUZxUWl4RFFVRXdRaXhKUVVFeFFpeERRVUVyUWl4VFFVRXZRaXhOUVVFNFF5eHBRa0ZCT1VNc1JVRkJhVVU3UVVGRGJrVXNLMEpCUVU4c1dVRkJXU3hKUVVGYUxFTkJRV2xDTEVkQlFXcENMRVZCUVhOQ0xGTkJRWFJDTEVWQlFXbERMRXRCUVdwRExFTkJRVkFzUTBGRWJVVTdjVUpCUVhKRk8wRkJSMEVzZDBKQlFVa3NVMEZCVXl4RlFVRlVPM2RDUVVOR0xGRkJRVkVzUTBGQlF5eFZRVUZWTEZWQlFWWXNSMEZCZFVJc1IwRkJka0lzUjBGQk5rSXNSVUZCTjBJc1EwRkJSQ3hKUVVGeFF5eFZRVUZWTEZOQlFWWXNSMEZCYzBJc1IwRkJkRUlzUjBGQk5FSXNSVUZCTlVJc1EwRkJja01zU1VGQmQwVXNWVUZCVlN4UlFVRldMRWRCUVhGQ0xFZEJRWEpDTEVkQlFUSkNMRVZCUVROQ0xFTkJRWGhGTzBGQlExQXNPRUpCUVZVc1RVRkJWaXhIUVVGdFFpeEhRVUZ1UWl4SFFVRjVRaXhGUVVGNlFpeERRVVJQT3pzN1FVRkhVaXh2UTBGQlowSXNRMEZCYUVJN096dEJRVVZCTEdkRFFVRlpMRWxCUVVrc1RVRkJTaXhEUVVGWExGVkJRVlVzVFVGQlZpeEZRVUZyUWl4UlFVRlJMRWRCUVZJc1EwRkJla003ZDBKQlEwRXNWVUZRUmp0M1FrRlBZeXhMUVZCa08zZENRVTl4UWl4VFFWQnlRanQzUWtGUFowTXNWVUZRYUVNc1EwRk1jVU03UVVGaGNrTXNNa0pCUVU4c1JVRkJVRHRCUVdKeFF5eDNRa0ZqYWtNc1EwRkJReXhwUWtGQlJDeEZRVUZ2UWpzN1FVRkZkRUlzY1VOQlFXRXNTVUZCU1N4TlFVRktMRU5CUVZjc1RVRkJUU3hWUVVGVkxFMUJRVllzUjBGQmJVSXNWVUZCZWtJc1JVRkJjVU1zUzBGQmFFUXNRMEZCWWl4RFFVWnpRanR4UWtGQmVFSTdPenM3T3pzN08wRkJaSEZETEhsQ1FYbENja01zUjBGQlVTeFZRVUZWTEV0QlFWWXNSMEZCYTBJc1EwRkJReXhEUVVGRUxFdEJRVThzUTBGQlVEdEJRVU14UWl3NFFrRkJWU3hEUVVGV08wRkJNVUp4UXl3eVFrRXlRamxDTEZGQlFWRXNWVUZCVlN4SlFVRldMRU5CUVdVc1IwRkJaaXhEUVVGU0xFVkJRVFpDT3p0QlFVVnNReXh2UTBGQldTeE5RVUZOTEV0QlFVNHNSMEZCWXl4TlFVRk5MRU5CUVU0c1JVRkJVeXhOUVVGVUxFTkJSbEU3UVVGSGJFTXNORUpCUVVrc1dVRkJXU3hoUVVGYUxFVkJRVEpDTzBGQlF6ZENMRzFEUVVGUExFbEJRVkFzUTBGQldTeEpRVUZKTEV0QlFVb3NRMEZCVlN4aFFVRldMRVZCUVhsQ0xFMUJRVTBzUzBGQlRpeERRVUZ5UXpzN08wRkJSRFpDTEdkRFFVbDZRaXhEUVVGRExHbENRVUZFTEVsQlFYTkNMRTFCUVUwc1RVRkJUaXhIUVVGbExFTkJRV1lzUlVGQmEwSTdRVUZETVVNc2MwTkJRVTBzUTBGQlRpeEZRVUZUTEU5QlFWUXNRMEZCYVVJc1ZVRkJha0lzUlVGQk5rSXNXVUZCVnp0QlFVTjBReXg1UTBGQlN5eEpRVUZKTEVsQlFVa3NRMEZCU2l4RlFVRlBMRWxCUVVrc1ZVRkJWU3hOUVVGV0xFZEJRVzFDTEVOQlFXNUNMRVZCUVhOQ0xFZEJRVEZETEVWQlFTdERPMEZCUXpkRExEUkRRVUZKTEZWQlFWVXNRMEZCVml4TlFVRnBRaXhMUVVGcVFpeEZRVUYzUWp0QlFVTXhRaXhyUkVGQlRTeERRVUZPTEVsQlFWY3NTMEZCV0N4RFFVUXdRanQ1UTBGQk5VSTdjVU5CUkVZN2FVTkJSREpDTEVOQlFUZENMRU5CUkRCRE96WkNRVUUxUXp0QlFWTkJMR2REUVVGSkxFMUJRVTBzVFVGQlRpeEhRVUZsTEVOQlFXWXNTVUZCYjBJc1RVRkJUU3hMUVVGT0xFZEJRV01zU1VGQlNTeE5RVUZLTEVWQlFWazdRVUZEYUVRc2MwTkJRVTBzVTBGQlRpeERRVUZuUWl4SlFVRm9RaXhEUVVGeFFpeExRVUZ5UWl4RFFVRXlRaXhOUVVFelFpeEZRVUZ0UXl4TlFVRk5MRXRCUVU0c1EwRkJXU3hEUVVGYUxFTkJRVzVETEVWQlJHZEVPelpDUVVGc1JEdEJRVWRCTEhsRFFVRmhMRTFCUVUwc1EwRkJUaXhGUVVGVExFMUJRVlFzUTBGb1FtZENPMEZCYVVJM1FpdzBRMEZCWjBJc1UwRkJhRUlzUTBGcVFqWkNPMEZCYTBJM1FpeG5RMEZCU1N4UFFVRlBMRTFCUVZBc1NVRkJhVUlzUzBGQmFrSXNSVUZCZDBJN1FVRkRNVUlzYzBOQlJEQkNPelpDUVVFMVFqdDVRa0ZzUWtZN1FVRnpRa0VzTkVKQlFVa3NWVUZCVlN4VFFVRldMRXRCUVhkQ0xFMUJRVTBzUzBGQlRpeEZRVUZoTzBGQlEzWkRMSE5EUVVGVkxGTkJRVlk3UVVGRWRVTXNlVUpCUVhwRE8zRkNRWHBDUmp0QlFUWkNRU3gzUWtGQlNTeHJRa0ZCYTBJc1NVRkJTU3hOUVVGS0xFVkJRVms3UVVGRGFFTXNORUpCUVVrc1kwRkJZeXhEUVVGRExGVkJRVlVzU1VGQlZpeERRVUZsTEVWQlFXWXNRMEZCUkN4RlFVRnhRanRCUVVOeVF5eHRRMEZCVHl4SlFVRlFMRU5CUVZrc1JVRkJXaXhGUVVSeFF6dDVRa0ZCZGtNN2NVSkJSRVlzVFVGSlR6dEJRVU5NTEN0Q1FVRlBMRWxCUVZBc1EwRkJXU3hKUVVGSkxFdEJRVW9zUTBGQlZTeGhRVUZXTEVOQlFWb3NSVUZFU3p0eFFrRktVRHRCUVU5QkxESkNRVUZQTEU5QlFVOHNUVUZCVUN4SFFVRm5RaXhMUVVGb1FpeEhRVUYzUWl4UFFVRlBMRXRCUVZBc1EwRkJZU3hEUVVGaUxFVkJRV2RDTEV0QlFXaENMRU5CUVhoQ0xFZEJRV2xFTEUxQlFXcEVMRU5CTDBRNFFqdHBRa0ZCYUVNc1EwRlFLMEk3TzBGQmVVVjBReXgxUWtGQlR5eEpRVUZRTEVOQmVrVnpRenRoUVVGMFFpeEZRVUZzUWl4RFFXaERjVW83VTBGQmFFTXNSVUUwUjI1SUxFVkJOVWRyU0N4RFFVRkdMRVZCTkVjMVJ5eEhRVUZGTEVOQlFVTXNWVUZCVXl4UFFVRlVMRVZCUVdsQ0xFMUJRV3BDTEVWQlFYZENMRTlCUVhoQ0xFVkJRV2RETEVWQlFXaERMRVZCUlZBc1JVRkdUU3hEUVVGR0xFVkJSVUVzUjBGQlJTeERRVUZETEZWQlFWTXNUMEZCVkN4RlFVRnBRaXhOUVVGcVFpeEZRVUYzUWl4UFFVRjRRaXhGUVVGblF6dEJRVU42UXl4NVFrRkVlVU03TzBGQlIzcERMR2RDUVVGSkxIVkNRVUYxUWl4UlFVRlJMSGRDUVVGU0xFTkJRWFpDTEVOQlNIRkRPenRCUVV0NlF5eG5Ra0ZCU1N4aFFVRmhMRWRCUVdJc1EwRk1jVU03UVVGTmVrTXNhVU5CUVhGQ0xGVkJRWEpDTEVWQlFXbERMRlZCUVdwRExFVkJUbmxET3p0QlFWRjZReXhuUWtGQlNTeFZRVUZWTEc5Q1FVRnZRaXhWUVVGd1FpeERRVkl5UWpzN1FVRlZla01zYlVKQlFVOHNUMEZCVUN4SFFVRnBRaXhQUVVGcVFpeERRVlo1UXpzN1FVRlpla01zY1VKQlFWTXNUMEZCVkN4RFFVRnBRaXhKUVVGcVFpeEZRVUYxUWp0QlFVTnVRaXh2UWtGQlNTeFBRVUZQTEV0QlFVc3NUMEZCVEN4RFFVRlFMRU5CUkdVN08wRkJSMjVDTEc5Q1FVRkpMRU5CUVVNc1NVRkJSQ3hGUVVGUE8wRkJRMUFzTWtKQlFVOHNTMEZCU3l4UFFVRk1MRWxCUVdkQ0xFVkJRV2hDTEVOQlJFRTdhVUpCUVZnN08wRkJTVUVzZFVKQlFVOHNTVUZCVUN4RFFWQnRRanRoUVVGMlFqdFRRVnBUTEVWQmMwSlFMRVZCUVVNc01FSkJRWGxDTEVOQlFYcENMRVZCZEVKTExFTkJRVVlzUlVGelFqQkNMRWRCUVVVc1EwRkJReXhWUVVGVExFOUJRVlFzUlVGQmFVSXNUVUZCYWtJc1JVRkJkMElzVDBGQmVFSXNSVUZCWjBNN1FVRkRia1VzWVVGQlF5eFZRVUZWTEUxQlFWWXNSVUZCYVVJN1FVRkRiRUk3T3pzN1FVRkVhMElzYjBKQlMyUXNUMEZCVHl4UFFVRlBMRTFCUVZBc1MwRkJhMElzVjBGQmJFSXNSMEZEVUN4TlFVUlBMRWRCUTBVc1QwRkJUeXhOUVVGUUxFdEJRV3RDTEZkQlFXeENMRWRCUTFRc1RVRkVVeXhIUVVOQkxFVkJSRUVzUTBGT1N6czdRVUZUYkVJc2RVSkJRVThzVDBGQlVDeEhRVUZwUWl4VlFVRnFRaXhEUVZSclFqczdRVUZYYkVJc2VVSkJRVk1zVlVGQlZDeERRVUZ2UWl4SFFVRndRaXhGUVVGNVFpeExRVUY2UWl4RlFVRm5RenRCUVVNMVFpeDNRa0ZCU1N4UFFVRlBMRWxCUVZBc1JVRkJZVHRCUVVOaUxDdENRVUZQTEV0QlFVc3NSMEZCVEN4RFFVRlFMRU5CUkdFN2NVSkJRV3BDT3p0QlFVbEJMSGxDUVVGTExFZEJRVXdzU1VGQldTeExRVUZhTEVOQlREUkNPenRCUVU4MVFpd3lRa0ZCVHl4TFFVRlFMRU5CVURSQ08ybENRVUZvUXp0aFFWaERMRU5CUVVRc1EwRnhRa2NzU1VGeVFrZ3NRMEZ4UWxFc1NVRnlRbElzUlVGeFFtRXNUMEZCVHl4TlFVRlFMRXRCUVd0Q0xGZEJRV3hDTEVkQlFXZERMRTFCUVdoRExFZEJRWGxETEU5QlFVOHNTVUZCVUN4TFFVRm5RaXhYUVVGb1FpeEhRVUU0UWl4SlFVRTVRaXhIUVVGeFF5eFBRVUZQTEUxQlFWQXNTMEZCYTBJc1YwRkJiRUlzUjBGQlowTXNUVUZCYUVNc1IwRkJlVU1zUlVGQmVrTXNRMEZ5UWpOR0xFTkJSRzFGTzFOQlFXaERMRVZCZFVKcVF5eEZRWFpDWjBNc1EwRkJSaXhGUVhWQ01VSXNSMEZCUlN4RFFVRkRMRlZCUVZNc1QwRkJWQ3hGUVVGcFFpeE5RVUZxUWl4RlFVRjNRaXhQUVVGNFFpeEZRVUZuUXp0QlFVTjZReXg1UWtGRWVVTTdPMEZCUjNwRExHZENRVUZKTEdGQlFXRXNVVUZCVVN4WlFVRlNMRU5CUVdJc1EwRkljVU03TzBGQlMzcERMRzFDUVVGUExFOUJRVkFzUjBGQmFVSXNWVUZCYWtJc1EwRk1lVU03TzBGQlQzcERMSEZDUVVGVExGVkJRVlFzUTBGQmIwSXNWVUZCY0VJc1JVRkJaME1zVDBGQmFFTXNSVUZCZVVNc1dVRkJla01zUlVGQmRVUTdRVUZEYmtRc2IwSkJRVWtzVFVGQlRTdzRRa0ZCT0VJc1ZVRkJPVUlzUTBGRWVVTTdRVUZGYmtRc2IwSkJRVWtzWVVGQllTeE5RVUZOTEc5Q1FVRk9MRU5CUm10RE96dEJRVWx1UkN4dlFrRkJTU3hsUVVGbExGZEJRVmNzVlVGQldDeEZRVUYxUWl4UFFVRjJRaXhEUVVGbUxFTkJTaXRET3p0QlFVMXVSQ3h2UWtGQlNTeHBRa0ZCYVVJc1QwRkJha0lzUlVGQk1FSTdRVUZETVVJc01FSkJRVTBzU1VGQlNTeExRVUZLTEVOQlFWVXNLMEpCUTFvc1ZVRkVXU3hIUVVORExFdEJSRVFzUjBGRldpd3lRa0ZHV1N4SFFVVnJRaXhaUVVac1FpeEhRVWRhTEdWQlNGa3NSMEZKV2l4M1EwRktXU3hIUVVrclFpeFBRVW92UWl4RFFVRm9RaXhEUVVRd1FqdHBRa0ZCT1VJN08wRkJVVUVzZFVKQlFVOHNWMEZCVnl4SFFVRllMRVZCUVdkQ0xGbEJRV2hDTEVOQlFWQXNRMEZrYlVRN1lVRkJka1E3VTBGUVV5eEZRWGRDVUN4RlFVRkRMR05CUVdFc1EwRkJZaXhGUVhoQ1N5eERRVUZHTEVWQmQwSmpMRWxCUVVjc1EwRkJReXhWUVVGVExFOUJRVlFzUlVGQmFVSXNUVUZCYWtJc1JVRkJkMElzVDBGQmVFSXNSVUZCWjBNN1FVRkRlRVFzWVVGQlF5eFZRVUZWTEUxQlFWWXNSVUZCYVVJN1FVRkRiRUlzYjBKQlFVa3NWMEZCVnl4UFFVRlBMRTFCUVZBc1MwRkJhMElzVjBGQmJFSXNSMEZCWjBNc1RVRkJhRU1zUjBGRFdDeFBRVUZQTEUxQlFWQXNTMEZCYTBJc1YwRkJiRUlzUjBGQlowTXNUVUZCYUVNc1IwRkJlVU1zUlVGQmVrTXNRMEZHWXp0QlFVZHNRaXh2UWtGQlNTeFRRVUZUTEZGQlFWRXNZMEZCVWl4RFFVRlVMRU5CU0dNN08wRkJTMnhDTEc5Q1FVRkpMRTlCUVU4c1VVRkJVQ3hMUVVGdlFpeFhRVUZ3UWl4RlFVRnBRenRCUVVOcVF5d3lRa0ZCVHl4UFFVRlFMRWRCUVdsQ0xGRkJRV3BDTEVOQlJHbERPMmxDUVVGeVF5eE5RVVZQTzBGQlEwZ3NkMEpCUVVrc1VVRkJVU3hUUVVGVExESkNRVUZVTEVOQlFWSXNRMEZFUkRzN1FVRkhTQ3gzUWtGQlNTeERRVUZETEV0QlFVUXNSVUZCVVR0QlFVTlNMR2REUVVGUkxGTkJRVk1zTWtKQlFWUXNTVUZCZDBNc1RVRkJlRU1zUTBGRVFUdHhRa0ZCV2pzN1FVRkpRU3d5UWtGQlR5eFBRVUZRTEVkQlFXbENMRXRCUVdwQ0xFTkJVRWM3YVVKQlJsQTdZVUZNUXl4RFFVRkVMRU5CYVVKSExFbEJha0pJTEVOQmFVSlJMRWxCYWtKU0xFVkJhVUpoTEU5QlFVOHNUVUZCVUN4TFFVRnJRaXhYUVVGc1FpeEhRVUZuUXl4TlFVRm9ReXhIUVVGNVF5eFBRVUZQTEVsQlFWQXNTMEZCWjBJc1YwRkJhRUlzUjBGQk9FSXNTVUZCT1VJc1IwRkJjVU1zVDBGQlR5eE5RVUZRTEV0QlFXdENMRmRCUVd4Q0xFZEJRV2RETEUxQlFXaERMRWRCUVhsRExFVkJRWHBETEVOQmFrSXpSaXhEUVVSM1JEdFRRVUZvUXl4RlFXMUNkRUlzUlVGQlF5eG5Ra0ZCWlN4RFFVRm1MRVZCYmtKdlFpeERRVUZJTEVWQmJVSkZMRWxCUVVjc1EwRkJReXhWUVVGVExFOUJRVlFzUlVGQmFVSXNUVUZCYWtJc1JVRkJkMElzVDBGQmVFSXNSVUZCWjBNN1FVRkRNVVFzZVVKQlJEQkVPenRCUVVjeFJDeHRRa0ZCVHl4UFFVRlFMRWRCUVdsQ0xGTkJRVk1zVVVGQlZDeERRVUZyUWl4RFFVRnNRaXhGUVVGeFFqdEJRVU55UXl4MVFrRkJUeXhQUVVGUExFTkJRVkFzUzBGQllTeFJRVUZpTEVsQlFYbENMRTFCUVUwc1NVRkJUaXhEUVVSTE8yRkJRWEpDTEVOQlNIbERPMU5CUVdoRExFVkJUM2hDTEVWQlVIVkNMRU5CUVVnc1JVRlBhRUlzU1VGQlJ5eERRVUZETEZWQlFWTXNUMEZCVkN4RlFVRnBRaXhOUVVGcVFpeEZRVUYzUWl4UFFVRjRRaXhGUVVGblF6dEJRVU14UXl4blFrRkJTU3huUWtGQlowSXNUVUZCVFN4UFFVRk9MRU5CUkhOQ08wRkJSVEZETEdkQ1FVRkpMRmRCUVZjc1QwRkJUeXhUUVVGUUxFTkJRV2xDTEZGQlFXcENMRU5CUmpKQ096dEJRVWt4UXl4dFFrRkJUeXhQUVVGUUxFZEJRV2xDTEdsQ1FVRnBRaXhQUVVGcVFpeERRVXA1UWpzN1FVRk5NVU1zY1VKQlFWTXNUMEZCVkN4RFFVRnBRaXhIUVVGcVFpeEZRVUZ6UWp0QlFVTnNRaXgxUWtGQlR5eFRRVUZUTEVsQlFWUXNRMEZCWXl4SFFVRmtMRTFCUVhWQ0xHZENRVUYyUWl4RFFVUlhPMkZCUVhSQ08xTkJUbFVzUlVGVlVpeEZRVlpQTEVOQlFVZ3NSVUZWUVN4SlFVRkhMRU5CUVVNc1ZVRkJVeXhQUVVGVUxFVkJRV2xDTEUxQlFXcENMRVZCUVhkQ0xFOUJRWGhDTEVWQlFXZERPMEZCUXpGRExHZENRVUZKTEZGQlFWRXNVVUZCVVN4cFFrRkJVaXhEUVVGU0xFTkJSSE5ET3p0QlFVY3hReXh0UWtGQlR5eFBRVUZRTEVkQlFXbENMRXRCUVdwQ0xFTkJTREJETzFOQlFXaERMRVZCUzFJc1JVRkJReXh0UWtGQmEwSXNSVUZCYkVJc1JVRk1UU3hEUVVGSUxFVkJTMjlDTEVsQlFVY3NRMEZCUXl4VlFVRlRMRTlCUVZRc1JVRkJhVUlzVFVGQmFrSXNSVUZCZDBJc1QwRkJlRUlzUlVGQlowTTdRVUZET1VRc1owSkJRVWtzVjBGQlZ5eFJRVUZSTEZkQlFWSXNRMEZCV0N4RFFVUXdSRHRCUVVVNVJDeG5Ra0ZCU1N4VFFVRlRMRkZCUVZFc2MwSkJRVklzUTBGQlZDeERRVVl3UkRzN1FVRkpPVVFzYlVKQlFVOHNUMEZCVUN4SFFVRnBRaXhsUVVGcVFpeERRVW80UkRzN1FVRk5PVVFzY1VKQlFWTXNaVUZCVkN4RFFVRjVRaXhKUVVGNlFpeEZRVUVyUWl4TFFVRXZRaXhGUVVGelF5eFJRVUYwUXl4RlFVRm5SRHRCUVVNMVF5eHhRa0ZCU3l4SlFVRkpMRkZCUVVvc1NVRkJaMElzUzBGQmNrSXNSVUZCTkVJN1FVRkRlRUlzZDBKQlFVa3NXVUZCV1N4TlFVRk5MRkZCUVU0c1EwRkJXaXhEUVVSdlFqczdRVUZIZUVJc2QwSkJRVWtzWTBGQll5eFRRVUZrTEVWQlFYbENPMEZCUTNwQ0xIVkRRVUZsTEVsQlFXWXNSVUZCY1VJc1VVRkJja0lzUlVGQkswSXNVMEZCTDBJc1JVRkJNRU1zVVVGQk1VTXNSVUZFZVVJN2NVSkJRVGRDTEUxQlJVOHNTVUZCU1N4UFFVRlBMRk5CUVZBc1EwRkJTaXhGUVVGMVFqdEJRVU14UWl4MVEwRkJaU3hKUVVGbUxFVkJRWEZDTEZGQlFYSkNMRVZCUVN0Q0xGTkJRUzlDTEVWQlFUQkRMRkZCUVRGRExFVkJSREJDTzBGQlJURkNMRFJDUVVGSkxGVkJRVlVzU1VGQlZpeEZRVUZuUWp0QlFVTm9RaXh6UTBGQlZTeEpRVUZXTEVOQlFXVXNTVUZCWml4RlFVTkpMRkZCUkVvc1JVRkZTU3hYUVVGWExGTkJRVk1zVVVGQlZDeERRVUZZTEVkQlFXZERMRk5CUVdoRExFTkJSa29zUTBGRVowSTdlVUpCUVhCQ08zRkNRVVpITEUxQlQwRTdRVUZEU0N3MFFrRkJTU3hUUVVGVExGTkJRVlFzUTBGQlNpeEZRVUY1UWp0QlFVTnlRaXgzUTBGQldTeEpRVUZhTEVWQlFXdENMRXRCUVd4Q0xFVkJRWGxDTEZGQlFYcENMRVZCUVcxRExGRkJRVzVETEVWQlFUWkRMRk5CUVRkRExFVkJSSEZDTzNsQ1FVRjZRaXhOUVVWUE8wRkJRMGdzYVVOQlFVc3NVVUZCVEN4SlFVRnBRaXhUUVVGcVFpeERRVVJITzNsQ1FVWlFPM0ZDUVZKSE8ybENRVXhZTzJGQlJFbzdPMEZCZFVKQkxIRkNRVUZUTEdOQlFWUXNRMEZCZDBJc1NVRkJlRUlzUlVGQk9FSXNVVUZCT1VJc1JVRkJkME1zVTBGQmVFTXNSVUZCYlVRc1VVRkJia1FzUlVGQk5rUTdRVUZEZWtRc2IwSkJRVWtzVVVGQlNpeEZRVUZqTzBGQlExWXNkMEpCUVVrc1owSkJRV2RDTEZOQlFWTXNVVUZCVkN4RFFVRm9RaXhEUVVSTk96dEJRVWRXTEhkQ1FVRkpMRU5CUVVNc1QwRkJUeXhoUVVGUUxFTkJRVVFzUlVGQmQwSTdRVUZEZUVJc05FSkJRVWtzWVVGQllTeFpRVUZpTEVWQlFUSkNPMEZCUXpOQ0xHbERRVUZMTEVsQlFVa3NVVUZCU2l4SlFVRm5RaXhoUVVGeVFpeEZRVUZ2UXp0QlFVTm9ReXh4UTBGQlN5eGxRVUZNTEVOQlFYRkNMRkZCUVhKQ0xFVkJSR2RET3paQ1FVRndRenQ1UWtGRVNpeE5RVWxQTEVsQlFVa3NZVUZCWVN4UFFVRmlMRVZCUVhOQ08wRkJRemRDTEdsRFFVRkxMRWxCUVVrc1EwRkJTaXhKUVVGVExHRkJRV1FzUlVGQk5rSTdRVUZEZWtJc2NVTkJRVXNzUzBGQlRDeERRVUZYTEVOQlFWZ3NTVUZCWjBJc1JVRkJhRUlzUTBGRWVVSTdOa0pCUVRkQ08zbENRVVJITEUxQlNVRXNTVUZCU1N4UFFVRlBMR0ZCUVZBc1MwRkJlVUlzVVVGQmVrSXNSVUZCYlVNN1FVRkRNVU1zYVVOQlFVc3NVVUZCVEN4SlFVRnBRaXhGUVVGcVFpeERRVVF3UXp0NVFrRkJka01zVFVGRlFUdEJRVU5JTEdsRFFVRkxMRkZCUVV3c1NVRkJhVUlzU1VGQmFrSXNRMEZFUnp0NVFrRkdRVHR4UWtGVVdDeE5RV05QTEVsQlFVa3NZMEZCWXl4TlFVRmtMRVZCUVhOQ08wRkJRemRDTEhORFFVRmpMRTFCUVdRc1EwRkJjVUlzU1VGQmNrSXNSVUZCTWtJc1VVRkJNMElzUlVGQmNVTXNVMEZCY2tNc1JVRkVOa0k3Y1VKQlFURkNPMmxDUVdwQ1dEdGhRVVJLT3p0QlFYZENRU3h4UWtGQlV5eFhRVUZVTEVOQlFYRkNMRWxCUVhKQ0xFVkJRVEpDTEV0QlFUTkNMRVZCUVd0RExGRkJRV3hETEVWQlFUUkRMRkZCUVRWRExFVkJRWE5FTEZOQlFYUkVMRVZCUVdsRk8wRkJRemRFTEc5Q1FVRkpMR2RDUVVGblFpeFhRVUZYTEZOQlFWTXNVVUZCVkN4RFFVRllMRWRCUVdkRExGTkJRV2hET3pzN1FVRkVlVU1zYjBKQlNYcEVMR0ZCUVdFc1dVRkJZaXhGUVVFeVFqdEJRVU16UWl4NVFrRkJTeXhKUVVGSkxGRkJRVW9zU1VGQlowSXNVMEZCY2tJc1JVRkJaME03UVVGRE5VSXNORUpCUVVrc1dVRkJXU3hWUVVGVkxGRkJRVllzUTBGQldpeERRVVIzUWpzN1FVRkhOVUlzTkVKQlFVa3NZMEZCWXl4VFFVRmtMRVZCUVhsQ08wRkJRM3BDTEdsRFFVRkxMR1ZCUVV3c1EwRkJjVUlzVVVGQmNrSXNSVUZFZVVJN2VVSkJRVGRDTEUxQlJVODdRVUZEU0N4cFEwRkJTeXhaUVVGTUxFTkJRV3RDTEZGQlFXeENMRVZCUVRSQ0xGTkJRVFZDTEVWQlJFYzdlVUpCUmxBN2NVSkJTRW83TzBGQlZVRXNNa0pCV0RKQ08ybENRVUV2UWpzN1FVRmpRU3h2UWtGQlJ5eHBRa0ZCYVVJc1UwRkJVeXhoUVVGVUxFTkJRV3BDTEVsQlEwTXNZVUZCWVN4aFFVRmlMRTFCUVdkRExHRkJRV0VzVTBGQllpeERRVUZvUXl4RlFVRjVSRHRCUVVONlJDeDVRa0ZCU3l4UlFVRk1MRWxCUVdsQ0xGTkJRV3BDTEVOQlJIbEVPMEZCUlhwRUxESkNRVVo1UkR0cFFrRkVOMFE3TzBGQlRVRXNiMEpCUVVrc1EwRkJReXhUUVVGVExFdEJRVXNzVVVGQlRDeERRVUZVTEVOQlFVUXNSVUZCTWtJN1FVRkRNMElzZVVKQlFVc3NVVUZCVEN4SlFVRnBRaXhGUVVGcVFpeERRVVF5UWp0cFFrRkJMMEk3TzBGQlNVRXNiMEpCUVVrc1YwRkJWeXhoUVVGaExFOUJRV0lzUjBGQmRVSXNSVUZCZGtJc1IwRkJORUlzVTBGQk5VSXNRMEUxUWpoRE96dEJRVGhDTjBRc2NVSkJRVXNzU1VGQlNTeERRVUZLTEVsQlFWTXNVMEZCWkN4RlFVRjVRanRCUVVOeVFpeDNRa0ZCU1N4UlFVRlJMRlZCUVZVc1EwRkJWaXhEUVVGU0xFTkJSR2xDTzBGQlJYSkNMSGxDUVVGTExGRkJRVXdzUlVGQlpTeERRVUZtTEVsQlFXOUNMRXRCUVVNc1MwRkJWU3hUUVVGV0xFZEJRWFZDTEZGQlFYaENMRWRCUVcxRExFdEJRVzVETEVOQlJrTTdhVUpCUVhwQ08yRkJPVUpLT3p0QlFXOURRU3h4UWtGQlV5eFpRVUZVTEVOQlFYTkNMRXRCUVhSQ0xFVkJRVFpDTzBGQlEzcENMRzlDUVVGSkxFOUJRVThzWTBGQlVDeEZRVUYxUWp0QlFVTjJRaXd5UWtGQlR5eFBRVUZQTEdOQlFWQXNRMEZCYzBJc1MwRkJkRUlzUTBGQlVDeERRVVIxUWp0cFFrRkJNMElzVFVGRlR5eEpRVUZKTEUxQlFVMHNVMEZCVGl4RlFVRnBRanRCUVVONFFpd3lRa0ZCVHl4TlFVRk5MRk5CUVU0c1EwRkVhVUk3YVVKQlFYSkNMRTFCUlVFc1NVRkJTU3hOUVVGTkxGZEJRVTRzUlVGQmJVSTdRVUZETVVJc01rSkJRVThzVFVGQlRTeFhRVUZPTEVOQlFXdENMRk5CUVd4Q0xFTkJSRzFDTzJsQ1FVRjJRanRoUVV4WU8xTkJla1k0UWl4RlFXMUhOVUlzUlVGQlF5eDNRa0ZCZFVJc1JVRkJka0lzUlVGQk1FSXNZVUZCV1N4RlFVRmFMRVZCYmtkQkxFTkJRVWdzUlVGdFIyOUNMRWxCUVVjc1EwRkJReXhWUVVGVExFOUJRVlFzUlVGQmFVSXNUVUZCYWtJc1JVRkJkMElzVDBGQmVFSXNSVUZCWjBNN1FVRkRiRVlzWjBKQlFVa3NWMEZCVnl4UlFVRlJMR2xDUVVGU0xFTkJRVmdzUTBGRU9FVTdPMEZCUjJ4R0xHZENRVUZKTEd0Q1FVRnJRaXhSUVVGUkxHOUNRVUZTTEVOQlFXeENMRU5CU0RoRk96dEJRVXRzUml4blFrRkJTU3hWUVVGVkxGRkJRVkVzYzBKQlFWSXNRMEZCVml4RFFVdzRSVHRCUVUxc1JpeG5Ra0ZCU1N4VlFVRlZMRkZCUVZFc2MwSkJRVklzUTBGQlZpeERRVTQ0UlR0QlFVOXNSaXhuUWtGQlNTeFhRVUZYTEZGQlFWRXNkVUpCUVZJc1EwRkJXQ3hEUVZBNFJUdEJRVkZzUml4blFrRkJTU3hqUVVGakxGRkJRVkVzTUVKQlFWSXNRMEZCWkN4RFFWSTRSVHM3UVVGVmJFWXNiVUpCUVU4c1QwRkJVQ3hIUVVGcFFpeGhRVUZxUWl4RFFWWnJSanM3UVVGWmJFWXNjVUpCUVZNc1lVRkJWQ3hEUVVGMVFpeExRVUYyUWl4RlFVRTRRaXhKUVVFNVFpeEZRVUZ2UXp0QlFVTm9ReXh2UWtGQlNTeE5RVUZOTEU5QlFVOHNTMEZCU3l4UlFVRk1MRWxCUVdsQ0xGRkJRV3BDTEVkQlFUUkNMRkZCUVc1RExFTkJSSE5DTzBGQlJXaERMRzlDUVVGSkxFOUJRVThzVDBGQlR5eExRVUZMTEVsQlFVd3NSMEZCV1N4SlFVRnVRaXhEUVVaeFFqczdRVUZKYUVNc2QwSkJRVkVzV1VGQldTeExRVUZhTEVWQlFXMUNMRU5CUVc1Q0xFTkJTbmRDT3p0QlFVMW9ReXh2UWtGQlNTeFRRVUZUTEV0QlFWUXNRMEZCU2l4RlFVRnhRanRCUVVOcVFpd3lRa0ZCVHl4TlFVRk5MRWxCUVU0c1JVRkJVQ3hEUVVScFFqdHBRa0ZCY2tJc1RVRkZUeXhKUVVGSkxGRkJRVkVzUzBGQlVpeERRVUZLTEVWQlFXOUNPMEZCUTNaQ0xESkNRVUZQTEVsQlFVa3NZMEZCU2l4RFFVRnRRaXhOUVVGTkxFbEJRVTRzUTBGQk1VSXNRMEZFZFVJN2FVSkJRWEJDTEUxQlJVRXNTVUZCU1N4RFFVRkRMRkZCUVZFc1MwRkJVaXhEUVVGRUxFVkJRV2xDTzBGQlEzaENMSGRDUVVGSkxFbEJRVW9zUlVGQlZUdEJRVU5PTERaQ1FVRkxMSE5EUVVGTUxFVkJRVFpETEV0QlFUZERMRVZCUkUwN2NVSkJRVlk3UVVGSFFTd3lRa0ZCVHl4SlFVRlFMRU5CU25kQ08ybENRVUZ5UWpzN1FVRlBVQ3h2UWtGQlNTeFBRVUZQTEV0QlFVTXNRMEZCVFN4VFFVRk9MRXRCUVc5Q0xFbEJRWEJDTEVkQlExSXNTVUZCU1N4aFFVRktMRU5CUVd0Q0xFMUJRVTBzVDBGQlRpeERRVVJZTEVkQlJWQXNTVUZCU1N4bFFVRktMRU5CUVc5Q0xFMUJRVTBzVTBGQlRpeEZRVUZwUWl4TlFVRk5MRTlCUVU0c1EwRkdPVUlzUTBGcVFuRkNPenRCUVhGQ2FFTXNiMEpCUVVrc1VVRkJVU3hOUVVGTkxGVkJRVTRzUTBGeVFtOUNPMEZCYzBKb1F5eG5RMEZCWjBJc1NVRkJhRUlzUlVGQmMwSXNTMEZCZEVJc1JVRjBRbWRET3p0QlFYZENhRU1zYjBKQlFVa3NWMEZCVnl4TlFVRk5MRkZCUVU0c1EwRjRRbWxDT3p0QlFUQkNhRU1zY1VKQlFVc3NTVUZCU1N4SlFVRkpMRU5CUVVvc1JVRkJUeXhKUVVGSkxGTkJRVk1zVFVGQlZDeEZRVUZwUWl4SFFVRnlReXhGUVVFd1F6dEJRVU4wUXl4M1FrRkJTU3haUVVGWkxHTkJRV01zVTBGQlV5eERRVUZVTEVOQlFXUXNSVUZCTWtJc1NVRkJNMElzUTBGQldpeERRVVJyUXp0QlFVVjBReXgzUWtGQlNTeFRRVUZLTEVWQlFXVTdRVUZEV0N3MlFrRkJTeXhYUVVGTUxFTkJRV2xDTEZOQlFXcENMRVZCUkZjN2NVSkJRV1k3YVVKQlJrbzdPMEZCVDBFc2RVSkJRVThzU1VGQlVDeERRV3BEWjBNN1lVRkJjRU03VTBGYWEwUXNSVUZuUkdoRUxFVkJRVU1zTkVKQlFUSkNMRVZCUVROQ0xFVkJRVGhDTEhkQ1FVRjFRaXhGUVVGMlFpeEZRVUV3UWl4M1FrRkJkVUlzUlVGQmRrSXNSVUZCTUVJc2VVSkJRWGRDTEVWQlFYaENMRVZCUVRKQ0xITkNRVUZ4UWl4RlFVRnlRaXhGUVVGM1FpeHRRa0ZCYTBJc1JVRkJiRUlzUlVGb1JIWkdMRU5CUVVnc1JVRm5SR2xJTEVsQlFVY3NRMEZCUXl4VlFVRlRMRTlCUVZRc1JVRkJhVUlzVFVGQmFrSXNSVUZCZDBJc1QwRkJlRUlzUlVGQlowTTdPenM3T3pzN1FVRlBiazBzWjBKQlFVa3NWVUZCVlN4RlFVRldMRU5CVUN0TU96dEJRVk51VFN4dFFrRkJUeXhQUVVGUUxFZEJRV2xDTEZGQlFXcENMRU5CVkcxTk96dEJRVmR1VFN4eFFrRkJVeXhSUVVGVUxFTkJRV3RDTEZGQlFXeENMRVZCUVRSQ0xFbEJRVFZDTEVWQlFXdERMRTlCUVd4RExFVkJRVEpETEV0QlFUTkRMRVZCUVd0RU8wRkJRemxETEc5Q1FVRkpMRU5CUVVNc1QwRkJSQ3hKUVVGWkxGRkJRVkVzVFVGQlVpeExRVUZ0UWl4RFFVRnVRaXhGUVVGelFqdEJRVU5zUXl3eVFrRkJUeXhGUVVGUUxFTkJSR3RETzJsQ1FVRjBReXhOUVVWUE8wRkJRMGdzTkVKQlFWRXNTVUZCVWl4RFFVRmhMRk5CUVdJc1JVRkVSenRCUVVWSUxESkNRVUZQTEZGQlFWRXNVVUZCVWl4RlFVRnJRaXhKUVVGc1FpeEZRVUYzUWl4UFFVRjRRaXhGUVVGcFF5eExRVUZxUXl4RlFVRjNReXhEUVVGNFF5eERRVUZRTEVOQlJrYzdhVUpCUmxBN1lVRkVTanM3UVVGVFFTeHhRa0ZCVXl4UFFVRlVMRU5CUVdsQ0xGRkJRV3BDTEVWQlFUSkNMRWxCUVROQ0xFVkJRV2xETEU5QlFXcERMRVZCUVRCRExFdEJRVEZETEVWQlFXbEVMRk5CUVdwRUxFVkJRVFJFTzBGQlEzaEVMSGRDUVVGUkxGTkJRVk1zUlVGQlZDeERRVVJuUkRzN1FVRkplRVFzYjBKQlFVa3NVVUZCU2l4RlFVRmpPMEZCUTFZc2QwSkJRVWtzWVVGQllTeFBRVUZpTEVWQlFYTkNMRk5CUVhSQ0xFVkJRV2xETEZOQlFXcERMRU5CUVVvc1JVRkJhVVE3UVVGRE4wTXNPRUpCUVUwc1UwRkJUaXhKUVVGdFFpeFJRVUZ1UWl4RFFVUTJRenR4UWtGQmFrUTdPMEZCU1VFc2QwSkJRVWtzV1VGQldTeExRVUZMTEZGQlFVd3NRMEZNVGpzN1FVRlBWaXgzUWtGQlNTeFRRVUZLTEVWQlFXVTdPMEZCUlZnc05FSkJRVWtzWVVGQllTeFRRVUZUTEZWQlFWUXNRMEZHVGpzN1FVRkpXQ3cyUWtGQlN5eEpRVUZKTEVsQlFVa3NRMEZCU2l4RlFVRlBMRWxCUVVrc1MwRkJTeXhSUVVGTUxFTkJRV01zVFVGQlpDeEZRVUZ6UWl4SFFVRXhReXhGUVVFclF6dEJRVU16UXl4NVEwRkJZU3hEUVVGaUxFTkJSREpET3p0QlFVY3pReXhuUTBGQlNTeFRRVUZUTEZWQlFWVXNRMEZCVml4TFFVRm5RaXhQUVVGb1FpeERRVWc0UWp0QlFVa3pReXhuUTBGQlNTeFpRVUZaTEdGQlFXRXNUMEZCVHl4TFFVRlFMRWxCUVdkQ0xFTkJRV2hDTEVOQlFXSTdPenRCUVVveVFpeG5RMEZQZGtNc1lVRkJZU3hQUVVGaUxFVkJRWE5DTEZOQlFYUkNMRVZCUVdsRExGTkJRV3BETEVOQlFVb3NSVUZCYVVRN1FVRkROME1zZDBOQlFWRXNWMEZCVnl4RFFVRllMRU5CUVZJc1JVRkJkVUlzVFVGQmRrSXNSVUZCSzBJc1QwRkJMMElzUlVGQmQwTXNTMEZCZUVNc1JVRkJLME1zVTBGQkwwTXNSVUZFTmtNN05rSkJRV3BFT3p0QlFVbEJMSGREUVVGWkxGTkJRVm9zUTBGWU1rTTdlVUpCUVM5RE8zRkNRVXBLTzJsQ1FWQktPenRCUVRKQ1FTeDFRa0ZCVHl4TFFVRlFMRU5CTDBKM1JEdGhRVUUxUkRzN08wRkJjRUp0VFN4eFFrRjFSREZNTEZsQlFWUXNRMEZCYzBJc1QwRkJkRUlzUlVGQkswSXNTVUZCTDBJc1JVRkJjVU1zUzBGQmNrTXNSVUZCTkVNN1FVRkRlRU1zYjBKQlFVa3NVVUZCVVN4TlFVRlNMRXRCUVcxQ0xFTkJRVzVDTEVWQlFYTkNPMEZCUTNSQ0xESkNRVUZQTEV0QlFWQXNRMEZFYzBJN2FVSkJRVEZDT3p0QlFVbEJMRzlDUVVGSkxGZEJRVmNzUTBGQldDeERRVXh2UXp0QlFVMTRReXh2UWtGQlNTeFhRVUZYTEZGQlFWRXNUVUZCVWl4SFFVRnBRaXhEUVVGcVFpeERRVTU1UWp0QlFVOTRReXh2UWtGQlNTeFpRVUZLTEVOQlVIZERPMEZCVVhoRExHOUNRVUZKTEZkQlFVb3NRMEZTZDBNN08wRkJWWGhETEhWQ1FVRlBMRmxCUVZrc1VVRkJXaXhGUVVGelFqdEJRVU42UWl4dFEwRkJaU3hEUVVGRkxGZEJRVmNzVVVGQldDeERRVUZFTEVkQlFYZENMRU5CUVhoQ0xFbEJRVGhDTEVOQlFTOUNMRU5CUkZVN1FVRkZla0lzYTBOQlFXTXNVVUZCVVN4WlFVRlNMRU5CUVdRc1EwRkdlVUk3TzBGQlNYcENMSGRDUVVGSkxHRkJRV0VzVVVGQllpeEZRVUYxUWp0QlFVTjJRaXdyUWtGQlR5eGxRVUZsTEVsQlFXWXNTVUZCZFVJc1pVRkJaU3hMUVVGbUxFTkJSRkE3Y1VKQlFUTkNMRTFCUlU4c1NVRkJTU3hqUVVGakxFbEJRV1FzUlVGQmIwSTdRVUZETTBJc2JVTkJRVmNzWlVGQlpTeERRVUZtTEVOQlJHZENPM0ZDUVVGNFFpeE5RVVZETEVsQlFVa3NZMEZCWXl4TFFVRmtMRVZCUVhGQ08wRkJRemRDTEcxRFFVRlhMR1ZCUVdVc1EwRkJaaXhEUVVSclFqdHhRa0ZCZWtJc1RVRkZSRHRCUVVOSUxDdENRVUZQTEVsQlFWQXNRMEZFUnp0eFFrRkdRenRwUWtGU1dqczdRVUZsUVN4MVFrRkJUeXhMUVVGUUxFTkJla0ozUXp0aFFVRTFRenM3UVVFMFFrRXNjVUpCUVZNc1UwRkJWQ3hEUVVGdFFpeERRVUZ1UWl4RlFVRnpRaXhEUVVGMFFpeEZRVUY1UWp0QlFVTnlRaXgxUWtGQlR5eEpRVUZKTEVOQlFVb3NSMEZCVVN4RFFVRlNMRWRCUVZrc1EwRkJReXhEUVVGRUxFTkJSRVU3WVVGQmVrSTdVMEZ1Um0xTExFVkJkVVpxU3l4RlFYWkdaMHNzUTBGQlNDeEZRWFZHZWtvc1NVRkJSeXhEUVVGRExGVkJRVk1zVDBGQlZDeEZRVUZwUWl4TlFVRnFRaXhGUVVGM1FpeFBRVUY0UWl4RlFVRm5RenRCUVVNeFF5eG5Ra0ZCU1N4clFrRkJhMElzVVVGQlVTeHZRa0ZCVWl4RFFVRnNRaXhEUVVSelF6czdRVUZITVVNc1owSkJRVWtzVjBGQlZ5eFJRVUZSTEhWQ1FVRlNMRU5CUVZnc1EwRkljME03UVVGSk1VTXNaMEpCUVVrc1UwRkJVeXhSUVVGUkxHOUNRVUZTTEVOQlFWUXNRMEZLYzBNN08wRkJUVEZETEdkQ1FVRkpMR1ZCUVdVc1VVRkJVU3hwUWtGQlVpeERRVUZtTEVOQlRuTkRPenRCUVZFeFF5eHRRa0ZCVHl4UFFVRlFMRWRCUVdsQ0xGVkJRV3BDTEVOQlVqQkRPenRCUVZVeFF5eHhRa0ZCVXl4VlFVRlVMRU5CUVc5Q0xFMUJRWEJDTEVWQlFUUkNMRTlCUVRWQ0xFVkJRWEZETEdGQlFYSkRMRVZCUVc5RU8wRkJRMmhFTEc5Q1FVRkpMRTlCUVU4c1QwRkJUeXhKUVVGUUxFTkJSSEZETzBGQlJXaEVMRzlDUVVGSkxGRkJRVkVzVDBGQlR5eExRVUZRTEVOQlJtOURPMEZCUjJoRUxHOUNRVUZKTEZGQlFWRXNUMEZCVHl4TFFVRlFMRU5CU0c5RE96dEJRVXRvUkN4M1FrRkJVU3hKUVVGU08wRkJRMGtzZVVKQlFVc3NUMEZCVHl4TlFVRlFPMEZCUTBRc0swSkJRVThzVjBGQlZ5eFBRVUZZTEVWQlFXOUNMRXRCUVhCQ0xFTkJRVkFzUTBGRVNqdEJRVVJLTEhsQ1FVZFRMRTlCUVU4c1RVRkJVRHRCUVVORUxDdENRVUZQTEZkQlFWY3NUMEZCV0N4RlFVRnZRaXhMUVVGd1FpeEZRVUV5UWl4aFFVRXpRaXhEUVVGUUxFTkJSRW83UVVGSVNpeDVRa0ZMVXl4UFFVRlBMRXRCUVZBN1FVRkRSQ3dyUWtGQlR5eFpRVUZaTEU5QlFWb3NSVUZCY1VJc1MwRkJja0lzUlVGQk5FSXNTMEZCTlVJc1JVRkJiVU1zWVVGQmJrTXNRMEZCVUN4RFFVUktPMEZCVEVvc2VVSkJUMU1zVDBGQlR5eE5RVUZRTzBGQlEwUXNLMEpCUVU4c1dVRkJXU3hQUVVGYUxFVkJRWEZDTEV0QlFYSkNMRVZCUVRSQ0xFdEJRVFZDTEVWQlFXMURMR0ZCUVc1RExFTkJRVkFzUTBGRVNqdEJRVkJLTEhsQ1FWTlRMRTlCUVU4c1MwRkJVRHRCUVVORUxDdENRVUZQTEZkQlFWY3NUMEZCV0N4RlFVRnZRaXhMUVVGd1FpeEZRVUV5UWl4TFFVRXpRaXhGUVVGclF5eGhRVUZzUXl4RFFVRlFMRU5CUkVvN1FVRlVTaXg1UWtGWFV5eFBRVUZQTEV0QlFWQTdRVUZEUkN4M1EwRkJaMElzVDBGQmFFSXNSVUZCZVVJc1MwRkJla0lzUlVGRVNqdEJRVVZKTEN0Q1FVRlBMRTlCUVZBc1EwRkdTanRCUVZoS0xIbENRV05UTEU5QlFVOHNTMEZCVUR0QlFVTkVMSGREUVVGblFpeFBRVUZvUWl4RlFVRjVRaXhMUVVGNlFpeEZRVUZuUXl4TlFVRk5MRlZCUVU0c1EwRkJhRU1zUTBGRVNqdEJRVVZKTEN0Q1FVRlBMRTlCUVZBc1EwRkdTanRCUVdSS0xIbENRV2xDVXl4UFFVRlBMRXRCUVZBN1FVRkRSQ3dyUWtGQlR5eFpRVUZaTEU5QlFWb3NSVUZEU0N4alFVRmpMRXRCUVdRc1EwRkJiMElzVDBGQmNFSXNSVUZCTmtJc1MwRkJOMElzUlVGQmIwTXNZVUZCY0VNc1EwRkVSeXhEUVVGUUxFTkJSRW83UVVGcVFrbzdRVUZ4UWxFc0swSkJRVThzVDBGQlVDeERRVVJLTzBGQmNFSktMR2xDUVV4blJEdGhRVUZ3UkRzN1FVRTRRa0VzY1VKQlFWTXNWVUZCVkN4RFFVRnZRaXhQUVVGd1FpeEZRVUUyUWl4TFFVRTNRaXhGUVVGdlF6dEJRVU5vUXl4dlFrRkJTU3hoUVVGaExGRkJRVkVzVlVGQlVpeERRVVJsT3p0QlFVZG9ReXh2UWtGQlNTeFZRVUZLTEVWQlFXZENPMEZCUTFvc0swSkJRVmNzVjBGQldDeERRVUYxUWl4UFFVRjJRaXhGUVVSWk8ybENRVUZvUWpzN1FVRkpRU3c0UWtGQll5eFBRVUZrTEVWQlFYVkNMRXRCUVhaQ0xFVkJVR2RET3p0QlFWTm9ReXgxUWtGQlR5eEpRVUZRTEVOQlZHZERPMkZCUVhCRE96dEJRVmxCTEhGQ1FVRlRMRlZCUVZRc1EwRkJiMElzVlVGQmNFSXNSVUZCWjBNc1MwRkJhRU1zUlVGQmRVTXNZVUZCZGtNc1JVRkJjMFE3UVVGRGJFUXNiMEpCUVVrc1ZVRkJWU3hqUVVGakxFMUJRV1FzUTBGQmNVSXNTMEZCY2tJc1JVRkJORUlzWVVGQk5VSXNRMEZCVml4RFFVUTRRenM3UVVGSGJFUXNiMEpCUVVrc1ZVRkJTaXhGUVVGblFqdEJRVU5hTEN0Q1FVRlhMRmRCUVZnc1EwRkJkVUlzVDBGQmRrSXNSVUZFV1R0cFFrRkJhRUk3TzBGQlNVRXNkVUpCUVU4c1ZVRkJVQ3hEUVZCclJEdGhRVUYwUkRzN1FVRlZRU3h4UWtGQlV5eFhRVUZVTEVOQlFYRkNMRTlCUVhKQ0xFVkJRVGhDTEZOQlFUbENMRVZCUVhsRExFdEJRWHBETEVWQlFXZEVMR0ZCUVdoRUxFVkJRU3RFTzBGQlF6TkVMRzlDUVVGSkxFOUJRVW9zUTBGRU1rUTdPMEZCUnpORUxHOUNRVUZKTEZGQlFWRXNVVUZCVWl4TFFVRnhRaXhEUVVGeVFpeEZRVUYzUWp0QlFVTjRRaXcwUWtGQlVTeFhRVUZTTEVOQlFXOUNMRU5CUVhCQ0xFVkJRWFZDTEZGQlFWRXNUVUZCVWl4RlFVRm5RaXhOUVVGTkxFbEJRVTRzUTBGQmRrTXNRMEZFZDBJN1FVRkZlRUlzT0VKQlFWVXNUMEZCVml4RFFVWjNRanRwUWtGQk5VSXNUVUZIVHp0QlFVTklMSGRDUVVGSkxHRkJRV0VzVVVGQlVTeFZRVUZTTEVOQlJHUTdRVUZGU0N3NFFrRkJWU3hqUVVGakxFMUJRV1FzUTBGQmNVSXNTMEZCY2tJc1JVRkJORUlzWVVGQk5VSXNRMEZCVml4RFFVWkhPenRCUVVsSUxIZENRVUZKTEdOQlFXTXNXVUZCV1N4UFFVRmFMRVZCUVhGQ08wRkJRMjVETEcxRFFVRlhMRmxCUVZnc1EwRkJkMElzVDBGQmVFSXNSVUZCYVVNc1QwRkJha01zUlVGRWJVTTdjVUpCUVhaRE8ybENRVkJLT3p0QlFWbEJMSFZDUVVGUExFOUJRVkFzUTBGbU1rUTdZVUZCTDBRN08wRkJhMEpCTEhGQ1FVRlRMRmRCUVZRc1EwRkJjVUlzVDBGQmNrSXNSVUZCT0VJc1UwRkJPVUlzUlVGQmVVTXNUVUZCZWtNc1JVRkJhVVFzWVVGQmFrUXNSVUZCWjBVN1FVRkROVVFzYjBKQlFVa3NWMEZCVnl4aFFVRmhMRk5CUVdJc1JVRkJkMElzVFVGQmVFSXNRMEZCV0N4RFFVUjNSRHRCUVVVMVJDeHZRa0ZCU1N4UFFVRktMRU5CUmpSRU96dEJRVWsxUkN4dlFrRkJTU3hSUVVGS0xFVkJRV003UVVGRFZpdzRRa0ZCVlN4UFFVRlBMRTFCUVZBc1EwRkJZeXhUUVVGa0xFVkJRWGxDTEU5QlFYcENMRXRCUVhGRExFOUJRWEpETEVOQlJFRTdhVUpCUVdRc1RVRkZUenRCUVVOSUxEaENRVUZWTEdOQlFXTXNUVUZCWkN4RFFVRnhRaXhOUVVGeVFpeEZRVUUyUWl4aFFVRTNRaXhEUVVGV0xFTkJSRWM3YVVKQlJsQTdPMEZCVFVFc2IwSkJRVWtzWVVGQllTeFJRVUZSTEZWQlFWSXNRMEZXTWtNN08wRkJXVFZFTEc5Q1FVRkpMR05CUVdNc1dVRkJXU3hQUVVGYUxFVkJRWEZDTzBGQlEyNURMQ3RDUVVGWExGbEJRVmdzUTBGQmQwSXNUMEZCZUVJc1JVRkJhVU1zVDBGQmFrTXNSVUZFYlVNN2FVSkJRWFpET3p0QlFVbEJMRzlDUVVGSkxFTkJRVU1zVVVGQlJDeEZRVUZYTzBGQlExZ3NhME5CUVdNc1QwRkJaQ3hGUVVGMVFpeFRRVUYyUWl4RlFVUlhPMmxDUVVGbU96dEJRVWxCTEhWQ1FVRlBMRTlCUVZBc1EwRndRalJFTzJGQlFXaEZPenRCUVhWQ1FTeHhRa0ZCVXl4VlFVRlVMRU5CUVc5Q0xFOUJRWEJDTEVWQlFUWkNMRk5CUVRkQ0xFVkJRWGRETEV0QlFYaERMRVZCUVN0RExHRkJRUzlETEVWQlFUaEVPMEZCUXpGRUxHOUNRVUZKTEdGQlFXRXNVVUZCVVN4VlFVRlNMRU5CUkhsRE8wRkJSVEZFTEc5Q1FVRkpMRlZCUVZVc1kwRkJZeXhOUVVGa0xFTkJRWEZDTEV0QlFYSkNMRVZCUVRSQ0xHRkJRVFZDTEVOQlFWWXNRMEZHYzBRN08wRkJTVEZFTEc5Q1FVRkpMR05CUVdNc1dVRkJXU3hQUVVGYUxFVkJRWEZDTzBGQlEyNURMQ3RDUVVGWExGbEJRVmdzUTBGQmQwSXNUMEZCZUVJc1JVRkJhVU1zVDBGQmFrTXNSVUZFYlVNN2FVSkJRWFpET3p0QlFVbEJMSFZDUVVGUExFOUJRVkFzUTBGU01FUTdZVUZCT1VRN08wRkJWMEVzY1VKQlFWTXNZVUZCVkN4RFFVRjFRaXhQUVVGMlFpeEZRVUZuUXl4RFFVRm9ReXhGUVVGdFF6dEJRVU12UWl4dlFrRkJTU3hQUVVGUExFVkJRVVVzVDBGQlJpeExRVUZqTEZWQlFYSkNMRWxCUVcxRExGTkJRVk1zUTBGQlZDeERRVUZ1UXl4RlFVRm5SRHRCUVVOb1JDeHpRa0ZCUlN4UFFVRkdMRU5CUVZVc1QwRkJWaXhGUVVSblJEdHBRa0ZCY0VRN1lVRkVTanM3UVVGTlFTeHhRa0ZCVXl4bFFVRlVMRU5CUVhsQ0xFOUJRWHBDTEVWQlFXdERMRXRCUVd4RExFVkJRWGxETzBGQlEzSkRMRzlDUVVGSkxHRkJRV0VzVVVGQlVTeFZRVUZTTEVOQlJHOUNPMEZCUlhKRExHOUNRVUZKTEZOQlFWTXNSVUZCVkN4RFFVWnBRenRCUVVkeVF5eHZRa0ZCU1N4SlFVRktMRU5CU0hGRE8wRkJTWEpETEc5Q1FVRkpMRTFCUVVvc1EwRktjVU03UVVGTGNrTXNiMEpCUVVrc1RVRkJTaXhEUVV4eFF6czdRVUZQY2tNc2NVSkJRVXNzU1VGQlNTeEpRVUZKTEVOQlFVb3NSVUZCVHl4SlFVRkpMRTFCUVUwc1QwRkJUaXhEUVVGakxFMUJRV1FzUlVGQmMwSXNSMEZCTVVNc1JVRkJLME03UVVGRE0wTXNOa0pCUVZNc1RVRkJUU3hQUVVGT0xFTkJRV01zUTBGQlpDeERRVUZVTEVOQlJESkRPMEZCUlRORExESkNRVUZQTEZkQlFWY3NUMEZCVHl4SlFVRlFMRU5CUVd4Q0xFTkJSakpETzBGQlJ6TkRMSGRDUVVGSkxFOUJRVThzUjBGQlVDeEZRVUZaTzBGQlExb3NLMEpCUVU4c1QwRkJUeXhIUVVGUUxFTkJRVkFzUjBGQmNVSXNTVUZCY2tJc1EwRkVXVHR4UWtGQmFFSTdRVUZIUVN3MFFrRkJVU3hYUVVGU0xFTkJRVzlDTEVsQlFYQkNMRVZCVGpKRE8ybENRVUV2UXpzN1FVRlRRU3h2UWtGQlNTeFRRVUZUTEZkQlFWY3NUVUZCV0N4RFFXaENkMEk3UVVGcFFuSkRMSEZDUVVGTExFbEJRVWtzU1VGQlNTeERRVUZLTEVWQlFVOHNTVUZCU1N4TlFVRk5MRTlCUVU0c1EwRkJZeXhOUVVGa0xFVkJRWE5DTEVkQlFURkRMRVZCUVN0RE8wRkJRek5ETERaQ1FVRlRMRTFCUVUwc1QwRkJUaXhEUVVGakxFTkJRV1FzUTBGQlZDeERRVVF5UXp0QlFVVXpReXd5UWtGQlR5eFBRVUZQTEU5QlFVOHNSMEZCVUN4RFFVRmtPenRCUVVZeVF5d3lRa0ZKTTBNc1EwRkJVU3haUVVGU0xFTkJRWEZDTEVsQlFYSkNMRVZCUVRKQ0xFOUJRVThzUlVGQlVDeEpRVUZoTEZGQlFXSXNSMEZCZDBJc1NVRkJlRUlzUjBGQkswSXNWMEZCVnl4UFFVRlBMRVZCUVZBc1EwRkJNVU1zUTBGQk0wSXNRMEZLTWtNN2FVSkJRUzlETzJGQmFrSktPenRCUVhsQ1FTeHhRa0ZCVXl4WFFVRlVMRU5CUVhGQ0xFOUJRWEpDTEVWQlFUaENMRTlCUVRsQ0xFVkJRWFZETzBGQlEyNURMRzlDUVVGSkxGZEJRVmNzVDBGQldDeEpRVUZ6UWl4WlFVRlpMRTlCUVZvc1NVRkJkVUlzVVVGQlVTeFZRVUZTTEVWQlFXOUNPMEZCUTJwRkxEUkNRVUZSTEZWQlFWSXNRMEZCYlVJc1dVRkJia0lzUTBGQlowTXNUMEZCYUVNc1JVRkJlVU1zVDBGQmVrTXNSVUZFYVVVN2FVSkJRWEpGT3p0QlFVbEJMSFZDUVVGUExFOUJRVkFzUTBGTWJVTTdZVUZCZGtNN1UwRnFTbFVzUlVGNVNsSXNSVUZCUXl4NVFrRkJkMElzUlVGQmVFSXNSVUZCTWtJc2MwSkJRWEZDTEVWQlFYSkNMRVZCUVhkQ0xITkNRVUZ4UWl4RlFVRnlRaXhGUVVGM1FpeHRRa0ZCYTBJc1JVRkJiRUlzUlVGNlNuSkZMRU5CUVVnc1JVRjVTaXRHTEVsQlFVY3NRMEZCUXl4VlFVRlRMRTlCUVZRc1JVRkJhVUlzVFVGQmFrSXNSVUZCZDBJc1QwRkJlRUlzUlVGQlowTTdRVUZEZWtrc1owSkJRVWtzVjBGQlZ5eFJRVUZSTEdsQ1FVRlNMRU5CUVZnc1EwRkVjVWs3UVVGRmVra3NaMEpCUVVrc1ZVRkJWU3hSUVVGUkxGbEJRVklzUTBGQlZpeERRVVp4U1RzN1FVRkpla2tzWjBKQlFVa3NVMEZCVXl4UlFVRlJMR3RDUVVGU0xFTkJRVlFzUTBGS2NVazdRVUZMZWtrc1owSkJRVWtzVjBGQlZ5eFJRVUZSTEdGQlFWSXNRMEZCV0N4RFFVeHhTVHRCUVUxNlNTeG5Ra0ZCU1N4VlFVRlZMRkZCUVZFc1dVRkJVaXhEUVVGV0xFTkJUbkZKTzBGQlQzcEpMRzFDUVVGUExFOUJRVkFzUjBGQmFVSXNTMEZCYWtJc1EwRlFlVWs3TzBGQlUzcEpMSEZDUVVGVExFdEJRVlFzUTBGQlpTeFJRVUZtTEVWQlFYbENMRTlCUVhwQ0xFVkJRV3RETEdGQlFXeERMRVZCUVdsRU8wRkJRemRETEdkRFFVRm5RaXhwUWtGQmFVSXNSVUZCYWtJc1EwRkVOa0k3UVVGRk4wTXNPRUpCUVdNc1MwRkJaQ3hIUVVGelFpeGpRVUZqTEV0QlFXUXNTVUZCZFVJc1kwRkJZeXhMUVVGa0xFdEJRWGRDTEV0QlFYaENMRWRCUTNaRExHTkJRV01zUzBGQlpDeEhRVU5CTEdOQlJtZENMRU5CUm5WQ08wRkJTemRETERoQ1FVRmpMRTFCUVdRc1IwRkJkVUlzWTBGQll5eE5RVUZrTEVsQlFYZENMRTFCUVhoQ0xFTkJUSE5DT3p0QlFVODNReXgxUWtGQlR5eGpRVUZqTEV0QlFXUXNRMEZCYjBJc1VVRkJjRUlzUlVGQk9FSXNUMEZCT1VJc1JVRkJkVU1zWVVGQmRrTXNRMEZCVUN4RFFWQTJRenRoUVVGcVJEczdRVUZWUVN4eFFrRkJVeXhqUVVGVUxFTkJRWGRDTEZGQlFYaENMRVZCUVd0RExFOUJRV3hETEVWQlFUSkRMR0ZCUVRORExFVkJRVEJFTzBGQlEzUkVMRzlDUVVGSkxGVkJRVlVzWVVGQllTeFBRVUZpTEVOQlFWWXNRMEZFYTBRN08wRkJSM1JFTEc5Q1FVRkpMRkZCUVZFc1RVRkJVaXhMUVVGdFFpeERRVUZ1UWl4RlFVRnpRanRCUVVOMFFpd3lRa0ZCVHl4UlFVRlFMRU5CUkhOQ08ybENRVUV4UWpzN1FVRkpRU3h2UWtGQlNTeFJRVUZSTEZOQlFWTXNVVUZCVkN4RlFVRnRRaXhSUVVGUkxFTkJRVklzUlVGQlZ5eFBRVUU1UWl4RFFVRlNMRU5CVUd0RU8wRkJVWFJFTEc5Q1FVRkpMR2RDUVVGblFpeFRRVUZUTEdGQlFWUXNRMEZTYTBNN08wRkJWWFJFTEc5Q1FVRkpMRU5CUVVNc1kwRkJZeXhSUVVGa0xFbEJRVEJDTEd0Q1FVRnJRaXhSUVVGc1FpeEZRVUUwUWp0QlFVTjJSQ3hyUTBGQll5eFJRVUZrTEVkQlFYbENMR0ZCUVhwQ0xFTkJSSFZFTzJsQ1FVRXpSRHM3UVVGSlFTeHhRa0ZCU3l4SlFVRkpMRWxCUVVrc1EwRkJTaXhGUVVGUExFbEJRVWtzVVVGQlVTeE5RVUZTTEVWQlFXZENMRWRCUVhCRExFVkJRWGxETzBGQlEzSkRMSGRDUVVGSkxGbEJRVmtzVVVGQlVTeERRVUZTTEVOQlFWb3NRMEZFYVVNN1FVRkZja01zSzBKQlFWY3NWMEZCVnl4UlFVRllMRVZCUTFBc1RVRkJUU3hUUVVGT0xFTkJSRThzUlVGRlVDeFJRVUZSTEZOQlFWSXNRMEZHVHl4RlFVZFFMR0ZCU0U4c1EwRkJXQ3hEUVVaeFF6dHBRa0ZCZWtNN08wRkJVVUVzZFVKQlFVOHNVVUZCVUN4RFFYUkNjMFE3WVVGQk1VUTdPMEZCZVVKQkxIRkNRVUZUTEZWQlFWUXNRMEZCYjBJc1VVRkJjRUlzUlVGQk9FSXNUMEZCT1VJc1JVRkJkVU1zVTBGQmRrTXNSVUZCYTBRc1lVRkJiRVFzUlVGQmFVVTdRVUZETjBRc2IwSkJRVWtzUTBGQlF5eFBRVUZFTEVWQlFWVTdRVUZEVml3eVFrRkJUeXhSUVVGUUxFTkJSRlU3YVVKQlFXUTdPMEZCU1VFc2IwSkJRVWtzVDBGQlNpeERRVXcyUkRzN1FVRlBOMFFzYjBKQlFVa3NVVUZCVVN4VFFVRlNMRU5CUVVvc1JVRkJkMEk3UVVGRGNFSXNlVUpCUVVzc1NVRkJTU3hKUVVGSkxFTkJRVW9zUlVGQlR5eEpRVUZKTEZWQlFWVXNUVUZCVml4RlFVRnJRaXhIUVVGMFF5eEZRVUV5UXp0QlFVTjJReXhyUTBGQlZTeFJRVUZSTEZWQlFWVXNRMEZCVml4RFFVRlNMRVZCUVhOQ0xFOUJRWFJDTEVWQlFTdENMR0ZCUVM5Q0xFTkJRVllzUTBGRWRVTTdPMEZCUjNaRExEUkNRVUZKTEZsQlFWa3NVVUZCV2l4RlFVRnpRanRCUVVOMFFpeDFRMEZCVnl4UFFVRllMRU5CUkhOQ08zbENRVUV4UWp0eFFrRklTanRwUWtGRVNpeE5RVkZQTzBGQlEwZ3NPRUpCUVZVc1VVRkJVU3hUUVVGU0xFVkJRVzFDTEU5QlFXNUNMRVZCUVRSQ0xHRkJRVFZDTEVOQlFWWXNRMEZFUnpzN1FVRkhTQ3gzUWtGQlNTeFpRVUZaTEZGQlFWb3NSVUZCYzBJN1FVRkRkRUlzYlVOQlFWY3NUMEZCV0N4RFFVUnpRanR4UWtGQk1VSTdhVUpCV0VvN08wRkJaMEpCTEhWQ1FVRlBMRkZCUVZBc1EwRjJRalpFTzJGQlFXcEZPenRCUVRCQ1FTeHhRa0ZCVXl4WlFVRlVMRU5CUVhOQ0xFOUJRWFJDTEVWQlFTdENPMEZCUXpOQ0xHOUNRVUZKTEZWQlFWVXNSVUZCVml4RFFVUjFRanM3UVVGSE0wSXNjVUpCUVVzc1NVRkJTU3hIUVVGS0xFbEJRVmNzVDBGQmFFSXNSVUZCZVVJN1FVRkRja0lzZDBKQlFVa3NVVUZCVVN4SFFVRlNMRVZCUVdFN1FVRkRZaXhuUTBGQlVTeEpRVUZTTEVOQlFXRXNUMEZCVHl4SFFVRlFMRU5CUVdJc1JVRkVZVHR4UWtGQmFrSTdhVUpCUkVvN08wRkJUVUVzZFVKQlFVOHNUMEZCVUN4RFFWUXlRanRoUVVFdlFqdFRRWFJGZVVjc1JVRnJSblpITEVWQlFVTXNiMEpCUVcxQ0xFVkJRVzVDTEVWQlFYTkNMR1ZCUVdNc1JVRkJaQ3hGUVVGcFFpeGpRVUZoTEVWQlFXSXNSVUZCWjBJc2JVSkJRV3RDTEVWQlFXeENMRVZCUVhGQ0xHTkJRV0VzUlVGQllpeEZRV3hHZVVJc1EwRkJTQ3hGUVd0R1NpeEpRVUZITEVOQlFVTXNWVUZCVXl4UFFVRlVMRVZCUVdsQ0xFMUJRV3BDTEVWQlFYZENMRTlCUVhoQ0xFVkJRV2RETzBGQlEzSkpMR2RDUVVGSkxGZEJRVmNzVVVGQlVTeDFRa0ZCVWl4RFFVRllMRU5CUkdsSk96dEJRVWR5U1N4dFFrRkJUeXhQUVVGUUxFZEJRV2xDTEZsQlFXcENMRU5CU0hGSk96dEJRVXR5U1N4eFFrRkJVeXhaUVVGVUxFTkJRWE5DTEVOQlFYUkNMRVZCUVhsQ0xFTkJRWHBDTEVWQlFUUkNPMEZCUTNoQ0xHOUNRVUZKTEZOQlFWTXNRMEZCVkN4TFFVRmxMRk5CUVZNc1EwRkJWQ3hEUVVGbUxFVkJRVFJDTzBGQlF6VkNMSGRDUVVGSkxGVkJRVlVzUTBGQlZpeEpRVUZsTEZWQlFWVXNRMEZCVml4RlFVRmhPMEZCUXpWQ0xDdENRVUZQTEVWQlFVVXNSVUZCUml4TFFVRlRMRVZCUVVVc1JVRkJSaXhEUVVSWk8zRkNRVUZvUXl4TlFVVlBPMEZCUTBnc0swSkJRVThzUlVGQlJTeEpRVUZHTEV0QlFWY3NSVUZCUlN4SlFVRkdMRU5CUkdZN2NVSkJSbEE3YVVKQlJFbzdPMEZCVVVFc2RVSkJRVThzUzBGQlVDeERRVlIzUWp0aFFVRTFRanRUUVV4eFJ5eEZRV2xDYmtjc1JVRkJReXg1UWtGQmQwSXNSVUZCZUVJc1JVRnFRbWxITEVOQlFVZ3NSVUZwUW1wRkxFbEJRVWNzUTBGQlF5eFZRVUZUTEU5QlFWUXNSVUZCYVVJc1RVRkJha0lzUlVGQmQwSXNUMEZCZUVJc1JVRkJaME03UVVGRGNFVXNlVUpCUkc5Rk96dEJRVWR3UlN4blFrRkJTU3hWUVVGVkxGRkJRVkVzVlVGQlVpeERRVUZXTEVOQlNHZEZPenRCUVV0d1JTeHRRa0ZCVHl4UFFVRlFMRWRCUVdsQ0xFMUJRV3BDTEVOQlRHOUZPenRCUVU5d1JTeHhRa0ZCVXl4TlFVRlVMRU5CUVdkQ0xFdEJRV2hDTEVWQlFYVkNPMEZCUTI1Q0xHOUNRVUZKTEVWQlFVVXNaMEpCUVdkQ0xFMUJRV2hDTEVOQlFVWXNSVUZCTWtJN1FVRkRNMElzTWtKQlFVOHNTVUZCU1N4TlFVRktMRU5CUVZjc1MwRkJXQ3hEUVVGUUxFTkJSREpDTzJsQ1FVRXZRanM3UVVGSlFTeHhRa0ZCU3l4TFFVRk1MRWRCUVdFc1MwRkJZaXhEUVV4dFFqdGhRVUYyUWpzN1FVRlJRU3h0UWtGQlR5eFRRVUZRTEVOQlFXbENMRWxCUVdwQ0xFZEJRWGRDTEZWQlFWVXNTVUZCVml4RlFVRm5RaXhaUVVGb1FpeEZRVUU0UWp0QlFVTnNSQ3h2UWtGQlNTeExRVUZMTEZGQlFWRXNTVUZCVWl4RFFVRk1MRU5CUkRoRE8wRkJSV3hFTEc5Q1FVRkpMRmRCUVZjc1lVRkJZU3hOUVVGaUxFTkJRVzlDTEVOQlFYQkNMRU5CUVZnc1EwRkdPRU03TzBGQlNXeEVMRzFDUVVGSExGRkJRVWdzU1VGQlpTeExRVUZMTEV0QlFVd3NRMEZLYlVNN1lVRkJPVUlzUTBGbU5FTTdPMEZCYzBKd1JTeHRRa0ZCVHl4VFFVRlFMRU5CUVdsQ0xFMUJRV3BDTEVkQlFUQkNMRlZCUVZNc1NVRkJWQ3hGUVVGbExGbEJRV1lzUlVGQk5rSTdRVUZEYmtRc2IwSkJRVWtzUzBGQlN5eFJRVUZSTEVsQlFWSXNRMEZCVEN4RFFVUXJRenRCUVVWdVJDeHZRa0ZCU1N4WFFVRlhMR0ZCUVdFc1RVRkJZaXhEUVVGdlFpeERRVUZ3UWl4RFFVRllMRU5CUml0RE96dEJRVWx1UkN4dFFrRkJSeXhSUVVGSUxFbEJRV1VzVTBGQlppeERRVXB0UkR0aFFVRTNRaXhEUVhSQ01FTTdVMEZCYUVNc1JVRTJRbXhETEVWQlFVTXNXVUZCVnl4RFFVRllMRVZCTjBKblF5eERRVUZJTEVWQk5rSmtMRWxCUVVjc1EwRkJReXhWUVVGVExFOUJRVlFzUlVGQmFVSXNUVUZCYWtJc1JVRkJkMElzVDBGQmVFSXNSVUZCWjBNN1FVRkRkRVFzZVVKQlJITkVPenRCUVVkMFJDeHRRa0ZCVHl4UFFVRlFMRWRCUVdsQ0xGZEJRV3BDTEVOQlNITkVPenRCUVV0MFJDeHhRa0ZCVXl4WFFVRlVMRU5CUVhGQ0xFdEJRWEpDTEVWQlFUUkNPMEZCUTNoQ0xHOUNRVUZKTEVWQlFVVXNaMEpCUVdkQ0xGZEJRV2hDTEVOQlFVWXNSVUZCWjBNN1FVRkRhRU1zTWtKQlFVOHNTVUZCU1N4WFFVRktMRU5CUVdkQ0xFdEJRV2hDTEVOQlFWQXNRMEZFWjBNN2FVSkJRWEJET3p0QlFVbEJMSEZDUVVGTExFdEJRVXdzUjBGQllTeExRVUZpTEVOQlRIZENPMkZCUVRWQ096dEJRVkZCTEhkQ1FVRlpMRk5CUVZvc1EwRkJjMElzU1VGQmRFSXNSMEZCTmtJc1ZVRkJWU3hKUVVGV0xFVkJRV2RDTEZsQlFXaENMRVZCUVRoQ08wRkJRM1pFTEc5Q1FVRkpMRXRCUVVzc1dVRkJUQ3hOUVVGMVFpeExRVUZMTEV0QlFVd3NSVUZCV1R0QlFVTnVReXg1UWtGQlN5eFpRVUZNTEVsQlFYRkNMRXRCUVVzc1MwRkJUQ3hEUVVSak8ybENRVUYyUXp0aFFVUjVRaXhEUVdKNVFqdFRRVUZvUXl4RlFXMUNjRUlzUlVGdVFtMUNMRU5CUVVnc1JVRnRRbG9zU1VGQlJ5eERRVUZETEZWQlFWTXNUMEZCVkN4RlFVRnBRaXhOUVVGcVFpeEZRVUYzUWl4UFFVRjRRaXhGUVVGblF6dEJRVU14UXl4NVFrRkVNRU03TzBGQlJ6RkRMR2RDUVVGSkxGVkJRVlVzVVVGQlVTeFpRVUZTTEVOQlFWWXNRMEZJYzBNN08wRkJTekZETEdkQ1FVRkpMRkZCUVZFc1VVRkJVU3h0UWtGQlVpeERRVUZTTEVOQlRITkRPMEZCVFRGRExHZENRVUZKTEZGQlFWRXNVVUZCVVN4dFFrRkJVaXhEUVVGU0xFTkJUbk5ETzBGQlR6RkRMR2RDUVVGSkxGVkJRVlVzVVVGQlVTeHRRa0ZCVWl4RFFVRldMRU5CVUhORE8wRkJVVEZETEdkQ1FVRkpMRlZCUVZVc1VVRkJVU3h0UWtGQlVpeERRVUZXTEVOQlVuTkRPMEZCVXpGRExHZENRVUZKTEZkQlFWY3NVVUZCVVN4dlFrRkJVaXhEUVVGWUxFTkJWSE5ETzBGQlZURkRMR2RDUVVGSkxGTkJRVk1zVVVGQlVTeHRRa0ZCVWl4RFFVRlVMRU5CVm5ORE8wRkJWekZETEdkQ1FVRkpMRmRCUVZjc1VVRkJVU3h0UWtGQlVpeERRVUZZTEVOQldITkRPenRCUVdFeFF5eG5Ra0ZCU1N4WFFVRlhMRkZCUVZFc1owSkJRVklzUTBGQldDeERRV0p6UXp0QlFXTXhReXhuUWtGQlNTeGpRVUZqTEZGQlFWRXNNRUpCUVZJc1EwRkJaQ3hEUVdSelF6dEJRV1V4UXl4blFrRkJTU3hUUVVGVExGRkJRVkVzYjBKQlFWSXNRMEZCVkN4RFFXWnpRenM3UVVGcFFqRkRMRzFDUVVGUExFOUJRVkFzUjBGQmFVSXNRMEZCYWtJc1EwRnFRakJET3p0QlFXMUNNVU1zY1VKQlFWTXNRMEZCVkN4RFFVRlhMRTlCUVZnc1JVRkJiMElzVlVGQmNFSXNSVUZCWjBNc1VVRkJhRU1zUlVGQk1FTTdRVUZEZEVNc2IwSkJRVWtzWVVGQllTeEZRVUZpTEVOQlJHdERPMEZCUlhSRExHOUNRVUZKTEVkQlFVb3NSVUZCVXl4TFFVRlVMRVZCUVdkQ0xFZEJRV2hDTEVWQlFYRkNMRk5CUVhKQ0xFTkJSbk5ET3p0QlFVbDBReXh2UWtGQlNTeERRVUZETEZGQlFVUXNTVUZCWVN4WFFVRlhMRlZCUVZnc1EwRkJZaXhGUVVGeFF6dEJRVU55UXl3clFrRkJWeXhWUVVGWUxFTkJSSEZETzBGQlJYSkRMRFJDUVVGUkxFVkJRVklzUTBGR2NVTTdhVUpCUVhwRE96dEJRVXRCTEhkQ1FVRlJMRk5CUVZNc1ZVRkJWQ3hKUVVGMVFpeEZRVUYyUWl4RFFWUTRRanRCUVZWMFF5eHpRa0ZCVFN4VFFVRlRMRTlCUVZRc1JVRkJhMElzUzBGQmJFSXNRMEZCVGpzN08wRkJWbk5ETEc5Q1FXRnNReXhOUVVGTkxHTkJRVTRzUTBGQmNVSXNTMEZCY2tJc1EwRkJTaXhGUVVGcFF6dEJRVU0zUWl3d1FrRkJUU3hOUVVGTkxFZEJRVTRzUTBGRWRVSTdRVUZGTjBJc01FSkJRVTBzUjBGQlRpeEhRVUZaTEZOQlFWb3NRMEZHTmtJN2FVSkJRV3BET3pzN1FVRmljME1zYjBKQmJVSnNReXhOUVVGTkxHTkJRVTRzUTBGQmNVSXNWMEZCY2tJc1EwRkJTaXhGUVVGMVF6dEJRVU51UXl4blEwRkJXU3hOUVVGTkxGTkJRVTRzUTBGRWRVSTdRVUZGYmtNc01FSkJRVTBzVTBGQlRpeEhRVUZyUWl4VFFVRnNRaXhEUVVadFF6dHBRa0ZCZGtNN096dEJRVzVDYzBNc2IwSkJlVUpzUXl4UlFVRlJMRTlCUVZJc1NVRkRRU3hEUVVGRExGTkJRVVFzU1VGRFFTeE5RVUZOTEdOQlFVNHNRMEZCY1VJc1QwRkJja0lzUTBGR1FTeEpRVWRCTEUxQlFVMHNTMEZCVGl4TFFVRm5RaXhUUVVGb1FpeEpRVU5CTEVOQlFVTXNUMEZCVHl4TlFVRk5MRXRCUVU0c1EwRkJVaXhGUVVOR08wRkJRMFVzTUVKQlFVMHNTMEZCVGl4SFFVRmpMRmxCUVZrc1RVRkJUU3hMUVVGT0xFTkJRVEZDTEVOQlJFWTdhVUpCVEVZN08wRkJVMEVzYjBOQlFXOUNMRXRCUVhCQ0xFVkJiRU56UXpzN1FVRnZRM1JETEc5Q1FVRkpMR0ZCUVdFc1UwRkJZaXhKUVVFd1FpeGhRVUZoTEVsQlFXSXNSVUZCYlVJN1FVRkROME1zTmtKQlFWTXNVVUZCVkN4RlFVRnRRaXhWUVVGdVFpeEZRVUVyUWl4SFFVRXZRaXhGUVVGdlF5eExRVUZ3UXl4RlFVUTJRenRwUWtGQmFrUTdPMEZCUzBFc2RVSkJRVThzU1VGQlNTeExRVUZLTEVOQlFWVXNSMEZCVml4RlFVRmxMRXRCUVdZc1JVRkJjMElzVlVGQmRFSXNSVUZCYTBNc1IwRkJiRU1zUlVGQmRVTXNVMEZCZGtNc1EwRkJVQ3hEUVhwRGMwTTdZVUZCTVVNN08wRkJORU5CTEhGQ1FVRlRMRkZCUVZRc1EwRkJhMElzUTBGQmJFSXNSVUZCY1VJc1ZVRkJja0lzUlVGQmFVTXNSMEZCYWtNc1JVRkJjME1zUzBGQmRFTXNSVUZCTmtNN1FVRkRla01zYjBKQlFVa3NUMEZCVHl4RFFVRlFMRXRCUVdFc1VVRkJZaXhGUVVGMVFqdEJRVU4yUWl3clFrRkJWeXhKUVVGWUxFTkJRV2RDTEVsQlFVa3NTMEZCU2l4RFFVRlZMRU5CUVZZc1EwRkJhRUlzUlVGRWRVSTdhVUpCUVROQ0xFMUJSVThzU1VGQlNTeFBRVUZQTEVOQlFWQXNTMEZCWVN4UlFVRmlMRVZCUVhWQ08wRkJRemxDTEN0Q1FVRlhMRWxCUVZnc1EwRkJaMElzU1VGQlNTeExRVUZLTEVOQlFWVXNUMEZCVHl4RFFVRlFMRU5CUVZZc1EwRkJhRUlzUlVGRU9FSTdhVUpCUVROQ0xFMUJSVUVzU1VGQlNTeFJRVUZSTEVOQlFWSXNRMEZCU2l4RlFVRm5RanRCUVVOdVFpd3JRa0ZCVnl4SlFVRllMRU5CUVdkQ0xFTkJRV2hDTEVWQlJHMUNPMmxDUVVGb1FpeE5RVVZCTEVsQlFVa3NVVUZCVVN4RFFVRlNMRU5CUVVvc1JVRkJaMEk3UVVGRGJrSXNlVUpCUVVzc1NVRkJTU3hKUVVGSkxFTkJRVW9zUlVGQlR5eEpRVUZKTEVWQlFVVXNUVUZCUml4RlFVRlZMRWRCUVRsQ0xFVkJRVzFETzBGQlF5OUNMR2xEUVVGVExFVkJRVVVzUTBGQlJpeERRVUZVTEVWQlFXVXNWVUZCWml4RlFVRXlRaXhIUVVFelFpeEZRVUZuUXl4TFFVRm9ReXhGUVVRclFqdHhRa0ZCYmtNN2FVSkJSRWNzVFVGSlFTeEpRVUZKTEUxQlFVMHNTVUZCVGl4SlFVRmpMRTFCUVUwc1UwRkJUaXhGUVVGcFFqdEJRVU4wUXl3eVFrRkVjME03YVVKQlFXNURMRTFCUlVFN1FVRkRTQ3d3UWtGQlRTeDVRa0ZCZVVJN1FVRkRNMElzZFVOQlFXVXNRMEZCWmp0QlFVTkJMSEZEUVVGaE8wRkJRMVFzY1VOQlFWTXNSMEZCVkR0QlFVTkJMSGREUVVGWkxFdEJRVm83ZVVKQlJrbzdjVUpCUmtVc1EwRkJUaXhEUVVSSE8ybENRVVpCTzJGQldGZzdPMEZCZDBKQkxIRkNRVUZUTEcxQ1FVRlVMRU5CUVRaQ0xFdEJRVGRDTEVWQlFXOURPMEZCUTJoRExIRkNRVUZMTEVsQlFVa3NVVUZCU2l4SlFVRm5RaXhMUVVGeVFpeEZRVUUwUWp0QlFVTjRRaXgzUWtGQlNTeE5RVUZOTEdOQlFVNHNRMEZCY1VJc1VVRkJja0lzUTBGQlNpeEZRVUZ2UXp0QlFVTm9ReXcwUWtGQlNTeFJRVUZSTEUxQlFVMHNVVUZCVGl4RFFVRlNMRU5CUkRSQ096dEJRVWRvUXl3MFFrRkJTU3hQUVVGUExFdEJRVkFzUTBGQlNpeEZRVUZ0UWp0QlFVTm1MSEZEUVVSbE8zbENRVUZ1UWpzN1FVRkpRU3cwUWtGQlNTeFRRVUZUTEUxQlFWUXNRMEZCWjBJc1EwRkJhRUlzUlVGQmJVSXNRMEZCYmtJc1RVRkJNRUlzUzBGQk1VSXNSVUZCYVVNN08wRkJSV3BETEd0RFFVRk5MRkZCUVU0c1NVRkJhMElzVDBGQlR5eExRVUZRTEVOQlFXeENMRU5CUm1sRE8zbENRVUZ5UXp0eFFrRlFTanRwUWtGRVNqdGhRVVJLT3p0QlFXbENRU3h4UWtGQlV5eFBRVUZVTEVOQlFXbENMRU5CUVdwQ0xFVkJRVzlDTzBGQlEyaENMSFZDUVVGUExGRkJRVkVzUTBGQlVpeExRVUZqTEZGQlFWRXNRMEZCVWl4RFFVRmtMRWxCUVRSQ0xGTkJRVk1zUTBGQlZDeERRVUUxUWl4SlFVRXlReXhUUVVGVExFTkJRVlFzUTBGQk0wTXNRMEZFVXp0aFFVRndRanM3UVVGSlFTeHhRa0ZCVXl4VlFVRlVMRU5CUVc5Q0xFTkJRWEJDTEVWQlFYVkNPMEZCUTI1Q0xIVkNRVUZQTEU5QlFVOHNRMEZCVUN4TFFVRmhMRkZCUVdJc1NVRkJlVUlzVVVGQlVTeERRVUZTTEVOQlFYcENMRWxCUVhWRExGRkJRVkVzUTBGQlVpeERRVUYyUXl4RFFVUlpPMkZCUVhaQ096dEJRVWxCTEhGQ1FVRlRMSGRDUVVGVUxFTkJRV3RETEVsQlFXeERMRVZCUVhkRE8wRkJRM0JETEc5Q1FVRkpMRTFCUVUwc1NVRkJTU3hMUVVGS0xFVkJRVTRzUTBGRVowTTdPMEZCUjNCRExHOUNRVUZKTEVsQlFVb3NSMEZCVnl4blJFRkJXQ3hEUVVodlF6dEJRVWx3UXl4dlFrRkJTU3hQUVVGS0xFZEJRV01zT0VOQlExWXNjVVJCUkZVc1IwRkZWaXhSUVVaVkxFZEJSMVlzV1VGQldTeExRVUZMTEdGQlFVd3NRMEZJUml4SFFVbFdMRXRCU2xVc1IwRkxWaXgzUWtGTVZTeEhRVTFXTEZsQlFWa3NTMEZCU3l4WFFVRk1MRU5CVGtZc1EwRktjMEk3UVVGWGFFTXNkVUpCUTBFc2QwUkJSRUVzUTBGWVowTTdRVUZoY0VNc2IwSkJRVWtzWVVGQlNpeEhRVUZ2UWl4TFFVRkxMR0ZCUVV3c1EwRmlaMEk3UVVGamNFTXNiMEpCUVVrc1YwRkJTaXhIUVVGclFpeExRVUZMTEZkQlFVd3NRMEZrYTBJN08wRkJaMEp3UXl4MVFrRkJUeXhIUVVGUUxFTkJhRUp2UXp0aFFVRjRRenM3UVVGdFFrRXNjVUpCUVZNc1YwRkJWQ3hEUVVGeFFpeEhRVUZ5UWl4RlFVRXdRanRCUVVOMFFpeHZRa0ZCU1R0QlFVTkJMREpDUVVGUExFdEJRVXNzVTBGQlRDeERRVUZsTEVkQlFXWXNSVUZCYjBJc1NVRkJjRUlzUlVGQk1FSXNUVUZCTVVJc1EwRkJVQ3hEUVVSQk8ybENRVUZLTEVOQlJVVXNUMEZCVHl4RFFVRlFMRVZCUVZVN1FVRkRVaXd5UWtGQlR5eFBRVUZQTEVkQlFWQXNRMEZCVUN4RFFVUlJPMmxDUVVGV08yRkJTRTQ3VTBGdVNWVXNSVUV5U1ZJc1JVRkJReXh4UWtGQmIwSXNSVUZCY0VJc1JVRkJkVUlzY1VKQlFXOUNMRVZCUVhCQ0xFVkJRWFZDTEhGQ1FVRnZRaXhGUVVGd1FpeEZRVUYxUWl4eFFrRkJiMElzUlVGQmNFSXNSVUZCZFVJc2MwSkJRWEZDTEVWQlFYSkNMRVZCUVhkQ0xIRkNRVUZ2UWl4RlFVRndRaXhGUVVGMVFpeHhRa0ZCYjBJc1JVRkJjRUlzUlVGQmRVSXNjMEpCUVhGQ0xFVkJRWEpDTEVWQlFYZENMRFJDUVVFeVFpeEZRVUV6UWl4RlFVRTRRaXhyUWtGQmFVSXNSVUZCYWtJc1JVRkJiMElzWTBGQllTeEZRVUZpTEVWQk0wbDBUeXhEUVVGSUxFVkJNa2t5VUN4SlFVRkhMRU5CUVVNc1ZVRkJVeXhQUVVGVUxFVkJRV2xDTEUxQlFXcENMRVZCUVhkQ0xFOUJRWGhDTEVWQlFXZERPMEZCUTNKVExIbENRVVJ4VXpzN1FVRkhjbE1zWjBKQlFVa3NVVUZCVVN4UlFVRlJMR1ZCUVZJc1EwRkJVaXhEUVVocFV6czdRVUZMY2xNc1owSkJRVWtzWlVGQlpTeHpRMEZCWml4RFFVeHBVenRCUVUxeVV5eG5Ra0ZCU1N4aFFVRmhMRTlCUVdJc1EwRk9hVk03TzBGQlVYSlRMRzFDUVVGUExFOUJRVkFzUjBGQmFVSXNVVUZCYWtJc1EwRlNjVk03TzBGQlZYSlRMSEZDUVVGVExGRkJRVlFzUTBGQmEwSXNSMEZCYkVJc1JVRkJkVUlzUzBGQmRrSXNSVUZCT0VJN1FVRkRNVUlzYjBKQlFVa3NRMEZCUXl4SFFVRkVMRVZCUVUwN1FVRkRUaXd5UWtGQlR5eExRVUZRTEVOQlJFMDdhVUpCUVZZN08wRkJTVUVzYjBKQlFVa3NUMEZCVHl4RFFVRkZMRTFCUVUwc1kwRkJUaXhEUVVGeFFpeEpRVUZ5UWl4RFFVRkdMRU5CVEdVN08wRkJUekZDTEc5Q1FVRkpMRmRCUVZjc1RVRkJUU3hIUVVGT0xFVkJRVmNzV1VGQldDeERRVUZZTEVOQlVITkNPMEZCVVRGQ0xHOUNRVUZKTEZWQlFWVXNTVUZCVml4RFFWSnpRanM3UVVGVk1VSXNiMEpCUVVrc1YwRkJWeXhKUVVGWUxFTkJRV2RDTEZOQlFWTXNRMEZCVkN4RFFVRm9RaXhEUVVGS0xFVkJRV3RETzBGQlF6bENMRGhDUVVGVkxFdEJRVllzUTBGRU9FSTdhVUpCUVd4RE96dEJRVWxCTEc5Q1FVRkpMRTlCUVVvc1JVRkJZU3hKUVVGaUxFVkJRVzFDTEVsQlFXNUNMRVZCUVhsQ0xFTkJRWHBDTEVOQlpEQkNPenRCUVdkQ01VSXNjVUpCUVVzc1NVRkJTU3hEUVVGS0xFVkJRVThzU1VGQlNTeFRRVUZUTEUxQlFWUXNSVUZCYVVJc1IwRkJha01zUlVGQmMwTTdRVUZEYkVNc01rSkJRVThzVTBGQlV5eERRVUZVTEVOQlFWQXNRMEZFYTBNN08wRkJSMnhETEhkQ1FVRkpMRU5CUVVNc1NVRkJSQ3hGUVVGUE8wRkJRMUFzYVVOQlJFODdjVUpCUVZnN08wRkJTVUVzTWtKQlFVOHNTMEZCU3l4TlFVRk1MRU5CUVZrc1EwRkJXaXhEUVVGUUxFTkJVR3RET3p0QlFWTnNReXgzUWtGQlNTeERRVUZETEU5QlFVUXNSVUZCVlR0QlFVTldMR3REUVVGVkxFbEJRVllzUTBGRVZUdHhRa0ZCWkN4TlFVVlBMRWxCUVVrc1UwRkJVeXhIUVVGVUxFVkJRV003UVVGRGNrSXNhME5CUVZVc1YwRkJWeXhGUVVGWUxFTkJSRmM3UVVGRmNrSXNaME5CUVZFc1NVRkJVaXhEUVVGaExFdEJRVXNzVTBGQlRDeERRVUZsTEVOQlFXWXNSVUZCYTBJc1MwRkJTeXhOUVVGTUxFTkJRUzlDTEVWQlJuRkNPM0ZDUVVGc1FpeE5RVWRCTEVsQlFVa3NVMEZCVXl4SFFVRlVMRWxCUVdkQ0xFbEJRV2hDTEVWQlFYTkNPMEZCUXpkQ0xEaENRVUZOTEVWQlFVNHNSMEZCVnl4TFFVRkxMRk5CUVV3c1EwRkJaU3hEUVVGbUxFVkJRV3RDTEV0QlFVc3NUVUZCVEN4RFFVRTNRaXhEUVVRMlFqdHhRa0ZCTVVJN2FVSkJaRmc3TzBGQmJVSkJMRzlDUVVGSkxFOUJRVW9zUlVGQllUdEJRVU5VTEhkQ1FVRkpMRTFCUVUwc1UwRkJUaXhGUVVGcFFqdEJRVU5xUWl4blEwRkJVU3hKUVVGU0xFTkJRV0VzVFVGQlRTeFRRVUZPTEVOQlFXSXNRMEZFYVVJN2NVSkJRWEpDT3p0QlFVbEJMREJDUVVGTkxGTkJRVTRzUjBGQmEwSXNVVUZCVVN4SlFVRlNMRU5CUVdFc1IwRkJZaXhEUVVGc1FpeERRVXhUTzJsQ1FVRmlPenRCUVZGQkxIVkNRVUZQTEUxQlFVMHNVMEZCVGl4SFFVRnJRaXhQUVVGc1FpeEhRVUUwUWl4UlFVRlJMRmRCUVZJc1JVRkJOVUlzUTBFelEyMUNPMkZCUVRsQ08xTkJWbkZSTEVWQmQwUnVVU3hGUVVGRExHbENRVUZuUWl4RFFVRm9RaXhGUVhoRWFWRXNRMEZCU0N4RlFYZEVNVThzU1VGQlJ5eERRVUZETEZWQlFWTXNUMEZCVkN4RlFVRnBRaXhOUVVGcVFpeEZRVUYzUWl4UFFVRjRRaXhGUVVGblF6dEJRVU16UkN4blFrRkJTU3hWUVVGVkxGRkJRVkVzV1VGQlVpeERRVUZXTEVOQlJIVkVPMEZCUlRORUxHZENRVUZKTEZWQlFWVXNVVUZCVVN4WlFVRlNMRU5CUVZZc1EwRkdkVVE3UVVGSE0wUXNaMEpCUVVrc1YwRkJWeXhSUVVGUkxHRkJRVklzUTBGQldDeERRVWgxUkR0QlFVa3pSQ3huUWtGQlNTeFZRVUZWTEZGQlFWRXNXVUZCVWl4RFFVRldMRU5CU25WRU96dEJRVTB6UkN4dFFrRkJUeXhQUVVGUUxFZEJRV2xDTEZkQlFXcENMRU5CVGpKRU96dEJRVkV6UkN4eFFrRkJVeXhYUVVGVUxFTkJRWEZDTEVOQlFYSkNMRVZCUVhkQ0xFTkJRWGhDTEVWQlFUSkNPMEZCUTNaQ0xHOUNRVUZKTEZsQlFWa3NRMEZCV2l4RFFVUnRRanRCUVVWMlFpeHZRa0ZCU1N4WlFVRlpMRU5CUVZvc1EwRkdiVUk3TzBGQlNYWkNMRzlDUVVGSkxGRkJRVkVzUTBGQlVpeERRVUZLTEVWQlFXZENPMEZCUTFvc1owTkJRVmtzV1VGQldTeERRVUZhTEVWQlFXVXNRMEZCWml4RFFVRmFMRU5CUkZrN2FVSkJRV2hDT3p0QlFVbEJMRzlDUVVGSkxGRkJRVkVzUTBGQlVpeERRVUZLTEVWQlFXZENPMEZCUTFvc1owTkJRVmtzV1VGQldTeERRVUZhTEVWQlFXVXNTVUZCWml4RFFVRmFMRU5CUkZrN2FVSkJRV2hDT3p0QlFVbEJMSFZDUVVGUE8wRkJRMGdzZFVKQlFVY3NVMEZCU0R0QlFVTkJMSFZDUVVGSExGTkJRVWc3YVVKQlJrb3NRMEZhZFVJN1lVRkJNMEk3TzBGQmEwSkJMSEZDUVVGVExGZEJRVlFzUTBGQmNVSXNTMEZCY2tJc1JVRkJORUlzVVVGQk5VSXNSVUZCYzBNN1FVRkRiRU1zYjBKQlFVa3NaMEpCUVdkQ0xFMUJRVTBzUzBGQlRpeERRVVJqT3p0QlFVZHNReXh2UWtGQlNTeERRVUZETEdGQlFVUXNSVUZCWjBJN1FVRkRhRUlzYjBOQlFXZENMRTFCUVUwc1MwRkJUaXhIUVVGakxFMUJRVTBzVFVGQlRpeERRVUZoTEZGQlFXSXNRMEZCWkN4RFFVUkJPMmxDUVVGd1FqczdRVUZKUVN4dlFrRkJTU3hGUVVGRkxGRkJRVkVzWVVGQlVpeExRVU5GTEZGQlFWRXNZVUZCVWl4RFFVUkdMRWxCUlVVc1UwRkJVeXhoUVVGVUxFTkJSa1lzUTBGQlJpeEZRVVU0UWp0QlFVTTVRaXd3UWtGQlRTeEpRVUZKTEV0QlFVb3NRMEZCVlN4dFEwRkJWaXhEUVVGT0xFTkJSRGhDTzJsQ1FVWnNRenM3UVVGTlFTeDFRa0ZCVHl4aFFVRlFMRU5CWW10RE8yRkJRWFJETzFOQk1VSXlRaXhGUVRCRGVrSXNSVUZCUXl4alFVRmhMRVZCUVdJc1JVRkJaMElzWTBGQllTeEZRVUZpTEVWQlFXZENMR05CUVdFc1JVRkJZaXhGUVVGblFpeGxRVUZqTEVWQlFXUXNSVUV4UTNwQ0xFTkJRVWdzUlVFd1F5dERMRWxCUVVjc1EwRkJReXhWUVVGVExFOUJRVlFzUlVGQmFVSXNUVUZCYWtJc1JVRkJkMElzVDBGQmVFSXNSVUZCWjBNN1FVRkRNVWNzYlVKQlFVOHNUMEZCVUN4SFFVRnBRaXhQUVVGcVFpeERRVVF3UnpzN1FVRkhNVWNzY1VKQlFWTXNUMEZCVkN4RFFVRnBRaXhEUVVGcVFpeEZRVUZ2UWp0QlFVTm9RaXgxUWtGQlR5eExRVUZMTEVWQlFVVXNTVUZCUml4TFFVRlhMRTlCUVZnc1EwRkVTVHRoUVVGd1FqdFRRVWd3UlN4RlFVOTRSU3hGUVZCMVJTeERRVUZJTEVWQlQyaEZMRWxCUVVjc1EwRkJReXhWUVVGVExFOUJRVlFzUlVGQmFVSXNUVUZCYWtJc1JVRkJkMElzVDBGQmVFSXNSVUZCWjBNN1FVRkRNVU1zYlVKQlFVOHNUMEZCVUN4SFFVRnBRaXhOUVVGcVFpeERRVVF3UXpzN1FVRkhNVU1zY1VKQlFWTXNUVUZCVkN4RFFVRm5RaXhKUVVGb1FpeEZRVUZ6UWp0QlFVTnNRaXgxUWtGQlR5eFRRVU5LTEU5QlFVOHNTMEZCU3l4SlFVRk1MRXRCUVdNc1ZVRkJja0lzU1VGQmJVTXNRMEZCUXl4TFFVRkxMR05CUVV3c1EwRkJiMElzVFVGQmNFSXNRMEZCUkN4SlFVTnVReXhQUVVGUExFdEJRVXNzVFVGQlRDeExRVUZuUWl4VlFVRjJRaXhKUVVGeFF5eERRVUZETEV0QlFVc3NZMEZCVEN4RFFVRnZRaXhSUVVGd1FpeERRVUZFTEVOQlJtcERMRU5CUkZjN1lVRkJkRUk3VTBGSVZTeEZRVk5TTEVWQlZFOHNRMEZCU0N4RlFWTkJMRWxCUVVjc1EwRkJReXhWUVVGVExFOUJRVlFzUlVGQmFVSXNUVUZCYWtJc1JVRkJkMElzVDBGQmVFSXNSVUZCWjBNN1FVRkRNVU1zWjBKQlFVa3NWVUZCVlN4UlFVRlJMRmRCUVZJc1EwRkJWaXhEUVVSelF6czdRVUZITVVNc2JVSkJRVThzVDBGQlVDeEhRVUZwUWl4aFFVRnFRaXhEUVVnd1F6czdRVUZMTVVNc2NVSkJRVk1zWVVGQlZDeERRVUYxUWl4RFFVRjJRaXhGUVVFd1FqdEJRVU4wUWl4MVFrRkJUeXhMUVVGTExFVkJRVVVzU1VGQlJpeExRVUZYTEdGQlFWZ3NTVUZCTkVJc1JVRkJSU3hQUVVGR0xFdEJRV01zVDBGQlpDeERRVVJzUWp0aFFVRXhRanRUUVV4VkxFVkJVMUlzUlVGQlF5eGhRVUZaTEVWQlFWb3NSVUZVVFN4RFFVRklMRVZCVTJNc1NVRkJSeXhEUVVGRExGVkJRVk1zVDBGQlZDeEZRVUZwUWl4TlFVRnFRaXhGUVVGM1FpeFBRVUY0UWl4RlFVRm5RenRCUVVONFJDeG5Ra0ZCU1N4VlFVRlZMRkZCUVZFc1YwRkJVaXhEUVVGV0xFTkJSRzlFT3p0QlFVZDRSQ3h0UWtGQlR5eFBRVUZRTEVkQlFXbENMR0ZCUVdwQ0xFTkJTSGRFT3p0QlFVdDRSQ3h4UWtGQlV5eGhRVUZVTEVOQlFYVkNMRU5CUVhaQ0xFVkJRVEJDTzBGQlEzUkNMSFZDUVVGUExFdEJRVXNzUlVGQlJTeEpRVUZHTEV0QlFWY3NZVUZCV0N4SlFVRTBRaXhGUVVGRkxFOUJRVVlzUzBGQll5eFBRVUZrTEVOQlJHeENPMkZCUVRGQ08xTkJUSGRDTEVWQlUzUkNMRVZCUVVNc1lVRkJXU3hGUVVGYUxFVkJWRzlDTEVOQlFVZ3NSVUZUUVN4SlFVRkhMRU5CUVVNc1ZVRkJVeXhQUVVGVUxFVkJRV2xDTEUxQlFXcENMRVZCUVhkQ0xFOUJRWGhDTEVWQlFXZERPMEZCUTNoRUxHMUNRVUZQTEU5QlFWQXNSMEZCYVVJc1VVRkJha0lzUTBGRWQwUTdPMEZCUjNoRUxIRkNRVUZUTEZGQlFWUXNRMEZCYTBJc1EwRkJiRUlzUlVGQmNVSTdRVUZEYWtJc2RVSkJRVThzUzBGQlN5eEZRVUZGTEVsQlFVWXNTMEZCVnl4UlFVRllMRU5CUkVzN1lVRkJja0k3VTBGSWQwSXNSVUZQZEVJc1JVRlFjVUlzUTBGQlNDeEZRVTlrTEVsQlFVY3NRMEZCUXl4VlFVRlRMRTlCUVZRc1JVRkJhVUlzVFVGQmFrSXNSVUZCZDBJc1QwRkJlRUlzUlVGQlowTTdRVUZETVVNc2JVSkJRVThzVDBGQlVDeEhRVUZwUWl4SFFVRnFRaXhEUVVRd1F6dFRRVUZvUXl4RlFVZFNMRVZCU0U4c1EwRkJTQ3hGUVVkQkxFbEJRVWNzUTBGQlF5eFZRVUZUTEU5QlFWUXNSVUZCYVVJc1RVRkJha0lzUlVGQmQwSXNUMEZCZUVJc1JVRkJaME03UVVGRE1VTXNaMEpCUVVrc1ZVRkJWU3hSUVVGUkxGZEJRVklzUTBGQlZpeERRVVJ6UXp0QlFVVXhReXhuUWtGQlNTeFZRVUZWTEZGQlFWRXNXVUZCVWl4RFFVRldMRU5CUm5ORE8wRkJSekZETEdkQ1FVRkpMRmRCUVZjc1VVRkJVU3hoUVVGU0xFTkJRVmdzUTBGSWMwTTdRVUZKTVVNc1owSkJRVWtzVlVGQlZTeFJRVUZSTEZsQlFWSXNRMEZCVml4RFFVcHpRenRCUVVzeFF5eG5Ra0ZCU1N4VlFVRlZMRkZCUVZFc1dVRkJVaXhEUVVGV0xFTkJUSE5ET3p0QlFVOHhReXh0UWtGQlR5eFBRVUZRTEVkQlFXbENMRmRCUVdwQ0xFTkJVREJET3p0QlFWTXhReXhuUWtGQlNTeGxRVUZsTEVWQlFXWXNRMEZVYzBNN1FVRlZNVU1zWjBKQlFVa3NZVUZCWVN4RlFVRmlMRU5CVm5ORE96dEJRVmt4UXl4eFFrRkJVeXhYUVVGVUxFTkJRWEZDTEU5QlFYSkNMRVZCUVRoQ0xGVkJRVGxDTEVWQlFUQkRMRkZCUVRGRExFVkJRVzlFTEVkQlFYQkVMRVZCUVhsRUxGTkJRWHBFTEVWQlFXOUZPMEZCUTJoRkxIRkNRVUZMTEU5QlFVd3NSMEZCWlN4UFFVRm1MRU5CUkdkRk8wRkJSV2hGTEhGQ1FVRkxMRlZCUVV3c1IwRkJhMElzWTBGQll5eFpRVUZrTEVOQlJqaERPMEZCUjJoRkxIRkNRVUZMTEZGQlFVd3NSMEZCWjBJc1dVRkJXU3hWUVVGYUxFTkJTR2RFTzBGQlNXaEZMSEZDUVVGTExFZEJRVXdzUjBGQlZ5eFBRVUZQTEVsQlFWQXNSMEZCWXl4UFFVRlBMRWRCUVZBc1EwRkJaQ3hIUVVFMFFpeFRRVUUxUWl4RFFVcHhSRHRCUVV0b1JTeHhRa0ZCU3l4VFFVRk1MRWRCUVdsQ0xFOUJRVkVzVTBGQlVDeExRVUZ4UWl4UlFVRnlRaXhIUVVGcFF5eFRRVUZzUXl4SFFVRTRReXhKUVVFNVF5eERRVXdyUXpzN1FVRlBhRVVzYjBKQlFVa3NVVUZCVVN4UlFVRkRMRWxCUVZrc1UwRkJVeXhOUVVGVUxFbEJRVzlDTEVOQlFXcERMRU5CVUc5RU8wRkJVV2hGTEc5Q1FVRkpMR05CUVdNc1EwRkJaQ3hEUVZJMFJEdEJRVk5vUlN4dlFrRkJTU3hoUVVGaExFdEJRV0lzUTBGVU5FUTdRVUZWYUVVc2IwSkJRVWtzV1VGQldTeExRVUZhTEVOQlZqUkVPMEZCVjJoRkxHOUNRVUZKTEd0Q1FVRnJRaXhMUVVGc1FpeERRVmcwUkR0QlFWbG9SU3h2UWtGQlNTeExRVUZLTEVOQldtZEZPenRCUVdOb1JTeHhRa0ZCU3l4SlFVRkpMRkZCUVVvc1NVRkJaMElzVlVGQmNrSXNSVUZCYVVNN1FVRkROMElzZDBKQlFVa3NWMEZCVnl4alFVRllMRU5CUVRCQ0xGRkJRVEZDTEVOQlFVb3NSVUZCZVVNN1FVRkRja01zTkVKQlFVa3NWMEZCVnl4WFFVRlhMRkZCUVZnc1EwRkJXQ3hEUVVScFF6dEJRVVZ5UXl3MFFrRkJTU3hSUVVGUkxGRkJRVklzUzBGQmNVSXNVMEZCVXl4TlFVRlVMRVZCUVdsQ08wRkJRM1JETEdkRFFVRkpMRU5CUVVNc1MwRkJSQ3hGUVVGUk8wRkJRMUlzZDBOQlFWRXNSVUZCVWl4RFFVUlJPelpDUVVGYU96dEJRVWxCTEd0RFFVRk5MRkZCUVU0c1NVRkJhMElzVVVGQmJFSXNRMEZNYzBNN2VVSkJRVEZETzNGQ1FVWktPMmxDUVVSS096dEJRV0ZCTEhGQ1FVRkxMRWxCUVVrc1NVRkJTU3hEUVVGS0xFVkJRVThzU1VGQlNTeExRVUZLTEVWQlFWY3NSMEZCTTBJc1JVRkJaME03UVVGRE5VSXNkMEpCUVVrc1VVRkJVU3hUUVVGVExFTkJRVlFzUTBGQlVpeERRVVIzUWp0QlFVVTFRaXgzUWtGQlNTeFJRVUZSTEV0QlFWSXNRMEZCU2l4RlFVRnZRanRCUVVOb1FpeDFRMEZCWlN4TlFVRk5MRXRCUVU0c1NVRkJaU3hEUVVGbUxFTkJSRU03TzBGQlIyaENMRFJDUVVGSkxFTkJRVU1zVlVGQlJDeEpRVUZsTEUxQlFVMHNWVUZCVGl4RlFVRnJRanRCUVVOcVF5eDVRMEZCWVN4SlFVRmlMRU5CUkdsRE8zbENRVUZ5UXpzN1FVRkpRU3cwUWtGQlNTeERRVUZETEZOQlFVUXNTVUZCWXl4TlFVRk5MRk5CUVU0c1JVRkJhVUk3UVVGREwwSXNkME5CUVZrc1NVRkJXaXhEUVVRclFqdDVRa0ZCYmtNN08wRkJTVUVzTkVKQlFVa3NRMEZCUXl4bFFVRkVMRXRCUVhGQ0xFMUJRVTBzUzBGQlRpeEpRVUZsTEUxQlFVMHNaVUZCVGl4RFFVRndReXhGUVVFMFJEdEJRVU0xUkN3NFEwRkJhMElzU1VGQmJFSXNRMEZFTkVRN2VVSkJRV2hGTzNGQ1FWaEtMRTFCWTA4c1NVRkJTU3hEUVVGRExGVkJRVVFzU1VGQlpTeFRRVUZUTEV0QlFWUXNRMEZCWml4RlFVRm5RenRCUVVOMlF5dzBRa0ZCU1N4UFFVRlBMRTFCUVUwc1QwRkJUaXhMUVVGclFpeFZRVUY2UWl4RlFVRnhRenRCUVVOeVF5eDVRMEZCWVN4SlFVRmlMRU5CUkhGRE8zbENRVUY2UXp0eFFrRkVSeXhOUVVsQkxFbEJRVWtzUTBGQlF5eFRRVUZFTEVsQlFXTXNVVUZCVVN4TFFVRlNMRU5CUVdRc1JVRkJPRUk3UVVGRGNrTXNiME5CUVZrc1NVRkJXaXhEUVVSeFF6dHhRa0ZCYkVNN2FVSkJjRUpZT3p0QlFYbENRU3h4UWtGQlN5eExRVUZNTEVkQlFXRXNVVUZCVVN4WFFVRlNMRU5CY0VSdFJEdEJRWEZFYUVVc2NVSkJRVXNzVlVGQlRDeEhRVUZyUWl4VlFVRnNRaXhEUVhKRVowVTdRVUZ6UkdoRkxIRkNRVUZMTEZOQlFVd3NSMEZCYVVJc1UwRkJha0lzUTBGMFJHZEZPMEZCZFVSb1JTeHhRa0ZCU3l4TFFVRk1MRWRCUVdFc1MwRkJZaXhEUVhaRVowVTdRVUYzUkdoRkxIRkNRVUZMTEdWQlFVd3NSMEZCZFVJc1pVRkJka0lzUTBGNFJHZEZPMkZCUVhCRk96dEJRVEpFUVN4M1FrRkJXU3hUUVVGYUxFTkJRWE5DTEU5QlFYUkNMRWRCUVdkRExFOUJRV2hETEVOQmRrVXdRenRCUVhkRk1VTXNkMEpCUVZrc1UwRkJXaXhEUVVGelFpeEpRVUYwUWl4SFFVRTJRaXhoUVVFM1FpeERRWGhGTUVNN1UwRkJhRU1zUlVFd1JWSXNSVUZCUXl4alFVRmhMRVZCUVdJc1JVRkJaMElzWTBGQllTeEZRVUZpTEVWQlFXZENMR05CUVdFc1JVRkJZaXhGUVVGblFpeGxRVUZqTEVWQlFXUXNSVUZCYVVJc1lVRkJXU3hGUVVGYUxFVkJNVVV6UkN4RFFVRklMRVZCTUVVclJTeEpRVUZITEVOQlFVTXNWVUZCVXl4UFFVRlVMRVZCUVdsQ0xFMUJRV3BDTEVWQlFYZENMRTlCUVhoQ0xFVkJRV2RETzBGQlEzcElMR2RDUVVGSkxGVkJRVlVzVVVGQlVTeFhRVUZTTEVOQlFWWXNRMEZFY1VnN08wRkJSM3BJTEhsQ1FVRmhMRWxCUVdJc1IwRkJiMElzUTBGQmNFSXNRMEZJZVVnN1FVRkpla2dzZVVKQlFXRXNTMEZCWWl4SFFVRnhRaXhEUVVGeVFpeERRVXA1U0R0QlFVdDZTQ3g1UWtGQllTeExRVUZpTEVkQlFYRkNMRU5CUVhKQ0xFTkJUSGxJTzBGQlRYcElMSGxDUVVGaExFMUJRV0lzUjBGQmMwSXNRMEZCZEVJc1EwRk9lVWc3UVVGUGVrZ3NlVUpCUVdFc1MwRkJZaXhIUVVGeFFpeERRVUZ5UWl4RFFWQjVTRHRCUVZGNlNDeDVRa0ZCWVN4TFFVRmlMRWRCUVhGQ0xFTkJRWEpDTEVOQlVubElPMEZCVTNwSUxIbENRVUZoTEUxQlFXSXNSMEZCYzBJc1EwRkJkRUlzUTBGVWVVZzdRVUZWZWtnc2VVSkJRV0VzVFVGQllpeEhRVUZ6UWl4RFFVRjBRaXhEUVZaNVNEdEJRVmQ2U0N4NVFrRkJZU3hMUVVGaUxFZEJRWEZDTEVOQlFYSkNMRU5CV0hsSU96dEJRV0Y2U0N4dFFrRkJUeXhQUVVGUUxFZEJRV2xDTEZsQlFXcENMRU5CWW5sSU96dEJRV1Y2U0N4eFFrRkJVeXhaUVVGVUxFTkJRWE5DTEVsQlFYUkNMRVZCUVRSQ0xFdEJRVFZDTEVWQlFXMURMRXRCUVc1RExFVkJRVEJETzBGQlEzUkRMSEZDUVVGTExFbEJRVXdzUjBGQldTeFBRVUZQTEVsQlFWQXNRMEZCV2l4RFFVUnpRenRCUVVWMFF5eHhRa0ZCU3l4TFFVRk1MRWRCUVdFc1MwRkJZaXhEUVVaelF6dEJRVWQwUXl4eFFrRkJTeXhMUVVGTUxFZEJRV0VzUzBGQllpeERRVWh6UXp0aFFVRXhRenM3UVVGTlFTeDVRa0ZCWVN4VFFVRmlMRU5CUVhWQ0xFOUJRWFpDTEVkQlFXbERMRTlCUVdwRExFTkJja0o1U0R0QlFYTkNla2dzZVVKQlFXRXNVMEZCWWl4RFFVRjFRaXhKUVVGMlFpeEhRVUU0UWl4alFVRTVRaXhEUVhSQ2VVZzdVMEZCYUVNc1JVRjNRblpHTEVWQlFVTXNZVUZCV1N4RlFVRmFMRVZCZUVKeFJpeERRVUZJTEVWQmQwSnFSU3hKUVVGSExFTkJRVU1zVlVGQlV5eFBRVUZVTEVWQlFXbENMRTFCUVdwQ0xFVkJRWGRDTEU5QlFYaENMRVZCUVdkRE8wRkJRM2hFTEdkQ1FVRkpMRlZCUVZVc1VVRkJVU3hYUVVGU0xFTkJRVllzUTBGRWIwUTdPMEZCUjNoRUxHMUNRVUZQTEU5QlFWQXNSMEZCYVVJc1YwRkJha0lzUTBGSWQwUTdPMEZCUzNoRUxIRkNRVUZUTEZkQlFWUXNRMEZCY1VJc1NVRkJja0lzUlVGQk1rSTdRVUZEZGtJc2NVSkJRVXNzU1VGQlRDeEhRVUZaTEU5QlFVOHNTVUZCVUN4RFFVRmFMRU5CUkhWQ08yRkJRVE5DT3p0QlFVbEJMSGRDUVVGWkxGTkJRVm9zUTBGQmMwSXNUMEZCZEVJc1IwRkJaME1zVDBGQmFFTXNRMEZVZDBRN1FVRlZlRVFzZDBKQlFWa3NVMEZCV2l4RFFVRnpRaXhKUVVGMFFpeEhRVUUyUWl4aFFVRTNRaXhEUVZaM1JEdFRRVUZvUXl4RlFWbDBRaXhGUVVGRExHRkJRVmtzUlVGQldpeEZRVnB2UWl4RFFVRklMRVZCV1VFc1NVRkJSeXhEUVVGRExGVkJRVk1zVDBGQlZDeEZRVUZwUWl4TlFVRnFRaXhGUVVGM1FpeFBRVUY0UWl4RlFVRm5RenRCUVVONFJDeG5Ra0ZCU1N4WFFVRlhMRkZCUVZFc1YwRkJVaXhEUVVGWUxFTkJSRzlFTzBGQlJYaEVMR2RDUVVGSkxGTkJRVk1zVVVGQlVTeHRRa0ZCVWl4RFFVRlVMRU5CUm05RU96dEJRVWw0UkN4dFFrRkJUeXhQUVVGUUxFZEJRV2xDTEZOQlFXcENMRU5CU25kRU96dEJRVTE0UkN4eFFrRkJVeXhUUVVGVUxFTkJRVzFDTEVOQlFXNUNMRVZCUVhOQ0xFTkJRWFJDTEVWQlFYbENPMEZCUTNKQ0xHOUNRVUZKTEVsQlFVb3NRMEZFY1VJN08wRkJSM0pDTEhGQ1FVRkxMRWxCUVVrc1NVRkJTaXhKUVVGWkxFTkJRV3BDTEVWQlFXOUNPMEZCUTJoQ0xIZENRVUZKTEVWQlFVVXNVVUZCVVN4RFFVRlNMRU5CUVVZc1JVRkJZenRCUVVOa0xDdENRVUZQTEZGQlFWRXNSVUZCVWl4RFFVUlBPMEZCUldRc05rSkJRVXNzU1VGQlRDeEpRVUZoTEZOQlFXSXNRMEZHWXp0eFFrRkJiRUk3TzBGQlMwRXNkMEpCUVVrc1UwRkJVeXhGUVVGRkxFbEJRVVlzUTBGQlZDeERRVTVaTzBGQlQyaENMSGRDUVVGSkxGTkJRVk1zUlVGQlJTeEpRVUZHTEVOQlFWUXNRMEZRV1RzN1FVRlRhRUlzZDBKQlFVa3NWMEZCVnl4TlFVRllMRVZCUVcxQ08wRkJRMjVDTEdsRFFVUnRRanR4UWtGQmRrSXNUVUZGVHl4SlFVRkpMRk5CUVZNc1RVRkJWQ3hMUVVGdlFpeFRRVUZUTEUxQlFWUXNRMEZCY0VJc1JVRkJjME03UVVGRE4wTXNORUpCUVVrc1lVRkJZU3hOUVVGaUxFMUJRWGxDTEdGQlFXRXNUVUZCWWl4RFFVRjZRaXhGUVVFclF6dEJRVU12UXl4dFEwRkJUeXhSUVVGUkxFVkJRVklzUTBGRWQwTTdRVUZGTDBNc2FVTkJRVXNzU1VGQlRDeEpRVUZoTEUxQlFXSXNRMEZHSzBNN2VVSkJRVzVFTEUxQlIwOHNTVUZCU1N4UFFVRlBMRTFCUVZBc1EwRkJTaXhGUVVGdlFqdEJRVU4wUWl4dFEwRkJUeXhSUVVGUkxFVkJRVklzUTBGRVpUdEJRVVYwUWl4cFEwRkJTeXhKUVVGTUxFbEJRV0VzVFVGQllpeERRVVp6UWp0NVFrRkJjRUlzVFVGSFFUdEJRVU5JTEdkRFFVRkpMR0ZCUVdFc1ZVRkJWU3hOUVVGV0xFVkJRV3RDTEUxQlFXeENMRU5CUVdJc1EwRkVSRHRCUVVWSUxHZERRVUZKTEZWQlFVb3NSVUZCWjBJN1FVRkRXaXgxUTBGQlR5eFJRVUZSTEVWQlFWSXNRMEZFU3p0QlFVVmFMSEZEUVVGTExFbEJRVXdzU1VGQllTeFZRVUZpTEVOQlJsazdOa0pCUVdoQ08zbENRVXhITzNGQ1FVcEtMRTFCWTBFN1FVRkRTQ3dyUWtGQlR5eFJRVUZSTEVWQlFWSXNRMEZFU2p0QlFVVklMRFpDUVVGTExFbEJRVXdzU1VGQllTeE5RVUZpTEVOQlJrYzdjVUpCWkVFN2FVSkJXRmc3TzBGQkswSkJMSEZDUVVGTExFbEJRVWtzU1VGQlNpeEpRVUZaTEVOQlFXcENMRVZCUVc5Q08wRkJRMmhDTEhkQ1FVRkpMRVZCUVVVc1VVRkJVU3hEUVVGU0xFTkJRVVlzUlVGQll6dEJRVU5rTEN0Q1FVRlBMRkZCUVZFc1JVRkJVaXhEUVVSUE8wRkJSV1FzTmtKQlFVc3NTVUZCVEN4SlFVRmhMRVZCUVVVc1NVRkJSaXhEUVVGaUxFTkJSbU03Y1VKQlFXeENPMmxDUVVSS096dEJRVTlCTEhWQ1FVRlBMRWxCUVZBc1EwRjZRM0ZDTzJGQlFYcENPenRCUVRSRFFTeHhRa0ZCVXl4WlFVRlVMRU5CUVhOQ0xFdEJRWFJDTEVWQlFUWkNPMEZCUXpOQ0xHOUNRVUZKTEU5QlFVOHNZMEZCVUN4RlFVRjFRanRCUVVONlFpd3lRa0ZCVHl4UFFVRlBMR05CUVZBc1EwRkJjMElzUzBGQmRFSXNRMEZCVUN4RFFVUjVRanRwUWtGQk0wSXNUVUZGVHl4SlFVRkpMRTFCUVUwc1UwRkJUaXhGUVVGcFFqdEJRVU14UWl3eVFrRkJUeXhOUVVGTkxGTkJRVTRzUTBGRWJVSTdhVUpCUVhKQ0xFMUJSVUVzU1VGQlNTeE5RVUZOTEZkQlFVNHNSVUZCYlVJN1FVRkROVUlzTWtKQlFVOHNUVUZCVFN4WFFVRk9MRU5CUVd0Q0xGTkJRV3hDTEVOQlJIRkNPMmxDUVVGMlFqdGhRVXhVTzFOQmJFUjNRaXhGUVRSRWRFSXNSVUZCUXl4eFFrRkJiMElzUlVGQmNFSXNSVUZCZFVJc1lVRkJXU3hGUVVGYUxFVkJOVVJJTEVOQlFVZ3NSVUUwUkhWQ0xFbEJRVWNzUTBGQlF5eFZRVUZUTEU5QlFWUXNSVUZCYVVJc1RVRkJha0lzUlVGQmQwSXNUMEZCZUVJc1JVRkJaME03UVVGREwwVXNaMEpCUVVrc1ZVRkJWU3hSUVVGUkxGbEJRVklzUTBGQlZpeERRVVF5UlRzN1FVRkhMMFVzWjBKQlFVa3NVMEZCVXl4UlFVRlJMR2xDUVVGU0xFTkJRVlFzUTBGSU1rVTdRVUZKTDBVc1owSkJRVWtzVlVGQlZTeFJRVUZSTEcxQ1FVRlNMRU5CUVZZc1EwRktNa1U3UVVGTEwwVXNaMEpCUVVrc1ZVRkJWU3hSUVVGUkxHMUNRVUZTTEVOQlFWWXNRMEZNTWtVN1FVRk5MMFVzWjBKQlFVa3NWMEZCVnl4UlFVRlJMRzlDUVVGU0xFTkJRVmdzUTBGT01rVTdRVUZQTDBVc1owSkJRVWtzVlVGQlZTeFJRVUZSTEcxQ1FVRlNMRU5CUVZZc1EwRlFNa1U3UVVGUkwwVXNaMEpCUVVrc1kwRkJZeXhSUVVGUkxIVkNRVUZTTEVOQlFXUXNRMEZTTWtVN08wRkJWUzlGTEdkQ1FVRkpMRmxCUVZrc1VVRkJVU3hqUVVGU0xFTkJRVm9zUTBGV01rVTdPMEZCV1M5RkxHMUNRVUZQTEU5QlFWQXNSMEZCYVVJc1NVRkJha0lzUTBGYUswVTdPMEZCWXk5RkxIRkNRVUZUTEVsQlFWUXNRMEZCWXl4RFFVRmtMRVZCUVdsQ0xFTkJRV3BDTEVWQlFXOUNPMEZCUTJoQ0xHOUNRVUZKTEZGQlFWRXNSVUZCUlN4SFFVRkhMRU5CUVVnc1JVRkJWaXhEUVVSWk8wRkJSV2hDTEhGQ1FVRkxMRU5CUVV3c1JVRkJVU3hEUVVGU0xFVkJRVmNzUzBGQldDeEZRVUZyUWl4RFFVRnNRaXhGUVVablFqdEJRVWRvUWl4MVFrRkJUeXhMUVVGUUxFTkJTR2RDTzJGQlFYQkNPenRCUVUxQkxIRkNRVUZUTEVsQlFWUXNRMEZCWXl4RFFVRmtMRVZCUVdsQ0xFTkJRV3BDTEVWQlFXOUNMRXRCUVhCQ0xFVkJRVEpDTEV0QlFUTkNMRVZCUVd0RE8wRkJRemxDTEc5Q1FVRkpMRTFCUVUwc1EwRkJUaXhGUVVGVE8wRkJRMVFzTWtKQlJGTTdhVUpCUVdJN08wRkJTVUVzYjBKQlFVa3NVVUZCVVN4TlFVRk5MRXRCUVU0c1EwRkJVaXhEUVV3d1FqdEJRVTA1UWl4dlFrRkJTU3hoUVVGaExFdEJRV0lzUTBGT01FSTdPMEZCVVRsQ0xHOUNRVUZKTEZGQlFWRXNRMEZCVWl4TFFVRmpMRkZCUVZFc1EwRkJVaXhEUVVGa0xFVkJRVEJDTzBGQlF6RkNMREpDUVVGUExFTkJRVkFzUlVGQlZTeERRVUZXTEVWQlFXRXNTMEZCWWl4RlFVRnZRaXhMUVVGd1FpeEZRVVF3UWp0cFFrRkJPVUlzVFVGRlR5eEpRVUZKTEV0QlFVc3NTVUZCVEN4RlFVRlhPenM3T3p0QlFVdHNRaXgzUWtGQlNTeERRVUZETEZOQlFWTXNRMEZCVkN4RFFVRkVMRVZCUVdNN1FVRkRaQ3h0UTBGQlZ5eERRVUZZTEVWQlFXTXNTMEZCWkN4RlFVRnhRaXhMUVVGeVFpeEZRVVJqTzBGQlJXUXNaME5CUVZFc1RVRkJUU3hMUVVGT0xFTkJRVklzUTBGR1l6dHhRa0ZCYkVJN08wRkJTMEVzTkVKQlFWRXNXVUZCV1N4TFFVRmFMRVZCUVcxQ0xFbEJRVWtzVFVGQlNpeERRVUZYTEU5QlFVOHNUVUZCVUN4RlFVRmxMRU5CUVRGQ0xFVkJRVFpDTEVOQlFUZENMRU5CUVc1Q0xFTkJRVklzUTBGV2EwSTdhVUpCUVdZc1RVRlhRU3hKUVVGSkxGRkJRVkVzUTBGQlVpeERRVUZLTEVWQlFXZENPMEZCUTI1Q0xIZENRVUZKTEZGQlFWRXNRMEZCVWl4RFFVRktMRVZCUVdkQ08wRkJRMW9zTkVKQlFVa3NSVUZCUlN4UFFVRkdMRXRCUVdNc1JVRkJSU3hQUVVGR0xFbEJRMlFzUlVGQlJTeFRRVUZHTEV0QlFXZENMRVZCUVVVc1UwRkJSaXhKUVVOb1FpeEZRVUZGTEVkQlFVWXNTMEZCVlN4RlFVRkZMRWRCUVVZc1JVRkJUenRCUVVOcVFpeG5RMEZCU1N4aFFVRmhMRlZCUVZVc1JVRkJSU3hWUVVGR0xFVkJRV01zUlVGQlJTeFZRVUZHTEVOQlFYSkRMRU5CUkdFN1FVRkZha0lzWjBOQlFVa3NWVUZCU2l4RlFVRm5RanRCUVVOYUxIZERRVUZSTEZsQlFWa3NTMEZCV2l4RlFVTktMRWxCUVVrc1RVRkJTaXhEUVVGWExFOUJRVThzUzBGQlVDeEZRVUZqTEVOQlFYcENMRVZCUVRSQ0xGVkJRVFZDTEVOQlJFa3NRMEZCVWl4RFFVUlpPelpDUVVGb1FqdEJRVWxCTEc5RFFVRlJMR0ZCUVdFc1EwRkJZaXhGUVVGblFpeERRVUZvUWl4RlFVRnRRaXhMUVVGdVFpeEZRVUV3UWl4TFFVRXhRaXhGUVVGcFF5eExRVUZxUXl4RFFVRlNMRU5CVG1sQ08zbENRVVp5UWl4TlFWTlBPMEZCUTBnc2IwTkJRVkVzV1VGQldTeExRVUZhTEVWQlFXMUNMRWxCUVVrc1RVRkJTaXhEUVVGWExFOUJRVThzUzBGQlVDeEZRVUZqTEVOQlFYcENMRVZCUVRSQ0xFTkJRVFZDTEVOQlFXNUNMRU5CUVZJc1EwRkVSenRCUVVWSUxIbERRVUZoTEVsQlFXSXNRMEZHUnp0NVFrRlVVRHR4UWtGRVNpeE5RV05QTzBGQlEwZ3NaME5CUVZFc1dVRkJXU3hMUVVGYUxFVkJRVzFDTEVsQlFVa3NUVUZCU2l4RFFVRlhMRTlCUVU4c1MwRkJVQ3hGUVVGakxFTkJRWHBDTEVWQlFUUkNMRU5CUVRWQ0xFTkJRVzVDTEVOQlFWSXNRMEZFUnp0QlFVVklMSEZEUVVGaExFbEJRV0lzUTBGR1J6dHhRa0ZrVUR0cFFrRkVSeXhOUVcxQ1FTeEpRVUZKTEZGQlFWRXNRMEZCVWl4RFFVRktMRVZCUVdkQ08wRkJRMjVDTEhkQ1FVRkpMRU5CUVVNc1VVRkJVU3hEUVVGU0xFTkJRVVFzUlVGQllUdEJRVU5pTEdkRFFVRlJMRmxCUVZrc1MwRkJXaXhGUVVGdFFpeEpRVUZKTEUxQlFVb3NRMEZCVnl4UFFVRlBMRXRCUVZBc1JVRkJZeXhEUVVGNlFpeEZRVUUwUWl4RFFVRTFRaXhEUVVGdVFpeERRVUZTTEVOQlJHRTdRVUZGWWl4eFEwRkJZU3hKUVVGaUxFTkJSbUU3Y1VKQlFXcENMRTFCUjA4c1NVRkJTU3hGUVVGRkxFbEJRVVlzUzBGQlZ5eEZRVUZGTEVsQlFVWXNSVUZCVVR0QlFVTXhRaXhuUTBGQlVTeFpRVUZaTEV0QlFWb3NSVUZCYlVJc1NVRkJTU3hOUVVGS0xFTkJRVmNzVDBGQlR5eExRVUZRTEVWQlFXTXNRMEZCZWtJc1JVRkJORUlzUTBGQk5VSXNRMEZCYmtJc1EwRkJVaXhEUVVRd1FqdHhRa0ZCZGtJN2FVSkJTa29zVFVGUFFTeEpRVUZKTEZOQlFWTXNRMEZCVkN4RFFVRktMRVZCUVdsQ08wRkJRM0JDTEhkQ1FVRkpMRU5CUVVNc1UwRkJVeXhEUVVGVUxFTkJRVVFzUlVGQll6dEJRVU5rTEhGRFFVRmhMRWxCUVdJc1EwRkVZenR4UWtGQmJFSTdPMEZCU1VFc05FSkJRVkVzV1VGQldTeExRVUZhTEVWQlFXMUNMRWxCUVVrc1RVRkJTaXhEUVVGWExFOUJRVThzVFVGQlVDeEZRVUZsTEVOQlFURkNMRVZCUVRaQ0xFTkJRVGRDTEVOQlFXNUNMRU5CUVZJc1EwRk1iMEk3YVVKQlFXcENPenRCUVZGUUxHOUNRVUZKTEV0QlFVb3NSVUZCVnp0QlFVTlFMREJDUVVGTkxFdEJRVTRzU1VGQlpTeExRVUZtTEVOQlJFODdhVUpCUVZnN08wRkJTVUVzYjBKQlFVa3NWVUZCU2l4RlFVRm5RanRCUVVOYUxDdENRVUZYTEVOQlFWZ3NSVUZCWXl4TFFVRmtMRVZCUVhGQ0xFdEJRWEpDTEVWQlJGazdhVUpCUVdoQ08yRkJNMFJLT3p0QlFXZEZRU3h4UWtGQlV5eFpRVUZVTEVOQlFYTkNMRU5CUVhSQ0xFVkJRWGxDTEVOQlFYcENMRVZCUVRSQ0xFdEJRVFZDTEVWQlFXMURMRXRCUVc1RExFVkJRVEJETEV0QlFURkRMRVZCUVdsRU8wRkJRemRETEc5Q1FVRkpMRmxCUVZrc1JVRkJSU3hSUVVGR0xFTkJSRFpDTzBGQlJUZERMRzlDUVVGSkxHRkJRV0VzVVVGQlVTeFRRVUZTTEVWQlFXMUNMRVZCUVVVc1VVRkJSaXhEUVVGb1F5eERRVVo1UXp0QlFVYzNReXh2UWtGQlNTeFpRVUZaTEZkQlFWY3NVVUZCV0N4RFFVZzJRanM3UVVGTE4wTXNiMEpCUVVrc1QwRkJUeXhWUVVGVkxFMUJRVllzUTBGTWEwTTdRVUZOTjBNc2IwSkJRVWtzVDBGQlR5eFZRVUZWTEUxQlFWWXNRMEZPYTBNN1FVRlBOME1zYjBKQlFVa3NUVUZCVFN4UFFVRlBMRWxCUVZBc1IwRkJZeXhKUVVGa0xFZEJRWEZDTEVsQlFYSkNMRU5CVUcxRE96dEJRVk0zUXl4eFFrRkJTeXhKUVVGSkxFbEJRVWtzUTBGQlNpeEZRVUZQTEVsQlFVa3NSMEZCU2l4RlFVRlRMRWRCUVhwQ0xFVkJRVGhDTzBGQlF6RkNMSGRDUVVGSkxGZEJRVmNzVlVGQlZTeERRVUZXTEVOQlFWZ3NRMEZFYzBJN1FVRkZNVUlzZDBKQlFVa3NXVUZCV1N4VlFVRlZMRU5CUVZZc1EwRkJXaXhEUVVaelFqdEJRVWN4UWl3MlFrRkJVeXhEUVVGVUxFTkJTREJDT3p0QlFVc3hRaXgzUWtGQlNTeERRVUZETEZGQlFVUXNSVUZCVnp0QlFVTllMRFJDUVVGSkxGTkJRVW9zUlVGQlpUczdRVUZGV0N4dlEwRkJVU3haUVVGWkxFdEJRVm9zUlVGRFNpeEpRVUZKTEUxQlFVb3NRMEZCVnl4UFFVRlBMRTFCUVZBc1JVRkJaU3hKUVVFeFFpeEZRVUZuUXl4VFFVRm9ReXhEUVVSSkxFTkJRVklzUTBGR1Z6dDVRa0ZCWmp0eFFrRkVTaXhOUVUxUE8wRkJRMGdzTmtKQlFVc3NVVUZCVEN4RlFVRmxMRk5CUVdZc1JVRkJNRUlzUzBGQk1VSXNSVUZCYVVNc1MwRkJha01zUlVGRVJ6dHhRa0ZPVURzN1FVRlZRU3gzUWtGQlNTeFJRVUZSTEZGQlFWSXNTMEZCY1VJc1UwRkJVeXhMUVVGVUxFVkJRV2RDTzBGQlEzSkRMR2xEUVVGVExGTkJRVk1zUzBGQlZDeERRVVEwUWp0eFFrRkJla003YVVKQlprbzdPMEZCYjBKQkxHOUNRVUZKTEZkQlFWY3NTMEZCV0N4RlFVRnJRanM3UVVGRmJFSXNORUpCUVZFc1dVRkJXU3hMUVVGYUxFVkJRVzFDTEVsQlFVa3NUVUZCU2l4RFFVTjJRaXhQUVVGUExFdEJRVkFzUlVGRFFTeERRVVoxUWl4RlFVZDJRaXhYUVVGWExFdEJRVmdzUTBGSVNTeERRVUZTTEVOQlJtdENPMmxDUVVGMFFqczdRVUZUUVN4MVFrRkJUeXhMUVVGUUxFTkJkRU0yUXp0aFFVRnFSRHM3UVVGNVEwRXNjVUpCUVZNc1ZVRkJWQ3hEUVVGdlFpeExRVUZ3UWl4RlFVRXlRaXhMUVVFelFpeEZRVUZyUXl4TFFVRnNReXhGUVVGNVF6czdRVUZGY2tNc2RVSkJRVThzUzBGQlVDeEZRVUZqTEV0QlFXUXNSVUZCY1VJc1MwRkJja0lzUlVGR2NVTTdRVUZIY2tNc0swSkJRV1VzUzBGQlppeEZRVUZ6UWl4TFFVRjBRaXhGUVVFMlFpeExRVUUzUWl4RlFVaHhRenRoUVVGNlF6czdPenRCUVRkSUswVXNjVUpCY1VsMFJTeGpRVUZVTEVOQlFYZENMRXRCUVhoQ0xFVkJRU3RDTEV0QlFTOUNMRVZCUVhORExFdEJRWFJETEVWQlFUWkRPMEZCUTNwRExHOUNRVUZKTEZOQlFWTXNTMEZCVkN4RFFVRktMRVZCUVhGQ08wRkJRMnBDTEhkQ1FVRkpMRTlCUVU4c1RVRkJUU3hQUVVGT0xFdEJRV3RDTEZWQlFYcENMRVZCUVhGRE8wRkJRM0pETERoQ1FVRk5MRXRCUVU0c1NVRkJaU3haUVVOWUxFMUJRVTBzUzBGQlRpeERRVVJYTEVWQlJWZ3NTVUZCU1N4TlFVRktMRU5CUVZjc1QwRkJUeXhOUVVGUUxFVkJRV1VzUzBGQk1VSXNSVUZCYVVNc1NVRkJha01zUTBGR1Z5eERRVUZtTEVOQlJIRkRPM0ZDUVVGNlF6dHBRa0ZFU2l4TlFVOVBMRWxCUVVrc1VVRkJVU3hMUVVGU0xFMUJRVzFDTEUxQlFVMHNWVUZCVGl4SlFVRnZRaXhOUVVGTkxGTkJRVTRzUTBGQmRrTXNSVUZCZVVRN1FVRkRhRVVzZDBKQlFVa3NWMEZCVnl4TlFVRk5MRkZCUVU0c1EwRkVhVVE3UVVGRmFFVXNkMEpCUVVrc1RVRkJUU3hUUVVGVExFMUJRVlFzUTBGR2MwUTdRVUZIYUVVc2VVSkJRVXNzU1VGQlNTeEpRVUZKTEVOQlFVb3NSVUZCVHl4SlFVRkpMRWRCUVVvc1JVRkJVeXhIUVVGNlFpeEZRVUU0UWp0QlFVTXhRaXcwUWtGQlNTeFJRVUZSTEZOQlFWTXNRMEZCVkN4RFFVRlNMRU5CUkhOQ08wRkJSVEZDTEdsRFFVRlRMRU5CUVZRc1EwRkdNRUk3TzBGQlNURkNMSFZEUVVGbExFdEJRV1lzUlVGQmMwSXNTMEZCZEVJc1JVRkJOa0lzUzBGQk4wSXNSVUZLTUVJN08wRkJUVEZDTERSQ1FVRkpMRkZCUVZFc1MwRkJVaXhMUVVGclFpeE5RVUZOTEV0QlFVNHNSVUZCWVR0QlFVTXZRaXh4UTBGQlV5eE5RVUZOTEV0QlFVNHNRMEZFYzBJN2VVSkJRVzVETzNGQ1FVNUtPMmxDUVVoSExFMUJZVUVzU1VGQlNTeFJRVUZSTEV0QlFWSXNRMEZCU2l4RlFVRnZRanRCUVVOMlFpd3lRa0ZCVHl4TFFVRlFMRVZCUVdNc1NVRkJaQ3hGUVVGdlFpeExRVUZ3UWl4RlFVRXlRaXhMUVVFelFpeEZRVVIxUWp0cFFrRkJjRUk3WVVGeVFsZzdPenRCUVhKSkswVXNjVUpCWjB0MFJTeE5RVUZVTEVOQlFXZENMRU5CUVdoQ0xFVkJRVzFDTEVOQlFXNUNMRVZCUVhOQ0xFdEJRWFJDTEVWQlFUWkNMRXRCUVRkQ0xFVkJRVzlETzBGQlEyaERMRzlDUVVGSkxGRkJRVkVzV1VGQldTeERRVUZhTEVWQlFXVXNRMEZCWml4RFFVRlNMRU5CUkRSQ08wRkJSV2hETEc5Q1FVRkpMR0ZCUVdFc1MwRkJTeXhOUVVGTkxFTkJRVTRzUlVGQlV5eE5RVUZOTEVOQlFVNHNRMEZCTTBJc1EwRkdORUk3UVVGSGFFTXNiMEpCUVVrc1YwRkJWeXhWUVVGWUxFTkJRVW9zUlVGQk5FSTdRVUZEZUVJc01FSkJRVTBzUzBGQlRpeEpRVUZsTEVsQlFVa3NUVUZCU2l4RFFVRlhMRTlCUVU4c1MwRkJVQ3hGUVVGakxFbEJRWHBDTEVWQlFTdENMRlZCUVM5Q0xFTkJRV1lzUTBGRWQwSTdhVUpCUVRWQ08yRkJTRW83TzBGQlVVRXNjVUpCUVZNc1ZVRkJWQ3hEUVVGdlFpeExRVUZ3UWl4RlFVRXlRanRCUVVOMlFpeHhRa0ZCU3l4SlFVRkpMRXRCUVVvc1NVRkJZU3hMUVVGc1FpeEZRVUY1UWp0QlFVTnlRaXgzUWtGQlNTeFZRVUZWTEVkQlFWWXNSVUZCWlR0QlFVTm1MQ3RDUVVGUExFbEJRVkFzUTBGRVpUdHhRa0ZCYmtJN2FVSkJSRW83TzBGQlRVRXNkVUpCUVU4c1MwRkJVQ3hEUVZCMVFqdGhRVUV6UWpzN08wRkJlRXNyUlN4eFFrRnRUSFJGTEUxQlFWUXNRMEZCWjBJc1MwRkJhRUlzUlVGQmRVSXNTMEZCZGtJc1JVRkJPRUlzUzBGQk9VSXNSVUZCY1VNN1FVRkRha01zYjBKQlFVa3NVVUZCVVN4TFFVRlNMRU5CUVVvc1JVRkJiMEk3UVVGRGFFSXNkMEpCUVVrc1RVRkJUU3hMUVVGT0xFVkJRV0U3UVVGRFlpdzRRa0ZCVFN4TFFVRk9MRWxCUVdVc1dVRkRXQ3hOUVVGTkxFdEJRVTRzUTBGRVZ5eEZRVVZZTEVsQlFVa3NUVUZCU2l4RFFVTkpMRTlCUVU4c1MwRkJVQ3hGUVVOQkxFdEJSa29zUlVGSFNTeGpRVUZqTEUxQlFVMHNTMEZCVGl4RFFVaHNRaXhEUVVaWExFTkJRV1lzUTBGRVlUdHhRa0ZCYWtJN08wRkJWMEVzZDBKQlFVa3NUVUZCVFN4bFFVRk9MRWxCUVhsQ0xFMUJRVTBzVTBGQlRpeEZRVUZwUWp0QlFVTXhReXcwUWtGQlNTeFhRVUZYTEUxQlFVMHNVVUZCVGl4RFFVUXlRanRCUVVVeFF5dzBRa0ZCU1N4TlFVRk5MRk5CUVZNc1RVRkJWQ3hEUVVablF6dEJRVWN4UXl3MlFrRkJTeXhKUVVGSkxFbEJRVWtzUTBGQlNpeEZRVUZQTEVsQlFVa3NSMEZCU2l4RlFVRlRMRWRCUVhwQ0xFVkJRVGhDTzBGQlF6RkNMR2REUVVGSkxGRkJRVkVzVTBGQlV5eERRVUZVTEVOQlFWSXNRMEZFYzBJN1FVRkZNVUlzY1VOQlFWTXNRMEZCVkN4RFFVWXdRanM3UVVGSk1VSXNiVU5CUVU4c1MwRkJVQ3hGUVVGakxFdEJRV1FzUlVGQmNVSXNTMEZCY2tJc1JVRktNRUk3TzBGQlRURkNMR2REUVVGSkxGRkJRVkVzUzBGQlVpeExRVUZyUWl4TlFVRk5MRXRCUVU0c1JVRkJZVHRCUVVNdlFpeDVRMEZCVXl4TlFVRk5MRXRCUVU0c1EwRkVjMEk3TmtKQlFXNURPM2xDUVU1S08zRkNRVWhLTzJsQ1FWcEtMRTFCTUVKUExFbEJRVWtzVVVGQlVTeExRVUZTTEVOQlFVb3NSVUZCYjBJN1FVRkRka0lzTWtKQlFVOHNTMEZCVUN4RlFVRmpMRWxCUVdRc1JVRkJiMElzUzBGQmNFSXNSVUZCTWtJc1MwRkJNMElzUlVGRWRVSTdhVUpCUVhCQ08yRkJNMEpZT3p0QlFXZERRU3h4UWtGQlV5eGhRVUZVTEVOQlFYVkNMRWRCUVhaQ0xFVkJRVFJDTzBGQlEzaENMRzlDUVVGSkxGTkJRVk1zUlVGQlZDeERRVVJ2UWpzN1FVRkhlRUlzY1VKQlFVc3NTVUZCU1N4SFFVRktMRWxCUVZjc1IwRkJhRUlzUlVGQmNVSTdRVUZEYWtJc01rSkJRVThzUjBGQlVDeEpRVUZqTEZOQlFXUXNRMEZFYVVJN2FVSkJRWEpDT3p0QlFVbEJMSFZDUVVGUExFMUJRVkFzUTBGUWQwSTdZVUZCTlVJN096dEJRVzVPSzBVc2NVSkJPRTUwUlN4UFFVRlVMRU5CUVdsQ0xGTkJRV3BDTEVWQlFUUkNMRk5CUVRWQ0xFVkJRWFZET3p0QlFVVnVReXh2UWtGQlNTeGpRVUZqTEZOQlFWTXNVMEZCVkN4RFFVRmtMRU5CUml0Q08wRkJSMjVETEc5Q1FVRkpMRkZCUVZFc1dVRkJXU3hKUVVGYUxFTkJTSFZDTzBGQlNXNURMRzlDUVVGSkxGRkJRVkVzV1VGQldTeEpRVUZhTEVOQlNuVkNPenRCUVUxdVF5eHZRa0ZCU1N4TlFVRk5MRTFCUVU0c1MwRkJhVUlzVlVGQlZTeE5RVUZXTEVWQlFXdENPMEZCUTI1RExESkNRVUZQTzBGQlEwZ3NhME5CUVZVc1UwRkJWanRCUVVOQkxDdENRVUZQTEVsQlFWQTdjVUpCUmtvc1EwRkViVU03YVVKQlFYWkRPenM3UVVGT2JVTXNiMEpCWXk5Q0xHTkJRV01zVTBGQlV5eFRRVUZVTEVOQlFXUXNRMEZrSzBJN1FVRmxia01zYjBKQlFVa3NVVUZCVVN4WlFVRlpMRWxCUVZvc1EwRm1kVUk3UVVGblFtNURMRzlDUVVGSkxGRkJRVkVzV1VGQldTeEpRVUZhTEVOQmFFSjFRanM3UVVGclFtNURMRzlDUVVGSkxFMUJRVTBzVFVGQlRpeExRVUZwUWl4VlFVRlZMRTFCUVZZc1JVRkJhMEk3UVVGRGJrTXNNa0pCUVU4N1FVRkRTQ3hyUTBGQlZTeFRRVUZXTzBGQlEwRXNLMEpCUVU4c1NVRkJVRHR4UWtGR1NpeERRVVJ0UXp0cFFrRkJka003T3p0QlFXeENiVU1zYjBKQk1FSXZRaXhqUVVGakxFVkJRV1FzUTBFeFFpdENPenRCUVRSQ2JrTXNiMEpCUVVrc1dVRkJXU3hEUVVGYUxFTkJOVUlyUWp0QlFUWkNia01zYjBKQlFVa3NXVUZCV1N4TlFVRk5MRTFCUVU0c1EwRTNRbTFDTzBGQk9FSnVReXh2UWtGQlNTeGxRVUZsTEVOQlFXWTdPenM3UVVFNVFpdENMSEZDUVd0RE9VSXNTVUZCU1N4SlFVRkpMRU5CUVVvc1JVRkJVU3hKUVVGSkxGVkJRVlVzVFVGQlZpeEZRVUZyUWl4SFFVRjJReXhGUVVFMFF6dEJRVU40UXl4M1FrRkJTU3hSUVVGUkxGVkJRVlVzUTBGQlZpeERRVUZTTEVOQlJHOURPMEZCUlhoRExIZENRVUZKTEZOQlFVb3NRMEZHZDBNN08wRkJTWGhETEhkQ1FVRkpMRTFCUVUwc1IwRkJUaXhGUVVGWE8wRkJRMWdzTkVKQlFVa3NUVUZCVFN4alFVRk9MRU5CUVhGQ0xFMUJRVTBzUjBGQlRpeERRVUY2UWl4RlFVRnhRenM3UVVGRmFrTXNkME5CUVZrc1RVRkJUU3hOUVVGTkxFZEJRVTRzUTBGQmJFSXNRMEZHYVVNN1FVRkhha01zZDBOQlFWa3NTVUZCV2l4RFFVRnBRaXhWUVVGVkxGTkJRVllzUTBGQmFrSXNSVUZJYVVNN2VVSkJRWEpETEUxQlMwODdPMEZCUlVnc2QwTkJRVmtzU1VGQlNTeGpRVUZLTEVOQlJsUTdRVUZIU0N4M1EwRkJXU3hKUVVGYUxFTkJRV2xDTEVsQlFXcENMRVZCU0VjN2VVSkJURkE3Y1VKQlJFb3NUVUZYVHpzN1FVRkZTQ3cwUWtGQlNTeFpRVUZaTEZOQlFWb3NSVUZCZFVJN1FVRkRka0lzZDBOQlFWa3NUVUZCVFN4WFFVRk9MRU5CUVZvc1EwRkVkVUk3UVVGRmRrSXNkME5CUVZrc1NVRkJXaXhEUVVGcFFpeFZRVUZWTEZOQlFWWXNRMEZCYWtJc1JVRkdkVUk3ZVVKQlFUTkNMRTFCUjA4N096czdRVUZKU0N4M1EwRkJXU3hKUVVGSkxHTkJRVW9zUTBGS1ZEdEJRVXRJTEhkRFFVRlpMRWxCUVZvc1EwRkJhVUlzU1VGQmFrSXNSVUZNUnp0NVFrRklVRHR4UWtGaVNqdHBRa0ZLU2pzN1FVRTRRa0VzYjBKQlFVa3NaMEpCUVdkQ0xHRkJRV0VzVFVGQlRTeE5RVUZPTEVkQlF6ZENMRlZCUVZVc1RVRkJWaXhIUVVOQkxFMUJRVTBzVTBGQlRpeERRVVpuUWpzN096dEJRV2hGWlN4eFFrRnpSVGxDTEVsQlFVa3NTVUZCU1N4RFFVRktMRVZCUVU4c1NVRkJTU3hWUVVGVkxFMUJRVllzUlVGQmEwSXNSMEZCZEVNc1JVRkJNa003UVVGRGRrTXNkMEpCUVVrc1ZVRkJWU3hWUVVGVkxFTkJRVllzUTBGQlZpeERRVVJ0UXpzN1FVRkhka01zZDBKQlFVa3NVVUZCVVN4SFFVRlNMRVZCUVdFN1FVRkRZaXcwUWtGQlNTeERRVUZETEUxQlFVMHNZMEZCVGl4RFFVRnhRaXhSUVVGUkxFZEJRVklzUTBGQmRFSXNSVUZCYjBNN096czdRVUZKY0VNc2QwTkJRVmtzU1VGQldpeERRVUZwUWl4UFFVRnFRaXhGUVVwdlF6dDVRa0ZCZUVNN2NVSkJSRW9zVFVGUFR5eEpRVUZKTEV0QlFVc3NZVUZCVEN4RlFVRnZRanM3UVVGRk0wSXNiME5CUVZrc1NVRkJXaXhEUVVGcFFpeFBRVUZxUWl4RlFVWXlRanR4UWtGQmVFSTdhVUpCVmxnN08wRkJaMEpCTEc5Q1FVRkpMRmRCUVZjc1dVRkJXU3hMUVVGYUxFVkJRVmdzUTBGMFJpdENPMEZCZFVadVF5eHZRa0ZCU1N4blFrRkJaMElzUTBGQmFFSXNRMEYyUml0Q08wRkJkMFp1UXl4dlFrRkJTU3hWUVVGVkxFVkJRVllzUTBGNFJpdENPMEZCZVVadVF5eHZRa0ZCU1N4VlFVRlZMRVZCUVZZc1EwRjZSaXRDTzBGQk1FWnVReXh2UWtGQlNTeFpRVUZLTEVOQk1VWnRRenM3UVVFMFJtNURMSEZDUVVGTExFbEJRVWtzU1VGQlNTeERRVUZLTEVWQlFVOHNTVUZCU1N4VlFVRlZMRTFCUVZZc1IwRkJiVUk3UVVGRGJrTXNkMEpCUVVrc1lVRkJZU3hWUVVGVkxFTkJRVllzUTBGQllpeERRVVFyUWp0QlFVVnVReXh0UTBGQlpTeFRRVUZUTEdGQlFWUXNRMEZCWmpzN08wRkJSbTFETERKQ1FVczFRaXhwUWtGQmFVSXNTVUZCYWtJc1NVRkJlVUlzVTBGQlV5eE5RVUZVTEVWQlFXbENPMEZCUXpkRExHZERRVUZSTEVsQlFWSXNRMEZCWVN4UFFVRlBMRkZCUVZBc1JVRkJhVUlzWVVGQmFrSXNSVUZCWjBNc1NVRkJhRU1zUTBGQllpeEZRVVEyUXp0QlFVVTNReXgxUTBGQlpTeFRRVUZUTEdGQlFWUXNRMEZCWml4RFFVWTJRenR4UWtGQmFrUTdPMEZCUzBFc2QwSkJRVWtzUTBGQlF5eFpRVUZFTEVsQlFXbENMR0ZCUVdFc1IwRkJZaXhMUVVGeFFpeFhRVUZYTEVkQlFWZ3NSVUZCWjBJN08wRkJSWFJFTERSQ1FVRkpMRmRCUVZjc1IwRkJXQ3hGUVVGblFqdEJRVU5vUWl4blEwRkJTU3huUWtGQlowSXNZVUZCWVN4SFFVRmlMRVZCUVd0Q096dEJRVVZzUXl4dlEwRkJTU3hOUVVGTkxHRkJRV0VzUjBGQllpeERRVUZPTEV0QlFUUkNMRWxCUVVrc1EwRkJTaXhGUVVGUE8wRkJRMjVETERSRFFVRlJMRWxCUVZJc1EwRkJZU3hQUVVGUExGRkJRVkFzUlVGQmFVSXNZVUZCYWtJc1JVRkJaME1zWVVGQllTeEhRVUZpTEVOQlFUZERMRVZCUkcxRE8wRkJSVzVETEcxRVFVRmxMRk5CUVZNc1lVRkJWQ3hEUVVGbU96dEJRVVp0UXl4M1EwRkpMMElzUTBGQlF5eFpRVUZFTEVsQlFXbENMR0ZCUVdFc1IwRkJZaXhMUVVGeFFpeFhRVUZYTEVkQlFWZ3NSVUZCWjBJN1FVRkRkRVFzWjBSQlFWRXNTVUZCVWl4RFFVRmhMRVZCUVVNc1MwRkJTeXhYUVVGWExFZEJRVmdzUlVGQlowSXNTVUZCU1N4RFFVRktMRVZCUVc1RExFVkJSSE5FT3pzN1FVRkJNVVFzZVVOQlNVczdRVUZEUkN3MFJFRkVRenQ1UTBGS1REdHBRMEZLU2l4TlFWbExPMEZCUTBRc05FTkJRVkVzU1VGQlVpeERRVUZoTEVWQlFVTXNTMEZCU3l4WFFVRlhMRWRCUVZnc1JVRkJaMElzU1VGQlNTeERRVUZLTEVWQlFXNURMRVZCUkVNN2FVTkJXa3c3TmtKQlJrb3NUVUZyUWtzN1FVRkRSQ3gzUTBGQlVTeEpRVUZTTEVOQlFXRXNSVUZCUXl4TFFVRkxMRmRCUVZjc1IwRkJXQ3hGUVVGblFpeEpRVUZKTEVOQlFVb3NSVUZCYmtNc1JVRkVRenMyUWtGc1FrdzdRVUZ4UWtFc1owTkJkRUpuUWpzN08wRkJRWEJDTERaQ1FYbENTeXhKUVVGSkxHZENRVUZuUWl4aFFVRmhMRWRCUVdJc1JVRkJhMEk3UVVGRGRrTXNkME5CUVZFc1NVRkJVaXhEUVVGaExFOUJRVThzVVVGQlVDeEZRVUZwUWl4aFFVRnFRaXhGUVVGblF5eGhRVUZoTEVkQlFXSXNRMEZCTjBNc1JVRkVkVU03TmtKQlFYUkRPM0ZDUVROQ1ZDeE5RU3RDU3p0QlFVTkVMSGREUVVSRE8wRkJSVVFzTkVKQlJrTTdjVUpCTDBKTU8ybENRVlpLT3pzN1FVRTFSbTFETEhWQ1FUUkpOMElzWjBKQlFXZENMRk5CUVZNc1RVRkJWQ3hGUVVGcFFqdEJRVU51UXl4dFEwRkJaU3hUUVVGVExHRkJRVlFzUTBGQlppeERRVVJ0UXp0QlFVVnVReXcwUWtGQlVTeEpRVUZTTEVOQlFXRXNUMEZCVHl4UlFVRlFMRVZCUVdsQ0xHRkJRV3BDTEVWQlFXZERMR2RDUVVGblFpeGhRVUZoTEVkQlFXSXNRMEZCTjBRc1JVRkdiVU03YVVKQlFYWkRPenM3TzBGQk5VbHRReXh2UWtGdFNpOUNMRkZCUVZFc1RVRkJVaXhMUVVGdFFpeFpRVUZ1UWl4SlFVRnRReXhEUVVGRExGRkJRVkVzVFVGQlVpeEZRVUZuUWp0QlFVTndSQ3d5UWtGQlR6dEJRVU5JTEd0RFFVRlZMRmRCUVZZN1FVRkRRU3dyUWtGQlR5eEpRVUZRTzNGQ1FVWktMRU5CUkc5RU8ybENRVUY0UkRzN1FVRlBRU3gxUWtGQlR6dEJRVU5JTERoQ1FVRlZMRmRCUVZZN1FVRkRRU3d5UWtGQlR6dEJRVU5JTEdsRFFVRlRMRTlCUVZRN1FVRkRRU3hwUTBGQlV5eFBRVUZVTzNGQ1FVWktPMmxDUVVaS0xFTkJNVXB0UXp0aFFVRjJRenM3UVVGdFMwRXNjVUpCUVZNc1RVRkJWQ3hEUVVGblFpeEhRVUZvUWl4RlFVRnhRaXhMUVVGeVFpeEZRVUUwUWl4SFFVRTFRaXhGUVVGcFF6dEJRVU0zUWl4dlFrRkJTU3hOUVVGS0xFTkJRVmNzUzBGQldDeEZRVUZyUWl4RFFVRnNRaXhGUVVRMlFqczdRVUZITjBJc2RVSkJRVTg3UVVGRFNDd3dRa0ZCVFN4TFFVRk9PMEZCUTBFc2VVSkJRVXNzUjBGQlREdHBRa0ZHU2l4RFFVZzJRanRoUVVGcVF6czdRVUZUUVN4eFFrRkJVeXhSUVVGVUxFTkJRV3RDTEZGQlFXeENMRVZCUVRSQ08wRkJRM2hDTEc5Q1FVRkpMRTlCUVU4c1JVRkJVQ3hEUVVSdlFqdEJRVVY0UWl4dlFrRkJTU3hQUVVGUExFVkJRVkFzUTBGR2IwSTdRVUZIZUVJc2IwSkJRVWtzVTBGQlV5eFRRVUZUTEUxQlFWUXNRMEZJVnpzN1FVRkxlRUlzY1VKQlFVc3NTVUZCU1N4SlFVRkpMRU5CUVVvc1JVRkJUeXhKUVVGSkxFMUJRVW9zUlVGQldTeEhRVUUxUWl4RlFVRnBRenRCUVVNM1FpeDNRa0ZCU1N4UlFVRlJMRk5CUVZNc1EwRkJWQ3hEUVVGU0xFTkJSSGxDT3p0QlFVYzNRaXgzUWtGQlNTeE5RVUZOTEVkQlFVNHNSVUZCVnp0QlFVTllMRFpDUVVGTExFMUJRVTBzUjBGQlRpeERRVUZNTEVkQlFXdENMRU5CUVd4Q0xFTkJSRmM3Y1VKQlFXWXNUVUZGVHp0QlFVTklMRFpDUVVGTExFbEJRVXdzUTBGQlZTeERRVUZXTEVWQlJFYzdjVUpCUmxBN2FVSkJTRW83TzBGQlZVRXNkVUpCUVU4N1FVRkRTQ3d3UWtGQlRTeEpRVUZPTzBGQlEwRXNNRUpCUVUwc1NVRkJUanRCUVVaSExHbENRVUZRTEVOQlpuZENPMkZCUVRWQ096dEJRWEZDUVN4eFFrRkJVeXhYUVVGVUxFTkJRWEZDTEV0QlFYSkNMRVZCUVRSQ0xFdEJRVFZDTEVWQlFXMURPMEZCUXk5Q0xHOUNRVUZKTEV0QlFVb3NSVUZCVnp0QlFVTlFMSGRDUVVGSkxGRkJRVkVzUzBGQlVpeERRVUZLTEVWQlFXOUNPMEZCUTJoQ0xEaENRVUZOTEVsQlFVNHNRMEZCVnl4TFFVRllMRVZCUkdkQ08zRkNRVUZ3UWl4TlFVVlBPMEZCUTBnc1owTkJRVkVzUTBGQlF5eExRVUZFTEVWQlFWRXNTMEZCVWl4RFFVRlNMRU5CUkVjN2NVSkJSbEE3TzBGQlRVRXNNa0pCUVU4c1MwRkJVQ3hEUVZCUE8ybENRVUZZTEUxQlVVODdRVUZEU0N3eVFrRkJUeXhMUVVGUUxFTkJSRWM3YVVKQlVsQTdZVUZFU2p0VFFTOWFLME1zUlVFMllUZERMRVZCUVVNc2VVSkJRWGRDTEVWQlFYaENMRVZCUVRKQ0xIRkNRVUZ2UWl4RlFVRndRaXhGUVVGMVFpeHhRa0ZCYjBJc1JVRkJjRUlzUlVGQmRVSXNjVUpCUVc5Q0xFVkJRWEJDTEVWQlFYVkNMSE5DUVVGeFFpeEZRVUZ5UWl4RlFVRjNRaXh0UWtGQmEwSXNSVUZCYkVJc1JVRkJjVUlzWjBKQlFXVXNSVUZCWml4RlFVRnJRaXhqUVVGaExFVkJRV0lzUlVFM1lYQklMRU5CUVVnc1JVRTVkVU0xUWl4RlFUSndSSE5MTEVWQk0zQkVkRXNzUlVFeWNFUjVTeXhEUVVGRExFTkJRVVFzUTBFemNFUjZTeXhGUVRKd1JEaExMRU5CTTNCRU9Vc3NRMEZCVUN4RFFVWkxPME5CUVZnc1EwRkdSVHM3UVVGcmNVUktMR1ZCUVdVc1ZVRkJaaUlzSW1acGJHVWlPaUpzYVdJdmRtbHlkSFZoYkMxa2IyMHVhbk1pTENKemIzVnlZMlZ6UTI5dWRHVnVkQ0k2V3lKc1pYUWdWbWx5ZEhWaGJFUlBUU0E5SUdaMWJtTjBhVzl1S0dVcElIdGNiaUFnY21WMGRYSnVJR1VvS1R0Y2JuMG9ablZ1WTNScGIyNG9LU0I3WEc0Z0lDQWdJQ0FnSUhaaGNpQmtaV1pwYm1Vc0lHMXZaSFZzWlN3Z1pYaHdiM0owY3p0Y2JpQWdJQ0FnSUNBZ2NtVjBkWEp1SUNobWRXNWpkR2x2YmlCbEtIUXNJRzRzSUhJcElIdGNiaUFnSUNBZ0lDQWdJQ0FnSUNBZ0lDQm1kVzVqZEdsdmJpQnpLRzhzSUhVcElIdGNiaUFnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnYVdZZ0tDRnVXMjlkS1NCN1hHNGdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNCcFppQW9JWFJiYjEwcElIdGNiaUFnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0IyWVhJZ1lTQTlJSFI1Y0dWdlppQnlaWEYxYVhKbElEMDlJRndpWm5WdVkzUnBiMjVjSWlBbUppQnlaWEYxYVhKbE8xeHVJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJR2xtSUNnaGRTQW1KaUJoS1NCeVpYUjFjbTRnWVNodkxDQWhNQ2s3WEc0Z0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ2FXWWdLR2twSUhKbGRIVnliaUJwS0c4c0lDRXdLVHRjYmlBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNCMllYSWdaaUE5SUc1bGR5QkZjbkp2Y2loY0lrTmhibTV2ZENCbWFXNWtJRzF2WkhWc1pTQW5YQ0lnS3lCdklDc2dYQ0luWENJcE8xeHVJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJSFJvY205M0lHWXVZMjlrWlNBOUlGd2lUVTlFVlV4RlgwNVBWRjlHVDFWT1JGd2lMQ0JtWEc0Z0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0I5WEc0Z0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0IyWVhJZ2JDQTlJRzViYjEwZ1BTQjdYRzRnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnWlhod2IzSjBjem9nZTMxY2JpQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUgwN1hHNGdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNCMFcyOWRXekJkTG1OaGJHd29iQzVsZUhCdmNuUnpMQ0JtZFc1amRHbHZiaWhsS1NCN1hHNGdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdkbUZ5SUc0Z1BTQjBXMjlkV3pGZFcyVmRPMXh1SUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUhKbGRIVnliaUJ6S0c0Z1B5QnVJRG9nWlNsY2JpQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUgwc0lHd3NJR3d1Wlhod2IzSjBjeXdnWlN3Z2RDd2diaXdnY2lsY2JpQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdmVnh1SUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNCeVpYUjFjbTRnYmx0dlhTNWxlSEJ2Y25SelhHNGdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ2ZWeHVJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lIWmhjaUJwSUQwZ2RIbHdaVzltSUhKbGNYVnBjbVVnUFQwZ1hDSm1kVzVqZEdsdmJsd2lJQ1ltSUhKbGNYVnBjbVU3WEc0Z0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnWm05eUlDaDJZWElnYnlBOUlEQTdJRzhnUENCeUxteGxibWQwYURzZ2J5c3JLU0J6S0hKYmIxMHBPMXh1SUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJSEpsZEhWeWJpQnpYRzRnSUNBZ0lDQWdJQ0FnSUNCOUtTaDdYRzRnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSURFNklGdG1kVzVqZEdsdmJpaHlaWEYxYVhKbExDQnRiMlIxYkdVc0lHVjRjRzl5ZEhNcElIdGNibHh1ZG1GeUlHTnlaV0YwWlVWc1pXMWxiblFnUFNCeVpYRjFhWEpsS0Z3aUxpOTJaRzl0TDJOeVpXRjBaUzFsYkdWdFpXNTBMbXB6WENJcFhHNWNibTF2WkhWc1pTNWxlSEJ2Y25SeklEMGdZM0psWVhSbFJXeGxiV1Z1ZEZ4dVhHNTlMSHRjSWk0dmRtUnZiUzlqY21WaGRHVXRaV3hsYldWdWRDNXFjMXdpT2pFMWZWMHNNanBiWm5WdVkzUnBiMjRvY21WeGRXbHlaU3h0YjJSMWJHVXNaWGh3YjNKMGN5bDdYRzUyWVhJZ1pHbG1aaUE5SUhKbGNYVnBjbVVvWENJdUwzWjBjbVZsTDJScFptWXVhbk5jSWlsY2JseHViVzlrZFd4bExtVjRjRzl5ZEhNZ1BTQmthV1ptWEc1Y2JuMHNlMXdpTGk5MmRISmxaUzlrYVdabUxtcHpYQ0k2TXpWOVhTd3pPbHRtZFc1amRHbHZiaWh5WlhGMWFYSmxMRzF2WkhWc1pTeGxlSEJ2Y25SektYdGNiblpoY2lCb0lEMGdjbVZ4ZFdseVpTaGNJaTR2ZG1seWRIVmhiQzFvZVhCbGNuTmpjbWx3ZEM5cGJtUmxlQzVxYzF3aUtWeHVYRzV0YjJSMWJHVXVaWGh3YjNKMGN5QTlJR2hjYmx4dWZTeDdYQ0l1TDNacGNuUjFZV3d0YUhsd1pYSnpZM0pwY0hRdmFXNWtaWGd1YW5OY0lqb3lNbjFkTERRNlcyWjFibU4wYVc5dUtISmxjWFZwY21Vc2JXOWtkV3hsTEdWNGNHOXlkSE1wZTF4dWRtRnlJR1JwWm1ZZ1BTQnlaWEYxYVhKbEtGd2lMaTlrYVdabUxtcHpYQ0lwWEc1MllYSWdjR0YwWTJnZ1BTQnlaWEYxYVhKbEtGd2lMaTl3WVhSamFDNXFjMXdpS1Z4dWRtRnlJR2dnUFNCeVpYRjFhWEpsS0Z3aUxpOW9MbXB6WENJcFhHNTJZWElnWTNKbFlYUmxJRDBnY21WeGRXbHlaU2hjSWk0dlkzSmxZWFJsTFdWc1pXMWxiblF1YW5OY0lpbGNiblpoY2lCV1RtOWtaU0E5SUhKbGNYVnBjbVVvSnk0dmRtNXZaR1V2ZG01dlpHVXVhbk1uS1Z4dWRtRnlJRlpVWlhoMElEMGdjbVZ4ZFdseVpTZ25MaTkyYm05a1pTOTJkR1Y0ZEM1cWN5Y3BYRzVjYm0xdlpIVnNaUzVsZUhCdmNuUnpJRDBnZTF4dUlDQWdJR1JwWm1ZNklHUnBabVlzWEc0Z0lDQWdjR0YwWTJnNklIQmhkR05vTEZ4dUlDQWdJR2c2SUdnc1hHNGdJQ0FnWTNKbFlYUmxPaUJqY21WaGRHVXNYRzRnSUNBZ1ZrNXZaR1U2SUZaT2IyUmxMRnh1SUNBZ0lGWlVaWGgwT2lCV1ZHVjRkRnh1ZlZ4dVhHNTlMSHRjSWk0dlkzSmxZWFJsTFdWc1pXMWxiblF1YW5OY0lqb3hMRndpTGk5a2FXWm1MbXB6WENJNk1peGNJaTR2YUM1cWMxd2lPak1zWENJdUwzQmhkR05vTG1welhDSTZNVE1zWENJdUwzWnViMlJsTDNadWIyUmxMbXB6WENJNk16RXNYQ0l1TDNadWIyUmxMM1owWlhoMExtcHpYQ0k2TXpOOVhTdzFPbHRtZFc1amRHbHZiaWh5WlhGMWFYSmxMRzF2WkhWc1pTeGxlSEJ2Y25SektYdGNiaThxSVZ4dUlDb2dRM0p2YzNNdFFuSnZkM05sY2lCVGNHeHBkQ0F4TGpFdU1WeHVJQ29nUTI5d2VYSnBaMmgwSURJd01EY3RNakF4TWlCVGRHVjJaVzRnVEdWMmFYUm9ZVzRnUEhOMFpYWmxibXhsZG1sMGFHRnVMbU52YlQ1Y2JpQXFJRUYyWVdsc1lXSnNaU0IxYm1SbGNpQjBhR1VnVFVsVUlFeHBZMlZ1YzJWY2JpQXFJRVZEVFVGVFkzSnBjSFFnWTI5dGNHeHBZVzUwTENCMWJtbG1iM0p0SUdOeWIzTnpMV0p5YjNkelpYSWdjM0JzYVhRZ2JXVjBhRzlrWEc0Z0tpOWNibHh1THlvcVhHNGdLaUJUY0d4cGRITWdZU0J6ZEhKcGJtY2dhVzUwYnlCaGJpQmhjbkpoZVNCdlppQnpkSEpwYm1keklIVnphVzVuSUdFZ2NtVm5aWGdnYjNJZ2MzUnlhVzVuSUhObGNHRnlZWFJ2Y2k0Z1RXRjBZMmhsY3lCdlppQjBhR1ZjYmlBcUlITmxjR0Z5WVhSdmNpQmhjbVVnYm05MElHbHVZMngxWkdWa0lHbHVJSFJvWlNCeVpYTjFiSFFnWVhKeVlYa3VJRWh2ZDJWMlpYSXNJR2xtSUdCelpYQmhjbUYwYjNKZ0lHbHpJR0VnY21WblpYZ2dkR2hoZENCamIyNTBZV2x1YzF4dUlDb2dZMkZ3ZEhWeWFXNW5JR2R5YjNWd2N5d2dZbUZqYTNKbFptVnlaVzVqWlhNZ1lYSmxJSE53YkdsalpXUWdhVzUwYnlCMGFHVWdjbVZ6ZFd4MElHVmhZMmdnZEdsdFpTQmdjMlZ3WVhKaGRHOXlZQ0JwY3lCdFlYUmphR1ZrTGx4dUlDb2dSbWw0WlhNZ1luSnZkM05sY2lCaWRXZHpJR052YlhCaGNtVmtJSFJ2SUhSb1pTQnVZWFJwZG1VZ1lGTjBjbWx1Wnk1d2NtOTBiM1I1Y0dVdWMzQnNhWFJnSUdGdVpDQmpZVzRnWW1VZ2RYTmxaQ0J5Wld4cFlXSnNlVnh1SUNvZ1kzSnZjM010WW5KdmQzTmxjaTVjYmlBcUlFQndZWEpoYlNCN1UzUnlhVzVuZlNCemRISWdVM1J5YVc1bklIUnZJSE53YkdsMExseHVJQ29nUUhCaGNtRnRJSHRTWldkRmVIQjhVM1J5YVc1bmZTQnpaWEJoY21GMGIzSWdVbVZuWlhnZ2IzSWdjM1J5YVc1bklIUnZJSFZ6WlNCbWIzSWdjMlZ3WVhKaGRHbHVaeUIwYUdVZ2MzUnlhVzVuTGx4dUlDb2dRSEJoY21GdElIdE9kVzFpWlhKOUlGdHNhVzFwZEYwZ1RXRjRhVzExYlNCdWRXMWlaWElnYjJZZ2FYUmxiWE1nZEc4Z2FXNWpiSFZrWlNCcGJpQjBhR1VnY21WemRXeDBJR0Z5Y21GNUxseHVJQ29nUUhKbGRIVnlibk1nZTBGeWNtRjVmU0JCY25KaGVTQnZaaUJ6ZFdKemRISnBibWR6TGx4dUlDb2dRR1Y0WVcxd2JHVmNiaUFxWEc0Z0tpQXZMeUJDWVhOcFl5QjFjMlZjYmlBcUlITndiR2wwS0NkaElHSWdZeUJrSnl3Z0p5QW5LVHRjYmlBcUlDOHZJQzArSUZzbllTY3NJQ2RpSnl3Z0oyTW5MQ0FuWkNkZFhHNGdLbHh1SUNvZ0x5OGdWMmwwYUNCc2FXMXBkRnh1SUNvZ2MzQnNhWFFvSjJFZ1lpQmpJR1FuTENBbklDY3NJRElwTzF4dUlDb2dMeThnTFQ0Z1d5ZGhKeXdnSjJJblhWeHVJQ3BjYmlBcUlDOHZJRUpoWTJ0eVpXWmxjbVZ1WTJWeklHbHVJSEpsYzNWc2RDQmhjbkpoZVZ4dUlDb2djM0JzYVhRb0p5NHVkMjl5WkRFZ2QyOXlaREl1TGljc0lDOG9XMkV0ZWwwcktTaGNYR1FyS1M5cEtUdGNiaUFxSUM4dklDMCtJRnNuTGk0bkxDQW5kMjl5WkNjc0lDY3hKeXdnSnlBbkxDQW5kMjl5WkNjc0lDY3lKeXdnSnk0dUoxMWNiaUFxTDF4dWJXOWtkV3hsTG1WNGNHOXlkSE1nUFNBb1puVnVZM1JwYjI0Z2MzQnNhWFFvZFc1a1pXWXBJSHRjYmx4dUlDQjJZWElnYm1GMGFYWmxVM0JzYVhRZ1BTQlRkSEpwYm1jdWNISnZkRzkwZVhCbExuTndiR2wwTEZ4dUlDQWdJR052YlhCc2FXRnVkRVY0WldOT2NHTm5JRDBnTHlncFB6OHZMbVY0WldNb1hDSmNJaWxiTVYwZ1BUMDlJSFZ1WkdWbUxGeHVJQ0FnSUM4dklFNVFRMGM2SUc1dmJuQmhjblJwWTJsd1lYUnBibWNnWTJGd2RIVnlhVzVuSUdkeWIzVndYRzRnSUNBZ2MyVnNaanRjYmx4dUlDQnpaV3htSUQwZ1puVnVZM1JwYjI0b2MzUnlMQ0J6WlhCaGNtRjBiM0lzSUd4cGJXbDBLU0I3WEc0Z0lDQWdMeThnU1dZZ1lITmxjR0Z5WVhSdmNtQWdhWE1nYm05MElHRWdjbVZuWlhnc0lIVnpaU0JnYm1GMGFYWmxVM0JzYVhSZ1hHNGdJQ0FnYVdZZ0tFOWlhbVZqZEM1d2NtOTBiM1I1Y0dVdWRHOVRkSEpwYm1jdVkyRnNiQ2h6WlhCaGNtRjBiM0lwSUNFOVBTQmNJbHR2WW1wbFkzUWdVbVZuUlhod1hWd2lLU0I3WEc0Z0lDQWdJQ0J5WlhSMWNtNGdibUYwYVhabFUzQnNhWFF1WTJGc2JDaHpkSElzSUhObGNHRnlZWFJ2Y2l3Z2JHbHRhWFFwTzF4dUlDQWdJSDFjYmlBZ0lDQjJZWElnYjNWMGNIVjBJRDBnVzEwc1hHNGdJQ0FnSUNCbWJHRm5jeUE5SUNoelpYQmhjbUYwYjNJdWFXZHViM0psUTJGelpTQS9JRndpYVZ3aUlEb2dYQ0pjSWlrZ0t5QW9jMlZ3WVhKaGRHOXlMbTExYkhScGJHbHVaU0EvSUZ3aWJWd2lJRG9nWENKY0lpa2dLeUFvYzJWd1lYSmhkRzl5TG1WNGRHVnVaR1ZrSUQ4Z1hDSjRYQ0lnT2lCY0lsd2lLU0FySUM4dklGQnliM0J2YzJWa0lHWnZjaUJGVXpaY2JpQWdJQ0FnSUNoelpYQmhjbUYwYjNJdWMzUnBZMnQ1SUQ4Z1hDSjVYQ0lnT2lCY0lsd2lLU3hjYmlBZ0lDQWdJQzh2SUVacGNtVm1iM2dnTXl0Y2JpQWdJQ0FnSUd4aGMzUk1ZWE4wU1c1a1pYZ2dQU0F3TEZ4dUlDQWdJQ0FnTHk4Z1RXRnJaU0JnWjJ4dlltRnNZQ0JoYm1RZ1lYWnZhV1FnWUd4aGMzUkpibVJsZUdBZ2FYTnpkV1Z6SUdKNUlIZHZjbXRwYm1jZ2QybDBhQ0JoSUdOdmNIbGNiaUFnSUNBZ0lITmxjR0Z5WVhSdmNpQTlJRzVsZHlCU1pXZEZlSEFvYzJWd1lYSmhkRzl5TG5OdmRYSmpaU3dnWm14aFozTWdLeUJjSW1kY0lpa3NYRzRnSUNBZ0lDQnpaWEJoY21GMGIzSXlMQ0J0WVhSamFDd2diR0Z6ZEVsdVpHVjRMQ0JzWVhOMFRHVnVaM1JvTzF4dUlDQWdJSE4wY2lBclBTQmNJbHdpT3lBdkx5QlVlWEJsTFdOdmJuWmxjblJjYmlBZ0lDQnBaaUFvSVdOdmJYQnNhV0Z1ZEVWNFpXTk9jR05uS1NCN1hHNGdJQ0FnSUNBdkx5QkViMlZ6YmlkMElHNWxaV1FnWm14aFozTWdaM2tzSUdKMWRDQjBhR1Y1SUdSdmJpZDBJR2gxY25SY2JpQWdJQ0FnSUhObGNHRnlZWFJ2Y2pJZ1BTQnVaWGNnVW1WblJYaHdLRndpWGx3aUlDc2djMlZ3WVhKaGRHOXlMbk52ZFhKalpTQXJJRndpSkNnL0lWeGNYRnh6S1Z3aUxDQm1iR0ZuY3lrN1hHNGdJQ0FnZlZ4dUlDQWdJQzhxSUZaaGJIVmxjeUJtYjNJZ1lHeHBiV2wwWUN3Z2NHVnlJSFJvWlNCemNHVmpPbHh1SUNBZ0lDQXFJRWxtSUhWdVpHVm1hVzVsWkRvZ05ESTVORGsyTnpJNU5TQXZMeUJOWVhSb0xuQnZkeWd5TENBek1pa2dMU0F4WEc0Z0lDQWdJQ29nU1dZZ01Dd2dTVzVtYVc1cGRIa3NJRzl5SUU1aFRqb2dNRnh1SUNBZ0lDQXFJRWxtSUhCdmMybDBhWFpsSUc1MWJXSmxjam9nYkdsdGFYUWdQU0JOWVhSb0xtWnNiMjl5S0d4cGJXbDBLVHNnYVdZZ0tHeHBiV2wwSUQ0Z05ESTVORGsyTnpJNU5Ta2diR2x0YVhRZ0xUMGdOREk1TkRrMk56STVOanRjYmlBZ0lDQWdLaUJKWmlCdVpXZGhkR2wyWlNCdWRXMWlaWEk2SURReU9UUTVOamN5T1RZZ0xTQk5ZWFJvTG1ac2IyOXlLRTFoZEdndVlXSnpLR3hwYldsMEtTbGNiaUFnSUNBZ0tpQkpaaUJ2ZEdobGNqb2dWSGx3WlMxamIyNTJaWEowTENCMGFHVnVJSFZ6WlNCMGFHVWdZV0p2ZG1VZ2NuVnNaWE5jYmlBZ0lDQWdLaTljYmlBZ0lDQnNhVzFwZENBOUlHeHBiV2wwSUQwOVBTQjFibVJsWmlBL0lDMHhJRDQrUGlBd0lEb2dMeThnVFdGMGFDNXdiM2NvTWl3Z016SXBJQzBnTVZ4dUlDQWdJR3hwYldsMElENCtQaUF3T3lBdkx5QlViMVZwYm5Rek1paHNhVzFwZENsY2JpQWdJQ0IzYUdsc1pTQW9iV0YwWTJnZ1BTQnpaWEJoY21GMGIzSXVaWGhsWXloemRISXBLU0I3WEc0Z0lDQWdJQ0F2THlCZ2MyVndZWEpoZEc5eUxteGhjM1JKYm1SbGVHQWdhWE1nYm05MElISmxiR2xoWW14bElHTnliM056TFdKeWIzZHpaWEpjYmlBZ0lDQWdJR3hoYzNSSmJtUmxlQ0E5SUcxaGRHTm9MbWx1WkdWNElDc2diV0YwWTJoYk1GMHViR1Z1WjNSb08xeHVJQ0FnSUNBZ2FXWWdLR3hoYzNSSmJtUmxlQ0ErSUd4aGMzUk1ZWE4wU1c1a1pYZ3BJSHRjYmlBZ0lDQWdJQ0FnYjNWMGNIVjBMbkIxYzJnb2MzUnlMbk5zYVdObEtHeGhjM1JNWVhOMFNXNWtaWGdzSUcxaGRHTm9MbWx1WkdWNEtTazdYRzRnSUNBZ0lDQWdJQzh2SUVacGVDQmljbTkzYzJWeWN5QjNhRzl6WlNCZ1pYaGxZMkFnYldWMGFHOWtjeUJrYjI0bmRDQmpiMjV6YVhOMFpXNTBiSGtnY21WMGRYSnVJR0IxYm1SbFptbHVaV1JnSUdadmNseHVJQ0FnSUNBZ0lDQXZMeUJ1YjI1d1lYSjBhV05wY0dGMGFXNW5JR05oY0hSMWNtbHVaeUJuY205MWNITmNiaUFnSUNBZ0lDQWdhV1lnS0NGamIyMXdiR2xoYm5SRmVHVmpUbkJqWnlBbUppQnRZWFJqYUM1c1pXNW5kR2dnUGlBeEtTQjdYRzRnSUNBZ0lDQWdJQ0FnYldGMFkyaGJNRjB1Y21Wd2JHRmpaU2h6WlhCaGNtRjBiM0l5TENCbWRXNWpkR2x2YmlncElIdGNiaUFnSUNBZ0lDQWdJQ0FnSUdadmNpQW9kbUZ5SUdrZ1BTQXhPeUJwSUR3Z1lYSm5kVzFsYm5SekxteGxibWQwYUNBdElESTdJR2tyS3lrZ2UxeHVJQ0FnSUNBZ0lDQWdJQ0FnSUNCcFppQW9ZWEpuZFcxbGJuUnpXMmxkSUQwOVBTQjFibVJsWmlrZ2UxeHVJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lHMWhkR05vVzJsZElEMGdkVzVrWldZN1hHNGdJQ0FnSUNBZ0lDQWdJQ0FnSUgxY2JpQWdJQ0FnSUNBZ0lDQWdJSDFjYmlBZ0lDQWdJQ0FnSUNCOUtUdGNiaUFnSUNBZ0lDQWdmVnh1SUNBZ0lDQWdJQ0JwWmlBb2JXRjBZMmd1YkdWdVozUm9JRDRnTVNBbUppQnRZWFJqYUM1cGJtUmxlQ0E4SUhOMGNpNXNaVzVuZEdncElIdGNiaUFnSUNBZ0lDQWdJQ0JCY25KaGVTNXdjbTkwYjNSNWNHVXVjSFZ6YUM1aGNIQnNlU2h2ZFhSd2RYUXNJRzFoZEdOb0xuTnNhV05sS0RFcEtUdGNiaUFnSUNBZ0lDQWdmVnh1SUNBZ0lDQWdJQ0JzWVhOMFRHVnVaM1JvSUQwZ2JXRjBZMmhiTUYwdWJHVnVaM1JvTzF4dUlDQWdJQ0FnSUNCc1lYTjBUR0Z6ZEVsdVpHVjRJRDBnYkdGemRFbHVaR1Y0TzF4dUlDQWdJQ0FnSUNCcFppQW9iM1YwY0hWMExteGxibWQwYUNBK1BTQnNhVzFwZENrZ2UxeHVJQ0FnSUNBZ0lDQWdJR0p5WldGck8xeHVJQ0FnSUNBZ0lDQjlYRzRnSUNBZ0lDQjlYRzRnSUNBZ0lDQnBaaUFvYzJWd1lYSmhkRzl5TG14aGMzUkpibVJsZUNBOVBUMGdiV0YwWTJndWFXNWtaWGdwSUh0Y2JpQWdJQ0FnSUNBZ2MyVndZWEpoZEc5eUxteGhjM1JKYm1SbGVDc3JPeUF2THlCQmRtOXBaQ0JoYmlCcGJtWnBibWwwWlNCc2IyOXdYRzRnSUNBZ0lDQjlYRzRnSUNBZ2ZWeHVJQ0FnSUdsbUlDaHNZWE4wVEdGemRFbHVaR1Y0SUQwOVBTQnpkSEl1YkdWdVozUm9LU0I3WEc0Z0lDQWdJQ0JwWmlBb2JHRnpkRXhsYm1kMGFDQjhmQ0FoYzJWd1lYSmhkRzl5TG5SbGMzUW9YQ0pjSWlrcElIdGNiaUFnSUNBZ0lDQWdiM1YwY0hWMExuQjFjMmdvWENKY0lpazdYRzRnSUNBZ0lDQjlYRzRnSUNBZ2ZTQmxiSE5sSUh0Y2JpQWdJQ0FnSUc5MWRIQjFkQzV3ZFhOb0tITjBjaTV6YkdsalpTaHNZWE4wVEdGemRFbHVaR1Y0S1NrN1hHNGdJQ0FnZlZ4dUlDQWdJSEpsZEhWeWJpQnZkWFJ3ZFhRdWJHVnVaM1JvSUQ0Z2JHbHRhWFFnUHlCdmRYUndkWFF1YzJ4cFkyVW9NQ3dnYkdsdGFYUXBJRG9nYjNWMGNIVjBPMXh1SUNCOU8xeHVYRzRnSUhKbGRIVnliaUJ6Wld4bU8xeHVmU2tvS1R0Y2JseHVmU3g3ZlYwc05qcGJablZ1WTNScGIyNG9jbVZ4ZFdseVpTeHRiMlIxYkdVc1pYaHdiM0owY3lsN1hHNWNibjBzZTMxZExEYzZXMloxYm1OMGFXOXVLSEpsY1hWcGNtVXNiVzlrZFd4bExHVjRjRzl5ZEhNcGUxeHVKM1Z6WlNCemRISnBZM1FuTzF4dVhHNTJZWElnVDI1bFZtVnljMmx2YmtOdmJuTjBjbUZwYm5RZ1BTQnlaWEYxYVhKbEtDZHBibVJwZG1sa2RXRnNMMjl1WlMxMlpYSnphVzl1SnlrN1hHNWNiblpoY2lCTldWOVdSVkpUU1U5T0lEMGdKemNuTzF4dVQyNWxWbVZ5YzJsdmJrTnZibk4wY21GcGJuUW9KMlYyTFhOMGIzSmxKeXdnVFZsZlZrVlNVMGxQVGlrN1hHNWNiblpoY2lCb1lYTm9TMlY1SUQwZ0oxOWZSVlpmVTFSUFVrVmZTMFZaUUNjZ0t5Qk5XVjlXUlZKVFNVOU9PMXh1WEc1dGIyUjFiR1V1Wlhod2IzSjBjeUE5SUVWMlUzUnZjbVU3WEc1Y2JtWjFibU4wYVc5dUlFVjJVM1J2Y21Vb1pXeGxiU2tnZTF4dUlDQWdJSFpoY2lCb1lYTm9JRDBnWld4bGJWdG9ZWE5vUzJWNVhUdGNibHh1SUNBZ0lHbG1JQ2doYUdGemFDa2dlMXh1SUNBZ0lDQWdJQ0JvWVhOb0lEMGdaV3hsYlZ0b1lYTm9TMlY1WFNBOUlIdDlPMXh1SUNBZ0lIMWNibHh1SUNBZ0lISmxkSFZ5YmlCb1lYTm9PMXh1ZlZ4dVhHNTlMSHRjSW1sdVpHbDJhV1IxWVd3dmIyNWxMWFpsY25OcGIyNWNJam81ZlYwc09EcGJablZ1WTNScGIyNG9jbVZ4ZFdseVpTeHRiMlIxYkdVc1pYaHdiM0owY3lsN1hHNG9ablZ1WTNScGIyNGdLR2RzYjJKaGJDbDdYRzRuZFhObElITjBjbWxqZENjN1hHNWNiaThxWjJ4dlltRnNJSGRwYm1SdmR5d2daMnh2WW1Gc0tpOWNibHh1ZG1GeUlISnZiM1FnUFNCMGVYQmxiMllnZDJsdVpHOTNJQ0U5UFNBbmRXNWtaV1pwYm1Wa0p5QS9YRzRnSUNBZ2QybHVaRzkzSURvZ2RIbHdaVzltSUdkc2IySmhiQ0FoUFQwZ0ozVnVaR1ZtYVc1bFpDY2dQMXh1SUNBZ0lHZHNiMkpoYkNBNklIdDlPMXh1WEc1dGIyUjFiR1V1Wlhod2IzSjBjeUE5SUVsdVpHbDJhV1IxWVd3N1hHNWNibVoxYm1OMGFXOXVJRWx1WkdsMmFXUjFZV3dvYTJWNUxDQjJZV3gxWlNrZ2UxeHVJQ0FnSUdsbUlDaHJaWGtnYVc0Z2NtOXZkQ2tnZTF4dUlDQWdJQ0FnSUNCeVpYUjFjbTRnY205dmRGdHJaWGxkTzF4dUlDQWdJSDFjYmx4dUlDQWdJSEp2YjNSYmEyVjVYU0E5SUhaaGJIVmxPMXh1WEc0Z0lDQWdjbVYwZFhKdUlIWmhiSFZsTzF4dWZWeHVYRzU5S1M1allXeHNLSFJvYVhNc2RIbHdaVzltSUdkc2IySmhiQ0FoUFQwZ1hDSjFibVJsWm1sdVpXUmNJaUEvSUdkc2IySmhiQ0E2SUhSNWNHVnZaaUJ6Wld4bUlDRTlQU0JjSW5WdVpHVm1hVzVsWkZ3aUlEOGdjMlZzWmlBNklIUjVjR1Z2WmlCM2FXNWtiM2NnSVQwOUlGd2lkVzVrWldacGJtVmtYQ0lnUHlCM2FXNWtiM2NnT2lCN2ZTbGNibjBzZTMxZExEazZXMloxYm1OMGFXOXVLSEpsY1hWcGNtVXNiVzlrZFd4bExHVjRjRzl5ZEhNcGUxeHVKM1Z6WlNCemRISnBZM1FuTzF4dVhHNTJZWElnU1c1a2FYWnBaSFZoYkNBOUlISmxjWFZwY21Vb0p5NHZhVzVrWlhndWFuTW5LVHRjYmx4dWJXOWtkV3hsTG1WNGNHOXlkSE1nUFNCUGJtVldaWEp6YVc5dU8xeHVYRzVtZFc1amRHbHZiaUJQYm1WV1pYSnphVzl1S0cxdlpIVnNaVTVoYldVc0lIWmxjbk5wYjI0c0lHUmxabUYxYkhSV1lXeDFaU2tnZTF4dUlDQWdJSFpoY2lCclpYa2dQU0FuWDE5SlRrUkpWa2xFVlVGTVgwOU9SVjlXUlZKVFNVOU9YeWNnS3lCdGIyUjFiR1ZPWVcxbE8xeHVJQ0FnSUhaaGNpQmxibVp2Y21ObFMyVjVJRDBnYTJWNUlDc2dKMTlGVGtaUFVrTkZYMU5KVGtkTVJWUlBUaWM3WEc1Y2JpQWdJQ0IyWVhJZ2RtVnljMmx2YmxaaGJIVmxJRDBnU1c1a2FYWnBaSFZoYkNobGJtWnZjbU5sUzJWNUxDQjJaWEp6YVc5dUtUdGNibHh1SUNBZ0lHbG1JQ2gyWlhKemFXOXVWbUZzZFdVZ0lUMDlJSFpsY25OcGIyNHBJSHRjYmlBZ0lDQWdJQ0FnZEdoeWIzY2dibVYzSUVWeWNtOXlLQ2REWVc0Z2IyNXNlU0JvWVhabElHOXVaU0JqYjNCNUlHOW1JQ2NnSzF4dUlDQWdJQ0FnSUNBZ0lDQWdiVzlrZFd4bFRtRnRaU0FySUNjdVhGeHVKeUFyWEc0Z0lDQWdJQ0FnSUNBZ0lDQW5XVzkxSUdGc2NtVmhaSGtnYUdGMlpTQjJaWEp6YVc5dUlDY2dLeUIyWlhKemFXOXVWbUZzZFdVZ0sxeHVJQ0FnSUNBZ0lDQWdJQ0FnSnlCcGJuTjBZV3hzWldRdVhGeHVKeUFyWEc0Z0lDQWdJQ0FnSUNBZ0lDQW5WR2hwY3lCdFpXRnVjeUI1YjNVZ1kyRnVibTkwSUdsdWMzUmhiR3dnZG1WeWMybHZiaUFuSUNzZ2RtVnljMmx2YmlrN1hHNGdJQ0FnZlZ4dVhHNGdJQ0FnY21WMGRYSnVJRWx1WkdsMmFXUjFZV3dvYTJWNUxDQmtaV1poZFd4MFZtRnNkV1VwTzF4dWZWeHVYRzU5TEh0Y0lpNHZhVzVrWlhndWFuTmNJam80ZlYwc01UQTZXMloxYm1OMGFXOXVLSEpsY1hWcGNtVXNiVzlrZFd4bExHVjRjRzl5ZEhNcGUxeHVLR1oxYm1OMGFXOXVJQ2huYkc5aVlXd3BlMXh1ZG1GeUlIUnZjRXhsZG1Wc0lEMGdkSGx3Wlc5bUlHZHNiMkpoYkNBaFBUMGdKM1Z1WkdWbWFXNWxaQ2NnUHlCbmJHOWlZV3dnT2x4dUlDQWdJSFI1Y0dWdlppQjNhVzVrYjNjZ0lUMDlJQ2QxYm1SbFptbHVaV1FuSUQ4Z2QybHVaRzkzSURvZ2UzMWNiblpoY2lCdGFXNUViMk1nUFNCeVpYRjFhWEpsS0NkdGFXNHRaRzlqZFcxbGJuUW5LVHRjYmx4dWFXWWdLSFI1Y0dWdlppQmtiMk4xYldWdWRDQWhQVDBnSjNWdVpHVm1hVzVsWkNjcElIdGNiaUFnSUNCdGIyUjFiR1V1Wlhod2IzSjBjeUE5SUdSdlkzVnRaVzUwTzF4dWZTQmxiSE5sSUh0Y2JpQWdJQ0IyWVhJZ1pHOWpZM2tnUFNCMGIzQk1aWFpsYkZzblgxOUhURTlDUVV4ZlJFOURWVTFGVGxSZlEwRkRTRVZBTkNkZE8xeHVYRzRnSUNBZ2FXWWdLQ0ZrYjJOamVTa2dlMXh1SUNBZ0lDQWdJQ0JrYjJOamVTQTlJSFJ2Y0V4bGRtVnNXeWRmWDBkTVQwSkJURjlFVDBOVlRVVk9WRjlEUVVOSVJVQTBKMTBnUFNCdGFXNUViMk03WEc0Z0lDQWdmVnh1WEc0Z0lDQWdiVzlrZFd4bExtVjRjRzl5ZEhNZ1BTQmtiMk5qZVR0Y2JuMWNibHh1ZlNrdVkyRnNiQ2gwYUdsekxIUjVjR1Z2WmlCbmJHOWlZV3dnSVQwOUlGd2lkVzVrWldacGJtVmtYQ0lnUHlCbmJHOWlZV3dnT2lCMGVYQmxiMllnYzJWc1ppQWhQVDBnWENKMWJtUmxabWx1WldSY0lpQS9JSE5sYkdZZ09pQjBlWEJsYjJZZ2QybHVaRzkzSUNFOVBTQmNJblZ1WkdWbWFXNWxaRndpSUQ4Z2QybHVaRzkzSURvZ2UzMHBYRzU5TEh0Y0ltMXBiaTFrYjJOMWJXVnVkRndpT2paOVhTd3hNVHBiWm5WdVkzUnBiMjRvY21WeGRXbHlaU3h0YjJSMWJHVXNaWGh3YjNKMGN5bDdYRzVjSW5WelpTQnpkSEpwWTNSY0lqdGNibHh1Ylc5a2RXeGxMbVY0Y0c5eWRITWdQU0JtZFc1amRHbHZiaUJwYzA5aWFtVmpkQ2g0S1NCN1hHNWNkSEpsZEhWeWJpQjBlWEJsYjJZZ2VDQTlQVDBnWENKdlltcGxZM1JjSWlBbUppQjRJQ0U5UFNCdWRXeHNPMXh1ZlR0Y2JseHVmU3g3ZlYwc01USTZXMloxYm1OMGFXOXVLSEpsY1hWcGNtVXNiVzlrZFd4bExHVjRjRzl5ZEhNcGUxeHVkbUZ5SUc1aGRHbDJaVWx6UVhKeVlYa2dQU0JCY25KaGVTNXBjMEZ5Y21GNVhHNTJZWElnZEc5VGRISnBibWNnUFNCUFltcGxZM1F1Y0hKdmRHOTBlWEJsTG5SdlUzUnlhVzVuWEc1Y2JtMXZaSFZzWlM1bGVIQnZjblJ6SUQwZ2JtRjBhWFpsU1hOQmNuSmhlU0I4ZkNCcGMwRnljbUY1WEc1Y2JtWjFibU4wYVc5dUlHbHpRWEp5WVhrb2IySnFLU0I3WEc0Z0lDQWdjbVYwZFhKdUlIUnZVM1J5YVc1bkxtTmhiR3dvYjJKcUtTQTlQVDBnWENKYmIySnFaV04wSUVGeWNtRjVYVndpWEc1OVhHNWNibjBzZTMxZExERXpPbHRtZFc1amRHbHZiaWh5WlhGMWFYSmxMRzF2WkhWc1pTeGxlSEJ2Y25SektYdGNiblpoY2lCd1lYUmphQ0E5SUhKbGNYVnBjbVVvWENJdUwzWmtiMjB2Y0dGMFkyZ3Vhbk5jSWlsY2JseHViVzlrZFd4bExtVjRjRzl5ZEhNZ1BTQndZWFJqYUZ4dVhHNTlMSHRjSWk0dmRtUnZiUzl3WVhSamFDNXFjMXdpT2pFNGZWMHNNVFE2VzJaMWJtTjBhVzl1S0hKbGNYVnBjbVVzYlc5a2RXeGxMR1Y0Y0c5eWRITXBlMXh1ZG1GeUlHbHpUMkpxWldOMElEMGdjbVZ4ZFdseVpTaGNJbWx6TFc5aWFtVmpkRndpS1Z4dWRtRnlJR2x6U0c5dmF5QTlJSEpsY1hWcGNtVW9YQ0l1TGk5MmJtOWtaUzlwY3kxMmFHOXZheTVxYzF3aUtWeHVYRzV0YjJSMWJHVXVaWGh3YjNKMGN5QTlJR0Z3Y0d4NVVISnZjR1Z5ZEdsbGMxeHVYRzVtZFc1amRHbHZiaUJoY0hCc2VWQnliM0JsY25ScFpYTW9ibTlrWlN3Z2NISnZjSE1zSUhCeVpYWnBiM1Z6S1NCN1hHNGdJQ0FnWm05eUlDaDJZWElnY0hKdmNFNWhiV1VnYVc0Z2NISnZjSE1wSUh0Y2JpQWdJQ0FnSUNBZ2RtRnlJSEJ5YjNCV1lXeDFaU0E5SUhCeWIzQnpXM0J5YjNCT1lXMWxYVnh1WEc0Z0lDQWdJQ0FnSUdsbUlDaHdjbTl3Vm1Gc2RXVWdQVDA5SUhWdVpHVm1hVzVsWkNrZ2UxeHVJQ0FnSUNBZ0lDQWdJQ0FnY21WdGIzWmxVSEp2Y0dWeWRIa29ibTlrWlN3Z2NISnZjRTVoYldVc0lIQnliM0JXWVd4MVpTd2djSEpsZG1sdmRYTXBPMXh1SUNBZ0lDQWdJQ0I5SUdWc2MyVWdhV1lnS0dselNHOXZheWh3Y205d1ZtRnNkV1VwS1NCN1hHNGdJQ0FnSUNBZ0lDQWdJQ0J5WlcxdmRtVlFjbTl3WlhKMGVTaHViMlJsTENCd2NtOXdUbUZ0WlN3Z2NISnZjRlpoYkhWbExDQndjbVYyYVc5MWN5bGNiaUFnSUNBZ0lDQWdJQ0FnSUdsbUlDaHdjbTl3Vm1Gc2RXVXVhRzl2YXlrZ2UxeHVJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lIQnliM0JXWVd4MVpTNW9iMjlyS0c1dlpHVXNYRzRnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUhCeWIzQk9ZVzFsTEZ4dUlDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQndjbVYyYVc5MWN5QS9JSEJ5WlhacGIzVnpXM0J5YjNCT1lXMWxYU0E2SUhWdVpHVm1hVzVsWkNsY2JpQWdJQ0FnSUNBZ0lDQWdJSDFjYmlBZ0lDQWdJQ0FnZlNCbGJITmxJSHRjYmlBZ0lDQWdJQ0FnSUNBZ0lHbG1JQ2hwYzA5aWFtVmpkQ2h3Y205d1ZtRnNkV1VwS1NCN1hHNGdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ2NHRjBZMmhQWW1wbFkzUW9ibTlrWlN3Z2NISnZjSE1zSUhCeVpYWnBiM1Z6TENCd2NtOXdUbUZ0WlN3Z2NISnZjRlpoYkhWbEtUdGNiaUFnSUNBZ0lDQWdJQ0FnSUgwZ1pXeHpaU0I3WEc0Z0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnYm05a1pWdHdjbTl3VG1GdFpWMGdQU0J3Y205d1ZtRnNkV1ZjYmlBZ0lDQWdJQ0FnSUNBZ0lIMWNiaUFnSUNBZ0lDQWdmVnh1SUNBZ0lIMWNibjFjYmx4dVpuVnVZM1JwYjI0Z2NtVnRiM1psVUhKdmNHVnlkSGtvYm05a1pTd2djSEp2Y0U1aGJXVXNJSEJ5YjNCV1lXeDFaU3dnY0hKbGRtbHZkWE1wSUh0Y2JpQWdJQ0JwWmlBb2NISmxkbWx2ZFhNcElIdGNiaUFnSUNBZ0lDQWdkbUZ5SUhCeVpYWnBiM1Z6Vm1Gc2RXVWdQU0J3Y21WMmFXOTFjMXR3Y205d1RtRnRaVjFjYmx4dUlDQWdJQ0FnSUNCcFppQW9JV2x6U0c5dmF5aHdjbVYyYVc5MWMxWmhiSFZsS1NrZ2UxeHVJQ0FnSUNBZ0lDQWdJQ0FnYVdZZ0tIQnliM0JPWVcxbElEMDlQU0JjSW1GMGRISnBZblYwWlhOY0lpa2dlMXh1SUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJR1p2Y2lBb2RtRnlJR0YwZEhKT1lXMWxJR2x1SUhCeVpYWnBiM1Z6Vm1Gc2RXVXBJSHRjYmlBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ2JtOWtaUzV5WlcxdmRtVkJkSFJ5YVdKMWRHVW9ZWFIwY2s1aGJXVXBYRzRnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdmVnh1SUNBZ0lDQWdJQ0FnSUNBZ2ZTQmxiSE5sSUdsbUlDaHdjbTl3VG1GdFpTQTlQVDBnWENKemRIbHNaVndpS1NCN1hHNGdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ1ptOXlJQ2gyWVhJZ2FTQnBiaUJ3Y21WMmFXOTFjMVpoYkhWbEtTQjdYRzRnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUc1dlpHVXVjM1I1YkdWYmFWMGdQU0JjSWx3aVhHNGdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ2ZWeHVJQ0FnSUNBZ0lDQWdJQ0FnZlNCbGJITmxJR2xtSUNoMGVYQmxiMllnY0hKbGRtbHZkWE5XWVd4MVpTQTlQVDBnWENKemRISnBibWRjSWlrZ2UxeHVJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lHNXZaR1ZiY0hKdmNFNWhiV1ZkSUQwZ1hDSmNJbHh1SUNBZ0lDQWdJQ0FnSUNBZ2ZTQmxiSE5sSUh0Y2JpQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNCdWIyUmxXM0J5YjNCT1lXMWxYU0E5SUc1MWJHeGNiaUFnSUNBZ0lDQWdJQ0FnSUgxY2JpQWdJQ0FnSUNBZ2ZTQmxiSE5sSUdsbUlDaHdjbVYyYVc5MWMxWmhiSFZsTG5WdWFHOXZheWtnZTF4dUlDQWdJQ0FnSUNBZ0lDQWdjSEpsZG1sdmRYTldZV3gxWlM1MWJtaHZiMnNvYm05a1pTd2djSEp2Y0U1aGJXVXNJSEJ5YjNCV1lXeDFaU2xjYmlBZ0lDQWdJQ0FnZlZ4dUlDQWdJSDFjYm4xY2JseHVablZ1WTNScGIyNGdjR0YwWTJoUFltcGxZM1FvYm05a1pTd2djSEp2Y0hNc0lIQnlaWFpwYjNWekxDQndjbTl3VG1GdFpTd2djSEp2Y0ZaaGJIVmxLU0I3WEc0Z0lDQWdkbUZ5SUhCeVpYWnBiM1Z6Vm1Gc2RXVWdQU0J3Y21WMmFXOTFjeUEvSUhCeVpYWnBiM1Z6VzNCeWIzQk9ZVzFsWFNBNklIVnVaR1ZtYVc1bFpGeHVYRzRnSUNBZ0x5OGdVMlYwSUdGMGRISnBZblYwWlhOY2JpQWdJQ0JwWmlBb2NISnZjRTVoYldVZ1BUMDlJRndpWVhSMGNtbGlkWFJsYzF3aUtTQjdYRzRnSUNBZ0lDQWdJR1p2Y2lBb2RtRnlJR0YwZEhKT1lXMWxJR2x1SUhCeWIzQldZV3gxWlNrZ2UxeHVJQ0FnSUNBZ0lDQWdJQ0FnZG1GeUlHRjBkSEpXWVd4MVpTQTlJSEJ5YjNCV1lXeDFaVnRoZEhSeVRtRnRaVjFjYmx4dUlDQWdJQ0FnSUNBZ0lDQWdhV1lnS0dGMGRISldZV3gxWlNBOVBUMGdkVzVrWldacGJtVmtLU0I3WEc0Z0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnYm05a1pTNXlaVzF2ZG1WQmRIUnlhV0oxZEdVb1lYUjBjazVoYldVcFhHNGdJQ0FnSUNBZ0lDQWdJQ0I5SUdWc2MyVWdlMXh1SUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJRzV2WkdVdWMyVjBRWFIwY21saWRYUmxLR0YwZEhKT1lXMWxMQ0JoZEhSeVZtRnNkV1VwWEc0Z0lDQWdJQ0FnSUNBZ0lDQjlYRzRnSUNBZ0lDQWdJSDFjYmx4dUlDQWdJQ0FnSUNCeVpYUjFjbTVjYmlBZ0lDQjlYRzVjYmlBZ0lDQnBaaWh3Y21WMmFXOTFjMVpoYkhWbElDWW1JR2x6VDJKcVpXTjBLSEJ5WlhacGIzVnpWbUZzZFdVcElDWW1YRzRnSUNBZ0lDQWdJR2RsZEZCeWIzUnZkSGx3WlNod2NtVjJhVzkxYzFaaGJIVmxLU0FoUFQwZ1oyVjBVSEp2ZEc5MGVYQmxLSEJ5YjNCV1lXeDFaU2twSUh0Y2JpQWdJQ0FnSUNBZ2JtOWtaVnR3Y205d1RtRnRaVjBnUFNCd2NtOXdWbUZzZFdWY2JpQWdJQ0FnSUNBZ2NtVjBkWEp1WEc0Z0lDQWdmVnh1WEc0Z0lDQWdhV1lnS0NGcGMwOWlhbVZqZENodWIyUmxXM0J5YjNCT1lXMWxYU2twSUh0Y2JpQWdJQ0FnSUNBZ2JtOWtaVnR3Y205d1RtRnRaVjBnUFNCN2ZWeHVJQ0FnSUgxY2JseHVJQ0FnSUhaaGNpQnlaWEJzWVdObGNpQTlJSEJ5YjNCT1lXMWxJRDA5UFNCY0luTjBlV3hsWENJZ1B5QmNJbHdpSURvZ2RXNWtaV1pwYm1Wa1hHNWNiaUFnSUNCbWIzSWdLSFpoY2lCcklHbHVJSEJ5YjNCV1lXeDFaU2tnZTF4dUlDQWdJQ0FnSUNCMllYSWdkbUZzZFdVZ1BTQndjbTl3Vm1Gc2RXVmJhMTFjYmlBZ0lDQWdJQ0FnYm05a1pWdHdjbTl3VG1GdFpWMWJhMTBnUFNBb2RtRnNkV1VnUFQwOUlIVnVaR1ZtYVc1bFpDa2dQeUJ5WlhCc1lXTmxjaUE2SUhaaGJIVmxYRzRnSUNBZ2ZWeHVmVnh1WEc1bWRXNWpkR2x2YmlCblpYUlFjbTkwYjNSNWNHVW9kbUZzZFdVcElIdGNiaUFnSUNCcFppQW9UMkpxWldOMExtZGxkRkJ5YjNSdmRIbHdaVTltS1NCN1hHNGdJQ0FnSUNBZ0lISmxkSFZ5YmlCUFltcGxZM1F1WjJWMFVISnZkRzkwZVhCbFQyWW9kbUZzZFdVcFhHNGdJQ0FnZlNCbGJITmxJR2xtSUNoMllXeDFaUzVmWDNCeWIzUnZYMThwSUh0Y2JpQWdJQ0FnSUNBZ2NtVjBkWEp1SUhaaGJIVmxMbDlmY0hKdmRHOWZYMXh1SUNBZ0lIMGdaV3h6WlNCcFppQW9kbUZzZFdVdVkyOXVjM1J5ZFdOMGIzSXBJSHRjYmlBZ0lDQWdJQ0FnY21WMGRYSnVJSFpoYkhWbExtTnZibk4wY25WamRHOXlMbkJ5YjNSdmRIbHdaVnh1SUNBZ0lIMWNibjFjYmx4dWZTeDdYQ0l1TGk5MmJtOWtaUzlwY3kxMmFHOXZheTVxYzF3aU9qSTJMRndpYVhNdGIySnFaV04wWENJNk1URjlYU3d4TlRwYlpuVnVZM1JwYjI0b2NtVnhkV2x5WlN4dGIyUjFiR1VzWlhod2IzSjBjeWw3WEc1MllYSWdaRzlqZFcxbGJuUWdQU0J5WlhGMWFYSmxLRndpWjJ4dlltRnNMMlJ2WTNWdFpXNTBYQ0lwWEc1Y2JuWmhjaUJoY0hCc2VWQnliM0JsY25ScFpYTWdQU0J5WlhGMWFYSmxLRndpTGk5aGNIQnNlUzF3Y205d1pYSjBhV1Z6WENJcFhHNWNiblpoY2lCcGMxWk9iMlJsSUQwZ2NtVnhkV2x5WlNoY0lpNHVMM1p1YjJSbEwybHpMWFp1YjJSbExtcHpYQ0lwWEc1MllYSWdhWE5XVkdWNGRDQTlJSEpsY1hWcGNtVW9YQ0l1TGk5MmJtOWtaUzlwY3kxMmRHVjRkQzVxYzF3aUtWeHVkbUZ5SUdselYybGtaMlYwSUQwZ2NtVnhkV2x5WlNoY0lpNHVMM1p1YjJSbEwybHpMWGRwWkdkbGRDNXFjMXdpS1Z4dWRtRnlJR2hoYm1Sc1pWUm9kVzVySUQwZ2NtVnhkV2x5WlNoY0lpNHVMM1p1YjJSbEwyaGhibVJzWlMxMGFIVnVheTVxYzF3aUtWeHVYRzV0YjJSMWJHVXVaWGh3YjNKMGN5QTlJR055WldGMFpVVnNaVzFsYm5SY2JseHVablZ1WTNScGIyNGdZM0psWVhSbFJXeGxiV1Z1ZENoMmJtOWtaU3dnYjNCMGN5a2dlMXh1SUNBZ0lIWmhjaUJrYjJNZ1BTQnZjSFJ6SUQ4Z2IzQjBjeTVrYjJOMWJXVnVkQ0I4ZkNCa2IyTjFiV1Z1ZENBNklHUnZZM1Z0Wlc1MFhHNGdJQ0FnZG1GeUlIZGhjbTRnUFNCdmNIUnpJRDhnYjNCMGN5NTNZWEp1SURvZ2JuVnNiRnh1WEc0Z0lDQWdkbTV2WkdVZ1BTQm9ZVzVrYkdWVWFIVnVheWgyYm05a1pTa3VZVnh1WEc0Z0lDQWdhV1lnS0dselYybGtaMlYwS0hadWIyUmxLU2tnZTF4dUlDQWdJQ0FnSUNCeVpYUjFjbTRnZG01dlpHVXVhVzVwZENncFhHNGdJQ0FnZlNCbGJITmxJR2xtSUNocGMxWlVaWGgwS0hadWIyUmxLU2tnZTF4dUlDQWdJQ0FnSUNCeVpYUjFjbTRnWkc5akxtTnlaV0YwWlZSbGVIUk9iMlJsS0hadWIyUmxMblJsZUhRcFhHNGdJQ0FnZlNCbGJITmxJR2xtSUNnaGFYTldUbTlrWlNoMmJtOWtaU2twSUh0Y2JpQWdJQ0FnSUNBZ2FXWWdLSGRoY200cElIdGNiaUFnSUNBZ0lDQWdJQ0FnSUhkaGNtNG9YQ0pKZEdWdElHbHpJRzV2ZENCaElIWmhiR2xrSUhacGNuUjFZV3dnWkc5dElHNXZaR1ZjSWl3Z2RtNXZaR1VwWEc0Z0lDQWdJQ0FnSUgxY2JpQWdJQ0FnSUNBZ2NtVjBkWEp1SUc1MWJHeGNiaUFnSUNCOVhHNWNiaUFnSUNCMllYSWdibTlrWlNBOUlDaDJibTlrWlM1dVlXMWxjM0JoWTJVZ1BUMDlJRzUxYkd3cElEOWNiaUFnSUNBZ0lDQWdaRzlqTG1OeVpXRjBaVVZzWlcxbGJuUW9kbTV2WkdVdWRHRm5UbUZ0WlNrZ09seHVJQ0FnSUNBZ0lDQmtiMk11WTNKbFlYUmxSV3hsYldWdWRFNVRLSFp1YjJSbExtNWhiV1Z6Y0dGalpTd2dkbTV2WkdVdWRHRm5UbUZ0WlNsY2JseHVJQ0FnSUhaaGNpQndjbTl3Y3lBOUlIWnViMlJsTG5CeWIzQmxjblJwWlhOY2JpQWdJQ0JoY0hCc2VWQnliM0JsY25ScFpYTW9ibTlrWlN3Z2NISnZjSE1wWEc1Y2JpQWdJQ0IyWVhJZ1kyaHBiR1J5Wlc0Z1BTQjJibTlrWlM1amFHbHNaSEpsYmx4dVhHNGdJQ0FnWm05eUlDaDJZWElnYVNBOUlEQTdJR2tnUENCamFHbHNaSEpsYmk1c1pXNW5kR2c3SUdrckt5a2dlMXh1SUNBZ0lDQWdJQ0IyWVhJZ1kyaHBiR1JPYjJSbElEMGdZM0psWVhSbFJXeGxiV1Z1ZENoamFHbHNaSEpsYmx0cFhTd2diM0IwY3lsY2JpQWdJQ0FnSUNBZ2FXWWdLR05vYVd4a1RtOWtaU2tnZTF4dUlDQWdJQ0FnSUNBZ0lDQWdibTlrWlM1aGNIQmxibVJEYUdsc1pDaGphR2xzWkU1dlpHVXBYRzRnSUNBZ0lDQWdJSDFjYmlBZ0lDQjlYRzVjYmlBZ0lDQnlaWFIxY200Z2JtOWtaVnh1ZlZ4dVhHNTlMSHRjSWk0dUwzWnViMlJsTDJoaGJtUnNaUzEwYUhWdWF5NXFjMXdpT2pJMExGd2lMaTR2ZG01dlpHVXZhWE10ZG01dlpHVXVhbk5jSWpveU55eGNJaTR1TDNadWIyUmxMMmx6TFhaMFpYaDBMbXB6WENJNk1qZ3NYQ0l1TGk5MmJtOWtaUzlwY3kxM2FXUm5aWFF1YW5OY0lqb3lPU3hjSWk0dllYQndiSGt0Y0hKdmNHVnlkR2xsYzF3aU9qRTBMRndpWjJ4dlltRnNMMlJ2WTNWdFpXNTBYQ0k2TVRCOVhTd3hOanBiWm5WdVkzUnBiMjRvY21WeGRXbHlaU3h0YjJSMWJHVXNaWGh3YjNKMGN5bDdYRzR2THlCTllYQnpJR0VnZG1seWRIVmhiQ0JFVDAwZ2RISmxaU0J2Ym5SdklHRWdjbVZoYkNCRVQwMGdkSEpsWlNCcGJpQmhiaUJsWm1acFkybGxiblFnYldGdWJtVnlMbHh1THk4Z1YyVWdaRzl1SjNRZ2QyRnVkQ0IwYnlCeVpXRmtJR0ZzYkNCdlppQjBhR1VnUkU5TklHNXZaR1Z6SUdsdUlIUm9aU0IwY21WbElITnZJSGRsSUhWelpWeHVMeThnZEdobElHbHVMVzl5WkdWeUlIUnlaV1VnYVc1a1pYaHBibWNnZEc4Z1pXeHBiV2x1WVhSbElISmxZM1Z5YzJsdmJpQmtiM2R1SUdObGNuUmhhVzRnWW5KaGJtTm9aWE11WEc0dkx5QlhaU0J2Ym14NUlISmxZM1Z5YzJVZ2FXNTBieUJoSUVSUFRTQnViMlJsSUdsbUlIZGxJR3R1YjNjZ2RHaGhkQ0JwZENCamIyNTBZV2x1Y3lCaElHTm9hV3hrSUc5bVhHNHZMeUJwYm5SbGNtVnpkQzVjYmx4dWRtRnlJRzV2UTJocGJHUWdQU0I3ZlZ4dVhHNXRiMlIxYkdVdVpYaHdiM0owY3lBOUlHUnZiVWx1WkdWNFhHNWNibVoxYm1OMGFXOXVJR1J2YlVsdVpHVjRLSEp2YjNST2IyUmxMQ0IwY21WbExDQnBibVJwWTJWekxDQnViMlJsY3lrZ2UxeHVJQ0FnSUdsbUlDZ2hhVzVrYVdObGN5QjhmQ0JwYm1ScFkyVnpMbXhsYm1kMGFDQTlQVDBnTUNrZ2UxeHVJQ0FnSUNBZ0lDQnlaWFIxY200Z2UzMWNiaUFnSUNCOUlHVnNjMlVnZTF4dUlDQWdJQ0FnSUNCcGJtUnBZMlZ6TG5OdmNuUW9ZWE5qWlc1a2FXNW5LVnh1SUNBZ0lDQWdJQ0J5WlhSMWNtNGdjbVZqZFhKelpTaHliMjkwVG05a1pTd2dkSEpsWlN3Z2FXNWthV05sY3l3Z2JtOWtaWE1zSURBcFhHNGdJQ0FnZlZ4dWZWeHVYRzVtZFc1amRHbHZiaUJ5WldOMWNuTmxLSEp2YjNST2IyUmxMQ0IwY21WbExDQnBibVJwWTJWekxDQnViMlJsY3l3Z2NtOXZkRWx1WkdWNEtTQjdYRzRnSUNBZ2JtOWtaWE1nUFNCdWIyUmxjeUI4ZkNCN2ZWeHVYRzVjYmlBZ0lDQnBaaUFvY205dmRFNXZaR1VwSUh0Y2JpQWdJQ0FnSUNBZ2FXWWdLR2x1WkdWNFNXNVNZVzVuWlNocGJtUnBZMlZ6TENCeWIyOTBTVzVrWlhnc0lISnZiM1JKYm1SbGVDa3BJSHRjYmlBZ0lDQWdJQ0FnSUNBZ0lHNXZaR1Z6VzNKdmIzUkpibVJsZUYwZ1BTQnliMjkwVG05a1pWeHVJQ0FnSUNBZ0lDQjlYRzVjYmlBZ0lDQWdJQ0FnZG1GeUlIWkRhR2xzWkhKbGJpQTlJSFJ5WldVdVkyaHBiR1J5Wlc1Y2JseHVJQ0FnSUNBZ0lDQnBaaUFvZGtOb2FXeGtjbVZ1S1NCN1hHNWNiaUFnSUNBZ0lDQWdJQ0FnSUhaaGNpQmphR2xzWkU1dlpHVnpJRDBnY205dmRFNXZaR1V1WTJocGJHUk9iMlJsYzF4dVhHNGdJQ0FnSUNBZ0lDQWdJQ0JtYjNJZ0tIWmhjaUJwSUQwZ01Ec2dhU0E4SUhSeVpXVXVZMmhwYkdSeVpXNHViR1Z1WjNSb095QnBLeXNwSUh0Y2JpQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNCeWIyOTBTVzVrWlhnZ0t6MGdNVnh1WEc0Z0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnZG1GeUlIWkRhR2xzWkNBOUlIWkRhR2xzWkhKbGJsdHBYU0I4ZkNCdWIwTm9hV3hrWEc0Z0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnZG1GeUlHNWxlSFJKYm1SbGVDQTlJSEp2YjNSSmJtUmxlQ0FySUNoMlEyaHBiR1F1WTI5MWJuUWdmSHdnTUNsY2JseHVJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDOHZJSE5yYVhBZ2NtVmpkWEp6YVc5dUlHUnZkMjRnZEdobElIUnlaV1VnYVdZZ2RHaGxjbVVnWVhKbElHNXZJRzV2WkdWeklHUnZkMjRnYUdWeVpWeHVJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lHbG1JQ2hwYm1SbGVFbHVVbUZ1WjJVb2FXNWthV05sY3l3Z2NtOXZkRWx1WkdWNExDQnVaWGgwU1c1a1pYZ3BLU0I3WEc0Z0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lISmxZM1Z5YzJVb1kyaHBiR1JPYjJSbGMxdHBYU3dnZGtOb2FXeGtMQ0JwYm1ScFkyVnpMQ0J1YjJSbGN5d2djbTl2ZEVsdVpHVjRLVnh1SUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJSDFjYmx4dUlDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUhKdmIzUkpibVJsZUNBOUlHNWxlSFJKYm1SbGVGeHVJQ0FnSUNBZ0lDQWdJQ0FnZlZ4dUlDQWdJQ0FnSUNCOVhHNGdJQ0FnZlZ4dVhHNGdJQ0FnY21WMGRYSnVJRzV2WkdWelhHNTlYRzVjYmk4dklFSnBibUZ5ZVNCelpXRnlZMmdnWm05eUlHRnVJR2x1WkdWNElHbHVJSFJvWlNCcGJuUmxjblpoYkNCYmJHVm1kQ3dnY21sbmFIUmRYRzVtZFc1amRHbHZiaUJwYm1SbGVFbHVVbUZ1WjJVb2FXNWthV05sY3l3Z2JHVm1kQ3dnY21sbmFIUXBJSHRjYmlBZ0lDQnBaaUFvYVc1a2FXTmxjeTVzWlc1bmRHZ2dQVDA5SURBcElIdGNiaUFnSUNBZ0lDQWdjbVYwZFhKdUlHWmhiSE5sWEc0Z0lDQWdmVnh1WEc0Z0lDQWdkbUZ5SUcxcGJrbHVaR1Y0SUQwZ01GeHVJQ0FnSUhaaGNpQnRZWGhKYm1SbGVDQTlJR2x1WkdsalpYTXViR1Z1WjNSb0lDMGdNVnh1SUNBZ0lIWmhjaUJqZFhKeVpXNTBTVzVrWlhoY2JpQWdJQ0IyWVhJZ1kzVnljbVZ1ZEVsMFpXMWNibHh1SUNBZ0lIZG9hV3hsSUNodGFXNUpibVJsZUNBOFBTQnRZWGhKYm1SbGVDa2dlMXh1SUNBZ0lDQWdJQ0JqZFhKeVpXNTBTVzVrWlhnZ1BTQW9LRzFoZUVsdVpHVjRJQ3NnYldsdVNXNWtaWGdwSUM4Z01pa2dQajRnTUZ4dUlDQWdJQ0FnSUNCamRYSnlaVzUwU1hSbGJTQTlJR2x1WkdsalpYTmJZM1Z5Y21WdWRFbHVaR1Y0WFZ4dVhHNGdJQ0FnSUNBZ0lHbG1JQ2h0YVc1SmJtUmxlQ0E5UFQwZ2JXRjRTVzVrWlhncElIdGNiaUFnSUNBZ0lDQWdJQ0FnSUhKbGRIVnliaUJqZFhKeVpXNTBTWFJsYlNBK1BTQnNaV1owSUNZbUlHTjFjbkpsYm5SSmRHVnRJRHc5SUhKcFoyaDBYRzRnSUNBZ0lDQWdJSDBnWld4elpTQnBaaUFvWTNWeWNtVnVkRWwwWlcwZ1BDQnNaV1owS1NCN1hHNGdJQ0FnSUNBZ0lDQWdJQ0J0YVc1SmJtUmxlQ0E5SUdOMWNuSmxiblJKYm1SbGVDQXJJREZjYmlBZ0lDQWdJQ0FnZlNCbGJITmxJQ0JwWmlBb1kzVnljbVZ1ZEVsMFpXMGdQaUJ5YVdkb2RDa2dlMXh1SUNBZ0lDQWdJQ0FnSUNBZ2JXRjRTVzVrWlhnZ1BTQmpkWEp5Wlc1MFNXNWtaWGdnTFNBeFhHNGdJQ0FnSUNBZ0lIMGdaV3h6WlNCN1hHNGdJQ0FnSUNBZ0lDQWdJQ0J5WlhSMWNtNGdkSEoxWlZ4dUlDQWdJQ0FnSUNCOVhHNGdJQ0FnZlZ4dVhHNGdJQ0FnY21WMGRYSnVJR1poYkhObE8xeHVmVnh1WEc1bWRXNWpkR2x2YmlCaGMyTmxibVJwYm1jb1lTd2dZaWtnZTF4dUlDQWdJSEpsZEhWeWJpQmhJRDRnWWlBL0lERWdPaUF0TVZ4dWZWeHVYRzU5TEh0OVhTd3hOenBiWm5WdVkzUnBiMjRvY21WeGRXbHlaU3h0YjJSMWJHVXNaWGh3YjNKMGN5bDdYRzUyWVhJZ1lYQndiSGxRY205d1pYSjBhV1Z6SUQwZ2NtVnhkV2x5WlNoY0lpNHZZWEJ3YkhrdGNISnZjR1Z5ZEdsbGMxd2lLVnh1WEc1MllYSWdhWE5YYVdSblpYUWdQU0J5WlhGMWFYSmxLRndpTGk0dmRtNXZaR1V2YVhNdGQybGtaMlYwTG1welhDSXBYRzUyWVhJZ1ZsQmhkR05vSUQwZ2NtVnhkV2x5WlNoY0lpNHVMM1p1YjJSbEwzWndZWFJqYUM1cWMxd2lLVnh1WEc1MllYSWdkWEJrWVhSbFYybGtaMlYwSUQwZ2NtVnhkV2x5WlNoY0lpNHZkWEJrWVhSbExYZHBaR2RsZEZ3aUtWeHVYRzV0YjJSMWJHVXVaWGh3YjNKMGN5QTlJR0Z3Y0d4NVVHRjBZMmhjYmx4dVpuVnVZM1JwYjI0Z1lYQndiSGxRWVhSamFDaDJjR0YwWTJnc0lHUnZiVTV2WkdVc0lISmxibVJsY2s5d2RHbHZibk1wSUh0Y2JpQWdJQ0IyWVhJZ2RIbHdaU0E5SUhad1lYUmphQzUwZVhCbFhHNGdJQ0FnZG1GeUlIWk9iMlJsSUQwZ2RuQmhkR05vTG5aT2IyUmxYRzRnSUNBZ2RtRnlJSEJoZEdOb0lEMGdkbkJoZEdOb0xuQmhkR05vWEc1Y2JpQWdJQ0J6ZDJsMFkyZ2dLSFI1Y0dVcElIdGNiaUFnSUNBZ0lDQWdZMkZ6WlNCV1VHRjBZMmd1VWtWTlQxWkZPbHh1SUNBZ0lDQWdJQ0FnSUNBZ2NtVjBkWEp1SUhKbGJXOTJaVTV2WkdVb1pHOXRUbTlrWlN3Z2RrNXZaR1VwWEc0Z0lDQWdJQ0FnSUdOaGMyVWdWbEJoZEdOb0xrbE9VMFZTVkRwY2JpQWdJQ0FnSUNBZ0lDQWdJSEpsZEhWeWJpQnBibk5sY25ST2IyUmxLR1J2YlU1dlpHVXNJSEJoZEdOb0xDQnlaVzVrWlhKUGNIUnBiMjV6S1Z4dUlDQWdJQ0FnSUNCallYTmxJRlpRWVhSamFDNVdWRVZZVkRwY2JpQWdJQ0FnSUNBZ0lDQWdJSEpsZEhWeWJpQnpkSEpwYm1kUVlYUmphQ2hrYjIxT2IyUmxMQ0IyVG05a1pTd2djR0YwWTJnc0lISmxibVJsY2s5d2RHbHZibk1wWEc0Z0lDQWdJQ0FnSUdOaGMyVWdWbEJoZEdOb0xsZEpSRWRGVkRwY2JpQWdJQ0FnSUNBZ0lDQWdJSEpsZEhWeWJpQjNhV1JuWlhSUVlYUmphQ2hrYjIxT2IyUmxMQ0IyVG05a1pTd2djR0YwWTJnc0lISmxibVJsY2s5d2RHbHZibk1wWEc0Z0lDQWdJQ0FnSUdOaGMyVWdWbEJoZEdOb0xsWk9UMFJGT2x4dUlDQWdJQ0FnSUNBZ0lDQWdjbVYwZFhKdUlIWk9iMlJsVUdGMFkyZ29aRzl0VG05a1pTd2dkazV2WkdVc0lIQmhkR05vTENCeVpXNWtaWEpQY0hScGIyNXpLVnh1SUNBZ0lDQWdJQ0JqWVhObElGWlFZWFJqYUM1UFVrUkZVanBjYmlBZ0lDQWdJQ0FnSUNBZ0lISmxiM0prWlhKRGFHbHNaSEpsYmloa2IyMU9iMlJsTENCd1lYUmphQ2xjYmlBZ0lDQWdJQ0FnSUNBZ0lISmxkSFZ5YmlCa2IyMU9iMlJsWEc0Z0lDQWdJQ0FnSUdOaGMyVWdWbEJoZEdOb0xsQlNUMUJUT2x4dUlDQWdJQ0FnSUNBZ0lDQWdZWEJ3YkhsUWNtOXdaWEowYVdWektHUnZiVTV2WkdVc0lIQmhkR05vTENCMlRtOWtaUzV3Y205d1pYSjBhV1Z6S1Z4dUlDQWdJQ0FnSUNBZ0lDQWdjbVYwZFhKdUlHUnZiVTV2WkdWY2JpQWdJQ0FnSUNBZ1kyRnpaU0JXVUdGMFkyZ3VWRWhWVGtzNlhHNGdJQ0FnSUNBZ0lDQWdJQ0J5WlhSMWNtNGdjbVZ3YkdGalpWSnZiM1FvWkc5dFRtOWtaU3hjYmlBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0J5Wlc1a1pYSlBjSFJwYjI1ekxuQmhkR05vS0dSdmJVNXZaR1VzSUhCaGRHTm9MQ0J5Wlc1a1pYSlBjSFJwYjI1ektTbGNiaUFnSUNBZ0lDQWdaR1ZtWVhWc2REcGNiaUFnSUNBZ0lDQWdJQ0FnSUhKbGRIVnliaUJrYjIxT2IyUmxYRzRnSUNBZ2ZWeHVmVnh1WEc1bWRXNWpkR2x2YmlCeVpXMXZkbVZPYjJSbEtHUnZiVTV2WkdVc0lIWk9iMlJsS1NCN1hHNGdJQ0FnZG1GeUlIQmhjbVZ1ZEU1dlpHVWdQU0JrYjIxT2IyUmxMbkJoY21WdWRFNXZaR1ZjYmx4dUlDQWdJR2xtSUNod1lYSmxiblJPYjJSbEtTQjdYRzRnSUNBZ0lDQWdJSEJoY21WdWRFNXZaR1V1Y21WdGIzWmxRMmhwYkdRb1pHOXRUbTlrWlNsY2JpQWdJQ0I5WEc1Y2JpQWdJQ0JrWlhOMGNtOTVWMmxrWjJWMEtHUnZiVTV2WkdVc0lIWk9iMlJsS1R0Y2JseHVJQ0FnSUhKbGRIVnliaUJ1ZFd4c1hHNTlYRzVjYm1aMWJtTjBhVzl1SUdsdWMyVnlkRTV2WkdVb2NHRnlaVzUwVG05a1pTd2dkazV2WkdVc0lISmxibVJsY2s5d2RHbHZibk1wSUh0Y2JpQWdJQ0IyWVhJZ2JtVjNUbTlrWlNBOUlISmxibVJsY2s5d2RHbHZibk11Y21WdVpHVnlLSFpPYjJSbExDQnlaVzVrWlhKUGNIUnBiMjV6S1Z4dVhHNGdJQ0FnYVdZZ0tIQmhjbVZ1ZEU1dlpHVXBJSHRjYmlBZ0lDQWdJQ0FnY0dGeVpXNTBUbTlrWlM1aGNIQmxibVJEYUdsc1pDaHVaWGRPYjJSbEtWeHVJQ0FnSUgxY2JseHVJQ0FnSUhKbGRIVnliaUJ3WVhKbGJuUk9iMlJsWEc1OVhHNWNibVoxYm1OMGFXOXVJSE4wY21sdVoxQmhkR05vS0dSdmJVNXZaR1VzSUd4bFpuUldUbTlrWlN3Z2RsUmxlSFFzSUhKbGJtUmxjazl3ZEdsdmJuTXBJSHRjYmlBZ0lDQjJZWElnYm1WM1RtOWtaVnh1WEc0Z0lDQWdhV1lnS0dSdmJVNXZaR1V1Ym05a1pWUjVjR1VnUFQwOUlETXBJSHRjYmlBZ0lDQWdJQ0FnWkc5dFRtOWtaUzV5WlhCc1lXTmxSR0YwWVNnd0xDQmtiMjFPYjJSbExteGxibWQwYUN3Z2RsUmxlSFF1ZEdWNGRDbGNiaUFnSUNBZ0lDQWdibVYzVG05a1pTQTlJR1J2YlU1dlpHVmNiaUFnSUNCOUlHVnNjMlVnZTF4dUlDQWdJQ0FnSUNCMllYSWdjR0Z5Wlc1MFRtOWtaU0E5SUdSdmJVNXZaR1V1Y0dGeVpXNTBUbTlrWlZ4dUlDQWdJQ0FnSUNCdVpYZE9iMlJsSUQwZ2NtVnVaR1Z5VDNCMGFXOXVjeTV5Wlc1a1pYSW9kbFJsZUhRc0lISmxibVJsY2s5d2RHbHZibk1wWEc1Y2JpQWdJQ0FnSUNBZ2FXWWdLSEJoY21WdWRFNXZaR1VnSmlZZ2JtVjNUbTlrWlNBaFBUMGdaRzl0VG05a1pTa2dlMXh1SUNBZ0lDQWdJQ0FnSUNBZ2NHRnlaVzUwVG05a1pTNXlaWEJzWVdObFEyaHBiR1FvYm1WM1RtOWtaU3dnWkc5dFRtOWtaU2xjYmlBZ0lDQWdJQ0FnZlZ4dUlDQWdJSDFjYmx4dUlDQWdJSEpsZEhWeWJpQnVaWGRPYjJSbFhHNTlYRzVjYm1aMWJtTjBhVzl1SUhkcFpHZGxkRkJoZEdOb0tHUnZiVTV2WkdVc0lHeGxablJXVG05a1pTd2dkMmxrWjJWMExDQnlaVzVrWlhKUGNIUnBiMjV6S1NCN1hHNGdJQ0FnZG1GeUlIVndaR0YwYVc1bklEMGdkWEJrWVhSbFYybGtaMlYwS0d4bFpuUldUbTlrWlN3Z2QybGtaMlYwS1Z4dUlDQWdJSFpoY2lCdVpYZE9iMlJsWEc1Y2JpQWdJQ0JwWmlBb2RYQmtZWFJwYm1jcElIdGNiaUFnSUNBZ0lDQWdibVYzVG05a1pTQTlJSGRwWkdkbGRDNTFjR1JoZEdVb2JHVm1kRlpPYjJSbExDQmtiMjFPYjJSbEtTQjhmQ0JrYjIxT2IyUmxYRzRnSUNBZ2ZTQmxiSE5sSUh0Y2JpQWdJQ0FnSUNBZ2JtVjNUbTlrWlNBOUlISmxibVJsY2s5d2RHbHZibk11Y21WdVpHVnlLSGRwWkdkbGRDd2djbVZ1WkdWeVQzQjBhVzl1Y3lsY2JpQWdJQ0I5WEc1Y2JpQWdJQ0IyWVhJZ2NHRnlaVzUwVG05a1pTQTlJR1J2YlU1dlpHVXVjR0Z5Wlc1MFRtOWtaVnh1WEc0Z0lDQWdhV1lnS0hCaGNtVnVkRTV2WkdVZ0ppWWdibVYzVG05a1pTQWhQVDBnWkc5dFRtOWtaU2tnZTF4dUlDQWdJQ0FnSUNCd1lYSmxiblJPYjJSbExuSmxjR3hoWTJWRGFHbHNaQ2h1WlhkT2IyUmxMQ0JrYjIxT2IyUmxLVnh1SUNBZ0lIMWNibHh1SUNBZ0lHbG1JQ2doZFhCa1lYUnBibWNwSUh0Y2JpQWdJQ0FnSUNBZ1pHVnpkSEp2ZVZkcFpHZGxkQ2hrYjIxT2IyUmxMQ0JzWldaMFZrNXZaR1VwWEc0Z0lDQWdmVnh1WEc0Z0lDQWdjbVYwZFhKdUlHNWxkMDV2WkdWY2JuMWNibHh1Wm5WdVkzUnBiMjRnZGs1dlpHVlFZWFJqYUNoa2IyMU9iMlJsTENCc1pXWjBWazV2WkdVc0lIWk9iMlJsTENCeVpXNWtaWEpQY0hScGIyNXpLU0I3WEc0Z0lDQWdkbUZ5SUhCaGNtVnVkRTV2WkdVZ1BTQmtiMjFPYjJSbExuQmhjbVZ1ZEU1dlpHVmNiaUFnSUNCMllYSWdibVYzVG05a1pTQTlJSEpsYm1SbGNrOXdkR2x2Ym5NdWNtVnVaR1Z5S0haT2IyUmxMQ0J5Wlc1a1pYSlBjSFJwYjI1ektWeHVYRzRnSUNBZ2FXWWdLSEJoY21WdWRFNXZaR1VnSmlZZ2JtVjNUbTlrWlNBaFBUMGdaRzl0VG05a1pTa2dlMXh1SUNBZ0lDQWdJQ0J3WVhKbGJuUk9iMlJsTG5KbGNHeGhZMlZEYUdsc1pDaHVaWGRPYjJSbExDQmtiMjFPYjJSbEtWeHVJQ0FnSUgxY2JseHVJQ0FnSUhKbGRIVnliaUJ1WlhkT2IyUmxYRzU5WEc1Y2JtWjFibU4wYVc5dUlHUmxjM1J5YjNsWGFXUm5aWFFvWkc5dFRtOWtaU3dnZHlrZ2UxeHVJQ0FnSUdsbUlDaDBlWEJsYjJZZ2R5NWtaWE4wY205NUlEMDlQU0JjSW1aMWJtTjBhVzl1WENJZ0ppWWdhWE5YYVdSblpYUW9keWtwSUh0Y2JpQWdJQ0FnSUNBZ2R5NWtaWE4wY205NUtHUnZiVTV2WkdVcFhHNGdJQ0FnZlZ4dWZWeHVYRzVtZFc1amRHbHZiaUJ5Wlc5eVpHVnlRMmhwYkdSeVpXNG9aRzl0VG05a1pTd2diVzkyWlhNcElIdGNiaUFnSUNCMllYSWdZMmhwYkdST2IyUmxjeUE5SUdSdmJVNXZaR1V1WTJocGJHUk9iMlJsYzF4dUlDQWdJSFpoY2lCclpYbE5ZWEFnUFNCN2ZWeHVJQ0FnSUhaaGNpQnViMlJsWEc0Z0lDQWdkbUZ5SUhKbGJXOTJaVnh1SUNBZ0lIWmhjaUJwYm5ObGNuUmNibHh1SUNBZ0lHWnZjaUFvZG1GeUlHa2dQU0F3T3lCcElEd2diVzkyWlhNdWNtVnRiM1psY3k1c1pXNW5kR2c3SUdrckt5a2dlMXh1SUNBZ0lDQWdJQ0J5WlcxdmRtVWdQU0J0YjNabGN5NXlaVzF2ZG1WelcybGRYRzRnSUNBZ0lDQWdJRzV2WkdVZ1BTQmphR2xzWkU1dlpHVnpXM0psYlc5MlpTNW1jbTl0WFZ4dUlDQWdJQ0FnSUNCcFppQW9jbVZ0YjNabExtdGxlU2tnZTF4dUlDQWdJQ0FnSUNBZ0lDQWdhMlY1VFdGd1czSmxiVzkyWlM1clpYbGRJRDBnYm05a1pWeHVJQ0FnSUNBZ0lDQjlYRzRnSUNBZ0lDQWdJR1J2YlU1dlpHVXVjbVZ0YjNabFEyaHBiR1FvYm05a1pTbGNiaUFnSUNCOVhHNWNiaUFnSUNCMllYSWdiR1Z1WjNSb0lEMGdZMmhwYkdST2IyUmxjeTVzWlc1bmRHaGNiaUFnSUNCbWIzSWdLSFpoY2lCcUlEMGdNRHNnYWlBOElHMXZkbVZ6TG1sdWMyVnlkSE11YkdWdVozUm9PeUJxS3lzcElIdGNiaUFnSUNBZ0lDQWdhVzV6WlhKMElEMGdiVzkyWlhNdWFXNXpaWEowYzF0cVhWeHVJQ0FnSUNBZ0lDQnViMlJsSUQwZ2EyVjVUV0Z3VzJsdWMyVnlkQzVyWlhsZFhHNGdJQ0FnSUNBZ0lDOHZJSFJvYVhNZ2FYTWdkR2hsSUhkbGFYSmtaWE4wSUdKMVp5QnBKM1psSUdWMlpYSWdjMlZsYmlCcGJpQjNaV0pyYVhSY2JpQWdJQ0FnSUNBZ1pHOXRUbTlrWlM1cGJuTmxjblJDWldadmNtVW9ibTlrWlN3Z2FXNXpaWEowTG5SdklENDlJR3hsYm1kMGFDc3JJRDhnYm5Wc2JDQTZJR05vYVd4a1RtOWtaWE5iYVc1elpYSjBMblJ2WFNsY2JpQWdJQ0I5WEc1OVhHNWNibVoxYm1OMGFXOXVJSEpsY0d4aFkyVlNiMjkwS0c5c1pGSnZiM1FzSUc1bGQxSnZiM1FwSUh0Y2JpQWdJQ0JwWmlBb2IyeGtVbTl2ZENBbUppQnVaWGRTYjI5MElDWW1JRzlzWkZKdmIzUWdJVDA5SUc1bGQxSnZiM1FnSmlZZ2IyeGtVbTl2ZEM1d1lYSmxiblJPYjJSbEtTQjdYRzRnSUNBZ0lDQWdJRzlzWkZKdmIzUXVjR0Z5Wlc1MFRtOWtaUzV5WlhCc1lXTmxRMmhwYkdRb2JtVjNVbTl2ZEN3Z2IyeGtVbTl2ZENsY2JpQWdJQ0I5WEc1Y2JpQWdJQ0J5WlhSMWNtNGdibVYzVW05dmREdGNibjFjYmx4dWZTeDdYQ0l1TGk5MmJtOWtaUzlwY3kxM2FXUm5aWFF1YW5OY0lqb3lPU3hjSWk0dUwzWnViMlJsTDNad1lYUmphQzVxYzF3aU9qTXlMRndpTGk5aGNIQnNlUzF3Y205d1pYSjBhV1Z6WENJNk1UUXNYQ0l1TDNWd1pHRjBaUzEzYVdSblpYUmNJam94T1gxZExERTRPbHRtZFc1amRHbHZiaWh5WlhGMWFYSmxMRzF2WkhWc1pTeGxlSEJ2Y25SektYdGNiblpoY2lCa2IyTjFiV1Z1ZENBOUlISmxjWFZwY21Vb1hDSm5iRzlpWVd3dlpHOWpkVzFsYm5SY0lpbGNiblpoY2lCcGMwRnljbUY1SUQwZ2NtVnhkV2x5WlNoY0luZ3RhWE10WVhKeVlYbGNJaWxjYmx4dWRtRnlJSEpsYm1SbGNpQTlJSEpsY1hWcGNtVW9YQ0l1TDJOeVpXRjBaUzFsYkdWdFpXNTBYQ0lwWEc1MllYSWdaRzl0U1c1a1pYZ2dQU0J5WlhGMWFYSmxLRndpTGk5a2IyMHRhVzVrWlhoY0lpbGNiblpoY2lCd1lYUmphRTl3SUQwZ2NtVnhkV2x5WlNoY0lpNHZjR0YwWTJndGIzQmNJaWxjYm0xdlpIVnNaUzVsZUhCdmNuUnpJRDBnY0dGMFkyaGNibHh1Wm5WdVkzUnBiMjRnY0dGMFkyZ29jbTl2ZEU1dlpHVXNJSEJoZEdOb1pYTXNJSEpsYm1SbGNrOXdkR2x2Ym5NcElIdGNiaUFnSUNCeVpXNWtaWEpQY0hScGIyNXpJRDBnY21WdVpHVnlUM0IwYVc5dWN5QjhmQ0I3ZlZ4dUlDQWdJSEpsYm1SbGNrOXdkR2x2Ym5NdWNHRjBZMmdnUFNCeVpXNWtaWEpQY0hScGIyNXpMbkJoZEdOb0lDWW1JSEpsYm1SbGNrOXdkR2x2Ym5NdWNHRjBZMmdnSVQwOUlIQmhkR05vWEc0Z0lDQWdJQ0FnSUQ4Z2NtVnVaR1Z5VDNCMGFXOXVjeTV3WVhSamFGeHVJQ0FnSUNBZ0lDQTZJSEJoZEdOb1VtVmpkWEp6YVhabFhHNGdJQ0FnY21WdVpHVnlUM0IwYVc5dWN5NXlaVzVrWlhJZ1BTQnlaVzVrWlhKUGNIUnBiMjV6TG5KbGJtUmxjaUI4ZkNCeVpXNWtaWEpjYmx4dUlDQWdJSEpsZEhWeWJpQnlaVzVrWlhKUGNIUnBiMjV6TG5CaGRHTm9LSEp2YjNST2IyUmxMQ0J3WVhSamFHVnpMQ0J5Wlc1a1pYSlBjSFJwYjI1ektWeHVmVnh1WEc1bWRXNWpkR2x2YmlCd1lYUmphRkpsWTNWeWMybDJaU2h5YjI5MFRtOWtaU3dnY0dGMFkyaGxjeXdnY21WdVpHVnlUM0IwYVc5dWN5a2dlMXh1SUNBZ0lIWmhjaUJwYm1ScFkyVnpJRDBnY0dGMFkyaEpibVJwWTJWektIQmhkR05vWlhNcFhHNWNiaUFnSUNCcFppQW9hVzVrYVdObGN5NXNaVzVuZEdnZ1BUMDlJREFwSUh0Y2JpQWdJQ0FnSUNBZ2NtVjBkWEp1SUhKdmIzUk9iMlJsWEc0Z0lDQWdmVnh1WEc0Z0lDQWdkbUZ5SUdsdVpHVjRJRDBnWkc5dFNXNWtaWGdvY205dmRFNXZaR1VzSUhCaGRHTm9aWE11WVN3Z2FXNWthV05sY3lsY2JpQWdJQ0IyWVhJZ2IzZHVaWEpFYjJOMWJXVnVkQ0E5SUhKdmIzUk9iMlJsTG05M2JtVnlSRzlqZFcxbGJuUmNibHh1SUNBZ0lHbG1JQ2doY21WdVpHVnlUM0IwYVc5dWN5NWtiMk4xYldWdWRDQW1KaUJ2ZDI1bGNrUnZZM1Z0Wlc1MElDRTlQU0JrYjJOMWJXVnVkQ2tnZTF4dUlDQWdJQ0FnSUNCeVpXNWtaWEpQY0hScGIyNXpMbVJ2WTNWdFpXNTBJRDBnYjNkdVpYSkViMk4xYldWdWRGeHVJQ0FnSUgxY2JseHVJQ0FnSUdadmNpQW9kbUZ5SUdrZ1BTQXdPeUJwSUR3Z2FXNWthV05sY3k1c1pXNW5kR2c3SUdrckt5a2dlMXh1SUNBZ0lDQWdJQ0IyWVhJZ2JtOWtaVWx1WkdWNElEMGdhVzVrYVdObGMxdHBYVnh1SUNBZ0lDQWdJQ0J5YjI5MFRtOWtaU0E5SUdGd2NHeDVVR0YwWTJnb2NtOXZkRTV2WkdVc1hHNGdJQ0FnSUNBZ0lDQWdJQ0JwYm1SbGVGdHViMlJsU1c1a1pYaGRMRnh1SUNBZ0lDQWdJQ0FnSUNBZ2NHRjBZMmhsYzF0dWIyUmxTVzVrWlhoZExGeHVJQ0FnSUNBZ0lDQWdJQ0FnY21WdVpHVnlUM0IwYVc5dWN5bGNiaUFnSUNCOVhHNWNiaUFnSUNCeVpYUjFjbTRnY205dmRFNXZaR1ZjYm4xY2JseHVablZ1WTNScGIyNGdZWEJ3YkhsUVlYUmphQ2h5YjI5MFRtOWtaU3dnWkc5dFRtOWtaU3dnY0dGMFkyaE1hWE4wTENCeVpXNWtaWEpQY0hScGIyNXpLU0I3WEc0Z0lDQWdhV1lnS0NGa2IyMU9iMlJsS1NCN1hHNGdJQ0FnSUNBZ0lISmxkSFZ5YmlCeWIyOTBUbTlrWlZ4dUlDQWdJSDFjYmx4dUlDQWdJSFpoY2lCdVpYZE9iMlJsWEc1Y2JpQWdJQ0JwWmlBb2FYTkJjbkpoZVNod1lYUmphRXhwYzNRcEtTQjdYRzRnSUNBZ0lDQWdJR1p2Y2lBb2RtRnlJR2tnUFNBd095QnBJRHdnY0dGMFkyaE1hWE4wTG14bGJtZDBhRHNnYVNzcktTQjdYRzRnSUNBZ0lDQWdJQ0FnSUNCdVpYZE9iMlJsSUQwZ2NHRjBZMmhQY0Nod1lYUmphRXhwYzNSYmFWMHNJR1J2YlU1dlpHVXNJSEpsYm1SbGNrOXdkR2x2Ym5NcFhHNWNiaUFnSUNBZ0lDQWdJQ0FnSUdsbUlDaGtiMjFPYjJSbElEMDlQU0J5YjI5MFRtOWtaU2tnZTF4dUlDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUhKdmIzUk9iMlJsSUQwZ2JtVjNUbTlrWlZ4dUlDQWdJQ0FnSUNBZ0lDQWdmVnh1SUNBZ0lDQWdJQ0I5WEc0Z0lDQWdmU0JsYkhObElIdGNiaUFnSUNBZ0lDQWdibVYzVG05a1pTQTlJSEJoZEdOb1QzQW9jR0YwWTJoTWFYTjBMQ0JrYjIxT2IyUmxMQ0J5Wlc1a1pYSlBjSFJwYjI1ektWeHVYRzRnSUNBZ0lDQWdJR2xtSUNoa2IyMU9iMlJsSUQwOVBTQnliMjkwVG05a1pTa2dlMXh1SUNBZ0lDQWdJQ0FnSUNBZ2NtOXZkRTV2WkdVZ1BTQnVaWGRPYjJSbFhHNGdJQ0FnSUNBZ0lIMWNiaUFnSUNCOVhHNWNiaUFnSUNCeVpYUjFjbTRnY205dmRFNXZaR1ZjYm4xY2JseHVablZ1WTNScGIyNGdjR0YwWTJoSmJtUnBZMlZ6S0hCaGRHTm9aWE1wSUh0Y2JpQWdJQ0IyWVhJZ2FXNWthV05sY3lBOUlGdGRYRzVjYmlBZ0lDQm1iM0lnS0haaGNpQnJaWGtnYVc0Z2NHRjBZMmhsY3lrZ2UxeHVJQ0FnSUNBZ0lDQnBaaUFvYTJWNUlDRTlQU0JjSW1GY0lpa2dlMXh1SUNBZ0lDQWdJQ0FnSUNBZ2FXNWthV05sY3k1d2RYTm9LRTUxYldKbGNpaHJaWGtwS1Z4dUlDQWdJQ0FnSUNCOVhHNGdJQ0FnZlZ4dVhHNGdJQ0FnY21WMGRYSnVJR2x1WkdsalpYTmNibjFjYmx4dWZTeDdYQ0l1TDJOeVpXRjBaUzFsYkdWdFpXNTBYQ0k2TVRVc1hDSXVMMlJ2YlMxcGJtUmxlRndpT2pFMkxGd2lMaTl3WVhSamFDMXZjRndpT2pFM0xGd2laMnh2WW1Gc0wyUnZZM1Z0Wlc1MFhDSTZNVEFzWENKNExXbHpMV0Z5Y21GNVhDSTZNVEo5WFN3eE9UcGJablZ1WTNScGIyNG9jbVZ4ZFdseVpTeHRiMlIxYkdVc1pYaHdiM0owY3lsN1hHNTJZWElnYVhOWGFXUm5aWFFnUFNCeVpYRjFhWEpsS0Z3aUxpNHZkbTV2WkdVdmFYTXRkMmxrWjJWMExtcHpYQ0lwWEc1Y2JtMXZaSFZzWlM1bGVIQnZjblJ6SUQwZ2RYQmtZWFJsVjJsa1oyVjBYRzVjYm1aMWJtTjBhVzl1SUhWd1pHRjBaVmRwWkdkbGRDaGhMQ0JpS1NCN1hHNGdJQ0FnYVdZZ0tHbHpWMmxrWjJWMEtHRXBJQ1ltSUdselYybGtaMlYwS0dJcEtTQjdYRzRnSUNBZ0lDQWdJR2xtSUNoY0ltNWhiV1ZjSWlCcGJpQmhJQ1ltSUZ3aWJtRnRaVndpSUdsdUlHSXBJSHRjYmlBZ0lDQWdJQ0FnSUNBZ0lISmxkSFZ5YmlCaExtbGtJRDA5UFNCaUxtbGtYRzRnSUNBZ0lDQWdJSDBnWld4elpTQjdYRzRnSUNBZ0lDQWdJQ0FnSUNCeVpYUjFjbTRnWVM1cGJtbDBJRDA5UFNCaUxtbHVhWFJjYmlBZ0lDQWdJQ0FnZlZ4dUlDQWdJSDFjYmx4dUlDQWdJSEpsZEhWeWJpQm1ZV3h6WlZ4dWZWeHVYRzU5TEh0Y0lpNHVMM1p1YjJSbEwybHpMWGRwWkdkbGRDNXFjMXdpT2pJNWZWMHNNakE2VzJaMWJtTjBhVzl1S0hKbGNYVnBjbVVzYlc5a2RXeGxMR1Y0Y0c5eWRITXBlMXh1SjNWelpTQnpkSEpwWTNRbk8xeHVYRzUyWVhJZ1JYWlRkRzl5WlNBOUlISmxjWFZwY21Vb0oyVjJMWE4wYjNKbEp5azdYRzVjYm0xdlpIVnNaUzVsZUhCdmNuUnpJRDBnUlhaSWIyOXJPMXh1WEc1bWRXNWpkR2x2YmlCRmRraHZiMnNvZG1Gc2RXVXBJSHRjYmlBZ0lDQnBaaUFvSVNoMGFHbHpJR2x1YzNSaGJtTmxiMllnUlhaSWIyOXJLU2tnZTF4dUlDQWdJQ0FnSUNCeVpYUjFjbTRnYm1WM0lFVjJTRzl2YXloMllXeDFaU2s3WEc0Z0lDQWdmVnh1WEc0Z0lDQWdkR2hwY3k1MllXeDFaU0E5SUhaaGJIVmxPMXh1ZlZ4dVhHNUZka2h2YjJzdWNISnZkRzkwZVhCbExtaHZiMnNnUFNCbWRXNWpkR2x2YmlBb2JtOWtaU3dnY0hKdmNHVnlkSGxPWVcxbEtTQjdYRzRnSUNBZ2RtRnlJR1Z6SUQwZ1JYWlRkRzl5WlNodWIyUmxLVHRjYmlBZ0lDQjJZWElnY0hKdmNFNWhiV1VnUFNCd2NtOXdaWEowZVU1aGJXVXVjM1ZpYzNSeUtETXBPMXh1WEc0Z0lDQWdaWE5iY0hKdmNFNWhiV1ZkSUQwZ2RHaHBjeTUyWVd4MVpUdGNibjA3WEc1Y2JrVjJTRzl2YXk1d2NtOTBiM1I1Y0dVdWRXNW9iMjlySUQwZ1puVnVZM1JwYjI0b2JtOWtaU3dnY0hKdmNHVnlkSGxPWVcxbEtTQjdYRzRnSUNBZ2RtRnlJR1Z6SUQwZ1JYWlRkRzl5WlNodWIyUmxLVHRjYmlBZ0lDQjJZWElnY0hKdmNFNWhiV1VnUFNCd2NtOXdaWEowZVU1aGJXVXVjM1ZpYzNSeUtETXBPMXh1WEc0Z0lDQWdaWE5iY0hKdmNFNWhiV1ZkSUQwZ2RXNWtaV1pwYm1Wa08xeHVmVHRjYmx4dWZTeDdYQ0psZGkxemRHOXlaVndpT2pkOVhTd3lNVHBiWm5WdVkzUnBiMjRvY21WeGRXbHlaU3h0YjJSMWJHVXNaWGh3YjNKMGN5bDdYRzRuZFhObElITjBjbWxqZENjN1hHNWNibTF2WkhWc1pTNWxlSEJ2Y25SeklEMGdVMjltZEZObGRFaHZiMnM3WEc1Y2JtWjFibU4wYVc5dUlGTnZablJUWlhSSWIyOXJLSFpoYkhWbEtTQjdYRzRnSUNBZ2FXWWdLQ0VvZEdocGN5QnBibk4wWVc1alpXOW1JRk52Wm5SVFpYUkliMjlyS1NrZ2UxeHVJQ0FnSUNBZ0lDQnlaWFIxY200Z2JtVjNJRk52Wm5SVFpYUkliMjlyS0haaGJIVmxLVHRjYmlBZ0lDQjlYRzVjYmlBZ0lDQjBhR2x6TG5aaGJIVmxJRDBnZG1Gc2RXVTdYRzU5WEc1Y2JsTnZablJUWlhSSWIyOXJMbkJ5YjNSdmRIbHdaUzVvYjI5cklEMGdablZ1WTNScGIyNGdLRzV2WkdVc0lIQnliM0JsY25SNVRtRnRaU2tnZTF4dUlDQWdJR2xtSUNodWIyUmxXM0J5YjNCbGNuUjVUbUZ0WlYwZ0lUMDlJSFJvYVhNdWRtRnNkV1VwSUh0Y2JpQWdJQ0FnSUNBZ2JtOWtaVnR3Y205d1pYSjBlVTVoYldWZElEMGdkR2hwY3k1MllXeDFaVHRjYmlBZ0lDQjlYRzU5TzF4dVhHNTlMSHQ5WFN3eU1qcGJablZ1WTNScGIyNG9jbVZ4ZFdseVpTeHRiMlIxYkdVc1pYaHdiM0owY3lsN1hHNG5kWE5sSUhOMGNtbGpkQ2M3WEc1Y2JuWmhjaUJwYzBGeWNtRjVJRDBnY21WeGRXbHlaU2duZUMxcGN5MWhjbkpoZVNjcE8xeHVYRzUyWVhJZ1ZrNXZaR1VnUFNCeVpYRjFhWEpsS0NjdUxpOTJibTlrWlM5MmJtOWtaUzVxY3ljcE8xeHVkbUZ5SUZaVVpYaDBJRDBnY21WeGRXbHlaU2duTGk0dmRtNXZaR1V2ZG5SbGVIUXVhbk1uS1R0Y2JuWmhjaUJwYzFaT2IyUmxJRDBnY21WeGRXbHlaU2duTGk0dmRtNXZaR1V2YVhNdGRtNXZaR1VuS1R0Y2JuWmhjaUJwYzFaVVpYaDBJRDBnY21WeGRXbHlaU2duTGk0dmRtNXZaR1V2YVhNdGRuUmxlSFFuS1R0Y2JuWmhjaUJwYzFkcFpHZGxkQ0E5SUhKbGNYVnBjbVVvSnk0dUwzWnViMlJsTDJsekxYZHBaR2RsZENjcE8xeHVkbUZ5SUdselNHOXZheUE5SUhKbGNYVnBjbVVvSnk0dUwzWnViMlJsTDJsekxYWm9iMjlySnlrN1hHNTJZWElnYVhOV1ZHaDFibXNnUFNCeVpYRjFhWEpsS0NjdUxpOTJibTlrWlM5cGN5MTBhSFZ1YXljcE8xeHVYRzUyWVhJZ2NHRnljMlZVWVdjZ1BTQnlaWEYxYVhKbEtDY3VMM0JoY25ObExYUmhaeTVxY3ljcE8xeHVkbUZ5SUhOdlpuUlRaWFJJYjI5cklEMGdjbVZ4ZFdseVpTZ25MaTlvYjI5cmN5OXpiMlowTFhObGRDMW9iMjlyTG1wekp5azdYRzUyWVhJZ1pYWkliMjlySUQwZ2NtVnhkV2x5WlNnbkxpOW9iMjlyY3k5bGRpMW9iMjlyTG1wekp5azdYRzVjYm0xdlpIVnNaUzVsZUhCdmNuUnpJRDBnYUR0Y2JseHVablZ1WTNScGIyNGdhQ2gwWVdkT1lXMWxMQ0J3Y205d1pYSjBhV1Z6TENCamFHbHNaSEpsYmlrZ2UxeHVJQ0FnSUhaaGNpQmphR2xzWkU1dlpHVnpJRDBnVzEwN1hHNGdJQ0FnZG1GeUlIUmhaeXdnY0hKdmNITXNJR3RsZVN3Z2JtRnRaWE53WVdObE8xeHVYRzRnSUNBZ2FXWWdLQ0ZqYUdsc1pISmxiaUFtSmlCcGMwTm9hV3hrY21WdUtIQnliM0JsY25ScFpYTXBLU0I3WEc0Z0lDQWdJQ0FnSUdOb2FXeGtjbVZ1SUQwZ2NISnZjR1Z5ZEdsbGN6dGNiaUFnSUNBZ0lDQWdjSEp2Y0hNZ1BTQjdmVHRjYmlBZ0lDQjlYRzVjYmlBZ0lDQndjbTl3Y3lBOUlIQnliM0J6SUh4OElIQnliM0JsY25ScFpYTWdmSHdnZTMwN1hHNGdJQ0FnZEdGbklEMGdjR0Z5YzJWVVlXY29kR0ZuVG1GdFpTd2djSEp2Y0hNcE8xeHVYRzRnSUNBZ0x5OGdjM1Z3Y0c5eWRDQnJaWGx6WEc0Z0lDQWdhV1lnS0hCeWIzQnpMbWhoYzA5M2JsQnliM0JsY25SNUtDZHJaWGtuS1NrZ2UxeHVJQ0FnSUNBZ0lDQnJaWGtnUFNCd2NtOXdjeTVyWlhrN1hHNGdJQ0FnSUNBZ0lIQnliM0J6TG10bGVTQTlJSFZ1WkdWbWFXNWxaRHRjYmlBZ0lDQjlYRzVjYmlBZ0lDQXZMeUJ6ZFhCd2IzSjBJRzVoYldWemNHRmpaVnh1SUNBZ0lHbG1JQ2h3Y205d2N5NW9ZWE5QZDI1UWNtOXdaWEowZVNnbmJtRnRaWE53WVdObEp5a3BJSHRjYmlBZ0lDQWdJQ0FnYm1GdFpYTndZV05sSUQwZ2NISnZjSE11Ym1GdFpYTndZV05sTzF4dUlDQWdJQ0FnSUNCd2NtOXdjeTV1WVcxbGMzQmhZMlVnUFNCMWJtUmxabWx1WldRN1hHNGdJQ0FnZlZ4dVhHNGdJQ0FnTHk4Z1ptbDRJR04xY25OdmNpQmlkV2RjYmlBZ0lDQnBaaUFvZEdGbklEMDlQU0FuU1U1UVZWUW5JQ1ltWEc0Z0lDQWdJQ0FnSUNGdVlXMWxjM0JoWTJVZ0ppWmNiaUFnSUNBZ0lDQWdjSEp2Y0hNdWFHRnpUM2R1VUhKdmNHVnlkSGtvSjNaaGJIVmxKeWtnSmlaY2JpQWdJQ0FnSUNBZ2NISnZjSE11ZG1Gc2RXVWdJVDA5SUhWdVpHVm1hVzVsWkNBbUpseHVJQ0FnSUNBZ0lDQWhhWE5JYjI5cktIQnliM0J6TG5aaGJIVmxLVnh1SUNBZ0lDa2dlMXh1SUNBZ0lDQWdJQ0J3Y205d2N5NTJZV3gxWlNBOUlITnZablJUWlhSSWIyOXJLSEJ5YjNCekxuWmhiSFZsS1R0Y2JpQWdJQ0I5WEc1Y2JpQWdJQ0IwY21GdWMyWnZjbTFRY205d1pYSjBhV1Z6S0hCeWIzQnpLVHRjYmx4dUlDQWdJR2xtSUNoamFHbHNaSEpsYmlBaFBUMGdkVzVrWldacGJtVmtJQ1ltSUdOb2FXeGtjbVZ1SUNFOVBTQnVkV3hzS1NCN1hHNGdJQ0FnSUNBZ0lHRmtaRU5vYVd4a0tHTm9hV3hrY21WdUxDQmphR2xzWkU1dlpHVnpMQ0IwWVdjc0lIQnliM0J6S1R0Y2JpQWdJQ0I5WEc1Y2JseHVJQ0FnSUhKbGRIVnliaUJ1WlhjZ1ZrNXZaR1VvZEdGbkxDQndjbTl3Y3l3Z1kyaHBiR1JPYjJSbGN5d2dhMlY1TENCdVlXMWxjM0JoWTJVcE8xeHVmVnh1WEc1bWRXNWpkR2x2YmlCaFpHUkRhR2xzWkNoakxDQmphR2xzWkU1dlpHVnpMQ0IwWVdjc0lIQnliM0J6S1NCN1hHNGdJQ0FnYVdZZ0tIUjVjR1Z2WmlCaklEMDlQU0FuYzNSeWFXNW5KeWtnZTF4dUlDQWdJQ0FnSUNCamFHbHNaRTV2WkdWekxuQjFjMmdvYm1WM0lGWlVaWGgwS0dNcEtUdGNiaUFnSUNCOUlHVnNjMlVnYVdZZ0tIUjVjR1Z2WmlCaklEMDlQU0FuYm5WdFltVnlKeWtnZTF4dUlDQWdJQ0FnSUNCamFHbHNaRTV2WkdWekxuQjFjMmdvYm1WM0lGWlVaWGgwS0ZOMGNtbHVaeWhqS1NrcE8xeHVJQ0FnSUgwZ1pXeHpaU0JwWmlBb2FYTkRhR2xzWkNoaktTa2dlMXh1SUNBZ0lDQWdJQ0JqYUdsc1pFNXZaR1Z6TG5CMWMyZ29ZeWs3WEc0Z0lDQWdmU0JsYkhObElHbG1JQ2hwYzBGeWNtRjVLR01wS1NCN1hHNGdJQ0FnSUNBZ0lHWnZjaUFvZG1GeUlHa2dQU0F3T3lCcElEd2dZeTVzWlc1bmRHZzdJR2tyS3lrZ2UxeHVJQ0FnSUNBZ0lDQWdJQ0FnWVdSa1EyaHBiR1FvWTF0cFhTd2dZMmhwYkdST2IyUmxjeXdnZEdGbkxDQndjbTl3Y3lrN1hHNGdJQ0FnSUNBZ0lIMWNiaUFnSUNCOUlHVnNjMlVnYVdZZ0tHTWdQVDA5SUc1MWJHd2dmSHdnWXlBOVBUMGdkVzVrWldacGJtVmtLU0I3WEc0Z0lDQWdJQ0FnSUhKbGRIVnlianRjYmlBZ0lDQjlJR1ZzYzJVZ2UxeHVJQ0FnSUNBZ0lDQjBhSEp2ZHlCVmJtVjRjR1ZqZEdWa1ZtbHlkSFZoYkVWc1pXMWxiblFvZTF4dUlDQWdJQ0FnSUNBZ0lDQWdabTl5WldsbmJrOWlhbVZqZERvZ1l5eGNiaUFnSUNBZ0lDQWdJQ0FnSUhCaGNtVnVkRlp1YjJSbE9pQjdYRzRnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdkR0ZuVG1GdFpUb2dkR0ZuTEZ4dUlDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUhCeWIzQmxjblJwWlhNNklIQnliM0J6WEc0Z0lDQWdJQ0FnSUNBZ0lDQjlYRzRnSUNBZ0lDQWdJSDBwTzF4dUlDQWdJSDFjYm4xY2JseHVablZ1WTNScGIyNGdkSEpoYm5ObWIzSnRVSEp2Y0dWeWRHbGxjeWh3Y205d2N5a2dlMXh1SUNBZ0lHWnZjaUFvZG1GeUlIQnliM0JPWVcxbElHbHVJSEJ5YjNCektTQjdYRzRnSUNBZ0lDQWdJR2xtSUNod2NtOXdjeTVvWVhOUGQyNVFjbTl3WlhKMGVTaHdjbTl3VG1GdFpTa3BJSHRjYmlBZ0lDQWdJQ0FnSUNBZ0lIWmhjaUIyWVd4MVpTQTlJSEJ5YjNCelczQnliM0JPWVcxbFhUdGNibHh1SUNBZ0lDQWdJQ0FnSUNBZ2FXWWdLR2x6U0c5dmF5aDJZV3gxWlNrcElIdGNiaUFnSUNBZ0lDQWdJQ0FnSUNBZ0lDQmpiMjUwYVc1MVpUdGNiaUFnSUNBZ0lDQWdJQ0FnSUgxY2JseHVJQ0FnSUNBZ0lDQWdJQ0FnYVdZZ0tIQnliM0JPWVcxbExuTjFZbk4wY2lnd0xDQXpLU0E5UFQwZ0oyVjJMU2NwSUh0Y2JpQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBdkx5QmhaR1FnWlhZdFptOXZJSE4xY0hCdmNuUmNiaUFnSUNBZ0lDQWdJQ0FnSUNBZ0lDQndjbTl3YzF0d2NtOXdUbUZ0WlYwZ1BTQmxka2h2YjJzb2RtRnNkV1VwTzF4dUlDQWdJQ0FnSUNBZ0lDQWdmVnh1SUNBZ0lDQWdJQ0I5WEc0Z0lDQWdmVnh1ZlZ4dVhHNW1kVzVqZEdsdmJpQnBjME5vYVd4a0tIZ3BJSHRjYmlBZ0lDQnlaWFIxY200Z2FYTldUbTlrWlNoNEtTQjhmQ0JwYzFaVVpYaDBLSGdwSUh4OElHbHpWMmxrWjJWMEtIZ3BJSHg4SUdselZsUm9kVzVyS0hncE8xeHVmVnh1WEc1bWRXNWpkR2x2YmlCcGMwTm9hV3hrY21WdUtIZ3BJSHRjYmlBZ0lDQnlaWFIxY200Z2RIbHdaVzltSUhnZ1BUMDlJQ2R6ZEhKcGJtY25JSHg4SUdselFYSnlZWGtvZUNrZ2ZId2dhWE5EYUdsc1pDaDRLVHRjYm4xY2JseHVablZ1WTNScGIyNGdWVzVsZUhCbFkzUmxaRlpwY25SMVlXeEZiR1Z0Wlc1MEtHUmhkR0VwSUh0Y2JpQWdJQ0IyWVhJZ1pYSnlJRDBnYm1WM0lFVnljbTl5S0NrN1hHNWNiaUFnSUNCbGNuSXVkSGx3WlNBOUlDZDJhWEowZFdGc0xXaDVjR1Z5YzJOeWFYQjBMblZ1Wlhod1pXTjBaV1F1ZG1seWRIVmhiQzFsYkdWdFpXNTBKenRjYmlBZ0lDQmxjbkl1YldWemMyRm5aU0E5SUNkVmJtVjRjR1ZqZEdWa0lIWnBjblIxWVd3Z1kyaHBiR1FnY0dGemMyVmtJSFJ2SUdnb0tTNWNYRzRuSUN0Y2JpQWdJQ0FnSUNBZ0owVjRjR1ZqZEdWa0lHRWdWazV2WkdVZ0x5QldkR2gxYm1zZ0x5QldWMmxrWjJWMElDOGdjM1J5YVc1bklHSjFkRHBjWEc0bklDdGNiaUFnSUNBZ0lDQWdKMmR2ZERwY1hHNG5JQ3RjYmlBZ0lDQWdJQ0FnWlhKeWIzSlRkSEpwYm1jb1pHRjBZUzVtYjNKbGFXZHVUMkpxWldOMEtTQXJYRzRnSUNBZ0lDQWdJQ2N1WEZ4dUp5QXJYRzRnSUNBZ0lDQWdJQ2RVYUdVZ2NHRnlaVzUwSUhadWIyUmxJR2x6T2x4Y2JpY2dLMXh1SUNBZ0lDQWdJQ0JsY25KdmNsTjBjbWx1Wnloa1lYUmhMbkJoY21WdWRGWnViMlJsS1Z4dUlDQWdJQ0FnSUNBblhGeHVKeUFyWEc0Z0lDQWdJQ0FnSUNkVGRXZG5aWE4wWldRZ1ptbDRPaUJqYUdGdVoyVWdlVzkxY2lCZ2FDZ3VMaTRzSUZzZ0xpNHVJRjBwWUNCallXeHNjMmwwWlM0bk8xeHVJQ0FnSUdWeWNpNW1iM0psYVdkdVQySnFaV04wSUQwZ1pHRjBZUzVtYjNKbGFXZHVUMkpxWldOME8xeHVJQ0FnSUdWeWNpNXdZWEpsYm5SV2JtOWtaU0E5SUdSaGRHRXVjR0Z5Wlc1MFZtNXZaR1U3WEc1Y2JpQWdJQ0J5WlhSMWNtNGdaWEp5TzF4dWZWeHVYRzVtZFc1amRHbHZiaUJsY25KdmNsTjBjbWx1Wnlodlltb3BJSHRjYmlBZ0lDQjBjbmtnZTF4dUlDQWdJQ0FnSUNCeVpYUjFjbTRnU2xOUFRpNXpkSEpwYm1kcFpua29iMkpxTENCdWRXeHNMQ0FuSUNBZ0lDY3BPMXh1SUNBZ0lIMGdZMkYwWTJnZ0tHVXBJSHRjYmlBZ0lDQWdJQ0FnY21WMGRYSnVJRk4wY21sdVp5aHZZbW9wTzF4dUlDQWdJSDFjYm4xY2JseHVmU3g3WENJdUxpOTJibTlrWlM5cGN5MTBhSFZ1YTF3aU9qSTFMRndpTGk0dmRtNXZaR1V2YVhNdGRtaHZiMnRjSWpveU5peGNJaTR1TDNadWIyUmxMMmx6TFhadWIyUmxYQ0k2TWpjc1hDSXVMaTkyYm05a1pTOXBjeTEyZEdWNGRGd2lPakk0TEZ3aUxpNHZkbTV2WkdVdmFYTXRkMmxrWjJWMFhDSTZNamtzWENJdUxpOTJibTlrWlM5MmJtOWtaUzVxYzF3aU9qTXhMRndpTGk0dmRtNXZaR1V2ZG5SbGVIUXVhbk5jSWpvek15eGNJaTR2YUc5dmEzTXZaWFl0YUc5dmF5NXFjMXdpT2pJd0xGd2lMaTlvYjI5cmN5OXpiMlowTFhObGRDMW9iMjlyTG1welhDSTZNakVzWENJdUwzQmhjbk5sTFhSaFp5NXFjMXdpT2pJekxGd2llQzFwY3kxaGNuSmhlVndpT2pFeWZWMHNNak02VzJaMWJtTjBhVzl1S0hKbGNYVnBjbVVzYlc5a2RXeGxMR1Y0Y0c5eWRITXBlMXh1SjNWelpTQnpkSEpwWTNRbk8xeHVYRzUyWVhJZ2MzQnNhWFFnUFNCeVpYRjFhWEpsS0NkaWNtOTNjMlZ5TFhOd2JHbDBKeWs3WEc1Y2JuWmhjaUJqYkdGemMwbGtVM0JzYVhRZ1BTQXZLRnRjWEM0alhUOWJZUzE2UVMxYU1DMDVYRngxTURBM1JpMWNYSFZHUmtaR1h6b3RYU3NwTHp0Y2JuWmhjaUJ1YjNSRGJHRnpjMGxrSUQwZ0wxNWNYQzU4SXk4N1hHNWNibTF2WkhWc1pTNWxlSEJ2Y25SeklEMGdjR0Z5YzJWVVlXYzdYRzVjYm1aMWJtTjBhVzl1SUhCaGNuTmxWR0ZuS0hSaFp5d2djSEp2Y0hNcElIdGNiaUFnSUNCcFppQW9JWFJoWnlrZ2UxeHVJQ0FnSUNBZ0lDQnlaWFIxY200Z0owUkpWaWM3WEc0Z0lDQWdmVnh1WEc0Z0lDQWdkbUZ5SUc1dlNXUWdQU0FoS0hCeWIzQnpMbWhoYzA5M2JsQnliM0JsY25SNUtDZHBaQ2NwS1R0Y2JseHVJQ0FnSUhaaGNpQjBZV2RRWVhKMGN5QTlJSE53YkdsMEtIUmhaeXdnWTJ4aGMzTkpaRk53YkdsMEtUdGNiaUFnSUNCMllYSWdkR0ZuVG1GdFpTQTlJRzUxYkd3N1hHNWNiaUFnSUNCcFppQW9ibTkwUTJ4aGMzTkpaQzUwWlhOMEtIUmhaMUJoY25Seld6RmRLU2tnZTF4dUlDQWdJQ0FnSUNCMFlXZE9ZVzFsSUQwZ0owUkpWaWM3WEc0Z0lDQWdmVnh1WEc0Z0lDQWdkbUZ5SUdOc1lYTnpaWE1zSUhCaGNuUXNJSFI1Y0dVc0lHazdYRzVjYmlBZ0lDQm1iM0lnS0drZ1BTQXdPeUJwSUR3Z2RHRm5VR0Z5ZEhNdWJHVnVaM1JvT3lCcEt5c3BJSHRjYmlBZ0lDQWdJQ0FnY0dGeWRDQTlJSFJoWjFCaGNuUnpXMmxkTzF4dVhHNGdJQ0FnSUNBZ0lHbG1JQ2doY0dGeWRDa2dlMXh1SUNBZ0lDQWdJQ0FnSUNBZ1kyOXVkR2x1ZFdVN1hHNGdJQ0FnSUNBZ0lIMWNibHh1SUNBZ0lDQWdJQ0IwZVhCbElEMGdjR0Z5ZEM1amFHRnlRWFFvTUNrN1hHNWNiaUFnSUNBZ0lDQWdhV1lnS0NGMFlXZE9ZVzFsS1NCN1hHNGdJQ0FnSUNBZ0lDQWdJQ0IwWVdkT1lXMWxJRDBnY0dGeWREdGNiaUFnSUNBZ0lDQWdmU0JsYkhObElHbG1JQ2gwZVhCbElEMDlQU0FuTGljcElIdGNiaUFnSUNBZ0lDQWdJQ0FnSUdOc1lYTnpaWE1nUFNCamJHRnpjMlZ6SUh4OElGdGRPMXh1SUNBZ0lDQWdJQ0FnSUNBZ1kyeGhjM05sY3k1d2RYTm9LSEJoY25RdWMzVmljM1J5YVc1bktERXNJSEJoY25RdWJHVnVaM1JvS1NrN1hHNGdJQ0FnSUNBZ0lIMGdaV3h6WlNCcFppQW9kSGx3WlNBOVBUMGdKeU1uSUNZbUlHNXZTV1FwSUh0Y2JpQWdJQ0FnSUNBZ0lDQWdJSEJ5YjNCekxtbGtJRDBnY0dGeWRDNXpkV0p6ZEhKcGJtY29NU3dnY0dGeWRDNXNaVzVuZEdncE8xeHVJQ0FnSUNBZ0lDQjlYRzRnSUNBZ2ZWeHVYRzRnSUNBZ2FXWWdLR05zWVhOelpYTXBJSHRjYmlBZ0lDQWdJQ0FnYVdZZ0tIQnliM0J6TG1Oc1lYTnpUbUZ0WlNrZ2UxeHVJQ0FnSUNBZ0lDQWdJQ0FnWTJ4aGMzTmxjeTV3ZFhOb0tIQnliM0J6TG1Oc1lYTnpUbUZ0WlNrN1hHNGdJQ0FnSUNBZ0lIMWNibHh1SUNBZ0lDQWdJQ0J3Y205d2N5NWpiR0Z6YzA1aGJXVWdQU0JqYkdGemMyVnpMbXB2YVc0b0p5QW5LVHRjYmlBZ0lDQjlYRzVjYmlBZ0lDQnlaWFIxY200Z2NISnZjSE11Ym1GdFpYTndZV05sSUQ4Z2RHRm5UbUZ0WlNBNklIUmhaMDVoYldVdWRHOVZjSEJsY2tOaGMyVW9LVHRjYm4xY2JseHVmU3g3WENKaWNtOTNjMlZ5TFhOd2JHbDBYQ0k2TlgxZExESTBPbHRtZFc1amRHbHZiaWh5WlhGMWFYSmxMRzF2WkhWc1pTeGxlSEJ2Y25SektYdGNiblpoY2lCcGMxWk9iMlJsSUQwZ2NtVnhkV2x5WlNoY0lpNHZhWE10ZG01dlpHVmNJaWxjYm5aaGNpQnBjMVpVWlhoMElEMGdjbVZ4ZFdseVpTaGNJaTR2YVhNdGRuUmxlSFJjSWlsY2JuWmhjaUJwYzFkcFpHZGxkQ0E5SUhKbGNYVnBjbVVvWENJdUwybHpMWGRwWkdkbGRGd2lLVnh1ZG1GeUlHbHpWR2gxYm1zZ1BTQnlaWEYxYVhKbEtGd2lMaTlwY3kxMGFIVnVhMXdpS1Z4dVhHNXRiMlIxYkdVdVpYaHdiM0owY3lBOUlHaGhibVJzWlZSb2RXNXJYRzVjYm1aMWJtTjBhVzl1SUdoaGJtUnNaVlJvZFc1cktHRXNJR0lwSUh0Y2JpQWdJQ0IyWVhJZ2NtVnVaR1Z5WldSQklEMGdZVnh1SUNBZ0lIWmhjaUJ5Wlc1a1pYSmxaRUlnUFNCaVhHNWNiaUFnSUNCcFppQW9hWE5VYUhWdWF5aGlLU2tnZTF4dUlDQWdJQ0FnSUNCeVpXNWtaWEpsWkVJZ1BTQnlaVzVrWlhKVWFIVnVheWhpTENCaEtWeHVJQ0FnSUgxY2JseHVJQ0FnSUdsbUlDaHBjMVJvZFc1cktHRXBLU0I3WEc0Z0lDQWdJQ0FnSUhKbGJtUmxjbVZrUVNBOUlISmxibVJsY2xSb2RXNXJLR0VzSUc1MWJHd3BYRzRnSUNBZ2ZWeHVYRzRnSUNBZ2NtVjBkWEp1SUh0Y2JpQWdJQ0FnSUNBZ1lUb2djbVZ1WkdWeVpXUkJMRnh1SUNBZ0lDQWdJQ0JpT2lCeVpXNWtaWEpsWkVKY2JpQWdJQ0I5WEc1OVhHNWNibVoxYm1OMGFXOXVJSEpsYm1SbGNsUm9kVzVyS0hSb2RXNXJMQ0J3Y21WMmFXOTFjeWtnZTF4dUlDQWdJSFpoY2lCeVpXNWtaWEpsWkZSb2RXNXJJRDBnZEdoMWJtc3VkbTV2WkdWY2JseHVJQ0FnSUdsbUlDZ2hjbVZ1WkdWeVpXUlVhSFZ1YXlrZ2UxeHVJQ0FnSUNBZ0lDQnlaVzVrWlhKbFpGUm9kVzVySUQwZ2RHaDFibXN1ZG01dlpHVWdQU0IwYUhWdWF5NXlaVzVrWlhJb2NISmxkbWx2ZFhNcFhHNGdJQ0FnZlZ4dVhHNGdJQ0FnYVdZZ0tDRW9hWE5XVG05a1pTaHlaVzVrWlhKbFpGUm9kVzVyS1NCOGZGeHVJQ0FnSUNBZ0lDQWdJQ0FnYVhOV1ZHVjRkQ2h5Wlc1a1pYSmxaRlJvZFc1cktTQjhmRnh1SUNBZ0lDQWdJQ0FnSUNBZ2FYTlhhV1JuWlhRb2NtVnVaR1Z5WldSVWFIVnVheWtwS1NCN1hHNGdJQ0FnSUNBZ0lIUm9jbTkzSUc1bGR5QkZjbkp2Y2loY0luUm9kVzVySUdScFpDQnViM1FnY21WMGRYSnVJR0VnZG1Gc2FXUWdibTlrWlZ3aUtUdGNiaUFnSUNCOVhHNWNiaUFnSUNCeVpYUjFjbTRnY21WdVpHVnlaV1JVYUhWdWExeHVmVnh1WEc1OUxIdGNJaTR2YVhNdGRHaDFibXRjSWpveU5TeGNJaTR2YVhNdGRtNXZaR1ZjSWpveU55eGNJaTR2YVhNdGRuUmxlSFJjSWpveU9DeGNJaTR2YVhNdGQybGtaMlYwWENJNk1qbDlYU3d5TlRwYlpuVnVZM1JwYjI0b2NtVnhkV2x5WlN4dGIyUjFiR1VzWlhod2IzSjBjeWw3WEc1dGIyUjFiR1V1Wlhod2IzSjBjeUE5SUdselZHaDFibXRjYmx4dVpuVnVZM1JwYjI0Z2FYTlVhSFZ1YXloMEtTQjdYRzRnSUNBZ2NtVjBkWEp1SUhRZ0ppWWdkQzUwZVhCbElEMDlQU0JjSWxSb2RXNXJYQ0pjYm4xY2JseHVmU3g3ZlYwc01qWTZXMloxYm1OMGFXOXVLSEpsY1hWcGNtVXNiVzlrZFd4bExHVjRjRzl5ZEhNcGUxeHViVzlrZFd4bExtVjRjRzl5ZEhNZ1BTQnBjMGh2YjJ0Y2JseHVablZ1WTNScGIyNGdhWE5JYjI5cktHaHZiMnNwSUh0Y2JpQWdJQ0J5WlhSMWNtNGdhRzl2YXlBbUpseHVJQ0FnSUNBZ0tIUjVjR1Z2WmlCb2IyOXJMbWh2YjJzZ1BUMDlJRndpWm5WdVkzUnBiMjVjSWlBbUppQWhhRzl2YXk1b1lYTlBkMjVRY205d1pYSjBlU2hjSW1odmIydGNJaWtnZkh4Y2JpQWdJQ0FnSUNCMGVYQmxiMllnYUc5dmF5NTFibWh2YjJzZ1BUMDlJRndpWm5WdVkzUnBiMjVjSWlBbUppQWhhRzl2YXk1b1lYTlBkMjVRY205d1pYSjBlU2hjSW5WdWFHOXZhMXdpS1NsY2JuMWNibHh1ZlN4N2ZWMHNNamM2VzJaMWJtTjBhVzl1S0hKbGNYVnBjbVVzYlc5a2RXeGxMR1Y0Y0c5eWRITXBlMXh1ZG1GeUlIWmxjbk5wYjI0Z1BTQnlaWEYxYVhKbEtGd2lMaTkyWlhKemFXOXVYQ0lwWEc1Y2JtMXZaSFZzWlM1bGVIQnZjblJ6SUQwZ2FYTldhWEowZFdGc1RtOWtaVnh1WEc1bWRXNWpkR2x2YmlCcGMxWnBjblIxWVd4T2IyUmxLSGdwSUh0Y2JpQWdJQ0J5WlhSMWNtNGdlQ0FtSmlCNExuUjVjR1VnUFQwOUlGd2lWbWx5ZEhWaGJFNXZaR1ZjSWlBbUppQjRMblpsY25OcGIyNGdQVDA5SUhabGNuTnBiMjVjYm4xY2JseHVmU3g3WENJdUwzWmxjbk5wYjI1Y0lqb3pNSDFkTERJNE9sdG1kVzVqZEdsdmJpaHlaWEYxYVhKbExHMXZaSFZzWlN4bGVIQnZjblJ6S1h0Y2JuWmhjaUIyWlhKemFXOXVJRDBnY21WeGRXbHlaU2hjSWk0dmRtVnljMmx2Ymx3aUtWeHVYRzV0YjJSMWJHVXVaWGh3YjNKMGN5QTlJR2x6Vm1seWRIVmhiRlJsZUhSY2JseHVablZ1WTNScGIyNGdhWE5XYVhKMGRXRnNWR1Y0ZENoNEtTQjdYRzRnSUNBZ2NtVjBkWEp1SUhnZ0ppWWdlQzUwZVhCbElEMDlQU0JjSWxacGNuUjFZV3hVWlhoMFhDSWdKaVlnZUM1MlpYSnphVzl1SUQwOVBTQjJaWEp6YVc5dVhHNTlYRzVjYm4wc2Uxd2lMaTkyWlhKemFXOXVYQ0k2TXpCOVhTd3lPVHBiWm5WdVkzUnBiMjRvY21WeGRXbHlaU3h0YjJSMWJHVXNaWGh3YjNKMGN5bDdYRzV0YjJSMWJHVXVaWGh3YjNKMGN5QTlJR2x6VjJsa1oyVjBYRzVjYm1aMWJtTjBhVzl1SUdselYybGtaMlYwS0hjcElIdGNiaUFnSUNCeVpYUjFjbTRnZHlBbUppQjNMblI1Y0dVZ1BUMDlJRndpVjJsa1oyVjBYQ0pjYm4xY2JseHVmU3g3ZlYwc016QTZXMloxYm1OMGFXOXVLSEpsY1hWcGNtVXNiVzlrZFd4bExHVjRjRzl5ZEhNcGUxeHViVzlrZFd4bExtVjRjRzl5ZEhNZ1BTQmNJakpjSWx4dVhHNTlMSHQ5WFN3ek1UcGJablZ1WTNScGIyNG9jbVZ4ZFdseVpTeHRiMlIxYkdVc1pYaHdiM0owY3lsN1hHNTJZWElnZG1WeWMybHZiaUE5SUhKbGNYVnBjbVVvWENJdUwzWmxjbk5wYjI1Y0lpbGNiblpoY2lCcGMxWk9iMlJsSUQwZ2NtVnhkV2x5WlNoY0lpNHZhWE10ZG01dlpHVmNJaWxjYm5aaGNpQnBjMWRwWkdkbGRDQTlJSEpsY1hWcGNtVW9YQ0l1TDJsekxYZHBaR2RsZEZ3aUtWeHVkbUZ5SUdselZHaDFibXNnUFNCeVpYRjFhWEpsS0Z3aUxpOXBjeTEwYUhWdWExd2lLVnh1ZG1GeUlHbHpWa2h2YjJzZ1BTQnlaWEYxYVhKbEtGd2lMaTlwY3kxMmFHOXZhMXdpS1Z4dVhHNXRiMlIxYkdVdVpYaHdiM0owY3lBOUlGWnBjblIxWVd4T2IyUmxYRzVjYm5aaGNpQnViMUJ5YjNCbGNuUnBaWE1nUFNCN2ZWeHVkbUZ5SUc1dlEyaHBiR1J5Wlc0Z1BTQmJYVnh1WEc1bWRXNWpkR2x2YmlCV2FYSjBkV0ZzVG05a1pTaDBZV2RPWVcxbExDQndjbTl3WlhKMGFXVnpMQ0JqYUdsc1pISmxiaXdnYTJWNUxDQnVZVzFsYzNCaFkyVXBJSHRjYmlBZ0lDQjBhR2x6TG5SaFowNWhiV1VnUFNCMFlXZE9ZVzFsWEc0Z0lDQWdkR2hwY3k1d2NtOXdaWEowYVdWeklEMGdjSEp2Y0dWeWRHbGxjeUI4ZkNCdWIxQnliM0JsY25ScFpYTmNiaUFnSUNCMGFHbHpMbU5vYVd4a2NtVnVJRDBnWTJocGJHUnlaVzRnZkh3Z2JtOURhR2xzWkhKbGJseHVJQ0FnSUhSb2FYTXVhMlY1SUQwZ2EyVjVJQ0U5SUc1MWJHd2dQeUJUZEhKcGJtY29hMlY1S1NBNklIVnVaR1ZtYVc1bFpGeHVJQ0FnSUhSb2FYTXVibUZ0WlhOd1lXTmxJRDBnS0hSNWNHVnZaaUJ1WVcxbGMzQmhZMlVnUFQwOUlGd2ljM1J5YVc1blhDSXBJRDhnYm1GdFpYTndZV05sSURvZ2JuVnNiRnh1WEc0Z0lDQWdkbUZ5SUdOdmRXNTBJRDBnS0dOb2FXeGtjbVZ1SUNZbUlHTm9hV3hrY21WdUxteGxibWQwYUNrZ2ZId2dNRnh1SUNBZ0lIWmhjaUJrWlhOalpXNWtZVzUwY3lBOUlEQmNiaUFnSUNCMllYSWdhR0Z6VjJsa1oyVjBjeUE5SUdaaGJITmxYRzRnSUNBZ2RtRnlJR2hoYzFSb2RXNXJjeUE5SUdaaGJITmxYRzRnSUNBZ2RtRnlJR1JsYzJObGJtUmhiblJJYjI5cmN5QTlJR1poYkhObFhHNGdJQ0FnZG1GeUlHaHZiMnR6WEc1Y2JpQWdJQ0JtYjNJZ0tIWmhjaUJ3Y205d1RtRnRaU0JwYmlCd2NtOXdaWEowYVdWektTQjdYRzRnSUNBZ0lDQWdJR2xtSUNod2NtOXdaWEowYVdWekxtaGhjMDkzYmxCeWIzQmxjblI1S0hCeWIzQk9ZVzFsS1NrZ2UxeHVJQ0FnSUNBZ0lDQWdJQ0FnZG1GeUlIQnliM0JsY25SNUlEMGdjSEp2Y0dWeWRHbGxjMXR3Y205d1RtRnRaVjFjYmlBZ0lDQWdJQ0FnSUNBZ0lHbG1JQ2hwYzFaSWIyOXJLSEJ5YjNCbGNuUjVLU0FtSmlCd2NtOXdaWEowZVM1MWJtaHZiMnNwSUh0Y2JpQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNCcFppQW9JV2h2YjJ0ektTQjdYRzRnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUdodmIydHpJRDBnZTMxY2JpQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNCOVhHNWNiaUFnSUNBZ0lDQWdJQ0FnSUNBZ0lDQm9iMjlyYzF0d2NtOXdUbUZ0WlYwZ1BTQndjbTl3WlhKMGVWeHVJQ0FnSUNBZ0lDQWdJQ0FnZlZ4dUlDQWdJQ0FnSUNCOVhHNGdJQ0FnZlZ4dVhHNGdJQ0FnWm05eUlDaDJZWElnYVNBOUlEQTdJR2tnUENCamIzVnVkRHNnYVNzcktTQjdYRzRnSUNBZ0lDQWdJSFpoY2lCamFHbHNaQ0E5SUdOb2FXeGtjbVZ1VzJsZFhHNGdJQ0FnSUNBZ0lHbG1JQ2hwYzFaT2IyUmxLR05vYVd4a0tTa2dlMXh1SUNBZ0lDQWdJQ0FnSUNBZ1pHVnpZMlZ1WkdGdWRITWdLejBnWTJocGJHUXVZMjkxYm5RZ2ZId2dNRnh1WEc0Z0lDQWdJQ0FnSUNBZ0lDQnBaaUFvSVdoaGMxZHBaR2RsZEhNZ0ppWWdZMmhwYkdRdWFHRnpWMmxrWjJWMGN5a2dlMXh1SUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJR2hoYzFkcFpHZGxkSE1nUFNCMGNuVmxYRzRnSUNBZ0lDQWdJQ0FnSUNCOVhHNWNiaUFnSUNBZ0lDQWdJQ0FnSUdsbUlDZ2hhR0Z6VkdoMWJtdHpJQ1ltSUdOb2FXeGtMbWhoYzFSb2RXNXJjeWtnZTF4dUlDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUdoaGMxUm9kVzVyY3lBOUlIUnlkV1ZjYmlBZ0lDQWdJQ0FnSUNBZ0lIMWNibHh1SUNBZ0lDQWdJQ0FnSUNBZ2FXWWdLQ0ZrWlhOalpXNWtZVzUwU0c5dmEzTWdKaVlnS0dOb2FXeGtMbWh2YjJ0eklIeDhJR05vYVd4a0xtUmxjMk5sYm1SaGJuUkliMjlyY3lrcElIdGNiaUFnSUNBZ0lDQWdJQ0FnSUNBZ0lDQmtaWE5qWlc1a1lXNTBTRzl2YTNNZ1BTQjBjblZsWEc0Z0lDQWdJQ0FnSUNBZ0lDQjlYRzRnSUNBZ0lDQWdJSDBnWld4elpTQnBaaUFvSVdoaGMxZHBaR2RsZEhNZ0ppWWdhWE5YYVdSblpYUW9ZMmhwYkdRcEtTQjdYRzRnSUNBZ0lDQWdJQ0FnSUNCcFppQW9kSGx3Wlc5bUlHTm9hV3hrTG1SbGMzUnliM2tnUFQwOUlGd2lablZ1WTNScGIyNWNJaWtnZTF4dUlDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUdoaGMxZHBaR2RsZEhNZ1BTQjBjblZsWEc0Z0lDQWdJQ0FnSUNBZ0lDQjlYRzRnSUNBZ0lDQWdJSDBnWld4elpTQnBaaUFvSVdoaGMxUm9kVzVyY3lBbUppQnBjMVJvZFc1cktHTm9hV3hrS1NrZ2UxeHVJQ0FnSUNBZ0lDQWdJQ0FnYUdGelZHaDFibXR6SUQwZ2RISjFaVHRjYmlBZ0lDQWdJQ0FnZlZ4dUlDQWdJSDFjYmx4dUlDQWdJSFJvYVhNdVkyOTFiblFnUFNCamIzVnVkQ0FySUdSbGMyTmxibVJoYm5SelhHNGdJQ0FnZEdocGN5NW9ZWE5YYVdSblpYUnpJRDBnYUdGelYybGtaMlYwYzF4dUlDQWdJSFJvYVhNdWFHRnpWR2gxYm10eklEMGdhR0Z6VkdoMWJtdHpYRzRnSUNBZ2RHaHBjeTVvYjI5cmN5QTlJR2h2YjJ0elhHNGdJQ0FnZEdocGN5NWtaWE5qWlc1a1lXNTBTRzl2YTNNZ1BTQmtaWE5qWlc1a1lXNTBTRzl2YTNOY2JuMWNibHh1Vm1seWRIVmhiRTV2WkdVdWNISnZkRzkwZVhCbExuWmxjbk5wYjI0Z1BTQjJaWEp6YVc5dVhHNVdhWEowZFdGc1RtOWtaUzV3Y205MGIzUjVjR1V1ZEhsd1pTQTlJRndpVm1seWRIVmhiRTV2WkdWY0lseHVYRzU5TEh0Y0lpNHZhWE10ZEdoMWJtdGNJam95TlN4Y0lpNHZhWE10ZG1odmIydGNJam95Tml4Y0lpNHZhWE10ZG01dlpHVmNJam95Tnl4Y0lpNHZhWE10ZDJsa1oyVjBYQ0k2TWprc1hDSXVMM1psY25OcGIyNWNJam96TUgxZExETXlPbHRtZFc1amRHbHZiaWh5WlhGMWFYSmxMRzF2WkhWc1pTeGxlSEJ2Y25SektYdGNiblpoY2lCMlpYSnphVzl1SUQwZ2NtVnhkV2x5WlNoY0lpNHZkbVZ5YzJsdmJsd2lLVnh1WEc1V2FYSjBkV0ZzVUdGMFkyZ3VUazlPUlNBOUlEQmNibFpwY25SMVlXeFFZWFJqYUM1V1ZFVllWQ0E5SURGY2JsWnBjblIxWVd4UVlYUmphQzVXVGs5RVJTQTlJREpjYmxacGNuUjFZV3hRWVhSamFDNVhTVVJIUlZRZ1BTQXpYRzVXYVhKMGRXRnNVR0YwWTJndVVGSlBVRk1nUFNBMFhHNVdhWEowZFdGc1VHRjBZMmd1VDFKRVJWSWdQU0ExWEc1V2FYSjBkV0ZzVUdGMFkyZ3VTVTVUUlZKVUlEMGdObHh1Vm1seWRIVmhiRkJoZEdOb0xsSkZUVTlXUlNBOUlEZGNibFpwY25SMVlXeFFZWFJqYUM1VVNGVk9TeUE5SURoY2JseHViVzlrZFd4bExtVjRjRzl5ZEhNZ1BTQldhWEowZFdGc1VHRjBZMmhjYmx4dVpuVnVZM1JwYjI0Z1ZtbHlkSFZoYkZCaGRHTm9LSFI1Y0dVc0lIWk9iMlJsTENCd1lYUmphQ2tnZTF4dUlDQWdJSFJvYVhNdWRIbHdaU0E5SUU1MWJXSmxjaWgwZVhCbEtWeHVJQ0FnSUhSb2FYTXVkazV2WkdVZ1BTQjJUbTlrWlZ4dUlDQWdJSFJvYVhNdWNHRjBZMmdnUFNCd1lYUmphRnh1ZlZ4dVhHNVdhWEowZFdGc1VHRjBZMmd1Y0hKdmRHOTBlWEJsTG5abGNuTnBiMjRnUFNCMlpYSnphVzl1WEc1V2FYSjBkV0ZzVUdGMFkyZ3VjSEp2ZEc5MGVYQmxMblI1Y0dVZ1BTQmNJbFpwY25SMVlXeFFZWFJqYUZ3aVhHNWNibjBzZTF3aUxpOTJaWEp6YVc5dVhDSTZNekI5WFN3ek16cGJablZ1WTNScGIyNG9jbVZ4ZFdseVpTeHRiMlIxYkdVc1pYaHdiM0owY3lsN1hHNTJZWElnZG1WeWMybHZiaUE5SUhKbGNYVnBjbVVvWENJdUwzWmxjbk5wYjI1Y0lpbGNibHh1Ylc5a2RXeGxMbVY0Y0c5eWRITWdQU0JXYVhKMGRXRnNWR1Y0ZEZ4dVhHNW1kVzVqZEdsdmJpQldhWEowZFdGc1ZHVjRkQ2gwWlhoMEtTQjdYRzRnSUNBZ2RHaHBjeTUwWlhoMElEMGdVM1J5YVc1bktIUmxlSFFwWEc1OVhHNWNibFpwY25SMVlXeFVaWGgwTG5CeWIzUnZkSGx3WlM1MlpYSnphVzl1SUQwZ2RtVnljMmx2Ymx4dVZtbHlkSFZoYkZSbGVIUXVjSEp2ZEc5MGVYQmxMblI1Y0dVZ1BTQmNJbFpwY25SMVlXeFVaWGgwWENKY2JseHVmU3g3WENJdUwzWmxjbk5wYjI1Y0lqb3pNSDFkTERNME9sdG1kVzVqZEdsdmJpaHlaWEYxYVhKbExHMXZaSFZzWlN4bGVIQnZjblJ6S1h0Y2JuWmhjaUJwYzA5aWFtVmpkQ0E5SUhKbGNYVnBjbVVvWENKcGN5MXZZbXBsWTNSY0lpbGNiblpoY2lCcGMwaHZiMnNnUFNCeVpYRjFhWEpsS0Z3aUxpNHZkbTV2WkdVdmFYTXRkbWh2YjJ0Y0lpbGNibHh1Ylc5a2RXeGxMbVY0Y0c5eWRITWdQU0JrYVdabVVISnZjSE5jYmx4dVpuVnVZM1JwYjI0Z1pHbG1abEJ5YjNCektHRXNJR0lwSUh0Y2JpQWdJQ0IyWVhJZ1pHbG1abHh1WEc0Z0lDQWdabTl5SUNoMllYSWdZVXRsZVNCcGJpQmhLU0I3WEc0Z0lDQWdJQ0FnSUdsbUlDZ2hLR0ZMWlhrZ2FXNGdZaWtwSUh0Y2JpQWdJQ0FnSUNBZ0lDQWdJR1JwWm1ZZ1BTQmthV1ptSUh4OElIdDlYRzRnSUNBZ0lDQWdJQ0FnSUNCa2FXWm1XMkZMWlhsZElEMGdkVzVrWldacGJtVmtYRzRnSUNBZ0lDQWdJSDFjYmx4dUlDQWdJQ0FnSUNCMllYSWdZVlpoYkhWbElEMGdZVnRoUzJWNVhWeHVJQ0FnSUNBZ0lDQjJZWElnWWxaaGJIVmxJRDBnWWx0aFMyVjVYVnh1WEc0Z0lDQWdJQ0FnSUdsbUlDaGhWbUZzZFdVZ1BUMDlJR0pXWVd4MVpTa2dlMXh1SUNBZ0lDQWdJQ0FnSUNBZ1kyOXVkR2x1ZFdWY2JpQWdJQ0FnSUNBZ2ZTQmxiSE5sSUdsbUlDaHBjMDlpYW1WamRDaGhWbUZzZFdVcElDWW1JR2x6VDJKcVpXTjBLR0pXWVd4MVpTa3BJSHRjYmlBZ0lDQWdJQ0FnSUNBZ0lHbG1JQ2huWlhSUWNtOTBiM1I1Y0dVb1lsWmhiSFZsS1NBaFBUMGdaMlYwVUhKdmRHOTBlWEJsS0dGV1lXeDFaU2twSUh0Y2JpQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNCa2FXWm1JRDBnWkdsbVppQjhmQ0I3ZlZ4dUlDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUdScFptWmJZVXRsZVYwZ1BTQmlWbUZzZFdWY2JpQWdJQ0FnSUNBZ0lDQWdJSDBnWld4elpTQnBaaUFvYVhOSWIyOXJLR0pXWVd4MVpTa3BJSHRjYmlBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnWkdsbVppQTlJR1JwWm1ZZ2ZId2dlMzFjYmlBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnWkdsbVpsdGhTMlY1WFNBOUlHSldZV3gxWlZ4dUlDQWdJQ0FnSUNBZ0lDQWdmU0JsYkhObElIdGNiaUFnSUNBZ0lDQWdJQ0FnSUNBZ0lDQjJZWElnYjJKcVpXTjBSR2xtWmlBOUlHUnBabVpRY205d2N5aGhWbUZzZFdVc0lHSldZV3gxWlNsY2JpQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNCcFppQW9iMkpxWldOMFJHbG1aaWtnZTF4dUlDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQmthV1ptSUQwZ1pHbG1aaUI4ZkNCN2ZWeHVJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0JrYVdabVcyRkxaWGxkSUQwZ2IySnFaV04wUkdsbVpseHVJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lIMWNiaUFnSUNBZ0lDQWdJQ0FnSUgxY2JpQWdJQ0FnSUNBZ2ZTQmxiSE5sSUh0Y2JpQWdJQ0FnSUNBZ0lDQWdJR1JwWm1ZZ1BTQmthV1ptSUh4OElIdDlYRzRnSUNBZ0lDQWdJQ0FnSUNCa2FXWm1XMkZMWlhsZElEMGdZbFpoYkhWbFhHNGdJQ0FnSUNBZ0lIMWNiaUFnSUNCOVhHNWNiaUFnSUNCbWIzSWdLSFpoY2lCaVMyVjVJR2x1SUdJcElIdGNiaUFnSUNBZ0lDQWdhV1lnS0NFb1lrdGxlU0JwYmlCaEtTa2dlMXh1SUNBZ0lDQWdJQ0FnSUNBZ1pHbG1aaUE5SUdScFptWWdmSHdnZTMxY2JpQWdJQ0FnSUNBZ0lDQWdJR1JwWm1aYllrdGxlVjBnUFNCaVcySkxaWGxkWEc0Z0lDQWdJQ0FnSUgxY2JpQWdJQ0I5WEc1Y2JpQWdJQ0J5WlhSMWNtNGdaR2xtWmx4dWZWeHVYRzVtZFc1amRHbHZiaUJuWlhSUWNtOTBiM1I1Y0dVb2RtRnNkV1VwSUh0Y2JpQWdhV1lnS0U5aWFtVmpkQzVuWlhSUWNtOTBiM1I1Y0dWUFppa2dlMXh1SUNBZ0lISmxkSFZ5YmlCUFltcGxZM1F1WjJWMFVISnZkRzkwZVhCbFQyWW9kbUZzZFdVcFhHNGdJSDBnWld4elpTQnBaaUFvZG1Gc2RXVXVYMTl3Y205MGIxOWZLU0I3WEc0Z0lDQWdjbVYwZFhKdUlIWmhiSFZsTGw5ZmNISnZkRzlmWDF4dUlDQjlJR1ZzYzJVZ2FXWWdLSFpoYkhWbExtTnZibk4wY25WamRHOXlLU0I3WEc0Z0lDQWdjbVYwZFhKdUlIWmhiSFZsTG1OdmJuTjBjblZqZEc5eUxuQnliM1J2ZEhsd1pWeHVJQ0I5WEc1OVhHNWNibjBzZTF3aUxpNHZkbTV2WkdVdmFYTXRkbWh2YjJ0Y0lqb3lOaXhjSW1sekxXOWlhbVZqZEZ3aU9qRXhmVjBzTXpVNlcyWjFibU4wYVc5dUtISmxjWFZwY21Vc2JXOWtkV3hsTEdWNGNHOXlkSE1wZTF4dWRtRnlJR2x6UVhKeVlYa2dQU0J5WlhGMWFYSmxLRndpZUMxcGN5MWhjbkpoZVZ3aUtWeHVYRzUyWVhJZ1ZsQmhkR05vSUQwZ2NtVnhkV2x5WlNoY0lpNHVMM1p1YjJSbEwzWndZWFJqYUZ3aUtWeHVkbUZ5SUdselZrNXZaR1VnUFNCeVpYRjFhWEpsS0Z3aUxpNHZkbTV2WkdVdmFYTXRkbTV2WkdWY0lpbGNiblpoY2lCcGMxWlVaWGgwSUQwZ2NtVnhkV2x5WlNoY0lpNHVMM1p1YjJSbEwybHpMWFowWlhoMFhDSXBYRzUyWVhJZ2FYTlhhV1JuWlhRZ1BTQnlaWEYxYVhKbEtGd2lMaTR2ZG01dlpHVXZhWE10ZDJsa1oyVjBYQ0lwWEc1MllYSWdhWE5VYUhWdWF5QTlJSEpsY1hWcGNtVW9YQ0l1TGk5MmJtOWtaUzlwY3kxMGFIVnVhMXdpS1Z4dWRtRnlJR2hoYm1Sc1pWUm9kVzVySUQwZ2NtVnhkV2x5WlNoY0lpNHVMM1p1YjJSbEwyaGhibVJzWlMxMGFIVnVhMXdpS1Z4dVhHNTJZWElnWkdsbVpsQnliM0J6SUQwZ2NtVnhkV2x5WlNoY0lpNHZaR2xtWmkxd2NtOXdjMXdpS1Z4dVhHNXRiMlIxYkdVdVpYaHdiM0owY3lBOUlHUnBabVpjYmx4dVpuVnVZM1JwYjI0Z1pHbG1aaWhoTENCaUtTQjdYRzRnSUNBZ2RtRnlJSEJoZEdOb0lEMGdleUJoT2lCaElIMWNiaUFnSUNCM1lXeHJLR0VzSUdJc0lIQmhkR05vTENBd0tWeHVJQ0FnSUhKbGRIVnliaUJ3WVhSamFGeHVmVnh1WEc1bWRXNWpkR2x2YmlCM1lXeHJLR0VzSUdJc0lIQmhkR05vTENCcGJtUmxlQ2tnZTF4dUlDQWdJR2xtSUNoaElEMDlQU0JpS1NCN1hHNGdJQ0FnSUNBZ0lISmxkSFZ5Ymx4dUlDQWdJSDFjYmx4dUlDQWdJSFpoY2lCaGNIQnNlU0E5SUhCaGRHTm9XMmx1WkdWNFhWeHVJQ0FnSUhaaGNpQmhjSEJzZVVOc1pXRnlJRDBnWm1Gc2MyVmNibHh1SUNBZ0lHbG1JQ2hwYzFSb2RXNXJLR0VwSUh4OElHbHpWR2gxYm1zb1lpa3BJSHRjYmlBZ0lDQWdJQ0FnZEdoMWJtdHpLR0VzSUdJc0lIQmhkR05vTENCcGJtUmxlQ2xjYmlBZ0lDQjlJR1ZzYzJVZ2FXWWdLR0lnUFQwZ2JuVnNiQ2tnZTF4dVhHNGdJQ0FnSUNBZ0lDOHZJRWxtSUdFZ2FYTWdZU0IzYVdSblpYUWdkMlVnZDJsc2JDQmhaR1FnWVNCeVpXMXZkbVVnY0dGMFkyZ2dabTl5SUdsMFhHNGdJQ0FnSUNBZ0lDOHZJRTkwYUdWeWQybHpaU0JoYm5rZ1kyaHBiR1FnZDJsa1oyVjBjeTlvYjI5cmN5QnRkWE4wSUdKbElHUmxjM1J5YjNsbFpDNWNiaUFnSUNBZ0lDQWdMeThnVkdocGN5QndjbVYyWlc1MGN5QmhaR1JwYm1jZ2RIZHZJSEpsYlc5MlpTQndZWFJqYUdWeklHWnZjaUJoSUhkcFpHZGxkQzVjYmlBZ0lDQWdJQ0FnYVdZZ0tDRnBjMWRwWkdkbGRDaGhLU2tnZTF4dUlDQWdJQ0FnSUNBZ0lDQWdZMnhsWVhKVGRHRjBaU2hoTENCd1lYUmphQ3dnYVc1a1pYZ3BYRzRnSUNBZ0lDQWdJQ0FnSUNCaGNIQnNlU0E5SUhCaGRHTm9XMmx1WkdWNFhWeHVJQ0FnSUNBZ0lDQjlYRzVjYmlBZ0lDQWdJQ0FnWVhCd2JIa2dQU0JoY0hCbGJtUlFZWFJqYUNoaGNIQnNlU3dnYm1WM0lGWlFZWFJqYUNoV1VHRjBZMmd1VWtWTlQxWkZMQ0JoTENCaUtTbGNiaUFnSUNCOUlHVnNjMlVnYVdZZ0tHbHpWazV2WkdVb1lpa3BJSHRjYmlBZ0lDQWdJQ0FnYVdZZ0tHbHpWazV2WkdVb1lTa3BJSHRjYmlBZ0lDQWdJQ0FnSUNBZ0lHbG1JQ2hoTG5SaFowNWhiV1VnUFQwOUlHSXVkR0ZuVG1GdFpTQW1KbHh1SUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJR0V1Ym1GdFpYTndZV05sSUQwOVBTQmlMbTVoYldWemNHRmpaU0FtSmx4dUlDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUdFdWEyVjVJRDA5UFNCaUxtdGxlU2tnZTF4dUlDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUhaaGNpQndjbTl3YzFCaGRHTm9JRDBnWkdsbVpsQnliM0J6S0dFdWNISnZjR1Z5ZEdsbGN5d2dZaTV3Y205d1pYSjBhV1Z6S1Z4dUlDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUdsbUlDaHdjbTl3YzFCaGRHTm9LU0I3WEc0Z0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lHRndjR3g1SUQwZ1lYQndaVzVrVUdGMFkyZ29ZWEJ3Ykhrc1hHNGdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNCdVpYY2dWbEJoZEdOb0tGWlFZWFJqYUM1UVVrOVFVeXdnWVN3Z2NISnZjSE5RWVhSamFDa3BYRzRnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdmVnh1SUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJR0Z3Y0d4NUlEMGdaR2xtWmtOb2FXeGtjbVZ1S0dFc0lHSXNJSEJoZEdOb0xDQmhjSEJzZVN3Z2FXNWtaWGdwWEc0Z0lDQWdJQ0FnSUNBZ0lDQjlJR1ZzYzJVZ2UxeHVJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lHRndjR3g1SUQwZ1lYQndaVzVrVUdGMFkyZ29ZWEJ3Ykhrc0lHNWxkeUJXVUdGMFkyZ29WbEJoZEdOb0xsWk9UMFJGTENCaExDQmlLU2xjYmlBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0JoY0hCc2VVTnNaV0Z5SUQwZ2RISjFaVnh1SUNBZ0lDQWdJQ0FnSUNBZ2ZWeHVJQ0FnSUNBZ0lDQjlJR1ZzYzJVZ2UxeHVJQ0FnSUNBZ0lDQWdJQ0FnWVhCd2JIa2dQU0JoY0hCbGJtUlFZWFJqYUNoaGNIQnNlU3dnYm1WM0lGWlFZWFJqYUNoV1VHRjBZMmd1Vms1UFJFVXNJR0VzSUdJcEtWeHVJQ0FnSUNBZ0lDQWdJQ0FnWVhCd2JIbERiR1ZoY2lBOUlIUnlkV1ZjYmlBZ0lDQWdJQ0FnZlZ4dUlDQWdJSDBnWld4elpTQnBaaUFvYVhOV1ZHVjRkQ2hpS1NrZ2UxeHVJQ0FnSUNBZ0lDQnBaaUFvSVdselZsUmxlSFFvWVNrcElIdGNiaUFnSUNBZ0lDQWdJQ0FnSUdGd2NHeDVJRDBnWVhCd1pXNWtVR0YwWTJnb1lYQndiSGtzSUc1bGR5QldVR0YwWTJnb1ZsQmhkR05vTGxaVVJWaFVMQ0JoTENCaUtTbGNiaUFnSUNBZ0lDQWdJQ0FnSUdGd2NHeDVRMnhsWVhJZ1BTQjBjblZsWEc0Z0lDQWdJQ0FnSUgwZ1pXeHpaU0JwWmlBb1lTNTBaWGgwSUNFOVBTQmlMblJsZUhRcElIdGNiaUFnSUNBZ0lDQWdJQ0FnSUdGd2NHeDVJRDBnWVhCd1pXNWtVR0YwWTJnb1lYQndiSGtzSUc1bGR5QldVR0YwWTJnb1ZsQmhkR05vTGxaVVJWaFVMQ0JoTENCaUtTbGNiaUFnSUNBZ0lDQWdmVnh1SUNBZ0lIMGdaV3h6WlNCcFppQW9hWE5YYVdSblpYUW9ZaWtwSUh0Y2JpQWdJQ0FnSUNBZ2FXWWdLQ0ZwYzFkcFpHZGxkQ2hoS1NrZ2UxeHVJQ0FnSUNBZ0lDQWdJQ0FnWVhCd2JIbERiR1ZoY2lBOUlIUnlkV1ZjYmlBZ0lDQWdJQ0FnZlZ4dVhHNGdJQ0FnSUNBZ0lHRndjR3g1SUQwZ1lYQndaVzVrVUdGMFkyZ29ZWEJ3Ykhrc0lHNWxkeUJXVUdGMFkyZ29WbEJoZEdOb0xsZEpSRWRGVkN3Z1lTd2dZaWtwWEc0Z0lDQWdmVnh1WEc0Z0lDQWdhV1lnS0dGd2NHeDVLU0I3WEc0Z0lDQWdJQ0FnSUhCaGRHTm9XMmx1WkdWNFhTQTlJR0Z3Y0d4NVhHNGdJQ0FnZlZ4dVhHNGdJQ0FnYVdZZ0tHRndjR3g1UTJ4bFlYSXBJSHRjYmlBZ0lDQWdJQ0FnWTJ4bFlYSlRkR0YwWlNoaExDQndZWFJqYUN3Z2FXNWtaWGdwWEc0Z0lDQWdmVnh1ZlZ4dVhHNW1kVzVqZEdsdmJpQmthV1ptUTJocGJHUnlaVzRvWVN3Z1lpd2djR0YwWTJnc0lHRndjR3g1TENCcGJtUmxlQ2tnZTF4dUlDQWdJSFpoY2lCaFEyaHBiR1J5Wlc0Z1BTQmhMbU5vYVd4a2NtVnVYRzRnSUNBZ2RtRnlJRzl5WkdWeVpXUlRaWFFnUFNCeVpXOXlaR1Z5S0dGRGFHbHNaSEpsYml3Z1lpNWphR2xzWkhKbGJpbGNiaUFnSUNCMllYSWdZa05vYVd4a2NtVnVJRDBnYjNKa1pYSmxaRk5sZEM1amFHbHNaSEpsYmx4dVhHNGdJQ0FnZG1GeUlHRk1aVzRnUFNCaFEyaHBiR1J5Wlc0dWJHVnVaM1JvWEc0Z0lDQWdkbUZ5SUdKTVpXNGdQU0JpUTJocGJHUnlaVzR1YkdWdVozUm9YRzRnSUNBZ2RtRnlJR3hsYmlBOUlHRk1aVzRnUGlCaVRHVnVJRDhnWVV4bGJpQTZJR0pNWlc1Y2JseHVJQ0FnSUdadmNpQW9kbUZ5SUdrZ1BTQXdPeUJwSUR3Z2JHVnVPeUJwS3lzcElIdGNiaUFnSUNBZ0lDQWdkbUZ5SUd4bFpuUk9iMlJsSUQwZ1lVTm9hV3hrY21WdVcybGRYRzRnSUNBZ0lDQWdJSFpoY2lCeWFXZG9kRTV2WkdVZ1BTQmlRMmhwYkdSeVpXNWJhVjFjYmlBZ0lDQWdJQ0FnYVc1a1pYZ2dLejBnTVZ4dVhHNGdJQ0FnSUNBZ0lHbG1JQ2doYkdWbWRFNXZaR1VwSUh0Y2JpQWdJQ0FnSUNBZ0lDQWdJR2xtSUNoeWFXZG9kRTV2WkdVcElIdGNiaUFnSUNBZ0lDQWdJQ0FnSUNBZ0lDQXZMeUJGZUdObGMzTWdibTlrWlhNZ2FXNGdZaUJ1WldWa0lIUnZJR0psSUdGa1pHVmtYRzRnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdZWEJ3YkhrZ1BTQmhjSEJsYm1SUVlYUmphQ2hoY0hCc2VTeGNiaUFnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnYm1WM0lGWlFZWFJqYUNoV1VHRjBZMmd1U1U1VFJWSlVMQ0J1ZFd4c0xDQnlhV2RvZEU1dlpHVXBLVnh1SUNBZ0lDQWdJQ0FnSUNBZ2ZWeHVJQ0FnSUNBZ0lDQjlJR1ZzYzJVZ2UxeHVJQ0FnSUNBZ0lDQWdJQ0FnZDJGc2F5aHNaV1owVG05a1pTd2djbWxuYUhST2IyUmxMQ0J3WVhSamFDd2dhVzVrWlhncFhHNGdJQ0FnSUNBZ0lIMWNibHh1SUNBZ0lDQWdJQ0JwWmlBb2FYTldUbTlrWlNoc1pXWjBUbTlrWlNrZ0ppWWdiR1ZtZEU1dlpHVXVZMjkxYm5RcElIdGNiaUFnSUNBZ0lDQWdJQ0FnSUdsdVpHVjRJQ3M5SUd4bFpuUk9iMlJsTG1OdmRXNTBYRzRnSUNBZ0lDQWdJSDFjYmlBZ0lDQjlYRzVjYmlBZ0lDQnBaaUFvYjNKa1pYSmxaRk5sZEM1dGIzWmxjeWtnZTF4dUlDQWdJQ0FnSUNBdkx5QlNaVzl5WkdWeUlHNXZaR1Z6SUd4aGMzUmNiaUFnSUNBZ0lDQWdZWEJ3YkhrZ1BTQmhjSEJsYm1SUVlYUmphQ2hoY0hCc2VTd2dibVYzSUZaUVlYUmphQ2hjYmlBZ0lDQWdJQ0FnSUNBZ0lGWlFZWFJqYUM1UFVrUkZVaXhjYmlBZ0lDQWdJQ0FnSUNBZ0lHRXNYRzRnSUNBZ0lDQWdJQ0FnSUNCdmNtUmxjbVZrVTJWMExtMXZkbVZ6WEc0Z0lDQWdJQ0FnSUNrcFhHNGdJQ0FnZlZ4dVhHNGdJQ0FnY21WMGRYSnVJR0Z3Y0d4NVhHNTlYRzVjYm1aMWJtTjBhVzl1SUdOc1pXRnlVM1JoZEdVb2RrNXZaR1VzSUhCaGRHTm9MQ0JwYm1SbGVDa2dlMXh1SUNBZ0lDOHZJRlJQUkU4NklFMWhhMlVnZEdocGN5QmhJSE5wYm1kc1pTQjNZV3hyTENCdWIzUWdkSGR2WEc0Z0lDQWdkVzVvYjI5cktIWk9iMlJsTENCd1lYUmphQ3dnYVc1a1pYZ3BYRzRnSUNBZ1pHVnpkSEp2ZVZkcFpHZGxkSE1vZGs1dlpHVXNJSEJoZEdOb0xDQnBibVJsZUNsY2JuMWNibHh1THk4Z1VHRjBZMmdnY21WamIzSmtjeUJtYjNJZ1lXeHNJR1JsYzNSeWIzbGxaQ0IzYVdSblpYUnpJRzExYzNRZ1ltVWdZV1JrWldRZ1ltVmpZWFZ6WlNCM1pTQnVaV1ZrWEc0dkx5QmhJRVJQVFNCdWIyUmxJSEpsWm1WeVpXNWpaU0JtYjNJZ2RHaGxJR1JsYzNSeWIza2dablZ1WTNScGIyNWNibVoxYm1OMGFXOXVJR1JsYzNSeWIzbFhhV1JuWlhSektIWk9iMlJsTENCd1lYUmphQ3dnYVc1a1pYZ3BJSHRjYmlBZ0lDQnBaaUFvYVhOWGFXUm5aWFFvZGs1dlpHVXBLU0I3WEc0Z0lDQWdJQ0FnSUdsbUlDaDBlWEJsYjJZZ2RrNXZaR1V1WkdWemRISnZlU0E5UFQwZ1hDSm1kVzVqZEdsdmJsd2lLU0I3WEc0Z0lDQWdJQ0FnSUNBZ0lDQndZWFJqYUZ0cGJtUmxlRjBnUFNCaGNIQmxibVJRWVhSamFDaGNiaUFnSUNBZ0lDQWdJQ0FnSUNBZ0lDQndZWFJqYUZ0cGJtUmxlRjBzWEc0Z0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnYm1WM0lGWlFZWFJqYUNoV1VHRjBZMmd1VWtWTlQxWkZMQ0IyVG05a1pTd2diblZzYkNsY2JpQWdJQ0FnSUNBZ0lDQWdJQ2xjYmlBZ0lDQWdJQ0FnZlZ4dUlDQWdJSDBnWld4elpTQnBaaUFvYVhOV1RtOWtaU2gyVG05a1pTa2dKaVlnS0haT2IyUmxMbWhoYzFkcFpHZGxkSE1nZkh3Z2RrNXZaR1V1YUdGelZHaDFibXR6S1NrZ2UxeHVJQ0FnSUNBZ0lDQjJZWElnWTJocGJHUnlaVzRnUFNCMlRtOWtaUzVqYUdsc1pISmxibHh1SUNBZ0lDQWdJQ0IyWVhJZ2JHVnVJRDBnWTJocGJHUnlaVzR1YkdWdVozUm9YRzRnSUNBZ0lDQWdJR1p2Y2lBb2RtRnlJR2tnUFNBd095QnBJRHdnYkdWdU95QnBLeXNwSUh0Y2JpQWdJQ0FnSUNBZ0lDQWdJSFpoY2lCamFHbHNaQ0E5SUdOb2FXeGtjbVZ1VzJsZFhHNGdJQ0FnSUNBZ0lDQWdJQ0JwYm1SbGVDQXJQU0F4WEc1Y2JpQWdJQ0FnSUNBZ0lDQWdJR1JsYzNSeWIzbFhhV1JuWlhSektHTm9hV3hrTENCd1lYUmphQ3dnYVc1a1pYZ3BYRzVjYmlBZ0lDQWdJQ0FnSUNBZ0lHbG1JQ2hwYzFaT2IyUmxLR05vYVd4a0tTQW1KaUJqYUdsc1pDNWpiM1Z1ZENrZ2UxeHVJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lHbHVaR1Y0SUNzOUlHTm9hV3hrTG1OdmRXNTBYRzRnSUNBZ0lDQWdJQ0FnSUNCOVhHNGdJQ0FnSUNBZ0lIMWNiaUFnSUNCOUlHVnNjMlVnYVdZZ0tHbHpWR2gxYm1zb2RrNXZaR1VwS1NCN1hHNGdJQ0FnSUNBZ0lIUm9kVzVyY3loMlRtOWtaU3dnYm5Wc2JDd2djR0YwWTJnc0lHbHVaR1Y0S1Z4dUlDQWdJSDFjYm4xY2JseHVMeThnUTNKbFlYUmxJR0VnYzNWaUxYQmhkR05vSUdadmNpQjBhSFZ1YTNOY2JtWjFibU4wYVc5dUlIUm9kVzVyY3loaExDQmlMQ0J3WVhSamFDd2dhVzVrWlhncElIdGNiaUFnSUNCMllYSWdibTlrWlhNZ1BTQm9ZVzVrYkdWVWFIVnVheWhoTENCaUtWeHVJQ0FnSUhaaGNpQjBhSFZ1YTFCaGRHTm9JRDBnWkdsbVppaHViMlJsY3k1aExDQnViMlJsY3k1aUtWeHVJQ0FnSUdsbUlDaG9ZWE5RWVhSamFHVnpLSFJvZFc1clVHRjBZMmdwS1NCN1hHNGdJQ0FnSUNBZ0lIQmhkR05vVzJsdVpHVjRYU0E5SUc1bGR5QldVR0YwWTJnb1ZsQmhkR05vTGxSSVZVNUxMQ0J1ZFd4c0xDQjBhSFZ1YTFCaGRHTm9LVnh1SUNBZ0lIMWNibjFjYmx4dVpuVnVZM1JwYjI0Z2FHRnpVR0YwWTJobGN5aHdZWFJqYUNrZ2UxeHVJQ0FnSUdadmNpQW9kbUZ5SUdsdVpHVjRJR2x1SUhCaGRHTm9LU0I3WEc0Z0lDQWdJQ0FnSUdsbUlDaHBibVJsZUNBaFBUMGdYQ0poWENJcElIdGNiaUFnSUNBZ0lDQWdJQ0FnSUhKbGRIVnliaUIwY25WbFhHNGdJQ0FnSUNBZ0lIMWNiaUFnSUNCOVhHNWNiaUFnSUNCeVpYUjFjbTRnWm1Gc2MyVmNibjFjYmx4dUx5OGdSWGhsWTNWMFpTQm9iMjlyY3lCM2FHVnVJSFIzYnlCdWIyUmxjeUJoY21VZ2FXUmxiblJwWTJGc1hHNW1kVzVqZEdsdmJpQjFibWh2YjJzb2RrNXZaR1VzSUhCaGRHTm9MQ0JwYm1SbGVDa2dlMXh1SUNBZ0lHbG1JQ2hwYzFaT2IyUmxLSFpPYjJSbEtTa2dlMXh1SUNBZ0lDQWdJQ0JwWmlBb2RrNXZaR1V1YUc5dmEzTXBJSHRjYmlBZ0lDQWdJQ0FnSUNBZ0lIQmhkR05vVzJsdVpHVjRYU0E5SUdGd2NHVnVaRkJoZEdOb0tGeHVJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lIQmhkR05vVzJsdVpHVjRYU3hjYmlBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0J1WlhjZ1ZsQmhkR05vS0Z4dUlDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQldVR0YwWTJndVVGSlBVRk1zWEc0Z0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lIWk9iMlJsTEZ4dUlDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQjFibVJsWm1sdVpXUkxaWGx6S0haT2IyUmxMbWh2YjJ0ektWeHVJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDbGNiaUFnSUNBZ0lDQWdJQ0FnSUNsY2JpQWdJQ0FnSUNBZ2ZWeHVYRzRnSUNBZ0lDQWdJR2xtSUNoMlRtOWtaUzVrWlhOalpXNWtZVzUwU0c5dmEzTWdmSHdnZGs1dlpHVXVhR0Z6VkdoMWJtdHpLU0I3WEc0Z0lDQWdJQ0FnSUNBZ0lDQjJZWElnWTJocGJHUnlaVzRnUFNCMlRtOWtaUzVqYUdsc1pISmxibHh1SUNBZ0lDQWdJQ0FnSUNBZ2RtRnlJR3hsYmlBOUlHTm9hV3hrY21WdUxteGxibWQwYUZ4dUlDQWdJQ0FnSUNBZ0lDQWdabTl5SUNoMllYSWdhU0E5SURBN0lHa2dQQ0JzWlc0N0lHa3JLeWtnZTF4dUlDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUhaaGNpQmphR2xzWkNBOUlHTm9hV3hrY21WdVcybGRYRzRnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdhVzVrWlhnZ0t6MGdNVnh1WEc0Z0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnZFc1b2IyOXJLR05vYVd4a0xDQndZWFJqYUN3Z2FXNWtaWGdwWEc1Y2JpQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNCcFppQW9hWE5XVG05a1pTaGphR2xzWkNrZ0ppWWdZMmhwYkdRdVkyOTFiblFwSUh0Y2JpQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdhVzVrWlhnZ0t6MGdZMmhwYkdRdVkyOTFiblJjYmlBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0I5WEc0Z0lDQWdJQ0FnSUNBZ0lDQjlYRzRnSUNBZ0lDQWdJSDFjYmlBZ0lDQjlJR1ZzYzJVZ2FXWWdLR2x6VkdoMWJtc29kazV2WkdVcEtTQjdYRzRnSUNBZ0lDQWdJSFJvZFc1cmN5aDJUbTlrWlN3Z2JuVnNiQ3dnY0dGMFkyZ3NJR2x1WkdWNEtWeHVJQ0FnSUgxY2JuMWNibHh1Wm5WdVkzUnBiMjRnZFc1a1pXWnBibVZrUzJWNWN5aHZZbW9wSUh0Y2JpQWdJQ0IyWVhJZ2NtVnpkV3gwSUQwZ2UzMWNibHh1SUNBZ0lHWnZjaUFvZG1GeUlHdGxlU0JwYmlCdlltb3BJSHRjYmlBZ0lDQWdJQ0FnY21WemRXeDBXMnRsZVYwZ1BTQjFibVJsWm1sdVpXUmNiaUFnSUNCOVhHNWNiaUFnSUNCeVpYUjFjbTRnY21WemRXeDBYRzU5WEc1Y2JpOHZJRXhwYzNRZ1pHbG1aaXdnYm1GcGRtVWdiR1ZtZENCMGJ5QnlhV2RvZENCeVpXOXlaR1Z5YVc1blhHNW1kVzVqZEdsdmJpQnlaVzl5WkdWeUtHRkRhR2xzWkhKbGJpd2dZa05vYVd4a2NtVnVLU0I3WEc0Z0lDQWdMeThnVHloTktTQjBhVzFsTENCUEtFMHBJRzFsYlc5eWVWeHVJQ0FnSUhaaGNpQmlRMmhwYkdSSmJtUmxlQ0E5SUd0bGVVbHVaR1Y0S0dKRGFHbHNaSEpsYmlsY2JpQWdJQ0IyWVhJZ1lrdGxlWE1nUFNCaVEyaHBiR1JKYm1SbGVDNXJaWGx6WEc0Z0lDQWdkbUZ5SUdKR2NtVmxJRDBnWWtOb2FXeGtTVzVrWlhndVpuSmxaVnh1WEc0Z0lDQWdhV1lnS0dKR2NtVmxMbXhsYm1kMGFDQTlQVDBnWWtOb2FXeGtjbVZ1TG14bGJtZDBhQ2tnZTF4dUlDQWdJQ0FnSUNCeVpYUjFjbTRnZTF4dUlDQWdJQ0FnSUNBZ0lDQWdZMmhwYkdSeVpXNDZJR0pEYUdsc1pISmxiaXhjYmlBZ0lDQWdJQ0FnSUNBZ0lHMXZkbVZ6T2lCdWRXeHNYRzRnSUNBZ0lDQWdJSDFjYmlBZ0lDQjlYRzVjYmlBZ0lDQXZMeUJQS0U0cElIUnBiV1VzSUU4b1Rpa2diV1Z0YjNKNVhHNGdJQ0FnZG1GeUlHRkRhR2xzWkVsdVpHVjRJRDBnYTJWNVNXNWtaWGdvWVVOb2FXeGtjbVZ1S1Z4dUlDQWdJSFpoY2lCaFMyVjVjeUE5SUdGRGFHbHNaRWx1WkdWNExtdGxlWE5jYmlBZ0lDQjJZWElnWVVaeVpXVWdQU0JoUTJocGJHUkpibVJsZUM1bWNtVmxYRzVjYmlBZ0lDQnBaaUFvWVVaeVpXVXViR1Z1WjNSb0lEMDlQU0JoUTJocGJHUnlaVzR1YkdWdVozUm9LU0I3WEc0Z0lDQWdJQ0FnSUhKbGRIVnliaUI3WEc0Z0lDQWdJQ0FnSUNBZ0lDQmphR2xzWkhKbGJqb2dZa05vYVd4a2NtVnVMRnh1SUNBZ0lDQWdJQ0FnSUNBZ2JXOTJaWE02SUc1MWJHeGNiaUFnSUNBZ0lDQWdmVnh1SUNBZ0lIMWNibHh1SUNBZ0lDOHZJRThvVFVGWUtFNHNJRTBwS1NCdFpXMXZjbmxjYmlBZ0lDQjJZWElnYm1WM1EyaHBiR1J5Wlc0Z1BTQmJYVnh1WEc0Z0lDQWdkbUZ5SUdaeVpXVkpibVJsZUNBOUlEQmNiaUFnSUNCMllYSWdabkpsWlVOdmRXNTBJRDBnWWtaeVpXVXViR1Z1WjNSb1hHNGdJQ0FnZG1GeUlHUmxiR1YwWldSSmRHVnRjeUE5SURCY2JseHVJQ0FnSUM4dklFbDBaWEpoZEdVZ2RHaHliM1ZuYUNCaElHRnVaQ0J0WVhSamFDQmhJRzV2WkdVZ2FXNGdZbHh1SUNBZ0lDOHZJRThvVGlrZ2RHbHRaU3hjYmlBZ0lDQm1iM0lnS0haaGNpQnBJRDBnTUNBN0lHa2dQQ0JoUTJocGJHUnlaVzR1YkdWdVozUm9PeUJwS3lzcElIdGNiaUFnSUNBZ0lDQWdkbUZ5SUdGSmRHVnRJRDBnWVVOb2FXeGtjbVZ1VzJsZFhHNGdJQ0FnSUNBZ0lIWmhjaUJwZEdWdFNXNWtaWGhjYmx4dUlDQWdJQ0FnSUNCcFppQW9ZVWwwWlcwdWEyVjVLU0I3WEc0Z0lDQWdJQ0FnSUNBZ0lDQnBaaUFvWWt0bGVYTXVhR0Z6VDNkdVVISnZjR1Z5ZEhrb1lVbDBaVzB1YTJWNUtTa2dlMXh1SUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQzh2SUUxaGRHTm9JSFZ3SUhSb1pTQnZiR1FnYTJWNWMxeHVJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lHbDBaVzFKYm1SbGVDQTlJR0pMWlhselcyRkpkR1Z0TG10bGVWMWNiaUFnSUNBZ0lDQWdJQ0FnSUNBZ0lDQnVaWGREYUdsc1pISmxiaTV3ZFhOb0tHSkRhR2xzWkhKbGJsdHBkR1Z0U1c1a1pYaGRLVnh1WEc0Z0lDQWdJQ0FnSUNBZ0lDQjlJR1ZzYzJVZ2UxeHVJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDOHZJRkpsYlc5MlpTQnZiR1FnYTJWNVpXUWdhWFJsYlhOY2JpQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNCcGRHVnRTVzVrWlhnZ1BTQnBJQzBnWkdWc1pYUmxaRWwwWlcxekt5dGNiaUFnSUNBZ0lDQWdJQ0FnSUNBZ0lDQnVaWGREYUdsc1pISmxiaTV3ZFhOb0tHNTFiR3dwWEc0Z0lDQWdJQ0FnSUNBZ0lDQjlYRzRnSUNBZ0lDQWdJSDBnWld4elpTQjdYRzRnSUNBZ0lDQWdJQ0FnSUNBdkx5Qk5ZWFJqYUNCMGFHVWdhWFJsYlNCcGJpQmhJSGRwZEdnZ2RHaGxJRzVsZUhRZ1puSmxaU0JwZEdWdElHbHVJR0pjYmlBZ0lDQWdJQ0FnSUNBZ0lHbG1JQ2htY21WbFNXNWtaWGdnUENCbWNtVmxRMjkxYm5RcElIdGNiaUFnSUNBZ0lDQWdJQ0FnSUNBZ0lDQnBkR1Z0U1c1a1pYZ2dQU0JpUm5KbFpWdG1jbVZsU1c1a1pYZ3JLMTFjYmlBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0J1WlhkRGFHbHNaSEpsYmk1d2RYTm9LR0pEYUdsc1pISmxibHRwZEdWdFNXNWtaWGhkS1Z4dUlDQWdJQ0FnSUNBZ0lDQWdmU0JsYkhObElIdGNiaUFnSUNBZ0lDQWdJQ0FnSUNBZ0lDQXZMeUJVYUdWeVpTQmhjbVVnYm04Z1puSmxaU0JwZEdWdGN5QnBiaUJpSUhSdklHMWhkR05vSUhkcGRHaGNiaUFnSUNBZ0lDQWdJQ0FnSUNBZ0lDQXZMeUIwYUdVZ1puSmxaU0JwZEdWdGN5QnBiaUJoTENCemJ5QjBhR1VnWlhoMGNtRWdabkpsWlNCdWIyUmxjMXh1SUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQzh2SUdGeVpTQmtaV3hsZEdWa0xseHVJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lHbDBaVzFKYm1SbGVDQTlJR2tnTFNCa1pXeGxkR1ZrU1hSbGJYTXJLMXh1SUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJRzVsZDBOb2FXeGtjbVZ1TG5CMWMyZ29iblZzYkNsY2JpQWdJQ0FnSUNBZ0lDQWdJSDFjYmlBZ0lDQWdJQ0FnZlZ4dUlDQWdJSDFjYmx4dUlDQWdJSFpoY2lCc1lYTjBSbkpsWlVsdVpHVjRJRDBnWm5KbFpVbHVaR1Y0SUQ0OUlHSkdjbVZsTG14bGJtZDBhQ0EvWEc0Z0lDQWdJQ0FnSUdKRGFHbHNaSEpsYmk1c1pXNW5kR2dnT2x4dUlDQWdJQ0FnSUNCaVJuSmxaVnRtY21WbFNXNWtaWGhkWEc1Y2JpQWdJQ0F2THlCSmRHVnlZWFJsSUhSb2NtOTFaMmdnWWlCaGJtUWdZWEJ3Wlc1a0lHRnVlU0J1WlhjZ2EyVjVjMXh1SUNBZ0lDOHZJRThvVFNrZ2RHbHRaVnh1SUNBZ0lHWnZjaUFvZG1GeUlHb2dQU0F3T3lCcUlEd2dZa05vYVd4a2NtVnVMbXhsYm1kMGFEc2dhaXNyS1NCN1hHNGdJQ0FnSUNBZ0lIWmhjaUJ1WlhkSmRHVnRJRDBnWWtOb2FXeGtjbVZ1VzJwZFhHNWNiaUFnSUNBZ0lDQWdhV1lnS0c1bGQwbDBaVzB1YTJWNUtTQjdYRzRnSUNBZ0lDQWdJQ0FnSUNCcFppQW9JV0ZMWlhsekxtaGhjMDkzYmxCeWIzQmxjblI1S0c1bGQwbDBaVzB1YTJWNUtTa2dlMXh1SUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQzh2SUVGa1pDQmhibmtnYm1WM0lHdGxlV1ZrSUdsMFpXMXpYRzRnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdMeThnVjJVZ1lYSmxJR0ZrWkdsdVp5QnVaWGNnYVhSbGJYTWdkRzhnZEdobElHVnVaQ0JoYm1RZ2RHaGxiaUJ6YjNKMGFXNW5JSFJvWlcxY2JpQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBdkx5QnBiaUJ3YkdGalpTNGdTVzRnWm5WMGRYSmxJSGRsSUhOb2IzVnNaQ0JwYm5ObGNuUWdibVYzSUdsMFpXMXpJR2x1SUhCc1lXTmxMbHh1SUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJRzVsZDBOb2FXeGtjbVZ1TG5CMWMyZ29ibVYzU1hSbGJTbGNiaUFnSUNBZ0lDQWdJQ0FnSUgxY2JpQWdJQ0FnSUNBZ2ZTQmxiSE5sSUdsbUlDaHFJRDQ5SUd4aGMzUkdjbVZsU1c1a1pYZ3BJSHRjYmlBZ0lDQWdJQ0FnSUNBZ0lDOHZJRUZrWkNCaGJua2diR1ZtZEc5MlpYSWdibTl1TFd0bGVXVmtJR2wwWlcxelhHNGdJQ0FnSUNBZ0lDQWdJQ0J1WlhkRGFHbHNaSEpsYmk1d2RYTm9LRzVsZDBsMFpXMHBYRzRnSUNBZ0lDQWdJSDFjYmlBZ0lDQjlYRzVjYmlBZ0lDQjJZWElnYzJsdGRXeGhkR1VnUFNCdVpYZERhR2xzWkhKbGJpNXpiR2xqWlNncFhHNGdJQ0FnZG1GeUlITnBiWFZzWVhSbFNXNWtaWGdnUFNBd1hHNGdJQ0FnZG1GeUlISmxiVzkyWlhNZ1BTQmJYVnh1SUNBZ0lIWmhjaUJwYm5ObGNuUnpJRDBnVzExY2JpQWdJQ0IyWVhJZ2MybHRkV3hoZEdWSmRHVnRYRzVjYmlBZ0lDQm1iM0lnS0haaGNpQnJJRDBnTURzZ2F5QThJR0pEYUdsc1pISmxiaTVzWlc1bmRHZzdLU0I3WEc0Z0lDQWdJQ0FnSUhaaGNpQjNZVzUwWldSSmRHVnRJRDBnWWtOb2FXeGtjbVZ1VzJ0ZFhHNGdJQ0FnSUNBZ0lITnBiWFZzWVhSbFNYUmxiU0E5SUhOcGJYVnNZWFJsVzNOcGJYVnNZWFJsU1c1a1pYaGRYRzVjYmlBZ0lDQWdJQ0FnTHk4Z2NtVnRiM1psSUdsMFpXMXpYRzRnSUNBZ0lDQWdJSGRvYVd4bElDaHphVzExYkdGMFpVbDBaVzBnUFQwOUlHNTFiR3dnSmlZZ2MybHRkV3hoZEdVdWJHVnVaM1JvS1NCN1hHNGdJQ0FnSUNBZ0lDQWdJQ0J5WlcxdmRtVnpMbkIxYzJnb2NtVnRiM1psS0hOcGJYVnNZWFJsTENCemFXMTFiR0YwWlVsdVpHVjRMQ0J1ZFd4c0tTbGNiaUFnSUNBZ0lDQWdJQ0FnSUhOcGJYVnNZWFJsU1hSbGJTQTlJSE5wYlhWc1lYUmxXM05wYlhWc1lYUmxTVzVrWlhoZFhHNGdJQ0FnSUNBZ0lIMWNibHh1SUNBZ0lDQWdJQ0JwWmlBb0lYTnBiWFZzWVhSbFNYUmxiU0I4ZkNCemFXMTFiR0YwWlVsMFpXMHVhMlY1SUNFOVBTQjNZVzUwWldSSmRHVnRMbXRsZVNrZ2UxeHVJQ0FnSUNBZ0lDQWdJQ0FnTHk4Z2FXWWdkMlVnYm1WbFpDQmhJR3RsZVNCcGJpQjBhR2x6SUhCdmMybDBhVzl1TGk0dVhHNGdJQ0FnSUNBZ0lDQWdJQ0JwWmlBb2QyRnVkR1ZrU1hSbGJTNXJaWGtwSUh0Y2JpQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNCcFppQW9jMmx0ZFd4aGRHVkpkR1Z0SUNZbUlITnBiWFZzWVhSbFNYUmxiUzVyWlhrcElIdGNiaUFnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnTHk4Z2FXWWdZVzRnYVc1elpYSjBJR1J2WlhOdUozUWdjSFYwSUhSb2FYTWdhMlY1SUdsdUlIQnNZV05sTENCcGRDQnVaV1ZrY3lCMGJ5QnRiM1psWEc0Z0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lHbG1JQ2hpUzJWNWMxdHphVzExYkdGMFpVbDBaVzB1YTJWNVhTQWhQVDBnYXlBcklERXBJSHRjYmlBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJSEpsYlc5MlpYTXVjSFZ6YUNoeVpXMXZkbVVvYzJsdGRXeGhkR1VzSUhOcGJYVnNZWFJsU1c1a1pYZ3NJSE5wYlhWc1lYUmxTWFJsYlM1clpYa3BLVnh1SUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdjMmx0ZFd4aGRHVkpkR1Z0SUQwZ2MybHRkV3hoZEdWYmMybHRkV3hoZEdWSmJtUmxlRjFjYmlBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQzh2SUdsbUlIUm9aU0J5WlcxdmRtVWdaR2xrYmlkMElIQjFkQ0IwYUdVZ2QyRnVkR1ZrSUdsMFpXMGdhVzRnY0d4aFkyVXNJSGRsSUc1bFpXUWdkRzhnYVc1elpYSjBJR2wwWEc0Z0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0JwWmlBb0lYTnBiWFZzWVhSbFNYUmxiU0I4ZkNCemFXMTFiR0YwWlVsMFpXMHVhMlY1SUNFOVBTQjNZVzUwWldSSmRHVnRMbXRsZVNrZ2UxeHVJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJR2x1YzJWeWRITXVjSFZ6YUNoN2EyVjVPaUIzWVc1MFpXUkpkR1Z0TG10bGVTd2dkRzg2SUd0OUtWeHVJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ2ZWeHVJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0x5OGdhWFJsYlhNZ1lYSmxJRzFoZEdOb2FXNW5MQ0J6YnlCemEybHdJR0ZvWldGa1hHNGdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNCbGJITmxJSHRjYmlBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNCemFXMTFiR0YwWlVsdVpHVjRLeXRjYmlBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJSDFjYmlBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ2ZWeHVJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0JsYkhObElIdGNiaUFnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lHbHVjMlZ5ZEhNdWNIVnphQ2g3YTJWNU9pQjNZVzUwWldSSmRHVnRMbXRsZVN3Z2RHODZJR3Q5S1Z4dUlDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQjlYRzRnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdmVnh1SUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJR1ZzYzJVZ2UxeHVJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0JwYm5ObGNuUnpMbkIxYzJnb2UydGxlVG9nZDJGdWRHVmtTWFJsYlM1clpYa3NJSFJ2T2lCcmZTbGNiaUFnSUNBZ0lDQWdJQ0FnSUNBZ0lDQjlYRzRnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdheXNyWEc0Z0lDQWdJQ0FnSUNBZ0lDQjlYRzRnSUNBZ0lDQWdJQ0FnSUNBdkx5QmhJR3RsZVNCcGJpQnphVzExYkdGMFpTQm9ZWE1nYm04Z2JXRjBZMmhwYm1jZ2QyRnVkR1ZrSUd0bGVTd2djbVZ0YjNabElHbDBYRzRnSUNBZ0lDQWdJQ0FnSUNCbGJITmxJR2xtSUNoemFXMTFiR0YwWlVsMFpXMGdKaVlnYzJsdGRXeGhkR1ZKZEdWdExtdGxlU2tnZTF4dUlDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUhKbGJXOTJaWE11Y0hWemFDaHlaVzF2ZG1Vb2MybHRkV3hoZEdVc0lITnBiWFZzWVhSbFNXNWtaWGdzSUhOcGJYVnNZWFJsU1hSbGJTNXJaWGtwS1Z4dUlDQWdJQ0FnSUNBZ0lDQWdmVnh1SUNBZ0lDQWdJQ0I5WEc0Z0lDQWdJQ0FnSUdWc2MyVWdlMXh1SUNBZ0lDQWdJQ0FnSUNBZ2MybHRkV3hoZEdWSmJtUmxlQ3NyWEc0Z0lDQWdJQ0FnSUNBZ0lDQnJLeXRjYmlBZ0lDQWdJQ0FnZlZ4dUlDQWdJSDFjYmx4dUlDQWdJQzh2SUhKbGJXOTJaU0JoYkd3Z2RHaGxJSEpsYldGcGJtbHVaeUJ1YjJSbGN5Qm1jbTl0SUhOcGJYVnNZWFJsWEc0Z0lDQWdkMmhwYkdVb2MybHRkV3hoZEdWSmJtUmxlQ0E4SUhOcGJYVnNZWFJsTG14bGJtZDBhQ2tnZTF4dUlDQWdJQ0FnSUNCemFXMTFiR0YwWlVsMFpXMGdQU0J6YVcxMWJHRjBaVnR6YVcxMWJHRjBaVWx1WkdWNFhWeHVJQ0FnSUNBZ0lDQnlaVzF2ZG1WekxuQjFjMmdvY21WdGIzWmxLSE5wYlhWc1lYUmxMQ0J6YVcxMWJHRjBaVWx1WkdWNExDQnphVzExYkdGMFpVbDBaVzBnSmlZZ2MybHRkV3hoZEdWSmRHVnRMbXRsZVNrcFhHNGdJQ0FnZlZ4dVhHNGdJQ0FnTHk4Z1NXWWdkR2hsSUc5dWJIa2diVzkyWlhNZ2QyVWdhR0YyWlNCaGNtVWdaR1ZzWlhSbGN5QjBhR1Z1SUhkbElHTmhiaUJxZFhOMFhHNGdJQ0FnTHk4Z2JHVjBJSFJvWlNCa1pXeGxkR1VnY0dGMFkyZ2djbVZ0YjNabElIUm9aWE5sSUdsMFpXMXpMbHh1SUNBZ0lHbG1JQ2h5WlcxdmRtVnpMbXhsYm1kMGFDQTlQVDBnWkdWc1pYUmxaRWwwWlcxeklDWW1JQ0ZwYm5ObGNuUnpMbXhsYm1kMGFDa2dlMXh1SUNBZ0lDQWdJQ0J5WlhSMWNtNGdlMXh1SUNBZ0lDQWdJQ0FnSUNBZ1kyaHBiR1J5Wlc0NklHNWxkME5vYVd4a2NtVnVMRnh1SUNBZ0lDQWdJQ0FnSUNBZ2JXOTJaWE02SUc1MWJHeGNiaUFnSUNBZ0lDQWdmVnh1SUNBZ0lIMWNibHh1SUNBZ0lISmxkSFZ5YmlCN1hHNGdJQ0FnSUNBZ0lHTm9hV3hrY21WdU9pQnVaWGREYUdsc1pISmxiaXhjYmlBZ0lDQWdJQ0FnYlc5MlpYTTZJSHRjYmlBZ0lDQWdJQ0FnSUNBZ0lISmxiVzkyWlhNNklISmxiVzkyWlhNc1hHNGdJQ0FnSUNBZ0lDQWdJQ0JwYm5ObGNuUnpPaUJwYm5ObGNuUnpYRzRnSUNBZ0lDQWdJSDFjYmlBZ0lDQjlYRzU5WEc1Y2JtWjFibU4wYVc5dUlISmxiVzkyWlNoaGNuSXNJR2x1WkdWNExDQnJaWGtwSUh0Y2JpQWdJQ0JoY25JdWMzQnNhV05sS0dsdVpHVjRMQ0F4S1Z4dVhHNGdJQ0FnY21WMGRYSnVJSHRjYmlBZ0lDQWdJQ0FnWm5KdmJUb2dhVzVrWlhnc1hHNGdJQ0FnSUNBZ0lHdGxlVG9nYTJWNVhHNGdJQ0FnZlZ4dWZWeHVYRzVtZFc1amRHbHZiaUJyWlhsSmJtUmxlQ2hqYUdsc1pISmxiaWtnZTF4dUlDQWdJSFpoY2lCclpYbHpJRDBnZTMxY2JpQWdJQ0IyWVhJZ1puSmxaU0E5SUZ0ZFhHNGdJQ0FnZG1GeUlHeGxibWQwYUNBOUlHTm9hV3hrY21WdUxteGxibWQwYUZ4dVhHNGdJQ0FnWm05eUlDaDJZWElnYVNBOUlEQTdJR2tnUENCc1pXNW5kR2c3SUdrckt5a2dlMXh1SUNBZ0lDQWdJQ0IyWVhJZ1kyaHBiR1FnUFNCamFHbHNaSEpsYmx0cFhWeHVYRzRnSUNBZ0lDQWdJR2xtSUNoamFHbHNaQzVyWlhrcElIdGNiaUFnSUNBZ0lDQWdJQ0FnSUd0bGVYTmJZMmhwYkdRdWEyVjVYU0E5SUdsY2JpQWdJQ0FnSUNBZ2ZTQmxiSE5sSUh0Y2JpQWdJQ0FnSUNBZ0lDQWdJR1p5WldVdWNIVnphQ2hwS1Z4dUlDQWdJQ0FnSUNCOVhHNGdJQ0FnZlZ4dVhHNGdJQ0FnY21WMGRYSnVJSHRjYmlBZ0lDQWdJQ0FnYTJWNWN6b2dhMlY1Y3l3Z0lDQWdJQzh2SUVFZ2FHRnphQ0J2WmlCclpYa2dibUZ0WlNCMGJ5QnBibVJsZUZ4dUlDQWdJQ0FnSUNCbWNtVmxPaUJtY21WbElDQWdJQ0FnTHk4Z1FXNGdZWEp5WVhrZ2IyWWdkVzVyWlhsbFpDQnBkR1Z0SUdsdVpHbGpaWE5jYmlBZ0lDQjlYRzU5WEc1Y2JtWjFibU4wYVc5dUlHRndjR1Z1WkZCaGRHTm9LR0Z3Y0d4NUxDQndZWFJqYUNrZ2UxeHVJQ0FnSUdsbUlDaGhjSEJzZVNrZ2UxeHVJQ0FnSUNBZ0lDQnBaaUFvYVhOQmNuSmhlU2hoY0hCc2VTa3BJSHRjYmlBZ0lDQWdJQ0FnSUNBZ0lHRndjR3g1TG5CMWMyZ29jR0YwWTJncFhHNGdJQ0FnSUNBZ0lIMGdaV3h6WlNCN1hHNGdJQ0FnSUNBZ0lDQWdJQ0JoY0hCc2VTQTlJRnRoY0hCc2VTd2djR0YwWTJoZFhHNGdJQ0FnSUNBZ0lIMWNibHh1SUNBZ0lDQWdJQ0J5WlhSMWNtNGdZWEJ3YkhsY2JpQWdJQ0I5SUdWc2MyVWdlMXh1SUNBZ0lDQWdJQ0J5WlhSMWNtNGdjR0YwWTJoY2JpQWdJQ0I5WEc1OVhHNWNibjBzZTF3aUxpNHZkbTV2WkdVdmFHRnVaR3hsTFhSb2RXNXJYQ0k2TWpRc1hDSXVMaTkyYm05a1pTOXBjeTEwYUhWdWExd2lPakkxTEZ3aUxpNHZkbTV2WkdVdmFYTXRkbTV2WkdWY0lqb3lOeXhjSWk0dUwzWnViMlJsTDJsekxYWjBaWGgwWENJNk1qZ3NYQ0l1TGk5MmJtOWtaUzlwY3kxM2FXUm5aWFJjSWpveU9TeGNJaTR1TDNadWIyUmxMM1p3WVhSamFGd2lPak15TEZ3aUxpOWthV1ptTFhCeWIzQnpYQ0k2TXpRc1hDSjRMV2x6TFdGeWNtRjVYQ0k2TVRKOVhYMHNlMzBzV3pSZEtTZzBLVnh1ZlNrN1hHNWNibVY0Y0c5eWRDQmtaV1poZFd4MElGWnBjblIxWVd4RVQwMDdYRzRpWFN3aWMyOTFjbU5sVW05dmRDSTZJaTl6YjNWeVkyVXZJbjA9XG4iLCJpbXBvcnQgQ29yZSBmcm9tICcuL2xpYi9jb3JlJztcbmltcG9ydCBFbnVtIGZyb20gJy4vbGliL2VudW0nO1xuaW1wb3J0IFZpcnR1YWxET00gZnJvbSAnLi9saWIvdmlydHVhbC1kb20nO1xuXG5leHBvcnQgZGVmYXVsdCB7XG4gIENvcmUsXG4gIEVudW0sXG4gIFZpcnR1YWxET01cbn07XG4vLyMgc291cmNlTWFwcGluZ1VSTD1kYXRhOmFwcGxpY2F0aW9uL2pzb247YmFzZTY0LGV5SjJaWEp6YVc5dUlqb3pMQ0p6YjNWeVkyVnpJanBiSW1Wc2FYaHBjaTVxY3lKZExDSnVZVzFsY3lJNlcxMHNJbTFoY0hCcGJtZHpJam9pUVVGQlFTeFBRVUZQTEVsQlFWQXNUVUZCYVVJc1dVRkJha0k3UVVGRFFTeFBRVUZQTEVsQlFWQXNUVUZCYVVJc1dVRkJha0k3UVVGRFFTeFBRVUZQTEZWQlFWQXNUVUZCZFVJc2JVSkJRWFpDT3p0QlFVVkJMR1ZCUVdVN1FVRkRZaXhOUVVSaE8wRkJSV0lzVFVGR1lUdEJRVWRpTEZsQlNHRTdRMEZCWmlJc0ltWnBiR1VpT2lKbGJHbDRhWEl1YW5NaUxDSnpiM1Z5WTJWelEyOXVkR1Z1ZENJNld5SnBiWEJ2Y25RZ1EyOXlaU0JtY205dElDY3VMMnhwWWk5amIzSmxKenRjYm1sdGNHOXlkQ0JGYm5WdElHWnliMjBnSnk0dmJHbGlMMlZ1ZFcwbk8xeHVhVzF3YjNKMElGWnBjblIxWVd4RVQwMGdabkp2YlNBbkxpOXNhV0l2ZG1seWRIVmhiQzFrYjIwbk8xeHVYRzVsZUhCdmNuUWdaR1ZtWVhWc2RDQjdYRzRnSUVOdmNtVXNYRzRnSUVWdWRXMHNYRzRnSUZacGNuUjFZV3hFVDAxY2JuMDdYRzRpWFN3aWMyOTFjbU5sVW05dmRDSTZJaTl6YjNWeVkyVXZJbjA9XG4iXSwibmFtZXMiOlsiUHJpbWl0aXZlcy5QSUQiLCJUeXBlcy5WYXJpYWJsZSJdLCJtYXBwaW5ncyI6IkFBRUEsTUFBTSxPQUFPLENBQUM7O0VBRVosV0FBVyxHQUFHO0lBQ1osSUFBSSxDQUFDLFFBQVEsR0FBRyxFQUFFLENBQUM7R0FDcEI7O0VBRUQsT0FBTyxDQUFDLE9BQU8sRUFBRTtJQUNmLElBQUksQ0FBQyxRQUFRLENBQUMsSUFBSSxDQUFDLE9BQU8sQ0FBQyxDQUFDO0lBQzVCLE9BQU8sT0FBTyxDQUFDO0dBQ2hCOztFQUVELEdBQUcsR0FBRztJQUNKLE9BQU8sSUFBSSxDQUFDLFFBQVEsQ0FBQztHQUN0Qjs7RUFFRCxPQUFPLEdBQUc7SUFDUixPQUFPLElBQUksQ0FBQyxRQUFRLENBQUMsTUFBTSxLQUFLLENBQUMsQ0FBQztHQUNuQzs7RUFFRCxRQUFRLENB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 \ No newline at end of file diff --git a/test/translator/protocol_test.exs b/test/translator/protocol_test.exs index 9e059915..3602ea0f 100644 --- a/test/translator/protocol_test.exs +++ b/test/translator/protocol_test.exs @@ -25,32 +25,62 @@ defmodule ElixirScript.Translator.Protocol.Test do end js_code = """ - import Elixir$ElixirScript$Kernel from './Elixir.ElixirScript.Kernel'; + import Elixir$ElixirScript$Kernel from './Elixir.ElixirScript.Kernel'; + import Implementations from './Elixir.Blank.Defimpl'; const Elixir$Blank = Elixir.Core.Functions.defprotocol({ - blank__qmark__: function(){} + blank__qmark__: function() { + + } }); - Elixir.Core.Functions.defimpl(Elixir$Blank, Array,{ - blank__qmark__: Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Object.freeze([])],function() { - return true; - }),Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.wildcard()],function() { - return false; - })) - }) - Elixir.Core.Functions.defimpl(Elixir$Blank,Symbol,{ - blank__qmark__: Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([false],function() { + for(let {Type,Implementation} of Implementations) Elixir.Core.Functions.defimpl(Elixir$Blank,Type,Implementation) + export default Elixir$Blank; + + import Elixir$ElixirScript$Kernel from './Elixir.ElixirScript.Kernel'; + const blank__qmark__ = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([false],function() { return true; }),Elixir.Core.Patterns.make_case([null],function() { return true; }),Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.wildcard()],function() { return false; - })) - }) - Elixir.Core.Functions.defimpl(Elixir$Blank, Elixir.Core.Integer, { - blank__qmark__: Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable()],function(number) { + })); + export default { + 'Type': Symbol, 'Implementation': { + blank__qmark__ + } + }; + + import Elixir$ElixirScript$Kernel from './Elixir.ElixirScript.Kernel'; + const blank__qmark__ = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable()],function(number) { return false; - })) - }) - export default Elixir$Blank; + })); + export default { + 'Type': Elixir.Core.Integer, 'Implementation': { + blank__qmark__ + } + }; + + import Elixir$ElixirScript$Kernel from './Elixir.ElixirScript.Kernel'; + const blank__qmark__ = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Object.freeze([])],function() { + return true; + }),Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.wildcard()],function() { + return false; + })); + export default { + 'Type': Array, 'Implementation': { + blank__qmark__ + } + }; + + + + let impls = []; + import Elixir$Blank$DefImpl$Elixir$Atom from './Elixir.Blank.DefImpl.Elixir.Atom'; + impls.push(Elixir$Blank$DefImpl$Elixir$Atom) + import Elixir$Blank$DefImpl$Elixir$Integer from './Elixir.Blank.DefImpl.Elixir.Integer'; + impls.push(Elixir$Blank$DefImpl$Elixir$Integer) + import Elixir$Blank$DefImpl$Elixir$List from './Elixir.Blank.DefImpl.Elixir.List'; + impls.push(Elixir$Blank$DefImpl$Elixir$List) + export default impls; """ assert_translation(ex_ast, js_code) From 4f266886ce20fa9bfaa59ab99a092f6fab303310 Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Mon, 14 Mar 2016 19:17:39 -0500 Subject: [PATCH 182/860] Add compiled stdlib. Add function to compile stdlib and cache state. --- lib/elixir_script.ex | 94 +++++--- lib/elixir_script/cli.ex | 25 ++- lib/elixir_script/translator/protocol.ex | 6 +- lib/elixir_script/translator/state.ex | 14 ++ lib/elixir_script/translator/stdlib_state.exs | Bin 0 -> 129805 bytes lib/elixir_script/translator/utils.ex | 9 + lib/mix/tasks/elixirscript.ex | 2 +- mix.exs | 16 +- priv/Elixir.ElixirScript.Agent.js | 46 ++++ priv/Elixir.ElixirScript.Atom.js | 11 + priv/Elixir.ElixirScript.Base.js | 20 ++ priv/Elixir.ElixirScript.Bitwise.js | 3 + priv/Elixir.ElixirScript.Collectable.js | 10 + priv/Elixir.ElixirScript.Enumerable.js | 14 ++ priv/Elixir.ElixirScript.Integer.js | 32 +++ priv/Elixir.ElixirScript.JS.js | 8 + priv/Elixir.ElixirScript.Kernel.js | 122 ++++++++++ priv/Elixir.ElixirScript.Keyword.js | 41 ++++ priv/Elixir.ElixirScript.List.js | 212 ++++++++++++++++++ priv/Elixir.ElixirScript.Macro.Env.js | 8 + priv/Elixir.ElixirScript.Map.js | 166 ++++++++++++++ priv/Elixir.ElixirScript.MapSet.js | 89 ++++++++ priv/Elixir.ElixirScript.Module.js | 9 + priv/Elixir.ElixirScript.Range.js | 18 ++ ...Script.String.Chars.DefImpl.Elixir.Atom.js | 13 ++ ...t.String.Chars.DefImpl.Elixir.BitString.js | 14 ++ ...cript.String.Chars.DefImpl.Elixir.Float.js | 10 + ...ipt.String.Chars.DefImpl.Elixir.Integer.js | 10 + ...Script.String.Chars.DefImpl.Elixir.List.js | 10 + ...cript.String.Chars.DefImpl.Elixir.Tuple.js | 10 + ...lixir.ElixirScript.String.Chars.DefImpl.js | 15 ++ priv/Elixir.ElixirScript.String.Chars.js | 10 + priv/Elixir.ElixirScript.String.js | 152 +++++++++++++ priv/Elixir.ElixirScript.Tuple.js | 53 +++++ priv/Elixir.ElixirScript.View.js | 45 ++++ 35 files changed, 1271 insertions(+), 46 deletions(-) create mode 100644 lib/elixir_script/translator/stdlib_state.exs create mode 100644 priv/Elixir.ElixirScript.Agent.js create mode 100644 priv/Elixir.ElixirScript.Atom.js create mode 100644 priv/Elixir.ElixirScript.Base.js create mode 100644 priv/Elixir.ElixirScript.Bitwise.js create mode 100644 priv/Elixir.ElixirScript.Collectable.js create mode 100644 priv/Elixir.ElixirScript.Enumerable.js create mode 100644 priv/Elixir.ElixirScript.Integer.js create mode 100644 priv/Elixir.ElixirScript.JS.js create mode 100644 priv/Elixir.ElixirScript.Kernel.js create mode 100644 priv/Elixir.ElixirScript.Keyword.js create mode 100644 priv/Elixir.ElixirScript.List.js create mode 100644 priv/Elixir.ElixirScript.Macro.Env.js create mode 100644 priv/Elixir.ElixirScript.Map.js create mode 100644 priv/Elixir.ElixirScript.MapSet.js create mode 100644 priv/Elixir.ElixirScript.Module.js create mode 100644 priv/Elixir.ElixirScript.Range.js create mode 100644 priv/Elixir.ElixirScript.String.Chars.DefImpl.Elixir.Atom.js create mode 100644 priv/Elixir.ElixirScript.String.Chars.DefImpl.Elixir.BitString.js create mode 100644 priv/Elixir.ElixirScript.String.Chars.DefImpl.Elixir.Float.js create mode 100644 priv/Elixir.ElixirScript.String.Chars.DefImpl.Elixir.Integer.js create mode 100644 priv/Elixir.ElixirScript.String.Chars.DefImpl.Elixir.List.js create mode 100644 priv/Elixir.ElixirScript.String.Chars.DefImpl.Elixir.Tuple.js create mode 100644 priv/Elixir.ElixirScript.String.Chars.DefImpl.js create mode 100644 priv/Elixir.ElixirScript.String.Chars.js create mode 100644 priv/Elixir.ElixirScript.String.js create mode 100644 priv/Elixir.ElixirScript.Tuple.js create mode 100644 priv/Elixir.ElixirScript.View.js diff --git a/lib/elixir_script.ex b/lib/elixir_script.ex index 2ba9e30c..4e69e659 100644 --- a/lib/elixir_script.ex +++ b/lib/elixir_script.ex @@ -33,24 +33,10 @@ defmodule ElixirScript do end end + @external_resource stdlib_state_path = Path.join([__DIR__, "elixir_script", "translator", "stdlib_state.exs"]) + @stdlib_state File.read!(stdlib_state_path) - # At compile time, gathers the files containing the standard lib modules, - # converts them to their quoted forms and keeps them in @libs for use when compiling. - - # These are full of macros and would not transpile to anything significant - @modules_to_not_read ["v_dom.ex", "html.ex"] - - @external_resource libs_path = Path.join([__DIR__, "elixir_script", "prelude", "**", "*.ex"]) - @libs Enum.filter(Path.wildcard(libs_path), fn(path) -> - !String.contains?(path, @modules_to_not_read) - end) - |> Enum.map(fn(path) -> - path - |> File.read! - |> Code.string_to_quoted! - end) - - @js_core_path "/Elixir.js" + @js_core_path "/*.js" @doc """ Compiles the given Elixir code string @@ -81,16 +67,38 @@ defmodule ElixirScript do do_compile(opts, code) end - defp do_compile(opts, quoted_code_list) do - compiler_opts = build_compiler_options(opts) - libs = update_quoted(@libs) + def compile_std_lib() do + compiler_opts = build_compiler_options(%{std_lib: true, include_path: true}) + libs_path = Path.join([__DIR__, "elixir_script", "prelude", "**", "*.ex"]) + code = Path.wildcard(libs_path) + |> Enum.filter(fn(path) -> + !String.contains?(path, ["v_dom.ex", "html.ex"]) + end) + |> Enum.map(&file_to_quoted/1) ElixirScript.Translator.State.start_link(compiler_opts) + ModuleCollector.process_modules(Enum.map(code, &update_quoted(&1))) + code = create_code(compiler_opts) + new_std_state = ElixirScript.Translator.State.serialize() + ElixirScript.Translator.State.stop - ModuleCollector.process_modules(libs ++ Enum.map(quoted_code_list, &update_quoted(&1))) + File.write!(File.cwd!() <> "/lib/elixir_script/translator/stdlib_state.exs", new_std_state) - code = create_code(compiler_opts) + output_path = File.cwd!() <> "/priv" + + Enum.filter(code, fn({path, _}) -> !String.contains?(path, "ElixirScript.Temp.js") end) + |> Enum.each(fn(x) -> + ElixirScript.CLI.write_to_file(x, output_path) + end) + end + + defp do_compile(opts, quoted_code_list) do + compiler_opts = build_compiler_options(opts) + ElixirScript.Translator.State.start_link(compiler_opts) + ElixirScript.Translator.State.deserialize(@stdlib_state) + ModuleCollector.process_modules(Enum.map(quoted_code_list, &update_quoted(&1))) + code = create_code(compiler_opts) ElixirScript.Translator.State.stop code @@ -145,9 +153,9 @@ defmodule ElixirScript do |> Enum.reject(fn(ast) -> name = Atom.to_string(ast.name) |> String.replace("Elixir.", "") cond do - compiler_opts.import_standard_libs == false and name in standard_lib_modules -> + Map.get(compiler_opts, :std_lib, false) == false and name in standard_lib_modules -> true - compiler_opts.import_standard_libs == false and ast.type == :protocol_implementation and String.starts_with?(name, standard_lib_modules) -> + Map.get(compiler_opts, :std_lib, false) == false and ast.type == :protocol_implementation and String.starts_with?(name, standard_lib_modules) -> true true -> false @@ -186,7 +194,7 @@ defmodule ElixirScript do end) defimpls = Enum.map(protocols, fn({protocol, implementations}) -> - ElixirScript.Translator.Protocol.make_defimpl(protocol, implementations) + ElixirScript.Translator.Protocol.make_defimpl(protocol, implementations, state.compiler_opts) end) |> Enum.map(fn(module) -> { path, code, _, _ } = convert_to_code(module) @@ -203,24 +211,54 @@ defmodule ElixirScript do false -> code end - end) + end) result end + def update_protocols(path, compiler_opts) do + result = Enum.filter(Path.wildcard(path), fn(js_file_path) -> + String.contains?(js_file_path, ".DefImpl") + end) + |> Enum.reduce(%{}, fn(js_file_path, state) -> + case String.split(js_file_path, ".DefImpl.") do + [protocol, "js"] -> + protocol = String.split(protocol, "/") |> List.last |> String.to_atom + Map.put(state, protocol, Map.get(state, protocol, [])) + [protocol, impl] -> + protocol = String.split(protocol, "/") |> List.last |> String.to_atom + impl = String.replace(impl, ".js", "") |> String.to_atom + Map.put(state, protocol, Map.get(state, protocol, []) ++ [impl]) + end + end) + |> Enum.map(fn {protocol, implementations} -> + ElixirScript.Translator.Protocol.make_defimpl(protocol, implementations, compiler_opts) + end) + |> Enum.map(fn(module) -> + { path, code, _, _ } = convert_to_code(module) + {path, code} + end) + + end + @doc """ Copies the javascript that makes up the ElixirScript core to the specified location """ def copy_core_to_destination(destination) do - File.cp!(operating_path <> @js_core_path, destination <> @js_core_path) + Enum.each(Path.wildcard(operating_path <> @js_core_path), fn(path) -> + base = Path.basename(path) + File.cp!(path, Path.join([destination, base])) + end) end @doc """ Returns the elixirscript core js code """ def elixirscript_core() do - File.read!(operating_path <> @js_core_path) + Enum.each(Path.wildcard(operating_path <> @js_core_path), fn(path) -> + File.read!(path) + end) end defp convert_to_code(js_ast) do diff --git a/lib/elixir_script/cli.ex b/lib/elixir_script/cli.ex index 40548fb4..9ae59e12 100644 --- a/lib/elixir_script/cli.ex +++ b/lib/elixir_script/cli.ex @@ -3,7 +3,7 @@ defmodule ElixirScript.CLI do @switches [ output: :binary, elixir: :boolean, root: :binary, - help: :boolean, core: :boolean, core_path: :binary + help: :boolean, core_path: :binary, std_lib: :binary ] @aliases [ @@ -37,15 +37,15 @@ defmodule ElixirScript.CLI do -o --output [path] places output at the given path -ex --elixir read input as elixir code string -r --root [path] root import path for all exported modules - --core outputs the elixirscript core JavaScript file + --std_lib [path] outputs the elixirscript standard library JavaScript files to the specified path --core_path es6 import path to the elixirscript standard lib only used with the [output] option. When used, Elixir.js is not exported -h --help this message """ end - def process(:core) do - IO.write(ElixirScript.elixirscript_core) + def process([std_lib: path]) do + ElixirScript.copy_core_to_destination(path) end def process({ input, options }) do @@ -72,18 +72,23 @@ defmodule ElixirScript.CLI do case options[:output] do nil -> - Enum.map(compile_output, - fn - ({path, code})-> "//#{path}:ENDFILENAME\n" <> code - end) - |> Enum.join("//:ENDFILE\n") - |> IO.write + Enum.each(compile_output, + fn + {_, code} -> + IO.write(code) + end) output_path -> Enum.each(compile_output, fn(x) -> write_to_file(x, output_path) end) + ElixirScript.update_protocols(Path.join(output_path, "*.js"), compile_opts) + |> Enum.each(fn + x -> + write_to_file(x, output_path) + end) + if options[:core_path] == nil do ElixirScript.copy_core_to_destination(output_path) end diff --git a/lib/elixir_script/translator/protocol.ex b/lib/elixir_script/translator/protocol.ex index 0aa0b580..1558bb7b 100644 --- a/lib/elixir_script/translator/protocol.ex +++ b/lib/elixir_script/translator/protocol.ex @@ -93,8 +93,8 @@ defmodule ElixirScript.Translator.Protocol do Makes the protocol implementation module for the given implementation name. This is used to consolidate all of the protocol implementations. """ - def make_defimpl(name, implementations \\ []) do - imports = Module.make_std_lib_import() + def make_defimpl(name, implementations \\ [], compiler_opts) do + imports = [ModuleSystems.import_module(:Elixir, Utils.make_local_file_path(compiler_opts.core_path, compiler_opts.root))] declarator = JS.variable_declarator( JS.identifier("impls"), @@ -107,7 +107,7 @@ defmodule ElixirScript.Translator.Protocol do body = Enum.flat_map(implementations, fn(x) -> name = Utils.name_to_js_name(x) - imports = ModuleSystems.import_module(name, Utils.make_local_file_path(Utils.name_to_js_file_name(x))) + imports = ModuleSystems.import_module(name, Utils.make_local_file_path(Utils.name_to_js_file_name(x), compiler_opts.root)) call = JS.call_expression( JS.member_expression( JS.identifier("impls"), diff --git a/lib/elixir_script/translator/state.ex b/lib/elixir_script/translator/state.ex index 4ef9bfb9..91267576 100644 --- a/lib/elixir_script/translator/state.ex +++ b/lib/elixir_script/translator/state.ex @@ -15,6 +15,20 @@ defmodule ElixirScript.Translator.State do end, name: __MODULE__) end + def serialize() do + Agent.get(__MODULE__, fn(state) -> + :erlang.term_to_binary(state) + end) + end + + def deserialize(frozen_state) do + Agent.update(__MODULE__, fn state -> + frozen_state = :erlang.binary_to_term(frozen_state) + modules = Map.delete(frozen_state.modules, ElixirScript.Temp) + %{ state | modules: modules, std_lib_map: frozen_state.std_lib_map } + end) + end + defp build_standard_lib_map() do Map.new |> Map.put(Kernel, ElixirScript.Kernel) diff --git a/lib/elixir_script/translator/stdlib_state.exs b/lib/elixir_script/translator/stdlib_state.exs new file mode 100644 index 0000000000000000000000000000000000000000..10cefd8223d02c611ba4b9890c12eb5b3ef4c595 GIT binary patch literal 129805 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 + "./" <> file_name + root -> + root <> "/" <> file_name + end + end + end diff --git a/lib/mix/tasks/elixirscript.ex b/lib/mix/tasks/elixirscript.ex index 65eca9f9..16090784 100644 --- a/lib/mix/tasks/elixirscript.ex +++ b/lib/mix/tasks/elixirscript.ex @@ -8,7 +8,7 @@ defmodule Mix.Tasks.Elixirscript do -o --output [path] places output at the given path -ex --elixir read input as elixir code string -r --root [path] root import path for all exported modules - --core outputs the elixirscript core JavaScript file + --std_lib [path] outputs the elixirscript standard library JavaScript files to the specified path --core_path es6 import path to the elixirscript standard lib only used with the [output] option. When used, elixir.js is not exported -h --help this message diff --git a/mix.exs b/mix.exs index e7bd9da6..d1b25d8b 100644 --- a/mix.exs +++ b/mix.exs @@ -60,7 +60,14 @@ defmodule ElixirScript.Mixfile do defp aliases do [dist: &dist/1, - install: &install/1] + install: &install/1, + std_lib: &std_lib/1] + end + + def std_lib(_) do + Mix.Task.run "app.start" + { _ , _ } = System.cmd("npm", ["run", "build"]) + ElixirScript.compile_std_lib() end def dist(_) do @@ -76,11 +83,12 @@ defmodule ElixirScript.Mixfile do File.rm_rf(dist_folder) end - { _ , _ } = System.cmd("npm", ["run", "build"]) - File.mkdir_p(folder_name <> "/bin") File.cp!("elixirscript", "#{folder_name}/bin/elixirscript") - File.cp!("priv/Elixir.js", "#{folder_name}/Elixir.js") + if File.exists?("priv/.DS_Store") do + File.rm!("priv/.DS_Store") + end + File.cp_r!("priv/", "#{folder_name}") File.cp!("LICENSE", "#{folder_name}/LICENSE") System.cmd("tar", ["czf", archive_file_name, folder_name]) diff --git a/priv/Elixir.ElixirScript.Agent.js b/priv/Elixir.ElixirScript.Agent.js new file mode 100644 index 00000000..7ffc9e9a --- /dev/null +++ b/priv/Elixir.ElixirScript.Agent.js @@ -0,0 +1,46 @@ + import Elixir from './Elixir'; + import Elixir$ElixirScript$Kernel from './Elixir.ElixirScript.Kernel'; + import Elixir$ElixirScript$JS from './Elixir.ElixirScript.JS'; + import Elixir$ElixirScript$Keyword from './Elixir.ElixirScript.Keyword'; + const update = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable(), Elixir.Core.Patterns.variable()],function(agent,fun) { + let [current_state] = Elixir.Core.Patterns.match(Elixir.Core.Patterns.variable(),Elixir.Core.Functions.call_property(Elixir.Core.Functions.call_property(Elixir$ElixirScript$JS,'global'),'processes').get(agent,'state')); + Elixir.Core.Functions.call_property(Elixir.Core.Functions.call_property(Elixir$ElixirScript$JS,'global'),'processes').put(agent,'state',fun(current_state)); + return Symbol.for('ok'); + })); + const get_and_update = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable(), Elixir.Core.Patterns.variable()],function(agent,fun) { + let [current_state] = Elixir.Core.Patterns.match(Elixir.Core.Patterns.variable(),Elixir.Core.Functions.call_property(Elixir.Core.Functions.call_property(Elixir$ElixirScript$JS,'global'),'processes').get(agent,'state')); + let [val,new_state] = Elixir.Core.Patterns.match(Elixir.Core.Patterns.type(Elixir.Core.Tuple,{ + values: [Elixir.Core.Patterns.variable(), Elixir.Core.Patterns.variable()] + }),fun(current_state)); + let _ref = new Elixir.Core.Tuple(val,new_state); + Elixir.Core.Functions.call_property(Elixir.Core.Functions.call_property(Elixir$ElixirScript$JS,'global'),'processes').put(agent,'state',new_state); + return val; + })); + const start = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable()],function(fun) { + let [pid] = Elixir.Core.Patterns.match(Elixir.Core.Patterns.variable(),Elixir.Core.Functions.call_property(Elixir.Core.Functions.call_property(Elixir.Core.Functions.call_property(Elixir$ElixirScript$JS,'global'),'processes'),'spawn')); + Elixir.Core.Functions.call_property(Elixir.Core.Functions.call_property(Elixir$ElixirScript$JS,'global'),'processes').put(pid,'state',fun()); + return new Elixir.Core.Tuple(Symbol.for('ok'),pid); + }),Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable(), Elixir.Core.Patterns.variable()],function(fun,options) { + let [pid] = Elixir.Core.Patterns.match(Elixir.Core.Patterns.variable(),Elixir.Core.Functions.call_property(Elixir.Core.Functions.call_property(Elixir.Core.Functions.call_property(Elixir$ElixirScript$JS,'global'),'processes'),'spawn')); + Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable()],function(x) { + return null; + },function(x) { + return Elixir.Enum.member__qmark__(Object.freeze([false, null]),x); + }),Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.wildcard()],function() { + let [pid1] = Elixir.Core.Patterns.match(Elixir.Core.Patterns.variable(),Elixir.Core.Functions.call_property(Elixir.Core.Functions.call_property(Elixir$ElixirScript$JS,'global'),'processes').register(Elixir$ElixirScript$Keyword.get(options,Symbol.for('name')),pid)); + return pid1; + })).call(this,Elixir$ElixirScript$Keyword.has_key__qmark__(options,Symbol.for('name'))); + Elixir.Core.Functions.call_property(Elixir.Core.Functions.call_property(Elixir$ElixirScript$JS,'global'),'processes').put(pid,'state',fun()); + return new Elixir.Core.Tuple(Symbol.for('ok'),pid); + })); + const get = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable(), Elixir.Core.Patterns.variable()],function(agent,fun) { + let [current_state] = Elixir.Core.Patterns.match(Elixir.Core.Patterns.variable(),Elixir.Core.Functions.call_property(Elixir.Core.Functions.call_property(Elixir$ElixirScript$JS,'global'),'processes').get(agent,'state')); + return fun(current_state); + })); + const stop = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable()],function(view) { + Elixir.Core.Functions.call_property(Elixir.Core.Functions.call_property(Elixir$ElixirScript$JS,'global'),'processes').exit(view); + return Symbol.for('ok'); + })); + export default { + update, get_and_update, start, get, stop + }; \ No newline at end of file diff --git a/priv/Elixir.ElixirScript.Atom.js b/priv/Elixir.ElixirScript.Atom.js new file mode 100644 index 00000000..ae19da2a --- /dev/null +++ b/priv/Elixir.ElixirScript.Atom.js @@ -0,0 +1,11 @@ + import Elixir from './Elixir'; + import Elixir$ElixirScript$Kernel from './Elixir.ElixirScript.Kernel'; + const to_string = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable()],function(atom) { + return Symbol.keyFor(atom); + })); + const to_char_list = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable()],function(atom) { + return to_string.split(''); + })); + export default { + to_string, to_char_list + }; \ No newline at end of file diff --git a/priv/Elixir.ElixirScript.Base.js b/priv/Elixir.ElixirScript.Base.js new file mode 100644 index 00000000..4c3ba1a4 --- /dev/null +++ b/priv/Elixir.ElixirScript.Base.js @@ -0,0 +1,20 @@ + import Elixir from './Elixir'; + import Elixir$ElixirScript$Kernel from './Elixir.ElixirScript.Kernel'; + const encode64 = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable()],function(data) { + return Elixir.Core.b64EncodeUnicode(data); + })); + const decode64 = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable()],function(data) { + return Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable()],function(x) { + return Symbol.for('error'); + },function(x) { + return Elixir.Enum.member__qmark__(Object.freeze([false, null]),x); + }),Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.wildcard()],function() { + return new Elixir.Core.Tuple(Symbol.for('ok'),decode64__emark__(data)); + })).call(this,Elixir.Core.can_decode64(data)); + })); + const decode64__emark__ = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable()],function(data) { + return Elixir.Core.Functions.call_property(Elixir.Core,'get_global').atob(data); + })); + export default { + encode64, decode64, decode64__emark__ + }; \ No newline at end of file diff --git a/priv/Elixir.ElixirScript.Bitwise.js b/priv/Elixir.ElixirScript.Bitwise.js new file mode 100644 index 00000000..d6e70174 --- /dev/null +++ b/priv/Elixir.ElixirScript.Bitwise.js @@ -0,0 +1,3 @@ + import Elixir from './Elixir'; + import Elixir$ElixirScript$Kernel from './Elixir.ElixirScript.Kernel'; + export default {}; \ No newline at end of file diff --git a/priv/Elixir.ElixirScript.Collectable.js b/priv/Elixir.ElixirScript.Collectable.js new file mode 100644 index 00000000..43c25626 --- /dev/null +++ b/priv/Elixir.ElixirScript.Collectable.js @@ -0,0 +1,10 @@ + import Elixir from './Elixir'; + import Elixir$ElixirScript$Kernel from './Elixir.ElixirScript.Kernel'; + import Implementations from './Elixir.ElixirScript.Collectable.Defimpl'; + const Elixir$ElixirScript$Collectable = Elixir.Core.Functions.defprotocol({ + into: function() { + + } + }); + for(let {Type,Implementation} of Implementations) Elixir.Core.Functions.defimpl(Elixir$ElixirScript$Collectable,Type,Implementation) + export default Elixir$ElixirScript$Collectable; \ No newline at end of file diff --git a/priv/Elixir.ElixirScript.Enumerable.js b/priv/Elixir.ElixirScript.Enumerable.js new file mode 100644 index 00000000..1a3edc59 --- /dev/null +++ b/priv/Elixir.ElixirScript.Enumerable.js @@ -0,0 +1,14 @@ + import Elixir from './Elixir'; + import Elixir$ElixirScript$Kernel from './Elixir.ElixirScript.Kernel'; + import Implementations from './Elixir.ElixirScript.Enumerable.Defimpl'; + const Elixir$ElixirScript$Enumerable = Elixir.Core.Functions.defprotocol({ + reduce: function() { + + }, member__qmark__: function() { + + }, count: function() { + + } + }); + for(let {Type,Implementation} of Implementations) Elixir.Core.Functions.defimpl(Elixir$ElixirScript$Enumerable,Type,Implementation) + export default Elixir$ElixirScript$Enumerable; \ No newline at end of file diff --git a/priv/Elixir.ElixirScript.Integer.js b/priv/Elixir.ElixirScript.Integer.js new file mode 100644 index 00000000..e29e47c1 --- /dev/null +++ b/priv/Elixir.ElixirScript.Integer.js @@ -0,0 +1,32 @@ + import Elixir from './Elixir'; + import Elixir$ElixirScript$Kernel from './Elixir.ElixirScript.Kernel'; + const is_even = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable()],function(number) { + return number % 2 == 0; + })); + const parse = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable()],function(bin) { + let [result] = Elixir.Core.Patterns.match(Elixir.Core.Patterns.variable(),Elixir.Core.Functions.call_property(Elixir.Core.Functions,'get_global').parseInt(bin)); + return Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable()],function(x) { + return Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable()],function(index_of_dot) { + return new Elixir.Core.Tuple(result,''); + },function(index_of_dot) { + return index_of_dot < 0; + }),Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable()],function(index_of_dot) { + return new Elixir.Core.Tuple(result,bin.substring(index_of_dot)); + })).call(this,bin.indexOf('.')); + },function(x) { + return Elixir.Enum.member__qmark__(Object.freeze([false, null]),x); + }),Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.wildcard()],function() { + return Symbol.for('error'); + })).call(this,Elixir.Core.Functions.call_property(Elixir.Core.Functions,'get_global').isNaN(result)); + })); + const is_odd = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable()],function(number) { + return number % 2 != 0; + })); + const to_char_list = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable()],function(number) { + return to_char_list(number,10); + }),Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable(), Elixir.Core.Patterns.variable()],function(number,base) { + return number.toString(base).split(Object.freeze([])); + })); + export default { + is_even, parse, is_odd, to_char_list + }; \ No newline at end of file diff --git a/priv/Elixir.ElixirScript.JS.js b/priv/Elixir.ElixirScript.JS.js new file mode 100644 index 00000000..f56c8f48 --- /dev/null +++ b/priv/Elixir.ElixirScript.JS.js @@ -0,0 +1,8 @@ + import Elixir from './Elixir'; + import Elixir$ElixirScript$Kernel from './Elixir.ElixirScript.Kernel'; + const global = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([],function() { + return Elixir.Core.Functions.call_property(Elixir.Core.Functions,'get_global'); + })); + export default { + global + }; \ No newline at end of file diff --git a/priv/Elixir.ElixirScript.Kernel.js b/priv/Elixir.ElixirScript.Kernel.js new file mode 100644 index 00000000..632ce36b --- /dev/null +++ b/priv/Elixir.ElixirScript.Kernel.js @@ -0,0 +1,122 @@ + import Elixir from './Elixir'; + import Elixir$ElixirScript$Atom from './Elixir.ElixirScript.Atom'; + const build_if = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable(), Object.freeze([Elixir.Core.Patterns.type(Elixir.Core.Tuple,{ + values: [Symbol.for('do'), Elixir.Core.Patterns.variable()] + })])],function(condition,do_clause) { + return build_if(condition,Object.freeze([new Elixir.Core.Tuple(Symbol.for('do'),do_clause), new Elixir.Core.Tuple(Symbol.for('else'),null)])); + }),Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable(), Object.freeze([Elixir.Core.Patterns.type(Elixir.Core.Tuple,{ + values: [Symbol.for('do'), Elixir.Core.Patterns.variable()] + }), Elixir.Core.Patterns.type(Elixir.Core.Tuple,{ + values: [Symbol.for('else'), Elixir.Core.Patterns.variable()] + })])],function(condition,do_clause,else_clause) { + return new Elixir.Core.Tuple(Symbol.for('case'),Object.freeze([new Elixir.Core.Tuple(Symbol.for('line'),15)]),Object.freeze([condition, Object.freeze([new Elixir.Core.Tuple(Symbol.for('do'),Object.freeze([new Elixir.Core.Tuple(Symbol.for('->'),Object.freeze([new Elixir.Core.Tuple(Symbol.for('line'),16)]),Object.freeze([Object.freeze([new Elixir.Core.Tuple(Symbol.for('when'),Object.freeze([new Elixir.Core.Tuple(Symbol.for('line'),16)]),Object.freeze([new Elixir.Core.Tuple(Symbol.for('x'),Object.freeze([new Elixir.Core.Tuple(Symbol.for('line'),16)]),null), new Elixir.Core.Tuple(Symbol.for('in'),Object.freeze([new Elixir.Core.Tuple(Symbol.for('line'),16)]),Object.freeze([new Elixir.Core.Tuple(Symbol.for('x'),Object.freeze([new Elixir.Core.Tuple(Symbol.for('line'),16)]),null), Object.freeze([false, null])]))]))]), else_clause])), new Elixir.Core.Tuple(Symbol.for('->'),Object.freeze([new Elixir.Core.Tuple(Symbol.for('line'),18)]),Object.freeze([Object.freeze([new Elixir.Core.Tuple(Symbol.for('_'),Object.freeze([new Elixir.Core.Tuple(Symbol.for('line'),18)]),null)]), do_clause]))]))])])); + })); + const build_unless = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable(), Object.freeze([Elixir.Core.Patterns.type(Elixir.Core.Tuple,{ + values: [Symbol.for('do'), Elixir.Core.Patterns.variable()] + })])],function(condition,do_clause) { + return build_unless(condition,Object.freeze([new Elixir.Core.Tuple(Symbol.for('do'),do_clause), new Elixir.Core.Tuple(Symbol.for('else'),null)])); + }),Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable(), Object.freeze([Elixir.Core.Patterns.type(Elixir.Core.Tuple,{ + values: [Symbol.for('do'), Elixir.Core.Patterns.variable()] + }), Elixir.Core.Patterns.type(Elixir.Core.Tuple,{ + values: [Symbol.for('else'), Elixir.Core.Patterns.variable()] + })])],function(condition,do_clause,else_clause) { + return new Elixir.Core.Tuple(Symbol.for('if'),Object.freeze([new Elixir.Core.Tuple(Symbol.for('line'),34)]),Object.freeze([condition, Object.freeze([new Elixir.Core.Tuple(Symbol.for('do'),else_clause), new Elixir.Core.Tuple(Symbol.for('else'),do_clause)])])); + })); + const is_bitstring = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable()],function(term) { + return is_binary(term) || (term instanceof Elixir.Core.BitString); + })); + const is_boolean = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable()],function(term) { + return (typeof term === 'boolean') || (term instanceof Boolean); + })); + const min = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable(), Elixir.Core.Patterns.variable()],function(first,second) { + return Math.min(first,second); + })); + const is_function = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable()],function(term) { + return is_function(term,0); + }),Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable(), Elixir.Core.Patterns.wildcard()],function(term) { + return (typeof term === 'function') || (term instanceof Function); + })); + const is_atom = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable()],function(term) { + return typeof term === 'symbol'; + })); + const elem = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable(), Elixir.Core.Patterns.variable()],function(tuple,index) { + return Elixir.Core.Functions.apply(tuple,'get',Object.freeze([index])); + })); + const map_size = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable()],function(term) { + return Elixir.Core.Functions.call_property(Object.keys(term),'length'); + })); + const tuple_size = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable()],function(tuple) { + return Elixir.Core.Functions.size(tuple); + })); + const is_tuple = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable()],function(term) { + return term instanceof Elixir.Core.Tuple; + })); + const is_reference = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.wildcard()],function() { + return false; + })); + const binary_part = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable(), Elixir.Core.Patterns.variable(), Elixir.Core.Patterns.variable()],function(binary,start,len) { + return binary.substring(start,len); + })); + const is_nil = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable()],function(term) { + return term === null; + })); + const is_pid = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable()],function(term) { + return term instanceof Elixir.Core.PID; + })); + const tl = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable()],function(list) { + return list.slice(1); + })); + const hd = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable()],function(list) { + return list[0]; + })); + const is_port = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.wildcard()],function() { + return false; + })); + const is_list = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable()],function(term) { + return Array.isArray(term); + })); + const is_float = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable()],function(term) { + return is_number(term) && !Number.isInteger(term); + })); + const round = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable()],function(number) { + return Math.round(number); + })); + const abs = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable()],function(number) { + return Math.abs(number); + })); + const trunc = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable()],function(number) { + return Math.floor(number); + })); + const is_integer = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable()],function(term) { + return Number.isInteger(term); + })); + const is_number = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable()],function(term) { + return (typeof term === 'number') || (term instanceof Number); + })); + const apply = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable(), Elixir.Core.Patterns.variable()],function(fun,args) { + return Elixir.Core.Functions.apply(fun,args); + }),Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable(), Elixir.Core.Patterns.variable(), Elixir.Core.Patterns.variable()],function(module,fun,args) { + let [fun1] = Elixir.Core.Patterns.match(Elixir.Core.Patterns.variable(),Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable()],function(x) { + return fun; + },function(x) { + return Elixir.Enum.member__qmark__(Object.freeze([false, null]),x); + }),Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.wildcard()],function() { + return Elixir$ElixirScript$Atom.to_string(fun); + })).call(this,Elixir.Core.is_atom(fun))); + return Elixir.Core.Functions.apply(module,fun,args); + })); + const is_binary = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable()],function(term) { + return typeof term === 'string'; + })); + const is_map = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable()],function(term) { + return (typeof term === 'object') || (term instanceof Object); + })); + const length = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable()],function(term) { + return Elixir.Core.Functions.call_property(term,'length'); + })); + const max = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable(), Elixir.Core.Patterns.variable()],function(first,second) { + return Math.max(first,second); + })); + export default { + is_bitstring, is_boolean, min, is_function, is_atom, elem, map_size, tuple_size, is_tuple, is_reference, binary_part, is_nil, is_pid, tl, hd, is_port, is_list, is_float, round, abs, trunc, is_integer, is_number, apply, is_binary, is_map, length, max + }; \ No newline at end of file diff --git a/priv/Elixir.ElixirScript.Keyword.js b/priv/Elixir.ElixirScript.Keyword.js new file mode 100644 index 00000000..46266ceb --- /dev/null +++ b/priv/Elixir.ElixirScript.Keyword.js @@ -0,0 +1,41 @@ + import Elixir from './Elixir'; + import Elixir$ElixirScript$Kernel from './Elixir.ElixirScript.Kernel'; + const do_has_key__qmark__ = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Object.freeze([]), Elixir.Core.Patterns.wildcard()],function() { + return false; + }),Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable(), Elixir.Core.Patterns.variable()],function(kw,key) { + return Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.type(Elixir.Core.Tuple,{ + values: [Elixir.Core.Patterns.variable(), Elixir.Core.Patterns.wildcard()] + })],function(the_key) { + return true; + },function(the_key) { + return the_key == key; + }),Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.wildcard()],function() { + return do_has_key__qmark__(Elixir$ElixirScript$Kernel.tl(kw),key); + })).call(this,Elixir$ElixirScript$Kernel.hd(kw)); + })); + const do_get = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable(), Elixir.Core.Patterns.variable()],function(kw,key) { + return Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.type(Elixir.Core.Tuple,{ + values: [Elixir.Core.Patterns.variable(), Elixir.Core.Patterns.variable()] + })],function(kw_key,value) { + return value; + },function(kw_key,value) { + return kw_key == key; + }),Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.wildcard()],function() { + return do_get(Elixir$ElixirScript$Kernel.tl(kw),key); + })).call(this,Elixir$ElixirScript$Kernel.hd(kw)); + })); + const has_key__qmark__ = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable(), Elixir.Core.Patterns.variable()],function(kw,key) { + return do_has_key__qmark__(kw,key); + })); + const get = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable(), Elixir.Core.Patterns.variable()],function(kw,key) { + return get(kw,key,null); + }),Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable(), Elixir.Core.Patterns.variable(), Elixir.Core.Patterns.variable()],function(kw,key,default_value) { + return Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([true],function() { + return do_get(kw,key); + }),Elixir.Core.Patterns.make_case([false],function() { + return default_value; + })).call(this,has_key__qmark__(kw,key)); + })); + export default { + has_key__qmark__, get + }; \ No newline at end of file diff --git a/priv/Elixir.ElixirScript.List.js b/priv/Elixir.ElixirScript.List.js new file mode 100644 index 00000000..3c9c680d --- /dev/null +++ b/priv/Elixir.ElixirScript.List.js @@ -0,0 +1,212 @@ + import Elixir from './Elixir'; + import Elixir$ElixirScript$Kernel from './Elixir.ElixirScript.Kernel'; + const do_flatten = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Object.freeze([]), Elixir.Core.Patterns.variable()],function(flattened_list) { + return flattened_list; + }),Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable(), Elixir.Core.Patterns.variable()],function(list,flattened_list) { + let [flattened_list1] = Elixir.Core.Patterns.match(Elixir.Core.Patterns.variable(),Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable()],function(l) { + return flattened_list.concat(do_flatten(l,Object.freeze([]))); + },function(l) { + return Elixir$ElixirScript$Kernel.is_list(l); + }),Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable()],function(item) { + return flattened_list.concat(Object.freeze([item])); + })).call(this,Elixir$ElixirScript$Kernel.hd(list))); + return do_flatten(Elixir$ElixirScript$Kernel.tl(list),flattened_list); + })); + const do_duplicate = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.wildcard(), 0, Elixir.Core.Patterns.variable()],function(list) { + return list; + }),Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable(), Elixir.Core.Patterns.variable(), Elixir.Core.Patterns.variable()],function(data,size,list) { + return do_duplicate(data,size - 1,list.concat(Object.freeze([data]))); + })); + const do_delete = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable(), Elixir.Core.Patterns.variable(), Elixir.Core.Patterns.variable(), Elixir.Core.Patterns.variable()],function(list,item,current_index,new_list) { + return Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable()],function(x) { + let [new_list1] = Elixir.Core.Patterns.match(Elixir.Core.Patterns.variable(),Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.bound(item)],function() { + return new_list; + }),Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.wildcard()],function() { + return new_list.concat(Object.freeze([list[current_index]])); + })).call(this,list[current_index])); + return do_delete(list,item,current_index + 1,new_list); + },function(x) { + return Elixir.Enum.member__qmark__(Object.freeze([false, null]),x); + }),Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.wildcard()],function() { + return new_list; + })).call(this,current_index == Elixir$ElixirScript$Kernel.length(list)); + })); + const do_keyreplace = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Object.freeze([]), Elixir.Core.Patterns.wildcard(), Elixir.Core.Patterns.wildcard(), Elixir.Core.Patterns.variable(), Elixir.Core.Patterns.wildcard()],function(new_list) { + return new_list; + }),Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable(), Elixir.Core.Patterns.variable(), Elixir.Core.Patterns.variable(), Elixir.Core.Patterns.variable(), Elixir.Core.Patterns.variable()],function(list,key,position,new_list,new_tuple) { + let [current_value] = Elixir.Core.Patterns.match(Elixir.Core.Patterns.variable(),Elixir$ElixirScript$Kernel.hd(list)); + let [new_list1] = Elixir.Core.Patterns.match(Elixir.Core.Patterns.variable(),Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable()],function(x) { + return new_list.concat(Object.freeze([current_value])); + },function(x) { + return Elixir.Enum.member__qmark__(Object.freeze([false, null]),x); + }),Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.wildcard()],function() { + return new_list.concat(Object.freeze([new_tuple])); + })).call(this,Elixir$ElixirScript$Kernel.elem(current_value,position) == key)); + return do_keyreplace(Elixir$ElixirScript$Kernel.tl(list),key,position,new_list,new_tuple); + })); + const do_keydelete = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Object.freeze([]), Elixir.Core.Patterns.wildcard(), Elixir.Core.Patterns.wildcard(), Elixir.Core.Patterns.variable()],function(new_list) { + return new_list; + }),Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable(), Elixir.Core.Patterns.variable(), Elixir.Core.Patterns.variable(), Elixir.Core.Patterns.variable()],function(list,key,position,new_list) { + let [current_value] = Elixir.Core.Patterns.match(Elixir.Core.Patterns.variable(),Elixir$ElixirScript$Kernel.hd(list)); + let [new_list1] = Elixir.Core.Patterns.match(Elixir.Core.Patterns.variable(),Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable()],function(x) { + return new_list.concat(Object.freeze([current_value])); + },function(x) { + return Elixir.Enum.member__qmark__(Object.freeze([false, null]),x); + }),Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.wildcard()],function() { + return new_list; + })).call(this,Elixir$ElixirScript$Kernel.elem(current_value,position) == key)); + return do_keydelete(Elixir$ElixirScript$Kernel.tl(list),key,position,new_list); + })); + const do_delete_at = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable(), Elixir.Core.Patterns.variable(), Elixir.Core.Patterns.variable(), Elixir.Core.Patterns.variable()],function(list,index,current_index,new_list) { + return Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable()],function(x) { + let [new_list1] = Elixir.Core.Patterns.match(Elixir.Core.Patterns.variable(),Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([true],function() { + return new_list; + }),Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.wildcard()],function() { + return new_list.concat(Object.freeze([list[current_index]])); + })).call(this,current_index == index)); + return do_delete_at(list,index,current_index + 1,new_list); + },function(x) { + return Elixir.Enum.member__qmark__(Object.freeze([false, null]),x); + }),Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.wildcard()],function() { + return new_list; + })).call(this,current_index == Elixir$ElixirScript$Kernel.length(list)); + })); + const do_update_at = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable(), Elixir.Core.Patterns.variable(), Elixir.Core.Patterns.variable(), Elixir.Core.Patterns.variable(), Elixir.Core.Patterns.variable()],function(list,index,func,current_index,new_list) { + return Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable()],function(x) { + let [new_list1] = Elixir.Core.Patterns.match(Elixir.Core.Patterns.variable(),Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([true],function() { + return new_list.concat(Object.freeze([func(list[current_index])])); + }),Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.wildcard()],function() { + return new_list.concat(Object.freeze([list[current_index]])); + })).call(this,current_index == index)); + return do_update_at(list,index,func,current_index + 1,new_list); + },function(x) { + return Elixir.Enum.member__qmark__(Object.freeze([false, null]),x); + }),Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.wildcard()],function() { + return new_list; + })).call(this,current_index == Elixir$ElixirScript$Kernel.length(list)); + })); + const do_keyfind = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Object.freeze([]), Elixir.Core.Patterns.wildcard(), Elixir.Core.Patterns.wildcard(), Elixir.Core.Patterns.variable()],function(__default__) { + return __default__; + }),Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable(), Elixir.Core.Patterns.variable(), Elixir.Core.Patterns.variable(), Elixir.Core.Patterns.variable()],function(list,key,position,__default__) { + let [current_value] = Elixir.Core.Patterns.match(Elixir.Core.Patterns.variable(),Elixir$ElixirScript$Kernel.hd(list)); + return Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable()],function(x) { + return do_keyfind(Elixir$ElixirScript$Kernel.tl(list),key,position,__default__); + },function(x) { + return Elixir.Enum.member__qmark__(Object.freeze([false, null]),x); + }),Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.wildcard()],function() { + return current_value; + })).call(this,Elixir$ElixirScript$Kernel.elem(current_value,position) == key); + })); + const do_foldl = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Object.freeze([]), Elixir.Core.Patterns.variable(), Elixir.Core.Patterns.wildcard(), Elixir.Core.Patterns.variable()],function(acc,new_list) { + return new Elixir.Core.Tuple(acc,new_list); + }),Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable(), Elixir.Core.Patterns.variable(), Elixir.Core.Patterns.variable(), Elixir.Core.Patterns.variable()],function(list,acc,func,new_list) { + let [acc1,value] = Elixir.Core.Patterns.match(Elixir.Core.Patterns.type(Elixir.Core.Tuple,{ + values: [Elixir.Core.Patterns.variable(), Elixir.Core.Patterns.variable()] + }),func(Elixir$ElixirScript$Kernel.hd(list),acc)); + let _ref = new Elixir.Core.Tuple(acc1,value); + return do_foldl(Elixir$ElixirScript$Kernel.tl(list),acc,func,new_list.concat(Object.freeze([value]))); + })); + const do_insert_at = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable(), Elixir.Core.Patterns.variable(), Elixir.Core.Patterns.variable(), Elixir.Core.Patterns.variable(), Elixir.Core.Patterns.variable()],function(list,index,value,current_index,new_list) { + return Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable()],function(x) { + let [new_list1] = Elixir.Core.Patterns.match(Elixir.Core.Patterns.variable(),Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([true],function() { + return new_list.concat(Object.freeze([value, list[current_index]])); + }),Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.wildcard()],function() { + return new_list.concat(Object.freeze([list[current_index]])); + })).call(this,current_index == index)); + return do_insert_at(list,index,value,current_index + 1,new_list); + },function(x) { + return Elixir.Enum.member__qmark__(Object.freeze([false, null]),x); + }),Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.wildcard()],function() { + return new_list; + })).call(this,current_index == Elixir$ElixirScript$Kernel.length(list)); + })); + const do_replace_at = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable(), Elixir.Core.Patterns.variable(), Elixir.Core.Patterns.variable(), Elixir.Core.Patterns.variable(), Elixir.Core.Patterns.variable()],function(list,index,value,current_index,new_list) { + return Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable()],function(x) { + let [new_list1] = Elixir.Core.Patterns.match(Elixir.Core.Patterns.variable(),Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([true],function() { + return new_list.concat(Object.freeze([value])); + }),Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.wildcard()],function() { + return new_list.concat(Object.freeze([list[current_index]])); + })).call(this,current_index == index)); + return do_replace_at(list,index,value,current_index + 1,new_list); + },function(x) { + return Elixir.Enum.member__qmark__(Object.freeze([false, null]),x); + }),Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.wildcard()],function() { + return new_list; + })).call(this,current_index == Elixir$ElixirScript$Kernel.length(list)); + })); + const keymember__qmark__ = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable(), Elixir.Core.Patterns.variable(), Elixir.Core.Patterns.variable()],function(list,key,position) { + return keyfind(list,key,position) != null; + })); + const flatten = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable()],function(list) { + return do_flatten(list,Object.freeze([])); + }),Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable(), Elixir.Core.Patterns.variable()],function(list,tail) { + return do_flatten.concat(tail); + })); + const duplicate = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable(), Elixir.Core.Patterns.variable()],function(data,size) { + return do_duplicate(data,size,Object.freeze([])); + })); + const __delete__ = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable(), Elixir.Core.Patterns.variable()],function(list,item) { + return do_delete(list,item,0,Object.freeze([])); + })); + const keydelete = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable(), Elixir.Core.Patterns.variable(), Elixir.Core.Patterns.variable()],function(list,key,position) { + return do_keydelete(list,key,position,Object.freeze([])); + })); + const to_tuple = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable()],function(list) { + return new Elixir.Core.Tuple(...list); + })); + const keyreplace = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable(), Elixir.Core.Patterns.variable(), Elixir.Core.Patterns.variable(), Elixir.Core.Patterns.variable()],function(list,key,position,new_tuple) { + return do_keyreplace(list,key,position,Object.freeze([]),new_tuple); + })); + const append = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable(), Elixir.Core.Patterns.variable()],function(list,term) { + return concat(list,Object.freeze([term])); + })); + const prepend = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable(), Elixir.Core.Patterns.variable()],function(list,term) { + return concat(Object.freeze([term]),list); + })); + const replace_at = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable(), Elixir.Core.Patterns.variable(), Elixir.Core.Patterns.variable()],function(list,index,value) { + return do_replace_at(list,index,value,0,Object.freeze([])); + })); + const keyfind = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable(), Elixir.Core.Patterns.variable(), Elixir.Core.Patterns.variable()],function(list,key,position) { + return do_keyfind(list,key,position,null); + }),Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable(), Elixir.Core.Patterns.variable(), Elixir.Core.Patterns.variable(), Elixir.Core.Patterns.variable()],function(list,key,position,__default__) { + return do_keyfind(list,key,position,__default__); + })); + const foldl = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable(), Elixir.Core.Patterns.variable(), Elixir.Core.Patterns.variable()],function(list,acc,func) { + return do_foldl(list,acc,func,Object.freeze([])); + })); + const first = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable()],function(list) { + return list[0]; + })); + const update_at = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable(), Elixir.Core.Patterns.variable(), Elixir.Core.Patterns.variable()],function(list,index,func) { + return do_update_at(list,index,func,0,Object.freeze([])); + })); + const last = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable()],function(list) { + return list[Elixir$ElixirScript$Kernel.length(list) - 1]; + })); + const insert_at = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable(), Elixir.Core.Patterns.variable(), Elixir.Core.Patterns.variable()],function(list,index,value) { + return do_insert_at(list,index,value,0,Object.freeze([])); + })); + const concat = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable(), Elixir.Core.Patterns.variable()],function(list_a,list_b) { + return list_a.concat(list_b); + })); + const delete_at = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable(), Elixir.Core.Patterns.variable()],function(list,index) { + return do_delete_at(list,index,0,Object.freeze([])); + })); + const foldr = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable(), Elixir.Core.Patterns.variable(), Elixir.Core.Patterns.variable()],function(list,acc,func) { + return do_foldl(Elixir.Core.Functions.call_property(list.concat(Object.freeze([])),'reverse'),acc,func,Object.freeze([])); + })); + const wrap = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable()],function(list) { + return list; + },function(list) { + return Elixir$ElixirScript$Kernel.is_list(list); + }),Elixir.Core.Patterns.make_case([null],function() { + return null; + }),Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable()],function(term) { + return term; + })); + const zip = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable()],function(list_of_lists) { + return Elixir.Core.Functions.zip(list_of_lists); + })); + export default { + keymember__qmark__, flatten, duplicate, __delete__, keydelete, to_tuple, keyreplace, append, prepend, replace_at, keyfind, foldl, first, update_at, last, insert_at, concat, delete_at, foldr, wrap, zip + }; \ No newline at end of file diff --git a/priv/Elixir.ElixirScript.Macro.Env.js b/priv/Elixir.ElixirScript.Macro.Env.js new file mode 100644 index 00000000..46d3279f --- /dev/null +++ b/priv/Elixir.ElixirScript.Macro.Env.js @@ -0,0 +1,8 @@ + import Elixir from './Elixir'; + import Elixir$ElixirScript$Kernel from './Elixir.ElixirScript.Kernel'; + const Elixir$ElixirScript$Macro$Env = Elixir.Core.Functions.defstruct({ + [Symbol.for('__struct__')]: Symbol.for('Elixir.ElixirScript.Macro.Env'), [Symbol.for('module')]: null, [Symbol.for('file')]: null, [Symbol.for('line')]: 0, [Symbol.for('function')]: null, [Symbol.for('context')]: null, [Symbol.for('aliases')]: Object.freeze([]), [Symbol.for('requires')]: Object.freeze([]), [Symbol.for('functions')]: Object.freeze([]), [Symbol.for('macros')]: Object.freeze([]), [Symbol.for('macro_aliases')]: Object.freeze([]), [Symbol.for('context_modules')]: Object.freeze([]), [Symbol.for('vars')]: Object.freeze([]), [Symbol.for('export_vars')]: null, [Symbol.for('lexical_tracker')]: null, [Symbol.for('caller')]: null + }); + export default { + Elixir$ElixirScript$Macro$Env + }; \ No newline at end of file diff --git a/priv/Elixir.ElixirScript.Map.js b/priv/Elixir.ElixirScript.Map.js new file mode 100644 index 00000000..6f1420b8 --- /dev/null +++ b/priv/Elixir.ElixirScript.Map.js @@ -0,0 +1,166 @@ + import Elixir from './Elixir'; + import Elixir$ElixirScript$Kernel from './Elixir.ElixirScript.Kernel'; + import Elixir$ElixirScript$String$Chars from './Elixir.ElixirScript.String.Chars'; + const do_split = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.wildcard(), Object.freeze([]), Elixir.Core.Patterns.variable()],function(split_tuple) { + return split_tuple; + }),Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable(), Elixir.Core.Patterns.variable(), Elixir.Core.Patterns.type(Elixir.Core.Tuple,{ + values: [Elixir.Core.Patterns.variable(), Elixir.Core.Patterns.variable()] + })],function(map,keys,key_map,non_key_map) { + let [key] = Elixir.Core.Patterns.match(Elixir.Core.Patterns.variable(),Elixir$ElixirScript$Kernel.hd(keys)); + let [new_split_tuple] = Elixir.Core.Patterns.match(Elixir.Core.Patterns.variable(),Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([true],function() { + return new Elixir.Core.Tuple(Elixir$ElixirScript$Map.put(key_map,key,map[key]),non_key_map); + }),Elixir.Core.Patterns.make_case([false],function() { + return new Elixir.Core.Tuple(key_map,Elixir$ElixirScript$Map.put(non_key_map,key,map[key])); + })).call(this,Elixir.Core.Functions.contains(key,keys(map)))); + return do_split(map,Elixir$ElixirScript$Kernel.tl(keys),new_split_tuple); + })); + const __new__ = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([],function() { + return Object.freeze({}); + })); + const equal__qmark__ = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable(), Elixir.Core.Patterns.variable()],function(map1,map2) { + return map1 === map2; + })); + const put_new = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable(), Elixir.Core.Patterns.variable(), Elixir.Core.Patterns.variable()],function(map,key,value) { + return Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([true],function() { + return map; + }),Elixir.Core.Patterns.make_case([false],function() { + return Elixir$ElixirScript$Map.put(map,key,value); + })).call(this,Elixir.Core.Functions.contains(key,keys(map))); + })); + const has_key__qmark__ = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable(), Elixir.Core.Patterns.variable()],function(map,key) { + return Elixir.Core.Functions.contains(key,keys(map)); + })); + const size = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable()],function(map) { + return Elixir.Core.Functions.call_property(keys,'length'); + })); + const get_and_update = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable(), Elixir.Core.Patterns.variable(), Elixir.Core.Patterns.variable()],function(map,key,func) { + return Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([true],function() { + return new Elixir.Core.Tuple(null,map); + }),Elixir.Core.Patterns.make_case([false],function() { + let [new_value] = Elixir.Core.Patterns.match(Elixir.Core.Patterns.variable(),func(map[key])); + return new Elixir.Core.Tuple(new_value,Elixir$ElixirScript$Map.put(map,key,new_value)); + })).call(this,Elixir.Core.Functions.contains(key,keys(map))); + })); + const __delete__ = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable(), Elixir.Core.Patterns.variable()],function(map,key) { + return Elixir.Core.Functions.delete_property_from_map(map,key); + })); + const update = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable(), Elixir.Core.Patterns.variable(), Elixir.Core.Patterns.variable(), Elixir.Core.Patterns.variable()],function(map,key,initial,func) { + return Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([true],function() { + return Elixir$ElixirScript$Map.put(map,key,func(map[key])); + }),Elixir.Core.Patterns.make_case([false],function() { + return Elixir$ElixirScript$Map.put(map,key,initial); + })).call(this,Elixir.Core.Functions.contains(key,keys(map))); + })); + const merge = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable(), Elixir.Core.Patterns.variable()],function(map1,map2) { + return Elixir.Core.SpecialForms.map_update(map1,map2); + })); + const take = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable(), Elixir.Core.Patterns.variable()],function(map,keys) { + let [key_map,undefined] = Elixir.Core.Patterns.match(Elixir.Core.Patterns.type(Elixir.Core.Tuple,{ + values: [Elixir.Core.Patterns.variable(), Elixir.Core.Patterns.wildcard()] + }),split(map,keys)); + let _ref = new Elixir.Core.Tuple(key_map,undefined); + return key_map; + })); + const to_list = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable()],function(map) { + return do_to_list(map,Object.freeze([])); + })); + const from_struct = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable()],function(struct) { + return __delete__(Elixir.Core.Functions.class_to_obj(struct),Symbol.for('__struct__')); + })); + const do_to_list = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable(), Elixir.Core.Patterns.variable()],function(map,list) { + return Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([0],function() { + return list; + }),Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.wildcard()],function() { + let [key] = Elixir.Core.Patterns.match(Elixir.Core.Patterns.variable(),Elixir$ElixirScript$Kernel.hd(keys(map))); + let [value] = Elixir.Core.Patterns.match(Elixir.Core.Patterns.variable(),map[key]); + return do_to_list(Elixir$ElixirScript$Map.__delete__(map,key),list.concat(Object.freeze([new Elixir.Core.Tuple(key,value)]))); + })).call(this,size(map)); + })); + const put = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable(), Elixir.Core.Patterns.variable(), Elixir.Core.Patterns.variable()],function(map,key,value) { + return Elixir.Core.Functions.add_property_to_map(map,key,value); + })); + const get = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable(), Elixir.Core.Patterns.variable()],function(map,key) { + return get(map,key,null); + }),Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable(), Elixir.Core.Patterns.variable(), Elixir.Core.Patterns.variable()],function(map,key,default_value) { + return Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([true],function() { + return map[key]; + }),Elixir.Core.Patterns.make_case([false],function() { + return default_value; + })).call(this,Elixir.Core.Functions.contains(key,keys(map))); + })); + const split = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable(), Elixir.Core.Patterns.variable()],function(map,keys) { + return do_split(map,keys,new Elixir.Core.Tuple(Object.freeze({}),Object.freeze({}))); + })); + const keys = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable()],function(map) { + return Elixir.Core.Functions.get_object_keys(map); + })); + const values = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable()],function(map) { + return Object.values(map); + })); + const fetch__emark__ = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable(), Elixir.Core.Patterns.variable()],function(map,key) { + return Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([true],function() { + return map[key]; + }),Elixir.Core.Patterns.make_case([false],function() { + throw { + [Symbol.for('__struct__')]: Symbol.for('RuntimeError'), [Symbol.for('__exception__')]: true, [Symbol.for('message')]: Elixir$ElixirScript$String$Chars.to_string(key) + ' not found in map' + }; + return null; + })).call(this,Elixir.Core.Functions.contains(key,keys(map))); + })); + const pop_lazy = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable(), Elixir.Core.Patterns.variable(), Elixir.Core.Patterns.variable()],function(map,key,func) { + return Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([true],function() { + return new Elixir.Core.Tuple(func(map[key]),Elixir$ElixirScript$Map.__delete__(map,key)); + }),Elixir.Core.Patterns.make_case([false],function() { + return new Elixir.Core.Tuple(func(),map); + })).call(this,Elixir.Core.Functions.contains(key,keys(map))); + })); + const put_new_lazy = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable(), Elixir.Core.Patterns.variable(), Elixir.Core.Patterns.variable()],function(map,key,func) { + return Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([true],function() { + return map; + }),Elixir.Core.Patterns.make_case([false],function() { + return Elixir$ElixirScript$Map.put(map,key,func()); + })).call(this,Elixir.Core.Functions.contains(key,keys(map))); + })); + const get_lazy = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable(), Elixir.Core.Patterns.variable(), Elixir.Core.Patterns.variable()],function(map,key,func) { + return Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([true],function() { + return func(map[key]); + }),Elixir.Core.Patterns.make_case([false],function() { + return func(); + })).call(this,Elixir.Core.Functions.contains(key,keys(map))); + })); + const update__emark__ = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable(), Elixir.Core.Patterns.variable(), Elixir.Core.Patterns.variable()],function(map,key,func) { + return Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([true],function() { + return Elixir$ElixirScript$Map.put(map,key,func(map[key])); + }),Elixir.Core.Patterns.make_case([false],function() { + throw { + [Symbol.for('__struct__')]: Symbol.for('RuntimeError'), [Symbol.for('__exception__')]: true, [Symbol.for('message')]: Elixir$ElixirScript$String$Chars.to_string(key) + ' not found in map' + }; + return null; + })).call(this,Elixir.Core.Functions.contains(key,keys(map))); + })); + const fetch = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable(), Elixir.Core.Patterns.variable()],function(map,key) { + return Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([true],function() { + return new Elixir.Core.Tuple(Symbol.for('ok'),map[key]); + }),Elixir.Core.Patterns.make_case([false],function() { + return Symbol.for('error'); + })).call(this,Elixir.Core.Functions.contains(key,keys(map))); + })); + const drop = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable(), Elixir.Core.Patterns.variable()],function(map,keys) { + let [undefined,non_key_map] = Elixir.Core.Patterns.match(Elixir.Core.Patterns.type(Elixir.Core.Tuple,{ + values: [Elixir.Core.Patterns.wildcard(), Elixir.Core.Patterns.variable()] + }),split(map,keys)); + let _ref = new Elixir.Core.Tuple(undefined,non_key_map); + return non_key_map; + })); + const pop = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable(), Elixir.Core.Patterns.variable()],function(map,key) { + return pop(map,key,null); + }),Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable(), Elixir.Core.Patterns.variable(), Elixir.Core.Patterns.variable()],function(map,key,default_value) { + return Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([true],function() { + return new Elixir.Core.Tuple(map[key],Elixir$ElixirScript$Map.__delete__(map,key)); + }),Elixir.Core.Patterns.make_case([false],function() { + return new Elixir.Core.Tuple(default_value,map); + })).call(this,Elixir.Core.Functions.contains(key,keys(map))); + })); + export default { + __new__, equal__qmark__, put_new, has_key__qmark__, size, get_and_update, __delete__, update, merge, take, to_list, from_struct, do_to_list, put, get, split, keys, values, fetch__emark__, pop_lazy, put_new_lazy, get_lazy, update__emark__, fetch, drop, pop + }; \ No newline at end of file diff --git a/priv/Elixir.ElixirScript.MapSet.js b/priv/Elixir.ElixirScript.MapSet.js new file mode 100644 index 00000000..41ba1408 --- /dev/null +++ b/priv/Elixir.ElixirScript.MapSet.js @@ -0,0 +1,89 @@ + import Elixir from './Elixir'; + import Elixir$ElixirScript$Kernel from './Elixir.ElixirScript.Kernel'; + import Elixir$ElixirScript$List from './Elixir.ElixirScript.List'; + const Elixir$ElixirScript$MapSet = Elixir.Core.Functions.defstruct({ + [Symbol.for('__struct__')]: Symbol.for('Elixir.ElixirScript.MapSet'), [Symbol.for('set')]: Object.freeze([]) + }); + const __new__ = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([],function() { + return Elixir$ElixirScript$MapSet.Elixir$ElixirScript$MapSet.create(Object.freeze({})); + })); + const equal__qmark__ = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable(), Elixir.Core.Patterns.variable()],function(set1,set2) { + return set1 === set2; + })); + const disjoint__qmark__ = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable(), Elixir.Core.Patterns.variable()],function(set1,set2) { + return size(intersection(set1,set2)) == 0; + })); + const member__qmark__ = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable(), Elixir.Core.Patterns.variable()],function(set,term) { + return Elixir.Core.Functions.call_property(set,'set').indexOf(term) >= 0; + })); + const do_subset__qmark__ = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Object.freeze([]), Elixir.Core.Patterns.wildcard()],function() { + return true; + }),Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable(), Elixir.Core.Patterns.variable()],function(set1_list,set2) { + let [term] = Elixir.Core.Patterns.match(Elixir.Core.Patterns.variable(),Elixir$ElixirScript$Kernel.hd(set1_list)); + return Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([false],function() { + return false; + }),Elixir.Core.Patterns.make_case([true],function() { + return do_subset__qmark__(Elixir$ElixirScript$Kernel.tl(set1_list),set2); + })).call(this,member__qmark__(set2,term)); + })); + const subset__qmark__ = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable(), Elixir.Core.Patterns.variable()],function(set1,set2) { + return do_subset__qmark__(to_list(set1),set2); + })); + const intersection = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable(), Elixir.Core.Patterns.variable()],function(set1,set2) { + return do_intersection(to_list(set1),set2,__new__()); + })); + const do_intersection = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Object.freeze([]), Elixir.Core.Patterns.wildcard(), Elixir.Core.Patterns.variable()],function(intersection_set) { + return intersection_set; + }),Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable(), Elixir.Core.Patterns.variable(), Elixir.Core.Patterns.variable()],function(set1_list,set2,intersection_set) { + let [term] = Elixir.Core.Patterns.match(Elixir.Core.Patterns.variable(),Elixir$ElixirScript$Kernel.hd(set1_list)); + return Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([false],function() { + return do_intersection(Elixir$ElixirScript$Kernel.tl(set1_list),set2,intersection_set); + }),Elixir.Core.Patterns.make_case([true],function() { + return do_intersection(Elixir$ElixirScript$Kernel.tl(set1_list),set2,Elixir.Core.SpecialForms.map_update(intersection_set,Object.freeze({ + [Symbol.for('set')]: Elixir.Core.Functions.call_property(intersection_set,'set').concat(Object.freeze([term])) + }))); + })).call(this,member__qmark__(set2,term)); + })); + const union = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable(), Elixir.Core.Patterns.variable()],function(set1,set2) { + return Elixir.Core.SpecialForms.map_update(set1,Object.freeze({ + [Symbol.for('set')]: Elixir.Core.Functions.call_property(set1,'set').concat(Elixir.Core.Functions.call_property(set2,'set')) + })); + })); + const size = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable()],function(set) { + return Elixir$ElixirScript$Kernel.length(Elixir.Core.Functions.call_property(set,'set')); + })); + const do_difference = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Object.freeze([]), Elixir.Core.Patterns.wildcard(), Elixir.Core.Patterns.variable()],function(difference_set) { + return difference_set; + }),Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable(), Elixir.Core.Patterns.variable(), Elixir.Core.Patterns.variable()],function(set1_list,set2,difference_set) { + let [term] = Elixir.Core.Patterns.match(Elixir.Core.Patterns.variable(),Elixir$ElixirScript$Kernel.hd(set1_list)); + return Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([true],function() { + return do_difference(Elixir$ElixirScript$Kernel.tl(set1_list),set2,difference_set); + }),Elixir.Core.Patterns.make_case([false],function() { + return do_difference(Elixir$ElixirScript$Kernel.tl(set1_list),set2,Elixir.Core.SpecialForms.map_update(difference_set,Object.freeze({ + [Symbol.for('set')]: Elixir.Core.Functions.call_property(difference_set,'set').concat(Object.freeze([term])) + }))); + })).call(this,member__qmark__(set2,term)); + })); + const __delete__ = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable(), Elixir.Core.Patterns.variable()],function(set,term) { + return Elixir.Core.SpecialForms.map_update(set,Object.freeze({ + [Symbol.for('set')]: Elixir$ElixirScript$List.remove(Elixir.Core.Functions.call_property(set,'set'),term) + })); + })); + const difference = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable(), Elixir.Core.Patterns.variable()],function(set1,set2) { + return do_difference(to_list(set1),set2,__new__()); + })); + const to_list = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable()],function(set) { + return Elixir.Core.Functions.call_property(set,'set'); + })); + const put = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable(), Elixir.Core.Patterns.variable()],function(set,term) { + return Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([false],function() { + return Elixir.Core.SpecialForms.map_update(set,Object.freeze({ + [Symbol.for('set')]: Elixir.Core.Functions.call_property(set,'set').concat(term) + })); + }),Elixir.Core.Patterns.make_case([true],function() { + return set; + })).call(this,member__qmark__(set,term)); + })); + export default { + Elixir$ElixirScript$MapSet, __new__, equal__qmark__, disjoint__qmark__, member__qmark__, do_subset__qmark__, subset__qmark__, intersection, do_intersection, union, size, do_difference, __delete__, difference, to_list, put + }; \ No newline at end of file diff --git a/priv/Elixir.ElixirScript.Module.js b/priv/Elixir.ElixirScript.Module.js new file mode 100644 index 00000000..8da28675 --- /dev/null +++ b/priv/Elixir.ElixirScript.Module.js @@ -0,0 +1,9 @@ + import Elixir from './Elixir'; + import Elixir$ElixirScript$Kernel from './Elixir.ElixirScript.Kernel'; + import Elixir$ElixirScript$Keyword from './Elixir.ElixirScript.Keyword'; + const Elixir$ElixirScript$Module = Elixir.Core.Functions.defstruct({ + [Symbol.for('__struct__')]: Symbol.for('Elixir.ElixirScript.Module'), [Symbol.for('name')]: null, [Symbol.for('functions')]: Elixir.Core.Functions.call_property(Elixir$ElixirScript$Keyword,'new'), [Symbol.for('private_functions')]: Elixir.Core.Functions.call_property(Elixir$ElixirScript$Keyword,'new'), [Symbol.for('macros')]: Elixir.Core.Functions.call_property(Elixir$ElixirScript$Keyword,'new'), [Symbol.for('private_macros')]: Elixir.Core.Functions.call_property(Elixir$ElixirScript$Keyword,'new'), [Symbol.for('body')]: null, [Symbol.for('js_imports')]: Object.freeze([]), [Symbol.for('module_refs')]: Object.freeze([]), [Symbol.for('type')]: Symbol.for('module'), [Symbol.for('impls')]: Elixir.Core.Functions.call_property(HashDict,'new'), [Symbol.for('impl_type')]: null + }); + export default { + Elixir$ElixirScript$Module + }; \ No newline at end of file diff --git a/priv/Elixir.ElixirScript.Range.js b/priv/Elixir.ElixirScript.Range.js new file mode 100644 index 00000000..cb324f83 --- /dev/null +++ b/priv/Elixir.ElixirScript.Range.js @@ -0,0 +1,18 @@ + import Elixir from './Elixir'; + import Elixir$ElixirScript$Kernel from './Elixir.ElixirScript.Kernel'; + const Elixir$ElixirScript$Range = Elixir.Core.Functions.defstruct({ + [Symbol.for('__struct__')]: Symbol.for('Elixir.ElixirScript.Range'), [Symbol.for('first')]: null, [Symbol.for('last')]: null + }); + const __new__ = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable(), Elixir.Core.Patterns.variable()],function(first,last) { + return Elixir$ElixirScript$Range.Elixir$ElixirScript$Range.create(Object.freeze({ + [Symbol.for('first')]: first, [Symbol.for('last')]: last + })); + })); + const range__qmark__ = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.type(Elixir$ElixirScript$Range.Elixir$ElixirScript$Range,{})],function() { + return true; + }),Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.wildcard()],function() { + return false; + })); + export default { + Elixir$ElixirScript$Range, __new__, range__qmark__ + }; \ No newline at end of file diff --git a/priv/Elixir.ElixirScript.String.Chars.DefImpl.Elixir.Atom.js b/priv/Elixir.ElixirScript.String.Chars.DefImpl.Elixir.Atom.js new file mode 100644 index 00000000..b7e08aba --- /dev/null +++ b/priv/Elixir.ElixirScript.String.Chars.DefImpl.Elixir.Atom.js @@ -0,0 +1,13 @@ + import Elixir from './Elixir'; + import Elixir$ElixirScript$Kernel from './Elixir.ElixirScript.Kernel'; + import Elixir$ElixirScript$Atom from './Elixir.ElixirScript.Atom'; + const to_string = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([null],function() { + return ''; + }),Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable()],function(atom) { + return Elixir$ElixirScript$Atom.to_string(atom); + })); + export default { + 'Type': Symbol, 'Implementation': { + to_string + } + }; \ No newline at end of file diff --git a/priv/Elixir.ElixirScript.String.Chars.DefImpl.Elixir.BitString.js b/priv/Elixir.ElixirScript.String.Chars.DefImpl.Elixir.BitString.js new file mode 100644 index 00000000..b2e6f708 --- /dev/null +++ b/priv/Elixir.ElixirScript.String.Chars.DefImpl.Elixir.BitString.js @@ -0,0 +1,14 @@ + import Elixir from './Elixir'; + import Elixir$ElixirScript$Kernel from './Elixir.ElixirScript.Kernel'; + const to_string = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable()],function(thing) { + return thing; + },function(thing) { + return Elixir$ElixirScript$Kernel.is_binary(thing); + }),Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable()],function(thing) { + return Elixir.Core.Functions.call_property(thing,'toString'); + })); + export default { + 'Type': Elixir.Core.BitString, 'Implementation': { + to_string + } + }; \ No newline at end of file diff --git a/priv/Elixir.ElixirScript.String.Chars.DefImpl.Elixir.Float.js b/priv/Elixir.ElixirScript.String.Chars.DefImpl.Elixir.Float.js new file mode 100644 index 00000000..41c8f436 --- /dev/null +++ b/priv/Elixir.ElixirScript.String.Chars.DefImpl.Elixir.Float.js @@ -0,0 +1,10 @@ + import Elixir from './Elixir'; + import Elixir$ElixirScript$Kernel from './Elixir.ElixirScript.Kernel'; + const to_string = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable()],function(float) { + return Elixir.Core.Functions.call_property(float,'toString'); + })); + export default { + 'Type': Elixir.Core.Float, 'Implementation': { + to_string + } + }; \ No newline at end of file diff --git a/priv/Elixir.ElixirScript.String.Chars.DefImpl.Elixir.Integer.js b/priv/Elixir.ElixirScript.String.Chars.DefImpl.Elixir.Integer.js new file mode 100644 index 00000000..de403853 --- /dev/null +++ b/priv/Elixir.ElixirScript.String.Chars.DefImpl.Elixir.Integer.js @@ -0,0 +1,10 @@ + import Elixir from './Elixir'; + import Elixir$ElixirScript$Kernel from './Elixir.ElixirScript.Kernel'; + const to_string = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable()],function(integer) { + return Elixir.Core.Functions.call_property(integer,'toString'); + })); + export default { + 'Type': Elixir.Core.Integer, 'Implementation': { + to_string + } + }; \ No newline at end of file diff --git a/priv/Elixir.ElixirScript.String.Chars.DefImpl.Elixir.List.js b/priv/Elixir.ElixirScript.String.Chars.DefImpl.Elixir.List.js new file mode 100644 index 00000000..072a5a56 --- /dev/null +++ b/priv/Elixir.ElixirScript.String.Chars.DefImpl.Elixir.List.js @@ -0,0 +1,10 @@ + import Elixir from './Elixir'; + import Elixir$ElixirScript$Kernel from './Elixir.ElixirScript.Kernel'; + const to_string = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable()],function(list) { + return Elixir.Core.Functions.call_property(list,'toString'); + })); + export default { + 'Type': Array, 'Implementation': { + to_string + } + }; \ No newline at end of file diff --git a/priv/Elixir.ElixirScript.String.Chars.DefImpl.Elixir.Tuple.js b/priv/Elixir.ElixirScript.String.Chars.DefImpl.Elixir.Tuple.js new file mode 100644 index 00000000..05d66609 --- /dev/null +++ b/priv/Elixir.ElixirScript.String.Chars.DefImpl.Elixir.Tuple.js @@ -0,0 +1,10 @@ + import Elixir from './Elixir'; + import Elixir$ElixirScript$Kernel from './Elixir.ElixirScript.Kernel'; + const to_string = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable()],function(tuple) { + return Elixir.Core.Functions.call_property(tuple,'toString'); + })); + export default { + 'Type': Elixir.Core.Tuple, 'Implementation': { + to_string + } + }; \ No newline at end of file diff --git a/priv/Elixir.ElixirScript.String.Chars.DefImpl.js b/priv/Elixir.ElixirScript.String.Chars.DefImpl.js new file mode 100644 index 00000000..dc568414 --- /dev/null +++ b/priv/Elixir.ElixirScript.String.Chars.DefImpl.js @@ -0,0 +1,15 @@ + import Elixir from './Elixir'; + let impls = []; + import Elixir$ElixirScript$String$Chars$DefImpl$Elixir$Atom from './Elixir.ElixirScript.String.Chars.DefImpl.Elixir.Atom'; + impls.push(Elixir$ElixirScript$String$Chars$DefImpl$Elixir$Atom) + import Elixir$ElixirScript$String$Chars$DefImpl$Elixir$BitString from './Elixir.ElixirScript.String.Chars.DefImpl.Elixir.BitString'; + impls.push(Elixir$ElixirScript$String$Chars$DefImpl$Elixir$BitString) + import Elixir$ElixirScript$String$Chars$DefImpl$Elixir$Float from './Elixir.ElixirScript.String.Chars.DefImpl.Elixir.Float'; + impls.push(Elixir$ElixirScript$String$Chars$DefImpl$Elixir$Float) + import Elixir$ElixirScript$String$Chars$DefImpl$Elixir$Integer from './Elixir.ElixirScript.String.Chars.DefImpl.Elixir.Integer'; + impls.push(Elixir$ElixirScript$String$Chars$DefImpl$Elixir$Integer) + import Elixir$ElixirScript$String$Chars$DefImpl$Elixir$List from './Elixir.ElixirScript.String.Chars.DefImpl.Elixir.List'; + impls.push(Elixir$ElixirScript$String$Chars$DefImpl$Elixir$List) + import Elixir$ElixirScript$String$Chars$DefImpl$Elixir$Tuple from './Elixir.ElixirScript.String.Chars.DefImpl.Elixir.Tuple'; + impls.push(Elixir$ElixirScript$String$Chars$DefImpl$Elixir$Tuple) + export default impls; \ No newline at end of file diff --git a/priv/Elixir.ElixirScript.String.Chars.js b/priv/Elixir.ElixirScript.String.Chars.js new file mode 100644 index 00000000..b03cdc0b --- /dev/null +++ b/priv/Elixir.ElixirScript.String.Chars.js @@ -0,0 +1,10 @@ + import Elixir from './Elixir'; + import Elixir$ElixirScript$Kernel from './Elixir.ElixirScript.Kernel'; + import Implementations from './Elixir.ElixirScript.String.Chars.Defimpl'; + const Elixir$ElixirScript$String$Chars = Elixir.Core.Functions.defprotocol({ + to_string: function() { + + } + }); + for(let {Type,Implementation} of Implementations) Elixir.Core.Functions.defimpl(Elixir$ElixirScript$String$Chars,Type,Implementation) + export default Elixir$ElixirScript$String$Chars; \ No newline at end of file diff --git a/priv/Elixir.ElixirScript.String.js b/priv/Elixir.ElixirScript.String.js new file mode 100644 index 00000000..eab78f19 --- /dev/null +++ b/priv/Elixir.ElixirScript.String.js @@ -0,0 +1,152 @@ + import Elixir from './Elixir'; + import Elixir$ElixirScript$Kernel from './Elixir.ElixirScript.Kernel'; + const do_reverse = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case(['', Elixir.Core.Patterns.variable()],function(str) { + return str; + }),Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable(), Elixir.Core.Patterns.variable()],function(str,reverse_str) { + return do_reverse(str.substr(1),reverse_str + last(str)); + })); + const match__qmark__ = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable(), Elixir.Core.Patterns.variable()],function(str,regex) { + return str.match(regex) != null; + })); + const starts_with__qmark__ = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable(), Elixir.Core.Patterns.variable()],function(str,prefix) { + return str.startsWith(prefix); + },function(str,prefix) { + return Elixir$ElixirScript$Kernel.is_binary(prefix); + }),Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable(), Elixir.Core.Patterns.variable()],function(str,prefixes) { + return do_starts_with__qmark__(str,prefixes); + },function(str,prefixes) { + return Elixir$ElixirScript$Kernel.is_list(prefixes); + })); + const valid_character__qmark__ = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable()],function(codepoint) { + return Elixir.Core.Functions.is_valid_character(codepoint); + })); + const do_ends_with__qmark__ = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.wildcard(), Object.freeze([])],function() { + return false; + }),Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable(), Elixir.Core.Patterns.variable()],function(str,suffixes) { + return Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([true],function() { + return true; + }),Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.wildcard()],function() { + return do_ends_with__qmark__(str,Elixir$ElixirScript$Kernel.tl(suffixes)); + })).call(this,ends_with__qmark__(str,Elixir$ElixirScript$Kernel.hd(suffixes))); + })); + const do_starts_with__qmark__ = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.wildcard(), Object.freeze([])],function() { + return false; + }),Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable(), Elixir.Core.Patterns.variable()],function(str,prefixes) { + return Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([true],function() { + return true; + }),Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.wildcard()],function() { + return do_starts_with__qmark__(str,Elixir$ElixirScript$Kernel.tl(prefixes)); + })).call(this,starts_with__qmark__(str,Elixir$ElixirScript$Kernel.hd(prefixes))); + })); + const ends_with__qmark__ = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable(), Elixir.Core.Patterns.variable()],function(str,suffix) { + return str.endsWith(suffix); + },function(str,suffix) { + return Elixir$ElixirScript$Kernel.is_binary(suffix); + }),Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable(), Elixir.Core.Patterns.variable()],function(str,suffixes) { + return do_ends_with__qmark__(str,suffixes); + },function(str,suffixes) { + return Elixir$ElixirScript$Kernel.is_list(suffixes); + })); + const contains__qmark__ = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable(), Elixir.Core.Patterns.variable()],function(str,s) { + return str.indexOf(s) > -1; + },function(str,s) { + return Elixir$ElixirScript$Kernel.is_binary(s); + }),Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable(), Elixir.Core.Patterns.variable()],function(str,s) { + return do_contains__qmark__(str,s); + },function(str,s) { + return Elixir$ElixirScript$Kernel.is_list(s); + })); + const do_contains__qmark__ = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.wildcard(), Object.freeze([])],function() { + return false; + }),Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable(), Elixir.Core.Patterns.variable()],function(str,prefixes) { + return Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([true],function() { + return true; + }),Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.wildcard()],function() { + return do_contains__qmark__(str,Elixir$ElixirScript$Kernel.tl(prefixes)); + })).call(this,contains__qmark__(str,Elixir$ElixirScript$Kernel.hd(prefixes))); + })); + const to_atom = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable()],function(str) { + return Symbol.for(str); + })); + const capitalize = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable()],function(str) { + let [first] = Elixir.Core.Patterns.match(Elixir.Core.Patterns.variable(),Elixir.Core.Functions.call_property(str[0],'toUpperCase')); + let [rest] = Elixir.Core.Patterns.match(Elixir.Core.Patterns.variable(),Elixir.Core.Functions.call_property(str.substr(1),'toLowerCase')); + return first + rest; + })); + const to_existing_atom = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable()],function(str) { + return Symbol.for(str); + })); + const downcase = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable()],function(str) { + return Elixir.Core.Functions.call_property(str,'toLowerCase'); + })); + const reverse = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable()],function(str) { + return do_reverse(str,''); + })); + const next_grapheme = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([null],function() { + return null; + }),Elixir.Core.Patterns.make_case([''],function() { + return null; + }),Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable()],function(str) { + return new Elixir.Core.Tuple(str[0],str.substr(1)); + })); + const duplicate = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable(), Elixir.Core.Patterns.variable()],function(str,n) { + return str.repeat(n); + })); + const upcase = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable()],function(str) { + return Elixir.Core.Functions.call_property(str,'toUpperCase'); + })); + const to_char_list = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable()],function(str) { + return str.split(''); + })); + const to_float = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable()],function(str) { + return Elixir.Core.Functions.call_property(Elixir.Core,'get_global').parseFloat(str); + })); + const first = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([null],function() { + return null; + }),Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable()],function(str) { + return str[0]; + })); + const last = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([null],function() { + return null; + }),Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable()],function(str) { + return str[length(str) - 1]; + })); + const at = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable(), Elixir.Core.Patterns.variable()],function(str,pos) { + return Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([true],function() { + return null; + }),Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.wildcard()],function() { + return str[pos]; + })).call(this,pos > length(str)); + })); + const next_codepoint = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([null],function() { + return null; + }),Elixir.Core.Patterns.make_case([''],function() { + return null; + }),Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable()],function(str) { + return new Elixir.Core.Tuple(str[0].codePointAt(0),str.substr(1)); + })); + const split = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable()],function(str) { + return Elixir.Core.Functions.call_property(str,'split'); + })); + const graphemes = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable()],function(str) { + return str.split(Object.freeze([])); + })); + const do_codepoints = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case(['', Elixir.Core.Patterns.variable()],function(codepoint_list) { + return codepoint_list; + }),Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable(), Elixir.Core.Patterns.variable()],function(str,codepoint_list) { + return do_codepoints(str.substr(1),codepoint_list.concat(Object.freeze([first.codePointAt(0)]))); + })); + const codepoints = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable()],function(str) { + return do_codepoints(str,Object.freeze([])); + })); + const to_integer = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable()],function(str) { + return Elixir.Core.Functions.call_property(Elixir.Core,'get_global').parseInt(str,10); + }),Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable(), Elixir.Core.Patterns.variable()],function(str,base) { + return Elixir.Core.Functions.call_property(Elixir.Core,'get_global').parseInt(str,base); + })); + const length = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable()],function(str) { + return Elixir.Core.Functions.call_property(str,'length'); + })); + export default { + match__qmark__, starts_with__qmark__, valid_character__qmark__, do_ends_with__qmark__, do_starts_with__qmark__, ends_with__qmark__, contains__qmark__, do_contains__qmark__, to_atom, capitalize, to_existing_atom, downcase, reverse, next_grapheme, duplicate, upcase, to_char_list, to_float, first, last, at, next_codepoint, split, graphemes, do_codepoints, codepoints, to_integer, length + }; \ No newline at end of file diff --git a/priv/Elixir.ElixirScript.Tuple.js b/priv/Elixir.ElixirScript.Tuple.js new file mode 100644 index 00000000..13cd970d --- /dev/null +++ b/priv/Elixir.ElixirScript.Tuple.js @@ -0,0 +1,53 @@ + import Elixir from './Elixir'; + import Elixir$ElixirScript$Kernel from './Elixir.ElixirScript.Kernel'; + const do_duplicate = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.wildcard(), 0, Elixir.Core.Patterns.variable()],function(list) { + return list; + }),Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable(), Elixir.Core.Patterns.variable(), Elixir.Core.Patterns.variable()],function(data,size,list) { + return do_duplicate(data,size - 1,list.concat(Object.freeze([data]))); + })); + const do_insert_at = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable(), Elixir.Core.Patterns.variable(), Elixir.Core.Patterns.variable(), Elixir.Core.Patterns.variable(), Elixir.Core.Patterns.variable()],function(tuple,index,value,current_index,list) { + return Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable()],function(x) { + let [list1] = Elixir.Core.Patterns.match(Elixir.Core.Patterns.variable(),Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([true],function() { + return list.concat(Object.freeze([value, tuple.get(current_index)])); + }),Elixir.Core.Patterns.make_case([false],function() { + return list.concat(Object.freeze([tuple.get(current_index)])); + })).call(this,index == current_index)); + return do_insert_at(tuple,index,value,current_index + 1,list); + },function(x) { + return Elixir.Enum.member__qmark__(Object.freeze([false, null]),x); + }),Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.wildcard()],function() { + return list; + })).call(this,current_index == Elixir$ElixirScript$Kernel.length(tuple)); + })); + const do_delete_at = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable(), Elixir.Core.Patterns.variable(), Elixir.Core.Patterns.variable(), Elixir.Core.Patterns.variable()],function(tuple,index,current_index,list) { + return Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable()],function(x) { + let [list1] = Elixir.Core.Patterns.match(Elixir.Core.Patterns.variable(),Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([true],function() { + return list; + }),Elixir.Core.Patterns.make_case([false],function() { + return list.concat(Object.freeze([tuple.get(current_index)])); + })).call(this,index == current_index)); + return do_delete_at(tuple,index,current_index + 1,list); + },function(x) { + return Elixir.Enum.member__qmark__(Object.freeze([false, null]),x); + }),Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.wildcard()],function() { + return list; + })).call(this,current_index == Elixir$ElixirScript$Kernel.length(tuple)); + })); + const duplicate = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable(), Elixir.Core.Patterns.variable()],function(data,size) { + return new Elixir.Core.Tuple(...do_duplicate(data,size,Object.freeze([]))); + })); + const to_list = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable()],function(tuple) { + return tuple['value']; + })); + const insert_at = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable(), Elixir.Core.Patterns.variable(), Elixir.Core.Patterns.variable()],function(tuple,index,value) { + return new Elixir.Core.Tuple(...do_insert_at(tuple,index,value,0,Object.freeze([]))); + })); + const delete_at = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable(), Elixir.Core.Patterns.variable()],function(tuple,index) { + return new Elixir.Core.Tuple(...do_delete_at(tuple,index,0,Object.freeze([]))); + })); + const append = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable(), Elixir.Core.Patterns.variable()],function(tuple,value) { + return new Elixir.Core.Tuple(...to_list.concat(Object.freeze([value]))); + })); + export default { + duplicate, to_list, insert_at, delete_at, append + }; \ No newline at end of file diff --git a/priv/Elixir.ElixirScript.View.js b/priv/Elixir.ElixirScript.View.js new file mode 100644 index 00000000..9915042c --- /dev/null +++ b/priv/Elixir.ElixirScript.View.js @@ -0,0 +1,45 @@ + import Elixir from './Elixir'; + import Elixir$ElixirScript$Kernel from './Elixir.ElixirScript.Kernel'; + import Elixir$ElixirScript$JS from './Elixir.ElixirScript.JS'; + import Elixir$ElixirScript$Keyword from './Elixir.ElixirScript.Keyword'; + const start = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable(), Elixir.Core.Patterns.variable(), Elixir.Core.Patterns.variable()],function(dom_root,render_func,args) { + let [pid] = Elixir.Core.Patterns.match(Elixir.Core.Patterns.variable(),Elixir.Core.Functions.call_property(Elixir.Core.Functions.call_property(Elixir.Core.Functions.call_property(Elixir$ElixirScript$JS,'global'),'processes'),'spawn')); + let [tree] = Elixir.Core.Patterns.match(Elixir.Core.Patterns.variable(),render_func.apply(null,args)); + let [root_node] = Elixir.Core.Patterns.match(Elixir.Core.Patterns.variable(),Elixir.VirtualDOM.create(tree)); + dom_root.appendChild(root_node); + Elixir.Core.Functions.call_property(Elixir.Core.Functions.call_property(Elixir$ElixirScript$JS,'global'),'processes').put(pid,'state',new Elixir.Core.Tuple(root_node,tree,render_func)); + return new Elixir.Core.Tuple(Symbol.for('ok'),pid); + }),Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable(), Elixir.Core.Patterns.variable(), Elixir.Core.Patterns.variable(), Elixir.Core.Patterns.variable()],function(dom_root,render_func,args,options) { + let [pid] = Elixir.Core.Patterns.match(Elixir.Core.Patterns.variable(),Elixir.Core.Functions.call_property(Elixir.Core.Functions.call_property(Elixir.Core.Functions.call_property(Elixir$ElixirScript$JS,'global'),'processes'),'spawn')); + Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable()],function(x) { + return null; + },function(x) { + return Elixir.Enum.member__qmark__(Object.freeze([false, null]),x); + }),Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.wildcard()],function() { + let [pid1] = Elixir.Core.Patterns.match(Elixir.Core.Patterns.variable(),Elixir.Core.Functions.call_property(Elixir.Core.Functions.call_property(Elixir$ElixirScript$JS,'global'),'processes').register(Elixir$ElixirScript$Keyword.get(options,Symbol.for('name')),pid)); + return pid1; + })).call(this,Elixir$ElixirScript$Keyword.has_key__qmark__(options,Symbol.for('name'))); + let [tree] = Elixir.Core.Patterns.match(Elixir.Core.Patterns.variable(),render_func.apply(null,args)); + let [root_node] = Elixir.Core.Patterns.match(Elixir.Core.Patterns.variable(),Elixir.VirtualDOM.create(tree)); + dom_root.appendChild(root_node); + Elixir.Core.Functions.call_property(Elixir.Core.Functions.call_property(Elixir$ElixirScript$JS,'global'),'processes').put(pid,'state',new Elixir.Core.Tuple(root_node,tree,render_func)); + return new Elixir.Core.Tuple(Symbol.for('ok'),pid); + })); + const render = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable(), Elixir.Core.Patterns.variable()],function(view,args) { + let [root_node,tree,render_func] = Elixir.Core.Patterns.match(Elixir.Core.Patterns.type(Elixir.Core.Tuple,{ + values: [Elixir.Core.Patterns.variable(), Elixir.Core.Patterns.variable(), Elixir.Core.Patterns.variable()] + }),Elixir.Core.Functions.call_property(Elixir.Core.Functions.call_property(Elixir$ElixirScript$JS,'global'),'processes').get(view,'state')); + let _ref = new Elixir.Core.Tuple(root_node,tree,render_func); + let [new_tree] = Elixir.Core.Patterns.match(Elixir.Core.Patterns.variable(),render_func.apply(null,args)); + let [patches] = Elixir.Core.Patterns.match(Elixir.Core.Patterns.variable(),Elixir.VirtualDOM.diff(tree,new_tree)); + let [root_node1] = Elixir.Core.Patterns.match(Elixir.Core.Patterns.variable(),Elixir.VirtualDOM.patch(root_node,patches)); + Elixir.Core.Functions.call_property(Elixir.Core.Functions.call_property(Elixir$ElixirScript$JS,'global'),'processes').put(view,'state',new Elixir.Core.Tuple(root_node,new_tree,render_func)); + return Symbol.for('ok'); + })); + const stop = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable()],function(view) { + Elixir.Core.Functions.call_property(Elixir.Core.Functions.call_property(Elixir$ElixirScript$JS,'global'),'processes').exit(view); + return Symbol.for('ok'); + })); + export default { + start, render, stop + }; \ No newline at end of file From d4f21435edbf73f42c15b9e1a3f370f2404b4038 Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Tue, 15 Mar 2016 16:30:13 -0500 Subject: [PATCH 183/860] Add CompilerStats module --- lib/elixir_script.ex | 55 ++++++++----- lib/elixir_script/compiler_stats.ex | 74 ++++++++++++++++++ lib/elixir_script/translator/state.ex | 13 +-- lib/elixir_script/translator/stdlib_state.exs | Bin 129805 -> 129882 bytes test/translator/protocol_test.exs | 1 + 5 files changed, 118 insertions(+), 25 deletions(-) create mode 100644 lib/elixir_script/compiler_stats.ex diff --git a/lib/elixir_script.ex b/lib/elixir_script.ex index 4e69e659..9fad943f 100644 --- a/lib/elixir_script.ex +++ b/lib/elixir_script.ex @@ -3,6 +3,8 @@ defmodule ElixirScript do alias ESTree.Tools.Generator alias ElixirScript.Translator.Utils alias ElixirScript.Translator.ModuleCollector + alias ElixirScript.CompilerStats + require Logger @moduledoc """ Translates Elixir into JavaScript. @@ -53,7 +55,8 @@ defmodule ElixirScript do """ @spec compile_quoted(Macro.t, Map.t) :: [binary | {binary, binary}] def compile_quoted(quoted, opts \\ %{}) do - do_compile(opts, [quoted]) + { code, _ } = do_compile(opts, [quoted]) + code end @doc """ @@ -61,10 +64,33 @@ defmodule ElixirScript do """ @spec compile_path(binary, Map.t) :: [binary | {binary, binary}] def compile_path(path, opts \\ %{}) do - path = Path.wildcard(path) - code = Enum.map(path, &file_to_quoted/1) + expanded_path = Path.wildcard(path) + + compiler_stats = if Map.get(opts, :rebuild, false) do + CompilerStats.delete_compiler_stats(path) + CompilerStats.new_compile_stats(@stdlib_state) + else + case CompilerStats.get_compiler_stats(path) do + nil -> + CompilerStats.new_compile_stats(@stdlib_state) + x -> + x + end + end + + new_file_stats = CompilerStats.build_file_stats(expanded_path) + + changed_files = CompilerStats.get_changed_files(compiler_stats.files, new_file_stats) + |> Enum.map(fn {file, state} -> file end) + + code = Enum.map(changed_files, &file_to_quoted/1) - do_compile(opts, code) + { code, new_state } = do_compile(opts, code, compiler_stats.state) + compiler_stats = %{compiler_stats | files: new_file_stats, state: new_state } + + CompilerStats.save_compiler_stats(path, compiler_stats) + + code end def compile_std_lib() do @@ -92,16 +118,17 @@ defmodule ElixirScript do end) end - defp do_compile(opts, quoted_code_list) do + defp do_compile(opts, quoted_code_list, state \\ @stdlib_state) do compiler_opts = build_compiler_options(opts) ElixirScript.Translator.State.start_link(compiler_opts) - ElixirScript.Translator.State.deserialize(@stdlib_state) + ElixirScript.Translator.State.deserialize(state) ModuleCollector.process_modules(Enum.map(quoted_code_list, &update_quoted(&1))) code = create_code(compiler_opts) + new_state = ElixirScript.Translator.State.serialize() ElixirScript.Translator.State.stop - code + { code, new_state } end defp build_compiler_options(opts) do @@ -146,21 +173,11 @@ defmodule ElixirScript do state = ElixirScript.Translator.State.get - standard_lib_modules = Map.values(state.std_lib_map) |> Enum.map(&to_string(&1)) |> Enum.map(&String.replace(&1, "Elixir.", "")) + standard_lib_modules = Map.values(state.std_lib_map) |> Enum.map(&to_string(&1)) result = Map.values(state.modules) - |> Enum.reject(fn(ast) -> - name = Atom.to_string(ast.name) |> String.replace("Elixir.", "") - cond do - Map.get(compiler_opts, :std_lib, false) == false and name in standard_lib_modules -> - true - Map.get(compiler_opts, :std_lib, false) == false and ast.type == :protocol_implementation and String.starts_with?(name, standard_lib_modules) -> - true - true -> - false - end - end) + |> Enum.reject(fn(ast) -> not ast.name in state.added_modules end) |> Enum.map(fn ast -> spawn_link fn -> env = ElixirScript.Translator.Env.module_env(ast.name, Utils.name_to_js_file_name(ast.name) <> ".js") diff --git a/lib/elixir_script/compiler_stats.ex b/lib/elixir_script/compiler_stats.ex new file mode 100644 index 00000000..a311789f --- /dev/null +++ b/lib/elixir_script/compiler_stats.ex @@ -0,0 +1,74 @@ +defmodule ElixirScript.CompilerStats do + @moduledoc false + + def delete_compiler_stats(path) do + tmp_file = get_tmp_file(path) + if !File.exists?(tmp_file) do + File.rm(tmp_file) + end + end + + def get_compiler_stats(path) do + tmp_file = get_tmp_file(path) + if File.exists?(tmp_file) do + File.read!(tmp_file) + |> :erlang.binary_to_term + else + nil + end + end + + def save_compiler_stats(path, stats) do + tmp_file = get_tmp_file(path) + File.write!(tmp_file, :erlang.term_to_binary(stats)) + end + + def get_changed_files(old_file_stats, new_file_stats) do + if(length(old_file_stats) != length(new_file_stats)) do + new_file_stats + else + old_file_stats = Enum.sort(old_file_stats, fn {file1, _}, {file2, _} -> file1 < file2 end) + new_file_stats = Enum.sort(new_file_stats, fn {file1, _}, {file2, _} -> file1 < file2 end) + zipped = Enum.zip(old_file_stats, new_file_stats) + + if(Enum.any?(zipped, fn({ {old_file, _} , {new_file, _ } }) -> old_file != new_file end)) do + new_file_stats + else + Enum.reduce(zipped, [], fn({ {_, old_stat} , {_, new_stat } = new }, state) -> + cond do + old_stat.mtime != new_stat.mtime -> + state ++ [new] + true -> + state + end + end) + end + end + end + + def build_file_stats(path) do + Enum.map(path, fn(file) -> + { file, File.stat!(file) } + end) + end + + def new_compile_stats(state) do + %{ + files: [], + state: state + } + end + + defp get_tmp_file(path) do + tmp_dir = Path.join([System.tmp_dir!, "elixirscript"]) + + if !File.exists?(tmp_dir) do + File.mkdir_p!(tmp_dir) + end + + encoded_path = Path.absname(path) |> Path.dirname |> Base.encode64 + Path.join([tmp_dir, encoded_path]) + + end + +end diff --git a/lib/elixir_script/translator/state.ex b/lib/elixir_script/translator/state.ex index 91267576..b7353f54 100644 --- a/lib/elixir_script/translator/state.ex +++ b/lib/elixir_script/translator/state.ex @@ -11,12 +11,13 @@ defmodule ElixirScript.Translator.State do def start_link(compiler_opts \\ []) do Agent.start_link(fn -> - %{ compiler_opts: compiler_opts, modules: Map.new, std_lib_map: build_standard_lib_map() } + %{ compiler_opts: compiler_opts, modules: Map.new, std_lib_map: build_standard_lib_map(), added_modules: MapSet.new } end, name: __MODULE__) end def serialize() do Agent.get(__MODULE__, fn(state) -> + state = Map.delete(state, :added_modules) :erlang.term_to_binary(state) end) end @@ -25,7 +26,7 @@ defmodule ElixirScript.Translator.State do Agent.update(__MODULE__, fn state -> frozen_state = :erlang.binary_to_term(frozen_state) modules = Map.delete(frozen_state.modules, ElixirScript.Temp) - %{ state | modules: modules, std_lib_map: frozen_state.std_lib_map } + %{ state | modules: modules, std_lib_map: frozen_state.std_lib_map, added_modules: MapSet.new } end) end @@ -57,13 +58,13 @@ defmodule ElixirScript.Translator.State do def add_module(module) do Agent.update(__MODULE__, fn state -> - %{ state | modules: Map.put(state.modules, module.name, module) } + %{ state | modules: Map.put(state.modules, module.name, module), added_modules: Set.put(state.added_modules, module.name) } end) end def delete_module_by_name(module_name) do Agent.update(__MODULE__, fn state -> - %{ state | modules: Map.delete(state.modules, module_name ) } + %{ state | modules: Map.delete(state.modules, module_name ), added_modules: Set.delete(state.added_modules, module_name) } end) end @@ -77,7 +78,7 @@ defmodule ElixirScript.Translator.State do proto = %ElixirScript.Module{proto | functions: functions, type: :protocol } end - %{ state | modules: Map.put(state.modules, name, proto) } + %{ state | modules: Map.put(state.modules, name, proto), added_modules: Set.put(state.added_modules, name) } end) end @@ -95,7 +96,7 @@ defmodule ElixirScript.Translator.State do proto_impl = %ElixirScript.Module{ name: module_name, body: impl, impl_type: type, type: :protocol_implementation } - %{ state | modules: Map.put(state.modules, module_name, proto_impl) } + %{ state | modules: Map.put(state.modules, module_name, proto_impl), added_modules: Set.put(state.added_modules, module_name) } end) end diff --git a/lib/elixir_script/translator/stdlib_state.exs b/lib/elixir_script/translator/stdlib_state.exs index 10cefd8223d02c611ba4b9890c12eb5b3ef4c595..c443e2bf86657a21c6a7cd768ab7fbbf6236e09a 100644 GIT binary patch delta 117 zcmeDE#(wJ?`-E&pj)^(%Bt%?uGAlBR^qli^3o>(3i-JoMONvt%6ek<9itwWdW-v`( z_=8b(b1kC^Gvo5ji&$ncGO|xM_{k_fJ?{r2+vF&=3V{>`UZ{CK`RVDYMa`GkwqIgn HwEhAB34kiL delta 54 zcmV-60LlN__6Lpj2asz42a#; Date: Tue, 15 Mar 2016 17:55:58 -0500 Subject: [PATCH 184/860] Added test for compiler stats --- lib/elixir_script.ex | 4 ++- lib/elixir_script/cli.ex | 5 +++- lib/mix/tasks/elixirscript.ex | 4 ++- test/compiler_stat_test.exs | 47 +++++++++++++++++++++++++++++++++++ 4 files changed, 57 insertions(+), 3 deletions(-) create mode 100644 test/compiler_stat_test.exs diff --git a/lib/elixir_script.ex b/lib/elixir_script.ex index 9fad943f..460703b2 100644 --- a/lib/elixir_script.ex +++ b/lib/elixir_script.ex @@ -22,6 +22,7 @@ defmodule ElixirScript do * `:root` - a binary path prepended to the path of the standard lib imports if needed * `:env` - a Macro.env struct to use. This is most useful when using macros. Make sure that the * `:core_path` - The es6 import path used to import the elixirscript core. + * `:full_build` - For compile_path, tells the compiler to perform a full build instead of incremental one When using this option, the Elixir.js file is not exported """ @@ -66,7 +67,7 @@ defmodule ElixirScript do def compile_path(path, opts \\ %{}) do expanded_path = Path.wildcard(path) - compiler_stats = if Map.get(opts, :rebuild, false) do + compiler_stats = if Map.get(opts, :full_build, false) do CompilerStats.delete_compiler_stats(path) CompilerStats.new_compile_stats(@stdlib_state) else @@ -138,6 +139,7 @@ defmodule ElixirScript do |> Map.put(:env, custom_env) |> Map.put(:import_standard_libs, true) |> Map.put(:core_path, "Elixir") + |> Map.put(:full_build, false) Map.merge(default_options, opts) end diff --git a/lib/elixir_script/cli.ex b/lib/elixir_script/cli.ex index 9ae59e12..e289d781 100644 --- a/lib/elixir_script/cli.ex +++ b/lib/elixir_script/cli.ex @@ -3,7 +3,8 @@ defmodule ElixirScript.CLI do @switches [ output: :binary, elixir: :boolean, root: :binary, - help: :boolean, core_path: :binary, std_lib: :binary + help: :boolean, core_path: :binary, std_lib: :binary, + full_build: :boolean ] @aliases [ @@ -38,6 +39,8 @@ defmodule ElixirScript.CLI do -ex --elixir read input as elixir code string -r --root [path] root import path for all exported modules --std_lib [path] outputs the elixirscript standard library JavaScript files to the specified path + --full_build informs the compiler to do a full build instead of an incremental one + only used when output is specified --core_path es6 import path to the elixirscript standard lib only used with the [output] option. When used, Elixir.js is not exported -h --help this message diff --git a/lib/mix/tasks/elixirscript.ex b/lib/mix/tasks/elixirscript.ex index 16090784..05b3fb33 100644 --- a/lib/mix/tasks/elixirscript.ex +++ b/lib/mix/tasks/elixirscript.ex @@ -9,6 +9,8 @@ defmodule Mix.Tasks.Elixirscript do -ex --elixir read input as elixir code string -r --root [path] root import path for all exported modules --std_lib [path] outputs the elixirscript standard library JavaScript files to the specified path + --full_build informs the compiler to do a full build instead of an incremental one + only used when output is specified --core_path es6 import path to the elixirscript standard lib only used with the [output] option. When used, elixir.js is not exported -h --help this message @@ -16,7 +18,7 @@ defmodule Mix.Tasks.Elixirscript do use Mix.Task - @shortdoc "Translate Elixir code to javascript" + @shortdoc "Translate Elixir to JavaScript" def run(args) do Mix.Task.run "app.start" diff --git a/test/compiler_stat_test.exs b/test/compiler_stat_test.exs new file mode 100644 index 00000000..f6173d6b --- /dev/null +++ b/test/compiler_stat_test.exs @@ -0,0 +1,47 @@ +defmodule ElixirScript.CompilerStats.Test do + use ExUnit.Case + alias ElixirScript.CompilerStats + + + test "no changes found when old and new are empty" do + old = [] + new = [] + assert CompilerStats.get_changed_files(old, new) == [] + end + + test "all new changes found when old empty and new has files" do + old = [] + new = [{"file.ex", %{mtime: 1}}] + assert CompilerStats.get_changed_files(old, new) == new + end + + test "all new changes found when old not emtpy and new is empty" do + old = [{"file.ex", %{mtime: 1}}] + new = [] + assert CompilerStats.get_changed_files(old, new) == new + end + + test "all new changes found when old and new have same size but different file" do + old = [{"file.ex", %{mtime: 1}}] + new = [{"new_file.ex", %{mtime: 1}}] + assert CompilerStats.get_changed_files(old, new) == new + end + + test "all new changes found when old and new have same file and different size" do + old = [{"file.ex", %{mtime: 1}}] + new = [{"file.ex", %{mtime: 2}}] + assert CompilerStats.get_changed_files(old, new) == new + end + + test "no changes found when old and new have same file and size" do + old = [{"file.ex", %{mtime: 1}}] + new = [{"file.ex", %{mtime: 1}}] + assert CompilerStats.get_changed_files(old, new) == [] + end + + test "all new changes found when old has less files than new" do + old = [{"file.ex", %{mtime: 1}}] + new = [{"file.ex", %{mtime: 1}}, {"new_file.ex", %{mtime: 1}}] + assert CompilerStats.get_changed_files(old, new) == new + end +end From b8a95bf03ef86a24ccb4f327d8dc118a7e586803 Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Tue, 15 Mar 2016 22:16:15 -0500 Subject: [PATCH 185/860] Renamed CompilerStats to CompilerCache. Added functionality to only add stdlib files when needed --- lib/elixir_script.ex | 22 ++-- lib/elixir_script/cli.ex | 12 +- lib/elixir_script/compiler_cache.ex | 112 ++++++++++++++++++ lib/elixir_script/compiler_stats.ex | 74 ------------ lib/elixir_script/translator/stdlib_state.exs | Bin 129882 -> 129903 bytes ..._stat_test.exs => compiler_cache_test.exs} | 18 +-- 6 files changed, 143 insertions(+), 95 deletions(-) create mode 100644 lib/elixir_script/compiler_cache.ex delete mode 100644 lib/elixir_script/compiler_stats.ex rename test/{compiler_stat_test.exs => compiler_cache_test.exs} (67%) diff --git a/lib/elixir_script.ex b/lib/elixir_script.ex index 460703b2..49f8951d 100644 --- a/lib/elixir_script.ex +++ b/lib/elixir_script.ex @@ -3,7 +3,7 @@ defmodule ElixirScript do alias ESTree.Tools.Generator alias ElixirScript.Translator.Utils alias ElixirScript.Translator.ModuleCollector - alias ElixirScript.CompilerStats + alias ElixirScript.CompilerCache require Logger @moduledoc """ @@ -68,20 +68,20 @@ defmodule ElixirScript do expanded_path = Path.wildcard(path) compiler_stats = if Map.get(opts, :full_build, false) do - CompilerStats.delete_compiler_stats(path) - CompilerStats.new_compile_stats(@stdlib_state) + CompilerCache.delete(path) + CompilerCache.new(@stdlib_state) else - case CompilerStats.get_compiler_stats(path) do + case CompilerCache.get(path) do nil -> - CompilerStats.new_compile_stats(@stdlib_state) + CompilerCache.new(@stdlib_state) x -> - x + %{ x | full_build?: false } end end - new_file_stats = CompilerStats.build_file_stats(expanded_path) + new_file_stats = CompilerCache.build_file_stats(expanded_path) - changed_files = CompilerStats.get_changed_files(compiler_stats.files, new_file_stats) + changed_files = CompilerCache.get_changed_files(compiler_stats.files, new_file_stats) |> Enum.map(fn {file, state} -> file end) code = Enum.map(changed_files, &file_to_quoted/1) @@ -89,7 +89,7 @@ defmodule ElixirScript do { code, new_state } = do_compile(opts, code, compiler_stats.state) compiler_stats = %{compiler_stats | files: new_file_stats, state: new_state } - CompilerStats.save_compiler_stats(path, compiler_stats) + CompilerCache.write(path, compiler_stats) code end @@ -179,7 +179,9 @@ defmodule ElixirScript do result = Map.values(state.modules) - |> Enum.reject(fn(ast) -> not ast.name in state.added_modules end) + |> Enum.reject(fn(ast) -> + not ast.name in state.added_modules + end) |> Enum.map(fn ast -> spawn_link fn -> env = ElixirScript.Translator.Env.module_env(ast.name, Utils.name_to_js_file_name(ast.name) <> ".js") diff --git a/lib/elixir_script/cli.ex b/lib/elixir_script/cli.ex index e289d781..75e1d4d0 100644 --- a/lib/elixir_script/cli.ex +++ b/lib/elixir_script/cli.ex @@ -63,7 +63,8 @@ defmodule ElixirScript.CLI do compile_opts = %{ root: options[:root], include_path: true, - core_path: Keyword.get(options, :core_path, "Elixir") + core_path: Keyword.get(options, :core_path, "Elixir"), + full_build: Keyword.get(options, :full_build, false) } compile_output = case options[:elixir] do @@ -93,7 +94,14 @@ defmodule ElixirScript.CLI do end) if options[:core_path] == nil do - ElixirScript.copy_core_to_destination(output_path) + case ElixirScript.CompilerCache.get(input) do + nil -> + ElixirScript.copy_core_to_destination(output_path) + %{ full_build?: true } -> + ElixirScript.copy_core_to_destination(output_path) + _ -> + nil + end end end end diff --git a/lib/elixir_script/compiler_cache.ex b/lib/elixir_script/compiler_cache.ex new file mode 100644 index 00000000..d2868bcb --- /dev/null +++ b/lib/elixir_script/compiler_cache.ex @@ -0,0 +1,112 @@ +defmodule ElixirScript.CompilerCache do + @moduledoc false + require Logger + + def delete(path) do + case get_tmp_file(path) do + nil -> + nil + tmp_file -> + if !File.exists?(tmp_file) do + File.rm(tmp_file) + end + end + end + + def get(path) do + case get_tmp_file(path) do + nil -> + nil + tmp_file -> + if File.exists?(tmp_file) do + case File.read(tmp_file) do + {:ok, data} -> + :erlang.binary_to_term(data) + {:error, reason} -> + Logger.info("Unable to read compiler cache") + Logger.info(reason) + nil + end + else + nil + end + end + end + + def write(path, stats) do + case get_tmp_file(path) do + nil -> + { :error, nil } + tmp_file -> + case File.write(tmp_file, :erlang.term_to_binary(stats)) do + :ok -> + :ok + {:error, reason} -> + Logger.info("Unable to write compiler cache") + Logger.info(reason) + { :error, reason } + end + end + end + + def get_changed_files(old_file_stats, new_file_stats) do + if(length(old_file_stats) != length(new_file_stats)) do + new_file_stats + else + old_file_stats = Enum.sort(old_file_stats, fn {file1, _}, {file2, _} -> file1 < file2 end) + new_file_stats = Enum.sort(new_file_stats, fn {file1, _}, {file2, _} -> file1 < file2 end) + zipped = Enum.zip(old_file_stats, new_file_stats) + + if(Enum.any?(zipped, fn({ {old_file, _} , {new_file, _ } }) -> old_file != new_file end)) do + new_file_stats + else + Enum.reduce(zipped, [], fn({ {_, old_stat} , {_, new_stat } = new }, state) -> + cond do + old_stat.mtime != new_stat.mtime -> + state ++ [new] + true -> + state + end + end) + end + end + end + + def build_file_stats(path) do + Enum.map(path, fn(file) -> + { file, File.stat!(file) } + end) + end + + def new(state) do + %{ + files: [], + state: state, + full_build?: true + } + end + + defp get_tmp_file(path) do + case System.tmp_dir do + nil -> + nil + tmp -> + tmp_dir = Path.join([tmp, "elixirscript"]) + if !File.exists?(tmp_dir) do + case File.mkdir_p(tmp_dir) do + :ok -> + encoded_path = Path.absname(path) |> Path.dirname |> Base.encode64 + Path.join([tmp_dir, encoded_path]) + {:error, reason} -> + Logger.info("Unable to write compiler cache") + Logger.info(reason) + nil + end + else + encoded_path = Path.absname(path) |> Path.dirname |> Base.encode64 + Path.join([tmp_dir, encoded_path]) + end + end + end + +end diff --git a/lib/elixir_script/compiler_stats.ex b/lib/elixir_script/compiler_stats.ex deleted file mode 100644 index a311789f..00000000 --- a/lib/elixir_script/compiler_stats.ex +++ /dev/null @@ -1,74 +0,0 @@ -defmodule ElixirScript.CompilerStats do - @moduledoc false - - def delete_compiler_stats(path) do - tmp_file = get_tmp_file(path) - if !File.exists?(tmp_file) do - File.rm(tmp_file) - end - end - - def get_compiler_stats(path) do - tmp_file = get_tmp_file(path) - if File.exists?(tmp_file) do - File.read!(tmp_file) - |> :erlang.binary_to_term - else - nil - end - end - - def save_compiler_stats(path, stats) do - tmp_file = get_tmp_file(path) - File.write!(tmp_file, :erlang.term_to_binary(stats)) - end - - def get_changed_files(old_file_stats, new_file_stats) do - if(length(old_file_stats) != length(new_file_stats)) do - new_file_stats - else - old_file_stats = Enum.sort(old_file_stats, fn {file1, _}, {file2, _} -> file1 < file2 end) - new_file_stats = Enum.sort(new_file_stats, fn {file1, _}, {file2, _} -> file1 < file2 end) - zipped = Enum.zip(old_file_stats, new_file_stats) - - if(Enum.any?(zipped, fn({ {old_file, _} , {new_file, _ } }) -> old_file != new_file end)) do - new_file_stats - else - Enum.reduce(zipped, [], fn({ {_, old_stat} , {_, new_stat } = new }, state) -> - cond do - old_stat.mtime != new_stat.mtime -> - state ++ [new] - true -> - state - end - end) - end - end - end - - def build_file_stats(path) do - Enum.map(path, fn(file) -> - { file, File.stat!(file) } - end) - end - - def new_compile_stats(state) do - %{ - files: [], - state: state - } - end - - defp get_tmp_file(path) do - tmp_dir = Path.join([System.tmp_dir!, "elixirscript"]) - - if !File.exists?(tmp_dir) do - File.mkdir_p!(tmp_dir) - end - - encoded_path = Path.absname(path) |> Path.dirname |> Base.encode64 - Path.join([tmp_dir, encoded_path]) - - end - -end diff --git a/lib/elixir_script/translator/stdlib_state.exs b/lib/elixir_script/translator/stdlib_state.exs index c443e2bf86657a21c6a7cd768ab7fbbf6236e09a..7a4a3847ce08a724b97ee0c706889acf699ad316 100644 GIT binary patch delta 112 zcmcchjs5*M_6bsq>>H*18CjhZlQU8$=QGN)gIO6&)8GAIRNcIbQH7at<>dP;nv6Fm zFJ#nY&tOVoU|_sC-S7~j_~ZaqDJXMu6YB~_VXm~&oSgWi(#)Kc6b9C`#GK;PW)1f3 J8tjZlUjUZ&C9MDe delta 83 zcmaF=js4a)_6bsqY#XKh8Cio%5=)9F=QGMfSeqv^dNVUFpM0N1lX2 Date: Wed, 16 Mar 2016 22:19:16 -0500 Subject: [PATCH 186/860] Added compiler output module. --- lib/elixir_script.ex | 143 +++++++++--------- lib/elixir_script/cli.ex | 46 +----- .../{compiler_cache.ex => compiler/cache.ex} | 4 +- lib/elixir_script/compiler/output.ex | 62 ++++++++ lib/elixir_script/translator/protocol.ex | 7 +- lib/elixir_script/translator/stdlib_state.exs | Bin 129903 -> 130017 bytes .../cache_test.exs} | 18 +-- 7 files changed, 153 insertions(+), 127 deletions(-) rename lib/elixir_script/{compiler_cache.ex => compiler/cache.ex} (97%) create mode 100644 lib/elixir_script/compiler/output.ex rename test/{compiler_cache_test.exs => compiler/cache_test.exs} (67%) diff --git a/lib/elixir_script.ex b/lib/elixir_script.ex index 49f8951d..535017ab 100644 --- a/lib/elixir_script.ex +++ b/lib/elixir_script.ex @@ -3,7 +3,8 @@ defmodule ElixirScript do alias ESTree.Tools.Generator alias ElixirScript.Translator.Utils alias ElixirScript.Translator.ModuleCollector - alias ElixirScript.CompilerCache + alias ElixirScript.Compiler.Cache + alias ElixirScript.Compiler.Output require Logger @moduledoc """ @@ -23,6 +24,10 @@ defmodule ElixirScript do * `:env` - a Macro.env struct to use. This is most useful when using macros. Make sure that the * `:core_path` - The es6 import path used to import the elixirscript core. * `:full_build` - For compile_path, tells the compiler to perform a full build instead of incremental one + * `:output` - option to tell compiler how to output data + `nil`: Return as list + `:stdout`: Write to standard out + `path (string)`: Write to specified path When using this option, the Elixir.js file is not exported """ @@ -57,7 +62,7 @@ defmodule ElixirScript do @spec compile_quoted(Macro.t, Map.t) :: [binary | {binary, binary}] def compile_quoted(quoted, opts \\ %{}) do { code, _ } = do_compile(opts, [quoted]) - code + Output.out(quoted, code, build_compiler_options(opts)) end @doc """ @@ -67,36 +72,36 @@ defmodule ElixirScript do def compile_path(path, opts \\ %{}) do expanded_path = Path.wildcard(path) - compiler_stats = if Map.get(opts, :full_build, false) do - CompilerCache.delete(path) - CompilerCache.new(@stdlib_state) + compiler_cache = if Map.get(opts, :full_build, false) do + Cache.delete(path) + Cache.new(@stdlib_state) else - case CompilerCache.get(path) do + case Cache.get(path) do nil -> - CompilerCache.new(@stdlib_state) + Cache.new(@stdlib_state) x -> %{ x | full_build?: false } end end - new_file_stats = CompilerCache.build_file_stats(expanded_path) + new_file_stats = Cache.build_file_stats(expanded_path) - changed_files = CompilerCache.get_changed_files(compiler_stats.files, new_file_stats) + changed_files = Cache.get_changed_files(compiler_cache.input_files, new_file_stats) |> Enum.map(fn {file, state} -> file end) code = Enum.map(changed_files, &file_to_quoted/1) - { code, new_state } = do_compile(opts, code, compiler_stats.state) - compiler_stats = %{compiler_stats | files: new_file_stats, state: new_state } + { code, new_state } = do_compile(opts, code, compiler_cache.state) + compiler_cache = %{compiler_cache | input_files: new_file_stats, state: new_state } - CompilerCache.write(path, compiler_stats) - - code + Cache.write(path, compiler_cache) + Output.out(path, code, opts) end def compile_std_lib() do - compiler_opts = build_compiler_options(%{std_lib: true, include_path: true}) + compiler_opts = build_compiler_options(%{std_lib: true, include_path: true, output: File.cwd!() <> "/priv"}) libs_path = Path.join([__DIR__, "elixir_script", "prelude", "**", "*.ex"]) + code = Path.wildcard(libs_path) |> Enum.filter(fn(path) -> !String.contains?(path, ["v_dom.ex", "html.ex"]) @@ -105,18 +110,15 @@ defmodule ElixirScript do ElixirScript.Translator.State.start_link(compiler_opts) ModuleCollector.process_modules(Enum.map(code, &update_quoted(&1))) + code = create_code(compiler_opts) + |> Enum.filter(fn({path, _}) -> !String.contains?(path, "ElixirScript.Temp.js") end) + new_std_state = ElixirScript.Translator.State.serialize() ElixirScript.Translator.State.stop File.write!(File.cwd!() <> "/lib/elixir_script/translator/stdlib_state.exs", new_std_state) - - output_path = File.cwd!() <> "/priv" - - Enum.filter(code, fn({path, _}) -> !String.contains?(path, "ElixirScript.Temp.js") end) - |> Enum.each(fn(x) -> - ElixirScript.CLI.write_to_file(x, output_path) - end) + Output.out(libs_path, code, compiler_opts) end defp do_compile(opts, quoted_code_list, state \\ @stdlib_state) do @@ -140,6 +142,7 @@ defmodule ElixirScript do |> Map.put(:import_standard_libs, true) |> Map.put(:core_path, "Elixir") |> Map.put(:full_build, false) + |> Map.put(:output, nil) Map.merge(default_options, opts) end @@ -177,8 +180,7 @@ defmodule ElixirScript do standard_lib_modules = Map.values(state.std_lib_map) |> Enum.map(&to_string(&1)) - result = - Map.values(state.modules) + Map.values(state.modules) |> Enum.reject(fn(ast) -> not ast.name in state.added_modules end) @@ -206,60 +208,59 @@ defmodule ElixirScript do {^pid, result} -> result end end) + end - { result, protocols } = Enum.map_reduce(result, %{}, fn - { path, code, nil, _ }, protocols -> - {{ path, code}, protocols } - { path, code, protocol, name }, protocols -> - {{ path, code}, Map.put(protocols, protocol, Map.get(protocols, protocol, []) ++ [name]) } - end) - - defimpls = Enum.map(protocols, fn({protocol, implementations}) -> - ElixirScript.Translator.Protocol.make_defimpl(protocol, implementations, state.compiler_opts) - end) - |> Enum.map(fn(module) -> - { path, code, _, _ } = convert_to_code(module) - {path, code} - end) - - result = result ++ defimpls - - result = Enum.map(result, fn - { path, code } -> - case compiler_opts.include_path do - true -> - { path, code } - false -> - code - end + def update_protocols(compiler_output, compiler_opts) do + Enum.reduce(compiler_output, %{}, fn + {file, code}, state -> + case String.split(file, ".DefImpl.") do + [protocol, impl] -> + protocol = String.split(protocol, "/") |> List.last |> String.to_atom + impl = String.replace(impl, ".js", "") |> String.to_atom + Map.put(state, protocol, Map.get(state, protocol, []) ++ [impl]) + [_] -> + state + end + _, state -> + state end) - - result + |> do_make_defimpl(compiler_opts) end - def update_protocols(path, compiler_opts) do - result = Enum.filter(Path.wildcard(path), fn(js_file_path) -> - String.contains?(js_file_path, ".DefImpl") - end) - |> Enum.reduce(%{}, fn(js_file_path, state) -> - case String.split(js_file_path, ".DefImpl.") do - [protocol, "js"] -> - protocol = String.split(protocol, "/") |> List.last |> String.to_atom - Map.put(state, protocol, Map.get(state, protocol, [])) - [protocol, impl] -> - protocol = String.split(protocol, "/") |> List.last |> String.to_atom - impl = String.replace(impl, ".js", "") |> String.to_atom - Map.put(state, protocol, Map.get(state, protocol, []) ++ [impl]) + def update_protocols_in_path(compiler_output, compiler_opts, output_path) do + Enum.reduce(compiler_output, %{}, fn {file, code}, state -> + case String.split(file, ".DefImpl.") do + [protocol, _] -> + protocol = String.split(protocol, "/") |> List.last + protocol_impls = find_protocols_implementations_in_path(output_path, protocol) + protocol = String.to_atom(protocol) + Map.put(state, protocol, Map.get(state, protocol, []) ++ protocol_impls) + [_] -> + state end end) - |> Enum.map(fn {protocol, implementations} -> - ElixirScript.Translator.Protocol.make_defimpl(protocol, implementations, compiler_opts) + |> do_make_defimpl(compiler_opts) + end + + defp do_make_defimpl(protocols, compiler_opts) do + Enum.map(protocols, fn {protocol, implementations} -> + ElixirScript.Translator.Protocol.make_defimpl(protocol, Enum.uniq(implementations), compiler_opts) end) |> Enum.map(fn(module) -> - { path, code, _, _ } = convert_to_code(module) - {path, code} + convert_to_code(module) end) + end + def find_protocols_implementations_in_path(path, protocol_prefix) do + Path.join([path, protocol_prefix <> ".DefImpl*.js"]) + |> Path.wildcard + |> Enum.filter(fn path -> !String.ends_with?(path, "DefImpl.js") end) + |> Enum.map(fn impl -> + Path.basename(impl) + |> String.split(".DefImpl.") + |> List.last + |> String.replace(".js", "") + |> String.to_atom end) end @doc """ @@ -290,15 +291,15 @@ defmodule ElixirScript do defp process_module(module) do file_path = Utils.name_to_js_file_name(module.name) <> ".js" - { file_path, Builder.program(module.body), Map.get(module, :protocol), Map.get(module, :name) } + { file_path, Builder.program(module.body) } end - defp javascript_ast_to_code({path, js_ast, protocol, name}) do + defp javascript_ast_to_code({path, js_ast}) do js_code = js_ast |> prepare_js_ast |> Generator.generate - {path, js_code, protocol, name} + { path, js_code } end defp prepare_js_ast(js_ast) do diff --git a/lib/elixir_script/cli.ex b/lib/elixir_script/cli.ex index 75e1d4d0..9756c2a3 100644 --- a/lib/elixir_script/cli.ex +++ b/lib/elixir_script/cli.ex @@ -64,46 +64,16 @@ defmodule ElixirScript.CLI do root: options[:root], include_path: true, core_path: Keyword.get(options, :core_path, "Elixir"), - full_build: Keyword.get(options, :full_build, false) + full_build: Keyword.get(options, :full_build, false), + output: Keyword.get(options, :output, :stdout) } - compile_output = case options[:elixir] do + case options[:elixir] do true -> ElixirScript.compile(input, compile_opts) _ -> ElixirScript.compile_path(input, compile_opts) end - - case options[:output] do - nil -> - Enum.each(compile_output, - fn - {_, code} -> - IO.write(code) - end) - - output_path -> - Enum.each(compile_output, fn(x) -> - write_to_file(x, output_path) - end) - - ElixirScript.update_protocols(Path.join(output_path, "*.js"), compile_opts) - |> Enum.each(fn - x -> - write_to_file(x, output_path) - end) - - if options[:core_path] == nil do - case ElixirScript.CompilerCache.get(input) do - nil -> - ElixirScript.copy_core_to_destination(output_path) - %{ full_build?: true } -> - ElixirScript.copy_core_to_destination(output_path) - _ -> - nil - end - end - end end defp options_contains_unknown_values(options) do @@ -115,14 +85,4 @@ defmodule ElixirScript.CLI do end end) end - - def write_to_file({ file_path, js_code }, destination) do - file_name = Path.join([destination, file_path]) - - if !File.exists?(Path.dirname(file_name)) do - File.mkdir_p!(Path.dirname(file_name)) - end - - File.write!(file_name, js_code) - end end diff --git a/lib/elixir_script/compiler_cache.ex b/lib/elixir_script/compiler/cache.ex similarity index 97% rename from lib/elixir_script/compiler_cache.ex rename to lib/elixir_script/compiler/cache.ex index d2868bcb..d9bc94dd 100644 --- a/lib/elixir_script/compiler_cache.ex +++ b/lib/elixir_script/compiler/cache.ex @@ -1,4 +1,4 @@ -defmodule ElixirScript.CompilerCache do +defmodule ElixirScript.Compiler.Cache do @moduledoc false require Logger @@ -80,7 +80,7 @@ defmodule ElixirScript.CompilerCache do def new(state) do %{ - files: [], + input_files: [], state: state, full_build?: true } diff --git a/lib/elixir_script/compiler/output.ex b/lib/elixir_script/compiler/output.ex new file mode 100644 index 00000000..75abac83 --- /dev/null +++ b/lib/elixir_script/compiler/output.ex @@ -0,0 +1,62 @@ +defmodule ElixirScript.Compiler.Output do + alias ElixirScript.Compiler.Cache + + def out(_, compiler_output, %{output: nil} = compiler_opts) do + compiler_output ++ ElixirScript.update_protocols(compiler_output, compiler_opts) + |> process_include_path(compiler_opts) + end + + def out(_, compiler_output, %{output: :stdout} = compiler_opts) do + compiler_output ++ ElixirScript.update_protocols(compiler_output, compiler_opts) + |> process_include_path(compiler_opts) + |> Enum.each(fn + {_, code} -> IO.write(code) + code -> IO.write(code) + end) + end + + def out(compiler_input, compiler_output, %{output: output_path, core_path: core_path} = compiler_opts) do + Enum.each(compiler_output, fn(x) -> + write_to_file(x, output_path) + end) + + ElixirScript.update_protocols_in_path(compiler_output, compiler_opts, output_path) + |> Enum.each(fn + x -> + write_to_file(x, output_path) + end) + + if core_path == "Elixir" and Map.get(compiler_opts, :std_lib, false) == false do + case Cache.get(compiler_input) do + nil -> + ElixirScript.copy_core_to_destination(output_path) + %{ full_build?: true } -> + ElixirScript.copy_core_to_destination(output_path) + _ -> + nil + end + end + end + + def write_to_file({ file_path, js_code }, destination) do + file_name = Path.join([destination, file_path]) + + if !File.exists?(Path.dirname(file_name)) do + File.mkdir_p!(Path.dirname(file_name)) + end + + File.write!(file_name, js_code) + end + + defp process_include_path(compiler_output, compiler_opts) do + Enum.map(compiler_output, fn + { path, code } -> + case compiler_opts.include_path do + true -> + { path, code } + false -> + code + end + end) + end +end diff --git a/lib/elixir_script/translator/protocol.ex b/lib/elixir_script/translator/protocol.ex index 1558bb7b..f281eff9 100644 --- a/lib/elixir_script/translator/protocol.ex +++ b/lib/elixir_script/translator/protocol.ex @@ -7,6 +7,7 @@ defmodule ElixirScript.Translator.Protocol do alias ElixirScript.Translator.Function alias ElixirScript.Translator.Utils alias ElixirScript.ModuleSystems + require Logger @doc """ Takes a protocol and turns it into a module @@ -105,7 +106,11 @@ defmodule ElixirScript.Translator.Protocol do default = JS.export_default_declaration(JS.identifier("impls")) + protocol_name = Atom.to_string(name) + body = Enum.flat_map(implementations, fn(x) -> + x = if is_atom(x), do: Atom.to_string(x), else: x + x = String.to_atom(protocol_name <> ".DefImpl." <> x) name = Utils.name_to_js_name(x) imports = ModuleSystems.import_module(name, Utils.make_local_file_path(Utils.name_to_js_file_name(x), compiler_opts.root)) call = JS.call_expression( @@ -119,8 +124,6 @@ defmodule ElixirScript.Translator.Protocol do [imports, call] end) - protocol_name = Atom.to_string(name) - %{ name: String.to_atom(protocol_name <> ".DefImpl"), body: imports ++ [declaration] ++ body ++ [default] diff --git a/lib/elixir_script/translator/stdlib_state.exs b/lib/elixir_script/translator/stdlib_state.exs index 7a4a3847ce08a724b97ee0c706889acf699ad316..aee575e4c31f5d258fabb08fa76aa36c16ff046a 100644 GIT binary patch delta 168 zcmaF=js4+w_6bsq922Dj7&#~Ayc6JY&B?6DEYfpMOwLG6VNjZE=pd$;TacNP3Kh#> zN@3uID)KKaDJU&TVNeFC;)SY$2yULt=*`TyX7YU&4JIbW$qN}Z*)y1u7#Kk8|KgJa sSS7*2|HU^qv3_LaVao>_mCL}uU_3dWNuQ;lD6_1&kbQe0JLA940Gfg~ng9R* delta 122 zcmaF(o&Ehc_6bsq>=UH}7&#{9yps@d&B?6DEYfq%&n?KzNiA|tOwLG6VNjgBkWq#e z%-MW|(VLlZ Date: Wed, 16 Mar 2016 22:35:34 -0500 Subject: [PATCH 187/860] Added version number to cli and mix task. Fixes #166 --- lib/elixir_script.ex | 5 +- lib/elixir_script/cli.ex | 47 +++++++++++------- lib/elixir_script/translator/stdlib_state.exs | Bin 130017 -> 130017 bytes lib/mix/tasks/elixirscript.ex | 17 +------ 4 files changed, 34 insertions(+), 35 deletions(-) diff --git a/lib/elixir_script.ex b/lib/elixir_script.ex index 535017ab..6e30fe3d 100644 --- a/lib/elixir_script.ex +++ b/lib/elixir_script.ex @@ -98,6 +98,7 @@ defmodule ElixirScript do Output.out(path, code, opts) end + @doc false def compile_std_lib() do compiler_opts = build_compiler_options(%{std_lib: true, include_path: true, output: File.cwd!() <> "/priv"}) libs_path = Path.join([__DIR__, "elixir_script", "prelude", "**", "*.ex"]) @@ -210,6 +211,7 @@ defmodule ElixirScript do end) end + @doc false def update_protocols(compiler_output, compiler_opts) do Enum.reduce(compiler_output, %{}, fn {file, code}, state -> @@ -227,6 +229,7 @@ defmodule ElixirScript do |> do_make_defimpl(compiler_opts) end + @doc false def update_protocols_in_path(compiler_output, compiler_opts, output_path) do Enum.reduce(compiler_output, %{}, fn {file, code}, state -> case String.split(file, ".DefImpl.") do @@ -251,7 +254,7 @@ defmodule ElixirScript do end) end - def find_protocols_implementations_in_path(path, protocol_prefix) do + defp find_protocols_implementations_in_path(path, protocol_prefix) do Path.join([path, protocol_prefix <> ".DefImpl*.js"]) |> Path.wildcard |> Enum.filter(fn path -> !String.ends_with?(path, "DefImpl.js") end) diff --git a/lib/elixir_script/cli.ex b/lib/elixir_script/cli.ex index 9756c2a3..a4ee647e 100644 --- a/lib/elixir_script/cli.ex +++ b/lib/elixir_script/cli.ex @@ -1,14 +1,16 @@ defmodule ElixirScript.CLI do @moduledoc false + @app_version Mix.Project.config()[:version] + @switches [ output: :binary, elixir: :boolean, root: :binary, help: :boolean, core_path: :binary, std_lib: :binary, - full_build: :boolean + full_build: :boolean, version: :boolean ] @aliases [ - o: :output, ex: :elixir, h: :help, r: :root + o: :output, ex: :elixir, h: :help, r: :root, v: :version ] def main(argv) do @@ -22,29 +24,38 @@ defmodule ElixirScript.CLI do case parse do { [help: true] , _ , _ } -> :help - { [core: true] , _ , _ } -> :core + { [version: true] , _ , _ } -> :version { options , [input], _ } -> { input, options } _ -> :help end end + def help_message() do + """ + usage: elixirscript [options] + path to elixir files or + the elixir code string if the -ex flag is used + options: + -o --output [path] places output at the given path + -ex --elixir read input as elixir code string + -r --root [path] root import path for all exported modules + --std_lib [path] outputs the elixirscript standard library JavaScript files to the specified path + --full_build informs the compiler to do a full build instead of an incremental one + only used when output is specified + --core_path es6 import path to the elixirscript standard lib + only used with the [output] option. When used, Elixir.js is not exported + -v --version the current version number + -h --help this message + """ + end + def process(:help) do - IO.write """ - usage: elixirscript [options] - path to elixir files or - the elixir code string if the -ex flag is used - options: - -o --output [path] places output at the given path - -ex --elixir read input as elixir code string - -r --root [path] root import path for all exported modules - --std_lib [path] outputs the elixirscript standard library JavaScript files to the specified path - --full_build informs the compiler to do a full build instead of an incremental one - only used when output is specified - --core_path es6 import path to the elixirscript standard lib - only used with the [output] option. When used, Elixir.js is not exported - -h --help this message - """ + IO.write help_message + end + + def process(:version) do + IO.write @app_version end def process([std_lib: path]) do diff --git a/lib/elixir_script/translator/stdlib_state.exs b/lib/elixir_script/translator/stdlib_state.exs index aee575e4c31f5d258fabb08fa76aa36c16ff046a..88d749e1de8678b688282339cb0b3b0cf3aa4850 100644 GIT binary patch delta 62 zcmaF(o&Di=_6-)SOpHILCw^y?ocx+mfIWjLiGhLf=VV1q@yS9=A}D-YCidoCtlM|7 IGOB+A0Jc9AEC2ui delta 62 zcmaF(o&Di=_6-)SOiYZ^6TdS`PJYcOz@EXB#K6GBI9X9se6kRe2nyepiM@Fj>-Jr& HjOyP2QsEIt diff --git a/lib/mix/tasks/elixirscript.ex b/lib/mix/tasks/elixirscript.ex index 05b3fb33..72590b5a 100644 --- a/lib/mix/tasks/elixirscript.ex +++ b/lib/mix/tasks/elixirscript.ex @@ -1,20 +1,5 @@ defmodule Mix.Tasks.Elixirscript do - @moduledoc """ - Translate Elixir code to javascript - - usage: mix elixirscript [options] - path to elixir files or the elixir code string if the -ex flag is used - options: - -o --output [path] places output at the given path - -ex --elixir read input as elixir code string - -r --root [path] root import path for all exported modules - --std_lib [path] outputs the elixirscript standard library JavaScript files to the specified path - --full_build informs the compiler to do a full build instead of an incremental one - only used when output is specified - --core_path es6 import path to the elixirscript standard lib - only used with the [output] option. When used, elixir.js is not exported - -h --help this message - """ + @moduledoc ElixirScript.CLI.help_message use Mix.Task From 795bfcc7684062d6c1757b4398ba2e0aad4eb807 Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Wed, 16 Mar 2016 22:44:31 -0500 Subject: [PATCH 188/860] renamed copy_core_to_destination to copy_stdlib_to_destination --- lib/elixir_script.ex | 13 ++----------- lib/elixir_script/cli.ex | 2 +- lib/elixir_script/compiler/output.ex | 10 +++------- lib/elixir_script/translator/stdlib_state.exs | Bin 130017 -> 130017 bytes 4 files changed, 6 insertions(+), 19 deletions(-) diff --git a/lib/elixir_script.ex b/lib/elixir_script.ex index 6e30fe3d..360641c9 100644 --- a/lib/elixir_script.ex +++ b/lib/elixir_script.ex @@ -267,25 +267,16 @@ defmodule ElixirScript do end @doc """ - Copies the javascript that makes up the ElixirScript core + Copies the javascript that makes up the ElixirScript stdlib to the specified location """ - def copy_core_to_destination(destination) do + def copy_stdlib_to_destination(destination) do Enum.each(Path.wildcard(operating_path <> @js_core_path), fn(path) -> base = Path.basename(path) File.cp!(path, Path.join([destination, base])) end) end - @doc """ - Returns the elixirscript core js code - """ - def elixirscript_core() do - Enum.each(Path.wildcard(operating_path <> @js_core_path), fn(path) -> - File.read!(path) - end) - end - defp convert_to_code(js_ast) do process_module(js_ast) |> javascript_ast_to_code diff --git a/lib/elixir_script/cli.ex b/lib/elixir_script/cli.ex index a4ee647e..c27f6f0e 100644 --- a/lib/elixir_script/cli.ex +++ b/lib/elixir_script/cli.ex @@ -59,7 +59,7 @@ defmodule ElixirScript.CLI do end def process([std_lib: path]) do - ElixirScript.copy_core_to_destination(path) + ElixirScript.copy_stdlib_to_destination(path) end def process({ input, options }) do diff --git a/lib/elixir_script/compiler/output.ex b/lib/elixir_script/compiler/output.ex index 75abac83..6cdbce6f 100644 --- a/lib/elixir_script/compiler/output.ex +++ b/lib/elixir_script/compiler/output.ex @@ -27,13 +27,9 @@ defmodule ElixirScript.Compiler.Output do end) if core_path == "Elixir" and Map.get(compiler_opts, :std_lib, false) == false do - case Cache.get(compiler_input) do - nil -> - ElixirScript.copy_core_to_destination(output_path) - %{ full_build?: true } -> - ElixirScript.copy_core_to_destination(output_path) - _ -> - nil + cache = Cache.get(compiler_input) + if cache == nil or Map.get(cache, :full_build?) == true do + ElixirScript.copy_stdlib_to_destination(output_path) end end end diff --git a/lib/elixir_script/translator/stdlib_state.exs b/lib/elixir_script/translator/stdlib_state.exs index 88d749e1de8678b688282339cb0b3b0cf3aa4850..4d49d50292cc36a9b35f3ffa85fcba01785881c3 100644 GIT binary patch delta 67 zcmaF(o&Di=_6_{3jB6(guxc{?ou2reQF8KYMgjH=rX&Ui#=nylHN__jF^Qn?ZJF4c Ncd>5Y#mcDu4FDM;6^sA? delta 67 zcmaF(o&Di=_6_{3jB6$fuxc{?oSyidQF8KYMgjH=rX&Ui#-EcFHN__jF^Qn?ZJF4c Ncd>5Y#mcDu4FDHS6@LH# From 9fc85f80da5a980d5e7c806aa5b4654b0748c3fe Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Wed, 16 Mar 2016 22:55:52 -0500 Subject: [PATCH 189/860] Updated docs --- lib/elixir_script.ex | 14 +++++++------- lib/mix/tasks/elixirscript.ex | 2 -- 2 files changed, 7 insertions(+), 9 deletions(-) diff --git a/lib/elixir_script.ex b/lib/elixir_script.ex index 360641c9..a4436061 100644 --- a/lib/elixir_script.ex +++ b/lib/elixir_script.ex @@ -23,12 +23,12 @@ defmodule ElixirScript do * `:root` - a binary path prepended to the path of the standard lib imports if needed * `:env` - a Macro.env struct to use. This is most useful when using macros. Make sure that the * `:core_path` - The es6 import path used to import the elixirscript core. + When using this option, the Elixir.js file is not exported * `:full_build` - For compile_path, tells the compiler to perform a full build instead of incremental one * `:output` - option to tell compiler how to output data - `nil`: Return as list - `:stdout`: Write to standard out - `path (string)`: Write to specified path - When using this option, the Elixir.js file is not exported + * `nil`: Return as list + * `:stdout`: Write to standard out + * `path (string)`: Write to specified path """ defmacro __using__(_) do @@ -49,7 +49,7 @@ defmodule ElixirScript do @doc """ Compiles the given Elixir code string """ - @spec compile(binary, Map.t) :: [binary | {binary, binary}] + @spec compile(binary, Map.t) :: [binary | {binary, binary} | :ok] def compile(elixir_code, opts \\ %{}) do elixir_code |> Code.string_to_quoted! @@ -59,7 +59,7 @@ defmodule ElixirScript do @doc """ Compiles the given Elixir code in quoted form """ - @spec compile_quoted(Macro.t, Map.t) :: [binary | {binary, binary}] + @spec compile_quoted(Macro.t, Map.t) :: [binary | {binary, binary} | :ok] def compile_quoted(quoted, opts \\ %{}) do { code, _ } = do_compile(opts, [quoted]) Output.out(quoted, code, build_compiler_options(opts)) @@ -68,7 +68,7 @@ defmodule ElixirScript do @doc """ Compiles the elixir files found at the given path """ - @spec compile_path(binary, Map.t) :: [binary | {binary, binary}] + @spec compile_path(binary, Map.t) :: [binary | {binary, binary} | :ok] def compile_path(path, opts \\ %{}) do expanded_path = Path.wildcard(path) diff --git a/lib/mix/tasks/elixirscript.ex b/lib/mix/tasks/elixirscript.ex index 72590b5a..9d1f5599 100644 --- a/lib/mix/tasks/elixirscript.ex +++ b/lib/mix/tasks/elixirscript.ex @@ -1,6 +1,4 @@ defmodule Mix.Tasks.Elixirscript do - @moduledoc ElixirScript.CLI.help_message - use Mix.Task @shortdoc "Translate Elixir to JavaScript" From 66029dc64f38e5f453b6946dfb0f0255a555709e Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Thu, 17 Mar 2016 14:41:05 -0500 Subject: [PATCH 190/860] Only compiling modules now that have changed --- lib/elixir_script/translator/state.ex | 23 +++++++++++++++--- lib/elixir_script/translator/stdlib_state.exs | Bin 130017 -> 130017 bytes 2 files changed, 20 insertions(+), 3 deletions(-) diff --git a/lib/elixir_script/translator/state.ex b/lib/elixir_script/translator/state.ex index b7353f54..edb889c1 100644 --- a/lib/elixir_script/translator/state.ex +++ b/lib/elixir_script/translator/state.ex @@ -58,7 +58,7 @@ defmodule ElixirScript.Translator.State do def add_module(module) do Agent.update(__MODULE__, fn state -> - %{ state | modules: Map.put(state.modules, module.name, module), added_modules: Set.put(state.added_modules, module.name) } + do_add_module_to_state(state, module) end) end @@ -78,7 +78,7 @@ defmodule ElixirScript.Translator.State do proto = %ElixirScript.Module{proto | functions: functions, type: :protocol } end - %{ state | modules: Map.put(state.modules, name, proto), added_modules: Set.put(state.added_modules, name) } + do_add_module_to_state(state, proto) end) end @@ -96,10 +96,27 @@ defmodule ElixirScript.Translator.State do proto_impl = %ElixirScript.Module{ name: module_name, body: impl, impl_type: type, type: :protocol_implementation } - %{ state | modules: Map.put(state.modules, module_name, proto_impl), added_modules: Set.put(state.added_modules, module_name) } + do_add_module_to_state(state, proto_impl) end) end + defp do_add_module_to_state(state, module) do + update_added = case state.modules[module.name] do + %ElixirScript.Module{ type: :protocol } = old_module -> + old_module.functions !== module.functions + %ElixirScript.Module{} = old_module -> + old_module.body !== module.body + nil -> + true + end + + if update_added do + %{ state | modules: Map.put(state.modules, module.name, module), added_modules: Set.put(state.added_modules, module.name) } + else + %{ state | modules: Map.put(state.modules, module.name, module) } + end + end + def get do Agent.get(__MODULE__, &(&1)) end diff --git a/lib/elixir_script/translator/stdlib_state.exs b/lib/elixir_script/translator/stdlib_state.exs index 4d49d50292cc36a9b35f3ffa85fcba01785881c3..452d27b137c07ec2f87145cebd09153fe81bc5ed 100644 GIT binary patch delta 61 zcmaF(o&Di=_6?S-jQ^)6erJ@N{F+gKJ%cHUfr0V=WJOK!$wEvbD12Kc_U2uz+jp@t Hs(%9jv&j@a delta 61 zcmaF(o&Di=_6?S-jDM#merJ@N{F+gKJ%cHUfr0VwWJOK!$wEvbD12Kc_U2uz+jp@t Hs(%9jvilS_ From bba55f467da71fcf5c0ccec91b9a07f05ec6ed69 Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Thu, 17 Mar 2016 15:41:28 -0500 Subject: [PATCH 191/860] Updated changelog --- CHANGELOG.md | 19 ++++++++++++++---- lib/elixir_script.ex | 7 ++++++- lib/elixir_script/cli.ex | 6 +++--- lib/elixir_script/translator/stdlib_state.exs | Bin 130017 -> 130017 bytes 4 files changed, 24 insertions(+), 8 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index ba15b37a..72874597 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,4 +1,15 @@ # v0.17.0-dev +* Enhancements + * Incremental Compilation: + Now ElixirScript will only build files and modules that have changed since the last build + * Added `output` as an option for compiler functions. This controls whether output is returned as a list of tuples, send to stdout, or saved to a file path + * Added `:full_build` as an option for compiler functions and `--full-build` option to CLI. These tell the compiler to perform a full build + * Added `--version` option to CLI. Outputs current version of elixirscript + * Added `--std-lib` option to CLI. Takes a path and adds the stdlib to that path + +* Breaking + * Removed `--core` option from CLI and `:core` compiler option. + * Renamed `copy_core_to_destination` to `copy_stdlib_to_destination` # v0.16.0 * Enhancements @@ -13,10 +24,10 @@ conveniently, `object(a: "b")` which turns into `{a: "b"}`. **NOTE**: when updating the created by, you still have to use the string form `%{ my_map | "a" => "c" }` - + * Bugfixes * Optional parameters should now work as expected - + * Breaking * `JS.update(object, property, value)` has been removed and replaced with `JS.update(object, map)` This allows you to update multiple values on a javascript object at once. @@ -24,10 +35,10 @@ # v0.15.2 * Enhancements * Support for variables as map keys - + * Bug fixes * Fixed protocol implementations for Integer and Float which where not recognized - * Fixed calling properties on non-objects + * Fixed calling properties on non-objects # v0.15.1 * Bug fixes diff --git a/lib/elixir_script.ex b/lib/elixir_script.ex index a4436061..91d6e534 100644 --- a/lib/elixir_script.ex +++ b/lib/elixir_script.ex @@ -100,7 +100,12 @@ defmodule ElixirScript do @doc false def compile_std_lib() do - compiler_opts = build_compiler_options(%{std_lib: true, include_path: true, output: File.cwd!() <> "/priv"}) + compile_std_lib(Path.join([File.cwd!, "priv"])) + end + + @doc false + def compile_std_lib(output_path) do + compiler_opts = build_compiler_options(%{std_lib: true, include_path: true, output: output_path}) libs_path = Path.join([__DIR__, "elixir_script", "prelude", "**", "*.ex"]) code = Path.wildcard(libs_path) diff --git a/lib/elixir_script/cli.ex b/lib/elixir_script/cli.ex index c27f6f0e..774ef03f 100644 --- a/lib/elixir_script/cli.ex +++ b/lib/elixir_script/cli.ex @@ -40,10 +40,10 @@ defmodule ElixirScript.CLI do -o --output [path] places output at the given path -ex --elixir read input as elixir code string -r --root [path] root import path for all exported modules - --std_lib [path] outputs the elixirscript standard library JavaScript files to the specified path - --full_build informs the compiler to do a full build instead of an incremental one + --std-lib [path] outputs the elixirscript standard library JavaScript files to the specified path + --full-build informs the compiler to do a full build instead of an incremental one only used when output is specified - --core_path es6 import path to the elixirscript standard lib + --core-path es6 import path to the elixirscript standard lib only used with the [output] option. When used, Elixir.js is not exported -v --version the current version number -h --help this message diff --git a/lib/elixir_script/translator/stdlib_state.exs b/lib/elixir_script/translator/stdlib_state.exs index 452d27b137c07ec2f87145cebd09153fe81bc5ed..e830ce14ed94e2948621af3aea9167a904eab3b6 100644 GIT binary patch delta 81 zcmaF(o&Di=_6>}z{ACOvkix){lbM&AxM{Kgt0v>+>51PNB`3dT6kyL_N@8GOygXS^ YQ+%=zlL!jmmWjQ27wh(2tc>d40R6=m`Tzg` delta 81 zcmaF(o&Di=_6>}z{N)TFkix){lbM&AxOTDtt0v?B>51PNB`3dT6kyL_N@8GO{6ASy YQ+%=zlL!jmmWjQ27wh(2tc>d401mPkdH?_b From 3164c74dd598e13408a87399c11cf23ad21b4bd9 Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Fri, 18 Mar 2016 18:23:05 -0500 Subject: [PATCH 192/860] Refactored ElixirScript module and added more documentation --- lib/elixir_script.ex | 29 ++++++++++------------------- 1 file changed, 10 insertions(+), 19 deletions(-) diff --git a/lib/elixir_script.ex b/lib/elixir_script.ex index 91d6e534..7ac64832 100644 --- a/lib/elixir_script.ex +++ b/lib/elixir_script.ex @@ -22,6 +22,7 @@ defmodule ElixirScript do or a tuple of the file name and the JavaScript code * `:root` - a binary path prepended to the path of the standard lib imports if needed * `:env` - a Macro.env struct to use. This is most useful when using macros. Make sure that the + env has the macros imported or required. * `:core_path` - The es6 import path used to import the elixirscript core. When using this option, the Elixir.js file is not exported * `:full_build` - For compile_path, tells the compiler to perform a full build instead of incremental one @@ -41,11 +42,10 @@ defmodule ElixirScript do end end + # This is the serialized state of the ElixirScript.State module containing references to the standard library @external_resource stdlib_state_path = Path.join([__DIR__, "elixir_script", "translator", "stdlib_state.exs"]) @stdlib_state File.read!(stdlib_state_path) - @js_core_path "/*.js" - @doc """ Compiles the given Elixir code string """ @@ -181,11 +181,8 @@ defmodule ElixirScript do defp create_code(compiler_opts) do parent = self - state = ElixirScript.Translator.State.get - standard_lib_modules = Map.values(state.std_lib_map) |> Enum.map(&to_string(&1)) - Map.values(state.modules) |> Enum.reject(fn(ast) -> not ast.name in state.added_modules @@ -204,7 +201,7 @@ defmodule ElixirScript do end - result = convert_to_code(module) + result = javascript_ast_to_code(module) send parent, { self, result } end @@ -255,7 +252,7 @@ defmodule ElixirScript do ElixirScript.Translator.Protocol.make_defimpl(protocol, Enum.uniq(implementations), compiler_opts) end) |> Enum.map(fn(module) -> - convert_to_code(module) + javascript_ast_to_code(module) end) end @@ -276,24 +273,16 @@ defmodule ElixirScript do to the specified location """ def copy_stdlib_to_destination(destination) do - Enum.each(Path.wildcard(operating_path <> @js_core_path), fn(path) -> + Enum.each(Path.wildcard(Path.join([operating_path, "*.js"])), fn(path) -> base = Path.basename(path) File.cp!(path, Path.join([destination, base])) end) end - defp convert_to_code(js_ast) do - process_module(js_ast) - |> javascript_ast_to_code - end - - defp process_module(module) do - file_path = Utils.name_to_js_file_name(module.name) <> ".js" - - { file_path, Builder.program(module.body) } - end + defp javascript_ast_to_code(module) do + path = Utils.name_to_js_file_name(module.name) <> ".js" + js_ast = Builder.program(module.body) - defp javascript_ast_to_code({path, js_ast}) do js_code = js_ast |> prepare_js_ast |> Generator.generate @@ -316,6 +305,8 @@ defmodule ElixirScript do js_ast end + #Gets path to js files whether the mix project is available + #or when used as an escript defp operating_path do try do Mix.Project.build_path <> "/lib/elixir_script/priv" From 87dc930660caf447e21f8e38adc142ed131fc9da Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Fri, 18 Mar 2016 19:17:41 -0500 Subject: [PATCH 193/860] More refactoring and documentation updates --- lib/elixir_script/compiler/output.ex | 1 + lib/elixir_script/translator.ex | 14 ++++++++++++-- 2 files changed, 13 insertions(+), 2 deletions(-) diff --git a/lib/elixir_script/compiler/output.ex b/lib/elixir_script/compiler/output.ex index 6cdbce6f..6b785501 100644 --- a/lib/elixir_script/compiler/output.ex +++ b/lib/elixir_script/compiler/output.ex @@ -1,4 +1,5 @@ defmodule ElixirScript.Compiler.Output do + @moduledoc false alias ElixirScript.Compiler.Cache def out(_, compiler_output, %{output: nil} = compiler_opts) do diff --git a/lib/elixir_script/translator.ex b/lib/elixir_script/translator.ex index 3c644cd0..9f52d094 100644 --- a/lib/elixir_script/translator.ex +++ b/lib/elixir_script/translator.ex @@ -1,6 +1,7 @@ defmodule ElixirScript.Translator do @moduledoc """ - Translates Elixir AST into JavaScript AST + Translates the given Elixir AST into + JavaScript AST. """ alias ElixirScript.Translator.Primitive alias ElixirScript.Translator.Expression @@ -24,6 +25,8 @@ defmodule ElixirScript.Translator do alias ESTree.Tools.Builder, as: JS alias ElixirScript.Translator.Rewriter + # A list of erlang modules. These are rewritten into equivalent + # JavaScript functions using ElixirScript.Translator.Rewriter @erlang_modules [ :erlang, :maps, @@ -37,6 +40,13 @@ defmodule ElixirScript.Translator do :file ] + @module_attributes_to_ignore [ + :doc, :moduledoc, :type, :typep, :spec, + :opaque, :callback, :macrocallback, :after_compile, + :before_compile, :behaviour, :compile, :file, + :on_definition, :on_load, :dialyzer, :vsn, :external_resource + ] + @doc """ Translates the given Elixir AST to JavaScript AST. The given `env` is a `ElixirScript.Macro.Env` used to track the variables, imports, aliases, and scopes like `Macro.Env`. The JavaScript AST and @@ -152,7 +162,7 @@ defmodule ElixirScript.Translator do end defp do_translate({:@, _, [{name, _, _}]}, env) - when name in [:doc, :moduledoc, :type, :typep, :spec, :opaque, :callback, :macrocallback, :after_compile, :before_compile, :behaviour, :compile, :file, :on_definition, :on_load, :dialyzer, :vsn, :external_resource] do + when name in @module_attributes_to_ignore do { %ElixirScript.Translator.Group{}, env } end From a76b273093c92b4ba82af36c142fc8c3a910862d Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Sat, 19 Mar 2016 06:43:07 -0500 Subject: [PATCH 194/860] Got pattern matching tests running again --- lib/elixir_script/translator.ex | 8 +- test/translator/pattern_matching_test.exs | 457 +++++++++++----------- 2 files changed, 231 insertions(+), 234 deletions(-) diff --git a/lib/elixir_script/translator.ex b/lib/elixir_script/translator.ex index 9f52d094..7a67f853 100644 --- a/lib/elixir_script/translator.ex +++ b/lib/elixir_script/translator.ex @@ -583,8 +583,12 @@ defmodule ElixirScript.Translator do end def has_function?(module_name, name_arity) do - module = ElixirScript.Translator.State.get_module(module_name) - name_arity in module.functions or name_arity in module.private_functions + case ElixirScript.Translator.State.get_module(module_name) do + nil -> + false + module -> + name_arity in module.functions or name_arity in module.private_functions + end end end diff --git a/test/translator/pattern_matching_test.exs b/test/translator/pattern_matching_test.exs index 9e0dca5c..45b63ef7 100644 --- a/test/translator/pattern_matching_test.exs +++ b/test/translator/pattern_matching_test.exs @@ -6,237 +6,230 @@ defmodule ElixirScript.Translator.PatternMatching.Test do alias ElixirScript.Translator.Map alias ESTree.Tools.Builder, as: JS -# test "match wildcard" do -# params = [{:_, [], Test}] -# result = PatternMatching.build_match(params, ElixirScript.Translator.Env.module_env(ElixirScript.Temp, "temp.ex") ) -# expected_result = { [PatternMatching.wildcard], [JS.identifier(:undefined)] } -# -# assert result == expected_result -# end -# -# test "match one identifier param" do -# params = [{:a, [], Test}] -# result = PatternMatching.build_match(params, ElixirScript.Translator.Env.module_env(ElixirScript.Temp, "temp.ex") ) -# expected_result = {[PatternMatching.parameter], [JS.identifier("a")]} -# -# assert result == expected_result -# end -# -# test "match multiple identifier params" do -# params = [{:a, [], Test}, {:b, [], Test}, {:c, [], Test}] -# result = PatternMatching.build_match(params, ElixirScript.Translator.Env.module_env(ElixirScript.Temp, "temp.ex") ) -# expected_result = { -# List.duplicate(PatternMatching.parameter, 3), -# [JS.identifier("a"), JS.identifier("b"), JS.identifier("c")] -# } -# -# assert result == expected_result -# end -# -# test "match head and tail param" do -# params = [[{:|, [], [{:head, [], Elixir}, {:tail, [], Elixir}]}]] -# result = PatternMatching.build_match(params, ElixirScript.Translator.Env.module_env(ElixirScript.Temp, "temp.ex") ) -# expected_result = { -# [PatternMatching.head_tail], -# [JS.identifier("head"), JS.identifier("tail")] -# } -# -# assert result == expected_result -# end -# -# test "match prefix param" do -# params = [{:<>, [context: Elixir, import: Elixir.Kernel], ["Bearer ", {:token, [], Elixir}]}] -# result = PatternMatching.build_match(params, ElixirScript.Translator.Env.module_env(ElixirScript.Temp, "temp.ex") ) -# expected_result = { -# [PatternMatching.starts_with("Bearer ")], -# [JS.identifier("token")] -# } -# -# assert result == expected_result -# end -# -# test "match list" do -# params = [[{:a, [], Elixir}, {:b, [], Elixir}, {:c, [], Elixir}]] -# result = PatternMatching.build_match(params, ElixirScript.Translator.Env.module_env(ElixirScript.Temp, "temp.ex") ) -# expected_result = { -# [Primitive.make_list_no_translate(List.duplicate(PatternMatching.parameter, 3))], -# [JS.identifier("a"), JS.identifier("b"), JS.identifier("c")] -# } -# -# assert result == expected_result -# end -# -# test "match list with a literal" do -# params = [[1, {:b, [], Elixir}, {:c, [], Elixir}]] -# result = PatternMatching.build_match(params, ElixirScript.Translator.Env.module_env(ElixirScript.Temp, "temp.ex") ) -# expected_result = { -# [Primitive.make_list_no_translate([JS.literal(1), PatternMatching.parameter, PatternMatching.parameter])], -# [JS.identifier("b"), JS.identifier("c")] -# } -# -# assert result == expected_result -# end -# -# test "match number" do -# params = [1] -# result = PatternMatching.build_match(params, ElixirScript.Translator.Env.module_env(ElixirScript.Temp, "temp.ex") ) -# expected_result = { -# [JS.literal(1)], -# [] -# } -# -# assert result == expected_result -# end -# -# test "match struct pattern" do -# ElixirScript.Translator.State.start_link(nil, nil) -# -# params = [{:%, [], [{:__aliases__, [alias: false], [:Hello]}, {:%{}, [], []}]}] -# result = PatternMatching.build_match(params, ElixirScript.Translator.Env.module_env(ElixirScript.Temp, "temp.ex") ) -# expected_result = { -# [PatternMatching.type(JS.identifier(:Hello), JS.object_expression([]))], -# [] -# } -# -# assert result == expected_result -# -# ElixirScript.Translator.State.stop() -# end -# -# test "match struct pattern with property" do -# ElixirScript.Translator.State.start_link(nil, nil) -# -# params = [{:%, [], [{:__aliases__, [alias: false], [:Hello]}, {:%{}, [], [key: 1]}]}] -# result = PatternMatching.build_match(params, ElixirScript.Translator.Env.module_env(ElixirScript.Temp, "temp.ex") ) -# expected_result = { -# [PatternMatching.type(JS.identifier(:Hello), JS.object_expression([ -# Map.make_property(Translator.translate!(:key, ElixirScript.Translator.Env.module_env(ElixirScript.Temp, "temp.ex") ), Translator.translate!(1, ElixirScript.Translator.Env.module_env(ElixirScript.Temp, "temp.ex") )) -# ])) -# ], -# [] -# } -# -# assert result == expected_result -# -# ElixirScript.Translator.State.stop() -# end -# -# test "match struct pattern with property param" do -# ElixirScript.Translator.State.start_link(nil, nil) -# -# params = [{:%, [], [{:__aliases__, [alias: false], [:Hello]}, {:%{}, [], [key: {:key, [], Elixir }]}]}] -# result = PatternMatching.build_match(params, ElixirScript.Translator.Env.module_env(ElixirScript.Temp, "temp.ex") ) -# expected_result = { -# [PatternMatching.type(JS.identifier(:Hello), JS.object_expression([ -# Map.make_property(Translator.translate!(:key, ElixirScript.Translator.Env.module_env(ElixirScript.Temp, "temp.ex") ), PatternMatching.parameter) -# ])) -# ], -# [JS.identifier("key")] -# } -# -# assert result == expected_result -# -# ElixirScript.Translator.State.stop() -# -# end -# -# test "capture parameter when assigning it" do -# ElixirScript.Translator.State.start_link(nil, nil) -# -# params = [{:=, [], [1, {:a, [], Elixir}]}] -# result = PatternMatching.build_match(params, ElixirScript.Translator.Env.module_env(ElixirScript.Temp, "temp.ex") ) -# expected_result = { -# [PatternMatching.capture(JS.literal(1))], -# [JS.identifier("a")] -# } -# -# assert result == expected_result -# -# -# params = [{:=, [], [{:a, [], Elixir}, 1]}] -# result = PatternMatching.build_match(params, ElixirScript.Translator.Env.module_env(ElixirScript.Temp, "temp.ex") ) -# expected_result = { -# [PatternMatching.capture(JS.literal(1))], -# [JS.identifier("a")] -# } -# -# assert result == expected_result -# -# -# params = [{:=, [], [{:%, [], [{:__aliases__, [alias: false], [:AStruct]}, {:%{}, [], []}]}, {:a, [], ElixirScript.Translator.Function.Test}]}] -# result = PatternMatching.build_match(params, ElixirScript.Translator.Env.module_env(ElixirScript.Temp, "temp.ex") ) -# expected_result = { -# [PatternMatching.capture(PatternMatching.type(JS.identifier(:AStruct), JS.object_expression([])))], -# [JS.identifier("a")] -# } -# -# assert result == expected_result -# -# ElixirScript.Translator.State.stop() -# end -# -# test "match and assign list" do -# params = [{:=, [], [[{:a, [], Elixir}, {:b, [], Elixir}, {:c, [], Elixir}], {:d, [], Elixir}]}] -# result = PatternMatching.build_match(params, ElixirScript.Translator.Env.module_env(ElixirScript.Temp, "temp.ex") ) -# expected_result = { -# [PatternMatching.capture(Primitive.make_list_no_translate([PatternMatching.parameter, PatternMatching.parameter, PatternMatching.parameter]))], -# [JS.identifier("a"), JS.identifier("b"), JS.identifier("c"), JS.identifier("d")] -# } -# -# assert result == expected_result -# end -# -# test "match on tuple" do -# params = [{:{}, [], [1, {:b, [], Elixir}, 3]}] -# result = PatternMatching.build_match(params, ElixirScript.Translator.Env.module_env(ElixirScript.Temp, "temp.ex") ) -# expected_result = { -# [PatternMatching.type(Primitive.tuple_class, JS.object_expression([JS.property( -# JS.identifier("values"), -# JS.array_expression([JS.literal(1), PatternMatching.parameter, JS.literal(3)]) -# ) ] )) ], -# [JS.identifier("b")] -# } -# -# assert result == expected_result -# -# params = [{1, {:b, [], Elixir}}] -# result = PatternMatching.build_match(params, ElixirScript.Translator.Env.module_env(ElixirScript.Temp, "temp.ex") ) -# expected_result = { -# [PatternMatching.type(Primitive.tuple_class, JS.object_expression([JS.property( -# JS.identifier("values"), -# JS.array_expression([JS.literal(1), PatternMatching.parameter]) -# ) ] )) ], -# [JS.identifier("b")] -# } -# -# assert result == expected_result -# end -# -# test "match on map" do -# params = [{:%{}, [], [which: 13]}] -# result = PatternMatching.build_match(params, ElixirScript.Translator.Env.module_env(ElixirScript.Temp, "temp.ex") ) -# -# expected_result = { -# [JS.object_expression([ -# Map.make_property(Translator.translate!(:which, ElixirScript.Translator.Env.module_env(ElixirScript.Temp, "temp.ex") ), JS.literal(13)) -# ])], -# [] -# } -# -# assert result == expected_result -# end -# -# -# test "match on bound value" do -# params = [{:^, [], [{:a, [], Elixir}]}] -# result = PatternMatching.build_match(params, ElixirScript.Translator.Env.module_env(ElixirScript.Temp, "temp.ex") ) -# -# expected_result = { -# [PatternMatching.bound(JS.identifier("a"))], -# [nil] -# } -# -# assert result == expected_result -# end + @std_lib_state File.read!(File.cwd!() <> "/lib/elixir_script/translator/stdlib_state.exs") + + setup do + ElixirScript.Translator.State.start_link(%{env: ElixirScript.custom_env}) + ElixirScript.Translator.State.deserialize(@std_lib_state) + + # Returns extra metadata, it must be a dict + {:ok, []} + end + + test "match wildcard" do + params = [{:_, [], Test}] + result = PatternMatching.build_match(params, ElixirScript.Translator.Env.module_env(ElixirScript.Temp, "temp.ex") ) + expected_result = { [PatternMatching.wildcard], [JS.identifier(:undefined)] } + + assert result == expected_result + end + + test "match one identifier param" do + params = [{:a, [], Test}] + result = PatternMatching.build_match(params, ElixirScript.Translator.Env.module_env(ElixirScript.Temp, "temp.ex") ) + expected_result = {[PatternMatching.parameter], [JS.identifier("a")]} + + assert result == expected_result + end + + test "match multiple identifier params" do + params = [{:a, [], Test}, {:b, [], Test}, {:c, [], Test}] + result = PatternMatching.build_match(params, ElixirScript.Translator.Env.module_env(ElixirScript.Temp, "temp.ex") ) + expected_result = { + List.duplicate(PatternMatching.parameter, 3), + [JS.identifier("a"), JS.identifier("b"), JS.identifier("c")] + } + + assert result == expected_result + end + + test "match head and tail param" do + params = [[{:|, [], [{:head, [], Elixir}, {:tail, [], Elixir}]}]] + result = PatternMatching.build_match(params, ElixirScript.Translator.Env.module_env(ElixirScript.Temp, "temp.ex") ) + expected_result = { + [PatternMatching.head_tail(PatternMatching.parameter, PatternMatching.parameter)], + [JS.identifier("head"), JS.identifier("tail")] + } + + assert result == expected_result + end + + test "match prefix param" do + params = [{:<>, [context: Elixir, import: Elixir.Kernel], ["Bearer ", {:token, [], Elixir}]}] + result = PatternMatching.build_match(params, ElixirScript.Translator.Env.module_env(ElixirScript.Temp, "temp.ex") ) + expected_result = { + [PatternMatching.starts_with("Bearer ")], + [JS.identifier("token")] + } + + assert result == expected_result + end + + test "match list" do + params = [[{:a, [], Elixir}, {:b, [], Elixir}, {:c, [], Elixir}]] + result = PatternMatching.build_match(params, ElixirScript.Translator.Env.module_env(ElixirScript.Temp, "temp.ex") ) + expected_result = { + [Primitive.make_list_no_translate(List.duplicate(PatternMatching.parameter, 3))], + [JS.identifier("a"), JS.identifier("b"), JS.identifier("c")] + } + + assert result == expected_result + end + + test "match list with a literal" do + params = [[1, {:b, [], Elixir}, {:c, [], Elixir}]] + result = PatternMatching.build_match(params, ElixirScript.Translator.Env.module_env(ElixirScript.Temp, "temp.ex") ) + expected_result = { + [Primitive.make_list_no_translate([JS.literal(1), PatternMatching.parameter, PatternMatching.parameter])], + [JS.identifier("b"), JS.identifier("c")] + } + + assert result == expected_result + end + + test "match number" do + params = [1] + result = PatternMatching.build_match(params, ElixirScript.Translator.Env.module_env(ElixirScript.Temp, "temp.ex") ) + expected_result = { + [JS.literal(1)], + [] + } + + assert result == expected_result + end + + test "match struct pattern" do + params = [{:%, [], [{:__aliases__, [alias: false], [:Hello]}, {:%{}, [], []}]}] + result = PatternMatching.build_match(params, ElixirScript.Translator.Env.module_env(ElixirScript.Temp, "temp.ex") ) + expected_result = { + [PatternMatching.type(JS.identifier(:Hello), JS.object_expression([]))], + [] + } + + assert result == expected_result + end + + test "match struct pattern with property" do + params = [{:%, [], [{:__aliases__, [alias: false], [:Hello]}, {:%{}, [], [key: 1]}]}] + result = PatternMatching.build_match(params, ElixirScript.Translator.Env.module_env(ElixirScript.Temp, "temp.ex") ) + expected_result = { + [PatternMatching.type(JS.identifier(:Hello), JS.object_expression([ + Map.make_property(Translator.translate!(:key, ElixirScript.Translator.Env.module_env(ElixirScript.Temp, "temp.ex") ), Translator.translate!(1, ElixirScript.Translator.Env.module_env(ElixirScript.Temp, "temp.ex") )) + ])) + ], + [] + } + + assert result == expected_result + end + + test "match struct pattern with property param" do + params = [{:%, [], [{:__aliases__, [alias: false], [:Hello]}, {:%{}, [], [key: {:key, [], Elixir }]}]}] + result = PatternMatching.build_match(params, ElixirScript.Translator.Env.module_env(ElixirScript.Temp, "temp.ex") ) + expected_result = { + [PatternMatching.type(JS.identifier(:Hello), JS.object_expression([ + Map.make_property(Translator.translate!(:key, ElixirScript.Translator.Env.module_env(ElixirScript.Temp, "temp.ex") ), PatternMatching.parameter) + ])) + ], + [JS.identifier("key")] + } + + assert result == expected_result + end + + test "capture parameter when assigning it" do + params = [{:=, [], [1, {:a, [], Elixir}]}] + result = PatternMatching.build_match(params, ElixirScript.Translator.Env.module_env(ElixirScript.Temp, "temp.ex") ) + expected_result = { + [PatternMatching.capture(JS.literal(1))], + [JS.identifier("a")] + } + + assert result == expected_result + + + params = [{:=, [], [{:a, [], Elixir}, 1]}] + result = PatternMatching.build_match(params, ElixirScript.Translator.Env.module_env(ElixirScript.Temp, "temp.ex") ) + expected_result = { + [PatternMatching.capture(JS.literal(1))], + [JS.identifier("a")] + } + + assert result == expected_result + + + params = [{:=, [], [{:%, [], [{:__aliases__, [alias: false], [:AStruct]}, {:%{}, [], []}]}, {:a, [], ElixirScript.Translator.Function.Test}]}] + result = PatternMatching.build_match(params, ElixirScript.Translator.Env.module_env(ElixirScript.Temp, "temp.ex") ) + expected_result = { + [PatternMatching.capture(PatternMatching.type(JS.identifier(:AStruct), JS.object_expression([])))], + [JS.identifier("a")] + } + + assert result == expected_result + end + + test "match and assign list" do + params = [{:=, [], [[{:a, [], Elixir}, {:b, [], Elixir}, {:c, [], Elixir}], {:d, [], Elixir}]}] + result = PatternMatching.build_match(params, ElixirScript.Translator.Env.module_env(ElixirScript.Temp, "temp.ex") ) + expected_result = { + [PatternMatching.capture(Primitive.make_list_no_translate([PatternMatching.parameter, PatternMatching.parameter, PatternMatching.parameter]))], + [JS.identifier("a"), JS.identifier("b"), JS.identifier("c"), JS.identifier("d")] + } + + assert result == expected_result + end + + test "match on tuple" do + params = [{:{}, [], [1, {:b, [], Elixir}, 3]}] + result = PatternMatching.build_match(params, ElixirScript.Translator.Env.module_env(ElixirScript.Temp, "temp.ex") ) + expected_result = { + [PatternMatching.type(Primitive.tuple_class, JS.object_expression([JS.property( + JS.identifier("values"), + JS.array_expression([JS.literal(1), PatternMatching.parameter, JS.literal(3)]) + ) ] )) ], + [JS.identifier("b")] + } + + assert result == expected_result + + params = [{1, {:b, [], Elixir}}] + result = PatternMatching.build_match(params, ElixirScript.Translator.Env.module_env(ElixirScript.Temp, "temp.ex") ) + expected_result = { + [PatternMatching.type(Primitive.tuple_class, JS.object_expression([JS.property( + JS.identifier("values"), + JS.array_expression([JS.literal(1), PatternMatching.parameter]) + ) ] )) ], + [JS.identifier("b")] + } + + assert result == expected_result + end + + test "match on map" do + params = [{:%{}, [], [which: 13]}] + result = PatternMatching.build_match(params, ElixirScript.Translator.Env.module_env(ElixirScript.Temp, "temp.ex") ) + + expected_result = { + [JS.object_expression([ + Map.make_property(Translator.translate!(:which, ElixirScript.Translator.Env.module_env(ElixirScript.Temp, "temp.ex") ), JS.literal(13)) + ])], + [] + } + + assert result == expected_result + end + + + test "match on bound value" do + params = [{:^, [], [{:a, [], Elixir}]}] + result = PatternMatching.build_match(params, ElixirScript.Translator.Env.module_env(ElixirScript.Temp, "temp.ex") ) + + expected_result = { + [PatternMatching.bound(JS.identifier("a"))], + [nil] + } + + assert result == expected_result + end end From 8fce13977695abd0f5f86890e96042b7fbf27912 Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Sat, 19 Mar 2016 06:49:38 -0500 Subject: [PATCH 195/860] Removing compiled stdlib from src control --- .gitignore | 1 + priv/Elixir.ElixirScript.Agent.js | 46 - priv/Elixir.ElixirScript.Atom.js | 11 - priv/Elixir.ElixirScript.Base.js | 20 - priv/Elixir.ElixirScript.Bitwise.js | 3 - priv/Elixir.ElixirScript.Collectable.js | 10 - priv/Elixir.ElixirScript.Enumerable.js | 14 - priv/Elixir.ElixirScript.Integer.js | 32 - priv/Elixir.ElixirScript.JS.js | 8 - priv/Elixir.ElixirScript.Kernel.js | 122 - priv/Elixir.ElixirScript.Keyword.js | 41 - priv/Elixir.ElixirScript.List.js | 212 - priv/Elixir.ElixirScript.Macro.Env.js | 8 - priv/Elixir.ElixirScript.Map.js | 166 - priv/Elixir.ElixirScript.MapSet.js | 89 - priv/Elixir.ElixirScript.Module.js | 9 - priv/Elixir.ElixirScript.Range.js | 18 - ...Script.String.Chars.DefImpl.Elixir.Atom.js | 13 - ...t.String.Chars.DefImpl.Elixir.BitString.js | 14 - ...cript.String.Chars.DefImpl.Elixir.Float.js | 10 - ...ipt.String.Chars.DefImpl.Elixir.Integer.js | 10 - ...Script.String.Chars.DefImpl.Elixir.List.js | 10 - ...cript.String.Chars.DefImpl.Elixir.Tuple.js | 10 - ...lixir.ElixirScript.String.Chars.DefImpl.js | 15 - priv/Elixir.ElixirScript.String.Chars.js | 10 - priv/Elixir.ElixirScript.String.js | 152 - priv/Elixir.ElixirScript.Tuple.js | 53 - priv/Elixir.ElixirScript.View.js | 45 - priv/Elixir.js | 3723 ----------------- 29 files changed, 1 insertion(+), 4874 deletions(-) delete mode 100644 priv/Elixir.ElixirScript.Agent.js delete mode 100644 priv/Elixir.ElixirScript.Atom.js delete mode 100644 priv/Elixir.ElixirScript.Base.js delete mode 100644 priv/Elixir.ElixirScript.Bitwise.js delete mode 100644 priv/Elixir.ElixirScript.Collectable.js delete mode 100644 priv/Elixir.ElixirScript.Enumerable.js delete mode 100644 priv/Elixir.ElixirScript.Integer.js delete mode 100644 priv/Elixir.ElixirScript.JS.js delete mode 100644 priv/Elixir.ElixirScript.Kernel.js delete mode 100644 priv/Elixir.ElixirScript.Keyword.js delete mode 100644 priv/Elixir.ElixirScript.List.js delete mode 100644 priv/Elixir.ElixirScript.Macro.Env.js delete mode 100644 priv/Elixir.ElixirScript.Map.js delete mode 100644 priv/Elixir.ElixirScript.MapSet.js delete mode 100644 priv/Elixir.ElixirScript.Module.js delete mode 100644 priv/Elixir.ElixirScript.Range.js delete mode 100644 priv/Elixir.ElixirScript.String.Chars.DefImpl.Elixir.Atom.js delete mode 100644 priv/Elixir.ElixirScript.String.Chars.DefImpl.Elixir.BitString.js delete mode 100644 priv/Elixir.ElixirScript.String.Chars.DefImpl.Elixir.Float.js delete mode 100644 priv/Elixir.ElixirScript.String.Chars.DefImpl.Elixir.Integer.js delete mode 100644 priv/Elixir.ElixirScript.String.Chars.DefImpl.Elixir.List.js delete mode 100644 priv/Elixir.ElixirScript.String.Chars.DefImpl.Elixir.Tuple.js delete mode 100644 priv/Elixir.ElixirScript.String.Chars.DefImpl.js delete mode 100644 priv/Elixir.ElixirScript.String.Chars.js delete mode 100644 priv/Elixir.ElixirScript.String.js delete mode 100644 priv/Elixir.ElixirScript.Tuple.js delete mode 100644 priv/Elixir.ElixirScript.View.js delete mode 100644 priv/Elixir.js diff --git a/.gitignore b/.gitignore index e1cdbf56..af535c67 100644 --- a/.gitignore +++ b/.gitignore @@ -16,3 +16,4 @@ index.js .tern-port test/std_lib_compile_test.exs src/elixirscript +priv/*.js diff --git a/priv/Elixir.ElixirScript.Agent.js b/priv/Elixir.ElixirScript.Agent.js deleted file mode 100644 index 7ffc9e9a..00000000 --- a/priv/Elixir.ElixirScript.Agent.js +++ /dev/null @@ -1,46 +0,0 @@ - import Elixir from './Elixir'; - import Elixir$ElixirScript$Kernel from './Elixir.ElixirScript.Kernel'; - import Elixir$ElixirScript$JS from './Elixir.ElixirScript.JS'; - import Elixir$ElixirScript$Keyword from './Elixir.ElixirScript.Keyword'; - const update = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable(), Elixir.Core.Patterns.variable()],function(agent,fun) { - let [current_state] = Elixir.Core.Patterns.match(Elixir.Core.Patterns.variable(),Elixir.Core.Functions.call_property(Elixir.Core.Functions.call_property(Elixir$ElixirScript$JS,'global'),'processes').get(agent,'state')); - Elixir.Core.Functions.call_property(Elixir.Core.Functions.call_property(Elixir$ElixirScript$JS,'global'),'processes').put(agent,'state',fun(current_state)); - return Symbol.for('ok'); - })); - const get_and_update = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable(), Elixir.Core.Patterns.variable()],function(agent,fun) { - let [current_state] = Elixir.Core.Patterns.match(Elixir.Core.Patterns.variable(),Elixir.Core.Functions.call_property(Elixir.Core.Functions.call_property(Elixir$ElixirScript$JS,'global'),'processes').get(agent,'state')); - let [val,new_state] = Elixir.Core.Patterns.match(Elixir.Core.Patterns.type(Elixir.Core.Tuple,{ - values: [Elixir.Core.Patterns.variable(), Elixir.Core.Patterns.variable()] - }),fun(current_state)); - let _ref = new Elixir.Core.Tuple(val,new_state); - Elixir.Core.Functions.call_property(Elixir.Core.Functions.call_property(Elixir$ElixirScript$JS,'global'),'processes').put(agent,'state',new_state); - return val; - })); - const start = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable()],function(fun) { - let [pid] = Elixir.Core.Patterns.match(Elixir.Core.Patterns.variable(),Elixir.Core.Functions.call_property(Elixir.Core.Functions.call_property(Elixir.Core.Functions.call_property(Elixir$ElixirScript$JS,'global'),'processes'),'spawn')); - Elixir.Core.Functions.call_property(Elixir.Core.Functions.call_property(Elixir$ElixirScript$JS,'global'),'processes').put(pid,'state',fun()); - return new Elixir.Core.Tuple(Symbol.for('ok'),pid); - }),Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable(), Elixir.Core.Patterns.variable()],function(fun,options) { - let [pid] = Elixir.Core.Patterns.match(Elixir.Core.Patterns.variable(),Elixir.Core.Functions.call_property(Elixir.Core.Functions.call_property(Elixir.Core.Functions.call_property(Elixir$ElixirScript$JS,'global'),'processes'),'spawn')); - Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable()],function(x) { - return null; - },function(x) { - return Elixir.Enum.member__qmark__(Object.freeze([false, null]),x); - }),Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.wildcard()],function() { - let [pid1] = Elixir.Core.Patterns.match(Elixir.Core.Patterns.variable(),Elixir.Core.Functions.call_property(Elixir.Core.Functions.call_property(Elixir$ElixirScript$JS,'global'),'processes').register(Elixir$ElixirScript$Keyword.get(options,Symbol.for('name')),pid)); - return pid1; - })).call(this,Elixir$ElixirScript$Keyword.has_key__qmark__(options,Symbol.for('name'))); - Elixir.Core.Functions.call_property(Elixir.Core.Functions.call_property(Elixir$ElixirScript$JS,'global'),'processes').put(pid,'state',fun()); - return new Elixir.Core.Tuple(Symbol.for('ok'),pid); - })); - const get = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable(), Elixir.Core.Patterns.variable()],function(agent,fun) { - let [current_state] = Elixir.Core.Patterns.match(Elixir.Core.Patterns.variable(),Elixir.Core.Functions.call_property(Elixir.Core.Functions.call_property(Elixir$ElixirScript$JS,'global'),'processes').get(agent,'state')); - return fun(current_state); - })); - const stop = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable()],function(view) { - Elixir.Core.Functions.call_property(Elixir.Core.Functions.call_property(Elixir$ElixirScript$JS,'global'),'processes').exit(view); - return Symbol.for('ok'); - })); - export default { - update, get_and_update, start, get, stop - }; \ No newline at end of file diff --git a/priv/Elixir.ElixirScript.Atom.js b/priv/Elixir.ElixirScript.Atom.js deleted file mode 100644 index ae19da2a..00000000 --- a/priv/Elixir.ElixirScript.Atom.js +++ /dev/null @@ -1,11 +0,0 @@ - import Elixir from './Elixir'; - import Elixir$ElixirScript$Kernel from './Elixir.ElixirScript.Kernel'; - const to_string = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable()],function(atom) { - return Symbol.keyFor(atom); - })); - const to_char_list = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable()],function(atom) { - return to_string.split(''); - })); - export default { - to_string, to_char_list - }; \ No newline at end of file diff --git a/priv/Elixir.ElixirScript.Base.js b/priv/Elixir.ElixirScript.Base.js deleted file mode 100644 index 4c3ba1a4..00000000 --- a/priv/Elixir.ElixirScript.Base.js +++ /dev/null @@ -1,20 +0,0 @@ - import Elixir from './Elixir'; - import Elixir$ElixirScript$Kernel from './Elixir.ElixirScript.Kernel'; - const encode64 = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable()],function(data) { - return Elixir.Core.b64EncodeUnicode(data); - })); - const decode64 = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable()],function(data) { - return Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable()],function(x) { - return Symbol.for('error'); - },function(x) { - return Elixir.Enum.member__qmark__(Object.freeze([false, null]),x); - }),Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.wildcard()],function() { - return new Elixir.Core.Tuple(Symbol.for('ok'),decode64__emark__(data)); - })).call(this,Elixir.Core.can_decode64(data)); - })); - const decode64__emark__ = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable()],function(data) { - return Elixir.Core.Functions.call_property(Elixir.Core,'get_global').atob(data); - })); - export default { - encode64, decode64, decode64__emark__ - }; \ No newline at end of file diff --git a/priv/Elixir.ElixirScript.Bitwise.js b/priv/Elixir.ElixirScript.Bitwise.js deleted file mode 100644 index d6e70174..00000000 --- a/priv/Elixir.ElixirScript.Bitwise.js +++ /dev/null @@ -1,3 +0,0 @@ - import Elixir from './Elixir'; - import Elixir$ElixirScript$Kernel from './Elixir.ElixirScript.Kernel'; - export default {}; \ No newline at end of file diff --git a/priv/Elixir.ElixirScript.Collectable.js b/priv/Elixir.ElixirScript.Collectable.js deleted file mode 100644 index 43c25626..00000000 --- a/priv/Elixir.ElixirScript.Collectable.js +++ /dev/null @@ -1,10 +0,0 @@ - import Elixir from './Elixir'; - import Elixir$ElixirScript$Kernel from './Elixir.ElixirScript.Kernel'; - import Implementations from './Elixir.ElixirScript.Collectable.Defimpl'; - const Elixir$ElixirScript$Collectable = Elixir.Core.Functions.defprotocol({ - into: function() { - - } - }); - for(let {Type,Implementation} of Implementations) Elixir.Core.Functions.defimpl(Elixir$ElixirScript$Collectable,Type,Implementation) - export default Elixir$ElixirScript$Collectable; \ No newline at end of file diff --git a/priv/Elixir.ElixirScript.Enumerable.js b/priv/Elixir.ElixirScript.Enumerable.js deleted file mode 100644 index 1a3edc59..00000000 --- a/priv/Elixir.ElixirScript.Enumerable.js +++ /dev/null @@ -1,14 +0,0 @@ - import Elixir from './Elixir'; - import Elixir$ElixirScript$Kernel from './Elixir.ElixirScript.Kernel'; - import Implementations from './Elixir.ElixirScript.Enumerable.Defimpl'; - const Elixir$ElixirScript$Enumerable = Elixir.Core.Functions.defprotocol({ - reduce: function() { - - }, member__qmark__: function() { - - }, count: function() { - - } - }); - for(let {Type,Implementation} of Implementations) Elixir.Core.Functions.defimpl(Elixir$ElixirScript$Enumerable,Type,Implementation) - export default Elixir$ElixirScript$Enumerable; \ No newline at end of file diff --git a/priv/Elixir.ElixirScript.Integer.js b/priv/Elixir.ElixirScript.Integer.js deleted file mode 100644 index e29e47c1..00000000 --- a/priv/Elixir.ElixirScript.Integer.js +++ /dev/null @@ -1,32 +0,0 @@ - import Elixir from './Elixir'; - import Elixir$ElixirScript$Kernel from './Elixir.ElixirScript.Kernel'; - const is_even = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable()],function(number) { - return number % 2 == 0; - })); - const parse = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable()],function(bin) { - let [result] = Elixir.Core.Patterns.match(Elixir.Core.Patterns.variable(),Elixir.Core.Functions.call_property(Elixir.Core.Functions,'get_global').parseInt(bin)); - return Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable()],function(x) { - return Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable()],function(index_of_dot) { - return new Elixir.Core.Tuple(result,''); - },function(index_of_dot) { - return index_of_dot < 0; - }),Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable()],function(index_of_dot) { - return new Elixir.Core.Tuple(result,bin.substring(index_of_dot)); - })).call(this,bin.indexOf('.')); - },function(x) { - return Elixir.Enum.member__qmark__(Object.freeze([false, null]),x); - }),Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.wildcard()],function() { - return Symbol.for('error'); - })).call(this,Elixir.Core.Functions.call_property(Elixir.Core.Functions,'get_global').isNaN(result)); - })); - const is_odd = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable()],function(number) { - return number % 2 != 0; - })); - const to_char_list = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable()],function(number) { - return to_char_list(number,10); - }),Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable(), Elixir.Core.Patterns.variable()],function(number,base) { - return number.toString(base).split(Object.freeze([])); - })); - export default { - is_even, parse, is_odd, to_char_list - }; \ No newline at end of file diff --git a/priv/Elixir.ElixirScript.JS.js b/priv/Elixir.ElixirScript.JS.js deleted file mode 100644 index f56c8f48..00000000 --- a/priv/Elixir.ElixirScript.JS.js +++ /dev/null @@ -1,8 +0,0 @@ - import Elixir from './Elixir'; - import Elixir$ElixirScript$Kernel from './Elixir.ElixirScript.Kernel'; - const global = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([],function() { - return Elixir.Core.Functions.call_property(Elixir.Core.Functions,'get_global'); - })); - export default { - global - }; \ No newline at end of file diff --git a/priv/Elixir.ElixirScript.Kernel.js b/priv/Elixir.ElixirScript.Kernel.js deleted file mode 100644 index 632ce36b..00000000 --- a/priv/Elixir.ElixirScript.Kernel.js +++ /dev/null @@ -1,122 +0,0 @@ - import Elixir from './Elixir'; - import Elixir$ElixirScript$Atom from './Elixir.ElixirScript.Atom'; - const build_if = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable(), Object.freeze([Elixir.Core.Patterns.type(Elixir.Core.Tuple,{ - values: [Symbol.for('do'), Elixir.Core.Patterns.variable()] - })])],function(condition,do_clause) { - return build_if(condition,Object.freeze([new Elixir.Core.Tuple(Symbol.for('do'),do_clause), new Elixir.Core.Tuple(Symbol.for('else'),null)])); - }),Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable(), Object.freeze([Elixir.Core.Patterns.type(Elixir.Core.Tuple,{ - values: [Symbol.for('do'), Elixir.Core.Patterns.variable()] - }), Elixir.Core.Patterns.type(Elixir.Core.Tuple,{ - values: [Symbol.for('else'), Elixir.Core.Patterns.variable()] - })])],function(condition,do_clause,else_clause) { - return new Elixir.Core.Tuple(Symbol.for('case'),Object.freeze([new Elixir.Core.Tuple(Symbol.for('line'),15)]),Object.freeze([condition, Object.freeze([new Elixir.Core.Tuple(Symbol.for('do'),Object.freeze([new Elixir.Core.Tuple(Symbol.for('->'),Object.freeze([new Elixir.Core.Tuple(Symbol.for('line'),16)]),Object.freeze([Object.freeze([new Elixir.Core.Tuple(Symbol.for('when'),Object.freeze([new Elixir.Core.Tuple(Symbol.for('line'),16)]),Object.freeze([new Elixir.Core.Tuple(Symbol.for('x'),Object.freeze([new Elixir.Core.Tuple(Symbol.for('line'),16)]),null), new Elixir.Core.Tuple(Symbol.for('in'),Object.freeze([new Elixir.Core.Tuple(Symbol.for('line'),16)]),Object.freeze([new Elixir.Core.Tuple(Symbol.for('x'),Object.freeze([new Elixir.Core.Tuple(Symbol.for('line'),16)]),null), Object.freeze([false, null])]))]))]), else_clause])), new Elixir.Core.Tuple(Symbol.for('->'),Object.freeze([new Elixir.Core.Tuple(Symbol.for('line'),18)]),Object.freeze([Object.freeze([new Elixir.Core.Tuple(Symbol.for('_'),Object.freeze([new Elixir.Core.Tuple(Symbol.for('line'),18)]),null)]), do_clause]))]))])])); - })); - const build_unless = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable(), Object.freeze([Elixir.Core.Patterns.type(Elixir.Core.Tuple,{ - values: [Symbol.for('do'), Elixir.Core.Patterns.variable()] - })])],function(condition,do_clause) { - return build_unless(condition,Object.freeze([new Elixir.Core.Tuple(Symbol.for('do'),do_clause), new Elixir.Core.Tuple(Symbol.for('else'),null)])); - }),Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable(), Object.freeze([Elixir.Core.Patterns.type(Elixir.Core.Tuple,{ - values: [Symbol.for('do'), Elixir.Core.Patterns.variable()] - }), Elixir.Core.Patterns.type(Elixir.Core.Tuple,{ - values: [Symbol.for('else'), Elixir.Core.Patterns.variable()] - })])],function(condition,do_clause,else_clause) { - return new Elixir.Core.Tuple(Symbol.for('if'),Object.freeze([new Elixir.Core.Tuple(Symbol.for('line'),34)]),Object.freeze([condition, Object.freeze([new Elixir.Core.Tuple(Symbol.for('do'),else_clause), new Elixir.Core.Tuple(Symbol.for('else'),do_clause)])])); - })); - const is_bitstring = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable()],function(term) { - return is_binary(term) || (term instanceof Elixir.Core.BitString); - })); - const is_boolean = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable()],function(term) { - return (typeof term === 'boolean') || (term instanceof Boolean); - })); - const min = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable(), Elixir.Core.Patterns.variable()],function(first,second) { - return Math.min(first,second); - })); - const is_function = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable()],function(term) { - return is_function(term,0); - }),Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable(), Elixir.Core.Patterns.wildcard()],function(term) { - return (typeof term === 'function') || (term instanceof Function); - })); - const is_atom = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable()],function(term) { - return typeof term === 'symbol'; - })); - const elem = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable(), Elixir.Core.Patterns.variable()],function(tuple,index) { - return Elixir.Core.Functions.apply(tuple,'get',Object.freeze([index])); - })); - const map_size = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable()],function(term) { - return Elixir.Core.Functions.call_property(Object.keys(term),'length'); - })); - const tuple_size = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable()],function(tuple) { - return Elixir.Core.Functions.size(tuple); - })); - const is_tuple = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable()],function(term) { - return term instanceof Elixir.Core.Tuple; - })); - const is_reference = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.wildcard()],function() { - return false; - })); - const binary_part = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable(), Elixir.Core.Patterns.variable(), Elixir.Core.Patterns.variable()],function(binary,start,len) { - return binary.substring(start,len); - })); - const is_nil = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable()],function(term) { - return term === null; - })); - const is_pid = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable()],function(term) { - return term instanceof Elixir.Core.PID; - })); - const tl = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable()],function(list) { - return list.slice(1); - })); - const hd = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable()],function(list) { - return list[0]; - })); - const is_port = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.wildcard()],function() { - return false; - })); - const is_list = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable()],function(term) { - return Array.isArray(term); - })); - const is_float = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable()],function(term) { - return is_number(term) && !Number.isInteger(term); - })); - const round = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable()],function(number) { - return Math.round(number); - })); - const abs = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable()],function(number) { - return Math.abs(number); - })); - const trunc = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable()],function(number) { - return Math.floor(number); - })); - const is_integer = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable()],function(term) { - return Number.isInteger(term); - })); - const is_number = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable()],function(term) { - return (typeof term === 'number') || (term instanceof Number); - })); - const apply = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable(), Elixir.Core.Patterns.variable()],function(fun,args) { - return Elixir.Core.Functions.apply(fun,args); - }),Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable(), Elixir.Core.Patterns.variable(), Elixir.Core.Patterns.variable()],function(module,fun,args) { - let [fun1] = Elixir.Core.Patterns.match(Elixir.Core.Patterns.variable(),Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable()],function(x) { - return fun; - },function(x) { - return Elixir.Enum.member__qmark__(Object.freeze([false, null]),x); - }),Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.wildcard()],function() { - return Elixir$ElixirScript$Atom.to_string(fun); - })).call(this,Elixir.Core.is_atom(fun))); - return Elixir.Core.Functions.apply(module,fun,args); - })); - const is_binary = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable()],function(term) { - return typeof term === 'string'; - })); - const is_map = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable()],function(term) { - return (typeof term === 'object') || (term instanceof Object); - })); - const length = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable()],function(term) { - return Elixir.Core.Functions.call_property(term,'length'); - })); - const max = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable(), Elixir.Core.Patterns.variable()],function(first,second) { - return Math.max(first,second); - })); - export default { - is_bitstring, is_boolean, min, is_function, is_atom, elem, map_size, tuple_size, is_tuple, is_reference, binary_part, is_nil, is_pid, tl, hd, is_port, is_list, is_float, round, abs, trunc, is_integer, is_number, apply, is_binary, is_map, length, max - }; \ No newline at end of file diff --git a/priv/Elixir.ElixirScript.Keyword.js b/priv/Elixir.ElixirScript.Keyword.js deleted file mode 100644 index 46266ceb..00000000 --- a/priv/Elixir.ElixirScript.Keyword.js +++ /dev/null @@ -1,41 +0,0 @@ - import Elixir from './Elixir'; - import Elixir$ElixirScript$Kernel from './Elixir.ElixirScript.Kernel'; - const do_has_key__qmark__ = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Object.freeze([]), Elixir.Core.Patterns.wildcard()],function() { - return false; - }),Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable(), Elixir.Core.Patterns.variable()],function(kw,key) { - return Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.type(Elixir.Core.Tuple,{ - values: [Elixir.Core.Patterns.variable(), Elixir.Core.Patterns.wildcard()] - })],function(the_key) { - return true; - },function(the_key) { - return the_key == key; - }),Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.wildcard()],function() { - return do_has_key__qmark__(Elixir$ElixirScript$Kernel.tl(kw),key); - })).call(this,Elixir$ElixirScript$Kernel.hd(kw)); - })); - const do_get = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable(), Elixir.Core.Patterns.variable()],function(kw,key) { - return Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.type(Elixir.Core.Tuple,{ - values: [Elixir.Core.Patterns.variable(), Elixir.Core.Patterns.variable()] - })],function(kw_key,value) { - return value; - },function(kw_key,value) { - return kw_key == key; - }),Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.wildcard()],function() { - return do_get(Elixir$ElixirScript$Kernel.tl(kw),key); - })).call(this,Elixir$ElixirScript$Kernel.hd(kw)); - })); - const has_key__qmark__ = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable(), Elixir.Core.Patterns.variable()],function(kw,key) { - return do_has_key__qmark__(kw,key); - })); - const get = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable(), Elixir.Core.Patterns.variable()],function(kw,key) { - return get(kw,key,null); - }),Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable(), Elixir.Core.Patterns.variable(), Elixir.Core.Patterns.variable()],function(kw,key,default_value) { - return Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([true],function() { - return do_get(kw,key); - }),Elixir.Core.Patterns.make_case([false],function() { - return default_value; - })).call(this,has_key__qmark__(kw,key)); - })); - export default { - has_key__qmark__, get - }; \ No newline at end of file diff --git a/priv/Elixir.ElixirScript.List.js b/priv/Elixir.ElixirScript.List.js deleted file mode 100644 index 3c9c680d..00000000 --- a/priv/Elixir.ElixirScript.List.js +++ /dev/null @@ -1,212 +0,0 @@ - import Elixir from './Elixir'; - import Elixir$ElixirScript$Kernel from './Elixir.ElixirScript.Kernel'; - const do_flatten = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Object.freeze([]), Elixir.Core.Patterns.variable()],function(flattened_list) { - return flattened_list; - }),Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable(), Elixir.Core.Patterns.variable()],function(list,flattened_list) { - let [flattened_list1] = Elixir.Core.Patterns.match(Elixir.Core.Patterns.variable(),Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable()],function(l) { - return flattened_list.concat(do_flatten(l,Object.freeze([]))); - },function(l) { - return Elixir$ElixirScript$Kernel.is_list(l); - }),Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable()],function(item) { - return flattened_list.concat(Object.freeze([item])); - })).call(this,Elixir$ElixirScript$Kernel.hd(list))); - return do_flatten(Elixir$ElixirScript$Kernel.tl(list),flattened_list); - })); - const do_duplicate = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.wildcard(), 0, Elixir.Core.Patterns.variable()],function(list) { - return list; - }),Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable(), Elixir.Core.Patterns.variable(), Elixir.Core.Patterns.variable()],function(data,size,list) { - return do_duplicate(data,size - 1,list.concat(Object.freeze([data]))); - })); - const do_delete = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable(), Elixir.Core.Patterns.variable(), Elixir.Core.Patterns.variable(), Elixir.Core.Patterns.variable()],function(list,item,current_index,new_list) { - return Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable()],function(x) { - let [new_list1] = Elixir.Core.Patterns.match(Elixir.Core.Patterns.variable(),Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.bound(item)],function() { - return new_list; - }),Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.wildcard()],function() { - return new_list.concat(Object.freeze([list[current_index]])); - })).call(this,list[current_index])); - return do_delete(list,item,current_index + 1,new_list); - },function(x) { - return Elixir.Enum.member__qmark__(Object.freeze([false, null]),x); - }),Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.wildcard()],function() { - return new_list; - })).call(this,current_index == Elixir$ElixirScript$Kernel.length(list)); - })); - const do_keyreplace = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Object.freeze([]), Elixir.Core.Patterns.wildcard(), Elixir.Core.Patterns.wildcard(), Elixir.Core.Patterns.variable(), Elixir.Core.Patterns.wildcard()],function(new_list) { - return new_list; - }),Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable(), Elixir.Core.Patterns.variable(), Elixir.Core.Patterns.variable(), Elixir.Core.Patterns.variable(), Elixir.Core.Patterns.variable()],function(list,key,position,new_list,new_tuple) { - let [current_value] = Elixir.Core.Patterns.match(Elixir.Core.Patterns.variable(),Elixir$ElixirScript$Kernel.hd(list)); - let [new_list1] = Elixir.Core.Patterns.match(Elixir.Core.Patterns.variable(),Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable()],function(x) { - return new_list.concat(Object.freeze([current_value])); - },function(x) { - return Elixir.Enum.member__qmark__(Object.freeze([false, null]),x); - }),Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.wildcard()],function() { - return new_list.concat(Object.freeze([new_tuple])); - })).call(this,Elixir$ElixirScript$Kernel.elem(current_value,position) == key)); - return do_keyreplace(Elixir$ElixirScript$Kernel.tl(list),key,position,new_list,new_tuple); - })); - const do_keydelete = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Object.freeze([]), Elixir.Core.Patterns.wildcard(), Elixir.Core.Patterns.wildcard(), Elixir.Core.Patterns.variable()],function(new_list) { - return new_list; - }),Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable(), Elixir.Core.Patterns.variable(), Elixir.Core.Patterns.variable(), Elixir.Core.Patterns.variable()],function(list,key,position,new_list) { - let [current_value] = Elixir.Core.Patterns.match(Elixir.Core.Patterns.variable(),Elixir$ElixirScript$Kernel.hd(list)); - let [new_list1] = Elixir.Core.Patterns.match(Elixir.Core.Patterns.variable(),Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable()],function(x) { - return new_list.concat(Object.freeze([current_value])); - },function(x) { - return Elixir.Enum.member__qmark__(Object.freeze([false, null]),x); - }),Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.wildcard()],function() { - return new_list; - })).call(this,Elixir$ElixirScript$Kernel.elem(current_value,position) == key)); - return do_keydelete(Elixir$ElixirScript$Kernel.tl(list),key,position,new_list); - })); - const do_delete_at = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable(), Elixir.Core.Patterns.variable(), Elixir.Core.Patterns.variable(), Elixir.Core.Patterns.variable()],function(list,index,current_index,new_list) { - return Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable()],function(x) { - let [new_list1] = Elixir.Core.Patterns.match(Elixir.Core.Patterns.variable(),Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([true],function() { - return new_list; - }),Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.wildcard()],function() { - return new_list.concat(Object.freeze([list[current_index]])); - })).call(this,current_index == index)); - return do_delete_at(list,index,current_index + 1,new_list); - },function(x) { - return Elixir.Enum.member__qmark__(Object.freeze([false, null]),x); - }),Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.wildcard()],function() { - return new_list; - })).call(this,current_index == Elixir$ElixirScript$Kernel.length(list)); - })); - const do_update_at = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable(), Elixir.Core.Patterns.variable(), Elixir.Core.Patterns.variable(), Elixir.Core.Patterns.variable(), Elixir.Core.Patterns.variable()],function(list,index,func,current_index,new_list) { - return Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable()],function(x) { - let [new_list1] = Elixir.Core.Patterns.match(Elixir.Core.Patterns.variable(),Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([true],function() { - return new_list.concat(Object.freeze([func(list[current_index])])); - }),Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.wildcard()],function() { - return new_list.concat(Object.freeze([list[current_index]])); - })).call(this,current_index == index)); - return do_update_at(list,index,func,current_index + 1,new_list); - },function(x) { - return Elixir.Enum.member__qmark__(Object.freeze([false, null]),x); - }),Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.wildcard()],function() { - return new_list; - })).call(this,current_index == Elixir$ElixirScript$Kernel.length(list)); - })); - const do_keyfind = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Object.freeze([]), Elixir.Core.Patterns.wildcard(), Elixir.Core.Patterns.wildcard(), Elixir.Core.Patterns.variable()],function(__default__) { - return __default__; - }),Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable(), Elixir.Core.Patterns.variable(), Elixir.Core.Patterns.variable(), Elixir.Core.Patterns.variable()],function(list,key,position,__default__) { - let [current_value] = Elixir.Core.Patterns.match(Elixir.Core.Patterns.variable(),Elixir$ElixirScript$Kernel.hd(list)); - return Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable()],function(x) { - return do_keyfind(Elixir$ElixirScript$Kernel.tl(list),key,position,__default__); - },function(x) { - return Elixir.Enum.member__qmark__(Object.freeze([false, null]),x); - }),Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.wildcard()],function() { - return current_value; - })).call(this,Elixir$ElixirScript$Kernel.elem(current_value,position) == key); - })); - const do_foldl = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Object.freeze([]), Elixir.Core.Patterns.variable(), Elixir.Core.Patterns.wildcard(), Elixir.Core.Patterns.variable()],function(acc,new_list) { - return new Elixir.Core.Tuple(acc,new_list); - }),Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable(), Elixir.Core.Patterns.variable(), Elixir.Core.Patterns.variable(), Elixir.Core.Patterns.variable()],function(list,acc,func,new_list) { - let [acc1,value] = Elixir.Core.Patterns.match(Elixir.Core.Patterns.type(Elixir.Core.Tuple,{ - values: [Elixir.Core.Patterns.variable(), Elixir.Core.Patterns.variable()] - }),func(Elixir$ElixirScript$Kernel.hd(list),acc)); - let _ref = new Elixir.Core.Tuple(acc1,value); - return do_foldl(Elixir$ElixirScript$Kernel.tl(list),acc,func,new_list.concat(Object.freeze([value]))); - })); - const do_insert_at = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable(), Elixir.Core.Patterns.variable(), Elixir.Core.Patterns.variable(), Elixir.Core.Patterns.variable(), Elixir.Core.Patterns.variable()],function(list,index,value,current_index,new_list) { - return Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable()],function(x) { - let [new_list1] = Elixir.Core.Patterns.match(Elixir.Core.Patterns.variable(),Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([true],function() { - return new_list.concat(Object.freeze([value, list[current_index]])); - }),Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.wildcard()],function() { - return new_list.concat(Object.freeze([list[current_index]])); - })).call(this,current_index == index)); - return do_insert_at(list,index,value,current_index + 1,new_list); - },function(x) { - return Elixir.Enum.member__qmark__(Object.freeze([false, null]),x); - }),Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.wildcard()],function() { - return new_list; - })).call(this,current_index == Elixir$ElixirScript$Kernel.length(list)); - })); - const do_replace_at = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable(), Elixir.Core.Patterns.variable(), Elixir.Core.Patterns.variable(), Elixir.Core.Patterns.variable(), Elixir.Core.Patterns.variable()],function(list,index,value,current_index,new_list) { - return Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable()],function(x) { - let [new_list1] = Elixir.Core.Patterns.match(Elixir.Core.Patterns.variable(),Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([true],function() { - return new_list.concat(Object.freeze([value])); - }),Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.wildcard()],function() { - return new_list.concat(Object.freeze([list[current_index]])); - })).call(this,current_index == index)); - return do_replace_at(list,index,value,current_index + 1,new_list); - },function(x) { - return Elixir.Enum.member__qmark__(Object.freeze([false, null]),x); - }),Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.wildcard()],function() { - return new_list; - })).call(this,current_index == Elixir$ElixirScript$Kernel.length(list)); - })); - const keymember__qmark__ = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable(), Elixir.Core.Patterns.variable(), Elixir.Core.Patterns.variable()],function(list,key,position) { - return keyfind(list,key,position) != null; - })); - const flatten = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable()],function(list) { - return do_flatten(list,Object.freeze([])); - }),Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable(), Elixir.Core.Patterns.variable()],function(list,tail) { - return do_flatten.concat(tail); - })); - const duplicate = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable(), Elixir.Core.Patterns.variable()],function(data,size) { - return do_duplicate(data,size,Object.freeze([])); - })); - const __delete__ = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable(), Elixir.Core.Patterns.variable()],function(list,item) { - return do_delete(list,item,0,Object.freeze([])); - })); - const keydelete = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable(), Elixir.Core.Patterns.variable(), Elixir.Core.Patterns.variable()],function(list,key,position) { - return do_keydelete(list,key,position,Object.freeze([])); - })); - const to_tuple = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable()],function(list) { - return new Elixir.Core.Tuple(...list); - })); - const keyreplace = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable(), Elixir.Core.Patterns.variable(), Elixir.Core.Patterns.variable(), Elixir.Core.Patterns.variable()],function(list,key,position,new_tuple) { - return do_keyreplace(list,key,position,Object.freeze([]),new_tuple); - })); - const append = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable(), Elixir.Core.Patterns.variable()],function(list,term) { - return concat(list,Object.freeze([term])); - })); - const prepend = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable(), Elixir.Core.Patterns.variable()],function(list,term) { - return concat(Object.freeze([term]),list); - })); - const replace_at = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable(), Elixir.Core.Patterns.variable(), Elixir.Core.Patterns.variable()],function(list,index,value) { - return do_replace_at(list,index,value,0,Object.freeze([])); - })); - const keyfind = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable(), Elixir.Core.Patterns.variable(), Elixir.Core.Patterns.variable()],function(list,key,position) { - return do_keyfind(list,key,position,null); - }),Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable(), Elixir.Core.Patterns.variable(), Elixir.Core.Patterns.variable(), Elixir.Core.Patterns.variable()],function(list,key,position,__default__) { - return do_keyfind(list,key,position,__default__); - })); - const foldl = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable(), Elixir.Core.Patterns.variable(), Elixir.Core.Patterns.variable()],function(list,acc,func) { - return do_foldl(list,acc,func,Object.freeze([])); - })); - const first = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable()],function(list) { - return list[0]; - })); - const update_at = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable(), Elixir.Core.Patterns.variable(), Elixir.Core.Patterns.variable()],function(list,index,func) { - return do_update_at(list,index,func,0,Object.freeze([])); - })); - const last = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable()],function(list) { - return list[Elixir$ElixirScript$Kernel.length(list) - 1]; - })); - const insert_at = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable(), Elixir.Core.Patterns.variable(), Elixir.Core.Patterns.variable()],function(list,index,value) { - return do_insert_at(list,index,value,0,Object.freeze([])); - })); - const concat = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable(), Elixir.Core.Patterns.variable()],function(list_a,list_b) { - return list_a.concat(list_b); - })); - const delete_at = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable(), Elixir.Core.Patterns.variable()],function(list,index) { - return do_delete_at(list,index,0,Object.freeze([])); - })); - const foldr = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable(), Elixir.Core.Patterns.variable(), Elixir.Core.Patterns.variable()],function(list,acc,func) { - return do_foldl(Elixir.Core.Functions.call_property(list.concat(Object.freeze([])),'reverse'),acc,func,Object.freeze([])); - })); - const wrap = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable()],function(list) { - return list; - },function(list) { - return Elixir$ElixirScript$Kernel.is_list(list); - }),Elixir.Core.Patterns.make_case([null],function() { - return null; - }),Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable()],function(term) { - return term; - })); - const zip = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable()],function(list_of_lists) { - return Elixir.Core.Functions.zip(list_of_lists); - })); - export default { - keymember__qmark__, flatten, duplicate, __delete__, keydelete, to_tuple, keyreplace, append, prepend, replace_at, keyfind, foldl, first, update_at, last, insert_at, concat, delete_at, foldr, wrap, zip - }; \ No newline at end of file diff --git a/priv/Elixir.ElixirScript.Macro.Env.js b/priv/Elixir.ElixirScript.Macro.Env.js deleted file mode 100644 index 46d3279f..00000000 --- a/priv/Elixir.ElixirScript.Macro.Env.js +++ /dev/null @@ -1,8 +0,0 @@ - import Elixir from './Elixir'; - import Elixir$ElixirScript$Kernel from './Elixir.ElixirScript.Kernel'; - const Elixir$ElixirScript$Macro$Env = Elixir.Core.Functions.defstruct({ - [Symbol.for('__struct__')]: Symbol.for('Elixir.ElixirScript.Macro.Env'), [Symbol.for('module')]: null, [Symbol.for('file')]: null, [Symbol.for('line')]: 0, [Symbol.for('function')]: null, [Symbol.for('context')]: null, [Symbol.for('aliases')]: Object.freeze([]), [Symbol.for('requires')]: Object.freeze([]), [Symbol.for('functions')]: Object.freeze([]), [Symbol.for('macros')]: Object.freeze([]), [Symbol.for('macro_aliases')]: Object.freeze([]), [Symbol.for('context_modules')]: Object.freeze([]), [Symbol.for('vars')]: Object.freeze([]), [Symbol.for('export_vars')]: null, [Symbol.for('lexical_tracker')]: null, [Symbol.for('caller')]: null - }); - export default { - Elixir$ElixirScript$Macro$Env - }; \ No newline at end of file diff --git a/priv/Elixir.ElixirScript.Map.js b/priv/Elixir.ElixirScript.Map.js deleted file mode 100644 index 6f1420b8..00000000 --- a/priv/Elixir.ElixirScript.Map.js +++ /dev/null @@ -1,166 +0,0 @@ - import Elixir from './Elixir'; - import Elixir$ElixirScript$Kernel from './Elixir.ElixirScript.Kernel'; - import Elixir$ElixirScript$String$Chars from './Elixir.ElixirScript.String.Chars'; - const do_split = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.wildcard(), Object.freeze([]), Elixir.Core.Patterns.variable()],function(split_tuple) { - return split_tuple; - }),Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable(), Elixir.Core.Patterns.variable(), Elixir.Core.Patterns.type(Elixir.Core.Tuple,{ - values: [Elixir.Core.Patterns.variable(), Elixir.Core.Patterns.variable()] - })],function(map,keys,key_map,non_key_map) { - let [key] = Elixir.Core.Patterns.match(Elixir.Core.Patterns.variable(),Elixir$ElixirScript$Kernel.hd(keys)); - let [new_split_tuple] = Elixir.Core.Patterns.match(Elixir.Core.Patterns.variable(),Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([true],function() { - return new Elixir.Core.Tuple(Elixir$ElixirScript$Map.put(key_map,key,map[key]),non_key_map); - }),Elixir.Core.Patterns.make_case([false],function() { - return new Elixir.Core.Tuple(key_map,Elixir$ElixirScript$Map.put(non_key_map,key,map[key])); - })).call(this,Elixir.Core.Functions.contains(key,keys(map)))); - return do_split(map,Elixir$ElixirScript$Kernel.tl(keys),new_split_tuple); - })); - const __new__ = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([],function() { - return Object.freeze({}); - })); - const equal__qmark__ = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable(), Elixir.Core.Patterns.variable()],function(map1,map2) { - return map1 === map2; - })); - const put_new = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable(), Elixir.Core.Patterns.variable(), Elixir.Core.Patterns.variable()],function(map,key,value) { - return Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([true],function() { - return map; - }),Elixir.Core.Patterns.make_case([false],function() { - return Elixir$ElixirScript$Map.put(map,key,value); - })).call(this,Elixir.Core.Functions.contains(key,keys(map))); - })); - const has_key__qmark__ = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable(), Elixir.Core.Patterns.variable()],function(map,key) { - return Elixir.Core.Functions.contains(key,keys(map)); - })); - const size = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable()],function(map) { - return Elixir.Core.Functions.call_property(keys,'length'); - })); - const get_and_update = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable(), Elixir.Core.Patterns.variable(), Elixir.Core.Patterns.variable()],function(map,key,func) { - return Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([true],function() { - return new Elixir.Core.Tuple(null,map); - }),Elixir.Core.Patterns.make_case([false],function() { - let [new_value] = Elixir.Core.Patterns.match(Elixir.Core.Patterns.variable(),func(map[key])); - return new Elixir.Core.Tuple(new_value,Elixir$ElixirScript$Map.put(map,key,new_value)); - })).call(this,Elixir.Core.Functions.contains(key,keys(map))); - })); - const __delete__ = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable(), Elixir.Core.Patterns.variable()],function(map,key) { - return Elixir.Core.Functions.delete_property_from_map(map,key); - })); - const update = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable(), Elixir.Core.Patterns.variable(), Elixir.Core.Patterns.variable(), Elixir.Core.Patterns.variable()],function(map,key,initial,func) { - return Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([true],function() { - return Elixir$ElixirScript$Map.put(map,key,func(map[key])); - }),Elixir.Core.Patterns.make_case([false],function() { - return Elixir$ElixirScript$Map.put(map,key,initial); - })).call(this,Elixir.Core.Functions.contains(key,keys(map))); - })); - const merge = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable(), Elixir.Core.Patterns.variable()],function(map1,map2) { - return Elixir.Core.SpecialForms.map_update(map1,map2); - })); - const take = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable(), Elixir.Core.Patterns.variable()],function(map,keys) { - let [key_map,undefined] = Elixir.Core.Patterns.match(Elixir.Core.Patterns.type(Elixir.Core.Tuple,{ - values: [Elixir.Core.Patterns.variable(), Elixir.Core.Patterns.wildcard()] - }),split(map,keys)); - let _ref = new Elixir.Core.Tuple(key_map,undefined); - return key_map; - })); - const to_list = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable()],function(map) { - return do_to_list(map,Object.freeze([])); - })); - const from_struct = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable()],function(struct) { - return __delete__(Elixir.Core.Functions.class_to_obj(struct),Symbol.for('__struct__')); - })); - const do_to_list = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable(), Elixir.Core.Patterns.variable()],function(map,list) { - return Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([0],function() { - return list; - }),Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.wildcard()],function() { - let [key] = Elixir.Core.Patterns.match(Elixir.Core.Patterns.variable(),Elixir$ElixirScript$Kernel.hd(keys(map))); - let [value] = Elixir.Core.Patterns.match(Elixir.Core.Patterns.variable(),map[key]); - return do_to_list(Elixir$ElixirScript$Map.__delete__(map,key),list.concat(Object.freeze([new Elixir.Core.Tuple(key,value)]))); - })).call(this,size(map)); - })); - const put = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable(), Elixir.Core.Patterns.variable(), Elixir.Core.Patterns.variable()],function(map,key,value) { - return Elixir.Core.Functions.add_property_to_map(map,key,value); - })); - const get = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable(), Elixir.Core.Patterns.variable()],function(map,key) { - return get(map,key,null); - }),Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable(), Elixir.Core.Patterns.variable(), Elixir.Core.Patterns.variable()],function(map,key,default_value) { - return Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([true],function() { - return map[key]; - }),Elixir.Core.Patterns.make_case([false],function() { - return default_value; - })).call(this,Elixir.Core.Functions.contains(key,keys(map))); - })); - const split = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable(), Elixir.Core.Patterns.variable()],function(map,keys) { - return do_split(map,keys,new Elixir.Core.Tuple(Object.freeze({}),Object.freeze({}))); - })); - const keys = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable()],function(map) { - return Elixir.Core.Functions.get_object_keys(map); - })); - const values = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable()],function(map) { - return Object.values(map); - })); - const fetch__emark__ = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable(), Elixir.Core.Patterns.variable()],function(map,key) { - return Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([true],function() { - return map[key]; - }),Elixir.Core.Patterns.make_case([false],function() { - throw { - [Symbol.for('__struct__')]: Symbol.for('RuntimeError'), [Symbol.for('__exception__')]: true, [Symbol.for('message')]: Elixir$ElixirScript$String$Chars.to_string(key) + ' not found in map' - }; - return null; - })).call(this,Elixir.Core.Functions.contains(key,keys(map))); - })); - const pop_lazy = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable(), Elixir.Core.Patterns.variable(), Elixir.Core.Patterns.variable()],function(map,key,func) { - return Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([true],function() { - return new Elixir.Core.Tuple(func(map[key]),Elixir$ElixirScript$Map.__delete__(map,key)); - }),Elixir.Core.Patterns.make_case([false],function() { - return new Elixir.Core.Tuple(func(),map); - })).call(this,Elixir.Core.Functions.contains(key,keys(map))); - })); - const put_new_lazy = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable(), Elixir.Core.Patterns.variable(), Elixir.Core.Patterns.variable()],function(map,key,func) { - return Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([true],function() { - return map; - }),Elixir.Core.Patterns.make_case([false],function() { - return Elixir$ElixirScript$Map.put(map,key,func()); - })).call(this,Elixir.Core.Functions.contains(key,keys(map))); - })); - const get_lazy = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable(), Elixir.Core.Patterns.variable(), Elixir.Core.Patterns.variable()],function(map,key,func) { - return Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([true],function() { - return func(map[key]); - }),Elixir.Core.Patterns.make_case([false],function() { - return func(); - })).call(this,Elixir.Core.Functions.contains(key,keys(map))); - })); - const update__emark__ = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable(), Elixir.Core.Patterns.variable(), Elixir.Core.Patterns.variable()],function(map,key,func) { - return Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([true],function() { - return Elixir$ElixirScript$Map.put(map,key,func(map[key])); - }),Elixir.Core.Patterns.make_case([false],function() { - throw { - [Symbol.for('__struct__')]: Symbol.for('RuntimeError'), [Symbol.for('__exception__')]: true, [Symbol.for('message')]: Elixir$ElixirScript$String$Chars.to_string(key) + ' not found in map' - }; - return null; - })).call(this,Elixir.Core.Functions.contains(key,keys(map))); - })); - const fetch = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable(), Elixir.Core.Patterns.variable()],function(map,key) { - return Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([true],function() { - return new Elixir.Core.Tuple(Symbol.for('ok'),map[key]); - }),Elixir.Core.Patterns.make_case([false],function() { - return Symbol.for('error'); - })).call(this,Elixir.Core.Functions.contains(key,keys(map))); - })); - const drop = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable(), Elixir.Core.Patterns.variable()],function(map,keys) { - let [undefined,non_key_map] = Elixir.Core.Patterns.match(Elixir.Core.Patterns.type(Elixir.Core.Tuple,{ - values: [Elixir.Core.Patterns.wildcard(), Elixir.Core.Patterns.variable()] - }),split(map,keys)); - let _ref = new Elixir.Core.Tuple(undefined,non_key_map); - return non_key_map; - })); - const pop = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable(), Elixir.Core.Patterns.variable()],function(map,key) { - return pop(map,key,null); - }),Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable(), Elixir.Core.Patterns.variable(), Elixir.Core.Patterns.variable()],function(map,key,default_value) { - return Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([true],function() { - return new Elixir.Core.Tuple(map[key],Elixir$ElixirScript$Map.__delete__(map,key)); - }),Elixir.Core.Patterns.make_case([false],function() { - return new Elixir.Core.Tuple(default_value,map); - })).call(this,Elixir.Core.Functions.contains(key,keys(map))); - })); - export default { - __new__, equal__qmark__, put_new, has_key__qmark__, size, get_and_update, __delete__, update, merge, take, to_list, from_struct, do_to_list, put, get, split, keys, values, fetch__emark__, pop_lazy, put_new_lazy, get_lazy, update__emark__, fetch, drop, pop - }; \ No newline at end of file diff --git a/priv/Elixir.ElixirScript.MapSet.js b/priv/Elixir.ElixirScript.MapSet.js deleted file mode 100644 index 41ba1408..00000000 --- a/priv/Elixir.ElixirScript.MapSet.js +++ /dev/null @@ -1,89 +0,0 @@ - import Elixir from './Elixir'; - import Elixir$ElixirScript$Kernel from './Elixir.ElixirScript.Kernel'; - import Elixir$ElixirScript$List from './Elixir.ElixirScript.List'; - const Elixir$ElixirScript$MapSet = Elixir.Core.Functions.defstruct({ - [Symbol.for('__struct__')]: Symbol.for('Elixir.ElixirScript.MapSet'), [Symbol.for('set')]: Object.freeze([]) - }); - const __new__ = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([],function() { - return Elixir$ElixirScript$MapSet.Elixir$ElixirScript$MapSet.create(Object.freeze({})); - })); - const equal__qmark__ = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable(), Elixir.Core.Patterns.variable()],function(set1,set2) { - return set1 === set2; - })); - const disjoint__qmark__ = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable(), Elixir.Core.Patterns.variable()],function(set1,set2) { - return size(intersection(set1,set2)) == 0; - })); - const member__qmark__ = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable(), Elixir.Core.Patterns.variable()],function(set,term) { - return Elixir.Core.Functions.call_property(set,'set').indexOf(term) >= 0; - })); - const do_subset__qmark__ = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Object.freeze([]), Elixir.Core.Patterns.wildcard()],function() { - return true; - }),Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable(), Elixir.Core.Patterns.variable()],function(set1_list,set2) { - let [term] = Elixir.Core.Patterns.match(Elixir.Core.Patterns.variable(),Elixir$ElixirScript$Kernel.hd(set1_list)); - return Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([false],function() { - return false; - }),Elixir.Core.Patterns.make_case([true],function() { - return do_subset__qmark__(Elixir$ElixirScript$Kernel.tl(set1_list),set2); - })).call(this,member__qmark__(set2,term)); - })); - const subset__qmark__ = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable(), Elixir.Core.Patterns.variable()],function(set1,set2) { - return do_subset__qmark__(to_list(set1),set2); - })); - const intersection = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable(), Elixir.Core.Patterns.variable()],function(set1,set2) { - return do_intersection(to_list(set1),set2,__new__()); - })); - const do_intersection = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Object.freeze([]), Elixir.Core.Patterns.wildcard(), Elixir.Core.Patterns.variable()],function(intersection_set) { - return intersection_set; - }),Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable(), Elixir.Core.Patterns.variable(), Elixir.Core.Patterns.variable()],function(set1_list,set2,intersection_set) { - let [term] = Elixir.Core.Patterns.match(Elixir.Core.Patterns.variable(),Elixir$ElixirScript$Kernel.hd(set1_list)); - return Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([false],function() { - return do_intersection(Elixir$ElixirScript$Kernel.tl(set1_list),set2,intersection_set); - }),Elixir.Core.Patterns.make_case([true],function() { - return do_intersection(Elixir$ElixirScript$Kernel.tl(set1_list),set2,Elixir.Core.SpecialForms.map_update(intersection_set,Object.freeze({ - [Symbol.for('set')]: Elixir.Core.Functions.call_property(intersection_set,'set').concat(Object.freeze([term])) - }))); - })).call(this,member__qmark__(set2,term)); - })); - const union = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable(), Elixir.Core.Patterns.variable()],function(set1,set2) { - return Elixir.Core.SpecialForms.map_update(set1,Object.freeze({ - [Symbol.for('set')]: Elixir.Core.Functions.call_property(set1,'set').concat(Elixir.Core.Functions.call_property(set2,'set')) - })); - })); - const size = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable()],function(set) { - return Elixir$ElixirScript$Kernel.length(Elixir.Core.Functions.call_property(set,'set')); - })); - const do_difference = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Object.freeze([]), Elixir.Core.Patterns.wildcard(), Elixir.Core.Patterns.variable()],function(difference_set) { - return difference_set; - }),Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable(), Elixir.Core.Patterns.variable(), Elixir.Core.Patterns.variable()],function(set1_list,set2,difference_set) { - let [term] = Elixir.Core.Patterns.match(Elixir.Core.Patterns.variable(),Elixir$ElixirScript$Kernel.hd(set1_list)); - return Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([true],function() { - return do_difference(Elixir$ElixirScript$Kernel.tl(set1_list),set2,difference_set); - }),Elixir.Core.Patterns.make_case([false],function() { - return do_difference(Elixir$ElixirScript$Kernel.tl(set1_list),set2,Elixir.Core.SpecialForms.map_update(difference_set,Object.freeze({ - [Symbol.for('set')]: Elixir.Core.Functions.call_property(difference_set,'set').concat(Object.freeze([term])) - }))); - })).call(this,member__qmark__(set2,term)); - })); - const __delete__ = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable(), Elixir.Core.Patterns.variable()],function(set,term) { - return Elixir.Core.SpecialForms.map_update(set,Object.freeze({ - [Symbol.for('set')]: Elixir$ElixirScript$List.remove(Elixir.Core.Functions.call_property(set,'set'),term) - })); - })); - const difference = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable(), Elixir.Core.Patterns.variable()],function(set1,set2) { - return do_difference(to_list(set1),set2,__new__()); - })); - const to_list = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable()],function(set) { - return Elixir.Core.Functions.call_property(set,'set'); - })); - const put = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable(), Elixir.Core.Patterns.variable()],function(set,term) { - return Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([false],function() { - return Elixir.Core.SpecialForms.map_update(set,Object.freeze({ - [Symbol.for('set')]: Elixir.Core.Functions.call_property(set,'set').concat(term) - })); - }),Elixir.Core.Patterns.make_case([true],function() { - return set; - })).call(this,member__qmark__(set,term)); - })); - export default { - Elixir$ElixirScript$MapSet, __new__, equal__qmark__, disjoint__qmark__, member__qmark__, do_subset__qmark__, subset__qmark__, intersection, do_intersection, union, size, do_difference, __delete__, difference, to_list, put - }; \ No newline at end of file diff --git a/priv/Elixir.ElixirScript.Module.js b/priv/Elixir.ElixirScript.Module.js deleted file mode 100644 index 8da28675..00000000 --- a/priv/Elixir.ElixirScript.Module.js +++ /dev/null @@ -1,9 +0,0 @@ - import Elixir from './Elixir'; - import Elixir$ElixirScript$Kernel from './Elixir.ElixirScript.Kernel'; - import Elixir$ElixirScript$Keyword from './Elixir.ElixirScript.Keyword'; - const Elixir$ElixirScript$Module = Elixir.Core.Functions.defstruct({ - [Symbol.for('__struct__')]: Symbol.for('Elixir.ElixirScript.Module'), [Symbol.for('name')]: null, [Symbol.for('functions')]: Elixir.Core.Functions.call_property(Elixir$ElixirScript$Keyword,'new'), [Symbol.for('private_functions')]: Elixir.Core.Functions.call_property(Elixir$ElixirScript$Keyword,'new'), [Symbol.for('macros')]: Elixir.Core.Functions.call_property(Elixir$ElixirScript$Keyword,'new'), [Symbol.for('private_macros')]: Elixir.Core.Functions.call_property(Elixir$ElixirScript$Keyword,'new'), [Symbol.for('body')]: null, [Symbol.for('js_imports')]: Object.freeze([]), [Symbol.for('module_refs')]: Object.freeze([]), [Symbol.for('type')]: Symbol.for('module'), [Symbol.for('impls')]: Elixir.Core.Functions.call_property(HashDict,'new'), [Symbol.for('impl_type')]: null - }); - export default { - Elixir$ElixirScript$Module - }; \ No newline at end of file diff --git a/priv/Elixir.ElixirScript.Range.js b/priv/Elixir.ElixirScript.Range.js deleted file mode 100644 index cb324f83..00000000 --- a/priv/Elixir.ElixirScript.Range.js +++ /dev/null @@ -1,18 +0,0 @@ - import Elixir from './Elixir'; - import Elixir$ElixirScript$Kernel from './Elixir.ElixirScript.Kernel'; - const Elixir$ElixirScript$Range = Elixir.Core.Functions.defstruct({ - [Symbol.for('__struct__')]: Symbol.for('Elixir.ElixirScript.Range'), [Symbol.for('first')]: null, [Symbol.for('last')]: null - }); - const __new__ = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable(), Elixir.Core.Patterns.variable()],function(first,last) { - return Elixir$ElixirScript$Range.Elixir$ElixirScript$Range.create(Object.freeze({ - [Symbol.for('first')]: first, [Symbol.for('last')]: last - })); - })); - const range__qmark__ = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.type(Elixir$ElixirScript$Range.Elixir$ElixirScript$Range,{})],function() { - return true; - }),Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.wildcard()],function() { - return false; - })); - export default { - Elixir$ElixirScript$Range, __new__, range__qmark__ - }; \ No newline at end of file diff --git a/priv/Elixir.ElixirScript.String.Chars.DefImpl.Elixir.Atom.js b/priv/Elixir.ElixirScript.String.Chars.DefImpl.Elixir.Atom.js deleted file mode 100644 index b7e08aba..00000000 --- a/priv/Elixir.ElixirScript.String.Chars.DefImpl.Elixir.Atom.js +++ /dev/null @@ -1,13 +0,0 @@ - import Elixir from './Elixir'; - import Elixir$ElixirScript$Kernel from './Elixir.ElixirScript.Kernel'; - import Elixir$ElixirScript$Atom from './Elixir.ElixirScript.Atom'; - const to_string = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([null],function() { - return ''; - }),Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable()],function(atom) { - return Elixir$ElixirScript$Atom.to_string(atom); - })); - export default { - 'Type': Symbol, 'Implementation': { - to_string - } - }; \ No newline at end of file diff --git a/priv/Elixir.ElixirScript.String.Chars.DefImpl.Elixir.BitString.js b/priv/Elixir.ElixirScript.String.Chars.DefImpl.Elixir.BitString.js deleted file mode 100644 index b2e6f708..00000000 --- a/priv/Elixir.ElixirScript.String.Chars.DefImpl.Elixir.BitString.js +++ /dev/null @@ -1,14 +0,0 @@ - import Elixir from './Elixir'; - import Elixir$ElixirScript$Kernel from './Elixir.ElixirScript.Kernel'; - const to_string = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable()],function(thing) { - return thing; - },function(thing) { - return Elixir$ElixirScript$Kernel.is_binary(thing); - }),Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable()],function(thing) { - return Elixir.Core.Functions.call_property(thing,'toString'); - })); - export default { - 'Type': Elixir.Core.BitString, 'Implementation': { - to_string - } - }; \ No newline at end of file diff --git a/priv/Elixir.ElixirScript.String.Chars.DefImpl.Elixir.Float.js b/priv/Elixir.ElixirScript.String.Chars.DefImpl.Elixir.Float.js deleted file mode 100644 index 41c8f436..00000000 --- a/priv/Elixir.ElixirScript.String.Chars.DefImpl.Elixir.Float.js +++ /dev/null @@ -1,10 +0,0 @@ - import Elixir from './Elixir'; - import Elixir$ElixirScript$Kernel from './Elixir.ElixirScript.Kernel'; - const to_string = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable()],function(float) { - return Elixir.Core.Functions.call_property(float,'toString'); - })); - export default { - 'Type': Elixir.Core.Float, 'Implementation': { - to_string - } - }; \ No newline at end of file diff --git a/priv/Elixir.ElixirScript.String.Chars.DefImpl.Elixir.Integer.js b/priv/Elixir.ElixirScript.String.Chars.DefImpl.Elixir.Integer.js deleted file mode 100644 index de403853..00000000 --- a/priv/Elixir.ElixirScript.String.Chars.DefImpl.Elixir.Integer.js +++ /dev/null @@ -1,10 +0,0 @@ - import Elixir from './Elixir'; - import Elixir$ElixirScript$Kernel from './Elixir.ElixirScript.Kernel'; - const to_string = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable()],function(integer) { - return Elixir.Core.Functions.call_property(integer,'toString'); - })); - export default { - 'Type': Elixir.Core.Integer, 'Implementation': { - to_string - } - }; \ No newline at end of file diff --git a/priv/Elixir.ElixirScript.String.Chars.DefImpl.Elixir.List.js b/priv/Elixir.ElixirScript.String.Chars.DefImpl.Elixir.List.js deleted file mode 100644 index 072a5a56..00000000 --- a/priv/Elixir.ElixirScript.String.Chars.DefImpl.Elixir.List.js +++ /dev/null @@ -1,10 +0,0 @@ - import Elixir from './Elixir'; - import Elixir$ElixirScript$Kernel from './Elixir.ElixirScript.Kernel'; - const to_string = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable()],function(list) { - return Elixir.Core.Functions.call_property(list,'toString'); - })); - export default { - 'Type': Array, 'Implementation': { - to_string - } - }; \ No newline at end of file diff --git a/priv/Elixir.ElixirScript.String.Chars.DefImpl.Elixir.Tuple.js b/priv/Elixir.ElixirScript.String.Chars.DefImpl.Elixir.Tuple.js deleted file mode 100644 index 05d66609..00000000 --- a/priv/Elixir.ElixirScript.String.Chars.DefImpl.Elixir.Tuple.js +++ /dev/null @@ -1,10 +0,0 @@ - import Elixir from './Elixir'; - import Elixir$ElixirScript$Kernel from './Elixir.ElixirScript.Kernel'; - const to_string = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable()],function(tuple) { - return Elixir.Core.Functions.call_property(tuple,'toString'); - })); - export default { - 'Type': Elixir.Core.Tuple, 'Implementation': { - to_string - } - }; \ No newline at end of file diff --git a/priv/Elixir.ElixirScript.String.Chars.DefImpl.js b/priv/Elixir.ElixirScript.String.Chars.DefImpl.js deleted file mode 100644 index dc568414..00000000 --- a/priv/Elixir.ElixirScript.String.Chars.DefImpl.js +++ /dev/null @@ -1,15 +0,0 @@ - import Elixir from './Elixir'; - let impls = []; - import Elixir$ElixirScript$String$Chars$DefImpl$Elixir$Atom from './Elixir.ElixirScript.String.Chars.DefImpl.Elixir.Atom'; - impls.push(Elixir$ElixirScript$String$Chars$DefImpl$Elixir$Atom) - import Elixir$ElixirScript$String$Chars$DefImpl$Elixir$BitString from './Elixir.ElixirScript.String.Chars.DefImpl.Elixir.BitString'; - impls.push(Elixir$ElixirScript$String$Chars$DefImpl$Elixir$BitString) - import Elixir$ElixirScript$String$Chars$DefImpl$Elixir$Float from './Elixir.ElixirScript.String.Chars.DefImpl.Elixir.Float'; - impls.push(Elixir$ElixirScript$String$Chars$DefImpl$Elixir$Float) - import Elixir$ElixirScript$String$Chars$DefImpl$Elixir$Integer from './Elixir.ElixirScript.String.Chars.DefImpl.Elixir.Integer'; - impls.push(Elixir$ElixirScript$String$Chars$DefImpl$Elixir$Integer) - import Elixir$ElixirScript$String$Chars$DefImpl$Elixir$List from './Elixir.ElixirScript.String.Chars.DefImpl.Elixir.List'; - impls.push(Elixir$ElixirScript$String$Chars$DefImpl$Elixir$List) - import Elixir$ElixirScript$String$Chars$DefImpl$Elixir$Tuple from './Elixir.ElixirScript.String.Chars.DefImpl.Elixir.Tuple'; - impls.push(Elixir$ElixirScript$String$Chars$DefImpl$Elixir$Tuple) - export default impls; \ No newline at end of file diff --git a/priv/Elixir.ElixirScript.String.Chars.js b/priv/Elixir.ElixirScript.String.Chars.js deleted file mode 100644 index b03cdc0b..00000000 --- a/priv/Elixir.ElixirScript.String.Chars.js +++ /dev/null @@ -1,10 +0,0 @@ - import Elixir from './Elixir'; - import Elixir$ElixirScript$Kernel from './Elixir.ElixirScript.Kernel'; - import Implementations from './Elixir.ElixirScript.String.Chars.Defimpl'; - const Elixir$ElixirScript$String$Chars = Elixir.Core.Functions.defprotocol({ - to_string: function() { - - } - }); - for(let {Type,Implementation} of Implementations) Elixir.Core.Functions.defimpl(Elixir$ElixirScript$String$Chars,Type,Implementation) - export default Elixir$ElixirScript$String$Chars; \ No newline at end of file diff --git a/priv/Elixir.ElixirScript.String.js b/priv/Elixir.ElixirScript.String.js deleted file mode 100644 index eab78f19..00000000 --- a/priv/Elixir.ElixirScript.String.js +++ /dev/null @@ -1,152 +0,0 @@ - import Elixir from './Elixir'; - import Elixir$ElixirScript$Kernel from './Elixir.ElixirScript.Kernel'; - const do_reverse = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case(['', Elixir.Core.Patterns.variable()],function(str) { - return str; - }),Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable(), Elixir.Core.Patterns.variable()],function(str,reverse_str) { - return do_reverse(str.substr(1),reverse_str + last(str)); - })); - const match__qmark__ = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable(), Elixir.Core.Patterns.variable()],function(str,regex) { - return str.match(regex) != null; - })); - const starts_with__qmark__ = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable(), Elixir.Core.Patterns.variable()],function(str,prefix) { - return str.startsWith(prefix); - },function(str,prefix) { - return Elixir$ElixirScript$Kernel.is_binary(prefix); - }),Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable(), Elixir.Core.Patterns.variable()],function(str,prefixes) { - return do_starts_with__qmark__(str,prefixes); - },function(str,prefixes) { - return Elixir$ElixirScript$Kernel.is_list(prefixes); - })); - const valid_character__qmark__ = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable()],function(codepoint) { - return Elixir.Core.Functions.is_valid_character(codepoint); - })); - const do_ends_with__qmark__ = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.wildcard(), Object.freeze([])],function() { - return false; - }),Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable(), Elixir.Core.Patterns.variable()],function(str,suffixes) { - return Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([true],function() { - return true; - }),Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.wildcard()],function() { - return do_ends_with__qmark__(str,Elixir$ElixirScript$Kernel.tl(suffixes)); - })).call(this,ends_with__qmark__(str,Elixir$ElixirScript$Kernel.hd(suffixes))); - })); - const do_starts_with__qmark__ = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.wildcard(), Object.freeze([])],function() { - return false; - }),Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable(), Elixir.Core.Patterns.variable()],function(str,prefixes) { - return Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([true],function() { - return true; - }),Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.wildcard()],function() { - return do_starts_with__qmark__(str,Elixir$ElixirScript$Kernel.tl(prefixes)); - })).call(this,starts_with__qmark__(str,Elixir$ElixirScript$Kernel.hd(prefixes))); - })); - const ends_with__qmark__ = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable(), Elixir.Core.Patterns.variable()],function(str,suffix) { - return str.endsWith(suffix); - },function(str,suffix) { - return Elixir$ElixirScript$Kernel.is_binary(suffix); - }),Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable(), Elixir.Core.Patterns.variable()],function(str,suffixes) { - return do_ends_with__qmark__(str,suffixes); - },function(str,suffixes) { - return Elixir$ElixirScript$Kernel.is_list(suffixes); - })); - const contains__qmark__ = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable(), Elixir.Core.Patterns.variable()],function(str,s) { - return str.indexOf(s) > -1; - },function(str,s) { - return Elixir$ElixirScript$Kernel.is_binary(s); - }),Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable(), Elixir.Core.Patterns.variable()],function(str,s) { - return do_contains__qmark__(str,s); - },function(str,s) { - return Elixir$ElixirScript$Kernel.is_list(s); - })); - const do_contains__qmark__ = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.wildcard(), Object.freeze([])],function() { - return false; - }),Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable(), Elixir.Core.Patterns.variable()],function(str,prefixes) { - return Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([true],function() { - return true; - }),Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.wildcard()],function() { - return do_contains__qmark__(str,Elixir$ElixirScript$Kernel.tl(prefixes)); - })).call(this,contains__qmark__(str,Elixir$ElixirScript$Kernel.hd(prefixes))); - })); - const to_atom = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable()],function(str) { - return Symbol.for(str); - })); - const capitalize = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable()],function(str) { - let [first] = Elixir.Core.Patterns.match(Elixir.Core.Patterns.variable(),Elixir.Core.Functions.call_property(str[0],'toUpperCase')); - let [rest] = Elixir.Core.Patterns.match(Elixir.Core.Patterns.variable(),Elixir.Core.Functions.call_property(str.substr(1),'toLowerCase')); - return first + rest; - })); - const to_existing_atom = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable()],function(str) { - return Symbol.for(str); - })); - const downcase = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable()],function(str) { - return Elixir.Core.Functions.call_property(str,'toLowerCase'); - })); - const reverse = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable()],function(str) { - return do_reverse(str,''); - })); - const next_grapheme = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([null],function() { - return null; - }),Elixir.Core.Patterns.make_case([''],function() { - return null; - }),Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable()],function(str) { - return new Elixir.Core.Tuple(str[0],str.substr(1)); - })); - const duplicate = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable(), Elixir.Core.Patterns.variable()],function(str,n) { - return str.repeat(n); - })); - const upcase = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable()],function(str) { - return Elixir.Core.Functions.call_property(str,'toUpperCase'); - })); - const to_char_list = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable()],function(str) { - return str.split(''); - })); - const to_float = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable()],function(str) { - return Elixir.Core.Functions.call_property(Elixir.Core,'get_global').parseFloat(str); - })); - const first = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([null],function() { - return null; - }),Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable()],function(str) { - return str[0]; - })); - const last = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([null],function() { - return null; - }),Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable()],function(str) { - return str[length(str) - 1]; - })); - const at = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable(), Elixir.Core.Patterns.variable()],function(str,pos) { - return Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([true],function() { - return null; - }),Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.wildcard()],function() { - return str[pos]; - })).call(this,pos > length(str)); - })); - const next_codepoint = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([null],function() { - return null; - }),Elixir.Core.Patterns.make_case([''],function() { - return null; - }),Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable()],function(str) { - return new Elixir.Core.Tuple(str[0].codePointAt(0),str.substr(1)); - })); - const split = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable()],function(str) { - return Elixir.Core.Functions.call_property(str,'split'); - })); - const graphemes = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable()],function(str) { - return str.split(Object.freeze([])); - })); - const do_codepoints = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case(['', Elixir.Core.Patterns.variable()],function(codepoint_list) { - return codepoint_list; - }),Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable(), Elixir.Core.Patterns.variable()],function(str,codepoint_list) { - return do_codepoints(str.substr(1),codepoint_list.concat(Object.freeze([first.codePointAt(0)]))); - })); - const codepoints = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable()],function(str) { - return do_codepoints(str,Object.freeze([])); - })); - const to_integer = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable()],function(str) { - return Elixir.Core.Functions.call_property(Elixir.Core,'get_global').parseInt(str,10); - }),Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable(), Elixir.Core.Patterns.variable()],function(str,base) { - return Elixir.Core.Functions.call_property(Elixir.Core,'get_global').parseInt(str,base); - })); - const length = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable()],function(str) { - return Elixir.Core.Functions.call_property(str,'length'); - })); - export default { - match__qmark__, starts_with__qmark__, valid_character__qmark__, do_ends_with__qmark__, do_starts_with__qmark__, ends_with__qmark__, contains__qmark__, do_contains__qmark__, to_atom, capitalize, to_existing_atom, downcase, reverse, next_grapheme, duplicate, upcase, to_char_list, to_float, first, last, at, next_codepoint, split, graphemes, do_codepoints, codepoints, to_integer, length - }; \ No newline at end of file diff --git a/priv/Elixir.ElixirScript.Tuple.js b/priv/Elixir.ElixirScript.Tuple.js deleted file mode 100644 index 13cd970d..00000000 --- a/priv/Elixir.ElixirScript.Tuple.js +++ /dev/null @@ -1,53 +0,0 @@ - import Elixir from './Elixir'; - import Elixir$ElixirScript$Kernel from './Elixir.ElixirScript.Kernel'; - const do_duplicate = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.wildcard(), 0, Elixir.Core.Patterns.variable()],function(list) { - return list; - }),Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable(), Elixir.Core.Patterns.variable(), Elixir.Core.Patterns.variable()],function(data,size,list) { - return do_duplicate(data,size - 1,list.concat(Object.freeze([data]))); - })); - const do_insert_at = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable(), Elixir.Core.Patterns.variable(), Elixir.Core.Patterns.variable(), Elixir.Core.Patterns.variable(), Elixir.Core.Patterns.variable()],function(tuple,index,value,current_index,list) { - return Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable()],function(x) { - let [list1] = Elixir.Core.Patterns.match(Elixir.Core.Patterns.variable(),Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([true],function() { - return list.concat(Object.freeze([value, tuple.get(current_index)])); - }),Elixir.Core.Patterns.make_case([false],function() { - return list.concat(Object.freeze([tuple.get(current_index)])); - })).call(this,index == current_index)); - return do_insert_at(tuple,index,value,current_index + 1,list); - },function(x) { - return Elixir.Enum.member__qmark__(Object.freeze([false, null]),x); - }),Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.wildcard()],function() { - return list; - })).call(this,current_index == Elixir$ElixirScript$Kernel.length(tuple)); - })); - const do_delete_at = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable(), Elixir.Core.Patterns.variable(), Elixir.Core.Patterns.variable(), Elixir.Core.Patterns.variable()],function(tuple,index,current_index,list) { - return Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable()],function(x) { - let [list1] = Elixir.Core.Patterns.match(Elixir.Core.Patterns.variable(),Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([true],function() { - return list; - }),Elixir.Core.Patterns.make_case([false],function() { - return list.concat(Object.freeze([tuple.get(current_index)])); - })).call(this,index == current_index)); - return do_delete_at(tuple,index,current_index + 1,list); - },function(x) { - return Elixir.Enum.member__qmark__(Object.freeze([false, null]),x); - }),Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.wildcard()],function() { - return list; - })).call(this,current_index == Elixir$ElixirScript$Kernel.length(tuple)); - })); - const duplicate = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable(), Elixir.Core.Patterns.variable()],function(data,size) { - return new Elixir.Core.Tuple(...do_duplicate(data,size,Object.freeze([]))); - })); - const to_list = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable()],function(tuple) { - return tuple['value']; - })); - const insert_at = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable(), Elixir.Core.Patterns.variable(), Elixir.Core.Patterns.variable()],function(tuple,index,value) { - return new Elixir.Core.Tuple(...do_insert_at(tuple,index,value,0,Object.freeze([]))); - })); - const delete_at = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable(), Elixir.Core.Patterns.variable()],function(tuple,index) { - return new Elixir.Core.Tuple(...do_delete_at(tuple,index,0,Object.freeze([]))); - })); - const append = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable(), Elixir.Core.Patterns.variable()],function(tuple,value) { - return new Elixir.Core.Tuple(...to_list.concat(Object.freeze([value]))); - })); - export default { - duplicate, to_list, insert_at, delete_at, append - }; \ No newline at end of file diff --git a/priv/Elixir.ElixirScript.View.js b/priv/Elixir.ElixirScript.View.js deleted file mode 100644 index 9915042c..00000000 --- a/priv/Elixir.ElixirScript.View.js +++ /dev/null @@ -1,45 +0,0 @@ - import Elixir from './Elixir'; - import Elixir$ElixirScript$Kernel from './Elixir.ElixirScript.Kernel'; - import Elixir$ElixirScript$JS from './Elixir.ElixirScript.JS'; - import Elixir$ElixirScript$Keyword from './Elixir.ElixirScript.Keyword'; - const start = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable(), Elixir.Core.Patterns.variable(), Elixir.Core.Patterns.variable()],function(dom_root,render_func,args) { - let [pid] = Elixir.Core.Patterns.match(Elixir.Core.Patterns.variable(),Elixir.Core.Functions.call_property(Elixir.Core.Functions.call_property(Elixir.Core.Functions.call_property(Elixir$ElixirScript$JS,'global'),'processes'),'spawn')); - let [tree] = Elixir.Core.Patterns.match(Elixir.Core.Patterns.variable(),render_func.apply(null,args)); - let [root_node] = Elixir.Core.Patterns.match(Elixir.Core.Patterns.variable(),Elixir.VirtualDOM.create(tree)); - dom_root.appendChild(root_node); - Elixir.Core.Functions.call_property(Elixir.Core.Functions.call_property(Elixir$ElixirScript$JS,'global'),'processes').put(pid,'state',new Elixir.Core.Tuple(root_node,tree,render_func)); - return new Elixir.Core.Tuple(Symbol.for('ok'),pid); - }),Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable(), Elixir.Core.Patterns.variable(), Elixir.Core.Patterns.variable(), Elixir.Core.Patterns.variable()],function(dom_root,render_func,args,options) { - let [pid] = Elixir.Core.Patterns.match(Elixir.Core.Patterns.variable(),Elixir.Core.Functions.call_property(Elixir.Core.Functions.call_property(Elixir.Core.Functions.call_property(Elixir$ElixirScript$JS,'global'),'processes'),'spawn')); - Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable()],function(x) { - return null; - },function(x) { - return Elixir.Enum.member__qmark__(Object.freeze([false, null]),x); - }),Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.wildcard()],function() { - let [pid1] = Elixir.Core.Patterns.match(Elixir.Core.Patterns.variable(),Elixir.Core.Functions.call_property(Elixir.Core.Functions.call_property(Elixir$ElixirScript$JS,'global'),'processes').register(Elixir$ElixirScript$Keyword.get(options,Symbol.for('name')),pid)); - return pid1; - })).call(this,Elixir$ElixirScript$Keyword.has_key__qmark__(options,Symbol.for('name'))); - let [tree] = Elixir.Core.Patterns.match(Elixir.Core.Patterns.variable(),render_func.apply(null,args)); - let [root_node] = Elixir.Core.Patterns.match(Elixir.Core.Patterns.variable(),Elixir.VirtualDOM.create(tree)); - dom_root.appendChild(root_node); - Elixir.Core.Functions.call_property(Elixir.Core.Functions.call_property(Elixir$ElixirScript$JS,'global'),'processes').put(pid,'state',new Elixir.Core.Tuple(root_node,tree,render_func)); - return new Elixir.Core.Tuple(Symbol.for('ok'),pid); - })); - const render = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable(), Elixir.Core.Patterns.variable()],function(view,args) { - let [root_node,tree,render_func] = Elixir.Core.Patterns.match(Elixir.Core.Patterns.type(Elixir.Core.Tuple,{ - values: [Elixir.Core.Patterns.variable(), Elixir.Core.Patterns.variable(), Elixir.Core.Patterns.variable()] - }),Elixir.Core.Functions.call_property(Elixir.Core.Functions.call_property(Elixir$ElixirScript$JS,'global'),'processes').get(view,'state')); - let _ref = new Elixir.Core.Tuple(root_node,tree,render_func); - let [new_tree] = Elixir.Core.Patterns.match(Elixir.Core.Patterns.variable(),render_func.apply(null,args)); - let [patches] = Elixir.Core.Patterns.match(Elixir.Core.Patterns.variable(),Elixir.VirtualDOM.diff(tree,new_tree)); - let [root_node1] = Elixir.Core.Patterns.match(Elixir.Core.Patterns.variable(),Elixir.VirtualDOM.patch(root_node,patches)); - Elixir.Core.Functions.call_property(Elixir.Core.Functions.call_property(Elixir$ElixirScript$JS,'global'),'processes').put(view,'state',new Elixir.Core.Tuple(root_node,new_tree,render_func)); - return Symbol.for('ok'); - })); - const stop = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable()],function(view) { - Elixir.Core.Functions.call_property(Elixir.Core.Functions.call_property(Elixir$ElixirScript$JS,'global'),'processes').exit(view); - return Symbol.for('ok'); - })); - export default { - start, render, stop - }; \ No newline at end of file diff --git a/priv/Elixir.js b/priv/Elixir.js deleted file mode 100644 index 081c30b9..00000000 --- a/priv/Elixir.js +++ /dev/null @@ -1,3723 +0,0 @@ -class Mailbox { - - constructor() { - this.messages = []; - } - - deliver(message) { - this.messages.push(message); - return message; - } - - get() { - return this.messages; - } - - isEmpty() { - return this.messages.length === 0; - } - - removeAt(index) { - this.messages.splice(index, 1); - } -} - -var States = { - NORMAL: Symbol.for("normal"), - KILL: Symbol.for("kill"), - SUSPEND: Symbol.for("suspend"), - CONTINUE: Symbol.for("continue"), - RECEIVE: Symbol.for("receive"), - SEND: Symbol.for("send"), - SLEEPING: Symbol.for("sleeping"), - RUNNING: Symbol.for("running"), - SUSPENDED: Symbol.for("suspended"), - STOPPED: Symbol.for("stopped"), - SLEEP: Symbol.for("sleep"), - EXIT: Symbol.for("exit"), - NOMATCH: Symbol.for("no_match") -}; - -class Process { - - constructor(pid, mailbox) { - this.pid = pid; - this.mailbox = mailbox; - this.status = States.STOPPED; - this.dict = {}; - } -} - -class Tuple { - - constructor(...args) { - this.values = Object.freeze(args); - this.length = this.values.length; - } - - get(index) { - return this.values[index]; - } - - count() { - return this.values.length; - } - - [Symbol.iterator]() { - return this.values[Symbol.iterator](); - } - - toString() { - var i, - s = ""; - for (i = 0; i < this.values.length; i++) { - if (s !== "") { - s += ", "; - } - s += this.values[i].toString(); - } - - return "{" + s + "}"; - } - - put_elem(index, elem) { - if (index === this.length) { - let new_values = this.values.concat([elem]); - return new Tuple(...new_values); - } - - let new_values = this.values.concat([]); - new_values.splice(index, 0, elem); - return new Tuple(...new_values); - } - - remove_elem(index) { - let new_values = this.values.concat([]); - new_values.splice(index, 1); - return new Tuple(...new_values); - } - -} - -let process_counter = -1; - -class PID { - constructor() { - process_counter = process_counter + 1; - this.id = process_counter; - } - - toString() { - return "PID#<0." + this.id + ".0>"; - } -} - -class Integer {} -class Float {} - -class ProcessSystem { - - constructor() { - this.pids = new Map(); - this.mailboxes = new Map(); - this.names = new Map(); - this.links = new Map(); - - this.current_process = null; - this.suspended = new Map(); - - this.main_process_pid = this.spawn(); - this.set_current(this.main_process_pid); - } - - spawn() { - return this.add_proc(false).pid; - } - - spawn_link() { - return this.add_proc(true).pid; - } - - link(pid) { - this.links.get(this.pid()).add(pid); - this.links.get(pid).add(this.pid()); - } - - unlink(pid) { - this.links.get(this.pid()).delete(pid); - this.links.get(pid).delete(this.pid()); - } - - set_current(id) { - let pid = this.pidof(id); - if (pid !== null) { - this.current_process = this.pids.get(pid); - this.current_process.status = States.RUNNING; - } - } - - add_proc(linked) { - let newpid = new PID(); - let mailbox = new Mailbox(); - let newproc = new Process(newpid, mailbox); - - this.pids.set(newpid, newproc); - this.mailboxes.set(newpid, mailbox); - this.links.set(newpid, new Set()); - - if (linked) { - this.link(newpid); - } - - return newproc; - } - - remove_proc(pid) { - this.pids.delete(pid); - this.unregister(pid); - - if (this.links.has(pid)) { - for (let linkpid of this.links.get(pid)) { - this.links.get(linkpid).delete(pid); - } - - this.links.delete(pid); - } - } - - exit(id) { - let pid = this.pidof(id); - this.remove_proc(id); - } - - register(name, pid) { - if (!this.names.has(name)) { - this.names.set(name, pid); - return name; - } else { - throw new Error("Name is already registered to another process"); - } - } - - registered(name) { - return this.names.has(name) ? this.names.get(name) : null; - } - - unregister(pid) { - for (let name of this.names.keys()) { - if (this.names.has(name) && this.names.get(name) === pid) { - this.names.delete(name); - } - } - } - - pid() { - return this.current_process.pid; - } - - pidof(id) { - if (id instanceof PID) { - return this.pids.has(id) ? id : null; - } else if (id instanceof Process) { - return id.pid; - } else { - let pid = this.registered(id); - if (pid === null) throw "Process name not registered: " + id + " (" + typeof id + ")"; - return pid; - } - } - - put(id, key, value) { - let pid = this.pidof(id); - let process = this.pids.get(pid); - process.dict[key] = value; - } - - get(id, key) { - let pid = this.pidof(id); - let process = this.pids.get(pid); - - if (key != null) { - return process.dict[key]; - } else { - return process.dict; - } - } - - get_keys(id) { - let pid = this.pidof(id); - let process = this.pids.get(pid); - - return Object.keys(process.dict); - } - - erase(id, key) { - let pid = this.pidof(id); - let process = this.pids.get(pid); - - if (key != null) { - delete process.dict[key]; - } else { - process.dict = {}; - } - } -} - -class BitString { - constructor(...args) { - this.value = Object.freeze(this.process(args)); - this.length = this.value.length; - this.bit_size = this.length * 8; - this.byte_size = this.length; - } - - get(index) { - return this.value[index]; - } - - count() { - return this.value.length; - } - - slice(start, end = null) { - let s = this.value.slice(start, end); - let ms = s.map(elem => BitString.integer(elem)); - return new BitString(...ms); - } - - [Symbol.iterator]() { - return this.value[Symbol.iterator](); - } - - toString() { - var i, - s = ""; - for (i = 0; i < this.count(); i++) { - if (s !== "") { - s += ", "; - } - s += this.get(i).toString(); - } - - return "<<" + s + ">>"; - } - - process(bitStringParts) { - let processed_values = []; - - var i; - for (i = 0; i < bitStringParts.length; i++) { - let processed_value = this['process_' + bitStringParts[i].type](bitStringParts[i]); - - for (let attr of bitStringParts[i].attributes) { - processed_value = this['process_' + attr](processed_value); - } - - processed_values = processed_values.concat(processed_value); - } - - return processed_values; - } - - process_integer(value) { - return value.value; - } - - process_float(value) { - if (value.size === 64) { - return BitString.float64ToBytes(value.value); - } else if (value.size === 32) { - return BitString.float32ToBytes(value.value); - } - - throw new Error('Invalid size for float'); - } - - process_bitstring(value) { - return value.value.value; - } - - process_binary(value) { - return BitString.toUTF8Array(value.value); - } - - process_utf8(value) { - return BitString.toUTF8Array(value.value); - } - - process_utf16(value) { - return BitString.toUTF16Array(value.value); - } - - process_utf32(value) { - return BitString.toUTF32Array(value.value); - } - - process_signed(value) { - return new Uint8Array([value])[0]; - } - - process_unsigned(value) { - return value; - } - - process_native(value) { - return value; - } - - process_big(value) { - return value; - } - - process_little(value) { - return value.reverse(); - } - - process_size(value) { - return value; - } - - process_unit(value) { - return value; - } - - static integer(value) { - return BitString.wrap(value, { 'type': 'integer', 'unit': 1, 'size': 8 }); - } - - static float(value) { - return BitString.wrap(value, { 'type': 'float', 'unit': 1, 'size': 64 }); - } - - static bitstring(value) { - return BitString.wrap(value, { 'type': 'bitstring', 'unit': 1, 'size': value.bit_size }); - } - - static bits(value) { - return BitString.bitstring(value); - } - - static binary(value) { - return BitString.wrap(value, { 'type': 'binary', 'unit': 8, 'size': value.length }); - } - - static bytes(value) { - return BitString.binary(value); - } - - static utf8(value) { - return BitString.wrap(value, { 'type': 'utf8', 'unit': 1, 'size': value.length }); - } - - static utf16(value) { - return BitString.wrap(value, { 'type': 'utf16', 'unit': 1, 'size': value.length * 2 }); - } - - static utf32(value) { - return BitString.wrap(value, { 'type': 'utf32', 'unit': 1, 'size': value.length * 4 }); - } - - static signed(value) { - return BitString.wrap(value, {}, 'signed'); - } - - static unsigned(value) { - return BitString.wrap(value, {}, 'unsigned'); - } - - static native(value) { - return BitString.wrap(value, {}, 'native'); - } - - static big(value) { - return BitString.wrap(value, {}, 'big'); - } - - static little(value) { - return BitString.wrap(value, {}, 'little'); - } - - static size(value, count) { - return BitString.wrap(value, { 'size': count }); - } - - static unit(value, count) { - return BitString.wrap(value, { 'unit': count }); - } - - static wrap(value, opt, new_attribute = null) { - let the_value = value; - - if (!(value instanceof Object)) { - the_value = { 'value': value, 'attributes': [] }; - } - - the_value = Object.assign(the_value, opt); - - if (new_attribute) { - the_value.attributes.push(new_attribute); - } - - return the_value; - } - - static toUTF8Array(str) { - var utf8 = []; - for (var i = 0; i < str.length; i++) { - var charcode = str.charCodeAt(i); - if (charcode < 0x80) { - utf8.push(charcode); - } else if (charcode < 0x800) { - utf8.push(0xc0 | charcode >> 6, 0x80 | charcode & 0x3f); - } else if (charcode < 0xd800 || charcode >= 0xe000) { - utf8.push(0xe0 | charcode >> 12, 0x80 | charcode >> 6 & 0x3f, 0x80 | charcode & 0x3f); - } - // surrogate pair - else { - i++; - // UTF-16 encodes 0x10000-0x10FFFF by - // subtracting 0x10000 and splitting the - // 20 bits of 0x0-0xFFFFF into two halves - charcode = 0x10000 + ((charcode & 0x3ff) << 10 | str.charCodeAt(i) & 0x3ff); - utf8.push(0xf0 | charcode >> 18, 0x80 | charcode >> 12 & 0x3f, 0x80 | charcode >> 6 & 0x3f, 0x80 | charcode & 0x3f); - } - } - return utf8; - } - - static toUTF16Array(str) { - var utf16 = []; - for (var i = 0; i < str.length; i++) { - var codePoint = str.codePointAt(i); - - if (codePoint <= 255) { - utf16.push(0); - utf16.push(codePoint); - } else { - utf16.push(codePoint >> 8 & 0xFF); - utf16.push(codePoint & 0xFF); - } - } - return utf16; - } - - static toUTF32Array(str) { - var utf32 = []; - for (var i = 0; i < str.length; i++) { - var codePoint = str.codePointAt(i); - - if (codePoint <= 255) { - utf32.push(0); - utf32.push(0); - utf32.push(0); - utf32.push(codePoint); - } else { - utf32.push(0); - utf32.push(0); - utf32.push(codePoint >> 8 & 0xFF); - utf32.push(codePoint & 0xFF); - } - } - return utf32; - } - - //http://stackoverflow.com/questions/2003493/javascript-float-from-to-bits - static float32ToBytes(f) { - var bytes = []; - - var buf = new ArrayBuffer(4); - new Float32Array(buf)[0] = f; - - let intVersion = new Uint32Array(buf)[0]; - - bytes.push(intVersion >> 24 & 0xFF); - bytes.push(intVersion >> 16 & 0xFF); - bytes.push(intVersion >> 8 & 0xFF); - bytes.push(intVersion & 0xFF); - - return bytes; - } - - static float64ToBytes(f) { - var bytes = []; - - var buf = new ArrayBuffer(8); - new Float64Array(buf)[0] = f; - - var intVersion1 = new Uint32Array(buf)[0]; - var intVersion2 = new Uint32Array(buf)[1]; - - bytes.push(intVersion2 >> 24 & 0xFF); - bytes.push(intVersion2 >> 16 & 0xFF); - bytes.push(intVersion2 >> 8 & 0xFF); - bytes.push(intVersion2 & 0xFF); - - bytes.push(intVersion1 >> 24 & 0xFF); - bytes.push(intVersion1 >> 16 & 0xFF); - bytes.push(intVersion1 >> 8 & 0xFF); - bytes.push(intVersion1 & 0xFF); - - return bytes; - } -} - -class Variable { - - constructor(default_value = Symbol.for("elixirscript.no_value")) { - this.default_value = default_value; - } -} - -class Wildcard { - constructor() {} -} - -class StartsWith { - - constructor(prefix) { - this.prefix = prefix; - } -} - -class Capture { - - constructor(value) { - this.value = value; - } -} - -class HeadTail { - - constructor(head = null, tail = null) { - this.head = head; - this.tail = tail; - } -} - -class Type { - - constructor(type, objPattern = {}) { - this.type = type; - this.objPattern = objPattern; - } -} - -class Bound { - - constructor(value) { - this.value = value; - } -} - -class BitStringMatch { - - constructor(...values) { - this.values = values; - } - - length() { - return values.length; - } - - bit_size() { - return this.byte_size() * 8; - } - - byte_size() { - let s = 0; - - for (let val of this.values) { - s = s + val.unit * val.size / 8; - } - - return s; - } - - getValue(index) { - return this.values(index); - } - - getSizeOfValue(index) { - let val = this.getValue(index); - return val.unit * val.size; - } - - getTypeOfValue(index) { - return this.getValue(index).type; - } -} - -function variable(default_value = Symbol.for("elixirscript.no_value")) { - return new Variable(default_value); -} - -function wildcard() { - return new Wildcard(); -} - -function startsWith(prefix) { - return new StartsWith(prefix); -} - -function capture(value) { - return new Capture(value); -} - -function headTail(head = null, tail = null) { - return new HeadTail(head, tail); -} - -function type(type, objPattern = {}) { - return new Type(type, objPattern); -} - -function bound(value) { - return new Bound(value); -} - -function bitStringMatch(...values) { - return new BitStringMatch(...values); -} - -function is_number(value) { - return typeof value === 'number'; -} - -function is_string(value) { - return typeof value === 'string'; -} - -function is_boolean(value) { - return typeof value === 'boolean'; -} - -function is_symbol(value) { - return typeof value === 'symbol'; -} - -function is_null(value) { - return value === null; -} - -function is_undefined(value) { - return typeof value === 'undefined'; -} - -function is_function(value) { - return Object.prototype.toString.call(value) == '[object Function]'; -} - -function is_variable(value) { - return value instanceof Variable; -} - -function is_wildcard(value) { - return value instanceof Wildcard; -} - -function is_headTail(value) { - return value instanceof HeadTail; -} - -function is_capture(value) { - return value instanceof Capture; -} - -function is_type(value) { - return value instanceof Type; -} - -function is_startsWith(value) { - return value instanceof StartsWith; -} - -function is_bound(value) { - return value instanceof Bound; -} - -function is_object(value) { - return typeof value === 'object'; -} - -function is_array(value) { - return Array.isArray(value); -} - -function is_bitstring(value) { - return value instanceof BitStringMatch; -} - -var Checks = { - is_number, - is_string, - is_boolean, - is_symbol, - is_null, - is_undefined, - is_function, - is_variable, - is_wildcard, - is_headTail, - is_capture, - is_type, - is_startsWith, - is_bound, - is_object, - is_array, - is_bitstring -}; - -function resolveSymbol(pattern) { - return function (value) { - return Checks.is_symbol(value) && value === pattern; - }; -} - -function resolveString(pattern) { - return function (value) { - return Checks.is_string(value) && value === pattern; - }; -} - -function resolveNumber(pattern) { - return function (value) { - return Checks.is_number(value) && value === pattern; - }; -} - -function resolveBoolean(pattern) { - return function (value) { - return Checks.is_boolean(value) && value === pattern; - }; -} - -function resolveFunction(pattern) { - return function (value) { - return Checks.is_function(value) && value === pattern; - }; -} - -function resolveNull(pattern) { - return function (value) { - return Checks.is_null(value); - }; -} - -function resolveBound(pattern) { - return function (value, args) { - if (typeof value === typeof pattern.value && value === pattern.value) { - args.push(value); - return true; - } - - return false; - }; -} - -function resolveWildcard() { - return function () { - return true; - }; -} - -function resolveVariable() { - return function (value, args) { - args.push(value); - return true; - }; -} - -function resolveHeadTail(pattern) { - const headMatches = buildMatch(pattern.head); - const tailMatches = buildMatch(pattern.tail); - - return function (value, args) { - if (!Checks.is_array(value) || value.length < 2) { - return false; - } - - const head = value[0]; - const tail = value.slice(1); - - if (headMatches(head, args) && tailMatches(tail, args)) { - return true; - } - }; -} - -function resolveCapture(pattern) { - const matches = buildMatch(pattern.value); - - return function (value, args) { - if (matches(value, args)) { - args.push(value); - return true; - } - - return false; - }; -} - -function resolveStartsWith(pattern) { - const prefix = pattern.prefix; - - return function (value, args) { - if (Checks.is_string(value) && value.startsWith(prefix)) { - args.push(value.substring(prefix.length)); - return true; - } - - return false; - }; -} - -function resolveType(pattern) { - return function (value, args) { - if (value instanceof pattern.type) { - const matches = buildMatch(pattern.objPattern); - return matches(value, args) && args.push(value) > 0; - } - - return false; - }; -} - -function resolveArray(pattern) { - const matches = pattern.map(x => buildMatch(x)); - - return function (value, args) { - if (!Checks.is_array(value) || value.length != pattern.length) { - return false; - } - - return value.every(function (v, i) { - return matches[i](value[i], args); - }); - }; -} - -function resolveObject(pattern) { - let matches = {}; - - for (let key of Object.keys(pattern).concat(Object.getOwnPropertySymbols(pattern))) { - matches[key] = buildMatch(pattern[key]); - } - - return function (value, args) { - if (!Checks.is_object(value) || pattern.length > value.length) { - return false; - } - - for (let key of Object.keys(pattern).concat(Object.getOwnPropertySymbols(pattern))) { - if (!(key in value) || !matches[key](value[key], args)) { - return false; - } - } - - return true; - }; -} - -function resolveBitString(pattern) { - let patternBitString = []; - - for (let bitstringMatchPart of pattern.values) { - if (Checks.is_variable(bitstringMatchPart.value)) { - let size = getSize(bitstringMatchPart.unit, bitstringMatchPart.size); - fillArray(patternBitString, size); - } else { - patternBitString = patternBitString.concat(new BitString(bitstringMatchPart).value); - } - } - - let patternValues = pattern.values; - - return function (value, args) { - let bsValue = null; - - if (!Checks.is_string(value) && !(value instanceof BitString)) { - return false; - } - - if (Checks.is_string(value)) { - bsValue = new BitString(BitString.binary(value)); - } else { - bsValue = value; - } - - let beginningIndex = 0; - - for (let i = 0; i < patternValues.length; i++) { - let bitstringMatchPart = patternValues[i]; - - if (Checks.is_variable(bitstringMatchPart.value) && bitstringMatchPart.type == 'binary' && bitstringMatchPart.size === undefined && i < patternValues.length - 1) { - throw new Error("a binary field without size is only allowed at the end of a binary pattern"); - } - - let size = 0; - let bsValueArrayPart = []; - let patternBitStringArrayPart = []; - size = getSize(bitstringMatchPart.unit, bitstringMatchPart.size); - - if (i === patternValues.length - 1) { - bsValueArrayPart = bsValue.value.slice(beginningIndex); - patternBitStringArrayPart = patternBitString.slice(beginningIndex); - } else { - bsValueArrayPart = bsValue.value.slice(beginningIndex, beginningIndex + size); - patternBitStringArrayPart = patternBitString.slice(beginningIndex, beginningIndex + size); - } - - if (Checks.is_variable(bitstringMatchPart.value)) { - switch (bitstringMatchPart.type) { - case 'integer': - if (bitstringMatchPart.attributes && bitstringMatchPart.attributes.indexOf("signed") != -1) { - args.push(new Int8Array([bsValueArrayPart[0]])[0]); - } else { - args.push(new Uint8Array([bsValueArrayPart[0]])[0]); - } - break; - - case 'float': - if (size === 64) { - args.push(Float64Array.from(bsValueArrayPart)[0]); - } else if (size === 32) { - args.push(Float32Array.from(bsValueArrayPart)[0]); - } else { - return false; - } - break; - - case 'bitstring': - args.push(createBitString(bsValueArrayPart)); - break; - - case 'binary': - args.push(String.fromCharCode.apply(null, new Uint8Array(bsValueArrayPart))); - break; - - case 'utf8': - args.push(String.fromCharCode.apply(null, new Uint8Array(bsValueArrayPart))); - break; - - case 'utf16': - args.push(String.fromCharCode.apply(null, new Uint16Array(bsValueArrayPart))); - break; - - case 'utf32': - args.push(String.fromCharCode.apply(null, new Uint32Array(bsValueArrayPart))); - break; - - default: - return false; - } - } else if (!arraysEqual(bsValueArrayPart, patternBitStringArrayPart)) { - return false; - } - - beginningIndex = beginningIndex + size; - } - - return true; - }; -} - -function getSize(unit, size) { - return unit * size / 8; -} - -function arraysEqual(a, b) { - if (a === b) return true; - if (a == null || b == null) return false; - if (a.length != b.length) return false; - - for (var i = 0; i < a.length; ++i) { - if (a[i] !== b[i]) return false; - } - - return true; -} - -function fillArray(arr, num) { - for (let i = 0; i < num; i++) { - arr.push(0); - } -} - -function createBitString(arr) { - let integerParts = arr.map(elem => BitString.integer(elem)); - return new BitString(...integerParts); -} - -function resolveNoMatch() { - return function () { - return false; - }; -} - -var Resolvers = { - resolveBound, - resolveWildcard, - resolveVariable, - resolveHeadTail, - resolveCapture, - resolveStartsWith, - resolveType, - resolveArray, - resolveObject, - resolveNoMatch, - resolveSymbol, - resolveString, - resolveNumber, - resolveBoolean, - resolveFunction, - resolveNull, - resolveBitString -}; - -function buildMatch(pattern) { - - if (Checks.is_variable(pattern)) { - return Resolvers.resolveVariable(pattern); - } - - if (Checks.is_wildcard(pattern)) { - return Resolvers.resolveWildcard(pattern); - } - - if (Checks.is_undefined(pattern)) { - return Resolvers.resolveWildcard(pattern); - } - - if (Checks.is_headTail(pattern)) { - return Resolvers.resolveHeadTail(pattern); - } - - if (Checks.is_startsWith(pattern)) { - return Resolvers.resolveStartsWith(pattern); - } - - if (Checks.is_capture(pattern)) { - return Resolvers.resolveCapture(pattern); - } - - if (Checks.is_bound(pattern)) { - return Resolvers.resolveBound(pattern); - } - - if (Checks.is_type(pattern)) { - return Resolvers.resolveType(pattern); - } - - if (Checks.is_array(pattern)) { - return Resolvers.resolveArray(pattern); - } - - if (Checks.is_number(pattern)) { - return Resolvers.resolveNumber(pattern); - } - - if (Checks.is_string(pattern)) { - return Resolvers.resolveString(pattern); - } - - if (Checks.is_boolean(pattern)) { - return Resolvers.resolveBoolean(pattern); - } - - if (Checks.is_symbol(pattern)) { - return Resolvers.resolveSymbol(pattern); - } - - if (Checks.is_null(pattern)) { - return Resolvers.resolveNull(pattern); - } - - if (Checks.is_bitstring(pattern)) { - return Resolvers.resolveBitString(pattern); - } - - if (Checks.is_object(pattern)) { - return Resolvers.resolveObject(pattern); - } - - return Resolvers.resolveNoMatch(); -} - -class MatchError extends Error { - constructor(arg) { - super(); - - if (typeof arg === 'symbol') { - this.message = 'No match for: ' + arg.toString(); - } else if (Array.isArray(arg)) { - let mappedValues = arg.map(x => x.toString()); - this.message = 'No match for: ' + mappedValues; - } else { - this.message = 'No match for: ' + arg; - } - - this.stack = new Error().stack; - this.name = this.constructor.name; - } -} - -class Case { - - constructor(pattern, fn, guard = () => true) { - this.pattern = buildMatch(pattern); - this.arity = pattern.length; - this.optionals = getOptionalValues(pattern); - this.fn = fn; - this.guard = guard; - } -} - -function make_case(pattern, fn, guard = () => true) { - return new Case(pattern, fn, guard); -} - -function defmatch(...cases) { - return function (...args) { - for (let processedCase of cases) { - let result = []; - args = fillInOptionalValues(args, processedCase.arity, processedCase.optionals); - - if (processedCase.pattern(args, result) && processedCase.guard.apply(this, result)) { - return processedCase.fn.apply(this, result); - } - } - - throw new MatchError(args); - }; -} - -function getOptionalValues(pattern) { - let optionals = []; - - for (let i = 0; i < pattern.length; i++) { - if (pattern[i] instanceof Variable && pattern[i].default_value != Symbol.for("elixirscript.no_value")) { - optionals.push([i, pattern[i].default_value]); - } - } - - return optionals; -} - -function fillInOptionalValues(args, arity, optionals) { - if (args.length === arity || optionals.length === 0) { - return args; - } - - if (args.length + optionals.length < arity) { - return args; - } - - let numberOfOptionalsToFill = arity - args.length; - let optionalsToRemove = optionals.length - numberOfOptionalsToFill; - - let optionalsToUse = optionals.slice(optionalsToRemove); - - for (let [index, value] of optionalsToUse) { - args.splice(index, 0, value); - if (args.length === arity) { - break; - } - } - - return args; -} - -function match(pattern, expr, guard = () => true) { - let result = []; - let processedPattern = buildMatch(pattern); - if (processedPattern(expr, result) && guard.apply(this, result)) { - return result; - } else { - throw new MatchError(expr); - } -} - -function match_no_throw(pattern, expr, guard = () => true) { - try { - return match(pattern, expr, guard); - } catch (e) { - if (e instanceof MatchError || e.message.startsWith('No match for:')) { - return null; - } - - throw e; - } -} - -var Patterns = { - defmatch, match, MatchError, match_no_throw, - variable, wildcard, startsWith, - capture, headTail, type, bound, Case, make_case, bitStringMatch -}; - -//https://github.com/airportyh/protomorphism -class Protocol { - constructor(spec) { - this.registry = new Map(); - this.fallback = null; - - for (let funName in spec) { - this[funName] = createFun(funName).bind(this); - } - - function createFun(funName) { - - return function (...args) { - let thing = args[0]; - let fun = null; - - if (Number.isInteger(thing) && this.hasImplementation(Integer)) { - fun = this.registry.get(Integer)[funName]; - } else if (typeof thing === "number" && !Number.isInteger(thing) && this.hasImplementation(Float)) { - fun = this.registry.get(Float)[funName]; - } else if (this.hasImplementation(thing)) { - fun = this.registry.get(thing.constructor)[funName]; - } else if (this.fallback) { - fun = this.fallback[funName]; - } - - if (fun != null) { - let retval = fun.apply(this, args); - return retval; - } - - throw new Error("No implementation found for " + thing); - }; - } - } - - implementation(type, implementation) { - if (type === null) { - this.fallback = implementation; - } else { - this.registry.set(type, implementation); - } - } - - hasImplementation(thing) { - if (thing === Integer || thing === Float) { - return this.registry.has(thing); - } - - return this.registry.has(thing.constructor); - } -} - -function call_property(item, property) { - let prop = null; - - if (typeof item === "number" || typeof item === "symbol" || typeof item === "boolean" || typeof item === "string") { - if (item[property] !== undefined) { - prop = property; - } else if (item[Symbol.for(property)] !== undefined) { - prop = Symbol.for(property); - } - } else { - if (property in item) { - prop = property; - } else if (Symbol.for(property) in item) { - prop = Symbol.for(property); - } - } - - if (prop === null) { - throw new Error(`Property ${ property } not found in ${ item }`); - } - - if (item[prop] instanceof Function) { - return item[prop](); - } else { - return item[prop]; - } -} - -function apply(...args) { - if (args.length === 2) { - args[0].apply(null, args.slice(1)); - } else { - args[0][args[1]].apply(null, args.slice(2)); - } -} - -function contains(left, right) { - for (let x of right) { - if (Patterns.match_no_throw(left, x) != null) { - return true; - } - } - - return false; -} - -function get_global() { - if (typeof self !== "undefined") { - return self; - } else if (typeof window !== "undefined") { - return window; - } else if (typeof global !== "undefined") { - return global; - } - - throw new Error("No global state found"); -} - -function defstruct(defaults) { - return class { - constructor(update = {}) { - let the_values = Object.assign(defaults, update); - Object.assign(this, the_values); - } - - static create(updates = {}) { - let x = new this(updates); - return Object.freeze(x); - } - }; -} - -function defexception(defaults) { - return class extends Error { - constructor(update = {}) { - let message = update.message || ""; - super(message); - - let the_values = Object.assign(defaults, update); - Object.assign(this, the_values); - - this.name = this.constructor.name; - this.message = message; - this[SpecialForms.atom("__exception__")] = true; - Error.captureStackTrace(this, this.constructor.name); - } - - static create(updates = {}) { - let x = new this(updates); - return Object.freeze(x); - } - }; -} - -function defprotocol(spec) { - return new Protocol(spec); -} - -function defimpl(protocol, type, impl) { - protocol.implementation(type, impl); -} - -function get_object_keys(obj) { - return Object.keys(obj).concat(Object.getOwnPropertySymbols(obj)); -} - -function is_valid_character(codepoint) { - try { - return String.fromCodePoint(codepoint) != null; - } catch (e) { - return false; - } -} - -//https://developer.mozilla.org/en-US/docs/Web/API/WindowBase64/Base64_encoding_and_decoding#Solution_2_%E2%80%93_rewrite_the_DOMs_atob()_and_btoa()_using_JavaScript's_TypedArrays_and_UTF-8 -function b64EncodeUnicode(str) { - return btoa(encodeURIComponent(str).replace(/%([0-9A-F]{2})/g, function (match, p1) { - return String.fromCharCode('0x' + p1); - })); -} - -function delete_property_from_map(map, property) { - let new_map = Object.assign(Object.create(map.constructor.prototype), map); - delete new_map[property]; - - return Object.freeze(new_map); -} - -function class_to_obj(map) { - let new_map = Object.assign({}, map); - return Object.freeze(new_map); -} - -function add_property_to_map(map, property, value) { - let new_map = Object.assign({}, map); - new_map[property] = value; - return Object.freeze(new_map); -} - -function update_map(map, property, value) { - if (property in get_object_keys(map)) { - return add_property_to_map(map, property, value); - } - - throw "map does not have key"; -} - -function bnot(expr) { - return ~expr; -} - -function band(left, right) { - return left & right; -} - -function bor(left, right) { - return left | right; -} - -function bsl(left, right) { - return left << right; -} - -function bsr(left, right) { - return left >> right; -} - -function bxor(left, right) { - return left ^ right; -} - -function zip(list_of_lists) { - if (list_of_lists.length === 0) { - return Object.freeze([]); - } - - let new_value = []; - let smallest_length = list_of_lists[0]; - - for (let x of list_of_lists) { - if (x.length < smallest_length) { - smallest_length = x.length; - } - } - - for (let i = 0; i < smallest_length; i++) { - let current_value = []; - for (let j = 0; j < list_of_lists.length; j++) { - current_value.push(list_of_lists[j][i]); - } - - new_value.push(new Tuple(...current_value)); - } - - return Object.freeze(new_value); -} - -function can_decode64(data) { - try { - atob(data); - return true; - } catch (e) { - return false; - } -} - -function remove_from_list(list, element) { - let found = false; - - return list.filter(elem => { - if (!found && elem === element) { - found = true; - return false; - } - - return true; - }); -} - -function foldl(fun, acc, list) { - let acc1 = acc; - - for (const el of list) { - acc1 = fun(el, acc1); - } - - return acc1; -} - -function foldr(fun, acc, list) { - let acc1 = acc; - - for (let i = list.length - 1; i >= 0; i--) { - acc1 = fun(list[i], acc1); - } - - return acc1; -} - -function keyfind(key, n, tuplelist) { - - for (let i = tuplelist.length - 1; i >= 0; i--) { - if (tuplelist[i].get(n) === key) { - return tuplelist[i]; - } - } - - return false; -} - -function keydelete(key, n, tuplelist) { - - for (let i = tuplelist.length - 1; i >= 0; i--) { - if (tuplelist[i].get(n) === key) { - return tuplelist.concat([]).splice(i, 1); - } - } - - return tuplelist; -} - -function keystore(key, n, list, newtuple) { - for (let i = list.length - 1; i >= 0; i--) { - if (list[i].get(n) === key) { - return list.concat([]).splice(i, 1, newtuple); - } - } - - return list.concat([]).push(newtuple); -} - -function keymember(key, n, list) { - for (let i = list.length - 1; i >= 0; i--) { - if (list[i].get(n) === key) { - return true; - } - } - - return false; -} - -function keytake(key, n, list) { - if (!keymember(key, n, list)) { - return false; - } - - let tuple = keyfind(key, n, list); - - return new Tuple(tuple.get(n), tuple, keydelete(key, n, list)); -} - -function keyreplace(key, n, list, newtuple) { - - for (let i = tuplelist.length - 1; i >= 0; i--) { - if (tuplelist[i].get(n) === key) { - return tuplelist.concat([]).splice(i, 1, newtuple); - } - } - - return tuplelist; -} - -function reverse(list) { - return list.concat([]).reverse(); -} - -function maps_find(key, map) { - if (key in get_object_keys(map)) { - return new Tuple(Symbol.for("ok"), map[key]); - } else { - return Symbol.for("error"); - } -} - -function flatten(list, tail = []) { - let new_list = []; - - for (let e of list) { - if (isArray(e)) { - new_list = new_list.concat(flatten(e)); - } else { - new_list.push(e); - } - } - - return Object.freeze(new_list.concat(tail)); -} - -function duplicate(n, elem) { - let list = []; - - for (let i = 0; i < n; i++) { - list.push(elem); - } - - return Object.freeze(list); -} - -function mapfoldl(fun, acc, list) { - let newlist = []; - - for (let x of list) { - let tup = fun(x, acc); - newlist.push(tup.get(0)); - acc = tup.get(1); - } - - return new Tuple(Object.freeze(newlist), acc); -} - -function filtermap(fun, list) { - let newlist = []; - - for (x of list) { - let result = fun(x); - - if (result === true) { - newlist.push(x); - } else if (result instanceof Tuple) { - newlist.push(result.get(1)); - } - } - - return Object.freeze(newlist); -} - -function maps_fold(fun, acc, map) { - let acc1 = acc; - - for (let k of get_object_keys(map)) { - acc1 = fun(k, map[k], acc1); - } - - return acc1; -} - -var Functions = { - call_property, - apply, - contains, - get_global, - defstruct, - defexception, - defprotocol, - defimpl, - get_object_keys, - is_valid_character, - b64EncodeUnicode, - delete_property_from_map, - add_property_to_map, - class_to_obj, - can_decode64, - bnot, - band, - bor, - bsl, - bsr, - bxor, - zip, - foldl, - foldr, - remove_from_list, - keydelete, - keystore, - keyfind, - keytake, - keyreplace, - reverse, - update_map, - maps_find, - flatten, - duplicate, - mapfoldl, - filtermap, - maps_fold -}; - -function _case(condition, clauses) { - return Patterns.defmatch(...clauses)(condition); -} - -function cond(clauses) { - for (let clause of clauses) { - if (clause[0]) { - return clause[1](); - } - } - - throw new Error(); -} - -function map_update(map, values) { - return Object.freeze(Object.assign(Object.create(map.constructor.prototype), map, values)); -} - -function _for(collections, fun, filter = () => true, into = [], previousValues = []) { - let pattern = collections[0][0]; - let collection = collections[0][1]; - - if (collections.length === 1) { - if (collection instanceof BitString) { - let bsSlice = collection.slice(0, pattern.byte_size()); - let i = 1; - - while (bsSlice.byte_size == pattern.byte_size()) { - let r = Patterns.match_no_throw(pattern, bsSlice); - let args = previousValues.concat(r); - - if (r && filter.apply(this, args)) { - into = into.concat([fun.apply(this, args)]); - } - - bsSlice = collection.slice(pattern.byte_size() * i, pattern.byte_size() * (i + 1)); - i++; - } - - return into; - } else { - for (let elem of collection) { - let r = Patterns.match_no_throw(pattern, elem); - let args = previousValues.concat(r); - - if (r && filter.apply(this, args)) { - into = into.concat([fun.apply(this, args)]); - } - } - - return into; - } - } else { - let _into = []; - - if (collection instanceof BitString) { - let bsSlice = collection.slice(0, pattern.byte_size()); - let i = 1; - - while (bsSlice.byte_size == pattern.byte_size()) { - let r = Patterns.match_no_throw(pattern, bsSlice); - if (r) { - _into = into.concat(this._for(collections.slice(1), fun, filter, _into, previousValues.concat(r))); - } - - bsSlice = collection.slice(pattern.byte_size() * i, pattern.byte_size() * (i + 1)); - i++; - } - } else { - for (let elem of collection) { - let r = Patterns.match_no_throw(pattern, elem); - if (r) { - _into = into.concat(this._for(collections.slice(1), fun, filter, _into, previousValues.concat(r))); - } - } - } - - return _into; - } -} - -function _try(do_fun, rescue_function, catch_fun, else_function, after_function) { - let result = null; - - try { - result = do_fun(); - } catch (e) { - let ex_result = null; - - if (rescue_function) { - try { - ex_result = rescue_function(e); - return ex_result; - } catch (ex) { - if (ex instanceof Patterns.MatchError) { - throw ex; - } - } - } - - if (catch_fun) { - try { - ex_result = catch_fun(e); - return ex_result; - } catch (ex) { - if (ex instanceof Patterns.MatchError) { - throw ex; - } - } - } - - throw e; - } finally { - if (after_function) { - after_function(); - } - } - - if (else_function) { - try { - return else_function(result); - } catch (ex) { - if (ex instanceof Patterns.MatchError) { - throw new Error("No Match Found in Else"); - } - - throw ex; - } - } else { - return result; - } -} - -function _with(...args) { - let argsToPass = []; - - for (let i = 0; i < args.length; i++) { - if (i === args.length - 1) { - return args[i].apply(null, argsToPass); - } else { - let [pattern, func] = args[i]; - - let result = func.apply(null, argsToPass); - - let patternResult = Patterns.match_no_throw(pattern, result); - - if (patternResult == null) { - return result; - } else { - argsToPass = argsToPass.concat(patternResult); - } - } - } - - return null; -} - -var SpecialForms$1 = { - _case, - cond, - map_update, - _for, - _try, - _with -}; - -Functions.get_global().processes = Functions.get_global().processes || new ProcessSystem(); - -var Core = { - ProcessSystem, - Tuple, - PID, - BitString, - Patterns, - Integer, - Float, - Functions, - SpecialForms: SpecialForms$1 -}; - -let Enum = { - - all__qmark__: function (collection, fun = x => x) { - for (let elem of collection) { - if (!fun(elem)) { - return false; - } - } - - return true; - }, - - any__qmark__: function (collection, fun = x => x) { - for (let elem of collection) { - if (fun(elem)) { - return true; - } - } - - return false; - }, - - at: function (collection, n, the_default = null) { - if (n > this.count(collection) || n < 0) { - return the_default; - } - - return collection[n]; - }, - - concat: function (...enumables) { - return enumables[0].concat(enumables[1]); - }, - - count: function (collection, fun = null) { - if (fun == null) { - return collection.length; - } else { - return collection.filter(fun).length; - } - }, - - drop: function (collection, count) { - return collection.slice(count); - }, - - drop_while: function (collection, fun) { - let count = 0; - - for (let elem of collection) { - if (fun(elem)) { - count = count + 1; - } else { - break; - } - } - - return collection.slice(count); - }, - - each: function (collection, fun) { - for (let elem of collection) { - fun(elem); - } - }, - - empty__qmark__: function (collection) { - return collection.length === 0; - }, - - fetch: function (collection, n) { - if (Array.isArray(collection)) { - if (n < this.count(collection) && n >= 0) { - return new Core.Tuple(Symbol.for("ok"), collection[n]); - } else { - return Symbol.for("error"); - } - } - - throw new Error("collection is not an Enumerable"); - }, - - fetch__emark__: function (collection, n) { - if (Array.isArray(collection)) { - if (n < this.count(collection) && n >= 0) { - return collection[n]; - } else { - throw new Error("out of bounds error"); - } - } - - throw new Error("collection is not an Enumerable"); - }, - - filter: function (collection, fun) { - let result = []; - - for (let elem of collection) { - if (fun(elem)) { - result.push(elem); - } - } - - return result; - }, - - filter_map: function (collection, filter, mapper) { - return Enum.map(Enum.filter(collection, filter), mapper); - }, - - find: function (collection, if_none = null, fun) { - for (let elem of collection) { - if (fun(elem)) { - return elem; - } - } - - return if_none; - }, - - into: function (collection, list) { - return list.concat(collection); - }, - - map: function (collection, fun) { - let result = []; - - for (let elem of collection) { - result.push(fun(elem)); - } - - return result; - }, - - map_reduce: function (collection, acc, fun) { - let mapped = Object.freeze([]); - let the_acc = acc; - - for (var i = 0; i < this.count(collection); i++) { - let tuple = fun(collection[i], the_acc); - - the_acc = tuple.get(1); - mapped = Object.freeze(mapped.concat([tuple.get(0)])); - } - - return new Core.Tuple(mapped, the_acc); - }, - - member__qmark__: function (collection, value) { - return collection.includes(value); - }, - - reduce: function (collection, acc, fun) { - let the_acc = acc; - - for (var i = 0; i < this.count(collection); i++) { - let tuple = fun(collection[i], the_acc); - - the_acc = tuple.get(1); - } - - return the_acc; - }, - - take: function (collection, count) { - return collection.slice(0, count); - }, - - take_every: function (collection, nth) { - let result = []; - let index = 0; - - for (let elem of collection) { - if (index % nth === 0) { - result.push(elem); - } - } - - return Object.freeze(result); - }, - - take_while: function (collection, fun) { - let count = 0; - - for (let elem of collection) { - if (fun(elem)) { - count = count + 1; - } else { - break; - } - } - - return collection.slice(0, count); - }, - - to_list: function (collection) { - return collection; - } -}; - -let VirtualDOM = function (e) { - return e(); -}(function () { - var define, module, exports; - return function e(t, n, r) { - function s(o, u) { - if (!n[o]) { - if (!t[o]) { - var a = typeof require == "function" && require; - if (!u && a) return a(o, !0); - if (i) return i(o, !0); - var f = new Error("Cannot find module '" + o + "'"); - throw f.code = "MODULE_NOT_FOUND", f; - } - var l = n[o] = { - exports: {} - }; - t[o][0].call(l.exports, function (e) { - var n = t[o][1][e]; - return s(n ? n : e); - }, l, l.exports, e, t, n, r); - } - return n[o].exports; - } - var i = typeof require == "function" && require; - for (var o = 0; o < r.length; o++) s(r[o]); - return s; - }({ - 1: [function (require, module, exports) { - - var createElement = require("./vdom/create-element.js"); - - module.exports = createElement; - }, { "./vdom/create-element.js": 15 }], 2: [function (require, module, exports) { - var diff = require("./vtree/diff.js"); - - module.exports = diff; - }, { "./vtree/diff.js": 35 }], 3: [function (require, module, exports) { - var h = require("./virtual-hyperscript/index.js"); - - module.exports = h; - }, { "./virtual-hyperscript/index.js": 22 }], 4: [function (require, module, exports) { - var diff = require("./diff.js"); - var patch = require("./patch.js"); - var h = require("./h.js"); - var create = require("./create-element.js"); - var VNode = require('./vnode/vnode.js'); - var VText = require('./vnode/vtext.js'); - - module.exports = { - diff: diff, - patch: patch, - h: h, - create: create, - VNode: VNode, - VText: VText - }; - }, { "./create-element.js": 1, "./diff.js": 2, "./h.js": 3, "./patch.js": 13, "./vnode/vnode.js": 31, "./vnode/vtext.js": 33 }], 5: [function (require, module, exports) { - /*! - * Cross-Browser Split 1.1.1 - * Copyright 2007-2012 Steven Levithan - * Available under the MIT License - * ECMAScript compliant, uniform cross-browser split method - */ - - /** - * Splits a string into an array of strings using a regex or string separator. Matches of the - * separator are not included in the result array. However, if `separator` is a regex that contains - * capturing groups, backreferences are spliced into the result each time `separator` is matched. - * Fixes browser bugs compared to the native `String.prototype.split` and can be used reliably - * cross-browser. - * @param {String} str String to split. - * @param {RegExp|String} separator Regex or string to use for separating the string. - * @param {Number} [limit] Maximum number of items to include in the result array. - * @returns {Array} Array of substrings. - * @example - * - * // Basic use - * split('a b c d', ' '); - * // -> ['a', 'b', 'c', 'd'] - * - * // With limit - * split('a b c d', ' ', 2); - * // -> ['a', 'b'] - * - * // Backreferences in result array - * split('..word1 word2..', /([a-z]+)(\d+)/i); - * // -> ['..', 'word', '1', ' ', 'word', '2', '..'] - */ - module.exports = function split(undef) { - - var nativeSplit = String.prototype.split, - compliantExecNpcg = /()??/.exec("")[1] === undef, - - // NPCG: nonparticipating capturing group - self; - - self = function (str, separator, limit) { - // If `separator` is not a regex, use `nativeSplit` - if (Object.prototype.toString.call(separator) !== "[object RegExp]") { - return nativeSplit.call(str, separator, limit); - } - var output = [], - flags = (separator.ignoreCase ? "i" : "") + (separator.multiline ? "m" : "") + (separator.extended ? "x" : "") + ( // Proposed for ES6 - separator.sticky ? "y" : ""), - - // Firefox 3+ - lastLastIndex = 0, - - // Make `global` and avoid `lastIndex` issues by working with a copy - separator = new RegExp(separator.source, flags + "g"), - separator2, - match, - lastIndex, - lastLength; - str += ""; // Type-convert - if (!compliantExecNpcg) { - // Doesn't need flags gy, but they don't hurt - separator2 = new RegExp("^" + separator.source + "$(?!\\s)", flags); - } - /* Values for `limit`, per the spec: - * If undefined: 4294967295 // Math.pow(2, 32) - 1 - * If 0, Infinity, or NaN: 0 - * If positive number: limit = Math.floor(limit); if (limit > 4294967295) limit -= 4294967296; - * If negative number: 4294967296 - Math.floor(Math.abs(limit)) - * If other: Type-convert, then use the above rules - */ - limit = limit === undef ? -1 >>> 0 : // Math.pow(2, 32) - 1 - limit >>> 0; // ToUint32(limit) - while (match = separator.exec(str)) { - // `separator.lastIndex` is not reliable cross-browser - lastIndex = match.index + match[0].length; - if (lastIndex > lastLastIndex) { - output.push(str.slice(lastLastIndex, match.index)); - // Fix browsers whose `exec` methods don't consistently return `undefined` for - // nonparticipating capturing groups - if (!compliantExecNpcg && match.length > 1) { - match[0].replace(separator2, function () { - for (var i = 1; i < arguments.length - 2; i++) { - if (arguments[i] === undef) { - match[i] = undef; - } - } - }); - } - if (match.length > 1 && match.index < str.length) { - Array.prototype.push.apply(output, match.slice(1)); - } - lastLength = match[0].length; - lastLastIndex = lastIndex; - if (output.length >= limit) { - break; - } - } - if (separator.lastIndex === match.index) { - separator.lastIndex++; // Avoid an infinite loop - } - } - if (lastLastIndex === str.length) { - if (lastLength || !separator.test("")) { - output.push(""); - } - } else { - output.push(str.slice(lastLastIndex)); - } - return output.length > limit ? output.slice(0, limit) : output; - }; - - return self; - }(); - }, {}], 6: [function (require, module, exports) {}, {}], 7: [function (require, module, exports) { - 'use strict'; - - var OneVersionConstraint = require('individual/one-version'); - - var MY_VERSION = '7'; - OneVersionConstraint('ev-store', MY_VERSION); - - var hashKey = '__EV_STORE_KEY@' + MY_VERSION; - - module.exports = EvStore; - - function EvStore(elem) { - var hash = elem[hashKey]; - - if (!hash) { - hash = elem[hashKey] = {}; - } - - return hash; - } - }, { "individual/one-version": 9 }], 8: [function (require, module, exports) { - (function (global) { - 'use strict'; - - /*global window, global*/ - - var root = typeof window !== 'undefined' ? window : typeof global !== 'undefined' ? global : {}; - - module.exports = Individual; - - function Individual(key, value) { - if (key in root) { - return root[key]; - } - - root[key] = value; - - return value; - } - }).call(this, typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}); - }, {}], 9: [function (require, module, exports) { - 'use strict'; - - var Individual = require('./index.js'); - - module.exports = OneVersion; - - function OneVersion(moduleName, version, defaultValue) { - var key = '__INDIVIDUAL_ONE_VERSION_' + moduleName; - var enforceKey = key + '_ENFORCE_SINGLETON'; - - var versionValue = Individual(enforceKey, version); - - if (versionValue !== version) { - throw new Error('Can only have one copy of ' + moduleName + '.\n' + 'You already have version ' + versionValue + ' installed.\n' + 'This means you cannot install version ' + version); - } - - return Individual(key, defaultValue); - } - }, { "./index.js": 8 }], 10: [function (require, module, exports) { - (function (global) { - var topLevel = typeof global !== 'undefined' ? global : typeof window !== 'undefined' ? window : {}; - var minDoc = require('min-document'); - - if (typeof document !== 'undefined') { - module.exports = document; - } else { - var doccy = topLevel['__GLOBAL_DOCUMENT_CACHE@4']; - - if (!doccy) { - doccy = topLevel['__GLOBAL_DOCUMENT_CACHE@4'] = minDoc; - } - - module.exports = doccy; - } - }).call(this, typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}); - }, { "min-document": 6 }], 11: [function (require, module, exports) { - "use strict"; - - module.exports = function isObject(x) { - return typeof x === "object" && x !== null; - }; - }, {}], 12: [function (require, module, exports) { - var nativeIsArray = Array.isArray; - var toString = Object.prototype.toString; - - module.exports = nativeIsArray || isArray; - - function isArray(obj) { - return toString.call(obj) === "[object Array]"; - } - }, {}], 13: [function (require, module, exports) { - var patch = require("./vdom/patch.js"); - - module.exports = patch; - }, { "./vdom/patch.js": 18 }], 14: [function (require, module, exports) { - var isObject = require("is-object"); - var isHook = require("../vnode/is-vhook.js"); - - module.exports = applyProperties; - - function applyProperties(node, props, previous) { - for (var propName in props) { - var propValue = props[propName]; - - if (propValue === undefined) { - removeProperty(node, propName, propValue, previous); - } else if (isHook(propValue)) { - removeProperty(node, propName, propValue, previous); - if (propValue.hook) { - propValue.hook(node, propName, previous ? previous[propName] : undefined); - } - } else { - if (isObject(propValue)) { - patchObject(node, props, previous, propName, propValue); - } else { - node[propName] = propValue; - } - } - } - } - - function removeProperty(node, propName, propValue, previous) { - if (previous) { - var previousValue = previous[propName]; - - if (!isHook(previousValue)) { - if (propName === "attributes") { - for (var attrName in previousValue) { - node.removeAttribute(attrName); - } - } else if (propName === "style") { - for (var i in previousValue) { - node.style[i] = ""; - } - } else if (typeof previousValue === "string") { - node[propName] = ""; - } else { - node[propName] = null; - } - } else if (previousValue.unhook) { - previousValue.unhook(node, propName, propValue); - } - } - } - - function patchObject(node, props, previous, propName, propValue) { - var previousValue = previous ? previous[propName] : undefined; - - // Set attributes - if (propName === "attributes") { - for (var attrName in propValue) { - var attrValue = propValue[attrName]; - - if (attrValue === undefined) { - node.removeAttribute(attrName); - } else { - node.setAttribute(attrName, attrValue); - } - } - - return; - } - - if (previousValue && isObject(previousValue) && getPrototype(previousValue) !== getPrototype(propValue)) { - node[propName] = propValue; - return; - } - - if (!isObject(node[propName])) { - node[propName] = {}; - } - - var replacer = propName === "style" ? "" : undefined; - - for (var k in propValue) { - var value = propValue[k]; - node[propName][k] = value === undefined ? replacer : value; - } - } - - function getPrototype(value) { - if (Object.getPrototypeOf) { - return Object.getPrototypeOf(value); - } else if (value.__proto__) { - return value.__proto__; - } else if (value.constructor) { - return value.constructor.prototype; - } - } - }, { "../vnode/is-vhook.js": 26, "is-object": 11 }], 15: [function (require, module, exports) { - var document = require("global/document"); - - var applyProperties = require("./apply-properties"); - - var isVNode = require("../vnode/is-vnode.js"); - var isVText = require("../vnode/is-vtext.js"); - var isWidget = require("../vnode/is-widget.js"); - var handleThunk = require("../vnode/handle-thunk.js"); - - module.exports = createElement; - - function createElement(vnode, opts) { - var doc = opts ? opts.document || document : document; - var warn = opts ? opts.warn : null; - - vnode = handleThunk(vnode).a; - - if (isWidget(vnode)) { - return vnode.init(); - } else if (isVText(vnode)) { - return doc.createTextNode(vnode.text); - } else if (!isVNode(vnode)) { - if (warn) { - warn("Item is not a valid virtual dom node", vnode); - } - return null; - } - - var node = vnode.namespace === null ? doc.createElement(vnode.tagName) : doc.createElementNS(vnode.namespace, vnode.tagName); - - var props = vnode.properties; - applyProperties(node, props); - - var children = vnode.children; - - for (var i = 0; i < children.length; i++) { - var childNode = createElement(children[i], opts); - if (childNode) { - node.appendChild(childNode); - } - } - - return node; - } - }, { "../vnode/handle-thunk.js": 24, "../vnode/is-vnode.js": 27, "../vnode/is-vtext.js": 28, "../vnode/is-widget.js": 29, "./apply-properties": 14, "global/document": 10 }], 16: [function (require, module, exports) { - // Maps a virtual DOM tree onto a real DOM tree in an efficient manner. - // We don't want to read all of the DOM nodes in the tree so we use - // the in-order tree indexing to eliminate recursion down certain branches. - // We only recurse into a DOM node if we know that it contains a child of - // interest. - - var noChild = {}; - - module.exports = domIndex; - - function domIndex(rootNode, tree, indices, nodes) { - if (!indices || indices.length === 0) { - return {}; - } else { - indices.sort(ascending); - return recurse(rootNode, tree, indices, nodes, 0); - } - } - - function recurse(rootNode, tree, indices, nodes, rootIndex) { - nodes = nodes || {}; - - if (rootNode) { - if (indexInRange(indices, rootIndex, rootIndex)) { - nodes[rootIndex] = rootNode; - } - - var vChildren = tree.children; - - if (vChildren) { - - var childNodes = rootNode.childNodes; - - for (var i = 0; i < tree.children.length; i++) { - rootIndex += 1; - - var vChild = vChildren[i] || noChild; - var nextIndex = rootIndex + (vChild.count || 0); - - // skip recursion down the tree if there are no nodes down here - if (indexInRange(indices, rootIndex, nextIndex)) { - recurse(childNodes[i], vChild, indices, nodes, rootIndex); - } - - rootIndex = nextIndex; - } - } - } - - return nodes; - } - - // Binary search for an index in the interval [left, right] - function indexInRange(indices, left, right) { - if (indices.length === 0) { - return false; - } - - var minIndex = 0; - var maxIndex = indices.length - 1; - var currentIndex; - var currentItem; - - while (minIndex <= maxIndex) { - currentIndex = (maxIndex + minIndex) / 2 >> 0; - currentItem = indices[currentIndex]; - - if (minIndex === maxIndex) { - return currentItem >= left && currentItem <= right; - } else if (currentItem < left) { - minIndex = currentIndex + 1; - } else if (currentItem > right) { - maxIndex = currentIndex - 1; - } else { - return true; - } - } - - return false; - } - - function ascending(a, b) { - return a > b ? 1 : -1; - } - }, {}], 17: [function (require, module, exports) { - var applyProperties = require("./apply-properties"); - - var isWidget = require("../vnode/is-widget.js"); - var VPatch = require("../vnode/vpatch.js"); - - var updateWidget = require("./update-widget"); - - module.exports = applyPatch; - - function applyPatch(vpatch, domNode, renderOptions) { - var type = vpatch.type; - var vNode = vpatch.vNode; - var patch = vpatch.patch; - - switch (type) { - case VPatch.REMOVE: - return removeNode(domNode, vNode); - case VPatch.INSERT: - return insertNode(domNode, patch, renderOptions); - case VPatch.VTEXT: - return stringPatch(domNode, vNode, patch, renderOptions); - case VPatch.WIDGET: - return widgetPatch(domNode, vNode, patch, renderOptions); - case VPatch.VNODE: - return vNodePatch(domNode, vNode, patch, renderOptions); - case VPatch.ORDER: - reorderChildren(domNode, patch); - return domNode; - case VPatch.PROPS: - applyProperties(domNode, patch, vNode.properties); - return domNode; - case VPatch.THUNK: - return replaceRoot(domNode, renderOptions.patch(domNode, patch, renderOptions)); - default: - return domNode; - } - } - - function removeNode(domNode, vNode) { - var parentNode = domNode.parentNode; - - if (parentNode) { - parentNode.removeChild(domNode); - } - - destroyWidget(domNode, vNode); - - return null; - } - - function insertNode(parentNode, vNode, renderOptions) { - var newNode = renderOptions.render(vNode, renderOptions); - - if (parentNode) { - parentNode.appendChild(newNode); - } - - return parentNode; - } - - function stringPatch(domNode, leftVNode, vText, renderOptions) { - var newNode; - - if (domNode.nodeType === 3) { - domNode.replaceData(0, domNode.length, vText.text); - newNode = domNode; - } else { - var parentNode = domNode.parentNode; - newNode = renderOptions.render(vText, renderOptions); - - if (parentNode && newNode !== domNode) { - parentNode.replaceChild(newNode, domNode); - } - } - - return newNode; - } - - function widgetPatch(domNode, leftVNode, widget, renderOptions) { - var updating = updateWidget(leftVNode, widget); - var newNode; - - if (updating) { - newNode = widget.update(leftVNode, domNode) || domNode; - } else { - newNode = renderOptions.render(widget, renderOptions); - } - - var parentNode = domNode.parentNode; - - if (parentNode && newNode !== domNode) { - parentNode.replaceChild(newNode, domNode); - } - - if (!updating) { - destroyWidget(domNode, leftVNode); - } - - return newNode; - } - - function vNodePatch(domNode, leftVNode, vNode, renderOptions) { - var parentNode = domNode.parentNode; - var newNode = renderOptions.render(vNode, renderOptions); - - if (parentNode && newNode !== domNode) { - parentNode.replaceChild(newNode, domNode); - } - - return newNode; - } - - function destroyWidget(domNode, w) { - if (typeof w.destroy === "function" && isWidget(w)) { - w.destroy(domNode); - } - } - - function reorderChildren(domNode, moves) { - var childNodes = domNode.childNodes; - var keyMap = {}; - var node; - var remove; - var insert; - - for (var i = 0; i < moves.removes.length; i++) { - remove = moves.removes[i]; - node = childNodes[remove.from]; - if (remove.key) { - keyMap[remove.key] = node; - } - domNode.removeChild(node); - } - - var length = childNodes.length; - for (var j = 0; j < moves.inserts.length; j++) { - insert = moves.inserts[j]; - node = keyMap[insert.key]; - // this is the weirdest bug i've ever seen in webkit - domNode.insertBefore(node, insert.to >= length++ ? null : childNodes[insert.to]); - } - } - - function replaceRoot(oldRoot, newRoot) { - if (oldRoot && newRoot && oldRoot !== newRoot && oldRoot.parentNode) { - oldRoot.parentNode.replaceChild(newRoot, oldRoot); - } - - return newRoot; - } - }, { "../vnode/is-widget.js": 29, "../vnode/vpatch.js": 32, "./apply-properties": 14, "./update-widget": 19 }], 18: [function (require, module, exports) { - var document = require("global/document"); - var isArray = require("x-is-array"); - - var render = require("./create-element"); - var domIndex = require("./dom-index"); - var patchOp = require("./patch-op"); - module.exports = patch; - - function patch(rootNode, patches, renderOptions) { - renderOptions = renderOptions || {}; - renderOptions.patch = renderOptions.patch && renderOptions.patch !== patch ? renderOptions.patch : patchRecursive; - renderOptions.render = renderOptions.render || render; - - return renderOptions.patch(rootNode, patches, renderOptions); - } - - function patchRecursive(rootNode, patches, renderOptions) { - var indices = patchIndices(patches); - - if (indices.length === 0) { - return rootNode; - } - - var index = domIndex(rootNode, patches.a, indices); - var ownerDocument = rootNode.ownerDocument; - - if (!renderOptions.document && ownerDocument !== document) { - renderOptions.document = ownerDocument; - } - - for (var i = 0; i < indices.length; i++) { - var nodeIndex = indices[i]; - rootNode = applyPatch(rootNode, index[nodeIndex], patches[nodeIndex], renderOptions); - } - - return rootNode; - } - - function applyPatch(rootNode, domNode, patchList, renderOptions) { - if (!domNode) { - return rootNode; - } - - var newNode; - - if (isArray(patchList)) { - for (var i = 0; i < patchList.length; i++) { - newNode = patchOp(patchList[i], domNode, renderOptions); - - if (domNode === rootNode) { - rootNode = newNode; - } - } - } else { - newNode = patchOp(patchList, domNode, renderOptions); - - if (domNode === rootNode) { - rootNode = newNode; - } - } - - return rootNode; - } - - function patchIndices(patches) { - var indices = []; - - for (var key in patches) { - if (key !== "a") { - indices.push(Number(key)); - } - } - - return indices; - } - }, { "./create-element": 15, "./dom-index": 16, "./patch-op": 17, "global/document": 10, "x-is-array": 12 }], 19: [function (require, module, exports) { - var isWidget = require("../vnode/is-widget.js"); - - module.exports = updateWidget; - - function updateWidget(a, b) { - if (isWidget(a) && isWidget(b)) { - if ("name" in a && "name" in b) { - return a.id === b.id; - } else { - return a.init === b.init; - } - } - - return false; - } - }, { "../vnode/is-widget.js": 29 }], 20: [function (require, module, exports) { - 'use strict'; - - var EvStore = require('ev-store'); - - module.exports = EvHook; - - function EvHook(value) { - if (!(this instanceof EvHook)) { - return new EvHook(value); - } - - this.value = value; - } - - EvHook.prototype.hook = function (node, propertyName) { - var es = EvStore(node); - var propName = propertyName.substr(3); - - es[propName] = this.value; - }; - - EvHook.prototype.unhook = function (node, propertyName) { - var es = EvStore(node); - var propName = propertyName.substr(3); - - es[propName] = undefined; - }; - }, { "ev-store": 7 }], 21: [function (require, module, exports) { - 'use strict'; - - module.exports = SoftSetHook; - - function SoftSetHook(value) { - if (!(this instanceof SoftSetHook)) { - return new SoftSetHook(value); - } - - this.value = value; - } - - SoftSetHook.prototype.hook = function (node, propertyName) { - if (node[propertyName] !== this.value) { - node[propertyName] = this.value; - } - }; - }, {}], 22: [function (require, module, exports) { - 'use strict'; - - var isArray = require('x-is-array'); - - var VNode = require('../vnode/vnode.js'); - var VText = require('../vnode/vtext.js'); - var isVNode = require('../vnode/is-vnode'); - var isVText = require('../vnode/is-vtext'); - var isWidget = require('../vnode/is-widget'); - var isHook = require('../vnode/is-vhook'); - var isVThunk = require('../vnode/is-thunk'); - - var parseTag = require('./parse-tag.js'); - var softSetHook = require('./hooks/soft-set-hook.js'); - var evHook = require('./hooks/ev-hook.js'); - - module.exports = h; - - function h(tagName, properties, children) { - var childNodes = []; - var tag, props, key, namespace; - - if (!children && isChildren(properties)) { - children = properties; - props = {}; - } - - props = props || properties || {}; - tag = parseTag(tagName, props); - - // support keys - if (props.hasOwnProperty('key')) { - key = props.key; - props.key = undefined; - } - - // support namespace - if (props.hasOwnProperty('namespace')) { - namespace = props.namespace; - props.namespace = undefined; - } - - // fix cursor bug - if (tag === 'INPUT' && !namespace && props.hasOwnProperty('value') && props.value !== undefined && !isHook(props.value)) { - props.value = softSetHook(props.value); - } - - transformProperties(props); - - if (children !== undefined && children !== null) { - addChild(children, childNodes, tag, props); - } - - return new VNode(tag, props, childNodes, key, namespace); - } - - function addChild(c, childNodes, tag, props) { - if (typeof c === 'string') { - childNodes.push(new VText(c)); - } else if (typeof c === 'number') { - childNodes.push(new VText(String(c))); - } else if (isChild(c)) { - childNodes.push(c); - } else if (isArray(c)) { - for (var i = 0; i < c.length; i++) { - addChild(c[i], childNodes, tag, props); - } - } else if (c === null || c === undefined) { - return; - } else { - throw UnexpectedVirtualElement({ - foreignObject: c, - parentVnode: { - tagName: tag, - properties: props - } - }); - } - } - - function transformProperties(props) { - for (var propName in props) { - if (props.hasOwnProperty(propName)) { - var value = props[propName]; - - if (isHook(value)) { - continue; - } - - if (propName.substr(0, 3) === 'ev-') { - // add ev-foo support - props[propName] = evHook(value); - } - } - } - } - - function isChild(x) { - return isVNode(x) || isVText(x) || isWidget(x) || isVThunk(x); - } - - function isChildren(x) { - return typeof x === 'string' || isArray(x) || isChild(x); - } - - function UnexpectedVirtualElement(data) { - var err = new Error(); - - err.type = 'virtual-hyperscript.unexpected.virtual-element'; - err.message = 'Unexpected virtual child passed to h().\n' + 'Expected a VNode / Vthunk / VWidget / string but:\n' + 'got:\n' + errorString(data.foreignObject) + '.\n' + 'The parent vnode is:\n' + errorString(data.parentVnode); - '\n' + 'Suggested fix: change your `h(..., [ ... ])` callsite.'; - err.foreignObject = data.foreignObject; - err.parentVnode = data.parentVnode; - - return err; - } - - function errorString(obj) { - try { - return JSON.stringify(obj, null, ' '); - } catch (e) { - return String(obj); - } - } - }, { "../vnode/is-thunk": 25, "../vnode/is-vhook": 26, "../vnode/is-vnode": 27, "../vnode/is-vtext": 28, "../vnode/is-widget": 29, "../vnode/vnode.js": 31, "../vnode/vtext.js": 33, "./hooks/ev-hook.js": 20, "./hooks/soft-set-hook.js": 21, "./parse-tag.js": 23, "x-is-array": 12 }], 23: [function (require, module, exports) { - 'use strict'; - - var split = require('browser-split'); - - var classIdSplit = /([\.#]?[a-zA-Z0-9\u007F-\uFFFF_:-]+)/; - var notClassId = /^\.|#/; - - module.exports = parseTag; - - function parseTag(tag, props) { - if (!tag) { - return 'DIV'; - } - - var noId = !props.hasOwnProperty('id'); - - var tagParts = split(tag, classIdSplit); - var tagName = null; - - if (notClassId.test(tagParts[1])) { - tagName = 'DIV'; - } - - var classes, part, type, i; - - for (i = 0; i < tagParts.length; i++) { - part = tagParts[i]; - - if (!part) { - continue; - } - - type = part.charAt(0); - - if (!tagName) { - tagName = part; - } else if (type === '.') { - classes = classes || []; - classes.push(part.substring(1, part.length)); - } else if (type === '#' && noId) { - props.id = part.substring(1, part.length); - } - } - - if (classes) { - if (props.className) { - classes.push(props.className); - } - - props.className = classes.join(' '); - } - - return props.namespace ? tagName : tagName.toUpperCase(); - } - }, { "browser-split": 5 }], 24: [function (require, module, exports) { - var isVNode = require("./is-vnode"); - var isVText = require("./is-vtext"); - var isWidget = require("./is-widget"); - var isThunk = require("./is-thunk"); - - module.exports = handleThunk; - - function handleThunk(a, b) { - var renderedA = a; - var renderedB = b; - - if (isThunk(b)) { - renderedB = renderThunk(b, a); - } - - if (isThunk(a)) { - renderedA = renderThunk(a, null); - } - - return { - a: renderedA, - b: renderedB - }; - } - - function renderThunk(thunk, previous) { - var renderedThunk = thunk.vnode; - - if (!renderedThunk) { - renderedThunk = thunk.vnode = thunk.render(previous); - } - - if (!(isVNode(renderedThunk) || isVText(renderedThunk) || isWidget(renderedThunk))) { - throw new Error("thunk did not return a valid node"); - } - - return renderedThunk; - } - }, { "./is-thunk": 25, "./is-vnode": 27, "./is-vtext": 28, "./is-widget": 29 }], 25: [function (require, module, exports) { - module.exports = isThunk; - - function isThunk(t) { - return t && t.type === "Thunk"; - } - }, {}], 26: [function (require, module, exports) { - module.exports = isHook; - - function isHook(hook) { - return hook && (typeof hook.hook === "function" && !hook.hasOwnProperty("hook") || typeof hook.unhook === "function" && !hook.hasOwnProperty("unhook")); - } - }, {}], 27: [function (require, module, exports) { - var version = require("./version"); - - module.exports = isVirtualNode; - - function isVirtualNode(x) { - return x && x.type === "VirtualNode" && x.version === version; - } - }, { "./version": 30 }], 28: [function (require, module, exports) { - var version = require("./version"); - - module.exports = isVirtualText; - - function isVirtualText(x) { - return x && x.type === "VirtualText" && x.version === version; - } - }, { "./version": 30 }], 29: [function (require, module, exports) { - module.exports = isWidget; - - function isWidget(w) { - return w && w.type === "Widget"; - } - }, {}], 30: [function (require, module, exports) { - module.exports = "2"; - }, {}], 31: [function (require, module, exports) { - var version = require("./version"); - var isVNode = require("./is-vnode"); - var isWidget = require("./is-widget"); - var isThunk = require("./is-thunk"); - var isVHook = require("./is-vhook"); - - module.exports = VirtualNode; - - var noProperties = {}; - var noChildren = []; - - function VirtualNode(tagName, properties, children, key, namespace) { - this.tagName = tagName; - this.properties = properties || noProperties; - this.children = children || noChildren; - this.key = key != null ? String(key) : undefined; - this.namespace = typeof namespace === "string" ? namespace : null; - - var count = children && children.length || 0; - var descendants = 0; - var hasWidgets = false; - var hasThunks = false; - var descendantHooks = false; - var hooks; - - for (var propName in properties) { - if (properties.hasOwnProperty(propName)) { - var property = properties[propName]; - if (isVHook(property) && property.unhook) { - if (!hooks) { - hooks = {}; - } - - hooks[propName] = property; - } - } - } - - for (var i = 0; i < count; i++) { - var child = children[i]; - if (isVNode(child)) { - descendants += child.count || 0; - - if (!hasWidgets && child.hasWidgets) { - hasWidgets = true; - } - - if (!hasThunks && child.hasThunks) { - hasThunks = true; - } - - if (!descendantHooks && (child.hooks || child.descendantHooks)) { - descendantHooks = true; - } - } else if (!hasWidgets && isWidget(child)) { - if (typeof child.destroy === "function") { - hasWidgets = true; - } - } else if (!hasThunks && isThunk(child)) { - hasThunks = true; - } - } - - this.count = count + descendants; - this.hasWidgets = hasWidgets; - this.hasThunks = hasThunks; - this.hooks = hooks; - this.descendantHooks = descendantHooks; - } - - VirtualNode.prototype.version = version; - VirtualNode.prototype.type = "VirtualNode"; - }, { "./is-thunk": 25, "./is-vhook": 26, "./is-vnode": 27, "./is-widget": 29, "./version": 30 }], 32: [function (require, module, exports) { - var version = require("./version"); - - VirtualPatch.NONE = 0; - VirtualPatch.VTEXT = 1; - VirtualPatch.VNODE = 2; - VirtualPatch.WIDGET = 3; - VirtualPatch.PROPS = 4; - VirtualPatch.ORDER = 5; - VirtualPatch.INSERT = 6; - VirtualPatch.REMOVE = 7; - VirtualPatch.THUNK = 8; - - module.exports = VirtualPatch; - - function VirtualPatch(type, vNode, patch) { - this.type = Number(type); - this.vNode = vNode; - this.patch = patch; - } - - VirtualPatch.prototype.version = version; - VirtualPatch.prototype.type = "VirtualPatch"; - }, { "./version": 30 }], 33: [function (require, module, exports) { - var version = require("./version"); - - module.exports = VirtualText; - - function VirtualText(text) { - this.text = String(text); - } - - VirtualText.prototype.version = version; - VirtualText.prototype.type = "VirtualText"; - }, { "./version": 30 }], 34: [function (require, module, exports) { - var isObject = require("is-object"); - var isHook = require("../vnode/is-vhook"); - - module.exports = diffProps; - - function diffProps(a, b) { - var diff; - - for (var aKey in a) { - if (!(aKey in b)) { - diff = diff || {}; - diff[aKey] = undefined; - } - - var aValue = a[aKey]; - var bValue = b[aKey]; - - if (aValue === bValue) { - continue; - } else if (isObject(aValue) && isObject(bValue)) { - if (getPrototype(bValue) !== getPrototype(aValue)) { - diff = diff || {}; - diff[aKey] = bValue; - } else if (isHook(bValue)) { - diff = diff || {}; - diff[aKey] = bValue; - } else { - var objectDiff = diffProps(aValue, bValue); - if (objectDiff) { - diff = diff || {}; - diff[aKey] = objectDiff; - } - } - } else { - diff = diff || {}; - diff[aKey] = bValue; - } - } - - for (var bKey in b) { - if (!(bKey in a)) { - diff = diff || {}; - diff[bKey] = b[bKey]; - } - } - - return diff; - } - - function getPrototype(value) { - if (Object.getPrototypeOf) { - return Object.getPrototypeOf(value); - } else if (value.__proto__) { - return value.__proto__; - } else if (value.constructor) { - return value.constructor.prototype; - } - } - }, { "../vnode/is-vhook": 26, "is-object": 11 }], 35: [function (require, module, exports) { - var isArray = require("x-is-array"); - - var VPatch = require("../vnode/vpatch"); - var isVNode = require("../vnode/is-vnode"); - var isVText = require("../vnode/is-vtext"); - var isWidget = require("../vnode/is-widget"); - var isThunk = require("../vnode/is-thunk"); - var handleThunk = require("../vnode/handle-thunk"); - - var diffProps = require("./diff-props"); - - module.exports = diff; - - function diff(a, b) { - var patch = { a: a }; - walk(a, b, patch, 0); - return patch; - } - - function walk(a, b, patch, index) { - if (a === b) { - return; - } - - var apply = patch[index]; - var applyClear = false; - - if (isThunk(a) || isThunk(b)) { - thunks(a, b, patch, index); - } else if (b == null) { - - // If a is a widget we will add a remove patch for it - // Otherwise any child widgets/hooks must be destroyed. - // This prevents adding two remove patches for a widget. - if (!isWidget(a)) { - clearState(a, patch, index); - apply = patch[index]; - } - - apply = appendPatch(apply, new VPatch(VPatch.REMOVE, a, b)); - } else if (isVNode(b)) { - if (isVNode(a)) { - if (a.tagName === b.tagName && a.namespace === b.namespace && a.key === b.key) { - var propsPatch = diffProps(a.properties, b.properties); - if (propsPatch) { - apply = appendPatch(apply, new VPatch(VPatch.PROPS, a, propsPatch)); - } - apply = diffChildren(a, b, patch, apply, index); - } else { - apply = appendPatch(apply, new VPatch(VPatch.VNODE, a, b)); - applyClear = true; - } - } else { - apply = appendPatch(apply, new VPatch(VPatch.VNODE, a, b)); - applyClear = true; - } - } else if (isVText(b)) { - if (!isVText(a)) { - apply = appendPatch(apply, new VPatch(VPatch.VTEXT, a, b)); - applyClear = true; - } else if (a.text !== b.text) { - apply = appendPatch(apply, new VPatch(VPatch.VTEXT, a, b)); - } - } else if (isWidget(b)) { - if (!isWidget(a)) { - applyClear = true; - } - - apply = appendPatch(apply, new VPatch(VPatch.WIDGET, a, b)); - } - - if (apply) { - patch[index] = apply; - } - - if (applyClear) { - clearState(a, patch, index); - } - } - - function diffChildren(a, b, patch, apply, index) { - var aChildren = a.children; - var orderedSet = reorder(aChildren, b.children); - var bChildren = orderedSet.children; - - var aLen = aChildren.length; - var bLen = bChildren.length; - var len = aLen > bLen ? aLen : bLen; - - for (var i = 0; i < len; i++) { - var leftNode = aChildren[i]; - var rightNode = bChildren[i]; - index += 1; - - if (!leftNode) { - if (rightNode) { - // Excess nodes in b need to be added - apply = appendPatch(apply, new VPatch(VPatch.INSERT, null, rightNode)); - } - } else { - walk(leftNode, rightNode, patch, index); - } - - if (isVNode(leftNode) && leftNode.count) { - index += leftNode.count; - } - } - - if (orderedSet.moves) { - // Reorder nodes last - apply = appendPatch(apply, new VPatch(VPatch.ORDER, a, orderedSet.moves)); - } - - return apply; - } - - function clearState(vNode, patch, index) { - // TODO: Make this a single walk, not two - unhook(vNode, patch, index); - destroyWidgets(vNode, patch, index); - } - - // Patch records for all destroyed widgets must be added because we need - // a DOM node reference for the destroy function - function destroyWidgets(vNode, patch, index) { - if (isWidget(vNode)) { - if (typeof vNode.destroy === "function") { - patch[index] = appendPatch(patch[index], new VPatch(VPatch.REMOVE, vNode, null)); - } - } else if (isVNode(vNode) && (vNode.hasWidgets || vNode.hasThunks)) { - var children = vNode.children; - var len = children.length; - for (var i = 0; i < len; i++) { - var child = children[i]; - index += 1; - - destroyWidgets(child, patch, index); - - if (isVNode(child) && child.count) { - index += child.count; - } - } - } else if (isThunk(vNode)) { - thunks(vNode, null, patch, index); - } - } - - // Create a sub-patch for thunks - function thunks(a, b, patch, index) { - var nodes = handleThunk(a, b); - var thunkPatch = diff(nodes.a, nodes.b); - if (hasPatches(thunkPatch)) { - patch[index] = new VPatch(VPatch.THUNK, null, thunkPatch); - } - } - - function hasPatches(patch) { - for (var index in patch) { - if (index !== "a") { - return true; - } - } - - return false; - } - - // Execute hooks when two nodes are identical - function unhook(vNode, patch, index) { - if (isVNode(vNode)) { - if (vNode.hooks) { - patch[index] = appendPatch(patch[index], new VPatch(VPatch.PROPS, vNode, undefinedKeys(vNode.hooks))); - } - - if (vNode.descendantHooks || vNode.hasThunks) { - var children = vNode.children; - var len = children.length; - for (var i = 0; i < len; i++) { - var child = children[i]; - index += 1; - - unhook(child, patch, index); - - if (isVNode(child) && child.count) { - index += child.count; - } - } - } - } else if (isThunk(vNode)) { - thunks(vNode, null, patch, index); - } - } - - function undefinedKeys(obj) { - var result = {}; - - for (var key in obj) { - result[key] = undefined; - } - - return result; - } - - // List diff, naive left to right reordering - function reorder(aChildren, bChildren) { - // O(M) time, O(M) memory - var bChildIndex = keyIndex(bChildren); - var bKeys = bChildIndex.keys; - var bFree = bChildIndex.free; - - if (bFree.length === bChildren.length) { - return { - children: bChildren, - moves: null - }; - } - - // O(N) time, O(N) memory - var aChildIndex = keyIndex(aChildren); - var aKeys = aChildIndex.keys; - var aFree = aChildIndex.free; - - if (aFree.length === aChildren.length) { - return { - children: bChildren, - moves: null - }; - } - - // O(MAX(N, M)) memory - var newChildren = []; - - var freeIndex = 0; - var freeCount = bFree.length; - var deletedItems = 0; - - // Iterate through a and match a node in b - // O(N) time, - for (var i = 0; i < aChildren.length; i++) { - var aItem = aChildren[i]; - var itemIndex; - - if (aItem.key) { - if (bKeys.hasOwnProperty(aItem.key)) { - // Match up the old keys - itemIndex = bKeys[aItem.key]; - newChildren.push(bChildren[itemIndex]); - } else { - // Remove old keyed items - itemIndex = i - deletedItems++; - newChildren.push(null); - } - } else { - // Match the item in a with the next free item in b - if (freeIndex < freeCount) { - itemIndex = bFree[freeIndex++]; - newChildren.push(bChildren[itemIndex]); - } else { - // There are no free items in b to match with - // the free items in a, so the extra free nodes - // are deleted. - itemIndex = i - deletedItems++; - newChildren.push(null); - } - } - } - - var lastFreeIndex = freeIndex >= bFree.length ? bChildren.length : bFree[freeIndex]; - - // Iterate through b and append any new keys - // O(M) time - for (var j = 0; j < bChildren.length; j++) { - var newItem = bChildren[j]; - - if (newItem.key) { - if (!aKeys.hasOwnProperty(newItem.key)) { - // Add any new keyed items - // We are adding new items to the end and then sorting them - // in place. In future we should insert new items in place. - newChildren.push(newItem); - } - } else if (j >= lastFreeIndex) { - // Add any leftover non-keyed items - newChildren.push(newItem); - } - } - - var simulate = newChildren.slice(); - var simulateIndex = 0; - var removes = []; - var inserts = []; - var simulateItem; - - for (var k = 0; k < bChildren.length;) { - var wantedItem = bChildren[k]; - simulateItem = simulate[simulateIndex]; - - // remove items - while (simulateItem === null && simulate.length) { - removes.push(remove(simulate, simulateIndex, null)); - simulateItem = simulate[simulateIndex]; - } - - if (!simulateItem || simulateItem.key !== wantedItem.key) { - // if we need a key in this position... - if (wantedItem.key) { - if (simulateItem && simulateItem.key) { - // if an insert doesn't put this key in place, it needs to move - if (bKeys[simulateItem.key] !== k + 1) { - removes.push(remove(simulate, simulateIndex, simulateItem.key)); - simulateItem = simulate[simulateIndex]; - // if the remove didn't put the wanted item in place, we need to insert it - if (!simulateItem || simulateItem.key !== wantedItem.key) { - inserts.push({ key: wantedItem.key, to: k }); - } - // items are matching, so skip ahead - else { - simulateIndex++; - } - } else { - inserts.push({ key: wantedItem.key, to: k }); - } - } else { - inserts.push({ key: wantedItem.key, to: k }); - } - k++; - } - // a key in simulate has no matching wanted key, remove it - else if (simulateItem && simulateItem.key) { - removes.push(remove(simulate, simulateIndex, simulateItem.key)); - } - } else { - simulateIndex++; - k++; - } - } - - // remove all the remaining nodes from simulate - while (simulateIndex < simulate.length) { - simulateItem = simulate[simulateIndex]; - removes.push(remove(simulate, simulateIndex, simulateItem && simulateItem.key)); - } - - // If the only moves we have are deletes then we can just - // let the delete patch remove these items. - if (removes.length === deletedItems && !inserts.length) { - return { - children: newChildren, - moves: null - }; - } - - return { - children: newChildren, - moves: { - removes: removes, - inserts: inserts - } - }; - } - - function remove(arr, index, key) { - arr.splice(index, 1); - - return { - from: index, - key: key - }; - } - - function keyIndex(children) { - var keys = {}; - var free = []; - var length = children.length; - - for (var i = 0; i < length; i++) { - var child = children[i]; - - if (child.key) { - keys[child.key] = i; - } else { - free.push(i); - } - } - - return { - keys: keys, // A hash of key name to index - free: free // An array of unkeyed item indices - }; - } - - function appendPatch(apply, patch) { - if (apply) { - if (isArray(apply)) { - apply.push(patch); - } else { - apply = [apply, patch]; - } - - return apply; - } else { - return patch; - } - } - }, { "../vnode/handle-thunk": 24, "../vnode/is-thunk": 25, "../vnode/is-vnode": 27, "../vnode/is-vtext": 28, "../vnode/is-widget": 29, "../vnode/vpatch": 32, "./diff-props": 34, "x-is-array": 12 }] }, {}, [4])(4); -}); - -var elixir = { - Core, - Enum, - VirtualDOM -}; - -export default elixir; -//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiRWxpeGlyLmpzIiwic291cmNlcyI6WyIuLi9zcmMvZWxpeGlyc2NyaXB0L2xpYi9jb3JlL3Byb2Nlc3Nlcy9tYWlsYm94LmpzIiwiLi4vc3JjL2VsaXhpcnNjcmlwdC9saWIvY29yZS9wcm9jZXNzZXMvc3RhdGVzLmpzIiwiLi4vc3JjL2VsaXhpcnNjcmlwdC9saWIvY29yZS9wcm9jZXNzZXMvcHJvY2Vzcy5qcyIsIi4uL3NyYy9lbGl4aXJzY3JpcHQvbGliL2NvcmUvcHJpbWl0aXZlcy5qcyIsIi4uL3NyYy9lbGl4aXJzY3JpcHQvbGliL2NvcmUvcHJvY2Vzc2VzL3Byb2Nlc3Nfc3lzdGVtLmpzIiwiLi4vc3JjL2VsaXhpcnNjcmlwdC9saWIvY29yZS9iaXRfc3RyaW5nLmpzIiwiLi4vc3JjL2VsaXhpcnNjcmlwdC9saWIvY29yZS9wYXR0ZXJucy90eXBlcy5qcyIsIi4uL3NyYy9lbGl4aXJzY3JpcHQvbGliL2NvcmUvcGF0dGVybnMvY2hlY2tzLmpzIiwiLi4vc3JjL2VsaXhpcnNjcmlwdC9saWIvY29yZS9wYXR0ZXJucy9yZXNvbHZlcnMuanMiLCIuLi9zcmMvZWxpeGlyc2NyaXB0L2xpYi9jb3JlL3BhdHRlcm5zL21hdGNoLmpzIiwiLi4vc3JjL2VsaXhpcnNjcmlwdC9saWIvY29yZS9wYXR0ZXJucy9kZWZtYXRjaC5qcyIsIi4uL3NyYy9lbGl4aXJzY3JpcHQvbGliL2NvcmUvcGF0dGVybnMuanMiLCIuLi9zcmMvZWxpeGlyc2NyaXB0L2xpYi9jb3JlL3Byb3RvY29sLmpzIiwiLi4vc3JjL2VsaXhpcnNjcmlwdC9saWIvY29yZS9mdW5jdGlvbnMuanMiLCIuLi9zcmMvZWxpeGlyc2NyaXB0L2xpYi9jb3JlL3NwZWNpYWxfZm9ybXMuanMiLCIuLi9zcmMvZWxpeGlyc2NyaXB0L2xpYi9jb3JlLmpzIiwiLi4vc3JjL2VsaXhpcnNjcmlwdC9saWIvZW51bS5qcyIsIi4uL3NyYy9lbGl4aXJzY3JpcHQvbGliL3ZpcnR1YWwtZG9tLmpzIiwiLi4vc3JjL2VsaXhpcnNjcmlwdC9lbGl4aXIuanMiXSwic291cmNlc0NvbnRlbnQiOlsiXCJ1c2Ugc3RyaWN0XCI7XG5cbmNsYXNzIE1haWxib3gge1xuXG4gIGNvbnN0cnVjdG9yKCkge1xuICAgIHRoaXMubWVzc2FnZXMgPSBbXTtcbiAgfVxuXG4gIGRlbGl2ZXIobWVzc2FnZSkge1xuICAgIHRoaXMubWVzc2FnZXMucHVzaChtZXNzYWdlKTtcbiAgICByZXR1cm4gbWVzc2FnZTtcbiAgfVxuXG4gIGdldCgpIHtcbiAgICByZXR1cm4gdGhpcy5tZXNzYWdlcztcbiAgfVxuXG4gIGlzRW1wdHkoKSB7XG4gICAgcmV0dXJuIHRoaXMubWVzc2FnZXMubGVuZ3RoID09PSAwO1xuICB9XG5cbiAgcmVtb3ZlQXQoaW5kZXgpIHtcbiAgICB0aGlzLm1lc3NhZ2VzLnNwbGljZShpbmRleCwgMSk7XG4gIH1cbn1cblxuZXhwb3J0IGRlZmF1bHQgTWFpbGJveDtcbi8vIyBzb3VyY2VNYXBwaW5nVVJMPWRhdGE6YXBwbGljYXRpb24vanNvbjtiYXNlNjQsZXlKMlpYSnphVzl1SWpvekxDSnpiM1Z5WTJWeklqcGJJbXhwWWk5amIzSmxMM0J5YjJObGMzTmxjeTl0WVdsc1ltOTRMbXB6SWwwc0ltNWhiV1Z6SWpwYlhTd2liV0Z3Y0dsdVozTWlPaUpCUVVGQk96dEJRVWxCTEUxQlFVMHNUMEZCVGl4RFFVRmhPenRCUVVkWUxHZENRVUZoTzBGQlExZ3NVMEZCU3l4UlFVRk1MRWRCUVdkQ0xFVkJRV2hDTEVOQlJGYzdSMEZCWWpzN1FVRkpRU3hWUVVGUkxFOUJRVklzUlVGQmNVSTdRVUZEYmtJc1UwRkJTeXhSUVVGTUxFTkJRV01zU1VGQlpDeERRVUZ0UWl4UFFVRnVRaXhGUVVSdFFqdEJRVVZ1UWl4WFFVRlBMRTlCUVZBc1EwRkdiVUk3UjBGQmNrSTdPMEZCUzBFc1VVRkJTenRCUVVOSUxGZEJRVThzUzBGQlN5eFJRVUZNTEVOQlJFbzdSMEZCVERzN1FVRkpRU3haUVVGVE8wRkJRMUFzVjBGQlR5eExRVUZMTEZGQlFVd3NRMEZCWXl4TlFVRmtMRXRCUVhsQ0xFTkJRWHBDTEVOQlJFRTdSMEZCVkRzN1FVRkpRU3hYUVVGVExFdEJRVlFzUlVGQlpUdEJRVU5pTEZOQlFVc3NVVUZCVEN4RFFVRmpMRTFCUVdRc1EwRkJjVUlzUzBGQmNrSXNSVUZCTkVJc1EwRkJOVUlzUlVGRVlUdEhRVUZtTzBOQmNFSkdPenRCUVhsQ1FTeGxRVUZsTEU5QlFXWWlMQ0ptYVd4bElqb2liR2xpTDJOdmNtVXZjSEp2WTJWemMyVnpMMjFoYVd4aWIzZ3Vhbk1pTENKemIzVnlZMlZ6UTI5dWRHVnVkQ0k2V3lKY0luVnpaU0J6ZEhKcFkzUmNJanRjYmx4dUx5b2dRR1pzYjNjZ0tpOWNibHh1WTJ4aGMzTWdUV0ZwYkdKdmVIdGNiaUFnYldWemMyRm5aWE02SUVGeWNtRjVQR0Z1ZVQ1Y2JseHVJQ0JqYjI1emRISjFZM1J2Y2lncGUxeHVJQ0FnSUhSb2FYTXViV1Z6YzJGblpYTWdQU0JiWFR0Y2JpQWdmVnh1WEc0Z0lHUmxiR2wyWlhJb2JXVnpjMkZuWlRvZ1lXNTVLWHRjYmlBZ0lDQjBhR2x6TG0xbGMzTmhaMlZ6TG5CMWMyZ29iV1Z6YzJGblpTazdYRzRnSUNBZ2NtVjBkWEp1SUcxbGMzTmhaMlU3WEc0Z0lIMWNibHh1SUNCblpYUW9LWHRjYmlBZ0lDQnlaWFIxY200Z2RHaHBjeTV0WlhOellXZGxjenRjYmlBZ2ZWeHVYRzRnSUdselJXMXdkSGtvS1h0Y2JpQWdJQ0J5WlhSMWNtNGdkR2hwY3k1dFpYTnpZV2RsY3k1c1pXNW5kR2dnUFQwOUlEQTdYRzRnSUgxY2JseHVJQ0J5WlcxdmRtVkJkQ2hwYm1SbGVDbDdYRzRnSUNBZ2RHaHBjeTV0WlhOellXZGxjeTV6Y0d4cFkyVW9hVzVrWlhnc0lERXBPMXh1SUNCOVhHNTlYRzVjYm1WNGNHOXlkQ0JrWldaaGRXeDBJRTFoYVd4aWIzZzdJbDBzSW5OdmRYSmpaVkp2YjNRaU9pSXZjMjkxY21ObEx5SjlcbiIsImV4cG9ydCBkZWZhdWx0IHtcbiAgTk9STUFMOiBTeW1ib2wuZm9yKFwibm9ybWFsXCIpLFxuICBLSUxMOiBTeW1ib2wuZm9yKFwia2lsbFwiKSxcbiAgU1VTUEVORDogU3ltYm9sLmZvcihcInN1c3BlbmRcIiksXG4gIENPTlRJTlVFOiBTeW1ib2wuZm9yKFwiY29udGludWVcIiksXG4gIFJFQ0VJVkU6IFN5bWJvbC5mb3IoXCJyZWNlaXZlXCIpLFxuICBTRU5EOiBTeW1ib2wuZm9yKFwic2VuZFwiKSxcbiAgU0xFRVBJTkc6IFN5bWJvbC5mb3IoXCJzbGVlcGluZ1wiKSxcbiAgUlVOTklORzogU3ltYm9sLmZvcihcInJ1bm5pbmdcIiksXG4gIFNVU1BFTkRFRDogU3ltYm9sLmZvcihcInN1c3BlbmRlZFwiKSxcbiAgU1RPUFBFRDogU3ltYm9sLmZvcihcInN0b3BwZWRcIiksXG4gIFNMRUVQOiBTeW1ib2wuZm9yKFwic2xlZXBcIiksXG4gIEVYSVQ6IFN5bWJvbC5mb3IoXCJleGl0XCIpLFxuICBOT01BVENIOiBTeW1ib2wuZm9yKFwibm9fbWF0Y2hcIilcbn07XG4vLyMgc291cmNlTWFwcGluZ1VSTD1kYXRhOmFwcGxpY2F0aW9uL2pzb247YmFzZTY0LGV5SjJaWEp6YVc5dUlqb3pMQ0p6YjNWeVkyVnpJanBiSW14cFlpOWpiM0psTDNCeWIyTmxjM05sY3k5emRHRjBaWE11YW5NaVhTd2libUZ0WlhNaU9sdGRMQ0p0WVhCd2FXNW5jeUk2SWtGQlFVRXNaVUZCWlR0QlFVTmlMRlZCUVZFc1QwRkJUeXhIUVVGUUxFTkJRVmNzVVVGQldDeERRVUZTTzBGQlEwRXNVVUZCVFN4UFFVRlBMRWRCUVZBc1EwRkJWeXhOUVVGWUxFTkJRVTQ3UVVGRFFTeFhRVUZUTEU5QlFVOHNSMEZCVUN4RFFVRlhMRk5CUVZnc1EwRkJWRHRCUVVOQkxGbEJRVlVzVDBGQlR5eEhRVUZRTEVOQlFWY3NWVUZCV0N4RFFVRldPMEZCUTBFc1YwRkJVeXhQUVVGUExFZEJRVkFzUTBGQlZ5eFRRVUZZTEVOQlFWUTdRVUZEUVN4UlFVRk5MRTlCUVU4c1IwRkJVQ3hEUVVGWExFMUJRVmdzUTBGQlRqdEJRVU5CTEZsQlFWVXNUMEZCVHl4SFFVRlFMRU5CUVZjc1ZVRkJXQ3hEUVVGV08wRkJRMEVzVjBGQlV5eFBRVUZQTEVkQlFWQXNRMEZCVnl4VFFVRllMRU5CUVZRN1FVRkRRU3hoUVVGWExFOUJRVThzUjBGQlVDeERRVUZYTEZkQlFWZ3NRMEZCV0R0QlFVTkJMRmRCUVZNc1QwRkJUeXhIUVVGUUxFTkJRVmNzVTBGQldDeERRVUZVTzBGQlEwRXNVMEZCVHl4UFFVRlBMRWRCUVZBc1EwRkJWeXhQUVVGWUxFTkJRVkE3UVVGRFFTeFJRVUZOTEU5QlFVOHNSMEZCVUN4RFFVRlhMRTFCUVZnc1EwRkJUanRCUVVOQkxGZEJRVk1zVDBGQlR5eEhRVUZRTEVOQlFWY3NWVUZCV0N4RFFVRlVPME5CWWtZaUxDSm1hV3hsSWpvaWJHbGlMMk52Y21VdmNISnZZMlZ6YzJWekwzTjBZWFJsY3k1cWN5SXNJbk52ZFhKalpYTkRiMjUwWlc1MElqcGJJbVY0Y0c5eWRDQmtaV1poZFd4MElIdGNiaUFnVGs5U1RVRk1PaUJUZVcxaWIyd3VabTl5S0Z3aWJtOXliV0ZzWENJcExGeHVJQ0JMU1V4TU9pQlRlVzFpYjJ3dVptOXlLRndpYTJsc2JGd2lLU3hjYmlBZ1UxVlRVRVZPUkRvZ1UzbHRZbTlzTG1admNpaGNJbk4xYzNCbGJtUmNJaWtzWEc0Z0lFTlBUbFJKVGxWRk9pQlRlVzFpYjJ3dVptOXlLRndpWTI5dWRHbHVkV1ZjSWlrc1hHNGdJRkpGUTBWSlZrVTZJRk41YldKdmJDNW1iM0lvWENKeVpXTmxhWFpsWENJcExGeHVJQ0JUUlU1RU9pQlRlVzFpYjJ3dVptOXlLRndpYzJWdVpGd2lLU3hjYmlBZ1UweEZSVkJKVGtjNklGTjViV0p2YkM1bWIzSW9YQ0p6YkdWbGNHbHVaMXdpS1N4Y2JpQWdVbFZPVGtsT1J6b2dVM2x0WW05c0xtWnZjaWhjSW5KMWJtNXBibWRjSWlrc1hHNGdJRk5WVTFCRlRrUkZSRG9nVTNsdFltOXNMbVp2Y2loY0luTjFjM0JsYm1SbFpGd2lLU3hjYmlBZ1UxUlBVRkJGUkRvZ1UzbHRZbTlzTG1admNpaGNJbk4wYjNCd1pXUmNJaWtzWEc0Z0lGTk1SVVZRT2lCVGVXMWliMnd1Wm05eUtGd2ljMnhsWlhCY0lpa3NYRzRnSUVWWVNWUTZJRk41YldKdmJDNW1iM0lvWENKbGVHbDBYQ0lwTEZ4dUlDQk9UMDFCVkVOSU9pQlRlVzFpYjJ3dVptOXlLRndpYm05ZmJXRjBZMmhjSWlsY2JuMGlYU3dpYzI5MWNtTmxVbTl2ZENJNklpOXpiM1Z5WTJVdkluMD1cbiIsIlwidXNlIHN0cmljdFwiO1xuXG5pbXBvcnQgTWFpbGJveCBmcm9tIFwiLi9tYWlsYm94XCI7XG5pbXBvcnQgU3RhdGVzIGZyb20gXCIuL3N0YXRlc1wiO1xuXG5jbGFzcyBQcm9jZXNzIHtcblxuICBjb25zdHJ1Y3RvcihwaWQsIG1haWxib3gpIHtcbiAgICB0aGlzLnBpZCA9IHBpZDtcbiAgICB0aGlzLm1haWxib3ggPSBtYWlsYm94O1xuICAgIHRoaXMuc3RhdHVzID0gU3RhdGVzLlNUT1BQRUQ7XG4gICAgdGhpcy5kaWN0ID0ge307XG4gIH1cbn1cblxuZXhwb3J0IGRlZmF1bHQgUHJvY2Vzcztcbi8vIyBzb3VyY2VNYXBwaW5nVVJMPWRhdGE6YXBwbGljYXRpb24vanNvbjtiYXNlNjQsZXlKMlpYSnphVzl1SWpvekxDSnpiM1Z5WTJWeklqcGJJbXhwWWk5amIzSmxMM0J5YjJObGMzTmxjeTl3Y205alpYTnpMbXB6SWwwc0ltNWhiV1Z6SWpwYlhTd2liV0Z3Y0dsdVozTWlPaUpCUVVGQk96dEJRVWRCTEU5QlFVOHNUMEZCVUN4TlFVRnZRaXhYUVVGd1FqdEJRVU5CTEU5QlFVOHNUVUZCVUN4TlFVRnRRaXhWUVVGdVFqczdRVUZGUVN4TlFVRk5MRTlCUVU0c1EwRkJZenM3UVVGTFdpeGpRVUZaTEVkQlFWb3NSVUZCZVVJc1QwRkJla0lzUlVGQk1FTTdRVUZEZUVNc1UwRkJTeXhIUVVGTUxFZEJRVmNzUjBGQldDeERRVVIzUXp0QlFVVjRReXhUUVVGTExFOUJRVXdzUjBGQlpTeFBRVUZtTEVOQlJuZERPMEZCUjNoRExGTkJRVXNzVFVGQlRDeEhRVUZqTEU5QlFVOHNUMEZCVUN4RFFVZ3dRanRCUVVsNFF5eFRRVUZMTEVsQlFVd3NSMEZCV1N4RlFVRmFMRU5CU25kRE8wZEJRVEZETzBOQlRFWTdPMEZCWVVFc1pVRkJaU3hQUVVGbUlpd2labWxzWlNJNklteHBZaTlqYjNKbEwzQnliMk5sYzNObGN5OXdjbTlqWlhOekxtcHpJaXdpYzI5MWNtTmxjME52Ym5SbGJuUWlPbHNpWENKMWMyVWdjM1J5YVdOMFhDSTdYRzVjYmk4cUlFQm1iRzkzSUNvdlhHNXBiWEJ2Y25RZ1RXRnBiR0p2ZUNCbWNtOXRJRndpTGk5dFlXbHNZbTk0WENJN1hHNXBiWEJ2Y25RZ1UzUmhkR1Z6SUdaeWIyMGdYQ0l1TDNOMFlYUmxjMXdpTzF4dVhHNWpiR0Z6Y3lCUWNtOWpaWE56SUh0Y2JpQWdjR2xrT2lCT2RXMWlaWEk3WEc0Z0lHMWhhV3hpYjNnNklFMWhhV3hpYjNnN1hHNGdJR1JwWTNRNklFOWlhbVZqZER0Y2JseHVJQ0JqYjI1emRISjFZM1J2Y2lod2FXUTZJRTUxYldKbGNpd2diV0ZwYkdKdmVEb2dUV0ZwYkdKdmVDbDdYRzRnSUNBZ2RHaHBjeTV3YVdRZ1BTQndhV1E3WEc0Z0lDQWdkR2hwY3k1dFlXbHNZbTk0SUQwZ2JXRnBiR0p2ZUR0Y2JpQWdJQ0IwYUdsekxuTjBZWFIxY3lBOUlGTjBZWFJsY3k1VFZFOVFVRVZFTzF4dUlDQWdJSFJvYVhNdVpHbGpkQ0E5SUh0OU8xeHVJQ0I5WEc1OVhHNWNibVY0Y0c5eWRDQmtaV1poZFd4MElGQnliMk5sYzNNN1hHNGlYU3dpYzI5MWNtTmxVbTl2ZENJNklpOXpiM1Z5WTJVdkluMD1cbiIsImNsYXNzIFR1cGxlIHtcblxuICBjb25zdHJ1Y3RvciguLi5hcmdzKSB7XG4gICAgdGhpcy52YWx1ZXMgPSBPYmplY3QuZnJlZXplKGFyZ3MpO1xuICAgIHRoaXMubGVuZ3RoID0gdGhpcy52YWx1ZXMubGVuZ3RoO1xuICB9XG5cbiAgZ2V0KGluZGV4KSB7XG4gICAgcmV0dXJuIHRoaXMudmFsdWVzW2luZGV4XTtcbiAgfVxuXG4gIGNvdW50KCkge1xuICAgIHJldHVybiB0aGlzLnZhbHVlcy5sZW5ndGg7XG4gIH1cblxuICBbU3ltYm9sLml0ZXJhdG9yXSgpIHtcbiAgICByZXR1cm4gdGhpcy52YWx1ZXNbU3ltYm9sLml0ZXJhdG9yXSgpO1xuICB9XG5cbiAgdG9TdHJpbmcoKSB7XG4gICAgdmFyIGksXG4gICAgICAgIHMgPSBcIlwiO1xuICAgIGZvciAoaSA9IDA7IGkgPCB0aGlzLnZhbHVlcy5sZW5ndGg7IGkrKykge1xuICAgICAgaWYgKHMgIT09IFwiXCIpIHtcbiAgICAgICAgcyArPSBcIiwgXCI7XG4gICAgICB9XG4gICAgICBzICs9IHRoaXMudmFsdWVzW2ldLnRvU3RyaW5nKCk7XG4gICAgfVxuXG4gICAgcmV0dXJuIFwie1wiICsgcyArIFwifVwiO1xuICB9XG5cbiAgcHV0X2VsZW0oaW5kZXgsIGVsZW0pIHtcbiAgICBpZiAoaW5kZXggPT09IHRoaXMubGVuZ3RoKSB7XG4gICAgICBsZXQgbmV3X3ZhbHVlcyA9IHRoaXMudmFsdWVzLmNvbmNhdChbZWxlbV0pO1xuICAgICAgcmV0dXJuIG5ldyBUdXBsZSguLi5uZXdfdmFsdWVzKTtcbiAgICB9XG5cbiAgICBsZXQgbmV3X3ZhbHVlcyA9IHRoaXMudmFsdWVzLmNvbmNhdChbXSk7XG4gICAgbmV3X3ZhbHVlcy5zcGxpY2UoaW5kZXgsIDAsIGVsZW0pO1xuICAgIHJldHVybiBuZXcgVHVwbGUoLi4ubmV3X3ZhbHVlcyk7XG4gIH1cblxuICByZW1vdmVfZWxlbShpbmRleCkge1xuICAgIGxldCBuZXdfdmFsdWVzID0gdGhpcy52YWx1ZXMuY29uY2F0KFtdKTtcbiAgICBuZXdfdmFsdWVzLnNwbGljZShpbmRleCwgMSk7XG4gICAgcmV0dXJuIG5ldyBUdXBsZSguLi5uZXdfdmFsdWVzKTtcbiAgfVxuXG59XG5cbmxldCBwcm9jZXNzX2NvdW50ZXIgPSAtMTtcblxuY2xhc3MgUElEIHtcbiAgY29uc3RydWN0b3IoKSB7XG4gICAgcHJvY2Vzc19jb3VudGVyID0gcHJvY2Vzc19jb3VudGVyICsgMTtcbiAgICB0aGlzLmlkID0gcHJvY2Vzc19jb3VudGVyO1xuICB9XG5cbiAgdG9TdHJpbmcoKSB7XG4gICAgcmV0dXJuIFwiUElEIzwwLlwiICsgdGhpcy5pZCArIFwiLjA+XCI7XG4gIH1cbn1cblxuY2xhc3MgSW50ZWdlciB7fVxuY2xhc3MgRmxvYXQge31cblxuZXhwb3J0IHsgUElELCBUdXBsZSwgSW50ZWdlciwgRmxvYXQgfTtcbi8vIyBzb3VyY2VNYXBwaW5nVVJMPWRhdGE6YXBwbGljYXRpb24vanNvbjtiYXNlNjQsZXlKMlpYSnphVzl1SWpvekxDSnpiM1Z5WTJWeklqcGJJbXhwWWk5amIzSmxMM0J5YVcxcGRHbDJaWE11YW5NaVhTd2libUZ0WlhNaU9sdGRMQ0p0WVhCd2FXNW5jeUk2SWtGQlFVRXNUVUZCVFN4TFFVRk9MRU5CUVZrN08wRkJSVllzWTBGQldTeEhRVUZITEVsQlFVZ3NSVUZCVVR0QlFVTnNRaXhUUVVGTExFMUJRVXdzUjBGQll5eFBRVUZQTEUxQlFWQXNRMEZCWXl4SlFVRmtMRU5CUVdRc1EwRkVhMEk3UVVGRmJFSXNVMEZCU3l4TlFVRk1MRWRCUVdNc1MwRkJTeXhOUVVGTUxFTkJRVmtzVFVGQldpeERRVVpKTzBkQlFYQkNPenRCUVV0QkxFMUJRVWtzUzBGQlNpeEZRVUZYTzBGQlExUXNWMEZCVHl4TFFVRkxMRTFCUVV3c1EwRkJXU3hMUVVGYUxFTkJRVkFzUTBGRVV6dEhRVUZZT3p0QlFVbEJMRlZCUVZFN1FVRkRUaXhYUVVGUExFdEJRVXNzVFVGQlRDeERRVUZaTEUxQlFWb3NRMEZFUkR0SFFVRlNPenRCUVVsQkxFZEJRVU1zVDBGQlR5eFJRVUZRTEVsQlFXMUNPMEZCUTJ4Q0xGZEJRVThzUzBGQlN5eE5RVUZNTEVOQlFWa3NUMEZCVHl4UlFVRlFMRU5CUVZvc1JVRkJVQ3hEUVVSclFqdEhRVUZ3UWpzN1FVRkpRU3hoUVVGWE8wRkJRMVFzVVVGQlNTeERRVUZLTzFGQlFVOHNTVUZCU1N4RlFVRktMRU5CUkVVN1FVRkZWQ3hUUVVGTExFbEJRVWtzUTBGQlNpeEZRVUZQTEVsQlFVa3NTMEZCU3l4TlFVRk1MRU5CUVZrc1RVRkJXaXhGUVVGdlFpeEhRVUZ3UXl4RlFVRjVRenRCUVVOMlF5eFZRVUZKTEUxQlFVMHNSVUZCVGl4RlFVRlZPMEZCUTFvc1lVRkJTeXhKUVVGTUxFTkJSRms3VDBGQlpEdEJRVWRCTEZkQlFVc3NTMEZCU3l4TlFVRk1MRU5CUVZrc1EwRkJXaXhGUVVGbExGRkJRV1lzUlVGQlRDeERRVXAxUXp0TFFVRjZRenM3UVVGUFFTeFhRVUZQTEUxQlFVMHNRMEZCVGl4SFFVRlZMRWRCUVZZc1EwRlVSVHRIUVVGWU96dEJRVmxCTEZkQlFWTXNTMEZCVkN4RlFVRm5RaXhKUVVGb1FpeEZRVUZ4UWp0QlFVTnVRaXhSUVVGSExGVkJRVlVzUzBGQlN5eE5RVUZNTEVWQlFWazdRVUZEZGtJc1ZVRkJTU3hoUVVGaExFdEJRVXNzVFVGQlRDeERRVUZaTEUxQlFWb3NRMEZCYlVJc1EwRkJReXhKUVVGRUxFTkJRVzVDTEVOQlFXSXNRMEZFYlVJN1FVRkZka0lzWVVGQlR5eEpRVUZKTEV0QlFVb3NRMEZCVlN4SFFVRkhMRlZCUVVnc1EwRkJha0lzUTBGR2RVSTdTMEZCZWtJN08wRkJTMEVzVVVGQlNTeGhRVUZoTEV0QlFVc3NUVUZCVEN4RFFVRlpMRTFCUVZvc1EwRkJiVUlzUlVGQmJrSXNRMEZCWWl4RFFVNWxPMEZCVDI1Q0xHVkJRVmNzVFVGQldDeERRVUZyUWl4TFFVRnNRaXhGUVVGNVFpeERRVUY2UWl4RlFVRTBRaXhKUVVFMVFpeEZRVkJ0UWp0QlFWRnVRaXhYUVVGUExFbEJRVWtzUzBGQlNpeERRVUZWTEVkQlFVY3NWVUZCU0N4RFFVRnFRaXhEUVZKdFFqdEhRVUZ5UWpzN1FVRlhRU3hqUVVGWkxFdEJRVm9zUlVGQmEwSTdRVUZEYUVJc1VVRkJTU3hoUVVGaExFdEJRVXNzVFVGQlRDeERRVUZaTEUxQlFWb3NRMEZCYlVJc1JVRkJia0lzUTBGQllpeERRVVJaTzBGQlJXaENMR1ZCUVZjc1RVRkJXQ3hEUVVGclFpeExRVUZzUWl4RlFVRjVRaXhEUVVGNlFpeEZRVVpuUWp0QlFVZG9RaXhYUVVGUExFbEJRVWtzUzBGQlNpeERRVUZWTEVkQlFVY3NWVUZCU0N4RFFVRnFRaXhEUVVoblFqdEhRVUZzUWpzN1EwRXhRMFk3TzBGQmJVUkJMRWxCUVVrc2EwSkJRV3RDTEVOQlFVTXNRMEZCUkRzN1FVRkZkRUlzVFVGQlRTeEhRVUZPTEVOQlFWVTdRVUZEVWl4blFrRkJZVHRCUVVOWUxITkNRVUZyUWl4clFrRkJhMElzUTBGQmJFSXNRMEZFVUR0QlFVVllMRk5CUVVzc1JVRkJUQ3hIUVVGVkxHVkJRVllzUTBGR1Z6dEhRVUZpT3p0QlFVdEJMR0ZCUVZVN1FVRkRVaXhYUVVGUExGbEJRVmtzUzBGQlN5eEZRVUZNTEVkQlFWVXNTMEZCZEVJc1EwRkVRenRIUVVGV08wTkJUa1k3TzBGQlYwRXNUVUZCVFN4UFFVRk9MRU5CUVdNc1JVRkJaRHRCUVVOQkxFMUJRVTBzUzBGQlRpeERRVUZaTEVWQlFWbzdPMEZCUlVFc1UwRkJVeXhIUVVGVUxFVkJRV01zUzBGQlpDeEZRVUZ4UWl4UFFVRnlRaXhGUVVFNFFpeExRVUU1UWlJc0ltWnBiR1VpT2lKc2FXSXZZMjl5WlM5d2NtbHRhWFJwZG1WekxtcHpJaXdpYzI5MWNtTmxjME52Ym5SbGJuUWlPbHNpWTJ4aGMzTWdWSFZ3YkdVZ2UxeHVYRzRnSUdOdmJuTjBjblZqZEc5eUtDNHVMbUZ5WjNNcGUxeHVJQ0FnSUhSb2FYTXVkbUZzZFdWeklEMGdUMkpxWldOMExtWnlaV1Y2WlNoaGNtZHpLVHRjYmlBZ0lDQjBhR2x6TG14bGJtZDBhQ0E5SUhSb2FYTXVkbUZzZFdWekxteGxibWQwYUR0Y2JpQWdmVnh1WEc0Z0lHZGxkQ2hwYm1SbGVDa2dlMXh1SUNBZ0lISmxkSFZ5YmlCMGFHbHpMblpoYkhWbGMxdHBibVJsZUYwN1hHNGdJSDFjYmx4dUlDQmpiM1Z1ZENncElIdGNiaUFnSUNCeVpYUjFjbTRnZEdocGN5NTJZV3gxWlhNdWJHVnVaM1JvTzF4dUlDQjlYRzVjYmlBZ1cxTjViV0p2YkM1cGRHVnlZWFJ2Y2wwb0tTQjdYRzRnSUNBZ2NtVjBkWEp1SUhSb2FYTXVkbUZzZFdWelcxTjViV0p2YkM1cGRHVnlZWFJ2Y2wwb0tUdGNiaUFnZlZ4dVhHNGdJSFJ2VTNSeWFXNW5LQ2tnZTF4dUlDQWdJSFpoY2lCcExDQnpJRDBnWENKY0lqdGNiaUFnSUNCbWIzSWdLR2tnUFNBd095QnBJRHdnZEdocGN5NTJZV3gxWlhNdWJHVnVaM1JvT3lCcEt5c3BJSHRjYmlBZ0lDQWdJR2xtSUNoeklDRTlQU0JjSWx3aUtTQjdYRzRnSUNBZ0lDQWdJSE1nS3owZ1hDSXNJRndpTzF4dUlDQWdJQ0FnZlZ4dUlDQWdJQ0FnY3lBclBTQjBhR2x6TG5aaGJIVmxjMXRwWFM1MGIxTjBjbWx1WnlncE8xeHVJQ0FnSUgxY2JseHVJQ0FnSUhKbGRIVnliaUJjSW50Y0lpQXJJSE1nS3lCY0luMWNJanRjYmlBZ2ZWeHVYRzRnSUhCMWRGOWxiR1Z0S0dsdVpHVjRMQ0JsYkdWdEtYdGNiaUFnSUNCcFppaHBibVJsZUNBOVBUMGdkR2hwY3k1c1pXNW5kR2dwZTF4dUlDQWdJQ0FnYkdWMElHNWxkMTkyWVd4MVpYTWdQU0IwYUdsekxuWmhiSFZsY3k1amIyNWpZWFFvVzJWc1pXMWRLVHRjYmlBZ0lDQWdJSEpsZEhWeWJpQnVaWGNnVkhWd2JHVW9MaTR1Ym1WM1gzWmhiSFZsY3lrN1hHNGdJQ0FnZlZ4dVhHNGdJQ0FnYkdWMElHNWxkMTkyWVd4MVpYTWdQU0IwYUdsekxuWmhiSFZsY3k1amIyNWpZWFFvVzEwcE8xeHVJQ0FnSUc1bGQxOTJZV3gxWlhNdWMzQnNhV05sS0dsdVpHVjRMQ0F3TENCbGJHVnRLVHRjYmlBZ0lDQnlaWFIxY200Z2JtVjNJRlIxY0d4bEtDNHVMbTVsZDE5MllXeDFaWE1wTzF4dUlDQjlYRzVjYmlBZ2NtVnRiM1psWDJWc1pXMG9hVzVrWlhncGUxeHVJQ0FnSUd4bGRDQnVaWGRmZG1Gc2RXVnpJRDBnZEdocGN5NTJZV3gxWlhNdVkyOXVZMkYwS0Z0ZEtUdGNiaUFnSUNCdVpYZGZkbUZzZFdWekxuTndiR2xqWlNocGJtUmxlQ3dnTVNrN1hHNGdJQ0FnY21WMGRYSnVJRzVsZHlCVWRYQnNaU2d1TGk1dVpYZGZkbUZzZFdWektUdGNiaUFnZlZ4dVhHNTlYRzVjYmx4dWJHVjBJSEJ5YjJObGMzTmZZMjkxYm5SbGNpQTlJQzB4TzF4dVhHNWpiR0Z6Y3lCUVNVUWdlMXh1SUNCamIyNXpkSEoxWTNSdmNpZ3BlMXh1SUNBZ0lIQnliMk5sYzNOZlkyOTFiblJsY2lBOUlIQnliMk5sYzNOZlkyOTFiblJsY2lBcklERTdYRzRnSUNBZ2RHaHBjeTVwWkNBOUlIQnliMk5sYzNOZlkyOTFiblJsY2p0Y2JpQWdmVnh1WEc0Z0lIUnZVM1J5YVc1bktDbDdYRzRnSUNBZ2NtVjBkWEp1SUZ3aVVFbEVJend3TGx3aUlDc2dkR2hwY3k1cFpDQXJJRndpTGpBK1hDSTdYRzRnSUgxY2JuMWNibHh1WTJ4aGMzTWdTVzUwWldkbGNpQjdmVnh1WTJ4aGMzTWdSbXh2WVhRZ2UzMWNibHh1Wlhod2IzSjBJSHNnVUVsRUxDQlVkWEJzWlN3Z1NXNTBaV2RsY2l3Z1JteHZZWFFnZlR0Y2JpSmRMQ0p6YjNWeVkyVlNiMjkwSWpvaUwzTnZkWEpqWlM4aWZRPT1cbiIsIlxuXCJ1c2Ugc3RyaWN0XCI7XG5cbmltcG9ydCBNYWlsYm94IGZyb20gXCIuL21haWxib3hcIjtcbmltcG9ydCBQcm9jZXNzIGZyb20gXCIuL3Byb2Nlc3NcIjtcbmltcG9ydCBTdGF0ZXMgZnJvbSBcIi4vc3RhdGVzXCI7XG5pbXBvcnQgKiBhcyBQcmltaXRpdmVzIGZyb20gXCIuLi9wcmltaXRpdmVzXCI7XG5cbmNsYXNzIFByb2Nlc3NTeXN0ZW0ge1xuXG4gIGNvbnN0cnVjdG9yKCkge1xuICAgIHRoaXMucGlkcyA9IG5ldyBNYXAoKTtcbiAgICB0aGlzLm1haWxib3hlcyA9IG5ldyBNYXAoKTtcbiAgICB0aGlzLm5hbWVzID0gbmV3IE1hcCgpO1xuICAgIHRoaXMubGlua3MgPSBuZXcgTWFwKCk7XG5cbiAgICB0aGlzLmN1cnJlbnRfcHJvY2VzcyA9IG51bGw7XG4gICAgdGhpcy5zdXNwZW5kZWQgPSBuZXcgTWFwKCk7XG5cbiAgICB0aGlzLm1haW5fcHJvY2Vzc19waWQgPSB0aGlzLnNwYXduKCk7XG4gICAgdGhpcy5zZXRfY3VycmVudCh0aGlzLm1haW5fcHJvY2Vzc19waWQpO1xuICB9XG5cbiAgc3Bhd24oKSB7XG4gICAgcmV0dXJuIHRoaXMuYWRkX3Byb2MoZmFsc2UpLnBpZDtcbiAgfVxuXG4gIHNwYXduX2xpbmsoKSB7XG4gICAgcmV0dXJuIHRoaXMuYWRkX3Byb2ModHJ1ZSkucGlkO1xuICB9XG5cbiAgbGluayhwaWQpIHtcbiAgICB0aGlzLmxpbmtzLmdldCh0aGlzLnBpZCgpKS5hZGQocGlkKTtcbiAgICB0aGlzLmxpbmtzLmdldChwaWQpLmFkZCh0aGlzLnBpZCgpKTtcbiAgfVxuXG4gIHVubGluayhwaWQpIHtcbiAgICB0aGlzLmxpbmtzLmdldCh0aGlzLnBpZCgpKS5kZWxldGUocGlkKTtcbiAgICB0aGlzLmxpbmtzLmdldChwaWQpLmRlbGV0ZSh0aGlzLnBpZCgpKTtcbiAgfVxuXG4gIHNldF9jdXJyZW50KGlkKSB7XG4gICAgbGV0IHBpZCA9IHRoaXMucGlkb2YoaWQpO1xuICAgIGlmIChwaWQgIT09IG51bGwpIHtcbiAgICAgIHRoaXMuY3VycmVudF9wcm9jZXNzID0gdGhpcy5waWRzLmdldChwaWQpO1xuICAgICAgdGhpcy5jdXJyZW50X3Byb2Nlc3Muc3RhdHVzID0gU3RhdGVzLlJVTk5JTkc7XG4gICAgfVxuICB9XG5cbiAgYWRkX3Byb2MobGlua2VkKSB7XG4gICAgbGV0IG5ld3BpZCA9IG5ldyBQcmltaXRpdmVzLlBJRCgpO1xuICAgIGxldCBtYWlsYm94ID0gbmV3IE1haWxib3goKTtcbiAgICBsZXQgbmV3cHJvYyA9IG5ldyBQcm9jZXNzKG5ld3BpZCwgbWFpbGJveCk7XG5cbiAgICB0aGlzLnBpZHMuc2V0KG5ld3BpZCwgbmV3cHJvYyk7XG4gICAgdGhpcy5tYWlsYm94ZXMuc2V0KG5ld3BpZCwgbWFpbGJveCk7XG4gICAgdGhpcy5saW5rcy5zZXQobmV3cGlkLCBuZXcgU2V0KCkpO1xuXG4gICAgaWYgKGxpbmtlZCkge1xuICAgICAgdGhpcy5saW5rKG5ld3BpZCk7XG4gICAgfVxuXG4gICAgcmV0dXJuIG5ld3Byb2M7XG4gIH1cblxuICByZW1vdmVfcHJvYyhwaWQpIHtcbiAgICB0aGlzLnBpZHMuZGVsZXRlKHBpZCk7XG4gICAgdGhpcy51bnJlZ2lzdGVyKHBpZCk7XG5cbiAgICBpZiAodGhpcy5saW5rcy5oYXMocGlkKSkge1xuICAgICAgZm9yIChsZXQgbGlua3BpZCBvZiB0aGlzLmxpbmtzLmdldChwaWQpKSB7XG4gICAgICAgIHRoaXMubGlua3MuZ2V0KGxpbmtwaWQpLmRlbGV0ZShwaWQpO1xuICAgICAgfVxuXG4gICAgICB0aGlzLmxpbmtzLmRlbGV0ZShwaWQpO1xuICAgIH1cbiAgfVxuXG4gIGV4aXQoaWQpIHtcbiAgICBsZXQgcGlkID0gdGhpcy5waWRvZihpZCk7XG4gICAgdGhpcy5yZW1vdmVfcHJvYyhpZCk7XG4gIH1cblxuICByZWdpc3RlcihuYW1lLCBwaWQpIHtcbiAgICBpZiAoIXRoaXMubmFtZXMuaGFzKG5hbWUpKSB7XG4gICAgICB0aGlzLm5hbWVzLnNldChuYW1lLCBwaWQpO1xuICAgICAgcmV0dXJuIG5hbWU7XG4gICAgfSBlbHNlIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcihcIk5hbWUgaXMgYWxyZWFkeSByZWdpc3RlcmVkIHRvIGFub3RoZXIgcHJvY2Vzc1wiKTtcbiAgICB9XG4gIH1cblxuICByZWdpc3RlcmVkKG5hbWUpIHtcbiAgICByZXR1cm4gdGhpcy5uYW1lcy5oYXMobmFtZSkgPyB0aGlzLm5hbWVzLmdldChuYW1lKSA6IG51bGw7XG4gIH1cblxuICB1bnJlZ2lzdGVyKHBpZCkge1xuICAgIGZvciAobGV0IG5hbWUgb2YgdGhpcy5uYW1lcy5rZXlzKCkpIHtcbiAgICAgIGlmICh0aGlzLm5hbWVzLmhhcyhuYW1lKSAmJiB0aGlzLm5hbWVzLmdldChuYW1lKSA9PT0gcGlkKSB7XG4gICAgICAgIHRoaXMubmFtZXMuZGVsZXRlKG5hbWUpO1xuICAgICAgfVxuICAgIH1cbiAgfVxuXG4gIHBpZCgpIHtcbiAgICByZXR1cm4gdGhpcy5jdXJyZW50X3Byb2Nlc3MucGlkO1xuICB9XG5cbiAgcGlkb2YoaWQpIHtcbiAgICBpZiAoaWQgaW5zdGFuY2VvZiBQcmltaXRpdmVzLlBJRCkge1xuICAgICAgcmV0dXJuIHRoaXMucGlkcy5oYXMoaWQpID8gaWQgOiBudWxsO1xuICAgIH0gZWxzZSBpZiAoaWQgaW5zdGFuY2VvZiBQcm9jZXNzKSB7XG4gICAgICByZXR1cm4gaWQucGlkO1xuICAgIH0gZWxzZSB7XG4gICAgICBsZXQgcGlkID0gdGhpcy5yZWdpc3RlcmVkKGlkKTtcbiAgICAgIGlmIChwaWQgPT09IG51bGwpIHRocm93IFwiUHJvY2VzcyBuYW1lIG5vdCByZWdpc3RlcmVkOiBcIiArIGlkICsgXCIgKFwiICsgdHlwZW9mIGlkICsgXCIpXCI7XG4gICAgICByZXR1cm4gcGlkO1xuICAgIH1cbiAgfVxuXG4gIHB1dChpZCwga2V5LCB2YWx1ZSkge1xuICAgIGxldCBwaWQgPSB0aGlzLnBpZG9mKGlkKTtcbiAgICBsZXQgcHJvY2VzcyA9IHRoaXMucGlkcy5nZXQocGlkKTtcbiAgICBwcm9jZXNzLmRpY3Rba2V5XSA9IHZhbHVlO1xuICB9XG5cbiAgZ2V0KGlkLCBrZXkpIHtcbiAgICBsZXQgcGlkID0gdGhpcy5waWRvZihpZCk7XG4gICAgbGV0IHByb2Nlc3MgPSB0aGlzLnBpZHMuZ2V0KHBpZCk7XG5cbiAgICBpZiAoa2V5ICE9IG51bGwpIHtcbiAgICAgIHJldHVybiBwcm9jZXNzLmRpY3Rba2V5XTtcbiAgICB9IGVsc2Uge1xuICAgICAgcmV0dXJuIHByb2Nlc3MuZGljdDtcbiAgICB9XG4gIH1cblxuICBnZXRfa2V5cyhpZCkge1xuICAgIGxldCBwaWQgPSB0aGlzLnBpZG9mKGlkKTtcbiAgICBsZXQgcHJvY2VzcyA9IHRoaXMucGlkcy5nZXQocGlkKTtcblxuICAgIHJldHVybiBPYmplY3Qua2V5cyhwcm9jZXNzLmRpY3QpO1xuICB9XG5cbiAgZXJhc2UoaWQsIGtleSkge1xuICAgIGxldCBwaWQgPSB0aGlzLnBpZG9mKGlkKTtcbiAgICBsZXQgcHJvY2VzcyA9IHRoaXMucGlkcy5nZXQocGlkKTtcblxuICAgIGlmIChrZXkgIT0gbnVsbCkge1xuICAgICAgZGVsZXRlIHByb2Nlc3MuZGljdFtrZXldO1xuICAgIH0gZWxzZSB7XG4gICAgICBwcm9jZXNzLmRpY3QgPSB7fTtcbiAgICB9XG4gIH1cbn1cblxuZXhwb3J0IGRlZmF1bHQgUHJvY2Vzc1N5c3RlbTtcbi8vIyBzb3VyY2VNYXBwaW5nVVJMPWRhdGE6YXBwbGljYXRpb24vanNvbjtiYXNlNjQsZXlKMlpYSnphVzl1SWpvekxDSnpiM1Z5WTJWeklqcGJJbXhwWWk5amIzSmxMM0J5YjJObGMzTmxjeTl3Y205alpYTnpYM041YzNSbGJTNXFjeUpkTENKdVlXMWxjeUk2VzEwc0ltMWhjSEJwYm1keklqb2lPMEZCUTBFN08wRkJSVUVzVDBGQlR5eFBRVUZRTEUxQlFXOUNMRmRCUVhCQ08wRkJRMEVzVDBGQlR5eFBRVUZRTEUxQlFXOUNMRmRCUVhCQ08wRkJRMEVzVDBGQlR5eE5RVUZRTEUxQlFXMUNMRlZCUVc1Q08wRkJRMEVzVDBGQlR5eExRVUZMTEZWQlFVd3NUVUZCY1VJc1pVRkJOVUk3TzBGQlJVRXNUVUZCVFN4aFFVRk9MRU5CUVc5Q096dEJRVVZzUWl4blFrRkJZVHRCUVVOWUxGTkJRVXNzU1VGQlRDeEhRVUZaTEVsQlFVa3NSMEZCU2l4RlFVRmFMRU5CUkZjN1FVRkZXQ3hUUVVGTExGTkJRVXdzUjBGQmFVSXNTVUZCU1N4SFFVRktMRVZCUVdwQ0xFTkJSbGM3UVVGSFdDeFRRVUZMTEV0QlFVd3NSMEZCWVN4SlFVRkpMRWRCUVVvc1JVRkJZaXhEUVVoWE8wRkJTVmdzVTBGQlN5eExRVUZNTEVkQlFXRXNTVUZCU1N4SFFVRktMRVZCUVdJc1EwRktWenM3UVVGTldDeFRRVUZMTEdWQlFVd3NSMEZCZFVJc1NVRkJka0lzUTBGT1Z6dEJRVTlZTEZOQlFVc3NVMEZCVEN4SFFVRnBRaXhKUVVGSkxFZEJRVW9zUlVGQmFrSXNRMEZRVnpzN1FVRlRXQ3hUUVVGTExHZENRVUZNTEVkQlFYZENMRXRCUVVzc1MwRkJUQ3hGUVVGNFFpeERRVlJYTzBGQlZWZ3NVMEZCU3l4WFFVRk1MRU5CUVdsQ0xFdEJRVXNzWjBKQlFVd3NRMEZCYWtJc1EwRldWenRIUVVGaU96dEJRV0ZCTEZWQlFVODdRVUZEVEN4WFFVRlBMRXRCUVVzc1VVRkJUQ3hEUVVGakxFdEJRV1FzUlVGQmNVSXNSMEZCY2tJc1EwRkVSanRIUVVGUU96dEJRVWxCTEdWQlFWazdRVUZEVml4WFFVRlBMRXRCUVVzc1VVRkJUQ3hEUVVGakxFbEJRV1FzUlVGQmIwSXNSMEZCY0VJc1EwRkVSenRIUVVGYU96dEJRVWxCTEU5QlFVc3NSMEZCVEN4RlFVRlRPMEZCUTFBc1UwRkJTeXhMUVVGTUxFTkJRVmNzUjBGQldDeERRVUZsTEV0QlFVc3NSMEZCVEN4RlFVRm1MRVZCUVRKQ0xFZEJRVE5DTEVOQlFTdENMRWRCUVM5Q0xFVkJSRTg3UVVGRlVDeFRRVUZMTEV0QlFVd3NRMEZCVnl4SFFVRllMRU5CUVdVc1IwRkJaaXhGUVVGdlFpeEhRVUZ3UWl4RFFVRjNRaXhMUVVGTExFZEJRVXdzUlVGQmVFSXNSVUZHVHp0SFFVRlVPenRCUVV0QkxGTkJRVThzUjBGQlVDeEZRVUZYTzBGQlExUXNVMEZCU3l4TFFVRk1MRU5CUVZjc1IwRkJXQ3hEUVVGbExFdEJRVXNzUjBGQlRDeEZRVUZtTEVWQlFUSkNMRTFCUVROQ0xFTkJRV3RETEVkQlFXeERMRVZCUkZNN1FVRkZWQ3hUUVVGTExFdEJRVXdzUTBGQlZ5eEhRVUZZTEVOQlFXVXNSMEZCWml4RlFVRnZRaXhOUVVGd1FpeERRVUV5UWl4TFFVRkxMRWRCUVV3c1JVRkJNMElzUlVGR1V6dEhRVUZZT3p0QlFVdEJMR05CUVZrc1JVRkJXaXhGUVVGbE8wRkJRMklzVVVGQlNTeE5RVUZOTEV0QlFVc3NTMEZCVEN4RFFVRlhMRVZCUVZnc1EwRkJUaXhEUVVSVE8wRkJSV0lzVVVGQlJ5eFJRVUZSTEVsQlFWSXNSVUZCWVR0QlFVTmtMRmRCUVVzc1pVRkJUQ3hIUVVGMVFpeExRVUZMTEVsQlFVd3NRMEZCVlN4SFFVRldMRU5CUVdNc1IwRkJaQ3hEUVVGMlFpeERRVVJqTzBGQlJXUXNWMEZCU3l4bFFVRk1MRU5CUVhGQ0xFMUJRWEpDTEVkQlFUaENMRTlCUVU4c1QwRkJVQ3hEUVVab1FqdExRVUZvUWp0SFFVWkdPenRCUVZGQkxGZEJRVk1zVFVGQlZDeEZRVUZuUWp0QlFVTmtMRkZCUVVrc1UwRkJVeXhKUVVGSkxGZEJRVmNzUjBGQldDeEZRVUZpTEVOQlJGVTdRVUZGWkN4UlFVRkpMRlZCUVZVc1NVRkJTU3hQUVVGS0xFVkJRVllzUTBGR1ZUdEJRVWRrTEZGQlFVa3NWVUZCVlN4SlFVRkpMRTlCUVVvc1EwRkJXU3hOUVVGYUxFVkJRVzlDTEU5QlFYQkNMRU5CUVZZc1EwRklWVHM3UVVGTFpDeFRRVUZMTEVsQlFVd3NRMEZCVlN4SFFVRldMRU5CUVdNc1RVRkJaQ3hGUVVGelFpeFBRVUYwUWl4RlFVeGpPMEZCVFdRc1UwRkJTeXhUUVVGTUxFTkJRV1VzUjBGQlppeERRVUZ0UWl4TlFVRnVRaXhGUVVFeVFpeFBRVUV6UWl4RlFVNWpPMEZCVDJRc1UwRkJTeXhMUVVGTUxFTkJRVmNzUjBGQldDeERRVUZsTEUxQlFXWXNSVUZCZFVJc1NVRkJTU3hIUVVGS0xFVkJRWFpDTEVWQlVHTTdPMEZCVTJRc1VVRkJSeXhOUVVGSUxFVkJRVlU3UVVGRFVpeFhRVUZMTEVsQlFVd3NRMEZCVlN4TlFVRldMRVZCUkZFN1MwRkJWanM3UVVGSlFTeFhRVUZQTEU5QlFWQXNRMEZpWXp0SFFVRm9RanM3UVVGblFrRXNZMEZCV1N4SFFVRmFMRVZCUVdkQ08wRkJRMlFzVTBGQlN5eEpRVUZNTEVOQlFWVXNUVUZCVml4RFFVRnBRaXhIUVVGcVFpeEZRVVJqTzBGQlJXUXNVMEZCU3l4VlFVRk1MRU5CUVdkQ0xFZEJRV2hDTEVWQlJtTTdPMEZCU1dRc1VVRkJSeXhMUVVGTExFdEJRVXdzUTBGQlZ5eEhRVUZZTEVOQlFXVXNSMEZCWml4RFFVRklMRVZCUVhWQ08wRkJRM0pDTEZkQlFVc3NTVUZCU1N4UFFVRktMRWxCUVdVc1MwRkJTeXhMUVVGTUxFTkJRVmNzUjBGQldDeERRVUZsTEVkQlFXWXNRMEZCY0VJc1JVRkJlVU03UVVGRGRrTXNZVUZCU3l4TFFVRk1MRU5CUVZjc1IwRkJXQ3hEUVVGbExFOUJRV1lzUlVGQmQwSXNUVUZCZUVJc1EwRkJLMElzUjBGQkwwSXNSVUZFZFVNN1QwRkJla003TzBGQlNVRXNWMEZCU3l4TFFVRk1MRU5CUVZjc1RVRkJXQ3hEUVVGclFpeEhRVUZzUWl4RlFVeHhRanRMUVVGMlFqdEhRVXBHT3p0QlFXRkJMRTlCUVVzc1JVRkJUQ3hGUVVGUk8wRkJRMDRzVVVGQlNTeE5RVUZOTEV0QlFVc3NTMEZCVEN4RFFVRlhMRVZCUVZnc1EwRkJUaXhEUVVSRk8wRkJSVTRzVTBGQlN5eFhRVUZNTEVOQlFXbENMRVZCUVdwQ0xFVkJSazA3UjBGQlVqczdRVUZMUVN4WFFVRlRMRWxCUVZRc1JVRkJaU3hIUVVGbUxFVkJRVzFDTzBGQlEycENMRkZCUVVjc1EwRkJReXhMUVVGTExFdEJRVXdzUTBGQlZ5eEhRVUZZTEVOQlFXVXNTVUZCWml4RFFVRkVMRVZCUVhOQ08wRkJRM1pDTEZkQlFVc3NTMEZCVEN4RFFVRlhMRWRCUVZnc1EwRkJaU3hKUVVGbUxFVkJRWEZDTEVkQlFYSkNMRVZCUkhWQ08wRkJSWFpDTEdGQlFVOHNTVUZCVUN4RFFVWjFRanRMUVVGNlFpeE5RVWRMTzBGQlEwZ3NXVUZCVFN4SlFVRkpMRXRCUVVvc1EwRkJWU3dyUTBGQlZpeERRVUZPTEVOQlJFYzdTMEZJVER0SFFVUkdPenRCUVZOQkxHRkJRVmNzU1VGQldDeEZRVUZuUWp0QlFVTmtMRmRCUVU4c1MwRkJTeXhMUVVGTUxFTkJRVmNzUjBGQldDeERRVUZsTEVsQlFXWXNTVUZCZFVJc1MwRkJTeXhMUVVGTUxFTkJRVmNzUjBGQldDeERRVUZsTEVsQlFXWXNRMEZCZGtJc1IwRkJPRU1zU1VGQk9VTXNRMEZFVHp0SFFVRm9RanM3UVVGSlFTeGhRVUZYTEVkQlFWZ3NSVUZCWlR0QlFVTmlMRk5CUVVrc1NVRkJTU3hKUVVGS0xFbEJRVmtzUzBGQlN5eExRVUZNTEVOQlFWY3NTVUZCV0N4RlFVRm9RaXhGUVVGclF6dEJRVU5vUXl4VlFVRkhMRXRCUVVzc1MwRkJUQ3hEUVVGWExFZEJRVmdzUTBGQlpTeEpRVUZtTEV0QlFYZENMRXRCUVVzc1MwRkJUQ3hEUVVGWExFZEJRVmdzUTBGQlpTeEpRVUZtTEUxQlFYbENMRWRCUVhwQ0xFVkJRVFpDTzBGQlEzUkVMR0ZCUVVzc1MwRkJUQ3hEUVVGWExFMUJRVmdzUTBGQmEwSXNTVUZCYkVJc1JVRkVjMFE3VDBGQmVFUTdTMEZFUmp0SFFVUkdPenRCUVZGQkxGRkJRVXM3UVVGRFNDeFhRVUZQTEV0QlFVc3NaVUZCVEN4RFFVRnhRaXhIUVVGeVFpeERRVVJLTzBkQlFVdzdPMEZCU1VFc1VVRkJUU3hGUVVGT0xFVkJRVk03UVVGRFVDeFJRVUZKTEdOQlFXTXNWMEZCVnl4SFFVRllMRVZCUVdkQ08wRkJReTlDTEdGQlFVOHNTMEZCU3l4SlFVRk1MRU5CUVZVc1IwRkJWaXhEUVVGakxFVkJRV1FzU1VGQmIwSXNSVUZCY0VJc1IwRkJlVUlzU1VGQmVrSXNRMEZFZDBJN1MwRkJiRU1zVFVGRlR5eEpRVUZKTEdOQlFXTXNUMEZCWkN4RlFVRjFRanRCUVVNdlFpeGhRVUZQTEVkQlFVY3NSMEZCU0N4RFFVUjNRanRMUVVFelFpeE5RVVZCTzBGQlEwb3NWVUZCU1N4TlFVRk5MRXRCUVVzc1ZVRkJUQ3hEUVVGblFpeEZRVUZvUWl4RFFVRk9MRU5CUkVFN1FVRkZTaXhWUVVGSkxGRkJRVkVzU1VGQlVpeEZRVU5FTEUxQlFVMHNhME5CUVd0RExFVkJRV3hETEVkQlFYVkRMRWxCUVhaRExFZEJRVGhETEU5QlFVOHNSVUZCVUN4SFFVRmhMRWRCUVRORUxFTkJSRlE3UVVGRlFTeGhRVUZQTEVkQlFWQXNRMEZLU1R0TFFVWkJPMGRCU0ZRN08wRkJZVUVzVFVGQlNTeEZRVUZLTEVWQlFWRXNSMEZCVWl4RlFVRmhMRXRCUVdJc1JVRkJiVUk3UVVGRGFrSXNVVUZCU1N4TlFVRk5MRXRCUVVzc1MwRkJUQ3hEUVVGWExFVkJRVmdzUTBGQlRpeERRVVJoTzBGQlJXcENMRkZCUVVrc1ZVRkJWU3hMUVVGTExFbEJRVXdzUTBGQlZTeEhRVUZXTEVOQlFXTXNSMEZCWkN4RFFVRldMRU5CUm1FN1FVRkhha0lzV1VGQlVTeEpRVUZTTEVOQlFXRXNSMEZCWWl4SlFVRnZRaXhMUVVGd1FpeERRVWhwUWp0SFFVRnVRanM3UVVGTlFTeE5RVUZKTEVWQlFVb3NSVUZCVVN4SFFVRlNMRVZCUVZrN1FVRkRWaXhSUVVGSkxFMUJRVTBzUzBGQlN5eExRVUZNTEVOQlFWY3NSVUZCV0N4RFFVRk9MRU5CUkUwN1FVRkZWaXhSUVVGSkxGVkJRVlVzUzBGQlN5eEpRVUZNTEVOQlFWVXNSMEZCVml4RFFVRmpMRWRCUVdRc1EwRkJWaXhEUVVaTk96dEJRVWxXTEZGQlFVY3NUMEZCVHl4SlFVRlFMRVZCUVZrN1FVRkRZaXhoUVVGUExGRkJRVkVzU1VGQlVpeERRVUZoTEVkQlFXSXNRMEZCVUN4RFFVUmhPMHRCUVdZc1RVRkZTenRCUVVOSUxHRkJRVThzVVVGQlVTeEpRVUZTTEVOQlJFbzdTMEZHVER0SFFVcEdPenRCUVZkQkxGZEJRVk1zUlVGQlZDeEZRVUZaTzBGQlExWXNVVUZCU1N4TlFVRk5MRXRCUVVzc1MwRkJUQ3hEUVVGWExFVkJRVmdzUTBGQlRpeERRVVJOTzBGQlJWWXNVVUZCU1N4VlFVRlZMRXRCUVVzc1NVRkJUQ3hEUVVGVkxFZEJRVllzUTBGQll5eEhRVUZrTEVOQlFWWXNRMEZHVFRzN1FVRkpWaXhYUVVGUExFOUJRVThzU1VGQlVDeERRVUZaTEZGQlFWRXNTVUZCVWl4RFFVRnVRaXhEUVVwVk8wZEJRVm83TzBGQlQwRXNVVUZCVFN4RlFVRk9MRVZCUVZVc1IwRkJWaXhGUVVGak8wRkJRMW9zVVVGQlNTeE5RVUZOTEV0QlFVc3NTMEZCVEN4RFFVRlhMRVZCUVZnc1EwRkJUaXhEUVVSUk8wRkJSVm9zVVVGQlNTeFZRVUZWTEV0QlFVc3NTVUZCVEN4RFFVRlZMRWRCUVZZc1EwRkJZeXhIUVVGa0xFTkJRVllzUTBGR1VUczdRVUZKV2l4UlFVRkhMRTlCUVU4c1NVRkJVQ3hGUVVGWk8wRkJRMklzWVVGQlR5eFJRVUZSTEVsQlFWSXNRMEZCWVN4SFFVRmlMRU5CUVZBc1EwRkVZVHRMUVVGbUxFMUJSVXM3UVVGRFNDeGpRVUZSTEVsQlFWSXNSMEZCWlN4RlFVRm1MRU5CUkVjN1MwRkdURHRIUVVwR08wTkJla2xHT3p0QlFYRktRU3hsUVVGbExHRkJRV1lpTENKbWFXeGxJam9pYkdsaUwyTnZjbVV2Y0hKdlkyVnpjMlZ6TDNCeWIyTmxjM05mYzNsemRHVnRMbXB6SWl3aWMyOTFjbU5sYzBOdmJuUmxiblFpT2xzaUx5b2dRR1pzYjNjZ0tpOWNibHdpZFhObElITjBjbWxqZEZ3aU8xeHVYRzVwYlhCdmNuUWdUV0ZwYkdKdmVDQm1jbTl0SUZ3aUxpOXRZV2xzWW05NFhDSTdYRzVwYlhCdmNuUWdVSEp2WTJWemN5Qm1jbTl0SUZ3aUxpOXdjbTlqWlhOelhDSTdYRzVwYlhCdmNuUWdVM1JoZEdWeklHWnliMjBnWENJdUwzTjBZWFJsYzF3aU8xeHVhVzF3YjNKMElDb2dZWE1nVUhKcGJXbDBhWFpsY3lCbWNtOXRJRndpTGk0dmNISnBiV2wwYVhabGMxd2lPMXh1WEc1amJHRnpjeUJRY205alpYTnpVM2x6ZEdWdElIdGNibHh1SUNCamIyNXpkSEoxWTNSdmNpZ3BlMXh1SUNBZ0lIUm9hWE11Y0dsa2N5QTlJRzVsZHlCTllYQW9LVHRjYmlBZ0lDQjBhR2x6TG0xaGFXeGliM2hsY3lBOUlHNWxkeUJOWVhBb0tUdGNiaUFnSUNCMGFHbHpMbTVoYldWeklEMGdibVYzSUUxaGNDZ3BPMXh1SUNBZ0lIUm9hWE11YkdsdWEzTWdQU0J1WlhjZ1RXRndLQ2s3WEc1Y2JpQWdJQ0IwYUdsekxtTjFjbkpsYm5SZmNISnZZMlZ6Y3lBOUlHNTFiR3c3WEc0Z0lDQWdkR2hwY3k1emRYTndaVzVrWldRZ1BTQnVaWGNnVFdGd0tDazdYRzVjYmlBZ0lDQjBhR2x6TG0xaGFXNWZjSEp2WTJWemMxOXdhV1FnUFNCMGFHbHpMbk53WVhkdUtDazdYRzRnSUNBZ2RHaHBjeTV6WlhSZlkzVnljbVZ1ZENoMGFHbHpMbTFoYVc1ZmNISnZZMlZ6YzE5d2FXUXBPMXh1SUNCOVhHNWNiaUFnYzNCaGQyNG9LWHRjYmlBZ0lDQnlaWFIxY200Z2RHaHBjeTVoWkdSZmNISnZZeWhtWVd4elpTa3VjR2xrTzF4dUlDQjlYRzVjYmlBZ2MzQmhkMjVmYkdsdWF5Z3BlMXh1SUNBZ0lISmxkSFZ5YmlCMGFHbHpMbUZrWkY5d2NtOWpLSFJ5ZFdVcExuQnBaRHRjYmlBZ2ZWeHVYRzRnSUd4cGJtc29jR2xrS1h0Y2JpQWdJQ0IwYUdsekxteHBibXR6TG1kbGRDaDBhR2x6TG5CcFpDZ3BLUzVoWkdRb2NHbGtLVHRjYmlBZ0lDQjBhR2x6TG14cGJtdHpMbWRsZENod2FXUXBMbUZrWkNoMGFHbHpMbkJwWkNncEtUdGNiaUFnZlZ4dVhHNGdJSFZ1YkdsdWF5aHdhV1FwZTF4dUlDQWdJSFJvYVhNdWJHbHVhM011WjJWMEtIUm9hWE11Y0dsa0tDa3BMbVJsYkdWMFpTaHdhV1FwTzF4dUlDQWdJSFJvYVhNdWJHbHVhM011WjJWMEtIQnBaQ2t1WkdWc1pYUmxLSFJvYVhNdWNHbGtLQ2twTzF4dUlDQjlYRzVjYmlBZ2MyVjBYMk4xY25KbGJuUW9hV1FwZTF4dUlDQWdJR3hsZENCd2FXUWdQU0IwYUdsekxuQnBaRzltS0dsa0tUdGNiaUFnSUNCcFppaHdhV1FnSVQwOUlHNTFiR3dwZTF4dUlDQWdJQ0FnZEdocGN5NWpkWEp5Wlc1MFgzQnliMk5sYzNNZ1BTQjBhR2x6TG5CcFpITXVaMlYwS0hCcFpDazdYRzRnSUNBZ0lDQjBhR2x6TG1OMWNuSmxiblJmY0hKdlkyVnpjeTV6ZEdGMGRYTWdQU0JUZEdGMFpYTXVVbFZPVGtsT1J6dGNiaUFnSUNCOVhHNGdJSDFjYmx4dUlDQmhaR1JmY0hKdll5aHNhVzVyWldRcGUxeHVJQ0FnSUd4bGRDQnVaWGR3YVdRZ1BTQnVaWGNnVUhKcGJXbDBhWFpsY3k1UVNVUW9LVHRjYmlBZ0lDQnNaWFFnYldGcGJHSnZlQ0E5SUc1bGR5Qk5ZV2xzWW05NEtDazdYRzRnSUNBZ2JHVjBJRzVsZDNCeWIyTWdQU0J1WlhjZ1VISnZZMlZ6Y3lodVpYZHdhV1FzSUcxaGFXeGliM2dwTzF4dVhHNGdJQ0FnZEdocGN5NXdhV1J6TG5ObGRDaHVaWGR3YVdRc0lHNWxkM0J5YjJNcE8xeHVJQ0FnSUhSb2FYTXViV0ZwYkdKdmVHVnpMbk5sZENodVpYZHdhV1FzSUcxaGFXeGliM2dwTzF4dUlDQWdJSFJvYVhNdWJHbHVhM011YzJWMEtHNWxkM0JwWkN3Z2JtVjNJRk5sZENncEtUdGNibHh1SUNBZ0lHbG1LR3hwYm10bFpDbDdYRzRnSUNBZ0lDQjBhR2x6TG14cGJtc29ibVYzY0dsa0tUdGNiaUFnSUNCOVhHNWNiaUFnSUNCeVpYUjFjbTRnYm1WM2NISnZZenRjYmlBZ2ZWeHVYRzRnSUhKbGJXOTJaVjl3Y205aktIQnBaQ2w3WEc0Z0lDQWdkR2hwY3k1d2FXUnpMbVJsYkdWMFpTaHdhV1FwTzF4dUlDQWdJSFJvYVhNdWRXNXlaV2RwYzNSbGNpaHdhV1FwTzF4dVhHNGdJQ0FnYVdZb2RHaHBjeTVzYVc1cmN5NW9ZWE1vY0dsa0tTbDdYRzRnSUNBZ0lDQm1iM0lnS0d4bGRDQnNhVzVyY0dsa0lHOW1JSFJvYVhNdWJHbHVhM011WjJWMEtIQnBaQ2twSUh0Y2JpQWdJQ0FnSUNBZ2RHaHBjeTVzYVc1cmN5NW5aWFFvYkdsdWEzQnBaQ2t1WkdWc1pYUmxLSEJwWkNrN1hHNGdJQ0FnSUNCOVhHNWNiaUFnSUNBZ0lIUm9hWE11YkdsdWEzTXVaR1ZzWlhSbEtIQnBaQ2s3WEc0Z0lDQWdmVnh1SUNCOVhHNWNiaUFnWlhocGRDaHBaQ2w3WEc0Z0lDQWdiR1YwSUhCcFpDQTlJSFJvYVhNdWNHbGtiMllvYVdRcE8xeHVJQ0FnSUhSb2FYTXVjbVZ0YjNabFgzQnliMk1vYVdRcE8xeHVJQ0I5WEc1Y2JpQWdjbVZuYVhOMFpYSW9ibUZ0WlN3Z2NHbGtLWHRjYmlBZ0lDQnBaaWdoZEdocGN5NXVZVzFsY3k1b1lYTW9ibUZ0WlNrcGUxeHVJQ0FnSUNBZ2RHaHBjeTV1WVcxbGN5NXpaWFFvYm1GdFpTd2djR2xrS1Z4dUlDQWdJQ0FnY21WMGRYSnVJRzVoYldVN1hHNGdJQ0FnZldWc2MyVjdYRzRnSUNBZ0lDQjBhSEp2ZHlCdVpYY2dSWEp5YjNJb1hDSk9ZVzFsSUdseklHRnNjbVZoWkhrZ2NtVm5hWE4wWlhKbFpDQjBieUJoYm05MGFHVnlJSEJ5YjJObGMzTmNJaWs3WEc0Z0lDQWdmVnh1SUNCOVhHNWNiaUFnY21WbmFYTjBaWEpsWkNodVlXMWxLWHRjYmlBZ0lDQnlaWFIxY200Z2RHaHBjeTV1WVcxbGN5NW9ZWE1vYm1GdFpTa2dQeUIwYUdsekxtNWhiV1Z6TG1kbGRDaHVZVzFsS1NBNklHNTFiR3c3WEc0Z0lIMWNibHh1SUNCMWJuSmxaMmx6ZEdWeUtIQnBaQ2w3WEc0Z0lDQWdabTl5S0d4bGRDQnVZVzFsSUc5bUlIUm9hWE11Ym1GdFpYTXVhMlY1Y3lncEtYdGNiaUFnSUNBZ0lHbG1LSFJvYVhNdWJtRnRaWE11YUdGektHNWhiV1VwSUNZbUlIUm9hWE11Ym1GdFpYTXVaMlYwS0c1aGJXVXBJRDA5UFNCd2FXUXBlMXh1SUNBZ0lDQWdJQ0IwYUdsekxtNWhiV1Z6TG1SbGJHVjBaU2h1WVcxbEtUdGNiaUFnSUNBZ0lIMWNiaUFnSUNCOVhHNGdJSDFjYmx4dUlDQndhV1FvS1h0Y2JpQWdJQ0J5WlhSMWNtNGdkR2hwY3k1amRYSnlaVzUwWDNCeWIyTmxjM011Y0dsa08xeHVJQ0I5WEc1Y2JpQWdjR2xrYjJZb2FXUXBlMXh1SUNBZ0lHbG1JQ2hwWkNCcGJuTjBZVzVqWlc5bUlGQnlhVzFwZEdsMlpYTXVVRWxFS1NCN1hHNGdJQ0FnSUNBZ2NtVjBkWEp1SUhSb2FYTXVjR2xrY3k1b1lYTW9hV1FwSUQ4Z2FXUWdPaUJ1ZFd4c08xeHVJQ0FnSUgwZ1pXeHpaU0JwWmlBb2FXUWdhVzV6ZEdGdVkyVnZaaUJRY205alpYTnpLU0I3WEc0Z0lDQWdJQ0FnY21WMGRYSnVJR2xrTG5CcFpEdGNiaUFnSUNCOUlHVnNjMlVnZTF4dUlDQWdJQ0FnSUd4bGRDQndhV1FnUFNCMGFHbHpMbkpsWjJsemRHVnlaV1FvYVdRcE8xeHVJQ0FnSUNBZ0lHbG1JQ2h3YVdRZ1BUMDlJRzUxYkd3cFhHNGdJQ0FnSUNBZ0lDQWdkR2h5YjNjb1hDSlFjbTlqWlhOeklHNWhiV1VnYm05MElISmxaMmx6ZEdWeVpXUTZJRndpSUNzZ2FXUWdLeUJjSWlBb1hDSWdLeUIwZVhCbGIyWW9hV1FwSUNzZ1hDSXBYQ0lwTzF4dUlDQWdJQ0FnSUhKbGRIVnliaUJ3YVdRN1hHNGdJQ0FnZlZ4dUlDQjlYRzVjYmlBZ2NIVjBLR2xrTENCclpYa3NJSFpoYkhWbEtYdGNiaUFnSUNCc1pYUWdjR2xrSUQwZ2RHaHBjeTV3YVdSdlppaHBaQ2s3WEc0Z0lDQWdiR1YwSUhCeWIyTmxjM01nUFNCMGFHbHpMbkJwWkhNdVoyVjBLSEJwWkNrN1hHNGdJQ0FnY0hKdlkyVnpjeTVrYVdOMFcydGxlVjBnUFNCMllXeDFaVHRjYmlBZ2ZWeHVYRzRnSUdkbGRDaHBaQ3dnYTJWNUtYdGNiaUFnSUNCc1pYUWdjR2xrSUQwZ2RHaHBjeTV3YVdSdlppaHBaQ2s3WEc0Z0lDQWdiR1YwSUhCeWIyTmxjM01nUFNCMGFHbHpMbkJwWkhNdVoyVjBLSEJwWkNrN1hHNWNiaUFnSUNCcFppaHJaWGtnSVQwZ2JuVnNiQ2w3WEc0Z0lDQWdJQ0J5WlhSMWNtNGdjSEp2WTJWemN5NWthV04wVzJ0bGVWMDdYRzRnSUNBZ2ZXVnNjMlY3WEc0Z0lDQWdJQ0J5WlhSMWNtNGdjSEp2WTJWemN5NWthV04wTzF4dUlDQWdJSDFjYmlBZ2ZWeHVYRzRnSUdkbGRGOXJaWGx6S0dsa0tYdGNiaUFnSUNCc1pYUWdjR2xrSUQwZ2RHaHBjeTV3YVdSdlppaHBaQ2s3WEc0Z0lDQWdiR1YwSUhCeWIyTmxjM01nUFNCMGFHbHpMbkJwWkhNdVoyVjBLSEJwWkNrN1hHNWNiaUFnSUNCeVpYUjFjbTRnVDJKcVpXTjBMbXRsZVhNb2NISnZZMlZ6Y3k1a2FXTjBLVHRjYmlBZ2ZWeHVYRzRnSUdWeVlYTmxLR2xrTENCclpYa3BlMXh1SUNBZ0lHeGxkQ0J3YVdRZ1BTQjBhR2x6TG5CcFpHOW1LR2xrS1R0Y2JpQWdJQ0JzWlhRZ2NISnZZMlZ6Y3lBOUlIUm9hWE11Y0dsa2N5NW5aWFFvY0dsa0tUdGNibHh1SUNBZ0lHbG1LR3RsZVNBaFBTQnVkV3hzS1h0Y2JpQWdJQ0FnSUdSbGJHVjBaU0J3Y205alpYTnpMbVJwWTNSYmEyVjVYVHRjYmlBZ0lDQjlaV3h6Wlh0Y2JpQWdJQ0FnSUhCeWIyTmxjM011WkdsamRDQTlJSHQ5TzF4dUlDQWdJSDFjYmlBZ2ZWeHVmVnh1WEc1bGVIQnZjblFnWkdWbVlYVnNkQ0JRY205alpYTnpVM2x6ZEdWdE8xeHVJbDBzSW5OdmRYSmpaVkp2YjNRaU9pSXZjMjkxY21ObEx5SjlcbiIsImNsYXNzIEJpdFN0cmluZyB7XG4gIGNvbnN0cnVjdG9yKC4uLmFyZ3MpIHtcbiAgICB0aGlzLnZhbHVlID0gT2JqZWN0LmZyZWV6ZSh0aGlzLnByb2Nlc3MoYXJncykpO1xuICAgIHRoaXMubGVuZ3RoID0gdGhpcy52YWx1ZS5sZW5ndGg7XG4gICAgdGhpcy5iaXRfc2l6ZSA9IHRoaXMubGVuZ3RoICogODtcbiAgICB0aGlzLmJ5dGVfc2l6ZSA9IHRoaXMubGVuZ3RoO1xuICB9XG5cbiAgZ2V0KGluZGV4KSB7XG4gICAgcmV0dXJuIHRoaXMudmFsdWVbaW5kZXhdO1xuICB9XG5cbiAgY291bnQoKSB7XG4gICAgcmV0dXJuIHRoaXMudmFsdWUubGVuZ3RoO1xuICB9XG5cbiAgc2xpY2Uoc3RhcnQsIGVuZCA9IG51bGwpIHtcbiAgICBsZXQgcyA9IHRoaXMudmFsdWUuc2xpY2Uoc3RhcnQsIGVuZCk7XG4gICAgbGV0IG1zID0gcy5tYXAoZWxlbSA9PiBCaXRTdHJpbmcuaW50ZWdlcihlbGVtKSk7XG4gICAgcmV0dXJuIG5ldyBCaXRTdHJpbmcoLi4ubXMpO1xuICB9XG5cbiAgW1N5bWJvbC5pdGVyYXRvcl0oKSB7XG4gICAgcmV0dXJuIHRoaXMudmFsdWVbU3ltYm9sLml0ZXJhdG9yXSgpO1xuICB9XG5cbiAgdG9TdHJpbmcoKSB7XG4gICAgdmFyIGksXG4gICAgICAgIHMgPSBcIlwiO1xuICAgIGZvciAoaSA9IDA7IGkgPCB0aGlzLmNvdW50KCk7IGkrKykge1xuICAgICAgaWYgKHMgIT09IFwiXCIpIHtcbiAgICAgICAgcyArPSBcIiwgXCI7XG4gICAgICB9XG4gICAgICBzICs9IHRoaXMuZ2V0KGkpLnRvU3RyaW5nKCk7XG4gICAgfVxuXG4gICAgcmV0dXJuIFwiPDxcIiArIHMgKyBcIj4+XCI7XG4gIH1cblxuICBwcm9jZXNzKGJpdFN0cmluZ1BhcnRzKSB7XG4gICAgbGV0IHByb2Nlc3NlZF92YWx1ZXMgPSBbXTtcblxuICAgIHZhciBpO1xuICAgIGZvciAoaSA9IDA7IGkgPCBiaXRTdHJpbmdQYXJ0cy5sZW5ndGg7IGkrKykge1xuICAgICAgbGV0IHByb2Nlc3NlZF92YWx1ZSA9IHRoaXNbJ3Byb2Nlc3NfJyArIGJpdFN0cmluZ1BhcnRzW2ldLnR5cGVdKGJpdFN0cmluZ1BhcnRzW2ldKTtcblxuICAgICAgZm9yIChsZXQgYXR0ciBvZiBiaXRTdHJpbmdQYXJ0c1tpXS5hdHRyaWJ1dGVzKSB7XG4gICAgICAgIHByb2Nlc3NlZF92YWx1ZSA9IHRoaXNbJ3Byb2Nlc3NfJyArIGF0dHJdKHByb2Nlc3NlZF92YWx1ZSk7XG4gICAgICB9XG5cbiAgICAgIHByb2Nlc3NlZF92YWx1ZXMgPSBwcm9jZXNzZWRfdmFsdWVzLmNvbmNhdChwcm9jZXNzZWRfdmFsdWUpO1xuICAgIH1cblxuICAgIHJldHVybiBwcm9jZXNzZWRfdmFsdWVzO1xuICB9XG5cbiAgcHJvY2Vzc19pbnRlZ2VyKHZhbHVlKSB7XG4gICAgcmV0dXJuIHZhbHVlLnZhbHVlO1xuICB9XG5cbiAgcHJvY2Vzc19mbG9hdCh2YWx1ZSkge1xuICAgIGlmICh2YWx1ZS5zaXplID09PSA2NCkge1xuICAgICAgcmV0dXJuIEJpdFN0cmluZy5mbG9hdDY0VG9CeXRlcyh2YWx1ZS52YWx1ZSk7XG4gICAgfSBlbHNlIGlmICh2YWx1ZS5zaXplID09PSAzMikge1xuICAgICAgcmV0dXJuIEJpdFN0cmluZy5mbG9hdDMyVG9CeXRlcyh2YWx1ZS52YWx1ZSk7XG4gICAgfVxuXG4gICAgdGhyb3cgbmV3IEVycm9yKCdJbnZhbGlkIHNpemUgZm9yIGZsb2F0Jyk7XG4gIH1cblxuICBwcm9jZXNzX2JpdHN0cmluZyh2YWx1ZSkge1xuICAgIHJldHVybiB2YWx1ZS52YWx1ZS52YWx1ZTtcbiAgfVxuXG4gIHByb2Nlc3NfYmluYXJ5KHZhbHVlKSB7XG4gICAgcmV0dXJuIEJpdFN0cmluZy50b1VURjhBcnJheSh2YWx1ZS52YWx1ZSk7XG4gIH1cblxuICBwcm9jZXNzX3V0ZjgodmFsdWUpIHtcbiAgICByZXR1cm4gQml0U3RyaW5nLnRvVVRGOEFycmF5KHZhbHVlLnZhbHVlKTtcbiAgfVxuXG4gIHByb2Nlc3NfdXRmMTYodmFsdWUpIHtcbiAgICByZXR1cm4gQml0U3RyaW5nLnRvVVRGMTZBcnJheSh2YWx1ZS52YWx1ZSk7XG4gIH1cblxuICBwcm9jZXNzX3V0ZjMyKHZhbHVlKSB7XG4gICAgcmV0dXJuIEJpdFN0cmluZy50b1VURjMyQXJyYXkodmFsdWUudmFsdWUpO1xuICB9XG5cbiAgcHJvY2Vzc19zaWduZWQodmFsdWUpIHtcbiAgICByZXR1cm4gbmV3IFVpbnQ4QXJyYXkoW3ZhbHVlXSlbMF07XG4gIH1cblxuICBwcm9jZXNzX3Vuc2lnbmVkKHZhbHVlKSB7XG4gICAgcmV0dXJuIHZhbHVlO1xuICB9XG5cbiAgcHJvY2Vzc19uYXRpdmUodmFsdWUpIHtcbiAgICByZXR1cm4gdmFsdWU7XG4gIH1cblxuICBwcm9jZXNzX2JpZyh2YWx1ZSkge1xuICAgIHJldHVybiB2YWx1ZTtcbiAgfVxuXG4gIHByb2Nlc3NfbGl0dGxlKHZhbHVlKSB7XG4gICAgcmV0dXJuIHZhbHVlLnJldmVyc2UoKTtcbiAgfVxuXG4gIHByb2Nlc3Nfc2l6ZSh2YWx1ZSkge1xuICAgIHJldHVybiB2YWx1ZTtcbiAgfVxuXG4gIHByb2Nlc3NfdW5pdCh2YWx1ZSkge1xuICAgIHJldHVybiB2YWx1ZTtcbiAgfVxuXG4gIHN0YXRpYyBpbnRlZ2VyKHZhbHVlKSB7XG4gICAgcmV0dXJuIEJpdFN0cmluZy53cmFwKHZhbHVlLCB7ICd0eXBlJzogJ2ludGVnZXInLCAndW5pdCc6IDEsICdzaXplJzogOCB9KTtcbiAgfVxuXG4gIHN0YXRpYyBmbG9hdCh2YWx1ZSkge1xuICAgIHJldHVybiBCaXRTdHJpbmcud3JhcCh2YWx1ZSwgeyAndHlwZSc6ICdmbG9hdCcsICd1bml0JzogMSwgJ3NpemUnOiA2NCB9KTtcbiAgfVxuXG4gIHN0YXRpYyBiaXRzdHJpbmcodmFsdWUpIHtcbiAgICByZXR1cm4gQml0U3RyaW5nLndyYXAodmFsdWUsIHsgJ3R5cGUnOiAnYml0c3RyaW5nJywgJ3VuaXQnOiAxLCAnc2l6ZSc6IHZhbHVlLmJpdF9zaXplIH0pO1xuICB9XG5cbiAgc3RhdGljIGJpdHModmFsdWUpIHtcbiAgICByZXR1cm4gQml0U3RyaW5nLmJpdHN0cmluZyh2YWx1ZSk7XG4gIH1cblxuICBzdGF0aWMgYmluYXJ5KHZhbHVlKSB7XG4gICAgcmV0dXJuIEJpdFN0cmluZy53cmFwKHZhbHVlLCB7ICd0eXBlJzogJ2JpbmFyeScsICd1bml0JzogOCwgJ3NpemUnOiB2YWx1ZS5sZW5ndGggfSk7XG4gIH1cblxuICBzdGF0aWMgYnl0ZXModmFsdWUpIHtcbiAgICByZXR1cm4gQml0U3RyaW5nLmJpbmFyeSh2YWx1ZSk7XG4gIH1cblxuICBzdGF0aWMgdXRmOCh2YWx1ZSkge1xuICAgIHJldHVybiBCaXRTdHJpbmcud3JhcCh2YWx1ZSwgeyAndHlwZSc6ICd1dGY4JywgJ3VuaXQnOiAxLCAnc2l6ZSc6IHZhbHVlLmxlbmd0aCB9KTtcbiAgfVxuXG4gIHN0YXRpYyB1dGYxNih2YWx1ZSkge1xuICAgIHJldHVybiBCaXRTdHJpbmcud3JhcCh2YWx1ZSwgeyAndHlwZSc6ICd1dGYxNicsICd1bml0JzogMSwgJ3NpemUnOiB2YWx1ZS5sZW5ndGggKiAyIH0pO1xuICB9XG5cbiAgc3RhdGljIHV0ZjMyKHZhbHVlKSB7XG4gICAgcmV0dXJuIEJpdFN0cmluZy53cmFwKHZhbHVlLCB7ICd0eXBlJzogJ3V0ZjMyJywgJ3VuaXQnOiAxLCAnc2l6ZSc6IHZhbHVlLmxlbmd0aCAqIDQgfSk7XG4gIH1cblxuICBzdGF0aWMgc2lnbmVkKHZhbHVlKSB7XG4gICAgcmV0dXJuIEJpdFN0cmluZy53cmFwKHZhbHVlLCB7fSwgJ3NpZ25lZCcpO1xuICB9XG5cbiAgc3RhdGljIHVuc2lnbmVkKHZhbHVlKSB7XG4gICAgcmV0dXJuIEJpdFN0cmluZy53cmFwKHZhbHVlLCB7fSwgJ3Vuc2lnbmVkJyk7XG4gIH1cblxuICBzdGF0aWMgbmF0aXZlKHZhbHVlKSB7XG4gICAgcmV0dXJuIEJpdFN0cmluZy53cmFwKHZhbHVlLCB7fSwgJ25hdGl2ZScpO1xuICB9XG5cbiAgc3RhdGljIGJpZyh2YWx1ZSkge1xuICAgIHJldHVybiBCaXRTdHJpbmcud3JhcCh2YWx1ZSwge30sICdiaWcnKTtcbiAgfVxuXG4gIHN0YXRpYyBsaXR0bGUodmFsdWUpIHtcbiAgICByZXR1cm4gQml0U3RyaW5nLndyYXAodmFsdWUsIHt9LCAnbGl0dGxlJyk7XG4gIH1cblxuICBzdGF0aWMgc2l6ZSh2YWx1ZSwgY291bnQpIHtcbiAgICByZXR1cm4gQml0U3RyaW5nLndyYXAodmFsdWUsIHsgJ3NpemUnOiBjb3VudCB9KTtcbiAgfVxuXG4gIHN0YXRpYyB1bml0KHZhbHVlLCBjb3VudCkge1xuICAgIHJldHVybiBCaXRTdHJpbmcud3JhcCh2YWx1ZSwgeyAndW5pdCc6IGNvdW50IH0pO1xuICB9XG5cbiAgc3RhdGljIHdyYXAodmFsdWUsIG9wdCwgbmV3X2F0dHJpYnV0ZSA9IG51bGwpIHtcbiAgICBsZXQgdGhlX3ZhbHVlID0gdmFsdWU7XG5cbiAgICBpZiAoISh2YWx1ZSBpbnN0YW5jZW9mIE9iamVjdCkpIHtcbiAgICAgIHRoZV92YWx1ZSA9IHsgJ3ZhbHVlJzogdmFsdWUsICdhdHRyaWJ1dGVzJzogW10gfTtcbiAgICB9XG5cbiAgICB0aGVfdmFsdWUgPSBPYmplY3QuYXNzaWduKHRoZV92YWx1ZSwgb3B0KTtcblxuICAgIGlmIChuZXdfYXR0cmlidXRlKSB7XG4gICAgICB0aGVfdmFsdWUuYXR0cmlidXRlcy5wdXNoKG5ld19hdHRyaWJ1dGUpO1xuICAgIH1cblxuICAgIHJldHVybiB0aGVfdmFsdWU7XG4gIH1cblxuICBzdGF0aWMgdG9VVEY4QXJyYXkoc3RyKSB7XG4gICAgdmFyIHV0ZjggPSBbXTtcbiAgICBmb3IgKHZhciBpID0gMDsgaSA8IHN0ci5sZW5ndGg7IGkrKykge1xuICAgICAgdmFyIGNoYXJjb2RlID0gc3RyLmNoYXJDb2RlQXQoaSk7XG4gICAgICBpZiAoY2hhcmNvZGUgPCAweDgwKSB7XG4gICAgICAgIHV0ZjgucHVzaChjaGFyY29kZSk7XG4gICAgICB9IGVsc2UgaWYgKGNoYXJjb2RlIDwgMHg4MDApIHtcbiAgICAgICAgdXRmOC5wdXNoKDB4YzAgfCBjaGFyY29kZSA+PiA2LCAweDgwIHwgY2hhcmNvZGUgJiAweDNmKTtcbiAgICAgIH0gZWxzZSBpZiAoY2hhcmNvZGUgPCAweGQ4MDAgfHwgY2hhcmNvZGUgPj0gMHhlMDAwKSB7XG4gICAgICAgIHV0ZjgucHVzaCgweGUwIHwgY2hhcmNvZGUgPj4gMTIsIDB4ODAgfCBjaGFyY29kZSA+PiA2ICYgMHgzZiwgMHg4MCB8IGNoYXJjb2RlICYgMHgzZik7XG4gICAgICB9XG4gICAgICAvLyBzdXJyb2dhdGUgcGFpclxuICAgICAgZWxzZSB7XG4gICAgICAgICAgaSsrO1xuICAgICAgICAgIC8vIFVURi0xNiBlbmNvZGVzIDB4MTAwMDAtMHgxMEZGRkYgYnlcbiAgICAgICAgICAvLyBzdWJ0cmFjdGluZyAweDEwMDAwIGFuZCBzcGxpdHRpbmcgdGhlXG4gICAgICAgICAgLy8gMjAgYml0cyBvZiAweDAtMHhGRkZGRiBpbnRvIHR3byBoYWx2ZXNcbiAgICAgICAgICBjaGFyY29kZSA9IDB4MTAwMDAgKyAoKGNoYXJjb2RlICYgMHgzZmYpIDw8IDEwIHwgc3RyLmNoYXJDb2RlQXQoaSkgJiAweDNmZik7XG4gICAgICAgICAgdXRmOC5wdXNoKDB4ZjAgfCBjaGFyY29kZSA+PiAxOCwgMHg4MCB8IGNoYXJjb2RlID4+IDEyICYgMHgzZiwgMHg4MCB8IGNoYXJjb2RlID4+IDYgJiAweDNmLCAweDgwIHwgY2hhcmNvZGUgJiAweDNmKTtcbiAgICAgICAgfVxuICAgIH1cbiAgICByZXR1cm4gdXRmODtcbiAgfVxuXG4gIHN0YXRpYyB0b1VURjE2QXJyYXkoc3RyKSB7XG4gICAgdmFyIHV0ZjE2ID0gW107XG4gICAgZm9yICh2YXIgaSA9IDA7IGkgPCBzdHIubGVuZ3RoOyBpKyspIHtcbiAgICAgIHZhciBjb2RlUG9pbnQgPSBzdHIuY29kZVBvaW50QXQoaSk7XG5cbiAgICAgIGlmIChjb2RlUG9pbnQgPD0gMjU1KSB7XG4gICAgICAgIHV0ZjE2LnB1c2goMCk7XG4gICAgICAgIHV0ZjE2LnB1c2goY29kZVBvaW50KTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHV0ZjE2LnB1c2goY29kZVBvaW50ID4+IDggJiAweEZGKTtcbiAgICAgICAgdXRmMTYucHVzaChjb2RlUG9pbnQgJiAweEZGKTtcbiAgICAgIH1cbiAgICB9XG4gICAgcmV0dXJuIHV0ZjE2O1xuICB9XG5cbiAgc3RhdGljIHRvVVRGMzJBcnJheShzdHIpIHtcbiAgICB2YXIgdXRmMzIgPSBbXTtcbiAgICBmb3IgKHZhciBpID0gMDsgaSA8IHN0ci5sZW5ndGg7IGkrKykge1xuICAgICAgdmFyIGNvZGVQb2ludCA9IHN0ci5jb2RlUG9pbnRBdChpKTtcblxuICAgICAgaWYgKGNvZGVQb2ludCA8PSAyNTUpIHtcbiAgICAgICAgdXRmMzIucHVzaCgwKTtcbiAgICAgICAgdXRmMzIucHVzaCgwKTtcbiAgICAgICAgdXRmMzIucHVzaCgwKTtcbiAgICAgICAgdXRmMzIucHVzaChjb2RlUG9pbnQpO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgdXRmMzIucHVzaCgwKTtcbiAgICAgICAgdXRmMzIucHVzaCgwKTtcbiAgICAgICAgdXRmMzIucHVzaChjb2RlUG9pbnQgPj4gOCAmIDB4RkYpO1xuICAgICAgICB1dGYzMi5wdXNoKGNvZGVQb2ludCAmIDB4RkYpO1xuICAgICAgfVxuICAgIH1cbiAgICByZXR1cm4gdXRmMzI7XG4gIH1cblxuICAvL2h0dHA6Ly9zdGFja292ZXJmbG93LmNvbS9xdWVzdGlvbnMvMjAwMzQ5My9qYXZhc2NyaXB0LWZsb2F0LWZyb20tdG8tYml0c1xuICBzdGF0aWMgZmxvYXQzMlRvQnl0ZXMoZikge1xuICAgIHZhciBieXRlcyA9IFtdO1xuXG4gICAgdmFyIGJ1ZiA9IG5ldyBBcnJheUJ1ZmZlcig0KTtcbiAgICBuZXcgRmxvYXQzMkFycmF5KGJ1ZilbMF0gPSBmO1xuXG4gICAgbGV0IGludFZlcnNpb24gPSBuZXcgVWludDMyQXJyYXkoYnVmKVswXTtcblxuICAgIGJ5dGVzLnB1c2goaW50VmVyc2lvbiA+PiAyNCAmIDB4RkYpO1xuICAgIGJ5dGVzLnB1c2goaW50VmVyc2lvbiA+PiAxNiAmIDB4RkYpO1xuICAgIGJ5dGVzLnB1c2goaW50VmVyc2lvbiA+PiA4ICYgMHhGRik7XG4gICAgYnl0ZXMucHVzaChpbnRWZXJzaW9uICYgMHhGRik7XG5cbiAgICByZXR1cm4gYnl0ZXM7XG4gIH1cblxuICBzdGF0aWMgZmxvYXQ2NFRvQnl0ZXMoZikge1xuICAgIHZhciBieXRlcyA9IFtdO1xuXG4gICAgdmFyIGJ1ZiA9IG5ldyBBcnJheUJ1ZmZlcig4KTtcbiAgICBuZXcgRmxvYXQ2NEFycmF5KGJ1ZilbMF0gPSBmO1xuXG4gICAgdmFyIGludFZlcnNpb24xID0gbmV3IFVpbnQzMkFycmF5KGJ1ZilbMF07XG4gICAgdmFyIGludFZlcnNpb24yID0gbmV3IFVpbnQzMkFycmF5KGJ1ZilbMV07XG5cbiAgICBieXRlcy5wdXNoKGludFZlcnNpb24yID4+IDI0ICYgMHhGRik7XG4gICAgYnl0ZXMucHVzaChpbnRWZXJzaW9uMiA+PiAxNiAmIDB4RkYpO1xuICAgIGJ5dGVzLnB1c2goaW50VmVyc2lvbjIgPj4gOCAmIDB4RkYpO1xuICAgIGJ5dGVzLnB1c2goaW50VmVyc2lvbjIgJiAweEZGKTtcblxuICAgIGJ5dGVzLnB1c2goaW50VmVyc2lvbjEgPj4gMjQgJiAweEZGKTtcbiAgICBieXRlcy5wdXNoKGludFZlcnNpb24xID4+IDE2ICYgMHhGRik7XG4gICAgYnl0ZXMucHVzaChpbnRWZXJzaW9uMSA+PiA4ICYgMHhGRik7XG4gICAgYnl0ZXMucHVzaChpbnRWZXJzaW9uMSAmIDB4RkYpO1xuXG4gICAgcmV0dXJuIGJ5dGVzO1xuICB9XG59XG5cbmV4cG9ydCBkZWZhdWx0IEJpdFN0cmluZztcbi8vIyBzb3VyY2VNYXBwaW5nVVJMPWRhdGE6YXBwbGljYXRpb24vanNvbjtiYXNlNjQsZXlKMlpYSnphVzl1SWpvekxDSnpiM1Z5WTJWeklqcGJJbXhwWWk5amIzSmxMMkpwZEY5emRISnBibWN1YW5NaVhTd2libUZ0WlhNaU9sdGRMQ0p0WVhCd2FXNW5jeUk2SWtGQlFVRXNUVUZCVFN4VFFVRk9MRU5CUVdkQ08wRkJRMlFzWTBGQldTeEhRVUZITEVsQlFVZ3NSVUZCVVR0QlFVTnNRaXhUUVVGTExFdEJRVXdzUjBGQllTeFBRVUZQTEUxQlFWQXNRMEZCWXl4TFFVRkxMRTlCUVV3c1EwRkJZU3hKUVVGaUxFTkJRV1FzUTBGQllpeERRVVJyUWp0QlFVVnNRaXhUUVVGTExFMUJRVXdzUjBGQll5eExRVUZMTEV0QlFVd3NRMEZCVnl4TlFVRllMRU5CUmtrN1FVRkhiRUlzVTBGQlN5eFJRVUZNTEVkQlFXZENMRXRCUVVzc1RVRkJUQ3hIUVVGakxFTkJRV1FzUTBGSVJUdEJRVWxzUWl4VFFVRkxMRk5CUVV3c1IwRkJhVUlzUzBGQlN5eE5RVUZNTEVOQlNrTTdSMEZCY0VJN08wRkJUMEVzVFVGQlNTeExRVUZLTEVWQlFWVTdRVUZEVWl4WFFVRlBMRXRCUVVzc1MwRkJUQ3hEUVVGWExFdEJRVmdzUTBGQlVDeERRVVJSTzBkQlFWWTdPMEZCU1VFc1ZVRkJUenRCUVVOTUxGZEJRVThzUzBGQlN5eExRVUZNTEVOQlFWY3NUVUZCV0N4RFFVUkdPMGRCUVZBN08wRkJTVUVzVVVGQlRTeExRVUZPTEVWQlFXRXNUVUZCVFN4SlFVRk9MRVZCUVZjN1FVRkRkRUlzVVVGQlNTeEpRVUZKTEV0QlFVc3NTMEZCVEN4RFFVRlhMRXRCUVZnc1EwRkJhVUlzUzBGQmFrSXNSVUZCZDBJc1IwRkJlRUlzUTBGQlNpeERRVVJyUWp0QlFVVjBRaXhSUVVGSkxFdEJRVXNzUlVGQlJTeEhRVUZHTEVOQlFVMHNVVUZCVlN4VlFVRlZMRTlCUVZZc1EwRkJhMElzU1VGQmJFSXNRMEZCVml4RFFVRllMRU5CUm10Q08wRkJSM1JDTEZkQlFVOHNTVUZCU1N4VFFVRktMRU5CUVdNc1IwRkJSeXhGUVVGSUxFTkJRWEpDTEVOQlNITkNPMGRCUVhoQ096dEJRVTFCTEVkQlFVTXNUMEZCVHl4UlFVRlFMRWxCUVcxQ08wRkJRMnhDTEZkQlFVOHNTMEZCU3l4TFFVRk1MRU5CUVZjc1QwRkJUeXhSUVVGUUxFTkJRVmdzUlVGQlVDeERRVVJyUWp0SFFVRndRanM3UVVGSlFTeGhRVUZWTzBGQlExSXNVVUZCU1N4RFFVRktPMUZCUVU4c1NVRkJTU3hGUVVGS0xFTkJSRU03UVVGRlVpeFRRVUZMTEVsQlFVa3NRMEZCU2l4RlFVRlBMRWxCUVVrc1MwRkJTeXhMUVVGTUxFVkJRVW9zUlVGQmEwSXNSMEZCT1VJc1JVRkJiVU03UVVGRGFrTXNWVUZCU1N4TlFVRk5MRVZCUVU0c1JVRkJWVHRCUVVOYUxHRkJRVXNzU1VGQlRDeERRVVJaTzA5QlFXUTdRVUZIUVN4WFFVRkxMRXRCUVVzc1IwRkJUQ3hEUVVGVExFTkJRVlFzUlVGQldTeFJRVUZhTEVWQlFVd3NRMEZLYVVNN1MwRkJia003TzBGQlQwRXNWMEZCVHl4UFFVRlBMRU5CUVZBc1IwRkJWeXhKUVVGWUxFTkJWRU03UjBGQlZqczdRVUZaUVN4VlFVRlJMR05CUVZJc1JVRkJkVUk3UVVGRGNrSXNVVUZCU1N4dFFrRkJiVUlzUlVGQmJrSXNRMEZFYVVJN08wRkJSM0pDTEZGQlFVa3NRMEZCU2l4RFFVaHhRanRCUVVseVFpeFRRVUZMTEVsQlFVa3NRMEZCU2l4RlFVRlBMRWxCUVVrc1pVRkJaU3hOUVVGbUxFVkJRWFZDTEVkQlFYWkRMRVZCUVRSRE8wRkJRekZETEZWQlFVa3NhMEpCUVd0Q0xFdEJRVXNzWVVGQllTeGxRVUZsTEVOQlFXWXNSVUZCYTBJc1NVRkJiRUlzUTBGQmJFSXNRMEZCTUVNc1pVRkJaU3hEUVVGbUxFTkJRVEZETEVOQlFXeENMRU5CUkhORE96dEJRVWN4UXl4WFFVRkpMRWxCUVVrc1NVRkJTaXhKUVVGWkxHVkJRV1VzUTBGQlppeEZRVUZyUWl4VlFVRnNRaXhGUVVFMlFqdEJRVU16UXl3d1FrRkJhMElzUzBGQlN5eGhRVUZoTEVsQlFXSXNRMEZCVEN4RFFVRjNRaXhsUVVGNFFpeERRVUZzUWl4RFFVUXlRenRQUVVFM1F6czdRVUZKUVN4NVFrRkJiVUlzYVVKQlFXbENMRTFCUVdwQ0xFTkJRWGRDTEdWQlFYaENMRU5CUVc1Q0xFTkJVREJETzB0QlFUVkRPenRCUVZWQkxGZEJRVThzWjBKQlFWQXNRMEZrY1VJN1IwRkJka0k3TzBGQmFVSkJMR3RDUVVGblFpeExRVUZvUWl4RlFVRnpRanRCUVVOd1FpeFhRVUZQTEUxQlFVMHNTMEZCVGl4RFFVUmhPMGRCUVhSQ096dEJRVWxCTEdkQ1FVRmpMRXRCUVdRc1JVRkJiMEk3UVVGRGJFSXNVVUZCUnl4TlFVRk5MRWxCUVU0c1MwRkJaU3hGUVVGbUxFVkJRV3RDTzBGQlEyNUNMR0ZCUVU4c1ZVRkJWU3hqUVVGV0xFTkJRWGxDTEUxQlFVMHNTMEZCVGl4RFFVRm9ReXhEUVVSdFFqdExRVUZ5UWl4TlFVVk5MRWxCUVVjc1RVRkJUU3hKUVVGT0xFdEJRV1VzUlVGQlppeEZRVUZyUWp0QlFVTjZRaXhoUVVGUExGVkJRVlVzWTBGQlZpeERRVUY1UWl4TlFVRk5MRXRCUVU0c1EwRkJhRU1zUTBGRWVVSTdTMEZCY2tJN08wRkJTVTRzVlVGQlRTeEpRVUZKTEV0QlFVb3NRMEZCVlN4M1FrRkJWaXhEUVVGT0xFTkJVR3RDTzBkQlFYQkNPenRCUVZWQkxHOUNRVUZyUWl4TFFVRnNRaXhGUVVGM1FqdEJRVU4wUWl4WFFVRlBMRTFCUVUwc1MwRkJUaXhEUVVGWkxFdEJRVm9zUTBGRVpUdEhRVUY0UWpzN1FVRkpRU3hwUWtGQlpTeExRVUZtTEVWQlFYRkNPMEZCUTI1Q0xGZEJRVThzVlVGQlZTeFhRVUZXTEVOQlFYTkNMRTFCUVUwc1MwRkJUaXhEUVVFM1FpeERRVVJ0UWp0SFFVRnlRanM3UVVGSlFTeGxRVUZoTEV0QlFXSXNSVUZCYlVJN1FVRkRha0lzVjBGQlR5eFZRVUZWTEZkQlFWWXNRMEZCYzBJc1RVRkJUU3hMUVVGT0xFTkJRVGRDTEVOQlJHbENPMGRCUVc1Q096dEJRVWxCTEdkQ1FVRmpMRXRCUVdRc1JVRkJiMEk3UVVGRGJFSXNWMEZCVHl4VlFVRlZMRmxCUVZZc1EwRkJkVUlzVFVGQlRTeExRVUZPTEVOQlFUbENMRU5CUkd0Q08wZEJRWEJDT3p0QlFVbEJMR2RDUVVGakxFdEJRV1FzUlVGQmIwSTdRVUZEYkVJc1YwRkJUeXhWUVVGVkxGbEJRVllzUTBGQmRVSXNUVUZCVFN4TFFVRk9MRU5CUVRsQ0xFTkJSR3RDTzBkQlFYQkNPenRCUVVsQkxHbENRVUZsTEV0QlFXWXNSVUZCY1VJN1FVRkRia0lzVjBGQlR5eEpRVUZMTEZWQlFVb3NRMEZCWlN4RFFVRkRMRXRCUVVRc1EwRkJaaXhEUVVGRUxFTkJRVEJDTEVOQlFURkNMRU5CUVZBc1EwRkViVUk3UjBGQmNrSTdPMEZCU1VFc2JVSkJRV2xDTEV0QlFXcENMRVZCUVhWQ08wRkJRM0pDTEZkQlFVOHNTMEZCVUN4RFFVUnhRanRIUVVGMlFqczdRVUZKUVN4cFFrRkJaU3hMUVVGbUxFVkJRWEZDTzBGQlEyNUNMRmRCUVU4c1MwRkJVQ3hEUVVSdFFqdEhRVUZ5UWpzN1FVRkpRU3hqUVVGWkxFdEJRVm9zUlVGQmEwSTdRVUZEYUVJc1YwRkJUeXhMUVVGUUxFTkJSR2RDTzBkQlFXeENPenRCUVVsQkxHbENRVUZsTEV0QlFXWXNSVUZCY1VJN1FVRkRia0lzVjBGQlR5eE5RVUZOTEU5QlFVNHNSVUZCVUN4RFFVUnRRanRIUVVGeVFqczdRVUZKUVN4bFFVRmhMRXRCUVdJc1JVRkJiVUk3UVVGRGFrSXNWMEZCVHl4TFFVRlFMRU5CUkdsQ08wZEJRVzVDT3p0QlFVbEJMR1ZCUVdFc1MwRkJZaXhGUVVGdFFqdEJRVU5xUWl4WFFVRlBMRXRCUVZBc1EwRkVhVUk3UjBGQmJrSTdPMEZCU1VFc1UwRkJUeXhQUVVGUUxFTkJRV1VzUzBGQlppeEZRVUZ4UWp0QlFVTnVRaXhYUVVGUExGVkJRVlVzU1VGQlZpeERRVUZsTEV0QlFXWXNSVUZCYzBJc1JVRkJSU3hSUVVGUkxGTkJRVklzUlVGQmJVSXNVVUZCVVN4RFFVRlNMRVZCUVZjc1VVRkJVU3hEUVVGU0xFVkJRWFJFTEVOQlFWQXNRMEZFYlVJN1IwRkJja0k3TzBGQlNVRXNVMEZCVHl4TFFVRlFMRU5CUVdFc1MwRkJZaXhGUVVGdFFqdEJRVU5xUWl4WFFVRlBMRlZCUVZVc1NVRkJWaXhEUVVGbExFdEJRV1lzUlVGQmMwSXNSVUZCUlN4UlFVRlJMRTlCUVZJc1JVRkJhVUlzVVVGQlVTeERRVUZTTEVWQlFWY3NVVUZCVVN4RlFVRlNMRVZCUVhCRUxFTkJRVkFzUTBGRWFVSTdSMEZCYmtJN08wRkJTVUVzVTBGQlR5eFRRVUZRTEVOQlFXbENMRXRCUVdwQ0xFVkJRWFZDTzBGQlEzSkNMRmRCUVU4c1ZVRkJWU3hKUVVGV0xFTkJRV1VzUzBGQlppeEZRVUZ6UWl4RlFVRkZMRkZCUVZFc1YwRkJVaXhGUVVGeFFpeFJRVUZSTEVOQlFWSXNSVUZCVnl4UlFVRlJMRTFCUVUwc1VVRkJUaXhGUVVGb1JTeERRVUZRTEVOQlJIRkNPMGRCUVhaQ096dEJRVWxCTEZOQlFVOHNTVUZCVUN4RFFVRlpMRXRCUVZvc1JVRkJhMEk3UVVGRGFFSXNWMEZCVHl4VlFVRlZMRk5CUVZZc1EwRkJiMElzUzBGQmNFSXNRMEZCVUN4RFFVUm5RanRIUVVGc1FqczdRVUZKUVN4VFFVRlBMRTFCUVZBc1EwRkJZeXhMUVVGa0xFVkJRVzlDTzBGQlEyeENMRmRCUVU4c1ZVRkJWU3hKUVVGV0xFTkJRV1VzUzBGQlppeEZRVUZ6UWl4RlFVRkZMRkZCUVZFc1VVRkJVaXhGUVVGclFpeFJRVUZSTEVOQlFWSXNSVUZCVnl4UlFVRlJMRTFCUVUwc1RVRkJUaXhGUVVFM1JDeERRVUZRTEVOQlJHdENPMGRCUVhCQ096dEJRVWxCTEZOQlFVOHNTMEZCVUN4RFFVRmhMRXRCUVdJc1JVRkJiVUk3UVVGRGFrSXNWMEZCVHl4VlFVRlZMRTFCUVZZc1EwRkJhVUlzUzBGQmFrSXNRMEZCVUN4RFFVUnBRanRIUVVGdVFqczdRVUZKUVN4VFFVRlBMRWxCUVZBc1EwRkJXU3hMUVVGYUxFVkJRV3RDTzBGQlEyaENMRmRCUVU4c1ZVRkJWU3hKUVVGV0xFTkJRV1VzUzBGQlppeEZRVUZ6UWl4RlFVRkZMRkZCUVZFc1RVRkJVaXhGUVVGblFpeFJRVUZSTEVOQlFWSXNSVUZCVnl4UlFVRlJMRTFCUVUwc1RVRkJUaXhGUVVFelJDeERRVUZRTEVOQlJHZENPMGRCUVd4Q096dEJRVWxCTEZOQlFVOHNTMEZCVUN4RFFVRmhMRXRCUVdJc1JVRkJiVUk3UVVGRGFrSXNWMEZCVHl4VlFVRlZMRWxCUVZZc1EwRkJaU3hMUVVGbUxFVkJRWE5DTEVWQlFVVXNVVUZCVVN4UFFVRlNMRVZCUVdsQ0xGRkJRVkVzUTBGQlVpeEZRVUZYTEZGQlFWRXNUVUZCVFN4TlFVRk9MRWRCUVdVc1EwRkJaaXhGUVVFMVJDeERRVUZRTEVOQlJHbENPMGRCUVc1Q096dEJRVWxCTEZOQlFVOHNTMEZCVUN4RFFVRmhMRXRCUVdJc1JVRkJiVUk3UVVGRGFrSXNWMEZCVHl4VlFVRlZMRWxCUVZZc1EwRkJaU3hMUVVGbUxFVkJRWE5DTEVWQlFVVXNVVUZCVVN4UFFVRlNMRVZCUVdsQ0xGRkJRVkVzUTBGQlVpeEZRVUZYTEZGQlFWRXNUVUZCVFN4TlFVRk9MRWRCUVdVc1EwRkJaaXhGUVVFMVJDeERRVUZRTEVOQlJHbENPMGRCUVc1Q096dEJRVWxCTEZOQlFVOHNUVUZCVUN4RFFVRmpMRXRCUVdRc1JVRkJiMEk3UVVGRGJFSXNWMEZCVHl4VlFVRlZMRWxCUVZZc1EwRkJaU3hMUVVGbUxFVkJRWE5DTEVWQlFYUkNMRVZCUVRCQ0xGRkJRVEZDTEVOQlFWQXNRMEZFYTBJN1IwRkJjRUk3TzBGQlNVRXNVMEZCVHl4UlFVRlFMRU5CUVdkQ0xFdEJRV2hDTEVWQlFYTkNPMEZCUTNCQ0xGZEJRVThzVlVGQlZTeEpRVUZXTEVOQlFXVXNTMEZCWml4RlFVRnpRaXhGUVVGMFFpeEZRVUV3UWl4VlFVRXhRaXhEUVVGUUxFTkJSRzlDTzBkQlFYUkNPenRCUVVsQkxGTkJRVThzVFVGQlVDeERRVUZqTEV0QlFXUXNSVUZCYjBJN1FVRkRiRUlzVjBGQlR5eFZRVUZWTEVsQlFWWXNRMEZCWlN4TFFVRm1MRVZCUVhOQ0xFVkJRWFJDTEVWQlFUQkNMRkZCUVRGQ0xFTkJRVkFzUTBGRWEwSTdSMEZCY0VJN08wRkJTVUVzVTBGQlR5eEhRVUZRTEVOQlFWY3NTMEZCV0N4RlFVRnBRanRCUVVObUxGZEJRVThzVlVGQlZTeEpRVUZXTEVOQlFXVXNTMEZCWml4RlFVRnpRaXhGUVVGMFFpeEZRVUV3UWl4TFFVRXhRaXhEUVVGUUxFTkJSR1U3UjBGQmFrSTdPMEZCU1VFc1UwRkJUeXhOUVVGUUxFTkJRV01zUzBGQlpDeEZRVUZ2UWp0QlFVTnNRaXhYUVVGUExGVkJRVlVzU1VGQlZpeERRVUZsTEV0QlFXWXNSVUZCYzBJc1JVRkJkRUlzUlVGQk1FSXNVVUZCTVVJc1EwRkJVQ3hEUVVSclFqdEhRVUZ3UWpzN1FVRkpRU3hUUVVGUExFbEJRVkFzUTBGQldTeExRVUZhTEVWQlFXMUNMRXRCUVc1Q0xFVkJRWGxDTzBGQlEzWkNMRmRCUVU4c1ZVRkJWU3hKUVVGV0xFTkJRV1VzUzBGQlppeEZRVUZ6UWl4RlFVRkRMRkZCUVZFc1MwRkJVaXhGUVVGMlFpeERRVUZRTEVOQlJIVkNPMGRCUVhwQ096dEJRVWxCTEZOQlFVOHNTVUZCVUN4RFFVRlpMRXRCUVZvc1JVRkJiVUlzUzBGQmJrSXNSVUZCZVVJN1FVRkRka0lzVjBGQlR5eFZRVUZWTEVsQlFWWXNRMEZCWlN4TFFVRm1MRVZCUVhOQ0xFVkJRVU1zVVVGQlVTeExRVUZTTEVWQlFYWkNMRU5CUVZBc1EwRkVkVUk3UjBGQmVrSTdPMEZCU1VFc1UwRkJUeXhKUVVGUUxFTkJRVmtzUzBGQldpeEZRVUZ0UWl4SFFVRnVRaXhGUVVGM1FpeG5Ra0ZCWjBJc1NVRkJhRUlzUlVGQmNVSTdRVUZETTBNc1VVRkJTU3haUVVGWkxFdEJRVm9zUTBGRWRVTTdPMEZCUnpORExGRkJRVWNzUlVGQlJTeHBRa0ZCYVVJc1RVRkJha0lzUTBGQlJpeEZRVUV5UWp0QlFVTTFRaXhyUWtGQldTeEZRVUZETEZOQlFWTXNTMEZCVkN4RlFVRm5RaXhqUVVGakxFVkJRV1FzUlVGQk4wSXNRMEZFTkVJN1MwRkJPVUk3TzBGQlNVRXNaMEpCUVZrc1QwRkJUeXhOUVVGUUxFTkJRV01zVTBGQlpDeEZRVUY1UWl4SFFVRjZRaXhEUVVGYUxFTkJVREpET3p0QlFWTXpReXhSUVVGSExHRkJRVWdzUlVGQmFVSTdRVUZEWml4blFrRkJWU3hWUVVGV0xFTkJRWEZDTEVsQlFYSkNMRU5CUVRCQ0xHRkJRVEZDTEVWQlJHVTdTMEZCYWtJN08wRkJTMEVzVjBGQlR5eFRRVUZRTEVOQlpESkRPMGRCUVRkRE96dEJRV2xDUVN4VFFVRlBMRmRCUVZBc1EwRkJiVUlzUjBGQmJrSXNSVUZCZDBJN1FVRkRkRUlzVVVGQlNTeFBRVUZQTEVWQlFWQXNRMEZFYTBJN1FVRkZkRUlzVTBGQlN5eEpRVUZKTEVsQlFVa3NRMEZCU2l4RlFVRlBMRWxCUVVrc1NVRkJTU3hOUVVGS0xFVkJRVmtzUjBGQmFFTXNSVUZCY1VNN1FVRkRia01zVlVGQlNTeFhRVUZYTEVsQlFVa3NWVUZCU2l4RFFVRmxMRU5CUVdZc1EwRkJXQ3hEUVVRclFqdEJRVVZ1UXl4VlFVRkpMRmRCUVZjc1NVRkJXQ3hGUVVGblFqdEJRVU5zUWl4aFFVRkxMRWxCUVV3c1EwRkJWU3hSUVVGV0xFVkJSR3RDTzA5QlFYQkNMRTFCUjBzc1NVRkJTU3hYUVVGWExFdEJRVmdzUlVGQmEwSTdRVUZEZWtJc1lVRkJTeXhKUVVGTUxFTkJRVlVzVDBGQlVTeFpRVUZaTEVOQlFWb3NSVUZEVWl4UFFVRlJMRmRCUVZjc1NVRkJXQ3hEUVVSc1FpeERRVVI1UWp0UFFVRjBRaXhOUVVsQkxFbEJRVWtzVjBGQlZ5eE5RVUZZTEVsQlFYRkNMRmxCUVZrc1RVRkJXaXhGUVVGdlFqdEJRVU5vUkN4aFFVRkxMRWxCUVV3c1EwRkJWU3hQUVVGUkxGbEJRVmtzUlVGQldpeEZRVU5TTEU5QlFWRXNVVUZCUXl4SlFVRlpMRU5CUVZvc1IwRkJhVUlzU1VGQmJFSXNSVUZEVWl4UFFVRlJMRmRCUVZjc1NVRkJXQ3hEUVVac1FpeERRVVJuUkRzN08wRkJRVGRETEZkQlRVRTdRVUZEU0RzN096dEJRVVJITEd0Q1FVdElMRWRCUVZjc1YwRkJWeXhEUVVGRkxGZEJRVmNzUzBGQldDeERRVUZFTEVsQlFYTkNMRVZCUVhSQ0xFZEJRMVlzU1VGQlNTeFZRVUZLTEVOQlFXVXNRMEZCWml4SlFVRnZRaXhMUVVGd1FpeERRVVJHTEVOQlRGSTdRVUZQU0N4bFFVRkxMRWxCUVV3c1EwRkJWU3hQUVVGUkxGbEJRVmtzUlVGQldpeEZRVU5TTEU5QlFWRXNVVUZCUXl4SlFVRlpMRVZCUVZvc1IwRkJhMElzU1VGQmJrSXNSVUZEVWl4UFFVRlJMRkZCUVVNc1NVRkJXU3hEUVVGYUxFZEJRV2xDTEVsQlFXeENMRVZCUTFJc1QwRkJVU3hYUVVGWExFbEJRVmdzUTBGSWJFSXNRMEZRUnp0VFFVNUJPMHRCVkZBN1FVRTBRa0VzVjBGQlR5eEpRVUZRTEVOQk9VSnpRanRIUVVGNFFqczdRVUZwUTBFc1UwRkJUeXhaUVVGUUxFTkJRVzlDTEVkQlFYQkNMRVZCUVhsQ08wRkJRM1pDTEZGQlFVa3NVVUZCVVN4RlFVRlNMRU5CUkcxQ08wRkJSWFpDTEZOQlFVc3NTVUZCU1N4SlFVRkpMRU5CUVVvc1JVRkJUeXhKUVVGSkxFbEJRVWtzVFVGQlNpeEZRVUZaTEVkQlFXaERMRVZCUVhGRE8wRkJRMjVETEZWQlFVa3NXVUZCV1N4SlFVRkpMRmRCUVVvc1EwRkJaMElzUTBGQmFFSXNRMEZCV2l4RFFVUXJRanM3UVVGSGJrTXNWVUZCUnl4aFFVRmhMRWRCUVdJc1JVRkJhVUk3UVVGRGJFSXNZMEZCVFN4SlFVRk9MRU5CUVZjc1EwRkJXQ3hGUVVSclFqdEJRVVZzUWl4alFVRk5MRWxCUVU0c1EwRkJWeXhUUVVGWUxFVkJSbXRDTzA5QlFYQkNMRTFCUjBzN1FVRkRTQ3hqUVVGTkxFbEJRVTRzUTBGQldTeFRRVUZETEVsQlFXRXNRMEZCWWl4SFFVRnJRaXhKUVVGdVFpeERRVUZhTEVOQlJFYzdRVUZGU0N4alFVRk5MRWxCUVU0c1EwRkJXU3haUVVGWkxFbEJRVm9zUTBGQldpeERRVVpITzA5QlNFdzdTMEZJUmp0QlFWZEJMRmRCUVU4c1MwRkJVQ3hEUVdKMVFqdEhRVUY2UWpzN1FVRnBRa0VzVTBGQlR5eFpRVUZRTEVOQlFXOUNMRWRCUVhCQ0xFVkJRWGxDTzBGQlEzWkNMRkZCUVVrc1VVRkJVU3hGUVVGU0xFTkJSRzFDTzBGQlJYWkNMRk5CUVVzc1NVRkJTU3hKUVVGSkxFTkJRVW9zUlVGQlR5eEpRVUZKTEVsQlFVa3NUVUZCU2l4RlFVRlpMRWRCUVdoRExFVkJRWEZETzBGQlEyNURMRlZCUVVrc1dVRkJXU3hKUVVGSkxGZEJRVW9zUTBGQlowSXNRMEZCYUVJc1EwRkJXaXhEUVVRclFqczdRVUZIYmtNc1ZVRkJSeXhoUVVGaExFZEJRV0lzUlVGQmFVSTdRVUZEYkVJc1kwRkJUU3hKUVVGT0xFTkJRVmNzUTBGQldDeEZRVVJyUWp0QlFVVnNRaXhqUVVGTkxFbEJRVTRzUTBGQlZ5eERRVUZZTEVWQlJtdENPMEZCUjJ4Q0xHTkJRVTBzU1VGQlRpeERRVUZYTEVOQlFWZ3NSVUZJYTBJN1FVRkpiRUlzWTBGQlRTeEpRVUZPTEVOQlFWY3NVMEZCV0N4RlFVcHJRanRQUVVGd1FpeE5RVXRMTzBGQlEwZ3NZMEZCVFN4SlFVRk9MRU5CUVZjc1EwRkJXQ3hGUVVSSE8wRkJSVWdzWTBGQlRTeEpRVUZPTEVOQlFWY3NRMEZCV0N4RlFVWkhPMEZCUjBnc1kwRkJUU3hKUVVGT0xFTkJRVmtzVTBGQlF5eEpRVUZoTEVOQlFXSXNSMEZCYTBJc1NVRkJia0lzUTBGQldpeERRVWhITzBGQlNVZ3NZMEZCVFN4SlFVRk9MRU5CUVZrc1dVRkJXU3hKUVVGYUxFTkJRVm9zUTBGS1J6dFBRVXhNTzB0QlNFWTdRVUZsUVN4WFFVRlBMRXRCUVZBc1EwRnFRblZDTzBkQlFYcENPenM3UVVGNFVHTXNVMEUyVVZBc1kwRkJVQ3hEUVVGelFpeERRVUYwUWl4RlFVRjVRanRCUVVOMlFpeFJRVUZKTEZGQlFWRXNSVUZCVWl4RFFVUnRRanM3UVVGSGRrSXNVVUZCU1N4TlFVRk5MRWxCUVVrc1YwRkJTaXhEUVVGblFpeERRVUZvUWl4RFFVRk9MRU5CU0cxQ08wRkJTWFpDTEZGQlFVc3NXVUZCU2l4RFFVRnBRaXhIUVVGcVFpeERRVUZFTEVOQlFYZENMRU5CUVhoQ0xFbEJRVFpDTEVOQlFUZENMRU5CU25WQ096dEJRVTEyUWl4UlFVRkpMR0ZCUVdFc1NVRkJTeXhYUVVGS0xFTkJRV2RDTEVkQlFXaENMRU5CUVVRc1EwRkJkVUlzUTBGQmRrSXNRMEZCWWl4RFFVNXRRanM3UVVGUmRrSXNWVUZCVFN4SlFVRk9MRU5CUVZrc1ZVRkJReXhKUVVGakxFVkJRV1FzUjBGQmIwSXNTVUZCY2tJc1EwRkJXaXhEUVZKMVFqdEJRVk4yUWl4VlFVRk5MRWxCUVU0c1EwRkJXU3hWUVVGRExFbEJRV01zUlVGQlpDeEhRVUZ2UWl4SlFVRnlRaXhEUVVGYUxFTkJWSFZDTzBGQlZYWkNMRlZCUVUwc1NVRkJUaXhEUVVGWkxGVkJRVU1zU1VGQll5eERRVUZrTEVkQlFXMUNMRWxCUVhCQ0xFTkJRVm9zUTBGV2RVSTdRVUZYZGtJc1ZVRkJUU3hKUVVGT0xFTkJRVmtzWVVGQllTeEpRVUZpTEVOQlFWb3NRMEZZZFVJN08wRkJZWFpDTEZkQlFVOHNTMEZCVUN4RFFXSjFRanRIUVVGNlFqczdRVUZuUWtFc1UwRkJUeXhqUVVGUUxFTkJRWE5DTEVOQlFYUkNMRVZCUVhsQ08wRkJRM1pDTEZGQlFVa3NVVUZCVVN4RlFVRlNMRU5CUkcxQ096dEJRVWQyUWl4UlFVRkpMRTFCUVUwc1NVRkJTU3hYUVVGS0xFTkJRV2RDTEVOQlFXaENMRU5CUVU0c1EwRkliVUk3UVVGSmRrSXNVVUZCU3l4WlFVRktMRU5CUVdsQ0xFZEJRV3BDTEVOQlFVUXNRMEZCZDBJc1EwRkJlRUlzU1VGQk5rSXNRMEZCTjBJc1EwRktkVUk3TzBGQlRYWkNMRkZCUVVrc1kwRkJZeXhKUVVGTExGZEJRVW9zUTBGQlowSXNSMEZCYUVJc1EwRkJSQ3hEUVVGMVFpeERRVUYyUWl4RFFVRmtMRU5CVG0xQ08wRkJUM1pDTEZGQlFVa3NZMEZCWXl4SlFVRkxMRmRCUVVvc1EwRkJaMElzUjBGQmFFSXNRMEZCUkN4RFFVRjFRaXhEUVVGMlFpeERRVUZrTEVOQlVHMUNPenRCUVZOMlFpeFZRVUZOTEVsQlFVNHNRMEZCV1N4WFFVRkRMRWxCUVdVc1JVRkJaaXhIUVVGeFFpeEpRVUYwUWl4RFFVRmFMRU5CVkhWQ08wRkJWWFpDTEZWQlFVMHNTVUZCVGl4RFFVRlpMRmRCUVVNc1NVRkJaU3hGUVVGbUxFZEJRWEZDTEVsQlFYUkNMRU5CUVZvc1EwRldkVUk3UVVGWGRrSXNWVUZCVFN4SlFVRk9MRU5CUVZrc1YwRkJReXhKUVVGbExFTkJRV1lzUjBGQmIwSXNTVUZCY2tJc1EwRkJXaXhEUVZoMVFqdEJRVmwyUWl4VlFVRk5MRWxCUVU0c1EwRkJXU3hqUVVGakxFbEJRV1FzUTBGQldpeERRVnAxUWpzN1FVRmpka0lzVlVGQlRTeEpRVUZPTEVOQlFWa3NWMEZCUXl4SlFVRmxMRVZCUVdZc1IwRkJjVUlzU1VGQmRFSXNRMEZCV2l4RFFXUjFRanRCUVdWMlFpeFZRVUZOTEVsQlFVNHNRMEZCV1N4WFFVRkRMRWxCUVdVc1JVRkJaaXhIUVVGeFFpeEpRVUYwUWl4RFFVRmFMRU5CWm5WQ08wRkJaMEoyUWl4VlFVRk5MRWxCUVU0c1EwRkJXU3hYUVVGRExFbEJRV1VzUTBGQlppeEhRVUZ2UWl4SlFVRnlRaXhEUVVGYUxFTkJhRUoxUWp0QlFXbENka0lzVlVGQlRTeEpRVUZPTEVOQlFWa3NZMEZCWXl4SlFVRmtMRU5CUVZvc1EwRnFRblZDT3p0QlFXMUNka0lzVjBGQlR5eExRVUZRTEVOQmJrSjFRanRIUVVGNlFqdERRVGRTUmpzN1FVRnZWRUVzWlVGQlpTeFRRVUZtSWl3aVptbHNaU0k2SW14cFlpOWpiM0psTDJKcGRGOXpkSEpwYm1jdWFuTWlMQ0p6YjNWeVkyVnpRMjl1ZEdWdWRDSTZXeUpqYkdGemN5QkNhWFJUZEhKcGJtY2dlMXh1SUNCamIyNXpkSEoxWTNSdmNpZ3VMaTVoY21kektYdGNiaUFnSUNCMGFHbHpMblpoYkhWbElEMGdUMkpxWldOMExtWnlaV1Y2WlNoMGFHbHpMbkJ5YjJObGMzTW9ZWEpuY3lrcE8xeHVJQ0FnSUhSb2FYTXViR1Z1WjNSb0lEMGdkR2hwY3k1MllXeDFaUzVzWlc1bmRHZzdYRzRnSUNBZ2RHaHBjeTVpYVhSZmMybDZaU0E5SUhSb2FYTXViR1Z1WjNSb0lDb2dPRHRjYmlBZ0lDQjBhR2x6TG1KNWRHVmZjMmw2WlNBOUlIUm9hWE11YkdWdVozUm9PMXh1SUNCOVhHNWNiaUFnWjJWMEtHbHVaR1Y0S1h0Y2JpQWdJQ0J5WlhSMWNtNGdkR2hwY3k1MllXeDFaVnRwYm1SbGVGMDdYRzRnSUgxY2JseHVJQ0JqYjNWdWRDZ3BlMXh1SUNBZ0lISmxkSFZ5YmlCMGFHbHpMblpoYkhWbExteGxibWQwYUR0Y2JpQWdmVnh1WEc0Z0lITnNhV05sS0hOMFlYSjBMQ0JsYm1RZ1BTQnVkV3hzS1h0Y2JpQWdJQ0JzWlhRZ2N5QTlJSFJvYVhNdWRtRnNkV1V1YzJ4cFkyVW9jM1JoY25Rc0lHVnVaQ2s3WEc0Z0lDQWdiR1YwSUcxeklEMGdjeTV0WVhBb0tHVnNaVzBwSUQwK0lFSnBkRk4wY21sdVp5NXBiblJsWjJWeUtHVnNaVzBwS1R0Y2JpQWdJQ0J5WlhSMWNtNGdibVYzSUVKcGRGTjBjbWx1WnlndUxpNXRjeWs3WEc0Z0lIMWNibHh1SUNCYlUzbHRZbTlzTG1sMFpYSmhkRzl5WFNncElIdGNiaUFnSUNCeVpYUjFjbTRnZEdocGN5NTJZV3gxWlZ0VGVXMWliMnd1YVhSbGNtRjBiM0pkS0NrN1hHNGdJSDFjYmx4dUlDQjBiMU4wY21sdVp5Z3BlMXh1SUNBZ0lIWmhjaUJwTENCeklEMGdYQ0pjSWp0Y2JpQWdJQ0JtYjNJZ0tHa2dQU0F3T3lCcElEd2dkR2hwY3k1amIzVnVkQ2dwT3lCcEt5c3BJSHRjYmlBZ0lDQWdJR2xtSUNoeklDRTlQU0JjSWx3aUtTQjdYRzRnSUNBZ0lDQWdJSE1nS3owZ1hDSXNJRndpTzF4dUlDQWdJQ0FnZlZ4dUlDQWdJQ0FnY3lBclBTQjBhR2x6TG1kbGRDaHBLUzUwYjFOMGNtbHVaeWdwTzF4dUlDQWdJSDFjYmx4dUlDQWdJSEpsZEhWeWJpQmNJanc4WENJZ0t5QnpJQ3NnWENJK1Bsd2lPMXh1SUNCOVhHNWNiaUFnY0hKdlkyVnpjeWhpYVhSVGRISnBibWRRWVhKMGN5bDdYRzRnSUNBZ2JHVjBJSEJ5YjJObGMzTmxaRjkyWVd4MVpYTWdQU0JiWFR0Y2JseHVJQ0FnSUhaaGNpQnBPMXh1SUNBZ0lHWnZjaUFvYVNBOUlEQTdJR2tnUENCaWFYUlRkSEpwYm1kUVlYSjBjeTVzWlc1bmRHZzdJR2tyS3lrZ2UxeHVJQ0FnSUNBZ2JHVjBJSEJ5YjJObGMzTmxaRjkyWVd4MVpTQTlJSFJvYVhOYkozQnliMk5sYzNOZkp5QXJJR0pwZEZOMGNtbHVaMUJoY25SelcybGRMblI1Y0dWZEtHSnBkRk4wY21sdVoxQmhjblJ6VzJsZEtUdGNibHh1SUNBZ0lDQWdabTl5S0d4bGRDQmhkSFJ5SUc5bUlHSnBkRk4wY21sdVoxQmhjblJ6VzJsZExtRjBkSEpwWW5WMFpYTXBlMXh1SUNBZ0lDQWdJQ0J3Y205alpYTnpaV1JmZG1Gc2RXVWdQU0IwYUdseld5ZHdjbTlqWlhOelh5Y2dLeUJoZEhSeVhTaHdjbTlqWlhOelpXUmZkbUZzZFdVcE8xeHVJQ0FnSUNBZ2ZWeHVYRzRnSUNBZ0lDQndjbTlqWlhOelpXUmZkbUZzZFdWeklEMGdjSEp2WTJWemMyVmtYM1poYkhWbGN5NWpiMjVqWVhRb2NISnZZMlZ6YzJWa1gzWmhiSFZsS1R0Y2JpQWdJQ0I5WEc1Y2JpQWdJQ0J5WlhSMWNtNGdjSEp2WTJWemMyVmtYM1poYkhWbGN6dGNiaUFnZlZ4dVhHNGdJSEJ5YjJObGMzTmZhVzUwWldkbGNpaDJZV3gxWlNsN1hHNGdJQ0FnY21WMGRYSnVJSFpoYkhWbExuWmhiSFZsTzF4dUlDQjlYRzVjYmlBZ2NISnZZMlZ6YzE5bWJHOWhkQ2gyWVd4MVpTbDdYRzRnSUNBZ2FXWW9kbUZzZFdVdWMybDZaU0E5UFQwZ05qUXBlMXh1SUNBZ0lDQWdjbVYwZFhKdUlFSnBkRk4wY21sdVp5NW1iRzloZERZMFZHOUNlWFJsY3loMllXeDFaUzUyWVd4MVpTazdYRzRnSUNBZ2ZXVnNjMlVnYVdZb2RtRnNkV1V1YzJsNlpTQTlQVDBnTXpJcGUxeHVJQ0FnSUNBZ2NtVjBkWEp1SUVKcGRGTjBjbWx1Wnk1bWJHOWhkRE15Vkc5Q2VYUmxjeWgyWVd4MVpTNTJZV3gxWlNrN1hHNGdJQ0FnZlZ4dVhHNGdJQ0FnZEdoeWIzY2dibVYzSUVWeWNtOXlLQ2RKYm5aaGJHbGtJSE5wZW1VZ1ptOXlJR1pzYjJGMEp5azdYRzRnSUgxY2JseHVJQ0J3Y205alpYTnpYMkpwZEhOMGNtbHVaeWgyWVd4MVpTbDdYRzRnSUNBZ2NtVjBkWEp1SUhaaGJIVmxMblpoYkhWbExuWmhiSFZsTzF4dUlDQjlYRzVjYmlBZ2NISnZZMlZ6YzE5aWFXNWhjbmtvZG1Gc2RXVXBlMXh1SUNBZ0lISmxkSFZ5YmlCQ2FYUlRkSEpwYm1jdWRHOVZWRVk0UVhKeVlYa29kbUZzZFdVdWRtRnNkV1VwTzF4dUlDQjlYRzVjYmlBZ2NISnZZMlZ6YzE5MWRHWTRLSFpoYkhWbEtYdGNiaUFnSUNCeVpYUjFjbTRnUW1sMFUzUnlhVzVuTG5SdlZWUkdPRUZ5Y21GNUtIWmhiSFZsTG5aaGJIVmxLVHRjYmlBZ2ZWeHVYRzRnSUhCeWIyTmxjM05mZFhSbU1UWW9kbUZzZFdVcGUxeHVJQ0FnSUhKbGRIVnliaUJDYVhSVGRISnBibWN1ZEc5VlZFWXhOa0Z5Y21GNUtIWmhiSFZsTG5aaGJIVmxLVHRjYmlBZ2ZWeHVYRzRnSUhCeWIyTmxjM05mZFhSbU16SW9kbUZzZFdVcGUxeHVJQ0FnSUhKbGRIVnliaUJDYVhSVGRISnBibWN1ZEc5VlZFWXpNa0Z5Y21GNUtIWmhiSFZsTG5aaGJIVmxLVHRjYmlBZ2ZWeHVYRzRnSUhCeWIyTmxjM05mYzJsbmJtVmtLSFpoYkhWbEtYdGNiaUFnSUNCeVpYUjFjbTRnS0c1bGR5QlZhVzUwT0VGeWNtRjVLRnQyWVd4MVpWMHBLVnN3WFR0Y2JpQWdmVnh1WEc0Z0lIQnliMk5sYzNOZmRXNXphV2R1WldRb2RtRnNkV1VwZTF4dUlDQWdJSEpsZEhWeWJpQjJZV3gxWlR0Y2JpQWdmVnh1WEc0Z0lIQnliMk5sYzNOZmJtRjBhWFpsS0haaGJIVmxLWHRjYmlBZ0lDQnlaWFIxY200Z2RtRnNkV1U3WEc0Z0lIMWNibHh1SUNCd2NtOWpaWE56WDJKcFp5aDJZV3gxWlNsN1hHNGdJQ0FnY21WMGRYSnVJSFpoYkhWbE8xeHVJQ0I5WEc1Y2JpQWdjSEp2WTJWemMxOXNhWFIwYkdVb2RtRnNkV1VwZTF4dUlDQWdJSEpsZEhWeWJpQjJZV3gxWlM1eVpYWmxjbk5sS0NrN1hHNGdJSDFjYmx4dUlDQndjbTlqWlhOelgzTnBlbVVvZG1Gc2RXVXBlMXh1SUNBZ0lISmxkSFZ5YmlCMllXeDFaVHRjYmlBZ2ZWeHVYRzRnSUhCeWIyTmxjM05mZFc1cGRDaDJZV3gxWlNsN1hHNGdJQ0FnY21WMGRYSnVJSFpoYkhWbE8xeHVJQ0I5WEc1Y2JpQWdjM1JoZEdsaklHbHVkR1ZuWlhJb2RtRnNkV1VwZTF4dUlDQWdJSEpsZEhWeWJpQkNhWFJUZEhKcGJtY3VkM0poY0NoMllXeDFaU3dnZXlBbmRIbHdaU2M2SUNkcGJuUmxaMlZ5Snl3Z0ozVnVhWFFuT2lBeExDQW5jMmw2WlNjNklEZ2dmU2s3WEc0Z0lIMWNibHh1SUNCemRHRjBhV01nWm14dllYUW9kbUZzZFdVcGUxeHVJQ0FnSUhKbGRIVnliaUJDYVhSVGRISnBibWN1ZDNKaGNDaDJZV3gxWlN3Z2V5QW5kSGx3WlNjNklDZG1iRzloZENjc0lDZDFibWwwSnpvZ01Td2dKM05wZW1Vbk9pQTJOQ0I5S1R0Y2JpQWdmVnh1WEc0Z0lITjBZWFJwWXlCaWFYUnpkSEpwYm1jb2RtRnNkV1VwZTF4dUlDQWdJSEpsZEhWeWJpQkNhWFJUZEhKcGJtY3VkM0poY0NoMllXeDFaU3dnZXlBbmRIbHdaU2M2SUNkaWFYUnpkSEpwYm1jbkxDQW5kVzVwZENjNklERXNJQ2R6YVhwbEp6b2dkbUZzZFdVdVltbDBYM05wZW1VZ2ZTazdYRzRnSUgxY2JseHVJQ0J6ZEdGMGFXTWdZbWwwY3loMllXeDFaU2w3WEc0Z0lDQWdjbVYwZFhKdUlFSnBkRk4wY21sdVp5NWlhWFJ6ZEhKcGJtY29kbUZzZFdVcE8xeHVJQ0I5WEc1Y2JpQWdjM1JoZEdsaklHSnBibUZ5ZVNoMllXeDFaU2w3WEc0Z0lDQWdjbVYwZFhKdUlFSnBkRk4wY21sdVp5NTNjbUZ3S0haaGJIVmxMQ0I3SUNkMGVYQmxKem9nSjJKcGJtRnllU2NzSUNkMWJtbDBKem9nT0N3Z0ozTnBlbVVuT2lCMllXeDFaUzVzWlc1bmRHZ2dmU2s3WEc0Z0lIMWNibHh1SUNCemRHRjBhV01nWW5sMFpYTW9kbUZzZFdVcGUxeHVJQ0FnSUhKbGRIVnliaUJDYVhSVGRISnBibWN1WW1sdVlYSjVLSFpoYkhWbEtUdGNiaUFnZlZ4dVhHNGdJSE4wWVhScFl5QjFkR1k0S0haaGJIVmxLWHRjYmlBZ0lDQnlaWFIxY200Z1FtbDBVM1J5YVc1bkxuZHlZWEFvZG1Gc2RXVXNJSHNnSjNSNWNHVW5PaUFuZFhSbU9DY3NJQ2QxYm1sMEp6b2dNU3dnSjNOcGVtVW5PaUIyWVd4MVpTNXNaVzVuZEdnZ0lIMHBPMXh1SUNCOVhHNWNiaUFnYzNSaGRHbGpJSFYwWmpFMktIWmhiSFZsS1h0Y2JpQWdJQ0J5WlhSMWNtNGdRbWwwVTNSeWFXNW5MbmR5WVhBb2RtRnNkV1VzSUhzZ0ozUjVjR1VuT2lBbmRYUm1NVFluTENBbmRXNXBkQ2M2SURFc0lDZHphWHBsSnpvZ2RtRnNkV1V1YkdWdVozUm9JQ29nTWlCOUtUdGNiaUFnZlZ4dVhHNGdJSE4wWVhScFl5QjFkR1l6TWloMllXeDFaU2w3WEc0Z0lDQWdjbVYwZFhKdUlFSnBkRk4wY21sdVp5NTNjbUZ3S0haaGJIVmxMQ0I3SUNkMGVYQmxKem9nSjNWMFpqTXlKeXdnSjNWdWFYUW5PaUF4TENBbmMybDZaU2M2SUhaaGJIVmxMbXhsYm1kMGFDQXFJRFFnZlNrN1hHNGdJSDFjYmx4dUlDQnpkR0YwYVdNZ2MybG5ibVZrS0haaGJIVmxLWHRjYmlBZ0lDQnlaWFIxY200Z1FtbDBVM1J5YVc1bkxuZHlZWEFvZG1Gc2RXVXNJSHQ5TENBbmMybG5ibVZrSnlrN1hHNGdJSDFjYmx4dUlDQnpkR0YwYVdNZ2RXNXphV2R1WldRb2RtRnNkV1VwZTF4dUlDQWdJSEpsZEhWeWJpQkNhWFJUZEhKcGJtY3VkM0poY0NoMllXeDFaU3dnZTMwc0lDZDFibk5wWjI1bFpDY3BPMXh1SUNCOVhHNWNiaUFnYzNSaGRHbGpJRzVoZEdsMlpTaDJZV3gxWlNsN1hHNGdJQ0FnY21WMGRYSnVJRUpwZEZOMGNtbHVaeTUzY21Gd0tIWmhiSFZsTENCN2ZTd2dKMjVoZEdsMlpTY3BPMXh1SUNCOVhHNWNiaUFnYzNSaGRHbGpJR0pwWnloMllXeDFaU2w3WEc0Z0lDQWdjbVYwZFhKdUlFSnBkRk4wY21sdVp5NTNjbUZ3S0haaGJIVmxMQ0I3ZlN3Z0oySnBaeWNwTzF4dUlDQjlYRzVjYmlBZ2MzUmhkR2xqSUd4cGRIUnNaU2gyWVd4MVpTbDdYRzRnSUNBZ2NtVjBkWEp1SUVKcGRGTjBjbWx1Wnk1M2NtRndLSFpoYkhWbExDQjdmU3dnSjJ4cGRIUnNaU2NwTzF4dUlDQjlYRzVjYmlBZ2MzUmhkR2xqSUhOcGVtVW9kbUZzZFdVc0lHTnZkVzUwS1h0Y2JpQWdJQ0J5WlhSMWNtNGdRbWwwVTNSeWFXNW5MbmR5WVhBb2RtRnNkV1VzSUhzbmMybDZaU2M2SUdOdmRXNTBmU2s3WEc0Z0lIMWNibHh1SUNCemRHRjBhV01nZFc1cGRDaDJZV3gxWlN3Z1kyOTFiblFwZTF4dUlDQWdJSEpsZEhWeWJpQkNhWFJUZEhKcGJtY3VkM0poY0NoMllXeDFaU3dnZXlkMWJtbDBKem9nWTI5MWJuUjlLVHRjYmlBZ2ZWeHVYRzRnSUhOMFlYUnBZeUIzY21Gd0tIWmhiSFZsTENCdmNIUXNJRzVsZDE5aGRIUnlhV0oxZEdVZ1BTQnVkV3hzS1h0Y2JpQWdJQ0JzWlhRZ2RHaGxYM1poYkhWbElEMGdkbUZzZFdVN1hHNWNiaUFnSUNCcFppZ2hLSFpoYkhWbElHbHVjM1JoYm1ObGIyWWdUMkpxWldOMEtTbDdYRzRnSUNBZ0lDQjBhR1ZmZG1Gc2RXVWdQU0I3SjNaaGJIVmxKem9nZG1Gc2RXVXNJQ2RoZEhSeWFXSjFkR1Z6SnpvZ1cxMTlPMXh1SUNBZ0lIMWNibHh1SUNBZ0lIUm9aVjkyWVd4MVpTQTlJRTlpYW1WamRDNWhjM05wWjI0b2RHaGxYM1poYkhWbExDQnZjSFFwTzF4dVhHNGdJQ0FnYVdZb2JtVjNYMkYwZEhKcFluVjBaU2w3WEc0Z0lDQWdJQ0IwYUdWZmRtRnNkV1V1WVhSMGNtbGlkWFJsY3k1d2RYTm9LRzVsZDE5aGRIUnlhV0oxZEdVcE8xeHVJQ0FnSUgxY2JseHVYRzRnSUNBZ2NtVjBkWEp1SUhSb1pWOTJZV3gxWlR0Y2JpQWdmVnh1WEc0Z0lITjBZWFJwWXlCMGIxVlVSamhCY25KaGVTaHpkSElwSUh0Y2JpQWdJQ0IyWVhJZ2RYUm1PQ0E5SUZ0ZE8xeHVJQ0FnSUdadmNpQW9kbUZ5SUdrZ1BTQXdPeUJwSUR3Z2MzUnlMbXhsYm1kMGFEc2dhU3NyS1NCN1hHNGdJQ0FnSUNCMllYSWdZMmhoY21OdlpHVWdQU0J6ZEhJdVkyaGhja052WkdWQmRDaHBLVHRjYmlBZ0lDQWdJR2xtSUNoamFHRnlZMjlrWlNBOElEQjRPREFwZTF4dUlDQWdJQ0FnSUNCMWRHWTRMbkIxYzJnb1kyaGhjbU52WkdVcE8xeHVJQ0FnSUNBZ2ZWeHVJQ0FnSUNBZ1pXeHpaU0JwWmlBb1kyaGhjbU52WkdVZ1BDQXdlRGd3TUNrZ2UxeHVJQ0FnSUNBZ0lDQjFkR1k0TG5CMWMyZ29NSGhqTUNCOElDaGphR0Z5WTI5a1pTQStQaUEyS1N4Y2JpQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lEQjRPREFnZkNBb1kyaGhjbU52WkdVZ0ppQXdlRE5tS1NrN1hHNGdJQ0FnSUNCOVhHNGdJQ0FnSUNCbGJITmxJR2xtSUNoamFHRnlZMjlrWlNBOElEQjRaRGd3TUNCOGZDQmphR0Z5WTI5a1pTQStQU0F3ZUdVd01EQXBJSHRjYmlBZ0lDQWdJQ0FnZFhSbU9DNXdkWE5vS0RCNFpUQWdmQ0FvWTJoaGNtTnZaR1VnUGo0Z01USXBMRnh1SUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnTUhnNE1DQjhJQ2dvWTJoaGNtTnZaR1VnUGo0Z05pa2dKaUF3ZURObUtTeGNiaUFnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJREI0T0RBZ2ZDQW9ZMmhoY21OdlpHVWdKaUF3ZURObUtTazdYRzRnSUNBZ0lDQjlYRzRnSUNBZ0lDQXZMeUJ6ZFhKeWIyZGhkR1VnY0dGcGNseHVJQ0FnSUNBZ1pXeHpaU0I3WEc0Z0lDQWdJQ0FnSUdrckt6dGNiaUFnSUNBZ0lDQWdMeThnVlZSR0xURTJJR1Z1WTI5a1pYTWdNSGd4TURBd01DMHdlREV3UmtaR1JpQmllVnh1SUNBZ0lDQWdJQ0F2THlCemRXSjBjbUZqZEdsdVp5QXdlREV3TURBd0lHRnVaQ0J6Y0d4cGRIUnBibWNnZEdobFhHNGdJQ0FnSUNBZ0lDOHZJREl3SUdKcGRITWdiMllnTUhnd0xUQjRSa1pHUmtZZ2FXNTBieUIwZDI4Z2FHRnNkbVZ6WEc0Z0lDQWdJQ0FnSUdOb1lYSmpiMlJsSUQwZ01IZ3hNREF3TUNBcklDZ29LR05vWVhKamIyUmxJQ1lnTUhnelptWXBJRHc4SURFd0tWeHVJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdmQ0FvYzNSeUxtTm9ZWEpEYjJSbFFYUW9hU2tnSmlBd2VETm1aaWtwTzF4dUlDQWdJQ0FnSUNCMWRHWTRMbkIxYzJnb01IaG1NQ0I4SUNoamFHRnlZMjlrWlNBK1BpQXhPQ2tzWEc0Z0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBd2VEZ3dJSHdnS0NoamFHRnlZMjlrWlNBK1BpQXhNaWtnSmlBd2VETm1LU3hjYmlBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSURCNE9EQWdmQ0FvS0dOb1lYSmpiMlJsSUQ0K0lEWXBJQ1lnTUhnelppa3NYRzRnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0F3ZURnd0lId2dLR05vWVhKamIyUmxJQ1lnTUhnelppa3BPMXh1SUNBZ0lDQWdmVnh1SUNBZ0lIMWNiaUFnSUNCeVpYUjFjbTRnZFhSbU9EdGNiaUFnZlZ4dVhHNGdJSE4wWVhScFl5QjBiMVZVUmpFMlFYSnlZWGtvYzNSeUtTQjdYRzRnSUNBZ2RtRnlJSFYwWmpFMklEMGdXMTA3WEc0Z0lDQWdabTl5SUNoMllYSWdhU0E5SURBN0lHa2dQQ0J6ZEhJdWJHVnVaM1JvT3lCcEt5c3BJSHRjYmlBZ0lDQWdJSFpoY2lCamIyUmxVRzlwYm5RZ1BTQnpkSEl1WTI5a1pWQnZhVzUwUVhRb2FTazdYRzVjYmlBZ0lDQWdJR2xtS0dOdlpHVlFiMmx1ZENBOFBTQXlOVFVwZTF4dUlDQWdJQ0FnSUNCMWRHWXhOaTV3ZFhOb0tEQXBPMXh1SUNBZ0lDQWdJQ0IxZEdZeE5pNXdkWE5vS0dOdlpHVlFiMmx1ZENrN1hHNGdJQ0FnSUNCOVpXeHpaWHRjYmlBZ0lDQWdJQ0FnZFhSbU1UWXVjSFZ6YUNnb0tHTnZaR1ZRYjJsdWRDQStQaUE0S1NBbUlEQjRSa1lwS1R0Y2JpQWdJQ0FnSUNBZ2RYUm1NVFl1Y0hWemFDZ29ZMjlrWlZCdmFXNTBJQ1lnTUhoR1Jpa3BPMXh1SUNBZ0lDQWdmVnh1SUNBZ0lIMWNiaUFnSUNCeVpYUjFjbTRnZFhSbU1UWTdYRzRnSUgxY2JseHVYRzRnSUhOMFlYUnBZeUIwYjFWVVJqTXlRWEp5WVhrb2MzUnlLU0I3WEc0Z0lDQWdkbUZ5SUhWMFpqTXlJRDBnVzEwN1hHNGdJQ0FnWm05eUlDaDJZWElnYVNBOUlEQTdJR2tnUENCemRISXViR1Z1WjNSb095QnBLeXNwSUh0Y2JpQWdJQ0FnSUhaaGNpQmpiMlJsVUc5cGJuUWdQU0J6ZEhJdVkyOWtaVkJ2YVc1MFFYUW9hU2s3WEc1Y2JpQWdJQ0FnSUdsbUtHTnZaR1ZRYjJsdWRDQThQU0F5TlRVcGUxeHVJQ0FnSUNBZ0lDQjFkR1l6TWk1d2RYTm9LREFwTzF4dUlDQWdJQ0FnSUNCMWRHWXpNaTV3ZFhOb0tEQXBPMXh1SUNBZ0lDQWdJQ0IxZEdZek1pNXdkWE5vS0RBcE8xeHVJQ0FnSUNBZ0lDQjFkR1l6TWk1d2RYTm9LR052WkdWUWIybHVkQ2s3WEc0Z0lDQWdJQ0I5Wld4elpYdGNiaUFnSUNBZ0lDQWdkWFJtTXpJdWNIVnphQ2d3S1R0Y2JpQWdJQ0FnSUNBZ2RYUm1Nekl1Y0hWemFDZ3dLVHRjYmlBZ0lDQWdJQ0FnZFhSbU16SXVjSFZ6YUNnb0tHTnZaR1ZRYjJsdWRDQStQaUE0S1NBbUlEQjRSa1lwS1R0Y2JpQWdJQ0FnSUNBZ2RYUm1Nekl1Y0hWemFDZ29ZMjlrWlZCdmFXNTBJQ1lnTUhoR1Jpa3BPMXh1SUNBZ0lDQWdmVnh1SUNBZ0lIMWNiaUFnSUNCeVpYUjFjbTRnZFhSbU16STdYRzRnSUgxY2JseHVJQ0F2TDJoMGRIQTZMeTl6ZEdGamEyOTJaWEptYkc5M0xtTnZiUzl4ZFdWemRHbHZibk12TWpBd016UTVNeTlxWVhaaGMyTnlhWEIwTFdac2IyRjBMV1p5YjIwdGRHOHRZbWwwYzF4dUlDQnpkR0YwYVdNZ1pteHZZWFF6TWxSdlFubDBaWE1vWmlrZ2UxeHVJQ0FnSUhaaGNpQmllWFJsY3lBOUlGdGRPMXh1WEc0Z0lDQWdkbUZ5SUdKMVppQTlJRzVsZHlCQmNuSmhlVUoxWm1abGNpZzBLVHRjYmlBZ0lDQW9ibVYzSUVac2IyRjBNekpCY25KaGVTaGlkV1lwS1Zzd1hTQTlJR1k3WEc1Y2JpQWdJQ0JzWlhRZ2FXNTBWbVZ5YzJsdmJpQTlJQ2h1WlhjZ1ZXbHVkRE15UVhKeVlYa29ZblZtS1NsYk1GMDdYRzVjYmlBZ0lDQmllWFJsY3k1d2RYTm9LQ2dvYVc1MFZtVnljMmx2YmlBK1BpQXlOQ2tnSmlBd2VFWkdLU2s3WEc0Z0lDQWdZbmwwWlhNdWNIVnphQ2dvS0dsdWRGWmxjbk5wYjI0Z1BqNGdNVFlwSUNZZ01IaEdSaWtwTzF4dUlDQWdJR0o1ZEdWekxuQjFjMmdvS0NocGJuUldaWEp6YVc5dUlENCtJRGdwSUNZZ01IaEdSaWtwTzF4dUlDQWdJR0o1ZEdWekxuQjFjMmdvS0dsdWRGWmxjbk5wYjI0Z0ppQXdlRVpHS1NrN1hHNWNiaUFnSUNCeVpYUjFjbTRnWW5sMFpYTTdYRzRnSUgxY2JseHVJQ0J6ZEdGMGFXTWdabXh2WVhRMk5GUnZRbmwwWlhNb1ppa2dlMXh1SUNBZ0lIWmhjaUJpZVhSbGN5QTlJRnRkTzF4dVhHNGdJQ0FnZG1GeUlHSjFaaUE5SUc1bGR5QkJjbkpoZVVKMVptWmxjaWc0S1R0Y2JpQWdJQ0FvYm1WM0lFWnNiMkYwTmpSQmNuSmhlU2hpZFdZcEtWc3dYU0E5SUdZN1hHNWNiaUFnSUNCMllYSWdhVzUwVm1WeWMybHZiakVnUFNBb2JtVjNJRlZwYm5Rek1rRnljbUY1S0dKMVppa3BXekJkTzF4dUlDQWdJSFpoY2lCcGJuUldaWEp6YVc5dU1pQTlJQ2h1WlhjZ1ZXbHVkRE15UVhKeVlYa29ZblZtS1NsYk1WMDdYRzVjYmlBZ0lDQmllWFJsY3k1d2RYTm9LQ2dvYVc1MFZtVnljMmx2YmpJZ1BqNGdNalFwSUNZZ01IaEdSaWtwTzF4dUlDQWdJR0o1ZEdWekxuQjFjMmdvS0NocGJuUldaWEp6YVc5dU1pQStQaUF4TmlrZ0ppQXdlRVpHS1NrN1hHNGdJQ0FnWW5sMFpYTXVjSFZ6YUNnb0tHbHVkRlpsY25OcGIyNHlJRDQrSURncElDWWdNSGhHUmlrcE8xeHVJQ0FnSUdKNWRHVnpMbkIxYzJnb0tHbHVkRlpsY25OcGIyNHlJQ1lnTUhoR1Jpa3BPMXh1WEc0Z0lDQWdZbmwwWlhNdWNIVnphQ2dvS0dsdWRGWmxjbk5wYjI0eElENCtJREkwS1NBbUlEQjRSa1lwS1R0Y2JpQWdJQ0JpZVhSbGN5NXdkWE5vS0Nnb2FXNTBWbVZ5YzJsdmJqRWdQajRnTVRZcElDWWdNSGhHUmlrcE8xeHVJQ0FnSUdKNWRHVnpMbkIxYzJnb0tDaHBiblJXWlhKemFXOXVNU0ErUGlBNEtTQW1JREI0UmtZcEtUdGNiaUFnSUNCaWVYUmxjeTV3ZFhOb0tDaHBiblJXWlhKemFXOXVNU0FtSURCNFJrWXBLVHRjYmx4dUlDQWdJSEpsZEhWeWJpQmllWFJsY3p0Y2JpQWdmVnh1ZlZ4dVhHNWxlSEJ2Y25RZ1pHVm1ZWFZzZENCQ2FYUlRkSEpwYm1jN1hHNGlYU3dpYzI5MWNtTmxVbTl2ZENJNklpOXpiM1Z5WTJVdkluMD1cbiIsIlxuZXhwb3J0IGNsYXNzIFZhcmlhYmxlIHtcblxuICBjb25zdHJ1Y3RvcihkZWZhdWx0X3ZhbHVlID0gU3ltYm9sLmZvcihcImVsaXhpcnNjcmlwdC5ub192YWx1ZVwiKSkge1xuICAgIHRoaXMuZGVmYXVsdF92YWx1ZSA9IGRlZmF1bHRfdmFsdWU7XG4gIH1cbn1cblxuZXhwb3J0IGNsYXNzIFdpbGRjYXJkIHtcbiAgY29uc3RydWN0b3IoKSB7fVxufVxuXG5leHBvcnQgY2xhc3MgU3RhcnRzV2l0aCB7XG5cbiAgY29uc3RydWN0b3IocHJlZml4KSB7XG4gICAgdGhpcy5wcmVmaXggPSBwcmVmaXg7XG4gIH1cbn1cblxuZXhwb3J0IGNsYXNzIENhcHR1cmUge1xuXG4gIGNvbnN0cnVjdG9yKHZhbHVlKSB7XG4gICAgdGhpcy52YWx1ZSA9IHZhbHVlO1xuICB9XG59XG5cbmV4cG9ydCBjbGFzcyBIZWFkVGFpbCB7XG5cbiAgY29uc3RydWN0b3IoaGVhZCA9IG51bGwsIHRhaWwgPSBudWxsKSB7XG4gICAgdGhpcy5oZWFkID0gaGVhZDtcbiAgICB0aGlzLnRhaWwgPSB0YWlsO1xuICB9XG59XG5cbmV4cG9ydCBjbGFzcyBUeXBlIHtcblxuICBjb25zdHJ1Y3Rvcih0eXBlLCBvYmpQYXR0ZXJuID0ge30pIHtcbiAgICB0aGlzLnR5cGUgPSB0eXBlO1xuICAgIHRoaXMub2JqUGF0dGVybiA9IG9ialBhdHRlcm47XG4gIH1cbn1cblxuZXhwb3J0IGNsYXNzIEJvdW5kIHtcblxuICBjb25zdHJ1Y3Rvcih2YWx1ZSkge1xuICAgIHRoaXMudmFsdWUgPSB2YWx1ZTtcbiAgfVxufVxuXG5leHBvcnQgY2xhc3MgQml0U3RyaW5nTWF0Y2gge1xuXG4gIGNvbnN0cnVjdG9yKC4uLnZhbHVlcykge1xuICAgIHRoaXMudmFsdWVzID0gdmFsdWVzO1xuICB9XG5cbiAgbGVuZ3RoKCkge1xuICAgIHJldHVybiB2YWx1ZXMubGVuZ3RoO1xuICB9XG5cbiAgYml0X3NpemUoKSB7XG4gICAgcmV0dXJuIHRoaXMuYnl0ZV9zaXplKCkgKiA4O1xuICB9XG5cbiAgYnl0ZV9zaXplKCkge1xuICAgIGxldCBzID0gMDtcblxuICAgIGZvciAobGV0IHZhbCBvZiB0aGlzLnZhbHVlcykge1xuICAgICAgcyA9IHMgKyB2YWwudW5pdCAqIHZhbC5zaXplIC8gODtcbiAgICB9XG5cbiAgICByZXR1cm4gcztcbiAgfVxuXG4gIGdldFZhbHVlKGluZGV4KSB7XG4gICAgcmV0dXJuIHRoaXMudmFsdWVzKGluZGV4KTtcbiAgfVxuXG4gIGdldFNpemVPZlZhbHVlKGluZGV4KSB7XG4gICAgbGV0IHZhbCA9IHRoaXMuZ2V0VmFsdWUoaW5kZXgpO1xuICAgIHJldHVybiB2YWwudW5pdCAqIHZhbC5zaXplO1xuICB9XG5cbiAgZ2V0VHlwZU9mVmFsdWUoaW5kZXgpIHtcbiAgICByZXR1cm4gdGhpcy5nZXRWYWx1ZShpbmRleCkudHlwZTtcbiAgfVxufVxuXG5leHBvcnQgZnVuY3Rpb24gdmFyaWFibGUoZGVmYXVsdF92YWx1ZSA9IFN5bWJvbC5mb3IoXCJlbGl4aXJzY3JpcHQubm9fdmFsdWVcIikpIHtcbiAgcmV0dXJuIG5ldyBWYXJpYWJsZShkZWZhdWx0X3ZhbHVlKTtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIHdpbGRjYXJkKCkge1xuICByZXR1cm4gbmV3IFdpbGRjYXJkKCk7XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBzdGFydHNXaXRoKHByZWZpeCkge1xuICByZXR1cm4gbmV3IFN0YXJ0c1dpdGgocHJlZml4KTtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIGNhcHR1cmUodmFsdWUpIHtcbiAgcmV0dXJuIG5ldyBDYXB0dXJlKHZhbHVlKTtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIGhlYWRUYWlsKGhlYWQgPSBudWxsLCB0YWlsID0gbnVsbCkge1xuICByZXR1cm4gbmV3IEhlYWRUYWlsKGhlYWQsIHRhaWwpO1xufVxuXG5leHBvcnQgZnVuY3Rpb24gdHlwZSh0eXBlLCBvYmpQYXR0ZXJuID0ge30pIHtcbiAgcmV0dXJuIG5ldyBUeXBlKHR5cGUsIG9ialBhdHRlcm4pO1xufVxuXG5leHBvcnQgZnVuY3Rpb24gYm91bmQodmFsdWUpIHtcbiAgcmV0dXJuIG5ldyBCb3VuZCh2YWx1ZSk7XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBiaXRTdHJpbmdNYXRjaCguLi52YWx1ZXMpIHtcbiAgcmV0dXJuIG5ldyBCaXRTdHJpbmdNYXRjaCguLi52YWx1ZXMpO1xufVxuLy8jIHNvdXJjZU1hcHBpbmdVUkw9ZGF0YTphcHBsaWNhdGlvbi9qc29uO2Jhc2U2NCxleUoyWlhKemFXOXVJam96TENKemIzVnlZMlZ6SWpwYklteHBZaTlqYjNKbEwzQmhkSFJsY201ekwzUjVjR1Z6TG1weklsMHNJbTVoYldWeklqcGJYU3dpYldGd2NHbHVaM01pT2lJN1FVRkRRU3hQUVVGUExFMUJRVTBzVVVGQlRpeERRVUZsT3p0QlFVZHdRaXhqUVVGblF5eG5Ra0ZCUlN4UFFVRlBMRWRCUVZBc1EwRkJWeXgxUWtGQldDeERRVUZHTEVWQlFYVkRPMEZCUTNKRkxGTkJRVXNzWVVGQlRDeEhRVUZ4UWl4aFFVRnlRaXhEUVVSeFJUdEhRVUYyUlR0RFFVaExPenRCUVZGUUxFOUJRVThzVFVGQlRTeFJRVUZPTEVOQlFXVTdRVUZEY0VJc1owSkJRV01zUlVGQlpEdERRVVJMT3p0QlFVdFFMRTlCUVU4c1RVRkJUU3hWUVVGT0xFTkJRV2xDT3p0QlFVZDBRaXhqUVVGWkxFMUJRVm9zUlVGQk5FSTdRVUZETVVJc1UwRkJTeXhOUVVGTUxFZEJRV01zVFVGQlpDeERRVVF3UWp0SFFVRTFRanREUVVoTE96dEJRVkZRTEU5QlFVOHNUVUZCVFN4UFFVRk9MRU5CUVdNN08wRkJSMjVDTEdOQlFWa3NTMEZCV2l4RlFVRjNRanRCUVVOMFFpeFRRVUZMTEV0QlFVd3NSMEZCWVN4TFFVRmlMRU5CUkhOQ08wZEJRWGhDTzBOQlNFczdPMEZCVVZBc1QwRkJUeXhOUVVGTkxGRkJRVTRzUTBGQlpUczdRVUZKY0VJc1kwRkJjMElzVDBGQlJTeEpRVUZHTEVWQlFXdENMRTlCUVVVc1NVRkJSaXhGUVVGUk8wRkJRemxETEZOQlFVc3NTVUZCVEN4SFFVRlpMRWxCUVZvc1EwRkVPRU03UVVGRk9VTXNVMEZCU3l4SlFVRk1MRWRCUVZrc1NVRkJXaXhEUVVZNFF6dEhRVUZvUkR0RFFVcExPenRCUVZWUUxFOUJRVThzVFVGQlRTeEpRVUZPTEVOQlFWYzdPMEZCU1doQ0xHTkJRVmtzU1VGQldpeEZRVUV3UXl4aFFVRkZMRVZCUVVZc1JVRkJUVHRCUVVNNVF5eFRRVUZMTEVsQlFVd3NSMEZCV1N4SlFVRmFMRU5CUkRoRE8wRkJSVGxETEZOQlFVc3NWVUZCVEN4SFFVRnJRaXhWUVVGc1FpeERRVVk0UXp0SFFVRm9SRHREUVVwTE96dEJRVlZRTEU5QlFVOHNUVUZCVFN4TFFVRk9MRU5CUVZrN08wRkJSMnBDTEdOQlFWa3NTMEZCV2l4RlFVRjNRanRCUVVOMFFpeFRRVUZMTEV0QlFVd3NSMEZCWVN4TFFVRmlMRU5CUkhOQ08wZEJRWGhDTzBOQlNFczdPMEZCVVZBc1QwRkJUeXhOUVVGTkxHTkJRVTRzUTBGQmNVSTdPMEZCUnpGQ0xHTkJRVmtzUjBGQlJ5eE5RVUZJTEVWQlFYbENPMEZCUTI1RExGTkJRVXNzVFVGQlRDeEhRVUZqTEUxQlFXUXNRMEZFYlVNN1IwRkJja003TzBGQlNVRXNWMEZCVXp0QlFVTlFMRmRCUVU4c1QwRkJUeXhOUVVGUUxFTkJSRUU3UjBGQlZEczdRVUZKUVN4aFFVRlhPMEZCUTFRc1YwRkJUeXhMUVVGTExGTkJRVXdzUzBGQmJVSXNRMEZCYmtJc1EwRkVSVHRIUVVGWU96dEJRVWxCTEdOQlFWYzdRVUZEVkN4UlFVRkpMRWxCUVVrc1EwRkJTaXhEUVVSTE96dEJRVWRVTEZOQlFVa3NTVUZCU1N4SFFVRktMRWxCUVZjc1MwRkJTeXhOUVVGTUxFVkJRVms3UVVGRGVrSXNWVUZCU1N4SlFVRkxMRWRCUVVNc1EwRkJTU3hKUVVGS0xFZEJRVmNzU1VGQlNTeEpRVUZLTEVkQlFWVXNRMEZCZEVJc1EwRkVaMEk3UzBGQk0wSTdPMEZCU1VFc1YwRkJUeXhEUVVGUUxFTkJVRk03UjBGQldEczdRVUZWUVN4WFFVRlRMRXRCUVZRc1JVRkJaVHRCUVVOaUxGZEJRVThzUzBGQlN5eE5RVUZNTEVOQlFWa3NTMEZCV2l4RFFVRlFMRU5CUkdFN1IwRkJaanM3UVVGSlFTeHBRa0ZCWlN4TFFVRm1MRVZCUVhGQ08wRkJRMjVDTEZGQlFVa3NUVUZCVFN4TFFVRkxMRkZCUVV3c1EwRkJZeXhMUVVGa0xFTkJRVTRzUTBGRVpUdEJRVVZ1UWl4WFFVRlBMRWxCUVVrc1NVRkJTaXhIUVVGWExFbEJRVWtzU1VGQlNpeERRVVpETzBkQlFYSkNPenRCUVV0QkxHbENRVUZsTEV0QlFXWXNSVUZCY1VJN1FVRkRia0lzVjBGQlR5eExRVUZMTEZGQlFVd3NRMEZCWXl4TFFVRmtMRVZCUVhGQ0xFbEJRWEpDTEVOQlJGazdSMEZCY2tJN1EwRnNRMHM3TzBGQmRVTlFMRTlCUVU4c1UwRkJVeXhSUVVGVUxFTkJRWE5ETEdkQ1FVRkZMRTlCUVU4c1IwRkJVQ3hEUVVGWExIVkNRVUZZTEVOQlFVWXNSVUZCYVVRN1FVRkROVVlzVTBGQlR5eEpRVUZKTEZGQlFVb3NRMEZCWVN4aFFVRmlMRU5CUVZBc1EwRkVORVk3UTBGQmRrWTdPMEZCU1ZBc1QwRkJUeXhUUVVGVExGRkJRVlFzUjBGQk9FSTdRVUZEYmtNc1UwRkJUeXhKUVVGSkxGRkJRVW9zUlVGQlVDeERRVVJ0UXp0RFFVRTVRanM3UVVGSlVDeFBRVUZQTEZOQlFWTXNWVUZCVkN4RFFVRnZRaXhOUVVGd1FpeEZRVUZuUkR0QlFVTnlSQ3hUUVVGUExFbEJRVWtzVlVGQlNpeERRVUZsTEUxQlFXWXNRMEZCVUN4RFFVUnhSRHREUVVGb1JEczdRVUZKVUN4UFFVRlBMRk5CUVZNc1QwRkJWQ3hEUVVGcFFpeExRVUZxUWl4RlFVRnpRenRCUVVNelF5eFRRVUZQTEVsQlFVa3NUMEZCU2l4RFFVRlpMRXRCUVZvc1EwRkJVQ3hEUVVReVF6dERRVUYwUXpzN1FVRkpVQ3hQUVVGUExGTkJRVk1zVVVGQlZDeERRVUUwUWl4UFFVRkZMRWxCUVVZc1JVRkJhMElzVDBGQlJTeEpRVUZHTEVWQlFXdENPMEZCUTNKRkxGTkJRVThzU1VGQlNTeFJRVUZLTEVOQlFXRXNTVUZCWWl4RlFVRnRRaXhKUVVGdVFpeERRVUZRTEVOQlJIRkZPME5CUVdoRk96dEJRVWxRTEU5QlFVOHNVMEZCVXl4SlFVRlVMRU5CUVdNc1NVRkJaQ3hGUVVFMFF5eGhRVUZGTEVWQlFVWXNSVUZCV1R0QlFVTTNSQ3hUUVVGUExFbEJRVWtzU1VGQlNpeERRVUZUTEVsQlFWUXNSVUZCWlN4VlFVRm1MRU5CUVZBc1EwRkVOa1E3UTBGQmVFUTdPMEZCU1ZBc1QwRkJUeXhUUVVGVExFdEJRVlFzUTBGQlpTeExRVUZtTEVWQlFXdERPMEZCUTNaRExGTkJRVThzU1VGQlNTeExRVUZLTEVOQlFWVXNTMEZCVml4RFFVRlFMRU5CUkhWRE8wTkJRV3hET3p0QlFVbFFMRTlCUVU4c1UwRkJVeXhqUVVGVUxFTkJRWGRDTEVkQlFVY3NUVUZCU0N4RlFVRjVRanRCUVVOMFJDeFRRVUZQTEVsQlFVa3NZMEZCU2l4RFFVRnRRaXhIUVVGSExFMUJRVWdzUTBGQk1VSXNRMEZFYzBRN1EwRkJha1FpTENKbWFXeGxJam9pYkdsaUwyTnZjbVV2Y0dGMGRHVnlibk12ZEhsd1pYTXVhbk1pTENKemIzVnlZMlZ6UTI5dWRHVnVkQ0k2V3lJdktpQkFabXh2ZHlBcUwxeHVaWGh3YjNKMElHTnNZWE56SUZaaGNtbGhZbXhsSUh0Y2JpQWdaR1ZtWVhWc2RGOTJZV3gxWlRvZ1AyRnVlVHRjYmx4dUlDQmpiMjV6ZEhKMVkzUnZjaWhrWldaaGRXeDBYM1poYkhWbE9pQS9ZVzU1SUQwZ1UzbHRZbTlzTG1admNpaGNJbVZzYVhocGNuTmpjbWx3ZEM1dWIxOTJZV3gxWlZ3aUtTa2dlMXh1SUNBZ0lIUm9hWE11WkdWbVlYVnNkRjkyWVd4MVpTQTlJR1JsWm1GMWJIUmZkbUZzZFdVN1hHNGdJSDFjYm4xY2JseHVaWGh3YjNKMElHTnNZWE56SUZkcGJHUmpZWEprSUh0Y2JpQWdZMjl1YzNSeWRXTjBiM0lvS1NCN1hHNGdJSDFjYm4xY2JseHVaWGh3YjNKMElHTnNZWE56SUZOMFlYSjBjMWRwZEdnZ2UxeHVJQ0J3Y21WbWFYZzZJSE4wY21sdVp6dGNibHh1SUNCamIyNXpkSEoxWTNSdmNpaHdjbVZtYVhnNklITjBjbWx1WnlrZ2UxeHVJQ0FnSUhSb2FYTXVjSEpsWm1sNElEMGdjSEpsWm1sNE8xeHVJQ0I5WEc1OVhHNWNibVY0Y0c5eWRDQmpiR0Z6Y3lCRFlYQjBkWEpsSUh0Y2JpQWdkbUZzZFdVNklHRnVlVHRjYmx4dUlDQmpiMjV6ZEhKMVkzUnZjaWgyWVd4MVpUb2dZVzU1S1NCN1hHNGdJQ0FnZEdocGN5NTJZV3gxWlNBOUlIWmhiSFZsTzF4dUlDQjlYRzU5WEc1Y2JtVjRjRzl5ZENCamJHRnpjeUJJWldGa1ZHRnBiQ0I3WEc0Z0lHaGxZV1E2SUdGdWVUdGNiaUFnZEdGcGJEb2dZVzU1TzF4dVhHNGdJR052Ym5OMGNuVmpkRzl5S0dobFlXUTZJR0Z1ZVNBOUlHNTFiR3dzSUhSaGFXdzZJR0Z1ZVNBOUlHNTFiR3dwSUh0Y2JpQWdJQ0IwYUdsekxtaGxZV1FnUFNCb1pXRmtPMXh1SUNBZ0lIUm9hWE11ZEdGcGJDQTlJSFJoYVd3N1hHNGdJSDFjYm4xY2JseHVaWGh3YjNKMElHTnNZWE56SUZSNWNHVWdlMXh1SUNCMGVYQmxPaUJoYm5rN1hHNGdJRzlpYWxCaGRIUmxjbTQ2SUU5aWFtVmpkRHRjYmx4dUlDQmpiMjV6ZEhKMVkzUnZjaWgwZVhCbE9pQmhibmtzSUc5aWFsQmhkSFJsY200NklFOWlhbVZqZENBOUlIdDlLU0I3WEc0Z0lDQWdkR2hwY3k1MGVYQmxJRDBnZEhsd1pWeHVJQ0FnSUhSb2FYTXViMkpxVUdGMGRHVnliaUE5SUc5aWFsQmhkSFJsY201Y2JpQWdmVnh1ZlZ4dVhHNWxlSEJ2Y25RZ1kyeGhjM01nUW05MWJtUWdlMXh1SUNCMllXeDFaVG9nWVc1NU8xeHVYRzRnSUdOdmJuTjBjblZqZEc5eUtIWmhiSFZsT2lCaGJua3BJSHRjYmlBZ0lDQjBhR2x6TG5aaGJIVmxJRDBnZG1Gc2RXVTdYRzRnSUgxY2JuMWNibHh1Wlhod2IzSjBJR05zWVhOeklFSnBkRk4wY21sdVowMWhkR05vSUh0Y2JpQWdkbUZzZFdWek9pQkJjbkpoZVR4UFltcGxZM1ErWEc1Y2JpQWdZMjl1YzNSeWRXTjBiM0lvTGk0dWRtRnNkV1Z6T2lCQmNuSmhlVHhQWW1wbFkzUStLWHRjYmlBZ0lDQjBhR2x6TG5aaGJIVmxjeUE5SUhaaGJIVmxjenRjYmlBZ2ZWeHVYRzRnSUd4bGJtZDBhQ2dwSUh0Y2JpQWdJQ0J5WlhSMWNtNGdkbUZzZFdWekxteGxibWQwYUR0Y2JpQWdmVnh1WEc0Z0lHSnBkRjl6YVhwbEtDa2dlMXh1SUNBZ0lISmxkSFZ5YmlCMGFHbHpMbUo1ZEdWZmMybDZaU2dwSUNvZ09EdGNiaUFnZlZ4dVhHNGdJR0o1ZEdWZmMybDZaU2dwZTF4dUlDQWdJR3hsZENCeklEMGdNRHRjYmx4dUlDQWdJR1p2Y2loc1pYUWdkbUZzSUc5bUlIUm9hWE11ZG1Gc2RXVnpLWHRjYmlBZ0lDQWdJSE1nUFNCeklDc2dLQ2gyWVd3dWRXNXBkQ0FxSUhaaGJDNXphWHBsS1M4NEtUdGNiaUFnSUNCOVhHNWNiaUFnSUNCeVpYUjFjbTRnY3p0Y2JpQWdmVnh1WEc0Z0lHZGxkRlpoYkhWbEtHbHVaR1Y0S1h0Y2JpQWdJQ0J5WlhSMWNtNGdkR2hwY3k1MllXeDFaWE1vYVc1a1pYZ3BPMXh1SUNCOVhHNWNiaUFnWjJWMFUybDZaVTltVm1Gc2RXVW9hVzVrWlhncGUxeHVJQ0FnSUd4bGRDQjJZV3dnUFNCMGFHbHpMbWRsZEZaaGJIVmxLR2x1WkdWNEtUdGNiaUFnSUNCeVpYUjFjbTRnZG1Gc0xuVnVhWFFnS2lCMllXd3VjMmw2WlR0Y2JpQWdmVnh1WEc0Z0lHZGxkRlI1Y0dWUFpsWmhiSFZsS0dsdVpHVjRLWHRjYmlBZ0lDQnlaWFIxY200Z2RHaHBjeTVuWlhSV1lXeDFaU2hwYm1SbGVDa3VkSGx3WlR0Y2JpQWdmVnh1ZlZ4dVhHNWxlSEJ2Y25RZ1puVnVZM1JwYjI0Z2RtRnlhV0ZpYkdVb1pHVm1ZWFZzZEY5MllXeDFaVG9nUDJGdWVTQTlJRk41YldKdmJDNW1iM0lvWENKbGJHbDRhWEp6WTNKcGNIUXVibTlmZG1Gc2RXVmNJaWtwT2lCV1lYSnBZV0pzWlNCN1hHNGdJSEpsZEhWeWJpQnVaWGNnVm1GeWFXRmliR1VvWkdWbVlYVnNkRjkyWVd4MVpTazdYRzU5WEc1Y2JtVjRjRzl5ZENCbWRXNWpkR2x2YmlCM2FXeGtZMkZ5WkNncE9pQlhhV3hrWTJGeVpDQjdYRzRnSUhKbGRIVnliaUJ1WlhjZ1YybHNaR05oY21Rb0tUdGNibjFjYmx4dVpYaHdiM0owSUdaMWJtTjBhVzl1SUhOMFlYSjBjMWRwZEdnb2NISmxabWw0T2lCemRISnBibWNwT2lCVGRHRnlkSE5YYVhSb0lIdGNiaUFnY21WMGRYSnVJRzVsZHlCVGRHRnlkSE5YYVhSb0tIQnlaV1pwZUNrN1hHNTlYRzVjYm1WNGNHOXlkQ0JtZFc1amRHbHZiaUJqWVhCMGRYSmxLSFpoYkhWbE9pQmhibmtwT2lCRFlYQjBkWEpsSUh0Y2JpQWdjbVYwZFhKdUlHNWxkeUJEWVhCMGRYSmxLSFpoYkhWbEtUdGNibjFjYmx4dVpYaHdiM0owSUdaMWJtTjBhVzl1SUdobFlXUlVZV2xzS0dobFlXUTZJR0Z1ZVNBOUlHNTFiR3dzSUhSaGFXdzZJR0Z1ZVNBOUlHNTFiR3dwT2lCSVpXRmtWR0ZwYkNCN1hHNGdJSEpsZEhWeWJpQnVaWGNnU0dWaFpGUmhhV3dvYUdWaFpDd2dkR0ZwYkNrN1hHNTlYRzVjYm1WNGNHOXlkQ0JtZFc1amRHbHZiaUIwZVhCbEtIUjVjR1U2SUdGdWVTd2diMkpxVUdGMGRHVnliam9nVDJKcVpXTjBJRDBnZTMwcE9pQlVlWEJsSUh0Y2JpQWdjbVYwZFhKdUlHNWxkeUJVZVhCbEtIUjVjR1VzSUc5aWFsQmhkSFJsY200cE8xeHVmVnh1WEc1bGVIQnZjblFnWm5WdVkzUnBiMjRnWW05MWJtUW9kbUZzZFdVNklHRnVlU2s2SUVKdmRXNWtJSHRjYmlBZ2NtVjBkWEp1SUc1bGR5QkNiM1Z1WkNoMllXeDFaU2s3WEc1OVhHNWNibVY0Y0c5eWRDQm1kVzVqZEdsdmJpQmlhWFJUZEhKcGJtZE5ZWFJqYUNndUxpNTJZV3gxWlhNNklFRnljbUY1UEU5aWFtVmpkRDRwZTF4dUlDQnlaWFIxY200Z2JtVjNJRUpwZEZOMGNtbHVaMDFoZEdOb0tDNHVMblpoYkhWbGN5azdYRzU5WEc0aVhTd2ljMjkxY21ObFVtOXZkQ0k2SWk5emIzVnlZMlV2SW4wPVxuIiwiXG5cbmltcG9ydCB7IFZhcmlhYmxlLCBXaWxkY2FyZCwgSGVhZFRhaWwsIENhcHR1cmUsIFR5cGUsIFN0YXJ0c1dpdGgsIEJvdW5kLCBCaXRTdHJpbmdNYXRjaCB9IGZyb20gXCIuL3R5cGVzXCI7XG5cbmZ1bmN0aW9uIGlzX251bWJlcih2YWx1ZSkge1xuICByZXR1cm4gdHlwZW9mIHZhbHVlID09PSAnbnVtYmVyJztcbn1cblxuZnVuY3Rpb24gaXNfc3RyaW5nKHZhbHVlKSB7XG4gIHJldHVybiB0eXBlb2YgdmFsdWUgPT09ICdzdHJpbmcnO1xufVxuXG5mdW5jdGlvbiBpc19ib29sZWFuKHZhbHVlKSB7XG4gIHJldHVybiB0eXBlb2YgdmFsdWUgPT09ICdib29sZWFuJztcbn1cblxuZnVuY3Rpb24gaXNfc3ltYm9sKHZhbHVlKSB7XG4gIHJldHVybiB0eXBlb2YgdmFsdWUgPT09ICdzeW1ib2wnO1xufVxuXG5mdW5jdGlvbiBpc19udWxsKHZhbHVlKSB7XG4gIHJldHVybiB2YWx1ZSA9PT0gbnVsbDtcbn1cblxuZnVuY3Rpb24gaXNfdW5kZWZpbmVkKHZhbHVlKSB7XG4gIHJldHVybiB0eXBlb2YgdmFsdWUgPT09ICd1bmRlZmluZWQnO1xufVxuXG5mdW5jdGlvbiBpc19mdW5jdGlvbih2YWx1ZSkge1xuICByZXR1cm4gT2JqZWN0LnByb3RvdHlwZS50b1N0cmluZy5jYWxsKHZhbHVlKSA9PSAnW29iamVjdCBGdW5jdGlvbl0nO1xufVxuXG5mdW5jdGlvbiBpc192YXJpYWJsZSh2YWx1ZSkge1xuICByZXR1cm4gdmFsdWUgaW5zdGFuY2VvZiBWYXJpYWJsZTtcbn1cblxuZnVuY3Rpb24gaXNfd2lsZGNhcmQodmFsdWUpIHtcbiAgcmV0dXJuIHZhbHVlIGluc3RhbmNlb2YgV2lsZGNhcmQ7XG59XG5cbmZ1bmN0aW9uIGlzX2hlYWRUYWlsKHZhbHVlKSB7XG4gIHJldHVybiB2YWx1ZSBpbnN0YW5jZW9mIEhlYWRUYWlsO1xufVxuXG5mdW5jdGlvbiBpc19jYXB0dXJlKHZhbHVlKSB7XG4gIHJldHVybiB2YWx1ZSBpbnN0YW5jZW9mIENhcHR1cmU7XG59XG5cbmZ1bmN0aW9uIGlzX3R5cGUodmFsdWUpIHtcbiAgcmV0dXJuIHZhbHVlIGluc3RhbmNlb2YgVHlwZTtcbn1cblxuZnVuY3Rpb24gaXNfc3RhcnRzV2l0aCh2YWx1ZSkge1xuICByZXR1cm4gdmFsdWUgaW5zdGFuY2VvZiBTdGFydHNXaXRoO1xufVxuXG5mdW5jdGlvbiBpc19ib3VuZCh2YWx1ZSkge1xuICByZXR1cm4gdmFsdWUgaW5zdGFuY2VvZiBCb3VuZDtcbn1cblxuZnVuY3Rpb24gaXNfb2JqZWN0KHZhbHVlKSB7XG4gIHJldHVybiB0eXBlb2YgdmFsdWUgPT09ICdvYmplY3QnO1xufVxuXG5mdW5jdGlvbiBpc19hcnJheSh2YWx1ZSkge1xuICByZXR1cm4gQXJyYXkuaXNBcnJheSh2YWx1ZSk7XG59XG5cbmZ1bmN0aW9uIGlzX2JpdHN0cmluZyh2YWx1ZSkge1xuICByZXR1cm4gdmFsdWUgaW5zdGFuY2VvZiBCaXRTdHJpbmdNYXRjaDtcbn1cblxuZXhwb3J0IGRlZmF1bHQge1xuICBpc19udW1iZXIsXG4gIGlzX3N0cmluZyxcbiAgaXNfYm9vbGVhbixcbiAgaXNfc3ltYm9sLFxuICBpc19udWxsLFxuICBpc191bmRlZmluZWQsXG4gIGlzX2Z1bmN0aW9uLFxuICBpc192YXJpYWJsZSxcbiAgaXNfd2lsZGNhcmQsXG4gIGlzX2hlYWRUYWlsLFxuICBpc19jYXB0dXJlLFxuICBpc190eXBlLFxuICBpc19zdGFydHNXaXRoLFxuICBpc19ib3VuZCxcbiAgaXNfb2JqZWN0LFxuICBpc19hcnJheSxcbiAgaXNfYml0c3RyaW5nXG59O1xuLy8jIHNvdXJjZU1hcHBpbmdVUkw9ZGF0YTphcHBsaWNhdGlvbi9qc29uO2Jhc2U2NCxleUoyWlhKemFXOXVJam96TENKemIzVnlZMlZ6SWpwYklteHBZaTlqYjNKbEwzQmhkSFJsY201ekwyTm9aV05yY3k1cWN5SmRMQ0p1WVcxbGN5STZXMTBzSW0xaGNIQnBibWR6SWpvaU96dEJRVVZCTEZOQlFWTXNVVUZCVkN4RlFVRnRRaXhSUVVGdVFpeEZRVUUyUWl4UlFVRTNRaXhGUVVGMVF5eFBRVUYyUXl4RlFVRm5SQ3hKUVVGb1JDeEZRVUZ6UkN4VlFVRjBSQ3hGUVVGclJTeExRVUZzUlN4RlFVRjVSU3hqUVVGNlJTeFJRVUVyUml4VFFVRXZSanM3UVVGRlFTeFRRVUZUTEZOQlFWUXNRMEZCYlVJc1MwRkJia0lzUlVGQmQwTTdRVUZEZEVNc1UwRkJUeXhQUVVGUExFdEJRVkFzUzBGQmFVSXNVVUZCYWtJc1EwRkVLMEk3UTBGQmVFTTdPMEZCU1VFc1UwRkJVeXhUUVVGVUxFTkJRVzFDTEV0QlFXNUNMRVZCUVhWRE8wRkJRM0pETEZOQlFVOHNUMEZCVHl4TFFVRlFMRXRCUVdsQ0xGRkJRV3BDTEVOQlJEaENPME5CUVhaRE96dEJRVWxCTEZOQlFWTXNWVUZCVkN4RFFVRnZRaXhMUVVGd1FpeEZRVUY1UXp0QlFVTjJReXhUUVVGUExFOUJRVThzUzBGQlVDeExRVUZwUWl4VFFVRnFRaXhEUVVSblF6dERRVUY2UXpzN1FVRkpRU3hUUVVGVExGTkJRVlFzUTBGQmJVSXNTMEZCYmtJc1JVRkJkME03UVVGRGRFTXNVMEZCVHl4UFFVRlBMRXRCUVZBc1MwRkJhVUlzVVVGQmFrSXNRMEZFSzBJN1EwRkJlRU03TzBGQlNVRXNVMEZCVXl4UFFVRlVMRU5CUVdsQ0xFdEJRV3BDTEVWQlFYTkRPMEZCUTNCRExGTkJRVThzVlVGQlZTeEpRVUZXTEVOQlJEWkNPME5CUVhSRE96dEJRVWxCTEZOQlFWTXNXVUZCVkN4RFFVRnpRaXhMUVVGMFFpeEZRVUV5UXp0QlFVTjZReXhUUVVGUExFOUJRVThzUzBGQlVDeExRVUZwUWl4WFFVRnFRaXhEUVVSclF6dERRVUV6UXpzN1FVRkpRU3hUUVVGVExGZEJRVlFzUTBGQmNVSXNTMEZCY2tJc1JVRkJNRU03UVVGRGVFTXNVMEZCVHl4UFFVRlBMRk5CUVZBc1EwRkJhVUlzVVVGQmFrSXNRMEZCTUVJc1NVRkJNVUlzUTBGQkswSXNTMEZCTDBJc1MwRkJlVU1zYlVKQlFYcERMRU5CUkdsRE8wTkJRVEZET3p0QlFVbEJMRk5CUVZNc1YwRkJWQ3hEUVVGeFFpeExRVUZ5UWl4RlFVRXdRenRCUVVONFF5eFRRVUZQTEdsQ1FVRnBRaXhSUVVGcVFpeERRVVJwUXp0RFFVRXhRenM3UVVGSlFTeFRRVUZUTEZkQlFWUXNRMEZCY1VJc1MwRkJja0lzUlVGQk1FTTdRVUZEZUVNc1UwRkJUeXhwUWtGQmFVSXNVVUZCYWtJc1EwRkVhVU03UTBGQk1VTTdPMEZCU1VFc1UwRkJVeXhYUVVGVUxFTkJRWEZDTEV0QlFYSkNMRVZCUVRCRE8wRkJRM2hETEZOQlFVOHNhVUpCUVdsQ0xGRkJRV3BDTEVOQlJHbERPME5CUVRGRE96dEJRVWxCTEZOQlFWTXNWVUZCVkN4RFFVRnZRaXhMUVVGd1FpeEZRVUY1UXp0QlFVTjJReXhUUVVGUExHbENRVUZwUWl4UFFVRnFRaXhEUVVSblF6dERRVUY2UXpzN1FVRkpRU3hUUVVGVExFOUJRVlFzUTBGQmFVSXNTMEZCYWtJc1JVRkJjME03UVVGRGNFTXNVMEZCVHl4cFFrRkJhVUlzU1VGQmFrSXNRMEZFTmtJN1EwRkJkRU03TzBGQlNVRXNVMEZCVXl4aFFVRlVMRU5CUVhWQ0xFdEJRWFpDTEVWQlFUUkRPMEZCUXpGRExGTkJRVThzYVVKQlFXbENMRlZCUVdwQ0xFTkJSRzFETzBOQlFUVkRPenRCUVVsQkxGTkJRVk1zVVVGQlZDeERRVUZyUWl4TFFVRnNRaXhGUVVGMVF6dEJRVU55UXl4VFFVRlBMR2xDUVVGcFFpeExRVUZxUWl4RFFVUTRRanREUVVGMlF6czdRVUZKUVN4VFFVRlRMRk5CUVZRc1EwRkJiVUlzUzBGQmJrSXNSVUZCZDBNN1FVRkRkRU1zVTBGQlR5eFBRVUZQTEV0QlFWQXNTMEZCYVVJc1VVRkJha0lzUTBGRUswSTdRMEZCZUVNN08wRkJTVUVzVTBGQlV5eFJRVUZVTEVOQlFXdENMRXRCUVd4Q0xFVkJRWFZETzBGQlEzSkRMRk5CUVU4c1RVRkJUU3hQUVVGT0xFTkJRV01zUzBGQlpDeERRVUZRTEVOQlJIRkRPME5CUVhaRE96dEJRVWxCTEZOQlFWTXNXVUZCVkN4RFFVRnpRaXhMUVVGMFFpeEZRVUV5UXp0QlFVTjZReXhUUVVGUExHbENRVUZwUWl4alFVRnFRaXhEUVVSclF6dERRVUV6UXpzN1FVRkxRU3hsUVVGbE8wRkJRMklzVjBGRVlUdEJRVVZpTEZkQlJtRTdRVUZIWWl4WlFVaGhPMEZCU1dJc1YwRktZVHRCUVV0aUxGTkJUR0U3UVVGTllpeGpRVTVoTzBGQlQySXNZVUZRWVR0QlFWRmlMR0ZCVW1FN1FVRlRZaXhoUVZSaE8wRkJWV0lzWVVGV1lUdEJRVmRpTEZsQldHRTdRVUZaWWl4VFFWcGhPMEZCWVdJc1pVRmlZVHRCUVdOaUxGVkJaR0U3UVVGbFlpeFhRV1poTzBGQlowSmlMRlZCYUVKaE8wRkJhVUppTEdOQmFrSmhPME5CUVdZaUxDSm1hV3hsSWpvaWJHbGlMMk52Y21VdmNHRjBkR1Z5Ym5NdlkyaGxZMnR6TG1weklpd2ljMjkxY21ObGMwTnZiblJsYm5RaU9sc2lMeW9nUUdac2IzY2dLaTljYmx4dWFXMXdiM0owSUhzZ1ZtRnlhV0ZpYkdVc0lGZHBiR1JqWVhKa0xDQklaV0ZrVkdGcGJDd2dRMkZ3ZEhWeVpTd2dWSGx3WlN3Z1UzUmhjblJ6VjJsMGFDd2dRbTkxYm1Rc0lFSnBkRk4wY21sdVowMWhkR05vSUgwZ1puSnZiU0JjSWk0dmRIbHdaWE5jSWp0Y2JseHVablZ1WTNScGIyNGdhWE5mYm5WdFltVnlLSFpoYkhWbE9pQmhibmtwT2lCaWIyOXNaV0Z1SUh0Y2JpQWdjbVYwZFhKdUlIUjVjR1Z2WmlCMllXeDFaU0E5UFQwZ0oyNTFiV0psY2ljN1hHNTlYRzVjYm1aMWJtTjBhVzl1SUdselgzTjBjbWx1WnloMllXeDFaVG9nWVc1NUtUb2dZbTl2YkdWaGJudGNiaUFnY21WMGRYSnVJSFI1Y0dWdlppQjJZV3gxWlNBOVBUMGdKM04wY21sdVp5YzdYRzU5WEc1Y2JtWjFibU4wYVc5dUlHbHpYMkp2YjJ4bFlXNG9kbUZzZFdVNklHRnVlU2s2SUdKdmIyeGxZVzRnZTF4dUlDQnlaWFIxY200Z2RIbHdaVzltSUhaaGJIVmxJRDA5UFNBblltOXZiR1ZoYmljN1hHNTlYRzVjYm1aMWJtTjBhVzl1SUdselgzTjViV0p2YkNoMllXeDFaVG9nWVc1NUtUb2dZbTl2YkdWaGJpQjdYRzRnSUhKbGRIVnliaUIwZVhCbGIyWWdkbUZzZFdVZ1BUMDlJQ2R6ZVcxaWIyd25PMXh1ZlZ4dVhHNW1kVzVqZEdsdmJpQnBjMTl1ZFd4c0tIWmhiSFZsT2lCaGJua3BPaUJpYjI5c1pXRnVJSHRjYmlBZ2NtVjBkWEp1SUhaaGJIVmxJRDA5UFNCdWRXeHNPMXh1ZlZ4dVhHNW1kVzVqZEdsdmJpQnBjMTkxYm1SbFptbHVaV1FvZG1Gc2RXVTZJR0Z1ZVNrNklHSnZiMnhsWVc0Z2UxeHVJQ0J5WlhSMWNtNGdkSGx3Wlc5bUlIWmhiSFZsSUQwOVBTQW5kVzVrWldacGJtVmtKenRjYm4xY2JseHVablZ1WTNScGIyNGdhWE5mWm5WdVkzUnBiMjRvZG1Gc2RXVTZJR0Z1ZVNrNklHSnZiMnhsWVc0Z2UxeHVJQ0J5WlhSMWNtNGdUMkpxWldOMExuQnliM1J2ZEhsd1pTNTBiMU4wY21sdVp5NWpZV3hzS0haaGJIVmxLU0E5UFNBblcyOWlhbVZqZENCR2RXNWpkR2x2Ymwwbk8xeHVmVnh1WEc1bWRXNWpkR2x2YmlCcGMxOTJZWEpwWVdKc1pTaDJZV3gxWlRvZ1lXNTVLVG9nWW05dmJHVmhiaUI3WEc0Z0lISmxkSFZ5YmlCMllXeDFaU0JwYm5OMFlXNWpaVzltSUZaaGNtbGhZbXhsTzF4dWZWeHVYRzVtZFc1amRHbHZiaUJwYzE5M2FXeGtZMkZ5WkNoMllXeDFaVG9nWVc1NUtUb2dZbTl2YkdWaGJpQjdYRzRnSUhKbGRIVnliaUIyWVd4MVpTQnBibk4wWVc1alpXOW1JRmRwYkdSallYSmtPMXh1ZlZ4dVhHNW1kVzVqZEdsdmJpQnBjMTlvWldGa1ZHRnBiQ2gyWVd4MVpUb2dZVzU1S1RvZ1ltOXZiR1ZoYmlCN1hHNGdJSEpsZEhWeWJpQjJZV3gxWlNCcGJuTjBZVzVqWlc5bUlFaGxZV1JVWVdsc08xeHVmVnh1WEc1bWRXNWpkR2x2YmlCcGMxOWpZWEIwZFhKbEtIWmhiSFZsT2lCaGJua3BPaUJpYjI5c1pXRnVJSHRjYmlBZ2NtVjBkWEp1SUhaaGJIVmxJR2x1YzNSaGJtTmxiMllnUTJGd2RIVnlaVHRjYm4xY2JseHVablZ1WTNScGIyNGdhWE5mZEhsd1pTaDJZV3gxWlRvZ1lXNTVLVG9nWW05dmJHVmhiaUI3WEc0Z0lISmxkSFZ5YmlCMllXeDFaU0JwYm5OMFlXNWpaVzltSUZSNWNHVTdYRzU5WEc1Y2JtWjFibU4wYVc5dUlHbHpYM04wWVhKMGMxZHBkR2dvZG1Gc2RXVTZJR0Z1ZVNrNklHSnZiMnhsWVc0Z2UxeHVJQ0J5WlhSMWNtNGdkbUZzZFdVZ2FXNXpkR0Z1WTJWdlppQlRkR0Z5ZEhOWGFYUm9PMXh1ZlZ4dVhHNW1kVzVqZEdsdmJpQnBjMTlpYjNWdVpDaDJZV3gxWlRvZ1lXNTVLVG9nWW05dmJHVmhiaUI3WEc0Z0lISmxkSFZ5YmlCMllXeDFaU0JwYm5OMFlXNWpaVzltSUVKdmRXNWtPMXh1ZlZ4dVhHNW1kVzVqZEdsdmJpQnBjMTl2WW1wbFkzUW9kbUZzZFdVNklHRnVlU2s2SUdKdmIyeGxZVzRnZTF4dUlDQnlaWFIxY200Z2RIbHdaVzltSUhaaGJIVmxJRDA5UFNBbmIySnFaV04wSnp0Y2JuMWNibHh1Wm5WdVkzUnBiMjRnYVhOZllYSnlZWGtvZG1Gc2RXVTZJR0Z1ZVNrNklHSnZiMnhsWVc0Z2UxeHVJQ0J5WlhSMWNtNGdRWEp5WVhrdWFYTkJjbkpoZVNoMllXeDFaU2s3WEc1OVhHNWNibVoxYm1OMGFXOXVJR2x6WDJKcGRITjBjbWx1WnloMllXeDFaVG9nWVc1NUtUb2dZbTl2YkdWaGJpQjdYRzRnSUhKbGRIVnliaUIyWVd4MVpTQnBibk4wWVc1alpXOW1JRUpwZEZOMGNtbHVaMDFoZEdOb08xeHVmVnh1WEc1Y2JtVjRjRzl5ZENCa1pXWmhkV3gwSUh0Y2JpQWdhWE5mYm5WdFltVnlMRnh1SUNCcGMxOXpkSEpwYm1jc1hHNGdJR2x6WDJKdmIyeGxZVzRzWEc0Z0lHbHpYM041YldKdmJDeGNiaUFnYVhOZmJuVnNiQ3hjYmlBZ2FYTmZkVzVrWldacGJtVmtMRnh1SUNCcGMxOW1kVzVqZEdsdmJpeGNiaUFnYVhOZmRtRnlhV0ZpYkdVc1hHNGdJR2x6WDNkcGJHUmpZWEprTEZ4dUlDQnBjMTlvWldGa1ZHRnBiQ3hjYmlBZ2FYTmZZMkZ3ZEhWeVpTeGNiaUFnYVhOZmRIbHdaU3hjYmlBZ2FYTmZjM1JoY25SelYybDBhQ3hjYmlBZ2FYTmZZbTkxYm1Rc1hHNGdJR2x6WDI5aWFtVmpkQ3hjYmlBZ2FYTmZZWEp5WVhrc1hHNGdJR2x6WDJKcGRITjBjbWx1WjF4dWZUdGNiaUpkTENKemIzVnlZMlZTYjI5MElqb2lMM052ZFhKalpTOGlmUT09XG4iLCJcblxuaW1wb3J0IENoZWNrcyBmcm9tIFwiLi9jaGVja3NcIjtcbmltcG9ydCAqIGFzIFR5cGVzIGZyb20gXCIuL3R5cGVzXCI7XG5pbXBvcnQgeyBidWlsZE1hdGNoIH0gZnJvbSBcIi4vbWF0Y2hcIjtcbmltcG9ydCBCaXRTdHJpbmcgZnJvbSBcIi4uL2JpdF9zdHJpbmdcIjtcblxuZnVuY3Rpb24gcmVzb2x2ZVN5bWJvbChwYXR0ZXJuKSB7XG4gIHJldHVybiBmdW5jdGlvbiAodmFsdWUpIHtcbiAgICByZXR1cm4gQ2hlY2tzLmlzX3N5bWJvbCh2YWx1ZSkgJiYgdmFsdWUgPT09IHBhdHRlcm47XG4gIH07XG59XG5cbmZ1bmN0aW9uIHJlc29sdmVTdHJpbmcocGF0dGVybikge1xuICByZXR1cm4gZnVuY3Rpb24gKHZhbHVlKSB7XG4gICAgcmV0dXJuIENoZWNrcy5pc19zdHJpbmcodmFsdWUpICYmIHZhbHVlID09PSBwYXR0ZXJuO1xuICB9O1xufVxuXG5mdW5jdGlvbiByZXNvbHZlTnVtYmVyKHBhdHRlcm4pIHtcbiAgcmV0dXJuIGZ1bmN0aW9uICh2YWx1ZSkge1xuICAgIHJldHVybiBDaGVja3MuaXNfbnVtYmVyKHZhbHVlKSAmJiB2YWx1ZSA9PT0gcGF0dGVybjtcbiAgfTtcbn1cblxuZnVuY3Rpb24gcmVzb2x2ZUJvb2xlYW4ocGF0dGVybikge1xuICByZXR1cm4gZnVuY3Rpb24gKHZhbHVlKSB7XG4gICAgcmV0dXJuIENoZWNrcy5pc19ib29sZWFuKHZhbHVlKSAmJiB2YWx1ZSA9PT0gcGF0dGVybjtcbiAgfTtcbn1cblxuZnVuY3Rpb24gcmVzb2x2ZUZ1bmN0aW9uKHBhdHRlcm4pIHtcbiAgcmV0dXJuIGZ1bmN0aW9uICh2YWx1ZSkge1xuICAgIHJldHVybiBDaGVja3MuaXNfZnVuY3Rpb24odmFsdWUpICYmIHZhbHVlID09PSBwYXR0ZXJuO1xuICB9O1xufVxuXG5mdW5jdGlvbiByZXNvbHZlTnVsbChwYXR0ZXJuKSB7XG4gIHJldHVybiBmdW5jdGlvbiAodmFsdWUpIHtcbiAgICByZXR1cm4gQ2hlY2tzLmlzX251bGwodmFsdWUpO1xuICB9O1xufVxuXG5mdW5jdGlvbiByZXNvbHZlQm91bmQocGF0dGVybikge1xuICByZXR1cm4gZnVuY3Rpb24gKHZhbHVlLCBhcmdzKSB7XG4gICAgaWYgKHR5cGVvZiB2YWx1ZSA9PT0gdHlwZW9mIHBhdHRlcm4udmFsdWUgJiYgdmFsdWUgPT09IHBhdHRlcm4udmFsdWUpIHtcbiAgICAgIGFyZ3MucHVzaCh2YWx1ZSk7XG4gICAgICByZXR1cm4gdHJ1ZTtcbiAgICB9XG5cbiAgICByZXR1cm4gZmFsc2U7XG4gIH07XG59XG5cbmZ1bmN0aW9uIHJlc29sdmVXaWxkY2FyZCgpIHtcbiAgcmV0dXJuIGZ1bmN0aW9uICgpIHtcbiAgICByZXR1cm4gdHJ1ZTtcbiAgfTtcbn1cblxuZnVuY3Rpb24gcmVzb2x2ZVZhcmlhYmxlKCkge1xuICByZXR1cm4gZnVuY3Rpb24gKHZhbHVlLCBhcmdzKSB7XG4gICAgYXJncy5wdXNoKHZhbHVlKTtcbiAgICByZXR1cm4gdHJ1ZTtcbiAgfTtcbn1cblxuZnVuY3Rpb24gcmVzb2x2ZUhlYWRUYWlsKHBhdHRlcm4pIHtcbiAgY29uc3QgaGVhZE1hdGNoZXMgPSBidWlsZE1hdGNoKHBhdHRlcm4uaGVhZCk7XG4gIGNvbnN0IHRhaWxNYXRjaGVzID0gYnVpbGRNYXRjaChwYXR0ZXJuLnRhaWwpO1xuXG4gIHJldHVybiBmdW5jdGlvbiAodmFsdWUsIGFyZ3MpIHtcbiAgICBpZiAoIUNoZWNrcy5pc19hcnJheSh2YWx1ZSkgfHwgdmFsdWUubGVuZ3RoIDwgMikge1xuICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH1cblxuICAgIGNvbnN0IGhlYWQgPSB2YWx1ZVswXTtcbiAgICBjb25zdCB0YWlsID0gdmFsdWUuc2xpY2UoMSk7XG5cbiAgICBpZiAoaGVhZE1hdGNoZXMoaGVhZCwgYXJncykgJiYgdGFpbE1hdGNoZXModGFpbCwgYXJncykpIHtcbiAgICAgIHJldHVybiB0cnVlO1xuICAgIH1cbiAgfTtcbn1cblxuZnVuY3Rpb24gcmVzb2x2ZUNhcHR1cmUocGF0dGVybikge1xuICBjb25zdCBtYXRjaGVzID0gYnVpbGRNYXRjaChwYXR0ZXJuLnZhbHVlKTtcblxuICByZXR1cm4gZnVuY3Rpb24gKHZhbHVlLCBhcmdzKSB7XG4gICAgaWYgKG1hdGNoZXModmFsdWUsIGFyZ3MpKSB7XG4gICAgICBhcmdzLnB1c2godmFsdWUpO1xuICAgICAgcmV0dXJuIHRydWU7XG4gICAgfVxuXG4gICAgcmV0dXJuIGZhbHNlO1xuICB9O1xufVxuXG5mdW5jdGlvbiByZXNvbHZlU3RhcnRzV2l0aChwYXR0ZXJuKSB7XG4gIGNvbnN0IHByZWZpeCA9IHBhdHRlcm4ucHJlZml4O1xuXG4gIHJldHVybiBmdW5jdGlvbiAodmFsdWUsIGFyZ3MpIHtcbiAgICBpZiAoQ2hlY2tzLmlzX3N0cmluZyh2YWx1ZSkgJiYgdmFsdWUuc3RhcnRzV2l0aChwcmVmaXgpKSB7XG4gICAgICBhcmdzLnB1c2godmFsdWUuc3Vic3RyaW5nKHByZWZpeC5sZW5ndGgpKTtcbiAgICAgIHJldHVybiB0cnVlO1xuICAgIH1cblxuICAgIHJldHVybiBmYWxzZTtcbiAgfTtcbn1cblxuZnVuY3Rpb24gcmVzb2x2ZVR5cGUocGF0dGVybikge1xuICByZXR1cm4gZnVuY3Rpb24gKHZhbHVlLCBhcmdzKSB7XG4gICAgaWYgKHZhbHVlIGluc3RhbmNlb2YgcGF0dGVybi50eXBlKSB7XG4gICAgICBjb25zdCBtYXRjaGVzID0gYnVpbGRNYXRjaChwYXR0ZXJuLm9ialBhdHRlcm4pO1xuICAgICAgcmV0dXJuIG1hdGNoZXModmFsdWUsIGFyZ3MpICYmIGFyZ3MucHVzaCh2YWx1ZSkgPiAwO1xuICAgIH1cblxuICAgIHJldHVybiBmYWxzZTtcbiAgfTtcbn1cblxuZnVuY3Rpb24gcmVzb2x2ZUFycmF5KHBhdHRlcm4pIHtcbiAgY29uc3QgbWF0Y2hlcyA9IHBhdHRlcm4ubWFwKHggPT4gYnVpbGRNYXRjaCh4KSk7XG5cbiAgcmV0dXJuIGZ1bmN0aW9uICh2YWx1ZSwgYXJncykge1xuICAgIGlmICghQ2hlY2tzLmlzX2FycmF5KHZhbHVlKSB8fCB2YWx1ZS5sZW5ndGggIT0gcGF0dGVybi5sZW5ndGgpIHtcbiAgICAgIHJldHVybiBmYWxzZTtcbiAgICB9XG5cbiAgICByZXR1cm4gdmFsdWUuZXZlcnkoZnVuY3Rpb24gKHYsIGkpIHtcbiAgICAgIHJldHVybiBtYXRjaGVzW2ldKHZhbHVlW2ldLCBhcmdzKTtcbiAgICB9KTtcbiAgfTtcbn1cblxuZnVuY3Rpb24gcmVzb2x2ZU9iamVjdChwYXR0ZXJuKSB7XG4gIGxldCBtYXRjaGVzID0ge307XG5cbiAgZm9yIChsZXQga2V5IG9mIE9iamVjdC5rZXlzKHBhdHRlcm4pLmNvbmNhdChPYmplY3QuZ2V0T3duUHJvcGVydHlTeW1ib2xzKHBhdHRlcm4pKSkge1xuICAgIG1hdGNoZXNba2V5XSA9IGJ1aWxkTWF0Y2gocGF0dGVybltrZXldKTtcbiAgfVxuXG4gIHJldHVybiBmdW5jdGlvbiAodmFsdWUsIGFyZ3MpIHtcbiAgICBpZiAoIUNoZWNrcy5pc19vYmplY3QodmFsdWUpIHx8IHBhdHRlcm4ubGVuZ3RoID4gdmFsdWUubGVuZ3RoKSB7XG4gICAgICByZXR1cm4gZmFsc2U7XG4gICAgfVxuXG4gICAgZm9yIChsZXQga2V5IG9mIE9iamVjdC5rZXlzKHBhdHRlcm4pLmNvbmNhdChPYmplY3QuZ2V0T3duUHJvcGVydHlTeW1ib2xzKHBhdHRlcm4pKSkge1xuICAgICAgaWYgKCEoa2V5IGluIHZhbHVlKSB8fCAhbWF0Y2hlc1trZXldKHZhbHVlW2tleV0sIGFyZ3MpKSB7XG4gICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICByZXR1cm4gdHJ1ZTtcbiAgfTtcbn1cblxuZnVuY3Rpb24gcmVzb2x2ZUJpdFN0cmluZyhwYXR0ZXJuKSB7XG4gIGxldCBwYXR0ZXJuQml0U3RyaW5nID0gW107XG5cbiAgZm9yIChsZXQgYml0c3RyaW5nTWF0Y2hQYXJ0IG9mIHBhdHRlcm4udmFsdWVzKSB7XG4gICAgaWYgKENoZWNrcy5pc192YXJpYWJsZShiaXRzdHJpbmdNYXRjaFBhcnQudmFsdWUpKSB7XG4gICAgICBsZXQgc2l6ZSA9IGdldFNpemUoYml0c3RyaW5nTWF0Y2hQYXJ0LnVuaXQsIGJpdHN0cmluZ01hdGNoUGFydC5zaXplKTtcbiAgICAgIGZpbGxBcnJheShwYXR0ZXJuQml0U3RyaW5nLCBzaXplKTtcbiAgICB9IGVsc2Uge1xuICAgICAgcGF0dGVybkJpdFN0cmluZyA9IHBhdHRlcm5CaXRTdHJpbmcuY29uY2F0KG5ldyBCaXRTdHJpbmcoYml0c3RyaW5nTWF0Y2hQYXJ0KS52YWx1ZSk7XG4gICAgfVxuICB9XG5cbiAgbGV0IHBhdHRlcm5WYWx1ZXMgPSBwYXR0ZXJuLnZhbHVlcztcblxuICByZXR1cm4gZnVuY3Rpb24gKHZhbHVlLCBhcmdzKSB7XG4gICAgbGV0IGJzVmFsdWUgPSBudWxsO1xuXG4gICAgaWYgKCFDaGVja3MuaXNfc3RyaW5nKHZhbHVlKSAmJiAhKHZhbHVlIGluc3RhbmNlb2YgQml0U3RyaW5nKSkge1xuICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH1cblxuICAgIGlmIChDaGVja3MuaXNfc3RyaW5nKHZhbHVlKSkge1xuICAgICAgYnNWYWx1ZSA9IG5ldyBCaXRTdHJpbmcoQml0U3RyaW5nLmJpbmFyeSh2YWx1ZSkpO1xuICAgIH0gZWxzZSB7XG4gICAgICBic1ZhbHVlID0gdmFsdWU7XG4gICAgfVxuXG4gICAgbGV0IGJlZ2lubmluZ0luZGV4ID0gMDtcblxuICAgIGZvciAobGV0IGkgPSAwOyBpIDwgcGF0dGVyblZhbHVlcy5sZW5ndGg7IGkrKykge1xuICAgICAgbGV0IGJpdHN0cmluZ01hdGNoUGFydCA9IHBhdHRlcm5WYWx1ZXNbaV07XG5cbiAgICAgIGlmIChDaGVja3MuaXNfdmFyaWFibGUoYml0c3RyaW5nTWF0Y2hQYXJ0LnZhbHVlKSAmJiBiaXRzdHJpbmdNYXRjaFBhcnQudHlwZSA9PSAnYmluYXJ5JyAmJiBiaXRzdHJpbmdNYXRjaFBhcnQuc2l6ZSA9PT0gdW5kZWZpbmVkICYmIGkgPCBwYXR0ZXJuVmFsdWVzLmxlbmd0aCAtIDEpIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKFwiYSBiaW5hcnkgZmllbGQgd2l0aG91dCBzaXplIGlzIG9ubHkgYWxsb3dlZCBhdCB0aGUgZW5kIG9mIGEgYmluYXJ5IHBhdHRlcm5cIik7XG4gICAgICB9XG5cbiAgICAgIGxldCBzaXplID0gMDtcbiAgICAgIGxldCBic1ZhbHVlQXJyYXlQYXJ0ID0gW107XG4gICAgICBsZXQgcGF0dGVybkJpdFN0cmluZ0FycmF5UGFydCA9IFtdO1xuICAgICAgc2l6ZSA9IGdldFNpemUoYml0c3RyaW5nTWF0Y2hQYXJ0LnVuaXQsIGJpdHN0cmluZ01hdGNoUGFydC5zaXplKTtcblxuICAgICAgaWYgKGkgPT09IHBhdHRlcm5WYWx1ZXMubGVuZ3RoIC0gMSkge1xuICAgICAgICBic1ZhbHVlQXJyYXlQYXJ0ID0gYnNWYWx1ZS52YWx1ZS5zbGljZShiZWdpbm5pbmdJbmRleCk7XG4gICAgICAgIHBhdHRlcm5CaXRTdHJpbmdBcnJheVBhcnQgPSBwYXR0ZXJuQml0U3RyaW5nLnNsaWNlKGJlZ2lubmluZ0luZGV4KTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIGJzVmFsdWVBcnJheVBhcnQgPSBic1ZhbHVlLnZhbHVlLnNsaWNlKGJlZ2lubmluZ0luZGV4LCBiZWdpbm5pbmdJbmRleCArIHNpemUpO1xuICAgICAgICBwYXR0ZXJuQml0U3RyaW5nQXJyYXlQYXJ0ID0gcGF0dGVybkJpdFN0cmluZy5zbGljZShiZWdpbm5pbmdJbmRleCwgYmVnaW5uaW5nSW5kZXggKyBzaXplKTtcbiAgICAgIH1cblxuICAgICAgaWYgKENoZWNrcy5pc192YXJpYWJsZShiaXRzdHJpbmdNYXRjaFBhcnQudmFsdWUpKSB7XG4gICAgICAgIHN3aXRjaCAoYml0c3RyaW5nTWF0Y2hQYXJ0LnR5cGUpIHtcbiAgICAgICAgICBjYXNlICdpbnRlZ2VyJzpcbiAgICAgICAgICAgIGlmIChiaXRzdHJpbmdNYXRjaFBhcnQuYXR0cmlidXRlcyAmJiBiaXRzdHJpbmdNYXRjaFBhcnQuYXR0cmlidXRlcy5pbmRleE9mKFwic2lnbmVkXCIpICE9IC0xKSB7XG4gICAgICAgICAgICAgIGFyZ3MucHVzaChuZXcgSW50OEFycmF5KFtic1ZhbHVlQXJyYXlQYXJ0WzBdXSlbMF0pO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgYXJncy5wdXNoKG5ldyBVaW50OEFycmF5KFtic1ZhbHVlQXJyYXlQYXJ0WzBdXSlbMF0pO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgYnJlYWs7XG5cbiAgICAgICAgICBjYXNlICdmbG9hdCc6XG4gICAgICAgICAgICBpZiAoc2l6ZSA9PT0gNjQpIHtcbiAgICAgICAgICAgICAgYXJncy5wdXNoKEZsb2F0NjRBcnJheS5mcm9tKGJzVmFsdWVBcnJheVBhcnQpWzBdKTtcbiAgICAgICAgICAgIH0gZWxzZSBpZiAoc2l6ZSA9PT0gMzIpIHtcbiAgICAgICAgICAgICAgYXJncy5wdXNoKEZsb2F0MzJBcnJheS5mcm9tKGJzVmFsdWVBcnJheVBhcnQpWzBdKTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGJyZWFrO1xuXG4gICAgICAgICAgY2FzZSAnYml0c3RyaW5nJzpcbiAgICAgICAgICAgIGFyZ3MucHVzaChjcmVhdGVCaXRTdHJpbmcoYnNWYWx1ZUFycmF5UGFydCkpO1xuICAgICAgICAgICAgYnJlYWs7XG5cbiAgICAgICAgICBjYXNlICdiaW5hcnknOlxuICAgICAgICAgICAgYXJncy5wdXNoKFN0cmluZy5mcm9tQ2hhckNvZGUuYXBwbHkobnVsbCwgbmV3IFVpbnQ4QXJyYXkoYnNWYWx1ZUFycmF5UGFydCkpKTtcbiAgICAgICAgICAgIGJyZWFrO1xuXG4gICAgICAgICAgY2FzZSAndXRmOCc6XG4gICAgICAgICAgICBhcmdzLnB1c2goU3RyaW5nLmZyb21DaGFyQ29kZS5hcHBseShudWxsLCBuZXcgVWludDhBcnJheShic1ZhbHVlQXJyYXlQYXJ0KSkpO1xuICAgICAgICAgICAgYnJlYWs7XG5cbiAgICAgICAgICBjYXNlICd1dGYxNic6XG4gICAgICAgICAgICBhcmdzLnB1c2goU3RyaW5nLmZyb21DaGFyQ29kZS5hcHBseShudWxsLCBuZXcgVWludDE2QXJyYXkoYnNWYWx1ZUFycmF5UGFydCkpKTtcbiAgICAgICAgICAgIGJyZWFrO1xuXG4gICAgICAgICAgY2FzZSAndXRmMzInOlxuICAgICAgICAgICAgYXJncy5wdXNoKFN0cmluZy5mcm9tQ2hhckNvZGUuYXBwbHkobnVsbCwgbmV3IFVpbnQzMkFycmF5KGJzVmFsdWVBcnJheVBhcnQpKSk7XG4gICAgICAgICAgICBicmVhaztcblxuICAgICAgICAgIGRlZmF1bHQ6XG4gICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgIH1cbiAgICAgIH0gZWxzZSBpZiAoIWFycmF5c0VxdWFsKGJzVmFsdWVBcnJheVBhcnQsIHBhdHRlcm5CaXRTdHJpbmdBcnJheVBhcnQpKSB7XG4gICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgIH1cblxuICAgICAgYmVnaW5uaW5nSW5kZXggPSBiZWdpbm5pbmdJbmRleCArIHNpemU7XG4gICAgfVxuXG4gICAgcmV0dXJuIHRydWU7XG4gIH07XG59XG5cbmZ1bmN0aW9uIGdldFNpemUodW5pdCwgc2l6ZSkge1xuICByZXR1cm4gdW5pdCAqIHNpemUgLyA4O1xufVxuXG5mdW5jdGlvbiBhcnJheXNFcXVhbChhLCBiKSB7XG4gIGlmIChhID09PSBiKSByZXR1cm4gdHJ1ZTtcbiAgaWYgKGEgPT0gbnVsbCB8fCBiID09IG51bGwpIHJldHVybiBmYWxzZTtcbiAgaWYgKGEubGVuZ3RoICE9IGIubGVuZ3RoKSByZXR1cm4gZmFsc2U7XG5cbiAgZm9yICh2YXIgaSA9IDA7IGkgPCBhLmxlbmd0aDsgKytpKSB7XG4gICAgaWYgKGFbaV0gIT09IGJbaV0pIHJldHVybiBmYWxzZTtcbiAgfVxuXG4gIHJldHVybiB0cnVlO1xufVxuXG5mdW5jdGlvbiBmaWxsQXJyYXkoYXJyLCBudW0pIHtcbiAgZm9yIChsZXQgaSA9IDA7IGkgPCBudW07IGkrKykge1xuICAgIGFyci5wdXNoKDApO1xuICB9XG59XG5cbmZ1bmN0aW9uIGNyZWF0ZUJpdFN0cmluZyhhcnIpIHtcbiAgbGV0IGludGVnZXJQYXJ0cyA9IGFyci5tYXAoZWxlbSA9PiBCaXRTdHJpbmcuaW50ZWdlcihlbGVtKSk7XG4gIHJldHVybiBuZXcgQml0U3RyaW5nKC4uLmludGVnZXJQYXJ0cyk7XG59XG5cbmZ1bmN0aW9uIHJlc29sdmVOb01hdGNoKCkge1xuICByZXR1cm4gZnVuY3Rpb24gKCkge1xuICAgIHJldHVybiBmYWxzZTtcbiAgfTtcbn1cblxuZXhwb3J0IGRlZmF1bHQge1xuICByZXNvbHZlQm91bmQsXG4gIHJlc29sdmVXaWxkY2FyZCxcbiAgcmVzb2x2ZVZhcmlhYmxlLFxuICByZXNvbHZlSGVhZFRhaWwsXG4gIHJlc29sdmVDYXB0dXJlLFxuICByZXNvbHZlU3RhcnRzV2l0aCxcbiAgcmVzb2x2ZVR5cGUsXG4gIHJlc29sdmVBcnJheSxcbiAgcmVzb2x2ZU9iamVjdCxcbiAgcmVzb2x2ZU5vTWF0Y2gsXG4gIHJlc29sdmVTeW1ib2wsXG4gIHJlc29sdmVTdHJpbmcsXG4gIHJlc29sdmVOdW1iZXIsXG4gIHJlc29sdmVCb29sZWFuLFxuICByZXNvbHZlRnVuY3Rpb24sXG4gIHJlc29sdmVOdWxsLFxuICByZXNvbHZlQml0U3RyaW5nXG59O1xuLy8jIHNvdXJjZU1hcHBpbmdVUkw9ZGF0YTphcHBsaWNhdGlvbi9qc29uO2Jhc2U2NCxleUoyWlhKemFXOXVJam96TENKemIzVnlZMlZ6SWpwYklteHBZaTlqYjNKbEwzQmhkSFJsY201ekwzSmxjMjlzZG1WeWN5NXFjeUpkTENKdVlXMWxjeUk2VzEwc0ltMWhjSEJwYm1keklqb2lPenRCUVVWQkxFOUJRVThzVFVGQlVDeE5RVUZ0UWl4VlFVRnVRanRCUVVOQkxFOUJRVThzUzBGQlN5eExRVUZNTEUxQlFXZENMRk5CUVhaQ08wRkJRMEVzVTBGQlV5eFZRVUZVTEZGQlFUSkNMRk5CUVROQ08wRkJRMEVzVDBGQlR5eFRRVUZRTEUxQlFYTkNMR1ZCUVhSQ096dEJRVVZCTEZOQlFWTXNZVUZCVkN4RFFVRjFRaXhQUVVGMlFpeEZRVUVyUXp0QlFVTTNReXhUUVVGUExGVkJRVk1zUzBGQlZDeEZRVUU0UWp0QlFVTnVReXhYUVVGUExFOUJRVThzVTBGQlVDeERRVUZwUWl4TFFVRnFRaXhMUVVFeVFpeFZRVUZWTEU5QlFWWXNRMEZFUXp0SFFVRTVRaXhEUVVSelF6dERRVUV2UXpzN1FVRk5RU3hUUVVGVExHRkJRVlFzUTBGQmRVSXNUMEZCZGtJc1JVRkJLME03UVVGRE4wTXNVMEZCVHl4VlFVRlRMRXRCUVZRc1JVRkJPRUk3UVVGRGJrTXNWMEZCVHl4UFFVRlBMRk5CUVZBc1EwRkJhVUlzUzBGQmFrSXNTMEZCTWtJc1ZVRkJWU3hQUVVGV0xFTkJSRU03UjBGQk9VSXNRMEZFYzBNN1EwRkJMME03TzBGQlRVRXNVMEZCVXl4aFFVRlVMRU5CUVhWQ0xFOUJRWFpDTEVWQlFTdERPMEZCUXpkRExGTkJRVThzVlVGQlV5eExRVUZVTEVWQlFUaENPMEZCUTI1RExGZEJRVThzVDBGQlR5eFRRVUZRTEVOQlFXbENMRXRCUVdwQ0xFdEJRVEpDTEZWQlFWVXNUMEZCVml4RFFVUkRPMGRCUVRsQ0xFTkJSSE5ETzBOQlFTOURPenRCUVUxQkxGTkJRVk1zWTBGQlZDeERRVUYzUWl4UFFVRjRRaXhGUVVGblJEdEJRVU01UXl4VFFVRlBMRlZCUVZNc1MwRkJWQ3hGUVVFNFFqdEJRVU51UXl4WFFVRlBMRTlCUVU4c1ZVRkJVQ3hEUVVGclFpeExRVUZzUWl4TFFVRTBRaXhWUVVGVkxFOUJRVllzUTBGRVFUdEhRVUU1UWl4RFFVUjFRenREUVVGb1JEczdRVUZOUVN4VFFVRlRMR1ZCUVZRc1EwRkJlVUlzVDBGQmVrSXNSVUZCYVVRN1FVRkRMME1zVTBGQlR5eFZRVUZUTEV0QlFWUXNSVUZCT0VJN1FVRkRia01zVjBGQlR5eFBRVUZQTEZkQlFWQXNRMEZCYlVJc1MwRkJia0lzUzBGQk5rSXNWVUZCVlN4UFFVRldMRU5CUkVRN1IwRkJPVUlzUTBGRWQwTTdRMEZCYWtRN08wRkJUVUVzVTBGQlV5eFhRVUZVTEVOQlFYRkNMRTlCUVhKQ0xFVkJRVFpETzBGQlF6TkRMRk5CUVU4c1ZVRkJVeXhMUVVGVUxFVkJRVGhDTzBGQlEyNURMRmRCUVU4c1QwRkJUeXhQUVVGUUxFTkJRV1VzUzBGQlppeERRVUZRTEVOQlJHMURPMGRCUVRsQ0xFTkJSRzlETzBOQlFUZERPenRCUVUxQkxGTkJRVk1zV1VGQlZDeERRVUZ6UWl4UFFVRjBRaXhGUVVGelJEdEJRVU53UkN4VFFVRlBMRlZCUVZNc1MwRkJWQ3hGUVVGeFFpeEpRVUZ5UWl4RlFVRm5SRHRCUVVOeVJDeFJRVUZITEU5QlFVOHNTMEZCVUN4TFFVRnBRaXhQUVVGUExGRkJRVkVzUzBGQlVpeEpRVUZwUWl4VlFVRlZMRkZCUVZFc1MwRkJVaXhGUVVGak8wRkJRMnhGTEZkQlFVc3NTVUZCVEN4RFFVRlZMRXRCUVZZc1JVRkVhMFU3UVVGRmJFVXNZVUZCVHl4SlFVRlFMRU5CUm10Rk8wdEJRWEJGT3p0QlFVdEJMRmRCUVU4c1MwRkJVQ3hEUVU1eFJEdEhRVUZvUkN4RFFVUTJRenREUVVGMFJEczdRVUZYUVN4VFFVRlRMR1ZCUVZRc1IwRkJjVU03UVVGRGJrTXNVMEZCVHl4WlFVRnZRanRCUVVONlFpeFhRVUZQTEVsQlFWQXNRMEZFZVVJN1IwRkJjRUlzUTBGRU5FSTdRMEZCY2tNN08wRkJUVUVzVTBGQlV5eGxRVUZVTEVkQlFYRkRPMEZCUTI1RExGTkJRVThzVlVGQlV5eExRVUZVTEVWQlFYRkNMRWxCUVhKQ0xFVkJRV2RFTzBGQlEzSkVMRk5CUVVzc1NVRkJUQ3hEUVVGVkxFdEJRVllzUlVGRWNVUTdRVUZGY2tRc1YwRkJUeXhKUVVGUUxFTkJSbkZFTzBkQlFXaEVMRU5CUkRSQ08wTkJRWEpET3p0QlFVOUJMRk5CUVZNc1pVRkJWQ3hEUVVGNVFpeFBRVUY2UWl4RlFVRTBSRHRCUVVNeFJDeFJRVUZOTEdOQlFXTXNWMEZCVnl4UlFVRlJMRWxCUVZJc1EwRkJla0lzUTBGRWIwUTdRVUZGTVVRc1VVRkJUU3hqUVVGakxGZEJRVmNzVVVGQlVTeEpRVUZTTEVOQlFYcENMRU5CUm05RU96dEJRVWt4UkN4VFFVRlBMRlZCUVZNc1MwRkJWQ3hGUVVGeFFpeEpRVUZ5UWl4RlFVRm5SRHRCUVVOeVJDeFJRVUZITEVOQlFVTXNUMEZCVHl4UlFVRlFMRU5CUVdkQ0xFdEJRV2hDTEVOQlFVUXNTVUZCTWtJc1RVRkJUU3hOUVVGT0xFZEJRV1VzUTBGQlppeEZRVUZwUWp0QlFVTTNReXhoUVVGUExFdEJRVkFzUTBGRU5rTTdTMEZCTDBNN08wRkJTVUVzVlVGQlRTeFBRVUZQTEUxQlFVMHNRMEZCVGl4RFFVRlFMRU5CVEN0RE8wRkJUWEpFTEZWQlFVMHNUMEZCVHl4TlFVRk5MRXRCUVU0c1EwRkJXU3hEUVVGYUxFTkJRVkFzUTBGT0swTTdPMEZCVVhKRUxGRkJRVWNzV1VGQldTeEpRVUZhTEVWQlFXdENMRWxCUVd4Q0xFdEJRVEpDTEZsQlFWa3NTVUZCV2l4RlFVRnJRaXhKUVVGc1FpeERRVUV6UWl4RlFVRnRSRHRCUVVOd1JDeGhRVUZQTEVsQlFWQXNRMEZFYjBRN1MwRkJkRVE3UjBGU1N5eERRVXB0UkR0RFFVRTFSRHM3UVVGclFrRXNVMEZCVXl4alFVRlVMRU5CUVhkQ0xFOUJRWGhDTEVWQlFUQkVPMEZCUTNoRUxGRkJRVTBzVlVGQlZTeFhRVUZYTEZGQlFWRXNTMEZCVWl4RFFVRnlRaXhEUVVSclJEczdRVUZIZUVRc1UwRkJUeXhWUVVGVExFdEJRVlFzUlVGQmNVSXNTVUZCY2tJc1JVRkJaMFE3UVVGRGNrUXNVVUZCUnl4UlFVRlJMRXRCUVZJc1JVRkJaU3hKUVVGbUxFTkJRVWdzUlVGQmQwSTdRVUZEZEVJc1YwRkJTeXhKUVVGTUxFTkJRVlVzUzBGQlZpeEZRVVJ6UWp0QlFVVjBRaXhoUVVGUExFbEJRVkFzUTBGR2MwSTdTMEZCZUVJN08wRkJTMEVzVjBGQlR5eExRVUZRTEVOQlRuRkVPMGRCUVdoRUxFTkJTR2xFTzBOQlFURkVPenRCUVdGQkxGTkJRVk1zYVVKQlFWUXNRMEZCTWtJc1QwRkJNMElzUlVGQlowVTdRVUZET1VRc1VVRkJUU3hUUVVGVExGRkJRVkVzVFVGQlVpeERRVVFyUXpzN1FVRkhPVVFzVTBGQlR5eFZRVUZUTEV0QlFWUXNSVUZCY1VJc1NVRkJja0lzUlVGQlowUTdRVUZEY2tRc1VVRkJSeXhQUVVGUExGTkJRVkFzUTBGQmFVSXNTMEZCYWtJc1MwRkJNa0lzVFVGQlRTeFZRVUZPTEVOQlFXbENMRTFCUVdwQ0xFTkJRVE5DTEVWQlFXOUVPMEZCUTNKRUxGZEJRVXNzU1VGQlRDeERRVUZWTEUxQlFVMHNVMEZCVGl4RFFVRm5RaXhQUVVGUExFMUJRVkFzUTBGQk1VSXNSVUZFY1VRN1FVRkZja1FzWVVGQlR5eEpRVUZRTEVOQlJuRkVPMHRCUVhaRU96dEJRVXRCTEZkQlFVOHNTMEZCVUN4RFFVNXhSRHRIUVVGb1JDeERRVWgxUkR0RFFVRm9SVHM3UVVGaFFTeFRRVUZUTEZkQlFWUXNRMEZCY1VJc1QwRkJja0lzUlVGQmIwUTdRVUZEYkVRc1UwRkJUeXhWUVVGVExFdEJRVlFzUlVGQmNVSXNTVUZCY2tJc1JVRkJaMFE3UVVGRGNrUXNVVUZCUnl4cFFrRkJhVUlzVVVGQlVTeEpRVUZTTEVWQlFXRTdRVUZETDBJc1dVRkJUU3hWUVVGVkxGZEJRVmNzVVVGQlVTeFZRVUZTTEVOQlFYSkNMRU5CUkhsQ08wRkJSUzlDTEdGQlFVOHNVVUZCVVN4TFFVRlNMRVZCUVdVc1NVRkJaaXhMUVVGM1FpeExRVUZMTEVsQlFVd3NRMEZCVlN4TFFVRldMRWxCUVcxQ0xFTkJRVzVDTEVOQlJrRTdTMEZCYWtNN08wRkJTMEVzVjBGQlR5eExRVUZRTEVOQlRuRkVPMGRCUVdoRUxFTkJSREpETzBOQlFYQkVPenRCUVZkQkxGTkJRVk1zV1VGQlZDeERRVUZ6UWl4UFFVRjBRaXhGUVVGeFJEdEJRVU51UkN4UlFVRk5MRlZCUVZVc1VVRkJVU3hIUVVGU0xFTkJRVmtzUzBGQlN5eFhRVUZYTEVOQlFWZ3NRMEZCVEN4RFFVRjBRaXhEUVVRMlF6czdRVUZIYmtRc1UwRkJUeXhWUVVGVExFdEJRVlFzUlVGQmNVSXNTVUZCY2tJc1JVRkJaMFE3UVVGRGNrUXNVVUZCUnl4RFFVRkRMRTlCUVU4c1VVRkJVQ3hEUVVGblFpeExRVUZvUWl4RFFVRkVMRWxCUVRKQ0xFMUJRVTBzVFVGQlRpeEpRVUZuUWl4UlFVRlJMRTFCUVZJc1JVRkJaVHRCUVVNelJDeGhRVUZQTEV0QlFWQXNRMEZFTWtRN1MwRkJOMFE3TzBGQlNVRXNWMEZCVHl4TlFVRk5MRXRCUVU0c1EwRkJXU3hWUVVGVExFTkJRVlFzUlVGQldTeERRVUZhTEVWQlFXVTdRVUZEYUVNc1lVRkJUeXhSUVVGUkxFTkJRVklzUlVGQlZ5eE5RVUZOTEVOQlFVNHNRMEZCV0N4RlFVRnhRaXhKUVVGeVFpeERRVUZRTEVOQlJHZERPMHRCUVdZc1EwRkJia0lzUTBGTWNVUTdSMEZCYUVRc1EwRklORU03UTBGQmNrUTdPMEZCWTBFc1UwRkJVeXhoUVVGVUxFTkJRWFZDTEU5QlFYWkNMRVZCUVd0RU8wRkJRMmhFTEUxQlFVa3NWVUZCVlN4RlFVRldMRU5CUkRSRE96dEJRVWRvUkN4UFFVRkpMRWxCUVVrc1IwRkJTaXhKUVVGWExFOUJRVThzU1VGQlVDeERRVUZaTEU5QlFWb3NSVUZCY1VJc1RVRkJja0lzUTBGQk5FSXNUMEZCVHl4eFFrRkJVQ3hEUVVFMlFpeFBRVUUzUWl4RFFVRTFRaXhEUVVGbUxFVkJRV3RHTzBGQlEyaEdMRmxCUVZFc1IwRkJVaXhKUVVGbExGZEJRVmNzVVVGQlVTeEhRVUZTTEVOQlFWZ3NRMEZCWml4RFFVUm5SanRIUVVGc1JqczdRVUZKUVN4VFFVRlBMRlZCUVZNc1MwRkJWQ3hGUVVGeFFpeEpRVUZ5UWl4RlFVRm5SRHRCUVVOeVJDeFJRVUZITEVOQlFVTXNUMEZCVHl4VFFVRlFMRU5CUVdsQ0xFdEJRV3BDTEVOQlFVUXNTVUZCTkVJc1VVRkJVU3hOUVVGU0xFZEJRV2xDTEUxQlFVMHNUVUZCVGl4RlFVRmhPMEZCUXpORUxHRkJRVThzUzBGQlVDeERRVVF5UkR0TFFVRTNSRHM3UVVGSlFTeFRRVUZKTEVsQlFVa3NSMEZCU2l4SlFVRlhMRTlCUVU4c1NVRkJVQ3hEUVVGWkxFOUJRVm9zUlVGQmNVSXNUVUZCY2tJc1EwRkJORUlzVDBGQlR5eHhRa0ZCVUN4RFFVRTJRaXhQUVVFM1FpeERRVUUxUWl4RFFVRm1MRVZCUVd0R08wRkJRMmhHTEZWQlFVY3NSVUZCUlN4UFFVRlBMRXRCUVZBc1EwRkJSaXhKUVVGdFFpeERRVUZETEZGQlFWRXNSMEZCVWl4RlFVRmhMRTFCUVUwc1IwRkJUaXhEUVVGaUxFVkJRWGxDTEVsQlFYcENMRU5CUVVRc1JVRkJhVU03UVVGRGNrUXNaVUZCVHl4TFFVRlFMRU5CUkhGRU8wOUJRWFpFTzB0QlJFWTdPMEZCVFVFc1YwRkJUeXhKUVVGUUxFTkJXSEZFTzBkQlFXaEVMRU5CVUhsRE8wTkJRV3hFT3p0QlFYTkNRU3hUUVVGVExHZENRVUZVTEVOQlFUQkNMRTlCUVRGQ0xFVkJRVzFGTzBGQlEycEZMRTFCUVVrc2JVSkJRVzFDTEVWQlFXNUNMRU5CUkRaRU96dEJRVWRxUlN4UFFVRkpMRWxCUVVrc2EwSkJRVW9zU1VGQk1FSXNVVUZCVVN4TlFVRlNMRVZCUVdVN1FVRkRNME1zVVVGQlJ5eFBRVUZQTEZkQlFWQXNRMEZCYlVJc2JVSkJRVzFDTEV0QlFXNUNMRU5CUVhSQ0xFVkJRV2RFTzBGQlF6bERMRlZCUVVrc1QwRkJUeXhSUVVGUkxHMUNRVUZ0UWl4SlFVRnVRaXhGUVVGNVFpeHRRa0ZCYlVJc1NVRkJia0lzUTBGQmVFTXNRMEZFTUVNN1FVRkZPVU1zWjBKQlFWVXNaMEpCUVZZc1JVRkJORUlzU1VGQk5VSXNSVUZHT0VNN1MwRkJhRVFzVFVGSFN6dEJRVU5JTEhsQ1FVRnRRaXhwUWtGQmFVSXNUVUZCYWtJc1EwRkJkMElzU1VGQlNTeFRRVUZLTEVOQlFXTXNhMEpCUVdRc1JVRkJhME1zUzBGQmJFTXNRMEZCTTBNc1EwRkVSenRMUVVoTU8wZEJSRVk3TzBGQlUwRXNUVUZCU1N4blFrRkJaMElzVVVGQlVTeE5RVUZTTEVOQldqWkRPenRCUVdOcVJTeFRRVUZQTEZWQlFWTXNTMEZCVkN4RlFVRnhRaXhKUVVGeVFpeEZRVUZuUkR0QlFVTnlSQ3hSUVVGSkxGVkJRVlVzU1VGQlZpeERRVVJwUkRzN1FVRkhja1FzVVVGQlJ5eERRVUZETEU5QlFVOHNVMEZCVUN4RFFVRnBRaXhMUVVGcVFpeERRVUZFTEVsQlFUUkNMRVZCUVVVc2FVSkJRV2xDTEZOQlFXcENMRU5CUVVZc1JVRkJLMEk3UVVGRE5VUXNZVUZCVHl4TFFVRlFMRU5CUkRSRU8wdEJRVGxFT3p0QlFVbEJMRkZCUVVjc1QwRkJUeXhUUVVGUUxFTkJRV2xDTEV0QlFXcENMRU5CUVVnc1JVRkJNa0k3UVVGRGVrSXNaMEpCUVZVc1NVRkJTU3hUUVVGS0xFTkJRV01zVlVGQlZTeE5RVUZXTEVOQlFXbENMRXRCUVdwQ0xFTkJRV1FzUTBGQlZpeERRVVI1UWp0TFFVRXpRaXhOUVVWTE8wRkJRMGdzWjBKQlFWVXNTMEZCVml4RFFVUkhPMHRCUmt3N08wRkJUVUVzVVVGQlNTeHBRa0ZCYVVJc1EwRkJha0lzUTBGaWFVUTdPMEZCWlhKRUxGTkJRVWtzU1VGQlNTeEpRVUZKTEVOQlFVb3NSVUZCVHl4SlFVRkpMR05CUVdNc1RVRkJaQ3hGUVVGelFpeEhRVUY2UXl4RlFVRTJRenRCUVVNelF5eFZRVUZKTEhGQ1FVRnhRaXhqUVVGakxFTkJRV1FzUTBGQmNrSXNRMEZFZFVNN08wRkJSek5ETEZWQlFVY3NUMEZCVHl4WFFVRlFMRU5CUVcxQ0xHMUNRVUZ0UWl4TFFVRnVRaXhEUVVGdVFpeEpRVU5CTEcxQ1FVRnRRaXhKUVVGdVFpeEpRVUV5UWl4UlFVRXpRaXhKUVVOQkxHMUNRVUZ0UWl4SlFVRnVRaXhMUVVFMFFpeFRRVUUxUWl4SlFVTkJMRWxCUVVrc1kwRkJZeXhOUVVGa0xFZEJRWFZDTEVOQlFYWkNMRVZCUVhsQ08wRkJRemxDTEdOQlFVMHNTVUZCU1N4TFFVRktMRU5CUVZVc05FVkJRVllzUTBGQlRpeERRVVE0UWp0UFFVaG9RenM3UVVGUFFTeFZRVUZKTEU5QlFVOHNRMEZCVUN4RFFWWjFRenRCUVZjelF5eFZRVUZKTEcxQ1FVRnRRaXhGUVVGdVFpeERRVmgxUXp0QlFWa3pReXhWUVVGSkxEUkNRVUUwUWl4RlFVRTFRaXhEUVZwMVF6dEJRV0V6UXl4aFFVRlBMRkZCUVZFc2JVSkJRVzFDTEVsQlFXNUNMRVZCUVhsQ0xHMUNRVUZ0UWl4SlFVRnVRaXhEUVVGNFF5eERRV0l5UXpzN1FVRmxNME1zVlVGQlJ5eE5RVUZOTEdOQlFXTXNUVUZCWkN4SFFVRjFRaXhEUVVGMlFpeEZRVUY1UWp0QlFVTm9ReXd5UWtGQmJVSXNVVUZCVVN4TFFVRlNMRU5CUVdNc1MwRkJaQ3hEUVVGdlFpeGpRVUZ3UWl4RFFVRnVRaXhEUVVSblF6dEJRVVZvUXl4dlEwRkJORUlzYVVKQlFXbENMRXRCUVdwQ0xFTkJRWFZDTEdOQlFYWkNMRU5CUVRWQ0xFTkJSbWRETzA5QlFXeERMRTFCUjA4N1FVRkRUQ3d5UWtGQmJVSXNVVUZCVVN4TFFVRlNMRU5CUVdNc1MwRkJaQ3hEUVVGdlFpeGpRVUZ3UWl4RlFVRnZReXhwUWtGQmFVSXNTVUZCYWtJc1EwRkJka1FzUTBGRVN6dEJRVVZNTEc5RFFVRTBRaXhwUWtGQmFVSXNTMEZCYWtJc1EwRkJkVUlzWTBGQmRrSXNSVUZCZFVNc2FVSkJRV2xDTEVsQlFXcENMRU5CUVc1RkxFTkJSa3M3VDBGSVVEczdRVUZSUVN4VlFVRkhMRTlCUVU4c1YwRkJVQ3hEUVVGdFFpeHRRa0ZCYlVJc1MwRkJia0lzUTBGQmRFSXNSVUZCWjBRN1FVRkRPVU1zWjBKQlFVOHNiVUpCUVcxQ0xFbEJRVzVDTzBGQlExQXNaVUZCU3l4VFFVRk1PMEZCUTBVc1owSkJRVWNzYlVKQlFXMUNMRlZCUVc1Q0xFbEJRV2xETEcxQ1FVRnRRaXhWUVVGdVFpeERRVUU0UWl4UFFVRTVRaXhEUVVGelF5eFJRVUYwUXl4TFFVRnRSQ3hEUVVGRExFTkJRVVFzUlVGQlJ6dEJRVU40Uml4dFFrRkJTeXhKUVVGTUxFTkJRVlVzU1VGQlNTeFRRVUZLTEVOQlFXTXNRMEZCUXl4cFFrRkJhVUlzUTBGQmFrSXNRMEZCUkN4RFFVRmtMRVZCUVhGRExFTkJRWEpETEVOQlFWWXNSVUZFZDBZN1lVRkJNVVlzVFVGRlR6dEJRVU5NTEcxQ1FVRkxMRWxCUVV3c1EwRkJWU3hKUVVGSkxGVkJRVW9zUTBGQlpTeERRVUZETEdsQ1FVRnBRaXhEUVVGcVFpeERRVUZFTEVOQlFXWXNSVUZCYzBNc1EwRkJkRU1zUTBGQlZpeEZRVVJMTzJGQlJsQTdRVUZMUVN4clFrRk9SanM3UVVGRVFTeGxRVk5MTEU5QlFVdzdRVUZEUlN4blFrRkJSeXhUUVVGVExFVkJRVlFzUlVGQldUdEJRVU5pTEcxQ1FVRkxMRWxCUVV3c1EwRkJWU3hoUVVGaExFbEJRV0lzUTBGQmEwSXNaMEpCUVd4Q0xFVkJRVzlETEVOQlFYQkRMRU5CUVZZc1JVRkVZVHRoUVVGbUxFMUJSVThzU1VGQlJ5eFRRVUZUTEVWQlFWUXNSVUZCV1R0QlFVTndRaXh0UWtGQlN5eEpRVUZNTEVOQlFWVXNZVUZCWVN4SlFVRmlMRU5CUVd0Q0xHZENRVUZzUWl4RlFVRnZReXhEUVVGd1F5eERRVUZXTEVWQlJHOUNPMkZCUVdZc1RVRkZSanRCUVVOSUxIRkNRVUZQTEV0QlFWQXNRMEZFUnp0aFFVWkZPMEZCUzFBc2EwSkJVa1k3TzBGQlZFRXNaVUZ0UWtzc1YwRkJURHRCUVVORkxHbENRVUZMTEVsQlFVd3NRMEZCVlN4blFrRkJaMElzWjBKQlFXaENMRU5CUVZZc1JVRkVSanRCUVVWRkxHdENRVVpHT3p0QlFXNUNRU3hsUVhWQ1N5eFJRVUZNTzBGQlEwVXNhVUpCUVVzc1NVRkJUQ3hEUVVGVkxFOUJRVThzV1VGQlVDeERRVUZ2UWl4TFFVRndRaXhEUVVFd1FpeEpRVUV4UWl4RlFVRm5ReXhKUVVGSkxGVkJRVW9zUTBGQlpTeG5Ra0ZCWml4RFFVRm9ReXhEUVVGV0xFVkJSRVk3UVVGRlJTeHJRa0ZHUmpzN1FVRjJRa0VzWlVFeVFrc3NUVUZCVER0QlFVTkZMR2xDUVVGTExFbEJRVXdzUTBGQlZTeFBRVUZQTEZsQlFWQXNRMEZCYjBJc1MwRkJjRUlzUTBGQk1FSXNTVUZCTVVJc1JVRkJaME1zU1VGQlNTeFZRVUZLTEVOQlFXVXNaMEpCUVdZc1EwRkJhRU1zUTBGQlZpeEZRVVJHTzBGQlJVVXNhMEpCUmtZN08wRkJNMEpCTEdWQkswSkxMRTlCUVV3N1FVRkRSU3hwUWtGQlN5eEpRVUZNTEVOQlFWVXNUMEZCVHl4WlFVRlFMRU5CUVc5Q0xFdEJRWEJDTEVOQlFUQkNMRWxCUVRGQ0xFVkJRV2RETEVsQlFVa3NWMEZCU2l4RFFVRm5RaXhuUWtGQmFFSXNRMEZCYUVNc1EwRkJWaXhGUVVSR08wRkJSVVVzYTBKQlJrWTdPMEZCTDBKQkxHVkJiVU5MTEU5QlFVdzdRVUZEUlN4cFFrRkJTeXhKUVVGTUxFTkJRVlVzVDBGQlR5eFpRVUZRTEVOQlFXOUNMRXRCUVhCQ0xFTkJRVEJDTEVsQlFURkNMRVZCUVdkRExFbEJRVWtzVjBGQlNpeERRVUZuUWl4blFrRkJhRUlzUTBGQmFFTXNRMEZCVml4RlFVUkdPMEZCUlVVc2EwSkJSa1k3TzBGQmJrTkJPMEZCZDBORkxHMUNRVUZQTEV0QlFWQXNRMEZFUmp0QlFYWkRRU3hUUVVRNFF6dFBRVUZvUkN4TlFUSkRUU3hKUVVGSExFTkJRVU1zV1VGQldTeG5Ra0ZCV2l4RlFVRTRRaXg1UWtGQk9VSXNRMEZCUkN4RlFVRXlSRHRCUVVOc1JTeGxRVUZQTEV0QlFWQXNRMEZFYTBVN1QwRkJPVVE3TzBGQlNVNHNkVUpCUVdsQ0xHbENRVUZwUWl4SlFVRnFRaXhEUVhSRk1FSTdTMEZCTjBNN08wRkJlVVZCTEZkQlFVOHNTVUZCVUN4RFFYaEdjVVE3UjBGQmFFUXNRMEZrTUVRN1EwRkJia1U3TzBGQk1rZEJMRk5CUVZNc1QwRkJWQ3hEUVVGcFFpeEpRVUZxUWl4RlFVRjFRaXhKUVVGMlFpeEZRVUUwUWp0QlFVTXhRaXhUUVVGUExFbEJRVU1zUjBGQlR5eEpRVUZRTEVkQlFXVXNRMEZCYUVJc1EwRkViVUk3UTBGQk5VSTdPMEZCU1VFc1UwRkJVeXhYUVVGVUxFTkJRWEZDTEVOQlFYSkNMRVZCUVhkQ0xFTkJRWGhDTEVWQlFUSkNPMEZCUTNwQ0xFMUJRVWtzVFVGQlRTeERRVUZPTEVWQlFWTXNUMEZCVHl4SlFVRlFMRU5CUVdJN1FVRkRRU3hOUVVGSkxFdEJRVXNzU1VGQlRDeEpRVUZoTEV0QlFVc3NTVUZCVEN4RlFVRlhMRTlCUVU4c1MwRkJVQ3hEUVVFMVFqdEJRVU5CTEUxQlFVa3NSVUZCUlN4TlFVRkdMRWxCUVZrc1JVRkJSU3hOUVVGR0xFVkJRVlVzVDBGQlR5eExRVUZRTEVOQlFURkNPenRCUVVWQkxFOUJRVXNzU1VGQlNTeEpRVUZKTEVOQlFVb3NSVUZCVHl4SlFVRkpMRVZCUVVVc1RVRkJSaXhGUVVGVkxFVkJRVVVzUTBGQlJpeEZRVUZMTzBGQlEycERMRkZCUVVrc1JVRkJSU3hEUVVGR0xFMUJRVk1zUlVGQlJTeERRVUZHTEVOQlFWUXNSVUZCWlN4UFFVRlBMRXRCUVZBc1EwRkJia0k3UjBGRVJqczdRVUZKUVN4VFFVRlBMRWxCUVZBc1EwRlVlVUk3UTBGQk0wSTdPMEZCV1VFc1UwRkJVeXhUUVVGVUxFTkJRVzFDTEVkQlFXNUNMRVZCUVhkQ0xFZEJRWGhDTEVWQlFUUkNPMEZCUXpGQ0xFOUJRVWtzU1VGQlNTeEpRVUZKTEVOQlFVb3NSVUZCVHl4SlFVRkpMRWRCUVVvc1JVRkJVeXhIUVVGNFFpeEZRVUUwUWp0QlFVTXhRaXhSUVVGSkxFbEJRVW9zUTBGQlV5eERRVUZVTEVWQlJEQkNPMGRCUVRWQ08wTkJSRVk3TzBGQlRVRXNVMEZCVXl4bFFVRlVMRU5CUVhsQ0xFZEJRWHBDTEVWQlFUWkNPMEZCUXpOQ0xFMUJRVWtzWlVGQlpTeEpRVUZKTEVkQlFVb3NRMEZCVVN4UlFVRlZMRlZCUVZVc1QwRkJWaXhEUVVGclFpeEpRVUZzUWl4RFFVRldMRU5CUVhaQ0xFTkJSSFZDTzBGQlJUTkNMRk5CUVU4c1NVRkJTU3hUUVVGS0xFTkJRV01zUjBGQlJ5eFpRVUZJTEVOQlFYSkNMRU5CUmpKQ08wTkJRVGRDT3p0QlFVdEJMRk5CUVZNc1kwRkJWQ3hIUVVGdlF6dEJRVU5zUXl4VFFVRlBMRmxCUVc5Q08wRkJRM3BDTEZkQlFVOHNTMEZCVUN4RFFVUjVRanRIUVVGd1FpeERRVVF5UWp0RFFVRndRenM3UVVGTlFTeGxRVUZsTzBGQlEySXNZMEZFWVR0QlFVVmlMR2xDUVVaaE8wRkJSMklzYVVKQlNHRTdRVUZKWWl4cFFrRktZVHRCUVV0aUxHZENRVXhoTzBGQlRXSXNiVUpCVG1FN1FVRlBZaXhoUVZCaE8wRkJVV0lzWTBGU1lUdEJRVk5pTEdWQlZHRTdRVUZWWWl4blFrRldZVHRCUVZkaUxHVkJXR0U3UVVGWllpeGxRVnBoTzBGQllXSXNaVUZpWVR0QlFXTmlMR2RDUVdSaE8wRkJaV0lzYVVKQlptRTdRVUZuUW1Jc1lVRm9RbUU3UVVGcFFtSXNhMEpCYWtKaE8wTkJRV1lpTENKbWFXeGxJam9pYkdsaUwyTnZjbVV2Y0dGMGRHVnlibk12Y21WemIyeDJaWEp6TG1weklpd2ljMjkxY21ObGMwTnZiblJsYm5RaU9sc2lMeW9nUUdac2IzY2dLaTljYmx4dWFXMXdiM0owSUVOb1pXTnJjeUJtY205dElGd2lMaTlqYUdWamEzTmNJanRjYm1sdGNHOXlkQ0FxSUdGeklGUjVjR1Z6SUdaeWIyMGdYQ0l1TDNSNWNHVnpYQ0k3WEc1cGJYQnZjblFnZXlCaWRXbHNaRTFoZEdOb0lIMGdabkp2YlNCY0lpNHZiV0YwWTJoY0lqdGNibWx0Y0c5eWRDQkNhWFJUZEhKcGJtY2dabkp2YlNCY0lpNHVMMkpwZEY5emRISnBibWRjSWp0Y2JseHVablZ1WTNScGIyNGdjbVZ6YjJ4MlpWTjViV0p2YkNod1lYUjBaWEp1T2lCaGJua3BPaUJHZFc1amRHbHZiaUI3WEc0Z0lISmxkSFZ5YmlCbWRXNWpkR2x2YmloMllXeDFaVG9nWVc1NUtUb2dZbTl2YkdWaGJpQjdYRzRnSUNBZ2NtVjBkWEp1SUVOb1pXTnJjeTVwYzE5emVXMWliMndvZG1Gc2RXVXBJQ1ltSUhaaGJIVmxJRDA5UFNCd1lYUjBaWEp1TzF4dUlDQjlPMXh1ZlZ4dVhHNW1kVzVqZEdsdmJpQnlaWE52YkhabFUzUnlhVzVuS0hCaGRIUmxjbTQ2SUdGdWVTazZJRVoxYm1OMGFXOXVJSHRjYmlBZ2NtVjBkWEp1SUdaMWJtTjBhVzl1S0haaGJIVmxPaUJoYm5rcE9pQmliMjlzWldGdUlIdGNiaUFnSUNCeVpYUjFjbTRnUTJobFkydHpMbWx6WDNOMGNtbHVaeWgyWVd4MVpTa2dKaVlnZG1Gc2RXVWdQVDA5SUhCaGRIUmxjbTQ3WEc0Z0lIMDdYRzU5WEc1Y2JtWjFibU4wYVc5dUlISmxjMjlzZG1WT2RXMWlaWElvY0dGMGRHVnliam9nWVc1NUtUb2dSblZ1WTNScGIyNGdlMXh1SUNCeVpYUjFjbTRnWm5WdVkzUnBiMjRvZG1Gc2RXVTZJR0Z1ZVNrNklHSnZiMnhsWVc0Z2UxeHVJQ0FnSUhKbGRIVnliaUJEYUdWamEzTXVhWE5mYm5WdFltVnlLSFpoYkhWbEtTQW1KaUIyWVd4MVpTQTlQVDBnY0dGMGRHVnlianRjYmlBZ2ZUdGNibjFjYmx4dVpuVnVZM1JwYjI0Z2NtVnpiMngyWlVKdmIyeGxZVzRvY0dGMGRHVnliam9nWVc1NUtUb2dSblZ1WTNScGIyNGdlMXh1SUNCeVpYUjFjbTRnWm5WdVkzUnBiMjRvZG1Gc2RXVTZJR0Z1ZVNrNklHSnZiMnhsWVc0Z2UxeHVJQ0FnSUhKbGRIVnliaUJEYUdWamEzTXVhWE5mWW05dmJHVmhiaWgyWVd4MVpTa2dKaVlnZG1Gc2RXVWdQVDA5SUhCaGRIUmxjbTQ3WEc0Z0lIMDdYRzU5WEc1Y2JtWjFibU4wYVc5dUlISmxjMjlzZG1WR2RXNWpkR2x2Ymlod1lYUjBaWEp1T2lCaGJua3BPaUJHZFc1amRHbHZiaUI3WEc0Z0lISmxkSFZ5YmlCbWRXNWpkR2x2YmloMllXeDFaVG9nWVc1NUtUb2dZbTl2YkdWaGJpQjdYRzRnSUNBZ2NtVjBkWEp1SUVOb1pXTnJjeTVwYzE5bWRXNWpkR2x2YmloMllXeDFaU2tnSmlZZ2RtRnNkV1VnUFQwOUlIQmhkSFJsY200N1hHNGdJSDA3WEc1OVhHNWNibVoxYm1OMGFXOXVJSEpsYzI5c2RtVk9kV3hzS0hCaGRIUmxjbTQ2SUdGdWVTazZJRVoxYm1OMGFXOXVJSHRjYmlBZ2NtVjBkWEp1SUdaMWJtTjBhVzl1S0haaGJIVmxPaUJoYm5rcE9pQmliMjlzWldGdUlIdGNiaUFnSUNCeVpYUjFjbTRnUTJobFkydHpMbWx6WDI1MWJHd29kbUZzZFdVcE8xeHVJQ0I5TzF4dWZWeHVYRzVtZFc1amRHbHZiaUJ5WlhOdmJIWmxRbTkxYm1Rb2NHRjBkR1Z5YmpvZ1ZIbHdaWE11UW05MWJtUXBPaUJHZFc1amRHbHZiaUI3WEc0Z0lISmxkSFZ5YmlCbWRXNWpkR2x2YmloMllXeDFaVG9nWVc1NUxDQmhjbWR6T2lCQmNuSmhlVHhoYm5rK0tUb2dZbTl2YkdWaGJpQjdYRzRnSUNBZ2FXWW9kSGx3Wlc5bUlIWmhiSFZsSUQwOVBTQjBlWEJsYjJZZ2NHRjBkR1Z5Ymk1MllXeDFaU0FtSmlCMllXeDFaU0E5UFQwZ2NHRjBkR1Z5Ymk1MllXeDFaU2w3WEc0Z0lDQWdJQ0JoY21kekxuQjFjMmdvZG1Gc2RXVXBPMXh1SUNBZ0lDQWdjbVYwZFhKdUlIUnlkV1U3WEc0Z0lDQWdmVnh1WEc0Z0lDQWdjbVYwZFhKdUlHWmhiSE5sTzF4dUlDQjlPMXh1ZlZ4dVhHNW1kVzVqZEdsdmJpQnlaWE52YkhabFYybHNaR05oY21Rb0tUb2dSblZ1WTNScGIyNGdlMXh1SUNCeVpYUjFjbTRnWm5WdVkzUnBiMjRvS1RvZ1ltOXZiR1ZoYmlCN1hHNGdJQ0FnY21WMGRYSnVJSFJ5ZFdVN1hHNGdJSDA3WEc1OVhHNWNibVoxYm1OMGFXOXVJSEpsYzI5c2RtVldZWEpwWVdKc1pTZ3BPaUJHZFc1amRHbHZiaUI3WEc0Z0lISmxkSFZ5YmlCbWRXNWpkR2x2YmloMllXeDFaVG9nWVc1NUxDQmhjbWR6T2lCQmNuSmhlVHhoYm5rK0tUb2dZbTl2YkdWaGJpQjdYRzRnSUNBZ1lYSm5jeTV3ZFhOb0tIWmhiSFZsS1R0Y2JpQWdJQ0J5WlhSMWNtNGdkSEoxWlR0Y2JpQWdmVHRjYm4xY2JseHVablZ1WTNScGIyNGdjbVZ6YjJ4MlpVaGxZV1JVWVdsc0tIQmhkSFJsY200NklGUjVjR1Z6TGtobFlXUlVZV2xzS1RvZ1JuVnVZM1JwYjI0Z2UxeHVJQ0JqYjI1emRDQm9aV0ZrVFdGMFkyaGxjeUE5SUdKMWFXeGtUV0YwWTJnb2NHRjBkR1Z5Ymk1b1pXRmtLVHRjYmlBZ1kyOXVjM1FnZEdGcGJFMWhkR05vWlhNZ1BTQmlkV2xzWkUxaGRHTm9LSEJoZEhSbGNtNHVkR0ZwYkNrN1hHNWNiaUFnY21WMGRYSnVJR1oxYm1OMGFXOXVLSFpoYkhWbE9pQmhibmtzSUdGeVozTTZJRUZ5Y21GNVBHRnVlVDRwT2lCaWIyOXNaV0Z1SUh0Y2JpQWdJQ0JwWmlnaFEyaGxZMnR6TG1selgyRnljbUY1S0haaGJIVmxLU0I4ZkNCMllXeDFaUzVzWlc1bmRHZ2dQQ0F5S1h0Y2JpQWdJQ0FnSUhKbGRIVnliaUJtWVd4elpUdGNiaUFnSUNCOVhHNWNiaUFnSUNCamIyNXpkQ0JvWldGa0lEMGdkbUZzZFdWYk1GMDdYRzRnSUNBZ1kyOXVjM1FnZEdGcGJDQTlJSFpoYkhWbExuTnNhV05sS0RFcE8xeHVYRzRnSUNBZ2FXWW9hR1ZoWkUxaGRHTm9aWE1vYUdWaFpDd2dZWEpuY3lrZ0ppWWdkR0ZwYkUxaGRHTm9aWE1vZEdGcGJDd2dZWEpuY3lrcGUxeHVJQ0FnSUNBZ2NtVjBkWEp1SUhSeWRXVTdYRzRnSUNBZ2ZWeHVJQ0I5TzF4dWZWeHVYRzVtZFc1amRHbHZiaUJ5WlhOdmJIWmxRMkZ3ZEhWeVpTaHdZWFIwWlhKdU9pQlVlWEJsY3k1RFlYQjBkWEpsS1RvZ1JuVnVZM1JwYjI0Z2UxeHVJQ0JqYjI1emRDQnRZWFJqYUdWeklEMGdZblZwYkdSTllYUmphQ2h3WVhSMFpYSnVMblpoYkhWbEtUdGNibHh1SUNCeVpYUjFjbTRnWm5WdVkzUnBiMjRvZG1Gc2RXVTZJR0Z1ZVN3Z1lYSm5jem9nUVhKeVlYazhZVzU1UGlrNklHSnZiMnhsWVc0Z2UxeHVJQ0FnSUdsbUtHMWhkR05vWlhNb2RtRnNkV1VzSUdGeVozTXBLWHRjYmlBZ0lDQWdJR0Z5WjNNdWNIVnphQ2gyWVd4MVpTazdYRzRnSUNBZ0lDQnlaWFIxY200Z2RISjFaVHRjYmlBZ0lDQjlYRzVjYmlBZ0lDQnlaWFIxY200Z1ptRnNjMlU3WEc0Z0lIMDdYRzU5WEc1Y2JtWjFibU4wYVc5dUlISmxjMjlzZG1WVGRHRnlkSE5YYVhSb0tIQmhkSFJsY200NklGUjVjR1Z6TGxOMFlYSjBjMWRwZEdncE9pQkdkVzVqZEdsdmJpQjdYRzRnSUdOdmJuTjBJSEJ5WldacGVDQTlJSEJoZEhSbGNtNHVjSEpsWm1sNE8xeHVYRzRnSUhKbGRIVnliaUJtZFc1amRHbHZiaWgyWVd4MVpUb2dZVzU1TENCaGNtZHpPaUJCY25KaGVUeGhibmsrS1RvZ1ltOXZiR1ZoYmlCN1hHNGdJQ0FnYVdZb1EyaGxZMnR6TG1selgzTjBjbWx1WnloMllXeDFaU2tnSmlZZ2RtRnNkV1V1YzNSaGNuUnpWMmwwYUNod2NtVm1hWGdwS1h0Y2JpQWdJQ0FnSUdGeVozTXVjSFZ6YUNoMllXeDFaUzV6ZFdKemRISnBibWNvY0hKbFptbDRMbXhsYm1kMGFDa3BPMXh1SUNBZ0lDQWdjbVYwZFhKdUlIUnlkV1U3WEc0Z0lDQWdmVnh1WEc0Z0lDQWdjbVYwZFhKdUlHWmhiSE5sTzF4dUlDQjlPMXh1ZlZ4dVhHNW1kVzVqZEdsdmJpQnlaWE52YkhabFZIbHdaU2h3WVhSMFpYSnVPaUJVZVhCbGN5NVVlWEJsS1RvZ1JuVnVZM1JwYjI0Z2UxeHVJQ0J5WlhSMWNtNGdablZ1WTNScGIyNG9kbUZzZFdVNklHRnVlU3dnWVhKbmN6b2dRWEp5WVhrOFlXNTVQaWs2SUdKdmIyeGxZVzRnZTF4dUlDQWdJR2xtS0haaGJIVmxJR2x1YzNSaGJtTmxiMllnY0dGMGRHVnliaTUwZVhCbEtYdGNiaUFnSUNBZ0lHTnZibk4wSUcxaGRHTm9aWE1nUFNCaWRXbHNaRTFoZEdOb0tIQmhkSFJsY200dWIySnFVR0YwZEdWeWJpazdYRzRnSUNBZ0lDQnlaWFIxY200Z2JXRjBZMmhsY3loMllXeDFaU3dnWVhKbmN5a2dKaVlnWVhKbmN5NXdkWE5vS0haaGJIVmxLU0ErSURBN1hHNGdJQ0FnZlZ4dVhHNGdJQ0FnY21WMGRYSnVJR1poYkhObE8xeHVJQ0I5TzF4dWZWeHVYRzVtZFc1amRHbHZiaUJ5WlhOdmJIWmxRWEp5WVhrb2NHRjBkR1Z5YmpvZ1FYSnlZWGs4WVc1NVBpazZJRVoxYm1OMGFXOXVJSHRjYmlBZ1kyOXVjM1FnYldGMFkyaGxjeUE5SUhCaGRIUmxjbTR1YldGd0tIZ2dQVDRnWW5WcGJHUk5ZWFJqYUNoNEtTazdYRzVjYmlBZ2NtVjBkWEp1SUdaMWJtTjBhVzl1S0haaGJIVmxPaUJoYm5rc0lHRnlaM002SUVGeWNtRjVQR0Z1ZVQ0cE9pQmliMjlzWldGdUlIdGNiaUFnSUNCcFppZ2hRMmhsWTJ0ekxtbHpYMkZ5Y21GNUtIWmhiSFZsS1NCOGZDQjJZV3gxWlM1c1pXNW5kR2dnSVQwZ2NHRjBkR1Z5Ymk1c1pXNW5kR2dwZTF4dUlDQWdJQ0FnY21WMGRYSnVJR1poYkhObE8xeHVJQ0FnSUgxY2JseHVJQ0FnSUhKbGRIVnliaUIyWVd4MVpTNWxkbVZ5ZVNobWRXNWpkR2x2YmloMkxDQnBLU0I3WEc0Z0lDQWdJQ0J5WlhSMWNtNGdiV0YwWTJobGMxdHBYU2gyWVd4MVpWdHBYU3dnWVhKbmN5azdYRzRnSUNBZ2ZTazdYRzRnSUgwN1hHNTlYRzVjYm1aMWJtTjBhVzl1SUhKbGMyOXNkbVZQWW1wbFkzUW9jR0YwZEdWeWJqb2dUMkpxWldOMEtUb2dSblZ1WTNScGIyNGdlMXh1SUNCc1pYUWdiV0YwWTJobGN5QTlJSHQ5TzF4dVhHNGdJR1p2Y2loc1pYUWdhMlY1SUc5bUlFOWlhbVZqZEM1clpYbHpLSEJoZEhSbGNtNHBMbU52Ym1OaGRDaFBZbXBsWTNRdVoyVjBUM2R1VUhKdmNHVnlkSGxUZVcxaWIyeHpLSEJoZEhSbGNtNHBLU2w3WEc0Z0lDQWdiV0YwWTJobGMxdHJaWGxkSUQwZ1luVnBiR1JOWVhSamFDaHdZWFIwWlhKdVcydGxlVjBwTzF4dUlDQjlYRzVjYmlBZ2NtVjBkWEp1SUdaMWJtTjBhVzl1S0haaGJIVmxPaUJoYm5rc0lHRnlaM002SUVGeWNtRjVQR0Z1ZVQ0cE9pQmliMjlzWldGdUlIdGNiaUFnSUNCcFppZ2hRMmhsWTJ0ekxtbHpYMjlpYW1WamRDaDJZV3gxWlNrZ2ZId2djR0YwZEdWeWJpNXNaVzVuZEdnZ1BpQjJZV3gxWlM1c1pXNW5kR2dwZTF4dUlDQWdJQ0FnY21WMGRYSnVJR1poYkhObE8xeHVJQ0FnSUgxY2JseHVJQ0FnSUdadmNpaHNaWFFnYTJWNUlHOW1JRTlpYW1WamRDNXJaWGx6S0hCaGRIUmxjbTRwTG1OdmJtTmhkQ2hQWW1wbFkzUXVaMlYwVDNkdVVISnZjR1Z5ZEhsVGVXMWliMnh6S0hCaGRIUmxjbTRwS1NsN1hHNGdJQ0FnSUNCcFppZ2hLR3RsZVNCcGJpQjJZV3gxWlNrZ2ZId2dJVzFoZEdOb1pYTmJhMlY1WFNoMllXeDFaVnRyWlhsZExDQmhjbWR6S1NBcGUxeHVJQ0FnSUNBZ0lDQnlaWFIxY200Z1ptRnNjMlU3WEc0Z0lDQWdJQ0I5WEc0Z0lDQWdmVnh1WEc0Z0lDQWdjbVYwZFhKdUlIUnlkV1U3WEc0Z0lIMDdYRzU5WEc1Y2JtWjFibU4wYVc5dUlISmxjMjlzZG1WQ2FYUlRkSEpwYm1jb2NHRjBkR1Z5YmpvZ1ZIbHdaWE11UW1sMFUzUnlhVzVuVFdGMFkyZ3BPaUJHZFc1amRHbHZiaUI3WEc0Z0lHeGxkQ0J3WVhSMFpYSnVRbWwwVTNSeWFXNW5JRDBnVzEwN1hHNWNiaUFnWm05eUtHeGxkQ0JpYVhSemRISnBibWROWVhSamFGQmhjblFnYjJZZ2NHRjBkR1Z5Ymk1MllXeDFaWE1wZTF4dUlDQWdJR2xtS0VOb1pXTnJjeTVwYzE5MllYSnBZV0pzWlNoaWFYUnpkSEpwYm1kTllYUmphRkJoY25RdWRtRnNkV1VwS1h0Y2JpQWdJQ0FnSUd4bGRDQnphWHBsSUQwZ1oyVjBVMmw2WlNoaWFYUnpkSEpwYm1kTllYUmphRkJoY25RdWRXNXBkQ3dnWW1sMGMzUnlhVzVuVFdGMFkyaFFZWEowTG5OcGVtVXBPMXh1SUNBZ0lDQWdabWxzYkVGeWNtRjVLSEJoZEhSbGNtNUNhWFJUZEhKcGJtY3NJSE5wZW1VcE8xeHVJQ0FnSUgxbGJITmxlMXh1SUNBZ0lDQWdjR0YwZEdWeWJrSnBkRk4wY21sdVp5QTlJSEJoZEhSbGNtNUNhWFJUZEhKcGJtY3VZMjl1WTJGMEtHNWxkeUJDYVhSVGRISnBibWNvWW1sMGMzUnlhVzVuVFdGMFkyaFFZWEowS1M1MllXeDFaU2s3WEc0Z0lDQWdmVnh1SUNCOVhHNWNiaUFnYkdWMElIQmhkSFJsY201V1lXeDFaWE1nUFNCd1lYUjBaWEp1TG5aaGJIVmxjenRjYmx4dUlDQnlaWFIxY200Z1puVnVZM1JwYjI0b2RtRnNkV1U2SUdGdWVTd2dZWEpuY3pvZ1FYSnlZWGs4WVc1NVBpazZJR0p2YjJ4bFlXNGdlMXh1SUNBZ0lHeGxkQ0JpYzFaaGJIVmxJRDBnYm5Wc2JEdGNibHh1SUNBZ0lHbG1LQ0ZEYUdWamEzTXVhWE5mYzNSeWFXNW5LSFpoYkhWbEtTQW1KaUFoS0haaGJIVmxJR2x1YzNSaGJtTmxiMllnUW1sMFUzUnlhVzVuS1NBcGUxeHVJQ0FnSUNBZ2NtVjBkWEp1SUdaaGJITmxPMXh1SUNBZ0lIMWNibHh1SUNBZ0lHbG1LRU5vWldOcmN5NXBjMTl6ZEhKcGJtY29kbUZzZFdVcEtYdGNiaUFnSUNBZ0lHSnpWbUZzZFdVZ1BTQnVaWGNnUW1sMFUzUnlhVzVuS0VKcGRGTjBjbWx1Wnk1aWFXNWhjbmtvZG1Gc2RXVXBLVHRjYmlBZ0lDQjlaV3h6Wlh0Y2JpQWdJQ0FnSUdKelZtRnNkV1VnUFNCMllXeDFaVHRjYmlBZ0lDQjlYRzVjYmlBZ0lDQnNaWFFnWW1WbmFXNXVhVzVuU1c1a1pYZ2dQU0F3TzF4dVhHNGdJQ0FnWm05eUtHeGxkQ0JwSUQwZ01Ec2dhU0E4SUhCaGRIUmxjbTVXWVd4MVpYTXViR1Z1WjNSb095QnBLeXNwZTF4dUlDQWdJQ0FnYkdWMElHSnBkSE4wY21sdVowMWhkR05vVUdGeWRDQTlJSEJoZEhSbGNtNVdZV3gxWlhOYmFWMDdYRzVjYmlBZ0lDQWdJR2xtS0VOb1pXTnJjeTVwYzE5MllYSnBZV0pzWlNoaWFYUnpkSEpwYm1kTllYUmphRkJoY25RdWRtRnNkV1VwSUNZbVhHNGdJQ0FnSUNBZ0lDQmlhWFJ6ZEhKcGJtZE5ZWFJqYUZCaGNuUXVkSGx3WlNBOVBTQW5ZbWx1WVhKNUp5QW1KbHh1SUNBZ0lDQWdJQ0FnWW1sMGMzUnlhVzVuVFdGMFkyaFFZWEowTG5OcGVtVWdQVDA5SUhWdVpHVm1hVzVsWkNBbUpseHVJQ0FnSUNBZ0lDQWdhU0E4SUhCaGRIUmxjbTVXWVd4MVpYTXViR1Z1WjNSb0lDMGdNU2w3WEc0Z0lDQWdJQ0FnSUhSb2NtOTNJRzVsZHlCRmNuSnZjaWhjSW1FZ1ltbHVZWEo1SUdacFpXeGtJSGRwZEdodmRYUWdjMmw2WlNCcGN5QnZibXg1SUdGc2JHOTNaV1FnWVhRZ2RHaGxJR1Z1WkNCdlppQmhJR0pwYm1GeWVTQndZWFIwWlhKdVhDSXBPMXh1SUNBZ0lDQWdmVnh1WEc0Z0lDQWdJQ0JzWlhRZ2MybDZaU0E5SURBN1hHNGdJQ0FnSUNCc1pYUWdZbk5XWVd4MVpVRnljbUY1VUdGeWRDQTlJRnRkTzF4dUlDQWdJQ0FnYkdWMElIQmhkSFJsY201Q2FYUlRkSEpwYm1kQmNuSmhlVkJoY25RZ1BTQmJYVHRjYmlBZ0lDQWdJSE5wZW1VZ1BTQm5aWFJUYVhwbEtHSnBkSE4wY21sdVowMWhkR05vVUdGeWRDNTFibWwwTENCaWFYUnpkSEpwYm1kTllYUmphRkJoY25RdWMybDZaU2s3WEc1Y2JpQWdJQ0FnSUdsbUtHa2dQVDA5SUhCaGRIUmxjbTVXWVd4MVpYTXViR1Z1WjNSb0lDMGdNU2w3WEc0Z0lDQWdJQ0FnSUdKelZtRnNkV1ZCY25KaGVWQmhjblFnUFNCaWMxWmhiSFZsTG5aaGJIVmxMbk5zYVdObEtHSmxaMmx1Ym1sdVowbHVaR1Y0S1R0Y2JpQWdJQ0FnSUNBZ2NHRjBkR1Z5YmtKcGRGTjBjbWx1WjBGeWNtRjVVR0Z5ZENBOUlIQmhkSFJsY201Q2FYUlRkSEpwYm1jdWMyeHBZMlVvWW1WbmFXNXVhVzVuU1c1a1pYZ3BPMXh1SUNBZ0lDQWdmU0JsYkhObElIdGNiaUFnSUNBZ0lDQWdZbk5XWVd4MVpVRnljbUY1VUdGeWRDQTlJR0p6Vm1Gc2RXVXVkbUZzZFdVdWMyeHBZMlVvWW1WbmFXNXVhVzVuU1c1a1pYZ3NJR0psWjJsdWJtbHVaMGx1WkdWNElDc2djMmw2WlNrN1hHNGdJQ0FnSUNBZ0lIQmhkSFJsY201Q2FYUlRkSEpwYm1kQmNuSmhlVkJoY25RZ1BTQndZWFIwWlhKdVFtbDBVM1J5YVc1bkxuTnNhV05sS0dKbFoybHVibWx1WjBsdVpHVjRMQ0JpWldkcGJtNXBibWRKYm1SbGVDQXJJSE5wZW1VcE8xeHVJQ0FnSUNBZ2ZWeHVYRzRnSUNBZ0lDQnBaaWhEYUdWamEzTXVhWE5mZG1GeWFXRmliR1VvWW1sMGMzUnlhVzVuVFdGMFkyaFFZWEowTG5aaGJIVmxLU2w3WEc0Z0lDQWdJQ0FnSUhOM2FYUmphQ2hpYVhSemRISnBibWROWVhSamFGQmhjblF1ZEhsd1pTa2dlMXh1SUNBZ0lDQWdJQ0JqWVhObElDZHBiblJsWjJWeUp6cGNiaUFnSUNBZ0lDQWdJQ0JwWmloaWFYUnpkSEpwYm1kTllYUmphRkJoY25RdVlYUjBjbWxpZFhSbGN5QW1KaUJpYVhSemRISnBibWROWVhSamFGQmhjblF1WVhSMGNtbGlkWFJsY3k1cGJtUmxlRTltS0Z3aWMybG5ibVZrWENJcElDRTlJQzB4S1h0Y2JpQWdJQ0FnSUNBZ0lDQWdJR0Z5WjNNdWNIVnphQ2h1WlhjZ1NXNTBPRUZ5Y21GNUtGdGljMVpoYkhWbFFYSnlZWGxRWVhKMFd6QmRYU2xiTUYwcE8xeHVJQ0FnSUNBZ0lDQWdJSDBnWld4elpTQjdYRzRnSUNBZ0lDQWdJQ0FnSUNCaGNtZHpMbkIxYzJnb2JtVjNJRlZwYm5RNFFYSnlZWGtvVzJKelZtRnNkV1ZCY25KaGVWQmhjblJiTUYxZEtWc3dYU2s3WEc0Z0lDQWdJQ0FnSUNBZ2ZWeHVJQ0FnSUNBZ0lDQWdJR0p5WldGck8xeHVYRzRnSUNBZ0lDQWdJR05oYzJVZ0oyWnNiMkYwSnpwY2JpQWdJQ0FnSUNBZ0lDQnBaaWh6YVhwbElEMDlQU0EyTkNsN1hHNGdJQ0FnSUNBZ0lDQWdJQ0JoY21kekxuQjFjMmdvUm14dllYUTJORUZ5Y21GNUxtWnliMjBvWW5OV1lXeDFaVUZ5Y21GNVVHRnlkQ2xiTUYwcE8xeHVJQ0FnSUNBZ0lDQWdJSDBnWld4elpTQnBaaWh6YVhwbElEMDlQU0F6TWlsN1hHNGdJQ0FnSUNBZ0lDQWdJQ0JoY21kekxuQjFjMmdvUm14dllYUXpNa0Z5Y21GNUxtWnliMjBvWW5OV1lXeDFaVUZ5Y21GNVVHRnlkQ2xiTUYwcE8xeHVJQ0FnSUNBZ0lDQWdJSDFsYkhObGUxeHVJQ0FnSUNBZ0lDQWdJQ0FnY21WMGRYSnVJR1poYkhObE8xeHVJQ0FnSUNBZ0lDQWdJSDFjYmlBZ0lDQWdJQ0FnSUNCaWNtVmhhenRjYmx4dUlDQWdJQ0FnSUNCallYTmxJQ2RpYVhSemRISnBibWNuT2x4dUlDQWdJQ0FnSUNBZ0lHRnlaM011Y0hWemFDaGpjbVZoZEdWQ2FYUlRkSEpwYm1jb1luTldZV3gxWlVGeWNtRjVVR0Z5ZENrcE8xeHVJQ0FnSUNBZ0lDQWdJR0p5WldGck8xeHVYRzRnSUNBZ0lDQWdJR05oYzJVZ0oySnBibUZ5ZVNjNlhHNGdJQ0FnSUNBZ0lDQWdZWEpuY3k1d2RYTm9LRk4wY21sdVp5NW1jbTl0UTJoaGNrTnZaR1V1WVhCd2JIa29iblZzYkN3Z2JtVjNJRlZwYm5RNFFYSnlZWGtvWW5OV1lXeDFaVUZ5Y21GNVVHRnlkQ2twS1R0Y2JpQWdJQ0FnSUNBZ0lDQmljbVZoYXp0Y2JseHVJQ0FnSUNBZ0lDQmpZWE5sSUNkMWRHWTRKenBjYmlBZ0lDQWdJQ0FnSUNCaGNtZHpMbkIxYzJnb1UzUnlhVzVuTG1aeWIyMURhR0Z5UTI5a1pTNWhjSEJzZVNodWRXeHNMQ0J1WlhjZ1ZXbHVkRGhCY25KaGVTaGljMVpoYkhWbFFYSnlZWGxRWVhKMEtTa3BPMXh1SUNBZ0lDQWdJQ0FnSUdKeVpXRnJPMXh1WEc0Z0lDQWdJQ0FnSUdOaGMyVWdKM1YwWmpFMkp6cGNiaUFnSUNBZ0lDQWdJQ0JoY21kekxuQjFjMmdvVTNSeWFXNW5MbVp5YjIxRGFHRnlRMjlrWlM1aGNIQnNlU2h1ZFd4c0xDQnVaWGNnVldsdWRERTJRWEp5WVhrb1luTldZV3gxWlVGeWNtRjVVR0Z5ZENrcEtUdGNiaUFnSUNBZ0lDQWdJQ0JpY21WaGF6dGNibHh1SUNBZ0lDQWdJQ0JqWVhObElDZDFkR1l6TWljNlhHNGdJQ0FnSUNBZ0lDQWdZWEpuY3k1d2RYTm9LRk4wY21sdVp5NW1jbTl0UTJoaGNrTnZaR1V1WVhCd2JIa29iblZzYkN3Z2JtVjNJRlZwYm5Rek1rRnljbUY1S0dKelZtRnNkV1ZCY25KaGVWQmhjblFwS1NrN1hHNGdJQ0FnSUNBZ0lDQWdZbkpsWVdzN1hHNWNiaUFnSUNBZ0lDQWdaR1ZtWVhWc2REcGNiaUFnSUNBZ0lDQWdJQ0J5WlhSMWNtNGdabUZzYzJVN1hHNGdJQ0FnSUNBZ0lIMWNiaUFnSUNBZ0lIMWxiSE5sSUdsbUtDRmhjbkpoZVhORmNYVmhiQ2hpYzFaaGJIVmxRWEp5WVhsUVlYSjBMQ0J3WVhSMFpYSnVRbWwwVTNSeWFXNW5RWEp5WVhsUVlYSjBLU2tnZTF4dUlDQWdJQ0FnSUNCeVpYUjFjbTRnWm1Gc2MyVTdYRzRnSUNBZ0lDQjlYRzVjYmlBZ0lDQWdJR0psWjJsdWJtbHVaMGx1WkdWNElEMGdZbVZuYVc1dWFXNW5TVzVrWlhnZ0t5QnphWHBsTzF4dUlDQWdJSDFjYmx4dUlDQWdJSEpsZEhWeWJpQjBjblZsTzF4dUlDQjlYRzVjYm4xY2JseHVablZ1WTNScGIyNGdaMlYwVTJsNlpTaDFibWwwTENCemFYcGxLWHRjYmlBZ2NtVjBkWEp1SUNoMWJtbDBJQ29nYzJsNlpTa2dMeUE0TzF4dWZWeHVYRzVtZFc1amRHbHZiaUJoY25KaGVYTkZjWFZoYkNoaExDQmlLU0I3WEc0Z0lHbG1JQ2hoSUQwOVBTQmlLU0J5WlhSMWNtNGdkSEoxWlR0Y2JpQWdhV1lnS0dFZ1BUMGdiblZzYkNCOGZDQmlJRDA5SUc1MWJHd3BJSEpsZEhWeWJpQm1ZV3h6WlR0Y2JpQWdhV1lnS0dFdWJHVnVaM1JvSUNFOUlHSXViR1Z1WjNSb0tTQnlaWFIxY200Z1ptRnNjMlU3WEc1Y2JpQWdabTl5SUNoMllYSWdhU0E5SURBN0lHa2dQQ0JoTG14bGJtZDBhRHNnS3l0cEtTQjdYRzRnSUNBZ2FXWWdLR0ZiYVYwZ0lUMDlJR0piYVYwcElISmxkSFZ5YmlCbVlXeHpaVHRjYmlBZ2ZWeHVYRzRnSUhKbGRIVnliaUIwY25WbE8xeHVmVnh1WEc1bWRXNWpkR2x2YmlCbWFXeHNRWEp5WVhrb1lYSnlMQ0J1ZFcwcGUxeHVJQ0JtYjNJb2JHVjBJR2tnUFNBd095QnBJRHdnYm5WdE95QnBLeXNwZTF4dUlDQWdJR0Z5Y2k1d2RYTm9LREFwTzF4dUlDQjlYRzU5WEc1Y2JtWjFibU4wYVc5dUlHTnlaV0YwWlVKcGRGTjBjbWx1WnloaGNuSXBlMXh1SUNCc1pYUWdhVzUwWldkbGNsQmhjblJ6SUQwZ1lYSnlMbTFoY0Nnb1pXeGxiU2tnUFQ0Z1FtbDBVM1J5YVc1bkxtbHVkR1ZuWlhJb1pXeGxiU2twTzF4dUlDQnlaWFIxY200Z2JtVjNJRUpwZEZOMGNtbHVaeWd1TGk1cGJuUmxaMlZ5VUdGeWRITXBPMXh1ZlZ4dVhHNW1kVzVqZEdsdmJpQnlaWE52YkhabFRtOU5ZWFJqYUNncE9pQkdkVzVqZEdsdmJpQjdYRzRnSUhKbGRIVnliaUJtZFc1amRHbHZiaWdwT2lCaWIyOXNaV0Z1SUh0Y2JpQWdJQ0J5WlhSMWNtNGdabUZzYzJVN1hHNGdJSDFjYm4xY2JseHVaWGh3YjNKMElHUmxabUYxYkhRZ2UxeHVJQ0J5WlhOdmJIWmxRbTkxYm1Rc1hHNGdJSEpsYzI5c2RtVlhhV3hrWTJGeVpDeGNiaUFnY21WemIyeDJaVlpoY21saFlteGxMRnh1SUNCeVpYTnZiSFpsU0dWaFpGUmhhV3dzWEc0Z0lISmxjMjlzZG1WRFlYQjBkWEpsTEZ4dUlDQnlaWE52YkhabFUzUmhjblJ6VjJsMGFDeGNiaUFnY21WemIyeDJaVlI1Y0dVc1hHNGdJSEpsYzI5c2RtVkJjbkpoZVN4Y2JpQWdjbVZ6YjJ4MlpVOWlhbVZqZEN4Y2JpQWdjbVZ6YjJ4MlpVNXZUV0YwWTJnc1hHNGdJSEpsYzI5c2RtVlRlVzFpYjJ3c1hHNGdJSEpsYzI5c2RtVlRkSEpwYm1jc1hHNGdJSEpsYzI5c2RtVk9kVzFpWlhJc1hHNGdJSEpsYzI5c2RtVkNiMjlzWldGdUxGeHVJQ0J5WlhOdmJIWmxSblZ1WTNScGIyNHNYRzRnSUhKbGMyOXNkbVZPZFd4c0xGeHVJQ0J5WlhOdmJIWmxRbWwwVTNSeWFXNW5YRzU5WEc0aVhTd2ljMjkxY21ObFVtOXZkQ0k2SWk5emIzVnlZMlV2SW4wPVxuIiwiXG5pbXBvcnQgQ2hlY2tzIGZyb20gXCIuL2NoZWNrc1wiO1xuaW1wb3J0IFJlc29sdmVycyBmcm9tIFwiLi9yZXNvbHZlcnNcIjtcblxuZXhwb3J0IGZ1bmN0aW9uIGJ1aWxkTWF0Y2gocGF0dGVybikge1xuXG4gIGlmIChDaGVja3MuaXNfdmFyaWFibGUocGF0dGVybikpIHtcbiAgICByZXR1cm4gUmVzb2x2ZXJzLnJlc29sdmVWYXJpYWJsZShwYXR0ZXJuKTtcbiAgfVxuXG4gIGlmIChDaGVja3MuaXNfd2lsZGNhcmQocGF0dGVybikpIHtcbiAgICByZXR1cm4gUmVzb2x2ZXJzLnJlc29sdmVXaWxkY2FyZChwYXR0ZXJuKTtcbiAgfVxuXG4gIGlmIChDaGVja3MuaXNfdW5kZWZpbmVkKHBhdHRlcm4pKSB7XG4gICAgcmV0dXJuIFJlc29sdmVycy5yZXNvbHZlV2lsZGNhcmQocGF0dGVybik7XG4gIH1cblxuICBpZiAoQ2hlY2tzLmlzX2hlYWRUYWlsKHBhdHRlcm4pKSB7XG4gICAgcmV0dXJuIFJlc29sdmVycy5yZXNvbHZlSGVhZFRhaWwocGF0dGVybik7XG4gIH1cblxuICBpZiAoQ2hlY2tzLmlzX3N0YXJ0c1dpdGgocGF0dGVybikpIHtcbiAgICByZXR1cm4gUmVzb2x2ZXJzLnJlc29sdmVTdGFydHNXaXRoKHBhdHRlcm4pO1xuICB9XG5cbiAgaWYgKENoZWNrcy5pc19jYXB0dXJlKHBhdHRlcm4pKSB7XG4gICAgcmV0dXJuIFJlc29sdmVycy5yZXNvbHZlQ2FwdHVyZShwYXR0ZXJuKTtcbiAgfVxuXG4gIGlmIChDaGVja3MuaXNfYm91bmQocGF0dGVybikpIHtcbiAgICByZXR1cm4gUmVzb2x2ZXJzLnJlc29sdmVCb3VuZChwYXR0ZXJuKTtcbiAgfVxuXG4gIGlmIChDaGVja3MuaXNfdHlwZShwYXR0ZXJuKSkge1xuICAgIHJldHVybiBSZXNvbHZlcnMucmVzb2x2ZVR5cGUocGF0dGVybik7XG4gIH1cblxuICBpZiAoQ2hlY2tzLmlzX2FycmF5KHBhdHRlcm4pKSB7XG4gICAgcmV0dXJuIFJlc29sdmVycy5yZXNvbHZlQXJyYXkocGF0dGVybik7XG4gIH1cblxuICBpZiAoQ2hlY2tzLmlzX251bWJlcihwYXR0ZXJuKSkge1xuICAgIHJldHVybiBSZXNvbHZlcnMucmVzb2x2ZU51bWJlcihwYXR0ZXJuKTtcbiAgfVxuXG4gIGlmIChDaGVja3MuaXNfc3RyaW5nKHBhdHRlcm4pKSB7XG4gICAgcmV0dXJuIFJlc29sdmVycy5yZXNvbHZlU3RyaW5nKHBhdHRlcm4pO1xuICB9XG5cbiAgaWYgKENoZWNrcy5pc19ib29sZWFuKHBhdHRlcm4pKSB7XG4gICAgcmV0dXJuIFJlc29sdmVycy5yZXNvbHZlQm9vbGVhbihwYXR0ZXJuKTtcbiAgfVxuXG4gIGlmIChDaGVja3MuaXNfc3ltYm9sKHBhdHRlcm4pKSB7XG4gICAgcmV0dXJuIFJlc29sdmVycy5yZXNvbHZlU3ltYm9sKHBhdHRlcm4pO1xuICB9XG5cbiAgaWYgKENoZWNrcy5pc19udWxsKHBhdHRlcm4pKSB7XG4gICAgcmV0dXJuIFJlc29sdmVycy5yZXNvbHZlTnVsbChwYXR0ZXJuKTtcbiAgfVxuXG4gIGlmIChDaGVja3MuaXNfYml0c3RyaW5nKHBhdHRlcm4pKSB7XG4gICAgcmV0dXJuIFJlc29sdmVycy5yZXNvbHZlQml0U3RyaW5nKHBhdHRlcm4pO1xuICB9XG5cbiAgaWYgKENoZWNrcy5pc19vYmplY3QocGF0dGVybikpIHtcbiAgICByZXR1cm4gUmVzb2x2ZXJzLnJlc29sdmVPYmplY3QocGF0dGVybik7XG4gIH1cblxuICByZXR1cm4gUmVzb2x2ZXJzLnJlc29sdmVOb01hdGNoKCk7XG59XG4vLyMgc291cmNlTWFwcGluZ1VSTD1kYXRhOmFwcGxpY2F0aW9uL2pzb247YmFzZTY0LGV5SjJaWEp6YVc5dUlqb3pMQ0p6YjNWeVkyVnpJanBiSW14cFlpOWpiM0psTDNCaGRIUmxjbTV6TDIxaGRHTm9MbXB6SWwwc0ltNWhiV1Z6SWpwYlhTd2liV0Z3Y0dsdVozTWlPaUk3UVVGRFFTeFBRVUZQTEUxQlFWQXNUVUZCYlVJc1ZVRkJia0k3UVVGRFFTeFBRVUZQTEZOQlFWQXNUVUZCYzBJc1lVRkJkRUk3TzBGQlJVRXNUMEZCVHl4VFFVRlRMRlZCUVZRc1EwRkJiMElzVDBGQmNFSXNSVUZCTkVNN08wRkJSV3BFTEUxQlFVY3NUMEZCVHl4WFFVRlFMRU5CUVcxQ0xFOUJRVzVDTEVOQlFVZ3NSVUZCSzBJN1FVRkROMElzVjBGQlR5eFZRVUZWTEdWQlFWWXNRMEZCTUVJc1QwRkJNVUlzUTBGQlVDeERRVVEyUWp0SFFVRXZRanM3UVVGSlFTeE5RVUZITEU5QlFVOHNWMEZCVUN4RFFVRnRRaXhQUVVGdVFpeERRVUZJTEVWQlFTdENPMEZCUXpkQ0xGZEJRVThzVlVGQlZTeGxRVUZXTEVOQlFUQkNMRTlCUVRGQ0xFTkJRVkFzUTBGRU5rSTdSMEZCTDBJN08wRkJTVUVzVFVGQlJ5eFBRVUZQTEZsQlFWQXNRMEZCYjBJc1QwRkJjRUlzUTBGQlNDeEZRVUZuUXp0QlFVTTVRaXhYUVVGUExGVkJRVlVzWlVGQlZpeERRVUV3UWl4UFFVRXhRaXhEUVVGUUxFTkJSRGhDTzBkQlFXaERPenRCUVVsQkxFMUJRVWNzVDBGQlR5eFhRVUZRTEVOQlFXMUNMRTlCUVc1Q0xFTkJRVWdzUlVGQkswSTdRVUZETjBJc1YwRkJUeXhWUVVGVkxHVkJRVllzUTBGQk1FSXNUMEZCTVVJc1EwRkJVQ3hEUVVRMlFqdEhRVUV2UWpzN1FVRkpRU3hOUVVGSExFOUJRVThzWVVGQlVDeERRVUZ4UWl4UFFVRnlRaXhEUVVGSUxFVkJRV2xETzBGQlF5OUNMRmRCUVU4c1ZVRkJWU3hwUWtGQlZpeERRVUUwUWl4UFFVRTFRaXhEUVVGUUxFTkJSQ3RDTzBkQlFXcERPenRCUVVsQkxFMUJRVWNzVDBGQlR5eFZRVUZRTEVOQlFXdENMRTlCUVd4Q0xFTkJRVWdzUlVGQk9FSTdRVUZETlVJc1YwRkJUeXhWUVVGVkxHTkJRVllzUTBGQmVVSXNUMEZCZWtJc1EwRkJVQ3hEUVVRMFFqdEhRVUU1UWpzN1FVRkpRU3hOUVVGSExFOUJRVThzVVVGQlVDeERRVUZuUWl4UFFVRm9RaXhEUVVGSUxFVkJRVFJDTzBGQlF6RkNMRmRCUVU4c1ZVRkJWU3haUVVGV0xFTkJRWFZDTEU5QlFYWkNMRU5CUVZBc1EwRkVNRUk3UjBGQk5VSTdPMEZCU1VFc1RVRkJSeXhQUVVGUExFOUJRVkFzUTBGQlpTeFBRVUZtTEVOQlFVZ3NSVUZCTWtJN1FVRkRla0lzVjBGQlR5eFZRVUZWTEZkQlFWWXNRMEZCYzBJc1QwRkJkRUlzUTBGQlVDeERRVVI1UWp0SFFVRXpRanM3UVVGSlFTeE5RVUZITEU5QlFVOHNVVUZCVUN4RFFVRm5RaXhQUVVGb1FpeERRVUZJTEVWQlFUUkNPMEZCUXpGQ0xGZEJRVThzVlVGQlZTeFpRVUZXTEVOQlFYVkNMRTlCUVhaQ0xFTkJRVkFzUTBGRU1FSTdSMEZCTlVJN08wRkJTVUVzVFVGQlJ5eFBRVUZQTEZOQlFWQXNRMEZCYVVJc1QwRkJha0lzUTBGQlNDeEZRVUUyUWp0QlFVTXpRaXhYUVVGUExGVkJRVlVzWVVGQlZpeERRVUYzUWl4UFFVRjRRaXhEUVVGUUxFTkJSREpDTzBkQlFUZENPenRCUVVsQkxFMUJRVWNzVDBGQlR5eFRRVUZRTEVOQlFXbENMRTlCUVdwQ0xFTkJRVWdzUlVGQk5rSTdRVUZETTBJc1YwRkJUeXhWUVVGVkxHRkJRVllzUTBGQmQwSXNUMEZCZUVJc1EwRkJVQ3hEUVVReVFqdEhRVUUzUWpzN1FVRkpRU3hOUVVGSExFOUJRVThzVlVGQlVDeERRVUZyUWl4UFFVRnNRaXhEUVVGSUxFVkJRVGhDTzBGQlF6VkNMRmRCUVU4c1ZVRkJWU3hqUVVGV0xFTkJRWGxDTEU5QlFYcENMRU5CUVZBc1EwRkVORUk3UjBGQk9VSTdPMEZCU1VFc1RVRkJSeXhQUVVGUExGTkJRVkFzUTBGQmFVSXNUMEZCYWtJc1EwRkJTQ3hGUVVFMlFqdEJRVU16UWl4WFFVRlBMRlZCUVZVc1lVRkJWaXhEUVVGM1FpeFBRVUY0UWl4RFFVRlFMRU5CUkRKQ08wZEJRVGRDT3p0QlFVbEJMRTFCUVVjc1QwRkJUeXhQUVVGUUxFTkJRV1VzVDBGQlppeERRVUZJTEVWQlFUSkNPMEZCUTNwQ0xGZEJRVThzVlVGQlZTeFhRVUZXTEVOQlFYTkNMRTlCUVhSQ0xFTkJRVkFzUTBGRWVVSTdSMEZCTTBJN08wRkJTVUVzVFVGQlJ5eFBRVUZQTEZsQlFWQXNRMEZCYjBJc1QwRkJjRUlzUTBGQlNDeEZRVUZuUXp0QlFVTTVRaXhYUVVGUExGVkJRVlVzWjBKQlFWWXNRMEZCTWtJc1QwRkJNMElzUTBGQlVDeERRVVE0UWp0SFFVRm9RenM3UVVGSlFTeE5RVUZITEU5QlFVOHNVMEZCVUN4RFFVRnBRaXhQUVVGcVFpeERRVUZJTEVWQlFUWkNPMEZCUXpOQ0xGZEJRVThzVlVGQlZTeGhRVUZXTEVOQlFYZENMRTlCUVhoQ0xFTkJRVkFzUTBGRU1rSTdSMEZCTjBJN08wRkJTVUVzVTBGQlR5eFZRVUZWTEdOQlFWWXNSVUZCVUN4RFFXeEZhVVE3UTBGQk5VTWlMQ0ptYVd4bElqb2liR2xpTDJOdmNtVXZjR0YwZEdWeWJuTXZiV0YwWTJndWFuTWlMQ0p6YjNWeVkyVnpRMjl1ZEdWdWRDSTZXeUl2S2lCQVpteHZkeUFxTDF4dWFXMXdiM0owSUVOb1pXTnJjeUJtY205dElGd2lMaTlqYUdWamEzTmNJanRjYm1sdGNHOXlkQ0JTWlhOdmJIWmxjbk1nWm5KdmJTQmNJaTR2Y21WemIyeDJaWEp6WENJN1hHNWNibVY0Y0c5eWRDQm1kVzVqZEdsdmJpQmlkV2xzWkUxaGRHTm9LSEJoZEhSbGNtNDZJR0Z1ZVNrNklFWjFibU4wYVc5dUlIdGNibHh1SUNCcFppaERhR1ZqYTNNdWFYTmZkbUZ5YVdGaWJHVW9jR0YwZEdWeWJpa3BlMXh1SUNBZ0lISmxkSFZ5YmlCU1pYTnZiSFpsY25NdWNtVnpiMngyWlZaaGNtbGhZbXhsS0hCaGRIUmxjbTRwTzF4dUlDQjlYRzVjYmlBZ2FXWW9RMmhsWTJ0ekxtbHpYM2RwYkdSallYSmtLSEJoZEhSbGNtNHBLWHRjYmlBZ0lDQnlaWFIxY200Z1VtVnpiMngyWlhKekxuSmxjMjlzZG1WWGFXeGtZMkZ5WkNod1lYUjBaWEp1S1R0Y2JpQWdmVnh1WEc0Z0lHbG1LRU5vWldOcmN5NXBjMTkxYm1SbFptbHVaV1FvY0dGMGRHVnliaWtwZTF4dUlDQWdJSEpsZEhWeWJpQlNaWE52YkhabGNuTXVjbVZ6YjJ4MlpWZHBiR1JqWVhKa0tIQmhkSFJsY200cE8xeHVJQ0I5WEc1Y2JpQWdhV1lvUTJobFkydHpMbWx6WDJobFlXUlVZV2xzS0hCaGRIUmxjbTRwS1h0Y2JpQWdJQ0J5WlhSMWNtNGdVbVZ6YjJ4MlpYSnpMbkpsYzI5c2RtVklaV0ZrVkdGcGJDaHdZWFIwWlhKdUtUdGNiaUFnZlZ4dVhHNGdJR2xtS0VOb1pXTnJjeTVwYzE5emRHRnlkSE5YYVhSb0tIQmhkSFJsY200cEtYdGNiaUFnSUNCeVpYUjFjbTRnVW1WemIyeDJaWEp6TG5KbGMyOXNkbVZUZEdGeWRITlhhWFJvS0hCaGRIUmxjbTRwTzF4dUlDQjlYRzVjYmlBZ2FXWW9RMmhsWTJ0ekxtbHpYMk5oY0hSMWNtVW9jR0YwZEdWeWJpa3BlMXh1SUNBZ0lISmxkSFZ5YmlCU1pYTnZiSFpsY25NdWNtVnpiMngyWlVOaGNIUjFjbVVvY0dGMGRHVnliaWs3WEc0Z0lIMWNibHh1SUNCcFppaERhR1ZqYTNNdWFYTmZZbTkxYm1Rb2NHRjBkR1Z5YmlrcGUxeHVJQ0FnSUhKbGRIVnliaUJTWlhOdmJIWmxjbk11Y21WemIyeDJaVUp2ZFc1a0tIQmhkSFJsY200cE8xeHVJQ0I5WEc1Y2JpQWdhV1lvUTJobFkydHpMbWx6WDNSNWNHVW9jR0YwZEdWeWJpa3BlMXh1SUNBZ0lISmxkSFZ5YmlCU1pYTnZiSFpsY25NdWNtVnpiMngyWlZSNWNHVW9jR0YwZEdWeWJpazdYRzRnSUgxY2JseHVJQ0JwWmloRGFHVmphM011YVhOZllYSnlZWGtvY0dGMGRHVnliaWtwZTF4dUlDQWdJSEpsZEhWeWJpQlNaWE52YkhabGNuTXVjbVZ6YjJ4MlpVRnljbUY1S0hCaGRIUmxjbTRwTzF4dUlDQjlYRzVjYmlBZ2FXWW9RMmhsWTJ0ekxtbHpYMjUxYldKbGNpaHdZWFIwWlhKdUtTbDdYRzRnSUNBZ2NtVjBkWEp1SUZKbGMyOXNkbVZ5Y3k1eVpYTnZiSFpsVG5WdFltVnlLSEJoZEhSbGNtNHBPMXh1SUNCOVhHNWNiaUFnYVdZb1EyaGxZMnR6TG1selgzTjBjbWx1Wnlod1lYUjBaWEp1S1NsN1hHNGdJQ0FnY21WMGRYSnVJRkpsYzI5c2RtVnljeTV5WlhOdmJIWmxVM1J5YVc1bktIQmhkSFJsY200cE8xeHVJQ0I5WEc1Y2JpQWdhV1lvUTJobFkydHpMbWx6WDJKdmIyeGxZVzRvY0dGMGRHVnliaWtwZTF4dUlDQWdJSEpsZEhWeWJpQlNaWE52YkhabGNuTXVjbVZ6YjJ4MlpVSnZiMnhsWVc0b2NHRjBkR1Z5YmlrN1hHNGdJSDFjYmx4dUlDQnBaaWhEYUdWamEzTXVhWE5mYzNsdFltOXNLSEJoZEhSbGNtNHBLWHRjYmlBZ0lDQnlaWFIxY200Z1VtVnpiMngyWlhKekxuSmxjMjlzZG1WVGVXMWliMndvY0dGMGRHVnliaWs3WEc0Z0lIMWNibHh1SUNCcFppaERhR1ZqYTNNdWFYTmZiblZzYkNod1lYUjBaWEp1S1NsN1hHNGdJQ0FnY21WMGRYSnVJRkpsYzI5c2RtVnljeTV5WlhOdmJIWmxUblZzYkNod1lYUjBaWEp1S1R0Y2JpQWdmVnh1WEc0Z0lHbG1LRU5vWldOcmN5NXBjMTlpYVhSemRISnBibWNvY0dGMGRHVnliaWtwZTF4dUlDQWdJSEpsZEhWeWJpQlNaWE52YkhabGNuTXVjbVZ6YjJ4MlpVSnBkRk4wY21sdVp5aHdZWFIwWlhKdUtUdGNiaUFnZlZ4dVhHNGdJR2xtS0VOb1pXTnJjeTVwYzE5dlltcGxZM1FvY0dGMGRHVnliaWtwZTF4dUlDQWdJSEpsZEhWeWJpQlNaWE52YkhabGNuTXVjbVZ6YjJ4MlpVOWlhbVZqZENod1lYUjBaWEp1S1R0Y2JpQWdmVnh1WEc0Z0lISmxkSFZ5YmlCU1pYTnZiSFpsY25NdWNtVnpiMngyWlU1dlRXRjBZMmdvS1R0Y2JuMWNiaUpkTENKemIzVnlZMlZTYjI5MElqb2lMM052ZFhKalpTOGlmUT09XG4iLCJcblxuaW1wb3J0IHsgYnVpbGRNYXRjaCB9IGZyb20gXCIuL21hdGNoXCI7XG5pbXBvcnQgKiBhcyBUeXBlcyBmcm9tIFwiLi90eXBlc1wiO1xuXG5leHBvcnQgY2xhc3MgTWF0Y2hFcnJvciBleHRlbmRzIEVycm9yIHtcbiAgY29uc3RydWN0b3IoYXJnKSB7XG4gICAgc3VwZXIoKTtcblxuICAgIGlmICh0eXBlb2YgYXJnID09PSAnc3ltYm9sJykge1xuICAgICAgdGhpcy5tZXNzYWdlID0gJ05vIG1hdGNoIGZvcjogJyArIGFyZy50b1N0cmluZygpO1xuICAgIH0gZWxzZSBpZiAoQXJyYXkuaXNBcnJheShhcmcpKSB7XG4gICAgICBsZXQgbWFwcGVkVmFsdWVzID0gYXJnLm1hcCh4ID0+IHgudG9TdHJpbmcoKSk7XG4gICAgICB0aGlzLm1lc3NhZ2UgPSAnTm8gbWF0Y2ggZm9yOiAnICsgbWFwcGVkVmFsdWVzO1xuICAgIH0gZWxzZSB7XG4gICAgICB0aGlzLm1lc3NhZ2UgPSAnTm8gbWF0Y2ggZm9yOiAnICsgYXJnO1xuICAgIH1cblxuICAgIHRoaXMuc3RhY2sgPSBuZXcgRXJyb3IoKS5zdGFjaztcbiAgICB0aGlzLm5hbWUgPSB0aGlzLmNvbnN0cnVjdG9yLm5hbWU7XG4gIH1cbn1cblxuZXhwb3J0IGNsYXNzIENhc2Uge1xuXG4gIGNvbnN0cnVjdG9yKHBhdHRlcm4sIGZuLCBndWFyZCA9ICgpID0+IHRydWUpIHtcbiAgICB0aGlzLnBhdHRlcm4gPSBidWlsZE1hdGNoKHBhdHRlcm4pO1xuICAgIHRoaXMuYXJpdHkgPSBwYXR0ZXJuLmxlbmd0aDtcbiAgICB0aGlzLm9wdGlvbmFscyA9IGdldE9wdGlvbmFsVmFsdWVzKHBhdHRlcm4pO1xuICAgIHRoaXMuZm4gPSBmbjtcbiAgICB0aGlzLmd1YXJkID0gZ3VhcmQ7XG4gIH1cbn1cblxuZXhwb3J0IGZ1bmN0aW9uIG1ha2VfY2FzZShwYXR0ZXJuLCBmbiwgZ3VhcmQgPSAoKSA9PiB0cnVlKSB7XG4gIHJldHVybiBuZXcgQ2FzZShwYXR0ZXJuLCBmbiwgZ3VhcmQpO1xufVxuXG5leHBvcnQgZnVuY3Rpb24gZGVmbWF0Y2goLi4uY2FzZXMpIHtcbiAgcmV0dXJuIGZ1bmN0aW9uICguLi5hcmdzKSB7XG4gICAgZm9yIChsZXQgcHJvY2Vzc2VkQ2FzZSBvZiBjYXNlcykge1xuICAgICAgbGV0IHJlc3VsdCA9IFtdO1xuICAgICAgYXJncyA9IGZpbGxJbk9wdGlvbmFsVmFsdWVzKGFyZ3MsIHByb2Nlc3NlZENhc2UuYXJpdHksIHByb2Nlc3NlZENhc2Uub3B0aW9uYWxzKTtcblxuICAgICAgaWYgKHByb2Nlc3NlZENhc2UucGF0dGVybihhcmdzLCByZXN1bHQpICYmIHByb2Nlc3NlZENhc2UuZ3VhcmQuYXBwbHkodGhpcywgcmVzdWx0KSkge1xuICAgICAgICByZXR1cm4gcHJvY2Vzc2VkQ2FzZS5mbi5hcHBseSh0aGlzLCByZXN1bHQpO1xuICAgICAgfVxuICAgIH1cblxuICAgIHRocm93IG5ldyBNYXRjaEVycm9yKGFyZ3MpO1xuICB9O1xufVxuXG5mdW5jdGlvbiBnZXRPcHRpb25hbFZhbHVlcyhwYXR0ZXJuKSB7XG4gIGxldCBvcHRpb25hbHMgPSBbXTtcblxuICBmb3IgKGxldCBpID0gMDsgaSA8IHBhdHRlcm4ubGVuZ3RoOyBpKyspIHtcbiAgICBpZiAocGF0dGVybltpXSBpbnN0YW5jZW9mIFR5cGVzLlZhcmlhYmxlICYmIHBhdHRlcm5baV0uZGVmYXVsdF92YWx1ZSAhPSBTeW1ib2wuZm9yKFwiZWxpeGlyc2NyaXB0Lm5vX3ZhbHVlXCIpKSB7XG4gICAgICBvcHRpb25hbHMucHVzaChbaSwgcGF0dGVybltpXS5kZWZhdWx0X3ZhbHVlXSk7XG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIG9wdGlvbmFscztcbn1cblxuZnVuY3Rpb24gZmlsbEluT3B0aW9uYWxWYWx1ZXMoYXJncywgYXJpdHksIG9wdGlvbmFscykge1xuICBpZiAoYXJncy5sZW5ndGggPT09IGFyaXR5IHx8IG9wdGlvbmFscy5sZW5ndGggPT09IDApIHtcbiAgICByZXR1cm4gYXJncztcbiAgfVxuXG4gIGlmIChhcmdzLmxlbmd0aCArIG9wdGlvbmFscy5sZW5ndGggPCBhcml0eSkge1xuICAgIHJldHVybiBhcmdzO1xuICB9XG5cbiAgbGV0IG51bWJlck9mT3B0aW9uYWxzVG9GaWxsID0gYXJpdHkgLSBhcmdzLmxlbmd0aDtcbiAgbGV0IG9wdGlvbmFsc1RvUmVtb3ZlID0gb3B0aW9uYWxzLmxlbmd0aCAtIG51bWJlck9mT3B0aW9uYWxzVG9GaWxsO1xuXG4gIGxldCBvcHRpb25hbHNUb1VzZSA9IG9wdGlvbmFscy5zbGljZShvcHRpb25hbHNUb1JlbW92ZSk7XG5cbiAgZm9yIChsZXQgW2luZGV4LCB2YWx1ZV0gb2Ygb3B0aW9uYWxzVG9Vc2UpIHtcbiAgICBhcmdzLnNwbGljZShpbmRleCwgMCwgdmFsdWUpO1xuICAgIGlmIChhcmdzLmxlbmd0aCA9PT0gYXJpdHkpIHtcbiAgICAgIGJyZWFrO1xuICAgIH1cbiAgfVxuXG4gIHJldHVybiBhcmdzO1xufVxuXG5leHBvcnQgZnVuY3Rpb24gbWF0Y2gocGF0dGVybiwgZXhwciwgZ3VhcmQgPSAoKSA9PiB0cnVlKSB7XG4gIGxldCByZXN1bHQgPSBbXTtcbiAgbGV0IHByb2Nlc3NlZFBhdHRlcm4gPSBidWlsZE1hdGNoKHBhdHRlcm4pO1xuICBpZiAocHJvY2Vzc2VkUGF0dGVybihleHByLCByZXN1bHQpICYmIGd1YXJkLmFwcGx5KHRoaXMsIHJlc3VsdCkpIHtcbiAgICByZXR1cm4gcmVzdWx0O1xuICB9IGVsc2Uge1xuICAgIHRocm93IG5ldyBNYXRjaEVycm9yKGV4cHIpO1xuICB9XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBtYXRjaF9ub190aHJvdyhwYXR0ZXJuLCBleHByLCBndWFyZCA9ICgpID0+IHRydWUpIHtcbiAgdHJ5IHtcbiAgICByZXR1cm4gbWF0Y2gocGF0dGVybiwgZXhwciwgZ3VhcmQpO1xuICB9IGNhdGNoIChlKSB7XG4gICAgaWYgKGUgaW5zdGFuY2VvZiBNYXRjaEVycm9yIHx8IGUubWVzc2FnZS5zdGFydHNXaXRoKCdObyBtYXRjaCBmb3I6JykpIHtcbiAgICAgIHJldHVybiBudWxsO1xuICAgIH1cblxuICAgIHRocm93IGU7XG4gIH1cbn1cblxuZXhwb3J0IGZ1bmN0aW9uIHBhdHRlcm5NYXAoY29sbGVjdGlvbiwgcGF0dGVybiwgZnVuLCBndWFyZCA9ICgpID0+IHRydWUpIHtcbiAgbGV0IHJldCA9IFtdO1xuXG4gIGZvciAobGV0IGVsZW0gb2YgY29sbGVjdGlvbikge1xuICAgIHRyeSB7XG4gICAgICBsZXQgcmVzdWx0ID0gZnVuLmFwcGx5KHRoaXMsIG1hdGNoKHBhdHRlcm4sIGVsZW0sIGd1YXJkKSk7XG4gICAgICByZXQgPSByZXQuY29uY2F0KHJlc3VsdCk7XG4gICAgfSBjYXRjaCAoZSkge1xuICAgICAgaWYgKCEoZSBpbnN0YW5jZW9mIE1hdGNoRXJyb3IpKSB7XG4gICAgICAgIHRocm93IGU7XG4gICAgICB9XG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIHJldDtcbn1cbi8vIyBzb3VyY2VNYXBwaW5nVVJMPWRhdGE6YXBwbGljYXRpb24vanNvbjtiYXNlNjQsZXlKMlpYSnphVzl1SWpvekxDSnpiM1Z5WTJWeklqcGJJbXhwWWk5amIzSmxMM0JoZEhSbGNtNXpMMlJsWm0xaGRHTm9MbXB6SWwwc0ltNWhiV1Z6SWpwYlhTd2liV0Z3Y0dsdVozTWlPaUk3TzBGQlJVRXNVMEZCVXl4VlFVRlVMRkZCUVRKQ0xGTkJRVE5DTzBGQlEwRXNUMEZCVHl4TFFVRkxMRXRCUVV3c1RVRkJaMElzVTBGQmRrSTdPMEZCUlVFc1QwRkJUeXhOUVVGTkxGVkJRVTRzVTBGQmVVSXNTMEZCZWtJc1EwRkJLMEk3UVVGRGNFTXNZMEZCV1N4SFFVRmFMRVZCUVhOQ08wRkJRM0JDTEZsQlJHOUNPenRCUVVkd1FpeFJRVUZITEU5QlFVOHNSMEZCVUN4TFFVRmxMRkZCUVdZc1JVRkJkMEk3UVVGRGVrSXNWMEZCU3l4UFFVRk1MRWRCUVdVc2JVSkJRVzFDTEVsQlFVa3NVVUZCU2l4RlFVRnVRaXhEUVVSVk8wdEJRVE5DTEUxQlJVOHNTVUZCUnl4TlFVRk5MRTlCUVU0c1EwRkJZeXhIUVVGa0xFTkJRVWdzUlVGQmMwSTdRVUZETTBJc1ZVRkJTU3hsUVVGbExFbEJRVWtzUjBGQlNpeERRVUZSTEV0QlFVOHNSVUZCUlN4UlFVRkdMRVZCUVZBc1EwRkJka0lzUTBGRWRVSTdRVUZGTTBJc1YwRkJTeXhQUVVGTUxFZEJRV1VzYlVKQlFXMUNMRmxCUVc1Q0xFTkJSbGs3UzBGQmRFSXNUVUZIUmp0QlFVTklMRmRCUVVzc1QwRkJUQ3hIUVVGbExHMUNRVUZ0UWl4SFFVRnVRaXhEUVVSYU8wdEJTRVU3TzBGQlQxQXNVMEZCU3l4TFFVRk1MRWRCUVdFc1NVRkJTeXhMUVVGS0xFVkJRVVFzUTBGQll5eExRVUZrTEVOQldrODdRVUZoY0VJc1UwRkJTeXhKUVVGTUxFZEJRVmtzUzBGQlN5eFhRVUZNTEVOQlFXbENMRWxCUVdwQ0xFTkJZbEU3UjBGQmRFSTdRMEZFU3pzN1FVRnRRbEFzVDBGQlR5eE5RVUZOTEVsQlFVNHNRMEZCVnpzN1FVRlBhRUlzWTBGQldTeFBRVUZhTEVWQlFXbERMRVZCUVdwRExFVkJRU3RFTEZGQlFVVXNUVUZCVFN4SlFVRk9MRVZCUVZjN1FVRkRNVVVzVTBGQlN5eFBRVUZNTEVkQlFXVXNWMEZCVnl4UFFVRllMRU5CUVdZc1EwRkVNRVU3UVVGRk1VVXNVMEZCU3l4TFFVRk1MRWRCUVdFc1VVRkJVU3hOUVVGU0xFTkJSalpFTzBGQlJ6RkZMRk5CUVVzc1UwRkJUQ3hIUVVGcFFpeHJRa0ZCYTBJc1QwRkJiRUlzUTBGQmFrSXNRMEZJTUVVN1FVRkpNVVVzVTBGQlN5eEZRVUZNTEVkQlFWVXNSVUZCVml4RFFVb3dSVHRCUVVzeFJTeFRRVUZMTEV0QlFVd3NSMEZCWVN4TFFVRmlMRU5CVERCRk8wZEJRVFZGTzBOQlVFczdPMEZCWjBKUUxFOUJRVThzVTBGQlV5eFRRVUZVTEVOQlFXMUNMRTlCUVc1Q0xFVkJRWGRETEVWQlFYaERMRVZCUVhORkxGRkJRVVVzVFVGQlRTeEpRVUZPTEVWQlFXdENPMEZCUXk5R0xGTkJRVThzU1VGQlNTeEpRVUZLTEVOQlFWTXNUMEZCVkN4RlFVRnJRaXhGUVVGc1FpeEZRVUZ6UWl4TFFVRjBRaXhEUVVGUUxFTkJSQ3RHTzBOQlFURkdPenRCUVVsUUxFOUJRVThzVTBGQlV5eFJRVUZVTEVOQlFXdENMRWRCUVVjc1MwRkJTQ3hGUVVGcFF6dEJRVU40UkN4VFFVRlBMRlZCUVZNc1IwRkJSeXhKUVVGSUxFVkJRVEJDTzBGQlEzaERMRk5CUVVzc1NVRkJTU3hoUVVGS0xFbEJRWEZDTEV0QlFURkNMRVZCUVdsRE8wRkJReTlDTEZWQlFVa3NVMEZCVXl4RlFVRlVMRU5CUkRKQ08wRkJSUzlDTEdGQlFVOHNjVUpCUVhGQ0xFbEJRWEpDTEVWQlFUSkNMR05CUVdNc1MwRkJaQ3hGUVVGeFFpeGpRVUZqTEZOQlFXUXNRMEZCZGtRc1EwRkdLMEk3TzBGQlNTOUNMRlZCUVVrc1kwRkJZeXhQUVVGa0xFTkJRWE5DTEVsQlFYUkNMRVZCUVRSQ0xFMUJRVFZDTEV0QlFYVkRMR05CUVdNc1MwRkJaQ3hEUVVGdlFpeExRVUZ3UWl4RFFVRXdRaXhKUVVFeFFpeEZRVUZuUXl4TlFVRm9ReXhEUVVGMlF5eEZRVUZuUmp0QlFVTnNSaXhsUVVGUExHTkJRV01zUlVGQlpDeERRVUZwUWl4TFFVRnFRaXhEUVVGMVFpeEpRVUYyUWl4RlFVRTJRaXhOUVVFM1FpeERRVUZRTEVOQlJHdEdPMDlCUVhCR08wdEJTa1k3TzBGQlUwRXNWVUZCVFN4SlFVRkpMRlZCUVVvc1EwRkJaU3hKUVVGbUxFTkJRVTRzUTBGV2QwTTdSMEZCYmtNc1EwRkVhVVE3UTBGQmJrUTdPMEZCWlZBc1UwRkJVeXhwUWtGQlZDeERRVUV5UWl4UFFVRXpRaXhGUVVFclF6dEJRVU0zUXl4TlFVRkpMRmxCUVZrc1JVRkJXaXhEUVVSNVF6czdRVUZITjBNc1QwRkJTU3hKUVVGSkxFbEJRVWtzUTBGQlNpeEZRVUZQTEVsQlFVa3NVVUZCVVN4TlFVRlNMRVZCUVdkQ0xFZEJRVzVETEVWQlFYVkRPMEZCUTNKRExGRkJRVWNzVVVGQlVTeERRVUZTTEdGQlFYTkNMRTFCUVUwc1VVRkJUaXhKUVVGclFpeFJRVUZSTEVOQlFWSXNSVUZCVnl4aFFVRllMRWxCUVRSQ0xFOUJRVThzUjBGQlVDeERRVUZYTEhWQ1FVRllMRU5CUVRWQ0xFVkJRV2RGTzBGQlEzcEhMR2RDUVVGVkxFbEJRVllzUTBGQlpTeERRVUZETEVOQlFVUXNSVUZCU1N4UlFVRlJMRU5CUVZJc1JVRkJWeXhoUVVGWUxFTkJRVzVDTEVWQlJIbEhPMHRCUVROSE8wZEJSRVk3TzBGQlRVRXNVMEZCVHl4VFFVRlFMRU5CVkRaRE8wTkJRUzlET3p0QlFWbEJMRk5CUVZNc2IwSkJRVlFzUTBGQk9FSXNTVUZCT1VJc1JVRkJiME1zUzBGQmNFTXNSVUZCTWtNc1UwRkJNME1zUlVGQmNVUTdRVUZEYmtRc1RVRkJSeXhMUVVGTExFMUJRVXdzUzBGQlowSXNTMEZCYUVJc1NVRkJlVUlzVlVGQlZTeE5RVUZXTEV0QlFYRkNMRU5CUVhKQ0xFVkJRWFZDTzBGQlEycEVMRmRCUVU4c1NVRkJVQ3hEUVVScFJEdEhRVUZ1UkRzN1FVRkpRU3hOUVVGSExFdEJRVXNzVFVGQlRDeEhRVUZqTEZWQlFWVXNUVUZCVml4SFFVRnRRaXhMUVVGcVF5eEZRVUYxUXp0QlFVTjRReXhYUVVGUExFbEJRVkFzUTBGRWQwTTdSMEZCTVVNN08wRkJTVUVzVFVGQlNTd3dRa0ZCTUVJc1VVRkJVU3hMUVVGTExFMUJRVXdzUTBGVVlUdEJRVlZ1UkN4TlFVRkpMRzlDUVVGdlFpeFZRVUZWTEUxQlFWWXNSMEZCYlVJc2RVSkJRVzVDTEVOQlZqSkNPenRCUVZsdVJDeE5RVUZKTEdsQ1FVRnBRaXhWUVVGVkxFdEJRVllzUTBGQlowSXNhVUpCUVdoQ0xFTkJRV3BDTEVOQldpdERPenRCUVdOdVJDeFBRVUZKTEVsQlFVa3NRMEZCUXl4TFFVRkVMRVZCUVZFc1MwRkJVaXhEUVVGS0xFbEJRWE5DTEdOQlFURkNMRVZCUVhsRE8wRkJRM1pETEZOQlFVc3NUVUZCVEN4RFFVRlpMRXRCUVZvc1JVRkJiVUlzUTBGQmJrSXNSVUZCYzBJc1MwRkJkRUlzUlVGRWRVTTdRVUZGZGtNc1VVRkJSeXhMUVVGTExFMUJRVXdzUzBGQlowSXNTMEZCYUVJc1JVRkJjMEk3UVVGRGRrSXNXVUZFZFVJN1MwRkJla0k3UjBGR1JqczdRVUZQUVN4VFFVRlBMRWxCUVZBc1EwRnlRbTFFTzBOQlFYSkVPenRCUVhkQ1FTeFBRVUZQTEZOQlFWTXNTMEZCVkN4RFFVRmxMRTlCUVdZc1JVRkJOa0lzU1VGQk4wSXNSVUZCZDBRc1VVRkJSU3hOUVVGTkxFbEJRVTRzUlVGQmQwSTdRVUZEZGtZc1RVRkJTU3hUUVVGVExFVkJRVlFzUTBGRWJVWTdRVUZGZGtZc1RVRkJTU3h0UWtGQmJVSXNWMEZCVnl4UFFVRllMRU5CUVc1Q0xFTkJSbTFHTzBGQlIzWkdMRTFCUVVrc2FVSkJRV2xDTEVsQlFXcENMRVZCUVhWQ0xFMUJRWFpDTEV0QlFXdERMRTFCUVUwc1MwRkJUaXhEUVVGWkxFbEJRVm9zUlVGQmEwSXNUVUZCYkVJc1EwRkJiRU1zUlVGQk5FUTdRVUZET1VRc1YwRkJUeXhOUVVGUUxFTkJSRGhFTzBkQlFXaEZMRTFCUlVzN1FVRkRTQ3hWUVVGTkxFbEJRVWtzVlVGQlNpeERRVUZsTEVsQlFXWXNRMEZCVGl4RFFVUkhPMGRCUmt3N1EwRklTenM3UVVGVlVDeFBRVUZQTEZOQlFWTXNZMEZCVkN4RFFVRjNRaXhQUVVGNFFpeEZRVUZ6UXl4SlFVRjBReXhGUVVGcFJTeFJRVUZGTEUxQlFVMHNTVUZCVGl4RlFVRjVRanRCUVVOcVJ5eE5RVUZITzBGQlEwUXNWMEZCVHl4TlFVRk5MRTlCUVU0c1JVRkJaU3hKUVVGbUxFVkJRWEZDTEV0QlFYSkNMRU5CUVZBc1EwRkVRenRIUVVGSUxFTkJSVU1zVDBGQlRTeERRVUZPTEVWQlFWRTdRVUZEVUN4UlFVRkhMR0ZCUVdFc1ZVRkJZaXhKUVVFeVFpeEZRVUZGTEU5QlFVWXNRMEZCVlN4VlFVRldMRU5CUVhGQ0xHVkJRWEpDTEVOQlFUTkNMRVZCUVdsRk8wRkJRMnhGTEdGQlFVOHNTVUZCVUN4RFFVUnJSVHRMUVVGd1JUczdRVUZKUVN4VlFVRk5MRU5CUVU0c1EwRk1UenRIUVVGU08wTkJTRWs3TzBGQldWQXNUMEZCVHl4VFFVRlRMRlZCUVZRc1EwRkJiMElzVlVGQmNFSXNSVUZCTkVNc1QwRkJOVU1zUlVGQk1FUXNSMEZCTVVRc1JVRkJlVVlzVVVGQlJTeE5RVUZOTEVsQlFVNHNSVUZCZDBJN1FVRkRlRWdzVFVGQlNTeE5RVUZOTEVWQlFVNHNRMEZFYjBnN08wRkJSM2hJTEU5QlFVa3NTVUZCU1N4SlFVRktMRWxCUVZrc1ZVRkJhRUlzUlVGQk1rSTdRVUZEZWtJc1VVRkJSenRCUVVORUxGVkJRVWtzVTBGQlV5eEpRVUZKTEV0QlFVb3NRMEZCVlN4SlFVRldMRVZCUVdkQ0xFMUJRVTBzVDBGQlRpeEZRVUZsTEVsQlFXWXNSVUZCY1VJc1MwRkJja0lzUTBGQmFFSXNRMEZCVkN4RFFVUklPMEZCUlVRc1dVRkJUU3hKUVVGSkxFMUJRVW9zUTBGQlZ5eE5RVUZZTEVOQlFVNHNRMEZHUXp0TFFVRklMRU5CUjBNc1QwRkJUU3hEUVVGT0xFVkJRVkU3UVVGRFZDeFZRVUZITEVWQlFVVXNZVUZCWVN4VlFVRmlMRU5CUVVZc1JVRkJNa0k3UVVGRE1VSXNZMEZCVFN4RFFVRk9MRU5CUkRCQ08wOUJRVGxDTzB0QlJFTTdSMEZLU0RzN1FVRlhRU3hUUVVGUExFZEJRVkFzUTBGa2QwZzdRMEZCYmtnaUxDSm1hV3hsSWpvaWJHbGlMMk52Y21VdmNHRjBkR1Z5Ym5NdlpHVm1iV0YwWTJndWFuTWlMQ0p6YjNWeVkyVnpRMjl1ZEdWdWRDSTZXeUl2S2lCQVpteHZkeUFxTDF4dVhHNXBiWEJ2Y25RZ2V5QmlkV2xzWkUxaGRHTm9JSDBnWm5KdmJTQmNJaTR2YldGMFkyaGNJanRjYm1sdGNHOXlkQ0FxSUdGeklGUjVjR1Z6SUdaeWIyMGdYQ0l1TDNSNWNHVnpYQ0k3WEc1Y2JtVjRjRzl5ZENCamJHRnpjeUJOWVhSamFFVnljbTl5SUdWNGRHVnVaSE1nUlhKeWIzSWdlMXh1SUNCamIyNXpkSEoxWTNSdmNpaGhjbWM2SUdGdWVTa2dlMXh1SUNBZ0lITjFjR1Z5S0NrN1hHNWNiaUFnSUNCcFppaDBlWEJsYjJZZ1lYSm5JRDA5UFNBbmMzbHRZbTlzSnlsN1hHNGdJQ0FnSUNCMGFHbHpMbTFsYzNOaFoyVWdQU0FuVG04Z2JXRjBZMmdnWm05eU9pQW5JQ3NnWVhKbkxuUnZVM1J5YVc1bktDazdYRzRnSUNBZ2ZTQmxiSE5sSUdsbUtFRnljbUY1TG1selFYSnlZWGtvWVhKbktTbDdYRzRnSUNBZ0lDQnNaWFFnYldGd2NHVmtWbUZzZFdWeklEMGdZWEpuTG0xaGNDZ29lQ2tnUFQ0Z2VDNTBiMU4wY21sdVp5Z3BLVHRjYmlBZ0lDQWdJSFJvYVhNdWJXVnpjMkZuWlNBOUlDZE9ieUJ0WVhSamFDQm1iM0k2SUNjZ0t5QnRZWEJ3WldSV1lXeDFaWE03WEc0Z0lDQWdmV1ZzYzJWN1hHNGdJQ0FnSUNCMGFHbHpMbTFsYzNOaFoyVWdQU0FuVG04Z2JXRjBZMmdnWm05eU9pQW5JQ3NnWVhKbk8xeHVJQ0FnSUgxY2JseHVJQ0FnSUhSb2FYTXVjM1JoWTJzZ1BTQW9ibVYzSUVWeWNtOXlLQ2twTG5OMFlXTnJPMXh1SUNBZ0lIUm9hWE11Ym1GdFpTQTlJSFJvYVhNdVkyOXVjM1J5ZFdOMGIzSXVibUZ0WlR0Y2JpQWdmVnh1ZlZ4dVhHNWNibVY0Y0c5eWRDQmpiR0Z6Y3lCRFlYTmxJSHRjYmlBZ2NHRjBkR1Z5YmpvZ1JuVnVZM1JwYjI0N1hHNGdJR1p1T2lCR2RXNWpkR2x2Ymp0Y2JpQWdaM1ZoY21RNklFWjFibU4wYVc5dU8xeHVJQ0JoY21sMGVUb2diblZ0WW1WeU8xeHVJQ0J2Y0hScGIyNWhiSE02SUVGeWNtRjVQR0Z1ZVQ0N1hHNWNiaUFnWTI5dWMzUnlkV04wYjNJb2NHRjBkR1Z5YmpvZ1FYSnlZWGs4WVc1NVBpd2dabTQ2SUVaMWJtTjBhVzl1TENCbmRXRnlaRG9nUm5WdVkzUnBiMjRnUFNBb0tTQTlQaUIwY25WbEtYdGNiaUFnSUNCMGFHbHpMbkJoZEhSbGNtNGdQU0JpZFdsc1pFMWhkR05vS0hCaGRIUmxjbTRwTzF4dUlDQWdJSFJvYVhNdVlYSnBkSGtnUFNCd1lYUjBaWEp1TG14bGJtZDBhRHRjYmlBZ0lDQjBhR2x6TG05d2RHbHZibUZzY3lBOUlHZGxkRTl3ZEdsdmJtRnNWbUZzZFdWektIQmhkSFJsY200cE8xeHVJQ0FnSUhSb2FYTXVabTRnUFNCbWJqdGNiaUFnSUNCMGFHbHpMbWQxWVhKa0lEMGdaM1ZoY21RN1hHNGdJSDFjYm4xY2JseHVaWGh3YjNKMElHWjFibU4wYVc5dUlHMWhhMlZmWTJGelpTaHdZWFIwWlhKdU9pQkJjbkpoZVR4aGJuaytMQ0JtYmpvZ1JuVnVZM1JwYjI0c0lHZDFZWEprT2lCR2RXNWpkR2x2YmlBOUlDZ3BJRDArSUhSeWRXVXBPaUJEWVhObElIdGNiaUFnY21WMGRYSnVJRzVsZHlCRFlYTmxLSEJoZEhSbGNtNHNJR1p1TENCbmRXRnlaQ2s3WEc1OVhHNWNibVY0Y0c5eWRDQm1kVzVqZEdsdmJpQmtaV1p0WVhSamFDZ3VMaTVqWVhObGN6b2dRWEp5WVhrOFEyRnpaVDRwT2lCR2RXNWpkR2x2YmlCN1hHNGdJSEpsZEhWeWJpQm1kVzVqZEdsdmJpZ3VMaTVoY21kek9pQkJjbkpoZVR4aGJuaytLVG9nWVc1NUlIdGNiaUFnSUNCbWIzSWdLR3hsZENCd2NtOWpaWE56WldSRFlYTmxJRzltSUdOaGMyVnpLU0I3WEc0Z0lDQWdJQ0JzWlhRZ2NtVnpkV3gwSUQwZ1cxMDdYRzRnSUNBZ0lDQmhjbWR6SUQwZ1ptbHNiRWx1VDNCMGFXOXVZV3hXWVd4MVpYTW9ZWEpuY3l3Z2NISnZZMlZ6YzJWa1EyRnpaUzVoY21sMGVTd2djSEp2WTJWemMyVmtRMkZ6WlM1dmNIUnBiMjVoYkhNcE8xeHVYRzRnSUNBZ0lDQnBaaUFvY0hKdlkyVnpjMlZrUTJGelpTNXdZWFIwWlhKdUtHRnlaM01zSUhKbGMzVnNkQ2tnSmlZZ2NISnZZMlZ6YzJWa1EyRnpaUzVuZFdGeVpDNWhjSEJzZVNoMGFHbHpMQ0J5WlhOMWJIUXBLU0I3WEc0Z0lDQWdJQ0FnSUhKbGRIVnliaUJ3Y205alpYTnpaV1JEWVhObExtWnVMbUZ3Y0d4NUtIUm9hWE1zSUhKbGMzVnNkQ2s3WEc0Z0lDQWdJQ0I5WEc0Z0lDQWdmVnh1WEc0Z0lDQWdkR2h5YjNjZ2JtVjNJRTFoZEdOb1JYSnliM0lvWVhKbmN5azdYRzRnSUgwN1hHNTlYRzVjYm1aMWJtTjBhVzl1SUdkbGRFOXdkR2x2Ym1Gc1ZtRnNkV1Z6S0hCaGRIUmxjbTQ2SUVGeWNtRjVQR0Z1ZVQ0cGUxeHVJQ0JzWlhRZ2IzQjBhVzl1WVd4eklEMGdXMTA3WEc1Y2JpQWdabTl5S0d4bGRDQnBJRDBnTURzZ2FTQThJSEJoZEhSbGNtNHViR1Z1WjNSb095QnBLeXNwZTF4dUlDQWdJR2xtS0hCaGRIUmxjbTViYVYwZ2FXNXpkR0Z1WTJWdlppQlVlWEJsY3k1V1lYSnBZV0pzWlNBbUppQndZWFIwWlhKdVcybGRMbVJsWm1GMWJIUmZkbUZzZFdVZ0lUMGdVM2x0WW05c0xtWnZjaWhjSW1Wc2FYaHBjbk5qY21sd2RDNXViMTkyWVd4MVpWd2lLU2w3WEc0Z0lDQWdJQ0J2Y0hScGIyNWhiSE11Y0hWemFDaGJhU3dnY0dGMGRHVnlibHRwWFM1a1pXWmhkV3gwWDNaaGJIVmxYU2s3WEc0Z0lDQWdmVnh1SUNCOVhHNWNiaUFnY21WMGRYSnVJRzl3ZEdsdmJtRnNjenRjYm4xY2JseHVablZ1WTNScGIyNGdabWxzYkVsdVQzQjBhVzl1WVd4V1lXeDFaWE1vWVhKbmN5d2dZWEpwZEhrc0lHOXdkR2x2Ym1Gc2N5bDdYRzRnSUdsbUtHRnlaM011YkdWdVozUm9JRDA5UFNCaGNtbDBlU0I4ZkNCdmNIUnBiMjVoYkhNdWJHVnVaM1JvSUQwOVBTQXdLWHRjYmlBZ0lDQnlaWFIxY200Z1lYSm5jenRjYmlBZ2ZWeHVYRzRnSUdsbUtHRnlaM011YkdWdVozUm9JQ3NnYjNCMGFXOXVZV3h6TG14bGJtZDBhQ0E4SUdGeWFYUjVLWHRjYmlBZ0lDQnlaWFIxY200Z1lYSm5jenRjYmlBZ2ZWeHVYRzRnSUd4bGRDQnVkVzFpWlhKUFprOXdkR2x2Ym1Gc2MxUnZSbWxzYkNBOUlHRnlhWFI1SUMwZ1lYSm5jeTVzWlc1bmRHZzdYRzRnSUd4bGRDQnZjSFJwYjI1aGJITlViMUpsYlc5MlpTQTlJRzl3ZEdsdmJtRnNjeTVzWlc1bmRHZ2dMU0J1ZFcxaVpYSlBaazl3ZEdsdmJtRnNjMVJ2Um1sc2JEdGNibHh1SUNCc1pYUWdiM0IwYVc5dVlXeHpWRzlWYzJVZ1BTQnZjSFJwYjI1aGJITXVjMnhwWTJVb2IzQjBhVzl1WVd4elZHOVNaVzF2ZG1VcE8xeHVYRzRnSUdadmNpaHNaWFFnVzJsdVpHVjRMQ0IyWVd4MVpWMGdiMllnYjNCMGFXOXVZV3h6Vkc5VmMyVXBlMXh1SUNBZ0lHRnlaM011YzNCc2FXTmxLR2x1WkdWNExDQXdMQ0IyWVd4MVpTazdYRzRnSUNBZ2FXWW9ZWEpuY3k1c1pXNW5kR2dnUFQwOUlHRnlhWFI1S1h0Y2JpQWdJQ0FnSUdKeVpXRnJPMXh1SUNBZ0lIMWNiaUFnZlZ4dVhHNGdJSEpsZEhWeWJpQmhjbWR6TzF4dWZWeHVYRzVsZUhCdmNuUWdablZ1WTNScGIyNGdiV0YwWTJnb2NHRjBkR1Z5YmpvZ1lXNTVMQ0JsZUhCeU9pQmhibmtzSUdkMVlYSmtPaUJHZFc1amRHbHZiaUE5SUNncElEMCtJSFJ5ZFdVcE9pQkJjbkpoZVR4aGJuaytJSHRjYmlBZ2JHVjBJSEpsYzNWc2RDQTlJRnRkTzF4dUlDQnNaWFFnY0hKdlkyVnpjMlZrVUdGMGRHVnliaUE5SUdKMWFXeGtUV0YwWTJnb2NHRjBkR1Z5YmlrN1hHNGdJR2xtSUNod2NtOWpaWE56WldSUVlYUjBaWEp1S0dWNGNISXNJSEpsYzNWc2RDa2dKaVlnWjNWaGNtUXVZWEJ3Ykhrb2RHaHBjeXdnY21WemRXeDBLU2w3WEc0Z0lDQWdjbVYwZFhKdUlISmxjM1ZzZER0Y2JpQWdmV1ZzYzJWN1hHNGdJQ0FnZEdoeWIzY2dibVYzSUUxaGRHTm9SWEp5YjNJb1pYaHdjaWs3WEc0Z0lIMWNibjFjYmx4dVpYaHdiM0owSUdaMWJtTjBhVzl1SUcxaGRHTm9YMjV2WDNSb2NtOTNLSEJoZEhSbGNtNDZJR0Z1ZVN3Z1pYaHdjam9nWVc1NUxDQm5kV0Z5WkRvZ1JuVnVZM1JwYjI0Z1BTQW9LU0E5UGlCMGNuVmxLVG9nUDBGeWNtRjVQR0Z1ZVQ0Z2UxeHVJQ0IwY25sN1hHNGdJQ0FnY21WMGRYSnVJRzFoZEdOb0tIQmhkSFJsY200c0lHVjRjSElzSUdkMVlYSmtLVHRjYmlBZ2ZXTmhkR05vS0dVcGUxeHVJQ0FnSUdsbUtHVWdhVzV6ZEdGdVkyVnZaaUJOWVhSamFFVnljbTl5SUh4OElHVXViV1Z6YzJGblpTNXpkR0Z5ZEhOWGFYUm9LQ2RPYnlCdFlYUmphQ0JtYjNJNkp5a3BlMXh1SUNBZ0lDQWdjbVYwZFhKdUlHNTFiR3c3WEc0Z0lDQWdmVnh1WEc0Z0lDQWdkR2h5YjNjZ1pUdGNiaUFnZlZ4dWZWeHVYRzVsZUhCdmNuUWdablZ1WTNScGIyNGdjR0YwZEdWeWJrMWhjQ2hqYjJ4c1pXTjBhVzl1T2lCQmNuSmhlVHhoYm5rK0xDQndZWFIwWlhKdU9pQmhibmtzSUdaMWJqb2dSblZ1WTNScGIyNHNJR2QxWVhKa09pQkdkVzVqZEdsdmJpQTlJQ2dwSUQwK0lIUnlkV1VwT2lCQmNuSmhlVHhoYm5rK0lIdGNiaUFnYkdWMElISmxkQ0E5SUZ0ZE8xeHVYRzRnSUdadmNpaHNaWFFnWld4bGJTQnZaaUJqYjJ4c1pXTjBhVzl1S1h0Y2JpQWdJQ0IwY25sN1hHNGdJQ0FnSUNCc1pYUWdjbVZ6ZFd4MElEMGdablZ1TG1Gd2NHeDVLSFJvYVhNc0lHMWhkR05vS0hCaGRIUmxjbTRzSUdWc1pXMHNJR2QxWVhKa0tTazdYRzRnSUNBZ0lDQnlaWFFnUFNCeVpYUXVZMjl1WTJGMEtISmxjM1ZzZENrN1hHNGdJQ0FnZldOaGRHTm9LR1VwZTF4dUlDQWdJR2xtS0NFb1pTQnBibk4wWVc1alpXOW1JRTFoZEdOb1JYSnliM0lwS1h0Y2JpQWdJQ0FnSUNBZ2RHaHliM2NnWlR0Y2JpQWdJQ0FnSUgxY2JpQWdJQ0I5WEc0Z0lIMWNibHh1SUNCeVpYUjFjbTRnY21WME8xeHVmVnh1SWwwc0luTnZkWEpqWlZKdmIzUWlPaUl2YzI5MWNtTmxMeUo5XG4iLCJcblxuaW1wb3J0IHsgZGVmbWF0Y2gsIG1hdGNoLCBNYXRjaEVycm9yLCBtYXRjaF9ub190aHJvdywgcGF0dGVybk1hcCwgQ2FzZSwgbWFrZV9jYXNlIH0gZnJvbSBcIi4vcGF0dGVybnMvZGVmbWF0Y2hcIjtcbmltcG9ydCB7IHZhcmlhYmxlLCB3aWxkY2FyZCwgc3RhcnRzV2l0aCwgY2FwdHVyZSwgaGVhZFRhaWwsIHR5cGUsIGJvdW5kLCBiaXRTdHJpbmdNYXRjaCB9IGZyb20gXCIuL3BhdHRlcm5zL3R5cGVzXCI7XG5cbmV4cG9ydCBkZWZhdWx0IHtcbiAgZGVmbWF0Y2gsIG1hdGNoLCBNYXRjaEVycm9yLCBtYXRjaF9ub190aHJvdyxcbiAgdmFyaWFibGUsIHdpbGRjYXJkLCBzdGFydHNXaXRoLFxuICBjYXB0dXJlLCBoZWFkVGFpbCwgdHlwZSwgYm91bmQsIENhc2UsIG1ha2VfY2FzZSwgYml0U3RyaW5nTWF0Y2hcbn07XG4vLyMgc291cmNlTWFwcGluZ1VSTD1kYXRhOmFwcGxpY2F0aW9uL2pzb247YmFzZTY0LGV5SjJaWEp6YVc5dUlqb3pMQ0p6YjNWeVkyVnpJanBiSW14cFlpOWpiM0psTDNCaGRIUmxjbTV6TG1weklsMHNJbTVoYldWeklqcGJYU3dpYldGd2NHbHVaM01pT2lJN08wRkJSVUVzVTBGQlV5eFJRVUZVTEVWQlFXMUNMRXRCUVc1Q0xFVkJRVEJDTEZWQlFURkNMRVZCUVhORExHTkJRWFJETEVWQlFYTkVMRlZCUVhSRUxFVkJRV3RGTEVsQlFXeEZMRVZCUVhkRkxGTkJRWGhGTEZGQlFYbEdMSEZDUVVGNlJqdEJRVU5CTEZOQlFWTXNVVUZCVkN4RlFVRnRRaXhSUVVGdVFpeEZRVUUyUWl4VlFVRTNRaXhGUVVGNVF5eFBRVUY2UXl4RlFVRnJSQ3hSUVVGc1JDeEZRVUUwUkN4SlFVRTFSQ3hGUVVGclJTeExRVUZzUlN4RlFVRjVSU3hqUVVGNlJTeFJRVUVyUml4clFrRkJMMFk3TzBGQlIwRXNaVUZCWlR0QlFVTmlMRlZCUkdFc1JVRkRTQ3hMUVVSSExFVkJRMGtzVlVGRVNpeEZRVU5uUWl4alFVUm9RanRCUVVWaUxGVkJSbUVzUlVGRlNDeFJRVVpITEVWQlJVOHNWVUZHVUR0QlFVZGlMRk5CU0dFc1JVRkhTaXhSUVVoSkxFVkJSMDBzU1VGSVRpeEZRVWRaTEV0QlNGb3NSVUZIYlVJc1NVRklia0lzUlVGSGVVSXNVMEZJZWtJc1JVRkhiME1zWTBGSWNFTTdRMEZCWmlJc0ltWnBiR1VpT2lKc2FXSXZZMjl5WlM5d1lYUjBaWEp1Y3k1cWN5SXNJbk52ZFhKalpYTkRiMjUwWlc1MElqcGJJaThxSUVCbWJHOTNJQ292WEc1Y2JtbHRjRzl5ZENCN0lHUmxabTFoZEdOb0xDQnRZWFJqYUN3Z1RXRjBZMmhGY25KdmNpd2diV0YwWTJoZmJtOWZkR2h5YjNjc0lIQmhkSFJsY201TllYQXNJRU5oYzJVc0lHMWhhMlZmWTJGelpTQjlJR1p5YjIwZ1hDSXVMM0JoZEhSbGNtNXpMMlJsWm0xaGRHTm9YQ0k3WEc1cGJYQnZjblFnZXlCMllYSnBZV0pzWlN3Z2QybHNaR05oY21Rc0lITjBZWEowYzFkcGRHZ3NJR05oY0hSMWNtVXNJR2hsWVdSVVlXbHNMQ0IwZVhCbExDQmliM1Z1WkN3Z1ltbDBVM1J5YVc1blRXRjBZMmdnZlNCbWNtOXRJRndpTGk5d1lYUjBaWEp1Y3k5MGVYQmxjMXdpTzF4dVhHNWNibVY0Y0c5eWRDQmtaV1poZFd4MElIdGNiaUFnWkdWbWJXRjBZMmdzSUcxaGRHTm9MQ0JOWVhSamFFVnljbTl5TENCdFlYUmphRjl1YjE5MGFISnZkeXhjYmlBZ2RtRnlhV0ZpYkdVc0lIZHBiR1JqWVhKa0xDQnpkR0Z5ZEhOWGFYUm9MRnh1SUNCallYQjBkWEpsTENCb1pXRmtWR0ZwYkN3Z2RIbHdaU3dnWW05MWJtUXNJRU5oYzJVc0lHMWhhMlZmWTJGelpTd2dZbWwwVTNSeWFXNW5UV0YwWTJoY2JuMDdYRzRpWFN3aWMyOTFjbU5sVW05dmRDSTZJaTl6YjNWeVkyVXZJbjA9XG4iLCJpbXBvcnQgeyBJbnRlZ2VyLCBGbG9hdCB9IGZyb20gJy4vcHJpbWl0aXZlcyc7XG5cbi8vaHR0cHM6Ly9naXRodWIuY29tL2FpcnBvcnR5aC9wcm90b21vcnBoaXNtXG5jbGFzcyBQcm90b2NvbCB7XG4gIGNvbnN0cnVjdG9yKHNwZWMpIHtcbiAgICB0aGlzLnJlZ2lzdHJ5ID0gbmV3IE1hcCgpO1xuICAgIHRoaXMuZmFsbGJhY2sgPSBudWxsO1xuXG4gICAgZm9yIChsZXQgZnVuTmFtZSBpbiBzcGVjKSB7XG4gICAgICB0aGlzW2Z1bk5hbWVdID0gY3JlYXRlRnVuKGZ1bk5hbWUpLmJpbmQodGhpcyk7XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gY3JlYXRlRnVuKGZ1bk5hbWUpIHtcblxuICAgICAgcmV0dXJuIGZ1bmN0aW9uICguLi5hcmdzKSB7XG4gICAgICAgIGxldCB0aGluZyA9IGFyZ3NbMF07XG4gICAgICAgIGxldCBmdW4gPSBudWxsO1xuXG4gICAgICAgIGlmIChOdW1iZXIuaXNJbnRlZ2VyKHRoaW5nKSAmJiB0aGlzLmhhc0ltcGxlbWVudGF0aW9uKEludGVnZXIpKSB7XG4gICAgICAgICAgZnVuID0gdGhpcy5yZWdpc3RyeS5nZXQoSW50ZWdlcilbZnVuTmFtZV07XG4gICAgICAgIH0gZWxzZSBpZiAodHlwZW9mIHRoaW5nID09PSBcIm51bWJlclwiICYmICFOdW1iZXIuaXNJbnRlZ2VyKHRoaW5nKSAmJiB0aGlzLmhhc0ltcGxlbWVudGF0aW9uKEZsb2F0KSkge1xuICAgICAgICAgIGZ1biA9IHRoaXMucmVnaXN0cnkuZ2V0KEZsb2F0KVtmdW5OYW1lXTtcbiAgICAgICAgfSBlbHNlIGlmICh0aGlzLmhhc0ltcGxlbWVudGF0aW9uKHRoaW5nKSkge1xuICAgICAgICAgIGZ1biA9IHRoaXMucmVnaXN0cnkuZ2V0KHRoaW5nLmNvbnN0cnVjdG9yKVtmdW5OYW1lXTtcbiAgICAgICAgfSBlbHNlIGlmICh0aGlzLmZhbGxiYWNrKSB7XG4gICAgICAgICAgZnVuID0gdGhpcy5mYWxsYmFja1tmdW5OYW1lXTtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmIChmdW4gIT0gbnVsbCkge1xuICAgICAgICAgIGxldCByZXR2YWwgPSBmdW4uYXBwbHkodGhpcywgYXJncyk7XG4gICAgICAgICAgcmV0dXJuIHJldHZhbDtcbiAgICAgICAgfVxuXG4gICAgICAgIHRocm93IG5ldyBFcnJvcihcIk5vIGltcGxlbWVudGF0aW9uIGZvdW5kIGZvciBcIiArIHRoaW5nKTtcbiAgICAgIH07XG4gICAgfVxuICB9XG5cbiAgaW1wbGVtZW50YXRpb24odHlwZSwgaW1wbGVtZW50YXRpb24pIHtcbiAgICBpZiAodHlwZSA9PT0gbnVsbCkge1xuICAgICAgdGhpcy5mYWxsYmFjayA9IGltcGxlbWVudGF0aW9uO1xuICAgIH0gZWxzZSB7XG4gICAgICB0aGlzLnJlZ2lzdHJ5LnNldCh0eXBlLCBpbXBsZW1lbnRhdGlvbik7XG4gICAgfVxuICB9XG5cbiAgaGFzSW1wbGVtZW50YXRpb24odGhpbmcpIHtcbiAgICBpZiAodGhpbmcgPT09IEludGVnZXIgfHwgdGhpbmcgPT09IEZsb2F0KSB7XG4gICAgICByZXR1cm4gdGhpcy5yZWdpc3RyeS5oYXModGhpbmcpO1xuICAgIH1cblxuICAgIHJldHVybiB0aGlzLnJlZ2lzdHJ5Lmhhcyh0aGluZy5jb25zdHJ1Y3Rvcik7XG4gIH1cbn1cblxuZXhwb3J0IGRlZmF1bHQgUHJvdG9jb2w7XG4vLyMgc291cmNlTWFwcGluZ1VSTD1kYXRhOmFwcGxpY2F0aW9uL2pzb247YmFzZTY0LGV5SjJaWEp6YVc5dUlqb3pMQ0p6YjNWeVkyVnpJanBiSW14cFlpOWpiM0psTDNCeWIzUnZZMjlzTG1weklsMHNJbTVoYldWeklqcGJYU3dpYldGd2NHbHVaM01pT2lKQlFVRkJMRk5CUVZNc1QwRkJWQ3hGUVVGclFpeExRVUZzUWl4UlFVRXJRaXhqUVVFdlFqczdPMEZCUjBFc1RVRkJUU3hSUVVGT0xFTkJRV003UVVGRFdpeGpRVUZaTEVsQlFWb3NSVUZCYVVJN1FVRkRaaXhUUVVGTExGRkJRVXdzUjBGQlowSXNTVUZCU1N4SFFVRktMRVZCUVdoQ0xFTkJSR1U3UVVGRlppeFRRVUZMTEZGQlFVd3NSMEZCWjBJc1NVRkJhRUlzUTBGR1pUczdRVUZKWml4VFFVRkxMRWxCUVVrc1QwRkJTaXhKUVVGbExFbEJRWEJDTEVWQlFYbENPMEZCUTNaQ0xGZEJRVXNzVDBGQlRDeEpRVUZuUWl4VlFVRlZMRTlCUVZZc1JVRkJiVUlzU1VGQmJrSXNRMEZCZDBJc1NVRkJlRUlzUTBGQmFFSXNRMEZFZFVJN1MwRkJla0k3TzBGQlNVRXNZVUZCVXl4VFFVRlVMRU5CUVcxQ0xFOUJRVzVDTEVWQlFUSkNPenRCUVVWNlFpeGhRVUZQTEZWQlFWTXNSMEZCUnl4SlFVRklMRVZCUVZNN1FVRkRka0lzV1VGQlNTeFJRVUZSTEV0QlFVc3NRMEZCVEN4RFFVRlNMRU5CUkcxQ08wRkJSWFpDTEZsQlFVa3NUVUZCVFN4SlFVRk9MRU5CUm0xQ096dEJRVWwyUWl4WlFVRkhMRTlCUVU4c1UwRkJVQ3hEUVVGcFFpeExRVUZxUWl4TFFVRXlRaXhMUVVGTExHbENRVUZNTEVOQlFYVkNMRTlCUVhaQ0xFTkJRVE5DTEVWQlFUSkVPMEZCUXpWRUxHZENRVUZOTEV0QlFVc3NVVUZCVEN4RFFVRmpMRWRCUVdRc1EwRkJhMElzVDBGQmJFSXNSVUZCTWtJc1QwRkJNMElzUTBGQlRpeERRVVEwUkR0VFFVRTVSQ3hOUVVWTkxFbEJRVWNzVDBGQlR5eExRVUZRTEV0QlFXbENMRkZCUVdwQ0xFbEJRVFpDTEVOQlFVTXNUMEZCVHl4VFFVRlFMRU5CUVdsQ0xFdEJRV3BDTEVOQlFVUXNTVUZCTkVJc1MwRkJTeXhwUWtGQlRDeERRVUYxUWl4TFFVRjJRaXhEUVVGNlJDeEZRVUYxUmp0QlFVTTVSaXhuUWtGQlRTeExRVUZMTEZGQlFVd3NRMEZCWXl4SFFVRmtMRU5CUVd0Q0xFdEJRV3hDTEVWQlFYbENMRTlCUVhwQ0xFTkJRVTRzUTBGRU9FWTdVMEZCTVVZc1RVRkZRU3hKUVVGSExFdEJRVXNzYVVKQlFVd3NRMEZCZFVJc1MwRkJka0lzUTBGQlNDeEZRVUZwUXp0QlFVTnlReXhuUWtGQlRTeExRVUZMTEZGQlFVd3NRMEZCWXl4SFFVRmtMRU5CUVd0Q0xFMUJRVTBzVjBGQlRpeERRVUZzUWl4RFFVRnhReXhQUVVGeVF5eERRVUZPTEVOQlJIRkRPMU5CUVdwRExFMUJSVUVzU1VGQlJ5eExRVUZMTEZGQlFVd3NSVUZCWXp0QlFVTnlRaXhuUWtGQlRTeExRVUZMTEZGQlFVd3NRMEZCWXl4UFFVRmtMRU5CUVU0c1EwRkVjVUk3VTBGQmFrSTdPMEZCU1U0c1dVRkJSeXhQUVVGUExFbEJRVkFzUlVGQldUdEJRVU5pTEdOQlFVa3NVMEZCVXl4SlFVRkpMRXRCUVVvc1EwRkJWU3hKUVVGV0xFVkJRV2RDTEVsQlFXaENMRU5CUVZRc1EwRkVVenRCUVVWaUxHbENRVUZQTEUxQlFWQXNRMEZHWVR0VFFVRm1PenRCUVV0QkxHTkJRVTBzU1VGQlNTeExRVUZLTEVOQlFWVXNhVU5CUVdsRExFdEJRV3BETEVOQlFXaENMRU5CYmtKMVFqdFBRVUZzUWl4RFFVWnJRanRMUVVFelFqdEhRVkpHT3p0QlFXdERRU3hwUWtGQlpTeEpRVUZtTEVWQlFYRkNMR05CUVhKQ0xFVkJRVzlETzBGQlEyeERMRkZCUVVjc1UwRkJVeXhKUVVGVUxFVkJRV003UVVGRFppeFhRVUZMTEZGQlFVd3NSMEZCWjBJc1kwRkJhRUlzUTBGRVpUdExRVUZxUWl4TlFVVkxPMEZCUTBnc1YwRkJTeXhSUVVGTUxFTkJRV01zUjBGQlpDeERRVUZyUWl4SlFVRnNRaXhGUVVGM1FpeGpRVUY0UWl4RlFVUkhPMHRCUmt3N1IwRkVSanM3UVVGUlFTeHZRa0ZCYTBJc1MwRkJiRUlzUlVGQmVVSTdRVUZEZGtJc1VVRkJTU3hWUVVGVkxFOUJRVllzU1VGQmNVSXNWVUZCVlN4TFFVRldMRVZCUVdkQ08wRkJRM1pETEdGQlFVOHNTMEZCU3l4UlFVRk1MRU5CUVdNc1IwRkJaQ3hEUVVGclFpeExRVUZzUWl4RFFVRlFMRU5CUkhWRE8wdEJRWHBET3p0QlFVbEJMRmRCUVU4c1MwRkJTeXhSUVVGTUxFTkJRV01zUjBGQlpDeERRVUZyUWl4TlFVRk5MRmRCUVU0c1EwRkJla0lzUTBGTWRVSTdSMEZCZWtJN1EwRXpRMFk3TzBGQmNVUkJMR1ZCUVdVc1VVRkJaaUlzSW1acGJHVWlPaUpzYVdJdlkyOXlaUzl3Y205MGIyTnZiQzVxY3lJc0luTnZkWEpqWlhORGIyNTBaVzUwSWpwYkltbHRjRzl5ZENCN0lFbHVkR1ZuWlhJc0lFWnNiMkYwSUgwZ1puSnZiU0FuTGk5d2NtbHRhWFJwZG1Wekp6dGNibHh1THk5b2RIUndjem92TDJkcGRHaDFZaTVqYjIwdllXbHljRzl5ZEhsb0wzQnliM1J2Ylc5eWNHaHBjMjFjYm1Oc1lYTnpJRkJ5YjNSdlkyOXNlMXh1SUNCamIyNXpkSEoxWTNSdmNpaHpjR1ZqS1h0Y2JpQWdJQ0IwYUdsekxuSmxaMmx6ZEhKNUlEMGdibVYzSUUxaGNDZ3BPMXh1SUNBZ0lIUm9hWE11Wm1Gc2JHSmhZMnNnUFNCdWRXeHNPMXh1WEc0Z0lDQWdabTl5SUNoc1pYUWdablZ1VG1GdFpTQnBiaUJ6Y0dWaktYdGNiaUFnSUNBZ0lIUm9hWE5iWm5WdVRtRnRaVjBnUFNCamNtVmhkR1ZHZFc0b1puVnVUbUZ0WlNrdVltbHVaQ2gwYUdsektUdGNiaUFnSUNCOVhHNWNiaUFnSUNCbWRXNWpkR2x2YmlCamNtVmhkR1ZHZFc0b1puVnVUbUZ0WlNsN1hHNWNiaUFnSUNBZ0lISmxkSFZ5YmlCbWRXNWpkR2x2YmlndUxpNWhjbWR6S1NCN1hHNGdJQ0FnSUNBZ0lHeGxkQ0IwYUdsdVp5QTlJR0Z5WjNOYk1GMDdYRzRnSUNBZ0lDQWdJR3hsZENCbWRXNGdQU0J1ZFd4c08xeHVYRzRnSUNBZ0lDQWdJR2xtS0U1MWJXSmxjaTVwYzBsdWRHVm5aWElvZEdocGJtY3BJQ1ltSUhSb2FYTXVhR0Z6U1cxd2JHVnRaVzUwWVhScGIyNG9TVzUwWldkbGNpa3BlMXh1SUNBZ0lDQWdJQ0FnSUdaMWJpQTlJSFJvYVhNdWNtVm5hWE4wY25rdVoyVjBLRWx1ZEdWblpYSXBXMloxYms1aGJXVmRPMXh1SUNBZ0lDQWdJQ0I5Wld4elpTQnBaaWgwZVhCbGIyWWdkR2hwYm1jZ1BUMDlJRndpYm5WdFltVnlYQ0lnSmlZZ0lVNTFiV0psY2k1cGMwbHVkR1ZuWlhJb2RHaHBibWNwSUNZbUlIUm9hWE11YUdGelNXMXdiR1Z0Wlc1MFlYUnBiMjRvUm14dllYUXBLWHRjYmlBZ0lDQWdJQ0FnSUNCbWRXNGdQU0IwYUdsekxuSmxaMmx6ZEhKNUxtZGxkQ2hHYkc5aGRDbGJablZ1VG1GdFpWMDdYRzRnSUNBZ0lDQWdJSDFsYkhObElHbG1LSFJvYVhNdWFHRnpTVzF3YkdWdFpXNTBZWFJwYjI0b2RHaHBibWNwS1h0Y2JpQWdJQ0FnSUNBZ0lDQm1kVzRnUFNCMGFHbHpMbkpsWjJsemRISjVMbWRsZENoMGFHbHVaeTVqYjI1emRISjFZM1J2Y2lsYlpuVnVUbUZ0WlYwN1hHNGdJQ0FnSUNBZ0lIMWxiSE5sSUdsbUtIUm9hWE11Wm1Gc2JHSmhZMnNwZTF4dUlDQWdJQ0FnSUNBZ0lHWjFiaUE5SUhSb2FYTXVabUZzYkdKaFkydGJablZ1VG1GdFpWMDdYRzRnSUNBZ0lDQWdJSDFjYmx4dUlDQWdJQ0FnSUNCcFppaG1kVzRnSVQwZ2JuVnNiQ2w3WEc0Z0lDQWdJQ0FnSUNBZ2JHVjBJSEpsZEhaaGJDQTlJR1oxYmk1aGNIQnNlU2gwYUdsekxDQmhjbWR6S1R0Y2JpQWdJQ0FnSUNBZ0lDQnlaWFIxY200Z2NtVjBkbUZzTzF4dUlDQWdJQ0FnSUNCOVhHNWNiaUFnSUNBZ0lDQWdkR2h5YjNjZ2JtVjNJRVZ5Y205eUtGd2lUbThnYVcxd2JHVnRaVzUwWVhScGIyNGdabTkxYm1RZ1ptOXlJRndpSUNzZ2RHaHBibWNwTzF4dUlDQWdJQ0FnZlR0Y2JpQWdJQ0I5WEc0Z0lIMWNibHh1SUNCcGJYQnNaVzFsYm5SaGRHbHZiaWgwZVhCbExDQnBiWEJzWlcxbGJuUmhkR2x2YmlsN1hHNGdJQ0FnYVdZb2RIbHdaU0E5UFQwZ2JuVnNiQ2w3WEc0Z0lDQWdJQ0IwYUdsekxtWmhiR3hpWVdOcklEMGdhVzF3YkdWdFpXNTBZWFJwYjI0N1hHNGdJQ0FnZldWc2MyVjdYRzRnSUNBZ0lDQjBhR2x6TG5KbFoybHpkSEo1TG5ObGRDaDBlWEJsTENCcGJYQnNaVzFsYm5SaGRHbHZiaWs3WEc0Z0lDQWdmVnh1SUNCOVhHNWNiaUFnYUdGelNXMXdiR1Z0Wlc1MFlYUnBiMjRvZEdocGJtY3BJSHRjYmlBZ0lDQnBaaUFvZEdocGJtY2dQVDA5SUVsdWRHVm5aWElnZkh3Z2RHaHBibWNnUFQwOUlFWnNiMkYwS1h0Y2JpQWdJQ0FnSUhKbGRIVnliaUIwYUdsekxuSmxaMmx6ZEhKNUxtaGhjeWgwYUdsdVp5azdYRzRnSUNBZ2ZWeHVYRzRnSUNBZ2NtVjBkWEp1SUhSb2FYTXVjbVZuYVhOMGNua3VhR0Z6S0hSb2FXNW5MbU52Ym5OMGNuVmpkRzl5S1R0Y2JpQWdmVnh1ZlZ4dVhHNWNibVY0Y0c5eWRDQmtaV1poZFd4MElGQnliM1J2WTI5c08xeHVJbDBzSW5OdmRYSmpaVkp2YjNRaU9pSXZjMjkxY21ObEx5SjlcbiIsImltcG9ydCB7IFR1cGxlIH0gZnJvbSAnLi9wcmltaXRpdmVzJztcbmltcG9ydCBCaXRTdHJpbmcgZnJvbSAnLi9iaXRfc3RyaW5nJztcbmltcG9ydCBQYXR0ZXJucyBmcm9tICcuL3BhdHRlcm5zJztcbmltcG9ydCBQcm90b2NvbCBmcm9tICcuL3Byb3RvY29sJztcblxuZnVuY3Rpb24gY2FsbF9wcm9wZXJ0eShpdGVtLCBwcm9wZXJ0eSkge1xuICBsZXQgcHJvcCA9IG51bGw7XG5cbiAgaWYgKHR5cGVvZiBpdGVtID09PSBcIm51bWJlclwiIHx8IHR5cGVvZiBpdGVtID09PSBcInN5bWJvbFwiIHx8IHR5cGVvZiBpdGVtID09PSBcImJvb2xlYW5cIiB8fCB0eXBlb2YgaXRlbSA9PT0gXCJzdHJpbmdcIikge1xuICAgIGlmIChpdGVtW3Byb3BlcnR5XSAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICBwcm9wID0gcHJvcGVydHk7XG4gICAgfSBlbHNlIGlmIChpdGVtW1N5bWJvbC5mb3IocHJvcGVydHkpXSAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICBwcm9wID0gU3ltYm9sLmZvcihwcm9wZXJ0eSk7XG4gICAgfVxuICB9IGVsc2Uge1xuICAgIGlmIChwcm9wZXJ0eSBpbiBpdGVtKSB7XG4gICAgICBwcm9wID0gcHJvcGVydHk7XG4gICAgfSBlbHNlIGlmIChTeW1ib2wuZm9yKHByb3BlcnR5KSBpbiBpdGVtKSB7XG4gICAgICBwcm9wID0gU3ltYm9sLmZvcihwcm9wZXJ0eSk7XG4gICAgfVxuICB9XG5cbiAgaWYgKHByb3AgPT09IG51bGwpIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoYFByb3BlcnR5ICR7IHByb3BlcnR5IH0gbm90IGZvdW5kIGluICR7IGl0ZW0gfWApO1xuICB9XG5cbiAgaWYgKGl0ZW1bcHJvcF0gaW5zdGFuY2VvZiBGdW5jdGlvbikge1xuICAgIHJldHVybiBpdGVtW3Byb3BdKCk7XG4gIH0gZWxzZSB7XG4gICAgcmV0dXJuIGl0ZW1bcHJvcF07XG4gIH1cbn1cblxuZnVuY3Rpb24gYXBwbHkoLi4uYXJncykge1xuICBpZiAoYXJncy5sZW5ndGggPT09IDIpIHtcbiAgICBhcmdzWzBdLmFwcGx5KG51bGwsIGFyZ3Muc2xpY2UoMSkpO1xuICB9IGVsc2Uge1xuICAgIGFyZ3NbMF1bYXJnc1sxXV0uYXBwbHkobnVsbCwgYXJncy5zbGljZSgyKSk7XG4gIH1cbn1cblxuZnVuY3Rpb24gY29udGFpbnMobGVmdCwgcmlnaHQpIHtcbiAgZm9yIChsZXQgeCBvZiByaWdodCkge1xuICAgIGlmIChQYXR0ZXJucy5tYXRjaF9ub190aHJvdyhsZWZ0LCB4KSAhPSBudWxsKSB7XG4gICAgICByZXR1cm4gdHJ1ZTtcbiAgICB9XG4gIH1cblxuICByZXR1cm4gZmFsc2U7XG59XG5cbmZ1bmN0aW9uIGdldF9nbG9iYWwoKSB7XG4gIGlmICh0eXBlb2Ygc2VsZiAhPT0gXCJ1bmRlZmluZWRcIikge1xuICAgIHJldHVybiBzZWxmO1xuICB9IGVsc2UgaWYgKHR5cGVvZiB3aW5kb3cgIT09IFwidW5kZWZpbmVkXCIpIHtcbiAgICByZXR1cm4gd2luZG93O1xuICB9IGVsc2UgaWYgKHR5cGVvZiBnbG9iYWwgIT09IFwidW5kZWZpbmVkXCIpIHtcbiAgICByZXR1cm4gZ2xvYmFsO1xuICB9XG5cbiAgdGhyb3cgbmV3IEVycm9yKFwiTm8gZ2xvYmFsIHN0YXRlIGZvdW5kXCIpO1xufVxuXG5mdW5jdGlvbiBkZWZzdHJ1Y3QoZGVmYXVsdHMpIHtcbiAgcmV0dXJuIGNsYXNzIHtcbiAgICBjb25zdHJ1Y3Rvcih1cGRhdGUgPSB7fSkge1xuICAgICAgbGV0IHRoZV92YWx1ZXMgPSBPYmplY3QuYXNzaWduKGRlZmF1bHRzLCB1cGRhdGUpO1xuICAgICAgT2JqZWN0LmFzc2lnbih0aGlzLCB0aGVfdmFsdWVzKTtcbiAgICB9XG5cbiAgICBzdGF0aWMgY3JlYXRlKHVwZGF0ZXMgPSB7fSkge1xuICAgICAgbGV0IHggPSBuZXcgdGhpcyh1cGRhdGVzKTtcbiAgICAgIHJldHVybiBPYmplY3QuZnJlZXplKHgpO1xuICAgIH1cbiAgfTtcbn1cblxuZnVuY3Rpb24gZGVmZXhjZXB0aW9uKGRlZmF1bHRzKSB7XG4gIHJldHVybiBjbGFzcyBleHRlbmRzIEVycm9yIHtcbiAgICBjb25zdHJ1Y3Rvcih1cGRhdGUgPSB7fSkge1xuICAgICAgbGV0IG1lc3NhZ2UgPSB1cGRhdGUubWVzc2FnZSB8fCBcIlwiO1xuICAgICAgc3VwZXIobWVzc2FnZSk7XG5cbiAgICAgIGxldCB0aGVfdmFsdWVzID0gT2JqZWN0LmFzc2lnbihkZWZhdWx0cywgdXBkYXRlKTtcbiAgICAgIE9iamVjdC5hc3NpZ24odGhpcywgdGhlX3ZhbHVlcyk7XG5cbiAgICAgIHRoaXMubmFtZSA9IHRoaXMuY29uc3RydWN0b3IubmFtZTtcbiAgICAgIHRoaXMubWVzc2FnZSA9IG1lc3NhZ2U7XG4gICAgICB0aGlzW1NwZWNpYWxGb3Jtcy5hdG9tKFwiX19leGNlcHRpb25fX1wiKV0gPSB0cnVlO1xuICAgICAgRXJyb3IuY2FwdHVyZVN0YWNrVHJhY2UodGhpcywgdGhpcy5jb25zdHJ1Y3Rvci5uYW1lKTtcbiAgICB9XG5cbiAgICBzdGF0aWMgY3JlYXRlKHVwZGF0ZXMgPSB7fSkge1xuICAgICAgbGV0IHggPSBuZXcgdGhpcyh1cGRhdGVzKTtcbiAgICAgIHJldHVybiBPYmplY3QuZnJlZXplKHgpO1xuICAgIH1cbiAgfTtcbn1cblxuZnVuY3Rpb24gZGVmcHJvdG9jb2woc3BlYykge1xuICByZXR1cm4gbmV3IFByb3RvY29sKHNwZWMpO1xufVxuXG5mdW5jdGlvbiBkZWZpbXBsKHByb3RvY29sLCB0eXBlLCBpbXBsKSB7XG4gIHByb3RvY29sLmltcGxlbWVudGF0aW9uKHR5cGUsIGltcGwpO1xufVxuXG5mdW5jdGlvbiBnZXRfb2JqZWN0X2tleXMob2JqKSB7XG4gIHJldHVybiBPYmplY3Qua2V5cyhvYmopLmNvbmNhdChPYmplY3QuZ2V0T3duUHJvcGVydHlTeW1ib2xzKG9iaikpO1xufVxuXG5mdW5jdGlvbiBpc192YWxpZF9jaGFyYWN0ZXIoY29kZXBvaW50KSB7XG4gIHRyeSB7XG4gICAgcmV0dXJuIFN0cmluZy5mcm9tQ29kZVBvaW50KGNvZGVwb2ludCkgIT0gbnVsbDtcbiAgfSBjYXRjaCAoZSkge1xuICAgIHJldHVybiBmYWxzZTtcbiAgfVxufVxuXG4vL2h0dHBzOi8vZGV2ZWxvcGVyLm1vemlsbGEub3JnL2VuLVVTL2RvY3MvV2ViL0FQSS9XaW5kb3dCYXNlNjQvQmFzZTY0X2VuY29kaW5nX2FuZF9kZWNvZGluZyNTb2x1dGlvbl8yXyVFMiU4MCU5M19yZXdyaXRlX3RoZV9ET01zX2F0b2IoKV9hbmRfYnRvYSgpX3VzaW5nX0phdmFTY3JpcHQnc19UeXBlZEFycmF5c19hbmRfVVRGLThcbmZ1bmN0aW9uIGI2NEVuY29kZVVuaWNvZGUoc3RyKSB7XG4gIHJldHVybiBidG9hKGVuY29kZVVSSUNvbXBvbmVudChzdHIpLnJlcGxhY2UoLyUoWzAtOUEtRl17Mn0pL2csIGZ1bmN0aW9uIChtYXRjaCwgcDEpIHtcbiAgICByZXR1cm4gU3RyaW5nLmZyb21DaGFyQ29kZSgnMHgnICsgcDEpO1xuICB9KSk7XG59XG5cbmZ1bmN0aW9uIGRlbGV0ZV9wcm9wZXJ0eV9mcm9tX21hcChtYXAsIHByb3BlcnR5KSB7XG4gIGxldCBuZXdfbWFwID0gT2JqZWN0LmFzc2lnbihPYmplY3QuY3JlYXRlKG1hcC5jb25zdHJ1Y3Rvci5wcm90b3R5cGUpLCBtYXApO1xuICBkZWxldGUgbmV3X21hcFtwcm9wZXJ0eV07XG5cbiAgcmV0dXJuIE9iamVjdC5mcmVlemUobmV3X21hcCk7XG59XG5cbmZ1bmN0aW9uIGNsYXNzX3RvX29iaihtYXApIHtcbiAgbGV0IG5ld19tYXAgPSBPYmplY3QuYXNzaWduKHt9LCBtYXApO1xuICByZXR1cm4gT2JqZWN0LmZyZWV6ZShuZXdfbWFwKTtcbn1cblxuZnVuY3Rpb24gYWRkX3Byb3BlcnR5X3RvX21hcChtYXAsIHByb3BlcnR5LCB2YWx1ZSkge1xuICBsZXQgbmV3X21hcCA9IE9iamVjdC5hc3NpZ24oe30sIG1hcCk7XG4gIG5ld19tYXBbcHJvcGVydHldID0gdmFsdWU7XG4gIHJldHVybiBPYmplY3QuZnJlZXplKG5ld19tYXApO1xufVxuXG5mdW5jdGlvbiB1cGRhdGVfbWFwKG1hcCwgcHJvcGVydHksIHZhbHVlKSB7XG4gIGlmIChwcm9wZXJ0eSBpbiBnZXRfb2JqZWN0X2tleXMobWFwKSkge1xuICAgIHJldHVybiBhZGRfcHJvcGVydHlfdG9fbWFwKG1hcCwgcHJvcGVydHksIHZhbHVlKTtcbiAgfVxuXG4gIHRocm93IFwibWFwIGRvZXMgbm90IGhhdmUga2V5XCI7XG59XG5cbmZ1bmN0aW9uIGJub3QoZXhwcikge1xuICByZXR1cm4gfmV4cHI7XG59XG5cbmZ1bmN0aW9uIGJhbmQobGVmdCwgcmlnaHQpIHtcbiAgcmV0dXJuIGxlZnQgJiByaWdodDtcbn1cblxuZnVuY3Rpb24gYm9yKGxlZnQsIHJpZ2h0KSB7XG4gIHJldHVybiBsZWZ0IHwgcmlnaHQ7XG59XG5cbmZ1bmN0aW9uIGJzbChsZWZ0LCByaWdodCkge1xuICByZXR1cm4gbGVmdCA8PCByaWdodDtcbn1cblxuZnVuY3Rpb24gYnNyKGxlZnQsIHJpZ2h0KSB7XG4gIHJldHVybiBsZWZ0ID4+IHJpZ2h0O1xufVxuXG5mdW5jdGlvbiBieG9yKGxlZnQsIHJpZ2h0KSB7XG4gIHJldHVybiBsZWZ0IF4gcmlnaHQ7XG59XG5cbmZ1bmN0aW9uIHppcChsaXN0X29mX2xpc3RzKSB7XG4gIGlmIChsaXN0X29mX2xpc3RzLmxlbmd0aCA9PT0gMCkge1xuICAgIHJldHVybiBPYmplY3QuZnJlZXplKFtdKTtcbiAgfVxuXG4gIGxldCBuZXdfdmFsdWUgPSBbXTtcbiAgbGV0IHNtYWxsZXN0X2xlbmd0aCA9IGxpc3Rfb2ZfbGlzdHNbMF07XG5cbiAgZm9yIChsZXQgeCBvZiBsaXN0X29mX2xpc3RzKSB7XG4gICAgaWYgKHgubGVuZ3RoIDwgc21hbGxlc3RfbGVuZ3RoKSB7XG4gICAgICBzbWFsbGVzdF9sZW5ndGggPSB4Lmxlbmd0aDtcbiAgICB9XG4gIH1cblxuICBmb3IgKGxldCBpID0gMDsgaSA8IHNtYWxsZXN0X2xlbmd0aDsgaSsrKSB7XG4gICAgbGV0IGN1cnJlbnRfdmFsdWUgPSBbXTtcbiAgICBmb3IgKGxldCBqID0gMDsgaiA8IGxpc3Rfb2ZfbGlzdHMubGVuZ3RoOyBqKyspIHtcbiAgICAgIGN1cnJlbnRfdmFsdWUucHVzaChsaXN0X29mX2xpc3RzW2pdW2ldKTtcbiAgICB9XG5cbiAgICBuZXdfdmFsdWUucHVzaChuZXcgVHVwbGUoLi4uY3VycmVudF92YWx1ZSkpO1xuICB9XG5cbiAgcmV0dXJuIE9iamVjdC5mcmVlemUobmV3X3ZhbHVlKTtcbn1cblxuZnVuY3Rpb24gY2FuX2RlY29kZTY0KGRhdGEpIHtcbiAgdHJ5IHtcbiAgICBhdG9iKGRhdGEpO1xuICAgIHJldHVybiB0cnVlO1xuICB9IGNhdGNoIChlKSB7XG4gICAgcmV0dXJuIGZhbHNlO1xuICB9XG59XG5cbmZ1bmN0aW9uIHJlbW92ZV9mcm9tX2xpc3QobGlzdCwgZWxlbWVudCkge1xuICBsZXQgZm91bmQgPSBmYWxzZTtcblxuICByZXR1cm4gbGlzdC5maWx0ZXIoZWxlbSA9PiB7XG4gICAgaWYgKCFmb3VuZCAmJiBlbGVtID09PSBlbGVtZW50KSB7XG4gICAgICBmb3VuZCA9IHRydWU7XG4gICAgICByZXR1cm4gZmFsc2U7XG4gICAgfVxuXG4gICAgcmV0dXJuIHRydWU7XG4gIH0pO1xufVxuXG5mdW5jdGlvbiBmb2xkbChmdW4sIGFjYywgbGlzdCkge1xuICBsZXQgYWNjMSA9IGFjYztcblxuICBmb3IgKGNvbnN0IGVsIG9mIGxpc3QpIHtcbiAgICBhY2MxID0gZnVuKGVsLCBhY2MxKTtcbiAgfVxuXG4gIHJldHVybiBhY2MxO1xufVxuXG5mdW5jdGlvbiBmb2xkcihmdW4sIGFjYywgbGlzdCkge1xuICBsZXQgYWNjMSA9IGFjYztcblxuICBmb3IgKGxldCBpID0gbGlzdC5sZW5ndGggLSAxOyBpID49IDA7IGktLSkge1xuICAgIGFjYzEgPSBmdW4obGlzdFtpXSwgYWNjMSk7XG4gIH1cblxuICByZXR1cm4gYWNjMTtcbn1cblxuZnVuY3Rpb24ga2V5ZmluZChrZXksIG4sIHR1cGxlbGlzdCkge1xuXG4gIGZvciAobGV0IGkgPSB0dXBsZWxpc3QubGVuZ3RoIC0gMTsgaSA+PSAwOyBpLS0pIHtcbiAgICBpZiAodHVwbGVsaXN0W2ldLmdldChuKSA9PT0ga2V5KSB7XG4gICAgICByZXR1cm4gdHVwbGVsaXN0W2ldO1xuICAgIH1cbiAgfVxuXG4gIHJldHVybiBmYWxzZTtcbn1cblxuZnVuY3Rpb24ga2V5ZGVsZXRlKGtleSwgbiwgdHVwbGVsaXN0KSB7XG5cbiAgZm9yIChsZXQgaSA9IHR1cGxlbGlzdC5sZW5ndGggLSAxOyBpID49IDA7IGktLSkge1xuICAgIGlmICh0dXBsZWxpc3RbaV0uZ2V0KG4pID09PSBrZXkpIHtcbiAgICAgIHJldHVybiB0dXBsZWxpc3QuY29uY2F0KFtdKS5zcGxpY2UoaSwgMSk7XG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIHR1cGxlbGlzdDtcbn1cblxuZnVuY3Rpb24ga2V5c3RvcmUoa2V5LCBuLCBsaXN0LCBuZXd0dXBsZSkge1xuICBmb3IgKGxldCBpID0gbGlzdC5sZW5ndGggLSAxOyBpID49IDA7IGktLSkge1xuICAgIGlmIChsaXN0W2ldLmdldChuKSA9PT0ga2V5KSB7XG4gICAgICByZXR1cm4gbGlzdC5jb25jYXQoW10pLnNwbGljZShpLCAxLCBuZXd0dXBsZSk7XG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIGxpc3QuY29uY2F0KFtdKS5wdXNoKG5ld3R1cGxlKTtcbn1cblxuZnVuY3Rpb24ga2V5bWVtYmVyKGtleSwgbiwgbGlzdCkge1xuICBmb3IgKGxldCBpID0gbGlzdC5sZW5ndGggLSAxOyBpID49IDA7IGktLSkge1xuICAgIGlmIChsaXN0W2ldLmdldChuKSA9PT0ga2V5KSB7XG4gICAgICByZXR1cm4gdHJ1ZTtcbiAgICB9XG4gIH1cblxuICByZXR1cm4gZmFsc2U7XG59XG5cbmZ1bmN0aW9uIGtleXRha2Uoa2V5LCBuLCBsaXN0KSB7XG4gIGlmICgha2V5bWVtYmVyKGtleSwgbiwgbGlzdCkpIHtcbiAgICByZXR1cm4gZmFsc2U7XG4gIH1cblxuICBsZXQgdHVwbGUgPSBrZXlmaW5kKGtleSwgbiwgbGlzdCk7XG5cbiAgcmV0dXJuIG5ldyBUdXBsZSh0dXBsZS5nZXQobiksIHR1cGxlLCBrZXlkZWxldGUoa2V5LCBuLCBsaXN0KSk7XG59XG5cbmZ1bmN0aW9uIGtleXJlcGxhY2Uoa2V5LCBuLCBsaXN0LCBuZXd0dXBsZSkge1xuXG4gIGZvciAobGV0IGkgPSB0dXBsZWxpc3QubGVuZ3RoIC0gMTsgaSA+PSAwOyBpLS0pIHtcbiAgICBpZiAodHVwbGVsaXN0W2ldLmdldChuKSA9PT0ga2V5KSB7XG4gICAgICByZXR1cm4gdHVwbGVsaXN0LmNvbmNhdChbXSkuc3BsaWNlKGksIDEsIG5ld3R1cGxlKTtcbiAgICB9XG4gIH1cblxuICByZXR1cm4gdHVwbGVsaXN0O1xufVxuXG5mdW5jdGlvbiByZXZlcnNlKGxpc3QpIHtcbiAgcmV0dXJuIGxpc3QuY29uY2F0KFtdKS5yZXZlcnNlKCk7XG59XG5cbmZ1bmN0aW9uIG1hcHNfZmluZChrZXksIG1hcCkge1xuICBpZiAoa2V5IGluIGdldF9vYmplY3Rfa2V5cyhtYXApKSB7XG4gICAgcmV0dXJuIG5ldyBUdXBsZShTeW1ib2wuZm9yKFwib2tcIiksIG1hcFtrZXldKTtcbiAgfSBlbHNlIHtcbiAgICByZXR1cm4gU3ltYm9sLmZvcihcImVycm9yXCIpO1xuICB9XG59XG5cbmZ1bmN0aW9uIGZsYXR0ZW4obGlzdCwgdGFpbCA9IFtdKSB7XG4gIGxldCBuZXdfbGlzdCA9IFtdO1xuXG4gIGZvciAobGV0IGUgb2YgbGlzdCkge1xuICAgIGlmIChpc0FycmF5KGUpKSB7XG4gICAgICBuZXdfbGlzdCA9IG5ld19saXN0LmNvbmNhdChmbGF0dGVuKGUpKTtcbiAgICB9IGVsc2Uge1xuICAgICAgbmV3X2xpc3QucHVzaChlKTtcbiAgICB9XG4gIH1cblxuICByZXR1cm4gT2JqZWN0LmZyZWV6ZShuZXdfbGlzdC5jb25jYXQodGFpbCkpO1xufVxuXG5mdW5jdGlvbiBkdXBsaWNhdGUobiwgZWxlbSkge1xuICBsZXQgbGlzdCA9IFtdO1xuXG4gIGZvciAobGV0IGkgPSAwOyBpIDwgbjsgaSsrKSB7XG4gICAgbGlzdC5wdXNoKGVsZW0pO1xuICB9XG5cbiAgcmV0dXJuIE9iamVjdC5mcmVlemUobGlzdCk7XG59XG5cbmZ1bmN0aW9uIG1hcGZvbGRsKGZ1biwgYWNjLCBsaXN0KSB7XG4gIGxldCBuZXdsaXN0ID0gW107XG5cbiAgZm9yIChsZXQgeCBvZiBsaXN0KSB7XG4gICAgbGV0IHR1cCA9IGZ1bih4LCBhY2MpO1xuICAgIG5ld2xpc3QucHVzaCh0dXAuZ2V0KDApKTtcbiAgICBhY2MgPSB0dXAuZ2V0KDEpO1xuICB9XG5cbiAgcmV0dXJuIG5ldyBUdXBsZShPYmplY3QuZnJlZXplKG5ld2xpc3QpLCBhY2MpO1xufVxuXG5mdW5jdGlvbiBmaWx0ZXJtYXAoZnVuLCBsaXN0KSB7XG4gIGxldCBuZXdsaXN0ID0gW107XG5cbiAgZm9yICh4IG9mIGxpc3QpIHtcbiAgICBsZXQgcmVzdWx0ID0gZnVuKHgpO1xuXG4gICAgaWYgKHJlc3VsdCA9PT0gdHJ1ZSkge1xuICAgICAgbmV3bGlzdC5wdXNoKHgpO1xuICAgIH0gZWxzZSBpZiAocmVzdWx0IGluc3RhbmNlb2YgVHVwbGUpIHtcbiAgICAgIG5ld2xpc3QucHVzaChyZXN1bHQuZ2V0KDEpKTtcbiAgICB9XG4gIH1cblxuICByZXR1cm4gT2JqZWN0LmZyZWV6ZShuZXdsaXN0KTtcbn1cblxuZnVuY3Rpb24gbWFwc19mb2xkKGZ1biwgYWNjLCBtYXApIHtcbiAgbGV0IGFjYzEgPSBhY2M7XG5cbiAgZm9yIChsZXQgayBvZiBnZXRfb2JqZWN0X2tleXMobWFwKSkge1xuICAgIGFjYzEgPSBmdW4oaywgbWFwW2tdLCBhY2MxKTtcbiAgfVxuXG4gIHJldHVybiBhY2MxO1xufVxuXG5mdW5jdGlvbiBtYXBzX2Zyb21fbGlzdChsaXN0KSB7XG4gIGxldCBtID0ge307XG5cbiAgZm9yICh4IG9mIGxpc3QpIHtcbiAgICBtW3guZ2V0KDApXSA9IHguZ2V0KDEpO1xuICB9XG5cbiAgcmV0dXJuIE9iamVjdC5mcmVlemUobSk7XG59XG5cbmV4cG9ydCBkZWZhdWx0IHtcbiAgY2FsbF9wcm9wZXJ0eSxcbiAgYXBwbHksXG4gIGNvbnRhaW5zLFxuICBnZXRfZ2xvYmFsLFxuICBkZWZzdHJ1Y3QsXG4gIGRlZmV4Y2VwdGlvbixcbiAgZGVmcHJvdG9jb2wsXG4gIGRlZmltcGwsXG4gIGdldF9vYmplY3Rfa2V5cyxcbiAgaXNfdmFsaWRfY2hhcmFjdGVyLFxuICBiNjRFbmNvZGVVbmljb2RlLFxuICBkZWxldGVfcHJvcGVydHlfZnJvbV9tYXAsXG4gIGFkZF9wcm9wZXJ0eV90b19tYXAsXG4gIGNsYXNzX3RvX29iaixcbiAgY2FuX2RlY29kZTY0LFxuICBibm90LFxuICBiYW5kLFxuICBib3IsXG4gIGJzbCxcbiAgYnNyLFxuICBieG9yLFxuICB6aXAsXG4gIGZvbGRsLFxuICBmb2xkcixcbiAgcmVtb3ZlX2Zyb21fbGlzdCxcbiAga2V5ZGVsZXRlLFxuICBrZXlzdG9yZSxcbiAga2V5ZmluZCxcbiAga2V5dGFrZSxcbiAga2V5cmVwbGFjZSxcbiAgcmV2ZXJzZSxcbiAgdXBkYXRlX21hcCxcbiAgbWFwc19maW5kLFxuICBmbGF0dGVuLFxuICBkdXBsaWNhdGUsXG4gIG1hcGZvbGRsLFxuICBmaWx0ZXJtYXAsXG4gIG1hcHNfZm9sZFxufTtcbi8vIyBzb3VyY2VNYXBwaW5nVVJMPWRhdGE6YXBwbGljYXRpb24vanNvbjtiYXNlNjQsZXlKMlpYSnphVzl1SWpvekxDSnpiM1Z5WTJWeklqcGJJbXhwWWk5amIzSmxMMloxYm1OMGFXOXVjeTVxY3lKZExDSnVZVzFsY3lJNlcxMHNJbTFoY0hCcGJtZHpJam9pUVVGQlFTeFRRVUZUTEV0QlFWUXNVVUZCYzBJc1kwRkJkRUk3UVVGRFFTeFBRVUZQTEZOQlFWQXNUVUZCYzBJc1kwRkJkRUk3UVVGRFFTeFBRVUZQTEZGQlFWQXNUVUZCY1VJc1dVRkJja0k3UVVGRFFTeFBRVUZQTEZGQlFWQXNUVUZCY1VJc1dVRkJja0k3TzBGQlJVRXNVMEZCVXl4aFFVRlVMRU5CUVhWQ0xFbEJRWFpDTEVWQlFUWkNMRkZCUVRkQ0xFVkJRWE5ETzBGQlEzQkRMRTFCUVVrc1QwRkJUeXhKUVVGUUxFTkJSR2RET3p0QlFVZHdReXhOUVVGSExFOUJRVThzU1VGQlVDeExRVUZuUWl4UlFVRm9RaXhKUVVFMFFpeFBRVUZQTEVsQlFWQXNTMEZCWjBJc1VVRkJhRUlzU1VGQk5FSXNUMEZCVHl4SlFVRlFMRXRCUVdkQ0xGTkJRV2hDTEVsQlFUWkNMRTlCUVU4c1NVRkJVQ3hMUVVGblFpeFJRVUZvUWl4RlFVRjVRanRCUVVNdlJ5eFJRVUZITEV0QlFVc3NVVUZCVEN4TlFVRnRRaXhUUVVGdVFpeEZRVUUyUWp0QlFVTTVRaXhoUVVGUExGRkJRVkFzUTBGRU9FSTdTMEZCYUVNc1RVRkZUU3hKUVVGSExFdEJRVXNzVDBGQlR5eEhRVUZRTEVOQlFWY3NVVUZCV0N4RFFVRk1MRTFCUVN0Q0xGTkJRUzlDTEVWQlFYbERPMEZCUTJoRUxHRkJRVThzVDBGQlR5eEhRVUZRTEVOQlFWY3NVVUZCV0N4RFFVRlFMRU5CUkdkRU8wdEJRVFZETzBkQlNGSXNUVUZOVHp0QlFVTk1MRkZCUVVjc1dVRkJXU3hKUVVGYUxFVkJRV2xDTzBGQlEyeENMR0ZCUVU4c1VVRkJVQ3hEUVVSclFqdExRVUZ3UWl4TlFVVk5MRWxCUVVjc1QwRkJUeXhIUVVGUUxFTkJRVmNzVVVGQldDeExRVUYzUWl4SlFVRjRRaXhGUVVFMlFqdEJRVU53UXl4aFFVRlBMRTlCUVU4c1IwRkJVQ3hEUVVGWExGRkJRVmdzUTBGQlVDeERRVVJ2UXp0TFFVRm9RenRIUVZSU096dEJRV05CTEUxQlFVY3NVMEZCVXl4SlFVRlVMRVZCUVdNN1FVRkRaaXhWUVVGTkxFbEJRVWtzUzBGQlNpeERRVUZWTEVOQlFVTXNVMEZCUkN4SFFVRmhMRkZCUVdJc1JVRkJkVUlzWTBGQmRrSXNSMEZCZDBNc1NVRkJlRU1zUlVGQk9FTXNRMEZCZUVRc1EwRkJUaXhEUVVSbE8wZEJRV3BDT3p0QlFVbEJMRTFCUVVjc1MwRkJTeXhKUVVGTUxHRkJRWE5DTEZGQlFYUkNMRVZCUVN0Q08wRkJRMmhETEZkQlFVOHNTMEZCU3l4SlFVRk1MRWRCUVZBc1EwRkVaME03UjBGQmJFTXNUVUZGU3p0QlFVTklMRmRCUVU4c1MwRkJTeXhKUVVGTUxFTkJRVkFzUTBGRVJ6dEhRVVpNTzBOQmNrSkdPenRCUVRSQ1FTeFRRVUZUTEV0QlFWUXNRMEZCWlN4SFFVRkhMRWxCUVVnc1JVRkJVVHRCUVVOeVFpeE5RVUZITEV0QlFVc3NUVUZCVEN4TFFVRm5RaXhEUVVGb1FpeEZRVUZyUWp0QlFVTnVRaXhUUVVGTExFTkJRVXdzUlVGQlVTeExRVUZTTEVOQlFXTXNTVUZCWkN4RlFVRnZRaXhMUVVGTExFdEJRVXdzUTBGQlZ5eERRVUZZTEVOQlFYQkNMRVZCUkcxQ08wZEJRWEpDTEUxQlJVczdRVUZEU0N4VFFVRkxMRU5CUVV3c1JVRkJVU3hMUVVGTExFTkJRVXdzUTBGQlVpeEZRVUZwUWl4TFFVRnFRaXhEUVVGMVFpeEpRVUYyUWl4RlFVRTJRaXhMUVVGTExFdEJRVXdzUTBGQlZ5eERRVUZZTEVOQlFUZENMRVZCUkVjN1IwRkdURHREUVVSR096dEJRVkZCTEZOQlFWTXNVVUZCVkN4RFFVRnJRaXhKUVVGc1FpeEZRVUYzUWl4TFFVRjRRaXhGUVVFNFFqdEJRVU0xUWl4UFFVRkpMRWxCUVVrc1EwRkJTaXhKUVVGVExFdEJRV0lzUlVGQmJVSTdRVUZEYWtJc1VVRkJSeXhUUVVGVExHTkJRVlFzUTBGQmQwSXNTVUZCZUVJc1JVRkJPRUlzUTBGQk9VSXNTMEZCYjBNc1NVRkJjRU1zUlVGQmVVTTdRVUZETVVNc1lVRkJUeXhKUVVGUUxFTkJSREJETzB0QlFUVkRPMGRCUkVZN08wRkJUVUVzVTBGQlR5eExRVUZRTEVOQlVEUkNPME5CUVRsQ096dEJRVlZCTEZOQlFWTXNWVUZCVkN4SFFVRnhRanRCUVVOdVFpeE5RVUZITEU5QlFVOHNTVUZCVUN4TFFVRnBRaXhYUVVGcVFpeEZRVUUyUWp0QlFVTTVRaXhYUVVGUExFbEJRVkFzUTBGRU9FSTdSMEZCYUVNc1RVRkZUU3hKUVVGSExFOUJRVThzVFVGQlVDeExRVUZ0UWl4WFFVRnVRaXhGUVVFclFqdEJRVU4wUXl4WFFVRlBMRTFCUVZBc1EwRkVjME03UjBGQmJFTXNUVUZGUVN4SlFVRkhMRTlCUVU4c1RVRkJVQ3hMUVVGdFFpeFhRVUZ1UWl4RlFVRXJRanRCUVVOMFF5eFhRVUZQTEUxQlFWQXNRMEZFYzBNN1IwRkJiRU03TzBGQlNVNHNVVUZCVFN4SlFVRkpMRXRCUVVvc1EwRkJWU3gxUWtGQlZpeERRVUZPTEVOQlZHMUNPME5CUVhKQ096dEJRVmxCTEZOQlFWTXNVMEZCVkN4RFFVRnRRaXhSUVVGdVFpeEZRVUUwUWp0QlFVTXhRaXhUUVVGUExFMUJRVTA3UVVGRFdDeG5Ra0ZCV1N4VFFVRlRMRVZCUVZRc1JVRkJXVHRCUVVOMFFpeFZRVUZKTEdGQlFXRXNUMEZCVHl4TlFVRlFMRU5CUVdNc1VVRkJaQ3hGUVVGM1FpeE5RVUY0UWl4RFFVRmlMRU5CUkd0Q08wRkJSWFJDTEdGQlFVOHNUVUZCVUN4RFFVRmpMRWxCUVdRc1JVRkJiMElzVlVGQmNFSXNSVUZHYzBJN1MwRkJlRUk3TzBGQlMwRXNWMEZCVHl4TlFVRlFMRU5CUVdNc1ZVRkJWU3hGUVVGV0xFVkJRV0U3UVVGRGVrSXNWVUZCU1N4SlFVRkpMRWxCUVVrc1NVRkJTaXhEUVVGVExFOUJRVlFzUTBGQlNpeERRVVJ4UWp0QlFVVjZRaXhoUVVGUExFOUJRVThzVFVGQlVDeERRVUZqTEVOQlFXUXNRMEZCVUN4RFFVWjVRanRMUVVFelFqdEhRVTVMTEVOQlJHMUNPME5CUVRWQ096dEJRV1ZCTEZOQlFWTXNXVUZCVkN4RFFVRnpRaXhSUVVGMFFpeEZRVUVyUWp0QlFVTTNRaXhUUVVGUExHTkJRV01zUzBGQlpDeERRVUZ2UWp0QlFVTjZRaXhuUWtGQldTeFRRVUZUTEVWQlFWUXNSVUZCV1R0QlFVTjBRaXhWUVVGSkxGVkJRVlVzVDBGQlR5eFBRVUZRTEVsQlFXdENMRVZCUVd4Q0xFTkJSRkU3UVVGRmRFSXNXVUZCVFN4UFFVRk9MRVZCUm5OQ096dEJRVWwwUWl4VlFVRkpMR0ZCUVdFc1QwRkJUeXhOUVVGUUxFTkJRV01zVVVGQlpDeEZRVUYzUWl4TlFVRjRRaXhEUVVGaUxFTkJTbXRDTzBGQlMzUkNMR0ZCUVU4c1RVRkJVQ3hEUVVGakxFbEJRV1FzUlVGQmIwSXNWVUZCY0VJc1JVRk1jMEk3TzBGQlQzUkNMRmRCUVVzc1NVRkJUQ3hIUVVGWkxFdEJRVXNzVjBGQlRDeERRVUZwUWl4SlFVRnFRaXhEUVZCVk8wRkJVWFJDTEZkQlFVc3NUMEZCVEN4SFFVRmxMRTlCUVdZc1EwRlNjMEk3UVVGVGRFSXNWMEZCU3l4aFFVRmhMRWxCUVdJc1EwRkJhMElzWlVGQmJFSXNRMEZCVEN4SlFVRXlReXhKUVVFelF5eERRVlJ6UWp0QlFWVjBRaXhaUVVGTkxHbENRVUZPTEVOQlFYZENMRWxCUVhoQ0xFVkJRVGhDTEV0QlFVc3NWMEZCVEN4RFFVRnBRaXhKUVVGcVFpeERRVUU1UWl4RFFWWnpRanRMUVVGNFFqczdRVUZoUVN4WFFVRlBMRTFCUVZBc1EwRkJZeXhWUVVGVkxFVkJRVllzUlVGQllUdEJRVU42UWl4VlFVRkpMRWxCUVVrc1NVRkJTU3hKUVVGS0xFTkJRVk1zVDBGQlZDeERRVUZLTEVOQlJIRkNPMEZCUlhwQ0xHRkJRVThzVDBGQlR5eE5RVUZRTEVOQlFXTXNRMEZCWkN4RFFVRlFMRU5CUm5sQ08wdEJRVE5DTzBkQlpFc3NRMEZFYzBJN1EwRkJMMEk3TzBGQmMwSkJMRk5CUVZNc1YwRkJWQ3hEUVVGeFFpeEpRVUZ5UWl4RlFVRXdRanRCUVVONFFpeFRRVUZQTEVsQlFVa3NVVUZCU2l4RFFVRmhMRWxCUVdJc1EwRkJVQ3hEUVVSM1FqdERRVUV4UWpzN1FVRkpRU3hUUVVGVExFOUJRVlFzUTBGQmFVSXNVVUZCYWtJc1JVRkJNa0lzU1VGQk0wSXNSVUZCYVVNc1NVRkJha01zUlVGQmMwTTdRVUZEY0VNc1YwRkJVeXhqUVVGVUxFTkJRWGRDTEVsQlFYaENMRVZCUVRoQ0xFbEJRVGxDTEVWQlJHOURPME5CUVhSRE96dEJRVWxCTEZOQlFWTXNaVUZCVkN4RFFVRjVRaXhIUVVGNlFpeEZRVUUyUWp0QlFVTjZRaXhUUVVGUExFOUJRVThzU1VGQlVDeERRVUZaTEVkQlFWb3NSVUZCYVVJc1RVRkJha0lzUTBGQmQwSXNUMEZCVHl4eFFrRkJVQ3hEUVVFMlFpeEhRVUUzUWl4RFFVRjRRaXhEUVVGUUxFTkJSSGxDTzBOQlFUZENPenRCUVVsQkxGTkJRVk1zYTBKQlFWUXNRMEZCTkVJc1UwRkJOVUlzUlVGQmMwTTdRVUZEY0VNc1RVRkJSenRCUVVORUxGZEJRVThzVDBGQlR5eGhRVUZRTEVOQlFYRkNMRk5CUVhKQ0xFdEJRVzFETEVsQlFXNURMRU5CUkU0N1IwRkJTQ3hEUVVWRExFOUJRVTBzUTBGQlRpeEZRVUZSTzBGQlExQXNWMEZCVHl4TFFVRlFMRU5CUkU4N1IwRkJVanREUVVoSU96czdRVUZUUVN4VFFVRlRMR2RDUVVGVUxFTkJRVEJDTEVkQlFURkNMRVZCUVN0Q08wRkJRek5DTEZOQlFVOHNTMEZCU3l4dFFrRkJiVUlzUjBGQmJrSXNSVUZCZDBJc1QwRkJlRUlzUTBGQlowTXNhVUpCUVdoRExFVkJRVzFFTEZWQlFWTXNTMEZCVkN4RlFVRm5RaXhGUVVGb1FpeEZRVUZ2UWp0QlFVTXZSU3hYUVVGUExFOUJRVThzV1VGQlVDeERRVUZ2UWl4UFFVRlBMRVZCUVZBc1EwRkJNMElzUTBGRUswVTdSMEZCY0VJc1EwRkJlRVFzUTBGQlVDeERRVVF5UWp0RFFVRXZRanM3UVVGTlFTeFRRVUZUTEhkQ1FVRlVMRU5CUVd0RExFZEJRV3hETEVWQlFYVkRMRkZCUVhaRExFVkJRV2RFTzBGQlF6VkRMRTFCUVVrc1ZVRkJWU3hQUVVGUExFMUJRVkFzUTBGQll5eFBRVUZQTEUxQlFWQXNRMEZCWXl4SlFVRkpMRmRCUVVvc1EwRkJaMElzVTBGQmFFSXNRMEZCTlVJc1JVRkJkMFFzUjBGQmVFUXNRMEZCVml4RFFVUjNRenRCUVVVMVF5eFRRVUZQTEZGQlFWRXNVVUZCVWl4RFFVRlFMRU5CUmpSRE96dEJRVWs1UXl4VFFVRlBMRTlCUVU4c1RVRkJVQ3hEUVVGakxFOUJRV1FzUTBGQlVDeERRVW80UXp0RFFVRm9SRHM3UVVGUFFTeFRRVUZUTEZsQlFWUXNRMEZCYzBJc1IwRkJkRUlzUlVGQk1FSTdRVUZEZEVJc1RVRkJTU3hWUVVGVkxFOUJRVThzVFVGQlVDeERRVUZqTEVWQlFXUXNSVUZCYTBJc1IwRkJiRUlzUTBGQlZpeERRVVJyUWp0QlFVVjRRaXhUUVVGUExFOUJRVThzVFVGQlVDeERRVUZqTEU5QlFXUXNRMEZCVUN4RFFVWjNRanREUVVFeFFqczdRVUZMUVN4VFFVRlRMRzFDUVVGVUxFTkJRVFpDTEVkQlFUZENMRVZCUVd0RExGRkJRV3hETEVWQlFUUkRMRXRCUVRWRExFVkJRV3RFTzBGQlEyaEVMRTFCUVVrc1ZVRkJWU3hQUVVGUExFMUJRVkFzUTBGQll5eEZRVUZrTEVWQlFXdENMRWRCUVd4Q0xFTkJRVllzUTBGRU5FTTdRVUZGYUVRc1ZVRkJVU3hSUVVGU0xFbEJRVzlDTEV0QlFYQkNMRU5CUm1kRU8wRkJSMmhFTEZOQlFVOHNUMEZCVHl4TlFVRlFMRU5CUVdNc1QwRkJaQ3hEUVVGUUxFTkJTR2RFTzBOQlFXeEVPenRCUVU5QkxGTkJRVk1zVlVGQlZDeERRVUZ2UWl4SFFVRndRaXhGUVVGNVFpeFJRVUY2UWl4RlFVRnRReXhMUVVGdVF5eEZRVUY1UXp0QlFVTnlReXhOUVVGSExGbEJRVmtzWjBKQlFXZENMRWRCUVdoQ0xFTkJRVm9zUlVGQmFVTTdRVUZEYUVNc1YwRkJUeXh2UWtGQmIwSXNSMEZCY0VJc1JVRkJlVUlzVVVGQmVrSXNSVUZCYlVNc1MwRkJia01zUTBGQlVDeERRVVJuUXp0SFFVRndRenM3UVVGSlFTeFJRVUZOTEhWQ1FVRk9MRU5CVEhGRE8wTkJRWHBET3p0QlFWRkJMRk5CUVZNc1NVRkJWQ3hEUVVGakxFbEJRV1FzUlVGQmJVSTdRVUZEYWtJc1UwRkJUeXhEUVVGRExFbEJRVVFzUTBGRVZUdERRVUZ1UWpzN1FVRkpRU3hUUVVGVExFbEJRVlFzUTBGQll5eEpRVUZrTEVWQlFXOUNMRXRCUVhCQ0xFVkJRVEJDTzBGQlEzaENMRk5CUVU4c1QwRkJUeXhMUVVGUUxFTkJSR2xDTzBOQlFURkNPenRCUVVsQkxGTkJRVk1zUjBGQlZDeERRVUZoTEVsQlFXSXNSVUZCYlVJc1MwRkJia0lzUlVGQmVVSTdRVUZEZGtJc1UwRkJUeXhQUVVGUExFdEJRVkFzUTBGRVowSTdRMEZCZWtJN08wRkJTVUVzVTBGQlV5eEhRVUZVTEVOQlFXRXNTVUZCWWl4RlFVRnRRaXhMUVVGdVFpeEZRVUY1UWp0QlFVTjJRaXhUUVVGUExGRkJRVkVzUzBGQlVpeERRVVJuUWp0RFFVRjZRanM3UVVGSlFTeFRRVUZUTEVkQlFWUXNRMEZCWVN4SlFVRmlMRVZCUVcxQ0xFdEJRVzVDTEVWQlFYbENPMEZCUTNaQ0xGTkJRVThzVVVGQlVTeExRVUZTTEVOQlJHZENPME5CUVhwQ096dEJRVWxCTEZOQlFWTXNTVUZCVkN4RFFVRmpMRWxCUVdRc1JVRkJiMElzUzBGQmNFSXNSVUZCTUVJN1FVRkRlRUlzVTBGQlR5eFBRVUZQTEV0QlFWQXNRMEZFYVVJN1EwRkJNVUk3TzBGQlNVRXNVMEZCVXl4SFFVRlVMRU5CUVdFc1lVRkJZaXhGUVVFeVFqdEJRVU42UWl4TlFVRkhMR05CUVdNc1RVRkJaQ3hMUVVGNVFpeERRVUY2UWl4RlFVRXlRanRCUVVNMVFpeFhRVUZQTEU5QlFVOHNUVUZCVUN4RFFVRmpMRVZCUVdRc1EwRkJVQ3hEUVVRMFFqdEhRVUU1UWpzN1FVRkpRU3hOUVVGSkxGbEJRVmtzUlVGQldpeERRVXh4UWp0QlFVMTZRaXhOUVVGSkxHdENRVUZyUWl4alFVRmpMRU5CUVdRc1EwRkJiRUlzUTBGT2NVSTdPMEZCVVhwQ0xFOUJRVWtzU1VGQlNTeERRVUZLTEVsQlFWTXNZVUZCWWl4RlFVRXlRanRCUVVONlFpeFJRVUZITEVWQlFVVXNUVUZCUml4SFFVRlhMR1ZCUVZnc1JVRkJNa0k3UVVGRE5VSXNkMEpCUVd0Q0xFVkJRVVVzVFVGQlJpeERRVVJWTzB0QlFUbENPMGRCUkVZN08wRkJUVUVzVDBGQlNTeEpRVUZKTEVsQlFVa3NRMEZCU2l4RlFVRlBMRWxCUVVrc1pVRkJTaXhGUVVGeFFpeEhRVUZ3UXl4RlFVRjNRenRCUVVOMFF5eFJRVUZKTEdkQ1FVRm5RaXhGUVVGb1FpeERRVVJyUXp0QlFVVjBReXhUUVVGSkxFbEJRVWtzU1VGQlNTeERRVUZLTEVWQlFVOHNTVUZCU1N4alFVRmpMRTFCUVdRc1JVRkJjMElzUjBGQmVrTXNSVUZCTmtNN1FVRkRNME1zYjBKQlFXTXNTVUZCWkN4RFFVRnRRaXhqUVVGakxFTkJRV1FzUlVGQmFVSXNRMEZCYWtJc1EwRkJia0lzUlVGRU1rTTdTMEZCTjBNN08wRkJTVUVzWTBGQlZTeEpRVUZXTEVOQlFXVXNTVUZCU1N4TFFVRktMRU5CUVZVc1IwRkJSeXhoUVVGSUxFTkJRWHBDTEVWQlRuTkRPMGRCUVhoRE96dEJRVk5CTEZOQlFVOHNUMEZCVHl4TlFVRlFMRU5CUVdNc1UwRkJaQ3hEUVVGUUxFTkJka0o1UWp0RFFVRXpRanM3UVVFd1FrRXNVMEZCVXl4WlFVRlVMRU5CUVhOQ0xFbEJRWFJDTEVWQlFUUkNPMEZCUXpGQ0xFMUJRVWM3UVVGRFJDeFRRVUZMTEVsQlFVd3NSVUZFUXp0QlFVVkVMRmRCUVU4c1NVRkJVQ3hEUVVaRE8wZEJRVWdzUTBGSFF5eFBRVUZOTEVOQlFVNHNSVUZCVVR0QlFVTlFMRmRCUVU4c1MwRkJVQ3hEUVVSUE8wZEJRVkk3UTBGS1NEczdRVUZUUVN4VFFVRlRMR2RDUVVGVUxFTkJRVEJDTEVsQlFURkNMRVZCUVdkRExFOUJRV2hETEVWQlFYZERPMEZCUTNCRExFMUJRVWtzVVVGQlVTeExRVUZTTEVOQlJHZERPenRCUVVkd1F5eFRRVUZQTEV0QlFVc3NUVUZCVEN4RFFVRlpMRkZCUVZVN1FVRkRla0lzVVVGQlJ5eERRVUZETEV0QlFVUXNTVUZCVlN4VFFVRlRMRTlCUVZRc1JVRkJhVUk3UVVGRE1VSXNZMEZCVVN4SlFVRlNMRU5CUkRCQ08wRkJSVEZDTEdGQlFVOHNTMEZCVUN4RFFVWXdRanRMUVVFNVFqczdRVUZMUVN4WFFVRlBMRWxCUVZBc1EwRk9lVUk3UjBGQlZpeERRVUZ1UWl4RFFVaHZRenREUVVGNFF6czdRVUZoUVN4VFFVRlRMRXRCUVZRc1EwRkJaU3hIUVVGbUxFVkJRVzlDTEVkQlFYQkNMRVZCUVhsQ0xFbEJRWHBDTEVWQlFUaENPMEZCUXpGQ0xFMUJRVWtzVDBGQlR5eEhRVUZRTEVOQlJITkNPenRCUVVjeFFpeFBRVUZKTEUxQlFVMHNSVUZCVGl4SlFVRlpMRWxCUVdoQ0xFVkJRWEZDTzBGQlEycENMRmRCUVU4c1NVRkJTU3hGUVVGS0xFVkJRVkVzU1VGQlVpeERRVUZRTEVOQlJHbENPMGRCUVhKQ096dEJRVWxCTEZOQlFVOHNTVUZCVUN4RFFWQXdRanREUVVFNVFqczdRVUZYUVN4VFFVRlRMRXRCUVZRc1EwRkJaU3hIUVVGbUxFVkJRVzlDTEVkQlFYQkNMRVZCUVhsQ0xFbEJRWHBDTEVWQlFUaENPMEZCUXpGQ0xFMUJRVWtzVDBGQlR5eEhRVUZRTEVOQlJITkNPenRCUVVjeFFpeFBRVUZKTEVsQlFVa3NTVUZCU1N4TFFVRkxMRTFCUVV3c1IwRkJZeXhEUVVGa0xFVkJRV2xDTEV0QlFVc3NRMEZCVEN4RlFVRlJMRWRCUVhKRExFVkJRWGxETzBGQlEzSkRMRmRCUVU4c1NVRkJTU3hMUVVGTExFTkJRVXdzUTBGQlNpeEZRVUZoTEVsQlFXSXNRMEZCVUN4RFFVUnhRenRIUVVGNlF6czdRVUZKUVN4VFFVRlBMRWxCUVZBc1EwRlFNRUk3UTBGQk9VSTdPMEZCVlVFc1UwRkJVeXhQUVVGVUxFTkJRV2xDTEVkQlFXcENMRVZCUVhOQ0xFTkJRWFJDTEVWQlFYbENMRk5CUVhwQ0xFVkJRVzFET3p0QlFVVnFReXhQUVVGSkxFbEJRVWtzU1VGQlNTeFZRVUZWTEUxQlFWWXNSMEZCYlVJc1EwRkJia0lzUlVGQmMwSXNTMEZCU3l4RFFVRk1MRVZCUVZFc1IwRkJNVU1zUlVGQk9FTTdRVUZETlVNc1VVRkJSeXhWUVVGVkxFTkJRVllzUlVGQllTeEhRVUZpTEVOQlFXbENMRU5CUVdwQ0xFMUJRWGRDTEVkQlFYaENMRVZCUVRSQ08wRkJRemRDTEdGQlFVOHNWVUZCVlN4RFFVRldMRU5CUVZBc1EwRkVOa0k3UzBGQkwwSTdSMEZFUmpzN1FVRk5RU3hUUVVGUExFdEJRVkFzUTBGU2FVTTdRMEZCYmtNN08wRkJWMEVzVTBGQlV5eFRRVUZVTEVOQlFXMUNMRWRCUVc1Q0xFVkJRWGRDTEVOQlFYaENMRVZCUVRKQ0xGTkJRVE5DTEVWQlFYRkRPenRCUVVWcVF5eFBRVUZKTEVsQlFVa3NTVUZCU1N4VlFVRlZMRTFCUVZZc1IwRkJiVUlzUTBGQmJrSXNSVUZCYzBJc1MwRkJTeXhEUVVGTUxFVkJRVkVzUjBGQk1VTXNSVUZCT0VNN1FVRkRNVU1zVVVGQlJ5eFZRVUZWTEVOQlFWWXNSVUZCWVN4SFFVRmlMRU5CUVdsQ0xFTkJRV3BDTEUxQlFYZENMRWRCUVhoQ0xFVkJRVFJDTzBGQlF6TkNMR0ZCUVU4c1ZVRkJWU3hOUVVGV0xFTkJRV2xDTEVWQlFXcENMRVZCUVhGQ0xFMUJRWEpDTEVOQlFUUkNMRU5CUVRWQ0xFVkJRU3RDTEVOQlFTOUNMRU5CUVZBc1EwRkVNa0k3UzBGQkwwSTdSMEZFU2pzN1FVRk5RU3hUUVVGUExGTkJRVkFzUTBGU2FVTTdRMEZCY2tNN08wRkJWMEVzVTBGQlV5eFJRVUZVTEVOQlFXdENMRWRCUVd4Q0xFVkJRWFZDTEVOQlFYWkNMRVZCUVRCQ0xFbEJRVEZDTEVWQlFXZERMRkZCUVdoRExFVkJRWGxETzBGQlEzSkRMRTlCUVVrc1NVRkJTU3hKUVVGSkxFdEJRVXNzVFVGQlRDeEhRVUZqTEVOQlFXUXNSVUZCYVVJc1MwRkJTeXhEUVVGTUxFVkJRVkVzUjBGQmNrTXNSVUZCZVVNN1FVRkRja01zVVVGQlJ5eExRVUZMTEVOQlFVd3NSVUZCVVN4SFFVRlNMRU5CUVZrc1EwRkJXaXhOUVVGdFFpeEhRVUZ1UWl4RlFVRjFRanRCUVVOMFFpeGhRVUZQTEV0QlFVc3NUVUZCVEN4RFFVRlpMRVZCUVZvc1JVRkJaMElzVFVGQmFFSXNRMEZCZFVJc1EwRkJka0lzUlVGQk1FSXNRMEZCTVVJc1JVRkJOa0lzVVVGQk4wSXNRMEZCVUN4RFFVUnpRanRMUVVFeFFqdEhRVVJLT3p0QlFVMUdMRk5CUVU4c1MwRkJTeXhOUVVGTUxFTkJRVmtzUlVGQldpeEZRVUZuUWl4SlFVRm9RaXhEUVVGeFFpeFJRVUZ5UWl4RFFVRlFMRU5CVUhWRE8wTkJRWHBET3p0QlFWVkJMRk5CUVZNc1UwRkJWQ3hEUVVGdFFpeEhRVUZ1UWl4RlFVRjNRaXhEUVVGNFFpeEZRVUV5UWl4SlFVRXpRaXhGUVVGblF6dEJRVU01UWl4UFFVRkpMRWxCUVVrc1NVRkJTU3hMUVVGTExFMUJRVXdzUjBGQll5eERRVUZrTEVWQlFXbENMRXRCUVVzc1EwRkJUQ3hGUVVGUkxFZEJRWEpETEVWQlFYbERPMEZCUTNaRExGRkJRVWNzUzBGQlN5eERRVUZNTEVWQlFWRXNSMEZCVWl4RFFVRlpMRU5CUVZvc1RVRkJiVUlzUjBGQmJrSXNSVUZCZFVJN1FVRkRlRUlzWVVGQlR5eEpRVUZRTEVOQlJIZENPMHRCUVRGQ08wZEJSRVk3TzBGQlRVRXNVMEZCVHl4TFFVRlFMRU5CVURoQ08wTkJRV2hET3p0QlFWVkJMRk5CUVZNc1QwRkJWQ3hEUVVGcFFpeEhRVUZxUWl4RlFVRnpRaXhEUVVGMFFpeEZRVUY1UWl4SlFVRjZRaXhGUVVFNFFqdEJRVU0xUWl4TlFVRkhMRU5CUVVNc1ZVRkJWU3hIUVVGV0xFVkJRV1VzUTBGQlppeEZRVUZyUWl4SlFVRnNRaXhEUVVGRUxFVkJRWGxDTzBGQlF6RkNMRmRCUVU4c1MwRkJVQ3hEUVVRd1FqdEhRVUUxUWpzN1FVRkpRU3hOUVVGSkxGRkJRVkVzVVVGQlVTeEhRVUZTTEVWQlFXRXNRMEZCWWl4RlFVRm5RaXhKUVVGb1FpeERRVUZTTEVOQlRIZENPenRCUVU4MVFpeFRRVUZQTEVsQlFVa3NTMEZCU2l4RFFVRlZMRTFCUVUwc1IwRkJUaXhEUVVGVkxFTkJRVllzUTBGQlZpeEZRVUYzUWl4TFFVRjRRaXhGUVVFclFpeFZRVUZWTEVkQlFWWXNSVUZCWlN4RFFVRm1MRVZCUVd0Q0xFbEJRV3hDTEVOQlFTOUNMRU5CUVZBc1EwRlFORUk3UTBGQk9VSTdPMEZCVlVFc1UwRkJVeXhWUVVGVUxFTkJRVzlDTEVkQlFYQkNMRVZCUVhsQ0xFTkJRWHBDTEVWQlFUUkNMRWxCUVRWQ0xFVkJRV3RETEZGQlFXeERMRVZCUVRKRE96dEJRVVY2UXl4UFFVRkpMRWxCUVVrc1NVRkJTU3hWUVVGVkxFMUJRVllzUjBGQmJVSXNRMEZCYmtJc1JVRkJjMElzUzBGQlN5eERRVUZNTEVWQlFWRXNSMEZCTVVNc1JVRkJPRU03UVVGRE5VTXNVVUZCUnl4VlFVRlZMRU5CUVZZc1JVRkJZU3hIUVVGaUxFTkJRV2xDTEVOQlFXcENMRTFCUVhkQ0xFZEJRWGhDTEVWQlFUUkNPMEZCUXpkQ0xHRkJRVThzVlVGQlZTeE5RVUZXTEVOQlFXbENMRVZCUVdwQ0xFVkJRWEZDTEUxQlFYSkNMRU5CUVRSQ0xFTkJRVFZDTEVWQlFTdENMRU5CUVM5Q0xFVkJRV3RETEZGQlFXeERMRU5CUVZBc1EwRkVOa0k3UzBGQkwwSTdSMEZFUmpzN1FVRk5RU3hUUVVGUExGTkJRVkFzUTBGU2VVTTdRMEZCTTBNN08wRkJXVUVzVTBGQlV5eFBRVUZVTEVOQlFXbENMRWxCUVdwQ0xFVkJRWE5DTzBGQlEyeENMRk5CUVU4c1MwRkJTeXhOUVVGTUxFTkJRVmtzUlVGQldpeEZRVUZuUWl4UFFVRm9RaXhGUVVGUUxFTkJSR3RDTzBOQlFYUkNPenRCUVVsQkxGTkJRVk1zVTBGQlZDeERRVUZ0UWl4SFFVRnVRaXhGUVVGM1FpeEhRVUY0UWl4RlFVRTBRanRCUVVONFFpeE5RVUZITEU5QlFVOHNaMEpCUVdkQ0xFZEJRV2hDTEVOQlFWQXNSVUZCTkVJN1FVRkRNMElzVjBGQlR5eEpRVUZKTEV0QlFVb3NRMEZCVlN4UFFVRlBMRWRCUVZBc1EwRkJWeXhKUVVGWUxFTkJRVllzUlVGQk5FSXNTVUZCU1N4SFFVRktMRU5CUVRWQ0xFTkJRVkFzUTBGRU1rSTdSMEZCTDBJc1RVRkZTenRCUVVORUxGZEJRVThzVDBGQlR5eEhRVUZRTEVOQlFWY3NUMEZCV0N4RFFVRlFMRU5CUkVNN1IwRkdURHREUVVSS096dEJRVkZCTEZOQlFWTXNUMEZCVkN4RFFVRnBRaXhKUVVGcVFpeEZRVUYxUWl4UFFVRlBMRVZCUVZBc1JVRkJWenRCUVVOb1F5eE5RVUZKTEZkQlFWY3NSVUZCV0N4RFFVUTBRanM3UVVGSGFFTXNUMEZCU1N4SlFVRkpMRU5CUVVvc1NVRkJVeXhKUVVGaUxFVkJRV3RDTzBGQlEyaENMRkZCUVVjc1VVRkJVU3hEUVVGU0xFTkJRVWdzUlVGQll6dEJRVU5hTEdsQ1FVRlhMRk5CUVZNc1RVRkJWQ3hEUVVGblFpeFJRVUZSTEVOQlFWSXNRMEZCYUVJc1EwRkJXQ3hEUVVSWk8wdEJRV1FzVFVGRlN6dEJRVU5JTEdWQlFWTXNTVUZCVkN4RFFVRmpMRU5CUVdRc1JVRkVSenRMUVVaTU8wZEJSRVk3TzBGQlVVRXNVMEZCVHl4UFFVRlBMRTFCUVZBc1EwRkJZeXhUUVVGVExFMUJRVlFzUTBGQlowSXNTVUZCYUVJc1EwRkJaQ3hEUVVGUUxFTkJXR2RETzBOQlFXeERPenRCUVdOQkxGTkJRVk1zVTBGQlZDeERRVUZ0UWl4RFFVRnVRaXhGUVVGelFpeEpRVUYwUWl4RlFVRXlRanRCUVVONlFpeE5RVUZKTEU5QlFVOHNSVUZCVUN4RFFVUnhRanM3UVVGSGVrSXNUMEZCU1N4SlFVRkpMRWxCUVVrc1EwRkJTaXhGUVVGUExFbEJRVWtzUTBGQlNpeEZRVUZQTEVkQlFYUkNMRVZCUVRCQ08wRkJRM2hDTEZOQlFVc3NTVUZCVEN4RFFVRlZMRWxCUVZZc1JVRkVkMEk3UjBGQk1VSTdPMEZCU1VFc1UwRkJUeXhQUVVGUExFMUJRVkFzUTBGQll5eEpRVUZrTEVOQlFWQXNRMEZRZVVJN1EwRkJNMEk3TzBGQlZVRXNVMEZCVXl4UlFVRlVMRU5CUVd0Q0xFZEJRV3hDTEVWQlFYVkNMRWRCUVhaQ0xFVkJRVFJDTEVsQlFUVkNMRVZCUVdsRE8wRkJReTlDTEUxQlFVa3NWVUZCVlN4RlFVRldMRU5CUkRKQ096dEJRVWN2UWl4UFFVRkpMRWxCUVVrc1EwRkJTaXhKUVVGVExFbEJRV0lzUlVGQmEwSTdRVUZEYUVJc1VVRkJTU3hOUVVGTkxFbEJRVWtzUTBGQlNpeEZRVUZQTEVkQlFWQXNRMEZCVGl4RFFVUlpPMEZCUldoQ0xGbEJRVkVzU1VGQlVpeERRVUZoTEVsQlFVa3NSMEZCU2l4RFFVRlJMRU5CUVZJc1EwRkJZaXhGUVVablFqdEJRVWRvUWl4VlFVRk5MRWxCUVVrc1IwRkJTaXhEUVVGUkxFTkJRVklzUTBGQlRpeERRVWhuUWp0SFFVRnNRanM3UVVGUFFTeFRRVUZQTEVsQlFVa3NTMEZCU2l4RFFVRlZMRTlCUVU4c1RVRkJVQ3hEUVVGakxFOUJRV1FzUTBGQlZpeEZRVUZyUXl4SFFVRnNReXhEUVVGUUxFTkJWaXRDTzBOQlFXcERPenRCUVdGQkxGTkJRVk1zVTBGQlZDeERRVUZ0UWl4SFFVRnVRaXhGUVVGM1FpeEpRVUY0UWl4RlFVRTJRanRCUVVNelFpeE5RVUZKTEZWQlFWVXNSVUZCVml4RFFVUjFRanM3UVVGSE0wSXNUMEZCU1N4RFFVRktMRWxCUVZNc1NVRkJWQ3hGUVVGak8wRkJRMW9zVVVGQlNTeFRRVUZUTEVsQlFVa3NRMEZCU2l4RFFVRlVMRU5CUkZFN08wRkJSMW9zVVVGQlJ5eFhRVUZYTEVsQlFWZ3NSVUZCWjBJN1FVRkRha0lzWTBGQlVTeEpRVUZTTEVOQlFXRXNRMEZCWWl4RlFVUnBRanRMUVVGdVFpeE5RVVZOTEVsQlFVY3NhMEpCUVd0Q0xFdEJRV3hDTEVWQlFYZENPMEZCUXk5Q0xHTkJRVkVzU1VGQlVpeERRVUZoTEU5QlFVOHNSMEZCVUN4RFFVRlhMRU5CUVZnc1EwRkJZaXhGUVVRclFqdExRVUV6UWp0SFFVeFNPenRCUVZWQkxGTkJRVThzVDBGQlR5eE5RVUZRTEVOQlFXTXNUMEZCWkN4RFFVRlFMRU5CWWpKQ08wTkJRVGRDT3p0QlFXZENRU3hUUVVGVExGTkJRVlFzUTBGQmJVSXNSMEZCYmtJc1JVRkJkMElzUjBGQmVFSXNSVUZCTmtJc1IwRkJOMElzUlVGQmFVTTdRVUZETDBJc1RVRkJTU3hQUVVGUExFZEJRVkFzUTBGRU1rSTdPMEZCUnk5Q0xFOUJRVWtzU1VGQlNTeERRVUZLTEVsQlFWTXNaMEpCUVdkQ0xFZEJRV2hDTEVOQlFXSXNSVUZCYTBNN1FVRkRhRU1zVjBGQlR5eEpRVUZKTEVOQlFVb3NSVUZCVHl4SlFVRkpMRU5CUVVvc1EwRkJVQ3hGUVVGbExFbEJRV1lzUTBGQlVDeERRVVJuUXp0SFFVRnNRenM3UVVGSlFTeFRRVUZQTEVsQlFWQXNRMEZRSzBJN1EwRkJha003TzBGQlZVRXNVMEZCVXl4alFVRlVMRU5CUVhkQ0xFbEJRWGhDTEVWQlFUWkNPMEZCUXpOQ0xFMUJRVWtzU1VGQlNTeEZRVUZLTEVOQlJIVkNPenRCUVVjelFpeFBRVUZKTEVOQlFVb3NTVUZCVXl4SlFVRlVMRVZCUVdNN1FVRkRXaXhOUVVGRkxFVkJRVVVzUjBGQlJpeERRVUZOTEVOQlFVNHNRMEZCUml4SlFVRmpMRVZCUVVVc1IwRkJSaXhEUVVGTkxFTkJRVTRzUTBGQlpDeERRVVJaTzBkQlFXUTdPMEZCU1VFc1UwRkJUeXhQUVVGUExFMUJRVkFzUTBGQll5eERRVUZrTEVOQlFWQXNRMEZRTWtJN1EwRkJOMEk3TzBGQlZVRXNaVUZCWlR0QlFVTmlMR1ZCUkdFN1FVRkZZaXhQUVVaaE8wRkJSMklzVlVGSVlUdEJRVWxpTEZsQlNtRTdRVUZMWWl4WFFVeGhPMEZCVFdJc1kwRk9ZVHRCUVU5aUxHRkJVR0U3UVVGUllpeFRRVkpoTzBGQlUySXNhVUpCVkdFN1FVRlZZaXh2UWtGV1lUdEJRVmRpTEd0Q1FWaGhPMEZCV1dJc01FSkJXbUU3UVVGaFlpeHhRa0ZpWVR0QlFXTmlMR05CWkdFN1FVRmxZaXhqUVdaaE8wRkJaMEppTEUxQmFFSmhPMEZCYVVKaUxFMUJha0poTzBGQmEwSmlMRXRCYkVKaE8wRkJiVUppTEV0QmJrSmhPMEZCYjBKaUxFdEJjRUpoTzBGQmNVSmlMRTFCY2tKaE8wRkJjMEppTEV0QmRFSmhPMEZCZFVKaUxFOUJka0poTzBGQmQwSmlMRTlCZUVKaE8wRkJlVUppTEd0Q1FYcENZVHRCUVRCQ1lpeFhRVEZDWVR0QlFUSkNZaXhWUVROQ1lUdEJRVFJDWWl4VFFUVkNZVHRCUVRaQ1lpeFRRVGRDWVR0QlFUaENZaXhaUVRsQ1lUdEJRU3RDWWl4VFFTOUNZVHRCUVdkRFlpeFpRV2hEWVR0QlFXbERZaXhYUVdwRFlUdEJRV3REWWl4VFFXeERZVHRCUVcxRFlpeFhRVzVEWVR0QlFXOURZaXhWUVhCRFlUdEJRWEZEWWl4WFFYSkRZVHRCUVhORFlpeFhRWFJEWVR0RFFVRm1JaXdpWm1sc1pTSTZJbXhwWWk5amIzSmxMMloxYm1OMGFXOXVjeTVxY3lJc0luTnZkWEpqWlhORGIyNTBaVzUwSWpwYkltbHRjRzl5ZENCN0lGUjFjR3hsSUgwZ1puSnZiU0FuTGk5d2NtbHRhWFJwZG1Wekp6dGNibWx0Y0c5eWRDQkNhWFJUZEhKcGJtY2dabkp2YlNBbkxpOWlhWFJmYzNSeWFXNW5KenRjYm1sdGNHOXlkQ0JRWVhSMFpYSnVjeUJtY205dElDY3VMM0JoZEhSbGNtNXpKenRjYm1sdGNHOXlkQ0JRY205MGIyTnZiQ0JtY205dElDY3VMM0J5YjNSdlkyOXNKenRjYmx4dVpuVnVZM1JwYjI0Z1kyRnNiRjl3Y205d1pYSjBlU2hwZEdWdExDQndjbTl3WlhKMGVTbDdYRzRnSUd4bGRDQndjbTl3SUQwZ2JuVnNiRHRjYmx4dUlDQnBaaWgwZVhCbGIyWWdhWFJsYlNBOVBUMGdYQ0p1ZFcxaVpYSmNJaUI4ZkNCMGVYQmxiMllnYVhSbGJTQTlQVDBnWENKemVXMWliMnhjSWlCOGZDQjBlWEJsYjJZZ2FYUmxiU0E5UFQwZ1hDSmliMjlzWldGdVhDSWdmSHdnZEhsd1pXOW1JR2wwWlcwZ1BUMDlJRndpYzNSeWFXNW5YQ0lwZTF4dUlDQWdJR2xtS0dsMFpXMWJjSEp2Y0dWeWRIbGRJQ0U5UFNCMWJtUmxabWx1WldRcGUxeHVJQ0FnSUNBZ2NISnZjQ0E5SUhCeWIzQmxjblI1TzF4dUlDQWdJSDFsYkhObElHbG1LR2wwWlcxYlUzbHRZbTlzTG1admNpaHdjbTl3WlhKMGVTbGRJQ0U5UFNCMWJtUmxabWx1WldRcGUxeHVJQ0FnSUNBZ2NISnZjQ0E5SUZONWJXSnZiQzVtYjNJb2NISnZjR1Z5ZEhrcE8xeHVJQ0FnSUgxY2JpQWdmU0JsYkhObElIdGNiaUFnSUNCcFppaHdjbTl3WlhKMGVTQnBiaUJwZEdWdEtYdGNiaUFnSUNBZ0lIQnliM0FnUFNCd2NtOXdaWEowZVR0Y2JpQWdJQ0I5Wld4elpTQnBaaWhUZVcxaWIyd3VabTl5S0hCeWIzQmxjblI1S1NCcGJpQnBkR1Z0S1h0Y2JpQWdJQ0FnSUhCeWIzQWdQU0JUZVcxaWIyd3VabTl5S0hCeWIzQmxjblI1S1R0Y2JpQWdJQ0I5WEc0Z0lIMWNibHh1SUNCcFppaHdjbTl3SUQwOVBTQnVkV3hzS1h0Y2JpQWdJQ0IwYUhKdmR5QnVaWGNnUlhKeWIzSW9ZRkJ5YjNCbGNuUjVJQ1I3SUhCeWIzQmxjblI1SUgwZ2JtOTBJR1p2ZFc1a0lHbHVJQ1I3SUdsMFpXMGdmV0FwT3lCY2JpQWdmVnh1WEc0Z0lHbG1LR2wwWlcxYmNISnZjRjBnYVc1emRHRnVZMlZ2WmlCR2RXNWpkR2x2YmlsN1hHNGdJQ0FnY21WMGRYSnVJR2wwWlcxYmNISnZjRjBvS1R0Y2JpQWdmV1ZzYzJWN1hHNGdJQ0FnY21WMGRYSnVJR2wwWlcxYmNISnZjRjA3WEc0Z0lIMWNibjFjYmx4dVpuVnVZM1JwYjI0Z1lYQndiSGtvTGk0dVlYSm5jeWw3WEc0Z0lHbG1LR0Z5WjNNdWJHVnVaM1JvSUQwOVBTQXlLWHRjYmlBZ0lDQmhjbWR6V3pCZExtRndjR3g1S0c1MWJHd3NJR0Z5WjNNdWMyeHBZMlVvTVNrcE8xeHVJQ0I5Wld4elpYdGNiaUFnSUNCaGNtZHpXekJkVzJGeVozTmJNVjFkTG1Gd2NHeDVLRzUxYkd3c0lHRnlaM011YzJ4cFkyVW9NaWtwTzF4dUlDQjlYRzU5WEc1Y2JtWjFibU4wYVc5dUlHTnZiblJoYVc1ektHeGxablFzSUhKcFoyaDBLWHRjYmlBZ1ptOXlLR3hsZENCNElHOW1JSEpwWjJoMEtYdGNiaUFnSUNCcFppaFFZWFIwWlhKdWN5NXRZWFJqYUY5dWIxOTBhSEp2ZHloc1pXWjBMQ0I0S1NBaFBTQnVkV3hzS1h0Y2JpQWdJQ0FnSUhKbGRIVnliaUIwY25WbE8xeHVJQ0FnSUgxY2JpQWdmVnh1WEc0Z0lISmxkSFZ5YmlCbVlXeHpaVHRjYm4xY2JseHVablZ1WTNScGIyNGdaMlYwWDJkc2IySmhiQ2dwZTF4dUlDQnBaaWgwZVhCbGIyWW9jMlZzWmlrZ0lUMDlJRndpZFc1a1pXWnBibVZrWENJcGUxeHVJQ0FnSUhKbGRIVnliaUJ6Wld4bU8xeHVJQ0I5Wld4elpTQnBaaWgwZVhCbGIyWW9kMmx1Wkc5M0tTQWhQVDBnWENKMWJtUmxabWx1WldSY0lpbDdYRzRnSUNBZ2NtVjBkWEp1SUhkcGJtUnZkenRjYmlBZ2ZXVnNjMlVnYVdZb2RIbHdaVzltS0dkc2IySmhiQ2tnSVQwOUlGd2lkVzVrWldacGJtVmtYQ0lwZTF4dUlDQWdJSEpsZEhWeWJpQm5iRzlpWVd3N1hHNGdJSDFjYmx4dUlDQjBhSEp2ZHlCdVpYY2dSWEp5YjNJb1hDSk9ieUJuYkc5aVlXd2djM1JoZEdVZ1ptOTFibVJjSWlrN1hHNTlYRzVjYm1aMWJtTjBhVzl1SUdSbFpuTjBjblZqZENoa1pXWmhkV3gwY3lsN1hHNGdJSEpsZEhWeWJpQmpiR0Z6Y3lCN1hHNGdJQ0FnWTI5dWMzUnlkV04wYjNJb2RYQmtZWFJsSUQwZ2UzMHBlMXh1SUNBZ0lDQWdiR1YwSUhSb1pWOTJZV3gxWlhNZ1BTQlBZbXBsWTNRdVlYTnphV2R1S0dSbFptRjFiSFJ6TENCMWNHUmhkR1VwTzF4dUlDQWdJQ0FnVDJKcVpXTjBMbUZ6YzJsbmJpaDBhR2x6TENCMGFHVmZkbUZzZFdWektUdGNiaUFnSUNCOVhHNWNiaUFnSUNCemRHRjBhV01nWTNKbFlYUmxLSFZ3WkdGMFpYTWdQU0I3ZlNsN1hHNGdJQ0FnSUNCc1pYUWdlQ0E5SUc1bGR5QjBhR2x6S0hWd1pHRjBaWE1wTzF4dUlDQWdJQ0FnY21WMGRYSnVJRTlpYW1WamRDNW1jbVZsZW1Vb2VDazdYRzRnSUNBZ2ZWeHVJQ0I5TzF4dWZWeHVYRzVjYm1aMWJtTjBhVzl1SUdSbFptVjRZMlZ3ZEdsdmJpaGtaV1poZFd4MGN5bDdYRzRnSUhKbGRIVnliaUJqYkdGemN5QmxlSFJsYm1SeklFVnljbTl5SUh0Y2JpQWdJQ0JqYjI1emRISjFZM1J2Y2loMWNHUmhkR1VnUFNCN2ZTbDdYRzRnSUNBZ0lDQnNaWFFnYldWemMyRm5aU0E5SUhWd1pHRjBaUzV0WlhOellXZGxJSHg4SUZ3aVhDSTdYRzRnSUNBZ0lDQnpkWEJsY2lodFpYTnpZV2RsS1R0Y2JseHVJQ0FnSUNBZ2JHVjBJSFJvWlY5MllXeDFaWE1nUFNCUFltcGxZM1F1WVhOemFXZHVLR1JsWm1GMWJIUnpMQ0IxY0dSaGRHVXBPMXh1SUNBZ0lDQWdUMkpxWldOMExtRnpjMmxuYmloMGFHbHpMQ0IwYUdWZmRtRnNkV1Z6S1R0Y2JseHVJQ0FnSUNBZ2RHaHBjeTV1WVcxbElEMGdkR2hwY3k1amIyNXpkSEoxWTNSdmNpNXVZVzFsTzF4dUlDQWdJQ0FnZEdocGN5NXRaWE56WVdkbElEMGdiV1Z6YzJGblpUdGNiaUFnSUNBZ0lIUm9hWE5iVTNCbFkybGhiRVp2Y20xekxtRjBiMjBvWENKZlgyVjRZMlZ3ZEdsdmJsOWZYQ0lwWFNBOUlIUnlkV1U3WEc0Z0lDQWdJQ0JGY25KdmNpNWpZWEIwZFhKbFUzUmhZMnRVY21GalpTaDBhR2x6TENCMGFHbHpMbU52Ym5OMGNuVmpkRzl5TG01aGJXVXBPMXh1SUNBZ0lIMWNibHh1SUNBZ0lITjBZWFJwWXlCamNtVmhkR1VvZFhCa1lYUmxjeUE5SUh0OUtYdGNiaUFnSUNBZ0lHeGxkQ0I0SUQwZ2JtVjNJSFJvYVhNb2RYQmtZWFJsY3lrN1hHNGdJQ0FnSUNCeVpYUjFjbTRnVDJKcVpXTjBMbVp5WldWNlpTaDRLVHRjYmlBZ0lDQjlYRzRnSUgwN1hHNTlYRzVjYm1aMWJtTjBhVzl1SUdSbFpuQnliM1J2WTI5c0tITndaV01wZTF4dUlDQnlaWFIxY200Z2JtVjNJRkJ5YjNSdlkyOXNLSE53WldNcE8xeHVmVnh1WEc1bWRXNWpkR2x2YmlCa1pXWnBiWEJzS0hCeWIzUnZZMjlzTENCMGVYQmxMQ0JwYlhCc0tYdGNiaUFnY0hKdmRHOWpiMnd1YVcxd2JHVnRaVzUwWVhScGIyNG9kSGx3WlN3Z2FXMXdiQ2s3WEc1OVhHNWNibVoxYm1OMGFXOXVJR2RsZEY5dlltcGxZM1JmYTJWNWN5aHZZbW9wZTF4dUlDQWdJSEpsZEhWeWJpQlBZbXBsWTNRdWEyVjVjeWh2WW1vcExtTnZibU5oZENoUFltcGxZM1F1WjJWMFQzZHVVSEp2Y0dWeWRIbFRlVzFpYjJ4ektHOWlhaWtwTzF4dWZWeHVYRzVtZFc1amRHbHZiaUJwYzE5MllXeHBaRjlqYUdGeVlXTjBaWElvWTI5a1pYQnZhVzUwS1h0Y2JpQWdkSEo1ZTF4dUlDQWdJSEpsZEhWeWJpQlRkSEpwYm1jdVpuSnZiVU52WkdWUWIybHVkQ2hqYjJSbGNHOXBiblFwSUNFOUlHNTFiR3c3WEc0Z0lIMWpZWFJqYUNobEtYdGNiaUFnSUNCeVpYUjFjbTRnWm1Gc2MyVTdYRzRnSUgxY2JuMWNibHh1THk5b2RIUndjem92TDJSbGRtVnNiM0JsY2k1dGIzcHBiR3hoTG05eVp5OWxiaTFWVXk5a2IyTnpMMWRsWWk5QlVFa3ZWMmx1Wkc5M1FtRnpaVFkwTDBKaGMyVTJORjlsYm1OdlpHbHVaMTloYm1SZlpHVmpiMlJwYm1jalUyOXNkWFJwYjI1Zk1sOGxSVElsT0RBbE9UTmZjbVYzY21sMFpWOTBhR1ZmUkU5TmMxOWhkRzlpS0NsZllXNWtYMkowYjJFb0tWOTFjMmx1WjE5S1lYWmhVMk55YVhCMEozTmZWSGx3WldSQmNuSmhlWE5mWVc1a1gxVlVSaTA0WEc1bWRXNWpkR2x2YmlCaU5qUkZibU52WkdWVmJtbGpiMlJsS0hOMGNpa2dlMXh1SUNBZ0lISmxkSFZ5YmlCaWRHOWhLR1Z1WTI5a1pWVlNTVU52YlhCdmJtVnVkQ2h6ZEhJcExuSmxjR3hoWTJVb0x5VW9XekF0T1VFdFJsMTdNbjBwTDJjc0lHWjFibU4wYVc5dUtHMWhkR05vTENCd01Ta2dlMXh1SUNBZ0lDQWdJQ0J5WlhSMWNtNGdVM1J5YVc1bkxtWnliMjFEYUdGeVEyOWtaU2duTUhnbklDc2djREVwTzF4dUlDQWdJSDBwS1R0Y2JuMWNibHh1Wm5WdVkzUnBiMjRnWkdWc1pYUmxYM0J5YjNCbGNuUjVYMlp5YjIxZmJXRndLRzFoY0N3Z2NISnZjR1Z5ZEhrcGUxeHVJQ0FnSUd4bGRDQnVaWGRmYldGd0lEMGdUMkpxWldOMExtRnpjMmxuYmloUFltcGxZM1F1WTNKbFlYUmxLRzFoY0M1amIyNXpkSEoxWTNSdmNpNXdjbTkwYjNSNWNHVXBMQ0J0WVhBcE8xeHVJQ0FnSUdSbGJHVjBaU0J1WlhkZmJXRndXM0J5YjNCbGNuUjVYVHRjYmx4dUlDQnlaWFIxY200Z1QySnFaV04wTG1aeVpXVjZaU2h1WlhkZmJXRndLVHRjYm4xY2JseHVablZ1WTNScGIyNGdZMnhoYzNOZmRHOWZiMkpxS0cxaGNDbDdYRzRnSUNBZ2JHVjBJRzVsZDE5dFlYQWdQU0JQWW1wbFkzUXVZWE56YVdkdUtIdDlMQ0J0WVhBcE8xeHVJQ0J5WlhSMWNtNGdUMkpxWldOMExtWnlaV1Y2WlNodVpYZGZiV0Z3S1R0Y2JuMWNibHh1Wm5WdVkzUnBiMjRnWVdSa1gzQnliM0JsY25SNVgzUnZYMjFoY0NodFlYQXNJSEJ5YjNCbGNuUjVMQ0IyWVd4MVpTbDdYRzRnSUd4bGRDQnVaWGRmYldGd0lEMGdUMkpxWldOMExtRnpjMmxuYmloN2ZTd2diV0Z3S1R0Y2JpQWdibVYzWDIxaGNGdHdjbTl3WlhKMGVWMGdQU0IyWVd4MVpUdGNiaUFnY21WMGRYSnVJRTlpYW1WamRDNW1jbVZsZW1Vb2JtVjNYMjFoY0NrN1hHNTlYRzVjYmx4dVpuVnVZM1JwYjI0Z2RYQmtZWFJsWDIxaGNDaHRZWEFzSUhCeWIzQmxjblI1TENCMllXeDFaU2w3WEc0Z0lDQWdhV1lvY0hKdmNHVnlkSGtnYVc0Z1oyVjBYMjlpYW1WamRGOXJaWGx6S0cxaGNDa3BlMXh1SUNBZ0lDQWdJQ0J5WlhSMWNtNGdZV1JrWDNCeWIzQmxjblI1WDNSdlgyMWhjQ2h0WVhBc0lIQnliM0JsY25SNUxDQjJZV3gxWlNrN1hHNGdJQ0FnZlZ4dVhHNGdJQ0FnZEdoeWIzY2dYQ0p0WVhBZ1pHOWxjeUJ1YjNRZ2FHRjJaU0JyWlhsY0lqdGNibjFjYmx4dVpuVnVZM1JwYjI0Z1ltNXZkQ2hsZUhCeUtYdGNiaUFnY21WMGRYSnVJSDVsZUhCeU8xeHVmVnh1WEc1bWRXNWpkR2x2YmlCaVlXNWtLR3hsWm5Rc0lISnBaMmgwS1h0Y2JpQWdjbVYwZFhKdUlHeGxablFnSmlCeWFXZG9kRHRjYm4xY2JseHVablZ1WTNScGIyNGdZbTl5S0d4bFpuUXNJSEpwWjJoMEtYdGNiaUFnY21WMGRYSnVJR3hsWm5RZ2ZDQnlhV2RvZER0Y2JuMWNibHh1Wm5WdVkzUnBiMjRnWW5Oc0tHeGxablFzSUhKcFoyaDBLWHRjYmlBZ2NtVjBkWEp1SUd4bFpuUWdQRHdnY21sbmFIUTdYRzU5WEc1Y2JtWjFibU4wYVc5dUlHSnpjaWhzWldaMExDQnlhV2RvZENsN1hHNGdJSEpsZEhWeWJpQnNaV1owSUQ0K0lISnBaMmgwTzF4dWZWeHVYRzVtZFc1amRHbHZiaUJpZUc5eUtHeGxablFzSUhKcFoyaDBLWHRjYmlBZ2NtVjBkWEp1SUd4bFpuUWdYaUJ5YVdkb2REdGNibjFjYmx4dVpuVnVZM1JwYjI0Z2VtbHdLR3hwYzNSZmIyWmZiR2x6ZEhNcGUxeHVJQ0JwWmloc2FYTjBYMjltWDJ4cGMzUnpMbXhsYm1kMGFDQTlQVDBnTUNsN1hHNGdJQ0FnY21WMGRYSnVJRTlpYW1WamRDNW1jbVZsZW1Vb1cxMHBPMXh1SUNCOVhHNWNiaUFnYkdWMElHNWxkMTkyWVd4MVpTQTlJRnRkTzF4dUlDQnNaWFFnYzIxaGJHeGxjM1JmYkdWdVozUm9JRDBnYkdsemRGOXZabDlzYVhOMGMxc3dYVHRjYmx4dUlDQm1iM0lvYkdWMElIZ2diMllnYkdsemRGOXZabDlzYVhOMGN5bDdYRzRnSUNBZ2FXWW9lQzVzWlc1bmRHZ2dQQ0J6YldGc2JHVnpkRjlzWlc1bmRHZ3BlMXh1SUNBZ0lDQWdjMjFoYkd4bGMzUmZiR1Z1WjNSb0lEMGdlQzVzWlc1bmRHZzdYRzRnSUNBZ2ZWeHVJQ0I5WEc1Y2JpQWdabTl5S0d4bGRDQnBJRDBnTURzZ2FTQThJSE50WVd4c1pYTjBYMnhsYm1kMGFEc2dhU3NyS1h0Y2JpQWdJQ0JzWlhRZ1kzVnljbVZ1ZEY5MllXeDFaU0E5SUZ0ZE8xeHVJQ0FnSUdadmNpaHNaWFFnYWlBOUlEQTdJR29nUENCc2FYTjBYMjltWDJ4cGMzUnpMbXhsYm1kMGFEc2dhaXNyS1h0Y2JpQWdJQ0FnSUdOMWNuSmxiblJmZG1Gc2RXVXVjSFZ6YUNoc2FYTjBYMjltWDJ4cGMzUnpXMnBkVzJsZEtUdGNiaUFnSUNCOVhHNWNiaUFnSUNCdVpYZGZkbUZzZFdVdWNIVnphQ2h1WlhjZ1ZIVndiR1VvTGk0dVkzVnljbVZ1ZEY5MllXeDFaU2twTzF4dUlDQjlYRzVjYmlBZ2NtVjBkWEp1SUU5aWFtVmpkQzVtY21WbGVtVW9ibVYzWDNaaGJIVmxLVHRjYm4xY2JseHVablZ1WTNScGIyNGdZMkZ1WDJSbFkyOWtaVFkwS0dSaGRHRXBJSHRjYmlBZ2RISjVlMXh1SUNBZ0lHRjBiMklvWkdGMFlTazdYRzRnSUNBZ2NtVjBkWEp1SUhSeWRXVTdYRzRnSUgxallYUmphQ2hsS1h0Y2JpQWdJQ0J5WlhSMWNtNGdabUZzYzJVN1hHNGdJSDFjYm4xY2JseHVablZ1WTNScGIyNGdjbVZ0YjNabFgyWnliMjFmYkdsemRDaHNhWE4wTENCbGJHVnRaVzUwS1h0Y2JpQWdJQ0JzWlhRZ1ptOTFibVFnUFNCbVlXeHpaVHRjYmx4dUlDQWdJSEpsZEhWeWJpQnNhWE4wTG1acGJIUmxjaWdvWld4bGJTa2dQVDRnZTF4dUlDQWdJQ0FnSUNCcFppZ2habTkxYm1RZ0ppWWdaV3hsYlNBOVBUMGdaV3hsYldWdWRDbDdYRzRnSUNBZ0lDQWdJQ0FnSUNCbWIzVnVaQ0E5SUhSeWRXVTdYRzRnSUNBZ0lDQWdJQ0FnSUNCeVpYUjFjbTRnWm1Gc2MyVTdYRzRnSUNBZ0lDQWdJSDFjYmx4dUlDQWdJQ0FnSUNCeVpYUjFjbTRnZEhKMVpUdGNiaUFnSUNCOUtUdGNibjFjYmx4dVpuVnVZM1JwYjI0Z1ptOXNaR3dvWm5WdUxDQmhZMk1zSUd4cGMzUXBlMXh1SUNBZ0lHeGxkQ0JoWTJNeElEMGdZV05qTzF4dVhHNGdJQ0FnWm05eUtHTnZibk4wSUdWc0lHOW1JR3hwYzNRcGUxeHVJQ0FnSUNBZ0lDQmhZMk14SUQwZ1puVnVLR1ZzTENCaFkyTXhLVHRjYmlBZ0lDQjlYRzVjYmlBZ0lDQnlaWFIxY200Z1lXTmpNVHRjYm4xY2JseHVYRzVtZFc1amRHbHZiaUJtYjJ4a2NpaG1kVzRzSUdGall5d2diR2x6ZENsN1hHNGdJQ0FnYkdWMElHRmpZekVnUFNCaFkyTTdYRzVjYmlBZ0lDQm1iM0lvYkdWMElHa2dQU0JzYVhOMExteGxibWQwYUNBdElERTdJR2tnUGowZ01Ec2dhUzB0S1h0Y2JpQWdJQ0FnSUNBZ1lXTmpNU0E5SUdaMWJpaHNhWE4wVzJsZExDQmhZMk14S1R0Y2JpQWdJQ0I5WEc1Y2JpQWdJQ0J5WlhSMWNtNGdZV05qTVR0Y2JuMWNibHh1Wm5WdVkzUnBiMjRnYTJWNVptbHVaQ2hyWlhrc0lHNHNJSFIxY0d4bGJHbHpkQ2w3WEc1Y2JpQWdabTl5S0d4bGRDQnBJRDBnZEhWd2JHVnNhWE4wTG14bGJtZDBhQ0F0SURFN0lHa2dQajBnTURzZ2FTMHRLWHRjYmlBZ0lDQnBaaWgwZFhCc1pXeHBjM1JiYVYwdVoyVjBLRzRwSUQwOVBTQnJaWGtwZTF4dUlDQWdJQ0FnY21WMGRYSnVJSFIxY0d4bGJHbHpkRnRwWFR0Y2JpQWdJQ0I5WEc0Z0lIMWNibHh1SUNCeVpYUjFjbTRnWm1Gc2MyVTdYRzU5WEc1Y2JtWjFibU4wYVc5dUlHdGxlV1JsYkdWMFpTaHJaWGtzSUc0c0lIUjFjR3hsYkdsemRDbDdYRzVjYmlBZ0lDQm1iM0lvYkdWMElHa2dQU0IwZFhCc1pXeHBjM1F1YkdWdVozUm9JQzBnTVRzZ2FTQStQU0F3T3lCcExTMHBlMXh1SUNBZ0lDQWdJQ0JwWmloMGRYQnNaV3hwYzNSYmFWMHVaMlYwS0c0cElEMDlQU0JyWlhrcGUxeHVJQ0FnSUNBZ0lDQWdJQ0FnY21WMGRYSnVJSFIxY0d4bGJHbHpkQzVqYjI1allYUW9XMTBwTG5Od2JHbGpaU2hwTENBeEtUdGNiaUFnSUNBZ0lDQWdmVnh1SUNBZ0lIMWNibHh1SUNBZ0lISmxkSFZ5YmlCMGRYQnNaV3hwYzNRN1hHNTlYRzVjYm1aMWJtTjBhVzl1SUd0bGVYTjBiM0psS0d0bGVTd2diaXdnYkdsemRDd2dibVYzZEhWd2JHVXBlMXh1SUNBZ0lHWnZjaWhzWlhRZ2FTQTlJR3hwYzNRdWJHVnVaM1JvSUMwZ01Uc2dhU0ErUFNBd095QnBMUzBwZTF4dUlDQWdJQ0FnSUNCcFppaHNhWE4wVzJsZExtZGxkQ2h1S1NBOVBUMGdhMlY1S1h0Y2JpQWdJQ0FnSUNBZ0lDQWdJSEpsZEhWeWJpQnNhWE4wTG1OdmJtTmhkQ2hiWFNrdWMzQnNhV05sS0drc0lERXNJRzVsZDNSMWNHeGxLVHRjYmlBZ0lDQWdJQ0FnZlZ4dUlDQWdJSDFjYmx4dUlDQnlaWFIxY200Z2JHbHpkQzVqYjI1allYUW9XMTBwTG5CMWMyZ29ibVYzZEhWd2JHVXBPMXh1ZlZ4dVhHNW1kVzVqZEdsdmJpQnJaWGx0WlcxaVpYSW9hMlY1TENCdUxDQnNhWE4wS1h0Y2JpQWdabTl5S0d4bGRDQnBJRDBnYkdsemRDNXNaVzVuZEdnZ0xTQXhPeUJwSUQ0OUlEQTdJR2t0TFNsN1hHNGdJQ0FnYVdZb2JHbHpkRnRwWFM1blpYUW9iaWtnUFQwOUlHdGxlU2w3WEc0Z0lDQWdJQ0J5WlhSMWNtNGdkSEoxWlR0Y2JpQWdJQ0I5WEc0Z0lIMWNibHh1SUNCeVpYUjFjbTRnWm1Gc2MyVTdYRzU5WEc1Y2JtWjFibU4wYVc5dUlHdGxlWFJoYTJVb2EyVjVMQ0J1TENCc2FYTjBLWHRjYmlBZ2FXWW9JV3RsZVcxbGJXSmxjaWhyWlhrc0lHNHNJR3hwYzNRcEtYdGNiaUFnSUNCeVpYUjFjbTRnWm1Gc2MyVTdYRzRnSUgxY2JseHVJQ0JzWlhRZ2RIVndiR1VnUFNCclpYbG1hVzVrS0d0bGVTd2diaXdnYkdsemRDazdYRzVjYmlBZ2NtVjBkWEp1SUc1bGR5QlVkWEJzWlNoMGRYQnNaUzVuWlhRb2Jpa3NJSFIxY0d4bExDQnJaWGxrWld4bGRHVW9hMlY1TENCdUxDQnNhWE4wS1NrN1hHNTlYRzVjYm1aMWJtTjBhVzl1SUd0bGVYSmxjR3hoWTJVb2EyVjVMQ0J1TENCc2FYTjBMQ0J1WlhkMGRYQnNaU2w3WEc0Z0lGeHVJQ0JtYjNJb2JHVjBJR2tnUFNCMGRYQnNaV3hwYzNRdWJHVnVaM1JvSUMwZ01Uc2dhU0ErUFNBd095QnBMUzBwZTF4dUlDQWdJR2xtS0hSMWNHeGxiR2x6ZEZ0cFhTNW5aWFFvYmlrZ1BUMDlJR3RsZVNsN1hHNGdJQ0FnSUNCeVpYUjFjbTRnZEhWd2JHVnNhWE4wTG1OdmJtTmhkQ2hiWFNrdWMzQnNhV05sS0drc0lERXNJRzVsZDNSMWNHeGxLVHRjYmlBZ0lDQjlYRzRnSUgxY2JseHVJQ0J5WlhSMWNtNGdkSFZ3YkdWc2FYTjBPMXh1ZlZ4dVhHNWNibVoxYm1OMGFXOXVJSEpsZG1WeWMyVW9iR2x6ZENsN1hHNGdJQ0FnY21WMGRYSnVJR3hwYzNRdVkyOXVZMkYwS0Z0ZEtTNXlaWFpsY25ObEtDazdYRzU5WEc1Y2JtWjFibU4wYVc5dUlHMWhjSE5mWm1sdVpDaHJaWGtzSUcxaGNDbDdYRzRnSUNBZ2FXWW9hMlY1SUdsdUlHZGxkRjl2WW1wbFkzUmZhMlY1Y3lodFlYQXBLWHRjYmlBZ0lDQWdJQ0FnY21WMGRYSnVJRzVsZHlCVWRYQnNaU2hUZVcxaWIyd3VabTl5S0Z3aWIydGNJaWtzSUcxaGNGdHJaWGxkS1R0Y2JpQWdJQ0I5Wld4elpYdGNiaUFnSUNBZ0lDQWdjbVYwZFhKdUlGTjViV0p2YkM1bWIzSW9YQ0psY25KdmNsd2lLVHRjYmlBZ0lDQjlYRzU5WEc1Y2JtWjFibU4wYVc5dUlHWnNZWFIwWlc0b2JHbHpkQ3dnZEdGcGJDQTlJRnRkS1NCN1hHNGdJR3hsZENCdVpYZGZiR2x6ZENBOUlGdGRPMXh1WEc0Z0lHWnZjaWhzWlhRZ1pTQnZaaUJzYVhOMEtYdGNiaUFnSUNCcFppaHBjMEZ5Y21GNUtHVXBLWHRjYmlBZ0lDQWdJRzVsZDE5c2FYTjBJRDBnYm1WM1gyeHBjM1F1WTI5dVkyRjBLR1pzWVhSMFpXNG9aU2twTzF4dUlDQWdJSDFsYkhObGUxeHVJQ0FnSUNBZ2JtVjNYMnhwYzNRdWNIVnphQ2hsS1R0Y2JpQWdJQ0I5WEc0Z0lIMWNibHh1SUNCeVpYUjFjbTRnVDJKcVpXTjBMbVp5WldWNlpTaHVaWGRmYkdsemRDNWpiMjVqWVhRb2RHRnBiQ2twTzF4dWZWeHVYRzVtZFc1amRHbHZiaUJrZFhCc2FXTmhkR1VvYml3Z1pXeGxiU2w3WEc0Z0lHeGxkQ0JzYVhOMElEMGdXMTA3WEc1Y2JpQWdabTl5S0d4bGRDQnBJRDBnTURzZ2FTQThJRzQ3SUdrckt5bDdYRzRnSUNBZ2JHbHpkQzV3ZFhOb0tHVnNaVzBwTzF4dUlDQjlYRzVjYmlBZ2NtVjBkWEp1SUU5aWFtVmpkQzVtY21WbGVtVW9iR2x6ZENrN1hHNTlYRzVjYm1aMWJtTjBhVzl1SUcxaGNHWnZiR1JzS0daMWJpd2dZV05qTENCc2FYTjBLWHRjYmlBZ2JHVjBJRzVsZDJ4cGMzUWdQU0JiWFR0Y2JseHVJQ0JtYjNJb2JHVjBJSGdnYjJZZ2JHbHpkQ2w3WEc0Z0lDQWdiR1YwSUhSMWNDQTlJR1oxYmloNExDQmhZMk1wTzF4dUlDQWdJRzVsZDJ4cGMzUXVjSFZ6YUNoMGRYQXVaMlYwS0RBcEtUdGNiaUFnSUNCaFkyTWdQU0IwZFhBdVoyVjBLREVwTzF4dUlDQjlYRzVjYmx4dUlDQnlaWFIxY200Z2JtVjNJRlIxY0d4bEtFOWlhbVZqZEM1bWNtVmxlbVVvYm1WM2JHbHpkQ2tzSUdGall5azdYRzU5WEc1Y2JtWjFibU4wYVc5dUlHWnBiSFJsY20xaGNDaG1kVzRzSUd4cGMzUXBlMXh1SUNCc1pYUWdibVYzYkdsemRDQTlJRnRkTzF4dVhHNGdJR1p2Y2loNElHOW1JR3hwYzNRcGUxeHVJQ0FnSUd4bGRDQnlaWE4xYkhRZ1BTQm1kVzRvZUNrN1hHNWNiaUFnSUNCcFppaHlaWE4xYkhRZ1BUMDlJSFJ5ZFdVcGUxeHVJQ0FnSUNBZ2JtVjNiR2x6ZEM1d2RYTm9LSGdwTzF4dUlDQWdJSDFsYkhObElHbG1LSEpsYzNWc2RDQnBibk4wWVc1alpXOW1JRlIxY0d4bEtYdGNiaUFnSUNBZ0lHNWxkMnhwYzNRdWNIVnphQ2h5WlhOMWJIUXVaMlYwS0RFcEtUdGNiaUFnSUNCOVhHNGdJSDFjYmx4dUlDQnlaWFIxY200Z1QySnFaV04wTG1aeVpXVjZaU2h1Wlhkc2FYTjBLVHRjYm4xY2JseHVablZ1WTNScGIyNGdiV0Z3YzE5bWIyeGtLR1oxYml3Z1lXTmpMQ0J0WVhBcGUxeHVJQ0JzWlhRZ1lXTmpNU0E5SUdGall6dGNibHh1SUNCbWIzSW9iR1YwSUdzZ2IyWWdaMlYwWDI5aWFtVmpkRjlyWlhsektHMWhjQ2twZTF4dUlDQWdJR0ZqWXpFZ1BTQm1kVzRvYXl3Z2JXRndXMnRkTENCaFkyTXhLVHRjYmlBZ2ZWeHVYRzRnSUhKbGRIVnliaUJoWTJNeE8xeHVmVnh1WEc1bWRXNWpkR2x2YmlCdFlYQnpYMlp5YjIxZmJHbHpkQ2hzYVhOMEtYdGNiaUFnYkdWMElHMGdQU0I3ZlR0Y2JseHVJQ0JtYjNJb2VDQnZaaUJzYVhOMEtYdGNiaUFnSUNCdFczZ3VaMlYwS0RBcFhTQTlJSGd1WjJWMEtERXBPMXh1SUNCOVhHNWNiaUFnY21WMGRYSnVJRTlpYW1WamRDNW1jbVZsZW1Vb2JTazdYRzU5WEc1Y2JtVjRjRzl5ZENCa1pXWmhkV3gwSUh0Y2JpQWdZMkZzYkY5d2NtOXdaWEowZVN4Y2JpQWdZWEJ3Ykhrc1hHNGdJR052Ym5SaGFXNXpMRnh1SUNCblpYUmZaMnh2WW1Gc0xGeHVJQ0JrWldaemRISjFZM1FzWEc0Z0lHUmxabVY0WTJWd2RHbHZiaXhjYmlBZ1pHVm1jSEp2ZEc5amIyd3NYRzRnSUdSbFptbHRjR3dzWEc0Z0lHZGxkRjl2WW1wbFkzUmZhMlY1Y3l4Y2JpQWdhWE5mZG1Gc2FXUmZZMmhoY21GamRHVnlMRnh1SUNCaU5qUkZibU52WkdWVmJtbGpiMlJsTEZ4dUlDQmtaV3hsZEdWZmNISnZjR1Z5ZEhsZlpuSnZiVjl0WVhBc1hHNGdJR0ZrWkY5d2NtOXdaWEowZVY5MGIxOXRZWEFzWEc0Z0lHTnNZWE56WDNSdlgyOWlhaXhjYmlBZ1kyRnVYMlJsWTI5a1pUWTBMRnh1SUNCaWJtOTBMRnh1SUNCaVlXNWtMRnh1SUNCaWIzSXNYRzRnSUdKemJDeGNiaUFnWW5OeUxGeHVJQ0JpZUc5eUxGeHVJQ0I2YVhBc1hHNGdJR1p2YkdSc0xGeHVJQ0JtYjJ4a2NpeGNiaUFnY21WdGIzWmxYMlp5YjIxZmJHbHpkQ3hjYmlBZ2EyVjVaR1ZzWlhSbExGeHVJQ0JyWlhsemRHOXlaU3hjYmlBZ2EyVjVabWx1WkN4Y2JpQWdhMlY1ZEdGclpTeGNiaUFnYTJWNWNtVndiR0ZqWlN4Y2JpQWdjbVYyWlhKelpTeGNiaUFnZFhCa1lYUmxYMjFoY0N4Y2JpQWdiV0Z3YzE5bWFXNWtMRnh1SUNCbWJHRjBkR1Z1TEZ4dUlDQmtkWEJzYVdOaGRHVXNYRzRnSUcxaGNHWnZiR1JzTEZ4dUlDQm1hV3gwWlhKdFlYQXNYRzRnSUcxaGNITmZabTlzWkZ4dWZUdGNiaUpkTENKemIzVnlZMlZTYjI5MElqb2lMM052ZFhKalpTOGlmUT09XG4iLCJpbXBvcnQgQml0U3RyaW5nIGZyb20gJy4vYml0X3N0cmluZyc7XG5pbXBvcnQgUGF0dGVybnMgZnJvbSAnLi9wYXR0ZXJucyc7XG5pbXBvcnQgeyBUdXBsZSB9IGZyb20gJy4vcHJpbWl0aXZlcyc7XG5cbmZ1bmN0aW9uIF9jYXNlKGNvbmRpdGlvbiwgY2xhdXNlcykge1xuICByZXR1cm4gUGF0dGVybnMuZGVmbWF0Y2goLi4uY2xhdXNlcykoY29uZGl0aW9uKTtcbn1cblxuZnVuY3Rpb24gY29uZChjbGF1c2VzKSB7XG4gIGZvciAobGV0IGNsYXVzZSBvZiBjbGF1c2VzKSB7XG4gICAgaWYgKGNsYXVzZVswXSkge1xuICAgICAgcmV0dXJuIGNsYXVzZVsxXSgpO1xuICAgIH1cbiAgfVxuXG4gIHRocm93IG5ldyBFcnJvcigpO1xufVxuXG5mdW5jdGlvbiBtYXBfdXBkYXRlKG1hcCwgdmFsdWVzKSB7XG4gIHJldHVybiBPYmplY3QuZnJlZXplKE9iamVjdC5hc3NpZ24oT2JqZWN0LmNyZWF0ZShtYXAuY29uc3RydWN0b3IucHJvdG90eXBlKSwgbWFwLCB2YWx1ZXMpKTtcbn1cblxuZnVuY3Rpb24gX2Zvcihjb2xsZWN0aW9ucywgZnVuLCBmaWx0ZXIgPSAoKSA9PiB0cnVlLCBpbnRvID0gW10sIHByZXZpb3VzVmFsdWVzID0gW10pIHtcbiAgbGV0IHBhdHRlcm4gPSBjb2xsZWN0aW9uc1swXVswXTtcbiAgbGV0IGNvbGxlY3Rpb24gPSBjb2xsZWN0aW9uc1swXVsxXTtcblxuICBpZiAoY29sbGVjdGlvbnMubGVuZ3RoID09PSAxKSB7XG4gICAgaWYgKGNvbGxlY3Rpb24gaW5zdGFuY2VvZiBCaXRTdHJpbmcpIHtcbiAgICAgIGxldCBic1NsaWNlID0gY29sbGVjdGlvbi5zbGljZSgwLCBwYXR0ZXJuLmJ5dGVfc2l6ZSgpKTtcbiAgICAgIGxldCBpID0gMTtcblxuICAgICAgd2hpbGUgKGJzU2xpY2UuYnl0ZV9zaXplID09IHBhdHRlcm4uYnl0ZV9zaXplKCkpIHtcbiAgICAgICAgbGV0IHIgPSBQYXR0ZXJucy5tYXRjaF9ub190aHJvdyhwYXR0ZXJuLCBic1NsaWNlKTtcbiAgICAgICAgbGV0IGFyZ3MgPSBwcmV2aW91c1ZhbHVlcy5jb25jYXQocik7XG5cbiAgICAgICAgaWYgKHIgJiYgZmlsdGVyLmFwcGx5KHRoaXMsIGFyZ3MpKSB7XG4gICAgICAgICAgaW50byA9IGludG8uY29uY2F0KFtmdW4uYXBwbHkodGhpcywgYXJncyldKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGJzU2xpY2UgPSBjb2xsZWN0aW9uLnNsaWNlKHBhdHRlcm4uYnl0ZV9zaXplKCkgKiBpLCBwYXR0ZXJuLmJ5dGVfc2l6ZSgpICogKGkgKyAxKSk7XG4gICAgICAgIGkrKztcbiAgICAgIH1cblxuICAgICAgcmV0dXJuIGludG87XG4gICAgfSBlbHNlIHtcbiAgICAgIGZvciAobGV0IGVsZW0gb2YgY29sbGVjdGlvbikge1xuICAgICAgICBsZXQgciA9IFBhdHRlcm5zLm1hdGNoX25vX3Rocm93KHBhdHRlcm4sIGVsZW0pO1xuICAgICAgICBsZXQgYXJncyA9IHByZXZpb3VzVmFsdWVzLmNvbmNhdChyKTtcblxuICAgICAgICBpZiAociAmJiBmaWx0ZXIuYXBwbHkodGhpcywgYXJncykpIHtcbiAgICAgICAgICBpbnRvID0gaW50by5jb25jYXQoW2Z1bi5hcHBseSh0aGlzLCBhcmdzKV0pO1xuICAgICAgICB9XG4gICAgICB9XG5cbiAgICAgIHJldHVybiBpbnRvO1xuICAgIH1cbiAgfSBlbHNlIHtcbiAgICBsZXQgX2ludG8gPSBbXTtcblxuICAgIGlmIChjb2xsZWN0aW9uIGluc3RhbmNlb2YgQml0U3RyaW5nKSB7XG4gICAgICBsZXQgYnNTbGljZSA9IGNvbGxlY3Rpb24uc2xpY2UoMCwgcGF0dGVybi5ieXRlX3NpemUoKSk7XG4gICAgICBsZXQgaSA9IDE7XG5cbiAgICAgIHdoaWxlIChic1NsaWNlLmJ5dGVfc2l6ZSA9PSBwYXR0ZXJuLmJ5dGVfc2l6ZSgpKSB7XG4gICAgICAgIGxldCByID0gUGF0dGVybnMubWF0Y2hfbm9fdGhyb3cocGF0dGVybiwgYnNTbGljZSk7XG4gICAgICAgIGlmIChyKSB7XG4gICAgICAgICAgX2ludG8gPSBpbnRvLmNvbmNhdCh0aGlzLl9mb3IoY29sbGVjdGlvbnMuc2xpY2UoMSksIGZ1biwgZmlsdGVyLCBfaW50bywgcHJldmlvdXNWYWx1ZXMuY29uY2F0KHIpKSk7XG4gICAgICAgIH1cblxuICAgICAgICBic1NsaWNlID0gY29sbGVjdGlvbi5zbGljZShwYXR0ZXJuLmJ5dGVfc2l6ZSgpICogaSwgcGF0dGVybi5ieXRlX3NpemUoKSAqIChpICsgMSkpO1xuICAgICAgICBpKys7XG4gICAgICB9XG4gICAgfSBlbHNlIHtcbiAgICAgIGZvciAobGV0IGVsZW0gb2YgY29sbGVjdGlvbikge1xuICAgICAgICBsZXQgciA9IFBhdHRlcm5zLm1hdGNoX25vX3Rocm93KHBhdHRlcm4sIGVsZW0pO1xuICAgICAgICBpZiAocikge1xuICAgICAgICAgIF9pbnRvID0gaW50by5jb25jYXQodGhpcy5fZm9yKGNvbGxlY3Rpb25zLnNsaWNlKDEpLCBmdW4sIGZpbHRlciwgX2ludG8sIHByZXZpb3VzVmFsdWVzLmNvbmNhdChyKSkpO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgfVxuXG4gICAgcmV0dXJuIF9pbnRvO1xuICB9XG59XG5cbmZ1bmN0aW9uIF90cnkoZG9fZnVuLCByZXNjdWVfZnVuY3Rpb24sIGNhdGNoX2Z1biwgZWxzZV9mdW5jdGlvbiwgYWZ0ZXJfZnVuY3Rpb24pIHtcbiAgbGV0IHJlc3VsdCA9IG51bGw7XG5cbiAgdHJ5IHtcbiAgICByZXN1bHQgPSBkb19mdW4oKTtcbiAgfSBjYXRjaCAoZSkge1xuICAgIGxldCBleF9yZXN1bHQgPSBudWxsO1xuXG4gICAgaWYgKHJlc2N1ZV9mdW5jdGlvbikge1xuICAgICAgdHJ5IHtcbiAgICAgICAgZXhfcmVzdWx0ID0gcmVzY3VlX2Z1bmN0aW9uKGUpO1xuICAgICAgICByZXR1cm4gZXhfcmVzdWx0O1xuICAgICAgfSBjYXRjaCAoZXgpIHtcbiAgICAgICAgaWYgKGV4IGluc3RhbmNlb2YgUGF0dGVybnMuTWF0Y2hFcnJvcikge1xuICAgICAgICAgIHRocm93IGV4O1xuICAgICAgICB9XG4gICAgICB9XG4gICAgfVxuXG4gICAgaWYgKGNhdGNoX2Z1bikge1xuICAgICAgdHJ5IHtcbiAgICAgICAgZXhfcmVzdWx0ID0gY2F0Y2hfZnVuKGUpO1xuICAgICAgICByZXR1cm4gZXhfcmVzdWx0O1xuICAgICAgfSBjYXRjaCAoZXgpIHtcbiAgICAgICAgaWYgKGV4IGluc3RhbmNlb2YgUGF0dGVybnMuTWF0Y2hFcnJvcikge1xuICAgICAgICAgIHRocm93IGV4O1xuICAgICAgICB9XG4gICAgICB9XG4gICAgfVxuXG4gICAgdGhyb3cgZTtcbiAgfSBmaW5hbGx5IHtcbiAgICBpZiAoYWZ0ZXJfZnVuY3Rpb24pIHtcbiAgICAgIGFmdGVyX2Z1bmN0aW9uKCk7XG4gICAgfVxuICB9XG5cbiAgaWYgKGVsc2VfZnVuY3Rpb24pIHtcbiAgICB0cnkge1xuICAgICAgcmV0dXJuIGVsc2VfZnVuY3Rpb24ocmVzdWx0KTtcbiAgICB9IGNhdGNoIChleCkge1xuICAgICAgaWYgKGV4IGluc3RhbmNlb2YgUGF0dGVybnMuTWF0Y2hFcnJvcikge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoXCJObyBNYXRjaCBGb3VuZCBpbiBFbHNlXCIpO1xuICAgICAgfVxuXG4gICAgICB0aHJvdyBleDtcbiAgICB9XG4gIH0gZWxzZSB7XG4gICAgcmV0dXJuIHJlc3VsdDtcbiAgfVxufVxuXG5mdW5jdGlvbiBfd2l0aCguLi5hcmdzKSB7XG4gIGxldCBhcmdzVG9QYXNzID0gW107XG5cbiAgZm9yIChsZXQgaSA9IDA7IGkgPCBhcmdzLmxlbmd0aDsgaSsrKSB7XG4gICAgaWYgKGkgPT09IGFyZ3MubGVuZ3RoIC0gMSkge1xuICAgICAgcmV0dXJuIGFyZ3NbaV0uYXBwbHkobnVsbCwgYXJnc1RvUGFzcyk7XG4gICAgfSBlbHNlIHtcbiAgICAgIGxldCBbcGF0dGVybiwgZnVuY10gPSBhcmdzW2ldO1xuXG4gICAgICBsZXQgcmVzdWx0ID0gZnVuYy5hcHBseShudWxsLCBhcmdzVG9QYXNzKTtcblxuICAgICAgbGV0IHBhdHRlcm5SZXN1bHQgPSBQYXR0ZXJucy5tYXRjaF9ub190aHJvdyhwYXR0ZXJuLCByZXN1bHQpO1xuXG4gICAgICBpZiAocGF0dGVyblJlc3VsdCA9PSBudWxsKSB7XG4gICAgICAgIHJldHVybiByZXN1bHQ7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBhcmdzVG9QYXNzID0gYXJnc1RvUGFzcy5jb25jYXQocGF0dGVyblJlc3VsdCk7XG4gICAgICB9XG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIG51bGw7XG59XG5cbmV4cG9ydCBkZWZhdWx0IHtcbiAgX2Nhc2UsXG4gIGNvbmQsXG4gIG1hcF91cGRhdGUsXG4gIF9mb3IsXG4gIF90cnksXG4gIF93aXRoXG59O1xuLy8jIHNvdXJjZU1hcHBpbmdVUkw9ZGF0YTphcHBsaWNhdGlvbi9qc29uO2Jhc2U2NCxleUoyWlhKemFXOXVJam96TENKemIzVnlZMlZ6SWpwYklteHBZaTlqYjNKbEwzTndaV05wWVd4ZlptOXliWE11YW5NaVhTd2libUZ0WlhNaU9sdGRMQ0p0WVhCd2FXNW5jeUk2SWtGQlFVRXNUMEZCVHl4VFFVRlFMRTFCUVhOQ0xHTkJRWFJDTzBGQlEwRXNUMEZCVHl4UlFVRlFMRTFCUVhGQ0xGbEJRWEpDTzBGQlEwRXNVMEZCVXl4TFFVRlVMRkZCUVhOQ0xHTkJRWFJDT3p0QlFVVkJMRk5CUVZNc1MwRkJWQ3hEUVVGbExGTkJRV1lzUlVGQk1FSXNUMEZCTVVJc1JVRkJhME03UVVGRGFFTXNVMEZCVHl4VFFVRlRMRkZCUVZRc1EwRkJhMElzUjBGQlJ5eFBRVUZJTEVOQlFXeENMRU5CUVRoQ0xGTkJRVGxDTEVOQlFWQXNRMEZFWjBNN1EwRkJiRU03TzBGQlNVRXNVMEZCVXl4SlFVRlVMRU5CUVdNc1QwRkJaQ3hGUVVGelFqdEJRVU53UWl4UFFVRkpMRWxCUVVrc1RVRkJTaXhKUVVGakxFOUJRV3hDTEVWQlFUQkNPMEZCUTNoQ0xGRkJRVWNzVDBGQlR5eERRVUZRTEVOQlFVZ3NSVUZCWVR0QlFVTllMR0ZCUVU4c1QwRkJUeXhEUVVGUUxFZEJRVkFzUTBGRVZ6dExRVUZpTzBkQlJFWTdPMEZCVFVFc1VVRkJUU3hKUVVGSkxFdEJRVW9zUlVGQlRpeERRVkJ2UWp0RFFVRjBRanM3UVVGVlFTeFRRVUZUTEZWQlFWUXNRMEZCYjBJc1IwRkJjRUlzUlVGQmVVSXNUVUZCZWtJc1JVRkJaME03UVVGRE9VSXNVMEZCVHl4UFFVRlBMRTFCUVZBc1EwRkRUQ3hQUVVGUExFMUJRVkFzUTBGRFJTeFBRVUZQTEUxQlFWQXNRMEZCWXl4SlFVRkpMRmRCUVVvc1EwRkJaMElzVTBGQmFFSXNRMEZFYUVJc1JVRkRORU1zUjBGRU5VTXNSVUZEYVVRc1RVRkVha1FzUTBGRVN5eERRVUZRTEVOQlJEaENPME5CUVdoRE96dEJRVkZCTEZOQlFWTXNTVUZCVkN4RFFVRmpMRmRCUVdRc1JVRkJNa0lzUjBGQk0wSXNSVUZCWjBNc1UwRkJVeXhOUVVGTkxFbEJRVTRzUlVGQldTeFBRVUZQTEVWQlFWQXNSVUZCVnl4cFFrRkJhVUlzUlVGQmFrSXNSVUZCYjBJN1FVRkRiRVlzVFVGQlNTeFZRVUZWTEZsQlFWa3NRMEZCV2l4RlFVRmxMRU5CUVdZc1EwRkJWaXhEUVVRNFJUdEJRVVZzUml4TlFVRkpMR0ZCUVdFc1dVRkJXU3hEUVVGYUxFVkJRV1VzUTBGQlppeERRVUZpTEVOQlJqaEZPenRCUVVsc1JpeE5RVUZITEZsQlFWa3NUVUZCV2l4TFFVRjFRaXhEUVVGMlFpeEZRVUY1UWp0QlFVTXhRaXhSUVVGSExITkNRVUZ6UWl4VFFVRjBRaXhGUVVGblF6dEJRVU5xUXl4VlFVRkpMRlZCUVZVc1YwRkJWeXhMUVVGWUxFTkJRV2xDTEVOQlFXcENMRVZCUVc5Q0xGRkJRVkVzVTBGQlVpeEZRVUZ3UWl4RFFVRldMRU5CUkRaQ08wRkJSV3BETEZWQlFVa3NTVUZCU1N4RFFVRktMRU5CUmpaQ096dEJRVWxxUXl4aFFVRk5MRkZCUVZFc1UwRkJVaXhKUVVGeFFpeFJRVUZSTEZOQlFWSXNSVUZCY2tJc1JVRkJlVU03UVVGRE4wTXNXVUZCU1N4SlFVRkpMRk5CUVZNc1kwRkJWQ3hEUVVGM1FpeFBRVUY0UWl4RlFVRnBReXhQUVVGcVF5eERRVUZLTEVOQlJIbERPMEZCUlRkRExGbEJRVWtzVDBGQlR5eGxRVUZsTEUxQlFXWXNRMEZCYzBJc1EwRkJkRUlzUTBGQlVDeERRVVo1UXpzN1FVRkpOME1zV1VGQlJ5eExRVUZMTEU5QlFVOHNTMEZCVUN4RFFVRmhMRWxCUVdJc1JVRkJiVUlzU1VGQmJrSXNRMEZCVEN4RlFVRTRRanRCUVVNdlFpeHBRa0ZCVHl4TFFVRkxMRTFCUVV3c1EwRkJXU3hEUVVGRExFbEJRVWtzUzBGQlNpeERRVUZWTEVsQlFWWXNSVUZCWjBJc1NVRkJhRUlzUTBGQlJDeERRVUZhTEVOQlFWQXNRMEZFSzBJN1UwRkJha003TzBGQlNVRXNhMEpCUVZVc1YwRkJWeXhMUVVGWUxFTkJRV2xDTEZGQlFWRXNVMEZCVWl4TFFVRnpRaXhEUVVGMFFpeEZRVUY1UWl4UlFVRlJMRk5CUVZJc1RVRkJkVUlzU1VGQlNTeERRVUZLTEVOQlFYWkNMRU5CUVhCRUxFTkJValpETzBGQlV6ZERMRmxCVkRaRE8wOUJRUzlET3p0QlFWbEJMR0ZCUVU4c1NVRkJVQ3hEUVdoQ2FVTTdTMEZCYmtNc1RVRnBRa3M3UVVGRFNDeFhRVUZKTEVsQlFVa3NTVUZCU2l4SlFVRlpMRlZCUVdoQ0xFVkJRVEpDTzBGQlEzcENMRmxCUVVrc1NVRkJTU3hUUVVGVExHTkJRVlFzUTBGQmQwSXNUMEZCZUVJc1JVRkJhVU1zU1VGQmFrTXNRMEZCU2l4RFFVUnhRanRCUVVWNlFpeFpRVUZKTEU5QlFVOHNaVUZCWlN4TlFVRm1MRU5CUVhOQ0xFTkJRWFJDTEVOQlFWQXNRMEZHY1VJN08wRkJTWHBDTEZsQlFVY3NTMEZCU3l4UFFVRlBMRXRCUVZBc1EwRkJZU3hKUVVGaUxFVkJRVzFDTEVsQlFXNUNMRU5CUVV3c1JVRkJPRUk3UVVGREwwSXNhVUpCUVU4c1MwRkJTeXhOUVVGTUxFTkJRVmtzUTBGQlF5eEpRVUZKTEV0QlFVb3NRMEZCVlN4SlFVRldMRVZCUVdkQ0xFbEJRV2hDTEVOQlFVUXNRMEZCV2l4RFFVRlFMRU5CUkN0Q08xTkJRV3BETzA5QlNrWTdPMEZCVTBFc1lVRkJUeXhKUVVGUUxFTkJWa2M3UzBGcVFrdzdSMEZFUml4TlFUaENTenRCUVVOSUxGRkJRVWtzVVVGQlVTeEZRVUZTTEVOQlJFUTdPMEZCUjBnc1VVRkJSeXh6UWtGQmMwSXNVMEZCZEVJc1JVRkJaME03UVVGRGFrTXNWVUZCU1N4VlFVRlZMRmRCUVZjc1MwRkJXQ3hEUVVGcFFpeERRVUZxUWl4RlFVRnZRaXhSUVVGUkxGTkJRVklzUlVGQmNFSXNRMEZCVml4RFFVUTJRanRCUVVWcVF5eFZRVUZKTEVsQlFVa3NRMEZCU2l4RFFVWTJRanM3UVVGSmFrTXNZVUZCVFN4UlFVRlJMRk5CUVZJc1NVRkJjVUlzVVVGQlVTeFRRVUZTTEVWQlFYSkNMRVZCUVhsRE8wRkJRemRETEZsQlFVa3NTVUZCU1N4VFFVRlRMR05CUVZRc1EwRkJkMElzVDBGQmVFSXNSVUZCYVVNc1QwRkJha01zUTBGQlNpeERRVVI1UXp0QlFVVTNReXhaUVVGSExFTkJRVWdzUlVGQlN6dEJRVU5JTEd0Q1FVRlJMRXRCUVVzc1RVRkJUQ3hEUVVGWkxFdEJRVXNzU1VGQlRDeERRVUZWTEZsQlFWa3NTMEZCV2l4RFFVRnJRaXhEUVVGc1FpeERRVUZXTEVWQlFXZERMRWRCUVdoRExFVkJRWEZETEUxQlFYSkRMRVZCUVRaRExFdEJRVGRETEVWQlFXOUVMR1ZCUVdVc1RVRkJaaXhEUVVGelFpeERRVUYwUWl4RFFVRndSQ3hEUVVGYUxFTkJRVklzUTBGRVJ6dFRRVUZNT3p0QlFVbEJMR3RDUVVGVkxGZEJRVmNzUzBGQldDeERRVUZwUWl4UlFVRlJMRk5CUVZJc1MwRkJjMElzUTBGQmRFSXNSVUZCZVVJc1VVRkJVU3hUUVVGU0xFMUJRWFZDTEVsQlFVa3NRMEZCU2l4RFFVRjJRaXhEUVVGd1JDeERRVTQyUXp0QlFVODNReXhaUVZBMlF6dFBRVUV2UXp0TFFVcEdMRTFCWVVzN1FVRkRTQ3hYUVVGSkxFbEJRVWtzU1VGQlNpeEpRVUZaTEZWQlFXaENMRVZCUVRKQ08wRkJRM3BDTEZsQlFVa3NTVUZCU1N4VFFVRlRMR05CUVZRc1EwRkJkMElzVDBGQmVFSXNSVUZCYVVNc1NVRkJha01zUTBGQlNpeERRVVJ4UWp0QlFVVjZRaXhaUVVGSExFTkJRVWdzUlVGQlN6dEJRVU5JTEd0Q1FVRlJMRXRCUVVzc1RVRkJUQ3hEUVVGWkxFdEJRVXNzU1VGQlRDeERRVUZWTEZsQlFWa3NTMEZCV2l4RFFVRnJRaXhEUVVGc1FpeERRVUZXTEVWQlFXZERMRWRCUVdoRExFVkJRWEZETEUxQlFYSkRMRVZCUVRaRExFdEJRVGRETEVWQlFXOUVMR1ZCUVdVc1RVRkJaaXhEUVVGelFpeERRVUYwUWl4RFFVRndSQ3hEUVVGYUxFTkJRVklzUTBGRVJ6dFRRVUZNTzA5QlJrWTdTMEZrUmpzN1FVRnpRa0VzVjBGQlR5eExRVUZRTEVOQmVrSkhPMGRCT1VKTU8wTkJTa1k3TzBGQkswUkJMRk5CUVZNc1NVRkJWQ3hEUVVGakxFMUJRV1FzUlVGQmMwSXNaVUZCZEVJc1JVRkJkVU1zVTBGQmRrTXNSVUZCYTBRc1lVRkJiRVFzUlVGQmFVVXNZMEZCYWtVc1JVRkJaMFk3UVVGRE9VVXNUVUZCU1N4VFFVRlRMRWxCUVZRc1EwRkVNRVU3TzBGQlJ6bEZMRTFCUVVjN1FVRkRSQ3hoUVVGVExGRkJRVlFzUTBGRVF6dEhRVUZJTEVOQlJVTXNUMEZCVFN4RFFVRk9MRVZCUVZFN1FVRkRVQ3hSUVVGSkxGbEJRVmtzU1VGQldpeERRVVJIT3p0QlFVZFFMRkZCUVVjc1pVRkJTQ3hGUVVGdFFqdEJRVU5xUWl4VlFVRkhPMEZCUTBRc2IwSkJRVmtzWjBKQlFXZENMRU5CUVdoQ0xFTkJRVm9zUTBGRVF6dEJRVVZFTEdWQlFVOHNVMEZCVUN4RFFVWkRPMDlCUVVnc1EwRkhReXhQUVVGTkxFVkJRVTRzUlVGQlV6dEJRVU5TTEZsQlFVY3NZMEZCWXl4VFFVRlRMRlZCUVZRc1JVRkJiMEk3UVVGRGJrTXNaMEpCUVUwc1JVRkJUaXhEUVVSdFF6dFRRVUZ5UXp0UFFVUkVPMHRCU2tnN08wRkJWMEVzVVVGQlJ5eFRRVUZJTEVWQlFXRTdRVUZEV0N4VlFVRkhPMEZCUTBRc2IwSkJRVmtzVlVGQlZTeERRVUZXTEVOQlFWb3NRMEZFUXp0QlFVVkVMR1ZCUVU4c1UwRkJVQ3hEUVVaRE8wOUJRVWdzUTBGSFF5eFBRVUZOTEVWQlFVNHNSVUZCVXp0QlFVTlNMRmxCUVVjc1kwRkJZeXhUUVVGVExGVkJRVlFzUlVGQmIwSTdRVUZEYmtNc1owSkJRVTBzUlVGQlRpeERRVVJ0UXp0VFFVRnlRenRQUVVSRU8wdEJTa2c3TzBGQlYwRXNWVUZCVFN4RFFVRk9MRU5CZWtKUE8wZEJRVklzVTBFeVFrODdRVUZEVGl4UlFVRkhMR05CUVVnc1JVRkJhMEk3UVVGRGFFSXNkVUpCUkdkQ08wdEJRV3hDTzBkQk9VSkdPenRCUVcxRFFTeE5RVUZITEdGQlFVZ3NSVUZCYVVJN1FVRkRaaXhSUVVGSE8wRkJRMFFzWVVGQlR5eGpRVUZqTEUxQlFXUXNRMEZCVUN4RFFVUkRPMHRCUVVnc1EwRkZReXhQUVVGTkxFVkJRVTRzUlVGQlV6dEJRVU5PTEZWQlFVY3NZMEZCWXl4VFFVRlRMRlZCUVZRc1JVRkJiMEk3UVVGRGJrTXNZMEZCVFN4SlFVRkpMRXRCUVVvc1EwRkJWU3gzUWtGQlZpeERRVUZPTEVOQlJHMURPMDlCUVhKRE96dEJRVWxHTEZsQlFVMHNSVUZCVGl4RFFVeFJPMHRCUVZRN1IwRklTQ3hOUVZWTE8wRkJRMGdzVjBGQlR5eE5RVUZRTEVOQlJFYzdSMEZXVER0RFFYUkRSanM3UVVGeFJFRXNVMEZCVXl4TFFVRlVMRU5CUVdVc1IwRkJSeXhKUVVGSUxFVkJRVkU3UVVGRGNrSXNUVUZCU1N4aFFVRmhMRVZCUVdJc1EwRkVhVUk3TzBGQlIzSkNMRTlCUVVrc1NVRkJTU3hKUVVGSkxFTkJRVW9zUlVGQlR5eEpRVUZKTEV0QlFVc3NUVUZCVEN4RlFVRmhMRWRCUVdoRExFVkJRVzlETzBGQlEyeERMRkZCUVVjc1RVRkJUU3hMUVVGTExFMUJRVXdzUjBGQll5eERRVUZrTEVWQlFXZENPMEZCUTNaQ0xHRkJRVThzUzBGQlN5eERRVUZNTEVWQlFWRXNTMEZCVWl4RFFVRmpMRWxCUVdRc1JVRkJiMElzVlVGQmNFSXNRMEZCVUN4RFFVUjFRanRMUVVGNlFpeE5RVVZMTzBGQlEwZ3NWVUZCU1N4RFFVRkRMRTlCUVVRc1JVRkJWU3hKUVVGV0xFbEJRV3RDTEV0QlFVc3NRMEZCVEN4RFFVRnNRaXhEUVVSRU96dEJRVWRJTEZWQlFVa3NVMEZCVXl4TFFVRkxMRXRCUVV3c1EwRkJWeXhKUVVGWUxFVkJRV2xDTEZWQlFXcENMRU5CUVZRc1EwRklSRHM3UVVGTFNDeFZRVUZKTEdkQ1FVRm5RaXhUUVVGVExHTkJRVlFzUTBGQmQwSXNUMEZCZUVJc1JVRkJhVU1zVFVGQmFrTXNRMEZCYUVJc1EwRk1SRHM3UVVGUFNDeFZRVUZITEdsQ1FVRnBRaXhKUVVGcVFpeEZRVUZ6UWp0QlFVTjJRaXhsUVVGUExFMUJRVkFzUTBGRWRVSTdUMEZCZWtJc1RVRkZTenRCUVVOSUxIRkNRVUZoTEZkQlFWY3NUVUZCV0N4RFFVRnJRaXhoUVVGc1FpeERRVUZpTEVOQlJFYzdUMEZHVER0TFFWUkdPMGRCUkVZN08wRkJhMEpCTEZOQlFVOHNTVUZCVUN4RFFYSkNjVUk3UTBGQmRrSTdPMEZCZDBKQkxHVkJRV1U3UVVGRFlpeFBRVVJoTzBGQlJXSXNUVUZHWVR0QlFVZGlMRmxCU0dFN1FVRkpZaXhOUVVwaE8wRkJTMklzVFVGTVlUdEJRVTFpTEU5QlRtRTdRMEZCWmlJc0ltWnBiR1VpT2lKc2FXSXZZMjl5WlM5emNHVmphV0ZzWDJadmNtMXpMbXB6SWl3aWMyOTFjbU5sYzBOdmJuUmxiblFpT2xzaWFXMXdiM0owSUVKcGRGTjBjbWx1WnlCbWNtOXRJQ2N1TDJKcGRGOXpkSEpwYm1jbk8xeHVhVzF3YjNKMElGQmhkSFJsY201eklHWnliMjBnSnk0dmNHRjBkR1Z5Ym5Nbk8xeHVhVzF3YjNKMElIc2dWSFZ3YkdVZ2ZTQm1jbTl0SUNjdUwzQnlhVzFwZEdsMlpYTW5PMXh1WEc1bWRXNWpkR2x2YmlCZlkyRnpaU2hqYjI1a2FYUnBiMjRzSUdOc1lYVnpaWE1wZTF4dUlDQnlaWFIxY200Z1VHRjBkR1Z5Ym5NdVpHVm1iV0YwWTJnb0xpNHVZMnhoZFhObGN5a29ZMjl1WkdsMGFXOXVLVHRjYm4xY2JseHVablZ1WTNScGIyNGdZMjl1WkNoamJHRjFjMlZ6S1h0Y2JpQWdabTl5S0d4bGRDQmpiR0YxYzJVZ2IyWWdZMnhoZFhObGN5bDdYRzRnSUNBZ2FXWW9ZMnhoZFhObFd6QmRLWHRjYmlBZ0lDQWdJSEpsZEhWeWJpQmpiR0YxYzJWYk1WMG9LVHRjYmlBZ0lDQjlYRzRnSUgxY2JseHVJQ0IwYUhKdmR5QnVaWGNnUlhKeWIzSW9LVHRjYm4xY2JseHVablZ1WTNScGIyNGdiV0Z3WDNWd1pHRjBaU2h0WVhBc0lIWmhiSFZsY3lsN1hHNGdJSEpsZEhWeWJpQlBZbXBsWTNRdVpuSmxaWHBsS0Z4dUlDQWdJRTlpYW1WamRDNWhjM05wWjI0b1hHNGdJQ0FnSUNCUFltcGxZM1F1WTNKbFlYUmxLRzFoY0M1amIyNXpkSEoxWTNSdmNpNXdjbTkwYjNSNWNHVXBMQ0J0WVhBc0lIWmhiSFZsYzF4dUlDQWdJQ2xjYmlBZ0tUdGNibjFjYmx4dVpuVnVZM1JwYjI0Z1gyWnZjaWhqYjJ4c1pXTjBhVzl1Y3l3Z1puVnVMQ0JtYVd4MFpYSWdQU0FvS1NBOVBpQjBjblZsTENCcGJuUnZJRDBnVzEwc0lIQnlaWFpwYjNWelZtRnNkV1Z6SUQwZ1cxMHBlMXh1SUNCc1pYUWdjR0YwZEdWeWJpQTlJR052Ykd4bFkzUnBiMjV6V3pCZFd6QmRPMXh1SUNCc1pYUWdZMjlzYkdWamRHbHZiaUE5SUdOdmJHeGxZM1JwYjI1eld6QmRXekZkTzF4dVhHNGdJR2xtS0dOdmJHeGxZM1JwYjI1ekxteGxibWQwYUNBOVBUMGdNU2w3WEc0Z0lDQWdhV1lvWTI5c2JHVmpkR2x2YmlCcGJuTjBZVzVqWlc5bUlFSnBkRk4wY21sdVp5bDdYRzRnSUNBZ0lDQnNaWFFnWW5OVGJHbGpaU0E5SUdOdmJHeGxZM1JwYjI0dWMyeHBZMlVvTUN3Z2NHRjBkR1Z5Ymk1aWVYUmxYM05wZW1Vb0tTazdYRzRnSUNBZ0lDQnNaWFFnYVNBOUlERTdYRzVjYmlBZ0lDQWdJSGRvYVd4bEtHSnpVMnhwWTJVdVlubDBaVjl6YVhwbElEMDlJSEJoZEhSbGNtNHVZbmwwWlY5emFYcGxLQ2twZTF4dUlDQWdJQ0FnSUNCc1pYUWdjaUE5SUZCaGRIUmxjbTV6TG0xaGRHTm9YMjV2WDNSb2NtOTNLSEJoZEhSbGNtNHNJR0p6VTJ4cFkyVXBPMXh1SUNBZ0lDQWdJQ0JzWlhRZ1lYSm5jeUE5SUhCeVpYWnBiM1Z6Vm1Gc2RXVnpMbU52Ym1OaGRDaHlLVHRjYmx4dUlDQWdJQ0FnSUNCcFppaHlJQ1ltSUdacGJIUmxjaTVoY0hCc2VTaDBhR2x6TENCaGNtZHpLU2w3WEc0Z0lDQWdJQ0FnSUNBZ2FXNTBieUE5SUdsdWRHOHVZMjl1WTJGMEtGdG1kVzR1WVhCd2JIa29kR2hwY3l3Z1lYSm5jeWxkS1R0Y2JpQWdJQ0FnSUNBZ2ZWeHVYRzRnSUNBZ0lDQWdJR0p6VTJ4cFkyVWdQU0JqYjJ4c1pXTjBhVzl1TG5Oc2FXTmxLSEJoZEhSbGNtNHVZbmwwWlY5emFYcGxLQ2tnS2lCcExDQndZWFIwWlhKdUxtSjVkR1ZmYzJsNlpTZ3BJQ29nS0drZ0t5QXhLU2s3WEc0Z0lDQWdJQ0FnSUdrckt6dGNiaUFnSUNBZ0lIMWNibHh1SUNBZ0lDQWdjbVYwZFhKdUlHbHVkRzg3WEc0Z0lDQWdmV1ZzYzJWN1hHNGdJQ0FnSUNCbWIzSW9iR1YwSUdWc1pXMGdiMllnWTI5c2JHVmpkR2x2YmlsN1hHNGdJQ0FnSUNBZ0lHeGxkQ0J5SUQwZ1VHRjBkR1Z5Ym5NdWJXRjBZMmhmYm05ZmRHaHliM2NvY0dGMGRHVnliaXdnWld4bGJTazdYRzRnSUNBZ0lDQWdJR3hsZENCaGNtZHpJRDBnY0hKbGRtbHZkWE5XWVd4MVpYTXVZMjl1WTJGMEtISXBPMXh1WEc0Z0lDQWdJQ0FnSUdsbUtISWdKaVlnWm1sc2RHVnlMbUZ3Y0d4NUtIUm9hWE1zSUdGeVozTXBLWHRjYmlBZ0lDQWdJQ0FnSUNCcGJuUnZJRDBnYVc1MGJ5NWpiMjVqWVhRb1cyWjFiaTVoY0hCc2VTaDBhR2x6TENCaGNtZHpLVjBwTzF4dUlDQWdJQ0FnSUNCOVhHNGdJQ0FnSUNCOVhHNWNiaUFnSUNBZ0lISmxkSFZ5YmlCcGJuUnZPMXh1SUNBZ0lIMWNiaUFnZldWc2MyVjdYRzRnSUNBZ2JHVjBJRjlwYm5SdklEMGdXMTA3WEc1Y2JpQWdJQ0JwWmloamIyeHNaV04wYVc5dUlHbHVjM1JoYm1ObGIyWWdRbWwwVTNSeWFXNW5LWHRjYmlBZ0lDQWdJR3hsZENCaWMxTnNhV05sSUQwZ1kyOXNiR1ZqZEdsdmJpNXpiR2xqWlNnd0xDQndZWFIwWlhKdUxtSjVkR1ZmYzJsNlpTZ3BLVHRjYmlBZ0lDQWdJR3hsZENCcElEMGdNVHRjYmx4dUlDQWdJQ0FnZDJocGJHVW9Zbk5UYkdsalpTNWllWFJsWDNOcGVtVWdQVDBnY0dGMGRHVnliaTVpZVhSbFgzTnBlbVVvS1NsN1hHNGdJQ0FnSUNBZ0lHeGxkQ0J5SUQwZ1VHRjBkR1Z5Ym5NdWJXRjBZMmhmYm05ZmRHaHliM2NvY0dGMGRHVnliaXdnWW5OVGJHbGpaU2s3WEc0Z0lDQWdJQ0FnSUdsbUtISXBlMXh1SUNBZ0lDQWdJQ0FnSUY5cGJuUnZJRDBnYVc1MGJ5NWpiMjVqWVhRb2RHaHBjeTVmWm05eUtHTnZiR3hsWTNScGIyNXpMbk5zYVdObEtERXBMQ0JtZFc0c0lHWnBiSFJsY2l3Z1gybHVkRzhzSUhCeVpYWnBiM1Z6Vm1Gc2RXVnpMbU52Ym1OaGRDaHlLU2twTzF4dUlDQWdJQ0FnSUNCOVhHNWNiaUFnSUNBZ0lDQWdZbk5UYkdsalpTQTlJR052Ykd4bFkzUnBiMjR1YzJ4cFkyVW9jR0YwZEdWeWJpNWllWFJsWDNOcGVtVW9LU0FxSUdrc0lIQmhkSFJsY200dVlubDBaVjl6YVhwbEtDa2dLaUFvYVNBcklERXBLVHRjYmlBZ0lDQWdJQ0FnYVNzck8xeHVJQ0FnSUNBZ2ZWeHVJQ0FnSUgxbGJITmxlMXh1SUNBZ0lDQWdabTl5S0d4bGRDQmxiR1Z0SUc5bUlHTnZiR3hsWTNScGIyNHBlMXh1SUNBZ0lDQWdJQ0JzWlhRZ2NpQTlJRkJoZEhSbGNtNXpMbTFoZEdOb1gyNXZYM1JvY205M0tIQmhkSFJsY200c0lHVnNaVzBwTzF4dUlDQWdJQ0FnSUNCcFppaHlLWHRjYmlBZ0lDQWdJQ0FnSUNCZmFXNTBieUE5SUdsdWRHOHVZMjl1WTJGMEtIUm9hWE11WDJadmNpaGpiMnhzWldOMGFXOXVjeTV6YkdsalpTZ3hLU3dnWm5WdUxDQm1hV3gwWlhJc0lGOXBiblJ2TENCd2NtVjJhVzkxYzFaaGJIVmxjeTVqYjI1allYUW9jaWtwS1R0Y2JpQWdJQ0FnSUNBZ2ZWeHVJQ0FnSUNBZ2ZTQmNiaUFnSUNCOVhHNWNiaUFnSUNCeVpYUjFjbTRnWDJsdWRHODdYRzRnSUgxY2JuMWNibHh1Wm5WdVkzUnBiMjRnWDNSeWVTaGtiMTltZFc0c0lISmxjMk4xWlY5bWRXNWpkR2x2Yml3Z1kyRjBZMmhmWm5WdUxDQmxiSE5sWDJaMWJtTjBhVzl1TENCaFpuUmxjbDltZFc1amRHbHZiaWw3WEc0Z0lHeGxkQ0J5WlhOMWJIUWdQU0J1ZFd4c08xeHVYRzRnSUhSeWVYdGNiaUFnSUNCeVpYTjFiSFFnUFNCa2IxOW1kVzRvS1R0Y2JpQWdmV05oZEdOb0tHVXBlMXh1SUNBZ0lHeGxkQ0JsZUY5eVpYTjFiSFFnUFNCdWRXeHNPMXh1WEc0Z0lDQWdhV1lvY21WelkzVmxYMloxYm1OMGFXOXVLWHRjYmlBZ0lDQWdJSFJ5ZVh0Y2JpQWdJQ0FnSUNBZ1pYaGZjbVZ6ZFd4MElEMGdjbVZ6WTNWbFgyWjFibU4wYVc5dUtHVXBPMXh1SUNBZ0lDQWdJQ0J5WlhSMWNtNGdaWGhmY21WemRXeDBPMXh1SUNBZ0lDQWdmV05oZEdOb0tHVjRLWHRjYmlBZ0lDQWdJQ0FnYVdZb1pYZ2dhVzV6ZEdGdVkyVnZaaUJRWVhSMFpYSnVjeTVOWVhSamFFVnljbTl5S1h0Y2JpQWdJQ0FnSUNBZ0lDQjBhSEp2ZHlCbGVEdGNiaUFnSUNBZ0lDQWdmVnh1SUNBZ0lDQWdmVnh1SUNBZ0lIMWNibHh1SUNBZ0lHbG1LR05oZEdOb1gyWjFiaWw3WEc0Z0lDQWdJQ0IwY25sN1hHNGdJQ0FnSUNBZ0lHVjRYM0psYzNWc2RDQTlJR05oZEdOb1gyWjFiaWhsS1R0Y2JpQWdJQ0FnSUNBZ2NtVjBkWEp1SUdWNFgzSmxjM1ZzZER0Y2JpQWdJQ0FnSUgxallYUmphQ2hsZUNsN1hHNGdJQ0FnSUNBZ0lHbG1LR1Y0SUdsdWMzUmhibU5sYjJZZ1VHRjBkR1Z5Ym5NdVRXRjBZMmhGY25KdmNpbDdYRzRnSUNBZ0lDQWdJQ0FnZEdoeWIzY2daWGc3WEc0Z0lDQWdJQ0FnSUgxY2JpQWdJQ0FnSUgxY2JpQWdJQ0I5WEc1Y2JpQWdJQ0IwYUhKdmR5QmxPMXh1WEc0Z0lIMW1hVzVoYkd4NWUxeHVJQ0FnSUdsbUtHRm1kR1Z5WDJaMWJtTjBhVzl1S1h0Y2JpQWdJQ0FnSUdGbWRHVnlYMloxYm1OMGFXOXVLQ2s3WEc0Z0lDQWdmVnh1SUNCOVhHNWNiaUFnYVdZb1pXeHpaVjltZFc1amRHbHZiaWw3WEc0Z0lDQWdkSEo1ZTF4dUlDQWdJQ0FnY21WMGRYSnVJR1ZzYzJWZlpuVnVZM1JwYjI0b2NtVnpkV3gwS1R0Y2JpQWdJQ0I5WTJGMFkyZ29aWGdwZTF4dUlDQWdJQ0FnSUNCcFppaGxlQ0JwYm5OMFlXNWpaVzltSUZCaGRIUmxjbTV6TGsxaGRHTm9SWEp5YjNJcGUxeHVJQ0FnSUNBZ0lDQWdJSFJvY205M0lHNWxkeUJGY25KdmNpaGNJazV2SUUxaGRHTm9JRVp2ZFc1a0lHbHVJRVZzYzJWY0lpazdYRzRnSUNBZ0lDQWdJSDFjYmx4dUlDQWdJQ0FnZEdoeWIzY2daWGc3WEc0Z0lDQWdmVnh1SUNCOVpXeHpaWHRjYmlBZ0lDQnlaWFIxY200Z2NtVnpkV3gwTzF4dUlDQjlYRzU5WEc1Y2JtWjFibU4wYVc5dUlGOTNhWFJvS0M0dUxtRnlaM01wZTF4dUlDQnNaWFFnWVhKbmMxUnZVR0Z6Y3lBOUlGdGRPMXh1WEc0Z0lHWnZjaWhzWlhRZ2FTQTlJREE3SUdrZ1BDQmhjbWR6TG14bGJtZDBhRHNnYVNzcktYdGNiaUFnSUNCcFppaHBJRDA5UFNCaGNtZHpMbXhsYm1kMGFDQXRJREVwZTF4dUlDQWdJQ0FnY21WMGRYSnVJR0Z5WjNOYmFWMHVZWEJ3Ykhrb2JuVnNiQ3dnWVhKbmMxUnZVR0Z6Y3lrN1hHNGdJQ0FnZldWc2MyVjdYRzRnSUNBZ0lDQnNaWFFnVzNCaGRIUmxjbTRzSUdaMWJtTmRJRDBnWVhKbmMxdHBYVHRjYmx4dUlDQWdJQ0FnYkdWMElISmxjM1ZzZENBOUlHWjFibU11WVhCd2JIa29iblZzYkN3Z1lYSm5jMVJ2VUdGemN5azdYRzVjYmlBZ0lDQWdJR3hsZENCd1lYUjBaWEp1VW1WemRXeDBJRDBnVUdGMGRHVnlibk11YldGMFkyaGZibTlmZEdoeWIzY29jR0YwZEdWeWJpd2djbVZ6ZFd4MEtUdGNibHh1SUNBZ0lDQWdhV1lvY0dGMGRHVnlibEpsYzNWc2RDQTlQU0J1ZFd4c0tYdGNiaUFnSUNBZ0lDQWdjbVYwZFhKdUlISmxjM1ZzZER0Y2JpQWdJQ0FnSUgxbGJITmxlMXh1SUNBZ0lDQWdJQ0JoY21kelZHOVFZWE56SUQwZ1lYSm5jMVJ2VUdGemN5NWpiMjVqWVhRb2NHRjBkR1Z5YmxKbGMzVnNkQ2s3WEc0Z0lDQWdJQ0I5WEc0Z0lDQWdmVnh1SUNCOVhHNWNiaUFnY21WMGRYSnVJRzUxYkd3N1hHNTlYRzVjYm1WNGNHOXlkQ0JrWldaaGRXeDBJSHRjYmlBZ1gyTmhjMlVzWEc0Z0lHTnZibVFzWEc0Z0lHMWhjRjkxY0dSaGRHVXNYRzRnSUY5bWIzSXNYRzRnSUY5MGNua3NYRzRnSUY5M2FYUm9YRzU5TzF4dUlsMHNJbk52ZFhKalpWSnZiM1FpT2lJdmMyOTFjbU5sTHlKOVxuIiwiaW1wb3J0IFByb2Nlc3NTeXN0ZW0gZnJvbSAnLi9jb3JlL3Byb2Nlc3Nlcy9wcm9jZXNzX3N5c3RlbSc7XG5pbXBvcnQgeyBUdXBsZSwgUElELCBJbnRlZ2VyLCBGbG9hdCB9IGZyb20gJy4vY29yZS9wcmltaXRpdmVzJztcbmltcG9ydCBCaXRTdHJpbmcgZnJvbSAnLi9jb3JlL2JpdF9zdHJpbmcnO1xuaW1wb3J0IFBhdHRlcm5zIGZyb20gJy4vY29yZS9wYXR0ZXJucyc7XG5pbXBvcnQgRnVuY3Rpb25zIGZyb20gJy4vY29yZS9mdW5jdGlvbnMnO1xuaW1wb3J0IFNwZWNpYWxGb3JtcyBmcm9tICcuL2NvcmUvc3BlY2lhbF9mb3Jtcyc7XG5cbkZ1bmN0aW9ucy5nZXRfZ2xvYmFsKCkucHJvY2Vzc2VzID0gRnVuY3Rpb25zLmdldF9nbG9iYWwoKS5wcm9jZXNzZXMgfHwgbmV3IFByb2Nlc3NTeXN0ZW0oKTtcblxuZXhwb3J0IGRlZmF1bHQge1xuICBQcm9jZXNzU3lzdGVtLFxuICBUdXBsZSxcbiAgUElELFxuICBCaXRTdHJpbmcsXG4gIFBhdHRlcm5zLFxuICBJbnRlZ2VyLFxuICBGbG9hdCxcbiAgRnVuY3Rpb25zLFxuICBTcGVjaWFsRm9ybXNcbn07XG4vLyMgc291cmNlTWFwcGluZ1VSTD1kYXRhOmFwcGxpY2F0aW9uL2pzb247YmFzZTY0LGV5SjJaWEp6YVc5dUlqb3pMQ0p6YjNWeVkyVnpJanBiSW14cFlpOWpiM0psTG1weklsMHNJbTVoYldWeklqcGJYU3dpYldGd2NHbHVaM01pT2lKQlFVRkJMRTlCUVU4c1lVRkJVQ3hOUVVFd1FpeHBRMEZCTVVJN1FVRkRRU3hUUVVGVExFdEJRVlFzUlVGQlowSXNSMEZCYUVJc1JVRkJjVUlzVDBGQmNrSXNSVUZCT0VJc1MwRkJPVUlzVVVGQk1rTXNiVUpCUVRORE8wRkJRMEVzVDBGQlR5eFRRVUZRTEUxQlFYTkNMRzFDUVVGMFFqdEJRVU5CTEU5QlFVOHNVVUZCVUN4TlFVRnhRaXhwUWtGQmNrSTdRVUZEUVN4UFFVRlBMRk5CUVZBc1RVRkJjMElzYTBKQlFYUkNPMEZCUTBFc1QwRkJUeXhaUVVGUUxFMUJRWGxDTEhOQ1FVRjZRanM3UVVGRlFTeFZRVUZWTEZWQlFWWXNSMEZCZFVJc1UwRkJka0lzUjBGQmJVTXNWVUZCVlN4VlFVRldMRWRCUVhWQ0xGTkJRWFpDTEVsQlFXOURMRWxCUVVrc1lVRkJTaXhGUVVGd1F6czdRVUZGYmtNc1pVRkJaVHRCUVVOaUxHVkJSR0U3UVVGRllpeFBRVVpoTzBGQlIySXNTMEZJWVR0QlFVbGlMRmRCU21FN1FVRkxZaXhWUVV4aE8wRkJUV0lzVTBGT1lUdEJRVTlpTEU5QlVHRTdRVUZSWWl4WFFWSmhPMEZCVTJJc1kwRlVZVHREUVVGbUlpd2labWxzWlNJNklteHBZaTlqYjNKbExtcHpJaXdpYzI5MWNtTmxjME52Ym5SbGJuUWlPbHNpYVcxd2IzSjBJRkJ5YjJObGMzTlRlWE4wWlcwZ1puSnZiU0FuTGk5amIzSmxMM0J5YjJObGMzTmxjeTl3Y205alpYTnpYM041YzNSbGJTYzdYRzVwYlhCdmNuUWdleUJVZFhCc1pTd2dVRWxFTENCSmJuUmxaMlZ5TENCR2JHOWhkQ0I5SUdaeWIyMGdKeTR2WTI5eVpTOXdjbWx0YVhScGRtVnpKenRjYm1sdGNHOXlkQ0JDYVhSVGRISnBibWNnWm5KdmJTQW5MaTlqYjNKbEwySnBkRjl6ZEhKcGJtY25PMXh1YVcxd2IzSjBJRkJoZEhSbGNtNXpJR1p5YjIwZ0p5NHZZMjl5WlM5d1lYUjBaWEp1Y3ljN1hHNXBiWEJ2Y25RZ1JuVnVZM1JwYjI1eklHWnliMjBnSnk0dlkyOXlaUzltZFc1amRHbHZibk1uTzF4dWFXMXdiM0owSUZOd1pXTnBZV3hHYjNKdGN5Qm1jbTl0SUNjdUwyTnZjbVV2YzNCbFkybGhiRjltYjNKdGN5YzdYRzVjYmtaMWJtTjBhVzl1Y3k1blpYUmZaMnh2WW1Gc0tDa3VjSEp2WTJWemMyVnpJRDBnUm5WdVkzUnBiMjV6TG1kbGRGOW5iRzlpWVd3b0tTNXdjbTlqWlhOelpYTWdmSHdnYm1WM0lGQnliMk5sYzNOVGVYTjBaVzBvS1R0Y2JseHVaWGh3YjNKMElHUmxabUYxYkhRZ2UxeHVJQ0JRY205alpYTnpVM2x6ZEdWdExGeHVJQ0JVZFhCc1pTeGNiaUFnVUVsRUxGeHVJQ0JDYVhSVGRISnBibWNzWEc0Z0lGQmhkSFJsY201ekxGeHVJQ0JKYm5SbFoyVnlMRnh1SUNCR2JHOWhkQ3hjYmlBZ1JuVnVZM1JwYjI1ekxGeHVJQ0JUY0dWamFXRnNSbTl5YlhOY2JuMWNiaUpkTENKemIzVnlZMlZTYjI5MElqb2lMM052ZFhKalpTOGlmUT09XG4iLCJpbXBvcnQgQ29yZSBmcm9tICcuL2NvcmUnO1xuXG5sZXQgRW51bSA9IHtcblxuICBhbGxfX3FtYXJrX186IGZ1bmN0aW9uIChjb2xsZWN0aW9uLCBmdW4gPSB4ID0+IHgpIHtcbiAgICBmb3IgKGxldCBlbGVtIG9mIGNvbGxlY3Rpb24pIHtcbiAgICAgIGlmICghZnVuKGVsZW0pKSB7XG4gICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICByZXR1cm4gdHJ1ZTtcbiAgfSxcblxuICBhbnlfX3FtYXJrX186IGZ1bmN0aW9uIChjb2xsZWN0aW9uLCBmdW4gPSB4ID0+IHgpIHtcbiAgICBmb3IgKGxldCBlbGVtIG9mIGNvbGxlY3Rpb24pIHtcbiAgICAgIGlmIChmdW4oZWxlbSkpIHtcbiAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICB9XG4gICAgfVxuXG4gICAgcmV0dXJuIGZhbHNlO1xuICB9LFxuXG4gIGF0OiBmdW5jdGlvbiAoY29sbGVjdGlvbiwgbiwgdGhlX2RlZmF1bHQgPSBudWxsKSB7XG4gICAgaWYgKG4gPiB0aGlzLmNvdW50KGNvbGxlY3Rpb24pIHx8IG4gPCAwKSB7XG4gICAgICByZXR1cm4gdGhlX2RlZmF1bHQ7XG4gICAgfVxuXG4gICAgcmV0dXJuIGNvbGxlY3Rpb25bbl07XG4gIH0sXG5cbiAgY29uY2F0OiBmdW5jdGlvbiAoLi4uZW51bWFibGVzKSB7XG4gICAgcmV0dXJuIGVudW1hYmxlc1swXS5jb25jYXQoZW51bWFibGVzWzFdKTtcbiAgfSxcblxuICBjb3VudDogZnVuY3Rpb24gKGNvbGxlY3Rpb24sIGZ1biA9IG51bGwpIHtcbiAgICBpZiAoZnVuID09IG51bGwpIHtcbiAgICAgIHJldHVybiBjb2xsZWN0aW9uLmxlbmd0aDtcbiAgICB9IGVsc2Uge1xuICAgICAgcmV0dXJuIGNvbGxlY3Rpb24uZmlsdGVyKGZ1bikubGVuZ3RoO1xuICAgIH1cbiAgfSxcblxuICBkcm9wOiBmdW5jdGlvbiAoY29sbGVjdGlvbiwgY291bnQpIHtcbiAgICByZXR1cm4gY29sbGVjdGlvbi5zbGljZShjb3VudCk7XG4gIH0sXG5cbiAgZHJvcF93aGlsZTogZnVuY3Rpb24gKGNvbGxlY3Rpb24sIGZ1bikge1xuICAgIGxldCBjb3VudCA9IDA7XG5cbiAgICBmb3IgKGxldCBlbGVtIG9mIGNvbGxlY3Rpb24pIHtcbiAgICAgIGlmIChmdW4oZWxlbSkpIHtcbiAgICAgICAgY291bnQgPSBjb3VudCArIDE7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBicmVhaztcbiAgICAgIH1cbiAgICB9XG5cbiAgICByZXR1cm4gY29sbGVjdGlvbi5zbGljZShjb3VudCk7XG4gIH0sXG5cbiAgZWFjaDogZnVuY3Rpb24gKGNvbGxlY3Rpb24sIGZ1bikge1xuICAgIGZvciAobGV0IGVsZW0gb2YgY29sbGVjdGlvbikge1xuICAgICAgZnVuKGVsZW0pO1xuICAgIH1cbiAgfSxcblxuICBlbXB0eV9fcW1hcmtfXzogZnVuY3Rpb24gKGNvbGxlY3Rpb24pIHtcbiAgICByZXR1cm4gY29sbGVjdGlvbi5sZW5ndGggPT09IDA7XG4gIH0sXG5cbiAgZmV0Y2g6IGZ1bmN0aW9uIChjb2xsZWN0aW9uLCBuKSB7XG4gICAgaWYgKEFycmF5LmlzQXJyYXkoY29sbGVjdGlvbikpIHtcbiAgICAgIGlmIChuIDwgdGhpcy5jb3VudChjb2xsZWN0aW9uKSAmJiBuID49IDApIHtcbiAgICAgICAgcmV0dXJuIG5ldyBDb3JlLlR1cGxlKFN5bWJvbC5mb3IoXCJva1wiKSwgY29sbGVjdGlvbltuXSk7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICByZXR1cm4gU3ltYm9sLmZvcihcImVycm9yXCIpO1xuICAgICAgfVxuICAgIH1cblxuICAgIHRocm93IG5ldyBFcnJvcihcImNvbGxlY3Rpb24gaXMgbm90IGFuIEVudW1lcmFibGVcIik7XG4gIH0sXG5cbiAgZmV0Y2hfX2VtYXJrX186IGZ1bmN0aW9uIChjb2xsZWN0aW9uLCBuKSB7XG4gICAgaWYgKEFycmF5LmlzQXJyYXkoY29sbGVjdGlvbikpIHtcbiAgICAgIGlmIChuIDwgdGhpcy5jb3VudChjb2xsZWN0aW9uKSAmJiBuID49IDApIHtcbiAgICAgICAgcmV0dXJuIGNvbGxlY3Rpb25bbl07XG4gICAgICB9IGVsc2Uge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoXCJvdXQgb2YgYm91bmRzIGVycm9yXCIpO1xuICAgICAgfVxuICAgIH1cblxuICAgIHRocm93IG5ldyBFcnJvcihcImNvbGxlY3Rpb24gaXMgbm90IGFuIEVudW1lcmFibGVcIik7XG4gIH0sXG5cbiAgZmlsdGVyOiBmdW5jdGlvbiAoY29sbGVjdGlvbiwgZnVuKSB7XG4gICAgbGV0IHJlc3VsdCA9IFtdO1xuXG4gICAgZm9yIChsZXQgZWxlbSBvZiBjb2xsZWN0aW9uKSB7XG4gICAgICBpZiAoZnVuKGVsZW0pKSB7XG4gICAgICAgIHJlc3VsdC5wdXNoKGVsZW0pO1xuICAgICAgfVxuICAgIH1cblxuICAgIHJldHVybiByZXN1bHQ7XG4gIH0sXG5cbiAgZmlsdGVyX21hcDogZnVuY3Rpb24gKGNvbGxlY3Rpb24sIGZpbHRlciwgbWFwcGVyKSB7XG4gICAgcmV0dXJuIEVudW0ubWFwKEVudW0uZmlsdGVyKGNvbGxlY3Rpb24sIGZpbHRlciksIG1hcHBlcik7XG4gIH0sXG5cbiAgZmluZDogZnVuY3Rpb24gKGNvbGxlY3Rpb24sIGlmX25vbmUgPSBudWxsLCBmdW4pIHtcbiAgICBmb3IgKGxldCBlbGVtIG9mIGNvbGxlY3Rpb24pIHtcbiAgICAgIGlmIChmdW4oZWxlbSkpIHtcbiAgICAgICAgcmV0dXJuIGVsZW07XG4gICAgICB9XG4gICAgfVxuXG4gICAgcmV0dXJuIGlmX25vbmU7XG4gIH0sXG5cbiAgaW50bzogZnVuY3Rpb24gKGNvbGxlY3Rpb24sIGxpc3QpIHtcbiAgICByZXR1cm4gbGlzdC5jb25jYXQoY29sbGVjdGlvbik7XG4gIH0sXG5cbiAgbWFwOiBmdW5jdGlvbiAoY29sbGVjdGlvbiwgZnVuKSB7XG4gICAgbGV0IHJlc3VsdCA9IFtdO1xuXG4gICAgZm9yIChsZXQgZWxlbSBvZiBjb2xsZWN0aW9uKSB7XG4gICAgICByZXN1bHQucHVzaChmdW4oZWxlbSkpO1xuICAgIH1cblxuICAgIHJldHVybiByZXN1bHQ7XG4gIH0sXG5cbiAgbWFwX3JlZHVjZTogZnVuY3Rpb24gKGNvbGxlY3Rpb24sIGFjYywgZnVuKSB7XG4gICAgbGV0IG1hcHBlZCA9IE9iamVjdC5mcmVlemUoW10pO1xuICAgIGxldCB0aGVfYWNjID0gYWNjO1xuXG4gICAgZm9yICh2YXIgaSA9IDA7IGkgPCB0aGlzLmNvdW50KGNvbGxlY3Rpb24pOyBpKyspIHtcbiAgICAgIGxldCB0dXBsZSA9IGZ1bihjb2xsZWN0aW9uW2ldLCB0aGVfYWNjKTtcblxuICAgICAgdGhlX2FjYyA9IHR1cGxlLmdldCgxKTtcbiAgICAgIG1hcHBlZCA9IE9iamVjdC5mcmVlemUobWFwcGVkLmNvbmNhdChbdHVwbGUuZ2V0KDApXSkpO1xuICAgIH1cblxuICAgIHJldHVybiBuZXcgQ29yZS5UdXBsZShtYXBwZWQsIHRoZV9hY2MpO1xuICB9LFxuXG4gIG1lbWJlcl9fcW1hcmtfXzogZnVuY3Rpb24gKGNvbGxlY3Rpb24sIHZhbHVlKSB7XG4gICAgcmV0dXJuIGNvbGxlY3Rpb24uaW5jbHVkZXModmFsdWUpO1xuICB9LFxuXG4gIHJlZHVjZTogZnVuY3Rpb24gKGNvbGxlY3Rpb24sIGFjYywgZnVuKSB7XG4gICAgbGV0IHRoZV9hY2MgPSBhY2M7XG5cbiAgICBmb3IgKHZhciBpID0gMDsgaSA8IHRoaXMuY291bnQoY29sbGVjdGlvbik7IGkrKykge1xuICAgICAgbGV0IHR1cGxlID0gZnVuKGNvbGxlY3Rpb25baV0sIHRoZV9hY2MpO1xuXG4gICAgICB0aGVfYWNjID0gdHVwbGUuZ2V0KDEpO1xuICAgIH1cblxuICAgIHJldHVybiB0aGVfYWNjO1xuICB9LFxuXG4gIHRha2U6IGZ1bmN0aW9uIChjb2xsZWN0aW9uLCBjb3VudCkge1xuICAgIHJldHVybiBjb2xsZWN0aW9uLnNsaWNlKDAsIGNvdW50KTtcbiAgfSxcblxuICB0YWtlX2V2ZXJ5OiBmdW5jdGlvbiAoY29sbGVjdGlvbiwgbnRoKSB7XG4gICAgbGV0IHJlc3VsdCA9IFtdO1xuICAgIGxldCBpbmRleCA9IDA7XG5cbiAgICBmb3IgKGxldCBlbGVtIG9mIGNvbGxlY3Rpb24pIHtcbiAgICAgIGlmIChpbmRleCAlIG50aCA9PT0gMCkge1xuICAgICAgICByZXN1bHQucHVzaChlbGVtKTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICByZXR1cm4gT2JqZWN0LmZyZWV6ZShyZXN1bHQpO1xuICB9LFxuXG4gIHRha2Vfd2hpbGU6IGZ1bmN0aW9uIChjb2xsZWN0aW9uLCBmdW4pIHtcbiAgICBsZXQgY291bnQgPSAwO1xuXG4gICAgZm9yIChsZXQgZWxlbSBvZiBjb2xsZWN0aW9uKSB7XG4gICAgICBpZiAoZnVuKGVsZW0pKSB7XG4gICAgICAgIGNvdW50ID0gY291bnQgKyAxO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgYnJlYWs7XG4gICAgICB9XG4gICAgfVxuXG4gICAgcmV0dXJuIGNvbGxlY3Rpb24uc2xpY2UoMCwgY291bnQpO1xuICB9LFxuXG4gIHRvX2xpc3Q6IGZ1bmN0aW9uIChjb2xsZWN0aW9uKSB7XG4gICAgcmV0dXJuIGNvbGxlY3Rpb247XG4gIH1cbn07XG5cbmV4cG9ydCBkZWZhdWx0IEVudW07XG4vLyMgc291cmNlTWFwcGluZ1VSTD1kYXRhOmFwcGxpY2F0aW9uL2pzb247YmFzZTY0LGV5SjJaWEp6YVc5dUlqb3pMQ0p6YjNWeVkyVnpJanBiSW14cFlpOWxiblZ0TG1weklsMHNJbTVoYldWeklqcGJYU3dpYldGd2NHbHVaM01pT2lKQlFVRkJMRTlCUVU4c1NVRkJVQ3hOUVVGcFFpeFJRVUZxUWpzN1FVRkZRU3hKUVVGSkxFOUJRVTg3TzBGQlJWUXNaMEpCUVdNc1ZVRkJVeXhWUVVGVUxFVkJRWEZDTEUxQlFVMHNTMEZCVHl4RFFVRlFMRVZCUVZNN1FVRkRhRVFzVTBGQlNTeEpRVUZKTEVsQlFVb3NTVUZCV1N4VlFVRm9RaXhGUVVFeVFqdEJRVU42UWl4VlFVRkhMRU5CUVVNc1NVRkJTU3hKUVVGS0xFTkJRVVFzUlVGQlZ6dEJRVU5hTEdWQlFVOHNTMEZCVUN4RFFVUlpPMDlCUVdRN1MwRkVSanM3UVVGTlFTeFhRVUZQTEVsQlFWQXNRMEZRWjBRN1IwRkJjRU03TzBGQlZXUXNaMEpCUVdNc1ZVRkJVeXhWUVVGVUxFVkJRWEZDTEUxQlFVMHNTMEZCVHl4RFFVRlFMRVZCUVZNN1FVRkRhRVFzVTBGQlNTeEpRVUZKTEVsQlFVb3NTVUZCV1N4VlFVRm9RaXhGUVVFeVFqdEJRVU42UWl4VlFVRkhMRWxCUVVrc1NVRkJTaXhEUVVGSUxFVkJRV0U3UVVGRFdDeGxRVUZQTEVsQlFWQXNRMEZFVnp0UFFVRmlPMHRCUkVZN08wRkJUVUVzVjBGQlR5eExRVUZRTEVOQlVHZEVPMGRCUVhCRE96dEJRVlZrTEUxQlFVa3NWVUZCVXl4VlFVRlVMRVZCUVhGQ0xFTkJRWEpDTEVWQlFYZENMR05CUVdNc1NVRkJaQ3hGUVVGdFFqdEJRVU0zUXl4UlFVRkhMRWxCUVVrc1MwRkJTeXhMUVVGTUxFTkJRVmNzVlVGQldDeERRVUZLTEVsQlFUaENMRWxCUVVrc1EwRkJTaXhGUVVGTk8wRkJRM0pETEdGQlFVOHNWMEZCVUN4RFFVUnhRenRMUVVGMlF6czdRVUZKUVN4WFFVRlBMRmRCUVZjc1EwRkJXQ3hEUVVGUUxFTkJURFpETzBkQlFUTkRPenRCUVZGS0xGVkJRVkVzVlVGQlV5eEhRVUZITEZOQlFVZ3NSVUZCWVR0QlFVTTFRaXhYUVVGUExGVkJRVlVzUTBGQlZpeEZRVUZoTEUxQlFXSXNRMEZCYjBJc1ZVRkJWU3hEUVVGV0xFTkJRWEJDTEVOQlFWQXNRMEZFTkVJN1IwRkJkRUk3TzBGQlNWSXNVMEZCVHl4VlFVRlRMRlZCUVZRc1JVRkJjVUlzVFVGQlRTeEpRVUZPTEVWQlFWYzdRVUZEY2tNc1VVRkJSeXhQUVVGUExFbEJRVkFzUlVGQldUdEJRVU5pTEdGQlFVOHNWMEZCVnl4TlFVRllMRU5CUkUwN1MwRkJaaXhOUVVWUE8wRkJRMHdzWVVGQlR5eFhRVUZYTEUxQlFWZ3NRMEZCYTBJc1IwRkJiRUlzUlVGQmRVSXNUVUZCZGtJc1EwRkVSanRMUVVaUU8wZEJSRXM3TzBGQlVWQXNVVUZCVFN4VlFVRlRMRlZCUVZRc1JVRkJjVUlzUzBGQmNrSXNSVUZCTWtJN1FVRkRMMElzVjBGQlR5eFhRVUZYTEV0QlFWZ3NRMEZCYVVJc1MwRkJha0lzUTBGQlVDeERRVVFyUWp0SFFVRXpRanM3UVVGSlRpeGpRVUZaTEZWQlFWTXNWVUZCVkN4RlFVRnhRaXhIUVVGeVFpeEZRVUY1UWp0QlFVTnVReXhSUVVGSkxGRkJRVkVzUTBGQlVpeERRVVFyUWpzN1FVRkhia01zVTBGQlNTeEpRVUZKTEVsQlFVb3NTVUZCV1N4VlFVRm9RaXhGUVVFeVFqdEJRVU42UWl4VlFVRkhMRWxCUVVrc1NVRkJTaXhEUVVGSUxFVkJRV0U3UVVGRFdDeG5Ra0ZCVVN4UlFVRlJMRU5CUVZJc1EwRkVSenRQUVVGaUxFMUJSVXM3UVVGRFNDeGpRVVJITzA5QlJrdzdTMEZFUmpzN1FVRlJRU3hYUVVGUExGZEJRVmNzUzBGQldDeERRVUZwUWl4TFFVRnFRaXhEUVVGUUxFTkJXRzFETzBkQlFYcENPenRCUVdOYUxGRkJRVTBzVlVGQlV5eFZRVUZVTEVWQlFYRkNMRWRCUVhKQ0xFVkJRWGxDTzBGQlF6ZENMRk5CUVVrc1NVRkJTU3hKUVVGS0xFbEJRVmtzVlVGQmFFSXNSVUZCTWtJN1FVRkRla0lzVlVGQlNTeEpRVUZLTEVWQlJIbENPMHRCUVROQ08wZEJSRWs3TzBGQlRVNHNhMEpCUVdkQ0xGVkJRVk1zVlVGQlZDeEZRVUZ2UWp0QlFVTnNReXhYUVVGUExGZEJRVmNzVFVGQldDeExRVUZ6UWl4RFFVRjBRaXhEUVVReVFqdEhRVUZ3UWpzN1FVRkphRUlzVTBGQlR5eFZRVUZUTEZWQlFWUXNSVUZCY1VJc1EwRkJja0lzUlVGQmRVSTdRVUZETlVJc1VVRkJSeXhOUVVGTkxFOUJRVTRzUTBGQll5eFZRVUZrTEVOQlFVZ3NSVUZCTmtJN1FVRkRNMElzVlVGQlJ5eEpRVUZKTEV0QlFVc3NTMEZCVEN4RFFVRlhMRlZCUVZnc1EwRkJTaXhKUVVFNFFpeExRVUZMTEVOQlFVd3NSVUZCVHp0QlFVTjBReXhsUVVGUExFbEJRVWtzUzBGQlN5eExRVUZNTEVOQlFWY3NUMEZCVHl4SFFVRlFMRU5CUVZjc1NVRkJXQ3hEUVVGbUxFVkJRV2xETEZkQlFWY3NRMEZCV0N4RFFVRnFReXhEUVVGUUxFTkJSSE5ETzA5QlFYaERMRTFCUlVzN1FVRkRTQ3hsUVVGUExFOUJRVThzUjBGQlVDeERRVUZYTEU5QlFWZ3NRMEZCVUN4RFFVUkhPMDlCUmt3N1MwRkVSanM3UVVGUlFTeFZRVUZOTEVsQlFVa3NTMEZCU2l4RFFVRlZMR2xEUVVGV0xFTkJRVTRzUTBGVU5FSTdSMEZCZGtJN08wRkJXVkFzYTBKQlFXZENMRlZCUVZNc1ZVRkJWQ3hGUVVGeFFpeERRVUZ5UWl4RlFVRjFRanRCUVVOeVF5eFJRVUZITEUxQlFVMHNUMEZCVGl4RFFVRmpMRlZCUVdRc1EwRkJTQ3hGUVVFMlFqdEJRVU16UWl4VlFVRkhMRWxCUVVrc1MwRkJTeXhMUVVGTUxFTkJRVmNzVlVGQldDeERRVUZLTEVsQlFUaENMRXRCUVVzc1EwRkJUQ3hGUVVGUE8wRkJRM1JETEdWQlFVOHNWMEZCVnl4RFFVRllMRU5CUVZBc1EwRkVjME03VDBGQmVFTXNUVUZGU3p0QlFVTklMR05CUVUwc1NVRkJTU3hMUVVGS0xFTkJRVlVzY1VKQlFWWXNRMEZCVGl4RFFVUkhPMDlCUmt3N1MwRkVSanM3UVVGUlFTeFZRVUZOTEVsQlFVa3NTMEZCU2l4RFFVRlZMR2xEUVVGV0xFTkJRVTRzUTBGVWNVTTdSMEZCZGtJN08wRkJXV2hDTEZWQlFWRXNWVUZCVXl4VlFVRlVMRVZCUVhGQ0xFZEJRWEpDTEVWQlFYbENPMEZCUXk5Q0xGRkJRVWtzVTBGQlV5eEZRVUZVTEVOQlJESkNPenRCUVVjdlFpeFRRVUZKTEVsQlFVa3NTVUZCU2l4SlFVRlpMRlZCUVdoQ0xFVkJRVEpDTzBGQlEzcENMRlZCUVVjc1NVRkJTU3hKUVVGS0xFTkJRVWdzUlVGQllUdEJRVU5ZTEdWQlFVOHNTVUZCVUN4RFFVRlpMRWxCUVZvc1JVRkVWenRQUVVGaU8wdEJSRVk3TzBGQlRVRXNWMEZCVHl4TlFVRlFMRU5CVkN0Q08wZEJRWHBDT3p0QlFWbFNMR05CUVZrc1ZVRkJVeXhWUVVGVUxFVkJRWEZDTEUxQlFYSkNMRVZCUVRaQ0xFMUJRVGRDTEVWQlFXOURPMEZCUXpsRExGZEJRVThzUzBGQlN5eEhRVUZNTEVOQlFWTXNTMEZCU3l4TlFVRk1MRU5CUVZrc1ZVRkJXaXhGUVVGM1FpeE5RVUY0UWl4RFFVRlVMRVZCUVRCRExFMUJRVEZETEVOQlFWQXNRMEZFT0VNN1IwRkJjRU03TzBGQlNWb3NVVUZCVFN4VlFVRlRMRlZCUVZRc1JVRkJjVUlzVlVGQlZTeEpRVUZXTEVWQlFXZENMRWRCUVhKRExFVkJRWGxETzBGQlF6ZERMRk5CUVVrc1NVRkJTU3hKUVVGS0xFbEJRVmtzVlVGQmFFSXNSVUZCTWtJN1FVRkRla0lzVlVGQlJ5eEpRVUZKTEVsQlFVb3NRMEZCU0N4RlFVRmhPMEZCUTFnc1pVRkJUeXhKUVVGUUxFTkJSRmM3VDBGQllqdExRVVJHT3p0QlFVMUJMRmRCUVU4c1QwRkJVQ3hEUVZBMlF6dEhRVUY2UXpzN1FVRlZUaXhSUVVGTkxGVkJRVk1zVlVGQlZDeEZRVUZ4UWl4SlFVRnlRaXhGUVVFd1FqdEJRVU01UWl4WFFVRlBMRXRCUVVzc1RVRkJUQ3hEUVVGWkxGVkJRVm9zUTBGQlVDeERRVVE0UWp0SFFVRXhRanM3UVVGSlRpeFBRVUZMTEZWQlFWTXNWVUZCVkN4RlFVRnhRaXhIUVVGeVFpeEZRVUY1UWp0QlFVTTFRaXhSUVVGSkxGTkJRVk1zUlVGQlZDeERRVVIzUWpzN1FVRkhOVUlzVTBGQlNTeEpRVUZKTEVsQlFVb3NTVUZCV1N4VlFVRm9RaXhGUVVFeVFqdEJRVU42UWl4aFFVRlBMRWxCUVZBc1EwRkJXU3hKUVVGSkxFbEJRVW9zUTBGQldpeEZRVVI1UWp0TFFVRXpRanM3UVVGSlFTeFhRVUZQTEUxQlFWQXNRMEZRTkVJN1IwRkJla0k3TzBGQlZVd3NZMEZCV1N4VlFVRlRMRlZCUVZRc1JVRkJjVUlzUjBGQmNrSXNSVUZCTUVJc1IwRkJNVUlzUlVGQk9FSTdRVUZEZUVNc1VVRkJTU3hUUVVGVExFOUJRVThzVFVGQlVDeERRVUZqTEVWQlFXUXNRMEZCVkN4RFFVUnZRenRCUVVWNFF5eFJRVUZKTEZWQlFWVXNSMEZCVml4RFFVWnZRenM3UVVGSmVFTXNVMEZCU3l4SlFVRkpMRWxCUVVrc1EwRkJTaXhGUVVGUExFbEJRVWtzUzBGQlN5eExRVUZNTEVOQlFWY3NWVUZCV0N4RFFVRktMRVZCUVRSQ0xFZEJRVFZETEVWQlFXbEVPMEZCUXk5RExGVkJRVWtzVVVGQlVTeEpRVUZKTEZkQlFWY3NRMEZCV0N4RFFVRktMRVZCUVcxQ0xFOUJRVzVDTEVOQlFWSXNRMEZFTWtNN08wRkJSeTlETEdkQ1FVRlZMRTFCUVUwc1IwRkJUaXhEUVVGVkxFTkJRVllzUTBGQlZpeERRVWdyUXp0QlFVa3ZReXhsUVVGVExFOUJRVThzVFVGQlVDeERRVUZqTEU5QlFVOHNUVUZCVUN4RFFVRmpMRU5CUVVNc1RVRkJUU3hIUVVGT0xFTkJRVlVzUTBGQlZpeERRVUZFTEVOQlFXUXNRMEZCWkN4RFFVRlVMRU5CU2l0RE8wdEJRV3BFT3p0QlFVOUJMRmRCUVU4c1NVRkJTU3hMUVVGTExFdEJRVXdzUTBGQlZ5eE5RVUZtTEVWQlFYVkNMRTlCUVhaQ0xFTkJRVkFzUTBGWWQwTTdSMEZCT1VJN08wRkJZMW9zYlVKQlFXbENMRlZCUVZNc1ZVRkJWQ3hGUVVGeFFpeExRVUZ5UWl4RlFVRXlRanRCUVVNeFF5eFhRVUZQTEZkQlFWY3NVVUZCV0N4RFFVRnZRaXhMUVVGd1FpeERRVUZRTEVOQlJEQkRPMGRCUVROQ096dEJRVWxxUWl4VlFVRlJMRlZCUVZNc1ZVRkJWQ3hGUVVGeFFpeEhRVUZ5UWl4RlFVRXdRaXhIUVVFeFFpeEZRVUU0UWp0QlFVTndReXhSUVVGSkxGVkJRVlVzUjBGQlZpeERRVVJuUXpzN1FVRkhjRU1zVTBGQlN5eEpRVUZKTEVsQlFVa3NRMEZCU2l4RlFVRlBMRWxCUVVrc1MwRkJTeXhMUVVGTUxFTkJRVmNzVlVGQldDeERRVUZLTEVWQlFUUkNMRWRCUVRWRExFVkJRV2xFTzBGQlF5OURMRlZCUVVrc1VVRkJVU3hKUVVGSkxGZEJRVmNzUTBGQldDeERRVUZLTEVWQlFXMUNMRTlCUVc1Q0xFTkJRVklzUTBGRU1rTTdPMEZCUnk5RExHZENRVUZWTEUxQlFVMHNSMEZCVGl4RFFVRlZMRU5CUVZZc1EwRkJWaXhEUVVnclF6dExRVUZxUkRzN1FVRk5RU3hYUVVGUExFOUJRVkFzUTBGVWIwTTdSMEZCT1VJN08wRkJXVklzVVVGQlRTeFZRVUZUTEZWQlFWUXNSVUZCY1VJc1MwRkJja0lzUlVGQk1rSTdRVUZETDBJc1YwRkJUeXhYUVVGWExFdEJRVmdzUTBGQmFVSXNRMEZCYWtJc1JVRkJiMElzUzBGQmNFSXNRMEZCVUN4RFFVUXJRanRIUVVFelFqczdRVUZKVGl4alFVRlpMRlZCUVZNc1ZVRkJWQ3hGUVVGeFFpeEhRVUZ5UWl4RlFVRjVRanRCUVVOdVF5eFJRVUZKTEZOQlFWTXNSVUZCVkN4RFFVUXJRanRCUVVWdVF5eFJRVUZKTEZGQlFWRXNRMEZCVWl4RFFVWXJRanM3UVVGSmJrTXNVMEZCU1N4SlFVRkpMRWxCUVVvc1NVRkJXU3hWUVVGb1FpeEZRVUV5UWp0QlFVTjZRaXhWUVVGSExGRkJRVkVzUjBGQlVpeExRVUZuUWl4RFFVRm9RaXhGUVVGclFqdEJRVU51UWl4bFFVRlBMRWxCUVZBc1EwRkJXU3hKUVVGYUxFVkJSRzFDTzA5QlFYSkNPMHRCUkVZN08wRkJUVUVzVjBGQlR5eFBRVUZQTEUxQlFWQXNRMEZCWXl4TlFVRmtMRU5CUVZBc1EwRldiVU03UjBGQmVrSTdPMEZCWVZvc1kwRkJXU3hWUVVGVExGVkJRVlFzUlVGQmNVSXNSMEZCY2tJc1JVRkJlVUk3UVVGRGJrTXNVVUZCU1N4UlFVRlJMRU5CUVZJc1EwRkVLMEk3TzBGQlIyNURMRk5CUVVrc1NVRkJTU3hKUVVGS0xFbEJRVmtzVlVGQmFFSXNSVUZCTWtJN1FVRkRla0lzVlVGQlJ5eEpRVUZKTEVsQlFVb3NRMEZCU0N4RlFVRmhPMEZCUTFnc1owSkJRVkVzVVVGQlVTeERRVUZTTEVOQlJFYzdUMEZCWWl4TlFVVkxPMEZCUTBnc1kwRkVSenRQUVVaTU8wdEJSRVk3TzBGQlVVRXNWMEZCVHl4WFFVRlhMRXRCUVZnc1EwRkJhVUlzUTBGQmFrSXNSVUZCYjBJc1MwRkJjRUlzUTBGQlVDeERRVmh0UXp0SFFVRjZRanM3UVVGaldpeFhRVUZUTEZWQlFWTXNWVUZCVkN4RlFVRnZRanRCUVVNelFpeFhRVUZQTEZWQlFWQXNRMEZFTWtJN1IwRkJjRUk3UTBGdVRWQTdPMEZCZDAxS0xHVkJRV1VzU1VGQlppSXNJbVpwYkdVaU9pSnNhV0l2Wlc1MWJTNXFjeUlzSW5OdmRYSmpaWE5EYjI1MFpXNTBJanBiSW1sdGNHOXlkQ0JEYjNKbElHWnliMjBnSnk0dlkyOXlaU2M3WEc1Y2JteGxkQ0JGYm5WdElEMGdlMXh1WEc0Z0lHRnNiRjlmY1cxaGNtdGZYem9nWm5WdVkzUnBiMjRvWTI5c2JHVmpkR2x2Yml3Z1puVnVJRDBnS0hncElEMCtJSGdwZTF4dUlDQWdJR1p2Y2loc1pYUWdaV3hsYlNCdlppQmpiMnhzWldOMGFXOXVLWHRjYmlBZ0lDQWdJR2xtS0NGbWRXNG9aV3hsYlNrcGUxeHVJQ0FnSUNBZ0lDQnlaWFIxY200Z1ptRnNjMlU3WEc0Z0lDQWdJQ0I5WEc0Z0lDQWdmVnh1WEc0Z0lDQWdjbVYwZFhKdUlIUnlkV1U3WEc0Z0lIMHNYRzVjYmlBZ1lXNTVYMTl4YldGeWExOWZPaUJtZFc1amRHbHZiaWhqYjJ4c1pXTjBhVzl1TENCbWRXNGdQU0FvZUNrZ1BUNGdlQ2w3WEc0Z0lDQWdabTl5S0d4bGRDQmxiR1Z0SUc5bUlHTnZiR3hsWTNScGIyNHBlMXh1SUNBZ0lDQWdhV1lvWm5WdUtHVnNaVzBwS1h0Y2JpQWdJQ0FnSUNBZ2NtVjBkWEp1SUhSeWRXVTdYRzRnSUNBZ0lDQjlYRzRnSUNBZ2ZWeHVYRzRnSUNBZ2NtVjBkWEp1SUdaaGJITmxPMXh1SUNCOUxGeHVYRzRnSUdGME9pQm1kVzVqZEdsdmJpaGpiMnhzWldOMGFXOXVMQ0J1TENCMGFHVmZaR1ZtWVhWc2RDQTlJRzUxYkd3cGUxeHVJQ0FnSUdsbUtHNGdQaUIwYUdsekxtTnZkVzUwS0dOdmJHeGxZM1JwYjI0cElIeDhJRzRnUENBd0tYdGNiaUFnSUNBZ0lISmxkSFZ5YmlCMGFHVmZaR1ZtWVhWc2REdGNiaUFnSUNCOVhHNWNiaUFnSUNCeVpYUjFjbTRnWTI5c2JHVmpkR2x2Ymx0dVhUdGNiaUFnZlN4Y2JseHVJQ0JqYjI1allYUTZJR1oxYm1OMGFXOXVLQzR1TG1WdWRXMWhZbXhsY3lsN1hHNGdJQ0FnY21WMGRYSnVJR1Z1ZFcxaFlteGxjMXN3WFM1amIyNWpZWFFvWlc1MWJXRmliR1Z6V3pGZEtUdGNiaUFnZlN4Y2JseHVJQ0JqYjNWdWREb2dablZ1WTNScGIyNG9ZMjlzYkdWamRHbHZiaXdnWm5WdUlEMGdiblZzYkNsN1hHNGdJQ0FnYVdZb1puVnVJRDA5SUc1MWJHd3BlMXh1SUNBZ0lDQWdjbVYwZFhKdUlHTnZiR3hsWTNScGIyNHViR1Z1WjNSb08xeHVJQ0FnSUgwZ1pXeHpaU0I3WEc0Z0lDQWdJQ0J5WlhSMWNtNGdZMjlzYkdWamRHbHZiaTVtYVd4MFpYSW9ablZ1S1M1c1pXNW5kR2c3WEc0Z0lDQWdmVnh1SUNCOUxGeHVYRzRnSUdSeWIzQTZJR1oxYm1OMGFXOXVLR052Ykd4bFkzUnBiMjRzSUdOdmRXNTBLWHRjYmlBZ0lDQnlaWFIxY200Z1kyOXNiR1ZqZEdsdmJpNXpiR2xqWlNoamIzVnVkQ2s3WEc0Z0lIMHNYRzVjYmlBZ1pISnZjRjkzYUdsc1pUb2dablZ1WTNScGIyNG9ZMjlzYkdWamRHbHZiaXdnWm5WdUtYdGNiaUFnSUNCc1pYUWdZMjkxYm5RZ1BTQXdPMXh1WEc0Z0lDQWdabTl5S0d4bGRDQmxiR1Z0SUc5bUlHTnZiR3hsWTNScGIyNHBlMXh1SUNBZ0lDQWdhV1lvWm5WdUtHVnNaVzBwS1h0Y2JpQWdJQ0FnSUNBZ1kyOTFiblFnUFNCamIzVnVkQ0FySURFN1hHNGdJQ0FnSUNCOVpXeHpaWHRjYmlBZ0lDQWdJQ0FnWW5KbFlXczdYRzRnSUNBZ0lDQjlYRzRnSUNBZ2ZWeHVYRzRnSUNBZ2NtVjBkWEp1SUdOdmJHeGxZM1JwYjI0dWMyeHBZMlVvWTI5MWJuUXBPMXh1SUNCOUxGeHVYRzRnSUdWaFkyZzZJR1oxYm1OMGFXOXVLR052Ykd4bFkzUnBiMjRzSUdaMWJpbDdYRzRnSUNBZ1ptOXlLR3hsZENCbGJHVnRJRzltSUdOdmJHeGxZM1JwYjI0cGUxeHVJQ0FnSUNBZ1puVnVLR1ZzWlcwcE8xeHVJQ0FnSUgxY2JpQWdmU3hjYmx4dUlDQmxiWEIwZVY5ZmNXMWhjbXRmWHpvZ1puVnVZM1JwYjI0b1kyOXNiR1ZqZEdsdmJpbDdYRzRnSUNBZ2NtVjBkWEp1SUdOdmJHeGxZM1JwYjI0dWJHVnVaM1JvSUQwOVBTQXdPMXh1SUNCOUxGeHVYRzRnSUdabGRHTm9PaUJtZFc1amRHbHZiaWhqYjJ4c1pXTjBhVzl1TENCdUtYdGNiaUFnSUNCcFppaEJjbkpoZVM1cGMwRnljbUY1S0dOdmJHeGxZM1JwYjI0cEtYdGNiaUFnSUNBZ0lHbG1LRzRnUENCMGFHbHpMbU52ZFc1MEtHTnZiR3hsWTNScGIyNHBJQ1ltSUc0Z1BqMGdNQ2w3WEc0Z0lDQWdJQ0FnSUhKbGRIVnliaUJ1WlhjZ1EyOXlaUzVVZFhCc1pTaFRlVzFpYjJ3dVptOXlLRndpYjJ0Y0lpa3NJR052Ykd4bFkzUnBiMjViYmwwcE8xeHVJQ0FnSUNBZ2ZXVnNjMlY3WEc0Z0lDQWdJQ0FnSUhKbGRIVnliaUJUZVcxaWIyd3VabTl5S0Z3aVpYSnliM0pjSWlrN1hHNGdJQ0FnSUNCOVhHNGdJQ0FnZlZ4dVhHNGdJQ0FnZEdoeWIzY2dibVYzSUVWeWNtOXlLRndpWTI5c2JHVmpkR2x2YmlCcGN5QnViM1FnWVc0Z1JXNTFiV1Z5WVdKc1pWd2lLVHRjYmlBZ2ZTeGNibHh1SUNCbVpYUmphRjlmWlcxaGNtdGZYem9nWm5WdVkzUnBiMjRvWTI5c2JHVmpkR2x2Yml3Z2JpbDdYRzRnSUNBZ2FXWW9RWEp5WVhrdWFYTkJjbkpoZVNoamIyeHNaV04wYVc5dUtTbDdYRzRnSUNBZ0lDQnBaaWh1SUR3Z2RHaHBjeTVqYjNWdWRDaGpiMnhzWldOMGFXOXVLU0FtSmlCdUlENDlJREFwZTF4dUlDQWdJQ0FnSUNCeVpYUjFjbTRnWTI5c2JHVmpkR2x2Ymx0dVhUdGNiaUFnSUNBZ0lIMWxiSE5sZTF4dUlDQWdJQ0FnSUNCMGFISnZkeUJ1WlhjZ1JYSnliM0lvWENKdmRYUWdiMllnWW05MWJtUnpJR1Z5Y205eVhDSXBPMXh1SUNBZ0lDQWdmVnh1SUNBZ0lIMWNibHh1SUNBZ0lIUm9jbTkzSUc1bGR5QkZjbkp2Y2loY0ltTnZiR3hsWTNScGIyNGdhWE1nYm05MElHRnVJRVZ1ZFcxbGNtRmliR1ZjSWlrN1hHNGdJSDBzWEc1Y2JpQWdabWxzZEdWeU9pQm1kVzVqZEdsdmJpaGpiMnhzWldOMGFXOXVMQ0JtZFc0cGUxeHVJQ0FnSUd4bGRDQnlaWE4xYkhRZ1BTQmJYVHRjYmx4dUlDQWdJR1p2Y2loc1pYUWdaV3hsYlNCdlppQmpiMnhzWldOMGFXOXVLWHRjYmlBZ0lDQWdJR2xtS0daMWJpaGxiR1Z0S1NsN1hHNGdJQ0FnSUNBZ0lISmxjM1ZzZEM1d2RYTm9LR1ZzWlcwcE8xeHVJQ0FnSUNBZ2ZWeHVJQ0FnSUgxY2JseHVJQ0FnSUhKbGRIVnliaUJ5WlhOMWJIUTdYRzRnSUgwc1hHNWNiaUFnWm1sc2RHVnlYMjFoY0RvZ1puVnVZM1JwYjI0b1kyOXNiR1ZqZEdsdmJpd2dabWxzZEdWeUxDQnRZWEJ3WlhJcGUxeHVJQ0FnSUhKbGRIVnliaUJGYm5WdExtMWhjQ2hGYm5WdExtWnBiSFJsY2loamIyeHNaV04wYVc5dUxDQm1hV3gwWlhJcExDQnRZWEJ3WlhJcE8xeHVJQ0I5TEZ4dVhHNGdJR1pwYm1RNklHWjFibU4wYVc5dUtHTnZiR3hsWTNScGIyNHNJR2xtWDI1dmJtVWdQU0J1ZFd4c0xDQm1kVzRwZTF4dUlDQWdJR1p2Y2loc1pYUWdaV3hsYlNCdlppQmpiMnhzWldOMGFXOXVLWHRjYmlBZ0lDQWdJR2xtS0daMWJpaGxiR1Z0S1NsN1hHNGdJQ0FnSUNBZ0lISmxkSFZ5YmlCbGJHVnRPMXh1SUNBZ0lDQWdmVnh1SUNBZ0lIMWNibHh1SUNBZ0lISmxkSFZ5YmlCcFpsOXViMjVsTzF4dUlDQjlMRnh1WEc0Z0lHbHVkRzg2SUdaMWJtTjBhVzl1S0dOdmJHeGxZM1JwYjI0c0lHeHBjM1FwZTF4dUlDQWdJSEpsZEhWeWJpQnNhWE4wTG1OdmJtTmhkQ2hqYjJ4c1pXTjBhVzl1S1R0Y2JpQWdmU3hjYmx4dUlDQnRZWEE2SUdaMWJtTjBhVzl1S0dOdmJHeGxZM1JwYjI0c0lHWjFiaWw3WEc0Z0lDQWdiR1YwSUhKbGMzVnNkQ0E5SUZ0ZE8xeHVYRzRnSUNBZ1ptOXlLR3hsZENCbGJHVnRJRzltSUdOdmJHeGxZM1JwYjI0cGUxeHVJQ0FnSUNBZ2NtVnpkV3gwTG5CMWMyZ29ablZ1S0dWc1pXMHBLVHRjYmlBZ0lDQjlYRzVjYmlBZ0lDQnlaWFIxY200Z2NtVnpkV3gwTzF4dUlDQjlMRnh1WEc0Z0lHMWhjRjl5WldSMVkyVTZJR1oxYm1OMGFXOXVLR052Ykd4bFkzUnBiMjRzSUdGall5d2dablZ1S1h0Y2JpQWdJQ0JzWlhRZ2JXRndjR1ZrSUQwZ1QySnFaV04wTG1aeVpXVjZaU2hiWFNrN1hHNGdJQ0FnYkdWMElIUm9aVjloWTJNZ1BTQmhZMk03WEc1Y2JpQWdJQ0JtYjNJZ0tIWmhjaUJwSUQwZ01Ec2dhU0E4SUhSb2FYTXVZMjkxYm5Rb1kyOXNiR1ZqZEdsdmJpazdJR2tyS3lrZ2UxeHVJQ0FnSUNBZ2JHVjBJSFIxY0d4bElEMGdablZ1S0dOdmJHeGxZM1JwYjI1YmFWMHNJSFJvWlY5aFkyTXBPMXh1WEc0Z0lDQWdJQ0IwYUdWZllXTmpJRDBnZEhWd2JHVXVaMlYwS0RFcE8xeHVJQ0FnSUNBZ2JXRndjR1ZrSUQwZ1QySnFaV04wTG1aeVpXVjZaU2h0WVhCd1pXUXVZMjl1WTJGMEtGdDBkWEJzWlM1blpYUW9NQ2xkS1NrN1hHNGdJQ0FnZlZ4dVhHNGdJQ0FnY21WMGRYSnVJRzVsZHlCRGIzSmxMbFIxY0d4bEtHMWhjSEJsWkN3Z2RHaGxYMkZqWXlrN1hHNGdJSDBzWEc1Y2JpQWdiV1Z0WW1WeVgxOXhiV0Z5YTE5Zk9pQm1kVzVqZEdsdmJpaGpiMnhzWldOMGFXOXVMQ0IyWVd4MVpTbDdYRzRnSUNBZ2NtVjBkWEp1SUdOdmJHeGxZM1JwYjI0dWFXNWpiSFZrWlhNb2RtRnNkV1VwTzF4dUlDQjlMRnh1WEc0Z0lISmxaSFZqWlRvZ1puVnVZM1JwYjI0b1kyOXNiR1ZqZEdsdmJpd2dZV05qTENCbWRXNHBlMXh1SUNBZ0lHeGxkQ0IwYUdWZllXTmpJRDBnWVdOak8xeHVYRzRnSUNBZ1ptOXlJQ2gyWVhJZ2FTQTlJREE3SUdrZ1BDQjBhR2x6TG1OdmRXNTBLR052Ykd4bFkzUnBiMjRwT3lCcEt5c3BJSHRjYmlBZ0lDQWdJR3hsZENCMGRYQnNaU0E5SUdaMWJpaGpiMnhzWldOMGFXOXVXMmxkTENCMGFHVmZZV05qS1R0Y2JseHVJQ0FnSUNBZ2RHaGxYMkZqWXlBOUlIUjFjR3hsTG1kbGRDZ3hLVHRjYmlBZ0lDQjlYRzVjYmlBZ0lDQnlaWFIxY200Z2RHaGxYMkZqWXp0Y2JpQWdmU3hjYmx4dUlDQjBZV3RsT2lCbWRXNWpkR2x2YmloamIyeHNaV04wYVc5dUxDQmpiM1Z1ZENsN1hHNGdJQ0FnY21WMGRYSnVJR052Ykd4bFkzUnBiMjR1YzJ4cFkyVW9NQ3dnWTI5MWJuUXBPMXh1SUNCOUxGeHVYRzRnSUhSaGEyVmZaWFpsY25rNklHWjFibU4wYVc5dUtHTnZiR3hsWTNScGIyNHNJRzUwYUNsN1hHNGdJQ0FnYkdWMElISmxjM1ZzZENBOUlGdGRPMXh1SUNBZ0lHeGxkQ0JwYm1SbGVDQTlJREE3WEc1Y2JpQWdJQ0JtYjNJb2JHVjBJR1ZzWlcwZ2IyWWdZMjlzYkdWamRHbHZiaWw3WEc0Z0lDQWdJQ0JwWmlocGJtUmxlQ0FsSUc1MGFDQTlQVDBnTUNsN1hHNGdJQ0FnSUNBZ0lISmxjM1ZzZEM1d2RYTm9LR1ZzWlcwcE8xeHVJQ0FnSUNBZ2ZWeHVJQ0FnSUgxY2JseHVJQ0FnSUhKbGRIVnliaUJQWW1wbFkzUXVabkpsWlhwbEtISmxjM1ZzZENrN1hHNGdJSDBzWEc1Y2JpQWdkR0ZyWlY5M2FHbHNaVG9nWm5WdVkzUnBiMjRvWTI5c2JHVmpkR2x2Yml3Z1puVnVLWHRjYmlBZ0lDQnNaWFFnWTI5MWJuUWdQU0F3TzF4dVhHNGdJQ0FnWm05eUtHeGxkQ0JsYkdWdElHOW1JR052Ykd4bFkzUnBiMjRwZTF4dUlDQWdJQ0FnYVdZb1puVnVLR1ZzWlcwcEtYdGNiaUFnSUNBZ0lDQWdZMjkxYm5RZ1BTQmpiM1Z1ZENBcklERTdYRzRnSUNBZ0lDQjlaV3h6Wlh0Y2JpQWdJQ0FnSUNBZ1luSmxZV3M3WEc0Z0lDQWdJQ0I5WEc0Z0lDQWdmVnh1WEc0Z0lDQWdjbVYwZFhKdUlHTnZiR3hsWTNScGIyNHVjMnhwWTJVb01Dd2dZMjkxYm5RcE8xeHVJQ0I5TEZ4dVhHNGdJSFJ2WDJ4cGMzUTZJR1oxYm1OMGFXOXVLR052Ykd4bFkzUnBiMjRwZTF4dUlDQWdJSEpsZEhWeWJpQmpiMnhzWldOMGFXOXVPMXh1SUNCOVhHNTlPMXh1WEc1bGVIQnZjblFnWkdWbVlYVnNkQ0JGYm5WdE8xeHVJbDBzSW5OdmRYSmpaVkp2YjNRaU9pSXZjMjkxY21ObEx5SjlcbiIsImxldCBWaXJ0dWFsRE9NID0gZnVuY3Rpb24gKGUpIHtcbiAgICByZXR1cm4gZSgpO1xufShmdW5jdGlvbiAoKSB7XG4gICAgdmFyIGRlZmluZSwgbW9kdWxlLCBleHBvcnRzO1xuICAgIHJldHVybiBmdW5jdGlvbiBlKHQsIG4sIHIpIHtcbiAgICAgICAgZnVuY3Rpb24gcyhvLCB1KSB7XG4gICAgICAgICAgICBpZiAoIW5bb10pIHtcbiAgICAgICAgICAgICAgICBpZiAoIXRbb10pIHtcbiAgICAgICAgICAgICAgICAgICAgdmFyIGEgPSB0eXBlb2YgcmVxdWlyZSA9PSBcImZ1bmN0aW9uXCIgJiYgcmVxdWlyZTtcbiAgICAgICAgICAgICAgICAgICAgaWYgKCF1ICYmIGEpIHJldHVybiBhKG8sICEwKTtcbiAgICAgICAgICAgICAgICAgICAgaWYgKGkpIHJldHVybiBpKG8sICEwKTtcbiAgICAgICAgICAgICAgICAgICAgdmFyIGYgPSBuZXcgRXJyb3IoXCJDYW5ub3QgZmluZCBtb2R1bGUgJ1wiICsgbyArIFwiJ1wiKTtcbiAgICAgICAgICAgICAgICAgICAgdGhyb3cgZi5jb2RlID0gXCJNT0RVTEVfTk9UX0ZPVU5EXCIsIGY7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHZhciBsID0gbltvXSA9IHtcbiAgICAgICAgICAgICAgICAgICAgZXhwb3J0czoge31cbiAgICAgICAgICAgICAgICB9O1xuICAgICAgICAgICAgICAgIHRbb11bMF0uY2FsbChsLmV4cG9ydHMsIGZ1bmN0aW9uIChlKSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciBuID0gdFtvXVsxXVtlXTtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHMobiA/IG4gOiBlKTtcbiAgICAgICAgICAgICAgICB9LCBsLCBsLmV4cG9ydHMsIGUsIHQsIG4sIHIpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmV0dXJuIG5bb10uZXhwb3J0cztcbiAgICAgICAgfVxuICAgICAgICB2YXIgaSA9IHR5cGVvZiByZXF1aXJlID09IFwiZnVuY3Rpb25cIiAmJiByZXF1aXJlO1xuICAgICAgICBmb3IgKHZhciBvID0gMDsgbyA8IHIubGVuZ3RoOyBvKyspIHMocltvXSk7XG4gICAgICAgIHJldHVybiBzO1xuICAgIH0oe1xuICAgICAgICAxOiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge1xuXG4gICAgICAgICAgICB2YXIgY3JlYXRlRWxlbWVudCA9IHJlcXVpcmUoXCIuL3Zkb20vY3JlYXRlLWVsZW1lbnQuanNcIik7XG5cbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gY3JlYXRlRWxlbWVudDtcbiAgICAgICAgfSwgeyBcIi4vdmRvbS9jcmVhdGUtZWxlbWVudC5qc1wiOiAxNSB9XSwgMjogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHtcbiAgICAgICAgICAgIHZhciBkaWZmID0gcmVxdWlyZShcIi4vdnRyZWUvZGlmZi5qc1wiKTtcblxuICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBkaWZmO1xuICAgICAgICB9LCB7IFwiLi92dHJlZS9kaWZmLmpzXCI6IDM1IH1dLCAzOiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge1xuICAgICAgICAgICAgdmFyIGggPSByZXF1aXJlKFwiLi92aXJ0dWFsLWh5cGVyc2NyaXB0L2luZGV4LmpzXCIpO1xuXG4gICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IGg7XG4gICAgICAgIH0sIHsgXCIuL3ZpcnR1YWwtaHlwZXJzY3JpcHQvaW5kZXguanNcIjogMjIgfV0sIDQ6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICB2YXIgZGlmZiA9IHJlcXVpcmUoXCIuL2RpZmYuanNcIik7XG4gICAgICAgICAgICB2YXIgcGF0Y2ggPSByZXF1aXJlKFwiLi9wYXRjaC5qc1wiKTtcbiAgICAgICAgICAgIHZhciBoID0gcmVxdWlyZShcIi4vaC5qc1wiKTtcbiAgICAgICAgICAgIHZhciBjcmVhdGUgPSByZXF1aXJlKFwiLi9jcmVhdGUtZWxlbWVudC5qc1wiKTtcbiAgICAgICAgICAgIHZhciBWTm9kZSA9IHJlcXVpcmUoJy4vdm5vZGUvdm5vZGUuanMnKTtcbiAgICAgICAgICAgIHZhciBWVGV4dCA9IHJlcXVpcmUoJy4vdm5vZGUvdnRleHQuanMnKTtcblxuICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSB7XG4gICAgICAgICAgICAgICAgZGlmZjogZGlmZixcbiAgICAgICAgICAgICAgICBwYXRjaDogcGF0Y2gsXG4gICAgICAgICAgICAgICAgaDogaCxcbiAgICAgICAgICAgICAgICBjcmVhdGU6IGNyZWF0ZSxcbiAgICAgICAgICAgICAgICBWTm9kZTogVk5vZGUsXG4gICAgICAgICAgICAgICAgVlRleHQ6IFZUZXh0XG4gICAgICAgICAgICB9O1xuICAgICAgICB9LCB7IFwiLi9jcmVhdGUtZWxlbWVudC5qc1wiOiAxLCBcIi4vZGlmZi5qc1wiOiAyLCBcIi4vaC5qc1wiOiAzLCBcIi4vcGF0Y2guanNcIjogMTMsIFwiLi92bm9kZS92bm9kZS5qc1wiOiAzMSwgXCIuL3Zub2RlL3Z0ZXh0LmpzXCI6IDMzIH1dLCA1OiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge1xuICAgICAgICAgICAgLyohXG4gICAgICAgICAgICAgKiBDcm9zcy1Ccm93c2VyIFNwbGl0IDEuMS4xXG4gICAgICAgICAgICAgKiBDb3B5cmlnaHQgMjAwNy0yMDEyIFN0ZXZlbiBMZXZpdGhhbiA8c3RldmVubGV2aXRoYW4uY29tPlxuICAgICAgICAgICAgICogQXZhaWxhYmxlIHVuZGVyIHRoZSBNSVQgTGljZW5zZVxuICAgICAgICAgICAgICogRUNNQVNjcmlwdCBjb21wbGlhbnQsIHVuaWZvcm0gY3Jvc3MtYnJvd3NlciBzcGxpdCBtZXRob2RcbiAgICAgICAgICAgICAqL1xuXG4gICAgICAgICAgICAvKipcbiAgICAgICAgICAgICAqIFNwbGl0cyBhIHN0cmluZyBpbnRvIGFuIGFycmF5IG9mIHN0cmluZ3MgdXNpbmcgYSByZWdleCBvciBzdHJpbmcgc2VwYXJhdG9yLiBNYXRjaGVzIG9mIHRoZVxuICAgICAgICAgICAgICogc2VwYXJhdG9yIGFyZSBub3QgaW5jbHVkZWQgaW4gdGhlIHJlc3VsdCBhcnJheS4gSG93ZXZlciwgaWYgYHNlcGFyYXRvcmAgaXMgYSByZWdleCB0aGF0IGNvbnRhaW5zXG4gICAgICAgICAgICAgKiBjYXB0dXJpbmcgZ3JvdXBzLCBiYWNrcmVmZXJlbmNlcyBhcmUgc3BsaWNlZCBpbnRvIHRoZSByZXN1bHQgZWFjaCB0aW1lIGBzZXBhcmF0b3JgIGlzIG1hdGNoZWQuXG4gICAgICAgICAgICAgKiBGaXhlcyBicm93c2VyIGJ1Z3MgY29tcGFyZWQgdG8gdGhlIG5hdGl2ZSBgU3RyaW5nLnByb3RvdHlwZS5zcGxpdGAgYW5kIGNhbiBiZSB1c2VkIHJlbGlhYmx5XG4gICAgICAgICAgICAgKiBjcm9zcy1icm93c2VyLlxuICAgICAgICAgICAgICogQHBhcmFtIHtTdHJpbmd9IHN0ciBTdHJpbmcgdG8gc3BsaXQuXG4gICAgICAgICAgICAgKiBAcGFyYW0ge1JlZ0V4cHxTdHJpbmd9IHNlcGFyYXRvciBSZWdleCBvciBzdHJpbmcgdG8gdXNlIGZvciBzZXBhcmF0aW5nIHRoZSBzdHJpbmcuXG4gICAgICAgICAgICAgKiBAcGFyYW0ge051bWJlcn0gW2xpbWl0XSBNYXhpbXVtIG51bWJlciBvZiBpdGVtcyB0byBpbmNsdWRlIGluIHRoZSByZXN1bHQgYXJyYXkuXG4gICAgICAgICAgICAgKiBAcmV0dXJucyB7QXJyYXl9IEFycmF5IG9mIHN1YnN0cmluZ3MuXG4gICAgICAgICAgICAgKiBAZXhhbXBsZVxuICAgICAgICAgICAgICpcbiAgICAgICAgICAgICAqIC8vIEJhc2ljIHVzZVxuICAgICAgICAgICAgICogc3BsaXQoJ2EgYiBjIGQnLCAnICcpO1xuICAgICAgICAgICAgICogLy8gLT4gWydhJywgJ2InLCAnYycsICdkJ11cbiAgICAgICAgICAgICAqXG4gICAgICAgICAgICAgKiAvLyBXaXRoIGxpbWl0XG4gICAgICAgICAgICAgKiBzcGxpdCgnYSBiIGMgZCcsICcgJywgMik7XG4gICAgICAgICAgICAgKiAvLyAtPiBbJ2EnLCAnYiddXG4gICAgICAgICAgICAgKlxuICAgICAgICAgICAgICogLy8gQmFja3JlZmVyZW5jZXMgaW4gcmVzdWx0IGFycmF5XG4gICAgICAgICAgICAgKiBzcGxpdCgnLi53b3JkMSB3b3JkMi4uJywgLyhbYS16XSspKFxcZCspL2kpO1xuICAgICAgICAgICAgICogLy8gLT4gWycuLicsICd3b3JkJywgJzEnLCAnICcsICd3b3JkJywgJzInLCAnLi4nXVxuICAgICAgICAgICAgICovXG4gICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uIHNwbGl0KHVuZGVmKSB7XG5cbiAgICAgICAgICAgICAgICB2YXIgbmF0aXZlU3BsaXQgPSBTdHJpbmcucHJvdG90eXBlLnNwbGl0LFxuICAgICAgICAgICAgICAgICAgICBjb21wbGlhbnRFeGVjTnBjZyA9IC8oKT8/Ly5leGVjKFwiXCIpWzFdID09PSB1bmRlZixcblxuICAgICAgICAgICAgICAgIC8vIE5QQ0c6IG5vbnBhcnRpY2lwYXRpbmcgY2FwdHVyaW5nIGdyb3VwXG4gICAgICAgICAgICAgICAgc2VsZjtcblxuICAgICAgICAgICAgICAgIHNlbGYgPSBmdW5jdGlvbiAoc3RyLCBzZXBhcmF0b3IsIGxpbWl0KSB7XG4gICAgICAgICAgICAgICAgICAgIC8vIElmIGBzZXBhcmF0b3JgIGlzIG5vdCBhIHJlZ2V4LCB1c2UgYG5hdGl2ZVNwbGl0YFxuICAgICAgICAgICAgICAgICAgICBpZiAoT2JqZWN0LnByb3RvdHlwZS50b1N0cmluZy5jYWxsKHNlcGFyYXRvcikgIT09IFwiW29iamVjdCBSZWdFeHBdXCIpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBuYXRpdmVTcGxpdC5jYWxsKHN0ciwgc2VwYXJhdG9yLCBsaW1pdCk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgdmFyIG91dHB1dCA9IFtdLFxuICAgICAgICAgICAgICAgICAgICAgICAgZmxhZ3MgPSAoc2VwYXJhdG9yLmlnbm9yZUNhc2UgPyBcImlcIiA6IFwiXCIpICsgKHNlcGFyYXRvci5tdWx0aWxpbmUgPyBcIm1cIiA6IFwiXCIpICsgKHNlcGFyYXRvci5leHRlbmRlZCA/IFwieFwiIDogXCJcIikgKyAoIC8vIFByb3Bvc2VkIGZvciBFUzZcbiAgICAgICAgICAgICAgICAgICAgc2VwYXJhdG9yLnN0aWNreSA/IFwieVwiIDogXCJcIiksXG5cbiAgICAgICAgICAgICAgICAgICAgLy8gRmlyZWZveCAzK1xuICAgICAgICAgICAgICAgICAgICBsYXN0TGFzdEluZGV4ID0gMCxcblxuICAgICAgICAgICAgICAgICAgICAvLyBNYWtlIGBnbG9iYWxgIGFuZCBhdm9pZCBgbGFzdEluZGV4YCBpc3N1ZXMgYnkgd29ya2luZyB3aXRoIGEgY29weVxuICAgICAgICAgICAgICAgICAgICBzZXBhcmF0b3IgPSBuZXcgUmVnRXhwKHNlcGFyYXRvci5zb3VyY2UsIGZsYWdzICsgXCJnXCIpLFxuICAgICAgICAgICAgICAgICAgICAgICAgc2VwYXJhdG9yMixcbiAgICAgICAgICAgICAgICAgICAgICAgIG1hdGNoLFxuICAgICAgICAgICAgICAgICAgICAgICAgbGFzdEluZGV4LFxuICAgICAgICAgICAgICAgICAgICAgICAgbGFzdExlbmd0aDtcbiAgICAgICAgICAgICAgICAgICAgc3RyICs9IFwiXCI7IC8vIFR5cGUtY29udmVydFxuICAgICAgICAgICAgICAgICAgICBpZiAoIWNvbXBsaWFudEV4ZWNOcGNnKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAvLyBEb2Vzbid0IG5lZWQgZmxhZ3MgZ3ksIGJ1dCB0aGV5IGRvbid0IGh1cnRcbiAgICAgICAgICAgICAgICAgICAgICAgIHNlcGFyYXRvcjIgPSBuZXcgUmVnRXhwKFwiXlwiICsgc2VwYXJhdG9yLnNvdXJjZSArIFwiJCg/IVxcXFxzKVwiLCBmbGFncyk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgLyogVmFsdWVzIGZvciBgbGltaXRgLCBwZXIgdGhlIHNwZWM6XG4gICAgICAgICAgICAgICAgICAgICAqIElmIHVuZGVmaW5lZDogNDI5NDk2NzI5NSAvLyBNYXRoLnBvdygyLCAzMikgLSAxXG4gICAgICAgICAgICAgICAgICAgICAqIElmIDAsIEluZmluaXR5LCBvciBOYU46IDBcbiAgICAgICAgICAgICAgICAgICAgICogSWYgcG9zaXRpdmUgbnVtYmVyOiBsaW1pdCA9IE1hdGguZmxvb3IobGltaXQpOyBpZiAobGltaXQgPiA0Mjk0OTY3Mjk1KSBsaW1pdCAtPSA0Mjk0OTY3Mjk2O1xuICAgICAgICAgICAgICAgICAgICAgKiBJZiBuZWdhdGl2ZSBudW1iZXI6IDQyOTQ5NjcyOTYgLSBNYXRoLmZsb29yKE1hdGguYWJzKGxpbWl0KSlcbiAgICAgICAgICAgICAgICAgICAgICogSWYgb3RoZXI6IFR5cGUtY29udmVydCwgdGhlbiB1c2UgdGhlIGFib3ZlIHJ1bGVzXG4gICAgICAgICAgICAgICAgICAgICAqL1xuICAgICAgICAgICAgICAgICAgICBsaW1pdCA9IGxpbWl0ID09PSB1bmRlZiA/IC0xID4+PiAwIDogLy8gTWF0aC5wb3coMiwgMzIpIC0gMVxuICAgICAgICAgICAgICAgICAgICBsaW1pdCA+Pj4gMDsgLy8gVG9VaW50MzIobGltaXQpXG4gICAgICAgICAgICAgICAgICAgIHdoaWxlIChtYXRjaCA9IHNlcGFyYXRvci5leGVjKHN0cikpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIGBzZXBhcmF0b3IubGFzdEluZGV4YCBpcyBub3QgcmVsaWFibGUgY3Jvc3MtYnJvd3NlclxuICAgICAgICAgICAgICAgICAgICAgICAgbGFzdEluZGV4ID0gbWF0Y2guaW5kZXggKyBtYXRjaFswXS5sZW5ndGg7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAobGFzdEluZGV4ID4gbGFzdExhc3RJbmRleCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIG91dHB1dC5wdXNoKHN0ci5zbGljZShsYXN0TGFzdEluZGV4LCBtYXRjaC5pbmRleCkpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIEZpeCBicm93c2VycyB3aG9zZSBgZXhlY2AgbWV0aG9kcyBkb24ndCBjb25zaXN0ZW50bHkgcmV0dXJuIGB1bmRlZmluZWRgIGZvclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIG5vbnBhcnRpY2lwYXRpbmcgY2FwdHVyaW5nIGdyb3Vwc1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmICghY29tcGxpYW50RXhlY05wY2cgJiYgbWF0Y2gubGVuZ3RoID4gMSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBtYXRjaFswXS5yZXBsYWNlKHNlcGFyYXRvcjIsIGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZvciAodmFyIGkgPSAxOyBpIDwgYXJndW1lbnRzLmxlbmd0aCAtIDI7IGkrKykge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChhcmd1bWVudHNbaV0gPT09IHVuZGVmKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1hdGNoW2ldID0gdW5kZWY7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKG1hdGNoLmxlbmd0aCA+IDEgJiYgbWF0Y2guaW5kZXggPCBzdHIubGVuZ3RoKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIEFycmF5LnByb3RvdHlwZS5wdXNoLmFwcGx5KG91dHB1dCwgbWF0Y2guc2xpY2UoMSkpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBsYXN0TGVuZ3RoID0gbWF0Y2hbMF0ubGVuZ3RoO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxhc3RMYXN0SW5kZXggPSBsYXN0SW5kZXg7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKG91dHB1dC5sZW5ndGggPj0gbGltaXQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHNlcGFyYXRvci5sYXN0SW5kZXggPT09IG1hdGNoLmluZGV4KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgc2VwYXJhdG9yLmxhc3RJbmRleCsrOyAvLyBBdm9pZCBhbiBpbmZpbml0ZSBsb29wXG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgaWYgKGxhc3RMYXN0SW5kZXggPT09IHN0ci5sZW5ndGgpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChsYXN0TGVuZ3RoIHx8ICFzZXBhcmF0b3IudGVzdChcIlwiKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIG91dHB1dC5wdXNoKFwiXCIpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgb3V0cHV0LnB1c2goc3RyLnNsaWNlKGxhc3RMYXN0SW5kZXgpKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICByZXR1cm4gb3V0cHV0Lmxlbmd0aCA+IGxpbWl0ID8gb3V0cHV0LnNsaWNlKDAsIGxpbWl0KSA6IG91dHB1dDtcbiAgICAgICAgICAgICAgICB9O1xuXG4gICAgICAgICAgICAgICAgcmV0dXJuIHNlbGY7XG4gICAgICAgICAgICB9KCk7XG4gICAgICAgIH0sIHt9XSwgNjogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHt9LCB7fV0sIDc6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICAndXNlIHN0cmljdCc7XG5cbiAgICAgICAgICAgIHZhciBPbmVWZXJzaW9uQ29uc3RyYWludCA9IHJlcXVpcmUoJ2luZGl2aWR1YWwvb25lLXZlcnNpb24nKTtcblxuICAgICAgICAgICAgdmFyIE1ZX1ZFUlNJT04gPSAnNyc7XG4gICAgICAgICAgICBPbmVWZXJzaW9uQ29uc3RyYWludCgnZXYtc3RvcmUnLCBNWV9WRVJTSU9OKTtcblxuICAgICAgICAgICAgdmFyIGhhc2hLZXkgPSAnX19FVl9TVE9SRV9LRVlAJyArIE1ZX1ZFUlNJT047XG5cbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gRXZTdG9yZTtcblxuICAgICAgICAgICAgZnVuY3Rpb24gRXZTdG9yZShlbGVtKSB7XG4gICAgICAgICAgICAgICAgdmFyIGhhc2ggPSBlbGVtW2hhc2hLZXldO1xuXG4gICAgICAgICAgICAgICAgaWYgKCFoYXNoKSB7XG4gICAgICAgICAgICAgICAgICAgIGhhc2ggPSBlbGVtW2hhc2hLZXldID0ge307XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgcmV0dXJuIGhhc2g7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0sIHsgXCJpbmRpdmlkdWFsL29uZS12ZXJzaW9uXCI6IDkgfV0sIDg6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICAoZnVuY3Rpb24gKGdsb2JhbCkge1xuICAgICAgICAgICAgICAgICd1c2Ugc3RyaWN0JztcblxuICAgICAgICAgICAgICAgIC8qZ2xvYmFsIHdpbmRvdywgZ2xvYmFsKi9cblxuICAgICAgICAgICAgICAgIHZhciByb290ID0gdHlwZW9mIHdpbmRvdyAhPT0gJ3VuZGVmaW5lZCcgPyB3aW5kb3cgOiB0eXBlb2YgZ2xvYmFsICE9PSAndW5kZWZpbmVkJyA/IGdsb2JhbCA6IHt9O1xuXG4gICAgICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBJbmRpdmlkdWFsO1xuXG4gICAgICAgICAgICAgICAgZnVuY3Rpb24gSW5kaXZpZHVhbChrZXksIHZhbHVlKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmIChrZXkgaW4gcm9vdCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHJvb3Rba2V5XTtcbiAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgIHJvb3Rba2V5XSA9IHZhbHVlO1xuXG4gICAgICAgICAgICAgICAgICAgIHJldHVybiB2YWx1ZTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9KS5jYWxsKHRoaXMsIHR5cGVvZiBnbG9iYWwgIT09IFwidW5kZWZpbmVkXCIgPyBnbG9iYWwgOiB0eXBlb2Ygc2VsZiAhPT0gXCJ1bmRlZmluZWRcIiA/IHNlbGYgOiB0eXBlb2Ygd2luZG93ICE9PSBcInVuZGVmaW5lZFwiID8gd2luZG93IDoge30pO1xuICAgICAgICB9LCB7fV0sIDk6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICAndXNlIHN0cmljdCc7XG5cbiAgICAgICAgICAgIHZhciBJbmRpdmlkdWFsID0gcmVxdWlyZSgnLi9pbmRleC5qcycpO1xuXG4gICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IE9uZVZlcnNpb247XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIE9uZVZlcnNpb24obW9kdWxlTmFtZSwgdmVyc2lvbiwgZGVmYXVsdFZhbHVlKSB7XG4gICAgICAgICAgICAgICAgdmFyIGtleSA9ICdfX0lORElWSURVQUxfT05FX1ZFUlNJT05fJyArIG1vZHVsZU5hbWU7XG4gICAgICAgICAgICAgICAgdmFyIGVuZm9yY2VLZXkgPSBrZXkgKyAnX0VORk9SQ0VfU0lOR0xFVE9OJztcblxuICAgICAgICAgICAgICAgIHZhciB2ZXJzaW9uVmFsdWUgPSBJbmRpdmlkdWFsKGVuZm9yY2VLZXksIHZlcnNpb24pO1xuXG4gICAgICAgICAgICAgICAgaWYgKHZlcnNpb25WYWx1ZSAhPT0gdmVyc2lvbikge1xuICAgICAgICAgICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ0NhbiBvbmx5IGhhdmUgb25lIGNvcHkgb2YgJyArIG1vZHVsZU5hbWUgKyAnLlxcbicgKyAnWW91IGFscmVhZHkgaGF2ZSB2ZXJzaW9uICcgKyB2ZXJzaW9uVmFsdWUgKyAnIGluc3RhbGxlZC5cXG4nICsgJ1RoaXMgbWVhbnMgeW91IGNhbm5vdCBpbnN0YWxsIHZlcnNpb24gJyArIHZlcnNpb24pO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHJldHVybiBJbmRpdmlkdWFsKGtleSwgZGVmYXVsdFZhbHVlKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSwgeyBcIi4vaW5kZXguanNcIjogOCB9XSwgMTA6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICAoZnVuY3Rpb24gKGdsb2JhbCkge1xuICAgICAgICAgICAgICAgIHZhciB0b3BMZXZlbCA9IHR5cGVvZiBnbG9iYWwgIT09ICd1bmRlZmluZWQnID8gZ2xvYmFsIDogdHlwZW9mIHdpbmRvdyAhPT0gJ3VuZGVmaW5lZCcgPyB3aW5kb3cgOiB7fTtcbiAgICAgICAgICAgICAgICB2YXIgbWluRG9jID0gcmVxdWlyZSgnbWluLWRvY3VtZW50Jyk7XG5cbiAgICAgICAgICAgICAgICBpZiAodHlwZW9mIGRvY3VtZW50ICE9PSAndW5kZWZpbmVkJykge1xuICAgICAgICAgICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IGRvY3VtZW50O1xuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciBkb2NjeSA9IHRvcExldmVsWydfX0dMT0JBTF9ET0NVTUVOVF9DQUNIRUA0J107XG5cbiAgICAgICAgICAgICAgICAgICAgaWYgKCFkb2NjeSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgZG9jY3kgPSB0b3BMZXZlbFsnX19HTE9CQUxfRE9DVU1FTlRfQ0FDSEVANCddID0gbWluRG9jO1xuICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBkb2NjeTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9KS5jYWxsKHRoaXMsIHR5cGVvZiBnbG9iYWwgIT09IFwidW5kZWZpbmVkXCIgPyBnbG9iYWwgOiB0eXBlb2Ygc2VsZiAhPT0gXCJ1bmRlZmluZWRcIiA/IHNlbGYgOiB0eXBlb2Ygd2luZG93ICE9PSBcInVuZGVmaW5lZFwiID8gd2luZG93IDoge30pO1xuICAgICAgICB9LCB7IFwibWluLWRvY3VtZW50XCI6IDYgfV0sIDExOiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge1xuICAgICAgICAgICAgXCJ1c2Ugc3RyaWN0XCI7XG5cbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gaXNPYmplY3QoeCkge1xuICAgICAgICAgICAgICAgIHJldHVybiB0eXBlb2YgeCA9PT0gXCJvYmplY3RcIiAmJiB4ICE9PSBudWxsO1xuICAgICAgICAgICAgfTtcbiAgICAgICAgfSwge31dLCAxMjogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHtcbiAgICAgICAgICAgIHZhciBuYXRpdmVJc0FycmF5ID0gQXJyYXkuaXNBcnJheTtcbiAgICAgICAgICAgIHZhciB0b1N0cmluZyA9IE9iamVjdC5wcm90b3R5cGUudG9TdHJpbmc7XG5cbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gbmF0aXZlSXNBcnJheSB8fCBpc0FycmF5O1xuXG4gICAgICAgICAgICBmdW5jdGlvbiBpc0FycmF5KG9iaikge1xuICAgICAgICAgICAgICAgIHJldHVybiB0b1N0cmluZy5jYWxsKG9iaikgPT09IFwiW29iamVjdCBBcnJheV1cIjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSwge31dLCAxMzogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHtcbiAgICAgICAgICAgIHZhciBwYXRjaCA9IHJlcXVpcmUoXCIuL3Zkb20vcGF0Y2guanNcIik7XG5cbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gcGF0Y2g7XG4gICAgICAgIH0sIHsgXCIuL3Zkb20vcGF0Y2guanNcIjogMTggfV0sIDE0OiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge1xuICAgICAgICAgICAgdmFyIGlzT2JqZWN0ID0gcmVxdWlyZShcImlzLW9iamVjdFwiKTtcbiAgICAgICAgICAgIHZhciBpc0hvb2sgPSByZXF1aXJlKFwiLi4vdm5vZGUvaXMtdmhvb2suanNcIik7XG5cbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gYXBwbHlQcm9wZXJ0aWVzO1xuXG4gICAgICAgICAgICBmdW5jdGlvbiBhcHBseVByb3BlcnRpZXMobm9kZSwgcHJvcHMsIHByZXZpb3VzKSB7XG4gICAgICAgICAgICAgICAgZm9yICh2YXIgcHJvcE5hbWUgaW4gcHJvcHMpIHtcbiAgICAgICAgICAgICAgICAgICAgdmFyIHByb3BWYWx1ZSA9IHByb3BzW3Byb3BOYW1lXTtcblxuICAgICAgICAgICAgICAgICAgICBpZiAocHJvcFZhbHVlID09PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJlbW92ZVByb3BlcnR5KG5vZGUsIHByb3BOYW1lLCBwcm9wVmFsdWUsIHByZXZpb3VzKTtcbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIGlmIChpc0hvb2socHJvcFZhbHVlKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgcmVtb3ZlUHJvcGVydHkobm9kZSwgcHJvcE5hbWUsIHByb3BWYWx1ZSwgcHJldmlvdXMpO1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHByb3BWYWx1ZS5ob29rKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcHJvcFZhbHVlLmhvb2sobm9kZSwgcHJvcE5hbWUsIHByZXZpb3VzID8gcHJldmlvdXNbcHJvcE5hbWVdIDogdW5kZWZpbmVkKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChpc09iamVjdChwcm9wVmFsdWUpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcGF0Y2hPYmplY3Qobm9kZSwgcHJvcHMsIHByZXZpb3VzLCBwcm9wTmFtZSwgcHJvcFZhbHVlKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgbm9kZVtwcm9wTmFtZV0gPSBwcm9wVmFsdWU7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIHJlbW92ZVByb3BlcnR5KG5vZGUsIHByb3BOYW1lLCBwcm9wVmFsdWUsIHByZXZpb3VzKSB7XG4gICAgICAgICAgICAgICAgaWYgKHByZXZpb3VzKSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciBwcmV2aW91c1ZhbHVlID0gcHJldmlvdXNbcHJvcE5hbWVdO1xuXG4gICAgICAgICAgICAgICAgICAgIGlmICghaXNIb29rKHByZXZpb3VzVmFsdWUpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAocHJvcE5hbWUgPT09IFwiYXR0cmlidXRlc1wiKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgZm9yICh2YXIgYXR0ck5hbWUgaW4gcHJldmlvdXNWYWx1ZSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBub2RlLnJlbW92ZUF0dHJpYnV0ZShhdHRyTmFtZSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIGlmIChwcm9wTmFtZSA9PT0gXCJzdHlsZVwiKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgZm9yICh2YXIgaSBpbiBwcmV2aW91c1ZhbHVlKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG5vZGUuc3R5bGVbaV0gPSBcIlwiO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAodHlwZW9mIHByZXZpb3VzVmFsdWUgPT09IFwic3RyaW5nXCIpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBub2RlW3Byb3BOYW1lXSA9IFwiXCI7XG4gICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIG5vZGVbcHJvcE5hbWVdID0gbnVsbDtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIGlmIChwcmV2aW91c1ZhbHVlLnVuaG9vaykge1xuICAgICAgICAgICAgICAgICAgICAgICAgcHJldmlvdXNWYWx1ZS51bmhvb2sobm9kZSwgcHJvcE5hbWUsIHByb3BWYWx1ZSk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIHBhdGNoT2JqZWN0KG5vZGUsIHByb3BzLCBwcmV2aW91cywgcHJvcE5hbWUsIHByb3BWYWx1ZSkge1xuICAgICAgICAgICAgICAgIHZhciBwcmV2aW91c1ZhbHVlID0gcHJldmlvdXMgPyBwcmV2aW91c1twcm9wTmFtZV0gOiB1bmRlZmluZWQ7XG5cbiAgICAgICAgICAgICAgICAvLyBTZXQgYXR0cmlidXRlc1xuICAgICAgICAgICAgICAgIGlmIChwcm9wTmFtZSA9PT0gXCJhdHRyaWJ1dGVzXCIpIHtcbiAgICAgICAgICAgICAgICAgICAgZm9yICh2YXIgYXR0ck5hbWUgaW4gcHJvcFZhbHVlKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICB2YXIgYXR0clZhbHVlID0gcHJvcFZhbHVlW2F0dHJOYW1lXTtcblxuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGF0dHJWYWx1ZSA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgbm9kZS5yZW1vdmVBdHRyaWJ1dGUoYXR0ck5hbWUpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBub2RlLnNldEF0dHJpYnV0ZShhdHRyTmFtZSwgYXR0clZhbHVlKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICBpZiAocHJldmlvdXNWYWx1ZSAmJiBpc09iamVjdChwcmV2aW91c1ZhbHVlKSAmJiBnZXRQcm90b3R5cGUocHJldmlvdXNWYWx1ZSkgIT09IGdldFByb3RvdHlwZShwcm9wVmFsdWUpKSB7XG4gICAgICAgICAgICAgICAgICAgIG5vZGVbcHJvcE5hbWVdID0gcHJvcFZhbHVlO1xuICAgICAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgaWYgKCFpc09iamVjdChub2RlW3Byb3BOYW1lXSkpIHtcbiAgICAgICAgICAgICAgICAgICAgbm9kZVtwcm9wTmFtZV0gPSB7fTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICB2YXIgcmVwbGFjZXIgPSBwcm9wTmFtZSA9PT0gXCJzdHlsZVwiID8gXCJcIiA6IHVuZGVmaW5lZDtcblxuICAgICAgICAgICAgICAgIGZvciAodmFyIGsgaW4gcHJvcFZhbHVlKSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciB2YWx1ZSA9IHByb3BWYWx1ZVtrXTtcbiAgICAgICAgICAgICAgICAgICAgbm9kZVtwcm9wTmFtZV1ba10gPSB2YWx1ZSA9PT0gdW5kZWZpbmVkID8gcmVwbGFjZXIgOiB2YWx1ZTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIGdldFByb3RvdHlwZSh2YWx1ZSkge1xuICAgICAgICAgICAgICAgIGlmIChPYmplY3QuZ2V0UHJvdG90eXBlT2YpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIE9iamVjdC5nZXRQcm90b3R5cGVPZih2YWx1ZSk7XG4gICAgICAgICAgICAgICAgfSBlbHNlIGlmICh2YWx1ZS5fX3Byb3RvX18pIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHZhbHVlLl9fcHJvdG9fXztcbiAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKHZhbHVlLmNvbnN0cnVjdG9yKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiB2YWx1ZS5jb25zdHJ1Y3Rvci5wcm90b3R5cGU7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9LCB7IFwiLi4vdm5vZGUvaXMtdmhvb2suanNcIjogMjYsIFwiaXMtb2JqZWN0XCI6IDExIH1dLCAxNTogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHtcbiAgICAgICAgICAgIHZhciBkb2N1bWVudCA9IHJlcXVpcmUoXCJnbG9iYWwvZG9jdW1lbnRcIik7XG5cbiAgICAgICAgICAgIHZhciBhcHBseVByb3BlcnRpZXMgPSByZXF1aXJlKFwiLi9hcHBseS1wcm9wZXJ0aWVzXCIpO1xuXG4gICAgICAgICAgICB2YXIgaXNWTm9kZSA9IHJlcXVpcmUoXCIuLi92bm9kZS9pcy12bm9kZS5qc1wiKTtcbiAgICAgICAgICAgIHZhciBpc1ZUZXh0ID0gcmVxdWlyZShcIi4uL3Zub2RlL2lzLXZ0ZXh0LmpzXCIpO1xuICAgICAgICAgICAgdmFyIGlzV2lkZ2V0ID0gcmVxdWlyZShcIi4uL3Zub2RlL2lzLXdpZGdldC5qc1wiKTtcbiAgICAgICAgICAgIHZhciBoYW5kbGVUaHVuayA9IHJlcXVpcmUoXCIuLi92bm9kZS9oYW5kbGUtdGh1bmsuanNcIik7XG5cbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gY3JlYXRlRWxlbWVudDtcblxuICAgICAgICAgICAgZnVuY3Rpb24gY3JlYXRlRWxlbWVudCh2bm9kZSwgb3B0cykge1xuICAgICAgICAgICAgICAgIHZhciBkb2MgPSBvcHRzID8gb3B0cy5kb2N1bWVudCB8fCBkb2N1bWVudCA6IGRvY3VtZW50O1xuICAgICAgICAgICAgICAgIHZhciB3YXJuID0gb3B0cyA/IG9wdHMud2FybiA6IG51bGw7XG5cbiAgICAgICAgICAgICAgICB2bm9kZSA9IGhhbmRsZVRodW5rKHZub2RlKS5hO1xuXG4gICAgICAgICAgICAgICAgaWYgKGlzV2lkZ2V0KHZub2RlKSkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gdm5vZGUuaW5pdCgpO1xuICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoaXNWVGV4dCh2bm9kZSkpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGRvYy5jcmVhdGVUZXh0Tm9kZSh2bm9kZS50ZXh0KTtcbiAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKCFpc1ZOb2RlKHZub2RlKSkge1xuICAgICAgICAgICAgICAgICAgICBpZiAod2Fybikge1xuICAgICAgICAgICAgICAgICAgICAgICAgd2FybihcIkl0ZW0gaXMgbm90IGEgdmFsaWQgdmlydHVhbCBkb20gbm9kZVwiLCB2bm9kZSk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIG51bGw7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgdmFyIG5vZGUgPSB2bm9kZS5uYW1lc3BhY2UgPT09IG51bGwgPyBkb2MuY3JlYXRlRWxlbWVudCh2bm9kZS50YWdOYW1lKSA6IGRvYy5jcmVhdGVFbGVtZW50TlModm5vZGUubmFtZXNwYWNlLCB2bm9kZS50YWdOYW1lKTtcblxuICAgICAgICAgICAgICAgIHZhciBwcm9wcyA9IHZub2RlLnByb3BlcnRpZXM7XG4gICAgICAgICAgICAgICAgYXBwbHlQcm9wZXJ0aWVzKG5vZGUsIHByb3BzKTtcblxuICAgICAgICAgICAgICAgIHZhciBjaGlsZHJlbiA9IHZub2RlLmNoaWxkcmVuO1xuXG4gICAgICAgICAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCBjaGlsZHJlbi5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgICAgICAgICB2YXIgY2hpbGROb2RlID0gY3JlYXRlRWxlbWVudChjaGlsZHJlbltpXSwgb3B0cyk7XG4gICAgICAgICAgICAgICAgICAgIGlmIChjaGlsZE5vZGUpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIG5vZGUuYXBwZW5kQ2hpbGQoY2hpbGROb2RlKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHJldHVybiBub2RlO1xuICAgICAgICAgICAgfVxuICAgICAgICB9LCB7IFwiLi4vdm5vZGUvaGFuZGxlLXRodW5rLmpzXCI6IDI0LCBcIi4uL3Zub2RlL2lzLXZub2RlLmpzXCI6IDI3LCBcIi4uL3Zub2RlL2lzLXZ0ZXh0LmpzXCI6IDI4LCBcIi4uL3Zub2RlL2lzLXdpZGdldC5qc1wiOiAyOSwgXCIuL2FwcGx5LXByb3BlcnRpZXNcIjogMTQsIFwiZ2xvYmFsL2RvY3VtZW50XCI6IDEwIH1dLCAxNjogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHtcbiAgICAgICAgICAgIC8vIE1hcHMgYSB2aXJ0dWFsIERPTSB0cmVlIG9udG8gYSByZWFsIERPTSB0cmVlIGluIGFuIGVmZmljaWVudCBtYW5uZXIuXG4gICAgICAgICAgICAvLyBXZSBkb24ndCB3YW50IHRvIHJlYWQgYWxsIG9mIHRoZSBET00gbm9kZXMgaW4gdGhlIHRyZWUgc28gd2UgdXNlXG4gICAgICAgICAgICAvLyB0aGUgaW4tb3JkZXIgdHJlZSBpbmRleGluZyB0byBlbGltaW5hdGUgcmVjdXJzaW9uIGRvd24gY2VydGFpbiBicmFuY2hlcy5cbiAgICAgICAgICAgIC8vIFdlIG9ubHkgcmVjdXJzZSBpbnRvIGEgRE9NIG5vZGUgaWYgd2Uga25vdyB0aGF0IGl0IGNvbnRhaW5zIGEgY2hpbGQgb2ZcbiAgICAgICAgICAgIC8vIGludGVyZXN0LlxuXG4gICAgICAgICAgICB2YXIgbm9DaGlsZCA9IHt9O1xuXG4gICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IGRvbUluZGV4O1xuXG4gICAgICAgICAgICBmdW5jdGlvbiBkb21JbmRleChyb290Tm9kZSwgdHJlZSwgaW5kaWNlcywgbm9kZXMpIHtcbiAgICAgICAgICAgICAgICBpZiAoIWluZGljZXMgfHwgaW5kaWNlcy5sZW5ndGggPT09IDApIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHt9O1xuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIGluZGljZXMuc29ydChhc2NlbmRpbmcpO1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gcmVjdXJzZShyb290Tm9kZSwgdHJlZSwgaW5kaWNlcywgbm9kZXMsIDApO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZnVuY3Rpb24gcmVjdXJzZShyb290Tm9kZSwgdHJlZSwgaW5kaWNlcywgbm9kZXMsIHJvb3RJbmRleCkge1xuICAgICAgICAgICAgICAgIG5vZGVzID0gbm9kZXMgfHwge307XG5cbiAgICAgICAgICAgICAgICBpZiAocm9vdE5vZGUpIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKGluZGV4SW5SYW5nZShpbmRpY2VzLCByb290SW5kZXgsIHJvb3RJbmRleCkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIG5vZGVzW3Jvb3RJbmRleF0gPSByb290Tm9kZTtcbiAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgIHZhciB2Q2hpbGRyZW4gPSB0cmVlLmNoaWxkcmVuO1xuXG4gICAgICAgICAgICAgICAgICAgIGlmICh2Q2hpbGRyZW4pIHtcblxuICAgICAgICAgICAgICAgICAgICAgICAgdmFyIGNoaWxkTm9kZXMgPSByb290Tm9kZS5jaGlsZE5vZGVzO1xuXG4gICAgICAgICAgICAgICAgICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IHRyZWUuY2hpbGRyZW4ubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICByb290SW5kZXggKz0gMTtcblxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZhciB2Q2hpbGQgPSB2Q2hpbGRyZW5baV0gfHwgbm9DaGlsZDtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB2YXIgbmV4dEluZGV4ID0gcm9vdEluZGV4ICsgKHZDaGlsZC5jb3VudCB8fCAwKTtcblxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIHNraXAgcmVjdXJzaW9uIGRvd24gdGhlIHRyZWUgaWYgdGhlcmUgYXJlIG5vIG5vZGVzIGRvd24gaGVyZVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChpbmRleEluUmFuZ2UoaW5kaWNlcywgcm9vdEluZGV4LCBuZXh0SW5kZXgpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlY3Vyc2UoY2hpbGROb2Rlc1tpXSwgdkNoaWxkLCBpbmRpY2VzLCBub2Rlcywgcm9vdEluZGV4KTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICByb290SW5kZXggPSBuZXh0SW5kZXg7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICByZXR1cm4gbm9kZXM7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIC8vIEJpbmFyeSBzZWFyY2ggZm9yIGFuIGluZGV4IGluIHRoZSBpbnRlcnZhbCBbbGVmdCwgcmlnaHRdXG4gICAgICAgICAgICBmdW5jdGlvbiBpbmRleEluUmFuZ2UoaW5kaWNlcywgbGVmdCwgcmlnaHQpIHtcbiAgICAgICAgICAgICAgICBpZiAoaW5kaWNlcy5sZW5ndGggPT09IDApIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHZhciBtaW5JbmRleCA9IDA7XG4gICAgICAgICAgICAgICAgdmFyIG1heEluZGV4ID0gaW5kaWNlcy5sZW5ndGggLSAxO1xuICAgICAgICAgICAgICAgIHZhciBjdXJyZW50SW5kZXg7XG4gICAgICAgICAgICAgICAgdmFyIGN1cnJlbnRJdGVtO1xuXG4gICAgICAgICAgICAgICAgd2hpbGUgKG1pbkluZGV4IDw9IG1heEluZGV4KSB7XG4gICAgICAgICAgICAgICAgICAgIGN1cnJlbnRJbmRleCA9IChtYXhJbmRleCArIG1pbkluZGV4KSAvIDIgPj4gMDtcbiAgICAgICAgICAgICAgICAgICAgY3VycmVudEl0ZW0gPSBpbmRpY2VzW2N1cnJlbnRJbmRleF07XG5cbiAgICAgICAgICAgICAgICAgICAgaWYgKG1pbkluZGV4ID09PSBtYXhJbmRleCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGN1cnJlbnRJdGVtID49IGxlZnQgJiYgY3VycmVudEl0ZW0gPD0gcmlnaHQ7XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoY3VycmVudEl0ZW0gPCBsZWZ0KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBtaW5JbmRleCA9IGN1cnJlbnRJbmRleCArIDE7XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoY3VycmVudEl0ZW0gPiByaWdodCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgbWF4SW5kZXggPSBjdXJyZW50SW5kZXggLSAxO1xuICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIGFzY2VuZGluZyhhLCBiKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGEgPiBiID8gMSA6IC0xO1xuICAgICAgICAgICAgfVxuICAgICAgICB9LCB7fV0sIDE3OiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge1xuICAgICAgICAgICAgdmFyIGFwcGx5UHJvcGVydGllcyA9IHJlcXVpcmUoXCIuL2FwcGx5LXByb3BlcnRpZXNcIik7XG5cbiAgICAgICAgICAgIHZhciBpc1dpZGdldCA9IHJlcXVpcmUoXCIuLi92bm9kZS9pcy13aWRnZXQuanNcIik7XG4gICAgICAgICAgICB2YXIgVlBhdGNoID0gcmVxdWlyZShcIi4uL3Zub2RlL3ZwYXRjaC5qc1wiKTtcblxuICAgICAgICAgICAgdmFyIHVwZGF0ZVdpZGdldCA9IHJlcXVpcmUoXCIuL3VwZGF0ZS13aWRnZXRcIik7XG5cbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gYXBwbHlQYXRjaDtcblxuICAgICAgICAgICAgZnVuY3Rpb24gYXBwbHlQYXRjaCh2cGF0Y2gsIGRvbU5vZGUsIHJlbmRlck9wdGlvbnMpIHtcbiAgICAgICAgICAgICAgICB2YXIgdHlwZSA9IHZwYXRjaC50eXBlO1xuICAgICAgICAgICAgICAgIHZhciB2Tm9kZSA9IHZwYXRjaC52Tm9kZTtcbiAgICAgICAgICAgICAgICB2YXIgcGF0Y2ggPSB2cGF0Y2gucGF0Y2g7XG5cbiAgICAgICAgICAgICAgICBzd2l0Y2ggKHR5cGUpIHtcbiAgICAgICAgICAgICAgICAgICAgY2FzZSBWUGF0Y2guUkVNT1ZFOlxuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHJlbW92ZU5vZGUoZG9tTm9kZSwgdk5vZGUpO1xuICAgICAgICAgICAgICAgICAgICBjYXNlIFZQYXRjaC5JTlNFUlQ6XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gaW5zZXJ0Tm9kZShkb21Ob2RlLCBwYXRjaCwgcmVuZGVyT3B0aW9ucyk7XG4gICAgICAgICAgICAgICAgICAgIGNhc2UgVlBhdGNoLlZURVhUOlxuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHN0cmluZ1BhdGNoKGRvbU5vZGUsIHZOb2RlLCBwYXRjaCwgcmVuZGVyT3B0aW9ucyk7XG4gICAgICAgICAgICAgICAgICAgIGNhc2UgVlBhdGNoLldJREdFVDpcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiB3aWRnZXRQYXRjaChkb21Ob2RlLCB2Tm9kZSwgcGF0Y2gsIHJlbmRlck9wdGlvbnMpO1xuICAgICAgICAgICAgICAgICAgICBjYXNlIFZQYXRjaC5WTk9ERTpcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiB2Tm9kZVBhdGNoKGRvbU5vZGUsIHZOb2RlLCBwYXRjaCwgcmVuZGVyT3B0aW9ucyk7XG4gICAgICAgICAgICAgICAgICAgIGNhc2UgVlBhdGNoLk9SREVSOlxuICAgICAgICAgICAgICAgICAgICAgICAgcmVvcmRlckNoaWxkcmVuKGRvbU5vZGUsIHBhdGNoKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBkb21Ob2RlO1xuICAgICAgICAgICAgICAgICAgICBjYXNlIFZQYXRjaC5QUk9QUzpcbiAgICAgICAgICAgICAgICAgICAgICAgIGFwcGx5UHJvcGVydGllcyhkb21Ob2RlLCBwYXRjaCwgdk5vZGUucHJvcGVydGllcyk7XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gZG9tTm9kZTtcbiAgICAgICAgICAgICAgICAgICAgY2FzZSBWUGF0Y2guVEhVTks6XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gcmVwbGFjZVJvb3QoZG9tTm9kZSwgcmVuZGVyT3B0aW9ucy5wYXRjaChkb21Ob2RlLCBwYXRjaCwgcmVuZGVyT3B0aW9ucykpO1xuICAgICAgICAgICAgICAgICAgICBkZWZhdWx0OlxuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGRvbU5vZGU7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBmdW5jdGlvbiByZW1vdmVOb2RlKGRvbU5vZGUsIHZOb2RlKSB7XG4gICAgICAgICAgICAgICAgdmFyIHBhcmVudE5vZGUgPSBkb21Ob2RlLnBhcmVudE5vZGU7XG5cbiAgICAgICAgICAgICAgICBpZiAocGFyZW50Tm9kZSkge1xuICAgICAgICAgICAgICAgICAgICBwYXJlbnROb2RlLnJlbW92ZUNoaWxkKGRvbU5vZGUpO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIGRlc3Ryb3lXaWRnZXQoZG9tTm9kZSwgdk5vZGUpO1xuXG4gICAgICAgICAgICAgICAgcmV0dXJuIG51bGw7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIGluc2VydE5vZGUocGFyZW50Tm9kZSwgdk5vZGUsIHJlbmRlck9wdGlvbnMpIHtcbiAgICAgICAgICAgICAgICB2YXIgbmV3Tm9kZSA9IHJlbmRlck9wdGlvbnMucmVuZGVyKHZOb2RlLCByZW5kZXJPcHRpb25zKTtcblxuICAgICAgICAgICAgICAgIGlmIChwYXJlbnROb2RlKSB7XG4gICAgICAgICAgICAgICAgICAgIHBhcmVudE5vZGUuYXBwZW5kQ2hpbGQobmV3Tm9kZSk7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgcmV0dXJuIHBhcmVudE5vZGU7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIHN0cmluZ1BhdGNoKGRvbU5vZGUsIGxlZnRWTm9kZSwgdlRleHQsIHJlbmRlck9wdGlvbnMpIHtcbiAgICAgICAgICAgICAgICB2YXIgbmV3Tm9kZTtcblxuICAgICAgICAgICAgICAgIGlmIChkb21Ob2RlLm5vZGVUeXBlID09PSAzKSB7XG4gICAgICAgICAgICAgICAgICAgIGRvbU5vZGUucmVwbGFjZURhdGEoMCwgZG9tTm9kZS5sZW5ndGgsIHZUZXh0LnRleHQpO1xuICAgICAgICAgICAgICAgICAgICBuZXdOb2RlID0gZG9tTm9kZTtcbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICB2YXIgcGFyZW50Tm9kZSA9IGRvbU5vZGUucGFyZW50Tm9kZTtcbiAgICAgICAgICAgICAgICAgICAgbmV3Tm9kZSA9IHJlbmRlck9wdGlvbnMucmVuZGVyKHZUZXh0LCByZW5kZXJPcHRpb25zKTtcblxuICAgICAgICAgICAgICAgICAgICBpZiAocGFyZW50Tm9kZSAmJiBuZXdOb2RlICE9PSBkb21Ob2RlKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBwYXJlbnROb2RlLnJlcGxhY2VDaGlsZChuZXdOb2RlLCBkb21Ob2RlKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHJldHVybiBuZXdOb2RlO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBmdW5jdGlvbiB3aWRnZXRQYXRjaChkb21Ob2RlLCBsZWZ0Vk5vZGUsIHdpZGdldCwgcmVuZGVyT3B0aW9ucykge1xuICAgICAgICAgICAgICAgIHZhciB1cGRhdGluZyA9IHVwZGF0ZVdpZGdldChsZWZ0Vk5vZGUsIHdpZGdldCk7XG4gICAgICAgICAgICAgICAgdmFyIG5ld05vZGU7XG5cbiAgICAgICAgICAgICAgICBpZiAodXBkYXRpbmcpIHtcbiAgICAgICAgICAgICAgICAgICAgbmV3Tm9kZSA9IHdpZGdldC51cGRhdGUobGVmdFZOb2RlLCBkb21Ob2RlKSB8fCBkb21Ob2RlO1xuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIG5ld05vZGUgPSByZW5kZXJPcHRpb25zLnJlbmRlcih3aWRnZXQsIHJlbmRlck9wdGlvbnMpO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHZhciBwYXJlbnROb2RlID0gZG9tTm9kZS5wYXJlbnROb2RlO1xuXG4gICAgICAgICAgICAgICAgaWYgKHBhcmVudE5vZGUgJiYgbmV3Tm9kZSAhPT0gZG9tTm9kZSkge1xuICAgICAgICAgICAgICAgICAgICBwYXJlbnROb2RlLnJlcGxhY2VDaGlsZChuZXdOb2RlLCBkb21Ob2RlKTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICBpZiAoIXVwZGF0aW5nKSB7XG4gICAgICAgICAgICAgICAgICAgIGRlc3Ryb3lXaWRnZXQoZG9tTm9kZSwgbGVmdFZOb2RlKTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICByZXR1cm4gbmV3Tm9kZTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZnVuY3Rpb24gdk5vZGVQYXRjaChkb21Ob2RlLCBsZWZ0Vk5vZGUsIHZOb2RlLCByZW5kZXJPcHRpb25zKSB7XG4gICAgICAgICAgICAgICAgdmFyIHBhcmVudE5vZGUgPSBkb21Ob2RlLnBhcmVudE5vZGU7XG4gICAgICAgICAgICAgICAgdmFyIG5ld05vZGUgPSByZW5kZXJPcHRpb25zLnJlbmRlcih2Tm9kZSwgcmVuZGVyT3B0aW9ucyk7XG5cbiAgICAgICAgICAgICAgICBpZiAocGFyZW50Tm9kZSAmJiBuZXdOb2RlICE9PSBkb21Ob2RlKSB7XG4gICAgICAgICAgICAgICAgICAgIHBhcmVudE5vZGUucmVwbGFjZUNoaWxkKG5ld05vZGUsIGRvbU5vZGUpO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHJldHVybiBuZXdOb2RlO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBmdW5jdGlvbiBkZXN0cm95V2lkZ2V0KGRvbU5vZGUsIHcpIHtcbiAgICAgICAgICAgICAgICBpZiAodHlwZW9mIHcuZGVzdHJveSA9PT0gXCJmdW5jdGlvblwiICYmIGlzV2lkZ2V0KHcpKSB7XG4gICAgICAgICAgICAgICAgICAgIHcuZGVzdHJveShkb21Ob2RlKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIHJlb3JkZXJDaGlsZHJlbihkb21Ob2RlLCBtb3Zlcykge1xuICAgICAgICAgICAgICAgIHZhciBjaGlsZE5vZGVzID0gZG9tTm9kZS5jaGlsZE5vZGVzO1xuICAgICAgICAgICAgICAgIHZhciBrZXlNYXAgPSB7fTtcbiAgICAgICAgICAgICAgICB2YXIgbm9kZTtcbiAgICAgICAgICAgICAgICB2YXIgcmVtb3ZlO1xuICAgICAgICAgICAgICAgIHZhciBpbnNlcnQ7XG5cbiAgICAgICAgICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IG1vdmVzLnJlbW92ZXMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgICAgICAgICAgcmVtb3ZlID0gbW92ZXMucmVtb3Zlc1tpXTtcbiAgICAgICAgICAgICAgICAgICAgbm9kZSA9IGNoaWxkTm9kZXNbcmVtb3ZlLmZyb21dO1xuICAgICAgICAgICAgICAgICAgICBpZiAocmVtb3ZlLmtleSkge1xuICAgICAgICAgICAgICAgICAgICAgICAga2V5TWFwW3JlbW92ZS5rZXldID0gbm9kZTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICBkb21Ob2RlLnJlbW92ZUNoaWxkKG5vZGUpO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHZhciBsZW5ndGggPSBjaGlsZE5vZGVzLmxlbmd0aDtcbiAgICAgICAgICAgICAgICBmb3IgKHZhciBqID0gMDsgaiA8IG1vdmVzLmluc2VydHMubGVuZ3RoOyBqKyspIHtcbiAgICAgICAgICAgICAgICAgICAgaW5zZXJ0ID0gbW92ZXMuaW5zZXJ0c1tqXTtcbiAgICAgICAgICAgICAgICAgICAgbm9kZSA9IGtleU1hcFtpbnNlcnQua2V5XTtcbiAgICAgICAgICAgICAgICAgICAgLy8gdGhpcyBpcyB0aGUgd2VpcmRlc3QgYnVnIGkndmUgZXZlciBzZWVuIGluIHdlYmtpdFxuICAgICAgICAgICAgICAgICAgICBkb21Ob2RlLmluc2VydEJlZm9yZShub2RlLCBpbnNlcnQudG8gPj0gbGVuZ3RoKysgPyBudWxsIDogY2hpbGROb2Rlc1tpbnNlcnQudG9dKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIHJlcGxhY2VSb290KG9sZFJvb3QsIG5ld1Jvb3QpIHtcbiAgICAgICAgICAgICAgICBpZiAob2xkUm9vdCAmJiBuZXdSb290ICYmIG9sZFJvb3QgIT09IG5ld1Jvb3QgJiYgb2xkUm9vdC5wYXJlbnROb2RlKSB7XG4gICAgICAgICAgICAgICAgICAgIG9sZFJvb3QucGFyZW50Tm9kZS5yZXBsYWNlQ2hpbGQobmV3Um9vdCwgb2xkUm9vdCk7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgcmV0dXJuIG5ld1Jvb3Q7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0sIHsgXCIuLi92bm9kZS9pcy13aWRnZXQuanNcIjogMjksIFwiLi4vdm5vZGUvdnBhdGNoLmpzXCI6IDMyLCBcIi4vYXBwbHktcHJvcGVydGllc1wiOiAxNCwgXCIuL3VwZGF0ZS13aWRnZXRcIjogMTkgfV0sIDE4OiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge1xuICAgICAgICAgICAgdmFyIGRvY3VtZW50ID0gcmVxdWlyZShcImdsb2JhbC9kb2N1bWVudFwiKTtcbiAgICAgICAgICAgIHZhciBpc0FycmF5ID0gcmVxdWlyZShcIngtaXMtYXJyYXlcIik7XG5cbiAgICAgICAgICAgIHZhciByZW5kZXIgPSByZXF1aXJlKFwiLi9jcmVhdGUtZWxlbWVudFwiKTtcbiAgICAgICAgICAgIHZhciBkb21JbmRleCA9IHJlcXVpcmUoXCIuL2RvbS1pbmRleFwiKTtcbiAgICAgICAgICAgIHZhciBwYXRjaE9wID0gcmVxdWlyZShcIi4vcGF0Y2gtb3BcIik7XG4gICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IHBhdGNoO1xuXG4gICAgICAgICAgICBmdW5jdGlvbiBwYXRjaChyb290Tm9kZSwgcGF0Y2hlcywgcmVuZGVyT3B0aW9ucykge1xuICAgICAgICAgICAgICAgIHJlbmRlck9wdGlvbnMgPSByZW5kZXJPcHRpb25zIHx8IHt9O1xuICAgICAgICAgICAgICAgIHJlbmRlck9wdGlvbnMucGF0Y2ggPSByZW5kZXJPcHRpb25zLnBhdGNoICYmIHJlbmRlck9wdGlvbnMucGF0Y2ggIT09IHBhdGNoID8gcmVuZGVyT3B0aW9ucy5wYXRjaCA6IHBhdGNoUmVjdXJzaXZlO1xuICAgICAgICAgICAgICAgIHJlbmRlck9wdGlvbnMucmVuZGVyID0gcmVuZGVyT3B0aW9ucy5yZW5kZXIgfHwgcmVuZGVyO1xuXG4gICAgICAgICAgICAgICAgcmV0dXJuIHJlbmRlck9wdGlvbnMucGF0Y2gocm9vdE5vZGUsIHBhdGNoZXMsIHJlbmRlck9wdGlvbnMpO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBmdW5jdGlvbiBwYXRjaFJlY3Vyc2l2ZShyb290Tm9kZSwgcGF0Y2hlcywgcmVuZGVyT3B0aW9ucykge1xuICAgICAgICAgICAgICAgIHZhciBpbmRpY2VzID0gcGF0Y2hJbmRpY2VzKHBhdGNoZXMpO1xuXG4gICAgICAgICAgICAgICAgaWYgKGluZGljZXMubGVuZ3RoID09PSAwKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiByb290Tm9kZTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICB2YXIgaW5kZXggPSBkb21JbmRleChyb290Tm9kZSwgcGF0Y2hlcy5hLCBpbmRpY2VzKTtcbiAgICAgICAgICAgICAgICB2YXIgb3duZXJEb2N1bWVudCA9IHJvb3ROb2RlLm93bmVyRG9jdW1lbnQ7XG5cbiAgICAgICAgICAgICAgICBpZiAoIXJlbmRlck9wdGlvbnMuZG9jdW1lbnQgJiYgb3duZXJEb2N1bWVudCAhPT0gZG9jdW1lbnQpIHtcbiAgICAgICAgICAgICAgICAgICAgcmVuZGVyT3B0aW9ucy5kb2N1bWVudCA9IG93bmVyRG9jdW1lbnQ7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCBpbmRpY2VzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciBub2RlSW5kZXggPSBpbmRpY2VzW2ldO1xuICAgICAgICAgICAgICAgICAgICByb290Tm9kZSA9IGFwcGx5UGF0Y2gocm9vdE5vZGUsIGluZGV4W25vZGVJbmRleF0sIHBhdGNoZXNbbm9kZUluZGV4XSwgcmVuZGVyT3B0aW9ucyk7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgcmV0dXJuIHJvb3ROb2RlO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBmdW5jdGlvbiBhcHBseVBhdGNoKHJvb3ROb2RlLCBkb21Ob2RlLCBwYXRjaExpc3QsIHJlbmRlck9wdGlvbnMpIHtcbiAgICAgICAgICAgICAgICBpZiAoIWRvbU5vZGUpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHJvb3ROb2RlO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHZhciBuZXdOb2RlO1xuXG4gICAgICAgICAgICAgICAgaWYgKGlzQXJyYXkocGF0Y2hMaXN0KSkge1xuICAgICAgICAgICAgICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IHBhdGNoTGlzdC5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgICAgICAgICAgICAgbmV3Tm9kZSA9IHBhdGNoT3AocGF0Y2hMaXN0W2ldLCBkb21Ob2RlLCByZW5kZXJPcHRpb25zKTtcblxuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGRvbU5vZGUgPT09IHJvb3ROb2RlKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcm9vdE5vZGUgPSBuZXdOb2RlO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgbmV3Tm9kZSA9IHBhdGNoT3AocGF0Y2hMaXN0LCBkb21Ob2RlLCByZW5kZXJPcHRpb25zKTtcblxuICAgICAgICAgICAgICAgICAgICBpZiAoZG9tTm9kZSA9PT0gcm9vdE5vZGUpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJvb3ROb2RlID0gbmV3Tm9kZTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHJldHVybiByb290Tm9kZTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZnVuY3Rpb24gcGF0Y2hJbmRpY2VzKHBhdGNoZXMpIHtcbiAgICAgICAgICAgICAgICB2YXIgaW5kaWNlcyA9IFtdO1xuXG4gICAgICAgICAgICAgICAgZm9yICh2YXIga2V5IGluIHBhdGNoZXMpIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKGtleSAhPT0gXCJhXCIpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGluZGljZXMucHVzaChOdW1iZXIoa2V5KSk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICByZXR1cm4gaW5kaWNlcztcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSwgeyBcIi4vY3JlYXRlLWVsZW1lbnRcIjogMTUsIFwiLi9kb20taW5kZXhcIjogMTYsIFwiLi9wYXRjaC1vcFwiOiAxNywgXCJnbG9iYWwvZG9jdW1lbnRcIjogMTAsIFwieC1pcy1hcnJheVwiOiAxMiB9XSwgMTk6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICB2YXIgaXNXaWRnZXQgPSByZXF1aXJlKFwiLi4vdm5vZGUvaXMtd2lkZ2V0LmpzXCIpO1xuXG4gICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IHVwZGF0ZVdpZGdldDtcblxuICAgICAgICAgICAgZnVuY3Rpb24gdXBkYXRlV2lkZ2V0KGEsIGIpIHtcbiAgICAgICAgICAgICAgICBpZiAoaXNXaWRnZXQoYSkgJiYgaXNXaWRnZXQoYikpIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKFwibmFtZVwiIGluIGEgJiYgXCJuYW1lXCIgaW4gYikge1xuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGEuaWQgPT09IGIuaWQ7XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gYS5pbml0ID09PSBiLmluaXQ7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0sIHsgXCIuLi92bm9kZS9pcy13aWRnZXQuanNcIjogMjkgfV0sIDIwOiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge1xuICAgICAgICAgICAgJ3VzZSBzdHJpY3QnO1xuXG4gICAgICAgICAgICB2YXIgRXZTdG9yZSA9IHJlcXVpcmUoJ2V2LXN0b3JlJyk7XG5cbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gRXZIb29rO1xuXG4gICAgICAgICAgICBmdW5jdGlvbiBFdkhvb2sodmFsdWUpIHtcbiAgICAgICAgICAgICAgICBpZiAoISh0aGlzIGluc3RhbmNlb2YgRXZIb29rKSkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gbmV3IEV2SG9vayh2YWx1ZSk7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgdGhpcy52YWx1ZSA9IHZhbHVlO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBFdkhvb2sucHJvdG90eXBlLmhvb2sgPSBmdW5jdGlvbiAobm9kZSwgcHJvcGVydHlOYW1lKSB7XG4gICAgICAgICAgICAgICAgdmFyIGVzID0gRXZTdG9yZShub2RlKTtcbiAgICAgICAgICAgICAgICB2YXIgcHJvcE5hbWUgPSBwcm9wZXJ0eU5hbWUuc3Vic3RyKDMpO1xuXG4gICAgICAgICAgICAgICAgZXNbcHJvcE5hbWVdID0gdGhpcy52YWx1ZTtcbiAgICAgICAgICAgIH07XG5cbiAgICAgICAgICAgIEV2SG9vay5wcm90b3R5cGUudW5ob29rID0gZnVuY3Rpb24gKG5vZGUsIHByb3BlcnR5TmFtZSkge1xuICAgICAgICAgICAgICAgIHZhciBlcyA9IEV2U3RvcmUobm9kZSk7XG4gICAgICAgICAgICAgICAgdmFyIHByb3BOYW1lID0gcHJvcGVydHlOYW1lLnN1YnN0cigzKTtcblxuICAgICAgICAgICAgICAgIGVzW3Byb3BOYW1lXSA9IHVuZGVmaW5lZDtcbiAgICAgICAgICAgIH07XG4gICAgICAgIH0sIHsgXCJldi1zdG9yZVwiOiA3IH1dLCAyMTogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHtcbiAgICAgICAgICAgICd1c2Ugc3RyaWN0JztcblxuICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBTb2Z0U2V0SG9vaztcblxuICAgICAgICAgICAgZnVuY3Rpb24gU29mdFNldEhvb2sodmFsdWUpIHtcbiAgICAgICAgICAgICAgICBpZiAoISh0aGlzIGluc3RhbmNlb2YgU29mdFNldEhvb2spKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBuZXcgU29mdFNldEhvb2sodmFsdWUpO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHRoaXMudmFsdWUgPSB2YWx1ZTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgU29mdFNldEhvb2sucHJvdG90eXBlLmhvb2sgPSBmdW5jdGlvbiAobm9kZSwgcHJvcGVydHlOYW1lKSB7XG4gICAgICAgICAgICAgICAgaWYgKG5vZGVbcHJvcGVydHlOYW1lXSAhPT0gdGhpcy52YWx1ZSkge1xuICAgICAgICAgICAgICAgICAgICBub2RlW3Byb3BlcnR5TmFtZV0gPSB0aGlzLnZhbHVlO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH07XG4gICAgICAgIH0sIHt9XSwgMjI6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICAndXNlIHN0cmljdCc7XG5cbiAgICAgICAgICAgIHZhciBpc0FycmF5ID0gcmVxdWlyZSgneC1pcy1hcnJheScpO1xuXG4gICAgICAgICAgICB2YXIgVk5vZGUgPSByZXF1aXJlKCcuLi92bm9kZS92bm9kZS5qcycpO1xuICAgICAgICAgICAgdmFyIFZUZXh0ID0gcmVxdWlyZSgnLi4vdm5vZGUvdnRleHQuanMnKTtcbiAgICAgICAgICAgIHZhciBpc1ZOb2RlID0gcmVxdWlyZSgnLi4vdm5vZGUvaXMtdm5vZGUnKTtcbiAgICAgICAgICAgIHZhciBpc1ZUZXh0ID0gcmVxdWlyZSgnLi4vdm5vZGUvaXMtdnRleHQnKTtcbiAgICAgICAgICAgIHZhciBpc1dpZGdldCA9IHJlcXVpcmUoJy4uL3Zub2RlL2lzLXdpZGdldCcpO1xuICAgICAgICAgICAgdmFyIGlzSG9vayA9IHJlcXVpcmUoJy4uL3Zub2RlL2lzLXZob29rJyk7XG4gICAgICAgICAgICB2YXIgaXNWVGh1bmsgPSByZXF1aXJlKCcuLi92bm9kZS9pcy10aHVuaycpO1xuXG4gICAgICAgICAgICB2YXIgcGFyc2VUYWcgPSByZXF1aXJlKCcuL3BhcnNlLXRhZy5qcycpO1xuICAgICAgICAgICAgdmFyIHNvZnRTZXRIb29rID0gcmVxdWlyZSgnLi9ob29rcy9zb2Z0LXNldC1ob29rLmpzJyk7XG4gICAgICAgICAgICB2YXIgZXZIb29rID0gcmVxdWlyZSgnLi9ob29rcy9ldi1ob29rLmpzJyk7XG5cbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gaDtcblxuICAgICAgICAgICAgZnVuY3Rpb24gaCh0YWdOYW1lLCBwcm9wZXJ0aWVzLCBjaGlsZHJlbikge1xuICAgICAgICAgICAgICAgIHZhciBjaGlsZE5vZGVzID0gW107XG4gICAgICAgICAgICAgICAgdmFyIHRhZywgcHJvcHMsIGtleSwgbmFtZXNwYWNlO1xuXG4gICAgICAgICAgICAgICAgaWYgKCFjaGlsZHJlbiAmJiBpc0NoaWxkcmVuKHByb3BlcnRpZXMpKSB7XG4gICAgICAgICAgICAgICAgICAgIGNoaWxkcmVuID0gcHJvcGVydGllcztcbiAgICAgICAgICAgICAgICAgICAgcHJvcHMgPSB7fTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICBwcm9wcyA9IHByb3BzIHx8IHByb3BlcnRpZXMgfHwge307XG4gICAgICAgICAgICAgICAgdGFnID0gcGFyc2VUYWcodGFnTmFtZSwgcHJvcHMpO1xuXG4gICAgICAgICAgICAgICAgLy8gc3VwcG9ydCBrZXlzXG4gICAgICAgICAgICAgICAgaWYgKHByb3BzLmhhc093blByb3BlcnR5KCdrZXknKSkge1xuICAgICAgICAgICAgICAgICAgICBrZXkgPSBwcm9wcy5rZXk7XG4gICAgICAgICAgICAgICAgICAgIHByb3BzLmtleSA9IHVuZGVmaW5lZDtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAvLyBzdXBwb3J0IG5hbWVzcGFjZVxuICAgICAgICAgICAgICAgIGlmIChwcm9wcy5oYXNPd25Qcm9wZXJ0eSgnbmFtZXNwYWNlJykpIHtcbiAgICAgICAgICAgICAgICAgICAgbmFtZXNwYWNlID0gcHJvcHMubmFtZXNwYWNlO1xuICAgICAgICAgICAgICAgICAgICBwcm9wcy5uYW1lc3BhY2UgPSB1bmRlZmluZWQ7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgLy8gZml4IGN1cnNvciBidWdcbiAgICAgICAgICAgICAgICBpZiAodGFnID09PSAnSU5QVVQnICYmICFuYW1lc3BhY2UgJiYgcHJvcHMuaGFzT3duUHJvcGVydHkoJ3ZhbHVlJykgJiYgcHJvcHMudmFsdWUgIT09IHVuZGVmaW5lZCAmJiAhaXNIb29rKHByb3BzLnZhbHVlKSkge1xuICAgICAgICAgICAgICAgICAgICBwcm9wcy52YWx1ZSA9IHNvZnRTZXRIb29rKHByb3BzLnZhbHVlKTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICB0cmFuc2Zvcm1Qcm9wZXJ0aWVzKHByb3BzKTtcblxuICAgICAgICAgICAgICAgIGlmIChjaGlsZHJlbiAhPT0gdW5kZWZpbmVkICYmIGNoaWxkcmVuICE9PSBudWxsKSB7XG4gICAgICAgICAgICAgICAgICAgIGFkZENoaWxkKGNoaWxkcmVuLCBjaGlsZE5vZGVzLCB0YWcsIHByb3BzKTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICByZXR1cm4gbmV3IFZOb2RlKHRhZywgcHJvcHMsIGNoaWxkTm9kZXMsIGtleSwgbmFtZXNwYWNlKTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZnVuY3Rpb24gYWRkQ2hpbGQoYywgY2hpbGROb2RlcywgdGFnLCBwcm9wcykge1xuICAgICAgICAgICAgICAgIGlmICh0eXBlb2YgYyA9PT0gJ3N0cmluZycpIHtcbiAgICAgICAgICAgICAgICAgICAgY2hpbGROb2Rlcy5wdXNoKG5ldyBWVGV4dChjKSk7XG4gICAgICAgICAgICAgICAgfSBlbHNlIGlmICh0eXBlb2YgYyA9PT0gJ251bWJlcicpIHtcbiAgICAgICAgICAgICAgICAgICAgY2hpbGROb2Rlcy5wdXNoKG5ldyBWVGV4dChTdHJpbmcoYykpKTtcbiAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKGlzQ2hpbGQoYykpIHtcbiAgICAgICAgICAgICAgICAgICAgY2hpbGROb2Rlcy5wdXNoKGMpO1xuICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoaXNBcnJheShjKSkge1xuICAgICAgICAgICAgICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IGMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGFkZENoaWxkKGNbaV0sIGNoaWxkTm9kZXMsIHRhZywgcHJvcHMpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfSBlbHNlIGlmIChjID09PSBudWxsIHx8IGMgPT09IHVuZGVmaW5lZCkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgdGhyb3cgVW5leHBlY3RlZFZpcnR1YWxFbGVtZW50KHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGZvcmVpZ25PYmplY3Q6IGMsXG4gICAgICAgICAgICAgICAgICAgICAgICBwYXJlbnRWbm9kZToge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRhZ05hbWU6IHRhZyxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBwcm9wZXJ0aWVzOiBwcm9wc1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIHRyYW5zZm9ybVByb3BlcnRpZXMocHJvcHMpIHtcbiAgICAgICAgICAgICAgICBmb3IgKHZhciBwcm9wTmFtZSBpbiBwcm9wcykge1xuICAgICAgICAgICAgICAgICAgICBpZiAocHJvcHMuaGFzT3duUHJvcGVydHkocHJvcE5hbWUpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICB2YXIgdmFsdWUgPSBwcm9wc1twcm9wTmFtZV07XG5cbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChpc0hvb2sodmFsdWUpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgY29udGludWU7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChwcm9wTmFtZS5zdWJzdHIoMCwgMykgPT09ICdldi0nKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gYWRkIGV2LWZvbyBzdXBwb3J0XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcHJvcHNbcHJvcE5hbWVdID0gZXZIb29rKHZhbHVlKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZnVuY3Rpb24gaXNDaGlsZCh4KSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGlzVk5vZGUoeCkgfHwgaXNWVGV4dCh4KSB8fCBpc1dpZGdldCh4KSB8fCBpc1ZUaHVuayh4KTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZnVuY3Rpb24gaXNDaGlsZHJlbih4KSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHR5cGVvZiB4ID09PSAnc3RyaW5nJyB8fCBpc0FycmF5KHgpIHx8IGlzQ2hpbGQoeCk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIFVuZXhwZWN0ZWRWaXJ0dWFsRWxlbWVudChkYXRhKSB7XG4gICAgICAgICAgICAgICAgdmFyIGVyciA9IG5ldyBFcnJvcigpO1xuXG4gICAgICAgICAgICAgICAgZXJyLnR5cGUgPSAndmlydHVhbC1oeXBlcnNjcmlwdC51bmV4cGVjdGVkLnZpcnR1YWwtZWxlbWVudCc7XG4gICAgICAgICAgICAgICAgZXJyLm1lc3NhZ2UgPSAnVW5leHBlY3RlZCB2aXJ0dWFsIGNoaWxkIHBhc3NlZCB0byBoKCkuXFxuJyArICdFeHBlY3RlZCBhIFZOb2RlIC8gVnRodW5rIC8gVldpZGdldCAvIHN0cmluZyBidXQ6XFxuJyArICdnb3Q6XFxuJyArIGVycm9yU3RyaW5nKGRhdGEuZm9yZWlnbk9iamVjdCkgKyAnLlxcbicgKyAnVGhlIHBhcmVudCB2bm9kZSBpczpcXG4nICsgZXJyb3JTdHJpbmcoZGF0YS5wYXJlbnRWbm9kZSk7XG4gICAgICAgICAgICAgICAgJ1xcbicgKyAnU3VnZ2VzdGVkIGZpeDogY2hhbmdlIHlvdXIgYGgoLi4uLCBbIC4uLiBdKWAgY2FsbHNpdGUuJztcbiAgICAgICAgICAgICAgICBlcnIuZm9yZWlnbk9iamVjdCA9IGRhdGEuZm9yZWlnbk9iamVjdDtcbiAgICAgICAgICAgICAgICBlcnIucGFyZW50Vm5vZGUgPSBkYXRhLnBhcmVudFZub2RlO1xuXG4gICAgICAgICAgICAgICAgcmV0dXJuIGVycjtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZnVuY3Rpb24gZXJyb3JTdHJpbmcob2JqKSB7XG4gICAgICAgICAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIEpTT04uc3RyaW5naWZ5KG9iaiwgbnVsbCwgJyAgICAnKTtcbiAgICAgICAgICAgICAgICB9IGNhdGNoIChlKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBTdHJpbmcob2JqKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH0sIHsgXCIuLi92bm9kZS9pcy10aHVua1wiOiAyNSwgXCIuLi92bm9kZS9pcy12aG9va1wiOiAyNiwgXCIuLi92bm9kZS9pcy12bm9kZVwiOiAyNywgXCIuLi92bm9kZS9pcy12dGV4dFwiOiAyOCwgXCIuLi92bm9kZS9pcy13aWRnZXRcIjogMjksIFwiLi4vdm5vZGUvdm5vZGUuanNcIjogMzEsIFwiLi4vdm5vZGUvdnRleHQuanNcIjogMzMsIFwiLi9ob29rcy9ldi1ob29rLmpzXCI6IDIwLCBcIi4vaG9va3Mvc29mdC1zZXQtaG9vay5qc1wiOiAyMSwgXCIuL3BhcnNlLXRhZy5qc1wiOiAyMywgXCJ4LWlzLWFycmF5XCI6IDEyIH1dLCAyMzogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHtcbiAgICAgICAgICAgICd1c2Ugc3RyaWN0JztcblxuICAgICAgICAgICAgdmFyIHNwbGl0ID0gcmVxdWlyZSgnYnJvd3Nlci1zcGxpdCcpO1xuXG4gICAgICAgICAgICB2YXIgY2xhc3NJZFNwbGl0ID0gLyhbXFwuI10/W2EtekEtWjAtOVxcdTAwN0YtXFx1RkZGRl86LV0rKS87XG4gICAgICAgICAgICB2YXIgbm90Q2xhc3NJZCA9IC9eXFwufCMvO1xuXG4gICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IHBhcnNlVGFnO1xuXG4gICAgICAgICAgICBmdW5jdGlvbiBwYXJzZVRhZyh0YWcsIHByb3BzKSB7XG4gICAgICAgICAgICAgICAgaWYgKCF0YWcpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuICdESVYnO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHZhciBub0lkID0gIXByb3BzLmhhc093blByb3BlcnR5KCdpZCcpO1xuXG4gICAgICAgICAgICAgICAgdmFyIHRhZ1BhcnRzID0gc3BsaXQodGFnLCBjbGFzc0lkU3BsaXQpO1xuICAgICAgICAgICAgICAgIHZhciB0YWdOYW1lID0gbnVsbDtcblxuICAgICAgICAgICAgICAgIGlmIChub3RDbGFzc0lkLnRlc3QodGFnUGFydHNbMV0pKSB7XG4gICAgICAgICAgICAgICAgICAgIHRhZ05hbWUgPSAnRElWJztcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICB2YXIgY2xhc3NlcywgcGFydCwgdHlwZSwgaTtcblxuICAgICAgICAgICAgICAgIGZvciAoaSA9IDA7IGkgPCB0YWdQYXJ0cy5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgICAgICAgICBwYXJ0ID0gdGFnUGFydHNbaV07XG5cbiAgICAgICAgICAgICAgICAgICAgaWYgKCFwYXJ0KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBjb250aW51ZTtcbiAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgIHR5cGUgPSBwYXJ0LmNoYXJBdCgwKTtcblxuICAgICAgICAgICAgICAgICAgICBpZiAoIXRhZ05hbWUpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHRhZ05hbWUgPSBwYXJ0O1xuICAgICAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKHR5cGUgPT09ICcuJykge1xuICAgICAgICAgICAgICAgICAgICAgICAgY2xhc3NlcyA9IGNsYXNzZXMgfHwgW107XG4gICAgICAgICAgICAgICAgICAgICAgICBjbGFzc2VzLnB1c2gocGFydC5zdWJzdHJpbmcoMSwgcGFydC5sZW5ndGgpKTtcbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIGlmICh0eXBlID09PSAnIycgJiYgbm9JZCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgcHJvcHMuaWQgPSBwYXJ0LnN1YnN0cmluZygxLCBwYXJ0Lmxlbmd0aCk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICBpZiAoY2xhc3Nlcykge1xuICAgICAgICAgICAgICAgICAgICBpZiAocHJvcHMuY2xhc3NOYW1lKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBjbGFzc2VzLnB1c2gocHJvcHMuY2xhc3NOYW1lKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgIHByb3BzLmNsYXNzTmFtZSA9IGNsYXNzZXMuam9pbignICcpO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHJldHVybiBwcm9wcy5uYW1lc3BhY2UgPyB0YWdOYW1lIDogdGFnTmFtZS50b1VwcGVyQ2FzZSgpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9LCB7IFwiYnJvd3Nlci1zcGxpdFwiOiA1IH1dLCAyNDogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHtcbiAgICAgICAgICAgIHZhciBpc1ZOb2RlID0gcmVxdWlyZShcIi4vaXMtdm5vZGVcIik7XG4gICAgICAgICAgICB2YXIgaXNWVGV4dCA9IHJlcXVpcmUoXCIuL2lzLXZ0ZXh0XCIpO1xuICAgICAgICAgICAgdmFyIGlzV2lkZ2V0ID0gcmVxdWlyZShcIi4vaXMtd2lkZ2V0XCIpO1xuICAgICAgICAgICAgdmFyIGlzVGh1bmsgPSByZXF1aXJlKFwiLi9pcy10aHVua1wiKTtcblxuICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBoYW5kbGVUaHVuaztcblxuICAgICAgICAgICAgZnVuY3Rpb24gaGFuZGxlVGh1bmsoYSwgYikge1xuICAgICAgICAgICAgICAgIHZhciByZW5kZXJlZEEgPSBhO1xuICAgICAgICAgICAgICAgIHZhciByZW5kZXJlZEIgPSBiO1xuXG4gICAgICAgICAgICAgICAgaWYgKGlzVGh1bmsoYikpIHtcbiAgICAgICAgICAgICAgICAgICAgcmVuZGVyZWRCID0gcmVuZGVyVGh1bmsoYiwgYSk7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgaWYgKGlzVGh1bmsoYSkpIHtcbiAgICAgICAgICAgICAgICAgICAgcmVuZGVyZWRBID0gcmVuZGVyVGh1bmsoYSwgbnVsbCk7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgICAgICAgICAgYTogcmVuZGVyZWRBLFxuICAgICAgICAgICAgICAgICAgICBiOiByZW5kZXJlZEJcbiAgICAgICAgICAgICAgICB9O1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBmdW5jdGlvbiByZW5kZXJUaHVuayh0aHVuaywgcHJldmlvdXMpIHtcbiAgICAgICAgICAgICAgICB2YXIgcmVuZGVyZWRUaHVuayA9IHRodW5rLnZub2RlO1xuXG4gICAgICAgICAgICAgICAgaWYgKCFyZW5kZXJlZFRodW5rKSB7XG4gICAgICAgICAgICAgICAgICAgIHJlbmRlcmVkVGh1bmsgPSB0aHVuay52bm9kZSA9IHRodW5rLnJlbmRlcihwcmV2aW91cyk7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgaWYgKCEoaXNWTm9kZShyZW5kZXJlZFRodW5rKSB8fCBpc1ZUZXh0KHJlbmRlcmVkVGh1bmspIHx8IGlzV2lkZ2V0KHJlbmRlcmVkVGh1bmspKSkge1xuICAgICAgICAgICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoXCJ0aHVuayBkaWQgbm90IHJldHVybiBhIHZhbGlkIG5vZGVcIik7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgcmV0dXJuIHJlbmRlcmVkVGh1bms7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0sIHsgXCIuL2lzLXRodW5rXCI6IDI1LCBcIi4vaXMtdm5vZGVcIjogMjcsIFwiLi9pcy12dGV4dFwiOiAyOCwgXCIuL2lzLXdpZGdldFwiOiAyOSB9XSwgMjU6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IGlzVGh1bms7XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIGlzVGh1bmsodCkge1xuICAgICAgICAgICAgICAgIHJldHVybiB0ICYmIHQudHlwZSA9PT0gXCJUaHVua1wiO1xuICAgICAgICAgICAgfVxuICAgICAgICB9LCB7fV0sIDI2OiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge1xuICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBpc0hvb2s7XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIGlzSG9vayhob29rKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGhvb2sgJiYgKHR5cGVvZiBob29rLmhvb2sgPT09IFwiZnVuY3Rpb25cIiAmJiAhaG9vay5oYXNPd25Qcm9wZXJ0eShcImhvb2tcIikgfHwgdHlwZW9mIGhvb2sudW5ob29rID09PSBcImZ1bmN0aW9uXCIgJiYgIWhvb2suaGFzT3duUHJvcGVydHkoXCJ1bmhvb2tcIikpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9LCB7fV0sIDI3OiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge1xuICAgICAgICAgICAgdmFyIHZlcnNpb24gPSByZXF1aXJlKFwiLi92ZXJzaW9uXCIpO1xuXG4gICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IGlzVmlydHVhbE5vZGU7XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIGlzVmlydHVhbE5vZGUoeCkge1xuICAgICAgICAgICAgICAgIHJldHVybiB4ICYmIHgudHlwZSA9PT0gXCJWaXJ0dWFsTm9kZVwiICYmIHgudmVyc2lvbiA9PT0gdmVyc2lvbjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSwgeyBcIi4vdmVyc2lvblwiOiAzMCB9XSwgMjg6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICB2YXIgdmVyc2lvbiA9IHJlcXVpcmUoXCIuL3ZlcnNpb25cIik7XG5cbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gaXNWaXJ0dWFsVGV4dDtcblxuICAgICAgICAgICAgZnVuY3Rpb24gaXNWaXJ0dWFsVGV4dCh4KSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHggJiYgeC50eXBlID09PSBcIlZpcnR1YWxUZXh0XCIgJiYgeC52ZXJzaW9uID09PSB2ZXJzaW9uO1xuICAgICAgICAgICAgfVxuICAgICAgICB9LCB7IFwiLi92ZXJzaW9uXCI6IDMwIH1dLCAyOTogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHtcbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzID0gaXNXaWRnZXQ7XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIGlzV2lkZ2V0KHcpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gdyAmJiB3LnR5cGUgPT09IFwiV2lkZ2V0XCI7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0sIHt9XSwgMzA6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IFwiMlwiO1xuICAgICAgICB9LCB7fV0sIDMxOiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge1xuICAgICAgICAgICAgdmFyIHZlcnNpb24gPSByZXF1aXJlKFwiLi92ZXJzaW9uXCIpO1xuICAgICAgICAgICAgdmFyIGlzVk5vZGUgPSByZXF1aXJlKFwiLi9pcy12bm9kZVwiKTtcbiAgICAgICAgICAgIHZhciBpc1dpZGdldCA9IHJlcXVpcmUoXCIuL2lzLXdpZGdldFwiKTtcbiAgICAgICAgICAgIHZhciBpc1RodW5rID0gcmVxdWlyZShcIi4vaXMtdGh1bmtcIik7XG4gICAgICAgICAgICB2YXIgaXNWSG9vayA9IHJlcXVpcmUoXCIuL2lzLXZob29rXCIpO1xuXG4gICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IFZpcnR1YWxOb2RlO1xuXG4gICAgICAgICAgICB2YXIgbm9Qcm9wZXJ0aWVzID0ge307XG4gICAgICAgICAgICB2YXIgbm9DaGlsZHJlbiA9IFtdO1xuXG4gICAgICAgICAgICBmdW5jdGlvbiBWaXJ0dWFsTm9kZSh0YWdOYW1lLCBwcm9wZXJ0aWVzLCBjaGlsZHJlbiwga2V5LCBuYW1lc3BhY2UpIHtcbiAgICAgICAgICAgICAgICB0aGlzLnRhZ05hbWUgPSB0YWdOYW1lO1xuICAgICAgICAgICAgICAgIHRoaXMucHJvcGVydGllcyA9IHByb3BlcnRpZXMgfHwgbm9Qcm9wZXJ0aWVzO1xuICAgICAgICAgICAgICAgIHRoaXMuY2hpbGRyZW4gPSBjaGlsZHJlbiB8fCBub0NoaWxkcmVuO1xuICAgICAgICAgICAgICAgIHRoaXMua2V5ID0ga2V5ICE9IG51bGwgPyBTdHJpbmcoa2V5KSA6IHVuZGVmaW5lZDtcbiAgICAgICAgICAgICAgICB0aGlzLm5hbWVzcGFjZSA9IHR5cGVvZiBuYW1lc3BhY2UgPT09IFwic3RyaW5nXCIgPyBuYW1lc3BhY2UgOiBudWxsO1xuXG4gICAgICAgICAgICAgICAgdmFyIGNvdW50ID0gY2hpbGRyZW4gJiYgY2hpbGRyZW4ubGVuZ3RoIHx8IDA7XG4gICAgICAgICAgICAgICAgdmFyIGRlc2NlbmRhbnRzID0gMDtcbiAgICAgICAgICAgICAgICB2YXIgaGFzV2lkZ2V0cyA9IGZhbHNlO1xuICAgICAgICAgICAgICAgIHZhciBoYXNUaHVua3MgPSBmYWxzZTtcbiAgICAgICAgICAgICAgICB2YXIgZGVzY2VuZGFudEhvb2tzID0gZmFsc2U7XG4gICAgICAgICAgICAgICAgdmFyIGhvb2tzO1xuXG4gICAgICAgICAgICAgICAgZm9yICh2YXIgcHJvcE5hbWUgaW4gcHJvcGVydGllcykge1xuICAgICAgICAgICAgICAgICAgICBpZiAocHJvcGVydGllcy5oYXNPd25Qcm9wZXJ0eShwcm9wTmFtZSkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHZhciBwcm9wZXJ0eSA9IHByb3BlcnRpZXNbcHJvcE5hbWVdO1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGlzVkhvb2socHJvcGVydHkpICYmIHByb3BlcnR5LnVuaG9vaykge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmICghaG9va3MpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaG9va3MgPSB7fTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBob29rc1twcm9wTmFtZV0gPSBwcm9wZXJ0eTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgY291bnQ7IGkrKykge1xuICAgICAgICAgICAgICAgICAgICB2YXIgY2hpbGQgPSBjaGlsZHJlbltpXTtcbiAgICAgICAgICAgICAgICAgICAgaWYgKGlzVk5vZGUoY2hpbGQpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBkZXNjZW5kYW50cyArPSBjaGlsZC5jb3VudCB8fCAwO1xuXG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoIWhhc1dpZGdldHMgJiYgY2hpbGQuaGFzV2lkZ2V0cykge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGhhc1dpZGdldHMgPSB0cnVlO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoIWhhc1RodW5rcyAmJiBjaGlsZC5oYXNUaHVua3MpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBoYXNUaHVua3MgPSB0cnVlO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoIWRlc2NlbmRhbnRIb29rcyAmJiAoY2hpbGQuaG9va3MgfHwgY2hpbGQuZGVzY2VuZGFudEhvb2tzKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRlc2NlbmRhbnRIb29rcyA9IHRydWU7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoIWhhc1dpZGdldHMgJiYgaXNXaWRnZXQoY2hpbGQpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAodHlwZW9mIGNoaWxkLmRlc3Ryb3kgPT09IFwiZnVuY3Rpb25cIikge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGhhc1dpZGdldHMgPSB0cnVlO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKCFoYXNUaHVua3MgJiYgaXNUaHVuayhjaGlsZCkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGhhc1RodW5rcyA9IHRydWU7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICB0aGlzLmNvdW50ID0gY291bnQgKyBkZXNjZW5kYW50cztcbiAgICAgICAgICAgICAgICB0aGlzLmhhc1dpZGdldHMgPSBoYXNXaWRnZXRzO1xuICAgICAgICAgICAgICAgIHRoaXMuaGFzVGh1bmtzID0gaGFzVGh1bmtzO1xuICAgICAgICAgICAgICAgIHRoaXMuaG9va3MgPSBob29rcztcbiAgICAgICAgICAgICAgICB0aGlzLmRlc2NlbmRhbnRIb29rcyA9IGRlc2NlbmRhbnRIb29rcztcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgVmlydHVhbE5vZGUucHJvdG90eXBlLnZlcnNpb24gPSB2ZXJzaW9uO1xuICAgICAgICAgICAgVmlydHVhbE5vZGUucHJvdG90eXBlLnR5cGUgPSBcIlZpcnR1YWxOb2RlXCI7XG4gICAgICAgIH0sIHsgXCIuL2lzLXRodW5rXCI6IDI1LCBcIi4vaXMtdmhvb2tcIjogMjYsIFwiLi9pcy12bm9kZVwiOiAyNywgXCIuL2lzLXdpZGdldFwiOiAyOSwgXCIuL3ZlcnNpb25cIjogMzAgfV0sIDMyOiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge1xuICAgICAgICAgICAgdmFyIHZlcnNpb24gPSByZXF1aXJlKFwiLi92ZXJzaW9uXCIpO1xuXG4gICAgICAgICAgICBWaXJ0dWFsUGF0Y2guTk9ORSA9IDA7XG4gICAgICAgICAgICBWaXJ0dWFsUGF0Y2guVlRFWFQgPSAxO1xuICAgICAgICAgICAgVmlydHVhbFBhdGNoLlZOT0RFID0gMjtcbiAgICAgICAgICAgIFZpcnR1YWxQYXRjaC5XSURHRVQgPSAzO1xuICAgICAgICAgICAgVmlydHVhbFBhdGNoLlBST1BTID0gNDtcbiAgICAgICAgICAgIFZpcnR1YWxQYXRjaC5PUkRFUiA9IDU7XG4gICAgICAgICAgICBWaXJ0dWFsUGF0Y2guSU5TRVJUID0gNjtcbiAgICAgICAgICAgIFZpcnR1YWxQYXRjaC5SRU1PVkUgPSA3O1xuICAgICAgICAgICAgVmlydHVhbFBhdGNoLlRIVU5LID0gODtcblxuICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBWaXJ0dWFsUGF0Y2g7XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIFZpcnR1YWxQYXRjaCh0eXBlLCB2Tm9kZSwgcGF0Y2gpIHtcbiAgICAgICAgICAgICAgICB0aGlzLnR5cGUgPSBOdW1iZXIodHlwZSk7XG4gICAgICAgICAgICAgICAgdGhpcy52Tm9kZSA9IHZOb2RlO1xuICAgICAgICAgICAgICAgIHRoaXMucGF0Y2ggPSBwYXRjaDtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgVmlydHVhbFBhdGNoLnByb3RvdHlwZS52ZXJzaW9uID0gdmVyc2lvbjtcbiAgICAgICAgICAgIFZpcnR1YWxQYXRjaC5wcm90b3R5cGUudHlwZSA9IFwiVmlydHVhbFBhdGNoXCI7XG4gICAgICAgIH0sIHsgXCIuL3ZlcnNpb25cIjogMzAgfV0sIDMzOiBbZnVuY3Rpb24gKHJlcXVpcmUsIG1vZHVsZSwgZXhwb3J0cykge1xuICAgICAgICAgICAgdmFyIHZlcnNpb24gPSByZXF1aXJlKFwiLi92ZXJzaW9uXCIpO1xuXG4gICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IFZpcnR1YWxUZXh0O1xuXG4gICAgICAgICAgICBmdW5jdGlvbiBWaXJ0dWFsVGV4dCh0ZXh0KSB7XG4gICAgICAgICAgICAgICAgdGhpcy50ZXh0ID0gU3RyaW5nKHRleHQpO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBWaXJ0dWFsVGV4dC5wcm90b3R5cGUudmVyc2lvbiA9IHZlcnNpb247XG4gICAgICAgICAgICBWaXJ0dWFsVGV4dC5wcm90b3R5cGUudHlwZSA9IFwiVmlydHVhbFRleHRcIjtcbiAgICAgICAgfSwgeyBcIi4vdmVyc2lvblwiOiAzMCB9XSwgMzQ6IFtmdW5jdGlvbiAocmVxdWlyZSwgbW9kdWxlLCBleHBvcnRzKSB7XG4gICAgICAgICAgICB2YXIgaXNPYmplY3QgPSByZXF1aXJlKFwiaXMtb2JqZWN0XCIpO1xuICAgICAgICAgICAgdmFyIGlzSG9vayA9IHJlcXVpcmUoXCIuLi92bm9kZS9pcy12aG9va1wiKTtcblxuICAgICAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBkaWZmUHJvcHM7XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIGRpZmZQcm9wcyhhLCBiKSB7XG4gICAgICAgICAgICAgICAgdmFyIGRpZmY7XG5cbiAgICAgICAgICAgICAgICBmb3IgKHZhciBhS2V5IGluIGEpIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKCEoYUtleSBpbiBiKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgZGlmZiA9IGRpZmYgfHwge307XG4gICAgICAgICAgICAgICAgICAgICAgICBkaWZmW2FLZXldID0gdW5kZWZpbmVkO1xuICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgdmFyIGFWYWx1ZSA9IGFbYUtleV07XG4gICAgICAgICAgICAgICAgICAgIHZhciBiVmFsdWUgPSBiW2FLZXldO1xuXG4gICAgICAgICAgICAgICAgICAgIGlmIChhVmFsdWUgPT09IGJWYWx1ZSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgY29udGludWU7XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoaXNPYmplY3QoYVZhbHVlKSAmJiBpc09iamVjdChiVmFsdWUpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoZ2V0UHJvdG90eXBlKGJWYWx1ZSkgIT09IGdldFByb3RvdHlwZShhVmFsdWUpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgZGlmZiA9IGRpZmYgfHwge307XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgZGlmZlthS2V5XSA9IGJWYWx1ZTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoaXNIb29rKGJWYWx1ZSkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBkaWZmID0gZGlmZiB8fCB7fTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBkaWZmW2FLZXldID0gYlZhbHVlO1xuICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB2YXIgb2JqZWN0RGlmZiA9IGRpZmZQcm9wcyhhVmFsdWUsIGJWYWx1ZSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKG9iamVjdERpZmYpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZGlmZiA9IGRpZmYgfHwge307XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRpZmZbYUtleV0gPSBvYmplY3REaWZmO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGRpZmYgPSBkaWZmIHx8IHt9O1xuICAgICAgICAgICAgICAgICAgICAgICAgZGlmZlthS2V5XSA9IGJWYWx1ZTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIGZvciAodmFyIGJLZXkgaW4gYikge1xuICAgICAgICAgICAgICAgICAgICBpZiAoIShiS2V5IGluIGEpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBkaWZmID0gZGlmZiB8fCB7fTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGRpZmZbYktleV0gPSBiW2JLZXldO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgcmV0dXJuIGRpZmY7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIGdldFByb3RvdHlwZSh2YWx1ZSkge1xuICAgICAgICAgICAgICAgIGlmIChPYmplY3QuZ2V0UHJvdG90eXBlT2YpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIE9iamVjdC5nZXRQcm90b3R5cGVPZih2YWx1ZSk7XG4gICAgICAgICAgICAgICAgfSBlbHNlIGlmICh2YWx1ZS5fX3Byb3RvX18pIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHZhbHVlLl9fcHJvdG9fXztcbiAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKHZhbHVlLmNvbnN0cnVjdG9yKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiB2YWx1ZS5jb25zdHJ1Y3Rvci5wcm90b3R5cGU7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9LCB7IFwiLi4vdm5vZGUvaXMtdmhvb2tcIjogMjYsIFwiaXMtb2JqZWN0XCI6IDExIH1dLCAzNTogW2Z1bmN0aW9uIChyZXF1aXJlLCBtb2R1bGUsIGV4cG9ydHMpIHtcbiAgICAgICAgICAgIHZhciBpc0FycmF5ID0gcmVxdWlyZShcIngtaXMtYXJyYXlcIik7XG5cbiAgICAgICAgICAgIHZhciBWUGF0Y2ggPSByZXF1aXJlKFwiLi4vdm5vZGUvdnBhdGNoXCIpO1xuICAgICAgICAgICAgdmFyIGlzVk5vZGUgPSByZXF1aXJlKFwiLi4vdm5vZGUvaXMtdm5vZGVcIik7XG4gICAgICAgICAgICB2YXIgaXNWVGV4dCA9IHJlcXVpcmUoXCIuLi92bm9kZS9pcy12dGV4dFwiKTtcbiAgICAgICAgICAgIHZhciBpc1dpZGdldCA9IHJlcXVpcmUoXCIuLi92bm9kZS9pcy13aWRnZXRcIik7XG4gICAgICAgICAgICB2YXIgaXNUaHVuayA9IHJlcXVpcmUoXCIuLi92bm9kZS9pcy10aHVua1wiKTtcbiAgICAgICAgICAgIHZhciBoYW5kbGVUaHVuayA9IHJlcXVpcmUoXCIuLi92bm9kZS9oYW5kbGUtdGh1bmtcIik7XG5cbiAgICAgICAgICAgIHZhciBkaWZmUHJvcHMgPSByZXF1aXJlKFwiLi9kaWZmLXByb3BzXCIpO1xuXG4gICAgICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IGRpZmY7XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIGRpZmYoYSwgYikge1xuICAgICAgICAgICAgICAgIHZhciBwYXRjaCA9IHsgYTogYSB9O1xuICAgICAgICAgICAgICAgIHdhbGsoYSwgYiwgcGF0Y2gsIDApO1xuICAgICAgICAgICAgICAgIHJldHVybiBwYXRjaDtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZnVuY3Rpb24gd2FsayhhLCBiLCBwYXRjaCwgaW5kZXgpIHtcbiAgICAgICAgICAgICAgICBpZiAoYSA9PT0gYikge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgdmFyIGFwcGx5ID0gcGF0Y2hbaW5kZXhdO1xuICAgICAgICAgICAgICAgIHZhciBhcHBseUNsZWFyID0gZmFsc2U7XG5cbiAgICAgICAgICAgICAgICBpZiAoaXNUaHVuayhhKSB8fCBpc1RodW5rKGIpKSB7XG4gICAgICAgICAgICAgICAgICAgIHRodW5rcyhhLCBiLCBwYXRjaCwgaW5kZXgpO1xuICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoYiA9PSBudWxsKSB7XG5cbiAgICAgICAgICAgICAgICAgICAgLy8gSWYgYSBpcyBhIHdpZGdldCB3ZSB3aWxsIGFkZCBhIHJlbW92ZSBwYXRjaCBmb3IgaXRcbiAgICAgICAgICAgICAgICAgICAgLy8gT3RoZXJ3aXNlIGFueSBjaGlsZCB3aWRnZXRzL2hvb2tzIG11c3QgYmUgZGVzdHJveWVkLlxuICAgICAgICAgICAgICAgICAgICAvLyBUaGlzIHByZXZlbnRzIGFkZGluZyB0d28gcmVtb3ZlIHBhdGNoZXMgZm9yIGEgd2lkZ2V0LlxuICAgICAgICAgICAgICAgICAgICBpZiAoIWlzV2lkZ2V0KGEpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBjbGVhclN0YXRlKGEsIHBhdGNoLCBpbmRleCk7XG4gICAgICAgICAgICAgICAgICAgICAgICBhcHBseSA9IHBhdGNoW2luZGV4XTtcbiAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgIGFwcGx5ID0gYXBwZW5kUGF0Y2goYXBwbHksIG5ldyBWUGF0Y2goVlBhdGNoLlJFTU9WRSwgYSwgYikpO1xuICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoaXNWTm9kZShiKSkge1xuICAgICAgICAgICAgICAgICAgICBpZiAoaXNWTm9kZShhKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGEudGFnTmFtZSA9PT0gYi50YWdOYW1lICYmIGEubmFtZXNwYWNlID09PSBiLm5hbWVzcGFjZSAmJiBhLmtleSA9PT0gYi5rZXkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB2YXIgcHJvcHNQYXRjaCA9IGRpZmZQcm9wcyhhLnByb3BlcnRpZXMsIGIucHJvcGVydGllcyk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHByb3BzUGF0Y2gpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYXBwbHkgPSBhcHBlbmRQYXRjaChhcHBseSwgbmV3IFZQYXRjaChWUGF0Y2guUFJPUFMsIGEsIHByb3BzUGF0Y2gpKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgYXBwbHkgPSBkaWZmQ2hpbGRyZW4oYSwgYiwgcGF0Y2gsIGFwcGx5LCBpbmRleCk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGFwcGx5ID0gYXBwZW5kUGF0Y2goYXBwbHksIG5ldyBWUGF0Y2goVlBhdGNoLlZOT0RFLCBhLCBiKSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgYXBwbHlDbGVhciA9IHRydWU7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBhcHBseSA9IGFwcGVuZFBhdGNoKGFwcGx5LCBuZXcgVlBhdGNoKFZQYXRjaC5WTk9ERSwgYSwgYikpO1xuICAgICAgICAgICAgICAgICAgICAgICAgYXBwbHlDbGVhciA9IHRydWU7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKGlzVlRleHQoYikpIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKCFpc1ZUZXh0KGEpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBhcHBseSA9IGFwcGVuZFBhdGNoKGFwcGx5LCBuZXcgVlBhdGNoKFZQYXRjaC5WVEVYVCwgYSwgYikpO1xuICAgICAgICAgICAgICAgICAgICAgICAgYXBwbHlDbGVhciA9IHRydWU7XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoYS50ZXh0ICE9PSBiLnRleHQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGFwcGx5ID0gYXBwZW5kUGF0Y2goYXBwbHksIG5ldyBWUGF0Y2goVlBhdGNoLlZURVhULCBhLCBiKSk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKGlzV2lkZ2V0KGIpKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmICghaXNXaWRnZXQoYSkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGFwcGx5Q2xlYXIgPSB0cnVlO1xuICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgYXBwbHkgPSBhcHBlbmRQYXRjaChhcHBseSwgbmV3IFZQYXRjaChWUGF0Y2guV0lER0VULCBhLCBiKSk7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgaWYgKGFwcGx5KSB7XG4gICAgICAgICAgICAgICAgICAgIHBhdGNoW2luZGV4XSA9IGFwcGx5O1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIGlmIChhcHBseUNsZWFyKSB7XG4gICAgICAgICAgICAgICAgICAgIGNsZWFyU3RhdGUoYSwgcGF0Y2gsIGluZGV4KTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIGRpZmZDaGlsZHJlbihhLCBiLCBwYXRjaCwgYXBwbHksIGluZGV4KSB7XG4gICAgICAgICAgICAgICAgdmFyIGFDaGlsZHJlbiA9IGEuY2hpbGRyZW47XG4gICAgICAgICAgICAgICAgdmFyIG9yZGVyZWRTZXQgPSByZW9yZGVyKGFDaGlsZHJlbiwgYi5jaGlsZHJlbik7XG4gICAgICAgICAgICAgICAgdmFyIGJDaGlsZHJlbiA9IG9yZGVyZWRTZXQuY2hpbGRyZW47XG5cbiAgICAgICAgICAgICAgICB2YXIgYUxlbiA9IGFDaGlsZHJlbi5sZW5ndGg7XG4gICAgICAgICAgICAgICAgdmFyIGJMZW4gPSBiQ2hpbGRyZW4ubGVuZ3RoO1xuICAgICAgICAgICAgICAgIHZhciBsZW4gPSBhTGVuID4gYkxlbiA/IGFMZW4gOiBiTGVuO1xuXG4gICAgICAgICAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCBsZW47IGkrKykge1xuICAgICAgICAgICAgICAgICAgICB2YXIgbGVmdE5vZGUgPSBhQ2hpbGRyZW5baV07XG4gICAgICAgICAgICAgICAgICAgIHZhciByaWdodE5vZGUgPSBiQ2hpbGRyZW5baV07XG4gICAgICAgICAgICAgICAgICAgIGluZGV4ICs9IDE7XG5cbiAgICAgICAgICAgICAgICAgICAgaWYgKCFsZWZ0Tm9kZSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHJpZ2h0Tm9kZSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIEV4Y2VzcyBub2RlcyBpbiBiIG5lZWQgdG8gYmUgYWRkZWRcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBhcHBseSA9IGFwcGVuZFBhdGNoKGFwcGx5LCBuZXcgVlBhdGNoKFZQYXRjaC5JTlNFUlQsIG51bGwsIHJpZ2h0Tm9kZSkpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgd2FsayhsZWZ0Tm9kZSwgcmlnaHROb2RlLCBwYXRjaCwgaW5kZXgpO1xuICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgaWYgKGlzVk5vZGUobGVmdE5vZGUpICYmIGxlZnROb2RlLmNvdW50KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBpbmRleCArPSBsZWZ0Tm9kZS5jb3VudDtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIGlmIChvcmRlcmVkU2V0Lm1vdmVzKSB7XG4gICAgICAgICAgICAgICAgICAgIC8vIFJlb3JkZXIgbm9kZXMgbGFzdFxuICAgICAgICAgICAgICAgICAgICBhcHBseSA9IGFwcGVuZFBhdGNoKGFwcGx5LCBuZXcgVlBhdGNoKFZQYXRjaC5PUkRFUiwgYSwgb3JkZXJlZFNldC5tb3ZlcykpO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHJldHVybiBhcHBseTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZnVuY3Rpb24gY2xlYXJTdGF0ZSh2Tm9kZSwgcGF0Y2gsIGluZGV4KSB7XG4gICAgICAgICAgICAgICAgLy8gVE9ETzogTWFrZSB0aGlzIGEgc2luZ2xlIHdhbGssIG5vdCB0d29cbiAgICAgICAgICAgICAgICB1bmhvb2sodk5vZGUsIHBhdGNoLCBpbmRleCk7XG4gICAgICAgICAgICAgICAgZGVzdHJveVdpZGdldHModk5vZGUsIHBhdGNoLCBpbmRleCk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIC8vIFBhdGNoIHJlY29yZHMgZm9yIGFsbCBkZXN0cm95ZWQgd2lkZ2V0cyBtdXN0IGJlIGFkZGVkIGJlY2F1c2Ugd2UgbmVlZFxuICAgICAgICAgICAgLy8gYSBET00gbm9kZSByZWZlcmVuY2UgZm9yIHRoZSBkZXN0cm95IGZ1bmN0aW9uXG4gICAgICAgICAgICBmdW5jdGlvbiBkZXN0cm95V2lkZ2V0cyh2Tm9kZSwgcGF0Y2gsIGluZGV4KSB7XG4gICAgICAgICAgICAgICAgaWYgKGlzV2lkZ2V0KHZOb2RlKSkge1xuICAgICAgICAgICAgICAgICAgICBpZiAodHlwZW9mIHZOb2RlLmRlc3Ryb3kgPT09IFwiZnVuY3Rpb25cIikge1xuICAgICAgICAgICAgICAgICAgICAgICAgcGF0Y2hbaW5kZXhdID0gYXBwZW5kUGF0Y2gocGF0Y2hbaW5kZXhdLCBuZXcgVlBhdGNoKFZQYXRjaC5SRU1PVkUsIHZOb2RlLCBudWxsKSk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKGlzVk5vZGUodk5vZGUpICYmICh2Tm9kZS5oYXNXaWRnZXRzIHx8IHZOb2RlLmhhc1RodW5rcykpIHtcbiAgICAgICAgICAgICAgICAgICAgdmFyIGNoaWxkcmVuID0gdk5vZGUuY2hpbGRyZW47XG4gICAgICAgICAgICAgICAgICAgIHZhciBsZW4gPSBjaGlsZHJlbi5sZW5ndGg7XG4gICAgICAgICAgICAgICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgbGVuOyBpKyspIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHZhciBjaGlsZCA9IGNoaWxkcmVuW2ldO1xuICAgICAgICAgICAgICAgICAgICAgICAgaW5kZXggKz0gMTtcblxuICAgICAgICAgICAgICAgICAgICAgICAgZGVzdHJveVdpZGdldHMoY2hpbGQsIHBhdGNoLCBpbmRleCk7XG5cbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChpc1ZOb2RlKGNoaWxkKSAmJiBjaGlsZC5jb3VudCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGluZGV4ICs9IGNoaWxkLmNvdW50O1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfSBlbHNlIGlmIChpc1RodW5rKHZOb2RlKSkge1xuICAgICAgICAgICAgICAgICAgICB0aHVua3Modk5vZGUsIG51bGwsIHBhdGNoLCBpbmRleCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAvLyBDcmVhdGUgYSBzdWItcGF0Y2ggZm9yIHRodW5rc1xuICAgICAgICAgICAgZnVuY3Rpb24gdGh1bmtzKGEsIGIsIHBhdGNoLCBpbmRleCkge1xuICAgICAgICAgICAgICAgIHZhciBub2RlcyA9IGhhbmRsZVRodW5rKGEsIGIpO1xuICAgICAgICAgICAgICAgIHZhciB0aHVua1BhdGNoID0gZGlmZihub2Rlcy5hLCBub2Rlcy5iKTtcbiAgICAgICAgICAgICAgICBpZiAoaGFzUGF0Y2hlcyh0aHVua1BhdGNoKSkge1xuICAgICAgICAgICAgICAgICAgICBwYXRjaFtpbmRleF0gPSBuZXcgVlBhdGNoKFZQYXRjaC5USFVOSywgbnVsbCwgdGh1bmtQYXRjaCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBmdW5jdGlvbiBoYXNQYXRjaGVzKHBhdGNoKSB7XG4gICAgICAgICAgICAgICAgZm9yICh2YXIgaW5kZXggaW4gcGF0Y2gpIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKGluZGV4ICE9PSBcImFcIikge1xuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIC8vIEV4ZWN1dGUgaG9va3Mgd2hlbiB0d28gbm9kZXMgYXJlIGlkZW50aWNhbFxuICAgICAgICAgICAgZnVuY3Rpb24gdW5ob29rKHZOb2RlLCBwYXRjaCwgaW5kZXgpIHtcbiAgICAgICAgICAgICAgICBpZiAoaXNWTm9kZSh2Tm9kZSkpIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKHZOb2RlLmhvb2tzKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBwYXRjaFtpbmRleF0gPSBhcHBlbmRQYXRjaChwYXRjaFtpbmRleF0sIG5ldyBWUGF0Y2goVlBhdGNoLlBST1BTLCB2Tm9kZSwgdW5kZWZpbmVkS2V5cyh2Tm9kZS5ob29rcykpKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgIGlmICh2Tm9kZS5kZXNjZW5kYW50SG9va3MgfHwgdk5vZGUuaGFzVGh1bmtzKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICB2YXIgY2hpbGRyZW4gPSB2Tm9kZS5jaGlsZHJlbjtcbiAgICAgICAgICAgICAgICAgICAgICAgIHZhciBsZW4gPSBjaGlsZHJlbi5sZW5ndGg7XG4gICAgICAgICAgICAgICAgICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IGxlbjsgaSsrKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdmFyIGNoaWxkID0gY2hpbGRyZW5baV07XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaW5kZXggKz0gMTtcblxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHVuaG9vayhjaGlsZCwgcGF0Y2gsIGluZGV4KTtcblxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChpc1ZOb2RlKGNoaWxkKSAmJiBjaGlsZC5jb3VudCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpbmRleCArPSBjaGlsZC5jb3VudDtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKGlzVGh1bmsodk5vZGUpKSB7XG4gICAgICAgICAgICAgICAgICAgIHRodW5rcyh2Tm9kZSwgbnVsbCwgcGF0Y2gsIGluZGV4KTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZ1bmN0aW9uIHVuZGVmaW5lZEtleXMob2JqKSB7XG4gICAgICAgICAgICAgICAgdmFyIHJlc3VsdCA9IHt9O1xuXG4gICAgICAgICAgICAgICAgZm9yICh2YXIga2V5IGluIG9iaikge1xuICAgICAgICAgICAgICAgICAgICByZXN1bHRba2V5XSA9IHVuZGVmaW5lZDtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICByZXR1cm4gcmVzdWx0O1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAvLyBMaXN0IGRpZmYsIG5haXZlIGxlZnQgdG8gcmlnaHQgcmVvcmRlcmluZ1xuICAgICAgICAgICAgZnVuY3Rpb24gcmVvcmRlcihhQ2hpbGRyZW4sIGJDaGlsZHJlbikge1xuICAgICAgICAgICAgICAgIC8vIE8oTSkgdGltZSwgTyhNKSBtZW1vcnlcbiAgICAgICAgICAgICAgICB2YXIgYkNoaWxkSW5kZXggPSBrZXlJbmRleChiQ2hpbGRyZW4pO1xuICAgICAgICAgICAgICAgIHZhciBiS2V5cyA9IGJDaGlsZEluZGV4LmtleXM7XG4gICAgICAgICAgICAgICAgdmFyIGJGcmVlID0gYkNoaWxkSW5kZXguZnJlZTtcblxuICAgICAgICAgICAgICAgIGlmIChiRnJlZS5sZW5ndGggPT09IGJDaGlsZHJlbi5sZW5ndGgpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGNoaWxkcmVuOiBiQ2hpbGRyZW4sXG4gICAgICAgICAgICAgICAgICAgICAgICBtb3ZlczogbnVsbFxuICAgICAgICAgICAgICAgICAgICB9O1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIC8vIE8oTikgdGltZSwgTyhOKSBtZW1vcnlcbiAgICAgICAgICAgICAgICB2YXIgYUNoaWxkSW5kZXggPSBrZXlJbmRleChhQ2hpbGRyZW4pO1xuICAgICAgICAgICAgICAgIHZhciBhS2V5cyA9IGFDaGlsZEluZGV4LmtleXM7XG4gICAgICAgICAgICAgICAgdmFyIGFGcmVlID0gYUNoaWxkSW5kZXguZnJlZTtcblxuICAgICAgICAgICAgICAgIGlmIChhRnJlZS5sZW5ndGggPT09IGFDaGlsZHJlbi5sZW5ndGgpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGNoaWxkcmVuOiBiQ2hpbGRyZW4sXG4gICAgICAgICAgICAgICAgICAgICAgICBtb3ZlczogbnVsbFxuICAgICAgICAgICAgICAgICAgICB9O1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIC8vIE8oTUFYKE4sIE0pKSBtZW1vcnlcbiAgICAgICAgICAgICAgICB2YXIgbmV3Q2hpbGRyZW4gPSBbXTtcblxuICAgICAgICAgICAgICAgIHZhciBmcmVlSW5kZXggPSAwO1xuICAgICAgICAgICAgICAgIHZhciBmcmVlQ291bnQgPSBiRnJlZS5sZW5ndGg7XG4gICAgICAgICAgICAgICAgdmFyIGRlbGV0ZWRJdGVtcyA9IDA7XG5cbiAgICAgICAgICAgICAgICAvLyBJdGVyYXRlIHRocm91Z2ggYSBhbmQgbWF0Y2ggYSBub2RlIGluIGJcbiAgICAgICAgICAgICAgICAvLyBPKE4pIHRpbWUsXG4gICAgICAgICAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCBhQ2hpbGRyZW4ubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgICAgICAgICAgdmFyIGFJdGVtID0gYUNoaWxkcmVuW2ldO1xuICAgICAgICAgICAgICAgICAgICB2YXIgaXRlbUluZGV4O1xuXG4gICAgICAgICAgICAgICAgICAgIGlmIChhSXRlbS5rZXkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChiS2V5cy5oYXNPd25Qcm9wZXJ0eShhSXRlbS5rZXkpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gTWF0Y2ggdXAgdGhlIG9sZCBrZXlzXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaXRlbUluZGV4ID0gYktleXNbYUl0ZW0ua2V5XTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBuZXdDaGlsZHJlbi5wdXNoKGJDaGlsZHJlbltpdGVtSW5kZXhdKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gUmVtb3ZlIG9sZCBrZXllZCBpdGVtc1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGl0ZW1JbmRleCA9IGkgLSBkZWxldGVkSXRlbXMrKztcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBuZXdDaGlsZHJlbi5wdXNoKG51bGwpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgLy8gTWF0Y2ggdGhlIGl0ZW0gaW4gYSB3aXRoIHRoZSBuZXh0IGZyZWUgaXRlbSBpbiBiXG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoZnJlZUluZGV4IDwgZnJlZUNvdW50KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaXRlbUluZGV4ID0gYkZyZWVbZnJlZUluZGV4KytdO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIG5ld0NoaWxkcmVuLnB1c2goYkNoaWxkcmVuW2l0ZW1JbmRleF0pO1xuICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBUaGVyZSBhcmUgbm8gZnJlZSBpdGVtcyBpbiBiIHRvIG1hdGNoIHdpdGhcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyB0aGUgZnJlZSBpdGVtcyBpbiBhLCBzbyB0aGUgZXh0cmEgZnJlZSBub2Rlc1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIGFyZSBkZWxldGVkLlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGl0ZW1JbmRleCA9IGkgLSBkZWxldGVkSXRlbXMrKztcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBuZXdDaGlsZHJlbi5wdXNoKG51bGwpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgdmFyIGxhc3RGcmVlSW5kZXggPSBmcmVlSW5kZXggPj0gYkZyZWUubGVuZ3RoID8gYkNoaWxkcmVuLmxlbmd0aCA6IGJGcmVlW2ZyZWVJbmRleF07XG5cbiAgICAgICAgICAgICAgICAvLyBJdGVyYXRlIHRocm91Z2ggYiBhbmQgYXBwZW5kIGFueSBuZXcga2V5c1xuICAgICAgICAgICAgICAgIC8vIE8oTSkgdGltZVxuICAgICAgICAgICAgICAgIGZvciAodmFyIGogPSAwOyBqIDwgYkNoaWxkcmVuLmxlbmd0aDsgaisrKSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciBuZXdJdGVtID0gYkNoaWxkcmVuW2pdO1xuXG4gICAgICAgICAgICAgICAgICAgIGlmIChuZXdJdGVtLmtleSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKCFhS2V5cy5oYXNPd25Qcm9wZXJ0eShuZXdJdGVtLmtleSkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBBZGQgYW55IG5ldyBrZXllZCBpdGVtc1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIFdlIGFyZSBhZGRpbmcgbmV3IGl0ZW1zIHRvIHRoZSBlbmQgYW5kIHRoZW4gc29ydGluZyB0aGVtXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gaW4gcGxhY2UuIEluIGZ1dHVyZSB3ZSBzaG91bGQgaW5zZXJ0IG5ldyBpdGVtcyBpbiBwbGFjZS5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBuZXdDaGlsZHJlbi5wdXNoKG5ld0l0ZW0pO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKGogPj0gbGFzdEZyZWVJbmRleCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgLy8gQWRkIGFueSBsZWZ0b3ZlciBub24ta2V5ZWQgaXRlbXNcbiAgICAgICAgICAgICAgICAgICAgICAgIG5ld0NoaWxkcmVuLnB1c2gobmV3SXRlbSk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICB2YXIgc2ltdWxhdGUgPSBuZXdDaGlsZHJlbi5zbGljZSgpO1xuICAgICAgICAgICAgICAgIHZhciBzaW11bGF0ZUluZGV4ID0gMDtcbiAgICAgICAgICAgICAgICB2YXIgcmVtb3ZlcyA9IFtdO1xuICAgICAgICAgICAgICAgIHZhciBpbnNlcnRzID0gW107XG4gICAgICAgICAgICAgICAgdmFyIHNpbXVsYXRlSXRlbTtcblxuICAgICAgICAgICAgICAgIGZvciAodmFyIGsgPSAwOyBrIDwgYkNoaWxkcmVuLmxlbmd0aDspIHtcbiAgICAgICAgICAgICAgICAgICAgdmFyIHdhbnRlZEl0ZW0gPSBiQ2hpbGRyZW5ba107XG4gICAgICAgICAgICAgICAgICAgIHNpbXVsYXRlSXRlbSA9IHNpbXVsYXRlW3NpbXVsYXRlSW5kZXhdO1xuXG4gICAgICAgICAgICAgICAgICAgIC8vIHJlbW92ZSBpdGVtc1xuICAgICAgICAgICAgICAgICAgICB3aGlsZSAoc2ltdWxhdGVJdGVtID09PSBudWxsICYmIHNpbXVsYXRlLmxlbmd0aCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgcmVtb3Zlcy5wdXNoKHJlbW92ZShzaW11bGF0ZSwgc2ltdWxhdGVJbmRleCwgbnVsbCkpO1xuICAgICAgICAgICAgICAgICAgICAgICAgc2ltdWxhdGVJdGVtID0gc2ltdWxhdGVbc2ltdWxhdGVJbmRleF07XG4gICAgICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgICAgICBpZiAoIXNpbXVsYXRlSXRlbSB8fCBzaW11bGF0ZUl0ZW0ua2V5ICE9PSB3YW50ZWRJdGVtLmtleSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgLy8gaWYgd2UgbmVlZCBhIGtleSBpbiB0aGlzIHBvc2l0aW9uLi4uXG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAod2FudGVkSXRlbS5rZXkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoc2ltdWxhdGVJdGVtICYmIHNpbXVsYXRlSXRlbS5rZXkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gaWYgYW4gaW5zZXJ0IGRvZXNuJ3QgcHV0IHRoaXMga2V5IGluIHBsYWNlLCBpdCBuZWVkcyB0byBtb3ZlXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChiS2V5c1tzaW11bGF0ZUl0ZW0ua2V5XSAhPT0gayArIDEpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlbW92ZXMucHVzaChyZW1vdmUoc2ltdWxhdGUsIHNpbXVsYXRlSW5kZXgsIHNpbXVsYXRlSXRlbS5rZXkpKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNpbXVsYXRlSXRlbSA9IHNpbXVsYXRlW3NpbXVsYXRlSW5kZXhdO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gaWYgdGhlIHJlbW92ZSBkaWRuJ3QgcHV0IHRoZSB3YW50ZWQgaXRlbSBpbiBwbGFjZSwgd2UgbmVlZCB0byBpbnNlcnQgaXRcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmICghc2ltdWxhdGVJdGVtIHx8IHNpbXVsYXRlSXRlbS5rZXkgIT09IHdhbnRlZEl0ZW0ua2V5KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaW5zZXJ0cy5wdXNoKHsga2V5OiB3YW50ZWRJdGVtLmtleSwgdG86IGsgfSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBpdGVtcyBhcmUgbWF0Y2hpbmcsIHNvIHNraXAgYWhlYWRcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzaW11bGF0ZUluZGV4Kys7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaW5zZXJ0cy5wdXNoKHsga2V5OiB3YW50ZWRJdGVtLmtleSwgdG86IGsgfSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpbnNlcnRzLnB1c2goeyBrZXk6IHdhbnRlZEl0ZW0ua2V5LCB0bzogayB9KTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaysrO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgLy8gYSBrZXkgaW4gc2ltdWxhdGUgaGFzIG5vIG1hdGNoaW5nIHdhbnRlZCBrZXksIHJlbW92ZSBpdFxuICAgICAgICAgICAgICAgICAgICAgICAgZWxzZSBpZiAoc2ltdWxhdGVJdGVtICYmIHNpbXVsYXRlSXRlbS5rZXkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmVtb3Zlcy5wdXNoKHJlbW92ZShzaW11bGF0ZSwgc2ltdWxhdGVJbmRleCwgc2ltdWxhdGVJdGVtLmtleSkpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHNpbXVsYXRlSW5kZXgrKztcbiAgICAgICAgICAgICAgICAgICAgICAgIGsrKztcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIC8vIHJlbW92ZSBhbGwgdGhlIHJlbWFpbmluZyBub2RlcyBmcm9tIHNpbXVsYXRlXG4gICAgICAgICAgICAgICAgd2hpbGUgKHNpbXVsYXRlSW5kZXggPCBzaW11bGF0ZS5sZW5ndGgpIHtcbiAgICAgICAgICAgICAgICAgICAgc2ltdWxhdGVJdGVtID0gc2ltdWxhdGVbc2ltdWxhdGVJbmRleF07XG4gICAgICAgICAgICAgICAgICAgIHJlbW92ZXMucHVzaChyZW1vdmUoc2ltdWxhdGUsIHNpbXVsYXRlSW5kZXgsIHNpbXVsYXRlSXRlbSAmJiBzaW11bGF0ZUl0ZW0ua2V5KSk7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgLy8gSWYgdGhlIG9ubHkgbW92ZXMgd2UgaGF2ZSBhcmUgZGVsZXRlcyB0aGVuIHdlIGNhbiBqdXN0XG4gICAgICAgICAgICAgICAgLy8gbGV0IHRoZSBkZWxldGUgcGF0Y2ggcmVtb3ZlIHRoZXNlIGl0ZW1zLlxuICAgICAgICAgICAgICAgIGlmIChyZW1vdmVzLmxlbmd0aCA9PT0gZGVsZXRlZEl0ZW1zICYmICFpbnNlcnRzLmxlbmd0aCkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgICAgICAgICAgICAgY2hpbGRyZW46IG5ld0NoaWxkcmVuLFxuICAgICAgICAgICAgICAgICAgICAgICAgbW92ZXM6IG51bGxcbiAgICAgICAgICAgICAgICAgICAgfTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgICAgICAgICBjaGlsZHJlbjogbmV3Q2hpbGRyZW4sXG4gICAgICAgICAgICAgICAgICAgIG1vdmVzOiB7XG4gICAgICAgICAgICAgICAgICAgICAgICByZW1vdmVzOiByZW1vdmVzLFxuICAgICAgICAgICAgICAgICAgICAgICAgaW5zZXJ0czogaW5zZXJ0c1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZnVuY3Rpb24gcmVtb3ZlKGFyciwgaW5kZXgsIGtleSkge1xuICAgICAgICAgICAgICAgIGFyci5zcGxpY2UoaW5kZXgsIDEpO1xuXG4gICAgICAgICAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgICAgICAgICAgZnJvbTogaW5kZXgsXG4gICAgICAgICAgICAgICAgICAgIGtleToga2V5XG4gICAgICAgICAgICAgICAgfTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZnVuY3Rpb24ga2V5SW5kZXgoY2hpbGRyZW4pIHtcbiAgICAgICAgICAgICAgICB2YXIga2V5cyA9IHt9O1xuICAgICAgICAgICAgICAgIHZhciBmcmVlID0gW107XG4gICAgICAgICAgICAgICAgdmFyIGxlbmd0aCA9IGNoaWxkcmVuLmxlbmd0aDtcblxuICAgICAgICAgICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgbGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgICAgICAgICAgdmFyIGNoaWxkID0gY2hpbGRyZW5baV07XG5cbiAgICAgICAgICAgICAgICAgICAgaWYgKGNoaWxkLmtleSkge1xuICAgICAgICAgICAgICAgICAgICAgICAga2V5c1tjaGlsZC5rZXldID0gaTtcbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGZyZWUucHVzaChpKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHJldHVybiB7XG4gICAgICAgICAgICAgICAgICAgIGtleXM6IGtleXMsIC8vIEEgaGFzaCBvZiBrZXkgbmFtZSB0byBpbmRleFxuICAgICAgICAgICAgICAgICAgICBmcmVlOiBmcmVlIC8vIEFuIGFycmF5IG9mIHVua2V5ZWQgaXRlbSBpbmRpY2VzXG4gICAgICAgICAgICAgICAgfTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZnVuY3Rpb24gYXBwZW5kUGF0Y2goYXBwbHksIHBhdGNoKSB7XG4gICAgICAgICAgICAgICAgaWYgKGFwcGx5KSB7XG4gICAgICAgICAgICAgICAgICAgIGlmIChpc0FycmF5KGFwcGx5KSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgYXBwbHkucHVzaChwYXRjaCk7XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBhcHBseSA9IFthcHBseSwgcGF0Y2hdO1xuICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGFwcGx5O1xuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBwYXRjaDtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH0sIHsgXCIuLi92bm9kZS9oYW5kbGUtdGh1bmtcIjogMjQsIFwiLi4vdm5vZGUvaXMtdGh1bmtcIjogMjUsIFwiLi4vdm5vZGUvaXMtdm5vZGVcIjogMjcsIFwiLi4vdm5vZGUvaXMtdnRleHRcIjogMjgsIFwiLi4vdm5vZGUvaXMtd2lkZ2V0XCI6IDI5LCBcIi4uL3Zub2RlL3ZwYXRjaFwiOiAzMiwgXCIuL2RpZmYtcHJvcHNcIjogMzQsIFwieC1pcy1hcnJheVwiOiAxMiB9XSB9LCB7fSwgWzRdKSg0KTtcbn0pO1xuXG5leHBvcnQgZGVmYXVsdCBWaXJ0dWFsRE9NO1xuLy8jIHNvdXJjZU1hcHBpbmdVUkw9ZGF0YTphcHBsaWNhdGlvbi9qc29uO2Jhc2U2NCxleUoyWlhKemFXOXVJam96TENKemIzVnlZMlZ6SWpwYklteHBZaTkyYVhKMGRXRnNMV1J2YlM1cWN5SmRMQ0p1WVcxbGN5STZXMTBzSW0xaGNIQnBibWR6SWpvaVFVRkJRU3hKUVVGSkxHRkJRV0VzVlVGQlV5eERRVUZVTEVWQlFWazdRVUZETTBJc1YwRkJUeXhIUVVGUUxFTkJSREpDTzBOQlFWb3NRMEZGWml4WlFVRlhPMEZCUTB3c1VVRkJTU3hOUVVGS0xFVkJRVmtzVFVGQldpeEZRVUZ2UWl4UFFVRndRaXhEUVVSTE8wRkJSVXdzVjBGQlR5eFRRVUZWTEVOQlFWUXNRMEZCVnl4RFFVRllMRVZCUVdNc1EwRkJaQ3hGUVVGcFFpeERRVUZxUWl4RlFVRnZRanRCUVVOd1FpeHBRa0ZCVXl4RFFVRlVMRU5CUVZjc1EwRkJXQ3hGUVVGakxFTkJRV1FzUlVGQmFVSTdRVUZEWWl4blFrRkJTU3hEUVVGRExFVkJRVVVzUTBGQlJpeERRVUZFTEVWQlFVODdRVUZEVUN4dlFrRkJTU3hEUVVGRExFVkJRVVVzUTBGQlJpeERRVUZFTEVWQlFVODdRVUZEVUN4M1FrRkJTU3hKUVVGSkxFOUJRVThzVDBGQlVDeEpRVUZyUWl4VlFVRnNRaXhKUVVGblF5eFBRVUZvUXl4RFFVUkVPMEZCUlZBc2QwSkJRVWtzUTBGQlF5eERRVUZFTEVsQlFVMHNRMEZCVGl4RlFVRlRMRTlCUVU4c1JVRkJSU3hEUVVGR0xFVkJRVXNzUTBGQlF5eERRVUZFTEVOQlFWb3NRMEZCWWp0QlFVTkJMSGRDUVVGSkxFTkJRVW9zUlVGQlR5eFBRVUZQTEVWQlFVVXNRMEZCUml4RlFVRkxMRU5CUVVNc1EwRkJSQ3hEUVVGYUxFTkJRVkE3UVVGRFFTeDNRa0ZCU1N4SlFVRkpMRWxCUVVrc1MwRkJTaXhEUVVGVkxIbENRVUY1UWl4RFFVRjZRaXhIUVVFMlFpeEhRVUUzUWl4RFFVRmtMRU5CU2tjN1FVRkxVQ3d3UWtGQlRTeEZRVUZGTEVsQlFVWXNSMEZCVXl4clFrRkJWQ3hGUVVFMlFpeERRVUUzUWl4RFFVeERPMmxDUVVGWU8wRkJUMEVzYjBKQlFVa3NTVUZCU1N4RlFVRkZMRU5CUVVZc1NVRkJUenRCUVVOWUxEWkNRVUZUTEVWQlFWUTdhVUpCUkVrc1EwRlNSRHRCUVZkUUxHdENRVUZGTEVOQlFVWXNSVUZCU3l4RFFVRk1MRVZCUVZFc1NVRkJVaXhEUVVGaExFVkJRVVVzVDBGQlJpeEZRVUZYTEZWQlFWTXNRMEZCVkN4RlFVRlpPMEZCUTJoRExIZENRVUZKTEVsQlFVa3NSVUZCUlN4RFFVRkdMRVZCUVVzc1EwRkJUQ3hGUVVGUkxFTkJRVklzUTBGQlNpeERRVVEwUWp0QlFVVm9ReXd5UWtGQlR5eEZRVUZGTEVsQlFVa3NRMEZCU2l4SFFVRlJMRU5CUVZJc1EwRkJWQ3hEUVVablF6dHBRa0ZCV2l4RlFVZHlRaXhEUVVoSUxFVkJSMDBzUlVGQlJTeFBRVUZHTEVWQlFWY3NRMEZJYWtJc1JVRkhiMElzUTBGSWNFSXNSVUZIZFVJc1EwRklka0lzUlVGSE1FSXNRMEZJTVVJc1JVRllUenRoUVVGWU8wRkJaMEpCTEcxQ1FVRlBMRVZCUVVVc1EwRkJSaXhGUVVGTExFOUJRVXdzUTBGcVFrMDdVMEZCYWtJN1FVRnRRa0VzV1VGQlNTeEpRVUZKTEU5QlFVOHNUMEZCVUN4SlFVRnJRaXhWUVVGc1FpeEpRVUZuUXl4UFFVRm9ReXhEUVhCQ1dUdEJRWEZDY0VJc1lVRkJTeXhKUVVGSkxFbEJRVWtzUTBGQlNpeEZRVUZQTEVsQlFVa3NSVUZCUlN4TlFVRkdMRVZCUVZVc1IwRkJPVUlzUlVGQmJVTXNSVUZCUlN4RlFVRkZMRU5CUVVZc1EwRkJSaXhGUVVGdVF6dEJRVU5CTEdWQlFVOHNRMEZCVUN4RFFYUkNiMEk3UzBGQmNFSXNRMEYxUWtRN1FVRkRTeXhYUVVGSExFTkJRVU1zVlVGQlV5eFBRVUZVTEVWQlFXdENMRTFCUVd4Q0xFVkJRVEJDTEU5QlFURkNMRVZCUVcxRE96dEJRVVV6UkN4blFrRkJTU3huUWtGQlowSXNVVUZCVVN3d1FrRkJVaXhEUVVGb1FpeERRVVoxUkRzN1FVRkpNMFFzYlVKQlFVOHNUMEZCVUN4SFFVRnBRaXhoUVVGcVFpeERRVW95UkR0VFFVRnVReXhGUVUxMFFpeEZRVUZETERSQ1FVRXlRaXhGUVVFelFpeEZRVTV2UWl4RFFVRklMRVZCVFdVc1IwRkJSU3hEUVVGRExGVkJRVk1zVDBGQlZDeEZRVUZwUWl4TlFVRnFRaXhGUVVGM1FpeFBRVUY0UWl4RlFVRm5RenRCUVVOMFJTeG5Ra0ZCU1N4UFFVRlBMRkZCUVZFc2FVSkJRVklzUTBGQlVDeERRVVJyUlRzN1FVRkhkRVVzYlVKQlFVOHNUMEZCVUN4SFFVRnBRaXhKUVVGcVFpeERRVWh6UlR0VFFVRm9ReXhGUVV0d1F5eEZRVUZETEcxQ1FVRnJRaXhGUVVGc1FpeEZRVXhyUXl4RFFVRkdMRVZCUzFRc1IwRkJSU3hEUVVGRExGVkJRVk1zVDBGQlZDeEZRVUZwUWl4TlFVRnFRaXhGUVVGM1FpeFBRVUY0UWl4RlFVRm5RenRCUVVNM1JDeG5Ra0ZCU1N4SlFVRkpMRkZCUVZFc1owTkJRVklzUTBGQlNpeERRVVI1UkRzN1FVRkhOMFFzYlVKQlFVOHNUMEZCVUN4SFFVRnBRaXhEUVVGcVFpeERRVWcyUkR0VFFVRm9ReXhGUVVzelFpeEZRVUZETEd0RFFVRnBReXhGUVVGcVF5eEZRVXg1UWl4RFFVRkdMRVZCUzJVc1IwRkJSU3hEUVVGRExGVkJRVk1zVDBGQlZDeEZRVUZwUWl4TlFVRnFRaXhGUVVGM1FpeFBRVUY0UWl4RlFVRm5RenRCUVVNMVJTeG5Ra0ZCU1N4UFFVRlBMRkZCUVZFc1YwRkJVaXhEUVVGUUxFTkJSSGRGTzBGQlJUVkZMR2RDUVVGSkxGRkJRVkVzVVVGQlVTeFpRVUZTTEVOQlFWSXNRMEZHZDBVN1FVRkhOVVVzWjBKQlFVa3NTVUZCU1N4UlFVRlJMRkZCUVZJc1EwRkJTaXhEUVVoM1JUdEJRVWsxUlN4blFrRkJTU3hUUVVGVExGRkJRVkVzY1VKQlFWSXNRMEZCVkN4RFFVcDNSVHRCUVVzMVJTeG5Ra0ZCU1N4UlFVRlJMRkZCUVZFc2EwSkJRVklzUTBGQlVpeERRVXgzUlR0QlFVMDFSU3huUWtGQlNTeFJRVUZSTEZGQlFWRXNhMEpCUVZJc1EwRkJVaXhEUVU1M1JUczdRVUZSTlVVc2JVSkJRVThzVDBGQlVDeEhRVUZwUWp0QlFVTmlMSE5DUVVGTkxFbEJRVTQ3UVVGRFFTeDFRa0ZCVHl4TFFVRlFPMEZCUTBFc2JVSkJRVWNzUTBGQlNEdEJRVU5CTEhkQ1FVRlJMRTFCUVZJN1FVRkRRU3gxUWtGQlR5eExRVUZRTzBGQlEwRXNkVUpCUVU4c1MwRkJVRHRoUVU1S0xFTkJValJGTzFOQlFXaERMRVZCYVVJeFF5eEZRVUZETEhWQ1FVRnpRaXhEUVVGMFFpeEZRVUYzUWl4aFFVRlpMRU5CUVZvc1JVRkJZeXhWUVVGVExFTkJRVlFzUlVGQlZ5eGpRVUZoTEVWQlFXSXNSVUZCWjBJc2IwSkJRVzFDTEVWQlFXNUNMRVZCUVhOQ0xHOUNRVUZ0UWl4RlFVRnVRaXhGUVdwQ0wwTXNRMEZCUml4RlFXbENlVVVzUjBGQlJTeERRVUZETEZWQlFWTXNUMEZCVkN4RlFVRnBRaXhOUVVGcVFpeEZRVUYzUWl4UFFVRjRRaXhGUVVGblF6czdPenM3T3pzN096czdPenM3T3pzN096czdPenM3T3pzN096czdPenM3UVVGblEzSktMRzFDUVVGUExFOUJRVkFzUjBGQmFVSXNVMEZCVlN4TFFVRlVMRU5CUVdVc1MwRkJaaXhGUVVGelFqczdRVUZGZEVNc2IwSkJRVWtzWTBGQll5eFBRVUZQTEZOQlFWQXNRMEZCYVVJc1MwRkJha0k3YjBKQlEyaENMRzlDUVVGdlFpeFBRVUZQTEVsQlFWQXNRMEZCV1N4RlFVRmFMRVZCUVdkQ0xFTkJRV2hDTEUxQlFYVkNMRXRCUVhaQ096czdRVUZGY0VJc2IwSkJTRVlzUTBGR2MwTTdPMEZCVDNSRExIVkNRVUZQTEZWQlFWTXNSMEZCVkN4RlFVRmpMRk5CUVdRc1JVRkJlVUlzUzBGQmVrSXNSVUZCWjBNN08wRkJSWEpETEhkQ1FVRkpMRTlCUVU4c1UwRkJVQ3hEUVVGcFFpeFJRVUZxUWl4RFFVRXdRaXhKUVVFeFFpeERRVUVyUWl4VFFVRXZRaXhOUVVFNFF5eHBRa0ZCT1VNc1JVRkJhVVU3UVVGRGJrVXNLMEpCUVU4c1dVRkJXU3hKUVVGYUxFTkJRV2xDTEVkQlFXcENMRVZCUVhOQ0xGTkJRWFJDTEVWQlFXbERMRXRCUVdwRExFTkJRVkFzUTBGRWJVVTdjVUpCUVhKRk8wRkJSMEVzZDBKQlFVa3NVMEZCVXl4RlFVRlVPM2RDUVVOR0xGRkJRVkVzUTBGQlF5eFZRVUZWTEZWQlFWWXNSMEZCZFVJc1IwRkJka0lzUjBGQk5rSXNSVUZCTjBJc1EwRkJSQ3hKUVVGeFF5eFZRVUZWTEZOQlFWWXNSMEZCYzBJc1IwRkJkRUlzUjBGQk5FSXNSVUZCTlVJc1EwRkJja01zU1VGQmQwVXNWVUZCVlN4UlFVRldMRWRCUVhGQ0xFZEJRWEpDTEVkQlFUSkNMRVZCUVROQ0xFTkJRWGhGTzBGQlExQXNPRUpCUVZVc1RVRkJWaXhIUVVGdFFpeEhRVUZ1UWl4SFFVRjVRaXhGUVVGNlFpeERRVVJQT3pzN1FVRkhVaXh2UTBGQlowSXNRMEZCYUVJN096dEJRVVZCTEdkRFFVRlpMRWxCUVVrc1RVRkJTaXhEUVVGWExGVkJRVlVzVFVGQlZpeEZRVUZyUWl4UlFVRlJMRWRCUVZJc1EwRkJla003ZDBKQlEwRXNWVUZRUmp0M1FrRlBZeXhMUVZCa08zZENRVTl4UWl4VFFWQnlRanQzUWtGUFowTXNWVUZRYUVNc1EwRk1jVU03UVVGaGNrTXNNa0pCUVU4c1JVRkJVRHRCUVdKeFF5eDNRa0ZqYWtNc1EwRkJReXhwUWtGQlJDeEZRVUZ2UWpzN1FVRkZkRUlzY1VOQlFXRXNTVUZCU1N4TlFVRktMRU5CUVZjc1RVRkJUU3hWUVVGVkxFMUJRVllzUjBGQmJVSXNWVUZCZWtJc1JVRkJjVU1zUzBGQmFFUXNRMEZCWWl4RFFVWnpRanR4UWtGQmVFSTdPenM3T3pzN08wRkJaSEZETEhsQ1FYbENja01zUjBGQlVTeFZRVUZWTEV0QlFWWXNSMEZCYTBJc1EwRkJReXhEUVVGRUxFdEJRVThzUTBGQlVEdEJRVU14UWl3NFFrRkJWU3hEUVVGV08wRkJNVUp4UXl3eVFrRXlRamxDTEZGQlFWRXNWVUZCVlN4SlFVRldMRU5CUVdVc1IwRkJaaXhEUVVGU0xFVkJRVFpDT3p0QlFVVnNReXh2UTBGQldTeE5RVUZOTEV0QlFVNHNSMEZCWXl4TlFVRk5MRU5CUVU0c1JVRkJVeXhOUVVGVUxFTkJSbEU3UVVGSGJFTXNORUpCUVVrc1dVRkJXU3hoUVVGYUxFVkJRVEpDTzBGQlF6ZENMRzFEUVVGUExFbEJRVkFzUTBGQldTeEpRVUZKTEV0QlFVb3NRMEZCVlN4aFFVRldMRVZCUVhsQ0xFMUJRVTBzUzBGQlRpeERRVUZ5UXpzN08wRkJSRFpDTEdkRFFVbDZRaXhEUVVGRExHbENRVUZFTEVsQlFYTkNMRTFCUVUwc1RVRkJUaXhIUVVGbExFTkJRV1lzUlVGQmEwSTdRVUZETVVNc2MwTkJRVTBzUTBGQlRpeEZRVUZUTEU5QlFWUXNRMEZCYVVJc1ZVRkJha0lzUlVGQk5rSXNXVUZCVnp0QlFVTjBReXg1UTBGQlN5eEpRVUZKTEVsQlFVa3NRMEZCU2l4RlFVRlBMRWxCUVVrc1ZVRkJWU3hOUVVGV0xFZEJRVzFDTEVOQlFXNUNMRVZCUVhOQ0xFZEJRVEZETEVWQlFTdERPMEZCUXpkRExEUkRRVUZKTEZWQlFWVXNRMEZCVml4TlFVRnBRaXhMUVVGcVFpeEZRVUYzUWp0QlFVTXhRaXhyUkVGQlRTeERRVUZPTEVsQlFWY3NTMEZCV0N4RFFVUXdRanQ1UTBGQk5VSTdjVU5CUkVZN2FVTkJSREpDTEVOQlFUZENMRU5CUkRCRE96WkNRVUUxUXp0QlFWTkJMR2REUVVGSkxFMUJRVTBzVFVGQlRpeEhRVUZsTEVOQlFXWXNTVUZCYjBJc1RVRkJUU3hMUVVGT0xFZEJRV01zU1VGQlNTeE5RVUZLTEVWQlFWazdRVUZEYUVRc2MwTkJRVTBzVTBGQlRpeERRVUZuUWl4SlFVRm9RaXhEUVVGeFFpeExRVUZ5UWl4RFFVRXlRaXhOUVVFelFpeEZRVUZ0UXl4TlFVRk5MRXRCUVU0c1EwRkJXU3hEUVVGYUxFTkJRVzVETEVWQlJHZEVPelpDUVVGc1JEdEJRVWRCTEhsRFFVRmhMRTFCUVUwc1EwRkJUaXhGUVVGVExFMUJRVlFzUTBGb1FtZENPMEZCYVVJM1FpdzBRMEZCWjBJc1UwRkJhRUlzUTBGcVFqWkNPMEZCYTBJM1FpeG5RMEZCU1N4UFFVRlBMRTFCUVZBc1NVRkJhVUlzUzBGQmFrSXNSVUZCZDBJN1FVRkRNVUlzYzBOQlJEQkNPelpDUVVFMVFqdDVRa0ZzUWtZN1FVRnpRa0VzTkVKQlFVa3NWVUZCVlN4VFFVRldMRXRCUVhkQ0xFMUJRVTBzUzBGQlRpeEZRVUZoTzBGQlEzWkRMSE5EUVVGVkxGTkJRVlk3UVVGRWRVTXNlVUpCUVhwRE8zRkNRWHBDUmp0QlFUWkNRU3gzUWtGQlNTeHJRa0ZCYTBJc1NVRkJTU3hOUVVGS0xFVkJRVms3UVVGRGFFTXNORUpCUVVrc1kwRkJZeXhEUVVGRExGVkJRVlVzU1VGQlZpeERRVUZsTEVWQlFXWXNRMEZCUkN4RlFVRnhRanRCUVVOeVF5eHRRMEZCVHl4SlFVRlFMRU5CUVZrc1JVRkJXaXhGUVVSeFF6dDVRa0ZCZGtNN2NVSkJSRVlzVFVGSlR6dEJRVU5NTEN0Q1FVRlBMRWxCUVZBc1EwRkJXU3hKUVVGSkxFdEJRVW9zUTBGQlZTeGhRVUZXTEVOQlFWb3NSVUZFU3p0eFFrRktVRHRCUVU5QkxESkNRVUZQTEU5QlFVOHNUVUZCVUN4SFFVRm5RaXhMUVVGb1FpeEhRVUYzUWl4UFFVRlBMRXRCUVZBc1EwRkJZU3hEUVVGaUxFVkJRV2RDTEV0QlFXaENMRU5CUVhoQ0xFZEJRV2xFTEUxQlFXcEVMRU5CTDBRNFFqdHBRa0ZCYUVNc1EwRlFLMEk3TzBGQmVVVjBReXgxUWtGQlR5eEpRVUZRTEVOQmVrVnpRenRoUVVGMFFpeEZRVUZzUWl4RFFXaERjVW83VTBGQmFFTXNSVUUwUjI1SUxFVkJOVWRyU0N4RFFVRkdMRVZCTkVjMVJ5eEhRVUZGTEVOQlFVTXNWVUZCVXl4UFFVRlVMRVZCUVdsQ0xFMUJRV3BDTEVWQlFYZENMRTlCUVhoQ0xFVkJRV2RETEVWQlFXaERMRVZCUlZBc1JVRkdUU3hEUVVGR0xFVkJSVUVzUjBGQlJTeERRVUZETEZWQlFWTXNUMEZCVkN4RlFVRnBRaXhOUVVGcVFpeEZRVUYzUWl4UFFVRjRRaXhGUVVGblF6dEJRVU42UXl4NVFrRkVlVU03TzBGQlIzcERMR2RDUVVGSkxIVkNRVUYxUWl4UlFVRlJMSGRDUVVGU0xFTkJRWFpDTEVOQlNIRkRPenRCUVV0NlF5eG5Ra0ZCU1N4aFFVRmhMRWRCUVdJc1EwRk1jVU03UVVGTmVrTXNhVU5CUVhGQ0xGVkJRWEpDTEVWQlFXbERMRlZCUVdwRExFVkJUbmxET3p0QlFWRjZReXhuUWtGQlNTeFZRVUZWTEc5Q1FVRnZRaXhWUVVGd1FpeERRVkl5UWpzN1FVRlZla01zYlVKQlFVOHNUMEZCVUN4SFFVRnBRaXhQUVVGcVFpeERRVlo1UXpzN1FVRlpla01zY1VKQlFWTXNUMEZCVkN4RFFVRnBRaXhKUVVGcVFpeEZRVUYxUWp0QlFVTnVRaXh2UWtGQlNTeFBRVUZQTEV0QlFVc3NUMEZCVEN4RFFVRlFMRU5CUkdVN08wRkJSMjVDTEc5Q1FVRkpMRU5CUVVNc1NVRkJSQ3hGUVVGUE8wRkJRMUFzTWtKQlFVOHNTMEZCU3l4UFFVRk1MRWxCUVdkQ0xFVkJRV2hDTEVOQlJFRTdhVUpCUVZnN08wRkJTVUVzZFVKQlFVOHNTVUZCVUN4RFFWQnRRanRoUVVGMlFqdFRRVnBUTEVWQmMwSlFMRVZCUVVNc01FSkJRWGxDTEVOQlFYcENMRVZCZEVKTExFTkJRVVlzUlVGelFqQkNMRWRCUVVVc1EwRkJReXhWUVVGVExFOUJRVlFzUlVGQmFVSXNUVUZCYWtJc1JVRkJkMElzVDBGQmVFSXNSVUZCWjBNN1FVRkRia1VzWVVGQlF5eFZRVUZWTEUxQlFWWXNSVUZCYVVJN1FVRkRiRUk3T3pzN1FVRkVhMElzYjBKQlMyUXNUMEZCVHl4UFFVRlBMRTFCUVZBc1MwRkJhMElzVjBGQmJFSXNSMEZEVUN4TlFVUlBMRWRCUTBVc1QwRkJUeXhOUVVGUUxFdEJRV3RDTEZkQlFXeENMRWRCUTFRc1RVRkVVeXhIUVVOQkxFVkJSRUVzUTBGT1N6czdRVUZUYkVJc2RVSkJRVThzVDBGQlVDeEhRVUZwUWl4VlFVRnFRaXhEUVZSclFqczdRVUZYYkVJc2VVSkJRVk1zVlVGQlZDeERRVUZ2UWl4SFFVRndRaXhGUVVGNVFpeExRVUY2UWl4RlFVRm5RenRCUVVNMVFpeDNRa0ZCU1N4UFFVRlBMRWxCUVZBc1JVRkJZVHRCUVVOaUxDdENRVUZQTEV0QlFVc3NSMEZCVEN4RFFVRlFMRU5CUkdFN2NVSkJRV3BDT3p0QlFVbEJMSGxDUVVGTExFZEJRVXdzU1VGQldTeExRVUZhTEVOQlREUkNPenRCUVU4MVFpd3lRa0ZCVHl4TFFVRlFMRU5CVURSQ08ybENRVUZvUXp0aFFWaERMRU5CUVVRc1EwRnhRa2NzU1VGeVFrZ3NRMEZ4UWxFc1NVRnlRbElzUlVGeFFtRXNUMEZCVHl4TlFVRlFMRXRCUVd0Q0xGZEJRV3hDTEVkQlFXZERMRTFCUVdoRExFZEJRWGxETEU5QlFVOHNTVUZCVUN4TFFVRm5RaXhYUVVGb1FpeEhRVUU0UWl4SlFVRTVRaXhIUVVGeFF5eFBRVUZQTEUxQlFWQXNTMEZCYTBJc1YwRkJiRUlzUjBGQlowTXNUVUZCYUVNc1IwRkJlVU1zUlVGQmVrTXNRMEZ5UWpOR0xFTkJSRzFGTzFOQlFXaERMRVZCZFVKcVF5eEZRWFpDWjBNc1EwRkJSaXhGUVhWQ01VSXNSMEZCUlN4RFFVRkRMRlZCUVZNc1QwRkJWQ3hGUVVGcFFpeE5RVUZxUWl4RlFVRjNRaXhQUVVGNFFpeEZRVUZuUXp0QlFVTjZReXg1UWtGRWVVTTdPMEZCUjNwRExHZENRVUZKTEdGQlFXRXNVVUZCVVN4WlFVRlNMRU5CUVdJc1EwRkljVU03TzBGQlMzcERMRzFDUVVGUExFOUJRVkFzUjBGQmFVSXNWVUZCYWtJc1EwRk1lVU03TzBGQlQzcERMSEZDUVVGVExGVkJRVlFzUTBGQmIwSXNWVUZCY0VJc1JVRkJaME1zVDBGQmFFTXNSVUZCZVVNc1dVRkJla01zUlVGQmRVUTdRVUZEYmtRc2IwSkJRVWtzVFVGQlRTdzRRa0ZCT0VJc1ZVRkJPVUlzUTBGRWVVTTdRVUZGYmtRc2IwSkJRVWtzWVVGQllTeE5RVUZOTEc5Q1FVRk9MRU5CUm10RE96dEJRVWx1UkN4dlFrRkJTU3hsUVVGbExGZEJRVmNzVlVGQldDeEZRVUYxUWl4UFFVRjJRaXhEUVVGbUxFTkJTaXRET3p0QlFVMXVSQ3h2UWtGQlNTeHBRa0ZCYVVJc1QwRkJha0lzUlVGQk1FSTdRVUZETVVJc01FSkJRVTBzU1VGQlNTeExRVUZLTEVOQlFWVXNLMEpCUTFvc1ZVRkVXU3hIUVVORExFdEJSRVFzUjBGRldpd3lRa0ZHV1N4SFFVVnJRaXhaUVVac1FpeEhRVWRhTEdWQlNGa3NSMEZKV2l4M1EwRktXU3hIUVVrclFpeFBRVW92UWl4RFFVRm9RaXhEUVVRd1FqdHBRa0ZCT1VJN08wRkJVVUVzZFVKQlFVOHNWMEZCVnl4SFFVRllMRVZCUVdkQ0xGbEJRV2hDTEVOQlFWQXNRMEZrYlVRN1lVRkJka1E3VTBGUVV5eEZRWGRDVUN4RlFVRkRMR05CUVdFc1EwRkJZaXhGUVhoQ1N5eERRVUZHTEVWQmQwSmpMRWxCUVVjc1EwRkJReXhWUVVGVExFOUJRVlFzUlVGQmFVSXNUVUZCYWtJc1JVRkJkMElzVDBGQmVFSXNSVUZCWjBNN1FVRkRlRVFzWVVGQlF5eFZRVUZWTEUxQlFWWXNSVUZCYVVJN1FVRkRiRUlzYjBKQlFVa3NWMEZCVnl4UFFVRlBMRTFCUVZBc1MwRkJhMElzVjBGQmJFSXNSMEZCWjBNc1RVRkJhRU1zUjBGRFdDeFBRVUZQTEUxQlFWQXNTMEZCYTBJc1YwRkJiRUlzUjBGQlowTXNUVUZCYUVNc1IwRkJlVU1zUlVGQmVrTXNRMEZHWXp0QlFVZHNRaXh2UWtGQlNTeFRRVUZUTEZGQlFWRXNZMEZCVWl4RFFVRlVMRU5CU0dNN08wRkJTMnhDTEc5Q1FVRkpMRTlCUVU4c1VVRkJVQ3hMUVVGdlFpeFhRVUZ3UWl4RlFVRnBRenRCUVVOcVF5d3lRa0ZCVHl4UFFVRlFMRWRCUVdsQ0xGRkJRV3BDTEVOQlJHbERPMmxDUVVGeVF5eE5RVVZQTzBGQlEwZ3NkMEpCUVVrc1VVRkJVU3hUUVVGVExESkNRVUZVTEVOQlFWSXNRMEZFUkRzN1FVRkhTQ3gzUWtGQlNTeERRVUZETEV0QlFVUXNSVUZCVVR0QlFVTlNMR2REUVVGUkxGTkJRVk1zTWtKQlFWUXNTVUZCZDBNc1RVRkJlRU1zUTBGRVFUdHhRa0ZCV2pzN1FVRkpRU3d5UWtGQlR5eFBRVUZRTEVkQlFXbENMRXRCUVdwQ0xFTkJVRWM3YVVKQlJsQTdZVUZNUXl4RFFVRkVMRU5CYVVKSExFbEJha0pJTEVOQmFVSlJMRWxCYWtKU0xFVkJhVUpoTEU5QlFVOHNUVUZCVUN4TFFVRnJRaXhYUVVGc1FpeEhRVUZuUXl4TlFVRm9ReXhIUVVGNVF5eFBRVUZQTEVsQlFWQXNTMEZCWjBJc1YwRkJhRUlzUjBGQk9FSXNTVUZCT1VJc1IwRkJjVU1zVDBGQlR5eE5RVUZRTEV0QlFXdENMRmRCUVd4Q0xFZEJRV2RETEUxQlFXaERMRWRCUVhsRExFVkJRWHBETEVOQmFrSXpSaXhEUVVSM1JEdFRRVUZvUXl4RlFXMUNkRUlzUlVGQlF5eG5Ra0ZCWlN4RFFVRm1MRVZCYmtKdlFpeERRVUZJTEVWQmJVSkZMRWxCUVVjc1EwRkJReXhWUVVGVExFOUJRVlFzUlVGQmFVSXNUVUZCYWtJc1JVRkJkMElzVDBGQmVFSXNSVUZCWjBNN1FVRkRNVVFzZVVKQlJEQkVPenRCUVVjeFJDeHRRa0ZCVHl4UFFVRlFMRWRCUVdsQ0xGTkJRVk1zVVVGQlZDeERRVUZyUWl4RFFVRnNRaXhGUVVGeFFqdEJRVU55UXl4MVFrRkJUeXhQUVVGUExFTkJRVkFzUzBGQllTeFJRVUZpTEVsQlFYbENMRTFCUVUwc1NVRkJUaXhEUVVSTE8yRkJRWEpDTEVOQlNIbERPMU5CUVdoRExFVkJUM2hDTEVWQlVIVkNMRU5CUVVnc1JVRlBhRUlzU1VGQlJ5eERRVUZETEZWQlFWTXNUMEZCVkN4RlFVRnBRaXhOUVVGcVFpeEZRVUYzUWl4UFFVRjRRaXhGUVVGblF6dEJRVU14UXl4blFrRkJTU3huUWtGQlowSXNUVUZCVFN4UFFVRk9MRU5CUkhOQ08wRkJSVEZETEdkQ1FVRkpMRmRCUVZjc1QwRkJUeXhUUVVGUUxFTkJRV2xDTEZGQlFXcENMRU5CUmpKQ096dEJRVWt4UXl4dFFrRkJUeXhQUVVGUUxFZEJRV2xDTEdsQ1FVRnBRaXhQUVVGcVFpeERRVXA1UWpzN1FVRk5NVU1zY1VKQlFWTXNUMEZCVkN4RFFVRnBRaXhIUVVGcVFpeEZRVUZ6UWp0QlFVTnNRaXgxUWtGQlR5eFRRVUZUTEVsQlFWUXNRMEZCWXl4SFFVRmtMRTFCUVhWQ0xHZENRVUYyUWl4RFFVUlhPMkZCUVhSQ08xTkJUbFVzUlVGVlVpeEZRVlpQTEVOQlFVZ3NSVUZWUVN4SlFVRkhMRU5CUVVNc1ZVRkJVeXhQUVVGVUxFVkJRV2xDTEUxQlFXcENMRVZCUVhkQ0xFOUJRWGhDTEVWQlFXZERPMEZCUXpGRExHZENRVUZKTEZGQlFWRXNVVUZCVVN4cFFrRkJVaXhEUVVGU0xFTkJSSE5ET3p0QlFVY3hReXh0UWtGQlR5eFBRVUZRTEVkQlFXbENMRXRCUVdwQ0xFTkJTREJETzFOQlFXaERMRVZCUzFJc1JVRkJReXh0UWtGQmEwSXNSVUZCYkVJc1JVRk1UU3hEUVVGSUxFVkJTMjlDTEVsQlFVY3NRMEZCUXl4VlFVRlRMRTlCUVZRc1JVRkJhVUlzVFVGQmFrSXNSVUZCZDBJc1QwRkJlRUlzUlVGQlowTTdRVUZET1VRc1owSkJRVWtzVjBGQlZ5eFJRVUZSTEZkQlFWSXNRMEZCV0N4RFFVUXdSRHRCUVVVNVJDeG5Ra0ZCU1N4VFFVRlRMRkZCUVZFc2MwSkJRVklzUTBGQlZDeERRVVl3UkRzN1FVRkpPVVFzYlVKQlFVOHNUMEZCVUN4SFFVRnBRaXhsUVVGcVFpeERRVW80UkRzN1FVRk5PVVFzY1VKQlFWTXNaVUZCVkN4RFFVRjVRaXhKUVVGNlFpeEZRVUVyUWl4TFFVRXZRaXhGUVVGelF5eFJRVUYwUXl4RlFVRm5SRHRCUVVNMVF5eHhRa0ZCU3l4SlFVRkpMRkZCUVVvc1NVRkJaMElzUzBGQmNrSXNSVUZCTkVJN1FVRkRlRUlzZDBKQlFVa3NXVUZCV1N4TlFVRk5MRkZCUVU0c1EwRkJXaXhEUVVSdlFqczdRVUZIZUVJc2QwSkJRVWtzWTBGQll5eFRRVUZrTEVWQlFYbENPMEZCUTNwQ0xIVkRRVUZsTEVsQlFXWXNSVUZCY1VJc1VVRkJja0lzUlVGQkswSXNVMEZCTDBJc1JVRkJNRU1zVVVGQk1VTXNSVUZFZVVJN2NVSkJRVGRDTEUxQlJVOHNTVUZCU1N4UFFVRlBMRk5CUVZBc1EwRkJTaXhGUVVGMVFqdEJRVU14UWl4MVEwRkJaU3hKUVVGbUxFVkJRWEZDTEZGQlFYSkNMRVZCUVN0Q0xGTkJRUzlDTEVWQlFUQkRMRkZCUVRGRExFVkJSREJDTzBGQlJURkNMRFJDUVVGSkxGVkJRVlVzU1VGQlZpeEZRVUZuUWp0QlFVTm9RaXh6UTBGQlZTeEpRVUZXTEVOQlFXVXNTVUZCWml4RlFVTkpMRkZCUkVvc1JVRkZTU3hYUVVGWExGTkJRVk1zVVVGQlZDeERRVUZZTEVkQlFXZERMRk5CUVdoRExFTkJSa29zUTBGRVowSTdlVUpCUVhCQ08zRkNRVVpITEUxQlQwRTdRVUZEU0N3MFFrRkJTU3hUUVVGVExGTkJRVlFzUTBGQlNpeEZRVUY1UWp0QlFVTnlRaXgzUTBGQldTeEpRVUZhTEVWQlFXdENMRXRCUVd4Q0xFVkJRWGxDTEZGQlFYcENMRVZCUVcxRExGRkJRVzVETEVWQlFUWkRMRk5CUVRkRExFVkJSSEZDTzNsQ1FVRjZRaXhOUVVWUE8wRkJRMGdzYVVOQlFVc3NVVUZCVEN4SlFVRnBRaXhUUVVGcVFpeERRVVJITzNsQ1FVWlFPM0ZDUVZKSE8ybENRVXhZTzJGQlJFbzdPMEZCZFVKQkxIRkNRVUZUTEdOQlFWUXNRMEZCZDBJc1NVRkJlRUlzUlVGQk9FSXNVVUZCT1VJc1JVRkJkME1zVTBGQmVFTXNSVUZCYlVRc1VVRkJia1FzUlVGQk5rUTdRVUZEZWtRc2IwSkJRVWtzVVVGQlNpeEZRVUZqTzBGQlExWXNkMEpCUVVrc1owSkJRV2RDTEZOQlFWTXNVVUZCVkN4RFFVRm9RaXhEUVVSTk96dEJRVWRXTEhkQ1FVRkpMRU5CUVVNc1QwRkJUeXhoUVVGUUxFTkJRVVFzUlVGQmQwSTdRVUZEZUVJc05FSkJRVWtzWVVGQllTeFpRVUZpTEVWQlFUSkNPMEZCUXpOQ0xHbERRVUZMTEVsQlFVa3NVVUZCU2l4SlFVRm5RaXhoUVVGeVFpeEZRVUZ2UXp0QlFVTm9ReXh4UTBGQlN5eGxRVUZNTEVOQlFYRkNMRkZCUVhKQ0xFVkJSR2RET3paQ1FVRndRenQ1UWtGRVNpeE5RVWxQTEVsQlFVa3NZVUZCWVN4UFFVRmlMRVZCUVhOQ08wRkJRemRDTEdsRFFVRkxMRWxCUVVrc1EwRkJTaXhKUVVGVExHRkJRV1FzUlVGQk5rSTdRVUZEZWtJc2NVTkJRVXNzUzBGQlRDeERRVUZYTEVOQlFWZ3NTVUZCWjBJc1JVRkJhRUlzUTBGRWVVSTdOa0pCUVRkQ08zbENRVVJITEUxQlNVRXNTVUZCU1N4UFFVRlBMR0ZCUVZBc1MwRkJlVUlzVVVGQmVrSXNSVUZCYlVNN1FVRkRNVU1zYVVOQlFVc3NVVUZCVEN4SlFVRnBRaXhGUVVGcVFpeERRVVF3UXp0NVFrRkJka01zVFVGRlFUdEJRVU5JTEdsRFFVRkxMRkZCUVV3c1NVRkJhVUlzU1VGQmFrSXNRMEZFUnp0NVFrRkdRVHR4UWtGVVdDeE5RV05QTEVsQlFVa3NZMEZCWXl4TlFVRmtMRVZCUVhOQ08wRkJRemRDTEhORFFVRmpMRTFCUVdRc1EwRkJjVUlzU1VGQmNrSXNSVUZCTWtJc1VVRkJNMElzUlVGQmNVTXNVMEZCY2tNc1JVRkVOa0k3Y1VKQlFURkNPMmxDUVdwQ1dEdGhRVVJLT3p0QlFYZENRU3h4UWtGQlV5eFhRVUZVTEVOQlFYRkNMRWxCUVhKQ0xFVkJRVEpDTEV0QlFUTkNMRVZCUVd0RExGRkJRV3hETEVWQlFUUkRMRkZCUVRWRExFVkJRWE5FTEZOQlFYUkVMRVZCUVdsRk8wRkJRemRFTEc5Q1FVRkpMR2RDUVVGblFpeFhRVUZYTEZOQlFWTXNVVUZCVkN4RFFVRllMRWRCUVdkRExGTkJRV2hET3pzN1FVRkVlVU1zYjBKQlNYcEVMR0ZCUVdFc1dVRkJZaXhGUVVFeVFqdEJRVU16UWl4NVFrRkJTeXhKUVVGSkxGRkJRVW9zU1VGQlowSXNVMEZCY2tJc1JVRkJaME03UVVGRE5VSXNORUpCUVVrc1dVRkJXU3hWUVVGVkxGRkJRVllzUTBGQldpeERRVVIzUWpzN1FVRkhOVUlzTkVKQlFVa3NZMEZCWXl4VFFVRmtMRVZCUVhsQ08wRkJRM3BDTEdsRFFVRkxMR1ZCUVV3c1EwRkJjVUlzVVVGQmNrSXNSVUZFZVVJN2VVSkJRVGRDTEUxQlJVODdRVUZEU0N4cFEwRkJTeXhaUVVGTUxFTkJRV3RDTEZGQlFXeENMRVZCUVRSQ0xGTkJRVFZDTEVWQlJFYzdlVUpCUmxBN2NVSkJTRW83TzBGQlZVRXNNa0pCV0RKQ08ybENRVUV2UWpzN1FVRmpRU3h2UWtGQlJ5eHBRa0ZCYVVJc1UwRkJVeXhoUVVGVUxFTkJRV3BDTEVsQlEwTXNZVUZCWVN4aFFVRmlMRTFCUVdkRExHRkJRV0VzVTBGQllpeERRVUZvUXl4RlFVRjVSRHRCUVVONlJDeDVRa0ZCU3l4UlFVRk1MRWxCUVdsQ0xGTkJRV3BDTEVOQlJIbEVPMEZCUlhwRUxESkNRVVo1UkR0cFFrRkVOMFE3TzBGQlRVRXNiMEpCUVVrc1EwRkJReXhUUVVGVExFdEJRVXNzVVVGQlRDeERRVUZVTEVOQlFVUXNSVUZCTWtJN1FVRkRNMElzZVVKQlFVc3NVVUZCVEN4SlFVRnBRaXhGUVVGcVFpeERRVVF5UWp0cFFrRkJMMEk3TzBGQlNVRXNiMEpCUVVrc1YwRkJWeXhoUVVGaExFOUJRV0lzUjBGQmRVSXNSVUZCZGtJc1IwRkJORUlzVTBGQk5VSXNRMEUxUWpoRE96dEJRVGhDTjBRc2NVSkJRVXNzU1VGQlNTeERRVUZLTEVsQlFWTXNVMEZCWkN4RlFVRjVRanRCUVVOeVFpeDNRa0ZCU1N4UlFVRlJMRlZCUVZVc1EwRkJWaXhEUVVGU0xFTkJSR2xDTzBGQlJYSkNMSGxDUVVGTExGRkJRVXdzUlVGQlpTeERRVUZtTEVsQlFXOUNMRXRCUVVNc1MwRkJWU3hUUVVGV0xFZEJRWFZDTEZGQlFYaENMRWRCUVcxRExFdEJRVzVETEVOQlJrTTdhVUpCUVhwQ08yRkJPVUpLT3p0QlFXOURRU3h4UWtGQlV5eFpRVUZVTEVOQlFYTkNMRXRCUVhSQ0xFVkJRVFpDTzBGQlEzcENMRzlDUVVGSkxFOUJRVThzWTBGQlVDeEZRVUYxUWp0QlFVTjJRaXd5UWtGQlR5eFBRVUZQTEdOQlFWQXNRMEZCYzBJc1MwRkJkRUlzUTBGQlVDeERRVVIxUWp0cFFrRkJNMElzVFVGRlR5eEpRVUZKTEUxQlFVMHNVMEZCVGl4RlFVRnBRanRCUVVONFFpd3lRa0ZCVHl4TlFVRk5MRk5CUVU0c1EwRkVhVUk3YVVKQlFYSkNMRTFCUlVFc1NVRkJTU3hOUVVGTkxGZEJRVTRzUlVGQmJVSTdRVUZETVVJc01rSkJRVThzVFVGQlRTeFhRVUZPTEVOQlFXdENMRk5CUVd4Q0xFTkJSRzFDTzJsQ1FVRjJRanRoUVV4WU8xTkJla1k0UWl4RlFXMUhOVUlzUlVGQlF5eDNRa0ZCZFVJc1JVRkJka0lzUlVGQk1FSXNZVUZCV1N4RlFVRmFMRVZCYmtkQkxFTkJRVWdzUlVGdFIyOUNMRWxCUVVjc1EwRkJReXhWUVVGVExFOUJRVlFzUlVGQmFVSXNUVUZCYWtJc1JVRkJkMElzVDBGQmVFSXNSVUZCWjBNN1FVRkRiRVlzWjBKQlFVa3NWMEZCVnl4UlFVRlJMR2xDUVVGU0xFTkJRVmdzUTBGRU9FVTdPMEZCUjJ4R0xHZENRVUZKTEd0Q1FVRnJRaXhSUVVGUkxHOUNRVUZTTEVOQlFXeENMRU5CU0RoRk96dEJRVXRzUml4blFrRkJTU3hWUVVGVkxGRkJRVkVzYzBKQlFWSXNRMEZCVml4RFFVdzRSVHRCUVUxc1JpeG5Ra0ZCU1N4VlFVRlZMRkZCUVZFc2MwSkJRVklzUTBGQlZpeERRVTQ0UlR0QlFVOXNSaXhuUWtGQlNTeFhRVUZYTEZGQlFWRXNkVUpCUVZJc1EwRkJXQ3hEUVZBNFJUdEJRVkZzUml4blFrRkJTU3hqUVVGakxGRkJRVkVzTUVKQlFWSXNRMEZCWkN4RFFWSTRSVHM3UVVGVmJFWXNiVUpCUVU4c1QwRkJVQ3hIUVVGcFFpeGhRVUZxUWl4RFFWWnJSanM3UVVGWmJFWXNjVUpCUVZNc1lVRkJWQ3hEUVVGMVFpeExRVUYyUWl4RlFVRTRRaXhKUVVFNVFpeEZRVUZ2UXp0QlFVTm9ReXh2UWtGQlNTeE5RVUZOTEU5QlFVOHNTMEZCU3l4UlFVRk1MRWxCUVdsQ0xGRkJRV3BDTEVkQlFUUkNMRkZCUVc1RExFTkJSSE5DTzBGQlJXaERMRzlDUVVGSkxFOUJRVThzVDBGQlR5eExRVUZMTEVsQlFVd3NSMEZCV1N4SlFVRnVRaXhEUVVaeFFqczdRVUZKYUVNc2QwSkJRVkVzV1VGQldTeExRVUZhTEVWQlFXMUNMRU5CUVc1Q0xFTkJTbmRDT3p0QlFVMW9ReXh2UWtGQlNTeFRRVUZUTEV0QlFWUXNRMEZCU2l4RlFVRnhRanRCUVVOcVFpd3lRa0ZCVHl4TlFVRk5MRWxCUVU0c1JVRkJVQ3hEUVVScFFqdHBRa0ZCY2tJc1RVRkZUeXhKUVVGSkxGRkJRVkVzUzBGQlVpeERRVUZLTEVWQlFXOUNPMEZCUTNaQ0xESkNRVUZQTEVsQlFVa3NZMEZCU2l4RFFVRnRRaXhOUVVGTkxFbEJRVTRzUTBGQk1VSXNRMEZFZFVJN2FVSkJRWEJDTEUxQlJVRXNTVUZCU1N4RFFVRkRMRkZCUVZFc1MwRkJVaXhEUVVGRUxFVkJRV2xDTzBGQlEzaENMSGRDUVVGSkxFbEJRVW9zUlVGQlZUdEJRVU5PTERaQ1FVRkxMSE5EUVVGTUxFVkJRVFpETEV0QlFUZERMRVZCUkUwN2NVSkJRVlk3UVVGSFFTd3lRa0ZCVHl4SlFVRlFMRU5CU25kQ08ybENRVUZ5UWpzN1FVRlBVQ3h2UWtGQlNTeFBRVUZQTEV0QlFVTXNRMEZCVFN4VFFVRk9MRXRCUVc5Q0xFbEJRWEJDTEVkQlExSXNTVUZCU1N4aFFVRktMRU5CUVd0Q0xFMUJRVTBzVDBGQlRpeERRVVJZTEVkQlJWQXNTVUZCU1N4bFFVRktMRU5CUVc5Q0xFMUJRVTBzVTBGQlRpeEZRVUZwUWl4TlFVRk5MRTlCUVU0c1EwRkdPVUlzUTBGcVFuRkNPenRCUVhGQ2FFTXNiMEpCUVVrc1VVRkJVU3hOUVVGTkxGVkJRVTRzUTBGeVFtOUNPMEZCYzBKb1F5eG5RMEZCWjBJc1NVRkJhRUlzUlVGQmMwSXNTMEZCZEVJc1JVRjBRbWRET3p0QlFYZENhRU1zYjBKQlFVa3NWMEZCVnl4TlFVRk5MRkZCUVU0c1EwRjRRbWxDT3p0QlFUQkNhRU1zY1VKQlFVc3NTVUZCU1N4SlFVRkpMRU5CUVVvc1JVRkJUeXhKUVVGSkxGTkJRVk1zVFVGQlZDeEZRVUZwUWl4SFFVRnlReXhGUVVFd1F6dEJRVU4wUXl4M1FrRkJTU3haUVVGWkxHTkJRV01zVTBGQlV5eERRVUZVTEVOQlFXUXNSVUZCTWtJc1NVRkJNMElzUTBGQldpeERRVVJyUXp0QlFVVjBReXgzUWtGQlNTeFRRVUZLTEVWQlFXVTdRVUZEV0N3MlFrRkJTeXhYUVVGTUxFTkJRV2xDTEZOQlFXcENMRVZCUkZjN2NVSkJRV1k3YVVKQlJrbzdPMEZCVDBFc2RVSkJRVThzU1VGQlVDeERRV3BEWjBNN1lVRkJjRU03VTBGYWEwUXNSVUZuUkdoRUxFVkJRVU1zTkVKQlFUSkNMRVZCUVROQ0xFVkJRVGhDTEhkQ1FVRjFRaXhGUVVGMlFpeEZRVUV3UWl4M1FrRkJkVUlzUlVGQmRrSXNSVUZCTUVJc2VVSkJRWGRDTEVWQlFYaENMRVZCUVRKQ0xITkNRVUZ4UWl4RlFVRnlRaXhGUVVGM1FpeHRRa0ZCYTBJc1JVRkJiRUlzUlVGb1JIWkdMRU5CUVVnc1JVRm5SR2xJTEVsQlFVY3NRMEZCUXl4VlFVRlRMRTlCUVZRc1JVRkJhVUlzVFVGQmFrSXNSVUZCZDBJc1QwRkJlRUlzUlVGQlowTTdPenM3T3pzN1FVRlBiazBzWjBKQlFVa3NWVUZCVlN4RlFVRldMRU5CVUN0TU96dEJRVk51VFN4dFFrRkJUeXhQUVVGUUxFZEJRV2xDTEZGQlFXcENMRU5CVkcxTk96dEJRVmR1VFN4eFFrRkJVeXhSUVVGVUxFTkJRV3RDTEZGQlFXeENMRVZCUVRSQ0xFbEJRVFZDTEVWQlFXdERMRTlCUVd4RExFVkJRVEpETEV0QlFUTkRMRVZCUVd0RU8wRkJRemxETEc5Q1FVRkpMRU5CUVVNc1QwRkJSQ3hKUVVGWkxGRkJRVkVzVFVGQlVpeExRVUZ0UWl4RFFVRnVRaXhGUVVGelFqdEJRVU5zUXl3eVFrRkJUeXhGUVVGUUxFTkJSR3RETzJsQ1FVRjBReXhOUVVWUE8wRkJRMGdzTkVKQlFWRXNTVUZCVWl4RFFVRmhMRk5CUVdJc1JVRkVSenRCUVVWSUxESkNRVUZQTEZGQlFWRXNVVUZCVWl4RlFVRnJRaXhKUVVGc1FpeEZRVUYzUWl4UFFVRjRRaXhGUVVGcFF5eExRVUZxUXl4RlFVRjNReXhEUVVGNFF5eERRVUZRTEVOQlJrYzdhVUpCUmxBN1lVRkVTanM3UVVGVFFTeHhRa0ZCVXl4UFFVRlVMRU5CUVdsQ0xGRkJRV3BDTEVWQlFUSkNMRWxCUVROQ0xFVkJRV2xETEU5QlFXcERMRVZCUVRCRExFdEJRVEZETEVWQlFXbEVMRk5CUVdwRUxFVkJRVFJFTzBGQlEzaEVMSGRDUVVGUkxGTkJRVk1zUlVGQlZDeERRVVJuUkRzN1FVRkplRVFzYjBKQlFVa3NVVUZCU2l4RlFVRmpPMEZCUTFZc2QwSkJRVWtzWVVGQllTeFBRVUZpTEVWQlFYTkNMRk5CUVhSQ0xFVkJRV2xETEZOQlFXcERMRU5CUVVvc1JVRkJhVVE3UVVGRE4wTXNPRUpCUVUwc1UwRkJUaXhKUVVGdFFpeFJRVUZ1UWl4RFFVUTJRenR4UWtGQmFrUTdPMEZCU1VFc2QwSkJRVWtzV1VGQldTeExRVUZMTEZGQlFVd3NRMEZNVGpzN1FVRlBWaXgzUWtGQlNTeFRRVUZLTEVWQlFXVTdPMEZCUlZnc05FSkJRVWtzWVVGQllTeFRRVUZUTEZWQlFWUXNRMEZHVGpzN1FVRkpXQ3cyUWtGQlN5eEpRVUZKTEVsQlFVa3NRMEZCU2l4RlFVRlBMRWxCUVVrc1MwRkJTeXhSUVVGTUxFTkJRV01zVFVGQlpDeEZRVUZ6UWl4SFFVRXhReXhGUVVFclF6dEJRVU16UXl4NVEwRkJZU3hEUVVGaUxFTkJSREpET3p0QlFVY3pReXhuUTBGQlNTeFRRVUZUTEZWQlFWVXNRMEZCVml4TFFVRm5RaXhQUVVGb1FpeERRVWc0UWp0QlFVa3pReXhuUTBGQlNTeFpRVUZaTEdGQlFXRXNUMEZCVHl4TFFVRlFMRWxCUVdkQ0xFTkJRV2hDTEVOQlFXSTdPenRCUVVveVFpeG5RMEZQZGtNc1lVRkJZU3hQUVVGaUxFVkJRWE5DTEZOQlFYUkNMRVZCUVdsRExGTkJRV3BETEVOQlFVb3NSVUZCYVVRN1FVRkROME1zZDBOQlFWRXNWMEZCVnl4RFFVRllMRU5CUVZJc1JVRkJkVUlzVFVGQmRrSXNSVUZCSzBJc1QwRkJMMElzUlVGQmQwTXNTMEZCZUVNc1JVRkJLME1zVTBGQkwwTXNSVUZFTmtNN05rSkJRV3BFT3p0QlFVbEJMSGREUVVGWkxGTkJRVm9zUTBGWU1rTTdlVUpCUVM5RE8zRkNRVXBLTzJsQ1FWQktPenRCUVRKQ1FTeDFRa0ZCVHl4TFFVRlFMRU5CTDBKM1JEdGhRVUUxUkRzN08wRkJjRUp0VFN4eFFrRjFSREZNTEZsQlFWUXNRMEZCYzBJc1QwRkJkRUlzUlVGQkswSXNTVUZCTDBJc1JVRkJjVU1zUzBGQmNrTXNSVUZCTkVNN1FVRkRlRU1zYjBKQlFVa3NVVUZCVVN4TlFVRlNMRXRCUVcxQ0xFTkJRVzVDTEVWQlFYTkNPMEZCUTNSQ0xESkNRVUZQTEV0QlFWQXNRMEZFYzBJN2FVSkJRVEZDT3p0QlFVbEJMRzlDUVVGSkxGZEJRVmNzUTBGQldDeERRVXh2UXp0QlFVMTRReXh2UWtGQlNTeFhRVUZYTEZGQlFWRXNUVUZCVWl4SFFVRnBRaXhEUVVGcVFpeERRVTU1UWp0QlFVOTRReXh2UWtGQlNTeFpRVUZLTEVOQlVIZERPMEZCVVhoRExHOUNRVUZKTEZkQlFVb3NRMEZTZDBNN08wRkJWWGhETEhWQ1FVRlBMRmxCUVZrc1VVRkJXaXhGUVVGelFqdEJRVU42UWl4dFEwRkJaU3hEUVVGRkxGZEJRVmNzVVVGQldDeERRVUZFTEVkQlFYZENMRU5CUVhoQ0xFbEJRVGhDTEVOQlFTOUNMRU5CUkZVN1FVRkZla0lzYTBOQlFXTXNVVUZCVVN4WlFVRlNMRU5CUVdRc1EwRkdlVUk3TzBGQlNYcENMSGRDUVVGSkxHRkJRV0VzVVVGQllpeEZRVUYxUWp0QlFVTjJRaXdyUWtGQlR5eGxRVUZsTEVsQlFXWXNTVUZCZFVJc1pVRkJaU3hMUVVGbUxFTkJSRkE3Y1VKQlFUTkNMRTFCUlU4c1NVRkJTU3hqUVVGakxFbEJRV1FzUlVGQmIwSTdRVUZETTBJc2JVTkJRVmNzWlVGQlpTeERRVUZtTEVOQlJHZENPM0ZDUVVGNFFpeE5RVVZETEVsQlFVa3NZMEZCWXl4TFFVRmtMRVZCUVhGQ08wRkJRemRDTEcxRFFVRlhMR1ZCUVdVc1EwRkJaaXhEUVVSclFqdHhRa0ZCZWtJc1RVRkZSRHRCUVVOSUxDdENRVUZQTEVsQlFWQXNRMEZFUnp0eFFrRkdRenRwUWtGU1dqczdRVUZsUVN4MVFrRkJUeXhMUVVGUUxFTkJla0ozUXp0aFFVRTFRenM3UVVFMFFrRXNjVUpCUVZNc1UwRkJWQ3hEUVVGdFFpeERRVUZ1UWl4RlFVRnpRaXhEUVVGMFFpeEZRVUY1UWp0QlFVTnlRaXgxUWtGQlR5eEpRVUZKTEVOQlFVb3NSMEZCVVN4RFFVRlNMRWRCUVZrc1EwRkJReXhEUVVGRUxFTkJSRVU3WVVGQmVrSTdVMEZ1Um0xTExFVkJkVVpxU3l4RlFYWkdaMHNzUTBGQlNDeEZRWFZHZWtvc1NVRkJSeXhEUVVGRExGVkJRVk1zVDBGQlZDeEZRVUZwUWl4TlFVRnFRaXhGUVVGM1FpeFBRVUY0UWl4RlFVRm5RenRCUVVNeFF5eG5Ra0ZCU1N4clFrRkJhMElzVVVGQlVTeHZRa0ZCVWl4RFFVRnNRaXhEUVVSelF6czdRVUZITVVNc1owSkJRVWtzVjBGQlZ5eFJRVUZSTEhWQ1FVRlNMRU5CUVZnc1EwRkljME03UVVGSk1VTXNaMEpCUVVrc1UwRkJVeXhSUVVGUkxHOUNRVUZTTEVOQlFWUXNRMEZLYzBNN08wRkJUVEZETEdkQ1FVRkpMR1ZCUVdVc1VVRkJVU3hwUWtGQlVpeERRVUZtTEVOQlRuTkRPenRCUVZFeFF5eHRRa0ZCVHl4UFFVRlFMRWRCUVdsQ0xGVkJRV3BDTEVOQlVqQkRPenRCUVZVeFF5eHhRa0ZCVXl4VlFVRlVMRU5CUVc5Q0xFMUJRWEJDTEVWQlFUUkNMRTlCUVRWQ0xFVkJRWEZETEdGQlFYSkRMRVZCUVc5RU8wRkJRMmhFTEc5Q1FVRkpMRTlCUVU4c1QwRkJUeXhKUVVGUUxFTkJSSEZETzBGQlJXaEVMRzlDUVVGSkxGRkJRVkVzVDBGQlR5eExRVUZRTEVOQlJtOURPMEZCUjJoRUxHOUNRVUZKTEZGQlFWRXNUMEZCVHl4TFFVRlFMRU5CU0c5RE96dEJRVXRvUkN4M1FrRkJVU3hKUVVGU08wRkJRMGtzZVVKQlFVc3NUMEZCVHl4TlFVRlFPMEZCUTBRc0swSkJRVThzVjBGQlZ5eFBRVUZZTEVWQlFXOUNMRXRCUVhCQ0xFTkJRVkFzUTBGRVNqdEJRVVJLTEhsQ1FVZFRMRTlCUVU4c1RVRkJVRHRCUVVORUxDdENRVUZQTEZkQlFWY3NUMEZCV0N4RlFVRnZRaXhMUVVGd1FpeEZRVUV5UWl4aFFVRXpRaXhEUVVGUUxFTkJSRW83UVVGSVNpeDVRa0ZMVXl4UFFVRlBMRXRCUVZBN1FVRkRSQ3dyUWtGQlR5eFpRVUZaTEU5QlFWb3NSVUZCY1VJc1MwRkJja0lzUlVGQk5FSXNTMEZCTlVJc1JVRkJiVU1zWVVGQmJrTXNRMEZCVUN4RFFVUktPMEZCVEVvc2VVSkJUMU1zVDBGQlR5eE5RVUZRTzBGQlEwUXNLMEpCUVU4c1dVRkJXU3hQUVVGYUxFVkJRWEZDTEV0QlFYSkNMRVZCUVRSQ0xFdEJRVFZDTEVWQlFXMURMR0ZCUVc1RExFTkJRVkFzUTBGRVNqdEJRVkJLTEhsQ1FWTlRMRTlCUVU4c1MwRkJVRHRCUVVORUxDdENRVUZQTEZkQlFWY3NUMEZCV0N4RlFVRnZRaXhMUVVGd1FpeEZRVUV5UWl4TFFVRXpRaXhGUVVGclF5eGhRVUZzUXl4RFFVRlFMRU5CUkVvN1FVRlVTaXg1UWtGWFV5eFBRVUZQTEV0QlFWQTdRVUZEUkN4M1EwRkJaMElzVDBGQmFFSXNSVUZCZVVJc1MwRkJla0lzUlVGRVNqdEJRVVZKTEN0Q1FVRlBMRTlCUVZBc1EwRkdTanRCUVZoS0xIbENRV05UTEU5QlFVOHNTMEZCVUR0QlFVTkVMSGREUVVGblFpeFBRVUZvUWl4RlFVRjVRaXhMUVVGNlFpeEZRVUZuUXl4TlFVRk5MRlZCUVU0c1EwRkJhRU1zUTBGRVNqdEJRVVZKTEN0Q1FVRlBMRTlCUVZBc1EwRkdTanRCUVdSS0xIbENRV2xDVXl4UFFVRlBMRXRCUVZBN1FVRkRSQ3dyUWtGQlR5eFpRVUZaTEU5QlFWb3NSVUZEU0N4alFVRmpMRXRCUVdRc1EwRkJiMElzVDBGQmNFSXNSVUZCTmtJc1MwRkJOMElzUlVGQmIwTXNZVUZCY0VNc1EwRkVSeXhEUVVGUUxFTkJSRW83UVVGcVFrbzdRVUZ4UWxFc0swSkJRVThzVDBGQlVDeERRVVJLTzBGQmNFSktMR2xDUVV4blJEdGhRVUZ3UkRzN1FVRTRRa0VzY1VKQlFWTXNWVUZCVkN4RFFVRnZRaXhQUVVGd1FpeEZRVUUyUWl4TFFVRTNRaXhGUVVGdlF6dEJRVU5vUXl4dlFrRkJTU3hoUVVGaExGRkJRVkVzVlVGQlVpeERRVVJsT3p0QlFVZG9ReXh2UWtGQlNTeFZRVUZLTEVWQlFXZENPMEZCUTFvc0swSkJRVmNzVjBGQldDeERRVUYxUWl4UFFVRjJRaXhGUVVSWk8ybENRVUZvUWpzN1FVRkpRU3c0UWtGQll5eFBRVUZrTEVWQlFYVkNMRXRCUVhaQ0xFVkJVR2RET3p0QlFWTm9ReXgxUWtGQlR5eEpRVUZRTEVOQlZHZERPMkZCUVhCRE96dEJRVmxCTEhGQ1FVRlRMRlZCUVZRc1EwRkJiMElzVlVGQmNFSXNSVUZCWjBNc1MwRkJhRU1zUlVGQmRVTXNZVUZCZGtNc1JVRkJjMFE3UVVGRGJFUXNiMEpCUVVrc1ZVRkJWU3hqUVVGakxFMUJRV1FzUTBGQmNVSXNTMEZCY2tJc1JVRkJORUlzWVVGQk5VSXNRMEZCVml4RFFVUTRRenM3UVVGSGJFUXNiMEpCUVVrc1ZVRkJTaXhGUVVGblFqdEJRVU5hTEN0Q1FVRlhMRmRCUVZnc1EwRkJkVUlzVDBGQmRrSXNSVUZFV1R0cFFrRkJhRUk3TzBGQlNVRXNkVUpCUVU4c1ZVRkJVQ3hEUVZCclJEdGhRVUYwUkRzN1FVRlZRU3h4UWtGQlV5eFhRVUZVTEVOQlFYRkNMRTlCUVhKQ0xFVkJRVGhDTEZOQlFUbENMRVZCUVhsRExFdEJRWHBETEVWQlFXZEVMR0ZCUVdoRUxFVkJRU3RFTzBGQlF6TkVMRzlDUVVGSkxFOUJRVW9zUTBGRU1rUTdPMEZCUnpORUxHOUNRVUZKTEZGQlFWRXNVVUZCVWl4TFFVRnhRaXhEUVVGeVFpeEZRVUYzUWp0QlFVTjRRaXcwUWtGQlVTeFhRVUZTTEVOQlFXOUNMRU5CUVhCQ0xFVkJRWFZDTEZGQlFWRXNUVUZCVWl4RlFVRm5RaXhOUVVGTkxFbEJRVTRzUTBGQmRrTXNRMEZFZDBJN1FVRkZlRUlzT0VKQlFWVXNUMEZCVml4RFFVWjNRanRwUWtGQk5VSXNUVUZIVHp0QlFVTklMSGRDUVVGSkxHRkJRV0VzVVVGQlVTeFZRVUZTTEVOQlJHUTdRVUZGU0N3NFFrRkJWU3hqUVVGakxFMUJRV1FzUTBGQmNVSXNTMEZCY2tJc1JVRkJORUlzWVVGQk5VSXNRMEZCVml4RFFVWkhPenRCUVVsSUxIZENRVUZKTEdOQlFXTXNXVUZCV1N4UFFVRmFMRVZCUVhGQ08wRkJRMjVETEcxRFFVRlhMRmxCUVZnc1EwRkJkMElzVDBGQmVFSXNSVUZCYVVNc1QwRkJha01zUlVGRWJVTTdjVUpCUVhaRE8ybENRVkJLT3p0QlFWbEJMSFZDUVVGUExFOUJRVkFzUTBGbU1rUTdZVUZCTDBRN08wRkJhMEpCTEhGQ1FVRlRMRmRCUVZRc1EwRkJjVUlzVDBGQmNrSXNSVUZCT0VJc1UwRkJPVUlzUlVGQmVVTXNUVUZCZWtNc1JVRkJhVVFzWVVGQmFrUXNSVUZCWjBVN1FVRkROVVFzYjBKQlFVa3NWMEZCVnl4aFFVRmhMRk5CUVdJc1JVRkJkMElzVFVGQmVFSXNRMEZCV0N4RFFVUjNSRHRCUVVVMVJDeHZRa0ZCU1N4UFFVRktMRU5CUmpSRU96dEJRVWsxUkN4dlFrRkJTU3hSUVVGS0xFVkJRV003UVVGRFZpdzRRa0ZCVlN4UFFVRlBMRTFCUVZBc1EwRkJZeXhUUVVGa0xFVkJRWGxDTEU5QlFYcENMRXRCUVhGRExFOUJRWEpETEVOQlJFRTdhVUpCUVdRc1RVRkZUenRCUVVOSUxEaENRVUZWTEdOQlFXTXNUVUZCWkN4RFFVRnhRaXhOUVVGeVFpeEZRVUUyUWl4aFFVRTNRaXhEUVVGV0xFTkJSRWM3YVVKQlJsQTdPMEZCVFVFc2IwSkJRVWtzWVVGQllTeFJRVUZSTEZWQlFWSXNRMEZXTWtNN08wRkJXVFZFTEc5Q1FVRkpMR05CUVdNc1dVRkJXU3hQUVVGYUxFVkJRWEZDTzBGQlEyNURMQ3RDUVVGWExGbEJRVmdzUTBGQmQwSXNUMEZCZUVJc1JVRkJhVU1zVDBGQmFrTXNSVUZFYlVNN2FVSkJRWFpET3p0QlFVbEJMRzlDUVVGSkxFTkJRVU1zVVVGQlJDeEZRVUZYTzBGQlExZ3NhME5CUVdNc1QwRkJaQ3hGUVVGMVFpeFRRVUYyUWl4RlFVUlhPMmxDUVVGbU96dEJRVWxCTEhWQ1FVRlBMRTlCUVZBc1EwRndRalJFTzJGQlFXaEZPenRCUVhWQ1FTeHhRa0ZCVXl4VlFVRlVMRU5CUVc5Q0xFOUJRWEJDTEVWQlFUWkNMRk5CUVRkQ0xFVkJRWGRETEV0QlFYaERMRVZCUVN0RExHRkJRUzlETEVWQlFUaEVPMEZCUXpGRUxHOUNRVUZKTEdGQlFXRXNVVUZCVVN4VlFVRlNMRU5CUkhsRE8wRkJSVEZFTEc5Q1FVRkpMRlZCUVZVc1kwRkJZeXhOUVVGa0xFTkJRWEZDTEV0QlFYSkNMRVZCUVRSQ0xHRkJRVFZDTEVOQlFWWXNRMEZHYzBRN08wRkJTVEZFTEc5Q1FVRkpMR05CUVdNc1dVRkJXU3hQUVVGYUxFVkJRWEZDTzBGQlEyNURMQ3RDUVVGWExGbEJRVmdzUTBGQmQwSXNUMEZCZUVJc1JVRkJhVU1zVDBGQmFrTXNSVUZFYlVNN2FVSkJRWFpET3p0QlFVbEJMSFZDUVVGUExFOUJRVkFzUTBGU01FUTdZVUZCT1VRN08wRkJWMEVzY1VKQlFWTXNZVUZCVkN4RFFVRjFRaXhQUVVGMlFpeEZRVUZuUXl4RFFVRm9ReXhGUVVGdFF6dEJRVU12UWl4dlFrRkJTU3hQUVVGUExFVkJRVVVzVDBGQlJpeExRVUZqTEZWQlFYSkNMRWxCUVcxRExGTkJRVk1zUTBGQlZDeERRVUZ1UXl4RlFVRm5SRHRCUVVOb1JDeHpRa0ZCUlN4UFFVRkdMRU5CUVZVc1QwRkJWaXhGUVVSblJEdHBRa0ZCY0VRN1lVRkVTanM3UVVGTlFTeHhRa0ZCVXl4bFFVRlVMRU5CUVhsQ0xFOUJRWHBDTEVWQlFXdERMRXRCUVd4RExFVkJRWGxETzBGQlEzSkRMRzlDUVVGSkxHRkJRV0VzVVVGQlVTeFZRVUZTTEVOQlJHOUNPMEZCUlhKRExHOUNRVUZKTEZOQlFWTXNSVUZCVkN4RFFVWnBRenRCUVVkeVF5eHZRa0ZCU1N4SlFVRktMRU5CU0hGRE8wRkJTWEpETEc5Q1FVRkpMRTFCUVVvc1EwRktjVU03UVVGTGNrTXNiMEpCUVVrc1RVRkJTaXhEUVV4eFF6czdRVUZQY2tNc2NVSkJRVXNzU1VGQlNTeEpRVUZKTEVOQlFVb3NSVUZCVHl4SlFVRkpMRTFCUVUwc1QwRkJUaXhEUVVGakxFMUJRV1FzUlVGQmMwSXNSMEZCTVVNc1JVRkJLME03UVVGRE0wTXNOa0pCUVZNc1RVRkJUU3hQUVVGT0xFTkJRV01zUTBGQlpDeERRVUZVTEVOQlJESkRPMEZCUlRORExESkNRVUZQTEZkQlFWY3NUMEZCVHl4SlFVRlFMRU5CUVd4Q0xFTkJSakpETzBGQlJ6TkRMSGRDUVVGSkxFOUJRVThzUjBGQlVDeEZRVUZaTzBGQlExb3NLMEpCUVU4c1QwRkJUeXhIUVVGUUxFTkJRVkFzUjBGQmNVSXNTVUZCY2tJc1EwRkVXVHR4UWtGQmFFSTdRVUZIUVN3MFFrRkJVU3hYUVVGU0xFTkJRVzlDTEVsQlFYQkNMRVZCVGpKRE8ybENRVUV2UXpzN1FVRlRRU3h2UWtGQlNTeFRRVUZUTEZkQlFWY3NUVUZCV0N4RFFXaENkMEk3UVVGcFFuSkRMSEZDUVVGTExFbEJRVWtzU1VGQlNTeERRVUZLTEVWQlFVOHNTVUZCU1N4TlFVRk5MRTlCUVU0c1EwRkJZeXhOUVVGa0xFVkJRWE5DTEVkQlFURkRMRVZCUVN0RE8wRkJRek5ETERaQ1FVRlRMRTFCUVUwc1QwRkJUaXhEUVVGakxFTkJRV1FzUTBGQlZDeERRVVF5UXp0QlFVVXpReXd5UWtGQlR5eFBRVUZQTEU5QlFVOHNSMEZCVUN4RFFVRmtPenRCUVVZeVF5d3lRa0ZKTTBNc1EwRkJVU3haUVVGU0xFTkJRWEZDTEVsQlFYSkNMRVZCUVRKQ0xFOUJRVThzUlVGQlVDeEpRVUZoTEZGQlFXSXNSMEZCZDBJc1NVRkJlRUlzUjBGQkswSXNWMEZCVnl4UFFVRlBMRVZCUVZBc1EwRkJNVU1zUTBGQk0wSXNRMEZLTWtNN2FVSkJRUzlETzJGQmFrSktPenRCUVhsQ1FTeHhRa0ZCVXl4WFFVRlVMRU5CUVhGQ0xFOUJRWEpDTEVWQlFUaENMRTlCUVRsQ0xFVkJRWFZETzBGQlEyNURMRzlDUVVGSkxGZEJRVmNzVDBGQldDeEpRVUZ6UWl4WlFVRlpMRTlCUVZvc1NVRkJkVUlzVVVGQlVTeFZRVUZTTEVWQlFXOUNPMEZCUTJwRkxEUkNRVUZSTEZWQlFWSXNRMEZCYlVJc1dVRkJia0lzUTBGQlowTXNUMEZCYUVNc1JVRkJlVU1zVDBGQmVrTXNSVUZFYVVVN2FVSkJRWEpGT3p0QlFVbEJMSFZDUVVGUExFOUJRVkFzUTBGTWJVTTdZVUZCZGtNN1UwRnFTbFVzUlVGNVNsSXNSVUZCUXl4NVFrRkJkMElzUlVGQmVFSXNSVUZCTWtJc2MwSkJRWEZDTEVWQlFYSkNMRVZCUVhkQ0xITkNRVUZ4UWl4RlFVRnlRaXhGUVVGM1FpeHRRa0ZCYTBJc1JVRkJiRUlzUlVGNlNuSkZMRU5CUVVnc1JVRjVTaXRHTEVsQlFVY3NRMEZCUXl4VlFVRlRMRTlCUVZRc1JVRkJhVUlzVFVGQmFrSXNSVUZCZDBJc1QwRkJlRUlzUlVGQlowTTdRVUZEZWtrc1owSkJRVWtzVjBGQlZ5eFJRVUZSTEdsQ1FVRlNMRU5CUVZnc1EwRkVjVWs3UVVGRmVra3NaMEpCUVVrc1ZVRkJWU3hSUVVGUkxGbEJRVklzUTBGQlZpeERRVVp4U1RzN1FVRkpla2tzWjBKQlFVa3NVMEZCVXl4UlFVRlJMR3RDUVVGU0xFTkJRVlFzUTBGS2NVazdRVUZMZWtrc1owSkJRVWtzVjBGQlZ5eFJRVUZSTEdGQlFWSXNRMEZCV0N4RFFVeHhTVHRCUVUxNlNTeG5Ra0ZCU1N4VlFVRlZMRkZCUVZFc1dVRkJVaXhEUVVGV0xFTkJUbkZKTzBGQlQzcEpMRzFDUVVGUExFOUJRVkFzUjBGQmFVSXNTMEZCYWtJc1EwRlFlVWs3TzBGQlUzcEpMSEZDUVVGVExFdEJRVlFzUTBGQlpTeFJRVUZtTEVWQlFYbENMRTlCUVhwQ0xFVkJRV3RETEdGQlFXeERMRVZCUVdsRU8wRkJRemRETEdkRFFVRm5RaXhwUWtGQmFVSXNSVUZCYWtJc1EwRkVOa0k3UVVGRk4wTXNPRUpCUVdNc1MwRkJaQ3hIUVVGelFpeGpRVUZqTEV0QlFXUXNTVUZCZFVJc1kwRkJZeXhMUVVGa0xFdEJRWGRDTEV0QlFYaENMRWRCUTNaRExHTkJRV01zUzBGQlpDeEhRVU5CTEdOQlJtZENMRU5CUm5WQ08wRkJTemRETERoQ1FVRmpMRTFCUVdRc1IwRkJkVUlzWTBGQll5eE5RVUZrTEVsQlFYZENMRTFCUVhoQ0xFTkJUSE5DT3p0QlFVODNReXgxUWtGQlR5eGpRVUZqTEV0QlFXUXNRMEZCYjBJc1VVRkJjRUlzUlVGQk9FSXNUMEZCT1VJc1JVRkJkVU1zWVVGQmRrTXNRMEZCVUN4RFFWQTJRenRoUVVGcVJEczdRVUZWUVN4eFFrRkJVeXhqUVVGVUxFTkJRWGRDTEZGQlFYaENMRVZCUVd0RExFOUJRV3hETEVWQlFUSkRMR0ZCUVRORExFVkJRVEJFTzBGQlEzUkVMRzlDUVVGSkxGVkJRVlVzWVVGQllTeFBRVUZpTEVOQlFWWXNRMEZFYTBRN08wRkJSM1JFTEc5Q1FVRkpMRkZCUVZFc1RVRkJVaXhMUVVGdFFpeERRVUZ1UWl4RlFVRnpRanRCUVVOMFFpd3lRa0ZCVHl4UlFVRlFMRU5CUkhOQ08ybENRVUV4UWpzN1FVRkpRU3h2UWtGQlNTeFJRVUZSTEZOQlFWTXNVVUZCVkN4RlFVRnRRaXhSUVVGUkxFTkJRVklzUlVGQlZ5eFBRVUU1UWl4RFFVRlNMRU5CVUd0RU8wRkJVWFJFTEc5Q1FVRkpMR2RDUVVGblFpeFRRVUZUTEdGQlFWUXNRMEZTYTBNN08wRkJWWFJFTEc5Q1FVRkpMRU5CUVVNc1kwRkJZeXhSUVVGa0xFbEJRVEJDTEd0Q1FVRnJRaXhSUVVGc1FpeEZRVUUwUWp0QlFVTjJSQ3hyUTBGQll5eFJRVUZrTEVkQlFYbENMR0ZCUVhwQ0xFTkJSSFZFTzJsQ1FVRXpSRHM3UVVGSlFTeHhRa0ZCU3l4SlFVRkpMRWxCUVVrc1EwRkJTaXhGUVVGUExFbEJRVWtzVVVGQlVTeE5RVUZTTEVWQlFXZENMRWRCUVhCRExFVkJRWGxETzBGQlEzSkRMSGRDUVVGSkxGbEJRVmtzVVVGQlVTeERRVUZTTEVOQlFWb3NRMEZFYVVNN1FVRkZja01zSzBKQlFWY3NWMEZCVnl4UlFVRllMRVZCUTFBc1RVRkJUU3hUUVVGT0xFTkJSRThzUlVGRlVDeFJRVUZSTEZOQlFWSXNRMEZHVHl4RlFVZFFMR0ZCU0U4c1EwRkJXQ3hEUVVaeFF6dHBRa0ZCZWtNN08wRkJVVUVzZFVKQlFVOHNVVUZCVUN4RFFYUkNjMFE3WVVGQk1VUTdPMEZCZVVKQkxIRkNRVUZUTEZWQlFWUXNRMEZCYjBJc1VVRkJjRUlzUlVGQk9FSXNUMEZCT1VJc1JVRkJkVU1zVTBGQmRrTXNSVUZCYTBRc1lVRkJiRVFzUlVGQmFVVTdRVUZETjBRc2IwSkJRVWtzUTBGQlF5eFBRVUZFTEVWQlFWVTdRVUZEVml3eVFrRkJUeXhSUVVGUUxFTkJSRlU3YVVKQlFXUTdPMEZCU1VFc2IwSkJRVWtzVDBGQlNpeERRVXcyUkRzN1FVRlBOMFFzYjBKQlFVa3NVVUZCVVN4VFFVRlNMRU5CUVVvc1JVRkJkMEk3UVVGRGNFSXNlVUpCUVVzc1NVRkJTU3hKUVVGSkxFTkJRVW9zUlVGQlR5eEpRVUZKTEZWQlFWVXNUVUZCVml4RlFVRnJRaXhIUVVGMFF5eEZRVUV5UXp0QlFVTjJReXhyUTBGQlZTeFJRVUZSTEZWQlFWVXNRMEZCVml4RFFVRlNMRVZCUVhOQ0xFOUJRWFJDTEVWQlFTdENMR0ZCUVM5Q0xFTkJRVllzUTBGRWRVTTdPMEZCUjNaRExEUkNRVUZKTEZsQlFWa3NVVUZCV2l4RlFVRnpRanRCUVVOMFFpeDFRMEZCVnl4UFFVRllMRU5CUkhOQ08zbENRVUV4UWp0eFFrRklTanRwUWtGRVNpeE5RVkZQTzBGQlEwZ3NPRUpCUVZVc1VVRkJVU3hUUVVGU0xFVkJRVzFDTEU5QlFXNUNMRVZCUVRSQ0xHRkJRVFZDTEVOQlFWWXNRMEZFUnpzN1FVRkhTQ3gzUWtGQlNTeFpRVUZaTEZGQlFWb3NSVUZCYzBJN1FVRkRkRUlzYlVOQlFWY3NUMEZCV0N4RFFVUnpRanR4UWtGQk1VSTdhVUpCV0VvN08wRkJaMEpCTEhWQ1FVRlBMRkZCUVZBc1EwRjJRalpFTzJGQlFXcEZPenRCUVRCQ1FTeHhRa0ZCVXl4WlFVRlVMRU5CUVhOQ0xFOUJRWFJDTEVWQlFTdENPMEZCUXpOQ0xHOUNRVUZKTEZWQlFWVXNSVUZCVml4RFFVUjFRanM3UVVGSE0wSXNjVUpCUVVzc1NVRkJTU3hIUVVGS0xFbEJRVmNzVDBGQmFFSXNSVUZCZVVJN1FVRkRja0lzZDBKQlFVa3NVVUZCVVN4SFFVRlNMRVZCUVdFN1FVRkRZaXhuUTBGQlVTeEpRVUZTTEVOQlFXRXNUMEZCVHl4SFFVRlFMRU5CUVdJc1JVRkVZVHR4UWtGQmFrSTdhVUpCUkVvN08wRkJUVUVzZFVKQlFVOHNUMEZCVUN4RFFWUXlRanRoUVVFdlFqdFRRWFJGZVVjc1JVRnJSblpITEVWQlFVTXNiMEpCUVcxQ0xFVkJRVzVDTEVWQlFYTkNMR1ZCUVdNc1JVRkJaQ3hGUVVGcFFpeGpRVUZoTEVWQlFXSXNSVUZCWjBJc2JVSkJRV3RDTEVWQlFXeENMRVZCUVhGQ0xHTkJRV0VzUlVGQllpeEZRV3hHZVVJc1EwRkJTQ3hGUVd0R1NpeEpRVUZITEVOQlFVTXNWVUZCVXl4UFFVRlVMRVZCUVdsQ0xFMUJRV3BDTEVWQlFYZENMRTlCUVhoQ0xFVkJRV2RETzBGQlEzSkpMR2RDUVVGSkxGZEJRVmNzVVVGQlVTeDFRa0ZCVWl4RFFVRllMRU5CUkdsSk96dEJRVWR5U1N4dFFrRkJUeXhQUVVGUUxFZEJRV2xDTEZsQlFXcENMRU5CU0hGSk96dEJRVXR5U1N4eFFrRkJVeXhaUVVGVUxFTkJRWE5DTEVOQlFYUkNMRVZCUVhsQ0xFTkJRWHBDTEVWQlFUUkNPMEZCUTNoQ0xHOUNRVUZKTEZOQlFWTXNRMEZCVkN4TFFVRmxMRk5CUVZNc1EwRkJWQ3hEUVVGbUxFVkJRVFJDTzBGQlF6VkNMSGRDUVVGSkxGVkJRVlVzUTBGQlZpeEpRVUZsTEZWQlFWVXNRMEZCVml4RlFVRmhPMEZCUXpWQ0xDdENRVUZQTEVWQlFVVXNSVUZCUml4TFFVRlRMRVZCUVVVc1JVRkJSaXhEUVVSWk8zRkNRVUZvUXl4TlFVVlBPMEZCUTBnc0swSkJRVThzUlVGQlJTeEpRVUZHTEV0QlFWY3NSVUZCUlN4SlFVRkdMRU5CUkdZN2NVSkJSbEE3YVVKQlJFbzdPMEZCVVVFc2RVSkJRVThzUzBGQlVDeERRVlIzUWp0aFFVRTFRanRUUVV4eFJ5eEZRV2xDYmtjc1JVRkJReXg1UWtGQmQwSXNSVUZCZUVJc1JVRnFRbWxITEVOQlFVZ3NSVUZwUW1wRkxFbEJRVWNzUTBGQlF5eFZRVUZUTEU5QlFWUXNSVUZCYVVJc1RVRkJha0lzUlVGQmQwSXNUMEZCZUVJc1JVRkJaME03UVVGRGNFVXNlVUpCUkc5Rk96dEJRVWR3UlN4blFrRkJTU3hWUVVGVkxGRkJRVkVzVlVGQlVpeERRVUZXTEVOQlNHZEZPenRCUVV0d1JTeHRRa0ZCVHl4UFFVRlFMRWRCUVdsQ0xFMUJRV3BDTEVOQlRHOUZPenRCUVU5d1JTeHhRa0ZCVXl4TlFVRlVMRU5CUVdkQ0xFdEJRV2hDTEVWQlFYVkNPMEZCUTI1Q0xHOUNRVUZKTEVWQlFVVXNaMEpCUVdkQ0xFMUJRV2hDTEVOQlFVWXNSVUZCTWtJN1FVRkRNMElzTWtKQlFVOHNTVUZCU1N4TlFVRktMRU5CUVZjc1MwRkJXQ3hEUVVGUUxFTkJSREpDTzJsQ1FVRXZRanM3UVVGSlFTeHhRa0ZCU3l4TFFVRk1MRWRCUVdFc1MwRkJZaXhEUVV4dFFqdGhRVUYyUWpzN1FVRlJRU3h0UWtGQlR5eFRRVUZRTEVOQlFXbENMRWxCUVdwQ0xFZEJRWGRDTEZWQlFWVXNTVUZCVml4RlFVRm5RaXhaUVVGb1FpeEZRVUU0UWp0QlFVTnNSQ3h2UWtGQlNTeExRVUZMTEZGQlFWRXNTVUZCVWl4RFFVRk1MRU5CUkRoRE8wRkJSV3hFTEc5Q1FVRkpMRmRCUVZjc1lVRkJZU3hOUVVGaUxFTkJRVzlDTEVOQlFYQkNMRU5CUVZnc1EwRkdPRU03TzBGQlNXeEVMRzFDUVVGSExGRkJRVWdzU1VGQlpTeExRVUZMTEV0QlFVd3NRMEZLYlVNN1lVRkJPVUlzUTBGbU5FTTdPMEZCYzBKd1JTeHRRa0ZCVHl4VFFVRlFMRU5CUVdsQ0xFMUJRV3BDTEVkQlFUQkNMRlZCUVZNc1NVRkJWQ3hGUVVGbExGbEJRV1lzUlVGQk5rSTdRVUZEYmtRc2IwSkJRVWtzUzBGQlN5eFJRVUZSTEVsQlFWSXNRMEZCVEN4RFFVUXJRenRCUVVWdVJDeHZRa0ZCU1N4WFFVRlhMR0ZCUVdFc1RVRkJZaXhEUVVGdlFpeERRVUZ3UWl4RFFVRllMRU5CUml0RE96dEJRVWx1UkN4dFFrRkJSeXhSUVVGSUxFbEJRV1VzVTBGQlppeERRVXB0UkR0aFFVRTNRaXhEUVhSQ01FTTdVMEZCYUVNc1JVRTJRbXhETEVWQlFVTXNXVUZCVnl4RFFVRllMRVZCTjBKblF5eERRVUZJTEVWQk5rSmtMRWxCUVVjc1EwRkJReXhWUVVGVExFOUJRVlFzUlVGQmFVSXNUVUZCYWtJc1JVRkJkMElzVDBGQmVFSXNSVUZCWjBNN1FVRkRkRVFzZVVKQlJITkVPenRCUVVkMFJDeHRRa0ZCVHl4UFFVRlFMRWRCUVdsQ0xGZEJRV3BDTEVOQlNITkVPenRCUVV0MFJDeHhRa0ZCVXl4WFFVRlVMRU5CUVhGQ0xFdEJRWEpDTEVWQlFUUkNPMEZCUTNoQ0xHOUNRVUZKTEVWQlFVVXNaMEpCUVdkQ0xGZEJRV2hDTEVOQlFVWXNSVUZCWjBNN1FVRkRhRU1zTWtKQlFVOHNTVUZCU1N4WFFVRktMRU5CUVdkQ0xFdEJRV2hDTEVOQlFWQXNRMEZFWjBNN2FVSkJRWEJET3p0QlFVbEJMSEZDUVVGTExFdEJRVXdzUjBGQllTeExRVUZpTEVOQlRIZENPMkZCUVRWQ096dEJRVkZCTEhkQ1FVRlpMRk5CUVZvc1EwRkJjMElzU1VGQmRFSXNSMEZCTmtJc1ZVRkJWU3hKUVVGV0xFVkJRV2RDTEZsQlFXaENMRVZCUVRoQ08wRkJRM1pFTEc5Q1FVRkpMRXRCUVVzc1dVRkJUQ3hOUVVGMVFpeExRVUZMTEV0QlFVd3NSVUZCV1R0QlFVTnVReXg1UWtGQlN5eFpRVUZNTEVsQlFYRkNMRXRCUVVzc1MwRkJUQ3hEUVVSak8ybENRVUYyUXp0aFFVUjVRaXhEUVdKNVFqdFRRVUZvUXl4RlFXMUNjRUlzUlVGdVFtMUNMRU5CUVVnc1JVRnRRbG9zU1VGQlJ5eERRVUZETEZWQlFWTXNUMEZCVkN4RlFVRnBRaXhOUVVGcVFpeEZRVUYzUWl4UFFVRjRRaXhGUVVGblF6dEJRVU14UXl4NVFrRkVNRU03TzBGQlJ6RkRMR2RDUVVGSkxGVkJRVlVzVVVGQlVTeFpRVUZTTEVOQlFWWXNRMEZJYzBNN08wRkJTekZETEdkQ1FVRkpMRkZCUVZFc1VVRkJVU3h0UWtGQlVpeERRVUZTTEVOQlRITkRPMEZCVFRGRExHZENRVUZKTEZGQlFWRXNVVUZCVVN4dFFrRkJVaXhEUVVGU0xFTkJUbk5ETzBGQlR6RkRMR2RDUVVGSkxGVkJRVlVzVVVGQlVTeHRRa0ZCVWl4RFFVRldMRU5CVUhORE8wRkJVVEZETEdkQ1FVRkpMRlZCUVZVc1VVRkJVU3h0UWtGQlVpeERRVUZXTEVOQlVuTkRPMEZCVXpGRExHZENRVUZKTEZkQlFWY3NVVUZCVVN4dlFrRkJVaXhEUVVGWUxFTkJWSE5ETzBGQlZURkRMR2RDUVVGSkxGTkJRVk1zVVVGQlVTeHRRa0ZCVWl4RFFVRlVMRU5CVm5ORE8wRkJWekZETEdkQ1FVRkpMRmRCUVZjc1VVRkJVU3h0UWtGQlVpeERRVUZZTEVOQldITkRPenRCUVdFeFF5eG5Ra0ZCU1N4WFFVRlhMRkZCUVZFc1owSkJRVklzUTBGQldDeERRV0p6UXp0QlFXTXhReXhuUWtGQlNTeGpRVUZqTEZGQlFWRXNNRUpCUVZJc1EwRkJaQ3hEUVdSelF6dEJRV1V4UXl4blFrRkJTU3hUUVVGVExGRkJRVkVzYjBKQlFWSXNRMEZCVkN4RFFXWnpRenM3UVVGcFFqRkRMRzFDUVVGUExFOUJRVkFzUjBGQmFVSXNRMEZCYWtJc1EwRnFRakJET3p0QlFXMUNNVU1zY1VKQlFWTXNRMEZCVkN4RFFVRlhMRTlCUVZnc1JVRkJiMElzVlVGQmNFSXNSVUZCWjBNc1VVRkJhRU1zUlVGQk1FTTdRVUZEZEVNc2IwSkJRVWtzWVVGQllTeEZRVUZpTEVOQlJHdERPMEZCUlhSRExHOUNRVUZKTEVkQlFVb3NSVUZCVXl4TFFVRlVMRVZCUVdkQ0xFZEJRV2hDTEVWQlFYRkNMRk5CUVhKQ0xFTkJSbk5ET3p0QlFVbDBReXh2UWtGQlNTeERRVUZETEZGQlFVUXNTVUZCWVN4WFFVRlhMRlZCUVZnc1EwRkJZaXhGUVVGeFF6dEJRVU55UXl3clFrRkJWeXhWUVVGWUxFTkJSSEZETzBGQlJYSkRMRFJDUVVGUkxFVkJRVklzUTBGR2NVTTdhVUpCUVhwRE96dEJRVXRCTEhkQ1FVRlJMRk5CUVZNc1ZVRkJWQ3hKUVVGMVFpeEZRVUYyUWl4RFFWUTRRanRCUVZWMFF5eHpRa0ZCVFN4VFFVRlRMRTlCUVZRc1JVRkJhMElzUzBGQmJFSXNRMEZCVGpzN08wRkJWbk5ETEc5Q1FXRnNReXhOUVVGTkxHTkJRVTRzUTBGQmNVSXNTMEZCY2tJc1EwRkJTaXhGUVVGcFF6dEJRVU0zUWl3d1FrRkJUU3hOUVVGTkxFZEJRVTRzUTBGRWRVSTdRVUZGTjBJc01FSkJRVTBzUjBGQlRpeEhRVUZaTEZOQlFWb3NRMEZHTmtJN2FVSkJRV3BET3pzN1FVRmljME1zYjBKQmJVSnNReXhOUVVGTkxHTkJRVTRzUTBGQmNVSXNWMEZCY2tJc1EwRkJTaXhGUVVGMVF6dEJRVU51UXl4blEwRkJXU3hOUVVGTkxGTkJRVTRzUTBGRWRVSTdRVUZGYmtNc01FSkJRVTBzVTBGQlRpeEhRVUZyUWl4VFFVRnNRaXhEUVVadFF6dHBRa0ZCZGtNN096dEJRVzVDYzBNc2IwSkJlVUpzUXl4UlFVRlJMRTlCUVZJc1NVRkRRU3hEUVVGRExGTkJRVVFzU1VGRFFTeE5RVUZOTEdOQlFVNHNRMEZCY1VJc1QwRkJja0lzUTBGR1FTeEpRVWRCTEUxQlFVMHNTMEZCVGl4TFFVRm5RaXhUUVVGb1FpeEpRVU5CTEVOQlFVTXNUMEZCVHl4TlFVRk5MRXRCUVU0c1EwRkJVaXhGUVVOR08wRkJRMFVzTUVKQlFVMHNTMEZCVGl4SFFVRmpMRmxCUVZrc1RVRkJUU3hMUVVGT0xFTkJRVEZDTEVOQlJFWTdhVUpCVEVZN08wRkJVMEVzYjBOQlFXOUNMRXRCUVhCQ0xFVkJiRU56UXpzN1FVRnZRM1JETEc5Q1FVRkpMR0ZCUVdFc1UwRkJZaXhKUVVFd1FpeGhRVUZoTEVsQlFXSXNSVUZCYlVJN1FVRkROME1zTmtKQlFWTXNVVUZCVkN4RlFVRnRRaXhWUVVGdVFpeEZRVUVyUWl4SFFVRXZRaXhGUVVGdlF5eExRVUZ3UXl4RlFVUTJRenRwUWtGQmFrUTdPMEZCUzBFc2RVSkJRVThzU1VGQlNTeExRVUZLTEVOQlFWVXNSMEZCVml4RlFVRmxMRXRCUVdZc1JVRkJjMElzVlVGQmRFSXNSVUZCYTBNc1IwRkJiRU1zUlVGQmRVTXNVMEZCZGtNc1EwRkJVQ3hEUVhwRGMwTTdZVUZCTVVNN08wRkJORU5CTEhGQ1FVRlRMRkZCUVZRc1EwRkJhMElzUTBGQmJFSXNSVUZCY1VJc1ZVRkJja0lzUlVGQmFVTXNSMEZCYWtNc1JVRkJjME1zUzBGQmRFTXNSVUZCTmtNN1FVRkRla01zYjBKQlFVa3NUMEZCVHl4RFFVRlFMRXRCUVdFc1VVRkJZaXhGUVVGMVFqdEJRVU4yUWl3clFrRkJWeXhKUVVGWUxFTkJRV2RDTEVsQlFVa3NTMEZCU2l4RFFVRlZMRU5CUVZZc1EwRkJhRUlzUlVGRWRVSTdhVUpCUVROQ0xFMUJSVThzU1VGQlNTeFBRVUZQTEVOQlFWQXNTMEZCWVN4UlFVRmlMRVZCUVhWQ08wRkJRemxDTEN0Q1FVRlhMRWxCUVZnc1EwRkJaMElzU1VGQlNTeExRVUZLTEVOQlFWVXNUMEZCVHl4RFFVRlFMRU5CUVZZc1EwRkJhRUlzUlVGRU9FSTdhVUpCUVROQ0xFMUJSVUVzU1VGQlNTeFJRVUZSTEVOQlFWSXNRMEZCU2l4RlFVRm5RanRCUVVOdVFpd3JRa0ZCVnl4SlFVRllMRU5CUVdkQ0xFTkJRV2hDTEVWQlJHMUNPMmxDUVVGb1FpeE5RVVZCTEVsQlFVa3NVVUZCVVN4RFFVRlNMRU5CUVVvc1JVRkJaMEk3UVVGRGJrSXNlVUpCUVVzc1NVRkJTU3hKUVVGSkxFTkJRVW9zUlVGQlR5eEpRVUZKTEVWQlFVVXNUVUZCUml4RlFVRlZMRWRCUVRsQ0xFVkJRVzFETzBGQlF5OUNMR2xEUVVGVExFVkJRVVVzUTBGQlJpeERRVUZVTEVWQlFXVXNWVUZCWml4RlFVRXlRaXhIUVVFelFpeEZRVUZuUXl4TFFVRm9ReXhGUVVRclFqdHhRa0ZCYmtNN2FVSkJSRWNzVFVGSlFTeEpRVUZKTEUxQlFVMHNTVUZCVGl4SlFVRmpMRTFCUVUwc1UwRkJUaXhGUVVGcFFqdEJRVU4wUXl3eVFrRkVjME03YVVKQlFXNURMRTFCUlVFN1FVRkRTQ3d3UWtGQlRTeDVRa0ZCZVVJN1FVRkRNMElzZFVOQlFXVXNRMEZCWmp0QlFVTkJMSEZEUVVGaE8wRkJRMVFzY1VOQlFWTXNSMEZCVkR0QlFVTkJMSGREUVVGWkxFdEJRVm83ZVVKQlJrbzdjVUpCUmtVc1EwRkJUaXhEUVVSSE8ybENRVVpCTzJGQldGZzdPMEZCZDBKQkxIRkNRVUZUTEcxQ1FVRlVMRU5CUVRaQ0xFdEJRVGRDTEVWQlFXOURPMEZCUTJoRExIRkNRVUZMTEVsQlFVa3NVVUZCU2l4SlFVRm5RaXhMUVVGeVFpeEZRVUUwUWp0QlFVTjRRaXgzUWtGQlNTeE5RVUZOTEdOQlFVNHNRMEZCY1VJc1VVRkJja0lzUTBGQlNpeEZRVUZ2UXp0QlFVTm9ReXcwUWtGQlNTeFJRVUZSTEUxQlFVMHNVVUZCVGl4RFFVRlNMRU5CUkRSQ096dEJRVWRvUXl3MFFrRkJTU3hQUVVGUExFdEJRVkFzUTBGQlNpeEZRVUZ0UWp0QlFVTm1MSEZEUVVSbE8zbENRVUZ1UWpzN1FVRkpRU3cwUWtGQlNTeFRRVUZUTEUxQlFWUXNRMEZCWjBJc1EwRkJhRUlzUlVGQmJVSXNRMEZCYmtJc1RVRkJNRUlzUzBGQk1VSXNSVUZCYVVNN08wRkJSV3BETEd0RFFVRk5MRkZCUVU0c1NVRkJhMElzVDBGQlR5eExRVUZRTEVOQlFXeENMRU5CUm1sRE8zbENRVUZ5UXp0eFFrRlFTanRwUWtGRVNqdGhRVVJLT3p0QlFXbENRU3h4UWtGQlV5eFBRVUZVTEVOQlFXbENMRU5CUVdwQ0xFVkJRVzlDTzBGQlEyaENMSFZDUVVGUExGRkJRVkVzUTBGQlVpeExRVUZqTEZGQlFWRXNRMEZCVWl4RFFVRmtMRWxCUVRSQ0xGTkJRVk1zUTBGQlZDeERRVUUxUWl4SlFVRXlReXhUUVVGVExFTkJRVlFzUTBGQk0wTXNRMEZFVXp0aFFVRndRanM3UVVGSlFTeHhRa0ZCVXl4VlFVRlVMRU5CUVc5Q0xFTkJRWEJDTEVWQlFYVkNPMEZCUTI1Q0xIVkNRVUZQTEU5QlFVOHNRMEZCVUN4TFFVRmhMRkZCUVdJc1NVRkJlVUlzVVVGQlVTeERRVUZTTEVOQlFYcENMRWxCUVhWRExGRkJRVkVzUTBGQlVpeERRVUYyUXl4RFFVUlpPMkZCUVhaQ096dEJRVWxCTEhGQ1FVRlRMSGRDUVVGVUxFTkJRV3RETEVsQlFXeERMRVZCUVhkRE8wRkJRM0JETEc5Q1FVRkpMRTFCUVUwc1NVRkJTU3hMUVVGS0xFVkJRVTRzUTBGRVowTTdPMEZCUjNCRExHOUNRVUZKTEVsQlFVb3NSMEZCVnl4blJFRkJXQ3hEUVVodlF6dEJRVWx3UXl4dlFrRkJTU3hQUVVGS0xFZEJRV01zT0VOQlExWXNjVVJCUkZVc1IwRkZWaXhSUVVaVkxFZEJSMVlzV1VGQldTeExRVUZMTEdGQlFVd3NRMEZJUml4SFFVbFdMRXRCU2xVc1IwRkxWaXgzUWtGTVZTeEhRVTFXTEZsQlFWa3NTMEZCU3l4WFFVRk1MRU5CVGtZc1EwRktjMEk3UVVGWGFFTXNkVUpCUTBFc2QwUkJSRUVzUTBGWVowTTdRVUZoY0VNc2IwSkJRVWtzWVVGQlNpeEhRVUZ2UWl4TFFVRkxMR0ZCUVV3c1EwRmlaMEk3UVVGamNFTXNiMEpCUVVrc1YwRkJTaXhIUVVGclFpeExRVUZMTEZkQlFVd3NRMEZrYTBJN08wRkJaMEp3UXl4MVFrRkJUeXhIUVVGUUxFTkJhRUp2UXp0aFFVRjRRenM3UVVGdFFrRXNjVUpCUVZNc1YwRkJWQ3hEUVVGeFFpeEhRVUZ5UWl4RlFVRXdRanRCUVVOMFFpeHZRa0ZCU1R0QlFVTkJMREpDUVVGUExFdEJRVXNzVTBGQlRDeERRVUZsTEVkQlFXWXNSVUZCYjBJc1NVRkJjRUlzUlVGQk1FSXNUVUZCTVVJc1EwRkJVQ3hEUVVSQk8ybENRVUZLTEVOQlJVVXNUMEZCVHl4RFFVRlFMRVZCUVZVN1FVRkRVaXd5UWtGQlR5eFBRVUZQTEVkQlFWQXNRMEZCVUN4RFFVUlJPMmxDUVVGV08yRkJTRTQ3VTBGdVNWVXNSVUV5U1ZJc1JVRkJReXh4UWtGQmIwSXNSVUZCY0VJc1JVRkJkVUlzY1VKQlFXOUNMRVZCUVhCQ0xFVkJRWFZDTEhGQ1FVRnZRaXhGUVVGd1FpeEZRVUYxUWl4eFFrRkJiMElzUlVGQmNFSXNSVUZCZFVJc2MwSkJRWEZDTEVWQlFYSkNMRVZCUVhkQ0xIRkNRVUZ2UWl4RlFVRndRaXhGUVVGMVFpeHhRa0ZCYjBJc1JVRkJjRUlzUlVGQmRVSXNjMEpCUVhGQ0xFVkJRWEpDTEVWQlFYZENMRFJDUVVFeVFpeEZRVUV6UWl4RlFVRTRRaXhyUWtGQmFVSXNSVUZCYWtJc1JVRkJiMElzWTBGQllTeEZRVUZpTEVWQk0wbDBUeXhEUVVGSUxFVkJNa2t5VUN4SlFVRkhMRU5CUVVNc1ZVRkJVeXhQUVVGVUxFVkJRV2xDTEUxQlFXcENMRVZCUVhkQ0xFOUJRWGhDTEVWQlFXZERPMEZCUTNKVExIbENRVVJ4VXpzN1FVRkhjbE1zWjBKQlFVa3NVVUZCVVN4UlFVRlJMR1ZCUVZJc1EwRkJVaXhEUVVocFV6czdRVUZMY2xNc1owSkJRVWtzWlVGQlpTeHpRMEZCWml4RFFVeHBVenRCUVUxeVV5eG5Ra0ZCU1N4aFFVRmhMRTlCUVdJc1EwRk9hVk03TzBGQlVYSlRMRzFDUVVGUExFOUJRVkFzUjBGQmFVSXNVVUZCYWtJc1EwRlNjVk03TzBGQlZYSlRMSEZDUVVGVExGRkJRVlFzUTBGQmEwSXNSMEZCYkVJc1JVRkJkVUlzUzBGQmRrSXNSVUZCT0VJN1FVRkRNVUlzYjBKQlFVa3NRMEZCUXl4SFFVRkVMRVZCUVUwN1FVRkRUaXd5UWtGQlR5eExRVUZRTEVOQlJFMDdhVUpCUVZZN08wRkJTVUVzYjBKQlFVa3NUMEZCVHl4RFFVRkZMRTFCUVUwc1kwRkJUaXhEUVVGeFFpeEpRVUZ5UWl4RFFVRkdMRU5CVEdVN08wRkJUekZDTEc5Q1FVRkpMRmRCUVZjc1RVRkJUU3hIUVVGT0xFVkJRVmNzV1VGQldDeERRVUZZTEVOQlVITkNPMEZCVVRGQ0xHOUNRVUZKTEZWQlFWVXNTVUZCVml4RFFWSnpRanM3UVVGVk1VSXNiMEpCUVVrc1YwRkJWeXhKUVVGWUxFTkJRV2RDTEZOQlFWTXNRMEZCVkN4RFFVRm9RaXhEUVVGS0xFVkJRV3RETzBGQlF6bENMRGhDUVVGVkxFdEJRVllzUTBGRU9FSTdhVUpCUVd4RE96dEJRVWxCTEc5Q1FVRkpMRTlCUVVvc1JVRkJZU3hKUVVGaUxFVkJRVzFDTEVsQlFXNUNMRVZCUVhsQ0xFTkJRWHBDTEVOQlpEQkNPenRCUVdkQ01VSXNjVUpCUVVzc1NVRkJTU3hEUVVGS0xFVkJRVThzU1VGQlNTeFRRVUZUTEUxQlFWUXNSVUZCYVVJc1IwRkJha01zUlVGQmMwTTdRVUZEYkVNc01rSkJRVThzVTBGQlV5eERRVUZVTEVOQlFWQXNRMEZFYTBNN08wRkJSMnhETEhkQ1FVRkpMRU5CUVVNc1NVRkJSQ3hGUVVGUE8wRkJRMUFzYVVOQlJFODdjVUpCUVZnN08wRkJTVUVzTWtKQlFVOHNTMEZCU3l4TlFVRk1MRU5CUVZrc1EwRkJXaXhEUVVGUUxFTkJVR3RET3p0QlFWTnNReXgzUWtGQlNTeERRVUZETEU5QlFVUXNSVUZCVlR0QlFVTldMR3REUVVGVkxFbEJRVllzUTBGRVZUdHhRa0ZCWkN4TlFVVlBMRWxCUVVrc1UwRkJVeXhIUVVGVUxFVkJRV003UVVGRGNrSXNhME5CUVZVc1YwRkJWeXhGUVVGWUxFTkJSRmM3UVVGRmNrSXNaME5CUVZFc1NVRkJVaXhEUVVGaExFdEJRVXNzVTBGQlRDeERRVUZsTEVOQlFXWXNSVUZCYTBJc1MwRkJTeXhOUVVGTUxFTkJRUzlDTEVWQlJuRkNPM0ZDUVVGc1FpeE5RVWRCTEVsQlFVa3NVMEZCVXl4SFFVRlVMRWxCUVdkQ0xFbEJRV2hDTEVWQlFYTkNPMEZCUXpkQ0xEaENRVUZOTEVWQlFVNHNSMEZCVnl4TFFVRkxMRk5CUVV3c1EwRkJaU3hEUVVGbUxFVkJRV3RDTEV0QlFVc3NUVUZCVEN4RFFVRTNRaXhEUVVRMlFqdHhRa0ZCTVVJN2FVSkJaRmc3TzBGQmJVSkJMRzlDUVVGSkxFOUJRVW9zUlVGQllUdEJRVU5VTEhkQ1FVRkpMRTFCUVUwc1UwRkJUaXhGUVVGcFFqdEJRVU5xUWl4blEwRkJVU3hKUVVGU0xFTkJRV0VzVFVGQlRTeFRRVUZPTEVOQlFXSXNRMEZFYVVJN2NVSkJRWEpDT3p0QlFVbEJMREJDUVVGTkxGTkJRVTRzUjBGQmEwSXNVVUZCVVN4SlFVRlNMRU5CUVdFc1IwRkJZaXhEUVVGc1FpeERRVXhUTzJsQ1FVRmlPenRCUVZGQkxIVkNRVUZQTEUxQlFVMHNVMEZCVGl4SFFVRnJRaXhQUVVGc1FpeEhRVUUwUWl4UlFVRlJMRmRCUVZJc1JVRkJOVUlzUTBFelEyMUNPMkZCUVRsQ08xTkJWbkZSTEVWQmQwUnVVU3hGUVVGRExHbENRVUZuUWl4RFFVRm9RaXhGUVhoRWFWRXNRMEZCU0N4RlFYZEVNVThzU1VGQlJ5eERRVUZETEZWQlFWTXNUMEZCVkN4RlFVRnBRaXhOUVVGcVFpeEZRVUYzUWl4UFFVRjRRaXhGUVVGblF6dEJRVU16UkN4blFrRkJTU3hWUVVGVkxGRkJRVkVzV1VGQlVpeERRVUZXTEVOQlJIVkVPMEZCUlRORUxHZENRVUZKTEZWQlFWVXNVVUZCVVN4WlFVRlNMRU5CUVZZc1EwRkdkVVE3UVVGSE0wUXNaMEpCUVVrc1YwRkJWeXhSUVVGUkxHRkJRVklzUTBGQldDeERRVWgxUkR0QlFVa3pSQ3huUWtGQlNTeFZRVUZWTEZGQlFWRXNXVUZCVWl4RFFVRldMRU5CU25WRU96dEJRVTB6UkN4dFFrRkJUeXhQUVVGUUxFZEJRV2xDTEZkQlFXcENMRU5CVGpKRU96dEJRVkV6UkN4eFFrRkJVeXhYUVVGVUxFTkJRWEZDTEVOQlFYSkNMRVZCUVhkQ0xFTkJRWGhDTEVWQlFUSkNPMEZCUTNaQ0xHOUNRVUZKTEZsQlFWa3NRMEZCV2l4RFFVUnRRanRCUVVWMlFpeHZRa0ZCU1N4WlFVRlpMRU5CUVZvc1EwRkdiVUk3TzBGQlNYWkNMRzlDUVVGSkxGRkJRVkVzUTBGQlVpeERRVUZLTEVWQlFXZENPMEZCUTFvc1owTkJRVmtzV1VGQldTeERRVUZhTEVWQlFXVXNRMEZCWml4RFFVRmFMRU5CUkZrN2FVSkJRV2hDT3p0QlFVbEJMRzlDUVVGSkxGRkJRVkVzUTBGQlVpeERRVUZLTEVWQlFXZENPMEZCUTFvc1owTkJRVmtzV1VGQldTeERRVUZhTEVWQlFXVXNTVUZCWml4RFFVRmFMRU5CUkZrN2FVSkJRV2hDT3p0QlFVbEJMSFZDUVVGUE8wRkJRMGdzZFVKQlFVY3NVMEZCU0R0QlFVTkJMSFZDUVVGSExGTkJRVWc3YVVKQlJrb3NRMEZhZFVJN1lVRkJNMEk3TzBGQmEwSkJMSEZDUVVGVExGZEJRVlFzUTBGQmNVSXNTMEZCY2tJc1JVRkJORUlzVVVGQk5VSXNSVUZCYzBNN1FVRkRiRU1zYjBKQlFVa3NaMEpCUVdkQ0xFMUJRVTBzUzBGQlRpeERRVVJqT3p0QlFVZHNReXh2UWtGQlNTeERRVUZETEdGQlFVUXNSVUZCWjBJN1FVRkRhRUlzYjBOQlFXZENMRTFCUVUwc1MwRkJUaXhIUVVGakxFMUJRVTBzVFVGQlRpeERRVUZoTEZGQlFXSXNRMEZCWkN4RFFVUkJPMmxDUVVGd1FqczdRVUZKUVN4dlFrRkJTU3hGUVVGRkxGRkJRVkVzWVVGQlVpeExRVU5GTEZGQlFWRXNZVUZCVWl4RFFVUkdMRWxCUlVVc1UwRkJVeXhoUVVGVUxFTkJSa1lzUTBGQlJpeEZRVVU0UWp0QlFVTTVRaXd3UWtGQlRTeEpRVUZKTEV0QlFVb3NRMEZCVlN4dFEwRkJWaXhEUVVGT0xFTkJSRGhDTzJsQ1FVWnNRenM3UVVGTlFTeDFRa0ZCVHl4aFFVRlFMRU5CWW10RE8yRkJRWFJETzFOQk1VSXlRaXhGUVRCRGVrSXNSVUZCUXl4alFVRmhMRVZCUVdJc1JVRkJaMElzWTBGQllTeEZRVUZpTEVWQlFXZENMR05CUVdFc1JVRkJZaXhGUVVGblFpeGxRVUZqTEVWQlFXUXNSVUV4UTNwQ0xFTkJRVWdzUlVFd1F5dERMRWxCUVVjc1EwRkJReXhWUVVGVExFOUJRVlFzUlVGQmFVSXNUVUZCYWtJc1JVRkJkMElzVDBGQmVFSXNSVUZCWjBNN1FVRkRNVWNzYlVKQlFVOHNUMEZCVUN4SFFVRnBRaXhQUVVGcVFpeERRVVF3UnpzN1FVRkhNVWNzY1VKQlFWTXNUMEZCVkN4RFFVRnBRaXhEUVVGcVFpeEZRVUZ2UWp0QlFVTm9RaXgxUWtGQlR5eExRVUZMTEVWQlFVVXNTVUZCUml4TFFVRlhMRTlCUVZnc1EwRkVTVHRoUVVGd1FqdFRRVWd3UlN4RlFVOTRSU3hGUVZCMVJTeERRVUZJTEVWQlQyaEZMRWxCUVVjc1EwRkJReXhWUVVGVExFOUJRVlFzUlVGQmFVSXNUVUZCYWtJc1JVRkJkMElzVDBGQmVFSXNSVUZCWjBNN1FVRkRNVU1zYlVKQlFVOHNUMEZCVUN4SFFVRnBRaXhOUVVGcVFpeERRVVF3UXpzN1FVRkhNVU1zY1VKQlFWTXNUVUZCVkN4RFFVRm5RaXhKUVVGb1FpeEZRVUZ6UWp0QlFVTnNRaXgxUWtGQlR5eFRRVU5LTEU5QlFVOHNTMEZCU3l4SlFVRk1MRXRCUVdNc1ZVRkJja0lzU1VGQmJVTXNRMEZCUXl4TFFVRkxMR05CUVV3c1EwRkJiMElzVFVGQmNFSXNRMEZCUkN4SlFVTnVReXhQUVVGUExFdEJRVXNzVFVGQlRDeExRVUZuUWl4VlFVRjJRaXhKUVVGeFF5eERRVUZETEV0QlFVc3NZMEZCVEN4RFFVRnZRaXhSUVVGd1FpeERRVUZFTEVOQlJtcERMRU5CUkZjN1lVRkJkRUk3VTBGSVZTeEZRVk5TTEVWQlZFOHNRMEZCU0N4RlFWTkJMRWxCUVVjc1EwRkJReXhWUVVGVExFOUJRVlFzUlVGQmFVSXNUVUZCYWtJc1JVRkJkMElzVDBGQmVFSXNSVUZCWjBNN1FVRkRNVU1zWjBKQlFVa3NWVUZCVlN4UlFVRlJMRmRCUVZJc1EwRkJWaXhEUVVSelF6czdRVUZITVVNc2JVSkJRVThzVDBGQlVDeEhRVUZwUWl4aFFVRnFRaXhEUVVnd1F6czdRVUZMTVVNc2NVSkJRVk1zWVVGQlZDeERRVUYxUWl4RFFVRjJRaXhGUVVFd1FqdEJRVU4wUWl4MVFrRkJUeXhMUVVGTExFVkJRVVVzU1VGQlJpeExRVUZYTEdGQlFWZ3NTVUZCTkVJc1JVRkJSU3hQUVVGR0xFdEJRV01zVDBGQlpDeERRVVJzUWp0aFFVRXhRanRUUVV4VkxFVkJVMUlzUlVGQlF5eGhRVUZaTEVWQlFWb3NSVUZVVFN4RFFVRklMRVZCVTJNc1NVRkJSeXhEUVVGRExGVkJRVk1zVDBGQlZDeEZRVUZwUWl4TlFVRnFRaXhGUVVGM1FpeFBRVUY0UWl4RlFVRm5RenRCUVVONFJDeG5Ra0ZCU1N4VlFVRlZMRkZCUVZFc1YwRkJVaXhEUVVGV0xFTkJSRzlFT3p0QlFVZDRSQ3h0UWtGQlR5eFBRVUZRTEVkQlFXbENMR0ZCUVdwQ0xFTkJTSGRFT3p0QlFVdDRSQ3h4UWtGQlV5eGhRVUZVTEVOQlFYVkNMRU5CUVhaQ0xFVkJRVEJDTzBGQlEzUkNMSFZDUVVGUExFdEJRVXNzUlVGQlJTeEpRVUZHTEV0QlFWY3NZVUZCV0N4SlFVRTBRaXhGUVVGRkxFOUJRVVlzUzBGQll5eFBRVUZrTEVOQlJHeENPMkZCUVRGQ08xTkJUSGRDTEVWQlUzUkNMRVZCUVVNc1lVRkJXU3hGUVVGYUxFVkJWRzlDTEVOQlFVZ3NSVUZUUVN4SlFVRkhMRU5CUVVNc1ZVRkJVeXhQUVVGVUxFVkJRV2xDTEUxQlFXcENMRVZCUVhkQ0xFOUJRWGhDTEVWQlFXZERPMEZCUTNoRUxHMUNRVUZQTEU5QlFWQXNSMEZCYVVJc1VVRkJha0lzUTBGRWQwUTdPMEZCUjNoRUxIRkNRVUZUTEZGQlFWUXNRMEZCYTBJc1EwRkJiRUlzUlVGQmNVSTdRVUZEYWtJc2RVSkJRVThzUzBGQlN5eEZRVUZGTEVsQlFVWXNTMEZCVnl4UlFVRllMRU5CUkVzN1lVRkJja0k3VTBGSWQwSXNSVUZQZEVJc1JVRlFjVUlzUTBGQlNDeEZRVTlrTEVsQlFVY3NRMEZCUXl4VlFVRlRMRTlCUVZRc1JVRkJhVUlzVFVGQmFrSXNSVUZCZDBJc1QwRkJlRUlzUlVGQlowTTdRVUZETVVNc2JVSkJRVThzVDBGQlVDeEhRVUZwUWl4SFFVRnFRaXhEUVVRd1F6dFRRVUZvUXl4RlFVZFNMRVZCU0U4c1EwRkJTQ3hGUVVkQkxFbEJRVWNzUTBGQlF5eFZRVUZUTEU5QlFWUXNSVUZCYVVJc1RVRkJha0lzUlVGQmQwSXNUMEZCZUVJc1JVRkJaME03UVVGRE1VTXNaMEpCUVVrc1ZVRkJWU3hSUVVGUkxGZEJRVklzUTBGQlZpeERRVVJ6UXp0QlFVVXhReXhuUWtGQlNTeFZRVUZWTEZGQlFWRXNXVUZCVWl4RFFVRldMRU5CUm5ORE8wRkJSekZETEdkQ1FVRkpMRmRCUVZjc1VVRkJVU3hoUVVGU0xFTkJRVmdzUTBGSWMwTTdRVUZKTVVNc1owSkJRVWtzVlVGQlZTeFJRVUZSTEZsQlFWSXNRMEZCVml4RFFVcHpRenRCUVVzeFF5eG5Ra0ZCU1N4VlFVRlZMRkZCUVZFc1dVRkJVaXhEUVVGV0xFTkJUSE5ET3p0QlFVOHhReXh0UWtGQlR5eFBRVUZRTEVkQlFXbENMRmRCUVdwQ0xFTkJVREJET3p0QlFWTXhReXhuUWtGQlNTeGxRVUZsTEVWQlFXWXNRMEZVYzBNN1FVRlZNVU1zWjBKQlFVa3NZVUZCWVN4RlFVRmlMRU5CVm5ORE96dEJRVmt4UXl4eFFrRkJVeXhYUVVGVUxFTkJRWEZDTEU5QlFYSkNMRVZCUVRoQ0xGVkJRVGxDTEVWQlFUQkRMRkZCUVRGRExFVkJRVzlFTEVkQlFYQkVMRVZCUVhsRUxGTkJRWHBFTEVWQlFXOUZPMEZCUTJoRkxIRkNRVUZMTEU5QlFVd3NSMEZCWlN4UFFVRm1MRU5CUkdkRk8wRkJSV2hGTEhGQ1FVRkxMRlZCUVV3c1IwRkJhMElzWTBGQll5eFpRVUZrTEVOQlJqaERPMEZCUjJoRkxIRkNRVUZMTEZGQlFVd3NSMEZCWjBJc1dVRkJXU3hWUVVGYUxFTkJTR2RFTzBGQlNXaEZMSEZDUVVGTExFZEJRVXdzUjBGQlZ5eFBRVUZQTEVsQlFWQXNSMEZCWXl4UFFVRlBMRWRCUVZBc1EwRkJaQ3hIUVVFMFFpeFRRVUUxUWl4RFFVcHhSRHRCUVV0b1JTeHhRa0ZCU3l4VFFVRk1MRWRCUVdsQ0xFOUJRVkVzVTBGQlVDeExRVUZ4UWl4UlFVRnlRaXhIUVVGcFF5eFRRVUZzUXl4SFFVRTRReXhKUVVFNVF5eERRVXdyUXpzN1FVRlBhRVVzYjBKQlFVa3NVVUZCVVN4UlFVRkRMRWxCUVZrc1UwRkJVeXhOUVVGVUxFbEJRVzlDTEVOQlFXcERMRU5CVUc5RU8wRkJVV2hGTEc5Q1FVRkpMR05CUVdNc1EwRkJaQ3hEUVZJMFJEdEJRVk5vUlN4dlFrRkJTU3hoUVVGaExFdEJRV0lzUTBGVU5FUTdRVUZWYUVVc2IwSkJRVWtzV1VGQldTeExRVUZhTEVOQlZqUkVPMEZCVjJoRkxHOUNRVUZKTEd0Q1FVRnJRaXhMUVVGc1FpeERRVmcwUkR0QlFWbG9SU3h2UWtGQlNTeExRVUZLTEVOQldtZEZPenRCUVdOb1JTeHhRa0ZCU3l4SlFVRkpMRkZCUVVvc1NVRkJaMElzVlVGQmNrSXNSVUZCYVVNN1FVRkROMElzZDBKQlFVa3NWMEZCVnl4alFVRllMRU5CUVRCQ0xGRkJRVEZDTEVOQlFVb3NSVUZCZVVNN1FVRkRja01zTkVKQlFVa3NWMEZCVnl4WFFVRlhMRkZCUVZnc1EwRkJXQ3hEUVVScFF6dEJRVVZ5UXl3MFFrRkJTU3hSUVVGUkxGRkJRVklzUzBGQmNVSXNVMEZCVXl4TlFVRlVMRVZCUVdsQ08wRkJRM1JETEdkRFFVRkpMRU5CUVVNc1MwRkJSQ3hGUVVGUk8wRkJRMUlzZDBOQlFWRXNSVUZCVWl4RFFVUlJPelpDUVVGYU96dEJRVWxCTEd0RFFVRk5MRkZCUVU0c1NVRkJhMElzVVVGQmJFSXNRMEZNYzBNN2VVSkJRVEZETzNGQ1FVWktPMmxDUVVSS096dEJRV0ZCTEhGQ1FVRkxMRWxCUVVrc1NVRkJTU3hEUVVGS0xFVkJRVThzU1VGQlNTeExRVUZLTEVWQlFWY3NSMEZCTTBJc1JVRkJaME03UVVGRE5VSXNkMEpCUVVrc1VVRkJVU3hUUVVGVExFTkJRVlFzUTBGQlVpeERRVVIzUWp0QlFVVTFRaXgzUWtGQlNTeFJRVUZSTEV0QlFWSXNRMEZCU2l4RlFVRnZRanRCUVVOb1FpeDFRMEZCWlN4TlFVRk5MRXRCUVU0c1NVRkJaU3hEUVVGbUxFTkJSRU03TzBGQlIyaENMRFJDUVVGSkxFTkJRVU1zVlVGQlJDeEpRVUZsTEUxQlFVMHNWVUZCVGl4RlFVRnJRanRCUVVOcVF5eDVRMEZCWVN4SlFVRmlMRU5CUkdsRE8zbENRVUZ5UXpzN1FVRkpRU3cwUWtGQlNTeERRVUZETEZOQlFVUXNTVUZCWXl4TlFVRk5MRk5CUVU0c1JVRkJhVUk3UVVGREwwSXNkME5CUVZrc1NVRkJXaXhEUVVRclFqdDVRa0ZCYmtNN08wRkJTVUVzTkVKQlFVa3NRMEZCUXl4bFFVRkVMRXRCUVhGQ0xFMUJRVTBzUzBGQlRpeEpRVUZsTEUxQlFVMHNaVUZCVGl4RFFVRndReXhGUVVFMFJEdEJRVU0xUkN3NFEwRkJhMElzU1VGQmJFSXNRMEZFTkVRN2VVSkJRV2hGTzNGQ1FWaEtMRTFCWTA4c1NVRkJTU3hEUVVGRExGVkJRVVFzU1VGQlpTeFRRVUZUTEV0QlFWUXNRMEZCWml4RlFVRm5RenRCUVVOMlF5dzBRa0ZCU1N4UFFVRlBMRTFCUVUwc1QwRkJUaXhMUVVGclFpeFZRVUY2UWl4RlFVRnhRenRCUVVOeVF5eDVRMEZCWVN4SlFVRmlMRU5CUkhGRE8zbENRVUY2UXp0eFFrRkVSeXhOUVVsQkxFbEJRVWtzUTBGQlF5eFRRVUZFTEVsQlFXTXNVVUZCVVN4TFFVRlNMRU5CUVdRc1JVRkJPRUk3UVVGRGNrTXNiME5CUVZrc1NVRkJXaXhEUVVSeFF6dHhRa0ZCYkVNN2FVSkJjRUpZT3p0QlFYbENRU3h4UWtGQlN5eExRVUZNTEVkQlFXRXNVVUZCVVN4WFFVRlNMRU5CY0VSdFJEdEJRWEZFYUVVc2NVSkJRVXNzVlVGQlRDeEhRVUZyUWl4VlFVRnNRaXhEUVhKRVowVTdRVUZ6UkdoRkxIRkNRVUZMTEZOQlFVd3NSMEZCYVVJc1UwRkJha0lzUTBGMFJHZEZPMEZCZFVSb1JTeHhRa0ZCU3l4TFFVRk1MRWRCUVdFc1MwRkJZaXhEUVhaRVowVTdRVUYzUkdoRkxIRkNRVUZMTEdWQlFVd3NSMEZCZFVJc1pVRkJka0lzUTBGNFJHZEZPMkZCUVhCRk96dEJRVEpFUVN4M1FrRkJXU3hUUVVGYUxFTkJRWE5DTEU5QlFYUkNMRWRCUVdkRExFOUJRV2hETEVOQmRrVXdRenRCUVhkRk1VTXNkMEpCUVZrc1UwRkJXaXhEUVVGelFpeEpRVUYwUWl4SFFVRTJRaXhoUVVFM1FpeERRWGhGTUVNN1UwRkJhRU1zUlVFd1JWSXNSVUZCUXl4alFVRmhMRVZCUVdJc1JVRkJaMElzWTBGQllTeEZRVUZpTEVWQlFXZENMR05CUVdFc1JVRkJZaXhGUVVGblFpeGxRVUZqTEVWQlFXUXNSVUZCYVVJc1lVRkJXU3hGUVVGYUxFVkJNVVV6UkN4RFFVRklMRVZCTUVVclJTeEpRVUZITEVOQlFVTXNWVUZCVXl4UFFVRlVMRVZCUVdsQ0xFMUJRV3BDTEVWQlFYZENMRTlCUVhoQ0xFVkJRV2RETzBGQlEzcElMR2RDUVVGSkxGVkJRVlVzVVVGQlVTeFhRVUZTTEVOQlFWWXNRMEZFY1VnN08wRkJSM3BJTEhsQ1FVRmhMRWxCUVdJc1IwRkJiMElzUTBGQmNFSXNRMEZJZVVnN1FVRkpla2dzZVVKQlFXRXNTMEZCWWl4SFFVRnhRaXhEUVVGeVFpeERRVXA1U0R0QlFVdDZTQ3g1UWtGQllTeExRVUZpTEVkQlFYRkNMRU5CUVhKQ0xFTkJUSGxJTzBGQlRYcElMSGxDUVVGaExFMUJRV0lzUjBGQmMwSXNRMEZCZEVJc1EwRk9lVWc3UVVGUGVrZ3NlVUpCUVdFc1MwRkJZaXhIUVVGeFFpeERRVUZ5UWl4RFFWQjVTRHRCUVZGNlNDeDVRa0ZCWVN4TFFVRmlMRWRCUVhGQ0xFTkJRWEpDTEVOQlVubElPMEZCVTNwSUxIbENRVUZoTEUxQlFXSXNSMEZCYzBJc1EwRkJkRUlzUTBGVWVVZzdRVUZWZWtnc2VVSkJRV0VzVFVGQllpeEhRVUZ6UWl4RFFVRjBRaXhEUVZaNVNEdEJRVmQ2U0N4NVFrRkJZU3hMUVVGaUxFZEJRWEZDTEVOQlFYSkNMRU5CV0hsSU96dEJRV0Y2U0N4dFFrRkJUeXhQUVVGUUxFZEJRV2xDTEZsQlFXcENMRU5CWW5sSU96dEJRV1Y2U0N4eFFrRkJVeXhaUVVGVUxFTkJRWE5DTEVsQlFYUkNMRVZCUVRSQ0xFdEJRVFZDTEVWQlFXMURMRXRCUVc1RExFVkJRVEJETzBGQlEzUkRMSEZDUVVGTExFbEJRVXdzUjBGQldTeFBRVUZQTEVsQlFWQXNRMEZCV2l4RFFVUnpRenRCUVVWMFF5eHhRa0ZCU3l4TFFVRk1MRWRCUVdFc1MwRkJZaXhEUVVaelF6dEJRVWQwUXl4eFFrRkJTeXhMUVVGTUxFZEJRV0VzUzBGQllpeERRVWh6UXp0aFFVRXhRenM3UVVGTlFTeDVRa0ZCWVN4VFFVRmlMRU5CUVhWQ0xFOUJRWFpDTEVkQlFXbERMRTlCUVdwRExFTkJja0o1U0R0QlFYTkNla2dzZVVKQlFXRXNVMEZCWWl4RFFVRjFRaXhKUVVGMlFpeEhRVUU0UWl4alFVRTVRaXhEUVhSQ2VVZzdVMEZCYUVNc1JVRjNRblpHTEVWQlFVTXNZVUZCV1N4RlFVRmFMRVZCZUVKeFJpeERRVUZJTEVWQmQwSnFSU3hKUVVGSExFTkJRVU1zVlVGQlV5eFBRVUZVTEVWQlFXbENMRTFCUVdwQ0xFVkJRWGRDTEU5QlFYaENMRVZCUVdkRE8wRkJRM2hFTEdkQ1FVRkpMRlZCUVZVc1VVRkJVU3hYUVVGU0xFTkJRVllzUTBGRWIwUTdPMEZCUjNoRUxHMUNRVUZQTEU5QlFWQXNSMEZCYVVJc1YwRkJha0lzUTBGSWQwUTdPMEZCUzNoRUxIRkNRVUZUTEZkQlFWUXNRMEZCY1VJc1NVRkJja0lzUlVGQk1rSTdRVUZEZGtJc2NVSkJRVXNzU1VGQlRDeEhRVUZaTEU5QlFVOHNTVUZCVUN4RFFVRmFMRU5CUkhWQ08yRkJRVE5DT3p0QlFVbEJMSGRDUVVGWkxGTkJRVm9zUTBGQmMwSXNUMEZCZEVJc1IwRkJaME1zVDBGQmFFTXNRMEZVZDBRN1FVRlZlRVFzZDBKQlFWa3NVMEZCV2l4RFFVRnpRaXhKUVVGMFFpeEhRVUUyUWl4aFFVRTNRaXhEUVZaM1JEdFRRVUZvUXl4RlFWbDBRaXhGUVVGRExHRkJRVmtzUlVGQldpeEZRVnB2UWl4RFFVRklMRVZCV1VFc1NVRkJSeXhEUVVGRExGVkJRVk1zVDBGQlZDeEZRVUZwUWl4TlFVRnFRaXhGUVVGM1FpeFBRVUY0UWl4RlFVRm5RenRCUVVONFJDeG5Ra0ZCU1N4WFFVRlhMRkZCUVZFc1YwRkJVaXhEUVVGWUxFTkJSRzlFTzBGQlJYaEVMR2RDUVVGSkxGTkJRVk1zVVVGQlVTeHRRa0ZCVWl4RFFVRlVMRU5CUm05RU96dEJRVWw0UkN4dFFrRkJUeXhQUVVGUUxFZEJRV2xDTEZOQlFXcENMRU5CU25kRU96dEJRVTE0UkN4eFFrRkJVeXhUUVVGVUxFTkJRVzFDTEVOQlFXNUNMRVZCUVhOQ0xFTkJRWFJDTEVWQlFYbENPMEZCUTNKQ0xHOUNRVUZKTEVsQlFVb3NRMEZFY1VJN08wRkJSM0pDTEhGQ1FVRkxMRWxCUVVrc1NVRkJTaXhKUVVGWkxFTkJRV3BDTEVWQlFXOUNPMEZCUTJoQ0xIZENRVUZKTEVWQlFVVXNVVUZCVVN4RFFVRlNMRU5CUVVZc1JVRkJZenRCUVVOa0xDdENRVUZQTEZGQlFWRXNSVUZCVWl4RFFVUlBPMEZCUldRc05rSkJRVXNzU1VGQlRDeEpRVUZoTEZOQlFXSXNRMEZHWXp0eFFrRkJiRUk3TzBGQlMwRXNkMEpCUVVrc1UwRkJVeXhGUVVGRkxFbEJRVVlzUTBGQlZDeERRVTVaTzBGQlQyaENMSGRDUVVGSkxGTkJRVk1zUlVGQlJTeEpRVUZHTEVOQlFWUXNRMEZRV1RzN1FVRlRhRUlzZDBKQlFVa3NWMEZCVnl4TlFVRllMRVZCUVcxQ08wRkJRMjVDTEdsRFFVUnRRanR4UWtGQmRrSXNUVUZGVHl4SlFVRkpMRk5CUVZNc1RVRkJWQ3hMUVVGdlFpeFRRVUZUTEUxQlFWUXNRMEZCY0VJc1JVRkJjME03UVVGRE4wTXNORUpCUVVrc1lVRkJZU3hOUVVGaUxFMUJRWGxDTEdGQlFXRXNUVUZCWWl4RFFVRjZRaXhGUVVFclF6dEJRVU12UXl4dFEwRkJUeXhSUVVGUkxFVkJRVklzUTBGRWQwTTdRVUZGTDBNc2FVTkJRVXNzU1VGQlRDeEpRVUZoTEUxQlFXSXNRMEZHSzBNN2VVSkJRVzVFTEUxQlIwOHNTVUZCU1N4UFFVRlBMRTFCUVZBc1EwRkJTaXhGUVVGdlFqdEJRVU4wUWl4dFEwRkJUeXhSUVVGUkxFVkJRVklzUTBGRVpUdEJRVVYwUWl4cFEwRkJTeXhKUVVGTUxFbEJRV0VzVFVGQllpeERRVVp6UWp0NVFrRkJjRUlzVFVGSFFUdEJRVU5JTEdkRFFVRkpMR0ZCUVdFc1ZVRkJWU3hOUVVGV0xFVkJRV3RDTEUxQlFXeENMRU5CUVdJc1EwRkVSRHRCUVVWSUxHZERRVUZKTEZWQlFVb3NSVUZCWjBJN1FVRkRXaXgxUTBGQlR5eFJRVUZSTEVWQlFWSXNRMEZFU3p0QlFVVmFMSEZEUVVGTExFbEJRVXdzU1VGQllTeFZRVUZpTEVOQlJsazdOa0pCUVdoQ08zbENRVXhITzNGQ1FVcEtMRTFCWTBFN1FVRkRTQ3dyUWtGQlR5eFJRVUZSTEVWQlFWSXNRMEZFU2p0QlFVVklMRFpDUVVGTExFbEJRVXdzU1VGQllTeE5RVUZpTEVOQlJrYzdjVUpCWkVFN2FVSkJXRmc3TzBGQkswSkJMSEZDUVVGTExFbEJRVWtzU1VGQlNpeEpRVUZaTEVOQlFXcENMRVZCUVc5Q08wRkJRMmhDTEhkQ1FVRkpMRVZCUVVVc1VVRkJVU3hEUVVGU0xFTkJRVVlzUlVGQll6dEJRVU5rTEN0Q1FVRlBMRkZCUVZFc1JVRkJVaXhEUVVSUE8wRkJSV1FzTmtKQlFVc3NTVUZCVEN4SlFVRmhMRVZCUVVVc1NVRkJSaXhEUVVGaUxFTkJSbU03Y1VKQlFXeENPMmxDUVVSS096dEJRVTlCTEhWQ1FVRlBMRWxCUVZBc1EwRjZRM0ZDTzJGQlFYcENPenRCUVRSRFFTeHhRa0ZCVXl4WlFVRlVMRU5CUVhOQ0xFdEJRWFJDTEVWQlFUWkNPMEZCUXpOQ0xHOUNRVUZKTEU5QlFVOHNZMEZCVUN4RlFVRjFRanRCUVVONlFpd3lRa0ZCVHl4UFFVRlBMR05CUVZBc1EwRkJjMElzUzBGQmRFSXNRMEZCVUN4RFFVUjVRanRwUWtGQk0wSXNUVUZGVHl4SlFVRkpMRTFCUVUwc1UwRkJUaXhGUVVGcFFqdEJRVU14UWl3eVFrRkJUeXhOUVVGTkxGTkJRVTRzUTBGRWJVSTdhVUpCUVhKQ0xFMUJSVUVzU1VGQlNTeE5RVUZOTEZkQlFVNHNSVUZCYlVJN1FVRkROVUlzTWtKQlFVOHNUVUZCVFN4WFFVRk9MRU5CUVd0Q0xGTkJRV3hDTEVOQlJIRkNPMmxDUVVGMlFqdGhRVXhVTzFOQmJFUjNRaXhGUVRSRWRFSXNSVUZCUXl4eFFrRkJiMElzUlVGQmNFSXNSVUZCZFVJc1lVRkJXU3hGUVVGYUxFVkJOVVJJTEVOQlFVZ3NSVUUwUkhWQ0xFbEJRVWNzUTBGQlF5eFZRVUZUTEU5QlFWUXNSVUZCYVVJc1RVRkJha0lzUlVGQmQwSXNUMEZCZUVJc1JVRkJaME03UVVGREwwVXNaMEpCUVVrc1ZVRkJWU3hSUVVGUkxGbEJRVklzUTBGQlZpeERRVVF5UlRzN1FVRkhMMFVzWjBKQlFVa3NVMEZCVXl4UlFVRlJMR2xDUVVGU0xFTkJRVlFzUTBGSU1rVTdRVUZKTDBVc1owSkJRVWtzVlVGQlZTeFJRVUZSTEcxQ1FVRlNMRU5CUVZZc1EwRktNa1U3UVVGTEwwVXNaMEpCUVVrc1ZVRkJWU3hSUVVGUkxHMUNRVUZTTEVOQlFWWXNRMEZNTWtVN1FVRk5MMFVzWjBKQlFVa3NWMEZCVnl4UlFVRlJMRzlDUVVGU0xFTkJRVmdzUTBGT01rVTdRVUZQTDBVc1owSkJRVWtzVlVGQlZTeFJRVUZSTEcxQ1FVRlNMRU5CUVZZc1EwRlFNa1U3UVVGUkwwVXNaMEpCUVVrc1kwRkJZeXhSUVVGUkxIVkNRVUZTTEVOQlFXUXNRMEZTTWtVN08wRkJWUzlGTEdkQ1FVRkpMRmxCUVZrc1VVRkJVU3hqUVVGU0xFTkJRVm9zUTBGV01rVTdPMEZCV1M5RkxHMUNRVUZQTEU5QlFWQXNSMEZCYVVJc1NVRkJha0lzUTBGYUswVTdPMEZCWXk5RkxIRkNRVUZUTEVsQlFWUXNRMEZCWXl4RFFVRmtMRVZCUVdsQ0xFTkJRV3BDTEVWQlFXOUNPMEZCUTJoQ0xHOUNRVUZKTEZGQlFWRXNSVUZCUlN4SFFVRkhMRU5CUVVnc1JVRkJWaXhEUVVSWk8wRkJSV2hDTEhGQ1FVRkxMRU5CUVV3c1JVRkJVU3hEUVVGU0xFVkJRVmNzUzBGQldDeEZRVUZyUWl4RFFVRnNRaXhGUVVablFqdEJRVWRvUWl4MVFrRkJUeXhMUVVGUUxFTkJTR2RDTzJGQlFYQkNPenRCUVUxQkxIRkNRVUZUTEVsQlFWUXNRMEZCWXl4RFFVRmtMRVZCUVdsQ0xFTkJRV3BDTEVWQlFXOUNMRXRCUVhCQ0xFVkJRVEpDTEV0QlFUTkNMRVZCUVd0RE8wRkJRemxDTEc5Q1FVRkpMRTFCUVUwc1EwRkJUaXhGUVVGVE8wRkJRMVFzTWtKQlJGTTdhVUpCUVdJN08wRkJTVUVzYjBKQlFVa3NVVUZCVVN4TlFVRk5MRXRCUVU0c1EwRkJVaXhEUVV3d1FqdEJRVTA1UWl4dlFrRkJTU3hoUVVGaExFdEJRV0lzUTBGT01FSTdPMEZCVVRsQ0xHOUNRVUZKTEZGQlFWRXNRMEZCVWl4TFFVRmpMRkZCUVZFc1EwRkJVaXhEUVVGa0xFVkJRVEJDTzBGQlF6RkNMREpDUVVGUExFTkJRVkFzUlVGQlZTeERRVUZXTEVWQlFXRXNTMEZCWWl4RlFVRnZRaXhMUVVGd1FpeEZRVVF3UWp0cFFrRkJPVUlzVFVGRlR5eEpRVUZKTEV0QlFVc3NTVUZCVEN4RlFVRlhPenM3T3p0QlFVdHNRaXgzUWtGQlNTeERRVUZETEZOQlFWTXNRMEZCVkN4RFFVRkVMRVZCUVdNN1FVRkRaQ3h0UTBGQlZ5eERRVUZZTEVWQlFXTXNTMEZCWkN4RlFVRnhRaXhMUVVGeVFpeEZRVVJqTzBGQlJXUXNaME5CUVZFc1RVRkJUU3hMUVVGT0xFTkJRVklzUTBGR1l6dHhRa0ZCYkVJN08wRkJTMEVzTkVKQlFWRXNXVUZCV1N4TFFVRmFMRVZCUVcxQ0xFbEJRVWtzVFVGQlNpeERRVUZYTEU5QlFVOHNUVUZCVUN4RlFVRmxMRU5CUVRGQ0xFVkJRVFpDTEVOQlFUZENMRU5CUVc1Q0xFTkJRVklzUTBGV2EwSTdhVUpCUVdZc1RVRlhRU3hKUVVGSkxGRkJRVkVzUTBGQlVpeERRVUZLTEVWQlFXZENPMEZCUTI1Q0xIZENRVUZKTEZGQlFWRXNRMEZCVWl4RFFVRktMRVZCUVdkQ08wRkJRMW9zTkVKQlFVa3NSVUZCUlN4UFFVRkdMRXRCUVdNc1JVRkJSU3hQUVVGR0xFbEJRMlFzUlVGQlJTeFRRVUZHTEV0QlFXZENMRVZCUVVVc1UwRkJSaXhKUVVOb1FpeEZRVUZGTEVkQlFVWXNTMEZCVlN4RlFVRkZMRWRCUVVZc1JVRkJUenRCUVVOcVFpeG5RMEZCU1N4aFFVRmhMRlZCUVZVc1JVRkJSU3hWUVVGR0xFVkJRV01zUlVGQlJTeFZRVUZHTEVOQlFYSkRMRU5CUkdFN1FVRkZha0lzWjBOQlFVa3NWVUZCU2l4RlFVRm5RanRCUVVOYUxIZERRVUZSTEZsQlFWa3NTMEZCV2l4RlFVTktMRWxCUVVrc1RVRkJTaXhEUVVGWExFOUJRVThzUzBGQlVDeEZRVUZqTEVOQlFYcENMRVZCUVRSQ0xGVkJRVFZDTEVOQlJFa3NRMEZCVWl4RFFVUlpPelpDUVVGb1FqdEJRVWxCTEc5RFFVRlJMR0ZCUVdFc1EwRkJZaXhGUVVGblFpeERRVUZvUWl4RlFVRnRRaXhMUVVGdVFpeEZRVUV3UWl4TFFVRXhRaXhGUVVGcFF5eExRVUZxUXl4RFFVRlNMRU5CVG1sQ08zbENRVVp5UWl4TlFWTlBPMEZCUTBnc2IwTkJRVkVzV1VGQldTeExRVUZhTEVWQlFXMUNMRWxCUVVrc1RVRkJTaXhEUVVGWExFOUJRVThzUzBGQlVDeEZRVUZqTEVOQlFYcENMRVZCUVRSQ0xFTkJRVFZDTEVOQlFXNUNMRU5CUVZJc1EwRkVSenRCUVVWSUxIbERRVUZoTEVsQlFXSXNRMEZHUnp0NVFrRlVVRHR4UWtGRVNpeE5RV05QTzBGQlEwZ3NaME5CUVZFc1dVRkJXU3hMUVVGYUxFVkJRVzFDTEVsQlFVa3NUVUZCU2l4RFFVRlhMRTlCUVU4c1MwRkJVQ3hGUVVGakxFTkJRWHBDTEVWQlFUUkNMRU5CUVRWQ0xFTkJRVzVDTEVOQlFWSXNRMEZFUnp0QlFVVklMSEZEUVVGaExFbEJRV0lzUTBGR1J6dHhRa0ZrVUR0cFFrRkVSeXhOUVcxQ1FTeEpRVUZKTEZGQlFWRXNRMEZCVWl4RFFVRktMRVZCUVdkQ08wRkJRMjVDTEhkQ1FVRkpMRU5CUVVNc1VVRkJVU3hEUVVGU0xFTkJRVVFzUlVGQllUdEJRVU5pTEdkRFFVRlJMRmxCUVZrc1MwRkJXaXhGUVVGdFFpeEpRVUZKTEUxQlFVb3NRMEZCVnl4UFFVRlBMRXRCUVZBc1JVRkJZeXhEUVVGNlFpeEZRVUUwUWl4RFFVRTFRaXhEUVVGdVFpeERRVUZTTEVOQlJHRTdRVUZGWWl4eFEwRkJZU3hKUVVGaUxFTkJSbUU3Y1VKQlFXcENMRTFCUjA4c1NVRkJTU3hGUVVGRkxFbEJRVVlzUzBGQlZ5eEZRVUZGTEVsQlFVWXNSVUZCVVR0QlFVTXhRaXhuUTBGQlVTeFpRVUZaTEV0QlFWb3NSVUZCYlVJc1NVRkJTU3hOUVVGS0xFTkJRVmNzVDBGQlR5eExRVUZRTEVWQlFXTXNRMEZCZWtJc1JVRkJORUlzUTBGQk5VSXNRMEZCYmtJc1EwRkJVaXhEUVVRd1FqdHhRa0ZCZGtJN2FVSkJTa29zVFVGUFFTeEpRVUZKTEZOQlFWTXNRMEZCVkN4RFFVRktMRVZCUVdsQ08wRkJRM0JDTEhkQ1FVRkpMRU5CUVVNc1UwRkJVeXhEUVVGVUxFTkJRVVFzUlVGQll6dEJRVU5rTEhGRFFVRmhMRWxCUVdJc1EwRkVZenR4UWtGQmJFSTdPMEZCU1VFc05FSkJRVkVzV1VGQldTeExRVUZhTEVWQlFXMUNMRWxCUVVrc1RVRkJTaXhEUVVGWExFOUJRVThzVFVGQlVDeEZRVUZsTEVOQlFURkNMRVZCUVRaQ0xFTkJRVGRDTEVOQlFXNUNMRU5CUVZJc1EwRk1iMEk3YVVKQlFXcENPenRCUVZGUUxHOUNRVUZKTEV0QlFVb3NSVUZCVnp0QlFVTlFMREJDUVVGTkxFdEJRVTRzU1VGQlpTeExRVUZtTEVOQlJFODdhVUpCUVZnN08wRkJTVUVzYjBKQlFVa3NWVUZCU2l4RlFVRm5RanRCUVVOYUxDdENRVUZYTEVOQlFWZ3NSVUZCWXl4TFFVRmtMRVZCUVhGQ0xFdEJRWEpDTEVWQlJGazdhVUpCUVdoQ08yRkJNMFJLT3p0QlFXZEZRU3h4UWtGQlV5eFpRVUZVTEVOQlFYTkNMRU5CUVhSQ0xFVkJRWGxDTEVOQlFYcENMRVZCUVRSQ0xFdEJRVFZDTEVWQlFXMURMRXRCUVc1RExFVkJRVEJETEV0QlFURkRMRVZCUVdsRU8wRkJRemRETEc5Q1FVRkpMRmxCUVZrc1JVRkJSU3hSUVVGR0xFTkJSRFpDTzBGQlJUZERMRzlDUVVGSkxHRkJRV0VzVVVGQlVTeFRRVUZTTEVWQlFXMUNMRVZCUVVVc1VVRkJSaXhEUVVGb1F5eERRVVo1UXp0QlFVYzNReXh2UWtGQlNTeFpRVUZaTEZkQlFWY3NVVUZCV0N4RFFVZzJRanM3UVVGTE4wTXNiMEpCUVVrc1QwRkJUeXhWUVVGVkxFMUJRVllzUTBGTWEwTTdRVUZOTjBNc2IwSkJRVWtzVDBGQlR5eFZRVUZWTEUxQlFWWXNRMEZPYTBNN1FVRlBOME1zYjBKQlFVa3NUVUZCVFN4UFFVRlBMRWxCUVZBc1IwRkJZeXhKUVVGa0xFZEJRWEZDTEVsQlFYSkNMRU5CVUcxRE96dEJRVk0zUXl4eFFrRkJTeXhKUVVGSkxFbEJRVWtzUTBGQlNpeEZRVUZQTEVsQlFVa3NSMEZCU2l4RlFVRlRMRWRCUVhwQ0xFVkJRVGhDTzBGQlF6RkNMSGRDUVVGSkxGZEJRVmNzVlVGQlZTeERRVUZXTEVOQlFWZ3NRMEZFYzBJN1FVRkZNVUlzZDBKQlFVa3NXVUZCV1N4VlFVRlZMRU5CUVZZc1EwRkJXaXhEUVVaelFqdEJRVWN4UWl3MlFrRkJVeXhEUVVGVUxFTkJTREJDT3p0QlFVc3hRaXgzUWtGQlNTeERRVUZETEZGQlFVUXNSVUZCVnp0QlFVTllMRFJDUVVGSkxGTkJRVW9zUlVGQlpUczdRVUZGV0N4dlEwRkJVU3haUVVGWkxFdEJRVm9zUlVGRFNpeEpRVUZKTEUxQlFVb3NRMEZCVnl4UFFVRlBMRTFCUVZBc1JVRkJaU3hKUVVFeFFpeEZRVUZuUXl4VFFVRm9ReXhEUVVSSkxFTkJRVklzUTBGR1Z6dDVRa0ZCWmp0eFFrRkVTaXhOUVUxUE8wRkJRMGdzTmtKQlFVc3NVVUZCVEN4RlFVRmxMRk5CUVdZc1JVRkJNRUlzUzBGQk1VSXNSVUZCYVVNc1MwRkJha01zUlVGRVJ6dHhRa0ZPVURzN1FVRlZRU3gzUWtGQlNTeFJRVUZSTEZGQlFWSXNTMEZCY1VJc1UwRkJVeXhMUVVGVUxFVkJRV2RDTzBGQlEzSkRMR2xEUVVGVExGTkJRVk1zUzBGQlZDeERRVVEwUWp0eFFrRkJla003YVVKQlprbzdPMEZCYjBKQkxHOUNRVUZKTEZkQlFWY3NTMEZCV0N4RlFVRnJRanM3UVVGRmJFSXNORUpCUVZFc1dVRkJXU3hMUVVGYUxFVkJRVzFDTEVsQlFVa3NUVUZCU2l4RFFVTjJRaXhQUVVGUExFdEJRVkFzUlVGRFFTeERRVVoxUWl4RlFVZDJRaXhYUVVGWExFdEJRVmdzUTBGSVNTeERRVUZTTEVOQlJtdENPMmxDUVVGMFFqczdRVUZUUVN4MVFrRkJUeXhMUVVGUUxFTkJkRU0yUXp0aFFVRnFSRHM3UVVGNVEwRXNjVUpCUVZNc1ZVRkJWQ3hEUVVGdlFpeExRVUZ3UWl4RlFVRXlRaXhMUVVFelFpeEZRVUZyUXl4TFFVRnNReXhGUVVGNVF6czdRVUZGY2tNc2RVSkJRVThzUzBGQlVDeEZRVUZqTEV0QlFXUXNSVUZCY1VJc1MwRkJja0lzUlVGR2NVTTdRVUZIY2tNc0swSkJRV1VzUzBGQlppeEZRVUZ6UWl4TFFVRjBRaXhGUVVFMlFpeExRVUUzUWl4RlFVaHhRenRoUVVGNlF6czdPenRCUVRkSUswVXNjVUpCY1VsMFJTeGpRVUZVTEVOQlFYZENMRXRCUVhoQ0xFVkJRU3RDTEV0QlFTOUNMRVZCUVhORExFdEJRWFJETEVWQlFUWkRPMEZCUTNwRExHOUNRVUZKTEZOQlFWTXNTMEZCVkN4RFFVRktMRVZCUVhGQ08wRkJRMnBDTEhkQ1FVRkpMRTlCUVU4c1RVRkJUU3hQUVVGT0xFdEJRV3RDTEZWQlFYcENMRVZCUVhGRE8wRkJRM0pETERoQ1FVRk5MRXRCUVU0c1NVRkJaU3haUVVOWUxFMUJRVTBzUzBGQlRpeERRVVJYTEVWQlJWZ3NTVUZCU1N4TlFVRktMRU5CUVZjc1QwRkJUeXhOUVVGUUxFVkJRV1VzUzBGQk1VSXNSVUZCYVVNc1NVRkJha01zUTBGR1Z5eERRVUZtTEVOQlJIRkRPM0ZDUVVGNlF6dHBRa0ZFU2l4TlFVOVBMRWxCUVVrc1VVRkJVU3hMUVVGU0xFMUJRVzFDTEUxQlFVMHNWVUZCVGl4SlFVRnZRaXhOUVVGTkxGTkJRVTRzUTBGQmRrTXNSVUZCZVVRN1FVRkRhRVVzZDBKQlFVa3NWMEZCVnl4TlFVRk5MRkZCUVU0c1EwRkVhVVE3UVVGRmFFVXNkMEpCUVVrc1RVRkJUU3hUUVVGVExFMUJRVlFzUTBGR2MwUTdRVUZIYUVVc2VVSkJRVXNzU1VGQlNTeEpRVUZKTEVOQlFVb3NSVUZCVHl4SlFVRkpMRWRCUVVvc1JVRkJVeXhIUVVGNlFpeEZRVUU0UWp0QlFVTXhRaXcwUWtGQlNTeFJRVUZSTEZOQlFWTXNRMEZCVkN4RFFVRlNMRU5CUkhOQ08wRkJSVEZDTEdsRFFVRlRMRU5CUVZRc1EwRkdNRUk3TzBGQlNURkNMSFZEUVVGbExFdEJRV1lzUlVGQmMwSXNTMEZCZEVJc1JVRkJOa0lzUzBGQk4wSXNSVUZLTUVJN08wRkJUVEZDTERSQ1FVRkpMRkZCUVZFc1MwRkJVaXhMUVVGclFpeE5RVUZOTEV0QlFVNHNSVUZCWVR0QlFVTXZRaXh4UTBGQlV5eE5RVUZOTEV0QlFVNHNRMEZFYzBJN2VVSkJRVzVETzNGQ1FVNUtPMmxDUVVoSExFMUJZVUVzU1VGQlNTeFJRVUZSTEV0QlFWSXNRMEZCU2l4RlFVRnZRanRCUVVOMlFpd3lRa0ZCVHl4TFFVRlFMRVZCUVdNc1NVRkJaQ3hGUVVGdlFpeExRVUZ3UWl4RlFVRXlRaXhMUVVFelFpeEZRVVIxUWp0cFFrRkJjRUk3WVVGeVFsZzdPenRCUVhKSkswVXNjVUpCWjB0MFJTeE5RVUZVTEVOQlFXZENMRU5CUVdoQ0xFVkJRVzFDTEVOQlFXNUNMRVZCUVhOQ0xFdEJRWFJDTEVWQlFUWkNMRXRCUVRkQ0xFVkJRVzlETzBGQlEyaERMRzlDUVVGSkxGRkJRVkVzV1VGQldTeERRVUZhTEVWQlFXVXNRMEZCWml4RFFVRlNMRU5CUkRSQ08wRkJSV2hETEc5Q1FVRkpMR0ZCUVdFc1MwRkJTeXhOUVVGTkxFTkJRVTRzUlVGQlV5eE5RVUZOTEVOQlFVNHNRMEZCTTBJc1EwRkdORUk3UVVGSGFFTXNiMEpCUVVrc1YwRkJWeXhWUVVGWUxFTkJRVW9zUlVGQk5FSTdRVUZEZUVJc01FSkJRVTBzUzBGQlRpeEpRVUZsTEVsQlFVa3NUVUZCU2l4RFFVRlhMRTlCUVU4c1MwRkJVQ3hGUVVGakxFbEJRWHBDTEVWQlFTdENMRlZCUVM5Q0xFTkJRV1lzUTBGRWQwSTdhVUpCUVRWQ08yRkJTRW83TzBGQlVVRXNjVUpCUVZNc1ZVRkJWQ3hEUVVGdlFpeExRVUZ3UWl4RlFVRXlRanRCUVVOMlFpeHhRa0ZCU3l4SlFVRkpMRXRCUVVvc1NVRkJZU3hMUVVGc1FpeEZRVUY1UWp0QlFVTnlRaXgzUWtGQlNTeFZRVUZWTEVkQlFWWXNSVUZCWlR0QlFVTm1MQ3RDUVVGUExFbEJRVkFzUTBGRVpUdHhRa0ZCYmtJN2FVSkJSRW83TzBGQlRVRXNkVUpCUVU4c1MwRkJVQ3hEUVZCMVFqdGhRVUV6UWpzN08wRkJlRXNyUlN4eFFrRnRUSFJGTEUxQlFWUXNRMEZCWjBJc1MwRkJhRUlzUlVGQmRVSXNTMEZCZGtJc1JVRkJPRUlzUzBGQk9VSXNSVUZCY1VNN1FVRkRha01zYjBKQlFVa3NVVUZCVVN4TFFVRlNMRU5CUVVvc1JVRkJiMEk3UVVGRGFFSXNkMEpCUVVrc1RVRkJUU3hMUVVGT0xFVkJRV0U3UVVGRFlpdzRRa0ZCVFN4TFFVRk9MRWxCUVdVc1dVRkRXQ3hOUVVGTkxFdEJRVTRzUTBGRVZ5eEZRVVZZTEVsQlFVa3NUVUZCU2l4RFFVTkpMRTlCUVU4c1MwRkJVQ3hGUVVOQkxFdEJSa29zUlVGSFNTeGpRVUZqTEUxQlFVMHNTMEZCVGl4RFFVaHNRaXhEUVVaWExFTkJRV1lzUTBGRVlUdHhRa0ZCYWtJN08wRkJWMEVzZDBKQlFVa3NUVUZCVFN4bFFVRk9MRWxCUVhsQ0xFMUJRVTBzVTBGQlRpeEZRVUZwUWp0QlFVTXhReXcwUWtGQlNTeFhRVUZYTEUxQlFVMHNVVUZCVGl4RFFVUXlRanRCUVVVeFF5dzBRa0ZCU1N4TlFVRk5MRk5CUVZNc1RVRkJWQ3hEUVVablF6dEJRVWN4UXl3MlFrRkJTeXhKUVVGSkxFbEJRVWtzUTBGQlNpeEZRVUZQTEVsQlFVa3NSMEZCU2l4RlFVRlRMRWRCUVhwQ0xFVkJRVGhDTzBGQlF6RkNMR2REUVVGSkxGRkJRVkVzVTBGQlV5eERRVUZVTEVOQlFWSXNRMEZFYzBJN1FVRkZNVUlzY1VOQlFWTXNRMEZCVkN4RFFVWXdRanM3UVVGSk1VSXNiVU5CUVU4c1MwRkJVQ3hGUVVGakxFdEJRV1FzUlVGQmNVSXNTMEZCY2tJc1JVRktNRUk3TzBGQlRURkNMR2REUVVGSkxGRkJRVkVzUzBGQlVpeExRVUZyUWl4TlFVRk5MRXRCUVU0c1JVRkJZVHRCUVVNdlFpeDVRMEZCVXl4TlFVRk5MRXRCUVU0c1EwRkVjMEk3TmtKQlFXNURPM2xDUVU1S08zRkNRVWhLTzJsQ1FWcEtMRTFCTUVKUExFbEJRVWtzVVVGQlVTeExRVUZTTEVOQlFVb3NSVUZCYjBJN1FVRkRka0lzTWtKQlFVOHNTMEZCVUN4RlFVRmpMRWxCUVdRc1JVRkJiMElzUzBGQmNFSXNSVUZCTWtJc1MwRkJNMElzUlVGRWRVSTdhVUpCUVhCQ08yRkJNMEpZT3p0QlFXZERRU3h4UWtGQlV5eGhRVUZVTEVOQlFYVkNMRWRCUVhaQ0xFVkJRVFJDTzBGQlEzaENMRzlDUVVGSkxGTkJRVk1zUlVGQlZDeERRVVJ2UWpzN1FVRkhlRUlzY1VKQlFVc3NTVUZCU1N4SFFVRktMRWxCUVZjc1IwRkJhRUlzUlVGQmNVSTdRVUZEYWtJc01rSkJRVThzUjBGQlVDeEpRVUZqTEZOQlFXUXNRMEZFYVVJN2FVSkJRWEpDT3p0QlFVbEJMSFZDUVVGUExFMUJRVkFzUTBGUWQwSTdZVUZCTlVJN096dEJRVzVPSzBVc2NVSkJPRTUwUlN4UFFVRlVMRU5CUVdsQ0xGTkJRV3BDTEVWQlFUUkNMRk5CUVRWQ0xFVkJRWFZET3p0QlFVVnVReXh2UWtGQlNTeGpRVUZqTEZOQlFWTXNVMEZCVkN4RFFVRmtMRU5CUml0Q08wRkJSMjVETEc5Q1FVRkpMRkZCUVZFc1dVRkJXU3hKUVVGYUxFTkJTSFZDTzBGQlNXNURMRzlDUVVGSkxGRkJRVkVzV1VGQldTeEpRVUZhTEVOQlNuVkNPenRCUVUxdVF5eHZRa0ZCU1N4TlFVRk5MRTFCUVU0c1MwRkJhVUlzVlVGQlZTeE5RVUZXTEVWQlFXdENPMEZCUTI1RExESkNRVUZQTzBGQlEwZ3NhME5CUVZVc1UwRkJWanRCUVVOQkxDdENRVUZQTEVsQlFWQTdjVUpCUmtvc1EwRkViVU03YVVKQlFYWkRPenM3UVVGT2JVTXNiMEpCWXk5Q0xHTkJRV01zVTBGQlV5eFRRVUZVTEVOQlFXUXNRMEZrSzBJN1FVRmxia01zYjBKQlFVa3NVVUZCVVN4WlFVRlpMRWxCUVZvc1EwRm1kVUk3UVVGblFtNURMRzlDUVVGSkxGRkJRVkVzV1VGQldTeEpRVUZhTEVOQmFFSjFRanM3UVVGclFtNURMRzlDUVVGSkxFMUJRVTBzVFVGQlRpeExRVUZwUWl4VlFVRlZMRTFCUVZZc1JVRkJhMEk3UVVGRGJrTXNNa0pCUVU4N1FVRkRTQ3hyUTBGQlZTeFRRVUZXTzBGQlEwRXNLMEpCUVU4c1NVRkJVRHR4UWtGR1NpeERRVVJ0UXp0cFFrRkJka003T3p0QlFXeENiVU1zYjBKQk1FSXZRaXhqUVVGakxFVkJRV1FzUTBFeFFpdENPenRCUVRSQ2JrTXNiMEpCUVVrc1dVRkJXU3hEUVVGYUxFTkJOVUlyUWp0QlFUWkNia01zYjBKQlFVa3NXVUZCV1N4TlFVRk5MRTFCUVU0c1EwRTNRbTFDTzBGQk9FSnVReXh2UWtGQlNTeGxRVUZsTEVOQlFXWTdPenM3UVVFNVFpdENMSEZDUVd0RE9VSXNTVUZCU1N4SlFVRkpMRU5CUVVvc1JVRkJVU3hKUVVGSkxGVkJRVlVzVFVGQlZpeEZRVUZyUWl4SFFVRjJReXhGUVVFMFF6dEJRVU40UXl4M1FrRkJTU3hSUVVGUkxGVkJRVlVzUTBGQlZpeERRVUZTTEVOQlJHOURPMEZCUlhoRExIZENRVUZKTEZOQlFVb3NRMEZHZDBNN08wRkJTWGhETEhkQ1FVRkpMRTFCUVUwc1IwRkJUaXhGUVVGWE8wRkJRMWdzTkVKQlFVa3NUVUZCVFN4alFVRk9MRU5CUVhGQ0xFMUJRVTBzUjBGQlRpeERRVUY2UWl4RlFVRnhRenM3UVVGRmFrTXNkME5CUVZrc1RVRkJUU3hOUVVGTkxFZEJRVTRzUTBGQmJFSXNRMEZHYVVNN1FVRkhha01zZDBOQlFWa3NTVUZCV2l4RFFVRnBRaXhWUVVGVkxGTkJRVllzUTBGQmFrSXNSVUZJYVVNN2VVSkJRWEpETEUxQlMwODdPMEZCUlVnc2QwTkJRVmtzU1VGQlNTeGpRVUZLTEVOQlJsUTdRVUZIU0N4M1EwRkJXU3hKUVVGYUxFTkJRV2xDTEVsQlFXcENMRVZCU0VjN2VVSkJURkE3Y1VKQlJFb3NUVUZYVHpzN1FVRkZTQ3cwUWtGQlNTeFpRVUZaTEZOQlFWb3NSVUZCZFVJN1FVRkRka0lzZDBOQlFWa3NUVUZCVFN4WFFVRk9MRU5CUVZvc1EwRkVkVUk3UVVGRmRrSXNkME5CUVZrc1NVRkJXaXhEUVVGcFFpeFZRVUZWTEZOQlFWWXNRMEZCYWtJc1JVRkdkVUk3ZVVKQlFUTkNMRTFCUjA4N096czdRVUZKU0N4M1EwRkJXU3hKUVVGSkxHTkJRVW9zUTBGS1ZEdEJRVXRJTEhkRFFVRlpMRWxCUVZvc1EwRkJhVUlzU1VGQmFrSXNSVUZNUnp0NVFrRklVRHR4UWtGaVNqdHBRa0ZLU2pzN1FVRTRRa0VzYjBKQlFVa3NaMEpCUVdkQ0xHRkJRV0VzVFVGQlRTeE5RVUZPTEVkQlF6ZENMRlZCUVZVc1RVRkJWaXhIUVVOQkxFMUJRVTBzVTBGQlRpeERRVVpuUWpzN096dEJRV2hGWlN4eFFrRnpSVGxDTEVsQlFVa3NTVUZCU1N4RFFVRktMRVZCUVU4c1NVRkJTU3hWUVVGVkxFMUJRVllzUlVGQmEwSXNSMEZCZEVNc1JVRkJNa003UVVGRGRrTXNkMEpCUVVrc1ZVRkJWU3hWUVVGVkxFTkJRVllzUTBGQlZpeERRVVJ0UXpzN1FVRkhka01zZDBKQlFVa3NVVUZCVVN4SFFVRlNMRVZCUVdFN1FVRkRZaXcwUWtGQlNTeERRVUZETEUxQlFVMHNZMEZCVGl4RFFVRnhRaXhSUVVGUkxFZEJRVklzUTBGQmRFSXNSVUZCYjBNN096czdRVUZKY0VNc2QwTkJRVmtzU1VGQldpeERRVUZwUWl4UFFVRnFRaXhGUVVwdlF6dDVRa0ZCZUVNN2NVSkJSRW9zVFVGUFR5eEpRVUZKTEV0QlFVc3NZVUZCVEN4RlFVRnZRanM3UVVGRk0wSXNiME5CUVZrc1NVRkJXaXhEUVVGcFFpeFBRVUZxUWl4RlFVWXlRanR4UWtGQmVFSTdhVUpCVmxnN08wRkJaMEpCTEc5Q1FVRkpMRmRCUVZjc1dVRkJXU3hMUVVGYUxFVkJRVmdzUTBGMFJpdENPMEZCZFVadVF5eHZRa0ZCU1N4blFrRkJaMElzUTBGQmFFSXNRMEYyUml0Q08wRkJkMFp1UXl4dlFrRkJTU3hWUVVGVkxFVkJRVllzUTBGNFJpdENPMEZCZVVadVF5eHZRa0ZCU1N4VlFVRlZMRVZCUVZZc1EwRjZSaXRDTzBGQk1FWnVReXh2UWtGQlNTeFpRVUZLTEVOQk1VWnRRenM3UVVFMFJtNURMSEZDUVVGTExFbEJRVWtzU1VGQlNTeERRVUZLTEVWQlFVOHNTVUZCU1N4VlFVRlZMRTFCUVZZc1IwRkJiVUk3UVVGRGJrTXNkMEpCUVVrc1lVRkJZU3hWUVVGVkxFTkJRVllzUTBGQllpeERRVVFyUWp0QlFVVnVReXh0UTBGQlpTeFRRVUZUTEdGQlFWUXNRMEZCWmpzN08wRkJSbTFETERKQ1FVczFRaXhwUWtGQmFVSXNTVUZCYWtJc1NVRkJlVUlzVTBGQlV5eE5RVUZVTEVWQlFXbENPMEZCUXpkRExHZERRVUZSTEVsQlFWSXNRMEZCWVN4UFFVRlBMRkZCUVZBc1JVRkJhVUlzWVVGQmFrSXNSVUZCWjBNc1NVRkJhRU1zUTBGQllpeEZRVVEyUXp0QlFVVTNReXgxUTBGQlpTeFRRVUZUTEdGQlFWUXNRMEZCWml4RFFVWTJRenR4UWtGQmFrUTdPMEZCUzBFc2QwSkJRVWtzUTBGQlF5eFpRVUZFTEVsQlFXbENMR0ZCUVdFc1IwRkJZaXhMUVVGeFFpeFhRVUZYTEVkQlFWZ3NSVUZCWjBJN08wRkJSWFJFTERSQ1FVRkpMRmRCUVZjc1IwRkJXQ3hGUVVGblFqdEJRVU5vUWl4blEwRkJTU3huUWtGQlowSXNZVUZCWVN4SFFVRmlMRVZCUVd0Q096dEJRVVZzUXl4dlEwRkJTU3hOUVVGTkxHRkJRV0VzUjBGQllpeERRVUZPTEV0QlFUUkNMRWxCUVVrc1EwRkJTaXhGUVVGUE8wRkJRMjVETERSRFFVRlJMRWxCUVZJc1EwRkJZU3hQUVVGUExGRkJRVkFzUlVGQmFVSXNZVUZCYWtJc1JVRkJaME1zWVVGQllTeEhRVUZpTEVOQlFUZERMRVZCUkcxRE8wRkJSVzVETEcxRVFVRmxMRk5CUVZNc1lVRkJWQ3hEUVVGbU96dEJRVVp0UXl4M1EwRkpMMElzUTBGQlF5eFpRVUZFTEVsQlFXbENMR0ZCUVdFc1IwRkJZaXhMUVVGeFFpeFhRVUZYTEVkQlFWZ3NSVUZCWjBJN1FVRkRkRVFzWjBSQlFWRXNTVUZCVWl4RFFVRmhMRVZCUVVNc1MwRkJTeXhYUVVGWExFZEJRVmdzUlVGQlowSXNTVUZCU1N4RFFVRktMRVZCUVc1RExFVkJSSE5FT3pzN1FVRkJNVVFzZVVOQlNVczdRVUZEUkN3MFJFRkVRenQ1UTBGS1REdHBRMEZLU2l4TlFWbExPMEZCUTBRc05FTkJRVkVzU1VGQlVpeERRVUZoTEVWQlFVTXNTMEZCU3l4WFFVRlhMRWRCUVZnc1JVRkJaMElzU1VGQlNTeERRVUZLTEVWQlFXNURMRVZCUkVNN2FVTkJXa3c3TmtKQlJrb3NUVUZyUWtzN1FVRkRSQ3gzUTBGQlVTeEpRVUZTTEVOQlFXRXNSVUZCUXl4TFFVRkxMRmRCUVZjc1IwRkJXQ3hGUVVGblFpeEpRVUZKTEVOQlFVb3NSVUZCYmtNc1JVRkVRenMyUWtGc1FrdzdRVUZ4UWtFc1owTkJkRUpuUWpzN08wRkJRWEJDTERaQ1FYbENTeXhKUVVGSkxHZENRVUZuUWl4aFFVRmhMRWRCUVdJc1JVRkJhMEk3UVVGRGRrTXNkME5CUVZFc1NVRkJVaXhEUVVGaExFOUJRVThzVVVGQlVDeEZRVUZwUWl4aFFVRnFRaXhGUVVGblF5eGhRVUZoTEVkQlFXSXNRMEZCTjBNc1JVRkVkVU03TmtKQlFYUkRPM0ZDUVROQ1ZDeE5RU3RDU3p0QlFVTkVMSGREUVVSRE8wRkJSVVFzTkVKQlJrTTdjVUpCTDBKTU8ybENRVlpLT3pzN1FVRTFSbTFETEhWQ1FUUkpOMElzWjBKQlFXZENMRk5CUVZNc1RVRkJWQ3hGUVVGcFFqdEJRVU51UXl4dFEwRkJaU3hUUVVGVExHRkJRVlFzUTBGQlppeERRVVJ0UXp0QlFVVnVReXcwUWtGQlVTeEpRVUZTTEVOQlFXRXNUMEZCVHl4UlFVRlFMRVZCUVdsQ0xHRkJRV3BDTEVWQlFXZERMR2RDUVVGblFpeGhRVUZoTEVkQlFXSXNRMEZCTjBRc1JVRkdiVU03YVVKQlFYWkRPenM3TzBGQk5VbHRReXh2UWtGdFNpOUNMRkZCUVZFc1RVRkJVaXhMUVVGdFFpeFpRVUZ1UWl4SlFVRnRReXhEUVVGRExGRkJRVkVzVFVGQlVpeEZRVUZuUWp0QlFVTndSQ3d5UWtGQlR6dEJRVU5JTEd0RFFVRlZMRmRCUVZZN1FVRkRRU3dyUWtGQlR5eEpRVUZRTzNGQ1FVWktMRU5CUkc5RU8ybENRVUY0UkRzN1FVRlBRU3gxUWtGQlR6dEJRVU5JTERoQ1FVRlZMRmRCUVZZN1FVRkRRU3d5UWtGQlR6dEJRVU5JTEdsRFFVRlRMRTlCUVZRN1FVRkRRU3hwUTBGQlV5eFBRVUZVTzNGQ1FVWktPMmxDUVVaS0xFTkJNVXB0UXp0aFFVRjJRenM3UVVGdFMwRXNjVUpCUVZNc1RVRkJWQ3hEUVVGblFpeEhRVUZvUWl4RlFVRnhRaXhMUVVGeVFpeEZRVUUwUWl4SFFVRTFRaXhGUVVGcFF6dEJRVU0zUWl4dlFrRkJTU3hOUVVGS0xFTkJRVmNzUzBGQldDeEZRVUZyUWl4RFFVRnNRaXhGUVVRMlFqczdRVUZITjBJc2RVSkJRVTg3UVVGRFNDd3dRa0ZCVFN4TFFVRk9PMEZCUTBFc2VVSkJRVXNzUjBGQlREdHBRa0ZHU2l4RFFVZzJRanRoUVVGcVF6czdRVUZUUVN4eFFrRkJVeXhSUVVGVUxFTkJRV3RDTEZGQlFXeENMRVZCUVRSQ08wRkJRM2hDTEc5Q1FVRkpMRTlCUVU4c1JVRkJVQ3hEUVVSdlFqdEJRVVY0UWl4dlFrRkJTU3hQUVVGUExFVkJRVkFzUTBGR2IwSTdRVUZIZUVJc2IwSkJRVWtzVTBGQlV5eFRRVUZUTEUxQlFWUXNRMEZJVnpzN1FVRkxlRUlzY1VKQlFVc3NTVUZCU1N4SlFVRkpMRU5CUVVvc1JVRkJUeXhKUVVGSkxFMUJRVW9zUlVGQldTeEhRVUUxUWl4RlFVRnBRenRCUVVNM1FpeDNRa0ZCU1N4UlFVRlJMRk5CUVZNc1EwRkJWQ3hEUVVGU0xFTkJSSGxDT3p0QlFVYzNRaXgzUWtGQlNTeE5RVUZOTEVkQlFVNHNSVUZCVnp0QlFVTllMRFpDUVVGTExFMUJRVTBzUjBGQlRpeERRVUZNTEVkQlFXdENMRU5CUVd4Q0xFTkJSRmM3Y1VKQlFXWXNUVUZGVHp0QlFVTklMRFpDUVVGTExFbEJRVXdzUTBGQlZTeERRVUZXTEVWQlJFYzdjVUpCUmxBN2FVSkJTRW83TzBGQlZVRXNkVUpCUVU4N1FVRkRTQ3d3UWtGQlRTeEpRVUZPTzBGQlEwRXNNRUpCUVUwc1NVRkJUanRCUVVaSExHbENRVUZRTEVOQlpuZENPMkZCUVRWQ096dEJRWEZDUVN4eFFrRkJVeXhYUVVGVUxFTkJRWEZDTEV0QlFYSkNMRVZCUVRSQ0xFdEJRVFZDTEVWQlFXMURPMEZCUXk5Q0xHOUNRVUZKTEV0QlFVb3NSVUZCVnp0QlFVTlFMSGRDUVVGSkxGRkJRVkVzUzBGQlVpeERRVUZLTEVWQlFXOUNPMEZCUTJoQ0xEaENRVUZOTEVsQlFVNHNRMEZCVnl4TFFVRllMRVZCUkdkQ08zRkNRVUZ3UWl4TlFVVlBPMEZCUTBnc1owTkJRVkVzUTBGQlF5eExRVUZFTEVWQlFWRXNTMEZCVWl4RFFVRlNMRU5CUkVjN2NVSkJSbEE3TzBGQlRVRXNNa0pCUVU4c1MwRkJVQ3hEUVZCUE8ybENRVUZZTEUxQlVVODdRVUZEU0N3eVFrRkJUeXhMUVVGUUxFTkJSRWM3YVVKQlVsQTdZVUZFU2p0VFFTOWFLME1zUlVFMllUZERMRVZCUVVNc2VVSkJRWGRDTEVWQlFYaENMRVZCUVRKQ0xIRkNRVUZ2UWl4RlFVRndRaXhGUVVGMVFpeHhRa0ZCYjBJc1JVRkJjRUlzUlVGQmRVSXNjVUpCUVc5Q0xFVkJRWEJDTEVWQlFYVkNMSE5DUVVGeFFpeEZRVUZ5UWl4RlFVRjNRaXh0UWtGQmEwSXNSVUZCYkVJc1JVRkJjVUlzWjBKQlFXVXNSVUZCWml4RlFVRnJRaXhqUVVGaExFVkJRV0lzUlVFM1lYQklMRU5CUVVnc1JVRTVkVU0xUWl4RlFUSndSSE5MTEVWQk0zQkVkRXNzUlVFeWNFUjVTeXhEUVVGRExFTkJRVVFzUTBFemNFUjZTeXhGUVRKd1JEaExMRU5CTTNCRU9Vc3NRMEZCVUN4RFFVWkxPME5CUVZnc1EwRkdSVHM3UVVGcmNVUktMR1ZCUVdVc1ZVRkJaaUlzSW1acGJHVWlPaUpzYVdJdmRtbHlkSFZoYkMxa2IyMHVhbk1pTENKemIzVnlZMlZ6UTI5dWRHVnVkQ0k2V3lKc1pYUWdWbWx5ZEhWaGJFUlBUU0E5SUdaMWJtTjBhVzl1S0dVcElIdGNiaUFnY21WMGRYSnVJR1VvS1R0Y2JuMG9ablZ1WTNScGIyNG9LU0I3WEc0Z0lDQWdJQ0FnSUhaaGNpQmtaV1pwYm1Vc0lHMXZaSFZzWlN3Z1pYaHdiM0owY3p0Y2JpQWdJQ0FnSUNBZ2NtVjBkWEp1SUNobWRXNWpkR2x2YmlCbEtIUXNJRzRzSUhJcElIdGNiaUFnSUNBZ0lDQWdJQ0FnSUNBZ0lDQm1kVzVqZEdsdmJpQnpLRzhzSUhVcElIdGNiaUFnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnYVdZZ0tDRnVXMjlkS1NCN1hHNGdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNCcFppQW9JWFJiYjEwcElIdGNiaUFnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0IyWVhJZ1lTQTlJSFI1Y0dWdlppQnlaWEYxYVhKbElEMDlJRndpWm5WdVkzUnBiMjVjSWlBbUppQnlaWEYxYVhKbE8xeHVJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJR2xtSUNnaGRTQW1KaUJoS1NCeVpYUjFjbTRnWVNodkxDQWhNQ2s3WEc0Z0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ2FXWWdLR2twSUhKbGRIVnliaUJwS0c4c0lDRXdLVHRjYmlBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNCMllYSWdaaUE5SUc1bGR5QkZjbkp2Y2loY0lrTmhibTV2ZENCbWFXNWtJRzF2WkhWc1pTQW5YQ0lnS3lCdklDc2dYQ0luWENJcE8xeHVJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJSFJvY205M0lHWXVZMjlrWlNBOUlGd2lUVTlFVlV4RlgwNVBWRjlHVDFWT1JGd2lMQ0JtWEc0Z0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0I5WEc0Z0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0IyWVhJZ2JDQTlJRzViYjEwZ1BTQjdYRzRnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnWlhod2IzSjBjem9nZTMxY2JpQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUgwN1hHNGdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNCMFcyOWRXekJkTG1OaGJHd29iQzVsZUhCdmNuUnpMQ0JtZFc1amRHbHZiaWhsS1NCN1hHNGdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdkbUZ5SUc0Z1BTQjBXMjlkV3pGZFcyVmRPMXh1SUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUhKbGRIVnliaUJ6S0c0Z1B5QnVJRG9nWlNsY2JpQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUgwc0lHd3NJR3d1Wlhod2IzSjBjeXdnWlN3Z2RDd2diaXdnY2lsY2JpQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdmVnh1SUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNCeVpYUjFjbTRnYmx0dlhTNWxlSEJ2Y25SelhHNGdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ2ZWeHVJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lIWmhjaUJwSUQwZ2RIbHdaVzltSUhKbGNYVnBjbVVnUFQwZ1hDSm1kVzVqZEdsdmJsd2lJQ1ltSUhKbGNYVnBjbVU3WEc0Z0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnWm05eUlDaDJZWElnYnlBOUlEQTdJRzhnUENCeUxteGxibWQwYURzZ2J5c3JLU0J6S0hKYmIxMHBPMXh1SUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJSEpsZEhWeWJpQnpYRzRnSUNBZ0lDQWdJQ0FnSUNCOUtTaDdYRzRnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSURFNklGdG1kVzVqZEdsdmJpaHlaWEYxYVhKbExDQnRiMlIxYkdVc0lHVjRjRzl5ZEhNcElIdGNibHh1ZG1GeUlHTnlaV0YwWlVWc1pXMWxiblFnUFNCeVpYRjFhWEpsS0Z3aUxpOTJaRzl0TDJOeVpXRjBaUzFsYkdWdFpXNTBMbXB6WENJcFhHNWNibTF2WkhWc1pTNWxlSEJ2Y25SeklEMGdZM0psWVhSbFJXeGxiV1Z1ZEZ4dVhHNTlMSHRjSWk0dmRtUnZiUzlqY21WaGRHVXRaV3hsYldWdWRDNXFjMXdpT2pFMWZWMHNNanBiWm5WdVkzUnBiMjRvY21WeGRXbHlaU3h0YjJSMWJHVXNaWGh3YjNKMGN5bDdYRzUyWVhJZ1pHbG1aaUE5SUhKbGNYVnBjbVVvWENJdUwzWjBjbVZsTDJScFptWXVhbk5jSWlsY2JseHViVzlrZFd4bExtVjRjRzl5ZEhNZ1BTQmthV1ptWEc1Y2JuMHNlMXdpTGk5MmRISmxaUzlrYVdabUxtcHpYQ0k2TXpWOVhTd3pPbHRtZFc1amRHbHZiaWh5WlhGMWFYSmxMRzF2WkhWc1pTeGxlSEJ2Y25SektYdGNiblpoY2lCb0lEMGdjbVZ4ZFdseVpTaGNJaTR2ZG1seWRIVmhiQzFvZVhCbGNuTmpjbWx3ZEM5cGJtUmxlQzVxYzF3aUtWeHVYRzV0YjJSMWJHVXVaWGh3YjNKMGN5QTlJR2hjYmx4dWZTeDdYQ0l1TDNacGNuUjFZV3d0YUhsd1pYSnpZM0pwY0hRdmFXNWtaWGd1YW5OY0lqb3lNbjFkTERRNlcyWjFibU4wYVc5dUtISmxjWFZwY21Vc2JXOWtkV3hsTEdWNGNHOXlkSE1wZTF4dWRtRnlJR1JwWm1ZZ1BTQnlaWEYxYVhKbEtGd2lMaTlrYVdabUxtcHpYQ0lwWEc1MllYSWdjR0YwWTJnZ1BTQnlaWEYxYVhKbEtGd2lMaTl3WVhSamFDNXFjMXdpS1Z4dWRtRnlJR2dnUFNCeVpYRjFhWEpsS0Z3aUxpOW9MbXB6WENJcFhHNTJZWElnWTNKbFlYUmxJRDBnY21WeGRXbHlaU2hjSWk0dlkzSmxZWFJsTFdWc1pXMWxiblF1YW5OY0lpbGNiblpoY2lCV1RtOWtaU0E5SUhKbGNYVnBjbVVvSnk0dmRtNXZaR1V2ZG01dlpHVXVhbk1uS1Z4dWRtRnlJRlpVWlhoMElEMGdjbVZ4ZFdseVpTZ25MaTkyYm05a1pTOTJkR1Y0ZEM1cWN5Y3BYRzVjYm0xdlpIVnNaUzVsZUhCdmNuUnpJRDBnZTF4dUlDQWdJR1JwWm1ZNklHUnBabVlzWEc0Z0lDQWdjR0YwWTJnNklIQmhkR05vTEZ4dUlDQWdJR2c2SUdnc1hHNGdJQ0FnWTNKbFlYUmxPaUJqY21WaGRHVXNYRzRnSUNBZ1ZrNXZaR1U2SUZaT2IyUmxMRnh1SUNBZ0lGWlVaWGgwT2lCV1ZHVjRkRnh1ZlZ4dVhHNTlMSHRjSWk0dlkzSmxZWFJsTFdWc1pXMWxiblF1YW5OY0lqb3hMRndpTGk5a2FXWm1MbXB6WENJNk1peGNJaTR2YUM1cWMxd2lPak1zWENJdUwzQmhkR05vTG1welhDSTZNVE1zWENJdUwzWnViMlJsTDNadWIyUmxMbXB6WENJNk16RXNYQ0l1TDNadWIyUmxMM1owWlhoMExtcHpYQ0k2TXpOOVhTdzFPbHRtZFc1amRHbHZiaWh5WlhGMWFYSmxMRzF2WkhWc1pTeGxlSEJ2Y25SektYdGNiaThxSVZ4dUlDb2dRM0p2YzNNdFFuSnZkM05sY2lCVGNHeHBkQ0F4TGpFdU1WeHVJQ29nUTI5d2VYSnBaMmgwSURJd01EY3RNakF4TWlCVGRHVjJaVzRnVEdWMmFYUm9ZVzRnUEhOMFpYWmxibXhsZG1sMGFHRnVMbU52YlQ1Y2JpQXFJRUYyWVdsc1lXSnNaU0IxYm1SbGNpQjBhR1VnVFVsVUlFeHBZMlZ1YzJWY2JpQXFJRVZEVFVGVFkzSnBjSFFnWTI5dGNHeHBZVzUwTENCMWJtbG1iM0p0SUdOeWIzTnpMV0p5YjNkelpYSWdjM0JzYVhRZ2JXVjBhRzlrWEc0Z0tpOWNibHh1THlvcVhHNGdLaUJUY0d4cGRITWdZU0J6ZEhKcGJtY2dhVzUwYnlCaGJpQmhjbkpoZVNCdlppQnpkSEpwYm1keklIVnphVzVuSUdFZ2NtVm5aWGdnYjNJZ2MzUnlhVzVuSUhObGNHRnlZWFJ2Y2k0Z1RXRjBZMmhsY3lCdlppQjBhR1ZjYmlBcUlITmxjR0Z5WVhSdmNpQmhjbVVnYm05MElHbHVZMngxWkdWa0lHbHVJSFJvWlNCeVpYTjFiSFFnWVhKeVlYa3VJRWh2ZDJWMlpYSXNJR2xtSUdCelpYQmhjbUYwYjNKZ0lHbHpJR0VnY21WblpYZ2dkR2hoZENCamIyNTBZV2x1YzF4dUlDb2dZMkZ3ZEhWeWFXNW5JR2R5YjNWd2N5d2dZbUZqYTNKbFptVnlaVzVqWlhNZ1lYSmxJSE53YkdsalpXUWdhVzUwYnlCMGFHVWdjbVZ6ZFd4MElHVmhZMmdnZEdsdFpTQmdjMlZ3WVhKaGRHOXlZQ0JwY3lCdFlYUmphR1ZrTGx4dUlDb2dSbWw0WlhNZ1luSnZkM05sY2lCaWRXZHpJR052YlhCaGNtVmtJSFJ2SUhSb1pTQnVZWFJwZG1VZ1lGTjBjbWx1Wnk1d2NtOTBiM1I1Y0dVdWMzQnNhWFJnSUdGdVpDQmpZVzRnWW1VZ2RYTmxaQ0J5Wld4cFlXSnNlVnh1SUNvZ1kzSnZjM010WW5KdmQzTmxjaTVjYmlBcUlFQndZWEpoYlNCN1UzUnlhVzVuZlNCemRISWdVM1J5YVc1bklIUnZJSE53YkdsMExseHVJQ29nUUhCaGNtRnRJSHRTWldkRmVIQjhVM1J5YVc1bmZTQnpaWEJoY21GMGIzSWdVbVZuWlhnZ2IzSWdjM1J5YVc1bklIUnZJSFZ6WlNCbWIzSWdjMlZ3WVhKaGRHbHVaeUIwYUdVZ2MzUnlhVzVuTGx4dUlDb2dRSEJoY21GdElIdE9kVzFpWlhKOUlGdHNhVzFwZEYwZ1RXRjRhVzExYlNCdWRXMWlaWElnYjJZZ2FYUmxiWE1nZEc4Z2FXNWpiSFZrWlNCcGJpQjBhR1VnY21WemRXeDBJR0Z5Y21GNUxseHVJQ29nUUhKbGRIVnlibk1nZTBGeWNtRjVmU0JCY25KaGVTQnZaaUJ6ZFdKemRISnBibWR6TGx4dUlDb2dRR1Y0WVcxd2JHVmNiaUFxWEc0Z0tpQXZMeUJDWVhOcFl5QjFjMlZjYmlBcUlITndiR2wwS0NkaElHSWdZeUJrSnl3Z0p5QW5LVHRjYmlBcUlDOHZJQzArSUZzbllTY3NJQ2RpSnl3Z0oyTW5MQ0FuWkNkZFhHNGdLbHh1SUNvZ0x5OGdWMmwwYUNCc2FXMXBkRnh1SUNvZ2MzQnNhWFFvSjJFZ1lpQmpJR1FuTENBbklDY3NJRElwTzF4dUlDb2dMeThnTFQ0Z1d5ZGhKeXdnSjJJblhWeHVJQ3BjYmlBcUlDOHZJRUpoWTJ0eVpXWmxjbVZ1WTJWeklHbHVJSEpsYzNWc2RDQmhjbkpoZVZ4dUlDb2djM0JzYVhRb0p5NHVkMjl5WkRFZ2QyOXlaREl1TGljc0lDOG9XMkV0ZWwwcktTaGNYR1FyS1M5cEtUdGNiaUFxSUM4dklDMCtJRnNuTGk0bkxDQW5kMjl5WkNjc0lDY3hKeXdnSnlBbkxDQW5kMjl5WkNjc0lDY3lKeXdnSnk0dUoxMWNiaUFxTDF4dWJXOWtkV3hsTG1WNGNHOXlkSE1nUFNBb1puVnVZM1JwYjI0Z2MzQnNhWFFvZFc1a1pXWXBJSHRjYmx4dUlDQjJZWElnYm1GMGFYWmxVM0JzYVhRZ1BTQlRkSEpwYm1jdWNISnZkRzkwZVhCbExuTndiR2wwTEZ4dUlDQWdJR052YlhCc2FXRnVkRVY0WldOT2NHTm5JRDBnTHlncFB6OHZMbVY0WldNb1hDSmNJaWxiTVYwZ1BUMDlJSFZ1WkdWbUxGeHVJQ0FnSUM4dklFNVFRMGM2SUc1dmJuQmhjblJwWTJsd1lYUnBibWNnWTJGd2RIVnlhVzVuSUdkeWIzVndYRzRnSUNBZ2MyVnNaanRjYmx4dUlDQnpaV3htSUQwZ1puVnVZM1JwYjI0b2MzUnlMQ0J6WlhCaGNtRjBiM0lzSUd4cGJXbDBLU0I3WEc0Z0lDQWdMeThnU1dZZ1lITmxjR0Z5WVhSdmNtQWdhWE1nYm05MElHRWdjbVZuWlhnc0lIVnpaU0JnYm1GMGFYWmxVM0JzYVhSZ1hHNGdJQ0FnYVdZZ0tFOWlhbVZqZEM1d2NtOTBiM1I1Y0dVdWRHOVRkSEpwYm1jdVkyRnNiQ2h6WlhCaGNtRjBiM0lwSUNFOVBTQmNJbHR2WW1wbFkzUWdVbVZuUlhod1hWd2lLU0I3WEc0Z0lDQWdJQ0J5WlhSMWNtNGdibUYwYVhabFUzQnNhWFF1WTJGc2JDaHpkSElzSUhObGNHRnlZWFJ2Y2l3Z2JHbHRhWFFwTzF4dUlDQWdJSDFjYmlBZ0lDQjJZWElnYjNWMGNIVjBJRDBnVzEwc1hHNGdJQ0FnSUNCbWJHRm5jeUE5SUNoelpYQmhjbUYwYjNJdWFXZHViM0psUTJGelpTQS9JRndpYVZ3aUlEb2dYQ0pjSWlrZ0t5QW9jMlZ3WVhKaGRHOXlMbTExYkhScGJHbHVaU0EvSUZ3aWJWd2lJRG9nWENKY0lpa2dLeUFvYzJWd1lYSmhkRzl5TG1WNGRHVnVaR1ZrSUQ4Z1hDSjRYQ0lnT2lCY0lsd2lLU0FySUM4dklGQnliM0J2YzJWa0lHWnZjaUJGVXpaY2JpQWdJQ0FnSUNoelpYQmhjbUYwYjNJdWMzUnBZMnQ1SUQ4Z1hDSjVYQ0lnT2lCY0lsd2lLU3hjYmlBZ0lDQWdJQzh2SUVacGNtVm1iM2dnTXl0Y2JpQWdJQ0FnSUd4aGMzUk1ZWE4wU1c1a1pYZ2dQU0F3TEZ4dUlDQWdJQ0FnTHk4Z1RXRnJaU0JnWjJ4dlltRnNZQ0JoYm1RZ1lYWnZhV1FnWUd4aGMzUkpibVJsZUdBZ2FYTnpkV1Z6SUdKNUlIZHZjbXRwYm1jZ2QybDBhQ0JoSUdOdmNIbGNiaUFnSUNBZ0lITmxjR0Z5WVhSdmNpQTlJRzVsZHlCU1pXZEZlSEFvYzJWd1lYSmhkRzl5TG5OdmRYSmpaU3dnWm14aFozTWdLeUJjSW1kY0lpa3NYRzRnSUNBZ0lDQnpaWEJoY21GMGIzSXlMQ0J0WVhSamFDd2diR0Z6ZEVsdVpHVjRMQ0JzWVhOMFRHVnVaM1JvTzF4dUlDQWdJSE4wY2lBclBTQmNJbHdpT3lBdkx5QlVlWEJsTFdOdmJuWmxjblJjYmlBZ0lDQnBaaUFvSVdOdmJYQnNhV0Z1ZEVWNFpXTk9jR05uS1NCN1hHNGdJQ0FnSUNBdkx5QkViMlZ6YmlkMElHNWxaV1FnWm14aFozTWdaM2tzSUdKMWRDQjBhR1Y1SUdSdmJpZDBJR2gxY25SY2JpQWdJQ0FnSUhObGNHRnlZWFJ2Y2pJZ1BTQnVaWGNnVW1WblJYaHdLRndpWGx3aUlDc2djMlZ3WVhKaGRHOXlMbk52ZFhKalpTQXJJRndpSkNnL0lWeGNYRnh6S1Z3aUxDQm1iR0ZuY3lrN1hHNGdJQ0FnZlZ4dUlDQWdJQzhxSUZaaGJIVmxjeUJtYjNJZ1lHeHBiV2wwWUN3Z2NHVnlJSFJvWlNCemNHVmpPbHh1SUNBZ0lDQXFJRWxtSUhWdVpHVm1hVzVsWkRvZ05ESTVORGsyTnpJNU5TQXZMeUJOWVhSb0xuQnZkeWd5TENBek1pa2dMU0F4WEc0Z0lDQWdJQ29nU1dZZ01Dd2dTVzVtYVc1cGRIa3NJRzl5SUU1aFRqb2dNRnh1SUNBZ0lDQXFJRWxtSUhCdmMybDBhWFpsSUc1MWJXSmxjam9nYkdsdGFYUWdQU0JOWVhSb0xtWnNiMjl5S0d4cGJXbDBLVHNnYVdZZ0tHeHBiV2wwSUQ0Z05ESTVORGsyTnpJNU5Ta2diR2x0YVhRZ0xUMGdOREk1TkRrMk56STVOanRjYmlBZ0lDQWdLaUJKWmlCdVpXZGhkR2wyWlNCdWRXMWlaWEk2SURReU9UUTVOamN5T1RZZ0xTQk5ZWFJvTG1ac2IyOXlLRTFoZEdndVlXSnpLR3hwYldsMEtTbGNiaUFnSUNBZ0tpQkpaaUJ2ZEdobGNqb2dWSGx3WlMxamIyNTJaWEowTENCMGFHVnVJSFZ6WlNCMGFHVWdZV0p2ZG1VZ2NuVnNaWE5jYmlBZ0lDQWdLaTljYmlBZ0lDQnNhVzFwZENBOUlHeHBiV2wwSUQwOVBTQjFibVJsWmlBL0lDMHhJRDQrUGlBd0lEb2dMeThnVFdGMGFDNXdiM2NvTWl3Z016SXBJQzBnTVZ4dUlDQWdJR3hwYldsMElENCtQaUF3T3lBdkx5QlViMVZwYm5Rek1paHNhVzFwZENsY2JpQWdJQ0IzYUdsc1pTQW9iV0YwWTJnZ1BTQnpaWEJoY21GMGIzSXVaWGhsWXloemRISXBLU0I3WEc0Z0lDQWdJQ0F2THlCZ2MyVndZWEpoZEc5eUxteGhjM1JKYm1SbGVHQWdhWE1nYm05MElISmxiR2xoWW14bElHTnliM056TFdKeWIzZHpaWEpjYmlBZ0lDQWdJR3hoYzNSSmJtUmxlQ0E5SUcxaGRHTm9MbWx1WkdWNElDc2diV0YwWTJoYk1GMHViR1Z1WjNSb08xeHVJQ0FnSUNBZ2FXWWdLR3hoYzNSSmJtUmxlQ0ErSUd4aGMzUk1ZWE4wU1c1a1pYZ3BJSHRjYmlBZ0lDQWdJQ0FnYjNWMGNIVjBMbkIxYzJnb2MzUnlMbk5zYVdObEtHeGhjM1JNWVhOMFNXNWtaWGdzSUcxaGRHTm9MbWx1WkdWNEtTazdYRzRnSUNBZ0lDQWdJQzh2SUVacGVDQmljbTkzYzJWeWN5QjNhRzl6WlNCZ1pYaGxZMkFnYldWMGFHOWtjeUJrYjI0bmRDQmpiMjV6YVhOMFpXNTBiSGtnY21WMGRYSnVJR0IxYm1SbFptbHVaV1JnSUdadmNseHVJQ0FnSUNBZ0lDQXZMeUJ1YjI1d1lYSjBhV05wY0dGMGFXNW5JR05oY0hSMWNtbHVaeUJuY205MWNITmNiaUFnSUNBZ0lDQWdhV1lnS0NGamIyMXdiR2xoYm5SRmVHVmpUbkJqWnlBbUppQnRZWFJqYUM1c1pXNW5kR2dnUGlBeEtTQjdYRzRnSUNBZ0lDQWdJQ0FnYldGMFkyaGJNRjB1Y21Wd2JHRmpaU2h6WlhCaGNtRjBiM0l5TENCbWRXNWpkR2x2YmlncElIdGNiaUFnSUNBZ0lDQWdJQ0FnSUdadmNpQW9kbUZ5SUdrZ1BTQXhPeUJwSUR3Z1lYSm5kVzFsYm5SekxteGxibWQwYUNBdElESTdJR2tyS3lrZ2UxeHVJQ0FnSUNBZ0lDQWdJQ0FnSUNCcFppQW9ZWEpuZFcxbGJuUnpXMmxkSUQwOVBTQjFibVJsWmlrZ2UxeHVJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lHMWhkR05vVzJsZElEMGdkVzVrWldZN1hHNGdJQ0FnSUNBZ0lDQWdJQ0FnSUgxY2JpQWdJQ0FnSUNBZ0lDQWdJSDFjYmlBZ0lDQWdJQ0FnSUNCOUtUdGNiaUFnSUNBZ0lDQWdmVnh1SUNBZ0lDQWdJQ0JwWmlBb2JXRjBZMmd1YkdWdVozUm9JRDRnTVNBbUppQnRZWFJqYUM1cGJtUmxlQ0E4SUhOMGNpNXNaVzVuZEdncElIdGNiaUFnSUNBZ0lDQWdJQ0JCY25KaGVTNXdjbTkwYjNSNWNHVXVjSFZ6YUM1aGNIQnNlU2h2ZFhSd2RYUXNJRzFoZEdOb0xuTnNhV05sS0RFcEtUdGNiaUFnSUNBZ0lDQWdmVnh1SUNBZ0lDQWdJQ0JzWVhOMFRHVnVaM1JvSUQwZ2JXRjBZMmhiTUYwdWJHVnVaM1JvTzF4dUlDQWdJQ0FnSUNCc1lYTjBUR0Z6ZEVsdVpHVjRJRDBnYkdGemRFbHVaR1Y0TzF4dUlDQWdJQ0FnSUNCcFppQW9iM1YwY0hWMExteGxibWQwYUNBK1BTQnNhVzFwZENrZ2UxeHVJQ0FnSUNBZ0lDQWdJR0p5WldGck8xeHVJQ0FnSUNBZ0lDQjlYRzRnSUNBZ0lDQjlYRzRnSUNBZ0lDQnBaaUFvYzJWd1lYSmhkRzl5TG14aGMzUkpibVJsZUNBOVBUMGdiV0YwWTJndWFXNWtaWGdwSUh0Y2JpQWdJQ0FnSUNBZ2MyVndZWEpoZEc5eUxteGhjM1JKYm1SbGVDc3JPeUF2THlCQmRtOXBaQ0JoYmlCcGJtWnBibWwwWlNCc2IyOXdYRzRnSUNBZ0lDQjlYRzRnSUNBZ2ZWeHVJQ0FnSUdsbUlDaHNZWE4wVEdGemRFbHVaR1Y0SUQwOVBTQnpkSEl1YkdWdVozUm9LU0I3WEc0Z0lDQWdJQ0JwWmlBb2JHRnpkRXhsYm1kMGFDQjhmQ0FoYzJWd1lYSmhkRzl5TG5SbGMzUW9YQ0pjSWlrcElIdGNiaUFnSUNBZ0lDQWdiM1YwY0hWMExuQjFjMmdvWENKY0lpazdYRzRnSUNBZ0lDQjlYRzRnSUNBZ2ZTQmxiSE5sSUh0Y2JpQWdJQ0FnSUc5MWRIQjFkQzV3ZFhOb0tITjBjaTV6YkdsalpTaHNZWE4wVEdGemRFbHVaR1Y0S1NrN1hHNGdJQ0FnZlZ4dUlDQWdJSEpsZEhWeWJpQnZkWFJ3ZFhRdWJHVnVaM1JvSUQ0Z2JHbHRhWFFnUHlCdmRYUndkWFF1YzJ4cFkyVW9NQ3dnYkdsdGFYUXBJRG9nYjNWMGNIVjBPMXh1SUNCOU8xeHVYRzRnSUhKbGRIVnliaUJ6Wld4bU8xeHVmU2tvS1R0Y2JseHVmU3g3ZlYwc05qcGJablZ1WTNScGIyNG9jbVZ4ZFdseVpTeHRiMlIxYkdVc1pYaHdiM0owY3lsN1hHNWNibjBzZTMxZExEYzZXMloxYm1OMGFXOXVLSEpsY1hWcGNtVXNiVzlrZFd4bExHVjRjRzl5ZEhNcGUxeHVKM1Z6WlNCemRISnBZM1FuTzF4dVhHNTJZWElnVDI1bFZtVnljMmx2YmtOdmJuTjBjbUZwYm5RZ1BTQnlaWEYxYVhKbEtDZHBibVJwZG1sa2RXRnNMMjl1WlMxMlpYSnphVzl1SnlrN1hHNWNiblpoY2lCTldWOVdSVkpUU1U5T0lEMGdKemNuTzF4dVQyNWxWbVZ5YzJsdmJrTnZibk4wY21GcGJuUW9KMlYyTFhOMGIzSmxKeXdnVFZsZlZrVlNVMGxQVGlrN1hHNWNiblpoY2lCb1lYTm9TMlY1SUQwZ0oxOWZSVlpmVTFSUFVrVmZTMFZaUUNjZ0t5Qk5XVjlXUlZKVFNVOU9PMXh1WEc1dGIyUjFiR1V1Wlhod2IzSjBjeUE5SUVWMlUzUnZjbVU3WEc1Y2JtWjFibU4wYVc5dUlFVjJVM1J2Y21Vb1pXeGxiU2tnZTF4dUlDQWdJSFpoY2lCb1lYTm9JRDBnWld4bGJWdG9ZWE5vUzJWNVhUdGNibHh1SUNBZ0lHbG1JQ2doYUdGemFDa2dlMXh1SUNBZ0lDQWdJQ0JvWVhOb0lEMGdaV3hsYlZ0b1lYTm9TMlY1WFNBOUlIdDlPMXh1SUNBZ0lIMWNibHh1SUNBZ0lISmxkSFZ5YmlCb1lYTm9PMXh1ZlZ4dVhHNTlMSHRjSW1sdVpHbDJhV1IxWVd3dmIyNWxMWFpsY25OcGIyNWNJam81ZlYwc09EcGJablZ1WTNScGIyNG9jbVZ4ZFdseVpTeHRiMlIxYkdVc1pYaHdiM0owY3lsN1hHNG9ablZ1WTNScGIyNGdLR2RzYjJKaGJDbDdYRzRuZFhObElITjBjbWxqZENjN1hHNWNiaThxWjJ4dlltRnNJSGRwYm1SdmR5d2daMnh2WW1Gc0tpOWNibHh1ZG1GeUlISnZiM1FnUFNCMGVYQmxiMllnZDJsdVpHOTNJQ0U5UFNBbmRXNWtaV1pwYm1Wa0p5QS9YRzRnSUNBZ2QybHVaRzkzSURvZ2RIbHdaVzltSUdkc2IySmhiQ0FoUFQwZ0ozVnVaR1ZtYVc1bFpDY2dQMXh1SUNBZ0lHZHNiMkpoYkNBNklIdDlPMXh1WEc1dGIyUjFiR1V1Wlhod2IzSjBjeUE5SUVsdVpHbDJhV1IxWVd3N1hHNWNibVoxYm1OMGFXOXVJRWx1WkdsMmFXUjFZV3dvYTJWNUxDQjJZV3gxWlNrZ2UxeHVJQ0FnSUdsbUlDaHJaWGtnYVc0Z2NtOXZkQ2tnZTF4dUlDQWdJQ0FnSUNCeVpYUjFjbTRnY205dmRGdHJaWGxkTzF4dUlDQWdJSDFjYmx4dUlDQWdJSEp2YjNSYmEyVjVYU0E5SUhaaGJIVmxPMXh1WEc0Z0lDQWdjbVYwZFhKdUlIWmhiSFZsTzF4dWZWeHVYRzU5S1M1allXeHNLSFJvYVhNc2RIbHdaVzltSUdkc2IySmhiQ0FoUFQwZ1hDSjFibVJsWm1sdVpXUmNJaUEvSUdkc2IySmhiQ0E2SUhSNWNHVnZaaUJ6Wld4bUlDRTlQU0JjSW5WdVpHVm1hVzVsWkZ3aUlEOGdjMlZzWmlBNklIUjVjR1Z2WmlCM2FXNWtiM2NnSVQwOUlGd2lkVzVrWldacGJtVmtYQ0lnUHlCM2FXNWtiM2NnT2lCN2ZTbGNibjBzZTMxZExEazZXMloxYm1OMGFXOXVLSEpsY1hWcGNtVXNiVzlrZFd4bExHVjRjRzl5ZEhNcGUxeHVKM1Z6WlNCemRISnBZM1FuTzF4dVhHNTJZWElnU1c1a2FYWnBaSFZoYkNBOUlISmxjWFZwY21Vb0p5NHZhVzVrWlhndWFuTW5LVHRjYmx4dWJXOWtkV3hsTG1WNGNHOXlkSE1nUFNCUGJtVldaWEp6YVc5dU8xeHVYRzVtZFc1amRHbHZiaUJQYm1WV1pYSnphVzl1S0cxdlpIVnNaVTVoYldVc0lIWmxjbk5wYjI0c0lHUmxabUYxYkhSV1lXeDFaU2tnZTF4dUlDQWdJSFpoY2lCclpYa2dQU0FuWDE5SlRrUkpWa2xFVlVGTVgwOU9SVjlXUlZKVFNVOU9YeWNnS3lCdGIyUjFiR1ZPWVcxbE8xeHVJQ0FnSUhaaGNpQmxibVp2Y21ObFMyVjVJRDBnYTJWNUlDc2dKMTlGVGtaUFVrTkZYMU5KVGtkTVJWUlBUaWM3WEc1Y2JpQWdJQ0IyWVhJZ2RtVnljMmx2YmxaaGJIVmxJRDBnU1c1a2FYWnBaSFZoYkNobGJtWnZjbU5sUzJWNUxDQjJaWEp6YVc5dUtUdGNibHh1SUNBZ0lHbG1JQ2gyWlhKemFXOXVWbUZzZFdVZ0lUMDlJSFpsY25OcGIyNHBJSHRjYmlBZ0lDQWdJQ0FnZEdoeWIzY2dibVYzSUVWeWNtOXlLQ2REWVc0Z2IyNXNlU0JvWVhabElHOXVaU0JqYjNCNUlHOW1JQ2NnSzF4dUlDQWdJQ0FnSUNBZ0lDQWdiVzlrZFd4bFRtRnRaU0FySUNjdVhGeHVKeUFyWEc0Z0lDQWdJQ0FnSUNBZ0lDQW5XVzkxSUdGc2NtVmhaSGtnYUdGMlpTQjJaWEp6YVc5dUlDY2dLeUIyWlhKemFXOXVWbUZzZFdVZ0sxeHVJQ0FnSUNBZ0lDQWdJQ0FnSnlCcGJuTjBZV3hzWldRdVhGeHVKeUFyWEc0Z0lDQWdJQ0FnSUNBZ0lDQW5WR2hwY3lCdFpXRnVjeUI1YjNVZ1kyRnVibTkwSUdsdWMzUmhiR3dnZG1WeWMybHZiaUFuSUNzZ2RtVnljMmx2YmlrN1hHNGdJQ0FnZlZ4dVhHNGdJQ0FnY21WMGRYSnVJRWx1WkdsMmFXUjFZV3dvYTJWNUxDQmtaV1poZFd4MFZtRnNkV1VwTzF4dWZWeHVYRzU5TEh0Y0lpNHZhVzVrWlhndWFuTmNJam80ZlYwc01UQTZXMloxYm1OMGFXOXVLSEpsY1hWcGNtVXNiVzlrZFd4bExHVjRjRzl5ZEhNcGUxeHVLR1oxYm1OMGFXOXVJQ2huYkc5aVlXd3BlMXh1ZG1GeUlIUnZjRXhsZG1Wc0lEMGdkSGx3Wlc5bUlHZHNiMkpoYkNBaFBUMGdKM1Z1WkdWbWFXNWxaQ2NnUHlCbmJHOWlZV3dnT2x4dUlDQWdJSFI1Y0dWdlppQjNhVzVrYjNjZ0lUMDlJQ2QxYm1SbFptbHVaV1FuSUQ4Z2QybHVaRzkzSURvZ2UzMWNiblpoY2lCdGFXNUViMk1nUFNCeVpYRjFhWEpsS0NkdGFXNHRaRzlqZFcxbGJuUW5LVHRjYmx4dWFXWWdLSFI1Y0dWdlppQmtiMk4xYldWdWRDQWhQVDBnSjNWdVpHVm1hVzVsWkNjcElIdGNiaUFnSUNCdGIyUjFiR1V1Wlhod2IzSjBjeUE5SUdSdlkzVnRaVzUwTzF4dWZTQmxiSE5sSUh0Y2JpQWdJQ0IyWVhJZ1pHOWpZM2tnUFNCMGIzQk1aWFpsYkZzblgxOUhURTlDUVV4ZlJFOURWVTFGVGxSZlEwRkRTRVZBTkNkZE8xeHVYRzRnSUNBZ2FXWWdLQ0ZrYjJOamVTa2dlMXh1SUNBZ0lDQWdJQ0JrYjJOamVTQTlJSFJ2Y0V4bGRtVnNXeWRmWDBkTVQwSkJURjlFVDBOVlRVVk9WRjlEUVVOSVJVQTBKMTBnUFNCdGFXNUViMk03WEc0Z0lDQWdmVnh1WEc0Z0lDQWdiVzlrZFd4bExtVjRjRzl5ZEhNZ1BTQmtiMk5qZVR0Y2JuMWNibHh1ZlNrdVkyRnNiQ2gwYUdsekxIUjVjR1Z2WmlCbmJHOWlZV3dnSVQwOUlGd2lkVzVrWldacGJtVmtYQ0lnUHlCbmJHOWlZV3dnT2lCMGVYQmxiMllnYzJWc1ppQWhQVDBnWENKMWJtUmxabWx1WldSY0lpQS9JSE5sYkdZZ09pQjBlWEJsYjJZZ2QybHVaRzkzSUNFOVBTQmNJblZ1WkdWbWFXNWxaRndpSUQ4Z2QybHVaRzkzSURvZ2UzMHBYRzU5TEh0Y0ltMXBiaTFrYjJOMWJXVnVkRndpT2paOVhTd3hNVHBiWm5WdVkzUnBiMjRvY21WeGRXbHlaU3h0YjJSMWJHVXNaWGh3YjNKMGN5bDdYRzVjSW5WelpTQnpkSEpwWTNSY0lqdGNibHh1Ylc5a2RXeGxMbVY0Y0c5eWRITWdQU0JtZFc1amRHbHZiaUJwYzA5aWFtVmpkQ2g0S1NCN1hHNWNkSEpsZEhWeWJpQjBlWEJsYjJZZ2VDQTlQVDBnWENKdlltcGxZM1JjSWlBbUppQjRJQ0U5UFNCdWRXeHNPMXh1ZlR0Y2JseHVmU3g3ZlYwc01USTZXMloxYm1OMGFXOXVLSEpsY1hWcGNtVXNiVzlrZFd4bExHVjRjRzl5ZEhNcGUxeHVkbUZ5SUc1aGRHbDJaVWx6UVhKeVlYa2dQU0JCY25KaGVTNXBjMEZ5Y21GNVhHNTJZWElnZEc5VGRISnBibWNnUFNCUFltcGxZM1F1Y0hKdmRHOTBlWEJsTG5SdlUzUnlhVzVuWEc1Y2JtMXZaSFZzWlM1bGVIQnZjblJ6SUQwZ2JtRjBhWFpsU1hOQmNuSmhlU0I4ZkNCcGMwRnljbUY1WEc1Y2JtWjFibU4wYVc5dUlHbHpRWEp5WVhrb2IySnFLU0I3WEc0Z0lDQWdjbVYwZFhKdUlIUnZVM1J5YVc1bkxtTmhiR3dvYjJKcUtTQTlQVDBnWENKYmIySnFaV04wSUVGeWNtRjVYVndpWEc1OVhHNWNibjBzZTMxZExERXpPbHRtZFc1amRHbHZiaWh5WlhGMWFYSmxMRzF2WkhWc1pTeGxlSEJ2Y25SektYdGNiblpoY2lCd1lYUmphQ0E5SUhKbGNYVnBjbVVvWENJdUwzWmtiMjB2Y0dGMFkyZ3Vhbk5jSWlsY2JseHViVzlrZFd4bExtVjRjRzl5ZEhNZ1BTQndZWFJqYUZ4dVhHNTlMSHRjSWk0dmRtUnZiUzl3WVhSamFDNXFjMXdpT2pFNGZWMHNNVFE2VzJaMWJtTjBhVzl1S0hKbGNYVnBjbVVzYlc5a2RXeGxMR1Y0Y0c5eWRITXBlMXh1ZG1GeUlHbHpUMkpxWldOMElEMGdjbVZ4ZFdseVpTaGNJbWx6TFc5aWFtVmpkRndpS1Z4dWRtRnlJR2x6U0c5dmF5QTlJSEpsY1hWcGNtVW9YQ0l1TGk5MmJtOWtaUzlwY3kxMmFHOXZheTVxYzF3aUtWeHVYRzV0YjJSMWJHVXVaWGh3YjNKMGN5QTlJR0Z3Y0d4NVVISnZjR1Z5ZEdsbGMxeHVYRzVtZFc1amRHbHZiaUJoY0hCc2VWQnliM0JsY25ScFpYTW9ibTlrWlN3Z2NISnZjSE1zSUhCeVpYWnBiM1Z6S1NCN1hHNGdJQ0FnWm05eUlDaDJZWElnY0hKdmNFNWhiV1VnYVc0Z2NISnZjSE1wSUh0Y2JpQWdJQ0FnSUNBZ2RtRnlJSEJ5YjNCV1lXeDFaU0E5SUhCeWIzQnpXM0J5YjNCT1lXMWxYVnh1WEc0Z0lDQWdJQ0FnSUdsbUlDaHdjbTl3Vm1Gc2RXVWdQVDA5SUhWdVpHVm1hVzVsWkNrZ2UxeHVJQ0FnSUNBZ0lDQWdJQ0FnY21WdGIzWmxVSEp2Y0dWeWRIa29ibTlrWlN3Z2NISnZjRTVoYldVc0lIQnliM0JXWVd4MVpTd2djSEpsZG1sdmRYTXBPMXh1SUNBZ0lDQWdJQ0I5SUdWc2MyVWdhV1lnS0dselNHOXZheWh3Y205d1ZtRnNkV1VwS1NCN1hHNGdJQ0FnSUNBZ0lDQWdJQ0J5WlcxdmRtVlFjbTl3WlhKMGVTaHViMlJsTENCd2NtOXdUbUZ0WlN3Z2NISnZjRlpoYkhWbExDQndjbVYyYVc5MWN5bGNiaUFnSUNBZ0lDQWdJQ0FnSUdsbUlDaHdjbTl3Vm1Gc2RXVXVhRzl2YXlrZ2UxeHVJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lIQnliM0JXWVd4MVpTNW9iMjlyS0c1dlpHVXNYRzRnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUhCeWIzQk9ZVzFsTEZ4dUlDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQndjbVYyYVc5MWN5QS9JSEJ5WlhacGIzVnpXM0J5YjNCT1lXMWxYU0E2SUhWdVpHVm1hVzVsWkNsY2JpQWdJQ0FnSUNBZ0lDQWdJSDFjYmlBZ0lDQWdJQ0FnZlNCbGJITmxJSHRjYmlBZ0lDQWdJQ0FnSUNBZ0lHbG1JQ2hwYzA5aWFtVmpkQ2h3Y205d1ZtRnNkV1VwS1NCN1hHNGdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ2NHRjBZMmhQWW1wbFkzUW9ibTlrWlN3Z2NISnZjSE1zSUhCeVpYWnBiM1Z6TENCd2NtOXdUbUZ0WlN3Z2NISnZjRlpoYkhWbEtUdGNiaUFnSUNBZ0lDQWdJQ0FnSUgwZ1pXeHpaU0I3WEc0Z0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnYm05a1pWdHdjbTl3VG1GdFpWMGdQU0J3Y205d1ZtRnNkV1ZjYmlBZ0lDQWdJQ0FnSUNBZ0lIMWNiaUFnSUNBZ0lDQWdmVnh1SUNBZ0lIMWNibjFjYmx4dVpuVnVZM1JwYjI0Z2NtVnRiM1psVUhKdmNHVnlkSGtvYm05a1pTd2djSEp2Y0U1aGJXVXNJSEJ5YjNCV1lXeDFaU3dnY0hKbGRtbHZkWE1wSUh0Y2JpQWdJQ0JwWmlBb2NISmxkbWx2ZFhNcElIdGNiaUFnSUNBZ0lDQWdkbUZ5SUhCeVpYWnBiM1Z6Vm1Gc2RXVWdQU0J3Y21WMmFXOTFjMXR3Y205d1RtRnRaVjFjYmx4dUlDQWdJQ0FnSUNCcFppQW9JV2x6U0c5dmF5aHdjbVYyYVc5MWMxWmhiSFZsS1NrZ2UxeHVJQ0FnSUNBZ0lDQWdJQ0FnYVdZZ0tIQnliM0JPWVcxbElEMDlQU0JjSW1GMGRISnBZblYwWlhOY0lpa2dlMXh1SUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJR1p2Y2lBb2RtRnlJR0YwZEhKT1lXMWxJR2x1SUhCeVpYWnBiM1Z6Vm1Gc2RXVXBJSHRjYmlBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ2JtOWtaUzV5WlcxdmRtVkJkSFJ5YVdKMWRHVW9ZWFIwY2s1aGJXVXBYRzRnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdmVnh1SUNBZ0lDQWdJQ0FnSUNBZ2ZTQmxiSE5sSUdsbUlDaHdjbTl3VG1GdFpTQTlQVDBnWENKemRIbHNaVndpS1NCN1hHNGdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ1ptOXlJQ2gyWVhJZ2FTQnBiaUJ3Y21WMmFXOTFjMVpoYkhWbEtTQjdYRzRnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUc1dlpHVXVjM1I1YkdWYmFWMGdQU0JjSWx3aVhHNGdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ2ZWeHVJQ0FnSUNBZ0lDQWdJQ0FnZlNCbGJITmxJR2xtSUNoMGVYQmxiMllnY0hKbGRtbHZkWE5XWVd4MVpTQTlQVDBnWENKemRISnBibWRjSWlrZ2UxeHVJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lHNXZaR1ZiY0hKdmNFNWhiV1ZkSUQwZ1hDSmNJbHh1SUNBZ0lDQWdJQ0FnSUNBZ2ZTQmxiSE5sSUh0Y2JpQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNCdWIyUmxXM0J5YjNCT1lXMWxYU0E5SUc1MWJHeGNiaUFnSUNBZ0lDQWdJQ0FnSUgxY2JpQWdJQ0FnSUNBZ2ZTQmxiSE5sSUdsbUlDaHdjbVYyYVc5MWMxWmhiSFZsTG5WdWFHOXZheWtnZTF4dUlDQWdJQ0FnSUNBZ0lDQWdjSEpsZG1sdmRYTldZV3gxWlM1MWJtaHZiMnNvYm05a1pTd2djSEp2Y0U1aGJXVXNJSEJ5YjNCV1lXeDFaU2xjYmlBZ0lDQWdJQ0FnZlZ4dUlDQWdJSDFjYm4xY2JseHVablZ1WTNScGIyNGdjR0YwWTJoUFltcGxZM1FvYm05a1pTd2djSEp2Y0hNc0lIQnlaWFpwYjNWekxDQndjbTl3VG1GdFpTd2djSEp2Y0ZaaGJIVmxLU0I3WEc0Z0lDQWdkbUZ5SUhCeVpYWnBiM1Z6Vm1Gc2RXVWdQU0J3Y21WMmFXOTFjeUEvSUhCeVpYWnBiM1Z6VzNCeWIzQk9ZVzFsWFNBNklIVnVaR1ZtYVc1bFpGeHVYRzRnSUNBZ0x5OGdVMlYwSUdGMGRISnBZblYwWlhOY2JpQWdJQ0JwWmlBb2NISnZjRTVoYldVZ1BUMDlJRndpWVhSMGNtbGlkWFJsYzF3aUtTQjdYRzRnSUNBZ0lDQWdJR1p2Y2lBb2RtRnlJR0YwZEhKT1lXMWxJR2x1SUhCeWIzQldZV3gxWlNrZ2UxeHVJQ0FnSUNBZ0lDQWdJQ0FnZG1GeUlHRjBkSEpXWVd4MVpTQTlJSEJ5YjNCV1lXeDFaVnRoZEhSeVRtRnRaVjFjYmx4dUlDQWdJQ0FnSUNBZ0lDQWdhV1lnS0dGMGRISldZV3gxWlNBOVBUMGdkVzVrWldacGJtVmtLU0I3WEc0Z0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnYm05a1pTNXlaVzF2ZG1WQmRIUnlhV0oxZEdVb1lYUjBjazVoYldVcFhHNGdJQ0FnSUNBZ0lDQWdJQ0I5SUdWc2MyVWdlMXh1SUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJRzV2WkdVdWMyVjBRWFIwY21saWRYUmxLR0YwZEhKT1lXMWxMQ0JoZEhSeVZtRnNkV1VwWEc0Z0lDQWdJQ0FnSUNBZ0lDQjlYRzRnSUNBZ0lDQWdJSDFjYmx4dUlDQWdJQ0FnSUNCeVpYUjFjbTVjYmlBZ0lDQjlYRzVjYmlBZ0lDQnBaaWh3Y21WMmFXOTFjMVpoYkhWbElDWW1JR2x6VDJKcVpXTjBLSEJ5WlhacGIzVnpWbUZzZFdVcElDWW1YRzRnSUNBZ0lDQWdJR2RsZEZCeWIzUnZkSGx3WlNod2NtVjJhVzkxYzFaaGJIVmxLU0FoUFQwZ1oyVjBVSEp2ZEc5MGVYQmxLSEJ5YjNCV1lXeDFaU2twSUh0Y2JpQWdJQ0FnSUNBZ2JtOWtaVnR3Y205d1RtRnRaVjBnUFNCd2NtOXdWbUZzZFdWY2JpQWdJQ0FnSUNBZ2NtVjBkWEp1WEc0Z0lDQWdmVnh1WEc0Z0lDQWdhV1lnS0NGcGMwOWlhbVZqZENodWIyUmxXM0J5YjNCT1lXMWxYU2twSUh0Y2JpQWdJQ0FnSUNBZ2JtOWtaVnR3Y205d1RtRnRaVjBnUFNCN2ZWeHVJQ0FnSUgxY2JseHVJQ0FnSUhaaGNpQnlaWEJzWVdObGNpQTlJSEJ5YjNCT1lXMWxJRDA5UFNCY0luTjBlV3hsWENJZ1B5QmNJbHdpSURvZ2RXNWtaV1pwYm1Wa1hHNWNiaUFnSUNCbWIzSWdLSFpoY2lCcklHbHVJSEJ5YjNCV1lXeDFaU2tnZTF4dUlDQWdJQ0FnSUNCMllYSWdkbUZzZFdVZ1BTQndjbTl3Vm1Gc2RXVmJhMTFjYmlBZ0lDQWdJQ0FnYm05a1pWdHdjbTl3VG1GdFpWMWJhMTBnUFNBb2RtRnNkV1VnUFQwOUlIVnVaR1ZtYVc1bFpDa2dQeUJ5WlhCc1lXTmxjaUE2SUhaaGJIVmxYRzRnSUNBZ2ZWeHVmVnh1WEc1bWRXNWpkR2x2YmlCblpYUlFjbTkwYjNSNWNHVW9kbUZzZFdVcElIdGNiaUFnSUNCcFppQW9UMkpxWldOMExtZGxkRkJ5YjNSdmRIbHdaVTltS1NCN1hHNGdJQ0FnSUNBZ0lISmxkSFZ5YmlCUFltcGxZM1F1WjJWMFVISnZkRzkwZVhCbFQyWW9kbUZzZFdVcFhHNGdJQ0FnZlNCbGJITmxJR2xtSUNoMllXeDFaUzVmWDNCeWIzUnZYMThwSUh0Y2JpQWdJQ0FnSUNBZ2NtVjBkWEp1SUhaaGJIVmxMbDlmY0hKdmRHOWZYMXh1SUNBZ0lIMGdaV3h6WlNCcFppQW9kbUZzZFdVdVkyOXVjM1J5ZFdOMGIzSXBJSHRjYmlBZ0lDQWdJQ0FnY21WMGRYSnVJSFpoYkhWbExtTnZibk4wY25WamRHOXlMbkJ5YjNSdmRIbHdaVnh1SUNBZ0lIMWNibjFjYmx4dWZTeDdYQ0l1TGk5MmJtOWtaUzlwY3kxMmFHOXZheTVxYzF3aU9qSTJMRndpYVhNdGIySnFaV04wWENJNk1URjlYU3d4TlRwYlpuVnVZM1JwYjI0b2NtVnhkV2x5WlN4dGIyUjFiR1VzWlhod2IzSjBjeWw3WEc1MllYSWdaRzlqZFcxbGJuUWdQU0J5WlhGMWFYSmxLRndpWjJ4dlltRnNMMlJ2WTNWdFpXNTBYQ0lwWEc1Y2JuWmhjaUJoY0hCc2VWQnliM0JsY25ScFpYTWdQU0J5WlhGMWFYSmxLRndpTGk5aGNIQnNlUzF3Y205d1pYSjBhV1Z6WENJcFhHNWNiblpoY2lCcGMxWk9iMlJsSUQwZ2NtVnhkV2x5WlNoY0lpNHVMM1p1YjJSbEwybHpMWFp1YjJSbExtcHpYQ0lwWEc1MllYSWdhWE5XVkdWNGRDQTlJSEpsY1hWcGNtVW9YQ0l1TGk5MmJtOWtaUzlwY3kxMmRHVjRkQzVxYzF3aUtWeHVkbUZ5SUdselYybGtaMlYwSUQwZ2NtVnhkV2x5WlNoY0lpNHVMM1p1YjJSbEwybHpMWGRwWkdkbGRDNXFjMXdpS1Z4dWRtRnlJR2hoYm1Sc1pWUm9kVzVySUQwZ2NtVnhkV2x5WlNoY0lpNHVMM1p1YjJSbEwyaGhibVJzWlMxMGFIVnVheTVxYzF3aUtWeHVYRzV0YjJSMWJHVXVaWGh3YjNKMGN5QTlJR055WldGMFpVVnNaVzFsYm5SY2JseHVablZ1WTNScGIyNGdZM0psWVhSbFJXeGxiV1Z1ZENoMmJtOWtaU3dnYjNCMGN5a2dlMXh1SUNBZ0lIWmhjaUJrYjJNZ1BTQnZjSFJ6SUQ4Z2IzQjBjeTVrYjJOMWJXVnVkQ0I4ZkNCa2IyTjFiV1Z1ZENBNklHUnZZM1Z0Wlc1MFhHNGdJQ0FnZG1GeUlIZGhjbTRnUFNCdmNIUnpJRDhnYjNCMGN5NTNZWEp1SURvZ2JuVnNiRnh1WEc0Z0lDQWdkbTV2WkdVZ1BTQm9ZVzVrYkdWVWFIVnVheWgyYm05a1pTa3VZVnh1WEc0Z0lDQWdhV1lnS0dselYybGtaMlYwS0hadWIyUmxLU2tnZTF4dUlDQWdJQ0FnSUNCeVpYUjFjbTRnZG01dlpHVXVhVzVwZENncFhHNGdJQ0FnZlNCbGJITmxJR2xtSUNocGMxWlVaWGgwS0hadWIyUmxLU2tnZTF4dUlDQWdJQ0FnSUNCeVpYUjFjbTRnWkc5akxtTnlaV0YwWlZSbGVIUk9iMlJsS0hadWIyUmxMblJsZUhRcFhHNGdJQ0FnZlNCbGJITmxJR2xtSUNnaGFYTldUbTlrWlNoMmJtOWtaU2twSUh0Y2JpQWdJQ0FnSUNBZ2FXWWdLSGRoY200cElIdGNiaUFnSUNBZ0lDQWdJQ0FnSUhkaGNtNG9YQ0pKZEdWdElHbHpJRzV2ZENCaElIWmhiR2xrSUhacGNuUjFZV3dnWkc5dElHNXZaR1ZjSWl3Z2RtNXZaR1VwWEc0Z0lDQWdJQ0FnSUgxY2JpQWdJQ0FnSUNBZ2NtVjBkWEp1SUc1MWJHeGNiaUFnSUNCOVhHNWNiaUFnSUNCMllYSWdibTlrWlNBOUlDaDJibTlrWlM1dVlXMWxjM0JoWTJVZ1BUMDlJRzUxYkd3cElEOWNiaUFnSUNBZ0lDQWdaRzlqTG1OeVpXRjBaVVZzWlcxbGJuUW9kbTV2WkdVdWRHRm5UbUZ0WlNrZ09seHVJQ0FnSUNBZ0lDQmtiMk11WTNKbFlYUmxSV3hsYldWdWRFNVRLSFp1YjJSbExtNWhiV1Z6Y0dGalpTd2dkbTV2WkdVdWRHRm5UbUZ0WlNsY2JseHVJQ0FnSUhaaGNpQndjbTl3Y3lBOUlIWnViMlJsTG5CeWIzQmxjblJwWlhOY2JpQWdJQ0JoY0hCc2VWQnliM0JsY25ScFpYTW9ibTlrWlN3Z2NISnZjSE1wWEc1Y2JpQWdJQ0IyWVhJZ1kyaHBiR1J5Wlc0Z1BTQjJibTlrWlM1amFHbHNaSEpsYmx4dVhHNGdJQ0FnWm05eUlDaDJZWElnYVNBOUlEQTdJR2tnUENCamFHbHNaSEpsYmk1c1pXNW5kR2c3SUdrckt5a2dlMXh1SUNBZ0lDQWdJQ0IyWVhJZ1kyaHBiR1JPYjJSbElEMGdZM0psWVhSbFJXeGxiV1Z1ZENoamFHbHNaSEpsYmx0cFhTd2diM0IwY3lsY2JpQWdJQ0FnSUNBZ2FXWWdLR05vYVd4a1RtOWtaU2tnZTF4dUlDQWdJQ0FnSUNBZ0lDQWdibTlrWlM1aGNIQmxibVJEYUdsc1pDaGphR2xzWkU1dlpHVXBYRzRnSUNBZ0lDQWdJSDFjYmlBZ0lDQjlYRzVjYmlBZ0lDQnlaWFIxY200Z2JtOWtaVnh1ZlZ4dVhHNTlMSHRjSWk0dUwzWnViMlJsTDJoaGJtUnNaUzEwYUhWdWF5NXFjMXdpT2pJMExGd2lMaTR2ZG01dlpHVXZhWE10ZG01dlpHVXVhbk5jSWpveU55eGNJaTR1TDNadWIyUmxMMmx6TFhaMFpYaDBMbXB6WENJNk1qZ3NYQ0l1TGk5MmJtOWtaUzlwY3kxM2FXUm5aWFF1YW5OY0lqb3lPU3hjSWk0dllYQndiSGt0Y0hKdmNHVnlkR2xsYzF3aU9qRTBMRndpWjJ4dlltRnNMMlJ2WTNWdFpXNTBYQ0k2TVRCOVhTd3hOanBiWm5WdVkzUnBiMjRvY21WeGRXbHlaU3h0YjJSMWJHVXNaWGh3YjNKMGN5bDdYRzR2THlCTllYQnpJR0VnZG1seWRIVmhiQ0JFVDAwZ2RISmxaU0J2Ym5SdklHRWdjbVZoYkNCRVQwMGdkSEpsWlNCcGJpQmhiaUJsWm1acFkybGxiblFnYldGdWJtVnlMbHh1THk4Z1YyVWdaRzl1SjNRZ2QyRnVkQ0IwYnlCeVpXRmtJR0ZzYkNCdlppQjBhR1VnUkU5TklHNXZaR1Z6SUdsdUlIUm9aU0IwY21WbElITnZJSGRsSUhWelpWeHVMeThnZEdobElHbHVMVzl5WkdWeUlIUnlaV1VnYVc1a1pYaHBibWNnZEc4Z1pXeHBiV2x1WVhSbElISmxZM1Z5YzJsdmJpQmtiM2R1SUdObGNuUmhhVzRnWW5KaGJtTm9aWE11WEc0dkx5QlhaU0J2Ym14NUlISmxZM1Z5YzJVZ2FXNTBieUJoSUVSUFRTQnViMlJsSUdsbUlIZGxJR3R1YjNjZ2RHaGhkQ0JwZENCamIyNTBZV2x1Y3lCaElHTm9hV3hrSUc5bVhHNHZMeUJwYm5SbGNtVnpkQzVjYmx4dWRtRnlJRzV2UTJocGJHUWdQU0I3ZlZ4dVhHNXRiMlIxYkdVdVpYaHdiM0owY3lBOUlHUnZiVWx1WkdWNFhHNWNibVoxYm1OMGFXOXVJR1J2YlVsdVpHVjRLSEp2YjNST2IyUmxMQ0IwY21WbExDQnBibVJwWTJWekxDQnViMlJsY3lrZ2UxeHVJQ0FnSUdsbUlDZ2hhVzVrYVdObGN5QjhmQ0JwYm1ScFkyVnpMbXhsYm1kMGFDQTlQVDBnTUNrZ2UxeHVJQ0FnSUNBZ0lDQnlaWFIxY200Z2UzMWNiaUFnSUNCOUlHVnNjMlVnZTF4dUlDQWdJQ0FnSUNCcGJtUnBZMlZ6TG5OdmNuUW9ZWE5qWlc1a2FXNW5LVnh1SUNBZ0lDQWdJQ0J5WlhSMWNtNGdjbVZqZFhKelpTaHliMjkwVG05a1pTd2dkSEpsWlN3Z2FXNWthV05sY3l3Z2JtOWtaWE1zSURBcFhHNGdJQ0FnZlZ4dWZWeHVYRzVtZFc1amRHbHZiaUJ5WldOMWNuTmxLSEp2YjNST2IyUmxMQ0IwY21WbExDQnBibVJwWTJWekxDQnViMlJsY3l3Z2NtOXZkRWx1WkdWNEtTQjdYRzRnSUNBZ2JtOWtaWE1nUFNCdWIyUmxjeUI4ZkNCN2ZWeHVYRzVjYmlBZ0lDQnBaaUFvY205dmRFNXZaR1VwSUh0Y2JpQWdJQ0FnSUNBZ2FXWWdLR2x1WkdWNFNXNVNZVzVuWlNocGJtUnBZMlZ6TENCeWIyOTBTVzVrWlhnc0lISnZiM1JKYm1SbGVDa3BJSHRjYmlBZ0lDQWdJQ0FnSUNBZ0lHNXZaR1Z6VzNKdmIzUkpibVJsZUYwZ1BTQnliMjkwVG05a1pWeHVJQ0FnSUNBZ0lDQjlYRzVjYmlBZ0lDQWdJQ0FnZG1GeUlIWkRhR2xzWkhKbGJpQTlJSFJ5WldVdVkyaHBiR1J5Wlc1Y2JseHVJQ0FnSUNBZ0lDQnBaaUFvZGtOb2FXeGtjbVZ1S1NCN1hHNWNiaUFnSUNBZ0lDQWdJQ0FnSUhaaGNpQmphR2xzWkU1dlpHVnpJRDBnY205dmRFNXZaR1V1WTJocGJHUk9iMlJsYzF4dVhHNGdJQ0FnSUNBZ0lDQWdJQ0JtYjNJZ0tIWmhjaUJwSUQwZ01Ec2dhU0E4SUhSeVpXVXVZMmhwYkdSeVpXNHViR1Z1WjNSb095QnBLeXNwSUh0Y2JpQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNCeWIyOTBTVzVrWlhnZ0t6MGdNVnh1WEc0Z0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnZG1GeUlIWkRhR2xzWkNBOUlIWkRhR2xzWkhKbGJsdHBYU0I4ZkNCdWIwTm9hV3hrWEc0Z0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnZG1GeUlHNWxlSFJKYm1SbGVDQTlJSEp2YjNSSmJtUmxlQ0FySUNoMlEyaHBiR1F1WTI5MWJuUWdmSHdnTUNsY2JseHVJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDOHZJSE5yYVhBZ2NtVmpkWEp6YVc5dUlHUnZkMjRnZEdobElIUnlaV1VnYVdZZ2RHaGxjbVVnWVhKbElHNXZJRzV2WkdWeklHUnZkMjRnYUdWeVpWeHVJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lHbG1JQ2hwYm1SbGVFbHVVbUZ1WjJVb2FXNWthV05sY3l3Z2NtOXZkRWx1WkdWNExDQnVaWGgwU1c1a1pYZ3BLU0I3WEc0Z0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lISmxZM1Z5YzJVb1kyaHBiR1JPYjJSbGMxdHBYU3dnZGtOb2FXeGtMQ0JwYm1ScFkyVnpMQ0J1YjJSbGN5d2djbTl2ZEVsdVpHVjRLVnh1SUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJSDFjYmx4dUlDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUhKdmIzUkpibVJsZUNBOUlHNWxlSFJKYm1SbGVGeHVJQ0FnSUNBZ0lDQWdJQ0FnZlZ4dUlDQWdJQ0FnSUNCOVhHNGdJQ0FnZlZ4dVhHNGdJQ0FnY21WMGRYSnVJRzV2WkdWelhHNTlYRzVjYmk4dklFSnBibUZ5ZVNCelpXRnlZMmdnWm05eUlHRnVJR2x1WkdWNElHbHVJSFJvWlNCcGJuUmxjblpoYkNCYmJHVm1kQ3dnY21sbmFIUmRYRzVtZFc1amRHbHZiaUJwYm1SbGVFbHVVbUZ1WjJVb2FXNWthV05sY3l3Z2JHVm1kQ3dnY21sbmFIUXBJSHRjYmlBZ0lDQnBaaUFvYVc1a2FXTmxjeTVzWlc1bmRHZ2dQVDA5SURBcElIdGNiaUFnSUNBZ0lDQWdjbVYwZFhKdUlHWmhiSE5sWEc0Z0lDQWdmVnh1WEc0Z0lDQWdkbUZ5SUcxcGJrbHVaR1Y0SUQwZ01GeHVJQ0FnSUhaaGNpQnRZWGhKYm1SbGVDQTlJR2x1WkdsalpYTXViR1Z1WjNSb0lDMGdNVnh1SUNBZ0lIWmhjaUJqZFhKeVpXNTBTVzVrWlhoY2JpQWdJQ0IyWVhJZ1kzVnljbVZ1ZEVsMFpXMWNibHh1SUNBZ0lIZG9hV3hsSUNodGFXNUpibVJsZUNBOFBTQnRZWGhKYm1SbGVDa2dlMXh1SUNBZ0lDQWdJQ0JqZFhKeVpXNTBTVzVrWlhnZ1BTQW9LRzFoZUVsdVpHVjRJQ3NnYldsdVNXNWtaWGdwSUM4Z01pa2dQajRnTUZ4dUlDQWdJQ0FnSUNCamRYSnlaVzUwU1hSbGJTQTlJR2x1WkdsalpYTmJZM1Z5Y21WdWRFbHVaR1Y0WFZ4dVhHNGdJQ0FnSUNBZ0lHbG1JQ2h0YVc1SmJtUmxlQ0E5UFQwZ2JXRjRTVzVrWlhncElIdGNiaUFnSUNBZ0lDQWdJQ0FnSUhKbGRIVnliaUJqZFhKeVpXNTBTWFJsYlNBK1BTQnNaV1owSUNZbUlHTjFjbkpsYm5SSmRHVnRJRHc5SUhKcFoyaDBYRzRnSUNBZ0lDQWdJSDBnWld4elpTQnBaaUFvWTNWeWNtVnVkRWwwWlcwZ1BDQnNaV1owS1NCN1hHNGdJQ0FnSUNBZ0lDQWdJQ0J0YVc1SmJtUmxlQ0E5SUdOMWNuSmxiblJKYm1SbGVDQXJJREZjYmlBZ0lDQWdJQ0FnZlNCbGJITmxJQ0JwWmlBb1kzVnljbVZ1ZEVsMFpXMGdQaUJ5YVdkb2RDa2dlMXh1SUNBZ0lDQWdJQ0FnSUNBZ2JXRjRTVzVrWlhnZ1BTQmpkWEp5Wlc1MFNXNWtaWGdnTFNBeFhHNGdJQ0FnSUNBZ0lIMGdaV3h6WlNCN1hHNGdJQ0FnSUNBZ0lDQWdJQ0J5WlhSMWNtNGdkSEoxWlZ4dUlDQWdJQ0FnSUNCOVhHNGdJQ0FnZlZ4dVhHNGdJQ0FnY21WMGRYSnVJR1poYkhObE8xeHVmVnh1WEc1bWRXNWpkR2x2YmlCaGMyTmxibVJwYm1jb1lTd2dZaWtnZTF4dUlDQWdJSEpsZEhWeWJpQmhJRDRnWWlBL0lERWdPaUF0TVZ4dWZWeHVYRzU5TEh0OVhTd3hOenBiWm5WdVkzUnBiMjRvY21WeGRXbHlaU3h0YjJSMWJHVXNaWGh3YjNKMGN5bDdYRzUyWVhJZ1lYQndiSGxRY205d1pYSjBhV1Z6SUQwZ2NtVnhkV2x5WlNoY0lpNHZZWEJ3YkhrdGNISnZjR1Z5ZEdsbGMxd2lLVnh1WEc1MllYSWdhWE5YYVdSblpYUWdQU0J5WlhGMWFYSmxLRndpTGk0dmRtNXZaR1V2YVhNdGQybGtaMlYwTG1welhDSXBYRzUyWVhJZ1ZsQmhkR05vSUQwZ2NtVnhkV2x5WlNoY0lpNHVMM1p1YjJSbEwzWndZWFJqYUM1cWMxd2lLVnh1WEc1MllYSWdkWEJrWVhSbFYybGtaMlYwSUQwZ2NtVnhkV2x5WlNoY0lpNHZkWEJrWVhSbExYZHBaR2RsZEZ3aUtWeHVYRzV0YjJSMWJHVXVaWGh3YjNKMGN5QTlJR0Z3Y0d4NVVHRjBZMmhjYmx4dVpuVnVZM1JwYjI0Z1lYQndiSGxRWVhSamFDaDJjR0YwWTJnc0lHUnZiVTV2WkdVc0lISmxibVJsY2s5d2RHbHZibk1wSUh0Y2JpQWdJQ0IyWVhJZ2RIbHdaU0E5SUhad1lYUmphQzUwZVhCbFhHNGdJQ0FnZG1GeUlIWk9iMlJsSUQwZ2RuQmhkR05vTG5aT2IyUmxYRzRnSUNBZ2RtRnlJSEJoZEdOb0lEMGdkbkJoZEdOb0xuQmhkR05vWEc1Y2JpQWdJQ0J6ZDJsMFkyZ2dLSFI1Y0dVcElIdGNiaUFnSUNBZ0lDQWdZMkZ6WlNCV1VHRjBZMmd1VWtWTlQxWkZPbHh1SUNBZ0lDQWdJQ0FnSUNBZ2NtVjBkWEp1SUhKbGJXOTJaVTV2WkdVb1pHOXRUbTlrWlN3Z2RrNXZaR1VwWEc0Z0lDQWdJQ0FnSUdOaGMyVWdWbEJoZEdOb0xrbE9VMFZTVkRwY2JpQWdJQ0FnSUNBZ0lDQWdJSEpsZEhWeWJpQnBibk5sY25ST2IyUmxLR1J2YlU1dlpHVXNJSEJoZEdOb0xDQnlaVzVrWlhKUGNIUnBiMjV6S1Z4dUlDQWdJQ0FnSUNCallYTmxJRlpRWVhSamFDNVdWRVZZVkRwY2JpQWdJQ0FnSUNBZ0lDQWdJSEpsZEhWeWJpQnpkSEpwYm1kUVlYUmphQ2hrYjIxT2IyUmxMQ0IyVG05a1pTd2djR0YwWTJnc0lISmxibVJsY2s5d2RHbHZibk1wWEc0Z0lDQWdJQ0FnSUdOaGMyVWdWbEJoZEdOb0xsZEpSRWRGVkRwY2JpQWdJQ0FnSUNBZ0lDQWdJSEpsZEhWeWJpQjNhV1JuWlhSUVlYUmphQ2hrYjIxT2IyUmxMQ0IyVG05a1pTd2djR0YwWTJnc0lISmxibVJsY2s5d2RHbHZibk1wWEc0Z0lDQWdJQ0FnSUdOaGMyVWdWbEJoZEdOb0xsWk9UMFJGT2x4dUlDQWdJQ0FnSUNBZ0lDQWdjbVYwZFhKdUlIWk9iMlJsVUdGMFkyZ29aRzl0VG05a1pTd2dkazV2WkdVc0lIQmhkR05vTENCeVpXNWtaWEpQY0hScGIyNXpLVnh1SUNBZ0lDQWdJQ0JqWVhObElGWlFZWFJqYUM1UFVrUkZVanBjYmlBZ0lDQWdJQ0FnSUNBZ0lISmxiM0prWlhKRGFHbHNaSEpsYmloa2IyMU9iMlJsTENCd1lYUmphQ2xjYmlBZ0lDQWdJQ0FnSUNBZ0lISmxkSFZ5YmlCa2IyMU9iMlJsWEc0Z0lDQWdJQ0FnSUdOaGMyVWdWbEJoZEdOb0xsQlNUMUJUT2x4dUlDQWdJQ0FnSUNBZ0lDQWdZWEJ3YkhsUWNtOXdaWEowYVdWektHUnZiVTV2WkdVc0lIQmhkR05vTENCMlRtOWtaUzV3Y205d1pYSjBhV1Z6S1Z4dUlDQWdJQ0FnSUNBZ0lDQWdjbVYwZFhKdUlHUnZiVTV2WkdWY2JpQWdJQ0FnSUNBZ1kyRnpaU0JXVUdGMFkyZ3VWRWhWVGtzNlhHNGdJQ0FnSUNBZ0lDQWdJQ0J5WlhSMWNtNGdjbVZ3YkdGalpWSnZiM1FvWkc5dFRtOWtaU3hjYmlBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0J5Wlc1a1pYSlBjSFJwYjI1ekxuQmhkR05vS0dSdmJVNXZaR1VzSUhCaGRHTm9MQ0J5Wlc1a1pYSlBjSFJwYjI1ektTbGNiaUFnSUNBZ0lDQWdaR1ZtWVhWc2REcGNiaUFnSUNBZ0lDQWdJQ0FnSUhKbGRIVnliaUJrYjIxT2IyUmxYRzRnSUNBZ2ZWeHVmVnh1WEc1bWRXNWpkR2x2YmlCeVpXMXZkbVZPYjJSbEtHUnZiVTV2WkdVc0lIWk9iMlJsS1NCN1hHNGdJQ0FnZG1GeUlIQmhjbVZ1ZEU1dlpHVWdQU0JrYjIxT2IyUmxMbkJoY21WdWRFNXZaR1ZjYmx4dUlDQWdJR2xtSUNod1lYSmxiblJPYjJSbEtTQjdYRzRnSUNBZ0lDQWdJSEJoY21WdWRFNXZaR1V1Y21WdGIzWmxRMmhwYkdRb1pHOXRUbTlrWlNsY2JpQWdJQ0I5WEc1Y2JpQWdJQ0JrWlhOMGNtOTVWMmxrWjJWMEtHUnZiVTV2WkdVc0lIWk9iMlJsS1R0Y2JseHVJQ0FnSUhKbGRIVnliaUJ1ZFd4c1hHNTlYRzVjYm1aMWJtTjBhVzl1SUdsdWMyVnlkRTV2WkdVb2NHRnlaVzUwVG05a1pTd2dkazV2WkdVc0lISmxibVJsY2s5d2RHbHZibk1wSUh0Y2JpQWdJQ0IyWVhJZ2JtVjNUbTlrWlNBOUlISmxibVJsY2s5d2RHbHZibk11Y21WdVpHVnlLSFpPYjJSbExDQnlaVzVrWlhKUGNIUnBiMjV6S1Z4dVhHNGdJQ0FnYVdZZ0tIQmhjbVZ1ZEU1dlpHVXBJSHRjYmlBZ0lDQWdJQ0FnY0dGeVpXNTBUbTlrWlM1aGNIQmxibVJEYUdsc1pDaHVaWGRPYjJSbEtWeHVJQ0FnSUgxY2JseHVJQ0FnSUhKbGRIVnliaUJ3WVhKbGJuUk9iMlJsWEc1OVhHNWNibVoxYm1OMGFXOXVJSE4wY21sdVoxQmhkR05vS0dSdmJVNXZaR1VzSUd4bFpuUldUbTlrWlN3Z2RsUmxlSFFzSUhKbGJtUmxjazl3ZEdsdmJuTXBJSHRjYmlBZ0lDQjJZWElnYm1WM1RtOWtaVnh1WEc0Z0lDQWdhV1lnS0dSdmJVNXZaR1V1Ym05a1pWUjVjR1VnUFQwOUlETXBJSHRjYmlBZ0lDQWdJQ0FnWkc5dFRtOWtaUzV5WlhCc1lXTmxSR0YwWVNnd0xDQmtiMjFPYjJSbExteGxibWQwYUN3Z2RsUmxlSFF1ZEdWNGRDbGNiaUFnSUNBZ0lDQWdibVYzVG05a1pTQTlJR1J2YlU1dlpHVmNiaUFnSUNCOUlHVnNjMlVnZTF4dUlDQWdJQ0FnSUNCMllYSWdjR0Z5Wlc1MFRtOWtaU0E5SUdSdmJVNXZaR1V1Y0dGeVpXNTBUbTlrWlZ4dUlDQWdJQ0FnSUNCdVpYZE9iMlJsSUQwZ2NtVnVaR1Z5VDNCMGFXOXVjeTV5Wlc1a1pYSW9kbFJsZUhRc0lISmxibVJsY2s5d2RHbHZibk1wWEc1Y2JpQWdJQ0FnSUNBZ2FXWWdLSEJoY21WdWRFNXZaR1VnSmlZZ2JtVjNUbTlrWlNBaFBUMGdaRzl0VG05a1pTa2dlMXh1SUNBZ0lDQWdJQ0FnSUNBZ2NHRnlaVzUwVG05a1pTNXlaWEJzWVdObFEyaHBiR1FvYm1WM1RtOWtaU3dnWkc5dFRtOWtaU2xjYmlBZ0lDQWdJQ0FnZlZ4dUlDQWdJSDFjYmx4dUlDQWdJSEpsZEhWeWJpQnVaWGRPYjJSbFhHNTlYRzVjYm1aMWJtTjBhVzl1SUhkcFpHZGxkRkJoZEdOb0tHUnZiVTV2WkdVc0lHeGxablJXVG05a1pTd2dkMmxrWjJWMExDQnlaVzVrWlhKUGNIUnBiMjV6S1NCN1hHNGdJQ0FnZG1GeUlIVndaR0YwYVc1bklEMGdkWEJrWVhSbFYybGtaMlYwS0d4bFpuUldUbTlrWlN3Z2QybGtaMlYwS1Z4dUlDQWdJSFpoY2lCdVpYZE9iMlJsWEc1Y2JpQWdJQ0JwWmlBb2RYQmtZWFJwYm1jcElIdGNiaUFnSUNBZ0lDQWdibVYzVG05a1pTQTlJSGRwWkdkbGRDNTFjR1JoZEdVb2JHVm1kRlpPYjJSbExDQmtiMjFPYjJSbEtTQjhmQ0JrYjIxT2IyUmxYRzRnSUNBZ2ZTQmxiSE5sSUh0Y2JpQWdJQ0FnSUNBZ2JtVjNUbTlrWlNBOUlISmxibVJsY2s5d2RHbHZibk11Y21WdVpHVnlLSGRwWkdkbGRDd2djbVZ1WkdWeVQzQjBhVzl1Y3lsY2JpQWdJQ0I5WEc1Y2JpQWdJQ0IyWVhJZ2NHRnlaVzUwVG05a1pTQTlJR1J2YlU1dlpHVXVjR0Z5Wlc1MFRtOWtaVnh1WEc0Z0lDQWdhV1lnS0hCaGNtVnVkRTV2WkdVZ0ppWWdibVYzVG05a1pTQWhQVDBnWkc5dFRtOWtaU2tnZTF4dUlDQWdJQ0FnSUNCd1lYSmxiblJPYjJSbExuSmxjR3hoWTJWRGFHbHNaQ2h1WlhkT2IyUmxMQ0JrYjIxT2IyUmxLVnh1SUNBZ0lIMWNibHh1SUNBZ0lHbG1JQ2doZFhCa1lYUnBibWNwSUh0Y2JpQWdJQ0FnSUNBZ1pHVnpkSEp2ZVZkcFpHZGxkQ2hrYjIxT2IyUmxMQ0JzWldaMFZrNXZaR1VwWEc0Z0lDQWdmVnh1WEc0Z0lDQWdjbVYwZFhKdUlHNWxkMDV2WkdWY2JuMWNibHh1Wm5WdVkzUnBiMjRnZGs1dlpHVlFZWFJqYUNoa2IyMU9iMlJsTENCc1pXWjBWazV2WkdVc0lIWk9iMlJsTENCeVpXNWtaWEpQY0hScGIyNXpLU0I3WEc0Z0lDQWdkbUZ5SUhCaGNtVnVkRTV2WkdVZ1BTQmtiMjFPYjJSbExuQmhjbVZ1ZEU1dlpHVmNiaUFnSUNCMllYSWdibVYzVG05a1pTQTlJSEpsYm1SbGNrOXdkR2x2Ym5NdWNtVnVaR1Z5S0haT2IyUmxMQ0J5Wlc1a1pYSlBjSFJwYjI1ektWeHVYRzRnSUNBZ2FXWWdLSEJoY21WdWRFNXZaR1VnSmlZZ2JtVjNUbTlrWlNBaFBUMGdaRzl0VG05a1pTa2dlMXh1SUNBZ0lDQWdJQ0J3WVhKbGJuUk9iMlJsTG5KbGNHeGhZMlZEYUdsc1pDaHVaWGRPYjJSbExDQmtiMjFPYjJSbEtWeHVJQ0FnSUgxY2JseHVJQ0FnSUhKbGRIVnliaUJ1WlhkT2IyUmxYRzU5WEc1Y2JtWjFibU4wYVc5dUlHUmxjM1J5YjNsWGFXUm5aWFFvWkc5dFRtOWtaU3dnZHlrZ2UxeHVJQ0FnSUdsbUlDaDBlWEJsYjJZZ2R5NWtaWE4wY205NUlEMDlQU0JjSW1aMWJtTjBhVzl1WENJZ0ppWWdhWE5YYVdSblpYUW9keWtwSUh0Y2JpQWdJQ0FnSUNBZ2R5NWtaWE4wY205NUtHUnZiVTV2WkdVcFhHNGdJQ0FnZlZ4dWZWeHVYRzVtZFc1amRHbHZiaUJ5Wlc5eVpHVnlRMmhwYkdSeVpXNG9aRzl0VG05a1pTd2diVzkyWlhNcElIdGNiaUFnSUNCMllYSWdZMmhwYkdST2IyUmxjeUE5SUdSdmJVNXZaR1V1WTJocGJHUk9iMlJsYzF4dUlDQWdJSFpoY2lCclpYbE5ZWEFnUFNCN2ZWeHVJQ0FnSUhaaGNpQnViMlJsWEc0Z0lDQWdkbUZ5SUhKbGJXOTJaVnh1SUNBZ0lIWmhjaUJwYm5ObGNuUmNibHh1SUNBZ0lHWnZjaUFvZG1GeUlHa2dQU0F3T3lCcElEd2diVzkyWlhNdWNtVnRiM1psY3k1c1pXNW5kR2c3SUdrckt5a2dlMXh1SUNBZ0lDQWdJQ0J5WlcxdmRtVWdQU0J0YjNabGN5NXlaVzF2ZG1WelcybGRYRzRnSUNBZ0lDQWdJRzV2WkdVZ1BTQmphR2xzWkU1dlpHVnpXM0psYlc5MlpTNW1jbTl0WFZ4dUlDQWdJQ0FnSUNCcFppQW9jbVZ0YjNabExtdGxlU2tnZTF4dUlDQWdJQ0FnSUNBZ0lDQWdhMlY1VFdGd1czSmxiVzkyWlM1clpYbGRJRDBnYm05a1pWeHVJQ0FnSUNBZ0lDQjlYRzRnSUNBZ0lDQWdJR1J2YlU1dlpHVXVjbVZ0YjNabFEyaHBiR1FvYm05a1pTbGNiaUFnSUNCOVhHNWNiaUFnSUNCMllYSWdiR1Z1WjNSb0lEMGdZMmhwYkdST2IyUmxjeTVzWlc1bmRHaGNiaUFnSUNCbWIzSWdLSFpoY2lCcUlEMGdNRHNnYWlBOElHMXZkbVZ6TG1sdWMyVnlkSE11YkdWdVozUm9PeUJxS3lzcElIdGNiaUFnSUNBZ0lDQWdhVzV6WlhKMElEMGdiVzkyWlhNdWFXNXpaWEowYzF0cVhWeHVJQ0FnSUNBZ0lDQnViMlJsSUQwZ2EyVjVUV0Z3VzJsdWMyVnlkQzVyWlhsZFhHNGdJQ0FnSUNBZ0lDOHZJSFJvYVhNZ2FYTWdkR2hsSUhkbGFYSmtaWE4wSUdKMVp5QnBKM1psSUdWMlpYSWdjMlZsYmlCcGJpQjNaV0pyYVhSY2JpQWdJQ0FnSUNBZ1pHOXRUbTlrWlM1cGJuTmxjblJDWldadmNtVW9ibTlrWlN3Z2FXNXpaWEowTG5SdklENDlJR3hsYm1kMGFDc3JJRDhnYm5Wc2JDQTZJR05vYVd4a1RtOWtaWE5iYVc1elpYSjBMblJ2WFNsY2JpQWdJQ0I5WEc1OVhHNWNibVoxYm1OMGFXOXVJSEpsY0d4aFkyVlNiMjkwS0c5c1pGSnZiM1FzSUc1bGQxSnZiM1FwSUh0Y2JpQWdJQ0JwWmlBb2IyeGtVbTl2ZENBbUppQnVaWGRTYjI5MElDWW1JRzlzWkZKdmIzUWdJVDA5SUc1bGQxSnZiM1FnSmlZZ2IyeGtVbTl2ZEM1d1lYSmxiblJPYjJSbEtTQjdYRzRnSUNBZ0lDQWdJRzlzWkZKdmIzUXVjR0Z5Wlc1MFRtOWtaUzV5WlhCc1lXTmxRMmhwYkdRb2JtVjNVbTl2ZEN3Z2IyeGtVbTl2ZENsY2JpQWdJQ0I5WEc1Y2JpQWdJQ0J5WlhSMWNtNGdibVYzVW05dmREdGNibjFjYmx4dWZTeDdYQ0l1TGk5MmJtOWtaUzlwY3kxM2FXUm5aWFF1YW5OY0lqb3lPU3hjSWk0dUwzWnViMlJsTDNad1lYUmphQzVxYzF3aU9qTXlMRndpTGk5aGNIQnNlUzF3Y205d1pYSjBhV1Z6WENJNk1UUXNYQ0l1TDNWd1pHRjBaUzEzYVdSblpYUmNJam94T1gxZExERTRPbHRtZFc1amRHbHZiaWh5WlhGMWFYSmxMRzF2WkhWc1pTeGxlSEJ2Y25SektYdGNiblpoY2lCa2IyTjFiV1Z1ZENBOUlISmxjWFZwY21Vb1hDSm5iRzlpWVd3dlpHOWpkVzFsYm5SY0lpbGNiblpoY2lCcGMwRnljbUY1SUQwZ2NtVnhkV2x5WlNoY0luZ3RhWE10WVhKeVlYbGNJaWxjYmx4dWRtRnlJSEpsYm1SbGNpQTlJSEpsY1hWcGNtVW9YQ0l1TDJOeVpXRjBaUzFsYkdWdFpXNTBYQ0lwWEc1MllYSWdaRzl0U1c1a1pYZ2dQU0J5WlhGMWFYSmxLRndpTGk5a2IyMHRhVzVrWlhoY0lpbGNiblpoY2lCd1lYUmphRTl3SUQwZ2NtVnhkV2x5WlNoY0lpNHZjR0YwWTJndGIzQmNJaWxjYm0xdlpIVnNaUzVsZUhCdmNuUnpJRDBnY0dGMFkyaGNibHh1Wm5WdVkzUnBiMjRnY0dGMFkyZ29jbTl2ZEU1dlpHVXNJSEJoZEdOb1pYTXNJSEpsYm1SbGNrOXdkR2x2Ym5NcElIdGNiaUFnSUNCeVpXNWtaWEpQY0hScGIyNXpJRDBnY21WdVpHVnlUM0IwYVc5dWN5QjhmQ0I3ZlZ4dUlDQWdJSEpsYm1SbGNrOXdkR2x2Ym5NdWNHRjBZMmdnUFNCeVpXNWtaWEpQY0hScGIyNXpMbkJoZEdOb0lDWW1JSEpsYm1SbGNrOXdkR2x2Ym5NdWNHRjBZMmdnSVQwOUlIQmhkR05vWEc0Z0lDQWdJQ0FnSUQ4Z2NtVnVaR1Z5VDNCMGFXOXVjeTV3WVhSamFGeHVJQ0FnSUNBZ0lDQTZJSEJoZEdOb1VtVmpkWEp6YVhabFhHNGdJQ0FnY21WdVpHVnlUM0IwYVc5dWN5NXlaVzVrWlhJZ1BTQnlaVzVrWlhKUGNIUnBiMjV6TG5KbGJtUmxjaUI4ZkNCeVpXNWtaWEpjYmx4dUlDQWdJSEpsZEhWeWJpQnlaVzVrWlhKUGNIUnBiMjV6TG5CaGRHTm9LSEp2YjNST2IyUmxMQ0J3WVhSamFHVnpMQ0J5Wlc1a1pYSlBjSFJwYjI1ektWeHVmVnh1WEc1bWRXNWpkR2x2YmlCd1lYUmphRkpsWTNWeWMybDJaU2h5YjI5MFRtOWtaU3dnY0dGMFkyaGxjeXdnY21WdVpHVnlUM0IwYVc5dWN5a2dlMXh1SUNBZ0lIWmhjaUJwYm1ScFkyVnpJRDBnY0dGMFkyaEpibVJwWTJWektIQmhkR05vWlhNcFhHNWNiaUFnSUNCcFppQW9hVzVrYVdObGN5NXNaVzVuZEdnZ1BUMDlJREFwSUh0Y2JpQWdJQ0FnSUNBZ2NtVjBkWEp1SUhKdmIzUk9iMlJsWEc0Z0lDQWdmVnh1WEc0Z0lDQWdkbUZ5SUdsdVpHVjRJRDBnWkc5dFNXNWtaWGdvY205dmRFNXZaR1VzSUhCaGRHTm9aWE11WVN3Z2FXNWthV05sY3lsY2JpQWdJQ0IyWVhJZ2IzZHVaWEpFYjJOMWJXVnVkQ0E5SUhKdmIzUk9iMlJsTG05M2JtVnlSRzlqZFcxbGJuUmNibHh1SUNBZ0lHbG1JQ2doY21WdVpHVnlUM0IwYVc5dWN5NWtiMk4xYldWdWRDQW1KaUJ2ZDI1bGNrUnZZM1Z0Wlc1MElDRTlQU0JrYjJOMWJXVnVkQ2tnZTF4dUlDQWdJQ0FnSUNCeVpXNWtaWEpQY0hScGIyNXpMbVJ2WTNWdFpXNTBJRDBnYjNkdVpYSkViMk4xYldWdWRGeHVJQ0FnSUgxY2JseHVJQ0FnSUdadmNpQW9kbUZ5SUdrZ1BTQXdPeUJwSUR3Z2FXNWthV05sY3k1c1pXNW5kR2c3SUdrckt5a2dlMXh1SUNBZ0lDQWdJQ0IyWVhJZ2JtOWtaVWx1WkdWNElEMGdhVzVrYVdObGMxdHBYVnh1SUNBZ0lDQWdJQ0J5YjI5MFRtOWtaU0E5SUdGd2NHeDVVR0YwWTJnb2NtOXZkRTV2WkdVc1hHNGdJQ0FnSUNBZ0lDQWdJQ0JwYm1SbGVGdHViMlJsU1c1a1pYaGRMRnh1SUNBZ0lDQWdJQ0FnSUNBZ2NHRjBZMmhsYzF0dWIyUmxTVzVrWlhoZExGeHVJQ0FnSUNBZ0lDQWdJQ0FnY21WdVpHVnlUM0IwYVc5dWN5bGNiaUFnSUNCOVhHNWNiaUFnSUNCeVpYUjFjbTRnY205dmRFNXZaR1ZjYm4xY2JseHVablZ1WTNScGIyNGdZWEJ3YkhsUVlYUmphQ2h5YjI5MFRtOWtaU3dnWkc5dFRtOWtaU3dnY0dGMFkyaE1hWE4wTENCeVpXNWtaWEpQY0hScGIyNXpLU0I3WEc0Z0lDQWdhV1lnS0NGa2IyMU9iMlJsS1NCN1hHNGdJQ0FnSUNBZ0lISmxkSFZ5YmlCeWIyOTBUbTlrWlZ4dUlDQWdJSDFjYmx4dUlDQWdJSFpoY2lCdVpYZE9iMlJsWEc1Y2JpQWdJQ0JwWmlBb2FYTkJjbkpoZVNod1lYUmphRXhwYzNRcEtTQjdYRzRnSUNBZ0lDQWdJR1p2Y2lBb2RtRnlJR2tnUFNBd095QnBJRHdnY0dGMFkyaE1hWE4wTG14bGJtZDBhRHNnYVNzcktTQjdYRzRnSUNBZ0lDQWdJQ0FnSUNCdVpYZE9iMlJsSUQwZ2NHRjBZMmhQY0Nod1lYUmphRXhwYzNSYmFWMHNJR1J2YlU1dlpHVXNJSEpsYm1SbGNrOXdkR2x2Ym5NcFhHNWNiaUFnSUNBZ0lDQWdJQ0FnSUdsbUlDaGtiMjFPYjJSbElEMDlQU0J5YjI5MFRtOWtaU2tnZTF4dUlDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUhKdmIzUk9iMlJsSUQwZ2JtVjNUbTlrWlZ4dUlDQWdJQ0FnSUNBZ0lDQWdmVnh1SUNBZ0lDQWdJQ0I5WEc0Z0lDQWdmU0JsYkhObElIdGNiaUFnSUNBZ0lDQWdibVYzVG05a1pTQTlJSEJoZEdOb1QzQW9jR0YwWTJoTWFYTjBMQ0JrYjIxT2IyUmxMQ0J5Wlc1a1pYSlBjSFJwYjI1ektWeHVYRzRnSUNBZ0lDQWdJR2xtSUNoa2IyMU9iMlJsSUQwOVBTQnliMjkwVG05a1pTa2dlMXh1SUNBZ0lDQWdJQ0FnSUNBZ2NtOXZkRTV2WkdVZ1BTQnVaWGRPYjJSbFhHNGdJQ0FnSUNBZ0lIMWNiaUFnSUNCOVhHNWNiaUFnSUNCeVpYUjFjbTRnY205dmRFNXZaR1ZjYm4xY2JseHVablZ1WTNScGIyNGdjR0YwWTJoSmJtUnBZMlZ6S0hCaGRHTm9aWE1wSUh0Y2JpQWdJQ0IyWVhJZ2FXNWthV05sY3lBOUlGdGRYRzVjYmlBZ0lDQm1iM0lnS0haaGNpQnJaWGtnYVc0Z2NHRjBZMmhsY3lrZ2UxeHVJQ0FnSUNBZ0lDQnBaaUFvYTJWNUlDRTlQU0JjSW1GY0lpa2dlMXh1SUNBZ0lDQWdJQ0FnSUNBZ2FXNWthV05sY3k1d2RYTm9LRTUxYldKbGNpaHJaWGtwS1Z4dUlDQWdJQ0FnSUNCOVhHNGdJQ0FnZlZ4dVhHNGdJQ0FnY21WMGRYSnVJR2x1WkdsalpYTmNibjFjYmx4dWZTeDdYQ0l1TDJOeVpXRjBaUzFsYkdWdFpXNTBYQ0k2TVRVc1hDSXVMMlJ2YlMxcGJtUmxlRndpT2pFMkxGd2lMaTl3WVhSamFDMXZjRndpT2pFM0xGd2laMnh2WW1Gc0wyUnZZM1Z0Wlc1MFhDSTZNVEFzWENKNExXbHpMV0Z5Y21GNVhDSTZNVEo5WFN3eE9UcGJablZ1WTNScGIyNG9jbVZ4ZFdseVpTeHRiMlIxYkdVc1pYaHdiM0owY3lsN1hHNTJZWElnYVhOWGFXUm5aWFFnUFNCeVpYRjFhWEpsS0Z3aUxpNHZkbTV2WkdVdmFYTXRkMmxrWjJWMExtcHpYQ0lwWEc1Y2JtMXZaSFZzWlM1bGVIQnZjblJ6SUQwZ2RYQmtZWFJsVjJsa1oyVjBYRzVjYm1aMWJtTjBhVzl1SUhWd1pHRjBaVmRwWkdkbGRDaGhMQ0JpS1NCN1hHNGdJQ0FnYVdZZ0tHbHpWMmxrWjJWMEtHRXBJQ1ltSUdselYybGtaMlYwS0dJcEtTQjdYRzRnSUNBZ0lDQWdJR2xtSUNoY0ltNWhiV1ZjSWlCcGJpQmhJQ1ltSUZ3aWJtRnRaVndpSUdsdUlHSXBJSHRjYmlBZ0lDQWdJQ0FnSUNBZ0lISmxkSFZ5YmlCaExtbGtJRDA5UFNCaUxtbGtYRzRnSUNBZ0lDQWdJSDBnWld4elpTQjdYRzRnSUNBZ0lDQWdJQ0FnSUNCeVpYUjFjbTRnWVM1cGJtbDBJRDA5UFNCaUxtbHVhWFJjYmlBZ0lDQWdJQ0FnZlZ4dUlDQWdJSDFjYmx4dUlDQWdJSEpsZEhWeWJpQm1ZV3h6WlZ4dWZWeHVYRzU5TEh0Y0lpNHVMM1p1YjJSbEwybHpMWGRwWkdkbGRDNXFjMXdpT2pJNWZWMHNNakE2VzJaMWJtTjBhVzl1S0hKbGNYVnBjbVVzYlc5a2RXeGxMR1Y0Y0c5eWRITXBlMXh1SjNWelpTQnpkSEpwWTNRbk8xeHVYRzUyWVhJZ1JYWlRkRzl5WlNBOUlISmxjWFZwY21Vb0oyVjJMWE4wYjNKbEp5azdYRzVjYm0xdlpIVnNaUzVsZUhCdmNuUnpJRDBnUlhaSWIyOXJPMXh1WEc1bWRXNWpkR2x2YmlCRmRraHZiMnNvZG1Gc2RXVXBJSHRjYmlBZ0lDQnBaaUFvSVNoMGFHbHpJR2x1YzNSaGJtTmxiMllnUlhaSWIyOXJLU2tnZTF4dUlDQWdJQ0FnSUNCeVpYUjFjbTRnYm1WM0lFVjJTRzl2YXloMllXeDFaU2s3WEc0Z0lDQWdmVnh1WEc0Z0lDQWdkR2hwY3k1MllXeDFaU0E5SUhaaGJIVmxPMXh1ZlZ4dVhHNUZka2h2YjJzdWNISnZkRzkwZVhCbExtaHZiMnNnUFNCbWRXNWpkR2x2YmlBb2JtOWtaU3dnY0hKdmNHVnlkSGxPWVcxbEtTQjdYRzRnSUNBZ2RtRnlJR1Z6SUQwZ1JYWlRkRzl5WlNodWIyUmxLVHRjYmlBZ0lDQjJZWElnY0hKdmNFNWhiV1VnUFNCd2NtOXdaWEowZVU1aGJXVXVjM1ZpYzNSeUtETXBPMXh1WEc0Z0lDQWdaWE5iY0hKdmNFNWhiV1ZkSUQwZ2RHaHBjeTUyWVd4MVpUdGNibjA3WEc1Y2JrVjJTRzl2YXk1d2NtOTBiM1I1Y0dVdWRXNW9iMjlySUQwZ1puVnVZM1JwYjI0b2JtOWtaU3dnY0hKdmNHVnlkSGxPWVcxbEtTQjdYRzRnSUNBZ2RtRnlJR1Z6SUQwZ1JYWlRkRzl5WlNodWIyUmxLVHRjYmlBZ0lDQjJZWElnY0hKdmNFNWhiV1VnUFNCd2NtOXdaWEowZVU1aGJXVXVjM1ZpYzNSeUtETXBPMXh1WEc0Z0lDQWdaWE5iY0hKdmNFNWhiV1ZkSUQwZ2RXNWtaV1pwYm1Wa08xeHVmVHRjYmx4dWZTeDdYQ0psZGkxemRHOXlaVndpT2pkOVhTd3lNVHBiWm5WdVkzUnBiMjRvY21WeGRXbHlaU3h0YjJSMWJHVXNaWGh3YjNKMGN5bDdYRzRuZFhObElITjBjbWxqZENjN1hHNWNibTF2WkhWc1pTNWxlSEJ2Y25SeklEMGdVMjltZEZObGRFaHZiMnM3WEc1Y2JtWjFibU4wYVc5dUlGTnZablJUWlhSSWIyOXJLSFpoYkhWbEtTQjdYRzRnSUNBZ2FXWWdLQ0VvZEdocGN5QnBibk4wWVc1alpXOW1JRk52Wm5SVFpYUkliMjlyS1NrZ2UxeHVJQ0FnSUNBZ0lDQnlaWFIxY200Z2JtVjNJRk52Wm5SVFpYUkliMjlyS0haaGJIVmxLVHRjYmlBZ0lDQjlYRzVjYmlBZ0lDQjBhR2x6TG5aaGJIVmxJRDBnZG1Gc2RXVTdYRzU5WEc1Y2JsTnZablJUWlhSSWIyOXJMbkJ5YjNSdmRIbHdaUzVvYjI5cklEMGdablZ1WTNScGIyNGdLRzV2WkdVc0lIQnliM0JsY25SNVRtRnRaU2tnZTF4dUlDQWdJR2xtSUNodWIyUmxXM0J5YjNCbGNuUjVUbUZ0WlYwZ0lUMDlJSFJvYVhNdWRtRnNkV1VwSUh0Y2JpQWdJQ0FnSUNBZ2JtOWtaVnR3Y205d1pYSjBlVTVoYldWZElEMGdkR2hwY3k1MllXeDFaVHRjYmlBZ0lDQjlYRzU5TzF4dVhHNTlMSHQ5WFN3eU1qcGJablZ1WTNScGIyNG9jbVZ4ZFdseVpTeHRiMlIxYkdVc1pYaHdiM0owY3lsN1hHNG5kWE5sSUhOMGNtbGpkQ2M3WEc1Y2JuWmhjaUJwYzBGeWNtRjVJRDBnY21WeGRXbHlaU2duZUMxcGN5MWhjbkpoZVNjcE8xeHVYRzUyWVhJZ1ZrNXZaR1VnUFNCeVpYRjFhWEpsS0NjdUxpOTJibTlrWlM5MmJtOWtaUzVxY3ljcE8xeHVkbUZ5SUZaVVpYaDBJRDBnY21WeGRXbHlaU2duTGk0dmRtNXZaR1V2ZG5SbGVIUXVhbk1uS1R0Y2JuWmhjaUJwYzFaT2IyUmxJRDBnY21WeGRXbHlaU2duTGk0dmRtNXZaR1V2YVhNdGRtNXZaR1VuS1R0Y2JuWmhjaUJwYzFaVVpYaDBJRDBnY21WeGRXbHlaU2duTGk0dmRtNXZaR1V2YVhNdGRuUmxlSFFuS1R0Y2JuWmhjaUJwYzFkcFpHZGxkQ0E5SUhKbGNYVnBjbVVvSnk0dUwzWnViMlJsTDJsekxYZHBaR2RsZENjcE8xeHVkbUZ5SUdselNHOXZheUE5SUhKbGNYVnBjbVVvSnk0dUwzWnViMlJsTDJsekxYWm9iMjlySnlrN1hHNTJZWElnYVhOV1ZHaDFibXNnUFNCeVpYRjFhWEpsS0NjdUxpOTJibTlrWlM5cGN5MTBhSFZ1YXljcE8xeHVYRzUyWVhJZ2NHRnljMlZVWVdjZ1BTQnlaWEYxYVhKbEtDY3VMM0JoY25ObExYUmhaeTVxY3ljcE8xeHVkbUZ5SUhOdlpuUlRaWFJJYjI5cklEMGdjbVZ4ZFdseVpTZ25MaTlvYjI5cmN5OXpiMlowTFhObGRDMW9iMjlyTG1wekp5azdYRzUyWVhJZ1pYWkliMjlySUQwZ2NtVnhkV2x5WlNnbkxpOW9iMjlyY3k5bGRpMW9iMjlyTG1wekp5azdYRzVjYm0xdlpIVnNaUzVsZUhCdmNuUnpJRDBnYUR0Y2JseHVablZ1WTNScGIyNGdhQ2gwWVdkT1lXMWxMQ0J3Y205d1pYSjBhV1Z6TENCamFHbHNaSEpsYmlrZ2UxeHVJQ0FnSUhaaGNpQmphR2xzWkU1dlpHVnpJRDBnVzEwN1hHNGdJQ0FnZG1GeUlIUmhaeXdnY0hKdmNITXNJR3RsZVN3Z2JtRnRaWE53WVdObE8xeHVYRzRnSUNBZ2FXWWdLQ0ZqYUdsc1pISmxiaUFtSmlCcGMwTm9hV3hrY21WdUtIQnliM0JsY25ScFpYTXBLU0I3WEc0Z0lDQWdJQ0FnSUdOb2FXeGtjbVZ1SUQwZ2NISnZjR1Z5ZEdsbGN6dGNiaUFnSUNBZ0lDQWdjSEp2Y0hNZ1BTQjdmVHRjYmlBZ0lDQjlYRzVjYmlBZ0lDQndjbTl3Y3lBOUlIQnliM0J6SUh4OElIQnliM0JsY25ScFpYTWdmSHdnZTMwN1hHNGdJQ0FnZEdGbklEMGdjR0Z5YzJWVVlXY29kR0ZuVG1GdFpTd2djSEp2Y0hNcE8xeHVYRzRnSUNBZ0x5OGdjM1Z3Y0c5eWRDQnJaWGx6WEc0Z0lDQWdhV1lnS0hCeWIzQnpMbWhoYzA5M2JsQnliM0JsY25SNUtDZHJaWGtuS1NrZ2UxeHVJQ0FnSUNBZ0lDQnJaWGtnUFNCd2NtOXdjeTVyWlhrN1hHNGdJQ0FnSUNBZ0lIQnliM0J6TG10bGVTQTlJSFZ1WkdWbWFXNWxaRHRjYmlBZ0lDQjlYRzVjYmlBZ0lDQXZMeUJ6ZFhCd2IzSjBJRzVoYldWemNHRmpaVnh1SUNBZ0lHbG1JQ2h3Y205d2N5NW9ZWE5QZDI1UWNtOXdaWEowZVNnbmJtRnRaWE53WVdObEp5a3BJSHRjYmlBZ0lDQWdJQ0FnYm1GdFpYTndZV05sSUQwZ2NISnZjSE11Ym1GdFpYTndZV05sTzF4dUlDQWdJQ0FnSUNCd2NtOXdjeTV1WVcxbGMzQmhZMlVnUFNCMWJtUmxabWx1WldRN1hHNGdJQ0FnZlZ4dVhHNGdJQ0FnTHk4Z1ptbDRJR04xY25OdmNpQmlkV2RjYmlBZ0lDQnBaaUFvZEdGbklEMDlQU0FuU1U1UVZWUW5JQ1ltWEc0Z0lDQWdJQ0FnSUNGdVlXMWxjM0JoWTJVZ0ppWmNiaUFnSUNBZ0lDQWdjSEp2Y0hNdWFHRnpUM2R1VUhKdmNHVnlkSGtvSjNaaGJIVmxKeWtnSmlaY2JpQWdJQ0FnSUNBZ2NISnZjSE11ZG1Gc2RXVWdJVDA5SUhWdVpHVm1hVzVsWkNBbUpseHVJQ0FnSUNBZ0lDQWhhWE5JYjI5cktIQnliM0J6TG5aaGJIVmxLVnh1SUNBZ0lDa2dlMXh1SUNBZ0lDQWdJQ0J3Y205d2N5NTJZV3gxWlNBOUlITnZablJUWlhSSWIyOXJLSEJ5YjNCekxuWmhiSFZsS1R0Y2JpQWdJQ0I5WEc1Y2JpQWdJQ0IwY21GdWMyWnZjbTFRY205d1pYSjBhV1Z6S0hCeWIzQnpLVHRjYmx4dUlDQWdJR2xtSUNoamFHbHNaSEpsYmlBaFBUMGdkVzVrWldacGJtVmtJQ1ltSUdOb2FXeGtjbVZ1SUNFOVBTQnVkV3hzS1NCN1hHNGdJQ0FnSUNBZ0lHRmtaRU5vYVd4a0tHTm9hV3hrY21WdUxDQmphR2xzWkU1dlpHVnpMQ0IwWVdjc0lIQnliM0J6S1R0Y2JpQWdJQ0I5WEc1Y2JseHVJQ0FnSUhKbGRIVnliaUJ1WlhjZ1ZrNXZaR1VvZEdGbkxDQndjbTl3Y3l3Z1kyaHBiR1JPYjJSbGN5d2dhMlY1TENCdVlXMWxjM0JoWTJVcE8xeHVmVnh1WEc1bWRXNWpkR2x2YmlCaFpHUkRhR2xzWkNoakxDQmphR2xzWkU1dlpHVnpMQ0IwWVdjc0lIQnliM0J6S1NCN1hHNGdJQ0FnYVdZZ0tIUjVjR1Z2WmlCaklEMDlQU0FuYzNSeWFXNW5KeWtnZTF4dUlDQWdJQ0FnSUNCamFHbHNaRTV2WkdWekxuQjFjMmdvYm1WM0lGWlVaWGgwS0dNcEtUdGNiaUFnSUNCOUlHVnNjMlVnYVdZZ0tIUjVjR1Z2WmlCaklEMDlQU0FuYm5WdFltVnlKeWtnZTF4dUlDQWdJQ0FnSUNCamFHbHNaRTV2WkdWekxuQjFjMmdvYm1WM0lGWlVaWGgwS0ZOMGNtbHVaeWhqS1NrcE8xeHVJQ0FnSUgwZ1pXeHpaU0JwWmlBb2FYTkRhR2xzWkNoaktTa2dlMXh1SUNBZ0lDQWdJQ0JqYUdsc1pFNXZaR1Z6TG5CMWMyZ29ZeWs3WEc0Z0lDQWdmU0JsYkhObElHbG1JQ2hwYzBGeWNtRjVLR01wS1NCN1hHNGdJQ0FnSUNBZ0lHWnZjaUFvZG1GeUlHa2dQU0F3T3lCcElEd2dZeTVzWlc1bmRHZzdJR2tyS3lrZ2UxeHVJQ0FnSUNBZ0lDQWdJQ0FnWVdSa1EyaHBiR1FvWTF0cFhTd2dZMmhwYkdST2IyUmxjeXdnZEdGbkxDQndjbTl3Y3lrN1hHNGdJQ0FnSUNBZ0lIMWNiaUFnSUNCOUlHVnNjMlVnYVdZZ0tHTWdQVDA5SUc1MWJHd2dmSHdnWXlBOVBUMGdkVzVrWldacGJtVmtLU0I3WEc0Z0lDQWdJQ0FnSUhKbGRIVnlianRjYmlBZ0lDQjlJR1ZzYzJVZ2UxeHVJQ0FnSUNBZ0lDQjBhSEp2ZHlCVmJtVjRjR1ZqZEdWa1ZtbHlkSFZoYkVWc1pXMWxiblFvZTF4dUlDQWdJQ0FnSUNBZ0lDQWdabTl5WldsbmJrOWlhbVZqZERvZ1l5eGNiaUFnSUNBZ0lDQWdJQ0FnSUhCaGNtVnVkRlp1YjJSbE9pQjdYRzRnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdkR0ZuVG1GdFpUb2dkR0ZuTEZ4dUlDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUhCeWIzQmxjblJwWlhNNklIQnliM0J6WEc0Z0lDQWdJQ0FnSUNBZ0lDQjlYRzRnSUNBZ0lDQWdJSDBwTzF4dUlDQWdJSDFjYm4xY2JseHVablZ1WTNScGIyNGdkSEpoYm5ObWIzSnRVSEp2Y0dWeWRHbGxjeWh3Y205d2N5a2dlMXh1SUNBZ0lHWnZjaUFvZG1GeUlIQnliM0JPWVcxbElHbHVJSEJ5YjNCektTQjdYRzRnSUNBZ0lDQWdJR2xtSUNod2NtOXdjeTVvWVhOUGQyNVFjbTl3WlhKMGVTaHdjbTl3VG1GdFpTa3BJSHRjYmlBZ0lDQWdJQ0FnSUNBZ0lIWmhjaUIyWVd4MVpTQTlJSEJ5YjNCelczQnliM0JPWVcxbFhUdGNibHh1SUNBZ0lDQWdJQ0FnSUNBZ2FXWWdLR2x6U0c5dmF5aDJZV3gxWlNrcElIdGNiaUFnSUNBZ0lDQWdJQ0FnSUNBZ0lDQmpiMjUwYVc1MVpUdGNiaUFnSUNBZ0lDQWdJQ0FnSUgxY2JseHVJQ0FnSUNBZ0lDQWdJQ0FnYVdZZ0tIQnliM0JPWVcxbExuTjFZbk4wY2lnd0xDQXpLU0E5UFQwZ0oyVjJMU2NwSUh0Y2JpQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBdkx5QmhaR1FnWlhZdFptOXZJSE4xY0hCdmNuUmNiaUFnSUNBZ0lDQWdJQ0FnSUNBZ0lDQndjbTl3YzF0d2NtOXdUbUZ0WlYwZ1BTQmxka2h2YjJzb2RtRnNkV1VwTzF4dUlDQWdJQ0FnSUNBZ0lDQWdmVnh1SUNBZ0lDQWdJQ0I5WEc0Z0lDQWdmVnh1ZlZ4dVhHNW1kVzVqZEdsdmJpQnBjME5vYVd4a0tIZ3BJSHRjYmlBZ0lDQnlaWFIxY200Z2FYTldUbTlrWlNoNEtTQjhmQ0JwYzFaVVpYaDBLSGdwSUh4OElHbHpWMmxrWjJWMEtIZ3BJSHg4SUdselZsUm9kVzVyS0hncE8xeHVmVnh1WEc1bWRXNWpkR2x2YmlCcGMwTm9hV3hrY21WdUtIZ3BJSHRjYmlBZ0lDQnlaWFIxY200Z2RIbHdaVzltSUhnZ1BUMDlJQ2R6ZEhKcGJtY25JSHg4SUdselFYSnlZWGtvZUNrZ2ZId2dhWE5EYUdsc1pDaDRLVHRjYm4xY2JseHVablZ1WTNScGIyNGdWVzVsZUhCbFkzUmxaRlpwY25SMVlXeEZiR1Z0Wlc1MEtHUmhkR0VwSUh0Y2JpQWdJQ0IyWVhJZ1pYSnlJRDBnYm1WM0lFVnljbTl5S0NrN1hHNWNiaUFnSUNCbGNuSXVkSGx3WlNBOUlDZDJhWEowZFdGc0xXaDVjR1Z5YzJOeWFYQjBMblZ1Wlhod1pXTjBaV1F1ZG1seWRIVmhiQzFsYkdWdFpXNTBKenRjYmlBZ0lDQmxjbkl1YldWemMyRm5aU0E5SUNkVmJtVjRjR1ZqZEdWa0lIWnBjblIxWVd3Z1kyaHBiR1FnY0dGemMyVmtJSFJ2SUdnb0tTNWNYRzRuSUN0Y2JpQWdJQ0FnSUNBZ0owVjRjR1ZqZEdWa0lHRWdWazV2WkdVZ0x5QldkR2gxYm1zZ0x5QldWMmxrWjJWMElDOGdjM1J5YVc1bklHSjFkRHBjWEc0bklDdGNiaUFnSUNBZ0lDQWdKMmR2ZERwY1hHNG5JQ3RjYmlBZ0lDQWdJQ0FnWlhKeWIzSlRkSEpwYm1jb1pHRjBZUzVtYjNKbGFXZHVUMkpxWldOMEtTQXJYRzRnSUNBZ0lDQWdJQ2N1WEZ4dUp5QXJYRzRnSUNBZ0lDQWdJQ2RVYUdVZ2NHRnlaVzUwSUhadWIyUmxJR2x6T2x4Y2JpY2dLMXh1SUNBZ0lDQWdJQ0JsY25KdmNsTjBjbWx1Wnloa1lYUmhMbkJoY21WdWRGWnViMlJsS1Z4dUlDQWdJQ0FnSUNBblhGeHVKeUFyWEc0Z0lDQWdJQ0FnSUNkVGRXZG5aWE4wWldRZ1ptbDRPaUJqYUdGdVoyVWdlVzkxY2lCZ2FDZ3VMaTRzSUZzZ0xpNHVJRjBwWUNCallXeHNjMmwwWlM0bk8xeHVJQ0FnSUdWeWNpNW1iM0psYVdkdVQySnFaV04wSUQwZ1pHRjBZUzVtYjNKbGFXZHVUMkpxWldOME8xeHVJQ0FnSUdWeWNpNXdZWEpsYm5SV2JtOWtaU0E5SUdSaGRHRXVjR0Z5Wlc1MFZtNXZaR1U3WEc1Y2JpQWdJQ0J5WlhSMWNtNGdaWEp5TzF4dWZWeHVYRzVtZFc1amRHbHZiaUJsY25KdmNsTjBjbWx1Wnlodlltb3BJSHRjYmlBZ0lDQjBjbmtnZTF4dUlDQWdJQ0FnSUNCeVpYUjFjbTRnU2xOUFRpNXpkSEpwYm1kcFpua29iMkpxTENCdWRXeHNMQ0FuSUNBZ0lDY3BPMXh1SUNBZ0lIMGdZMkYwWTJnZ0tHVXBJSHRjYmlBZ0lDQWdJQ0FnY21WMGRYSnVJRk4wY21sdVp5aHZZbW9wTzF4dUlDQWdJSDFjYm4xY2JseHVmU3g3WENJdUxpOTJibTlrWlM5cGN5MTBhSFZ1YTF3aU9qSTFMRndpTGk0dmRtNXZaR1V2YVhNdGRtaHZiMnRjSWpveU5peGNJaTR1TDNadWIyUmxMMmx6TFhadWIyUmxYQ0k2TWpjc1hDSXVMaTkyYm05a1pTOXBjeTEyZEdWNGRGd2lPakk0TEZ3aUxpNHZkbTV2WkdVdmFYTXRkMmxrWjJWMFhDSTZNamtzWENJdUxpOTJibTlrWlM5MmJtOWtaUzVxYzF3aU9qTXhMRndpTGk0dmRtNXZaR1V2ZG5SbGVIUXVhbk5jSWpvek15eGNJaTR2YUc5dmEzTXZaWFl0YUc5dmF5NXFjMXdpT2pJd0xGd2lMaTlvYjI5cmN5OXpiMlowTFhObGRDMW9iMjlyTG1welhDSTZNakVzWENJdUwzQmhjbk5sTFhSaFp5NXFjMXdpT2pJekxGd2llQzFwY3kxaGNuSmhlVndpT2pFeWZWMHNNak02VzJaMWJtTjBhVzl1S0hKbGNYVnBjbVVzYlc5a2RXeGxMR1Y0Y0c5eWRITXBlMXh1SjNWelpTQnpkSEpwWTNRbk8xeHVYRzUyWVhJZ2MzQnNhWFFnUFNCeVpYRjFhWEpsS0NkaWNtOTNjMlZ5TFhOd2JHbDBKeWs3WEc1Y2JuWmhjaUJqYkdGemMwbGtVM0JzYVhRZ1BTQXZLRnRjWEM0alhUOWJZUzE2UVMxYU1DMDVYRngxTURBM1JpMWNYSFZHUmtaR1h6b3RYU3NwTHp0Y2JuWmhjaUJ1YjNSRGJHRnpjMGxrSUQwZ0wxNWNYQzU4SXk4N1hHNWNibTF2WkhWc1pTNWxlSEJ2Y25SeklEMGdjR0Z5YzJWVVlXYzdYRzVjYm1aMWJtTjBhVzl1SUhCaGNuTmxWR0ZuS0hSaFp5d2djSEp2Y0hNcElIdGNiaUFnSUNCcFppQW9JWFJoWnlrZ2UxeHVJQ0FnSUNBZ0lDQnlaWFIxY200Z0owUkpWaWM3WEc0Z0lDQWdmVnh1WEc0Z0lDQWdkbUZ5SUc1dlNXUWdQU0FoS0hCeWIzQnpMbWhoYzA5M2JsQnliM0JsY25SNUtDZHBaQ2NwS1R0Y2JseHVJQ0FnSUhaaGNpQjBZV2RRWVhKMGN5QTlJSE53YkdsMEtIUmhaeXdnWTJ4aGMzTkpaRk53YkdsMEtUdGNiaUFnSUNCMllYSWdkR0ZuVG1GdFpTQTlJRzUxYkd3N1hHNWNiaUFnSUNCcFppQW9ibTkwUTJ4aGMzTkpaQzUwWlhOMEtIUmhaMUJoY25Seld6RmRLU2tnZTF4dUlDQWdJQ0FnSUNCMFlXZE9ZVzFsSUQwZ0owUkpWaWM3WEc0Z0lDQWdmVnh1WEc0Z0lDQWdkbUZ5SUdOc1lYTnpaWE1zSUhCaGNuUXNJSFI1Y0dVc0lHazdYRzVjYmlBZ0lDQm1iM0lnS0drZ1BTQXdPeUJwSUR3Z2RHRm5VR0Z5ZEhNdWJHVnVaM1JvT3lCcEt5c3BJSHRjYmlBZ0lDQWdJQ0FnY0dGeWRDQTlJSFJoWjFCaGNuUnpXMmxkTzF4dVhHNGdJQ0FnSUNBZ0lHbG1JQ2doY0dGeWRDa2dlMXh1SUNBZ0lDQWdJQ0FnSUNBZ1kyOXVkR2x1ZFdVN1hHNGdJQ0FnSUNBZ0lIMWNibHh1SUNBZ0lDQWdJQ0IwZVhCbElEMGdjR0Z5ZEM1amFHRnlRWFFvTUNrN1hHNWNiaUFnSUNBZ0lDQWdhV1lnS0NGMFlXZE9ZVzFsS1NCN1hHNGdJQ0FnSUNBZ0lDQWdJQ0IwWVdkT1lXMWxJRDBnY0dGeWREdGNiaUFnSUNBZ0lDQWdmU0JsYkhObElHbG1JQ2gwZVhCbElEMDlQU0FuTGljcElIdGNiaUFnSUNBZ0lDQWdJQ0FnSUdOc1lYTnpaWE1nUFNCamJHRnpjMlZ6SUh4OElGdGRPMXh1SUNBZ0lDQWdJQ0FnSUNBZ1kyeGhjM05sY3k1d2RYTm9LSEJoY25RdWMzVmljM1J5YVc1bktERXNJSEJoY25RdWJHVnVaM1JvS1NrN1hHNGdJQ0FnSUNBZ0lIMGdaV3h6WlNCcFppQW9kSGx3WlNBOVBUMGdKeU1uSUNZbUlHNXZTV1FwSUh0Y2JpQWdJQ0FnSUNBZ0lDQWdJSEJ5YjNCekxtbGtJRDBnY0dGeWRDNXpkV0p6ZEhKcGJtY29NU3dnY0dGeWRDNXNaVzVuZEdncE8xeHVJQ0FnSUNBZ0lDQjlYRzRnSUNBZ2ZWeHVYRzRnSUNBZ2FXWWdLR05zWVhOelpYTXBJSHRjYmlBZ0lDQWdJQ0FnYVdZZ0tIQnliM0J6TG1Oc1lYTnpUbUZ0WlNrZ2UxeHVJQ0FnSUNBZ0lDQWdJQ0FnWTJ4aGMzTmxjeTV3ZFhOb0tIQnliM0J6TG1Oc1lYTnpUbUZ0WlNrN1hHNGdJQ0FnSUNBZ0lIMWNibHh1SUNBZ0lDQWdJQ0J3Y205d2N5NWpiR0Z6YzA1aGJXVWdQU0JqYkdGemMyVnpMbXB2YVc0b0p5QW5LVHRjYmlBZ0lDQjlYRzVjYmlBZ0lDQnlaWFIxY200Z2NISnZjSE11Ym1GdFpYTndZV05sSUQ4Z2RHRm5UbUZ0WlNBNklIUmhaMDVoYldVdWRHOVZjSEJsY2tOaGMyVW9LVHRjYm4xY2JseHVmU3g3WENKaWNtOTNjMlZ5TFhOd2JHbDBYQ0k2TlgxZExESTBPbHRtZFc1amRHbHZiaWh5WlhGMWFYSmxMRzF2WkhWc1pTeGxlSEJ2Y25SektYdGNiblpoY2lCcGMxWk9iMlJsSUQwZ2NtVnhkV2x5WlNoY0lpNHZhWE10ZG01dlpHVmNJaWxjYm5aaGNpQnBjMVpVWlhoMElEMGdjbVZ4ZFdseVpTaGNJaTR2YVhNdGRuUmxlSFJjSWlsY2JuWmhjaUJwYzFkcFpHZGxkQ0E5SUhKbGNYVnBjbVVvWENJdUwybHpMWGRwWkdkbGRGd2lLVnh1ZG1GeUlHbHpWR2gxYm1zZ1BTQnlaWEYxYVhKbEtGd2lMaTlwY3kxMGFIVnVhMXdpS1Z4dVhHNXRiMlIxYkdVdVpYaHdiM0owY3lBOUlHaGhibVJzWlZSb2RXNXJYRzVjYm1aMWJtTjBhVzl1SUdoaGJtUnNaVlJvZFc1cktHRXNJR0lwSUh0Y2JpQWdJQ0IyWVhJZ2NtVnVaR1Z5WldSQklEMGdZVnh1SUNBZ0lIWmhjaUJ5Wlc1a1pYSmxaRUlnUFNCaVhHNWNiaUFnSUNCcFppQW9hWE5VYUhWdWF5aGlLU2tnZTF4dUlDQWdJQ0FnSUNCeVpXNWtaWEpsWkVJZ1BTQnlaVzVrWlhKVWFIVnVheWhpTENCaEtWeHVJQ0FnSUgxY2JseHVJQ0FnSUdsbUlDaHBjMVJvZFc1cktHRXBLU0I3WEc0Z0lDQWdJQ0FnSUhKbGJtUmxjbVZrUVNBOUlISmxibVJsY2xSb2RXNXJLR0VzSUc1MWJHd3BYRzRnSUNBZ2ZWeHVYRzRnSUNBZ2NtVjBkWEp1SUh0Y2JpQWdJQ0FnSUNBZ1lUb2djbVZ1WkdWeVpXUkJMRnh1SUNBZ0lDQWdJQ0JpT2lCeVpXNWtaWEpsWkVKY2JpQWdJQ0I5WEc1OVhHNWNibVoxYm1OMGFXOXVJSEpsYm1SbGNsUm9kVzVyS0hSb2RXNXJMQ0J3Y21WMmFXOTFjeWtnZTF4dUlDQWdJSFpoY2lCeVpXNWtaWEpsWkZSb2RXNXJJRDBnZEdoMWJtc3VkbTV2WkdWY2JseHVJQ0FnSUdsbUlDZ2hjbVZ1WkdWeVpXUlVhSFZ1YXlrZ2UxeHVJQ0FnSUNBZ0lDQnlaVzVrWlhKbFpGUm9kVzVySUQwZ2RHaDFibXN1ZG01dlpHVWdQU0IwYUhWdWF5NXlaVzVrWlhJb2NISmxkbWx2ZFhNcFhHNGdJQ0FnZlZ4dVhHNGdJQ0FnYVdZZ0tDRW9hWE5XVG05a1pTaHlaVzVrWlhKbFpGUm9kVzVyS1NCOGZGeHVJQ0FnSUNBZ0lDQWdJQ0FnYVhOV1ZHVjRkQ2h5Wlc1a1pYSmxaRlJvZFc1cktTQjhmRnh1SUNBZ0lDQWdJQ0FnSUNBZ2FYTlhhV1JuWlhRb2NtVnVaR1Z5WldSVWFIVnVheWtwS1NCN1hHNGdJQ0FnSUNBZ0lIUm9jbTkzSUc1bGR5QkZjbkp2Y2loY0luUm9kVzVySUdScFpDQnViM1FnY21WMGRYSnVJR0VnZG1Gc2FXUWdibTlrWlZ3aUtUdGNiaUFnSUNCOVhHNWNiaUFnSUNCeVpYUjFjbTRnY21WdVpHVnlaV1JVYUhWdWExeHVmVnh1WEc1OUxIdGNJaTR2YVhNdGRHaDFibXRjSWpveU5TeGNJaTR2YVhNdGRtNXZaR1ZjSWpveU55eGNJaTR2YVhNdGRuUmxlSFJjSWpveU9DeGNJaTR2YVhNdGQybGtaMlYwWENJNk1qbDlYU3d5TlRwYlpuVnVZM1JwYjI0b2NtVnhkV2x5WlN4dGIyUjFiR1VzWlhod2IzSjBjeWw3WEc1dGIyUjFiR1V1Wlhod2IzSjBjeUE5SUdselZHaDFibXRjYmx4dVpuVnVZM1JwYjI0Z2FYTlVhSFZ1YXloMEtTQjdYRzRnSUNBZ2NtVjBkWEp1SUhRZ0ppWWdkQzUwZVhCbElEMDlQU0JjSWxSb2RXNXJYQ0pjYm4xY2JseHVmU3g3ZlYwc01qWTZXMloxYm1OMGFXOXVLSEpsY1hWcGNtVXNiVzlrZFd4bExHVjRjRzl5ZEhNcGUxeHViVzlrZFd4bExtVjRjRzl5ZEhNZ1BTQnBjMGh2YjJ0Y2JseHVablZ1WTNScGIyNGdhWE5JYjI5cktHaHZiMnNwSUh0Y2JpQWdJQ0J5WlhSMWNtNGdhRzl2YXlBbUpseHVJQ0FnSUNBZ0tIUjVjR1Z2WmlCb2IyOXJMbWh2YjJzZ1BUMDlJRndpWm5WdVkzUnBiMjVjSWlBbUppQWhhRzl2YXk1b1lYTlBkMjVRY205d1pYSjBlU2hjSW1odmIydGNJaWtnZkh4Y2JpQWdJQ0FnSUNCMGVYQmxiMllnYUc5dmF5NTFibWh2YjJzZ1BUMDlJRndpWm5WdVkzUnBiMjVjSWlBbUppQWhhRzl2YXk1b1lYTlBkMjVRY205d1pYSjBlU2hjSW5WdWFHOXZhMXdpS1NsY2JuMWNibHh1ZlN4N2ZWMHNNamM2VzJaMWJtTjBhVzl1S0hKbGNYVnBjbVVzYlc5a2RXeGxMR1Y0Y0c5eWRITXBlMXh1ZG1GeUlIWmxjbk5wYjI0Z1BTQnlaWEYxYVhKbEtGd2lMaTkyWlhKemFXOXVYQ0lwWEc1Y2JtMXZaSFZzWlM1bGVIQnZjblJ6SUQwZ2FYTldhWEowZFdGc1RtOWtaVnh1WEc1bWRXNWpkR2x2YmlCcGMxWnBjblIxWVd4T2IyUmxLSGdwSUh0Y2JpQWdJQ0J5WlhSMWNtNGdlQ0FtSmlCNExuUjVjR1VnUFQwOUlGd2lWbWx5ZEhWaGJFNXZaR1ZjSWlBbUppQjRMblpsY25OcGIyNGdQVDA5SUhabGNuTnBiMjVjYm4xY2JseHVmU3g3WENJdUwzWmxjbk5wYjI1Y0lqb3pNSDFkTERJNE9sdG1kVzVqZEdsdmJpaHlaWEYxYVhKbExHMXZaSFZzWlN4bGVIQnZjblJ6S1h0Y2JuWmhjaUIyWlhKemFXOXVJRDBnY21WeGRXbHlaU2hjSWk0dmRtVnljMmx2Ymx3aUtWeHVYRzV0YjJSMWJHVXVaWGh3YjNKMGN5QTlJR2x6Vm1seWRIVmhiRlJsZUhSY2JseHVablZ1WTNScGIyNGdhWE5XYVhKMGRXRnNWR1Y0ZENoNEtTQjdYRzRnSUNBZ2NtVjBkWEp1SUhnZ0ppWWdlQzUwZVhCbElEMDlQU0JjSWxacGNuUjFZV3hVWlhoMFhDSWdKaVlnZUM1MlpYSnphVzl1SUQwOVBTQjJaWEp6YVc5dVhHNTlYRzVjYm4wc2Uxd2lMaTkyWlhKemFXOXVYQ0k2TXpCOVhTd3lPVHBiWm5WdVkzUnBiMjRvY21WeGRXbHlaU3h0YjJSMWJHVXNaWGh3YjNKMGN5bDdYRzV0YjJSMWJHVXVaWGh3YjNKMGN5QTlJR2x6VjJsa1oyVjBYRzVjYm1aMWJtTjBhVzl1SUdselYybGtaMlYwS0hjcElIdGNiaUFnSUNCeVpYUjFjbTRnZHlBbUppQjNMblI1Y0dVZ1BUMDlJRndpVjJsa1oyVjBYQ0pjYm4xY2JseHVmU3g3ZlYwc016QTZXMloxYm1OMGFXOXVLSEpsY1hWcGNtVXNiVzlrZFd4bExHVjRjRzl5ZEhNcGUxeHViVzlrZFd4bExtVjRjRzl5ZEhNZ1BTQmNJakpjSWx4dVhHNTlMSHQ5WFN3ek1UcGJablZ1WTNScGIyNG9jbVZ4ZFdseVpTeHRiMlIxYkdVc1pYaHdiM0owY3lsN1hHNTJZWElnZG1WeWMybHZiaUE5SUhKbGNYVnBjbVVvWENJdUwzWmxjbk5wYjI1Y0lpbGNiblpoY2lCcGMxWk9iMlJsSUQwZ2NtVnhkV2x5WlNoY0lpNHZhWE10ZG01dlpHVmNJaWxjYm5aaGNpQnBjMWRwWkdkbGRDQTlJSEpsY1hWcGNtVW9YQ0l1TDJsekxYZHBaR2RsZEZ3aUtWeHVkbUZ5SUdselZHaDFibXNnUFNCeVpYRjFhWEpsS0Z3aUxpOXBjeTEwYUhWdWExd2lLVnh1ZG1GeUlHbHpWa2h2YjJzZ1BTQnlaWEYxYVhKbEtGd2lMaTlwY3kxMmFHOXZhMXdpS1Z4dVhHNXRiMlIxYkdVdVpYaHdiM0owY3lBOUlGWnBjblIxWVd4T2IyUmxYRzVjYm5aaGNpQnViMUJ5YjNCbGNuUnBaWE1nUFNCN2ZWeHVkbUZ5SUc1dlEyaHBiR1J5Wlc0Z1BTQmJYVnh1WEc1bWRXNWpkR2x2YmlCV2FYSjBkV0ZzVG05a1pTaDBZV2RPWVcxbExDQndjbTl3WlhKMGFXVnpMQ0JqYUdsc1pISmxiaXdnYTJWNUxDQnVZVzFsYzNCaFkyVXBJSHRjYmlBZ0lDQjBhR2x6TG5SaFowNWhiV1VnUFNCMFlXZE9ZVzFsWEc0Z0lDQWdkR2hwY3k1d2NtOXdaWEowYVdWeklEMGdjSEp2Y0dWeWRHbGxjeUI4ZkNCdWIxQnliM0JsY25ScFpYTmNiaUFnSUNCMGFHbHpMbU5vYVd4a2NtVnVJRDBnWTJocGJHUnlaVzRnZkh3Z2JtOURhR2xzWkhKbGJseHVJQ0FnSUhSb2FYTXVhMlY1SUQwZ2EyVjVJQ0U5SUc1MWJHd2dQeUJUZEhKcGJtY29hMlY1S1NBNklIVnVaR1ZtYVc1bFpGeHVJQ0FnSUhSb2FYTXVibUZ0WlhOd1lXTmxJRDBnS0hSNWNHVnZaaUJ1WVcxbGMzQmhZMlVnUFQwOUlGd2ljM1J5YVc1blhDSXBJRDhnYm1GdFpYTndZV05sSURvZ2JuVnNiRnh1WEc0Z0lDQWdkbUZ5SUdOdmRXNTBJRDBnS0dOb2FXeGtjbVZ1SUNZbUlHTm9hV3hrY21WdUxteGxibWQwYUNrZ2ZId2dNRnh1SUNBZ0lIWmhjaUJrWlhOalpXNWtZVzUwY3lBOUlEQmNiaUFnSUNCMllYSWdhR0Z6VjJsa1oyVjBjeUE5SUdaaGJITmxYRzRnSUNBZ2RtRnlJR2hoYzFSb2RXNXJjeUE5SUdaaGJITmxYRzRnSUNBZ2RtRnlJR1JsYzJObGJtUmhiblJJYjI5cmN5QTlJR1poYkhObFhHNGdJQ0FnZG1GeUlHaHZiMnR6WEc1Y2JpQWdJQ0JtYjNJZ0tIWmhjaUJ3Y205d1RtRnRaU0JwYmlCd2NtOXdaWEowYVdWektTQjdYRzRnSUNBZ0lDQWdJR2xtSUNod2NtOXdaWEowYVdWekxtaGhjMDkzYmxCeWIzQmxjblI1S0hCeWIzQk9ZVzFsS1NrZ2UxeHVJQ0FnSUNBZ0lDQWdJQ0FnZG1GeUlIQnliM0JsY25SNUlEMGdjSEp2Y0dWeWRHbGxjMXR3Y205d1RtRnRaVjFjYmlBZ0lDQWdJQ0FnSUNBZ0lHbG1JQ2hwYzFaSWIyOXJLSEJ5YjNCbGNuUjVLU0FtSmlCd2NtOXdaWEowZVM1MWJtaHZiMnNwSUh0Y2JpQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNCcFppQW9JV2h2YjJ0ektTQjdYRzRnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUdodmIydHpJRDBnZTMxY2JpQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNCOVhHNWNiaUFnSUNBZ0lDQWdJQ0FnSUNBZ0lDQm9iMjlyYzF0d2NtOXdUbUZ0WlYwZ1BTQndjbTl3WlhKMGVWeHVJQ0FnSUNBZ0lDQWdJQ0FnZlZ4dUlDQWdJQ0FnSUNCOVhHNGdJQ0FnZlZ4dVhHNGdJQ0FnWm05eUlDaDJZWElnYVNBOUlEQTdJR2tnUENCamIzVnVkRHNnYVNzcktTQjdYRzRnSUNBZ0lDQWdJSFpoY2lCamFHbHNaQ0E5SUdOb2FXeGtjbVZ1VzJsZFhHNGdJQ0FnSUNBZ0lHbG1JQ2hwYzFaT2IyUmxLR05vYVd4a0tTa2dlMXh1SUNBZ0lDQWdJQ0FnSUNBZ1pHVnpZMlZ1WkdGdWRITWdLejBnWTJocGJHUXVZMjkxYm5RZ2ZId2dNRnh1WEc0Z0lDQWdJQ0FnSUNBZ0lDQnBaaUFvSVdoaGMxZHBaR2RsZEhNZ0ppWWdZMmhwYkdRdWFHRnpWMmxrWjJWMGN5a2dlMXh1SUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJR2hoYzFkcFpHZGxkSE1nUFNCMGNuVmxYRzRnSUNBZ0lDQWdJQ0FnSUNCOVhHNWNiaUFnSUNBZ0lDQWdJQ0FnSUdsbUlDZ2hhR0Z6VkdoMWJtdHpJQ1ltSUdOb2FXeGtMbWhoYzFSb2RXNXJjeWtnZTF4dUlDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUdoaGMxUm9kVzVyY3lBOUlIUnlkV1ZjYmlBZ0lDQWdJQ0FnSUNBZ0lIMWNibHh1SUNBZ0lDQWdJQ0FnSUNBZ2FXWWdLQ0ZrWlhOalpXNWtZVzUwU0c5dmEzTWdKaVlnS0dOb2FXeGtMbWh2YjJ0eklIeDhJR05vYVd4a0xtUmxjMk5sYm1SaGJuUkliMjlyY3lrcElIdGNiaUFnSUNBZ0lDQWdJQ0FnSUNBZ0lDQmtaWE5qWlc1a1lXNTBTRzl2YTNNZ1BTQjBjblZsWEc0Z0lDQWdJQ0FnSUNBZ0lDQjlYRzRnSUNBZ0lDQWdJSDBnWld4elpTQnBaaUFvSVdoaGMxZHBaR2RsZEhNZ0ppWWdhWE5YYVdSblpYUW9ZMmhwYkdRcEtTQjdYRzRnSUNBZ0lDQWdJQ0FnSUNCcFppQW9kSGx3Wlc5bUlHTm9hV3hrTG1SbGMzUnliM2tnUFQwOUlGd2lablZ1WTNScGIyNWNJaWtnZTF4dUlDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUdoaGMxZHBaR2RsZEhNZ1BTQjBjblZsWEc0Z0lDQWdJQ0FnSUNBZ0lDQjlYRzRnSUNBZ0lDQWdJSDBnWld4elpTQnBaaUFvSVdoaGMxUm9kVzVyY3lBbUppQnBjMVJvZFc1cktHTm9hV3hrS1NrZ2UxeHVJQ0FnSUNBZ0lDQWdJQ0FnYUdGelZHaDFibXR6SUQwZ2RISjFaVHRjYmlBZ0lDQWdJQ0FnZlZ4dUlDQWdJSDFjYmx4dUlDQWdJSFJvYVhNdVkyOTFiblFnUFNCamIzVnVkQ0FySUdSbGMyTmxibVJoYm5SelhHNGdJQ0FnZEdocGN5NW9ZWE5YYVdSblpYUnpJRDBnYUdGelYybGtaMlYwYzF4dUlDQWdJSFJvYVhNdWFHRnpWR2gxYm10eklEMGdhR0Z6VkdoMWJtdHpYRzRnSUNBZ2RHaHBjeTVvYjI5cmN5QTlJR2h2YjJ0elhHNGdJQ0FnZEdocGN5NWtaWE5qWlc1a1lXNTBTRzl2YTNNZ1BTQmtaWE5qWlc1a1lXNTBTRzl2YTNOY2JuMWNibHh1Vm1seWRIVmhiRTV2WkdVdWNISnZkRzkwZVhCbExuWmxjbk5wYjI0Z1BTQjJaWEp6YVc5dVhHNVdhWEowZFdGc1RtOWtaUzV3Y205MGIzUjVjR1V1ZEhsd1pTQTlJRndpVm1seWRIVmhiRTV2WkdWY0lseHVYRzU5TEh0Y0lpNHZhWE10ZEdoMWJtdGNJam95TlN4Y0lpNHZhWE10ZG1odmIydGNJam95Tml4Y0lpNHZhWE10ZG01dlpHVmNJam95Tnl4Y0lpNHZhWE10ZDJsa1oyVjBYQ0k2TWprc1hDSXVMM1psY25OcGIyNWNJam96TUgxZExETXlPbHRtZFc1amRHbHZiaWh5WlhGMWFYSmxMRzF2WkhWc1pTeGxlSEJ2Y25SektYdGNiblpoY2lCMlpYSnphVzl1SUQwZ2NtVnhkV2x5WlNoY0lpNHZkbVZ5YzJsdmJsd2lLVnh1WEc1V2FYSjBkV0ZzVUdGMFkyZ3VUazlPUlNBOUlEQmNibFpwY25SMVlXeFFZWFJqYUM1V1ZFVllWQ0E5SURGY2JsWnBjblIxWVd4UVlYUmphQzVXVGs5RVJTQTlJREpjYmxacGNuUjFZV3hRWVhSamFDNVhTVVJIUlZRZ1BTQXpYRzVXYVhKMGRXRnNVR0YwWTJndVVGSlBVRk1nUFNBMFhHNVdhWEowZFdGc1VHRjBZMmd1VDFKRVJWSWdQU0ExWEc1V2FYSjBkV0ZzVUdGMFkyZ3VTVTVUUlZKVUlEMGdObHh1Vm1seWRIVmhiRkJoZEdOb0xsSkZUVTlXUlNBOUlEZGNibFpwY25SMVlXeFFZWFJqYUM1VVNGVk9TeUE5SURoY2JseHViVzlrZFd4bExtVjRjRzl5ZEhNZ1BTQldhWEowZFdGc1VHRjBZMmhjYmx4dVpuVnVZM1JwYjI0Z1ZtbHlkSFZoYkZCaGRHTm9LSFI1Y0dVc0lIWk9iMlJsTENCd1lYUmphQ2tnZTF4dUlDQWdJSFJvYVhNdWRIbHdaU0E5SUU1MWJXSmxjaWgwZVhCbEtWeHVJQ0FnSUhSb2FYTXVkazV2WkdVZ1BTQjJUbTlrWlZ4dUlDQWdJSFJvYVhNdWNHRjBZMmdnUFNCd1lYUmphRnh1ZlZ4dVhHNVdhWEowZFdGc1VHRjBZMmd1Y0hKdmRHOTBlWEJsTG5abGNuTnBiMjRnUFNCMlpYSnphVzl1WEc1V2FYSjBkV0ZzVUdGMFkyZ3VjSEp2ZEc5MGVYQmxMblI1Y0dVZ1BTQmNJbFpwY25SMVlXeFFZWFJqYUZ3aVhHNWNibjBzZTF3aUxpOTJaWEp6YVc5dVhDSTZNekI5WFN3ek16cGJablZ1WTNScGIyNG9jbVZ4ZFdseVpTeHRiMlIxYkdVc1pYaHdiM0owY3lsN1hHNTJZWElnZG1WeWMybHZiaUE5SUhKbGNYVnBjbVVvWENJdUwzWmxjbk5wYjI1Y0lpbGNibHh1Ylc5a2RXeGxMbVY0Y0c5eWRITWdQU0JXYVhKMGRXRnNWR1Y0ZEZ4dVhHNW1kVzVqZEdsdmJpQldhWEowZFdGc1ZHVjRkQ2gwWlhoMEtTQjdYRzRnSUNBZ2RHaHBjeTUwWlhoMElEMGdVM1J5YVc1bktIUmxlSFFwWEc1OVhHNWNibFpwY25SMVlXeFVaWGgwTG5CeWIzUnZkSGx3WlM1MlpYSnphVzl1SUQwZ2RtVnljMmx2Ymx4dVZtbHlkSFZoYkZSbGVIUXVjSEp2ZEc5MGVYQmxMblI1Y0dVZ1BTQmNJbFpwY25SMVlXeFVaWGgwWENKY2JseHVmU3g3WENJdUwzWmxjbk5wYjI1Y0lqb3pNSDFkTERNME9sdG1kVzVqZEdsdmJpaHlaWEYxYVhKbExHMXZaSFZzWlN4bGVIQnZjblJ6S1h0Y2JuWmhjaUJwYzA5aWFtVmpkQ0E5SUhKbGNYVnBjbVVvWENKcGN5MXZZbXBsWTNSY0lpbGNiblpoY2lCcGMwaHZiMnNnUFNCeVpYRjFhWEpsS0Z3aUxpNHZkbTV2WkdVdmFYTXRkbWh2YjJ0Y0lpbGNibHh1Ylc5a2RXeGxMbVY0Y0c5eWRITWdQU0JrYVdabVVISnZjSE5jYmx4dVpuVnVZM1JwYjI0Z1pHbG1abEJ5YjNCektHRXNJR0lwSUh0Y2JpQWdJQ0IyWVhJZ1pHbG1abHh1WEc0Z0lDQWdabTl5SUNoMllYSWdZVXRsZVNCcGJpQmhLU0I3WEc0Z0lDQWdJQ0FnSUdsbUlDZ2hLR0ZMWlhrZ2FXNGdZaWtwSUh0Y2JpQWdJQ0FnSUNBZ0lDQWdJR1JwWm1ZZ1BTQmthV1ptSUh4OElIdDlYRzRnSUNBZ0lDQWdJQ0FnSUNCa2FXWm1XMkZMWlhsZElEMGdkVzVrWldacGJtVmtYRzRnSUNBZ0lDQWdJSDFjYmx4dUlDQWdJQ0FnSUNCMllYSWdZVlpoYkhWbElEMGdZVnRoUzJWNVhWeHVJQ0FnSUNBZ0lDQjJZWElnWWxaaGJIVmxJRDBnWWx0aFMyVjVYVnh1WEc0Z0lDQWdJQ0FnSUdsbUlDaGhWbUZzZFdVZ1BUMDlJR0pXWVd4MVpTa2dlMXh1SUNBZ0lDQWdJQ0FnSUNBZ1kyOXVkR2x1ZFdWY2JpQWdJQ0FnSUNBZ2ZTQmxiSE5sSUdsbUlDaHBjMDlpYW1WamRDaGhWbUZzZFdVcElDWW1JR2x6VDJKcVpXTjBLR0pXWVd4MVpTa3BJSHRjYmlBZ0lDQWdJQ0FnSUNBZ0lHbG1JQ2huWlhSUWNtOTBiM1I1Y0dVb1lsWmhiSFZsS1NBaFBUMGdaMlYwVUhKdmRHOTBlWEJsS0dGV1lXeDFaU2twSUh0Y2JpQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNCa2FXWm1JRDBnWkdsbVppQjhmQ0I3ZlZ4dUlDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUdScFptWmJZVXRsZVYwZ1BTQmlWbUZzZFdWY2JpQWdJQ0FnSUNBZ0lDQWdJSDBnWld4elpTQnBaaUFvYVhOSWIyOXJLR0pXWVd4MVpTa3BJSHRjYmlBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnWkdsbVppQTlJR1JwWm1ZZ2ZId2dlMzFjYmlBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnWkdsbVpsdGhTMlY1WFNBOUlHSldZV3gxWlZ4dUlDQWdJQ0FnSUNBZ0lDQWdmU0JsYkhObElIdGNiaUFnSUNBZ0lDQWdJQ0FnSUNBZ0lDQjJZWElnYjJKcVpXTjBSR2xtWmlBOUlHUnBabVpRY205d2N5aGhWbUZzZFdVc0lHSldZV3gxWlNsY2JpQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNCcFppQW9iMkpxWldOMFJHbG1aaWtnZTF4dUlDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQmthV1ptSUQwZ1pHbG1aaUI4ZkNCN2ZWeHVJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0JrYVdabVcyRkxaWGxkSUQwZ2IySnFaV04wUkdsbVpseHVJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lIMWNiaUFnSUNBZ0lDQWdJQ0FnSUgxY2JpQWdJQ0FnSUNBZ2ZTQmxiSE5sSUh0Y2JpQWdJQ0FnSUNBZ0lDQWdJR1JwWm1ZZ1BTQmthV1ptSUh4OElIdDlYRzRnSUNBZ0lDQWdJQ0FnSUNCa2FXWm1XMkZMWlhsZElEMGdZbFpoYkhWbFhHNGdJQ0FnSUNBZ0lIMWNiaUFnSUNCOVhHNWNiaUFnSUNCbWIzSWdLSFpoY2lCaVMyVjVJR2x1SUdJcElIdGNiaUFnSUNBZ0lDQWdhV1lnS0NFb1lrdGxlU0JwYmlCaEtTa2dlMXh1SUNBZ0lDQWdJQ0FnSUNBZ1pHbG1aaUE5SUdScFptWWdmSHdnZTMxY2JpQWdJQ0FnSUNBZ0lDQWdJR1JwWm1aYllrdGxlVjBnUFNCaVcySkxaWGxkWEc0Z0lDQWdJQ0FnSUgxY2JpQWdJQ0I5WEc1Y2JpQWdJQ0J5WlhSMWNtNGdaR2xtWmx4dWZWeHVYRzVtZFc1amRHbHZiaUJuWlhSUWNtOTBiM1I1Y0dVb2RtRnNkV1VwSUh0Y2JpQWdhV1lnS0U5aWFtVmpkQzVuWlhSUWNtOTBiM1I1Y0dWUFppa2dlMXh1SUNBZ0lISmxkSFZ5YmlCUFltcGxZM1F1WjJWMFVISnZkRzkwZVhCbFQyWW9kbUZzZFdVcFhHNGdJSDBnWld4elpTQnBaaUFvZG1Gc2RXVXVYMTl3Y205MGIxOWZLU0I3WEc0Z0lDQWdjbVYwZFhKdUlIWmhiSFZsTGw5ZmNISnZkRzlmWDF4dUlDQjlJR1ZzYzJVZ2FXWWdLSFpoYkhWbExtTnZibk4wY25WamRHOXlLU0I3WEc0Z0lDQWdjbVYwZFhKdUlIWmhiSFZsTG1OdmJuTjBjblZqZEc5eUxuQnliM1J2ZEhsd1pWeHVJQ0I5WEc1OVhHNWNibjBzZTF3aUxpNHZkbTV2WkdVdmFYTXRkbWh2YjJ0Y0lqb3lOaXhjSW1sekxXOWlhbVZqZEZ3aU9qRXhmVjBzTXpVNlcyWjFibU4wYVc5dUtISmxjWFZwY21Vc2JXOWtkV3hsTEdWNGNHOXlkSE1wZTF4dWRtRnlJR2x6UVhKeVlYa2dQU0J5WlhGMWFYSmxLRndpZUMxcGN5MWhjbkpoZVZ3aUtWeHVYRzUyWVhJZ1ZsQmhkR05vSUQwZ2NtVnhkV2x5WlNoY0lpNHVMM1p1YjJSbEwzWndZWFJqYUZ3aUtWeHVkbUZ5SUdselZrNXZaR1VnUFNCeVpYRjFhWEpsS0Z3aUxpNHZkbTV2WkdVdmFYTXRkbTV2WkdWY0lpbGNiblpoY2lCcGMxWlVaWGgwSUQwZ2NtVnhkV2x5WlNoY0lpNHVMM1p1YjJSbEwybHpMWFowWlhoMFhDSXBYRzUyWVhJZ2FYTlhhV1JuWlhRZ1BTQnlaWEYxYVhKbEtGd2lMaTR2ZG01dlpHVXZhWE10ZDJsa1oyVjBYQ0lwWEc1MllYSWdhWE5VYUhWdWF5QTlJSEpsY1hWcGNtVW9YQ0l1TGk5MmJtOWtaUzlwY3kxMGFIVnVhMXdpS1Z4dWRtRnlJR2hoYm1Sc1pWUm9kVzVySUQwZ2NtVnhkV2x5WlNoY0lpNHVMM1p1YjJSbEwyaGhibVJzWlMxMGFIVnVhMXdpS1Z4dVhHNTJZWElnWkdsbVpsQnliM0J6SUQwZ2NtVnhkV2x5WlNoY0lpNHZaR2xtWmkxd2NtOXdjMXdpS1Z4dVhHNXRiMlIxYkdVdVpYaHdiM0owY3lBOUlHUnBabVpjYmx4dVpuVnVZM1JwYjI0Z1pHbG1aaWhoTENCaUtTQjdYRzRnSUNBZ2RtRnlJSEJoZEdOb0lEMGdleUJoT2lCaElIMWNiaUFnSUNCM1lXeHJLR0VzSUdJc0lIQmhkR05vTENBd0tWeHVJQ0FnSUhKbGRIVnliaUJ3WVhSamFGeHVmVnh1WEc1bWRXNWpkR2x2YmlCM1lXeHJLR0VzSUdJc0lIQmhkR05vTENCcGJtUmxlQ2tnZTF4dUlDQWdJR2xtSUNoaElEMDlQU0JpS1NCN1hHNGdJQ0FnSUNBZ0lISmxkSFZ5Ymx4dUlDQWdJSDFjYmx4dUlDQWdJSFpoY2lCaGNIQnNlU0E5SUhCaGRHTm9XMmx1WkdWNFhWeHVJQ0FnSUhaaGNpQmhjSEJzZVVOc1pXRnlJRDBnWm1Gc2MyVmNibHh1SUNBZ0lHbG1JQ2hwYzFSb2RXNXJLR0VwSUh4OElHbHpWR2gxYm1zb1lpa3BJSHRjYmlBZ0lDQWdJQ0FnZEdoMWJtdHpLR0VzSUdJc0lIQmhkR05vTENCcGJtUmxlQ2xjYmlBZ0lDQjlJR1ZzYzJVZ2FXWWdLR0lnUFQwZ2JuVnNiQ2tnZTF4dVhHNGdJQ0FnSUNBZ0lDOHZJRWxtSUdFZ2FYTWdZU0IzYVdSblpYUWdkMlVnZDJsc2JDQmhaR1FnWVNCeVpXMXZkbVVnY0dGMFkyZ2dabTl5SUdsMFhHNGdJQ0FnSUNBZ0lDOHZJRTkwYUdWeWQybHpaU0JoYm5rZ1kyaHBiR1FnZDJsa1oyVjBjeTlvYjI5cmN5QnRkWE4wSUdKbElHUmxjM1J5YjNsbFpDNWNiaUFnSUNBZ0lDQWdMeThnVkdocGN5QndjbVYyWlc1MGN5QmhaR1JwYm1jZ2RIZHZJSEpsYlc5MlpTQndZWFJqYUdWeklHWnZjaUJoSUhkcFpHZGxkQzVjYmlBZ0lDQWdJQ0FnYVdZZ0tDRnBjMWRwWkdkbGRDaGhLU2tnZTF4dUlDQWdJQ0FnSUNBZ0lDQWdZMnhsWVhKVGRHRjBaU2hoTENCd1lYUmphQ3dnYVc1a1pYZ3BYRzRnSUNBZ0lDQWdJQ0FnSUNCaGNIQnNlU0E5SUhCaGRHTm9XMmx1WkdWNFhWeHVJQ0FnSUNBZ0lDQjlYRzVjYmlBZ0lDQWdJQ0FnWVhCd2JIa2dQU0JoY0hCbGJtUlFZWFJqYUNoaGNIQnNlU3dnYm1WM0lGWlFZWFJqYUNoV1VHRjBZMmd1VWtWTlQxWkZMQ0JoTENCaUtTbGNiaUFnSUNCOUlHVnNjMlVnYVdZZ0tHbHpWazV2WkdVb1lpa3BJSHRjYmlBZ0lDQWdJQ0FnYVdZZ0tHbHpWazV2WkdVb1lTa3BJSHRjYmlBZ0lDQWdJQ0FnSUNBZ0lHbG1JQ2hoTG5SaFowNWhiV1VnUFQwOUlHSXVkR0ZuVG1GdFpTQW1KbHh1SUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJR0V1Ym1GdFpYTndZV05sSUQwOVBTQmlMbTVoYldWemNHRmpaU0FtSmx4dUlDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUdFdWEyVjVJRDA5UFNCaUxtdGxlU2tnZTF4dUlDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUhaaGNpQndjbTl3YzFCaGRHTm9JRDBnWkdsbVpsQnliM0J6S0dFdWNISnZjR1Z5ZEdsbGN5d2dZaTV3Y205d1pYSjBhV1Z6S1Z4dUlDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUdsbUlDaHdjbTl3YzFCaGRHTm9LU0I3WEc0Z0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lHRndjR3g1SUQwZ1lYQndaVzVrVUdGMFkyZ29ZWEJ3Ykhrc1hHNGdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNCdVpYY2dWbEJoZEdOb0tGWlFZWFJqYUM1UVVrOVFVeXdnWVN3Z2NISnZjSE5RWVhSamFDa3BYRzRnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdmVnh1SUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJR0Z3Y0d4NUlEMGdaR2xtWmtOb2FXeGtjbVZ1S0dFc0lHSXNJSEJoZEdOb0xDQmhjSEJzZVN3Z2FXNWtaWGdwWEc0Z0lDQWdJQ0FnSUNBZ0lDQjlJR1ZzYzJVZ2UxeHVJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lHRndjR3g1SUQwZ1lYQndaVzVrVUdGMFkyZ29ZWEJ3Ykhrc0lHNWxkeUJXVUdGMFkyZ29WbEJoZEdOb0xsWk9UMFJGTENCaExDQmlLU2xjYmlBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0JoY0hCc2VVTnNaV0Z5SUQwZ2RISjFaVnh1SUNBZ0lDQWdJQ0FnSUNBZ2ZWeHVJQ0FnSUNBZ0lDQjlJR1ZzYzJVZ2UxeHVJQ0FnSUNBZ0lDQWdJQ0FnWVhCd2JIa2dQU0JoY0hCbGJtUlFZWFJqYUNoaGNIQnNlU3dnYm1WM0lGWlFZWFJqYUNoV1VHRjBZMmd1Vms1UFJFVXNJR0VzSUdJcEtWeHVJQ0FnSUNBZ0lDQWdJQ0FnWVhCd2JIbERiR1ZoY2lBOUlIUnlkV1ZjYmlBZ0lDQWdJQ0FnZlZ4dUlDQWdJSDBnWld4elpTQnBaaUFvYVhOV1ZHVjRkQ2hpS1NrZ2UxeHVJQ0FnSUNBZ0lDQnBaaUFvSVdselZsUmxlSFFvWVNrcElIdGNiaUFnSUNBZ0lDQWdJQ0FnSUdGd2NHeDVJRDBnWVhCd1pXNWtVR0YwWTJnb1lYQndiSGtzSUc1bGR5QldVR0YwWTJnb1ZsQmhkR05vTGxaVVJWaFVMQ0JoTENCaUtTbGNiaUFnSUNBZ0lDQWdJQ0FnSUdGd2NHeDVRMnhsWVhJZ1BTQjBjblZsWEc0Z0lDQWdJQ0FnSUgwZ1pXeHpaU0JwWmlBb1lTNTBaWGgwSUNFOVBTQmlMblJsZUhRcElIdGNiaUFnSUNBZ0lDQWdJQ0FnSUdGd2NHeDVJRDBnWVhCd1pXNWtVR0YwWTJnb1lYQndiSGtzSUc1bGR5QldVR0YwWTJnb1ZsQmhkR05vTGxaVVJWaFVMQ0JoTENCaUtTbGNiaUFnSUNBZ0lDQWdmVnh1SUNBZ0lIMGdaV3h6WlNCcFppQW9hWE5YYVdSblpYUW9ZaWtwSUh0Y2JpQWdJQ0FnSUNBZ2FXWWdLQ0ZwYzFkcFpHZGxkQ2hoS1NrZ2UxeHVJQ0FnSUNBZ0lDQWdJQ0FnWVhCd2JIbERiR1ZoY2lBOUlIUnlkV1ZjYmlBZ0lDQWdJQ0FnZlZ4dVhHNGdJQ0FnSUNBZ0lHRndjR3g1SUQwZ1lYQndaVzVrVUdGMFkyZ29ZWEJ3Ykhrc0lHNWxkeUJXVUdGMFkyZ29WbEJoZEdOb0xsZEpSRWRGVkN3Z1lTd2dZaWtwWEc0Z0lDQWdmVnh1WEc0Z0lDQWdhV1lnS0dGd2NHeDVLU0I3WEc0Z0lDQWdJQ0FnSUhCaGRHTm9XMmx1WkdWNFhTQTlJR0Z3Y0d4NVhHNGdJQ0FnZlZ4dVhHNGdJQ0FnYVdZZ0tHRndjR3g1UTJ4bFlYSXBJSHRjYmlBZ0lDQWdJQ0FnWTJ4bFlYSlRkR0YwWlNoaExDQndZWFJqYUN3Z2FXNWtaWGdwWEc0Z0lDQWdmVnh1ZlZ4dVhHNW1kVzVqZEdsdmJpQmthV1ptUTJocGJHUnlaVzRvWVN3Z1lpd2djR0YwWTJnc0lHRndjR3g1TENCcGJtUmxlQ2tnZTF4dUlDQWdJSFpoY2lCaFEyaHBiR1J5Wlc0Z1BTQmhMbU5vYVd4a2NtVnVYRzRnSUNBZ2RtRnlJRzl5WkdWeVpXUlRaWFFnUFNCeVpXOXlaR1Z5S0dGRGFHbHNaSEpsYml3Z1lpNWphR2xzWkhKbGJpbGNiaUFnSUNCMllYSWdZa05vYVd4a2NtVnVJRDBnYjNKa1pYSmxaRk5sZEM1amFHbHNaSEpsYmx4dVhHNGdJQ0FnZG1GeUlHRk1aVzRnUFNCaFEyaHBiR1J5Wlc0dWJHVnVaM1JvWEc0Z0lDQWdkbUZ5SUdKTVpXNGdQU0JpUTJocGJHUnlaVzR1YkdWdVozUm9YRzRnSUNBZ2RtRnlJR3hsYmlBOUlHRk1aVzRnUGlCaVRHVnVJRDhnWVV4bGJpQTZJR0pNWlc1Y2JseHVJQ0FnSUdadmNpQW9kbUZ5SUdrZ1BTQXdPeUJwSUR3Z2JHVnVPeUJwS3lzcElIdGNiaUFnSUNBZ0lDQWdkbUZ5SUd4bFpuUk9iMlJsSUQwZ1lVTm9hV3hrY21WdVcybGRYRzRnSUNBZ0lDQWdJSFpoY2lCeWFXZG9kRTV2WkdVZ1BTQmlRMmhwYkdSeVpXNWJhVjFjYmlBZ0lDQWdJQ0FnYVc1a1pYZ2dLejBnTVZ4dVhHNGdJQ0FnSUNBZ0lHbG1JQ2doYkdWbWRFNXZaR1VwSUh0Y2JpQWdJQ0FnSUNBZ0lDQWdJR2xtSUNoeWFXZG9kRTV2WkdVcElIdGNiaUFnSUNBZ0lDQWdJQ0FnSUNBZ0lDQXZMeUJGZUdObGMzTWdibTlrWlhNZ2FXNGdZaUJ1WldWa0lIUnZJR0psSUdGa1pHVmtYRzRnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdZWEJ3YkhrZ1BTQmhjSEJsYm1SUVlYUmphQ2hoY0hCc2VTeGNiaUFnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnYm1WM0lGWlFZWFJqYUNoV1VHRjBZMmd1U1U1VFJWSlVMQ0J1ZFd4c0xDQnlhV2RvZEU1dlpHVXBLVnh1SUNBZ0lDQWdJQ0FnSUNBZ2ZWeHVJQ0FnSUNBZ0lDQjlJR1ZzYzJVZ2UxeHVJQ0FnSUNBZ0lDQWdJQ0FnZDJGc2F5aHNaV1owVG05a1pTd2djbWxuYUhST2IyUmxMQ0J3WVhSamFDd2dhVzVrWlhncFhHNGdJQ0FnSUNBZ0lIMWNibHh1SUNBZ0lDQWdJQ0JwWmlBb2FYTldUbTlrWlNoc1pXWjBUbTlrWlNrZ0ppWWdiR1ZtZEU1dlpHVXVZMjkxYm5RcElIdGNiaUFnSUNBZ0lDQWdJQ0FnSUdsdVpHVjRJQ3M5SUd4bFpuUk9iMlJsTG1OdmRXNTBYRzRnSUNBZ0lDQWdJSDFjYmlBZ0lDQjlYRzVjYmlBZ0lDQnBaaUFvYjNKa1pYSmxaRk5sZEM1dGIzWmxjeWtnZTF4dUlDQWdJQ0FnSUNBdkx5QlNaVzl5WkdWeUlHNXZaR1Z6SUd4aGMzUmNiaUFnSUNBZ0lDQWdZWEJ3YkhrZ1BTQmhjSEJsYm1SUVlYUmphQ2hoY0hCc2VTd2dibVYzSUZaUVlYUmphQ2hjYmlBZ0lDQWdJQ0FnSUNBZ0lGWlFZWFJqYUM1UFVrUkZVaXhjYmlBZ0lDQWdJQ0FnSUNBZ0lHRXNYRzRnSUNBZ0lDQWdJQ0FnSUNCdmNtUmxjbVZrVTJWMExtMXZkbVZ6WEc0Z0lDQWdJQ0FnSUNrcFhHNGdJQ0FnZlZ4dVhHNGdJQ0FnY21WMGRYSnVJR0Z3Y0d4NVhHNTlYRzVjYm1aMWJtTjBhVzl1SUdOc1pXRnlVM1JoZEdVb2RrNXZaR1VzSUhCaGRHTm9MQ0JwYm1SbGVDa2dlMXh1SUNBZ0lDOHZJRlJQUkU4NklFMWhhMlVnZEdocGN5QmhJSE5wYm1kc1pTQjNZV3hyTENCdWIzUWdkSGR2WEc0Z0lDQWdkVzVvYjI5cktIWk9iMlJsTENCd1lYUmphQ3dnYVc1a1pYZ3BYRzRnSUNBZ1pHVnpkSEp2ZVZkcFpHZGxkSE1vZGs1dlpHVXNJSEJoZEdOb0xDQnBibVJsZUNsY2JuMWNibHh1THk4Z1VHRjBZMmdnY21WamIzSmtjeUJtYjNJZ1lXeHNJR1JsYzNSeWIzbGxaQ0IzYVdSblpYUnpJRzExYzNRZ1ltVWdZV1JrWldRZ1ltVmpZWFZ6WlNCM1pTQnVaV1ZrWEc0dkx5QmhJRVJQVFNCdWIyUmxJSEpsWm1WeVpXNWpaU0JtYjNJZ2RHaGxJR1JsYzNSeWIza2dablZ1WTNScGIyNWNibVoxYm1OMGFXOXVJR1JsYzNSeWIzbFhhV1JuWlhSektIWk9iMlJsTENCd1lYUmphQ3dnYVc1a1pYZ3BJSHRjYmlBZ0lDQnBaaUFvYVhOWGFXUm5aWFFvZGs1dlpHVXBLU0I3WEc0Z0lDQWdJQ0FnSUdsbUlDaDBlWEJsYjJZZ2RrNXZaR1V1WkdWemRISnZlU0E5UFQwZ1hDSm1kVzVqZEdsdmJsd2lLU0I3WEc0Z0lDQWdJQ0FnSUNBZ0lDQndZWFJqYUZ0cGJtUmxlRjBnUFNCaGNIQmxibVJRWVhSamFDaGNiaUFnSUNBZ0lDQWdJQ0FnSUNBZ0lDQndZWFJqYUZ0cGJtUmxlRjBzWEc0Z0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnYm1WM0lGWlFZWFJqYUNoV1VHRjBZMmd1VWtWTlQxWkZMQ0IyVG05a1pTd2diblZzYkNsY2JpQWdJQ0FnSUNBZ0lDQWdJQ2xjYmlBZ0lDQWdJQ0FnZlZ4dUlDQWdJSDBnWld4elpTQnBaaUFvYVhOV1RtOWtaU2gyVG05a1pTa2dKaVlnS0haT2IyUmxMbWhoYzFkcFpHZGxkSE1nZkh3Z2RrNXZaR1V1YUdGelZHaDFibXR6S1NrZ2UxeHVJQ0FnSUNBZ0lDQjJZWElnWTJocGJHUnlaVzRnUFNCMlRtOWtaUzVqYUdsc1pISmxibHh1SUNBZ0lDQWdJQ0IyWVhJZ2JHVnVJRDBnWTJocGJHUnlaVzR1YkdWdVozUm9YRzRnSUNBZ0lDQWdJR1p2Y2lBb2RtRnlJR2tnUFNBd095QnBJRHdnYkdWdU95QnBLeXNwSUh0Y2JpQWdJQ0FnSUNBZ0lDQWdJSFpoY2lCamFHbHNaQ0E5SUdOb2FXeGtjbVZ1VzJsZFhHNGdJQ0FnSUNBZ0lDQWdJQ0JwYm1SbGVDQXJQU0F4WEc1Y2JpQWdJQ0FnSUNBZ0lDQWdJR1JsYzNSeWIzbFhhV1JuWlhSektHTm9hV3hrTENCd1lYUmphQ3dnYVc1a1pYZ3BYRzVjYmlBZ0lDQWdJQ0FnSUNBZ0lHbG1JQ2hwYzFaT2IyUmxLR05vYVd4a0tTQW1KaUJqYUdsc1pDNWpiM1Z1ZENrZ2UxeHVJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lHbHVaR1Y0SUNzOUlHTm9hV3hrTG1OdmRXNTBYRzRnSUNBZ0lDQWdJQ0FnSUNCOVhHNGdJQ0FnSUNBZ0lIMWNiaUFnSUNCOUlHVnNjMlVnYVdZZ0tHbHpWR2gxYm1zb2RrNXZaR1VwS1NCN1hHNGdJQ0FnSUNBZ0lIUm9kVzVyY3loMlRtOWtaU3dnYm5Wc2JDd2djR0YwWTJnc0lHbHVaR1Y0S1Z4dUlDQWdJSDFjYm4xY2JseHVMeThnUTNKbFlYUmxJR0VnYzNWaUxYQmhkR05vSUdadmNpQjBhSFZ1YTNOY2JtWjFibU4wYVc5dUlIUm9kVzVyY3loaExDQmlMQ0J3WVhSamFDd2dhVzVrWlhncElIdGNiaUFnSUNCMllYSWdibTlrWlhNZ1BTQm9ZVzVrYkdWVWFIVnVheWhoTENCaUtWeHVJQ0FnSUhaaGNpQjBhSFZ1YTFCaGRHTm9JRDBnWkdsbVppaHViMlJsY3k1aExDQnViMlJsY3k1aUtWeHVJQ0FnSUdsbUlDaG9ZWE5RWVhSamFHVnpLSFJvZFc1clVHRjBZMmdwS1NCN1hHNGdJQ0FnSUNBZ0lIQmhkR05vVzJsdVpHVjRYU0E5SUc1bGR5QldVR0YwWTJnb1ZsQmhkR05vTGxSSVZVNUxMQ0J1ZFd4c0xDQjBhSFZ1YTFCaGRHTm9LVnh1SUNBZ0lIMWNibjFjYmx4dVpuVnVZM1JwYjI0Z2FHRnpVR0YwWTJobGN5aHdZWFJqYUNrZ2UxeHVJQ0FnSUdadmNpQW9kbUZ5SUdsdVpHVjRJR2x1SUhCaGRHTm9LU0I3WEc0Z0lDQWdJQ0FnSUdsbUlDaHBibVJsZUNBaFBUMGdYQ0poWENJcElIdGNiaUFnSUNBZ0lDQWdJQ0FnSUhKbGRIVnliaUIwY25WbFhHNGdJQ0FnSUNBZ0lIMWNiaUFnSUNCOVhHNWNiaUFnSUNCeVpYUjFjbTRnWm1Gc2MyVmNibjFjYmx4dUx5OGdSWGhsWTNWMFpTQm9iMjlyY3lCM2FHVnVJSFIzYnlCdWIyUmxjeUJoY21VZ2FXUmxiblJwWTJGc1hHNW1kVzVqZEdsdmJpQjFibWh2YjJzb2RrNXZaR1VzSUhCaGRHTm9MQ0JwYm1SbGVDa2dlMXh1SUNBZ0lHbG1JQ2hwYzFaT2IyUmxLSFpPYjJSbEtTa2dlMXh1SUNBZ0lDQWdJQ0JwWmlBb2RrNXZaR1V1YUc5dmEzTXBJSHRjYmlBZ0lDQWdJQ0FnSUNBZ0lIQmhkR05vVzJsdVpHVjRYU0E5SUdGd2NHVnVaRkJoZEdOb0tGeHVJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lIQmhkR05vVzJsdVpHVjRYU3hjYmlBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0J1WlhjZ1ZsQmhkR05vS0Z4dUlDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQldVR0YwWTJndVVGSlBVRk1zWEc0Z0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lIWk9iMlJsTEZ4dUlDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQjFibVJsWm1sdVpXUkxaWGx6S0haT2IyUmxMbWh2YjJ0ektWeHVJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDbGNiaUFnSUNBZ0lDQWdJQ0FnSUNsY2JpQWdJQ0FnSUNBZ2ZWeHVYRzRnSUNBZ0lDQWdJR2xtSUNoMlRtOWtaUzVrWlhOalpXNWtZVzUwU0c5dmEzTWdmSHdnZGs1dlpHVXVhR0Z6VkdoMWJtdHpLU0I3WEc0Z0lDQWdJQ0FnSUNBZ0lDQjJZWElnWTJocGJHUnlaVzRnUFNCMlRtOWtaUzVqYUdsc1pISmxibHh1SUNBZ0lDQWdJQ0FnSUNBZ2RtRnlJR3hsYmlBOUlHTm9hV3hrY21WdUxteGxibWQwYUZ4dUlDQWdJQ0FnSUNBZ0lDQWdabTl5SUNoMllYSWdhU0E5SURBN0lHa2dQQ0JzWlc0N0lHa3JLeWtnZTF4dUlDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUhaaGNpQmphR2xzWkNBOUlHTm9hV3hrY21WdVcybGRYRzRnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdhVzVrWlhnZ0t6MGdNVnh1WEc0Z0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnZFc1b2IyOXJLR05vYVd4a0xDQndZWFJqYUN3Z2FXNWtaWGdwWEc1Y2JpQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNCcFppQW9hWE5XVG05a1pTaGphR2xzWkNrZ0ppWWdZMmhwYkdRdVkyOTFiblFwSUh0Y2JpQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdhVzVrWlhnZ0t6MGdZMmhwYkdRdVkyOTFiblJjYmlBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0I5WEc0Z0lDQWdJQ0FnSUNBZ0lDQjlYRzRnSUNBZ0lDQWdJSDFjYmlBZ0lDQjlJR1ZzYzJVZ2FXWWdLR2x6VkdoMWJtc29kazV2WkdVcEtTQjdYRzRnSUNBZ0lDQWdJSFJvZFc1cmN5aDJUbTlrWlN3Z2JuVnNiQ3dnY0dGMFkyZ3NJR2x1WkdWNEtWeHVJQ0FnSUgxY2JuMWNibHh1Wm5WdVkzUnBiMjRnZFc1a1pXWnBibVZrUzJWNWN5aHZZbW9wSUh0Y2JpQWdJQ0IyWVhJZ2NtVnpkV3gwSUQwZ2UzMWNibHh1SUNBZ0lHWnZjaUFvZG1GeUlHdGxlU0JwYmlCdlltb3BJSHRjYmlBZ0lDQWdJQ0FnY21WemRXeDBXMnRsZVYwZ1BTQjFibVJsWm1sdVpXUmNiaUFnSUNCOVhHNWNiaUFnSUNCeVpYUjFjbTRnY21WemRXeDBYRzU5WEc1Y2JpOHZJRXhwYzNRZ1pHbG1aaXdnYm1GcGRtVWdiR1ZtZENCMGJ5QnlhV2RvZENCeVpXOXlaR1Z5YVc1blhHNW1kVzVqZEdsdmJpQnlaVzl5WkdWeUtHRkRhR2xzWkhKbGJpd2dZa05vYVd4a2NtVnVLU0I3WEc0Z0lDQWdMeThnVHloTktTQjBhVzFsTENCUEtFMHBJRzFsYlc5eWVWeHVJQ0FnSUhaaGNpQmlRMmhwYkdSSmJtUmxlQ0E5SUd0bGVVbHVaR1Y0S0dKRGFHbHNaSEpsYmlsY2JpQWdJQ0IyWVhJZ1lrdGxlWE1nUFNCaVEyaHBiR1JKYm1SbGVDNXJaWGx6WEc0Z0lDQWdkbUZ5SUdKR2NtVmxJRDBnWWtOb2FXeGtTVzVrWlhndVpuSmxaVnh1WEc0Z0lDQWdhV1lnS0dKR2NtVmxMbXhsYm1kMGFDQTlQVDBnWWtOb2FXeGtjbVZ1TG14bGJtZDBhQ2tnZTF4dUlDQWdJQ0FnSUNCeVpYUjFjbTRnZTF4dUlDQWdJQ0FnSUNBZ0lDQWdZMmhwYkdSeVpXNDZJR0pEYUdsc1pISmxiaXhjYmlBZ0lDQWdJQ0FnSUNBZ0lHMXZkbVZ6T2lCdWRXeHNYRzRnSUNBZ0lDQWdJSDFjYmlBZ0lDQjlYRzVjYmlBZ0lDQXZMeUJQS0U0cElIUnBiV1VzSUU4b1Rpa2diV1Z0YjNKNVhHNGdJQ0FnZG1GeUlHRkRhR2xzWkVsdVpHVjRJRDBnYTJWNVNXNWtaWGdvWVVOb2FXeGtjbVZ1S1Z4dUlDQWdJSFpoY2lCaFMyVjVjeUE5SUdGRGFHbHNaRWx1WkdWNExtdGxlWE5jYmlBZ0lDQjJZWElnWVVaeVpXVWdQU0JoUTJocGJHUkpibVJsZUM1bWNtVmxYRzVjYmlBZ0lDQnBaaUFvWVVaeVpXVXViR1Z1WjNSb0lEMDlQU0JoUTJocGJHUnlaVzR1YkdWdVozUm9LU0I3WEc0Z0lDQWdJQ0FnSUhKbGRIVnliaUI3WEc0Z0lDQWdJQ0FnSUNBZ0lDQmphR2xzWkhKbGJqb2dZa05vYVd4a2NtVnVMRnh1SUNBZ0lDQWdJQ0FnSUNBZ2JXOTJaWE02SUc1MWJHeGNiaUFnSUNBZ0lDQWdmVnh1SUNBZ0lIMWNibHh1SUNBZ0lDOHZJRThvVFVGWUtFNHNJRTBwS1NCdFpXMXZjbmxjYmlBZ0lDQjJZWElnYm1WM1EyaHBiR1J5Wlc0Z1BTQmJYVnh1WEc0Z0lDQWdkbUZ5SUdaeVpXVkpibVJsZUNBOUlEQmNiaUFnSUNCMllYSWdabkpsWlVOdmRXNTBJRDBnWWtaeVpXVXViR1Z1WjNSb1hHNGdJQ0FnZG1GeUlHUmxiR1YwWldSSmRHVnRjeUE5SURCY2JseHVJQ0FnSUM4dklFbDBaWEpoZEdVZ2RHaHliM1ZuYUNCaElHRnVaQ0J0WVhSamFDQmhJRzV2WkdVZ2FXNGdZbHh1SUNBZ0lDOHZJRThvVGlrZ2RHbHRaU3hjYmlBZ0lDQm1iM0lnS0haaGNpQnBJRDBnTUNBN0lHa2dQQ0JoUTJocGJHUnlaVzR1YkdWdVozUm9PeUJwS3lzcElIdGNiaUFnSUNBZ0lDQWdkbUZ5SUdGSmRHVnRJRDBnWVVOb2FXeGtjbVZ1VzJsZFhHNGdJQ0FnSUNBZ0lIWmhjaUJwZEdWdFNXNWtaWGhjYmx4dUlDQWdJQ0FnSUNCcFppQW9ZVWwwWlcwdWEyVjVLU0I3WEc0Z0lDQWdJQ0FnSUNBZ0lDQnBaaUFvWWt0bGVYTXVhR0Z6VDNkdVVISnZjR1Z5ZEhrb1lVbDBaVzB1YTJWNUtTa2dlMXh1SUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQzh2SUUxaGRHTm9JSFZ3SUhSb1pTQnZiR1FnYTJWNWMxeHVJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lHbDBaVzFKYm1SbGVDQTlJR0pMWlhselcyRkpkR1Z0TG10bGVWMWNiaUFnSUNBZ0lDQWdJQ0FnSUNBZ0lDQnVaWGREYUdsc1pISmxiaTV3ZFhOb0tHSkRhR2xzWkhKbGJsdHBkR1Z0U1c1a1pYaGRLVnh1WEc0Z0lDQWdJQ0FnSUNBZ0lDQjlJR1ZzYzJVZ2UxeHVJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDOHZJRkpsYlc5MlpTQnZiR1FnYTJWNVpXUWdhWFJsYlhOY2JpQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNCcGRHVnRTVzVrWlhnZ1BTQnBJQzBnWkdWc1pYUmxaRWwwWlcxekt5dGNiaUFnSUNBZ0lDQWdJQ0FnSUNBZ0lDQnVaWGREYUdsc1pISmxiaTV3ZFhOb0tHNTFiR3dwWEc0Z0lDQWdJQ0FnSUNBZ0lDQjlYRzRnSUNBZ0lDQWdJSDBnWld4elpTQjdYRzRnSUNBZ0lDQWdJQ0FnSUNBdkx5Qk5ZWFJqYUNCMGFHVWdhWFJsYlNCcGJpQmhJSGRwZEdnZ2RHaGxJRzVsZUhRZ1puSmxaU0JwZEdWdElHbHVJR0pjYmlBZ0lDQWdJQ0FnSUNBZ0lHbG1JQ2htY21WbFNXNWtaWGdnUENCbWNtVmxRMjkxYm5RcElIdGNiaUFnSUNBZ0lDQWdJQ0FnSUNBZ0lDQnBkR1Z0U1c1a1pYZ2dQU0JpUm5KbFpWdG1jbVZsU1c1a1pYZ3JLMTFjYmlBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0J1WlhkRGFHbHNaSEpsYmk1d2RYTm9LR0pEYUdsc1pISmxibHRwZEdWdFNXNWtaWGhkS1Z4dUlDQWdJQ0FnSUNBZ0lDQWdmU0JsYkhObElIdGNiaUFnSUNBZ0lDQWdJQ0FnSUNBZ0lDQXZMeUJVYUdWeVpTQmhjbVVnYm04Z1puSmxaU0JwZEdWdGN5QnBiaUJpSUhSdklHMWhkR05vSUhkcGRHaGNiaUFnSUNBZ0lDQWdJQ0FnSUNBZ0lDQXZMeUIwYUdVZ1puSmxaU0JwZEdWdGN5QnBiaUJoTENCemJ5QjBhR1VnWlhoMGNtRWdabkpsWlNCdWIyUmxjMXh1SUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQzh2SUdGeVpTQmtaV3hsZEdWa0xseHVJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lHbDBaVzFKYm1SbGVDQTlJR2tnTFNCa1pXeGxkR1ZrU1hSbGJYTXJLMXh1SUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJRzVsZDBOb2FXeGtjbVZ1TG5CMWMyZ29iblZzYkNsY2JpQWdJQ0FnSUNBZ0lDQWdJSDFjYmlBZ0lDQWdJQ0FnZlZ4dUlDQWdJSDFjYmx4dUlDQWdJSFpoY2lCc1lYTjBSbkpsWlVsdVpHVjRJRDBnWm5KbFpVbHVaR1Y0SUQ0OUlHSkdjbVZsTG14bGJtZDBhQ0EvWEc0Z0lDQWdJQ0FnSUdKRGFHbHNaSEpsYmk1c1pXNW5kR2dnT2x4dUlDQWdJQ0FnSUNCaVJuSmxaVnRtY21WbFNXNWtaWGhkWEc1Y2JpQWdJQ0F2THlCSmRHVnlZWFJsSUhSb2NtOTFaMmdnWWlCaGJtUWdZWEJ3Wlc1a0lHRnVlU0J1WlhjZ2EyVjVjMXh1SUNBZ0lDOHZJRThvVFNrZ2RHbHRaVnh1SUNBZ0lHWnZjaUFvZG1GeUlHb2dQU0F3T3lCcUlEd2dZa05vYVd4a2NtVnVMbXhsYm1kMGFEc2dhaXNyS1NCN1hHNGdJQ0FnSUNBZ0lIWmhjaUJ1WlhkSmRHVnRJRDBnWWtOb2FXeGtjbVZ1VzJwZFhHNWNiaUFnSUNBZ0lDQWdhV1lnS0c1bGQwbDBaVzB1YTJWNUtTQjdYRzRnSUNBZ0lDQWdJQ0FnSUNCcFppQW9JV0ZMWlhsekxtaGhjMDkzYmxCeWIzQmxjblI1S0c1bGQwbDBaVzB1YTJWNUtTa2dlMXh1SUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQzh2SUVGa1pDQmhibmtnYm1WM0lHdGxlV1ZrSUdsMFpXMXpYRzRnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdMeThnVjJVZ1lYSmxJR0ZrWkdsdVp5QnVaWGNnYVhSbGJYTWdkRzhnZEdobElHVnVaQ0JoYm1RZ2RHaGxiaUJ6YjNKMGFXNW5JSFJvWlcxY2JpQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBdkx5QnBiaUJ3YkdGalpTNGdTVzRnWm5WMGRYSmxJSGRsSUhOb2IzVnNaQ0JwYm5ObGNuUWdibVYzSUdsMFpXMXpJR2x1SUhCc1lXTmxMbHh1SUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJRzVsZDBOb2FXeGtjbVZ1TG5CMWMyZ29ibVYzU1hSbGJTbGNiaUFnSUNBZ0lDQWdJQ0FnSUgxY2JpQWdJQ0FnSUNBZ2ZTQmxiSE5sSUdsbUlDaHFJRDQ5SUd4aGMzUkdjbVZsU1c1a1pYZ3BJSHRjYmlBZ0lDQWdJQ0FnSUNBZ0lDOHZJRUZrWkNCaGJua2diR1ZtZEc5MlpYSWdibTl1TFd0bGVXVmtJR2wwWlcxelhHNGdJQ0FnSUNBZ0lDQWdJQ0J1WlhkRGFHbHNaSEpsYmk1d2RYTm9LRzVsZDBsMFpXMHBYRzRnSUNBZ0lDQWdJSDFjYmlBZ0lDQjlYRzVjYmlBZ0lDQjJZWElnYzJsdGRXeGhkR1VnUFNCdVpYZERhR2xzWkhKbGJpNXpiR2xqWlNncFhHNGdJQ0FnZG1GeUlITnBiWFZzWVhSbFNXNWtaWGdnUFNBd1hHNGdJQ0FnZG1GeUlISmxiVzkyWlhNZ1BTQmJYVnh1SUNBZ0lIWmhjaUJwYm5ObGNuUnpJRDBnVzExY2JpQWdJQ0IyWVhJZ2MybHRkV3hoZEdWSmRHVnRYRzVjYmlBZ0lDQm1iM0lnS0haaGNpQnJJRDBnTURzZ2F5QThJR0pEYUdsc1pISmxiaTVzWlc1bmRHZzdLU0I3WEc0Z0lDQWdJQ0FnSUhaaGNpQjNZVzUwWldSSmRHVnRJRDBnWWtOb2FXeGtjbVZ1VzJ0ZFhHNGdJQ0FnSUNBZ0lITnBiWFZzWVhSbFNYUmxiU0E5SUhOcGJYVnNZWFJsVzNOcGJYVnNZWFJsU1c1a1pYaGRYRzVjYmlBZ0lDQWdJQ0FnTHk4Z2NtVnRiM1psSUdsMFpXMXpYRzRnSUNBZ0lDQWdJSGRvYVd4bElDaHphVzExYkdGMFpVbDBaVzBnUFQwOUlHNTFiR3dnSmlZZ2MybHRkV3hoZEdVdWJHVnVaM1JvS1NCN1hHNGdJQ0FnSUNBZ0lDQWdJQ0J5WlcxdmRtVnpMbkIxYzJnb2NtVnRiM1psS0hOcGJYVnNZWFJsTENCemFXMTFiR0YwWlVsdVpHVjRMQ0J1ZFd4c0tTbGNiaUFnSUNBZ0lDQWdJQ0FnSUhOcGJYVnNZWFJsU1hSbGJTQTlJSE5wYlhWc1lYUmxXM05wYlhWc1lYUmxTVzVrWlhoZFhHNGdJQ0FnSUNBZ0lIMWNibHh1SUNBZ0lDQWdJQ0JwWmlBb0lYTnBiWFZzWVhSbFNYUmxiU0I4ZkNCemFXMTFiR0YwWlVsMFpXMHVhMlY1SUNFOVBTQjNZVzUwWldSSmRHVnRMbXRsZVNrZ2UxeHVJQ0FnSUNBZ0lDQWdJQ0FnTHk4Z2FXWWdkMlVnYm1WbFpDQmhJR3RsZVNCcGJpQjBhR2x6SUhCdmMybDBhVzl1TGk0dVhHNGdJQ0FnSUNBZ0lDQWdJQ0JwWmlBb2QyRnVkR1ZrU1hSbGJTNXJaWGtwSUh0Y2JpQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNCcFppQW9jMmx0ZFd4aGRHVkpkR1Z0SUNZbUlITnBiWFZzWVhSbFNYUmxiUzVyWlhrcElIdGNiaUFnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnTHk4Z2FXWWdZVzRnYVc1elpYSjBJR1J2WlhOdUozUWdjSFYwSUhSb2FYTWdhMlY1SUdsdUlIQnNZV05sTENCcGRDQnVaV1ZrY3lCMGJ5QnRiM1psWEc0Z0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lHbG1JQ2hpUzJWNWMxdHphVzExYkdGMFpVbDBaVzB1YTJWNVhTQWhQVDBnYXlBcklERXBJSHRjYmlBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJSEpsYlc5MlpYTXVjSFZ6YUNoeVpXMXZkbVVvYzJsdGRXeGhkR1VzSUhOcGJYVnNZWFJsU1c1a1pYZ3NJSE5wYlhWc1lYUmxTWFJsYlM1clpYa3BLVnh1SUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdjMmx0ZFd4aGRHVkpkR1Z0SUQwZ2MybHRkV3hoZEdWYmMybHRkV3hoZEdWSmJtUmxlRjFjYmlBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQzh2SUdsbUlIUm9aU0J5WlcxdmRtVWdaR2xrYmlkMElIQjFkQ0IwYUdVZ2QyRnVkR1ZrSUdsMFpXMGdhVzRnY0d4aFkyVXNJSGRsSUc1bFpXUWdkRzhnYVc1elpYSjBJR2wwWEc0Z0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0JwWmlBb0lYTnBiWFZzWVhSbFNYUmxiU0I4ZkNCemFXMTFiR0YwWlVsMFpXMHVhMlY1SUNFOVBTQjNZVzUwWldSSmRHVnRMbXRsZVNrZ2UxeHVJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJR2x1YzJWeWRITXVjSFZ6YUNoN2EyVjVPaUIzWVc1MFpXUkpkR1Z0TG10bGVTd2dkRzg2SUd0OUtWeHVJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ2ZWeHVJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0x5OGdhWFJsYlhNZ1lYSmxJRzFoZEdOb2FXNW5MQ0J6YnlCemEybHdJR0ZvWldGa1hHNGdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNCbGJITmxJSHRjYmlBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNCemFXMTFiR0YwWlVsdVpHVjRLeXRjYmlBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJSDFjYmlBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ2ZWeHVJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0JsYkhObElIdGNiaUFnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lHbHVjMlZ5ZEhNdWNIVnphQ2g3YTJWNU9pQjNZVzUwWldSSmRHVnRMbXRsZVN3Z2RHODZJR3Q5S1Z4dUlDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQjlYRzRnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdmVnh1SUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJR1ZzYzJVZ2UxeHVJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0JwYm5ObGNuUnpMbkIxYzJnb2UydGxlVG9nZDJGdWRHVmtTWFJsYlM1clpYa3NJSFJ2T2lCcmZTbGNiaUFnSUNBZ0lDQWdJQ0FnSUNBZ0lDQjlYRzRnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdheXNyWEc0Z0lDQWdJQ0FnSUNBZ0lDQjlYRzRnSUNBZ0lDQWdJQ0FnSUNBdkx5QmhJR3RsZVNCcGJpQnphVzExYkdGMFpTQm9ZWE1nYm04Z2JXRjBZMmhwYm1jZ2QyRnVkR1ZrSUd0bGVTd2djbVZ0YjNabElHbDBYRzRnSUNBZ0lDQWdJQ0FnSUNCbGJITmxJR2xtSUNoemFXMTFiR0YwWlVsMFpXMGdKaVlnYzJsdGRXeGhkR1ZKZEdWdExtdGxlU2tnZTF4dUlDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUhKbGJXOTJaWE11Y0hWemFDaHlaVzF2ZG1Vb2MybHRkV3hoZEdVc0lITnBiWFZzWVhSbFNXNWtaWGdzSUhOcGJYVnNZWFJsU1hSbGJTNXJaWGtwS1Z4dUlDQWdJQ0FnSUNBZ0lDQWdmVnh1SUNBZ0lDQWdJQ0I5WEc0Z0lDQWdJQ0FnSUdWc2MyVWdlMXh1SUNBZ0lDQWdJQ0FnSUNBZ2MybHRkV3hoZEdWSmJtUmxlQ3NyWEc0Z0lDQWdJQ0FnSUNBZ0lDQnJLeXRjYmlBZ0lDQWdJQ0FnZlZ4dUlDQWdJSDFjYmx4dUlDQWdJQzh2SUhKbGJXOTJaU0JoYkd3Z2RHaGxJSEpsYldGcGJtbHVaeUJ1YjJSbGN5Qm1jbTl0SUhOcGJYVnNZWFJsWEc0Z0lDQWdkMmhwYkdVb2MybHRkV3hoZEdWSmJtUmxlQ0E4SUhOcGJYVnNZWFJsTG14bGJtZDBhQ2tnZTF4dUlDQWdJQ0FnSUNCemFXMTFiR0YwWlVsMFpXMGdQU0J6YVcxMWJHRjBaVnR6YVcxMWJHRjBaVWx1WkdWNFhWeHVJQ0FnSUNBZ0lDQnlaVzF2ZG1WekxuQjFjMmdvY21WdGIzWmxLSE5wYlhWc1lYUmxMQ0J6YVcxMWJHRjBaVWx1WkdWNExDQnphVzExYkdGMFpVbDBaVzBnSmlZZ2MybHRkV3hoZEdWSmRHVnRMbXRsZVNrcFhHNGdJQ0FnZlZ4dVhHNGdJQ0FnTHk4Z1NXWWdkR2hsSUc5dWJIa2diVzkyWlhNZ2QyVWdhR0YyWlNCaGNtVWdaR1ZzWlhSbGN5QjBhR1Z1SUhkbElHTmhiaUJxZFhOMFhHNGdJQ0FnTHk4Z2JHVjBJSFJvWlNCa1pXeGxkR1VnY0dGMFkyZ2djbVZ0YjNabElIUm9aWE5sSUdsMFpXMXpMbHh1SUNBZ0lHbG1JQ2h5WlcxdmRtVnpMbXhsYm1kMGFDQTlQVDBnWkdWc1pYUmxaRWwwWlcxeklDWW1JQ0ZwYm5ObGNuUnpMbXhsYm1kMGFDa2dlMXh1SUNBZ0lDQWdJQ0J5WlhSMWNtNGdlMXh1SUNBZ0lDQWdJQ0FnSUNBZ1kyaHBiR1J5Wlc0NklHNWxkME5vYVd4a2NtVnVMRnh1SUNBZ0lDQWdJQ0FnSUNBZ2JXOTJaWE02SUc1MWJHeGNiaUFnSUNBZ0lDQWdmVnh1SUNBZ0lIMWNibHh1SUNBZ0lISmxkSFZ5YmlCN1hHNGdJQ0FnSUNBZ0lHTm9hV3hrY21WdU9pQnVaWGREYUdsc1pISmxiaXhjYmlBZ0lDQWdJQ0FnYlc5MlpYTTZJSHRjYmlBZ0lDQWdJQ0FnSUNBZ0lISmxiVzkyWlhNNklISmxiVzkyWlhNc1hHNGdJQ0FnSUNBZ0lDQWdJQ0JwYm5ObGNuUnpPaUJwYm5ObGNuUnpYRzRnSUNBZ0lDQWdJSDFjYmlBZ0lDQjlYRzU5WEc1Y2JtWjFibU4wYVc5dUlISmxiVzkyWlNoaGNuSXNJR2x1WkdWNExDQnJaWGtwSUh0Y2JpQWdJQ0JoY25JdWMzQnNhV05sS0dsdVpHVjRMQ0F4S1Z4dVhHNGdJQ0FnY21WMGRYSnVJSHRjYmlBZ0lDQWdJQ0FnWm5KdmJUb2dhVzVrWlhnc1hHNGdJQ0FnSUNBZ0lHdGxlVG9nYTJWNVhHNGdJQ0FnZlZ4dWZWeHVYRzVtZFc1amRHbHZiaUJyWlhsSmJtUmxlQ2hqYUdsc1pISmxiaWtnZTF4dUlDQWdJSFpoY2lCclpYbHpJRDBnZTMxY2JpQWdJQ0IyWVhJZ1puSmxaU0E5SUZ0ZFhHNGdJQ0FnZG1GeUlHeGxibWQwYUNBOUlHTm9hV3hrY21WdUxteGxibWQwYUZ4dVhHNGdJQ0FnWm05eUlDaDJZWElnYVNBOUlEQTdJR2tnUENCc1pXNW5kR2c3SUdrckt5a2dlMXh1SUNBZ0lDQWdJQ0IyWVhJZ1kyaHBiR1FnUFNCamFHbHNaSEpsYmx0cFhWeHVYRzRnSUNBZ0lDQWdJR2xtSUNoamFHbHNaQzVyWlhrcElIdGNiaUFnSUNBZ0lDQWdJQ0FnSUd0bGVYTmJZMmhwYkdRdWEyVjVYU0E5SUdsY2JpQWdJQ0FnSUNBZ2ZTQmxiSE5sSUh0Y2JpQWdJQ0FnSUNBZ0lDQWdJR1p5WldVdWNIVnphQ2hwS1Z4dUlDQWdJQ0FnSUNCOVhHNGdJQ0FnZlZ4dVhHNGdJQ0FnY21WMGRYSnVJSHRjYmlBZ0lDQWdJQ0FnYTJWNWN6b2dhMlY1Y3l3Z0lDQWdJQzh2SUVFZ2FHRnphQ0J2WmlCclpYa2dibUZ0WlNCMGJ5QnBibVJsZUZ4dUlDQWdJQ0FnSUNCbWNtVmxPaUJtY21WbElDQWdJQ0FnTHk4Z1FXNGdZWEp5WVhrZ2IyWWdkVzVyWlhsbFpDQnBkR1Z0SUdsdVpHbGpaWE5jYmlBZ0lDQjlYRzU5WEc1Y2JtWjFibU4wYVc5dUlHRndjR1Z1WkZCaGRHTm9LR0Z3Y0d4NUxDQndZWFJqYUNrZ2UxeHVJQ0FnSUdsbUlDaGhjSEJzZVNrZ2UxeHVJQ0FnSUNBZ0lDQnBaaUFvYVhOQmNuSmhlU2hoY0hCc2VTa3BJSHRjYmlBZ0lDQWdJQ0FnSUNBZ0lHRndjR3g1TG5CMWMyZ29jR0YwWTJncFhHNGdJQ0FnSUNBZ0lIMGdaV3h6WlNCN1hHNGdJQ0FnSUNBZ0lDQWdJQ0JoY0hCc2VTQTlJRnRoY0hCc2VTd2djR0YwWTJoZFhHNGdJQ0FnSUNBZ0lIMWNibHh1SUNBZ0lDQWdJQ0J5WlhSMWNtNGdZWEJ3YkhsY2JpQWdJQ0I5SUdWc2MyVWdlMXh1SUNBZ0lDQWdJQ0J5WlhSMWNtNGdjR0YwWTJoY2JpQWdJQ0I5WEc1OVhHNWNibjBzZTF3aUxpNHZkbTV2WkdVdmFHRnVaR3hsTFhSb2RXNXJYQ0k2TWpRc1hDSXVMaTkyYm05a1pTOXBjeTEwYUhWdWExd2lPakkxTEZ3aUxpNHZkbTV2WkdVdmFYTXRkbTV2WkdWY0lqb3lOeXhjSWk0dUwzWnViMlJsTDJsekxYWjBaWGgwWENJNk1qZ3NYQ0l1TGk5MmJtOWtaUzlwY3kxM2FXUm5aWFJjSWpveU9TeGNJaTR1TDNadWIyUmxMM1p3WVhSamFGd2lPak15TEZ3aUxpOWthV1ptTFhCeWIzQnpYQ0k2TXpRc1hDSjRMV2x6TFdGeWNtRjVYQ0k2TVRKOVhYMHNlMzBzV3pSZEtTZzBLVnh1ZlNrN1hHNWNibVY0Y0c5eWRDQmtaV1poZFd4MElGWnBjblIxWVd4RVQwMDdYRzRpWFN3aWMyOTFjbU5sVW05dmRDSTZJaTl6YjNWeVkyVXZJbjA9XG4iLCJpbXBvcnQgQ29yZSBmcm9tICcuL2xpYi9jb3JlJztcbmltcG9ydCBFbnVtIGZyb20gJy4vbGliL2VudW0nO1xuaW1wb3J0IFZpcnR1YWxET00gZnJvbSAnLi9saWIvdmlydHVhbC1kb20nO1xuXG5leHBvcnQgZGVmYXVsdCB7XG4gIENvcmUsXG4gIEVudW0sXG4gIFZpcnR1YWxET01cbn07XG4vLyMgc291cmNlTWFwcGluZ1VSTD1kYXRhOmFwcGxpY2F0aW9uL2pzb247YmFzZTY0LGV5SjJaWEp6YVc5dUlqb3pMQ0p6YjNWeVkyVnpJanBiSW1Wc2FYaHBjaTVxY3lKZExDSnVZVzFsY3lJNlcxMHNJbTFoY0hCcGJtZHpJam9pUVVGQlFTeFBRVUZQTEVsQlFWQXNUVUZCYVVJc1dVRkJha0k3UVVGRFFTeFBRVUZQTEVsQlFWQXNUVUZCYVVJc1dVRkJha0k3UVVGRFFTeFBRVUZQTEZWQlFWQXNUVUZCZFVJc2JVSkJRWFpDT3p0QlFVVkJMR1ZCUVdVN1FVRkRZaXhOUVVSaE8wRkJSV0lzVFVGR1lUdEJRVWRpTEZsQlNHRTdRMEZCWmlJc0ltWnBiR1VpT2lKbGJHbDRhWEl1YW5NaUxDSnpiM1Z5WTJWelEyOXVkR1Z1ZENJNld5SnBiWEJ2Y25RZ1EyOXlaU0JtY205dElDY3VMMnhwWWk5amIzSmxKenRjYm1sdGNHOXlkQ0JGYm5WdElHWnliMjBnSnk0dmJHbGlMMlZ1ZFcwbk8xeHVhVzF3YjNKMElGWnBjblIxWVd4RVQwMGdabkp2YlNBbkxpOXNhV0l2ZG1seWRIVmhiQzFrYjIwbk8xeHVYRzVsZUhCdmNuUWdaR1ZtWVhWc2RDQjdYRzRnSUVOdmNtVXNYRzRnSUVWdWRXMHNYRzRnSUZacGNuUjFZV3hFVDAxY2JuMDdYRzRpWFN3aWMyOTFjbU5sVW05dmRDSTZJaTl6YjNWeVkyVXZJbjA9XG4iXSwibmFtZXMiOlsiUHJpbWl0aXZlcy5QSUQiLCJUeXBlcy5WYXJpYWJsZSJdLCJtYXBwaW5ncyI6IkFBRUEsTUFBTSxPQUFPLENBQUM7O0VBRVosV0FBVyxHQUFHO0lBQ1osSUFBSSxDQUFDLFFBQVEsR0FBRyxFQUFFLENBQUM7R0FDcEI7O0VBRUQsT0FBTyxDQUFDLE9BQU8sRUFBRTtJQUNmLElBQUksQ0FBQyxRQUFRLENBQUMsSUFBSSxDQUFDLE9BQU8sQ0FBQyxDQUFDO0lBQzVCLE9BQU8sT0FBTyxDQUFDO0dBQ2hCOztFQUVELEdBQUcsR0FBRztJQUNKLE9BQU8sSUFBSSxDQUFDLFFBQVEsQ0FBQztHQUN0Qjs7RUFFRCxPQUFPLEdBQUc7SUFDUixPQUFPLElBQUksQ0FBQyxRQUFRLENBQUMsTUFBTSxLQUFLLENBQUMsQ0FBQztHQUNuQzs7RUFFRCxRQUFRLENB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 \ No newline at end of file From bfa7319329bf9bf148b67951a976c7f53b93475b Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Sat, 19 Mar 2016 06:57:17 -0500 Subject: [PATCH 196/860] Removed stdlib_state.exs from src control. Updated readme --- .gitignore | 1 + README.md | 1 + lib/elixir_script.ex | 4 ++-- lib/elixir_script/translator/stdlib_state.exs | Bin 130017 -> 0 bytes mix.exs | 2 +- test/translator/pattern_matching_test.exs | 2 +- 6 files changed, 6 insertions(+), 4 deletions(-) delete mode 100644 lib/elixir_script/translator/stdlib_state.exs diff --git a/.gitignore b/.gitignore index af535c67..329b7dbb 100644 --- a/.gitignore +++ b/.gitignore @@ -17,3 +17,4 @@ index.js test/std_lib_compile_test.exs src/elixirscript priv/*.js +lib/elixir_script/translator/stdlib_state.bin diff --git a/README.md b/README.md index ae1a03f8..3580315f 100644 --- a/README.md +++ b/README.md @@ -34,6 +34,7 @@ Get dependencies Compile mix compile + mix std_lib Test diff --git a/lib/elixir_script.ex b/lib/elixir_script.ex index 7ac64832..4f4958c4 100644 --- a/lib/elixir_script.ex +++ b/lib/elixir_script.ex @@ -43,7 +43,7 @@ defmodule ElixirScript do end # This is the serialized state of the ElixirScript.State module containing references to the standard library - @external_resource stdlib_state_path = Path.join([__DIR__, "elixir_script", "translator", "stdlib_state.exs"]) + @external_resource stdlib_state_path = Path.join([__DIR__, "elixir_script", "translator", "stdlib_state.bin"]) @stdlib_state File.read!(stdlib_state_path) @doc """ @@ -123,7 +123,7 @@ defmodule ElixirScript do new_std_state = ElixirScript.Translator.State.serialize() ElixirScript.Translator.State.stop - File.write!(File.cwd!() <> "/lib/elixir_script/translator/stdlib_state.exs", new_std_state) + File.write!(File.cwd!() <> "/lib/elixir_script/translator/stdlib_state.bin", new_std_state) Output.out(libs_path, code, compiler_opts) end diff --git a/lib/elixir_script/translator/stdlib_state.exs b/lib/elixir_script/translator/stdlib_state.exs deleted file mode 100644 index e830ce14ed94e2948621af3aea9167a904eab3b6..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 130017 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 I4-r8BAH7YxQ~&?~ diff --git a/mix.exs b/mix.exs index d1b25d8b..b14f2f1a 100644 --- a/mix.exs +++ b/mix.exs @@ -48,7 +48,7 @@ defmodule ElixirScript.Mixfile do defp package do [ - files: ["lib", "priv/Elixir.js", "mix.exs", "README*", "readme*", "LICENSE*", "license*", "CHANGELOG*"], + files: ["lib", "priv/*.js", "mix.exs", "README*", "readme*", "LICENSE*", "license*", "CHANGELOG*"], maintainers: ["Bryan Joseph"], licenses: ["MIT"], links: %{ diff --git a/test/translator/pattern_matching_test.exs b/test/translator/pattern_matching_test.exs index 45b63ef7..a1025aa2 100644 --- a/test/translator/pattern_matching_test.exs +++ b/test/translator/pattern_matching_test.exs @@ -6,7 +6,7 @@ defmodule ElixirScript.Translator.PatternMatching.Test do alias ElixirScript.Translator.Map alias ESTree.Tools.Builder, as: JS - @std_lib_state File.read!(File.cwd!() <> "/lib/elixir_script/translator/stdlib_state.exs") + @std_lib_state File.read!(File.cwd!() <> "/lib/elixir_script/translator/stdlib_state.bin") setup do ElixirScript.Translator.State.start_link(%{env: ElixirScript.custom_env}) From a4a341fa94cd9f055a7425be499da047481d2fbc Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Sat, 19 Mar 2016 07:01:59 -0500 Subject: [PATCH 197/860] Added build section to readme --- README.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/README.md b/README.md index 3580315f..11ea4702 100644 --- a/README.md +++ b/README.md @@ -42,6 +42,10 @@ Test npm test +Build +============= + MIX_ENV=prod mix do clean, compile, std_lib, dist + Contributing ======== From cf884409491d62dff9e5a7f976f86af827351964 Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Sat, 19 Mar 2016 08:35:40 -0500 Subject: [PATCH 198/860] Updated travis config --- .travis.yml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/.travis.yml b/.travis.yml index 9fc86223..8bb5aaae 100644 --- a/.travis.yml +++ b/.travis.yml @@ -4,8 +4,8 @@ elixir: - 1.2.3 otp_release: - 18.0 -#before_script: -# - npm install +before_script: + - npm install script: - - mix test -# - npm test \ No newline at end of file + - mix std_lib + - mix test \ No newline at end of file From 63290ccdb9e24f4e617b2c681711fef8053faa1a Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Sat, 19 Mar 2016 08:42:55 -0500 Subject: [PATCH 199/860] Added stdlib_state.bin back into source control --- .gitignore | 1 - .travis.yml | 1 - lib/elixir_script/translator/stdlib_state.bin | Bin 0 -> 130008 bytes 3 files changed, 2 deletions(-) create mode 100644 lib/elixir_script/translator/stdlib_state.bin diff --git a/.gitignore b/.gitignore index 329b7dbb..af535c67 100644 --- a/.gitignore +++ b/.gitignore @@ -17,4 +17,3 @@ index.js test/std_lib_compile_test.exs src/elixirscript priv/*.js -lib/elixir_script/translator/stdlib_state.bin diff --git a/.travis.yml b/.travis.yml index 8bb5aaae..611676f9 100644 --- a/.travis.yml +++ b/.travis.yml @@ -7,5 +7,4 @@ otp_release: before_script: - npm install script: - - mix std_lib - mix test \ No newline at end of file diff --git a/lib/elixir_script/translator/stdlib_state.bin b/lib/elixir_script/translator/stdlib_state.bin new file mode 100644 index 0000000000000000000000000000000000000000..6e2726c94d2121873e7d8e1fa58a5a730a3d6b0f GIT binary patch literal 130008 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 F{}1|4yB+`l literal 0 HcmV?d00001 From 979cb95fb0e2a713c1afa4ade171808a521615f2 Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Sat, 19 Mar 2016 08:55:52 -0500 Subject: [PATCH 200/860] Updated travis config --- .travis.yml | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index 611676f9..0499dd73 100644 --- a/.travis.yml +++ b/.travis.yml @@ -4,7 +4,11 @@ elixir: - 1.2.3 otp_release: - 18.0 -before_script: +env: + - TRAVIS_NODE_VERSION="5" +install: + - rm -rf ~/.nvm && git clone https://github.com/creationix/nvm.git ~/.nvm && (cd ~/.nvm && git checkout `git describe --abbrev=0 --tags`) && source ~/.nvm/nvm.sh && nvm install $TRAVIS_NODE_VERSION - npm install script: - - mix test \ No newline at end of file + - mix test + - npm test \ No newline at end of file From 14a3bb8c716140135693b404cf00a7c0786fce15 Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Sat, 19 Mar 2016 08:59:03 -0500 Subject: [PATCH 201/860] travis config: explicitly installing deps --- .travis.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.travis.yml b/.travis.yml index 0499dd73..aac0580c 100644 --- a/.travis.yml +++ b/.travis.yml @@ -10,5 +10,7 @@ install: - rm -rf ~/.nvm && git clone https://github.com/creationix/nvm.git ~/.nvm && (cd ~/.nvm && git checkout `git describe --abbrev=0 --tags`) && source ~/.nvm/nvm.sh && nvm install $TRAVIS_NODE_VERSION - npm install script: + - mix local.hex --force + - mix deps.get - mix test - npm test \ No newline at end of file From 657c115e77f9d0149e96aa3cf89e951af21507b1 Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Tue, 22 Mar 2016 17:15:24 -0500 Subject: [PATCH 202/860] Some refactoring and adding comments to module collector --- lib/elixir_script.ex | 59 +++++++++++++----- .../translator/module_collector.ex | 40 ++++++------ lib/elixir_script/translator/stdlib_state.bin | Bin 130008 -> 129613 bytes 3 files changed, 64 insertions(+), 35 deletions(-) diff --git a/lib/elixir_script.ex b/lib/elixir_script.ex index 4f4958c4..d0bbf277 100644 --- a/lib/elixir_script.ex +++ b/lib/elixir_script.ex @@ -72,17 +72,7 @@ defmodule ElixirScript do def compile_path(path, opts \\ %{}) do expanded_path = Path.wildcard(path) - compiler_cache = if Map.get(opts, :full_build, false) do - Cache.delete(path) - Cache.new(@stdlib_state) - else - case Cache.get(path) do - nil -> - Cache.new(@stdlib_state) - x -> - %{ x | full_build?: false } - end - end + compiler_cache = get_compiler_cache(path, opts) new_file_stats = Cache.build_file_stats(expanded_path) @@ -96,6 +86,35 @@ defmodule ElixirScript do Cache.write(path, compiler_cache) Output.out(path, code, opts) +end + + defp get_compiler_cache(path, opts) do + if Map.get(opts, :full_build) or empty?(opts.output) do + Cache.delete(path) + Cache.new(@stdlib_state) + else + case Cache.get(path) do + nil -> + Cache.new(@stdlib_state) + x -> + %{ x | full_build?: false } + end + end + end + + defp empty?(path) when is_binary(path) do + case File.ls(path) do + {:ok, []} -> + true + {:error, _} -> + true + _ -> + false + end + end + + defp empty?(_) do + true end @doc false @@ -115,9 +134,12 @@ defmodule ElixirScript do |> Enum.map(&file_to_quoted/1) ElixirScript.Translator.State.start_link(compiler_opts) - ModuleCollector.process_modules(Enum.map(code, &update_quoted(&1))) - code = create_code(compiler_opts) + code + |> Enum.map(&update_quoted(&1)) + |> ModuleCollector.process_modules + + code = create_code(compiler_opts, ElixirScript.Translator.State.get) |> Enum.filter(fn({path, _}) -> !String.contains?(path, "ElixirScript.Temp.js") end) new_std_state = ElixirScript.Translator.State.serialize() @@ -129,11 +151,15 @@ defmodule ElixirScript do defp do_compile(opts, quoted_code_list, state \\ @stdlib_state) do compiler_opts = build_compiler_options(opts) + ElixirScript.Translator.State.start_link(compiler_opts) ElixirScript.Translator.State.deserialize(state) - ModuleCollector.process_modules(Enum.map(quoted_code_list, &update_quoted(&1))) - code = create_code(compiler_opts) + quoted_code_list + |> Enum.map(&update_quoted(&1)) + |> ModuleCollector.process_modules + + code = create_code(compiler_opts, ElixirScript.Translator.State.get) new_state = ElixirScript.Translator.State.serialize() ElixirScript.Translator.State.stop @@ -178,10 +204,9 @@ defmodule ElixirScript do __ENV__ end - defp create_code(compiler_opts) do + defp create_code(compiler_opts, state) do parent = self - state = ElixirScript.Translator.State.get Map.values(state.modules) |> Enum.reject(fn(ast) -> diff --git a/lib/elixir_script/translator/module_collector.ex b/lib/elixir_script/translator/module_collector.ex index ce0f26cd..883c0bf7 100644 --- a/lib/elixir_script/translator/module_collector.ex +++ b/lib/elixir_script/translator/module_collector.ex @@ -1,30 +1,34 @@ defmodule ElixirScript.Translator.ModuleCollector do @moduledoc false + # This module is responsible for + # taking the compiler input and parsing out any modules found + # These modules are then added to ElixirScript.Translator.State + alias ElixirScript.Translator.State alias ElixirScript.Translator.Utils def process_modules(modules) do Enum.map(modules, fn { :__block__, _, list } -> - {modules, not_modules} = Enum.partition(list, fn - ({:defprotocol, _, _ }) -> - true - ({:defimpl, _, _ }) -> - true - ({:defmodule, _, _}) -> - true - _ -> - false - end) - - temp_module = [{:defmodule, [], [{:__aliases__, [], [:ElixirScript, :Temp]}, [do: { :__block__, [], not_modules }]]}] - modules ++ temp_module - ({:defprotocol, _, _ }) = x -> - x - ({:defimpl, _, _}) = x -> - x - ({:defmodule, _, _}) = x -> + {modules, not_modules} = Enum.partition(list, + fn + {type, _, _ } when type in [:defprotocol, :defimpl, :defmodule] -> + true + _ -> + false + end) + + temp_module = case not_modules do + [] -> + [] + _ -> + [{:defmodule, [], [{:__aliases__, [], [:ElixirScript, :Temp]}, [do: { :__block__, [], not_modules }]]}] + end + + modules ++ temp_module + + {type, _, _ } = x when type in [:defprotocol, :defimpl, :defmodule] -> x x -> {:defmodule, [], [{:__aliases__, [], [:ElixirScript, :Temp]}, [do: { :__block__, [], [x] }]]} diff --git a/lib/elixir_script/translator/stdlib_state.bin b/lib/elixir_script/translator/stdlib_state.bin index 6e2726c94d2121873e7d8e1fa58a5a730a3d6b0f..48607d487056a9ac41ec3eaed72dbcaaa3afc91a 100644 GIT binary patch delta 121 zcmccdo&D?=_6>}z{N)TFkix){lbM&AcxHMdE2GF{6;?rxBnAd1-4q6~$qRu3eyk#_ zV1el$4>O8Su4WZO=Gro`Z{Eln%ETg-!XOD!-z>+mU5}z{8 z;GF3SzZh9IZ)c5QVw7$c;Mgv}!MJMIWMxfJmXOrkg2@v#U8fgqVw9Tvz_x$#ht<}T Z3zQ);(+zhq8cbhM!YH@>{2|6Va{xJKEe8Mq From bee94a2946a80e213ba14847573c353b70a5bbd0 Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Fri, 25 Mar 2016 18:49:33 -0500 Subject: [PATCH 203/860] Some updates to change log --- CHANGELOG.md | 4 ++-- lib/elixir_script/translator/stdlib_state.bin | Bin 129613 -> 129604 bytes 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 72874597..98509b60 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,9 +1,9 @@ # v0.17.0-dev * Enhancements * Incremental Compilation: - Now ElixirScript will only build files and modules that have changed since the last build + ElixirScript will now only build files and modules that have changed since the last build * Added `output` as an option for compiler functions. This controls whether output is returned as a list of tuples, send to stdout, or saved to a file path - * Added `:full_build` as an option for compiler functions and `--full-build` option to CLI. These tell the compiler to perform a full build + * Added `:full_build` as an option for compiler functions and `--full-build` option to CLI. These force the compiler to perform a full build * Added `--version` option to CLI. Outputs current version of elixirscript * Added `--std-lib` option to CLI. Takes a path and adds the stdlib to that path diff --git a/lib/elixir_script/translator/stdlib_state.bin b/lib/elixir_script/translator/stdlib_state.bin index 48607d487056a9ac41ec3eaed72dbcaaa3afc91a..8e1aa3e667a4f43612966970cd96c9e94d44268c 100644 GIT binary patch delta 62 zcmX^6h5g7E_6>}zjG2>}SdEzyYbO`@N=|;wD8P~d;wWm0PZnYlfpexS{9}z{N)TFkix){lbM&AcxHMdE2GF{6;?rxBnAd1-4q6~$qRu3eyk#_ eV1elizcGqWu4WZO=Gro`H*aL!zLAx2@)rPO!5KaP From 019684cc85011296ec99efa070b8cfcf7329d7c0 Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Sat, 26 Mar 2016 12:26:28 -0500 Subject: [PATCH 204/860] Added Empty struct --- lib/elixir_script.ex | 20 +++++++------ lib/elixir_script/translator.ex | 28 +++++++++--------- lib/elixir_script/translator/empty.ex | 6 ++++ lib/elixir_script/translator/stdlib_state.bin | Bin 129604 -> 129613 bytes lib/elixir_script/translator/utils.ex | 2 ++ 5 files changed, 33 insertions(+), 23 deletions(-) create mode 100644 lib/elixir_script/translator/empty.ex diff --git a/lib/elixir_script.ex b/lib/elixir_script.ex index d0bbf277..4c2ffcb9 100644 --- a/lib/elixir_script.ex +++ b/lib/elixir_script.ex @@ -317,15 +317,17 @@ end defp prepare_js_ast(js_ast) do js_ast = case js_ast do - modules when is_list(modules) -> - modules - |> Enum.reduce([], &(&2 ++ &1.body)) - |> Builder.program - %ElixirScript.Translator.Group{ body: body } -> - Builder.program(body) - _ -> - js_ast - end + modules when is_list(modules) -> + modules + |> Enum.reduce([], &(&2 ++ &1.body)) + |> Builder.program + %ElixirScript.Translator.Group{ body: body } -> + Builder.program(body) + %ElixirScript.Translator.Empty{ } -> + Builder.program([]) + _ -> + js_ast + end js_ast end diff --git a/lib/elixir_script/translator.ex b/lib/elixir_script/translator.ex index 7a67f853..81b75388 100644 --- a/lib/elixir_script/translator.ex +++ b/lib/elixir_script/translator.ex @@ -163,7 +163,7 @@ defmodule ElixirScript.Translator do defp do_translate({:@, _, [{name, _, _}]}, env) when name in @module_attributes_to_ignore do - { %ElixirScript.Translator.Group{}, env } + { %ElixirScript.Translator.Empty{}, env } end defp do_translate({:@, _, [{name, _, [value]}]}, env) do @@ -344,13 +344,13 @@ defmodule ElixirScript.Translator do ElixirScript.Translator.Env.add_import(acc, module_name) end) - { %ElixirScript.Translator.Group{}, env } + { %ElixirScript.Translator.Empty{}, env } end defp do_translate({:import, _, [{:__aliases__, _, _} = module_name]}, env) do env = ElixirScript.Translator.Env.add_import(env, module_name) - { %ElixirScript.Translator.Group{}, env } + { %ElixirScript.Translator.Empty{}, env } end defp do_translate({:import, _, [{:__aliases__, _, _} = module_name, options]}, env) do @@ -358,7 +358,7 @@ defmodule ElixirScript.Translator do env = ElixirScript.Translator.Env.add_import(env, module_name, options) - { %ElixirScript.Translator.Group{}, env } + { %ElixirScript.Translator.Empty{}, env } end defp do_translate({:alias, _, [{{:., _, [{:__aliases__, _, head_alias_name}, :{}]}, _, tail_aliases }]}, env) do @@ -371,7 +371,7 @@ defmodule ElixirScript.Translator do ElixirScript.Translator.Env.add_alias(acc, module_name, alias_name) end) - { %ElixirScript.Translator.Group{}, env } + { %ElixirScript.Translator.Empty{}, env } end defp do_translate({:alias, _, [{:__aliases__, _, _} = module_name] }, env) do @@ -382,7 +382,7 @@ defmodule ElixirScript.Translator do alias_name = Utils.quoted_to_name({:__aliases__, [], name }) env = ElixirScript.Translator.Env.add_alias(env, module_name, alias_name) - { %ElixirScript.Translator.Group{}, env } + { %ElixirScript.Translator.Empty{}, env } end defp do_translate({:alias, _, [{:__aliases__, _, _} = module_name, [as: {:__aliases__, _, _} = alias_name]]}, env) do @@ -390,7 +390,7 @@ defmodule ElixirScript.Translator do alias_name = Utils.quoted_to_name(alias_name) env = ElixirScript.Translator.Env.add_alias(env, module_name, alias_name) - { %ElixirScript.Translator.Group{}, env } + { %ElixirScript.Translator.Empty{}, env } end defp do_translate({:require, _, [{{:., _, [{:__aliases__, _, head_require_name}, :{}]}, _, tail_requires }]}, env) do @@ -401,13 +401,13 @@ defmodule ElixirScript.Translator do ElixirScript.Translator.Env.add_require(acc, module_name) end) - { %ElixirScript.Translator.Group{}, env } + { %ElixirScript.Translator.Empty{}, env } end defp do_translate({:require, _, [{:__aliases__, _, _} = module_name] }, env) do module_name = Utils.quoted_to_name(module_name) env = ElixirScript.Translator.Env.add_require(env, module_name) - { %ElixirScript.Translator.Group{}, env } + { %ElixirScript.Translator.Empty{}, env } end defp do_translate({:require, _, [{:__aliases__, _, _} = module_name, [as: {:__aliases__, _, _} = alias_name]]}, env) do @@ -415,7 +415,7 @@ defmodule ElixirScript.Translator do alias_name = Utils.quoted_to_name(alias_name) env = ElixirScript.Translator.Env.add_require(env, module_name, alias_name) - { %ElixirScript.Translator.Group{}, env } + { %ElixirScript.Translator.Empty{}, env } end defp do_translate({:case, _, [condition, [do: clauses]]}, env) do @@ -472,19 +472,19 @@ defmodule ElixirScript.Translator do end defp do_translate({:defprotocol, _, _}, env) do - { %ElixirScript.Translator.Group{}, env } + { %ElixirScript.Translator.Empty{}, env } end defp do_translate({:defmacro, _, _}, env) do - { %ElixirScript.Translator.Group{}, env } + { %ElixirScript.Translator.Empty{}, env } end defp do_translate({:defmacrop, _, _}, env) do - { %ElixirScript.Translator.Group{}, env } + { %ElixirScript.Translator.Empty{}, env } end defp do_translate({:defimpl, _, _}, env) do - { %ElixirScript.Translator.Group{}, env } + { %ElixirScript.Translator.Empty{}, env } end defp do_translate({:|, _, [item, list]}, env) do diff --git a/lib/elixir_script/translator/empty.ex b/lib/elixir_script/translator/empty.ex new file mode 100644 index 00000000..7810dc62 --- /dev/null +++ b/lib/elixir_script/translator/empty.ex @@ -0,0 +1,6 @@ +defmodule ElixirScript.Translator.Empty do + @moduledoc false + + @type t :: %ElixirScript.Translator.Empty{} + defstruct type: "Empty" +end diff --git a/lib/elixir_script/translator/stdlib_state.bin b/lib/elixir_script/translator/stdlib_state.bin index 8e1aa3e667a4f43612966970cd96c9e94d44268c..fbfadd55bec6fe2a563ae1185a29065e36cad906 100644 GIT binary patch delta 90 zcmX@|h5hUo_6>}z{N)TFkix){lbM&AcxHMdE2GF{6;?rxBnAd1>l6mD$qRu3eyk#_ eV1elizcGqWu4WZO=Gro`H*aL!zLAx2@)rPUaT#a; delta 62 zcmX^6h5g7E_6>}zjG2>}SdEzyYbO`@N=|;wD8P~d;wWm0PZnYlfpexS{9 case x do + %ElixirScript.Translator.Empty{} -> + [] %ElixirScript.Translator.Group{body: group_body} -> group_body %ESTree.BlockStatement{} -> From 81da83ba512b3e5ad6a41d6ed0c045e9629abbf6 Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Sat, 26 Mar 2016 12:43:53 -0500 Subject: [PATCH 205/860] Added more developer documentation --- lib/elixir_script/module_systems/es6.ex | 1 - lib/elixir_script/translator/empty.ex | 2 ++ lib/elixir_script/translator/group.ex | 11 +++++++---- lib/elixir_script/translator/protocol.ex | 1 - lib/elixir_script/translator/stdlib_state.bin | Bin 129613 -> 129613 bytes 5 files changed, 9 insertions(+), 6 deletions(-) diff --git a/lib/elixir_script/module_systems/es6.ex b/lib/elixir_script/module_systems/es6.ex index ef5cb7a4..1a706e7c 100644 --- a/lib/elixir_script/module_systems/es6.ex +++ b/lib/elixir_script/module_systems/es6.ex @@ -1,7 +1,6 @@ defmodule ElixirScript.ModuleSystems.ES6 do alias ESTree.Tools.Builder, as: JS alias ElixirScript.Translator - alias ElixirScript.Translator.Utils def import_module(module_names, from, env) when is_list(module_names) do import_specifiers = Enum.map(module_names, fn(x) -> diff --git a/lib/elixir_script/translator/empty.ex b/lib/elixir_script/translator/empty.ex index 7810dc62..1456cc4f 100644 --- a/lib/elixir_script/translator/empty.ex +++ b/lib/elixir_script/translator/empty.ex @@ -1,6 +1,8 @@ defmodule ElixirScript.Translator.Empty do @moduledoc false + # Represents no translation to JS AST + @type t :: %ElixirScript.Translator.Empty{} defstruct type: "Empty" end diff --git a/lib/elixir_script/translator/group.ex b/lib/elixir_script/translator/group.ex index a16665b5..e2c2b609 100644 --- a/lib/elixir_script/translator/group.ex +++ b/lib/elixir_script/translator/group.ex @@ -1,9 +1,12 @@ defmodule ElixirScript.Translator.Group do @moduledoc false - @type t :: %ElixirScript.Translator.Group{ - type: binary, - body: [ESTree.Statement.t] + # Represents a collection of JavaScript AST. + # Contents in body are expanded within outer AST before JS code generation + + @type t :: %ElixirScript.Translator.Group{ + type: binary, + body: [ESTree.Statement.t] } defstruct type: "Group", body: [] -end \ No newline at end of file +end diff --git a/lib/elixir_script/translator/protocol.ex b/lib/elixir_script/translator/protocol.ex index f281eff9..6e342938 100644 --- a/lib/elixir_script/translator/protocol.ex +++ b/lib/elixir_script/translator/protocol.ex @@ -4,7 +4,6 @@ defmodule ElixirScript.Translator.Protocol do alias ESTree.Tools.Builder, as: JS alias ElixirScript.Translator.Module alias ElixirScript.Translator.Map - alias ElixirScript.Translator.Function alias ElixirScript.Translator.Utils alias ElixirScript.ModuleSystems require Logger diff --git a/lib/elixir_script/translator/stdlib_state.bin b/lib/elixir_script/translator/stdlib_state.bin index fbfadd55bec6fe2a563ae1185a29065e36cad906..4f4a5b62abff453d1c41c9ce90268ac7b248639c 100644 GIT binary patch delta 61 zcmX^6h5hUo_6?S-j6RbKd?hEpW)xu0U`k?OVDg!)s3|^Kh)D#QKV9J$BTMsk*6rI_ I8K->#09CgVoB#j- delta 61 zcmX^6h5hUo_6?S-jMkG2d?hEpW)xu0U`k?OV6vX9s3|^Kh)D#QKV9J$BTMsk*6rI_ I8K->#08YLVX#fBK From d013b5af1caf053caec36289712f24639353f8ee Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Mon, 28 Mar 2016 20:38:41 -0500 Subject: [PATCH 206/860] Added environment configs. Added lib_path configuration --- config/config.exs | 4 +++- config/dev.exs | 1 + config/prod.exs | 1 + config/test.exs | 1 + lib/elixir_script.ex | 24 ++++++++++++++++-------- 5 files changed, 22 insertions(+), 9 deletions(-) create mode 100644 config/dev.exs create mode 100644 config/prod.exs create mode 100644 config/test.exs diff --git a/config/config.exs b/config/config.exs index a45f173b..32ca3de0 100644 --- a/config/config.exs +++ b/config/config.exs @@ -15,10 +15,12 @@ use Mix.Config format: "$date $time [$level] $metadata$message\n", metadata: [:user_id] + config :elixir_script, + lib_path: nil #The path to the elixirscript core and standard library JavaScript files # It is also possible to import configuration files, relative to this # directory. For example, you can emulate configuration per environment # by uncommenting the line below and defining dev.exs, test.exs and such. # Configuration from the imported file will override the ones defined # here (which is why it is important to import them last). # -# import_config "#{Mix.env}.exs" \ No newline at end of file + import_config "#{Mix.env}.exs" diff --git a/config/dev.exs b/config/dev.exs new file mode 100644 index 00000000..d2d855e6 --- /dev/null +++ b/config/dev.exs @@ -0,0 +1 @@ +use Mix.Config diff --git a/config/prod.exs b/config/prod.exs new file mode 100644 index 00000000..d2d855e6 --- /dev/null +++ b/config/prod.exs @@ -0,0 +1 @@ +use Mix.Config diff --git a/config/test.exs b/config/test.exs new file mode 100644 index 00000000..d2d855e6 --- /dev/null +++ b/config/test.exs @@ -0,0 +1 @@ +use Mix.Config diff --git a/lib/elixir_script.ex b/lib/elixir_script.ex index 4c2ffcb9..f0bc1431 100644 --- a/lib/elixir_script.ex +++ b/lib/elixir_script.ex @@ -45,6 +45,7 @@ defmodule ElixirScript do # This is the serialized state of the ElixirScript.State module containing references to the standard library @external_resource stdlib_state_path = Path.join([__DIR__, "elixir_script", "translator", "stdlib_state.bin"]) @stdlib_state File.read!(stdlib_state_path) + @lib_path Application.get_env(:elixir_script, :lib_path) @doc """ Compiles the given Elixir code string @@ -71,6 +72,7 @@ defmodule ElixirScript do @spec compile_path(binary, Map.t) :: [binary | {binary, binary} | :ok] def compile_path(path, opts \\ %{}) do expanded_path = Path.wildcard(path) + opts = build_compiler_options(opts) compiler_cache = get_compiler_cache(path, opts) @@ -335,14 +337,20 @@ end #Gets path to js files whether the mix project is available #or when used as an escript defp operating_path do - try do - Mix.Project.build_path <> "/lib/elixir_script/priv" - rescue - UndefinedFunctionError -> - split_path = Path.split(Application.app_dir(:elixirscript)) - replaced_path = List.delete_at(split_path, length(split_path) - 1) - replaced_path = List.delete_at(replaced_path, length(replaced_path) - 1) - Path.join(replaced_path) + case @lib_path do + nil -> + try do + Mix.Project.build_path <> "/lib/elixir_script/priv" + rescue + UndefinedFunctionError -> + split_path = Path.split(Application.app_dir(:elixirscript)) + replaced_path = List.delete_at(split_path, length(split_path) - 1) + replaced_path = List.delete_at(replaced_path, length(replaced_path) - 1) + Path.join(replaced_path) + end + lib_path -> + lib_path end end + end From eeac2ebe36a57f80f295ac7242c2115617854187 Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Mon, 28 Mar 2016 21:06:18 -0500 Subject: [PATCH 207/860] Removed stdlib_state.bin --- lib/elixir_script.ex | 21 +++++++++++++----- lib/elixir_script/translator/stdlib_state.bin | Bin 129613 -> 0 bytes 2 files changed, 15 insertions(+), 6 deletions(-) delete mode 100644 lib/elixir_script/translator/stdlib_state.bin diff --git a/lib/elixir_script.ex b/lib/elixir_script.ex index f0bc1431..7a84cdf2 100644 --- a/lib/elixir_script.ex +++ b/lib/elixir_script.ex @@ -44,7 +44,7 @@ defmodule ElixirScript do # This is the serialized state of the ElixirScript.State module containing references to the standard library @external_resource stdlib_state_path = Path.join([__DIR__, "elixir_script", "translator", "stdlib_state.bin"]) - @stdlib_state File.read!(stdlib_state_path) + @stdlib_state File.read(stdlib_state_path) @lib_path Application.get_env(:elixir_script, :lib_path) @doc """ @@ -62,7 +62,7 @@ defmodule ElixirScript do """ @spec compile_quoted(Macro.t, Map.t) :: [binary | {binary, binary} | :ok] def compile_quoted(quoted, opts \\ %{}) do - { code, _ } = do_compile(opts, [quoted]) + { code, _ } = do_compile(opts, [quoted], get_stdlib_state) Output.out(quoted, code, build_compiler_options(opts)) end @@ -88,16 +88,25 @@ defmodule ElixirScript do Cache.write(path, compiler_cache) Output.out(path, code, opts) -end + end + + defp get_stdlib_state() do + case @stdlib_state do + {:ok, data} -> + data + {:error, _} -> + raise RuntimeError, message: "Standard Library state not found. Please run `mix std_lib`" + end + end defp get_compiler_cache(path, opts) do if Map.get(opts, :full_build) or empty?(opts.output) do Cache.delete(path) - Cache.new(@stdlib_state) + Cache.new(get_stdlib_state) else case Cache.get(path) do nil -> - Cache.new(@stdlib_state) + Cache.new(get_stdlib_state) x -> %{ x | full_build?: false } end @@ -151,7 +160,7 @@ end Output.out(libs_path, code, compiler_opts) end - defp do_compile(opts, quoted_code_list, state \\ @stdlib_state) do + defp do_compile(opts, quoted_code_list, state) do compiler_opts = build_compiler_options(opts) ElixirScript.Translator.State.start_link(compiler_opts) diff --git a/lib/elixir_script/translator/stdlib_state.bin b/lib/elixir_script/translator/stdlib_state.bin deleted file mode 100644 index 4f4a5b62abff453d1c41c9ce90268ac7b248639c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 129613 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 KObR_j0R4Zc%`@!) From e7df6b6e0b8f720a4358d37cff2440f75ca0fcfd Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Mon, 28 Mar 2016 21:11:23 -0500 Subject: [PATCH 208/860] Added function to get standard lib state and throw error if unavailable --- .gitignore | 1 + README.md | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/.gitignore b/.gitignore index af535c67..ec7fe1c3 100644 --- a/.gitignore +++ b/.gitignore @@ -17,3 +17,4 @@ index.js test/std_lib_compile_test.exs src/elixirscript priv/*.js +stdlib_state.bin diff --git a/README.md b/README.md index 11ea4702..a7f37f30 100644 --- a/README.md +++ b/README.md @@ -33,8 +33,8 @@ Get dependencies Compile - mix compile mix std_lib + mix compile Test From 1d3fab669bca990ab3c4b8139cfff49f90f786a0 Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Mon, 28 Mar 2016 21:12:34 -0500 Subject: [PATCH 209/860] Updated travis configuration --- .travis.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.travis.yml b/.travis.yml index aac0580c..0d4ec731 100644 --- a/.travis.yml +++ b/.travis.yml @@ -12,5 +12,6 @@ install: script: - mix local.hex --force - mix deps.get + - mix do std_lib, clean, compile - mix test - npm test \ No newline at end of file From 8efadb731aaf11d5bab3550151bbceeee0a83116 Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Tue, 29 Mar 2016 21:27:30 -0500 Subject: [PATCH 210/860] Updated Build section of README with information on how to change lib path --- README.md | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index a7f37f30..a2d3bfd1 100644 --- a/README.md +++ b/README.md @@ -33,8 +33,7 @@ Get dependencies Compile - mix std_lib - mix compile + mix do std_lib, clean, compile Test @@ -46,6 +45,12 @@ Build ============= MIX_ENV=prod mix do clean, compile, std_lib, dist + This will build a tarball in the dist folder. + By default the escript built will look into the folder above it for the + core JavaScript files needed for ElixirScript. To change the location, + update the `lib_path` config variable in the `:elixir_script` config block + to the path to look in and then do a clean build. + Contributing ======== From d1889375db02e02a0e3bbf240eca725cd32a19a4 Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Tue, 29 Mar 2016 21:29:10 -0500 Subject: [PATCH 211/860] Updated README --- README.md | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index a2d3bfd1..9a4da446 100644 --- a/README.md +++ b/README.md @@ -45,11 +45,11 @@ Build ============= MIX_ENV=prod mix do clean, compile, std_lib, dist - This will build a tarball in the dist folder. - By default the escript built will look into the folder above it for the - core JavaScript files needed for ElixirScript. To change the location, - update the `lib_path` config variable in the `:elixir_script` config block - to the path to look in and then do a clean build. +This will build a tarball in the dist folder. +By default the escript built will look into the folder above it for the +core JavaScript files needed for ElixirScript. To change the location, +update the `lib_path` config variable in the `:elixir_script` config block +to the path to look in and then do a clean build. Contributing ======== From 95e2a4ba2e8fc9a26abf84d0625b1d0b0459e1e2 Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Thu, 31 Mar 2016 15:25:00 -0500 Subject: [PATCH 212/860] Preparing for release --- CHANGELOG.md | 2 +- mix.exs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 98509b60..38376a0c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,4 +1,4 @@ -# v0.17.0-dev +# v0.17.0 * Enhancements * Incremental Compilation: ElixirScript will now only build files and modules that have changed since the last build diff --git a/mix.exs b/mix.exs index b14f2f1a..1cd38977 100644 --- a/mix.exs +++ b/mix.exs @@ -4,7 +4,7 @@ defmodule ElixirScript.Mixfile do def project do [ app: :elixir_script, - version: "0.17.0-dev", + version: "0.17.0", elixir: "~> 1.0", escript: escript_config, deps: deps, From 40e316b53b556c04c1927198384176e788c939b2 Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Thu, 31 Mar 2016 15:28:34 -0500 Subject: [PATCH 213/860] Updated docs --- GettingStarted.md | 28 ++++++++++++++++------------ 1 file changed, 16 insertions(+), 12 deletions(-) diff --git a/GettingStarted.md b/GettingStarted.md index cb50ec93..aef64cd7 100644 --- a/GettingStarted.md +++ b/GettingStarted.md @@ -28,16 +28,20 @@ The intent of this guide is to get you started with ElixirScript. It will give y This is the help output of elixirscript ```bash - usage: elixirscript [options] - - path to elixir files or - the elixir code string if the -ex flag is used - - options: - -o --output [path] places output at the given path - -ex --elixir read input as elixir code string - -r --root [path] root path for standard libs - -h --help this message + usage: elixirscript [options] + path to elixir files or the elixir code string if the -ex flag is used + + options: + -o --output [path] places output at the given path + -ex --elixir read input as elixir code string + -r --root [path] root import path for all exported modules + --std-lib [path] outputs the elixirscript standard library JavaScript files to the specified path + --full-build informs the compiler to do a full build instead of an incremental one + only used when output is specified + --core-path es6 import path to the elixirscript standard lib + only used with the [output] option. When used, Elixir.js is not exported + -v --version the current version number + -h --help this message ``` the `` is the elixir code string or file path you want to convert from elixir to javascript. Below is an example of using a code string and turning it into JavaScript @@ -97,7 +101,7 @@ The intent of this guide is to get you started with ElixirScript. It will give y The first step is getting the dependency. In your mix.exs file for your elixir project, add elixir_script to your deps. ```elixir - {:elixir_script, "~> 0.16"} + {:elixir_script, "~> 0.17"} ``` * Step 2: Now download the dep @@ -121,7 +125,7 @@ The intent of this guide is to get you started with ElixirScript. It will give y The first step is getting the dependency. In your mix.exs file for your elixir project, add elixir_script to your deps. ```elixir - {:elixir_script, "~> 0.15"} + {:elixir_script, "~> 0.17"} ``` * Step 2: Now download the dep From 1d8195565278009b90fcf3162f3563066990088a Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Sun, 3 Apr 2016 16:00:01 -0500 Subject: [PATCH 214/860] Update README.md --- README.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/README.md b/README.md index 9a4da446..01b1b3df 100644 --- a/README.md +++ b/README.md @@ -66,3 +66,6 @@ Please check the [CONTRIBUTING.md](CONTRIBUTING.md) #### Using with Brunch There is a plugin for using ElixirScript in your Brunch project [here](https://www.npmjs.com/package/elixirscript-brunch) + +#### 1.0 Roadmap +There is a [1.0.0 Milestone](https://github.com/bryanjos/elixirscript/milestones/1.0.0) defined which includes issues that are needed to be cleared before 1.0 can be reached. From d8d5501151483a156099575099e10aed2f9504bd Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Wed, 6 Apr 2016 20:22:04 -0500 Subject: [PATCH 215/860] Updated Env.ex to create new Macro.Env with loaded modules when doing imports or requires --- lib/elixir_script.ex | 6 +- lib/elixir_script/prelude/macro/env.ex | 8 +- lib/elixir_script/translator/env.ex | 158 +++++++++++++++------- lib/elixir_script/translator/state.ex | 17 ++- test/translator/pattern_matching_test.exs | 46 +++---- 5 files changed, 153 insertions(+), 82 deletions(-) diff --git a/lib/elixir_script.ex b/lib/elixir_script.ex index 7a84cdf2..17c3d90c 100644 --- a/lib/elixir_script.ex +++ b/lib/elixir_script.ex @@ -144,7 +144,7 @@ defmodule ElixirScript do end) |> Enum.map(&file_to_quoted/1) - ElixirScript.Translator.State.start_link(compiler_opts) + ElixirScript.Translator.State.start_link(compiler_opts, []) code |> Enum.map(&update_quoted(&1)) @@ -163,7 +163,7 @@ defmodule ElixirScript do defp do_compile(opts, quoted_code_list, state) do compiler_opts = build_compiler_options(opts) - ElixirScript.Translator.State.start_link(compiler_opts) + ElixirScript.Translator.State.start_link(compiler_opts, []) ElixirScript.Translator.State.deserialize(state) quoted_code_list @@ -225,7 +225,7 @@ defmodule ElixirScript do end) |> Enum.map(fn ast -> spawn_link fn -> - env = ElixirScript.Translator.Env.module_env(ast.name, Utils.name_to_js_file_name(ast.name) <> ".js") + env = ElixirScript.Translator.Env.module_env(ast.name, Utils.name_to_js_file_name(ast.name) <> ".js", state.compiler_opts.env) module = case ast.type do :module -> diff --git a/lib/elixir_script/prelude/macro/env.ex b/lib/elixir_script/prelude/macro/env.ex index f634409d..05d74707 100644 --- a/lib/elixir_script/prelude/macro/env.ex +++ b/lib/elixir_script/prelude/macro/env.ex @@ -1,5 +1,5 @@ defmodule ElixirScript.Macro.Env do - @type t :: %ElixirScript.Macro.Env{ + @type t :: %ElixirScript.Macro.Env{ module: atom, file: binary, line: non_neg_integer, @@ -14,7 +14,8 @@ defmodule ElixirScript.Macro.Env do vars: [{atom, atom | non_neg_integer}], export_vars: [{atom, atom | non_neg_integer}] | nil, lexical_tracker: nil, - caller: t | nil + caller: t | nil, + env: nil } defstruct [ @@ -32,6 +33,7 @@ defmodule ElixirScript.Macro.Env do vars: [], export_vars: nil, lexical_tracker: nil, - caller: nil + caller: nil, + env: nil ] end diff --git a/lib/elixir_script/translator/env.ex b/lib/elixir_script/translator/env.ex index 41c8bbc0..e888ccac 100644 --- a/lib/elixir_script/translator/env.ex +++ b/lib/elixir_script/translator/env.ex @@ -1,24 +1,26 @@ defmodule ElixirScript.Translator.Env do @moduledoc false - def module_env(ElixirScript.Temp, filename) do + def module_env(ElixirScript.Temp, filename, env) do env = %ElixirScript.Macro.Env { module: ElixirScript.Temp, file: filename, requires: [], functions: [], - macros: [] + macros: [], + env: env } add_import(env, ElixirScript.Kernel) end - def module_env(module_name, filename) do + def module_env(module_name, filename, env) do module = ElixirScript.Translator.State.get_module(module_name) env = %ElixirScript.Macro.Env { module: module_name, file: filename, requires: [], functions: [{ module.name, module.functions}], - macros: [{ module.name, module.macros}] + macros: [{ module.name, module.macros}], + env: env } add_import(env, ElixirScript.Kernel) @@ -105,76 +107,110 @@ defmodule ElixirScript.Translator.Env do module end - def add_import(env, module_name) do + def add_alias(env, module_name, alias_name) do module = get_module(env, module_name) + %{ env | aliases: Enum.uniq(env.aliases ++ [{alias_name, module.name}]) } + end - %{ env | requires: Enum.uniq(env.requires ++ [module.name]), - functions: env.functions ++ [{ module.name, module.functions }], - macros: env.macros ++ [{ module.name, module.macros }] } + def add_import(env, module_name) do + case ElixirScript.Translator.State.is_module_loaded?(module_name) do + true -> + add_import_macro(env, module_name, []) + false -> + module = get_module(env, module_name) + + %{ env | requires: Enum.uniq(env.requires ++ [module.name]), + functions: env.functions ++ [{ module.name, module.functions }], + macros: env.macros ++ [{ module.name, module.macros }] } + end end def add_import(env, module_name, [only: :functions]) do - module = get_module(env, module_name) - - %{ env | functions: List.keydelete(env.functions, module_name, 0) ++ [{ module.name, module.functions }], - macros: List.keydelete(env.macros, module.name, 0), - requires: Enum.uniq(env.requires ++ [module.name]) } + case ElixirScript.Translator.State.is_module_loaded?(module_name) do + true -> + add_import_macro(env, module_name, [only: :functions]) + false -> + module = get_module(env, module_name) + + %{ env | functions: List.keydelete(env.functions, module_name, 0) ++ [{ module.name, module.functions }], + macros: List.keydelete(env.macros, module.name, 0), + requires: Enum.uniq(env.requires ++ [module.name]) } + end end def add_import(env, module_name, [only: :macros]) do - module = get_module(env, module_name) - - %{ env | macros: List.keydelete(env.macros, module_name, 0) ++ [{ module.name, module.macros }], - functions: List.keydelete(env.functions, module.name, 0), - requires: Enum.uniq(env.requires ++ [module.name]) } + case ElixirScript.Translator.State.is_module_loaded?(module_name) do + true -> + add_import_macro(env, module_name, [only: :macros]) + false -> + module = get_module(env, module_name) + + %{ env | macros: List.keydelete(env.macros, module_name, 0) ++ [{ module.name, module.macros }], + functions: List.keydelete(env.functions, module.name, 0), + requires: Enum.uniq(env.requires ++ [module.name]) } + end end def add_import(env, module_name, [only: only]) do - module = get_module(env, module_name) - - macros = Enum.filter(module.macros, fn(mac) -> - mac in only - end) - functions = Enum.filter(module.functions, fn(func) -> - func in only - end) - - %{ env | requires: Enum.uniq(env.requires ++ [module.name]), - functions: List.keydelete(env.functions, module.name, 0) ++ [{ module.name, functions }], - macros: List.keydelete(env.macros, module.name, 0) ++ [{ module.name, macros }] } + case ElixirScript.Translator.State.is_module_loaded?(module_name) do + true -> + add_import_macro(env, module_name, [only: only]) + false -> + module = get_module(env, module_name) + + macros = Enum.filter(module.macros, fn(mac) -> + mac in only + end) + functions = Enum.filter(module.functions, fn(func) -> + func in only + end) + + %{ env | requires: Enum.uniq(env.requires ++ [module.name]), + functions: List.keydelete(env.functions, module.name, 0) ++ [{ module.name, functions }], + macros: List.keydelete(env.macros, module.name, 0) ++ [{ module.name, macros }] } + end end def add_import(env, module_name, [except: except]) do - module = get_module(env, module_name) + case ElixirScript.Translator.State.is_module_loaded?(module_name) do + true -> + add_import_macro(env, module_name, [except: except]) + false -> + module = get_module(env, module_name) - {_, current_functions } = List.keyfind(env.functions, module.name, 0, { module.name, module.functions }) - {_, current_macros } = List.keyfind(env.macros, module.name, 0, { module.name, module.macros }) + {_, current_functions } = List.keyfind(env.functions, module.name, 0, { module.name, module.functions }) + {_, current_macros } = List.keyfind(env.macros, module.name, 0, { module.name, module.macros }) - macros = Enum.filter(current_macros, fn(mac) -> not(mac in except) end) - functions = Enum.filter(current_functions, fn(func) -> not(func in except) end) + macros = Enum.filter(current_macros, fn(mac) -> not(mac in except) end) + functions = Enum.filter(current_functions, fn(func) -> not(func in except) end) - %{ env | requires: env.requires ++ [module.name], - functions: List.keydelete(env.functions, module.name, 0) ++ [{ module.name, functions }], - macros: List.keydelete(env.macros, module.name, 0) ++ [{ module.name, macros }] } - end - - def add_alias(env, module_name, alias_name) do - module = get_module(env, module_name) - - %{ env | aliases: Enum.uniq(env.aliases ++ [{alias_name, module.name}]) } + %{ env | requires: env.requires ++ [module.name], + functions: List.keydelete(env.functions, module.name, 0) ++ [{ module.name, functions }], + macros: List.keydelete(env.macros, module.name, 0) ++ [{ module.name, macros }] } + end end def add_require(env, module_name) do - module = get_module(env, module_name) - - %{ env | requires: Enum.uniq(env.requires ++ [module.name]) } + case ElixirScript.Translator.State.is_module_loaded?(module_name) do + true -> + add_require_macro(env, module_name, []) + false -> + module = get_module(env, module_name) + %{ env | requires: Enum.uniq(env.requires ++ [module.name]) } + end end def add_require(env, module_name, alias_name) do - module = get_module(env, module_name) + case ElixirScript.Translator.State.is_module_loaded?(module_name) do + true -> + add_require_macro(env, module_name, [as: alias_name]) + false -> + module = get_module(env, module_name) + + %{ env | aliases: Enum.uniq(env.aliases ++ [{alias_name, module.name}]), + requires: Enum.uniq(env.requires ++ [module.name]) } + end - %{ env | aliases: Enum.uniq(env.aliases ++ [{alias_name, module.name}]), - requires: Enum.uniq(env.requires ++ [module.name]) } end def get_module_name(env, module_name) do @@ -188,4 +224,26 @@ defmodule ElixirScript.Translator.Env do end + def add_import_macro(elixirscript_env, module, opts) do + eval = """ + import #{inspect module}, #{inspect opts} + __ENV__ + """ + + do_macro(eval, elixirscript_env) + end + + def add_require_macro(elixirscript_env, module, opts) do + eval = """ + require #{inspect module}, #{inspect opts} + __ENV__ + """ + + do_macro(eval, elixirscript_env) + end + + def do_macro(eval, elixirscript_env) do + {env, _} = Code.eval_string(eval, [], elixirscript_env.env) + %{ elixirscript_env | env: env } + end end diff --git a/lib/elixir_script/translator/state.ex b/lib/elixir_script/translator/state.ex index edb889c1..c7c4b919 100644 --- a/lib/elixir_script/translator/state.ex +++ b/lib/elixir_script/translator/state.ex @@ -9,9 +9,9 @@ defmodule ElixirScript.Translator.State do @moduledoc false alias ElixirScript.Translator.Utils - def start_link(compiler_opts \\ []) do + def start_link(compiler_opts, loaded_modules) do Agent.start_link(fn -> - %{ compiler_opts: compiler_opts, modules: Map.new, std_lib_map: build_standard_lib_map(), added_modules: MapSet.new } + %{ compiler_opts: compiler_opts, modules: Map.new, std_lib_map: build_standard_lib_map(), added_modules: MapSet.new, loaded_modules: loaded_modules } end, name: __MODULE__) end @@ -26,7 +26,7 @@ defmodule ElixirScript.Translator.State do Agent.update(__MODULE__, fn state -> frozen_state = :erlang.binary_to_term(frozen_state) modules = Map.delete(frozen_state.modules, ElixirScript.Temp) - %{ state | modules: modules, std_lib_map: frozen_state.std_lib_map, added_modules: MapSet.new } + %{ state | modules: modules, std_lib_map: frozen_state.std_lib_map, added_modules: MapSet.new, loaded_modules: [] } end) end @@ -141,6 +141,17 @@ defmodule ElixirScript.Translator.State do end end + def is_module_loaded?(module) when is_atom(module) do + Agent.get(__MODULE__, fn(state) -> + module in state.loaded_modules + end) + end + + def is_module_loaded?({:__aliases__, _, _} = module) do + Utils.quoted_to_name(module) + |> is_module_loaded? + end + def get_module(module) when is_atom(module) do do_get_module(module) end diff --git a/test/translator/pattern_matching_test.exs b/test/translator/pattern_matching_test.exs index a1025aa2..7a9f0588 100644 --- a/test/translator/pattern_matching_test.exs +++ b/test/translator/pattern_matching_test.exs @@ -9,7 +9,7 @@ defmodule ElixirScript.Translator.PatternMatching.Test do @std_lib_state File.read!(File.cwd!() <> "/lib/elixir_script/translator/stdlib_state.bin") setup do - ElixirScript.Translator.State.start_link(%{env: ElixirScript.custom_env}) + ElixirScript.Translator.State.start_link(%{env: ElixirScript.custom_env}, []) ElixirScript.Translator.State.deserialize(@std_lib_state) # Returns extra metadata, it must be a dict @@ -18,7 +18,7 @@ defmodule ElixirScript.Translator.PatternMatching.Test do test "match wildcard" do params = [{:_, [], Test}] - result = PatternMatching.build_match(params, ElixirScript.Translator.Env.module_env(ElixirScript.Temp, "temp.ex") ) + result = PatternMatching.build_match(params, ElixirScript.Translator.Env.module_env(ElixirScript.Temp, "temp.ex", ElixirScript.custom_env) ) expected_result = { [PatternMatching.wildcard], [JS.identifier(:undefined)] } assert result == expected_result @@ -26,7 +26,7 @@ defmodule ElixirScript.Translator.PatternMatching.Test do test "match one identifier param" do params = [{:a, [], Test}] - result = PatternMatching.build_match(params, ElixirScript.Translator.Env.module_env(ElixirScript.Temp, "temp.ex") ) + result = PatternMatching.build_match(params, ElixirScript.Translator.Env.module_env(ElixirScript.Temp, "temp.ex", ElixirScript.custom_env) ) expected_result = {[PatternMatching.parameter], [JS.identifier("a")]} assert result == expected_result @@ -34,7 +34,7 @@ defmodule ElixirScript.Translator.PatternMatching.Test do test "match multiple identifier params" do params = [{:a, [], Test}, {:b, [], Test}, {:c, [], Test}] - result = PatternMatching.build_match(params, ElixirScript.Translator.Env.module_env(ElixirScript.Temp, "temp.ex") ) + result = PatternMatching.build_match(params, ElixirScript.Translator.Env.module_env(ElixirScript.Temp, "temp.ex", ElixirScript.custom_env) ) expected_result = { List.duplicate(PatternMatching.parameter, 3), [JS.identifier("a"), JS.identifier("b"), JS.identifier("c")] @@ -45,7 +45,7 @@ defmodule ElixirScript.Translator.PatternMatching.Test do test "match head and tail param" do params = [[{:|, [], [{:head, [], Elixir}, {:tail, [], Elixir}]}]] - result = PatternMatching.build_match(params, ElixirScript.Translator.Env.module_env(ElixirScript.Temp, "temp.ex") ) + result = PatternMatching.build_match(params, ElixirScript.Translator.Env.module_env(ElixirScript.Temp, "temp.ex", ElixirScript.custom_env) ) expected_result = { [PatternMatching.head_tail(PatternMatching.parameter, PatternMatching.parameter)], [JS.identifier("head"), JS.identifier("tail")] @@ -56,7 +56,7 @@ defmodule ElixirScript.Translator.PatternMatching.Test do test "match prefix param" do params = [{:<>, [context: Elixir, import: Elixir.Kernel], ["Bearer ", {:token, [], Elixir}]}] - result = PatternMatching.build_match(params, ElixirScript.Translator.Env.module_env(ElixirScript.Temp, "temp.ex") ) + result = PatternMatching.build_match(params, ElixirScript.Translator.Env.module_env(ElixirScript.Temp, "temp.ex", ElixirScript.custom_env) ) expected_result = { [PatternMatching.starts_with("Bearer ")], [JS.identifier("token")] @@ -67,7 +67,7 @@ defmodule ElixirScript.Translator.PatternMatching.Test do test "match list" do params = [[{:a, [], Elixir}, {:b, [], Elixir}, {:c, [], Elixir}]] - result = PatternMatching.build_match(params, ElixirScript.Translator.Env.module_env(ElixirScript.Temp, "temp.ex") ) + result = PatternMatching.build_match(params, ElixirScript.Translator.Env.module_env(ElixirScript.Temp, "temp.ex", ElixirScript.custom_env) ) expected_result = { [Primitive.make_list_no_translate(List.duplicate(PatternMatching.parameter, 3))], [JS.identifier("a"), JS.identifier("b"), JS.identifier("c")] @@ -78,7 +78,7 @@ defmodule ElixirScript.Translator.PatternMatching.Test do test "match list with a literal" do params = [[1, {:b, [], Elixir}, {:c, [], Elixir}]] - result = PatternMatching.build_match(params, ElixirScript.Translator.Env.module_env(ElixirScript.Temp, "temp.ex") ) + result = PatternMatching.build_match(params, ElixirScript.Translator.Env.module_env(ElixirScript.Temp, "temp.ex", ElixirScript.custom_env) ) expected_result = { [Primitive.make_list_no_translate([JS.literal(1), PatternMatching.parameter, PatternMatching.parameter])], [JS.identifier("b"), JS.identifier("c")] @@ -89,7 +89,7 @@ defmodule ElixirScript.Translator.PatternMatching.Test do test "match number" do params = [1] - result = PatternMatching.build_match(params, ElixirScript.Translator.Env.module_env(ElixirScript.Temp, "temp.ex") ) + result = PatternMatching.build_match(params, ElixirScript.Translator.Env.module_env(ElixirScript.Temp, "temp.ex", ElixirScript.custom_env) ) expected_result = { [JS.literal(1)], [] @@ -100,7 +100,7 @@ defmodule ElixirScript.Translator.PatternMatching.Test do test "match struct pattern" do params = [{:%, [], [{:__aliases__, [alias: false], [:Hello]}, {:%{}, [], []}]}] - result = PatternMatching.build_match(params, ElixirScript.Translator.Env.module_env(ElixirScript.Temp, "temp.ex") ) + result = PatternMatching.build_match(params, ElixirScript.Translator.Env.module_env(ElixirScript.Temp, "temp.ex", ElixirScript.custom_env) ) expected_result = { [PatternMatching.type(JS.identifier(:Hello), JS.object_expression([]))], [] @@ -111,10 +111,10 @@ defmodule ElixirScript.Translator.PatternMatching.Test do test "match struct pattern with property" do params = [{:%, [], [{:__aliases__, [alias: false], [:Hello]}, {:%{}, [], [key: 1]}]}] - result = PatternMatching.build_match(params, ElixirScript.Translator.Env.module_env(ElixirScript.Temp, "temp.ex") ) + result = PatternMatching.build_match(params, ElixirScript.Translator.Env.module_env(ElixirScript.Temp, "temp.ex", ElixirScript.custom_env) ) expected_result = { [PatternMatching.type(JS.identifier(:Hello), JS.object_expression([ - Map.make_property(Translator.translate!(:key, ElixirScript.Translator.Env.module_env(ElixirScript.Temp, "temp.ex") ), Translator.translate!(1, ElixirScript.Translator.Env.module_env(ElixirScript.Temp, "temp.ex") )) + Map.make_property(Translator.translate!(:key, ElixirScript.Translator.Env.module_env(ElixirScript.Temp, "temp.ex", ElixirScript.custom_env) ), Translator.translate!(1, ElixirScript.Translator.Env.module_env(ElixirScript.Temp, "temp.ex", ElixirScript.custom_env) )) ])) ], [] @@ -125,10 +125,10 @@ defmodule ElixirScript.Translator.PatternMatching.Test do test "match struct pattern with property param" do params = [{:%, [], [{:__aliases__, [alias: false], [:Hello]}, {:%{}, [], [key: {:key, [], Elixir }]}]}] - result = PatternMatching.build_match(params, ElixirScript.Translator.Env.module_env(ElixirScript.Temp, "temp.ex") ) + result = PatternMatching.build_match(params, ElixirScript.Translator.Env.module_env(ElixirScript.Temp, "temp.ex", ElixirScript.custom_env) ) expected_result = { [PatternMatching.type(JS.identifier(:Hello), JS.object_expression([ - Map.make_property(Translator.translate!(:key, ElixirScript.Translator.Env.module_env(ElixirScript.Temp, "temp.ex") ), PatternMatching.parameter) + Map.make_property(Translator.translate!(:key, ElixirScript.Translator.Env.module_env(ElixirScript.Temp, "temp.ex", ElixirScript.custom_env) ), PatternMatching.parameter) ])) ], [JS.identifier("key")] @@ -139,7 +139,7 @@ defmodule ElixirScript.Translator.PatternMatching.Test do test "capture parameter when assigning it" do params = [{:=, [], [1, {:a, [], Elixir}]}] - result = PatternMatching.build_match(params, ElixirScript.Translator.Env.module_env(ElixirScript.Temp, "temp.ex") ) + result = PatternMatching.build_match(params, ElixirScript.Translator.Env.module_env(ElixirScript.Temp, "temp.ex", ElixirScript.custom_env) ) expected_result = { [PatternMatching.capture(JS.literal(1))], [JS.identifier("a")] @@ -149,7 +149,7 @@ defmodule ElixirScript.Translator.PatternMatching.Test do params = [{:=, [], [{:a, [], Elixir}, 1]}] - result = PatternMatching.build_match(params, ElixirScript.Translator.Env.module_env(ElixirScript.Temp, "temp.ex") ) + result = PatternMatching.build_match(params, ElixirScript.Translator.Env.module_env(ElixirScript.Temp, "temp.ex", ElixirScript.custom_env) ) expected_result = { [PatternMatching.capture(JS.literal(1))], [JS.identifier("a")] @@ -159,7 +159,7 @@ defmodule ElixirScript.Translator.PatternMatching.Test do params = [{:=, [], [{:%, [], [{:__aliases__, [alias: false], [:AStruct]}, {:%{}, [], []}]}, {:a, [], ElixirScript.Translator.Function.Test}]}] - result = PatternMatching.build_match(params, ElixirScript.Translator.Env.module_env(ElixirScript.Temp, "temp.ex") ) + result = PatternMatching.build_match(params, ElixirScript.Translator.Env.module_env(ElixirScript.Temp, "temp.ex", ElixirScript.custom_env) ) expected_result = { [PatternMatching.capture(PatternMatching.type(JS.identifier(:AStruct), JS.object_expression([])))], [JS.identifier("a")] @@ -170,7 +170,7 @@ defmodule ElixirScript.Translator.PatternMatching.Test do test "match and assign list" do params = [{:=, [], [[{:a, [], Elixir}, {:b, [], Elixir}, {:c, [], Elixir}], {:d, [], Elixir}]}] - result = PatternMatching.build_match(params, ElixirScript.Translator.Env.module_env(ElixirScript.Temp, "temp.ex") ) + result = PatternMatching.build_match(params, ElixirScript.Translator.Env.module_env(ElixirScript.Temp, "temp.ex", ElixirScript.custom_env) ) expected_result = { [PatternMatching.capture(Primitive.make_list_no_translate([PatternMatching.parameter, PatternMatching.parameter, PatternMatching.parameter]))], [JS.identifier("a"), JS.identifier("b"), JS.identifier("c"), JS.identifier("d")] @@ -181,7 +181,7 @@ defmodule ElixirScript.Translator.PatternMatching.Test do test "match on tuple" do params = [{:{}, [], [1, {:b, [], Elixir}, 3]}] - result = PatternMatching.build_match(params, ElixirScript.Translator.Env.module_env(ElixirScript.Temp, "temp.ex") ) + result = PatternMatching.build_match(params, ElixirScript.Translator.Env.module_env(ElixirScript.Temp, "temp.ex", ElixirScript.custom_env) ) expected_result = { [PatternMatching.type(Primitive.tuple_class, JS.object_expression([JS.property( JS.identifier("values"), @@ -193,7 +193,7 @@ defmodule ElixirScript.Translator.PatternMatching.Test do assert result == expected_result params = [{1, {:b, [], Elixir}}] - result = PatternMatching.build_match(params, ElixirScript.Translator.Env.module_env(ElixirScript.Temp, "temp.ex") ) + result = PatternMatching.build_match(params, ElixirScript.Translator.Env.module_env(ElixirScript.Temp, "temp.ex", ElixirScript.custom_env) ) expected_result = { [PatternMatching.type(Primitive.tuple_class, JS.object_expression([JS.property( JS.identifier("values"), @@ -207,11 +207,11 @@ defmodule ElixirScript.Translator.PatternMatching.Test do test "match on map" do params = [{:%{}, [], [which: 13]}] - result = PatternMatching.build_match(params, ElixirScript.Translator.Env.module_env(ElixirScript.Temp, "temp.ex") ) + result = PatternMatching.build_match(params, ElixirScript.Translator.Env.module_env(ElixirScript.Temp, "temp.ex", ElixirScript.custom_env) ) expected_result = { [JS.object_expression([ - Map.make_property(Translator.translate!(:which, ElixirScript.Translator.Env.module_env(ElixirScript.Temp, "temp.ex") ), JS.literal(13)) + Map.make_property(Translator.translate!(:which, ElixirScript.Translator.Env.module_env(ElixirScript.Temp, "temp.ex", ElixirScript.custom_env) ), JS.literal(13)) ])], [] } @@ -222,7 +222,7 @@ defmodule ElixirScript.Translator.PatternMatching.Test do test "match on bound value" do params = [{:^, [], [{:a, [], Elixir}]}] - result = PatternMatching.build_match(params, ElixirScript.Translator.Env.module_env(ElixirScript.Temp, "temp.ex") ) + result = PatternMatching.build_match(params, ElixirScript.Translator.Env.module_env(ElixirScript.Temp, "temp.ex", ElixirScript.custom_env) ) expected_result = { [PatternMatching.bound(JS.identifier("a"))], From 1be86bf9dd23ef399474dd21f39334be65d84f23 Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Wed, 6 Apr 2016 21:24:15 -0500 Subject: [PATCH 216/860] Now using .ex and .exs for macros and .exjs for elixirscript code --- lib/elixir_script.ex | 31 +++++++++++++++++++++------ lib/elixir_script/translator.ex | 12 ++++++----- lib/elixir_script/translator/env.ex | 5 ++--- lib/elixir_script/translator/state.ex | 4 ++-- 4 files changed, 36 insertions(+), 16 deletions(-) diff --git a/lib/elixir_script.ex b/lib/elixir_script.ex index 17c3d90c..de9e3dc3 100644 --- a/lib/elixir_script.ex +++ b/lib/elixir_script.ex @@ -62,7 +62,7 @@ defmodule ElixirScript do """ @spec compile_quoted(Macro.t, Map.t) :: [binary | {binary, binary} | :ok] def compile_quoted(quoted, opts \\ %{}) do - { code, _ } = do_compile(opts, [quoted], get_stdlib_state) + { code, _ } = do_compile(opts, [quoted], get_stdlib_state, []) Output.out(quoted, code, build_compiler_options(opts)) end @@ -71,7 +71,9 @@ defmodule ElixirScript do """ @spec compile_path(binary, Map.t) :: [binary | {binary, binary} | :ok] def compile_path(path, opts \\ %{}) do - expanded_path = Path.wildcard(path) + + {expanded_path, loaded_modules} = process_path(path) + opts = build_compiler_options(opts) compiler_cache = get_compiler_cache(path, opts) @@ -83,13 +85,30 @@ defmodule ElixirScript do code = Enum.map(changed_files, &file_to_quoted/1) - { code, new_state } = do_compile(opts, code, compiler_cache.state) + { code, new_state } = do_compile(opts, code, compiler_cache.state, loaded_modules) compiler_cache = %{compiler_cache | input_files: new_file_stats, state: new_state } Cache.write(path, compiler_cache) Output.out(path, code, opts) end + defp process_path(path) do + path = Path.join(path, "**/*.{ex,exs,exjs}") |> Path.wildcard + {exjs, ex} = Enum.partition(path, fn(x) -> + case Path.extname(x) do + ext when ext in [".ex", ".exs"] -> + false + _ -> + true + end + end) + + ex = Enum.flat_map(ex, fn(x) -> Code.load_file(x) end) + |> Enum.map(fn({module, _}) -> module end) + + {exjs, ex} + end + defp get_stdlib_state() do case @stdlib_state do {:ok, data} -> @@ -160,11 +179,11 @@ defmodule ElixirScript do Output.out(libs_path, code, compiler_opts) end - defp do_compile(opts, quoted_code_list, state) do + defp do_compile(opts, quoted_code_list, state, loaded_modules) do compiler_opts = build_compiler_options(opts) - ElixirScript.Translator.State.start_link(compiler_opts, []) - ElixirScript.Translator.State.deserialize(state) + ElixirScript.Translator.State.start_link(compiler_opts, loaded_modules) + ElixirScript.Translator.State.deserialize(state, loaded_modules) quoted_code_list |> Enum.map(&update_quoted(&1)) diff --git a/lib/elixir_script/translator.ex b/lib/elixir_script/translator.ex index 81b75388..884d9026 100644 --- a/lib/elixir_script/translator.ex +++ b/lib/elixir_script/translator.ex @@ -222,7 +222,7 @@ defmodule ElixirScript.Translator do end defp do_translate({:., _, [module_name, function_name]} = ast, env) do - expanded_ast = Macro.expand(ast, ElixirScript.Translator.State.get().compiler_opts.env) + expanded_ast = Macro.expand(ast, env.env) if expanded_ast == ast do module_name = create_module_name(module_name, env) @@ -233,7 +233,7 @@ defmodule ElixirScript.Translator do end defp do_translate({{:., _, [module_name, function_name]}, _, [] } = ast, env) do - expanded_ast = Macro.expand(ast, ElixirScript.Translator.State.get().compiler_opts.env) + expanded_ast = Macro.expand(ast, env.env) if expanded_ast == ast do module_name = create_module_name(module_name, env) @@ -244,7 +244,7 @@ defmodule ElixirScript.Translator do end defp do_translate({{:., _, [{:__aliases__, _, _} = module_name]}, _, params} = ast, env) do - expanded_ast = Macro.expand(ast, ElixirScript.Translator.State.get().compiler_opts.env) + expanded_ast = Macro.expand(ast, env.env) if expanded_ast == ast do module_name = create_module_name(module_name, env) @@ -263,7 +263,7 @@ defmodule ElixirScript.Translator do end defp do_translate({{:., _, [module_name, function_name]}, _, params } = ast, env) do - expanded_ast = Macro.expand(ast, ElixirScript.Translator.State.get().compiler_opts.env) + expanded_ast = Macro.expand(ast, env.env) if expanded_ast == ast do module_name = create_module_name(module_name, env) @@ -349,6 +349,8 @@ defmodule ElixirScript.Translator do defp do_translate({:import, _, [{:__aliases__, _, _} = module_name]}, env) do + module_name = Utils.quoted_to_name(module_name) + env = ElixirScript.Translator.Env.add_import(env, module_name) { %ElixirScript.Translator.Empty{}, env } end @@ -528,7 +530,7 @@ defmodule ElixirScript.Translator do defp do_translate({name, _, params} = ast, env) when is_list(params) do - expanded_ast = Macro.expand(ast, ElixirScript.Translator.State.get().compiler_opts.env) + expanded_ast = Macro.expand(ast, env.env) if expanded_ast == ast do name_arity = {name, length(params)} diff --git a/lib/elixir_script/translator/env.ex b/lib/elixir_script/translator/env.ex index e888ccac..ef2decf6 100644 --- a/lib/elixir_script/translator/env.ex +++ b/lib/elixir_script/translator/env.ex @@ -85,8 +85,7 @@ defmodule ElixirScript.Translator.Env do end defp get_module(env, module_name) do - module = get_module_name(env, module_name) |> - ElixirScript.Translator.State.get_module + module = get_module_name(env, module_name) |> ElixirScript.Translator.State.get_module unless module do module_name = case module_name do @@ -100,7 +99,7 @@ defmodule ElixirScript.Translator.Env do module_name end - raise "Module #{module_name} not found" + raise "Module #{inspect module_name} not found" end ElixirScript.Translator.State.add_module_reference(env.module, module.name) diff --git a/lib/elixir_script/translator/state.ex b/lib/elixir_script/translator/state.ex index c7c4b919..37fea445 100644 --- a/lib/elixir_script/translator/state.ex +++ b/lib/elixir_script/translator/state.ex @@ -22,11 +22,11 @@ defmodule ElixirScript.Translator.State do end) end - def deserialize(frozen_state) do + def deserialize(frozen_state, loaded_modules \\ []) do Agent.update(__MODULE__, fn state -> frozen_state = :erlang.binary_to_term(frozen_state) modules = Map.delete(frozen_state.modules, ElixirScript.Temp) - %{ state | modules: modules, std_lib_map: frozen_state.std_lib_map, added_modules: MapSet.new, loaded_modules: [] } + %{ state | modules: modules, std_lib_map: frozen_state.std_lib_map, added_modules: MapSet.new, loaded_modules: loaded_modules } end) end From f05264c23d1d6d88af4a831cb5776e4978cb0d0b Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Wed, 6 Apr 2016 21:39:53 -0500 Subject: [PATCH 217/860] Updated docs. Updated compile_path to not process path if just a file --- CHANGELOG.md | 7 +++++++ GettingStarted.md | 42 ++++++++---------------------------------- lib/elixir_script.ex | 7 ++++++- mix.exs | 2 +- 4 files changed, 22 insertions(+), 36 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 38376a0c..e8ebf76a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,10 @@ +# v0.18.0-dev +* Enhancements + * Better support for macros. Macros should be defined in .ex or .exs files. ElixirScript code should be in .exjs files + +* Breaking + * The above functionality will cause either compiler errors or no output. Please change extensions of ElixirScript code to .exjs + # v0.17.0 * Enhancements * Incremental Compilation: diff --git a/GettingStarted.md b/GettingStarted.md index aef64cd7..a4d0cc88 100644 --- a/GettingStarted.md +++ b/GettingStarted.md @@ -60,6 +60,8 @@ The intent of this guide is to get you started with ElixirScript. It will give y Symbol.for('atom') ``` + **NOTE**: ElixirScript files must have the extension, `.exjs` + What you will have noticed by now is that it has output everything we've done so far to the terminal. What about if we want to place the output to a path? The next example takes a file as input and outputs the result in another directory. ```bash @@ -71,7 +73,7 @@ The intent of this guide is to get you started with ElixirScript. It will give y wildcards are also accepted: ```bash - $ elixirscript "src/**/*.exjs" -o "dist" + $ elixirscript "src" -o "dist" ``` The last option we will show is the root option. This option is for defining a root path for the import statements. By default your import statement will not have anything prepended to it. For example, the elixir import will look like this: @@ -83,7 +85,7 @@ The intent of this guide is to get you started with ElixirScript. It will give y If we wanted to prepend "js" to the root, we can like this: ``` - $ elixirscript "example.ex" -o "dist" -r "js" + $ elixirscript "example.exjs" -o "dist" -r "js" ``` Now the import will look like this: @@ -114,7 +116,7 @@ The intent of this guide is to get you started with ElixirScript. It will give y * Step 3: Use ```bash - $ mix elixirscript "example.ex" -o "dist" -r "js" + $ mix elixirscript "example.exjs" -o "dist" -r "js" ``` What you will notice is that the parameters are exactly the same as the escript. @@ -143,38 +145,10 @@ The intent of this guide is to get you started with ElixirScript. It will give y The is also compile_path/2 and compile_quoted/2. Each of the functions take an options keyword list. - * `:root` - a binary path prepended to the path of the standard lib imports if needed - * `:env` - a Macro.env struct to use. This is most useful when using macros. Make sure that the given env has the macros required. Defaults to `__ENV__`. - - You may notice the mention of macros. Using the module in your code allows you to use macros. As long as you pass in an environment with the macros loaded. By default, it uses the current environment. - - For example, if I have a module with a macro in it - - ```elixir - defmodule ElixirScript.Math do - defmacro squared(x) do - quote do - unquote(x) * unquote(x) - end - end - end - ``` - - If I create a custom env I can pass it to the compile functions: - - ```elixir - def make_custom_env do - require Logger - require ElixirScript.Math - - __ENV__ - end - - ElixirScript.compile("ElixirScript.Math.squared(2)", [env: make_custom_env]) - - #Should return ["2 * 2"] - ``` +### Macros +Macros must be defined in either a `.ex` or `.exs` file. These will be loaded at compile time and +whenever an import or require expression is found, if the module specified is loaded, it will use it to expand macros within the lexical scope ### Appendix diff --git a/lib/elixir_script.ex b/lib/elixir_script.ex index de9e3dc3..351c7fdf 100644 --- a/lib/elixir_script.ex +++ b/lib/elixir_script.ex @@ -72,7 +72,12 @@ defmodule ElixirScript do @spec compile_path(binary, Map.t) :: [binary | {binary, binary} | :ok] def compile_path(path, opts \\ %{}) do - {expanded_path, loaded_modules} = process_path(path) + {expanded_path, loaded_modules} = case File.dir?(path) do + true -> + process_path(path) + false -> + {[path], []} + end opts = build_compiler_options(opts) diff --git a/mix.exs b/mix.exs index 1cd38977..bd9388b0 100644 --- a/mix.exs +++ b/mix.exs @@ -4,7 +4,7 @@ defmodule ElixirScript.Mixfile do def project do [ app: :elixir_script, - version: "0.17.0", + version: "0.18.0-dev", elixir: "~> 1.0", escript: escript_config, deps: deps, From 91bf3cc66f3e52872180da3dc1d22df8cb1cfd46 Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Thu, 7 Apr 2016 07:28:55 -0500 Subject: [PATCH 218/860] Using Kernel.ParallelRequire.files to load in files for macros now --- lib/elixir_script.ex | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/lib/elixir_script.ex b/lib/elixir_script.ex index 351c7fdf..f7571d26 100644 --- a/lib/elixir_script.ex +++ b/lib/elixir_script.ex @@ -108,9 +108,7 @@ defmodule ElixirScript do end end) - ex = Enum.flat_map(ex, fn(x) -> Code.load_file(x) end) - |> Enum.map(fn({module, _}) -> module end) - + ex = Kernel.ParallelRequire.files(ex) {exjs, ex} end From 03e14c0c355d0c184eeaf6ed606fc2d87ab404dd Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Thu, 7 Apr 2016 09:11:20 -0500 Subject: [PATCH 219/860] Now allowing for imports and requires for elixirscript modules and elixir modules with the same module name --- lib/elixir_script/translator/env.ex | 167 ++++++++++++++++++---------- 1 file changed, 109 insertions(+), 58 deletions(-) diff --git a/lib/elixir_script/translator/env.ex b/lib/elixir_script/translator/env.ex index ef2decf6..50fb6093 100644 --- a/lib/elixir_script/translator/env.ex +++ b/lib/elixir_script/translator/env.ex @@ -106,57 +106,86 @@ defmodule ElixirScript.Translator.Env do module end + defp has_module?(env, module_name) do + try do + get_module(env, module_name) + true + rescue + _ -> + false + end + end + def add_alias(env, module_name, alias_name) do module = get_module(env, module_name) %{ env | aliases: Enum.uniq(env.aliases ++ [{alias_name, module.name}]) } end def add_import(env, module_name) do - case ElixirScript.Translator.State.is_module_loaded?(module_name) do - true -> - add_import_macro(env, module_name, []) - false -> - module = get_module(env, module_name) + check_for_module_existence(env, module_name) + + if ElixirScript.Translator.State.is_module_loaded?(module_name) do + env = add_import_macro(env, module_name, []) + end + + if has_module?(env, module_name) do + module = get_module(env, module_name) + + env = %{ env | requires: Enum.uniq(env.requires ++ [module.name]), + functions: env.functions ++ [{ module.name, module.functions }], + macros: env.macros ++ [{ module.name, module.macros }] } - %{ env | requires: Enum.uniq(env.requires ++ [module.name]), - functions: env.functions ++ [{ module.name, module.functions }], - macros: env.macros ++ [{ module.name, module.macros }] } end + + env end def add_import(env, module_name, [only: :functions]) do - case ElixirScript.Translator.State.is_module_loaded?(module_name) do - true -> - add_import_macro(env, module_name, [only: :functions]) - false -> - module = get_module(env, module_name) + check_for_module_existence(env, module_name) - %{ env | functions: List.keydelete(env.functions, module_name, 0) ++ [{ module.name, module.functions }], - macros: List.keydelete(env.macros, module.name, 0), - requires: Enum.uniq(env.requires ++ [module.name]) } + if ElixirScript.Translator.State.is_module_loaded?(module_name) do + env = add_import_macro(env, module_name, [only: :functions]) end + + if has_module?(env, module_name) do + module = get_module(env, module_name) + + env = %{ env | functions: List.keydelete(env.functions, module_name, 0) ++ [{ module.name, module.functions }], + macros: List.keydelete(env.macros, module.name, 0), + requires: Enum.uniq(env.requires ++ [module.name]) } + + end + + env end def add_import(env, module_name, [only: :macros]) do - case ElixirScript.Translator.State.is_module_loaded?(module_name) do - true -> - add_import_macro(env, module_name, [only: :macros]) - false -> - module = get_module(env, module_name) + check_for_module_existence(env, module_name) - %{ env | macros: List.keydelete(env.macros, module_name, 0) ++ [{ module.name, module.macros }], - functions: List.keydelete(env.functions, module.name, 0), - requires: Enum.uniq(env.requires ++ [module.name]) } + if ElixirScript.Translator.State.is_module_loaded?(module_name) do + env = add_import_macro(env, module_name, [only: :macros]) end + + if has_module?(env, module_name) do + module = get_module(env, module_name) + + env = %{ env | macros: List.keydelete(env.macros, module_name, 0) ++ [{ module.name, module.macros }], + functions: List.keydelete(env.functions, module.name, 0), + requires: Enum.uniq(env.requires ++ [module.name]) } + end + + env end def add_import(env, module_name, [only: only]) do - case ElixirScript.Translator.State.is_module_loaded?(module_name) do - true -> - add_import_macro(env, module_name, [only: only]) - false -> - module = get_module(env, module_name) + check_for_module_existence(env, module_name) + + if ElixirScript.Translator.State.is_module_loaded?(module_name) do + env = add_import_macro(env, module_name, [only: only]) + end + if has_module?(env, module_name) do + module = get_module(env, module_name) macros = Enum.filter(module.macros, fn(mac) -> mac in only end) @@ -164,52 +193,67 @@ defmodule ElixirScript.Translator.Env do func in only end) - %{ env | requires: Enum.uniq(env.requires ++ [module.name]), + env = %{ env | requires: Enum.uniq(env.requires ++ [module.name]), functions: List.keydelete(env.functions, module.name, 0) ++ [{ module.name, functions }], macros: List.keydelete(env.macros, module.name, 0) ++ [{ module.name, macros }] } end + + env end def add_import(env, module_name, [except: except]) do - case ElixirScript.Translator.State.is_module_loaded?(module_name) do - true -> - add_import_macro(env, module_name, [except: except]) - false -> - module = get_module(env, module_name) + check_for_module_existence(env, module_name) - {_, current_functions } = List.keyfind(env.functions, module.name, 0, { module.name, module.functions }) - {_, current_macros } = List.keyfind(env.macros, module.name, 0, { module.name, module.macros }) + if ElixirScript.Translator.State.is_module_loaded?(module_name) do + env = add_import_macro(env, module_name, [except: except]) + end - macros = Enum.filter(current_macros, fn(mac) -> not(mac in except) end) - functions = Enum.filter(current_functions, fn(func) -> not(func in except) end) + if has_module?(env, module_name) do + module = get_module(env, module_name) + {_, current_functions } = List.keyfind(env.functions, module.name, 0, { module.name, module.functions }) + {_, current_macros } = List.keyfind(env.macros, module.name, 0, { module.name, module.macros }) - %{ env | requires: env.requires ++ [module.name], - functions: List.keydelete(env.functions, module.name, 0) ++ [{ module.name, functions }], - macros: List.keydelete(env.macros, module.name, 0) ++ [{ module.name, macros }] } + macros = Enum.filter(current_macros, fn(mac) -> not(mac in except) end) + functions = Enum.filter(current_functions, fn(func) -> not(func in except) end) + + env = %{ env | requires: env.requires ++ [module.name], + functions: List.keydelete(env.functions, module.name, 0) ++ [{ module.name, functions }], + macros: List.keydelete(env.macros, module.name, 0) ++ [{ module.name, macros }] } end + + env end def add_require(env, module_name) do - case ElixirScript.Translator.State.is_module_loaded?(module_name) do - true -> - add_require_macro(env, module_name, []) - false -> - module = get_module(env, module_name) - %{ env | requires: Enum.uniq(env.requires ++ [module.name]) } + check_for_module_existence(env, module_name) + + if ElixirScript.Translator.State.is_module_loaded?(module_name) do + env = add_require_macro(env, module_name, []) + end + + if has_module?(env, module_name) do + module = get_module(env, module_name) + env = %{ env | requires: Enum.uniq(env.requires ++ [module.name]) } end + + env end def add_require(env, module_name, alias_name) do - case ElixirScript.Translator.State.is_module_loaded?(module_name) do - true -> - add_require_macro(env, module_name, [as: alias_name]) - false -> - module = get_module(env, module_name) + check_for_module_existence(env, module_name) + + if ElixirScript.Translator.State.is_module_loaded?(module_name) do + env = add_require_macro(env, module_name, [as: alias_name]) + end - %{ env | aliases: Enum.uniq(env.aliases ++ [{alias_name, module.name}]), - requires: Enum.uniq(env.requires ++ [module.name]) } + if has_module?(env, module_name) do + module = get_module(env, module_name) + env = %{ env | aliases: Enum.uniq(env.aliases ++ [{alias_name, module.name}]), + requires: Enum.uniq(env.requires ++ [module.name]) } end + env + end def get_module_name(env, module_name) do @@ -223,7 +267,14 @@ defmodule ElixirScript.Translator.Env do end - def add_import_macro(elixirscript_env, module, opts) do + defp check_for_module_existence(env, module_name) do + if !ElixirScript.Translator.State.is_module_loaded?(module_name) and !has_module?(env, module_name) do + raise "Module #{inspect module_name} not found" + end + end + + + defp add_import_macro(elixirscript_env, module, opts) do eval = """ import #{inspect module}, #{inspect opts} __ENV__ @@ -232,7 +283,7 @@ defmodule ElixirScript.Translator.Env do do_macro(eval, elixirscript_env) end - def add_require_macro(elixirscript_env, module, opts) do + defp add_require_macro(elixirscript_env, module, opts) do eval = """ require #{inspect module}, #{inspect opts} __ENV__ @@ -241,7 +292,7 @@ defmodule ElixirScript.Translator.Env do do_macro(eval, elixirscript_env) end - def do_macro(eval, elixirscript_env) do + defp do_macro(eval, elixirscript_env) do {env, _} = Code.eval_string(eval, [], elixirscript_env.env) %{ elixirscript_env | env: env } end From 4bf4ffedbfa941ed89a79a53a89d9ca59d5e8b59 Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Thu, 7 Apr 2016 09:53:17 -0500 Subject: [PATCH 220/860] Removed macros from module struct. Updated env to make sure macros exists for only and except imports --- lib/elixir_script/prelude/module.ex | 1 - lib/elixir_script/translator/env.ex | 55 +++++-------------- .../translator/module_collector.ex | 32 +++-------- 3 files changed, 21 insertions(+), 67 deletions(-) diff --git a/lib/elixir_script/prelude/module.ex b/lib/elixir_script/prelude/module.ex index 0af8805c..a78df8ca 100644 --- a/lib/elixir_script/prelude/module.ex +++ b/lib/elixir_script/prelude/module.ex @@ -3,7 +3,6 @@ defmodule ElixirScript.Module do defstruct name: nil, functions: Keyword.new, private_functions: Keyword.new, - macros: Keyword.new, private_macros: Keyword.new, body: nil, js_imports: [], module_refs: [], type: :module, impls: HashDict.new, impl_type: nil diff --git a/lib/elixir_script/translator/env.ex b/lib/elixir_script/translator/env.ex index 50fb6093..aa5e7d67 100644 --- a/lib/elixir_script/translator/env.ex +++ b/lib/elixir_script/translator/env.ex @@ -6,7 +6,6 @@ defmodule ElixirScript.Translator.Env do env = %ElixirScript.Macro.Env { module: ElixirScript.Temp, file: filename, requires: [], functions: [], - macros: [], env: env } @@ -19,7 +18,6 @@ defmodule ElixirScript.Translator.Env do env = %ElixirScript.Macro.Env { module: module_name, file: filename, requires: [], functions: [{ module.name, module.functions}], - macros: [{ module.name, module.macros}], env: env } @@ -132,8 +130,7 @@ defmodule ElixirScript.Translator.Env do module = get_module(env, module_name) env = %{ env | requires: Enum.uniq(env.requires ++ [module.name]), - functions: env.functions ++ [{ module.name, module.functions }], - macros: env.macros ++ [{ module.name, module.macros }] } + functions: env.functions ++ [{ module.name, module.functions }] } end @@ -141,61 +138,38 @@ defmodule ElixirScript.Translator.Env do end def add_import(env, module_name, [only: :functions]) do - check_for_module_existence(env, module_name) - - if ElixirScript.Translator.State.is_module_loaded?(module_name) do - env = add_import_macro(env, module_name, [only: :functions]) - end - - if has_module?(env, module_name) do module = get_module(env, module_name) - env = %{ env | functions: List.keydelete(env.functions, module_name, 0) ++ [{ module.name, module.functions }], - macros: List.keydelete(env.macros, module.name, 0), + %{ env | functions: List.keydelete(env.functions, module_name, 0) ++ [{ module.name, module.functions }], requires: Enum.uniq(env.requires ++ [module.name]) } - - end - - env end def add_import(env, module_name, [only: :macros]) do - check_for_module_existence(env, module_name) - - if ElixirScript.Translator.State.is_module_loaded?(module_name) do - env = add_import_macro(env, module_name, [only: :macros]) - end - - if has_module?(env, module_name) do - module = get_module(env, module_name) - - env = %{ env | macros: List.keydelete(env.macros, module_name, 0) ++ [{ module.name, module.macros }], - functions: List.keydelete(env.functions, module.name, 0), - requires: Enum.uniq(env.requires ++ [module.name]) } + if !ElixirScript.Translator.State.is_module_loaded?(module_name) do + raise "Module #{inspect module_name} not found" end - env + add_import_macro(env, module_name, [only: :macros]) end def add_import(env, module_name, [only: only]) do check_for_module_existence(env, module_name) if ElixirScript.Translator.State.is_module_loaded?(module_name) do - env = add_import_macro(env, module_name, [only: only]) + list = module_name.__info__(:macros) + list = Enum.filter(list, fn(mac) -> mac in only end) + env = add_import_macro(env, module_name, [only: list]) end if has_module?(env, module_name) do module = get_module(env, module_name) - macros = Enum.filter(module.macros, fn(mac) -> - mac in only - end) + functions = Enum.filter(module.functions, fn(func) -> func in only end) env = %{ env | requires: Enum.uniq(env.requires ++ [module.name]), - functions: List.keydelete(env.functions, module.name, 0) ++ [{ module.name, functions }], - macros: List.keydelete(env.macros, module.name, 0) ++ [{ module.name, macros }] } + functions: List.keydelete(env.functions, module.name, 0) ++ [{ module.name, functions }] } end env @@ -205,20 +179,19 @@ defmodule ElixirScript.Translator.Env do check_for_module_existence(env, module_name) if ElixirScript.Translator.State.is_module_loaded?(module_name) do - env = add_import_macro(env, module_name, [except: except]) + list = module_name.__info__(:macros) + list = Enum.filter(list, fn(mac) -> mac in except end) + env = add_import_macro(env, module_name, [except: list]) end if has_module?(env, module_name) do module = get_module(env, module_name) {_, current_functions } = List.keyfind(env.functions, module.name, 0, { module.name, module.functions }) - {_, current_macros } = List.keyfind(env.macros, module.name, 0, { module.name, module.macros }) - macros = Enum.filter(current_macros, fn(mac) -> not(mac in except) end) functions = Enum.filter(current_functions, fn(func) -> not(func in except) end) env = %{ env | requires: env.requires ++ [module.name], - functions: List.keydelete(env.functions, module.name, 0) ++ [{ module.name, functions }], - macros: List.keydelete(env.macros, module.name, 0) ++ [{ module.name, macros }] } + functions: List.keydelete(env.functions, module.name, 0) ++ [{ module.name, functions }] } end env diff --git a/lib/elixir_script/translator/module_collector.ex b/lib/elixir_script/translator/module_collector.ex index 883c0bf7..301b11e9 100644 --- a/lib/elixir_script/translator/module_collector.ex +++ b/lib/elixir_script/translator/module_collector.ex @@ -40,12 +40,12 @@ defmodule ElixirScript.Translator.ModuleCollector do end def do_process_modules({:defprotocol, _, [{:__aliases__, _, _} = the_alias, [do: {:__block__, _, _} = block]]}) do - %{def: functions, defp: _, defmacro: _, defmacrop: _ } = get_functions_from_module(block) + %{def: functions, defp: _ } = get_functions_from_module(block) ElixirScript.Translator.State.add_protocol(Utils.quoted_to_name(the_alias), functions) end def do_process_modules({:defprotocol, _, [{:__aliases__, _, _} = the_alias, [do: spec]]}) do - %{def: functions, defp: _, defmacro: _, defmacrop: _ } = get_functions_from_module({:__block__, [], [spec]}) + %{def: functions, defp: _ } = get_functions_from_module({:__block__, [], [spec]}) ElixirScript.Translator.State.add_protocol(Utils.quoted_to_name(the_alias), functions) end @@ -115,13 +115,11 @@ defmodule ElixirScript.Translator.ModuleCollector do body end - %{def: functions, defp: private_functions, defmacro: macros, defmacrop: private_macros } = get_functions_from_module(body) + %{def: functions, defp: private_functions } = get_functions_from_module(body) js_imports = get_js_imports_from_module(body) %ElixirScript.Module{ name: Utils.quoted_to_name({:__aliases__, [], name}) , body: body, - functions: functions, private_functions: private_functions, - macros: macros, private_macros: private_macros, - js_imports: js_imports } + functions: functions, private_functions: private_functions, js_imports: js_imports } end defp make_inner_module_aliases(name, body) do @@ -148,7 +146,7 @@ defmodule ElixirScript.Translator.ModuleCollector do end defp add_module_to_state(name, inner_module_name, inner_module_body) do - %{def: functions, defp: private_functions, defmacro: macros, defmacrop: private_macros } = get_functions_from_module(inner_module_body) + %{ def: functions, defp: private_functions } = get_functions_from_module(inner_module_body) js_imports = get_js_imports_from_module(inner_module_body) inner_alias = { :alias, [], [{:__aliases__, [alias: false], name ++ inner_module_name}] } @@ -160,7 +158,6 @@ defmodule ElixirScript.Translator.ModuleCollector do mod = %ElixirScript.Module{ name: module_name, body: inner_module_body, functions: functions, private_functions: private_functions, - macros: macros, private_macros: private_macros, js_imports: js_imports } State.add_module(mod) @@ -170,7 +167,7 @@ defmodule ElixirScript.Translator.ModuleCollector do defp get_functions_from_module({:__block__, _, list}) do - Enum.reduce(list, %{ def: Keyword.new, defp: Keyword.new, defmacro: Keyword.new, defmacrop: Keyword.new }, fn + Enum.reduce(list, %{ def: Keyword.new, defp: Keyword.new }, fn ({type, _, [{:when, _, [{name, _, params} | _guards] }, _] }, state) when type in [:def, :defp] and is_atom(params) -> arity = 0 @@ -186,25 +183,10 @@ defmodule ElixirScript.Translator.ModuleCollector do add_function_to_map(state, type, name, arity) - ({type, _, [{name, _, params}, _]}, state) when type in [:def, :defp] -> arity = if is_nil(params), do: 0, else: length(params) add_function_to_map(state, type, name, arity) - ({type, _, [{:when, _, [{name, _, params} | _guards] }, [do: _body]] }, state) when type in [:defmacro, :defmacrop] -> - arity = length(params) - - add_function_to_map(state, type, name, arity) - - ({type, _, [{name, _, nil}, [do: _body]]}, state) when type in [:defmacro, :defmacrop] -> - add_function_to_map(state, type, name, 0) - - - ({type, _, [{name, _, params}, [do: _body]]}, state) when type in [:defmacro, :defmacrop] -> - arity = length(params) - - add_function_to_map(state, type, name, arity) - ({type, _, [{name, _, params}]}, state) when is_atom(params) and type in [:def, :defp] -> arity = 0 add_function_to_map(state, type, name, arity) @@ -220,7 +202,7 @@ defmodule ElixirScript.Translator.ModuleCollector do end defp get_functions_from_module(_) do - %{ def: Keyword.new, defp: Keyword.new, defmacro: Keyword.new, defmacrop: Keyword.new } + %{ def: Keyword.new, defp: Keyword.new } end defp add_function_to_map(map, type, name, arity) do From 670455fd59ddcf147b70cc30b05245a80ae3d334 Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Thu, 7 Apr 2016 10:01:35 -0500 Subject: [PATCH 221/860] Updated CHANGELOG.md --- CHANGELOG.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index e8ebf76a..4e6cb7d6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,9 @@ * Breaking * The above functionality will cause either compiler errors or no output. Please change extensions of ElixirScript code to .exjs +* Deprecations + * `Html`, `View`, and `VDom` modules will be removed in the next version as they can now be replicated using macros + # v0.17.0 * Enhancements * Incremental Compilation: From 5ef3e08854b8fb4967564ac5fdc8fbecc01ca5a0 Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Thu, 7 Apr 2016 18:35:11 -0500 Subject: [PATCH 222/860] Expanding use macros before adding modules to state --- lib/elixir_script/translator/module.ex | 23 --------- .../translator/module_collector.ex | 48 +++++++++++++++++-- 2 files changed, 45 insertions(+), 26 deletions(-) diff --git a/lib/elixir_script/translator/module.ex b/lib/elixir_script/translator/module.ex index b25233d8..5ae8c4dc 100644 --- a/lib/elixir_script/translator/module.ex +++ b/lib/elixir_script/translator/module.ex @@ -16,7 +16,6 @@ defmodule ElixirScript.Translator.Module do end def make_module(module, body, env) do - body = process_use(body) { body, functions } = extract_functions_from_module(body) { body, env } = translate_body(body, env) @@ -61,28 +60,6 @@ defmodule ElixirScript.Translator.Module do result end - defp process_use(ast) do - Macro.prewalk(ast, &do_process_use(&1)) - end - - defp do_process_use({:use, _, _} = ast) do - ast - |> Macro.expand(ElixirScript.Translator.State.get().compiler_opts.env) - |> expand__using__ - end - - defp do_process_use(ast) do - ast - end - - defp expand__using__({:__block__, _, [{:require, _, _}, {{:., _, [_, :__using__]}, _, _} = using_ast]}) do - Macro.expand_once(using_ast, ElixirScript.Translator.State.get().compiler_opts.env) - end - - defp expand__using__({:__block__, _, [{:__block__, _, [{:require, _, _}, {{:., _, [_, :__using__]}, _, _} = using_ast]}]}) do - Macro.expand_once(using_ast, ElixirScript.Translator.State.get().compiler_opts.env) - end - def translate_body(body, env) do { body, env } = Translator.translate(body, env) diff --git a/lib/elixir_script/translator/module_collector.ex b/lib/elixir_script/translator/module_collector.ex index 301b11e9..e18d9044 100644 --- a/lib/elixir_script/translator/module_collector.ex +++ b/lib/elixir_script/translator/module_collector.ex @@ -108,12 +108,35 @@ defmodule ElixirScript.Translator.ModuleCollector do end defp make_module(body, name) do + # Finds use expressions and expands them body = case body do - {:__block__, _, _ } -> - Macro.expand(body, State.get().compiler_opts.env) + {:__block__, context, list } -> + list = Enum.map(list, fn + {:use, _, [module, _] } = using -> + {:use, handle_use_expression(using, module) } + {:use, _, [module] } = using -> + {:use, handle_use_expression(using, module) } + ast -> + {:expanded, ast} + end) + |> Enum.reduce([], fn + {:use, ast}, state -> + case ast do + {:__block__, _, list} -> + state ++ list + _ -> + state ++ [ast] + end + + {:expanded, ast}, state -> + state ++ [ast] + end) + + {:__block__, context, list} + _ -> body - end + end %{def: functions, defp: private_functions } = get_functions_from_module(body) js_imports = get_js_imports_from_module(body) @@ -122,6 +145,25 @@ defmodule ElixirScript.Translator.ModuleCollector do functions: functions, private_functions: private_functions, js_imports: js_imports } end + def handle_use_expression(using_ast, module) do + module = Utils.quoted_to_name(module) + + eval = """ + require #{inspect module} + __ENV__ + """ + {env, _} = Code.eval_string(eval, [], State.get().compiler_opts.env) + + + case Macro.expand(using_ast, env) do + {:__block__, _, + [{:__block__, _, + [{:require, _, _}, + {{:., _, [_, :__using__]}, _, _} = ast]}]} -> + Macro.expand_once(ast, env) + end + end + defp make_inner_module_aliases(name, body) do case body do nil -> From a24faa78b2823c3b393cd3b226557c6af38f1c94 Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Thu, 7 Apr 2016 20:25:46 -0500 Subject: [PATCH 223/860] Update GettingStarted.md --- GettingStarted.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/GettingStarted.md b/GettingStarted.md index a4d0cc88..a0482abf 100644 --- a/GettingStarted.md +++ b/GettingStarted.md @@ -155,9 +155,9 @@ whenever an import or require expression is found, if the module specified is lo #### Using JavaScript Modules -You can use `alias`, `import`, and `require` as you would in Elixir (sans macros). +You can use `alias`, `import`, and `require` as you would in Elixir. -For JavaScript modules, use `JS.import` +For JavaScript modules, you use must `JS.import` ```elixir JS.import A, "a" #translates to "import {default as A} from 'a'" From 27784352a46dec60cfdf129f0e6c6dbd62e0893c Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Fri, 8 Apr 2016 08:53:19 -0500 Subject: [PATCH 224/860] Updated documentation --- CHANGELOG.md | 2 +- FAQ.md | 4 ++-- GettingStarted.md | 4 ++-- mix.exs | 2 +- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 4e6cb7d6..544a3ddb 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,4 +1,4 @@ -# v0.18.0-dev +# v0.18.0 * Enhancements * Better support for macros. Macros should be defined in .ex or .exs files. ElixirScript code should be in .exjs files diff --git a/FAQ.md b/FAQ.md index 8b11ba90..09d31ff2 100644 --- a/FAQ.md +++ b/FAQ.md @@ -83,7 +83,7 @@ You **can** use ElixirScript on your front ends and have it work and interoperat ## Q. Can I use pattern matching? -### A. Yes, but not for bitstrings (yet) +### A. Yes ## Q. Can I use processes? @@ -94,7 +94,7 @@ You **can** use ElixirScript on your front ends and have it work and interoperat ### A. Maybe, but in an idiomatic fashion. -One of my demos is an example of using a design similar to redux to accomplish the things that redux does only using the Elixir standard library. Redux is influenced by Elm. The goal is to eventually allow for designs that can be Elm influenced if that is the desire. Similar to the same way the José saya to bring the spirit of projects from other languages to Elixir and not always just a straight port. If processes are added, I believe it will be easier to do those things in an idiomatic Elixir way. +One of my demos is an example of using a design similar to redux to accomplish the things that redux does only using the Elixir standard library. Redux is influenced by Elm. The goal is to eventually allow for designs that can be Elm influenced if that is the desire. Similar to the same way the José says to bring the spirit of projects from other languages to Elixir and not always just a straight port. If processes are added, I believe it will be easier to do those things in an idiomatic Elixir way. ## Q. What about OTP? diff --git a/GettingStarted.md b/GettingStarted.md index a4d0cc88..c8995e74 100644 --- a/GettingStarted.md +++ b/GettingStarted.md @@ -148,14 +148,14 @@ The intent of this guide is to get you started with ElixirScript. It will give y ### Macros Macros must be defined in either a `.ex` or `.exs` file. These will be loaded at compile time and -whenever an import or require expression is found, if the module specified is loaded, it will use it to expand macros within the lexical scope +whenever an import or require expression is found, if the module specified is loaded, it will use it to expand macros within the lexical scope. ### Appendix #### Using JavaScript Modules -You can use `alias`, `import`, and `require` as you would in Elixir (sans macros). +You can use `alias`, `import`, and `require` as you would in Elixir. For JavaScript modules, use `JS.import` diff --git a/mix.exs b/mix.exs index bd9388b0..72e82a82 100644 --- a/mix.exs +++ b/mix.exs @@ -4,7 +4,7 @@ defmodule ElixirScript.Mixfile do def project do [ app: :elixir_script, - version: "0.18.0-dev", + version: "0.18.0", elixir: "~> 1.0", escript: escript_config, deps: deps, From 658f17c1a6e862c01a4d006f04b7769cc7eb2b30 Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Fri, 8 Apr 2016 09:21:38 -0500 Subject: [PATCH 225/860] Updated docs --- GettingStarted.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/GettingStarted.md b/GettingStarted.md index 406b9fa3..bc81bcb7 100644 --- a/GettingStarted.md +++ b/GettingStarted.md @@ -103,7 +103,7 @@ The intent of this guide is to get you started with ElixirScript. It will give y The first step is getting the dependency. In your mix.exs file for your elixir project, add elixir_script to your deps. ```elixir - {:elixir_script, "~> 0.17"} + {:elixir_script, "~> 0.18"} ``` * Step 2: Now download the dep @@ -127,7 +127,7 @@ The intent of this guide is to get you started with ElixirScript. It will give y The first step is getting the dependency. In your mix.exs file for your elixir project, add elixir_script to your deps. ```elixir - {:elixir_script, "~> 0.17"} + {:elixir_script, "~> 0.18"} ``` * Step 2: Now download the dep From aad241d48e72405ab04b290eda0fdf96b81844ea Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Sun, 10 Apr 2016 13:31:46 -0500 Subject: [PATCH 226/860] Update GettingStarted.md --- GettingStarted.md | 31 ++++++------------------------- 1 file changed, 6 insertions(+), 25 deletions(-) diff --git a/GettingStarted.md b/GettingStarted.md index bc81bcb7..a05ee8a2 100644 --- a/GettingStarted.md +++ b/GettingStarted.md @@ -9,6 +9,8 @@ The intent of this guide is to get you started with ElixirScript. It will give y ### Escript +**OSX**: Elixirscript can be installed via homebrew `brew install elixirscript`. For everyone else, plase read below + * Step 1: Get escript You can download the elixirscript escript from the [releases page on github](https://github.com/bryanjos/elixirscript/releases). It is a tar file named elixirscript.tar.gz. @@ -165,33 +167,12 @@ JS.import A, "a" #translates to "import {default as A} from 'a'" JS.import [A, B, C], "a" #translates to "import {A, B, C} from 'a'" ``` +#### Frontend Project Boilerplate + +There is an [elixirscript frontend boilerplate project](https://github.com/bryanjos/elixirscript-project-boilerplate). This setup uses gulp and brunch to build and bundle assets. + #### ElixirScript-Brunch There is an Brunch plugin, [ElixirScript-Brunch](https://www.npmjs.com/package/elixirscript-brunch). There are instructions there on how to use it with Phoenix. - -#### Gulp - -There is no gulp plugin just yet, but below is an example of how to make a gulp -task that will work with it. - -```javascript -var gulp = require('gulp'); -var exec = require('child_process').exec; -var babel = require('gulp-babel'); - -//Calls out to the elixirscript compiler and places the output in src/js -gulp.task('build-exjs', function(cb) { - exec('elixirscript "' + exjsSrc + '" -o ' + "src/js", function (err, stdout, stderr) { - cb(err); - }); -}); - -// A task to turn the es6 output from build-exjs to es5 -gulp.task('build-js', ['build-exjs'], function() { - return gulp.src(jsSrc) - .pipe(babel()) - .pipe(gulp.dest(jsDest)); -}); -``` From be1ce57a2d5dfb4667f3787401599a56dc98cc60 Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Sun, 10 Apr 2016 13:32:49 -0500 Subject: [PATCH 227/860] Update README.md --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index 01b1b3df..65589b4f 100644 --- a/README.md +++ b/README.md @@ -58,6 +58,7 @@ Please check the [CONTRIBUTING.md](CONTRIBUTING.md) ### Example projects +* [elixirscript frontend boilerplate](https://github.com/bryanjos/elixirscript-project-boilerplate) A boilerplate project for elixirscript frontends * [todo-elixirscript](https://github.com/bryanjos/todo-elixirscript) A Todo App built with Elixirscript and Phoenix * [phoenix_chat_example](https://github.com/bryanjos/phoenix_chat_example) The Phoenix Chat App using ElixirScript. * [MobileElixir](https://github.com/bryanjos/MobileElixir) Using ElixirScript with React Native From ee691f252979b287908908057b084f0b6aad5908 Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Sun, 10 Apr 2016 13:33:34 -0500 Subject: [PATCH 228/860] Removed view modules --- lib/elixir_script.ex | 5 - lib/elixir_script/prelude/html.ex | 84 -- lib/elixir_script/prelude/tags.txt | 106 -- lib/elixir_script/prelude/v_dom.ex | 80 -- lib/elixir_script/prelude/view.ex | 78 -- src/javascript/elixir.js | 4 +- src/javascript/lib/virtual-dom.js | 1699 ---------------------------- test/elixir_script_test.exs | 24 - 8 files changed, 1 insertion(+), 2079 deletions(-) delete mode 100644 lib/elixir_script/prelude/html.ex delete mode 100644 lib/elixir_script/prelude/tags.txt delete mode 100644 lib/elixir_script/prelude/v_dom.ex delete mode 100644 lib/elixir_script/prelude/view.ex delete mode 100644 src/javascript/lib/virtual-dom.js diff --git a/lib/elixir_script.ex b/lib/elixir_script.ex index f7571d26..957770be 100644 --- a/lib/elixir_script.ex +++ b/lib/elixir_script.ex @@ -37,8 +37,6 @@ defmodule ElixirScript do import Kernel, only: [&&: 2, use: 2, use: 1] import ElixirScript.Kernel require ElixirScript.JS, as: JS - require ElixirScript.Html, as: Html - require ElixirScript.VDom, as: VDom end end @@ -161,9 +159,6 @@ defmodule ElixirScript do libs_path = Path.join([__DIR__, "elixir_script", "prelude", "**", "*.ex"]) code = Path.wildcard(libs_path) - |> Enum.filter(fn(path) -> - !String.contains?(path, ["v_dom.ex", "html.ex"]) - end) |> Enum.map(&file_to_quoted/1) ElixirScript.Translator.State.start_link(compiler_opts, []) diff --git a/lib/elixir_script/prelude/html.ex b/lib/elixir_script/prelude/html.ex deleted file mode 100644 index a476c134..00000000 --- a/lib/elixir_script/prelude/html.ex +++ /dev/null @@ -1,84 +0,0 @@ -defmodule ElixirScript.Html do - @moduledoc """ - Defines macros for HTML elements to be used to build up a virtual dom tree. - The virtual dom tree defined here can then be used with macros defined in the - VDom module or with the View module - - tree = Html.div [id: "hello"] do - Html.span do - "Hello" - end - end - - rootNode = VDom.create(tree) - :document.getElementById("main").appendChild(rootNode) - - newTree = Html.div [id: "world"] - - - patches = VDom.diff(tree, newTree) - rootNode = VDom.patch(rootNode, patches) - - Instead of patching and diffing manually, the `View` module can also be used - instead. - """ - - @external_resource tags_path = Path.join([__DIR__, "tags.txt"]) - - @tags (for line <- File.stream!(tags_path, [], :line) do - line |> String.strip |> String.to_atom - end) - - for tag <- @tags do - @doc """ - Defines a macro for the html element, #{tag} - """ - defmacro unquote(tag)(attrs, do: inner) do - tag = Atom.to_string(unquote(tag)) - { inner, attributes } = do_tag(inner, attrs) - - quote do - Elixir.VirtualDOM.h(unquote(tag), unquote(attributes), unquote(inner)) - end - end - - defmacro unquote(tag)(attrs \\ []) do - tag = Atom.to_string(unquote(tag)) - - { inner, attributes } = Dict.pop(attrs, :do) - { inner, attributes } = do_tag(inner, attributes) - - quote do - Elixir.VirtualDOM.h(unquote(tag), unquote(attributes), unquote(inner)) - end - end - end - - defp do_tag(inner, attributes) do - inner = case inner do - {:__block__, [], params} -> - params - nil -> - [] - x -> - [x] - end - - attributes = config_to_map(attributes) - - {inner, attributes} - end - - defp config_to_map(config) do - config = Enum.map(config, fn({key, value}) -> - if is_atom(key) do - {Atom.to_string(key), value} - else - {key, value} - end - end) - - {:%{}, [], config} - end - -end diff --git a/lib/elixir_script/prelude/tags.txt b/lib/elixir_script/prelude/tags.txt deleted file mode 100644 index f4228193..00000000 --- a/lib/elixir_script/prelude/tags.txt +++ /dev/null @@ -1,106 +0,0 @@ -a -abbr -address -area -article -aside -audio -b -base -bdi -bdo -blockquote -body -br -button -canvas -caption -cite -code -col -colgroup -command -datalist -dd -del -details -dfn -dialog -div -dl -dt -em -embed -fieldset -figcaption -figure -footer -form -h1 -head -header -hgroup -hr -html -i -iframe -img -input -ins -kbd -keygen -label -legend -li -link -main -map -mark -menu -menuitem -meta -meter -nav -noscript -object -ol -optgroup -option -output -p -param -pre -progress -q -rp -rt -ruby -s -samp -script -section -select -small -source -span -strong -style -sub -summary -sup -table -tbody -td -textarea -tfoot -th -thead -time -title -tr -track -u -ul -var -video -wbr diff --git a/lib/elixir_script/prelude/v_dom.ex b/lib/elixir_script/prelude/v_dom.ex deleted file mode 100644 index e4d7cc87..00000000 --- a/lib/elixir_script/prelude/v_dom.ex +++ /dev/null @@ -1,80 +0,0 @@ -defmodule ElixirScript.VDom do - @moduledoc """ - This defines macros for updating a virual dom tree based on patches. - This module is used in tandem with the Html module - - tree = Html.div [id: "hello"] do - Html.span do - "Hello" - end - end - - rootNode = VDom.create(tree) - :document.getElementById("main").appendChild(rootNode) - - newTree = Html.div [id: "world"] - - - patches = VDom.diff(tree, newTree) - rootNode = VDom.patch(rootNode, patches) - - """ - - - @doc """ - Creates a node from the virtual dom tree passed in. - This node is used to append to a real DOM element - - tree = Html.div [id: "hello"] do - Html.span do - "Hello" - end - end - - rootNode = VDom.create(tree) - :document.getElementById("main").appendChild(rootNode) - """ - defmacro create(element) do - quote do - Elixir.VirtualDOM.create(unquote(element)) - end - end - - - @doc """ - Takes two nodes and returns a list of differences between the two - This node is used to append to a real DOM element - - tree = Html.div [id: "hello"] - - newTree = Html.div [id: "world"] - - patches = VDom.diff(tree, newTree) - """ - defmacro diff(tree, newTree) do - quote do - Elixir.VirtualDOM.diff(unquote(tree), unquote(newTree)) - end - end - - - @doc """ - Returns a new node based on the node passed in with the passed in patches applied - - tree = Html.div [id: "hello"] - - rootNode = VDom.create(tree) - :document.getElementById("main").appendChild(rootNode) - - newTree = Html.div [id: "world"] - - - patches = VDom.diff(tree, newTree) - rootNode = VDom.patch(rootNode, patches) - """ - defmacro patch(root, patches) do - quote do - Elixir.VirtualDOM.patch(unquote(root), unquote(patches)) - end - end -end diff --git a/lib/elixir_script/prelude/view.ex b/lib/elixir_script/prelude/view.ex deleted file mode 100644 index 667bae0b..00000000 --- a/lib/elixir_script/prelude/view.ex +++ /dev/null @@ -1,78 +0,0 @@ -defmodule ElixirScript.View do - @moduledoc """ - Defines a module to handle view state. Handles the diffing and patching - normally done manually using the `VDom` module. - - def render(id) do - Html.div [id: "hello"] do - Html.span do - "Hello" - end - end - end - - #Starts View state and renders initial view - {:ok, view} = View.start(:document.body, &render/1, ["hello"]) - - #Updates the view with the new args - View.render(view, ["world"]) - """ - - - @doc """ - Starts the View state. This will render the initial view using the - render_func and the args - """ - def start(dom_root, render_func, args) do - pid = JS.global().processes.spawn() - - tree = render_func.apply(nil, args); - root_node = Elixir.VirtualDOM.create(tree); - - dom_root.appendChild(root_node); - - JS.global().processes.put(pid, "state", { root_node, tree, render_func }); - { :ok, pid } - end - - def start(dom_root, render_func, args, options) do - pid = JS.global().processes.spawn() - - if Elixir.Keyword.has_key?(options, :name) do - pid = JS.global().processes.register(Elixir.Keyword.get(options, :name), pid) - end - - tree = render_func.apply(nil, args); - root_node = Elixir.VirtualDOM.create(tree); - - dom_root.appendChild(root_node); - - JS.global().processes.put(pid, "state", { root_node, tree, render_func }) - { :ok, pid } - end - - @doc """ - Stops the View state - """ - def stop(view) do - JS.global().processes.exit(view) - :ok - end - - @doc """ - Updates the view by passing the args to the render_func - """ - def render(view, args) do - { root_node, tree, render_func } = JS.global().processes.get(view, "state") - - new_tree = render_func.apply(nil, args); - - patches = Elixir.VirtualDOM.diff(tree, new_tree) - root_node = Elixir.VirtualDOM.patch(root_node, patches) - - JS.global().processes.put(view, "state", { root_node, new_tree, render_func }); - - :ok - end - -end diff --git a/src/javascript/elixir.js b/src/javascript/elixir.js index 8495d9b1..1972ade5 100644 --- a/src/javascript/elixir.js +++ b/src/javascript/elixir.js @@ -1,9 +1,7 @@ import Core from './lib/core'; import Enum from './lib/enum'; -import VirtualDOM from './lib/virtual-dom'; export default { Core, - Enum, - VirtualDOM + Enum }; diff --git a/src/javascript/lib/virtual-dom.js b/src/javascript/lib/virtual-dom.js deleted file mode 100644 index f3238bc7..00000000 --- a/src/javascript/lib/virtual-dom.js +++ /dev/null @@ -1,1699 +0,0 @@ -let VirtualDOM = function(e) { - return e(); -}(function() { - var define, module, exports; - return (function e(t, n, r) { - function s(o, u) { - if (!n[o]) { - if (!t[o]) { - var a = typeof require == "function" && require; - if (!u && a) return a(o, !0); - if (i) return i(o, !0); - var f = new Error("Cannot find module '" + o + "'"); - throw f.code = "MODULE_NOT_FOUND", f - } - var l = n[o] = { - exports: {} - }; - t[o][0].call(l.exports, function(e) { - var n = t[o][1][e]; - return s(n ? n : e) - }, l, l.exports, e, t, n, r) - } - return n[o].exports - } - var i = typeof require == "function" && require; - for (var o = 0; o < r.length; o++) s(r[o]); - return s - })({ - 1: [function(require, module, exports) { - -var createElement = require("./vdom/create-element.js") - -module.exports = createElement - -},{"./vdom/create-element.js":15}],2:[function(require,module,exports){ -var diff = require("./vtree/diff.js") - -module.exports = diff - -},{"./vtree/diff.js":35}],3:[function(require,module,exports){ -var h = require("./virtual-hyperscript/index.js") - -module.exports = h - -},{"./virtual-hyperscript/index.js":22}],4:[function(require,module,exports){ -var diff = require("./diff.js") -var patch = require("./patch.js") -var h = require("./h.js") -var create = require("./create-element.js") -var VNode = require('./vnode/vnode.js') -var VText = require('./vnode/vtext.js') - -module.exports = { - diff: diff, - patch: patch, - h: h, - create: create, - VNode: VNode, - VText: VText -} - -},{"./create-element.js":1,"./diff.js":2,"./h.js":3,"./patch.js":13,"./vnode/vnode.js":31,"./vnode/vtext.js":33}],5:[function(require,module,exports){ -/*! - * Cross-Browser Split 1.1.1 - * Copyright 2007-2012 Steven Levithan - * Available under the MIT License - * ECMAScript compliant, uniform cross-browser split method - */ - -/** - * Splits a string into an array of strings using a regex or string separator. Matches of the - * separator are not included in the result array. However, if `separator` is a regex that contains - * capturing groups, backreferences are spliced into the result each time `separator` is matched. - * Fixes browser bugs compared to the native `String.prototype.split` and can be used reliably - * cross-browser. - * @param {String} str String to split. - * @param {RegExp|String} separator Regex or string to use for separating the string. - * @param {Number} [limit] Maximum number of items to include in the result array. - * @returns {Array} Array of substrings. - * @example - * - * // Basic use - * split('a b c d', ' '); - * // -> ['a', 'b', 'c', 'd'] - * - * // With limit - * split('a b c d', ' ', 2); - * // -> ['a', 'b'] - * - * // Backreferences in result array - * split('..word1 word2..', /([a-z]+)(\d+)/i); - * // -> ['..', 'word', '1', ' ', 'word', '2', '..'] - */ -module.exports = (function split(undef) { - - var nativeSplit = String.prototype.split, - compliantExecNpcg = /()??/.exec("")[1] === undef, - // NPCG: nonparticipating capturing group - self; - - self = function(str, separator, limit) { - // If `separator` is not a regex, use `nativeSplit` - if (Object.prototype.toString.call(separator) !== "[object RegExp]") { - return nativeSplit.call(str, separator, limit); - } - var output = [], - flags = (separator.ignoreCase ? "i" : "") + (separator.multiline ? "m" : "") + (separator.extended ? "x" : "") + // Proposed for ES6 - (separator.sticky ? "y" : ""), - // Firefox 3+ - lastLastIndex = 0, - // Make `global` and avoid `lastIndex` issues by working with a copy - separator = new RegExp(separator.source, flags + "g"), - separator2, match, lastIndex, lastLength; - str += ""; // Type-convert - if (!compliantExecNpcg) { - // Doesn't need flags gy, but they don't hurt - separator2 = new RegExp("^" + separator.source + "$(?!\\s)", flags); - } - /* Values for `limit`, per the spec: - * If undefined: 4294967295 // Math.pow(2, 32) - 1 - * If 0, Infinity, or NaN: 0 - * If positive number: limit = Math.floor(limit); if (limit > 4294967295) limit -= 4294967296; - * If negative number: 4294967296 - Math.floor(Math.abs(limit)) - * If other: Type-convert, then use the above rules - */ - limit = limit === undef ? -1 >>> 0 : // Math.pow(2, 32) - 1 - limit >>> 0; // ToUint32(limit) - while (match = separator.exec(str)) { - // `separator.lastIndex` is not reliable cross-browser - lastIndex = match.index + match[0].length; - if (lastIndex > lastLastIndex) { - output.push(str.slice(lastLastIndex, match.index)); - // Fix browsers whose `exec` methods don't consistently return `undefined` for - // nonparticipating capturing groups - if (!compliantExecNpcg && match.length > 1) { - match[0].replace(separator2, function() { - for (var i = 1; i < arguments.length - 2; i++) { - if (arguments[i] === undef) { - match[i] = undef; - } - } - }); - } - if (match.length > 1 && match.index < str.length) { - Array.prototype.push.apply(output, match.slice(1)); - } - lastLength = match[0].length; - lastLastIndex = lastIndex; - if (output.length >= limit) { - break; - } - } - if (separator.lastIndex === match.index) { - separator.lastIndex++; // Avoid an infinite loop - } - } - if (lastLastIndex === str.length) { - if (lastLength || !separator.test("")) { - output.push(""); - } - } else { - output.push(str.slice(lastLastIndex)); - } - return output.length > limit ? output.slice(0, limit) : output; - }; - - return self; -})(); - -},{}],6:[function(require,module,exports){ - -},{}],7:[function(require,module,exports){ -'use strict'; - -var OneVersionConstraint = require('individual/one-version'); - -var MY_VERSION = '7'; -OneVersionConstraint('ev-store', MY_VERSION); - -var hashKey = '__EV_STORE_KEY@' + MY_VERSION; - -module.exports = EvStore; - -function EvStore(elem) { - var hash = elem[hashKey]; - - if (!hash) { - hash = elem[hashKey] = {}; - } - - return hash; -} - -},{"individual/one-version":9}],8:[function(require,module,exports){ -(function (global){ -'use strict'; - -/*global window, global*/ - -var root = typeof window !== 'undefined' ? - window : typeof global !== 'undefined' ? - global : {}; - -module.exports = Individual; - -function Individual(key, value) { - if (key in root) { - return root[key]; - } - - root[key] = value; - - return value; -} - -}).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}) -},{}],9:[function(require,module,exports){ -'use strict'; - -var Individual = require('./index.js'); - -module.exports = OneVersion; - -function OneVersion(moduleName, version, defaultValue) { - var key = '__INDIVIDUAL_ONE_VERSION_' + moduleName; - var enforceKey = key + '_ENFORCE_SINGLETON'; - - var versionValue = Individual(enforceKey, version); - - if (versionValue !== version) { - throw new Error('Can only have one copy of ' + - moduleName + '.\n' + - 'You already have version ' + versionValue + - ' installed.\n' + - 'This means you cannot install version ' + version); - } - - return Individual(key, defaultValue); -} - -},{"./index.js":8}],10:[function(require,module,exports){ -(function (global){ -var topLevel = typeof global !== 'undefined' ? global : - typeof window !== 'undefined' ? window : {} -var minDoc = require('min-document'); - -if (typeof document !== 'undefined') { - module.exports = document; -} else { - var doccy = topLevel['__GLOBAL_DOCUMENT_CACHE@4']; - - if (!doccy) { - doccy = topLevel['__GLOBAL_DOCUMENT_CACHE@4'] = minDoc; - } - - module.exports = doccy; -} - -}).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}) -},{"min-document":6}],11:[function(require,module,exports){ -"use strict"; - -module.exports = function isObject(x) { - return typeof x === "object" && x !== null; -}; - -},{}],12:[function(require,module,exports){ -var nativeIsArray = Array.isArray -var toString = Object.prototype.toString - -module.exports = nativeIsArray || isArray - -function isArray(obj) { - return toString.call(obj) === "[object Array]" -} - -},{}],13:[function(require,module,exports){ -var patch = require("./vdom/patch.js") - -module.exports = patch - -},{"./vdom/patch.js":18}],14:[function(require,module,exports){ -var isObject = require("is-object") -var isHook = require("../vnode/is-vhook.js") - -module.exports = applyProperties - -function applyProperties(node, props, previous) { - for (var propName in props) { - var propValue = props[propName] - - if (propValue === undefined) { - removeProperty(node, propName, propValue, previous); - } else if (isHook(propValue)) { - removeProperty(node, propName, propValue, previous) - if (propValue.hook) { - propValue.hook(node, - propName, - previous ? previous[propName] : undefined) - } - } else { - if (isObject(propValue)) { - patchObject(node, props, previous, propName, propValue); - } else { - node[propName] = propValue - } - } - } -} - -function removeProperty(node, propName, propValue, previous) { - if (previous) { - var previousValue = previous[propName] - - if (!isHook(previousValue)) { - if (propName === "attributes") { - for (var attrName in previousValue) { - node.removeAttribute(attrName) - } - } else if (propName === "style") { - for (var i in previousValue) { - node.style[i] = "" - } - } else if (typeof previousValue === "string") { - node[propName] = "" - } else { - node[propName] = null - } - } else if (previousValue.unhook) { - previousValue.unhook(node, propName, propValue) - } - } -} - -function patchObject(node, props, previous, propName, propValue) { - var previousValue = previous ? previous[propName] : undefined - - // Set attributes - if (propName === "attributes") { - for (var attrName in propValue) { - var attrValue = propValue[attrName] - - if (attrValue === undefined) { - node.removeAttribute(attrName) - } else { - node.setAttribute(attrName, attrValue) - } - } - - return - } - - if(previousValue && isObject(previousValue) && - getPrototype(previousValue) !== getPrototype(propValue)) { - node[propName] = propValue - return - } - - if (!isObject(node[propName])) { - node[propName] = {} - } - - var replacer = propName === "style" ? "" : undefined - - for (var k in propValue) { - var value = propValue[k] - node[propName][k] = (value === undefined) ? replacer : value - } -} - -function getPrototype(value) { - if (Object.getPrototypeOf) { - return Object.getPrototypeOf(value) - } else if (value.__proto__) { - return value.__proto__ - } else if (value.constructor) { - return value.constructor.prototype - } -} - -},{"../vnode/is-vhook.js":26,"is-object":11}],15:[function(require,module,exports){ -var document = require("global/document") - -var applyProperties = require("./apply-properties") - -var isVNode = require("../vnode/is-vnode.js") -var isVText = require("../vnode/is-vtext.js") -var isWidget = require("../vnode/is-widget.js") -var handleThunk = require("../vnode/handle-thunk.js") - -module.exports = createElement - -function createElement(vnode, opts) { - var doc = opts ? opts.document || document : document - var warn = opts ? opts.warn : null - - vnode = handleThunk(vnode).a - - if (isWidget(vnode)) { - return vnode.init() - } else if (isVText(vnode)) { - return doc.createTextNode(vnode.text) - } else if (!isVNode(vnode)) { - if (warn) { - warn("Item is not a valid virtual dom node", vnode) - } - return null - } - - var node = (vnode.namespace === null) ? - doc.createElement(vnode.tagName) : - doc.createElementNS(vnode.namespace, vnode.tagName) - - var props = vnode.properties - applyProperties(node, props) - - var children = vnode.children - - for (var i = 0; i < children.length; i++) { - var childNode = createElement(children[i], opts) - if (childNode) { - node.appendChild(childNode) - } - } - - return node -} - -},{"../vnode/handle-thunk.js":24,"../vnode/is-vnode.js":27,"../vnode/is-vtext.js":28,"../vnode/is-widget.js":29,"./apply-properties":14,"global/document":10}],16:[function(require,module,exports){ -// Maps a virtual DOM tree onto a real DOM tree in an efficient manner. -// We don't want to read all of the DOM nodes in the tree so we use -// the in-order tree indexing to eliminate recursion down certain branches. -// We only recurse into a DOM node if we know that it contains a child of -// interest. - -var noChild = {} - -module.exports = domIndex - -function domIndex(rootNode, tree, indices, nodes) { - if (!indices || indices.length === 0) { - return {} - } else { - indices.sort(ascending) - return recurse(rootNode, tree, indices, nodes, 0) - } -} - -function recurse(rootNode, tree, indices, nodes, rootIndex) { - nodes = nodes || {} - - - if (rootNode) { - if (indexInRange(indices, rootIndex, rootIndex)) { - nodes[rootIndex] = rootNode - } - - var vChildren = tree.children - - if (vChildren) { - - var childNodes = rootNode.childNodes - - for (var i = 0; i < tree.children.length; i++) { - rootIndex += 1 - - var vChild = vChildren[i] || noChild - var nextIndex = rootIndex + (vChild.count || 0) - - // skip recursion down the tree if there are no nodes down here - if (indexInRange(indices, rootIndex, nextIndex)) { - recurse(childNodes[i], vChild, indices, nodes, rootIndex) - } - - rootIndex = nextIndex - } - } - } - - return nodes -} - -// Binary search for an index in the interval [left, right] -function indexInRange(indices, left, right) { - if (indices.length === 0) { - return false - } - - var minIndex = 0 - var maxIndex = indices.length - 1 - var currentIndex - var currentItem - - while (minIndex <= maxIndex) { - currentIndex = ((maxIndex + minIndex) / 2) >> 0 - currentItem = indices[currentIndex] - - if (minIndex === maxIndex) { - return currentItem >= left && currentItem <= right - } else if (currentItem < left) { - minIndex = currentIndex + 1 - } else if (currentItem > right) { - maxIndex = currentIndex - 1 - } else { - return true - } - } - - return false; -} - -function ascending(a, b) { - return a > b ? 1 : -1 -} - -},{}],17:[function(require,module,exports){ -var applyProperties = require("./apply-properties") - -var isWidget = require("../vnode/is-widget.js") -var VPatch = require("../vnode/vpatch.js") - -var updateWidget = require("./update-widget") - -module.exports = applyPatch - -function applyPatch(vpatch, domNode, renderOptions) { - var type = vpatch.type - var vNode = vpatch.vNode - var patch = vpatch.patch - - switch (type) { - case VPatch.REMOVE: - return removeNode(domNode, vNode) - case VPatch.INSERT: - return insertNode(domNode, patch, renderOptions) - case VPatch.VTEXT: - return stringPatch(domNode, vNode, patch, renderOptions) - case VPatch.WIDGET: - return widgetPatch(domNode, vNode, patch, renderOptions) - case VPatch.VNODE: - return vNodePatch(domNode, vNode, patch, renderOptions) - case VPatch.ORDER: - reorderChildren(domNode, patch) - return domNode - case VPatch.PROPS: - applyProperties(domNode, patch, vNode.properties) - return domNode - case VPatch.THUNK: - return replaceRoot(domNode, - renderOptions.patch(domNode, patch, renderOptions)) - default: - return domNode - } -} - -function removeNode(domNode, vNode) { - var parentNode = domNode.parentNode - - if (parentNode) { - parentNode.removeChild(domNode) - } - - destroyWidget(domNode, vNode); - - return null -} - -function insertNode(parentNode, vNode, renderOptions) { - var newNode = renderOptions.render(vNode, renderOptions) - - if (parentNode) { - parentNode.appendChild(newNode) - } - - return parentNode -} - -function stringPatch(domNode, leftVNode, vText, renderOptions) { - var newNode - - if (domNode.nodeType === 3) { - domNode.replaceData(0, domNode.length, vText.text) - newNode = domNode - } else { - var parentNode = domNode.parentNode - newNode = renderOptions.render(vText, renderOptions) - - if (parentNode && newNode !== domNode) { - parentNode.replaceChild(newNode, domNode) - } - } - - return newNode -} - -function widgetPatch(domNode, leftVNode, widget, renderOptions) { - var updating = updateWidget(leftVNode, widget) - var newNode - - if (updating) { - newNode = widget.update(leftVNode, domNode) || domNode - } else { - newNode = renderOptions.render(widget, renderOptions) - } - - var parentNode = domNode.parentNode - - if (parentNode && newNode !== domNode) { - parentNode.replaceChild(newNode, domNode) - } - - if (!updating) { - destroyWidget(domNode, leftVNode) - } - - return newNode -} - -function vNodePatch(domNode, leftVNode, vNode, renderOptions) { - var parentNode = domNode.parentNode - var newNode = renderOptions.render(vNode, renderOptions) - - if (parentNode && newNode !== domNode) { - parentNode.replaceChild(newNode, domNode) - } - - return newNode -} - -function destroyWidget(domNode, w) { - if (typeof w.destroy === "function" && isWidget(w)) { - w.destroy(domNode) - } -} - -function reorderChildren(domNode, moves) { - var childNodes = domNode.childNodes - var keyMap = {} - var node - var remove - var insert - - for (var i = 0; i < moves.removes.length; i++) { - remove = moves.removes[i] - node = childNodes[remove.from] - if (remove.key) { - keyMap[remove.key] = node - } - domNode.removeChild(node) - } - - var length = childNodes.length - for (var j = 0; j < moves.inserts.length; j++) { - insert = moves.inserts[j] - node = keyMap[insert.key] - // this is the weirdest bug i've ever seen in webkit - domNode.insertBefore(node, insert.to >= length++ ? null : childNodes[insert.to]) - } -} - -function replaceRoot(oldRoot, newRoot) { - if (oldRoot && newRoot && oldRoot !== newRoot && oldRoot.parentNode) { - oldRoot.parentNode.replaceChild(newRoot, oldRoot) - } - - return newRoot; -} - -},{"../vnode/is-widget.js":29,"../vnode/vpatch.js":32,"./apply-properties":14,"./update-widget":19}],18:[function(require,module,exports){ -var document = require("global/document") -var isArray = require("x-is-array") - -var render = require("./create-element") -var domIndex = require("./dom-index") -var patchOp = require("./patch-op") -module.exports = patch - -function patch(rootNode, patches, renderOptions) { - renderOptions = renderOptions || {} - renderOptions.patch = renderOptions.patch && renderOptions.patch !== patch - ? renderOptions.patch - : patchRecursive - renderOptions.render = renderOptions.render || render - - return renderOptions.patch(rootNode, patches, renderOptions) -} - -function patchRecursive(rootNode, patches, renderOptions) { - var indices = patchIndices(patches) - - if (indices.length === 0) { - return rootNode - } - - var index = domIndex(rootNode, patches.a, indices) - var ownerDocument = rootNode.ownerDocument - - if (!renderOptions.document && ownerDocument !== document) { - renderOptions.document = ownerDocument - } - - for (var i = 0; i < indices.length; i++) { - var nodeIndex = indices[i] - rootNode = applyPatch(rootNode, - index[nodeIndex], - patches[nodeIndex], - renderOptions) - } - - return rootNode -} - -function applyPatch(rootNode, domNode, patchList, renderOptions) { - if (!domNode) { - return rootNode - } - - var newNode - - if (isArray(patchList)) { - for (var i = 0; i < patchList.length; i++) { - newNode = patchOp(patchList[i], domNode, renderOptions) - - if (domNode === rootNode) { - rootNode = newNode - } - } - } else { - newNode = patchOp(patchList, domNode, renderOptions) - - if (domNode === rootNode) { - rootNode = newNode - } - } - - return rootNode -} - -function patchIndices(patches) { - var indices = [] - - for (var key in patches) { - if (key !== "a") { - indices.push(Number(key)) - } - } - - return indices -} - -},{"./create-element":15,"./dom-index":16,"./patch-op":17,"global/document":10,"x-is-array":12}],19:[function(require,module,exports){ -var isWidget = require("../vnode/is-widget.js") - -module.exports = updateWidget - -function updateWidget(a, b) { - if (isWidget(a) && isWidget(b)) { - if ("name" in a && "name" in b) { - return a.id === b.id - } else { - return a.init === b.init - } - } - - return false -} - -},{"../vnode/is-widget.js":29}],20:[function(require,module,exports){ -'use strict'; - -var EvStore = require('ev-store'); - -module.exports = EvHook; - -function EvHook(value) { - if (!(this instanceof EvHook)) { - return new EvHook(value); - } - - this.value = value; -} - -EvHook.prototype.hook = function (node, propertyName) { - var es = EvStore(node); - var propName = propertyName.substr(3); - - es[propName] = this.value; -}; - -EvHook.prototype.unhook = function(node, propertyName) { - var es = EvStore(node); - var propName = propertyName.substr(3); - - es[propName] = undefined; -}; - -},{"ev-store":7}],21:[function(require,module,exports){ -'use strict'; - -module.exports = SoftSetHook; - -function SoftSetHook(value) { - if (!(this instanceof SoftSetHook)) { - return new SoftSetHook(value); - } - - this.value = value; -} - -SoftSetHook.prototype.hook = function (node, propertyName) { - if (node[propertyName] !== this.value) { - node[propertyName] = this.value; - } -}; - -},{}],22:[function(require,module,exports){ -'use strict'; - -var isArray = require('x-is-array'); - -var VNode = require('../vnode/vnode.js'); -var VText = require('../vnode/vtext.js'); -var isVNode = require('../vnode/is-vnode'); -var isVText = require('../vnode/is-vtext'); -var isWidget = require('../vnode/is-widget'); -var isHook = require('../vnode/is-vhook'); -var isVThunk = require('../vnode/is-thunk'); - -var parseTag = require('./parse-tag.js'); -var softSetHook = require('./hooks/soft-set-hook.js'); -var evHook = require('./hooks/ev-hook.js'); - -module.exports = h; - -function h(tagName, properties, children) { - var childNodes = []; - var tag, props, key, namespace; - - if (!children && isChildren(properties)) { - children = properties; - props = {}; - } - - props = props || properties || {}; - tag = parseTag(tagName, props); - - // support keys - if (props.hasOwnProperty('key')) { - key = props.key; - props.key = undefined; - } - - // support namespace - if (props.hasOwnProperty('namespace')) { - namespace = props.namespace; - props.namespace = undefined; - } - - // fix cursor bug - if (tag === 'INPUT' && - !namespace && - props.hasOwnProperty('value') && - props.value !== undefined && - !isHook(props.value) - ) { - props.value = softSetHook(props.value); - } - - transformProperties(props); - - if (children !== undefined && children !== null) { - addChild(children, childNodes, tag, props); - } - - - return new VNode(tag, props, childNodes, key, namespace); -} - -function addChild(c, childNodes, tag, props) { - if (typeof c === 'string') { - childNodes.push(new VText(c)); - } else if (typeof c === 'number') { - childNodes.push(new VText(String(c))); - } else if (isChild(c)) { - childNodes.push(c); - } else if (isArray(c)) { - for (var i = 0; i < c.length; i++) { - addChild(c[i], childNodes, tag, props); - } - } else if (c === null || c === undefined) { - return; - } else { - throw UnexpectedVirtualElement({ - foreignObject: c, - parentVnode: { - tagName: tag, - properties: props - } - }); - } -} - -function transformProperties(props) { - for (var propName in props) { - if (props.hasOwnProperty(propName)) { - var value = props[propName]; - - if (isHook(value)) { - continue; - } - - if (propName.substr(0, 3) === 'ev-') { - // add ev-foo support - props[propName] = evHook(value); - } - } - } -} - -function isChild(x) { - return isVNode(x) || isVText(x) || isWidget(x) || isVThunk(x); -} - -function isChildren(x) { - return typeof x === 'string' || isArray(x) || isChild(x); -} - -function UnexpectedVirtualElement(data) { - var err = new Error(); - - err.type = 'virtual-hyperscript.unexpected.virtual-element'; - err.message = 'Unexpected virtual child passed to h().\n' + - 'Expected a VNode / Vthunk / VWidget / string but:\n' + - 'got:\n' + - errorString(data.foreignObject) + - '.\n' + - 'The parent vnode is:\n' + - errorString(data.parentVnode) - '\n' + - 'Suggested fix: change your `h(..., [ ... ])` callsite.'; - err.foreignObject = data.foreignObject; - err.parentVnode = data.parentVnode; - - return err; -} - -function errorString(obj) { - try { - return JSON.stringify(obj, null, ' '); - } catch (e) { - return String(obj); - } -} - -},{"../vnode/is-thunk":25,"../vnode/is-vhook":26,"../vnode/is-vnode":27,"../vnode/is-vtext":28,"../vnode/is-widget":29,"../vnode/vnode.js":31,"../vnode/vtext.js":33,"./hooks/ev-hook.js":20,"./hooks/soft-set-hook.js":21,"./parse-tag.js":23,"x-is-array":12}],23:[function(require,module,exports){ -'use strict'; - -var split = require('browser-split'); - -var classIdSplit = /([\.#]?[a-zA-Z0-9\u007F-\uFFFF_:-]+)/; -var notClassId = /^\.|#/; - -module.exports = parseTag; - -function parseTag(tag, props) { - if (!tag) { - return 'DIV'; - } - - var noId = !(props.hasOwnProperty('id')); - - var tagParts = split(tag, classIdSplit); - var tagName = null; - - if (notClassId.test(tagParts[1])) { - tagName = 'DIV'; - } - - var classes, part, type, i; - - for (i = 0; i < tagParts.length; i++) { - part = tagParts[i]; - - if (!part) { - continue; - } - - type = part.charAt(0); - - if (!tagName) { - tagName = part; - } else if (type === '.') { - classes = classes || []; - classes.push(part.substring(1, part.length)); - } else if (type === '#' && noId) { - props.id = part.substring(1, part.length); - } - } - - if (classes) { - if (props.className) { - classes.push(props.className); - } - - props.className = classes.join(' '); - } - - return props.namespace ? tagName : tagName.toUpperCase(); -} - -},{"browser-split":5}],24:[function(require,module,exports){ -var isVNode = require("./is-vnode") -var isVText = require("./is-vtext") -var isWidget = require("./is-widget") -var isThunk = require("./is-thunk") - -module.exports = handleThunk - -function handleThunk(a, b) { - var renderedA = a - var renderedB = b - - if (isThunk(b)) { - renderedB = renderThunk(b, a) - } - - if (isThunk(a)) { - renderedA = renderThunk(a, null) - } - - return { - a: renderedA, - b: renderedB - } -} - -function renderThunk(thunk, previous) { - var renderedThunk = thunk.vnode - - if (!renderedThunk) { - renderedThunk = thunk.vnode = thunk.render(previous) - } - - if (!(isVNode(renderedThunk) || - isVText(renderedThunk) || - isWidget(renderedThunk))) { - throw new Error("thunk did not return a valid node"); - } - - return renderedThunk -} - -},{"./is-thunk":25,"./is-vnode":27,"./is-vtext":28,"./is-widget":29}],25:[function(require,module,exports){ -module.exports = isThunk - -function isThunk(t) { - return t && t.type === "Thunk" -} - -},{}],26:[function(require,module,exports){ -module.exports = isHook - -function isHook(hook) { - return hook && - (typeof hook.hook === "function" && !hook.hasOwnProperty("hook") || - typeof hook.unhook === "function" && !hook.hasOwnProperty("unhook")) -} - -},{}],27:[function(require,module,exports){ -var version = require("./version") - -module.exports = isVirtualNode - -function isVirtualNode(x) { - return x && x.type === "VirtualNode" && x.version === version -} - -},{"./version":30}],28:[function(require,module,exports){ -var version = require("./version") - -module.exports = isVirtualText - -function isVirtualText(x) { - return x && x.type === "VirtualText" && x.version === version -} - -},{"./version":30}],29:[function(require,module,exports){ -module.exports = isWidget - -function isWidget(w) { - return w && w.type === "Widget" -} - -},{}],30:[function(require,module,exports){ -module.exports = "2" - -},{}],31:[function(require,module,exports){ -var version = require("./version") -var isVNode = require("./is-vnode") -var isWidget = require("./is-widget") -var isThunk = require("./is-thunk") -var isVHook = require("./is-vhook") - -module.exports = VirtualNode - -var noProperties = {} -var noChildren = [] - -function VirtualNode(tagName, properties, children, key, namespace) { - this.tagName = tagName - this.properties = properties || noProperties - this.children = children || noChildren - this.key = key != null ? String(key) : undefined - this.namespace = (typeof namespace === "string") ? namespace : null - - var count = (children && children.length) || 0 - var descendants = 0 - var hasWidgets = false - var hasThunks = false - var descendantHooks = false - var hooks - - for (var propName in properties) { - if (properties.hasOwnProperty(propName)) { - var property = properties[propName] - if (isVHook(property) && property.unhook) { - if (!hooks) { - hooks = {} - } - - hooks[propName] = property - } - } - } - - for (var i = 0; i < count; i++) { - var child = children[i] - if (isVNode(child)) { - descendants += child.count || 0 - - if (!hasWidgets && child.hasWidgets) { - hasWidgets = true - } - - if (!hasThunks && child.hasThunks) { - hasThunks = true - } - - if (!descendantHooks && (child.hooks || child.descendantHooks)) { - descendantHooks = true - } - } else if (!hasWidgets && isWidget(child)) { - if (typeof child.destroy === "function") { - hasWidgets = true - } - } else if (!hasThunks && isThunk(child)) { - hasThunks = true; - } - } - - this.count = count + descendants - this.hasWidgets = hasWidgets - this.hasThunks = hasThunks - this.hooks = hooks - this.descendantHooks = descendantHooks -} - -VirtualNode.prototype.version = version -VirtualNode.prototype.type = "VirtualNode" - -},{"./is-thunk":25,"./is-vhook":26,"./is-vnode":27,"./is-widget":29,"./version":30}],32:[function(require,module,exports){ -var version = require("./version") - -VirtualPatch.NONE = 0 -VirtualPatch.VTEXT = 1 -VirtualPatch.VNODE = 2 -VirtualPatch.WIDGET = 3 -VirtualPatch.PROPS = 4 -VirtualPatch.ORDER = 5 -VirtualPatch.INSERT = 6 -VirtualPatch.REMOVE = 7 -VirtualPatch.THUNK = 8 - -module.exports = VirtualPatch - -function VirtualPatch(type, vNode, patch) { - this.type = Number(type) - this.vNode = vNode - this.patch = patch -} - -VirtualPatch.prototype.version = version -VirtualPatch.prototype.type = "VirtualPatch" - -},{"./version":30}],33:[function(require,module,exports){ -var version = require("./version") - -module.exports = VirtualText - -function VirtualText(text) { - this.text = String(text) -} - -VirtualText.prototype.version = version -VirtualText.prototype.type = "VirtualText" - -},{"./version":30}],34:[function(require,module,exports){ -var isObject = require("is-object") -var isHook = require("../vnode/is-vhook") - -module.exports = diffProps - -function diffProps(a, b) { - var diff - - for (var aKey in a) { - if (!(aKey in b)) { - diff = diff || {} - diff[aKey] = undefined - } - - var aValue = a[aKey] - var bValue = b[aKey] - - if (aValue === bValue) { - continue - } else if (isObject(aValue) && isObject(bValue)) { - if (getPrototype(bValue) !== getPrototype(aValue)) { - diff = diff || {} - diff[aKey] = bValue - } else if (isHook(bValue)) { - diff = diff || {} - diff[aKey] = bValue - } else { - var objectDiff = diffProps(aValue, bValue) - if (objectDiff) { - diff = diff || {} - diff[aKey] = objectDiff - } - } - } else { - diff = diff || {} - diff[aKey] = bValue - } - } - - for (var bKey in b) { - if (!(bKey in a)) { - diff = diff || {} - diff[bKey] = b[bKey] - } - } - - return diff -} - -function getPrototype(value) { - if (Object.getPrototypeOf) { - return Object.getPrototypeOf(value) - } else if (value.__proto__) { - return value.__proto__ - } else if (value.constructor) { - return value.constructor.prototype - } -} - -},{"../vnode/is-vhook":26,"is-object":11}],35:[function(require,module,exports){ -var isArray = require("x-is-array") - -var VPatch = require("../vnode/vpatch") -var isVNode = require("../vnode/is-vnode") -var isVText = require("../vnode/is-vtext") -var isWidget = require("../vnode/is-widget") -var isThunk = require("../vnode/is-thunk") -var handleThunk = require("../vnode/handle-thunk") - -var diffProps = require("./diff-props") - -module.exports = diff - -function diff(a, b) { - var patch = { a: a } - walk(a, b, patch, 0) - return patch -} - -function walk(a, b, patch, index) { - if (a === b) { - return - } - - var apply = patch[index] - var applyClear = false - - if (isThunk(a) || isThunk(b)) { - thunks(a, b, patch, index) - } else if (b == null) { - - // If a is a widget we will add a remove patch for it - // Otherwise any child widgets/hooks must be destroyed. - // This prevents adding two remove patches for a widget. - if (!isWidget(a)) { - clearState(a, patch, index) - apply = patch[index] - } - - apply = appendPatch(apply, new VPatch(VPatch.REMOVE, a, b)) - } else if (isVNode(b)) { - if (isVNode(a)) { - if (a.tagName === b.tagName && - a.namespace === b.namespace && - a.key === b.key) { - var propsPatch = diffProps(a.properties, b.properties) - if (propsPatch) { - apply = appendPatch(apply, - new VPatch(VPatch.PROPS, a, propsPatch)) - } - apply = diffChildren(a, b, patch, apply, index) - } else { - apply = appendPatch(apply, new VPatch(VPatch.VNODE, a, b)) - applyClear = true - } - } else { - apply = appendPatch(apply, new VPatch(VPatch.VNODE, a, b)) - applyClear = true - } - } else if (isVText(b)) { - if (!isVText(a)) { - apply = appendPatch(apply, new VPatch(VPatch.VTEXT, a, b)) - applyClear = true - } else if (a.text !== b.text) { - apply = appendPatch(apply, new VPatch(VPatch.VTEXT, a, b)) - } - } else if (isWidget(b)) { - if (!isWidget(a)) { - applyClear = true - } - - apply = appendPatch(apply, new VPatch(VPatch.WIDGET, a, b)) - } - - if (apply) { - patch[index] = apply - } - - if (applyClear) { - clearState(a, patch, index) - } -} - -function diffChildren(a, b, patch, apply, index) { - var aChildren = a.children - var orderedSet = reorder(aChildren, b.children) - var bChildren = orderedSet.children - - var aLen = aChildren.length - var bLen = bChildren.length - var len = aLen > bLen ? aLen : bLen - - for (var i = 0; i < len; i++) { - var leftNode = aChildren[i] - var rightNode = bChildren[i] - index += 1 - - if (!leftNode) { - if (rightNode) { - // Excess nodes in b need to be added - apply = appendPatch(apply, - new VPatch(VPatch.INSERT, null, rightNode)) - } - } else { - walk(leftNode, rightNode, patch, index) - } - - if (isVNode(leftNode) && leftNode.count) { - index += leftNode.count - } - } - - if (orderedSet.moves) { - // Reorder nodes last - apply = appendPatch(apply, new VPatch( - VPatch.ORDER, - a, - orderedSet.moves - )) - } - - return apply -} - -function clearState(vNode, patch, index) { - // TODO: Make this a single walk, not two - unhook(vNode, patch, index) - destroyWidgets(vNode, patch, index) -} - -// Patch records for all destroyed widgets must be added because we need -// a DOM node reference for the destroy function -function destroyWidgets(vNode, patch, index) { - if (isWidget(vNode)) { - if (typeof vNode.destroy === "function") { - patch[index] = appendPatch( - patch[index], - new VPatch(VPatch.REMOVE, vNode, null) - ) - } - } else if (isVNode(vNode) && (vNode.hasWidgets || vNode.hasThunks)) { - var children = vNode.children - var len = children.length - for (var i = 0; i < len; i++) { - var child = children[i] - index += 1 - - destroyWidgets(child, patch, index) - - if (isVNode(child) && child.count) { - index += child.count - } - } - } else if (isThunk(vNode)) { - thunks(vNode, null, patch, index) - } -} - -// Create a sub-patch for thunks -function thunks(a, b, patch, index) { - var nodes = handleThunk(a, b) - var thunkPatch = diff(nodes.a, nodes.b) - if (hasPatches(thunkPatch)) { - patch[index] = new VPatch(VPatch.THUNK, null, thunkPatch) - } -} - -function hasPatches(patch) { - for (var index in patch) { - if (index !== "a") { - return true - } - } - - return false -} - -// Execute hooks when two nodes are identical -function unhook(vNode, patch, index) { - if (isVNode(vNode)) { - if (vNode.hooks) { - patch[index] = appendPatch( - patch[index], - new VPatch( - VPatch.PROPS, - vNode, - undefinedKeys(vNode.hooks) - ) - ) - } - - if (vNode.descendantHooks || vNode.hasThunks) { - var children = vNode.children - var len = children.length - for (var i = 0; i < len; i++) { - var child = children[i] - index += 1 - - unhook(child, patch, index) - - if (isVNode(child) && child.count) { - index += child.count - } - } - } - } else if (isThunk(vNode)) { - thunks(vNode, null, patch, index) - } -} - -function undefinedKeys(obj) { - var result = {} - - for (var key in obj) { - result[key] = undefined - } - - return result -} - -// List diff, naive left to right reordering -function reorder(aChildren, bChildren) { - // O(M) time, O(M) memory - var bChildIndex = keyIndex(bChildren) - var bKeys = bChildIndex.keys - var bFree = bChildIndex.free - - if (bFree.length === bChildren.length) { - return { - children: bChildren, - moves: null - } - } - - // O(N) time, O(N) memory - var aChildIndex = keyIndex(aChildren) - var aKeys = aChildIndex.keys - var aFree = aChildIndex.free - - if (aFree.length === aChildren.length) { - return { - children: bChildren, - moves: null - } - } - - // O(MAX(N, M)) memory - var newChildren = [] - - var freeIndex = 0 - var freeCount = bFree.length - var deletedItems = 0 - - // Iterate through a and match a node in b - // O(N) time, - for (var i = 0 ; i < aChildren.length; i++) { - var aItem = aChildren[i] - var itemIndex - - if (aItem.key) { - if (bKeys.hasOwnProperty(aItem.key)) { - // Match up the old keys - itemIndex = bKeys[aItem.key] - newChildren.push(bChildren[itemIndex]) - - } else { - // Remove old keyed items - itemIndex = i - deletedItems++ - newChildren.push(null) - } - } else { - // Match the item in a with the next free item in b - if (freeIndex < freeCount) { - itemIndex = bFree[freeIndex++] - newChildren.push(bChildren[itemIndex]) - } else { - // There are no free items in b to match with - // the free items in a, so the extra free nodes - // are deleted. - itemIndex = i - deletedItems++ - newChildren.push(null) - } - } - } - - var lastFreeIndex = freeIndex >= bFree.length ? - bChildren.length : - bFree[freeIndex] - - // Iterate through b and append any new keys - // O(M) time - for (var j = 0; j < bChildren.length; j++) { - var newItem = bChildren[j] - - if (newItem.key) { - if (!aKeys.hasOwnProperty(newItem.key)) { - // Add any new keyed items - // We are adding new items to the end and then sorting them - // in place. In future we should insert new items in place. - newChildren.push(newItem) - } - } else if (j >= lastFreeIndex) { - // Add any leftover non-keyed items - newChildren.push(newItem) - } - } - - var simulate = newChildren.slice() - var simulateIndex = 0 - var removes = [] - var inserts = [] - var simulateItem - - for (var k = 0; k < bChildren.length;) { - var wantedItem = bChildren[k] - simulateItem = simulate[simulateIndex] - - // remove items - while (simulateItem === null && simulate.length) { - removes.push(remove(simulate, simulateIndex, null)) - simulateItem = simulate[simulateIndex] - } - - if (!simulateItem || simulateItem.key !== wantedItem.key) { - // if we need a key in this position... - if (wantedItem.key) { - if (simulateItem && simulateItem.key) { - // if an insert doesn't put this key in place, it needs to move - if (bKeys[simulateItem.key] !== k + 1) { - removes.push(remove(simulate, simulateIndex, simulateItem.key)) - simulateItem = simulate[simulateIndex] - // if the remove didn't put the wanted item in place, we need to insert it - if (!simulateItem || simulateItem.key !== wantedItem.key) { - inserts.push({key: wantedItem.key, to: k}) - } - // items are matching, so skip ahead - else { - simulateIndex++ - } - } - else { - inserts.push({key: wantedItem.key, to: k}) - } - } - else { - inserts.push({key: wantedItem.key, to: k}) - } - k++ - } - // a key in simulate has no matching wanted key, remove it - else if (simulateItem && simulateItem.key) { - removes.push(remove(simulate, simulateIndex, simulateItem.key)) - } - } - else { - simulateIndex++ - k++ - } - } - - // remove all the remaining nodes from simulate - while(simulateIndex < simulate.length) { - simulateItem = simulate[simulateIndex] - removes.push(remove(simulate, simulateIndex, simulateItem && simulateItem.key)) - } - - // If the only moves we have are deletes then we can just - // let the delete patch remove these items. - if (removes.length === deletedItems && !inserts.length) { - return { - children: newChildren, - moves: null - } - } - - return { - children: newChildren, - moves: { - removes: removes, - inserts: inserts - } - } -} - -function remove(arr, index, key) { - arr.splice(index, 1) - - return { - from: index, - key: key - } -} - -function keyIndex(children) { - var keys = {} - var free = [] - var length = children.length - - for (var i = 0; i < length; i++) { - var child = children[i] - - if (child.key) { - keys[child.key] = i - } else { - free.push(i) - } - } - - return { - keys: keys, // A hash of key name to index - free: free // An array of unkeyed item indices - } -} - -function appendPatch(apply, patch) { - if (apply) { - if (isArray(apply)) { - apply.push(patch) - } else { - apply = [apply, patch] - } - - return apply - } else { - return patch - } -} - -},{"../vnode/handle-thunk":24,"../vnode/is-thunk":25,"../vnode/is-vnode":27,"../vnode/is-vtext":28,"../vnode/is-widget":29,"../vnode/vpatch":32,"./diff-props":34,"x-is-array":12}]},{},[4])(4) -}); - -export default VirtualDOM; diff --git a/test/elixir_script_test.exs b/test/elixir_script_test.exs index ef0f5990..d13461db 100644 --- a/test/elixir_script_test.exs +++ b/test/elixir_script_test.exs @@ -130,30 +130,6 @@ defmodule ElixirScript.Test do end - test "expand Html macros" do - js_code = ElixirScript.compile(""" - tree = Html.div [id: "myDiv"] do - Html.span do - "Hello" - end - - Html.span do - "World" - end - end - - rootNode = VDom.create(tree) - :document.getElementById("main").appendChild(rootNode) - """) - - js_code = Enum.join(js_code, "\n") - - assert js_code =~ "Elixir.VirtualDOM.h('div'" - assert js_code =~ "Elixir.VirtualDOM.h('span'" - assert js_code =~ "Elixir.VirtualDOM.create" - end - - test "set standard lib path" do js_code = ElixirScript.compile(""" From d68454fde6544e7b48e11e8844f08ebd2d0cf2d1 Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Wed, 13 Apr 2016 16:54:22 -0500 Subject: [PATCH 229/860] Added elixirscript mix compiler --- lib/mix/tasks/compile.elixir_script.ex | 51 ++++++++++++++++++++++++++ 1 file changed, 51 insertions(+) create mode 100644 lib/mix/tasks/compile.elixir_script.ex diff --git a/lib/mix/tasks/compile.elixir_script.ex b/lib/mix/tasks/compile.elixir_script.ex new file mode 100644 index 00000000..eaf36ecc --- /dev/null +++ b/lib/mix/tasks/compile.elixir_script.ex @@ -0,0 +1,51 @@ +defmodule Mix.Tasks.Compile.ElixirScript do + use Mix.Task + + @moduledoc """ + Compiles Elixirscript source files into JavaScript + + Looks for an `elixirscript` key in your mix project config + + def project do + [ + app: :my_app, + version: "0.1.0", + elixir: "~> 1.0", + deps: deps, + elixirscript: [ input: "src/exjs", output: "src/js"], + compilers: [:elixir_script] ++ Mix.compilers + ] + end + """ + + + def run(_) do + elixirscript_config = get_elixirscript_config() + input_path = Keyword.fetch!(elixirscript_config, :input) + output_path = Keyword.fetch!(elixirscript_config, :output) + + ElixirScript.compile_path(input_path, %{ output: output_path }) + :ok + end + + def clean do + elixirscript_config = get_elixirscript_config() + input_path = Keyword.fetch!(elixirscript_config, :input) + output_path = Keyword.fetch!(elixirscript_config, :output) + + File.ls!(output_path) + |> Enum.each(fn(x) -> + if String.contains?(Path.basename(x), "Elixir.") do + File.rm!(Path.join(output_path, x)) + end + end) + + :ok + end + + def get_elixirscript_config() do + config = Mix.Project.config + Keyword.fetch!(config, :elixirscript) + end + +end From 32568d6facdb080091fee8f0a32c74416215b2bb Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Thu, 14 Apr 2016 09:17:58 -0500 Subject: [PATCH 230/860] Updated elixir_script key in mix project --- lib/mix/tasks/compile.elixir_script.ex | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/mix/tasks/compile.elixir_script.ex b/lib/mix/tasks/compile.elixir_script.ex index eaf36ecc..e8d90cd4 100644 --- a/lib/mix/tasks/compile.elixir_script.ex +++ b/lib/mix/tasks/compile.elixir_script.ex @@ -12,7 +12,7 @@ defmodule Mix.Tasks.Compile.ElixirScript do version: "0.1.0", elixir: "~> 1.0", deps: deps, - elixirscript: [ input: "src/exjs", output: "src/js"], + elixir_script: [ input: "src/exjs", output: "src/js"], compilers: [:elixir_script] ++ Mix.compilers ] end @@ -45,7 +45,7 @@ defmodule Mix.Tasks.Compile.ElixirScript do def get_elixirscript_config() do config = Mix.Project.config - Keyword.fetch!(config, :elixirscript) + Keyword.fetch!(config, :elixir_script) end end From 496900539af6f8c43c0d6283aee856934d3fb615 Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Thu, 21 Apr 2016 20:14:23 -0500 Subject: [PATCH 231/860] Updated docs --- lib/mix/tasks/compile.elixir_script.ex | 6 +++--- lib/mix/tasks/elixirscript.ex | 3 ++- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/lib/mix/tasks/compile.elixir_script.ex b/lib/mix/tasks/compile.elixir_script.ex index e8d90cd4..7a31da00 100644 --- a/lib/mix/tasks/compile.elixir_script.ex +++ b/lib/mix/tasks/compile.elixir_script.ex @@ -2,7 +2,7 @@ defmodule Mix.Tasks.Compile.ElixirScript do use Mix.Task @moduledoc """ - Compiles Elixirscript source files into JavaScript + Mix compiler to allow mix to compile Elixirscript source files into JavaScript Looks for an `elixirscript` key in your mix project config @@ -12,7 +12,7 @@ defmodule Mix.Tasks.Compile.ElixirScript do version: "0.1.0", elixir: "~> 1.0", deps: deps, - elixir_script: [ input: "src/exjs", output: "src/js"], + elixir_script: [ input: "src/exjs", output: "dest/js"], compilers: [:elixir_script] ++ Mix.compilers ] end @@ -43,7 +43,7 @@ defmodule Mix.Tasks.Compile.ElixirScript do :ok end - def get_elixirscript_config() do + defp get_elixirscript_config() do config = Mix.Project.config Keyword.fetch!(config, :elixir_script) end diff --git a/lib/mix/tasks/elixirscript.ex b/lib/mix/tasks/elixirscript.ex index 9d1f5599..cc075cfb 100644 --- a/lib/mix/tasks/elixirscript.ex +++ b/lib/mix/tasks/elixirscript.ex @@ -1,7 +1,8 @@ defmodule Mix.Tasks.Elixirscript do use Mix.Task - @shortdoc "Translate Elixir to JavaScript" + @shortdoc "Translate Elixir to JavaScript" + def run(args) do Mix.Task.run "app.start" From 830d246c3a442fdfd284357a74fe945d20ad103f Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Sun, 24 Apr 2016 13:13:56 -0500 Subject: [PATCH 232/860] Trying to add watcher --- lib/elixir_script/cli.ex | 10 +++++++++- lib/elixir_script/watcher.ex | 20 ++++++++++++++++++++ mix.exs | 3 ++- mix.lock | 1 + 4 files changed, 32 insertions(+), 2 deletions(-) create mode 100644 lib/elixir_script/watcher.ex diff --git a/lib/elixir_script/cli.ex b/lib/elixir_script/cli.ex index 774ef03f..d673020c 100644 --- a/lib/elixir_script/cli.ex +++ b/lib/elixir_script/cli.ex @@ -6,7 +6,7 @@ defmodule ElixirScript.CLI do @switches [ output: :binary, elixir: :boolean, root: :binary, help: :boolean, core_path: :binary, std_lib: :binary, - full_build: :boolean, version: :boolean + full_build: :boolean, version: :boolean, watch: :boolean ] @aliases [ @@ -63,6 +63,7 @@ defmodule ElixirScript.CLI do end def process({ input, options }) do + IO.inspect(options) if options_contains_unknown_values(options) do process(:help) else @@ -71,6 +72,8 @@ defmodule ElixirScript.CLI do end def do_process(input, options) do + {watch, options} = Keyword.pop(options, :watch, false) + compile_opts = %{ root: options[:root], include_path: true, @@ -84,6 +87,11 @@ defmodule ElixirScript.CLI do ElixirScript.compile(input, compile_opts) _ -> ElixirScript.compile_path(input, compile_opts) + + if watch do + ElixirScript.Watcher.start_link(input, compile_opts) + :timer.sleep :infinity + end end end diff --git a/lib/elixir_script/watcher.ex b/lib/elixir_script/watcher.ex new file mode 100644 index 00000000..75a24edf --- /dev/null +++ b/lib/elixir_script/watcher.ex @@ -0,0 +1,20 @@ +defmodule ElixirScript.Watcher do + use GenServer + require Logger + + def start_link(input, options) do + GenServer.start_link(__MODULE__, [input: input, options: options]) + end + + def init(args) do + {:ok, _} = Application.ensure_all_started(:elixir_script) + :fs.subscribe() + {:ok, args} + end + + def handle_info({_pid, {:fs, :file_event}, {path, event}}, state) do + Logger.debug "File changed: #{path}" + ElixirScript.compile_path(state[:input], state[:options]) + {:noreply, state} + end +end diff --git a/mix.exs b/mix.exs index 72e82a82..69fbcc16 100644 --- a/mix.exs +++ b/mix.exs @@ -22,13 +22,14 @@ defmodule ElixirScript.Mixfile do def application do [ - applications: [:logger, :estree] + applications: [:logger, :estree, :fs] ] end defp deps do [ {:estree, "~> 2.3" }, + {:fs, "~> 0.9.1"}, {:earmark, "~> 0.2", only: :dev }, {:ex_doc, "~> 0.11", only: :dev }, {:excoveralls, "~> 0.4", only: :test}, diff --git a/mix.lock b/mix.lock index 9e5f21e5..d751de3f 100644 --- a/mix.lock +++ b/mix.lock @@ -8,6 +8,7 @@ "ex_doc": {:hex, :ex_doc, "0.11.4"}, "excoveralls": {:hex, :excoveralls, "0.5.1"}, "exjsx": {:hex, :exjsx, "3.2.0"}, + "fs": {:hex, :fs, "0.9.2"}, "hackney": {:hex, :hackney, "1.4.8"}, "idna": {:hex, :idna, "1.0.3"}, "inflex": {:hex, :inflex, "1.5.0"}, From 66bfb17551c33452488381465e720d935eaa104f Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Fri, 29 Apr 2016 17:10:52 -0500 Subject: [PATCH 233/860] Updated to 0.19.0 --- CHANGELOG.md | 7 +++++++ mix.exs | 2 +- package.json | 10 +++++----- 3 files changed, 13 insertions(+), 6 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 544a3ddb..71d0ffa2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,10 @@ +# v0.19.0 +* Enhancements + * Added elixir_script mix compiler + +* Breaking + * `Html`, `View`, and `VDom` modules have been removed + # v0.18.0 * Enhancements * Better support for macros. Macros should be defined in .ex or .exs files. ElixirScript code should be in .exjs files diff --git a/mix.exs b/mix.exs index 72e82a82..45ade4b7 100644 --- a/mix.exs +++ b/mix.exs @@ -4,7 +4,7 @@ defmodule ElixirScript.Mixfile do def project do [ app: :elixir_script, - version: "0.18.0", + version: "0.19.0", elixir: "~> 1.0", escript: escript_config, deps: deps, diff --git a/package.json b/package.json index dfc1c269..ef01b487 100644 --- a/package.json +++ b/package.json @@ -21,16 +21,16 @@ "dependencies": {}, "devDependencies": { "babel": "^6.5.2", - "babel-core": "^6.5.2", - "babel-preset-es2015": "^6.5.0", + "babel-core": "^6.7.7", + "babel-preset-es2015": "^6.6.0", "babel-preset-react": "^6.5.0", "babel-preset-stage-0": "^6.5.0", "chai": "^3.5.0", - "eslint": "^2.2.0", + "eslint": "^2.9.0", "gulp": "^3.9.1", "gulp-babel": "^6.1.2", - "gulp-sourcemaps": "^1.6.0", + "gulp-sourcemaps": "^2.0.0-alpha", "mocha": "^2.4.5", - "rollup": "^0.25.4" + "rollup": "^0.26.1" } } From 07e6250671a97052d870a9137173d97f94ad2148 Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Sun, 8 May 2016 14:09:58 -0500 Subject: [PATCH 234/860] Added console.error calls near MatchError throws --- src/javascript/lib/core/patterns.js | 2 +- src/javascript/lib/core/patterns/defmatch.js | 33 ++----- .../lib/core/patterns/patterns/checks.js | 86 ------------------- 3 files changed, 9 insertions(+), 112 deletions(-) delete mode 100644 src/javascript/lib/core/patterns/patterns/checks.js diff --git a/src/javascript/lib/core/patterns.js b/src/javascript/lib/core/patterns.js index 81876a78..c5d537ba 100644 --- a/src/javascript/lib/core/patterns.js +++ b/src/javascript/lib/core/patterns.js @@ -1,6 +1,6 @@ /* @flow */ -import { defmatch, match, MatchError, match_no_throw, patternMap, Case, make_case } from "./patterns/defmatch"; +import { defmatch, match, MatchError, match_no_throw, Case, make_case } from "./patterns/defmatch"; import { variable, wildcard, startsWith, capture, headTail, type, bound, bitStringMatch } from "./patterns/types"; diff --git a/src/javascript/lib/core/patterns/defmatch.js b/src/javascript/lib/core/patterns/defmatch.js index 28400f24..3d9802a2 100644 --- a/src/javascript/lib/core/patterns/defmatch.js +++ b/src/javascript/lib/core/patterns/defmatch.js @@ -53,6 +53,7 @@ export function defmatch(...cases: Array): Function { } } + console.error('No match for:', args); throw new MatchError(args); }; } @@ -99,35 +100,17 @@ export function match(pattern: any, expr: any, guard: Function = () => true): Ar if (processedPattern(expr, result) && guard.apply(this, result)){ return result; }else{ + console.error('No match for:', args); throw new MatchError(expr); } } export function match_no_throw(pattern: any, expr: any, guard: Function = () => true): ?Array { - try{ - return match(pattern, expr, guard); - }catch(e){ - if(e instanceof MatchError || e.message.startsWith('No match for:')){ - return null; - } - - throw e; - } -} - -export function patternMap(collection: Array, pattern: any, fun: Function, guard: Function = () => true): Array { - let ret = []; - - for(let elem of collection){ - try{ - let result = fun.apply(this, match(pattern, elem, guard)); - ret = ret.concat(result); - }catch(e){ - if(!(e instanceof MatchError)){ - throw e; - } - } + let result = []; + let processedPattern = buildMatch(pattern); + if (processedPattern(expr, result) && guard.apply(this, result)){ + return result; + }else{ + return null; } - - return ret; } diff --git a/src/javascript/lib/core/patterns/patterns/checks.js b/src/javascript/lib/core/patterns/patterns/checks.js deleted file mode 100644 index 1840e5c4..00000000 --- a/src/javascript/lib/core/patterns/patterns/checks.js +++ /dev/null @@ -1,86 +0,0 @@ -/* @flow */ - -import { Variable, Wildcard, HeadTail, Capture, Type, StartsWith, Bound } from "./types"; - -function is_number(value: any): boolean { - return typeof value === 'number'; -} - -function is_string(value: any): boolean{ - return typeof value === 'string'; -} - -function is_boolean(value: any): boolean { - return typeof value === 'boolean'; -} - -function is_symbol(value: any): boolean { - return typeof value === 'symbol'; -} - -function is_null(value: any): boolean { - return value === null; -} - -function is_undefined(value: any): boolean { - return typeof value === 'undefined'; -} - -function is_function(value: any): boolean { - return Object.prototype.toString.call(value) == '[object Function]'; -} - -function is_variable(value: any): boolean { - return value instanceof Variable; -} - -function is_wildcard(value: any): boolean { - return value instanceof Wildcard; -} - -function is_headTail(value: any): boolean { - return value instanceof HeadTail; -} - -function is_capture(value: any): boolean { - return value instanceof Capture; -} - -function is_type(value: any): boolean { - return value instanceof Type; -} - -function is_startsWith(value: any): boolean { - return value instanceof StartsWith; -} - -function is_bound(value: any): boolean { - return value instanceof Bound; -} - -function is_object(value: any): boolean { - return typeof value === 'object'; -} - -function is_array(value: any): boolean { - return Array.isArray(value); -} - -export default { - is_number, - is_string, - is_boolean, - is_symbol, - is_null, - is_undefined, - is_function, - is_variable, - is_wildcard, - is_headTail, - is_capture, - is_type, - is_startsWith, - is_bound, - is_object, - is_array -}; From bb67ae863a667510d7be06aa913aefa5fb019c01 Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Sun, 8 May 2016 14:25:49 -0500 Subject: [PATCH 235/860] New dev version --- CHANGELOG.md | 2 ++ mix.exs | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 71d0ffa2..e4e1c8f0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,5 @@ +# v0.20.0-dev + # v0.19.0 * Enhancements * Added elixir_script mix compiler diff --git a/mix.exs b/mix.exs index 45ade4b7..a4aa5d90 100644 --- a/mix.exs +++ b/mix.exs @@ -4,7 +4,7 @@ defmodule ElixirScript.Mixfile do def project do [ app: :elixir_script, - version: "0.19.0", + version: "0.20.0-dev", elixir: "~> 1.0", escript: escript_config, deps: deps, From 3f727acf2cc4f71a673d8c1adbf6183efac73a67 Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Sat, 14 May 2016 13:00:51 -0500 Subject: [PATCH 236/860] Only acting on changes in the input folder --- lib/elixir_script/watcher.ex | 24 ++++++++++++++++++++++-- 1 file changed, 22 insertions(+), 2 deletions(-) diff --git a/lib/elixir_script/watcher.ex b/lib/elixir_script/watcher.ex index 75a24edf..85471593 100644 --- a/lib/elixir_script/watcher.ex +++ b/lib/elixir_script/watcher.ex @@ -13,8 +13,28 @@ defmodule ElixirScript.Watcher do end def handle_info({_pid, {:fs, :file_event}, {path, event}}, state) do - Logger.debug "File changed: #{path}" - ElixirScript.compile_path(state[:input], state[:options]) + + try do + if input_changed?(to_string(path), state) do + Logger.debug "Event: #{inspect event} Path: #{path}" + ElixirScript.compile_path(state[:input], state[:options]) + end + rescue + x -> + Logger.error(x.message) + end + {:noreply, state} end + + defp input_changed?(path, state) do + file = Path.basename(path) + + case file do + "." <> _ -> + false + _ -> + path == Path.absname(Path.join([state[:input], file])) + end + end end From 30dd2a15ed2633ad4ad890c1ad4a8a47612587a0 Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Sat, 14 May 2016 13:13:59 -0500 Subject: [PATCH 237/860] Added elixirscript.watch mix command --- lib/mix/tasks/elixirscript.watch.ex | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) create mode 100644 lib/mix/tasks/elixirscript.watch.ex diff --git a/lib/mix/tasks/elixirscript.watch.ex b/lib/mix/tasks/elixirscript.watch.ex new file mode 100644 index 00000000..6dd9cbe7 --- /dev/null +++ b/lib/mix/tasks/elixirscript.watch.ex @@ -0,0 +1,22 @@ +defmodule Mix.Tasks.Elixirscript.Watch do + use Mix.Task + + @shortdoc "Watches ElixirScript files for changes" + + def run(_) do + Mix.Task.run "app.start" + + elixirscript_config = get_elixirscript_config() + input_path = Keyword.fetch!(elixirscript_config, :input) + output_path = Keyword.fetch!(elixirscript_config, :output) + {:ok, pid} = ElixirScript.Watcher.start_link(input_path, %{ output: output_path }) + + :timer.sleep :infinity + end + + defp get_elixirscript_config() do + config = Mix.Project.config + Keyword.fetch!(config, :elixir_script) + end + +end From 253d9ee09c886beafa3efefca35420b20bc6d95c Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Sat, 14 May 2016 13:47:07 -0500 Subject: [PATCH 238/860] Removed dev from version --- CHANGELOG.md | 5 ++++- mix.exs | 2 +- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index e4e1c8f0..ee79e8ea 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,4 +1,7 @@ -# v0.20.0-dev +# v0.20.0 +* Enhancements + * Add `ElixirScript.Watcher` module and `elixirscript.watch` mix task + * Add logging MatchError exceptions to better show terms that don't match # v0.19.0 * Enhancements diff --git a/mix.exs b/mix.exs index 83f9c4f8..9283606a 100644 --- a/mix.exs +++ b/mix.exs @@ -4,7 +4,7 @@ defmodule ElixirScript.Mixfile do def project do [ app: :elixir_script, - version: "0.20.0-dev", + version: "0.20.0", elixir: "~> 1.0", escript: escript_config, deps: deps, From ad63eaf00286b83437c5557d6cae5d2a91945574 Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Sat, 14 May 2016 13:50:16 -0500 Subject: [PATCH 239/860] Updated documentation --- lib/elixir_script/watcher.ex | 5 +++++ lib/mix/tasks/compile.elixir_script.ex | 2 +- lib/mix/tasks/elixirscript.watch.ex | 19 +++++++++++++++++++ 3 files changed, 25 insertions(+), 1 deletion(-) diff --git a/lib/elixir_script/watcher.ex b/lib/elixir_script/watcher.ex index 85471593..436a03ed 100644 --- a/lib/elixir_script/watcher.ex +++ b/lib/elixir_script/watcher.ex @@ -2,6 +2,11 @@ defmodule ElixirScript.Watcher do use GenServer require Logger + @moduledoc """ + Watches the input folder for changes and calls the ElixirScript compiler + """ + + def start_link(input, options) do GenServer.start_link(__MODULE__, [input: input, options: options]) end diff --git a/lib/mix/tasks/compile.elixir_script.ex b/lib/mix/tasks/compile.elixir_script.ex index 7a31da00..cbafeb5d 100644 --- a/lib/mix/tasks/compile.elixir_script.ex +++ b/lib/mix/tasks/compile.elixir_script.ex @@ -4,7 +4,7 @@ defmodule Mix.Tasks.Compile.ElixirScript do @moduledoc """ Mix compiler to allow mix to compile Elixirscript source files into JavaScript - Looks for an `elixirscript` key in your mix project config + Looks for an `elixir_script` key in your mix project config def project do [ diff --git a/lib/mix/tasks/elixirscript.watch.ex b/lib/mix/tasks/elixirscript.watch.ex index 6dd9cbe7..1208811f 100644 --- a/lib/mix/tasks/elixirscript.watch.ex +++ b/lib/mix/tasks/elixirscript.watch.ex @@ -3,6 +3,25 @@ defmodule Mix.Tasks.Elixirscript.Watch do @shortdoc "Watches ElixirScript files for changes" + @moduledoc """ + Watches ElixirScript files for changes + + Looks for the `elixir_script` key in your mix project config + + def project do + [ + app: :my_app, + version: "0.1.0", + elixir: "~> 1.0", + deps: deps, + elixir_script: [ input: "src/exjs", output: "dest/js"], + compilers: [:elixir_script] ++ Mix.compilers + ] + end + """ + + + def run(_) do Mix.Task.run "app.start" From 7250c940c2b67ab34dce140c80c96c0ae3d9c5de Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Sat, 14 May 2016 13:56:47 -0500 Subject: [PATCH 240/860] Update README.md --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index 65589b4f..6425745d 100644 --- a/README.md +++ b/README.md @@ -58,6 +58,7 @@ Please check the [CONTRIBUTING.md](CONTRIBUTING.md) ### Example projects +* [hello](https://github.com/bryanjos/hello) Shows using Phoenix + Elixirscript with file watching * [elixirscript frontend boilerplate](https://github.com/bryanjos/elixirscript-project-boilerplate) A boilerplate project for elixirscript frontends * [todo-elixirscript](https://github.com/bryanjos/todo-elixirscript) A Todo App built with Elixirscript and Phoenix * [phoenix_chat_example](https://github.com/bryanjos/phoenix_chat_example) The Phoenix Chat App using ElixirScript. From d9016cc89518b0056b00ce758f15cf68be505ddc Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Wed, 25 May 2016 20:49:43 -0500 Subject: [PATCH 241/860] Refactored Env to LexicalScope. ElixirScript.Macro.Env now fully represents Macro.Env fields --- CHANGELOG.md | 4 + lib/elixir_script.ex | 2 +- lib/elixir_script/cli.ex | 1 - lib/elixir_script/module_systems.ex | 2 +- lib/elixir_script/module_systems/common.ex | 3 +- lib/elixir_script/module_systems/es6.ex | 2 +- lib/elixir_script/prelude/macro/env.ex | 8 +- lib/elixir_script/translator.ex | 38 ++++---- lib/elixir_script/translator/function.ex | 2 +- .../translator/{env.ex => lexical_scope.ex} | 94 +++++++++++++++++-- .../translator/pattern_matching.ex | 4 +- lib/elixir_script/translator/struct.ex | 4 +- mix.exs | 2 +- test/translator/pattern_matching_test.exs | 44 ++++----- 14 files changed, 142 insertions(+), 68 deletions(-) rename lib/elixir_script/translator/{env.ex => lexical_scope.ex} (73%) diff --git a/CHANGELOG.md b/CHANGELOG.md index ee79e8ea..28ff6891 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,7 @@ +# v0.21.0-dev +* Fixed + * Scoping on `fn` and `def` + # v0.20.0 * Enhancements * Add `ElixirScript.Watcher` module and `elixirscript.watch` mix task diff --git a/lib/elixir_script.ex b/lib/elixir_script.ex index 957770be..eec1d8c1 100644 --- a/lib/elixir_script.ex +++ b/lib/elixir_script.ex @@ -242,7 +242,7 @@ defmodule ElixirScript do end) |> Enum.map(fn ast -> spawn_link fn -> - env = ElixirScript.Translator.Env.module_env(ast.name, Utils.name_to_js_file_name(ast.name) <> ".js", state.compiler_opts.env) + env = ElixirScript.Translator.LexicalScope.module_scope(ast.name, Utils.name_to_js_file_name(ast.name) <> ".js", state.compiler_opts.env) module = case ast.type do :module -> diff --git a/lib/elixir_script/cli.ex b/lib/elixir_script/cli.ex index d673020c..bbc7104d 100644 --- a/lib/elixir_script/cli.ex +++ b/lib/elixir_script/cli.ex @@ -63,7 +63,6 @@ defmodule ElixirScript.CLI do end def process({ input, options }) do - IO.inspect(options) if options_contains_unknown_values(options) do process(:help) else diff --git a/lib/elixir_script/module_systems.ex b/lib/elixir_script/module_systems.ex index e2ea1e8e..efa8ca7f 100644 --- a/lib/elixir_script/module_systems.ex +++ b/lib/elixir_script/module_systems.ex @@ -12,7 +12,7 @@ defmodule ElixirScript.ModuleSystems do module_system.import_module(module_name, from, env) end - def import_module(module_name, %ElixirScript.Macro.Env{} = env) do + def import_module(module_name, %ElixirScript.Translator.LexicalScope{} = env) do module_system.import_module(module_name, env) end diff --git a/lib/elixir_script/module_systems/common.ex b/lib/elixir_script/module_systems/common.ex index c1a4c140..6d227420 100644 --- a/lib/elixir_script/module_systems/common.ex +++ b/lib/elixir_script/module_systems/common.ex @@ -1,7 +1,6 @@ defmodule ElixirScript.ModuleSystems.Common do alias ESTree.Tools.Builder, as: JS alias ElixirScript.Translator - alias ElixirScript.Translator.Utils def import_module(module_names, from, env) when is_list(module_names) do assignment_properties = Enum.map(module_names, fn(x) -> @@ -15,7 +14,7 @@ defmodule ElixirScript.ModuleSystems.Common do do_import_module(Translator.translate!(module_name, env), from) end - def import_module(module_name, %ElixirScript.Macro.Env{} = env) do + def import_module(module_name, %ElixirScript.Translator.LexicalScope{} = env) do {from, _ } = Code.eval_quoted(module_name) do_import_module(Translator.translate!(module_name, env), Macro.underscore(from)) end diff --git a/lib/elixir_script/module_systems/es6.ex b/lib/elixir_script/module_systems/es6.ex index 1a706e7c..606ae302 100644 --- a/lib/elixir_script/module_systems/es6.ex +++ b/lib/elixir_script/module_systems/es6.ex @@ -22,7 +22,7 @@ defmodule ElixirScript.ModuleSystems.ES6 do do_import_module([import_specifier], from) end - def import_module(module_name, %ElixirScript.Macro.Env{} = env) do + def import_module(module_name, %ElixirScript.Translator.LexicalScope{} = env) do import_specifier = JS.import_default_specifier( Translator.translate!(module_name, env), Translator.translate!(module_name, env) diff --git a/lib/elixir_script/prelude/macro/env.ex b/lib/elixir_script/prelude/macro/env.ex index 05d74707..9e2615e6 100644 --- a/lib/elixir_script/prelude/macro/env.ex +++ b/lib/elixir_script/prelude/macro/env.ex @@ -13,9 +13,7 @@ defmodule ElixirScript.Macro.Env do context_modules: [atom], vars: [{atom, atom | non_neg_integer}], export_vars: [{atom, atom | non_neg_integer}] | nil, - lexical_tracker: nil, - caller: t | nil, - env: nil + lexical_tracker: nil } defstruct [ @@ -32,8 +30,6 @@ defmodule ElixirScript.Macro.Env do context_modules: [], vars: [], export_vars: nil, - lexical_tracker: nil, - caller: nil, - env: nil + lexical_tracker: nil ] end diff --git a/lib/elixir_script/translator.ex b/lib/elixir_script/translator.ex index 884d9026..0b407f37 100644 --- a/lib/elixir_script/translator.ex +++ b/lib/elixir_script/translator.ex @@ -315,14 +315,14 @@ defmodule ElixirScript.Translator do end defp do_translate({:__CALLER__, _, _expressions }, env) do - env_to_translate = %{ env.caller | vars: Enum.map(env.caller.vars, fn({key, _}) -> {key, nil} end), caller: nil } + env_to_translate = ElixirScript.Translator.LexicalScope.caller(env) quoted = Macro.escape(env_to_translate) translate(quoted, env) end defp do_translate({:__ENV__, _, _expressions }, env) do - env_to_translate = %{ env | vars: Enum.map(env.vars, fn({key, _}) -> {key, nil} end), caller: nil } + env_to_translate = ElixirScript.Translator.LexicalScope.env(env) quoted = Macro.escape(env_to_translate) translate(quoted, env) @@ -341,7 +341,7 @@ defmodule ElixirScript.Translator do full_module_name = { :__aliases__, context, head_import_name ++ name } module_name = Utils.quoted_to_name(full_module_name) - ElixirScript.Translator.Env.add_import(acc, module_name) + ElixirScript.Translator.LexicalScope.add_import(acc, module_name) end) { %ElixirScript.Translator.Empty{}, env } @@ -351,14 +351,14 @@ defmodule ElixirScript.Translator do defp do_translate({:import, _, [{:__aliases__, _, _} = module_name]}, env) do module_name = Utils.quoted_to_name(module_name) - env = ElixirScript.Translator.Env.add_import(env, module_name) + env = ElixirScript.Translator.LexicalScope.add_import(env, module_name) { %ElixirScript.Translator.Empty{}, env } end defp do_translate({:import, _, [{:__aliases__, _, _} = module_name, options]}, env) do module_name = Utils.quoted_to_name(module_name) - env = ElixirScript.Translator.Env.add_import(env, module_name, options) + env = ElixirScript.Translator.LexicalScope.add_import(env, module_name, options) { %ElixirScript.Translator.Empty{}, env } end @@ -370,7 +370,7 @@ defmodule ElixirScript.Translator do module_name = Utils.quoted_to_name(full_module_name) alias_name = Utils.quoted_to_name({:__aliases__, [], [List.last(name)] }) - ElixirScript.Translator.Env.add_alias(acc, module_name, alias_name) + ElixirScript.Translator.LexicalScope.add_alias(acc, module_name, alias_name) end) { %ElixirScript.Translator.Empty{}, env } @@ -383,7 +383,7 @@ defmodule ElixirScript.Translator do module_name = Utils.quoted_to_name(module_name) alias_name = Utils.quoted_to_name({:__aliases__, [], name }) - env = ElixirScript.Translator.Env.add_alias(env, module_name, alias_name) + env = ElixirScript.Translator.LexicalScope.add_alias(env, module_name, alias_name) { %ElixirScript.Translator.Empty{}, env } end @@ -391,7 +391,7 @@ defmodule ElixirScript.Translator do module_name = Utils.quoted_to_name(module_name) alias_name = Utils.quoted_to_name(alias_name) - env = ElixirScript.Translator.Env.add_alias(env, module_name, alias_name) + env = ElixirScript.Translator.LexicalScope.add_alias(env, module_name, alias_name) { %ElixirScript.Translator.Empty{}, env } end @@ -400,7 +400,7 @@ defmodule ElixirScript.Translator do full_module_name = { :__aliases__, context, head_require_name ++ name } module_name = Utils.quoted_to_name(full_module_name) - ElixirScript.Translator.Env.add_require(acc, module_name) + ElixirScript.Translator.LexicalScope.add_require(acc, module_name) end) { %ElixirScript.Translator.Empty{}, env } @@ -408,7 +408,7 @@ defmodule ElixirScript.Translator do defp do_translate({:require, _, [{:__aliases__, _, _} = module_name] }, env) do module_name = Utils.quoted_to_name(module_name) - env = ElixirScript.Translator.Env.add_require(env, module_name) + env = ElixirScript.Translator.LexicalScope.add_require(env, module_name) { %ElixirScript.Translator.Empty{}, env } end @@ -416,7 +416,7 @@ defmodule ElixirScript.Translator do module_name = Utils.quoted_to_name(module_name) alias_name = Utils.quoted_to_name(alias_name) - env = ElixirScript.Translator.Env.add_require(env, module_name, alias_name) + env = ElixirScript.Translator.LexicalScope.add_require(env, module_name, alias_name) { %ElixirScript.Translator.Empty{}, env } end @@ -433,7 +433,7 @@ defmodule ElixirScript.Translator do end defp do_translate({:fn, _, clauses}, env) do - env = ElixirScript.Translator.Env.function_env(env, nil) + env = ElixirScript.Translator.LexicalScope.function_scope(env, nil) Function.make_anonymous_function(clauses, env) end @@ -539,8 +539,8 @@ defmodule ElixirScript.Translator do cond do name_arity in module.functions or name_arity in module.private_functions -> Function.make_function_call(name, params, env) - ElixirScript.Translator.Env.find_module(env, name_arity) -> - imported_module_name = ElixirScript.Translator.Env.find_module(env, name_arity) + ElixirScript.Translator.LexicalScope.find_module(env, name_arity) -> + imported_module_name = ElixirScript.Translator.LexicalScope.find_module(env, name_arity) Function.make_function_call(imported_module_name, name, params, env) true -> Function.make_function_call(name, params, env) @@ -553,13 +553,13 @@ defmodule ElixirScript.Translator do defp do_translate({ name, _, params }, env) when is_atom(params) do cond do - ElixirScript.Translator.Env.has_var?(env, name) -> + ElixirScript.Translator.LexicalScope.has_var?(env, name) -> name = Utils.filter_name(name) { Primitive.make_identifier(name), env } has_function?(env.module, {name, 0}) -> Function.make_function_call(name, [], env) - ElixirScript.Translator.Env.find_module(env, {name, 0}) -> - imported_module_name = ElixirScript.Translator.Env.find_module(env, {name, 0}) + ElixirScript.Translator.LexicalScope.find_module(env, {name, 0}) -> + imported_module_name = ElixirScript.Translator.LexicalScope.find_module(env, {name, 0}) Function.make_function_call(imported_module_name, name, params, env) true -> name = Utils.filter_name(name) @@ -574,8 +574,8 @@ defmodule ElixirScript.Translator do candiate_module_name = Utils.quoted_to_name(module_name) |> ElixirScript.Translator.State.get_module_name - if ElixirScript.Translator.Env.get_module_name(env, candiate_module_name) in ElixirScript.Translator.State.list_module_names() do - ElixirScript.Translator.Env.get_module_name(env, candiate_module_name) + if ElixirScript.Translator.LexicalScope.get_module_name(env, candiate_module_name) in ElixirScript.Translator.State.list_module_names() do + ElixirScript.Translator.LexicalScope.get_module_name(env, candiate_module_name) else module_name end diff --git a/lib/elixir_script/translator/function.ex b/lib/elixir_script/translator/function.ex index 906b3e3e..ef93d3c8 100644 --- a/lib/elixir_script/translator/function.ex +++ b/lib/elixir_script/translator/function.ex @@ -67,7 +67,7 @@ defmodule ElixirScript.Translator.Function do end defp process_function_body(params, body, env, name, guards \\ nil) do - env = ElixirScript.Translator.Env.function_env(env, {name, get_arity(params)}) + env = ElixirScript.Translator.LexicalScope.function_scope(env, {name, get_arity(params)}) { patterns, params, env } = process_params(params, env) { body, _ } = make_function_body(body, env) diff --git a/lib/elixir_script/translator/env.ex b/lib/elixir_script/translator/lexical_scope.ex similarity index 73% rename from lib/elixir_script/translator/env.ex rename to lib/elixir_script/translator/lexical_scope.ex index aa5e7d67..0e4af785 100644 --- a/lib/elixir_script/translator/env.ex +++ b/lib/elixir_script/translator/lexical_scope.ex @@ -1,9 +1,85 @@ -defmodule ElixirScript.Translator.Env do +defmodule ElixirScript.Translator.LexicalScope do @moduledoc false - def module_env(ElixirScript.Temp, filename, env) do + @type t :: %ElixirScript.Translator.LexicalScope{ + module: atom, + file: binary, + line: non_neg_integer, + function: { atom, non_neg_integer } | nil, + context: :match | :guard | nil, + aliases: [{atom, atom}], + requires: [atom], + functions: [{atom, [{ atom, non_neg_integer }]}], + macros: [{atom, [{ atom, non_neg_integer }]}], + macro_aliases: [{atom, {integer, atom}}], + context_modules: [atom], + vars: [{atom, atom | non_neg_integer}], + export_vars: [{atom, atom | non_neg_integer}] | nil, + lexical_tracker: nil, + caller: t | nil, + env: nil + } + + defstruct [ + module: nil, + file: nil, + line: 0, + function: nil, + context: nil, + aliases: [], + requires: [], + functions: [], + macros: [], + macro_aliases: [], + context_modules: [], + vars: [], + export_vars: nil, + lexical_tracker: nil, + caller: nil, + env: nil + ] + + def env(scope) do + %Macro.Env{ + module: scope.module, + file: scope.file, + line: scope.line, + function: scope.function, + context: scope.context, + aliases: scope.aliases, + requires: scope.requires, + functions: scope.functions, + macros: scope.macros, + macro_aliases: scope.macro_aliases, + context_modules: scope.context_modules, + vars: Enum.map(scope.vars, fn({key, _}) -> {key, nil} end), + export_vars: scope.export_vars, + lexical_tracker: scope.lexical_tracker + } + end + + def caller(scope) do + %Macro.Env{ + module: scope.caller.module, + file: scope.caller.file, + line: scope.caller.line, + function: scope.caller.function, + context: scope.caller.context, + aliases: scope.caller.aliases, + requires: scope.caller.requires, + functions: scope.caller.functions, + macros: scope.caller.macros, + macro_aliases: scope.caller.macro_aliases, + context_modules: scope.caller.context_modules, + vars: Enum.map(scope.vars, fn({key, _}) -> {key, nil} end), + export_vars: scope.caller.export_vars, + lexical_tracker: scope.caller.lexical_tracker + } + end + + def module_scope(ElixirScript.Temp, filename, env) do - env = %ElixirScript.Macro.Env { + env = %ElixirScript.Translator.LexicalScope { module: ElixirScript.Temp, file: filename, requires: [], functions: [], env: env @@ -12,10 +88,10 @@ defmodule ElixirScript.Translator.Env do add_import(env, ElixirScript.Kernel) end - def module_env(module_name, filename, env) do + def module_scope(module_name, filename, env) do module = ElixirScript.Translator.State.get_module(module_name) - env = %ElixirScript.Macro.Env { + env = %ElixirScript.Translator.LexicalScope { module: module_name, file: filename, requires: [], functions: [{ module.name, module.functions}], env: env @@ -24,12 +100,12 @@ defmodule ElixirScript.Translator.Env do add_import(env, ElixirScript.Kernel) end - def function_env(env, { _, _ } = func) do - %{ env | function: func, caller: env } + def function_scope(env, { _, _ } = func) do + %{ env | function: func, caller: env, vars: [] } end - def function_env(env, nil) do - %{ env | function: nil, caller: env, vars: [] } + def function_scope(env, nil) do + %{ env | function: nil, caller: env } end def find_module(env, name_arity) do diff --git a/lib/elixir_script/translator/pattern_matching.ex b/lib/elixir_script/translator/pattern_matching.ex index 44ea9d25..9d19167c 100644 --- a/lib/elixir_script/translator/pattern_matching.ex +++ b/lib/elixir_script/translator/pattern_matching.ex @@ -133,8 +133,8 @@ defmodule ElixirScript.Translator.PatternMatching do { param, env } (%ESTree.Identifier{} = param, env) -> - env = ElixirScript.Translator.Env.add_var(env, param.name) - new_name = ElixirScript.Translator.Env.get_var(env, param.name) + env = ElixirScript.Translator.LexicalScope.add_var(env, param.name) + new_name = ElixirScript.Translator.LexicalScope.get_var(env, param.name) { %{ param | name: new_name }, env } diff --git a/lib/elixir_script/translator/struct.ex b/lib/elixir_script/translator/struct.ex index e575653f..de4beb56 100644 --- a/lib/elixir_script/translator/struct.ex +++ b/lib/elixir_script/translator/struct.ex @@ -9,8 +9,8 @@ defmodule ElixirScript.Translator.Struct do candiate_module_name = Utils.quoted_to_name(module_name) |> ElixirScript.Translator.State.get_module_name - if ElixirScript.Translator.Env.get_module_name(env, candiate_module_name) in ElixirScript.Translator.State.list_module_names() do - name = ElixirScript.Translator.Env.get_module_name(env, candiate_module_name) + if ElixirScript.Translator.LexicalScope.get_module_name(env, candiate_module_name) in ElixirScript.Translator.State.list_module_names() do + name = ElixirScript.Translator.LexicalScope.get_module_name(env, candiate_module_name) JS.member_expression( JS.identifier(Utils.name_to_js_name(name)), diff --git a/mix.exs b/mix.exs index 9283606a..7ad736d6 100644 --- a/mix.exs +++ b/mix.exs @@ -4,7 +4,7 @@ defmodule ElixirScript.Mixfile do def project do [ app: :elixir_script, - version: "0.20.0", + version: "0.21.0-dev", elixir: "~> 1.0", escript: escript_config, deps: deps, diff --git a/test/translator/pattern_matching_test.exs b/test/translator/pattern_matching_test.exs index 7a9f0588..ed1487cf 100644 --- a/test/translator/pattern_matching_test.exs +++ b/test/translator/pattern_matching_test.exs @@ -18,7 +18,7 @@ defmodule ElixirScript.Translator.PatternMatching.Test do test "match wildcard" do params = [{:_, [], Test}] - result = PatternMatching.build_match(params, ElixirScript.Translator.Env.module_env(ElixirScript.Temp, "temp.ex", ElixirScript.custom_env) ) + result = PatternMatching.build_match(params, ElixirScript.Translator.LexicalScope.module_scope(ElixirScript.Temp, "temp.ex", ElixirScript.custom_env) ) expected_result = { [PatternMatching.wildcard], [JS.identifier(:undefined)] } assert result == expected_result @@ -26,7 +26,7 @@ defmodule ElixirScript.Translator.PatternMatching.Test do test "match one identifier param" do params = [{:a, [], Test}] - result = PatternMatching.build_match(params, ElixirScript.Translator.Env.module_env(ElixirScript.Temp, "temp.ex", ElixirScript.custom_env) ) + result = PatternMatching.build_match(params, ElixirScript.Translator.LexicalScope.module_scope(ElixirScript.Temp, "temp.ex", ElixirScript.custom_env) ) expected_result = {[PatternMatching.parameter], [JS.identifier("a")]} assert result == expected_result @@ -34,7 +34,7 @@ defmodule ElixirScript.Translator.PatternMatching.Test do test "match multiple identifier params" do params = [{:a, [], Test}, {:b, [], Test}, {:c, [], Test}] - result = PatternMatching.build_match(params, ElixirScript.Translator.Env.module_env(ElixirScript.Temp, "temp.ex", ElixirScript.custom_env) ) + result = PatternMatching.build_match(params, ElixirScript.Translator.LexicalScope.module_scope(ElixirScript.Temp, "temp.ex", ElixirScript.custom_env) ) expected_result = { List.duplicate(PatternMatching.parameter, 3), [JS.identifier("a"), JS.identifier("b"), JS.identifier("c")] @@ -45,7 +45,7 @@ defmodule ElixirScript.Translator.PatternMatching.Test do test "match head and tail param" do params = [[{:|, [], [{:head, [], Elixir}, {:tail, [], Elixir}]}]] - result = PatternMatching.build_match(params, ElixirScript.Translator.Env.module_env(ElixirScript.Temp, "temp.ex", ElixirScript.custom_env) ) + result = PatternMatching.build_match(params, ElixirScript.Translator.LexicalScope.module_scope(ElixirScript.Temp, "temp.ex", ElixirScript.custom_env) ) expected_result = { [PatternMatching.head_tail(PatternMatching.parameter, PatternMatching.parameter)], [JS.identifier("head"), JS.identifier("tail")] @@ -56,7 +56,7 @@ defmodule ElixirScript.Translator.PatternMatching.Test do test "match prefix param" do params = [{:<>, [context: Elixir, import: Elixir.Kernel], ["Bearer ", {:token, [], Elixir}]}] - result = PatternMatching.build_match(params, ElixirScript.Translator.Env.module_env(ElixirScript.Temp, "temp.ex", ElixirScript.custom_env) ) + result = PatternMatching.build_match(params, ElixirScript.Translator.LexicalScope.module_scope(ElixirScript.Temp, "temp.ex", ElixirScript.custom_env) ) expected_result = { [PatternMatching.starts_with("Bearer ")], [JS.identifier("token")] @@ -67,7 +67,7 @@ defmodule ElixirScript.Translator.PatternMatching.Test do test "match list" do params = [[{:a, [], Elixir}, {:b, [], Elixir}, {:c, [], Elixir}]] - result = PatternMatching.build_match(params, ElixirScript.Translator.Env.module_env(ElixirScript.Temp, "temp.ex", ElixirScript.custom_env) ) + result = PatternMatching.build_match(params, ElixirScript.Translator.LexicalScope.module_scope(ElixirScript.Temp, "temp.ex", ElixirScript.custom_env) ) expected_result = { [Primitive.make_list_no_translate(List.duplicate(PatternMatching.parameter, 3))], [JS.identifier("a"), JS.identifier("b"), JS.identifier("c")] @@ -78,7 +78,7 @@ defmodule ElixirScript.Translator.PatternMatching.Test do test "match list with a literal" do params = [[1, {:b, [], Elixir}, {:c, [], Elixir}]] - result = PatternMatching.build_match(params, ElixirScript.Translator.Env.module_env(ElixirScript.Temp, "temp.ex", ElixirScript.custom_env) ) + result = PatternMatching.build_match(params, ElixirScript.Translator.LexicalScope.module_scope(ElixirScript.Temp, "temp.ex", ElixirScript.custom_env) ) expected_result = { [Primitive.make_list_no_translate([JS.literal(1), PatternMatching.parameter, PatternMatching.parameter])], [JS.identifier("b"), JS.identifier("c")] @@ -89,7 +89,7 @@ defmodule ElixirScript.Translator.PatternMatching.Test do test "match number" do params = [1] - result = PatternMatching.build_match(params, ElixirScript.Translator.Env.module_env(ElixirScript.Temp, "temp.ex", ElixirScript.custom_env) ) + result = PatternMatching.build_match(params, ElixirScript.Translator.LexicalScope.module_scope(ElixirScript.Temp, "temp.ex", ElixirScript.custom_env) ) expected_result = { [JS.literal(1)], [] @@ -100,7 +100,7 @@ defmodule ElixirScript.Translator.PatternMatching.Test do test "match struct pattern" do params = [{:%, [], [{:__aliases__, [alias: false], [:Hello]}, {:%{}, [], []}]}] - result = PatternMatching.build_match(params, ElixirScript.Translator.Env.module_env(ElixirScript.Temp, "temp.ex", ElixirScript.custom_env) ) + result = PatternMatching.build_match(params, ElixirScript.Translator.LexicalScope.module_scope(ElixirScript.Temp, "temp.ex", ElixirScript.custom_env) ) expected_result = { [PatternMatching.type(JS.identifier(:Hello), JS.object_expression([]))], [] @@ -111,10 +111,10 @@ defmodule ElixirScript.Translator.PatternMatching.Test do test "match struct pattern with property" do params = [{:%, [], [{:__aliases__, [alias: false], [:Hello]}, {:%{}, [], [key: 1]}]}] - result = PatternMatching.build_match(params, ElixirScript.Translator.Env.module_env(ElixirScript.Temp, "temp.ex", ElixirScript.custom_env) ) + result = PatternMatching.build_match(params, ElixirScript.Translator.LexicalScope.module_scope(ElixirScript.Temp, "temp.ex", ElixirScript.custom_env) ) expected_result = { [PatternMatching.type(JS.identifier(:Hello), JS.object_expression([ - Map.make_property(Translator.translate!(:key, ElixirScript.Translator.Env.module_env(ElixirScript.Temp, "temp.ex", ElixirScript.custom_env) ), Translator.translate!(1, ElixirScript.Translator.Env.module_env(ElixirScript.Temp, "temp.ex", ElixirScript.custom_env) )) + Map.make_property(Translator.translate!(:key, ElixirScript.Translator.LexicalScope.module_scope(ElixirScript.Temp, "temp.ex", ElixirScript.custom_env) ), Translator.translate!(1, ElixirScript.Translator.LexicalScope.module_scope(ElixirScript.Temp, "temp.ex", ElixirScript.custom_env) )) ])) ], [] @@ -125,10 +125,10 @@ defmodule ElixirScript.Translator.PatternMatching.Test do test "match struct pattern with property param" do params = [{:%, [], [{:__aliases__, [alias: false], [:Hello]}, {:%{}, [], [key: {:key, [], Elixir }]}]}] - result = PatternMatching.build_match(params, ElixirScript.Translator.Env.module_env(ElixirScript.Temp, "temp.ex", ElixirScript.custom_env) ) + result = PatternMatching.build_match(params, ElixirScript.Translator.LexicalScope.module_scope(ElixirScript.Temp, "temp.ex", ElixirScript.custom_env) ) expected_result = { [PatternMatching.type(JS.identifier(:Hello), JS.object_expression([ - Map.make_property(Translator.translate!(:key, ElixirScript.Translator.Env.module_env(ElixirScript.Temp, "temp.ex", ElixirScript.custom_env) ), PatternMatching.parameter) + Map.make_property(Translator.translate!(:key, ElixirScript.Translator.LexicalScope.module_scope(ElixirScript.Temp, "temp.ex", ElixirScript.custom_env) ), PatternMatching.parameter) ])) ], [JS.identifier("key")] @@ -139,7 +139,7 @@ defmodule ElixirScript.Translator.PatternMatching.Test do test "capture parameter when assigning it" do params = [{:=, [], [1, {:a, [], Elixir}]}] - result = PatternMatching.build_match(params, ElixirScript.Translator.Env.module_env(ElixirScript.Temp, "temp.ex", ElixirScript.custom_env) ) + result = PatternMatching.build_match(params, ElixirScript.Translator.LexicalScope.module_scope(ElixirScript.Temp, "temp.ex", ElixirScript.custom_env) ) expected_result = { [PatternMatching.capture(JS.literal(1))], [JS.identifier("a")] @@ -149,7 +149,7 @@ defmodule ElixirScript.Translator.PatternMatching.Test do params = [{:=, [], [{:a, [], Elixir}, 1]}] - result = PatternMatching.build_match(params, ElixirScript.Translator.Env.module_env(ElixirScript.Temp, "temp.ex", ElixirScript.custom_env) ) + result = PatternMatching.build_match(params, ElixirScript.Translator.LexicalScope.module_scope(ElixirScript.Temp, "temp.ex", ElixirScript.custom_env) ) expected_result = { [PatternMatching.capture(JS.literal(1))], [JS.identifier("a")] @@ -159,7 +159,7 @@ defmodule ElixirScript.Translator.PatternMatching.Test do params = [{:=, [], [{:%, [], [{:__aliases__, [alias: false], [:AStruct]}, {:%{}, [], []}]}, {:a, [], ElixirScript.Translator.Function.Test}]}] - result = PatternMatching.build_match(params, ElixirScript.Translator.Env.module_env(ElixirScript.Temp, "temp.ex", ElixirScript.custom_env) ) + result = PatternMatching.build_match(params, ElixirScript.Translator.LexicalScope.module_scope(ElixirScript.Temp, "temp.ex", ElixirScript.custom_env) ) expected_result = { [PatternMatching.capture(PatternMatching.type(JS.identifier(:AStruct), JS.object_expression([])))], [JS.identifier("a")] @@ -170,7 +170,7 @@ defmodule ElixirScript.Translator.PatternMatching.Test do test "match and assign list" do params = [{:=, [], [[{:a, [], Elixir}, {:b, [], Elixir}, {:c, [], Elixir}], {:d, [], Elixir}]}] - result = PatternMatching.build_match(params, ElixirScript.Translator.Env.module_env(ElixirScript.Temp, "temp.ex", ElixirScript.custom_env) ) + result = PatternMatching.build_match(params, ElixirScript.Translator.LexicalScope.module_scope(ElixirScript.Temp, "temp.ex", ElixirScript.custom_env) ) expected_result = { [PatternMatching.capture(Primitive.make_list_no_translate([PatternMatching.parameter, PatternMatching.parameter, PatternMatching.parameter]))], [JS.identifier("a"), JS.identifier("b"), JS.identifier("c"), JS.identifier("d")] @@ -181,7 +181,7 @@ defmodule ElixirScript.Translator.PatternMatching.Test do test "match on tuple" do params = [{:{}, [], [1, {:b, [], Elixir}, 3]}] - result = PatternMatching.build_match(params, ElixirScript.Translator.Env.module_env(ElixirScript.Temp, "temp.ex", ElixirScript.custom_env) ) + result = PatternMatching.build_match(params, ElixirScript.Translator.LexicalScope.module_scope(ElixirScript.Temp, "temp.ex", ElixirScript.custom_env) ) expected_result = { [PatternMatching.type(Primitive.tuple_class, JS.object_expression([JS.property( JS.identifier("values"), @@ -193,7 +193,7 @@ defmodule ElixirScript.Translator.PatternMatching.Test do assert result == expected_result params = [{1, {:b, [], Elixir}}] - result = PatternMatching.build_match(params, ElixirScript.Translator.Env.module_env(ElixirScript.Temp, "temp.ex", ElixirScript.custom_env) ) + result = PatternMatching.build_match(params, ElixirScript.Translator.LexicalScope.module_scope(ElixirScript.Temp, "temp.ex", ElixirScript.custom_env) ) expected_result = { [PatternMatching.type(Primitive.tuple_class, JS.object_expression([JS.property( JS.identifier("values"), @@ -207,11 +207,11 @@ defmodule ElixirScript.Translator.PatternMatching.Test do test "match on map" do params = [{:%{}, [], [which: 13]}] - result = PatternMatching.build_match(params, ElixirScript.Translator.Env.module_env(ElixirScript.Temp, "temp.ex", ElixirScript.custom_env) ) + result = PatternMatching.build_match(params, ElixirScript.Translator.LexicalScope.module_scope(ElixirScript.Temp, "temp.ex", ElixirScript.custom_env) ) expected_result = { [JS.object_expression([ - Map.make_property(Translator.translate!(:which, ElixirScript.Translator.Env.module_env(ElixirScript.Temp, "temp.ex", ElixirScript.custom_env) ), JS.literal(13)) + Map.make_property(Translator.translate!(:which, ElixirScript.Translator.LexicalScope.module_scope(ElixirScript.Temp, "temp.ex", ElixirScript.custom_env) ), JS.literal(13)) ])], [] } @@ -222,7 +222,7 @@ defmodule ElixirScript.Translator.PatternMatching.Test do test "match on bound value" do params = [{:^, [], [{:a, [], Elixir}]}] - result = PatternMatching.build_match(params, ElixirScript.Translator.Env.module_env(ElixirScript.Temp, "temp.ex", ElixirScript.custom_env) ) + result = PatternMatching.build_match(params, ElixirScript.Translator.LexicalScope.module_scope(ElixirScript.Temp, "temp.ex", ElixirScript.custom_env) ) expected_result = { [PatternMatching.bound(JS.identifier("a"))], From a6125d19c7f6b7a30cdeecd1d3ba912f12c60c28 Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Wed, 25 May 2016 21:15:04 -0500 Subject: [PATCH 242/860] Fixed undefined variable in error logging for match errors --- src/javascript/lib/core/patterns/defmatch.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/javascript/lib/core/patterns/defmatch.js b/src/javascript/lib/core/patterns/defmatch.js index 3d9802a2..b9988a27 100644 --- a/src/javascript/lib/core/patterns/defmatch.js +++ b/src/javascript/lib/core/patterns/defmatch.js @@ -100,7 +100,7 @@ export function match(pattern: any, expr: any, guard: Function = () => true): Ar if (processedPattern(expr, result) && guard.apply(this, result)){ return result; }else{ - console.error('No match for:', args); + console.error('No match for:', expr); throw new MatchError(expr); } } From ec26884f4fb478c59431b0fca68744ee2b92764c Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Thu, 26 May 2016 18:29:42 -0500 Subject: [PATCH 243/860] Refactored locations of translation files --- lib/elixir_script.ex | 8 ++++---- lib/elixir_script/translator.ex | 17 +++++++++-------- lib/elixir_script/translator/kernel/def.ex | 18 ++++++++++++++++++ .../implementation.ex => kernel/defimpl.ex} | 6 +++--- .../{module.ex => kernel/defmodule.ex} | 7 ++++--- .../{protocol.ex => kernel/defprotocol.ex} | 12 ++++++------ .../translator/{ => kernel}/expression.ex | 0 .../translator/{ => kernel}/js.ex | 0 .../{ => kernel/special_forms}/bitstring.ex | 0 .../{ => kernel/special_forms}/block.ex | 0 .../{ => kernel/special_forms}/capture.ex | 0 .../{ => kernel/special_forms}/case.ex | 0 .../{ => kernel/special_forms}/cond.ex | 0 .../special_forms/fn.ex} | 11 ----------- .../{ => kernel/special_forms}/for.ex | 0 .../{ => kernel/special_forms}/map.ex | 0 .../special_forms/match.ex} | 4 ++-- .../{ => kernel/special_forms}/primitive.ex | 0 .../{ => kernel/special_forms}/quote.ex | 0 .../{ => kernel/special_forms}/struct.ex | 0 .../{ => kernel/special_forms}/try.ex | 0 .../{ => kernel/special_forms}/with.ex | 0 test/translator/assignment_test.exs | 2 +- test/translator/protocol_test.exs | 2 +- 24 files changed, 48 insertions(+), 39 deletions(-) create mode 100644 lib/elixir_script/translator/kernel/def.ex rename lib/elixir_script/translator/{protocol/implementation.ex => kernel/defimpl.ex} (94%) rename lib/elixir_script/translator/{module.ex => kernel/defmodule.ex} (96%) rename lib/elixir_script/translator/{protocol.ex => kernel/defprotocol.ex} (92%) rename lib/elixir_script/translator/{ => kernel}/expression.ex (100%) rename lib/elixir_script/translator/{ => kernel}/js.ex (100%) rename lib/elixir_script/translator/{ => kernel/special_forms}/bitstring.ex (100%) rename lib/elixir_script/translator/{ => kernel/special_forms}/block.ex (100%) rename lib/elixir_script/translator/{ => kernel/special_forms}/capture.ex (100%) rename lib/elixir_script/translator/{ => kernel/special_forms}/case.ex (100%) rename lib/elixir_script/translator/{ => kernel/special_forms}/cond.ex (100%) rename lib/elixir_script/translator/{function.ex => kernel/special_forms/fn.ex} (96%) rename lib/elixir_script/translator/{ => kernel/special_forms}/for.ex (100%) rename lib/elixir_script/translator/{ => kernel/special_forms}/map.ex (100%) rename lib/elixir_script/translator/{assignment.ex => kernel/special_forms/match.ex} (96%) rename lib/elixir_script/translator/{ => kernel/special_forms}/primitive.ex (100%) rename lib/elixir_script/translator/{ => kernel/special_forms}/quote.ex (100%) rename lib/elixir_script/translator/{ => kernel/special_forms}/struct.ex (100%) rename lib/elixir_script/translator/{ => kernel/special_forms}/try.ex (100%) rename lib/elixir_script/translator/{ => kernel/special_forms}/with.ex (100%) diff --git a/lib/elixir_script.ex b/lib/elixir_script.ex index eec1d8c1..e4cfe0e0 100644 --- a/lib/elixir_script.ex +++ b/lib/elixir_script.ex @@ -246,11 +246,11 @@ defmodule ElixirScript do module = case ast.type do :module -> - ElixirScript.Translator.Module.make_module(ast.name, ast.body, env) + ElixirScript.Translator.Defmodule.make_module(ast.name, ast.body, env) :protocol -> - ElixirScript.Translator.Protocol.make(ast.name, ast.functions, env) + ElixirScript.Translator.Defprotocol.make(ast.name, ast.functions, env) :protocol_implementation -> - ElixirScript.Translator.Protocol.Implementation.make(ast.name, ast.impl_type, ast.body, env) + ElixirScript.Translator.Defimpl.make(ast.name, ast.impl_type, ast.body, env) end @@ -302,7 +302,7 @@ defmodule ElixirScript do defp do_make_defimpl(protocols, compiler_opts) do Enum.map(protocols, fn {protocol, implementations} -> - ElixirScript.Translator.Protocol.make_defimpl(protocol, Enum.uniq(implementations), compiler_opts) + ElixirScript.Translator.Defprotocol.make_defimpl(protocol, Enum.uniq(implementations), compiler_opts) end) |> Enum.map(fn(module) -> javascript_ast_to_code(module) diff --git a/lib/elixir_script/translator.ex b/lib/elixir_script/translator.ex index 0b407f37..f9eb4d4a 100644 --- a/lib/elixir_script/translator.ex +++ b/lib/elixir_script/translator.ex @@ -5,9 +5,10 @@ defmodule ElixirScript.Translator do """ alias ElixirScript.Translator.Primitive alias ElixirScript.Translator.Expression - alias ElixirScript.Translator.Assignment + alias ElixirScript.Translator.Match alias ElixirScript.Translator.Map alias ElixirScript.Translator.Function + alias ElixirScript.Translator.Def alias ElixirScript.Translator.Capture alias ElixirScript.Translator.Cond alias ElixirScript.Translator.Case @@ -16,7 +17,7 @@ defmodule ElixirScript.Translator do alias ElixirScript.Translator.With alias ElixirScript.Translator.Block alias ElixirScript.Translator.Struct - alias ElixirScript.Translator.Module + alias ElixirScript.Translator.Defmodule alias ElixirScript.Translator.Utils alias ElixirScript.Translator.Bitstring alias ElixirScript.Translator.Quote @@ -168,7 +169,7 @@ defmodule ElixirScript.Translator do defp do_translate({:@, _, [{name, _, [value]}]}, env) do name = Utils.filter_name(name) - { Module.make_attribute(name, value, env), env } + { Defmodule.make_attribute(name, value, env), env } end defp do_translate({:@, _, [{name, _, _}]}, env) do @@ -446,19 +447,19 @@ defmodule ElixirScript.Translator do end defp do_translate({:=, _, [left, right]}, env) do - Assignment.make_assignment(left, right, env) + Match.make_match(left, right, env) end defp do_translate({function, _, [{:when, _, [{name, _, _params} | _guards] }, _] } = ast, env) when function in [:def, :defp] do - Function.process_function(Utils.filter_name(name), [ast], env) + Def.process_function(Utils.filter_name(name), [ast], env) end defp do_translate({function, _, [{name, _, params}, _]} = ast, env) when function in [:def, :defp] and is_atom(params) do - Function.process_function(Utils.filter_name(name), [ast], env) + Def.process_function(Utils.filter_name(name), [ast], env) end defp do_translate({function, _, [{name, _, _params}, _]} = ast, env) when function in [:def, :defp] do - Function.process_function(Utils.filter_name(name), [ast], env) + Def.process_function(Utils.filter_name(name), [ast], env) end defp do_translate({:defstruct, _, attributes}, env) do @@ -470,7 +471,7 @@ defmodule ElixirScript.Translator do end defp do_translate({:defmodule, _, [{:__aliases__, _, module_name_list}, [do: body]]}, env) do - { Module.make_module(module_name_list, body, env), env } + { Defmodule.make_module(module_name_list, body, env), env } end defp do_translate({:defprotocol, _, _}, env) do diff --git a/lib/elixir_script/translator/kernel/def.ex b/lib/elixir_script/translator/kernel/def.ex new file mode 100644 index 00000000..025c8b0e --- /dev/null +++ b/lib/elixir_script/translator/kernel/def.ex @@ -0,0 +1,18 @@ +defmodule ElixirScript.Translator.Def do + @moduledoc false + alias ESTree.Tools.Builder, as: JS + alias ElixirScript.Translator + alias ElixirScript.Translator.Function + alias ElixirScript.Translator.Utils + + def process_function(name, functions, env) do + { result, _ } = Function.make_anonymous_function(functions, env, name) + + declarator = JS.variable_declarator( + JS.identifier(Utils.filter_name(name)), + result + ) + + { JS.variable_declaration([declarator], :const), env } + end +end diff --git a/lib/elixir_script/translator/protocol/implementation.ex b/lib/elixir_script/translator/kernel/defimpl.ex similarity index 94% rename from lib/elixir_script/translator/protocol/implementation.ex rename to lib/elixir_script/translator/kernel/defimpl.ex index 52fc3b3d..79ed8569 100644 --- a/lib/elixir_script/translator/protocol/implementation.ex +++ b/lib/elixir_script/translator/kernel/defimpl.ex @@ -1,11 +1,11 @@ -defmodule ElixirScript.Translator.Protocol.Implementation do +defmodule ElixirScript.Translator.Defimpl do alias ESTree.Tools.Builder, as: JS - alias ElixirScript.Translator.Module + alias ElixirScript.Translator.Defmodule def make(name, type, body, env) do type = map_to_js(type, env) - module = Module.make_module(name, body, env) + module = Defmodule.make_module(name, body, env) protocol_name = Atom.to_string(name) |> String.split(".DefImpl.") |> hd |> String.to_atom diff --git a/lib/elixir_script/translator/module.ex b/lib/elixir_script/translator/kernel/defmodule.ex similarity index 96% rename from lib/elixir_script/translator/module.ex rename to lib/elixir_script/translator/kernel/defmodule.ex index 5ae8c4dc..6924fabc 100644 --- a/lib/elixir_script/translator/module.ex +++ b/lib/elixir_script/translator/kernel/defmodule.ex @@ -1,9 +1,10 @@ -defmodule ElixirScript.Translator.Module do +defmodule ElixirScript.Translator.Defmodule do @moduledoc false alias ESTree.Tools.Builder, as: JS alias ElixirScript.Translator alias ElixirScript.Translator.Utils alias ElixirScript.Translator.Function + alias ElixirScript.Translator.Def alias ElixirScript.ModuleSystems def make_module(ElixirScript.Temp, body, env) do @@ -163,13 +164,13 @@ defmodule ElixirScript.Translator.Module do exported_functions = Enum.map(Dict.keys(exported), fn(key) -> functions = Dict.get(exported, key) - { functions, _ } = Function.process_function(key, functions, env) + { functions, _ } = Def.process_function(key, functions, env) { key, functions } end) private_functions = Enum.map(Dict.keys(private), fn(key) -> functions = Dict.get(private, key) - { functions, _ } = Function.process_function(key, functions, env) + { functions, _ } = Def.process_function(key, functions, env) { key, functions } end) diff --git a/lib/elixir_script/translator/protocol.ex b/lib/elixir_script/translator/kernel/defprotocol.ex similarity index 92% rename from lib/elixir_script/translator/protocol.ex rename to lib/elixir_script/translator/kernel/defprotocol.ex index 6e342938..e62274a8 100644 --- a/lib/elixir_script/translator/protocol.ex +++ b/lib/elixir_script/translator/kernel/defprotocol.ex @@ -1,8 +1,8 @@ -defmodule ElixirScript.Translator.Protocol do +defmodule ElixirScript.Translator.Defprotocol do @moduledoc false alias ESTree.Tools.Builder, as: JS - alias ElixirScript.Translator.Module + alias ElixirScript.Translator.Defmodule alias ElixirScript.Translator.Map alias ElixirScript.Translator.Utils alias ElixirScript.ModuleSystems @@ -12,14 +12,14 @@ defmodule ElixirScript.Translator.Protocol do Takes a protocol and turns it into a module """ def make(name, functions, env) do - { body, _ } = Module.translate_body( {:__block__, [], [] }, env) + { body, _ } = Defmodule.translate_body( {:__block__, [], [] }, env) module_refs = ElixirScript.Translator.State.get_module_references(name) - {imports, body} = Module.extract_imports_from_body(body) + {imports, body} = Defmodule.extract_imports_from_body(body) - imports = imports ++ Module.make_std_lib_import() ++ - Module.make_imports(module_refs) ++ + imports = imports ++ Defmodule.make_std_lib_import() ++ + Defmodule.make_imports(module_refs) ++ [ElixirScript.ModuleSystems.import_module("Implementations", Utils.make_local_file_path(Utils.name_to_js_file_name(name) <> ".Defimpl"))] object = process_spec_functions(functions) diff --git a/lib/elixir_script/translator/expression.ex b/lib/elixir_script/translator/kernel/expression.ex similarity index 100% rename from lib/elixir_script/translator/expression.ex rename to lib/elixir_script/translator/kernel/expression.ex diff --git a/lib/elixir_script/translator/js.ex b/lib/elixir_script/translator/kernel/js.ex similarity index 100% rename from lib/elixir_script/translator/js.ex rename to lib/elixir_script/translator/kernel/js.ex diff --git a/lib/elixir_script/translator/bitstring.ex b/lib/elixir_script/translator/kernel/special_forms/bitstring.ex similarity index 100% rename from lib/elixir_script/translator/bitstring.ex rename to lib/elixir_script/translator/kernel/special_forms/bitstring.ex diff --git a/lib/elixir_script/translator/block.ex b/lib/elixir_script/translator/kernel/special_forms/block.ex similarity index 100% rename from lib/elixir_script/translator/block.ex rename to lib/elixir_script/translator/kernel/special_forms/block.ex diff --git a/lib/elixir_script/translator/capture.ex b/lib/elixir_script/translator/kernel/special_forms/capture.ex similarity index 100% rename from lib/elixir_script/translator/capture.ex rename to lib/elixir_script/translator/kernel/special_forms/capture.ex diff --git a/lib/elixir_script/translator/case.ex b/lib/elixir_script/translator/kernel/special_forms/case.ex similarity index 100% rename from lib/elixir_script/translator/case.ex rename to lib/elixir_script/translator/kernel/special_forms/case.ex diff --git a/lib/elixir_script/translator/cond.ex b/lib/elixir_script/translator/kernel/special_forms/cond.ex similarity index 100% rename from lib/elixir_script/translator/cond.ex rename to lib/elixir_script/translator/kernel/special_forms/cond.ex diff --git a/lib/elixir_script/translator/function.ex b/lib/elixir_script/translator/kernel/special_forms/fn.ex similarity index 96% rename from lib/elixir_script/translator/function.ex rename to lib/elixir_script/translator/kernel/special_forms/fn.ex index ef93d3c8..210d8cff 100644 --- a/lib/elixir_script/translator/function.ex +++ b/lib/elixir_script/translator/kernel/special_forms/fn.ex @@ -13,17 +13,6 @@ defmodule ElixirScript.Translator.Function do JS.identifier("Patterns") ) - def process_function(name, functions, env) do - { result, _ } = make_anonymous_function(functions, env, name) - - declarator = JS.variable_declarator( - JS.identifier(Utils.filter_name(name)), - result - ) - - { JS.variable_declaration([declarator], :const), env } - end - def make_anonymous_function(functions, env, name \\ nil) do clauses = functions |> Enum.map(fn diff --git a/lib/elixir_script/translator/for.ex b/lib/elixir_script/translator/kernel/special_forms/for.ex similarity index 100% rename from lib/elixir_script/translator/for.ex rename to lib/elixir_script/translator/kernel/special_forms/for.ex diff --git a/lib/elixir_script/translator/map.ex b/lib/elixir_script/translator/kernel/special_forms/map.ex similarity index 100% rename from lib/elixir_script/translator/map.ex rename to lib/elixir_script/translator/kernel/special_forms/map.ex diff --git a/lib/elixir_script/translator/assignment.ex b/lib/elixir_script/translator/kernel/special_forms/match.ex similarity index 96% rename from lib/elixir_script/translator/assignment.ex rename to lib/elixir_script/translator/kernel/special_forms/match.ex index 368cc1b9..2263c391 100644 --- a/lib/elixir_script/translator/assignment.ex +++ b/lib/elixir_script/translator/kernel/special_forms/match.ex @@ -1,11 +1,11 @@ -defmodule ElixirScript.Translator.Assignment do +defmodule ElixirScript.Translator.Match do @moduledoc false alias ESTree.Tools.Builder, as: JS alias ElixirScript.Translator alias ElixirScript.Translator.PatternMatching alias ElixirScript.Translator.Primitive - def make_assignment(left, right, env) do + def make_match(left, right, env) do { right_ast, env } = Translator.translate(right, env) { patterns, params, env } = PatternMatching.process_match([left], env) diff --git a/lib/elixir_script/translator/primitive.ex b/lib/elixir_script/translator/kernel/special_forms/primitive.ex similarity index 100% rename from lib/elixir_script/translator/primitive.ex rename to lib/elixir_script/translator/kernel/special_forms/primitive.ex diff --git a/lib/elixir_script/translator/quote.ex b/lib/elixir_script/translator/kernel/special_forms/quote.ex similarity index 100% rename from lib/elixir_script/translator/quote.ex rename to lib/elixir_script/translator/kernel/special_forms/quote.ex diff --git a/lib/elixir_script/translator/struct.ex b/lib/elixir_script/translator/kernel/special_forms/struct.ex similarity index 100% rename from lib/elixir_script/translator/struct.ex rename to lib/elixir_script/translator/kernel/special_forms/struct.ex diff --git a/lib/elixir_script/translator/try.ex b/lib/elixir_script/translator/kernel/special_forms/try.ex similarity index 100% rename from lib/elixir_script/translator/try.ex rename to lib/elixir_script/translator/kernel/special_forms/try.ex diff --git a/lib/elixir_script/translator/with.ex b/lib/elixir_script/translator/kernel/special_forms/with.ex similarity index 100% rename from lib/elixir_script/translator/with.ex rename to lib/elixir_script/translator/kernel/special_forms/with.ex diff --git a/test/translator/assignment_test.exs b/test/translator/assignment_test.exs index c03f1b7f..a60f76d8 100644 --- a/test/translator/assignment_test.exs +++ b/test/translator/assignment_test.exs @@ -1,4 +1,4 @@ -defmodule ElixirScript.Translator.Assignment.Test do +defmodule ElixirScript.Translator.Match.Test do use ExUnit.Case import ElixirScript.TestHelper diff --git a/test/translator/protocol_test.exs b/test/translator/protocol_test.exs index f1dd0da7..01b4b6fe 100644 --- a/test/translator/protocol_test.exs +++ b/test/translator/protocol_test.exs @@ -1,4 +1,4 @@ -defmodule ElixirScript.Translator.Protocol.Test do +defmodule ElixirScript.Translator.Defprotocol.Test do use ExUnit.Case import ElixirScript.TestHelper From 8622da811d7d0aa27b6e455d1b3f7a3ee404a10c Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Thu, 26 May 2016 23:00:22 -0500 Subject: [PATCH 244/860] Refactored identifier creation so that name filtering is done in one place --- lib/elixir_script/translator.ex | 12 +++------ lib/elixir_script/translator/kernel/def.ex | 3 ++- .../translator/kernel/defmodule.ex | 6 ++--- .../translator/kernel/defprotocol.ex | 3 ++- .../kernel/special_forms/capture.ex | 3 ++- .../translator/kernel/special_forms/fn.ex | 7 ++--- .../kernel/special_forms/primitive.ex | 6 +++-- .../translator/pattern_matching.ex | 11 +++----- lib/elixir_script/translator/utils.ex | 27 ++++++++++--------- test/translator/pattern_matching_test.exs | 8 +++--- 10 files changed, 42 insertions(+), 44 deletions(-) diff --git a/lib/elixir_script/translator.ex b/lib/elixir_script/translator.ex index f9eb4d4a..1205f9b5 100644 --- a/lib/elixir_script/translator.ex +++ b/lib/elixir_script/translator.ex @@ -148,12 +148,10 @@ defmodule ElixirScript.Translator do end defp do_translate({:&, _, [{:/, _, [{{:., _, [module_name, function_name]}, _, []}, arity]}]}, env) do - function_name = Utils.filter_name(function_name) { Capture.make_capture(module_name, function_name, arity, env), env } end defp do_translate({:&, _, [{:/, _, [{function_name, _, _}, arity]}]}, env) do - function_name = Utils.filter_name(function_name) { Capture.make_capture(function_name, arity, env), env } end @@ -168,12 +166,10 @@ defmodule ElixirScript.Translator do end defp do_translate({:@, _, [{name, _, [value]}]}, env) do - name = Utils.filter_name(name) { Defmodule.make_attribute(name, value, env), env } end defp do_translate({:@, _, [{name, _, _}]}, env) do - name = Utils.filter_name(name) { Primitive.make_identifier(name), env } end @@ -451,15 +447,15 @@ defmodule ElixirScript.Translator do end defp do_translate({function, _, [{:when, _, [{name, _, _params} | _guards] }, _] } = ast, env) when function in [:def, :defp] do - Def.process_function(Utils.filter_name(name), [ast], env) + Def.process_function(name, [ast], env) end defp do_translate({function, _, [{name, _, params}, _]} = ast, env) when function in [:def, :defp] and is_atom(params) do - Def.process_function(Utils.filter_name(name), [ast], env) + Def.process_function(name, [ast], env) end defp do_translate({function, _, [{name, _, _params}, _]} = ast, env) when function in [:def, :defp] do - Def.process_function(Utils.filter_name(name), [ast], env) + Def.process_function(name, [ast], env) end defp do_translate({:defstruct, _, attributes}, env) do @@ -555,7 +551,6 @@ defmodule ElixirScript.Translator do defp do_translate({ name, _, params }, env) when is_atom(params) do cond do ElixirScript.Translator.LexicalScope.has_var?(env, name) -> - name = Utils.filter_name(name) { Primitive.make_identifier(name), env } has_function?(env.module, {name, 0}) -> Function.make_function_call(name, [], env) @@ -563,7 +558,6 @@ defmodule ElixirScript.Translator do imported_module_name = ElixirScript.Translator.LexicalScope.find_module(env, {name, 0}) Function.make_function_call(imported_module_name, name, params, env) true -> - name = Utils.filter_name(name) { Primitive.make_identifier(name), env } end end diff --git a/lib/elixir_script/translator/kernel/def.ex b/lib/elixir_script/translator/kernel/def.ex index 025c8b0e..22429be0 100644 --- a/lib/elixir_script/translator/kernel/def.ex +++ b/lib/elixir_script/translator/kernel/def.ex @@ -4,12 +4,13 @@ defmodule ElixirScript.Translator.Def do alias ElixirScript.Translator alias ElixirScript.Translator.Function alias ElixirScript.Translator.Utils + alias ElixirScript.Translator.Primitive def process_function(name, functions, env) do { result, _ } = Function.make_anonymous_function(functions, env, name) declarator = JS.variable_declarator( - JS.identifier(Utils.filter_name(name)), + Primitive.make_identifier(name), result ) diff --git a/lib/elixir_script/translator/kernel/defmodule.ex b/lib/elixir_script/translator/kernel/defmodule.ex index 6924fabc..6ac2be34 100644 --- a/lib/elixir_script/translator/kernel/defmodule.ex +++ b/lib/elixir_script/translator/kernel/defmodule.ex @@ -3,9 +3,9 @@ defmodule ElixirScript.Translator.Defmodule do alias ESTree.Tools.Builder, as: JS alias ElixirScript.Translator alias ElixirScript.Translator.Utils - alias ElixirScript.Translator.Function alias ElixirScript.Translator.Def alias ElixirScript.ModuleSystems + alias ElixirScript.Translator.Primitive def make_module(ElixirScript.Temp, body, env) do { body, _ } = translate_body(body, env) @@ -44,7 +44,7 @@ defmodule ElixirScript.Translator.Defmodule do exported_object = JS.object_expression( make_defstruct_property(module, structs) ++ Enum.map(exported_functions, fn({key, _value}) -> - JS.property(JS.identifier(Utils.filter_name(key)), JS.identifier(Utils.filter_name(key)), :init, true) + JS.property(Primitive.make_identifier(key), Primitive.make_identifier(key), :init, true) end) ) @@ -179,7 +179,7 @@ defmodule ElixirScript.Translator.Defmodule do def make_attribute(name, value, env) do declarator = JS.variable_declarator( - JS.identifier(name), + Primitive.make_identifier(name), ElixirScript.Translator.translate!(value, env) ) diff --git a/lib/elixir_script/translator/kernel/defprotocol.ex b/lib/elixir_script/translator/kernel/defprotocol.ex index e62274a8..40aaf009 100644 --- a/lib/elixir_script/translator/kernel/defprotocol.ex +++ b/lib/elixir_script/translator/kernel/defprotocol.ex @@ -6,6 +6,7 @@ defmodule ElixirScript.Translator.Defprotocol do alias ElixirScript.Translator.Map alias ElixirScript.Translator.Utils alias ElixirScript.ModuleSystems + alias ElixirScript.Translator.Primitive require Logger @doc """ @@ -24,7 +25,7 @@ defmodule ElixirScript.Translator.Defprotocol do object = process_spec_functions(functions) |> Enum.map(fn({key, value}) -> - Map.make_property(JS.identifier(Utils.filter_name(key)), value) + Map.make_property(Primitive.make_identifier(key), value) end) |> JS.object_expression diff --git a/lib/elixir_script/translator/kernel/special_forms/capture.ex b/lib/elixir_script/translator/kernel/special_forms/capture.ex index 6aaaebfd..359749d4 100644 --- a/lib/elixir_script/translator/kernel/special_forms/capture.ex +++ b/lib/elixir_script/translator/kernel/special_forms/capture.ex @@ -4,6 +4,7 @@ defmodule ElixirScript.Translator.Capture do alias ESTree.Tools.Builder, as: JS alias ElixirScript.Translator.PatternMatching alias ElixirScript.Translator.Function + alias ElixirScript.Translator.Primitive def make_capture(function_name, arity, env) do { patterns, params, _ } = process_params(arity, env) @@ -11,7 +12,7 @@ defmodule ElixirScript.Translator.Capture do body = JS.block_statement([ JS.return_statement( JS.call_expression( - JS.identifier(function_name), + Primitive.make_identifier(function_name), params ) ) diff --git a/lib/elixir_script/translator/kernel/special_forms/fn.ex b/lib/elixir_script/translator/kernel/special_forms/fn.ex index 210d8cff..ae137487 100644 --- a/lib/elixir_script/translator/kernel/special_forms/fn.ex +++ b/lib/elixir_script/translator/kernel/special_forms/fn.ex @@ -4,6 +4,7 @@ defmodule ElixirScript.Translator.Function do alias ElixirScript.Translator alias ElixirScript.Translator.Utils alias ElixirScript.Translator.PatternMatching + alias ElixirScript.Translator.Primitive @patterns JS.member_expression( JS.member_expression( @@ -165,14 +166,14 @@ defmodule ElixirScript.Translator.Function do end def make_function_call(function_name, params, env) do - { Utils.make_call_expression(Utils.filter_name(function_name), params, env), env } + { Utils.make_call_expression(function_name, params, env), env } end def make_function_call(module_name, function_name, params, env) when is_list(module_name) do call = JS.call_expression( JS.member_expression( Translator.translate!(module_name, env), - JS.identifier(Utils.filter_name(function_name)) + Primitive.make_identifier(function_name) ), Enum.map(params, &Translator.translate!(&1, env)) ) @@ -182,7 +183,7 @@ defmodule ElixirScript.Translator.Function do def make_function_call(module_name, function_name, params, env) do the_name = get_module_name_for_function(module_name, env) - { Utils.make_call_expression(the_name, Utils.filter_name(function_name), params, env), env } + { Utils.make_call_expression(the_name, function_name, params, env), env } end def prepare_function_body(body, env) do diff --git a/lib/elixir_script/translator/kernel/special_forms/primitive.ex b/lib/elixir_script/translator/kernel/special_forms/primitive.ex index 1910173c..8fa4d9c2 100644 --- a/lib/elixir_script/translator/kernel/special_forms/primitive.ex +++ b/lib/elixir_script/translator/kernel/special_forms/primitive.ex @@ -44,11 +44,13 @@ defmodule ElixirScript.Translator.Primitive do end def make_identifier([ast]) do - JS.identifier(ast) + make_identifier(ast) end def make_identifier(ast) do - JS.identifier(ast) + ast + |> Utils.filter_name + |> JS.identifier end def make_literal(ast) when is_number(ast) or is_binary(ast) or is_boolean(ast) or is_nil(ast) do diff --git a/lib/elixir_script/translator/pattern_matching.ex b/lib/elixir_script/translator/pattern_matching.ex index 9d19167c..8e8eb6f5 100644 --- a/lib/elixir_script/translator/pattern_matching.ex +++ b/lib/elixir_script/translator/pattern_matching.ex @@ -4,7 +4,6 @@ defmodule ElixirScript.Translator.PatternMatching do alias ESTree.Tools.Builder, as: JS alias ElixirScript.Translator alias ElixirScript.Translator.Primitive - alias ElixirScript.Translator.Utils alias ElixirScript.Translator.Map alias ElixirScript.Translator.Struct alias ElixirScript.Translator.Bitstring @@ -167,7 +166,7 @@ defmodule ElixirScript.Translator.PatternMatching do end) elements = Enum.map(elements, fn - ({:::, context, [{ variable, _, params }, options]}) when is_atom(params) -> + ({:::, context, [{ _, _, params }, options]}) when is_atom(params) -> Bitstring.make_bitstring_element({:::, context, [ElixirScript.Translator.PatternMatching, options]}, env) x -> Bitstring.make_bitstring_element(x, env) @@ -255,14 +254,12 @@ defmodule ElixirScript.Translator.PatternMatching do end defp do_build_match({:\\, _, [{name, _, _}, default]}, env) do - name = Utils.filter_name(name) - { [parameter(Translator.translate!(default, env))], [JS.identifier(name)] } + { [parameter(Translator.translate!(default, env))], [Primitive.make_identifier(name)] } end defp do_build_match({name, _, _}, _) do - name = Utils.filter_name(name) - { [parameter()], [JS.identifier(name)] } + { [parameter()], [Primitive.make_identifier(name)] } end defp reduce_patterns(patterns) do @@ -274,7 +271,7 @@ defmodule ElixirScript.Translator.PatternMatching do defp unify(target, source, env) do { patterns, params } = build_match([source], env) - { [capture(hd(patterns))], params ++ [JS.identifier(Utils.filter_name(target))] } + { [capture(hd(patterns))], params ++ [Primitive.make_identifier(target)] } end end diff --git a/lib/elixir_script/translator/utils.ex b/lib/elixir_script/translator/utils.ex index 9d244bc8..45a2baa1 100644 --- a/lib/elixir_script/translator/utils.ex +++ b/lib/elixir_script/translator/utils.ex @@ -2,6 +2,7 @@ defmodule ElixirScript.Translator.Utils do @moduledoc false alias ESTree.Tools.Builder, as: JS alias ElixirScript.Translator + alias ElixirScript.Translator.Primitive @js_reserved_words [ :break, @@ -62,17 +63,17 @@ defmodule ElixirScript.Translator.Utils do Enum.reduce(modules, nil, fn(x, ast) -> case ast do nil -> - JS.member_expression(JS.identifier(x), nil, computed) + JS.member_expression(Primitive.make_identifier(x), nil, computed) %ESTree.MemberExpression{ property: nil } -> - %{ ast | property: JS.identifier(x) } + %{ ast | property: Primitive.make_identifier(x) } _ -> - JS.member_expression(ast, JS.identifier(x), computed) + JS.member_expression(ast, Primitive.make_identifier(x), computed) end end) end def make_module_expression_tree(module, _computed, _) when is_binary(module) or is_atom(module) do - JS.identifier(module) + Primitive.make_identifier(module) end def make_module_expression_tree(module, _computed, env) do @@ -95,7 +96,7 @@ defmodule ElixirScript.Translator.Utils do def make_call_expression(function_name, params, env) do JS.call_expression( - JS.identifier(function_name), + Primitive.make_identifier(function_name), Enum.map(params, &Translator.translate!(&1, env)) ) end @@ -106,37 +107,37 @@ defmodule ElixirScript.Translator.Utils do ast = make_module_expression_tree(modules, computed, env) JS.member_expression( ast, - JS.identifier(function_name), + Primitive.make_identifier(function_name), computed ) modules when is_list(modules) and length(modules) == 1 -> JS.member_expression( - JS.identifier(hd(modules)), - JS.identifier(function_name), + Primitive.make_identifier(hd(modules)), + Primitive.make_identifier(function_name), computed ) {{:., _, [_module_name, _function_name]}, _, _params } = ast -> JS.member_expression( Translator.translate!(ast, env), - JS.identifier(function_name), + Primitive.make_identifier(function_name), computed ) {{:., _, [{:__aliases__, _, _}]}, _, _} = ast -> JS.member_expression( Translator.translate!(ast, env), - JS.identifier(function_name), + Primitive.make_identifier(function_name), computed ) {:., _, _} = ast -> JS.member_expression( Translator.translate!(ast, env), - JS.identifier(function_name), + Primitive.make_identifier(function_name), computed ) _ -> JS.member_expression( - JS.identifier(module_name), - JS.identifier(function_name), + Primitive.make_identifier(module_name), + Primitive.make_identifier(function_name), computed ) end diff --git a/test/translator/pattern_matching_test.exs b/test/translator/pattern_matching_test.exs index ed1487cf..402eebab 100644 --- a/test/translator/pattern_matching_test.exs +++ b/test/translator/pattern_matching_test.exs @@ -102,7 +102,7 @@ defmodule ElixirScript.Translator.PatternMatching.Test do params = [{:%, [], [{:__aliases__, [alias: false], [:Hello]}, {:%{}, [], []}]}] result = PatternMatching.build_match(params, ElixirScript.Translator.LexicalScope.module_scope(ElixirScript.Temp, "temp.ex", ElixirScript.custom_env) ) expected_result = { - [PatternMatching.type(JS.identifier(:Hello), JS.object_expression([]))], + [PatternMatching.type(JS.identifier("Hello"), JS.object_expression([]))], [] } @@ -113,7 +113,7 @@ defmodule ElixirScript.Translator.PatternMatching.Test do params = [{:%, [], [{:__aliases__, [alias: false], [:Hello]}, {:%{}, [], [key: 1]}]}] result = PatternMatching.build_match(params, ElixirScript.Translator.LexicalScope.module_scope(ElixirScript.Temp, "temp.ex", ElixirScript.custom_env) ) expected_result = { - [PatternMatching.type(JS.identifier(:Hello), JS.object_expression([ + [PatternMatching.type(JS.identifier("Hello"), JS.object_expression([ Map.make_property(Translator.translate!(:key, ElixirScript.Translator.LexicalScope.module_scope(ElixirScript.Temp, "temp.ex", ElixirScript.custom_env) ), Translator.translate!(1, ElixirScript.Translator.LexicalScope.module_scope(ElixirScript.Temp, "temp.ex", ElixirScript.custom_env) )) ])) ], @@ -127,7 +127,7 @@ defmodule ElixirScript.Translator.PatternMatching.Test do params = [{:%, [], [{:__aliases__, [alias: false], [:Hello]}, {:%{}, [], [key: {:key, [], Elixir }]}]}] result = PatternMatching.build_match(params, ElixirScript.Translator.LexicalScope.module_scope(ElixirScript.Temp, "temp.ex", ElixirScript.custom_env) ) expected_result = { - [PatternMatching.type(JS.identifier(:Hello), JS.object_expression([ + [PatternMatching.type(JS.identifier("Hello"), JS.object_expression([ Map.make_property(Translator.translate!(:key, ElixirScript.Translator.LexicalScope.module_scope(ElixirScript.Temp, "temp.ex", ElixirScript.custom_env) ), PatternMatching.parameter) ])) ], @@ -161,7 +161,7 @@ defmodule ElixirScript.Translator.PatternMatching.Test do params = [{:=, [], [{:%, [], [{:__aliases__, [alias: false], [:AStruct]}, {:%{}, [], []}]}, {:a, [], ElixirScript.Translator.Function.Test}]}] result = PatternMatching.build_match(params, ElixirScript.Translator.LexicalScope.module_scope(ElixirScript.Temp, "temp.ex", ElixirScript.custom_env) ) expected_result = { - [PatternMatching.capture(PatternMatching.type(JS.identifier(:AStruct), JS.object_expression([])))], + [PatternMatching.capture(PatternMatching.type(JS.identifier("AStruct"), JS.object_expression([])))], [JS.identifier("a")] } From ebfa1d71e937a726471a3ca156abf2ca6ac7fd0e Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Thu, 26 May 2016 23:04:51 -0500 Subject: [PATCH 245/860] renamed test --- .../translator/{assignment_test.exs => match_test.exs} | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) rename test/translator/{assignment_test.exs => match_test.exs} (92%) diff --git a/test/translator/assignment_test.exs b/test/translator/match_test.exs similarity index 92% rename from test/translator/assignment_test.exs rename to test/translator/match_test.exs index a60f76d8..d233b873 100644 --- a/test/translator/assignment_test.exs +++ b/test/translator/match_test.exs @@ -2,7 +2,7 @@ defmodule ElixirScript.Translator.Match.Test do use ExUnit.Case import ElixirScript.TestHelper - test "translate simple assignment" do + test "translate simple match" do ex_ast = quote do: a = 1 js_code = "let [a] = Elixir.Core.Patterns.match(Elixir.Core.Patterns.variable(), 1);" @@ -14,7 +14,7 @@ defmodule ElixirScript.Translator.Match.Test do assert_translation(ex_ast, js_code) end - test "translate tuple assignment" do + test "translate tuple match" do ex_ast = quote do {a, b} = {1, 2} end @@ -49,7 +49,7 @@ defmodule ElixirScript.Translator.Match.Test do assert_translation(ex_ast, js_code) end - test "translate bound assignment" do + test "translate bound match" do ex_ast = quote do: ^a = 1 js_code = """ let [] = Elixir.Core.Patterns.match(Elixir.Core.Patterns.bound(a),1); @@ -58,7 +58,7 @@ defmodule ElixirScript.Translator.Match.Test do assert_translation(ex_ast, js_code) end - test "translate list assignment" do + test "translate list match" do ex_ast = quote do: [a, b] = [1, 2] js_code = """ let [a,b] = Elixir.Core.Patterns.match(Object.freeze([Elixir.Core.Patterns.variable(), Elixir.Core.Patterns.variable()]),Object.freeze([1, 2])); @@ -68,7 +68,7 @@ defmodule ElixirScript.Translator.Match.Test do assert_translation(ex_ast, js_code) end - test "translate head/tail assignment" do + test "translate head/tail match" do ex_ast = quote do: [a | b] = [1, 2, 3, 4] js_code = """ let [a,b] = Elixir.Core.Patterns.match(Elixir.Core.Patterns.headTail(Elixir.Core.Patterns.variable(),Elixir.Core.Patterns.variable()),Object.freeze([1, 2, 3, 4])); From 0596304cb2e64fe354d818a9ebd0a6cd6d505030 Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Thu, 26 May 2016 23:17:48 -0500 Subject: [PATCH 246/860] Separated function calls from function definitions --- lib/elixir_script/translator.ex | 21 ++-- .../translator/kernel/special_forms/call.ex | 111 ++++++++++++++++++ .../kernel/special_forms/capture.ex | 3 +- .../translator/kernel/special_forms/fn.ex | 96 --------------- 4 files changed, 124 insertions(+), 107 deletions(-) create mode 100644 lib/elixir_script/translator/kernel/special_forms/call.ex diff --git a/lib/elixir_script/translator.ex b/lib/elixir_script/translator.ex index 1205f9b5..0402bd73 100644 --- a/lib/elixir_script/translator.ex +++ b/lib/elixir_script/translator.ex @@ -8,6 +8,7 @@ defmodule ElixirScript.Translator do alias ElixirScript.Translator.Match alias ElixirScript.Translator.Map alias ElixirScript.Translator.Function + alias ElixirScript.Translator.Call alias ElixirScript.Translator.Def alias ElixirScript.Translator.Capture alias ElixirScript.Translator.Cond @@ -215,7 +216,7 @@ defmodule ElixirScript.Translator do end defp do_translate({{:., _, [function_name]}, _, params}, env) do - Function.make_function_call(function_name, params, env) + Call.make_function_call(function_name, params, env) end defp do_translate({:., _, [module_name, function_name]} = ast, env) do @@ -223,7 +224,7 @@ defmodule ElixirScript.Translator do if expanded_ast == ast do module_name = create_module_name(module_name, env) - Function.make_function_or_property_call(module_name, function_name, env) + Call.make_function_or_property_call(module_name, function_name, env) else translate(expanded_ast, env) end @@ -234,7 +235,7 @@ defmodule ElixirScript.Translator do if expanded_ast == ast do module_name = create_module_name(module_name, env) - Function.make_function_or_property_call(module_name, function_name, env) + Call.make_function_or_property_call(module_name, function_name, env) else translate(expanded_ast, env) end @@ -245,7 +246,7 @@ defmodule ElixirScript.Translator do if expanded_ast == ast do module_name = create_module_name(module_name, env) - Function.make_function_call(module_name, params, env) + Call.make_function_call(module_name, params, env) else translate(expanded_ast, env) end @@ -264,7 +265,7 @@ defmodule ElixirScript.Translator do if expanded_ast == ast do module_name = create_module_name(module_name, env) - Function.make_function_call(module_name, function_name, params, env) + Call.make_function_call(module_name, function_name, params, env) else translate(expanded_ast, env) end @@ -535,12 +536,12 @@ defmodule ElixirScript.Translator do cond do name_arity in module.functions or name_arity in module.private_functions -> - Function.make_function_call(name, params, env) + Call.make_function_call(name, params, env) ElixirScript.Translator.LexicalScope.find_module(env, name_arity) -> imported_module_name = ElixirScript.Translator.LexicalScope.find_module(env, name_arity) - Function.make_function_call(imported_module_name, name, params, env) + Call.make_function_call(imported_module_name, name, params, env) true -> - Function.make_function_call(name, params, env) + Call.make_function_call(name, params, env) end else @@ -553,10 +554,10 @@ defmodule ElixirScript.Translator do ElixirScript.Translator.LexicalScope.has_var?(env, name) -> { Primitive.make_identifier(name), env } has_function?(env.module, {name, 0}) -> - Function.make_function_call(name, [], env) + Call.make_function_call(name, [], env) ElixirScript.Translator.LexicalScope.find_module(env, {name, 0}) -> imported_module_name = ElixirScript.Translator.LexicalScope.find_module(env, {name, 0}) - Function.make_function_call(imported_module_name, name, params, env) + Call.make_function_call(imported_module_name, name, params, env) true -> { Primitive.make_identifier(name), env } end diff --git a/lib/elixir_script/translator/kernel/special_forms/call.ex b/lib/elixir_script/translator/kernel/special_forms/call.ex new file mode 100644 index 00000000..8f3c2ac0 --- /dev/null +++ b/lib/elixir_script/translator/kernel/special_forms/call.ex @@ -0,0 +1,111 @@ +defmodule ElixirScript.Translator.Call do + @moduledoc false + alias ESTree.Tools.Builder, as: JS + alias ElixirScript.Translator + alias ElixirScript.Translator.Utils + alias ElixirScript.Translator.PatternMatching + alias ElixirScript.Translator.Primitive + + + def make_function_or_property_call(module_name, function_name, env) do + the_name = get_module_name_for_function(module_name, env) + + js_ast = JS.call_expression( + JS.member_expression( + JS.member_expression( + JS.identifier("Elixir"), + JS.member_expression( + JS.identifier("Core"), + JS.identifier("Functions") + ) + ), + JS.identifier("call_property") + ), + [ + Utils.make_module_expression_tree(the_name, false, env), + Translator.translate!(to_string(function_name), env) + ] + ) + + { js_ast, env } + end + + + defp get_module_name_for_function(module_name, env) do + case module_name do + {:__aliases__, _, name} -> + module_name = Utils.quoted_to_name(name) + get_js_name(module_name, env) + {name, _, _} when is_atom(name) -> + get_js_name(name, env) + {{:., _, [_, _]}, _, _ } = ast -> + ast + {{:., _, [{:__aliases__, _, _}]}, _, _} = ast -> + ast + ast when is_list(ast) -> + ast + name -> + get_js_name(name, env) + end + end + + + def make_function_call(function_name, params, env) when is_tuple(function_name) do + { Utils.make_call_expression(function_name, params, env), env } + end + + def make_function_call(function_name, params, env) do + { Utils.make_call_expression(function_name, params, env), env } + end + + def make_function_call(module_name, function_name, params, env) when is_list(module_name) do + call = JS.call_expression( + JS.member_expression( + Translator.translate!(module_name, env), + Primitive.make_identifier(function_name) + ), + Enum.map(params, &Translator.translate!(&1, env)) + ) + + { call, env } + end + + def make_function_call(module_name, function_name, params, env) do + the_name = get_module_name_for_function(module_name, env) + { Utils.make_call_expression(the_name, function_name, params, env), env } + end + + + defp get_js_name([Elixir | _] = list, _) do + list + end + + defp get_js_name(module_name, env) when is_list(module_name) do + Utils.quoted_to_name({:__aliases__, [], module_name}) + |> get_js_name(env) + end + + defp get_js_name(module_name, env) do + + cond do + module_name in env.requires -> + Utils.name_to_js_name(module_name) + + module_name in ElixirScript.Translator.State.list_module_names -> + ElixirScript.Translator.State.add_module_reference(env.module, module_name) + Utils.name_to_js_name(module_name) + + true -> + case Atom.to_string(module_name) do + "Elixir." <> _ -> + {:__aliases__, _, name } = Utils.name_to_quoted(module_name) + name + _ -> + module_name + end + end + end + + + + end diff --git a/lib/elixir_script/translator/kernel/special_forms/capture.ex b/lib/elixir_script/translator/kernel/special_forms/capture.ex index 359749d4..d66ef324 100644 --- a/lib/elixir_script/translator/kernel/special_forms/capture.ex +++ b/lib/elixir_script/translator/kernel/special_forms/capture.ex @@ -4,6 +4,7 @@ defmodule ElixirScript.Translator.Capture do alias ESTree.Tools.Builder, as: JS alias ElixirScript.Translator.PatternMatching alias ElixirScript.Translator.Function + alias ElixirScript.Translator.Call alias ElixirScript.Translator.Primitive def make_capture(function_name, arity, env) do @@ -32,7 +33,7 @@ defmodule ElixirScript.Translator.Capture do name = [:ElixirScript, :Kernel] end - { func, _ } = Function.make_function_call({:__aliases__, [], name }, function_name, arity_params, env) + { func, _ } = Call.make_function_call({:__aliases__, [], name }, function_name, arity_params, env) body = JS.block_statement([ JS.return_statement( diff --git a/lib/elixir_script/translator/kernel/special_forms/fn.ex b/lib/elixir_script/translator/kernel/special_forms/fn.ex index ae137487..b2c4dec2 100644 --- a/lib/elixir_script/translator/kernel/special_forms/fn.ex +++ b/lib/elixir_script/translator/kernel/special_forms/fn.ex @@ -120,72 +120,6 @@ defmodule ElixirScript.Translator.Function do ) end - def make_function_or_property_call(module_name, function_name, env) do - the_name = get_module_name_for_function(module_name, env) - - js_ast = JS.call_expression( - JS.member_expression( - JS.member_expression( - JS.identifier("Elixir"), - JS.member_expression( - JS.identifier("Core"), - JS.identifier("Functions") - ) - ), - JS.identifier("call_property") - ), - [ - Utils.make_module_expression_tree(the_name, false, env), - Translator.translate!(to_string(function_name), env) - ] - ) - - { js_ast, env } - end - - defp get_module_name_for_function(module_name, env) do - case module_name do - {:__aliases__, _, name} -> - module_name = Utils.quoted_to_name(name) - get_js_name(module_name, env) - {name, _, _} when is_atom(name) -> - get_js_name(name, env) - {{:., _, [_, _]}, _, _ } = ast -> - ast - {{:., _, [{:__aliases__, _, _}]}, _, _} = ast -> - ast - ast when is_list(ast) -> - ast - name -> - get_js_name(name, env) - end - end - - def make_function_call(function_name, params, env) when is_tuple(function_name) do - { Utils.make_call_expression(function_name, params, env), env } - end - - def make_function_call(function_name, params, env) do - { Utils.make_call_expression(function_name, params, env), env } - end - - def make_function_call(module_name, function_name, params, env) when is_list(module_name) do - call = JS.call_expression( - JS.member_expression( - Translator.translate!(module_name, env), - Primitive.make_identifier(function_name) - ), - Enum.map(params, &Translator.translate!(&1, env)) - ) - - { call, env } - end - - def make_function_call(module_name, function_name, params, env) do - the_name = get_module_name_for_function(module_name, env) - { Utils.make_call_expression(the_name, function_name, params, env), env } - end - def prepare_function_body(body, env) do { list, env } = case body do nil -> @@ -274,34 +208,4 @@ defmodule ElixirScript.Translator.Function do list ++ [last_item] end end - - defp get_js_name([Elixir | _] = list, _) do - list - end - - defp get_js_name(module_name, env) when is_list(module_name) do - Utils.quoted_to_name({:__aliases__, [], module_name}) - |> get_js_name(env) - end - - defp get_js_name(module_name, env) do - - cond do - module_name in env.requires -> - Utils.name_to_js_name(module_name) - - module_name in ElixirScript.Translator.State.list_module_names -> - ElixirScript.Translator.State.add_module_reference(env.module, module_name) - Utils.name_to_js_name(module_name) - - true -> - case Atom.to_string(module_name) do - "Elixir." <> _ -> - {:__aliases__, _, name } = Utils.name_to_quoted(module_name) - name - _ -> - module_name - end - end - end end From 2d942e953d5824060a3fd9c07e3c8079e87d129e Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Thu, 26 May 2016 23:27:53 -0500 Subject: [PATCH 247/860] Moved inflate_groups to Group module. Removed some warnings --- lib/elixir_script/translator/group.ex | 18 ++++++++++++++++ lib/elixir_script/translator/kernel/def.ex | 2 -- .../translator/kernel/defmodule.ex | 5 +++-- .../translator/kernel/special_forms/call.ex | 1 - .../translator/kernel/special_forms/fn.ex | 5 ++--- .../translator/kernel/special_forms/for.ex | 2 +- .../translator/kernel/special_forms/with.ex | 2 +- .../translator/module_collector.ex | 21 ------------------- lib/elixir_script/translator/utils.ex | 18 ---------------- 9 files changed, 25 insertions(+), 49 deletions(-) diff --git a/lib/elixir_script/translator/group.ex b/lib/elixir_script/translator/group.ex index e2c2b609..391315ff 100644 --- a/lib/elixir_script/translator/group.ex +++ b/lib/elixir_script/translator/group.ex @@ -9,4 +9,22 @@ defmodule ElixirScript.Translator.Group do body: [ESTree.Statement.t] } defstruct type: "Group", body: [] + + def inflate_groups(body) do + Enum.map(body, fn(x) -> + case x do + %ElixirScript.Translator.Empty{} -> + [] + %ElixirScript.Translator.Group{body: group_body} -> + group_body + %ESTree.BlockStatement{} -> + %ESTree.BlockStatement{ body: inflate_groups(x.body) } + %ESTree.IfStatement{} -> + %{x | consequent: inflate_groups(x.consequent), alternate: inflate_groups(x.alternate) } + _ -> + x + end + end) + |> List.flatten + end end diff --git a/lib/elixir_script/translator/kernel/def.ex b/lib/elixir_script/translator/kernel/def.ex index 22429be0..30e7815e 100644 --- a/lib/elixir_script/translator/kernel/def.ex +++ b/lib/elixir_script/translator/kernel/def.ex @@ -1,9 +1,7 @@ defmodule ElixirScript.Translator.Def do @moduledoc false alias ESTree.Tools.Builder, as: JS - alias ElixirScript.Translator alias ElixirScript.Translator.Function - alias ElixirScript.Translator.Utils alias ElixirScript.Translator.Primitive def process_function(name, functions, env) do diff --git a/lib/elixir_script/translator/kernel/defmodule.ex b/lib/elixir_script/translator/kernel/defmodule.ex index 6ac2be34..94767175 100644 --- a/lib/elixir_script/translator/kernel/defmodule.ex +++ b/lib/elixir_script/translator/kernel/defmodule.ex @@ -3,13 +3,14 @@ defmodule ElixirScript.Translator.Defmodule do alias ESTree.Tools.Builder, as: JS alias ElixirScript.Translator alias ElixirScript.Translator.Utils + alias ElixirScript.Translator.Group alias ElixirScript.Translator.Def alias ElixirScript.ModuleSystems alias ElixirScript.Translator.Primitive def make_module(ElixirScript.Temp, body, env) do { body, _ } = translate_body(body, env) - %{ name: ElixirScript.Temp, body: body |> Utils.inflate_groups } + %{ name: ElixirScript.Temp, body: body |> Group.inflate_groups } end def make_module(module, nil, _) do @@ -39,7 +40,7 @@ defmodule ElixirScript.Translator.Defmodule do end end) - body = Utils.inflate_groups(body) + body = Group.inflate_groups(body) exported_object = JS.object_expression( make_defstruct_property(module, structs) ++ diff --git a/lib/elixir_script/translator/kernel/special_forms/call.ex b/lib/elixir_script/translator/kernel/special_forms/call.ex index 8f3c2ac0..d1f677b5 100644 --- a/lib/elixir_script/translator/kernel/special_forms/call.ex +++ b/lib/elixir_script/translator/kernel/special_forms/call.ex @@ -3,7 +3,6 @@ defmodule ElixirScript.Translator.Call do alias ESTree.Tools.Builder, as: JS alias ElixirScript.Translator alias ElixirScript.Translator.Utils - alias ElixirScript.Translator.PatternMatching alias ElixirScript.Translator.Primitive diff --git a/lib/elixir_script/translator/kernel/special_forms/fn.ex b/lib/elixir_script/translator/kernel/special_forms/fn.ex index b2c4dec2..2372e8fe 100644 --- a/lib/elixir_script/translator/kernel/special_forms/fn.ex +++ b/lib/elixir_script/translator/kernel/special_forms/fn.ex @@ -2,9 +2,8 @@ defmodule ElixirScript.Translator.Function do @moduledoc false alias ESTree.Tools.Builder, as: JS alias ElixirScript.Translator - alias ElixirScript.Translator.Utils + alias ElixirScript.Translator.Group alias ElixirScript.Translator.PatternMatching - alias ElixirScript.Translator.Primitive @patterns JS.member_expression( JS.member_expression( @@ -138,7 +137,7 @@ defmodule ElixirScript.Translator.Function do end) end - list = Utils.inflate_groups(list) + list = Group.inflate_groups(list) |> return_last_expression { list, env } diff --git a/lib/elixir_script/translator/kernel/special_forms/for.ex b/lib/elixir_script/translator/kernel/special_forms/for.ex index acff77bf..1e97f5d5 100644 --- a/lib/elixir_script/translator/kernel/special_forms/for.ex +++ b/lib/elixir_script/translator/kernel/special_forms/for.ex @@ -33,7 +33,7 @@ defmodule ElixirScript.Translator.For do { bs_parts, collection } = Enum.map_reduce(body, nil, fn {:::, _, _} = ast, state -> {ast, state} - {:<-, [], [var, collection]}, state -> + {:<-, [], [var, collection]}, _ -> { var, collection } end) diff --git a/lib/elixir_script/translator/kernel/special_forms/with.ex b/lib/elixir_script/translator/kernel/special_forms/with.ex index 7ca3865b..4f485edd 100644 --- a/lib/elixir_script/translator/kernel/special_forms/with.ex +++ b/lib/elixir_script/translator/kernel/special_forms/with.ex @@ -13,7 +13,7 @@ defmodule ElixirScript.Translator.With do translated_body = JS.block_statement(body) expr_function = JS.function_expression(state.arguments, [], translated_body) - { patterns, params, env } = PatternMatching.process_match([pattern], env) + { patterns, params, _ } = PatternMatching.process_match([pattern], env) %{state | arguments: state.arguments ++ params, expressions: state.expressions ++ [ JS.array_expression([hd(patterns), expr_function]) ] } diff --git a/lib/elixir_script/translator/module_collector.ex b/lib/elixir_script/translator/module_collector.ex index e18d9044..903c7881 100644 --- a/lib/elixir_script/translator/module_collector.ex +++ b/lib/elixir_script/translator/module_collector.ex @@ -187,27 +187,6 @@ defmodule ElixirScript.Translator.ModuleCollector do end end - defp add_module_to_state(name, inner_module_name, inner_module_body) do - %{ def: functions, defp: private_functions } = get_functions_from_module(inner_module_body) - js_imports = get_js_imports_from_module(inner_module_body) - - inner_alias = { :alias, [], [{:__aliases__, [alias: false], name ++ inner_module_name}] } - - module_name = Utils.quoted_to_name({:__aliases__, [], tl(name) ++ inner_module_name}) - State.delete_module_by_name(module_name) - - module_name = Utils.quoted_to_name({:__aliases__, [], name ++ inner_module_name}) - - mod = %ElixirScript.Module{ name: module_name, body: inner_module_body, - functions: functions, private_functions: private_functions, - js_imports: js_imports } - - State.add_module(mod) - - inner_alias - end - - defp get_functions_from_module({:__block__, _, list}) do Enum.reduce(list, %{ def: Keyword.new, defp: Keyword.new }, fn ({type, _, [{:when, _, [{name, _, params} | _guards] }, _] }, state) when type in [:def, :defp] and is_atom(params) -> diff --git a/lib/elixir_script/translator/utils.ex b/lib/elixir_script/translator/utils.ex index 45a2baa1..7ff6f684 100644 --- a/lib/elixir_script/translator/utils.ex +++ b/lib/elixir_script/translator/utils.ex @@ -37,24 +37,6 @@ defmodule ElixirScript.Translator.Utils do :yield ] - def inflate_groups(body) do - Enum.map(body, fn(x) -> - case x do - %ElixirScript.Translator.Empty{} -> - [] - %ElixirScript.Translator.Group{body: group_body} -> - group_body - %ESTree.BlockStatement{} -> - %ESTree.BlockStatement{ body: inflate_groups(x.body) } - %ESTree.IfStatement{} -> - %{x | consequent: inflate_groups(x.consequent), alternate: inflate_groups(x.alternate) } - _ -> - x - end - end) - |> List.flatten - end - def make_module_expression_tree([module], computed, env) do make_module_expression_tree(module, computed, env) end From a9136beea6d71ad7e683bea906b5d3b562dd31a0 Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Fri, 27 May 2016 15:50:16 -0500 Subject: [PATCH 248/860] Refactored identifier translation into its own module --- lib/elixir_script/translator.ex | 13 ++-- lib/elixir_script/translator/kernel/def.ex | 4 +- .../translator/kernel/defmodule.ex | 6 +- .../translator/kernel/defprotocol.ex | 4 +- .../translator/kernel/special_forms/call.ex | 4 +- .../kernel/special_forms/capture.ex | 4 +- .../kernel/special_forms/identifier.ex | 73 +++++++++++++++++++ .../kernel/special_forms/primitive.ex | 16 ---- .../translator/pattern_matching.ex | 7 +- lib/elixir_script/translator/utils.ex | 71 ++++-------------- 10 files changed, 109 insertions(+), 93 deletions(-) create mode 100644 lib/elixir_script/translator/kernel/special_forms/identifier.ex diff --git a/lib/elixir_script/translator.ex b/lib/elixir_script/translator.ex index 0402bd73..3b624db8 100644 --- a/lib/elixir_script/translator.ex +++ b/lib/elixir_script/translator.ex @@ -4,6 +4,7 @@ defmodule ElixirScript.Translator do JavaScript AST. """ alias ElixirScript.Translator.Primitive + alias ElixirScript.Translator.Identifier alias ElixirScript.Translator.Expression alias ElixirScript.Translator.Match alias ElixirScript.Translator.Map @@ -145,7 +146,7 @@ defmodule ElixirScript.Translator do end defp do_translate({:&, _, [number]}, env) when is_number(number) do - { Primitive.make_identifier(String.to_atom("__#{number}")), env } + { Identifier.make_identifier(String.to_atom("__#{number}")), env } end defp do_translate({:&, _, [{:/, _, [{{:., _, [module_name, function_name]}, _, []}, arity]}]}, env) do @@ -171,7 +172,7 @@ defmodule ElixirScript.Translator do end defp do_translate({:@, _, [{name, _, _}]}, env) do - { Primitive.make_identifier(name), env } + { Identifier.make_identifier(name), env } end defp do_translate({:%, _, [alias_info, data]}, env) do @@ -272,11 +273,11 @@ defmodule ElixirScript.Translator do end defp do_translate({:_, _, _}, env) do - { Primitive.make_identifier(:undefined), env } + { Identifier.make_identifier(:undefined), env } end defp do_translate({:__aliases__, _, aliases}, env) do - { Primitive.make_identifier({:__aliases__, [], aliases}), env } + { Identifier.make_identifier({:__aliases__, [], aliases}), env } end defp do_translate({:__MODULE__, _, _ }, env) do @@ -552,14 +553,14 @@ defmodule ElixirScript.Translator do defp do_translate({ name, _, params }, env) when is_atom(params) do cond do ElixirScript.Translator.LexicalScope.has_var?(env, name) -> - { Primitive.make_identifier(name), env } + { Identifier.make_identifier(name), env } has_function?(env.module, {name, 0}) -> Call.make_function_call(name, [], env) ElixirScript.Translator.LexicalScope.find_module(env, {name, 0}) -> imported_module_name = ElixirScript.Translator.LexicalScope.find_module(env, {name, 0}) Call.make_function_call(imported_module_name, name, params, env) true -> - { Primitive.make_identifier(name), env } + { Identifier.make_identifier(name), env } end end diff --git a/lib/elixir_script/translator/kernel/def.ex b/lib/elixir_script/translator/kernel/def.ex index 30e7815e..5f6f1c45 100644 --- a/lib/elixir_script/translator/kernel/def.ex +++ b/lib/elixir_script/translator/kernel/def.ex @@ -2,13 +2,13 @@ defmodule ElixirScript.Translator.Def do @moduledoc false alias ESTree.Tools.Builder, as: JS alias ElixirScript.Translator.Function - alias ElixirScript.Translator.Primitive + alias ElixirScript.Translator.Identifier def process_function(name, functions, env) do { result, _ } = Function.make_anonymous_function(functions, env, name) declarator = JS.variable_declarator( - Primitive.make_identifier(name), + Identifier.make_identifier(name), result ) diff --git a/lib/elixir_script/translator/kernel/defmodule.ex b/lib/elixir_script/translator/kernel/defmodule.ex index 94767175..3aa48e0d 100644 --- a/lib/elixir_script/translator/kernel/defmodule.ex +++ b/lib/elixir_script/translator/kernel/defmodule.ex @@ -6,7 +6,7 @@ defmodule ElixirScript.Translator.Defmodule do alias ElixirScript.Translator.Group alias ElixirScript.Translator.Def alias ElixirScript.ModuleSystems - alias ElixirScript.Translator.Primitive + alias ElixirScript.Translator.Identifier def make_module(ElixirScript.Temp, body, env) do { body, _ } = translate_body(body, env) @@ -45,7 +45,7 @@ defmodule ElixirScript.Translator.Defmodule do exported_object = JS.object_expression( make_defstruct_property(module, structs) ++ Enum.map(exported_functions, fn({key, _value}) -> - JS.property(Primitive.make_identifier(key), Primitive.make_identifier(key), :init, true) + JS.property(Identifier.make_identifier(key), Identifier.make_identifier(key), :init, true) end) ) @@ -180,7 +180,7 @@ defmodule ElixirScript.Translator.Defmodule do def make_attribute(name, value, env) do declarator = JS.variable_declarator( - Primitive.make_identifier(name), + Identifier.make_identifier(name), ElixirScript.Translator.translate!(value, env) ) diff --git a/lib/elixir_script/translator/kernel/defprotocol.ex b/lib/elixir_script/translator/kernel/defprotocol.ex index 40aaf009..4e10f3b1 100644 --- a/lib/elixir_script/translator/kernel/defprotocol.ex +++ b/lib/elixir_script/translator/kernel/defprotocol.ex @@ -6,7 +6,7 @@ defmodule ElixirScript.Translator.Defprotocol do alias ElixirScript.Translator.Map alias ElixirScript.Translator.Utils alias ElixirScript.ModuleSystems - alias ElixirScript.Translator.Primitive + alias ElixirScript.Translator.Identifier require Logger @doc """ @@ -25,7 +25,7 @@ defmodule ElixirScript.Translator.Defprotocol do object = process_spec_functions(functions) |> Enum.map(fn({key, value}) -> - Map.make_property(Primitive.make_identifier(key), value) + Map.make_property(Identifier.make_identifier(key), value) end) |> JS.object_expression diff --git a/lib/elixir_script/translator/kernel/special_forms/call.ex b/lib/elixir_script/translator/kernel/special_forms/call.ex index d1f677b5..f22a10dc 100644 --- a/lib/elixir_script/translator/kernel/special_forms/call.ex +++ b/lib/elixir_script/translator/kernel/special_forms/call.ex @@ -3,7 +3,7 @@ defmodule ElixirScript.Translator.Call do alias ESTree.Tools.Builder, as: JS alias ElixirScript.Translator alias ElixirScript.Translator.Utils - alias ElixirScript.Translator.Primitive + alias ElixirScript.Translator.Identifier def make_function_or_property_call(module_name, function_name, env) do @@ -61,7 +61,7 @@ defmodule ElixirScript.Translator.Call do call = JS.call_expression( JS.member_expression( Translator.translate!(module_name, env), - Primitive.make_identifier(function_name) + Identifier.make_identifier(function_name) ), Enum.map(params, &Translator.translate!(&1, env)) ) diff --git a/lib/elixir_script/translator/kernel/special_forms/capture.ex b/lib/elixir_script/translator/kernel/special_forms/capture.ex index d66ef324..1b806883 100644 --- a/lib/elixir_script/translator/kernel/special_forms/capture.ex +++ b/lib/elixir_script/translator/kernel/special_forms/capture.ex @@ -5,7 +5,7 @@ defmodule ElixirScript.Translator.Capture do alias ElixirScript.Translator.PatternMatching alias ElixirScript.Translator.Function alias ElixirScript.Translator.Call - alias ElixirScript.Translator.Primitive + alias ElixirScript.Translator.Identifier def make_capture(function_name, arity, env) do { patterns, params, _ } = process_params(arity, env) @@ -13,7 +13,7 @@ defmodule ElixirScript.Translator.Capture do body = JS.block_statement([ JS.return_statement( JS.call_expression( - Primitive.make_identifier(function_name), + Identifier.make_identifier(function_name), params ) ) diff --git a/lib/elixir_script/translator/kernel/special_forms/identifier.ex b/lib/elixir_script/translator/kernel/special_forms/identifier.ex new file mode 100644 index 00000000..37d9d2b5 --- /dev/null +++ b/lib/elixir_script/translator/kernel/special_forms/identifier.ex @@ -0,0 +1,73 @@ +defmodule ElixirScript.Translator.Identifier do + @moduledoc false + alias ESTree.Tools.Builder, as: JS + + @js_reserved_words [ + :break, + :case, + :class, + :const, + :continue, + :debugger, + :default, + :delete, + :do, + :else, + :export, + :extends, + :finally, + :function, + :if, + :import, + :in, + :instanceof, + :new, + :return, + :super, + :switch, + :throw, + :try, + :typeof, + :var, + :void, + :while, + :with, + :yield + ] + + + def make_identifier({:__aliases__, _, aliases}) do + aliases + |> Enum.reverse + |> make_alias + end + + def make_identifier([ast]) do + make_identifier(ast) + end + + def make_identifier(ast) do + ast + |> filter_name + |> JS.identifier + end + + defp filter_name(reserved_word) when reserved_word in @js_reserved_words do + "__#{Atom.to_string(reserved_word)}__" + end + + defp filter_name(name) do + to_string(name) + |> String.replace("?", "__qmark__") + |> String.replace("!", "__emark__") + end + + defp make_alias([x]) do + make_identifier(x) + end + + defp make_alias([h|t]) do + JS.member_expression(make_alias(t), make_identifier(h)) + end + +end diff --git a/lib/elixir_script/translator/kernel/special_forms/primitive.ex b/lib/elixir_script/translator/kernel/special_forms/primitive.ex index 8fa4d9c2..e5bdd1c8 100644 --- a/lib/elixir_script/translator/kernel/special_forms/primitive.ex +++ b/lib/elixir_script/translator/kernel/special_forms/primitive.ex @@ -3,7 +3,6 @@ defmodule ElixirScript.Translator.Primitive do alias ESTree.Tools.Builder, as: JS alias ElixirScript.Translator alias ElixirScript.Translator.Quote - alias ElixirScript.Translator.Utils def special_forms() do JS.member_expression( @@ -38,21 +37,6 @@ defmodule ElixirScript.Translator.Primitive do ) end - - def make_identifier({:__aliases__, _, aliases}) do - Utils.make_module_expression_tree(aliases, false, __ENV__) - end - - def make_identifier([ast]) do - make_identifier(ast) - end - - def make_identifier(ast) do - ast - |> Utils.filter_name - |> JS.identifier - end - def make_literal(ast) when is_number(ast) or is_binary(ast) or is_boolean(ast) or is_nil(ast) do JS.literal(ast) end diff --git a/lib/elixir_script/translator/pattern_matching.ex b/lib/elixir_script/translator/pattern_matching.ex index 8e8eb6f5..946e920e 100644 --- a/lib/elixir_script/translator/pattern_matching.ex +++ b/lib/elixir_script/translator/pattern_matching.ex @@ -4,6 +4,7 @@ defmodule ElixirScript.Translator.PatternMatching do alias ESTree.Tools.Builder, as: JS alias ElixirScript.Translator alias ElixirScript.Translator.Primitive + alias ElixirScript.Translator.Identifier alias ElixirScript.Translator.Map alias ElixirScript.Translator.Struct alias ElixirScript.Translator.Bitstring @@ -254,12 +255,12 @@ defmodule ElixirScript.Translator.PatternMatching do end defp do_build_match({:\\, _, [{name, _, _}, default]}, env) do - { [parameter(Translator.translate!(default, env))], [Primitive.make_identifier(name)] } + { [parameter(Translator.translate!(default, env))], [Identifier.make_identifier(name)] } end defp do_build_match({name, _, _}, _) do - { [parameter()], [Primitive.make_identifier(name)] } + { [parameter()], [Identifier.make_identifier(name)] } end defp reduce_patterns(patterns) do @@ -271,7 +272,7 @@ defmodule ElixirScript.Translator.PatternMatching do defp unify(target, source, env) do { patterns, params } = build_match([source], env) - { [capture(hd(patterns))], params ++ [Primitive.make_identifier(target)] } + { [capture(hd(patterns))], params ++ [Identifier.make_identifier(target)] } end end diff --git a/lib/elixir_script/translator/utils.ex b/lib/elixir_script/translator/utils.ex index 7ff6f684..4543b682 100644 --- a/lib/elixir_script/translator/utils.ex +++ b/lib/elixir_script/translator/utils.ex @@ -2,40 +2,7 @@ defmodule ElixirScript.Translator.Utils do @moduledoc false alias ESTree.Tools.Builder, as: JS alias ElixirScript.Translator - alias ElixirScript.Translator.Primitive - - @js_reserved_words [ - :break, - :case, - :class, - :const, - :continue, - :debugger, - :default, - :delete, - :do, - :else, - :export, - :extends, - :finally, - :function, - :if, - :import, - :in, - :instanceof, - :new, - :return, - :super, - :switch, - :throw, - :try, - :typeof, - :var, - :void, - :while, - :with, - :yield - ] + alias ElixirScript.Translator.Identifier def make_module_expression_tree([module], computed, env) do make_module_expression_tree(module, computed, env) @@ -45,17 +12,17 @@ defmodule ElixirScript.Translator.Utils do Enum.reduce(modules, nil, fn(x, ast) -> case ast do nil -> - JS.member_expression(Primitive.make_identifier(x), nil, computed) + JS.member_expression(Identifier.make_identifier(x), nil, computed) %ESTree.MemberExpression{ property: nil } -> - %{ ast | property: Primitive.make_identifier(x) } + %{ ast | property: Identifier.make_identifier(x) } _ -> - JS.member_expression(ast, Primitive.make_identifier(x), computed) + JS.member_expression(ast, Identifier.make_identifier(x), computed) end end) end def make_module_expression_tree(module, _computed, _) when is_binary(module) or is_atom(module) do - Primitive.make_identifier(module) + Identifier.make_identifier(module) end def make_module_expression_tree(module, _computed, env) do @@ -78,7 +45,7 @@ defmodule ElixirScript.Translator.Utils do def make_call_expression(function_name, params, env) do JS.call_expression( - Primitive.make_identifier(function_name), + Identifier.make_identifier(function_name), Enum.map(params, &Translator.translate!(&1, env)) ) end @@ -89,52 +56,42 @@ defmodule ElixirScript.Translator.Utils do ast = make_module_expression_tree(modules, computed, env) JS.member_expression( ast, - Primitive.make_identifier(function_name), + Identifier.make_identifier(function_name), computed ) modules when is_list(modules) and length(modules) == 1 -> JS.member_expression( - Primitive.make_identifier(hd(modules)), - Primitive.make_identifier(function_name), + Identifier.make_identifier(hd(modules)), + Identifier.make_identifier(function_name), computed ) {{:., _, [_module_name, _function_name]}, _, _params } = ast -> JS.member_expression( Translator.translate!(ast, env), - Primitive.make_identifier(function_name), + Identifier.make_identifier(function_name), computed ) {{:., _, [{:__aliases__, _, _}]}, _, _} = ast -> JS.member_expression( Translator.translate!(ast, env), - Primitive.make_identifier(function_name), + Identifier.make_identifier(function_name), computed ) {:., _, _} = ast -> JS.member_expression( Translator.translate!(ast, env), - Primitive.make_identifier(function_name), + Identifier.make_identifier(function_name), computed ) _ -> JS.member_expression( - Primitive.make_identifier(module_name), - Primitive.make_identifier(function_name), + Identifier.make_identifier(module_name), + Identifier.make_identifier(function_name), computed ) end end - def filter_name(reserved_word) when reserved_word in @js_reserved_words do - "__#{Atom.to_string(reserved_word)}__" - end - - def filter_name(name) do - to_string(name) - |> String.replace("?", "__qmark__") - |> String.replace("!", "__emark__") - end - def quoted_to_name(the_alias) do {name, _} = Code.eval_quoted(the_alias) name From e2f47478d30f7e7cb21df1cd5baf218ec93001a3 Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Fri, 27 May 2016 19:16:32 -0500 Subject: [PATCH 249/860] Refactored utils and moved functions only used by one module to that module --- .../translator/kernel/special_forms/call.ex | 95 ++++++++++++++++++- .../translator/kernel/special_forms/struct.ex | 10 +- lib/elixir_script/translator/utils.ex | 91 ------------------ 3 files changed, 95 insertions(+), 101 deletions(-) diff --git a/lib/elixir_script/translator/kernel/special_forms/call.ex b/lib/elixir_script/translator/kernel/special_forms/call.ex index f22a10dc..c78ae269 100644 --- a/lib/elixir_script/translator/kernel/special_forms/call.ex +++ b/lib/elixir_script/translator/kernel/special_forms/call.ex @@ -21,7 +21,7 @@ defmodule ElixirScript.Translator.Call do JS.identifier("call_property") ), [ - Utils.make_module_expression_tree(the_name, false, env), + make_module_expression_tree(the_name, false, env), Translator.translate!(to_string(function_name), env) ] ) @@ -50,11 +50,11 @@ defmodule ElixirScript.Translator.Call do def make_function_call(function_name, params, env) when is_tuple(function_name) do - { Utils.make_call_expression(function_name, params, env), env } + { make_call_expression(function_name, params, env), env } end def make_function_call(function_name, params, env) do - { Utils.make_call_expression(function_name, params, env), env } + { make_call_expression(function_name, params, env), env } end def make_function_call(module_name, function_name, params, env) when is_list(module_name) do @@ -71,7 +71,7 @@ defmodule ElixirScript.Translator.Call do def make_function_call(module_name, function_name, params, env) do the_name = get_module_name_for_function(module_name, env) - { Utils.make_call_expression(the_name, function_name, params, env), env } + { make_call_expression(the_name, function_name, params, env), env } end @@ -106,5 +106,92 @@ defmodule ElixirScript.Translator.Call do end + defp make_call_expression(module_name, function_name, params, env) do + JS.call_expression( + make_member_expression(module_name, function_name, env), + Enum.map(params, &Translator.translate!(&1, env)) + ) + end + + defp make_call_expression(function_name, params, env) when is_tuple(function_name) do + JS.call_expression( + Translator.translate!(function_name, env), + Enum.map(params, &Translator.translate!(&1, env)) + ) + end + + defp make_call_expression(function_name, params, env) do + JS.call_expression( + Identifier.make_identifier(function_name), + Enum.map(params, &Translator.translate!(&1, env)) + ) + end + + + def make_member_expression(module_name, function_name, env, computed \\ false) do + case module_name do + modules when is_list(modules) and length(modules) > 1 -> + ast = make_module_expression_tree(modules, computed, env) + JS.member_expression( + ast, + Identifier.make_identifier(function_name), + computed + ) + modules when is_list(modules) and length(modules) == 1 -> + JS.member_expression( + Identifier.make_identifier(hd(modules)), + Identifier.make_identifier(function_name), + computed + ) + {{:., _, [_module_name, _function_name]}, _, _params } = ast -> + JS.member_expression( + Translator.translate!(ast, env), + Identifier.make_identifier(function_name), + computed + ) + {{:., _, [{:__aliases__, _, _}]}, _, _} = ast -> + JS.member_expression( + Translator.translate!(ast, env), + Identifier.make_identifier(function_name), + computed + ) + {:., _, _} = ast -> + JS.member_expression( + Translator.translate!(ast, env), + Identifier.make_identifier(function_name), + computed + ) + _ -> + JS.member_expression( + Identifier.make_identifier(module_name), + Identifier.make_identifier(function_name), + computed + ) + end + end + + defp make_module_expression_tree([module], computed, env) do + make_module_expression_tree(module, computed, env) + end + + defp make_module_expression_tree(modules, computed, _) when is_list(modules) do + Enum.reduce(modules, nil, fn(x, ast) -> + case ast do + nil -> + JS.member_expression(Identifier.make_identifier(x), nil, computed) + %ESTree.MemberExpression{ property: nil } -> + %{ ast | property: Identifier.make_identifier(x) } + _ -> + JS.member_expression(ast, Identifier.make_identifier(x), computed) + end + end) + end + + defp make_module_expression_tree(module, _, _) when is_binary(module) or is_atom(module) do + Identifier.make_identifier(module) + end + defp make_module_expression_tree(module, _, env) do + Translator.translate!(module, env) end +end diff --git a/lib/elixir_script/translator/kernel/special_forms/struct.ex b/lib/elixir_script/translator/kernel/special_forms/struct.ex index de4beb56..f4f24277 100644 --- a/lib/elixir_script/translator/kernel/special_forms/struct.ex +++ b/lib/elixir_script/translator/kernel/special_forms/struct.ex @@ -4,6 +4,7 @@ defmodule ElixirScript.Translator.Struct do alias ElixirScript.Translator alias ElixirScript.Translator.Utils alias ElixirScript.Translator.Map + alias ElixirScript.Translator.Identifier def get_struct_class(module_name, env) do candiate_module_name = Utils.quoted_to_name(module_name) @@ -11,14 +12,11 @@ defmodule ElixirScript.Translator.Struct do if ElixirScript.Translator.LexicalScope.get_module_name(env, candiate_module_name) in ElixirScript.Translator.State.list_module_names() do name = ElixirScript.Translator.LexicalScope.get_module_name(env, candiate_module_name) - - JS.member_expression( - JS.identifier(Utils.name_to_js_name(name)), - JS.identifier(Utils.name_to_js_name(name)) - ) + ident = JS.identifier(Utils.name_to_js_name(name)) + JS.member_expression(ident, ident) else - Utils.make_module_expression_tree(module_name, false, env) + Identifier.make_identifier(module_name) end end diff --git a/lib/elixir_script/translator/utils.ex b/lib/elixir_script/translator/utils.ex index 4543b682..f4fa29d6 100644 --- a/lib/elixir_script/translator/utils.ex +++ b/lib/elixir_script/translator/utils.ex @@ -1,96 +1,5 @@ defmodule ElixirScript.Translator.Utils do @moduledoc false - alias ESTree.Tools.Builder, as: JS - alias ElixirScript.Translator - alias ElixirScript.Translator.Identifier - - def make_module_expression_tree([module], computed, env) do - make_module_expression_tree(module, computed, env) - end - - def make_module_expression_tree(modules, computed, _) when is_list(modules) do - Enum.reduce(modules, nil, fn(x, ast) -> - case ast do - nil -> - JS.member_expression(Identifier.make_identifier(x), nil, computed) - %ESTree.MemberExpression{ property: nil } -> - %{ ast | property: Identifier.make_identifier(x) } - _ -> - JS.member_expression(ast, Identifier.make_identifier(x), computed) - end - end) - end - - def make_module_expression_tree(module, _computed, _) when is_binary(module) or is_atom(module) do - Identifier.make_identifier(module) - end - - def make_module_expression_tree(module, _computed, env) do - Translator.translate!(module, env) - end - - def make_call_expression(module_name, function_name, params, env) do - JS.call_expression( - make_member_expression(module_name, function_name, env), - Enum.map(params, &Translator.translate!(&1, env)) - ) - end - - def make_call_expression(function_name, params, env) when is_tuple(function_name) do - JS.call_expression( - Translator.translate!(function_name, env), - Enum.map(params, &Translator.translate!(&1, env)) - ) - end - - def make_call_expression(function_name, params, env) do - JS.call_expression( - Identifier.make_identifier(function_name), - Enum.map(params, &Translator.translate!(&1, env)) - ) - end - - def make_member_expression(module_name, function_name, env, computed \\ false) do - case module_name do - modules when is_list(modules) and length(modules) > 1 -> - ast = make_module_expression_tree(modules, computed, env) - JS.member_expression( - ast, - Identifier.make_identifier(function_name), - computed - ) - modules when is_list(modules) and length(modules) == 1 -> - JS.member_expression( - Identifier.make_identifier(hd(modules)), - Identifier.make_identifier(function_name), - computed - ) - {{:., _, [_module_name, _function_name]}, _, _params } = ast -> - JS.member_expression( - Translator.translate!(ast, env), - Identifier.make_identifier(function_name), - computed - ) - {{:., _, [{:__aliases__, _, _}]}, _, _} = ast -> - JS.member_expression( - Translator.translate!(ast, env), - Identifier.make_identifier(function_name), - computed - ) - {:., _, _} = ast -> - JS.member_expression( - Translator.translate!(ast, env), - Identifier.make_identifier(function_name), - computed - ) - _ -> - JS.member_expression( - Identifier.make_identifier(module_name), - Identifier.make_identifier(function_name), - computed - ) - end - end def quoted_to_name(the_alias) do {name, _} = Code.eval_quoted(the_alias) From 17827d393901ba01849b4d853d1fb41823df2271 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ren=C3=A9=20F=C3=B6hring?= Date: Sat, 28 May 2016 14:21:04 +0200 Subject: [PATCH 250/860] Add deps badge to README [ci skip] --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 6425745d..5776df1f 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -## ElixirScript [![Documentation](https://img.shields.io/badge/docs-hexpm-blue.svg)](http://hexdocs.pm/elixir_script/) [![Build](https://travis-ci.org/bryanjos/elixirscript.svg?branch=master)](https://travis-ci.org/bryanjos/elixirscript) +## ElixirScript [![Documentation](https://img.shields.io/badge/docs-hexpm-blue.svg)](http://hexdocs.pm/elixir_script/) [![Build](https://travis-ci.org/bryanjos/elixirscript.svg?branch=master)](https://travis-ci.org/bryanjos/elixirscript) [![Deps Status](https://beta.hexfaktor.org/badge/all/github/bryanjos/elixirscript.svg)](https://beta.hexfaktor.org/github/bryanjos/elixirscript) The goal is to convert a subset (or full set) of Elixir code to JavaScript, providing the ability to write JavaScript in Elixir. This is done by taking the Elixir AST and converting it into JavaScript AST and then to JavaScript code. This is done using the [Elixir-ESTree](https://github.com/bryanjos/elixir-estree) library. From d112d4ed9287e39a6bd14cd610b2b6cea41c64b4 Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Sun, 5 Jun 2016 11:17:16 -0500 Subject: [PATCH 251/860] Update README.md --- README.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/README.md b/README.md index 5776df1f..cd916f51 100644 --- a/README.md +++ b/README.md @@ -51,6 +51,11 @@ core JavaScript files needed for ElixirScript. To change the location, update the `lib_path` config variable in the `:elixir_script` config block to the path to look in and then do a clean build. +Communication +======== + +[#elixirscript](https://elixir-lang.slack.com/messages/elixirscript/) on the elixir-lang Slack + Contributing ======== From 7ded8db4fd98d88880011ffe7fc3716327bede69 Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Wed, 8 Jun 2016 10:15:23 -0500 Subject: [PATCH 252/860] Removed processes folder in favor of using erlang-processes library --- package.json | 14 +- rollup.config.js | 18 ++ src/javascript/lib/core.js | 8 +- src/javascript/lib/core/processes/mailbox.js | 30 ---- src/javascript/lib/core/processes/process.js | 20 --- .../lib/core/processes/process_system.js | 158 ------------------ src/javascript/lib/core/processes/states.js | 15 -- 7 files changed, 32 insertions(+), 231 deletions(-) create mode 100644 rollup.config.js delete mode 100644 src/javascript/lib/core/processes/mailbox.js delete mode 100644 src/javascript/lib/core/processes/process.js delete mode 100644 src/javascript/lib/core/processes/process_system.js delete mode 100644 src/javascript/lib/core/processes/states.js diff --git a/package.json b/package.json index ef01b487..0eaebfb0 100644 --- a/package.json +++ b/package.json @@ -8,8 +8,8 @@ }, "scripts": { "lint": "eslint src/javascript/lib/**/*.js src/javascript/tests/**/*.js", - "build": "gulp build && rollup -m inline src/elixirscript/elixir.js -o priv/Elixir.js", - "clean": "rm -rf src/javascript/dist_build", + "build": "rollup -c rollup.config.js", + "clean": "rm -rf priv", "test": "mocha src/javascript/tests --recursive --compilers js:babel-core/register" }, "repository": { @@ -18,11 +18,15 @@ }, "author": "", "license": "MIT", - "dependencies": {}, + "dependencies": { + "erlang-processes": "^1.0.2" + }, "devDependencies": { "babel": "^6.5.2", "babel-core": "^6.7.7", + "babel-plugin-transform-class-properties": "^6.9.1", "babel-preset-es2015": "^6.6.0", + "babel-preset-es2015-rollup": "^1.1.1", "babel-preset-react": "^6.5.0", "babel-preset-stage-0": "^6.5.0", "chai": "^3.5.0", @@ -31,6 +35,8 @@ "gulp-babel": "^6.1.2", "gulp-sourcemaps": "^2.0.0-alpha", "mocha": "^2.4.5", - "rollup": "^0.26.1" + "rollup": "^0.28.0", + "rollup-plugin-babel": "^2.5.1", + "rollup-plugin-node-resolve": "^1.7.0" } } diff --git a/rollup.config.js b/rollup.config.js new file mode 100644 index 00000000..758136ff --- /dev/null +++ b/rollup.config.js @@ -0,0 +1,18 @@ +import { rollup } from 'rollup'; +import nodeResolve from 'rollup-plugin-node-resolve'; +import babel from 'rollup-plugin-babel'; + +export default { + entry: 'src/javascript/elixir.js', + dest: 'priv/Elixir.js', + sourceMap: 'inline', + format: 'es6', + plugins: [ + nodeResolve({ jsnext: true }), + babel({ + presets: ["react"], + plugins: ["transform-class-properties"], + babelrc: false + }) + ] +}; diff --git a/src/javascript/lib/core.js b/src/javascript/lib/core.js index f55eca1f..aba8b66c 100644 --- a/src/javascript/lib/core.js +++ b/src/javascript/lib/core.js @@ -1,14 +1,14 @@ -import ProcessSystem from './core/processes/process_system'; +import Processes from 'erlang-processes'; import { Tuple, PID, Integer, Float } from './core/primitives'; import BitString from './core/bit_string'; import Patterns from './core/patterns'; import Functions from './core/functions'; import SpecialForms from './core/special_forms'; -Functions.get_global().processes = Functions.get_global().processes || new ProcessSystem(); +Functions.get_global().processes = Functions.get_global().processes || new Processes.ProcessSystem(); export default { - ProcessSystem, + ProcessSystem: Processes.ProcessSystem, Tuple, PID, BitString, @@ -17,4 +17,4 @@ export default { Float, Functions, SpecialForms -} +}; diff --git a/src/javascript/lib/core/processes/mailbox.js b/src/javascript/lib/core/processes/mailbox.js deleted file mode 100644 index 10b69f1d..00000000 --- a/src/javascript/lib/core/processes/mailbox.js +++ /dev/null @@ -1,30 +0,0 @@ -"use strict"; - -/* @flow */ - -class Mailbox{ - messages: Array - - constructor(){ - this.messages = []; - } - - deliver(message: any){ - this.messages.push(message); - return message; - } - - get(){ - return this.messages; - } - - isEmpty(){ - return this.messages.length === 0; - } - - removeAt(index){ - this.messages.splice(index, 1); - } -} - -export default Mailbox; \ No newline at end of file diff --git a/src/javascript/lib/core/processes/process.js b/src/javascript/lib/core/processes/process.js deleted file mode 100644 index abe9ddf8..00000000 --- a/src/javascript/lib/core/processes/process.js +++ /dev/null @@ -1,20 +0,0 @@ -"use strict"; - -/* @flow */ -import Mailbox from "./mailbox"; -import States from "./states"; - -class Process { - pid: Number; - mailbox: Mailbox; - dict: Object; - - constructor(pid: Number, mailbox: Mailbox){ - this.pid = pid; - this.mailbox = mailbox; - this.status = States.STOPPED; - this.dict = {}; - } -} - -export default Process; diff --git a/src/javascript/lib/core/processes/process_system.js b/src/javascript/lib/core/processes/process_system.js deleted file mode 100644 index a28e2243..00000000 --- a/src/javascript/lib/core/processes/process_system.js +++ /dev/null @@ -1,158 +0,0 @@ -/* @flow */ -"use strict"; - -import Mailbox from "./mailbox"; -import Process from "./process"; -import States from "./states"; -import * as Primitives from "../primitives"; - -class ProcessSystem { - - constructor(){ - this.pids = new Map(); - this.mailboxes = new Map(); - this.names = new Map(); - this.links = new Map(); - - this.current_process = null; - this.suspended = new Map(); - - this.main_process_pid = this.spawn(); - this.set_current(this.main_process_pid); - } - - spawn(){ - return this.add_proc(false).pid; - } - - spawn_link(){ - return this.add_proc(true).pid; - } - - link(pid){ - this.links.get(this.pid()).add(pid); - this.links.get(pid).add(this.pid()); - } - - unlink(pid){ - this.links.get(this.pid()).delete(pid); - this.links.get(pid).delete(this.pid()); - } - - set_current(id){ - let pid = this.pidof(id); - if(pid !== null){ - this.current_process = this.pids.get(pid); - this.current_process.status = States.RUNNING; - } - } - - add_proc(linked){ - let newpid = new Primitives.PID(); - let mailbox = new Mailbox(); - let newproc = new Process(newpid, mailbox); - - this.pids.set(newpid, newproc); - this.mailboxes.set(newpid, mailbox); - this.links.set(newpid, new Set()); - - if(linked){ - this.link(newpid); - } - - return newproc; - } - - remove_proc(pid){ - this.pids.delete(pid); - this.unregister(pid); - - if(this.links.has(pid)){ - for (let linkpid of this.links.get(pid)) { - this.links.get(linkpid).delete(pid); - } - - this.links.delete(pid); - } - } - - exit(id){ - let pid = this.pidof(id); - this.remove_proc(id); - } - - register(name, pid){ - if(!this.names.has(name)){ - this.names.set(name, pid) - return name; - }else{ - throw new Error("Name is already registered to another process"); - } - } - - registered(name){ - return this.names.has(name) ? this.names.get(name) : null; - } - - unregister(pid){ - for(let name of this.names.keys()){ - if(this.names.has(name) && this.names.get(name) === pid){ - this.names.delete(name); - } - } - } - - pid(){ - return this.current_process.pid; - } - - pidof(id){ - if (id instanceof Primitives.PID) { - return this.pids.has(id) ? id : null; - } else if (id instanceof Process) { - return id.pid; - } else { - let pid = this.registered(id); - if (pid === null) - throw("Process name not registered: " + id + " (" + typeof(id) + ")"); - return pid; - } - } - - put(id, key, value){ - let pid = this.pidof(id); - let process = this.pids.get(pid); - process.dict[key] = value; - } - - get(id, key){ - let pid = this.pidof(id); - let process = this.pids.get(pid); - - if(key != null){ - return process.dict[key]; - }else{ - return process.dict; - } - } - - get_keys(id){ - let pid = this.pidof(id); - let process = this.pids.get(pid); - - return Object.keys(process.dict); - } - - erase(id, key){ - let pid = this.pidof(id); - let process = this.pids.get(pid); - - if(key != null){ - delete process.dict[key]; - }else{ - process.dict = {}; - } - } -} - -export default ProcessSystem; diff --git a/src/javascript/lib/core/processes/states.js b/src/javascript/lib/core/processes/states.js deleted file mode 100644 index 24294ecd..00000000 --- a/src/javascript/lib/core/processes/states.js +++ /dev/null @@ -1,15 +0,0 @@ -export default { - NORMAL: Symbol.for("normal"), - KILL: Symbol.for("kill"), - SUSPEND: Symbol.for("suspend"), - CONTINUE: Symbol.for("continue"), - RECEIVE: Symbol.for("receive"), - SEND: Symbol.for("send"), - SLEEPING: Symbol.for("sleeping"), - RUNNING: Symbol.for("running"), - SUSPENDED: Symbol.for("suspended"), - STOPPED: Symbol.for("stopped"), - SLEEP: Symbol.for("sleep"), - EXIT: Symbol.for("exit"), - NOMATCH: Symbol.for("no_match") -} \ No newline at end of file From 87c9c320662aa84631af570ce508bb9002ee734f Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Wed, 8 Jun 2016 11:55:24 -0500 Subject: [PATCH 253/860] Turning function calls into yields and functions into generators --- lib/elixir_script/translator.ex | 8 +-- .../translator/kernel/special_forms/block.ex | 24 +++++++- .../translator/kernel/special_forms/call.ex | 61 ++++++++++++------- .../translator/kernel/special_forms/fn.ex | 16 ++--- .../kernel/special_forms/primitive.ex | 10 +++ lib/elixir_script/watcher.ex | 2 + mix.exs | 2 +- src/javascript/lib/core/functions.js | 19 ++++-- src/javascript/lib/core/patterns/defmatch.js | 4 +- 9 files changed, 98 insertions(+), 48 deletions(-) diff --git a/lib/elixir_script/translator.ex b/lib/elixir_script/translator.ex index 3b624db8..49c58119 100644 --- a/lib/elixir_script/translator.ex +++ b/lib/elixir_script/translator.ex @@ -75,13 +75,7 @@ defmodule ElixirScript.Translator do end defp do_translate(ast, env) when is_atom(ast) do - str = Atom.to_string(ast) - - quoted = quote do - Symbol.for(unquote(str)) - end - - translate(quoted, env) + { Primitive.make_atom(ast), env } end defp do_translate([ {:|, _, [left, right] } ], env) do diff --git a/lib/elixir_script/translator/kernel/special_forms/block.ex b/lib/elixir_script/translator/kernel/special_forms/block.ex index 2173e1ae..66244b82 100644 --- a/lib/elixir_script/translator/kernel/special_forms/block.ex +++ b/lib/elixir_script/translator/kernel/special_forms/block.ex @@ -1,14 +1,32 @@ defmodule ElixirScript.Translator.Block do @moduledoc false - alias ESTree.Tools.Builder + alias ESTree.Tools.Builder, as: JS alias ElixirScript.Translator def make_block(expressions, env) do { list, env } = Enum.map_reduce(expressions, env, fn(x, updated_env) -> - Translator.translate(x, updated_env) + {item, updated_env } = Translator.translate(x, updated_env) + {process_call(item), updated_env} end) - { Builder.block_statement(list), env } + { JS.block_statement(list), env } + end + + defp process_call(item) do + case item do + %ESTree.CallExpression{ callee: %ESTree.MemberExpression{ object: %ESTree.Identifier{ name: :Object }, property: %ESTree.Identifier{ name: :freeze }} } -> + item + %ESTree.CallExpression{ callee: %ESTree.MemberExpression{ object: %ESTree.Identifier{ name: "Symbol" }, property: %ESTree.Identifier{ name: "for" }} } -> + item + %ESTree.CallExpression{}-> + JS.yield_expression(item, true) + %ESTree.BinaryExpression{ left: %ESTree.CallExpression{} }-> + JS.yield_expression(item, true) + %ESTree.BinaryExpression{ right: %ESTree.CallExpression{} }-> + JS.yield_expression(item, true) + _ -> + item + end end end diff --git a/lib/elixir_script/translator/kernel/special_forms/call.ex b/lib/elixir_script/translator/kernel/special_forms/call.ex index c78ae269..3383fca8 100644 --- a/lib/elixir_script/translator/kernel/special_forms/call.ex +++ b/lib/elixir_script/translator/kernel/special_forms/call.ex @@ -58,7 +58,7 @@ defmodule ElixirScript.Translator.Call do end def make_function_call(module_name, function_name, params, env) when is_list(module_name) do - call = JS.call_expression( + call = make_gen_call( JS.member_expression( Translator.translate!(module_name, env), Identifier.make_identifier(function_name) @@ -74,6 +74,43 @@ defmodule ElixirScript.Translator.Call do { make_call_expression(the_name, function_name, params, env), env } end + defp make_call_expression(module_name, function_name, params, env) do + make_gen_call( + make_member_expression(module_name, function_name, env), + Enum.map(params, &Translator.translate!(&1, env)) + ) + end + + defp make_call_expression(function_name, params, env) when is_tuple(function_name) do + make_gen_call( + Translator.translate!(function_name, env), + Enum.map(params, &Translator.translate!(&1, env)) + ) + end + + defp make_call_expression(function_name, params, env) do + make_gen_call( + Identifier.make_identifier(function_name), + Enum.map(params, &Translator.translate!(&1, env)) + ) + end + + defp make_gen_call(func, params) do + JS.call_expression( + JS.member_expression( + JS.member_expression( + JS.identifier("Elixir"), + JS.member_expression( + JS.identifier("Core"), + JS.identifier("Functions") + ) + ), + JS.identifier("run") + ), + [func, JS.array_expression(params)] + ) + end + defp get_js_name([Elixir | _] = list, _) do list @@ -106,28 +143,6 @@ defmodule ElixirScript.Translator.Call do end - defp make_call_expression(module_name, function_name, params, env) do - JS.call_expression( - make_member_expression(module_name, function_name, env), - Enum.map(params, &Translator.translate!(&1, env)) - ) - end - - defp make_call_expression(function_name, params, env) when is_tuple(function_name) do - JS.call_expression( - Translator.translate!(function_name, env), - Enum.map(params, &Translator.translate!(&1, env)) - ) - end - - defp make_call_expression(function_name, params, env) do - JS.call_expression( - Identifier.make_identifier(function_name), - Enum.map(params, &Translator.translate!(&1, env)) - ) - end - - def make_member_expression(module_name, function_name, env, computed \\ false) do case module_name do modules when is_list(modules) and length(modules) > 1 -> diff --git a/lib/elixir_script/translator/kernel/special_forms/fn.ex b/lib/elixir_script/translator/kernel/special_forms/fn.ex index 2372e8fe..c4415628 100644 --- a/lib/elixir_script/translator/kernel/special_forms/fn.ex +++ b/lib/elixir_script/translator/kernel/special_forms/fn.ex @@ -103,11 +103,11 @@ defmodule ElixirScript.Translator.Function do def make_function_clause(patterns, params, body, guard_body) do arguments = [ JS.array_expression(patterns), - JS.function_expression(params, [], body), + JS.function_expression(params, [], body, true), ] if guard_body do - arguments = arguments ++ [JS.function_expression(params, [], guard_body)] + arguments = arguments ++ [JS.function_expression(params, [], guard_body, true)] end JS.call_expression( @@ -159,6 +159,8 @@ defmodule ElixirScript.Translator.Function do last_item = List.last(list) last_item = case last_item do + %ESTree.YieldExpression{} -> + JS.return_statement(last_item) %ESTree.Literal{} -> JS.return_statement(last_item) %ESTree.Identifier{} -> @@ -181,11 +183,11 @@ defmodule ElixirScript.Translator.Function do %ESTree.BlockStatement{} -> last_item = %ESTree.BlockStatement{ last_item | body: return_last_expression(last_item.body) } _ -> - if String.contains?(last_item.type, "Expression") do - JS.return_statement(last_item) - else - [last_item, JS.return_statement(JS.literal(nil))] - end + if String.contains?(last_item.type, "Expression") do + JS.return_statement(last_item) + else + [last_item, JS.return_statement(JS.literal(nil))] + end end diff --git a/lib/elixir_script/translator/kernel/special_forms/primitive.ex b/lib/elixir_script/translator/kernel/special_forms/primitive.ex index e5bdd1c8..b4924306 100644 --- a/lib/elixir_script/translator/kernel/special_forms/primitive.ex +++ b/lib/elixir_script/translator/kernel/special_forms/primitive.ex @@ -37,6 +37,16 @@ defmodule ElixirScript.Translator.Primitive do ) end + def make_atom(ast) when is_atom(ast) do + JS.call_expression( + JS.member_expression( + JS.identifier("Symbol"), + JS.identifier("for") + ), + [JS.literal(ast)] + ) + end + def make_literal(ast) when is_number(ast) or is_binary(ast) or is_boolean(ast) or is_nil(ast) do JS.literal(ast) end diff --git a/lib/elixir_script/watcher.ex b/lib/elixir_script/watcher.ex index 436a03ed..ba4861d2 100644 --- a/lib/elixir_script/watcher.ex +++ b/lib/elixir_script/watcher.ex @@ -13,6 +13,8 @@ defmodule ElixirScript.Watcher do def init(args) do {:ok, _} = Application.ensure_all_started(:elixir_script) + {:ok, _} = Application.ensure_all_started(:fs) + :fs.subscribe() {:ok, args} end diff --git a/mix.exs b/mix.exs index 7ad736d6..3c3be636 100644 --- a/mix.exs +++ b/mix.exs @@ -22,7 +22,7 @@ defmodule ElixirScript.Mixfile do def application do [ - applications: [:logger, :estree, :fs] + applications: [:logger, :estree] ] end diff --git a/src/javascript/lib/core/functions.js b/src/javascript/lib/core/functions.js index 0cc6500d..f1a0d22b 100644 --- a/src/javascript/lib/core/functions.js +++ b/src/javascript/lib/core/functions.js @@ -3,7 +3,7 @@ import BitString from './bit_string'; import Patterns from './patterns'; import Protocol from './protocol'; -function call_property(item, property){ +function* call_property(item, property){ let prop = null; if(typeof item === "number" || typeof item === "symbol" || typeof item === "boolean" || typeof item === "string"){ @@ -21,16 +21,24 @@ function call_property(item, property){ } if(prop === null){ - throw new Error(`Property ${ property } not found in ${ item }`); + throw new Error(`Property ${ property } not found in ${ item }`); } if(item[prop] instanceof Function){ - return item[prop](); + return yield* item[prop](); }else{ - return item[prop]; + return yield item[prop]; } } +function* run(fun, args, context = null){ + if(fun.constructor.name === "GeneratorFunction"){ + return yield* fun.apply(context, args); + } + + return yield fun.apply(context, args); +} + function apply(...args){ if(args.length === 2){ args[0].apply(null, args.slice(1)); @@ -298,7 +306,7 @@ function keytake(key, n, list){ } function keyreplace(key, n, list, newtuple){ - + for(let i = tuplelist.length - 1; i >= 0; i--){ if(tuplelist[i].get(n) === key){ return tuplelist.concat([]).splice(i, 1, newtuple); @@ -396,6 +404,7 @@ function maps_from_list(list){ export default { call_property, + run, apply, contains, get_global, diff --git a/src/javascript/lib/core/patterns/defmatch.js b/src/javascript/lib/core/patterns/defmatch.js index b9988a27..7a952940 100644 --- a/src/javascript/lib/core/patterns/defmatch.js +++ b/src/javascript/lib/core/patterns/defmatch.js @@ -43,13 +43,13 @@ export function make_case(pattern: Array, fn: Function, guard: Function = ( } export function defmatch(...cases: Array): Function { - return function(...args: Array): any { + return function* (...args: Array): any { for (let processedCase of cases) { let result = []; args = fillInOptionalValues(args, processedCase.arity, processedCase.optionals); if (processedCase.pattern(args, result) && processedCase.guard.apply(this, result)) { - return processedCase.fn.apply(this, result); + return yield* processedCase.fn.apply(this, result); } } From a6d3fabfeeefdebb30688eacbc6313a1db2f8b98 Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Wed, 8 Jun 2016 13:03:37 -0500 Subject: [PATCH 254/860] Trying to find best way to yield functions --- .../translator/kernel/special_forms/block.ex | 24 +++++++++++++++---- .../translator/kernel/special_forms/call.ex | 24 ++++--------------- .../kernel/special_forms/primitive.ex | 4 ++-- 3 files changed, 26 insertions(+), 26 deletions(-) diff --git a/lib/elixir_script/translator/kernel/special_forms/block.ex b/lib/elixir_script/translator/kernel/special_forms/block.ex index 66244b82..ace96b32 100644 --- a/lib/elixir_script/translator/kernel/special_forms/block.ex +++ b/lib/elixir_script/translator/kernel/special_forms/block.ex @@ -14,19 +14,35 @@ defmodule ElixirScript.Translator.Block do defp process_call(item) do case item do - %ESTree.CallExpression{ callee: %ESTree.MemberExpression{ object: %ESTree.Identifier{ name: :Object }, property: %ESTree.Identifier{ name: :freeze }} } -> + %ESTree.CallExpression{ callee: %ESTree.MemberExpression{ object: %ESTree.Identifier{ name: "Object" }, property: %ESTree.Identifier{ name: "freeze" }} } -> item %ESTree.CallExpression{ callee: %ESTree.MemberExpression{ object: %ESTree.Identifier{ name: "Symbol" }, property: %ESTree.Identifier{ name: "for" }} } -> item %ESTree.CallExpression{}-> - JS.yield_expression(item, true) + item %ESTree.BinaryExpression{ left: %ESTree.CallExpression{} }-> - JS.yield_expression(item, true) + item %ESTree.BinaryExpression{ right: %ESTree.CallExpression{} }-> - JS.yield_expression(item, true) + item _ -> item end end + defp make_gen_call(func, params) do + JS.call_expression( + JS.member_expression( + JS.member_expression( + JS.identifier("Elixir"), + JS.member_expression( + JS.identifier("Core"), + JS.identifier("Functions") + ) + ), + JS.identifier("run") + ), + [func, JS.array_expression(params)] + ) + end + end diff --git a/lib/elixir_script/translator/kernel/special_forms/call.ex b/lib/elixir_script/translator/kernel/special_forms/call.ex index 3383fca8..3fa62a23 100644 --- a/lib/elixir_script/translator/kernel/special_forms/call.ex +++ b/lib/elixir_script/translator/kernel/special_forms/call.ex @@ -58,7 +58,7 @@ defmodule ElixirScript.Translator.Call do end def make_function_call(module_name, function_name, params, env) when is_list(module_name) do - call = make_gen_call( + call = JS.call_expression( JS.member_expression( Translator.translate!(module_name, env), Identifier.make_identifier(function_name) @@ -75,42 +75,26 @@ defmodule ElixirScript.Translator.Call do end defp make_call_expression(module_name, function_name, params, env) do - make_gen_call( + JS.call_expression( make_member_expression(module_name, function_name, env), Enum.map(params, &Translator.translate!(&1, env)) ) end defp make_call_expression(function_name, params, env) when is_tuple(function_name) do - make_gen_call( + JS.call_expression( Translator.translate!(function_name, env), Enum.map(params, &Translator.translate!(&1, env)) ) end defp make_call_expression(function_name, params, env) do - make_gen_call( + JS.call_expression( Identifier.make_identifier(function_name), Enum.map(params, &Translator.translate!(&1, env)) ) end - defp make_gen_call(func, params) do - JS.call_expression( - JS.member_expression( - JS.member_expression( - JS.identifier("Elixir"), - JS.member_expression( - JS.identifier("Core"), - JS.identifier("Functions") - ) - ), - JS.identifier("run") - ), - [func, JS.array_expression(params)] - ) - end - defp get_js_name([Elixir | _] = list, _) do list diff --git a/lib/elixir_script/translator/kernel/special_forms/primitive.ex b/lib/elixir_script/translator/kernel/special_forms/primitive.ex index b4924306..25cea0c3 100644 --- a/lib/elixir_script/translator/kernel/special_forms/primitive.ex +++ b/lib/elixir_script/translator/kernel/special_forms/primitive.ex @@ -70,8 +70,8 @@ defmodule ElixirScript.Translator.Primitive do def do_make_list(ast) do JS.call_expression( JS.member_expression( - JS.identifier(:Object), - JS.identifier(:freeze) + JS.identifier("Object"), + JS.identifier("freeze") ), [JS.array_expression(ast)] ) From 2779c001215413d6bc40c832699fb45df54f4f8a Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Wed, 15 Jun 2016 12:42:48 -0500 Subject: [PATCH 255/860] Add in_process to lexical_scope. Removed created of generators --- .../translator/kernel/special_forms/block.ex | 14 +++++++++----- .../translator/kernel/special_forms/fn.ex | 10 ++++++---- lib/elixir_script/translator/lexical_scope.ex | 2 ++ src/javascript/lib/core/functions.js | 6 +++--- src/javascript/lib/core/patterns/defmatch.js | 2 +- 5 files changed, 21 insertions(+), 13 deletions(-) diff --git a/lib/elixir_script/translator/kernel/special_forms/block.ex b/lib/elixir_script/translator/kernel/special_forms/block.ex index ace96b32..2935508d 100644 --- a/lib/elixir_script/translator/kernel/special_forms/block.ex +++ b/lib/elixir_script/translator/kernel/special_forms/block.ex @@ -6,29 +6,33 @@ defmodule ElixirScript.Translator.Block do def make_block(expressions, env) do { list, env } = Enum.map_reduce(expressions, env, fn(x, updated_env) -> {item, updated_env } = Translator.translate(x, updated_env) - {process_call(item), updated_env} + {process_call(item, env), updated_env} end) { JS.block_statement(list), env } end - defp process_call(item) do + def process_call(item, %ElixirScript.Translator.LexicalScope{ in_process: true }) do case item do %ESTree.CallExpression{ callee: %ESTree.MemberExpression{ object: %ESTree.Identifier{ name: "Object" }, property: %ESTree.Identifier{ name: "freeze" }} } -> item %ESTree.CallExpression{ callee: %ESTree.MemberExpression{ object: %ESTree.Identifier{ name: "Symbol" }, property: %ESTree.Identifier{ name: "for" }} } -> item %ESTree.CallExpression{}-> - item + JS.yield_expression(item, true) %ESTree.BinaryExpression{ left: %ESTree.CallExpression{} }-> - item + JS.yield_expression(item, true) %ESTree.BinaryExpression{ right: %ESTree.CallExpression{} }-> - item + JS.yield_expression(item, true) _ -> item end end + def process_call(item, _) do + item + end + defp make_gen_call(func, params) do JS.call_expression( JS.member_expression( diff --git a/lib/elixir_script/translator/kernel/special_forms/fn.ex b/lib/elixir_script/translator/kernel/special_forms/fn.ex index c4415628..fa0b9c18 100644 --- a/lib/elixir_script/translator/kernel/special_forms/fn.ex +++ b/lib/elixir_script/translator/kernel/special_forms/fn.ex @@ -4,6 +4,7 @@ defmodule ElixirScript.Translator.Function do alias ElixirScript.Translator alias ElixirScript.Translator.Group alias ElixirScript.Translator.PatternMatching + alias ElixirScript.Translator.Block @patterns JS.member_expression( JS.member_expression( @@ -63,7 +64,7 @@ defmodule ElixirScript.Translator.Function do if guards do { guard_body, _ } = hd(List.wrap(guards)) - |> prepare_function_body(env) + |> prepare_function_body(%{ env | context: :guard}) guard_body = JS.block_statement(guard_body) make_function_clause(patterns, params, body, guard_body) @@ -103,11 +104,11 @@ defmodule ElixirScript.Translator.Function do def make_function_clause(patterns, params, body, guard_body) do arguments = [ JS.array_expression(patterns), - JS.function_expression(params, [], body, true), + JS.function_expression(params, [], body), ] if guard_body do - arguments = arguments ++ [JS.function_expression(params, [], guard_body, true)] + arguments = arguments ++ [JS.function_expression(params, [], guard_body)] end JS.call_expression( @@ -138,6 +139,7 @@ defmodule ElixirScript.Translator.Function do end list = Group.inflate_groups(list) + |> Enum.map(fn(x) -> Block.process_call(x, env) end) |> return_last_expression { list, env } @@ -160,7 +162,7 @@ defmodule ElixirScript.Translator.Function do last_item = case last_item do %ESTree.YieldExpression{} -> - JS.return_statement(last_item) + JS.return_statement(last_item) %ESTree.Literal{} -> JS.return_statement(last_item) %ESTree.Identifier{} -> diff --git a/lib/elixir_script/translator/lexical_scope.ex b/lib/elixir_script/translator/lexical_scope.ex index 0e4af785..44104758 100644 --- a/lib/elixir_script/translator/lexical_scope.ex +++ b/lib/elixir_script/translator/lexical_scope.ex @@ -17,6 +17,7 @@ defmodule ElixirScript.Translator.LexicalScope do export_vars: [{atom, atom | non_neg_integer}] | nil, lexical_tracker: nil, caller: t | nil, + in_process: boolean, env: nil } @@ -36,6 +37,7 @@ defmodule ElixirScript.Translator.LexicalScope do export_vars: nil, lexical_tracker: nil, caller: nil, + in_process: false, env: nil ] diff --git a/src/javascript/lib/core/functions.js b/src/javascript/lib/core/functions.js index f1a0d22b..9bda3db8 100644 --- a/src/javascript/lib/core/functions.js +++ b/src/javascript/lib/core/functions.js @@ -3,7 +3,7 @@ import BitString from './bit_string'; import Patterns from './patterns'; import Protocol from './protocol'; -function* call_property(item, property){ +function call_property(item, property){ let prop = null; if(typeof item === "number" || typeof item === "symbol" || typeof item === "boolean" || typeof item === "string"){ @@ -25,9 +25,9 @@ function* call_property(item, property){ } if(item[prop] instanceof Function){ - return yield* item[prop](); + return item[prop](); }else{ - return yield item[prop]; + return item[prop]; } } diff --git a/src/javascript/lib/core/patterns/defmatch.js b/src/javascript/lib/core/patterns/defmatch.js index 7a952940..1bcf3a23 100644 --- a/src/javascript/lib/core/patterns/defmatch.js +++ b/src/javascript/lib/core/patterns/defmatch.js @@ -43,7 +43,7 @@ export function make_case(pattern: Array, fn: Function, guard: Function = ( } export function defmatch(...cases: Array): Function { - return function* (...args: Array): any { + return function (...args: Array): any { for (let processedCase of cases) { let result = []; args = fillInOptionalValues(args, processedCase.arity, processedCase.optionals); From 11873d9f507d54bff7a699fc339ea7e2fe2b986f Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Wed, 15 Jun 2016 12:59:39 -0500 Subject: [PATCH 256/860] Added stubs for spawn translation --- lib/elixir_script/translator.ex | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/lib/elixir_script/translator.ex b/lib/elixir_script/translator.ex index 49c58119..d8ca71c9 100644 --- a/lib/elixir_script/translator.ex +++ b/lib/elixir_script/translator.ex @@ -426,10 +426,25 @@ defmodule ElixirScript.Translator do end defp do_translate({:fn, _, clauses}, env) do - env = ElixirScript.Translator.LexicalScope.function_scope(env, nil) Function.make_anonymous_function(clauses, env) end + defp do_translate({:spawn, _, [{:fn, _, _} = func]}, env) do + #TODO: set in_process and set to original value before passing on + end + + defp do_translate({:spawn, _, [module, function, params]}, env) do + #TODO: set in_process and set to original value before passing on + end + + defp do_translate({:spawn_link, _, [{:fn, _, _} = func]}, env) do + #TODO: set in_process and set to original value before passing on + end + + defp do_translate({:spawn_link, _, [module, function, params]}, env) do + #TODO: set in_process and set to original value before passing on + end + defp do_translate({:{}, _, elements}, env) do quoted = quote do JS.new(Elixir.Core.Tuple, unquote(elements)) From 9aae52ec647ca9283f8f39e521823e1900eaccac Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Wed, 15 Jun 2016 15:22:52 -0500 Subject: [PATCH 257/860] Add spawn implementations --- .travis.yml | 3 +- lib/elixir_script/translator.ex | 9 +- lib/elixir_script/translator/kernel/spawn.ex | 113 ++++++++++++++++++ .../translator/kernel/special_forms/call.ex | 2 +- 4 files changed, 121 insertions(+), 6 deletions(-) create mode 100644 lib/elixir_script/translator/kernel/spawn.ex diff --git a/.travis.yml b/.travis.yml index 0d4ec731..735aa1c3 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,7 +1,8 @@ sudo: false language: elixir elixir: - - 1.2.3 + - 1.2.6 + - 1.3.0-rc.1 otp_release: - 18.0 env: diff --git a/lib/elixir_script/translator.ex b/lib/elixir_script/translator.ex index d8ca71c9..9cbbe8b4 100644 --- a/lib/elixir_script/translator.ex +++ b/lib/elixir_script/translator.ex @@ -27,6 +27,7 @@ defmodule ElixirScript.Translator do alias ElixirScript.Translator.JS, as: JSLib alias ESTree.Tools.Builder, as: JS alias ElixirScript.Translator.Rewriter + alias ElixirScript.Translator.Spawn # A list of erlang modules. These are rewritten into equivalent # JavaScript functions using ElixirScript.Translator.Rewriter @@ -430,19 +431,19 @@ defmodule ElixirScript.Translator do end defp do_translate({:spawn, _, [{:fn, _, _} = func]}, env) do - #TODO: set in_process and set to original value before passing on + Spawn.make_spawn(func, env) end defp do_translate({:spawn, _, [module, function, params]}, env) do - #TODO: set in_process and set to original value before passing on + Spawn.make_spawn(module, function, params, env) end defp do_translate({:spawn_link, _, [{:fn, _, _} = func]}, env) do - #TODO: set in_process and set to original value before passing on + Spawn.make_spawn_link(func, env) end defp do_translate({:spawn_link, _, [module, function, params]}, env) do - #TODO: set in_process and set to original value before passing on + Spawn.make_spawn_link(module, function, params, env) end defp do_translate({:{}, _, elements}, env) do diff --git a/lib/elixir_script/translator/kernel/spawn.ex b/lib/elixir_script/translator/kernel/spawn.ex new file mode 100644 index 00000000..14001702 --- /dev/null +++ b/lib/elixir_script/translator/kernel/spawn.ex @@ -0,0 +1,113 @@ +defmodule ElixirScript.Translator.Spawn do + alias ESTree.Tools.Builder, as: JS + alias ElixirScript.Translator + alias ElixirScript.Function + + + def make_spawn(func, env) do + do_spawn_with_fn(func, env, "spawn") + end + + def make_spawn_link(func, env) do + do_spawn_with_fn(func, env, "spawn_link") + end + + defp do_spawn_with_fn(func, env, spawn_func_name) do + + js_ast = JS.call_expression( + JS.member_expression( + JS.member_expression( + JS.identifier("Elixir"), + JS.member_expression( + JS.identifier("Core"), + JS.identifier("Functions") + ) + ), + JS.identifier("get_global") + ), []) + + + js_ast = JS.call_expression( + JS.member_expression( + js_ast, + JS.identifier("processes") + ), + JS.identifier(spawn_func_name), + [ + !Translator.translate(func, %{ env | in_process: true }) + ] + ) + + + { js_ast, env } + + + end + + def make_spawn(module, fun, args, env) do + do_spawn_with_mod(module, fun, args, env, "spawn") + end + + def make_spawn_link(module, fun, args, env) do + do_spawn_with_mod(module, fun, args, env, "spawn_link") + end + + defp do_spawn_with_mod(module, fun, args, env, spawn_func_name) do + + js_ast = JS.call_expression( + JS.member_expression( + JS.member_expression( + JS.identifier("Elixir"), + JS.member_expression( + JS.identifier("Core"), + JS.identifier("Functions") + ) + ), + JS.identifier("get_global") + ), []) + + + run_func = JS.member_expression( + JS.member_expression( + JS.identifier("Elixir"), + JS.member_expression( + JS.identifier("Core"), + JS.identifier("Functions") + ) + ), + JS.identifier("run") + ) + + + module_name = Function.get_module_name_for_function(module, env) + func = to_string(fun) + args = Translator.translate!(args, env) + + func_to_run = JS.member_expression( + JS.identifier(module_name), + JS.identifier(func), + true + ) + + + js_ast = JS.call_expression( + JS.member_expression( + js_ast, + JS.identifier("processes") + ), + JS.identifier(spawn_func_name), + [ + run_func, + JS.array_expression([func_to_run, args]) + ] + ) + + + { js_ast, env } + + + end + + + +end diff --git a/lib/elixir_script/translator/kernel/special_forms/call.ex b/lib/elixir_script/translator/kernel/special_forms/call.ex index 3fa62a23..396d71e2 100644 --- a/lib/elixir_script/translator/kernel/special_forms/call.ex +++ b/lib/elixir_script/translator/kernel/special_forms/call.ex @@ -30,7 +30,7 @@ defmodule ElixirScript.Translator.Call do end - defp get_module_name_for_function(module_name, env) do + def get_module_name_for_function(module_name, env) do case module_name do {:__aliases__, _, name} -> module_name = Utils.quoted_to_name(name) From 2eb9c2bbb2dc72b2000fc3db5c4e97de322dfd55 Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Wed, 15 Jun 2016 16:48:13 -0500 Subject: [PATCH 258/860] Fixed spawn implementations. Added tests --- lib/elixir_script/translator.ex | 2 +- lib/elixir_script/translator/kernel/spawn.ex | 48 +++++++-------- .../translator/kernel/special_forms/block.ex | 59 +++++++++++++----- .../translator/kernel/special_forms/call.ex | 11 +++- test/translator/kernel/spawn_test.exs | 60 +++++++++++++++++++ 5 files changed, 137 insertions(+), 43 deletions(-) create mode 100644 test/translator/kernel/spawn_test.exs diff --git a/lib/elixir_script/translator.ex b/lib/elixir_script/translator.ex index 9cbbe8b4..99297ac4 100644 --- a/lib/elixir_script/translator.ex +++ b/lib/elixir_script/translator.ex @@ -575,7 +575,7 @@ defmodule ElixirScript.Translator do end - defp create_module_name(module_name, env) do + def create_module_name(module_name, env) do case module_name do {:__aliases__, _, _} -> candiate_module_name = Utils.quoted_to_name(module_name) diff --git a/lib/elixir_script/translator/kernel/spawn.ex b/lib/elixir_script/translator/kernel/spawn.ex index 14001702..b0212a46 100644 --- a/lib/elixir_script/translator/kernel/spawn.ex +++ b/lib/elixir_script/translator/kernel/spawn.ex @@ -1,8 +1,8 @@ defmodule ElixirScript.Translator.Spawn do alias ESTree.Tools.Builder, as: JS alias ElixirScript.Translator - alias ElixirScript.Function - + alias ElixirScript.Translator.Function + alias ElixirScript.Translator.Call def make_spawn(func, env) do do_spawn_with_fn(func, env, "spawn") @@ -12,7 +12,8 @@ defmodule ElixirScript.Translator.Spawn do do_spawn_with_fn(func, env, "spawn_link") end - defp do_spawn_with_fn(func, env, spawn_func_name) do + defp do_spawn_with_fn({:fn, _, [{:->, _, [[], body]}]}, env, spawn_func_name) do + { body, env } = Function.prepare_function_body(body, %{ env | in_process: true }) js_ast = JS.call_expression( JS.member_expression( @@ -24,24 +25,25 @@ defmodule ElixirScript.Translator.Spawn do ) ), JS.identifier("get_global") - ), []) + ), + [] + ) js_ast = JS.call_expression( JS.member_expression( - js_ast, - JS.identifier("processes") + JS.member_expression( + js_ast, + JS.identifier("processes") + ), + JS.identifier(spawn_func_name) ), - JS.identifier(spawn_func_name), [ - !Translator.translate(func, %{ env | in_process: true }) + JS.function_expression([], [], JS.block_statement(body), true) ] ) - { js_ast, env } - - end def make_spawn(module, fun, args, env) do @@ -78,34 +80,30 @@ defmodule ElixirScript.Translator.Spawn do JS.identifier("run") ) - - module_name = Function.get_module_name_for_function(module, env) - func = to_string(fun) - args = Translator.translate!(args, env) + {js, _} = Call.make_function_call(Translator.create_module_name(module, env), fun, args, env) + %ESTree.CallExpression{ callee: %ESTree.MemberExpression{ object: module, property: %ESTree.Identifier{ name: fun } }, arguments: args } = js func_to_run = JS.member_expression( - JS.identifier(module_name), - JS.identifier(func), + module, + JS.literal(fun), true ) - js_ast = JS.call_expression( JS.member_expression( - js_ast, - JS.identifier("processes") + JS.member_expression( + js_ast, + JS.identifier("processes") + ), + JS.identifier(spawn_func_name) ), - JS.identifier(spawn_func_name), [ run_func, - JS.array_expression([func_to_run, args]) + JS.array_expression([func_to_run, JS.array_expression(args)]) ] ) - { js_ast, env } - - end diff --git a/lib/elixir_script/translator/kernel/special_forms/block.ex b/lib/elixir_script/translator/kernel/special_forms/block.ex index 2935508d..c911ea4f 100644 --- a/lib/elixir_script/translator/kernel/special_forms/block.ex +++ b/lib/elixir_script/translator/kernel/special_forms/block.ex @@ -18,12 +18,10 @@ defmodule ElixirScript.Translator.Block do item %ESTree.CallExpression{ callee: %ESTree.MemberExpression{ object: %ESTree.Identifier{ name: "Symbol" }, property: %ESTree.Identifier{ name: "for" }} } -> item - %ESTree.CallExpression{}-> - JS.yield_expression(item, true) - %ESTree.BinaryExpression{ left: %ESTree.CallExpression{} }-> - JS.yield_expression(item, true) - %ESTree.BinaryExpression{ right: %ESTree.CallExpression{} }-> - JS.yield_expression(item, true) + %ESTree.CallExpression{ callee: %ESTree.MemberExpression{ object: object, property: %ESTree.Identifier{ name: name } }, arguments: arguments } -> + make_gen_call(object, name, arguments) + %ESTree.CallExpression{ callee: %ESTree.Identifier{ name: name }, arguments: arguments } -> + make_gen_call(name, arguments) _ -> item end @@ -33,19 +31,52 @@ defmodule ElixirScript.Translator.Block do item end + defp make_gen_call(callee, func, params) do + JS.yield_expression( + JS.call_expression( + JS.member_expression( + JS.member_expression( + JS.identifier("Elixir"), + JS.member_expression( + JS.identifier("Core"), + JS.identifier("Functions") + ) + ), + JS.identifier("run") + ), + [ + JS.member_expression( + callee, + JS.literal(func), + true + ), + JS.array_expression(params) + ] + ), + true + ) + end + + defp make_gen_call(func, params) do - JS.call_expression( - JS.member_expression( + JS.yield_expression( + JS.call_expression( JS.member_expression( - JS.identifier("Elixir"), JS.member_expression( - JS.identifier("Core"), - JS.identifier("Functions") - ) + JS.identifier("Elixir"), + JS.member_expression( + JS.identifier("Core"), + JS.identifier("Functions") + ) + ), + JS.identifier("run") ), - JS.identifier("run") + [ + JS.identifier(func), + JS.array_expression(params) + ] ), - [func, JS.array_expression(params)] + true ) end diff --git a/lib/elixir_script/translator/kernel/special_forms/call.ex b/lib/elixir_script/translator/kernel/special_forms/call.ex index 396d71e2..8a6d3bcb 100644 --- a/lib/elixir_script/translator/kernel/special_forms/call.ex +++ b/lib/elixir_script/translator/kernel/special_forms/call.ex @@ -96,16 +96,21 @@ defmodule ElixirScript.Translator.Call do end - defp get_js_name([Elixir | _] = list, _) do + def get_js_name([Elixir | _] = list, _) do list end - defp get_js_name(module_name, env) when is_list(module_name) do + def get_js_name({:__aliases__, _, _} = name, env) do + Utils.quoted_to_name(name) + |> get_js_name(env) + end + + def get_js_name(module_name, env) when is_list(module_name) do Utils.quoted_to_name({:__aliases__, [], module_name}) |> get_js_name(env) end - defp get_js_name(module_name, env) do + def get_js_name(module_name, env) do cond do module_name in env.requires -> diff --git a/test/translator/kernel/spawn_test.exs b/test/translator/kernel/spawn_test.exs new file mode 100644 index 00000000..e0ba7860 --- /dev/null +++ b/test/translator/kernel/spawn_test.exs @@ -0,0 +1,60 @@ +defmodule ElixirScript.Translator.Spawn.Test do + use ExUnit.Case + import ElixirScript.TestHelper + + test "call spawn" do + ex_ast = quote do + spawn(fn() -> 1 end) + end + + js_code = """ + Elixir.Core.Functions.get_global().processes.spawn(function*() { return 1; }) + """ + + assert_translation(ex_ast, js_code) + end + + test "call spawn with calls" do + ex_ast = quote do + spawn(fn() -> + Window.call(1) + Tuple.to_list({1, 2, 3}) + end) + end + + js_code = """ + Elixir.Core.Functions.get_global().processes.spawn(function*() { + yield* Elixir.Core.Functions.run(Window['call'],[1]) + return yield* Elixir.Core.Functions.run(Elixir$ElixirScript$Tuple['to_list'],[new Elixir.Core.Tuple(1,2,3)]); + }) + """ + + assert_translation(ex_ast, js_code) + end + + + test "call spawn with function apply" do + ex_ast = quote do + spawn(Tuple, :to_list, [{1, 2, 3}]) + end + + js_code = """ + Elixir.Core.Functions.get_global().processes.spawn(Elixir.Core.Functions.run,[Elixir$ElixirScript$Tuple['to_list'], [new Elixir.Core.Tuple(1,2,3)]]) + """ + + assert_translation(ex_ast, js_code) + end + + + test "call spawn with JS function" do + ex_ast = quote do + spawn(Window, :call, [{1, 2, 3}]) + end + + js_code = """ + Elixir.Core.Functions.get_global().processes.spawn(Elixir.Core.Functions.run,[Window['call'], [new Elixir.Core.Tuple(1,2,3)]]) + """ + + assert_translation(ex_ast, js_code) + end +end From 5caae18b6898e3f01c96b8f95579ad6ad0259ebf Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Wed, 15 Jun 2016 16:50:05 -0500 Subject: [PATCH 259/860] Fixed defmatch function --- src/javascript/lib/core/patterns/defmatch.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/javascript/lib/core/patterns/defmatch.js b/src/javascript/lib/core/patterns/defmatch.js index 1bcf3a23..a8f09645 100644 --- a/src/javascript/lib/core/patterns/defmatch.js +++ b/src/javascript/lib/core/patterns/defmatch.js @@ -49,7 +49,7 @@ export function defmatch(...cases: Array): Function { args = fillInOptionalValues(args, processedCase.arity, processedCase.optionals); if (processedCase.pattern(args, result) && processedCase.guard.apply(this, result)) { - return yield* processedCase.fn.apply(this, result); + return processedCase.fn.apply(this, result); } } From 3bfe6d677c16ed6c08d06a6eaeb153b9ceca1025 Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Wed, 15 Jun 2016 18:00:42 -0500 Subject: [PATCH 260/860] Adding context if calling to console --- lib/elixir_script/translator/kernel/spawn.ex | 26 +++++++++++-------- .../translator/kernel/special_forms/block.ex | 11 +++++++- test/translator/kernel/spawn_test.exs | 4 +-- 3 files changed, 27 insertions(+), 14 deletions(-) diff --git a/lib/elixir_script/translator/kernel/spawn.ex b/lib/elixir_script/translator/kernel/spawn.ex index b0212a46..330a8f4e 100644 --- a/lib/elixir_script/translator/kernel/spawn.ex +++ b/lib/elixir_script/translator/kernel/spawn.ex @@ -68,16 +68,12 @@ defmodule ElixirScript.Translator.Spawn do JS.identifier("get_global") ), []) - - run_func = JS.member_expression( + functions_module = JS.member_expression( + JS.identifier("Elixir"), JS.member_expression( - JS.identifier("Elixir"), - JS.member_expression( - JS.identifier("Core"), - JS.identifier("Functions") - ) - ), - JS.identifier("run") + JS.identifier("Core"), + JS.identifier("Functions") + ) ) {js, _} = Call.make_function_call(Translator.create_module_name(module, env), fun, args, env) @@ -89,6 +85,13 @@ defmodule ElixirScript.Translator.Spawn do true ) + context = case module do + %ESTree.Identifier{ name: "console" } -> + JS.identifier("console") + _ -> + JS.identifier("null") + end + js_ast = JS.call_expression( JS.member_expression( JS.member_expression( @@ -98,8 +101,9 @@ defmodule ElixirScript.Translator.Spawn do JS.identifier(spawn_func_name) ), [ - run_func, - JS.array_expression([func_to_run, JS.array_expression(args)]) + functions_module, + JS.literal("run"), + JS.array_expression([func_to_run, JS.array_expression(args), context]) ] ) diff --git a/lib/elixir_script/translator/kernel/special_forms/block.ex b/lib/elixir_script/translator/kernel/special_forms/block.ex index c911ea4f..65e87de1 100644 --- a/lib/elixir_script/translator/kernel/special_forms/block.ex +++ b/lib/elixir_script/translator/kernel/special_forms/block.ex @@ -32,6 +32,14 @@ defmodule ElixirScript.Translator.Block do end defp make_gen_call(callee, func, params) do + context = case callee do + %ESTree.Identifier{ name: "console" } -> + JS.identifier("console") + _ -> + JS.identifier("null") + end + + JS.yield_expression( JS.call_expression( JS.member_expression( @@ -50,7 +58,8 @@ defmodule ElixirScript.Translator.Block do JS.literal(func), true ), - JS.array_expression(params) + JS.array_expression(params), + context ] ), true diff --git a/test/translator/kernel/spawn_test.exs b/test/translator/kernel/spawn_test.exs index e0ba7860..3f0f81d4 100644 --- a/test/translator/kernel/spawn_test.exs +++ b/test/translator/kernel/spawn_test.exs @@ -39,7 +39,7 @@ defmodule ElixirScript.Translator.Spawn.Test do end js_code = """ - Elixir.Core.Functions.get_global().processes.spawn(Elixir.Core.Functions.run,[Elixir$ElixirScript$Tuple['to_list'], [new Elixir.Core.Tuple(1,2,3)]]) + Elixir.Core.Functions.get_global().processes.spawn(Elixir.Core.Functions,'run',[Elixir$ElixirScript$Tuple['to_list'], [new Elixir.Core.Tuple(1,2,3)]]) """ assert_translation(ex_ast, js_code) @@ -52,7 +52,7 @@ defmodule ElixirScript.Translator.Spawn.Test do end js_code = """ - Elixir.Core.Functions.get_global().processes.spawn(Elixir.Core.Functions.run,[Window['call'], [new Elixir.Core.Tuple(1,2,3)]]) + Elixir.Core.Functions.get_global().processes.spawn(Elixir.Core.Functions,'run',[Window['call'], [new Elixir.Core.Tuple(1,2,3)]]) """ assert_translation(ex_ast, js_code) From 813ee2dd5b2d51155ecba2bf621330881fa2dc2a Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Wed, 15 Jun 2016 19:23:38 -0500 Subject: [PATCH 261/860] Add send and self implementations --- lib/elixir_script/translator.ex | 10 +++ lib/elixir_script/translator/kernel/spawn.ex | 84 ++++++++------------ test/translator/kernel/send_test.exs | 36 +++++++++ test/translator/kernel/spawn_test.exs | 8 +- 4 files changed, 83 insertions(+), 55 deletions(-) create mode 100644 test/translator/kernel/send_test.exs diff --git a/lib/elixir_script/translator.ex b/lib/elixir_script/translator.ex index 99297ac4..0c403dea 100644 --- a/lib/elixir_script/translator.ex +++ b/lib/elixir_script/translator.ex @@ -446,6 +446,16 @@ defmodule ElixirScript.Translator do Spawn.make_spawn_link(module, function, params, env) end + defp do_translate({:send, _, [id, msg]}, env) do + js = Spawn.call_processes_func("send", [translate!(id, env), translate!(msg, env)]) + {js, env} + end + + defp do_translate({:self, _, []}, env) do + js = Spawn.call_processes_func("pid", []) + {js, env} + end + defp do_translate({:{}, _, elements}, env) do quoted = quote do JS.new(Elixir.Core.Tuple, unquote(elements)) diff --git a/lib/elixir_script/translator/kernel/spawn.ex b/lib/elixir_script/translator/kernel/spawn.ex index 330a8f4e..8b5d62fb 100644 --- a/lib/elixir_script/translator/kernel/spawn.ex +++ b/lib/elixir_script/translator/kernel/spawn.ex @@ -14,36 +14,8 @@ defmodule ElixirScript.Translator.Spawn do defp do_spawn_with_fn({:fn, _, [{:->, _, [[], body]}]}, env, spawn_func_name) do { body, env } = Function.prepare_function_body(body, %{ env | in_process: true }) - - js_ast = JS.call_expression( - JS.member_expression( - JS.member_expression( - JS.identifier("Elixir"), - JS.member_expression( - JS.identifier("Core"), - JS.identifier("Functions") - ) - ), - JS.identifier("get_global") - ), - [] - ) - - - js_ast = JS.call_expression( - JS.member_expression( - JS.member_expression( - js_ast, - JS.identifier("processes") - ), - JS.identifier(spawn_func_name) - ), - [ - JS.function_expression([], [], JS.block_statement(body), true) - ] - ) - - { js_ast, env } + js = call_processes_func(spawn_func_name, [JS.function_expression([], [], JS.block_statement(body), true)]) + { js, env } end def make_spawn(module, fun, args, env) do @@ -55,19 +27,6 @@ defmodule ElixirScript.Translator.Spawn do end defp do_spawn_with_mod(module, fun, args, env, spawn_func_name) do - - js_ast = JS.call_expression( - JS.member_expression( - JS.member_expression( - JS.identifier("Elixir"), - JS.member_expression( - JS.identifier("Core"), - JS.identifier("Functions") - ) - ), - JS.identifier("get_global") - ), []) - functions_module = JS.member_expression( JS.identifier("Elixir"), JS.member_expression( @@ -92,24 +51,47 @@ defmodule ElixirScript.Translator.Spawn do JS.identifier("null") end + + js = call_processes_func(spawn_func_name, [ + functions_module, + JS.literal("run"), + JS.array_expression([func_to_run, JS.array_expression(args), context]) + ]) + + { js, env } + end + + + + def call_processes_func(func_name, params) do + js_ast = JS.call_expression( + JS.member_expression( + JS.member_expression( + JS.identifier("Elixir"), + JS.member_expression( + JS.identifier("Core"), + JS.identifier("Functions") + ) + ), + JS.identifier("get_global") + ), + [] + ) + + js_ast = JS.call_expression( JS.member_expression( JS.member_expression( js_ast, JS.identifier("processes") ), - JS.identifier(spawn_func_name) + JS.identifier(func_name) ), - [ - functions_module, - JS.literal("run"), - JS.array_expression([func_to_run, JS.array_expression(args), context]) - ] + params ) - { js_ast, env } - end + end end diff --git a/test/translator/kernel/send_test.exs b/test/translator/kernel/send_test.exs new file mode 100644 index 00000000..7789dd9b --- /dev/null +++ b/test/translator/kernel/send_test.exs @@ -0,0 +1,36 @@ +defmodule ElixirScript.Translator.Send.Test do + use ExUnit.Case + import ElixirScript.TestHelper + + test "call send outside process" do + ex_ast = quote do + send(pid, "hello") + end + + js_code = """ + Elixir.Core.Functions.get_global().processes.send(pid, 'hello') + """ + + assert_translation(ex_ast, js_code) + end + + + test "call send inside process" do + ex_ast = quote do + spawn(fn() -> + inside = self() + + send(pid, "hello") + end) + end + + js_code = """ + Elixir.Core.Functions.get_global().processes.spawn(function*() { + let [inside] = Elixir.Core.Patterns.match(Elixir.Core.Patterns.variable(),Elixir.Core.Functions.get_global().processes.pid()); + return yield* Elixir.Core.Functions.run(Elixir.Core.Functions.get_global().processes['send'],[pid, 'hello'], null); + }) + """ + + assert_translation(ex_ast, js_code) + end +end diff --git a/test/translator/kernel/spawn_test.exs b/test/translator/kernel/spawn_test.exs index 3f0f81d4..40bd87bd 100644 --- a/test/translator/kernel/spawn_test.exs +++ b/test/translator/kernel/spawn_test.exs @@ -24,8 +24,8 @@ defmodule ElixirScript.Translator.Spawn.Test do js_code = """ Elixir.Core.Functions.get_global().processes.spawn(function*() { - yield* Elixir.Core.Functions.run(Window['call'],[1]) - return yield* Elixir.Core.Functions.run(Elixir$ElixirScript$Tuple['to_list'],[new Elixir.Core.Tuple(1,2,3)]); + yield* Elixir.Core.Functions.run(Window['call'],[1],null) + return yield* Elixir.Core.Functions.run(Elixir$ElixirScript$Tuple['to_list'],[new Elixir.Core.Tuple(1,2,3)],null); }) """ @@ -39,7 +39,7 @@ defmodule ElixirScript.Translator.Spawn.Test do end js_code = """ - Elixir.Core.Functions.get_global().processes.spawn(Elixir.Core.Functions,'run',[Elixir$ElixirScript$Tuple['to_list'], [new Elixir.Core.Tuple(1,2,3)]]) + Elixir.Core.Functions.get_global().processes.spawn(Elixir.Core.Functions,'run',[Elixir$ElixirScript$Tuple['to_list'], [new Elixir.Core.Tuple(1,2,3)], null]) """ assert_translation(ex_ast, js_code) @@ -52,7 +52,7 @@ defmodule ElixirScript.Translator.Spawn.Test do end js_code = """ - Elixir.Core.Functions.get_global().processes.spawn(Elixir.Core.Functions,'run',[Window['call'], [new Elixir.Core.Tuple(1,2,3)]]) + Elixir.Core.Functions.get_global().processes.spawn(Elixir.Core.Functions,'run',[Window['call'], [new Elixir.Core.Tuple(1,2,3)], null]) """ assert_translation(ex_ast, js_code) From 71e7d4957cbea95c74ca931b6b1e28488f0e8bf3 Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Wed, 15 Jun 2016 19:59:43 -0500 Subject: [PATCH 262/860] Added receive implementation inside of processes --- lib/elixir_script/translator.ex | 13 ++- .../kernel/special_forms/receive.ex | 94 +++++++++++++++++++ test/translator/kernel/receive_test.exs | 74 +++++++++++++++ 3 files changed, 177 insertions(+), 4 deletions(-) create mode 100644 lib/elixir_script/translator/kernel/special_forms/receive.ex create mode 100644 test/translator/kernel/receive_test.exs diff --git a/lib/elixir_script/translator.ex b/lib/elixir_script/translator.ex index 0c403dea..676d29b9 100644 --- a/lib/elixir_script/translator.ex +++ b/lib/elixir_script/translator.ex @@ -28,6 +28,7 @@ defmodule ElixirScript.Translator do alias ESTree.Tools.Builder, as: JS alias ElixirScript.Translator.Rewriter alias ElixirScript.Translator.Spawn + alias ElixirScript.Translator.Receive # A list of erlang modules. These are rewritten into equivalent # JavaScript functions using ElixirScript.Translator.Rewriter @@ -300,10 +301,6 @@ defmodule ElixirScript.Translator do With.make_with(args, env) end - defp do_translate({:receive, _, _ }, _ ) do - raise ElixirScript.Translator.UnsupportedError, "receive" - end - defp do_translate({:super, _, _expressions }, _ ) do raise ElixirScript.Translator.UnsupportedError, "super" end @@ -456,6 +453,14 @@ defmodule ElixirScript.Translator do {js, env} end + defp do_translate({:receive, _, _ }, %LexicalScope{ in_process: false}) do + raise ElixirScript.Translator.UnsupportedError, "receive outside of a process" + end + + defp do_translate({:receive, _, [expressions] }, env) do + Receive.make_receive(expressions, env) + end + defp do_translate({:{}, _, elements}, env) do quoted = quote do JS.new(Elixir.Core.Tuple, unquote(elements)) diff --git a/lib/elixir_script/translator/kernel/special_forms/receive.ex b/lib/elixir_script/translator/kernel/special_forms/receive.ex new file mode 100644 index 00000000..fce47ebd --- /dev/null +++ b/lib/elixir_script/translator/kernel/special_forms/receive.ex @@ -0,0 +1,94 @@ + +defmodule ElixirScript.Translator.Receive do + alias ESTree.Tools.Builder, as: JS + alias ElixirScript.Translator + alias ElixirScript.Translator.Spawn + alias ElixirScript.Translator.Primitive + alias ElixirScript.Translator.LexicalScope + + + def make_receive([do: clauses], %LexicalScope{ in_process: true} = env) do + {made_case, _} = ElixirScript.Translator.Case.make_case({:__aliases__, [], [:message]}, clauses, env) + + + js = JS.yield_expression( + Spawn.call_processes_func("receive", [ + JS.function_expression( + [JS.identifier(:message)], + [], + JS.block_statement([ + JS.return_statement( + made_case + ) + ]) + ) + ]) + ) + + {js, env} + end + + def make_receive([do: clauses], env) do + {made_case, _} = ElixirScript.Translator.Case.make_case({:__aliases__, [], [:message]}, clauses, env) + + js = Spawn.call_processes_func("receive", [ + JS.function_expression( + [JS.identifier(:message)], + [], + JS.block_statement([ + JS.return_statement( + made_case + ) + ]) + ) + ]) + + {js, env} + end + + def make_receive([do: clauses, after: [{:->, _, [[time], _body]}] = after_clause], %LexicalScope{ in_process: true } = env) do + {made_case, _} = ElixirScript.Translator.Case.make_case({:__aliases__, [], [:message]}, clauses, env) + {anon_func, _} = ElixirScript.Translator.Function.make_anonymous_function(after_clause, env) + + js = JS.yield_expression( + Spawn.call_processes_func("receive", [ + JS.function_expression( + [JS.identifier(:message)], + [], + JS.block_statement([ + JS.return_statement( + made_case + ) + ]) + ), + Translator.translate!(time, env), + anon_func + ]) + ) + + {js, env} + end + + def make_receive([do: clauses, after: [{:->, _, [[time], _body]}] = after_clause], env) do + {made_case, _} = ElixirScript.Translator.Case.make_case({:__aliases__, [], [:message]}, clauses, env) + {anon_func, _} = ElixirScript.Translator.Function.make_anonymous_function(after_clause, env) + + + js = Spawn.call_processes_func("receive", [ + JS.function_expression( + [JS.identifier(:message)], + [], + JS.block_statement([ + JS.return_statement( + made_case + ) + ]) + ), + Translator.translate!(time, env), + anon_func + ]) + + {js, env} + end + +end diff --git a/test/translator/kernel/receive_test.exs b/test/translator/kernel/receive_test.exs new file mode 100644 index 00000000..57684fa8 --- /dev/null +++ b/test/translator/kernel/receive_test.exs @@ -0,0 +1,74 @@ + +defmodule ElixirScript.Translator.Receive.Test do + use ExUnit.Case + import ElixirScript.TestHelper + + test "translate receive without after in process" do + ex_ast = quote do + spawn(fn() -> + receive do + :ok -> + value + :error -> + value + _ -> + IO.puts "Unexpected message received" + end + end) + + end + + js_code = """ + Elixir.Core.Functions.get_global().processes.spawn(function*() { + return yield Elixir.Core.Functions.get_global().processes.receive(function(message) { + return Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Symbol.for('ok')],function() { + return value; + }),Elixir.Core.Patterns.make_case([Symbol.for('error')],function() { + return value; + }),Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.wildcard()],function() { + return yield* Elixir.Core.Functions.run(IO['puts'],['Unexpected message received'],null); + })).call(this,message); + }); + }) + """ + + assert_translation(ex_ast, js_code) + end + + test "translate receive with after in process" do + ex_ast = quote do + + spawn(fn() -> + receive do + :ok -> + value + :error -> + value + _ -> + IO.puts "Unexpected message received" + after + 5000 -> + IO.puts "No message in 5 seconds" + end + end) + end + + js_code = """ + Elixir.Core.Functions.get_global().processes.spawn(function*() { + return yield Elixir.Core.Functions.get_global().processes.receive(function(message) { + return Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Symbol.for('ok')],function() { + return value; + }),Elixir.Core.Patterns.make_case([Symbol.for('error')],function() { + return value; + }),Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.wildcard()],function() { + return yield* Elixir.Core.Functions.run(IO['puts'],['Unexpected message received'],null); + })).call(this,message); + },5000,Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([5000],function() { + return yield* Elixir.Core.Functions.run(IO['puts'],['No message in 5 seconds'],null); + }))); + }) + """ + + assert_translation(ex_ast, js_code) + end +end From b4db0162163916cae7effccd7461ac9c9af52982 Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Sun, 19 Jun 2016 10:43:49 -0500 Subject: [PATCH 263/860] Added processes module --- lib/elixir_script/prelude/process.ex | 68 +++++++++++++++++++ lib/elixir_script/translator.ex | 9 +++ lib/elixir_script/translator/kernel/spawn.ex | 26 +++---- .../translator/kernel/special_forms/block.ex | 7 +- .../kernel/special_forms/receive.ex | 13 ++-- lib/elixir_script/translator/state.ex | 3 +- package.json | 2 +- src/javascript/lib/core.js | 3 +- 8 files changed, 98 insertions(+), 33 deletions(-) create mode 100644 lib/elixir_script/prelude/process.ex diff --git a/lib/elixir_script/prelude/process.ex b/lib/elixir_script/prelude/process.ex new file mode 100644 index 00000000..46561977 --- /dev/null +++ b/lib/elixir_script/prelude/process.ex @@ -0,0 +1,68 @@ +defmodule ElixirScript.Process do + + def alive?(pid) do + Elixir.Core.processes.is_alive(pid) + end + + def delete(key) do + Elixir.Core.processes.erase(key) + end + + def exit(pid, reason) do + Elixir.Core.processes.exit(pid, reason) + end + + def flag(flag, value) do + Elixir.Core.processes.process_flag(flag, value) + end + + def flag(pid, flag, value) do + Elixir.Core.processes.process_flag(pid, flag, value) + end + + def get() do + Elixir.Core.processes.get_process_dict() + end + + def get(key, default \\ nil) do + Elixir.Core.processes.get(key, default) + end + + def get_keys() do + Elixir.Core.processes.get_keys() + end + + def get_keys(value) do + Elixir.Core.processes.get_keys(value) + end + + def put(key, value) do + Elixir.Core.processes.put(key, value) + end + + def link(pid) do + Elixir.Core.processes.link(pid) + end + + def unlink(pid) do + Elixir.Core.processes.unlink(pid) + end + + def register(pid, name) when is_atom(name) do + Elixir.Core.processes.register(pid, name) + end + + def registered() do + Elixir.Core.processes.registered() + end + + def whereis(name) do + Elixir.Core.processes.whereis(name) + end + + def list() do + Elixir.Core.processes.list() + end + + +end diff --git a/lib/elixir_script/translator.ex b/lib/elixir_script/translator.ex index 676d29b9..f3a5b15c 100644 --- a/lib/elixir_script/translator.ex +++ b/lib/elixir_script/translator.ex @@ -29,6 +29,7 @@ defmodule ElixirScript.Translator do alias ElixirScript.Translator.Rewriter alias ElixirScript.Translator.Spawn alias ElixirScript.Translator.Receive + alias ElixirScript.Translator.LexicalScope # A list of erlang modules. These are rewritten into equivalent # JavaScript functions using ElixirScript.Translator.Rewriter @@ -443,6 +444,14 @@ defmodule ElixirScript.Translator do Spawn.make_spawn_link(module, function, params, env) end + defp do_translate({:spawn_monitor, _, [{:fn, _, _} = func]}, env) do + Spawn.make_spawn_monitor(func, env) + end + + defp do_translate({:spawn_monitor, _, [module, function, params]}, env) do + Spawn.make_spawn_monitor(module, function, params, env) + end + defp do_translate({:send, _, [id, msg]}, env) do js = Spawn.call_processes_func("send", [translate!(id, env), translate!(msg, env)]) {js, env} diff --git a/lib/elixir_script/translator/kernel/spawn.ex b/lib/elixir_script/translator/kernel/spawn.ex index 8b5d62fb..6e1b468e 100644 --- a/lib/elixir_script/translator/kernel/spawn.ex +++ b/lib/elixir_script/translator/kernel/spawn.ex @@ -12,6 +12,10 @@ defmodule ElixirScript.Translator.Spawn do do_spawn_with_fn(func, env, "spawn_link") end + def make_spawn_monitor(func, env) do + do_spawn_with_fn(func, env, "spawn_monitor") + end + defp do_spawn_with_fn({:fn, _, [{:->, _, [[], body]}]}, env, spawn_func_name) do { body, env } = Function.prepare_function_body(body, %{ env | in_process: true }) js = call_processes_func(spawn_func_name, [JS.function_expression([], [], JS.block_statement(body), true)]) @@ -26,6 +30,10 @@ defmodule ElixirScript.Translator.Spawn do do_spawn_with_mod(module, fun, args, env, "spawn_link") end + def make_spawn_monitor(module, fun, args, env) do + do_spawn_with_mod(module, fun, args, env, "spawn_monitor") + end + defp do_spawn_with_mod(module, fun, args, env, spawn_func_name) do functions_module = JS.member_expression( JS.identifier("Elixir"), @@ -64,33 +72,19 @@ defmodule ElixirScript.Translator.Spawn do def call_processes_func(func_name, params) do - js_ast = JS.call_expression( + JS.call_expression( JS.member_expression( JS.member_expression( JS.identifier("Elixir"), JS.member_expression( JS.identifier("Core"), - JS.identifier("Functions") + JS.identifier("processes") ) ), - JS.identifier("get_global") - ), - [] - ) - - - js_ast = JS.call_expression( - JS.member_expression( - JS.member_expression( - js_ast, - JS.identifier("processes") - ), JS.identifier(func_name) ), params ) - - end diff --git a/lib/elixir_script/translator/kernel/special_forms/block.ex b/lib/elixir_script/translator/kernel/special_forms/block.ex index 65e87de1..60f4f359 100644 --- a/lib/elixir_script/translator/kernel/special_forms/block.ex +++ b/lib/elixir_script/translator/kernel/special_forms/block.ex @@ -32,12 +32,7 @@ defmodule ElixirScript.Translator.Block do end defp make_gen_call(callee, func, params) do - context = case callee do - %ESTree.Identifier{ name: "console" } -> - JS.identifier("console") - _ -> - JS.identifier("null") - end + context = callee JS.yield_expression( diff --git a/lib/elixir_script/translator/kernel/special_forms/receive.ex b/lib/elixir_script/translator/kernel/special_forms/receive.ex index fce47ebd..649a3a25 100644 --- a/lib/elixir_script/translator/kernel/special_forms/receive.ex +++ b/lib/elixir_script/translator/kernel/special_forms/receive.ex @@ -8,8 +8,7 @@ defmodule ElixirScript.Translator.Receive do def make_receive([do: clauses], %LexicalScope{ in_process: true} = env) do - {made_case, _} = ElixirScript.Translator.Case.make_case({:__aliases__, [], [:message]}, clauses, env) - + {made_case, _} = ElixirScript.Translator.Case.make_case({:__aliases__, [], [:message]}, clauses, %{ env | in_process: false}) js = JS.yield_expression( Spawn.call_processes_func("receive", [ @@ -29,7 +28,7 @@ defmodule ElixirScript.Translator.Receive do end def make_receive([do: clauses], env) do - {made_case, _} = ElixirScript.Translator.Case.make_case({:__aliases__, [], [:message]}, clauses, env) + {made_case, _} = ElixirScript.Translator.Case.make_case({:__aliases__, [], [:message]}, clauses, %{ env | in_process: false}) js = Spawn.call_processes_func("receive", [ JS.function_expression( @@ -47,8 +46,8 @@ defmodule ElixirScript.Translator.Receive do end def make_receive([do: clauses, after: [{:->, _, [[time], _body]}] = after_clause], %LexicalScope{ in_process: true } = env) do - {made_case, _} = ElixirScript.Translator.Case.make_case({:__aliases__, [], [:message]}, clauses, env) - {anon_func, _} = ElixirScript.Translator.Function.make_anonymous_function(after_clause, env) + {made_case, _} = ElixirScript.Translator.Case.make_case({:__aliases__, [], [:message]}, clauses, %{ env | in_process: false}) + {anon_func, _} = ElixirScript.Translator.Function.make_anonymous_function(after_clause, %{ env | in_process: false}) js = JS.yield_expression( Spawn.call_processes_func("receive", [ @@ -70,8 +69,8 @@ defmodule ElixirScript.Translator.Receive do end def make_receive([do: clauses, after: [{:->, _, [[time], _body]}] = after_clause], env) do - {made_case, _} = ElixirScript.Translator.Case.make_case({:__aliases__, [], [:message]}, clauses, env) - {anon_func, _} = ElixirScript.Translator.Function.make_anonymous_function(after_clause, env) + {made_case, _} = ElixirScript.Translator.Case.make_case({:__aliases__, [], [:message]}, clauses, %{ env | in_process: false}) + {anon_func, _} = ElixirScript.Translator.Function.make_anonymous_function(after_clause, %{ env | in_process: false}) js = Spawn.call_processes_func("receive", [ diff --git a/lib/elixir_script/translator/state.ex b/lib/elixir_script/translator/state.ex index 37fea445..acb7a48b 100644 --- a/lib/elixir_script/translator/state.ex +++ b/lib/elixir_script/translator/state.ex @@ -52,8 +52,7 @@ defmodule ElixirScript.Translator.State do |> Map.put(MapSet, ElixirScript.MapSet) |> Map.put(List, ElixirScript.List) |> Map.put(JS, ElixirScript.JS) - |> Map.put(VDom, ElixirScript.VDom) - |> Map.put(Html, ElixirScript.Html) + |> Map.put(Process, ElixirScript.Process) end def add_module(module) do diff --git a/package.json b/package.json index 0eaebfb0..86c7511c 100644 --- a/package.json +++ b/package.json @@ -19,7 +19,7 @@ "author": "", "license": "MIT", "dependencies": { - "erlang-processes": "^1.0.2" + "erlang-processes": "bryanjos/processes" }, "devDependencies": { "babel": "^6.5.2", diff --git a/src/javascript/lib/core.js b/src/javascript/lib/core.js index aba8b66c..40d845f4 100644 --- a/src/javascript/lib/core.js +++ b/src/javascript/lib/core.js @@ -5,10 +5,11 @@ import Patterns from './core/patterns'; import Functions from './core/functions'; import SpecialForms from './core/special_forms'; -Functions.get_global().processes = Functions.get_global().processes || new Processes.ProcessSystem(); +let processes = new Processes.ProcessSystem(); export default { ProcessSystem: Processes.ProcessSystem, + processes: processes, Tuple, PID, BitString, From 4b9b07fc8133159609e7f4adb73b5448a48ea49d Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Wed, 22 Jun 2016 14:55:04 -0500 Subject: [PATCH 264/860] Now using erlang-types, processes, and tailored libraries --- .babelrc | 2 +- .../translator/kernel/special_forms/fn.ex | 2 +- lib/elixir_script/translator/rewriter.ex | 4 + mix.lock | 28 +- package.json | 6 +- rollup.config.js | 2 - src/javascript/lib/core.js | 14 +- src/javascript/lib/core/bit_string.js | 309 ----------------- src/javascript/lib/core/functions.js | 18 +- src/javascript/lib/core/patterns.js | 11 - src/javascript/lib/core/patterns/checks.js | 92 ----- src/javascript/lib/core/patterns/defmatch.js | 116 ------- src/javascript/lib/core/patterns/match.js | 72 ---- src/javascript/lib/core/patterns/resolvers.js | 317 ------------------ src/javascript/lib/core/patterns/types.js | 128 ------- src/javascript/lib/core/primitives.js | 68 ---- src/javascript/lib/core/protocol.js | 12 +- src/javascript/lib/core/special_forms.js | 28 +- src/javascript/tests/bit_string.spec.js | 63 ---- src/javascript/tests/case.spec.js | 4 +- .../tests/patterns/defmatch.spec.js | 299 ----------------- src/javascript/tests/patterns/match.spec.js | 51 --- src/javascript/tests/try.spec.js | 4 +- test/elixir_script_test.exs | 14 +- test/translator/bug_test.exs | 12 +- test/translator/capture_test.exs | 16 +- test/translator/case_test.exs | 40 +-- test/translator/defmodule_test.exs | 22 +- test/translator/function_test.exs | 116 +++---- test/translator/kernel/receive_test.exs | 22 +- test/translator/kernel/send_test.exs | 8 +- test/translator/kernel/spawn_test.exs | 8 +- test/translator/list_test.exs | 2 +- test/translator/protocol_test.exs | 12 +- test/translator/try_test.exs | 22 +- 35 files changed, 210 insertions(+), 1734 deletions(-) delete mode 100644 src/javascript/lib/core/bit_string.js delete mode 100644 src/javascript/lib/core/patterns.js delete mode 100644 src/javascript/lib/core/patterns/checks.js delete mode 100644 src/javascript/lib/core/patterns/defmatch.js delete mode 100644 src/javascript/lib/core/patterns/match.js delete mode 100644 src/javascript/lib/core/patterns/resolvers.js delete mode 100644 src/javascript/lib/core/patterns/types.js delete mode 100644 src/javascript/lib/core/primitives.js delete mode 100644 src/javascript/tests/bit_string.spec.js delete mode 100644 src/javascript/tests/patterns/defmatch.spec.js delete mode 100644 src/javascript/tests/patterns/match.spec.js diff --git a/.babelrc b/.babelrc index 3a411289..9a615718 100644 --- a/.babelrc +++ b/.babelrc @@ -1,3 +1,3 @@ { - "presets": ["react", "es2015", "stage-0"], + "plugins": ["transform-es2015-modules-commonjs"] } \ No newline at end of file diff --git a/lib/elixir_script/translator/kernel/special_forms/fn.ex b/lib/elixir_script/translator/kernel/special_forms/fn.ex index fa0b9c18..a37f8bbe 100644 --- a/lib/elixir_script/translator/kernel/special_forms/fn.ex +++ b/lib/elixir_script/translator/kernel/special_forms/fn.ex @@ -114,7 +114,7 @@ defmodule ElixirScript.Translator.Function do JS.call_expression( JS.member_expression( @patterns, - JS.identifier("make_case") + JS.identifier("clause") ), arguments ) diff --git a/lib/elixir_script/translator/rewriter.ex b/lib/elixir_script/translator/rewriter.ex index 38d1aa47..ff3ff8db 100644 --- a/lib/elixir_script/translator/rewriter.ex +++ b/lib/elixir_script/translator/rewriter.ex @@ -249,6 +249,10 @@ defmodule ElixirScript.Translator.Rewriter do {:||, [], [left, right]} end + def rewrite({{:., _, [:erlang, :or]}, _, [left, right]}) do + {:||, [], [left, right]} + end + def rewrite({{:., _, [:erlang, :andalso]}, _, [left, right]}) do {:&&, [], [left, right]} end diff --git a/mix.lock b/mix.lock index d751de3f..49e65dc7 100644 --- a/mix.lock +++ b/mix.lock @@ -1,19 +1,19 @@ %{"benchfella": {:hex, :benchfella, "0.3.1"}, - "bunt": {:hex, :bunt, "0.1.5"}, - "certifi": {:hex, :certifi, "0.3.0"}, - "credo": {:hex, :credo, "0.2.6"}, + "bunt": {:hex, :bunt, "0.1.5", "c378ea1698232597d3778e4b83234dcea4a60e7c28114b0fe53657a2c0d8885e", [:mix], []}, + "certifi": {:hex, :certifi, "0.3.0", "389d4b126a47895fe96d65fcf8681f4d09eca1153dc2243ed6babad0aac1e763", [:rebar3], []}, + "credo": {:hex, :credo, "0.2.6", "d6c28e2074bfbfe4918a9918f131d69e14c05f8c04db69170e9d77b4bb33d995", [:mix], [{:bunt, "~> 0.1.4", [hex: :bunt, optional: false]}]}, "dogma": {:hex, :dogma, "0.0.7"}, - "earmark": {:hex, :earmark, "0.2.1"}, - "estree": {:hex, :estree, "2.3.0"}, - "ex_doc": {:hex, :ex_doc, "0.11.4"}, - "excoveralls": {:hex, :excoveralls, "0.5.1"}, - "exjsx": {:hex, :exjsx, "3.2.0"}, - "fs": {:hex, :fs, "0.9.2"}, - "hackney": {:hex, :hackney, "1.4.8"}, - "idna": {:hex, :idna, "1.0.3"}, + "earmark": {:hex, :earmark, "0.2.1", "ba6d26ceb16106d069b289df66751734802777a3cbb6787026dd800ffeb850f3", [:mix], []}, + "estree": {:hex, :estree, "2.3.0", "96a190aee9b7ecb05a9486fe0f1e0a912c98b2d98419a84c74956687b6e53c71", [:mix], []}, + "ex_doc": {:hex, :ex_doc, "0.11.4", "a064bdb720594c3745b94709b17ffb834fd858b4e0c1f48f37c0d92700759e02", [:mix], [{:earmark, "~> 0.1.17 or ~> 0.2", [hex: :earmark, optional: true]}]}, + "excoveralls": {:hex, :excoveralls, "0.5.1", "5b55d62b384c7edda8b26b52b1a9fc9358fec2e6b157a81071de5cb8a42e4721", [:mix], [{:hackney, ">= 0.12.0", [hex: :hackney, optional: false]}, {:exjsx, "~> 3.0", [hex: :exjsx, optional: false]}]}, + "exjsx": {:hex, :exjsx, "3.2.0", "7136cc739ace295fc74c378f33699e5145bead4fdc1b4799822d0287489136fb", [:mix], [{:jsx, "~> 2.6.2", [hex: :jsx, optional: false]}]}, + "fs": {:hex, :fs, "0.9.2", "ed17036c26c3f70ac49781ed9220a50c36775c6ca2cf8182d123b6566e49ec59", [:rebar], []}, + "hackney": {:hex, :hackney, "1.4.8", "c8c6977ed55cc5095e3929f6d94a6f732dd2e31ae42a7b9236d5574ec3f5be13", [:rebar3], [{:ssl_verify_hostname, "1.0.5", [hex: :ssl_verify_hostname, optional: false]}, {:mimerl, "1.0.2", [hex: :mimerl, optional: false]}, {:idna, "1.0.3", [hex: :idna, optional: false]}, {:certifi, "0.3.0", [hex: :certifi, optional: false]}]}, + "idna": {:hex, :idna, "1.0.3", "d456a8761cad91c97e9788c27002eb3b773adaf5c893275fc35ba4e3434bbd9b", [:rebar3], []}, "inflex": {:hex, :inflex, "1.5.0"}, - "jsx": {:hex, :jsx, "2.6.2"}, - "mimerl": {:hex, :mimerl, "1.0.2"}, + "jsx": {:hex, :jsx, "2.6.2", "213721e058da0587a4bce3cc8a00ff6684ced229c8f9223245c6ff2c88fbaa5a", [:mix, :rebar], []}, + "mimerl": {:hex, :mimerl, "1.0.2", "993f9b0e084083405ed8252b99460c4f0563e41729ab42d9074fd5e52439be88", [:rebar3], []}, "poison": {:hex, :poison, "1.5.0"}, "shouldi": {:hex, :shouldi, "0.2.3"}, - "ssl_verify_hostname": {:hex, :ssl_verify_hostname, "1.0.5"}} + "ssl_verify_hostname": {:hex, :ssl_verify_hostname, "1.0.5", "2e73e068cd6393526f9fa6d399353d7c9477d6886ba005f323b592d389fb47be", [:make], []}} diff --git a/package.json b/package.json index 86c7511c..b0cb8c73 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "elixirscript", - "version": "0.14.1", + "version": "0.21.0", "description": "Convert Elixir to JavaScript", "main": "elixir.js", "bin": { @@ -19,7 +19,9 @@ "author": "", "license": "MIT", "dependencies": { - "erlang-processes": "bryanjos/processes" + "erlang-types": "^1.0.0", + "erlang-processes": "bryanjos/processes", + "tailored": "bryanjos/tailored" }, "devDependencies": { "babel": "^6.5.2", diff --git a/rollup.config.js b/rollup.config.js index 758136ff..5a62de3b 100644 --- a/rollup.config.js +++ b/rollup.config.js @@ -10,8 +10,6 @@ export default { plugins: [ nodeResolve({ jsnext: true }), babel({ - presets: ["react"], - plugins: ["transform-class-properties"], babelrc: false }) ] diff --git a/src/javascript/lib/core.js b/src/javascript/lib/core.js index 40d845f4..f3b5b4bd 100644 --- a/src/javascript/lib/core.js +++ b/src/javascript/lib/core.js @@ -1,18 +1,20 @@ import Processes from 'erlang-processes'; -import { Tuple, PID, Integer, Float } from './core/primitives'; -import BitString from './core/bit_string'; -import Patterns from './core/patterns'; +import Patterns from 'tailored'; +import ErlangTypes from 'erlang-types'; import Functions from './core/functions'; import SpecialForms from './core/special_forms'; let processes = new Processes.ProcessSystem(); +class Integer {} +class Float {} + export default { ProcessSystem: Processes.ProcessSystem, processes: processes, - Tuple, - PID, - BitString, + Tuple: ErlangTypes.Tuple, + PID: ErlangTypes.PID, + BitString: ErlangTypes.BitString, Patterns, Integer, Float, diff --git a/src/javascript/lib/core/bit_string.js b/src/javascript/lib/core/bit_string.js deleted file mode 100644 index fbec5544..00000000 --- a/src/javascript/lib/core/bit_string.js +++ /dev/null @@ -1,309 +0,0 @@ -class BitString { - constructor(...args){ - this.value = Object.freeze(this.process(args)); - this.length = this.value.length; - this.bit_size = this.length * 8; - this.byte_size = this.length; - } - - get(index){ - return this.value[index]; - } - - count(){ - return this.value.length; - } - - slice(start, end = null){ - let s = this.value.slice(start, end); - let ms = s.map((elem) => BitString.integer(elem)); - return new BitString(...ms); - } - - [Symbol.iterator]() { - return this.value[Symbol.iterator](); - } - - toString(){ - var i, s = ""; - for (i = 0; i < this.count(); i++) { - if (s !== "") { - s += ", "; - } - s += this.get(i).toString(); - } - - return "<<" + s + ">>"; - } - - process(bitStringParts){ - let processed_values = []; - - var i; - for (i = 0; i < bitStringParts.length; i++) { - let processed_value = this['process_' + bitStringParts[i].type](bitStringParts[i]); - - for(let attr of bitStringParts[i].attributes){ - processed_value = this['process_' + attr](processed_value); - } - - processed_values = processed_values.concat(processed_value); - } - - return processed_values; - } - - process_integer(value){ - return value.value; - } - - process_float(value){ - if(value.size === 64){ - return BitString.float64ToBytes(value.value); - }else if(value.size === 32){ - return BitString.float32ToBytes(value.value); - } - - throw new Error('Invalid size for float'); - } - - process_bitstring(value){ - return value.value.value; - } - - process_binary(value){ - return BitString.toUTF8Array(value.value); - } - - process_utf8(value){ - return BitString.toUTF8Array(value.value); - } - - process_utf16(value){ - return BitString.toUTF16Array(value.value); - } - - process_utf32(value){ - return BitString.toUTF32Array(value.value); - } - - process_signed(value){ - return (new Uint8Array([value]))[0]; - } - - process_unsigned(value){ - return value; - } - - process_native(value){ - return value; - } - - process_big(value){ - return value; - } - - process_little(value){ - return value.reverse(); - } - - process_size(value){ - return value; - } - - process_unit(value){ - return value; - } - - static integer(value){ - return BitString.wrap(value, { 'type': 'integer', 'unit': 1, 'size': 8 }); - } - - static float(value){ - return BitString.wrap(value, { 'type': 'float', 'unit': 1, 'size': 64 }); - } - - static bitstring(value){ - return BitString.wrap(value, { 'type': 'bitstring', 'unit': 1, 'size': value.bit_size }); - } - - static bits(value){ - return BitString.bitstring(value); - } - - static binary(value){ - return BitString.wrap(value, { 'type': 'binary', 'unit': 8, 'size': value.length }); - } - - static bytes(value){ - return BitString.binary(value); - } - - static utf8(value){ - return BitString.wrap(value, { 'type': 'utf8', 'unit': 1, 'size': value.length }); - } - - static utf16(value){ - return BitString.wrap(value, { 'type': 'utf16', 'unit': 1, 'size': value.length * 2 }); - } - - static utf32(value){ - return BitString.wrap(value, { 'type': 'utf32', 'unit': 1, 'size': value.length * 4 }); - } - - static signed(value){ - return BitString.wrap(value, {}, 'signed'); - } - - static unsigned(value){ - return BitString.wrap(value, {}, 'unsigned'); - } - - static native(value){ - return BitString.wrap(value, {}, 'native'); - } - - static big(value){ - return BitString.wrap(value, {}, 'big'); - } - - static little(value){ - return BitString.wrap(value, {}, 'little'); - } - - static size(value, count){ - return BitString.wrap(value, {'size': count}); - } - - static unit(value, count){ - return BitString.wrap(value, {'unit': count}); - } - - static wrap(value, opt, new_attribute = null){ - let the_value = value; - - if(!(value instanceof Object)){ - the_value = {'value': value, 'attributes': []}; - } - - the_value = Object.assign(the_value, opt); - - if(new_attribute){ - the_value.attributes.push(new_attribute); - } - - - return the_value; - } - - static toUTF8Array(str) { - var utf8 = []; - for (var i = 0; i < str.length; i++) { - var charcode = str.charCodeAt(i); - if (charcode < 0x80){ - utf8.push(charcode); - } - else if (charcode < 0x800) { - utf8.push(0xc0 | (charcode >> 6), - 0x80 | (charcode & 0x3f)); - } - else if (charcode < 0xd800 || charcode >= 0xe000) { - utf8.push(0xe0 | (charcode >> 12), - 0x80 | ((charcode >> 6) & 0x3f), - 0x80 | (charcode & 0x3f)); - } - // surrogate pair - else { - i++; - // UTF-16 encodes 0x10000-0x10FFFF by - // subtracting 0x10000 and splitting the - // 20 bits of 0x0-0xFFFFF into two halves - charcode = 0x10000 + (((charcode & 0x3ff) << 10) - | (str.charCodeAt(i) & 0x3ff)); - utf8.push(0xf0 | (charcode >> 18), - 0x80 | ((charcode >> 12) & 0x3f), - 0x80 | ((charcode >> 6) & 0x3f), - 0x80 | (charcode & 0x3f)); - } - } - return utf8; - } - - static toUTF16Array(str) { - var utf16 = []; - for (var i = 0; i < str.length; i++) { - var codePoint = str.codePointAt(i); - - if(codePoint <= 255){ - utf16.push(0); - utf16.push(codePoint); - }else{ - utf16.push(((codePoint >> 8) & 0xFF)); - utf16.push((codePoint & 0xFF)); - } - } - return utf16; - } - - - static toUTF32Array(str) { - var utf32 = []; - for (var i = 0; i < str.length; i++) { - var codePoint = str.codePointAt(i); - - if(codePoint <= 255){ - utf32.push(0); - utf32.push(0); - utf32.push(0); - utf32.push(codePoint); - }else{ - utf32.push(0); - utf32.push(0); - utf32.push(((codePoint >> 8) & 0xFF)); - utf32.push((codePoint & 0xFF)); - } - } - return utf32; - } - - //http://stackoverflow.com/questions/2003493/javascript-float-from-to-bits - static float32ToBytes(f) { - var bytes = []; - - var buf = new ArrayBuffer(4); - (new Float32Array(buf))[0] = f; - - let intVersion = (new Uint32Array(buf))[0]; - - bytes.push(((intVersion >> 24) & 0xFF)); - bytes.push(((intVersion >> 16) & 0xFF)); - bytes.push(((intVersion >> 8) & 0xFF)); - bytes.push((intVersion & 0xFF)); - - return bytes; - } - - static float64ToBytes(f) { - var bytes = []; - - var buf = new ArrayBuffer(8); - (new Float64Array(buf))[0] = f; - - var intVersion1 = (new Uint32Array(buf))[0]; - var intVersion2 = (new Uint32Array(buf))[1]; - - bytes.push(((intVersion2 >> 24) & 0xFF)); - bytes.push(((intVersion2 >> 16) & 0xFF)); - bytes.push(((intVersion2 >> 8) & 0xFF)); - bytes.push((intVersion2 & 0xFF)); - - bytes.push(((intVersion1 >> 24) & 0xFF)); - bytes.push(((intVersion1 >> 16) & 0xFF)); - bytes.push(((intVersion1 >> 8) & 0xFF)); - bytes.push((intVersion1 & 0xFF)); - - return bytes; - } -} - -export default BitString; diff --git a/src/javascript/lib/core/functions.js b/src/javascript/lib/core/functions.js index 9bda3db8..cc3ad014 100644 --- a/src/javascript/lib/core/functions.js +++ b/src/javascript/lib/core/functions.js @@ -1,7 +1,5 @@ -import { Tuple } from './primitives'; -import BitString from './bit_string'; -import Patterns from './patterns'; import Protocol from './protocol'; +import Core from '../core'; function call_property(item, property){ let prop = null; @@ -49,7 +47,7 @@ function apply(...args){ function contains(left, right){ for(let x of right){ - if(Patterns.match_no_throw(left, x) != null){ + if(Core.Patterns.match_or_default(left, x) != null){ return true; } } @@ -95,7 +93,7 @@ function defexception(defaults){ this.name = this.constructor.name; this.message = message; - this[SpecialForms.atom("__exception__")] = true; + this[Symbol.for("__exception__")] = true; Error.captureStackTrace(this, this.constructor.name); } @@ -204,7 +202,7 @@ function zip(list_of_lists){ current_value.push(list_of_lists[j][i]); } - new_value.push(new Tuple(...current_value)); + new_value.push(new Core.Tuple(...current_value)); } return Object.freeze(new_value); @@ -323,7 +321,7 @@ function reverse(list){ function maps_find(key, map){ if(key in get_object_keys(map)){ - return new Tuple(Symbol.for("ok"), map[key]); + return new Core.Tuple(Symbol.for("ok"), map[key]); }else{ return Symbol.for("error"); } @@ -333,7 +331,7 @@ function flatten(list, tail = []) { let new_list = []; for(let e of list){ - if(isArray(e)){ + if(Array.isArray(e)){ new_list = new_list.concat(flatten(e)); }else{ new_list.push(e); @@ -363,7 +361,7 @@ function mapfoldl(fun, acc, list){ } - return new Tuple(Object.freeze(newlist), acc); + return new Core.Tuple(Object.freeze(newlist), acc); } function filtermap(fun, list){ @@ -374,7 +372,7 @@ function filtermap(fun, list){ if(result === true){ newlist.push(x); - }else if(result instanceof Tuple){ + }else if(result instanceof Core.Tuple){ newlist.push(result.get(1)); } } diff --git a/src/javascript/lib/core/patterns.js b/src/javascript/lib/core/patterns.js deleted file mode 100644 index c5d537ba..00000000 --- a/src/javascript/lib/core/patterns.js +++ /dev/null @@ -1,11 +0,0 @@ -/* @flow */ - -import { defmatch, match, MatchError, match_no_throw, Case, make_case } from "./patterns/defmatch"; -import { variable, wildcard, startsWith, capture, headTail, type, bound, bitStringMatch } from "./patterns/types"; - - -export default { - defmatch, match, MatchError, match_no_throw, - variable, wildcard, startsWith, - capture, headTail, type, bound, Case, make_case, bitStringMatch -}; diff --git a/src/javascript/lib/core/patterns/checks.js b/src/javascript/lib/core/patterns/checks.js deleted file mode 100644 index d5f59778..00000000 --- a/src/javascript/lib/core/patterns/checks.js +++ /dev/null @@ -1,92 +0,0 @@ -/* @flow */ - -import { Variable, Wildcard, HeadTail, Capture, Type, StartsWith, Bound, BitStringMatch } from "./types"; - -function is_number(value: any): boolean { - return typeof value === 'number'; -} - -function is_string(value: any): boolean{ - return typeof value === 'string'; -} - -function is_boolean(value: any): boolean { - return typeof value === 'boolean'; -} - -function is_symbol(value: any): boolean { - return typeof value === 'symbol'; -} - -function is_null(value: any): boolean { - return value === null; -} - -function is_undefined(value: any): boolean { - return typeof value === 'undefined'; -} - -function is_function(value: any): boolean { - return Object.prototype.toString.call(value) == '[object Function]'; -} - -function is_variable(value: any): boolean { - return value instanceof Variable; -} - -function is_wildcard(value: any): boolean { - return value instanceof Wildcard; -} - -function is_headTail(value: any): boolean { - return value instanceof HeadTail; -} - -function is_capture(value: any): boolean { - return value instanceof Capture; -} - -function is_type(value: any): boolean { - return value instanceof Type; -} - -function is_startsWith(value: any): boolean { - return value instanceof StartsWith; -} - -function is_bound(value: any): boolean { - return value instanceof Bound; -} - -function is_object(value: any): boolean { - return typeof value === 'object'; -} - -function is_array(value: any): boolean { - return Array.isArray(value); -} - -function is_bitstring(value: any): boolean { - return value instanceof BitStringMatch; -} - - -export default { - is_number, - is_string, - is_boolean, - is_symbol, - is_null, - is_undefined, - is_function, - is_variable, - is_wildcard, - is_headTail, - is_capture, - is_type, - is_startsWith, - is_bound, - is_object, - is_array, - is_bitstring -}; diff --git a/src/javascript/lib/core/patterns/defmatch.js b/src/javascript/lib/core/patterns/defmatch.js deleted file mode 100644 index a8f09645..00000000 --- a/src/javascript/lib/core/patterns/defmatch.js +++ /dev/null @@ -1,116 +0,0 @@ -/* @flow */ - -import { buildMatch } from "./match"; -import * as Types from "./types"; - -export class MatchError extends Error { - constructor(arg: any) { - super(); - - if(typeof arg === 'symbol'){ - this.message = 'No match for: ' + arg.toString(); - } else if(Array.isArray(arg)){ - let mappedValues = arg.map((x) => x.toString()); - this.message = 'No match for: ' + mappedValues; - }else{ - this.message = 'No match for: ' + arg; - } - - this.stack = (new Error()).stack; - this.name = this.constructor.name; - } -} - - -export class Case { - pattern: Function; - fn: Function; - guard: Function; - arity: number; - optionals: Array; - - constructor(pattern: Array, fn: Function, guard: Function = () => true){ - this.pattern = buildMatch(pattern); - this.arity = pattern.length; - this.optionals = getOptionalValues(pattern); - this.fn = fn; - this.guard = guard; - } -} - -export function make_case(pattern: Array, fn: Function, guard: Function = () => true): Case { - return new Case(pattern, fn, guard); -} - -export function defmatch(...cases: Array): Function { - return function (...args: Array): any { - for (let processedCase of cases) { - let result = []; - args = fillInOptionalValues(args, processedCase.arity, processedCase.optionals); - - if (processedCase.pattern(args, result) && processedCase.guard.apply(this, result)) { - return processedCase.fn.apply(this, result); - } - } - - console.error('No match for:', args); - throw new MatchError(args); - }; -} - -function getOptionalValues(pattern: Array){ - let optionals = []; - - for(let i = 0; i < pattern.length; i++){ - if(pattern[i] instanceof Types.Variable && pattern[i].default_value != Symbol.for("elixirscript.no_value")){ - optionals.push([i, pattern[i].default_value]); - } - } - - return optionals; -} - -function fillInOptionalValues(args, arity, optionals){ - if(args.length === arity || optionals.length === 0){ - return args; - } - - if(args.length + optionals.length < arity){ - return args; - } - - let numberOfOptionalsToFill = arity - args.length; - let optionalsToRemove = optionals.length - numberOfOptionalsToFill; - - let optionalsToUse = optionals.slice(optionalsToRemove); - - for(let [index, value] of optionalsToUse){ - args.splice(index, 0, value); - if(args.length === arity){ - break; - } - } - - return args; -} - -export function match(pattern: any, expr: any, guard: Function = () => true): Array { - let result = []; - let processedPattern = buildMatch(pattern); - if (processedPattern(expr, result) && guard.apply(this, result)){ - return result; - }else{ - console.error('No match for:', expr); - throw new MatchError(expr); - } -} - -export function match_no_throw(pattern: any, expr: any, guard: Function = () => true): ?Array { - let result = []; - let processedPattern = buildMatch(pattern); - if (processedPattern(expr, result) && guard.apply(this, result)){ - return result; - }else{ - return null; - } -} diff --git a/src/javascript/lib/core/patterns/match.js b/src/javascript/lib/core/patterns/match.js deleted file mode 100644 index 79fb718f..00000000 --- a/src/javascript/lib/core/patterns/match.js +++ /dev/null @@ -1,72 +0,0 @@ -/* @flow */ -import Checks from "./checks"; -import Resolvers from "./resolvers"; - -export function buildMatch(pattern: any): Function { - - if(Checks.is_variable(pattern)){ - return Resolvers.resolveVariable(pattern); - } - - if(Checks.is_wildcard(pattern)){ - return Resolvers.resolveWildcard(pattern); - } - - if(Checks.is_undefined(pattern)){ - return Resolvers.resolveWildcard(pattern); - } - - if(Checks.is_headTail(pattern)){ - return Resolvers.resolveHeadTail(pattern); - } - - if(Checks.is_startsWith(pattern)){ - return Resolvers.resolveStartsWith(pattern); - } - - if(Checks.is_capture(pattern)){ - return Resolvers.resolveCapture(pattern); - } - - if(Checks.is_bound(pattern)){ - return Resolvers.resolveBound(pattern); - } - - if(Checks.is_type(pattern)){ - return Resolvers.resolveType(pattern); - } - - if(Checks.is_array(pattern)){ - return Resolvers.resolveArray(pattern); - } - - if(Checks.is_number(pattern)){ - return Resolvers.resolveNumber(pattern); - } - - if(Checks.is_string(pattern)){ - return Resolvers.resolveString(pattern); - } - - if(Checks.is_boolean(pattern)){ - return Resolvers.resolveBoolean(pattern); - } - - if(Checks.is_symbol(pattern)){ - return Resolvers.resolveSymbol(pattern); - } - - if(Checks.is_null(pattern)){ - return Resolvers.resolveNull(pattern); - } - - if(Checks.is_bitstring(pattern)){ - return Resolvers.resolveBitString(pattern); - } - - if(Checks.is_object(pattern)){ - return Resolvers.resolveObject(pattern); - } - - return Resolvers.resolveNoMatch(); -} diff --git a/src/javascript/lib/core/patterns/resolvers.js b/src/javascript/lib/core/patterns/resolvers.js deleted file mode 100644 index defe9f2d..00000000 --- a/src/javascript/lib/core/patterns/resolvers.js +++ /dev/null @@ -1,317 +0,0 @@ -/* @flow */ - -import Checks from "./checks"; -import * as Types from "./types"; -import { buildMatch } from "./match"; -import BitString from "../bit_string"; - -function resolveSymbol(pattern: any): Function { - return function(value: any): boolean { - return Checks.is_symbol(value) && value === pattern; - }; -} - -function resolveString(pattern: any): Function { - return function(value: any): boolean { - return Checks.is_string(value) && value === pattern; - }; -} - -function resolveNumber(pattern: any): Function { - return function(value: any): boolean { - return Checks.is_number(value) && value === pattern; - }; -} - -function resolveBoolean(pattern: any): Function { - return function(value: any): boolean { - return Checks.is_boolean(value) && value === pattern; - }; -} - -function resolveFunction(pattern: any): Function { - return function(value: any): boolean { - return Checks.is_function(value) && value === pattern; - }; -} - -function resolveNull(pattern: any): Function { - return function(value: any): boolean { - return Checks.is_null(value); - }; -} - -function resolveBound(pattern: Types.Bound): Function { - return function(value: any, args: Array): boolean { - if(typeof value === typeof pattern.value && value === pattern.value){ - args.push(value); - return true; - } - - return false; - }; -} - -function resolveWildcard(): Function { - return function(): boolean { - return true; - }; -} - -function resolveVariable(): Function { - return function(value: any, args: Array): boolean { - args.push(value); - return true; - }; -} - -function resolveHeadTail(pattern: Types.HeadTail): Function { - const headMatches = buildMatch(pattern.head); - const tailMatches = buildMatch(pattern.tail); - - return function(value: any, args: Array): boolean { - if(!Checks.is_array(value) || value.length < 2){ - return false; - } - - const head = value[0]; - const tail = value.slice(1); - - if(headMatches(head, args) && tailMatches(tail, args)){ - return true; - } - }; -} - -function resolveCapture(pattern: Types.Capture): Function { - const matches = buildMatch(pattern.value); - - return function(value: any, args: Array): boolean { - if(matches(value, args)){ - args.push(value); - return true; - } - - return false; - }; -} - -function resolveStartsWith(pattern: Types.StartsWith): Function { - const prefix = pattern.prefix; - - return function(value: any, args: Array): boolean { - if(Checks.is_string(value) && value.startsWith(prefix)){ - args.push(value.substring(prefix.length)); - return true; - } - - return false; - }; -} - -function resolveType(pattern: Types.Type): Function { - return function(value: any, args: Array): boolean { - if(value instanceof pattern.type){ - const matches = buildMatch(pattern.objPattern); - return matches(value, args) && args.push(value) > 0; - } - - return false; - }; -} - -function resolveArray(pattern: Array): Function { - const matches = pattern.map(x => buildMatch(x)); - - return function(value: any, args: Array): boolean { - if(!Checks.is_array(value) || value.length != pattern.length){ - return false; - } - - return value.every(function(v, i) { - return matches[i](value[i], args); - }); - }; -} - -function resolveObject(pattern: Object): Function { - let matches = {}; - - for(let key of Object.keys(pattern).concat(Object.getOwnPropertySymbols(pattern))){ - matches[key] = buildMatch(pattern[key]); - } - - return function(value: any, args: Array): boolean { - if(!Checks.is_object(value) || pattern.length > value.length){ - return false; - } - - for(let key of Object.keys(pattern).concat(Object.getOwnPropertySymbols(pattern))){ - if(!(key in value) || !matches[key](value[key], args) ){ - return false; - } - } - - return true; - }; -} - -function resolveBitString(pattern: Types.BitStringMatch): Function { - let patternBitString = []; - - for(let bitstringMatchPart of pattern.values){ - if(Checks.is_variable(bitstringMatchPart.value)){ - let size = getSize(bitstringMatchPart.unit, bitstringMatchPart.size); - fillArray(patternBitString, size); - }else{ - patternBitString = patternBitString.concat(new BitString(bitstringMatchPart).value); - } - } - - let patternValues = pattern.values; - - return function(value: any, args: Array): boolean { - let bsValue = null; - - if(!Checks.is_string(value) && !(value instanceof BitString) ){ - return false; - } - - if(Checks.is_string(value)){ - bsValue = new BitString(BitString.binary(value)); - }else{ - bsValue = value; - } - - let beginningIndex = 0; - - for(let i = 0; i < patternValues.length; i++){ - let bitstringMatchPart = patternValues[i]; - - if(Checks.is_variable(bitstringMatchPart.value) && - bitstringMatchPart.type == 'binary' && - bitstringMatchPart.size === undefined && - i < patternValues.length - 1){ - throw new Error("a binary field without size is only allowed at the end of a binary pattern"); - } - - let size = 0; - let bsValueArrayPart = []; - let patternBitStringArrayPart = []; - size = getSize(bitstringMatchPart.unit, bitstringMatchPart.size); - - if(i === patternValues.length - 1){ - bsValueArrayPart = bsValue.value.slice(beginningIndex); - patternBitStringArrayPart = patternBitString.slice(beginningIndex); - } else { - bsValueArrayPart = bsValue.value.slice(beginningIndex, beginningIndex + size); - patternBitStringArrayPart = patternBitString.slice(beginningIndex, beginningIndex + size); - } - - if(Checks.is_variable(bitstringMatchPart.value)){ - switch(bitstringMatchPart.type) { - case 'integer': - if(bitstringMatchPart.attributes && bitstringMatchPart.attributes.indexOf("signed") != -1){ - args.push(new Int8Array([bsValueArrayPart[0]])[0]); - } else { - args.push(new Uint8Array([bsValueArrayPart[0]])[0]); - } - break; - - case 'float': - if(size === 64){ - args.push(Float64Array.from(bsValueArrayPart)[0]); - } else if(size === 32){ - args.push(Float32Array.from(bsValueArrayPart)[0]); - }else{ - return false; - } - break; - - case 'bitstring': - args.push(createBitString(bsValueArrayPart)); - break; - - case 'binary': - args.push(String.fromCharCode.apply(null, new Uint8Array(bsValueArrayPart))); - break; - - case 'utf8': - args.push(String.fromCharCode.apply(null, new Uint8Array(bsValueArrayPart))); - break; - - case 'utf16': - args.push(String.fromCharCode.apply(null, new Uint16Array(bsValueArrayPart))); - break; - - case 'utf32': - args.push(String.fromCharCode.apply(null, new Uint32Array(bsValueArrayPart))); - break; - - default: - return false; - } - }else if(!arraysEqual(bsValueArrayPart, patternBitStringArrayPart)) { - return false; - } - - beginningIndex = beginningIndex + size; - } - - return true; - } - -} - -function getSize(unit, size){ - return (unit * size) / 8; -} - -function arraysEqual(a, b) { - if (a === b) return true; - if (a == null || b == null) return false; - if (a.length != b.length) return false; - - for (var i = 0; i < a.length; ++i) { - if (a[i] !== b[i]) return false; - } - - return true; -} - -function fillArray(arr, num){ - for(let i = 0; i < num; i++){ - arr.push(0); - } -} - -function createBitString(arr){ - let integerParts = arr.map((elem) => BitString.integer(elem)); - return new BitString(...integerParts); -} - -function resolveNoMatch(): Function { - return function(): boolean { - return false; - } -} - -export default { - resolveBound, - resolveWildcard, - resolveVariable, - resolveHeadTail, - resolveCapture, - resolveStartsWith, - resolveType, - resolveArray, - resolveObject, - resolveNoMatch, - resolveSymbol, - resolveString, - resolveNumber, - resolveBoolean, - resolveFunction, - resolveNull, - resolveBitString -} diff --git a/src/javascript/lib/core/patterns/types.js b/src/javascript/lib/core/patterns/types.js deleted file mode 100644 index 57cfa43b..00000000 --- a/src/javascript/lib/core/patterns/types.js +++ /dev/null @@ -1,128 +0,0 @@ -/* @flow */ -export class Variable { - default_value: ?any; - - constructor(default_value: ?any = Symbol.for("elixirscript.no_value")) { - this.default_value = default_value; - } -} - -export class Wildcard { - constructor() { - } -} - -export class StartsWith { - prefix: string; - - constructor(prefix: string) { - this.prefix = prefix; - } -} - -export class Capture { - value: any; - - constructor(value: any) { - this.value = value; - } -} - -export class HeadTail { - head: any; - tail: any; - - constructor(head: any = null, tail: any = null) { - this.head = head; - this.tail = tail; - } -} - -export class Type { - type: any; - objPattern: Object; - - constructor(type: any, objPattern: Object = {}) { - this.type = type - this.objPattern = objPattern - } -} - -export class Bound { - value: any; - - constructor(value: any) { - this.value = value; - } -} - -export class BitStringMatch { - values: Array - - constructor(...values: Array){ - this.values = values; - } - - length() { - return values.length; - } - - bit_size() { - return this.byte_size() * 8; - } - - byte_size(){ - let s = 0; - - for(let val of this.values){ - s = s + ((val.unit * val.size)/8); - } - - return s; - } - - getValue(index){ - return this.values(index); - } - - getSizeOfValue(index){ - let val = this.getValue(index); - return val.unit * val.size; - } - - getTypeOfValue(index){ - return this.getValue(index).type; - } -} - -export function variable(default_value: ?any = Symbol.for("elixirscript.no_value")): Variable { - return new Variable(default_value); -} - -export function wildcard(): Wildcard { - return new Wildcard(); -} - -export function startsWith(prefix: string): StartsWith { - return new StartsWith(prefix); -} - -export function capture(value: any): Capture { - return new Capture(value); -} - -export function headTail(head: any = null, tail: any = null): HeadTail { - return new HeadTail(head, tail); -} - -export function type(type: any, objPattern: Object = {}): Type { - return new Type(type, objPattern); -} - -export function bound(value: any): Bound { - return new Bound(value); -} - -export function bitStringMatch(...values: Array){ - return new BitStringMatch(...values); -} diff --git a/src/javascript/lib/core/primitives.js b/src/javascript/lib/core/primitives.js deleted file mode 100644 index d483ec8a..00000000 --- a/src/javascript/lib/core/primitives.js +++ /dev/null @@ -1,68 +0,0 @@ -class Tuple { - - constructor(...args){ - this.values = Object.freeze(args); - this.length = this.values.length; - } - - get(index) { - return this.values[index]; - } - - count() { - return this.values.length; - } - - [Symbol.iterator]() { - return this.values[Symbol.iterator](); - } - - toString() { - var i, s = ""; - for (i = 0; i < this.values.length; i++) { - if (s !== "") { - s += ", "; - } - s += this.values[i].toString(); - } - - return "{" + s + "}"; - } - - put_elem(index, elem){ - if(index === this.length){ - let new_values = this.values.concat([elem]); - return new Tuple(...new_values); - } - - let new_values = this.values.concat([]); - new_values.splice(index, 0, elem); - return new Tuple(...new_values); - } - - remove_elem(index){ - let new_values = this.values.concat([]); - new_values.splice(index, 1); - return new Tuple(...new_values); - } - -} - - -let process_counter = -1; - -class PID { - constructor(){ - process_counter = process_counter + 1; - this.id = process_counter; - } - - toString(){ - return "PID#<0." + this.id + ".0>"; - } -} - -class Integer {} -class Float {} - -export { PID, Tuple, Integer, Float }; diff --git a/src/javascript/lib/core/protocol.js b/src/javascript/lib/core/protocol.js index 34e7cb0d..d0b7aa90 100644 --- a/src/javascript/lib/core/protocol.js +++ b/src/javascript/lib/core/protocol.js @@ -1,4 +1,4 @@ -import { Integer, Float } from './primitives'; +import Core from '../core'; //https://github.com/airportyh/protomorphism class Protocol{ @@ -16,10 +16,10 @@ class Protocol{ let thing = args[0]; let fun = null; - if(Number.isInteger(thing) && this.hasImplementation(Integer)){ - fun = this.registry.get(Integer)[funName]; - }else if(typeof thing === "number" && !Number.isInteger(thing) && this.hasImplementation(Float)){ - fun = this.registry.get(Float)[funName]; + if(Number.isInteger(thing) && this.hasImplementation(Core.Integer)){ + fun = this.registry.get(Core.Integer)[funName]; + }else if(typeof thing === "number" && !Number.isInteger(thing) && this.hasImplementation(Core.Float)){ + fun = this.registry.get(Core.Float)[funName]; }else if(this.hasImplementation(thing)){ fun = this.registry.get(thing.constructor)[funName]; }else if(this.fallback){ @@ -45,7 +45,7 @@ class Protocol{ } hasImplementation(thing) { - if (thing === Integer || thing === Float){ + if (thing === Core.Integer || thing === Core.Float){ return this.registry.has(thing); } diff --git a/src/javascript/lib/core/special_forms.js b/src/javascript/lib/core/special_forms.js index 76f700c4..864b0516 100644 --- a/src/javascript/lib/core/special_forms.js +++ b/src/javascript/lib/core/special_forms.js @@ -1,9 +1,7 @@ -import BitString from './bit_string'; -import Patterns from './patterns'; -import { Tuple } from './primitives'; +import Core from '../core'; function _case(condition, clauses){ - return Patterns.defmatch(...clauses)(condition); + return Core.Patterns.defmatch(...clauses)(condition); } function cond(clauses){ @@ -29,12 +27,12 @@ function _for(collections, fun, filter = () => true, into = [], previousValues = let collection = collections[0][1]; if(collections.length === 1){ - if(collection instanceof BitString){ + if(collection instanceof Core.BitString){ let bsSlice = collection.slice(0, pattern.byte_size()); let i = 1; while(bsSlice.byte_size == pattern.byte_size()){ - let r = Patterns.match_no_throw(pattern, bsSlice); + let r = Core.Patterns.match_or_default(pattern, bsSlice); let args = previousValues.concat(r); if(r && filter.apply(this, args)){ @@ -48,7 +46,7 @@ function _for(collections, fun, filter = () => true, into = [], previousValues = return into; }else{ for(let elem of collection){ - let r = Patterns.match_no_throw(pattern, elem); + let r = Core.Patterns.match_or_default(pattern, elem); let args = previousValues.concat(r); if(r && filter.apply(this, args)){ @@ -61,12 +59,12 @@ function _for(collections, fun, filter = () => true, into = [], previousValues = }else{ let _into = []; - if(collection instanceof BitString){ + if(collection instanceof Core.BitString){ let bsSlice = collection.slice(0, pattern.byte_size()); let i = 1; while(bsSlice.byte_size == pattern.byte_size()){ - let r = Patterns.match_no_throw(pattern, bsSlice); + let r = Core.Patterns.match_or_default(pattern, bsSlice); if(r){ _into = into.concat(this._for(collections.slice(1), fun, filter, _into, previousValues.concat(r))); } @@ -76,11 +74,11 @@ function _for(collections, fun, filter = () => true, into = [], previousValues = } }else{ for(let elem of collection){ - let r = Patterns.match_no_throw(pattern, elem); + let r = Core.Patterns.match_or_default(pattern, elem); if(r){ _into = into.concat(this._for(collections.slice(1), fun, filter, _into, previousValues.concat(r))); } - } + } } return _into; @@ -100,7 +98,7 @@ function _try(do_fun, rescue_function, catch_fun, else_function, after_function) ex_result = rescue_function(e); return ex_result; }catch(ex){ - if(ex instanceof Patterns.MatchError){ + if(ex instanceof Core.Patterns.MatchError){ throw ex; } } @@ -111,7 +109,7 @@ function _try(do_fun, rescue_function, catch_fun, else_function, after_function) ex_result = catch_fun(e); return ex_result; }catch(ex){ - if(ex instanceof Patterns.MatchError){ + if(ex instanceof Core.Patterns.MatchError){ throw ex; } } @@ -129,7 +127,7 @@ function _try(do_fun, rescue_function, catch_fun, else_function, after_function) try{ return else_function(result); }catch(ex){ - if(ex instanceof Patterns.MatchError){ + if(ex instanceof Core.Patterns.MatchError){ throw new Error("No Match Found in Else"); } @@ -151,7 +149,7 @@ function _with(...args){ let result = func.apply(null, argsToPass); - let patternResult = Patterns.match_no_throw(pattern, result); + let patternResult = Core.Patterns.match_or_default(pattern, result); if(patternResult == null){ return result; diff --git a/src/javascript/tests/bit_string.spec.js b/src/javascript/tests/bit_string.spec.js deleted file mode 100644 index 90f5d48c..00000000 --- a/src/javascript/tests/bit_string.spec.js +++ /dev/null @@ -1,63 +0,0 @@ -import Core from "../lib/core"; -const Patterns = Core.Patterns; -const BitString = Core.BitString; - -import Enum from "../lib/enum"; - -import chai from 'chai'; -var expect = chai.expect; - -function is_match(pattern, expr, guard = () => true){ - return Patterns.match_no_throw(pattern, expr, guard) != null; -} - -describe('BitString', function(){ - - describe('creation', function(){ - it('create properly', function(){ - let bs = new BitString(BitString.integer(1)); - expect(is_match(bs.value, [1])).to.equal(true); - - bs = new BitString(BitString.binary("foo")); - expect(is_match(bs.value, [102, 111, 111])).to.equal(true); - - bs = new BitString(BitString.integer(0), BitString.binary("foo")); - expect(is_match(bs.value, [0, 102, 111, 111])).to.equal(true); - - bs = new BitString(BitString.float(3.14)); - expect(is_match(bs.value, [64, 9, 30, 184, 81, 235, 133, 31])).to.equal(true); - - bs = new BitString(BitString.signed(BitString.integer(-100))); - expect(is_match(bs.value, [156])).to.equal(true); - }); - }); - - describe('UTF conversions', function(){ - it('toUTF8Array', function(){ - let bs = BitString.toUTF8Array("fo≈"); - expect(is_match(bs, [102, 111, 226, 137, 136])).to.equal(true); - }); - - it('toUTF16Array', function(){ - let bs = BitString.toUTF16Array("fo≈"); - expect(is_match(bs, [0, 102, 0, 111, 34, 72])).to.equal(true); - }); - - it('toUTF32Array', function(){ - let bs = BitString.toUTF32Array("fo≈"); - expect(is_match(bs, [0, 0, 0, 102, 0, 0, 0, 111, 0, 0, 34, 72])).to.equal(true); - }); - }); - - describe('Float conversions', function(){ - it('float32ToBytes', function(){ - let bs = BitString.float32ToBytes(3.14); - expect(is_match(bs, [64, 72, 245, 195])).to.equal(true); - }); - - it('float64ToBytes', function(){ - let bs = BitString.float64ToBytes(3.14); - expect(is_match(bs, [64, 9, 30, 184, 81, 235, 133, 31])).to.equal(true); - }); - }); -}); diff --git a/src/javascript/tests/case.spec.js b/src/javascript/tests/case.spec.js index 1dc9b8cc..963c8f0a 100644 --- a/src/javascript/tests/case.spec.js +++ b/src/javascript/tests/case.spec.js @@ -13,12 +13,12 @@ describe('case', () => { it('case', () => { let clauses = [ - Patterns.make_case( + Patterns.clause( [new Tuple(Symbol.for("selector"), Patterns.variable(), Patterns.variable())], function(i, value){ return value; }, function(i){ return Kernel.is_integer(i); } ), - Patterns.make_case( + Patterns.clause( [Patterns.variable()], function(value){ return value; } ) diff --git a/src/javascript/tests/patterns/defmatch.spec.js b/src/javascript/tests/patterns/defmatch.spec.js deleted file mode 100644 index 995c3375..00000000 --- a/src/javascript/tests/patterns/defmatch.spec.js +++ /dev/null @@ -1,299 +0,0 @@ -import Core from "../../lib/core"; -const Patterns = Core.Patterns; -const Tuple = Core.Tuple; -const BitString = Core.BitString; - -import chai from 'chai'; -var expect = chai.expect; - -const _ = Patterns.wildcard(); -const $ = Patterns.variable(); - -describe('example', () => { - it('must correctly evaluate example', () => { - - let fact = Patterns.defmatch( - Patterns.make_case([0], () => 1), - Patterns.make_case([$], (n) => n * fact(n - 1)) - ); - - let response = fact(0); - expect(response).to.equal(1); - - response = fact(10); - expect(response).to.equal(3628800); - }); -}); - -describe('defmatch', () => { - it('must throw error when no match is found', () => { - - let fn = Patterns.defmatch( - Patterns.make_case([0], () => 1) - ); - - expect(fn.bind(fn, 1)).to.throw("No match for: 1"); - }); - - it('must have wildcard except everything', () => { - - let fn = Patterns.defmatch( - Patterns.make_case([_], () => 1) - ); - - expect(fn(1)).to.equal(1); - expect(fn("1")).to.equal(1); - expect(fn("ABC")).to.equal(1); - expect(fn(() => 34)).to.equal(1); - }); - - it('must work symbols', () => { - - let fn = Patterns.defmatch( - Patterns.make_case([Symbol.for('infinity')], () => 1) - ); - - expect(fn(Symbol.for('infinity'))).to.equal(1); - expect(fn.bind(fn, Symbol('infinity'))).to.throw("No match for: Symbol(infinity)"); - }); - - it('must match on values in object', () => { - - let fn = Patterns.defmatch( - Patterns.make_case([{value: $}], (val) => 1 + val), - Patterns.make_case([{a: {b: {c: $} } }], (val) => 1 - val) - ); - - expect(fn({value: 20})).to.equal(21); - expect(fn({a: {b: {c: 20} } })).to.equal(-19); - }); - - it('must match on objects even when value has more keys', () => { - - let fn = Patterns.defmatch( - Patterns.make_case([{value: $}], (val) => 1 + val), - Patterns.make_case([{a: {b: {c: $} } }], (val) => 1 - val) - ); - - expect(fn({value: 20})).to.equal(21); - expect(fn({a: {b: {c: 20}, d: 10 } })).to.equal(-19); - }); - - it('must match on substrings', () => { - - let fn = Patterns.defmatch( - Patterns.make_case([Patterns.startsWith("Bearer ")], (token) => token) - ); - - expect(fn("Bearer 1234")).to.equal("1234"); - }); - - - it('must work with guards', () => { - - let fn = Patterns.defmatch( - Patterns.make_case([$], (number) => number, (number) => number > 0) - ); - - expect(fn(3)).to.equal(3); - expect(fn.bind(fn, -1)).to.throw("No match for: -1"); - }); - - it('must capture entire match as parameter', () => { - - let fn = Patterns.defmatch( - Patterns.make_case([Patterns.capture({a: {b: {c: $} } })], (val, bound_value) => bound_value["a"]["b"]["c"]) - ); - - expect(fn({a: {b: {c: 20} } })).to.equal(20); - - fn = Patterns.defmatch( - Patterns.make_case([Patterns.capture([1, $, 3, $])], (a, b, bound_value) => bound_value.length) - ); - - expect(fn([1, 2, 3, 4])).to.equal(4); - - fn = Patterns.defmatch( - Patterns.make_case( - [Patterns.capture([1, Patterns.capture({a: {b: {c: $} } }), 3, $])], - (c, two, four, arg) => two["a"]["b"]["c"] - ) - ); - - expect(fn([1, {a: {b: {c: 20} } }, 3, 4])).to.equal(20); - }); - - it('must produce a head and a tail', () => { - - let fn = Patterns.defmatch( - Patterns.make_case( - [Patterns.headTail($, $)], - (head, tail) => tail - ) - ); - - expect(fn([3, 1, 2, 4]).length).to.equal(3); - }); - - it('must match on tuple', () => { - - let fn = Patterns.defmatch( - Patterns.make_case( - [Patterns.type(Tuple, {values: [1, 2, 3]})], - () => 3 - ) - ); - - expect(fn(new Tuple(1, 2, 3))).to.equal(3); - expect(fn.bind(fn, new Tuple(1, 2, 4))).to.throw("No match for: {1, 2, 4}"); - }); - - describe('BitString', () => { - it('must match on a string', () => { - - let fn = Patterns.defmatch( - Patterns.make_case( - [Patterns.bitStringMatch(BitString.integer(102), BitString.integer(111), BitString.integer(111))], - () => 3 - ) - ); - - expect(fn("foo")).to.equal(3); - expect(fn.bind(fn, "bar")).to.throw("No match for: bar"); - }); - - it('must match on a bitstring', () => { - - let fn = Patterns.defmatch( - Patterns.make_case( - [Patterns.bitStringMatch(BitString.integer(102), BitString.integer(111), BitString.integer(111))], - () => 3 - ) - ); - - expect(fn(new BitString(BitString.integer(102), BitString.integer(111), BitString.integer(111)))).to.equal(3); - }); - - it('must allow for variables', () => { - - let fn = Patterns.defmatch( - Patterns.make_case( - [Patterns.bitStringMatch(BitString.integer({value: $}), BitString.integer(111), BitString.integer(111))], - (pattern) => pattern - ) - ); - - expect(fn(new BitString(BitString.integer(102), BitString.integer(111), BitString.integer(111)))).to.equal(102); - }); - - it('must match on variable and convert to type', () => { - - let fn = Patterns.defmatch( - Patterns.make_case( - [Patterns.bitStringMatch(BitString.integer(102), BitString.binary({value: $}))], - (b) => b - ) - ); - - expect(fn(new BitString(BitString.integer(102), BitString.integer(111), BitString.integer(111)))).to.equal("oo"); - }); - - it('throw error when binary is used without size', () => { - - let fn = Patterns.defmatch( - Patterns.make_case( - [Patterns.bitStringMatch(BitString.binary({value: $}), BitString.binary(" the "), BitString.binary({value: $}))], - (name, species) => name - ) - ); - - expect(fn.bind(fn, "Frank the Walrus")).to.throw("a binary field without size is only allowed at the end of a binary pattern"); - }); - - it('allow binary pattern with size', () => { - - let fn = Patterns.defmatch( - Patterns.make_case( - [Patterns.bitStringMatch(BitString.size(BitString.binary({value: $}), 5), BitString.binary(" the "), BitString.binary({value: $}))], - (name, species) => name - ) - ); - - expect(fn("Frank the Walrus")).to.equal("Frank"); - }); - - - it('allow unsigned integer', () => { - - let fn = Patterns.defmatch( - Patterns.make_case( - [Patterns.bitStringMatch(BitString.integer({value: $}))], - (int) => int - ) - ); - - expect(fn(new BitString(BitString.integer(-100)))).to.equal(156); - }); - }); - - - describe('Optional Arguments', () => { - it('single optional argument', () => { - - let fn = Patterns.defmatch( - Patterns.make_case( - [Patterns.variable(2)], - (arg) => arg - ) - ); - - expect(fn()).to.equal(2); - expect(fn(3)).to.equal(3); - }); - - - it('single optional argument and one required argument', () => { - - let fn = Patterns.defmatch( - Patterns.make_case( - [Patterns.variable(), Patterns.variable(2)], - (arg1, arg2) => arg1 + arg2 - ) - ); - - expect(fn.bind(fn)).to.throw("No match for:"); - expect(fn(1)).to.equal(3); - expect(fn(3, 4)).to.equal(7); - }); - - it('two optional arguments and one required argument', () => { - - let fn = Patterns.defmatch( - Patterns.make_case( - [Patterns.variable(3), Patterns.variable(), Patterns.variable(2)], - (arg1, arg2, arg3) => arg1 + arg2 + arg3 - ) - ); - - expect(fn(1)).to.equal(6); - expect(fn(3, 4)).to.equal(9); - }); - - - it('two optional arguments in between 2 required', () => { - - let fn = Patterns.defmatch( - Patterns.make_case( - [Patterns.variable(), Patterns.variable(2), Patterns.variable(3), Patterns.variable()], - (arg1, arg2, arg3, arg4) => arg1 + arg2 + arg3 + arg4 - ) - ); - - expect(fn(1, 4)).to.equal(10); - expect(fn(1, 5, 4)).to.equal(13); - expect(fn(1, 5, 7, 4)).to.equal(17); - }); - }); - - -}); diff --git a/src/javascript/tests/patterns/match.spec.js b/src/javascript/tests/patterns/match.spec.js deleted file mode 100644 index f2d2dd16..00000000 --- a/src/javascript/tests/patterns/match.spec.js +++ /dev/null @@ -1,51 +0,0 @@ -import Core from "../../lib/core"; -const Patterns = Core.Patterns; - -import chai from 'chai'; -var expect = chai.expect; - -const _ = Patterns.wildcard(); -const $ = Patterns.variable(); - -describe('match', () => { - it('must return value on parameter', () => { - let [a] = Patterns.match($, 1); - expect(a).to.equal(1); - }); - - it('must ignore value when wildcard given', () => { - let [a] = Patterns.match(_, 1); - expect(a).to.equal(undefined); - }); - - it('must match on multiple values when an array is given', () => { - let [a, ] = Patterns.match([$, 2, _, 4], [1, 2, 3, 4]); - expect(a).to.equal(1); - }); - - it('must throw an error when there is no match', () => { - expect(Patterns.match.bind(Patterns.match, [$, 2, _, 4], 1)).to.throw("No match for: 1"); - }); - - it('must match values in object', () => { - let [a] = Patterns.match({a: [1, $, 3]}, {a: [1, 2, 3]}); - expect(a).to.equal(2); - }); - - it('must match on capture variables', () => { - let a = 1; - - let [b] = Patterns.match(Patterns.capture(a), 1); - expect(b).to.equal(1); - - let c = {a: 1}; - - let [d] = Patterns.match(Patterns.capture(c), {a: 1}); - expect(d["a"]).to.equal(1); - }); - - it('must throw an error when capture value does not match', () => { - let a = 1; - expect(Patterns.match.bind(Patterns.match, Patterns.capture(a), 2)).to.throw("No match for: 2"); - }); -}); diff --git a/src/javascript/tests/try.spec.js b/src/javascript/tests/try.spec.js index 2009c022..d4b7cf60 100644 --- a/src/javascript/tests/try.spec.js +++ b/src/javascript/tests/try.spec.js @@ -27,11 +27,11 @@ describe('try', () => { let value = SpecialForms._try(function() { return 1 / x; - }, null, null, Patterns.defmatch(Patterns.make_case([Patterns.variable()], function(y) { + }, null, null, Patterns.defmatch(Patterns.clause([Patterns.variable()], function(y) { return Symbol.for('small'); }, function(y) { return (y < 1) && (y > -1); - }), Patterns.make_case([Patterns.wildcard()], function() { + }), Patterns.clause([Patterns.wildcard()], function() { return Symbol.for('large'); })), null); diff --git a/test/elixir_script_test.exs b/test/elixir_script_test.exs index d13461db..893ca412 100644 --- a/test/elixir_script_test.exs +++ b/test/elixir_script_test.exs @@ -45,10 +45,10 @@ defmodule ElixirScript.Test do import Elixir from './Elixir'; import Elixir$ElixirScript$Kernel from './Elixir.ElixirScript.Kernel'; import Elixir$ElixirScript$String$Chars from './Elixir.ElixirScript.String.Chars'; - const something_else = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([],function() { + const something_else = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.clause([],function() { return Elixir$ElixirScript$String$Chars.to_string(10); })); - const something = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([],function() { + const something = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.clause([],function() { return ul; })); const ul = JQuery('#todo-list'); @@ -79,7 +79,7 @@ defmodule ElixirScript.Test do import Elixir from './Elixir'; import Elixir$ElixirScript$Kernel from './Elixir.ElixirScript.Kernel'; import Elixir$Animals$Elephant from './Elixir.Animals.Elephant'; - const something = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([],function() { + const something = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.clause([],function() { return Elixir$Animals$Elephant.Elixir$Animals$Elephant.create(Object.freeze({})); })); export default { @@ -117,10 +117,10 @@ defmodule ElixirScript.Test do assert_js_matches """ import Elixir from './Elixir'; import Elixir$ElixirScript$Kernel from './Elixir.ElixirScript.Kernel'; - const something_else = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([],function() { + const something_else = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.clause([],function() { return 1 * 1; })); - const sandwich = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([],function() { + const sandwich = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.clause([],function() { return null; })); export default { @@ -146,10 +146,10 @@ defmodule ElixirScript.Test do assert_js_matches """ import Elixir from './elixirscript'; import Elixir$ElixirScript$Kernel from './Elixir.ElixirScript.Kernel'; - const something_else = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([],function() { + const something_else = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.clause([],function() { return 1 * 1; })); - const sandwich = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([],function() { + const sandwich = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.clause([],function() { return null; })); export default { diff --git a/test/translator/bug_test.exs b/test/translator/bug_test.exs index 92adfba7..7bc8cf92 100644 --- a/test/translator/bug_test.exs +++ b/test/translator/bug_test.exs @@ -10,7 +10,7 @@ defmodule ElixirScript.Translator.Bug.Test do end js_code = """ - const test = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([],function(){ + const test = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.clause([],function(){ return Symbol.for('atom'); })); """ @@ -117,15 +117,15 @@ defmodule ElixirScript.Translator.Bug.Test do js_code = """ - const getDispatcher = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([],function() { + const getDispatcher = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.clause([],function() { return DeLorean.Flux.createDispatcher(Object.freeze({ - [Symbol.for('startPainting')]: Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([],function() { + [Symbol.for('startPainting')]: Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.clause([],function() { return this.dispatch('startPainting'); - })), [Symbol.for('stopPainting')]: Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([],function() { + })), [Symbol.for('stopPainting')]: Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.clause([],function() { return this.dispatch('stopPainting'); - })), [Symbol.for('addPoint')]: Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable()],function(data) { + })), [Symbol.for('addPoint')]: Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.clause([Elixir.Core.Patterns.variable()],function(data) { return this.dispatch('addPoint',data); - })), [Symbol.for('getStores')]: Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([],function() { + })), [Symbol.for('getStores')]: Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.clause([],function() { return Object.freeze({ [Symbol.for('graphic')]: GraphicStore }); diff --git a/test/translator/capture_test.exs b/test/translator/capture_test.exs index bec406c9..36ca34b4 100644 --- a/test/translator/capture_test.exs +++ b/test/translator/capture_test.exs @@ -8,7 +8,7 @@ defmodule ElixirScript.Translator.Capture.Test do end js_code = """ - let [fun] = Elixir.Core.Patterns.match(Elixir.Core.Patterns.variable(),Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable()],function(__1) { + let [fun] = Elixir.Core.Patterns.match(Elixir.Core.Patterns.variable(),Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.clause([Elixir.Core.Patterns.variable()],function(__1) { return Elixir$ElixirScript$Kernel.is_atom(__1); }))); """ @@ -24,7 +24,7 @@ defmodule ElixirScript.Translator.Capture.Test do end js_code = """ - let [fun] = Elixir.Core.Patterns.match(Elixir.Core.Patterns.variable(),Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable()],function(__1) { + let [fun] = Elixir.Core.Patterns.match(Elixir.Core.Patterns.variable(),Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.clause([Elixir.Core.Patterns.variable()],function(__1) { return Elixir$ElixirScript$Kernel.is_atom(__1); }))); """ @@ -41,7 +41,7 @@ defmodule ElixirScript.Translator.Capture.Test do end js_code = """ - let [fun] = Elixir.Core.Patterns.match(Elixir.Core.Patterns.variable(),Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable()],function(__1) { + let [fun] = Elixir.Core.Patterns.match(Elixir.Core.Patterns.variable(),Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.clause([Elixir.Core.Patterns.variable()],function(__1) { return local_function(__1); }))); """ @@ -57,7 +57,7 @@ defmodule ElixirScript.Translator.Capture.Test do end js_code = """ - let [fun] = Elixir.Core.Patterns.match(Elixir.Core.Patterns.variable(),Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable()],function(__1) { + let [fun] = Elixir.Core.Patterns.match(Elixir.Core.Patterns.variable(),Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.clause([Elixir.Core.Patterns.variable()],function(__1) { return __1 * 2; }))); """ @@ -73,7 +73,7 @@ defmodule ElixirScript.Translator.Capture.Test do end js_code = """ - let [fun] = Elixir.Core.Patterns.match(Elixir.Core.Patterns.variable(),Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable(), Elixir.Core.Patterns.variable()],function(__1,__2) { + let [fun] = Elixir.Core.Patterns.match(Elixir.Core.Patterns.variable(),Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.clause([Elixir.Core.Patterns.variable(), Elixir.Core.Patterns.variable()],function(__1,__2) { return new Elixir.Core.Tuple(__1,__2); }))); """ @@ -85,7 +85,7 @@ defmodule ElixirScript.Translator.Capture.Test do end js_code = """ - let [fun] = Elixir.Core.Patterns.match(Elixir.Core.Patterns.variable(),Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable(), Elixir.Core.Patterns.variable(), Elixir.Core.Patterns.variable()],function(__1,__2,__3) { + let [fun] = Elixir.Core.Patterns.match(Elixir.Core.Patterns.variable(),Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.clause([Elixir.Core.Patterns.variable(), Elixir.Core.Patterns.variable(), Elixir.Core.Patterns.variable()],function(__1,__2,__3) { return new Elixir.Core.Tuple(__1,__2,__3); }))); """ @@ -102,7 +102,7 @@ defmodule ElixirScript.Translator.Capture.Test do end js_code = """ - Elixir.Enum.map(items,Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable()],function(__1) { + Elixir.Enum.map(items,Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.clause([Elixir.Core.Patterns.variable()],function(__1) { return process(__1); }))) """ @@ -115,7 +115,7 @@ defmodule ElixirScript.Translator.Capture.Test do end js_code = """ - elem.keypress(Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable()],function(__1) { + elem.keypress(Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.clause([Elixir.Core.Patterns.variable()],function(__1) { return process_event(__1); }))) """ diff --git a/test/translator/case_test.exs b/test/translator/case_test.exs index d5b06678..6a1477b6 100644 --- a/test/translator/case_test.exs +++ b/test/translator/case_test.exs @@ -12,9 +12,9 @@ defmodule ElixirScript.Translator.Case.Test do end js_code = """ - Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Symbol.for('ok')],function() { + Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.clause([Symbol.for('ok')],function() { return value; - }),Elixir.Core.Patterns.make_case([Symbol.for('error')],function() { + }),Elixir.Core.Patterns.clause([Symbol.for('error')],function() { return null; })).call(this,data) """ @@ -29,10 +29,10 @@ defmodule ElixirScript.Translator.Case.Test do end js_code = """ - Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([false],function() { + Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.clause([false],function() { let [value] = Elixir.Core.Patterns.match(Elixir.Core.Patterns.variable(),13); return value; - }),Elixir.Core.Patterns.make_case([true],function() { + }),Elixir.Core.Patterns.clause([true],function() { return true; })).call(this,data) """ @@ -49,10 +49,10 @@ defmodule ElixirScript.Translator.Case.Test do end js_code = """ - Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([false],function() { + Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.clause([false],function() { let [value] = Elixir.Core.Patterns.match(Elixir.Core.Patterns.variable(),13); return value; - }),Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.wildcard()],function() { + }),Elixir.Core.Patterns.clause([Elixir.Core.Patterns.wildcard()],function() { return true; })).call(this,data) """ @@ -71,12 +71,12 @@ defmodule ElixirScript.Translator.Case.Test do end js_code = """ - Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable()],function(number) { + Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.clause([Elixir.Core.Patterns.variable()],function(number) { let [value] = Elixir.Core.Patterns.match(Elixir.Core.Patterns.variable(),13); return value; },function(number) { return Elixir.Core.Functions.contains(number,Object.freeze([1, 2, 3, 4])); - }),Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.wildcard()],function() { + }),Elixir.Core.Patterns.clause([Elixir.Core.Patterns.wildcard()],function() { return true; })).call(this,data) """ @@ -96,10 +96,10 @@ defmodule ElixirScript.Translator.Case.Test do end js_code = """ - Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Symbol.for('ok')],function() { + Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.clause([Symbol.for('ok')],function() { console.info('info'); return Todo.add(data); - }),Elixir.Core.Patterns.make_case([Symbol.for('error')],function() { + }),Elixir.Core.Patterns.clause([Symbol.for('error')],function() { return null; })).call(this,data) """ @@ -118,11 +118,11 @@ defmodule ElixirScript.Translator.Case.Test do end js_code = """ - Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.type(Elixir.Core.Tuple, { + Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.clause([Elixir.Core.Patterns.type(Elixir.Core.Tuple, { values: [Elixir.Core.Patterns.variable(), Elixir.Core.Patterns.variable()] })], function(one, two) { return console.info(one); - }), Elixir.Core.Patterns.make_case([Symbol.for('error')], function() { + }), Elixir.Core.Patterns.clause([Symbol.for('error')], function() { return null; })).call(this, data) """ @@ -141,13 +141,13 @@ defmodule ElixirScript.Translator.Case.Test do end js_code = """ - Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.type(Elixir.Core.Tuple, { + Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.clause([Elixir.Core.Patterns.type(Elixir.Core.Tuple, { values: [Elixir.Core.Patterns.type(Elixir.Core.Tuple, { values: [Elixir.Core.Patterns.variable(), Elixir.Core.Patterns.variable()] }), Elixir.Core.Patterns.variable()] })], function(one, two, three) { return console.info(one); - }), Elixir.Core.Patterns.make_case([Symbol.for('error')], function() { + }), Elixir.Core.Patterns.clause([Symbol.for('error')], function() { return null; })).call(this, data) """ @@ -164,13 +164,13 @@ defmodule ElixirScript.Translator.Case.Test do end js_code = """ - Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.type(Elixir.Core.Tuple, { + Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.clause([Elixir.Core.Patterns.type(Elixir.Core.Tuple, { values: [Elixir.Core.Patterns.variable(), Elixir.Core.Patterns.type(Elixir.Core.Tuple, { values: [Elixir.Core.Patterns.variable(), Elixir.Core.Patterns.variable()] })] })], function(one, two, three) { return console.info(one); - }), Elixir.Core.Patterns.make_case([Symbol.for('error')], function() { + }), Elixir.Core.Patterns.clause([Symbol.for('error')], function() { return null; })).call(this, data) """ @@ -188,13 +188,13 @@ defmodule ElixirScript.Translator.Case.Test do end js_code = """ - Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.type(AStruct, { + Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.clause([Elixir.Core.Patterns.type(AStruct, { [Symbol.for('key')]: Elixir.Core.Patterns.type(BStruct, { [Symbol.for('key2')]: Elixir.Core.Patterns.variable() }) })], function(value) { return console.info(value); - }), Elixir.Core.Patterns.make_case([Symbol.for('error')], function() { + }), Elixir.Core.Patterns.clause([Symbol.for('error')], function() { return null; })).call(this, data) """ @@ -212,7 +212,7 @@ defmodule ElixirScript.Translator.Case.Test do end js_code = """ - Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.type(AStruct, { + Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.clause([Elixir.Core.Patterns.type(AStruct, { [Symbol.for('key')]: Elixir.Core.Patterns.type(BStruct, { [Symbol.for('key2')]: Elixir.Core.Patterns.variable(), [Symbol.for('key3')]: Elixir.Core.Patterns.type(CStruct, { [Symbol.for('key4')]: Elixir.Core.Patterns.variable() @@ -220,7 +220,7 @@ defmodule ElixirScript.Translator.Case.Test do }) })], function(value, value2) { return console.info(value); - }), Elixir.Core.Patterns.make_case([Symbol.for('error')], function() { + }), Elixir.Core.Patterns.clause([Symbol.for('error')], function() { return null; })).call(this, data) """ diff --git a/test/translator/defmodule_test.exs b/test/translator/defmodule_test.exs index e41627f6..8e901690 100644 --- a/test/translator/defmodule_test.exs +++ b/test/translator/defmodule_test.exs @@ -33,10 +33,10 @@ defmodule ElixirScript.Translator.Defmodule.Test do js_code = """ import Elixir$ElixirScript$Kernel from './Elixir.ElixirScript.Kernel'; - const something_else = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([],function() { + const something_else = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.clause([],function() { return null; })); - const something = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([],function() { + const something = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.clause([],function() { return ul; })); const ul = JQuery('#todo-list'); @@ -69,11 +69,11 @@ defmodule ElixirScript.Translator.Defmodule.Test do js_code = """ import Elixir$ElixirScript$Kernel from './Elixir.ElixirScript.Kernel'; import Elixir$Animals$Elephant from './Elixir.Animals.Elephant'; - const something_else = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([],function() { + const something_else = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.clause([],function() { return null; })); - const something = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([],function() { + const something = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.clause([],function() { return Elixir$Animals$Elephant.Elixir$Animals$Elephant.create(Object.freeze({})); })); @@ -121,10 +121,10 @@ defmodule ElixirScript.Translator.Defmodule.Test do js_code = """ import Elixir$ElixirScript$Kernel from './Elixir.ElixirScript.Kernel'; import Elixir$Animals$Elephant from './Elixir.Animals.Elephant'; - const something_else = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([],function() { + const something_else = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.clause([],function() { return null; })); - const something = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([],function() { + const something = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.clause([],function() { return Elixir$Animals$Elephant.Elixir$Animals$Elephant.create(Object.freeze({})); })); @@ -204,7 +204,7 @@ defmodule ElixirScript.Translator.Defmodule.Test do export default {}; import Elixir$ElixirScript$Kernel from './Elixir.ElixirScript.Kernel'; - const oh_my = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([],function() { + const oh_my = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.clause([],function() { return null; })); Elixir.Core.Functions.call_property(Lions.Tigers.Bears,'oh_my'); @@ -240,11 +240,11 @@ defmodule ElixirScript.Translator.Defmodule.Test do export default {}; import Elixir$ElixirScript$Kernel from './Elixir.ElixirScript.Kernel'; - const oh_my2 = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([],function() { + const oh_my2 = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.clause([],function() { return null; })); - const oh_my = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([],function() { + const oh_my = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.clause([],function() { return null; })); @@ -280,11 +280,11 @@ defmodule ElixirScript.Translator.Defmodule.Test do export default {}; import Elixir$ElixirScript$Kernel from './Elixir.ElixirScript.Kernel'; - const oh_my2 = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([],function() { + const oh_my2 = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.clause([],function() { return null; })); - const oh_my = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([],function() { + const oh_my = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.clause([],function() { return null; })); diff --git a/test/translator/function_test.exs b/test/translator/function_test.exs index 6d65d96f..f46df062 100644 --- a/test/translator/function_test.exs +++ b/test/translator/function_test.exs @@ -24,7 +24,7 @@ defmodule ElixirScript.Translator.Function.Test do end js_code = """ - const test1 = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([],function() { + const test1 = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.clause([],function() { return 1 * 1; })); """ @@ -39,7 +39,7 @@ defmodule ElixirScript.Translator.Function.Test do end js_code = """ - const test1 = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([],function() { + const test1 = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.clause([],function() { return null; })); """ @@ -52,7 +52,7 @@ defmodule ElixirScript.Translator.Function.Test do end js_code = """ - const test1 = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable(), Elixir.Core.Patterns.variable()],function(alpha,beta) { + const test1 = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.clause([Elixir.Core.Patterns.variable(), Elixir.Core.Patterns.variable()],function(alpha,beta) { return null; })); """ @@ -66,7 +66,7 @@ defmodule ElixirScript.Translator.Function.Test do end js_code = """ - const test1 = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable(), Elixir.Core.Patterns.variable()],function(alpha,beta) { + const test1 = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.clause([Elixir.Core.Patterns.variable(), Elixir.Core.Patterns.variable()],function(alpha,beta) { let [a] = Elixir.Core.Patterns.match(Elixir.Core.Patterns.variable(),alpha); return a; })); @@ -85,12 +85,12 @@ defmodule ElixirScript.Translator.Function.Test do end js_code = """ - const test1 = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable(), Elixir.Core.Patterns.variable()],function(alpha,beta) { - return Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable()],function(x) { + const test1 = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.clause([Elixir.Core.Patterns.variable(), Elixir.Core.Patterns.variable()],function(alpha,beta) { + return Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.clause([Elixir.Core.Patterns.variable()],function(x) { return 2; },function(x) { return Elixir.Enum.member__qmark__(Object.freeze([false, null]),x); - }),Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.wildcard()],function() { + }),Elixir.Core.Patterns.clause([Elixir.Core.Patterns.wildcard()],function() { return 1; })).call(this,1 == 1); })); @@ -113,18 +113,18 @@ defmodule ElixirScript.Translator.Function.Test do end js_code = """ - const test1 = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable(), Elixir.Core.Patterns.variable()],function(alpha,beta) { - return Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable()],function(x) { + const test1 = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.clause([Elixir.Core.Patterns.variable(), Elixir.Core.Patterns.variable()],function(alpha,beta) { + return Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.clause([Elixir.Core.Patterns.variable()],function(x) { return 2; },function(x) { return Elixir.Enum.member__qmark__(Object.freeze([false, null]),x); - }),Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.wildcard()],function() { - return Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable()],function(x) { + }),Elixir.Core.Patterns.clause([Elixir.Core.Patterns.wildcard()],function() { + return Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.clause([Elixir.Core.Patterns.variable()],function(x) { let [a] = Elixir.Core.Patterns.match(Elixir.Core.Patterns.variable(),1); return a; },function(x) { return Elixir.Enum.member__qmark__(Object.freeze([false, null]),x); - }),Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.wildcard()],function() { + }),Elixir.Core.Patterns.clause([Elixir.Core.Patterns.wildcard()],function() { return 4; })).call(this,2 == 2); })).call(this,1 == 1); @@ -140,7 +140,7 @@ defmodule ElixirScript.Translator.Function.Test do end js_code = """ - const test1 = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable(), Elixir.Core.Patterns.variable()], function(alpha, beta) { + const test1 = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.clause([Elixir.Core.Patterns.variable(), Elixir.Core.Patterns.variable()], function(alpha, beta) { let [a, b] = Elixir.Core.Patterns.match(Elixir.Core.Patterns.type(Elixir.Core.Tuple, { values: [Elixir.Core.Patterns.variable(), Elixir.Core.Patterns.variable()] }), new Elixir.Core.Tuple(1, 2)); @@ -209,7 +209,7 @@ defmodule ElixirScript.Translator.Function.Test do end js_code = """ - Elixir.Enum.map(list,Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable()],function(x) { + Elixir.Enum.map(list,Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.clause([Elixir.Core.Patterns.variable()],function(x) { return x * 2; }))) """ @@ -240,15 +240,15 @@ defmodule ElixirScript.Translator.Function.Test do js_code = """ import Elixir$ElixirScript$Kernel from './Elixir.ElixirScript.Kernel'; - const example = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([],function() { + const example = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.clause([],function() { return null; - }),Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable()],function(oneArg) { + }),Elixir.Core.Patterns.clause([Elixir.Core.Patterns.variable()],function(oneArg) { return null; - }),Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable(), Elixir.Core.Patterns.variable()],function(oneArg,twoArg) { + }),Elixir.Core.Patterns.clause([Elixir.Core.Patterns.variable(), Elixir.Core.Patterns.variable()],function(oneArg,twoArg) { return null; - }),Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable(), Elixir.Core.Patterns.variable(), Elixir.Core.Patterns.variable()],function(oneArg,twoArg,redArg) { + }),Elixir.Core.Patterns.clause([Elixir.Core.Patterns.variable(), Elixir.Core.Patterns.variable(), Elixir.Core.Patterns.variable()],function(oneArg,twoArg,redArg) { return null; - }),Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable(), Elixir.Core.Patterns.variable(), Elixir.Core.Patterns.variable(), Elixir.Core.Patterns.variable()],function(oneArg,twoArg,redArg,blueArg) { + }),Elixir.Core.Patterns.clause([Elixir.Core.Patterns.variable(), Elixir.Core.Patterns.variable(), Elixir.Core.Patterns.variable(), Elixir.Core.Patterns.variable()],function(oneArg,twoArg,redArg,blueArg) { return null; })); export default {}; @@ -277,15 +277,15 @@ defmodule ElixirScript.Translator.Function.Test do js_code = """ import Elixir$ElixirScript$Kernel from './Elixir.ElixirScript.Kernel'; - const example = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([],function() { + const example = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.clause([],function() { return null; - }),Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable()],function(oneArg) { + }),Elixir.Core.Patterns.clause([Elixir.Core.Patterns.variable()],function(oneArg) { return null; - }),Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable(), Elixir.Core.Patterns.variable()],function(oneArg,twoArg) { + }),Elixir.Core.Patterns.clause([Elixir.Core.Patterns.variable(), Elixir.Core.Patterns.variable()],function(oneArg,twoArg) { return null; - }),Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable(), Elixir.Core.Patterns.variable(), Elixir.Core.Patterns.variable()],function(oneArg,twoArg,redArg) { + }),Elixir.Core.Patterns.clause([Elixir.Core.Patterns.variable(), Elixir.Core.Patterns.variable(), Elixir.Core.Patterns.variable()],function(oneArg,twoArg,redArg) { return null; - }),Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable(), Elixir.Core.Patterns.variable(), Elixir.Core.Patterns.variable(), Elixir.Core.Patterns.variable()],function(oneArg,twoArg,redArg,blueArg) { + }),Elixir.Core.Patterns.clause([Elixir.Core.Patterns.variable(), Elixir.Core.Patterns.variable(), Elixir.Core.Patterns.variable(), Elixir.Core.Patterns.variable()],function(oneArg,twoArg,redArg,blueArg) { return null; })); export default { @@ -304,7 +304,7 @@ defmodule ElixirScript.Translator.Function.Test do js_code = """ import Elixir$ElixirScript$Kernel from './Elixir.ElixirScript.Kernel'; - const example = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable()],function(oneArg) { + const example = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.clause([Elixir.Core.Patterns.variable()],function(oneArg) { return null; })); export default { @@ -352,7 +352,7 @@ defmodule ElixirScript.Translator.Function.Test do js_code = """ - const something = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable()],function(one) { + const something = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.clause([Elixir.Core.Patterns.variable()],function(one) { return null; },function(one) { return Elixir$ElixirScript$Kernel.is_number(one); @@ -369,7 +369,7 @@ defmodule ElixirScript.Translator.Function.Test do js_code = """ - const something = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable()],function(one) { + const something = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.clause([Elixir.Core.Patterns.variable()],function(one) { return null; },function(one) { return Elixir$ElixirScript$Kernel.is_number(one) || Elixir$ElixirScript$Kernel.is_atom(one); @@ -385,7 +385,7 @@ defmodule ElixirScript.Translator.Function.Test do js_code = """ - const something = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable()],function(one) { + const something = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.clause([Elixir.Core.Patterns.variable()],function(one) { return null; },function(one) { return Elixir$ElixirScript$Kernel.is_number(one) || Elixir$ElixirScript$Kernel.is_atom(one); @@ -401,7 +401,7 @@ defmodule ElixirScript.Translator.Function.Test do js_code = """ - const something = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable(), Elixir.Core.Patterns.variable()],function(one,two) { + const something = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.clause([Elixir.Core.Patterns.variable(), Elixir.Core.Patterns.variable()],function(one,two) { return null; },function(one,two) { return Elixir.Core.Functions.contains(one,Object.freeze([1, 2, 3])); @@ -422,11 +422,11 @@ defmodule ElixirScript.Translator.Function.Test do js_code = """ import Elixir$ElixirScript$Kernel from './Elixir.ElixirScript.Kernel'; - const something = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable()],function(one) { + const something = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.clause([Elixir.Core.Patterns.variable()],function(one) { return null; },function(one) { return Elixir.Core.Functions.contains(one,Object.freeze([1, 2, 3])); - }),Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable()],function(one) { + }),Elixir.Core.Patterns.clause([Elixir.Core.Patterns.variable()],function(one) { return null; },function(one) { return Elixir$ElixirScript$Kernel.is_number(one) || Elixir$ElixirScript$Kernel.is_atom(one); @@ -447,7 +447,7 @@ defmodule ElixirScript.Translator.Function.Test do js_code = """ - const something = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([1],function() { + const something = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.clause([1],function() { return null; })); """ @@ -463,7 +463,7 @@ defmodule ElixirScript.Translator.Function.Test do js_code = """ - const something = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.headTail(Elixir.Core.Patterns.variable(),Elixir.Core.Patterns.variable())],function(apple,fruits) { + const something = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.clause([Elixir.Core.Patterns.headTail(Elixir.Core.Patterns.variable(),Elixir.Core.Patterns.variable())],function(apple,fruits) { return null; })); """ @@ -479,7 +479,7 @@ defmodule ElixirScript.Translator.Function.Test do js_code = """ - const something = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Object.freeze([Elixir.Core.Patterns.variable(), Elixir.Core.Patterns.variable(), Elixir.Core.Patterns.variable()])],function(apple,pear,banana) { + const something = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.clause([Object.freeze([Elixir.Core.Patterns.variable(), Elixir.Core.Patterns.variable(), Elixir.Core.Patterns.variable()])],function(apple,pear,banana) { return null; })); """ @@ -495,7 +495,7 @@ defmodule ElixirScript.Translator.Function.Test do js_code = """ - const something = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.type(Elixir.Core.Tuple, { + const something = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.clause([Elixir.Core.Patterns.type(Elixir.Core.Tuple, { values: [Elixir.Core.Patterns.variable(), Elixir.Core.Patterns.variable()] })], function(apple, fruits) { return null; @@ -513,7 +513,7 @@ defmodule ElixirScript.Translator.Function.Test do js_code = """ - const something = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.type(AStruct, {})], function() { + const something = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.clause([Elixir.Core.Patterns.type(AStruct, {})], function() { return null; })); """ @@ -528,7 +528,7 @@ defmodule ElixirScript.Translator.Function.Test do end js_code = """ - const something = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.capture(Elixir.Core.Patterns.type(AStruct, {}))], function(a) { + const something = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.clause([Elixir.Core.Patterns.capture(Elixir.Core.Patterns.type(AStruct, {}))], function(a) { return null; })); """ @@ -542,7 +542,7 @@ defmodule ElixirScript.Translator.Function.Test do end js_code = """ - const something = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.capture({ + const something = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.clause([Elixir.Core.Patterns.capture({ [Symbol.for('which')]: 13 })],function(a) { return null; @@ -560,7 +560,7 @@ defmodule ElixirScript.Translator.Function.Test do js_code = """ - const something = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.type(AStruct, { + const something = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.clause([Elixir.Core.Patterns.type(AStruct, { [Symbol.for('key')]: Elixir.Core.Patterns.variable(), [Symbol.for('key1')]: 2 })], function(value) { return null; @@ -576,7 +576,7 @@ defmodule ElixirScript.Translator.Function.Test do js_code = """ - const something = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.type(AStruct, { + const something = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.clause([Elixir.Core.Patterns.type(AStruct, { [Symbol.for('key')]: Elixir.Core.Patterns.variable(), [Symbol.for('key1')]: 2 })], function(value) { return null; @@ -596,7 +596,7 @@ defmodule ElixirScript.Translator.Function.Test do js_code = """ - const something = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.startsWith('Bearer ')],function(token) { + const something = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.clause([Elixir.Core.Patterns.startsWith('Bearer ')],function(token) { return null; })); """ @@ -610,7 +610,7 @@ defmodule ElixirScript.Translator.Function.Test do js_code = """ - const something = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.startsWith('Bearer '), Elixir.Core.Patterns.variable()],function(token,hotel) { + const something = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.clause([Elixir.Core.Patterns.startsWith('Bearer '), Elixir.Core.Patterns.variable()],function(token,hotel) { return null; })); """ @@ -624,7 +624,7 @@ defmodule ElixirScript.Translator.Function.Test do js_code = """ - const something = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.startsWith('Bearer '), Elixir.Core.Patterns.variable(), 1],function(token,hotel) { + const something = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.clause([Elixir.Core.Patterns.startsWith('Bearer '), Elixir.Core.Patterns.variable(), 1],function(token,hotel) { return null; })); """ @@ -653,15 +653,15 @@ defmodule ElixirScript.Translator.Function.Test do js_code = """ import Elixir$ElixirScript$Kernel from './Elixir.ElixirScript.Kernel'; - const something = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([1],function() { + const something = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.clause([1],function() { return null; - }),Elixir.Core.Patterns.make_case([2],function() { + }),Elixir.Core.Patterns.clause([2],function() { return null; - }),Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable()],function(one) { + }),Elixir.Core.Patterns.clause([Elixir.Core.Patterns.variable()],function(one) { return null; },function(one) { return Elixir$ElixirScript$Kernel.is_binary(one); - }),Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable()],function(one) { + }),Elixir.Core.Patterns.clause([Elixir.Core.Patterns.variable()],function(one) { return null; })); export default { @@ -682,7 +682,7 @@ defmodule ElixirScript.Translator.Function.Test do end js_code = """ - const test1 = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable(), Elixir.Core.Patterns.variable()],function(alpha,beta) { + const test1 = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.clause([Elixir.Core.Patterns.variable(), Elixir.Core.Patterns.variable()],function(alpha,beta) { let [a] = Elixir.Core.Patterns.match(Elixir.Core.Patterns.variable(),1); let [a1] = Elixir.Core.Patterns.match(Elixir.Core.Patterns.variable(),2); return a1; @@ -700,7 +700,7 @@ defmodule ElixirScript.Translator.Function.Test do end js_code = """ - const test1 = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable(), Elixir.Core.Patterns.variable()],function(alpha,beta) { + const test1 = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.clause([Elixir.Core.Patterns.variable(), Elixir.Core.Patterns.variable()],function(alpha,beta) { let [a] = Elixir.Core.Patterns.match(Elixir.Core.Patterns.variable(),1); let [a1] = Elixir.Core.Patterns.match(Elixir.Core.Patterns.variable(),a); let [a2] = Elixir.Core.Patterns.match(Elixir.Core.Patterns.variable(),2); @@ -718,7 +718,7 @@ defmodule ElixirScript.Translator.Function.Test do end js_code = """ - const test1 = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable(), Elixir.Core.Patterns.variable()],function(alpha,beta) { + const test1 = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.clause([Elixir.Core.Patterns.variable(), Elixir.Core.Patterns.variable()],function(alpha,beta) { let [a] = Elixir.Core.Patterns.match(Elixir.Core.Patterns.variable(),1); let [a1,b,c] = Elixir.Core.Patterns.match(Object.freeze([Elixir.Core.Patterns.variable(), Elixir.Core.Patterns.variable(), Elixir.Core.Patterns.variable()]),Object.freeze([a, 2, 3])); let _ref = Object.freeze([a1, b, c]); @@ -738,7 +738,7 @@ defmodule ElixirScript.Translator.Function.Test do end js_code = """ - const test1 = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable(), Elixir.Core.Patterns.variable()],function(alpha__qmark__,beta__emark__) { + const test1 = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.clause([Elixir.Core.Patterns.variable(), Elixir.Core.Patterns.variable()],function(alpha__qmark__,beta__emark__) { let [a__qmark__] = Elixir.Core.Patterns.match(Elixir.Core.Patterns.variable(),1); let [b__emark__] = Elixir.Core.Patterns.match(Elixir.Core.Patterns.variable(),2); return b__emark__; @@ -755,7 +755,7 @@ defmodule ElixirScript.Translator.Function.Test do end js_code = """ - const test1 = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable(), Elixir.Core.Patterns.variable(0)],function(alpha,beta) { + const test1 = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.clause([Elixir.Core.Patterns.variable(), Elixir.Core.Patterns.variable(0)],function(alpha,beta) { return null; })); """ @@ -768,7 +768,7 @@ defmodule ElixirScript.Translator.Function.Test do end js_code = """ - const test1 = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable(Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable()],function(x) { + const test1 = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.clause([Elixir.Core.Patterns.variable(Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.clause([Elixir.Core.Patterns.variable()],function(x) { return x; })))], function(alpha) { @@ -793,21 +793,21 @@ defmodule ElixirScript.Translator.Function.Test do end js_code = """ - const func = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable()], + const func = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.clause([Elixir.Core.Patterns.variable()], function(param) { return Elixir.Core.SpecialForms._try(function() { - return Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable()], function(x) { + return Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.clause([Elixir.Core.Patterns.variable()], function(x) { return Symbol.for('error'); }, function(x) { return Elixir.Enum.member__qmark__(Object.freeze([false, null]), x); }), - Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.wildcard()], function() { + Elixir.Core.Patterns.clause([Elixir.Core.Patterns.wildcard()], function() { return null; })).call(this, true); }, null, - Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Symbol.for('invalid')], function() { + Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.clause([Symbol.for('invalid')], function() { return Symbol.for('error'); })), null, @@ -830,7 +830,7 @@ defmodule ElixirScript.Translator.Function.Test do let [key] = Elixir.Core.Patterns.match(Elixir.Core.Patterns.variable(),'test'); Elixir.Core.Patterns.defmatch( - Elixir.Core.Patterns.make_case( + Elixir.Core.Patterns.clause( [Elixir.Core.Patterns.bound(key)], function() { return Symbol.for('ok'); diff --git a/test/translator/kernel/receive_test.exs b/test/translator/kernel/receive_test.exs index 57684fa8..41b69162 100644 --- a/test/translator/kernel/receive_test.exs +++ b/test/translator/kernel/receive_test.exs @@ -19,13 +19,13 @@ defmodule ElixirScript.Translator.Receive.Test do end js_code = """ - Elixir.Core.Functions.get_global().processes.spawn(function*() { - return yield Elixir.Core.Functions.get_global().processes.receive(function(message) { - return Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Symbol.for('ok')],function() { + Elixir.Core.processes.spawn(function*() { + return yield Elixir.Core.processes.receive(function(message) { + return Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.clause([Symbol.for('ok')],function() { return value; - }),Elixir.Core.Patterns.make_case([Symbol.for('error')],function() { + }),Elixir.Core.Patterns.clause([Symbol.for('error')],function() { return value; - }),Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.wildcard()],function() { + }),Elixir.Core.Patterns.clause([Elixir.Core.Patterns.wildcard()],function() { return yield* Elixir.Core.Functions.run(IO['puts'],['Unexpected message received'],null); })).call(this,message); }); @@ -54,16 +54,16 @@ defmodule ElixirScript.Translator.Receive.Test do end js_code = """ - Elixir.Core.Functions.get_global().processes.spawn(function*() { - return yield Elixir.Core.Functions.get_global().processes.receive(function(message) { - return Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Symbol.for('ok')],function() { + Elixir.Core.processes.spawn(function*() { + return yield Elixir.Core.processes.receive(function(message) { + return Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.clause([Symbol.for('ok')],function() { return value; - }),Elixir.Core.Patterns.make_case([Symbol.for('error')],function() { + }),Elixir.Core.Patterns.clause([Symbol.for('error')],function() { return value; - }),Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.wildcard()],function() { + }),Elixir.Core.Patterns.clause([Elixir.Core.Patterns.wildcard()],function() { return yield* Elixir.Core.Functions.run(IO['puts'],['Unexpected message received'],null); })).call(this,message); - },5000,Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([5000],function() { + },5000,Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.clause([5000],function() { return yield* Elixir.Core.Functions.run(IO['puts'],['No message in 5 seconds'],null); }))); }) diff --git a/test/translator/kernel/send_test.exs b/test/translator/kernel/send_test.exs index 7789dd9b..19fc2e86 100644 --- a/test/translator/kernel/send_test.exs +++ b/test/translator/kernel/send_test.exs @@ -8,7 +8,7 @@ defmodule ElixirScript.Translator.Send.Test do end js_code = """ - Elixir.Core.Functions.get_global().processes.send(pid, 'hello') + Elixir.Core.processes.send(pid, 'hello') """ assert_translation(ex_ast, js_code) @@ -25,9 +25,9 @@ defmodule ElixirScript.Translator.Send.Test do end js_code = """ - Elixir.Core.Functions.get_global().processes.spawn(function*() { - let [inside] = Elixir.Core.Patterns.match(Elixir.Core.Patterns.variable(),Elixir.Core.Functions.get_global().processes.pid()); - return yield* Elixir.Core.Functions.run(Elixir.Core.Functions.get_global().processes['send'],[pid, 'hello'], null); + Elixir.Core.processes.spawn(function*() { + let [inside] = Elixir.Core.Patterns.match(Elixir.Core.Patterns.variable(),Elixir.Core.processes.pid()); + return yield* Elixir.Core.Functions.run(Elixir.Core.processes['send'],[pid, 'hello'], null); }) """ diff --git a/test/translator/kernel/spawn_test.exs b/test/translator/kernel/spawn_test.exs index 40bd87bd..d367d8d5 100644 --- a/test/translator/kernel/spawn_test.exs +++ b/test/translator/kernel/spawn_test.exs @@ -8,7 +8,7 @@ defmodule ElixirScript.Translator.Spawn.Test do end js_code = """ - Elixir.Core.Functions.get_global().processes.spawn(function*() { return 1; }) + Elixir.Core.processes.spawn(function*() { return 1; }) """ assert_translation(ex_ast, js_code) @@ -23,7 +23,7 @@ defmodule ElixirScript.Translator.Spawn.Test do end js_code = """ - Elixir.Core.Functions.get_global().processes.spawn(function*() { + Elixir.Core.processes.spawn(function*() { yield* Elixir.Core.Functions.run(Window['call'],[1],null) return yield* Elixir.Core.Functions.run(Elixir$ElixirScript$Tuple['to_list'],[new Elixir.Core.Tuple(1,2,3)],null); }) @@ -39,7 +39,7 @@ defmodule ElixirScript.Translator.Spawn.Test do end js_code = """ - Elixir.Core.Functions.get_global().processes.spawn(Elixir.Core.Functions,'run',[Elixir$ElixirScript$Tuple['to_list'], [new Elixir.Core.Tuple(1,2,3)], null]) + Elixir.Core.processes.spawn(Elixir.Core.Functions,'run',[Elixir$ElixirScript$Tuple['to_list'], [new Elixir.Core.Tuple(1,2,3)], null]) """ assert_translation(ex_ast, js_code) @@ -52,7 +52,7 @@ defmodule ElixirScript.Translator.Spawn.Test do end js_code = """ - Elixir.Core.Functions.get_global().processes.spawn(Elixir.Core.Functions,'run',[Window['call'], [new Elixir.Core.Tuple(1,2,3)], null]) + Elixir.Core.processes.spawn(Elixir.Core.Functions,'run',[Window['call'], [new Elixir.Core.Tuple(1,2,3)], null]) """ assert_translation(ex_ast, js_code) diff --git a/test/translator/list_test.exs b/test/translator/list_test.exs index 79567c77..ed25bc2c 100644 --- a/test/translator/list_test.exs +++ b/test/translator/list_test.exs @@ -50,7 +50,7 @@ defmodule ElixirScript.Translator.List.Test do end js_code = """ - Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.wildcard()],function(){ + Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.clause([Elixir.Core.Patterns.wildcard()],function(){ return Object.freeze([x]).concat(list); })) """ diff --git a/test/translator/protocol_test.exs b/test/translator/protocol_test.exs index 01b4b6fe..c72a5527 100644 --- a/test/translator/protocol_test.exs +++ b/test/translator/protocol_test.exs @@ -36,11 +36,11 @@ defmodule ElixirScript.Translator.Defprotocol.Test do export default Elixir$Blank; import Elixir$ElixirScript$Kernel from './Elixir.ElixirScript.Kernel'; - const blank__qmark__ = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([false],function() { + const blank__qmark__ = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.clause([false],function() { return true; - }),Elixir.Core.Patterns.make_case([null],function() { + }),Elixir.Core.Patterns.clause([null],function() { return true; - }),Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.wildcard()],function() { + }),Elixir.Core.Patterns.clause([Elixir.Core.Patterns.wildcard()],function() { return false; })); export default { @@ -50,7 +50,7 @@ defmodule ElixirScript.Translator.Defprotocol.Test do }; import Elixir$ElixirScript$Kernel from './Elixir.ElixirScript.Kernel'; - const blank__qmark__ = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable()],function(number) { + const blank__qmark__ = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.clause([Elixir.Core.Patterns.variable()],function(number) { return false; })); export default { @@ -60,9 +60,9 @@ defmodule ElixirScript.Translator.Defprotocol.Test do }; import Elixir$ElixirScript$Kernel from './Elixir.ElixirScript.Kernel'; - const blank__qmark__ = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Object.freeze([])],function() { + const blank__qmark__ = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.clause([Object.freeze([])],function() { return true; - }),Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.wildcard()],function() { + }),Elixir.Core.Patterns.clause([Elixir.Core.Patterns.wildcard()],function() { return false; })); export default { diff --git a/test/translator/try_test.exs b/test/translator/try_test.exs index 7be94ed7..cdfe85c8 100644 --- a/test/translator/try_test.exs +++ b/test/translator/try_test.exs @@ -15,7 +15,7 @@ defmodule ElixirScript.Translator.Try.Test do js_code = """ Elixir.Core.SpecialForms._try(function() { return do_something_that_may_fail(some_arg); - }, Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.type(ArgumentError, {})], function() { + }, Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.clause([Elixir.Core.Patterns.type(ArgumentError, {})], function() { return IO.puts('Invalid argument given'); })), null, null, null) """ @@ -36,7 +36,7 @@ defmodule ElixirScript.Translator.Try.Test do js_code = """ Elixir.Core.SpecialForms._try(function() { return do_something_that_may_fail(some_arg); - }, Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.type(ArgumentError, {})], function() { + }, Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.clause([Elixir.Core.Patterns.type(ArgumentError, {})], function() { return IO.puts('Invalid argument given'); })), null, null, null) """ @@ -57,7 +57,7 @@ defmodule ElixirScript.Translator.Try.Test do js_code = """ Elixir.Core.SpecialForms._try(function() { return do_something_that_may_fail(some_arg); - },Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable()],function(x) { + },Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.clause([Elixir.Core.Patterns.variable()],function(x) { return IO.puts('Invalid argument given'); },function(x) { return Elixir.Core.Functions.contains(x,Object.freeze([ArgumentError.create(Object.freeze({}))])); @@ -80,7 +80,7 @@ defmodule ElixirScript.Translator.Try.Test do js_code = """ Elixir.Core.SpecialForms._try(function() { return do_something_that_may_fail(some_arg); - },Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable()],function(x) { + },Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.clause([Elixir.Core.Patterns.variable()],function(x) { return IO.puts('Invalid argument given'); })),null,null,null) """ @@ -104,9 +104,9 @@ defmodule ElixirScript.Translator.Try.Test do js_code = """ Elixir.Core.SpecialForms._try(function() { return do_something_that_may_fail(some_arg); - }, Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.type(ArgumentError, {})], function() { + }, Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.clause([Elixir.Core.Patterns.type(ArgumentError, {})], function() { return IO.puts('ArgumentError'); - }), Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable()], function(x) { + }), Elixir.Core.Patterns.clause([Elixir.Core.Patterns.variable()], function(x) { return IO.puts('x'); })), null, null, null) """ @@ -129,7 +129,7 @@ defmodule ElixirScript.Translator.Try.Test do js_code = """ Elixir.Core.SpecialForms._try(function() { return do_something_that_may_fail(some_arg); - }, Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.type(ArgumentError, {})], function() { + }, Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.clause([Elixir.Core.Patterns.type(ArgumentError, {})], function() { return IO.puts('Invalid argument given'); })), null, null, function() { return IO.puts('This is printed regardless if it failed or succeed'); @@ -174,11 +174,11 @@ defmodule ElixirScript.Translator.Try.Test do js_code = """ Elixir.Core.SpecialForms._try(function() { return 1 / x; - },null,null,Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.variable()],function(y) { + },null,null,Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.clause([Elixir.Core.Patterns.variable()],function(y) { return Symbol.for('small'); },function(y) { return (y < 1) && (y > -1); - }),Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.wildcard()],function() { + }),Elixir.Core.Patterns.clause([Elixir.Core.Patterns.wildcard()],function() { return Symbol.for('large'); })),null) """ @@ -202,9 +202,9 @@ defmodule ElixirScript.Translator.Try.Test do js_code = """ Elixir.Core.SpecialForms._try(function() { return do_something_that_may_fail(some_arg); - }, Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Elixir.Core.Patterns.type(ArgumentError, {})], function() { + }, Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.clause([Elixir.Core.Patterns.type(ArgumentError, {})], function() { return IO.puts('Invalid argument given'); - })), Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.make_case([Symbol.for('throw'), Symbol.for('Error')], function() { + })), Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.clause([Symbol.for('throw'), Symbol.for('Error')], function() { return IO.puts('caught error'); })), null, null) """ From 1d745eb2201c88ca64467f6ccc8088717810b081 Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Wed, 22 Jun 2016 15:01:25 -0500 Subject: [PATCH 265/860] Updated broken tests --- test/translator/function_test.exs | 10 +++++----- test/translator/kernel/receive_test.exs | 6 +++--- test/translator/kernel/send_test.exs | 2 +- test/translator/kernel/spawn_test.exs | 4 ++-- test/translator/string_test.exs | 2 +- 5 files changed, 12 insertions(+), 12 deletions(-) diff --git a/test/translator/function_test.exs b/test/translator/function_test.exs index f46df062..7a01af3c 100644 --- a/test/translator/function_test.exs +++ b/test/translator/function_test.exs @@ -89,7 +89,7 @@ defmodule ElixirScript.Translator.Function.Test do return Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.clause([Elixir.Core.Patterns.variable()],function(x) { return 2; },function(x) { - return Elixir.Enum.member__qmark__(Object.freeze([false, null]),x); + return (x === null) || (x === false); }),Elixir.Core.Patterns.clause([Elixir.Core.Patterns.wildcard()],function() { return 1; })).call(this,1 == 1); @@ -117,13 +117,13 @@ defmodule ElixirScript.Translator.Function.Test do return Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.clause([Elixir.Core.Patterns.variable()],function(x) { return 2; },function(x) { - return Elixir.Enum.member__qmark__(Object.freeze([false, null]),x); + return (x === null) || (x === false); }),Elixir.Core.Patterns.clause([Elixir.Core.Patterns.wildcard()],function() { return Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.clause([Elixir.Core.Patterns.variable()],function(x) { let [a] = Elixir.Core.Patterns.match(Elixir.Core.Patterns.variable(),1); return a; },function(x) { - return Elixir.Enum.member__qmark__(Object.freeze([false, null]),x); + return (x === null) || (x === false); }),Elixir.Core.Patterns.clause([Elixir.Core.Patterns.wildcard()],function() { return 4; })).call(this,2 == 2); @@ -800,7 +800,7 @@ defmodule ElixirScript.Translator.Function.Test do return Symbol.for('error'); }, function(x) { - return Elixir.Enum.member__qmark__(Object.freeze([false, null]), x); + return (x === null) || (x === false); }), Elixir.Core.Patterns.clause([Elixir.Core.Patterns.wildcard()], function() { return null; @@ -828,7 +828,7 @@ defmodule ElixirScript.Translator.Function.Test do js_code = """ let [key] = Elixir.Core.Patterns.match(Elixir.Core.Patterns.variable(),'test'); - + Elixir.Core.Patterns.defmatch( Elixir.Core.Patterns.clause( [Elixir.Core.Patterns.bound(key)], diff --git a/test/translator/kernel/receive_test.exs b/test/translator/kernel/receive_test.exs index 41b69162..0c84ea75 100644 --- a/test/translator/kernel/receive_test.exs +++ b/test/translator/kernel/receive_test.exs @@ -26,7 +26,7 @@ defmodule ElixirScript.Translator.Receive.Test do }),Elixir.Core.Patterns.clause([Symbol.for('error')],function() { return value; }),Elixir.Core.Patterns.clause([Elixir.Core.Patterns.wildcard()],function() { - return yield* Elixir.Core.Functions.run(IO['puts'],['Unexpected message received'],null); + return IO.puts('Unexpected message received'); })).call(this,message); }); }) @@ -61,10 +61,10 @@ defmodule ElixirScript.Translator.Receive.Test do }),Elixir.Core.Patterns.clause([Symbol.for('error')],function() { return value; }),Elixir.Core.Patterns.clause([Elixir.Core.Patterns.wildcard()],function() { - return yield* Elixir.Core.Functions.run(IO['puts'],['Unexpected message received'],null); + return IO.puts('Unexpected message received'); })).call(this,message); },5000,Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.clause([5000],function() { - return yield* Elixir.Core.Functions.run(IO['puts'],['No message in 5 seconds'],null); + return IO.puts('No message in 5 seconds'); }))); }) """ diff --git a/test/translator/kernel/send_test.exs b/test/translator/kernel/send_test.exs index 19fc2e86..5de1de2d 100644 --- a/test/translator/kernel/send_test.exs +++ b/test/translator/kernel/send_test.exs @@ -27,7 +27,7 @@ defmodule ElixirScript.Translator.Send.Test do js_code = """ Elixir.Core.processes.spawn(function*() { let [inside] = Elixir.Core.Patterns.match(Elixir.Core.Patterns.variable(),Elixir.Core.processes.pid()); - return yield* Elixir.Core.Functions.run(Elixir.Core.processes['send'],[pid, 'hello'], null); + return yield* Elixir.Core.Functions.run(Elixir.Core.processes['send'],[pid, 'hello'],Elixir.Core.processes); }) """ diff --git a/test/translator/kernel/spawn_test.exs b/test/translator/kernel/spawn_test.exs index d367d8d5..763c6e47 100644 --- a/test/translator/kernel/spawn_test.exs +++ b/test/translator/kernel/spawn_test.exs @@ -24,8 +24,8 @@ defmodule ElixirScript.Translator.Spawn.Test do js_code = """ Elixir.Core.processes.spawn(function*() { - yield* Elixir.Core.Functions.run(Window['call'],[1],null) - return yield* Elixir.Core.Functions.run(Elixir$ElixirScript$Tuple['to_list'],[new Elixir.Core.Tuple(1,2,3)],null); + yield* Elixir.Core.Functions.run(Window['call'],[1],Window) + return yield* Elixir.Core.Functions.run(Elixir$ElixirScript$Tuple['to_list'],[new Elixir.Core.Tuple(1,2,3)],Elixir$ElixirScript$Tuple); }) """ diff --git a/test/translator/string_test.exs b/test/translator/string_test.exs index 5d1318ef..16d3d6b9 100644 --- a/test/translator/string_test.exs +++ b/test/translator/string_test.exs @@ -22,7 +22,7 @@ defmodule ElixirScript.Translator.String.Test do test "translate string interpolation" do ex_ast = quote do: "Hello #{"world"}" - assert_translation(ex_ast, "'Hello ' + 'world'") + assert_translation(ex_ast, "'Hello ' + Elixir$ElixirScript$String$Chars.to_string('world')") ex_ast = quote do: "Hello #{length([])}" assert_translation(ex_ast, "'Hello ' + Elixir$ElixirScript$String$Chars.to_string(Elixir$ElixirScript$Kernel.length(Object.freeze([])))") From bcfe41beba16d76f9f46d30d803dd5ed4877c2e0 Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Wed, 22 Jun 2016 15:49:34 -0500 Subject: [PATCH 266/860] Updated travis config --- .travis.yml | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/.travis.yml b/.travis.yml index 735aa1c3..76b8c5fd 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,12 +1,11 @@ sudo: false language: elixir elixir: - - 1.2.6 - - 1.3.0-rc.1 + - 1.3.0 otp_release: - 18.0 env: - - TRAVIS_NODE_VERSION="5" + - TRAVIS_NODE_VERSION="6" install: - rm -rf ~/.nvm && git clone https://github.com/creationix/nvm.git ~/.nvm && (cd ~/.nvm && git checkout `git describe --abbrev=0 --tags`) && source ~/.nvm/nvm.sh && nvm install $TRAVIS_NODE_VERSION - npm install From 7a83b581d1043b35bd2be5449575151526041afa Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Wed, 22 Jun 2016 15:55:24 -0500 Subject: [PATCH 267/860] Updated travis config --- .travis.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.travis.yml b/.travis.yml index 76b8c5fd..f43c7343 100644 --- a/.travis.yml +++ b/.travis.yml @@ -11,6 +11,7 @@ install: - npm install script: - mix local.hex --force + - mix local.rebar --force - mix deps.get - mix do std_lib, clean, compile - mix test From 636a8e0ba9fa280e8faa6b50d79434161381d285 Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Wed, 22 Jun 2016 16:16:26 -0500 Subject: [PATCH 268/860] Removed unsafe variable binding warnings --- lib/elixir_script.ex | 8 ++- lib/elixir_script/prelude/agent.ex | 24 +++---- .../kernel/special_forms/capture.ex | 6 +- .../translator/kernel/special_forms/fn.ex | 6 +- .../translator/kernel/special_forms/try.ex | 25 ++++---- lib/elixir_script/translator/lexical_scope.ex | 62 +++++++++++-------- lib/elixir_script/translator/state.ex | 6 +- lib/mix/tasks/elixirscript.watch.ex | 2 +- 8 files changed, 78 insertions(+), 61 deletions(-) diff --git a/lib/elixir_script.ex b/lib/elixir_script.ex index e4cfe0e0..0fc327e8 100644 --- a/lib/elixir_script.ex +++ b/lib/elixir_script.ex @@ -216,9 +216,11 @@ defmodule ElixirScript do defp update_quoted(quoted) do Macro.prewalk(quoted, fn ({name, context, parms}) -> - if context[:import] == Kernel do - context = Keyword.update!(context, :import, fn(_) -> ElixirScript.Kernel end) - end + context = if context[:import] == Kernel do + context = Keyword.update!(context, :import, fn(_) -> ElixirScript.Kernel end) + else + context + end {name, context, parms} (x) -> diff --git a/lib/elixir_script/prelude/agent.ex b/lib/elixir_script/prelude/agent.ex index 6e212eb4..7ac21b12 100644 --- a/lib/elixir_script/prelude/agent.ex +++ b/lib/elixir_script/prelude/agent.ex @@ -2,29 +2,31 @@ defmodule ElixirScript.Agent do def start(fun) do pid = JS.global().processes.spawn() - JS.global().processes.put(pid, "state", fun.()); + Elixir.Core.processes.put(pid, "state", fun.()); { :ok, pid } end def start(fun, options) do - pid = JS.global().processes.spawn() + pid = Elixir.Core.processes.spawn() - if Elixir.Keyword.has_key?(options, :name) do - pid = JS.global().processes.register(Elixir.Keyword.get(options, :name), pid) + pid = if Elixir.Keyword.has_key?(options, :name) do + Elixir.Core.processes.register(Elixir.Keyword.get(options, :name), pid) + else + pid end - JS.global().processes.put(pid, "state", fun.()) + Elixir.Core.processes.put(pid, "state", fun.()) { :ok, pid } end - def stop(view) do - JS.global().processes.exit(view) + def stop(agent) do + Elixir.Core.processes.exit(agent) :ok end def update(agent, fun) do - current_state = JS.global().processes.get(agent, "state") - JS.global().processes.put(agent, "state", fun.(current_state)); + current_state = Elixir.Core.processes.get(agent, "state") + Elixir.Core.processes.put(agent, "state", fun.(current_state)); :ok end @@ -34,9 +36,9 @@ defmodule ElixirScript.Agent do end def get_and_update(agent, fun) do - current_state = JS.global().processes.get(agent, "state") + current_state = Elixir.Core.processes.get(agent, "state") {val, new_state} = fun.(current_state) - JS.global().processes.put(agent, "state", new_state); + Elixir.Core.processes.put(agent, "state", new_state); val end diff --git a/lib/elixir_script/translator/kernel/special_forms/capture.ex b/lib/elixir_script/translator/kernel/special_forms/capture.ex index 1b806883..9d53fd20 100644 --- a/lib/elixir_script/translator/kernel/special_forms/capture.ex +++ b/lib/elixir_script/translator/kernel/special_forms/capture.ex @@ -29,8 +29,10 @@ defmodule ElixirScript.Translator.Capture do { _, _, name } = module_name - if name == [:Kernel] or name == [Elixir, :Kernel] do - name = [:ElixirScript, :Kernel] + name = if name == [:Kernel] or name == [Elixir, :Kernel] do + [:ElixirScript, :Kernel] + else + name end { func, _ } = Call.make_function_call({:__aliases__, [], name }, function_name, arity_params, env) diff --git a/lib/elixir_script/translator/kernel/special_forms/fn.ex b/lib/elixir_script/translator/kernel/special_forms/fn.ex index a37f8bbe..5eced876 100644 --- a/lib/elixir_script/translator/kernel/special_forms/fn.ex +++ b/lib/elixir_script/translator/kernel/special_forms/fn.ex @@ -107,8 +107,10 @@ defmodule ElixirScript.Translator.Function do JS.function_expression(params, [], body), ] - if guard_body do - arguments = arguments ++ [JS.function_expression(params, [], guard_body)] + argument = if guard_body do + arguments ++ [JS.function_expression(params, [], guard_body)] + else + arguments end JS.call_expression( diff --git a/lib/elixir_script/translator/kernel/special_forms/try.ex b/lib/elixir_script/translator/kernel/special_forms/try.ex index 3568427a..81db4a39 100644 --- a/lib/elixir_script/translator/kernel/special_forms/try.ex +++ b/lib/elixir_script/translator/kernel/special_forms/try.ex @@ -16,28 +16,29 @@ defmodule ElixirScript.Translator.Try do translated_body = JS.block_statement(translated_body) try_block = JS.function_expression([], [], translated_body) - if rescue_block do - rescue_block = process_rescue_block(rescue_block, env) + rescue_block = if rescue_block do + process_rescue_block(rescue_block, env) else - rescue_block = JS.identifier(:null) + JS.identifier(:null) end - if catch_block do - catch_block = process_catch_block(catch_block, env) + catch_block = if catch_block do + process_catch_block(catch_block, env) else - catch_block = JS.identifier(:null) + JS.identifier(:null) end - if after_block do - after_block = process_after_block(after_block, env) + after_block = if after_block do + process_after_block(after_block, env) else - after_block = JS.identifier(:null) + JS.identifier(:null) end - if else_block do - { else_block, _ } = Function.make_anonymous_function(else_block, env) + else_block = if else_block do + Function.make_anonymous_function(else_block, env) + |> elem(0) else - else_block = JS.identifier(:null) + JS.identifier(:null) end js_ast = JS.call_expression( diff --git a/lib/elixir_script/translator/lexical_scope.ex b/lib/elixir_script/translator/lexical_scope.ex index 44104758..d5fbee58 100644 --- a/lib/elixir_script/translator/lexical_scope.ex +++ b/lib/elixir_script/translator/lexical_scope.ex @@ -200,19 +200,20 @@ defmodule ElixirScript.Translator.LexicalScope do def add_import(env, module_name) do check_for_module_existence(env, module_name) - if ElixirScript.Translator.State.is_module_loaded?(module_name) do - env = add_import_macro(env, module_name, []) + env = if ElixirScript.Translator.State.is_module_loaded?(module_name) do + add_import_macro(env, module_name, []) + else + env end if has_module?(env, module_name) do module = get_module(env, module_name) - env = %{ env | requires: Enum.uniq(env.requires ++ [module.name]), + %{ env | requires: Enum.uniq(env.requires ++ [module.name]), functions: env.functions ++ [{ module.name, module.functions }] } - + else + env end - - env end def add_import(env, module_name, [only: :functions]) do @@ -233,10 +234,12 @@ defmodule ElixirScript.Translator.LexicalScope do def add_import(env, module_name, [only: only]) do check_for_module_existence(env, module_name) - if ElixirScript.Translator.State.is_module_loaded?(module_name) do + env = if ElixirScript.Translator.State.is_module_loaded?(module_name) do list = module_name.__info__(:macros) list = Enum.filter(list, fn(mac) -> mac in only end) - env = add_import_macro(env, module_name, [only: list]) + add_import_macro(env, module_name, [only: list]) + else + env end if has_module?(env, module_name) do @@ -246,20 +249,22 @@ defmodule ElixirScript.Translator.LexicalScope do func in only end) - env = %{ env | requires: Enum.uniq(env.requires ++ [module.name]), + %{ env | requires: Enum.uniq(env.requires ++ [module.name]), functions: List.keydelete(env.functions, module.name, 0) ++ [{ module.name, functions }] } + else + env end - - env end def add_import(env, module_name, [except: except]) do check_for_module_existence(env, module_name) - if ElixirScript.Translator.State.is_module_loaded?(module_name) do + env = if ElixirScript.Translator.State.is_module_loaded?(module_name) do list = module_name.__info__(:macros) list = Enum.filter(list, fn(mac) -> mac in except end) - env = add_import_macro(env, module_name, [except: list]) + add_import_macro(env, module_name, [except: list]) + else + env end if has_module?(env, module_name) do @@ -268,43 +273,46 @@ defmodule ElixirScript.Translator.LexicalScope do functions = Enum.filter(current_functions, fn(func) -> not(func in except) end) - env = %{ env | requires: env.requires ++ [module.name], + %{ env | requires: env.requires ++ [module.name], functions: List.keydelete(env.functions, module.name, 0) ++ [{ module.name, functions }] } + else + env end - - env end def add_require(env, module_name) do check_for_module_existence(env, module_name) - if ElixirScript.Translator.State.is_module_loaded?(module_name) do - env = add_require_macro(env, module_name, []) + env = if ElixirScript.Translator.State.is_module_loaded?(module_name) do + add_require_macro(env, module_name, []) + else + env end if has_module?(env, module_name) do module = get_module(env, module_name) - env = %{ env | requires: Enum.uniq(env.requires ++ [module.name]) } + %{ env | requires: Enum.uniq(env.requires ++ [module.name]) } + else + env end - - env end def add_require(env, module_name, alias_name) do check_for_module_existence(env, module_name) - if ElixirScript.Translator.State.is_module_loaded?(module_name) do - env = add_require_macro(env, module_name, [as: alias_name]) + env = if ElixirScript.Translator.State.is_module_loaded?(module_name) do + add_require_macro(env, module_name, [as: alias_name]) + else + env end if has_module?(env, module_name) do module = get_module(env, module_name) - env = %{ env | aliases: Enum.uniq(env.aliases ++ [{alias_name, module.name}]), + %{ env | aliases: Enum.uniq(env.aliases ++ [{alias_name, module.name}]), requires: Enum.uniq(env.requires ++ [module.name]) } + else + env end - - env - end def get_module_name(env, module_name) do diff --git a/lib/elixir_script/translator/state.ex b/lib/elixir_script/translator/state.ex index acb7a48b..87def232 100644 --- a/lib/elixir_script/translator/state.ex +++ b/lib/elixir_script/translator/state.ex @@ -71,10 +71,10 @@ defmodule ElixirScript.Translator.State do Agent.update(__MODULE__, fn state -> proto = Map.get(state.modules, do_get_module_name(name, state)) - if proto == nil do - proto = %ElixirScript.Module{ name: name, functions: functions, type: :protocol } + proto = if proto == nil do + %ElixirScript.Module{ name: name, functions: functions, type: :protocol } else - proto = %ElixirScript.Module{proto | functions: functions, type: :protocol } + %ElixirScript.Module{proto | functions: functions, type: :protocol } end do_add_module_to_state(state, proto) diff --git a/lib/mix/tasks/elixirscript.watch.ex b/lib/mix/tasks/elixirscript.watch.ex index 1208811f..a5695712 100644 --- a/lib/mix/tasks/elixirscript.watch.ex +++ b/lib/mix/tasks/elixirscript.watch.ex @@ -28,7 +28,7 @@ defmodule Mix.Tasks.Elixirscript.Watch do elixirscript_config = get_elixirscript_config() input_path = Keyword.fetch!(elixirscript_config, :input) output_path = Keyword.fetch!(elixirscript_config, :output) - {:ok, pid} = ElixirScript.Watcher.start_link(input_path, %{ output: output_path }) + {:ok, _} = ElixirScript.Watcher.start_link(input_path, %{ output: output_path }) :timer.sleep :infinity end From 9be8c5ff62e80ad61291a58cabc7441ed0dde66d Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Wed, 22 Jun 2016 16:24:11 -0500 Subject: [PATCH 269/860] Fixed issue with guard clause not being added correctly --- .../translator/kernel/special_forms/fn.ex | 22 +++++++++++-------- 1 file changed, 13 insertions(+), 9 deletions(-) diff --git a/lib/elixir_script/translator/kernel/special_forms/fn.ex b/lib/elixir_script/translator/kernel/special_forms/fn.ex index 5eced876..215e1324 100644 --- a/lib/elixir_script/translator/kernel/special_forms/fn.ex +++ b/lib/elixir_script/translator/kernel/special_forms/fn.ex @@ -102,16 +102,20 @@ defmodule ElixirScript.Translator.Function do end def make_function_clause(patterns, params, body, guard_body) do - arguments = [ - JS.array_expression(patterns), - JS.function_expression(params, [], body), - ] + arguments = case guard_body do + nil -> + [ + JS.array_expression(patterns), + JS.function_expression(params, [], body) + ] + _ -> + [ + JS.array_expression(patterns), + JS.function_expression(params, [], body), + JS.function_expression(params, [], guard_body) + ] + end - argument = if guard_body do - arguments ++ [JS.function_expression(params, [], guard_body)] - else - arguments - end JS.call_expression( JS.member_expression( From b14be109abb855e8c4f7508ab20824534886e2b5 Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Wed, 22 Jun 2016 17:46:32 -0500 Subject: [PATCH 270/860] Updated agent code to work with new processes module --- lib/elixir_script/prelude/agent.ex | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/lib/elixir_script/prelude/agent.ex b/lib/elixir_script/prelude/agent.ex index 7ac21b12..55bd45df 100644 --- a/lib/elixir_script/prelude/agent.ex +++ b/lib/elixir_script/prelude/agent.ex @@ -1,13 +1,14 @@ defmodule ElixirScript.Agent do def start(fun) do - pid = JS.global().processes.spawn() + pid = Elixir.Core.processes.spawn(fn() -> end) Elixir.Core.processes.put(pid, "state", fun.()); { :ok, pid } end def start(fun, options) do - pid = Elixir.Core.processes.spawn() + pid = Elixir.Core.processes.spawn(fn() -> + end) pid = if Elixir.Keyword.has_key?(options, :name) do Elixir.Core.processes.register(Elixir.Keyword.get(options, :name), pid) From 8a3531fc40a6feafac48099aa09a1f574de351f8 Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Sat, 25 Jun 2016 16:12:31 -0500 Subject: [PATCH 271/860] Add store javascript module to act as backing for agent --- lib/elixir_script/prelude/agent.ex | 25 +++++++++++-------------- src/javascript/lib/core.js | 4 +++- src/javascript/lib/core/functions.js | 4 ++++ src/javascript/lib/core/store.js | 24 ++++++++++++++++++++++++ 4 files changed, 42 insertions(+), 15 deletions(-) create mode 100644 src/javascript/lib/core/store.js diff --git a/lib/elixir_script/prelude/agent.ex b/lib/elixir_script/prelude/agent.ex index 55bd45df..8d2a5f04 100644 --- a/lib/elixir_script/prelude/agent.ex +++ b/lib/elixir_script/prelude/agent.ex @@ -1,45 +1,42 @@ defmodule ElixirScript.Agent do def start(fun) do - pid = Elixir.Core.processes.spawn(fn() -> end) - Elixir.Core.processes.put(pid, "state", fun.()); + pid = Elixir.Core.Functions.new_pid() + Elixir.Core.Store.create(pid, fun.()) { :ok, pid } end def start(fun, options) do - pid = Elixir.Core.processes.spawn(fn() -> - end) - pid = if Elixir.Keyword.has_key?(options, :name) do - Elixir.Core.processes.register(Elixir.Keyword.get(options, :name), pid) + Elixir.Keyword.get(options, :name) else - pid + Elixir.Core.Functions.new_pid() end - Elixir.Core.processes.put(pid, "state", fun.()) + Elixir.Core.Store.create(pid, fun.()) { :ok, pid } end def stop(agent) do - Elixir.Core.processes.exit(agent) + Elixir.Core.Store.remove(agent) :ok end def update(agent, fun) do - current_state = Elixir.Core.processes.get(agent, "state") - Elixir.Core.processes.put(agent, "state", fun.(current_state)); + current_state = Elixir.Core.Store.read(agent) + Elixir.Core.Store.update(agent, fun.(current_state)) :ok end def get(agent, fun) do - current_state = JS.global().processes.get(agent, "state") + current_state = Elixir.Core.Store.read(agent) fun.(current_state) end def get_and_update(agent, fun) do - current_state = Elixir.Core.processes.get(agent, "state") + current_state = Elixir.Core.Store.read(agent) {val, new_state} = fun.(current_state) - Elixir.Core.processes.put(agent, "state", new_state); + Elixir.Core.Store.update(agent, new_state) val end diff --git a/src/javascript/lib/core.js b/src/javascript/lib/core.js index f3b5b4bd..e1b229aa 100644 --- a/src/javascript/lib/core.js +++ b/src/javascript/lib/core.js @@ -3,6 +3,7 @@ import Patterns from 'tailored'; import ErlangTypes from 'erlang-types'; import Functions from './core/functions'; import SpecialForms from './core/special_forms'; +import Store from './core/store'; let processes = new Processes.ProcessSystem(); @@ -19,5 +20,6 @@ export default { Integer, Float, Functions, - SpecialForms + SpecialForms, + Store }; diff --git a/src/javascript/lib/core/functions.js b/src/javascript/lib/core/functions.js index cc3ad014..2e9dd59c 100644 --- a/src/javascript/lib/core/functions.js +++ b/src/javascript/lib/core/functions.js @@ -400,6 +400,10 @@ function maps_from_list(list){ return Object.freeze(m); } +function new_pid(){ + return new Core.PID(); +} + export default { call_property, run, diff --git a/src/javascript/lib/core/store.js b/src/javascript/lib/core/store.js new file mode 100644 index 00000000..6a1c6450 --- /dev/null +++ b/src/javascript/lib/core/store.js @@ -0,0 +1,24 @@ +let store = new Map(); + +function create(key, value){ + store.set(key, value); +} + +function update(key, value){ + store.set(key, value); +} + +function read(key){ + return store.get(key); +} + +function remove(key){ + return store.delete(key); +} + +export default { + create, + read, + update, + remove +}; From 0b60b1447964d87d175a80f929f04d2a6b822385 Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Sat, 25 Jun 2016 19:40:55 -0500 Subject: [PATCH 272/860] Add sleep function to Process --- lib/elixir_script/prelude/process.ex | 3 +++ 1 file changed, 3 insertions(+) diff --git a/lib/elixir_script/prelude/process.ex b/lib/elixir_script/prelude/process.ex index 46561977..c8fbfad3 100644 --- a/lib/elixir_script/prelude/process.ex +++ b/lib/elixir_script/prelude/process.ex @@ -64,5 +64,8 @@ defmodule ElixirScript.Process do Elixir.Core.processes.list() end + def sleep(duration) do + Elixir.Core.processes.sleep(duration) + end end From bffbb5b511f12dae66de21a59f1429a204e8bf69 Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Sat, 25 Jun 2016 19:49:45 -0500 Subject: [PATCH 273/860] Add monitor and demonitor to Process module --- lib/elixir_script/prelude/process.ex | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/lib/elixir_script/prelude/process.ex b/lib/elixir_script/prelude/process.ex index c8fbfad3..b1847f11 100644 --- a/lib/elixir_script/prelude/process.ex +++ b/lib/elixir_script/prelude/process.ex @@ -48,6 +48,14 @@ defmodule ElixirScript.Process do Elixir.Core.processes.unlink(pid) end + def monitor(item) do + Elixir.Core.processes.monitor(item) + end + + def demonitor(monitor_ref) do + Elixir.Core.processes.demonitor(monitor_ref) + end + def register(pid, name) when is_atom(name) do Elixir.Core.processes.register(pid, name) end From 40c8764255632540bffd13e862e98c30f8cf1280 Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Sun, 26 Jun 2016 08:57:40 -0500 Subject: [PATCH 274/860] Add sleep infinity function head --- lib/elixir_script/prelude/process.ex | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/lib/elixir_script/prelude/process.ex b/lib/elixir_script/prelude/process.ex index b1847f11..35335799 100644 --- a/lib/elixir_script/prelude/process.ex +++ b/lib/elixir_script/prelude/process.ex @@ -72,8 +72,12 @@ defmodule ElixirScript.Process do Elixir.Core.processes.list() end - def sleep(duration) do + def sleep(duration) when is_integer(duration) do Elixir.Core.processes.sleep(duration) end + def sleep(:infinity) do + Elixir.Core.processes.sleep(:infinity) + end + end From 565d81bad730e188dfc330a31cd19ed7bcb2b1e0 Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Sun, 26 Jun 2016 09:19:11 -0500 Subject: [PATCH 275/860] Fixed scope issue with spawn. Added start_link to Agent --- lib/elixir_script/prelude/agent.ex | 34 ++++++++++++-------- lib/elixir_script/translator/kernel/spawn.ex | 2 +- 2 files changed, 22 insertions(+), 14 deletions(-) diff --git a/lib/elixir_script/prelude/agent.ex b/lib/elixir_script/prelude/agent.ex index 8d2a5f04..ce2dcdde 100644 --- a/lib/elixir_script/prelude/agent.ex +++ b/lib/elixir_script/prelude/agent.ex @@ -1,16 +1,21 @@ defmodule ElixirScript.Agent do - def start(fun) do - pid = Elixir.Core.Functions.new_pid() + def start(fun, options \\ []) do + pid = spawn(fn() -> Process.sleep(:infinity) end) + + if Elixir.Keyword.has_key?(options, :name) do + Process.register(pid, Elixir.Keyword.get(options, :name)) + end + Elixir.Core.Store.create(pid, fun.()) { :ok, pid } end - def start(fun, options) do - pid = if Elixir.Keyword.has_key?(options, :name) do - Elixir.Keyword.get(options, :name) - else - Elixir.Core.Functions.new_pid() + def start_link(fun, options \\ []) do + pid = spawn_link(fn() -> Process.sleep(:infinity) end) + + if Elixir.Keyword.has_key?(options, :name) do + Process.register(pid, Elixir.Keyword.get(options, :name)) end Elixir.Core.Store.create(pid, fun.()) @@ -18,25 +23,28 @@ defmodule ElixirScript.Agent do end def stop(agent) do - Elixir.Core.Store.remove(agent) + Process.exit(agent) :ok end def update(agent, fun) do - current_state = Elixir.Core.Store.read(agent) - Elixir.Core.Store.update(agent, fun.(current_state)) + pid = Elixir.Core.processes.pidof(agent) + current_state = Elixir.Core.Store.read(pid) + Elixir.Core.Store.update(pid, fun.(current_state)) :ok end def get(agent, fun) do - current_state = Elixir.Core.Store.read(agent) + pid = Elixir.Core.processes.pidof(agent) + current_state = Elixir.Core.Store.read(pid) fun.(current_state) end def get_and_update(agent, fun) do - current_state = Elixir.Core.Store.read(agent) + pid = Elixir.Core.processes.pidof(agent) + current_state = Elixir.Core.Store.read(pid) {val, new_state} = fun.(current_state) - Elixir.Core.Store.update(agent, new_state) + Elixir.Core.Store.update(pid, new_state) val end diff --git a/lib/elixir_script/translator/kernel/spawn.ex b/lib/elixir_script/translator/kernel/spawn.ex index 6e1b468e..cf096547 100644 --- a/lib/elixir_script/translator/kernel/spawn.ex +++ b/lib/elixir_script/translator/kernel/spawn.ex @@ -17,7 +17,7 @@ defmodule ElixirScript.Translator.Spawn do end defp do_spawn_with_fn({:fn, _, [{:->, _, [[], body]}]}, env, spawn_func_name) do - { body, env } = Function.prepare_function_body(body, %{ env | in_process: true }) + { body, _ } = Function.prepare_function_body(body, %{ env | in_process: true }) js = call_processes_func(spawn_func_name, [JS.function_expression([], [], JS.block_statement(body), true)]) { js, env } end From f60fc5330402cf66ed37e9f6d36db2795f364859 Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Sun, 26 Jun 2016 09:20:05 -0500 Subject: [PATCH 276/860] Removed make_pid function --- src/javascript/lib/core/functions.js | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/javascript/lib/core/functions.js b/src/javascript/lib/core/functions.js index 2e9dd59c..cc3ad014 100644 --- a/src/javascript/lib/core/functions.js +++ b/src/javascript/lib/core/functions.js @@ -400,10 +400,6 @@ function maps_from_list(list){ return Object.freeze(m); } -function new_pid(){ - return new Core.PID(); -} - export default { call_property, run, From e8ef5aea03c4e5da0c6eaa7dd234040ac2ec81a9 Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Sun, 26 Jun 2016 09:41:13 -0500 Subject: [PATCH 277/860] Add version to compiler cache --- lib/elixir_script.ex | 11 ++++++++++- lib/elixir_script/compiler/cache.ex | 3 ++- 2 files changed, 12 insertions(+), 2 deletions(-) diff --git a/lib/elixir_script.ex b/lib/elixir_script.ex index 0fc327e8..e32ecdf1 100644 --- a/lib/elixir_script.ex +++ b/lib/elixir_script.ex @@ -44,6 +44,7 @@ defmodule ElixirScript do @external_resource stdlib_state_path = Path.join([__DIR__, "elixir_script", "translator", "stdlib_state.bin"]) @stdlib_state File.read(stdlib_state_path) @lib_path Application.get_env(:elixir_script, :lib_path) + @version Mix.Project.config[:version] @doc """ Compiles the given Elixir code string @@ -120,7 +121,7 @@ defmodule ElixirScript do end defp get_compiler_cache(path, opts) do - if Map.get(opts, :full_build) or empty?(opts.output) do + if Map.get(opts, :full_build) or empty?(opts.output) or old_version?(opts) do Cache.delete(path) Cache.new(get_stdlib_state) else @@ -148,6 +149,14 @@ defmodule ElixirScript do true end + defp old_version?(opts) do + cache_version = Map.get(opts, :version, nil) + cache_version == version() + end + + @doc false + def version(), do: @version + @doc false def compile_std_lib() do compile_std_lib(Path.join([File.cwd!, "priv"])) diff --git a/lib/elixir_script/compiler/cache.ex b/lib/elixir_script/compiler/cache.ex index d9bc94dd..13f1d534 100644 --- a/lib/elixir_script/compiler/cache.ex +++ b/lib/elixir_script/compiler/cache.ex @@ -82,7 +82,8 @@ defmodule ElixirScript.Compiler.Cache do %{ input_files: [], state: state, - full_build?: true + full_build?: true, + version: ElixirScript.version() } end From 68b33696fab9bbe9c22bcc6428056fe3e9ef9cd4 Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Sun, 26 Jun 2016 09:51:19 -0500 Subject: [PATCH 278/860] Refactored refresh_cache code --- lib/elixir_script.ex | 22 +++++++++++++++------- 1 file changed, 15 insertions(+), 7 deletions(-) diff --git a/lib/elixir_script.ex b/lib/elixir_script.ex index e32ecdf1..d15e86e8 100644 --- a/lib/elixir_script.ex +++ b/lib/elixir_script.ex @@ -121,16 +121,24 @@ defmodule ElixirScript do end defp get_compiler_cache(path, opts) do - if Map.get(opts, :full_build) or empty?(opts.output) or old_version?(opts) do + refresh_cache = cond do + Map.get(opts, :full_build) -> + true + empty?(opts.output) -> + true + old_version?(opts) -> + true + Cache.get(path) == nil -> + true + true -> + false + end + + if refresh_cache do Cache.delete(path) Cache.new(get_stdlib_state) else - case Cache.get(path) do - nil -> - Cache.new(get_stdlib_state) - x -> - %{ x | full_build?: false } - end + %{ Cache.get(path) | full_build?: false } end end From 7918c388bdf77cdc3e836e1519ad4ecb443bc23a Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Mon, 27 Jun 2016 21:32:44 -0500 Subject: [PATCH 279/860] Updated npm package versions --- package.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/package.json b/package.json index b0cb8c73..02cbdac2 100644 --- a/package.json +++ b/package.json @@ -20,8 +20,8 @@ "license": "MIT", "dependencies": { "erlang-types": "^1.0.0", - "erlang-processes": "bryanjos/processes", - "tailored": "bryanjos/tailored" + "erlang-processes": "^2.0.0", + "tailored": "^2.0.0" }, "devDependencies": { "babel": "^6.5.2", From 62928b5452a40ea9b3683168d9192b812b112a66 Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Tue, 28 Jun 2016 14:22:32 -0500 Subject: [PATCH 280/860] Updated changelog. Added make_ref to kernel --- CHANGELOG.md | 33 ++++++++++++++++++++++++++++ lib/elixir_script/prelude/kernel.ex | 4 ++++ lib/elixir_script/prelude/process.ex | 7 ++++++ lib/elixir_script/translator.ex | 5 +++++ 4 files changed, 49 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 28ff6891..63a6a3d3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,4 +1,37 @@ # v0.21.0-dev +* Enhancements + * This is the first release with early support for processes in elixirscript. Creating a process only works currently using `spawn/1`, `spawn_link/1`, and `spawn_monitor/1`. Inside of a process, you can use functions such as `send` and `receive`, along with some defined in the `Process` module. From outside of a process, you can send messages to a process, but you cannot receive a message from a process. Eventually all code will run inside processes and this restriction will naturally lift. + * The `Process` module has been implemented with the following functions: + * `alive?/1` + * `delete/1` + * `demonitor/1` + * `exit/2` + * `flag/2` + * `flag/3` + * `get/0` + * `get_keys/0` + * `get_keys/1` + * `link/1` + * `list/0` + * `monitor/1` + * `put/2` + * `register/2` + * `registered/0` + * `send/3` + * `sleep/1` + * `unlink/1` + * `unregister/1` + * `whereis/1` + * The `receive` special form has been implemented with the above caveat + * The following have been implemented on `Kernel`: + * `spawn/1` + * `spawn_link/1` + * `spawn_monitor/1` + * `send/2` + * `make_ref/0` + + + * Fixed * Scoping on `fn` and `def` diff --git a/lib/elixir_script/prelude/kernel.ex b/lib/elixir_script/prelude/kernel.ex index fb4de196..92026de9 100644 --- a/lib/elixir_script/prelude/kernel.ex +++ b/lib/elixir_script/prelude/kernel.ex @@ -156,6 +156,10 @@ defmodule ElixirScript.Kernel do term === nil end + def make_ref() do + Elixir.Core.processes.make_ref() + end + defmacro match?(left, right) do quote do case unquote(right) do diff --git a/lib/elixir_script/prelude/process.ex b/lib/elixir_script/prelude/process.ex index 35335799..cef9db6d 100644 --- a/lib/elixir_script/prelude/process.ex +++ b/lib/elixir_script/prelude/process.ex @@ -68,6 +68,10 @@ defmodule ElixirScript.Process do Elixir.Core.processes.whereis(name) end + def unregister(name) do + Elixir.Core.processes.unregister(name) + end + def list() do Elixir.Core.processes.list() end @@ -80,4 +84,7 @@ defmodule ElixirScript.Process do Elixir.Core.processes.sleep(:infinity) end + def send(dest, msg, _) do + Elixir.Core.processes.send(dest, msg) + end end diff --git a/lib/elixir_script/translator.ex b/lib/elixir_script/translator.ex index f3a5b15c..973508ad 100644 --- a/lib/elixir_script/translator.ex +++ b/lib/elixir_script/translator.ex @@ -457,6 +457,11 @@ defmodule ElixirScript.Translator do {js, env} end + defp do_translate({:send, _, [id, msg, _]}, env) do + js = Spawn.call_processes_func("send", [translate!(id, env), translate!(msg, env)]) + {js, env} + end + defp do_translate({:self, _, []}, env) do js = Spawn.call_processes_func("pid", []) {js, env} From a90dc5b03a19ffd21c263adb9747f091531d1208 Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Tue, 28 Jun 2016 15:30:35 -0500 Subject: [PATCH 281/860] Updating for release --- CHANGELOG.md | 2 +- lib/elixir_script/translator/kernel/spawn.ex | 2 ++ lib/elixir_script/translator/kernel/special_forms/receive.ex | 3 ++- mix.exs | 2 +- 4 files changed, 6 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 63a6a3d3..dd68832a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,4 +1,4 @@ -# v0.21.0-dev +# v0.21.0 * Enhancements * This is the first release with early support for processes in elixirscript. Creating a process only works currently using `spawn/1`, `spawn_link/1`, and `spawn_monitor/1`. Inside of a process, you can use functions such as `send` and `receive`, along with some defined in the `Process` module. From outside of a process, you can send messages to a process, but you cannot receive a message from a process. Eventually all code will run inside processes and this restriction will naturally lift. * The `Process` module has been implemented with the following functions: diff --git a/lib/elixir_script/translator/kernel/spawn.ex b/lib/elixir_script/translator/kernel/spawn.ex index cf096547..b2da02ce 100644 --- a/lib/elixir_script/translator/kernel/spawn.ex +++ b/lib/elixir_script/translator/kernel/spawn.ex @@ -1,4 +1,6 @@ defmodule ElixirScript.Translator.Spawn do + @moduledoc false + alias ESTree.Tools.Builder, as: JS alias ElixirScript.Translator alias ElixirScript.Translator.Function diff --git a/lib/elixir_script/translator/kernel/special_forms/receive.ex b/lib/elixir_script/translator/kernel/special_forms/receive.ex index 649a3a25..fc5aa941 100644 --- a/lib/elixir_script/translator/kernel/special_forms/receive.ex +++ b/lib/elixir_script/translator/kernel/special_forms/receive.ex @@ -1,5 +1,6 @@ - defmodule ElixirScript.Translator.Receive do + @moduledoc false + alias ESTree.Tools.Builder, as: JS alias ElixirScript.Translator alias ElixirScript.Translator.Spawn diff --git a/mix.exs b/mix.exs index 3c3be636..6b4714bf 100644 --- a/mix.exs +++ b/mix.exs @@ -4,7 +4,7 @@ defmodule ElixirScript.Mixfile do def project do [ app: :elixir_script, - version: "0.21.0-dev", + version: "0.21.0", elixir: "~> 1.0", escript: escript_config, deps: deps, From 4b54c4f14e191bc2b39f1ba2a20bb49ba4357e42 Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Sun, 10 Jul 2016 13:40:31 -0500 Subject: [PATCH 282/860] Added the ability to make anonymous js functions --- lib/elixir_script/translator/kernel/js.ex | 96 ++++++++++++++++++-- test/translator/kernel/js_test.exs | 101 ++++++++++++++++++++++ 2 files changed, 192 insertions(+), 5 deletions(-) create mode 100644 test/translator/kernel/js_test.exs diff --git a/lib/elixir_script/translator/kernel/js.ex b/lib/elixir_script/translator/kernel/js.ex index c5c36b0e..cd2427a5 100644 --- a/lib/elixir_script/translator/kernel/js.ex +++ b/lib/elixir_script/translator/kernel/js.ex @@ -3,6 +3,7 @@ defmodule ElixirScript.Translator.JS do alias ESTree.Tools.Builder alias ElixirScript.Translator + alias ElixirScript.Translator.Identifier alias ElixirScript.ModuleSystems @doc false @@ -10,23 +11,108 @@ defmodule ElixirScript.Translator.JS do { do_translate({name, [], params}, env), env } end - defp do_translate({:typeof, _, [param]}, env) do + defp do_translate({op, _, [param]}, env) when op in [:typeof, :delete, :void, :-, :+, :!, :"~"] do Builder.unary_expression( - :typeof, + op, true, Translator.translate!(param, env) ) end - - defp do_translate({:instanceof, _, [value, type]}, env) do + defp do_translate({op, _, [value, type]}, env) when op in [:"**", :==, :!=, :===, :!==, :<, :<=, :>, :>=, :"<<", :">>", :<<<, :+, :-, :*, :/, :%, :|, :^, :&, :in, :instanceof] do Builder.binary_expression( - :instanceof, + op, + Translator.translate!(value, env), + Translator.translate!(type, env) + ) + end + + defp do_translate({op, _, [value, type]}, env) when op in [:||, :&&] do + Builder.logical_expression( + op, Translator.translate!(value, env), Translator.translate!(type, env) ) end + defp do_translate({:function, _, [{name, _, params}, [do: body]]}, env) when is_list(params) do + make_function(name, params, body, env, []) + end + + defp do_translate({:function, _, params}, env) do + [do: body] = List.last(params) + params = Enum.reverse(params) |> tl |> Enum.reverse + + make_function(nil, params, body, env, []) + end + + defp do_translate({:generator, _, [{name, _, params}, [do: body]]}, env) when is_list(params) do + make_function(name, params, body, env, generator: true) + end + + defp do_translate({:generator, _, params}, env) do + [do: body] = List.last(params) + params = Enum.reverse(params) |> tl |> Enum.reverse + + make_function(nil, params, body, env, generator: true) + end + + defp do_translate({:async, _, [{name, _, params}, [do: body]]}, env) when is_list(params) do + make_function(name, params, body, env, async: true) + end + + defp do_translate({:async, _, params}, env) do + [do: body] = List.last(params) + params = Enum.reverse(params) |> tl |> Enum.reverse + + make_function(nil, params, body, env, async: true) + end + + defp make_function(nil, params, body, env, opts) do + env = ElixirScript.Translator.LexicalScope.function_scope(env, {nil, length(params)}) + {block, env} = ElixirScript.Translator.Function.prepare_function_body(body, env) + + Builder.function_expression( + Enum.map(params, &Translator.translate!(&1, env)), + [], + Builder.block_statement(block), + opts[:generator] || false, + false, + opts[:async] || false + ) + end + + defp make_function(name, params, body, env, opts) do + env = ElixirScript.Translator.LexicalScope.function_scope(env, {name, length(params)}) + {block, env} = ElixirScript.Translator.Function.prepare_function_body(body, env) + + Builder.function_declaration( + Identifier.make_identifier(name), + Enum.map(params, &Translator.translate!(&1, env)), + [], + Builder.block_statement(block), + opts[:generator] || false, + false, + opts[:async] || false + ) + end + + defp do_translate({:yield, _, []}, env) do + Builder.yield_expression() + end + + defp do_translate({:yield, _, [term]}, env) do + Builder.yield_expression( + Translator.translate!(term, env) + ) + end + + defp do_translate({:await, _, [term]}, env) do + Builder.await_expression( + Translator.translate!(term, env) + ) + end + defp do_translate({:throw, _, [term]}, env) do Builder.throw_statement( Translator.translate!(term, env) diff --git a/test/translator/kernel/js_test.exs b/test/translator/kernel/js_test.exs new file mode 100644 index 00000000..9365a443 --- /dev/null +++ b/test/translator/kernel/js_test.exs @@ -0,0 +1,101 @@ + +defmodule ElixirScript.Translator.JS.Test do + use ExUnit.Case + import ElixirScript.TestHelper + + test "JS.function" do + ex_ast = quote do + JS.function hello(name) do + "Hello #{name}" + end + end + + js_code = """ + function hello(name){ + return 'Hello ' + Elixir$ElixirScript$String$Chars.to_string(name); + } + """ + + assert_translation(ex_ast, js_code) + end + + test "JS.function without name" do + ex_ast = quote do + JS.function(name) do + "Hello #{name}" + end + end + + js_code = """ + function(name){ + return 'Hello ' + Elixir$ElixirScript$String$Chars.to_string(name); + } + """ + + assert_translation(ex_ast, js_code) + end + + test "JS.generator" do + ex_ast = quote do + JS.generator hello(name) do + JS.yield "Hello #{name}" + end + end + + js_code = """ + function* hello(name){ + return yield 'Hello ' + Elixir$ElixirScript$String$Chars.to_string(name); + } + """ + + assert_translation(ex_ast, js_code) + end + + test "JS.generator without name" do + ex_ast = quote do + JS.generator(name) do + JS.yield "Hello #{name}" + end + end + + js_code = """ + function* (name){ + return yield 'Hello ' + Elixir$ElixirScript$String$Chars.to_string(name); + } + """ + + assert_translation(ex_ast, js_code) + end + + test "JS.async" do + ex_ast = quote do + JS.async hello(name) do + JS.await "Hello #{name}" + end + end + + js_code = """ + async function hello(name){ + return await 'Hello ' + Elixir$ElixirScript$String$Chars.to_string(name); + } + """ + + assert_translation(ex_ast, js_code) + end + + test "JS.async without name" do + ex_ast = quote do + JS.async(name) do + JS.await "Hello #{name}" + end + end + + js_code = """ + async function(name){ + return await 'Hello ' + Elixir$ElixirScript$String$Chars.to_string(name); + } + """ + + assert_translation(ex_ast, js_code) + end +end From 94ec413ce782497efe545299367d9b39836ead44 Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Mon, 11 Jul 2016 20:51:13 -0500 Subject: [PATCH 283/860] Refactored js function type function heads --- lib/elixir_script/translator.ex | 8 +++-- lib/elixir_script/translator/kernel/js.ex | 34 ++++--------------- .../translator/module_collector.ex | 15 ++++---- 3 files changed, 21 insertions(+), 36 deletions(-) diff --git a/lib/elixir_script/translator.ex b/lib/elixir_script/translator.ex index 973508ad..00e9645b 100644 --- a/lib/elixir_script/translator.ex +++ b/lib/elixir_script/translator.ex @@ -53,6 +53,8 @@ defmodule ElixirScript.Translator do :on_definition, :on_load, :dialyzer, :vsn, :external_resource ] + @function_types [:def, :defp] + @doc """ Translates the given Elixir AST to JavaScript AST. The given `env` is a `ElixirScript.Macro.Env` used to track the variables, imports, aliases, and scopes like `Macro.Env`. The JavaScript AST and @@ -487,15 +489,15 @@ defmodule ElixirScript.Translator do Match.make_match(left, right, env) end - defp do_translate({function, _, [{:when, _, [{name, _, _params} | _guards] }, _] } = ast, env) when function in [:def, :defp] do + defp do_translate({function, _, [{:when, _, [{name, _, _params} | _guards] }, _] } = ast, env) when function in @function_types do Def.process_function(name, [ast], env) end - defp do_translate({function, _, [{name, _, params}, _]} = ast, env) when function in [:def, :defp] and is_atom(params) do + defp do_translate({function, _, [{name, _, params}, _]} = ast, env) when function in @function_types and is_atom(params) do Def.process_function(name, [ast], env) end - defp do_translate({function, _, [{name, _, _params}, _]} = ast, env) when function in [:def, :defp] do + defp do_translate({function, _, [{name, _, _params}, _]} = ast, env) when function in @function_types do Def.process_function(name, [ast], env) end diff --git a/lib/elixir_script/translator/kernel/js.ex b/lib/elixir_script/translator/kernel/js.ex index cd2427a5..f2ba836f 100644 --- a/lib/elixir_script/translator/kernel/js.ex +++ b/lib/elixir_script/translator/kernel/js.ex @@ -35,37 +35,17 @@ defmodule ElixirScript.Translator.JS do ) end - defp do_translate({:function, _, [{name, _, params}, [do: body]]}, env) when is_list(params) do - make_function(name, params, body, env, []) + defp do_translate({type, _, [{name, _, params}, [do: body]]}, env) when is_list(params) and type in [:generator, :function, :async] do + make_function(name, params, body, env, Keyword.new([{type, true}])) end - defp do_translate({:function, _, params}, env) do - [do: body] = List.last(params) - params = Enum.reverse(params) |> tl |> Enum.reverse - - make_function(nil, params, body, env, []) - end - - defp do_translate({:generator, _, [{name, _, params}, [do: body]]}, env) when is_list(params) do - make_function(name, params, body, env, generator: true) + defp do_translate({type, _, [[do: body]]}, env) when type in [:generator, :function, :async] do + make_function(nil, [], body, env, Keyword.new([{type, true}])) end - defp do_translate({:generator, _, params}, env) do - [do: body] = List.last(params) - params = Enum.reverse(params) |> tl |> Enum.reverse - - make_function(nil, params, body, env, generator: true) - end - - defp do_translate({:async, _, [{name, _, params}, [do: body]]}, env) when is_list(params) do - make_function(name, params, body, env, async: true) - end - - defp do_translate({:async, _, params}, env) do - [do: body] = List.last(params) - params = Enum.reverse(params) |> tl |> Enum.reverse - - make_function(nil, params, body, env, async: true) + defp do_translate({type, _, params}, env) when type in [:generator, :function, :async] do + [[do: body] | params] = Enum.reverse(params) + make_function(nil, Enum.reverse(params), body, env, Keyword.new([{type, true}])) end defp make_function(nil, params, body, env, opts) do diff --git a/lib/elixir_script/translator/module_collector.ex b/lib/elixir_script/translator/module_collector.ex index 903c7881..52d1bd4b 100644 --- a/lib/elixir_script/translator/module_collector.ex +++ b/lib/elixir_script/translator/module_collector.ex @@ -8,6 +8,9 @@ defmodule ElixirScript.Translator.ModuleCollector do alias ElixirScript.Translator.State alias ElixirScript.Translator.Utils + @function_types [:def, :defp] + + def process_modules(modules) do Enum.map(modules, fn { :__block__, _, list } -> @@ -189,30 +192,30 @@ defmodule ElixirScript.Translator.ModuleCollector do defp get_functions_from_module({:__block__, _, list}) do Enum.reduce(list, %{ def: Keyword.new, defp: Keyword.new }, fn - ({type, _, [{:when, _, [{name, _, params} | _guards] }, _] }, state) when type in [:def, :defp] and is_atom(params) -> + ({type, _, [{:when, _, [{name, _, params} | _guards] }, _] }, state) when type in @function_types and is_atom(params) -> arity = 0 add_function_to_map(state, type, name, arity) - ({type, _, [{:when, _, [{name, _, params} | _guards] }, _] }, state) when type in [:def, :defp] -> + ({type, _, [{:when, _, [{name, _, params} | _guards] }, _] }, state) when type in @function_types -> arity = if is_nil(params), do: 0, else: length(params) add_function_to_map(state, type, name, arity) - ({type, _, [{name, _, params}, _]}, state) when type in [:def, :defp] and is_atom(params) -> + ({type, _, [{name, _, params}, _]}, state) when type in @function_types and is_atom(params) -> arity = 0 add_function_to_map(state, type, name, arity) - ({type, _, [{name, _, params}, _]}, state) when type in [:def, :defp] -> + ({type, _, [{name, _, params}, _]}, state) when type in @function_types -> arity = if is_nil(params), do: 0, else: length(params) add_function_to_map(state, type, name, arity) - ({type, _, [{name, _, params}]}, state) when is_atom(params) and type in [:def, :defp] -> + ({type, _, [{name, _, params}]}, state) when is_atom(params) and type in @function_types -> arity = 0 add_function_to_map(state, type, name, arity) - ({type, _, [{name, _, params}]}, state) when type in [:def, :defp] -> + ({type, _, [{name, _, params}]}, state) when type in @function_types -> arity = length(params) add_function_to_map(state, type, name, arity) From 3d13f4b0c6ed457d5b362303c0b10c56728a0072 Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Fri, 15 Jul 2016 12:51:14 -0500 Subject: [PATCH 284/860] Refactored function function heads --- lib/elixir_script/translator/kernel/js.ex | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/lib/elixir_script/translator/kernel/js.ex b/lib/elixir_script/translator/kernel/js.ex index f2ba836f..9ae9f24b 100644 --- a/lib/elixir_script/translator/kernel/js.ex +++ b/lib/elixir_script/translator/kernel/js.ex @@ -6,6 +6,8 @@ defmodule ElixirScript.Translator.JS do alias ElixirScript.Translator.Identifier alias ElixirScript.ModuleSystems + @js_function_types [:generator, :function, :async] + @doc false def translate_js_function(name, params, env) do { do_translate({name, [], params}, env), env } @@ -35,15 +37,15 @@ defmodule ElixirScript.Translator.JS do ) end - defp do_translate({type, _, [{name, _, params}, [do: body]]}, env) when is_list(params) and type in [:generator, :function, :async] do + defp do_translate({type, _, [{name, _, params}, [do: body]]}, env) when is_list(params) and type in @js_function_types do make_function(name, params, body, env, Keyword.new([{type, true}])) end - defp do_translate({type, _, [[do: body]]}, env) when type in [:generator, :function, :async] do + defp do_translate({type, _, [[do: body]]}, env) when type in @js_function_types do make_function(nil, [], body, env, Keyword.new([{type, true}])) end - defp do_translate({type, _, params}, env) when type in [:generator, :function, :async] do + defp do_translate({type, _, params}, env) when type in @js_function_types do [[do: body] | params] = Enum.reverse(params) make_function(nil, Enum.reverse(params), body, env, Keyword.new([{type, true}])) end @@ -83,7 +85,8 @@ defmodule ElixirScript.Translator.JS do defp do_translate({:yield, _, [term]}, env) do Builder.yield_expression( - Translator.translate!(term, env) + Translator.translate!(term, env), + true ) end From 10af93f35b9bb1ef3769244cf6f3de2f48a4ca99 Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Fri, 15 Jul 2016 12:53:38 -0500 Subject: [PATCH 285/860] Removed js function implementations. Added yield_all --- lib/elixir_script/translator/kernel/js.ex | 54 ++---------- test/translator/kernel/js_test.exs | 101 ---------------------- 2 files changed, 5 insertions(+), 150 deletions(-) delete mode 100644 test/translator/kernel/js_test.exs diff --git a/lib/elixir_script/translator/kernel/js.ex b/lib/elixir_script/translator/kernel/js.ex index 9ae9f24b..bf50655b 100644 --- a/lib/elixir_script/translator/kernel/js.ex +++ b/lib/elixir_script/translator/kernel/js.ex @@ -6,8 +6,6 @@ defmodule ElixirScript.Translator.JS do alias ElixirScript.Translator.Identifier alias ElixirScript.ModuleSystems - @js_function_types [:generator, :function, :async] - @doc false def translate_js_function(name, params, env) do { do_translate({name, [], params}, env), env } @@ -37,62 +35,20 @@ defmodule ElixirScript.Translator.JS do ) end - defp do_translate({type, _, [{name, _, params}, [do: body]]}, env) when is_list(params) and type in @js_function_types do - make_function(name, params, body, env, Keyword.new([{type, true}])) - end - - defp do_translate({type, _, [[do: body]]}, env) when type in @js_function_types do - make_function(nil, [], body, env, Keyword.new([{type, true}])) - end - - defp do_translate({type, _, params}, env) when type in @js_function_types do - [[do: body] | params] = Enum.reverse(params) - make_function(nil, Enum.reverse(params), body, env, Keyword.new([{type, true}])) - end - - defp make_function(nil, params, body, env, opts) do - env = ElixirScript.Translator.LexicalScope.function_scope(env, {nil, length(params)}) - {block, env} = ElixirScript.Translator.Function.prepare_function_body(body, env) - - Builder.function_expression( - Enum.map(params, &Translator.translate!(&1, env)), - [], - Builder.block_statement(block), - opts[:generator] || false, - false, - opts[:async] || false - ) - end - - defp make_function(name, params, body, env, opts) do - env = ElixirScript.Translator.LexicalScope.function_scope(env, {name, length(params)}) - {block, env} = ElixirScript.Translator.Function.prepare_function_body(body, env) - - Builder.function_declaration( - Identifier.make_identifier(name), - Enum.map(params, &Translator.translate!(&1, env)), - [], - Builder.block_statement(block), - opts[:generator] || false, - false, - opts[:async] || false - ) - end - defp do_translate({:yield, _, []}, env) do Builder.yield_expression() end defp do_translate({:yield, _, [term]}, env) do Builder.yield_expression( - Translator.translate!(term, env), - true + Translator.translate!(term, env) ) end - defp do_translate({:await, _, [term]}, env) do - Builder.await_expression( - Translator.translate!(term, env) + defp do_translate({:yield_all, _, [term]}, env) do + Builder.yield_expression( + Translator.translate!(term, env), + true ) end diff --git a/test/translator/kernel/js_test.exs b/test/translator/kernel/js_test.exs deleted file mode 100644 index 9365a443..00000000 --- a/test/translator/kernel/js_test.exs +++ /dev/null @@ -1,101 +0,0 @@ - -defmodule ElixirScript.Translator.JS.Test do - use ExUnit.Case - import ElixirScript.TestHelper - - test "JS.function" do - ex_ast = quote do - JS.function hello(name) do - "Hello #{name}" - end - end - - js_code = """ - function hello(name){ - return 'Hello ' + Elixir$ElixirScript$String$Chars.to_string(name); - } - """ - - assert_translation(ex_ast, js_code) - end - - test "JS.function without name" do - ex_ast = quote do - JS.function(name) do - "Hello #{name}" - end - end - - js_code = """ - function(name){ - return 'Hello ' + Elixir$ElixirScript$String$Chars.to_string(name); - } - """ - - assert_translation(ex_ast, js_code) - end - - test "JS.generator" do - ex_ast = quote do - JS.generator hello(name) do - JS.yield "Hello #{name}" - end - end - - js_code = """ - function* hello(name){ - return yield 'Hello ' + Elixir$ElixirScript$String$Chars.to_string(name); - } - """ - - assert_translation(ex_ast, js_code) - end - - test "JS.generator without name" do - ex_ast = quote do - JS.generator(name) do - JS.yield "Hello #{name}" - end - end - - js_code = """ - function* (name){ - return yield 'Hello ' + Elixir$ElixirScript$String$Chars.to_string(name); - } - """ - - assert_translation(ex_ast, js_code) - end - - test "JS.async" do - ex_ast = quote do - JS.async hello(name) do - JS.await "Hello #{name}" - end - end - - js_code = """ - async function hello(name){ - return await 'Hello ' + Elixir$ElixirScript$String$Chars.to_string(name); - } - """ - - assert_translation(ex_ast, js_code) - end - - test "JS.async without name" do - ex_ast = quote do - JS.async(name) do - JS.await "Hello #{name}" - end - end - - js_code = """ - async function(name){ - return await 'Hello ' + Elixir$ElixirScript$String$Chars.to_string(name); - } - """ - - assert_translation(ex_ast, js_code) - end -end From c0eac32470b5b0d0cf41b93f72161b046e4aee23 Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Fri, 15 Jul 2016 17:32:51 -0500 Subject: [PATCH 286/860] Add generator context to Macro.Env --- lib/elixir_script/prelude/macro/env.ex | 2 +- .../kernel/special_forms/capture.ex | 12 ++++++---- .../translator/kernel/special_forms/fn.ex | 24 +++++++++++++------ 3 files changed, 25 insertions(+), 13 deletions(-) diff --git a/lib/elixir_script/prelude/macro/env.ex b/lib/elixir_script/prelude/macro/env.ex index 9e2615e6..896f3e75 100644 --- a/lib/elixir_script/prelude/macro/env.ex +++ b/lib/elixir_script/prelude/macro/env.ex @@ -4,7 +4,7 @@ defmodule ElixirScript.Macro.Env do file: binary, line: non_neg_integer, function: { atom, non_neg_integer } | nil, - context: :match | :guard | nil, + context: :match | :guard | :generator | nil, aliases: [{atom, atom}], requires: [atom], functions: [{atom, [{ atom, non_neg_integer }]}], diff --git a/lib/elixir_script/translator/kernel/special_forms/capture.ex b/lib/elixir_script/translator/kernel/special_forms/capture.ex index 9d53fd20..57ba474b 100644 --- a/lib/elixir_script/translator/kernel/special_forms/capture.ex +++ b/lib/elixir_script/translator/kernel/special_forms/capture.ex @@ -19,7 +19,7 @@ defmodule ElixirScript.Translator.Capture do ) ]) - make_capture_function(patterns, params, body) + make_capture_function(patterns, params, body, env) end def make_capture(module_name, function_name, arity, env) do @@ -43,7 +43,7 @@ defmodule ElixirScript.Translator.Capture do ) ]) - make_capture_function(patterns, params, body) + make_capture_function(patterns, params, body, env) end defp process_params(arity, env) do @@ -51,10 +51,12 @@ defmodule ElixirScript.Translator.Capture do PatternMatching.process_match(params, env) end - defp make_capture_function(patterns, params, body) do + defp make_capture_function(patterns, params, body, env) do + is_generator? = env.context == :generator Function.make_defmatch([ - Function.make_function_clause(patterns, params, body, nil) - ]) + Function.make_function_clause(patterns, params, body, nil, is_generator?) + ], + is_generator?) end def find_value_placeholders(ast) do diff --git a/lib/elixir_script/translator/kernel/special_forms/fn.ex b/lib/elixir_script/translator/kernel/special_forms/fn.ex index 215e1324..58531994 100644 --- a/lib/elixir_script/translator/kernel/special_forms/fn.ex +++ b/lib/elixir_script/translator/kernel/special_forms/fn.ex @@ -35,7 +35,7 @@ defmodule ElixirScript.Translator.Function do process_function_body(params, [], env, name) end) - { make_defmatch(clauses), env } + { make_defmatch(clauses, env.context == :generator), env } end def convert_to_try([do: body]) do @@ -46,7 +46,17 @@ defmodule ElixirScript.Translator.Function do { :__block__, [], [{ :try, [], [function_kw_list] }] } end - def make_defmatch(clauses) do + def make_defmatch(clauses, true) do + JS.call_expression( + JS.member_expression( + @patterns, + JS.identifier("defmatchgen") + ), + clauses + ) + end + + def make_defmatch(clauses, _) do JS.call_expression( JS.member_expression( @patterns, @@ -67,9 +77,9 @@ defmodule ElixirScript.Translator.Function do |> prepare_function_body(%{ env | context: :guard}) guard_body = JS.block_statement(guard_body) - make_function_clause(patterns, params, body, guard_body) + make_function_clause(patterns, params, body, guard_body, env.context == :generator) else - make_function_clause(patterns, params, body, nil) + make_function_clause(patterns, params, body, nil, env.context == :generator) end end @@ -101,17 +111,17 @@ defmodule ElixirScript.Translator.Function do { patterns, make_params(params), env } end - def make_function_clause(patterns, params, body, guard_body) do + def make_function_clause(patterns, params, body, guard_body, is_generator?) do arguments = case guard_body do nil -> [ JS.array_expression(patterns), - JS.function_expression(params, [], body) + JS.function_expression(params, [], body, is_generator?) ] _ -> [ JS.array_expression(patterns), - JS.function_expression(params, [], body), + JS.function_expression(params, [], body, is_generator?), JS.function_expression(params, [], guard_body) ] end From 5ac6fc87e6e917130736ab5f34b8ad17fddfa7df Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Sun, 17 Jul 2016 08:51:30 -0500 Subject: [PATCH 287/860] Add defgen and defgenp. Add yield and yield_all --- lib/elixir_script/translator.ex | 54 +++++++++++-- .../translator/kernel/defmodule.ex | 39 +++++++++- lib/elixir_script/translator/kernel/spawn.ex | 10 +-- .../translator/kernel/special_forms/block.ex | 75 +------------------ .../translator/kernel/special_forms/fn.ex | 1 - .../kernel/special_forms/receive.ex | 50 +------------ lib/elixir_script/translator/lexical_scope.ex | 4 +- .../translator/module_collector.ex | 8 +- test/translator/defmodule_test.exs | 6 +- 9 files changed, 99 insertions(+), 148 deletions(-) diff --git a/lib/elixir_script/translator.ex b/lib/elixir_script/translator.ex index 00e9645b..d27f16b3 100644 --- a/lib/elixir_script/translator.ex +++ b/lib/elixir_script/translator.ex @@ -53,7 +53,9 @@ defmodule ElixirScript.Translator do :on_definition, :on_load, :dialyzer, :vsn, :external_resource ] - @function_types [:def, :defp] + @function_types [:def, :defp, :defgen, :defgenp] + @generator_types [:defgen, :defgenp] + @doc """ Translates the given Elixir AST to JavaScript AST. The given `env` is a `ElixirScript.Macro.Env` @@ -107,6 +109,30 @@ defmodule ElixirScript.Translator do Expression.make_unary_expression(operator, value, env) end + defp do_translate({:yield, _, []}, env) do + quoted = quote do + JS.yield + end + + translate(quoted, env) + end + + defp do_translate({:yield, _, [term]}, env) do + quoted = quote do + JS.yield unquote(term) + end + + translate(quoted, env) + end + + defp do_translate({:yield_all, _, [term]}, env) do + quoted = quote do + JS.yield_all unquote(term) + end + + translate(quoted, env) + end + defp do_translate({:not, _, [value]}, env) do Expression.make_unary_expression(:!, value, env) end @@ -430,8 +456,12 @@ defmodule ElixirScript.Translator do Function.make_anonymous_function(clauses, env) end + defp do_translate({:gn, _, clauses}, env) do + Function.make_anonymous_function(clauses, %{ env | context: :generator}) + end + defp do_translate({:spawn, _, [{:fn, _, _} = func]}, env) do - Spawn.make_spawn(func, env) + Spawn.make_spawn(func, %{ env | context: :generator}) end defp do_translate({:spawn, _, [module, function, params]}, env) do @@ -439,7 +469,7 @@ defmodule ElixirScript.Translator do end defp do_translate({:spawn_link, _, [{:fn, _, _} = func]}, env) do - Spawn.make_spawn_link(func, env) + Spawn.make_spawn_link(func, %{ env | context: :generator}) end defp do_translate({:spawn_link, _, [module, function, params]}, env) do @@ -447,7 +477,7 @@ defmodule ElixirScript.Translator do end defp do_translate({:spawn_monitor, _, [{:fn, _, _} = func]}, env) do - Spawn.make_spawn_monitor(func, env) + Spawn.make_spawn_monitor(func, %{ env | context: :generator}) end defp do_translate({:spawn_monitor, _, [module, function, params]}, env) do @@ -469,10 +499,6 @@ defmodule ElixirScript.Translator do {js, env} end - defp do_translate({:receive, _, _ }, %LexicalScope{ in_process: false}) do - raise ElixirScript.Translator.UnsupportedError, "receive outside of a process" - end - defp do_translate({:receive, _, [expressions] }, env) do Receive.make_receive(expressions, env) end @@ -489,6 +515,18 @@ defmodule ElixirScript.Translator do Match.make_match(left, right, env) end + defp do_translate({function, _, [{:when, _, [{name, _, _params} | _guards] }, _] } = ast, env) when function in @generator_types do + Def.process_function(name, [ast], %{ env | context: :generator}) + end + + defp do_translate({function, _, [{name, _, params}, _]} = ast, env) when function in @generator_types and is_atom(params) do + Def.process_function(name, [ast], %{ env | context: :generator}) + end + + defp do_translate({function, _, [{name, _, _params}, _]} = ast, env) when function in @generator_types do + Def.process_function(name, [ast], %{ env | context: :generator}) + end + defp do_translate({function, _, [{:when, _, [{name, _, _params} | _guards] }, _] } = ast, env) when function in @function_types do Def.process_function(name, [ast], env) end diff --git a/lib/elixir_script/translator/kernel/defmodule.ex b/lib/elixir_script/translator/kernel/defmodule.ex index 3aa48e0d..d1004618 100644 --- a/lib/elixir_script/translator/kernel/defmodule.ex +++ b/lib/elixir_script/translator/kernel/defmodule.ex @@ -79,7 +79,7 @@ defmodule ElixirScript.Translator.Defmodule do def extract_functions_from_module({:__block__, meta, body_list}) do { body_list, functions } = Enum.map_reduce(body_list, - %{exported: HashDict.new(), private: HashDict.new()}, fn + %{exported: HashDict.new(), private: HashDict.new(), exported_generators: HashDict.new(), private_generators: HashDict.new()}, fn ({:def, _, [{:when, _, [{name, _, _} | _guards] }, _] } = function, state) -> { nil, @@ -100,6 +100,26 @@ defmodule ElixirScript.Translator.Defmodule do nil, %{ state | private: HashDict.put(state.private, name, HashDict.get(state.private, name, []) ++ [function]) } } + ({:defgen, _, [{:when, _, [{name, _, _} | _guards] }, _] } = function, state) -> + { + nil, + %{ state | exported_generators: HashDict.put(state.exported_generators, name, HashDict.get(state.exported_generators, name, []) ++ [function]) } + } + ({:defgen, _, [{name, _, _}, _]} = function, state) -> + { + nil, + %{ state | exported_generators: HashDict.put(state.exported_generators, name, HashDict.get(state.exported_generators, name, []) ++ [function]) } + } + ({:defgenp, _, [{:when, _, [{name, _, _} | _guards] }, _] } = function, state) -> + { + nil, + %{ state | private_generators: HashDict.put(state.private_generators, name, HashDict.get(state.private_generators, name, []) ++ [function]) } + } + ({:defgenp, _, [{name, _, _}, _]} = function, state) -> + { + nil, + %{ state | private_generators: HashDict.put(state.private_generators, name, HashDict.get(state.private_generators, name, []) ++ [function]) } + } (x, state) -> { x, state } end) @@ -161,7 +181,7 @@ defmodule ElixirScript.Translator.Defmodule do end end - def process_functions(%{ exported: exported, private: private }, env) do + def process_functions(%{ exported: exported, private: private, exported_generators: exported_generators, private_generators: private_generators }, env) do exported_functions = Enum.map(Dict.keys(exported), fn(key) -> functions = Dict.get(exported, key) @@ -169,13 +189,26 @@ defmodule ElixirScript.Translator.Defmodule do { key, functions } end) + exported_generators = Enum.map(Dict.keys(exported_generators), fn(key) -> + functions = Dict.get(exported_generators, key) + + { functions, _ } = Def.process_function(key, functions, %{ env | context: :generator}) + { key, functions } + end) + private_functions = Enum.map(Dict.keys(private), fn(key) -> functions = Dict.get(private, key) { functions, _ } = Def.process_function(key, functions, env) { key, functions } end) - { exported_functions, private_functions } + private_generators = Enum.map(Dict.keys(private_generators), fn(key) -> + functions = Dict.get(private_generators, key) + { functions, _ } = Def.process_function(key, functions, %{ env | context: :generator}) + { key, functions } + end) + + { exported_functions ++ exported_generators, private_functions ++ private_generators } end def make_attribute(name, value, env) do diff --git a/lib/elixir_script/translator/kernel/spawn.ex b/lib/elixir_script/translator/kernel/spawn.ex index b2da02ce..ca0657bc 100644 --- a/lib/elixir_script/translator/kernel/spawn.ex +++ b/lib/elixir_script/translator/kernel/spawn.ex @@ -7,19 +7,19 @@ defmodule ElixirScript.Translator.Spawn do alias ElixirScript.Translator.Call def make_spawn(func, env) do - do_spawn_with_fn(func, env, "spawn") + do_spawn_with_gn(func, env, "spawn") end def make_spawn_link(func, env) do - do_spawn_with_fn(func, env, "spawn_link") + do_spawn_with_gn(func, env, "spawn_link") end def make_spawn_monitor(func, env) do - do_spawn_with_fn(func, env, "spawn_monitor") + do_spawn_with_gn(func, env, "spawn_monitor") end - defp do_spawn_with_fn({:fn, _, [{:->, _, [[], body]}]}, env, spawn_func_name) do - { body, _ } = Function.prepare_function_body(body, %{ env | in_process: true }) + defp do_spawn_with_gn({:fn, _, [{:->, _, [[], body]}]}, env, spawn_func_name) do + { body, _ } = Function.prepare_function_body(body, env) js = call_processes_func(spawn_func_name, [JS.function_expression([], [], JS.block_statement(body), true)]) { js, env } end diff --git a/lib/elixir_script/translator/kernel/special_forms/block.ex b/lib/elixir_script/translator/kernel/special_forms/block.ex index 60f4f359..52689574 100644 --- a/lib/elixir_script/translator/kernel/special_forms/block.ex +++ b/lib/elixir_script/translator/kernel/special_forms/block.ex @@ -5,83 +5,10 @@ defmodule ElixirScript.Translator.Block do def make_block(expressions, env) do { list, env } = Enum.map_reduce(expressions, env, fn(x, updated_env) -> - {item, updated_env } = Translator.translate(x, updated_env) - {process_call(item, env), updated_env} + Translator.translate(x, updated_env) end) { JS.block_statement(list), env } end - def process_call(item, %ElixirScript.Translator.LexicalScope{ in_process: true }) do - case item do - %ESTree.CallExpression{ callee: %ESTree.MemberExpression{ object: %ESTree.Identifier{ name: "Object" }, property: %ESTree.Identifier{ name: "freeze" }} } -> - item - %ESTree.CallExpression{ callee: %ESTree.MemberExpression{ object: %ESTree.Identifier{ name: "Symbol" }, property: %ESTree.Identifier{ name: "for" }} } -> - item - %ESTree.CallExpression{ callee: %ESTree.MemberExpression{ object: object, property: %ESTree.Identifier{ name: name } }, arguments: arguments } -> - make_gen_call(object, name, arguments) - %ESTree.CallExpression{ callee: %ESTree.Identifier{ name: name }, arguments: arguments } -> - make_gen_call(name, arguments) - _ -> - item - end - end - - def process_call(item, _) do - item - end - - defp make_gen_call(callee, func, params) do - context = callee - - - JS.yield_expression( - JS.call_expression( - JS.member_expression( - JS.member_expression( - JS.identifier("Elixir"), - JS.member_expression( - JS.identifier("Core"), - JS.identifier("Functions") - ) - ), - JS.identifier("run") - ), - [ - JS.member_expression( - callee, - JS.literal(func), - true - ), - JS.array_expression(params), - context - ] - ), - true - ) - end - - - defp make_gen_call(func, params) do - JS.yield_expression( - JS.call_expression( - JS.member_expression( - JS.member_expression( - JS.identifier("Elixir"), - JS.member_expression( - JS.identifier("Core"), - JS.identifier("Functions") - ) - ), - JS.identifier("run") - ), - [ - JS.identifier(func), - JS.array_expression(params) - ] - ), - true - ) - end - end diff --git a/lib/elixir_script/translator/kernel/special_forms/fn.ex b/lib/elixir_script/translator/kernel/special_forms/fn.ex index 58531994..1061ffce 100644 --- a/lib/elixir_script/translator/kernel/special_forms/fn.ex +++ b/lib/elixir_script/translator/kernel/special_forms/fn.ex @@ -155,7 +155,6 @@ defmodule ElixirScript.Translator.Function do end list = Group.inflate_groups(list) - |> Enum.map(fn(x) -> Block.process_call(x, env) end) |> return_last_expression { list, env } diff --git a/lib/elixir_script/translator/kernel/special_forms/receive.ex b/lib/elixir_script/translator/kernel/special_forms/receive.ex index fc5aa941..4b461177 100644 --- a/lib/elixir_script/translator/kernel/special_forms/receive.ex +++ b/lib/elixir_script/translator/kernel/special_forms/receive.ex @@ -7,29 +7,8 @@ defmodule ElixirScript.Translator.Receive do alias ElixirScript.Translator.Primitive alias ElixirScript.Translator.LexicalScope - - def make_receive([do: clauses], %LexicalScope{ in_process: true} = env) do - {made_case, _} = ElixirScript.Translator.Case.make_case({:__aliases__, [], [:message]}, clauses, %{ env | in_process: false}) - - js = JS.yield_expression( - Spawn.call_processes_func("receive", [ - JS.function_expression( - [JS.identifier(:message)], - [], - JS.block_statement([ - JS.return_statement( - made_case - ) - ]) - ) - ]) - ) - - {js, env} - end - def make_receive([do: clauses], env) do - {made_case, _} = ElixirScript.Translator.Case.make_case({:__aliases__, [], [:message]}, clauses, %{ env | in_process: false}) + {made_case, _} = ElixirScript.Translator.Case.make_case({:__aliases__, [], [:message]}, clauses, env) js = Spawn.call_processes_func("receive", [ JS.function_expression( @@ -46,32 +25,9 @@ defmodule ElixirScript.Translator.Receive do {js, env} end - def make_receive([do: clauses, after: [{:->, _, [[time], _body]}] = after_clause], %LexicalScope{ in_process: true } = env) do - {made_case, _} = ElixirScript.Translator.Case.make_case({:__aliases__, [], [:message]}, clauses, %{ env | in_process: false}) - {anon_func, _} = ElixirScript.Translator.Function.make_anonymous_function(after_clause, %{ env | in_process: false}) - - js = JS.yield_expression( - Spawn.call_processes_func("receive", [ - JS.function_expression( - [JS.identifier(:message)], - [], - JS.block_statement([ - JS.return_statement( - made_case - ) - ]) - ), - Translator.translate!(time, env), - anon_func - ]) - ) - - {js, env} - end - def make_receive([do: clauses, after: [{:->, _, [[time], _body]}] = after_clause], env) do - {made_case, _} = ElixirScript.Translator.Case.make_case({:__aliases__, [], [:message]}, clauses, %{ env | in_process: false}) - {anon_func, _} = ElixirScript.Translator.Function.make_anonymous_function(after_clause, %{ env | in_process: false}) + {made_case, _} = ElixirScript.Translator.Case.make_case({:__aliases__, [], [:message]}, clauses, env) + {anon_func, _} = ElixirScript.Translator.Function.make_anonymous_function(after_clause, env) js = Spawn.call_processes_func("receive", [ diff --git a/lib/elixir_script/translator/lexical_scope.ex b/lib/elixir_script/translator/lexical_scope.ex index d5fbee58..b90c1971 100644 --- a/lib/elixir_script/translator/lexical_scope.ex +++ b/lib/elixir_script/translator/lexical_scope.ex @@ -6,7 +6,7 @@ defmodule ElixirScript.Translator.LexicalScope do file: binary, line: non_neg_integer, function: { atom, non_neg_integer } | nil, - context: :match | :guard | nil, + context: :match | :guard | :generator | nil, aliases: [{atom, atom}], requires: [atom], functions: [{atom, [{ atom, non_neg_integer }]}], @@ -17,7 +17,6 @@ defmodule ElixirScript.Translator.LexicalScope do export_vars: [{atom, atom | non_neg_integer}] | nil, lexical_tracker: nil, caller: t | nil, - in_process: boolean, env: nil } @@ -37,7 +36,6 @@ defmodule ElixirScript.Translator.LexicalScope do export_vars: nil, lexical_tracker: nil, caller: nil, - in_process: false, env: nil ] diff --git a/lib/elixir_script/translator/module_collector.ex b/lib/elixir_script/translator/module_collector.ex index 52d1bd4b..46ea3219 100644 --- a/lib/elixir_script/translator/module_collector.ex +++ b/lib/elixir_script/translator/module_collector.ex @@ -8,7 +8,7 @@ defmodule ElixirScript.Translator.ModuleCollector do alias ElixirScript.Translator.State alias ElixirScript.Translator.Utils - @function_types [:def, :defp] + @function_types [:def, :defp, :defgen, :defgenp] def process_modules(modules) do @@ -141,11 +141,11 @@ defmodule ElixirScript.Translator.ModuleCollector do body end - %{def: functions, defp: private_functions } = get_functions_from_module(body) + %{def: functions, defp: private_functions, defgen: generators, defgenp: private_generators } = get_functions_from_module(body) js_imports = get_js_imports_from_module(body) %ElixirScript.Module{ name: Utils.quoted_to_name({:__aliases__, [], name}) , body: body, - functions: functions, private_functions: private_functions, js_imports: js_imports } + functions: functions ++ generators, private_functions: private_functions ++ private_generators, js_imports: js_imports } end def handle_use_expression(using_ast, module) do @@ -191,7 +191,7 @@ defmodule ElixirScript.Translator.ModuleCollector do end defp get_functions_from_module({:__block__, _, list}) do - Enum.reduce(list, %{ def: Keyword.new, defp: Keyword.new }, fn + Enum.reduce(list, %{ def: Keyword.new, defp: Keyword.new, defgen: Keyword.new, defgenp: Keyword.new }, fn ({type, _, [{:when, _, [{name, _, params} | _guards] }, _] }, state) when type in @function_types and is_atom(params) -> arity = 0 diff --git a/test/translator/defmodule_test.exs b/test/translator/defmodule_test.exs index 8e901690..165946dd 100644 --- a/test/translator/defmodule_test.exs +++ b/test/translator/defmodule_test.exs @@ -25,7 +25,7 @@ defmodule ElixirScript.Translator.Defmodule.Test do @ul end - defp something_else() do + defgenp something_else() do end end end @@ -33,7 +33,7 @@ defmodule ElixirScript.Translator.Defmodule.Test do js_code = """ import Elixir$ElixirScript$Kernel from './Elixir.ElixirScript.Kernel'; - const something_else = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.clause([],function() { + const something_else = Elixir.Core.Patterns.defmatchgen(Elixir.Core.Patterns.clause([],function*() { return null; })); const something = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.clause([],function() { @@ -306,7 +306,7 @@ defmodule ElixirScript.Translator.Defmodule.Test do end defmodule Parser.DSL do - + end end end From 6e333f470bb5230aaf81b31dd9a9750ed5a3839c Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Thu, 28 Jul 2016 21:24:25 -0500 Subject: [PATCH 288/860] Some refactoring of process functions and javascript functions --- lib/elixir_script/prelude/kernel.ex | 71 ++++++++++++-- lib/elixir_script/translator.ex | 51 +--------- lib/elixir_script/translator/kernel/js.ex | 2 +- lib/elixir_script/translator/kernel/spawn.ex | 93 ------------------- .../translator/kernel/special_forms/call.ex | 5 + .../kernel/special_forms/receive.ex | 21 ++++- mix.exs | 2 +- src/javascript/lib/core/functions.js | 7 +- test/translator/kernel/receive_test.exs | 15 +-- test/translator/kernel/send_test.exs | 22 +---- test/translator/kernel/spawn_test.exs | 36 +------ 11 files changed, 106 insertions(+), 219 deletions(-) delete mode 100644 lib/elixir_script/translator/kernel/spawn.ex diff --git a/lib/elixir_script/prelude/kernel.ex b/lib/elixir_script/prelude/kernel.ex index 92026de9..bcc903c6 100644 --- a/lib/elixir_script/prelude/kernel.ex +++ b/lib/elixir_script/prelude/kernel.ex @@ -35,6 +35,18 @@ defmodule ElixirScript.Kernel do end end + defmacro typeof(term) do + quote do + JS.typeof(unquote(term)) + end + end + + defmacro instanceof(term, type) do + quote do + JS.instanceof(unquote(term), unquote(type)) + end + end + def abs(number) do Math.abs(number) end @@ -61,19 +73,19 @@ defmodule ElixirScript.Kernel do end def is_atom(term) do - JS.typeof(term) === "symbol" + typeof(term) === "symbol" end def is_binary(term) do - JS.typeof(term) === "string" + typeof(term) === "string" end def is_bitstring(term) do - is_binary(term) || JS.instanceof(term, Elixir.Core.BitString) + is_binary(term) || instanceof(term, Elixir.Core.BitString) end def is_boolean(term) do - JS.typeof(term) === "boolean" || JS.instanceof(term, Boolean) + JS.typeof(term) === "boolean" || instanceof(term, Boolean) end def is_float(term) do @@ -85,7 +97,7 @@ defmodule ElixirScript.Kernel do end def is_function(term, _) do - JS.typeof(term) === "function" || JS.instanceof(term, Function) + typeof(term) === "function" || instanceof(term, Function) end def is_integer(term) do @@ -97,7 +109,7 @@ defmodule ElixirScript.Kernel do end def is_number(term) do - JS.typeof(term) === "number" || JS.instanceof(term, Number) + typeof(term) === "number" || instanceof(term, Number) end def is_pid(term) do @@ -109,7 +121,11 @@ defmodule ElixirScript.Kernel do end def is_map(term) do - JS.typeof(term) === "object" || JS.instanceof(term, Object) + typeof(term) === "object" || instanceof(term, Object) + end + + def is_generator(term) do + term.constructor.name === "GeneratorFunction" end def is_port(_) do @@ -160,6 +176,29 @@ defmodule ElixirScript.Kernel do Elixir.Core.processes.make_ref() end + def spawn(module, fun, args) do + fun = if Elixir.Core.is_atom(fun), do: Atom.to_string(fun), else: fun + Elixir.Core.processes.spawn(module, fun, args) + end + + def spawn_link(module, fun, args) do + fun = if Elixir.Core.is_atom(fun), do: Atom.to_string(fun), else: fun + Elixir.Core.processes.spawn_link(module, fun, args) + end + + def spawn_monitor(module, fun, args) do + fun = if Elixir.Core.is_atom(fun), do: Atom.to_string(fun), else: fun + Elixir.Core.processes.spawn_monitor(module, fun, args) + end + + def send(pid, message) do + Elixir.Core.processes.send(pid, message) + end + + def self() do + Elixir.Core.processes.pid() + end + defmacro match?(left, right) do quote do case unquote(right) do @@ -197,6 +236,24 @@ defmodule ElixirScript.Kernel do end end + defmacro yield() do + quote do + JS.yield() + end + end + + defmacro yield(term) do + quote do + JS.yield(unquote(term)) + end + end + + defmacro yield_to(term) do + quote do + JS.yield_to(unquote(term)) + end + end + @doc """ Provides a convenient way to create a string-based map. diff --git a/lib/elixir_script/translator.ex b/lib/elixir_script/translator.ex index d27f16b3..2fe7ef18 100644 --- a/lib/elixir_script/translator.ex +++ b/lib/elixir_script/translator.ex @@ -27,7 +27,6 @@ defmodule ElixirScript.Translator do alias ElixirScript.Translator.JS, as: JSLib alias ESTree.Tools.Builder, as: JS alias ElixirScript.Translator.Rewriter - alias ElixirScript.Translator.Spawn alias ElixirScript.Translator.Receive alias ElixirScript.Translator.LexicalScope @@ -137,7 +136,7 @@ defmodule ElixirScript.Translator do Expression.make_unary_expression(:!, value, env) end - defp do_translate({operator, _, [left, right]}, env) when operator in [:+, :-, :/, :*, :==, :!=, :&&, :||, :>, :<, :>=, :<=, :===, :!==] do + defp do_translate({operator, _, [left, right]}, env) when operator in [:+, :-, :/, :*, :==, :!=, :&&, :||, :>, :<, :>=, :<=, :===, :!==, :"**"] do Expression.make_binary_expression(operator, left, right, env) end @@ -301,8 +300,9 @@ defmodule ElixirScript.Translator do { Identifier.make_identifier(:undefined), env } end - defp do_translate({:__aliases__, _, aliases}, env) do - { Identifier.make_identifier({:__aliases__, [], aliases}), env } + defp do_translate({:__aliases__, _, aliases} = ast, env) do + module_name = create_module_name(ast, env) + Call.make_module_name(module_name, env) end defp do_translate({:__MODULE__, _, _ }, env) do @@ -456,49 +456,6 @@ defmodule ElixirScript.Translator do Function.make_anonymous_function(clauses, env) end - defp do_translate({:gn, _, clauses}, env) do - Function.make_anonymous_function(clauses, %{ env | context: :generator}) - end - - defp do_translate({:spawn, _, [{:fn, _, _} = func]}, env) do - Spawn.make_spawn(func, %{ env | context: :generator}) - end - - defp do_translate({:spawn, _, [module, function, params]}, env) do - Spawn.make_spawn(module, function, params, env) - end - - defp do_translate({:spawn_link, _, [{:fn, _, _} = func]}, env) do - Spawn.make_spawn_link(func, %{ env | context: :generator}) - end - - defp do_translate({:spawn_link, _, [module, function, params]}, env) do - Spawn.make_spawn_link(module, function, params, env) - end - - defp do_translate({:spawn_monitor, _, [{:fn, _, _} = func]}, env) do - Spawn.make_spawn_monitor(func, %{ env | context: :generator}) - end - - defp do_translate({:spawn_monitor, _, [module, function, params]}, env) do - Spawn.make_spawn_monitor(module, function, params, env) - end - - defp do_translate({:send, _, [id, msg]}, env) do - js = Spawn.call_processes_func("send", [translate!(id, env), translate!(msg, env)]) - {js, env} - end - - defp do_translate({:send, _, [id, msg, _]}, env) do - js = Spawn.call_processes_func("send", [translate!(id, env), translate!(msg, env)]) - {js, env} - end - - defp do_translate({:self, _, []}, env) do - js = Spawn.call_processes_func("pid", []) - {js, env} - end - defp do_translate({:receive, _, [expressions] }, env) do Receive.make_receive(expressions, env) end diff --git a/lib/elixir_script/translator/kernel/js.ex b/lib/elixir_script/translator/kernel/js.ex index bf50655b..4bae2857 100644 --- a/lib/elixir_script/translator/kernel/js.ex +++ b/lib/elixir_script/translator/kernel/js.ex @@ -45,7 +45,7 @@ defmodule ElixirScript.Translator.JS do ) end - defp do_translate({:yield_all, _, [term]}, env) do + defp do_translate({:yield_to, _, [term]}, env) do Builder.yield_expression( Translator.translate!(term, env), true diff --git a/lib/elixir_script/translator/kernel/spawn.ex b/lib/elixir_script/translator/kernel/spawn.ex deleted file mode 100644 index ca0657bc..00000000 --- a/lib/elixir_script/translator/kernel/spawn.ex +++ /dev/null @@ -1,93 +0,0 @@ -defmodule ElixirScript.Translator.Spawn do - @moduledoc false - - alias ESTree.Tools.Builder, as: JS - alias ElixirScript.Translator - alias ElixirScript.Translator.Function - alias ElixirScript.Translator.Call - - def make_spawn(func, env) do - do_spawn_with_gn(func, env, "spawn") - end - - def make_spawn_link(func, env) do - do_spawn_with_gn(func, env, "spawn_link") - end - - def make_spawn_monitor(func, env) do - do_spawn_with_gn(func, env, "spawn_monitor") - end - - defp do_spawn_with_gn({:fn, _, [{:->, _, [[], body]}]}, env, spawn_func_name) do - { body, _ } = Function.prepare_function_body(body, env) - js = call_processes_func(spawn_func_name, [JS.function_expression([], [], JS.block_statement(body), true)]) - { js, env } - end - - def make_spawn(module, fun, args, env) do - do_spawn_with_mod(module, fun, args, env, "spawn") - end - - def make_spawn_link(module, fun, args, env) do - do_spawn_with_mod(module, fun, args, env, "spawn_link") - end - - def make_spawn_monitor(module, fun, args, env) do - do_spawn_with_mod(module, fun, args, env, "spawn_monitor") - end - - defp do_spawn_with_mod(module, fun, args, env, spawn_func_name) do - functions_module = JS.member_expression( - JS.identifier("Elixir"), - JS.member_expression( - JS.identifier("Core"), - JS.identifier("Functions") - ) - ) - - {js, _} = Call.make_function_call(Translator.create_module_name(module, env), fun, args, env) - %ESTree.CallExpression{ callee: %ESTree.MemberExpression{ object: module, property: %ESTree.Identifier{ name: fun } }, arguments: args } = js - - func_to_run = JS.member_expression( - module, - JS.literal(fun), - true - ) - - context = case module do - %ESTree.Identifier{ name: "console" } -> - JS.identifier("console") - _ -> - JS.identifier("null") - end - - - js = call_processes_func(spawn_func_name, [ - functions_module, - JS.literal("run"), - JS.array_expression([func_to_run, JS.array_expression(args), context]) - ]) - - { js, env } - end - - - - def call_processes_func(func_name, params) do - JS.call_expression( - JS.member_expression( - JS.member_expression( - JS.identifier("Elixir"), - JS.member_expression( - JS.identifier("Core"), - JS.identifier("processes") - ) - ), - JS.identifier(func_name) - ), - params - ) - end - - -end diff --git a/lib/elixir_script/translator/kernel/special_forms/call.ex b/lib/elixir_script/translator/kernel/special_forms/call.ex index 8a6d3bcb..8ed21f61 100644 --- a/lib/elixir_script/translator/kernel/special_forms/call.ex +++ b/lib/elixir_script/translator/kernel/special_forms/call.ex @@ -5,6 +5,11 @@ defmodule ElixirScript.Translator.Call do alias ElixirScript.Translator.Utils alias ElixirScript.Translator.Identifier + def make_module_name(module_name, env) do + the_name = get_module_name_for_function(module_name, env) + { make_module_expression_tree(the_name, false, env), env } + end + def make_function_or_property_call(module_name, function_name, env) do the_name = get_module_name_for_function(module_name, env) diff --git a/lib/elixir_script/translator/kernel/special_forms/receive.ex b/lib/elixir_script/translator/kernel/special_forms/receive.ex index 4b461177..da13b442 100644 --- a/lib/elixir_script/translator/kernel/special_forms/receive.ex +++ b/lib/elixir_script/translator/kernel/special_forms/receive.ex @@ -3,14 +3,13 @@ defmodule ElixirScript.Translator.Receive do alias ESTree.Tools.Builder, as: JS alias ElixirScript.Translator - alias ElixirScript.Translator.Spawn alias ElixirScript.Translator.Primitive alias ElixirScript.Translator.LexicalScope def make_receive([do: clauses], env) do {made_case, _} = ElixirScript.Translator.Case.make_case({:__aliases__, [], [:message]}, clauses, env) - js = Spawn.call_processes_func("receive", [ + js = call_processes_func("receive", [ JS.function_expression( [JS.identifier(:message)], [], @@ -30,7 +29,7 @@ defmodule ElixirScript.Translator.Receive do {anon_func, _} = ElixirScript.Translator.Function.make_anonymous_function(after_clause, env) - js = Spawn.call_processes_func("receive", [ + js = call_processes_func("receive", [ JS.function_expression( [JS.identifier(:message)], [], @@ -47,4 +46,20 @@ defmodule ElixirScript.Translator.Receive do {js, env} end + def call_processes_func(func_name, params) do + JS.call_expression( + JS.member_expression( + JS.member_expression( + JS.identifier("Elixir"), + JS.member_expression( + JS.identifier("Core"), + JS.identifier("processes") + ) + ), + JS.identifier(func_name) + ), + params + ) + end + end diff --git a/mix.exs b/mix.exs index 6b4714bf..d0defc24 100644 --- a/mix.exs +++ b/mix.exs @@ -4,7 +4,7 @@ defmodule ElixirScript.Mixfile do def project do [ app: :elixir_script, - version: "0.21.0", + version: "0.22.0-dev", elixir: "~> 1.0", escript: escript_config, deps: deps, diff --git a/src/javascript/lib/core/functions.js b/src/javascript/lib/core/functions.js index cc3ad014..6411e238 100644 --- a/src/javascript/lib/core/functions.js +++ b/src/javascript/lib/core/functions.js @@ -29,6 +29,10 @@ function call_property(item, property){ } } +function is_generator(fun){ + return fun.constructor.name === "GeneratorFunction"; +} + function* run(fun, args, context = null){ if(fun.constructor.name === "GeneratorFunction"){ return yield* fun.apply(context, args); @@ -439,5 +443,6 @@ export default { duplicate, mapfoldl, filtermap, - maps_fold + maps_fold, + is_generator }; diff --git a/test/translator/kernel/receive_test.exs b/test/translator/kernel/receive_test.exs index 0c84ea75..e1bf547b 100644 --- a/test/translator/kernel/receive_test.exs +++ b/test/translator/kernel/receive_test.exs @@ -5,7 +5,6 @@ defmodule ElixirScript.Translator.Receive.Test do test "translate receive without after in process" do ex_ast = quote do - spawn(fn() -> receive do :ok -> value @@ -14,13 +13,11 @@ defmodule ElixirScript.Translator.Receive.Test do _ -> IO.puts "Unexpected message received" end - end) end js_code = """ - Elixir.Core.processes.spawn(function*() { - return yield Elixir.Core.processes.receive(function(message) { + Elixir.Core.processes.receive(function(message) { return Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.clause([Symbol.for('ok')],function() { return value; }),Elixir.Core.Patterns.clause([Symbol.for('error')],function() { @@ -28,7 +25,6 @@ defmodule ElixirScript.Translator.Receive.Test do }),Elixir.Core.Patterns.clause([Elixir.Core.Patterns.wildcard()],function() { return IO.puts('Unexpected message received'); })).call(this,message); - }); }) """ @@ -37,8 +33,6 @@ defmodule ElixirScript.Translator.Receive.Test do test "translate receive with after in process" do ex_ast = quote do - - spawn(fn() -> receive do :ok -> value @@ -50,12 +44,10 @@ defmodule ElixirScript.Translator.Receive.Test do 5000 -> IO.puts "No message in 5 seconds" end - end) end js_code = """ - Elixir.Core.processes.spawn(function*() { - return yield Elixir.Core.processes.receive(function(message) { + Elixir.Core.processes.receive(function(message) { return Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.clause([Symbol.for('ok')],function() { return value; }),Elixir.Core.Patterns.clause([Symbol.for('error')],function() { @@ -65,8 +57,7 @@ defmodule ElixirScript.Translator.Receive.Test do })).call(this,message); },5000,Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.clause([5000],function() { return IO.puts('No message in 5 seconds'); - }))); - }) + }))) """ assert_translation(ex_ast, js_code) diff --git a/test/translator/kernel/send_test.exs b/test/translator/kernel/send_test.exs index 5de1de2d..0c0daf7a 100644 --- a/test/translator/kernel/send_test.exs +++ b/test/translator/kernel/send_test.exs @@ -8,27 +8,7 @@ defmodule ElixirScript.Translator.Send.Test do end js_code = """ - Elixir.Core.processes.send(pid, 'hello') - """ - - assert_translation(ex_ast, js_code) - end - - - test "call send inside process" do - ex_ast = quote do - spawn(fn() -> - inside = self() - - send(pid, "hello") - end) - end - - js_code = """ - Elixir.Core.processes.spawn(function*() { - let [inside] = Elixir.Core.Patterns.match(Elixir.Core.Patterns.variable(),Elixir.Core.processes.pid()); - return yield* Elixir.Core.Functions.run(Elixir.Core.processes['send'],[pid, 'hello'],Elixir.Core.processes); - }) + Elixir$ElixirScript$Kernel.send(pid, 'hello') """ assert_translation(ex_ast, js_code) diff --git a/test/translator/kernel/spawn_test.exs b/test/translator/kernel/spawn_test.exs index 763c6e47..a2f9152a 100644 --- a/test/translator/kernel/spawn_test.exs +++ b/test/translator/kernel/spawn_test.exs @@ -2,44 +2,13 @@ defmodule ElixirScript.Translator.Spawn.Test do use ExUnit.Case import ElixirScript.TestHelper - test "call spawn" do - ex_ast = quote do - spawn(fn() -> 1 end) - end - - js_code = """ - Elixir.Core.processes.spawn(function*() { return 1; }) - """ - - assert_translation(ex_ast, js_code) - end - - test "call spawn with calls" do - ex_ast = quote do - spawn(fn() -> - Window.call(1) - Tuple.to_list({1, 2, 3}) - end) - end - - js_code = """ - Elixir.Core.processes.spawn(function*() { - yield* Elixir.Core.Functions.run(Window['call'],[1],Window) - return yield* Elixir.Core.Functions.run(Elixir$ElixirScript$Tuple['to_list'],[new Elixir.Core.Tuple(1,2,3)],Elixir$ElixirScript$Tuple); - }) - """ - - assert_translation(ex_ast, js_code) - end - - test "call spawn with function apply" do ex_ast = quote do spawn(Tuple, :to_list, [{1, 2, 3}]) end js_code = """ - Elixir.Core.processes.spawn(Elixir.Core.Functions,'run',[Elixir$ElixirScript$Tuple['to_list'], [new Elixir.Core.Tuple(1,2,3)], null]) + Elixir$ElixirScript$Kernel.spawn(Elixir$ElixirScript$Tuple,Symbol.for('to_list'),Object.freeze([new Elixir.Core.Tuple(1,2,3)])) """ assert_translation(ex_ast, js_code) @@ -52,9 +21,10 @@ defmodule ElixirScript.Translator.Spawn.Test do end js_code = """ - Elixir.Core.processes.spawn(Elixir.Core.Functions,'run',[Window['call'], [new Elixir.Core.Tuple(1,2,3)], null]) + Elixir$ElixirScript$Kernel.spawn(Window,Symbol.for('call'),Object.freeze([new Elixir.Core.Tuple(1,2,3)])) """ assert_translation(ex_ast, js_code) end + end From ad1b8ca4f38dbb1300a9c4ebf4f17d35573594b0 Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Thu, 28 Jul 2016 21:26:18 -0500 Subject: [PATCH 289/860] Removed yield translator functions --- lib/elixir_script/translator.ex | 24 ------------------------ 1 file changed, 24 deletions(-) diff --git a/lib/elixir_script/translator.ex b/lib/elixir_script/translator.ex index 2fe7ef18..e0bd92da 100644 --- a/lib/elixir_script/translator.ex +++ b/lib/elixir_script/translator.ex @@ -108,30 +108,6 @@ defmodule ElixirScript.Translator do Expression.make_unary_expression(operator, value, env) end - defp do_translate({:yield, _, []}, env) do - quoted = quote do - JS.yield - end - - translate(quoted, env) - end - - defp do_translate({:yield, _, [term]}, env) do - quoted = quote do - JS.yield unquote(term) - end - - translate(quoted, env) - end - - defp do_translate({:yield_all, _, [term]}, env) do - quoted = quote do - JS.yield_all unquote(term) - end - - translate(quoted, env) - end - defp do_translate({:not, _, [value]}, env) do Expression.make_unary_expression(:!, value, env) end From 033695ba9fc62d6ed212a2a35579333e7d18f642 Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Fri, 29 Jul 2016 22:16:46 -0500 Subject: [PATCH 290/860] Updated capture implementation --- .../kernel/special_forms/capture.ex | 52 +++---------------- test/translator/capture_test.exs | 8 +-- 2 files changed, 8 insertions(+), 52 deletions(-) diff --git a/lib/elixir_script/translator/kernel/special_forms/capture.ex b/lib/elixir_script/translator/kernel/special_forms/capture.ex index 57ba474b..05bb62f7 100644 --- a/lib/elixir_script/translator/kernel/special_forms/capture.ex +++ b/lib/elixir_script/translator/kernel/special_forms/capture.ex @@ -6,57 +6,17 @@ defmodule ElixirScript.Translator.Capture do alias ElixirScript.Translator.Function alias ElixirScript.Translator.Call alias ElixirScript.Translator.Identifier + alias ElixirScript.Translator def make_capture(function_name, arity, env) do - { patterns, params, _ } = process_params(arity, env) - - body = JS.block_statement([ - JS.return_statement( - JS.call_expression( - Identifier.make_identifier(function_name), - params - ) - ) - ]) - - make_capture_function(patterns, params, body, env) + Identifier.make_identifier(function_name) end def make_capture(module_name, function_name, arity, env) do - arity_params = Enum.map(1..arity, fn(x) -> {String.to_atom("__#{x}"), [], ElixirScript.Translator.Capture} end) - - { patterns, params, env } = process_params(arity, env) - - { _, _, name } = module_name - - name = if name == [:Kernel] or name == [Elixir, :Kernel] do - [:ElixirScript, :Kernel] - else - name - end - - { func, _ } = Call.make_function_call({:__aliases__, [], name }, function_name, arity_params, env) - - body = JS.block_statement([ - JS.return_statement( - func - ) - ]) - - make_capture_function(patterns, params, body, env) - end - - defp process_params(arity, env) do - params = Enum.map(1..arity, fn(x) -> {String.to_atom("__#{x}"), [], ElixirScript.Translator.Capture} end) - PatternMatching.process_match(params, env) - end - - defp make_capture_function(patterns, params, body, env) do - is_generator? = env.context == :generator - Function.make_defmatch([ - Function.make_function_clause(patterns, params, body, nil, is_generator?) - ], - is_generator?) + JS.member_expression( + Translator.translate!(module_name, env), + JS.identifier(function_name) + ) end def find_value_placeholders(ast) do diff --git a/test/translator/capture_test.exs b/test/translator/capture_test.exs index 36ca34b4..f7a55e9c 100644 --- a/test/translator/capture_test.exs +++ b/test/translator/capture_test.exs @@ -8,9 +8,7 @@ defmodule ElixirScript.Translator.Capture.Test do end js_code = """ - let [fun] = Elixir.Core.Patterns.match(Elixir.Core.Patterns.variable(),Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.clause([Elixir.Core.Patterns.variable()],function(__1) { - return Elixir$ElixirScript$Kernel.is_atom(__1); - }))); + let [fun] = Elixir.Core.Patterns.match(Elixir.Core.Patterns.variable(),Elixir$ElixirScript$Kernel.is_atom); """ assert_translation(ex_ast, js_code) @@ -41,9 +39,7 @@ defmodule ElixirScript.Translator.Capture.Test do end js_code = """ - let [fun] = Elixir.Core.Patterns.match(Elixir.Core.Patterns.variable(),Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.clause([Elixir.Core.Patterns.variable()],function(__1) { - return local_function(__1); - }))); + let [fun] = Elixir.Core.Patterns.match(Elixir.Core.Patterns.variable(),local_function); """ assert_translation(ex_ast, js_code) From 670c38df5a36f6cd175bd9a6ab8c9443fb6e8f41 Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Sun, 31 Jul 2016 15:43:56 -0500 Subject: [PATCH 291/860] Add 1-arity versions of spawn functions --- lib/elixir_script/prelude/kernel.ex | 24 ++++++++++++++++-------- 1 file changed, 16 insertions(+), 8 deletions(-) diff --git a/lib/elixir_script/prelude/kernel.ex b/lib/elixir_script/prelude/kernel.ex index bcc903c6..df87e323 100644 --- a/lib/elixir_script/prelude/kernel.ex +++ b/lib/elixir_script/prelude/kernel.ex @@ -56,8 +56,7 @@ defmodule ElixirScript.Kernel do end def apply(module, fun, args) do - fun = if Elixir.Core.is_atom(fun), do: Atom.to_string(fun), else: fun - Elixir.Core.Functions.apply(module, fun, args) + Elixir.Core.Functions.apply(module, Atom.to_string(fun), args) end def binary_part(binary, start, len) do @@ -176,19 +175,28 @@ defmodule ElixirScript.Kernel do Elixir.Core.processes.make_ref() end + def spawn(gen) do + Elixir.Core.processes.spawn(gen) + end + def spawn(module, fun, args) do - fun = if Elixir.Core.is_atom(fun), do: Atom.to_string(fun), else: fun - Elixir.Core.processes.spawn(module, fun, args) + Elixir.Core.processes.spawn(module, Atom.to_string(fun), args) + end + + def spawn_link(gen) do + Elixir.Core.processes.spawn_link(gen) end def spawn_link(module, fun, args) do - fun = if Elixir.Core.is_atom(fun), do: Atom.to_string(fun), else: fun - Elixir.Core.processes.spawn_link(module, fun, args) + Elixir.Core.processes.spawn_link(module, Atom.to_string(fun), args) + end + + def spawn_monitor(gen) do + Elixir.Core.processes.spawn_monitor(gen) end def spawn_monitor(module, fun, args) do - fun = if Elixir.Core.is_atom(fun), do: Atom.to_string(fun), else: fun - Elixir.Core.processes.spawn_monitor(module, fun, args) + Elixir.Core.processes.spawn_monitor(module, Atom.to_string(fun), args) end def send(pid, message) do From 97a413d18c22b4246546e76b1cb915a54419b16f Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Sun, 31 Jul 2016 15:55:04 -0500 Subject: [PATCH 292/860] Removed is_generator function from javascript functions --- src/javascript/lib/core/functions.js | 16 +--------------- 1 file changed, 1 insertion(+), 15 deletions(-) diff --git a/src/javascript/lib/core/functions.js b/src/javascript/lib/core/functions.js index 6411e238..bec25fd4 100644 --- a/src/javascript/lib/core/functions.js +++ b/src/javascript/lib/core/functions.js @@ -29,18 +29,6 @@ function call_property(item, property){ } } -function is_generator(fun){ - return fun.constructor.name === "GeneratorFunction"; -} - -function* run(fun, args, context = null){ - if(fun.constructor.name === "GeneratorFunction"){ - return yield* fun.apply(context, args); - } - - return yield fun.apply(context, args); -} - function apply(...args){ if(args.length === 2){ args[0].apply(null, args.slice(1)); @@ -406,7 +394,6 @@ function maps_from_list(list){ export default { call_property, - run, apply, contains, get_global, @@ -443,6 +430,5 @@ export default { duplicate, mapfoldl, filtermap, - maps_fold, - is_generator + maps_fold }; From f677d2ffdc5349b7a24308fdf89fad4116448b3a Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Sat, 3 Sep 2016 03:26:13 -0500 Subject: [PATCH 293/860] Fixed compilation error not returning lists correctly --- lib/elixir_script/translator.ex | 2 +- .../translator/kernel/special_forms/fn.ex | 5 ++--- test/translator/bug_test.exs | 16 ++++++++++++++++ 3 files changed, 19 insertions(+), 4 deletions(-) diff --git a/lib/elixir_script/translator.ex b/lib/elixir_script/translator.ex index e0bd92da..e4f83e04 100644 --- a/lib/elixir_script/translator.ex +++ b/lib/elixir_script/translator.ex @@ -157,7 +157,7 @@ defmodule ElixirScript.Translator do { Capture.make_capture(function_name, arity, env), env } end - defp do_translate({:&, _, body}, env) do + defp do_translate({:&, _, [body]}, env) do params = Capture.find_value_placeholders(body) |> List.flatten Function.make_anonymous_function([{:->, [], [params, body]}], env) end diff --git a/lib/elixir_script/translator/kernel/special_forms/fn.ex b/lib/elixir_script/translator/kernel/special_forms/fn.ex index 1061ffce..1673a8fa 100644 --- a/lib/elixir_script/translator/kernel/special_forms/fn.ex +++ b/lib/elixir_script/translator/kernel/special_forms/fn.ex @@ -141,9 +141,8 @@ defmodule ElixirScript.Translator.Function do nil -> { [], env } list when is_list(list) -> - Enum.map_reduce(list, env, fn(x, env) -> - Translator.translate(x, env) - end) + t = Translator.translate!(list, env) + {[t], env} {:__block__, _, list} -> Enum.map_reduce(list, env, fn(x, env) -> Translator.translate(x, env) diff --git a/test/translator/bug_test.exs b/test/translator/bug_test.exs index 7bc8cf92..296daf69 100644 --- a/test/translator/bug_test.exs +++ b/test/translator/bug_test.exs @@ -138,4 +138,20 @@ defmodule ElixirScript.Translator.Bug.Test do end + test "test array returns correctly" do + ex_ast = quote do + def my_func(x) do + [x.a, x.b] + end + end + + js_code = """ + const my_func = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.clause([Elixir.Core.Patterns.variable()],function(x){ + return Object.freeze([Elixir.Core.Functions.call_property(x,'a'), Elixir.Core.Functions.call_property(x,'b')]); + })); + """ + + assert_translation(ex_ast, js_code) + end + end From d99e953af8a94f4dfcbc2df583487607aa685542 Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Sat, 3 Sep 2016 03:29:35 -0500 Subject: [PATCH 294/860] Updated changelog --- CHANGELOG.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index dd68832a..577f3bb2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,7 @@ +# v0.22.0-dev +* Bug fixes + * Correctly returning list if list is only item in body + # v0.21.0 * Enhancements * This is the first release with early support for processes in elixirscript. Creating a process only works currently using `spawn/1`, `spawn_link/1`, and `spawn_monitor/1`. Inside of a process, you can use functions such as `send` and `receive`, along with some defined in the `Process` module. From outside of a process, you can send messages to a process, but you cannot receive a message from a process. Eventually all code will run inside processes and this restriction will naturally lift. From c015ec9d0760ead6df62ad844aa76cff331dd4cb Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Sat, 8 Oct 2016 16:18:09 -0500 Subject: [PATCH 295/860] Add deps module --- lib/elixir_script/compiler/deps.ex | 15 +++++++++++++++ 1 file changed, 15 insertions(+) create mode 100644 lib/elixir_script/compiler/deps.ex diff --git a/lib/elixir_script/compiler/deps.ex b/lib/elixir_script/compiler/deps.ex new file mode 100644 index 00000000..8bc4440f --- /dev/null +++ b/lib/elixir_script/compiler/deps.ex @@ -0,0 +1,15 @@ +defmodule ElixirScript.Compiler.Deps do + + def get_deps_paths(env \\ Mix.env) do + deps = Mix.Dep.loaded([env: "env"]) + + Enum.reduce(deps, Map.new, fn(dep, map) -> + paths = Mix.Project.in_project dep.app, dep.opts[:dest], fn mixfile -> Mix.Project.config()[:elixirc_paths] end + paths = Enum.map(paths, fn path -> Path.join([dep.opts[:dest], path]) end) + + Map.put(map, dep.app, paths) + end) + end + + +end From 570c229f55351352c2bde10acac907218aecb8a7 Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Sun, 9 Oct 2016 20:07:34 -0500 Subject: [PATCH 296/860] Add function to deps module to find modules in files --- lib/elixir_script/compiler/deps.ex | 57 ++++++++++++++++++++++++++++++ test/compiler/deps_test.exs | 5 +++ 2 files changed, 62 insertions(+) create mode 100644 test/compiler/deps_test.exs diff --git a/lib/elixir_script/compiler/deps.ex b/lib/elixir_script/compiler/deps.ex index 8bc4440f..30bc0d74 100644 --- a/lib/elixir_script/compiler/deps.ex +++ b/lib/elixir_script/compiler/deps.ex @@ -1,4 +1,5 @@ defmodule ElixirScript.Compiler.Deps do + alias ElixirScript.Translator.Utils def get_deps_paths(env \\ Mix.env) do deps = Mix.Dep.loaded([env: "env"]) @@ -11,5 +12,61 @@ defmodule ElixirScript.Compiler.Deps do end) end + def get_module_filepath_map(env \\ Mix.env) do + deps_paths = get_deps_paths(env) + + Enum.reduce(deps_paths, Map.new, fn({dep, paths}, map) -> + + file_paths = Enum.flat_map(paths, fn(path) -> + path = Path.join(path, "**/*.{ex,exs,exjs}") + |> Path.wildcard + end) + + file_paths = Enum.reduce(file_paths, Map.new, fn(path, map) -> + quoted = path + |> File.read! + |> Code.string_to_quoted! + + { _, modules } = Macro.postwalk(quoted, %{protocols: [], modules: [], impls: []}, &get_defmodules(&1, &2)) + + { path, modules } + Map.put(map, path, modules) + end) + + {dep, file_paths} + Map.put(map, dep, file_paths) + end) + + end + + + defp get_defmodules({:defprotocol, _, [{:__aliases__, _, _} = the_alias, _]} = ast, state) do + state = Map.update!(state, :protocols, fn(l) -> [ Utils.quoted_to_name(the_alias) | l ] end) + { ast, state } + end + + defp get_defmodules({:defprotocol, _, [{:__aliases__, _, _} = the_alias, _]} = ast, state) do + state = Map.update!(state, :protocols, fn(l) -> [ Utils.quoted_to_name(the_alias) | l ] end) + { ast, state } + end + + defp get_defmodules({:defimpl, _, [ {:__aliases__, _, _} = the_alias, [for: type], _ ]} = ast, state) do + state = Map.update!(state, :impls, fn(l) -> [ { Utils.quoted_to_name(the_alias), Utils.quoted_to_name(type) } | l ] end) + { ast, state } + end + + defp get_defmodules({:defimpl, _, [ {:__aliases__, _, _} = the_alias, [for: type], _ ]} = ast, state) do + state = Map.update!(state, :impls, fn(l) -> [ { Utils.quoted_to_name(the_alias), Utils.quoted_to_name(type) } | l ] end) + { ast, state } + end + + defp get_defmodules({:defmodule, _, [{:__aliases__, _, _} = the_alias, [do: _]]} = ast, state) do + state = Map.update!(state, :modules, fn(l) -> [ Utils.quoted_to_name(the_alias) | l ] end) + { ast, state } + end + + defp get_defmodules(ast, state) do + { ast, state } + end end diff --git a/test/compiler/deps_test.exs b/test/compiler/deps_test.exs new file mode 100644 index 00000000..7c5d5cf6 --- /dev/null +++ b/test/compiler/deps_test.exs @@ -0,0 +1,5 @@ +defmodule ElixirScript.Compiler.Deps.Test do + use ExUnit.Case + alias ElixirScript.Compiler.Cache + +end From 50bc6eae4b6d990174435c3bec4d7183eacd54e3 Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Wed, 12 Oct 2016 20:02:52 -0500 Subject: [PATCH 297/860] Update package config --- mix.exs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mix.exs b/mix.exs index d0defc24..79f0f958 100644 --- a/mix.exs +++ b/mix.exs @@ -49,7 +49,7 @@ defmodule ElixirScript.Mixfile do defp package do [ - files: ["lib", "priv/*.js", "mix.exs", "README*", "readme*", "LICENSE*", "license*", "CHANGELOG*"], + files: ["lib", "priv/*.js", "mix.exs", "README.md", "LICENSE", "CHANGELOG.md"], maintainers: ["Bryan Joseph"], licenses: ["MIT"], links: %{ From 8407876095cf7392fcaedc9e3ce0dcbe596ef4ce Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Wed, 12 Oct 2016 20:12:25 -0500 Subject: [PATCH 298/860] Add app_name to modules --- lib/elixir_script.ex | 4 +- lib/elixir_script/prelude/module.ex | 2 +- .../translator/module_collector.ex | 40 +++++++++---------- lib/elixir_script/translator/state.ex | 12 +++--- 4 files changed, 29 insertions(+), 29 deletions(-) diff --git a/lib/elixir_script.ex b/lib/elixir_script.ex index d15e86e8..b94bb59a 100644 --- a/lib/elixir_script.ex +++ b/lib/elixir_script.ex @@ -182,7 +182,7 @@ defmodule ElixirScript do code |> Enum.map(&update_quoted(&1)) - |> ModuleCollector.process_modules + |> ModuleCollector.process_modules(:elixir) code = create_code(compiler_opts, ElixirScript.Translator.State.get) |> Enum.filter(fn({path, _}) -> !String.contains?(path, "ElixirScript.Temp.js") end) @@ -202,7 +202,7 @@ defmodule ElixirScript do quoted_code_list |> Enum.map(&update_quoted(&1)) - |> ModuleCollector.process_modules + |> ModuleCollector.process_modules(:app) code = create_code(compiler_opts, ElixirScript.Translator.State.get) new_state = ElixirScript.Translator.State.serialize() diff --git a/lib/elixir_script/prelude/module.ex b/lib/elixir_script/prelude/module.ex index a78df8ca..44c1acc4 100644 --- a/lib/elixir_script/prelude/module.ex +++ b/lib/elixir_script/prelude/module.ex @@ -4,6 +4,6 @@ defmodule ElixirScript.Module do defstruct name: nil, functions: Keyword.new, private_functions: Keyword.new, body: nil, js_imports: [], module_refs: [], type: :module, - impls: HashDict.new, impl_type: nil + impls: HashDict.new, impl_type: nil, app_name: nil end diff --git a/lib/elixir_script/translator/module_collector.ex b/lib/elixir_script/translator/module_collector.ex index 46ea3219..04c86c7a 100644 --- a/lib/elixir_script/translator/module_collector.ex +++ b/lib/elixir_script/translator/module_collector.ex @@ -11,7 +11,7 @@ defmodule ElixirScript.Translator.ModuleCollector do @function_types [:def, :defp, :defgen, :defgenp] - def process_modules(modules) do + def process_modules(modules, app_name) do Enum.map(modules, fn { :__block__, _, list } -> {modules, not_modules} = Enum.partition(list, @@ -38,46 +38,46 @@ defmodule ElixirScript.Translator.ModuleCollector do end) |> List.flatten |> Enum.each(fn(m) -> - Macro.postwalk(m, &do_process_modules(&1)) + Macro.postwalk(m, &do_process_modules(&1, app_name)) end) end - def do_process_modules({:defprotocol, _, [{:__aliases__, _, _} = the_alias, [do: {:__block__, _, _} = block]]}) do + def do_process_modules({:defprotocol, _, [{:__aliases__, _, _} = the_alias, [do: {:__block__, _, _} = block]]}, app_name) do %{def: functions, defp: _ } = get_functions_from_module(block) - ElixirScript.Translator.State.add_protocol(Utils.quoted_to_name(the_alias), functions) + ElixirScript.Translator.State.add_protocol(Utils.quoted_to_name(the_alias), functions, app_name) end - def do_process_modules({:defprotocol, _, [{:__aliases__, _, _} = the_alias, [do: spec]]}) do + def do_process_modules({:defprotocol, _, [{:__aliases__, _, _} = the_alias, [do: spec]]}, app_name) do %{def: functions, defp: _ } = get_functions_from_module({:__block__, [], [spec]}) - ElixirScript.Translator.State.add_protocol(Utils.quoted_to_name(the_alias), functions) + ElixirScript.Translator.State.add_protocol(Utils.quoted_to_name(the_alias), functions, app_name) end - def do_process_modules({:defimpl, _, [ {:__aliases__, _, _} = the_alias, [for: type], [do: {:__block__, context, spec}] ]}) do - ElixirScript.Translator.State.add_protocol_impl(Utils.quoted_to_name(the_alias), type, {:__block__, context, spec}) + def do_process_modules({:defimpl, _, [ {:__aliases__, _, _} = the_alias, [for: type], [do: {:__block__, context, spec}] ]}, app_name) do + ElixirScript.Translator.State.add_protocol_impl(Utils.quoted_to_name(the_alias), type, {:__block__, context, spec}, app_name) end - def do_process_modules({:defimpl, _, [ {:__aliases__, _, _} = the_alias, [for: type], [do: spec] ]}) do - ElixirScript.Translator.State.add_protocol_impl(Utils.quoted_to_name(the_alias), type, {:__block__, [], [spec]}) + def do_process_modules({:defimpl, _, [ {:__aliases__, _, _} = the_alias, [for: type], [do: spec] ]}, app_name) do + ElixirScript.Translator.State.add_protocol_impl(Utils.quoted_to_name(the_alias), type, {:__block__, [], [spec]}, app_name) end - def do_process_modules({:defmodule, _, [{:__aliases__, _, [:ElixirScript, :Temp]}, [do: body]]} = ast) do + def do_process_modules({:defmodule, _, [{:__aliases__, _, [:ElixirScript, :Temp]}, [do: body]]} = ast, app_name) do body - |> make_module([:ElixirScript, :Temp]) + |> make_module([:ElixirScript, :Temp], app_name) |> State.add_module ast end - def do_process_modules({:defmodule, _, [{:__aliases__, _, _}, [do: _]]} = ast) do - do_module_processing(ast) + def do_process_modules({:defmodule, _, [{:__aliases__, _, _}, [do: _]]} = ast, app_name) do + do_module_processing(ast, app_name) ast end - def do_process_modules(ast) do + def do_process_modules(ast, _) do ast end - defp do_module_processing({:defmodule, _, [{:__aliases__, _, name}, [do: body]]}) do + defp do_module_processing({:defmodule, _, [{:__aliases__, _, name}, [do: body]]}, app_name) do { body, inner_modules } = make_inner_module_aliases(name, body) aliases = Enum.map(inner_modules, fn @@ -94,10 +94,10 @@ defmodule ElixirScript.Translator.ModuleCollector do this_module_aliases = aliases -- [{ :alias, [], [{:__aliases__, [alias: false], name ++ inner_module_name}, [as: {:__aliases__, [alias: false], inner_module_name }] ] }] {:defmodule, context1, [{:__aliases__, context2, name ++ inner_module_name}, [do: add_aliases_to_body(inner_module_body, this_module_aliases)]]} - |> do_module_processing + |> do_module_processing(app_name) end) - module = make_module(add_aliases_to_body(body, aliases), name) + module = make_module(add_aliases_to_body(body, aliases), name, app_name) State.add_module(module) end @@ -110,7 +110,7 @@ defmodule ElixirScript.Translator.ModuleCollector do end end - defp make_module(body, name) do + defp make_module(body, name, app_name) do # Finds use expressions and expands them body = case body do {:__block__, context, list } -> @@ -144,7 +144,7 @@ defmodule ElixirScript.Translator.ModuleCollector do %{def: functions, defp: private_functions, defgen: generators, defgenp: private_generators } = get_functions_from_module(body) js_imports = get_js_imports_from_module(body) - %ElixirScript.Module{ name: Utils.quoted_to_name({:__aliases__, [], name}) , body: body, + %ElixirScript.Module{app_name: app_name, name: Utils.quoted_to_name({:__aliases__, [], name}) , body: body, functions: functions ++ generators, private_functions: private_functions ++ private_generators, js_imports: js_imports } end diff --git a/lib/elixir_script/translator/state.ex b/lib/elixir_script/translator/state.ex index 87def232..d7a1c3ca 100644 --- a/lib/elixir_script/translator/state.ex +++ b/lib/elixir_script/translator/state.ex @@ -67,12 +67,12 @@ defmodule ElixirScript.Translator.State do end) end - def add_protocol(name, functions) do + def add_protocol(name, functions, app_name) do Agent.update(__MODULE__, fn state -> proto = Map.get(state.modules, do_get_module_name(name, state)) proto = if proto == nil do - %ElixirScript.Module{ name: name, functions: functions, type: :protocol } + %ElixirScript.Module{ app_name: app_name, name: name, functions: functions, type: :protocol } else %ElixirScript.Module{proto | functions: functions, type: :protocol } end @@ -81,19 +81,19 @@ defmodule ElixirScript.Translator.State do end) end - def add_protocol_impl(protocol, type, impl) when is_list(type) do + def add_protocol_impl(protocol, type, impl, app_name) when is_list(type) do Enum.each(type, fn x -> - add_protocol_impl(protocol, x, impl) + add_protocol_impl(protocol, x, impl, app_name) end) end - def add_protocol_impl(protocol, type, impl) do + def add_protocol_impl(protocol, type, impl, app_name) do Agent.update(__MODULE__, fn state -> protocol_name = Atom.to_string(do_get_module_name(protocol, state)) type_name = Atom.to_string(Utils.quoted_to_name(type)) module_name = String.to_atom(protocol_name <> ".DefImpl." <> type_name) - proto_impl = %ElixirScript.Module{ name: module_name, body: impl, impl_type: type, type: :protocol_implementation } + proto_impl = %ElixirScript.Module{ app_name: app_name, name: module_name, body: impl, impl_type: type, type: :protocol_implementation } do_add_module_to_state(state, proto_impl) end) From 6ef40713ee9bc92b815acaacae3f6d372dab3231 Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Thu, 13 Oct 2016 19:51:24 -0500 Subject: [PATCH 299/860] putting output into app folders --- .gitignore | 2 +- lib/elixir_script.ex | 56 +++++++++++++----- lib/elixir_script/compiler/output.ex | 10 ++-- .../translator/kernel/defmodule.ex | 23 +++++--- .../translator/kernel/defprotocol.ex | 21 ++++--- lib/elixir_script/translator/utils.ex | 24 ++++++-- rollup.config.js | 2 +- test/elixir_script_test.exs | 24 ++++---- test/translator/bug_test.exs | 2 +- test/translator/defmodule_test.exs | 58 +++++++++---------- test/translator/function_test.exs | 10 ++-- test/translator/protocol_test.exs | 18 +++--- test/translator/struct_test.exs | 14 ++--- 13 files changed, 159 insertions(+), 105 deletions(-) diff --git a/.gitignore b/.gitignore index ec7fe1c3..e9c2abd6 100644 --- a/.gitignore +++ b/.gitignore @@ -16,5 +16,5 @@ index.js .tern-port test/std_lib_compile_test.exs src/elixirscript -priv/*.js +priv/**/*.js stdlib_state.bin diff --git a/lib/elixir_script.ex b/lib/elixir_script.ex index b94bb59a..981ed78e 100644 --- a/lib/elixir_script.ex +++ b/lib/elixir_script.ex @@ -62,7 +62,9 @@ defmodule ElixirScript do @spec compile_quoted(Macro.t, Map.t) :: [binary | {binary, binary} | :ok] def compile_quoted(quoted, opts \\ %{}) do { code, _ } = do_compile(opts, [quoted], get_stdlib_state, []) - Output.out(quoted, code, build_compiler_options(opts)) + result = Output.out(quoted, code, build_compiler_options(opts)) + ElixirScript.Translator.State.stop + result end @doc """ @@ -93,7 +95,9 @@ defmodule ElixirScript do compiler_cache = %{compiler_cache | input_files: new_file_stats, state: new_state } Cache.write(path, compiler_cache) - Output.out(path, code, opts) + result = Output.out(path, code, opts) + ElixirScript.Translator.State.stop + result end defp process_path(path) do @@ -185,13 +189,16 @@ defmodule ElixirScript do |> ModuleCollector.process_modules(:elixir) code = create_code(compiler_opts, ElixirScript.Translator.State.get) - |> Enum.filter(fn({path, _}) -> !String.contains?(path, "ElixirScript.Temp.js") end) + |> Enum.filter(fn({path, _, _}) -> !String.contains?(path, "ElixirScript.Temp.js") end) new_std_state = ElixirScript.Translator.State.serialize() - ElixirScript.Translator.State.stop File.write!(File.cwd!() <> "/lib/elixir_script/translator/stdlib_state.bin", new_std_state) - Output.out(libs_path, code, compiler_opts) + result = Output.out(libs_path, code, compiler_opts) + + ElixirScript.Translator.State.stop + + result end defp do_compile(opts, quoted_code_list, state, loaded_modules) do @@ -206,7 +213,6 @@ defmodule ElixirScript do code = create_code(compiler_opts, ElixirScript.Translator.State.get) new_state = ElixirScript.Translator.State.serialize() - ElixirScript.Translator.State.stop { code, new_state } end @@ -288,12 +294,17 @@ defmodule ElixirScript do @doc false def update_protocols(compiler_output, compiler_opts) do Enum.reduce(compiler_output, %{}, fn - {file, code}, state -> + {file, code, app_name}, state -> case String.split(file, ".DefImpl.") do [protocol, impl] -> protocol = String.split(protocol, "/") |> List.last |> String.to_atom impl = String.replace(impl, ".js", "") |> String.to_atom - Map.put(state, protocol, Map.get(state, protocol, []) ++ [impl]) + + entry = Map.get(state, protocol, []) + entry = entry ++ [{app_name, impl}] + + + Map.put(state, protocol, entry) [_] -> state end @@ -305,13 +316,17 @@ defmodule ElixirScript do @doc false def update_protocols_in_path(compiler_output, compiler_opts, output_path) do - Enum.reduce(compiler_output, %{}, fn {file, code}, state -> + Enum.reduce(compiler_output, %{}, fn { file, code, app_name }, state -> case String.split(file, ".DefImpl.") do [protocol, _] -> protocol = String.split(protocol, "/") |> List.last protocol_impls = find_protocols_implementations_in_path(output_path, protocol) protocol = String.to_atom(protocol) - Map.put(state, protocol, Map.get(state, protocol, []) ++ protocol_impls) + + entry = Map.get(state, protocol, []) + entry = entry ++ protocol_impls + + Map.put(state, protocol, entry) [_] -> state end @@ -320,8 +335,8 @@ defmodule ElixirScript do end defp do_make_defimpl(protocols, compiler_opts) do - Enum.map(protocols, fn {protocol, implementations} -> - ElixirScript.Translator.Defprotocol.make_defimpl(protocol, Enum.uniq(implementations), compiler_opts) + Enum.map(protocols, fn {protocol, impls} -> + ElixirScript.Translator.Defprotocol.make_defimpl(protocol, Enum.uniq(impls), compiler_opts) end) |> Enum.map(fn(module) -> javascript_ast_to_code(module) @@ -329,15 +344,24 @@ defmodule ElixirScript do end defp find_protocols_implementations_in_path(path, protocol_prefix) do - Path.join([path, protocol_prefix <> ".DefImpl*.js"]) + Path.join([path, "**", protocol_prefix <> ".DefImpl*.js"]) |> Path.wildcard |> Enum.filter(fn path -> !String.ends_with?(path, "DefImpl.js") end) |> Enum.map(fn impl -> - Path.basename(impl) + + path_split = Path.split(impl) + + implementation = path_split + |> List.last |> String.split(".DefImpl.") |> List.last |> String.replace(".js", "") - |> String.to_atom end) + |> String.to_atom + + app_name = Enum.at(path_split, length(path_split) - 2) + + {app_name, implementation} + end) end @doc """ @@ -359,7 +383,7 @@ defmodule ElixirScript do |> prepare_js_ast |> Generator.generate - { path, js_code } + { path, js_code, module.app_name } end defp prepare_js_ast(js_ast) do diff --git a/lib/elixir_script/compiler/output.ex b/lib/elixir_script/compiler/output.ex index 6b785501..71a5c821 100644 --- a/lib/elixir_script/compiler/output.ex +++ b/lib/elixir_script/compiler/output.ex @@ -11,7 +11,7 @@ defmodule ElixirScript.Compiler.Output do compiler_output ++ ElixirScript.update_protocols(compiler_output, compiler_opts) |> process_include_path(compiler_opts) |> Enum.each(fn - {_, code} -> IO.write(code) + {_, code, _} -> IO.write(code) code -> IO.write(code) end) end @@ -35,8 +35,8 @@ defmodule ElixirScript.Compiler.Output do end end - def write_to_file({ file_path, js_code }, destination) do - file_name = Path.join([destination, file_path]) + def write_to_file({ file_path, js_code, app }, destination) do + file_name = Path.join([destination, to_string(app), file_path]) if !File.exists?(Path.dirname(file_name)) do File.mkdir_p!(Path.dirname(file_name)) @@ -47,10 +47,10 @@ defmodule ElixirScript.Compiler.Output do defp process_include_path(compiler_output, compiler_opts) do Enum.map(compiler_output, fn - { path, code } -> + { path, code, app_name } -> case compiler_opts.include_path do true -> - { path, code } + { path, code, app_name } false -> code end diff --git a/lib/elixir_script/translator/kernel/defmodule.ex b/lib/elixir_script/translator/kernel/defmodule.ex index d1004618..77801a81 100644 --- a/lib/elixir_script/translator/kernel/defmodule.ex +++ b/lib/elixir_script/translator/kernel/defmodule.ex @@ -2,6 +2,7 @@ defmodule ElixirScript.Translator.Defmodule do @moduledoc false alias ESTree.Tools.Builder, as: JS alias ElixirScript.Translator + alias ElixirScript.Translator.State alias ElixirScript.Translator.Utils alias ElixirScript.Translator.Group alias ElixirScript.Translator.Def @@ -10,11 +11,11 @@ defmodule ElixirScript.Translator.Defmodule do def make_module(ElixirScript.Temp, body, env) do { body, _ } = translate_body(body, env) - %{ name: ElixirScript.Temp, body: body |> Group.inflate_groups } + %{ name: ElixirScript.Temp, body: body |> Group.inflate_groups, app_name: :app } end def make_module(module, nil, _) do - %{ name: module, body: [] } + %{ name: module, body: [], app_name: :app } end def make_module(module, body, env) do @@ -28,7 +29,9 @@ defmodule ElixirScript.Translator.Defmodule do {imports, body} = extract_imports_from_body(body) {structs, body} = extract_structs_from_body(body, env) - imports = imports ++ make_std_lib_import() ++ make_imports(module_refs) + app_name = State.get_module(module).app_name + + imports = imports ++ make_std_lib_import() ++ make_imports(app_name, module_refs) #Collect all the functions so that we can process their arity body = Enum.map(body, fn(x) -> @@ -56,7 +59,8 @@ defmodule ElixirScript.Translator.Defmodule do result = %{ name: Utils.quoted_to_name({:__aliases__, [], module }), - body: imports ++ structs ++ private_functions ++ exported_functions ++ body ++ [default] + body: imports ++ structs ++ private_functions ++ exported_functions ++ body ++ [default], + app_name: app_name } result @@ -175,7 +179,7 @@ defmodule ElixirScript.Translator.Defmodule do compiler_opts = ElixirScript.Translator.State.get().compiler_opts case compiler_opts.import_standard_libs do true -> - [ModuleSystems.import_module(:Elixir, Utils.make_local_file_path(compiler_opts.core_path))] + [ModuleSystems.import_module(:Elixir, Utils.make_local_file_path(:elixir, compiler_opts.core_path))] false -> [] end @@ -220,8 +224,13 @@ defmodule ElixirScript.Translator.Defmodule do JS.variable_declaration([declarator], :const) end - def make_imports(enum) do - Enum.map(enum, fn(x) -> ModuleSystems.import_module(Utils.name_to_js_name(x), Utils.make_local_file_path(Utils.name_to_js_file_name(x))) end) + def make_imports(current_app_name, enum) do + Enum.map(enum, fn(x) -> + module_name = Utils.name_to_js_name(x) + app_name = State.get_module(x).app_name + path = Utils.make_local_file_path(app_name, Utils.name_to_js_file_name(x)) + ModuleSystems.import_module(module_name, path) + end) end end diff --git a/lib/elixir_script/translator/kernel/defprotocol.ex b/lib/elixir_script/translator/kernel/defprotocol.ex index 4e10f3b1..16a18708 100644 --- a/lib/elixir_script/translator/kernel/defprotocol.ex +++ b/lib/elixir_script/translator/kernel/defprotocol.ex @@ -5,6 +5,7 @@ defmodule ElixirScript.Translator.Defprotocol do alias ElixirScript.Translator.Defmodule alias ElixirScript.Translator.Map alias ElixirScript.Translator.Utils + alias ElixirScript.Translator.State alias ElixirScript.ModuleSystems alias ElixirScript.Translator.Identifier require Logger @@ -19,9 +20,11 @@ defmodule ElixirScript.Translator.Defprotocol do {imports, body} = Defmodule.extract_imports_from_body(body) + app_name = State.get_module(name).app_name + imports = imports ++ Defmodule.make_std_lib_import() ++ - Defmodule.make_imports(module_refs) ++ - [ElixirScript.ModuleSystems.import_module("Implementations", Utils.make_local_file_path(Utils.name_to_js_file_name(name) <> ".Defimpl"))] + Defmodule.make_imports(app_name, module_refs) ++ + [ElixirScript.ModuleSystems.import_module("Implementations", Utils.make_local_file_path(app_name, Utils.name_to_js_file_name(name) <> ".Defimpl"))] object = process_spec_functions(functions) |> Enum.map(fn({key, value}) -> @@ -80,7 +83,8 @@ defmodule ElixirScript.Translator.Defprotocol do %{ name: name, - body: imports ++ body ++ [declaration] ++ [implementations] ++ [default] + body: imports ++ body ++ [declaration] ++ [implementations] ++ [default], + app_name: app_name } end @@ -95,7 +99,7 @@ defmodule ElixirScript.Translator.Defprotocol do This is used to consolidate all of the protocol implementations. """ def make_defimpl(name, implementations \\ [], compiler_opts) do - imports = [ModuleSystems.import_module(:Elixir, Utils.make_local_file_path(compiler_opts.core_path, compiler_opts.root))] + imports = [ModuleSystems.import_module(:Elixir, Utils.make_local_file_path(:elixir, compiler_opts.core_path, compiler_opts.root))] declarator = JS.variable_declarator( JS.identifier("impls"), @@ -108,11 +112,13 @@ defmodule ElixirScript.Translator.Defprotocol do protocol_name = Atom.to_string(name) - body = Enum.flat_map(implementations, fn(x) -> + app_name = State.get_module(name).app_name + + body = Enum.flat_map(implementations, fn({impl_app_name, x}) -> x = if is_atom(x), do: Atom.to_string(x), else: x x = String.to_atom(protocol_name <> ".DefImpl." <> x) name = Utils.name_to_js_name(x) - imports = ModuleSystems.import_module(name, Utils.make_local_file_path(Utils.name_to_js_file_name(x), compiler_opts.root)) + imports = ModuleSystems.import_module(name, Utils.make_local_file_path(impl_app_name, Utils.name_to_js_file_name(x), compiler_opts.root)) call = JS.call_expression( JS.member_expression( JS.identifier("impls"), @@ -126,7 +132,8 @@ defmodule ElixirScript.Translator.Defprotocol do %{ name: String.to_atom(protocol_name <> ".DefImpl"), - body: imports ++ [declaration] ++ body ++ [default] + body: imports ++ [declaration] ++ body ++ [default], + app_name: app_name } end end diff --git a/lib/elixir_script/translator/utils.ex b/lib/elixir_script/translator/utils.ex index f4fa29d6..9ef5a198 100644 --- a/lib/elixir_script/translator/utils.ex +++ b/lib/elixir_script/translator/utils.ex @@ -26,23 +26,37 @@ defmodule ElixirScript.Translator.Utils do Enum.join([:Elixir] ++ name, ".") end + def make_local_file_path(module_app_name, file_name) when is_atom(module_app_name) do + root = ElixirScript.Translator.State.get().compiler_opts.root + app_name = to_string(module_app_name) + + case root do + nil -> + Path.join(["..", app_name, file_name]) + root -> + Path.join([root, app_name, file_name]) + end + end + def make_local_file_path(file_name) do root = ElixirScript.Translator.State.get().compiler_opts.root case root do nil -> - "./" <> file_name + Path.join([".", file_name]) root -> - root <> "/" <> file_name + Path.join([root, file_name]) end end - def make_local_file_path(file_name, root) do + def make_local_file_path(module_app_name, file_name, root) do + app_name = to_string(module_app_name) + case root do nil -> - "./" <> file_name + Path.join(["..", app_name, file_name]) root -> - root <> "/" <> file_name + Path.join([root, app_name, file_name]) end end diff --git a/rollup.config.js b/rollup.config.js index 5a62de3b..72924ca9 100644 --- a/rollup.config.js +++ b/rollup.config.js @@ -4,7 +4,7 @@ import babel from 'rollup-plugin-babel'; export default { entry: 'src/javascript/elixir.js', - dest: 'priv/Elixir.js', + dest: 'priv/elixir/Elixir.js', sourceMap: 'inline', format: 'es6', plugins: [ diff --git a/test/elixir_script_test.exs b/test/elixir_script_test.exs index 893ca412..d8f6fada 100644 --- a/test/elixir_script_test.exs +++ b/test/elixir_script_test.exs @@ -42,9 +42,9 @@ defmodule ElixirScript.Test do """) assert_js_matches """ - import Elixir from './Elixir'; - import Elixir$ElixirScript$Kernel from './Elixir.ElixirScript.Kernel'; - import Elixir$ElixirScript$String$Chars from './Elixir.ElixirScript.String.Chars'; + import Elixir from '../elixir/Elixir'; + import Elixir$ElixirScript$Kernel from '../elixir/Elixir.ElixirScript.Kernel'; + import Elixir$ElixirScript$String$Chars from '../elixir/Elixir.ElixirScript.String.Chars'; const something_else = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.clause([],function() { return Elixir$ElixirScript$String$Chars.to_string(10); })); @@ -76,9 +76,9 @@ defmodule ElixirScript.Test do """, %{ env: make_custom_env }) assert_js_matches """ - import Elixir from './Elixir'; - import Elixir$ElixirScript$Kernel from './Elixir.ElixirScript.Kernel'; - import Elixir$Animals$Elephant from './Elixir.Animals.Elephant'; + import Elixir from '../elixir/Elixir'; + import Elixir$ElixirScript$Kernel from '../elixir/Elixir.ElixirScript.Kernel'; + import Elixir$Animals$Elephant from '../app/Elixir.Animals.Elephant'; const something = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.clause([],function() { return Elixir$Animals$Elephant.Elixir$Animals$Elephant.create(Object.freeze({})); })); @@ -88,8 +88,8 @@ defmodule ElixirScript.Test do """, hd(js_code) assert_js_matches """ - import Elixir from './Elixir'; - import Elixir$ElixirScript$Kernel from './Elixir.ElixirScript.Kernel'; + import Elixir from '../elixir/Elixir'; + import Elixir$ElixirScript$Kernel from '../elixir/Elixir.ElixirScript.Kernel'; const Elixir$Animals$Elephant = Elixir.Core.Functions.defstruct({ [Symbol.for('__struct__')]: Symbol.for('Elixir.Animals.Elephant'), [Symbol.for('trunk')]: true @@ -115,8 +115,8 @@ defmodule ElixirScript.Test do """, %{ env: make_custom_env }) assert_js_matches """ - import Elixir from './Elixir'; - import Elixir$ElixirScript$Kernel from './Elixir.ElixirScript.Kernel'; + import Elixir from '../elixir/Elixir'; + import Elixir$ElixirScript$Kernel from '../elixir/Elixir.ElixirScript.Kernel'; const something_else = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.clause([],function() { return 1 * 1; })); @@ -144,8 +144,8 @@ defmodule ElixirScript.Test do """, %{ env: make_custom_env, core_path: "elixirscript"} ) assert_js_matches """ - import Elixir from './elixirscript'; - import Elixir$ElixirScript$Kernel from './Elixir.ElixirScript.Kernel'; + import Elixir from '../elixir/elixirscript'; + import Elixir$ElixirScript$Kernel from '../elixir/Elixir.ElixirScript.Kernel'; const something_else = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.clause([],function() { return 1 * 1; })); diff --git a/test/translator/bug_test.exs b/test/translator/bug_test.exs index 296daf69..cfb474bc 100644 --- a/test/translator/bug_test.exs +++ b/test/translator/bug_test.exs @@ -47,7 +47,7 @@ defmodule ElixirScript.Translator.Bug.Test do js_code = """ import JQuery from 'jquery'; - import Elixir$ElixirScript$Kernel from './Elixir.ElixirScript.Kernel'; + import Elixir$ElixirScript$Kernel from '../elixir/Elixir.ElixirScript.Kernel'; JQuery(Elixir.Core.Functions.call_property(e,'target')); export default {}; """ diff --git a/test/translator/defmodule_test.exs b/test/translator/defmodule_test.exs index 165946dd..b157b680 100644 --- a/test/translator/defmodule_test.exs +++ b/test/translator/defmodule_test.exs @@ -9,7 +9,7 @@ defmodule ElixirScript.Translator.Defmodule.Test do end js_code = """ - import Elixir$ElixirScript$Kernel from './Elixir.ElixirScript.Kernel'; + import Elixir$ElixirScript$Kernel from '../elixir/Elixir.ElixirScript.Kernel'; export default {}; """ @@ -32,7 +32,7 @@ defmodule ElixirScript.Translator.Defmodule.Test do js_code = """ - import Elixir$ElixirScript$Kernel from './Elixir.ElixirScript.Kernel'; + import Elixir$ElixirScript$Kernel from '../elixir/Elixir.ElixirScript.Kernel'; const something_else = Elixir.Core.Patterns.defmatchgen(Elixir.Core.Patterns.clause([],function*() { return null; })); @@ -67,8 +67,8 @@ defmodule ElixirScript.Translator.Defmodule.Test do end js_code = """ - import Elixir$ElixirScript$Kernel from './Elixir.ElixirScript.Kernel'; - import Elixir$Animals$Elephant from './Elixir.Animals.Elephant'; + import Elixir$ElixirScript$Kernel from '../elixir/Elixir.ElixirScript.Kernel'; + import Elixir$Animals$Elephant from '../app/Elixir.Animals.Elephant'; const something_else = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.clause([],function() { return null; })); @@ -81,7 +81,7 @@ defmodule ElixirScript.Translator.Defmodule.Test do something }; - import Elixir$ElixirScript$Kernel from './Elixir.ElixirScript.Kernel'; + import Elixir$ElixirScript$Kernel from '../elixir/Elixir.ElixirScript.Kernel'; const Elixir$Animals$Elephant = Elixir.Core.Functions.defstruct({ [Symbol.for('__struct__')]: Symbol.for('Elixir.Animals.Elephant'), [Symbol.for('trunk')]: true }); @@ -119,8 +119,8 @@ defmodule ElixirScript.Translator.Defmodule.Test do end js_code = """ - import Elixir$ElixirScript$Kernel from './Elixir.ElixirScript.Kernel'; - import Elixir$Animals$Elephant from './Elixir.Animals.Elephant'; + import Elixir$ElixirScript$Kernel from '../elixir/Elixir.ElixirScript.Kernel'; + import Elixir$Animals$Elephant from '../app/Elixir.Animals.Elephant'; const something_else = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.clause([],function() { return null; })); @@ -132,8 +132,8 @@ defmodule ElixirScript.Translator.Defmodule.Test do something }; - import Elixir$ElixirScript$Kernel from './Elixir.ElixirScript.Kernel'; - import Elixir$Animals$Elephant$Bear from './Elixir.Animals.Elephant.Bear'; + import Elixir$ElixirScript$Kernel from '../elixir/Elixir.ElixirScript.Kernel'; + import Elixir$Animals$Elephant$Bear from '../app/Elixir.Animals.Elephant.Bear'; const Elixir$Animals$Elephant = Elixir.Core.Functions.defstruct({ [Symbol.for('__struct__')]: Symbol.for('Elixir.Animals.Elephant'), [Symbol.for('trunk')]: true @@ -142,7 +142,7 @@ defmodule ElixirScript.Translator.Defmodule.Test do Elixir$Animals$Elephant }; - import Elixir$ElixirScript$Kernel from './Elixir.ElixirScript.Kernel'; + import Elixir$ElixirScript$Kernel from '../elixir/Elixir.ElixirScript.Kernel'; const Elixir$Animals$Elephant$Bear = Elixir.Core.Functions.defstruct({ [Symbol.for('__struct__')]: Symbol.for('Elixir.Animals.Elephant.Bear'), [Symbol.for('trunk')]: true @@ -168,12 +168,12 @@ defmodule ElixirScript.Translator.Defmodule.Test do end js_code = """ - import Elixir$ElixirScript$Kernel from './Elixir.ElixirScript.Kernel'; - import Elixir$Lions$Tigers from './Elixir.Lions.Tigers'; + import Elixir$ElixirScript$Kernel from '../elixir/Elixir.ElixirScript.Kernel'; + import Elixir$Lions$Tigers from '../app/Elixir.Lions.Tigers'; Elixir.Core.Functions.call_property(Elixir$Lions$Tigers,'oh_my'); export default {}; - import Elixir$ElixirScript$Kernel from './Elixir.ElixirScript.Kernel'; + import Elixir$ElixirScript$Kernel from '../elixir/Elixir.ElixirScript.Kernel'; Elixir.Core.Functions.call_property(Lions.Tigers.Bears,'oh_my'); export default {}; """ @@ -198,12 +198,12 @@ defmodule ElixirScript.Translator.Defmodule.Test do end js_code = """ - import Elixir$ElixirScript$Kernel from './Elixir.ElixirScript.Kernel'; - import Elixir$Lions$Tigers from './Elixir.Lions.Tigers'; + import Elixir$ElixirScript$Kernel from '../elixir/Elixir.ElixirScript.Kernel'; + import Elixir$Lions$Tigers from '../app/Elixir.Lions.Tigers'; Elixir.Core.Functions.call_property(Elixir$Lions$Tigers,'oh_my'); export default {}; - import Elixir$ElixirScript$Kernel from './Elixir.ElixirScript.Kernel'; + import Elixir$ElixirScript$Kernel from '../elixir/Elixir.ElixirScript.Kernel'; const oh_my = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.clause([],function() { return null; })); @@ -234,12 +234,12 @@ defmodule ElixirScript.Translator.Defmodule.Test do end js_code = """ - import Elixir$ElixirScript$Kernel from './Elixir.ElixirScript.Kernel'; - import Elixir$Lions$Tigers from './Elixir.Lions.Tigers'; + import Elixir$ElixirScript$Kernel from '../elixir/Elixir.ElixirScript.Kernel'; + import Elixir$Lions$Tigers from '../app/Elixir.Lions.Tigers'; Elixir$Lions$Tigers.oh_my(); export default {}; - import Elixir$ElixirScript$Kernel from './Elixir.ElixirScript.Kernel'; + import Elixir$ElixirScript$Kernel from '../elixir/Elixir.ElixirScript.Kernel'; const oh_my2 = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.clause([],function() { return null; })); @@ -274,12 +274,12 @@ defmodule ElixirScript.Translator.Defmodule.Test do end js_code = """ - import Elixir$ElixirScript$Kernel from './Elixir.ElixirScript.Kernel'; - import Elixir$Lions$Tigers from './Elixir.Lions.Tigers'; + import Elixir$ElixirScript$Kernel from '../elixir/Elixir.ElixirScript.Kernel'; + import Elixir$Lions$Tigers from '../app/Elixir.Lions.Tigers'; Elixir$Lions$Tigers.oh_my2(); export default {}; - import Elixir$ElixirScript$Kernel from './Elixir.ElixirScript.Kernel'; + import Elixir$ElixirScript$Kernel from '../elixir/Elixir.ElixirScript.Kernel'; const oh_my2 = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.clause([],function() { return null; })); @@ -312,17 +312,17 @@ defmodule ElixirScript.Translator.Defmodule.Test do end js_code = """ - import Elixir$ElixirScript$Kernel from './Elixir.ElixirScript.Kernel'; - import Elixir$Version$Parser from './Elixir.Version.Parser'; - import Elixir$Version$Parser$DSL from './Elixir.Version.Parser.DSL'; + import Elixir$ElixirScript$Kernel from '../elixir/Elixir.ElixirScript.Kernel'; + import Elixir$Version$Parser from '../app/Elixir.Version.Parser'; + import Elixir$Version$Parser$DSL from '../app/Elixir.Version.Parser.DSL'; export default {}; - import Elixir$ElixirScript$Kernel from './Elixir.ElixirScript.Kernel'; - import Elixir$Version$Parser$DSL from './Elixir.Version.Parser.DSL'; + import Elixir$ElixirScript$Kernel from '../elixir/Elixir.ElixirScript.Kernel'; + import Elixir$Version$Parser$DSL from '../app/Elixir.Version.Parser.DSL'; export default {}; - import Elixir$ElixirScript$Kernel from './Elixir.ElixirScript.Kernel'; - import Elixir$Version$Parser from './Elixir.Version.Parser'; + import Elixir$ElixirScript$Kernel from '../elixir/Elixir.ElixirScript.Kernel'; + import Elixir$Version$Parser from '../app/Elixir.Version.Parser'; export default {}; """ diff --git a/test/translator/function_test.exs b/test/translator/function_test.exs index 7a01af3c..a8986098 100644 --- a/test/translator/function_test.exs +++ b/test/translator/function_test.exs @@ -239,7 +239,7 @@ defmodule ElixirScript.Translator.Function.Test do end js_code = """ - import Elixir$ElixirScript$Kernel from './Elixir.ElixirScript.Kernel'; + import Elixir$ElixirScript$Kernel from '../elixir/Elixir.ElixirScript.Kernel'; const example = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.clause([],function() { return null; }),Elixir.Core.Patterns.clause([Elixir.Core.Patterns.variable()],function(oneArg) { @@ -276,7 +276,7 @@ defmodule ElixirScript.Translator.Function.Test do end js_code = """ - import Elixir$ElixirScript$Kernel from './Elixir.ElixirScript.Kernel'; + import Elixir$ElixirScript$Kernel from '../elixir/Elixir.ElixirScript.Kernel'; const example = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.clause([],function() { return null; }),Elixir.Core.Patterns.clause([Elixir.Core.Patterns.variable()],function(oneArg) { @@ -303,7 +303,7 @@ defmodule ElixirScript.Translator.Function.Test do end js_code = """ - import Elixir$ElixirScript$Kernel from './Elixir.ElixirScript.Kernel'; + import Elixir$ElixirScript$Kernel from '../elixir/Elixir.ElixirScript.Kernel'; const example = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.clause([Elixir.Core.Patterns.variable()],function(oneArg) { return null; })); @@ -421,7 +421,7 @@ defmodule ElixirScript.Translator.Function.Test do end js_code = """ - import Elixir$ElixirScript$Kernel from './Elixir.ElixirScript.Kernel'; + import Elixir$ElixirScript$Kernel from '../elixir/Elixir.ElixirScript.Kernel'; const something = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.clause([Elixir.Core.Patterns.variable()],function(one) { return null; },function(one) { @@ -652,7 +652,7 @@ defmodule ElixirScript.Translator.Function.Test do js_code = """ - import Elixir$ElixirScript$Kernel from './Elixir.ElixirScript.Kernel'; + import Elixir$ElixirScript$Kernel from '../elixir/Elixir.ElixirScript.Kernel'; const something = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.clause([1],function() { return null; }),Elixir.Core.Patterns.clause([2],function() { diff --git a/test/translator/protocol_test.exs b/test/translator/protocol_test.exs index c72a5527..6b20ad77 100644 --- a/test/translator/protocol_test.exs +++ b/test/translator/protocol_test.exs @@ -25,8 +25,8 @@ defmodule ElixirScript.Translator.Defprotocol.Test do end js_code = """ - import Elixir$ElixirScript$Kernel from './Elixir.ElixirScript.Kernel'; - import Implementations from './Elixir.Blank.Defimpl'; + import Elixir$ElixirScript$Kernel from '../elixir/Elixir.ElixirScript.Kernel'; + import Implementations from '../app/Elixir.Blank.Defimpl'; const Elixir$Blank = Elixir.Core.Functions.defprotocol({ blank__qmark__: function() { @@ -35,7 +35,7 @@ defmodule ElixirScript.Translator.Defprotocol.Test do for(let {Type,Implementation} of Implementations) Elixir.Core.Functions.defimpl(Elixir$Blank,Type,Implementation) export default Elixir$Blank; - import Elixir$ElixirScript$Kernel from './Elixir.ElixirScript.Kernel'; + import Elixir$ElixirScript$Kernel from '../elixir/Elixir.ElixirScript.Kernel'; const blank__qmark__ = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.clause([false],function() { return true; }),Elixir.Core.Patterns.clause([null],function() { @@ -49,7 +49,7 @@ defmodule ElixirScript.Translator.Defprotocol.Test do } }; - import Elixir$ElixirScript$Kernel from './Elixir.ElixirScript.Kernel'; + import Elixir$ElixirScript$Kernel from '../elixir/Elixir.ElixirScript.Kernel'; const blank__qmark__ = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.clause([Elixir.Core.Patterns.variable()],function(number) { return false; })); @@ -59,7 +59,7 @@ defmodule ElixirScript.Translator.Defprotocol.Test do } }; - import Elixir$ElixirScript$Kernel from './Elixir.ElixirScript.Kernel'; + import Elixir$ElixirScript$Kernel from '../elixir/Elixir.ElixirScript.Kernel'; const blank__qmark__ = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.clause([Object.freeze([])],function() { return true; }),Elixir.Core.Patterns.clause([Elixir.Core.Patterns.wildcard()],function() { @@ -73,13 +73,13 @@ defmodule ElixirScript.Translator.Defprotocol.Test do - import Elixir from './Elixir'; + import Elixir from '../elixir/Elixir'; let impls = []; - import Elixir$Blank$DefImpl$Elixir$Atom from './Elixir.Blank.DefImpl.Elixir.Atom'; + import Elixir$Blank$DefImpl$Elixir$Atom from '../app/Elixir.Blank.DefImpl.Elixir.Atom'; impls.push(Elixir$Blank$DefImpl$Elixir$Atom) - import Elixir$Blank$DefImpl$Elixir$Integer from './Elixir.Blank.DefImpl.Elixir.Integer'; + import Elixir$Blank$DefImpl$Elixir$Integer from '../app/Elixir.Blank.DefImpl.Elixir.Integer'; impls.push(Elixir$Blank$DefImpl$Elixir$Integer) - import Elixir$Blank$DefImpl$Elixir$List from './Elixir.Blank.DefImpl.Elixir.List'; + import Elixir$Blank$DefImpl$Elixir$List from '../app/Elixir.Blank.DefImpl.Elixir.List'; impls.push(Elixir$Blank$DefImpl$Elixir$List) export default impls; """ diff --git a/test/translator/struct_test.exs b/test/translator/struct_test.exs index f92a84d8..3821aa54 100644 --- a/test/translator/struct_test.exs +++ b/test/translator/struct_test.exs @@ -10,7 +10,7 @@ defmodule ElixirScript.Translator.Struct.Test do end js_code = """ - import Elixir$ElixirScript$Kernel from './Elixir.ElixirScript.Kernel'; + import Elixir$ElixirScript$Kernel from '../elixir/Elixir.ElixirScript.Kernel'; const Elixir$User = Elixir.Core.Functions.defstruct({ [Symbol.for('__struct__')]: Symbol.for('Elixir.User'), [Symbol.for('name')]: 'john', @@ -34,7 +34,7 @@ defmodule ElixirScript.Translator.Struct.Test do end js_code = """ - import Elixir$ElixirScript$Kernel from './Elixir.ElixirScript.Kernel'; + import Elixir$ElixirScript$Kernel from '../elixir/Elixir.ElixirScript.Kernel'; const Elixir$User = Elixir.Core.Functions.defstruct({ [Symbol.for('__struct__')]: Symbol.for('Elixir.User'), [Symbol.for('name')]: null, @@ -61,7 +61,7 @@ defmodule ElixirScript.Translator.Struct.Test do js_code = """ let [user] = Elixir.Core.Patterns.match(Elixir.Core.Patterns.variable(), Elixir$User.Elixir$User.create(Object.freeze({}))); - import Elixir$ElixirScript$Kernel from './Elixir.ElixirScript.Kernel'; + import Elixir$ElixirScript$Kernel from '../elixir/Elixir.ElixirScript.Kernel'; const Elixir$User = Elixir.Core.Functions.defstruct({ [Symbol.for('__struct__')]: Symbol.for('Elixir.User'), [Symbol.for('name')]: null, @@ -88,7 +88,7 @@ defmodule ElixirScript.Translator.Struct.Test do [Symbol.for('name')]: 'John' }))); - import Elixir$ElixirScript$Kernel from './Elixir.ElixirScript.Kernel'; + import Elixir$ElixirScript$Kernel from '../elixir/Elixir.ElixirScript.Kernel'; const Elixir$User = Elixir.Core.Functions.defstruct({ [Symbol.for('__struct__')]: Symbol.for('Elixir.User'), [Symbol.for('name')]: null, @@ -137,7 +137,7 @@ defmodule ElixirScript.Translator.Struct.Test do end js_code = """ - import Elixir$ElixirScript$Kernel from './Elixir.ElixirScript.Kernel'; + import Elixir$ElixirScript$Kernel from '../elixir/Elixir.ElixirScript.Kernel'; const Elixir$MyAppError = Elixir.Core.Functions.defexception({ [Symbol.for('__struct__')]: Symbol.for('Elixir.MyAppError'), [Symbol.for('__exception__')]: true, @@ -157,7 +157,7 @@ defmodule ElixirScript.Translator.Struct.Test do end js_code = """ - import Elixir$ElixirScript$Kernel from './Elixir.ElixirScript.Kernel'; + import Elixir$ElixirScript$Kernel from '../elixir/Elixir.ElixirScript.Kernel'; const Elixir$MyAppError = Elixir.Core.Functions.defexception({ [Symbol.for('__struct__')]: Symbol.for('Elixir.MyAppError'), [Symbol.for('__exception__')]: true, @@ -187,7 +187,7 @@ defmodule ElixirScript.Translator.Struct.Test do [Symbol.for('message')]: 'did not get what was expected' })); -import Elixir$ElixirScript$Kernel from './Elixir.ElixirScript.Kernel'; + import Elixir$ElixirScript$Kernel from '../elixir/Elixir.ElixirScript.Kernel'; const Elixir$MyAppError = Elixir.Core.Functions.defexception({ [Symbol.for('__struct__')]: Symbol.for('Elixir.MyAppError'), [Symbol.for('__exception__')]: true, From e9538289f19880cdf47a4faa8d8b527cefe77556 Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Thu, 13 Oct 2016 21:43:31 -0500 Subject: [PATCH 300/860] Fixed copy_stdlib_to_destination for new path structure --- lib/elixir_script.ex | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/lib/elixir_script.ex b/lib/elixir_script.ex index 981ed78e..dbec3f35 100644 --- a/lib/elixir_script.ex +++ b/lib/elixir_script.ex @@ -369,9 +369,10 @@ defmodule ElixirScript do to the specified location """ def copy_stdlib_to_destination(destination) do - Enum.each(Path.wildcard(Path.join([operating_path, "*.js"])), fn(path) -> + Enum.each(Path.wildcard(Path.join([operating_path, "elixir", "*.js"])), fn(path) -> base = Path.basename(path) - File.cp!(path, Path.join([destination, base])) + File.mkdir_p!(Path.join([destination, "elixir"])) + File.cp!(path, Path.join([destination, "elixir", base])) end) end From b3cde0e78b274a6027461c95c73b45273b4f650a Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Fri, 14 Oct 2016 23:00:37 -0500 Subject: [PATCH 301/860] Flattening out deps --- lib/elixir_script.ex | 6 ++++++ lib/elixir_script/compiler/deps.ex | 12 +++++++++--- 2 files changed, 15 insertions(+), 3 deletions(-) diff --git a/lib/elixir_script.ex b/lib/elixir_script.ex index dbec3f35..cd5b3fa7 100644 --- a/lib/elixir_script.ex +++ b/lib/elixir_script.ex @@ -80,6 +80,12 @@ defmodule ElixirScript do {[path], []} end + #deps = if Code.ensure_loaded?(Mix) do + # ElixirScript.Compiler.Deps.get_deps_paths + #else + # [] + #end + opts = build_compiler_options(opts) compiler_cache = get_compiler_cache(path, opts) diff --git a/lib/elixir_script/compiler/deps.ex b/lib/elixir_script/compiler/deps.ex index 30bc0d74..42d3410f 100644 --- a/lib/elixir_script/compiler/deps.ex +++ b/lib/elixir_script/compiler/deps.ex @@ -2,14 +2,20 @@ defmodule ElixirScript.Compiler.Deps do alias ElixirScript.Translator.Utils def get_deps_paths(env \\ Mix.env) do - deps = Mix.Dep.loaded([env: "env"]) + Mix.Dep.loaded([env: env]) + |> do_get_deps_paths + end - Enum.reduce(deps, Map.new, fn(dep, map) -> + defp do_get_deps_paths(deps) do + Enum.reduce(deps, [], fn(dep, list) -> paths = Mix.Project.in_project dep.app, dep.opts[:dest], fn mixfile -> Mix.Project.config()[:elixirc_paths] end paths = Enum.map(paths, fn path -> Path.join([dep.opts[:dest], path]) end) - Map.put(map, dep.app, paths) + deps = do_get_deps_paths(dep.deps) + + deps ++ [{dep.app, paths}] ++ list end) + |> Enum.uniq end def get_module_filepath_map(env \\ Mix.env) do From f639a3c6b63fef06f50d5761098abdcd7161b14e Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Sat, 15 Oct 2016 10:08:00 -0500 Subject: [PATCH 302/860] Removed hardcoded references to :app or :elxiir --- lib/elixir_script.ex | 22 ++++++++----------- .../translator/kernel/defmodule.ex | 4 ++-- 2 files changed, 11 insertions(+), 15 deletions(-) diff --git a/lib/elixir_script.ex b/lib/elixir_script.ex index cd5b3fa7..3478b1b0 100644 --- a/lib/elixir_script.ex +++ b/lib/elixir_script.ex @@ -73,6 +73,8 @@ defmodule ElixirScript do @spec compile_path(binary, Map.t) :: [binary | {binary, binary} | :ok] def compile_path(path, opts \\ %{}) do + opts = build_compiler_options(opts) + {expanded_path, loaded_modules} = case File.dir?(path) do true -> process_path(path) @@ -80,16 +82,7 @@ defmodule ElixirScript do {[path], []} end - #deps = if Code.ensure_loaded?(Mix) do - # ElixirScript.Compiler.Deps.get_deps_paths - #else - # [] - #end - - opts = build_compiler_options(opts) - compiler_cache = get_compiler_cache(path, opts) - new_file_stats = Cache.build_file_stats(expanded_path) changed_files = Cache.get_changed_files(compiler_cache.input_files, new_file_stats) @@ -182,7 +175,7 @@ defmodule ElixirScript do @doc false def compile_std_lib(output_path) do - compiler_opts = build_compiler_options(%{std_lib: true, include_path: true, output: output_path}) + compiler_opts = build_compiler_options(%{std_lib: true, include_path: true, output: output_path, app: :elixir}) libs_path = Path.join([__DIR__, "elixir_script", "prelude", "**", "*.ex"]) code = Path.wildcard(libs_path) @@ -192,14 +185,16 @@ defmodule ElixirScript do code |> Enum.map(&update_quoted(&1)) - |> ModuleCollector.process_modules(:elixir) + |> ModuleCollector.process_modules(compiler_opts[:app]) code = create_code(compiler_opts, ElixirScript.Translator.State.get) |> Enum.filter(fn({path, _, _}) -> !String.contains?(path, "ElixirScript.Temp.js") end) new_std_state = ElixirScript.Translator.State.serialize() - File.write!(File.cwd!() <> "/lib/elixir_script/translator/stdlib_state.bin", new_std_state) + stdlib_state_path = Path.join([File.cwd!(), "lib", "elixir_script", "translator", "stdlib_state.bin"]) + + File.write!(stdlib_state_path, new_std_state) result = Output.out(libs_path, code, compiler_opts) ElixirScript.Translator.State.stop @@ -215,7 +210,7 @@ defmodule ElixirScript do quoted_code_list |> Enum.map(&update_quoted(&1)) - |> ModuleCollector.process_modules(:app) + |> ModuleCollector.process_modules(compiler_opts[:app]) code = create_code(compiler_opts, ElixirScript.Translator.State.get) new_state = ElixirScript.Translator.State.serialize() @@ -232,6 +227,7 @@ defmodule ElixirScript do |> Map.put(:core_path, "Elixir") |> Map.put(:full_build, false) |> Map.put(:output, nil) + |> Map.put(:app, :app) Map.merge(default_options, opts) end diff --git a/lib/elixir_script/translator/kernel/defmodule.ex b/lib/elixir_script/translator/kernel/defmodule.ex index 77801a81..5c985512 100644 --- a/lib/elixir_script/translator/kernel/defmodule.ex +++ b/lib/elixir_script/translator/kernel/defmodule.ex @@ -11,11 +11,11 @@ defmodule ElixirScript.Translator.Defmodule do def make_module(ElixirScript.Temp, body, env) do { body, _ } = translate_body(body, env) - %{ name: ElixirScript.Temp, body: body |> Group.inflate_groups, app_name: :app } + %{ name: ElixirScript.Temp, body: body |> Group.inflate_groups, app_name: ElixirScript.Translator.State.get().compiler_opts.app } end def make_module(module, nil, _) do - %{ name: module, body: [], app_name: :app } + %{ name: module, body: [], app_name: ElixirScript.Translator.State.get().compiler_opts.app } end def make_module(module, body, env) do From 8a930e0a11f6c8241ffa8894fb282aa2c999fec2 Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Sat, 15 Oct 2016 10:42:11 -0500 Subject: [PATCH 303/860] updated module file path structure --- lib/elixir_script/compiler/deps.ex | 34 +++++++++++++++--------------- 1 file changed, 17 insertions(+), 17 deletions(-) diff --git a/lib/elixir_script/compiler/deps.ex b/lib/elixir_script/compiler/deps.ex index 42d3410f..8602e37e 100644 --- a/lib/elixir_script/compiler/deps.ex +++ b/lib/elixir_script/compiler/deps.ex @@ -21,54 +21,54 @@ defmodule ElixirScript.Compiler.Deps do def get_module_filepath_map(env \\ Mix.env) do deps_paths = get_deps_paths(env) - Enum.reduce(deps_paths, Map.new, fn({dep, paths}, map) -> + Enum.reduce(deps_paths, [], fn({dep, paths}, list) -> file_paths = Enum.flat_map(paths, fn(path) -> path = Path.join(path, "**/*.{ex,exs,exjs}") |> Path.wildcard end) - file_paths = Enum.reduce(file_paths, Map.new, fn(path, map) -> + file_paths = Enum.reduce(file_paths, [], fn(path, list) -> quoted = path |> File.read! |> Code.string_to_quoted! - { _, modules } = Macro.postwalk(quoted, %{protocols: [], modules: [], impls: []}, &get_defmodules(&1, &2)) + { _, modules } = Macro.postwalk(quoted, [], &get_defmodules(&1, &2)) - { path, modules } - Map.put(map, path, modules) + modules = Enum.map(modules, fn(x) -> { x.module, Map.put(x, :path, path) |> Map.put(:app, dep) } end) + list ++ modules end) - {dep, file_paths} - Map.put(map, dep, file_paths) + + list ++ file_paths end) end defp get_defmodules({:defprotocol, _, [{:__aliases__, _, _} = the_alias, _]} = ast, state) do - state = Map.update!(state, :protocols, fn(l) -> [ Utils.quoted_to_name(the_alias) | l ] end) - { ast, state } + s = %{ module: Utils.quoted_to_name(the_alias), type: :protocol } + { ast, state ++ [s] } end defp get_defmodules({:defprotocol, _, [{:__aliases__, _, _} = the_alias, _]} = ast, state) do - state = Map.update!(state, :protocols, fn(l) -> [ Utils.quoted_to_name(the_alias) | l ] end) - { ast, state } + s = %{module: Utils.quoted_to_name(the_alias), type: :protocol } + { ast, state ++ [s] } end defp get_defmodules({:defimpl, _, [ {:__aliases__, _, _} = the_alias, [for: type], _ ]} = ast, state) do - state = Map.update!(state, :impls, fn(l) -> [ { Utils.quoted_to_name(the_alias), Utils.quoted_to_name(type) } | l ] end) - { ast, state } + s = %{module: Utils.quoted_to_name(the_alias), type: :impl, for: Utils.quoted_to_name(type) } + { ast, state ++ [s] } end defp get_defmodules({:defimpl, _, [ {:__aliases__, _, _} = the_alias, [for: type], _ ]} = ast, state) do - state = Map.update!(state, :impls, fn(l) -> [ { Utils.quoted_to_name(the_alias), Utils.quoted_to_name(type) } | l ] end) - { ast, state } + s = %{module: Utils.quoted_to_name(the_alias), type: :impl, for: Utils.quoted_to_name(type) } + { ast, state ++ [s] } end defp get_defmodules({:defmodule, _, [{:__aliases__, _, _} = the_alias, [do: _]]} = ast, state) do - state = Map.update!(state, :modules, fn(l) -> [ Utils.quoted_to_name(the_alias) | l ] end) - { ast, state } + s = %{module: Utils.quoted_to_name(the_alias), type: :module } + { ast, state ++ [s] } end defp get_defmodules(ast, state) do From b065614c3ade8a10e2ba5337314546174897ce35 Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Sat, 15 Oct 2016 14:00:34 -0500 Subject: [PATCH 304/860] Add more functions to find, track, and remove unneeded deps from compilation --- lib/elixir_script.ex | 11 +++ lib/elixir_script/compiler/deps.ex | 106 ++++++++++++++++++++++++++--- 2 files changed, 109 insertions(+), 8 deletions(-) diff --git a/lib/elixir_script.ex b/lib/elixir_script.ex index 3478b1b0..18868554 100644 --- a/lib/elixir_script.ex +++ b/lib/elixir_script.ex @@ -75,6 +75,17 @@ defmodule ElixirScript do opts = build_compiler_options(opts) + paths = if Code.ensure_loaded?(Mix) do + deps = ElixirScript.Compiler.Deps.get_deps_paths(Mix.env) + deps ++ [{opts[:app], [path]}] + else + [{opts[:app], [path]}] + end + + paths = ElixirScript.Compiler.Deps.get_module_filepath_map(paths) + + + {expanded_path, loaded_modules} = case File.dir?(path) do true -> process_path(path) diff --git a/lib/elixir_script/compiler/deps.ex b/lib/elixir_script/compiler/deps.ex index 8602e37e..24dc5fd2 100644 --- a/lib/elixir_script/compiler/deps.ex +++ b/lib/elixir_script/compiler/deps.ex @@ -18,9 +18,7 @@ defmodule ElixirScript.Compiler.Deps do |> Enum.uniq end - def get_module_filepath_map(env \\ Mix.env) do - deps_paths = get_deps_paths(env) - + def get_module_filepath_map(deps_paths) do Enum.reduce(deps_paths, [], fn({dep, paths}, list) -> file_paths = Enum.flat_map(paths, fn(path) -> @@ -33,6 +31,7 @@ defmodule ElixirScript.Compiler.Deps do |> File.read! |> Code.string_to_quoted! + #TODO: build sumbmodules correctly { _, modules } = Macro.postwalk(quoted, [], &get_defmodules(&1, &2)) modules = Enum.map(modules, fn(x) -> { x.module, Map.put(x, :path, path) |> Map.put(:app, dep) } end) @@ -47,27 +46,27 @@ defmodule ElixirScript.Compiler.Deps do defp get_defmodules({:defprotocol, _, [{:__aliases__, _, _} = the_alias, _]} = ast, state) do - s = %{ module: Utils.quoted_to_name(the_alias), type: :protocol } + s = %{ module: Utils.quoted_to_name(the_alias), type: :protocol, ast: ast } { ast, state ++ [s] } end defp get_defmodules({:defprotocol, _, [{:__aliases__, _, _} = the_alias, _]} = ast, state) do - s = %{module: Utils.quoted_to_name(the_alias), type: :protocol } + s = %{module: Utils.quoted_to_name(the_alias), type: :protocol, ast: ast } { ast, state ++ [s] } end defp get_defmodules({:defimpl, _, [ {:__aliases__, _, _} = the_alias, [for: type], _ ]} = ast, state) do - s = %{module: Utils.quoted_to_name(the_alias), type: :impl, for: Utils.quoted_to_name(type) } + s = %{module: Utils.quoted_to_name(the_alias), type: :impl, for: Utils.quoted_to_name(type), ast: ast } { ast, state ++ [s] } end defp get_defmodules({:defimpl, _, [ {:__aliases__, _, _} = the_alias, [for: type], _ ]} = ast, state) do - s = %{module: Utils.quoted_to_name(the_alias), type: :impl, for: Utils.quoted_to_name(type) } + s = %{module: Utils.quoted_to_name(the_alias), type: :impl, for: Utils.quoted_to_name(type), ast: ast } { ast, state ++ [s] } end defp get_defmodules({:defmodule, _, [{:__aliases__, _, _} = the_alias, [do: _]]} = ast, state) do - s = %{module: Utils.quoted_to_name(the_alias), type: :module } + s = %{module: Utils.quoted_to_name(the_alias), type: :module, ast: ast } { ast, state ++ [s] } end @@ -75,4 +74,95 @@ defmodule ElixirScript.Compiler.Deps do { ast, state } end + def find_dependencies(module_filepath_map) do + Enum.map(module_filepath_map, &do_find_dependencies(&1)) + end + + defp do_find_dependencies({ module, module_data }) do + {_, deps} = Macro.prewalk(module_data.ast, [], &collect_references(&1, &2)) + { module, Map.put(module_data, :deps, deps) } + end + + defp collect_references({:import, _, [{{:., _, [{:__aliases__, _, head_import_name}, :{}]}, _, tail_imports }]}, state) do + deps = Enum.map(tail_imports, fn({:__aliases__, context, name}) -> + full_module_name = { :__aliases__, context, head_import_name ++ name } + Utils.quoted_to_name(full_module_name) + end) + + state ++ deps + end + + defp collect_references({:import, _, [{:__aliases__, _, _} = module_name]} = ast, state) do + module_name = Utils.quoted_to_name(module_name) + { ast, state ++ [module_name] } + end + + defp collect_references({:import, _, [{:__aliases__, _, _} = module_name, _]} = ast, state) do + module_name = Utils.quoted_to_name(module_name) + {ast, state ++ [module_name] } + end + + defp collect_references({:alias, _, [{{:., _, [{:__aliases__, _, head_alias_name}, :{}]}, _, tail_aliases }]} = ast, state) do + deps = Enum.map(tail_aliases, fn({:__aliases__, context, name}) -> + full_module_name = { :__aliases__, context, head_alias_name ++ name } + Utils.quoted_to_name(full_module_name) + end) + + { ast, state ++ deps } + end + + defp collect_references({:alias, _, [{:__aliases__, _, _} = module_name] } = ast, state) do + module_name = Utils.quoted_to_name(module_name) + { ast, state ++ [module_name] } + end + + defp collect_references({:alias, _, [{:__aliases__, _, _} = module_name, _]} = ast, state) do + module_name = Utils.quoted_to_name(module_name) + {ast, state ++ [module_name] } + end + + defp collect_references({:require, _, [{{:., _, [{:__aliases__, _, head_alias_name}, :{}]}, _, tail_aliases }]} = ast, state) do + deps = Enum.map(tail_aliases, fn({:__aliases__, context, name}) -> + full_module_name = { :__aliases__, context, head_alias_name ++ name } + Utils.quoted_to_name(full_module_name) + end) + + { ast, state ++ deps } + end + + defp collect_references({:require, _, [{:__aliases__, _, _} = module_name] } = ast, state) do + module_name = Utils.quoted_to_name(module_name) + { ast, state ++ [module_name] } + end + + defp collect_references({:require, _, [{:__aliases__, _, _} = module_name, _]} = ast, state) do + module_name = Utils.quoted_to_name(module_name) + { ast, state ++ [module_name] } + end + + defp collect_references({:., _, [{:__aliases__, _, _} = module_name, _]} = ast, state) do + module_name = Utils.quoted_to_name(module_name) + { ast, state ++ [module_name] } + end + + defp collect_references({{:., _, [{:__aliases__, _, _} = module_name, _]}, _, _ } = ast, state) do + module_name = Utils.quoted_to_name(module_name) + { ast, state ++ [module_name] } + end + + defp collect_references(ast, state) do + { ast, state } + end + + def remove_modules_not_depended_on(module_filepath_map, apps_not_to_touch) do + Enum.filter(module_filepath_map, fn({module_name, _}) -> + module_found_in_deps(module_name, module_filepath_map, List.wrap(apps_not_to_touch)) == true + end) + end + + defp module_found_in_deps(module_name, module_filepath_map, apps_not_to_touch) do + Enum.any?(module_filepath_map, fn({_, %{deps: deps, app: app}}) -> + Enum.member?(apps_not_to_touch, app) or Enum.member?(deps, module_name) + end) + end end From 4ac49d6fd94c3beaefc2d3170c3f444782e5a33a Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Sat, 15 Oct 2016 17:49:39 -0500 Subject: [PATCH 305/860] Adding compiler passes to simplify compilation --- lib/elixir_script.ex | 19 +-- lib/elixir_script/compiler/deps.ex | 168 ------------------- lib/elixir_script/passes/deps_paths.ex | 30 ++++ lib/elixir_script/passes/find_deps.ex | 85 ++++++++++ lib/elixir_script/passes/find_functions.ex | 77 +++++++++ lib/elixir_script/passes/java_script_ast.ex | 29 ++++ lib/elixir_script/passes/java_script_code.ex | 41 +++++ lib/elixir_script/passes/java_script_name.ex | 31 ++++ lib/elixir_script/passes/load_modules.ex | 16 ++ lib/elixir_script/passes/module_filepaths.ex | 114 +++++++++++++ lib/elixir_script/passes/remove_unused.ex | 15 ++ 11 files changed, 447 insertions(+), 178 deletions(-) delete mode 100644 lib/elixir_script/compiler/deps.ex create mode 100644 lib/elixir_script/passes/deps_paths.ex create mode 100644 lib/elixir_script/passes/find_deps.ex create mode 100644 lib/elixir_script/passes/find_functions.ex create mode 100644 lib/elixir_script/passes/java_script_ast.ex create mode 100644 lib/elixir_script/passes/java_script_code.ex create mode 100644 lib/elixir_script/passes/java_script_name.ex create mode 100644 lib/elixir_script/passes/load_modules.ex create mode 100644 lib/elixir_script/passes/module_filepaths.ex create mode 100644 lib/elixir_script/passes/remove_unused.ex diff --git a/lib/elixir_script.ex b/lib/elixir_script.ex index 18868554..a3a20b43 100644 --- a/lib/elixir_script.ex +++ b/lib/elixir_script.ex @@ -75,16 +75,15 @@ defmodule ElixirScript do opts = build_compiler_options(opts) - paths = if Code.ensure_loaded?(Mix) do - deps = ElixirScript.Compiler.Deps.get_deps_paths(Mix.env) - deps ++ [{opts[:app], [path]}] - else - [{opts[:app], [path]}] - end - - paths = ElixirScript.Compiler.Deps.get_module_filepath_map(paths) - - + paths = path + |> ElixirScript.Passes.DepsPaths.execute(opts) + |> ElixirScript.Passes.ModuleFilepaths.execute(opts) + |> ElixirScript.Passes.FindDeps.execute(opts) + |> ElixirScript.Passes.RemoveUnused.execute(opts) + |> ElixirScript.Passes.LoadModules.execute(opts) + |> ElixirScript.Passes.FindFunctions.execute(opts) + |> ElixirScript.Passes.JavaScriptAST.execute(opts) + |> ElixirScript.Passes.JavaScriptCode.execute(opts) {expanded_path, loaded_modules} = case File.dir?(path) do true -> diff --git a/lib/elixir_script/compiler/deps.ex b/lib/elixir_script/compiler/deps.ex deleted file mode 100644 index 24dc5fd2..00000000 --- a/lib/elixir_script/compiler/deps.ex +++ /dev/null @@ -1,168 +0,0 @@ -defmodule ElixirScript.Compiler.Deps do - alias ElixirScript.Translator.Utils - - def get_deps_paths(env \\ Mix.env) do - Mix.Dep.loaded([env: env]) - |> do_get_deps_paths - end - - defp do_get_deps_paths(deps) do - Enum.reduce(deps, [], fn(dep, list) -> - paths = Mix.Project.in_project dep.app, dep.opts[:dest], fn mixfile -> Mix.Project.config()[:elixirc_paths] end - paths = Enum.map(paths, fn path -> Path.join([dep.opts[:dest], path]) end) - - deps = do_get_deps_paths(dep.deps) - - deps ++ [{dep.app, paths}] ++ list - end) - |> Enum.uniq - end - - def get_module_filepath_map(deps_paths) do - Enum.reduce(deps_paths, [], fn({dep, paths}, list) -> - - file_paths = Enum.flat_map(paths, fn(path) -> - path = Path.join(path, "**/*.{ex,exs,exjs}") - |> Path.wildcard - end) - - file_paths = Enum.reduce(file_paths, [], fn(path, list) -> - quoted = path - |> File.read! - |> Code.string_to_quoted! - - #TODO: build sumbmodules correctly - { _, modules } = Macro.postwalk(quoted, [], &get_defmodules(&1, &2)) - - modules = Enum.map(modules, fn(x) -> { x.module, Map.put(x, :path, path) |> Map.put(:app, dep) } end) - list ++ modules - end) - - - list ++ file_paths - end) - - end - - - defp get_defmodules({:defprotocol, _, [{:__aliases__, _, _} = the_alias, _]} = ast, state) do - s = %{ module: Utils.quoted_to_name(the_alias), type: :protocol, ast: ast } - { ast, state ++ [s] } - end - - defp get_defmodules({:defprotocol, _, [{:__aliases__, _, _} = the_alias, _]} = ast, state) do - s = %{module: Utils.quoted_to_name(the_alias), type: :protocol, ast: ast } - { ast, state ++ [s] } - end - - defp get_defmodules({:defimpl, _, [ {:__aliases__, _, _} = the_alias, [for: type], _ ]} = ast, state) do - s = %{module: Utils.quoted_to_name(the_alias), type: :impl, for: Utils.quoted_to_name(type), ast: ast } - { ast, state ++ [s] } - end - - defp get_defmodules({:defimpl, _, [ {:__aliases__, _, _} = the_alias, [for: type], _ ]} = ast, state) do - s = %{module: Utils.quoted_to_name(the_alias), type: :impl, for: Utils.quoted_to_name(type), ast: ast } - { ast, state ++ [s] } - end - - defp get_defmodules({:defmodule, _, [{:__aliases__, _, _} = the_alias, [do: _]]} = ast, state) do - s = %{module: Utils.quoted_to_name(the_alias), type: :module, ast: ast } - { ast, state ++ [s] } - end - - defp get_defmodules(ast, state) do - { ast, state } - end - - def find_dependencies(module_filepath_map) do - Enum.map(module_filepath_map, &do_find_dependencies(&1)) - end - - defp do_find_dependencies({ module, module_data }) do - {_, deps} = Macro.prewalk(module_data.ast, [], &collect_references(&1, &2)) - { module, Map.put(module_data, :deps, deps) } - end - - defp collect_references({:import, _, [{{:., _, [{:__aliases__, _, head_import_name}, :{}]}, _, tail_imports }]}, state) do - deps = Enum.map(tail_imports, fn({:__aliases__, context, name}) -> - full_module_name = { :__aliases__, context, head_import_name ++ name } - Utils.quoted_to_name(full_module_name) - end) - - state ++ deps - end - - defp collect_references({:import, _, [{:__aliases__, _, _} = module_name]} = ast, state) do - module_name = Utils.quoted_to_name(module_name) - { ast, state ++ [module_name] } - end - - defp collect_references({:import, _, [{:__aliases__, _, _} = module_name, _]} = ast, state) do - module_name = Utils.quoted_to_name(module_name) - {ast, state ++ [module_name] } - end - - defp collect_references({:alias, _, [{{:., _, [{:__aliases__, _, head_alias_name}, :{}]}, _, tail_aliases }]} = ast, state) do - deps = Enum.map(tail_aliases, fn({:__aliases__, context, name}) -> - full_module_name = { :__aliases__, context, head_alias_name ++ name } - Utils.quoted_to_name(full_module_name) - end) - - { ast, state ++ deps } - end - - defp collect_references({:alias, _, [{:__aliases__, _, _} = module_name] } = ast, state) do - module_name = Utils.quoted_to_name(module_name) - { ast, state ++ [module_name] } - end - - defp collect_references({:alias, _, [{:__aliases__, _, _} = module_name, _]} = ast, state) do - module_name = Utils.quoted_to_name(module_name) - {ast, state ++ [module_name] } - end - - defp collect_references({:require, _, [{{:., _, [{:__aliases__, _, head_alias_name}, :{}]}, _, tail_aliases }]} = ast, state) do - deps = Enum.map(tail_aliases, fn({:__aliases__, context, name}) -> - full_module_name = { :__aliases__, context, head_alias_name ++ name } - Utils.quoted_to_name(full_module_name) - end) - - { ast, state ++ deps } - end - - defp collect_references({:require, _, [{:__aliases__, _, _} = module_name] } = ast, state) do - module_name = Utils.quoted_to_name(module_name) - { ast, state ++ [module_name] } - end - - defp collect_references({:require, _, [{:__aliases__, _, _} = module_name, _]} = ast, state) do - module_name = Utils.quoted_to_name(module_name) - { ast, state ++ [module_name] } - end - - defp collect_references({:., _, [{:__aliases__, _, _} = module_name, _]} = ast, state) do - module_name = Utils.quoted_to_name(module_name) - { ast, state ++ [module_name] } - end - - defp collect_references({{:., _, [{:__aliases__, _, _} = module_name, _]}, _, _ } = ast, state) do - module_name = Utils.quoted_to_name(module_name) - { ast, state ++ [module_name] } - end - - defp collect_references(ast, state) do - { ast, state } - end - - def remove_modules_not_depended_on(module_filepath_map, apps_not_to_touch) do - Enum.filter(module_filepath_map, fn({module_name, _}) -> - module_found_in_deps(module_name, module_filepath_map, List.wrap(apps_not_to_touch)) == true - end) - end - - defp module_found_in_deps(module_name, module_filepath_map, apps_not_to_touch) do - Enum.any?(module_filepath_map, fn({_, %{deps: deps, app: app}}) -> - Enum.member?(apps_not_to_touch, app) or Enum.member?(deps, module_name) - end) - end -end diff --git a/lib/elixir_script/passes/deps_paths.ex b/lib/elixir_script/passes/deps_paths.ex new file mode 100644 index 00000000..d2b3060c --- /dev/null +++ b/lib/elixir_script/passes/deps_paths.ex @@ -0,0 +1,30 @@ +defmodule ElixirScript.Passes.DepsPaths do + @pass 1 + + def execute(path, opts) do + if Code.ensure_loaded?(Mix) do + deps = get_deps_paths(Mix.env) + deps ++ [{opts[:app], [path]}] + else + [{opts[:app], [path]}] + end + end + + defp get_deps_paths(env) do + Mix.Dep.loaded([env: env]) + |> do_get_deps_paths + end + + defp do_get_deps_paths(deps) do + Enum.reduce(deps, [], fn(dep, list) -> + paths = Mix.Project.in_project dep.app, dep.opts[:dest], fn mixfile -> Mix.Project.config()[:elixirc_paths] end + paths = Enum.map(paths, fn path -> Path.join([dep.opts[:dest], path]) end) + + deps = do_get_deps_paths(dep.deps) + + deps ++ [{dep.app, paths}] ++ list + end) + |> Enum.uniq + end + +end diff --git a/lib/elixir_script/passes/find_deps.ex b/lib/elixir_script/passes/find_deps.ex new file mode 100644 index 00000000..7fc8b83a --- /dev/null +++ b/lib/elixir_script/passes/find_deps.ex @@ -0,0 +1,85 @@ +defmodule ElixirScript.Passes.FindDeps do + @pass 3 + + alias ElixirScript.Translator.Utils + + def execute(module_filepath_map, _) do + Enum.map(module_filepath_map, &do_find_dependencies(&1)) + end + + defp do_find_dependencies({ module, module_data }) do + {_, deps} = Macro.prewalk(module_data.ast, [], &collect_references(&1, &2)) + { module, Map.put(module_data, :deps, deps) } + end + + defp collect_references({:import, _, [{{:., _, [{:__aliases__, _, head_import_name}, :{}]}, _, tail_imports }]}, state) do + deps = Enum.map(tail_imports, fn({:__aliases__, context, name}) -> + full_module_name = { :__aliases__, context, head_import_name ++ name } + Utils.quoted_to_name(full_module_name) + end) + + state ++ deps + end + + defp collect_references({:import, _, [{:__aliases__, _, _} = module_name]} = ast, state) do + module_name = Utils.quoted_to_name(module_name) + { ast, state ++ [module_name] } + end + + defp collect_references({:import, _, [{:__aliases__, _, _} = module_name, _]} = ast, state) do + module_name = Utils.quoted_to_name(module_name) + {ast, state ++ [module_name] } + end + + defp collect_references({:alias, _, [{{:., _, [{:__aliases__, _, head_alias_name}, :{}]}, _, tail_aliases }]} = ast, state) do + deps = Enum.map(tail_aliases, fn({:__aliases__, context, name}) -> + full_module_name = { :__aliases__, context, head_alias_name ++ name } + Utils.quoted_to_name(full_module_name) + end) + + { ast, state ++ deps } + end + + defp collect_references({:alias, _, [{:__aliases__, _, _} = module_name] } = ast, state) do + module_name = Utils.quoted_to_name(module_name) + { ast, state ++ [module_name] } + end + + defp collect_references({:alias, _, [{:__aliases__, _, _} = module_name, _]} = ast, state) do + module_name = Utils.quoted_to_name(module_name) + {ast, state ++ [module_name] } + end + + defp collect_references({:require, _, [{{:., _, [{:__aliases__, _, head_alias_name}, :{}]}, _, tail_aliases }]} = ast, state) do + deps = Enum.map(tail_aliases, fn({:__aliases__, context, name}) -> + full_module_name = { :__aliases__, context, head_alias_name ++ name } + Utils.quoted_to_name(full_module_name) + end) + + { ast, state ++ deps } + end + + defp collect_references({:require, _, [{:__aliases__, _, _} = module_name] } = ast, state) do + module_name = Utils.quoted_to_name(module_name) + { ast, state ++ [module_name] } + end + + defp collect_references({:require, _, [{:__aliases__, _, _} = module_name, _]} = ast, state) do + module_name = Utils.quoted_to_name(module_name) + { ast, state ++ [module_name] } + end + + defp collect_references({:., _, [{:__aliases__, _, _} = module_name, _]} = ast, state) do + module_name = Utils.quoted_to_name(module_name) + { ast, state ++ [module_name] } + end + + defp collect_references({{:., _, [{:__aliases__, _, _} = module_name, _]}, _, _ } = ast, state) do + module_name = Utils.quoted_to_name(module_name) + { ast, state ++ [module_name] } + end + + defp collect_references(ast, state) do + { ast, state } + end +end diff --git a/lib/elixir_script/passes/find_functions.ex b/lib/elixir_script/passes/find_functions.ex new file mode 100644 index 00000000..b4795fc4 --- /dev/null +++ b/lib/elixir_script/passes/find_functions.ex @@ -0,0 +1,77 @@ +defmodule ElixirScript.Passes.FindFunctions do + @pass 6 + @function_types [:def, :defp, :defgen, :defgenp] + + def execute(data, opts) do + new_data = Enum.map(data.data, fn { module_name, module_data } -> + + functions = case module_data.ast do + {:defmodule, _, [_, [do: body]]} -> + get_functions_from_module(body) + {:defprotocol, _, [_, [do: {:__block__, _, _} = block]]} -> + get_functions_from_module(block) + {:defprotocol, _, [{:__aliases__, _, _} = the_alias, [do: spec]]} -> + get_functions_from_module({:__block__, [], [spec]}) + _ -> + %{} + end + + + module_data = Map.put(module_data, :functions, functions) + {module_name, module_data} + end) + + %{data | data: new_data} + end + + defp get_functions_from_module({:__block__, _, list}) do + Enum.reduce(list, %{ def: Keyword.new, defp: Keyword.new, defgen: Keyword.new, defgenp: Keyword.new }, fn + ({type, _, [{:when, _, [{name, _, params} | _guards] }, _] }, state) when type in @function_types and is_atom(params) -> + arity = 0 + + add_function_to_map(state, type, name, arity) + + ({type, _, [{:when, _, [{name, _, params} | _guards] }, _] }, state) when type in @function_types -> + arity = if is_nil(params), do: 0, else: length(params) + + add_function_to_map(state, type, name, arity) + + ({type, _, [{name, _, params}, _]}, state) when type in @function_types and is_atom(params) -> + arity = 0 + + add_function_to_map(state, type, name, arity) + + ({type, _, [{name, _, params}, _]}, state) when type in @function_types -> + arity = if is_nil(params), do: 0, else: length(params) + add_function_to_map(state, type, name, arity) + + ({type, _, [{name, _, params}]}, state) when is_atom(params) and type in @function_types -> + arity = 0 + add_function_to_map(state, type, name, arity) + + ({type, _, [{name, _, params}]}, state) when type in @function_types -> + arity = length(params) + add_function_to_map(state, type, name, arity) + + _, state -> + state + + end) + end + + defp get_functions_from_module(_) do + %{ def: Keyword.new, defp: Keyword.new } + end + + defp add_function_to_map(map, type, name, arity) do + list = Map.get(map, type) + + if {name, arity} in list do + map + else + Map.put(map, type, list ++ [{ name, arity }]) + end + end + + +end diff --git a/lib/elixir_script/passes/java_script_ast.ex b/lib/elixir_script/passes/java_script_ast.ex new file mode 100644 index 00000000..d72dbe7d --- /dev/null +++ b/lib/elixir_script/passes/java_script_ast.ex @@ -0,0 +1,29 @@ +defmodule ElixirScript.Passes.JavaScriptAST do + @pass 7 + alias ElixirScript.Translator.Utils + + def execute(compiler_data, opts) do + data = Enum.map(compiler_data.data, fn({module_name, module_data}) -> + module_data = compile(module_data, opts) + {module_name, module_data} + end) + + %{ compiler_data | data: data } + end + + + defp compile(module_data, opts) do + env = ElixirScript.Translator.LexicalScope.module_scope(module_data.module, Utils.name_to_js_file_name(module_data.module) <> ".js", opts.env) + + module = case module_data.type do + :module -> + ElixirScript.Translator.Defmodule.make_module(module_data.module, module_data.ast, env) + :protocol -> + ElixirScript.Translator.Defprotocol.make(module_data.module, module_data.functions, env) + :protocol_implementation -> + ElixirScript.Translator.Defimpl.make(module_data.module, module_data.for, module_data.ast, env) + end + + Map.put(module_data, :javascript_ast, module.body) + end +end diff --git a/lib/elixir_script/passes/java_script_code.ex b/lib/elixir_script/passes/java_script_code.ex new file mode 100644 index 00000000..b03343b4 --- /dev/null +++ b/lib/elixir_script/passes/java_script_code.ex @@ -0,0 +1,41 @@ +defmodule ElixirScript.Passes.JavaScriptCode do + @pass 8 + alias ESTree.Tools.{ Builder, Generator } + + def execute(compiler_data, _) do + data = Enum.map(compiler_data.data, fn({module_name, module_data}) -> + module_data = compile(module_data) + {module_name, module_data} + end) + + %{ compiler_data | data: data } + end + + + defp compile(module_data) do + js_ast = Builder.program(module_data.javascript_ast) + + js_code = js_ast + |> prepare_js_ast + |> Generator.generate + + Map.put(module_data, :javascript_code, js_code) + end + + defp prepare_js_ast(js_ast) do + js_ast = case js_ast do + modules when is_list(modules) -> + modules + |> Enum.reduce([], &(&2 ++ &1.body)) + |> Builder.program + %ElixirScript.Translator.Group{ body: body } -> + Builder.program(body) + %ElixirScript.Translator.Empty{ } -> + Builder.program([]) + _ -> + js_ast + end + + js_ast + end +end diff --git a/lib/elixir_script/passes/java_script_name.ex b/lib/elixir_script/passes/java_script_name.ex new file mode 100644 index 00000000..f9bb5786 --- /dev/null +++ b/lib/elixir_script/passes/java_script_name.ex @@ -0,0 +1,31 @@ +defmodule ElixirScript.Passes.JavaScriptName do + @pass 8 + alias ElixirScript.Translator.Utils + + def execute(compiler_data, _) do + data = Enum.map(compiler_data.data, fn({module_name, module_data}) -> + module_data = make_name(module_data) + {module_name, module_data} + end) + + %{ compiler_data | data: data } + end + + + defp make_name(%{ module: module, type: :module } = module_data) do + js_name = Utils.name_to_js_file_name(module) <> ".js" + Map.put(module_data, :javascript_name, js_name) + end + + defp make_name(%{ module: module, type: :protocol } = module_data) do + js_name = Utils.name_to_js_file_name(module) <> ".js" + Map.put(module_data, :javascript_name, js_name) + end + + defp make_name(%{ module: module, type: :impl, for: type } = module_data) do + type_name = Atom.to_string(Utils.quoted_to_name(type)) + + js_name = Utils.name_to_js_file_name(module) <> ".DefImpl." <> type_name <> ".js" + Map.put(module_data, :javascript_name, js_name) + end +end diff --git a/lib/elixir_script/passes/load_modules.ex b/lib/elixir_script/passes/load_modules.ex new file mode 100644 index 00000000..f0017a80 --- /dev/null +++ b/lib/elixir_script/passes/load_modules.ex @@ -0,0 +1,16 @@ +defmodule ElixirScript.Passes.LoadModules do + @pass 5 + + def execute(data, opts) do + ex_files = Enum.map(data, fn { module, %{path: path} } -> path end) + |> Enum.filter(fn path -> Path.extname(path) == ".ex" || Path.extname(path) == ".exs" end) + + loaded_modules = Kernel.ParallelRequire.files(ex_files) + + %{ + data: data, + loaded_modules: loaded_modules + } + end + +end diff --git a/lib/elixir_script/passes/module_filepaths.ex b/lib/elixir_script/passes/module_filepaths.ex new file mode 100644 index 00000000..ba59cfb8 --- /dev/null +++ b/lib/elixir_script/passes/module_filepaths.ex @@ -0,0 +1,114 @@ +defmodule ElixirScript.Passes.ModuleFilepaths do + @pass 2 + + alias ElixirScript.Translator.Utils + + def execute(deps_paths, _) do + Enum.reduce(deps_paths, [], fn({dep, paths}, list) -> + + file_paths = Enum.flat_map(paths, fn(path) -> + path = Path.join(path, "**/*.{ex,exs,exjs}") + |> Path.wildcard + end) + + file_paths = Enum.reduce(file_paths, [], fn(path, list) -> + quoted = path + |> File.read! + |> Code.string_to_quoted! + + { _, modules } = Macro.postwalk(quoted, [], &get_defmodules(&1, &2)) + + modules = Enum.map(modules, fn(x) -> { x.module, Map.put(x, :path, path) |> Map.put(:app, dep) } end) + list ++ modules + end) + + + list ++ file_paths + end) + end + + defp get_defmodules({:defprotocol, _, [{:__aliases__, _, _} = the_alias, _]} = ast, state) do + s = %{ module: Utils.quoted_to_name(the_alias), type: :protocol, ast: ast } + { ast, state ++ [s] } + end + + defp get_defmodules({:defprotocol, _, [{:__aliases__, _, _} = the_alias, _]} = ast, state) do + s = %{module: Utils.quoted_to_name(the_alias), type: :protocol, ast: ast } + { ast, state ++ [s] } + end + + defp get_defmodules({:defimpl, _, [ {:__aliases__, _, _} = the_alias, [for: type], _ ]} = ast, state) do + s = %{module: Utils.quoted_to_name(the_alias), type: :impl, for: Utils.quoted_to_name(type), ast: ast } + { ast, state ++ [s] } + end + + defp get_defmodules({:defimpl, _, [ {:__aliases__, _, _} = the_alias, [for: type], _ ]} = ast, state) do + s = %{module: Utils.quoted_to_name(the_alias), type: :impl, for: Utils.quoted_to_name(type), ast: ast } + { ast, state ++ [s] } + end + + defp get_defmodules({:defmodule, _, [{:__aliases__, _, _} = the_alias, [do: _]]} = ast, state) do + { ast, do_module_processing(ast, state) } + end + + defp get_defmodules(ast, state) do + { ast, state } + end + + defp do_module_processing({:defmodule, context1, [{:__aliases__, _, name} = the_alias, [do: body]]}, state) do + { body, inner_modules } = make_inner_module_aliases(name, body) + + aliases = Enum.map(inner_modules, fn + ({:defmodule, _, [{:__aliases__, _, inner_module_name}, [do: inner_module_body]]}) -> + { :alias, [], [{:__aliases__, [alias: false], name ++ inner_module_name}, [as: {:__aliases__, [alias: false], inner_module_name }] ] } + end) + + state = Enum.reduce(inner_modules, state, fn + ({:defmodule, context1, [{:__aliases__, context2, inner_module_name}, [do: inner_module_body]]}, state) -> + + module_name = Utils.quoted_to_name({:__aliases__, [], tl(name) ++ inner_module_name}) + state = Enum.reject(state, fn(x) -> x.module == module_name end) + + this_module_aliases = aliases -- [{ :alias, [], [{:__aliases__, [alias: false], name ++ inner_module_name}, [as: {:__aliases__, [alias: false], inner_module_name }] ] }] + + do_module_processing( + {:defmodule, context1, [{:__aliases__, context2, name ++ inner_module_name}, [do: add_aliases_to_body(inner_module_body, this_module_aliases)]]}, + state) + end) + + + [%{module: Utils.quoted_to_name(the_alias), type: :module, ast: {:defmodule, context1, [the_alias, [do: body]]} }] ++ state + end + + defp add_aliases_to_body(body, aliases) do + case body do + { :__block__, context, body } -> + { :__block__, context, aliases ++ List.wrap(body) } + _ -> + { :__block__, [], aliases ++ List.wrap(body) } + end + end + + defp make_inner_module_aliases(name, body) do + case body do + nil -> + { { :__block__, [], [] }, [] } + + {:__block__, context, list2 } -> + { list2, inner_modules } = Enum.partition(list2, fn(x) -> + case x do + {:defmodule, _, [{:__aliases__, _, inner_module_name}, [do: inner_module_body]]} -> + false + _ -> + true + end + end) + + { {:__block__, context, list2}, inner_modules } + {:defmodule, _, [{:__aliases__, context, inner_module_name}, [do: inner_module_body]]} = mod -> + { {:__block__, context, [] }, [mod] } + _ -> + { body, [] } + end + end +end diff --git a/lib/elixir_script/passes/remove_unused.ex b/lib/elixir_script/passes/remove_unused.ex new file mode 100644 index 00000000..c17816ab --- /dev/null +++ b/lib/elixir_script/passes/remove_unused.ex @@ -0,0 +1,15 @@ +defmodule ElixirScript.Passes.RemoveUnused do + @pass 4 + + def execute(module_filepath_map, opts) do + Enum.filter(module_filepath_map, fn({module_name, _}) -> + module_found_in_deps(module_name, module_filepath_map, [opts[:app]]) == true + end) + end + + defp module_found_in_deps(module_name, module_filepath_map, apps_not_to_touch) do + Enum.any?(module_filepath_map, fn({_, %{deps: deps, app: app}}) -> + Enum.member?(apps_not_to_touch, app) or Enum.member?(deps, module_name) + end) + end +end From 1e0b359728c54721feebd68fdc9c9b34f33f9bf5 Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Sun, 16 Oct 2016 08:06:26 -0500 Subject: [PATCH 306/860] Add more passes --- lib/elixir_script.ex | 3 + .../passes/consolidate_protocols.ex | 90 +++++++++++++++++++ lib/elixir_script/passes/handle_output.ex | 52 +++++++++++ lib/elixir_script/passes/java_script_ast.ex | 2 +- lib/elixir_script/passes/java_script_code.ex | 28 +++--- lib/elixir_script/passes/java_script_name.ex | 23 +---- lib/elixir_script/passes/module_filepaths.ex | 85 +++++++++++++----- lib/elixir_script/passes/remove_unused.ex | 7 +- lib/elixir_script/translator/lexical_scope.ex | 16 ++-- 9 files changed, 240 insertions(+), 66 deletions(-) create mode 100644 lib/elixir_script/passes/consolidate_protocols.ex create mode 100644 lib/elixir_script/passes/handle_output.ex diff --git a/lib/elixir_script.ex b/lib/elixir_script.ex index a3a20b43..19f9a26c 100644 --- a/lib/elixir_script.ex +++ b/lib/elixir_script.ex @@ -83,7 +83,10 @@ defmodule ElixirScript do |> ElixirScript.Passes.LoadModules.execute(opts) |> ElixirScript.Passes.FindFunctions.execute(opts) |> ElixirScript.Passes.JavaScriptAST.execute(opts) + |> ElixirScript.Passes.ConsolidateProtocols.execute(opts) |> ElixirScript.Passes.JavaScriptCode.execute(opts) + |> ElixirScript.Passes.JavaScriptName.execute(opts) + |> ElixirScript.Passes.HandleOutput.execute(opts) {expanded_path, loaded_modules} = case File.dir?(path) do true -> diff --git a/lib/elixir_script/passes/consolidate_protocols.ex b/lib/elixir_script/passes/consolidate_protocols.ex new file mode 100644 index 00000000..29a858d4 --- /dev/null +++ b/lib/elixir_script/passes/consolidate_protocols.ex @@ -0,0 +1,90 @@ +defmodule ElixirScript.Passes.ConsolidateProtocols do + @pass 8 + alias ESTree.Tools.Builder, as: JS + alias ElixirScript.Translator.Utils + alias ElixirScript.ModuleSystems + alias ElixirScript.Translator.Identifier + require Logger + + def execute(compiler_data, opts) do + only_protocols_and_impls = Enum.filter(compiler_data.data, fn + ({_, %{type: :module}}) -> + false + _ -> + true + end) + + grouped = group_protocol_data(only_protocols_and_impls) + consolidated_protocols = update_protocols(grouped, opts) + + %{ compiler_data | data: compiler_data.data ++ consolidated_protocols } + end + + + defp group_protocol_data(data) do + Enum.reduce(data, %{}, fn({module_name, module_data} = dat, state) -> + if module_data.type == :protocol do + existing = Map.get(state, module_name, %{}) + Map.put(existing, :protocol, dat) + Map.put(state, module_name, existing) + else + existing = Map.get(state, module_data.implements, %{}) + existing_protocol_data = Map.get(existing, :impls, []) + existing_protocol_data = existing_protocol_data ++ [dat] + Map.put(existing, :impls, existing_protocol_data) + Map.put(state, module_name.implements, existing) + end + end) + end + + defp update_protocols(grouped_protocol_data, opts) do + Enum.map(grouped_protocol_data, fn({ protocol_name, %{ protocol: protocol, impls: impls } }) -> + make_defimpl(protocol_name, protocol, Enum.uniq(impls), opts) + end) + end + + defp make_defimpl(name, protocol, implementations, compiler_opts) do + imports = [ModuleSystems.import_module(:Elixir, Utils.make_local_file_path(:elixir, compiler_opts.core_path, compiler_opts.root))] + + declarator = JS.variable_declarator( + JS.identifier("impls"), + JS.array_expression([]) + ) + + declaration = JS.variable_declaration([declarator], :let) + + default = JS.export_default_declaration(JS.identifier("impls")) + + protocol_name = Atom.to_string(name) + + app_name = protocol.app + + body = Enum.flat_map(implementations, fn({impl_app_name, impl_data}) -> + x = Atom.to_string(impl_data.type) + x = String.to_atom(protocol_name <> ".DefImpl." <> x) + name = Utils.name_to_js_name(x) + imports = ModuleSystems.import_module(name, Utils.make_local_file_path(impl_app_name, Utils.name_to_js_file_name(x), compiler_opts.root)) + call = JS.call_expression( + JS.member_expression( + JS.identifier("impls"), + JS.identifier("push") + ), + [JS.identifier(name)] + ) + + [imports, call] + end) + + module_name = String.to_atom(protocol_name <> ".DefImpl") + module_data = %{ + module: String.to_atom(protocol_name <> ".DefImpl"), + javascript_ast: imports ++ [declaration] ++ body ++ [default], + app: app_name, + type: :consolidated, + protocol: name + } + + { module_name, module_data } + end + +end diff --git a/lib/elixir_script/passes/handle_output.ex b/lib/elixir_script/passes/handle_output.ex new file mode 100644 index 00000000..66f636e3 --- /dev/null +++ b/lib/elixir_script/passes/handle_output.ex @@ -0,0 +1,52 @@ +defmodule ElixirScript.Passes.HandleOutput do + @pass 11 + + def execute(compiler_data, opts) do + out(compiler_data, opts) + compiler_data + end + + defp out(compiler_output, %{output: nil} = compiler_opts) do + compiler_output + |> process_include_path(compiler_opts) + end + + defp out(compiler_output, %{output: :stdout} = compiler_opts) do + compiler_output + |> process_include_path(compiler_opts) + |> Enum.each(fn + {_, code, _} -> IO.write(code) + code -> IO.write(code) + end) + end + + defp out(compiler_output, %{output: output_path, core_path: core_path} = compiler_opts) do + Enum.each(compiler_output, fn(x) -> + write_to_file(x, output_path) + end) + + ElixirScript.copy_stdlib_to_destination(output_path) + end + + defp write_to_file({_, module_data}, destination) do + file_name = Path.join([destination, to_string(module_data.app), module_data.javascript_name]) + + if !File.exists?(Path.dirname(file_name)) do + File.mkdir_p!(Path.dirname(file_name)) + end + + File.write!(file_name, module_data.javascript_code) + end + + defp process_include_path(compiler_output, compiler_opts) do + Enum.map(compiler_output, fn + {module_name, module_data} -> + case compiler_opts.include_path do + true -> + { module_data.javascript_name, module_data.javascript_code, module_data.app } + false -> + module_data.javascript_code + end + end) + end +end diff --git a/lib/elixir_script/passes/java_script_ast.ex b/lib/elixir_script/passes/java_script_ast.ex index d72dbe7d..f492faf2 100644 --- a/lib/elixir_script/passes/java_script_ast.ex +++ b/lib/elixir_script/passes/java_script_ast.ex @@ -13,7 +13,7 @@ defmodule ElixirScript.Passes.JavaScriptAST do defp compile(module_data, opts) do - env = ElixirScript.Translator.LexicalScope.module_scope(module_data.module, Utils.name_to_js_file_name(module_data.module) <> ".js", opts.env) + env = ElixirScript.Translator.LexicalScope.module_scope(module_data.module, Utils.name_to_js_file_name(module_data.module) <> ".js", opts.env, module_data) module = case module_data.type do :module -> diff --git a/lib/elixir_script/passes/java_script_code.ex b/lib/elixir_script/passes/java_script_code.ex index b03343b4..e31ba7ba 100644 --- a/lib/elixir_script/passes/java_script_code.ex +++ b/lib/elixir_script/passes/java_script_code.ex @@ -1,5 +1,5 @@ defmodule ElixirScript.Passes.JavaScriptCode do - @pass 8 + @pass 9 alias ESTree.Tools.{ Builder, Generator } def execute(compiler_data, _) do @@ -23,19 +23,17 @@ defmodule ElixirScript.Passes.JavaScriptCode do end defp prepare_js_ast(js_ast) do - js_ast = case js_ast do - modules when is_list(modules) -> - modules - |> Enum.reduce([], &(&2 ++ &1.body)) - |> Builder.program - %ElixirScript.Translator.Group{ body: body } -> - Builder.program(body) - %ElixirScript.Translator.Empty{ } -> - Builder.program([]) - _ -> - js_ast - end - - js_ast + case js_ast do + modules when is_list(modules) -> + modules + |> Enum.reduce([], &(&2 ++ &1.body)) + |> Builder.program + %ElixirScript.Translator.Group{ body: body } -> + Builder.program(body) + %ElixirScript.Translator.Empty{ } -> + Builder.program([]) + _ -> + js_ast + end end end diff --git a/lib/elixir_script/passes/java_script_name.ex b/lib/elixir_script/passes/java_script_name.ex index f9bb5786..5c707b7c 100644 --- a/lib/elixir_script/passes/java_script_name.ex +++ b/lib/elixir_script/passes/java_script_name.ex @@ -1,31 +1,14 @@ defmodule ElixirScript.Passes.JavaScriptName do - @pass 8 + @pass 10 alias ElixirScript.Translator.Utils def execute(compiler_data, _) do data = Enum.map(compiler_data.data, fn({module_name, module_data}) -> - module_data = make_name(module_data) + js_name = Utils.name_to_js_file_name(module_name) <> ".js" + module_data = Map.put(module_data, :javascript_name, js_name) {module_name, module_data} end) %{ compiler_data | data: data } end - - - defp make_name(%{ module: module, type: :module } = module_data) do - js_name = Utils.name_to_js_file_name(module) <> ".js" - Map.put(module_data, :javascript_name, js_name) - end - - defp make_name(%{ module: module, type: :protocol } = module_data) do - js_name = Utils.name_to_js_file_name(module) <> ".js" - Map.put(module_data, :javascript_name, js_name) - end - - defp make_name(%{ module: module, type: :impl, for: type } = module_data) do - type_name = Atom.to_string(Utils.quoted_to_name(type)) - - js_name = Utils.name_to_js_file_name(module) <> ".DefImpl." <> type_name <> ".js" - Map.put(module_data, :javascript_name, js_name) - end end diff --git a/lib/elixir_script/passes/module_filepaths.ex b/lib/elixir_script/passes/module_filepaths.ex index ba59cfb8..d5bbebc1 100644 --- a/lib/elixir_script/passes/module_filepaths.ex +++ b/lib/elixir_script/passes/module_filepaths.ex @@ -3,11 +3,11 @@ defmodule ElixirScript.Passes.ModuleFilepaths do alias ElixirScript.Translator.Utils - def execute(deps_paths, _) do + def execute(deps_paths, opts) do Enum.reduce(deps_paths, [], fn({dep, paths}, list) -> file_paths = Enum.flat_map(paths, fn(path) -> - path = Path.join(path, "**/*.{ex,exs,exjs}") + Path.join(path, "**/*.{ex,exs,exjs}") |> Path.wildcard end) @@ -16,9 +16,11 @@ defmodule ElixirScript.Passes.ModuleFilepaths do |> File.read! |> Code.string_to_quoted! - { _, modules } = Macro.postwalk(quoted, [], &get_defmodules(&1, &2)) + { _, modules } = Macro.postwalk(quoted, [], &get_defmodules(&1, &2, opts)) - modules = Enum.map(modules, fn(x) -> { x.module, Map.put(x, :path, path) |> Map.put(:app, dep) } end) + stat = File.stat!(path) + + modules = Enum.map(modules, fn(x) -> { x.module, Map.merge(x, %{ path: path, app: dep, stat: stat }) } end) list ++ modules end) @@ -27,35 +29,26 @@ defmodule ElixirScript.Passes.ModuleFilepaths do end) end - defp get_defmodules({:defprotocol, _, [{:__aliases__, _, _} = the_alias, _]} = ast, state) do + defp get_defmodules({:defprotocol, _, [{:__aliases__, _, _} = the_alias, _]} = ast, state, _) do s = %{ module: Utils.quoted_to_name(the_alias), type: :protocol, ast: ast } { ast, state ++ [s] } end - defp get_defmodules({:defprotocol, _, [{:__aliases__, _, _} = the_alias, _]} = ast, state) do - s = %{module: Utils.quoted_to_name(the_alias), type: :protocol, ast: ast } - { ast, state ++ [s] } - end - - defp get_defmodules({:defimpl, _, [ {:__aliases__, _, _} = the_alias, [for: type], _ ]} = ast, state) do - s = %{module: Utils.quoted_to_name(the_alias), type: :impl, for: Utils.quoted_to_name(type), ast: ast } - { ast, state ++ [s] } - end - - defp get_defmodules({:defimpl, _, [ {:__aliases__, _, _} = the_alias, [for: type], _ ]} = ast, state) do - s = %{module: Utils.quoted_to_name(the_alias), type: :impl, for: Utils.quoted_to_name(type), ast: ast } + defp get_defmodules({:defimpl, _, [ {:__aliases__, _, name} = the_alias, [for: {:__aliases__, _, type_name} = type], _ ]} = ast, state, _) do + name = name ++ [DefImpl] ++ type_name + s = %{module: Utils.quoted_to_name({:__aliases__, [], name}), type: :impl, for: Utils.quoted_to_name(type), ast: ast, implements: Utils.quoted_to_name(the_alias) } { ast, state ++ [s] } end - defp get_defmodules({:defmodule, _, [{:__aliases__, _, _} = the_alias, [do: _]]} = ast, state) do - { ast, do_module_processing(ast, state) } + defp get_defmodules({:defmodule, _, [{:__aliases__, _, _}, [do: _]]} = ast, state, opts) do + { ast, do_module_processing(ast, state, opts) } end - defp get_defmodules(ast, state) do + defp get_defmodules(ast, state, _) do { ast, state } end - defp do_module_processing({:defmodule, context1, [{:__aliases__, _, name} = the_alias, [do: body]]}, state) do + defp do_module_processing({:defmodule, context1, [{:__aliases__, _, name} = the_alias, [do: body]]}, state, opts) do { body, inner_modules } = make_inner_module_aliases(name, body) aliases = Enum.map(inner_modules, fn @@ -73,9 +66,38 @@ defmodule ElixirScript.Passes.ModuleFilepaths do do_module_processing( {:defmodule, context1, [{:__aliases__, context2, name ++ inner_module_name}, [do: add_aliases_to_body(inner_module_body, this_module_aliases)]]}, - state) + state, opts) end) + body = case body do + {:__block__, context, list } -> + list = Enum.map(list, fn + {:use, _, [module, _] } = using -> + {:use, handle_use_expression(using, module, opts) } + {:use, _, [module] } = using -> + {:use, handle_use_expression(using, module, opts) } + ast -> + {:expanded, ast} + end) + |> Enum.reduce([], fn + {:use, ast}, state -> + case ast do + {:__block__, _, list} -> + state ++ list + _ -> + state ++ [ast] + end + + {:expanded, ast}, state -> + state ++ [ast] + end) + + {:__block__, context, list} + + _ -> + body + end + [%{module: Utils.quoted_to_name(the_alias), type: :module, ast: {:defmodule, context1, [the_alias, [do: body]]} }] ++ state end @@ -111,4 +133,23 @@ defmodule ElixirScript.Passes.ModuleFilepaths do { body, [] } end end + + defp handle_use_expression(using_ast, module, opts) do + module = Utils.quoted_to_name(module) + + eval = """ + require #{inspect module} + __ENV__ + """ + {env, _} = Code.eval_string(eval, [], opts.env) + + + case Macro.expand(using_ast, env) do + {:__block__, _, + [{:__block__, _, + [{:require, _, _}, + {{:., _, [_, :__using__]}, _, _} = ast]}]} -> + Macro.expand_once(ast, env) + end + end end diff --git a/lib/elixir_script/passes/remove_unused.ex b/lib/elixir_script/passes/remove_unused.ex index c17816ab..7877b74b 100644 --- a/lib/elixir_script/passes/remove_unused.ex +++ b/lib/elixir_script/passes/remove_unused.ex @@ -8,8 +8,11 @@ defmodule ElixirScript.Passes.RemoveUnused do end defp module_found_in_deps(module_name, module_filepath_map, apps_not_to_touch) do - Enum.any?(module_filepath_map, fn({_, %{deps: deps, app: app}}) -> - Enum.member?(apps_not_to_touch, app) or Enum.member?(deps, module_name) + Enum.any?(module_filepath_map, fn + ({_, %{deps: deps, app: app, type: :module}}) -> + Enum.member?(apps_not_to_touch, app) or Enum.member?(deps, module_name) + _ -> + true end) end end diff --git a/lib/elixir_script/translator/lexical_scope.ex b/lib/elixir_script/translator/lexical_scope.ex index b90c1971..c2cbaa40 100644 --- a/lib/elixir_script/translator/lexical_scope.ex +++ b/lib/elixir_script/translator/lexical_scope.ex @@ -17,7 +17,8 @@ defmodule ElixirScript.Translator.LexicalScope do export_vars: [{atom, atom | non_neg_integer}] | nil, lexical_tracker: nil, caller: t | nil, - env: nil + env: nil, + module_data: [{atom, %{}}] } defstruct [ @@ -36,7 +37,8 @@ defmodule ElixirScript.Translator.LexicalScope do export_vars: nil, lexical_tracker: nil, caller: nil, - env: nil + env: nil, + module_data: [] ] def env(scope) do @@ -77,24 +79,26 @@ defmodule ElixirScript.Translator.LexicalScope do } end - def module_scope(ElixirScript.Temp, filename, env) do + def module_scope(ElixirScript.Temp, filename, env, module_data) do env = %ElixirScript.Translator.LexicalScope { module: ElixirScript.Temp, file: filename, requires: [], functions: [], - env: env + env: env, + module_data: module_data } add_import(env, ElixirScript.Kernel) end - def module_scope(module_name, filename, env) do + def module_scope(module_name, filename, env, module_data) do module = ElixirScript.Translator.State.get_module(module_name) env = %ElixirScript.Translator.LexicalScope { module: module_name, file: filename, requires: [], functions: [{ module.name, module.functions}], - env: env + env: env, + module_data: module_data } add_import(env, ElixirScript.Kernel) From c18bc171b2744a8cd565b6174a4efb25f2e8b861 Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Sun, 16 Oct 2016 08:12:18 -0500 Subject: [PATCH 307/860] Update change log. Update extree version --- CHANGELOG.md | 7 ++++++- mix.exs | 4 ++-- mix.lock | 6 +++--- 3 files changed, 11 insertions(+), 6 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 577f3bb2..3c2cd5ab 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,4 +1,9 @@ -# v0.22.0-dev +# v0.22.0 + +* Enhancements + * Add `defgen` and `defgenp` for defining public and private generators + * Updated output folder structure + * Bug fixes * Correctly returning list if list is only item in body diff --git a/mix.exs b/mix.exs index 79f0f958..684d5103 100644 --- a/mix.exs +++ b/mix.exs @@ -4,7 +4,7 @@ defmodule ElixirScript.Mixfile do def project do [ app: :elixir_script, - version: "0.22.0-dev", + version: "0.22.0", elixir: "~> 1.0", escript: escript_config, deps: deps, @@ -28,7 +28,7 @@ defmodule ElixirScript.Mixfile do defp deps do [ - {:estree, "~> 2.3" }, + {:estree, "~> 2.4" }, {:fs, "~> 0.9.1"}, {:earmark, "~> 0.2", only: :dev }, {:ex_doc, "~> 0.11", only: :dev }, diff --git a/mix.lock b/mix.lock index 49e65dc7..effdca55 100644 --- a/mix.lock +++ b/mix.lock @@ -4,12 +4,12 @@ "credo": {:hex, :credo, "0.2.6", "d6c28e2074bfbfe4918a9918f131d69e14c05f8c04db69170e9d77b4bb33d995", [:mix], [{:bunt, "~> 0.1.4", [hex: :bunt, optional: false]}]}, "dogma": {:hex, :dogma, "0.0.7"}, "earmark": {:hex, :earmark, "0.2.1", "ba6d26ceb16106d069b289df66751734802777a3cbb6787026dd800ffeb850f3", [:mix], []}, - "estree": {:hex, :estree, "2.3.0", "96a190aee9b7ecb05a9486fe0f1e0a912c98b2d98419a84c74956687b6e53c71", [:mix], []}, + "estree": {:hex, :estree, "2.4.1", "9e8a26b0d9e3a83266c73f6a577f971b011e291a52d5d328706cf28ba0fceef5", [:mix], []}, "ex_doc": {:hex, :ex_doc, "0.11.4", "a064bdb720594c3745b94709b17ffb834fd858b4e0c1f48f37c0d92700759e02", [:mix], [{:earmark, "~> 0.1.17 or ~> 0.2", [hex: :earmark, optional: true]}]}, - "excoveralls": {:hex, :excoveralls, "0.5.1", "5b55d62b384c7edda8b26b52b1a9fc9358fec2e6b157a81071de5cb8a42e4721", [:mix], [{:hackney, ">= 0.12.0", [hex: :hackney, optional: false]}, {:exjsx, "~> 3.0", [hex: :exjsx, optional: false]}]}, + "excoveralls": {:hex, :excoveralls, "0.5.1", "5b55d62b384c7edda8b26b52b1a9fc9358fec2e6b157a81071de5cb8a42e4721", [:mix], [{:exjsx, "~> 3.0", [hex: :exjsx, optional: false]}, {:hackney, ">= 0.12.0", [hex: :hackney, optional: false]}]}, "exjsx": {:hex, :exjsx, "3.2.0", "7136cc739ace295fc74c378f33699e5145bead4fdc1b4799822d0287489136fb", [:mix], [{:jsx, "~> 2.6.2", [hex: :jsx, optional: false]}]}, "fs": {:hex, :fs, "0.9.2", "ed17036c26c3f70ac49781ed9220a50c36775c6ca2cf8182d123b6566e49ec59", [:rebar], []}, - "hackney": {:hex, :hackney, "1.4.8", "c8c6977ed55cc5095e3929f6d94a6f732dd2e31ae42a7b9236d5574ec3f5be13", [:rebar3], [{:ssl_verify_hostname, "1.0.5", [hex: :ssl_verify_hostname, optional: false]}, {:mimerl, "1.0.2", [hex: :mimerl, optional: false]}, {:idna, "1.0.3", [hex: :idna, optional: false]}, {:certifi, "0.3.0", [hex: :certifi, optional: false]}]}, + "hackney": {:hex, :hackney, "1.4.8", "c8c6977ed55cc5095e3929f6d94a6f732dd2e31ae42a7b9236d5574ec3f5be13", [:rebar3], [{:certifi, "0.3.0", [hex: :certifi, optional: false]}, {:idna, "1.0.3", [hex: :idna, optional: false]}, {:mimerl, "1.0.2", [hex: :mimerl, optional: false]}, {:ssl_verify_hostname, "1.0.5", [hex: :ssl_verify_hostname, optional: false]}]}, "idna": {:hex, :idna, "1.0.3", "d456a8761cad91c97e9788c27002eb3b773adaf5c893275fc35ba4e3434bbd9b", [:rebar3], []}, "inflex": {:hex, :inflex, "1.5.0"}, "jsx": {:hex, :jsx, "2.6.2", "213721e058da0587a4bce3cc8a00ff6684ced229c8f9223245c6ff2c88fbaa5a", [:mix, :rebar], []}, From 30be69f2b9c85babaa449462e53d5ea018900d43 Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Sun, 16 Oct 2016 08:15:34 -0500 Subject: [PATCH 308/860] Updated deps and getting started guide --- GettingStarted.md | 2 +- mix.exs | 8 ++++---- mix.lock | 8 ++++---- 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/GettingStarted.md b/GettingStarted.md index a05ee8a2..03bc6869 100644 --- a/GettingStarted.md +++ b/GettingStarted.md @@ -129,7 +129,7 @@ The intent of this guide is to get you started with ElixirScript. It will give y The first step is getting the dependency. In your mix.exs file for your elixir project, add elixir_script to your deps. ```elixir - {:elixir_script, "~> 0.18"} + {:elixir_script, "~> 0.22"} ``` * Step 2: Now download the dep diff --git a/mix.exs b/mix.exs index 684d5103..f96ecb83 100644 --- a/mix.exs +++ b/mix.exs @@ -30,10 +30,10 @@ defmodule ElixirScript.Mixfile do [ {:estree, "~> 2.4" }, {:fs, "~> 0.9.1"}, - {:earmark, "~> 0.2", only: :dev }, - {:ex_doc, "~> 0.11", only: :dev }, - {:excoveralls, "~> 0.4", only: :test}, - {:credo, "~> 0.2.0", only: [:dev, :test]} + {:earmark, "~> 1.0", only: :dev }, + {:ex_doc, "~> 0.14", only: :dev }, + {:excoveralls, "~> 0.5", only: :test}, + {:credo, "~> 0.4", only: [:dev, :test]} ] end diff --git a/mix.lock b/mix.lock index effdca55..6777ab1d 100644 --- a/mix.lock +++ b/mix.lock @@ -1,11 +1,11 @@ %{"benchfella": {:hex, :benchfella, "0.3.1"}, - "bunt": {:hex, :bunt, "0.1.5", "c378ea1698232597d3778e4b83234dcea4a60e7c28114b0fe53657a2c0d8885e", [:mix], []}, + "bunt": {:hex, :bunt, "0.1.6", "5d95a6882f73f3b9969fdfd1953798046664e6f77ec4e486e6fafc7caad97c6f", [:mix], []}, "certifi": {:hex, :certifi, "0.3.0", "389d4b126a47895fe96d65fcf8681f4d09eca1153dc2243ed6babad0aac1e763", [:rebar3], []}, - "credo": {:hex, :credo, "0.2.6", "d6c28e2074bfbfe4918a9918f131d69e14c05f8c04db69170e9d77b4bb33d995", [:mix], [{:bunt, "~> 0.1.4", [hex: :bunt, optional: false]}]}, + "credo": {:hex, :credo, "0.4.12", "f5e1973405ea25c6e64959fb0b6bf92950147a0278cc2a002a491b45f78f7b87", [:mix], [{:bunt, "~> 0.1.6", [hex: :bunt, optional: false]}]}, "dogma": {:hex, :dogma, "0.0.7"}, - "earmark": {:hex, :earmark, "0.2.1", "ba6d26ceb16106d069b289df66751734802777a3cbb6787026dd800ffeb850f3", [:mix], []}, + "earmark": {:hex, :earmark, "1.0.2", "a0b0904d74ecc14da8bd2e6e0248e1a409a2bc91aade75fcf428125603de3853", [:mix], []}, "estree": {:hex, :estree, "2.4.1", "9e8a26b0d9e3a83266c73f6a577f971b011e291a52d5d328706cf28ba0fceef5", [:mix], []}, - "ex_doc": {:hex, :ex_doc, "0.11.4", "a064bdb720594c3745b94709b17ffb834fd858b4e0c1f48f37c0d92700759e02", [:mix], [{:earmark, "~> 0.1.17 or ~> 0.2", [hex: :earmark, optional: true]}]}, + "ex_doc": {:hex, :ex_doc, "0.14.3", "e61cec6cf9731d7d23d254266ab06ac1decbb7651c3d1568402ec535d387b6f7", [:mix], [{:earmark, "~> 1.0", [hex: :earmark, optional: false]}]}, "excoveralls": {:hex, :excoveralls, "0.5.1", "5b55d62b384c7edda8b26b52b1a9fc9358fec2e6b157a81071de5cb8a42e4721", [:mix], [{:exjsx, "~> 3.0", [hex: :exjsx, optional: false]}, {:hackney, ">= 0.12.0", [hex: :hackney, optional: false]}]}, "exjsx": {:hex, :exjsx, "3.2.0", "7136cc739ace295fc74c378f33699e5145bead4fdc1b4799822d0287489136fb", [:mix], [{:jsx, "~> 2.6.2", [hex: :jsx, optional: false]}]}, "fs": {:hex, :fs, "0.9.2", "ed17036c26c3f70ac49781ed9220a50c36775c6ca2cf8182d123b6566e49ec59", [:rebar], []}, From 9415723ef0211ca4b7ea01062fe0083cc185b4b6 Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Sun, 16 Oct 2016 08:20:24 -0500 Subject: [PATCH 309/860] Updated change log --- CHANGELOG.md | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 3c2cd5ab..29112bad 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,7 +2,11 @@ * Enhancements * Add `defgen` and `defgenp` for defining public and private generators - * Updated output folder structure + * Add `yield/0`, `yield/1`, and `yield_to\1` to `Kernel` + * Updated output folder structure. stdlib code will now go in an `elxiir` folder under the output paths while generated app code will go into an `app` folder under the output path + +* Breaking + * All process macros and functions now expect to receive and/or work using generators as entry points. Using functions defined with `def` or `defp` will not work correctly with them * Bug fixes * Correctly returning list if list is only item in body From 9c51aa1c6afb92c0be7505d0ec226a934e9ab70f Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Sun, 16 Oct 2016 08:22:37 -0500 Subject: [PATCH 310/860] Updated package config --- mix.exs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mix.exs b/mix.exs index f96ecb83..340a6972 100644 --- a/mix.exs +++ b/mix.exs @@ -49,7 +49,7 @@ defmodule ElixirScript.Mixfile do defp package do [ - files: ["lib", "priv/*.js", "mix.exs", "README.md", "LICENSE", "CHANGELOG.md"], + files: ["lib", "priv/**/*.js", "mix.exs", "README.md", "LICENSE", "CHANGELOG.md"], maintainers: ["Bryan Joseph"], licenses: ["MIT"], links: %{ From 217e33b18e12780fa32a748857bf41c0ad0c0373 Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Sun, 16 Oct 2016 20:18:59 -0500 Subject: [PATCH 311/860] Add cache passes. Update state module --- lib/elixir_script.ex | 70 ++--- lib/elixir_script/compiler/cache.ex | 43 +++ lib/elixir_script/passes/deps_paths.ex | 20 +- .../passes/find_changed_files.ex | 21 ++ lib/elixir_script/passes/find_deps.ex | 5 +- lib/elixir_script/passes/handle_output.ex | 10 +- lib/elixir_script/passes/load_modules.ex | 10 +- lib/elixir_script/passes/module_filepaths.ex | 26 +- lib/elixir_script/passes/remove_unused.ex | 8 +- lib/elixir_script/passes/write_cache.ex | 20 ++ lib/elixir_script/translator/lexical_scope.ex | 16 +- .../translator/module_collector.ex | 257 ------------------ lib/elixir_script/translator/state.ex | 91 +------ 13 files changed, 181 insertions(+), 416 deletions(-) create mode 100644 lib/elixir_script/passes/find_changed_files.ex create mode 100644 lib/elixir_script/passes/write_cache.ex delete mode 100644 lib/elixir_script/translator/module_collector.ex diff --git a/lib/elixir_script.ex b/lib/elixir_script.ex index 19f9a26c..305027f1 100644 --- a/lib/elixir_script.ex +++ b/lib/elixir_script.ex @@ -2,7 +2,6 @@ defmodule ElixirScript do alias ESTree.Tools.Builder alias ESTree.Tools.Generator alias ElixirScript.Translator.Utils - alias ElixirScript.Translator.ModuleCollector alias ElixirScript.Compiler.Cache alias ElixirScript.Compiler.Output require Logger @@ -75,41 +74,20 @@ defmodule ElixirScript do opts = build_compiler_options(opts) - paths = path + result = %{ path: path } |> ElixirScript.Passes.DepsPaths.execute(opts) |> ElixirScript.Passes.ModuleFilepaths.execute(opts) |> ElixirScript.Passes.FindDeps.execute(opts) |> ElixirScript.Passes.RemoveUnused.execute(opts) |> ElixirScript.Passes.LoadModules.execute(opts) + |> ElixirScript.Passes.FindChangedFiles.execute(opts) |> ElixirScript.Passes.FindFunctions.execute(opts) |> ElixirScript.Passes.JavaScriptAST.execute(opts) |> ElixirScript.Passes.ConsolidateProtocols.execute(opts) |> ElixirScript.Passes.JavaScriptCode.execute(opts) |> ElixirScript.Passes.JavaScriptName.execute(opts) + |> ElixirScript.Passes.WriteCache.execute(opts) |> ElixirScript.Passes.HandleOutput.execute(opts) - - {expanded_path, loaded_modules} = case File.dir?(path) do - true -> - process_path(path) - false -> - {[path], []} - end - - compiler_cache = get_compiler_cache(path, opts) - new_file_stats = Cache.build_file_stats(expanded_path) - - changed_files = Cache.get_changed_files(compiler_cache.input_files, new_file_stats) - |> Enum.map(fn {file, state} -> file end) - - code = Enum.map(changed_files, &file_to_quoted/1) - - { code, new_state } = do_compile(opts, code, compiler_cache.state, loaded_modules) - compiler_cache = %{compiler_cache | input_files: new_file_stats, state: new_state } - - Cache.write(path, compiler_cache) - result = Output.out(path, code, opts) - ElixirScript.Translator.State.stop - result end defp process_path(path) do @@ -127,7 +105,8 @@ defmodule ElixirScript do {exjs, ex} end - defp get_stdlib_state() do + @doc false + def get_stdlib_state() do case @stdlib_state do {:ok, data} -> data @@ -188,29 +167,22 @@ defmodule ElixirScript do @doc false def compile_std_lib(output_path) do - compiler_opts = build_compiler_options(%{std_lib: true, include_path: true, output: output_path, app: :elixir}) - libs_path = Path.join([__DIR__, "elixir_script", "prelude", "**", "*.ex"]) - - code = Path.wildcard(libs_path) - |> Enum.map(&file_to_quoted/1) - - ElixirScript.Translator.State.start_link(compiler_opts, []) + opts = build_compiler_options(%{std_lib: true, include_path: true, output: output_path, app: :elixir}) + libs_path = Path.join([__DIR__, "elixir_script", "prelude"]) - code - |> Enum.map(&update_quoted(&1)) - |> ModuleCollector.process_modules(compiler_opts[:app]) - - code = create_code(compiler_opts, ElixirScript.Translator.State.get) - |> Enum.filter(fn({path, _, _}) -> !String.contains?(path, "ElixirScript.Temp.js") end) - - new_std_state = ElixirScript.Translator.State.serialize() - - stdlib_state_path = Path.join([File.cwd!(), "lib", "elixir_script", "translator", "stdlib_state.bin"]) - - File.write!(stdlib_state_path, new_std_state) - result = Output.out(libs_path, code, compiler_opts) - - ElixirScript.Translator.State.stop + result = %{ path: libs_path } + |> ElixirScript.Passes.DepsPaths.execute(opts) + |> ElixirScript.Passes.ModuleFilepaths.execute(opts) + #|> ElixirScript.Passes.FindDeps.execute(opts) + #|> ElixirScript.Passes.RemoveUnused.execute(opts) + #|> ElixirScript.Passes.LoadModules.execute(opts) + #|> ElixirScript.Passes.FindChangedFiles.execute(opts) + |> ElixirScript.Passes.FindFunctions.execute(opts) + |> ElixirScript.Passes.JavaScriptAST.execute(opts) + |> ElixirScript.Passes.ConsolidateProtocols.execute(opts) + |> ElixirScript.Passes.JavaScriptCode.execute(opts) + |> ElixirScript.Passes.JavaScriptName.execute(opts) + |> ElixirScript.Passes.HandleOutput.execute(opts) result end @@ -223,7 +195,7 @@ defmodule ElixirScript do quoted_code_list |> Enum.map(&update_quoted(&1)) - |> ModuleCollector.process_modules(compiler_opts[:app]) + #|> ModuleCollector.process_modules(compiler_opts[:app]) code = create_code(compiler_opts, ElixirScript.Translator.State.get) new_state = ElixirScript.Translator.State.serialize() diff --git a/lib/elixir_script/compiler/cache.ex b/lib/elixir_script/compiler/cache.ex index 13f1d534..e17fb95c 100644 --- a/lib/elixir_script/compiler/cache.ex +++ b/lib/elixir_script/compiler/cache.ex @@ -110,4 +110,47 @@ defmodule ElixirScript.Compiler.Cache do end end + def get_compiler_cache(path, opts) do + refresh_cache = cond do + Map.get(opts, :full_build) -> + true + empty?(opts.output) -> + true + old_version?(opts) -> + true + get(path) == nil -> + true + true -> + false + end + + if refresh_cache do + delete(path) + new(ElixirScript.get_stdlib_state()) + else + %{ get(path) | full_build?: false } + end + end + + defp empty?(path) when is_binary(path) do + case File.ls(path) do + {:ok, []} -> + true + {:error, _} -> + true + _ -> + false + end + end + + defp empty?(_) do + true + end + + defp old_version?(opts) do + cache_version = Map.get(opts, :version, nil) + cache_version == ElixirScript.version() + end + + end diff --git a/lib/elixir_script/passes/deps_paths.ex b/lib/elixir_script/passes/deps_paths.ex index d2b3060c..91c71231 100644 --- a/lib/elixir_script/passes/deps_paths.ex +++ b/lib/elixir_script/passes/deps_paths.ex @@ -1,13 +1,21 @@ defmodule ElixirScript.Passes.DepsPaths do @pass 1 + alias ElixirScript.Translator.State - def execute(path, opts) do - if Code.ensure_loaded?(Mix) do - deps = get_deps_paths(Mix.env) - deps ++ [{opts[:app], [path]}] - else - [{opts[:app], [path]}] + def execute(compiler_data, opts) do + State.start_link(opts, []) + + data = cond do + opts.std_lib -> + [{opts[:app], [compiler_data.path]}] + Code.ensure_loaded?(Mix) -> + deps = get_deps_paths(Mix.env) + deps ++ [{opts[:app], [compiler_data.path]}] + true -> + [{opts[:app], [compiler_data.path]}] end + + Map.put(compiler_data, :data, data) end defp get_deps_paths(env) do diff --git a/lib/elixir_script/passes/find_changed_files.ex b/lib/elixir_script/passes/find_changed_files.ex new file mode 100644 index 00000000..d513c1d4 --- /dev/null +++ b/lib/elixir_script/passes/find_changed_files.ex @@ -0,0 +1,21 @@ +defmodule ElixirScript.Passes.FindChangedFiles do + @pass 2 + + alias ElixirScript.Compiler.Cache + alias ElixirScript.Translator.State + @version Mix.Project.config[:version] + + def execute(compiler_data, opts) do + compiler_cache = Cache.get_compiler_cache(compiler_data.path, opts) + new_file_stats = Enum.map(compiler_data.data, fn({_, data}) -> { data.path, data.stat } end) |> Enum.uniq + + changed_files = Cache.get_changed_files(compiler_cache.input_files, new_file_stats) + |> Enum.map(fn {file, state} -> file end) + + + State.deserialize(compiler_cache.state, compiler_data.loaded_modules) + + + Map.put(compiler_data, :changed_files, changed_files) + end +end diff --git a/lib/elixir_script/passes/find_deps.ex b/lib/elixir_script/passes/find_deps.ex index 7fc8b83a..8f6db229 100644 --- a/lib/elixir_script/passes/find_deps.ex +++ b/lib/elixir_script/passes/find_deps.ex @@ -3,8 +3,9 @@ defmodule ElixirScript.Passes.FindDeps do alias ElixirScript.Translator.Utils - def execute(module_filepath_map, _) do - Enum.map(module_filepath_map, &do_find_dependencies(&1)) + def execute(compiler_data, _) do + data = Enum.map(compiler_data.data, &do_find_dependencies(&1)) + Map.put(compiler_data, :data, data) end defp do_find_dependencies({ module, module_data }) do diff --git a/lib/elixir_script/passes/handle_output.ex b/lib/elixir_script/passes/handle_output.ex index 66f636e3..2786781f 100644 --- a/lib/elixir_script/passes/handle_output.ex +++ b/lib/elixir_script/passes/handle_output.ex @@ -1,9 +1,17 @@ defmodule ElixirScript.Passes.HandleOutput do @pass 11 + alias ElixirScript.Translator.State def execute(compiler_data, opts) do + if opts.std_lib do + State.set_module_data(compiler_data.data) + new_std_state = State.serialize() + stdlib_state_path = Path.join([File.cwd!(), "lib", "elixir_script", "translator", "stdlib_state.bin"]) + File.write!(stdlib_state_path, new_std_state) + end + + State.stop() out(compiler_data, opts) - compiler_data end defp out(compiler_output, %{output: nil} = compiler_opts) do diff --git a/lib/elixir_script/passes/load_modules.ex b/lib/elixir_script/passes/load_modules.ex index f0017a80..cd0cbc39 100644 --- a/lib/elixir_script/passes/load_modules.ex +++ b/lib/elixir_script/passes/load_modules.ex @@ -1,16 +1,12 @@ defmodule ElixirScript.Passes.LoadModules do @pass 5 - def execute(data, opts) do - ex_files = Enum.map(data, fn { module, %{path: path} } -> path end) + def execute(compiler_data, opts) do + ex_files = Enum.map(compiler_data.data, fn { module, %{path: path} } -> path end) |> Enum.filter(fn path -> Path.extname(path) == ".ex" || Path.extname(path) == ".exs" end) loaded_modules = Kernel.ParallelRequire.files(ex_files) - - %{ - data: data, - loaded_modules: loaded_modules - } + Map.put(compiler_data, :loaded_modules, loaded_modules) end end diff --git a/lib/elixir_script/passes/module_filepaths.ex b/lib/elixir_script/passes/module_filepaths.ex index d5bbebc1..264b2053 100644 --- a/lib/elixir_script/passes/module_filepaths.ex +++ b/lib/elixir_script/passes/module_filepaths.ex @@ -3,8 +3,11 @@ defmodule ElixirScript.Passes.ModuleFilepaths do alias ElixirScript.Translator.Utils - def execute(deps_paths, opts) do - Enum.reduce(deps_paths, [], fn({dep, paths}, list) -> + + #TODO: Split into smaller passes? + + def execute(compiler_data, opts) do + data = Enum.reduce(compiler_data.data, [], fn({dep, paths}, list) -> file_paths = Enum.flat_map(paths, fn(path) -> Path.join(path, "**/*.{ex,exs,exjs}") @@ -15,6 +18,7 @@ defmodule ElixirScript.Passes.ModuleFilepaths do quoted = path |> File.read! |> Code.string_to_quoted! + |> update_quoted { _, modules } = Macro.postwalk(quoted, [], &get_defmodules(&1, &2, opts)) @@ -27,6 +31,8 @@ defmodule ElixirScript.Passes.ModuleFilepaths do list ++ file_paths end) + + Map.put(compiler_data, :data, data) end defp get_defmodules({:defprotocol, _, [{:__aliases__, _, _} = the_alias, _]} = ast, state, _) do @@ -152,4 +158,20 @@ defmodule ElixirScript.Passes.ModuleFilepaths do Macro.expand_once(ast, env) end end + + defp update_quoted(quoted) do + Macro.prewalk(quoted, fn + ({name, context, parms}) -> + context = if context[:import] == Kernel do + context = Keyword.update!(context, :import, fn(_) -> ElixirScript.Kernel end) + else + context + end + + {name, context, parms} + (x) -> + x + end) + end + end diff --git a/lib/elixir_script/passes/remove_unused.ex b/lib/elixir_script/passes/remove_unused.ex index 7877b74b..5b83426c 100644 --- a/lib/elixir_script/passes/remove_unused.ex +++ b/lib/elixir_script/passes/remove_unused.ex @@ -1,10 +1,12 @@ defmodule ElixirScript.Passes.RemoveUnused do @pass 4 - def execute(module_filepath_map, opts) do - Enum.filter(module_filepath_map, fn({module_name, _}) -> - module_found_in_deps(module_name, module_filepath_map, [opts[:app]]) == true + def execute(compiler_data, opts) do + data = Enum.filter(compiler_data.data, fn({module_name, _}) -> + module_found_in_deps(module_name, compiler_data.data, [opts[:app]]) == true end) + + Map.put(compiler_data, :data, data) end defp module_found_in_deps(module_name, module_filepath_map, apps_not_to_touch) do diff --git a/lib/elixir_script/passes/write_cache.ex b/lib/elixir_script/passes/write_cache.ex new file mode 100644 index 00000000..79cea1e1 --- /dev/null +++ b/lib/elixir_script/passes/write_cache.ex @@ -0,0 +1,20 @@ +defmodule ElixirScript.Passes.WriteCache do + alias ElixirScript.Compiler.Cache + alias ElixirScript.Translator.State + + def execute(compiler_data, opts) do + compiler_cache = Cache.get_compiler_cache(compiler_data.path, opts) + + State.set_module_data(compiler_data.data) + new_state = State.serialize() + new_file_stats = Enum.map(compiler_data.data, fn({_, data}) -> { data.path, data.stat } end) |> Enum.uniq + + compiler_cache = %{compiler_cache | input_files: new_file_stats, state: new_state } + + Cache.write(compiler_data.path, compiler_cache) + + compiler_data + end + + +end diff --git a/lib/elixir_script/translator/lexical_scope.ex b/lib/elixir_script/translator/lexical_scope.ex index c2cbaa40..b90c1971 100644 --- a/lib/elixir_script/translator/lexical_scope.ex +++ b/lib/elixir_script/translator/lexical_scope.ex @@ -17,8 +17,7 @@ defmodule ElixirScript.Translator.LexicalScope do export_vars: [{atom, atom | non_neg_integer}] | nil, lexical_tracker: nil, caller: t | nil, - env: nil, - module_data: [{atom, %{}}] + env: nil } defstruct [ @@ -37,8 +36,7 @@ defmodule ElixirScript.Translator.LexicalScope do export_vars: nil, lexical_tracker: nil, caller: nil, - env: nil, - module_data: [] + env: nil ] def env(scope) do @@ -79,26 +77,24 @@ defmodule ElixirScript.Translator.LexicalScope do } end - def module_scope(ElixirScript.Temp, filename, env, module_data) do + def module_scope(ElixirScript.Temp, filename, env) do env = %ElixirScript.Translator.LexicalScope { module: ElixirScript.Temp, file: filename, requires: [], functions: [], - env: env, - module_data: module_data + env: env } add_import(env, ElixirScript.Kernel) end - def module_scope(module_name, filename, env, module_data) do + def module_scope(module_name, filename, env) do module = ElixirScript.Translator.State.get_module(module_name) env = %ElixirScript.Translator.LexicalScope { module: module_name, file: filename, requires: [], functions: [{ module.name, module.functions}], - env: env, - module_data: module_data + env: env } add_import(env, ElixirScript.Kernel) diff --git a/lib/elixir_script/translator/module_collector.ex b/lib/elixir_script/translator/module_collector.ex deleted file mode 100644 index 04c86c7a..00000000 --- a/lib/elixir_script/translator/module_collector.ex +++ /dev/null @@ -1,257 +0,0 @@ -defmodule ElixirScript.Translator.ModuleCollector do - @moduledoc false - - # This module is responsible for - # taking the compiler input and parsing out any modules found - # These modules are then added to ElixirScript.Translator.State - - alias ElixirScript.Translator.State - alias ElixirScript.Translator.Utils - - @function_types [:def, :defp, :defgen, :defgenp] - - - def process_modules(modules, app_name) do - Enum.map(modules, fn - { :__block__, _, list } -> - {modules, not_modules} = Enum.partition(list, - fn - {type, _, _ } when type in [:defprotocol, :defimpl, :defmodule] -> - true - _ -> - false - end) - - temp_module = case not_modules do - [] -> - [] - _ -> - [{:defmodule, [], [{:__aliases__, [], [:ElixirScript, :Temp]}, [do: { :__block__, [], not_modules }]]}] - end - - modules ++ temp_module - - {type, _, _ } = x when type in [:defprotocol, :defimpl, :defmodule] -> - x - x -> - {:defmodule, [], [{:__aliases__, [], [:ElixirScript, :Temp]}, [do: { :__block__, [], [x] }]]} - end) - |> List.flatten - |> Enum.each(fn(m) -> - Macro.postwalk(m, &do_process_modules(&1, app_name)) - end) - end - - def do_process_modules({:defprotocol, _, [{:__aliases__, _, _} = the_alias, [do: {:__block__, _, _} = block]]}, app_name) do - %{def: functions, defp: _ } = get_functions_from_module(block) - ElixirScript.Translator.State.add_protocol(Utils.quoted_to_name(the_alias), functions, app_name) - end - - def do_process_modules({:defprotocol, _, [{:__aliases__, _, _} = the_alias, [do: spec]]}, app_name) do - %{def: functions, defp: _ } = get_functions_from_module({:__block__, [], [spec]}) - ElixirScript.Translator.State.add_protocol(Utils.quoted_to_name(the_alias), functions, app_name) - end - - def do_process_modules({:defimpl, _, [ {:__aliases__, _, _} = the_alias, [for: type], [do: {:__block__, context, spec}] ]}, app_name) do - ElixirScript.Translator.State.add_protocol_impl(Utils.quoted_to_name(the_alias), type, {:__block__, context, spec}, app_name) - end - - def do_process_modules({:defimpl, _, [ {:__aliases__, _, _} = the_alias, [for: type], [do: spec] ]}, app_name) do - ElixirScript.Translator.State.add_protocol_impl(Utils.quoted_to_name(the_alias), type, {:__block__, [], [spec]}, app_name) - end - - def do_process_modules({:defmodule, _, [{:__aliases__, _, [:ElixirScript, :Temp]}, [do: body]]} = ast, app_name) do - body - |> make_module([:ElixirScript, :Temp], app_name) - |> State.add_module - - ast - end - - def do_process_modules({:defmodule, _, [{:__aliases__, _, _}, [do: _]]} = ast, app_name) do - do_module_processing(ast, app_name) - ast - end - - def do_process_modules(ast, _) do - ast - end - - defp do_module_processing({:defmodule, _, [{:__aliases__, _, name}, [do: body]]}, app_name) do - { body, inner_modules } = make_inner_module_aliases(name, body) - - aliases = Enum.map(inner_modules, fn - ({:defmodule, _, [{:__aliases__, _, inner_module_name}, [do: inner_module_body]]}) -> - { :alias, [], [{:__aliases__, [alias: false], name ++ inner_module_name}, [as: {:__aliases__, [alias: false], inner_module_name }] ] } - end) - - Enum.each(inner_modules, fn - ({:defmodule, context1, [{:__aliases__, context2, inner_module_name}, [do: inner_module_body]]}) -> - - module_name = Utils.quoted_to_name({:__aliases__, [], tl(name) ++ inner_module_name}) - State.delete_module_by_name(module_name) - - this_module_aliases = aliases -- [{ :alias, [], [{:__aliases__, [alias: false], name ++ inner_module_name}, [as: {:__aliases__, [alias: false], inner_module_name }] ] }] - - {:defmodule, context1, [{:__aliases__, context2, name ++ inner_module_name}, [do: add_aliases_to_body(inner_module_body, this_module_aliases)]]} - |> do_module_processing(app_name) - end) - - module = make_module(add_aliases_to_body(body, aliases), name, app_name) - State.add_module(module) - end - - defp add_aliases_to_body(body, aliases) do - case body do - { :__block__, context, body } -> - { :__block__, context, aliases ++ List.wrap(body) } - _ -> - { :__block__, [], aliases ++ List.wrap(body) } - end - end - - defp make_module(body, name, app_name) do - # Finds use expressions and expands them - body = case body do - {:__block__, context, list } -> - list = Enum.map(list, fn - {:use, _, [module, _] } = using -> - {:use, handle_use_expression(using, module) } - {:use, _, [module] } = using -> - {:use, handle_use_expression(using, module) } - ast -> - {:expanded, ast} - end) - |> Enum.reduce([], fn - {:use, ast}, state -> - case ast do - {:__block__, _, list} -> - state ++ list - _ -> - state ++ [ast] - end - - {:expanded, ast}, state -> - state ++ [ast] - end) - - {:__block__, context, list} - - _ -> - body - end - - %{def: functions, defp: private_functions, defgen: generators, defgenp: private_generators } = get_functions_from_module(body) - js_imports = get_js_imports_from_module(body) - - %ElixirScript.Module{app_name: app_name, name: Utils.quoted_to_name({:__aliases__, [], name}) , body: body, - functions: functions ++ generators, private_functions: private_functions ++ private_generators, js_imports: js_imports } - end - - def handle_use_expression(using_ast, module) do - module = Utils.quoted_to_name(module) - - eval = """ - require #{inspect module} - __ENV__ - """ - {env, _} = Code.eval_string(eval, [], State.get().compiler_opts.env) - - - case Macro.expand(using_ast, env) do - {:__block__, _, - [{:__block__, _, - [{:require, _, _}, - {{:., _, [_, :__using__]}, _, _} = ast]}]} -> - Macro.expand_once(ast, env) - end - end - - defp make_inner_module_aliases(name, body) do - case body do - nil -> - { { :__block__, [], [] }, [] } - - {:__block__, context, list2 } -> - { list2, inner_modules } = Enum.partition(list2, fn(x) -> - case x do - {:defmodule, _, [{:__aliases__, _, inner_module_name}, [do: inner_module_body]]} -> - false - _ -> - true - end - end) - - { {:__block__, context, list2}, inner_modules } - {:defmodule, _, [{:__aliases__, context, inner_module_name}, [do: inner_module_body]]} = mod -> - { {:__block__, context, [] }, [mod] } - _ -> - { body, [] } - end - end - - defp get_functions_from_module({:__block__, _, list}) do - Enum.reduce(list, %{ def: Keyword.new, defp: Keyword.new, defgen: Keyword.new, defgenp: Keyword.new }, fn - ({type, _, [{:when, _, [{name, _, params} | _guards] }, _] }, state) when type in @function_types and is_atom(params) -> - arity = 0 - - add_function_to_map(state, type, name, arity) - - ({type, _, [{:when, _, [{name, _, params} | _guards] }, _] }, state) when type in @function_types -> - arity = if is_nil(params), do: 0, else: length(params) - - add_function_to_map(state, type, name, arity) - - ({type, _, [{name, _, params}, _]}, state) when type in @function_types and is_atom(params) -> - arity = 0 - - add_function_to_map(state, type, name, arity) - - ({type, _, [{name, _, params}, _]}, state) when type in @function_types -> - arity = if is_nil(params), do: 0, else: length(params) - add_function_to_map(state, type, name, arity) - - ({type, _, [{name, _, params}]}, state) when is_atom(params) and type in @function_types -> - arity = 0 - add_function_to_map(state, type, name, arity) - - ({type, _, [{name, _, params}]}, state) when type in @function_types -> - arity = length(params) - add_function_to_map(state, type, name, arity) - - _, state -> - state - - end) - end - - defp get_functions_from_module(_) do - %{ def: Keyword.new, defp: Keyword.new } - end - - defp add_function_to_map(map, type, name, arity) do - list = Map.get(map, type) - - if {name, arity} in list do - map - else - Map.put(map, type, list ++ [{ name, arity }]) - end - end - - defp get_js_imports_from_module({:__block__, _, list}) do - Enum.reduce(list, MapSet.new, fn - ({{:., _, [{:__aliases__, _, [:JS]}, :import]}, _, [name, path]}, state) -> - {name, _} = Code.eval_quoted(name) - MapSet.put(state, {name, path}) - - _, state -> - state - end) - end - - - defp get_js_imports_from_module(_) do - MapSet.new - end -end diff --git a/lib/elixir_script/translator/state.ex b/lib/elixir_script/translator/state.ex index d7a1c3ca..e45ccc8a 100644 --- a/lib/elixir_script/translator/state.ex +++ b/lib/elixir_script/translator/state.ex @@ -11,13 +11,12 @@ defmodule ElixirScript.Translator.State do def start_link(compiler_opts, loaded_modules) do Agent.start_link(fn -> - %{ compiler_opts: compiler_opts, modules: Map.new, std_lib_map: build_standard_lib_map(), added_modules: MapSet.new, loaded_modules: loaded_modules } + %{ compiler_opts: compiler_opts, modules: Keyword.new, std_lib_map: build_standard_lib_map(), loaded_modules: loaded_modules } end, name: __MODULE__) end def serialize() do Agent.get(__MODULE__, fn(state) -> - state = Map.delete(state, :added_modules) :erlang.term_to_binary(state) end) end @@ -26,7 +25,7 @@ defmodule ElixirScript.Translator.State do Agent.update(__MODULE__, fn state -> frozen_state = :erlang.binary_to_term(frozen_state) modules = Map.delete(frozen_state.modules, ElixirScript.Temp) - %{ state | modules: modules, std_lib_map: frozen_state.std_lib_map, added_modules: MapSet.new, loaded_modules: loaded_modules } + %{ state | modules: modules, std_lib_map: frozen_state.std_lib_map, loaded_modules: loaded_modules } end) end @@ -55,67 +54,14 @@ defmodule ElixirScript.Translator.State do |> Map.put(Process, ElixirScript.Process) end - def add_module(module) do + def set_module_data(module_data) do Agent.update(__MODULE__, fn state -> - do_add_module_to_state(state, module) + keys = Map.values(state.std_lib_map) + data = Keyword.take(state.modules, keys) + %{ state | modules: Keyword.merge(data, module_data) } end) end - def delete_module_by_name(module_name) do - Agent.update(__MODULE__, fn state -> - %{ state | modules: Map.delete(state.modules, module_name ), added_modules: Set.delete(state.added_modules, module_name) } - end) - end - - def add_protocol(name, functions, app_name) do - Agent.update(__MODULE__, fn state -> - proto = Map.get(state.modules, do_get_module_name(name, state)) - - proto = if proto == nil do - %ElixirScript.Module{ app_name: app_name, name: name, functions: functions, type: :protocol } - else - %ElixirScript.Module{proto | functions: functions, type: :protocol } - end - - do_add_module_to_state(state, proto) - end) - end - - def add_protocol_impl(protocol, type, impl, app_name) when is_list(type) do - Enum.each(type, fn x -> - add_protocol_impl(protocol, x, impl, app_name) - end) - end - - def add_protocol_impl(protocol, type, impl, app_name) do - Agent.update(__MODULE__, fn state -> - protocol_name = Atom.to_string(do_get_module_name(protocol, state)) - type_name = Atom.to_string(Utils.quoted_to_name(type)) - module_name = String.to_atom(protocol_name <> ".DefImpl." <> type_name) - - proto_impl = %ElixirScript.Module{ app_name: app_name, name: module_name, body: impl, impl_type: type, type: :protocol_implementation } - - do_add_module_to_state(state, proto_impl) - end) - end - - defp do_add_module_to_state(state, module) do - update_added = case state.modules[module.name] do - %ElixirScript.Module{ type: :protocol } = old_module -> - old_module.functions !== module.functions - %ElixirScript.Module{} = old_module -> - old_module.body !== module.body - nil -> - true - end - - if update_added do - %{ state | modules: Map.put(state.modules, module.name, module), added_modules: Set.put(state.added_modules, module.name) } - else - %{ state | modules: Map.put(state.modules, module.name, module) } - end - end - def get do Agent.get(__MODULE__, &(&1)) end @@ -165,19 +111,7 @@ defmodule ElixirScript.Translator.State do defp do_get_module(name) do Agent.get(__MODULE__, fn(state) -> - Map.get(state.modules, do_get_module_name(name, state)) - end) - end - - def add_module_reference(module_name, module_ref) do - Agent.update(__MODULE__, fn(state) -> - case Map.get(state.modules, do_get_module_name(module_name, state)) do - nil -> - state - module -> - module = %{ module | module_refs: Enum.uniq(module.module_refs ++ [module_ref]) } - %{ state | modules: Map.put(state.modules, module.name, module) } - end + Keyword.get(state.modules, do_get_module_name(name, state)) end) end @@ -186,20 +120,19 @@ defmodule ElixirScript.Translator.State do nil -> [] module -> - module.module_refs + module.deps end end def list_modules() do - Agent.get(__MODULE__, fn(x) -> - Map.values(x.modules) + Agent.get(__MODULE__, fn(state) -> + Keyword.values(state.modules) end) end def list_module_names() do - Agent.get(__MODULE__, fn(x) -> - Map.values(x.modules) - |> Enum.map(fn(x) -> x.name end) + Agent.get(__MODULE__, fn(state) -> + Keyword.keys(state.modules) end) end From f84c5d8d3cb310baf58decd143474cbb569b5081 Mon Sep 17 00:00:00 2001 From: Frank van Eldijk Date: Mon, 17 Oct 2016 14:37:58 +0200 Subject: [PATCH 312/860] Modified CHANGELOG.MD to adhere keepachangelog format --- CHANGELOG.md | 578 ++++++++++++++++++++++++++------------------------- 1 file changed, 292 insertions(+), 286 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 29112bad..69ea33b5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,20 +1,29 @@ -# v0.22.0 +# Change Log +All notable changes to this project will be documented in this file. -* Enhancements - * Add `defgen` and `defgenp` for defining public and private generators - * Add `yield/0`, `yield/1`, and `yield_to\1` to `Kernel` - * Updated output folder structure. stdlib code will now go in an `elxiir` folder under the output paths while generated app code will go into an `app` folder under the output path +The format is based on [Keep a Changelog](http://keepachangelog.com/) +and this project adheres to [Semantic Versioning](http://semver.org/). -* Breaking - * All process macros and functions now expect to receive and/or work using generators as entry points. Using functions defined with `def` or `defp` will not work correctly with them +## [Unreleased] +### Changed +- Changed CHANGELOG.md to adhere the format from Keep a Changelog -* Bug fixes - * Correctly returning list if list is only item in body +## [0.22.0] - 2016-10-16 +### Added +- `defgen` and `defgenp` for defining public and private generators +- `yield/0`, `yield/1`, and `yield_to\1` to `Kernel` -# v0.21.0 -* Enhancements - * This is the first release with early support for processes in elixirscript. Creating a process only works currently using `spawn/1`, `spawn_link/1`, and `spawn_monitor/1`. Inside of a process, you can use functions such as `send` and `receive`, along with some defined in the `Process` module. From outside of a process, you can send messages to a process, but you cannot receive a message from a process. Eventually all code will run inside processes and this restriction will naturally lift. - * The `Process` module has been implemented with the following functions: +### Changed +- Updated output folder structure. stdlib code will now go in an `elxiir` folder under the output paths while generated app code will go into an `app` folder under the output path +- All process macros and functions now expect to receive and/or work using generators as entry points. Using functions defined with `def` or `defp` will not work correctly with them + +### Fixed +- Correctly returning list if list is only item in body + +## [0.21.0] - 2016-06-28 +### Added +- This is the first release with early support for processes in elixirscript. Creating a process only works currently using `spawn/1`, `spawn_link/1`, and `spawn_monitor/1`. Inside of a process, you can use functions such as `send` and `receive`, along with some defined in the `Process` module. From outside of a process, you can send messages to a process, but you cannot receive a message from a process. Eventually all code will run inside processes and this restriction will naturally lift. +- The `Process` module has been implemented with the following functions: * `alive?/1` * `delete/1` * `demonitor/1` @@ -35,293 +44,290 @@ * `unlink/1` * `unregister/1` * `whereis/1` - * The `receive` special form has been implemented with the above caveat - * The following have been implemented on `Kernel`: +- The `receive` special form has been implemented with the above caveat +- The following have been implemented on `Kernel`: * `spawn/1` * `spawn_link/1` * `spawn_monitor/1` * `send/2` * `make_ref/0` - - -* Fixed - * Scoping on `fn` and `def` - -# v0.20.0 -* Enhancements - * Add `ElixirScript.Watcher` module and `elixirscript.watch` mix task - * Add logging MatchError exceptions to better show terms that don't match - -# v0.19.0 -* Enhancements - * Added elixir_script mix compiler - -* Breaking - * `Html`, `View`, and `VDom` modules have been removed - -# v0.18.0 -* Enhancements - * Better support for macros. Macros should be defined in .ex or .exs files. ElixirScript code should be in .exjs files - -* Breaking - * The above functionality will cause either compiler errors or no output. Please change extensions of ElixirScript code to .exjs - -* Deprecations - * `Html`, `View`, and `VDom` modules will be removed in the next version as they can now be replicated using macros - -# v0.17.0 -* Enhancements - * Incremental Compilation: - ElixirScript will now only build files and modules that have changed since the last build - * Added `output` as an option for compiler functions. This controls whether output is returned as a list of tuples, send to stdout, or saved to a file path - * Added `:full_build` as an option for compiler functions and `--full-build` option to CLI. These force the compiler to perform a full build - * Added `--version` option to CLI. Outputs current version of elixirscript - * Added `--std-lib` option to CLI. Takes a path and adds the stdlib to that path - -* Breaking - * Removed `--core` option from CLI and `:core` compiler option. - * Renamed `copy_core_to_destination` to `copy_stdlib_to_destination` - -# v0.16.0 -* Enhancements - * Bitstring pattern matching - * Bitstrings in for comprehensions - * Functions with catch, after, else clauses - * `with` special form - * Pin operator in map keys and function clauses - * Added `Kernel.object/1` function to make it more natural to create a JavaScript object with string keys - Elixirscript, by default turns the following, `%{a: "b"}` into `{[Symbol.for("a")]: "b"}` in JavaScript. In order to get string keys, - one would have to do `%{"a" => "b"}` which turns into `{a: "b"}` in JavaScript. With `Kernel.object`, you can create string keyed maps - conveniently, `object(a: "b")` which turns into `{a: "b"}`. - - **NOTE**: when updating the created by, you still have to use the string form `%{ my_map | "a" => "c" }` - -* Bugfixes - * Optional parameters should now work as expected - -* Breaking - * `JS.update(object, property, value)` has been removed and replaced with `JS.update(object, map)` - This allows you to update multiple values on a javascript object at once. - -# v0.15.2 -* Enhancements - * Support for variables as map keys - -* Bug fixes - * Fixed protocol implementations for Integer and Float which where not recognized - * Fixed calling properties on non-objects - -# v0.15.1 -* Bug fixes - * Fixed View module so that an element can have multiple elements within - * Removed `catch` as a javascript keyword to filter - * Fixed struct implementation so that lists of atoms for fields are compiled correctly - * Fixed head-tail pattern match to allow for more complicated scenarios - * Fixed ModuleCollector to properly alias inner modules - * Fixed raise translation to properly translate when string messages are given - -# v0.15.0 -* Enhancements - * `alias`, `require`, and `import` now work inside lexical scopes - * `__ENV__` and `__CALLER__` are now supported - * Some of the standard library originally written in JavaScript has been rewritten - in Elixir. - * Added `JS.import/1`, `JS.typeof/1`,`JS.instanceof/1`, and `JS.global/1` - * Added support for multi alias/require/imports statements - * Generated JavaScript export statements are now default exports - * When output is sent to standard out, there are now markers to specify where - each module begins as well as what the file name would be. - For the end of a file, `//:ENDFILE` is used. For the file name, `//:ENDFILENAME` - is used where `` is the name of the file - -* Breaking - * `compile`, `compile_path`, and `compile_quoted` opts parameter now expects a map - * The `stdlib` compiler option is now `core`. The `stdlib_path` compiler options is now - `core_path` - -# v0.14.1 -* Enhancements - * Removed .DS_Store and LICENSE from output - -# v0.14.0 -* Breaking - * Renamed `ex2js` to `elixirscript`. This effects the escript as well as the - mix task -* Enhancements - * Structs are now translated into classes - * Structs and Tuples now match on their types - * Can now match on JavaScript classes. Works just like matching on structs: +## Fixed +- Scoping on `fn` and `def` + +## [0.20.0] - 2016-05-14 +### Added +- `ElixirScript.Watcher` module and `elixirscript.watch` mix task +- logging MatchError exceptions to better show terms that don't match + +## [0.19.0] - 2016-04-30 +### Added +- elixir_script mix compiler + +### Removed +- `Html`, `View`, and `VDom` modules have been removed + +## [0.18.0] - 2016-04-08 +### Changed +- Better support for macros. Macros should be defined in .ex or .exs files. ElixirScript code should be in .exjs files + +**NOTE**: The above functionality will cause either compiler errors or no output. Please change extensions of ElixirScript code to .exjs + +### Deprecated +- `Html`, `View`, and `VDom` modules will be removed in the next version as they can now be replicated using macros + +## [0.17.0] - 2016-03-31 +### Added +- `output` as an option for compiler functions. This controls whether output is returned as a list of tuples, send to stdout, or saved to a file path +- `:full_build` as an option for compiler functions and `--full-build` option to CLI. These force the compiler to perform a full build +- `--version` option to CLI. Outputs current version of elixirscript +- `--std-lib` option to CLI. Takes a path and adds the stdlib to that path + +### Changed +- Renamed `copy_core_to_destination` to `copy_stdlib_to_destination` +- Incremental Compilation: ElixirScript will now only build files and modules that have changed since the last build + +### Removed +- `--core` option from CLI and `:core` compiler option. + +## [0.16.0] 2016-02-27 +### Added +- Bitstring pattern matching +- Bitstrings in for comprehensions +- Functions with catch, after, else clauses +- `with` special form +- Pin operator in map keys and function clauses +- Added `Kernel.object/1` function to make it more natural to create a JavaScript object with string keys. Elixirscript, by default turns the following, `%{a:"b"}` into `{[Symbol.for("a")]: "b"}` in JavaScript. In order to get string keys, one would have to do `%{"a" => "b"}` which turns into `{a: "b"}` in JavaScript. With `Kernel.object`, you can create string keyed maps conveniently, `object(a: "b")` which turns into `{a: "b"}`. + + **NOTE**: when updating the created by, you still have to use the string form `%{ my_map | "a" => "c" }` + +### Removed +- `JS.update(object, property, value)` has been removed and replaced with `JS.update(object, map)`. This allows you to update multiple values on a javascript object at once. + +### Fixed +- Optional parameters should now work as expected + +## [0.15.2] - 2016-02-21 +### Addded +- Support for variables as map keys + +### Fixed +- Protocol implementations for Integer and Float which where not recognized +- Calling properties on non-objects + +## [0.15.1] - 2016-02-19 +### Removed +- Removed `catch` as a javascript keyword to filter + +### Fixed +- Fixed View module so that an element can have multiple elements within +- struct implementation so that lists of atoms for fields are compiled correctly +- head-tail pattern match to allow for more complicated scenarios +- ModuleCollector to properly alias inner modules +- Raise translation to properly translate when string messages are given + +## [0.15.0] - 2016-01-26 +### Added +- `__ENV__` and `__CALLER__` are now supported +- `JS.import/1`, `JS.typeof/1`,`JS.instanceof/1`, and `JS.global/1` +- Support for multi alias/require/imports statements + +### Changed +- `alias`, `require`, and `import` now work inside lexical scopes +- Some of the standard library originally written in JavaScript has been rewritten in Elixir. +- Generated JavaScript export statements are now default exports +- When output is sent to standard out, there are now markers to specify where each module begins as well as what the file name would be. For the end of a file, `//:ENDFILE` is used. For the file name, `//:ENDFILENAME` is used where `` is the name of the file +- `compile`, `compile_path`, and `compile_quoted` opts parameter now expects a map +- The `stdlib` compiler option is now `core`. The `stdlib_path` compiler options is now `core_path` + +## [0.14.1] - 2015-12-07 +### Removed +- .DS_Store and LICENSE from output + +## [0.14.0] - 2015-12-06 +### Added +- Can now implement protocols using JavaScript types ```elixir - def my_func(%HTMLElement{id: "myId"}) + defimpl MyProtocol, for: HTMLElement ``` - * Can now implement protocols using JavaScript types +- virtual-dom JavaScript library +- ElixirScript.Html module for defining a virtual-dom tree +- ElixirScript.VDom module for manipulating the virtual-dom tree created using the ElixirScript.Html module +- Added ElixirScript.View module for handling view state and rendering virtual-dom +- Added `stdlib_path` compiler option to specify the es6 path to the standard library. If used, elixir.js will not be exported with the compiled modules + +### Changed +- Renamed `ex2js` to `elixirscript`. This effects the escript as well as the + mix task +- Structs are now translated into classes +- Structs and Tuples now match on their types +- Can now match on JavaScript classes. Works just like matching on structs: ```elixir - defimpl MyProtocol, for: HTMLElement + def my_func(%HTMLElement{id: "myId"}) ``` - * Added virtual-dom JavaScript library - * Added ElixirScript.Html module for defining a virtual-dom tree - * Added ElixirScript.VDom module for manipulating the virtual-dom tree created - using the ElixirScript.Html module - * Added ElixirScript.View module for handling view state and rendering virtual-dom - * Added `stdlib_path` compiler option to specify the es6 path to the standard library. - If used, elixir.js will not be exported with the compiled modules - * Moved non-elixir JavaScript code into `core` es6 module. This will hopefully +- Moved non-elixir JavaScript code into `core` es6 module. This will hopefully make it so ElixirScript Standard Library modules can be defined in Elixir soon. - -# v0.13.0 -* Enhancements - * Added `Base` module with function: encode64, decode64, and decode64! - * Added `String` module - * Added `Bitwise` module - * Added `Map` module - * Added `MapSet` module - * Added `Set` module - * Protocol support - * Added `Collectable`, `Enumerable`, `Inspect`, `List.Chars`, and `String.Chars` protocols. - The only one currently being used in the Standard Library, however, is String.Chars - -# v0.12.0 -* Enhancements - * Updated tuple implementation. It's now a class. - * Replaced pattern matching library with custom one - * Added PostOffice. Only thing that current uses it is Agent - * Removed erlang.js. Moved data types to Kernel.SpecialForms - * `else` now works for try expressions - * for now works with `into` for lists - -# v0.11.0 -* Enhancements - * `import` works with all options - * Added `JS` module with `new`, `mutate`, `import` macros - * All Standard libraries are rolled up into one elixir.js file and imported from that - * Added `Keyword` module with functions, `has_key?` and `get` - * Added `Agent` module with functions, `start`, `get`, `update`, and `get_and_update` - * Map keys are now correctly turned into their atom counterparts if atom keys are used - * Modules no longer export a default object - * `alias` now translates to a namespace import unless `default` option is given - -* Breaking - * `Mutable.update` has been replaced by `JS.update` - * `transpile`, `transpile_quoted`, and `transpile_path` are now `compile`, `compile_quoted`, and `compile_path` - -# v0.10.0 -* Enhancements - * Added `env` option for `ElixirScript.transpile` adding macros for compilation - * Fixed `case` implementation to add `this` to call - * Updated `Kernel` module to translate some functions to it's JavaScript equivalent - * Added `Logger` that translates Logger functions to console - -# v0.9.0 -* Enhancements - * an implementation for quote. Currently ignores `:location` and `:context` options - * an implementation for unquote and unquote_splicing - -# v0.8.0 -* Enhancements - * Can now support catch blocks in try expressions - * Wrapped try's in function closure to make sure they return a value; - * Added receive - * Updated pattern matching implementation - -# v0.7.0 -* Enhancements - * Can now support rescue and after blocks in try expressions - -# v0.6.5 -* Enhancements - * Now using the JS code generator from elixir-estree for code generation, improving speed of transpilation - * the parse functions in the ElixirScript module have been renamed to transpile - -# v0.6.0 - * Enhancements - * Made the Tuple, Range and BitString data structures more immutable - * Now replacing characters that can't be used in variable and function names in JavaScript with - something that it (i.e. `match?` -> `match__qmark__`) - * Implemented Integer module - * Atom now translates to an ES6 Symbol - * List now translates to a frozen JS Array - * Added iterators for Range and BitString - * Updated the pattern match binding to use ES6 destructuring for lists and tuples - * Inner modules are now split out into their own files +## [0.13.0] - 2015-10-26 +### Added +- `Base` module with function: encode64, decode64, and decode64! +- `String` module +- `Bitwise` module +- `Map` module +- `MapSet` module +- `Set` module +- Protocol support +- Added `Collectable`, `Enumerable`, `Inspect`, `List.Chars`, and `String.Chars` protocols. The only one currently being used in the Standard Library, however, is String.Chars + +## [0.12.0] - 2015-09-23 +### Added +- Added PostOffice. Only thing that current uses it is Agent + +### Changed +- Updated tuple implementation. It's now a class. +- Replaced pattern matching library with custom one +- Moved data types to Kernel.SpecialForms +- `else` now works for try expressions +- for now works with `into` for lists + +### Removed +- Removed erlang.js. + +## [0.11.0] - 2015-09-17 +### Added +- Added `JS` module with `new`, `mutate`, `import` macros +- Added `Keyword` module with functions, `has_key?` and `get` +- Added `Agent` module with functions, `start`, `get`, `update`, and `get_and_update` + +### Changed +- Map keys are now correctly turned into their atom counterparts if atom keys are used +- `import` works with all options +- `Mutable.update` has been replaced by `JS.update` +- `transpile`, `transpile_quoted`, and `transpile_path` are now `compile`, `compile_quoted`, and `compile_path` +- All Standard libraries are rolled up into one elixir.js file and imported from that +- Modules no longer export a default object +- `alias` now translates to a namespace import unless `default` option is given + +## [0.10.0] - 2015-09-02 +### Added +- Added `env` option for `ElixirScript.transpile` adding macros for compilation +- Added `Logger` that translates Logger functions to console + +### Changed +- Updated `Kernel` module to translate some functions to it's JavaScript equivalent + +### Fixed +- Fixed `case` implementation to add `this` to call + +## [0.9.0] - 2015-08-30 +### Added +- an implementation for quote. Currently ignores `:location` and `:context` options +- an implementation for unquote and unquote_splicing + +## [0.8.0] - 2015-08-15 +### Added +- Can now support catch blocks in try expressions +- Added receive + +### Changed +- Updated pattern matching implementation +- Wrapped try's in function closure to make sure they return a value; + +## [0.7.0] - 2015-08-01 +### Added +- Can now support rescue and after blocks in try expressions + +## [0.6.5] - 2015-07-13 +### Changed +- Now using the JS code generator from elixir-estree for code generation, improving speed of transpilation +- the parse functions in the ElixirScript module have been renamed to transpile + +## [0.6.0] - 2015-07-02 +### Added +- Added iterators for Range and BitString +- Now replacing characters that can't be used in variable and function names in JavaScript with something that it (i.e. `match?` -> `match__qmark__`) +- Implemented Integer module + +### Changed +- Made the Tuple, Range and BitString data structures more immutable +- Atom now translates to an ES6 Symbol +- List now translates to a frozen JS Array +- Updated the pattern match binding to use ES6 destructuring for lists and tuples +- Inner modules are now split out into their own files * Standard lib is now exported with file output from cli * Standard lib modules are now automatically imported * No longer have to define modules via aliases ahead of time. They will be automatically be resolved and made into JavaScript import statements -# v0.5.0 - * Enhancements - * For statements now work with pattern matching tuples - * Improved function chaining - * added `from` clause to `import`, `alias`, and `require` so that the import path can be overridden - * `alias` now acts like `require` in that it is translated into an import default statement - * modules now export a default object with def functions added as properties on it. - * for function closures, now calling by using `.call(this)` so that `this` is available inside of it - -# v0.4.0 - * Enhancements - * bitstrings - * Better Pattern Matching (Does not support bitstrings yet) - * Capture Operator - * Fixed multi arity implementation - * Updated variable implementation to match Elixir's (i.e. Reusing the same variable name creates a new one in the background) - * Throwing ParseError for SpecialForms currently not supported - * Added more functions from the list standard library - -# v0.3.0 - * Enhancements - * function and case guards - * function and case pattern matching - * Can now use ^ on a variable during assignment - -# v0.2.1 - * Enhancements - * Renamed project to ElixirScript - * Reduced escript file size - -# v0.2.0 - * Enhancements - * Pipe operator - * String interpolation - * Adding more functions to the Kernel module - * Now checking to see if a function is a Kernel function and prepending Kernel to it - * Now turning Atoms into an Atom javascript object instead of a Symbol - * Now turning tuples into a Tuple javascript object - * Fully implemented Tuple module - * Fully implemented Atom module - * Fully implemented Range module - * Can now call properties and zero parameter functions correctly - * case, cond, and if are now turned into if statements wrapped in function closures - * Anonymous functions are now turned into anonymous functions in javascript insteed of arrow functions - -# v0.1.0 - -* Enhancements - * From standard library implemented: - * Enum.map - * Kernel.tl - * Kernel.hd - * Logger - - * Implemented language features: - * All primitives except bitstrings - * defmodule - * import, alias, and require - * case, cond, if - * def, defp - * defstruct, defexception - * raise - * multiple arity functions - * basic binary operations - * for without into - - * Missing features: - * bitstrings - * pattern matching - * macros - * actors - * try - * regular expressions - * string interpolation - * Most of standard library +## [0.5.0] - 2015-05-31 +### Added +- added `from` clause to `import`, `alias`, and `require` so that the import path can be overridden + +### Changed +- For statements now work with pattern matching tuples +- Improved function chaining +- `alias` now acts like `require` in that it is translated into an import default statement +- modules now export a default object with def functions added as properties on it. +- for function closures, now calling by using `.call(this)` so that `this` is available inside of it + +## [0.4.0] - 2015-05-05 +### Added +- bitstrings +- Better Pattern Matching (Does not support bitstrings yet) +- Capture Operator +- Added more functions from the list standard library + +### Changed +- Updated variable implementation to match Elixir's (i.e. Reusing the same variable name creates a new one in the background) + +### Fixed +- Fixed multi arity implementation + +## [0.3.0] - 2015-04-23 +### Added +- function and case guards +- function and case pattern matching + +### Changed +- Can now use ^ on a variable during assignment + +## [0.2.1] - 2015-04-14 +### Changed +- Renamed project to ElixirScript +- Reduced escript file size + +## [0.2.0] - 2015-04-12 +### Added +- Pipe operator +- String interpolation +- Adding more functions to the Kernel module +- Fully implemented Tuple module +- Fully implemented Atom module +- Fully implemented Range module + +### Changed +- Now checking to see if a function is a Kernel function and prepending Kernel to it +- Now turning Atoms into an Atom javascript object instead of a Symbol +- Now turning tuples into a Tuple javascript object +- Can now call properties and zero parameter functions correctly +- case, cond, and if are now turned into if statements wrapped in function closures +- Anonymous functions are now turned into anonymous functions in javascript insteed of arrow functions + +## [0.1.0] - 2015-04-04 +### Added +- From standard library implemented: + * Enum.map + * Kernel.tl + * Kernel.hd + * Logger +- Implemented language features: + * All primitives except bitstrings + * defmodule + * import, alias, and require + * case, cond, if + * def, defp + * defstruct, defexception + * raise + * multiple arity functions + * basic binary operations + * for without into From 408b0bbb55ace89bc810b81ebb7bfdfa989b81d9 Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Mon, 17 Oct 2016 08:46:04 -0500 Subject: [PATCH 313/860] separate module_filepaths into 2 separate passes --- lib/elixir_script.ex | 23 +++++++++++-- lib/elixir_script/passes/ast_from_file.ex | 26 +++++++++++++++ .../{module_filepaths.ex => find_modules.ex} | 32 ++++--------------- 3 files changed, 53 insertions(+), 28 deletions(-) create mode 100644 lib/elixir_script/passes/ast_from_file.ex rename lib/elixir_script/passes/{module_filepaths.ex => find_modules.ex} (86%) diff --git a/lib/elixir_script.ex b/lib/elixir_script.ex index 305027f1..8808fb7b 100644 --- a/lib/elixir_script.ex +++ b/lib/elixir_script.ex @@ -60,6 +60,23 @@ defmodule ElixirScript do """ @spec compile_quoted(Macro.t, Map.t) :: [binary | {binary, binary} | :ok] def compile_quoted(quoted, opts \\ %{}) do + + opts = build_compiler_options(opts) + + result = %{ data: [%{ast: quoted}] } + |> ElixirScript.Passes.FindModules.execute(opts) + |> ElixirScript.Passes.FindDeps.execute(opts) + |> ElixirScript.Passes.RemoveUnused.execute(opts) + |> ElixirScript.Passes.LoadModules.execute(opts) + |> ElixirScript.Passes.FindChangedFiles.execute(opts) + |> ElixirScript.Passes.FindFunctions.execute(opts) + |> ElixirScript.Passes.JavaScriptAST.execute(opts) + |> ElixirScript.Passes.ConsolidateProtocols.execute(opts) + |> ElixirScript.Passes.JavaScriptCode.execute(opts) + |> ElixirScript.Passes.JavaScriptName.execute(opts) + |> ElixirScript.Passes.HandleOutput.execute(opts) + + { code, _ } = do_compile(opts, [quoted], get_stdlib_state, []) result = Output.out(quoted, code, build_compiler_options(opts)) ElixirScript.Translator.State.stop @@ -76,7 +93,8 @@ defmodule ElixirScript do result = %{ path: path } |> ElixirScript.Passes.DepsPaths.execute(opts) - |> ElixirScript.Passes.ModuleFilepaths.execute(opts) + |> ElixirScript.Passes.ASTFromFile.execute(opts) + |> ElixirScript.Passes.FindModules.execute(opts) |> ElixirScript.Passes.FindDeps.execute(opts) |> ElixirScript.Passes.RemoveUnused.execute(opts) |> ElixirScript.Passes.LoadModules.execute(opts) @@ -172,7 +190,8 @@ defmodule ElixirScript do result = %{ path: libs_path } |> ElixirScript.Passes.DepsPaths.execute(opts) - |> ElixirScript.Passes.ModuleFilepaths.execute(opts) + |> ElixirScript.Passes.ASTFromFile.execute(opts) + |> ElixirScript.Passes.FindModules.execute(opts) #|> ElixirScript.Passes.FindDeps.execute(opts) #|> ElixirScript.Passes.RemoveUnused.execute(opts) #|> ElixirScript.Passes.LoadModules.execute(opts) diff --git a/lib/elixir_script/passes/ast_from_file.ex b/lib/elixir_script/passes/ast_from_file.ex new file mode 100644 index 00000000..969aee69 --- /dev/null +++ b/lib/elixir_script/passes/ast_from_file.ex @@ -0,0 +1,26 @@ +defmodule ElixirScript.Passes.ASTFromFile do + + + def execute(compiler_data, opts) do + data = Enum.reduce(compiler_data.data, [], fn({dep, paths}, list) -> + + file_paths = paths + |> Enum.flat_map(fn(path) -> Path.join(path, "**/*.{ex,exs,exjs}") |> Path.wildcard end) + |> Enum.reduce([], fn(path, list) -> + quoted = path + |> File.read! + |> Code.string_to_quoted! + + stat = File.stat!(path) + + list ++ [%{ path: path, app: dep, stat: stat, ast: quoted }] + end) + + + list ++ file_paths + end) + + Map.put(compiler_data, :data, data) + end + +end diff --git a/lib/elixir_script/passes/module_filepaths.ex b/lib/elixir_script/passes/find_modules.ex similarity index 86% rename from lib/elixir_script/passes/module_filepaths.ex rename to lib/elixir_script/passes/find_modules.ex index 264b2053..7c0a1473 100644 --- a/lib/elixir_script/passes/module_filepaths.ex +++ b/lib/elixir_script/passes/find_modules.ex @@ -1,35 +1,15 @@ -defmodule ElixirScript.Passes.ModuleFilepaths do +defmodule ElixirScript.Passes.FindModules do @pass 2 alias ElixirScript.Translator.Utils - - #TODO: Split into smaller passes? - def execute(compiler_data, opts) do - data = Enum.reduce(compiler_data.data, [], fn({dep, paths}, list) -> - - file_paths = Enum.flat_map(paths, fn(path) -> - Path.join(path, "**/*.{ex,exs,exjs}") - |> Path.wildcard - end) - - file_paths = Enum.reduce(file_paths, [], fn(path, list) -> - quoted = path - |> File.read! - |> Code.string_to_quoted! - |> update_quoted - - { _, modules } = Macro.postwalk(quoted, [], &get_defmodules(&1, &2, opts)) - - stat = File.stat!(path) - - modules = Enum.map(modules, fn(x) -> { x.module, Map.merge(x, %{ path: path, app: dep, stat: stat }) } end) - list ++ modules - end) - + data = Enum.reduce(compiler_data.data, [], fn(data, list) -> + quoted = update_quoted(data.ast) + { _, modules } = Macro.postwalk(quoted, [], &get_defmodules(&1, &2, opts)) - list ++ file_paths + modules = Enum.map(modules, fn(x) -> { x.module, Map.merge(data, x) } end) + list ++ modules end) Map.put(compiler_data, :data, data) From b93ac767bda4d2fe9be7566a8051a09f5bd773a7 Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Mon, 17 Oct 2016 08:49:03 -0500 Subject: [PATCH 314/860] updated operating path function --- lib/elixir_script.ex | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/lib/elixir_script.ex b/lib/elixir_script.ex index 8808fb7b..20944c23 100644 --- a/lib/elixir_script.ex +++ b/lib/elixir_script.ex @@ -415,11 +415,10 @@ defmodule ElixirScript do defp operating_path do case @lib_path do nil -> - try do + if Code.ensure_loaded?(Mix.Project) do Mix.Project.build_path <> "/lib/elixir_script/priv" - rescue - UndefinedFunctionError -> - split_path = Path.split(Application.app_dir(:elixirscript)) + else + split_path = Path.split(Application.app_dir(:elixirscript)) replaced_path = List.delete_at(split_path, length(split_path) - 1) replaced_path = List.delete_at(replaced_path, length(replaced_path) - 1) Path.join(replaced_path) From 36ead77eae65ca02e6d05914ea88a31b3175119b Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Mon, 17 Oct 2016 20:38:22 -0500 Subject: [PATCH 315/860] Got tests running again --- lib/elixir_script.ex | 52 ++++++++++++++----- lib/elixir_script/passes/add_std_lib.ex | 9 ++++ .../passes/consolidate_protocols.ex | 16 +++--- lib/elixir_script/passes/deps_paths.ex | 3 +- lib/elixir_script/passes/find_functions.ex | 8 +-- lib/elixir_script/passes/find_modules.ex | 16 ++++-- lib/elixir_script/passes/handle_output.ex | 12 +++-- lib/elixir_script/passes/init.ex | 9 ++++ lib/elixir_script/passes/java_script_ast.ex | 12 +++-- lib/elixir_script/passes/load_modules.ex | 3 +- .../translator/kernel/defmodule.ex | 5 +- .../translator/kernel/defprotocol.ex | 4 +- .../translator/kernel/special_forms/call.ex | 1 - lib/elixir_script/translator/lexical_scope.ex | 3 +- lib/elixir_script/translator/state.ex | 4 +- lib/elixir_script/translator/utils.ex | 4 ++ mix.exs | 2 +- mix.lock | 24 ++++----- 18 files changed, 124 insertions(+), 63 deletions(-) create mode 100644 lib/elixir_script/passes/add_std_lib.ex create mode 100644 lib/elixir_script/passes/init.ex diff --git a/lib/elixir_script.ex b/lib/elixir_script.ex index 20944c23..a066499a 100644 --- a/lib/elixir_script.ex +++ b/lib/elixir_script.ex @@ -63,26 +63,54 @@ defmodule ElixirScript do opts = build_compiler_options(opts) - result = %{ data: [%{ast: quoted}] } + data = quoted + |> get_modules_from_quoted + |> Enum.map(fn(x) -> %{ast: x, app: :app} end) + + result = %{ data: data } + |> ElixirScript.Passes.Init.execute(opts) |> ElixirScript.Passes.FindModules.execute(opts) |> ElixirScript.Passes.FindDeps.execute(opts) - |> ElixirScript.Passes.RemoveUnused.execute(opts) - |> ElixirScript.Passes.LoadModules.execute(opts) - |> ElixirScript.Passes.FindChangedFiles.execute(opts) |> ElixirScript.Passes.FindFunctions.execute(opts) + |> ElixirScript.Passes.AddStdLib.execute(opts) |> ElixirScript.Passes.JavaScriptAST.execute(opts) |> ElixirScript.Passes.ConsolidateProtocols.execute(opts) |> ElixirScript.Passes.JavaScriptCode.execute(opts) |> ElixirScript.Passes.JavaScriptName.execute(opts) |> ElixirScript.Passes.HandleOutput.execute(opts) - - { code, _ } = do_compile(opts, [quoted], get_stdlib_state, []) - result = Output.out(quoted, code, build_compiler_options(opts)) - ElixirScript.Translator.State.stop result end + defp get_modules_from_quoted(quoted) do + results = case quoted do + { :__block__, _, list } -> + {modules, not_modules} = Enum.partition(list, + fn + {type, _, _ } when type in [:defprotocol, :defimpl, :defmodule] -> + true + _ -> + false + end) + + temp_module = case not_modules do + [] -> + [] + _ -> + [{:defmodule, [], [{:__aliases__, [], [:ElixirScript, :Temp]}, [do: { :__block__, [], not_modules }]]}] + end + + modules ++ temp_module + + {type, _, _ } = x when type in [:defprotocol, :defimpl, :defmodule] -> + x + x -> + {:defmodule, [], [{:__aliases__, [], [:ElixirScript, :Temp]}, [do: { :__block__, [], [x] }]]} + end + + List.wrap(results) + end + @doc """ Compiles the elixir files found at the given path """ @@ -92,6 +120,7 @@ defmodule ElixirScript do opts = build_compiler_options(opts) result = %{ path: path } + |> ElixirScript.Passes.Init.execute(opts) |> ElixirScript.Passes.DepsPaths.execute(opts) |> ElixirScript.Passes.ASTFromFile.execute(opts) |> ElixirScript.Passes.FindModules.execute(opts) @@ -106,6 +135,8 @@ defmodule ElixirScript do |> ElixirScript.Passes.JavaScriptName.execute(opts) |> ElixirScript.Passes.WriteCache.execute(opts) |> ElixirScript.Passes.HandleOutput.execute(opts) + + result end defp process_path(path) do @@ -189,13 +220,10 @@ defmodule ElixirScript do libs_path = Path.join([__DIR__, "elixir_script", "prelude"]) result = %{ path: libs_path } + |> ElixirScript.Passes.Init.execute(opts) |> ElixirScript.Passes.DepsPaths.execute(opts) |> ElixirScript.Passes.ASTFromFile.execute(opts) |> ElixirScript.Passes.FindModules.execute(opts) - #|> ElixirScript.Passes.FindDeps.execute(opts) - #|> ElixirScript.Passes.RemoveUnused.execute(opts) - #|> ElixirScript.Passes.LoadModules.execute(opts) - #|> ElixirScript.Passes.FindChangedFiles.execute(opts) |> ElixirScript.Passes.FindFunctions.execute(opts) |> ElixirScript.Passes.JavaScriptAST.execute(opts) |> ElixirScript.Passes.ConsolidateProtocols.execute(opts) diff --git a/lib/elixir_script/passes/add_std_lib.ex b/lib/elixir_script/passes/add_std_lib.ex new file mode 100644 index 00000000..5718a33a --- /dev/null +++ b/lib/elixir_script/passes/add_std_lib.ex @@ -0,0 +1,9 @@ +defmodule ElixirScript.Passes.AddStdLib do + alias ElixirScript.Translator.State + + def execute(compiler_data, opts) do + State.deserialize(ElixirScript.get_stdlib_state, []) + compiler_data + end + +end diff --git a/lib/elixir_script/passes/consolidate_protocols.ex b/lib/elixir_script/passes/consolidate_protocols.ex index 29a858d4..06ec5b10 100644 --- a/lib/elixir_script/passes/consolidate_protocols.ex +++ b/lib/elixir_script/passes/consolidate_protocols.ex @@ -25,25 +25,29 @@ defmodule ElixirScript.Passes.ConsolidateProtocols do Enum.reduce(data, %{}, fn({module_name, module_data} = dat, state) -> if module_data.type == :protocol do existing = Map.get(state, module_name, %{}) - Map.put(existing, :protocol, dat) + existing = Map.put(existing, :protocol, dat) Map.put(state, module_name, existing) else existing = Map.get(state, module_data.implements, %{}) existing_protocol_data = Map.get(existing, :impls, []) existing_protocol_data = existing_protocol_data ++ [dat] - Map.put(existing, :impls, existing_protocol_data) - Map.put(state, module_name.implements, existing) + existing = Map.put(existing, :impls, existing_protocol_data) + Map.put(state, module_data.implements, existing) end end) end defp update_protocols(grouped_protocol_data, opts) do - Enum.map(grouped_protocol_data, fn({ protocol_name, %{ protocol: protocol, impls: impls } }) -> - make_defimpl(protocol_name, protocol, Enum.uniq(impls), opts) + Enum.map(grouped_protocol_data, fn + ({ protocol_name, %{ protocol: protocol, impls: impls } }) -> + make_defimpl(protocol_name, protocol, Enum.uniq(impls), opts) + + ({ protocol_name, %{ protocol: protocol } }) -> + make_defimpl(protocol_name, protocol, [], opts) end) end - defp make_defimpl(name, protocol, implementations, compiler_opts) do + defp make_defimpl(name, { protocol_name, protocol }, implementations, compiler_opts) do imports = [ModuleSystems.import_module(:Elixir, Utils.make_local_file_path(:elixir, compiler_opts.core_path, compiler_opts.root))] declarator = JS.variable_declarator( diff --git a/lib/elixir_script/passes/deps_paths.ex b/lib/elixir_script/passes/deps_paths.ex index 91c71231..5a2d1e17 100644 --- a/lib/elixir_script/passes/deps_paths.ex +++ b/lib/elixir_script/passes/deps_paths.ex @@ -1,9 +1,8 @@ defmodule ElixirScript.Passes.DepsPaths do @pass 1 - alias ElixirScript.Translator.State + def execute(compiler_data, opts) do - State.start_link(opts, []) data = cond do opts.std_lib -> diff --git a/lib/elixir_script/passes/find_functions.ex b/lib/elixir_script/passes/find_functions.ex index b4795fc4..9706eebf 100644 --- a/lib/elixir_script/passes/find_functions.ex +++ b/lib/elixir_script/passes/find_functions.ex @@ -5,7 +5,7 @@ defmodule ElixirScript.Passes.FindFunctions do def execute(data, opts) do new_data = Enum.map(data.data, fn { module_name, module_data } -> - functions = case module_data.ast do + %{def: functions, defp: private_functions, defgen: generators, defgenp: private_generators } = case module_data.ast do {:defmodule, _, [_, [do: body]]} -> get_functions_from_module(body) {:defprotocol, _, [_, [do: {:__block__, _, _} = block]]} -> @@ -13,11 +13,13 @@ defmodule ElixirScript.Passes.FindFunctions do {:defprotocol, _, [{:__aliases__, _, _} = the_alias, [do: spec]]} -> get_functions_from_module({:__block__, [], [spec]}) _ -> - %{} + %{ def: Keyword.new, defp: Keyword.new, defgen: Keyword.new, defgenp: Keyword.new } end - module_data = Map.put(module_data, :functions, functions) + module_data = Map.put(module_data, :functions, functions ++ generators) + |> Map.put(:private_functions, private_functions ++ private_generators) + {module_name, module_data} end) diff --git a/lib/elixir_script/passes/find_modules.ex b/lib/elixir_script/passes/find_modules.ex index 7c0a1473..105c4a6d 100644 --- a/lib/elixir_script/passes/find_modules.ex +++ b/lib/elixir_script/passes/find_modules.ex @@ -8,7 +8,7 @@ defmodule ElixirScript.Passes.FindModules do quoted = update_quoted(data.ast) { _, modules } = Macro.postwalk(quoted, [], &get_defmodules(&1, &2, opts)) - modules = Enum.map(modules, fn(x) -> { x.module, Map.merge(data, x) } end) + modules = Enum.map(modules, fn(x) -> { x.name, Map.merge(data, x) } end) list ++ modules end) @@ -16,16 +16,22 @@ defmodule ElixirScript.Passes.FindModules do end defp get_defmodules({:defprotocol, _, [{:__aliases__, _, _} = the_alias, _]} = ast, state, _) do - s = %{ module: Utils.quoted_to_name(the_alias), type: :protocol, ast: ast } + s = %{ name: Utils.quoted_to_name(the_alias), type: :protocol, ast: ast } { ast, state ++ [s] } end defp get_defmodules({:defimpl, _, [ {:__aliases__, _, name} = the_alias, [for: {:__aliases__, _, type_name} = type], _ ]} = ast, state, _) do name = name ++ [DefImpl] ++ type_name - s = %{module: Utils.quoted_to_name({:__aliases__, [], name}), type: :impl, for: Utils.quoted_to_name(type), ast: ast, implements: Utils.quoted_to_name(the_alias) } + s = %{name: Utils.quoted_to_name({:__aliases__, [], name}), type: :impl, for: type, ast: ast, implements: Utils.quoted_to_name(the_alias) } { ast, state ++ [s] } end + defp get_defmodules({:defmodule, _, [{:__aliases__, _, [:ElixirScript, :Temp]}, [do: body]]} = ast, state, opts) do + s = %{name: ElixirScript.Temp, type: :module, ast: body } + { ast, state ++ [s] } + end + + defp get_defmodules({:defmodule, _, [{:__aliases__, _, _}, [do: _]]} = ast, state, opts) do { ast, do_module_processing(ast, state, opts) } end @@ -46,7 +52,7 @@ defmodule ElixirScript.Passes.FindModules do ({:defmodule, context1, [{:__aliases__, context2, inner_module_name}, [do: inner_module_body]]}, state) -> module_name = Utils.quoted_to_name({:__aliases__, [], tl(name) ++ inner_module_name}) - state = Enum.reject(state, fn(x) -> x.module == module_name end) + state = Enum.reject(state, fn(x) -> x.name == module_name end) this_module_aliases = aliases -- [{ :alias, [], [{:__aliases__, [alias: false], name ++ inner_module_name}, [as: {:__aliases__, [alias: false], inner_module_name }] ] }] @@ -85,7 +91,7 @@ defmodule ElixirScript.Passes.FindModules do end - [%{module: Utils.quoted_to_name(the_alias), type: :module, ast: {:defmodule, context1, [the_alias, [do: body]]} }] ++ state + [%{name: Utils.quoted_to_name(the_alias), type: :module, ast: body }] ++ state end defp add_aliases_to_body(body, aliases) do diff --git a/lib/elixir_script/passes/handle_output.ex b/lib/elixir_script/passes/handle_output.ex index 2786781f..cd4c3540 100644 --- a/lib/elixir_script/passes/handle_output.ex +++ b/lib/elixir_script/passes/handle_output.ex @@ -3,7 +3,7 @@ defmodule ElixirScript.Passes.HandleOutput do alias ElixirScript.Translator.State def execute(compiler_data, opts) do - if opts.std_lib do + if Map.get(opts, :std_lib, false) do State.set_module_data(compiler_data.data) new_std_state = State.serialize() stdlib_state_path = Path.join([File.cwd!(), "lib", "elixir_script", "translator", "stdlib_state.bin"]) @@ -29,14 +29,16 @@ defmodule ElixirScript.Passes.HandleOutput do end defp out(compiler_output, %{output: output_path, core_path: core_path} = compiler_opts) do - Enum.each(compiler_output, fn(x) -> + Enum.each(compiler_output.data, fn({_, x}) -> write_to_file(x, output_path) end) - ElixirScript.copy_stdlib_to_destination(output_path) + if Map.get(compiler_opts, :std_lib, false) == false do + ElixirScript.copy_stdlib_to_destination(output_path) + end end - defp write_to_file({_, module_data}, destination) do + defp write_to_file(module_data, destination) do file_name = Path.join([destination, to_string(module_data.app), module_data.javascript_name]) if !File.exists?(Path.dirname(file_name)) do @@ -47,7 +49,7 @@ defmodule ElixirScript.Passes.HandleOutput do end defp process_include_path(compiler_output, compiler_opts) do - Enum.map(compiler_output, fn + Enum.map(compiler_output.data, fn {module_name, module_data} -> case compiler_opts.include_path do true -> diff --git a/lib/elixir_script/passes/init.ex b/lib/elixir_script/passes/init.ex new file mode 100644 index 00000000..6538e2d4 --- /dev/null +++ b/lib/elixir_script/passes/init.ex @@ -0,0 +1,9 @@ +defmodule ElixirScript.Passes.Init do + alias ElixirScript.Translator.State + + def execute(compiler_data, opts) do + State.start_link(opts, []) + compiler_data + end + +end diff --git a/lib/elixir_script/passes/java_script_ast.ex b/lib/elixir_script/passes/java_script_ast.ex index f492faf2..2b89ab54 100644 --- a/lib/elixir_script/passes/java_script_ast.ex +++ b/lib/elixir_script/passes/java_script_ast.ex @@ -1,8 +1,10 @@ defmodule ElixirScript.Passes.JavaScriptAST do @pass 7 alias ElixirScript.Translator.Utils + alias ElixirScript.Translator.State def execute(compiler_data, opts) do + State.set_module_data(compiler_data.data) data = Enum.map(compiler_data.data, fn({module_name, module_data}) -> module_data = compile(module_data, opts) {module_name, module_data} @@ -13,15 +15,15 @@ defmodule ElixirScript.Passes.JavaScriptAST do defp compile(module_data, opts) do - env = ElixirScript.Translator.LexicalScope.module_scope(module_data.module, Utils.name_to_js_file_name(module_data.module) <> ".js", opts.env, module_data) + env = ElixirScript.Translator.LexicalScope.module_scope(module_data.name, Utils.name_to_js_file_name(module_data.name) <> ".js", opts.env) module = case module_data.type do :module -> - ElixirScript.Translator.Defmodule.make_module(module_data.module, module_data.ast, env) + ElixirScript.Translator.Defmodule.make_module(module_data.name, module_data.ast, env) :protocol -> - ElixirScript.Translator.Defprotocol.make(module_data.module, module_data.functions, env) - :protocol_implementation -> - ElixirScript.Translator.Defimpl.make(module_data.module, module_data.for, module_data.ast, env) + ElixirScript.Translator.Defprotocol.make(module_data.name, module_data.functions, env) + :impl -> + ElixirScript.Translator.Defimpl.make(module_data.name, module_data.for, module_data.ast, env) end Map.put(module_data, :javascript_ast, module.body) diff --git a/lib/elixir_script/passes/load_modules.ex b/lib/elixir_script/passes/load_modules.ex index cd0cbc39..bb4d53cf 100644 --- a/lib/elixir_script/passes/load_modules.ex +++ b/lib/elixir_script/passes/load_modules.ex @@ -2,7 +2,8 @@ defmodule ElixirScript.Passes.LoadModules do @pass 5 def execute(compiler_data, opts) do - ex_files = Enum.map(compiler_data.data, fn { module, %{path: path} } -> path end) + ex_files = Enum.filter(compiler_data.data, fn + { module, %{path: path} } -> path end) |> Enum.filter(fn path -> Path.extname(path) == ".ex" || Path.extname(path) == ".exs" end) loaded_modules = Kernel.ParallelRequire.files(ex_files) diff --git a/lib/elixir_script/translator/kernel/defmodule.ex b/lib/elixir_script/translator/kernel/defmodule.ex index 5c985512..8199692f 100644 --- a/lib/elixir_script/translator/kernel/defmodule.ex +++ b/lib/elixir_script/translator/kernel/defmodule.ex @@ -20,6 +20,7 @@ defmodule ElixirScript.Translator.Defmodule do def make_module(module, body, env) do { body, functions } = extract_functions_from_module(body) + { body, env } = translate_body(body, env) { exported_functions, private_functions } = process_functions(functions, env) @@ -29,7 +30,7 @@ defmodule ElixirScript.Translator.Defmodule do {imports, body} = extract_imports_from_body(body) {structs, body} = extract_structs_from_body(body, env) - app_name = State.get_module(module).app_name + app_name = State.get_module(module).app imports = imports ++ make_std_lib_import() ++ make_imports(app_name, module_refs) @@ -227,7 +228,7 @@ defmodule ElixirScript.Translator.Defmodule do def make_imports(current_app_name, enum) do Enum.map(enum, fn(x) -> module_name = Utils.name_to_js_name(x) - app_name = State.get_module(x).app_name + app_name = State.get_module(x).app path = Utils.make_local_file_path(app_name, Utils.name_to_js_file_name(x)) ModuleSystems.import_module(module_name, path) end) diff --git a/lib/elixir_script/translator/kernel/defprotocol.ex b/lib/elixir_script/translator/kernel/defprotocol.ex index 16a18708..8f56f64e 100644 --- a/lib/elixir_script/translator/kernel/defprotocol.ex +++ b/lib/elixir_script/translator/kernel/defprotocol.ex @@ -20,7 +20,7 @@ defmodule ElixirScript.Translator.Defprotocol do {imports, body} = Defmodule.extract_imports_from_body(body) - app_name = State.get_module(name).app_name + app_name = State.get_module(name).app imports = imports ++ Defmodule.make_std_lib_import() ++ Defmodule.make_imports(app_name, module_refs) ++ @@ -112,7 +112,7 @@ defmodule ElixirScript.Translator.Defprotocol do protocol_name = Atom.to_string(name) - app_name = State.get_module(name).app_name + app_name = State.get_module(name).app body = Enum.flat_map(implementations, fn({impl_app_name, x}) -> x = if is_atom(x), do: Atom.to_string(x), else: x diff --git a/lib/elixir_script/translator/kernel/special_forms/call.ex b/lib/elixir_script/translator/kernel/special_forms/call.ex index 8ed21f61..06a33933 100644 --- a/lib/elixir_script/translator/kernel/special_forms/call.ex +++ b/lib/elixir_script/translator/kernel/special_forms/call.ex @@ -122,7 +122,6 @@ defmodule ElixirScript.Translator.Call do Utils.name_to_js_name(module_name) module_name in ElixirScript.Translator.State.list_module_names -> - ElixirScript.Translator.State.add_module_reference(env.module, module_name) Utils.name_to_js_name(module_name) true -> diff --git a/lib/elixir_script/translator/lexical_scope.ex b/lib/elixir_script/translator/lexical_scope.ex index b90c1971..eb7c4b6a 100644 --- a/lib/elixir_script/translator/lexical_scope.ex +++ b/lib/elixir_script/translator/lexical_scope.ex @@ -176,7 +176,6 @@ defmodule ElixirScript.Translator.LexicalScope do raise "Module #{inspect module_name} not found" end - ElixirScript.Translator.State.add_module_reference(env.module, module.name) module end @@ -325,7 +324,7 @@ defmodule ElixirScript.Translator.LexicalScope do end defp check_for_module_existence(env, module_name) do - if !ElixirScript.Translator.State.is_module_loaded?(module_name) and !has_module?(env, module_name) do + if ElixirScript.Translator.State.is_module_loaded?(module_name) == false and has_module?(env, module_name) == false do raise "Module #{inspect module_name} not found" end end diff --git a/lib/elixir_script/translator/state.ex b/lib/elixir_script/translator/state.ex index e45ccc8a..d262c3d6 100644 --- a/lib/elixir_script/translator/state.ex +++ b/lib/elixir_script/translator/state.ex @@ -24,7 +24,7 @@ defmodule ElixirScript.Translator.State do def deserialize(frozen_state, loaded_modules \\ []) do Agent.update(__MODULE__, fn state -> frozen_state = :erlang.binary_to_term(frozen_state) - modules = Map.delete(frozen_state.modules, ElixirScript.Temp) + modules = Keyword.delete(frozen_state.modules, ElixirScript.Temp) %{ state | modules: modules, std_lib_map: frozen_state.std_lib_map, loaded_modules: loaded_modules } end) end @@ -120,7 +120,7 @@ defmodule ElixirScript.Translator.State do nil -> [] module -> - module.deps + Map.get(module, :deps, []) end end diff --git a/lib/elixir_script/translator/utils.ex b/lib/elixir_script/translator/utils.ex index 9ef5a198..66fd6538 100644 --- a/lib/elixir_script/translator/utils.ex +++ b/lib/elixir_script/translator/utils.ex @@ -6,6 +6,10 @@ defmodule ElixirScript.Translator.Utils do name end + def name_to_quoted(name) when is_list(name) do + { :__aliases__, [], name } + end + def name_to_quoted(name) do name = name |> Atom.to_string diff --git a/mix.exs b/mix.exs index 340a6972..f833e235 100644 --- a/mix.exs +++ b/mix.exs @@ -28,7 +28,7 @@ defmodule ElixirScript.Mixfile do defp deps do [ - {:estree, "~> 2.4" }, + {:estree, "~> 2.3.0" }, {:fs, "~> 0.9.1"}, {:earmark, "~> 1.0", only: :dev }, {:ex_doc, "~> 0.14", only: :dev }, diff --git a/mix.lock b/mix.lock index 6777ab1d..70217318 100644 --- a/mix.lock +++ b/mix.lock @@ -1,19 +1,15 @@ -%{"benchfella": {:hex, :benchfella, "0.3.1"}, - "bunt": {:hex, :bunt, "0.1.6", "5d95a6882f73f3b9969fdfd1953798046664e6f77ec4e486e6fafc7caad97c6f", [:mix], []}, - "certifi": {:hex, :certifi, "0.3.0", "389d4b126a47895fe96d65fcf8681f4d09eca1153dc2243ed6babad0aac1e763", [:rebar3], []}, +%{"bunt": {:hex, :bunt, "0.1.6", "5d95a6882f73f3b9969fdfd1953798046664e6f77ec4e486e6fafc7caad97c6f", [:mix], []}, + "certifi": {:hex, :certifi, "0.4.0", "a7966efb868b179023618d29a407548f70c52466bf1849b9e8ebd0e34b7ea11f", [:rebar3], []}, "credo": {:hex, :credo, "0.4.12", "f5e1973405ea25c6e64959fb0b6bf92950147a0278cc2a002a491b45f78f7b87", [:mix], [{:bunt, "~> 0.1.6", [hex: :bunt, optional: false]}]}, - "dogma": {:hex, :dogma, "0.0.7"}, "earmark": {:hex, :earmark, "1.0.2", "a0b0904d74ecc14da8bd2e6e0248e1a409a2bc91aade75fcf428125603de3853", [:mix], []}, - "estree": {:hex, :estree, "2.4.1", "9e8a26b0d9e3a83266c73f6a577f971b011e291a52d5d328706cf28ba0fceef5", [:mix], []}, + "estree": {:hex, :estree, "2.3.0", "96a190aee9b7ecb05a9486fe0f1e0a912c98b2d98419a84c74956687b6e53c71", [:mix], []}, "ex_doc": {:hex, :ex_doc, "0.14.3", "e61cec6cf9731d7d23d254266ab06ac1decbb7651c3d1568402ec535d387b6f7", [:mix], [{:earmark, "~> 1.0", [hex: :earmark, optional: false]}]}, - "excoveralls": {:hex, :excoveralls, "0.5.1", "5b55d62b384c7edda8b26b52b1a9fc9358fec2e6b157a81071de5cb8a42e4721", [:mix], [{:exjsx, "~> 3.0", [hex: :exjsx, optional: false]}, {:hackney, ">= 0.12.0", [hex: :hackney, optional: false]}]}, - "exjsx": {:hex, :exjsx, "3.2.0", "7136cc739ace295fc74c378f33699e5145bead4fdc1b4799822d0287489136fb", [:mix], [{:jsx, "~> 2.6.2", [hex: :jsx, optional: false]}]}, + "excoveralls": {:hex, :excoveralls, "0.5.7", "5d26e4a7cdf08294217594a1b0643636accc2ad30e984d62f1d166f70629ff50", [:mix], [{:exjsx, "~> 3.0", [hex: :exjsx, optional: false]}, {:hackney, ">= 0.12.0", [hex: :hackney, optional: false]}]}, + "exjsx": {:hex, :exjsx, "3.2.1", "1bc5bf1e4fd249104178f0885030bcd75a4526f4d2a1e976f4b428d347614f0f", [:mix], [{:jsx, "~> 2.8.0", [hex: :jsx, optional: false]}]}, "fs": {:hex, :fs, "0.9.2", "ed17036c26c3f70ac49781ed9220a50c36775c6ca2cf8182d123b6566e49ec59", [:rebar], []}, - "hackney": {:hex, :hackney, "1.4.8", "c8c6977ed55cc5095e3929f6d94a6f732dd2e31ae42a7b9236d5574ec3f5be13", [:rebar3], [{:certifi, "0.3.0", [hex: :certifi, optional: false]}, {:idna, "1.0.3", [hex: :idna, optional: false]}, {:mimerl, "1.0.2", [hex: :mimerl, optional: false]}, {:ssl_verify_hostname, "1.0.5", [hex: :ssl_verify_hostname, optional: false]}]}, - "idna": {:hex, :idna, "1.0.3", "d456a8761cad91c97e9788c27002eb3b773adaf5c893275fc35ba4e3434bbd9b", [:rebar3], []}, - "inflex": {:hex, :inflex, "1.5.0"}, - "jsx": {:hex, :jsx, "2.6.2", "213721e058da0587a4bce3cc8a00ff6684ced229c8f9223245c6ff2c88fbaa5a", [:mix, :rebar], []}, + "hackney": {:hex, :hackney, "1.6.1", "ddd22d42db2b50e6a155439c8811b8f6df61a4395de10509714ad2751c6da817", [:rebar3], [{:certifi, "0.4.0", [hex: :certifi, optional: false]}, {:idna, "1.2.0", [hex: :idna, optional: false]}, {:metrics, "1.0.1", [hex: :metrics, optional: false]}, {:mimerl, "1.0.2", [hex: :mimerl, optional: false]}, {:ssl_verify_fun, "1.1.0", [hex: :ssl_verify_fun, optional: false]}]}, + "idna": {:hex, :idna, "1.2.0", "ac62ee99da068f43c50dc69acf700e03a62a348360126260e87f2b54eced86b2", [:rebar3], []}, + "jsx": {:hex, :jsx, "2.8.0", "749bec6d205c694ae1786d62cea6cc45a390437e24835fd16d12d74f07097727", [:mix, :rebar], []}, + "metrics": {:hex, :metrics, "1.0.1", "25f094dea2cda98213cecc3aeff09e940299d950904393b2a29d191c346a8486", [:rebar3], []}, "mimerl": {:hex, :mimerl, "1.0.2", "993f9b0e084083405ed8252b99460c4f0563e41729ab42d9074fd5e52439be88", [:rebar3], []}, - "poison": {:hex, :poison, "1.5.0"}, - "shouldi": {:hex, :shouldi, "0.2.3"}, - "ssl_verify_hostname": {:hex, :ssl_verify_hostname, "1.0.5", "2e73e068cd6393526f9fa6d399353d7c9477d6886ba005f323b592d389fb47be", [:make], []}} + "ssl_verify_fun": {:hex, :ssl_verify_fun, "1.1.0", "edee20847c42e379bf91261db474ffbe373f8acb56e9079acb6038d4e0bf414f", [:rebar, :make], []}} From d4e6b4887f92ba57567626f6c285ccc451ee9f3a Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Tue, 18 Oct 2016 07:09:39 -0500 Subject: [PATCH 316/860] got all tests passing again --- lib/elixir_script.ex | 231 ------------------ lib/elixir_script/compiler/output.ex | 59 ----- .../passes/consolidate_protocols.ex | 4 +- lib/elixir_script/passes/find_deps.ex | 2 +- lib/elixir_script/passes/find_functions.ex | 14 +- lib/elixir_script/passes/find_modules.ex | 20 +- lib/elixir_script/translator.ex | 3 - .../translator/kernel/special_forms/call.ex | 1 + .../translator/kernel/special_forms/fn.ex | 5 +- lib/elixir_script/translator/lexical_scope.ex | 2 +- lib/elixir_script/translator/state.ex | 13 + test/translator/defmodule_test.exs | 24 +- test/translator/protocol_test.exs | 32 ++- test/translator/struct_test.exs | 19 +- 14 files changed, 76 insertions(+), 353 deletions(-) delete mode 100644 lib/elixir_script/compiler/output.ex diff --git a/lib/elixir_script.ex b/lib/elixir_script.ex index a066499a..2e9bd490 100644 --- a/lib/elixir_script.ex +++ b/lib/elixir_script.ex @@ -70,7 +70,6 @@ defmodule ElixirScript do result = %{ data: data } |> ElixirScript.Passes.Init.execute(opts) |> ElixirScript.Passes.FindModules.execute(opts) - |> ElixirScript.Passes.FindDeps.execute(opts) |> ElixirScript.Passes.FindFunctions.execute(opts) |> ElixirScript.Passes.AddStdLib.execute(opts) |> ElixirScript.Passes.JavaScriptAST.execute(opts) @@ -124,7 +123,6 @@ defmodule ElixirScript do |> ElixirScript.Passes.DepsPaths.execute(opts) |> ElixirScript.Passes.ASTFromFile.execute(opts) |> ElixirScript.Passes.FindModules.execute(opts) - |> ElixirScript.Passes.FindDeps.execute(opts) |> ElixirScript.Passes.RemoveUnused.execute(opts) |> ElixirScript.Passes.LoadModules.execute(opts) |> ElixirScript.Passes.FindChangedFiles.execute(opts) @@ -139,21 +137,6 @@ defmodule ElixirScript do result end - defp process_path(path) do - path = Path.join(path, "**/*.{ex,exs,exjs}") |> Path.wildcard - {exjs, ex} = Enum.partition(path, fn(x) -> - case Path.extname(x) do - ext when ext in [".ex", ".exs"] -> - false - _ -> - true - end - end) - - ex = Kernel.ParallelRequire.files(ex) - {exjs, ex} - end - @doc false def get_stdlib_state() do case @stdlib_state do @@ -164,48 +147,6 @@ defmodule ElixirScript do end end - defp get_compiler_cache(path, opts) do - refresh_cache = cond do - Map.get(opts, :full_build) -> - true - empty?(opts.output) -> - true - old_version?(opts) -> - true - Cache.get(path) == nil -> - true - true -> - false - end - - if refresh_cache do - Cache.delete(path) - Cache.new(get_stdlib_state) - else - %{ Cache.get(path) | full_build?: false } - end - end - - defp empty?(path) when is_binary(path) do - case File.ls(path) do - {:ok, []} -> - true - {:error, _} -> - true - _ -> - false - end - end - - defp empty?(_) do - true - end - - defp old_version?(opts) do - cache_version = Map.get(opts, :version, nil) - cache_version == version() - end - @doc false def version(), do: @version @@ -234,22 +175,6 @@ defmodule ElixirScript do result end - defp do_compile(opts, quoted_code_list, state, loaded_modules) do - compiler_opts = build_compiler_options(opts) - - ElixirScript.Translator.State.start_link(compiler_opts, loaded_modules) - ElixirScript.Translator.State.deserialize(state, loaded_modules) - - quoted_code_list - |> Enum.map(&update_quoted(&1)) - #|> ModuleCollector.process_modules(compiler_opts[:app]) - - code = create_code(compiler_opts, ElixirScript.Translator.State.get) - new_state = ElixirScript.Translator.State.serialize() - - { code, new_state } - end - defp build_compiler_options(opts) do default_options = Map.new |> Map.put(:include_path, false) @@ -264,140 +189,12 @@ defmodule ElixirScript do Map.merge(default_options, opts) end - defp file_to_quoted(file) do - file - |> File.read! - |> Code.string_to_quoted! - end - - defp update_quoted(quoted) do - Macro.prewalk(quoted, fn - ({name, context, parms}) -> - context = if context[:import] == Kernel do - context = Keyword.update!(context, :import, fn(_) -> ElixirScript.Kernel end) - else - context - end - - {name, context, parms} - (x) -> - x - end) - end - @doc false def custom_env() do __using__([]) __ENV__ end - defp create_code(compiler_opts, state) do - - parent = self - - Map.values(state.modules) - |> Enum.reject(fn(ast) -> - not ast.name in state.added_modules - end) - |> Enum.map(fn ast -> - spawn_link fn -> - env = ElixirScript.Translator.LexicalScope.module_scope(ast.name, Utils.name_to_js_file_name(ast.name) <> ".js", state.compiler_opts.env) - - module = case ast.type do - :module -> - ElixirScript.Translator.Defmodule.make_module(ast.name, ast.body, env) - :protocol -> - ElixirScript.Translator.Defprotocol.make(ast.name, ast.functions, env) - :protocol_implementation -> - ElixirScript.Translator.Defimpl.make(ast.name, ast.impl_type, ast.body, env) - end - - - result = javascript_ast_to_code(module) - - send parent, { self, result } - end - end) - |> Enum.map(fn pid -> - receive do - {^pid, result} -> result - end - end) - end - - @doc false - def update_protocols(compiler_output, compiler_opts) do - Enum.reduce(compiler_output, %{}, fn - {file, code, app_name}, state -> - case String.split(file, ".DefImpl.") do - [protocol, impl] -> - protocol = String.split(protocol, "/") |> List.last |> String.to_atom - impl = String.replace(impl, ".js", "") |> String.to_atom - - entry = Map.get(state, protocol, []) - entry = entry ++ [{app_name, impl}] - - - Map.put(state, protocol, entry) - [_] -> - state - end - _, state -> - state - end) - |> do_make_defimpl(compiler_opts) - end - - @doc false - def update_protocols_in_path(compiler_output, compiler_opts, output_path) do - Enum.reduce(compiler_output, %{}, fn { file, code, app_name }, state -> - case String.split(file, ".DefImpl.") do - [protocol, _] -> - protocol = String.split(protocol, "/") |> List.last - protocol_impls = find_protocols_implementations_in_path(output_path, protocol) - protocol = String.to_atom(protocol) - - entry = Map.get(state, protocol, []) - entry = entry ++ protocol_impls - - Map.put(state, protocol, entry) - [_] -> - state - end - end) - |> do_make_defimpl(compiler_opts) - end - - defp do_make_defimpl(protocols, compiler_opts) do - Enum.map(protocols, fn {protocol, impls} -> - ElixirScript.Translator.Defprotocol.make_defimpl(protocol, Enum.uniq(impls), compiler_opts) - end) - |> Enum.map(fn(module) -> - javascript_ast_to_code(module) - end) - end - - defp find_protocols_implementations_in_path(path, protocol_prefix) do - Path.join([path, "**", protocol_prefix <> ".DefImpl*.js"]) - |> Path.wildcard - |> Enum.filter(fn path -> !String.ends_with?(path, "DefImpl.js") end) - |> Enum.map(fn impl -> - - path_split = Path.split(impl) - - implementation = path_split - |> List.last - |> String.split(".DefImpl.") - |> List.last - |> String.replace(".js", "") - |> String.to_atom - - app_name = Enum.at(path_split, length(path_split) - 2) - - {app_name, implementation} - end) - end - @doc """ Copies the javascript that makes up the ElixirScript stdlib to the specified location @@ -410,34 +207,6 @@ defmodule ElixirScript do end) end - defp javascript_ast_to_code(module) do - path = Utils.name_to_js_file_name(module.name) <> ".js" - js_ast = Builder.program(module.body) - - js_code = js_ast - |> prepare_js_ast - |> Generator.generate - - { path, js_code, module.app_name } - end - - defp prepare_js_ast(js_ast) do - js_ast = case js_ast do - modules when is_list(modules) -> - modules - |> Enum.reduce([], &(&2 ++ &1.body)) - |> Builder.program - %ElixirScript.Translator.Group{ body: body } -> - Builder.program(body) - %ElixirScript.Translator.Empty{ } -> - Builder.program([]) - _ -> - js_ast - end - - js_ast - end - #Gets path to js files whether the mix project is available #or when used as an escript defp operating_path do diff --git a/lib/elixir_script/compiler/output.ex b/lib/elixir_script/compiler/output.ex deleted file mode 100644 index 71a5c821..00000000 --- a/lib/elixir_script/compiler/output.ex +++ /dev/null @@ -1,59 +0,0 @@ -defmodule ElixirScript.Compiler.Output do - @moduledoc false - alias ElixirScript.Compiler.Cache - - def out(_, compiler_output, %{output: nil} = compiler_opts) do - compiler_output ++ ElixirScript.update_protocols(compiler_output, compiler_opts) - |> process_include_path(compiler_opts) - end - - def out(_, compiler_output, %{output: :stdout} = compiler_opts) do - compiler_output ++ ElixirScript.update_protocols(compiler_output, compiler_opts) - |> process_include_path(compiler_opts) - |> Enum.each(fn - {_, code, _} -> IO.write(code) - code -> IO.write(code) - end) - end - - def out(compiler_input, compiler_output, %{output: output_path, core_path: core_path} = compiler_opts) do - Enum.each(compiler_output, fn(x) -> - write_to_file(x, output_path) - end) - - ElixirScript.update_protocols_in_path(compiler_output, compiler_opts, output_path) - |> Enum.each(fn - x -> - write_to_file(x, output_path) - end) - - if core_path == "Elixir" and Map.get(compiler_opts, :std_lib, false) == false do - cache = Cache.get(compiler_input) - if cache == nil or Map.get(cache, :full_build?) == true do - ElixirScript.copy_stdlib_to_destination(output_path) - end - end - end - - def write_to_file({ file_path, js_code, app }, destination) do - file_name = Path.join([destination, to_string(app), file_path]) - - if !File.exists?(Path.dirname(file_name)) do - File.mkdir_p!(Path.dirname(file_name)) - end - - File.write!(file_name, js_code) - end - - defp process_include_path(compiler_output, compiler_opts) do - Enum.map(compiler_output, fn - { path, code, app_name } -> - case compiler_opts.include_path do - true -> - { path, code, app_name } - false -> - code - end - end) - end -end diff --git a/lib/elixir_script/passes/consolidate_protocols.ex b/lib/elixir_script/passes/consolidate_protocols.ex index 06ec5b10..4f708fc0 100644 --- a/lib/elixir_script/passes/consolidate_protocols.ex +++ b/lib/elixir_script/passes/consolidate_protocols.ex @@ -64,10 +64,10 @@ defmodule ElixirScript.Passes.ConsolidateProtocols do app_name = protocol.app body = Enum.flat_map(implementations, fn({impl_app_name, impl_data}) -> - x = Atom.to_string(impl_data.type) + x = Atom.to_string(Utils.quoted_to_name(impl_data.for)) x = String.to_atom(protocol_name <> ".DefImpl." <> x) name = Utils.name_to_js_name(x) - imports = ModuleSystems.import_module(name, Utils.make_local_file_path(impl_app_name, Utils.name_to_js_file_name(x), compiler_opts.root)) + imports = ModuleSystems.import_module(name, Utils.make_local_file_path(impl_data.app, Utils.name_to_js_file_name(x), compiler_opts.root)) call = JS.call_expression( JS.member_expression( JS.identifier("impls"), diff --git a/lib/elixir_script/passes/find_deps.ex b/lib/elixir_script/passes/find_deps.ex index 8f6db229..16bc9b35 100644 --- a/lib/elixir_script/passes/find_deps.ex +++ b/lib/elixir_script/passes/find_deps.ex @@ -10,7 +10,7 @@ defmodule ElixirScript.Passes.FindDeps do defp do_find_dependencies({ module, module_data }) do {_, deps} = Macro.prewalk(module_data.ast, [], &collect_references(&1, &2)) - { module, Map.put(module_data, :deps, deps) } + { module, Map.put(module_data, :deps, [ElixirScript.Kernel] ++ deps) } end defp collect_references({:import, _, [{{:., _, [{:__aliases__, _, head_import_name}, :{}]}, _, tail_imports }]}, state) do diff --git a/lib/elixir_script/passes/find_functions.ex b/lib/elixir_script/passes/find_functions.ex index 9706eebf..7864df53 100644 --- a/lib/elixir_script/passes/find_functions.ex +++ b/lib/elixir_script/passes/find_functions.ex @@ -5,17 +5,7 @@ defmodule ElixirScript.Passes.FindFunctions do def execute(data, opts) do new_data = Enum.map(data.data, fn { module_name, module_data } -> - %{def: functions, defp: private_functions, defgen: generators, defgenp: private_generators } = case module_data.ast do - {:defmodule, _, [_, [do: body]]} -> - get_functions_from_module(body) - {:defprotocol, _, [_, [do: {:__block__, _, _} = block]]} -> - get_functions_from_module(block) - {:defprotocol, _, [{:__aliases__, _, _} = the_alias, [do: spec]]} -> - get_functions_from_module({:__block__, [], [spec]}) - _ -> - %{ def: Keyword.new, defp: Keyword.new, defgen: Keyword.new, defgenp: Keyword.new } - end - + %{def: functions, defp: private_functions, defgen: generators, defgenp: private_generators } = get_functions_from_module(module_data.ast) module_data = Map.put(module_data, :functions, functions ++ generators) |> Map.put(:private_functions, private_functions ++ private_generators) @@ -62,7 +52,7 @@ defmodule ElixirScript.Passes.FindFunctions do end defp get_functions_from_module(_) do - %{ def: Keyword.new, defp: Keyword.new } + %{ def: Keyword.new, defp: Keyword.new, defgen: Keyword.new, defgenp: Keyword.new } end defp add_function_to_map(map, type, name, arity) do diff --git a/lib/elixir_script/passes/find_modules.ex b/lib/elixir_script/passes/find_modules.ex index 105c4a6d..e64e16f1 100644 --- a/lib/elixir_script/passes/find_modules.ex +++ b/lib/elixir_script/passes/find_modules.ex @@ -15,14 +15,25 @@ defmodule ElixirScript.Passes.FindModules do Map.put(compiler_data, :data, data) end - defp get_defmodules({:defprotocol, _, [{:__aliases__, _, _} = the_alias, _]} = ast, state, _) do - s = %{ name: Utils.quoted_to_name(the_alias), type: :protocol, ast: ast } + defp get_defmodules({:defprotocol, _, [{:__aliases__, _, _} = the_alias, [do: {:__block__, _, _} = block]]} = ast, state, _) do + s = %{ name: Utils.quoted_to_name(the_alias), type: :protocol, ast: block } { ast, state ++ [s] } end - defp get_defmodules({:defimpl, _, [ {:__aliases__, _, name} = the_alias, [for: {:__aliases__, _, type_name} = type], _ ]} = ast, state, _) do + defp get_defmodules({:defprotocol, _, [{:__aliases__, _, _} = the_alias, [do: spec]]} = ast, state, _) do + s = %{ name: Utils.quoted_to_name(the_alias), type: :protocol, ast: {:__block__, [], [spec]} } + { ast, state ++ [s] } + end + + defp get_defmodules({:defimpl, _, [ {:__aliases__, _, name} = the_alias, [for: {:__aliases__, _, type_name} = type], [do: {:__block__, context, spec}] ]} = ast, state, _) do + name = name ++ [DefImpl] ++ type_name + s = %{name: Utils.quoted_to_name({:__aliases__, [], name}), type: :impl, for: type, ast: {:__block__, context, spec}, implements: Utils.quoted_to_name(the_alias) } + { ast, state ++ [s] } + end + + defp get_defmodules({:defimpl, _, [ {:__aliases__, _, name} = the_alias, [for: {:__aliases__, _, type_name} = type], [do: spec] ]} = ast, state, _) do name = name ++ [DefImpl] ++ type_name - s = %{name: Utils.quoted_to_name({:__aliases__, [], name}), type: :impl, for: type, ast: ast, implements: Utils.quoted_to_name(the_alias) } + s = %{name: Utils.quoted_to_name({:__aliases__, [], name}), type: :impl, for: type, ast: {:__block__, [], [spec]}, implements: Utils.quoted_to_name(the_alias) } { ast, state ++ [s] } end @@ -90,6 +101,7 @@ defmodule ElixirScript.Passes.FindModules do body end + body = add_aliases_to_body(body, aliases) [%{name: Utils.quoted_to_name(the_alias), type: :module, ast: body }] ++ state end diff --git a/lib/elixir_script/translator.ex b/lib/elixir_script/translator.ex index e4f83e04..70f244e4 100644 --- a/lib/elixir_script/translator.ex +++ b/lib/elixir_script/translator.ex @@ -539,10 +539,7 @@ defmodule ElixirScript.Translator do end defp do_translate({name, _, params} = ast, env) when is_list(params) do - - expanded_ast = Macro.expand(ast, env.env) - if expanded_ast == ast do name_arity = {name, length(params)} module = ElixirScript.Translator.State.get_module(env.module) diff --git a/lib/elixir_script/translator/kernel/special_forms/call.ex b/lib/elixir_script/translator/kernel/special_forms/call.ex index 06a33933..8ed21f61 100644 --- a/lib/elixir_script/translator/kernel/special_forms/call.ex +++ b/lib/elixir_script/translator/kernel/special_forms/call.ex @@ -122,6 +122,7 @@ defmodule ElixirScript.Translator.Call do Utils.name_to_js_name(module_name) module_name in ElixirScript.Translator.State.list_module_names -> + ElixirScript.Translator.State.add_module_reference(env.module, module_name) Utils.name_to_js_name(module_name) true -> diff --git a/lib/elixir_script/translator/kernel/special_forms/fn.ex b/lib/elixir_script/translator/kernel/special_forms/fn.ex index 1673a8fa..26c4f44a 100644 --- a/lib/elixir_script/translator/kernel/special_forms/fn.ex +++ b/lib/elixir_script/translator/kernel/special_forms/fn.ex @@ -147,8 +147,9 @@ defmodule ElixirScript.Translator.Function do Enum.map_reduce(list, env, fn(x, env) -> Translator.translate(x, env) end) - _ -> - Enum.map_reduce(List.wrap(body), env, fn(x, env) -> + _ -> + + Enum.map_reduce(List.wrap(body), env, fn(x, env) -> Translator.translate(x, env) end) end diff --git a/lib/elixir_script/translator/lexical_scope.ex b/lib/elixir_script/translator/lexical_scope.ex index eb7c4b6a..f3487d74 100644 --- a/lib/elixir_script/translator/lexical_scope.ex +++ b/lib/elixir_script/translator/lexical_scope.ex @@ -176,6 +176,7 @@ defmodule ElixirScript.Translator.LexicalScope do raise "Module #{inspect module_name} not found" end + ElixirScript.Translator.State.add_module_reference(env.module, module.name) module end @@ -205,7 +206,6 @@ defmodule ElixirScript.Translator.LexicalScope do if has_module?(env, module_name) do module = get_module(env, module_name) - %{ env | requires: Enum.uniq(env.requires ++ [module.name]), functions: env.functions ++ [{ module.name, module.functions }] } else diff --git a/lib/elixir_script/translator/state.ex b/lib/elixir_script/translator/state.ex index d262c3d6..380a9feb 100644 --- a/lib/elixir_script/translator/state.ex +++ b/lib/elixir_script/translator/state.ex @@ -115,6 +115,19 @@ defmodule ElixirScript.Translator.State do end) end + def add_module_reference(module_name, module_ref) do + Agent.update(__MODULE__, fn(state) -> + case Keyword.get(state.modules, do_get_module_name(module_name, state)) do + nil -> + state + module -> + module = Map.update(module, :deps, [module_ref], fn(x) -> Enum.uniq(x ++ [module_ref]) end) + modules = Keyword.put(state.modules, module.name, module) + %{ state | modules: modules } + end + end) + end + def get_module_references(module_name) do case get_module(module_name) do nil -> diff --git a/test/translator/defmodule_test.exs b/test/translator/defmodule_test.exs index b157b680..e49ffc2b 100644 --- a/test/translator/defmodule_test.exs +++ b/test/translator/defmodule_test.exs @@ -234,11 +234,6 @@ defmodule ElixirScript.Translator.Defmodule.Test do end js_code = """ - import Elixir$ElixirScript$Kernel from '../elixir/Elixir.ElixirScript.Kernel'; - import Elixir$Lions$Tigers from '../app/Elixir.Lions.Tigers'; - Elixir$Lions$Tigers.oh_my(); - export default {}; - import Elixir$ElixirScript$Kernel from '../elixir/Elixir.ElixirScript.Kernel'; const oh_my2 = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.clause([],function() { return null; @@ -251,6 +246,11 @@ defmodule ElixirScript.Translator.Defmodule.Test do export default { oh_my2, oh_my }; + + import Elixir$ElixirScript$Kernel from '../elixir/Elixir.ElixirScript.Kernel'; + import Elixir$Lions$Tigers from '../app/Elixir.Lions.Tigers'; + Elixir$Lions$Tigers.oh_my(); + export default {}; """ assert_translation(ex_ast, js_code) @@ -274,11 +274,6 @@ defmodule ElixirScript.Translator.Defmodule.Test do end js_code = """ - import Elixir$ElixirScript$Kernel from '../elixir/Elixir.ElixirScript.Kernel'; - import Elixir$Lions$Tigers from '../app/Elixir.Lions.Tigers'; - Elixir$Lions$Tigers.oh_my2(); - export default {}; - import Elixir$ElixirScript$Kernel from '../elixir/Elixir.ElixirScript.Kernel'; const oh_my2 = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.clause([],function() { return null; @@ -292,6 +287,11 @@ defmodule ElixirScript.Translator.Defmodule.Test do oh_my2, oh_my }; + + import Elixir$ElixirScript$Kernel from '../elixir/Elixir.ElixirScript.Kernel'; + import Elixir$Lions$Tigers from '../app/Elixir.Lions.Tigers'; + Elixir$Lions$Tigers.oh_my2(); + export default {}; """ assert_translation(ex_ast, js_code) @@ -318,11 +318,11 @@ defmodule ElixirScript.Translator.Defmodule.Test do export default {}; import Elixir$ElixirScript$Kernel from '../elixir/Elixir.ElixirScript.Kernel'; - import Elixir$Version$Parser$DSL from '../app/Elixir.Version.Parser.DSL'; + import Elixir$Version$Parser from '../app/Elixir.Version.Parser'; export default {}; import Elixir$ElixirScript$Kernel from '../elixir/Elixir.ElixirScript.Kernel'; - import Elixir$Version$Parser from '../app/Elixir.Version.Parser'; + import Elixir$Version$Parser$DSL from '../app/Elixir.Version.Parser.DSL'; export default {}; """ diff --git a/test/translator/protocol_test.exs b/test/translator/protocol_test.exs index 6b20ad77..8a0d1f06 100644 --- a/test/translator/protocol_test.exs +++ b/test/translator/protocol_test.exs @@ -35,20 +35,6 @@ defmodule ElixirScript.Translator.Defprotocol.Test do for(let {Type,Implementation} of Implementations) Elixir.Core.Functions.defimpl(Elixir$Blank,Type,Implementation) export default Elixir$Blank; - import Elixir$ElixirScript$Kernel from '../elixir/Elixir.ElixirScript.Kernel'; - const blank__qmark__ = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.clause([false],function() { - return true; - }),Elixir.Core.Patterns.clause([null],function() { - return true; - }),Elixir.Core.Patterns.clause([Elixir.Core.Patterns.wildcard()],function() { - return false; - })); - export default { - 'Type': Symbol, 'Implementation': { - blank__qmark__ - } - }; - import Elixir$ElixirScript$Kernel from '../elixir/Elixir.ElixirScript.Kernel'; const blank__qmark__ = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.clause([Elixir.Core.Patterns.variable()],function(number) { return false; @@ -71,16 +57,28 @@ defmodule ElixirScript.Translator.Defprotocol.Test do } }; - + import Elixir$ElixirScript$Kernel from '../elixir/Elixir.ElixirScript.Kernel'; + const blank__qmark__ = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.clause([false],function() { + return true; + }),Elixir.Core.Patterns.clause([null],function() { + return true; + }),Elixir.Core.Patterns.clause([Elixir.Core.Patterns.wildcard()],function() { + return false; + })); + export default { + 'Type': Symbol, 'Implementation': { + blank__qmark__ + } + }; import Elixir from '../elixir/Elixir'; let impls = []; - import Elixir$Blank$DefImpl$Elixir$Atom from '../app/Elixir.Blank.DefImpl.Elixir.Atom'; - impls.push(Elixir$Blank$DefImpl$Elixir$Atom) import Elixir$Blank$DefImpl$Elixir$Integer from '../app/Elixir.Blank.DefImpl.Elixir.Integer'; impls.push(Elixir$Blank$DefImpl$Elixir$Integer) import Elixir$Blank$DefImpl$Elixir$List from '../app/Elixir.Blank.DefImpl.Elixir.List'; impls.push(Elixir$Blank$DefImpl$Elixir$List) + import Elixir$Blank$DefImpl$Elixir$Atom from '../app/Elixir.Blank.DefImpl.Elixir.Atom'; + impls.push(Elixir$Blank$DefImpl$Elixir$Atom) export default impls; """ diff --git a/test/translator/struct_test.exs b/test/translator/struct_test.exs index 3821aa54..4d7248b5 100644 --- a/test/translator/struct_test.exs +++ b/test/translator/struct_test.exs @@ -59,7 +59,6 @@ defmodule ElixirScript.Translator.Struct.Test do end js_code = """ - let [user] = Elixir.Core.Patterns.match(Elixir.Core.Patterns.variable(), Elixir$User.Elixir$User.create(Object.freeze({}))); import Elixir$ElixirScript$Kernel from '../elixir/Elixir.ElixirScript.Kernel'; const Elixir$User = Elixir.Core.Functions.defstruct({ @@ -71,6 +70,8 @@ defmodule ElixirScript.Translator.Struct.Test do export default { Elixir$User }; + + let [user] = Elixir.Core.Patterns.match(Elixir.Core.Patterns.variable(), Elixir$User.Elixir$User.create(Object.freeze({}))); """ assert_translation(ex_ast, js_code) @@ -84,10 +85,6 @@ defmodule ElixirScript.Translator.Struct.Test do end js_code = """ - let [user] = Elixir.Core.Patterns.match(Elixir.Core.Patterns.variable(),Elixir$User.Elixir$User.create(Object.freeze({ - [Symbol.for('name')]: 'John' - }))); - import Elixir$ElixirScript$Kernel from '../elixir/Elixir.ElixirScript.Kernel'; const Elixir$User = Elixir.Core.Functions.defstruct({ [Symbol.for('__struct__')]: Symbol.for('Elixir.User'), @@ -97,6 +94,10 @@ defmodule ElixirScript.Translator.Struct.Test do export default { Elixir$User }; + + let [user] = Elixir.Core.Patterns.match(Elixir.Core.Patterns.variable(),Elixir$User.Elixir$User.create(Object.freeze({ + [Symbol.for('name')]: 'John' + }))); """ assert_translation(ex_ast, js_code) @@ -183,10 +184,6 @@ defmodule ElixirScript.Translator.Struct.Test do end js_code = """ - throw Elixir$MyAppError.Elixir$MyAppError.create(Object.freeze({ - [Symbol.for('message')]: 'did not get what was expected' - })); - import Elixir$ElixirScript$Kernel from '../elixir/Elixir.ElixirScript.Kernel'; const Elixir$MyAppError = Elixir.Core.Functions.defexception({ [Symbol.for('__struct__')]: Symbol.for('Elixir.MyAppError'), @@ -197,6 +194,10 @@ defmodule ElixirScript.Translator.Struct.Test do export default { Elixir$MyAppError }; + + throw Elixir$MyAppError.Elixir$MyAppError.create(Object.freeze({ + [Symbol.for('message')]: 'did not get what was expected' + })); """ assert_translation(ex_ast, js_code) From 3a81b9b5d404411f5091366decff20be7b4d2af8 Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Tue, 18 Oct 2016 08:27:07 -0500 Subject: [PATCH 317/860] Fixed issues with loading modules --- lib/elixir_script/passes/deps_paths.ex | 2 +- lib/elixir_script/passes/load_modules.ex | 3 +-- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/lib/elixir_script/passes/deps_paths.ex b/lib/elixir_script/passes/deps_paths.ex index 5a2d1e17..0ee73c54 100644 --- a/lib/elixir_script/passes/deps_paths.ex +++ b/lib/elixir_script/passes/deps_paths.ex @@ -5,7 +5,7 @@ defmodule ElixirScript.Passes.DepsPaths do def execute(compiler_data, opts) do data = cond do - opts.std_lib -> + Map.get(opts, :std_lib, false) -> [{opts[:app], [compiler_data.path]}] Code.ensure_loaded?(Mix) -> deps = get_deps_paths(Mix.env) diff --git a/lib/elixir_script/passes/load_modules.ex b/lib/elixir_script/passes/load_modules.ex index bb4d53cf..caa7716e 100644 --- a/lib/elixir_script/passes/load_modules.ex +++ b/lib/elixir_script/passes/load_modules.ex @@ -2,8 +2,7 @@ defmodule ElixirScript.Passes.LoadModules do @pass 5 def execute(compiler_data, opts) do - ex_files = Enum.filter(compiler_data.data, fn - { module, %{path: path} } -> path end) + ex_files = Enum.map(compiler_data.data, fn { module, %{path: path} } -> path end) |> Enum.filter(fn path -> Path.extname(path) == ".ex" || Path.extname(path) == ".exs" end) loaded_modules = Kernel.ParallelRequire.files(ex_files) From ac49d9782ae316e5ff8b9b92f22036a8afb328b8 Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Tue, 18 Oct 2016 09:02:34 -0500 Subject: [PATCH 318/860] Add filter_exjs so that only exjs files are compiled --- lib/elixir_script.ex | 1 + lib/elixir_script/passes/deps_paths.ex | 2 +- lib/elixir_script/passes/filter_exjs.ex | 11 +++++++++++ lib/elixir_script/passes/load_modules.ex | 10 ++++++++-- 4 files changed, 21 insertions(+), 3 deletions(-) create mode 100644 lib/elixir_script/passes/filter_exjs.ex diff --git a/lib/elixir_script.ex b/lib/elixir_script.ex index 2e9bd490..a6ec93b5 100644 --- a/lib/elixir_script.ex +++ b/lib/elixir_script.ex @@ -126,6 +126,7 @@ defmodule ElixirScript do |> ElixirScript.Passes.RemoveUnused.execute(opts) |> ElixirScript.Passes.LoadModules.execute(opts) |> ElixirScript.Passes.FindChangedFiles.execute(opts) + |> ElixirScript.Passes.FilterExjs.execute(opts) |> ElixirScript.Passes.FindFunctions.execute(opts) |> ElixirScript.Passes.JavaScriptAST.execute(opts) |> ElixirScript.Passes.ConsolidateProtocols.execute(opts) diff --git a/lib/elixir_script/passes/deps_paths.ex b/lib/elixir_script/passes/deps_paths.ex index 0ee73c54..c556cfbc 100644 --- a/lib/elixir_script/passes/deps_paths.ex +++ b/lib/elixir_script/passes/deps_paths.ex @@ -8,7 +8,7 @@ defmodule ElixirScript.Passes.DepsPaths do Map.get(opts, :std_lib, false) -> [{opts[:app], [compiler_data.path]}] Code.ensure_loaded?(Mix) -> - deps = get_deps_paths(Mix.env) + deps = get_deps_paths(:elixirscript) deps ++ [{opts[:app], [compiler_data.path]}] true -> [{opts[:app], [compiler_data.path]}] diff --git a/lib/elixir_script/passes/filter_exjs.ex b/lib/elixir_script/passes/filter_exjs.ex new file mode 100644 index 00000000..0c1e81a5 --- /dev/null +++ b/lib/elixir_script/passes/filter_exjs.ex @@ -0,0 +1,11 @@ +defmodule ElixirScript.Passes.FilterExjs do + + + def execute(compiler_data, opts) do + + data = Enum.filter(compiler_data.data, fn({m, data}) -> Path.extname(data.path) == ".exjs" end) + + Map.put(compiler_data, :data, data) + end + +end diff --git a/lib/elixir_script/passes/load_modules.ex b/lib/elixir_script/passes/load_modules.ex index caa7716e..8ad6c997 100644 --- a/lib/elixir_script/passes/load_modules.ex +++ b/lib/elixir_script/passes/load_modules.ex @@ -5,8 +5,14 @@ defmodule ElixirScript.Passes.LoadModules do ex_files = Enum.map(compiler_data.data, fn { module, %{path: path} } -> path end) |> Enum.filter(fn path -> Path.extname(path) == ".ex" || Path.extname(path) == ".exs" end) - loaded_modules = Kernel.ParallelRequire.files(ex_files) - Map.put(compiler_data, :loaded_modules, loaded_modules) + loaded_modules = try do + Kernel.ParallelRequire.files(ex_files) + rescue + _ -> + [] + end + + Map.put(compiler_data, :loaded_modules, []) end end From 64893861f831197bec0901e732d87039d91162b3 Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Tue, 18 Oct 2016 21:42:12 -0500 Subject: [PATCH 319/860] only adding deps from projects with elixirscript configs --- lib/elixir_script.ex | 1 - lib/elixir_script/passes/deps_paths.ex | 20 +++++++++++++------- lib/elixir_script/passes/load_modules.ex | 19 ++++++++++++------- 3 files changed, 25 insertions(+), 15 deletions(-) diff --git a/lib/elixir_script.ex b/lib/elixir_script.ex index a6ec93b5..76ab8225 100644 --- a/lib/elixir_script.ex +++ b/lib/elixir_script.ex @@ -123,7 +123,6 @@ defmodule ElixirScript do |> ElixirScript.Passes.DepsPaths.execute(opts) |> ElixirScript.Passes.ASTFromFile.execute(opts) |> ElixirScript.Passes.FindModules.execute(opts) - |> ElixirScript.Passes.RemoveUnused.execute(opts) |> ElixirScript.Passes.LoadModules.execute(opts) |> ElixirScript.Passes.FindChangedFiles.execute(opts) |> ElixirScript.Passes.FilterExjs.execute(opts) diff --git a/lib/elixir_script/passes/deps_paths.ex b/lib/elixir_script/passes/deps_paths.ex index c556cfbc..e1e1e09c 100644 --- a/lib/elixir_script/passes/deps_paths.ex +++ b/lib/elixir_script/passes/deps_paths.ex @@ -8,7 +8,7 @@ defmodule ElixirScript.Passes.DepsPaths do Map.get(opts, :std_lib, false) -> [{opts[:app], [compiler_data.path]}] Code.ensure_loaded?(Mix) -> - deps = get_deps_paths(:elixirscript) + deps = get_deps_paths(Mix.env) deps ++ [{opts[:app], [compiler_data.path]}] true -> [{opts[:app], [compiler_data.path]}] @@ -24,12 +24,18 @@ defmodule ElixirScript.Passes.DepsPaths do defp do_get_deps_paths(deps) do Enum.reduce(deps, [], fn(dep, list) -> - paths = Mix.Project.in_project dep.app, dep.opts[:dest], fn mixfile -> Mix.Project.config()[:elixirc_paths] end - paths = Enum.map(paths, fn path -> Path.join([dep.opts[:dest], path]) end) - - deps = do_get_deps_paths(dep.deps) - - deps ++ [{dep.app, paths}] ++ list + elixirscript_config = Mix.Project.in_project dep.app, dep.opts[:dest], fn mixfile -> Mix.Project.config()[:elixirscript] end + + paths = case elixirscript_config do + nil -> + list + + config -> + paths = Keyword.get(config, :input, "") |> List.wrap + paths = Enum.map(paths, fn path -> Path.join([dep.opts[:dest], path]) end) + deps = do_get_deps_paths(dep.deps) + deps ++ [{dep.app, paths}] ++ list + end end) |> Enum.uniq end diff --git a/lib/elixir_script/passes/load_modules.ex b/lib/elixir_script/passes/load_modules.ex index 8ad6c997..066d3c8a 100644 --- a/lib/elixir_script/passes/load_modules.ex +++ b/lib/elixir_script/passes/load_modules.ex @@ -5,14 +5,19 @@ defmodule ElixirScript.Passes.LoadModules do ex_files = Enum.map(compiler_data.data, fn { module, %{path: path} } -> path end) |> Enum.filter(fn path -> Path.extname(path) == ".ex" || Path.extname(path) == ".exs" end) - loaded_modules = try do - Kernel.ParallelRequire.files(ex_files) - rescue - _ -> - [] - end + loaded_modules = case ex_files do + [] -> + [] + files -> + try do + Kernel.ParallelRequire.files(files) + rescue + _ -> + [] + end + end - Map.put(compiler_data, :loaded_modules, []) + Map.put(compiler_data, :loaded_modules, loaded_modules) end end From 6b790bf13c9d70f05c079b831010624569d07516 Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Wed, 19 Oct 2016 20:04:07 -0500 Subject: [PATCH 320/860] Updated compile pipeline. compiling in parallel --- lib/elixir_script.ex | 4 ++-- lib/elixir_script/passes/filter_exjs.ex | 5 ++++- lib/elixir_script/passes/java_script_ast.ex | 18 ++++++++++++++++-- lib/elixir_script/passes/java_script_code.ex | 17 +++++++++++++++-- lib/elixir_script/passes/load_modules.ex | 5 ++++- 5 files changed, 41 insertions(+), 8 deletions(-) diff --git a/lib/elixir_script.ex b/lib/elixir_script.ex index 76ab8225..e1fa5e49 100644 --- a/lib/elixir_script.ex +++ b/lib/elixir_script.ex @@ -122,10 +122,10 @@ defmodule ElixirScript do |> ElixirScript.Passes.Init.execute(opts) |> ElixirScript.Passes.DepsPaths.execute(opts) |> ElixirScript.Passes.ASTFromFile.execute(opts) - |> ElixirScript.Passes.FindModules.execute(opts) |> ElixirScript.Passes.LoadModules.execute(opts) - |> ElixirScript.Passes.FindChangedFiles.execute(opts) |> ElixirScript.Passes.FilterExjs.execute(opts) + |> ElixirScript.Passes.FindModules.execute(opts) + |> ElixirScript.Passes.FindChangedFiles.execute(opts) |> ElixirScript.Passes.FindFunctions.execute(opts) |> ElixirScript.Passes.JavaScriptAST.execute(opts) |> ElixirScript.Passes.ConsolidateProtocols.execute(opts) diff --git a/lib/elixir_script/passes/filter_exjs.ex b/lib/elixir_script/passes/filter_exjs.ex index 0c1e81a5..582f8fec 100644 --- a/lib/elixir_script/passes/filter_exjs.ex +++ b/lib/elixir_script/passes/filter_exjs.ex @@ -3,7 +3,10 @@ defmodule ElixirScript.Passes.FilterExjs do def execute(compiler_data, opts) do - data = Enum.filter(compiler_data.data, fn({m, data}) -> Path.extname(data.path) == ".exjs" end) + data = Enum.filter(compiler_data.data, fn + {m, data} -> Path.extname(data.path) == ".exjs" + data -> Path.extname(data.path) == ".exjs" + end) Map.put(compiler_data, :data, data) end diff --git a/lib/elixir_script/passes/java_script_ast.ex b/lib/elixir_script/passes/java_script_ast.ex index 2b89ab54..e6dc1fd6 100644 --- a/lib/elixir_script/passes/java_script_ast.ex +++ b/lib/elixir_script/passes/java_script_ast.ex @@ -5,9 +5,23 @@ defmodule ElixirScript.Passes.JavaScriptAST do def execute(compiler_data, opts) do State.set_module_data(compiler_data.data) + + parent = self + data = Enum.map(compiler_data.data, fn({module_name, module_data}) -> - module_data = compile(module_data, opts) - {module_name, module_data} + + spawn_link fn -> + module_data = compile(module_data, opts) + result = {module_name, module_data} + send parent, {self, result } + end + + end) + |> Enum.map(fn pid -> + receive do + {^pid, result} -> + result + end end) %{ compiler_data | data: data } diff --git a/lib/elixir_script/passes/java_script_code.ex b/lib/elixir_script/passes/java_script_code.ex index e31ba7ba..bc995381 100644 --- a/lib/elixir_script/passes/java_script_code.ex +++ b/lib/elixir_script/passes/java_script_code.ex @@ -3,9 +3,22 @@ defmodule ElixirScript.Passes.JavaScriptCode do alias ESTree.Tools.{ Builder, Generator } def execute(compiler_data, _) do + parent = self + data = Enum.map(compiler_data.data, fn({module_name, module_data}) -> - module_data = compile(module_data) - {module_name, module_data} + + spawn_link fn -> + module_data = compile(module_data) + result = {module_name, module_data} + send parent, {self, result } + end + + end) + |> Enum.map(fn pid -> + receive do + {^pid, result} -> + result + end end) %{ compiler_data | data: data } diff --git a/lib/elixir_script/passes/load_modules.ex b/lib/elixir_script/passes/load_modules.ex index 066d3c8a..5029d421 100644 --- a/lib/elixir_script/passes/load_modules.ex +++ b/lib/elixir_script/passes/load_modules.ex @@ -2,7 +2,10 @@ defmodule ElixirScript.Passes.LoadModules do @pass 5 def execute(compiler_data, opts) do - ex_files = Enum.map(compiler_data.data, fn { module, %{path: path} } -> path end) + ex_files = Enum.map(compiler_data.data, fn + { module, %{path: path} } -> path + %{path: path} -> path + end) |> Enum.filter(fn path -> Path.extname(path) == ".ex" || Path.extname(path) == ".exs" end) loaded_modules = case ex_files do From 2caee238a0b37f1e7d851ca138bff0efff4c1312 Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Wed, 19 Oct 2016 20:09:17 -0500 Subject: [PATCH 321/860] Update CHANGELOG --- CHANGELOG.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 69ea33b5..366beb44 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,8 @@ and this project adheres to [Semantic Versioning](http://semver.org/). ## [Unreleased] ### Changed - Changed CHANGELOG.md to adhere the format from Keep a Changelog +- New compiler pipeline +- If in mix project, will crawls deps to find packages that have an `elixirscript` config key with the `input` key set to a path to look in ## [0.22.0] - 2016-10-16 ### Added From 0bc17c4d3aaafc63dd035393f15ce4aeee1a338b Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Wed, 19 Oct 2016 20:10:52 -0500 Subject: [PATCH 322/860] Updated CHANGELOG --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 366beb44..94812162 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,7 +8,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/). ### Changed - Changed CHANGELOG.md to adhere the format from Keep a Changelog - New compiler pipeline -- If in mix project, will crawls deps to find packages that have an `elixirscript` config key with the `input` key set to a path to look in +- If in mix project, will crawls deps to find packages that have an `elixir_script` config key with the `input` key set to a path to look in ## [0.22.0] - 2016-10-16 ### Added From 201a8b8f11585d10f0e3c2b9b339d2ac139efc39 Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Wed, 19 Oct 2016 21:11:58 -0500 Subject: [PATCH 323/860] Fixed some warnings --- lib/elixir_script/passes/add_std_lib.ex | 2 +- .../passes/consolidate_protocols.ex | 5 ++-- lib/elixir_script/passes/deps_paths.ex | 24 +++++++++---------- lib/elixir_script/passes/filter_exjs.ex | 4 ++-- .../passes/find_changed_files.ex | 2 +- lib/elixir_script/passes/find_functions.ex | 2 +- lib/elixir_script/passes/handle_output.ex | 4 ++-- lib/elixir_script/passes/java_script_ast.ex | 3 ++- lib/elixir_script/passes/load_modules.ex | 4 ++-- lib/elixir_script/translator.ex | 1 - lib/elixir_script/translator/state.ex | 1 + test/compiler/deps_test.exs | 5 ---- 12 files changed, 26 insertions(+), 31 deletions(-) delete mode 100644 test/compiler/deps_test.exs diff --git a/lib/elixir_script/passes/add_std_lib.ex b/lib/elixir_script/passes/add_std_lib.ex index 5718a33a..05b5672e 100644 --- a/lib/elixir_script/passes/add_std_lib.ex +++ b/lib/elixir_script/passes/add_std_lib.ex @@ -1,7 +1,7 @@ defmodule ElixirScript.Passes.AddStdLib do alias ElixirScript.Translator.State - def execute(compiler_data, opts) do + def execute(compiler_data, _) do State.deserialize(ElixirScript.get_stdlib_state, []) compiler_data end diff --git a/lib/elixir_script/passes/consolidate_protocols.ex b/lib/elixir_script/passes/consolidate_protocols.ex index 4f708fc0..2035cf1d 100644 --- a/lib/elixir_script/passes/consolidate_protocols.ex +++ b/lib/elixir_script/passes/consolidate_protocols.ex @@ -3,7 +3,6 @@ defmodule ElixirScript.Passes.ConsolidateProtocols do alias ESTree.Tools.Builder, as: JS alias ElixirScript.Translator.Utils alias ElixirScript.ModuleSystems - alias ElixirScript.Translator.Identifier require Logger def execute(compiler_data, opts) do @@ -47,7 +46,7 @@ defmodule ElixirScript.Passes.ConsolidateProtocols do end) end - defp make_defimpl(name, { protocol_name, protocol }, implementations, compiler_opts) do + defp make_defimpl(name, { _, protocol }, implementations, compiler_opts) do imports = [ModuleSystems.import_module(:Elixir, Utils.make_local_file_path(:elixir, compiler_opts.core_path, compiler_opts.root))] declarator = JS.variable_declarator( @@ -63,7 +62,7 @@ defmodule ElixirScript.Passes.ConsolidateProtocols do app_name = protocol.app - body = Enum.flat_map(implementations, fn({impl_app_name, impl_data}) -> + body = Enum.flat_map(implementations, fn({_, impl_data}) -> x = Atom.to_string(Utils.quoted_to_name(impl_data.for)) x = String.to_atom(protocol_name <> ".DefImpl." <> x) name = Utils.name_to_js_name(x) diff --git a/lib/elixir_script/passes/deps_paths.ex b/lib/elixir_script/passes/deps_paths.ex index e1e1e09c..b2430ffb 100644 --- a/lib/elixir_script/passes/deps_paths.ex +++ b/lib/elixir_script/passes/deps_paths.ex @@ -24,18 +24,18 @@ defmodule ElixirScript.Passes.DepsPaths do defp do_get_deps_paths(deps) do Enum.reduce(deps, [], fn(dep, list) -> - elixirscript_config = Mix.Project.in_project dep.app, dep.opts[:dest], fn mixfile -> Mix.Project.config()[:elixirscript] end - - paths = case elixirscript_config do - nil -> - list - - config -> - paths = Keyword.get(config, :input, "") |> List.wrap - paths = Enum.map(paths, fn path -> Path.join([dep.opts[:dest], path]) end) - deps = do_get_deps_paths(dep.deps) - deps ++ [{dep.app, paths}] ++ list - end + elixirscript_config = Mix.Project.in_project dep.app, dep.opts[:dest], fn _ -> Mix.Project.config()[:elixirscript] end + + case elixirscript_config do + nil -> + list + + config -> + paths = Keyword.get(config, :input, "") |> List.wrap + paths = Enum.map(paths, fn path -> Path.join([dep.opts[:dest], path]) end) + deps = do_get_deps_paths(dep.deps) + deps ++ [{dep.app, paths}] ++ list + end end) |> Enum.uniq end diff --git a/lib/elixir_script/passes/filter_exjs.ex b/lib/elixir_script/passes/filter_exjs.ex index 582f8fec..bfb7edf5 100644 --- a/lib/elixir_script/passes/filter_exjs.ex +++ b/lib/elixir_script/passes/filter_exjs.ex @@ -1,10 +1,10 @@ defmodule ElixirScript.Passes.FilterExjs do - def execute(compiler_data, opts) do + def execute(compiler_data, _) do data = Enum.filter(compiler_data.data, fn - {m, data} -> Path.extname(data.path) == ".exjs" + {_, data} -> Path.extname(data.path) == ".exjs" data -> Path.extname(data.path) == ".exjs" end) diff --git a/lib/elixir_script/passes/find_changed_files.ex b/lib/elixir_script/passes/find_changed_files.ex index d513c1d4..44b52b7c 100644 --- a/lib/elixir_script/passes/find_changed_files.ex +++ b/lib/elixir_script/passes/find_changed_files.ex @@ -10,7 +10,7 @@ defmodule ElixirScript.Passes.FindChangedFiles do new_file_stats = Enum.map(compiler_data.data, fn({_, data}) -> { data.path, data.stat } end) |> Enum.uniq changed_files = Cache.get_changed_files(compiler_cache.input_files, new_file_stats) - |> Enum.map(fn {file, state} -> file end) + |> Enum.map(fn {file, _} -> file end) State.deserialize(compiler_cache.state, compiler_data.loaded_modules) diff --git a/lib/elixir_script/passes/find_functions.ex b/lib/elixir_script/passes/find_functions.ex index 7864df53..72e55dd2 100644 --- a/lib/elixir_script/passes/find_functions.ex +++ b/lib/elixir_script/passes/find_functions.ex @@ -2,7 +2,7 @@ defmodule ElixirScript.Passes.FindFunctions do @pass 6 @function_types [:def, :defp, :defgen, :defgenp] - def execute(data, opts) do + def execute(data, _) do new_data = Enum.map(data.data, fn { module_name, module_data } -> %{def: functions, defp: private_functions, defgen: generators, defgenp: private_generators } = get_functions_from_module(module_data.ast) diff --git a/lib/elixir_script/passes/handle_output.ex b/lib/elixir_script/passes/handle_output.ex index cd4c3540..8e38b8d9 100644 --- a/lib/elixir_script/passes/handle_output.ex +++ b/lib/elixir_script/passes/handle_output.ex @@ -28,7 +28,7 @@ defmodule ElixirScript.Passes.HandleOutput do end) end - defp out(compiler_output, %{output: output_path, core_path: core_path} = compiler_opts) do + defp out(compiler_output, %{output: output_path, core_path: _} = compiler_opts) do Enum.each(compiler_output.data, fn({_, x}) -> write_to_file(x, output_path) end) @@ -50,7 +50,7 @@ defmodule ElixirScript.Passes.HandleOutput do defp process_include_path(compiler_output, compiler_opts) do Enum.map(compiler_output.data, fn - {module_name, module_data} -> + {_, module_data} -> case compiler_opts.include_path do true -> { module_data.javascript_name, module_data.javascript_code, module_data.app } diff --git a/lib/elixir_script/passes/java_script_ast.ex b/lib/elixir_script/passes/java_script_ast.ex index e6dc1fd6..857156f9 100644 --- a/lib/elixir_script/passes/java_script_ast.ex +++ b/lib/elixir_script/passes/java_script_ast.ex @@ -8,7 +8,8 @@ defmodule ElixirScript.Passes.JavaScriptAST do parent = self - data = Enum.map(compiler_data.data, fn({module_name, module_data}) -> + data = compiler_data.data + |> Enum.map(fn({module_name, module_data}) -> spawn_link fn -> module_data = compile(module_data, opts) diff --git a/lib/elixir_script/passes/load_modules.ex b/lib/elixir_script/passes/load_modules.ex index 5029d421..6f7a99ef 100644 --- a/lib/elixir_script/passes/load_modules.ex +++ b/lib/elixir_script/passes/load_modules.ex @@ -1,9 +1,9 @@ defmodule ElixirScript.Passes.LoadModules do @pass 5 - def execute(compiler_data, opts) do + def execute(compiler_data, _) do ex_files = Enum.map(compiler_data.data, fn - { module, %{path: path} } -> path + { _, %{path: path} } -> path %{path: path} -> path end) |> Enum.filter(fn path -> Path.extname(path) == ".ex" || Path.extname(path) == ".exs" end) diff --git a/lib/elixir_script/translator.ex b/lib/elixir_script/translator.ex index 70f244e4..20b0cc34 100644 --- a/lib/elixir_script/translator.ex +++ b/lib/elixir_script/translator.ex @@ -28,7 +28,6 @@ defmodule ElixirScript.Translator do alias ESTree.Tools.Builder, as: JS alias ElixirScript.Translator.Rewriter alias ElixirScript.Translator.Receive - alias ElixirScript.Translator.LexicalScope # A list of erlang modules. These are rewritten into equivalent # JavaScript functions using ElixirScript.Translator.Rewriter diff --git a/lib/elixir_script/translator/state.ex b/lib/elixir_script/translator/state.ex index 380a9feb..9aa2ba05 100644 --- a/lib/elixir_script/translator/state.ex +++ b/lib/elixir_script/translator/state.ex @@ -17,6 +17,7 @@ defmodule ElixirScript.Translator.State do def serialize() do Agent.get(__MODULE__, fn(state) -> + state = Map.delete(state, :changed_modules) :erlang.term_to_binary(state) end) end diff --git a/test/compiler/deps_test.exs b/test/compiler/deps_test.exs deleted file mode 100644 index 7c5d5cf6..00000000 --- a/test/compiler/deps_test.exs +++ /dev/null @@ -1,5 +0,0 @@ -defmodule ElixirScript.Compiler.Deps.Test do - use ExUnit.Case - alias ElixirScript.Compiler.Cache - -end From aec10c9ee90a733217f1ee50622615ff9ca20eda Mon Sep 17 00:00:00 2001 From: Konstantin Lazarev Date: Sun, 16 Oct 2016 19:45:12 +0500 Subject: [PATCH 324/860] Implement else on with fixes #180 --- .../translator/kernel/special_forms/with.ex | 17 ++++-- src/javascript/lib/core/special_forms.js | 28 +++++---- src/javascript/tests/with.spec.js | 59 ++++++++++++++++++- test/translator/with_test.exs | 29 +++++++++ 4 files changed, 118 insertions(+), 15 deletions(-) diff --git a/lib/elixir_script/translator/kernel/special_forms/with.ex b/lib/elixir_script/translator/kernel/special_forms/with.ex index 4f485edd..dbd8b7bf 100644 --- a/lib/elixir_script/translator/kernel/special_forms/with.ex +++ b/lib/elixir_script/translator/kernel/special_forms/with.ex @@ -19,12 +19,15 @@ defmodule ElixirScript.Translator.With do expressions: state.expressions ++ [ JS.array_expression([hd(patterns), expr_function]) ] } [do: expr], state -> - - {body , _} = Function.prepare_function_body(expr, env) - translated_body = JS.block_statement(body) - expr_function = JS.function_expression(state.arguments, [], translated_body) + expr_function = process_do_block(expr, state.arguments, env) %{state | expressions: state.expressions ++ [ expr_function ] } + [do: do_expr, else: else_expr], state -> + do_function = process_do_block(do_expr, state.arguments, env) + + { else_function, _ } = Function.make_anonymous_function(else_expr, env) + + %{state | expressions: state.expressions ++ [ do_function, else_function ] } end) expressions = result.expressions @@ -40,4 +43,10 @@ defmodule ElixirScript.Translator.With do { js_ast, env } end + + defp process_do_block(expr, arguments, env) do + {body , _} = Function.prepare_function_body(expr, env) + translated_body = JS.block_statement(body) + JS.function_expression(arguments, [], translated_body) + end end diff --git a/src/javascript/lib/core/special_forms.js b/src/javascript/lib/core/special_forms.js index 864b0516..4214cfea 100644 --- a/src/javascript/lib/core/special_forms.js +++ b/src/javascript/lib/core/special_forms.js @@ -140,26 +140,34 @@ function _try(do_fun, rescue_function, catch_fun, else_function, after_function) function _with(...args){ let argsToPass = []; + let successFunction = null; + let elseFunction = null; + + if(typeof(args[args.length - 2]) === 'function'){ + [successFunction, elseFunction] = args.splice(-2); + }else{ + successFunction = args.pop(); + } for(let i = 0; i < args.length; i++){ - if(i === args.length - 1){ - return args[i].apply(null, argsToPass); - }else{ - let [pattern, func] = args[i]; + let [pattern, func] = args[i]; - let result = func.apply(null, argsToPass); + let result = func.apply(null, argsToPass); - let patternResult = Core.Patterns.match_or_default(pattern, result); + let patternResult = Core.Patterns.match_or_default(pattern, result); - if(patternResult == null){ - return result; + if(patternResult == null){ + if(elseFunction){ + return elseFunction.call(null, result); }else{ - argsToPass = argsToPass.concat(patternResult); + return result; } + }else{ + argsToPass = argsToPass.concat(patternResult); } } - return null; + return successFunction.apply(null, argsToPass); } export default { diff --git a/src/javascript/tests/with.spec.js b/src/javascript/tests/with.spec.js index 8fef947a..70f5c233 100644 --- a/src/javascript/tests/with.spec.js +++ b/src/javascript/tests/with.spec.js @@ -2,6 +2,7 @@ import Core from "../lib/core"; const Patterns = Core.Patterns; const SpecialForms = Core.SpecialForms; const Tuple = Core.Tuple; +const MatchError = Core.Patterns.MatchError; import Enum from "../lib/enum"; @@ -90,5 +91,61 @@ describe('with', () => { expect(value).to.eql(new Tuple(Symbol.for('ok'), 300)); }); -}); + it('with else', () => { + /* + opts = %{width: 10} + + with {:ok, width} <- Map.fetch(opts, :width), + {:ok, height} <- Map.fetch(opts, :height) do + {:ok, width * height} + else + :error -> {:error, :wrong_data} + end + + {:error, :wrong_data} + */ + + let opts = { width: 10 }; + + let value = SpecialForms._with( + [new Tuple(Symbol.for('ok'), $), () => map_fetch(opts, "width")], + [new Tuple(Symbol.for('ok'), $), (width) => map_fetch(opts, "height")], + (width, height) => new Tuple(Symbol.for('ok'), width * height), + Patterns.defmatch( + Patterns.clause([Symbol.for('error')], () => new Tuple(Symbol.for('error'), Symbol.for('wrong_data'))) + ) + ); + + expect(value).to.eql(new Tuple(Symbol.for('error'), Symbol.for('wrong_data'))); + }); + + it('with else that don`t match', () => { + /* + opts = %{width: 10} + + with {:ok, width} <- Map.fetch(opts, :width), + {:ok, height} <- Map.fetch(opts, :height) do + {:ok, width * height} + else + :fail -> {:error, :wrong_data} + end + + {:error, :wrong_data} + */ + + let opts = { width: 10 }; + + let withFunction = SpecialForms._with.bind( + null, + [new Tuple(Symbol.for('ok'), $), () => map_fetch(opts, "width")], + [new Tuple(Symbol.for('ok'), $), (width) => map_fetch(opts, "height")], + (width, height) => new Tuple(Symbol.for('ok'), width * height), + Patterns.defmatch( + Patterns.clause([Symbol.for('fail')], () => new Tuple(Symbol.for('error'), Symbol.for('wrong_data'))) + ) + ); + + expect(withFunction).to.throw(MatchError, 'No match for: Symbol(error)'); + }); +}); diff --git a/test/translator/with_test.exs b/test/translator/with_test.exs index 28a4c8b3..4a1fedb7 100644 --- a/test/translator/with_test.exs +++ b/test/translator/with_test.exs @@ -53,4 +53,33 @@ defmodule ElixirScript.Translator.With.Test do assert_translation(ex_ast, js_code) end + + test "translate with with else" do + ex_ast = quote do + with {:ok, width} <- Map.fetch(opts, :width), + {:ok, height} <- Map.fetch(opts, :height) do + {:ok, width * height} + else + :error -> {:error, :wrong_data} + end + end + + js_code = """ + Elixir.Core.SpecialForms._with([Elixir.Core.Patterns.type(Elixir.Core.Tuple,{ + values: [Symbol.for('ok'), Elixir.Core.Patterns.variable()] + }), function() { + return Elixir$ElixirScript$Map.fetch(opts,Symbol.for('width')); + }],[Elixir.Core.Patterns.type(Elixir.Core.Tuple,{ + values: [Symbol.for('ok'), Elixir.Core.Patterns.variable()] + }), function(width) { + return Elixir$ElixirScript$Map.fetch(opts,Symbol.for('height')); + }],function(width,height) { + return new Elixir.Core.Tuple(Symbol.for('ok'),width * height); + },Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.clause([Symbol.for('error')],function() { + return new Elixir.Core.Tuple(Symbol.for('error'),Symbol.for('wrong_data')); + }))) + """ + + assert_translation(ex_ast, js_code) + end end From a93b2f17c1e22c85308ab0bb99112ce65a3f79de Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Sun, 23 Oct 2016 17:43:17 -0500 Subject: [PATCH 325/860] Now checking to see if module is already loaded when looking for modules --- CHANGELOG.md | 5 +++-- lib/elixir_script/passes/deps_paths.ex | 10 ++++------ lib/elixir_script/passes/load_modules.ex | 2 +- lib/elixir_script/translator/lexical_scope.ex | 2 +- lib/elixir_script/translator/state.ex | 2 +- mix.exs | 2 +- 6 files changed, 11 insertions(+), 12 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 94812162..11b5c4ac 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,9 +6,10 @@ and this project adheres to [Semantic Versioning](http://semver.org/). ## [Unreleased] ### Changed -- Changed CHANGELOG.md to adhere the format from Keep a Changelog +- [Changed CHANGELOG.md to adhere the format from Keep a Changelog](https://github.com/bryanjos/elixirscript/pull/205) +- [`with` now supports `else`](https://github.com/bryanjos/elixirscript/pull/207) - New compiler pipeline -- If in mix project, will crawls deps to find packages that have an `elixir_script` config key with the `input` key set to a path to look in +- In mix projects, will now crawl deps to find packages that have an `elixir_script` config key with the `input` key set to a path to look in. Basically, if a compiler has elixirscript code in it and the above is in the mix config, then it will be used during compilation ## [0.22.0] - 2016-10-16 ### Added diff --git a/lib/elixir_script/passes/deps_paths.ex b/lib/elixir_script/passes/deps_paths.ex index b2430ffb..bdede1cc 100644 --- a/lib/elixir_script/passes/deps_paths.ex +++ b/lib/elixir_script/passes/deps_paths.ex @@ -3,15 +3,14 @@ defmodule ElixirScript.Passes.DepsPaths do def execute(compiler_data, opts) do - data = cond do Map.get(opts, :std_lib, false) -> - [{opts[:app], [compiler_data.path]}] + [{opts[:app], List.wrap(compiler_data.path)}] Code.ensure_loaded?(Mix) -> deps = get_deps_paths(Mix.env) - deps ++ [{opts[:app], [compiler_data.path]}] + deps ++ [{opts[:app], List.wrap(compiler_data.path)}] true -> - [{opts[:app], [compiler_data.path]}] + [{opts[:app], List.wrap(compiler_data.path)}] end Map.put(compiler_data, :data, data) @@ -24,8 +23,7 @@ defmodule ElixirScript.Passes.DepsPaths do defp do_get_deps_paths(deps) do Enum.reduce(deps, [], fn(dep, list) -> - elixirscript_config = Mix.Project.in_project dep.app, dep.opts[:dest], fn _ -> Mix.Project.config()[:elixirscript] end - + elixirscript_config = Mix.Project.in_project dep.app, dep.opts[:dest], fn _ -> Mix.Project.config()[:elixir_script] end case elixirscript_config do nil -> list diff --git a/lib/elixir_script/passes/load_modules.ex b/lib/elixir_script/passes/load_modules.ex index 6f7a99ef..7109e65a 100644 --- a/lib/elixir_script/passes/load_modules.ex +++ b/lib/elixir_script/passes/load_modules.ex @@ -18,7 +18,7 @@ defmodule ElixirScript.Passes.LoadModules do _ -> [] end - end + end Map.put(compiler_data, :loaded_modules, loaded_modules) end diff --git a/lib/elixir_script/translator/lexical_scope.ex b/lib/elixir_script/translator/lexical_scope.ex index f3487d74..65ab075c 100644 --- a/lib/elixir_script/translator/lexical_scope.ex +++ b/lib/elixir_script/translator/lexical_scope.ex @@ -324,7 +324,7 @@ defmodule ElixirScript.Translator.LexicalScope do end defp check_for_module_existence(env, module_name) do - if ElixirScript.Translator.State.is_module_loaded?(module_name) == false and has_module?(env, module_name) == false do + if Code.ensure_loaded?(module_name) == false and ElixirScript.Translator.State.is_module_loaded?(module_name) == false and has_module?(env, module_name) == false do raise "Module #{inspect module_name} not found" end end diff --git a/lib/elixir_script/translator/state.ex b/lib/elixir_script/translator/state.ex index 9aa2ba05..60caf769 100644 --- a/lib/elixir_script/translator/state.ex +++ b/lib/elixir_script/translator/state.ex @@ -89,7 +89,7 @@ defmodule ElixirScript.Translator.State do def is_module_loaded?(module) when is_atom(module) do Agent.get(__MODULE__, fn(state) -> - module in state.loaded_modules + Code.ensure_loaded?(module) or (module in state.loaded_modules) end) end diff --git a/mix.exs b/mix.exs index f833e235..2e5c3493 100644 --- a/mix.exs +++ b/mix.exs @@ -4,7 +4,7 @@ defmodule ElixirScript.Mixfile do def project do [ app: :elixir_script, - version: "0.22.0", + version: "0.23.0-dev", elixir: "~> 1.0", escript: escript_config, deps: deps, From 45aa965d8dce8375fc1d5f8b05a7fba9ff0ecb2e Mon Sep 17 00:00:00 2001 From: Konstantin Lazarev Date: Sun, 30 Oct 2016 00:17:36 +0500 Subject: [PATCH 326/860] Implement context option on quote --- .../translator/kernel/special_forms/quote.ex | 5 +++++ test/translator/quote_test.exs | 17 +++++++++++++++++ 2 files changed, 22 insertions(+) diff --git a/lib/elixir_script/translator/kernel/special_forms/quote.ex b/lib/elixir_script/translator/kernel/special_forms/quote.ex index 80b6b3fd..a02168a8 100644 --- a/lib/elixir_script/translator/kernel/special_forms/quote.ex +++ b/lib/elixir_script/translator/kernel/special_forms/quote.ex @@ -47,6 +47,11 @@ defmodule ElixirScript.Translator.Quote do Primitive.make_tuple_quoted(opts, [:unquote, context, params], env) end + def make_quote([context: {_, _, [new_context]}] = opts, {name, context, params}, env) do + updated_context = Keyword.put(context, :context, new_context) + Primitive.make_tuple_quoted(opts, [name, updated_context, params], env) + end + def make_quote(_, {:alias!, _, [the_alias]}, _) do the_alias end diff --git a/test/translator/quote_test.exs b/test/translator/quote_test.exs index 21ee5107..27f7c33d 100644 --- a/test/translator/quote_test.exs +++ b/test/translator/quote_test.exs @@ -120,4 +120,21 @@ defmodule ElixirScript.Translator.Quote.Test do assert_translation(ex_ast, js_code) end + + test "quote with context option" do + ex_ast = quote do + quote context: Elixir do + test(1) + end + end + + js_code = """ + new Elixir.Core.Tuple( + Symbol.for('test'), + Object.freeze([new Elixir.Core.Tuple(Symbol.for('context'),Symbol.for('Elixir')), new Elixir.Core.Tuple(Symbol.for('import'),Symbol.for('Elixir.ExUnit.Case'))]),Object.freeze([1]) + ) + """ + + assert_translation(ex_ast, js_code) + end end From 1c7e7ec6727f5242efce94c64df1de271949a2d7 Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Sat, 29 Oct 2016 18:40:56 -0500 Subject: [PATCH 327/860] Update Changelog and is_module_loaded? --- CHANGELOG.md | 1 + lib/elixir_script/translator/state.ex | 1 + 2 files changed, 2 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 11b5c4ac..445886f8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/). ### Changed - [Changed CHANGELOG.md to adhere the format from Keep a Changelog](https://github.com/bryanjos/elixirscript/pull/205) - [`with` now supports `else`](https://github.com/bryanjos/elixirscript/pull/207) +- [Implement `context` option on `quote`](https://github.com/bryanjos/elixirscript/pull/208) - New compiler pipeline - In mix projects, will now crawl deps to find packages that have an `elixir_script` config key with the `input` key set to a path to look in. Basically, if a compiler has elixirscript code in it and the above is in the mix config, then it will be used during compilation diff --git a/lib/elixir_script/translator/state.ex b/lib/elixir_script/translator/state.ex index 60caf769..d54024b4 100644 --- a/lib/elixir_script/translator/state.ex +++ b/lib/elixir_script/translator/state.ex @@ -88,6 +88,7 @@ defmodule ElixirScript.Translator.State do end def is_module_loaded?(module) when is_atom(module) do + module = get_module_name(module) Agent.get(__MODULE__, fn(state) -> Code.ensure_loaded?(module) or (module in state.loaded_modules) end) From bb8d70c06fc7b4548ee6e2b2fc59b73a690cbc82 Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Sat, 29 Oct 2016 18:48:35 -0500 Subject: [PATCH 328/860] returning false when Kernel is used in is_module_loaded? --- lib/elixir_script.ex | 2 +- lib/elixir_script/translator/state.ex | 5 ++++- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/lib/elixir_script.ex b/lib/elixir_script.ex index e1fa5e49..302e42bb 100644 --- a/lib/elixir_script.ex +++ b/lib/elixir_script.ex @@ -179,7 +179,7 @@ defmodule ElixirScript do default_options = Map.new |> Map.put(:include_path, false) |> Map.put(:root, nil) - |> Map.put(:env, custom_env) + |> Map.put(:env, custom_env()) |> Map.put(:import_standard_libs, true) |> Map.put(:core_path, "Elixir") |> Map.put(:full_build, false) diff --git a/lib/elixir_script/translator/state.ex b/lib/elixir_script/translator/state.ex index d54024b4..9aa351ff 100644 --- a/lib/elixir_script/translator/state.ex +++ b/lib/elixir_script/translator/state.ex @@ -87,8 +87,11 @@ defmodule ElixirScript.Translator.State do end end + def is_module_loaded?(Kernel) do + false + end + def is_module_loaded?(module) when is_atom(module) do - module = get_module_name(module) Agent.get(__MODULE__, fn(state) -> Code.ensure_loaded?(module) or (module in state.loaded_modules) end) From 3890ad5c26a8aa8280453b44dc4df3c15a39d921 Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Mon, 7 Nov 2016 18:01:41 -0600 Subject: [PATCH 329/860] Removing dep crawling --- CHANGELOG.md | 1 - lib/elixir_script/passes/deps_paths.ex | 34 +------------------ lib/elixir_script/translator/lexical_scope.ex | 2 +- lib/elixir_script/translator/state.ex | 6 +--- 4 files changed, 3 insertions(+), 40 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 445886f8..0fa97c4c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,7 +10,6 @@ and this project adheres to [Semantic Versioning](http://semver.org/). - [`with` now supports `else`](https://github.com/bryanjos/elixirscript/pull/207) - [Implement `context` option on `quote`](https://github.com/bryanjos/elixirscript/pull/208) - New compiler pipeline -- In mix projects, will now crawl deps to find packages that have an `elixir_script` config key with the `input` key set to a path to look in. Basically, if a compiler has elixirscript code in it and the above is in the mix config, then it will be used during compilation ## [0.22.0] - 2016-10-16 ### Added diff --git a/lib/elixir_script/passes/deps_paths.ex b/lib/elixir_script/passes/deps_paths.ex index bdede1cc..bd54bba2 100644 --- a/lib/elixir_script/passes/deps_paths.ex +++ b/lib/elixir_script/passes/deps_paths.ex @@ -1,41 +1,9 @@ defmodule ElixirScript.Passes.DepsPaths do @pass 1 - def execute(compiler_data, opts) do - data = cond do - Map.get(opts, :std_lib, false) -> - [{opts[:app], List.wrap(compiler_data.path)}] - Code.ensure_loaded?(Mix) -> - deps = get_deps_paths(Mix.env) - deps ++ [{opts[:app], List.wrap(compiler_data.path)}] - true -> - [{opts[:app], List.wrap(compiler_data.path)}] - end - + data = [{opts[:app], List.wrap(compiler_data.path)}] Map.put(compiler_data, :data, data) end - defp get_deps_paths(env) do - Mix.Dep.loaded([env: env]) - |> do_get_deps_paths - end - - defp do_get_deps_paths(deps) do - Enum.reduce(deps, [], fn(dep, list) -> - elixirscript_config = Mix.Project.in_project dep.app, dep.opts[:dest], fn _ -> Mix.Project.config()[:elixir_script] end - case elixirscript_config do - nil -> - list - - config -> - paths = Keyword.get(config, :input, "") |> List.wrap - paths = Enum.map(paths, fn path -> Path.join([dep.opts[:dest], path]) end) - deps = do_get_deps_paths(dep.deps) - deps ++ [{dep.app, paths}] ++ list - end - end) - |> Enum.uniq - end - end diff --git a/lib/elixir_script/translator/lexical_scope.ex b/lib/elixir_script/translator/lexical_scope.ex index 65ab075c..f3487d74 100644 --- a/lib/elixir_script/translator/lexical_scope.ex +++ b/lib/elixir_script/translator/lexical_scope.ex @@ -324,7 +324,7 @@ defmodule ElixirScript.Translator.LexicalScope do end defp check_for_module_existence(env, module_name) do - if Code.ensure_loaded?(module_name) == false and ElixirScript.Translator.State.is_module_loaded?(module_name) == false and has_module?(env, module_name) == false do + if ElixirScript.Translator.State.is_module_loaded?(module_name) == false and has_module?(env, module_name) == false do raise "Module #{inspect module_name} not found" end end diff --git a/lib/elixir_script/translator/state.ex b/lib/elixir_script/translator/state.ex index 9aa351ff..342e1f60 100644 --- a/lib/elixir_script/translator/state.ex +++ b/lib/elixir_script/translator/state.ex @@ -87,13 +87,9 @@ defmodule ElixirScript.Translator.State do end end - def is_module_loaded?(Kernel) do - false - end - def is_module_loaded?(module) when is_atom(module) do Agent.get(__MODULE__, fn(state) -> - Code.ensure_loaded?(module) or (module in state.loaded_modules) + (module in state.loaded_modules) end) end From 3664fa234c8312cbc1c29a5b1f75fca16a404344 Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Mon, 7 Nov 2016 18:42:59 -0600 Subject: [PATCH 330/860] Update to load in current module's macros --- lib/elixir_script/passes/java_script_ast.ex | 10 ++++++++++ lib/elixir_script/translator/lexical_scope.ex | 11 ++++++++++- lib/elixir_script/translator/state.ex | 6 ++++++ 3 files changed, 26 insertions(+), 1 deletion(-) diff --git a/lib/elixir_script/passes/java_script_ast.ex b/lib/elixir_script/passes/java_script_ast.ex index 857156f9..9f192a03 100644 --- a/lib/elixir_script/passes/java_script_ast.ex +++ b/lib/elixir_script/passes/java_script_ast.ex @@ -30,6 +30,16 @@ defmodule ElixirScript.Passes.JavaScriptAST do defp compile(module_data, opts) do + loaded_modules = case Map.get(module_data, :path) do + nil -> + [] + files -> + Kernel.ParallelRequire.files(List.wrap(files)) + end + + State.add_loaded_modules(loaded_modules) + + env = ElixirScript.Translator.LexicalScope.module_scope(module_data.name, Utils.name_to_js_file_name(module_data.name) <> ".js", opts.env) module = case module_data.type do diff --git a/lib/elixir_script/translator/lexical_scope.ex b/lib/elixir_script/translator/lexical_scope.ex index f3487d74..22e856d7 100644 --- a/lib/elixir_script/translator/lexical_scope.ex +++ b/lib/elixir_script/translator/lexical_scope.ex @@ -97,7 +97,16 @@ defmodule ElixirScript.Translator.LexicalScope do env: env } - add_import(env, ElixirScript.Kernel) + env = add_import(env, ElixirScript.Kernel) + + cond do + module_name == ElixirScript.JS -> + env + ElixirScript.Translator.State.is_module_loaded?(module_name) -> + add_import(env, module_name, [only: :macros]) + true -> + env + end end def function_scope(env, { _, _ } = func) do diff --git a/lib/elixir_script/translator/state.ex b/lib/elixir_script/translator/state.ex index 342e1f60..d8738f0c 100644 --- a/lib/elixir_script/translator/state.ex +++ b/lib/elixir_script/translator/state.ex @@ -150,6 +150,12 @@ defmodule ElixirScript.Translator.State do end) end + def add_loaded_modules(modules) do + Agent.update(__MODULE__, fn(state) -> + %{ state | loaded_modules: state.loaded_modules ++ List.wrap(modules) } + end) + end + def stop do Agent.stop(__MODULE__) end From a3a0deaa2e69d75359e297c015c01a7679dec251 Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Wed, 9 Nov 2016 09:56:35 -0600 Subject: [PATCH 331/860] Fixed issues with consolidating protocols --- lib/elixir_script.ex | 2 +- lib/elixir_script/module_systems/common.ex | 5 ---- lib/elixir_script/module_systems/es6.ex | 11 -------- .../passes/consolidate_protocols.ex | 15 ++++++++--- lib/elixir_script/passes/deps_paths.ex | 1 - .../passes/find_changed_files.ex | 1 - lib/elixir_script/passes/find_deps.ex | 1 - lib/elixir_script/passes/find_functions.ex | 15 +++++++---- lib/elixir_script/passes/find_modules.ex | 16 ++++++----- lib/elixir_script/passes/handle_output.ex | 5 ---- lib/elixir_script/passes/java_script_ast.ex | 11 +------- lib/elixir_script/passes/java_script_code.ex | 1 - lib/elixir_script/passes/java_script_name.ex | 1 - lib/elixir_script/passes/load_modules.ex | 18 +++++-------- lib/elixir_script/passes/remove_unused.ex | 1 - lib/elixir_script/passes/write_cache.ex | 4 ++- lib/elixir_script/prelude/js.ex | 27 +++++-------------- lib/elixir_script/translator/kernel/js.ex | 4 --- lib/elixir_script/translator/lexical_scope.ex | 4 ++- lib/elixir_script/translator/state.ex | 16 +++++------ test/elixir_script_test.exs | 8 ------ 21 files changed, 58 insertions(+), 109 deletions(-) diff --git a/lib/elixir_script.ex b/lib/elixir_script.ex index 302e42bb..48969fa3 100644 --- a/lib/elixir_script.ex +++ b/lib/elixir_script.ex @@ -35,7 +35,6 @@ defmodule ElixirScript do quote do import Kernel, only: [&&: 2, use: 2, use: 1] import ElixirScript.Kernel - require ElixirScript.JS, as: JS end end @@ -127,6 +126,7 @@ defmodule ElixirScript do |> ElixirScript.Passes.FindModules.execute(opts) |> ElixirScript.Passes.FindChangedFiles.execute(opts) |> ElixirScript.Passes.FindFunctions.execute(opts) + |> ElixirScript.Passes.AddStdLib.execute(opts) |> ElixirScript.Passes.JavaScriptAST.execute(opts) |> ElixirScript.Passes.ConsolidateProtocols.execute(opts) |> ElixirScript.Passes.JavaScriptCode.execute(opts) diff --git a/lib/elixir_script/module_systems/common.ex b/lib/elixir_script/module_systems/common.ex index 6d227420..b278c990 100644 --- a/lib/elixir_script/module_systems/common.ex +++ b/lib/elixir_script/module_systems/common.ex @@ -14,11 +14,6 @@ defmodule ElixirScript.ModuleSystems.Common do do_import_module(Translator.translate!(module_name, env), from) end - def import_module(module_name, %ElixirScript.Translator.LexicalScope{} = env) do - {from, _ } = Code.eval_quoted(module_name) - do_import_module(Translator.translate!(module_name, env), Macro.underscore(from)) - end - def import_module(import_name, from) do do_import_module(JS.identifier(import_name), from) end diff --git a/lib/elixir_script/module_systems/es6.ex b/lib/elixir_script/module_systems/es6.ex index 606ae302..3fc0b525 100644 --- a/lib/elixir_script/module_systems/es6.ex +++ b/lib/elixir_script/module_systems/es6.ex @@ -22,17 +22,6 @@ defmodule ElixirScript.ModuleSystems.ES6 do do_import_module([import_specifier], from) end - def import_module(module_name, %ElixirScript.Translator.LexicalScope{} = env) do - import_specifier = JS.import_default_specifier( - Translator.translate!(module_name, env), - Translator.translate!(module_name, env) - ) - - {from, _ } = Code.eval_quoted(module_name) - - do_import_module([import_specifier], Macro.underscore(from)) - end - def import_module(import_name, from) do import_specifier = JS.import_default_specifier( JS.identifier(import_name) diff --git a/lib/elixir_script/passes/consolidate_protocols.ex b/lib/elixir_script/passes/consolidate_protocols.ex index 2035cf1d..8691410e 100644 --- a/lib/elixir_script/passes/consolidate_protocols.ex +++ b/lib/elixir_script/passes/consolidate_protocols.ex @@ -1,14 +1,19 @@ defmodule ElixirScript.Passes.ConsolidateProtocols do - @pass 8 alias ESTree.Tools.Builder, as: JS alias ElixirScript.Translator.Utils alias ElixirScript.ModuleSystems + alias ElixirScript.Translator.State require Logger def execute(compiler_data, opts) do - only_protocols_and_impls = Enum.filter(compiler_data.data, fn + State.set_module_data(compiler_data.data) + data = State.get_module_data() + + only_protocols_and_impls = Enum.filter(data, fn ({_, %{type: :module}}) -> false + ({_, %{type: :consolidated}}) -> + false _ -> true end) @@ -16,7 +21,9 @@ defmodule ElixirScript.Passes.ConsolidateProtocols do grouped = group_protocol_data(only_protocols_and_impls) consolidated_protocols = update_protocols(grouped, opts) - %{ compiler_data | data: compiler_data.data ++ consolidated_protocols } + data = Enum.reduce(consolidated_protocols, data, fn({ key, value }, d) -> Keyword.put(d, key, value) end) + + %{ compiler_data | data: data } end @@ -42,7 +49,7 @@ defmodule ElixirScript.Passes.ConsolidateProtocols do make_defimpl(protocol_name, protocol, Enum.uniq(impls), opts) ({ protocol_name, %{ protocol: protocol } }) -> - make_defimpl(protocol_name, protocol, [], opts) + make_defimpl(protocol_name, protocol, [], opts) end) end diff --git a/lib/elixir_script/passes/deps_paths.ex b/lib/elixir_script/passes/deps_paths.ex index bd54bba2..a49640bb 100644 --- a/lib/elixir_script/passes/deps_paths.ex +++ b/lib/elixir_script/passes/deps_paths.ex @@ -1,5 +1,4 @@ defmodule ElixirScript.Passes.DepsPaths do - @pass 1 def execute(compiler_data, opts) do data = [{opts[:app], List.wrap(compiler_data.path)}] diff --git a/lib/elixir_script/passes/find_changed_files.ex b/lib/elixir_script/passes/find_changed_files.ex index 44b52b7c..74eb960b 100644 --- a/lib/elixir_script/passes/find_changed_files.ex +++ b/lib/elixir_script/passes/find_changed_files.ex @@ -1,5 +1,4 @@ defmodule ElixirScript.Passes.FindChangedFiles do - @pass 2 alias ElixirScript.Compiler.Cache alias ElixirScript.Translator.State diff --git a/lib/elixir_script/passes/find_deps.ex b/lib/elixir_script/passes/find_deps.ex index 16bc9b35..288e244e 100644 --- a/lib/elixir_script/passes/find_deps.ex +++ b/lib/elixir_script/passes/find_deps.ex @@ -1,5 +1,4 @@ defmodule ElixirScript.Passes.FindDeps do - @pass 3 alias ElixirScript.Translator.Utils diff --git a/lib/elixir_script/passes/find_functions.ex b/lib/elixir_script/passes/find_functions.ex index 72e55dd2..0d4cddaf 100644 --- a/lib/elixir_script/passes/find_functions.ex +++ b/lib/elixir_script/passes/find_functions.ex @@ -1,14 +1,15 @@ defmodule ElixirScript.Passes.FindFunctions do - @pass 6 - @function_types [:def, :defp, :defgen, :defgenp] + @function_types [:def, :defp, :defgen, :defgenp, :defmacro, :defmacrop] def execute(data, _) do new_data = Enum.map(data.data, fn { module_name, module_data } -> - %{def: functions, defp: private_functions, defgen: generators, defgenp: private_generators } = get_functions_from_module(module_data.ast) + %{def: functions, defp: private_functions, defgen: generators, defgenp: private_generators, defmacro: macros, defmacrop: private_macros } = get_functions_from_module(module_data.ast) module_data = Map.put(module_data, :functions, functions ++ generators) |> Map.put(:private_functions, private_functions ++ private_generators) + |> Map.put(:macros, macros) + |> Map.put(:private_macros, private_macros) {module_name, module_data} end) @@ -17,7 +18,7 @@ defmodule ElixirScript.Passes.FindFunctions do end defp get_functions_from_module({:__block__, _, list}) do - Enum.reduce(list, %{ def: Keyword.new, defp: Keyword.new, defgen: Keyword.new, defgenp: Keyword.new }, fn + Enum.reduce(list, new_function_map(), fn ({type, _, [{:when, _, [{name, _, params} | _guards] }, _] }, state) when type in @function_types and is_atom(params) -> arity = 0 @@ -51,8 +52,12 @@ defmodule ElixirScript.Passes.FindFunctions do end) end + defp new_function_map() do + %{ def: Keyword.new, defp: Keyword.new, defgen: Keyword.new, defgenp: Keyword.new, defmacro: Keyword.new, defmacrop: Keyword.new } + end + defp get_functions_from_module(_) do - %{ def: Keyword.new, defp: Keyword.new, defgen: Keyword.new, defgenp: Keyword.new } + new_function_map() end defp add_function_to_map(map, type, name, arity) do diff --git a/lib/elixir_script/passes/find_modules.ex b/lib/elixir_script/passes/find_modules.ex index e64e16f1..6eaedb65 100644 --- a/lib/elixir_script/passes/find_modules.ex +++ b/lib/elixir_script/passes/find_modules.ex @@ -1,7 +1,7 @@ defmodule ElixirScript.Passes.FindModules do - @pass 2 alias ElixirScript.Translator.Utils + alias ElixirScript.Translator.State def execute(compiler_data, opts) do data = Enum.reduce(compiler_data.data, [], fn(data, list) -> @@ -25,15 +25,17 @@ defmodule ElixirScript.Passes.FindModules do { ast, state ++ [s] } end - defp get_defmodules({:defimpl, _, [ {:__aliases__, _, name} = the_alias, [for: {:__aliases__, _, type_name} = type], [do: {:__block__, context, spec}] ]} = ast, state, _) do - name = name ++ [DefImpl] ++ type_name - s = %{name: Utils.quoted_to_name({:__aliases__, [], name}), type: :impl, for: type, ast: {:__block__, context, spec}, implements: Utils.quoted_to_name(the_alias) } + defp get_defmodules({:defimpl, _, [ the_alias, [for: {:__aliases__, _, type_name} = type], [do: {:__block__, context, spec}] ]} = ast, state, _) do + {:__aliases__, _, original_name} = Utils.name_to_quoted(State.get_module_name(the_alias)) + name = original_name ++ [DefImpl] ++ type_name + s = %{name: Utils.quoted_to_name({:__aliases__, [], name}), type: :impl, for: type, ast: {:__block__, context, spec}, implements: Utils.quoted_to_name({:__aliases__, [], original_name}) } { ast, state ++ [s] } end - defp get_defmodules({:defimpl, _, [ {:__aliases__, _, name} = the_alias, [for: {:__aliases__, _, type_name} = type], [do: spec] ]} = ast, state, _) do - name = name ++ [DefImpl] ++ type_name - s = %{name: Utils.quoted_to_name({:__aliases__, [], name}), type: :impl, for: type, ast: {:__block__, [], [spec]}, implements: Utils.quoted_to_name(the_alias) } + defp get_defmodules({:defimpl, _, [ the_alias, [for: {:__aliases__, _, type_name} = type], [do: spec] ]} = ast, state, _) do + {:__aliases__, _, original_name} = Utils.name_to_quoted(State.get_module_name(the_alias)) + name = original_name ++ [DefImpl] ++ type_name + s = %{name: Utils.quoted_to_name({:__aliases__, [], name}), type: :impl, for: type, ast: {:__block__, [], [spec]}, implements: Utils.quoted_to_name({:__aliases__, [], original_name}) } { ast, state ++ [s] } end diff --git a/lib/elixir_script/passes/handle_output.ex b/lib/elixir_script/passes/handle_output.ex index 8e38b8d9..be2b3f56 100644 --- a/lib/elixir_script/passes/handle_output.ex +++ b/lib/elixir_script/passes/handle_output.ex @@ -1,5 +1,4 @@ defmodule ElixirScript.Passes.HandleOutput do - @pass 11 alias ElixirScript.Translator.State def execute(compiler_data, opts) do @@ -32,10 +31,6 @@ defmodule ElixirScript.Passes.HandleOutput do Enum.each(compiler_output.data, fn({_, x}) -> write_to_file(x, output_path) end) - - if Map.get(compiler_opts, :std_lib, false) == false do - ElixirScript.copy_stdlib_to_destination(output_path) - end end defp write_to_file(module_data, destination) do diff --git a/lib/elixir_script/passes/java_script_ast.ex b/lib/elixir_script/passes/java_script_ast.ex index 9f192a03..ecab5890 100644 --- a/lib/elixir_script/passes/java_script_ast.ex +++ b/lib/elixir_script/passes/java_script_ast.ex @@ -1,9 +1,9 @@ defmodule ElixirScript.Passes.JavaScriptAST do - @pass 7 alias ElixirScript.Translator.Utils alias ElixirScript.Translator.State def execute(compiler_data, opts) do + State.set_module_data(compiler_data.data) parent = self @@ -30,15 +30,6 @@ defmodule ElixirScript.Passes.JavaScriptAST do defp compile(module_data, opts) do - loaded_modules = case Map.get(module_data, :path) do - nil -> - [] - files -> - Kernel.ParallelRequire.files(List.wrap(files)) - end - - State.add_loaded_modules(loaded_modules) - env = ElixirScript.Translator.LexicalScope.module_scope(module_data.name, Utils.name_to_js_file_name(module_data.name) <> ".js", opts.env) diff --git a/lib/elixir_script/passes/java_script_code.ex b/lib/elixir_script/passes/java_script_code.ex index bc995381..47c350bd 100644 --- a/lib/elixir_script/passes/java_script_code.ex +++ b/lib/elixir_script/passes/java_script_code.ex @@ -1,5 +1,4 @@ defmodule ElixirScript.Passes.JavaScriptCode do - @pass 9 alias ESTree.Tools.{ Builder, Generator } def execute(compiler_data, _) do diff --git a/lib/elixir_script/passes/java_script_name.ex b/lib/elixir_script/passes/java_script_name.ex index 5c707b7c..21f2df08 100644 --- a/lib/elixir_script/passes/java_script_name.ex +++ b/lib/elixir_script/passes/java_script_name.ex @@ -1,5 +1,4 @@ defmodule ElixirScript.Passes.JavaScriptName do - @pass 10 alias ElixirScript.Translator.Utils def execute(compiler_data, _) do diff --git a/lib/elixir_script/passes/load_modules.ex b/lib/elixir_script/passes/load_modules.ex index 7109e65a..7ed10641 100644 --- a/lib/elixir_script/passes/load_modules.ex +++ b/lib/elixir_script/passes/load_modules.ex @@ -1,23 +1,17 @@ defmodule ElixirScript.Passes.LoadModules do - @pass 5 def execute(compiler_data, _) do + ex_files = Enum.map(compiler_data.data, fn { _, %{path: path} } -> path %{path: path} -> path end) - |> Enum.filter(fn path -> Path.extname(path) == ".ex" || Path.extname(path) == ".exs" end) - loaded_modules = case ex_files do - [] -> - [] - files -> - try do - Kernel.ParallelRequire.files(files) - rescue - _ -> - [] - end + loaded_modules = case Enum.reverse(ex_files) do + [] -> + [] + files -> + Kernel.ParallelCompiler.files(files) end Map.put(compiler_data, :loaded_modules, loaded_modules) diff --git a/lib/elixir_script/passes/remove_unused.ex b/lib/elixir_script/passes/remove_unused.ex index 5b83426c..633cbc97 100644 --- a/lib/elixir_script/passes/remove_unused.ex +++ b/lib/elixir_script/passes/remove_unused.ex @@ -1,5 +1,4 @@ defmodule ElixirScript.Passes.RemoveUnused do - @pass 4 def execute(compiler_data, opts) do data = Enum.filter(compiler_data.data, fn({module_name, _}) -> diff --git a/lib/elixir_script/passes/write_cache.ex b/lib/elixir_script/passes/write_cache.ex index 79cea1e1..a624e629 100644 --- a/lib/elixir_script/passes/write_cache.ex +++ b/lib/elixir_script/passes/write_cache.ex @@ -7,7 +7,9 @@ defmodule ElixirScript.Passes.WriteCache do State.set_module_data(compiler_data.data) new_state = State.serialize() - new_file_stats = Enum.map(compiler_data.data, fn({_, data}) -> { data.path, data.stat } end) |> Enum.uniq + new_file_stats = Enum.filter(compiler_data.data, fn({ _, data }) -> Map.has_key?(data, :path) end) + |> Enum.map(fn({_, data}) -> { data.path, data.stat } end) + |> Enum.uniq compiler_cache = %{compiler_cache | input_files: new_file_stats, state: new_state } diff --git a/lib/elixir_script/prelude/js.ex b/lib/elixir_script/prelude/js.ex index ec047e8d..f23119da 100644 --- a/lib/elixir_script/prelude/js.ex +++ b/lib/elixir_script/prelude/js.ex @@ -1,4 +1,4 @@ -defmodule ElixirScript.JS do +defmodule JS do @moduledoc """ This module defines macros and functions which implement JavaScript functionality that may not translate easily to @@ -12,7 +12,7 @@ defmodule ElixirScript.JS do ex: JS.new User, ["first_name", "last_name"] """ - defmacro new(module, params) do + def new(module, params) do end @@ -22,7 +22,7 @@ defmodule ElixirScript.JS do ex: JS.update elem, %{"width" => 100} """ - defmacro update(object, map) do + def update(object, map) do end @@ -41,38 +41,25 @@ defmodule ElixirScript.JS do JS.import [A, B, C], "a" #translates to "import {A, B, C} from 'a'" """ - defmacro import(module, from) do - end - - - @doc """ - Imports a JavaScript module. - - Works like import/2, but tries to infer the path to the module. - Only works for default imports. Uses `Macro.underscore` to infer path. - - ex: - JS.import React #translates to "import React from 'react'" - """ - defmacro import(module) do + def import(module, from) do end @doc """ Returns the type of the given value """ - defmacro typeof(value) do + def typeof(value) do end @doc """ Determines if value is an instance of type. """ - defmacro instanceof(value, type) do + def instanceof(value, type) do end @doc """ Throws the term given """ - defmacro throw(term) do + def throw(term) do end diff --git a/lib/elixir_script/translator/kernel/js.ex b/lib/elixir_script/translator/kernel/js.ex index 4bae2857..e83a3497 100644 --- a/lib/elixir_script/translator/kernel/js.ex +++ b/lib/elixir_script/translator/kernel/js.ex @@ -88,8 +88,4 @@ defmodule ElixirScript.Translator.JS do ModuleSystems.import_module(module_name, from, env) end - defp do_translate({:import, _, [module_name]}, env) do - ModuleSystems.import_module(module_name, env) - end - end diff --git a/lib/elixir_script/translator/lexical_scope.ex b/lib/elixir_script/translator/lexical_scope.ex index 22e856d7..a2fe688c 100644 --- a/lib/elixir_script/translator/lexical_scope.ex +++ b/lib/elixir_script/translator/lexical_scope.ex @@ -82,6 +82,7 @@ defmodule ElixirScript.Translator.LexicalScope do env = %ElixirScript.Translator.LexicalScope { module: ElixirScript.Temp, file: filename, requires: [], functions: [], + macros: [], env: env } @@ -94,6 +95,7 @@ defmodule ElixirScript.Translator.LexicalScope do env = %ElixirScript.Translator.LexicalScope { module: module_name, file: filename, requires: [], functions: [{ module.name, module.functions}], + macros: [{module.name, module.macros}], env: env } @@ -102,7 +104,7 @@ defmodule ElixirScript.Translator.LexicalScope do cond do module_name == ElixirScript.JS -> env - ElixirScript.Translator.State.is_module_loaded?(module_name) -> + ElixirScript.Translator.State.is_module_loaded?(module_name) and length(module.macros) > 0 -> add_import(env, module_name, [only: :macros]) true -> env diff --git a/lib/elixir_script/translator/state.ex b/lib/elixir_script/translator/state.ex index d8738f0c..9c881fd3 100644 --- a/lib/elixir_script/translator/state.ex +++ b/lib/elixir_script/translator/state.ex @@ -51,18 +51,22 @@ defmodule ElixirScript.Translator.State do |> Map.put(Bitwise, ElixirScript.Bitwise) |> Map.put(MapSet, ElixirScript.MapSet) |> Map.put(List, ElixirScript.List) - |> Map.put(JS, ElixirScript.JS) |> Map.put(Process, ElixirScript.Process) end def set_module_data(module_data) do Agent.update(__MODULE__, fn state -> - keys = Map.values(state.std_lib_map) - data = Keyword.take(state.modules, keys) + data = Enum.filter(state.modules, fn {module_name, data} -> data.app == :elixir end) %{ state | modules: Keyword.merge(data, module_data) } end) end + def get_module_data() do + Agent.get(__MODULE__, fn state -> + state.modules + end) + end + def get do Agent.get(__MODULE__, &(&1)) end @@ -150,12 +154,6 @@ defmodule ElixirScript.Translator.State do end) end - def add_loaded_modules(modules) do - Agent.update(__MODULE__, fn(state) -> - %{ state | loaded_modules: state.loaded_modules ++ List.wrap(modules) } - end) - end - def stop do Agent.stop(__MODULE__) end diff --git a/test/elixir_script_test.exs b/test/elixir_script_test.exs index d8f6fada..60b23d60 100644 --- a/test/elixir_script_test.exs +++ b/test/elixir_script_test.exs @@ -10,14 +10,6 @@ defmodule ElixirScript.Test do assert Enum.join(js_code, "\n") =~ "JQuery('
').text(html)" end - test "JS.import/1" do - js_code = ElixirScript.compile(""" - JS.import React - """) - - assert Enum.join(js_code, "\n") =~ "import React from 'react'" - end - test "turn javascript ast into javascript code strings" do js_code = ElixirScript.compile(":atom") assert Enum.join(js_code, "\n") =~ "Symbol.for('atom')" From 135949870b070d5cd17cb261a6ed1eddd74ab9dc Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Thu, 10 Nov 2016 20:34:39 -0600 Subject: [PATCH 332/860] Updates to changelog --- CHANGELOG.md | 25 ++++++- lib/elixir_script.ex | 11 ++- lib/elixir_script/passes/handle_output.ex | 19 ++++-- lib/elixir_script/passes/java_script_ast.ex | 1 + lib/elixir_script/prelude/js.ex | 36 ++++++++++ lib/elixir_script/prelude/kernel.ex | 67 +++---------------- lib/elixir_script/translator.ex | 4 ++ lib/elixir_script/translator/lexical_scope.ex | 2 +- lib/elixir_script/translator/state.ex | 6 ++ 9 files changed, 103 insertions(+), 68 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 0fa97c4c..b78ab750 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,11 +5,32 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/) and this project adheres to [Semantic Versioning](http://semver.org/). ## [Unreleased] -### Changed -- [Changed CHANGELOG.md to adhere the format from Keep a Changelog](https://github.com/bryanjos/elixirscript/pull/205) + +### Added - [`with` now supports `else`](https://github.com/bryanjos/elixirscript/pull/207) - [Implement `context` option on `quote`](https://github.com/bryanjos/elixirscript/pull/208) - New compiler pipeline +- `@on_js_load`. Expects a 0 arity function. This function will be called when the compiled module is loaded in JavaScript + +### Changed +- [Changed CHANGELOG.md to adhere the format from Keep a Changelog](https://github.com/bryanjos/elixirscript/pull/205) +- `defmacro` now supported. No longer have to separate macros from functions in separate files. `defmacrop` still unsupported +- Elixirscript files must now be valid Elixir syntax. Syntax once supported by Elixirscript `JQuery.("#element")`, is no longer supported +- Now compiles `exjs` and `ex` files within the path can be compiled all the same. Dependencies from hex are still unsupported so these files must not rely on any code outside of the path. What this does mean is that it is now possible to share code between Elixir and Elixirscript as long as the Elixir files functionality fall within what Elixirscript currently supports. +- `defgen`, `defgenp`, `yield`, `yield_to`, and `object` now require a `use ElixirScript` expression before use. +- To access functions in the global JavaScript scope, either use `JS.global\0` or use the erlang module call syntax + ```elixir + #calling alert + JS.global().alert("hi") + + #calling alert + :window.alert("hi") + ``` + Calling JavaScript modules in the global scope works without using the above methods + ```elixir + #calls window.Date.now() + Date.now() + ``` ## [0.22.0] - 2016-10-16 ### Added diff --git a/lib/elixir_script.ex b/lib/elixir_script.ex index 48969fa3..1eb4dd1c 100644 --- a/lib/elixir_script.ex +++ b/lib/elixir_script.ex @@ -33,8 +33,17 @@ defmodule ElixirScript do defmacro __using__(_) do quote do - import Kernel, only: [&&: 2, use: 2, use: 1] + import Kernel, except: [ + if: 2, unless: 2, abs: 1, apply: 2, apply: 3, binary_part: 3, hd: 1, + tl: 1, is_atom: 1, is_binary: 1, is_bitstring: 1, is_boolean: 1, is_float: 1, + is_function: 1, is_function: 2, is_integer: 1, is_list: 1, is_number: 1, + is_pid: 1, is_tuple: 1, is_map: 1, is_port: 1, is_reference: 1, length: 1, + map_size: 1, max: 2, min: 2, round: 1, trunc: 1, tuple_size: 1, elem: 2, is_nil: 1, + make_ref: 1, spawn: 1, spawn: 3, spawn_link: 1, spawn_link: 3, spawn_monitor: 1, + spawn_monitor: 3, send: 2, self: 0, match?: 2, to_string: 1, "|>": 2, in: 2, "..": 2 + ] import ElixirScript.Kernel + import JS, only: [defgen: 1, defgen: 2, is_generator: 1, yield: 0, yield: 1, yield_to: 1, object: 1] end end diff --git a/lib/elixir_script/passes/handle_output.ex b/lib/elixir_script/passes/handle_output.ex index be2b3f56..979b72f4 100644 --- a/lib/elixir_script/passes/handle_output.ex +++ b/lib/elixir_script/passes/handle_output.ex @@ -2,15 +2,16 @@ defmodule ElixirScript.Passes.HandleOutput do alias ElixirScript.Translator.State def execute(compiler_data, opts) do + if Map.get(opts, :std_lib, false) do State.set_module_data(compiler_data.data) new_std_state = State.serialize() stdlib_state_path = Path.join([File.cwd!(), "lib", "elixir_script", "translator", "stdlib_state.bin"]) File.write!(stdlib_state_path, new_std_state) + State.stop() + else + out(compiler_data, opts) end - - State.stop() - out(compiler_data, opts) end defp out(compiler_output, %{output: nil} = compiler_opts) do @@ -28,7 +29,13 @@ defmodule ElixirScript.Passes.HandleOutput do end defp out(compiler_output, %{output: output_path, core_path: _} = compiler_opts) do - Enum.each(compiler_output.data, fn({_, x}) -> + if Map.get(compiler_opts, :std_lib, false) == false do + ElixirScript.copy_stdlib_to_destination(output_path) + end + + compiler_output.data + |> Enum.reject(fn({m, d}) -> Map.get(compiler_opts, :import_standard_libs, true) == false && d.app == :elixir end) + |> Enum.each(fn({_, x}) -> write_to_file(x, output_path) end) end @@ -44,7 +51,9 @@ defmodule ElixirScript.Passes.HandleOutput do end defp process_include_path(compiler_output, compiler_opts) do - Enum.map(compiler_output.data, fn + compiler_output.data + |> Enum.reject(fn({m, d}) -> Map.get(compiler_opts, :import_standard_libs, true) == false && d.app == :elixir end) + |> Enum.map(fn {_, module_data} -> case compiler_opts.include_path do true -> diff --git a/lib/elixir_script/passes/java_script_ast.ex b/lib/elixir_script/passes/java_script_ast.ex index ecab5890..ccb16012 100644 --- a/lib/elixir_script/passes/java_script_ast.ex +++ b/lib/elixir_script/passes/java_script_ast.ex @@ -5,6 +5,7 @@ defmodule ElixirScript.Passes.JavaScriptAST do def execute(compiler_data, opts) do State.set_module_data(compiler_data.data) + State.set_loaded_modules(Map.get(compiler_data, :loaded_modules, [])) parent = self diff --git a/lib/elixir_script/prelude/js.ex b/lib/elixir_script/prelude/js.ex index f23119da..72cb66f6 100644 --- a/lib/elixir_script/prelude/js.ex +++ b/lib/elixir_script/prelude/js.ex @@ -73,4 +73,40 @@ defmodule JS do Elixir.Core.Functions.get_global() end + defmacro defgen(call, expr \\ nil) do + end + + defmacro defgenp(call, expr \\ nil) do + end + + def is_generator(term) do + term.constructor.name === "GeneratorFunction" + end + + def yield() do + end + + def yield(term) do + end + + def yield_to(term) do + end + + @doc """ + Provides a convenient way to create a string-based map. + + Elixirscript, by default turns the following, `%{a: "b"}` into `{[Symbol.for("a")]: "b"}` in JavaScript. In order to get string keys, + one would have to do `%{"a" => "b"}` which turns into `{a: "b"}` in JavaScript. With `Kernel.object`, you can create string keyed maps + conveniently, `object(a: "b")` which turns into `{a: "b"}` + """ + defmacro object(args) do + args = Enum.map(args, fn + { k, v } when Kernel.is_atom(k) -> + { Atom.to_string(k), v } + pair -> + pair + end) + + { :%{}, [], args } + end end diff --git a/lib/elixir_script/prelude/kernel.ex b/lib/elixir_script/prelude/kernel.ex index df87e323..2ddb25b2 100644 --- a/lib/elixir_script/prelude/kernel.ex +++ b/lib/elixir_script/prelude/kernel.ex @@ -2,6 +2,7 @@ defmodule ElixirScript.Kernel do import Kernel, only: [defmodule: 2, def: 1, def: 2, defp: 2, defmacro: 1, defmacro: 2, defmacrop: 2, ||: 2, !: 1, ++: 2, in: 2, &&: 2, ===: 2, @: 1] + defmacro if(condition, clauses) do build_if(condition, clauses) end @@ -35,18 +36,6 @@ defmodule ElixirScript.Kernel do end end - defmacro typeof(term) do - quote do - JS.typeof(unquote(term)) - end - end - - defmacro instanceof(term, type) do - quote do - JS.instanceof(unquote(term), unquote(type)) - end - end - def abs(number) do Math.abs(number) end @@ -72,19 +61,19 @@ defmodule ElixirScript.Kernel do end def is_atom(term) do - typeof(term) === "symbol" + JS.typeof(term) === "symbol" end def is_binary(term) do - typeof(term) === "string" + JS.typeof(term) === "string" end def is_bitstring(term) do - is_binary(term) || instanceof(term, Elixir.Core.BitString) + is_binary(term) || JS.instanceof(term, Elixir.Core.BitString) end def is_boolean(term) do - JS.typeof(term) === "boolean" || instanceof(term, Boolean) + JS.typeof(term) === "boolean" || JS.instanceof(term, Boolean) end def is_float(term) do @@ -96,7 +85,7 @@ defmodule ElixirScript.Kernel do end def is_function(term, _) do - typeof(term) === "function" || instanceof(term, Function) + JS.typeof(term) === "function" || JS.instanceof(term, Function) end def is_integer(term) do @@ -108,7 +97,7 @@ defmodule ElixirScript.Kernel do end def is_number(term) do - typeof(term) === "number" || instanceof(term, Number) + JS.typeof(term) === "number" || JS.instanceof(term, Number) end def is_pid(term) do @@ -120,11 +109,7 @@ defmodule ElixirScript.Kernel do end def is_map(term) do - typeof(term) === "object" || instanceof(term, Object) - end - - def is_generator(term) do - term.constructor.name === "GeneratorFunction" + JS.typeof(term) === "object" || JS.instanceof(term, Object) end def is_port(_) do @@ -243,40 +228,4 @@ defmodule ElixirScript.Kernel do %ElixirScript.Range{ first: unquote(first), last: unquote(last) } end end - - defmacro yield() do - quote do - JS.yield() - end - end - - defmacro yield(term) do - quote do - JS.yield(unquote(term)) - end - end - - defmacro yield_to(term) do - quote do - JS.yield_to(unquote(term)) - end - end - - @doc """ - Provides a convenient way to create a string-based map. - - Elixirscript, by default turns the following, `%{a: "b"}` into `{[Symbol.for("a")]: "b"}` in JavaScript. In order to get string keys, - one would have to do `%{"a" => "b"}` which turns into `{a: "b"}` in JavaScript. With `Kernel.object`, you can create string keyed maps - conveniently, `object(a: "b")` which turns into `{a: "b"}` - """ - defmacro object(args) do - args = Enum.map(args, fn - { k, v } when Kernel.is_atom(k) -> - { Atom.to_string(k), v } - pair -> - pair - end) - - { :%{}, [], args } - end end diff --git a/lib/elixir_script/translator.ex b/lib/elixir_script/translator.ex index 20b0cc34..26d43edd 100644 --- a/lib/elixir_script/translator.ex +++ b/lib/elixir_script/translator.ex @@ -166,6 +166,10 @@ defmodule ElixirScript.Translator do { %ElixirScript.Translator.Empty{}, env } end + defp do_translate({:@, _, [{:on_js_load, _, [value]}]}, env) do + Call.make_function_call(value, [], env) + end + defp do_translate({:@, _, [{name, _, [value]}]}, env) do { Defmodule.make_attribute(name, value, env), env } end diff --git a/lib/elixir_script/translator/lexical_scope.ex b/lib/elixir_script/translator/lexical_scope.ex index a2fe688c..91e4dd07 100644 --- a/lib/elixir_script/translator/lexical_scope.ex +++ b/lib/elixir_script/translator/lexical_scope.ex @@ -102,7 +102,7 @@ defmodule ElixirScript.Translator.LexicalScope do env = add_import(env, ElixirScript.Kernel) cond do - module_name == ElixirScript.JS -> + module_name == JS -> env ElixirScript.Translator.State.is_module_loaded?(module_name) and length(module.macros) > 0 -> add_import(env, module_name, [only: :macros]) diff --git a/lib/elixir_script/translator/state.ex b/lib/elixir_script/translator/state.ex index 9c881fd3..b51bf5b6 100644 --- a/lib/elixir_script/translator/state.ex +++ b/lib/elixir_script/translator/state.ex @@ -67,6 +67,12 @@ defmodule ElixirScript.Translator.State do end) end + def set_loaded_modules(modules) do + Agent.update(__MODULE__, fn state -> + %{ state | loaded_modules: modules } + end) + end + def get do Agent.get(__MODULE__, &(&1)) end From ae3a0a2a6c0acb21d22b08817e5bcd53539caab6 Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Thu, 10 Nov 2016 21:27:29 -0600 Subject: [PATCH 333/860] Fix tests --- lib/elixir_script/passes/handle_output.ex | 9 ++- lib/elixir_script/passes/java_script_ast.ex | 1 - test/elixir_script_test.exs | 89 +-------------------- test/translator/protocol_test.exs | 54 ++++++------- 4 files changed, 36 insertions(+), 117 deletions(-) diff --git a/lib/elixir_script/passes/handle_output.ex b/lib/elixir_script/passes/handle_output.ex index 979b72f4..7589a62a 100644 --- a/lib/elixir_script/passes/handle_output.ex +++ b/lib/elixir_script/passes/handle_output.ex @@ -10,10 +10,17 @@ defmodule ElixirScript.Passes.HandleOutput do File.write!(stdlib_state_path, new_std_state) State.stop() else + State.stop() out(compiler_data, opts) end end + defp out(compiler_output, %{import_standard_libs: false} = compiler_opts) do + data = Enum.filter(compiler_output.data, fn({m, d}) -> d.app != :elixir end) + + out(%{ compiler_output | data: data }, Map.delete(compiler_opts, :import_standard_libs)) + end + defp out(compiler_output, %{output: nil} = compiler_opts) do compiler_output |> process_include_path(compiler_opts) @@ -34,7 +41,6 @@ defmodule ElixirScript.Passes.HandleOutput do end compiler_output.data - |> Enum.reject(fn({m, d}) -> Map.get(compiler_opts, :import_standard_libs, true) == false && d.app == :elixir end) |> Enum.each(fn({_, x}) -> write_to_file(x, output_path) end) @@ -52,7 +58,6 @@ defmodule ElixirScript.Passes.HandleOutput do defp process_include_path(compiler_output, compiler_opts) do compiler_output.data - |> Enum.reject(fn({m, d}) -> Map.get(compiler_opts, :import_standard_libs, true) == false && d.app == :elixir end) |> Enum.map(fn {_, module_data} -> case compiler_opts.include_path do diff --git a/lib/elixir_script/passes/java_script_ast.ex b/lib/elixir_script/passes/java_script_ast.ex index ccb16012..40fd60f3 100644 --- a/lib/elixir_script/passes/java_script_ast.ex +++ b/lib/elixir_script/passes/java_script_ast.ex @@ -29,7 +29,6 @@ defmodule ElixirScript.Passes.JavaScriptAST do %{ compiler_data | data: data } end - defp compile(module_data, opts) do env = ElixirScript.Translator.LexicalScope.module_scope(module_data.name, Utils.name_to_js_file_name(module_data.name) <> ".js", opts.env) diff --git a/test/elixir_script_test.exs b/test/elixir_script_test.exs index 60b23d60..5f8b11b6 100644 --- a/test/elixir_script_test.exs +++ b/test/elixir_script_test.exs @@ -2,96 +2,11 @@ defmodule ElixirScript.Test do use ExUnit.Case import ElixirScript.TestHelper - test "chain methods" do - js_code = ElixirScript.compile(""" - JQuery.("
").text(html) - """) - - assert Enum.join(js_code, "\n") =~ "JQuery('
').text(html)" - end - test "turn javascript ast into javascript code strings" do js_code = ElixirScript.compile(":atom") assert Enum.join(js_code, "\n") =~ "Symbol.for('atom')" end - test "parse one module correctly" do - js_code = ElixirScript.compile(""" - - defmodule Elephant do - @ul JQuery.("#todo-list") - - @doc "ignore" - def something() do - @ul - end - - defp something_else() do - to_string(10) - end - end - - """) - - assert_js_matches """ - import Elixir from '../elixir/Elixir'; - import Elixir$ElixirScript$Kernel from '../elixir/Elixir.ElixirScript.Kernel'; - import Elixir$ElixirScript$String$Chars from '../elixir/Elixir.ElixirScript.String.Chars'; - const something_else = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.clause([],function() { - return Elixir$ElixirScript$String$Chars.to_string(10); - })); - const something = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.clause([],function() { - return ul; - })); - const ul = JQuery('#todo-list'); - export default { - something - }; - """, hd(js_code) - end - - test "parse multiple modules correctly" do - - js_code = ElixirScript.compile(""" - defmodule Animals do - - defmodule Elephant do - defstruct trunk: true - end - - - def something() do - %Elephant{} - end - - end - """, %{ env: make_custom_env }) - - assert_js_matches """ - import Elixir from '../elixir/Elixir'; - import Elixir$ElixirScript$Kernel from '../elixir/Elixir.ElixirScript.Kernel'; - import Elixir$Animals$Elephant from '../app/Elixir.Animals.Elephant'; - const something = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.clause([],function() { - return Elixir$Animals$Elephant.Elixir$Animals$Elephant.create(Object.freeze({})); - })); - export default { - something - }; - """, hd(js_code) - - assert_js_matches """ - import Elixir from '../elixir/Elixir'; - import Elixir$ElixirScript$Kernel from '../elixir/Elixir.ElixirScript.Kernel'; - const Elixir$Animals$Elephant = Elixir.Core.Functions.defstruct({ - [Symbol.for('__struct__')]: Symbol.for('Elixir.Animals.Elephant'), - [Symbol.for('trunk')]: true - }); - export default { - Elixir$Animals$Elephant - }; - """, Enum.fetch!(js_code, 1) - end - test "parse macros" do @@ -118,7 +33,7 @@ defmodule ElixirScript.Test do export default { sandwich }; - """, hd(js_code) + """, List.last(js_code) end @@ -147,6 +62,6 @@ defmodule ElixirScript.Test do export default { sandwich }; - """, hd(js_code) + """, List.last(js_code) end end diff --git a/test/translator/protocol_test.exs b/test/translator/protocol_test.exs index 8a0d1f06..4d96d90b 100644 --- a/test/translator/protocol_test.exs +++ b/test/translator/protocol_test.exs @@ -25,8 +25,18 @@ defmodule ElixirScript.Translator.Defprotocol.Test do end js_code = """ - import Elixir$ElixirScript$Kernel from '../elixir/Elixir.ElixirScript.Kernel'; - import Implementations from '../app/Elixir.Blank.Defimpl'; + import Elixir from '../elixir/Elixir'; + let impls = []; + import Elixir$Blank$DefImpl$Elixir$Integer from '../app/Elixir.Blank.DefImpl.Elixir.Integer'; + impls.push(Elixir$Blank$DefImpl$Elixir$Integer) + import Elixir$Blank$DefImpl$Elixir$List from '../app/Elixir.Blank.DefImpl.Elixir.List'; + impls.push(Elixir$Blank$DefImpl$Elixir$List) + import Elixir$Blank$DefImpl$Elixir$Atom from '../app/Elixir.Blank.DefImpl.Elixir.Atom'; + impls.push(Elixir$Blank$DefImpl$Elixir$Atom) + export default impls; + + import Elixir$ElixirScript$Kernel from '../elixir/Elixir.ElixirScript.Kernel'; + import Implementations from '../app/Elixir.Blank.Defimpl'; const Elixir$Blank = Elixir.Core.Functions.defprotocol({ blank__qmark__: function() { @@ -35,7 +45,7 @@ defmodule ElixirScript.Translator.Defprotocol.Test do for(let {Type,Implementation} of Implementations) Elixir.Core.Functions.defimpl(Elixir$Blank,Type,Implementation) export default Elixir$Blank; - import Elixir$ElixirScript$Kernel from '../elixir/Elixir.ElixirScript.Kernel'; + import Elixir$ElixirScript$Kernel from '../elixir/Elixir.ElixirScript.Kernel'; const blank__qmark__ = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.clause([Elixir.Core.Patterns.variable()],function(number) { return false; })); @@ -45,7 +55,7 @@ defmodule ElixirScript.Translator.Defprotocol.Test do } }; - import Elixir$ElixirScript$Kernel from '../elixir/Elixir.ElixirScript.Kernel'; + import Elixir$ElixirScript$Kernel from '../elixir/Elixir.ElixirScript.Kernel'; const blank__qmark__ = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.clause([Object.freeze([])],function() { return true; }),Elixir.Core.Patterns.clause([Elixir.Core.Patterns.wildcard()],function() { @@ -57,29 +67,19 @@ defmodule ElixirScript.Translator.Defprotocol.Test do } }; - import Elixir$ElixirScript$Kernel from '../elixir/Elixir.ElixirScript.Kernel'; - const blank__qmark__ = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.clause([false],function() { - return true; - }),Elixir.Core.Patterns.clause([null],function() { - return true; - }),Elixir.Core.Patterns.clause([Elixir.Core.Patterns.wildcard()],function() { - return false; - })); - export default { - 'Type': Symbol, 'Implementation': { - blank__qmark__ - } - }; - - import Elixir from '../elixir/Elixir'; - let impls = []; - import Elixir$Blank$DefImpl$Elixir$Integer from '../app/Elixir.Blank.DefImpl.Elixir.Integer'; - impls.push(Elixir$Blank$DefImpl$Elixir$Integer) - import Elixir$Blank$DefImpl$Elixir$List from '../app/Elixir.Blank.DefImpl.Elixir.List'; - impls.push(Elixir$Blank$DefImpl$Elixir$List) - import Elixir$Blank$DefImpl$Elixir$Atom from '../app/Elixir.Blank.DefImpl.Elixir.Atom'; - impls.push(Elixir$Blank$DefImpl$Elixir$Atom) - export default impls; + import Elixir$ElixirScript$Kernel from '../elixir/Elixir.ElixirScript.Kernel'; + const blank__qmark__ = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.clause([false],function() { + return true; + }),Elixir.Core.Patterns.clause([null],function() { + return true; + }),Elixir.Core.Patterns.clause([Elixir.Core.Patterns.wildcard()],function() { + return false; + })); + export default { + 'Type': Symbol, 'Implementation': { + blank__qmark__ + } + }; """ assert_translation(ex_ast, js_code) From b37a5e2deac669556a39e12f04ec2f5937ec3205 Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Sat, 12 Nov 2016 15:26:55 -0600 Subject: [PATCH 334/860] Add Js.import\3. Update Changelog --- CHANGELOG.md | 11 +++++++++++ lib/elixir_script/module_systems.ex | 8 ++------ lib/elixir_script/module_systems/common.ex | 8 ++------ lib/elixir_script/module_systems/es6.ex | 16 +++++++--------- lib/elixir_script/prelude/js.ex | 8 ++++---- lib/elixir_script/translator/kernel/js.ex | 8 ++++++-- 6 files changed, 32 insertions(+), 27 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index b78ab750..beaaed00 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,6 +11,17 @@ and this project adheres to [Semantic Versioning](http://semver.org/). - [Implement `context` option on `quote`](https://github.com/bryanjos/elixirscript/pull/208) - New compiler pipeline - `@on_js_load`. Expects a 0 arity function. This function will be called when the compiled module is loaded in JavaScript +- `JS.import\3`. Just like `JS.import\2` but expects options to decide if the import should be a default one or a namespace on. Only option allowed is `default`. Set to `true` by default + ```elixir + # translates to "import A from 'a'" + JS.import A, "a" + + #translates to "import * as A from 'a'" + JS.import A, "a", default: false + ``` + +### Removed +- The form of `JS.import` that accepted a list of atoms as the first arg. Used `JS.import\3` with `default: false` instead to create a namespace import ### Changed - [Changed CHANGELOG.md to adhere the format from Keep a Changelog](https://github.com/bryanjos/elixirscript/pull/205) diff --git a/lib/elixir_script/module_systems.ex b/lib/elixir_script/module_systems.ex index efa8ca7f..6d2b3db6 100644 --- a/lib/elixir_script/module_systems.ex +++ b/lib/elixir_script/module_systems.ex @@ -4,18 +4,14 @@ defmodule ElixirScript.ModuleSystems do ElixirScript.ModuleSystems.ES6 end - def import_module(module_names, from, env) when is_list(module_names) do - module_system.import_module(module_names, from, env) + def import_namespace_module(module_name, from, env) do + module_system.import_namespace_module(module_name, from, env) end def import_module(module_name, from, env) do module_system.import_module(module_name, from, env) end - def import_module(module_name, %ElixirScript.Translator.LexicalScope{} = env) do - module_system.import_module(module_name, env) - end - def import_module(import_name, from) do module_system.import_module(import_name, from) end diff --git a/lib/elixir_script/module_systems/common.ex b/lib/elixir_script/module_systems/common.ex index b278c990..7f1cc5c9 100644 --- a/lib/elixir_script/module_systems/common.ex +++ b/lib/elixir_script/module_systems/common.ex @@ -2,12 +2,8 @@ defmodule ElixirScript.ModuleSystems.Common do alias ESTree.Tools.Builder, as: JS alias ElixirScript.Translator - def import_module(module_names, from, env) when is_list(module_names) do - assignment_properties = Enum.map(module_names, fn(x) -> - JS.assignment_property(Translator.translate!(x, env)) - end) - - do_import_module(JS.object_pattern(assignment_properties), from) + def import_namespace_module(module_name, from, env) do + do_import_module(Translator.translate!(module_name, env), from) end def import_module(module_name, from, env) do diff --git a/lib/elixir_script/module_systems/es6.ex b/lib/elixir_script/module_systems/es6.ex index 3fc0b525..cd50e3bb 100644 --- a/lib/elixir_script/module_systems/es6.ex +++ b/lib/elixir_script/module_systems/es6.ex @@ -2,15 +2,13 @@ defmodule ElixirScript.ModuleSystems.ES6 do alias ESTree.Tools.Builder, as: JS alias ElixirScript.Translator - def import_module(module_names, from, env) when is_list(module_names) do - import_specifiers = Enum.map(module_names, fn(x) -> - JS.import_specifier( - Translator.translate!(x, env), - Translator.translate!(x, env) - ) - end) - - do_import_module(import_specifiers, from) + def import_namespace_module(module_name, from, env) do + import_specifier = JS.import_namespace_specifier( + Translator.translate!(module_name, env), + Translator.translate!(module_name, env) + ) + + do_import_module([import_specifier], from) end def import_module(module_name, from, env) do diff --git a/lib/elixir_script/prelude/js.ex b/lib/elixir_script/prelude/js.ex index 72cb66f6..ddad57f5 100644 --- a/lib/elixir_script/prelude/js.ex +++ b/lib/elixir_script/prelude/js.ex @@ -33,15 +33,15 @@ defmodule JS do but JavaScript modules work differently and have to be imported using this. - If module is not a list, then it is treated as a default import, - otherwise it is not. + If `default` is set to true then it is treated as a default import. + Otherwise it is treated as a namespace import. ex: JS.import A, "a" #translates to "import A from 'a'" - JS.import [A, B, C], "a" #translates to "import {A, B, C} from 'a'" + JS.import A, "a", default: false #translates to "import * as A from 'a'" """ - def import(module, from) do + def import(module, from, opts \\ [default: true]) do end @doc """ diff --git a/lib/elixir_script/translator/kernel/js.ex b/lib/elixir_script/translator/kernel/js.ex index e83a3497..3bc2d70b 100644 --- a/lib/elixir_script/translator/kernel/js.ex +++ b/lib/elixir_script/translator/kernel/js.ex @@ -80,8 +80,12 @@ defmodule ElixirScript.Translator.JS do Translator.translate!(quoted, env) end - defp do_translate({:import, _, [module_names, from]}, env) when is_list(module_names) do - ModuleSystems.import_module(module_names, from, env) + defp do_translate({:import, _, [module_name, from, [default: false]]}, env) do + ModuleSystems.import_namespace_module(module_name, from, env) + end + + defp do_translate({:import, _, [module_name, from, [default: true]]}, env) do + ModuleSystems.import_module(module_name, from, env) end defp do_translate({:import, _, [module_name, from]}, env) do From 88036e476b316a3f736c1396373defaa1715eddc Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Sat, 12 Nov 2016 20:56:16 -0600 Subject: [PATCH 335/860] Removed env option from compile functions Updated default core_path from 'Elixir' to Elixir.Bootstrap Removed pass that filters exjs files --- CHANGELOG.md | 4 +- lib/elixir_script.ex | 14 ++----- lib/elixir_script/cli.ex | 2 +- lib/elixir_script/passes/filter_exjs.ex | 14 ------- lib/elixir_script/prelude/js.ex | 26 +++++-------- lib/elixir_script/prelude/kernel.ex | 3 +- lib/elixir_script/prelude/list.ex | 1 + lib/elixir_script/prelude/tuple.ex | 1 + lib/elixir_script/translator/kernel/js.ex | 11 ++++++ rollup.config.js | 2 +- test/elixir_script_test.exs | 2 +- test/translator/map_test.exs | 6 --- test/translator/pattern_matching_test.exs | 46 +++++++++++------------ test/translator/protocol_test.exs | 2 +- 14 files changed, 57 insertions(+), 77 deletions(-) delete mode 100644 lib/elixir_script/passes/filter_exjs.ex diff --git a/CHANGELOG.md b/CHANGELOG.md index beaaed00..2dca75a3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -22,13 +22,15 @@ and this project adheres to [Semantic Versioning](http://semver.org/). ### Removed - The form of `JS.import` that accepted a list of atoms as the first arg. Used `JS.import\3` with `default: false` instead to create a namespace import +- `env` is no longer an option for `ElixirScript`'s compile functions ### Changed - [Changed CHANGELOG.md to adhere the format from Keep a Changelog](https://github.com/bryanjos/elixirscript/pull/205) - `defmacro` now supported. No longer have to separate macros from functions in separate files. `defmacrop` still unsupported - Elixirscript files must now be valid Elixir syntax. Syntax once supported by Elixirscript `JQuery.("#element")`, is no longer supported - Now compiles `exjs` and `ex` files within the path can be compiled all the same. Dependencies from hex are still unsupported so these files must not rely on any code outside of the path. What this does mean is that it is now possible to share code between Elixir and Elixirscript as long as the Elixir files functionality fall within what Elixirscript currently supports. -- `defgen`, `defgenp`, `yield`, `yield_to`, and `object` now require a `use ElixirScript` expression before use. +- To use anything in the `JS` module, you must `require` the `JS` module first +- `defgen`, `defgenp`, `yield`, `yield_to`, and `object` are now in the `JS` module - To access functions in the global JavaScript scope, either use `JS.global\0` or use the erlang module call syntax ```elixir #calling alert diff --git a/lib/elixir_script.ex b/lib/elixir_script.ex index 1eb4dd1c..e798b4a3 100644 --- a/lib/elixir_script.ex +++ b/lib/elixir_script.ex @@ -20,7 +20,6 @@ defmodule ElixirScript do * `:include_path` - a boolean controlling whether to return just the JavaScript code or a tuple of the file name and the JavaScript code * `:root` - a binary path prepended to the path of the standard lib imports if needed - * `:env` - a Macro.env struct to use. This is most useful when using macros. Make sure that the env has the macros imported or required. * `:core_path` - The es6 import path used to import the elixirscript core. When using this option, the Elixir.js file is not exported @@ -43,7 +42,7 @@ defmodule ElixirScript do spawn_monitor: 3, send: 2, self: 0, match?: 2, to_string: 1, "|>": 2, in: 2, "..": 2 ] import ElixirScript.Kernel - import JS, only: [defgen: 1, defgen: 2, is_generator: 1, yield: 0, yield: 1, yield_to: 1, object: 1] + require JS end end @@ -131,7 +130,6 @@ defmodule ElixirScript do |> ElixirScript.Passes.DepsPaths.execute(opts) |> ElixirScript.Passes.ASTFromFile.execute(opts) |> ElixirScript.Passes.LoadModules.execute(opts) - |> ElixirScript.Passes.FilterExjs.execute(opts) |> ElixirScript.Passes.FindModules.execute(opts) |> ElixirScript.Passes.FindChangedFiles.execute(opts) |> ElixirScript.Passes.FindFunctions.execute(opts) @@ -188,9 +186,9 @@ defmodule ElixirScript do default_options = Map.new |> Map.put(:include_path, false) |> Map.put(:root, nil) - |> Map.put(:env, custom_env()) + |> Map.put(:env, __ENV__) |> Map.put(:import_standard_libs, true) - |> Map.put(:core_path, "Elixir") + |> Map.put(:core_path, "Elixir.Bootstrap") |> Map.put(:full_build, false) |> Map.put(:output, nil) |> Map.put(:app, :app) @@ -198,12 +196,6 @@ defmodule ElixirScript do Map.merge(default_options, opts) end - @doc false - def custom_env() do - __using__([]) - __ENV__ - end - @doc """ Copies the javascript that makes up the ElixirScript stdlib to the specified location diff --git a/lib/elixir_script/cli.ex b/lib/elixir_script/cli.ex index bbc7104d..b4cb3aa1 100644 --- a/lib/elixir_script/cli.ex +++ b/lib/elixir_script/cli.ex @@ -76,7 +76,7 @@ defmodule ElixirScript.CLI do compile_opts = %{ root: options[:root], include_path: true, - core_path: Keyword.get(options, :core_path, "Elixir"), + core_path: Keyword.get(options, :core_path, "Elixir.Bootstrap"), full_build: Keyword.get(options, :full_build, false), output: Keyword.get(options, :output, :stdout) } diff --git a/lib/elixir_script/passes/filter_exjs.ex b/lib/elixir_script/passes/filter_exjs.ex deleted file mode 100644 index bfb7edf5..00000000 --- a/lib/elixir_script/passes/filter_exjs.ex +++ /dev/null @@ -1,14 +0,0 @@ -defmodule ElixirScript.Passes.FilterExjs do - - - def execute(compiler_data, _) do - - data = Enum.filter(compiler_data.data, fn - {_, data} -> Path.extname(data.path) == ".exjs" - data -> Path.extname(data.path) == ".exjs" - end) - - Map.put(compiler_data, :data, data) - end - -end diff --git a/lib/elixir_script/prelude/js.ex b/lib/elixir_script/prelude/js.ex index ddad57f5..47433486 100644 --- a/lib/elixir_script/prelude/js.ex +++ b/lib/elixir_script/prelude/js.ex @@ -12,7 +12,7 @@ defmodule JS do ex: JS.new User, ["first_name", "last_name"] """ - def new(module, params) do + defmacro new(module, params) do end @@ -22,7 +22,7 @@ defmodule JS do ex: JS.update elem, %{"width" => 100} """ - def update(object, map) do + defmacro update(object, map) do end @@ -41,25 +41,25 @@ defmodule JS do JS.import A, "a", default: false #translates to "import * as A from 'a'" """ - def import(module, from, opts \\ [default: true]) do + defmacro import(module, from, opts \\ [default: true]) do end @doc """ Returns the type of the given value """ - def typeof(value) do + defmacro typeof(value) do end @doc """ Determines if value is an instance of type. """ - def instanceof(value, type) do + defmacro instanceof(value, type) do end @doc """ Throws the term given """ - def throw(term) do + defmacro throw(term) do end @@ -83,13 +83,13 @@ defmodule JS do term.constructor.name === "GeneratorFunction" end - def yield() do + defmacro yield() do end - def yield(term) do + defmacro yield(term) do end - def yield_to(term) do + defmacro yield_to(term) do end @doc """ @@ -100,13 +100,5 @@ defmodule JS do conveniently, `object(a: "b")` which turns into `{a: "b"}` """ defmacro object(args) do - args = Enum.map(args, fn - { k, v } when Kernel.is_atom(k) -> - { Atom.to_string(k), v } - pair -> - pair - end) - - { :%{}, [], args } end end diff --git a/lib/elixir_script/prelude/kernel.ex b/lib/elixir_script/prelude/kernel.ex index 2ddb25b2..12e9c20a 100644 --- a/lib/elixir_script/prelude/kernel.ex +++ b/lib/elixir_script/prelude/kernel.ex @@ -1,6 +1,7 @@ defmodule ElixirScript.Kernel do import Kernel, only: [defmodule: 2, def: 1, def: 2, defp: 2, - defmacro: 1, defmacro: 2, defmacrop: 2, ||: 2, !: 1, ++: 2, in: 2, &&: 2, ===: 2, @: 1] + defmacro: 1, defmacro: 2, defmacrop: 2, ||: 2, !: 1, ++: 2, in: 2, &&: 2, ===: 2, @: 1] + require JS defmacro if(condition, clauses) do diff --git a/lib/elixir_script/prelude/list.ex b/lib/elixir_script/prelude/list.ex index 97f5114c..441f2373 100644 --- a/lib/elixir_script/prelude/list.ex +++ b/lib/elixir_script/prelude/list.ex @@ -1,4 +1,5 @@ defmodule ElixirScript.List do + require JS def duplicate(data, size) do do_duplicate(data, size, []) diff --git a/lib/elixir_script/prelude/tuple.ex b/lib/elixir_script/prelude/tuple.ex index d5f98b00..c803f4d8 100644 --- a/lib/elixir_script/prelude/tuple.ex +++ b/lib/elixir_script/prelude/tuple.ex @@ -1,4 +1,5 @@ defmodule ElixirScript.Tuple do + require JS def duplicate(data, size) do JS.new(Elixir.Core.Tuple, do_duplicate(data, size, [])) diff --git a/lib/elixir_script/translator/kernel/js.ex b/lib/elixir_script/translator/kernel/js.ex index 3bc2d70b..49df2d9f 100644 --- a/lib/elixir_script/translator/kernel/js.ex +++ b/lib/elixir_script/translator/kernel/js.ex @@ -92,4 +92,15 @@ defmodule ElixirScript.Translator.JS do ModuleSystems.import_module(module_name, from, env) end + defp do_translate({:object, _, [args]}, env) do + args = Enum.map(args, fn + { k, v } when Kernel.is_atom(k) -> + { Atom.to_string(k), v } + pair -> + pair + end) + + Translator.translate!({ :%{}, [], args }, env) + end + end diff --git a/rollup.config.js b/rollup.config.js index 72924ca9..e71e5b51 100644 --- a/rollup.config.js +++ b/rollup.config.js @@ -4,7 +4,7 @@ import babel from 'rollup-plugin-babel'; export default { entry: 'src/javascript/elixir.js', - dest: 'priv/elixir/Elixir.js', + dest: 'priv/elixir/Elixir.Bootstrap.js', sourceMap: 'inline', format: 'es6', plugins: [ diff --git a/test/elixir_script_test.exs b/test/elixir_script_test.exs index 5f8b11b6..4cdc5f06 100644 --- a/test/elixir_script_test.exs +++ b/test/elixir_script_test.exs @@ -22,7 +22,7 @@ defmodule ElixirScript.Test do """, %{ env: make_custom_env }) assert_js_matches """ - import Elixir from '../elixir/Elixir'; + import Elixir from '../elixir/Elixir.Bootstrap'; import Elixir$ElixirScript$Kernel from '../elixir/Elixir.ElixirScript.Kernel'; const something_else = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.clause([],function() { return 1 * 1; diff --git a/test/translator/map_test.exs b/test/translator/map_test.exs index 9dd2a3a3..f06e701f 100644 --- a/test/translator/map_test.exs +++ b/test/translator/map_test.exs @@ -70,10 +70,4 @@ defmodule ElixirScript.Translator.Map.Test do assert_translation(ex_ast, js_code) end - test "translate object macro" do - ex_ast = quote do: object(a: b) - js_code = "Object.freeze({ a: b })" - assert_translation(ex_ast, js_code) - end - end diff --git a/test/translator/pattern_matching_test.exs b/test/translator/pattern_matching_test.exs index 402eebab..c01d8840 100644 --- a/test/translator/pattern_matching_test.exs +++ b/test/translator/pattern_matching_test.exs @@ -9,7 +9,7 @@ defmodule ElixirScript.Translator.PatternMatching.Test do @std_lib_state File.read!(File.cwd!() <> "/lib/elixir_script/translator/stdlib_state.bin") setup do - ElixirScript.Translator.State.start_link(%{env: ElixirScript.custom_env}, []) + ElixirScript.Translator.State.start_link(%{env: __ENV__}, []) ElixirScript.Translator.State.deserialize(@std_lib_state) # Returns extra metadata, it must be a dict @@ -18,7 +18,7 @@ defmodule ElixirScript.Translator.PatternMatching.Test do test "match wildcard" do params = [{:_, [], Test}] - result = PatternMatching.build_match(params, ElixirScript.Translator.LexicalScope.module_scope(ElixirScript.Temp, "temp.ex", ElixirScript.custom_env) ) + result = PatternMatching.build_match(params, ElixirScript.Translator.LexicalScope.module_scope(ElixirScript.Temp, "temp.ex", __ENV__) ) expected_result = { [PatternMatching.wildcard], [JS.identifier(:undefined)] } assert result == expected_result @@ -26,7 +26,7 @@ defmodule ElixirScript.Translator.PatternMatching.Test do test "match one identifier param" do params = [{:a, [], Test}] - result = PatternMatching.build_match(params, ElixirScript.Translator.LexicalScope.module_scope(ElixirScript.Temp, "temp.ex", ElixirScript.custom_env) ) + result = PatternMatching.build_match(params, ElixirScript.Translator.LexicalScope.module_scope(ElixirScript.Temp, "temp.ex", __ENV__) ) expected_result = {[PatternMatching.parameter], [JS.identifier("a")]} assert result == expected_result @@ -34,7 +34,7 @@ defmodule ElixirScript.Translator.PatternMatching.Test do test "match multiple identifier params" do params = [{:a, [], Test}, {:b, [], Test}, {:c, [], Test}] - result = PatternMatching.build_match(params, ElixirScript.Translator.LexicalScope.module_scope(ElixirScript.Temp, "temp.ex", ElixirScript.custom_env) ) + result = PatternMatching.build_match(params, ElixirScript.Translator.LexicalScope.module_scope(ElixirScript.Temp, "temp.ex", __ENV__) ) expected_result = { List.duplicate(PatternMatching.parameter, 3), [JS.identifier("a"), JS.identifier("b"), JS.identifier("c")] @@ -45,7 +45,7 @@ defmodule ElixirScript.Translator.PatternMatching.Test do test "match head and tail param" do params = [[{:|, [], [{:head, [], Elixir}, {:tail, [], Elixir}]}]] - result = PatternMatching.build_match(params, ElixirScript.Translator.LexicalScope.module_scope(ElixirScript.Temp, "temp.ex", ElixirScript.custom_env) ) + result = PatternMatching.build_match(params, ElixirScript.Translator.LexicalScope.module_scope(ElixirScript.Temp, "temp.ex", __ENV__) ) expected_result = { [PatternMatching.head_tail(PatternMatching.parameter, PatternMatching.parameter)], [JS.identifier("head"), JS.identifier("tail")] @@ -56,7 +56,7 @@ defmodule ElixirScript.Translator.PatternMatching.Test do test "match prefix param" do params = [{:<>, [context: Elixir, import: Elixir.Kernel], ["Bearer ", {:token, [], Elixir}]}] - result = PatternMatching.build_match(params, ElixirScript.Translator.LexicalScope.module_scope(ElixirScript.Temp, "temp.ex", ElixirScript.custom_env) ) + result = PatternMatching.build_match(params, ElixirScript.Translator.LexicalScope.module_scope(ElixirScript.Temp, "temp.ex", __ENV__) ) expected_result = { [PatternMatching.starts_with("Bearer ")], [JS.identifier("token")] @@ -67,7 +67,7 @@ defmodule ElixirScript.Translator.PatternMatching.Test do test "match list" do params = [[{:a, [], Elixir}, {:b, [], Elixir}, {:c, [], Elixir}]] - result = PatternMatching.build_match(params, ElixirScript.Translator.LexicalScope.module_scope(ElixirScript.Temp, "temp.ex", ElixirScript.custom_env) ) + result = PatternMatching.build_match(params, ElixirScript.Translator.LexicalScope.module_scope(ElixirScript.Temp, "temp.ex", __ENV__) ) expected_result = { [Primitive.make_list_no_translate(List.duplicate(PatternMatching.parameter, 3))], [JS.identifier("a"), JS.identifier("b"), JS.identifier("c")] @@ -78,7 +78,7 @@ defmodule ElixirScript.Translator.PatternMatching.Test do test "match list with a literal" do params = [[1, {:b, [], Elixir}, {:c, [], Elixir}]] - result = PatternMatching.build_match(params, ElixirScript.Translator.LexicalScope.module_scope(ElixirScript.Temp, "temp.ex", ElixirScript.custom_env) ) + result = PatternMatching.build_match(params, ElixirScript.Translator.LexicalScope.module_scope(ElixirScript.Temp, "temp.ex", __ENV__) ) expected_result = { [Primitive.make_list_no_translate([JS.literal(1), PatternMatching.parameter, PatternMatching.parameter])], [JS.identifier("b"), JS.identifier("c")] @@ -89,7 +89,7 @@ defmodule ElixirScript.Translator.PatternMatching.Test do test "match number" do params = [1] - result = PatternMatching.build_match(params, ElixirScript.Translator.LexicalScope.module_scope(ElixirScript.Temp, "temp.ex", ElixirScript.custom_env) ) + result = PatternMatching.build_match(params, ElixirScript.Translator.LexicalScope.module_scope(ElixirScript.Temp, "temp.ex", __ENV__) ) expected_result = { [JS.literal(1)], [] @@ -100,7 +100,7 @@ defmodule ElixirScript.Translator.PatternMatching.Test do test "match struct pattern" do params = [{:%, [], [{:__aliases__, [alias: false], [:Hello]}, {:%{}, [], []}]}] - result = PatternMatching.build_match(params, ElixirScript.Translator.LexicalScope.module_scope(ElixirScript.Temp, "temp.ex", ElixirScript.custom_env) ) + result = PatternMatching.build_match(params, ElixirScript.Translator.LexicalScope.module_scope(ElixirScript.Temp, "temp.ex", __ENV__) ) expected_result = { [PatternMatching.type(JS.identifier("Hello"), JS.object_expression([]))], [] @@ -111,10 +111,10 @@ defmodule ElixirScript.Translator.PatternMatching.Test do test "match struct pattern with property" do params = [{:%, [], [{:__aliases__, [alias: false], [:Hello]}, {:%{}, [], [key: 1]}]}] - result = PatternMatching.build_match(params, ElixirScript.Translator.LexicalScope.module_scope(ElixirScript.Temp, "temp.ex", ElixirScript.custom_env) ) + result = PatternMatching.build_match(params, ElixirScript.Translator.LexicalScope.module_scope(ElixirScript.Temp, "temp.ex", __ENV__) ) expected_result = { [PatternMatching.type(JS.identifier("Hello"), JS.object_expression([ - Map.make_property(Translator.translate!(:key, ElixirScript.Translator.LexicalScope.module_scope(ElixirScript.Temp, "temp.ex", ElixirScript.custom_env) ), Translator.translate!(1, ElixirScript.Translator.LexicalScope.module_scope(ElixirScript.Temp, "temp.ex", ElixirScript.custom_env) )) + Map.make_property(Translator.translate!(:key, ElixirScript.Translator.LexicalScope.module_scope(ElixirScript.Temp, "temp.ex", __ENV__) ), Translator.translate!(1, ElixirScript.Translator.LexicalScope.module_scope(ElixirScript.Temp, "temp.ex", __ENV__) )) ])) ], [] @@ -125,10 +125,10 @@ defmodule ElixirScript.Translator.PatternMatching.Test do test "match struct pattern with property param" do params = [{:%, [], [{:__aliases__, [alias: false], [:Hello]}, {:%{}, [], [key: {:key, [], Elixir }]}]}] - result = PatternMatching.build_match(params, ElixirScript.Translator.LexicalScope.module_scope(ElixirScript.Temp, "temp.ex", ElixirScript.custom_env) ) + result = PatternMatching.build_match(params, ElixirScript.Translator.LexicalScope.module_scope(ElixirScript.Temp, "temp.ex", __ENV__) ) expected_result = { [PatternMatching.type(JS.identifier("Hello"), JS.object_expression([ - Map.make_property(Translator.translate!(:key, ElixirScript.Translator.LexicalScope.module_scope(ElixirScript.Temp, "temp.ex", ElixirScript.custom_env) ), PatternMatching.parameter) + Map.make_property(Translator.translate!(:key, ElixirScript.Translator.LexicalScope.module_scope(ElixirScript.Temp, "temp.ex", __ENV__) ), PatternMatching.parameter) ])) ], [JS.identifier("key")] @@ -139,7 +139,7 @@ defmodule ElixirScript.Translator.PatternMatching.Test do test "capture parameter when assigning it" do params = [{:=, [], [1, {:a, [], Elixir}]}] - result = PatternMatching.build_match(params, ElixirScript.Translator.LexicalScope.module_scope(ElixirScript.Temp, "temp.ex", ElixirScript.custom_env) ) + result = PatternMatching.build_match(params, ElixirScript.Translator.LexicalScope.module_scope(ElixirScript.Temp, "temp.ex", __ENV__) ) expected_result = { [PatternMatching.capture(JS.literal(1))], [JS.identifier("a")] @@ -149,7 +149,7 @@ defmodule ElixirScript.Translator.PatternMatching.Test do params = [{:=, [], [{:a, [], Elixir}, 1]}] - result = PatternMatching.build_match(params, ElixirScript.Translator.LexicalScope.module_scope(ElixirScript.Temp, "temp.ex", ElixirScript.custom_env) ) + result = PatternMatching.build_match(params, ElixirScript.Translator.LexicalScope.module_scope(ElixirScript.Temp, "temp.ex", __ENV__) ) expected_result = { [PatternMatching.capture(JS.literal(1))], [JS.identifier("a")] @@ -159,7 +159,7 @@ defmodule ElixirScript.Translator.PatternMatching.Test do params = [{:=, [], [{:%, [], [{:__aliases__, [alias: false], [:AStruct]}, {:%{}, [], []}]}, {:a, [], ElixirScript.Translator.Function.Test}]}] - result = PatternMatching.build_match(params, ElixirScript.Translator.LexicalScope.module_scope(ElixirScript.Temp, "temp.ex", ElixirScript.custom_env) ) + result = PatternMatching.build_match(params, ElixirScript.Translator.LexicalScope.module_scope(ElixirScript.Temp, "temp.ex", __ENV__) ) expected_result = { [PatternMatching.capture(PatternMatching.type(JS.identifier("AStruct"), JS.object_expression([])))], [JS.identifier("a")] @@ -170,7 +170,7 @@ defmodule ElixirScript.Translator.PatternMatching.Test do test "match and assign list" do params = [{:=, [], [[{:a, [], Elixir}, {:b, [], Elixir}, {:c, [], Elixir}], {:d, [], Elixir}]}] - result = PatternMatching.build_match(params, ElixirScript.Translator.LexicalScope.module_scope(ElixirScript.Temp, "temp.ex", ElixirScript.custom_env) ) + result = PatternMatching.build_match(params, ElixirScript.Translator.LexicalScope.module_scope(ElixirScript.Temp, "temp.ex", __ENV__) ) expected_result = { [PatternMatching.capture(Primitive.make_list_no_translate([PatternMatching.parameter, PatternMatching.parameter, PatternMatching.parameter]))], [JS.identifier("a"), JS.identifier("b"), JS.identifier("c"), JS.identifier("d")] @@ -181,7 +181,7 @@ defmodule ElixirScript.Translator.PatternMatching.Test do test "match on tuple" do params = [{:{}, [], [1, {:b, [], Elixir}, 3]}] - result = PatternMatching.build_match(params, ElixirScript.Translator.LexicalScope.module_scope(ElixirScript.Temp, "temp.ex", ElixirScript.custom_env) ) + result = PatternMatching.build_match(params, ElixirScript.Translator.LexicalScope.module_scope(ElixirScript.Temp, "temp.ex", __ENV__) ) expected_result = { [PatternMatching.type(Primitive.tuple_class, JS.object_expression([JS.property( JS.identifier("values"), @@ -193,7 +193,7 @@ defmodule ElixirScript.Translator.PatternMatching.Test do assert result == expected_result params = [{1, {:b, [], Elixir}}] - result = PatternMatching.build_match(params, ElixirScript.Translator.LexicalScope.module_scope(ElixirScript.Temp, "temp.ex", ElixirScript.custom_env) ) + result = PatternMatching.build_match(params, ElixirScript.Translator.LexicalScope.module_scope(ElixirScript.Temp, "temp.ex", __ENV__) ) expected_result = { [PatternMatching.type(Primitive.tuple_class, JS.object_expression([JS.property( JS.identifier("values"), @@ -207,11 +207,11 @@ defmodule ElixirScript.Translator.PatternMatching.Test do test "match on map" do params = [{:%{}, [], [which: 13]}] - result = PatternMatching.build_match(params, ElixirScript.Translator.LexicalScope.module_scope(ElixirScript.Temp, "temp.ex", ElixirScript.custom_env) ) + result = PatternMatching.build_match(params, ElixirScript.Translator.LexicalScope.module_scope(ElixirScript.Temp, "temp.ex", __ENV__) ) expected_result = { [JS.object_expression([ - Map.make_property(Translator.translate!(:which, ElixirScript.Translator.LexicalScope.module_scope(ElixirScript.Temp, "temp.ex", ElixirScript.custom_env) ), JS.literal(13)) + Map.make_property(Translator.translate!(:which, ElixirScript.Translator.LexicalScope.module_scope(ElixirScript.Temp, "temp.ex", __ENV__) ), JS.literal(13)) ])], [] } @@ -222,7 +222,7 @@ defmodule ElixirScript.Translator.PatternMatching.Test do test "match on bound value" do params = [{:^, [], [{:a, [], Elixir}]}] - result = PatternMatching.build_match(params, ElixirScript.Translator.LexicalScope.module_scope(ElixirScript.Temp, "temp.ex", ElixirScript.custom_env) ) + result = PatternMatching.build_match(params, ElixirScript.Translator.LexicalScope.module_scope(ElixirScript.Temp, "temp.ex", __ENV__) ) expected_result = { [PatternMatching.bound(JS.identifier("a"))], diff --git a/test/translator/protocol_test.exs b/test/translator/protocol_test.exs index 4d96d90b..efcfbc5f 100644 --- a/test/translator/protocol_test.exs +++ b/test/translator/protocol_test.exs @@ -25,7 +25,7 @@ defmodule ElixirScript.Translator.Defprotocol.Test do end js_code = """ - import Elixir from '../elixir/Elixir'; + import Elixir from '../elixir/Elixir.Bootstrap'; let impls = []; import Elixir$Blank$DefImpl$Elixir$Integer from '../app/Elixir.Blank.DefImpl.Elixir.Integer'; impls.push(Elixir$Blank$DefImpl$Elixir$Integer) From 0ad7f21d2bf0c9c007dc8604eeed13926264b61d Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Sat, 12 Nov 2016 21:00:51 -0600 Subject: [PATCH 336/860] Updated changelog --- CHANGELOG.md | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 2dca75a3..04f5a13c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -23,13 +23,14 @@ and this project adheres to [Semantic Versioning](http://semver.org/). ### Removed - The form of `JS.import` that accepted a list of atoms as the first arg. Used `JS.import\3` with `default: false` instead to create a namespace import - `env` is no longer an option for `ElixirScript`'s compile functions +- Syntax once supported by Elixirscript `JQuery.("#element")`, is no longer supported ### Changed - [Changed CHANGELOG.md to adhere the format from Keep a Changelog](https://github.com/bryanjos/elixirscript/pull/205) - `defmacro` now supported. No longer have to separate macros from functions in separate files. `defmacrop` still unsupported -- Elixirscript files must now be valid Elixir syntax. Syntax once supported by Elixirscript `JQuery.("#element")`, is no longer supported -- Now compiles `exjs` and `ex` files within the path can be compiled all the same. Dependencies from hex are still unsupported so these files must not rely on any code outside of the path. What this does mean is that it is now possible to share code between Elixir and Elixirscript as long as the Elixir files functionality fall within what Elixirscript currently supports. - To use anything in the `JS` module, you must `require` the `JS` module first +- Elixirscript files must now contain valid Elixir syntax. +- Now compiles `exjs` and `ex` files within the path can be compiled all the same. Dependencies from hex are still unsupported so these files must not rely on any code outside of the path. What this does mean is that it is now possible to share code between Elixir and Elixirscript as long as the Elixir files functionality fall within what Elixirscript currently supports. - `defgen`, `defgenp`, `yield`, `yield_to`, and `object` are now in the `JS` module - To access functions in the global JavaScript scope, either use `JS.global\0` or use the erlang module call syntax ```elixir From 29ea4f00d37f8d58bee52e7c903859b2e1335bc5 Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Sun, 13 Nov 2016 09:02:37 -0600 Subject: [PATCH 337/860] Removed unused aliases --- lib/elixir_script.ex | 5 ----- 1 file changed, 5 deletions(-) diff --git a/lib/elixir_script.ex b/lib/elixir_script.ex index e798b4a3..a361f496 100644 --- a/lib/elixir_script.ex +++ b/lib/elixir_script.ex @@ -1,9 +1,4 @@ defmodule ElixirScript do - alias ESTree.Tools.Builder - alias ESTree.Tools.Generator - alias ElixirScript.Translator.Utils - alias ElixirScript.Compiler.Cache - alias ElixirScript.Compiler.Output require Logger @moduledoc """ From 5a434c114e1804caba0efd038bddc5580f788c27 Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Mon, 14 Nov 2016 20:21:05 -0600 Subject: [PATCH 338/860] Updated serialization code to not cache javascript ast and code --- lib/elixir_script.ex | 3 +-- lib/elixir_script/passes/java_script_ast.ex | 2 +- lib/elixir_script/translator/state.ex | 12 ++++++++++++ 3 files changed, 14 insertions(+), 3 deletions(-) diff --git a/lib/elixir_script.ex b/lib/elixir_script.ex index a361f496..bc3ddefa 100644 --- a/lib/elixir_script.ex +++ b/lib/elixir_script.ex @@ -15,7 +15,6 @@ defmodule ElixirScript do * `:include_path` - a boolean controlling whether to return just the JavaScript code or a tuple of the file name and the JavaScript code * `:root` - a binary path prepended to the path of the standard lib imports if needed - env has the macros imported or required. * `:core_path` - The es6 import path used to import the elixirscript core. When using this option, the Elixir.js file is not exported * `:full_build` - For compile_path, tells the compiler to perform a full build instead of incremental one @@ -45,7 +44,7 @@ defmodule ElixirScript do @external_resource stdlib_state_path = Path.join([__DIR__, "elixir_script", "translator", "stdlib_state.bin"]) @stdlib_state File.read(stdlib_state_path) @lib_path Application.get_env(:elixir_script, :lib_path) - @version Mix.Project.config[:version] + @version Mix.Project.config[:version] @doc """ Compiles the given Elixir code string diff --git a/lib/elixir_script/passes/java_script_ast.ex b/lib/elixir_script/passes/java_script_ast.ex index 40fd60f3..e08e03f6 100644 --- a/lib/elixir_script/passes/java_script_ast.ex +++ b/lib/elixir_script/passes/java_script_ast.ex @@ -9,7 +9,7 @@ defmodule ElixirScript.Passes.JavaScriptAST do parent = self - data = compiler_data.data + data = State.get_module_data() |> Enum.map(fn({module_name, module_data}) -> spawn_link fn -> diff --git a/lib/elixir_script/translator/state.ex b/lib/elixir_script/translator/state.ex index b51bf5b6..bbd56fdb 100644 --- a/lib/elixir_script/translator/state.ex +++ b/lib/elixir_script/translator/state.ex @@ -17,7 +17,19 @@ defmodule ElixirScript.Translator.State do def serialize() do Agent.get(__MODULE__, fn(state) -> + modules = state.modules + modules = Enum.map(modules, fn {m, d} -> + d = Map.delete(d, :javascript_ast) + |> Map.delete(:javascript_code) + |> Map.delete(:javascript_name) + + {m, d} + end) + |> Enum.filter(fn {_, d} -> d.type != :consolidated end) + state = Map.delete(state, :changed_modules) + |> Map.put(:modules, modules) + :erlang.term_to_binary(state) end) end From b0a11a13d41af1df9983fb20e53355fb44eb1c96 Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Mon, 14 Nov 2016 20:45:02 -0600 Subject: [PATCH 339/860] Remove root option --- CHANGELOG.md | 2 +- lib/elixir_script.ex | 1 - lib/elixir_script/cli.ex | 16 +++++----------- 3 files changed, 6 insertions(+), 13 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 04f5a13c..1a90699f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -22,7 +22,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/). ### Removed - The form of `JS.import` that accepted a list of atoms as the first arg. Used `JS.import\3` with `default: false` instead to create a namespace import -- `env` is no longer an option for `ElixirScript`'s compile functions +- `env` and `root` are no longer options for `ElixirScript`'s compile functions and cli - Syntax once supported by Elixirscript `JQuery.("#element")`, is no longer supported ### Changed diff --git a/lib/elixir_script.ex b/lib/elixir_script.ex index bc3ddefa..4751c447 100644 --- a/lib/elixir_script.ex +++ b/lib/elixir_script.ex @@ -14,7 +14,6 @@ defmodule ElixirScript do Available options are: * `:include_path` - a boolean controlling whether to return just the JavaScript code or a tuple of the file name and the JavaScript code - * `:root` - a binary path prepended to the path of the standard lib imports if needed * `:core_path` - The es6 import path used to import the elixirscript core. When using this option, the Elixir.js file is not exported * `:full_build` - For compile_path, tells the compiler to perform a full build instead of incremental one diff --git a/lib/elixir_script/cli.ex b/lib/elixir_script/cli.ex index b4cb3aa1..af2efbfc 100644 --- a/lib/elixir_script/cli.ex +++ b/lib/elixir_script/cli.ex @@ -4,13 +4,14 @@ defmodule ElixirScript.CLI do @app_version Mix.Project.config()[:version] @switches [ - output: :binary, elixir: :boolean, root: :binary, - help: :boolean, core_path: :binary, std_lib: :binary, - full_build: :boolean, version: :boolean, watch: :boolean + output: :binary, elixir: :boolean, + help: :boolean, core_path: :binary, + full_build: :boolean, version: :boolean, + watch: :boolean ] @aliases [ - o: :output, ex: :elixir, h: :help, r: :root, v: :version + o: :output, ex: :elixir, h: :help, v: :version ] def main(argv) do @@ -39,8 +40,6 @@ defmodule ElixirScript.CLI do options: -o --output [path] places output at the given path -ex --elixir read input as elixir code string - -r --root [path] root import path for all exported modules - --std-lib [path] outputs the elixirscript standard library JavaScript files to the specified path --full-build informs the compiler to do a full build instead of an incremental one only used when output is specified --core-path es6 import path to the elixirscript standard lib @@ -58,10 +57,6 @@ defmodule ElixirScript.CLI do IO.write @app_version end - def process([std_lib: path]) do - ElixirScript.copy_stdlib_to_destination(path) - end - def process({ input, options }) do if options_contains_unknown_values(options) do process(:help) @@ -74,7 +69,6 @@ defmodule ElixirScript.CLI do {watch, options} = Keyword.pop(options, :watch, false) compile_opts = %{ - root: options[:root], include_path: true, core_path: Keyword.get(options, :core_path, "Elixir.Bootstrap"), full_build: Keyword.get(options, :full_build, false), From 7a1d1a0791330775b9b6ffc25f58225394b4e108 Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Tue, 15 Nov 2016 16:50:53 -0600 Subject: [PATCH 340/860] Changes to documentation --- CONTRIBUTING.md | 4 +- FAQ.md | 25 ++--- GettingStarted.md | 98 +++++++++---------- lib/elixir_script/module_systems.ex | 2 +- lib/elixir_script/module_systems/common.ex | 1 + lib/elixir_script/module_systems/es6.ex | 1 + lib/elixir_script/passes/add_std_lib.ex | 1 + lib/elixir_script/passes/ast_from_file.ex | 2 +- .../passes/consolidate_protocols.ex | 1 + lib/elixir_script/passes/deps_paths.ex | 2 +- .../passes/find_changed_files.ex | 2 +- lib/elixir_script/passes/find_deps.ex | 2 +- lib/elixir_script/passes/find_functions.ex | 1 + lib/elixir_script/passes/find_modules.ex | 2 +- lib/elixir_script/passes/handle_output.ex | 1 + lib/elixir_script/passes/init.ex | 1 + lib/elixir_script/passes/java_script_ast.ex | 1 + lib/elixir_script/passes/java_script_code.ex | 1 + lib/elixir_script/passes/java_script_name.ex | 1 + lib/elixir_script/passes/load_modules.ex | 2 +- lib/elixir_script/passes/remove_unused.ex | 2 +- lib/elixir_script/passes/write_cache.ex | 1 + lib/elixir_script/prelude/agent.ex | 1 + lib/elixir_script/prelude/atom.ex | 1 + lib/elixir_script/prelude/base.ex | 1 + lib/elixir_script/prelude/bitwise.ex | 2 +- lib/elixir_script/prelude/collectable.ex | 1 + lib/elixir_script/prelude/enumerable.ex | 1 + lib/elixir_script/prelude/integer.ex | 2 +- lib/elixir_script/prelude/js.ex | 21 +++- lib/elixir_script/prelude/kernel.ex | 1 + lib/elixir_script/prelude/keyword.ex | 3 +- lib/elixir_script/prelude/list.ex | 1 + lib/elixir_script/prelude/macro/env.ex | 2 + lib/elixir_script/prelude/map.ex | 3 +- lib/elixir_script/prelude/map_set.ex | 2 +- lib/elixir_script/prelude/process.ex | 2 +- lib/elixir_script/prelude/range.ex | 1 + lib/elixir_script/prelude/string.ex | 1 + lib/elixir_script/prelude/string/chars.ex | 1 + lib/elixir_script/prelude/tuple.ex | 1 + lib/elixir_script/translator.ex | 5 +- .../translator/kernel/defimpl.ex | 1 + lib/elixir_script/translator/rewriter.ex | 1 + 44 files changed, 122 insertions(+), 87 deletions(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index ae6315ab..b83cdf14 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -75,8 +75,6 @@ The standard library modules are in the `lib/elixir_script/prelude` folder. The JavaScript code is in the `src/javascript`. This is where features such as pattern matching and the standard library are implemented. -Please look at [this issue](https://github.com/bryanjos/elixirscript/issues/143) for information on how to add modules to the standard library. - The ElixirScript tests can be run using `mix test` The JavaScript tests can be run using `npm test` @@ -152,7 +150,7 @@ in order to craft an excellent pull request: ```sh mix test - gulp test + npm test ``` This is needed to ensure your changes can diff --git a/FAQ.md b/FAQ.md index 09d31ff2..cfb7df3a 100644 --- a/FAQ.md +++ b/FAQ.md @@ -1,5 +1,9 @@ # FAQ +# Q. How do I get started? + +### A. Check out the [Getting Started](GettingStarted.md) Guide for more info. + # Q. How much is implemented? ### A. Most of Kernel.SpecialForms as well as some modules in the Standard Library @@ -37,16 +41,16 @@ The compiler to this point has been focused on translating Kernel.SpecialForms a * Missing * `super(args)` - * `receive` * Caveats - * `quote` - ignores `location` and `context` options + * `quote` - ignores `context` options * `left = right` does not support full unification yet. ```elixir a = 1 # works as expected 1 = a # may not work currently, but in some cases it will ``` + * `send` and `receive` only work on functions defined with `defgen` or `defgenp` #### Completed Modules @@ -77,9 +81,9 @@ The compiler to this point has been focused on translating Kernel.SpecialForms a ## Q. Can I use it today? -### A. Yes, but don't expect it to be pretty or idiomatic. Also it is not production ready. +### A. Yes, but realize this is not at 1.0 yet. -You **can** use ElixirScript on your front ends and have it work and interoperate with JavaScript modules. The problem is since most of the standard library is incomplete, it will not feel the same. It will feel like some weird hybrid of Elixir and JavaScript. That is not the goal of the project. The end goal is to have it look and feel like Elixir code with the added availability of JavaScript modules. +You **can** use ElixirScript on your front ends and have it work and interoperate with JavaScript modules. The problem is since most of the standard library is incomplete. ## Q. Can I use pattern matching? @@ -87,17 +91,8 @@ You **can** use ElixirScript on your front ends and have it work and interoperat ## Q. Can I use processes? -### A. No, but follow [this issue](https://github.com/bryanjos/elixirscript/issues/99). Any ideas or contributions are appreciated. - - -## Q. Will it be able to do the things that Elm can? - -### A. Maybe, but in an idiomatic fashion. - -One of my demos is an example of using a design similar to redux to accomplish the things that redux does only using the Elixir standard library. Redux is influenced by Elm. The goal is to eventually allow for designs that can be Elm influenced if that is the desire. Similar to the same way the José says to bring the spirit of projects from other languages to Elixir and not always just a straight port. If processes are added, I believe it will be easier to do those things in an idiomatic Elixir way. +### A. Yes, with some caveats as mentioned above. Only current works with functions defined with `defgen` or `defgenp` ## Q. What about OTP? -### A. Maybe. - -Once processes are added, then we can see about adding OTP similar or specific things to ElixirScript. +### A. Not yet. Maybe never. diff --git a/GettingStarted.md b/GettingStarted.md index 03bc6869..4280d1fa 100644 --- a/GettingStarted.md +++ b/GettingStarted.md @@ -36,7 +36,6 @@ The intent of this guide is to get you started with ElixirScript. It will give y options: -o --output [path] places output at the given path -ex --elixir read input as elixir code string - -r --root [path] root import path for all exported modules --std-lib [path] outputs the elixirscript standard library JavaScript files to the specified path --full-build informs the compiler to do a full build instead of an incremental one only used when output is specified @@ -55,48 +54,13 @@ The intent of this guide is to get you started with ElixirScript. It will give y The elixirscript escript changed the elixir code, `:atom` into the JavaScript code `Symbol.for('atom')`. The `-ex` parameter lets the script know that the input is an Elixir code string instead of a file. - What if we wanted to give it a file? You would simply do the following: - - ```bash - $ elixirscript "example.exjs" - Symbol.for('atom') - ``` - - **NOTE**: ElixirScript files must have the extension, `.exjs` - - What you will have noticed by now is that it has output everything we've done so far to the terminal. What about if we want to place the output to a path? The next example takes a file as input and outputs the result in another directory. - - ```bash - $ elixirscript "example.exjs" -o "dist" - ``` - - If you look in the dist folder, you should see example.js as well as elixir.js. elixir.js is the JavaScript file that contains the Elixir Standard library. In example.js, the first line should be an import statement importing elixir.js for use. - - wildcards are also accepted: + elixirscript also takes a path to your `.ex` and `.exjs` files as well: ```bash $ elixirscript "src" -o "dist" ``` - The last option we will show is the root option. This option is for defining a root path for the import statements. By default your import statement will not have anything prepended to it. For example, the elixir import will look like this: - - ```javascript - import * as Elixir from 'elixir'; - ``` - - If we wanted to prepend "js" to the root, we can like this: - - ``` - $ elixirscript "example.exjs" -o "dist" -r "js" - ``` - - Now the import will look like this: - - ```javascript - import * as Elixir from 'js/elixir'; - ``` - - That concludes the walkthrough on options, as well as the walkthrough on using the elixirscript escript. + If you look in the dist folder, you should see 2 folders. One, `app`, contains your code and the other, `elixir` contains the elixirscript standard library files. ### mix elixirscript @@ -105,7 +69,7 @@ The intent of this guide is to get you started with ElixirScript. It will give y The first step is getting the dependency. In your mix.exs file for your elixir project, add elixir_script to your deps. ```elixir - {:elixir_script, "~> 0.18"} + {:elixir_script, "~> 0.23"} ``` * Step 2: Now download the dep @@ -118,7 +82,7 @@ The intent of this guide is to get you started with ElixirScript. It will give y * Step 3: Use ```bash - $ mix elixirscript "example.exjs" -o "dist" -r "js" + $ mix elixirscript "src" -o "dist" ``` What you will notice is that the parameters are exactly the same as the escript. @@ -129,7 +93,7 @@ The intent of this guide is to get you started with ElixirScript. It will give y The first step is getting the dependency. In your mix.exs file for your elixir project, add elixir_script to your deps. ```elixir - {:elixir_script, "~> 0.22"} + {:elixir_script, "~> 0.23"} ``` * Step 2: Now download the dep @@ -149,27 +113,61 @@ The intent of this guide is to get you started with ElixirScript. It will give y ### Macros -Macros must be defined in either a `.ex` or `.exs` file. These will be loaded at compile time and -whenever an import or require expression is found, if the module specified is loaded, it will use it to expand macros within the lexical scope. +Macros can be used in Elixirscript just like in Elixir. The only exception is that `defmacrop` is unsupported + + +#### JavaScript Interop + +Elixirscript has a couple of ways of interacting with JavaScript. + +#### Globally scoped functions + +To call functions in JavaScript in the global scope, such as those defined on `window`, use the erlang module syntax + +```elixir +# Calling alert +:window.alert("hi") +# console +:console.log("hello") -### Appendix +# document +:document.getElementById("main") +``` + +#### Globally scoped modules + +To call globally scoped modules defined in JavaScript, you can call them just like you would an Elixir module -#### Using JavaScript Modules +```elixir +Date.now() +``` -You can use `alias`, `import`, and `require` as you would in Elixir. +Only works if module begins with a captial letter -For JavaScript modules, you use must `JS.import` +#### Importing ES Modules + +To import ES modules, first you must require the `JS` module. Then import the module using `JS.import` ```elixir -JS.import A, "a" #translates to "import {default as A} from 'a'" +defmodule MyModule do + require JS + JS.import React, "react" + + def func() do + React.render(my_component) + end +end -JS.import [A, B, C], "a" #translates to "import {A, B, C} from 'a'" ``` +#### The JS module + +The JS module has a number of other functions and macros. For more information, check out the docs. + #### Frontend Project Boilerplate -There is an [elixirscript frontend boilerplate project](https://github.com/bryanjos/elixirscript-project-boilerplate). This setup uses gulp and brunch to build and bundle assets. +There is an [elixirscript frontend boilerplate project](https://github.com/bryanjos/elixirscript-project-boilerplate). This setup uses gulp and webpack to build and bundle assets. #### ElixirScript-Brunch diff --git a/lib/elixir_script/module_systems.ex b/lib/elixir_script/module_systems.ex index 6d2b3db6..c25968f9 100644 --- a/lib/elixir_script/module_systems.ex +++ b/lib/elixir_script/module_systems.ex @@ -1,5 +1,5 @@ defmodule ElixirScript.ModuleSystems do - + @moduledoc false defp module_system() do ElixirScript.ModuleSystems.ES6 end diff --git a/lib/elixir_script/module_systems/common.ex b/lib/elixir_script/module_systems/common.ex index 7f1cc5c9..46798e29 100644 --- a/lib/elixir_script/module_systems/common.ex +++ b/lib/elixir_script/module_systems/common.ex @@ -1,4 +1,5 @@ defmodule ElixirScript.ModuleSystems.Common do + @moduledoc false alias ESTree.Tools.Builder, as: JS alias ElixirScript.Translator diff --git a/lib/elixir_script/module_systems/es6.ex b/lib/elixir_script/module_systems/es6.ex index cd50e3bb..1398d1a5 100644 --- a/lib/elixir_script/module_systems/es6.ex +++ b/lib/elixir_script/module_systems/es6.ex @@ -1,4 +1,5 @@ defmodule ElixirScript.ModuleSystems.ES6 do + @moduledoc false alias ESTree.Tools.Builder, as: JS alias ElixirScript.Translator diff --git a/lib/elixir_script/passes/add_std_lib.ex b/lib/elixir_script/passes/add_std_lib.ex index 05b5672e..2cb7a127 100644 --- a/lib/elixir_script/passes/add_std_lib.ex +++ b/lib/elixir_script/passes/add_std_lib.ex @@ -1,4 +1,5 @@ defmodule ElixirScript.Passes.AddStdLib do + @moduledoc false alias ElixirScript.Translator.State def execute(compiler_data, _) do diff --git a/lib/elixir_script/passes/ast_from_file.ex b/lib/elixir_script/passes/ast_from_file.ex index 969aee69..24e656bf 100644 --- a/lib/elixir_script/passes/ast_from_file.ex +++ b/lib/elixir_script/passes/ast_from_file.ex @@ -1,5 +1,5 @@ defmodule ElixirScript.Passes.ASTFromFile do - + @moduledoc false def execute(compiler_data, opts) do data = Enum.reduce(compiler_data.data, [], fn({dep, paths}, list) -> diff --git a/lib/elixir_script/passes/consolidate_protocols.ex b/lib/elixir_script/passes/consolidate_protocols.ex index 8691410e..26b0818e 100644 --- a/lib/elixir_script/passes/consolidate_protocols.ex +++ b/lib/elixir_script/passes/consolidate_protocols.ex @@ -1,4 +1,5 @@ defmodule ElixirScript.Passes.ConsolidateProtocols do + @moduledoc false alias ESTree.Tools.Builder, as: JS alias ElixirScript.Translator.Utils alias ElixirScript.ModuleSystems diff --git a/lib/elixir_script/passes/deps_paths.ex b/lib/elixir_script/passes/deps_paths.ex index a49640bb..b0dac9b1 100644 --- a/lib/elixir_script/passes/deps_paths.ex +++ b/lib/elixir_script/passes/deps_paths.ex @@ -1,5 +1,5 @@ defmodule ElixirScript.Passes.DepsPaths do - + @moduledoc false def execute(compiler_data, opts) do data = [{opts[:app], List.wrap(compiler_data.path)}] Map.put(compiler_data, :data, data) diff --git a/lib/elixir_script/passes/find_changed_files.ex b/lib/elixir_script/passes/find_changed_files.ex index 74eb960b..cacff587 100644 --- a/lib/elixir_script/passes/find_changed_files.ex +++ b/lib/elixir_script/passes/find_changed_files.ex @@ -1,5 +1,5 @@ defmodule ElixirScript.Passes.FindChangedFiles do - + @moduledoc false alias ElixirScript.Compiler.Cache alias ElixirScript.Translator.State @version Mix.Project.config[:version] diff --git a/lib/elixir_script/passes/find_deps.ex b/lib/elixir_script/passes/find_deps.ex index 288e244e..c3f379aa 100644 --- a/lib/elixir_script/passes/find_deps.ex +++ b/lib/elixir_script/passes/find_deps.ex @@ -1,5 +1,5 @@ defmodule ElixirScript.Passes.FindDeps do - + @moduledoc false alias ElixirScript.Translator.Utils def execute(compiler_data, _) do diff --git a/lib/elixir_script/passes/find_functions.ex b/lib/elixir_script/passes/find_functions.ex index 0d4cddaf..d4ca8581 100644 --- a/lib/elixir_script/passes/find_functions.ex +++ b/lib/elixir_script/passes/find_functions.ex @@ -1,4 +1,5 @@ defmodule ElixirScript.Passes.FindFunctions do + @moduledoc false @function_types [:def, :defp, :defgen, :defgenp, :defmacro, :defmacrop] def execute(data, _) do diff --git a/lib/elixir_script/passes/find_modules.ex b/lib/elixir_script/passes/find_modules.ex index 6eaedb65..f1f58844 100644 --- a/lib/elixir_script/passes/find_modules.ex +++ b/lib/elixir_script/passes/find_modules.ex @@ -1,5 +1,5 @@ defmodule ElixirScript.Passes.FindModules do - + @moduledoc false alias ElixirScript.Translator.Utils alias ElixirScript.Translator.State diff --git a/lib/elixir_script/passes/handle_output.ex b/lib/elixir_script/passes/handle_output.ex index 7589a62a..d197bf9e 100644 --- a/lib/elixir_script/passes/handle_output.ex +++ b/lib/elixir_script/passes/handle_output.ex @@ -1,4 +1,5 @@ defmodule ElixirScript.Passes.HandleOutput do + @moduledoc false alias ElixirScript.Translator.State def execute(compiler_data, opts) do diff --git a/lib/elixir_script/passes/init.ex b/lib/elixir_script/passes/init.ex index 6538e2d4..7f30662b 100644 --- a/lib/elixir_script/passes/init.ex +++ b/lib/elixir_script/passes/init.ex @@ -1,4 +1,5 @@ defmodule ElixirScript.Passes.Init do + @moduledoc false alias ElixirScript.Translator.State def execute(compiler_data, opts) do diff --git a/lib/elixir_script/passes/java_script_ast.ex b/lib/elixir_script/passes/java_script_ast.ex index e08e03f6..8c4069bd 100644 --- a/lib/elixir_script/passes/java_script_ast.ex +++ b/lib/elixir_script/passes/java_script_ast.ex @@ -1,4 +1,5 @@ defmodule ElixirScript.Passes.JavaScriptAST do + @moduledoc false alias ElixirScript.Translator.Utils alias ElixirScript.Translator.State diff --git a/lib/elixir_script/passes/java_script_code.ex b/lib/elixir_script/passes/java_script_code.ex index 47c350bd..c9f5ca5f 100644 --- a/lib/elixir_script/passes/java_script_code.ex +++ b/lib/elixir_script/passes/java_script_code.ex @@ -1,4 +1,5 @@ defmodule ElixirScript.Passes.JavaScriptCode do + @moduledoc false alias ESTree.Tools.{ Builder, Generator } def execute(compiler_data, _) do diff --git a/lib/elixir_script/passes/java_script_name.ex b/lib/elixir_script/passes/java_script_name.ex index 21f2df08..c5881810 100644 --- a/lib/elixir_script/passes/java_script_name.ex +++ b/lib/elixir_script/passes/java_script_name.ex @@ -1,4 +1,5 @@ defmodule ElixirScript.Passes.JavaScriptName do + @moduledoc false alias ElixirScript.Translator.Utils def execute(compiler_data, _) do diff --git a/lib/elixir_script/passes/load_modules.ex b/lib/elixir_script/passes/load_modules.ex index 7ed10641..fe1e9704 100644 --- a/lib/elixir_script/passes/load_modules.ex +++ b/lib/elixir_script/passes/load_modules.ex @@ -1,5 +1,5 @@ defmodule ElixirScript.Passes.LoadModules do - + @moduledoc false def execute(compiler_data, _) do ex_files = Enum.map(compiler_data.data, fn diff --git a/lib/elixir_script/passes/remove_unused.ex b/lib/elixir_script/passes/remove_unused.ex index 633cbc97..5182adcc 100644 --- a/lib/elixir_script/passes/remove_unused.ex +++ b/lib/elixir_script/passes/remove_unused.ex @@ -1,5 +1,5 @@ defmodule ElixirScript.Passes.RemoveUnused do - + @moduledoc false def execute(compiler_data, opts) do data = Enum.filter(compiler_data.data, fn({module_name, _}) -> module_found_in_deps(module_name, compiler_data.data, [opts[:app]]) == true diff --git a/lib/elixir_script/passes/write_cache.ex b/lib/elixir_script/passes/write_cache.ex index a624e629..d52a6d20 100644 --- a/lib/elixir_script/passes/write_cache.ex +++ b/lib/elixir_script/passes/write_cache.ex @@ -1,4 +1,5 @@ defmodule ElixirScript.Passes.WriteCache do + @moduledoc false alias ElixirScript.Compiler.Cache alias ElixirScript.Translator.State diff --git a/lib/elixir_script/prelude/agent.ex b/lib/elixir_script/prelude/agent.ex index ce2dcdde..29d2d533 100644 --- a/lib/elixir_script/prelude/agent.ex +++ b/lib/elixir_script/prelude/agent.ex @@ -1,4 +1,5 @@ defmodule ElixirScript.Agent do + @moduledoc false def start(fun, options \\ []) do pid = spawn(fn() -> Process.sleep(:infinity) end) diff --git a/lib/elixir_script/prelude/atom.ex b/lib/elixir_script/prelude/atom.ex index 13929c47..f932c1d2 100644 --- a/lib/elixir_script/prelude/atom.ex +++ b/lib/elixir_script/prelude/atom.ex @@ -1,4 +1,5 @@ defmodule ElixirScript.Atom do + @moduledoc false import Kernel, except: [to_string: 1] def to_char_list(atom) do diff --git a/lib/elixir_script/prelude/base.ex b/lib/elixir_script/prelude/base.ex index 0ec26036..a3851f33 100644 --- a/lib/elixir_script/prelude/base.ex +++ b/lib/elixir_script/prelude/base.ex @@ -1,4 +1,5 @@ defmodule ElixirScript.Base do + @moduledoc false def encode64(data) do Elixir.Core.b64EncodeUnicode(data) diff --git a/lib/elixir_script/prelude/bitwise.ex b/lib/elixir_script/prelude/bitwise.ex index 06fa0064..9775f36b 100644 --- a/lib/elixir_script/prelude/bitwise.ex +++ b/lib/elixir_script/prelude/bitwise.ex @@ -1,5 +1,5 @@ defmodule ElixirScript.Bitwise do - + @moduledoc false defmacro bnot(expr) do quote do Elixir.Core.bnot(unquote(expr)) diff --git a/lib/elixir_script/prelude/collectable.ex b/lib/elixir_script/prelude/collectable.ex index 66990821..339b17ce 100644 --- a/lib/elixir_script/prelude/collectable.ex +++ b/lib/elixir_script/prelude/collectable.ex @@ -1,3 +1,4 @@ defprotocol ElixirScript.Collectable do + @moduledoc false def into(collectable) end diff --git a/lib/elixir_script/prelude/enumerable.ex b/lib/elixir_script/prelude/enumerable.ex index ab04c59b..3fbba469 100644 --- a/lib/elixir_script/prelude/enumerable.ex +++ b/lib/elixir_script/prelude/enumerable.ex @@ -1,4 +1,5 @@ defprotocol ElixirScript.Enumerable do + @moduledoc false def reduce(enumerable, acc, fun) def member?(enumerable, element) def count(enumerable) diff --git a/lib/elixir_script/prelude/integer.ex b/lib/elixir_script/prelude/integer.ex index 97c7a7ed..5ef4415e 100644 --- a/lib/elixir_script/prelude/integer.ex +++ b/lib/elixir_script/prelude/integer.ex @@ -1,5 +1,5 @@ defmodule ElixirScript.Integer do - + @moduledoc false def is_even(number) do rem(number, 2) == 0 end diff --git a/lib/elixir_script/prelude/js.ex b/lib/elixir_script/prelude/js.ex index 47433486..0706647e 100644 --- a/lib/elixir_script/prelude/js.ex +++ b/lib/elixir_script/prelude/js.ex @@ -73,23 +73,42 @@ defmodule JS do Elixir.Core.Functions.get_global() end + @doc """ + Defines a generator. This is compiled into a generator function in JavaScript. + defgen and defgenp are currently the only ways to use process in Elixirscript right now. + """ defmacro defgen(call, expr \\ nil) do end + @doc """ + Defines a private generator. This is compiled into a generator function in JavaScript. + """ defmacro defgenp(call, expr \\ nil) do end + @doc """ + Determines if term is a generator + """ def is_generator(term) do term.constructor.name === "GeneratorFunction" end + @doc """ + Yields the current generator function + """ defmacro yield() do end + @doc """ + Yields the current generator function with the given term + """ defmacro yield(term) do end - defmacro yield_to(term) do + @doc """ + Yields control to the given generator + """ + defmacro yield_to(gen) do end @doc """ diff --git a/lib/elixir_script/prelude/kernel.ex b/lib/elixir_script/prelude/kernel.ex index 12e9c20a..60128d88 100644 --- a/lib/elixir_script/prelude/kernel.ex +++ b/lib/elixir_script/prelude/kernel.ex @@ -1,4 +1,5 @@ defmodule ElixirScript.Kernel do + @moduledoc false import Kernel, only: [defmodule: 2, def: 1, def: 2, defp: 2, defmacro: 1, defmacro: 2, defmacrop: 2, ||: 2, !: 1, ++: 2, in: 2, &&: 2, ===: 2, @: 1] require JS diff --git a/lib/elixir_script/prelude/keyword.ex b/lib/elixir_script/prelude/keyword.ex index 22247563..c08c71b1 100644 --- a/lib/elixir_script/prelude/keyword.ex +++ b/lib/elixir_script/prelude/keyword.ex @@ -1,5 +1,6 @@ defmodule ElixirScript.Keyword do - + @moduledoc false + def has_key?(kw, key) do do_has_key?(kw, key) end diff --git a/lib/elixir_script/prelude/list.ex b/lib/elixir_script/prelude/list.ex index 441f2373..962c224c 100644 --- a/lib/elixir_script/prelude/list.ex +++ b/lib/elixir_script/prelude/list.ex @@ -1,4 +1,5 @@ defmodule ElixirScript.List do + @moduledoc false require JS def duplicate(data, size) do diff --git a/lib/elixir_script/prelude/macro/env.ex b/lib/elixir_script/prelude/macro/env.ex index 896f3e75..1528e2c8 100644 --- a/lib/elixir_script/prelude/macro/env.ex +++ b/lib/elixir_script/prelude/macro/env.ex @@ -1,4 +1,6 @@ defmodule ElixirScript.Macro.Env do + @moduledoc false + @type t :: %ElixirScript.Macro.Env{ module: atom, file: binary, diff --git a/lib/elixir_script/prelude/map.ex b/lib/elixir_script/prelude/map.ex index 0cdceb13..6edcf85c 100644 --- a/lib/elixir_script/prelude/map.ex +++ b/lib/elixir_script/prelude/map.ex @@ -1,5 +1,6 @@ defmodule ElixirScript.Map do - + @moduledoc false + def new() do %{} end diff --git a/lib/elixir_script/prelude/map_set.ex b/lib/elixir_script/prelude/map_set.ex index 52e5e35b..a22fe57b 100644 --- a/lib/elixir_script/prelude/map_set.ex +++ b/lib/elixir_script/prelude/map_set.ex @@ -1,5 +1,5 @@ defmodule ElixirScript.MapSet do - + @moduledoc false defstruct set: [] def new() do diff --git a/lib/elixir_script/prelude/process.ex b/lib/elixir_script/prelude/process.ex index cef9db6d..df873d20 100644 --- a/lib/elixir_script/prelude/process.ex +++ b/lib/elixir_script/prelude/process.ex @@ -1,5 +1,5 @@ defmodule ElixirScript.Process do - + @moduledoc false def alive?(pid) do Elixir.Core.processes.is_alive(pid) end diff --git a/lib/elixir_script/prelude/range.ex b/lib/elixir_script/prelude/range.ex index 5e64017a..9ae8bffe 100644 --- a/lib/elixir_script/prelude/range.ex +++ b/lib/elixir_script/prelude/range.ex @@ -1,4 +1,5 @@ defmodule ElixirScript.Range do + @moduledoc false defstruct first: nil, last: nil def new(first, last) do diff --git a/lib/elixir_script/prelude/string.ex b/lib/elixir_script/prelude/string.ex index 8ce8ebe2..e76d72a6 100644 --- a/lib/elixir_script/prelude/string.ex +++ b/lib/elixir_script/prelude/string.ex @@ -1,4 +1,5 @@ defmodule ElixirScript.String do + @moduledoc false import Kernel, except: [length: 1] def to_atom(str) do diff --git a/lib/elixir_script/prelude/string/chars.ex b/lib/elixir_script/prelude/string/chars.ex index 50e12fcd..ae5d0227 100644 --- a/lib/elixir_script/prelude/string/chars.ex +++ b/lib/elixir_script/prelude/string/chars.ex @@ -1,4 +1,5 @@ defprotocol ElixirScript.String.Chars do + @moduledoc false def to_string(item) end diff --git a/lib/elixir_script/prelude/tuple.ex b/lib/elixir_script/prelude/tuple.ex index c803f4d8..cdd7b765 100644 --- a/lib/elixir_script/prelude/tuple.ex +++ b/lib/elixir_script/prelude/tuple.ex @@ -1,4 +1,5 @@ defmodule ElixirScript.Tuple do + @moduledoc false require JS def duplicate(data, size) do diff --git a/lib/elixir_script/translator.ex b/lib/elixir_script/translator.ex index 26d43edd..71095ac3 100644 --- a/lib/elixir_script/translator.ex +++ b/lib/elixir_script/translator.ex @@ -1,8 +1,5 @@ defmodule ElixirScript.Translator do - @moduledoc """ - Translates the given Elixir AST into - JavaScript AST. - """ + @moduledoc false alias ElixirScript.Translator.Primitive alias ElixirScript.Translator.Identifier alias ElixirScript.Translator.Expression diff --git a/lib/elixir_script/translator/kernel/defimpl.ex b/lib/elixir_script/translator/kernel/defimpl.ex index 79ed8569..996ca689 100644 --- a/lib/elixir_script/translator/kernel/defimpl.ex +++ b/lib/elixir_script/translator/kernel/defimpl.ex @@ -1,4 +1,5 @@ defmodule ElixirScript.Translator.Defimpl do + @moduledoc false alias ESTree.Tools.Builder, as: JS alias ElixirScript.Translator.Defmodule diff --git a/lib/elixir_script/translator/rewriter.ex b/lib/elixir_script/translator/rewriter.ex index ff3ff8db..5039fe0a 100644 --- a/lib/elixir_script/translator/rewriter.ex +++ b/lib/elixir_script/translator/rewriter.ex @@ -1,4 +1,5 @@ defmodule ElixirScript.Translator.Rewriter do + @moduledoc false # :erlang, :lists, :maps, :beam_lib, :binary, :calendar, :digraph, # :epp, :erl_lint, :erl_internal, :erl_expand_records, :erl_eval, From e0cd65e2e8f35abf26d4c1f7a1e68c9d32ec3e42 Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Tue, 15 Nov 2016 16:53:31 -0600 Subject: [PATCH 341/860] rename OSX to macOS --- GettingStarted.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/GettingStarted.md b/GettingStarted.md index 4280d1fa..fb3a11fa 100644 --- a/GettingStarted.md +++ b/GettingStarted.md @@ -9,7 +9,7 @@ The intent of this guide is to get you started with ElixirScript. It will give y ### Escript -**OSX**: Elixirscript can be installed via homebrew `brew install elixirscript`. For everyone else, plase read below +**macOS**: Elixirscript can be installed via homebrew `brew install elixirscript`. For everyone else, plase read below * Step 1: Get escript From 79dd1851b56f8316c7491ad0691ccb0d2a2f862a Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Tue, 15 Nov 2016 16:55:10 -0600 Subject: [PATCH 342/860] Get link to getting started to work in docs --- FAQ.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/FAQ.md b/FAQ.md index cfb7df3a..50a7dcc8 100644 --- a/FAQ.md +++ b/FAQ.md @@ -2,7 +2,7 @@ # Q. How do I get started? -### A. Check out the [Getting Started](GettingStarted.md) Guide for more info. +### A. Check out the [Getting Started](GettingStarted.html) Guide for more info. # Q. How much is implemented? From ee9479268cb24799e9783eeeb3a26bbb1a05d08c Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Tue, 15 Nov 2016 16:56:30 -0600 Subject: [PATCH 343/860] Update GettingStarted --- GettingStarted.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/GettingStarted.md b/GettingStarted.md index fb3a11fa..0c2c9c92 100644 --- a/GettingStarted.md +++ b/GettingStarted.md @@ -116,7 +116,7 @@ The intent of this guide is to get you started with ElixirScript. It will give y Macros can be used in Elixirscript just like in Elixir. The only exception is that `defmacrop` is unsupported -#### JavaScript Interop +### JavaScript Interop Elixirscript has a couple of ways of interacting with JavaScript. From 97374ae40b165146a7459c13670cd49f81d04435 Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Tue, 15 Nov 2016 17:34:24 -0600 Subject: [PATCH 344/860] Update version and changelog --- CHANGELOG.md | 2 +- mix.exs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 1a90699f..2a5e2e8a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,7 +4,7 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](http://keepachangelog.com/) and this project adheres to [Semantic Versioning](http://semver.org/). -## [Unreleased] +## [0.23.0] - 2016-11-15 ### Added - [`with` now supports `else`](https://github.com/bryanjos/elixirscript/pull/207) diff --git a/mix.exs b/mix.exs index 2e5c3493..0f1c7374 100644 --- a/mix.exs +++ b/mix.exs @@ -4,7 +4,7 @@ defmodule ElixirScript.Mixfile do def project do [ app: :elixir_script, - version: "0.23.0-dev", + version: "0.23.0", elixir: "~> 1.0", escript: escript_config, deps: deps, From 23f06fc2e38eeece45870fd68c4568c757716c1e Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Tue, 15 Nov 2016 19:21:36 -0600 Subject: [PATCH 345/860] Removed unsupported example projects from readme --- README.md | 4 ---- 1 file changed, 4 deletions(-) diff --git a/README.md b/README.md index cd916f51..e0e8a59f 100644 --- a/README.md +++ b/README.md @@ -65,10 +65,6 @@ Please check the [CONTRIBUTING.md](CONTRIBUTING.md) ### Example projects * [hello](https://github.com/bryanjos/hello) Shows using Phoenix + Elixirscript with file watching * [elixirscript frontend boilerplate](https://github.com/bryanjos/elixirscript-project-boilerplate) A boilerplate project for elixirscript frontends -* [todo-elixirscript](https://github.com/bryanjos/todo-elixirscript) A Todo App built with Elixirscript and Phoenix -* [phoenix_chat_example](https://github.com/bryanjos/phoenix_chat_example) The Phoenix Chat App using ElixirScript. -* [MobileElixir](https://github.com/bryanjos/MobileElixir) Using ElixirScript with React Native -* [color_bar_spike](https://github.com/bryanjos/color_bar_spike) A canvas drawing example using ElixirScript, React and a Redux-like design #### Using with Brunch There is a plugin for using ElixirScript in your Brunch project From c62693fe9c6460fa57edc538f2d29cc3fec595ae Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Wed, 16 Nov 2016 07:28:01 -0600 Subject: [PATCH 346/860] Readying for release --- CHANGELOG.md | 5 +++++ lib/elixir_script.ex | 2 +- mix.exs | 2 +- test/elixir_script_test.exs | 6 ++---- 4 files changed, 9 insertions(+), 6 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 2a5e2e8a..a25fda1d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,11 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](http://keepachangelog.com/) and this project adheres to [Semantic Versioning](http://semver.org/). +## [0.23.1] - 2016-11-16 + +### Fixed +- Incorrectly sending standard lib when using compile or compile_path by default + ## [0.23.0] - 2016-11-15 ### Added diff --git a/lib/elixir_script.ex b/lib/elixir_script.ex index 4751c447..295ca1bc 100644 --- a/lib/elixir_script.ex +++ b/lib/elixir_script.ex @@ -61,7 +61,7 @@ defmodule ElixirScript do @spec compile_quoted(Macro.t, Map.t) :: [binary | {binary, binary} | :ok] def compile_quoted(quoted, opts \\ %{}) do - opts = build_compiler_options(opts) + opts = build_compiler_options(Map.merge(opts, %{import_standard_libs: false})) data = quoted |> get_modules_from_quoted diff --git a/mix.exs b/mix.exs index 0f1c7374..8a4bb172 100644 --- a/mix.exs +++ b/mix.exs @@ -4,7 +4,7 @@ defmodule ElixirScript.Mixfile do def project do [ app: :elixir_script, - version: "0.23.0", + version: "0.23.1", elixir: "~> 1.0", escript: escript_config, deps: deps, diff --git a/test/elixir_script_test.exs b/test/elixir_script_test.exs index 4cdc5f06..a40365af 100644 --- a/test/elixir_script_test.exs +++ b/test/elixir_script_test.exs @@ -4,7 +4,7 @@ defmodule ElixirScript.Test do test "turn javascript ast into javascript code strings" do js_code = ElixirScript.compile(":atom") - assert Enum.join(js_code, "\n") =~ "Symbol.for('atom')" + assert Enum.join(js_code, "\n") |> String.trim == "Symbol.for('atom')" end @@ -22,8 +22,7 @@ defmodule ElixirScript.Test do """, %{ env: make_custom_env }) assert_js_matches """ - import Elixir from '../elixir/Elixir.Bootstrap'; - import Elixir$ElixirScript$Kernel from '../elixir/Elixir.ElixirScript.Kernel'; + import Elixir$ElixirScript$Kernel from '../elixir/Elixir.ElixirScript.Kernel'; const something_else = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.clause([],function() { return 1 * 1; })); @@ -51,7 +50,6 @@ defmodule ElixirScript.Test do """, %{ env: make_custom_env, core_path: "elixirscript"} ) assert_js_matches """ - import Elixir from '../elixir/elixirscript'; import Elixir$ElixirScript$Kernel from '../elixir/Elixir.ElixirScript.Kernel'; const something_else = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.clause([],function() { return 1 * 1; From b68db3e665a8830e2cfdfcf3d6f40d3273ccd93a Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Thu, 17 Nov 2016 09:19:07 -0600 Subject: [PATCH 347/860] Fixed issues with protocols and agents and defgen defined functions --- CHANGELOG.md | 8 ++++ .../passes/consolidate_protocols.ex | 2 +- lib/elixir_script/passes/find_modules.ex | 6 +-- lib/elixir_script/passes/java_script_name.ex | 2 +- lib/elixir_script/prelude/agent.ex | 38 ++++++++++--------- lib/elixir_script/prelude/js.ex | 6 +++ lib/elixir_script/prelude/process.ex | 2 +- mix.exs | 2 +- src/javascript/lib/core/functions.js | 7 +++- src/javascript/lib/core/protocol.js | 4 +- src/javascript/lib/core/store.js | 31 +++++++++++++-- 11 files changed, 77 insertions(+), 31 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index a25fda1d..550793f4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,14 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](http://keepachangelog.com/) and this project adheres to [Semantic Versioning](http://semver.org/). +## [0.23.2] - Unreleased + +### Fixed +- Agent not functioning properly. Now uses internal store instead of making a process and using that to put data in store +- Protocol incorrectly handling strings +- `defgen` and `defgenp` functions not being recognized by Elixir compiler. + + ## [0.23.1] - 2016-11-16 ### Fixed diff --git a/lib/elixir_script/passes/consolidate_protocols.ex b/lib/elixir_script/passes/consolidate_protocols.ex index 26b0818e..60c1e33e 100644 --- a/lib/elixir_script/passes/consolidate_protocols.ex +++ b/lib/elixir_script/passes/consolidate_protocols.ex @@ -1,5 +1,5 @@ defmodule ElixirScript.Passes.ConsolidateProtocols do - @moduledoc false + @moduledoc false alias ESTree.Tools.Builder, as: JS alias ElixirScript.Translator.Utils alias ElixirScript.ModuleSystems diff --git a/lib/elixir_script/passes/find_modules.ex b/lib/elixir_script/passes/find_modules.ex index f1f58844..fc3faee9 100644 --- a/lib/elixir_script/passes/find_modules.ex +++ b/lib/elixir_script/passes/find_modules.ex @@ -1,5 +1,5 @@ defmodule ElixirScript.Passes.FindModules do - @moduledoc false + @moduledoc false alias ElixirScript.Translator.Utils alias ElixirScript.Translator.State @@ -27,14 +27,14 @@ defmodule ElixirScript.Passes.FindModules do defp get_defmodules({:defimpl, _, [ the_alias, [for: {:__aliases__, _, type_name} = type], [do: {:__block__, context, spec}] ]} = ast, state, _) do {:__aliases__, _, original_name} = Utils.name_to_quoted(State.get_module_name(the_alias)) - name = original_name ++ [DefImpl] ++ type_name + name = original_name ++ [DefImpl] ++ [Elixir] ++ type_name s = %{name: Utils.quoted_to_name({:__aliases__, [], name}), type: :impl, for: type, ast: {:__block__, context, spec}, implements: Utils.quoted_to_name({:__aliases__, [], original_name}) } { ast, state ++ [s] } end defp get_defmodules({:defimpl, _, [ the_alias, [for: {:__aliases__, _, type_name} = type], [do: spec] ]} = ast, state, _) do {:__aliases__, _, original_name} = Utils.name_to_quoted(State.get_module_name(the_alias)) - name = original_name ++ [DefImpl] ++ type_name + name = original_name ++ [DefImpl] ++ [Elixir] ++ type_name s = %{name: Utils.quoted_to_name({:__aliases__, [], name}), type: :impl, for: type, ast: {:__block__, [], [spec]}, implements: Utils.quoted_to_name({:__aliases__, [], original_name}) } { ast, state ++ [s] } end diff --git a/lib/elixir_script/passes/java_script_name.ex b/lib/elixir_script/passes/java_script_name.ex index c5881810..07a873ff 100644 --- a/lib/elixir_script/passes/java_script_name.ex +++ b/lib/elixir_script/passes/java_script_name.ex @@ -1,5 +1,5 @@ defmodule ElixirScript.Passes.JavaScriptName do - @moduledoc false + @moduledoc false alias ElixirScript.Translator.Utils def execute(compiler_data, _) do diff --git a/lib/elixir_script/prelude/agent.ex b/lib/elixir_script/prelude/agent.ex index 29d2d533..f1750335 100644 --- a/lib/elixir_script/prelude/agent.ex +++ b/lib/elixir_script/prelude/agent.ex @@ -1,51 +1,53 @@ defmodule ElixirScript.Agent do - @moduledoc false + @moduledoc false + require JS def start(fun, options \\ []) do - pid = spawn(fn() -> Process.sleep(:infinity) end) + pid = JS.new Elixir.Core.PID, [] - if Elixir.Keyword.has_key?(options, :name) do - Process.register(pid, Elixir.Keyword.get(options, :name)) + name = if Elixir.Keyword.has_key?(options, :name) do + Elixir.Keyword.get(options, :name) + else + nil end - Elixir.Core.Store.create(pid, fun.()) + Elixir.Core.Store.create(pid, fun.(), name) { :ok, pid } end def start_link(fun, options \\ []) do - pid = spawn_link(fn() -> Process.sleep(:infinity) end) + pid = JS.new Elixir.Core.PID, [] - if Elixir.Keyword.has_key?(options, :name) do - Process.register(pid, Elixir.Keyword.get(options, :name)) + name = if Elixir.Keyword.has_key?(options, :name) do + Elixir.Keyword.get(options, :name) + else + nil end - Elixir.Core.Store.create(pid, fun.()) + Elixir.Core.Store.create(pid, fun.(), name) { :ok, pid } end def stop(agent) do - Process.exit(agent) + Elixir.Core.Store.remove(agent) :ok end def update(agent, fun) do - pid = Elixir.Core.processes.pidof(agent) - current_state = Elixir.Core.Store.read(pid) - Elixir.Core.Store.update(pid, fun.(current_state)) + current_state = Elixir.Core.Store.read(agent) + Elixir.Core.Store.update(agent, fun.(current_state)) :ok end def get(agent, fun) do - pid = Elixir.Core.processes.pidof(agent) - current_state = Elixir.Core.Store.read(pid) + current_state = Elixir.Core.Store.read(agent) fun.(current_state) end def get_and_update(agent, fun) do - pid = Elixir.Core.processes.pidof(agent) - current_state = Elixir.Core.Store.read(pid) + current_state = Elixir.Core.Store.read(agent) {val, new_state} = fun.(current_state) - Elixir.Core.Store.update(pid, new_state) + Elixir.Core.Store.update(agent, new_state) val end diff --git a/lib/elixir_script/prelude/js.ex b/lib/elixir_script/prelude/js.ex index 0706647e..35c9508a 100644 --- a/lib/elixir_script/prelude/js.ex +++ b/lib/elixir_script/prelude/js.ex @@ -78,12 +78,18 @@ defmodule JS do defgen and defgenp are currently the only ways to use process in Elixirscript right now. """ defmacro defgen(call, expr \\ nil) do + quote do + def unquote(call), unquote(expr) + end end @doc """ Defines a private generator. This is compiled into a generator function in JavaScript. """ defmacro defgenp(call, expr \\ nil) do + quote do + defp unquote(call), unquote(expr) + end end @doc """ diff --git a/lib/elixir_script/prelude/process.ex b/lib/elixir_script/prelude/process.ex index df873d20..caeed8f3 100644 --- a/lib/elixir_script/prelude/process.ex +++ b/lib/elixir_script/prelude/process.ex @@ -57,7 +57,7 @@ defmodule ElixirScript.Process do end def register(pid, name) when is_atom(name) do - Elixir.Core.processes.register(pid, name) + Elixir.Core.processes.register(name, pid) end def registered() do diff --git a/mix.exs b/mix.exs index 8a4bb172..e7dbf374 100644 --- a/mix.exs +++ b/mix.exs @@ -4,7 +4,7 @@ defmodule ElixirScript.Mixfile do def project do [ app: :elixir_script, - version: "0.23.1", + version: "0.23.2-dev", elixir: "~> 1.0", escript: escript_config, deps: deps, diff --git a/src/javascript/lib/core/functions.js b/src/javascript/lib/core/functions.js index bec25fd4..f5228161 100644 --- a/src/javascript/lib/core/functions.js +++ b/src/javascript/lib/core/functions.js @@ -392,6 +392,10 @@ function maps_from_list(list){ return Object.freeze(m); } +function* sleep_forever(){ + yield* Core.processes.sleep(Symbol("infinity")); +} + export default { call_property, apply, @@ -430,5 +434,6 @@ export default { duplicate, mapfoldl, filtermap, - maps_fold + maps_fold, + sleep_forever }; diff --git a/src/javascript/lib/core/protocol.js b/src/javascript/lib/core/protocol.js index d0b7aa90..488dee04 100644 --- a/src/javascript/lib/core/protocol.js +++ b/src/javascript/lib/core/protocol.js @@ -20,6 +20,8 @@ class Protocol{ fun = this.registry.get(Core.Integer)[funName]; }else if(typeof thing === "number" && !Number.isInteger(thing) && this.hasImplementation(Core.Float)){ fun = this.registry.get(Core.Float)[funName]; + }else if(typeof thing === "string" && this.hasImplementation(Core.BitString)){ + fun = this.registry.get(Core.BitString)[funName]; }else if(this.hasImplementation(thing)){ fun = this.registry.get(thing.constructor)[funName]; }else if(this.fallback){ @@ -45,7 +47,7 @@ class Protocol{ } hasImplementation(thing) { - if (thing === Core.Integer || thing === Core.Float){ + if (thing === Core.Integer || thing === Core.Float || Core.BitString){ return this.registry.has(thing); } diff --git a/src/javascript/lib/core/store.js b/src/javascript/lib/core/store.js index 6a1c6450..202946c4 100644 --- a/src/javascript/lib/core/store.js +++ b/src/javascript/lib/core/store.js @@ -1,19 +1,42 @@ let store = new Map(); +let names = new Map(); + +function get_key(key){ + let real_key = key; + + if(names.has(key)){ + real_key = names.get(key); + } + + if(store.has(real_key)){ + return real_key + } + + return new Error('Key Not Found'); +} + +function create(key, value, name = null){ + + if(name != null){ + names.set(name, key); + } -function create(key, value){ store.set(key, value); } function update(key, value){ - store.set(key, value); + let real_key = get_key(key); + store.set(real_key, value); } function read(key){ - return store.get(key); + let real_key = get_key(key); + return store.get(real_key); } function remove(key){ - return store.delete(key); + let real_key = get_key(key); + return store.delete(real_key); } export default { From 33c0b7e173bc951157e9faea77cfa4c594a905a4 Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Thu, 17 Nov 2016 20:41:21 -0600 Subject: [PATCH 348/860] Readying for release --- CHANGELOG.md | 2 +- mix.exs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 550793f4..1bf49fea 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,7 +4,7 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](http://keepachangelog.com/) and this project adheres to [Semantic Versioning](http://semver.org/). -## [0.23.2] - Unreleased +## [0.23.2] - 2016-11-17 ### Fixed - Agent not functioning properly. Now uses internal store instead of making a process and using that to put data in store diff --git a/mix.exs b/mix.exs index e7dbf374..0053a450 100644 --- a/mix.exs +++ b/mix.exs @@ -4,7 +4,7 @@ defmodule ElixirScript.Mixfile do def project do [ app: :elixir_script, - version: "0.23.2-dev", + version: "0.23.2", elixir: "~> 1.0", escript: escript_config, deps: deps, From fad714fc0da0ac40979dfb033a1b1e0ea9934456 Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Thu, 17 Nov 2016 21:04:58 -0600 Subject: [PATCH 349/860] Update Readme --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index e0e8a59f..9213a465 100644 --- a/README.md +++ b/README.md @@ -65,6 +65,7 @@ Please check the [CONTRIBUTING.md](CONTRIBUTING.md) ### Example projects * [hello](https://github.com/bryanjos/hello) Shows using Phoenix + Elixirscript with file watching * [elixirscript frontend boilerplate](https://github.com/bryanjos/elixirscript-project-boilerplate) A boilerplate project for elixirscript frontends +* [elixirscript react example](https://github.com/bryanjos/elixirscript_react) An example of using with React #### Using with Brunch There is a plugin for using ElixirScript in your Brunch project From 1363b1a9e66aa6bce82096a088a93a079a004e5b Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Fri, 18 Nov 2016 09:44:56 -0600 Subject: [PATCH 350/860] Readying for release --- CHANGELOG.md | 7 ++++ lib/elixir_script.ex | 3 ++ lib/elixir_script/passes/find_load_only.ex | 33 +++++++++++++++++++ lib/elixir_script/passes/handle_output.ex | 15 +++++++-- lib/elixir_script/passes/java_script_ast.ex | 6 +++- lib/elixir_script/passes/java_script_code.ex | 6 +++- lib/elixir_script/translator/lexical_scope.ex | 14 ++++++-- mix.exs | 2 +- 8 files changed, 77 insertions(+), 9 deletions(-) create mode 100644 lib/elixir_script/passes/find_load_only.ex diff --git a/CHANGELOG.md b/CHANGELOG.md index 1bf49fea..6519eb1a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,13 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](http://keepachangelog.com/) and this project adheres to [Semantic Versioning](http://semver.org/). + +## [0.23.3] - 2016-11-18 + +### Added +- `@load_only`: lets the compiler know to load in the module, but not to compile it + + ## [0.23.2] - 2016-11-17 ### Fixed diff --git a/lib/elixir_script.ex b/lib/elixir_script.ex index 295ca1bc..49b71830 100644 --- a/lib/elixir_script.ex +++ b/lib/elixir_script.ex @@ -70,6 +70,7 @@ defmodule ElixirScript do result = %{ data: data } |> ElixirScript.Passes.Init.execute(opts) |> ElixirScript.Passes.FindModules.execute(opts) + |> ElixirScript.Passes.FindLoadOnly.execute(opts) |> ElixirScript.Passes.FindFunctions.execute(opts) |> ElixirScript.Passes.AddStdLib.execute(opts) |> ElixirScript.Passes.JavaScriptAST.execute(opts) @@ -124,6 +125,7 @@ defmodule ElixirScript do |> ElixirScript.Passes.ASTFromFile.execute(opts) |> ElixirScript.Passes.LoadModules.execute(opts) |> ElixirScript.Passes.FindModules.execute(opts) + |> ElixirScript.Passes.FindLoadOnly.execute(opts) |> ElixirScript.Passes.FindChangedFiles.execute(opts) |> ElixirScript.Passes.FindFunctions.execute(opts) |> ElixirScript.Passes.AddStdLib.execute(opts) @@ -165,6 +167,7 @@ defmodule ElixirScript do |> ElixirScript.Passes.DepsPaths.execute(opts) |> ElixirScript.Passes.ASTFromFile.execute(opts) |> ElixirScript.Passes.FindModules.execute(opts) + |> ElixirScript.Passes.FindLoadOnly.execute(opts) |> ElixirScript.Passes.FindFunctions.execute(opts) |> ElixirScript.Passes.JavaScriptAST.execute(opts) |> ElixirScript.Passes.ConsolidateProtocols.execute(opts) diff --git a/lib/elixir_script/passes/find_load_only.ex b/lib/elixir_script/passes/find_load_only.ex new file mode 100644 index 00000000..86fb0754 --- /dev/null +++ b/lib/elixir_script/passes/find_load_only.ex @@ -0,0 +1,33 @@ +defmodule ElixirScript.Passes.FindLoadOnly do + @moduledoc false + + def execute(compiler_data, opts) do + data = compiler_data.data + |> Enum.map(fn({module_name, module_data}) -> + + {_, load_only} = Macro.prewalk(module_data.ast, false, fn + ({:@, _, [{:load_only, _, [true]}]} = ast, state) -> + {ast, true} + + ({:@, _, [{:load_only, _, [false]}]} = ast, state) -> + {ast, false} + + ({:@, _, [{:load_only, _, []}]} = ast, state) -> + {ast, true} + + (ast, state) -> + {ast, state} + end) + + { module_name, Map.put(module_data, :load_only, load_only) } + + end) + + + + %{ compiler_data | data: data } + end + + + +end diff --git a/lib/elixir_script/passes/handle_output.ex b/lib/elixir_script/passes/handle_output.ex index d197bf9e..c9f640fb 100644 --- a/lib/elixir_script/passes/handle_output.ex +++ b/lib/elixir_script/passes/handle_output.ex @@ -1,5 +1,5 @@ defmodule ElixirScript.Passes.HandleOutput do - @moduledoc false + @moduledoc false alias ElixirScript.Translator.State def execute(compiler_data, opts) do @@ -24,12 +24,14 @@ defmodule ElixirScript.Passes.HandleOutput do defp out(compiler_output, %{output: nil} = compiler_opts) do compiler_output - |> process_include_path(compiler_opts) + |> remove_load_only + |> process_include_path(compiler_opts) end defp out(compiler_output, %{output: :stdout} = compiler_opts) do compiler_output - |> process_include_path(compiler_opts) + |> remove_load_only + |> process_include_path(compiler_opts) |> Enum.each(fn {_, code, _} -> IO.write(code) code -> IO.write(code) @@ -41,6 +43,8 @@ defmodule ElixirScript.Passes.HandleOutput do ElixirScript.copy_stdlib_to_destination(output_path) end + compiler_output = remove_load_only(compiler_output) + compiler_output.data |> Enum.each(fn({_, x}) -> write_to_file(x, output_path) @@ -69,4 +73,9 @@ defmodule ElixirScript.Passes.HandleOutput do end end) end + + defp remove_load_only(compiler_output) do + data = Enum.filter(compiler_output.data, fn({m, d}) -> Map.get(d, :load_only, false) == false end) + %{ compiler_output | data: data } + end end diff --git a/lib/elixir_script/passes/java_script_ast.ex b/lib/elixir_script/passes/java_script_ast.ex index 8c4069bd..920dfb97 100644 --- a/lib/elixir_script/passes/java_script_ast.ex +++ b/lib/elixir_script/passes/java_script_ast.ex @@ -1,5 +1,5 @@ defmodule ElixirScript.Passes.JavaScriptAST do - @moduledoc false + @moduledoc false alias ElixirScript.Translator.Utils alias ElixirScript.Translator.State @@ -30,6 +30,10 @@ defmodule ElixirScript.Passes.JavaScriptAST do %{ compiler_data | data: data } end + defp compile(%{load_only: true} = module_data, opts) do + module_data + end + defp compile(module_data, opts) do env = ElixirScript.Translator.LexicalScope.module_scope(module_data.name, Utils.name_to_js_file_name(module_data.name) <> ".js", opts.env) diff --git a/lib/elixir_script/passes/java_script_code.ex b/lib/elixir_script/passes/java_script_code.ex index c9f5ca5f..8d8e00de 100644 --- a/lib/elixir_script/passes/java_script_code.ex +++ b/lib/elixir_script/passes/java_script_code.ex @@ -1,5 +1,5 @@ defmodule ElixirScript.Passes.JavaScriptCode do - @moduledoc false + @moduledoc false alias ESTree.Tools.{ Builder, Generator } def execute(compiler_data, _) do @@ -24,6 +24,10 @@ defmodule ElixirScript.Passes.JavaScriptCode do %{ compiler_data | data: data } end + defp compile(%{load_only: true} = module_data) do + module_data + end + defp compile(module_data) do js_ast = Builder.program(module_data.javascript_ast) diff --git a/lib/elixir_script/translator/lexical_scope.ex b/lib/elixir_script/translator/lexical_scope.ex index 91e4dd07..2c20d61c 100644 --- a/lib/elixir_script/translator/lexical_scope.ex +++ b/lib/elixir_script/translator/lexical_scope.ex @@ -187,14 +187,22 @@ defmodule ElixirScript.Translator.LexicalScope do raise "Module #{inspect module_name} not found" end - ElixirScript.Translator.State.add_module_reference(env.module, module.name) + if Map.get(module, :load_only, false) == false do + ElixirScript.Translator.State.add_module_reference(env.module, module.name) + end + module end defp has_module?(env, module_name) do try do - get_module(env, module_name) - true + module = get_module(env, module_name) + case module do + %{load_only: true} -> + false + _ -> + true + end rescue _ -> false diff --git a/mix.exs b/mix.exs index 0053a450..da64ef93 100644 --- a/mix.exs +++ b/mix.exs @@ -4,7 +4,7 @@ defmodule ElixirScript.Mixfile do def project do [ app: :elixir_script, - version: "0.23.2", + version: "0.23.3", elixir: "~> 1.0", escript: escript_config, deps: deps, From 2a7398552ebde842e93f660fc424342e253de444 Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Fri, 25 Nov 2016 17:15:57 -0600 Subject: [PATCH 351/860] Allow CLI to accept muliple paths --- CHANGELOG.md | 4 ++++ lib/elixir_script.ex | 2 +- lib/elixir_script/cli.ex | 4 ++++ mix.exs | 2 +- 4 files changed, 10 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 6519eb1a..ffc098f5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,10 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](http://keepachangelog.com/) and this project adheres to [Semantic Versioning](http://semver.org/). +## [0.23.4] - Unreleased + +### Fixed +- CLI now allows a comma-separated or space-separated list of paths ## [0.23.3] - 2016-11-18 diff --git a/lib/elixir_script.ex b/lib/elixir_script.ex index 49b71830..445e53be 100644 --- a/lib/elixir_script.ex +++ b/lib/elixir_script.ex @@ -114,7 +114,7 @@ defmodule ElixirScript do @doc """ Compiles the elixir files found at the given path """ - @spec compile_path(binary, Map.t) :: [binary | {binary, binary} | :ok] + @spec compile_path(binary | [binary], Map.t) :: [binary | {binary, binary} | :ok] def compile_path(path, opts \\ %{}) do opts = build_compiler_options(opts) diff --git a/lib/elixir_script/cli.ex b/lib/elixir_script/cli.ex index af2efbfc..c6f0b77b 100644 --- a/lib/elixir_script/cli.ex +++ b/lib/elixir_script/cli.ex @@ -79,6 +79,9 @@ defmodule ElixirScript.CLI do true -> ElixirScript.compile(input, compile_opts) _ -> + input = input + |> String.split([" ", ","], trim: true) + ElixirScript.compile_path(input, compile_opts) if watch do @@ -97,4 +100,5 @@ defmodule ElixirScript.CLI do end end) end + end diff --git a/mix.exs b/mix.exs index da64ef93..3ea7dda6 100644 --- a/mix.exs +++ b/mix.exs @@ -4,7 +4,7 @@ defmodule ElixirScript.Mixfile do def project do [ app: :elixir_script, - version: "0.23.3", + version: "0.23.4-dev", elixir: "~> 1.0", escript: escript_config, deps: deps, From 62c98287bdc77a7117b128bb9eb8a7ce82c6a9a1 Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Tue, 29 Nov 2016 22:55:08 -0600 Subject: [PATCH 352/860] Add Regex module --- lib/elixir_script.ex | 3 +- lib/elixir_script/prelude/kernel.ex | 9 +++- lib/elixir_script/prelude/regex.ex | 65 +++++++++++++++++++++++++++ lib/elixir_script/translator/state.ex | 5 ++- test/prelude/kernel_test.exs | 12 +++++ 5 files changed, 89 insertions(+), 5 deletions(-) create mode 100644 lib/elixir_script/prelude/regex.ex diff --git a/lib/elixir_script.ex b/lib/elixir_script.ex index 445e53be..574556b2 100644 --- a/lib/elixir_script.ex +++ b/lib/elixir_script.ex @@ -32,7 +32,8 @@ defmodule ElixirScript do is_pid: 1, is_tuple: 1, is_map: 1, is_port: 1, is_reference: 1, length: 1, map_size: 1, max: 2, min: 2, round: 1, trunc: 1, tuple_size: 1, elem: 2, is_nil: 1, make_ref: 1, spawn: 1, spawn: 3, spawn_link: 1, spawn_link: 3, spawn_monitor: 1, - spawn_monitor: 3, send: 2, self: 0, match?: 2, to_string: 1, "|>": 2, in: 2, "..": 2 + spawn_monitor: 3, send: 2, self: 0, match?: 2, to_string: 1, "|>": 2, in: 2, "..": 2, + sigil_r: 2 ] import ElixirScript.Kernel require JS diff --git a/lib/elixir_script/prelude/kernel.ex b/lib/elixir_script/prelude/kernel.ex index 60128d88..44487421 100644 --- a/lib/elixir_script/prelude/kernel.ex +++ b/lib/elixir_script/prelude/kernel.ex @@ -1,7 +1,8 @@ defmodule ElixirScript.Kernel do - @moduledoc false + @moduledoc false import Kernel, only: [defmodule: 2, def: 1, def: 2, defp: 2, - defmacro: 1, defmacro: 2, defmacrop: 2, ||: 2, !: 1, ++: 2, in: 2, &&: 2, ===: 2, @: 1] + defmacro: 1, defmacro: 2, defmacrop: 2, ||: 2, !: 1, + ++: 2, in: 2, &&: 2, ===: 2, @: 1, sigil_r: 2] require JS @@ -194,6 +195,10 @@ defmodule ElixirScript.Kernel do Elixir.Core.processes.pid() end + def sigil_r({:<<>>, _meta, [string]}, options) do + JS.new(RegExp, [string, options]) + end + defmacro match?(left, right) do quote do case unquote(right) do diff --git a/lib/elixir_script/prelude/regex.ex b/lib/elixir_script/prelude/regex.ex new file mode 100644 index 00000000..847d6b9d --- /dev/null +++ b/lib/elixir_script/prelude/regex.ex @@ -0,0 +1,65 @@ +defmodule ElixirScript.Regex do + require JS + + def compile(source, options \\ "") do + try do + {:ok, JS.new(RegExp, [source, options]) } + rescue + x -> + {:error, x.message} + end + end + + def regex?(term) do + JS.instanceof(term, RegExp) + end + + def match?(regex, string) do + regex.test(string) + end + + def source(regex) do + regex.source + end + + def opts(regex) do + regex.flags + end + + def run(regex, string, options \\ []) do + regex.exec(string) + end + + def scan(regex, string, options \\ []) do + reg = make_global(regex) + do_scan(reg, string, options, []) + end + + def replace(regex, string, replacement, options \\ []) do + reg = if Keyword.get(options, :global, true) do + make_global(regex) + else + regex + end + + string.replace(regex, replacement) + end + + defp do_scan(regex, string, options, results) do + case run(regex, string, options) do + nil -> + results + match -> + do_scan(regex, string, options, results ++ match) + end + end + + defp make_global(regex) do + if String.contains?(regex.flags, "g") do + regex + else + JS.new(RegExp, [ source(regex), opts(regex) <> "g" ]) + end + end + +end diff --git a/lib/elixir_script/translator/state.ex b/lib/elixir_script/translator/state.ex index bbd56fdb..41edd340 100644 --- a/lib/elixir_script/translator/state.ex +++ b/lib/elixir_script/translator/state.ex @@ -18,12 +18,12 @@ defmodule ElixirScript.Translator.State do def serialize() do Agent.get(__MODULE__, fn(state) -> modules = state.modules - modules = Enum.map(modules, fn {m, d} -> + modules = Enum.map(modules, fn {m, d} -> d = Map.delete(d, :javascript_ast) |> Map.delete(:javascript_code) |> Map.delete(:javascript_name) - {m, d} + {m, d} end) |> Enum.filter(fn {_, d} -> d.type != :consolidated end) @@ -64,6 +64,7 @@ defmodule ElixirScript.Translator.State do |> Map.put(MapSet, ElixirScript.MapSet) |> Map.put(List, ElixirScript.List) |> Map.put(Process, ElixirScript.Process) + |> Map.put(Regex, ElixirScript.Regex) end def set_module_data(module_data) do diff --git a/test/prelude/kernel_test.exs b/test/prelude/kernel_test.exs index 4eb7f06a..1b20aaa5 100644 --- a/test/prelude/kernel_test.exs +++ b/test/prelude/kernel_test.exs @@ -16,4 +16,16 @@ defmodule ElixirScript.Lib.Elixir.Kernel.Test do assert_translation(ex_ast, js_code) end + + test "translate sigil_r" do + ex_ast = quote do + ~r/foo/ + end + + js_code = """ + new RegExp('foo') + """ + + assert_translation(ex_ast, js_code) + end end From f68b5617b6452c1969758ced1e67361f27af7c82 Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Wed, 30 Nov 2016 06:56:11 -0600 Subject: [PATCH 353/860] Add working sigil_r to Kernel --- lib/elixir_script/prelude/kernel.ex | 7 +++++-- lib/elixir_script/prelude/regex.ex | 4 ++++ test/prelude/kernel_test.exs | 14 +++++++++++++- 3 files changed, 22 insertions(+), 3 deletions(-) diff --git a/lib/elixir_script/prelude/kernel.ex b/lib/elixir_script/prelude/kernel.ex index 44487421..6e99a97f 100644 --- a/lib/elixir_script/prelude/kernel.ex +++ b/lib/elixir_script/prelude/kernel.ex @@ -195,8 +195,11 @@ defmodule ElixirScript.Kernel do Elixir.Core.processes.pid() end - def sigil_r({:<<>>, _meta, [string]}, options) do - JS.new(RegExp, [string, options]) + defmacro sigil_r({:<<>>, _meta, [string]}, options) do + str_options = List.to_string(options) + quote do + Regex.compile!(unquote(string), unquote(str_options)) + end end defmacro match?(left, right) do diff --git a/lib/elixir_script/prelude/regex.ex b/lib/elixir_script/prelude/regex.ex index 847d6b9d..c78facdc 100644 --- a/lib/elixir_script/prelude/regex.ex +++ b/lib/elixir_script/prelude/regex.ex @@ -10,6 +10,10 @@ defmodule ElixirScript.Regex do end end + def compile!(source, options \\ "") do + JS.new(RegExp, [source, options]) + end + def regex?(term) do JS.instanceof(term, RegExp) end diff --git a/test/prelude/kernel_test.exs b/test/prelude/kernel_test.exs index 1b20aaa5..2d90972b 100644 --- a/test/prelude/kernel_test.exs +++ b/test/prelude/kernel_test.exs @@ -23,7 +23,19 @@ defmodule ElixirScript.Lib.Elixir.Kernel.Test do end js_code = """ - new RegExp('foo') + Elixir$ElixirScript$Regex.compile__emark__('foo','') + """ + + assert_translation(ex_ast, js_code) + end + + test "translate sigil_r with options" do + ex_ast = quote do + ~r/foo/ig + end + + js_code = """ + Elixir$ElixirScript$Regex.compile__emark__('foo', 'ig') """ assert_translation(ex_ast, js_code) From b2b00700af55ccf754a19784051b5511faa6d819 Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Fri, 2 Dec 2016 08:52:28 -0600 Subject: [PATCH 354/860] Update docs --- CHANGELOG.md | 3 ++- mix.exs | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index ffc098f5..86afc7a8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,10 +4,11 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](http://keepachangelog.com/) and this project adheres to [Semantic Versioning](http://semver.org/). -## [0.23.4] - Unreleased +## [0.24.0] - Unreleased ### Fixed - CLI now allows a comma-separated or space-separated list of paths +- Implement `sigil_r` and `Regex` module ## [0.23.3] - 2016-11-18 diff --git a/mix.exs b/mix.exs index 3ea7dda6..c11665e7 100644 --- a/mix.exs +++ b/mix.exs @@ -4,7 +4,7 @@ defmodule ElixirScript.Mixfile do def project do [ app: :elixir_script, - version: "0.23.4-dev", + version: "0.24.0-dev", elixir: "~> 1.0", escript: escript_config, deps: deps, From c788f8805061d2124de0df7b2acf86868d2e711d Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Sun, 4 Dec 2016 08:11:26 -0600 Subject: [PATCH 355/860] Update README.md --- README.md | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 9213a465..ccb150c2 100644 --- a/README.md +++ b/README.md @@ -64,8 +64,9 @@ Please check the [CONTRIBUTING.md](CONTRIBUTING.md) ### Example projects * [hello](https://github.com/bryanjos/hello) Shows using Phoenix + Elixirscript with file watching -* [elixirscript frontend boilerplate](https://github.com/bryanjos/elixirscript-project-boilerplate) A boilerplate project for elixirscript frontends -* [elixirscript react example](https://github.com/bryanjos/elixirscript_react) An example of using with React +* [Elixirscript frontend boilerplate](https://github.com/bryanjos/elixirscript-project-boilerplate) A boilerplate project for elixirscript frontends +* [Elixirscript React example](https://github.com/bryanjos/elixirscript_react) An example of using with React +* [Elixirscript AWS Lambda example](https://github.com/bryanjos/elixirscript_lambda) #### Using with Brunch There is a plugin for using ElixirScript in your Brunch project From f1850eadc1958447bd11ddac1fe36d76be70eb5a Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Wed, 28 Dec 2016 16:55:34 -0600 Subject: [PATCH 356/860] Fix allowing for multiple input. Fix struct module references --- CHANGELOG.md | 5 +++- lib/elixir_script.ex | 9 +++++-- lib/elixir_script/cli.ex | 27 ++++++++++++------- .../translator/kernel/special_forms/struct.ex | 1 + lib/elixir_script/watcher.ex | 4 ++- 5 files changed, 32 insertions(+), 14 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 86afc7a8..37efb939 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,9 +6,12 @@ and this project adheres to [Semantic Versioning](http://semver.org/). ## [0.24.0] - Unreleased +### Added +- Implement `sigil_r` and `Regex` module + ### Fixed - CLI now allows a comma-separated or space-separated list of paths -- Implement `sigil_r` and `Regex` module +- Struct not properly referenced ## [0.23.3] - 2016-11-18 diff --git a/lib/elixir_script.ex b/lib/elixir_script.ex index 574556b2..ca73429e 100644 --- a/lib/elixir_script.ex +++ b/lib/elixir_script.ex @@ -52,8 +52,13 @@ defmodule ElixirScript do @spec compile(binary, Map.t) :: [binary | {binary, binary} | :ok] def compile(elixir_code, opts \\ %{}) do elixir_code - |> Code.string_to_quoted! - |> compile_quoted(opts) + |> List.wrap + |> Enum.map(fn(x) -> + x + |> Code.string_to_quoted! + |> compile_quoted(opts) + end) + |> List.flatten end @doc """ diff --git a/lib/elixir_script/cli.ex b/lib/elixir_script/cli.ex index c6f0b77b..c870f3c9 100644 --- a/lib/elixir_script/cli.ex +++ b/lib/elixir_script/cli.ex @@ -6,7 +6,7 @@ defmodule ElixirScript.CLI do @switches [ output: :binary, elixir: :boolean, help: :boolean, core_path: :binary, - full_build: :boolean, version: :boolean, + full_build: :boolean, version: :boolean, watch: :boolean ] @@ -21,13 +21,19 @@ defmodule ElixirScript.CLI do end def parse_args(args) do - parse = OptionParser.parse(args, switches: @switches, aliases: @aliases) - - case parse do - { [help: true] , _ , _ } -> :help - { [version: true] , _ , _ } -> :version - { options , [input], _ } -> { input, options } - _ -> :help + { options, input, errors } = OptionParser.parse(args, switches: @switches, aliases: @aliases) + + cond do + length(errors) > 0 -> + :help + Keyword.get(options, :help, false) -> + :help + Keyword.get(options, :version, false) -> + :version + length(input) == 0 -> + :help + true -> + { input, options } end end @@ -80,8 +86,9 @@ defmodule ElixirScript.CLI do ElixirScript.compile(input, compile_opts) _ -> input = input - |> String.split([" ", ","], trim: true) - + |> Enum.map(fn(x) -> String.split(x, [" ", ","], trim: true) end) + |> List.flatten + ElixirScript.compile_path(input, compile_opts) if watch do diff --git a/lib/elixir_script/translator/kernel/special_forms/struct.ex b/lib/elixir_script/translator/kernel/special_forms/struct.ex index f4f24277..670ae90b 100644 --- a/lib/elixir_script/translator/kernel/special_forms/struct.ex +++ b/lib/elixir_script/translator/kernel/special_forms/struct.ex @@ -13,6 +13,7 @@ defmodule ElixirScript.Translator.Struct do if ElixirScript.Translator.LexicalScope.get_module_name(env, candiate_module_name) in ElixirScript.Translator.State.list_module_names() do name = ElixirScript.Translator.LexicalScope.get_module_name(env, candiate_module_name) ident = JS.identifier(Utils.name_to_js_name(name)) + ElixirScript.Translator.State.add_module_reference(env.module, name) JS.member_expression(ident, ident) else diff --git a/lib/elixir_script/watcher.ex b/lib/elixir_script/watcher.ex index ba4861d2..b54cc03e 100644 --- a/lib/elixir_script/watcher.ex +++ b/lib/elixir_script/watcher.ex @@ -41,7 +41,9 @@ defmodule ElixirScript.Watcher do "." <> _ -> false _ -> - path == Path.absname(Path.join([state[:input], file])) + Enum.any?(List.wrap(state[:input]), fn(x) -> + path == Path.absname(Path.join([x, file])) + end) end end end From fb9091cdb9c507f11d77dd59d2b89c081089d6a0 Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Thu, 5 Jan 2017 20:25:23 -0600 Subject: [PATCH 357/860] Update estree dependency --- mix.exs | 2 +- mix.lock | 2 +- test/translator/function_test.exs | 35 ++++++++++++++++--------------- test/translator/try_test.exs | 18 ++++++++-------- 4 files changed, 29 insertions(+), 28 deletions(-) diff --git a/mix.exs b/mix.exs index c11665e7..e1c28ac2 100644 --- a/mix.exs +++ b/mix.exs @@ -28,7 +28,7 @@ defmodule ElixirScript.Mixfile do defp deps do [ - {:estree, "~> 2.3.0" }, + {:estree, "~> 2.5" }, {:fs, "~> 0.9.1"}, {:earmark, "~> 1.0", only: :dev }, {:ex_doc, "~> 0.14", only: :dev }, diff --git a/mix.lock b/mix.lock index 70217318..8df49871 100644 --- a/mix.lock +++ b/mix.lock @@ -2,7 +2,7 @@ "certifi": {:hex, :certifi, "0.4.0", "a7966efb868b179023618d29a407548f70c52466bf1849b9e8ebd0e34b7ea11f", [:rebar3], []}, "credo": {:hex, :credo, "0.4.12", "f5e1973405ea25c6e64959fb0b6bf92950147a0278cc2a002a491b45f78f7b87", [:mix], [{:bunt, "~> 0.1.6", [hex: :bunt, optional: false]}]}, "earmark": {:hex, :earmark, "1.0.2", "a0b0904d74ecc14da8bd2e6e0248e1a409a2bc91aade75fcf428125603de3853", [:mix], []}, - "estree": {:hex, :estree, "2.3.0", "96a190aee9b7ecb05a9486fe0f1e0a912c98b2d98419a84c74956687b6e53c71", [:mix], []}, + "estree": {:hex, :estree, "2.5.0", "9776c1705a72dc5a0d56cdf431173c3e75f9e509278a857ec55374a49f5699ef", [:mix], []}, "ex_doc": {:hex, :ex_doc, "0.14.3", "e61cec6cf9731d7d23d254266ab06ac1decbb7651c3d1568402ec535d387b6f7", [:mix], [{:earmark, "~> 1.0", [hex: :earmark, optional: false]}]}, "excoveralls": {:hex, :excoveralls, "0.5.7", "5d26e4a7cdf08294217594a1b0643636accc2ad30e984d62f1d166f70629ff50", [:mix], [{:exjsx, "~> 3.0", [hex: :exjsx, optional: false]}, {:hackney, ">= 0.12.0", [hex: :hackney, optional: false]}]}, "exjsx": {:hex, :exjsx, "3.2.1", "1bc5bf1e4fd249104178f0885030bcd75a4526f4d2a1e976f4b428d347614f0f", [:mix], [{:jsx, "~> 2.8.0", [hex: :jsx, optional: false]}]}, diff --git a/test/translator/function_test.exs b/test/translator/function_test.exs index a8986098..cbeeb62f 100644 --- a/test/translator/function_test.exs +++ b/test/translator/function_test.exs @@ -89,7 +89,7 @@ defmodule ElixirScript.Translator.Function.Test do return Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.clause([Elixir.Core.Patterns.variable()],function(x) { return 2; },function(x) { - return (x === null) || (x === false); + return x === null || x === false; }),Elixir.Core.Patterns.clause([Elixir.Core.Patterns.wildcard()],function() { return 1; })).call(this,1 == 1); @@ -113,21 +113,22 @@ defmodule ElixirScript.Translator.Function.Test do end js_code = """ - const test1 = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.clause([Elixir.Core.Patterns.variable(), Elixir.Core.Patterns.variable()],function(alpha,beta) { - return Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.clause([Elixir.Core.Patterns.variable()],function(x) { - return 2; - },function(x) { - return (x === null) || (x === false); - }),Elixir.Core.Patterns.clause([Elixir.Core.Patterns.wildcard()],function() { - return Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.clause([Elixir.Core.Patterns.variable()],function(x) { - let [a] = Elixir.Core.Patterns.match(Elixir.Core.Patterns.variable(),1); - return a; - },function(x) { - return (x === null) || (x === false); - }),Elixir.Core.Patterns.clause([Elixir.Core.Patterns.wildcard()],function() { - return 4; - })).call(this,2 == 2); - })).call(this,1 == 1); + const test1 = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.clause([Elixir.Core.Patterns.variable(), Elixir.Core.Patterns.variable()], function(alpha, beta) { + return Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.clause([Elixir.Core.Patterns.variable()], function(x) { + return 2; + }, function(x) { + return x === null || x === false; + }), Elixir.Core.Patterns.clause([Elixir.Core.Patterns.wildcard()], function() { + return Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.clause([Elixir.Core.Patterns.variable()], function(x) { + let [a] = Elixir.Core.Patterns.match(Elixir.Core.Patterns.variable(), 1); + + return a; + }, function(x) { + return x === null || x === false; + }), Elixir.Core.Patterns.clause([Elixir.Core.Patterns.wildcard()], function() { + return 4; + })).call(this, 2 == 2); + })).call(this, 1 == 1); })); """ @@ -800,7 +801,7 @@ defmodule ElixirScript.Translator.Function.Test do return Symbol.for('error'); }, function(x) { - return (x === null) || (x === false); + return x === null || x === false; }), Elixir.Core.Patterns.clause([Elixir.Core.Patterns.wildcard()], function() { return null; diff --git a/test/translator/try_test.exs b/test/translator/try_test.exs index cdfe85c8..d165688d 100644 --- a/test/translator/try_test.exs +++ b/test/translator/try_test.exs @@ -172,15 +172,15 @@ defmodule ElixirScript.Translator.Try.Test do end js_code = """ - Elixir.Core.SpecialForms._try(function() { - return 1 / x; - },null,null,Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.clause([Elixir.Core.Patterns.variable()],function(y) { - return Symbol.for('small'); - },function(y) { - return (y < 1) && (y > -1); - }),Elixir.Core.Patterns.clause([Elixir.Core.Patterns.wildcard()],function() { - return Symbol.for('large'); - })),null) + Elixir.Core.SpecialForms._try(function() { + return 1 / x; + }, null, null, Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.clause([Elixir.Core.Patterns.variable()], function(y) { + return Symbol.for('small'); + }, function(y) { + return y < 1 && y > -1; + }), Elixir.Core.Patterns.clause([Elixir.Core.Patterns.wildcard()], function() { + return Symbol.for('large'); + })), null) """ assert_translation(ex_ast, js_code) From 9bc53809e0d19eb17575450ce1b3b7aadb3487dc Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Thu, 5 Jan 2017 20:27:08 -0600 Subject: [PATCH 358/860] Update Changelog --- CHANGELOG.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 37efb939..e3a3d8bf 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,7 +7,9 @@ and this project adheres to [Semantic Versioning](http://semver.org/). ## [0.24.0] - Unreleased ### Added -- Implement `sigil_r` and `Regex` module +- Support for `sigil_r` +- `Regex` module +- Better JavaScript formatting ### Fixed - CLI now allows a comma-separated or space-separated list of paths From 6fee69ec6dc74affcd8d22f070f37d699b137e70 Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Thu, 12 Jan 2017 19:14:11 -0600 Subject: [PATCH 359/860] Fixed issues found while testing --- lib/elixir_script/prelude/string.ex | 16 +++++++++- lib/elixir_script/translator.ex | 24 +++++++++++++++ .../translator/kernel/special_forms/call.ex | 9 ++++++ .../translator/kernel/special_forms/fn.ex | 1 + .../kernel/special_forms/receive.ex | 7 +++-- test/translator/bitwise_test.exs | 15 ++++++++++ test/translator/kernel/receive_test.exs | 30 +++++++++++++++++-- 7 files changed, 97 insertions(+), 5 deletions(-) create mode 100644 test/translator/bitwise_test.exs diff --git a/lib/elixir_script/prelude/string.ex b/lib/elixir_script/prelude/string.ex index e76d72a6..d4d6cfc0 100644 --- a/lib/elixir_script/prelude/string.ex +++ b/lib/elixir_script/prelude/string.ex @@ -1,5 +1,5 @@ defmodule ElixirScript.String do - @moduledoc false + @moduledoc false import Kernel, except: [length: 1] def to_atom(str) do @@ -54,6 +54,20 @@ defmodule ElixirScript.String do str.split() end + def split(str, replace, options \\ []) do + limit = Keyword.get(options, :parts, -1) + trim = Keyword.get(options, :trim, false) + split = str.split(replace, limit) + + Enum.map(split, fn(x) -> + if trim do + x.trim() + else + x + end + end) + end + def next_grapheme(nil), do: nil def next_grapheme(""), do: nil diff --git a/lib/elixir_script/translator.ex b/lib/elixir_script/translator.ex index 71095ac3..dddf252b 100644 --- a/lib/elixir_script/translator.ex +++ b/lib/elixir_script/translator.ex @@ -108,10 +108,34 @@ defmodule ElixirScript.Translator do Expression.make_unary_expression(:!, value, env) end + defp do_translate({:"~~~", _, [value]}, env) do + Expression.make_unary_expression(:"~~~", value, env) + end + defp do_translate({operator, _, [left, right]}, env) when operator in [:+, :-, :/, :*, :==, :!=, :&&, :||, :>, :<, :>=, :<=, :===, :!==, :"**"] do Expression.make_binary_expression(operator, left, right, env) end + defp do_translate({:&&&, _, [left, right]}, env) do + Expression.make_binary_expression(:&, left, right, env) + end + + defp do_translate({:<<<, _, [left, right]}, env) do + Expression.make_binary_expression(:<, left, right, env) + end + + defp do_translate({:>>>, _, [left, right]}, env) do + Expression.make_binary_expression(:^, left, right, env) + end + + defp do_translate({:^^^, _, [left, right]}, env) do + Expression.make_binary_expression(:^, left, right, env) + end + + defp do_translate({:|||, _, [left, right]}, env) do + Expression.make_binary_expression(:|, left, right, env) + end + defp do_translate({:and, _, [left, right]}, env) do Expression.make_binary_expression(:&&, left, right, env) end diff --git a/lib/elixir_script/translator/kernel/special_forms/call.ex b/lib/elixir_script/translator/kernel/special_forms/call.ex index 8ed21f61..5cff6ec8 100644 --- a/lib/elixir_script/translator/kernel/special_forms/call.ex +++ b/lib/elixir_script/translator/kernel/special_forms/call.ex @@ -75,6 +75,15 @@ defmodule ElixirScript.Translator.Call do end def make_function_call(module_name, function_name, params, env) do + params = case params do + atom when is_atom(atom) -> + [] + nil -> + [] + _ -> + params + end + the_name = get_module_name_for_function(module_name, env) { make_call_expression(the_name, function_name, params, env), env } end diff --git a/lib/elixir_script/translator/kernel/special_forms/fn.ex b/lib/elixir_script/translator/kernel/special_forms/fn.ex index 26c4f44a..f82fa98e 100644 --- a/lib/elixir_script/translator/kernel/special_forms/fn.ex +++ b/lib/elixir_script/translator/kernel/special_forms/fn.ex @@ -112,6 +112,7 @@ defmodule ElixirScript.Translator.Function do end def make_function_clause(patterns, params, body, guard_body, is_generator?) do + arguments = case guard_body do nil -> [ diff --git a/lib/elixir_script/translator/kernel/special_forms/receive.ex b/lib/elixir_script/translator/kernel/special_forms/receive.ex index da13b442..75c72287 100644 --- a/lib/elixir_script/translator/kernel/special_forms/receive.ex +++ b/lib/elixir_script/translator/kernel/special_forms/receive.ex @@ -21,6 +21,7 @@ defmodule ElixirScript.Translator.Receive do ) ]) + {js, env} end @@ -47,7 +48,8 @@ defmodule ElixirScript.Translator.Receive do end def call_processes_func(func_name, params) do - JS.call_expression( + JS.yield_expression( + JS.call_expression( JS.member_expression( JS.member_expression( JS.identifier("Elixir"), @@ -59,7 +61,8 @@ defmodule ElixirScript.Translator.Receive do JS.identifier(func_name) ), params - ) + ) + ) end end diff --git a/test/translator/bitwise_test.exs b/test/translator/bitwise_test.exs new file mode 100644 index 00000000..0f9f6a57 --- /dev/null +++ b/test/translator/bitwise_test.exs @@ -0,0 +1,15 @@ +defmodule ElixirScript.Translator.Bitwise.Test do + use ExUnit.Case + import ElixirScript.TestHelper + + test "bitwise when imported" do + ex_ast = quote do + import Bitwise + 1 &&& 2 + end + + js_code = "1 & 2" + + assert_translation(ex_ast, js_code) + end +end diff --git a/test/translator/kernel/receive_test.exs b/test/translator/kernel/receive_test.exs index e1bf547b..fccc8a10 100644 --- a/test/translator/kernel/receive_test.exs +++ b/test/translator/kernel/receive_test.exs @@ -17,7 +17,7 @@ defmodule ElixirScript.Translator.Receive.Test do end js_code = """ - Elixir.Core.processes.receive(function(message) { + yield Elixir.Core.processes.receive(function(message) { return Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.clause([Symbol.for('ok')],function() { return value; }),Elixir.Core.Patterns.clause([Symbol.for('error')],function() { @@ -47,7 +47,7 @@ defmodule ElixirScript.Translator.Receive.Test do end js_code = """ - Elixir.Core.processes.receive(function(message) { + yield Elixir.Core.processes.receive(function(message) { return Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.clause([Symbol.for('ok')],function() { return value; }),Elixir.Core.Patterns.clause([Symbol.for('error')],function() { @@ -62,4 +62,30 @@ defmodule ElixirScript.Translator.Receive.Test do assert_translation(ex_ast, js_code) end + + test "translate receive" do + ex_ast = quote do + require JS + + defgen await(counter) do + receive do + {:ping, sender} -> send sender, {:pong, self} + end + end + end + + js_code = """ + const await = Elixir.Core.Patterns.defmatchgen(Elixir.Core.Patterns.clause([Elixir.Core.Patterns.variable()], function*(counter) { + return yield Elixir.Core.processes.receive(function(message) { + return Elixir.Core.Patterns.defmatchgen(Elixir.Core.Patterns.clause([Elixir.Core.Patterns.type(Elixir.Core.Tuple, { + values: [Symbol.for('ping'), Elixir.Core.Patterns.variable()] + })], function*(sender) { + return Elixir$ElixirScript$Kernel.send(sender, new Elixir.Core.Tuple(Symbol.for('pong'), Elixir$ElixirScript$Kernel.self())); + })).call(this, message); + }); + })); + """ + + assert_translation(ex_ast, js_code) + end end From 6be39e07e8dd72b4cfecc9f335120d0cb73dffcd Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Fri, 13 Jan 2017 21:03:27 -0600 Subject: [PATCH 360/860] Update tailored package --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 02cbdac2..7c7bd05b 100644 --- a/package.json +++ b/package.json @@ -21,7 +21,7 @@ "dependencies": { "erlang-types": "^1.0.0", "erlang-processes": "^2.0.0", - "tailored": "^2.0.0" + "tailored": "^2.2.0" }, "devDependencies": { "babel": "^6.5.2", From 0e00299b411e0f749781ee0b57022432698576f6 Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Fri, 13 Jan 2017 21:04:37 -0600 Subject: [PATCH 361/860] Update changelog --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index e3a3d8bf..19c7482e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -14,6 +14,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/). ### Fixed - CLI now allows a comma-separated or space-separated list of paths - Struct not properly referenced +- Tail call optimization ## [0.23.3] - 2016-11-18 From 6f5d1469b6c01aac130e6a560fbf0edc8f32c5c6 Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Sun, 15 Jan 2017 12:59:04 -0600 Subject: [PATCH 362/860] Ready for release --- CHANGELOG.md | 2 +- mix.exs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 19c7482e..8e4ba01c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,7 +4,7 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](http://keepachangelog.com/) and this project adheres to [Semantic Versioning](http://semver.org/). -## [0.24.0] - Unreleased +## [0.24.0] ### Added - Support for `sigil_r` diff --git a/mix.exs b/mix.exs index e1c28ac2..4b44c765 100644 --- a/mix.exs +++ b/mix.exs @@ -4,7 +4,7 @@ defmodule ElixirScript.Mixfile do def project do [ app: :elixir_script, - version: "0.24.0-dev", + version: "0.24.0", elixir: "~> 1.0", escript: escript_config, deps: deps, From 674402dd1948570fe3852eb7f98642566bca02f5 Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Sun, 15 Jan 2017 13:01:20 -0600 Subject: [PATCH 363/860] Update CHANGELOG.md --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 8e4ba01c..9634c91d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,7 +4,7 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](http://keepachangelog.com/) and this project adheres to [Semantic Versioning](http://semver.org/). -## [0.24.0] +## [0.24.0] - 2017-01-15 ### Added - Support for `sigil_r` From 73ed49e24fca46f96298a120015fbf2a8d63231f Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Mon, 23 Jan 2017 19:08:49 -0600 Subject: [PATCH 364/860] Make sure JS functions are translated when imported --- lib/elixir_script/translator.ex | 51 ++++++++++++++----- lib/elixir_script/translator/lexical_scope.ex | 6 ++- lib/elixir_script/translator/state.ex | 6 +-- 3 files changed, 46 insertions(+), 17 deletions(-) diff --git a/lib/elixir_script/translator.ex b/lib/elixir_script/translator.ex index dddf252b..12f9777e 100644 --- a/lib/elixir_script/translator.ex +++ b/lib/elixir_script/translator.ex @@ -563,6 +563,9 @@ defmodule ElixirScript.Translator do end defp do_translate({name, _, params} = ast, env) when is_list(params) do + if is_from_js_module(name, params, env) do + do_translate({{:., [], [{:__aliases__, [], [:JS]}, name]}, [], params }, env) + else expanded_ast = Macro.expand(ast, env.env) if expanded_ast == ast do name_arity = {name, length(params)} @@ -572,8 +575,8 @@ defmodule ElixirScript.Translator do name_arity in module.functions or name_arity in module.private_functions -> Call.make_function_call(name, params, env) ElixirScript.Translator.LexicalScope.find_module(env, name_arity) -> - imported_module_name = ElixirScript.Translator.LexicalScope.find_module(env, name_arity) - Call.make_function_call(imported_module_name, name, params, env) + imported_module_name = ElixirScript.Translator.LexicalScope.find_module(env, name_arity) + Call.make_function_call(imported_module_name, name, params, env) true -> Call.make_function_call(name, params, env) end @@ -581,22 +584,46 @@ defmodule ElixirScript.Translator do else translate(expanded_ast, env) end + end end defp do_translate({ name, _, params }, env) when is_atom(params) do - cond do - ElixirScript.Translator.LexicalScope.has_var?(env, name) -> - { Identifier.make_identifier(name), env } - has_function?(env.module, {name, 0}) -> - Call.make_function_call(name, [], env) - ElixirScript.Translator.LexicalScope.find_module(env, {name, 0}) -> - imported_module_name = ElixirScript.Translator.LexicalScope.find_module(env, {name, 0}) - Call.make_function_call(imported_module_name, name, params, env) - true -> - { Identifier.make_identifier(name), env } + if is_from_js_module(name, params, env) do + do_translate({{:., [], [{:__aliases__, [], [:JS]}, name]}, [], params }, env) + else + + cond do + ElixirScript.Translator.LexicalScope.has_var?(env, name) -> + { Identifier.make_identifier(name), env } + has_function?(env.module, {name, 0}) -> + Call.make_function_call(name, [], env) + ElixirScript.Translator.LexicalScope.find_module(env, {name, 0}) -> + imported_module_name = ElixirScript.Translator.LexicalScope.find_module(env, {name, 0}) + Call.make_function_call(imported_module_name, name, params, env) + true -> + { Identifier.make_identifier(name), env } + end end end + defp is_from_js_module(name, params, env) do + func = if is_list(params) do + {name, length(params)} + else + {name, 0} + end + + {_, macros} = Enum.find(env.env.macros, {nil, []}, fn({k, v}) -> to_string(k) == "Elixir.JS" end) + {_, functions} = Enum.find(env.env.functions, {nil, []}, fn({k, v}) -> to_string(k) == "Elixir.JS" end) + + js = macros ++ functions + + if func in js do + true + else + false + end + end def create_module_name(module_name, env) do case module_name do diff --git a/lib/elixir_script/translator/lexical_scope.ex b/lib/elixir_script/translator/lexical_scope.ex index 2c20d61c..423e2eeb 100644 --- a/lib/elixir_script/translator/lexical_scope.ex +++ b/lib/elixir_script/translator/lexical_scope.ex @@ -226,7 +226,8 @@ defmodule ElixirScript.Translator.LexicalScope do if has_module?(env, module_name) do module = get_module(env, module_name) %{ env | requires: Enum.uniq(env.requires ++ [module.name]), - functions: env.functions ++ [{ module.name, module.functions }] } + functions: env.functions ++ [{ module.name, module.functions }] + } else env end @@ -236,7 +237,8 @@ defmodule ElixirScript.Translator.LexicalScope do module = get_module(env, module_name) %{ env | functions: List.keydelete(env.functions, module_name, 0) ++ [{ module.name, module.functions }], - requires: Enum.uniq(env.requires ++ [module.name]) } + requires: Enum.uniq(env.requires ++ [module.name]) + } end def add_import(env, module_name, [only: :macros]) do diff --git a/lib/elixir_script/translator/state.ex b/lib/elixir_script/translator/state.ex index 41edd340..2070a600 100644 --- a/lib/elixir_script/translator/state.ex +++ b/lib/elixir_script/translator/state.ex @@ -11,7 +11,7 @@ defmodule ElixirScript.Translator.State do def start_link(compiler_opts, loaded_modules) do Agent.start_link(fn -> - %{ compiler_opts: compiler_opts, modules: Keyword.new, std_lib_map: build_standard_lib_map(), loaded_modules: loaded_modules } + %{ compiler_opts: compiler_opts, modules: Keyword.new, std_lib_map: build_standard_lib_map(), loaded_modules: [JS | loaded_modules] } end, name: __MODULE__) end @@ -38,7 +38,7 @@ defmodule ElixirScript.Translator.State do Agent.update(__MODULE__, fn state -> frozen_state = :erlang.binary_to_term(frozen_state) modules = Keyword.delete(frozen_state.modules, ElixirScript.Temp) - %{ state | modules: modules, std_lib_map: frozen_state.std_lib_map, loaded_modules: loaded_modules } + %{ state | modules: modules, std_lib_map: frozen_state.std_lib_map, loaded_modules: [JS | loaded_modules] } end) end @@ -82,7 +82,7 @@ defmodule ElixirScript.Translator.State do def set_loaded_modules(modules) do Agent.update(__MODULE__, fn state -> - %{ state | loaded_modules: modules } + %{ state | loaded_modules: [ JS | modules ] } end) end From 8ce40971d5a8a359950a62e7996c3209b8349143 Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Mon, 23 Jan 2017 20:17:45 -0600 Subject: [PATCH 365/860] make sure defgen and defgenp are compiled correctly when calling from JS module --- lib/elixir_script/translator.ex | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/lib/elixir_script/translator.ex b/lib/elixir_script/translator.ex index 12f9777e..b83a1132 100644 --- a/lib/elixir_script/translator.ex +++ b/lib/elixir_script/translator.ex @@ -281,6 +281,10 @@ defmodule ElixirScript.Translator do translate({{:., context1, [{:__aliases__, context2, [:Elixir, :Enum]}, function_name]}, context3, params }, env) end + defp do_translate({{:., _, [{:__aliases__, _, [:JS]}, function_name]}, _, params }, env) when function_name in @generator_types do + do_translate({function_name, [], params}, env) + end + defp do_translate({{:., _, [{:__aliases__, _, [:JS]}, function_name]}, _, params }, env) do JSLib.translate_js_function(function_name, params, env) end From 863e21f6f090544a987b5edf234d408755498e20 Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Mon, 23 Jan 2017 20:35:42 -0600 Subject: [PATCH 366/860] refactoring --- lib/elixir_script/translator.ex | 7 ++----- test/elixir_script_test.exs | 1 + 2 files changed, 3 insertions(+), 5 deletions(-) diff --git a/lib/elixir_script/translator.ex b/lib/elixir_script/translator.ex index b83a1132..bdee21ed 100644 --- a/lib/elixir_script/translator.ex +++ b/lib/elixir_script/translator.ex @@ -592,11 +592,9 @@ defmodule ElixirScript.Translator do end defp do_translate({ name, _, params }, env) when is_atom(params) do - if is_from_js_module(name, params, env) do - do_translate({{:., [], [{:__aliases__, [], [:JS]}, name]}, [], params }, env) - else - cond do + is_from_js_module(name, params, env) -> + do_translate({{:., [], [{:__aliases__, [], [:JS]}, name]}, [], params }, env) ElixirScript.Translator.LexicalScope.has_var?(env, name) -> { Identifier.make_identifier(name), env } has_function?(env.module, {name, 0}) -> @@ -607,7 +605,6 @@ defmodule ElixirScript.Translator do true -> { Identifier.make_identifier(name), env } end - end end defp is_from_js_module(name, params, env) do diff --git a/test/elixir_script_test.exs b/test/elixir_script_test.exs index a40365af..45e881bb 100644 --- a/test/elixir_script_test.exs +++ b/test/elixir_script_test.exs @@ -15,6 +15,7 @@ defmodule ElixirScript.Test do use ElixirScript.Using defp something_else() do + new Date, [] ElixirScript.Math.squared(1) end From 294a3b9dae86f76e12f612622c13d22d92013ad4 Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Mon, 23 Jan 2017 20:39:02 -0600 Subject: [PATCH 367/860] Fix test --- test/elixir_script_test.exs | 1 - 1 file changed, 1 deletion(-) diff --git a/test/elixir_script_test.exs b/test/elixir_script_test.exs index 45e881bb..a40365af 100644 --- a/test/elixir_script_test.exs +++ b/test/elixir_script_test.exs @@ -15,7 +15,6 @@ defmodule ElixirScript.Test do use ElixirScript.Using defp something_else() do - new Date, [] ElixirScript.Math.squared(1) end From 6ef28feaf125ced02900746cb3b5ce49f00a66c0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jakub=20Zawi=C5=9Blak?= Date: Sun, 12 Feb 2017 19:20:11 +0100 Subject: [PATCH 368/860] Fixed getting started link --- FAQ.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/FAQ.md b/FAQ.md index 50a7dcc8..cfb7df3a 100644 --- a/FAQ.md +++ b/FAQ.md @@ -2,7 +2,7 @@ # Q. How do I get started? -### A. Check out the [Getting Started](GettingStarted.html) Guide for more info. +### A. Check out the [Getting Started](GettingStarted.md) Guide for more info. # Q. How much is implemented? From ef944ac8098e3f93aebdc18b7857a65ff41ae32e Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Mon, 13 Feb 2017 20:37:50 -0600 Subject: [PATCH 369/860] Update compile.elixir_script to support getting elixirscript paths from deps --- CHANGELOG.md | 8 ++++++++ lib/mix/tasks/compile.elixir_script.ex | 25 +++++++++++++++++++---- mix.exs | 9 ++++----- mix.lock | 28 +++++++++++++------------- 4 files changed, 47 insertions(+), 23 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 9634c91d..2a8abf1e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,14 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](http://keepachangelog.com/) and this project adheres to [Semantic Versioning](http://semver.org/). +## [0.24.1-dev] +### Added +- Updated elixir_script mix compiler to support compiling elixir_script paths in dependencies + +### Fixed +- JS module functions not translated properly when imported +- Update fs dependency to 2.12 + ## [0.24.0] - 2017-01-15 ### Added diff --git a/lib/mix/tasks/compile.elixir_script.ex b/lib/mix/tasks/compile.elixir_script.ex index cbafeb5d..153bf87b 100644 --- a/lib/mix/tasks/compile.elixir_script.ex +++ b/lib/mix/tasks/compile.elixir_script.ex @@ -21,16 +21,33 @@ defmodule Mix.Tasks.Compile.ElixirScript do def run(_) do elixirscript_config = get_elixirscript_config() + + elixirscript_base = Path.join([Mix.Project.build_path, "elixirscript"]) + File.mkdir_p!(elixirscript_base) + elixirscript_path = Path.join([elixirscript_base, "#{Mix.Project.config[:app]}"]) + input_path = Keyword.fetch!(elixirscript_config, :input) - output_path = Keyword.fetch!(elixirscript_config, :output) + |> List.wrap + |> Enum.map(fn(path) -> + Path.absname(path) + end) + |> Enum.join("\n") + + File.write!(elixirscript_path, input_path) - ElixirScript.compile_path(input_path, %{ output: output_path }) + paths = Path.join([elixirscript_base, "*"]) + |> Path.wildcard + |> Enum.map(fn(path) -> + File.read!(path) + end) + + output_path = Keyword.fetch!(elixirscript_config, :output) + ElixirScript.compile_path(paths, %{output: output_path}) :ok end def clean do elixirscript_config = get_elixirscript_config() - input_path = Keyword.fetch!(elixirscript_config, :input) output_path = Keyword.fetch!(elixirscript_config, :output) File.ls!(output_path) @@ -45,7 +62,7 @@ defmodule Mix.Tasks.Compile.ElixirScript do defp get_elixirscript_config() do config = Mix.Project.config - Keyword.fetch!(config, :elixir_script) + Keyword.fetch!(config, :elixir_script) || Keyword.fetch!(config, :elixirscript) end end diff --git a/mix.exs b/mix.exs index 4b44c765..a2ef5f84 100644 --- a/mix.exs +++ b/mix.exs @@ -4,7 +4,7 @@ defmodule ElixirScript.Mixfile do def project do [ app: :elixir_script, - version: "0.24.0", + version: "0.24.1-dev", elixir: "~> 1.0", escript: escript_config, deps: deps, @@ -28,10 +28,9 @@ defmodule ElixirScript.Mixfile do defp deps do [ - {:estree, "~> 2.5" }, - {:fs, "~> 0.9.1"}, - {:earmark, "~> 1.0", only: :dev }, - {:ex_doc, "~> 0.14", only: :dev }, + {:estree, "~> 2.5"}, + {:fs, "~> 2.12"}, + {:ex_doc, "~> 0.14", only: :dev}, {:excoveralls, "~> 0.5", only: :test}, {:credo, "~> 0.4", only: [:dev, :test]} ] diff --git a/mix.lock b/mix.lock index 8df49871..32939a49 100644 --- a/mix.lock +++ b/mix.lock @@ -1,15 +1,15 @@ -%{"bunt": {:hex, :bunt, "0.1.6", "5d95a6882f73f3b9969fdfd1953798046664e6f77ec4e486e6fafc7caad97c6f", [:mix], []}, - "certifi": {:hex, :certifi, "0.4.0", "a7966efb868b179023618d29a407548f70c52466bf1849b9e8ebd0e34b7ea11f", [:rebar3], []}, - "credo": {:hex, :credo, "0.4.12", "f5e1973405ea25c6e64959fb0b6bf92950147a0278cc2a002a491b45f78f7b87", [:mix], [{:bunt, "~> 0.1.6", [hex: :bunt, optional: false]}]}, - "earmark": {:hex, :earmark, "1.0.2", "a0b0904d74ecc14da8bd2e6e0248e1a409a2bc91aade75fcf428125603de3853", [:mix], []}, +%{"bunt": {:hex, :bunt, "0.2.0", "951c6e801e8b1d2cbe58ebbd3e616a869061ddadcc4863d0a2182541acae9a38", [:mix], []}, + "certifi": {:hex, :certifi, "0.7.0", "861a57f3808f7eb0c2d1802afeaae0fa5de813b0df0979153cbafcd853ababaf", [:rebar3], []}, + "credo": {:hex, :credo, "0.6.1", "a941e2591bd2bd2055dc92b810c174650b40b8290459c89a835af9d59ac4a5f8", [:mix], [{:bunt, "~> 0.2.0", [hex: :bunt, optional: false]}]}, + "earmark": {:hex, :earmark, "1.1.1", "433136b7f2e99cde88b745b3a0cfc3fbc81fe58b918a09b40fce7f00db4d8187", [:mix], []}, "estree": {:hex, :estree, "2.5.0", "9776c1705a72dc5a0d56cdf431173c3e75f9e509278a857ec55374a49f5699ef", [:mix], []}, - "ex_doc": {:hex, :ex_doc, "0.14.3", "e61cec6cf9731d7d23d254266ab06ac1decbb7651c3d1568402ec535d387b6f7", [:mix], [{:earmark, "~> 1.0", [hex: :earmark, optional: false]}]}, - "excoveralls": {:hex, :excoveralls, "0.5.7", "5d26e4a7cdf08294217594a1b0643636accc2ad30e984d62f1d166f70629ff50", [:mix], [{:exjsx, "~> 3.0", [hex: :exjsx, optional: false]}, {:hackney, ">= 0.12.0", [hex: :hackney, optional: false]}]}, - "exjsx": {:hex, :exjsx, "3.2.1", "1bc5bf1e4fd249104178f0885030bcd75a4526f4d2a1e976f4b428d347614f0f", [:mix], [{:jsx, "~> 2.8.0", [hex: :jsx, optional: false]}]}, - "fs": {:hex, :fs, "0.9.2", "ed17036c26c3f70ac49781ed9220a50c36775c6ca2cf8182d123b6566e49ec59", [:rebar], []}, - "hackney": {:hex, :hackney, "1.6.1", "ddd22d42db2b50e6a155439c8811b8f6df61a4395de10509714ad2751c6da817", [:rebar3], [{:certifi, "0.4.0", [hex: :certifi, optional: false]}, {:idna, "1.2.0", [hex: :idna, optional: false]}, {:metrics, "1.0.1", [hex: :metrics, optional: false]}, {:mimerl, "1.0.2", [hex: :mimerl, optional: false]}, {:ssl_verify_fun, "1.1.0", [hex: :ssl_verify_fun, optional: false]}]}, - "idna": {:hex, :idna, "1.2.0", "ac62ee99da068f43c50dc69acf700e03a62a348360126260e87f2b54eced86b2", [:rebar3], []}, - "jsx": {:hex, :jsx, "2.8.0", "749bec6d205c694ae1786d62cea6cc45a390437e24835fd16d12d74f07097727", [:mix, :rebar], []}, - "metrics": {:hex, :metrics, "1.0.1", "25f094dea2cda98213cecc3aeff09e940299d950904393b2a29d191c346a8486", [:rebar3], []}, - "mimerl": {:hex, :mimerl, "1.0.2", "993f9b0e084083405ed8252b99460c4f0563e41729ab42d9074fd5e52439be88", [:rebar3], []}, - "ssl_verify_fun": {:hex, :ssl_verify_fun, "1.1.0", "edee20847c42e379bf91261db474ffbe373f8acb56e9079acb6038d4e0bf414f", [:rebar, :make], []}} + "ex_doc": {:hex, :ex_doc, "0.14.5", "c0433c8117e948404d93ca69411dd575ec6be39b47802e81ca8d91017a0cf83c", [:mix], [{:earmark, "~> 1.0", [hex: :earmark, optional: false]}]}, + "excoveralls": {:hex, :excoveralls, "0.6.2", "0e993d096f1fbb6e70a3daced5c89aac066bda6bce57829622aa2d1e2b338cfb", [:mix], [{:exjsx, "~> 3.0", [hex: :exjsx, optional: false]}, {:hackney, ">= 0.12.0", [hex: :hackney, optional: false]}]}, + "exjsx": {:hex, :exjsx, "3.2.1", "1bc5bf1e4fd249104178f0885030bcd75a4526f4d2a1e976f4b428d347614f0f", [], [{:jsx, "~> 2.8.0", [hex: :jsx, optional: false]}]}, + "fs": {:hex, :fs, "2.12.0", "ad631efacc9a5683c8eaa1b274e24fa64a1b8eb30747e9595b93bec7e492e25e", [:rebar3], []}, + "hackney": {:hex, :hackney, "1.6.5", "8c025ee397ac94a184b0743c73b33b96465e85f90a02e210e86df6cbafaa5065", [:rebar3], [{:certifi, "0.7.0", [hex: :certifi, optional: false]}, {:idna, "1.2.0", [hex: :idna, optional: false]}, {:metrics, "1.0.1", [hex: :metrics, optional: false]}, {:mimerl, "1.0.2", [hex: :mimerl, optional: false]}, {:ssl_verify_fun, "1.1.1", [hex: :ssl_verify_fun, optional: false]}]}, + "idna": {:hex, :idna, "1.2.0", "ac62ee99da068f43c50dc69acf700e03a62a348360126260e87f2b54eced86b2", [], []}, + "jsx": {:hex, :jsx, "2.8.2", "7acc7d785b5abe8a6e9adbde926a24e481f29956dd8b4df49e3e4e7bcc92a018", [:mix, :rebar3], []}, + "metrics": {:hex, :metrics, "1.0.1", "25f094dea2cda98213cecc3aeff09e940299d950904393b2a29d191c346a8486", [], []}, + "mimerl": {:hex, :mimerl, "1.0.2", "993f9b0e084083405ed8252b99460c4f0563e41729ab42d9074fd5e52439be88", [], []}, + "ssl_verify_fun": {:hex, :ssl_verify_fun, "1.1.1", "28a4d65b7f59893bc2c7de786dec1e1555bd742d336043fe644ae956c3497fbe", [:make, :rebar], []}} From 74fc7bd759e9700f0965a5fc0e4d88b5bc2b1120 Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Tue, 14 Feb 2017 22:05:11 -0600 Subject: [PATCH 370/860] Updated compile_path to allow paths and apps to be passed in --- lib/elixir_script.ex | 37 +++++++--- lib/elixir_script/prelude/module.ex | 2 +- .../translator/kernel/defmodule.ex | 18 ++--- lib/elixir_script/translator/utils.ex | 4 +- lib/mix/tasks/compile.elixir_script.ex | 5 +- mix.exs | 10 +-- test/elixir_script_test.exs | 4 +- test/test_helper.exs | 2 +- test/translator/defmodule_test.exs | 67 +++++++++++-------- 9 files changed, 90 insertions(+), 59 deletions(-) diff --git a/lib/elixir_script.ex b/lib/elixir_script.ex index ca73429e..cb0b9c1e 100644 --- a/lib/elixir_script.ex +++ b/lib/elixir_script.ex @@ -120,26 +120,48 @@ defmodule ElixirScript do @doc """ Compiles the elixir files found at the given path """ - @spec compile_path(binary | [binary], Map.t) :: [binary | {binary, binary} | :ok] - def compile_path(path, opts \\ %{}) do + @spec compile_path(binary | [binary] | map, Map.t) :: [binary | {binary, binary} | :ok] + def compile_path(path, opts \\ %{}) + + def compile_path(path, opts) when is_binary(path) do + compile_path([path], opts) + end + + def compile_path(path, opts) when is_list(path) do + built_opts = build_compiler_options(opts) + + app_name = cond do + !is_nil(built_opts[:app]) -> + opts[:app] + Code.ensure_loaded?(Mix) -> + Mix.Project.config()[:app] + true -> + :app + end + + compile_path(Map.put(%{}, app_name, path), opts) + end + + def compile_path(path, opts) do opts = build_compiler_options(opts) - result = %{ path: path } + deps = path + |> Map.to_list + |> Enum.map(fn {app, path} -> {app, List.wrap(path)} end) + + result = %{ data: deps } |> ElixirScript.Passes.Init.execute(opts) - |> ElixirScript.Passes.DepsPaths.execute(opts) |> ElixirScript.Passes.ASTFromFile.execute(opts) |> ElixirScript.Passes.LoadModules.execute(opts) |> ElixirScript.Passes.FindModules.execute(opts) |> ElixirScript.Passes.FindLoadOnly.execute(opts) - |> ElixirScript.Passes.FindChangedFiles.execute(opts) |> ElixirScript.Passes.FindFunctions.execute(opts) |> ElixirScript.Passes.AddStdLib.execute(opts) |> ElixirScript.Passes.JavaScriptAST.execute(opts) |> ElixirScript.Passes.ConsolidateProtocols.execute(opts) |> ElixirScript.Passes.JavaScriptCode.execute(opts) |> ElixirScript.Passes.JavaScriptName.execute(opts) - |> ElixirScript.Passes.WriteCache.execute(opts) |> ElixirScript.Passes.HandleOutput.execute(opts) result @@ -168,9 +190,8 @@ defmodule ElixirScript do opts = build_compiler_options(%{std_lib: true, include_path: true, output: output_path, app: :elixir}) libs_path = Path.join([__DIR__, "elixir_script", "prelude"]) - result = %{ path: libs_path } + result = %{ data: [{:elixir, List.wrap(libs_path)}] } |> ElixirScript.Passes.Init.execute(opts) - |> ElixirScript.Passes.DepsPaths.execute(opts) |> ElixirScript.Passes.ASTFromFile.execute(opts) |> ElixirScript.Passes.FindModules.execute(opts) |> ElixirScript.Passes.FindLoadOnly.execute(opts) diff --git a/lib/elixir_script/prelude/module.ex b/lib/elixir_script/prelude/module.ex index 44c1acc4..f1454a5d 100644 --- a/lib/elixir_script/prelude/module.ex +++ b/lib/elixir_script/prelude/module.ex @@ -4,6 +4,6 @@ defmodule ElixirScript.Module do defstruct name: nil, functions: Keyword.new, private_functions: Keyword.new, body: nil, js_imports: [], module_refs: [], type: :module, - impls: HashDict.new, impl_type: nil, app_name: nil + impls: Map.new, impl_type: nil, app_name: nil end diff --git a/lib/elixir_script/translator/kernel/defmodule.ex b/lib/elixir_script/translator/kernel/defmodule.ex index 8199692f..edba9c78 100644 --- a/lib/elixir_script/translator/kernel/defmodule.ex +++ b/lib/elixir_script/translator/kernel/defmodule.ex @@ -84,46 +84,46 @@ defmodule ElixirScript.Translator.Defmodule do def extract_functions_from_module({:__block__, meta, body_list}) do { body_list, functions } = Enum.map_reduce(body_list, - %{exported: HashDict.new(), private: HashDict.new(), exported_generators: HashDict.new(), private_generators: HashDict.new()}, fn + %{exported: Map.new(), private: Map.new(), exported_generators: Map.new(), private_generators: Map.new()}, fn ({:def, _, [{:when, _, [{name, _, _} | _guards] }, _] } = function, state) -> { nil, - %{ state | exported: HashDict.put(state.exported, name, HashDict.get(state.exported, name, []) ++ [function]) } + %{ state | exported: Map.put(state.exported, name, Map.get(state.exported, name, []) ++ [function]) } } ({:def, _, [{name, _, _}, _]} = function, state) -> { nil, - %{ state | exported: HashDict.put(state.exported, name, HashDict.get(state.exported, name, []) ++ [function]) } + %{ state | exported: Map.put(state.exported, name, Map.get(state.exported, name, []) ++ [function]) } } ({:defp, _, [{:when, _, [{name, _, _} | _guards] }, _] } = function, state) -> { nil, - %{ state | private: HashDict.put(state.private, name, HashDict.get(state.private, name, []) ++ [function]) } + %{ state | private: Map.put(state.private, name, Map.get(state.private, name, []) ++ [function]) } } ({:defp, _, [{name, _, _}, _]} = function, state) -> { nil, - %{ state | private: HashDict.put(state.private, name, HashDict.get(state.private, name, []) ++ [function]) } + %{ state | private: Map.put(state.private, name, Map.get(state.private, name, []) ++ [function]) } } ({:defgen, _, [{:when, _, [{name, _, _} | _guards] }, _] } = function, state) -> { nil, - %{ state | exported_generators: HashDict.put(state.exported_generators, name, HashDict.get(state.exported_generators, name, []) ++ [function]) } + %{ state | exported_generators: Map.put(state.exported_generators, name, Map.get(state.exported_generators, name, []) ++ [function]) } } ({:defgen, _, [{name, _, _}, _]} = function, state) -> { nil, - %{ state | exported_generators: HashDict.put(state.exported_generators, name, HashDict.get(state.exported_generators, name, []) ++ [function]) } + %{ state | exported_generators: Map.put(state.exported_generators, name, Map.get(state.exported_generators, name, []) ++ [function]) } } ({:defgenp, _, [{:when, _, [{name, _, _} | _guards] }, _] } = function, state) -> { nil, - %{ state | private_generators: HashDict.put(state.private_generators, name, HashDict.get(state.private_generators, name, []) ++ [function]) } + %{ state | private_generators: Map.put(state.private_generators, name, Map.get(state.private_generators, name, []) ++ [function]) } } ({:defgenp, _, [{name, _, _}, _]} = function, state) -> { nil, - %{ state | private_generators: HashDict.put(state.private_generators, name, HashDict.get(state.private_generators, name, []) ++ [function]) } + %{ state | private_generators: Map.put(state.private_generators, name, Map.get(state.private_generators, name, []) ++ [function]) } } (x, state) -> { x, state } diff --git a/lib/elixir_script/translator/utils.ex b/lib/elixir_script/translator/utils.ex index 66fd6538..0c573c0e 100644 --- a/lib/elixir_script/translator/utils.ex +++ b/lib/elixir_script/translator/utils.ex @@ -30,9 +30,9 @@ defmodule ElixirScript.Translator.Utils do Enum.join([:Elixir] ++ name, ".") end - def make_local_file_path(module_app_name, file_name) when is_atom(module_app_name) do + def make_local_file_path(module_app_name, file_name) do root = ElixirScript.Translator.State.get().compiler_opts.root - app_name = to_string(module_app_name) + app_name = if is_binary(module_app_name), do: module_app_name, else: to_string(module_app_name) case root do nil -> diff --git a/lib/mix/tasks/compile.elixir_script.ex b/lib/mix/tasks/compile.elixir_script.ex index 153bf87b..bdf523ed 100644 --- a/lib/mix/tasks/compile.elixir_script.ex +++ b/lib/mix/tasks/compile.elixir_script.ex @@ -37,9 +37,10 @@ defmodule Mix.Tasks.Compile.ElixirScript do paths = Path.join([elixirscript_base, "*"]) |> Path.wildcard - |> Enum.map(fn(path) -> - File.read!(path) + |> Enum.map(fn(path) -> + {Path.basename(path), File.read!(path)} end) + |> Map.new output_path = Keyword.fetch!(elixirscript_config, :output) ElixirScript.compile_path(paths, %{output: output_path}) diff --git a/mix.exs b/mix.exs index a2ef5f84..37513bb7 100644 --- a/mix.exs +++ b/mix.exs @@ -6,12 +6,12 @@ defmodule ElixirScript.Mixfile do app: :elixir_script, version: "0.24.1-dev", elixir: "~> 1.0", - escript: escript_config, - deps: deps, - description: description, - package: package, + escript: escript_config(), + deps: deps(), + description: description(), + package: package(), source_url: "https://github.com/bryanjos/elixirscript", - aliases: aliases, + aliases: aliases(), test_coverage: [tool: ExCoveralls], preferred_cli_env: [coveralls: :test], docs: [ diff --git a/test/elixir_script_test.exs b/test/elixir_script_test.exs index a40365af..aed71914 100644 --- a/test/elixir_script_test.exs +++ b/test/elixir_script_test.exs @@ -19,7 +19,7 @@ defmodule ElixirScript.Test do end end - """, %{ env: make_custom_env }) + """, %{ env: make_custom_env() }) assert_js_matches """ import Elixir$ElixirScript$Kernel from '../elixir/Elixir.ElixirScript.Kernel'; @@ -47,7 +47,7 @@ defmodule ElixirScript.Test do end end - """, %{ env: make_custom_env, core_path: "elixirscript"} ) + """, %{ env: make_custom_env(), core_path: "elixirscript"} ) assert_js_matches """ import Elixir$ElixirScript$Kernel from '../elixir/Elixir.ElixirScript.Kernel'; diff --git a/test/test_helper.exs b/test/test_helper.exs index d5b1bcbf..863353a9 100644 --- a/test/test_helper.exs +++ b/test/test_helper.exs @@ -30,7 +30,7 @@ defmodule ElixirScript.TestHelper do end def ex_ast_to_js(ex_ast) do - ElixirScript.compile_quoted(ex_ast, %{ env: make_custom_env, import_standard_libs: false }) + ElixirScript.compile_quoted(ex_ast, %{ env: make_custom_env(), import_standard_libs: false }) end def strip_spaces(js) do diff --git a/test/translator/defmodule_test.exs b/test/translator/defmodule_test.exs index e49ffc2b..4e204f48 100644 --- a/test/translator/defmodule_test.exs +++ b/test/translator/defmodule_test.exs @@ -234,23 +234,28 @@ defmodule ElixirScript.Translator.Defmodule.Test do end js_code = """ - import Elixir$ElixirScript$Kernel from '../elixir/Elixir.ElixirScript.Kernel'; - const oh_my2 = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.clause([],function() { - return null; - })); + import Elixir$ElixirScript$Kernel from '../elixir/Elixir.ElixirScript.Kernel'; - const oh_my = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.clause([],function() { - return null; - })); + const oh_my = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.clause([], function() { + return null; + })); - export default { - oh_my2, oh_my - }; + const oh_my2 = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.clause([], function() { + return null; + })); - import Elixir$ElixirScript$Kernel from '../elixir/Elixir.ElixirScript.Kernel'; - import Elixir$Lions$Tigers from '../app/Elixir.Lions.Tigers'; - Elixir$Lions$Tigers.oh_my(); - export default {}; + export default { + oh_my, + oh_my2 + }; + + import Elixir$ElixirScript$Kernel from '../elixir/Elixir.ElixirScript.Kernel'; + + import Elixir$Lions$Tigers from '../app/Elixir.Lions.Tigers'; + + Elixir$Lions$Tigers.oh_my(); + + export default {}; """ assert_translation(ex_ast, js_code) @@ -274,24 +279,28 @@ defmodule ElixirScript.Translator.Defmodule.Test do end js_code = """ - import Elixir$ElixirScript$Kernel from '../elixir/Elixir.ElixirScript.Kernel'; - const oh_my2 = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.clause([],function() { - return null; - })); + import Elixir$ElixirScript$Kernel from '../elixir/Elixir.ElixirScript.Kernel'; - const oh_my = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.clause([],function() { - return null; - })); + const oh_my = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.clause([], function() { + return null; + })); - export default { - oh_my2, - oh_my - }; + const oh_my2 = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.clause([], function() { + return null; + })); - import Elixir$ElixirScript$Kernel from '../elixir/Elixir.ElixirScript.Kernel'; - import Elixir$Lions$Tigers from '../app/Elixir.Lions.Tigers'; - Elixir$Lions$Tigers.oh_my2(); - export default {}; + export default { + oh_my, + oh_my2 + }; + + import Elixir$ElixirScript$Kernel from '../elixir/Elixir.ElixirScript.Kernel'; + + import Elixir$Lions$Tigers from '../app/Elixir.Lions.Tigers'; + + Elixir$Lions$Tigers.oh_my2(); + + export default {}; """ assert_translation(ex_ast, js_code) From e303d39c8729fcd0a7f11d3e7f0e642d80ead404 Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Wed, 15 Feb 2017 18:34:29 -0600 Subject: [PATCH 371/860] State now takes a pid --- .credo.exs | 129 ++++++++++++++++++ lib/elixir_script.ex | 6 +- lib/elixir_script/passes/add_std_lib.ex | 4 +- .../passes/consolidate_protocols.ex | 8 +- .../passes/find_changed_files.ex | 2 +- lib/elixir_script/passes/find_modules.ex | 20 +-- lib/elixir_script/passes/handle_output.ex | 8 +- lib/elixir_script/passes/init.ex | 4 +- lib/elixir_script/passes/java_script_ast.ex | 14 +- lib/elixir_script/passes/write_cache.ex | 4 +- lib/elixir_script/translator.ex | 14 +- .../translator/kernel/defmodule.ex | 24 ++-- .../translator/kernel/defprotocol.ex | 16 +-- .../translator/kernel/special_forms/call.ex | 4 +- .../translator/kernel/special_forms/fn.ex | 64 +++++---- .../translator/kernel/special_forms/struct.ex | 7 +- lib/elixir_script/translator/lexical_scope.ex | 40 +++--- lib/elixir_script/translator/state.ex | 80 +++++------ lib/elixir_script/translator/utils.ex | 10 +- test/translator/pattern_matching_test.exs | 84 ++++++------ 20 files changed, 340 insertions(+), 202 deletions(-) create mode 100644 .credo.exs diff --git a/.credo.exs b/.credo.exs new file mode 100644 index 00000000..ca7b102a --- /dev/null +++ b/.credo.exs @@ -0,0 +1,129 @@ +# This file contains the configuration for Credo and you are probably reading +# this after creating it with `mix credo.gen.config`. +# +# If you find anything wrong or unclear in this file, please report an +# issue on GitHub: https://github.com/rrrene/credo/issues +# +%{ + # + # You can have as many configs as you like in the `configs:` field. + configs: [ + %{ + # + # Run any config using `mix credo -C `. If no config name is given + # "default" is used. + name: "default", + # + # These are the files included in the analysis: + files: %{ + # + # You can give explicit globs or simply directories. + # In the latter case `**/*.{ex,exs}` will be used. + included: ["lib/", "src/", "web/", "apps/"], + excluded: [~r"/_build/", ~r"/deps/"] + }, + # + # If you create your own checks, you must specify the source files for + # them here, so they can be loaded by Credo before running the analysis. + requires: [], + # + # Credo automatically checks for updates, like e.g. Hex does. + # You can disable this behaviour below: + check_for_updates: true, + # + # If you want to enforce a style guide and need a more traditional linting + # experience, you can change `strict` to `true` below: + strict: false, + # + # If you want to use uncolored output by default, you can change `color` + # to `false` below: + color: true, + # + # You can customize the parameters of any check by adding a second element + # to the tuple. + # + # To disable a check put `false` as second element: + # + # {Credo.Check.Design.DuplicatedCode, false} + # + checks: [ + {Credo.Check.Consistency.ExceptionNames}, + {Credo.Check.Consistency.LineEndings}, + {Credo.Check.Consistency.MultiAliasImportRequireUse}, + {Credo.Check.Consistency.ParameterPatternMatching}, + {Credo.Check.Consistency.SpaceAroundOperators}, + {Credo.Check.Consistency.SpaceInParentheses}, + {Credo.Check.Consistency.TabsOrSpaces}, + + # For some checks, like AliasUsage, you can only customize the priority + # Priority values are: `low, normal, high, higher` + {Credo.Check.Design.AliasUsage, priority: :low}, + + # For others you can set parameters + + # If you don't want the `setup` and `test` macro calls in ExUnit tests + # or the `schema` macro in Ecto schemas to trigger DuplicatedCode, just + # set the `excluded_macros` parameter to `[:schema, :setup, :test]`. + {Credo.Check.Design.DuplicatedCode, excluded_macros: []}, + + # You can also customize the exit_status of each check. + # If you don't want TODO comments to cause `mix credo` to fail, just + # set this value to 0 (zero). + {Credo.Check.Design.TagTODO, exit_status: 2}, + {Credo.Check.Design.TagFIXME}, + + {Credo.Check.Readability.FunctionNames}, + {Credo.Check.Readability.LargeNumbers}, + {Credo.Check.Readability.MaxLineLength, priority: :low, max_length: 80}, + {Credo.Check.Readability.ModuleAttributeNames}, + {Credo.Check.Readability.ModuleDoc}, + {Credo.Check.Readability.ModuleNames}, + {Credo.Check.Readability.NoParenthesesWhenZeroArity}, + {Credo.Check.Readability.ParenthesesInCondition}, + {Credo.Check.Readability.PredicateFunctionNames}, + {Credo.Check.Readability.PreferImplicitTry}, + {Credo.Check.Readability.RedundantBlankLines}, + {Credo.Check.Readability.Specs}, + {Credo.Check.Readability.StringSigils}, + {Credo.Check.Readability.TrailingBlankLine}, + {Credo.Check.Readability.TrailingWhiteSpace}, + {Credo.Check.Readability.VariableNames}, + {Credo.Check.Refactor.DoubleBooleanNegation}, + + # {Credo.Check.Refactor.CaseTrivialMatches}, # deprecated in 0.4.0 + {Credo.Check.Refactor.ABCSize}, + {Credo.Check.Refactor.CondStatements}, + {Credo.Check.Refactor.CyclomaticComplexity}, + {Credo.Check.Refactor.FunctionArity}, + {Credo.Check.Refactor.MatchInCondition}, + {Credo.Check.Refactor.NegatedConditionsInUnless}, + {Credo.Check.Refactor.NegatedConditionsWithElse}, + {Credo.Check.Refactor.Nesting}, + {Credo.Check.Refactor.PipeChainStart}, + {Credo.Check.Refactor.UnlessWithElse}, + {Credo.Check.Refactor.VariableRebinding}, + + {Credo.Check.Warning.BoolOperationOnSameValues}, + {Credo.Check.Warning.IExPry}, + {Credo.Check.Warning.IoInspect}, + {Credo.Check.Warning.NameRedeclarationByAssignment}, + {Credo.Check.Warning.NameRedeclarationByCase}, + {Credo.Check.Warning.NameRedeclarationByDef}, + {Credo.Check.Warning.NameRedeclarationByFn}, + {Credo.Check.Warning.OperationOnSameValues}, + {Credo.Check.Warning.OperationWithConstantResult}, + {Credo.Check.Warning.UnusedEnumOperation}, + {Credo.Check.Warning.UnusedFileOperation}, + {Credo.Check.Warning.UnusedKeywordOperation}, + {Credo.Check.Warning.UnusedListOperation}, + {Credo.Check.Warning.UnusedPathOperation}, + {Credo.Check.Warning.UnusedRegexOperation}, + {Credo.Check.Warning.UnusedStringOperation}, + {Credo.Check.Warning.UnusedTupleOperation}, + + # Custom checks can be created using `mix credo.gen.check`. + # + ] + } + ] +} diff --git a/lib/elixir_script.ex b/lib/elixir_script.ex index cb0b9c1e..ec987923 100644 --- a/lib/elixir_script.ex +++ b/lib/elixir_script.ex @@ -73,7 +73,7 @@ defmodule ElixirScript do |> get_modules_from_quoted |> Enum.map(fn(x) -> %{ast: x, app: :app} end) - result = %{ data: data } + result = %{data: data} |> ElixirScript.Passes.Init.execute(opts) |> ElixirScript.Passes.FindModules.execute(opts) |> ElixirScript.Passes.FindLoadOnly.execute(opts) @@ -90,7 +90,7 @@ defmodule ElixirScript do defp get_modules_from_quoted(quoted) do results = case quoted do - { :__block__, _, list } -> + {:__block__, _, list} -> {modules, not_modules} = Enum.partition(list, fn {type, _, _ } when type in [:defprotocol, :defimpl, :defmodule] -> @@ -150,7 +150,7 @@ defmodule ElixirScript do |> Map.to_list |> Enum.map(fn {app, path} -> {app, List.wrap(path)} end) - result = %{ data: deps } + result = %{data: deps} |> ElixirScript.Passes.Init.execute(opts) |> ElixirScript.Passes.ASTFromFile.execute(opts) |> ElixirScript.Passes.LoadModules.execute(opts) diff --git a/lib/elixir_script/passes/add_std_lib.ex b/lib/elixir_script/passes/add_std_lib.ex index 2cb7a127..cfad4105 100644 --- a/lib/elixir_script/passes/add_std_lib.ex +++ b/lib/elixir_script/passes/add_std_lib.ex @@ -2,8 +2,8 @@ defmodule ElixirScript.Passes.AddStdLib do @moduledoc false alias ElixirScript.Translator.State - def execute(compiler_data, _) do - State.deserialize(ElixirScript.get_stdlib_state, []) + def execute(compiler_data, opts) do + State.deserialize(compiler_data.state, ElixirScript.get_stdlib_state, []) compiler_data end diff --git a/lib/elixir_script/passes/consolidate_protocols.ex b/lib/elixir_script/passes/consolidate_protocols.ex index 60c1e33e..81bc70b9 100644 --- a/lib/elixir_script/passes/consolidate_protocols.ex +++ b/lib/elixir_script/passes/consolidate_protocols.ex @@ -7,8 +7,8 @@ defmodule ElixirScript.Passes.ConsolidateProtocols do require Logger def execute(compiler_data, opts) do - State.set_module_data(compiler_data.data) - data = State.get_module_data() + State.set_module_data(compiler_data.state, compiler_data.data) + data = State.get_module_data(compiler_data.state) only_protocols_and_impls = Enum.filter(data, fn ({_, %{type: :module}}) -> @@ -55,7 +55,7 @@ defmodule ElixirScript.Passes.ConsolidateProtocols do end defp make_defimpl(name, { _, protocol }, implementations, compiler_opts) do - imports = [ModuleSystems.import_module(:Elixir, Utils.make_local_file_path(:elixir, compiler_opts.core_path, compiler_opts.root))] + imports = [ModuleSystems.import_module(:Elixir, Utils.make_local_file_path(:elixir, compiler_opts.core_path, compiler_opts.root, nil))] declarator = JS.variable_declarator( JS.identifier("impls"), @@ -74,7 +74,7 @@ defmodule ElixirScript.Passes.ConsolidateProtocols do x = Atom.to_string(Utils.quoted_to_name(impl_data.for)) x = String.to_atom(protocol_name <> ".DefImpl." <> x) name = Utils.name_to_js_name(x) - imports = ModuleSystems.import_module(name, Utils.make_local_file_path(impl_data.app, Utils.name_to_js_file_name(x), compiler_opts.root)) + imports = ModuleSystems.import_module(name, Utils.make_local_file_path(impl_data.app, Utils.name_to_js_file_name(x), compiler_opts.root, nil)) call = JS.call_expression( JS.member_expression( JS.identifier("impls"), diff --git a/lib/elixir_script/passes/find_changed_files.ex b/lib/elixir_script/passes/find_changed_files.ex index cacff587..9b841bb0 100644 --- a/lib/elixir_script/passes/find_changed_files.ex +++ b/lib/elixir_script/passes/find_changed_files.ex @@ -12,7 +12,7 @@ defmodule ElixirScript.Passes.FindChangedFiles do |> Enum.map(fn {file, _} -> file end) - State.deserialize(compiler_cache.state, compiler_data.loaded_modules) + State.deserialize(compiler_data.state, compiler_cache.state, compiler_data.loaded_modules) Map.put(compiler_data, :changed_files, changed_files) diff --git a/lib/elixir_script/passes/find_modules.ex b/lib/elixir_script/passes/find_modules.ex index fc3faee9..0079aadb 100644 --- a/lib/elixir_script/passes/find_modules.ex +++ b/lib/elixir_script/passes/find_modules.ex @@ -6,7 +6,7 @@ defmodule ElixirScript.Passes.FindModules do def execute(compiler_data, opts) do data = Enum.reduce(compiler_data.data, [], fn(data, list) -> quoted = update_quoted(data.ast) - { _, modules } = Macro.postwalk(quoted, [], &get_defmodules(&1, &2, opts)) + { _, modules } = Macro.postwalk(quoted, [], &get_defmodules(&1, &2, opts, compiler_data)) modules = Enum.map(modules, fn(x) -> { x.name, Map.merge(data, x) } end) list ++ modules @@ -15,41 +15,41 @@ defmodule ElixirScript.Passes.FindModules do Map.put(compiler_data, :data, data) end - defp get_defmodules({:defprotocol, _, [{:__aliases__, _, _} = the_alias, [do: {:__block__, _, _} = block]]} = ast, state, _) do + defp get_defmodules({:defprotocol, _, [{:__aliases__, _, _} = the_alias, [do: {:__block__, _, _} = block]]} = ast, state, _, _) do s = %{ name: Utils.quoted_to_name(the_alias), type: :protocol, ast: block } { ast, state ++ [s] } end - defp get_defmodules({:defprotocol, _, [{:__aliases__, _, _} = the_alias, [do: spec]]} = ast, state, _) do + defp get_defmodules({:defprotocol, _, [{:__aliases__, _, _} = the_alias, [do: spec]]} = ast, state, _, _) do s = %{ name: Utils.quoted_to_name(the_alias), type: :protocol, ast: {:__block__, [], [spec]} } { ast, state ++ [s] } end - defp get_defmodules({:defimpl, _, [ the_alias, [for: {:__aliases__, _, type_name} = type], [do: {:__block__, context, spec}] ]} = ast, state, _) do - {:__aliases__, _, original_name} = Utils.name_to_quoted(State.get_module_name(the_alias)) + defp get_defmodules({:defimpl, _, [ the_alias, [for: {:__aliases__, _, type_name} = type], [do: {:__block__, context, spec}] ]} = ast, state, _, compiler_data) do + {:__aliases__, _, original_name} = Utils.name_to_quoted(State.get_module_name(compiler_data.state, the_alias)) name = original_name ++ [DefImpl] ++ [Elixir] ++ type_name s = %{name: Utils.quoted_to_name({:__aliases__, [], name}), type: :impl, for: type, ast: {:__block__, context, spec}, implements: Utils.quoted_to_name({:__aliases__, [], original_name}) } { ast, state ++ [s] } end - defp get_defmodules({:defimpl, _, [ the_alias, [for: {:__aliases__, _, type_name} = type], [do: spec] ]} = ast, state, _) do - {:__aliases__, _, original_name} = Utils.name_to_quoted(State.get_module_name(the_alias)) + defp get_defmodules({:defimpl, _, [ the_alias, [for: {:__aliases__, _, type_name} = type], [do: spec] ]} = ast, state, _, compiler_data) do + {:__aliases__, _, original_name} = Utils.name_to_quoted(State.get_module_name(compiler_data.state, the_alias)) name = original_name ++ [DefImpl] ++ [Elixir] ++ type_name s = %{name: Utils.quoted_to_name({:__aliases__, [], name}), type: :impl, for: type, ast: {:__block__, [], [spec]}, implements: Utils.quoted_to_name({:__aliases__, [], original_name}) } { ast, state ++ [s] } end - defp get_defmodules({:defmodule, _, [{:__aliases__, _, [:ElixirScript, :Temp]}, [do: body]]} = ast, state, opts) do + defp get_defmodules({:defmodule, _, [{:__aliases__, _, [:ElixirScript, :Temp]}, [do: body]]} = ast, state, _, _) do s = %{name: ElixirScript.Temp, type: :module, ast: body } { ast, state ++ [s] } end - defp get_defmodules({:defmodule, _, [{:__aliases__, _, _}, [do: _]]} = ast, state, opts) do + defp get_defmodules({:defmodule, _, [{:__aliases__, _, _}, [do: _]]} = ast, state, opts, _) do { ast, do_module_processing(ast, state, opts) } end - defp get_defmodules(ast, state, _) do + defp get_defmodules(ast, state, _, _) do { ast, state } end diff --git a/lib/elixir_script/passes/handle_output.ex b/lib/elixir_script/passes/handle_output.ex index c9f640fb..5f949193 100644 --- a/lib/elixir_script/passes/handle_output.ex +++ b/lib/elixir_script/passes/handle_output.ex @@ -5,13 +5,13 @@ defmodule ElixirScript.Passes.HandleOutput do def execute(compiler_data, opts) do if Map.get(opts, :std_lib, false) do - State.set_module_data(compiler_data.data) - new_std_state = State.serialize() + State.set_module_data(compiler_data.state, compiler_data.data) + new_std_state = State.serialize(compiler_data.state) stdlib_state_path = Path.join([File.cwd!(), "lib", "elixir_script", "translator", "stdlib_state.bin"]) File.write!(stdlib_state_path, new_std_state) - State.stop() + State.stop(compiler_data.state) else - State.stop() + State.stop(compiler_data.state) out(compiler_data, opts) end end diff --git a/lib/elixir_script/passes/init.ex b/lib/elixir_script/passes/init.ex index 7f30662b..3ac9d5d9 100644 --- a/lib/elixir_script/passes/init.ex +++ b/lib/elixir_script/passes/init.ex @@ -3,8 +3,8 @@ defmodule ElixirScript.Passes.Init do alias ElixirScript.Translator.State def execute(compiler_data, opts) do - State.start_link(opts, []) - compiler_data + {:ok, pid} = State.start_link(opts, []) + Map.put(compiler_data, :state, pid) end end diff --git a/lib/elixir_script/passes/java_script_ast.ex b/lib/elixir_script/passes/java_script_ast.ex index 920dfb97..152085a0 100644 --- a/lib/elixir_script/passes/java_script_ast.ex +++ b/lib/elixir_script/passes/java_script_ast.ex @@ -5,16 +5,16 @@ defmodule ElixirScript.Passes.JavaScriptAST do def execute(compiler_data, opts) do - State.set_module_data(compiler_data.data) - State.set_loaded_modules(Map.get(compiler_data, :loaded_modules, [])) + State.set_module_data(compiler_data.state, compiler_data.data) + State.set_loaded_modules(compiler_data.state, Map.get(compiler_data, :loaded_modules, [])) parent = self - data = State.get_module_data() + data = State.get_module_data(compiler_data.state) |> Enum.map(fn({module_name, module_data}) -> spawn_link fn -> - module_data = compile(module_data, opts) + module_data = compile(module_data, opts, compiler_data.state) result = {module_name, module_data} send parent, {self, result } end @@ -30,13 +30,13 @@ defmodule ElixirScript.Passes.JavaScriptAST do %{ compiler_data | data: data } end - defp compile(%{load_only: true} = module_data, opts) do + defp compile(%{load_only: true} = module_data, opts, state) do module_data end - defp compile(module_data, opts) do + defp compile(module_data, opts, state) do - env = ElixirScript.Translator.LexicalScope.module_scope(module_data.name, Utils.name_to_js_file_name(module_data.name) <> ".js", opts.env) + env = ElixirScript.Translator.LexicalScope.module_scope(module_data.name, Utils.name_to_js_file_name(module_data.name) <> ".js", opts.env, state) module = case module_data.type do :module -> diff --git a/lib/elixir_script/passes/write_cache.ex b/lib/elixir_script/passes/write_cache.ex index d52a6d20..5b023070 100644 --- a/lib/elixir_script/passes/write_cache.ex +++ b/lib/elixir_script/passes/write_cache.ex @@ -6,8 +6,8 @@ defmodule ElixirScript.Passes.WriteCache do def execute(compiler_data, opts) do compiler_cache = Cache.get_compiler_cache(compiler_data.path, opts) - State.set_module_data(compiler_data.data) - new_state = State.serialize() + State.set_module_data(compiler_data.state, compiler_data.data) + new_state = State.serialize(compiler_data.state) new_file_stats = Enum.filter(compiler_data.data, fn({ _, data }) -> Map.has_key?(data, :path) end) |> Enum.map(fn({_, data}) -> { data.path, data.stat } end) |> Enum.uniq diff --git a/lib/elixir_script/translator.ex b/lib/elixir_script/translator.ex index bdee21ed..4f38e098 100644 --- a/lib/elixir_script/translator.ex +++ b/lib/elixir_script/translator.ex @@ -573,7 +573,7 @@ defmodule ElixirScript.Translator do expanded_ast = Macro.expand(ast, env.env) if expanded_ast == ast do name_arity = {name, length(params)} - module = ElixirScript.Translator.State.get_module(env.module) + module = ElixirScript.Translator.State.get_module(env.state, env.module) cond do name_arity in module.functions or name_arity in module.private_functions -> @@ -597,7 +597,7 @@ defmodule ElixirScript.Translator do do_translate({{:., [], [{:__aliases__, [], [:JS]}, name]}, [], params }, env) ElixirScript.Translator.LexicalScope.has_var?(env, name) -> { Identifier.make_identifier(name), env } - has_function?(env.module, {name, 0}) -> + has_function?(env.module, {name, 0}, env) -> Call.make_function_call(name, [], env) ElixirScript.Translator.LexicalScope.find_module(env, {name, 0}) -> imported_module_name = ElixirScript.Translator.LexicalScope.find_module(env, {name, 0}) @@ -629,10 +629,10 @@ defmodule ElixirScript.Translator do def create_module_name(module_name, env) do case module_name do {:__aliases__, _, _} -> - candiate_module_name = Utils.quoted_to_name(module_name) - |> ElixirScript.Translator.State.get_module_name + candiate_module_name = ElixirScript.Translator.State.get_module_name(env.state, + Utils.quoted_to_name(module_name)) - if ElixirScript.Translator.LexicalScope.get_module_name(env, candiate_module_name) in ElixirScript.Translator.State.list_module_names() do + if ElixirScript.Translator.LexicalScope.get_module_name(env, candiate_module_name) in ElixirScript.Translator.State.list_module_names(env.state) do ElixirScript.Translator.LexicalScope.get_module_name(env, candiate_module_name) else module_name @@ -642,8 +642,8 @@ defmodule ElixirScript.Translator do end end - def has_function?(module_name, name_arity) do - case ElixirScript.Translator.State.get_module(module_name) do + def has_function?(module_name, name_arity, env) do + case ElixirScript.Translator.State.get_module(env.state, module_name) do nil -> false module -> diff --git a/lib/elixir_script/translator/kernel/defmodule.ex b/lib/elixir_script/translator/kernel/defmodule.ex index edba9c78..1eb6d767 100644 --- a/lib/elixir_script/translator/kernel/defmodule.ex +++ b/lib/elixir_script/translator/kernel/defmodule.ex @@ -11,11 +11,11 @@ defmodule ElixirScript.Translator.Defmodule do def make_module(ElixirScript.Temp, body, env) do { body, _ } = translate_body(body, env) - %{ name: ElixirScript.Temp, body: body |> Group.inflate_groups, app_name: ElixirScript.Translator.State.get().compiler_opts.app } + %{ name: ElixirScript.Temp, body: body |> Group.inflate_groups, app_name: ElixirScript.Translator.State.get(env.state).compiler_opts.app } end - def make_module(module, nil, _) do - %{ name: module, body: [], app_name: ElixirScript.Translator.State.get().compiler_opts.app } + def make_module(module, nil, env) do + %{ name: module, body: [], app_name: ElixirScript.Translator.State.get(env.state).compiler_opts.app } end def make_module(module, body, env) do @@ -25,14 +25,14 @@ defmodule ElixirScript.Translator.Defmodule do { exported_functions, private_functions } = process_functions(functions, env) - module_refs = ElixirScript.Translator.State.get_module_references(module) -- [env.module] + module_refs = ElixirScript.Translator.State.get_module_references(env.state, module) -- [env.module] {imports, body} = extract_imports_from_body(body) {structs, body} = extract_structs_from_body(body, env) - app_name = State.get_module(module).app + app_name = State.get_module(env.state, module).app - imports = imports ++ make_std_lib_import() ++ make_imports(app_name, module_refs) + imports = imports ++ make_std_lib_import(env) ++ make_imports(app_name, module_refs, env) #Collect all the functions so that we can process their arity body = Enum.map(body, fn(x) -> @@ -176,11 +176,11 @@ defmodule ElixirScript.Translator.Defmodule do end end - def make_std_lib_import() do - compiler_opts = ElixirScript.Translator.State.get().compiler_opts + def make_std_lib_import(env) do + compiler_opts = ElixirScript.Translator.State.get(env.state).compiler_opts case compiler_opts.import_standard_libs do true -> - [ModuleSystems.import_module(:Elixir, Utils.make_local_file_path(:elixir, compiler_opts.core_path))] + [ModuleSystems.import_module(:Elixir, Utils.make_local_file_path(:elixir, compiler_opts.core_path, env))] false -> [] end @@ -225,11 +225,11 @@ defmodule ElixirScript.Translator.Defmodule do JS.variable_declaration([declarator], :const) end - def make_imports(current_app_name, enum) do + def make_imports(current_app_name, enum, env) do Enum.map(enum, fn(x) -> module_name = Utils.name_to_js_name(x) - app_name = State.get_module(x).app - path = Utils.make_local_file_path(app_name, Utils.name_to_js_file_name(x)) + app_name = State.get_module(env.state, x).app + path = Utils.make_local_file_path(app_name, Utils.name_to_js_file_name(x), env) ModuleSystems.import_module(module_name, path) end) end diff --git a/lib/elixir_script/translator/kernel/defprotocol.ex b/lib/elixir_script/translator/kernel/defprotocol.ex index 8f56f64e..d8644a0e 100644 --- a/lib/elixir_script/translator/kernel/defprotocol.ex +++ b/lib/elixir_script/translator/kernel/defprotocol.ex @@ -16,15 +16,15 @@ defmodule ElixirScript.Translator.Defprotocol do def make(name, functions, env) do { body, _ } = Defmodule.translate_body( {:__block__, [], [] }, env) - module_refs = ElixirScript.Translator.State.get_module_references(name) + module_refs = ElixirScript.Translator.State.get_module_references(env.state, name) {imports, body} = Defmodule.extract_imports_from_body(body) - app_name = State.get_module(name).app + app_name = State.get_module(env.state, name).app - imports = imports ++ Defmodule.make_std_lib_import() ++ - Defmodule.make_imports(app_name, module_refs) ++ - [ElixirScript.ModuleSystems.import_module("Implementations", Utils.make_local_file_path(app_name, Utils.name_to_js_file_name(name) <> ".Defimpl"))] + imports = imports ++ Defmodule.make_std_lib_import(env) ++ + Defmodule.make_imports(app_name, module_refs, env) ++ + [ElixirScript.ModuleSystems.import_module("Implementations", Utils.make_local_file_path(app_name, Utils.name_to_js_file_name(name) <> ".Defimpl", env)) ] object = process_spec_functions(functions) |> Enum.map(fn({key, value}) -> @@ -98,8 +98,8 @@ defmodule ElixirScript.Translator.Defprotocol do Makes the protocol implementation module for the given implementation name. This is used to consolidate all of the protocol implementations. """ - def make_defimpl(name, implementations \\ [], compiler_opts) do - imports = [ModuleSystems.import_module(:Elixir, Utils.make_local_file_path(:elixir, compiler_opts.core_path, compiler_opts.root))] + def make_defimpl(name, implementations \\ [], compiler_opts, env) do + imports = [ModuleSystems.import_module(:Elixir, Utils.make_local_file_path(:elixir, compiler_opts.core_path, compiler_opts.root, env))] declarator = JS.variable_declarator( JS.identifier("impls"), @@ -112,7 +112,7 @@ defmodule ElixirScript.Translator.Defprotocol do protocol_name = Atom.to_string(name) - app_name = State.get_module(name).app + app_name = State.get_module(env.state, name).app body = Enum.flat_map(implementations, fn({impl_app_name, x}) -> x = if is_atom(x), do: Atom.to_string(x), else: x diff --git a/lib/elixir_script/translator/kernel/special_forms/call.ex b/lib/elixir_script/translator/kernel/special_forms/call.ex index 5cff6ec8..6d1c34f0 100644 --- a/lib/elixir_script/translator/kernel/special_forms/call.ex +++ b/lib/elixir_script/translator/kernel/special_forms/call.ex @@ -130,8 +130,8 @@ defmodule ElixirScript.Translator.Call do module_name in env.requires -> Utils.name_to_js_name(module_name) - module_name in ElixirScript.Translator.State.list_module_names -> - ElixirScript.Translator.State.add_module_reference(env.module, module_name) + module_name in ElixirScript.Translator.State.list_module_names(env.state) -> + ElixirScript.Translator.State.add_module_reference(env.state, env.module, module_name) Utils.name_to_js_name(module_name) true -> diff --git a/lib/elixir_script/translator/kernel/special_forms/fn.ex b/lib/elixir_script/translator/kernel/special_forms/fn.ex index f82fa98e..d3f6aeef 100644 --- a/lib/elixir_script/translator/kernel/special_forms/fn.ex +++ b/lib/elixir_script/translator/kernel/special_forms/fn.ex @@ -14,16 +14,19 @@ defmodule ElixirScript.Translator.Function do JS.identifier("Patterns") ) - def make_anonymous_function(functions, env, name \\ nil) do + @spec make_anonymous_function(list(), ElixirScript.Translator.LexicalScope.t, binary | atom) :: tuple() + def make_anonymous_function(functions, env, name \\ nil) + + def make_anonymous_function(functions, env, name) do clauses = functions |> Enum.map(fn - {:->, _, [ [{:when, _, [params | guards]}], body ]} -> + ({:->, _, [ [{:when, _, [params | guards]}], body ]}) -> process_function_body(params, body, env, name, guards) ({:->, _, [params, body]}) -> process_function_body(params, body, env, name) - ({_, _, [{:when, _, [{_, _, params} | guards] }, body]}) -> + ({_, _, [{:when, _, [{_, _, params} | guards]}, body]}) -> body = convert_to_try(body) process_function_body(params, body, env, name, guards) @@ -35,18 +38,18 @@ defmodule ElixirScript.Translator.Function do process_function_body(params, [], env, name) end) - { make_defmatch(clauses, env.context == :generator), env } + {make_defmatch(clauses, env.context == :generator), env} end - def convert_to_try([do: body]) do + defp convert_to_try([do: body]) do body end - def convert_to_try(function_kw_list) do - { :__block__, [], [{ :try, [], [function_kw_list] }] } + defp convert_to_try(function_kw_list) do + {:__block__, [], [{:try, [], [function_kw_list]}]} end - def make_defmatch(clauses, true) do + defp make_defmatch(clauses, true) do JS.call_expression( JS.member_expression( @patterns, @@ -56,7 +59,7 @@ defmodule ElixirScript.Translator.Function do ) end - def make_defmatch(clauses, _) do + defp make_defmatch(clauses, _) do JS.call_expression( JS.member_expression( @patterns, @@ -69,12 +72,14 @@ defmodule ElixirScript.Translator.Function do defp process_function_body(params, body, env, name, guards \\ nil) do env = ElixirScript.Translator.LexicalScope.function_scope(env, {name, get_arity(params)}) - { patterns, params, env } = process_params(params, env) - { body, _ } = make_function_body(body, env) + {patterns, params, env} = process_params(params, env) + {body, _} = make_function_body(body, env) if guards do - { guard_body, _ } = hd(List.wrap(guards)) - |> prepare_function_body(%{ env | context: :guard}) + {guard_body, _} = guards + |> List.wrap + |> hd + |> prepare_function_body(%{env | context: :guard}) guard_body = JS.block_statement(guard_body) make_function_clause(patterns, params, body, guard_body, env.context == :generator) @@ -83,15 +88,16 @@ defmodule ElixirScript.Translator.Function do end end - def wrap_params(params) when is_atom(params), do: [] - def wrap_params(params), do: List.wrap(params) + defp wrap_params(params) when is_atom(params), do: [] + defp wrap_params(params), do: List.wrap(params) + @spec make_function_body(list | tuple, ElixirScript.Translator.LexicalScope.t) :: tuple() def make_function_body(body, env) do - { body, _ } = body + {body, _} = body |> prepare_function_body(env) - { JS.block_statement(body), env } + {JS.block_statement(body), env} end defp get_arity(params) when is_atom(params), do: 0 @@ -107,11 +113,11 @@ defmodule ElixirScript.Translator.Function do defp process_params(params, env) do params = wrap_params(params) - { patterns, params, env } = PatternMatching.process_match(params, env) - { patterns, make_params(params), env } + {patterns, params, env} = PatternMatching.process_match(params, env) + {patterns, make_params(params), env} end - def make_function_clause(patterns, params, body, guard_body, is_generator?) do + defp make_function_clause(patterns, params, body, guard_body, is_generator?) do arguments = case guard_body do nil -> @@ -138,9 +144,9 @@ defmodule ElixirScript.Translator.Function do end def prepare_function_body(body, env) do - { list, env } = case body do + {list, env} = case body do nil -> - { [], env } + {[], env} list when is_list(list) -> t = Translator.translate!(list, env) {[t], env} @@ -158,22 +164,22 @@ defmodule ElixirScript.Translator.Function do list = Group.inflate_groups(list) |> return_last_expression - { list, env } + {list, env} end - def return_last_expression(nil) do + defp return_last_expression(nil) do nil end - def return_last_expression([]) do + defp return_last_expression([]) do [JS.return_statement(JS.literal(nil))] end - def return_last_expression(%ESTree.BlockStatement{} = block) do - %ESTree.BlockStatement{ block | body: return_last_expression(block.body) } + defp return_last_expression(%ESTree.BlockStatement{} = block) do + %ESTree.BlockStatement{block | body: return_last_expression(block.body)} end - def return_last_expression(list) when is_list(list) do + defp return_last_expression(list) when is_list(list) do last_item = List.last(list) last_item = case last_item do @@ -199,7 +205,7 @@ defmodule ElixirScript.Translator.Function do [last_item, return_statement] %ESTree.BlockStatement{} -> - last_item = %ESTree.BlockStatement{ last_item | body: return_last_expression(last_item.body) } + last_item = %ESTree.BlockStatement{last_item | body: return_last_expression(last_item.body)} _ -> if String.contains?(last_item.type, "Expression") do JS.return_statement(last_item) diff --git a/lib/elixir_script/translator/kernel/special_forms/struct.ex b/lib/elixir_script/translator/kernel/special_forms/struct.ex index 670ae90b..d8b0228d 100644 --- a/lib/elixir_script/translator/kernel/special_forms/struct.ex +++ b/lib/elixir_script/translator/kernel/special_forms/struct.ex @@ -7,13 +7,12 @@ defmodule ElixirScript.Translator.Struct do alias ElixirScript.Translator.Identifier def get_struct_class(module_name, env) do - candiate_module_name = Utils.quoted_to_name(module_name) - |> ElixirScript.Translator.State.get_module_name + candiate_module_name = ElixirScript.Translator.State.get_module_name(env.state, Utils.quoted_to_name(module_name)) - if ElixirScript.Translator.LexicalScope.get_module_name(env, candiate_module_name) in ElixirScript.Translator.State.list_module_names() do + if ElixirScript.Translator.LexicalScope.get_module_name(env, candiate_module_name) in ElixirScript.Translator.State.list_module_names(env.state) do name = ElixirScript.Translator.LexicalScope.get_module_name(env, candiate_module_name) ident = JS.identifier(Utils.name_to_js_name(name)) - ElixirScript.Translator.State.add_module_reference(env.module, name) + ElixirScript.Translator.State.add_module_reference(env.state, env.module, name) JS.member_expression(ident, ident) else diff --git a/lib/elixir_script/translator/lexical_scope.ex b/lib/elixir_script/translator/lexical_scope.ex index 423e2eeb..de2f9492 100644 --- a/lib/elixir_script/translator/lexical_scope.ex +++ b/lib/elixir_script/translator/lexical_scope.ex @@ -17,7 +17,8 @@ defmodule ElixirScript.Translator.LexicalScope do export_vars: [{atom, atom | non_neg_integer}] | nil, lexical_tracker: nil, caller: t | nil, - env: nil + env: nil, + state: pid } defstruct [ @@ -36,7 +37,8 @@ defmodule ElixirScript.Translator.LexicalScope do export_vars: nil, lexical_tracker: nil, caller: nil, - env: nil + env: nil, + state: nil ] def env(scope) do @@ -77,26 +79,28 @@ defmodule ElixirScript.Translator.LexicalScope do } end - def module_scope(ElixirScript.Temp, filename, env) do + def module_scope(ElixirScript.Temp, filename, env, state) do env = %ElixirScript.Translator.LexicalScope { module: ElixirScript.Temp, file: filename, requires: [], functions: [], macros: [], - env: env + env: env, + state: state } add_import(env, ElixirScript.Kernel) end - def module_scope(module_name, filename, env) do - module = ElixirScript.Translator.State.get_module(module_name) + def module_scope(module_name, filename, env, state) do + module = ElixirScript.Translator.State.get_module(state, module_name) env = %ElixirScript.Translator.LexicalScope { module: module_name, file: filename, requires: [], functions: [{ module.name, module.functions}], macros: [{module.name, module.macros}], - env: env + env: env, + state: state } env = add_import(env, ElixirScript.Kernel) @@ -104,7 +108,7 @@ defmodule ElixirScript.Translator.LexicalScope do cond do module_name == JS -> env - ElixirScript.Translator.State.is_module_loaded?(module_name) and length(module.macros) > 0 -> + ElixirScript.Translator.State.is_module_loaded?(env.state, module_name) and length(module.macros) > 0 -> add_import(env, module_name, [only: :macros]) true -> env @@ -170,7 +174,7 @@ defmodule ElixirScript.Translator.LexicalScope do end defp get_module(env, module_name) do - module = get_module_name(env, module_name) |> ElixirScript.Translator.State.get_module + module = ElixirScript.Translator.State.get_module(env.state, get_module_name(env, module_name)) unless module do module_name = case module_name do @@ -188,7 +192,7 @@ defmodule ElixirScript.Translator.LexicalScope do end if Map.get(module, :load_only, false) == false do - ElixirScript.Translator.State.add_module_reference(env.module, module.name) + ElixirScript.Translator.State.add_module_reference(env.state, env.module, module.name) end module @@ -217,7 +221,7 @@ defmodule ElixirScript.Translator.LexicalScope do def add_import(env, module_name) do check_for_module_existence(env, module_name) - env = if ElixirScript.Translator.State.is_module_loaded?(module_name) do + env = if ElixirScript.Translator.State.is_module_loaded?(env.state, module_name) do add_import_macro(env, module_name, []) else env @@ -242,7 +246,7 @@ defmodule ElixirScript.Translator.LexicalScope do end def add_import(env, module_name, [only: :macros]) do - if !ElixirScript.Translator.State.is_module_loaded?(module_name) do + if !ElixirScript.Translator.State.is_module_loaded?(env.state, module_name) do raise "Module #{inspect module_name} not found" end @@ -252,7 +256,7 @@ defmodule ElixirScript.Translator.LexicalScope do def add_import(env, module_name, [only: only]) do check_for_module_existence(env, module_name) - env = if ElixirScript.Translator.State.is_module_loaded?(module_name) do + env = if ElixirScript.Translator.State.is_module_loaded?(env.state, module_name) do list = module_name.__info__(:macros) list = Enum.filter(list, fn(mac) -> mac in only end) add_import_macro(env, module_name, [only: list]) @@ -277,7 +281,7 @@ defmodule ElixirScript.Translator.LexicalScope do def add_import(env, module_name, [except: except]) do check_for_module_existence(env, module_name) - env = if ElixirScript.Translator.State.is_module_loaded?(module_name) do + env = if ElixirScript.Translator.State.is_module_loaded?(env.state, module_name) do list = module_name.__info__(:macros) list = Enum.filter(list, fn(mac) -> mac in except end) add_import_macro(env, module_name, [except: list]) @@ -301,7 +305,7 @@ defmodule ElixirScript.Translator.LexicalScope do def add_require(env, module_name) do check_for_module_existence(env, module_name) - env = if ElixirScript.Translator.State.is_module_loaded?(module_name) do + env = if ElixirScript.Translator.State.is_module_loaded?(env.state, module_name) do add_require_macro(env, module_name, []) else env @@ -318,7 +322,7 @@ defmodule ElixirScript.Translator.LexicalScope do def add_require(env, module_name, alias_name) do check_for_module_existence(env, module_name) - env = if ElixirScript.Translator.State.is_module_loaded?(module_name) do + env = if ElixirScript.Translator.State.is_module_loaded?(env.state, module_name) do add_require_macro(env, module_name, [as: alias_name]) else env @@ -334,7 +338,7 @@ defmodule ElixirScript.Translator.LexicalScope do end def get_module_name(env, module_name) do - module_name = ElixirScript.Translator.State.get_module_name(module_name) + module_name = ElixirScript.Translator.State.get_module_name(env.state, module_name) if Keyword.has_key?(env.aliases, module_name) do Keyword.fetch!(env.aliases, module_name) @@ -345,7 +349,7 @@ defmodule ElixirScript.Translator.LexicalScope do end defp check_for_module_existence(env, module_name) do - if ElixirScript.Translator.State.is_module_loaded?(module_name) == false and has_module?(env, module_name) == false do + if ElixirScript.Translator.State.is_module_loaded?(env.state, module_name) == false and has_module?(env, module_name) == false do raise "Module #{inspect module_name} not found" end end diff --git a/lib/elixir_script/translator/state.ex b/lib/elixir_script/translator/state.ex index 2070a600..aa486b4c 100644 --- a/lib/elixir_script/translator/state.ex +++ b/lib/elixir_script/translator/state.ex @@ -12,11 +12,11 @@ defmodule ElixirScript.Translator.State do def start_link(compiler_opts, loaded_modules) do Agent.start_link(fn -> %{ compiler_opts: compiler_opts, modules: Keyword.new, std_lib_map: build_standard_lib_map(), loaded_modules: [JS | loaded_modules] } - end, name: __MODULE__) + end) end - def serialize() do - Agent.get(__MODULE__, fn(state) -> + def serialize(pid) do + Agent.get(pid, fn(state) -> modules = state.modules modules = Enum.map(modules, fn {m, d} -> d = Map.delete(d, :javascript_ast) @@ -34,8 +34,8 @@ defmodule ElixirScript.Translator.State do end) end - def deserialize(frozen_state, loaded_modules \\ []) do - Agent.update(__MODULE__, fn state -> + def deserialize(pid, frozen_state, loaded_modules \\ []) do + Agent.update(pid, fn state -> frozen_state = :erlang.binary_to_term(frozen_state) modules = Keyword.delete(frozen_state.modules, ElixirScript.Temp) %{ state | modules: modules, std_lib_map: frozen_state.std_lib_map, loaded_modules: [JS | loaded_modules] } @@ -67,35 +67,35 @@ defmodule ElixirScript.Translator.State do |> Map.put(Regex, ElixirScript.Regex) end - def set_module_data(module_data) do - Agent.update(__MODULE__, fn state -> + def set_module_data(pid, module_data) do + Agent.update(pid, fn state -> data = Enum.filter(state.modules, fn {module_name, data} -> data.app == :elixir end) %{ state | modules: Keyword.merge(data, module_data) } end) end - def get_module_data() do - Agent.get(__MODULE__, fn state -> + def get_module_data(pid) do + Agent.get(pid, fn state -> state.modules end) end - def set_loaded_modules(modules) do - Agent.update(__MODULE__, fn state -> + def set_loaded_modules(pid, modules) do + Agent.update(pid, fn state -> %{ state | loaded_modules: [ JS | modules ] } end) end - def get do - Agent.get(__MODULE__, &(&1)) + def get(pid) do + Agent.get(pid, &(&1)) end - def get_module_name({:__aliases__, _, _} = name) do - get_module_name(Utils.quoted_to_name(name)) + def get_module_name(pid, {:__aliases__, _, _} = name) do + get_module_name(pid, Utils.quoted_to_name(name)) end - def get_module_name(module_name) do - Agent.get(__MODULE__, fn(state) -> + def get_module_name(pid, module_name) do + Agent.get(pid, fn(state) -> do_get_module_name(module_name, state) end) end @@ -110,37 +110,37 @@ defmodule ElixirScript.Translator.State do end end - def is_module_loaded?(module) when is_atom(module) do - Agent.get(__MODULE__, fn(state) -> + def is_module_loaded?(pid, module) when is_atom(module) do + Agent.get(pid, fn(state) -> (module in state.loaded_modules) end) end - def is_module_loaded?({:__aliases__, _, _} = module) do - Utils.quoted_to_name(module) - |> is_module_loaded? + def is_module_loaded?(pid, {:__aliases__, _, _} = module) do + + is_module_loaded?(pid, Utils.quoted_to_name(module)) end - def get_module(module) when is_atom(module) do - do_get_module(module) + def get_module(pid, module) when is_atom(module) do + do_get_module(pid, module) end - def get_module({:__aliases__, _, _} = name) do - do_get_module(Utils.quoted_to_name(name)) + def get_module(pid, {:__aliases__, _, _} = name) do + do_get_module(pid, Utils.quoted_to_name(name)) end - def get_module(module_name_list) when is_list(module_name_list) do - do_get_module(Utils.quoted_to_name({:__aliases__, [], module_name_list})) + def get_module(pid, module_name_list) when is_list(module_name_list) do + do_get_module(pid, Utils.quoted_to_name({:__aliases__, [], module_name_list})) end - defp do_get_module(name) do - Agent.get(__MODULE__, fn(state) -> + defp do_get_module(pid, name) do + Agent.get(pid, fn(state) -> Keyword.get(state.modules, do_get_module_name(name, state)) end) end - def add_module_reference(module_name, module_ref) do - Agent.update(__MODULE__, fn(state) -> + def add_module_reference(pid, module_name, module_ref) do + Agent.update(pid, fn(state) -> case Keyword.get(state.modules, do_get_module_name(module_name, state)) do nil -> state @@ -152,8 +152,8 @@ defmodule ElixirScript.Translator.State do end) end - def get_module_references(module_name) do - case get_module(module_name) do + def get_module_references(pid, module_name) do + case get_module(pid, module_name) do nil -> [] module -> @@ -161,19 +161,19 @@ defmodule ElixirScript.Translator.State do end end - def list_modules() do - Agent.get(__MODULE__, fn(state) -> + def list_modules(pid) do + Agent.get(pid, fn(state) -> Keyword.values(state.modules) end) end - def list_module_names() do - Agent.get(__MODULE__, fn(state) -> + def list_module_names(pid) do + Agent.get(pid, fn(state) -> Keyword.keys(state.modules) end) end - def stop do - Agent.stop(__MODULE__) + def stop(pid) do + Agent.stop(pid) end end diff --git a/lib/elixir_script/translator/utils.ex b/lib/elixir_script/translator/utils.ex index 0c573c0e..7d40cfff 100644 --- a/lib/elixir_script/translator/utils.ex +++ b/lib/elixir_script/translator/utils.ex @@ -30,8 +30,8 @@ defmodule ElixirScript.Translator.Utils do Enum.join([:Elixir] ++ name, ".") end - def make_local_file_path(module_app_name, file_name) do - root = ElixirScript.Translator.State.get().compiler_opts.root + def make_local_file_path(module_app_name, file_name, env) do + root = ElixirScript.Translator.State.get(env.state).compiler_opts.root app_name = if is_binary(module_app_name), do: module_app_name, else: to_string(module_app_name) case root do @@ -42,8 +42,8 @@ defmodule ElixirScript.Translator.Utils do end end - def make_local_file_path(file_name) do - root = ElixirScript.Translator.State.get().compiler_opts.root + def make_local_file_path(file_name, env) do + root = ElixirScript.Translator.State.get(env.state).compiler_opts.root case root do nil -> @@ -53,7 +53,7 @@ defmodule ElixirScript.Translator.Utils do end end - def make_local_file_path(module_app_name, file_name, root) do + def make_local_file_path(module_app_name, file_name, root, _) do app_name = to_string(module_app_name) case root do diff --git a/test/translator/pattern_matching_test.exs b/test/translator/pattern_matching_test.exs index c01d8840..0b2cd8f9 100644 --- a/test/translator/pattern_matching_test.exs +++ b/test/translator/pattern_matching_test.exs @@ -9,32 +9,32 @@ defmodule ElixirScript.Translator.PatternMatching.Test do @std_lib_state File.read!(File.cwd!() <> "/lib/elixir_script/translator/stdlib_state.bin") setup do - ElixirScript.Translator.State.start_link(%{env: __ENV__}, []) - ElixirScript.Translator.State.deserialize(@std_lib_state) + {:ok, pid} = ElixirScript.Translator.State.start_link(%{env: __ENV__}, []) + ElixirScript.Translator.State.deserialize(pid, @std_lib_state) + scope = ElixirScript.Translator.LexicalScope.module_scope(ElixirScript.Temp, "temp.ex", __ENV__, pid) - # Returns extra metadata, it must be a dict - {:ok, []} + {:ok, [scope: scope]} end - test "match wildcard" do + test "match wildcard", %{scope: scope} do params = [{:_, [], Test}] - result = PatternMatching.build_match(params, ElixirScript.Translator.LexicalScope.module_scope(ElixirScript.Temp, "temp.ex", __ENV__) ) + result = PatternMatching.build_match(params, scope) expected_result = { [PatternMatching.wildcard], [JS.identifier(:undefined)] } assert result == expected_result end - test "match one identifier param" do + test "match one identifier param", %{scope: scope} do params = [{:a, [], Test}] - result = PatternMatching.build_match(params, ElixirScript.Translator.LexicalScope.module_scope(ElixirScript.Temp, "temp.ex", __ENV__) ) + result = PatternMatching.build_match(params, scope ) expected_result = {[PatternMatching.parameter], [JS.identifier("a")]} assert result == expected_result end - test "match multiple identifier params" do + test "match multiple identifier params", %{scope: scope} do params = [{:a, [], Test}, {:b, [], Test}, {:c, [], Test}] - result = PatternMatching.build_match(params, ElixirScript.Translator.LexicalScope.module_scope(ElixirScript.Temp, "temp.ex", __ENV__) ) + result = PatternMatching.build_match(params, scope ) expected_result = { List.duplicate(PatternMatching.parameter, 3), [JS.identifier("a"), JS.identifier("b"), JS.identifier("c")] @@ -43,9 +43,9 @@ defmodule ElixirScript.Translator.PatternMatching.Test do assert result == expected_result end - test "match head and tail param" do + test "match head and tail param", %{scope: scope} do params = [[{:|, [], [{:head, [], Elixir}, {:tail, [], Elixir}]}]] - result = PatternMatching.build_match(params, ElixirScript.Translator.LexicalScope.module_scope(ElixirScript.Temp, "temp.ex", __ENV__) ) + result = PatternMatching.build_match(params, scope ) expected_result = { [PatternMatching.head_tail(PatternMatching.parameter, PatternMatching.parameter)], [JS.identifier("head"), JS.identifier("tail")] @@ -54,9 +54,9 @@ defmodule ElixirScript.Translator.PatternMatching.Test do assert result == expected_result end - test "match prefix param" do + test "match prefix param", %{scope: scope} do params = [{:<>, [context: Elixir, import: Elixir.Kernel], ["Bearer ", {:token, [], Elixir}]}] - result = PatternMatching.build_match(params, ElixirScript.Translator.LexicalScope.module_scope(ElixirScript.Temp, "temp.ex", __ENV__) ) + result = PatternMatching.build_match(params, scope ) expected_result = { [PatternMatching.starts_with("Bearer ")], [JS.identifier("token")] @@ -65,9 +65,9 @@ defmodule ElixirScript.Translator.PatternMatching.Test do assert result == expected_result end - test "match list" do + test "match list", %{scope: scope} do params = [[{:a, [], Elixir}, {:b, [], Elixir}, {:c, [], Elixir}]] - result = PatternMatching.build_match(params, ElixirScript.Translator.LexicalScope.module_scope(ElixirScript.Temp, "temp.ex", __ENV__) ) + result = PatternMatching.build_match(params, scope ) expected_result = { [Primitive.make_list_no_translate(List.duplicate(PatternMatching.parameter, 3))], [JS.identifier("a"), JS.identifier("b"), JS.identifier("c")] @@ -76,9 +76,9 @@ defmodule ElixirScript.Translator.PatternMatching.Test do assert result == expected_result end - test "match list with a literal" do + test "match list with a literal", %{scope: scope} do params = [[1, {:b, [], Elixir}, {:c, [], Elixir}]] - result = PatternMatching.build_match(params, ElixirScript.Translator.LexicalScope.module_scope(ElixirScript.Temp, "temp.ex", __ENV__) ) + result = PatternMatching.build_match(params, scope ) expected_result = { [Primitive.make_list_no_translate([JS.literal(1), PatternMatching.parameter, PatternMatching.parameter])], [JS.identifier("b"), JS.identifier("c")] @@ -87,9 +87,9 @@ defmodule ElixirScript.Translator.PatternMatching.Test do assert result == expected_result end - test "match number" do + test "match number", %{scope: scope} do params = [1] - result = PatternMatching.build_match(params, ElixirScript.Translator.LexicalScope.module_scope(ElixirScript.Temp, "temp.ex", __ENV__) ) + result = PatternMatching.build_match(params, scope ) expected_result = { [JS.literal(1)], [] @@ -98,9 +98,9 @@ defmodule ElixirScript.Translator.PatternMatching.Test do assert result == expected_result end - test "match struct pattern" do + test "match struct pattern", %{scope: scope} do params = [{:%, [], [{:__aliases__, [alias: false], [:Hello]}, {:%{}, [], []}]}] - result = PatternMatching.build_match(params, ElixirScript.Translator.LexicalScope.module_scope(ElixirScript.Temp, "temp.ex", __ENV__) ) + result = PatternMatching.build_match(params, scope ) expected_result = { [PatternMatching.type(JS.identifier("Hello"), JS.object_expression([]))], [] @@ -109,12 +109,12 @@ defmodule ElixirScript.Translator.PatternMatching.Test do assert result == expected_result end - test "match struct pattern with property" do + test "match struct pattern with property", %{scope: scope} do params = [{:%, [], [{:__aliases__, [alias: false], [:Hello]}, {:%{}, [], [key: 1]}]}] - result = PatternMatching.build_match(params, ElixirScript.Translator.LexicalScope.module_scope(ElixirScript.Temp, "temp.ex", __ENV__) ) + result = PatternMatching.build_match(params, scope ) expected_result = { [PatternMatching.type(JS.identifier("Hello"), JS.object_expression([ - Map.make_property(Translator.translate!(:key, ElixirScript.Translator.LexicalScope.module_scope(ElixirScript.Temp, "temp.ex", __ENV__) ), Translator.translate!(1, ElixirScript.Translator.LexicalScope.module_scope(ElixirScript.Temp, "temp.ex", __ENV__) )) + Map.make_property(Translator.translate!(:key, scope ), Translator.translate!(1, scope )) ])) ], [] @@ -123,12 +123,12 @@ defmodule ElixirScript.Translator.PatternMatching.Test do assert result == expected_result end - test "match struct pattern with property param" do + test "match struct pattern with property param", %{scope: scope} do params = [{:%, [], [{:__aliases__, [alias: false], [:Hello]}, {:%{}, [], [key: {:key, [], Elixir }]}]}] - result = PatternMatching.build_match(params, ElixirScript.Translator.LexicalScope.module_scope(ElixirScript.Temp, "temp.ex", __ENV__) ) + result = PatternMatching.build_match(params, scope ) expected_result = { [PatternMatching.type(JS.identifier("Hello"), JS.object_expression([ - Map.make_property(Translator.translate!(:key, ElixirScript.Translator.LexicalScope.module_scope(ElixirScript.Temp, "temp.ex", __ENV__) ), PatternMatching.parameter) + Map.make_property(Translator.translate!(:key, scope ), PatternMatching.parameter) ])) ], [JS.identifier("key")] @@ -137,9 +137,9 @@ defmodule ElixirScript.Translator.PatternMatching.Test do assert result == expected_result end - test "capture parameter when assigning it" do + test "capture parameter when assigning it", %{scope: scope} do params = [{:=, [], [1, {:a, [], Elixir}]}] - result = PatternMatching.build_match(params, ElixirScript.Translator.LexicalScope.module_scope(ElixirScript.Temp, "temp.ex", __ENV__) ) + result = PatternMatching.build_match(params, scope ) expected_result = { [PatternMatching.capture(JS.literal(1))], [JS.identifier("a")] @@ -149,7 +149,7 @@ defmodule ElixirScript.Translator.PatternMatching.Test do params = [{:=, [], [{:a, [], Elixir}, 1]}] - result = PatternMatching.build_match(params, ElixirScript.Translator.LexicalScope.module_scope(ElixirScript.Temp, "temp.ex", __ENV__) ) + result = PatternMatching.build_match(params, scope ) expected_result = { [PatternMatching.capture(JS.literal(1))], [JS.identifier("a")] @@ -159,7 +159,7 @@ defmodule ElixirScript.Translator.PatternMatching.Test do params = [{:=, [], [{:%, [], [{:__aliases__, [alias: false], [:AStruct]}, {:%{}, [], []}]}, {:a, [], ElixirScript.Translator.Function.Test}]}] - result = PatternMatching.build_match(params, ElixirScript.Translator.LexicalScope.module_scope(ElixirScript.Temp, "temp.ex", __ENV__) ) + result = PatternMatching.build_match(params, scope ) expected_result = { [PatternMatching.capture(PatternMatching.type(JS.identifier("AStruct"), JS.object_expression([])))], [JS.identifier("a")] @@ -168,9 +168,9 @@ defmodule ElixirScript.Translator.PatternMatching.Test do assert result == expected_result end - test "match and assign list" do + test "match and assign list", %{scope: scope} do params = [{:=, [], [[{:a, [], Elixir}, {:b, [], Elixir}, {:c, [], Elixir}], {:d, [], Elixir}]}] - result = PatternMatching.build_match(params, ElixirScript.Translator.LexicalScope.module_scope(ElixirScript.Temp, "temp.ex", __ENV__) ) + result = PatternMatching.build_match(params, scope ) expected_result = { [PatternMatching.capture(Primitive.make_list_no_translate([PatternMatching.parameter, PatternMatching.parameter, PatternMatching.parameter]))], [JS.identifier("a"), JS.identifier("b"), JS.identifier("c"), JS.identifier("d")] @@ -179,9 +179,9 @@ defmodule ElixirScript.Translator.PatternMatching.Test do assert result == expected_result end - test "match on tuple" do + test "match on tuple", %{scope: scope} do params = [{:{}, [], [1, {:b, [], Elixir}, 3]}] - result = PatternMatching.build_match(params, ElixirScript.Translator.LexicalScope.module_scope(ElixirScript.Temp, "temp.ex", __ENV__) ) + result = PatternMatching.build_match(params, scope ) expected_result = { [PatternMatching.type(Primitive.tuple_class, JS.object_expression([JS.property( JS.identifier("values"), @@ -193,7 +193,7 @@ defmodule ElixirScript.Translator.PatternMatching.Test do assert result == expected_result params = [{1, {:b, [], Elixir}}] - result = PatternMatching.build_match(params, ElixirScript.Translator.LexicalScope.module_scope(ElixirScript.Temp, "temp.ex", __ENV__) ) + result = PatternMatching.build_match(params, scope ) expected_result = { [PatternMatching.type(Primitive.tuple_class, JS.object_expression([JS.property( JS.identifier("values"), @@ -205,13 +205,13 @@ defmodule ElixirScript.Translator.PatternMatching.Test do assert result == expected_result end - test "match on map" do + test "match on map", %{scope: scope} do params = [{:%{}, [], [which: 13]}] - result = PatternMatching.build_match(params, ElixirScript.Translator.LexicalScope.module_scope(ElixirScript.Temp, "temp.ex", __ENV__) ) + result = PatternMatching.build_match(params, scope ) expected_result = { [JS.object_expression([ - Map.make_property(Translator.translate!(:which, ElixirScript.Translator.LexicalScope.module_scope(ElixirScript.Temp, "temp.ex", __ENV__) ), JS.literal(13)) + Map.make_property(Translator.translate!(:which, scope ), JS.literal(13)) ])], [] } @@ -220,9 +220,9 @@ defmodule ElixirScript.Translator.PatternMatching.Test do end - test "match on bound value" do + test "match on bound value", %{scope: scope} do params = [{:^, [], [{:a, [], Elixir}]}] - result = PatternMatching.build_match(params, ElixirScript.Translator.LexicalScope.module_scope(ElixirScript.Temp, "temp.ex", __ENV__) ) + result = PatternMatching.build_match(params, scope ) expected_result = { [PatternMatching.bound(JS.identifier("a"))], From dd7de5653ccea98f5ea7a99f12537eb42a561bf2 Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Thu, 16 Feb 2017 19:03:52 -0600 Subject: [PATCH 372/860] Update implemenation of for --- .../translator/kernel/special_forms/for.ex | 56 ++++- package.json | 4 +- src/javascript/lib/core/special_forms.js | 155 ++++++------- src/javascript/tests/for.spec.js | 121 +++++----- test/translator/for_test.exs | 208 +++++++++++++----- test/translator/pattern_matching_test.exs | 38 ++-- 6 files changed, 357 insertions(+), 225 deletions(-) diff --git a/lib/elixir_script/translator/kernel/special_forms/for.ex b/lib/elixir_script/translator/kernel/special_forms/for.ex index 1e97f5d5..8d92a3a7 100644 --- a/lib/elixir_script/translator/kernel/special_forms/for.ex +++ b/lib/elixir_script/translator/kernel/special_forms/for.ex @@ -10,24 +10,40 @@ defmodule ElixirScript.Translator.For do def make_for(generators, env) do args = handle_args(generators, env) + generators = JS.array_expression(args.generators) + collections = Primitive.make_list_no_translate(args.collections) into = args.into || Primitive.make_list_no_translate([]) filter = args.filter || JS.function_expression([], [], JS.block_statement([JS.return_statement(JS.identifier("true"))])) fun = args.fun + expression = JS.call_expression( + JS.member_expression( + JS.member_expression( + JS.member_expression( + JS.identifier("Elixir"), + JS.identifier("Core") + ), + JS.identifier("Patterns") + ), + JS.identifier("clause") + ), + [JS.array_expression(args.patterns), fun, filter] + ) + js_ast = JS.call_expression( JS.member_expression( Primitive.special_forms(), JS.identifier("_for") ), - [collections, fun, filter, into] + [expression, generators, into] ) { js_ast, env } end defp handle_args(generators, env) do - Enum.reduce(generators, %{collections: [], args: [], filter: nil, fun: nil, into: nil}, fn + Enum.reduce(generators, %{generators: [], collections: [], args: [], filter: nil, fun: nil, into: nil, patterns: []}, fn ({:<<>>, [], body}, state) -> { bs_parts, collection } = Enum.map_reduce(body, nil, fn @@ -38,15 +54,41 @@ defmodule ElixirScript.Translator.For do end) { patterns, params, env } = PatternMatching.process_match([{:<<>>, [], bs_parts}], env) - list = Primitive.make_list_no_translate([hd(patterns), Translator.translate!(collection, env)]) - %{state | collections: state.collections ++ [list], args: state.args ++ params } + + gen = JS.call_expression( + JS.member_expression( + JS.member_expression( + JS.member_expression( + JS.identifier("Elixir"), + JS.identifier("Core") + ), + JS.identifier("Patterns") + ), + JS.identifier("bitstring_generator") + ), + [hd(patterns), Translator.translate!(collection, env)] + ) + + %{state | generators: state.generators ++ [gen], args: state.args ++ params, patterns: state.patterns ++ patterns } ({:<-, _, [identifier, enum]}, state) -> { patterns, params, env } = PatternMatching.process_match([identifier], env) - list = Primitive.make_list_no_translate([hd(patterns), Translator.translate!(enum, env)]) - - %{state | collections: state.collections ++ [list], args: state.args ++ params } + gen = JS.call_expression( + JS.member_expression( + JS.member_expression( + JS.member_expression( + JS.identifier("Elixir"), + JS.identifier("Core") + ), + JS.identifier("Patterns") + ), + JS.identifier("list_generator") + ), + [hd(patterns), Translator.translate!(enum, env)] + ) + + %{state | generators: state.generators ++ [gen], args: state.args ++ params, patterns: state.patterns ++ patterns } ([into: expression], state) -> %{ state | into: Translator.translate(expression, env) } diff --git a/package.json b/package.json index 7c7bd05b..b22b3b64 100644 --- a/package.json +++ b/package.json @@ -21,7 +21,7 @@ "dependencies": { "erlang-types": "^1.0.0", "erlang-processes": "^2.0.0", - "tailored": "^2.2.0" + "tailored": "2.3.1" }, "devDependencies": { "babel": "^6.5.2", @@ -41,4 +41,4 @@ "rollup-plugin-babel": "^2.5.1", "rollup-plugin-node-resolve": "^1.7.0" } -} +} \ No newline at end of file diff --git a/src/javascript/lib/core/special_forms.js b/src/javascript/lib/core/special_forms.js index 4214cfea..68c53c12 100644 --- a/src/javascript/lib/core/special_forms.js +++ b/src/javascript/lib/core/special_forms.js @@ -1,12 +1,12 @@ -import Core from '../core'; +import Core from "../core"; -function _case(condition, clauses){ +function _case(condition, clauses) { return Core.Patterns.defmatch(...clauses)(condition); } -function cond(clauses){ - for(let clause of clauses){ - if(clause[0]){ +function cond(clauses) { + for (let clause of clauses) { + if (clause[0]) { return clause[1](); } } @@ -14,155 +14,132 @@ function cond(clauses){ throw new Error(); } -function map_update(map, values){ +function map_update(map, values) { return Object.freeze( - Object.assign( - Object.create(map.constructor.prototype), map, values - ) + Object.assign(Object.create(map.constructor.prototype), map, values) ); } -function _for(collections, fun, filter = () => true, into = [], previousValues = []){ - let pattern = collections[0][0]; - let collection = collections[0][1]; +function _for(expression, generators, into = []) { + const generatedValues = run_list_generators(generators.pop()(), generators); - if(collections.length === 1){ - if(collection instanceof Core.BitString){ - let bsSlice = collection.slice(0, pattern.byte_size()); - let i = 1; + let result = into; - while(bsSlice.byte_size == pattern.byte_size()){ - let r = Core.Patterns.match_or_default(pattern, bsSlice); - let args = previousValues.concat(r); - - if(r && filter.apply(this, args)){ - into = into.concat([fun.apply(this, args)]); - } - - bsSlice = collection.slice(pattern.byte_size() * i, pattern.byte_size() * (i + 1)); - i++; - } - - return into; - }else{ - for(let elem of collection){ - let r = Core.Patterns.match_or_default(pattern, elem); - let args = previousValues.concat(r); - - if(r && filter.apply(this, args)){ - into = into.concat([fun.apply(this, args)]); - } - } - - return into; + for (let value of generatedValues) { + if (expression.guard.apply(this, value)) { + result = result.concat([expression.fn.apply(this, value)]); } - }else{ - let _into = []; - - if(collection instanceof Core.BitString){ - let bsSlice = collection.slice(0, pattern.byte_size()); - let i = 1; + } - while(bsSlice.byte_size == pattern.byte_size()){ - let r = Core.Patterns.match_or_default(pattern, bsSlice); - if(r){ - _into = into.concat(this._for(collections.slice(1), fun, filter, _into, previousValues.concat(r))); - } + return result; +} - bsSlice = collection.slice(pattern.byte_size() * i, pattern.byte_size() * (i + 1)); - i++; +function run_list_generators(generator, generators) { + if (generators.length == 0) { + return generator.map(x => { + if (Array.isArray(x)) { + return x; + } else { + return [x]; } - }else{ - for(let elem of collection){ - let r = Core.Patterns.match_or_default(pattern, elem); - if(r){ - _into = into.concat(this._for(collections.slice(1), fun, filter, _into, previousValues.concat(r))); - } + }); + } else { + const list = generators.pop(); + + let next_gen = []; + for (let j of list()) { + for (let i of generator) { + next_gen.push([j].concat(i)); } } - return _into; + return run_list_generators(next_gen, generators); } } -function _try(do_fun, rescue_function, catch_fun, else_function, after_function){ +function _try( + do_fun, + rescue_function, + catch_fun, + else_function, + after_function +) { let result = null; - try{ + try { result = do_fun(); - }catch(e){ + } catch (e) { let ex_result = null; - if(rescue_function){ - try{ + if (rescue_function) { + try { ex_result = rescue_function(e); return ex_result; - }catch(ex){ - if(ex instanceof Core.Patterns.MatchError){ + } catch (ex) { + if (ex instanceof Core.Patterns.MatchError) { throw ex; } } } - if(catch_fun){ - try{ + if (catch_fun) { + try { ex_result = catch_fun(e); return ex_result; - }catch(ex){ - if(ex instanceof Core.Patterns.MatchError){ + } catch (ex) { + if (ex instanceof Core.Patterns.MatchError) { throw ex; } } } throw e; - - }finally{ - if(after_function){ + } finally { + if (after_function) { after_function(); } } - if(else_function){ - try{ + if (else_function) { + try { return else_function(result); - }catch(ex){ - if(ex instanceof Core.Patterns.MatchError){ - throw new Error("No Match Found in Else"); - } + } catch (ex) { + if (ex instanceof Core.Patterns.MatchError) { + throw new Error("No Match Found in Else"); + } throw ex; } - }else{ + } else { return result; } } -function _with(...args){ +function _with(...args) { let argsToPass = []; let successFunction = null; let elseFunction = null; - if(typeof(args[args.length - 2]) === 'function'){ + if (typeof args[args.length - 2] === "function") { [successFunction, elseFunction] = args.splice(-2); - }else{ + } else { successFunction = args.pop(); } - for(let i = 0; i < args.length; i++){ + for (let i = 0; i < args.length; i++) { let [pattern, func] = args[i]; let result = func.apply(null, argsToPass); let patternResult = Core.Patterns.match_or_default(pattern, result); - if(patternResult == null){ - if(elseFunction){ + if (patternResult == null) { + if (elseFunction) { return elseFunction.call(null, result); - }else{ + } else { return result; } - }else{ + } else { argsToPass = argsToPass.concat(patternResult); } } diff --git a/src/javascript/tests/for.spec.js b/src/javascript/tests/for.spec.js index 5ae6f667..a1e002da 100644 --- a/src/javascript/tests/for.spec.js +++ b/src/javascript/tests/for.spec.js @@ -6,86 +6,105 @@ const BitString = Core.BitString; import Enum from "../lib/enum"; -import chai from 'chai'; +import chai from "chai"; var expect = chai.expect; const $ = Patterns.variable(); -describe('for', () => { - it('simple for', () => { - let collections = [ - [$, [1, 2, 3, 4]] - ]; - - let result = SpecialForms._for(collections, (n) => n * 2); +describe("for", () => { + it("simple for", () => { + let gen = Patterns.list_generator($, [1, 2, 3, 4]); + let result = SpecialForms._for(Patterns.clause([$], x => x * 2), [gen]); expect(result).to.eql([2, 4, 6, 8]); }); - it('for with multiple generators', () => { + it("for with multiple generators", () => { //for x <- [1, 2], y <- [2, 3], do: x*y - let collections = [ - [$, [1, 2]], - [$, [2, 3]] - ]; - let result = SpecialForms._for(collections, (x, y) => x * y); + let gen = Patterns.list_generator($, [1, 2]); + let gen2 = Patterns.list_generator($, [2, 3]); + let result = SpecialForms._for(Patterns.clause([$, $], (x, y) => x * y), [ + gen, + gen2 + ]); expect(result).to.eql([2, 3, 4, 6]); }); - - it('for with filter', () => { + it("for with filter", () => { //for n <- [1, 2, 3, 4, 5, 6], rem(n, 2) == 0, do: n - let collections = [ - [$, [1, 2, 3, 4, 5, 6]] - ]; - - let result = SpecialForms._for(collections, (n) => n, (n) => n % 2 == 0); + let gen = Patterns.list_generator($, [1, 2, 3, 4, 5, 6]); + let result = SpecialForms._for( + Patterns.clause([$], x => x, x => x % 2 === 0), + [gen] + ); expect(result).to.eql([2, 4, 6]); }); - it('for with pattern matching', () => { + it("for with pattern matching", () => { //for {:user, name} <- [user: "john", admin: "john", user: "meg"], do // String.upcase(name) //end - let collections = [ - [[Symbol.for("user"), $], [[Symbol.for("user"), "john"], [Symbol.for("admin"), "john"], [Symbol.for("user"), "meg"]]] - ]; - let result = SpecialForms._for(collections, (name) => name.toUpperCase()); + let gen = Patterns.list_generator([Symbol.for("user"), $], [ + [Symbol.for("user"), "john"], + [Symbol.for("admin"), "john"], + [Symbol.for("user"), "meg"] + ]); + + let result = SpecialForms._for( + Patterns.clause([[Symbol.for("user"), $]], name => name.toUpperCase()), + [gen] + ); expect(result).to.eql(["JOHN", "MEG"]); }); - - it('for with bitstring', () => { + it("for with bitstring", () => { //for <> >>, do: {r, g, b} - - let collections = [ + + let gen = Patterns.bitstring_generator( + Patterns.bitStringMatch( + BitString.integer({ value: $ }), + BitString.integer({ value: $ }), + BitString.integer({ value: $ }) + ), + new BitString( + BitString.integer(213), + BitString.integer(45), + BitString.integer(132), + BitString.integer(64), + BitString.integer(76), + BitString.integer(32), + BitString.integer(76), + BitString.integer(0), + BitString.integer(0), + BitString.integer(234), + BitString.integer(32), + BitString.integer(15) + ) + ); + + let expression = Patterns.clause( [ - Patterns.bitStringMatch(BitString.integer({value: $}), BitString.integer({value: $}), BitString.integer({value: $})), - new BitString( - BitString.integer(213), - BitString.integer(45), - BitString.integer(132), - BitString.integer(64), - BitString.integer(76), - BitString.integer(32), - BitString.integer(76), - BitString.integer(0), - BitString.integer(0), - BitString.integer(234), - BitString.integer(32), - BitString.integer(15) + Patterns.bitStringMatch( + BitString.integer({ value: $ }), + BitString.integer({ value: $ }), + BitString.integer({ value: $ }) ) - ] - ]; - - let result = SpecialForms._for(collections, (r, g, b) => new Tuple(r, g, b)); - - expect(result).to.eql([new Tuple(213, 45, 132), new Tuple(64, 76, 32), new Tuple(76, 0, 0), new Tuple(234, 32, 15)]); + ], + (r, g, b) => new Tuple(r, g, b) + ); + + let result = SpecialForms._for(expression, [gen]); + + expect(result).to.eql([ + new Tuple(213, 45, 132), + new Tuple(64, 76, 32), + new Tuple(76, 0, 0), + new Tuple(234, 32, 15) + ]); }); - }); diff --git a/test/translator/for_test.exs b/test/translator/for_test.exs index 945c8bd5..79e682ba 100644 --- a/test/translator/for_test.exs +++ b/test/translator/for_test.exs @@ -8,12 +8,25 @@ defmodule ElixirScript.Translator.For.Test do end js_code = """ - Elixir.Core.SpecialForms._for(Object.freeze([Object.freeze([Elixir.Core.Patterns.variable(), Object.freeze([1, 2, 3, 4])])]),function(n) { - return n * 2; - },function() { - return true; - },Object.freeze([])) - """ + Elixir.Core.SpecialForms._for( + Elixir.Core.Patterns.clause( + [Elixir.Core.Patterns.variable()], + function(n) { + return n * 2; + }, + function() { + return true; + } + ), + [ + Elixir.Core.Patterns.list_generator( + Elixir.Core.Patterns.variable(), + Object.freeze([1, 2, 3, 4]) + ) + ], + Object.freeze([]) + ) + """ assert_translation(ex_ast, js_code) end @@ -24,14 +37,24 @@ defmodule ElixirScript.Translator.For.Test do end js_code = """ - Elixir.Core.SpecialForms._for( - Object.freeze([Object.freeze([Elixir.Core.Patterns.variable(), Object.freeze([1, 2, 3, 4])])]), - function(n) { - return n * 2; - },function() { - return true; - }, - Object.freeze([])) + Elixir.Core.SpecialForms._for( + Elixir.Core.Patterns.clause( + [Elixir.Core.Patterns.variable()], + function(n) { + return n * 2; + }, + function() { + return true; + } + ), + [ + Elixir.Core.Patterns.list_generator( + Elixir.Core.Patterns.variable(), + Object.freeze([1, 2, 3, 4]) + ) + ], + Object.freeze([]) + ) """ assert_translation(ex_ast, js_code) @@ -43,11 +66,24 @@ defmodule ElixirScript.Translator.For.Test do end js_code = """ - Elixir.Core.SpecialForms._for(Object.freeze([Object.freeze([Elixir.Core.Patterns.variable(), 'Opera'])]),function(n) { - return n; - },function() { - return true; - },Object.freeze([])) + Elixir.Core.SpecialForms._for( + Elixir.Core.Patterns.clause( + [Elixir.Core.Patterns.variable()], + function(n) { + return n; + }, + function() { + return true; + } + ), + [ + Elixir.Core.Patterns.list_generator( + Elixir.Core.Patterns.variable(), + 'Opera' + ) + ], + Object.freeze([]) + ) """ assert_translation(ex_ast, js_code) @@ -59,11 +95,28 @@ defmodule ElixirScript.Translator.For.Test do end js_code = """ - Elixir.Core.SpecialForms._for(Object.freeze([Object.freeze([Elixir.Core.Patterns.variable(), Object.freeze([1, 2])]), Object.freeze([Elixir.Core.Patterns.variable(), Object.freeze([2, 3])])]),function(x,y) { - return x * y; - },function() { - return true; - },Object.freeze([])) + Elixir.Core.SpecialForms._for( + Elixir.Core.Patterns.clause( + [Elixir.Core.Patterns.variable(), Elixir.Core.Patterns.variable()], + function(x, y) { + return x * y; + }, + function() { + return true; + } + ), + [ + Elixir.Core.Patterns.list_generator( + Elixir.Core.Patterns.variable(), + Object.freeze([1, 2]) + ), + Elixir.Core.Patterns.list_generator( + Elixir.Core.Patterns.variable(), + Object.freeze([2, 3]) + ) + ], + Object.freeze([]) + ) """ assert_translation(ex_ast, js_code) @@ -77,11 +130,31 @@ defmodule ElixirScript.Translator.For.Test do end js_code = """ - let [r] = Elixir.Core.Patterns.match(Elixir.Core.Patterns.variable(),Elixir.Core.SpecialForms._for(Object.freeze([Object.freeze([Elixir.Core.Patterns.variable(), Object.freeze([1, 2])]), Object.freeze([Elixir.Core.Patterns.variable(), Object.freeze([2, 3])])]),function(x,y) { - return x * y; - },function() { - return true; - },Object.freeze([]))); + let [r] = Elixir.Core.Patterns.match( + Elixir.Core.Patterns.variable(), + Elixir.Core.SpecialForms._for( + Elixir.Core.Patterns.clause( + [Elixir.Core.Patterns.variable(), Elixir.Core.Patterns.variable()], + function(x, y) { + return x * y; + }, + function() { + return true; + } + ), + [ + Elixir.Core.Patterns.list_generator( + Elixir.Core.Patterns.variable(), + Object.freeze([1, 2]) + ), + Elixir.Core.Patterns.list_generator( + Elixir.Core.Patterns.variable(), + Object.freeze([2, 3]) + ) + ], + Object.freeze([]) + ) + ); """ assert_translation(ex_ast, js_code) @@ -93,11 +166,24 @@ defmodule ElixirScript.Translator.For.Test do end js_code = """ - Elixir.Core.SpecialForms._for(Object.freeze([Object.freeze([Elixir.Core.Patterns.variable(), Object.freeze([1, 2, 3, 4, 5, 6])])]),function(n) { - return n; - },function(n) { - return n % 2 == 0; - },Object.freeze([])) + Elixir.Core.SpecialForms._for( + Elixir.Core.Patterns.clause( + [Elixir.Core.Patterns.variable()], + function(n) { + return n; + }, + function(n) { + return n % 2 == 0; + } + ), + [ + Elixir.Core.Patterns.list_generator( + Elixir.Core.Patterns.variable(), + Object.freeze([1, 2, 3, 4, 5, 6]) + ) + ], + Object.freeze([]) + ) """ assert_translation(ex_ast, js_code) @@ -111,13 +197,20 @@ defmodule ElixirScript.Translator.For.Test do end js_code = """ - Elixir.Core.SpecialForms._for(Object.freeze([Object.freeze([Elixir.Core.Patterns.type(Elixir.Core.Tuple,{ - values: [Symbol.for('user'), Elixir.Core.Patterns.variable()] - }), Object.freeze([new Elixir.Core.Tuple(Symbol.for('user'),'john'), new Elixir.Core.Tuple(Symbol.for('admin'),'john'), new Elixir.Core.Tuple(Symbol.for('user'),'meg')])])]),function(name) { - return Elixir$ElixirScript$String.upcase(name); - },function() { - return true; - },Object.freeze([])) + Elixir.Core.SpecialForms._for( + Elixir.Core.Patterns.clause([Elixir.Core.Patterns.type(Elixir.Core.Tuple, { + values: [Symbol.for('user'), Elixir.Core.Patterns.variable()] + })], function(name) { + return Elixir$ElixirScript$String.upcase(name); + }, function() { + return true; + }), + [ + Elixir.Core.Patterns.list_generator(Elixir.Core.Patterns.type(Elixir.Core.Tuple, { + values: [Symbol.for('user'), Elixir.Core.Patterns.variable()] + }), Object.freeze([new Elixir.Core.Tuple(Symbol.for('user'), 'john'), new Elixir.Core.Tuple(Symbol.for('admin'), 'john'), new Elixir.Core.Tuple(Symbol.for('user'), 'meg')])) + ], + Object.freeze([])) """ assert_translation(ex_ast, js_code) @@ -131,22 +224,23 @@ defmodule ElixirScript.Translator.For.Test do end js_code = """ - Elixir.Core.SpecialForms._for(Object.freeze([Object.freeze([Elixir.Core.Patterns.bitStringMatch(Elixir.Core.BitString.size({ - 'value': Elixir.Core.Patterns.variable() - },8), - Elixir.Core.BitString.size({ - 'value': Elixir.Core.Patterns.variable() - },8), - Elixir.Core.BitString.size({ - 'value': Elixir.Core.Patterns.variable() - },8)), pixels])]), - function(r,g,b) { - return new Elixir.Core.Tuple(r,g,b); - }, - function() { - return true; - }, - Object.freeze([])) + Elixir.Core.SpecialForms._for(Elixir.Core.Patterns.clause([Elixir.Core.Patterns.bitStringMatch(Elixir.Core.BitString.size({ + 'value': Elixir.Core.Patterns.variable() + }, 8), Elixir.Core.BitString.size({ + 'value': Elixir.Core.Patterns.variable() + }, 8), Elixir.Core.BitString.size({ + 'value': Elixir.Core.Patterns.variable() + }, 8))], function(r, g, b) { + return new Elixir.Core.Tuple(r, g, b); + }, function() { + return true; + }), [Elixir.Core.Patterns.bitstring_generator(Elixir.Core.Patterns.bitStringMatch(Elixir.Core.BitString.size({ + 'value': Elixir.Core.Patterns.variable() + }, 8), Elixir.Core.BitString.size({ + 'value': Elixir.Core.Patterns.variable() + }, 8), Elixir.Core.BitString.size({ + 'value': Elixir.Core.Patterns.variable() + }, 8)), pixels)], Object.freeze([])) """ assert_translation(ex_ast, js_code) diff --git a/test/translator/pattern_matching_test.exs b/test/translator/pattern_matching_test.exs index 0b2cd8f9..2effb06a 100644 --- a/test/translator/pattern_matching_test.exs +++ b/test/translator/pattern_matching_test.exs @@ -19,7 +19,7 @@ defmodule ElixirScript.Translator.PatternMatching.Test do test "match wildcard", %{scope: scope} do params = [{:_, [], Test}] result = PatternMatching.build_match(params, scope) - expected_result = { [PatternMatching.wildcard], [JS.identifier(:undefined)] } + expected_result = {[PatternMatching.wildcard], [JS.identifier(:undefined)]} assert result == expected_result end @@ -38,7 +38,7 @@ defmodule ElixirScript.Translator.PatternMatching.Test do expected_result = { List.duplicate(PatternMatching.parameter, 3), [JS.identifier("a"), JS.identifier("b"), JS.identifier("c")] - } + } assert result == expected_result end @@ -49,7 +49,7 @@ defmodule ElixirScript.Translator.PatternMatching.Test do expected_result = { [PatternMatching.head_tail(PatternMatching.parameter, PatternMatching.parameter)], [JS.identifier("head"), JS.identifier("tail")] - } + } assert result == expected_result end @@ -60,7 +60,7 @@ defmodule ElixirScript.Translator.PatternMatching.Test do expected_result = { [PatternMatching.starts_with("Bearer ")], [JS.identifier("token")] - } + } assert result == expected_result end @@ -71,7 +71,7 @@ defmodule ElixirScript.Translator.PatternMatching.Test do expected_result = { [Primitive.make_list_no_translate(List.duplicate(PatternMatching.parameter, 3))], [JS.identifier("a"), JS.identifier("b"), JS.identifier("c")] - } + } assert result == expected_result end @@ -82,7 +82,7 @@ defmodule ElixirScript.Translator.PatternMatching.Test do expected_result = { [Primitive.make_list_no_translate([JS.literal(1), PatternMatching.parameter, PatternMatching.parameter])], [JS.identifier("b"), JS.identifier("c")] - } + } assert result == expected_result end @@ -93,7 +93,7 @@ defmodule ElixirScript.Translator.PatternMatching.Test do expected_result = { [JS.literal(1)], [] - } + } assert result == expected_result end @@ -104,7 +104,7 @@ defmodule ElixirScript.Translator.PatternMatching.Test do expected_result = { [PatternMatching.type(JS.identifier("Hello"), JS.object_expression([]))], [] - } + } assert result == expected_result end @@ -118,13 +118,13 @@ defmodule ElixirScript.Translator.PatternMatching.Test do ])) ], [] - } + } assert result == expected_result end test "match struct pattern with property param", %{scope: scope} do - params = [{:%, [], [{:__aliases__, [alias: false], [:Hello]}, {:%{}, [], [key: {:key, [], Elixir }]}]}] + params = [{:%, [], [{:__aliases__, [alias: false], [:Hello]}, {:%{}, [], [key: {:key, [], Elixir}]}]}] result = PatternMatching.build_match(params, scope ) expected_result = { [PatternMatching.type(JS.identifier("Hello"), JS.object_expression([ @@ -132,7 +132,7 @@ defmodule ElixirScript.Translator.PatternMatching.Test do ])) ], [JS.identifier("key")] - } + } assert result == expected_result end @@ -143,7 +143,7 @@ defmodule ElixirScript.Translator.PatternMatching.Test do expected_result = { [PatternMatching.capture(JS.literal(1))], [JS.identifier("a")] - } + } assert result == expected_result @@ -153,7 +153,7 @@ defmodule ElixirScript.Translator.PatternMatching.Test do expected_result = { [PatternMatching.capture(JS.literal(1))], [JS.identifier("a")] - } + } assert result == expected_result @@ -163,7 +163,7 @@ defmodule ElixirScript.Translator.PatternMatching.Test do expected_result = { [PatternMatching.capture(PatternMatching.type(JS.identifier("AStruct"), JS.object_expression([])))], [JS.identifier("a")] - } + } assert result == expected_result end @@ -174,7 +174,7 @@ defmodule ElixirScript.Translator.PatternMatching.Test do expected_result = { [PatternMatching.capture(Primitive.make_list_no_translate([PatternMatching.parameter, PatternMatching.parameter, PatternMatching.parameter]))], [JS.identifier("a"), JS.identifier("b"), JS.identifier("c"), JS.identifier("d")] - } + } assert result == expected_result end @@ -188,7 +188,7 @@ defmodule ElixirScript.Translator.PatternMatching.Test do JS.array_expression([JS.literal(1), PatternMatching.parameter, JS.literal(3)]) ) ] )) ], [JS.identifier("b")] - } + } assert result == expected_result @@ -200,7 +200,7 @@ defmodule ElixirScript.Translator.PatternMatching.Test do JS.array_expression([JS.literal(1), PatternMatching.parameter]) ) ] )) ], [JS.identifier("b")] - } + } assert result == expected_result end @@ -214,7 +214,7 @@ defmodule ElixirScript.Translator.PatternMatching.Test do Map.make_property(Translator.translate!(:which, scope ), JS.literal(13)) ])], [] - } + } assert result == expected_result end @@ -227,7 +227,7 @@ defmodule ElixirScript.Translator.PatternMatching.Test do expected_result = { [PatternMatching.bound(JS.identifier("a"))], [nil] - } + } assert result == expected_result end From 56fdf982d0fe632dcbc5b353ae012555336227e6 Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Thu, 16 Feb 2017 20:52:48 -0600 Subject: [PATCH 373/860] Add implementations for Collectable --- lib/elixir_script/prelude/collectable.ex | 30 +++++++++++++ .../translator/kernel/special_forms/for.ex | 4 +- package.json | 2 +- src/javascript/lib/core/special_forms.js | 13 +++--- src/javascript/tests/for.spec.js | 42 +++++++++++++++---- test/translator/for_test.exs | 21 ++++++---- 6 files changed, 90 insertions(+), 22 deletions(-) diff --git a/lib/elixir_script/prelude/collectable.ex b/lib/elixir_script/prelude/collectable.ex index 339b17ce..9d521de8 100644 --- a/lib/elixir_script/prelude/collectable.ex +++ b/lib/elixir_script/prelude/collectable.ex @@ -2,3 +2,33 @@ defprotocol ElixirScript.Collectable do @moduledoc false def into(collectable) end + +defimpl Collectable, for: List do + def into(original) do + {[], fn + list, {:cont, x} -> list ++ [x] + list, :done -> original ++ list + _, :halt -> :ok + end} + end +end + +defimpl Collectable, for: BitString do + def into(original) do + {original, fn + acc, {:cont, x} when is_bitstring(x) -> <> + acc, :done -> acc + _, :halt -> :ok + end} + end +end + +defimpl Collectable, for: Map do + def into(original) do + {original, fn + map, {:cont, {k, v}} -> Map.put(map, k, v) + map, :done -> map + _, :halt -> :ok + end} + end +end \ No newline at end of file diff --git a/lib/elixir_script/translator/kernel/special_forms/for.ex b/lib/elixir_script/translator/kernel/special_forms/for.ex index 8d92a3a7..2b5d893c 100644 --- a/lib/elixir_script/translator/kernel/special_forms/for.ex +++ b/lib/elixir_script/translator/kernel/special_forms/for.ex @@ -5,9 +5,11 @@ defmodule ElixirScript.Translator.For do alias ElixirScript.Translator.PatternMatching alias ElixirScript.Translator.Primitive alias ElixirScript.Translator.Function + alias ElixirScript.Translator.Utils def make_for(generators, env) do + ElixirScript.Translator.State.add_module_reference(env.state, env.module, ElixirScript.Collectable) args = handle_args(generators, env) generators = JS.array_expression(args.generators) @@ -36,7 +38,7 @@ defmodule ElixirScript.Translator.For do Primitive.special_forms(), JS.identifier("_for") ), - [expression, generators, into] + [expression, generators, JS.identifier(Utils.name_to_js_name(ElixirScript.Collectable)), into] ) { js_ast, env } diff --git a/package.json b/package.json index b22b3b64..59b2b859 100644 --- a/package.json +++ b/package.json @@ -21,7 +21,7 @@ "dependencies": { "erlang-types": "^1.0.0", "erlang-processes": "^2.0.0", - "tailored": "2.3.1" + "tailored": "2.3.2" }, "devDependencies": { "babel": "^6.5.2", diff --git a/src/javascript/lib/core/special_forms.js b/src/javascript/lib/core/special_forms.js index 68c53c12..c5854097 100644 --- a/src/javascript/lib/core/special_forms.js +++ b/src/javascript/lib/core/special_forms.js @@ -20,18 +20,21 @@ function map_update(map, values) { ); } -function _for(expression, generators, into = []) { - const generatedValues = run_list_generators(generators.pop()(), generators); +function _for(expression, generators, collectable_protocol, into = []) { + let [result, fun] = collectable_protocol.into(into); - let result = into; + const generatedValues = run_list_generators(generators.pop()(), generators); for (let value of generatedValues) { if (expression.guard.apply(this, value)) { - result = result.concat([expression.fn.apply(this, value)]); + result = fun(result, new Core.Tuple( + Symbol.for("cont"), + expression.fn.apply(this, value) + )); } } - return result; + return fun(result, Symbol.for("done")); } function run_list_generators(generator, generators) { diff --git a/src/javascript/tests/for.spec.js b/src/javascript/tests/for.spec.js index a1e002da..f872d649 100644 --- a/src/javascript/tests/for.spec.js +++ b/src/javascript/tests/for.spec.js @@ -11,10 +11,33 @@ var expect = chai.expect; const $ = Patterns.variable(); +const collectable = { + into: function(original) { + const fun = Patterns.defmatch( + Patterns.clause( + [ + $, + Patterns.type(Tuple, { + values: [Symbol.for("cont"), Patterns.variable()] + }) + ], + (list, x) => list.concat([x]) + ), + Patterns.clause([$, Symbol.for("done")], list => list) + ); + + return new Tuple([], fun); + } +}; + describe("for", () => { it("simple for", () => { let gen = Patterns.list_generator($, [1, 2, 3, 4]); - let result = SpecialForms._for(Patterns.clause([$], x => x * 2), [gen]); + let result = SpecialForms._for( + Patterns.clause([$], x => x * 2), + [gen], + collectable + ); expect(result).to.eql([2, 4, 6, 8]); }); @@ -24,10 +47,11 @@ describe("for", () => { let gen = Patterns.list_generator($, [1, 2]); let gen2 = Patterns.list_generator($, [2, 3]); - let result = SpecialForms._for(Patterns.clause([$, $], (x, y) => x * y), [ - gen, - gen2 - ]); + let result = SpecialForms._for( + Patterns.clause([$, $], (x, y) => x * y), + [gen, gen2], + collectable + ); expect(result).to.eql([2, 3, 4, 6]); }); @@ -37,7 +61,8 @@ describe("for", () => { let gen = Patterns.list_generator($, [1, 2, 3, 4, 5, 6]); let result = SpecialForms._for( Patterns.clause([$], x => x, x => x % 2 === 0), - [gen] + [gen], + collectable ); expect(result).to.eql([2, 4, 6]); @@ -56,7 +81,8 @@ describe("for", () => { let result = SpecialForms._for( Patterns.clause([[Symbol.for("user"), $]], name => name.toUpperCase()), - [gen] + [gen], + collectable ); expect(result).to.eql(["JOHN", "MEG"]); @@ -98,7 +124,7 @@ describe("for", () => { (r, g, b) => new Tuple(r, g, b) ); - let result = SpecialForms._for(expression, [gen]); + let result = SpecialForms._for(expression, [gen], collectable); expect(result).to.eql([ new Tuple(213, 45, 132), diff --git a/test/translator/for_test.exs b/test/translator/for_test.exs index 79e682ba..0ab2666a 100644 --- a/test/translator/for_test.exs +++ b/test/translator/for_test.exs @@ -23,7 +23,8 @@ defmodule ElixirScript.Translator.For.Test do Elixir.Core.Patterns.variable(), Object.freeze([1, 2, 3, 4]) ) - ], + ], + Elixir$ElixirScript$Collectable, Object.freeze([]) ) """ @@ -52,7 +53,8 @@ defmodule ElixirScript.Translator.For.Test do Elixir.Core.Patterns.variable(), Object.freeze([1, 2, 3, 4]) ) - ], + ], + Elixir$ElixirScript$Collectable, Object.freeze([]) ) """ @@ -81,7 +83,8 @@ defmodule ElixirScript.Translator.For.Test do Elixir.Core.Patterns.variable(), 'Opera' ) - ], + ], + Elixir$ElixirScript$Collectable, Object.freeze([]) ) """ @@ -114,7 +117,8 @@ defmodule ElixirScript.Translator.For.Test do Elixir.Core.Patterns.variable(), Object.freeze([2, 3]) ) - ], + ], + Elixir$ElixirScript$Collectable, Object.freeze([]) ) """ @@ -152,6 +156,7 @@ defmodule ElixirScript.Translator.For.Test do Object.freeze([2, 3]) ) ], + Elixir$ElixirScript$Collectable, Object.freeze([]) ) ); @@ -181,7 +186,8 @@ defmodule ElixirScript.Translator.For.Test do Elixir.Core.Patterns.variable(), Object.freeze([1, 2, 3, 4, 5, 6]) ) - ], + ], + Elixir$ElixirScript$Collectable, Object.freeze([]) ) """ @@ -209,7 +215,8 @@ defmodule ElixirScript.Translator.For.Test do Elixir.Core.Patterns.list_generator(Elixir.Core.Patterns.type(Elixir.Core.Tuple, { values: [Symbol.for('user'), Elixir.Core.Patterns.variable()] }), Object.freeze([new Elixir.Core.Tuple(Symbol.for('user'), 'john'), new Elixir.Core.Tuple(Symbol.for('admin'), 'john'), new Elixir.Core.Tuple(Symbol.for('user'), 'meg')])) - ], + ], + Elixir$ElixirScript$Collectable, Object.freeze([])) """ @@ -240,7 +247,7 @@ defmodule ElixirScript.Translator.For.Test do 'value': Elixir.Core.Patterns.variable() }, 8), Elixir.Core.BitString.size({ 'value': Elixir.Core.Patterns.variable() - }, 8)), pixels)], Object.freeze([])) + }, 8)), pixels)], Elixir$ElixirScript$Collectable, Object.freeze([])) """ assert_translation(ex_ast, js_code) From 4dbce8e9c674501358009d1e138865f8e6e93ac5 Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Thu, 16 Feb 2017 21:28:37 -0600 Subject: [PATCH 374/860] Fix function head when there is a guard and multiple params --- lib/elixir_script/translator/kernel/special_forms/fn.ex | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/lib/elixir_script/translator/kernel/special_forms/fn.ex b/lib/elixir_script/translator/kernel/special_forms/fn.ex index d3f6aeef..d9c34886 100644 --- a/lib/elixir_script/translator/kernel/special_forms/fn.ex +++ b/lib/elixir_script/translator/kernel/special_forms/fn.ex @@ -20,7 +20,9 @@ defmodule ElixirScript.Translator.Function do def make_anonymous_function(functions, env, name) do clauses = functions |> Enum.map(fn - ({:->, _, [ [{:when, _, [params | guards]}], body ]}) -> + ({:->, _, [ [{:when, _, params}], body ]}) -> + guards = List.last(params) |> List.wrap + params = params |> Enum.reverse |> tl |> Enum.reverse process_function_body(params, body, env, name, guards) ({:->, _, [params, body]}) -> From e230e6cc26805473dfdf8e9ac9af7c3103a33d63 Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Thu, 16 Feb 2017 21:36:25 -0600 Subject: [PATCH 375/860] Update changelog and clean up lints --- CHANGELOG.md | 5 +++- .../translator/kernel/special_forms/for.ex | 28 +++++++++---------- mix.exs | 2 +- package.json | 2 +- 4 files changed, 19 insertions(+), 18 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 2a8abf1e..598de771 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,13 +4,16 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](http://keepachangelog.com/) and this project adheres to [Semantic Versioning](http://semver.org/). -## [0.24.1-dev] +## [0.25.0-dev] ### Added - Updated elixir_script mix compiler to support compiling elixir_script paths in dependencies +- Add `Collectable` implementations +- Updated `for` implementation to use Collectable ### Fixed - JS module functions not translated properly when imported - Update fs dependency to 2.12 +- Incorrect handling of function heads with guards ## [0.24.0] - 2017-01-15 diff --git a/lib/elixir_script/translator/kernel/special_forms/for.ex b/lib/elixir_script/translator/kernel/special_forms/for.ex index 2b5d893c..816bf3e7 100644 --- a/lib/elixir_script/translator/kernel/special_forms/for.ex +++ b/lib/elixir_script/translator/kernel/special_forms/for.ex @@ -7,14 +7,12 @@ defmodule ElixirScript.Translator.For do alias ElixirScript.Translator.Function alias ElixirScript.Translator.Utils - def make_for(generators, env) do ElixirScript.Translator.State.add_module_reference(env.state, env.module, ElixirScript.Collectable) args = handle_args(generators, env) generators = JS.array_expression(args.generators) - collections = Primitive.make_list_no_translate(args.collections) into = args.into || Primitive.make_list_no_translate([]) filter = args.filter || JS.function_expression([], [], JS.block_statement([JS.return_statement(JS.identifier("true"))])) fun = args.fun @@ -41,21 +39,21 @@ defmodule ElixirScript.Translator.For do [expression, generators, JS.identifier(Utils.name_to_js_name(ElixirScript.Collectable)), into] ) - { js_ast, env } + {js_ast, env} end defp handle_args(generators, env) do - Enum.reduce(generators, %{generators: [], collections: [], args: [], filter: nil, fun: nil, into: nil, patterns: []}, fn + Enum.reduce(generators, %{generators: [], args: [], filter: nil, fun: nil, into: nil, patterns: []}, fn ({:<<>>, [], body}, state) -> - { bs_parts, collection } = Enum.map_reduce(body, nil, fn + {bs_parts, collection} = Enum.map_reduce(body, nil, fn {:::, _, _} = ast, state -> {ast, state} {:<-, [], [var, collection]}, _ -> - { var, collection } + {var, collection} end) - { patterns, params, env } = PatternMatching.process_match([{:<<>>, [], bs_parts}], env) + {patterns, params, env} = PatternMatching.process_match([{:<<>>, [], bs_parts}], env) gen = JS.call_expression( JS.member_expression( @@ -71,10 +69,10 @@ defmodule ElixirScript.Translator.For do [hd(patterns), Translator.translate!(collection, env)] ) - %{state | generators: state.generators ++ [gen], args: state.args ++ params, patterns: state.patterns ++ patterns } + %{state | generators: state.generators ++ [gen], args: state.args ++ params, patterns: state.patterns ++ patterns} ({:<-, _, [identifier, enum]}, state) -> - { patterns, params, env } = PatternMatching.process_match([identifier], env) + {patterns, params, env} = PatternMatching.process_match([identifier], env) gen = JS.call_expression( JS.member_expression( @@ -90,29 +88,29 @@ defmodule ElixirScript.Translator.For do [hd(patterns), Translator.translate!(enum, env)] ) - %{state | generators: state.generators ++ [gen], args: state.args ++ params, patterns: state.patterns ++ patterns } + %{state | generators: state.generators ++ [gen], args: state.args ++ params, patterns: state.patterns ++ patterns} ([into: expression], state) -> - %{ state | into: Translator.translate(expression, env) } + %{state | into: Translator.translate(expression, env)} ([into: expression, do: expression2], state) -> fun = create_function_expression(expression2, env, state) - %{ state | into: Translator.translate!(expression, env), fun: fun } + %{state | into: Translator.translate!(expression, env), fun: fun} ([do: expression], state) -> fun = create_function_expression(expression, env, state) - %{ state | fun: fun } + %{state | fun: fun} (filter, state) -> fun = create_function_expression(filter, env, state) - %{ state | filter: fun } + %{state | filter: fun} end) end defp create_function_expression(ast, env, state) do - { ast, _ } = Function.make_function_body(ast, env) + {ast, _} = Function.make_function_body(ast, env) JS.function_expression( state.args, diff --git a/mix.exs b/mix.exs index 37513bb7..a1aa5964 100644 --- a/mix.exs +++ b/mix.exs @@ -4,7 +4,7 @@ defmodule ElixirScript.Mixfile do def project do [ app: :elixir_script, - version: "0.24.1-dev", + version: "0.25.0-dev", elixir: "~> 1.0", escript: escript_config(), deps: deps(), diff --git a/package.json b/package.json index 59b2b859..e84e8d83 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "elixirscript", - "version": "0.21.0", + "version": "0.25.0", "description": "Convert Elixir to JavaScript", "main": "elixir.js", "bin": { From a6c96c3f7503bf80ab04255386d0d638d942a6d8 Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Thu, 16 Feb 2017 21:52:08 -0600 Subject: [PATCH 376/860] Add enumerable implementation --- lib/elixir_script/prelude/collectable.ex | 6 ++-- lib/elixir_script/prelude/enumerable.ex | 36 ++++++++++++++++++++++++ 2 files changed, 39 insertions(+), 3 deletions(-) diff --git a/lib/elixir_script/prelude/collectable.ex b/lib/elixir_script/prelude/collectable.ex index 9d521de8..6950b962 100644 --- a/lib/elixir_script/prelude/collectable.ex +++ b/lib/elixir_script/prelude/collectable.ex @@ -3,7 +3,7 @@ defprotocol ElixirScript.Collectable do def into(collectable) end -defimpl Collectable, for: List do +defimpl ElixirScript.Collectable, for: List do def into(original) do {[], fn list, {:cont, x} -> list ++ [x] @@ -13,7 +13,7 @@ defimpl Collectable, for: List do end end -defimpl Collectable, for: BitString do +defimpl ElixirScript.Collectable, for: BitString do def into(original) do {original, fn acc, {:cont, x} when is_bitstring(x) -> <> @@ -23,7 +23,7 @@ defimpl Collectable, for: BitString do end end -defimpl Collectable, for: Map do +defimpl ElixirScript.Collectable, for: Map do def into(original) do {original, fn map, {:cont, {k, v}} -> Map.put(map, k, v) diff --git a/lib/elixir_script/prelude/enumerable.ex b/lib/elixir_script/prelude/enumerable.ex index 3fbba469..0b6d4928 100644 --- a/lib/elixir_script/prelude/enumerable.ex +++ b/lib/elixir_script/prelude/enumerable.ex @@ -4,3 +4,39 @@ defprotocol ElixirScript.Enumerable do def member?(enumerable, element) def count(enumerable) end + +defimpl ElixirScript.Enumerable, for: List do + def count(list), + do: length(list) + + def member?(list, value), + do: value in list + + def reduce(_, {:halt, acc}, _fun), do: {:halted, acc} + def reduce(list, {:suspend, acc}, fun), do: {:suspended, acc, &reduce(list, &1, fun)} + def reduce([], {:cont, acc}, _fun), do: {:done, acc} + def reduce([h | t], {:cont, acc}, fun), do: reduce(t, fun.(h, acc), fun) +end + +defimpl ElixirScript.Enumerable, for: Map do + def count(map) do + {:ok, map_size(map)} + end + + def member?(map, {key, value}) do + {:ok, match?(^value, Map.get(map, key))} + end + + def member?(_, _) do + {:ok, false} + end + + def reduce(map, acc, fun) do + do_reduce(Map.to_list(map), acc, fun) + end + + defp do_reduce(_, {:halt, acc}, _fun), do: {:halted, acc} + defp do_reduce(list, {:suspend, acc}, fun), do: {:suspended, acc, &do_reduce(list, &1, fun)} + defp do_reduce([], {:cont, acc}, _fun), do: {:done, acc} + defp do_reduce([h | t], {:cont, acc}, fun), do: do_reduce(t, fun.(h, acc), fun) +end From 34304e182911dc0f518a7731abf93bf4b309ea44 Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Thu, 16 Feb 2017 22:16:08 -0600 Subject: [PATCH 377/860] Fix invalid conditional in Protocol.hasImplementation --- lib/elixir_script.ex | 3 +-- src/javascript/lib/core/protocol.js | 40 +++++++++++++++++------------ 2 files changed, 24 insertions(+), 19 deletions(-) diff --git a/lib/elixir_script.ex b/lib/elixir_script.ex index ec987923..e2869449 100644 --- a/lib/elixir_script.ex +++ b/lib/elixir_script.ex @@ -132,7 +132,7 @@ defmodule ElixirScript do app_name = cond do !is_nil(built_opts[:app]) -> - opts[:app] + built_opts[:app] Code.ensure_loaded?(Mix) -> Mix.Project.config()[:app] true -> @@ -143,7 +143,6 @@ defmodule ElixirScript do end def compile_path(path, opts) do - opts = build_compiler_options(opts) deps = path diff --git a/src/javascript/lib/core/protocol.js b/src/javascript/lib/core/protocol.js index 488dee04..5eb4063f 100644 --- a/src/javascript/lib/core/protocol.js +++ b/src/javascript/lib/core/protocol.js @@ -1,34 +1,39 @@ -import Core from '../core'; +import Core from "../core"; //https://github.com/airportyh/protomorphism -class Protocol{ - constructor(spec){ +class Protocol { + constructor(spec) { this.registry = new Map(); this.fallback = null; - for (let funName in spec){ + for (let funName in spec) { this[funName] = createFun(funName).bind(this); } - function createFun(funName){ - + function createFun(funName) { return function(...args) { let thing = args[0]; let fun = null; - if(Number.isInteger(thing) && this.hasImplementation(Core.Integer)){ + if (Number.isInteger(thing) && this.hasImplementation(Core.Integer)) { fun = this.registry.get(Core.Integer)[funName]; - }else if(typeof thing === "number" && !Number.isInteger(thing) && this.hasImplementation(Core.Float)){ + } else if ( + typeof thing === "number" && + !Number.isInteger(thing) && + this.hasImplementation(Core.Float) + ) { fun = this.registry.get(Core.Float)[funName]; - }else if(typeof thing === "string" && this.hasImplementation(Core.BitString)){ + } else if ( + typeof thing === "string" && this.hasImplementation(Core.BitString) + ) { fun = this.registry.get(Core.BitString)[funName]; - }else if(this.hasImplementation(thing)){ + } else if (this.hasImplementation(thing)) { fun = this.registry.get(thing.constructor)[funName]; - }else if(this.fallback){ + } else if (this.fallback) { fun = this.fallback[funName]; } - if(fun != null){ + if (fun != null) { let retval = fun.apply(this, args); return retval; } @@ -38,16 +43,18 @@ class Protocol{ } } - implementation(type, implementation){ - if(type === null){ + implementation(type, implementation) { + if (type === null) { this.fallback = implementation; - }else{ + } else { this.registry.set(type, implementation); } } hasImplementation(thing) { - if (thing === Core.Integer || thing === Core.Float || Core.BitString){ + if ( + thing === Core.Integer || thing === Core.Float || thing === Core.BitString + ) { return this.registry.has(thing); } @@ -55,5 +62,4 @@ class Protocol{ } } - export default Protocol; From d0f403cf09bf9affd4bcb798d6280d28ae94755a Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Thu, 16 Feb 2017 22:43:54 -0600 Subject: [PATCH 378/860] Add umd version of bootstrap file --- lib/elixir_script.ex | 4 ++-- lib/elixir_script/passes/handle_output.ex | 2 +- package.json | 10 ++++++---- rollup.config.js | 14 +++++++------- 4 files changed, 16 insertions(+), 14 deletions(-) diff --git a/lib/elixir_script.ex b/lib/elixir_script.ex index e2869449..e36beb1a 100644 --- a/lib/elixir_script.ex +++ b/lib/elixir_script.ex @@ -222,8 +222,8 @@ defmodule ElixirScript do Copies the javascript that makes up the ElixirScript stdlib to the specified location """ - def copy_stdlib_to_destination(destination) do - Enum.each(Path.wildcard(Path.join([operating_path, "elixir", "*.js"])), fn(path) -> + def copy_stdlib_to_destination(module_format, destination) do + Enum.each(Path.wildcard(Path.join([operating_path, module_format, "elixir", "*.js"])), fn(path) -> base = Path.basename(path) File.mkdir_p!(Path.join([destination, "elixir"])) File.cp!(path, Path.join([destination, "elixir", base])) diff --git a/lib/elixir_script/passes/handle_output.ex b/lib/elixir_script/passes/handle_output.ex index 5f949193..229fabb6 100644 --- a/lib/elixir_script/passes/handle_output.ex +++ b/lib/elixir_script/passes/handle_output.ex @@ -40,7 +40,7 @@ defmodule ElixirScript.Passes.HandleOutput do defp out(compiler_output, %{output: output_path, core_path: _} = compiler_opts) do if Map.get(compiler_opts, :std_lib, false) == false do - ElixirScript.copy_stdlib_to_destination(output_path) + ElixirScript.copy_stdlib_to_destination("es", output_path) end compiler_output = remove_load_only(compiler_output) diff --git a/package.json b/package.json index e84e8d83..1fc20cd5 100644 --- a/package.json +++ b/package.json @@ -8,7 +8,9 @@ }, "scripts": { "lint": "eslint src/javascript/lib/**/*.js src/javascript/tests/**/*.js", - "build": "rollup -c rollup.config.js", + "build": "npm run build:es && npm run build:umd", + "build:es": "rollup -c rollup.config.js", + "build:umd": "rollup -c rollup.config.js -f umd -o priv/umd/elixir/Elixir.Bootstrap.js", "clean": "rm -rf priv", "test": "mocha src/javascript/tests --recursive --compilers js:babel-core/register" }, @@ -37,8 +39,8 @@ "gulp-babel": "^6.1.2", "gulp-sourcemaps": "^2.0.0-alpha", "mocha": "^2.4.5", - "rollup": "^0.28.0", - "rollup-plugin-babel": "^2.5.1", - "rollup-plugin-node-resolve": "^1.7.0" + "rollup": "^0.41.4", + "rollup-plugin-babel": "^2.7.1", + "rollup-plugin-node-resolve": "^2.0.0" } } \ No newline at end of file diff --git a/rollup.config.js b/rollup.config.js index e71e5b51..4bf6303d 100644 --- a/rollup.config.js +++ b/rollup.config.js @@ -1,12 +1,12 @@ -import { rollup } from 'rollup'; -import nodeResolve from 'rollup-plugin-node-resolve'; -import babel from 'rollup-plugin-babel'; +import nodeResolve from "rollup-plugin-node-resolve"; +import babel from "rollup-plugin-babel"; export default { - entry: 'src/javascript/elixir.js', - dest: 'priv/elixir/Elixir.Bootstrap.js', - sourceMap: 'inline', - format: 'es6', + entry: "src/javascript/elixir.js", + dest: "priv/es/elixir/Elixir.Bootstrap.js", + sourceMap: "inline", + format: "es", + moduleName: "Elixir.Bootstrap", plugins: [ nodeResolve({ jsnext: true }), babel({ From 7ad7ba0585d65bb626ac27f90fbe791094cc1886 Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Thu, 16 Feb 2017 22:49:33 -0600 Subject: [PATCH 379/860] Remove sleep_forever function from functions module --- src/javascript/lib/core/functions.js | 280 +++++++++++++-------------- 1 file changed, 137 insertions(+), 143 deletions(-) diff --git a/src/javascript/lib/core/functions.js b/src/javascript/lib/core/functions.js index f5228161..874e9af0 100644 --- a/src/javascript/lib/core/functions.js +++ b/src/javascript/lib/core/functions.js @@ -1,45 +1,50 @@ -import Protocol from './protocol'; -import Core from '../core'; +import Protocol from "./protocol"; +import Core from "../core"; -function call_property(item, property){ +function call_property(item, property) { let prop = null; - if(typeof item === "number" || typeof item === "symbol" || typeof item === "boolean" || typeof item === "string"){ - if(item[property] !== undefined){ + if ( + typeof item === "number" || + typeof item === "symbol" || + typeof item === "boolean" || + typeof item === "string" + ) { + if (item[property] !== undefined) { prop = property; - }else if(item[Symbol.for(property)] !== undefined){ + } else if (item[Symbol.for(property)] !== undefined) { prop = Symbol.for(property); } } else { - if(property in item){ + if (property in item) { prop = property; - }else if(Symbol.for(property) in item){ + } else if (Symbol.for(property) in item) { prop = Symbol.for(property); } } - if(prop === null){ - throw new Error(`Property ${ property } not found in ${ item }`); + if (prop === null) { + throw new Error(`Property ${property} not found in ${item}`); } - if(item[prop] instanceof Function){ + if (item[prop] instanceof Function) { return item[prop](); - }else{ + } else { return item[prop]; } } -function apply(...args){ - if(args.length === 2){ +function apply(...args) { + if (args.length === 2) { args[0].apply(null, args.slice(1)); - }else{ + } else { args[0][args[1]].apply(null, args.slice(2)); } } -function contains(left, right){ - for(let x of right){ - if(Core.Patterns.match_or_default(left, x) != null){ +function contains(left, right) { + for (let x of right) { + if (Core.Patterns.match_or_default(left, x) != null) { return true; } } @@ -47,36 +52,35 @@ function contains(left, right){ return false; } -function get_global(){ - if(typeof(self) !== "undefined"){ +function get_global() { + if (typeof self !== "undefined") { return self; - }else if(typeof(window) !== "undefined"){ + } else if (typeof window !== "undefined") { return window; - }else if(typeof(global) !== "undefined"){ + } else if (typeof global !== "undefined") { return global; } throw new Error("No global state found"); } -function defstruct(defaults){ +function defstruct(defaults) { return class { - constructor(update = {}){ + constructor(update = {}) { let the_values = Object.assign(defaults, update); Object.assign(this, the_values); } - static create(updates = {}){ + static create(updates = {}) { let x = new this(updates); return Object.freeze(x); } }; } - -function defexception(defaults){ +function defexception(defaults) { return class extends Error { - constructor(update = {}){ + constructor(update = {}) { let message = update.message || ""; super(message); @@ -89,108 +93,109 @@ function defexception(defaults){ Error.captureStackTrace(this, this.constructor.name); } - static create(updates = {}){ + static create(updates = {}) { let x = new this(updates); return Object.freeze(x); } }; } -function defprotocol(spec){ +function defprotocol(spec) { return new Protocol(spec); } -function defimpl(protocol, type, impl){ +function defimpl(protocol, type, impl) { protocol.implementation(type, impl); } -function get_object_keys(obj){ - return Object.keys(obj).concat(Object.getOwnPropertySymbols(obj)); +function get_object_keys(obj) { + return Object.keys(obj).concat(Object.getOwnPropertySymbols(obj)); } -function is_valid_character(codepoint){ - try{ +function is_valid_character(codepoint) { + try { return String.fromCodePoint(codepoint) != null; - }catch(e){ + } catch (e) { return false; } } //https://developer.mozilla.org/en-US/docs/Web/API/WindowBase64/Base64_encoding_and_decoding#Solution_2_%E2%80%93_rewrite_the_DOMs_atob()_and_btoa()_using_JavaScript's_TypedArrays_and_UTF-8 function b64EncodeUnicode(str) { - return btoa(encodeURIComponent(str).replace(/%([0-9A-F]{2})/g, function(match, p1) { - return String.fromCharCode('0x' + p1); - })); + return btoa( + encodeURIComponent(str).replace(/%([0-9A-F]{2})/g, function(match, p1) { + return String.fromCharCode("0x" + p1); + }) + ); } -function delete_property_from_map(map, property){ - let new_map = Object.assign(Object.create(map.constructor.prototype), map); - delete new_map[property]; +function delete_property_from_map(map, property) { + let new_map = Object.assign(Object.create(map.constructor.prototype), map); + delete new_map[property]; return Object.freeze(new_map); } -function class_to_obj(map){ - let new_map = Object.assign({}, map); +function class_to_obj(map) { + let new_map = Object.assign({}, map); return Object.freeze(new_map); } -function add_property_to_map(map, property, value){ +function add_property_to_map(map, property, value) { let new_map = Object.assign({}, map); new_map[property] = value; return Object.freeze(new_map); } +function update_map(map, property, value) { + if (property in get_object_keys(map)) { + return add_property_to_map(map, property, value); + } -function update_map(map, property, value){ - if(property in get_object_keys(map)){ - return add_property_to_map(map, property, value); - } - - throw "map does not have key"; + throw "map does not have key"; } -function bnot(expr){ +function bnot(expr) { return ~expr; } -function band(left, right){ +function band(left, right) { return left & right; } -function bor(left, right){ +function bor(left, right) { return left | right; } -function bsl(left, right){ +function bsl(left, right) { return left << right; } -function bsr(left, right){ +function bsr(left, right) { return left >> right; } -function bxor(left, right){ +function bxor(left, right) { return left ^ right; } -function zip(list_of_lists){ - if(list_of_lists.length === 0){ +function zip(list_of_lists) { + if (list_of_lists.length === 0) { return Object.freeze([]); } let new_value = []; let smallest_length = list_of_lists[0]; - for(let x of list_of_lists){ - if(x.length < smallest_length){ + for (let x of list_of_lists) { + if (x.length < smallest_length) { smallest_length = x.length; } } - for(let i = 0; i < smallest_length; i++){ + for (let i = 0; i < smallest_length; i++) { let current_value = []; - for(let j = 0; j < list_of_lists.length; j++){ + for (let j = 0; j < list_of_lists.length; j++) { current_value.push(list_of_lists[j][i]); } @@ -201,52 +206,50 @@ function zip(list_of_lists){ } function can_decode64(data) { - try{ + try { atob(data); return true; - }catch(e){ + } catch (e) { return false; } } -function remove_from_list(list, element){ - let found = false; +function remove_from_list(list, element) { + let found = false; - return list.filter((elem) => { - if(!found && elem === element){ - found = true; - return false; - } + return list.filter(elem => { + if (!found && elem === element) { + found = true; + return false; + } - return true; - }); + return true; + }); } -function foldl(fun, acc, list){ - let acc1 = acc; +function foldl(fun, acc, list) { + let acc1 = acc; - for(const el of list){ - acc1 = fun(el, acc1); - } + for (const el of list) { + acc1 = fun(el, acc1); + } - return acc1; + return acc1; } +function foldr(fun, acc, list) { + let acc1 = acc; -function foldr(fun, acc, list){ - let acc1 = acc; - - for(let i = list.length - 1; i >= 0; i--){ - acc1 = fun(list[i], acc1); - } + for (let i = list.length - 1; i >= 0; i--) { + acc1 = fun(list[i], acc1); + } - return acc1; + return acc1; } -function keyfind(key, n, tuplelist){ - - for(let i = tuplelist.length - 1; i >= 0; i--){ - if(tuplelist[i].get(n) === key){ +function keyfind(key, n, tuplelist) { + for (let i = tuplelist.length - 1; i >= 0; i--) { + if (tuplelist[i].get(n) === key) { return tuplelist[i]; } } @@ -254,30 +257,29 @@ function keyfind(key, n, tuplelist){ return false; } -function keydelete(key, n, tuplelist){ - - for(let i = tuplelist.length - 1; i >= 0; i--){ - if(tuplelist[i].get(n) === key){ - return tuplelist.concat([]).splice(i, 1); - } +function keydelete(key, n, tuplelist) { + for (let i = tuplelist.length - 1; i >= 0; i--) { + if (tuplelist[i].get(n) === key) { + return tuplelist.concat([]).splice(i, 1); } + } - return tuplelist; + return tuplelist; } -function keystore(key, n, list, newtuple){ - for(let i = list.length - 1; i >= 0; i--){ - if(list[i].get(n) === key){ - return list.concat([]).splice(i, 1, newtuple); - } +function keystore(key, n, list, newtuple) { + for (let i = list.length - 1; i >= 0; i--) { + if (list[i].get(n) === key) { + return list.concat([]).splice(i, 1, newtuple); } + } return list.concat([]).push(newtuple); } -function keymember(key, n, list){ - for(let i = list.length - 1; i >= 0; i--){ - if(list[i].get(n) === key){ +function keymember(key, n, list) { + for (let i = list.length - 1; i >= 0; i--) { + if (list[i].get(n) === key) { return true; } } @@ -285,8 +287,8 @@ function keymember(key, n, list){ return false; } -function keytake(key, n, list){ - if(!keymember(key, n, list)){ +function keytake(key, n, list) { + if (!keymember(key, n, list)) { return false; } @@ -295,10 +297,9 @@ function keytake(key, n, list){ return new Tuple(tuple.get(n), tuple, keydelete(key, n, list)); } -function keyreplace(key, n, list, newtuple){ - - for(let i = tuplelist.length - 1; i >= 0; i--){ - if(tuplelist[i].get(n) === key){ +function keyreplace(key, n, list, newtuple) { + for (let i = tuplelist.length - 1; i >= 0; i--) { + if (tuplelist[i].get(n) === key) { return tuplelist.concat([]).splice(i, 1, newtuple); } } @@ -306,26 +307,25 @@ function keyreplace(key, n, list, newtuple){ return tuplelist; } - -function reverse(list){ - return list.concat([]).reverse(); +function reverse(list) { + return list.concat([]).reverse(); } -function maps_find(key, map){ - if(key in get_object_keys(map)){ - return new Core.Tuple(Symbol.for("ok"), map[key]); - }else{ - return Symbol.for("error"); - } +function maps_find(key, map) { + if (key in get_object_keys(map)) { + return new Core.Tuple(Symbol.for("ok"), map[key]); + } else { + return Symbol.for("error"); + } } function flatten(list, tail = []) { let new_list = []; - for(let e of list){ - if(Array.isArray(e)){ + for (let e of list) { + if (Array.isArray(e)) { new_list = new_list.concat(flatten(e)); - }else{ + } else { new_list.push(e); } } @@ -333,38 +333,37 @@ function flatten(list, tail = []) { return Object.freeze(new_list.concat(tail)); } -function duplicate(n, elem){ +function duplicate(n, elem) { let list = []; - for(let i = 0; i < n; i++){ + for (let i = 0; i < n; i++) { list.push(elem); } return Object.freeze(list); } -function mapfoldl(fun, acc, list){ +function mapfoldl(fun, acc, list) { let newlist = []; - for(let x of list){ + for (let x of list) { let tup = fun(x, acc); newlist.push(tup.get(0)); acc = tup.get(1); } - return new Core.Tuple(Object.freeze(newlist), acc); } -function filtermap(fun, list){ +function filtermap(fun, list) { let newlist = []; - for(x of list){ + for (x of list) { let result = fun(x); - if(result === true){ + if (result === true) { newlist.push(x); - }else if(result instanceof Core.Tuple){ + } else if (result instanceof Core.Tuple) { newlist.push(result.get(1)); } } @@ -372,30 +371,26 @@ function filtermap(fun, list){ return Object.freeze(newlist); } -function maps_fold(fun, acc, map){ +function maps_fold(fun, acc, map) { let acc1 = acc; - for(let k of get_object_keys(map)){ + for (let k of get_object_keys(map)) { acc1 = fun(k, map[k], acc1); } return acc1; } -function maps_from_list(list){ +function maps_from_list(list) { let m = {}; - for(x of list){ + for (x of list) { m[x.get(0)] = x.get(1); } return Object.freeze(m); } -function* sleep_forever(){ - yield* Core.processes.sleep(Symbol("infinity")); -} - export default { call_property, apply, @@ -434,6 +429,5 @@ export default { duplicate, mapfoldl, filtermap, - maps_fold, - sleep_forever + maps_fold }; From 24cd7df337196e18dd4a0d0f4ae144623bc52bb9 Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Thu, 16 Feb 2017 23:11:11 -0600 Subject: [PATCH 380/860] Fixed js linting issues --- .eslintrc | 26 ----- .eslintrc.js | 16 +++ .gitignore | 1 + package.json | 5 +- src/javascript/lib/core/functions.js | 122 +++++++++----------- src/javascript/lib/core/protocol.js | 18 +-- src/javascript/lib/core/special_forms.js | 58 +++++----- src/javascript/lib/core/store.js | 31 +++-- src/javascript/tests/core/functions.spec.js | 26 ++--- 9 files changed, 138 insertions(+), 165 deletions(-) delete mode 100644 .eslintrc create mode 100644 .eslintrc.js diff --git a/.eslintrc b/.eslintrc deleted file mode 100644 index 3221dd47..00000000 --- a/.eslintrc +++ /dev/null @@ -1,26 +0,0 @@ -{ - "rules": { - "indent": [ - 2, - 4 - ], - "quotes": [ - 2, - "single" - ], - "linebreak-style": [ - 2, - "unix" - ], - "semi": [ - 2, - "always" - ] - }, - "env": { - "es6": true, - "browser": true, - "node": true - }, - "extends": "eslint:recommended" -} \ No newline at end of file diff --git a/.eslintrc.js b/.eslintrc.js new file mode 100644 index 00000000..cc2122f0 --- /dev/null +++ b/.eslintrc.js @@ -0,0 +1,16 @@ +module.exports = { + rules: { + camelcase: "off", + "no-bitwise": "off", + "no-plusplus": "off", + "no-restricted-syntax": "off", + "no-underscore-dangle": "off" + }, + extends: "airbnb-base", + plugins: ["import"], + env: { + browser: true, + node: true, + mocha: true + } +}; diff --git a/.gitignore b/.gitignore index e9c2abd6..e0db4469 100644 --- a/.gitignore +++ b/.gitignore @@ -18,3 +18,4 @@ test/std_lib_compile_test.exs src/elixirscript priv/**/*.js stdlib_state.bin +*.log diff --git a/package.json b/package.json index 1fc20cd5..c6d5e7af 100644 --- a/package.json +++ b/package.json @@ -8,6 +8,7 @@ }, "scripts": { "lint": "eslint src/javascript/lib/**/*.js src/javascript/tests/**/*.js", + "lint:fix": "eslint src/javascript/lib/**/*.js src/javascript/tests/**/*.js --fix", "build": "npm run build:es && npm run build:umd", "build:es": "rollup -c rollup.config.js", "build:umd": "rollup -c rollup.config.js -f umd -o priv/umd/elixir/Elixir.Bootstrap.js", @@ -34,7 +35,9 @@ "babel-preset-react": "^6.5.0", "babel-preset-stage-0": "^6.5.0", "chai": "^3.5.0", - "eslint": "^2.9.0", + "eslint": "^3.15.0", + "eslint-config-airbnb-base": "^11.1.0", + "eslint-plugin-import": "^2.2.0", "gulp": "^3.9.1", "gulp-babel": "^6.1.2", "gulp-sourcemaps": "^2.0.0-alpha", diff --git a/src/javascript/lib/core/functions.js b/src/javascript/lib/core/functions.js index 874e9af0..b747a9f6 100644 --- a/src/javascript/lib/core/functions.js +++ b/src/javascript/lib/core/functions.js @@ -1,26 +1,24 @@ -import Protocol from "./protocol"; -import Core from "../core"; +import Protocol from './protocol'; +import Core from '../core'; function call_property(item, property) { let prop = null; if ( - typeof item === "number" || - typeof item === "symbol" || - typeof item === "boolean" || - typeof item === "string" + typeof item === 'number' || + typeof item === 'symbol' || + typeof item === 'boolean' || + typeof item === 'string' ) { if (item[property] !== undefined) { prop = property; } else if (item[Symbol.for(property)] !== undefined) { prop = Symbol.for(property); } - } else { - if (property in item) { - prop = property; - } else if (Symbol.for(property) in item) { - prop = Symbol.for(property); - } + } else if (property in item) { + prop = property; + } else if (Symbol.for(property) in item) { + prop = Symbol.for(property); } if (prop === null) { @@ -29,9 +27,8 @@ function call_property(item, property) { if (item[prop] instanceof Function) { return item[prop](); - } else { - return item[prop]; } + return item[prop]; } function apply(...args) { @@ -43,7 +40,7 @@ function apply(...args) { } function contains(left, right) { - for (let x of right) { + for (const x of right) { if (Core.Patterns.match_or_default(left, x) != null) { return true; } @@ -53,26 +50,26 @@ function contains(left, right) { } function get_global() { - if (typeof self !== "undefined") { + if (typeof self !== 'undefined') { return self; - } else if (typeof window !== "undefined") { + } else if (typeof window !== 'undefined') { return window; - } else if (typeof global !== "undefined") { + } else if (typeof global !== 'undefined') { return global; } - throw new Error("No global state found"); + throw new Error('No global state found'); } function defstruct(defaults) { return class { constructor(update = {}) { - let the_values = Object.assign(defaults, update); + const the_values = Object.assign(defaults, update); Object.assign(this, the_values); } static create(updates = {}) { - let x = new this(updates); + const x = new this(updates); return Object.freeze(x); } }; @@ -81,20 +78,20 @@ function defstruct(defaults) { function defexception(defaults) { return class extends Error { constructor(update = {}) { - let message = update.message || ""; + const message = update.message || ''; super(message); - let the_values = Object.assign(defaults, update); + const the_values = Object.assign(defaults, update); Object.assign(this, the_values); this.name = this.constructor.name; this.message = message; - this[Symbol.for("__exception__")] = true; + this[Symbol.for('__exception__')] = true; Error.captureStackTrace(this, this.constructor.name); } static create(updates = {}) { - let x = new this(updates); + const x = new this(updates); return Object.freeze(x); } }; @@ -120,29 +117,28 @@ function is_valid_character(codepoint) { } } -//https://developer.mozilla.org/en-US/docs/Web/API/WindowBase64/Base64_encoding_and_decoding#Solution_2_%E2%80%93_rewrite_the_DOMs_atob()_and_btoa()_using_JavaScript's_TypedArrays_and_UTF-8 +// https://developer.mozilla.org/en-US/docs/Web/API/WindowBase64/Base64_encoding_and_decoding#Solution_2_%E2%80%93_rewrite_the_DOMs_atob()_and_btoa()_using_JavaScript's_TypedArrays_and_UTF-8 function b64EncodeUnicode(str) { return btoa( - encodeURIComponent(str).replace(/%([0-9A-F]{2})/g, function(match, p1) { - return String.fromCharCode("0x" + p1); - }) + encodeURIComponent(str).replace(/%([0-9A-F]{2})/g, (match, p1) => + String.fromCharCode(`0x${p1}`)), ); } function delete_property_from_map(map, property) { - let new_map = Object.assign(Object.create(map.constructor.prototype), map); + const new_map = Object.assign(Object.create(map.constructor.prototype), map); delete new_map[property]; return Object.freeze(new_map); } function class_to_obj(map) { - let new_map = Object.assign({}, map); + const new_map = Object.assign({}, map); return Object.freeze(new_map); } function add_property_to_map(map, property, value) { - let new_map = Object.assign({}, map); + const new_map = Object.assign({}, map); new_map[property] = value; return Object.freeze(new_map); } @@ -152,7 +148,7 @@ function update_map(map, property, value) { return add_property_to_map(map, property, value); } - throw "map does not have key"; + throw 'map does not have key'; } function bnot(expr) { @@ -184,17 +180,17 @@ function zip(list_of_lists) { return Object.freeze([]); } - let new_value = []; + const new_value = []; let smallest_length = list_of_lists[0]; - for (let x of list_of_lists) { + for (const x of list_of_lists) { if (x.length < smallest_length) { smallest_length = x.length; } } for (let i = 0; i < smallest_length; i++) { - let current_value = []; + const current_value = []; for (let j = 0; j < list_of_lists.length; j++) { current_value.push(list_of_lists[j][i]); } @@ -217,7 +213,7 @@ function can_decode64(data) { function remove_from_list(list, element) { let found = false; - return list.filter(elem => { + return list.filter((elem) => { if (!found && elem === element) { found = true; return false; @@ -292,19 +288,19 @@ function keytake(key, n, list) { return false; } - let tuple = keyfind(key, n, list); + const tuple = keyfind(key, n, list); - return new Tuple(tuple.get(n), tuple, keydelete(key, n, list)); + return new Core.Tuple(tuple.get(n), tuple, keydelete(key, n, list)); } function keyreplace(key, n, list, newtuple) { - for (let i = tuplelist.length - 1; i >= 0; i--) { - if (tuplelist[i].get(n) === key) { - return tuplelist.concat([]).splice(i, 1, newtuple); + for (let i = list.length - 1; i >= 0; i--) { + if (list[i].get(n) === key) { + return list.concat([]).splice(i, 1, newtuple); } } - return tuplelist; + return list; } function reverse(list) { @@ -313,16 +309,15 @@ function reverse(list) { function maps_find(key, map) { if (key in get_object_keys(map)) { - return new Core.Tuple(Symbol.for("ok"), map[key]); - } else { - return Symbol.for("error"); + return new Core.Tuple(Symbol.for('ok'), map[key]); } + return Symbol.for('error'); } function flatten(list, tail = []) { let new_list = []; - for (let e of list) { + for (const e of list) { if (Array.isArray(e)) { new_list = new_list.concat(flatten(e)); } else { @@ -334,7 +329,7 @@ function flatten(list, tail = []) { } function duplicate(n, elem) { - let list = []; + const list = []; for (let i = 0; i < n; i++) { list.push(elem); @@ -344,22 +339,23 @@ function duplicate(n, elem) { } function mapfoldl(fun, acc, list) { - let newlist = []; + const newlist = []; + let new_acc = acc; - for (let x of list) { - let tup = fun(x, acc); + for (const x of list) { + const tup = fun(x, new_acc); newlist.push(tup.get(0)); - acc = tup.get(1); + new_acc = tup.get(1); } - return new Core.Tuple(Object.freeze(newlist), acc); + return new Core.Tuple(Object.freeze(newlist), new_acc); } function filtermap(fun, list) { - let newlist = []; + const newlist = []; - for (x of list) { - let result = fun(x); + for (const x of list) { + const result = fun(x); if (result === true) { newlist.push(x); @@ -374,23 +370,13 @@ function filtermap(fun, list) { function maps_fold(fun, acc, map) { let acc1 = acc; - for (let k of get_object_keys(map)) { + for (const k of get_object_keys(map)) { acc1 = fun(k, map[k], acc1); } return acc1; } -function maps_from_list(list) { - let m = {}; - - for (x of list) { - m[x.get(0)] = x.get(1); - } - - return Object.freeze(m); -} - export default { call_property, apply, @@ -429,5 +415,5 @@ export default { duplicate, mapfoldl, filtermap, - maps_fold + maps_fold, }; diff --git a/src/javascript/lib/core/protocol.js b/src/javascript/lib/core/protocol.js index 5eb4063f..936fc59e 100644 --- a/src/javascript/lib/core/protocol.js +++ b/src/javascript/lib/core/protocol.js @@ -1,30 +1,30 @@ -import Core from "../core"; +import Core from '../core'; -//https://github.com/airportyh/protomorphism +// https://github.com/airportyh/protomorphism class Protocol { constructor(spec) { this.registry = new Map(); this.fallback = null; - for (let funName in spec) { + for (const funName in spec) { this[funName] = createFun(funName).bind(this); } function createFun(funName) { - return function(...args) { - let thing = args[0]; + return function (...args) { + const thing = args[0]; let fun = null; if (Number.isInteger(thing) && this.hasImplementation(Core.Integer)) { fun = this.registry.get(Core.Integer)[funName]; } else if ( - typeof thing === "number" && + typeof thing === 'number' && !Number.isInteger(thing) && this.hasImplementation(Core.Float) ) { fun = this.registry.get(Core.Float)[funName]; } else if ( - typeof thing === "string" && this.hasImplementation(Core.BitString) + typeof thing === 'string' && this.hasImplementation(Core.BitString) ) { fun = this.registry.get(Core.BitString)[funName]; } else if (this.hasImplementation(thing)) { @@ -34,11 +34,11 @@ class Protocol { } if (fun != null) { - let retval = fun.apply(this, args); + const retval = fun.apply(this, args); return retval; } - throw new Error("No implementation found for " + thing); + throw new Error(`No implementation found for ${thing}`); }; } } diff --git a/src/javascript/lib/core/special_forms.js b/src/javascript/lib/core/special_forms.js index c5854097..faac7e94 100644 --- a/src/javascript/lib/core/special_forms.js +++ b/src/javascript/lib/core/special_forms.js @@ -1,11 +1,11 @@ -import Core from "../core"; +import Core from '../core'; function _case(condition, clauses) { return Core.Patterns.defmatch(...clauses)(condition); } function cond(clauses) { - for (let clause of clauses) { + for (const clause of clauses) { if (clause[0]) { return clause[1](); } @@ -16,7 +16,7 @@ function cond(clauses) { function map_update(map, values) { return Object.freeze( - Object.assign(Object.create(map.constructor.prototype), map, values) + Object.assign(Object.create(map.constructor.prototype), map, values), ); } @@ -25,39 +25,37 @@ function _for(expression, generators, collectable_protocol, into = []) { const generatedValues = run_list_generators(generators.pop()(), generators); - for (let value of generatedValues) { + for (const value of generatedValues) { if (expression.guard.apply(this, value)) { result = fun(result, new Core.Tuple( - Symbol.for("cont"), - expression.fn.apply(this, value) + Symbol.for('cont'), + expression.fn.apply(this, value), )); } } - return fun(result, Symbol.for("done")); + return fun(result, Symbol.for('done')); } function run_list_generators(generator, generators) { if (generators.length == 0) { - return generator.map(x => { + return generator.map((x) => { if (Array.isArray(x)) { return x; - } else { - return [x]; } + return [x]; }); - } else { - const list = generators.pop(); + } + const list = generators.pop(); - let next_gen = []; - for (let j of list()) { - for (let i of generator) { - next_gen.push([j].concat(i)); - } + const next_gen = []; + for (const j of list()) { + for (const i of generator) { + next_gen.push([j].concat(i)); } - - return run_list_generators(next_gen, generators); } + + return run_list_generators(next_gen, generators); } function _try( @@ -65,7 +63,7 @@ function _try( rescue_function, catch_fun, else_function, - after_function + after_function, ) { let result = null; @@ -108,7 +106,7 @@ function _try( return else_function(result); } catch (ex) { if (ex instanceof Core.Patterns.MatchError) { - throw new Error("No Match Found in Else"); + throw new Error('No Match Found in Else'); } throw ex; @@ -123,31 +121,29 @@ function _with(...args) { let successFunction = null; let elseFunction = null; - if (typeof args[args.length - 2] === "function") { + if (typeof args[args.length - 2] === 'function') { [successFunction, elseFunction] = args.splice(-2); } else { successFunction = args.pop(); } for (let i = 0; i < args.length; i++) { - let [pattern, func] = args[i]; + const [pattern, func] = args[i]; - let result = func.apply(null, argsToPass); + const result = func(...argsToPass); - let patternResult = Core.Patterns.match_or_default(pattern, result); + const patternResult = Core.Patterns.match_or_default(pattern, result); if (patternResult == null) { if (elseFunction) { return elseFunction.call(null, result); - } else { - return result; } - } else { - argsToPass = argsToPass.concat(patternResult); + return result; } + argsToPass = argsToPass.concat(patternResult); } - return successFunction.apply(null, argsToPass); + return successFunction(...argsToPass); } export default { @@ -156,5 +152,5 @@ export default { map_update, _for, _try, - _with + _with, }; diff --git a/src/javascript/lib/core/store.js b/src/javascript/lib/core/store.js index 202946c4..bf8aa04a 100644 --- a/src/javascript/lib/core/store.js +++ b/src/javascript/lib/core/store.js @@ -1,41 +1,40 @@ -let store = new Map(); -let names = new Map(); +const store = new Map(); +const names = new Map(); -function get_key(key){ +function get_key(key) { let real_key = key; - if(names.has(key)){ + if (names.has(key)) { real_key = names.get(key); } - if(store.has(real_key)){ - return real_key + if (store.has(real_key)) { + return real_key; } return new Error('Key Not Found'); } -function create(key, value, name = null){ - - if(name != null){ +function create(key, value, name = null) { + if (name != null) { names.set(name, key); } store.set(key, value); } -function update(key, value){ - let real_key = get_key(key); +function update(key, value) { + const real_key = get_key(key); store.set(real_key, value); } -function read(key){ - let real_key = get_key(key); +function read(key) { + const real_key = get_key(key); return store.get(real_key); } -function remove(key){ - let real_key = get_key(key); +function remove(key) { + const real_key = get_key(key); return store.delete(real_key); } @@ -43,5 +42,5 @@ export default { create, read, update, - remove + remove, }; diff --git a/src/javascript/tests/core/functions.spec.js b/src/javascript/tests/core/functions.spec.js index aef7192d..698d8c3c 100644 --- a/src/javascript/tests/core/functions.spec.js +++ b/src/javascript/tests/core/functions.spec.js @@ -1,20 +1,18 @@ -import Core from "../../lib/core"; +import Core from '../../lib/core'; const Functions = Core.Functions; import chai from 'chai'; -var expect = chai.expect; +const expect = chai.expect; -describe('Functions', function(){ - - it('call_property', function(){ - expect(Functions.call_property(1, "toString")).to.equal("1"); - expect(Functions.call_property([], "toString")).to.equal(""); - expect(Functions.call_property([], "length")).to.equal(0); - expect(Functions.call_property("", "toString")).to.equal(""); - expect(Functions.call_property("", "length")).to.equal(0); - expect(Functions.call_property(Symbol("test"), "toString")).to.equal("Symbol(test)"); - expect(Functions.call_property({completed: false}, "completed")).to.equal(false); - expect(Functions.call_property({id: 0}, "id")).to.equal(0); +describe('Functions', () => { + it('call_property', () => { + expect(Functions.call_property(1, 'toString')).to.equal('1'); + expect(Functions.call_property([], 'toString')).to.equal(''); + expect(Functions.call_property([], 'length')).to.equal(0); + expect(Functions.call_property('', 'toString')).to.equal(''); + expect(Functions.call_property('', 'length')).to.equal(0); + expect(Functions.call_property(Symbol('test'), 'toString')).to.equal('Symbol(test)'); + expect(Functions.call_property({ completed: false }, 'completed')).to.equal(false); + expect(Functions.call_property({ id: 0 }, 'id')).to.equal(0); }); - }); From 281640fa0c065e0895b395f88860f50c0a13390a Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Fri, 17 Feb 2017 10:54:41 -0600 Subject: [PATCH 381/860] Add umd module rename ES6 module to ES --- lib/elixir_script.ex | 16 +++- lib/elixir_script/module_systems.ex | 23 ----- lib/elixir_script/module_systems/es.ex | 83 +++++++++++++++++++ lib/elixir_script/module_systems/es6.ex | 43 ---------- lib/elixir_script/module_systems/umd.ex | 2 + .../passes/consolidate_protocols.ex | 21 +++-- lib/elixir_script/passes/java_script_ast.ex | 2 +- .../translator/kernel/defmodule.ex | 30 +------ .../translator/kernel/defprotocol.ex | 62 ++------------ lib/elixir_script/translator/kernel/js.ex | 11 ++- lib/elixir_script/translator/lexical_scope.ex | 20 +++-- lib/elixir_script/translator/state.ex | 24 +++++- mix.lock | 6 +- test/test_helper.exs | 7 +- test/translator/pattern_matching_test.exs | 2 +- test/translator/protocol_test.exs | 9 +- 16 files changed, 180 insertions(+), 181 deletions(-) delete mode 100644 lib/elixir_script/module_systems.ex create mode 100644 lib/elixir_script/module_systems/es.ex delete mode 100644 lib/elixir_script/module_systems/es6.ex create mode 100644 lib/elixir_script/module_systems/umd.ex diff --git a/lib/elixir_script.ex b/lib/elixir_script.ex index e36beb1a..31e7e82a 100644 --- a/lib/elixir_script.ex +++ b/lib/elixir_script.ex @@ -214,8 +214,22 @@ defmodule ElixirScript do |> Map.put(:full_build, false) |> Map.put(:output, nil) |> Map.put(:app, :app) + |> Map.put(:format, :es) - Map.merge(default_options, opts) + options = Map.merge(default_options, opts) + Map.put(options, :module_formatter, get_module_formatter(options[:format])) + end + + defp get_module_formatter(:umd) do + ElixirScript.ModuleSystems.UMD + end + + defp get_module_formatter(:common) do + ElixirScript.ModuleSystems.Common + end + + defp get_module_formatter(_) do + ElixirScript.ModuleSystems.ES end @doc """ diff --git a/lib/elixir_script/module_systems.ex b/lib/elixir_script/module_systems.ex deleted file mode 100644 index c25968f9..00000000 --- a/lib/elixir_script/module_systems.ex +++ /dev/null @@ -1,23 +0,0 @@ -defmodule ElixirScript.ModuleSystems do - @moduledoc false - defp module_system() do - ElixirScript.ModuleSystems.ES6 - end - - def import_namespace_module(module_name, from, env) do - module_system.import_namespace_module(module_name, from, env) - end - - def import_module(module_name, from, env) do - module_system.import_module(module_name, from, env) - end - - def import_module(import_name, from) do - module_system.import_module(import_name, from) - end - - def export_module(exported_object) do - module_system.export_module(exported_object) - end - -end diff --git a/lib/elixir_script/module_systems/es.ex b/lib/elixir_script/module_systems/es.ex new file mode 100644 index 00000000..aa088e0c --- /dev/null +++ b/lib/elixir_script/module_systems/es.ex @@ -0,0 +1,83 @@ +defmodule ElixirScript.ModuleSystems.ES do + @moduledoc false + alias ESTree.Tools.Builder, as: JS + alias ElixirScript.Translator + alias ElixirScript.Translator.State + alias ElixirScript.Translator.Utils + + def build(body, exports, env) do + js_module_refs = State.get_javascript_module_references(env.state, env.module) + std_import = make_std_lib_import(env) + module_refs = State.get_module_references(env.state, env.module) -- [env.module] + |> module_imports_to_js_imports(env) + app_name = State.get_module(env.state, env.module).app + + imports = js_module_refs ++ std_import + |> Enum.map(fn + {module, path, true} -> import_module(module, path, env) + {module, path, false} -> import_namespace_module(module, path, env) + end) + + imports = Enum.uniq(imports ++ module_refs) + + export = export_module(exports) + imports ++ body ++ [export] + end + + defp module_imports_to_js_imports(module_refs, env) do + Enum.map(module_refs, fn(x) -> + module_name = Utils.name_to_js_name(x) + app_name = State.get_module(env.state, x).app + path = Utils.make_local_file_path(app_name, Utils.name_to_js_file_name(x), env) + import_module(module_name, path) + end) + end + + defp make_std_lib_import(env) do + compiler_opts = State.get(env.state).compiler_opts + case compiler_opts.import_standard_libs do + true -> + [{:Elixir, Utils.make_local_file_path(:elixir, compiler_opts.core_path, env), true }] + false -> + [] + end + end + + def import_namespace_module(module_name, from, env) do + import_specifier = JS.import_namespace_specifier( + Translator.translate!(module_name, env), + Translator.translate!(module_name, env) + ) + + do_import_module([import_specifier], from) + end + + def import_module(module_name, from, env) do + import_specifier = JS.import_default_specifier( + Translator.translate!(module_name, env), + Translator.translate!(module_name, env) + ) + + do_import_module([import_specifier], from) + end + + def import_module(import_name, from) do + import_specifier = JS.import_default_specifier( + JS.identifier(import_name) + ) + + do_import_module([import_specifier], from) + end + + defp do_import_module(import_specifiers, file_path) do + JS.import_declaration( + import_specifiers, + JS.literal(file_path) + ) + end + + def export_module(exported_object) do + JS.export_default_declaration(exported_object) + end + +end diff --git a/lib/elixir_script/module_systems/es6.ex b/lib/elixir_script/module_systems/es6.ex deleted file mode 100644 index 1398d1a5..00000000 --- a/lib/elixir_script/module_systems/es6.ex +++ /dev/null @@ -1,43 +0,0 @@ -defmodule ElixirScript.ModuleSystems.ES6 do - @moduledoc false - alias ESTree.Tools.Builder, as: JS - alias ElixirScript.Translator - - def import_namespace_module(module_name, from, env) do - import_specifier = JS.import_namespace_specifier( - Translator.translate!(module_name, env), - Translator.translate!(module_name, env) - ) - - do_import_module([import_specifier], from) - end - - def import_module(module_name, from, env) do - import_specifier = JS.import_default_specifier( - Translator.translate!(module_name, env), - Translator.translate!(module_name, env) - ) - - do_import_module([import_specifier], from) - end - - def import_module(import_name, from) do - import_specifier = JS.import_default_specifier( - JS.identifier(import_name) - ) - - do_import_module([import_specifier], from) - end - - defp do_import_module(import_specifiers, file_path) do - JS.import_declaration( - import_specifiers, - JS.literal(file_path) - ) - end - - def export_module(exported_object) do - JS.export_default_declaration(exported_object) - end - -end diff --git a/lib/elixir_script/module_systems/umd.ex b/lib/elixir_script/module_systems/umd.ex new file mode 100644 index 00000000..218ea4a3 --- /dev/null +++ b/lib/elixir_script/module_systems/umd.ex @@ -0,0 +1,2 @@ +defmodule ElixirScript.ModuleSystems.UMD do +end \ No newline at end of file diff --git a/lib/elixir_script/passes/consolidate_protocols.ex b/lib/elixir_script/passes/consolidate_protocols.ex index 81bc70b9..8ebe2a5b 100644 --- a/lib/elixir_script/passes/consolidate_protocols.ex +++ b/lib/elixir_script/passes/consolidate_protocols.ex @@ -2,7 +2,6 @@ defmodule ElixirScript.Passes.ConsolidateProtocols do @moduledoc false alias ESTree.Tools.Builder, as: JS alias ElixirScript.Translator.Utils - alias ElixirScript.ModuleSystems alias ElixirScript.Translator.State require Logger @@ -55,8 +54,6 @@ defmodule ElixirScript.Passes.ConsolidateProtocols do end defp make_defimpl(name, { _, protocol }, implementations, compiler_opts) do - imports = [ModuleSystems.import_module(:Elixir, Utils.make_local_file_path(:elixir, compiler_opts.core_path, compiler_opts.root, nil))] - declarator = JS.variable_declarator( JS.identifier("impls"), JS.array_expression([]) @@ -70,22 +67,30 @@ defmodule ElixirScript.Passes.ConsolidateProtocols do app_name = protocol.app - body = Enum.flat_map(implementations, fn({_, impl_data}) -> + imports = [compiler_opts.module_formatter.import_module(:Elixir, Utils.make_local_file_path(:elixir, compiler_opts.core_path, compiler_opts.root, nil))] + + defimpl_imports = Enum.map(implementations, fn({_, impl_data}) -> x = Atom.to_string(Utils.quoted_to_name(impl_data.for)) x = String.to_atom(protocol_name <> ".DefImpl." <> x) name = Utils.name_to_js_name(x) - imports = ModuleSystems.import_module(name, Utils.make_local_file_path(impl_data.app, Utils.name_to_js_file_name(x), compiler_opts.root, nil)) - call = JS.call_expression( + compiler_opts.module_formatter.import_module(name, Utils.make_local_file_path(impl_data.app, Utils.name_to_js_file_name(x), compiler_opts.root, nil)) + end) + + body = Enum.map(implementations, fn({_, impl_data}) -> + x = Atom.to_string(Utils.quoted_to_name(impl_data.for)) + x = String.to_atom(protocol_name <> ".DefImpl." <> x) + name = Utils.name_to_js_name(x) + JS.call_expression( JS.member_expression( JS.identifier("impls"), JS.identifier("push") ), [JS.identifier(name)] ) - - [imports, call] end) + imports = imports ++ defimpl_imports + module_name = String.to_atom(protocol_name <> ".DefImpl") module_data = %{ module: String.to_atom(protocol_name <> ".DefImpl"), diff --git a/lib/elixir_script/passes/java_script_ast.ex b/lib/elixir_script/passes/java_script_ast.ex index 152085a0..3b31088f 100644 --- a/lib/elixir_script/passes/java_script_ast.ex +++ b/lib/elixir_script/passes/java_script_ast.ex @@ -36,7 +36,7 @@ defmodule ElixirScript.Passes.JavaScriptAST do defp compile(module_data, opts, state) do - env = ElixirScript.Translator.LexicalScope.module_scope(module_data.name, Utils.name_to_js_file_name(module_data.name) <> ".js", opts.env, state) + env = ElixirScript.Translator.LexicalScope.module_scope(module_data.name, Utils.name_to_js_file_name(module_data.name) <> ".js", opts.env, state, opts) module = case module_data.type do :module -> diff --git a/lib/elixir_script/translator/kernel/defmodule.ex b/lib/elixir_script/translator/kernel/defmodule.ex index 1eb6d767..72e2ce80 100644 --- a/lib/elixir_script/translator/kernel/defmodule.ex +++ b/lib/elixir_script/translator/kernel/defmodule.ex @@ -6,7 +6,6 @@ defmodule ElixirScript.Translator.Defmodule do alias ElixirScript.Translator.Utils alias ElixirScript.Translator.Group alias ElixirScript.Translator.Def - alias ElixirScript.ModuleSystems alias ElixirScript.Translator.Identifier def make_module(ElixirScript.Temp, body, env) do @@ -25,15 +24,10 @@ defmodule ElixirScript.Translator.Defmodule do { exported_functions, private_functions } = process_functions(functions, env) - module_refs = ElixirScript.Translator.State.get_module_references(env.state, module) -- [env.module] - - {imports, body} = extract_imports_from_body(body) {structs, body} = extract_structs_from_body(body, env) app_name = State.get_module(env.state, module).app - imports = imports ++ make_std_lib_import(env) ++ make_imports(app_name, module_refs, env) - #Collect all the functions so that we can process their arity body = Enum.map(body, fn(x) -> case x do @@ -56,11 +50,12 @@ defmodule ElixirScript.Translator.Defmodule do exported_functions = Enum.map(exported_functions, fn({_key, value}) -> value end) private_functions = Enum.map(private_functions, fn({_key, value}) -> value end) - default = ModuleSystems.export_module(exported_object) + body = structs ++ private_functions ++ exported_functions ++ body + body = env.module_formatter.build(body, exported_object, env) result = %{ name: Utils.quoted_to_name({:__aliases__, [], module }), - body: imports ++ structs ++ private_functions ++ exported_functions ++ body ++ [default], + body: body, app_name: app_name } @@ -176,16 +171,6 @@ defmodule ElixirScript.Translator.Defmodule do end end - def make_std_lib_import(env) do - compiler_opts = ElixirScript.Translator.State.get(env.state).compiler_opts - case compiler_opts.import_standard_libs do - true -> - [ModuleSystems.import_module(:Elixir, Utils.make_local_file_path(:elixir, compiler_opts.core_path, env))] - false -> - [] - end - end - def process_functions(%{ exported: exported, private: private, exported_generators: exported_generators, private_generators: private_generators }, env) do exported_functions = Enum.map(Dict.keys(exported), fn(key) -> functions = Dict.get(exported, key) @@ -225,13 +210,4 @@ defmodule ElixirScript.Translator.Defmodule do JS.variable_declaration([declarator], :const) end - def make_imports(current_app_name, enum, env) do - Enum.map(enum, fn(x) -> - module_name = Utils.name_to_js_name(x) - app_name = State.get_module(env.state, x).app - path = Utils.make_local_file_path(app_name, Utils.name_to_js_file_name(x), env) - ModuleSystems.import_module(module_name, path) - end) - end - end diff --git a/lib/elixir_script/translator/kernel/defprotocol.ex b/lib/elixir_script/translator/kernel/defprotocol.ex index d8644a0e..da9419ab 100644 --- a/lib/elixir_script/translator/kernel/defprotocol.ex +++ b/lib/elixir_script/translator/kernel/defprotocol.ex @@ -6,7 +6,6 @@ defmodule ElixirScript.Translator.Defprotocol do alias ElixirScript.Translator.Map alias ElixirScript.Translator.Utils alias ElixirScript.Translator.State - alias ElixirScript.ModuleSystems alias ElixirScript.Translator.Identifier require Logger @@ -16,15 +15,14 @@ defmodule ElixirScript.Translator.Defprotocol do def make(name, functions, env) do { body, _ } = Defmodule.translate_body( {:__block__, [], [] }, env) - module_refs = ElixirScript.Translator.State.get_module_references(env.state, name) - - {imports, body} = Defmodule.extract_imports_from_body(body) - app_name = State.get_module(env.state, name).app - imports = imports ++ Defmodule.make_std_lib_import(env) ++ - Defmodule.make_imports(app_name, module_refs, env) ++ - [ElixirScript.ModuleSystems.import_module("Implementations", Utils.make_local_file_path(app_name, Utils.name_to_js_file_name(name) <> ".Defimpl", env)) ] + State.add_javascript_module_reference( + env.state, + env.module, + {:__aliases__, [], [:Implementations]}, + Utils.make_local_file_path(app_name, Utils.name_to_js_file_name(name) <> ".Defimpl", env) + ) object = process_spec_functions(functions) |> Enum.map(fn({key, value}) -> @@ -79,11 +77,12 @@ defmodule ElixirScript.Translator.Defprotocol do ) ) - default = JS.export_default_declaration(JS.identifier(Utils.name_to_js_name(name))) + body = body ++ [declaration] ++ [implementations] + body = env.module_formatter.build(body, JS.identifier(Utils.name_to_js_name(name)), env) %{ name: name, - body: imports ++ body ++ [declaration] ++ [implementations] ++ [default], + body: body, app_name: app_name } end @@ -93,47 +92,4 @@ defmodule ElixirScript.Translator.Defprotocol do {function_name, JS.function_expression([], [], JS.block_statement([]))} end) end - - @doc """ - Makes the protocol implementation module for the given implementation name. - This is used to consolidate all of the protocol implementations. - """ - def make_defimpl(name, implementations \\ [], compiler_opts, env) do - imports = [ModuleSystems.import_module(:Elixir, Utils.make_local_file_path(:elixir, compiler_opts.core_path, compiler_opts.root, env))] - - declarator = JS.variable_declarator( - JS.identifier("impls"), - JS.array_expression([]) - ) - - declaration = JS.variable_declaration([declarator], :let) - - default = JS.export_default_declaration(JS.identifier("impls")) - - protocol_name = Atom.to_string(name) - - app_name = State.get_module(env.state, name).app - - body = Enum.flat_map(implementations, fn({impl_app_name, x}) -> - x = if is_atom(x), do: Atom.to_string(x), else: x - x = String.to_atom(protocol_name <> ".DefImpl." <> x) - name = Utils.name_to_js_name(x) - imports = ModuleSystems.import_module(name, Utils.make_local_file_path(impl_app_name, Utils.name_to_js_file_name(x), compiler_opts.root)) - call = JS.call_expression( - JS.member_expression( - JS.identifier("impls"), - JS.identifier("push") - ), - [JS.identifier(name)] - ) - - [imports, call] - end) - - %{ - name: String.to_atom(protocol_name <> ".DefImpl"), - body: imports ++ [declaration] ++ body ++ [default], - app_name: app_name - } - end end diff --git a/lib/elixir_script/translator/kernel/js.ex b/lib/elixir_script/translator/kernel/js.ex index 49df2d9f..27acde1d 100644 --- a/lib/elixir_script/translator/kernel/js.ex +++ b/lib/elixir_script/translator/kernel/js.ex @@ -4,7 +4,7 @@ defmodule ElixirScript.Translator.JS do alias ESTree.Tools.Builder alias ElixirScript.Translator alias ElixirScript.Translator.Identifier - alias ElixirScript.ModuleSystems + alias ElixirScript.Translator.State @doc false def translate_js_function(name, params, env) do @@ -81,15 +81,18 @@ defmodule ElixirScript.Translator.JS do end defp do_translate({:import, _, [module_name, from, [default: false]]}, env) do - ModuleSystems.import_namespace_module(module_name, from, env) + State.add_javascript_module_reference(env.state, env.module, module_name, from, false) + %ElixirScript.Translator.Empty{} end defp do_translate({:import, _, [module_name, from, [default: true]]}, env) do - ModuleSystems.import_module(module_name, from, env) + State.add_javascript_module_reference(env.state, env.module, module_name, from, true) + %ElixirScript.Translator.Empty{} end defp do_translate({:import, _, [module_name, from]}, env) do - ModuleSystems.import_module(module_name, from, env) + State.add_javascript_module_reference(env.state, env.module, module_name, from, true) + %ElixirScript.Translator.Empty{} end defp do_translate({:object, _, [args]}, env) do diff --git a/lib/elixir_script/translator/lexical_scope.ex b/lib/elixir_script/translator/lexical_scope.ex index de2f9492..0e444c05 100644 --- a/lib/elixir_script/translator/lexical_scope.ex +++ b/lib/elixir_script/translator/lexical_scope.ex @@ -18,7 +18,9 @@ defmodule ElixirScript.Translator.LexicalScope do lexical_tracker: nil, caller: t | nil, env: nil, - state: pid + state: pid, + format: atom, + module_formatter: atom } defstruct [ @@ -38,7 +40,9 @@ defmodule ElixirScript.Translator.LexicalScope do lexical_tracker: nil, caller: nil, env: nil, - state: nil + state: nil, + format: :es, + module_formatter: ElixirScript.ModuleSystems.ES ] def env(scope) do @@ -79,20 +83,22 @@ defmodule ElixirScript.Translator.LexicalScope do } end - def module_scope(ElixirScript.Temp, filename, env, state) do + def module_scope(ElixirScript.Temp, filename, env, state, opts) do env = %ElixirScript.Translator.LexicalScope { module: ElixirScript.Temp, file: filename, requires: [], functions: [], macros: [], env: env, - state: state + state: state, + format: opts.format, + module_formatter: opts.module_formatter } add_import(env, ElixirScript.Kernel) end - def module_scope(module_name, filename, env, state) do + def module_scope(module_name, filename, env, state, opts) do module = ElixirScript.Translator.State.get_module(state, module_name) env = %ElixirScript.Translator.LexicalScope { @@ -100,7 +106,9 @@ defmodule ElixirScript.Translator.LexicalScope do functions: [{ module.name, module.functions}], macros: [{module.name, module.macros}], env: env, - state: state + state: state, + format: opts.format, + module_formatter: opts.module_formatter } env = add_import(env, ElixirScript.Kernel) diff --git a/lib/elixir_script/translator/state.ex b/lib/elixir_script/translator/state.ex index aa486b4c..40a09f74 100644 --- a/lib/elixir_script/translator/state.ex +++ b/lib/elixir_script/translator/state.ex @@ -117,7 +117,7 @@ defmodule ElixirScript.Translator.State do end def is_module_loaded?(pid, {:__aliases__, _, _} = module) do - + is_module_loaded?(pid, Utils.quoted_to_name(module)) end @@ -176,4 +176,26 @@ defmodule ElixirScript.Translator.State do def stop(pid) do Agent.stop(pid) end + + def add_javascript_module_reference(pid, module_name, name, path, default \\ true) do + Agent.update(pid, fn(state) -> + case Keyword.get(state.modules, do_get_module_name(module_name, state)) do + nil -> + state + module -> + module = Map.update(module, :js_modules, [{name, path, default}], fn(x) -> Enum.uniq(x ++ [{name, path, default}]) end) + modules = Keyword.put(state.modules, module.name, module) + %{ state | modules: modules } + end + end) + end + + def get_javascript_module_references(pid, module_name) do + case get_module(pid, module_name) do + nil -> + [] + module -> + Map.get(module, :js_modules, []) + end + end end diff --git a/mix.lock b/mix.lock index 32939a49..113af924 100644 --- a/mix.lock +++ b/mix.lock @@ -5,11 +5,11 @@ "estree": {:hex, :estree, "2.5.0", "9776c1705a72dc5a0d56cdf431173c3e75f9e509278a857ec55374a49f5699ef", [:mix], []}, "ex_doc": {:hex, :ex_doc, "0.14.5", "c0433c8117e948404d93ca69411dd575ec6be39b47802e81ca8d91017a0cf83c", [:mix], [{:earmark, "~> 1.0", [hex: :earmark, optional: false]}]}, "excoveralls": {:hex, :excoveralls, "0.6.2", "0e993d096f1fbb6e70a3daced5c89aac066bda6bce57829622aa2d1e2b338cfb", [:mix], [{:exjsx, "~> 3.0", [hex: :exjsx, optional: false]}, {:hackney, ">= 0.12.0", [hex: :hackney, optional: false]}]}, - "exjsx": {:hex, :exjsx, "3.2.1", "1bc5bf1e4fd249104178f0885030bcd75a4526f4d2a1e976f4b428d347614f0f", [], [{:jsx, "~> 2.8.0", [hex: :jsx, optional: false]}]}, + "exjsx": {:hex, :exjsx, "3.2.1", "1bc5bf1e4fd249104178f0885030bcd75a4526f4d2a1e976f4b428d347614f0f", [:mix], [{:jsx, "~> 2.8.0", [hex: :jsx, optional: false]}]}, "fs": {:hex, :fs, "2.12.0", "ad631efacc9a5683c8eaa1b274e24fa64a1b8eb30747e9595b93bec7e492e25e", [:rebar3], []}, "hackney": {:hex, :hackney, "1.6.5", "8c025ee397ac94a184b0743c73b33b96465e85f90a02e210e86df6cbafaa5065", [:rebar3], [{:certifi, "0.7.0", [hex: :certifi, optional: false]}, {:idna, "1.2.0", [hex: :idna, optional: false]}, {:metrics, "1.0.1", [hex: :metrics, optional: false]}, {:mimerl, "1.0.2", [hex: :mimerl, optional: false]}, {:ssl_verify_fun, "1.1.1", [hex: :ssl_verify_fun, optional: false]}]}, - "idna": {:hex, :idna, "1.2.0", "ac62ee99da068f43c50dc69acf700e03a62a348360126260e87f2b54eced86b2", [], []}, + "idna": {:hex, :idna, "1.2.0", "ac62ee99da068f43c50dc69acf700e03a62a348360126260e87f2b54eced86b2", [:rebar3], []}, "jsx": {:hex, :jsx, "2.8.2", "7acc7d785b5abe8a6e9adbde926a24e481f29956dd8b4df49e3e4e7bcc92a018", [:mix, :rebar3], []}, - "metrics": {:hex, :metrics, "1.0.1", "25f094dea2cda98213cecc3aeff09e940299d950904393b2a29d191c346a8486", [], []}, + "metrics": {:hex, :metrics, "1.0.1", "25f094dea2cda98213cecc3aeff09e940299d950904393b2a29d191c346a8486", [:rebar3], []}, "mimerl": {:hex, :mimerl, "1.0.2", "993f9b0e084083405ed8252b99460c4f0563e41729ab42d9074fd5e52439be88", [], []}, "ssl_verify_fun": {:hex, :ssl_verify_fun, "1.1.1", "28a4d65b7f59893bc2c7de786dec1e1555bd742d336043fe644ae956c3497fbe", [:make, :rebar], []}} diff --git a/test/test_helper.exs b/test/test_helper.exs index 863353a9..fd0d3f84 100644 --- a/test/test_helper.exs +++ b/test/test_helper.exs @@ -34,14 +34,9 @@ defmodule ElixirScript.TestHelper do end def strip_spaces(js) do - js |> strip_new_lines |> String.replace(" ", "") + js |> String.replace(~r/\s+/, "") end - def strip_new_lines(js) do - js |> String.replace("\n", "") - end - - def assert_translation(ex_ast, js_code) do converted_code = ex_ast_to_js(ex_ast) |> Elixir.Enum.join("\n\n") diff --git a/test/translator/pattern_matching_test.exs b/test/translator/pattern_matching_test.exs index 2effb06a..4688f142 100644 --- a/test/translator/pattern_matching_test.exs +++ b/test/translator/pattern_matching_test.exs @@ -11,7 +11,7 @@ defmodule ElixirScript.Translator.PatternMatching.Test do setup do {:ok, pid} = ElixirScript.Translator.State.start_link(%{env: __ENV__}, []) ElixirScript.Translator.State.deserialize(pid, @std_lib_state) - scope = ElixirScript.Translator.LexicalScope.module_scope(ElixirScript.Temp, "temp.ex", __ENV__, pid) + scope = ElixirScript.Translator.LexicalScope.module_scope(ElixirScript.Temp, "temp.ex", __ENV__, pid, %{ format: :es, module_formatter: ElixirScript.ModuleSystems.ES }) {:ok, [scope: scope]} end diff --git a/test/translator/protocol_test.exs b/test/translator/protocol_test.exs index efcfbc5f..26d79de7 100644 --- a/test/translator/protocol_test.exs +++ b/test/translator/protocol_test.exs @@ -26,17 +26,18 @@ defmodule ElixirScript.Translator.Defprotocol.Test do js_code = """ import Elixir from '../elixir/Elixir.Bootstrap'; - let impls = []; import Elixir$Blank$DefImpl$Elixir$Integer from '../app/Elixir.Blank.DefImpl.Elixir.Integer'; - impls.push(Elixir$Blank$DefImpl$Elixir$Integer) import Elixir$Blank$DefImpl$Elixir$List from '../app/Elixir.Blank.DefImpl.Elixir.List'; - impls.push(Elixir$Blank$DefImpl$Elixir$List) import Elixir$Blank$DefImpl$Elixir$Atom from '../app/Elixir.Blank.DefImpl.Elixir.Atom'; + + let impls = []; + impls.push(Elixir$Blank$DefImpl$Elixir$Integer) + impls.push(Elixir$Blank$DefImpl$Elixir$List) impls.push(Elixir$Blank$DefImpl$Elixir$Atom) export default impls; - import Elixir$ElixirScript$Kernel from '../elixir/Elixir.ElixirScript.Kernel'; import Implementations from '../app/Elixir.Blank.Defimpl'; + import Elixir$ElixirScript$Kernel from '../elixir/Elixir.ElixirScript.Kernel'; const Elixir$Blank = Elixir.Core.Functions.defprotocol({ blank__qmark__: function() { From 3e7f91a5a22db3ba4a77f6d4571405688e8f6e4b Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Fri, 17 Feb 2017 10:59:30 -0600 Subject: [PATCH 382/860] Add support for commonjs output --- lib/elixir_script/module_systems/common.ex | 40 +++++++++++++++++++++- lib/elixir_script/passes/handle_output.ex | 2 +- package.json | 3 +- 3 files changed, 42 insertions(+), 3 deletions(-) diff --git a/lib/elixir_script/module_systems/common.ex b/lib/elixir_script/module_systems/common.ex index 46798e29..61916eb1 100644 --- a/lib/elixir_script/module_systems/common.ex +++ b/lib/elixir_script/module_systems/common.ex @@ -1,8 +1,46 @@ defmodule ElixirScript.ModuleSystems.Common do - @moduledoc false + @moduledoc false alias ESTree.Tools.Builder, as: JS alias ElixirScript.Translator + def build(body, exports, env) do + js_module_refs = State.get_javascript_module_references(env.state, env.module) + std_import = make_std_lib_import(env) + module_refs = State.get_module_references(env.state, env.module) -- [env.module] + |> module_imports_to_js_imports(env) + app_name = State.get_module(env.state, env.module).app + + imports = js_module_refs ++ std_import + |> Enum.map(fn + {module, path, true} -> import_module(module, path, env) + {module, path, false} -> import_namespace_module(module, path, env) + end) + + imports = Enum.uniq(imports ++ module_refs) + + export = export_module(exports) + imports ++ body ++ [export] + end + + defp module_imports_to_js_imports(module_refs, env) do + Enum.map(module_refs, fn(x) -> + module_name = Utils.name_to_js_name(x) + app_name = State.get_module(env.state, x).app + path = Utils.make_local_file_path(app_name, Utils.name_to_js_file_name(x), env) + import_module(module_name, path) + end) + end + + defp make_std_lib_import(env) do + compiler_opts = State.get(env.state).compiler_opts + case compiler_opts.import_standard_libs do + true -> + [{:Elixir, Utils.make_local_file_path(:elixir, compiler_opts.core_path, env), true }] + false -> + [] + end + end + def import_namespace_module(module_name, from, env) do do_import_module(Translator.translate!(module_name, env), from) end diff --git a/lib/elixir_script/passes/handle_output.ex b/lib/elixir_script/passes/handle_output.ex index 229fabb6..728f5e91 100644 --- a/lib/elixir_script/passes/handle_output.ex +++ b/lib/elixir_script/passes/handle_output.ex @@ -40,7 +40,7 @@ defmodule ElixirScript.Passes.HandleOutput do defp out(compiler_output, %{output: output_path, core_path: _} = compiler_opts) do if Map.get(compiler_opts, :std_lib, false) == false do - ElixirScript.copy_stdlib_to_destination("es", output_path) + ElixirScript.copy_stdlib_to_destination(compiler_opts.format, output_path) end compiler_output = remove_load_only(compiler_output) diff --git a/package.json b/package.json index c6d5e7af..3546a987 100644 --- a/package.json +++ b/package.json @@ -9,9 +9,10 @@ "scripts": { "lint": "eslint src/javascript/lib/**/*.js src/javascript/tests/**/*.js", "lint:fix": "eslint src/javascript/lib/**/*.js src/javascript/tests/**/*.js --fix", - "build": "npm run build:es && npm run build:umd", + "build": "npm run build:es && npm run build:umd && npm run build:common", "build:es": "rollup -c rollup.config.js", "build:umd": "rollup -c rollup.config.js -f umd -o priv/umd/elixir/Elixir.Bootstrap.js", + "build:common": "rollup -c rollup.config.js -f cjs -o priv/common/elixir/Elixir.Bootstrap.js", "clean": "rm -rf priv", "test": "mocha src/javascript/tests --recursive --compilers js:babel-core/register" }, From 1f1625acbdc08664802534e3943c633cc569165f Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Fri, 17 Feb 2017 11:03:27 -0600 Subject: [PATCH 383/860] Update cli options --- lib/elixir_script/cli.ex | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/lib/elixir_script/cli.ex b/lib/elixir_script/cli.ex index c870f3c9..936226c8 100644 --- a/lib/elixir_script/cli.ex +++ b/lib/elixir_script/cli.ex @@ -4,14 +4,14 @@ defmodule ElixirScript.CLI do @app_version Mix.Project.config()[:version] @switches [ - output: :binary, elixir: :boolean, - help: :boolean, core_path: :binary, + output: :string, elixir: :boolean, + help: :boolean, core_path: :string, full_build: :boolean, version: :boolean, - watch: :boolean + watch: :boolean, format: :string ] @aliases [ - o: :output, ex: :elixir, h: :help, v: :version + o: :output, ex: :elixir, h: :help, v: :version, f: :format ] def main(argv) do @@ -44,11 +44,12 @@ defmodule ElixirScript.CLI do path to elixir files or the elixir code string if the -ex flag is used options: + -f --format [format] module format of output. options: es (default), common, umd -o --output [path] places output at the given path -ex --elixir read input as elixir code string --full-build informs the compiler to do a full build instead of an incremental one only used when output is specified - --core-path es6 import path to the elixirscript standard lib + --core-path import path to the elixirscript standard lib only used with the [output] option. When used, Elixir.js is not exported -v --version the current version number -h --help this message From c6df2c63e2a852b5da980c1c4465aa5cc5e01746 Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Fri, 17 Feb 2017 11:04:25 -0600 Subject: [PATCH 384/860] Update cli options --- lib/elixir_script/cli.ex | 1 + 1 file changed, 1 insertion(+) diff --git a/lib/elixir_script/cli.ex b/lib/elixir_script/cli.ex index 936226c8..fce03d27 100644 --- a/lib/elixir_script/cli.ex +++ b/lib/elixir_script/cli.ex @@ -80,6 +80,7 @@ defmodule ElixirScript.CLI do core_path: Keyword.get(options, :core_path, "Elixir.Bootstrap"), full_build: Keyword.get(options, :full_build, false), output: Keyword.get(options, :output, :stdout) + format: Keyword.get(options, :format, :es) } case options[:elixir] do From 0080de2cae1a07b2fe5b096af2cb16c0af2e1aed Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Fri, 17 Feb 2017 18:04:42 -0600 Subject: [PATCH 385/860] Add umd format. Add tests for commonjs and umd formats --- lib/elixir_script/cli.ex | 2 +- lib/elixir_script/module_systems/common.ex | 3 +- lib/elixir_script/module_systems/es.ex | 1 - lib/elixir_script/module_systems/umd.ex | 135 +++++++++++++ .../passes/consolidate_protocols.ex | 15 +- .../translator/kernel/defimpl.ex | 19 +- .../translator/kernel/defmodule.ex | 26 +-- test/test_helper.exs | 10 +- test/translator/commonjs_test.exs | 141 ++++++++++++++ test/translator/umd_test.exs | 181 ++++++++++++++++++ 10 files changed, 507 insertions(+), 26 deletions(-) create mode 100644 test/translator/commonjs_test.exs create mode 100644 test/translator/umd_test.exs diff --git a/lib/elixir_script/cli.ex b/lib/elixir_script/cli.ex index fce03d27..7bccc78b 100644 --- a/lib/elixir_script/cli.ex +++ b/lib/elixir_script/cli.ex @@ -79,7 +79,7 @@ defmodule ElixirScript.CLI do include_path: true, core_path: Keyword.get(options, :core_path, "Elixir.Bootstrap"), full_build: Keyword.get(options, :full_build, false), - output: Keyword.get(options, :output, :stdout) + output: Keyword.get(options, :output, :stdout), format: Keyword.get(options, :format, :es) } diff --git a/lib/elixir_script/module_systems/common.ex b/lib/elixir_script/module_systems/common.ex index 61916eb1..f61659b0 100644 --- a/lib/elixir_script/module_systems/common.ex +++ b/lib/elixir_script/module_systems/common.ex @@ -2,13 +2,14 @@ defmodule ElixirScript.ModuleSystems.Common do @moduledoc false alias ESTree.Tools.Builder, as: JS alias ElixirScript.Translator + alias ElixirScript.Translator.State + alias ElixirScript.Translator.Utils def build(body, exports, env) do js_module_refs = State.get_javascript_module_references(env.state, env.module) std_import = make_std_lib_import(env) module_refs = State.get_module_references(env.state, env.module) -- [env.module] |> module_imports_to_js_imports(env) - app_name = State.get_module(env.state, env.module).app imports = js_module_refs ++ std_import |> Enum.map(fn diff --git a/lib/elixir_script/module_systems/es.ex b/lib/elixir_script/module_systems/es.ex index aa088e0c..8ecd3fbb 100644 --- a/lib/elixir_script/module_systems/es.ex +++ b/lib/elixir_script/module_systems/es.ex @@ -10,7 +10,6 @@ defmodule ElixirScript.ModuleSystems.ES do std_import = make_std_lib_import(env) module_refs = State.get_module_references(env.state, env.module) -- [env.module] |> module_imports_to_js_imports(env) - app_name = State.get_module(env.state, env.module).app imports = js_module_refs ++ std_import |> Enum.map(fn diff --git a/lib/elixir_script/module_systems/umd.ex b/lib/elixir_script/module_systems/umd.ex index 218ea4a3..077c5c89 100644 --- a/lib/elixir_script/module_systems/umd.ex +++ b/lib/elixir_script/module_systems/umd.ex @@ -1,2 +1,137 @@ defmodule ElixirScript.ModuleSystems.UMD do + @moduledoc false + alias ESTree.Tools.Builder, as: JS + alias ElixirScript.Translator + alias ElixirScript.Translator.State + alias ElixirScript.Translator.Utils + + def build(body, exports, env) do + js_module_refs = State.get_javascript_module_references(env.state, env.module) + std_import = make_std_lib_import(env) + module_refs = State.get_module_references(env.state, env.module) -- [env.module] + |> module_imports_to_js_imports(env) + + imports = js_module_refs ++ std_import + |> Enum.map(fn + {module, path, true} -> import_module(module, path, env) + {module, path, false} -> import_namespace_module(module, path, env) + end) + + imports = Enum.uniq(imports ++ module_refs) + + export = export_module(exports) + + List.wrap(make_umd(imports, body, export)) + end + + defp module_imports_to_js_imports(module_refs, env) do + Enum.map(module_refs, fn(x) -> + module_name = Utils.name_to_js_name(x) + app_name = State.get_module(env.state, x).app + path = Utils.make_local_file_path(app_name, Utils.name_to_js_file_name(x), env) + import_module(module_name, path) + end) + end + + defp make_std_lib_import(env) do + compiler_opts = State.get(env.state).compiler_opts + case compiler_opts.import_standard_libs do + true -> + [{:Elixir, Utils.make_local_file_path(:elixir, compiler_opts.core_path, env), true }] + false -> + [] + end + end + + def import_namespace_module(module_name, from, env) do + {Translator.translate!(module_name, env), JS.literal(from)} + end + + def import_module(module_name, from, env) do + {Translator.translate!(module_name, env), JS.literal(from)} + end + + def import_module(import_name, from) do + {JS.identifier(import_name), JS.literal(from)} + end + + def export_module(exported_object) do + exported_object + end + + def make_umd(imports, body, exports) do + import_paths = Enum.map(imports, fn({_, path}) -> path end) + import_identifiers = Enum.map(imports, fn({id, _}) -> id end) + + JS.expression_statement( + JS.call_expression( + JS.function_expression([JS.identifier("root"), JS.identifier("factory")], [], JS.block_statement([ + JS.if_statement( + JS.logical_expression( + :&&, + JS.binary_expression( + :===, + JS.unary_expression(:typeof, true, JS.identifier("define")), + JS.literal("function") + ), + JS.member_expression( + JS.identifier("define"), + JS.identifier("amd") + ) + ), + JS.block_statement([ + JS.call_expression( + JS.identifier("define"), + [JS.array_expression(import_paths), JS.identifier("factory")] + ) + ]), + JS.if_statement( + JS.binary_expression( + :===, + JS.unary_expression(:typeof, true, JS.identifier("exports")), + JS.literal("object") + ), + JS.block_statement([ + JS.assignment_expression( + :=, + JS.member_expression( + JS.identifier("module"), + JS.identifier("exports") + ), + JS.call_expression( + JS.identifier("factory"), + Enum.map(import_paths, fn x -> + JS.call_expression( + JS.identifier("require"), + [x] + ) + end) + ) + ) + ]), + JS.block_statement([ + JS.assignment_expression( + :=, + JS.member_expression( + JS.identifier("root"), + JS.identifier("returnExports") + ), + JS.call_expression( + JS.identifier("factory"), + Enum.map(import_identifiers, fn x -> + JS.member_expression( + JS.identifier("root"), + x + ) + end) + ) + ) + ]) + ) + ) + ])), + [JS.this_expression(), JS.function_expression(import_identifiers, [], JS.block_statement(body ++ [JS.return_statement(exports)]))] + ) + ) + end end \ No newline at end of file diff --git a/lib/elixir_script/passes/consolidate_protocols.ex b/lib/elixir_script/passes/consolidate_protocols.ex index 8ebe2a5b..6ad87e26 100644 --- a/lib/elixir_script/passes/consolidate_protocols.ex +++ b/lib/elixir_script/passes/consolidate_protocols.ex @@ -90,11 +90,24 @@ defmodule ElixirScript.Passes.ConsolidateProtocols do end) imports = imports ++ defimpl_imports + body = [declaration] ++ body + exports = compiler_opts.module_formatter.export_module(JS.identifier("impls")) + + body = case compiler_opts.format do + :umd -> + compiler_opts.module_formatter.make_umd( + imports, + body, + exports + ) + _ -> + imports ++ body ++ [exports] + end module_name = String.to_atom(protocol_name <> ".DefImpl") module_data = %{ module: String.to_atom(protocol_name <> ".DefImpl"), - javascript_ast: imports ++ [declaration] ++ body ++ [default], + javascript_ast: List.wrap(body), app: app_name, type: :consolidated, protocol: name diff --git a/lib/elixir_script/translator/kernel/defimpl.ex b/lib/elixir_script/translator/kernel/defimpl.ex index 996ca689..b405e47f 100644 --- a/lib/elixir_script/translator/kernel/defimpl.ex +++ b/lib/elixir_script/translator/kernel/defimpl.ex @@ -1,16 +1,17 @@ defmodule ElixirScript.Translator.Defimpl do - @moduledoc false + @moduledoc false alias ESTree.Tools.Builder, as: JS alias ElixirScript.Translator.Defmodule + alias ElixirScript.Translator.State + alias ElixirScript.Translator.Utils def make(name, type, body, env) do type = map_to_js(type, env) - module = Defmodule.make_module(name, body, env) + {body, export} = Defmodule.process_module(name, body, env) protocol_name = Atom.to_string(name) |> String.split(".DefImpl.") |> hd |> String.to_atom - %ESTree.ExportDefaultDeclaration{ declaration: export } = List.last(module.body) export = JS.object_expression([ JS.property( JS.literal("Type"), @@ -22,12 +23,14 @@ defmodule ElixirScript.Translator.Defimpl do ) ]) - body = Enum.reverse(module.body) - |> tl - |> Enum.reverse + body = env.module_formatter.build(body, export, env) - %{ module | body: body ++ [JS.export_default_declaration(export)] } - |> Map.put(:protocol, protocol_name) + %{ + name: Utils.quoted_to_name({:__aliases__, [], name }), + body: body, + app_name: State.get_module(env.state, name).app, + protocol: protocol_name + } end defp map_to_js({:__aliases__, _, [:Integer]}, _) do diff --git a/lib/elixir_script/translator/kernel/defmodule.ex b/lib/elixir_script/translator/kernel/defmodule.ex index 72e2ce80..0b6770f5 100644 --- a/lib/elixir_script/translator/kernel/defmodule.ex +++ b/lib/elixir_script/translator/kernel/defmodule.ex @@ -18,6 +18,20 @@ defmodule ElixirScript.Translator.Defmodule do end def make_module(module, body, env) do + {body, exported_object} = process_module(module, body, env) + body = env.module_formatter.build(body, exported_object, env) + app_name = State.get_module(env.state, module).app + + result = %{ + name: Utils.quoted_to_name({:__aliases__, [], module }), + body: body, + app_name: app_name + } + + result + end + + def process_module(module, body, env) do { body, functions } = extract_functions_from_module(body) { body, env } = translate_body(body, env) @@ -26,8 +40,6 @@ defmodule ElixirScript.Translator.Defmodule do {structs, body} = extract_structs_from_body(body, env) - app_name = State.get_module(env.state, module).app - #Collect all the functions so that we can process their arity body = Enum.map(body, fn(x) -> case x do @@ -51,15 +63,7 @@ defmodule ElixirScript.Translator.Defmodule do private_functions = Enum.map(private_functions, fn({_key, value}) -> value end) body = structs ++ private_functions ++ exported_functions ++ body - body = env.module_formatter.build(body, exported_object, env) - - result = %{ - name: Utils.quoted_to_name({:__aliases__, [], module }), - body: body, - app_name: app_name - } - - result + {body, exported_object} end def translate_body(body, env) do diff --git a/test/test_helper.exs b/test/test_helper.exs index fd0d3f84..2771b873 100644 --- a/test/test_helper.exs +++ b/test/test_helper.exs @@ -29,8 +29,8 @@ defmodule ElixirScript.TestHelper do __ENV__ end - def ex_ast_to_js(ex_ast) do - ElixirScript.compile_quoted(ex_ast, %{ env: make_custom_env(), import_standard_libs: false }) + def ex_ast_to_js(ex_ast, format) do + ElixirScript.compile_quoted(ex_ast, %{ env: make_custom_env(), import_standard_libs: false, format: format }) end def strip_spaces(js) do @@ -38,7 +38,11 @@ defmodule ElixirScript.TestHelper do end def assert_translation(ex_ast, js_code) do - converted_code = ex_ast_to_js(ex_ast) |> Elixir.Enum.join("\n\n") + assert_translation(ex_ast, js_code, :es) + end + + def assert_translation(ex_ast, js_code, format) do + converted_code = ex_ast_to_js(ex_ast, format) |> Elixir.Enum.join("\n\n") assert converted_code |> strip_spaces == strip_spaces(js_code), """ **Code Does Not Match ** diff --git a/test/translator/commonjs_test.exs b/test/translator/commonjs_test.exs new file mode 100644 index 00000000..72bddc1c --- /dev/null +++ b/test/translator/commonjs_test.exs @@ -0,0 +1,141 @@ +defmodule ElixirScript.Translator.CommonJS.Test do + use ExUnit.Case + import ElixirScript.TestHelper + + test "translate module to commonjs" do + ex_ast = quote do + defmodule Elephant do + @ul JQuery.("#todo-list") + + def something() do + @ul + end + + defgenp something_else() do + end + end + end + + js_code = """ + const Elixir$ElixirScript$Kernel = require('../elixir/Elixir.ElixirScript.Kernel'); + + const something_else = Elixir.Core.Patterns.defmatchgen(Elixir.Core.Patterns.clause([], function*() { + return null; + })); + + const something = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.clause([], function() { + return ul; + })); + + const ul = JQuery('#todo-list'); + + module.exports = { + something + } + """ + + assert_translation(ex_ast, js_code, :common) + end + + test "protocol to commonjs" do + ex_ast = quote do + defprotocol Blank do + def blank?(data) + end + + defimpl Blank, for: Integer do + def blank?(number), do: false + end + + defimpl Blank, for: List do + def blank?([]), do: true + def blank?(_), do: false + end + + defimpl Blank, for: Atom do + def blank?(false), do: true + def blank?(nil), do: true + def blank?(_), do: false + end + end + + js_code = """ + const Elixir = require('../elixir/Elixir.Bootstrap'); + + const Elixir$Blank$DefImpl$Elixir$Integer = require('../app/Elixir.Blank.DefImpl.Elixir.Integer'); + + const Elixir$Blank$DefImpl$Elixir$List = require('../app/Elixir.Blank.DefImpl.Elixir.List'); + + const Elixir$Blank$DefImpl$Elixir$Atom = require('../app/Elixir.Blank.DefImpl.Elixir.Atom'); + + let impls = []; + + impls.push(Elixir$Blank$DefImpl$Elixir$Integer) + + impls.push(Elixir$Blank$DefImpl$Elixir$List) + + impls.push(Elixir$Blank$DefImpl$Elixir$Atom) + + module.exports = impls + + const Implementations = require('../app/Elixir.Blank.Defimpl'); + + const Elixir$ElixirScript$Kernel = require('../elixir/Elixir.ElixirScript.Kernel'); + + const Elixir$Blank = Elixir.Core.Functions.defprotocol({ + blank__qmark__: function() {} + }); + + for (let {Type, Implementation} of Implementations) Elixir.Core.Functions.defimpl(Elixir$Blank, Type, Implementation) + + module.exports = Elixir$Blank + + const Elixir$ElixirScript$Kernel = require('../elixir/Elixir.ElixirScript.Kernel'); + + const blank__qmark__ = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.clause([Elixir.Core.Patterns.variable()], function(number) { + return false; + })); + + module.exports = { + 'Type': Elixir.Core.Integer, + 'Implementation': { + blank__qmark__ + } + } + + const Elixir$ElixirScript$Kernel = require('../elixir/Elixir.ElixirScript.Kernel'); + + const blank__qmark__ = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.clause([Object.freeze([])], function() { + return true; + }), Elixir.Core.Patterns.clause([Elixir.Core.Patterns.wildcard()], function() { + return false; + })); + + module.exports = { + 'Type': Array, + 'Implementation': { + blank__qmark__ + } + } + + const Elixir$ElixirScript$Kernel = require('../elixir/Elixir.ElixirScript.Kernel'); + + const blank__qmark__ = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.clause([false], function() { + return true; + }), Elixir.Core.Patterns.clause([null], function() { + return true; + }), Elixir.Core.Patterns.clause([Elixir.Core.Patterns.wildcard()], function() { + return false; + })); + + module.exports = { + 'Type': Symbol, + 'Implementation': { + blank__qmark__ + } + } + """ + + assert_translation(ex_ast, js_code, :common) + end +end diff --git a/test/translator/umd_test.exs b/test/translator/umd_test.exs new file mode 100644 index 00000000..9a231f58 --- /dev/null +++ b/test/translator/umd_test.exs @@ -0,0 +1,181 @@ +defmodule ElixirScript.Translator.UMD.Test do + use ExUnit.Case + import ElixirScript.TestHelper + + test "translate module to umd" do + ex_ast = quote do + defmodule Elephant do + @ul JQuery.("#todo-list") + + def something() do + @ul + end + + defgenp something_else() do + end + end + end + + js_code = """ + (function(root, factory) { + if (typeof define === 'function' && define.amd) { + define(['../elixir/Elixir.ElixirScript.Kernel'], factory) + } else if (typeof exports === 'object') { + module.exports = factory(require('../elixir/Elixir.ElixirScript.Kernel')) + } else { + root.returnExports = factory(root.Elixir$ElixirScript$Kernel) + } + })(this, function(Elixir$ElixirScript$Kernel) { + const something_else = Elixir.Core.Patterns.defmatchgen(Elixir.Core.Patterns.clause([], function*() { + return null; + })); + + const something = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.clause([], function() { + return ul; + })); + + const ul = JQuery('#todo-list'); + + return { + something + }; + }); + """ + + assert_translation(ex_ast, js_code, :umd) + end + + test "protocol to umd" do + ex_ast = quote do + defprotocol Blank do + def blank?(data) + end + + defimpl Blank, for: Integer do + def blank?(number), do: false + end + + defimpl Blank, for: List do + def blank?([]), do: true + def blank?(_), do: false + end + + defimpl Blank, for: Atom do + def blank?(false), do: true + def blank?(nil), do: true + def blank?(_), do: false + end + end + + js_code = """ + (function(root, factory) { + if (typeof define === 'function' && define.amd) { + define(['../elixir/Elixir.Bootstrap', '../app/Elixir.Blank.DefImpl.Elixir.Integer', '../app/Elixir.Blank.DefImpl.Elixir.List', '../app/Elixir.Blank.DefImpl.Elixir.Atom'], factory) + } else if (typeof exports === 'object') { + module.exports = factory(require('../elixir/Elixir.Bootstrap'), require('../app/Elixir.Blank.DefImpl.Elixir.Integer'), require('../app/Elixir.Blank.DefImpl.Elixir.List'), require('../app/Elixir.Blank.DefImpl.Elixir.Atom')) + } else { + root.returnExports = factory(root.Elixir, root.Elixir$Blank$DefImpl$Elixir$Integer, root.Elixir$Blank$DefImpl$Elixir$List, root.Elixir$Blank$DefImpl$Elixir$Atom) + } + })(this, function(Elixir, Elixir$Blank$DefImpl$Elixir$Integer, Elixir$Blank$DefImpl$Elixir$List, Elixir$Blank$DefImpl$Elixir$Atom) { + let impls = []; + + impls.push(Elixir$Blank$DefImpl$Elixir$Integer) + + impls.push(Elixir$Blank$DefImpl$Elixir$List) + + impls.push(Elixir$Blank$DefImpl$Elixir$Atom) + + return impls; + }); + + (function(root, factory) { + if (typeof define === 'function' && define.amd) { + define(['../app/Elixir.Blank.Defimpl', '../elixir/Elixir.ElixirScript.Kernel'], factory) + } else if (typeof exports === 'object') { + module.exports = factory(require('../app/Elixir.Blank.Defimpl'), require('../elixir/Elixir.ElixirScript.Kernel')) + } else { + root.returnExports = factory(root.Implementations, root.Elixir$ElixirScript$Kernel) + } + })(this, function(Implementations, Elixir$ElixirScript$Kernel) { + const Elixir$Blank = Elixir.Core.Functions.defprotocol({ + blank__qmark__: function() {} + }); + + for (let {Type, Implementation} of Implementations) Elixir.Core.Functions.defimpl(Elixir$Blank, Type, Implementation) + + return Elixir$Blank; + }); + + (function(root, factory) { + if (typeof define === 'function' && define.amd) { + define(['../elixir/Elixir.ElixirScript.Kernel'], factory) + } else if (typeof exports === 'object') { + module.exports = factory(require('../elixir/Elixir.ElixirScript.Kernel')) + } else { + root.returnExports = factory(root.Elixir$ElixirScript$Kernel) + } + })(this, function(Elixir$ElixirScript$Kernel) { + const blank__qmark__ = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.clause([Elixir.Core.Patterns.variable()], function(number) { + return false; + })); + + return { + 'Type': Elixir.Core.Integer, + 'Implementation': { + blank__qmark__ + } + }; + }); + + (function(root, factory) { + if (typeof define === 'function' && define.amd) { + define(['../elixir/Elixir.ElixirScript.Kernel'], factory) + } else if (typeof exports === 'object') { + module.exports = factory(require('../elixir/Elixir.ElixirScript.Kernel')) + } else { + root.returnExports = factory(root.Elixir$ElixirScript$Kernel) + } + })(this, function(Elixir$ElixirScript$Kernel) { + const blank__qmark__ = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.clause([Object.freeze([])], function() { + return true; + }), Elixir.Core.Patterns.clause([Elixir.Core.Patterns.wildcard()], function() { + return false; + })); + + return { + 'Type': Array, + 'Implementation': { + blank__qmark__ + } + }; + }); + + (function(root, factory) { + if (typeof define === 'function' && define.amd) { + define(['../elixir/Elixir.ElixirScript.Kernel'], factory) + } else if (typeof exports === 'object') { + module.exports = factory(require('../elixir/Elixir.ElixirScript.Kernel')) + } else { + root.returnExports = factory(root.Elixir$ElixirScript$Kernel) + } + })(this, function(Elixir$ElixirScript$Kernel) { + const blank__qmark__ = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.clause([false], function() { + return true; + }), Elixir.Core.Patterns.clause([null], function() { + return true; + }), Elixir.Core.Patterns.clause([Elixir.Core.Patterns.wildcard()], function() { + return false; + })); + + return { + 'Type': Symbol, + 'Implementation': { + blank__qmark__ + } + }; + }); + """ + + assert_translation(ex_ast, js_code, :umd) + end +end \ No newline at end of file From 470eb35a06f3317cb6008ed9f3e2aa411e965e0c Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Fri, 17 Feb 2017 18:23:48 -0600 Subject: [PATCH 386/860] Fix Elixir.Bootstrap import --- lib/elixir_script.ex | 2 +- lib/elixir_script/cli.ex | 2 +- lib/elixir_script/module_systems/common.ex | 4 ++++ lib/elixir_script/module_systems/es.ex | 9 +++++++++ lib/elixir_script/module_systems/umd.ex | 4 ++++ 5 files changed, 19 insertions(+), 2 deletions(-) diff --git a/lib/elixir_script.ex b/lib/elixir_script.ex index 31e7e82a..9ec3110a 100644 --- a/lib/elixir_script.ex +++ b/lib/elixir_script.ex @@ -237,7 +237,7 @@ defmodule ElixirScript do to the specified location """ def copy_stdlib_to_destination(module_format, destination) do - Enum.each(Path.wildcard(Path.join([operating_path, module_format, "elixir", "*.js"])), fn(path) -> + Enum.each(Path.wildcard(Path.join([operating_path, to_string(module_format), "elixir", "*.js"])), fn(path) -> base = Path.basename(path) File.mkdir_p!(Path.join([destination, "elixir"])) File.cp!(path, Path.join([destination, "elixir", base])) diff --git a/lib/elixir_script/cli.ex b/lib/elixir_script/cli.ex index 7bccc78b..18efdeef 100644 --- a/lib/elixir_script/cli.ex +++ b/lib/elixir_script/cli.ex @@ -80,7 +80,7 @@ defmodule ElixirScript.CLI do core_path: Keyword.get(options, :core_path, "Elixir.Bootstrap"), full_build: Keyword.get(options, :full_build, false), output: Keyword.get(options, :output, :stdout), - format: Keyword.get(options, :format, :es) + format: String.to_atom(Keyword.get(options, :format, "es")) } case options[:elixir] do diff --git a/lib/elixir_script/module_systems/common.ex b/lib/elixir_script/module_systems/common.ex index f61659b0..05868410 100644 --- a/lib/elixir_script/module_systems/common.ex +++ b/lib/elixir_script/module_systems/common.ex @@ -46,6 +46,10 @@ defmodule ElixirScript.ModuleSystems.Common do do_import_module(Translator.translate!(module_name, env), from) end + def import_module(:Elixir, from, env) do + do_import_module(JS.identifier("Elixir"), from) + end + def import_module(module_name, from, env) do do_import_module(Translator.translate!(module_name, env), from) end diff --git a/lib/elixir_script/module_systems/es.ex b/lib/elixir_script/module_systems/es.ex index 8ecd3fbb..b4bc0c63 100644 --- a/lib/elixir_script/module_systems/es.ex +++ b/lib/elixir_script/module_systems/es.ex @@ -51,6 +51,15 @@ defmodule ElixirScript.ModuleSystems.ES do do_import_module([import_specifier], from) end + def import_module(:Elixir, from, env) do + import_specifier = JS.import_default_specifier( + JS.identifier("Elixir"), + JS.identifier("Elixir") + ) + + do_import_module([import_specifier], from) + end + def import_module(module_name, from, env) do import_specifier = JS.import_default_specifier( Translator.translate!(module_name, env), diff --git a/lib/elixir_script/module_systems/umd.ex b/lib/elixir_script/module_systems/umd.ex index 077c5c89..eabd5de0 100644 --- a/lib/elixir_script/module_systems/umd.ex +++ b/lib/elixir_script/module_systems/umd.ex @@ -47,6 +47,10 @@ defmodule ElixirScript.ModuleSystems.UMD do {Translator.translate!(module_name, env), JS.literal(from)} end + def import_module(:Elixir, from, env) do + {JS.identifier("Elixir"), JS.literal(from)} + end + def import_module(module_name, from, env) do {Translator.translate!(module_name, env), JS.literal(from)} end From 6ed7d9b3871a992ce9ff463acd5fbc7ecd15d63f Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Fri, 17 Feb 2017 18:35:51 -0600 Subject: [PATCH 387/860] Update readme. Update mix compiler to look for format key --- CHANGELOG.md | 1 + lib/mix/tasks/compile.elixir_script.ex | 7 ++++--- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 598de771..16c4d2b0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,6 +9,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/). - Updated elixir_script mix compiler to support compiling elixir_script paths in dependencies - Add `Collectable` implementations - Updated `for` implementation to use Collectable +- `format` option. Can now specify the module format of output. Choices are `es` (default), `umd`, or `common` ### Fixed - JS module functions not translated properly when imported diff --git a/lib/mix/tasks/compile.elixir_script.ex b/lib/mix/tasks/compile.elixir_script.ex index bdf523ed..1a98f1ae 100644 --- a/lib/mix/tasks/compile.elixir_script.ex +++ b/lib/mix/tasks/compile.elixir_script.ex @@ -28,14 +28,14 @@ defmodule Mix.Tasks.Compile.ElixirScript do input_path = Keyword.fetch!(elixirscript_config, :input) |> List.wrap - |> Enum.map(fn(path) -> + |> Enum.map(fn(path) -> Path.absname(path) end) |> Enum.join("\n") File.write!(elixirscript_path, input_path) - paths = Path.join([elixirscript_base, "*"]) + paths = Path.join([elixirscript_base, "*"]) |> Path.wildcard |> Enum.map(fn(path) -> {Path.basename(path), File.read!(path)} @@ -43,7 +43,8 @@ defmodule Mix.Tasks.Compile.ElixirScript do |> Map.new output_path = Keyword.fetch!(elixirscript_config, :output) - ElixirScript.compile_path(paths, %{output: output_path}) + format = Keyword.get(elixirscript_config, :format, :es) + ElixirScript.compile_path(paths, %{output: output_path, format: format}) :ok end From 8c7772dbd6141b1f23fa5a55e7df0d7704258eee Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Sat, 18 Feb 2017 01:07:24 -0600 Subject: [PATCH 388/860] Remove references to processes --- CHANGELOG.md | 4 + FAQ.md | 6 +- lib/elixir_script/prelude/kernel.ex | 36 -------- lib/elixir_script/prelude/process.ex | 90 ------------------ lib/elixir_script/translator.ex | 5 +- .../kernel/special_forms/receive.ex | 68 -------------- package.json | 1 - src/javascript/lib/core.js | 15 +-- test/translator/kernel/receive_test.exs | 91 ------------------- test/translator/kernel/send_test.exs | 16 ---- test/translator/kernel/spawn_test.exs | 30 ------ 11 files changed, 14 insertions(+), 348 deletions(-) delete mode 100644 lib/elixir_script/prelude/process.ex delete mode 100644 lib/elixir_script/translator/kernel/special_forms/receive.ex delete mode 100644 test/translator/kernel/receive_test.exs delete mode 100644 test/translator/kernel/send_test.exs delete mode 100644 test/translator/kernel/spawn_test.exs diff --git a/CHANGELOG.md b/CHANGELOG.md index 16c4d2b0..daa832a8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,6 +11,10 @@ and this project adheres to [Semantic Versioning](http://semver.org/). - Updated `for` implementation to use Collectable - `format` option. Can now specify the module format of output. Choices are `es` (default), `umd`, or `common` +### Removed +- `receive` +- `Process` module + ### Fixed - JS module functions not translated properly when imported - Update fs dependency to 2.12 diff --git a/FAQ.md b/FAQ.md index cfb7df3a..107cd895 100644 --- a/FAQ.md +++ b/FAQ.md @@ -41,6 +41,7 @@ The compiler to this point has been focused on translating Kernel.SpecialForms a * Missing * `super(args)` + * `receive` * Caveats * `quote` - ignores `context` options @@ -50,7 +51,6 @@ The compiler to this point has been focused on translating Kernel.SpecialForms a 1 = a # may not work currently, but in some cases it will ``` - * `send` and `receive` only work on functions defined with `defgen` or `defgenp` #### Completed Modules @@ -91,8 +91,8 @@ You **can** use ElixirScript on your front ends and have it work and interoperat ## Q. Can I use processes? -### A. Yes, with some caveats as mentioned above. Only current works with functions defined with `defgen` or `defgenp` +### A. ElixirScript does not support processes ## Q. What about OTP? -### A. Not yet. Maybe never. +### A. ElixirScript does not support OTP diff --git a/lib/elixir_script/prelude/kernel.ex b/lib/elixir_script/prelude/kernel.ex index 6e99a97f..1fa8333a 100644 --- a/lib/elixir_script/prelude/kernel.ex +++ b/lib/elixir_script/prelude/kernel.ex @@ -159,42 +159,6 @@ defmodule ElixirScript.Kernel do term === nil end - def make_ref() do - Elixir.Core.processes.make_ref() - end - - def spawn(gen) do - Elixir.Core.processes.spawn(gen) - end - - def spawn(module, fun, args) do - Elixir.Core.processes.spawn(module, Atom.to_string(fun), args) - end - - def spawn_link(gen) do - Elixir.Core.processes.spawn_link(gen) - end - - def spawn_link(module, fun, args) do - Elixir.Core.processes.spawn_link(module, Atom.to_string(fun), args) - end - - def spawn_monitor(gen) do - Elixir.Core.processes.spawn_monitor(gen) - end - - def spawn_monitor(module, fun, args) do - Elixir.Core.processes.spawn_monitor(module, Atom.to_string(fun), args) - end - - def send(pid, message) do - Elixir.Core.processes.send(pid, message) - end - - def self() do - Elixir.Core.processes.pid() - end - defmacro sigil_r({:<<>>, _meta, [string]}, options) do str_options = List.to_string(options) quote do diff --git a/lib/elixir_script/prelude/process.ex b/lib/elixir_script/prelude/process.ex deleted file mode 100644 index caeed8f3..00000000 --- a/lib/elixir_script/prelude/process.ex +++ /dev/null @@ -1,90 +0,0 @@ -defmodule ElixirScript.Process do - @moduledoc false - def alive?(pid) do - Elixir.Core.processes.is_alive(pid) - end - - def delete(key) do - Elixir.Core.processes.erase(key) - end - - def exit(pid, reason) do - Elixir.Core.processes.exit(pid, reason) - end - - def flag(flag, value) do - Elixir.Core.processes.process_flag(flag, value) - end - - def flag(pid, flag, value) do - Elixir.Core.processes.process_flag(pid, flag, value) - end - - def get() do - Elixir.Core.processes.get_process_dict() - end - - def get(key, default \\ nil) do - Elixir.Core.processes.get(key, default) - end - - def get_keys() do - Elixir.Core.processes.get_keys() - end - - def get_keys(value) do - Elixir.Core.processes.get_keys(value) - end - - def put(key, value) do - Elixir.Core.processes.put(key, value) - end - - def link(pid) do - Elixir.Core.processes.link(pid) - end - - def unlink(pid) do - Elixir.Core.processes.unlink(pid) - end - - def monitor(item) do - Elixir.Core.processes.monitor(item) - end - - def demonitor(monitor_ref) do - Elixir.Core.processes.demonitor(monitor_ref) - end - - def register(pid, name) when is_atom(name) do - Elixir.Core.processes.register(name, pid) - end - - def registered() do - Elixir.Core.processes.registered() - end - - def whereis(name) do - Elixir.Core.processes.whereis(name) - end - - def unregister(name) do - Elixir.Core.processes.unregister(name) - end - - def list() do - Elixir.Core.processes.list() - end - - def sleep(duration) when is_integer(duration) do - Elixir.Core.processes.sleep(duration) - end - - def sleep(:infinity) do - Elixir.Core.processes.sleep(:infinity) - end - - def send(dest, msg, _) do - Elixir.Core.processes.send(dest, msg) - end -end diff --git a/lib/elixir_script/translator.ex b/lib/elixir_script/translator.ex index 4f38e098..9be13020 100644 --- a/lib/elixir_script/translator.ex +++ b/lib/elixir_script/translator.ex @@ -24,7 +24,6 @@ defmodule ElixirScript.Translator do alias ElixirScript.Translator.JS, as: JSLib alias ESTree.Tools.Builder, as: JS alias ElixirScript.Translator.Rewriter - alias ElixirScript.Translator.Receive # A list of erlang modules. These are rewritten into equivalent # JavaScript functions using ElixirScript.Translator.Rewriter @@ -460,8 +459,8 @@ defmodule ElixirScript.Translator do Function.make_anonymous_function(clauses, env) end - defp do_translate({:receive, _, [expressions] }, env) do - Receive.make_receive(expressions, env) + defp do_translate({:receive, _, _ }, _) do + raise ElixirScript.Translator.UnsupportedError, "receive" end defp do_translate({:{}, _, elements}, env) do diff --git a/lib/elixir_script/translator/kernel/special_forms/receive.ex b/lib/elixir_script/translator/kernel/special_forms/receive.ex deleted file mode 100644 index 75c72287..00000000 --- a/lib/elixir_script/translator/kernel/special_forms/receive.ex +++ /dev/null @@ -1,68 +0,0 @@ -defmodule ElixirScript.Translator.Receive do - @moduledoc false - - alias ESTree.Tools.Builder, as: JS - alias ElixirScript.Translator - alias ElixirScript.Translator.Primitive - alias ElixirScript.Translator.LexicalScope - - def make_receive([do: clauses], env) do - {made_case, _} = ElixirScript.Translator.Case.make_case({:__aliases__, [], [:message]}, clauses, env) - - js = call_processes_func("receive", [ - JS.function_expression( - [JS.identifier(:message)], - [], - JS.block_statement([ - JS.return_statement( - made_case - ) - ]) - ) - ]) - - - {js, env} - end - - def make_receive([do: clauses, after: [{:->, _, [[time], _body]}] = after_clause], env) do - {made_case, _} = ElixirScript.Translator.Case.make_case({:__aliases__, [], [:message]}, clauses, env) - {anon_func, _} = ElixirScript.Translator.Function.make_anonymous_function(after_clause, env) - - - js = call_processes_func("receive", [ - JS.function_expression( - [JS.identifier(:message)], - [], - JS.block_statement([ - JS.return_statement( - made_case - ) - ]) - ), - Translator.translate!(time, env), - anon_func - ]) - - {js, env} - end - - def call_processes_func(func_name, params) do - JS.yield_expression( - JS.call_expression( - JS.member_expression( - JS.member_expression( - JS.identifier("Elixir"), - JS.member_expression( - JS.identifier("Core"), - JS.identifier("processes") - ) - ), - JS.identifier(func_name) - ), - params - ) - ) - end - -end diff --git a/package.json b/package.json index 3546a987..3176dd63 100644 --- a/package.json +++ b/package.json @@ -24,7 +24,6 @@ "license": "MIT", "dependencies": { "erlang-types": "^1.0.0", - "erlang-processes": "^2.0.0", "tailored": "2.3.2" }, "devDependencies": { diff --git a/src/javascript/lib/core.js b/src/javascript/lib/core.js index e1b229aa..d8bccde4 100644 --- a/src/javascript/lib/core.js +++ b/src/javascript/lib/core.js @@ -1,18 +1,13 @@ -import Processes from 'erlang-processes'; -import Patterns from 'tailored'; -import ErlangTypes from 'erlang-types'; -import Functions from './core/functions'; -import SpecialForms from './core/special_forms'; -import Store from './core/store'; - -let processes = new Processes.ProcessSystem(); +import Patterns from "tailored"; +import ErlangTypes from "erlang-types"; +import Functions from "./core/functions"; +import SpecialForms from "./core/special_forms"; +import Store from "./core/store"; class Integer {} class Float {} export default { - ProcessSystem: Processes.ProcessSystem, - processes: processes, Tuple: ErlangTypes.Tuple, PID: ErlangTypes.PID, BitString: ErlangTypes.BitString, diff --git a/test/translator/kernel/receive_test.exs b/test/translator/kernel/receive_test.exs deleted file mode 100644 index fccc8a10..00000000 --- a/test/translator/kernel/receive_test.exs +++ /dev/null @@ -1,91 +0,0 @@ - -defmodule ElixirScript.Translator.Receive.Test do - use ExUnit.Case - import ElixirScript.TestHelper - - test "translate receive without after in process" do - ex_ast = quote do - receive do - :ok -> - value - :error -> - value - _ -> - IO.puts "Unexpected message received" - end - - end - - js_code = """ - yield Elixir.Core.processes.receive(function(message) { - return Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.clause([Symbol.for('ok')],function() { - return value; - }),Elixir.Core.Patterns.clause([Symbol.for('error')],function() { - return value; - }),Elixir.Core.Patterns.clause([Elixir.Core.Patterns.wildcard()],function() { - return IO.puts('Unexpected message received'); - })).call(this,message); - }) - """ - - assert_translation(ex_ast, js_code) - end - - test "translate receive with after in process" do - ex_ast = quote do - receive do - :ok -> - value - :error -> - value - _ -> - IO.puts "Unexpected message received" - after - 5000 -> - IO.puts "No message in 5 seconds" - end - end - - js_code = """ - yield Elixir.Core.processes.receive(function(message) { - return Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.clause([Symbol.for('ok')],function() { - return value; - }),Elixir.Core.Patterns.clause([Symbol.for('error')],function() { - return value; - }),Elixir.Core.Patterns.clause([Elixir.Core.Patterns.wildcard()],function() { - return IO.puts('Unexpected message received'); - })).call(this,message); - },5000,Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.clause([5000],function() { - return IO.puts('No message in 5 seconds'); - }))) - """ - - assert_translation(ex_ast, js_code) - end - - test "translate receive" do - ex_ast = quote do - require JS - - defgen await(counter) do - receive do - {:ping, sender} -> send sender, {:pong, self} - end - end - end - - js_code = """ - const await = Elixir.Core.Patterns.defmatchgen(Elixir.Core.Patterns.clause([Elixir.Core.Patterns.variable()], function*(counter) { - return yield Elixir.Core.processes.receive(function(message) { - return Elixir.Core.Patterns.defmatchgen(Elixir.Core.Patterns.clause([Elixir.Core.Patterns.type(Elixir.Core.Tuple, { - values: [Symbol.for('ping'), Elixir.Core.Patterns.variable()] - })], function*(sender) { - return Elixir$ElixirScript$Kernel.send(sender, new Elixir.Core.Tuple(Symbol.for('pong'), Elixir$ElixirScript$Kernel.self())); - })).call(this, message); - }); - })); - """ - - assert_translation(ex_ast, js_code) - end -end diff --git a/test/translator/kernel/send_test.exs b/test/translator/kernel/send_test.exs deleted file mode 100644 index 0c0daf7a..00000000 --- a/test/translator/kernel/send_test.exs +++ /dev/null @@ -1,16 +0,0 @@ -defmodule ElixirScript.Translator.Send.Test do - use ExUnit.Case - import ElixirScript.TestHelper - - test "call send outside process" do - ex_ast = quote do - send(pid, "hello") - end - - js_code = """ - Elixir$ElixirScript$Kernel.send(pid, 'hello') - """ - - assert_translation(ex_ast, js_code) - end -end diff --git a/test/translator/kernel/spawn_test.exs b/test/translator/kernel/spawn_test.exs deleted file mode 100644 index a2f9152a..00000000 --- a/test/translator/kernel/spawn_test.exs +++ /dev/null @@ -1,30 +0,0 @@ -defmodule ElixirScript.Translator.Spawn.Test do - use ExUnit.Case - import ElixirScript.TestHelper - - test "call spawn with function apply" do - ex_ast = quote do - spawn(Tuple, :to_list, [{1, 2, 3}]) - end - - js_code = """ - Elixir$ElixirScript$Kernel.spawn(Elixir$ElixirScript$Tuple,Symbol.for('to_list'),Object.freeze([new Elixir.Core.Tuple(1,2,3)])) - """ - - assert_translation(ex_ast, js_code) - end - - - test "call spawn with JS function" do - ex_ast = quote do - spawn(Window, :call, [{1, 2, 3}]) - end - - js_code = """ - Elixir$ElixirScript$Kernel.spawn(Window,Symbol.for('call'),Object.freeze([new Elixir.Core.Tuple(1,2,3)])) - """ - - assert_translation(ex_ast, js_code) - end - -end From 6e56ef3d132baabdc3c78c5b1dedfafe82d22c77 Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Sat, 18 Feb 2017 01:33:58 -0600 Subject: [PATCH 389/860] Fix paths retrieval code in mix compiler. add defaults --- lib/elixir_script.ex | 2 +- lib/mix/tasks/compile.elixir_script.ex | 32 +++++++++++++++++++++----- 2 files changed, 27 insertions(+), 7 deletions(-) diff --git a/lib/elixir_script.ex b/lib/elixir_script.ex index 9ec3110a..c9b062ff 100644 --- a/lib/elixir_script.ex +++ b/lib/elixir_script.ex @@ -127,7 +127,7 @@ defmodule ElixirScript do compile_path([path], opts) end - def compile_path(path, opts) when is_list(path) do + def compile_path(path, opts) when is_list(path) do built_opts = build_compiler_options(opts) app_name = cond do diff --git a/lib/mix/tasks/compile.elixir_script.ex b/lib/mix/tasks/compile.elixir_script.ex index 1a98f1ae..69e1bff5 100644 --- a/lib/mix/tasks/compile.elixir_script.ex +++ b/lib/mix/tasks/compile.elixir_script.ex @@ -26,7 +26,7 @@ defmodule Mix.Tasks.Compile.ElixirScript do File.mkdir_p!(elixirscript_base) elixirscript_path = Path.join([elixirscript_base, "#{Mix.Project.config[:app]}"]) - input_path = Keyword.fetch!(elixirscript_config, :input) + input_path = Keyword.get(elixirscript_config, :input) |> List.wrap |> Enum.map(fn(path) -> Path.absname(path) @@ -38,19 +38,22 @@ defmodule Mix.Tasks.Compile.ElixirScript do paths = Path.join([elixirscript_base, "*"]) |> Path.wildcard |> Enum.map(fn(path) -> - {Path.basename(path), File.read!(path)} + app = Path.basename(path) + paths = path |> File.read!() |> String.split("\n") + {app, paths} end) |> Map.new - output_path = Keyword.fetch!(elixirscript_config, :output) - format = Keyword.get(elixirscript_config, :format, :es) + output_path = Keyword.get(elixirscript_config, :output) + format = Keyword.get(elixirscript_config, :format) + ElixirScript.compile_path(paths, %{output: output_path, format: format}) :ok end def clean do elixirscript_config = get_elixirscript_config() - output_path = Keyword.fetch!(elixirscript_config, :output) + output_path = Keyword.get(elixirscript_config, :output) File.ls!(output_path) |> Enum.each(fn(x) -> @@ -64,7 +67,24 @@ defmodule Mix.Tasks.Compile.ElixirScript do defp get_elixirscript_config() do config = Mix.Project.config - Keyword.fetch!(config, :elixir_script) || Keyword.fetch!(config, :elixirscript) + exjs_config = cond do + Keyword.has_key?(config, :elixir_script) -> + Keyword.get(config, :elixir_script, []) + Keyword.has_key?(config, :elixirscript) -> + Keyword.get(config, :elixirscript, []) + true -> + defaults() + end + + Keyword.merge(defaults(), exjs_config) + end + + defp defaults() do + [ + input: "lib/elixirscript", + output: "priv/elixirscript", + format: :es + ] end end From 9c0103ef7f15b0d6e302c8cfb17e5c0103019387 Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Sat, 18 Feb 2017 01:34:52 -0600 Subject: [PATCH 390/860] Update changelog --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index daa832a8..89cc5e31 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,6 +10,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/). - Add `Collectable` implementations - Updated `for` implementation to use Collectable - `format` option. Can now specify the module format of output. Choices are `es` (default), `umd`, or `common` +- Default input, output and format for elixirscript mix compiler ### Removed - `receive` From 0e78944d278a084a093c9691233af5153aa19b4e Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Sat, 18 Feb 2017 10:40:56 -0600 Subject: [PATCH 391/860] move standard lib folder. Add and update docs for mix tasks --- .credo.exs | 1 - CONTRIBUTING.md | 2 +- lib/elixir_script.ex | 4 +- lib/mix/tasks/compile.elixir_script.ex | 37 ++++++++++----- lib/mix/tasks/elixirscript.ex | 3 ++ lib/mix/tasks/elixirscript.watch.ex | 47 +++++++++++++------ .../prelude => std_lib}/agent.ex | 0 .../prelude => std_lib}/atom.ex | 0 .../prelude => std_lib}/base.ex | 0 .../prelude => std_lib}/bitwise.ex | 0 .../prelude => std_lib}/collectable.ex | 0 .../prelude => std_lib}/enumerable.ex | 0 .../prelude => std_lib}/integer.ex | 0 lib/{elixir_script/prelude => std_lib}/js.ex | 0 .../prelude => std_lib}/kernel.ex | 0 .../prelude => std_lib}/keyword.ex | 0 .../prelude => std_lib}/list.ex | 0 .../prelude => std_lib}/macro/env.ex | 0 lib/{elixir_script/prelude => std_lib}/map.ex | 0 .../prelude => std_lib}/map_set.ex | 0 .../prelude => std_lib}/module.ex | 0 .../prelude => std_lib}/range.ex | 0 .../prelude => std_lib}/regex.ex | 3 +- .../prelude => std_lib}/string.ex | 0 .../prelude => std_lib}/string/chars.ex | 0 .../prelude => std_lib}/tuple.ex | 0 26 files changed, 66 insertions(+), 31 deletions(-) rename lib/{elixir_script/prelude => std_lib}/agent.ex (100%) rename lib/{elixir_script/prelude => std_lib}/atom.ex (100%) rename lib/{elixir_script/prelude => std_lib}/base.ex (100%) rename lib/{elixir_script/prelude => std_lib}/bitwise.ex (100%) rename lib/{elixir_script/prelude => std_lib}/collectable.ex (100%) rename lib/{elixir_script/prelude => std_lib}/enumerable.ex (100%) rename lib/{elixir_script/prelude => std_lib}/integer.ex (100%) rename lib/{elixir_script/prelude => std_lib}/js.ex (100%) rename lib/{elixir_script/prelude => std_lib}/kernel.ex (100%) rename lib/{elixir_script/prelude => std_lib}/keyword.ex (100%) rename lib/{elixir_script/prelude => std_lib}/list.ex (100%) rename lib/{elixir_script/prelude => std_lib}/macro/env.ex (100%) rename lib/{elixir_script/prelude => std_lib}/map.ex (100%) rename lib/{elixir_script/prelude => std_lib}/map_set.ex (100%) rename lib/{elixir_script/prelude => std_lib}/module.ex (100%) rename lib/{elixir_script/prelude => std_lib}/range.ex (100%) rename lib/{elixir_script/prelude => std_lib}/regex.ex (94%) rename lib/{elixir_script/prelude => std_lib}/string.ex (100%) rename lib/{elixir_script/prelude => std_lib}/string/chars.ex (100%) rename lib/{elixir_script/prelude => std_lib}/tuple.ex (100%) diff --git a/.credo.exs b/.credo.exs index ca7b102a..18abcc24 100644 --- a/.credo.exs +++ b/.credo.exs @@ -90,7 +90,6 @@ {Credo.Check.Readability.VariableNames}, {Credo.Check.Refactor.DoubleBooleanNegation}, - # {Credo.Check.Refactor.CaseTrivialMatches}, # deprecated in 0.4.0 {Credo.Check.Refactor.ABCSize}, {Credo.Check.Refactor.CondStatements}, {Credo.Check.Refactor.CyclomaticComplexity}, diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index b83cdf14..511aa424 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -70,7 +70,7 @@ ElixirScript is broken up into the following parts: The ElixirScript compiler is in the `lib` folder of the project. Here is where Elixir code is converted into JavaScript. -The standard library modules are in the `lib/elixir_script/prelude` folder. +The standard library modules are in the `lib/std_lib` folder. The JavaScript code is in the `src/javascript`. This is where features such as pattern matching and the standard library are implemented. diff --git a/lib/elixir_script.ex b/lib/elixir_script.ex index c9b062ff..fd0020d6 100644 --- a/lib/elixir_script.ex +++ b/lib/elixir_script.ex @@ -187,9 +187,9 @@ defmodule ElixirScript do @doc false def compile_std_lib(output_path) do opts = build_compiler_options(%{std_lib: true, include_path: true, output: output_path, app: :elixir}) - libs_path = Path.join([__DIR__, "elixir_script", "prelude"]) + libs_path = Path.join([__DIR__, "std_lib"]) - result = %{ data: [{:elixir, List.wrap(libs_path)}] } + result = %{data: [{:elixir, List.wrap(libs_path)}]} |> ElixirScript.Passes.Init.execute(opts) |> ElixirScript.Passes.ASTFromFile.execute(opts) |> ElixirScript.Passes.FindModules.execute(opts) diff --git a/lib/mix/tasks/compile.elixir_script.ex b/lib/mix/tasks/compile.elixir_script.ex index 69e1bff5..b16f7cd4 100644 --- a/lib/mix/tasks/compile.elixir_script.ex +++ b/lib/mix/tasks/compile.elixir_script.ex @@ -4,21 +4,31 @@ defmodule Mix.Tasks.Compile.ElixirScript do @moduledoc """ Mix compiler to allow mix to compile Elixirscript source files into JavaScript - Looks for an `elixir_script` key in your mix project config + Looks for an `elixir_script` or `elixirscript` key in your mix project config def project do - [ - app: :my_app, - version: "0.1.0", - elixir: "~> 1.0", - deps: deps, - elixir_script: [ input: "src/exjs", output: "dest/js"], - compilers: [:elixir_script] ++ Mix.compilers - ] + [ + app: :my_app, + version: "0.1.0", + elixir: "~> 1.0", + deps: deps, + elixir_script: [ input: "src/exjs", output: "dest/js"], + compilers: [:elixir_script] ++ Mix.compilers + ] end + + Available options are: + * `input`: The folder to look for Elixirscript files in. (defaults to `lib/elixirscript`) + * `output`: The folder to place generated JavaScript code in. (defaults to `priv/elixirscript`) + * `format`: The module format of generated JavaScript code. (defaults to `:es`). + Choices are: + * `:es` - ES Modules + * `:common` - CommonJS + * `:umd` - UMD """ + @spec run(any()) :: :ok def run(_) do elixirscript_config = get_elixirscript_config() @@ -26,7 +36,8 @@ defmodule Mix.Tasks.Compile.ElixirScript do File.mkdir_p!(elixirscript_base) elixirscript_path = Path.join([elixirscript_base, "#{Mix.Project.config[:app]}"]) - input_path = Keyword.get(elixirscript_config, :input) + input_path = elixirscript_config + |> Keyword.get(:input) |> List.wrap |> Enum.map(fn(path) -> Path.absname(path) @@ -35,7 +46,8 @@ defmodule Mix.Tasks.Compile.ElixirScript do File.write!(elixirscript_path, input_path) - paths = Path.join([elixirscript_base, "*"]) + paths = [elixirscript_base, "*"] + |> Path.join() |> Path.wildcard |> Enum.map(fn(path) -> app = Path.basename(path) @@ -55,7 +67,8 @@ defmodule Mix.Tasks.Compile.ElixirScript do elixirscript_config = get_elixirscript_config() output_path = Keyword.get(elixirscript_config, :output) - File.ls!(output_path) + output_path + |> File.ls! |> Enum.each(fn(x) -> if String.contains?(Path.basename(x), "Elixir.") do File.rm!(Path.join(output_path, x)) diff --git a/lib/mix/tasks/elixirscript.ex b/lib/mix/tasks/elixirscript.ex index cc075cfb..7cfb3d33 100644 --- a/lib/mix/tasks/elixirscript.ex +++ b/lib/mix/tasks/elixirscript.ex @@ -1,4 +1,7 @@ defmodule Mix.Tasks.Elixirscript do + @moduledoc """ + A command-line interface to the elixirscript compiler + """ use Mix.Task @shortdoc "Translate Elixir to JavaScript" diff --git a/lib/mix/tasks/elixirscript.watch.ex b/lib/mix/tasks/elixirscript.watch.ex index a5695712..31d0e3de 100644 --- a/lib/mix/tasks/elixirscript.watch.ex +++ b/lib/mix/tasks/elixirscript.watch.ex @@ -8,16 +8,16 @@ defmodule Mix.Tasks.Elixirscript.Watch do Looks for the `elixir_script` key in your mix project config - def project do - [ - app: :my_app, - version: "0.1.0", - elixir: "~> 1.0", - deps: deps, - elixir_script: [ input: "src/exjs", output: "dest/js"], - compilers: [:elixir_script] ++ Mix.compilers - ] - end + def project do + [ + app: :my_app, + version: "0.1.0", + elixir: "~> 1.0", + deps: deps, + elixir_script: [ input: "src/exjs", output: "dest/js"], + compilers: [:elixir_script] ++ Mix.compilers + ] + end """ @@ -26,16 +26,35 @@ defmodule Mix.Tasks.Elixirscript.Watch do Mix.Task.run "app.start" elixirscript_config = get_elixirscript_config() - input_path = Keyword.fetch!(elixirscript_config, :input) - output_path = Keyword.fetch!(elixirscript_config, :output) - {:ok, _} = ElixirScript.Watcher.start_link(input_path, %{ output: output_path }) + input_path = Keyword.get(elixirscript_config, :input) + output_path = Keyword.get(elixirscript_config, :output) + format = Keyword.get(elixirscript_config, :format) + + {:ok, _} = ElixirScript.Watcher.start_link(input_path, %{output: output_path, format: format}) :timer.sleep :infinity end defp get_elixirscript_config() do config = Mix.Project.config - Keyword.fetch!(config, :elixir_script) + exjs_config = cond do + Keyword.has_key?(config, :elixir_script) -> + Keyword.get(config, :elixir_script, []) + Keyword.has_key?(config, :elixirscript) -> + Keyword.get(config, :elixirscript, []) + true -> + defaults() + end + + Keyword.merge(defaults(), exjs_config) + end + + defp defaults() do + [ + input: "lib/elixirscript", + output: "priv/elixirscript", + format: :es + ] end end diff --git a/lib/elixir_script/prelude/agent.ex b/lib/std_lib/agent.ex similarity index 100% rename from lib/elixir_script/prelude/agent.ex rename to lib/std_lib/agent.ex diff --git a/lib/elixir_script/prelude/atom.ex b/lib/std_lib/atom.ex similarity index 100% rename from lib/elixir_script/prelude/atom.ex rename to lib/std_lib/atom.ex diff --git a/lib/elixir_script/prelude/base.ex b/lib/std_lib/base.ex similarity index 100% rename from lib/elixir_script/prelude/base.ex rename to lib/std_lib/base.ex diff --git a/lib/elixir_script/prelude/bitwise.ex b/lib/std_lib/bitwise.ex similarity index 100% rename from lib/elixir_script/prelude/bitwise.ex rename to lib/std_lib/bitwise.ex diff --git a/lib/elixir_script/prelude/collectable.ex b/lib/std_lib/collectable.ex similarity index 100% rename from lib/elixir_script/prelude/collectable.ex rename to lib/std_lib/collectable.ex diff --git a/lib/elixir_script/prelude/enumerable.ex b/lib/std_lib/enumerable.ex similarity index 100% rename from lib/elixir_script/prelude/enumerable.ex rename to lib/std_lib/enumerable.ex diff --git a/lib/elixir_script/prelude/integer.ex b/lib/std_lib/integer.ex similarity index 100% rename from lib/elixir_script/prelude/integer.ex rename to lib/std_lib/integer.ex diff --git a/lib/elixir_script/prelude/js.ex b/lib/std_lib/js.ex similarity index 100% rename from lib/elixir_script/prelude/js.ex rename to lib/std_lib/js.ex diff --git a/lib/elixir_script/prelude/kernel.ex b/lib/std_lib/kernel.ex similarity index 100% rename from lib/elixir_script/prelude/kernel.ex rename to lib/std_lib/kernel.ex diff --git a/lib/elixir_script/prelude/keyword.ex b/lib/std_lib/keyword.ex similarity index 100% rename from lib/elixir_script/prelude/keyword.ex rename to lib/std_lib/keyword.ex diff --git a/lib/elixir_script/prelude/list.ex b/lib/std_lib/list.ex similarity index 100% rename from lib/elixir_script/prelude/list.ex rename to lib/std_lib/list.ex diff --git a/lib/elixir_script/prelude/macro/env.ex b/lib/std_lib/macro/env.ex similarity index 100% rename from lib/elixir_script/prelude/macro/env.ex rename to lib/std_lib/macro/env.ex diff --git a/lib/elixir_script/prelude/map.ex b/lib/std_lib/map.ex similarity index 100% rename from lib/elixir_script/prelude/map.ex rename to lib/std_lib/map.ex diff --git a/lib/elixir_script/prelude/map_set.ex b/lib/std_lib/map_set.ex similarity index 100% rename from lib/elixir_script/prelude/map_set.ex rename to lib/std_lib/map_set.ex diff --git a/lib/elixir_script/prelude/module.ex b/lib/std_lib/module.ex similarity index 100% rename from lib/elixir_script/prelude/module.ex rename to lib/std_lib/module.ex diff --git a/lib/elixir_script/prelude/range.ex b/lib/std_lib/range.ex similarity index 100% rename from lib/elixir_script/prelude/range.ex rename to lib/std_lib/range.ex diff --git a/lib/elixir_script/prelude/regex.ex b/lib/std_lib/regex.ex similarity index 94% rename from lib/elixir_script/prelude/regex.ex rename to lib/std_lib/regex.ex index c78facdc..1176b8ac 100644 --- a/lib/elixir_script/prelude/regex.ex +++ b/lib/std_lib/regex.ex @@ -1,9 +1,10 @@ defmodule ElixirScript.Regex do + @moduledoc false require JS def compile(source, options \\ "") do try do - {:ok, JS.new(RegExp, [source, options]) } + {:ok, JS.new(RegExp, [source, options])} rescue x -> {:error, x.message} diff --git a/lib/elixir_script/prelude/string.ex b/lib/std_lib/string.ex similarity index 100% rename from lib/elixir_script/prelude/string.ex rename to lib/std_lib/string.ex diff --git a/lib/elixir_script/prelude/string/chars.ex b/lib/std_lib/string/chars.ex similarity index 100% rename from lib/elixir_script/prelude/string/chars.ex rename to lib/std_lib/string/chars.ex diff --git a/lib/elixir_script/prelude/tuple.ex b/lib/std_lib/tuple.ex similarity index 100% rename from lib/elixir_script/prelude/tuple.ex rename to lib/std_lib/tuple.ex From 46a8fb0ab463dc4396ff8b4b273a5c1b9e37fc46 Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Sat, 18 Feb 2017 11:06:26 -0600 Subject: [PATCH 392/860] Update GettingStarted.md --- GettingStarted.md | 177 ++++++++++++++++----------------------- lib/elixir_script/cli.ex | 3 +- 2 files changed, 73 insertions(+), 107 deletions(-) diff --git a/GettingStarted.md b/GettingStarted.md index 0c2c9c92..3691d4ea 100644 --- a/GettingStarted.md +++ b/GettingStarted.md @@ -1,120 +1,96 @@ # Getting Started with ElixirScript +The intent of this guide is to get you started with ElixirScript. It will give you instructions on using ElixirScript. I will go over the two ways you can use Elixirscript: -The intent of this guide is to get you started with ElixirScript. It will give you instructions on using ElixirScript. I will go over the three ways you can use ElixirScript: +* As a CLI +* As a mix dependency -* As an escript -* As a mix task -* As a library in your application +### CLI -### Escript +**macOS**: Elixirscript is available via homebrew `brew install elixirscript`. For everyone else, please read below -**macOS**: Elixirscript can be installed via homebrew `brew install elixirscript`. For everyone else, plase read below +Step 1: Get CLI -* Step 1: Get escript +You can download the elixirscript CLI from the [releases page on github](https://github.com/bryanjos/elixirscript/releases). It is a tar file named elixirscript.tar.gz. - You can download the elixirscript escript from the [releases page on github](https://github.com/bryanjos/elixirscript/releases). It is a tar file named elixirscript.tar.gz. +Step 2: Untar -* Step 2: Untar +Next, untar elixirscript.tar.gz - Next, untar elixirscript.tar.gz - - ```bash tar -xvzf elixirscript.tar.gz - ``` - You will want to put the bin folder from the uncompressed folder into your path. This should allow you to use the elixirscript escript. +You will want to put the bin folder from the uncompressed folder into your path. This should allow you to use the elixirscript CLI. -* Step 3: Use +Step 3: Use - This is the help output of elixirscript +This is the help output of elixirscript - ```bash usage: elixirscript [options] - path to elixir files or the elixir code string if the -ex flag is used - - options: - -o --output [path] places output at the given path - -ex --elixir read input as elixir code string - --std-lib [path] outputs the elixirscript standard library JavaScript files to the specified path - --full-build informs the compiler to do a full build instead of an incremental one - only used when output is specified - --core-path es6 import path to the elixirscript standard lib - only used with the [output] option. When used, Elixir.js is not exported - -v --version the current version number - -h --help this message - ``` + path to elixir files or + the elixir code string if passed the -ex flag + options: + -f --format [format] module format of output. options: es (default), common, umd + -o --output [path] places output at the given path + -ex --elixir read input as elixir code string + --full-build informs the compiler to do a full build instead of an incremental one + --core-path import path to the elixirscript standard lib + only used with the [output] option. When used, Elixir.js is not exported + -v --version the current version number + -h --help this message + +the `` is the elixir code string or file path you want to convert from elixir to javascript. Below is an example of using a code string and turning it into JavaScript - the `` is the elixir code string or file path you want to convert from elixir to javascript. Below is an example of using a code string and turning it into JavaScript - - ```bash $ elixirscript ":atom" -ex - Symbol.for('atom') - ``` + Symbol.for('atom') - The elixirscript escript changed the elixir code, `:atom` into the JavaScript code `Symbol.for('atom')`. The `-ex` parameter lets the script know that the input is an Elixir code string instead of a file. +It changed the elixir code, `:atom` into the JavaScript code `Symbol.for('atom')`. The `-ex` parameter lets the script know that the input is an Elixir code string instead of a file. - elixirscript also takes a path to your `.ex` and `.exjs` files as well: +elixirscript also takes a path to your `.ex` files as well: - ```bash $ elixirscript "src" -o "dist" - ``` - If you look in the dist folder, you should see 2 folders. One, `app`, contains your code and the other, `elixir` contains the elixirscript standard library files. +If you look in the dist folder, you should see 2 folders. `app` contains your code and `elixir` contains the elixirscript standard library files. -### mix elixirscript +### Mix dependency -* Step 1: Get dependency +Adding Elixirscript to your mix project gives you the ability to add it to your list of mix compilers. This means when you `mix compile`, Elixirscript will compile your code as well. - The first step is getting the dependency. In your mix.exs file for your elixir project, add elixir_script to your deps. +Add dependency to your deps in mix.exs: ```elixir - {:elixir_script, "~> 0.23"} - ``` - -* Step 2: Now download the dep - - ```bash - $ mix deps.get - ``` - - Now you should have the mix task, elixirscript. - -* Step 3: Use - ```bash - $ mix elixirscript "src" -o "dist" + {:elixir_script, "~> 0.25"} ``` - What you will notice is that the parameters are exactly the same as the escript. + Elixirscript uses default input, output and module formats if options are not given. If you wish to change any or all options, add an `elixir_script` key to your project configuration. + + def project do + [ + app: :my_app, + version: "0.1.0", + elixir: "~> 1.0", + deps: deps, + elixir_script: [ input: "lib/elixirscript", output: "priv/elixirscript", format: :es], + compilers: [:elixir_script] ++ Mix.compilers + ] + end -### ElixirScript module -* Step 1: Get dependency +Available options are: - The first step is getting the dependency. In your mix.exs file for your elixir project, add elixir_script to your deps. +* `input`: The folder to look for Elixirscript files in. (defaults to `lib/elixirscript`) - ```elixir - {:elixir_script, "~> 0.23"} - ``` +* `output`: The folder to place generated JavaScript code in. (defaults to `priv/elixirscript`) -* Step 2: Now download the dep +* `format`: The module format of generated JavaScript code. (defaults to `:es`). Choices are:     - ```bash - $ mix deps.get - ``` + * `:es` - ES Modules -* Step 3: Use - Now you will be able to use the ElixirScript module within your code. - - ```elixir - ElixirScript.compile(":atom") - ``` - - The is also compile_path/2 and compile_quoted/2. Each of the functions take an options keyword list. + * `:common` - CommonJS + * `:umd` - UMD ### Macros -Macros can be used in Elixirscript just like in Elixir. The only exception is that `defmacrop` is unsupported +Elixirscript supports public macros. Private macros are currently unsupported. ### JavaScript Interop @@ -122,55 +98,46 @@ Elixirscript has a couple of ways of interacting with JavaScript. #### Globally scoped functions -To call functions in JavaScript in the global scope, such as those defined on `window`, use the erlang module syntax +Use the erlang module syntax, to call JavaScript functions in the global scope. -```elixir -# Calling alert -:window.alert("hi") + # Calling alert + :window.alert("hi") -# console -:console.log("hello") + # console + :console.log("hello") -# document -:document.getElementById("main") -``` + # document + :document.getElementById("main") #### Globally scoped modules -To call globally scoped modules defined in JavaScript, you can call them just like you would an Elixir module +You can call globally scoped modules you would an Elixir module -```elixir -Date.now() -``` + Date.now() Only works if module begins with a captial letter -#### Importing ES Modules +#### Importing Modules -To import ES modules, first you must require the `JS` module. Then import the module using `JS.import` +To import modules, first you must `require` the `JS` module. Then import the module using `JS.import` -```elixir -defmodule MyModule do - require JS - JS.import React, "react" + defmodule MyModule do + require JS + JS.import React, "react" - def func() do - React.render(my_component) + def func() do + React.render(my_component) + end end -end - -``` #### The JS module -The JS module has a number of other functions and macros. For more information, check out the docs. +The JS module has many other functions and macros. For more information, check out the docs. #### Frontend Project Boilerplate There is an [elixirscript frontend boilerplate project](https://github.com/bryanjos/elixirscript-project-boilerplate). This setup uses gulp and webpack to build and bundle assets. - #### ElixirScript-Brunch -There is an Brunch plugin, [ElixirScript-Brunch](https://www.npmjs.com/package/elixirscript-brunch). -There are instructions there on how to use it with Phoenix. +There is an Brunch plugin, [ElixirScript-Brunch](https://www.npmjs.com/package/elixirscript-brunch). There are instructions there on how to use it with Phoenix. \ No newline at end of file diff --git a/lib/elixir_script/cli.ex b/lib/elixir_script/cli.ex index 18efdeef..1a6e1c70 100644 --- a/lib/elixir_script/cli.ex +++ b/lib/elixir_script/cli.ex @@ -42,13 +42,12 @@ defmodule ElixirScript.CLI do """ usage: elixirscript [options] path to elixir files or - the elixir code string if the -ex flag is used + the elixir code string if passed the -ex flag options: -f --format [format] module format of output. options: es (default), common, umd -o --output [path] places output at the given path -ex --elixir read input as elixir code string --full-build informs the compiler to do a full build instead of an incremental one - only used when output is specified --core-path import path to the elixirscript standard lib only used with the [output] option. When used, Elixir.js is not exported -v --version the current version number From 5301252085b2bb0f505bc2200e33c3075ff27a1d Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Sat, 18 Feb 2017 11:13:49 -0600 Subject: [PATCH 393/860] Update estree dependency --- mix.exs | 2 +- mix.lock | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/mix.exs b/mix.exs index a1aa5964..5f2efe47 100644 --- a/mix.exs +++ b/mix.exs @@ -66,7 +66,7 @@ defmodule ElixirScript.Mixfile do def std_lib(_) do Mix.Task.run "app.start" - { _ , _ } = System.cmd("npm", ["run", "build"]) + {_ , _} = System.cmd("npm", ["run", "build"]) ElixirScript.compile_std_lib() end diff --git a/mix.lock b/mix.lock index 113af924..2020bc3f 100644 --- a/mix.lock +++ b/mix.lock @@ -2,7 +2,7 @@ "certifi": {:hex, :certifi, "0.7.0", "861a57f3808f7eb0c2d1802afeaae0fa5de813b0df0979153cbafcd853ababaf", [:rebar3], []}, "credo": {:hex, :credo, "0.6.1", "a941e2591bd2bd2055dc92b810c174650b40b8290459c89a835af9d59ac4a5f8", [:mix], [{:bunt, "~> 0.2.0", [hex: :bunt, optional: false]}]}, "earmark": {:hex, :earmark, "1.1.1", "433136b7f2e99cde88b745b3a0cfc3fbc81fe58b918a09b40fce7f00db4d8187", [:mix], []}, - "estree": {:hex, :estree, "2.5.0", "9776c1705a72dc5a0d56cdf431173c3e75f9e509278a857ec55374a49f5699ef", [:mix], []}, + "estree": {:hex, :estree, "2.5.1", "c93a8fa8a29886e6a6f6c489ba6dc949b998d2985b189967e41e69a92b58e846", [:mix], []}, "ex_doc": {:hex, :ex_doc, "0.14.5", "c0433c8117e948404d93ca69411dd575ec6be39b47802e81ca8d91017a0cf83c", [:mix], [{:earmark, "~> 1.0", [hex: :earmark, optional: false]}]}, "excoveralls": {:hex, :excoveralls, "0.6.2", "0e993d096f1fbb6e70a3daced5c89aac066bda6bce57829622aa2d1e2b338cfb", [:mix], [{:exjsx, "~> 3.0", [hex: :exjsx, optional: false]}, {:hackney, ">= 0.12.0", [hex: :hackney, optional: false]}]}, "exjsx": {:hex, :exjsx, "3.2.1", "1bc5bf1e4fd249104178f0885030bcd75a4526f4d2a1e976f4b428d347614f0f", [:mix], [{:jsx, "~> 2.8.0", [hex: :jsx, optional: false]}]}, From bdb59f0588798e85f032dad516464bc7b4a1af53 Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Sat, 18 Feb 2017 11:19:59 -0600 Subject: [PATCH 394/860] Updated changelog --- CHANGELOG.md | 15 ++++++++++----- lib/mix/tasks/compile.elixir_script.ex | 2 ++ 2 files changed, 12 insertions(+), 5 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 89cc5e31..d553fdc0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,11 +6,16 @@ and this project adheres to [Semantic Versioning](http://semver.org/). ## [0.25.0-dev] ### Added -- Updated elixir_script mix compiler to support compiling elixir_script paths in dependencies -- Add `Collectable` implementations -- Updated `for` implementation to use Collectable -- `format` option. Can now specify the module format of output. Choices are `es` (default), `umd`, or `common` -- Default input, output and format for elixirscript mix compiler +- Updated elixir_script mix compiler to support compiling elixir_script paths in dependencies if dependency has mix compiler defined as well +- Add `Collectable` protocol implementations +- Updated `for` implementation to use `Collectable` +- `format` option. Can now specify the module format of output. + Choices are: + * `:es` (default) for ES Modules + * `:umd` for UMD + * `:common` for CommonJS + +- Default input, output and format for elixirscript mix compiler. In a mix project by default the elixirscript compiler will look in `lib/elixirscript` and input and place output in `priv/elixirscript`. The default format is `:es` ### Removed - `receive` diff --git a/lib/mix/tasks/compile.elixir_script.ex b/lib/mix/tasks/compile.elixir_script.ex index b16f7cd4..b15496d1 100644 --- a/lib/mix/tasks/compile.elixir_script.ex +++ b/lib/mix/tasks/compile.elixir_script.ex @@ -25,6 +25,8 @@ defmodule Mix.Tasks.Compile.ElixirScript do * `:es` - ES Modules * `:common` - CommonJS * `:umd` - UMD + + The mix compiler will also compile any dependencies that have the elixirscript compiler in its mix compilers as well """ From e3631bfc7cd25af3e5915fbcc907696e5284ff44 Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Sat, 18 Feb 2017 19:19:08 -0600 Subject: [PATCH 395/860] Update github repo url --- mix.exs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/mix.exs b/mix.exs index 5f2efe47..afda7a38 100644 --- a/mix.exs +++ b/mix.exs @@ -10,7 +10,7 @@ defmodule ElixirScript.Mixfile do deps: deps(), description: description(), package: package(), - source_url: "https://github.com/bryanjos/elixirscript", + source_url: "https://github.com/elixirscript/elixirscript", aliases: aliases(), test_coverage: [tool: ExCoveralls], preferred_cli_env: [coveralls: :test], @@ -52,7 +52,7 @@ defmodule ElixirScript.Mixfile do maintainers: ["Bryan Joseph"], licenses: ["MIT"], links: %{ - "GitHub" => "https://github.com/bryanjos/elixirscript" + "GitHub" => "https://github.com/elixirscript/elixirscript" }, build_tools: ["mix"] ] From 3e64c59de4d9311142c481282716bcd6f540e05e Mon Sep 17 00:00:00 2001 From: The Gitter Badger Date: Sun, 19 Feb 2017 14:50:07 +0000 Subject: [PATCH 396/860] Add Gitter badge --- README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README.md b/README.md index ccb150c2..3e7e429f 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,7 @@ ## ElixirScript [![Documentation](https://img.shields.io/badge/docs-hexpm-blue.svg)](http://hexdocs.pm/elixir_script/) [![Build](https://travis-ci.org/bryanjos/elixirscript.svg?branch=master)](https://travis-ci.org/bryanjos/elixirscript) [![Deps Status](https://beta.hexfaktor.org/badge/all/github/bryanjos/elixirscript.svg)](https://beta.hexfaktor.org/github/bryanjos/elixirscript) +[![Join the chat at https://gitter.im/elixirscript/elixirscript](https://badges.gitter.im/elixirscript/elixirscript.svg)](https://gitter.im/elixirscript/elixirscript?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) + The goal is to convert a subset (or full set) of Elixir code to JavaScript, providing the ability to write JavaScript in Elixir. This is done by taking the Elixir AST and converting it into JavaScript AST and then to JavaScript code. This is done using the [Elixir-ESTree](https://github.com/bryanjos/elixir-estree) library. Requirements From c68277ce1a6d6f33d880da7e60d712caf98f69e6 Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Sun, 19 Feb 2017 09:03:21 -0600 Subject: [PATCH 397/860] Add gitter notifications to travis configuration --- .travis.yml | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index f43c7343..55de8f28 100644 --- a/.travis.yml +++ b/.travis.yml @@ -15,4 +15,11 @@ script: - mix deps.get - mix do std_lib, clean, compile - mix test - - npm test \ No newline at end of file + - npm test +notifications: + webhooks: + urls: + - https://webhooks.gitter.im/e/fbd8944d285c0696dc41 + on_success: always # options: [always|never|change] default: always + on_failure: always # options: [always|never|change] default: always + on_start: never # options: [always|never|change] default: always \ No newline at end of file From 06e423de77795e1a847b66149cd9020b9201875a Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Sun, 19 Feb 2017 12:19:57 -0600 Subject: [PATCH 398/860] Update version number for release --- CHANGELOG.md | 3 ++- README.md | 5 ++--- mix.exs | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index d553fdc0..c8b6f0a2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,7 +4,8 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](http://keepachangelog.com/) and this project adheres to [Semantic Versioning](http://semver.org/). -## [0.25.0-dev] +## [0.25.0] - 2017-02-19 + ### Added - Updated elixir_script mix compiler to support compiling elixir_script paths in dependencies if dependency has mix compiler defined as well - Add `Collectable` protocol implementations diff --git a/README.md b/README.md index 3e7e429f..fa0f2325 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,4 @@ -## ElixirScript [![Documentation](https://img.shields.io/badge/docs-hexpm-blue.svg)](http://hexdocs.pm/elixir_script/) [![Build](https://travis-ci.org/bryanjos/elixirscript.svg?branch=master)](https://travis-ci.org/bryanjos/elixirscript) [![Deps Status](https://beta.hexfaktor.org/badge/all/github/bryanjos/elixirscript.svg)](https://beta.hexfaktor.org/github/bryanjos/elixirscript) - -[![Join the chat at https://gitter.im/elixirscript/elixirscript](https://badges.gitter.im/elixirscript/elixirscript.svg)](https://gitter.im/elixirscript/elixirscript?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) +## ElixirScript [![Documentation](https://img.shields.io/badge/docs-hexpm-blue.svg)](http://hexdocs.pm/elixir_script/) [![Build](https://travis-ci.org/bryanjos/elixirscript.svg?branch=master)](https://travis-ci.org/bryanjos/elixirscript) [![Deps Status](https://beta.hexfaktor.org/badge/all/github/bryanjos/elixirscript.svg)](https://beta.hexfaktor.org/github/bryanjos/elixirscript) [![Join the chat at https://gitter.im/elixirscript/elixirscript](https://badges.gitter.im/elixirscript/elixirscript.svg)](https://gitter.im/elixirscript/elixirscript?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) The goal is to convert a subset (or full set) of Elixir code to JavaScript, providing the ability to write JavaScript in Elixir. This is done by taking the Elixir AST and converting it into JavaScript AST and then to JavaScript code. This is done using the [Elixir-ESTree](https://github.com/bryanjos/elixir-estree) library. @@ -56,6 +54,7 @@ to the path to look in and then do a clean build. Communication ======== +[gitter room](https://gitter.im/elixirscript/elixirscript) [#elixirscript](https://elixir-lang.slack.com/messages/elixirscript/) on the elixir-lang Slack Contributing diff --git a/mix.exs b/mix.exs index afda7a38..cf432b2b 100644 --- a/mix.exs +++ b/mix.exs @@ -4,7 +4,7 @@ defmodule ElixirScript.Mixfile do def project do [ app: :elixir_script, - version: "0.25.0-dev", + version: "0.25.0", elixir: "~> 1.0", escript: escript_config(), deps: deps(), From d5d72b1ed5234e23515f80d561d2c489bd425869 Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Mon, 20 Feb 2017 13:11:19 -0600 Subject: [PATCH 399/860] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index fa0f2325..f4e9702f 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -## ElixirScript [![Documentation](https://img.shields.io/badge/docs-hexpm-blue.svg)](http://hexdocs.pm/elixir_script/) [![Build](https://travis-ci.org/bryanjos/elixirscript.svg?branch=master)](https://travis-ci.org/bryanjos/elixirscript) [![Deps Status](https://beta.hexfaktor.org/badge/all/github/bryanjos/elixirscript.svg)](https://beta.hexfaktor.org/github/bryanjos/elixirscript) [![Join the chat at https://gitter.im/elixirscript/elixirscript](https://badges.gitter.im/elixirscript/elixirscript.svg)](https://gitter.im/elixirscript/elixirscript?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) +## ElixirScript [![Documentation](https://img.shields.io/badge/docs-hexpm-blue.svg)](http://hexdocs.pm/elixir_script/) [![Build](https://travis-ci.org/elixirscript/elixirscript.svg?branch=master)](https://travis-ci.org/elixirscript/elixirscript) [![Deps Status](https://beta.hexfaktor.org/badge/all/github/bryanjos/elixirscript.svg)](https://beta.hexfaktor.org/github/bryanjos/elixirscript) [![Join the chat at https://gitter.im/elixirscript/elixirscript](https://badges.gitter.im/elixirscript/elixirscript.svg)](https://gitter.im/elixirscript/elixirscript?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) The goal is to convert a subset (or full set) of Elixir code to JavaScript, providing the ability to write JavaScript in Elixir. This is done by taking the Elixir AST and converting it into JavaScript AST and then to JavaScript code. This is done using the [Elixir-ESTree](https://github.com/bryanjos/elixir-estree) library. From 0ebb9fcfbcb0d8a18988ac9ca909fb496a090776 Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Mon, 20 Feb 2017 17:05:51 -0600 Subject: [PATCH 400/860] Add support for multiple when expressions --- CHANGELOG.md | 5 +++ .../translator/kernel/special_forms/fn.ex | 32 ++++++++++++++----- mix.exs | 2 +- test/translator/case_test.exs | 24 ++++++++++++++ test/translator/function_test.exs | 18 +++++++++++ 5 files changed, 72 insertions(+), 9 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index c8b6f0a2..88fcdde3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,11 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](http://keepachangelog.com/) and this project adheres to [Semantic Versioning](http://semver.org/). +## [0.26.0] - Unreleased + +### Added +- Support for multiple when clauses in guards + ## [0.25.0] - 2017-02-19 ### Added diff --git a/lib/elixir_script/translator/kernel/special_forms/fn.ex b/lib/elixir_script/translator/kernel/special_forms/fn.ex index d9c34886..ab66ef7c 100644 --- a/lib/elixir_script/translator/kernel/special_forms/fn.ex +++ b/lib/elixir_script/translator/kernel/special_forms/fn.ex @@ -20,17 +20,17 @@ defmodule ElixirScript.Translator.Function do def make_anonymous_function(functions, env, name) do clauses = functions |> Enum.map(fn - ({:->, _, [ [{:when, _, params}], body ]}) -> - guards = List.last(params) |> List.wrap + ({:->, _, [[{:when, _, params}], body ]}) -> + guards = List.last(params) params = params |> Enum.reverse |> tl |> Enum.reverse process_function_body(params, body, env, name, guards) ({:->, _, [params, body]}) -> process_function_body(params, body, env, name) - ({_, _, [{:when, _, [{_, _, params} | guards]}, body]}) -> + ({_, _, [{:when, _, [{_, _, params}, guards]}, body]}) -> body = convert_to_try(body) - process_function_body(params, body, env, name, guards) + process_function_body(params, body, env, name, guards) ({_, _, [{_, _, params}, body]}) -> body = convert_to_try(body) @@ -78,10 +78,18 @@ defmodule ElixirScript.Translator.Function do {body, _} = make_function_body(body, env) if guards do - {guard_body, _} = guards - |> List.wrap - |> hd - |> prepare_function_body(%{env | context: :guard}) + guards = case guards do + {:when, _, whens} -> + whens + wh -> + List.wrap(wh) + end + + guards = guards + |> Enum.reverse + |> process_guards + + {guard_body, _} = prepare_function_body(guards, %{env | context: :guard}) guard_body = JS.block_statement(guard_body) make_function_clause(patterns, params, body, guard_body, env.context == :generator) @@ -90,6 +98,14 @@ defmodule ElixirScript.Translator.Function do end end + defp process_guards([guard]) do + guard + end + + defp process_guards([head | tail]) do + {:or, [], [process_guards(tail), head]} + end + defp wrap_params(params) when is_atom(params), do: [] defp wrap_params(params), do: List.wrap(params) diff --git a/mix.exs b/mix.exs index cf432b2b..a8275289 100644 --- a/mix.exs +++ b/mix.exs @@ -4,7 +4,7 @@ defmodule ElixirScript.Mixfile do def project do [ app: :elixir_script, - version: "0.25.0", + version: "0.26.0-dev", elixir: "~> 1.0", escript: escript_config(), deps: deps(), diff --git a/test/translator/case_test.exs b/test/translator/case_test.exs index 6a1477b6..c54250ae 100644 --- a/test/translator/case_test.exs +++ b/test/translator/case_test.exs @@ -84,6 +84,30 @@ defmodule ElixirScript.Translator.Case.Test do assert_translation(ex_ast, js_code) end + test "translate case with multiple guards" do + ex_ast = quote do + case data do + number when number in [1,2,3,4] when number in [4, 3, 2, 1] -> + value = 13 + _ -> + true + end + end + + js_code = """ + Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.clause([Elixir.Core.Patterns.variable()],function(number) { + let [value] = Elixir.Core.Patterns.match(Elixir.Core.Patterns.variable(),13); + return value; + },function(number) { + return Elixir.Core.Functions.contains(number,Object.freeze([1, 2, 3, 4])) || Elixir.Core.Functions.contains(number,Object.freeze([4, 3, 2, 1])); + }),Elixir.Core.Patterns.clause([Elixir.Core.Patterns.wildcard()],function() { + return true; + })).call(this,data) + """ + + assert_translation(ex_ast, js_code) + end + test "translate case with multiple statements in body" do ex_ast = quote do case data do diff --git a/test/translator/function_test.exs b/test/translator/function_test.exs index cbeeb62f..029ee11d 100644 --- a/test/translator/function_test.exs +++ b/test/translator/function_test.exs @@ -842,4 +842,22 @@ defmodule ElixirScript.Translator.Function.Test do assert_translation(ex_ast, js_code) end + + test "multiple when guards" do + ex_ast = quote do + def something(one) when is_number(one) when is_atom(one) do + end + end + + + js_code = """ + const something = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.clause([Elixir.Core.Patterns.variable()],function(one) { + return null; + },function(one) { + return Elixir$ElixirScript$Kernel.is_number(one) || Elixir$ElixirScript$Kernel.is_atom(one); + })); + """ + + assert_translation(ex_ast, js_code) + end end From 94fdb1a7af832c49e398e013f00b66b9c0aa930b Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Mon, 20 Feb 2017 17:35:58 -0600 Subject: [PATCH 401/860] Add support for defdelegate --- CHANGELOG.md | 3 +- lib/elixir_script/passes/find_functions.ex | 59 ++++++++++++++-------- lib/elixir_script/translator.ex | 4 ++ lib/elixir_script/translator/kernel/def.ex | 22 ++++++++ test/translator/defdelegate_test.exs | 28 ++++++++++ 5 files changed, 94 insertions(+), 22 deletions(-) create mode 100644 test/translator/defdelegate_test.exs diff --git a/CHANGELOG.md b/CHANGELOG.md index 88fcdde3..fd131a0c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,7 +7,8 @@ and this project adheres to [Semantic Versioning](http://semver.org/). ## [0.26.0] - Unreleased ### Added -- Support for multiple when clauses in guards +- Multiple `when` clauses in guards +- Kernel.defdelegate/2 ## [0.25.0] - 2017-02-19 diff --git a/lib/elixir_script/passes/find_functions.ex b/lib/elixir_script/passes/find_functions.ex index d4ca8581..f78e2d38 100644 --- a/lib/elixir_script/passes/find_functions.ex +++ b/lib/elixir_script/passes/find_functions.ex @@ -5,9 +5,17 @@ defmodule ElixirScript.Passes.FindFunctions do def execute(data, _) do new_data = Enum.map(data.data, fn { module_name, module_data } -> - %{def: functions, defp: private_functions, defgen: generators, defgenp: private_generators, defmacro: macros, defmacrop: private_macros } = get_functions_from_module(module_data.ast) - - module_data = Map.put(module_data, :functions, functions ++ generators) + %{ + def: functions, + defp: private_functions, + defgen: generators, + defgenp: private_generators, + defmacro: macros, + defmacrop: private_macros, + defdelegate: delegates + } = get_functions_from_module(module_data.ast) + + module_data = Map.put(module_data, :functions, functions ++ generators ++ delegates) |> Map.put(:private_functions, private_functions ++ private_generators) |> Map.put(:macros, macros) |> Map.put(:private_macros, private_macros) @@ -21,40 +29,49 @@ defmodule ElixirScript.Passes.FindFunctions do defp get_functions_from_module({:__block__, _, list}) do Enum.reduce(list, new_function_map(), fn ({type, _, [{:when, _, [{name, _, params} | _guards] }, _] }, state) when type in @function_types and is_atom(params) -> - arity = 0 - - add_function_to_map(state, type, name, arity) + arity = 0 + add_function_to_map(state, type, name, arity) ({type, _, [{:when, _, [{name, _, params} | _guards] }, _] }, state) when type in @function_types -> - arity = if is_nil(params), do: 0, else: length(params) - - add_function_to_map(state, type, name, arity) + arity = if is_nil(params), do: 0, else: length(params) + add_function_to_map(state, type, name, arity) ({type, _, [{name, _, params}, _]}, state) when type in @function_types and is_atom(params) -> - arity = 0 - - add_function_to_map(state, type, name, arity) + arity = 0 + add_function_to_map(state, type, name, arity) ({type, _, [{name, _, params}, _]}, state) when type in @function_types -> - arity = if is_nil(params), do: 0, else: length(params) + arity = if is_nil(params), do: 0, else: length(params) add_function_to_map(state, type, name, arity) ({type, _, [{name, _, params}]}, state) when is_atom(params) and type in @function_types -> - arity = 0 - add_function_to_map(state, type, name, arity) + arity = 0 + add_function_to_map(state, type, name, arity) ({type, _, [{name, _, params}]}, state) when type in @function_types -> - arity = length(params) - add_function_to_map(state, type, name, arity) + arity = length(params) + add_function_to_map(state, type, name, arity) + + ({:defdelegate, _, [{name, _, params}], _}, state) -> + arity = length(params) + add_function_to_map(state, :defdelegate, name, arity) - _, state -> - state + _, state -> + state end) end defp new_function_map() do - %{ def: Keyword.new, defp: Keyword.new, defgen: Keyword.new, defgenp: Keyword.new, defmacro: Keyword.new, defmacrop: Keyword.new } + %{ + def: Keyword.new, + defp: Keyword.new, + defgen: Keyword.new, + defgenp: Keyword.new, + defmacro: Keyword.new, + defmacrop: Keyword.new, + defdelegate: Keyword.new + } end defp get_functions_from_module(_) do @@ -72,4 +89,4 @@ defmodule ElixirScript.Passes.FindFunctions do end -end +end \ No newline at end of file diff --git a/lib/elixir_script/translator.ex b/lib/elixir_script/translator.ex index 9be13020..3e6eaa52 100644 --- a/lib/elixir_script/translator.ex +++ b/lib/elixir_script/translator.ex @@ -499,6 +499,10 @@ defmodule ElixirScript.Translator do Def.process_function(name, [ast], env) end + defp do_translate({:defdelegate, _, [{name, _, params}, options]}, env) do + Def.process_delegate(name, params, options, env) + end + defp do_translate({:defstruct, _, attributes}, env) do { Struct.make_defstruct(attributes, env), env } end diff --git a/lib/elixir_script/translator/kernel/def.ex b/lib/elixir_script/translator/kernel/def.ex index 5f6f1c45..6fee1fb1 100644 --- a/lib/elixir_script/translator/kernel/def.ex +++ b/lib/elixir_script/translator/kernel/def.ex @@ -3,6 +3,7 @@ defmodule ElixirScript.Translator.Def do alias ESTree.Tools.Builder, as: JS alias ElixirScript.Translator.Function alias ElixirScript.Translator.Identifier + alias ElixirScript.Translator def process_function(name, functions, env) do { result, _ } = Function.make_anonymous_function(functions, env, name) @@ -14,4 +15,25 @@ defmodule ElixirScript.Translator.Def do { JS.variable_declaration([declarator], :const), env } end + + def process_delegate(name, params, options, env) do + translated_params = Enum.map(params, &Translator.translate!(&1, env)) + to = options[:to] + as = options[:as] || name + + function = JS.function_expression(translated_params, [], + JS.block_statement([ + JS.return_statement( + Translator.translate!({{:., [], [to, as]}, [], params}, env) + ) + ]) + ) + + declarator = JS.variable_declarator( + Identifier.make_identifier(name), + function + ) + + { JS.variable_declaration([declarator], :const), env } + end end diff --git a/test/translator/defdelegate_test.exs b/test/translator/defdelegate_test.exs new file mode 100644 index 00000000..f71c0d23 --- /dev/null +++ b/test/translator/defdelegate_test.exs @@ -0,0 +1,28 @@ +defmodule ElixirScript.Translator.Defdelegate.Test do + use ExUnit.Case + import ElixirScript.TestHelper + + test "translate defdelegate" do + ex_ast = quote do: defdelegate reverse(list), to: :lists + + js_code = """ + const reverse = function(list) { + return Elixir.Core.Functions.reverse(list); + }; + """ + + assert_translation(ex_ast, js_code) + end + + test "translate defdelegate as another name" do + ex_ast = quote do: defdelegate other_reverse(list), to: :lists, as: :reverse + + js_code = """ + const other_reverse = function(list) { + return Elixir.Core.Functions.reverse(list); + }; + """ + + assert_translation(ex_ast, js_code) + end +end \ No newline at end of file From 21971744da2fd9258c203237b6a34657ddbdbfdb Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Mon, 20 Feb 2017 21:07:53 -0600 Subject: [PATCH 402/860] Add create js modules pass --- lib/elixir_script.ex | 3 + lib/elixir_script/module_systems/common.ex | 16 +++-- lib/elixir_script/module_systems/es.ex | 16 +++-- lib/elixir_script/module_systems/umd.ex | 16 +++-- .../passes/consolidate_protocols.ex | 25 +++----- lib/elixir_script/passes/create_js_modules.ex | 63 +++++++++++++++++++ lib/elixir_script/passes/java_script_ast.ex | 2 +- lib/elixir_script/passes/java_script_code.ex | 2 +- .../translator/kernel/defimpl.ex | 11 ++-- .../translator/kernel/defmodule.ex | 57 +++++++++++++++-- .../translator/kernel/defprotocol.ex | 14 ++++- lib/elixir_script/translator/state.ex | 1 + 12 files changed, 167 insertions(+), 59 deletions(-) create mode 100644 lib/elixir_script/passes/create_js_modules.ex diff --git a/lib/elixir_script.ex b/lib/elixir_script.ex index fd0020d6..7a19180a 100644 --- a/lib/elixir_script.ex +++ b/lib/elixir_script.ex @@ -81,6 +81,7 @@ defmodule ElixirScript do |> ElixirScript.Passes.AddStdLib.execute(opts) |> ElixirScript.Passes.JavaScriptAST.execute(opts) |> ElixirScript.Passes.ConsolidateProtocols.execute(opts) + |> ElixirScript.Passes.CreateJSModules.execute(opts) |> ElixirScript.Passes.JavaScriptCode.execute(opts) |> ElixirScript.Passes.JavaScriptName.execute(opts) |> ElixirScript.Passes.HandleOutput.execute(opts) @@ -159,6 +160,7 @@ defmodule ElixirScript do |> ElixirScript.Passes.AddStdLib.execute(opts) |> ElixirScript.Passes.JavaScriptAST.execute(opts) |> ElixirScript.Passes.ConsolidateProtocols.execute(opts) + |> ElixirScript.Passes.CreateJSModules.execute(opts) |> ElixirScript.Passes.JavaScriptCode.execute(opts) |> ElixirScript.Passes.JavaScriptName.execute(opts) |> ElixirScript.Passes.HandleOutput.execute(opts) @@ -197,6 +199,7 @@ defmodule ElixirScript do |> ElixirScript.Passes.FindFunctions.execute(opts) |> ElixirScript.Passes.JavaScriptAST.execute(opts) |> ElixirScript.Passes.ConsolidateProtocols.execute(opts) + |> ElixirScript.Passes.CreateJSModules.execute(opts) |> ElixirScript.Passes.JavaScriptCode.execute(opts) |> ElixirScript.Passes.JavaScriptName.execute(opts) |> ElixirScript.Passes.HandleOutput.execute(opts) diff --git a/lib/elixir_script/module_systems/common.ex b/lib/elixir_script/module_systems/common.ex index 05868410..da8e2b6d 100644 --- a/lib/elixir_script/module_systems/common.ex +++ b/lib/elixir_script/module_systems/common.ex @@ -5,22 +5,20 @@ defmodule ElixirScript.ModuleSystems.Common do alias ElixirScript.Translator.State alias ElixirScript.Translator.Utils - def build(body, exports, env) do - js_module_refs = State.get_javascript_module_references(env.state, env.module) - std_import = make_std_lib_import(env) - module_refs = State.get_module_references(env.state, env.module) -- [env.module] - |> module_imports_to_js_imports(env) + def build(std_import, imports, js_imports, body, exports, env) do + module_imports = Enum.map(imports, fn {module, path} -> import_module(module, path) end) - imports = js_module_refs ++ std_import + imports = js_imports ++ List.wrap(std_import) |> Enum.map(fn + {module, path} -> import_module(module, path, env) {module, path, true} -> import_module(module, path, env) {module, path, false} -> import_namespace_module(module, path, env) end) - imports = Enum.uniq(imports ++ module_refs) + imports = Enum.uniq(imports ++ module_imports) - export = export_module(exports) - imports ++ body ++ [export] + export = if is_nil(exports), do: [], else: [export_module(exports)] + imports ++ body ++ export end defp module_imports_to_js_imports(module_refs, env) do diff --git a/lib/elixir_script/module_systems/es.ex b/lib/elixir_script/module_systems/es.ex index b4bc0c63..4845fbf7 100644 --- a/lib/elixir_script/module_systems/es.ex +++ b/lib/elixir_script/module_systems/es.ex @@ -5,22 +5,20 @@ defmodule ElixirScript.ModuleSystems.ES do alias ElixirScript.Translator.State alias ElixirScript.Translator.Utils - def build(body, exports, env) do - js_module_refs = State.get_javascript_module_references(env.state, env.module) - std_import = make_std_lib_import(env) - module_refs = State.get_module_references(env.state, env.module) -- [env.module] - |> module_imports_to_js_imports(env) + def build(std_import, imports, js_imports, body, exports, env) do + module_imports = Enum.map(imports, fn {module, path} -> import_module(module, path) end) - imports = js_module_refs ++ std_import + imports = js_imports ++ List.wrap(std_import) |> Enum.map(fn + {module, path} -> import_module(module, path, env) {module, path, true} -> import_module(module, path, env) {module, path, false} -> import_namespace_module(module, path, env) end) - imports = Enum.uniq(imports ++ module_refs) + imports = Enum.uniq(imports ++ module_imports) - export = export_module(exports) - imports ++ body ++ [export] + export = if is_nil(exports), do: [], else: [export_module(exports)] + imports ++ body ++ export end defp module_imports_to_js_imports(module_refs, env) do diff --git a/lib/elixir_script/module_systems/umd.ex b/lib/elixir_script/module_systems/umd.ex index eabd5de0..2a492638 100644 --- a/lib/elixir_script/module_systems/umd.ex +++ b/lib/elixir_script/module_systems/umd.ex @@ -5,22 +5,19 @@ defmodule ElixirScript.ModuleSystems.UMD do alias ElixirScript.Translator.State alias ElixirScript.Translator.Utils - def build(body, exports, env) do - js_module_refs = State.get_javascript_module_references(env.state, env.module) - std_import = make_std_lib_import(env) - module_refs = State.get_module_references(env.state, env.module) -- [env.module] - |> module_imports_to_js_imports(env) + def build(std_import, imports, js_imports, body, exports, env) do + module_imports = Enum.map(imports, fn {module, path} -> import_module(module, path) end) - imports = js_module_refs ++ std_import + imports = js_imports ++ List.wrap(std_import) |> Enum.map(fn + {module, path} -> import_module(module, path, env) {module, path, true} -> import_module(module, path, env) {module, path, false} -> import_namespace_module(module, path, env) end) - imports = Enum.uniq(imports ++ module_refs) + imports = Enum.uniq(imports ++ module_imports) export = export_module(exports) - List.wrap(make_umd(imports, body, export)) end @@ -66,6 +63,7 @@ defmodule ElixirScript.ModuleSystems.UMD do def make_umd(imports, body, exports) do import_paths = Enum.map(imports, fn({_, path}) -> path end) import_identifiers = Enum.map(imports, fn({id, _}) -> id end) + exports = if is_nil(exports), do: [], else: [JS.return_statement(exports)] JS.expression_statement( JS.call_expression( @@ -134,7 +132,7 @@ defmodule ElixirScript.ModuleSystems.UMD do ) ) ])), - [JS.this_expression(), JS.function_expression(import_identifiers, [], JS.block_statement(body ++ [JS.return_statement(exports)]))] + [JS.this_expression(), JS.function_expression(import_identifiers, [], JS.block_statement(body ++ exports))] ) ) end diff --git a/lib/elixir_script/passes/consolidate_protocols.ex b/lib/elixir_script/passes/consolidate_protocols.ex index 6ad87e26..fb73c772 100644 --- a/lib/elixir_script/passes/consolidate_protocols.ex +++ b/lib/elixir_script/passes/consolidate_protocols.ex @@ -67,13 +67,11 @@ defmodule ElixirScript.Passes.ConsolidateProtocols do app_name = protocol.app - imports = [compiler_opts.module_formatter.import_module(:Elixir, Utils.make_local_file_path(:elixir, compiler_opts.core_path, compiler_opts.root, nil))] - defimpl_imports = Enum.map(implementations, fn({_, impl_data}) -> x = Atom.to_string(Utils.quoted_to_name(impl_data.for)) x = String.to_atom(protocol_name <> ".DefImpl." <> x) name = Utils.name_to_js_name(x) - compiler_opts.module_formatter.import_module(name, Utils.make_local_file_path(impl_data.app, Utils.name_to_js_file_name(x), compiler_opts.root, nil)) + {name, Utils.make_local_file_path(impl_data.app, Utils.name_to_js_file_name(x), compiler_opts.root, nil)} end) body = Enum.map(implementations, fn({_, impl_data}) -> @@ -89,25 +87,18 @@ defmodule ElixirScript.Passes.ConsolidateProtocols do ) end) - imports = imports ++ defimpl_imports + imports = defimpl_imports body = [declaration] ++ body - exports = compiler_opts.module_formatter.export_module(JS.identifier("impls")) - - body = case compiler_opts.format do - :umd -> - compiler_opts.module_formatter.make_umd( - imports, - body, - exports - ) - _ -> - imports ++ body ++ [exports] - end module_name = String.to_atom(protocol_name <> ".DefImpl") module_data = %{ + name: name, module: String.to_atom(protocol_name <> ".DefImpl"), - javascript_ast: List.wrap(body), + std_lib: {:Elixir, Utils.make_local_file_path(:elixir, compiler_opts.core_path, compiler_opts.root, nil)}, + js_imports: [], + imports: imports, + body: List.wrap(body), + exports: JS.identifier("impls"), app: app_name, type: :consolidated, protocol: name diff --git a/lib/elixir_script/passes/create_js_modules.ex b/lib/elixir_script/passes/create_js_modules.ex new file mode 100644 index 00000000..a896cf8c --- /dev/null +++ b/lib/elixir_script/passes/create_js_modules.ex @@ -0,0 +1,63 @@ +defmodule ElixirScript.Passes.CreateJSModules do + @moduledoc false + alias ElixirScript.Translator.Utils + + def execute(compiler_data, opts) do + parent = self + + data = Enum.map(compiler_data.data, fn({module_name, module_data}) -> + + spawn_link fn -> + module_data = compile(module_data, opts, compiler_data.state) + result = {module_name, module_data} + send parent, {self, result } + end + + end) + |> Enum.map(fn pid -> + receive do + {^pid, result} -> + result + end + end) + + %{ compiler_data | data: data } + end + + defp compile(%{load_only: true} = module_data, opts, state) do + module_data + end + + defp compile(%{type: :consolidated} = module_data, opts, state) do + js_module = module_data + env = ElixirScript.Translator.LexicalScope.module_scope(module_data.name, Utils.name_to_js_file_name(module_data.name) <> ".js", opts.env, state, opts) + + ast = opts.module_formatter.build( + js_module.std_lib, + js_module.imports, + js_module.js_imports, + js_module.body, + js_module.exports, + env + ) + + Map.put(module_data, :javascript_ast, ast) + end + + defp compile(module_data, opts, state) do + js_module = module_data.javascript_module + env = js_module.env + + ast = opts.module_formatter.build( + js_module.std_lib, + js_module.imports, + js_module.js_imports, + js_module.body, + js_module.exports, + env + ) + + Map.put(module_data, :javascript_ast, ast) + end + +end diff --git a/lib/elixir_script/passes/java_script_ast.ex b/lib/elixir_script/passes/java_script_ast.ex index 3b31088f..c27db835 100644 --- a/lib/elixir_script/passes/java_script_ast.ex +++ b/lib/elixir_script/passes/java_script_ast.ex @@ -47,6 +47,6 @@ defmodule ElixirScript.Passes.JavaScriptAST do ElixirScript.Translator.Defimpl.make(module_data.name, module_data.for, module_data.ast, env) end - Map.put(module_data, :javascript_ast, module.body) + Map.put(module_data, :javascript_module, module) end end diff --git a/lib/elixir_script/passes/java_script_code.ex b/lib/elixir_script/passes/java_script_code.ex index 8d8e00de..2381fcd8 100644 --- a/lib/elixir_script/passes/java_script_code.ex +++ b/lib/elixir_script/passes/java_script_code.ex @@ -30,7 +30,7 @@ defmodule ElixirScript.Passes.JavaScriptCode do defp compile(module_data) do - js_ast = Builder.program(module_data.javascript_ast) + js_ast = Builder.program(List.wrap(module_data.javascript_ast)) js_code = js_ast |> prepare_js_ast diff --git a/lib/elixir_script/translator/kernel/defimpl.ex b/lib/elixir_script/translator/kernel/defimpl.ex index b405e47f..2c4c45ae 100644 --- a/lib/elixir_script/translator/kernel/defimpl.ex +++ b/lib/elixir_script/translator/kernel/defimpl.ex @@ -8,7 +8,7 @@ defmodule ElixirScript.Translator.Defimpl do def make(name, type, body, env) do type = map_to_js(type, env) - {body, export} = Defmodule.process_module(name, body, env) + {imports, js_imports, body, export} = Defmodule.process_module(name, body, env) protocol_name = Atom.to_string(name) |> String.split(".DefImpl.") |> hd |> String.to_atom @@ -23,13 +23,16 @@ defmodule ElixirScript.Translator.Defimpl do ) ]) - body = env.module_formatter.build(body, export, env) - %{ name: Utils.quoted_to_name({:__aliases__, [], name }), + std_lib: Defmodule.make_std_lib_import(env), + imports: imports, + js_imports: js_imports, + exports: export, body: body, app_name: State.get_module(env.state, name).app, - protocol: protocol_name + protocol: protocol_name, + env: env } end diff --git a/lib/elixir_script/translator/kernel/defmodule.ex b/lib/elixir_script/translator/kernel/defmodule.ex index 0b6770f5..e013da2c 100644 --- a/lib/elixir_script/translator/kernel/defmodule.ex +++ b/lib/elixir_script/translator/kernel/defmodule.ex @@ -10,22 +10,44 @@ defmodule ElixirScript.Translator.Defmodule do def make_module(ElixirScript.Temp, body, env) do { body, _ } = translate_body(body, env) - %{ name: ElixirScript.Temp, body: body |> Group.inflate_groups, app_name: ElixirScript.Translator.State.get(env.state).compiler_opts.app } + %{ + name: ElixirScript.Temp, + std_lib: make_std_lib_import(env), + js_imports: [], + imports: [], + body: body |> Group.inflate_groups, + exports: nil, + app_name: ElixirScript.Translator.State.get(env.state).compiler_opts.app, + env: env + } end def make_module(module, nil, env) do - %{ name: module, body: [], app_name: ElixirScript.Translator.State.get(env.state).compiler_opts.app } + %{ + name: module, + std_lib: make_std_lib_import(env), + js_imports: [], + imports: [], + body: [], + exports: nil, + app_name: ElixirScript.Translator.State.get(env.state).compiler_opts.app, + env: env + } end def make_module(module, body, env) do - {body, exported_object} = process_module(module, body, env) - body = env.module_formatter.build(body, exported_object, env) + {imports, js_imports, body, exported_object} = process_module(module, body, env) app_name = State.get_module(env.state, module).app result = %{ name: Utils.quoted_to_name({:__aliases__, [], module }), + std_lib: make_std_lib_import(env), + imports: imports, + js_imports: js_imports, + exports: exported_object, body: body, - app_name: app_name + app_name: app_name, + env: env } result @@ -62,10 +84,33 @@ defmodule ElixirScript.Translator.Defmodule do exported_functions = Enum.map(exported_functions, fn({_key, value}) -> value end) private_functions = Enum.map(private_functions, fn({_key, value}) -> value end) + module_refs = State.get_module_references(env.state, env.module) -- [env.module] + imports = process_module_refs(module_refs, env) + js_imports = State.get_javascript_module_references(env.state, env.module) + body = structs ++ private_functions ++ exported_functions ++ body - {body, exported_object} + {imports, js_imports, body, exported_object} + end + + def make_std_lib_import(env) do + compiler_opts = State.get(env.state).compiler_opts + case compiler_opts.import_standard_libs do + true -> + {:Elixir, Utils.make_local_file_path(:elixir, compiler_opts.core_path, env), true } + false -> + nil + end end + def process_module_refs(module_refs, env) do + Enum.map(module_refs, fn(x) -> + module_name = Utils.name_to_js_name(x) + app_name = State.get_module(env.state, x).app + path = Utils.make_local_file_path(app_name, Utils.name_to_js_file_name(x), env) + {module_name, path} + end) + end + def translate_body(body, env) do { body, env } = Translator.translate(body, env) diff --git a/lib/elixir_script/translator/kernel/defprotocol.ex b/lib/elixir_script/translator/kernel/defprotocol.ex index da9419ab..eedbd211 100644 --- a/lib/elixir_script/translator/kernel/defprotocol.ex +++ b/lib/elixir_script/translator/kernel/defprotocol.ex @@ -78,12 +78,20 @@ defmodule ElixirScript.Translator.Defprotocol do ) body = body ++ [declaration] ++ [implementations] - body = env.module_formatter.build(body, JS.identifier(Utils.name_to_js_name(name)), env) + + module_refs = State.get_module_references(env.state, env.module) -- [env.module] + imports = Defmodule.process_module_refs(module_refs, env) + js_imports = State.get_javascript_module_references(env.state, env.module) %{ name: name, + std_lib: Defmodule.make_std_lib_import(env), + js_imports: js_imports, + imports: imports, body: body, - app_name: app_name + exports: JS.identifier(Utils.name_to_js_name(name)), + app_name: app_name, + env: env } end @@ -91,5 +99,5 @@ defmodule ElixirScript.Translator.Defprotocol do Enum.map(Keyword.keys(functions), fn(function_name) -> {function_name, JS.function_expression([], [], JS.block_statement([]))} end) - end + end end diff --git a/lib/elixir_script/translator/state.ex b/lib/elixir_script/translator/state.ex index 40a09f74..7ebf5ef4 100644 --- a/lib/elixir_script/translator/state.ex +++ b/lib/elixir_script/translator/state.ex @@ -20,6 +20,7 @@ defmodule ElixirScript.Translator.State do modules = state.modules modules = Enum.map(modules, fn {m, d} -> d = Map.delete(d, :javascript_ast) + |> Map.delete(:javascript_module) |> Map.delete(:javascript_code) |> Map.delete(:javascript_name) From c1f6574e2529e2ddb45de5ef7fb804b27796b022 Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Tue, 21 Feb 2017 06:58:46 -0600 Subject: [PATCH 403/860] Stopped doing steps on modules in different processes --- lib/elixir_script.ex | 1 - lib/elixir_script/passes/create_js_modules.ex | 16 +----- lib/elixir_script/passes/java_script_ast.ex | 18 +------ lib/elixir_script/passes/java_script_code.ex | 16 +----- src/javascript/lib/core/functions.js | 54 +++++++++++++------ 5 files changed, 43 insertions(+), 62 deletions(-) diff --git a/lib/elixir_script.ex b/lib/elixir_script.ex index 7a19180a..2626ea27 100644 --- a/lib/elixir_script.ex +++ b/lib/elixir_script.ex @@ -199,7 +199,6 @@ defmodule ElixirScript do |> ElixirScript.Passes.FindFunctions.execute(opts) |> ElixirScript.Passes.JavaScriptAST.execute(opts) |> ElixirScript.Passes.ConsolidateProtocols.execute(opts) - |> ElixirScript.Passes.CreateJSModules.execute(opts) |> ElixirScript.Passes.JavaScriptCode.execute(opts) |> ElixirScript.Passes.JavaScriptName.execute(opts) |> ElixirScript.Passes.HandleOutput.execute(opts) diff --git a/lib/elixir_script/passes/create_js_modules.ex b/lib/elixir_script/passes/create_js_modules.ex index a896cf8c..f357b535 100644 --- a/lib/elixir_script/passes/create_js_modules.ex +++ b/lib/elixir_script/passes/create_js_modules.ex @@ -4,21 +4,9 @@ defmodule ElixirScript.Passes.CreateJSModules do def execute(compiler_data, opts) do parent = self - - data = Enum.map(compiler_data.data, fn({module_name, module_data}) -> - - spawn_link fn -> + data = Enum.map(compiler_data.data, fn({module_name, module_data}) -> module_data = compile(module_data, opts, compiler_data.state) - result = {module_name, module_data} - send parent, {self, result } - end - - end) - |> Enum.map(fn pid -> - receive do - {^pid, result} -> - result - end + {module_name, module_data} end) %{ compiler_data | data: data } diff --git a/lib/elixir_script/passes/java_script_ast.ex b/lib/elixir_script/passes/java_script_ast.ex index c27db835..cc1ef76b 100644 --- a/lib/elixir_script/passes/java_script_ast.ex +++ b/lib/elixir_script/passes/java_script_ast.ex @@ -8,23 +8,9 @@ defmodule ElixirScript.Passes.JavaScriptAST do State.set_module_data(compiler_data.state, compiler_data.data) State.set_loaded_modules(compiler_data.state, Map.get(compiler_data, :loaded_modules, [])) - parent = self - - data = State.get_module_data(compiler_data.state) - |> Enum.map(fn({module_name, module_data}) -> - - spawn_link fn -> + data = Enum.map(State.get_module_data(compiler_data.state), fn({module_name, module_data}) -> module_data = compile(module_data, opts, compiler_data.state) - result = {module_name, module_data} - send parent, {self, result } - end - - end) - |> Enum.map(fn pid -> - receive do - {^pid, result} -> - result - end + {module_name, module_data} end) %{ compiler_data | data: data } diff --git a/lib/elixir_script/passes/java_script_code.ex b/lib/elixir_script/passes/java_script_code.ex index 2381fcd8..01dc2963 100644 --- a/lib/elixir_script/passes/java_script_code.ex +++ b/lib/elixir_script/passes/java_script_code.ex @@ -5,20 +5,9 @@ defmodule ElixirScript.Passes.JavaScriptCode do def execute(compiler_data, _) do parent = self - data = Enum.map(compiler_data.data, fn({module_name, module_data}) -> - - spawn_link fn -> + data = Enum.map(compiler_data.data, fn({module_name, module_data}) -> module_data = compile(module_data) - result = {module_name, module_data} - send parent, {self, result } - end - - end) - |> Enum.map(fn pid -> - receive do - {^pid, result} -> - result - end + {module_name, module_data} end) %{ compiler_data | data: data } @@ -28,7 +17,6 @@ defmodule ElixirScript.Passes.JavaScriptCode do module_data end - defp compile(module_data) do js_ast = Builder.program(List.wrap(module_data.javascript_ast)) diff --git a/src/javascript/lib/core/functions.js b/src/javascript/lib/core/functions.js index b747a9f6..f76a2422 100644 --- a/src/javascript/lib/core/functions.js +++ b/src/javascript/lib/core/functions.js @@ -1,14 +1,14 @@ -import Protocol from './protocol'; -import Core from '../core'; +import Protocol from "./protocol"; +import Core from "../core"; function call_property(item, property) { let prop = null; if ( - typeof item === 'number' || - typeof item === 'symbol' || - typeof item === 'boolean' || - typeof item === 'string' + typeof item === "number" || + typeof item === "symbol" || + typeof item === "boolean" || + typeof item === "string" ) { if (item[property] !== undefined) { prop = property; @@ -50,15 +50,15 @@ function contains(left, right) { } function get_global() { - if (typeof self !== 'undefined') { + if (typeof self !== "undefined") { return self; - } else if (typeof window !== 'undefined') { + } else if (typeof window !== "undefined") { return window; - } else if (typeof global !== 'undefined') { + } else if (typeof global !== "undefined") { return global; } - throw new Error('No global state found'); + throw new Error("No global state found"); } function defstruct(defaults) { @@ -78,7 +78,7 @@ function defstruct(defaults) { function defexception(defaults) { return class extends Error { constructor(update = {}) { - const message = update.message || ''; + const message = update.message || ""; super(message); const the_values = Object.assign(defaults, update); @@ -86,7 +86,7 @@ function defexception(defaults) { this.name = this.constructor.name; this.message = message; - this[Symbol.for('__exception__')] = true; + this[Symbol.for("__exception__")] = true; Error.captureStackTrace(this, this.constructor.name); } @@ -121,7 +121,7 @@ function is_valid_character(codepoint) { function b64EncodeUnicode(str) { return btoa( encodeURIComponent(str).replace(/%([0-9A-F]{2})/g, (match, p1) => - String.fromCharCode(`0x${p1}`)), + String.fromCharCode(`0x${p1}`)) ); } @@ -148,7 +148,7 @@ function update_map(map, property, value) { return add_property_to_map(map, property, value); } - throw 'map does not have key'; + throw "map does not have key"; } function bnot(expr) { @@ -213,7 +213,7 @@ function can_decode64(data) { function remove_from_list(list, element) { let found = false; - return list.filter((elem) => { + return list.filter(elem => { if (!found && elem === element) { found = true; return false; @@ -309,9 +309,9 @@ function reverse(list) { function maps_find(key, map) { if (key in get_object_keys(map)) { - return new Core.Tuple(Symbol.for('ok'), map[key]); + return new Core.Tuple(Symbol.for("ok"), map[key]); } - return Symbol.for('error'); + return Symbol.for("error"); } function flatten(list, tail = []) { @@ -377,6 +377,25 @@ function maps_fold(fun, acc, map) { return acc1; } +function build_namespace(ns, ns_string) { + let parts = ns_string.split("."); + let parent = ns; + + if (parts[0] === "Elixir") { + parts = parts.slice(1); + } + + for (const part of parts) { + if (typeof parent[part] === "undefined") { + parent[part] = {}; + } + + parent = parent[part]; + } + + return parent; +} + export default { call_property, apply, @@ -416,4 +435,5 @@ export default { mapfoldl, filtermap, maps_fold, + build_namespace }; From 1114cb0a24f3c40228d2ea73b56698358c28efd5 Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Tue, 21 Feb 2017 07:05:56 -0600 Subject: [PATCH 404/860] Add new pass to compile_std_lib --- lib/elixir_script.ex | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/lib/elixir_script.ex b/lib/elixir_script.ex index 2626ea27..91bd1e74 100644 --- a/lib/elixir_script.ex +++ b/lib/elixir_script.ex @@ -160,7 +160,7 @@ defmodule ElixirScript do |> ElixirScript.Passes.AddStdLib.execute(opts) |> ElixirScript.Passes.JavaScriptAST.execute(opts) |> ElixirScript.Passes.ConsolidateProtocols.execute(opts) - |> ElixirScript.Passes.CreateJSModules.execute(opts) + |> ElixirScript.Passes.CreateJSModules.execute(opts) |> ElixirScript.Passes.JavaScriptCode.execute(opts) |> ElixirScript.Passes.JavaScriptName.execute(opts) |> ElixirScript.Passes.HandleOutput.execute(opts) @@ -199,6 +199,7 @@ defmodule ElixirScript do |> ElixirScript.Passes.FindFunctions.execute(opts) |> ElixirScript.Passes.JavaScriptAST.execute(opts) |> ElixirScript.Passes.ConsolidateProtocols.execute(opts) + |> ElixirScript.Passes.CreateJSModules.execute(opts) |> ElixirScript.Passes.JavaScriptCode.execute(opts) |> ElixirScript.Passes.JavaScriptName.execute(opts) |> ElixirScript.Passes.HandleOutput.execute(opts) From d5eda1ca7672a89ab19e0616ec2c11636e9e701f Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Tue, 21 Feb 2017 07:39:56 -0600 Subject: [PATCH 405/860] Add namespace module system --- lib/elixir_script/module_systems/namespace.ex | 81 +++++++++++++++++++ 1 file changed, 81 insertions(+) create mode 100644 lib/elixir_script/module_systems/namespace.ex diff --git a/lib/elixir_script/module_systems/namespace.ex b/lib/elixir_script/module_systems/namespace.ex new file mode 100644 index 00000000..5a9cd830 --- /dev/null +++ b/lib/elixir_script/module_systems/namespace.ex @@ -0,0 +1,81 @@ +defmodule ElixirScript.ModuleSystems.Namespace do + @moduledoc false + alias ESTree.Tools.Builder, as: JS + alias ElixirScript.Translator + alias ElixirScript.Translator.State + alias ElixirScript.Translator.Utils + + def build(module_name, imports, body, exports, env) do + module_imports = Enum.map(imports, fn {module, path} -> import_module(module, env) end) + export = export_module(exports) + List.wrap(make_namespace_body(module_name, imports, body, export)) + end + + defp module_imports_to_js_imports(module_refs, env) do + Enum.map(module_refs, fn(x) -> + module_name = Utils.name_to_js_name(x) + app_name = State.get_module(env.state, x).app + path = Utils.make_local_file_path(app_name, Utils.name_to_js_file_name(x), env) + import_module(module_name, path) + end) + end + + def import_module(module_name, env) do + declarator = JS.variable_declarator( + Translator.translate!(module_name, env), + JS.call_expression( + JS.member_expression( + JS.call_expression( + JS.member_expression( + JS.identifier(:Elixir), + JS.member_expression( + JS.identifier(:Core), + JS.member_expression( + JS.identifier(:Functions), + JS.identifier(:build_namespace) + ) + ) + ), + [JS.identifier("Elixir"), Utils.name_to_js_file_name(module_name)] + ), + JS.identifier("make") + ), + [] + ) + ) + + JS.variable_declaration([declarator], :const) + end + + def export_module(exported_object) do + exported_object + end + + def make_namespace_body(module_name, imports, body, exports) do + exports = if is_nil(exports), do: [], else: [JS.return_statement(exports)] + + make = JS.member_expression( + JS.call_expression( + JS.member_expression( + JS.identifier(:Elixir), + JS.member_expression( + JS.identifier(:Core), + JS.member_expression( + JS.identifier(:Functions), + JS.identifier(:build_namespace) + ) + ) + ), + [JS.identifier("Elixir"), Utils.name_to_js_file_name(module_name)] + ), + JS.identifier("make") + ) + + func = JS.function_expression([JS.identifier("Elixir")], [], JS.block_statement(imports ++ body ++ exports)) + JS.assignment_expression( + :=, + make, + func + ) + end +end \ No newline at end of file From b812feaa68874d36e06d6441ff6f83bfc2128ffd Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Tue, 21 Feb 2017 09:55:50 -0600 Subject: [PATCH 406/860] Preparing for bundled output --- lib/elixir_script/module_systems/common.ex | 43 ++-------- lib/elixir_script/module_systems/es.ex | 51 ++---------- lib/elixir_script/module_systems/namespace.ex | 27 +++---- lib/elixir_script/module_systems/umd.ex | 39 ++------- .../passes/consolidate_protocols.ex | 2 +- lib/elixir_script/passes/create_js_modules.ex | 80 ++++++++++++------- .../translator/kernel/defmodule.ex | 29 +++---- 7 files changed, 96 insertions(+), 175 deletions(-) diff --git a/lib/elixir_script/module_systems/common.ex b/lib/elixir_script/module_systems/common.ex index da8e2b6d..7b53838c 100644 --- a/lib/elixir_script/module_systems/common.ex +++ b/lib/elixir_script/module_systems/common.ex @@ -5,14 +5,14 @@ defmodule ElixirScript.ModuleSystems.Common do alias ElixirScript.Translator.State alias ElixirScript.Translator.Utils - def build(std_import, imports, js_imports, body, exports, env) do + def build(std_import, imports, js_imports, body, exports) do module_imports = Enum.map(imports, fn {module, path} -> import_module(module, path) end) imports = js_imports ++ List.wrap(std_import) |> Enum.map(fn - {module, path} -> import_module(module, path, env) - {module, path, true} -> import_module(module, path, env) - {module, path, false} -> import_namespace_module(module, path, env) + {module, path} -> import_module(module, path) + {module, path, true} -> import_module(module, path) + {module, path, false} -> import_namespace_module(module, path) end) imports = Enum.uniq(imports ++ module_imports) @@ -21,39 +21,12 @@ defmodule ElixirScript.ModuleSystems.Common do imports ++ body ++ export end - defp module_imports_to_js_imports(module_refs, env) do - Enum.map(module_refs, fn(x) -> - module_name = Utils.name_to_js_name(x) - app_name = State.get_module(env.state, x).app - path = Utils.make_local_file_path(app_name, Utils.name_to_js_file_name(x), env) - import_module(module_name, path) - end) - end - - defp make_std_lib_import(env) do - compiler_opts = State.get(env.state).compiler_opts - case compiler_opts.import_standard_libs do - true -> - [{:Elixir, Utils.make_local_file_path(:elixir, compiler_opts.core_path, env), true }] - false -> - [] - end - end - - def import_namespace_module(module_name, from, env) do - do_import_module(Translator.translate!(module_name, env), from) - end - - def import_module(:Elixir, from, env) do - do_import_module(JS.identifier("Elixir"), from) - end - - def import_module(module_name, from, env) do - do_import_module(Translator.translate!(module_name, env), from) + def import_namespace_module(module_name, from) do + do_import_module(JS.identifier(module_name), from) end - def import_module(import_name, from) do - do_import_module(JS.identifier(import_name), from) + def import_module(module_name, from) do + do_import_module(JS.identifier(module_name), from) end defp do_import_module(ref, file_path) do diff --git a/lib/elixir_script/module_systems/es.ex b/lib/elixir_script/module_systems/es.ex index 4845fbf7..bc66da16 100644 --- a/lib/elixir_script/module_systems/es.ex +++ b/lib/elixir_script/module_systems/es.ex @@ -5,14 +5,14 @@ defmodule ElixirScript.ModuleSystems.ES do alias ElixirScript.Translator.State alias ElixirScript.Translator.Utils - def build(std_import, imports, js_imports, body, exports, env) do + def build(std_import, imports, js_imports, body, exports) do module_imports = Enum.map(imports, fn {module, path} -> import_module(module, path) end) imports = js_imports ++ List.wrap(std_import) |> Enum.map(fn - {module, path} -> import_module(module, path, env) - {module, path, true} -> import_module(module, path, env) - {module, path, false} -> import_namespace_module(module, path, env) + {module, path} -> import_module(module, path) + {module, path, true} -> import_module(module, path) + {module, path, false} -> import_namespace_module(module, path) end) imports = Enum.uniq(imports ++ module_imports) @@ -21,47 +21,10 @@ defmodule ElixirScript.ModuleSystems.ES do imports ++ body ++ export end - defp module_imports_to_js_imports(module_refs, env) do - Enum.map(module_refs, fn(x) -> - module_name = Utils.name_to_js_name(x) - app_name = State.get_module(env.state, x).app - path = Utils.make_local_file_path(app_name, Utils.name_to_js_file_name(x), env) - import_module(module_name, path) - end) - end - - defp make_std_lib_import(env) do - compiler_opts = State.get(env.state).compiler_opts - case compiler_opts.import_standard_libs do - true -> - [{:Elixir, Utils.make_local_file_path(:elixir, compiler_opts.core_path, env), true }] - false -> - [] - end - end - - def import_namespace_module(module_name, from, env) do + def import_namespace_module(module_name, from) do import_specifier = JS.import_namespace_specifier( - Translator.translate!(module_name, env), - Translator.translate!(module_name, env) - ) - - do_import_module([import_specifier], from) - end - - def import_module(:Elixir, from, env) do - import_specifier = JS.import_default_specifier( - JS.identifier("Elixir"), - JS.identifier("Elixir") - ) - - do_import_module([import_specifier], from) - end - - def import_module(module_name, from, env) do - import_specifier = JS.import_default_specifier( - Translator.translate!(module_name, env), - Translator.translate!(module_name, env) + JS.identifier(module_name), + JS.identifier(module_name) ) do_import_module([import_specifier], from) diff --git a/lib/elixir_script/module_systems/namespace.ex b/lib/elixir_script/module_systems/namespace.ex index 5a9cd830..d467eeca 100644 --- a/lib/elixir_script/module_systems/namespace.ex +++ b/lib/elixir_script/module_systems/namespace.ex @@ -6,18 +6,11 @@ defmodule ElixirScript.ModuleSystems.Namespace do alias ElixirScript.Translator.Utils def build(module_name, imports, body, exports, env) do - module_imports = Enum.map(imports, fn {module, path} -> import_module(module, env) end) - export = export_module(exports) - List.wrap(make_namespace_body(module_name, imports, body, export)) - end - - defp module_imports_to_js_imports(module_refs, env) do - Enum.map(module_refs, fn(x) -> - module_name = Utils.name_to_js_name(x) - app_name = State.get_module(env.state, x).app - path = Utils.make_local_file_path(app_name, Utils.name_to_js_file_name(x), env) - import_module(module_name, path) + module_imports = Enum.map(imports, fn {module, path} -> + IO.inspect module + import_module(module, env) end) + List.wrap(make_namespace_body(module_name, imports, body, exports)) end def import_module(module_name, env) do @@ -38,7 +31,7 @@ defmodule ElixirScript.ModuleSystems.Namespace do ), [JS.identifier("Elixir"), Utils.name_to_js_file_name(module_name)] ), - JS.identifier("make") + JS.identifier("__make") ), [] ) @@ -47,10 +40,6 @@ defmodule ElixirScript.ModuleSystems.Namespace do JS.variable_declaration([declarator], :const) end - def export_module(exported_object) do - exported_object - end - def make_namespace_body(module_name, imports, body, exports) do exports = if is_nil(exports), do: [], else: [JS.return_statement(exports)] @@ -68,10 +57,12 @@ defmodule ElixirScript.ModuleSystems.Namespace do ), [JS.identifier("Elixir"), Utils.name_to_js_file_name(module_name)] ), - JS.identifier("make") + JS.identifier("__make") ) - func = JS.function_expression([JS.identifier("Elixir")], [], JS.block_statement(imports ++ body ++ exports)) + func_body = JS.block_statement(imports ++ body ++ exports) + + func = JS.function_expression([JS.identifier("Elixir")], [], func_body) JS.assignment_expression( :=, make, diff --git a/lib/elixir_script/module_systems/umd.ex b/lib/elixir_script/module_systems/umd.ex index 2a492638..a3d6c794 100644 --- a/lib/elixir_script/module_systems/umd.ex +++ b/lib/elixir_script/module_systems/umd.ex @@ -5,14 +5,14 @@ defmodule ElixirScript.ModuleSystems.UMD do alias ElixirScript.Translator.State alias ElixirScript.Translator.Utils - def build(std_import, imports, js_imports, body, exports, env) do + def build(std_import, imports, js_imports, body, exports) do module_imports = Enum.map(imports, fn {module, path} -> import_module(module, path) end) imports = js_imports ++ List.wrap(std_import) |> Enum.map(fn - {module, path} -> import_module(module, path, env) - {module, path, true} -> import_module(module, path, env) - {module, path, false} -> import_namespace_module(module, path, env) + {module, path} -> import_module(module, path) + {module, path, true} -> import_module(module, path) + {module, path, false} -> import_namespace_module(module, path) end) imports = Enum.uniq(imports ++ module_imports) @@ -21,35 +21,12 @@ defmodule ElixirScript.ModuleSystems.UMD do List.wrap(make_umd(imports, body, export)) end - defp module_imports_to_js_imports(module_refs, env) do - Enum.map(module_refs, fn(x) -> - module_name = Utils.name_to_js_name(x) - app_name = State.get_module(env.state, x).app - path = Utils.make_local_file_path(app_name, Utils.name_to_js_file_name(x), env) - import_module(module_name, path) - end) - end - - defp make_std_lib_import(env) do - compiler_opts = State.get(env.state).compiler_opts - case compiler_opts.import_standard_libs do - true -> - [{:Elixir, Utils.make_local_file_path(:elixir, compiler_opts.core_path, env), true }] - false -> - [] - end - end - - def import_namespace_module(module_name, from, env) do - {Translator.translate!(module_name, env), JS.literal(from)} - end - - def import_module(:Elixir, from, env) do - {JS.identifier("Elixir"), JS.literal(from)} + def import_namespace_module(module_name, from) do + {JS.identifier(module_name), JS.literal(from)} end - def import_module(module_name, from, env) do - {Translator.translate!(module_name, env), JS.literal(from)} + def import_module(module_name, from) do + {JS.identifier(module_name), JS.literal(from)} end def import_module(import_name, from) do diff --git a/lib/elixir_script/passes/consolidate_protocols.ex b/lib/elixir_script/passes/consolidate_protocols.ex index fb73c772..7d7e2b63 100644 --- a/lib/elixir_script/passes/consolidate_protocols.ex +++ b/lib/elixir_script/passes/consolidate_protocols.ex @@ -71,7 +71,7 @@ defmodule ElixirScript.Passes.ConsolidateProtocols do x = Atom.to_string(Utils.quoted_to_name(impl_data.for)) x = String.to_atom(protocol_name <> ".DefImpl." <> x) name = Utils.name_to_js_name(x) - {name, Utils.make_local_file_path(impl_data.app, Utils.name_to_js_file_name(x), compiler_opts.root, nil)} + {x, ""} end) body = Enum.map(implementations, fn({_, impl_data}) -> diff --git a/lib/elixir_script/passes/create_js_modules.ex b/lib/elixir_script/passes/create_js_modules.ex index f357b535..31352087 100644 --- a/lib/elixir_script/passes/create_js_modules.ex +++ b/lib/elixir_script/passes/create_js_modules.ex @@ -1,51 +1,71 @@ defmodule ElixirScript.Passes.CreateJSModules do - @moduledoc false + @moduledoc false alias ElixirScript.Translator.Utils + alias ESTree.Tools.Builder, as: JS def execute(compiler_data, opts) do - parent = self - data = Enum.map(compiler_data.data, fn({module_name, module_data}) -> - module_data = compile(module_data, opts, compiler_data.state) - {module_name, module_data} + namespace_modules = Enum.reduce(compiler_data.data, %{ js_imports: [], body: [] }, fn + ({_, %{load_only: true} = module_data}, acc) -> + acc + + ({module_name, module_data}, acc) -> + {js_imports, body} = generate_namespace_module( + module_data.type, + module_name, + Map.get(module_data, :javascript_module, module_data), + opts, + compiler_data.state + ) + + Map.update!(acc, :js_imports, fn x -> x ++ js_imports end) + |> Map.update!(:body, fn x -> x ++ body end) end) - %{ compiler_data | data: data } + compiled = compile(namespace_modules.js_imports, namespace_modules.body, opts) + Map.put(compiler_data, :compiled, compiled) end - defp compile(%{load_only: true} = module_data, opts, state) do - module_data - end + defp generate_namespace_module(:consolidated, module_name, js_module, opts, state) do + env = ElixirScript.Translator.LexicalScope.module_scope( + js_module.name, + Utils.name_to_js_file_name(js_module.name) <> ".js", + opts.env, + state, + opts) - defp compile(%{type: :consolidated} = module_data, opts, state) do - js_module = module_data - env = ElixirScript.Translator.LexicalScope.module_scope(module_data.name, Utils.name_to_js_file_name(module_data.name) <> ".js", opts.env, state, opts) - - ast = opts.module_formatter.build( - js_module.std_lib, - js_module.imports, - js_module.js_imports, + body = ElixirScript.ModuleSystems.Namespace.build( + module_name, + js_module.imports, js_module.body, js_module.exports, env ) - Map.put(module_data, :javascript_ast, ast) - end + {js_module.js_imports, body} + end - defp compile(module_data, opts, state) do - js_module = module_data.javascript_module - env = js_module.env - - ast = opts.module_formatter.build( - js_module.std_lib, - js_module.imports, - js_module.js_imports, + defp generate_namespace_module(_, module_name, js_module, _, _) do + body = ElixirScript.ModuleSystems.Namespace.build( + module_name, + js_module.imports, js_module.body, js_module.exports, - env + js_module.env ) - Map.put(module_data, :javascript_ast, ast) - end + {js_module.js_imports, body} + end + + defp compile(js_imports, body, opts) do + ast = opts.module_formatter.build( + {:Elixir, "./Elixir.Bootstrap", true }, + [], + js_imports, + body, + JS.identifier("Elixir") + ) + + ast + end end diff --git a/lib/elixir_script/translator/kernel/defmodule.ex b/lib/elixir_script/translator/kernel/defmodule.ex index e013da2c..5ccb4bf4 100644 --- a/lib/elixir_script/translator/kernel/defmodule.ex +++ b/lib/elixir_script/translator/kernel/defmodule.ex @@ -10,26 +10,26 @@ defmodule ElixirScript.Translator.Defmodule do def make_module(ElixirScript.Temp, body, env) do { body, _ } = translate_body(body, env) - %{ + %{ name: ElixirScript.Temp, std_lib: make_std_lib_import(env), js_imports: [], - imports: [], - body: body |> Group.inflate_groups, - exports: nil, + imports: [], + body: body |> Group.inflate_groups, + exports: nil, app_name: ElixirScript.Translator.State.get(env.state).compiler_opts.app, - env: env + env: env } end def make_module(module, nil, env) do - %{ - name: module, + %{ + name: module, std_lib: make_std_lib_import(env), - js_imports: [], - imports: [], + js_imports: [], + imports: [], body: [], - exports: nil, + exports: nil, app_name: ElixirScript.Translator.State.get(env.state).compiler_opts.app, env: env } @@ -86,7 +86,7 @@ defmodule ElixirScript.Translator.Defmodule do module_refs = State.get_module_references(env.state, env.module) -- [env.module] imports = process_module_refs(module_refs, env) - js_imports = State.get_javascript_module_references(env.state, env.module) + js_imports = State.get_javascript_module_references(env.state, env.module) body = structs ++ private_functions ++ exported_functions ++ body {imports, js_imports, body, exported_object} @@ -104,12 +104,9 @@ defmodule ElixirScript.Translator.Defmodule do def process_module_refs(module_refs, env) do Enum.map(module_refs, fn(x) -> - module_name = Utils.name_to_js_name(x) - app_name = State.get_module(env.state, x).app - path = Utils.make_local_file_path(app_name, Utils.name_to_js_file_name(x), env) - {module_name, path} + {x, ""} end) - end + end def translate_body(body, env) do { body, env } = Translator.translate(body, env) From 49c53a0d14be8d8a919f5101ed01cb8816647430 Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Tue, 21 Feb 2017 18:27:31 -0600 Subject: [PATCH 407/860] Single file output --- lib/elixir_script/module_systems/namespace.ex | 16 +++--- .../passes/consolidate_protocols.ex | 11 ++-- lib/elixir_script/passes/handle_output.ex | 51 +++++-------------- lib/elixir_script/passes/java_script_code.ex | 27 +++------- lib/elixir_script/passes/java_script_name.ex | 8 +-- .../translator/kernel/defprotocol.ex | 22 ++++---- test/test_helper.exs | 2 +- 7 files changed, 44 insertions(+), 93 deletions(-) diff --git a/lib/elixir_script/module_systems/namespace.ex b/lib/elixir_script/module_systems/namespace.ex index d467eeca..97c6e6ce 100644 --- a/lib/elixir_script/module_systems/namespace.ex +++ b/lib/elixir_script/module_systems/namespace.ex @@ -7,15 +7,17 @@ defmodule ElixirScript.ModuleSystems.Namespace do def build(module_name, imports, body, exports, env) do module_imports = Enum.map(imports, fn {module, path} -> - IO.inspect module import_module(module, env) end) - List.wrap(make_namespace_body(module_name, imports, body, exports)) + + List.wrap(make_namespace_body(module_name, module_imports, body, exports)) end - def import_module(module_name, env) do + defp import_module(module_name, env) do + name = ["Elixir" | Module.split(module_name) ] |> Enum.join("$") + declarator = JS.variable_declarator( - Translator.translate!(module_name, env), + JS.identifier(name), JS.call_expression( JS.member_expression( JS.call_expression( @@ -29,7 +31,7 @@ defmodule ElixirScript.ModuleSystems.Namespace do ) ) ), - [JS.identifier("Elixir"), Utils.name_to_js_file_name(module_name)] + [JS.identifier("Elixir"), JS.literal(Utils.name_to_js_file_name(module_name))] ), JS.identifier("__make") ), @@ -40,7 +42,7 @@ defmodule ElixirScript.ModuleSystems.Namespace do JS.variable_declaration([declarator], :const) end - def make_namespace_body(module_name, imports, body, exports) do + defp make_namespace_body(module_name, imports, body, exports) do exports = if is_nil(exports), do: [], else: [JS.return_statement(exports)] make = JS.member_expression( @@ -55,7 +57,7 @@ defmodule ElixirScript.ModuleSystems.Namespace do ) ) ), - [JS.identifier("Elixir"), Utils.name_to_js_file_name(module_name)] + [JS.identifier("Elixir"), JS.literal(Utils.name_to_js_file_name(module_name))] ), JS.identifier("__make") ) diff --git a/lib/elixir_script/passes/consolidate_protocols.ex b/lib/elixir_script/passes/consolidate_protocols.ex index 7d7e2b63..0da5f108 100644 --- a/lib/elixir_script/passes/consolidate_protocols.ex +++ b/lib/elixir_script/passes/consolidate_protocols.ex @@ -53,7 +53,7 @@ defmodule ElixirScript.Passes.ConsolidateProtocols do end) end - defp make_defimpl(name, { _, protocol }, implementations, compiler_opts) do + defp make_defimpl(name, {_, protocol}, implementations, compiler_opts) do declarator = JS.variable_declarator( JS.identifier("impls"), JS.array_expression([]) @@ -87,24 +87,21 @@ defmodule ElixirScript.Passes.ConsolidateProtocols do ) end) - imports = defimpl_imports - body = [declaration] ++ body - module_name = String.to_atom(protocol_name <> ".DefImpl") module_data = %{ name: name, module: String.to_atom(protocol_name <> ".DefImpl"), std_lib: {:Elixir, Utils.make_local_file_path(:elixir, compiler_opts.core_path, compiler_opts.root, nil)}, js_imports: [], - imports: imports, - body: List.wrap(body), + imports: defimpl_imports, + body: [declaration] ++ body, exports: JS.identifier("impls"), app: app_name, type: :consolidated, protocol: name } - { module_name, module_data } + {module_name, module_data} end end diff --git a/lib/elixir_script/passes/handle_output.ex b/lib/elixir_script/passes/handle_output.ex index 728f5e91..8eb5edc8 100644 --- a/lib/elixir_script/passes/handle_output.ex +++ b/lib/elixir_script/passes/handle_output.ex @@ -16,26 +16,19 @@ defmodule ElixirScript.Passes.HandleOutput do end end - defp out(compiler_output, %{import_standard_libs: false} = compiler_opts) do - data = Enum.filter(compiler_output.data, fn({m, d}) -> d.app != :elixir end) - - out(%{ compiler_output | data: data }, Map.delete(compiler_opts, :import_standard_libs)) - end - defp out(compiler_output, %{output: nil} = compiler_opts) do compiler_output - |> remove_load_only |> process_include_path(compiler_opts) end defp out(compiler_output, %{output: :stdout} = compiler_opts) do - compiler_output - |> remove_load_only + out = compiler_output |> process_include_path(compiler_opts) - |> Enum.each(fn - {_, code, _} -> IO.write(code) + + case out do + {code, _} -> IO.write(code) code -> IO.write(code) - end) + end end defp out(compiler_output, %{output: output_path, core_path: _} = compiler_opts) do @@ -43,39 +36,21 @@ defmodule ElixirScript.Passes.HandleOutput do ElixirScript.copy_stdlib_to_destination(compiler_opts.format, output_path) end - compiler_output = remove_load_only(compiler_output) - - compiler_output.data - |> Enum.each(fn({_, x}) -> - write_to_file(x, output_path) - end) - end - - defp write_to_file(module_data, destination) do - file_name = Path.join([destination, to_string(module_data.app), module_data.javascript_name]) + file_name = Path.join([output_path, compiler_output.generated_name]) if !File.exists?(Path.dirname(file_name)) do File.mkdir_p!(Path.dirname(file_name)) end - File.write!(file_name, module_data.javascript_code) + File.write!(file_name, compiler_output.generated) end defp process_include_path(compiler_output, compiler_opts) do - compiler_output.data - |> Enum.map(fn - {_, module_data} -> - case compiler_opts.include_path do - true -> - { module_data.javascript_name, module_data.javascript_code, module_data.app } - false -> - module_data.javascript_code - end - end) - end - - defp remove_load_only(compiler_output) do - data = Enum.filter(compiler_output.data, fn({m, d}) -> Map.get(d, :load_only, false) == false end) - %{ compiler_output | data: data } + case compiler_opts.include_path do + true -> + {compiler_output.generated, compiler_output.generated_name} + false -> + compiler_output.generated + end end end diff --git a/lib/elixir_script/passes/java_script_code.ex b/lib/elixir_script/passes/java_script_code.ex index 01dc2963..7eb2f7ef 100644 --- a/lib/elixir_script/passes/java_script_code.ex +++ b/lib/elixir_script/passes/java_script_code.ex @@ -1,30 +1,17 @@ defmodule ElixirScript.Passes.JavaScriptCode do @moduledoc false - alias ESTree.Tools.{ Builder, Generator } + alias ESTree.Tools.{Builder, Generator} def execute(compiler_data, _) do parent = self - data = Enum.map(compiler_data.data, fn({module_name, module_data}) -> - module_data = compile(module_data) - {module_name, module_data} - end) - - %{ compiler_data | data: data } - end - - defp compile(%{load_only: true} = module_data) do - module_data - end - - defp compile(module_data) do - js_ast = Builder.program(List.wrap(module_data.javascript_ast)) - - js_code = js_ast + js_code = compiler_data.compiled + |> List.wrap + |> Builder.program |> prepare_js_ast |> Generator.generate - Map.put(module_data, :javascript_code, js_code) + Map.put(compiler_data, :generated, js_code) end defp prepare_js_ast(js_ast) do @@ -33,9 +20,9 @@ defmodule ElixirScript.Passes.JavaScriptCode do modules |> Enum.reduce([], &(&2 ++ &1.body)) |> Builder.program - %ElixirScript.Translator.Group{ body: body } -> + %ElixirScript.Translator.Group{body: body} -> Builder.program(body) - %ElixirScript.Translator.Empty{ } -> + %ElixirScript.Translator.Empty{} -> Builder.program([]) _ -> js_ast diff --git a/lib/elixir_script/passes/java_script_name.ex b/lib/elixir_script/passes/java_script_name.ex index 07a873ff..38871341 100644 --- a/lib/elixir_script/passes/java_script_name.ex +++ b/lib/elixir_script/passes/java_script_name.ex @@ -3,12 +3,6 @@ defmodule ElixirScript.Passes.JavaScriptName do alias ElixirScript.Translator.Utils def execute(compiler_data, _) do - data = Enum.map(compiler_data.data, fn({module_name, module_data}) -> - js_name = Utils.name_to_js_file_name(module_name) <> ".js" - module_data = Map.put(module_data, :javascript_name, js_name) - {module_name, module_data} - end) - - %{ compiler_data | data: data } + Map.put(compiler_data, :generated_name, "Elixir.App.js") end end diff --git a/lib/elixir_script/translator/kernel/defprotocol.ex b/lib/elixir_script/translator/kernel/defprotocol.ex index eedbd211..cae6ad52 100644 --- a/lib/elixir_script/translator/kernel/defprotocol.ex +++ b/lib/elixir_script/translator/kernel/defprotocol.ex @@ -14,16 +14,8 @@ defmodule ElixirScript.Translator.Defprotocol do """ def make(name, functions, env) do { body, _ } = Defmodule.translate_body( {:__block__, [], [] }, env) - app_name = State.get_module(env.state, name).app - State.add_javascript_module_reference( - env.state, - env.module, - {:__aliases__, [], [:Implementations]}, - Utils.make_local_file_path(app_name, Utils.name_to_js_file_name(name) <> ".Defimpl", env) - ) - object = process_spec_functions(functions) |> Enum.map(fn({key, value}) -> Map.make_property(Identifier.make_identifier(key), value) @@ -49,6 +41,10 @@ defmodule ElixirScript.Translator.Defprotocol do declaration = JS.variable_declaration([declarator], :const) + implementation_name_split = Module.split(name) ++ ["DefImpl"] + implementation_name = Enum.join(implementation_name_split, "$") + implementation_name_module = Module.concat(implementation_name_split) + implementations = JS.for_of_statement( JS.variable_declaration([JS.variable_declarator( JS.object_pattern([ @@ -57,7 +53,7 @@ defmodule ElixirScript.Translator.Defprotocol do ]), nil )], :let), - JS.identifier("Implementations"), + JS.identifier(implementation_name), JS.call_expression( JS.member_expression( JS.identifier(:Elixir), @@ -85,13 +81,13 @@ defmodule ElixirScript.Translator.Defprotocol do %{ name: name, - std_lib: Defmodule.make_std_lib_import(env), + std_lib: Defmodule.make_std_lib_import(env), js_imports: js_imports, - imports: imports, + imports: imports ++ [{implementation_name_module, ""}], body: body, exports: JS.identifier(Utils.name_to_js_name(name)), app_name: app_name, - env: env + env: env } end @@ -99,5 +95,5 @@ defmodule ElixirScript.Translator.Defprotocol do Enum.map(Keyword.keys(functions), fn(function_name) -> {function_name, JS.function_expression([], [], JS.block_statement([]))} end) - end + end end diff --git a/test/test_helper.exs b/test/test_helper.exs index 2771b873..3cc39872 100644 --- a/test/test_helper.exs +++ b/test/test_helper.exs @@ -42,7 +42,7 @@ defmodule ElixirScript.TestHelper do end def assert_translation(ex_ast, js_code, format) do - converted_code = ex_ast_to_js(ex_ast, format) |> Elixir.Enum.join("\n\n") + converted_code = ex_ast_to_js(ex_ast, format) assert converted_code |> strip_spaces == strip_spaces(js_code), """ **Code Does Not Match ** From e9a1cd54577f760d539a4046d2a48a6d73371182 Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Tue, 21 Feb 2017 19:40:51 -0600 Subject: [PATCH 408/860] Update dep resolution for modules --- lib/elixir_script/module_systems/namespace.ex | 48 ++++++++++++++++++- 1 file changed, 46 insertions(+), 2 deletions(-) diff --git a/lib/elixir_script/module_systems/namespace.ex b/lib/elixir_script/module_systems/namespace.ex index 97c6e6ce..9bba3b6c 100644 --- a/lib/elixir_script/module_systems/namespace.ex +++ b/lib/elixir_script/module_systems/namespace.ex @@ -43,7 +43,51 @@ defmodule ElixirScript.ModuleSystems.Namespace do end defp make_namespace_body(module_name, imports, body, exports) do - exports = if is_nil(exports), do: [], else: [JS.return_statement(exports)] + _self = + JS.call_expression( + JS.member_expression( + JS.identifier(:Elixir), + JS.member_expression( + JS.identifier(:Core), + JS.member_expression( + JS.identifier(:Functions), + JS.identifier(:build_namespace) + ) + ) + ), + [JS.identifier("Elixir"), JS.literal(Utils.name_to_js_file_name(module_name))] + ) + + values = JS.member_expression( + _self, + JS.identifier("values") + ) + + _if = JS.if_statement( + values, + JS.return_statement(values) + ) + + exports = if is_nil(exports) do + JS.object_expression([]) + else + exports + end + + declarator = JS.variable_declarator( + JS.identifier("values"), + exports + ) + + declaration = JS.variable_declaration([declarator], :const) + + assign = JS.assignment_expression( + :=, + values, + JS.identifier("values") + ) + + exports = [JS.return_statement(JS.identifier("values"))] make = JS.member_expression( JS.call_expression( @@ -62,7 +106,7 @@ defmodule ElixirScript.ModuleSystems.Namespace do JS.identifier("__make") ) - func_body = JS.block_statement(imports ++ body ++ exports) + func_body = JS.block_statement([_if] ++ imports ++ body ++ [declaration, assign] ++ exports) func = JS.function_expression([JS.identifier("Elixir")], [], func_body) JS.assignment_expression( From 8a69da92e38c5365c70c52cde646d26f7d752a01 Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Tue, 21 Feb 2017 20:35:44 -0600 Subject: [PATCH 409/860] Update tests --- lib/elixir_script.ex | 1 + lib/elixir_script/module_systems/common.ex | 4 +- lib/elixir_script/module_systems/es.ex | 4 +- lib/elixir_script/module_systems/umd.ex | 4 +- .../passes/consolidate_protocols.ex | 1 - lib/elixir_script/passes/create_js_modules.ex | 18 +- .../translator/kernel/defimpl.ex | 3 +- .../translator/kernel/defmodule.ex | 8 +- .../translator/kernel/defprotocol.ex | 2 - test/elixir_script_test.exs | 14 +- test/test_helper.exs | 6 +- test/translator/bug_test.exs | 3 - test/translator/commonjs_test.exs | 118 +--------- test/translator/defmodule_test.exs | 219 +----------------- test/translator/function_test.exs | 18 -- test/translator/protocol_test.exs | 89 ------- test/translator/struct_test.exs | 44 ---- test/translator/umd_test.exs | 156 ------------- 18 files changed, 27 insertions(+), 685 deletions(-) delete mode 100644 test/translator/protocol_test.exs diff --git a/lib/elixir_script.ex b/lib/elixir_script.ex index 91bd1e74..268a2678 100644 --- a/lib/elixir_script.ex +++ b/lib/elixir_script.ex @@ -218,6 +218,7 @@ defmodule ElixirScript do |> Map.put(:output, nil) |> Map.put(:app, :app) |> Map.put(:format, :es) + |> Map.put(:js_modules, []) options = Map.merge(default_options, opts) Map.put(options, :module_formatter, get_module_formatter(options[:format])) diff --git a/lib/elixir_script/module_systems/common.ex b/lib/elixir_script/module_systems/common.ex index 7b53838c..795043c1 100644 --- a/lib/elixir_script/module_systems/common.ex +++ b/lib/elixir_script/module_systems/common.ex @@ -5,10 +5,10 @@ defmodule ElixirScript.ModuleSystems.Common do alias ElixirScript.Translator.State alias ElixirScript.Translator.Utils - def build(std_import, imports, js_imports, body, exports) do + def build(imports, js_imports, body, exports) do module_imports = Enum.map(imports, fn {module, path} -> import_module(module, path) end) - imports = js_imports ++ List.wrap(std_import) + imports = js_imports |> Enum.map(fn {module, path} -> import_module(module, path) {module, path, true} -> import_module(module, path) diff --git a/lib/elixir_script/module_systems/es.ex b/lib/elixir_script/module_systems/es.ex index bc66da16..348ac6a3 100644 --- a/lib/elixir_script/module_systems/es.ex +++ b/lib/elixir_script/module_systems/es.ex @@ -5,10 +5,10 @@ defmodule ElixirScript.ModuleSystems.ES do alias ElixirScript.Translator.State alias ElixirScript.Translator.Utils - def build(std_import, imports, js_imports, body, exports) do + def build(imports, js_imports, body, exports) do module_imports = Enum.map(imports, fn {module, path} -> import_module(module, path) end) - imports = js_imports ++ List.wrap(std_import) + imports = js_imports |> Enum.map(fn {module, path} -> import_module(module, path) {module, path, true} -> import_module(module, path) diff --git a/lib/elixir_script/module_systems/umd.ex b/lib/elixir_script/module_systems/umd.ex index a3d6c794..b86cefbf 100644 --- a/lib/elixir_script/module_systems/umd.ex +++ b/lib/elixir_script/module_systems/umd.ex @@ -5,10 +5,10 @@ defmodule ElixirScript.ModuleSystems.UMD do alias ElixirScript.Translator.State alias ElixirScript.Translator.Utils - def build(std_import, imports, js_imports, body, exports) do + def build(imports, js_imports, body, exports) do module_imports = Enum.map(imports, fn {module, path} -> import_module(module, path) end) - imports = js_imports ++ List.wrap(std_import) + imports = js_imports |> Enum.map(fn {module, path} -> import_module(module, path) {module, path, true} -> import_module(module, path) diff --git a/lib/elixir_script/passes/consolidate_protocols.ex b/lib/elixir_script/passes/consolidate_protocols.ex index 0da5f108..0e92b62b 100644 --- a/lib/elixir_script/passes/consolidate_protocols.ex +++ b/lib/elixir_script/passes/consolidate_protocols.ex @@ -92,7 +92,6 @@ defmodule ElixirScript.Passes.ConsolidateProtocols do name: name, module: String.to_atom(protocol_name <> ".DefImpl"), std_lib: {:Elixir, Utils.make_local_file_path(:elixir, compiler_opts.core_path, compiler_opts.root, nil)}, - js_imports: [], imports: defimpl_imports, body: [declaration] ++ body, exports: JS.identifier("impls"), diff --git a/lib/elixir_script/passes/create_js_modules.ex b/lib/elixir_script/passes/create_js_modules.ex index 31352087..0125bab9 100644 --- a/lib/elixir_script/passes/create_js_modules.ex +++ b/lib/elixir_script/passes/create_js_modules.ex @@ -4,12 +4,12 @@ defmodule ElixirScript.Passes.CreateJSModules do alias ESTree.Tools.Builder, as: JS def execute(compiler_data, opts) do - namespace_modules = Enum.reduce(compiler_data.data, %{ js_imports: [], body: [] }, fn + namespace_modules = Enum.reduce(compiler_data.data, [], fn ({_, %{load_only: true} = module_data}, acc) -> acc ({module_name, module_data}, acc) -> - {js_imports, body} = generate_namespace_module( + body = generate_namespace_module( module_data.type, module_name, Map.get(module_data, :javascript_module, module_data), @@ -17,11 +17,10 @@ defmodule ElixirScript.Passes.CreateJSModules do compiler_data.state ) - Map.update!(acc, :js_imports, fn x -> x ++ js_imports end) - |> Map.update!(:body, fn x -> x ++ body end) + acc ++ List.wrap(body) end) - compiled = compile(namespace_modules.js_imports, namespace_modules.body, opts) + compiled = compile(namespace_modules, opts) Map.put(compiler_data, :compiled, compiled) end @@ -41,7 +40,7 @@ defmodule ElixirScript.Passes.CreateJSModules do env ) - {js_module.js_imports, body} + body end defp generate_namespace_module(_, module_name, js_module, _, _) do @@ -53,14 +52,13 @@ defmodule ElixirScript.Passes.CreateJSModules do js_module.env ) - {js_module.js_imports, body} + body end - defp compile(js_imports, body, opts) do + defp compile(body, opts) do ast = opts.module_formatter.build( - {:Elixir, "./Elixir.Bootstrap", true }, [], - js_imports, + [{:Elixir, "./Elixir.Bootstrap", true }] ++ opts.js_modules, body, JS.identifier("Elixir") ) diff --git a/lib/elixir_script/translator/kernel/defimpl.ex b/lib/elixir_script/translator/kernel/defimpl.ex index 2c4c45ae..78d61a88 100644 --- a/lib/elixir_script/translator/kernel/defimpl.ex +++ b/lib/elixir_script/translator/kernel/defimpl.ex @@ -8,7 +8,7 @@ defmodule ElixirScript.Translator.Defimpl do def make(name, type, body, env) do type = map_to_js(type, env) - {imports, js_imports, body, export} = Defmodule.process_module(name, body, env) + {imports, body, export} = Defmodule.process_module(name, body, env) protocol_name = Atom.to_string(name) |> String.split(".DefImpl.") |> hd |> String.to_atom @@ -27,7 +27,6 @@ defmodule ElixirScript.Translator.Defimpl do name: Utils.quoted_to_name({:__aliases__, [], name }), std_lib: Defmodule.make_std_lib_import(env), imports: imports, - js_imports: js_imports, exports: export, body: body, app_name: State.get_module(env.state, name).app, diff --git a/lib/elixir_script/translator/kernel/defmodule.ex b/lib/elixir_script/translator/kernel/defmodule.ex index 5ccb4bf4..f35a8868 100644 --- a/lib/elixir_script/translator/kernel/defmodule.ex +++ b/lib/elixir_script/translator/kernel/defmodule.ex @@ -13,7 +13,6 @@ defmodule ElixirScript.Translator.Defmodule do %{ name: ElixirScript.Temp, std_lib: make_std_lib_import(env), - js_imports: [], imports: [], body: body |> Group.inflate_groups, exports: nil, @@ -26,7 +25,6 @@ defmodule ElixirScript.Translator.Defmodule do %{ name: module, std_lib: make_std_lib_import(env), - js_imports: [], imports: [], body: [], exports: nil, @@ -36,14 +34,13 @@ defmodule ElixirScript.Translator.Defmodule do end def make_module(module, body, env) do - {imports, js_imports, body, exported_object} = process_module(module, body, env) + {imports, body, exported_object} = process_module(module, body, env) app_name = State.get_module(env.state, module).app result = %{ name: Utils.quoted_to_name({:__aliases__, [], module }), std_lib: make_std_lib_import(env), imports: imports, - js_imports: js_imports, exports: exported_object, body: body, app_name: app_name, @@ -86,10 +83,9 @@ defmodule ElixirScript.Translator.Defmodule do module_refs = State.get_module_references(env.state, env.module) -- [env.module] imports = process_module_refs(module_refs, env) - js_imports = State.get_javascript_module_references(env.state, env.module) body = structs ++ private_functions ++ exported_functions ++ body - {imports, js_imports, body, exported_object} + {imports, body, exported_object} end def make_std_lib_import(env) do diff --git a/lib/elixir_script/translator/kernel/defprotocol.ex b/lib/elixir_script/translator/kernel/defprotocol.ex index cae6ad52..318c3c57 100644 --- a/lib/elixir_script/translator/kernel/defprotocol.ex +++ b/lib/elixir_script/translator/kernel/defprotocol.ex @@ -77,12 +77,10 @@ defmodule ElixirScript.Translator.Defprotocol do module_refs = State.get_module_references(env.state, env.module) -- [env.module] imports = Defmodule.process_module_refs(module_refs, env) - js_imports = State.get_javascript_module_references(env.state, env.module) %{ name: name, std_lib: Defmodule.make_std_lib_import(env), - js_imports: js_imports, imports: imports ++ [{implementation_name_module, ""}], body: body, exports: JS.identifier(Utils.name_to_js_name(name)), diff --git a/test/elixir_script_test.exs b/test/elixir_script_test.exs index aed71914..0053603b 100644 --- a/test/elixir_script_test.exs +++ b/test/elixir_script_test.exs @@ -4,7 +4,7 @@ defmodule ElixirScript.Test do test "turn javascript ast into javascript code strings" do js_code = ElixirScript.compile(":atom") - assert Enum.join(js_code, "\n") |> String.trim == "Symbol.for('atom')" + assert_js_matches "Symbol.for('atom')", js_code end @@ -22,17 +22,13 @@ defmodule ElixirScript.Test do """, %{ env: make_custom_env() }) assert_js_matches """ - import Elixir$ElixirScript$Kernel from '../elixir/Elixir.ElixirScript.Kernel'; const something_else = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.clause([],function() { return 1 * 1; })); const sandwich = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.clause([],function() { return null; })); - export default { - sandwich - }; - """, List.last(js_code) + """, js_code end @@ -50,16 +46,12 @@ defmodule ElixirScript.Test do """, %{ env: make_custom_env(), core_path: "elixirscript"} ) assert_js_matches """ - import Elixir$ElixirScript$Kernel from '../elixir/Elixir.ElixirScript.Kernel'; const something_else = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.clause([],function() { return 1 * 1; })); const sandwich = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.clause([],function() { return null; })); - export default { - sandwich - }; - """, List.last(js_code) + """, js_code end end diff --git a/test/test_helper.exs b/test/test_helper.exs index 3cc39872..7d3e45ea 100644 --- a/test/test_helper.exs +++ b/test/test_helper.exs @@ -43,8 +43,9 @@ defmodule ElixirScript.TestHelper do def assert_translation(ex_ast, js_code, format) do converted_code = ex_ast_to_js(ex_ast, format) + |> strip_spaces - assert converted_code |> strip_spaces == strip_spaces(js_code), """ + assert converted_code =~ strip_spaces(js_code), """ **Code Does Not Match ** ***Expected*** @@ -56,7 +57,8 @@ defmodule ElixirScript.TestHelper do end def assert_js_matches(expected_js_code, actual_js_code) do - assert strip_spaces(expected_js_code) == strip_spaces(actual_js_code), """ + actual_js_code = hd(List.wrap(actual_js_code)) + assert strip_spaces(actual_js_code) =~ strip_spaces(expected_js_code), """ **Code Does Not Match ** ***Expected*** diff --git a/test/translator/bug_test.exs b/test/translator/bug_test.exs index cfb474bc..48dfcb15 100644 --- a/test/translator/bug_test.exs +++ b/test/translator/bug_test.exs @@ -46,10 +46,7 @@ defmodule ElixirScript.Translator.Bug.Test do end js_code = """ - import JQuery from 'jquery'; - import Elixir$ElixirScript$Kernel from '../elixir/Elixir.ElixirScript.Kernel'; JQuery(Elixir.Core.Functions.call_property(e,'target')); - export default {}; """ assert_translation(ex_ast, js_code) diff --git a/test/translator/commonjs_test.exs b/test/translator/commonjs_test.exs index 72bddc1c..89842df9 100644 --- a/test/translator/commonjs_test.exs +++ b/test/translator/commonjs_test.exs @@ -17,123 +17,7 @@ defmodule ElixirScript.Translator.CommonJS.Test do end js_code = """ - const Elixir$ElixirScript$Kernel = require('../elixir/Elixir.ElixirScript.Kernel'); - - const something_else = Elixir.Core.Patterns.defmatchgen(Elixir.Core.Patterns.clause([], function*() { - return null; - })); - - const something = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.clause([], function() { - return ul; - })); - - const ul = JQuery('#todo-list'); - - module.exports = { - something - } - """ - - assert_translation(ex_ast, js_code, :common) - end - - test "protocol to commonjs" do - ex_ast = quote do - defprotocol Blank do - def blank?(data) - end - - defimpl Blank, for: Integer do - def blank?(number), do: false - end - - defimpl Blank, for: List do - def blank?([]), do: true - def blank?(_), do: false - end - - defimpl Blank, for: Atom do - def blank?(false), do: true - def blank?(nil), do: true - def blank?(_), do: false - end - end - - js_code = """ - const Elixir = require('../elixir/Elixir.Bootstrap'); - - const Elixir$Blank$DefImpl$Elixir$Integer = require('../app/Elixir.Blank.DefImpl.Elixir.Integer'); - - const Elixir$Blank$DefImpl$Elixir$List = require('../app/Elixir.Blank.DefImpl.Elixir.List'); - - const Elixir$Blank$DefImpl$Elixir$Atom = require('../app/Elixir.Blank.DefImpl.Elixir.Atom'); - - let impls = []; - - impls.push(Elixir$Blank$DefImpl$Elixir$Integer) - - impls.push(Elixir$Blank$DefImpl$Elixir$List) - - impls.push(Elixir$Blank$DefImpl$Elixir$Atom) - - module.exports = impls - - const Implementations = require('../app/Elixir.Blank.Defimpl'); - - const Elixir$ElixirScript$Kernel = require('../elixir/Elixir.ElixirScript.Kernel'); - - const Elixir$Blank = Elixir.Core.Functions.defprotocol({ - blank__qmark__: function() {} - }); - - for (let {Type, Implementation} of Implementations) Elixir.Core.Functions.defimpl(Elixir$Blank, Type, Implementation) - - module.exports = Elixir$Blank - - const Elixir$ElixirScript$Kernel = require('../elixir/Elixir.ElixirScript.Kernel'); - - const blank__qmark__ = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.clause([Elixir.Core.Patterns.variable()], function(number) { - return false; - })); - - module.exports = { - 'Type': Elixir.Core.Integer, - 'Implementation': { - blank__qmark__ - } - } - - const Elixir$ElixirScript$Kernel = require('../elixir/Elixir.ElixirScript.Kernel'); - - const blank__qmark__ = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.clause([Object.freeze([])], function() { - return true; - }), Elixir.Core.Patterns.clause([Elixir.Core.Patterns.wildcard()], function() { - return false; - })); - - module.exports = { - 'Type': Array, - 'Implementation': { - blank__qmark__ - } - } - - const Elixir$ElixirScript$Kernel = require('../elixir/Elixir.ElixirScript.Kernel'); - - const blank__qmark__ = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.clause([false], function() { - return true; - }), Elixir.Core.Patterns.clause([null], function() { - return true; - }), Elixir.Core.Patterns.clause([Elixir.Core.Patterns.wildcard()], function() { - return false; - })); - - module.exports = { - 'Type': Symbol, - 'Implementation': { - blank__qmark__ - } - } + module.exports = Elixir """ assert_translation(ex_ast, js_code, :common) diff --git a/test/translator/defmodule_test.exs b/test/translator/defmodule_test.exs index 4e204f48..2fb26520 100644 --- a/test/translator/defmodule_test.exs +++ b/test/translator/defmodule_test.exs @@ -9,8 +9,7 @@ defmodule ElixirScript.Translator.Defmodule.Test do end js_code = """ - import Elixir$ElixirScript$Kernel from '../elixir/Elixir.ElixirScript.Kernel'; - export default {}; + const values = {}; """ assert_translation(ex_ast, js_code) @@ -31,8 +30,6 @@ defmodule ElixirScript.Translator.Defmodule.Test do end js_code = """ - - import Elixir$ElixirScript$Kernel from '../elixir/Elixir.ElixirScript.Kernel'; const something_else = Elixir.Core.Patterns.defmatchgen(Elixir.Core.Patterns.clause([],function*() { return null; })); @@ -40,9 +37,6 @@ defmodule ElixirScript.Translator.Defmodule.Test do return ul; })); const ul = JQuery('#todo-list'); - export default { - something - }; """ assert_translation(ex_ast, js_code) @@ -67,28 +61,9 @@ defmodule ElixirScript.Translator.Defmodule.Test do end js_code = """ - import Elixir$ElixirScript$Kernel from '../elixir/Elixir.ElixirScript.Kernel'; - import Elixir$Animals$Elephant from '../app/Elixir.Animals.Elephant'; - const something_else = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.clause([],function() { - return null; - })); - - const something = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.clause([],function() { - return Elixir$Animals$Elephant.Elixir$Animals$Elephant.create(Object.freeze({})); - })); - - export default { - something - }; - - import Elixir$ElixirScript$Kernel from '../elixir/Elixir.ElixirScript.Kernel'; const Elixir$Animals$Elephant = Elixir.Core.Functions.defstruct({ [Symbol.for('__struct__')]: Symbol.for('Elixir.Animals.Elephant'), [Symbol.for('trunk')]: true }); - - export default { - Elixir$Animals$Elephant - }; """ assert_translation(ex_ast, js_code) @@ -119,38 +94,10 @@ defmodule ElixirScript.Translator.Defmodule.Test do end js_code = """ - import Elixir$ElixirScript$Kernel from '../elixir/Elixir.ElixirScript.Kernel'; - import Elixir$Animals$Elephant from '../app/Elixir.Animals.Elephant'; - const something_else = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.clause([],function() { - return null; - })); - const something = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.clause([],function() { - return Elixir$Animals$Elephant.Elixir$Animals$Elephant.create(Object.freeze({})); - })); - - export default { - something - }; - - import Elixir$ElixirScript$Kernel from '../elixir/Elixir.ElixirScript.Kernel'; - import Elixir$Animals$Elephant$Bear from '../app/Elixir.Animals.Elephant.Bear'; - const Elixir$Animals$Elephant = Elixir.Core.Functions.defstruct({ - [Symbol.for('__struct__')]: Symbol.for('Elixir.Animals.Elephant'), - [Symbol.for('trunk')]: true - }); - export default { - Elixir$Animals$Elephant - }; - - import Elixir$ElixirScript$Kernel from '../elixir/Elixir.ElixirScript.Kernel'; const Elixir$Animals$Elephant$Bear = Elixir.Core.Functions.defstruct({ [Symbol.for('__struct__')]: Symbol.for('Elixir.Animals.Elephant.Bear'), [Symbol.for('trunk')]: true }); - - export default { - Elixir$Animals$Elephant$Bear - }; """ assert_translation(ex_ast, js_code) @@ -168,171 +115,7 @@ defmodule ElixirScript.Translator.Defmodule.Test do end js_code = """ - import Elixir$ElixirScript$Kernel from '../elixir/Elixir.ElixirScript.Kernel'; - import Elixir$Lions$Tigers from '../app/Elixir.Lions.Tigers'; - Elixir.Core.Functions.call_property(Elixir$Lions$Tigers,'oh_my'); - export default {}; - - import Elixir$ElixirScript$Kernel from '../elixir/Elixir.ElixirScript.Kernel'; - Elixir.Core.Functions.call_property(Lions.Tigers.Bears,'oh_my'); - export default {}; - """ - - assert_translation(ex_ast, js_code) - end - - test "ignore aliases already added" do - ex_ast = quote do - defmodule Animals do - alias Lions.Tigers - - Tigers.oh_my() - end - - defmodule Lions.Tigers do - Lions.Tigers.Bears.oh_my() - - def oh_my() do - end - end - end - - js_code = """ - import Elixir$ElixirScript$Kernel from '../elixir/Elixir.ElixirScript.Kernel'; - import Elixir$Lions$Tigers from '../app/Elixir.Lions.Tigers'; - Elixir.Core.Functions.call_property(Elixir$Lions$Tigers,'oh_my'); - export default {}; - - import Elixir$ElixirScript$Kernel from '../elixir/Elixir.ElixirScript.Kernel'; - const oh_my = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.clause([],function() { - return null; - })); Elixir.Core.Functions.call_property(Lions.Tigers.Bears,'oh_my'); - export default { - oh_my - }; - """ - - assert_translation(ex_ast, js_code) - end - - test "import only" do - ex_ast = quote do - defmodule Lions.Tigers do - def oh_my() do - end - - def oh_my2() do - end - end - - defmodule Animals do - import Lions.Tigers, only: [oh_my: 0] - - oh_my() - end - end - - js_code = """ - import Elixir$ElixirScript$Kernel from '../elixir/Elixir.ElixirScript.Kernel'; - - const oh_my = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.clause([], function() { - return null; - })); - - const oh_my2 = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.clause([], function() { - return null; - })); - - export default { - oh_my, - oh_my2 - }; - - import Elixir$ElixirScript$Kernel from '../elixir/Elixir.ElixirScript.Kernel'; - - import Elixir$Lions$Tigers from '../app/Elixir.Lions.Tigers'; - - Elixir$Lions$Tigers.oh_my(); - - export default {}; - """ - - assert_translation(ex_ast, js_code) - end - - test "import except" do - ex_ast = quote do - defmodule Lions.Tigers do - def oh_my() do - end - - def oh_my2() do - end - end - - defmodule Animals do - import Lions.Tigers, except: [oh_my: 1] - - oh_my2() - end - end - - js_code = """ - import Elixir$ElixirScript$Kernel from '../elixir/Elixir.ElixirScript.Kernel'; - - const oh_my = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.clause([], function() { - return null; - })); - - const oh_my2 = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.clause([], function() { - return null; - })); - - export default { - oh_my, - oh_my2 - }; - - import Elixir$ElixirScript$Kernel from '../elixir/Elixir.ElixirScript.Kernel'; - - import Elixir$Lions$Tigers from '../app/Elixir.Lions.Tigers'; - - Elixir$Lions$Tigers.oh_my2(); - - export default {}; - """ - - assert_translation(ex_ast, js_code) - end - - - test "translate inner module has another inner module alias" do - ex_ast = quote do - defmodule Version do - defmodule Parser do - import Parser.DSL - end - - defmodule Parser.DSL do - - end - end - end - - js_code = """ - import Elixir$ElixirScript$Kernel from '../elixir/Elixir.ElixirScript.Kernel'; - import Elixir$Version$Parser from '../app/Elixir.Version.Parser'; - import Elixir$Version$Parser$DSL from '../app/Elixir.Version.Parser.DSL'; - export default {}; - - import Elixir$ElixirScript$Kernel from '../elixir/Elixir.ElixirScript.Kernel'; - import Elixir$Version$Parser from '../app/Elixir.Version.Parser'; - export default {}; - - import Elixir$ElixirScript$Kernel from '../elixir/Elixir.ElixirScript.Kernel'; - import Elixir$Version$Parser$DSL from '../app/Elixir.Version.Parser.DSL'; - export default {}; """ assert_translation(ex_ast, js_code) diff --git a/test/translator/function_test.exs b/test/translator/function_test.exs index 029ee11d..09733cfd 100644 --- a/test/translator/function_test.exs +++ b/test/translator/function_test.exs @@ -240,7 +240,6 @@ defmodule ElixirScript.Translator.Function.Test do end js_code = """ - import Elixir$ElixirScript$Kernel from '../elixir/Elixir.ElixirScript.Kernel'; const example = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.clause([],function() { return null; }),Elixir.Core.Patterns.clause([Elixir.Core.Patterns.variable()],function(oneArg) { @@ -252,7 +251,6 @@ defmodule ElixirScript.Translator.Function.Test do }),Elixir.Core.Patterns.clause([Elixir.Core.Patterns.variable(), Elixir.Core.Patterns.variable(), Elixir.Core.Patterns.variable(), Elixir.Core.Patterns.variable()],function(oneArg,twoArg,redArg,blueArg) { return null; })); - export default {}; """ assert_translation(ex_ast, js_code) @@ -277,7 +275,6 @@ defmodule ElixirScript.Translator.Function.Test do end js_code = """ - import Elixir$ElixirScript$Kernel from '../elixir/Elixir.ElixirScript.Kernel'; const example = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.clause([],function() { return null; }),Elixir.Core.Patterns.clause([Elixir.Core.Patterns.variable()],function(oneArg) { @@ -289,9 +286,6 @@ defmodule ElixirScript.Translator.Function.Test do }),Elixir.Core.Patterns.clause([Elixir.Core.Patterns.variable(), Elixir.Core.Patterns.variable(), Elixir.Core.Patterns.variable(), Elixir.Core.Patterns.variable()],function(oneArg,twoArg,redArg,blueArg) { return null; })); - export default { - example - }; """ assert_translation(ex_ast, js_code) @@ -304,13 +298,9 @@ defmodule ElixirScript.Translator.Function.Test do end js_code = """ - import Elixir$ElixirScript$Kernel from '../elixir/Elixir.ElixirScript.Kernel'; const example = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.clause([Elixir.Core.Patterns.variable()],function(oneArg) { return null; })); - export default { - example - }; """ assert_translation(ex_ast, js_code) @@ -422,7 +412,6 @@ defmodule ElixirScript.Translator.Function.Test do end js_code = """ - import Elixir$ElixirScript$Kernel from '../elixir/Elixir.ElixirScript.Kernel'; const something = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.clause([Elixir.Core.Patterns.variable()],function(one) { return null; },function(one) { @@ -432,9 +421,6 @@ defmodule ElixirScript.Translator.Function.Test do },function(one) { return Elixir$ElixirScript$Kernel.is_number(one) || Elixir$ElixirScript$Kernel.is_atom(one); })); - export default { - something - }; """ assert_translation(ex_ast, js_code) @@ -653,7 +639,6 @@ defmodule ElixirScript.Translator.Function.Test do js_code = """ - import Elixir$ElixirScript$Kernel from '../elixir/Elixir.ElixirScript.Kernel'; const something = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.clause([1],function() { return null; }),Elixir.Core.Patterns.clause([2],function() { @@ -665,9 +650,6 @@ defmodule ElixirScript.Translator.Function.Test do }),Elixir.Core.Patterns.clause([Elixir.Core.Patterns.variable()],function(one) { return null; })); - export default { - something - }; """ assert_translation(ex_ast, js_code) diff --git a/test/translator/protocol_test.exs b/test/translator/protocol_test.exs deleted file mode 100644 index 26d79de7..00000000 --- a/test/translator/protocol_test.exs +++ /dev/null @@ -1,89 +0,0 @@ -defmodule ElixirScript.Translator.Defprotocol.Test do - use ExUnit.Case - import ElixirScript.TestHelper - - test "parse protocol spec with implementations" do - ex_ast = quote do - defprotocol Blank do - def blank?(data) - end - - defimpl Blank, for: Integer do - def blank?(number), do: false - end - - defimpl Blank, for: List do - def blank?([]), do: true - def blank?(_), do: false - end - - defimpl Blank, for: Atom do - def blank?(false), do: true - def blank?(nil), do: true - def blank?(_), do: false - end - end - - js_code = """ - import Elixir from '../elixir/Elixir.Bootstrap'; - import Elixir$Blank$DefImpl$Elixir$Integer from '../app/Elixir.Blank.DefImpl.Elixir.Integer'; - import Elixir$Blank$DefImpl$Elixir$List from '../app/Elixir.Blank.DefImpl.Elixir.List'; - import Elixir$Blank$DefImpl$Elixir$Atom from '../app/Elixir.Blank.DefImpl.Elixir.Atom'; - - let impls = []; - impls.push(Elixir$Blank$DefImpl$Elixir$Integer) - impls.push(Elixir$Blank$DefImpl$Elixir$List) - impls.push(Elixir$Blank$DefImpl$Elixir$Atom) - export default impls; - - import Implementations from '../app/Elixir.Blank.Defimpl'; - import Elixir$ElixirScript$Kernel from '../elixir/Elixir.ElixirScript.Kernel'; - const Elixir$Blank = Elixir.Core.Functions.defprotocol({ - blank__qmark__: function() { - - } - }); - for(let {Type,Implementation} of Implementations) Elixir.Core.Functions.defimpl(Elixir$Blank,Type,Implementation) - export default Elixir$Blank; - - import Elixir$ElixirScript$Kernel from '../elixir/Elixir.ElixirScript.Kernel'; - const blank__qmark__ = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.clause([Elixir.Core.Patterns.variable()],function(number) { - return false; - })); - export default { - 'Type': Elixir.Core.Integer, 'Implementation': { - blank__qmark__ - } - }; - - import Elixir$ElixirScript$Kernel from '../elixir/Elixir.ElixirScript.Kernel'; - const blank__qmark__ = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.clause([Object.freeze([])],function() { - return true; - }),Elixir.Core.Patterns.clause([Elixir.Core.Patterns.wildcard()],function() { - return false; - })); - export default { - 'Type': Array, 'Implementation': { - blank__qmark__ - } - }; - - import Elixir$ElixirScript$Kernel from '../elixir/Elixir.ElixirScript.Kernel'; - const blank__qmark__ = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.clause([false],function() { - return true; - }),Elixir.Core.Patterns.clause([null],function() { - return true; - }),Elixir.Core.Patterns.clause([Elixir.Core.Patterns.wildcard()],function() { - return false; - })); - export default { - 'Type': Symbol, 'Implementation': { - blank__qmark__ - } - }; - """ - - assert_translation(ex_ast, js_code) - end - -end diff --git a/test/translator/struct_test.exs b/test/translator/struct_test.exs index 4d7248b5..50dce2c2 100644 --- a/test/translator/struct_test.exs +++ b/test/translator/struct_test.exs @@ -10,16 +10,11 @@ defmodule ElixirScript.Translator.Struct.Test do end js_code = """ - import Elixir$ElixirScript$Kernel from '../elixir/Elixir.ElixirScript.Kernel'; const Elixir$User = Elixir.Core.Functions.defstruct({ [Symbol.for('__struct__')]: Symbol.for('Elixir.User'), [Symbol.for('name')]: 'john', [Symbol.for('age')]: 27 }); - - export default { - Elixir$User - }; """ assert_translation(ex_ast, js_code) @@ -34,15 +29,11 @@ defmodule ElixirScript.Translator.Struct.Test do end js_code = """ - import Elixir$ElixirScript$Kernel from '../elixir/Elixir.ElixirScript.Kernel'; const Elixir$User = Elixir.Core.Functions.defstruct({ [Symbol.for('__struct__')]: Symbol.for('Elixir.User'), [Symbol.for('name')]: null, [Symbol.for('age')]: null }); - export default { - Elixir$User - }; """ assert_translation(ex_ast, js_code) @@ -59,19 +50,11 @@ defmodule ElixirScript.Translator.Struct.Test do end js_code = """ - - import Elixir$ElixirScript$Kernel from '../elixir/Elixir.ElixirScript.Kernel'; const Elixir$User = Elixir.Core.Functions.defstruct({ [Symbol.for('__struct__')]: Symbol.for('Elixir.User'), [Symbol.for('name')]: null, [Symbol.for('age')]: null }); - - export default { - Elixir$User - }; - - let [user] = Elixir.Core.Patterns.match(Elixir.Core.Patterns.variable(), Elixir$User.Elixir$User.create(Object.freeze({}))); """ assert_translation(ex_ast, js_code) @@ -85,19 +68,12 @@ defmodule ElixirScript.Translator.Struct.Test do end js_code = """ - import Elixir$ElixirScript$Kernel from '../elixir/Elixir.ElixirScript.Kernel'; const Elixir$User = Elixir.Core.Functions.defstruct({ [Symbol.for('__struct__')]: Symbol.for('Elixir.User'), [Symbol.for('name')]: null, [Symbol.for('age')]: null }); - export default { - Elixir$User - }; - let [user] = Elixir.Core.Patterns.match(Elixir.Core.Patterns.variable(),Elixir$User.Elixir$User.create(Object.freeze({ - [Symbol.for('name')]: 'John' - }))); """ assert_translation(ex_ast, js_code) @@ -138,15 +114,11 @@ defmodule ElixirScript.Translator.Struct.Test do end js_code = """ - import Elixir$ElixirScript$Kernel from '../elixir/Elixir.ElixirScript.Kernel'; const Elixir$MyAppError = Elixir.Core.Functions.defexception({ [Symbol.for('__struct__')]: Symbol.for('Elixir.MyAppError'), [Symbol.for('__exception__')]: true, [Symbol.for('message')]: 'This is a message' }); - export default { - Elixir$MyAppError - }; """ assert_translation(ex_ast, js_code) @@ -158,16 +130,11 @@ defmodule ElixirScript.Translator.Struct.Test do end js_code = """ - import Elixir$ElixirScript$Kernel from '../elixir/Elixir.ElixirScript.Kernel'; const Elixir$MyAppError = Elixir.Core.Functions.defexception({ [Symbol.for('__struct__')]: Symbol.for('Elixir.MyAppError'), [Symbol.for('__exception__')]: true, [Symbol.for('message')]: null }); - - export default { - Elixir$MyAppError - }; """ assert_translation(ex_ast, js_code) @@ -184,17 +151,6 @@ defmodule ElixirScript.Translator.Struct.Test do end js_code = """ - import Elixir$ElixirScript$Kernel from '../elixir/Elixir.ElixirScript.Kernel'; - const Elixir$MyAppError = Elixir.Core.Functions.defexception({ - [Symbol.for('__struct__')]: Symbol.for('Elixir.MyAppError'), - [Symbol.for('__exception__')]: true, - [Symbol.for('message')]: null - }); - - export default { - Elixir$MyAppError - }; - throw Elixir$MyAppError.Elixir$MyAppError.create(Object.freeze({ [Symbol.for('message')]: 'did not get what was expected' })); diff --git a/test/translator/umd_test.exs b/test/translator/umd_test.exs index 9a231f58..9256c3f3 100644 --- a/test/translator/umd_test.exs +++ b/test/translator/umd_test.exs @@ -18,162 +18,6 @@ defmodule ElixirScript.Translator.UMD.Test do js_code = """ (function(root, factory) { - if (typeof define === 'function' && define.amd) { - define(['../elixir/Elixir.ElixirScript.Kernel'], factory) - } else if (typeof exports === 'object') { - module.exports = factory(require('../elixir/Elixir.ElixirScript.Kernel')) - } else { - root.returnExports = factory(root.Elixir$ElixirScript$Kernel) - } - })(this, function(Elixir$ElixirScript$Kernel) { - const something_else = Elixir.Core.Patterns.defmatchgen(Elixir.Core.Patterns.clause([], function*() { - return null; - })); - - const something = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.clause([], function() { - return ul; - })); - - const ul = JQuery('#todo-list'); - - return { - something - }; - }); - """ - - assert_translation(ex_ast, js_code, :umd) - end - - test "protocol to umd" do - ex_ast = quote do - defprotocol Blank do - def blank?(data) - end - - defimpl Blank, for: Integer do - def blank?(number), do: false - end - - defimpl Blank, for: List do - def blank?([]), do: true - def blank?(_), do: false - end - - defimpl Blank, for: Atom do - def blank?(false), do: true - def blank?(nil), do: true - def blank?(_), do: false - end - end - - js_code = """ - (function(root, factory) { - if (typeof define === 'function' && define.amd) { - define(['../elixir/Elixir.Bootstrap', '../app/Elixir.Blank.DefImpl.Elixir.Integer', '../app/Elixir.Blank.DefImpl.Elixir.List', '../app/Elixir.Blank.DefImpl.Elixir.Atom'], factory) - } else if (typeof exports === 'object') { - module.exports = factory(require('../elixir/Elixir.Bootstrap'), require('../app/Elixir.Blank.DefImpl.Elixir.Integer'), require('../app/Elixir.Blank.DefImpl.Elixir.List'), require('../app/Elixir.Blank.DefImpl.Elixir.Atom')) - } else { - root.returnExports = factory(root.Elixir, root.Elixir$Blank$DefImpl$Elixir$Integer, root.Elixir$Blank$DefImpl$Elixir$List, root.Elixir$Blank$DefImpl$Elixir$Atom) - } - })(this, function(Elixir, Elixir$Blank$DefImpl$Elixir$Integer, Elixir$Blank$DefImpl$Elixir$List, Elixir$Blank$DefImpl$Elixir$Atom) { - let impls = []; - - impls.push(Elixir$Blank$DefImpl$Elixir$Integer) - - impls.push(Elixir$Blank$DefImpl$Elixir$List) - - impls.push(Elixir$Blank$DefImpl$Elixir$Atom) - - return impls; - }); - - (function(root, factory) { - if (typeof define === 'function' && define.amd) { - define(['../app/Elixir.Blank.Defimpl', '../elixir/Elixir.ElixirScript.Kernel'], factory) - } else if (typeof exports === 'object') { - module.exports = factory(require('../app/Elixir.Blank.Defimpl'), require('../elixir/Elixir.ElixirScript.Kernel')) - } else { - root.returnExports = factory(root.Implementations, root.Elixir$ElixirScript$Kernel) - } - })(this, function(Implementations, Elixir$ElixirScript$Kernel) { - const Elixir$Blank = Elixir.Core.Functions.defprotocol({ - blank__qmark__: function() {} - }); - - for (let {Type, Implementation} of Implementations) Elixir.Core.Functions.defimpl(Elixir$Blank, Type, Implementation) - - return Elixir$Blank; - }); - - (function(root, factory) { - if (typeof define === 'function' && define.amd) { - define(['../elixir/Elixir.ElixirScript.Kernel'], factory) - } else if (typeof exports === 'object') { - module.exports = factory(require('../elixir/Elixir.ElixirScript.Kernel')) - } else { - root.returnExports = factory(root.Elixir$ElixirScript$Kernel) - } - })(this, function(Elixir$ElixirScript$Kernel) { - const blank__qmark__ = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.clause([Elixir.Core.Patterns.variable()], function(number) { - return false; - })); - - return { - 'Type': Elixir.Core.Integer, - 'Implementation': { - blank__qmark__ - } - }; - }); - - (function(root, factory) { - if (typeof define === 'function' && define.amd) { - define(['../elixir/Elixir.ElixirScript.Kernel'], factory) - } else if (typeof exports === 'object') { - module.exports = factory(require('../elixir/Elixir.ElixirScript.Kernel')) - } else { - root.returnExports = factory(root.Elixir$ElixirScript$Kernel) - } - })(this, function(Elixir$ElixirScript$Kernel) { - const blank__qmark__ = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.clause([Object.freeze([])], function() { - return true; - }), Elixir.Core.Patterns.clause([Elixir.Core.Patterns.wildcard()], function() { - return false; - })); - - return { - 'Type': Array, - 'Implementation': { - blank__qmark__ - } - }; - }); - - (function(root, factory) { - if (typeof define === 'function' && define.amd) { - define(['../elixir/Elixir.ElixirScript.Kernel'], factory) - } else if (typeof exports === 'object') { - module.exports = factory(require('../elixir/Elixir.ElixirScript.Kernel')) - } else { - root.returnExports = factory(root.Elixir$ElixirScript$Kernel) - } - })(this, function(Elixir$ElixirScript$Kernel) { - const blank__qmark__ = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.clause([false], function() { - return true; - }), Elixir.Core.Patterns.clause([null], function() { - return true; - }), Elixir.Core.Patterns.clause([Elixir.Core.Patterns.wildcard()], function() { - return false; - })); - - return { - 'Type': Symbol, - 'Implementation': { - blank__qmark__ - } - }; - }); """ assert_translation(ex_ast, js_code, :umd) From a1555d760bb4e65752a8f733b82e4feda35b9156 Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Tue, 21 Feb 2017 23:06:45 -0600 Subject: [PATCH 410/860] Fix assert translation --- test/test_helper.exs | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/test/test_helper.exs b/test/test_helper.exs index 7d3e45ea..16090d48 100644 --- a/test/test_helper.exs +++ b/test/test_helper.exs @@ -43,9 +43,8 @@ defmodule ElixirScript.TestHelper do def assert_translation(ex_ast, js_code, format) do converted_code = ex_ast_to_js(ex_ast, format) - |> strip_spaces - assert converted_code =~ strip_spaces(js_code), """ + assert converted_code |> strip_spaces =~ strip_spaces(js_code), """ **Code Does Not Match ** ***Expected*** @@ -57,8 +56,7 @@ defmodule ElixirScript.TestHelper do end def assert_js_matches(expected_js_code, actual_js_code) do - actual_js_code = hd(List.wrap(actual_js_code)) - assert strip_spaces(actual_js_code) =~ strip_spaces(expected_js_code), """ + assert strip_spaces(hd(List.wrap(actual_js_code))) =~ strip_spaces(expected_js_code), """ **Code Does Not Match ** ***Expected*** From e3760d6f801eb84da702c39f4f687eb0435657c3 Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Wed, 22 Feb 2017 04:48:12 -0600 Subject: [PATCH 411/860] Rename Elixir import identifier to Bootstrap. Removed on_js_load and now look for start function --- lib/elixir_script.ex | 9 +- lib/elixir_script/module_systems/namespace.ex | 32 ++-- lib/elixir_script/passes/create_js_modules.ex | 39 +++- lib/elixir_script/translator.ex | 10 +- .../translator/kernel/defimpl.ex | 17 +- .../translator/kernel/defmodule.ex | 14 -- .../translator/kernel/defprotocol.ex | 5 +- .../kernel/special_forms/bitstring.ex | 4 +- .../translator/kernel/special_forms/call.ex | 2 +- .../translator/kernel/special_forms/fn.ex | 2 +- .../translator/kernel/special_forms/for.ex | 6 +- .../translator/kernel/special_forms/match.ex | 4 +- .../kernel/special_forms/primitive.ex | 6 +- .../translator/kernel/special_forms/quote.ex | 2 +- .../translator/kernel/special_forms/struct.ex | 2 +- .../translator/pattern_matching.ex | 2 +- lib/elixir_script/translator/rewriter.ex | 56 +++--- lib/elixir_script/translator/utils.ex | 4 +- lib/std_lib/agent.ex | 20 +-- lib/std_lib/base.ex | 6 +- lib/std_lib/bitwise.ex | 24 +-- lib/std_lib/integer.ex | 4 +- lib/std_lib/js.ex | 2 +- lib/std_lib/kernel.ex | 16 +- lib/std_lib/list.ex | 4 +- lib/std_lib/map.ex | 10 +- lib/std_lib/string.ex | 8 +- lib/std_lib/tuple.ex | 8 +- test/elixir_script_test.exs | 8 +- test/translator/bitstring_test.exs | 44 ++--- test/translator/bug_test.exs | 24 +-- test/translator/capture_test.exs | 20 +-- test/translator/case_test.exs | 78 ++++---- test/translator/cond_test.exs | 10 +- test/translator/defdelegate_test.exs | 4 +- test/translator/defmodule_test.exs | 12 +- test/translator/for_test.exs | 110 ++++++------ test/translator/function_test.exs | 168 +++++++++--------- test/translator/list_test.exs | 4 +- test/translator/map_test.exs | 6 +- test/translator/match_test.exs | 34 ++-- test/translator/quote_test.exs | 26 +-- test/translator/struct_test.exs | 16 +- test/translator/try_test.exs | 42 ++--- test/translator/tuple_test.exs | 10 +- test/translator/with_test.exs | 36 ++-- 46 files changed, 495 insertions(+), 475 deletions(-) diff --git a/lib/elixir_script.ex b/lib/elixir_script.ex index 268a2678..b3da2a31 100644 --- a/lib/elixir_script.ex +++ b/lib/elixir_script.ex @@ -241,11 +241,10 @@ defmodule ElixirScript do to the specified location """ def copy_stdlib_to_destination(module_format, destination) do - Enum.each(Path.wildcard(Path.join([operating_path, to_string(module_format), "elixir", "*.js"])), fn(path) -> - base = Path.basename(path) - File.mkdir_p!(Path.join([destination, "elixir"])) - File.cp!(path, Path.join([destination, "elixir", base])) - end) + path = Path.join([operating_path, to_string(module_format), "elixir", "Elixir.Bootstrap.js"]) + base = Path.basename(path) + File.mkdir_p!(destination) + File.cp!(path, Path.join([destination, base])) end #Gets path to js files whether the mix project is available diff --git a/lib/elixir_script/module_systems/namespace.ex b/lib/elixir_script/module_systems/namespace.ex index 9bba3b6c..9ea3a549 100644 --- a/lib/elixir_script/module_systems/namespace.ex +++ b/lib/elixir_script/module_systems/namespace.ex @@ -6,7 +6,15 @@ defmodule ElixirScript.ModuleSystems.Namespace do alias ElixirScript.Translator.Utils def build(module_name, imports, body, exports, env) do - module_imports = Enum.map(imports, fn {module, path} -> + module_imports = imports + |> Enum.filter(fn + {mod, _} -> + case Module.split(mod) do + ["JS"] -> false + _ -> true + end + end) + |> Enum.map(fn {module, path} -> import_module(module, env) end) @@ -22,7 +30,7 @@ defmodule ElixirScript.ModuleSystems.Namespace do JS.member_expression( JS.call_expression( JS.member_expression( - JS.identifier(:Elixir), + JS.identifier(:Bootstrap), JS.member_expression( JS.identifier(:Core), JS.member_expression( @@ -33,9 +41,9 @@ defmodule ElixirScript.ModuleSystems.Namespace do ), [JS.identifier("Elixir"), JS.literal(Utils.name_to_js_file_name(module_name))] ), - JS.identifier("__make") + JS.identifier("__load") ), - [] + [JS.identifier("Elixir")] ) ) @@ -46,7 +54,7 @@ defmodule ElixirScript.ModuleSystems.Namespace do _self = JS.call_expression( JS.member_expression( - JS.identifier(:Elixir), + JS.identifier(:Bootstrap), JS.member_expression( JS.identifier(:Core), JS.member_expression( @@ -60,7 +68,7 @@ defmodule ElixirScript.ModuleSystems.Namespace do values = JS.member_expression( _self, - JS.identifier("values") + JS.identifier("__exports") ) _if = JS.if_statement( @@ -75,7 +83,7 @@ defmodule ElixirScript.ModuleSystems.Namespace do end declarator = JS.variable_declarator( - JS.identifier("values"), + JS.identifier("__exports"), exports ) @@ -84,15 +92,15 @@ defmodule ElixirScript.ModuleSystems.Namespace do assign = JS.assignment_expression( :=, values, - JS.identifier("values") + JS.identifier("__exports") ) - exports = [JS.return_statement(JS.identifier("values"))] + exports = [JS.return_statement(JS.identifier("__exports"))] make = JS.member_expression( JS.call_expression( JS.member_expression( - JS.identifier(:Elixir), + JS.identifier(:Bootstrap), JS.member_expression( JS.identifier(:Core), JS.member_expression( @@ -103,10 +111,10 @@ defmodule ElixirScript.ModuleSystems.Namespace do ), [JS.identifier("Elixir"), JS.literal(Utils.name_to_js_file_name(module_name))] ), - JS.identifier("__make") + JS.identifier("__load") ) - func_body = JS.block_statement([_if] ++ imports ++ body ++ [declaration, assign] ++ exports) + func_body = JS.block_statement([_if] ++ body ++ [declaration, assign] ++ imports ++ exports) func = JS.function_expression([JS.identifier("Elixir")], [], func_body) JS.assignment_expression( diff --git a/lib/elixir_script/passes/create_js_modules.ex b/lib/elixir_script/passes/create_js_modules.ex index 0125bab9..fef3095a 100644 --- a/lib/elixir_script/passes/create_js_modules.ex +++ b/lib/elixir_script/passes/create_js_modules.ex @@ -56,10 +56,45 @@ defmodule ElixirScript.Passes.CreateJSModules do end defp compile(body, opts) do + declarator = JS.variable_declarator( + JS.identifier("Elixir"), + JS.object_expression([]) + ) + + elixir = JS.variable_declaration([declarator], :const) + + start = JS.assignment_expression( + :=, + JS.member_expression( + JS.identifier("Elixir"), + JS.identifier("start") + ), + JS.function_expression( + [JS.identifier(:app), JS.identifier(:args)], + [], + JS.block_statement([ + JS.call_expression( + JS.member_expression( + JS.call_expression( + JS.member_expression( + JS.identifier(:app), + JS.identifier("__load") + ), + [JS.identifier("Elixir")] + ), + JS.identifier("start") + ), + [ElixirScript.Translator.Primitive.make_atom(:normal), JS.identifier(:args)] + ) + ]) + ) + ) + + ast = opts.module_formatter.build( [], - [{:Elixir, "./Elixir.Bootstrap", true }] ++ opts.js_modules, - body, + [{:Bootstrap, "./Elixir.Bootstrap", true }] ++ opts.js_modules, + [elixir, start] ++ body, JS.identifier("Elixir") ) diff --git a/lib/elixir_script/translator.ex b/lib/elixir_script/translator.ex index 3e6eaa52..bc41ad45 100644 --- a/lib/elixir_script/translator.ex +++ b/lib/elixir_script/translator.ex @@ -93,7 +93,7 @@ defmodule ElixirScript.Translator do defp do_translate({ one, two }, env) do quoted = quote do - JS.new(Elixir.Core.Tuple, [unquote(one), unquote(two)]) + JS.new(Bootstrap.Core.Tuple, [unquote(one), unquote(two)]) end translate(quoted, env) @@ -186,10 +186,6 @@ defmodule ElixirScript.Translator do { %ElixirScript.Translator.Empty{}, env } end - defp do_translate({:@, _, [{:on_js_load, _, [value]}]}, env) do - Call.make_function_call(value, [], env) - end - defp do_translate({:@, _, [{name, _, [value]}]}, env) do { Defmodule.make_attribute(name, value, env), env } end @@ -277,7 +273,7 @@ defmodule ElixirScript.Translator do end defp do_translate({{:., context1, [{:__aliases__, context2, [:Enum]}, function_name]}, context3, params }, env) do - translate({{:., context1, [{:__aliases__, context2, [:Elixir, :Enum]}, function_name]}, context3, params }, env) + translate({{:., context1, [{:__aliases__, context2, [:Bootstrap, :Enum]}, function_name]}, context3, params }, env) end defp do_translate({{:., _, [{:__aliases__, _, [:JS]}, function_name]}, _, params }, env) when function_name in @generator_types do @@ -465,7 +461,7 @@ defmodule ElixirScript.Translator do defp do_translate({:{}, _, elements}, env) do quoted = quote do - JS.new(Elixir.Core.Tuple, unquote(elements)) + JS.new(Bootstrap.Core.Tuple, unquote(elements)) end translate(quoted, env) diff --git a/lib/elixir_script/translator/kernel/defimpl.ex b/lib/elixir_script/translator/kernel/defimpl.ex index 78d61a88..a09a5acd 100644 --- a/lib/elixir_script/translator/kernel/defimpl.ex +++ b/lib/elixir_script/translator/kernel/defimpl.ex @@ -24,8 +24,7 @@ defmodule ElixirScript.Translator.Defimpl do ]) %{ - name: Utils.quoted_to_name({:__aliases__, [], name }), - std_lib: Defmodule.make_std_lib_import(env), + name: Utils.quoted_to_name({:__aliases__, [], name }), imports: imports, exports: export, body: body, @@ -38,7 +37,7 @@ defmodule ElixirScript.Translator.Defimpl do defp map_to_js({:__aliases__, _, [:Integer]}, _) do JS.member_expression( JS.member_expression( - JS.identifier(:Elixir), + JS.identifier(:Bootstrap), JS.identifier(:Core) ), JS.identifier(:Integer) @@ -48,7 +47,7 @@ defmodule ElixirScript.Translator.Defimpl do defp map_to_js({:__aliases__, _, [:Tuple]}, _) do JS.member_expression( JS.member_expression( - JS.identifier(:Elixir), + JS.identifier(:Bootstrap), JS.identifier(:Core) ), JS.identifier(:Tuple) @@ -66,7 +65,7 @@ defmodule ElixirScript.Translator.Defimpl do defp map_to_js({:__aliases__, _, [:BitString]}, _) do JS.member_expression( JS.member_expression( - JS.identifier(:Elixir), + JS.identifier(:Bootstrap), JS.identifier(:Core) ), JS.identifier(:BitString) @@ -76,7 +75,7 @@ defmodule ElixirScript.Translator.Defimpl do defp map_to_js({:__aliases__, _, [:Float]}, _) do JS.member_expression( JS.member_expression( - JS.identifier(:Elixir), + JS.identifier(:Bootstrap), JS.identifier(:Core) ), JS.identifier(:Float) @@ -90,7 +89,7 @@ defmodule ElixirScript.Translator.Defimpl do defp map_to_js({:__aliases__, _, [:PID]}, _) do JS.member_expression( JS.member_expression( - JS.identifier(:Elixir), + JS.identifier(:Bootstrap), JS.identifier(:Core) ), JS.identifier(:PID) @@ -99,14 +98,14 @@ defmodule ElixirScript.Translator.Defimpl do defp map_to_js({:__aliases__, _, [:Port]}, _) do JS.member_expression( - JS.identifier(:Elixir), + JS.identifier(:Bootstrap), JS.identifier(:Port) ) end defp map_to_js({:__aliases__, _, [:Reference]}, _) do JS.member_expression( - JS.identifier(:Elixir), + JS.identifier(:Bootstrap), JS.identifier(:Reference) ) end diff --git a/lib/elixir_script/translator/kernel/defmodule.ex b/lib/elixir_script/translator/kernel/defmodule.ex index f35a8868..60dc747a 100644 --- a/lib/elixir_script/translator/kernel/defmodule.ex +++ b/lib/elixir_script/translator/kernel/defmodule.ex @@ -12,7 +12,6 @@ defmodule ElixirScript.Translator.Defmodule do { body, _ } = translate_body(body, env) %{ name: ElixirScript.Temp, - std_lib: make_std_lib_import(env), imports: [], body: body |> Group.inflate_groups, exports: nil, @@ -24,7 +23,6 @@ defmodule ElixirScript.Translator.Defmodule do def make_module(module, nil, env) do %{ name: module, - std_lib: make_std_lib_import(env), imports: [], body: [], exports: nil, @@ -39,7 +37,6 @@ defmodule ElixirScript.Translator.Defmodule do result = %{ name: Utils.quoted_to_name({:__aliases__, [], module }), - std_lib: make_std_lib_import(env), imports: imports, exports: exported_object, body: body, @@ -59,7 +56,6 @@ defmodule ElixirScript.Translator.Defmodule do {structs, body} = extract_structs_from_body(body, env) - #Collect all the functions so that we can process their arity body = Enum.map(body, fn(x) -> case x do %ESTree.CallExpression{} -> @@ -88,16 +84,6 @@ defmodule ElixirScript.Translator.Defmodule do {imports, body, exported_object} end - def make_std_lib_import(env) do - compiler_opts = State.get(env.state).compiler_opts - case compiler_opts.import_standard_libs do - true -> - {:Elixir, Utils.make_local_file_path(:elixir, compiler_opts.core_path, env), true } - false -> - nil - end - end - def process_module_refs(module_refs, env) do Enum.map(module_refs, fn(x) -> {x, ""} diff --git a/lib/elixir_script/translator/kernel/defprotocol.ex b/lib/elixir_script/translator/kernel/defprotocol.ex index 318c3c57..45382fa1 100644 --- a/lib/elixir_script/translator/kernel/defprotocol.ex +++ b/lib/elixir_script/translator/kernel/defprotocol.ex @@ -26,7 +26,7 @@ defmodule ElixirScript.Translator.Defprotocol do JS.identifier(Utils.name_to_js_name(name)), JS.call_expression( JS.member_expression( - JS.identifier(:Elixir), + JS.identifier(:Bootstrap), JS.member_expression( JS.identifier(:Core), JS.member_expression( @@ -56,7 +56,7 @@ defmodule ElixirScript.Translator.Defprotocol do JS.identifier(implementation_name), JS.call_expression( JS.member_expression( - JS.identifier(:Elixir), + JS.identifier(:Bootstrap), JS.member_expression( JS.identifier(:Core), JS.member_expression( @@ -80,7 +80,6 @@ defmodule ElixirScript.Translator.Defprotocol do %{ name: name, - std_lib: Defmodule.make_std_lib_import(env), imports: imports ++ [{implementation_name_module, ""}], body: body, exports: JS.identifier(Utils.name_to_js_name(name)), diff --git a/lib/elixir_script/translator/kernel/special_forms/bitstring.ex b/lib/elixir_script/translator/kernel/special_forms/bitstring.ex index d4f2d657..2e2bc2ce 100644 --- a/lib/elixir_script/translator/kernel/special_forms/bitstring.ex +++ b/lib/elixir_script/translator/kernel/special_forms/bitstring.ex @@ -8,7 +8,7 @@ defmodule ElixirScript.Translator.Bitstring do js_ast = JS.new_expression( JS.member_expression( JS.member_expression( - JS.identifier("Elixir"), + JS.identifier(:Bootstrap), JS.identifier("Core") ), JS.identifier("BitString") @@ -88,7 +88,7 @@ defmodule ElixirScript.Translator.Bitstring do defp bitstring_class() do JS.member_expression( JS.member_expression( - JS.identifier("Elixir"), + JS.identifier(:Bootstrap), JS.identifier("Core") ), JS.identifier("BitString") diff --git a/lib/elixir_script/translator/kernel/special_forms/call.ex b/lib/elixir_script/translator/kernel/special_forms/call.ex index 6d1c34f0..c07f84a6 100644 --- a/lib/elixir_script/translator/kernel/special_forms/call.ex +++ b/lib/elixir_script/translator/kernel/special_forms/call.ex @@ -17,7 +17,7 @@ defmodule ElixirScript.Translator.Call do js_ast = JS.call_expression( JS.member_expression( JS.member_expression( - JS.identifier("Elixir"), + JS.identifier(:Bootstrap), JS.member_expression( JS.identifier("Core"), JS.identifier("Functions") diff --git a/lib/elixir_script/translator/kernel/special_forms/fn.ex b/lib/elixir_script/translator/kernel/special_forms/fn.ex index ab66ef7c..fc9cb865 100644 --- a/lib/elixir_script/translator/kernel/special_forms/fn.ex +++ b/lib/elixir_script/translator/kernel/special_forms/fn.ex @@ -8,7 +8,7 @@ defmodule ElixirScript.Translator.Function do @patterns JS.member_expression( JS.member_expression( - JS.identifier("Elixir"), + JS.identifier(:Bootstrap), JS.identifier("Core") ), JS.identifier("Patterns") diff --git a/lib/elixir_script/translator/kernel/special_forms/for.ex b/lib/elixir_script/translator/kernel/special_forms/for.ex index 816bf3e7..c5f8f17e 100644 --- a/lib/elixir_script/translator/kernel/special_forms/for.ex +++ b/lib/elixir_script/translator/kernel/special_forms/for.ex @@ -21,7 +21,7 @@ defmodule ElixirScript.Translator.For do JS.member_expression( JS.member_expression( JS.member_expression( - JS.identifier("Elixir"), + JS.identifier(:Bootstrap), JS.identifier("Core") ), JS.identifier("Patterns") @@ -59,7 +59,7 @@ defmodule ElixirScript.Translator.For do JS.member_expression( JS.member_expression( JS.member_expression( - JS.identifier("Elixir"), + JS.identifier(:Bootstrap), JS.identifier("Core") ), JS.identifier("Patterns") @@ -78,7 +78,7 @@ defmodule ElixirScript.Translator.For do JS.member_expression( JS.member_expression( JS.member_expression( - JS.identifier("Elixir"), + JS.identifier(:Bootstrap), JS.identifier("Core") ), JS.identifier("Patterns") diff --git a/lib/elixir_script/translator/kernel/special_forms/match.ex b/lib/elixir_script/translator/kernel/special_forms/match.ex index 2263c391..49f44a80 100644 --- a/lib/elixir_script/translator/kernel/special_forms/match.ex +++ b/lib/elixir_script/translator/kernel/special_forms/match.ex @@ -16,7 +16,7 @@ defmodule ElixirScript.Translator.Match do JS.member_expression( JS.member_expression( JS.member_expression( - JS.identifier("Elixir"), + JS.identifier(:Bootstrap), JS.identifier("Core") ), JS.identifier("Patterns") @@ -61,7 +61,7 @@ defmodule ElixirScript.Translator.Match do ref, JS.new_expression( JS.member_expression( - JS.identifier("Elixir"), + JS.identifier(:Bootstrap), JS.member_expression( JS.identifier("Core"), JS.identifier("Tuple") diff --git a/lib/elixir_script/translator/kernel/special_forms/primitive.ex b/lib/elixir_script/translator/kernel/special_forms/primitive.ex index 25cea0c3..5dbe92b5 100644 --- a/lib/elixir_script/translator/kernel/special_forms/primitive.ex +++ b/lib/elixir_script/translator/kernel/special_forms/primitive.ex @@ -6,7 +6,7 @@ defmodule ElixirScript.Translator.Primitive do def special_forms() do JS.member_expression( - JS.identifier("Elixir"), + JS.identifier(:Bootstrap), JS.member_expression( JS.identifier("Core"), JS.identifier("SpecialForms") @@ -17,7 +17,7 @@ defmodule ElixirScript.Translator.Primitive do def tuple_class() do JS.member_expression( JS.member_expression( - JS.identifier("Elixir"), + JS.identifier(:Bootstrap), JS.identifier("Core") ), JS.identifier("Tuple") @@ -27,7 +27,7 @@ defmodule ElixirScript.Translator.Primitive do def list_ast() do JS.member_expression( JS.member_expression( - JS.identifier("Elixir"), + JS.identifier(:Bootstrap), JS.member_expression( JS.identifier("Core"), JS.identifier("SpecialForms") diff --git a/lib/elixir_script/translator/kernel/special_forms/quote.ex b/lib/elixir_script/translator/kernel/special_forms/quote.ex index a02168a8..76033f88 100644 --- a/lib/elixir_script/translator/kernel/special_forms/quote.ex +++ b/lib/elixir_script/translator/kernel/special_forms/quote.ex @@ -26,7 +26,7 @@ defmodule ElixirScript.Translator.Quote do JS.call_expression( JS.member_expression( - JS.identifier("Elixir"), + JS.identifier(:Bootstrap), JS.member_expression( JS.identifier("Enum"), JS.identifier("concat") diff --git a/lib/elixir_script/translator/kernel/special_forms/struct.ex b/lib/elixir_script/translator/kernel/special_forms/struct.ex index d8b0228d..5aa8d058 100644 --- a/lib/elixir_script/translator/kernel/special_forms/struct.ex +++ b/lib/elixir_script/translator/kernel/special_forms/struct.ex @@ -112,7 +112,7 @@ defmodule ElixirScript.Translator.Struct do JS.call_expression( JS.member_expression( JS.member_expression( - JS.identifier("Elixir"), + JS.identifier(:Bootstrap), JS.member_expression( JS.identifier("Core"), JS.identifier("Functions") diff --git a/lib/elixir_script/translator/pattern_matching.ex b/lib/elixir_script/translator/pattern_matching.ex index 946e920e..2934677d 100644 --- a/lib/elixir_script/translator/pattern_matching.ex +++ b/lib/elixir_script/translator/pattern_matching.ex @@ -11,7 +11,7 @@ defmodule ElixirScript.Translator.PatternMatching do @patterns JS.member_expression( JS.member_expression( - JS.identifier("Elixir"), + JS.identifier(:Bootstrap), JS.identifier("Core") ), JS.identifier("Patterns") diff --git a/lib/elixir_script/translator/rewriter.ex b/lib/elixir_script/translator/rewriter.ex index 5039fe0a..c4760a7c 100644 --- a/lib/elixir_script/translator/rewriter.ex +++ b/lib/elixir_script/translator/rewriter.ex @@ -56,7 +56,7 @@ defmodule ElixirScript.Translator.Rewriter do end def rewrite({{:., _, [:erlang, :is_bitstring]}, _, [term]}) do - quote do: is_binary(unquote(term)) || JS.instanceof(unquote(term), Elixir.Core.BitString) + quote do: is_binary(unquote(term)) || JS.instanceof(unquote(term), Bootstrap.Core.BitString) end def rewrite({{:., _, [:erlang, :is_boolean]}, _, [term]}) do @@ -88,7 +88,7 @@ defmodule ElixirScript.Translator.Rewriter do end def rewrite({{:., _, [:erlang, :is_pid]}, _, [term]}) do - quote do: JS.instanceof(unquote(term), Elixir.Core.PID) + quote do: JS.instanceof(unquote(term), Bootstrap.Core.PID) end def rewrite({{:., _, [:erlang, :is_port]}, _, [_term]}) do @@ -102,7 +102,7 @@ defmodule ElixirScript.Translator.Rewriter do end def rewrite({{:., _, [:erlang, :is_tuple]}, _, [term]}) do - quote do: JS.instanceof(unquote(term), Elixir.Core.Tuple) + quote do: JS.instanceof(unquote(term), Bootstrap.Core.Tuple) end def rewrite({{:., _, [:erlang, :is_map]}, _, [term]}) do @@ -303,7 +303,7 @@ defmodule ElixirScript.Translator.Rewriter do end def rewrite({{:., _, [:erlang, :make_tuple]}, _, [size, data]}) do - quote do: JS.new(Elixir.Core.Tuple, List.duplicate(unquote(size), unquote(data))) + quote do: JS.new(Bootstrap.Core.Tuple, List.duplicate(unquote(size), unquote(data))) end def rewrite({{:., _, [:erlang, :insert_element]}, _, [index, tuple, term]}) do @@ -331,35 +331,35 @@ defmodule ElixirScript.Translator.Rewriter do end def rewrite({{:., _, [:lists, :foldl]}, _, [fun, acc, list]}) do - quote do: Elixir.Core.Functions.foldl(unquote(fun), unquote(acc), unquote(list)) + quote do: Bootstrap.Core.Functions.foldl(unquote(fun), unquote(acc), unquote(list)) end def rewrite({{:., _, [:lists, :foldr]}, _, [fun, acc, list]}) do - quote do: Elixir.Core.Functions.foldr(unquote(fun), unquote(acc), unquote(list)) + quote do: Bootstrap.Core.Functions.foldr(unquote(fun), unquote(acc), unquote(list)) end def rewrite({{:., _, [:lists, :keymember]}, _, [key, n, list]}) do - quote do: Elixir.Core.Functions.keymember(unquote(key), unquote(n), unquote(list)) + quote do: Bootstrap.Core.Functions.keymember(unquote(key), unquote(n), unquote(list)) end def rewrite({{:., _, [:lists, :keydelete]}, _, [key, n, list]}) do - quote do: Elixir.Core.Functions.keydelete(unquote(key), unquote(n), unquote(list)) + quote do: Bootstrap.Core.Functions.keydelete(unquote(key), unquote(n), unquote(list)) end def rewrite({{:., _, [:lists, :keystore]}, _, [key, n, list, newtuple]}) do - quote do: Elixir.Core.Functions.keystore(unquote(key), unquote(n), unquote(list), unquote(newtuple)) + quote do: Bootstrap.Core.Functions.keystore(unquote(key), unquote(n), unquote(list), unquote(newtuple)) end def rewrite({{:., _, [:lists, :keytake]}, _, [key, n, list]}) do - quote do: Elixir.Core.Functions.keystore(unquote(key), unquote(n), unquote(list)) + quote do: Bootstrap.Core.Functions.keystore(unquote(key), unquote(n), unquote(list)) end def rewrite({{:., _, [:lists, :keyfind]}, _, [key, n, list]}) do - quote do: Elixir.Core.Functions.keyfind(unquote(key), unquote(n), unquote(list)) + quote do: Bootstrap.Core.Functions.keyfind(unquote(key), unquote(n), unquote(list)) end def rewrite({{:., _, [:lists, :keyreplace]}, _, [key, n, list, newtuple]}) do - quote do: Elixir.Core.Functions.keyreplace(unquote(key), unquote(n), unquote(list), unquote(newtuple)) + quote do: Bootstrap.Core.Functions.keyreplace(unquote(key), unquote(n), unquote(list), unquote(newtuple)) end def rewrite({{:., _, [:lists, :keysort]}, _, [n, tuplelist]}) do @@ -368,31 +368,31 @@ defmodule ElixirScript.Translator.Rewriter do end def rewrite({{:., _, [:lists, :reverse]}, _, [list]}) do - quote do: Elixir.Core.Functions.reverse(unquote(list)) + quote do: Bootstrap.Core.Functions.reverse(unquote(list)) end def rewrite({{:., _, [:lists, :reverse]}, _, [list, tail]}) do - quote do: Elixir.Core.Functions.reverse(unquote(list)) ++ unquote(tail) + quote do: Bootstrap.Core.Functions.reverse(unquote(list)) ++ unquote(tail) end def rewrite({{:., _, [:lists, :flatten]}, _, [list]}) do - quote do: Elixir.Core.Functions.flatten(unquote(list)) + quote do: Bootstrap.Core.Functions.flatten(unquote(list)) end def rewrite({{:., _, [:lists, :flatten]}, _, [list, tail]}) do - quote do: Elixir.Core.Functions.flatten(unquote(list), unquote(tail)) + quote do: Bootstrap.Core.Functions.flatten(unquote(list), unquote(tail)) end def rewrite({{:., _, [:lists, :delete]}, _, [elem, list]}) do - quote do: Elixir.Core.Functions.remove_from_list(unquote(list), unquote(elem)) + quote do: Bootstrap.Core.Functions.remove_from_list(unquote(list), unquote(elem)) end def rewrite({{:., _, [:lists, :duplicate]}, _, [n, elem]}) do - quote do: Elixir.Core.Functions.duplicate(unquote(n), unquote(elem)) + quote do: Bootstrap.Core.Functions.duplicate(unquote(n), unquote(elem)) end def rewrite({{:., _, [:lists, :mapfoldl]}, _, [fun, acc, list]}) do - quote do: Elixir.Core.Functions.mapfoldl(unquote(fun), unquote(acc), unquote(list)) + quote do: Bootstrap.Core.Functions.mapfoldl(unquote(fun), unquote(acc), unquote(list)) end def rewrite({{:., _, [:lists, :sort]}, _, [list]}) do @@ -409,7 +409,7 @@ defmodule ElixirScript.Translator.Rewriter do end def rewrite({{:., _, [:lists, :filtermap]}, _, [fun, list]}) do - quote do: Elixir.Core.Functions.filtermap(unquote(fun), unquote(list)) + quote do: Bootstrap.Core.Functions.filtermap(unquote(fun), unquote(list)) end def rewrite({{:., _, [:lists, :concat]}, _, [things]}) do @@ -433,7 +433,7 @@ defmodule ElixirScript.Translator.Rewriter do end def rewrite({{:., _, [:erlang, :list_to_tuple]}, _, [list]}) do - quote do: JS.new(Elixir.Core.Tuple, unquote(list)) + quote do: JS.new(Bootstrap.Core.Tuple, unquote(list)) end def rewrite({{:., _, [:erlang, :list_to_float]}, _, [list]}) do @@ -493,31 +493,31 @@ defmodule ElixirScript.Translator.Rewriter do end def rewrite({{:., _, [:maps, :is_key]}, _, [key, map]}) do - quote do: unquote(key) in Elixir.Core.Functions.get_object_keys(unquote(map)) + quote do: unquote(key) in Bootstrap.Core.Functions.get_object_keys(unquote(map)) end def rewrite({{:., _, [:maps, :put]}, _, [key, value, map]}) do - quote do: Elixir.Core.Functions.add_property_to_map(unquote(map), unquote(key), unquote(value)) + quote do: Bootstrap.Core.Functions.add_property_to_map(unquote(map), unquote(key), unquote(value)) end def rewrite({{:., _, [:maps, :update]}, _, [key, value, map]}) do - quote do: Elixir.Core.Functions.update_map(unquote(map), unquote(key), unquote(value)) + quote do: Bootstrap.Core.Functions.update_map(unquote(map), unquote(key), unquote(value)) end def rewrite({{:., _, [:maps, :find]}, _, [key, map]}) do - quote do: Elixir.Core.Functions.maps_find(unquote(key), unquote(map)) + quote do: Bootstrap.Core.Functions.maps_find(unquote(key), unquote(map)) end def rewrite({{:., _, [:maps, :remove]}, _, [key, map]}) do - quote do: Elixir.Core.Functions.delete_property_from_map(unquote(map), unquote(key)) + quote do: Bootstrap.Core.Functions.delete_property_from_map(unquote(map), unquote(key)) end def rewrite({{:., _, [:maps, :fold]}, _, [fun, init, map]}) do - quote do: Elixir.Core.Functions.maps_fold(unquote(fun), unquote(init), unquote(map)) + quote do: Bootstrap.Core.Functions.maps_fold(unquote(fun), unquote(init), unquote(map)) end def rewrite({{:., _, [:maps, :from_list]}, _, [list]}) do - quote do: Elixir.Core.Functions.maps_fold(unquote(list)) + quote do: Bootstrap.Core.Functions.maps_fold(unquote(list)) end end diff --git a/lib/elixir_script/translator/utils.ex b/lib/elixir_script/translator/utils.ex index 7d40cfff..e0611980 100644 --- a/lib/elixir_script/translator/utils.ex +++ b/lib/elixir_script/translator/utils.ex @@ -12,9 +12,7 @@ defmodule ElixirScript.Translator.Utils do def name_to_quoted(name) do name = name - |> Atom.to_string - |> String.split(".") - |> tl + |> Module.split |> Enum.map(fn x -> String.to_atom(x) end) { :__aliases__, [], name } diff --git a/lib/std_lib/agent.ex b/lib/std_lib/agent.ex index f1750335..6000058f 100644 --- a/lib/std_lib/agent.ex +++ b/lib/std_lib/agent.ex @@ -3,7 +3,7 @@ defmodule ElixirScript.Agent do require JS def start(fun, options \\ []) do - pid = JS.new Elixir.Core.PID, [] + pid = JS.new Bootstrap.Core.PID, [] name = if Elixir.Keyword.has_key?(options, :name) do Elixir.Keyword.get(options, :name) @@ -11,12 +11,12 @@ defmodule ElixirScript.Agent do nil end - Elixir.Core.Store.create(pid, fun.(), name) + Bootstrap.Core.Store.create(pid, fun.(), name) { :ok, pid } end def start_link(fun, options \\ []) do - pid = JS.new Elixir.Core.PID, [] + pid = JS.new Bootstrap.Core.PID, [] name = if Elixir.Keyword.has_key?(options, :name) do Elixir.Keyword.get(options, :name) @@ -24,30 +24,30 @@ defmodule ElixirScript.Agent do nil end - Elixir.Core.Store.create(pid, fun.(), name) + Bootstrap.Core.Store.create(pid, fun.(), name) { :ok, pid } end def stop(agent) do - Elixir.Core.Store.remove(agent) + Bootstrap.Core.Store.remove(agent) :ok end def update(agent, fun) do - current_state = Elixir.Core.Store.read(agent) - Elixir.Core.Store.update(agent, fun.(current_state)) + current_state = Bootstrap.Core.Store.read(agent) + Bootstrap.Core.Store.update(agent, fun.(current_state)) :ok end def get(agent, fun) do - current_state = Elixir.Core.Store.read(agent) + current_state = Bootstrap.Core.Store.read(agent) fun.(current_state) end def get_and_update(agent, fun) do - current_state = Elixir.Core.Store.read(agent) + current_state = Bootstrap.Core.Store.read(agent) {val, new_state} = fun.(current_state) - Elixir.Core.Store.update(agent, new_state) + Bootstrap.Core.Store.update(agent, new_state) val end diff --git a/lib/std_lib/base.ex b/lib/std_lib/base.ex index a3851f33..3e02779f 100644 --- a/lib/std_lib/base.ex +++ b/lib/std_lib/base.ex @@ -2,11 +2,11 @@ defmodule ElixirScript.Base do @moduledoc false def encode64(data) do - Elixir.Core.b64EncodeUnicode(data) + Bootstrap.Core.b64EncodeUnicode(data) end def decode64(data) do - if Elixir.Core.can_decode64(data) do + if Bootstrap.Core.can_decode64(data) do {:ok, decode64!(data) } else :error @@ -14,7 +14,7 @@ defmodule ElixirScript.Base do end def decode64!(data) do - Elixir.Core.get_global().atob(data) + Bootstrap.Core.get_global().atob(data) end end diff --git a/lib/std_lib/bitwise.ex b/lib/std_lib/bitwise.ex index 9775f36b..83d5e1d4 100644 --- a/lib/std_lib/bitwise.ex +++ b/lib/std_lib/bitwise.ex @@ -2,73 +2,73 @@ defmodule ElixirScript.Bitwise do @moduledoc false defmacro bnot(expr) do quote do - Elixir.Core.bnot(unquote(expr)) + Bootstrap.Core.bnot(unquote(expr)) end end defmacro ~~~(expr) do quote do - Elixir.Core.bnot(unquote(expr)) + Bootstrap.Core.bnot(unquote(expr)) end end defmacro band(left, right) do quote do - Elixir.Core.band(unquote(left), unquote(right)) + Bootstrap.Core.band(unquote(left), unquote(right)) end end defmacro left &&& right do quote do - Elixir.Core.band(unquote(left), unquote(right)) + Bootstrap.Core.band(unquote(left), unquote(right)) end end defmacro bor(left, right) do quote do - Elixir.Core.bor(unquote(left), unquote(right)) + Bootstrap.Core.bor(unquote(left), unquote(right)) end end defmacro left ||| right do quote do - Elixir.Core.bor(unquote(left), unquote(right)) + Bootstrap.Core.bor(unquote(left), unquote(right)) end end defmacro bxor(left, right) do quote do - Elixir.Core.bxor(unquote(left), unquote(right)) + Bootstrap.Core.bxor(unquote(left), unquote(right)) end end defmacro left ^^^ right do quote do - Elixir.Core.bxor(unquote(left), unquote(right)) + Bootstrap.Core.bxor(unquote(left), unquote(right)) end end defmacro bsl(left, right) do quote do - Elixir.Core.bsl(unquote(left), unquote(right)) + Bootstrap.Core.bsl(unquote(left), unquote(right)) end end defmacro left <<< right do quote do - Elixir.Core.bsl(unquote(left), unquote(right)) + Bootstrap.Core.bsl(unquote(left), unquote(right)) end end defmacro bsr(left, right) do quote do - Elixir.Core.bsr(unquote(left), unquote(right)) + Bootstrap.Core.bsr(unquote(left), unquote(right)) end end defmacro left >>> right do quote do - Elixir.Core.bsr(unquote(left), unquote(right)) + Bootstrap.Core.bsr(unquote(left), unquote(right)) end end end diff --git a/lib/std_lib/integer.ex b/lib/std_lib/integer.ex index 5ef4415e..abfee5a2 100644 --- a/lib/std_lib/integer.ex +++ b/lib/std_lib/integer.ex @@ -17,9 +17,9 @@ defmodule ElixirScript.Integer do end def parse(bin) do - result = Elixir.Core.Functions.get_global().parseInt(bin) + result = Bootstrap.Core.Functions.get_global().parseInt(bin) - if Elixir.Core.Functions.get_global().isNaN(result) do + if Bootstrap.Core.Functions.get_global().isNaN(result) do :error else case bin.indexOf(".") do diff --git a/lib/std_lib/js.ex b/lib/std_lib/js.ex index 35c9508a..9838a6ca 100644 --- a/lib/std_lib/js.ex +++ b/lib/std_lib/js.ex @@ -70,7 +70,7 @@ defmodule JS do In node this would be the global object. """ def global() do - Elixir.Core.Functions.get_global() + Bootstrap.Core.Functions.get_global() end @doc """ diff --git a/lib/std_lib/kernel.ex b/lib/std_lib/kernel.ex index 1fa8333a..33ad1b81 100644 --- a/lib/std_lib/kernel.ex +++ b/lib/std_lib/kernel.ex @@ -44,11 +44,11 @@ defmodule ElixirScript.Kernel do end def apply(fun, args) do - Elixir.Core.Functions.apply(fun, args) + Bootstrap.Core.Functions.apply(fun, args) end def apply(module, fun, args) do - Elixir.Core.Functions.apply(module, Atom.to_string(fun), args) + Bootstrap.Core.Functions.apply(module, Atom.to_string(fun), args) end def binary_part(binary, start, len) do @@ -72,7 +72,7 @@ defmodule ElixirScript.Kernel do end def is_bitstring(term) do - is_binary(term) || JS.instanceof(term, Elixir.Core.BitString) + is_binary(term) || JS.instanceof(term, Bootstrap.Core.BitString) end def is_boolean(term) do @@ -104,11 +104,11 @@ defmodule ElixirScript.Kernel do end def is_pid(term) do - JS.instanceof(term, Elixir.Core.PID) + JS.instanceof(term, Bootstrap.Core.PID) end def is_tuple(term) do - JS.instanceof(term, Elixir.Core.Tuple) + JS.instanceof(term, Bootstrap.Core.Tuple) end def is_map(term) do @@ -148,11 +148,11 @@ defmodule ElixirScript.Kernel do end def tuple_size(tuple) do - Elixir.Core.Functions.size(tuple) + Bootstrap.Core.Functions.size(tuple) end def elem(tuple, index) do - Elixir.Core.Functions.apply(tuple, "get", [index]) + Bootstrap.Core.Functions.apply(tuple, "get", [index]) end def is_nil(term) do @@ -193,7 +193,7 @@ defmodule ElixirScript.Kernel do defmacro left in right do quote do - Elixir.Core.Functions.contains(unquote(left), unquote(right)) + Bootstrap.Core.Functions.contains(unquote(left), unquote(right)) end end diff --git a/lib/std_lib/list.ex b/lib/std_lib/list.ex index 962c224c..1a07d6a0 100644 --- a/lib/std_lib/list.ex +++ b/lib/std_lib/list.ex @@ -15,7 +15,7 @@ defmodule ElixirScript.List do end def to_tuple(list) do - JS.new(Elixir.Core.Tuple, list) + JS.new(Bootstrap.Core.Tuple, list) end def wrap(list) when is_list(list), do: list @@ -247,6 +247,6 @@ defmodule ElixirScript.List do end def zip(list_of_lists) do - Elixir.Core.Functions.zip(list_of_lists) + Bootstrap.Core.Functions.zip(list_of_lists) end end diff --git a/lib/std_lib/map.ex b/lib/std_lib/map.ex index 6edcf85c..e2f3b46e 100644 --- a/lib/std_lib/map.ex +++ b/lib/std_lib/map.ex @@ -6,7 +6,7 @@ defmodule ElixirScript.Map do end def keys(map) do - Elixir.Core.Functions.get_object_keys(map) + Bootstrap.Core.Functions.get_object_keys(map) end def size(map) do @@ -34,13 +34,13 @@ defmodule ElixirScript.Map do def from_struct(struct) do struct - |> Elixir.Core.Functions.class_to_obj + |> Bootstrap.Core.Functions.class_to_obj |> delete(:__struct__) end def delete(map, key) do map - |> Elixir.Core.Functions.delete_property_from_map(key) + |> Bootstrap.Core.Functions.delete_property_from_map(key) end def equal?(map1, map2) do @@ -70,7 +70,7 @@ defmodule ElixirScript.Map do end def merge(map1, map2) do - Elixir.Core.SpecialForms.map_update(map1, map2) + Bootstrap.Core.SpecialForms.map_update(map1, map2) end def split(map, keys) do @@ -123,7 +123,7 @@ defmodule ElixirScript.Map do end def put(map, key, value) do - Elixir.Core.Functions.add_property_to_map(map, key, value) + Bootstrap.Core.Functions.add_property_to_map(map, key, value) end def get(map, key) do diff --git a/lib/std_lib/string.ex b/lib/std_lib/string.ex index d4d6cfc0..2997ab63 100644 --- a/lib/std_lib/string.ex +++ b/lib/std_lib/string.ex @@ -15,15 +15,15 @@ defmodule ElixirScript.String do end def to_float(str) do - Elixir.Core.get_global().parseFloat(str) + Bootstrap.Core.get_global().parseFloat(str) end def to_integer(str) do - Elixir.Core.get_global().parseInt(str, 10) + Bootstrap.Core.get_global().parseInt(str, 10) end def to_integer(str, base) do - Elixir.Core.get_global().parseInt(str, base) + Bootstrap.Core.get_global().parseInt(str, base) end def upcase(str) do @@ -199,6 +199,6 @@ defmodule ElixirScript.String do end def valid_character?(codepoint) do - Elixir.Core.Functions.is_valid_character(codepoint) + Bootstrap.Core.Functions.is_valid_character(codepoint) end end diff --git a/lib/std_lib/tuple.ex b/lib/std_lib/tuple.ex index cdd7b765..bed5e717 100644 --- a/lib/std_lib/tuple.ex +++ b/lib/std_lib/tuple.ex @@ -3,7 +3,7 @@ defmodule ElixirScript.Tuple do require JS def duplicate(data, size) do - JS.new(Elixir.Core.Tuple, do_duplicate(data, size, [])) + JS.new(Bootstrap.Core.Tuple, do_duplicate(data, size, [])) end defp do_duplicate(_, 0, list) do @@ -19,7 +19,7 @@ defmodule ElixirScript.Tuple do end def insert_at(tuple, index, value) do - JS.new(Elixir.Core.Tuple, do_insert_at(tuple, index, value, 0, [])) + JS.new(Bootstrap.Core.Tuple, do_insert_at(tuple, index, value, 0, [])) end defp do_insert_at(tuple, index, value, current_index, list) do @@ -38,7 +38,7 @@ defmodule ElixirScript.Tuple do end def delete_at(tuple, index) do - JS.new(Elixir.Core.Tuple, do_delete_at(tuple, index, 0, [])) + JS.new(Bootstrap.Core.Tuple, do_delete_at(tuple, index, 0, [])) end defp do_delete_at(tuple, index, current_index, list) do @@ -57,7 +57,7 @@ defmodule ElixirScript.Tuple do end def append(tuple, value) do - JS.new(Elixir.Core.Tuple, to_list(tuple) ++ [value]) + JS.new(Bootstrap.Core.Tuple, to_list(tuple) ++ [value]) end end diff --git a/test/elixir_script_test.exs b/test/elixir_script_test.exs index 0053603b..fe02d67f 100644 --- a/test/elixir_script_test.exs +++ b/test/elixir_script_test.exs @@ -22,10 +22,10 @@ defmodule ElixirScript.Test do """, %{ env: make_custom_env() }) assert_js_matches """ - const something_else = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.clause([],function() { + const something_else = Bootstrap.Core.Patterns.defmatch(Bootstrap.Core.Patterns.clause([],function() { return 1 * 1; })); - const sandwich = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.clause([],function() { + const sandwich = Bootstrap.Core.Patterns.defmatch(Bootstrap.Core.Patterns.clause([],function() { return null; })); """, js_code @@ -46,10 +46,10 @@ defmodule ElixirScript.Test do """, %{ env: make_custom_env(), core_path: "elixirscript"} ) assert_js_matches """ - const something_else = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.clause([],function() { + const something_else = Bootstrap.Core.Patterns.defmatch(Bootstrap.Core.Patterns.clause([],function() { return 1 * 1; })); - const sandwich = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.clause([],function() { + const sandwich = Bootstrap.Core.Patterns.defmatch(Bootstrap.Core.Patterns.clause([],function() { return null; })); """, js_code diff --git a/test/translator/bitstring_test.exs b/test/translator/bitstring_test.exs index 9d0fdae3..82f3e294 100644 --- a/test/translator/bitstring_test.exs +++ b/test/translator/bitstring_test.exs @@ -4,49 +4,49 @@ defmodule ElixirScript.Translator.Bitstring.Test do test "translate bitstring" do ex_ast = quote do: <<1, 2, 3>> - assert_translation(ex_ast, "new Elixir.Core.BitString(Elixir.Core.BitString.integer(1), Elixir.Core.BitString.integer(2), Elixir.Core.BitString.integer(3))") + assert_translation(ex_ast, "new Bootstrap.Core.BitString(Bootstrap.Core.BitString.integer(1), Bootstrap.Core.BitString.integer(2), Bootstrap.Core.BitString.integer(3))") ex_ast = quote do: <<1, "foo">> - assert_translation(ex_ast, "new Elixir.Core.BitString(Elixir.Core.BitString.integer(1), Elixir.Core.BitString.binary('foo'))") + assert_translation(ex_ast, "new Bootstrap.Core.BitString(Bootstrap.Core.BitString.integer(1), Bootstrap.Core.BitString.binary('foo'))") ex_ast = quote do: <<1, "foo" :: binary>> - assert_translation(ex_ast, "new Elixir.Core.BitString(Elixir.Core.BitString.integer(1), Elixir.Core.BitString.binary('foo'))") + assert_translation(ex_ast, "new Bootstrap.Core.BitString(Bootstrap.Core.BitString.integer(1), Bootstrap.Core.BitString.binary('foo'))") ex_ast = quote do: <<1, "foo" :: utf8, "bar" :: utf32>> - assert_translation(ex_ast, "new Elixir.Core.BitString(Elixir.Core.BitString.integer(1), Elixir.Core.BitString.utf8('foo'), Elixir.Core.BitString.utf32('bar'))") + assert_translation(ex_ast, "new Bootstrap.Core.BitString(Bootstrap.Core.BitString.integer(1), Bootstrap.Core.BitString.utf8('foo'), Bootstrap.Core.BitString.utf32('bar'))") ex_ast = quote do: <<102 :: integer-native, rest :: binary>> - assert_translation(ex_ast, "new Elixir.Core.BitString(Elixir.Core.BitString.native(Elixir.Core.BitString.integer(102)), Elixir.Core.BitString.binary(rest))") + assert_translation(ex_ast, "new Bootstrap.Core.BitString(Bootstrap.Core.BitString.native(Bootstrap.Core.BitString.integer(102)), Bootstrap.Core.BitString.binary(rest))") ex_ast = quote do: <<102 :: unsigned-big-integer, rest :: binary>> - assert_translation(ex_ast, "new Elixir.Core.BitString(Elixir.Core.BitString.integer(Elixir.Core.BitString.big(Elixir.Core.BitString.unsigned(102))), Elixir.Core.BitString.binary(rest))") + assert_translation(ex_ast, "new Bootstrap.Core.BitString(Bootstrap.Core.BitString.integer(Bootstrap.Core.BitString.big(Bootstrap.Core.BitString.unsigned(102))), Bootstrap.Core.BitString.binary(rest))") ex_ast = quote do: <<102, _rest :: size(16)>> - assert_translation(ex_ast, "new Elixir.Core.BitString(Elixir.Core.BitString.integer(102), Elixir.Core.BitString.size(_rest, 16))") + assert_translation(ex_ast, "new Bootstrap.Core.BitString(Bootstrap.Core.BitString.integer(102), Bootstrap.Core.BitString.size(_rest, 16))") ex_ast = quote do: <<102, _rest :: size(16)-unit(4)>> - assert_translation(ex_ast, "new Elixir.Core.BitString(Elixir.Core.BitString.integer(102), Elixir.Core.BitString.unit(Elixir.Core.BitString.size(_rest, 16), 4))") + assert_translation(ex_ast, "new Bootstrap.Core.BitString(Bootstrap.Core.BitString.integer(102), Bootstrap.Core.BitString.unit(Bootstrap.Core.BitString.size(_rest, 16), 4))") ex_ast = quote do: <<102, _rest :: 16 * 4>> - assert_translation(ex_ast, "new Elixir.Core.BitString(Elixir.Core.BitString.integer(102), Elixir.Core.BitString.unit(Elixir.Core.BitString.size(_rest, 16), 4))") + assert_translation(ex_ast, "new Bootstrap.Core.BitString(Bootstrap.Core.BitString.integer(102), Bootstrap.Core.BitString.unit(Bootstrap.Core.BitString.size(_rest, 16), 4))") ex_ast = quote do: <<102, _rest :: _ * 4>> - assert_translation(ex_ast, "new Elixir.Core.BitString(Elixir.Core.BitString.integer(102), Elixir.Core.BitString.unit(Elixir.Core.BitString.size(_rest, undefined), 4))") + assert_translation(ex_ast, "new Bootstrap.Core.BitString(Bootstrap.Core.BitString.integer(102), Bootstrap.Core.BitString.unit(Bootstrap.Core.BitString.size(_rest, undefined), 4))") ex_ast = quote do: <<102, _rest :: 16>> - assert_translation(ex_ast, "new Elixir.Core.BitString(Elixir.Core.BitString.integer(102), Elixir.Core.BitString.size(_rest, 16))") + assert_translation(ex_ast, "new Bootstrap.Core.BitString(Bootstrap.Core.BitString.integer(102), Bootstrap.Core.BitString.size(_rest, 16))") ex_ast = quote do: << 1, <<2>> >> - assert_translation(ex_ast, "new Elixir.Core.BitString(Elixir.Core.BitString.integer(1), new Elixir.Core.BitString(Elixir.Core.BitString.integer(2)))") + assert_translation(ex_ast, "new Bootstrap.Core.BitString(Bootstrap.Core.BitString.integer(1), new Bootstrap.Core.BitString(Bootstrap.Core.BitString.integer(2)))") end test "translate pattern matching bitstring" do ex_ast = quote do: <> = <<"Frank the Walrus">> js_code = """ - let [name,species] = Elixir.Core.Patterns.match(Elixir.Core.Patterns.bitStringMatch(Elixir.Core.BitString.size(Elixir.Core.BitString.binary({ - 'value': Elixir.Core.Patterns.variable() - }),5),Elixir.Core.BitString.binary(' the '),Elixir.Core.BitString.binary({ - 'value': Elixir.Core.Patterns.variable() + let [name,species] = Bootstrap.Core.Patterns.match(Bootstrap.Core.Patterns.bitStringMatch(Bootstrap.Core.BitString.size(Bootstrap.Core.BitString.binary({ + 'value': Bootstrap.Core.Patterns.variable() + }),5),Bootstrap.Core.BitString.binary(' the '),Bootstrap.Core.BitString.binary({ + 'value': Bootstrap.Core.Patterns.variable() })),'Frank the Walrus'); """ @@ -55,9 +55,9 @@ defmodule ElixirScript.Translator.Bitstring.Test do ex_ast = quote do: <> = <<-100>> js_code = """ - let [int] = Elixir.Core.Patterns.match(Elixir.Core.Patterns.bitStringMatch(Elixir.Core.BitString.integer({ - 'value': Elixir.Core.Patterns.variable() - })),new Elixir.Core.BitString(Elixir.Core.BitString.binary(-100))); + let [int] = Bootstrap.Core.Patterns.match(Bootstrap.Core.Patterns.bitStringMatch(Bootstrap.Core.BitString.integer({ + 'value': Bootstrap.Core.Patterns.variable() + })),new Bootstrap.Core.BitString(Bootstrap.Core.BitString.binary(-100))); """ assert_translation(ex_ast, js_code) @@ -65,9 +65,9 @@ defmodule ElixirScript.Translator.Bitstring.Test do ex_ast = quote do: <<-100::signed, _rest::binary>> = <<-100, "foo">> js_code = """ - let [_rest] = Elixir.Core.Patterns.match(Elixir.Core.Patterns.bitStringMatch(Elixir.Core.BitString.signed(-100),Elixir.Core.BitString.binary({ - 'value': Elixir.Core.Patterns.variable() - })),new Elixir.Core.BitString(Elixir.Core.BitString.binary(-100),Elixir.Core.BitString.binary('foo'))); + let [_rest] = Bootstrap.Core.Patterns.match(Bootstrap.Core.Patterns.bitStringMatch(Bootstrap.Core.BitString.signed(-100),Bootstrap.Core.BitString.binary({ + 'value': Bootstrap.Core.Patterns.variable() + })),new Bootstrap.Core.BitString(Bootstrap.Core.BitString.binary(-100),Bootstrap.Core.BitString.binary('foo'))); """ assert_translation(ex_ast, js_code) diff --git a/test/translator/bug_test.exs b/test/translator/bug_test.exs index 48dfcb15..76736e5a 100644 --- a/test/translator/bug_test.exs +++ b/test/translator/bug_test.exs @@ -10,7 +10,7 @@ defmodule ElixirScript.Translator.Bug.Test do end js_code = """ - const test = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.clause([],function(){ + const test = Bootstrap.Core.Patterns.defmatch(Bootstrap.Core.Patterns.clause([],function(){ return Symbol.for('atom'); })); """ @@ -29,7 +29,7 @@ defmodule ElixirScript.Translator.Bug.Test do js_code = """ React.createElement(React.Text,Object.freeze({ - style: Elixir.Core.Functions.call_property(styles,'welcome') + style: Bootstrap.Core.Functions.call_property(styles,'welcome') }),'Welcome to React Native!') """ @@ -46,7 +46,7 @@ defmodule ElixirScript.Translator.Bug.Test do end js_code = """ - JQuery(Elixir.Core.Functions.call_property(e,'target')); + JQuery(Bootstrap.Core.Functions.call_property(e,'target')); """ assert_translation(ex_ast, js_code) @@ -58,7 +58,7 @@ defmodule ElixirScript.Translator.Bug.Test do end js_code = """ - const graphic_store = Elixir.Core.Functions.call_property(App.Stores.GraphicStore, 'create_store'); + const graphic_store = Bootstrap.Core.Functions.call_property(App.Stores.GraphicStore, 'create_store'); """ @@ -83,7 +83,7 @@ defmodule ElixirScript.Translator.Bug.Test do end js_code = """ - Elixir.Core.Functions.call_property(this, 'getRawCanvas').getContext('2d') + Bootstrap.Core.Functions.call_property(this, 'getRawCanvas').getContext('2d') """ assert_translation(ex_ast, js_code) @@ -114,15 +114,15 @@ defmodule ElixirScript.Translator.Bug.Test do js_code = """ - const getDispatcher = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.clause([],function() { + const getDispatcher = Bootstrap.Core.Patterns.defmatch(Bootstrap.Core.Patterns.clause([],function() { return DeLorean.Flux.createDispatcher(Object.freeze({ - [Symbol.for('startPainting')]: Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.clause([],function() { + [Symbol.for('startPainting')]: Bootstrap.Core.Patterns.defmatch(Bootstrap.Core.Patterns.clause([],function() { return this.dispatch('startPainting'); - })), [Symbol.for('stopPainting')]: Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.clause([],function() { + })), [Symbol.for('stopPainting')]: Bootstrap.Core.Patterns.defmatch(Bootstrap.Core.Patterns.clause([],function() { return this.dispatch('stopPainting'); - })), [Symbol.for('addPoint')]: Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.clause([Elixir.Core.Patterns.variable()],function(data) { + })), [Symbol.for('addPoint')]: Bootstrap.Core.Patterns.defmatch(Bootstrap.Core.Patterns.clause([Bootstrap.Core.Patterns.variable()],function(data) { return this.dispatch('addPoint',data); - })), [Symbol.for('getStores')]: Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.clause([],function() { + })), [Symbol.for('getStores')]: Bootstrap.Core.Patterns.defmatch(Bootstrap.Core.Patterns.clause([],function() { return Object.freeze({ [Symbol.for('graphic')]: GraphicStore }); @@ -143,8 +143,8 @@ defmodule ElixirScript.Translator.Bug.Test do end js_code = """ - const my_func = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.clause([Elixir.Core.Patterns.variable()],function(x){ - return Object.freeze([Elixir.Core.Functions.call_property(x,'a'), Elixir.Core.Functions.call_property(x,'b')]); + const my_func = Bootstrap.Core.Patterns.defmatch(Bootstrap.Core.Patterns.clause([Bootstrap.Core.Patterns.variable()],function(x){ + return Object.freeze([Bootstrap.Core.Functions.call_property(x,'a'), Bootstrap.Core.Functions.call_property(x,'b')]); })); """ diff --git a/test/translator/capture_test.exs b/test/translator/capture_test.exs index f7a55e9c..ed0e6059 100644 --- a/test/translator/capture_test.exs +++ b/test/translator/capture_test.exs @@ -8,7 +8,7 @@ defmodule ElixirScript.Translator.Capture.Test do end js_code = """ - let [fun] = Elixir.Core.Patterns.match(Elixir.Core.Patterns.variable(),Elixir$ElixirScript$Kernel.is_atom); + let [fun] = Bootstrap.Core.Patterns.match(Bootstrap.Core.Patterns.variable(),Elixir$ElixirScript$Kernel.is_atom); """ assert_translation(ex_ast, js_code) @@ -22,7 +22,7 @@ defmodule ElixirScript.Translator.Capture.Test do end js_code = """ - let [fun] = Elixir.Core.Patterns.match(Elixir.Core.Patterns.variable(),Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.clause([Elixir.Core.Patterns.variable()],function(__1) { + let [fun] = Bootstrap.Core.Patterns.match(Bootstrap.Core.Patterns.variable(),Bootstrap.Core.Patterns.defmatch(Bootstrap.Core.Patterns.clause([Bootstrap.Core.Patterns.variable()],function(__1) { return Elixir$ElixirScript$Kernel.is_atom(__1); }))); """ @@ -39,7 +39,7 @@ defmodule ElixirScript.Translator.Capture.Test do end js_code = """ - let [fun] = Elixir.Core.Patterns.match(Elixir.Core.Patterns.variable(),local_function); + let [fun] = Bootstrap.Core.Patterns.match(Bootstrap.Core.Patterns.variable(),local_function); """ assert_translation(ex_ast, js_code) @@ -53,7 +53,7 @@ defmodule ElixirScript.Translator.Capture.Test do end js_code = """ - let [fun] = Elixir.Core.Patterns.match(Elixir.Core.Patterns.variable(),Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.clause([Elixir.Core.Patterns.variable()],function(__1) { + let [fun] = Bootstrap.Core.Patterns.match(Bootstrap.Core.Patterns.variable(),Bootstrap.Core.Patterns.defmatch(Bootstrap.Core.Patterns.clause([Bootstrap.Core.Patterns.variable()],function(__1) { return __1 * 2; }))); """ @@ -69,8 +69,8 @@ defmodule ElixirScript.Translator.Capture.Test do end js_code = """ - let [fun] = Elixir.Core.Patterns.match(Elixir.Core.Patterns.variable(),Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.clause([Elixir.Core.Patterns.variable(), Elixir.Core.Patterns.variable()],function(__1,__2) { - return new Elixir.Core.Tuple(__1,__2); + let [fun] = Bootstrap.Core.Patterns.match(Bootstrap.Core.Patterns.variable(),Bootstrap.Core.Patterns.defmatch(Bootstrap.Core.Patterns.clause([Bootstrap.Core.Patterns.variable(), Bootstrap.Core.Patterns.variable()],function(__1,__2) { + return new Bootstrap.Core.Tuple(__1,__2); }))); """ @@ -81,8 +81,8 @@ defmodule ElixirScript.Translator.Capture.Test do end js_code = """ - let [fun] = Elixir.Core.Patterns.match(Elixir.Core.Patterns.variable(),Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.clause([Elixir.Core.Patterns.variable(), Elixir.Core.Patterns.variable(), Elixir.Core.Patterns.variable()],function(__1,__2,__3) { - return new Elixir.Core.Tuple(__1,__2,__3); + let [fun] = Bootstrap.Core.Patterns.match(Bootstrap.Core.Patterns.variable(),Bootstrap.Core.Patterns.defmatch(Bootstrap.Core.Patterns.clause([Bootstrap.Core.Patterns.variable(), Bootstrap.Core.Patterns.variable(), Bootstrap.Core.Patterns.variable()],function(__1,__2,__3) { + return new Bootstrap.Core.Tuple(__1,__2,__3); }))); """ @@ -98,7 +98,7 @@ defmodule ElixirScript.Translator.Capture.Test do end js_code = """ - Elixir.Enum.map(items,Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.clause([Elixir.Core.Patterns.variable()],function(__1) { + Elixir.Enum.map(items,Bootstrap.Core.Patterns.defmatch(Bootstrap.Core.Patterns.clause([Bootstrap.Core.Patterns.variable()],function(__1) { return process(__1); }))) """ @@ -111,7 +111,7 @@ defmodule ElixirScript.Translator.Capture.Test do end js_code = """ - elem.keypress(Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.clause([Elixir.Core.Patterns.variable()],function(__1) { + elem.keypress(Bootstrap.Core.Patterns.defmatch(Bootstrap.Core.Patterns.clause([Bootstrap.Core.Patterns.variable()],function(__1) { return process_event(__1); }))) """ diff --git a/test/translator/case_test.exs b/test/translator/case_test.exs index c54250ae..11161e6d 100644 --- a/test/translator/case_test.exs +++ b/test/translator/case_test.exs @@ -12,9 +12,9 @@ defmodule ElixirScript.Translator.Case.Test do end js_code = """ - Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.clause([Symbol.for('ok')],function() { + Bootstrap.Core.Patterns.defmatch(Bootstrap.Core.Patterns.clause([Symbol.for('ok')],function() { return value; - }),Elixir.Core.Patterns.clause([Symbol.for('error')],function() { + }),Bootstrap.Core.Patterns.clause([Symbol.for('error')],function() { return null; })).call(this,data) """ @@ -29,10 +29,10 @@ defmodule ElixirScript.Translator.Case.Test do end js_code = """ - Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.clause([false],function() { - let [value] = Elixir.Core.Patterns.match(Elixir.Core.Patterns.variable(),13); + Bootstrap.Core.Patterns.defmatch(Bootstrap.Core.Patterns.clause([false],function() { + let [value] = Bootstrap.Core.Patterns.match(Bootstrap.Core.Patterns.variable(),13); return value; - }),Elixir.Core.Patterns.clause([true],function() { + }),Bootstrap.Core.Patterns.clause([true],function() { return true; })).call(this,data) """ @@ -49,10 +49,10 @@ defmodule ElixirScript.Translator.Case.Test do end js_code = """ - Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.clause([false],function() { - let [value] = Elixir.Core.Patterns.match(Elixir.Core.Patterns.variable(),13); + Bootstrap.Core.Patterns.defmatch(Bootstrap.Core.Patterns.clause([false],function() { + let [value] = Bootstrap.Core.Patterns.match(Bootstrap.Core.Patterns.variable(),13); return value; - }),Elixir.Core.Patterns.clause([Elixir.Core.Patterns.wildcard()],function() { + }),Bootstrap.Core.Patterns.clause([Bootstrap.Core.Patterns.wildcard()],function() { return true; })).call(this,data) """ @@ -71,12 +71,12 @@ defmodule ElixirScript.Translator.Case.Test do end js_code = """ - Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.clause([Elixir.Core.Patterns.variable()],function(number) { - let [value] = Elixir.Core.Patterns.match(Elixir.Core.Patterns.variable(),13); + Bootstrap.Core.Patterns.defmatch(Bootstrap.Core.Patterns.clause([Bootstrap.Core.Patterns.variable()],function(number) { + let [value] = Bootstrap.Core.Patterns.match(Bootstrap.Core.Patterns.variable(),13); return value; },function(number) { - return Elixir.Core.Functions.contains(number,Object.freeze([1, 2, 3, 4])); - }),Elixir.Core.Patterns.clause([Elixir.Core.Patterns.wildcard()],function() { + return Bootstrap.Core.Functions.contains(number,Object.freeze([1, 2, 3, 4])); + }),Bootstrap.Core.Patterns.clause([Bootstrap.Core.Patterns.wildcard()],function() { return true; })).call(this,data) """ @@ -95,12 +95,12 @@ defmodule ElixirScript.Translator.Case.Test do end js_code = """ - Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.clause([Elixir.Core.Patterns.variable()],function(number) { - let [value] = Elixir.Core.Patterns.match(Elixir.Core.Patterns.variable(),13); + Bootstrap.Core.Patterns.defmatch(Bootstrap.Core.Patterns.clause([Bootstrap.Core.Patterns.variable()],function(number) { + let [value] = Bootstrap.Core.Patterns.match(Bootstrap.Core.Patterns.variable(),13); return value; },function(number) { - return Elixir.Core.Functions.contains(number,Object.freeze([1, 2, 3, 4])) || Elixir.Core.Functions.contains(number,Object.freeze([4, 3, 2, 1])); - }),Elixir.Core.Patterns.clause([Elixir.Core.Patterns.wildcard()],function() { + return Bootstrap.Core.Functions.contains(number,Object.freeze([1, 2, 3, 4])) || Bootstrap.Core.Functions.contains(number,Object.freeze([4, 3, 2, 1])); + }),Bootstrap.Core.Patterns.clause([Bootstrap.Core.Patterns.wildcard()],function() { return true; })).call(this,data) """ @@ -120,10 +120,10 @@ defmodule ElixirScript.Translator.Case.Test do end js_code = """ - Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.clause([Symbol.for('ok')],function() { + Bootstrap.Core.Patterns.defmatch(Bootstrap.Core.Patterns.clause([Symbol.for('ok')],function() { console.info('info'); return Todo.add(data); - }),Elixir.Core.Patterns.clause([Symbol.for('error')],function() { + }),Bootstrap.Core.Patterns.clause([Symbol.for('error')],function() { return null; })).call(this,data) """ @@ -142,11 +142,11 @@ defmodule ElixirScript.Translator.Case.Test do end js_code = """ - Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.clause([Elixir.Core.Patterns.type(Elixir.Core.Tuple, { - values: [Elixir.Core.Patterns.variable(), Elixir.Core.Patterns.variable()] + Bootstrap.Core.Patterns.defmatch(Bootstrap.Core.Patterns.clause([Bootstrap.Core.Patterns.type(Bootstrap.Core.Tuple, { + values: [Bootstrap.Core.Patterns.variable(), Bootstrap.Core.Patterns.variable()] })], function(one, two) { return console.info(one); - }), Elixir.Core.Patterns.clause([Symbol.for('error')], function() { + }), Bootstrap.Core.Patterns.clause([Symbol.for('error')], function() { return null; })).call(this, data) """ @@ -165,13 +165,13 @@ defmodule ElixirScript.Translator.Case.Test do end js_code = """ - Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.clause([Elixir.Core.Patterns.type(Elixir.Core.Tuple, { - values: [Elixir.Core.Patterns.type(Elixir.Core.Tuple, { - values: [Elixir.Core.Patterns.variable(), Elixir.Core.Patterns.variable()] - }), Elixir.Core.Patterns.variable()] + Bootstrap.Core.Patterns.defmatch(Bootstrap.Core.Patterns.clause([Bootstrap.Core.Patterns.type(Bootstrap.Core.Tuple, { + values: [Bootstrap.Core.Patterns.type(Bootstrap.Core.Tuple, { + values: [Bootstrap.Core.Patterns.variable(), Bootstrap.Core.Patterns.variable()] + }), Bootstrap.Core.Patterns.variable()] })], function(one, two, three) { return console.info(one); - }), Elixir.Core.Patterns.clause([Symbol.for('error')], function() { + }), Bootstrap.Core.Patterns.clause([Symbol.for('error')], function() { return null; })).call(this, data) """ @@ -188,13 +188,13 @@ defmodule ElixirScript.Translator.Case.Test do end js_code = """ - Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.clause([Elixir.Core.Patterns.type(Elixir.Core.Tuple, { - values: [Elixir.Core.Patterns.variable(), Elixir.Core.Patterns.type(Elixir.Core.Tuple, { - values: [Elixir.Core.Patterns.variable(), Elixir.Core.Patterns.variable()] + Bootstrap.Core.Patterns.defmatch(Bootstrap.Core.Patterns.clause([Bootstrap.Core.Patterns.type(Bootstrap.Core.Tuple, { + values: [Bootstrap.Core.Patterns.variable(), Bootstrap.Core.Patterns.type(Bootstrap.Core.Tuple, { + values: [Bootstrap.Core.Patterns.variable(), Bootstrap.Core.Patterns.variable()] })] })], function(one, two, three) { return console.info(one); - }), Elixir.Core.Patterns.clause([Symbol.for('error')], function() { + }), Bootstrap.Core.Patterns.clause([Symbol.for('error')], function() { return null; })).call(this, data) """ @@ -212,13 +212,13 @@ defmodule ElixirScript.Translator.Case.Test do end js_code = """ - Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.clause([Elixir.Core.Patterns.type(AStruct, { - [Symbol.for('key')]: Elixir.Core.Patterns.type(BStruct, { - [Symbol.for('key2')]: Elixir.Core.Patterns.variable() + Bootstrap.Core.Patterns.defmatch(Bootstrap.Core.Patterns.clause([Bootstrap.Core.Patterns.type(AStruct, { + [Symbol.for('key')]: Bootstrap.Core.Patterns.type(BStruct, { + [Symbol.for('key2')]: Bootstrap.Core.Patterns.variable() }) })], function(value) { return console.info(value); - }), Elixir.Core.Patterns.clause([Symbol.for('error')], function() { + }), Bootstrap.Core.Patterns.clause([Symbol.for('error')], function() { return null; })).call(this, data) """ @@ -236,15 +236,15 @@ defmodule ElixirScript.Translator.Case.Test do end js_code = """ - Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.clause([Elixir.Core.Patterns.type(AStruct, { - [Symbol.for('key')]: Elixir.Core.Patterns.type(BStruct, { - [Symbol.for('key2')]: Elixir.Core.Patterns.variable(), [Symbol.for('key3')]: Elixir.Core.Patterns.type(CStruct, { - [Symbol.for('key4')]: Elixir.Core.Patterns.variable() + Bootstrap.Core.Patterns.defmatch(Bootstrap.Core.Patterns.clause([Bootstrap.Core.Patterns.type(AStruct, { + [Symbol.for('key')]: Bootstrap.Core.Patterns.type(BStruct, { + [Symbol.for('key2')]: Bootstrap.Core.Patterns.variable(), [Symbol.for('key3')]: Bootstrap.Core.Patterns.type(CStruct, { + [Symbol.for('key4')]: Bootstrap.Core.Patterns.variable() }) }) })], function(value, value2) { return console.info(value); - }), Elixir.Core.Patterns.clause([Symbol.for('error')], function() { + }), Bootstrap.Core.Patterns.clause([Symbol.for('error')], function() { return null; })).call(this, data) """ diff --git a/test/translator/cond_test.exs b/test/translator/cond_test.exs index 7666d4f5..8b5f605d 100644 --- a/test/translator/cond_test.exs +++ b/test/translator/cond_test.exs @@ -15,7 +15,7 @@ defmodule ElixirScript.Translator.Cond.Test do end js_code = """ - Elixir.Core.SpecialForms.cond(Object.freeze([1 + 1 == 1, function() { + Bootstrap.Core.SpecialForms.cond(Object.freeze([1 + 1 == 1, function() { return 'This will never match'; }]),Object.freeze([2 * 2 != 4, function() { return 'Nor this'; @@ -41,14 +41,14 @@ defmodule ElixirScript.Translator.Cond.Test do end js_code = """ - Elixir.Core.SpecialForms.cond(Object.freeze([1 + 1 == 1, function() { - let [a] = Elixir.Core.Patterns.match(Elixir.Core.Patterns.variable(),1); + Bootstrap.Core.SpecialForms.cond(Object.freeze([1 + 1 == 1, function() { + let [a] = Bootstrap.Core.Patterns.match(Bootstrap.Core.Patterns.variable(),1); return 'This will never match'; }]),Object.freeze([2 * 2 != 4, function() { - let [a] = Elixir.Core.Patterns.match(Elixir.Core.Patterns.variable(),2); + let [a] = Bootstrap.Core.Patterns.match(Bootstrap.Core.Patterns.variable(),2); return 'Nor this'; }]),Object.freeze([true, function() { - let [a] = Elixir.Core.Patterns.match(Elixir.Core.Patterns.variable(),3); + let [a] = Bootstrap.Core.Patterns.match(Bootstrap.Core.Patterns.variable(),3); return 'This will'; }])) """ diff --git a/test/translator/defdelegate_test.exs b/test/translator/defdelegate_test.exs index f71c0d23..d6488ab2 100644 --- a/test/translator/defdelegate_test.exs +++ b/test/translator/defdelegate_test.exs @@ -7,7 +7,7 @@ defmodule ElixirScript.Translator.Defdelegate.Test do js_code = """ const reverse = function(list) { - return Elixir.Core.Functions.reverse(list); + return Bootstrap.Core.Functions.reverse(list); }; """ @@ -19,7 +19,7 @@ defmodule ElixirScript.Translator.Defdelegate.Test do js_code = """ const other_reverse = function(list) { - return Elixir.Core.Functions.reverse(list); + return Bootstrap.Core.Functions.reverse(list); }; """ diff --git a/test/translator/defmodule_test.exs b/test/translator/defmodule_test.exs index 2fb26520..f4dd0d3e 100644 --- a/test/translator/defmodule_test.exs +++ b/test/translator/defmodule_test.exs @@ -9,7 +9,7 @@ defmodule ElixirScript.Translator.Defmodule.Test do end js_code = """ - const values = {}; + const __exports = {}; """ assert_translation(ex_ast, js_code) @@ -30,10 +30,10 @@ defmodule ElixirScript.Translator.Defmodule.Test do end js_code = """ - const something_else = Elixir.Core.Patterns.defmatchgen(Elixir.Core.Patterns.clause([],function*() { + const something_else = Bootstrap.Core.Patterns.defmatchgen(Bootstrap.Core.Patterns.clause([],function*() { return null; })); - const something = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.clause([],function() { + const something = Bootstrap.Core.Patterns.defmatch(Bootstrap.Core.Patterns.clause([],function() { return ul; })); const ul = JQuery('#todo-list'); @@ -61,7 +61,7 @@ defmodule ElixirScript.Translator.Defmodule.Test do end js_code = """ - const Elixir$Animals$Elephant = Elixir.Core.Functions.defstruct({ + const Elixir$Animals$Elephant = Bootstrap.Core.Functions.defstruct({ [Symbol.for('__struct__')]: Symbol.for('Elixir.Animals.Elephant'), [Symbol.for('trunk')]: true }); """ @@ -94,7 +94,7 @@ defmodule ElixirScript.Translator.Defmodule.Test do end js_code = """ - const Elixir$Animals$Elephant$Bear = Elixir.Core.Functions.defstruct({ + const Elixir$Animals$Elephant$Bear = Bootstrap.Core.Functions.defstruct({ [Symbol.for('__struct__')]: Symbol.for('Elixir.Animals.Elephant.Bear'), [Symbol.for('trunk')]: true }); @@ -115,7 +115,7 @@ defmodule ElixirScript.Translator.Defmodule.Test do end js_code = """ - Elixir.Core.Functions.call_property(Lions.Tigers.Bears,'oh_my'); + Bootstrap.Core.Functions.call_property(Lions.Tigers.Bears,'oh_my'); """ assert_translation(ex_ast, js_code) diff --git a/test/translator/for_test.exs b/test/translator/for_test.exs index 0ab2666a..4cd22260 100644 --- a/test/translator/for_test.exs +++ b/test/translator/for_test.exs @@ -8,9 +8,9 @@ defmodule ElixirScript.Translator.For.Test do end js_code = """ - Elixir.Core.SpecialForms._for( - Elixir.Core.Patterns.clause( - [Elixir.Core.Patterns.variable()], + Bootstrap.Core.SpecialForms._for( + Bootstrap.Core.Patterns.clause( + [Bootstrap.Core.Patterns.variable()], function(n) { return n * 2; }, @@ -19,8 +19,8 @@ defmodule ElixirScript.Translator.For.Test do } ), [ - Elixir.Core.Patterns.list_generator( - Elixir.Core.Patterns.variable(), + Bootstrap.Core.Patterns.list_generator( + Bootstrap.Core.Patterns.variable(), Object.freeze([1, 2, 3, 4]) ) ], @@ -38,9 +38,9 @@ defmodule ElixirScript.Translator.For.Test do end js_code = """ - Elixir.Core.SpecialForms._for( - Elixir.Core.Patterns.clause( - [Elixir.Core.Patterns.variable()], + Bootstrap.Core.SpecialForms._for( + Bootstrap.Core.Patterns.clause( + [Bootstrap.Core.Patterns.variable()], function(n) { return n * 2; }, @@ -49,8 +49,8 @@ defmodule ElixirScript.Translator.For.Test do } ), [ - Elixir.Core.Patterns.list_generator( - Elixir.Core.Patterns.variable(), + Bootstrap.Core.Patterns.list_generator( + Bootstrap.Core.Patterns.variable(), Object.freeze([1, 2, 3, 4]) ) ], @@ -68,9 +68,9 @@ defmodule ElixirScript.Translator.For.Test do end js_code = """ - Elixir.Core.SpecialForms._for( - Elixir.Core.Patterns.clause( - [Elixir.Core.Patterns.variable()], + Bootstrap.Core.SpecialForms._for( + Bootstrap.Core.Patterns.clause( + [Bootstrap.Core.Patterns.variable()], function(n) { return n; }, @@ -79,8 +79,8 @@ defmodule ElixirScript.Translator.For.Test do } ), [ - Elixir.Core.Patterns.list_generator( - Elixir.Core.Patterns.variable(), + Bootstrap.Core.Patterns.list_generator( + Bootstrap.Core.Patterns.variable(), 'Opera' ) ], @@ -98,9 +98,9 @@ defmodule ElixirScript.Translator.For.Test do end js_code = """ - Elixir.Core.SpecialForms._for( - Elixir.Core.Patterns.clause( - [Elixir.Core.Patterns.variable(), Elixir.Core.Patterns.variable()], + Bootstrap.Core.SpecialForms._for( + Bootstrap.Core.Patterns.clause( + [Bootstrap.Core.Patterns.variable(), Bootstrap.Core.Patterns.variable()], function(x, y) { return x * y; }, @@ -109,12 +109,12 @@ defmodule ElixirScript.Translator.For.Test do } ), [ - Elixir.Core.Patterns.list_generator( - Elixir.Core.Patterns.variable(), + Bootstrap.Core.Patterns.list_generator( + Bootstrap.Core.Patterns.variable(), Object.freeze([1, 2]) ), - Elixir.Core.Patterns.list_generator( - Elixir.Core.Patterns.variable(), + Bootstrap.Core.Patterns.list_generator( + Bootstrap.Core.Patterns.variable(), Object.freeze([2, 3]) ) ], @@ -134,11 +134,11 @@ defmodule ElixirScript.Translator.For.Test do end js_code = """ - let [r] = Elixir.Core.Patterns.match( - Elixir.Core.Patterns.variable(), - Elixir.Core.SpecialForms._for( - Elixir.Core.Patterns.clause( - [Elixir.Core.Patterns.variable(), Elixir.Core.Patterns.variable()], + let [r] = Bootstrap.Core.Patterns.match( + Bootstrap.Core.Patterns.variable(), + Bootstrap.Core.SpecialForms._for( + Bootstrap.Core.Patterns.clause( + [Bootstrap.Core.Patterns.variable(), Bootstrap.Core.Patterns.variable()], function(x, y) { return x * y; }, @@ -147,12 +147,12 @@ defmodule ElixirScript.Translator.For.Test do } ), [ - Elixir.Core.Patterns.list_generator( - Elixir.Core.Patterns.variable(), + Bootstrap.Core.Patterns.list_generator( + Bootstrap.Core.Patterns.variable(), Object.freeze([1, 2]) ), - Elixir.Core.Patterns.list_generator( - Elixir.Core.Patterns.variable(), + Bootstrap.Core.Patterns.list_generator( + Bootstrap.Core.Patterns.variable(), Object.freeze([2, 3]) ) ], @@ -171,9 +171,9 @@ defmodule ElixirScript.Translator.For.Test do end js_code = """ - Elixir.Core.SpecialForms._for( - Elixir.Core.Patterns.clause( - [Elixir.Core.Patterns.variable()], + Bootstrap.Core.SpecialForms._for( + Bootstrap.Core.Patterns.clause( + [Bootstrap.Core.Patterns.variable()], function(n) { return n; }, @@ -182,8 +182,8 @@ defmodule ElixirScript.Translator.For.Test do } ), [ - Elixir.Core.Patterns.list_generator( - Elixir.Core.Patterns.variable(), + Bootstrap.Core.Patterns.list_generator( + Bootstrap.Core.Patterns.variable(), Object.freeze([1, 2, 3, 4, 5, 6]) ) ], @@ -203,18 +203,18 @@ defmodule ElixirScript.Translator.For.Test do end js_code = """ - Elixir.Core.SpecialForms._for( - Elixir.Core.Patterns.clause([Elixir.Core.Patterns.type(Elixir.Core.Tuple, { - values: [Symbol.for('user'), Elixir.Core.Patterns.variable()] + Bootstrap.Core.SpecialForms._for( + Bootstrap.Core.Patterns.clause([Bootstrap.Core.Patterns.type(Bootstrap.Core.Tuple, { + values: [Symbol.for('user'), Bootstrap.Core.Patterns.variable()] })], function(name) { return Elixir$ElixirScript$String.upcase(name); }, function() { return true; }), [ - Elixir.Core.Patterns.list_generator(Elixir.Core.Patterns.type(Elixir.Core.Tuple, { - values: [Symbol.for('user'), Elixir.Core.Patterns.variable()] - }), Object.freeze([new Elixir.Core.Tuple(Symbol.for('user'), 'john'), new Elixir.Core.Tuple(Symbol.for('admin'), 'john'), new Elixir.Core.Tuple(Symbol.for('user'), 'meg')])) + Bootstrap.Core.Patterns.list_generator(Bootstrap.Core.Patterns.type(Bootstrap.Core.Tuple, { + values: [Symbol.for('user'), Bootstrap.Core.Patterns.variable()] + }), Object.freeze([new Bootstrap.Core.Tuple(Symbol.for('user'), 'john'), new Bootstrap.Core.Tuple(Symbol.for('admin'), 'john'), new Bootstrap.Core.Tuple(Symbol.for('user'), 'meg')])) ], Elixir$ElixirScript$Collectable, Object.freeze([])) @@ -231,22 +231,22 @@ defmodule ElixirScript.Translator.For.Test do end js_code = """ - Elixir.Core.SpecialForms._for(Elixir.Core.Patterns.clause([Elixir.Core.Patterns.bitStringMatch(Elixir.Core.BitString.size({ - 'value': Elixir.Core.Patterns.variable() - }, 8), Elixir.Core.BitString.size({ - 'value': Elixir.Core.Patterns.variable() - }, 8), Elixir.Core.BitString.size({ - 'value': Elixir.Core.Patterns.variable() + Bootstrap.Core.SpecialForms._for(Bootstrap.Core.Patterns.clause([Bootstrap.Core.Patterns.bitStringMatch(Bootstrap.Core.BitString.size({ + 'value': Bootstrap.Core.Patterns.variable() + }, 8), Bootstrap.Core.BitString.size({ + 'value': Bootstrap.Core.Patterns.variable() + }, 8), Bootstrap.Core.BitString.size({ + 'value': Bootstrap.Core.Patterns.variable() }, 8))], function(r, g, b) { - return new Elixir.Core.Tuple(r, g, b); + return new Bootstrap.Core.Tuple(r, g, b); }, function() { return true; - }), [Elixir.Core.Patterns.bitstring_generator(Elixir.Core.Patterns.bitStringMatch(Elixir.Core.BitString.size({ - 'value': Elixir.Core.Patterns.variable() - }, 8), Elixir.Core.BitString.size({ - 'value': Elixir.Core.Patterns.variable() - }, 8), Elixir.Core.BitString.size({ - 'value': Elixir.Core.Patterns.variable() + }), [Bootstrap.Core.Patterns.bitstring_generator(Bootstrap.Core.Patterns.bitStringMatch(Bootstrap.Core.BitString.size({ + 'value': Bootstrap.Core.Patterns.variable() + }, 8), Bootstrap.Core.BitString.size({ + 'value': Bootstrap.Core.Patterns.variable() + }, 8), Bootstrap.Core.BitString.size({ + 'value': Bootstrap.Core.Patterns.variable() }, 8)), pixels)], Elixir$ElixirScript$Collectable, Object.freeze([])) """ diff --git a/test/translator/function_test.exs b/test/translator/function_test.exs index 09733cfd..928b74de 100644 --- a/test/translator/function_test.exs +++ b/test/translator/function_test.exs @@ -24,7 +24,7 @@ defmodule ElixirScript.Translator.Function.Test do end js_code = """ - const test1 = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.clause([],function() { + const test1 = Bootstrap.Core.Patterns.defmatch(Bootstrap.Core.Patterns.clause([],function() { return 1 * 1; })); """ @@ -39,7 +39,7 @@ defmodule ElixirScript.Translator.Function.Test do end js_code = """ - const test1 = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.clause([],function() { + const test1 = Bootstrap.Core.Patterns.defmatch(Bootstrap.Core.Patterns.clause([],function() { return null; })); """ @@ -52,7 +52,7 @@ defmodule ElixirScript.Translator.Function.Test do end js_code = """ - const test1 = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.clause([Elixir.Core.Patterns.variable(), Elixir.Core.Patterns.variable()],function(alpha,beta) { + const test1 = Bootstrap.Core.Patterns.defmatch(Bootstrap.Core.Patterns.clause([Bootstrap.Core.Patterns.variable(), Bootstrap.Core.Patterns.variable()],function(alpha,beta) { return null; })); """ @@ -66,8 +66,8 @@ defmodule ElixirScript.Translator.Function.Test do end js_code = """ - const test1 = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.clause([Elixir.Core.Patterns.variable(), Elixir.Core.Patterns.variable()],function(alpha,beta) { - let [a] = Elixir.Core.Patterns.match(Elixir.Core.Patterns.variable(),alpha); + const test1 = Bootstrap.Core.Patterns.defmatch(Bootstrap.Core.Patterns.clause([Bootstrap.Core.Patterns.variable(), Bootstrap.Core.Patterns.variable()],function(alpha,beta) { + let [a] = Bootstrap.Core.Patterns.match(Bootstrap.Core.Patterns.variable(),alpha); return a; })); """ @@ -85,12 +85,12 @@ defmodule ElixirScript.Translator.Function.Test do end js_code = """ - const test1 = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.clause([Elixir.Core.Patterns.variable(), Elixir.Core.Patterns.variable()],function(alpha,beta) { - return Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.clause([Elixir.Core.Patterns.variable()],function(x) { + const test1 = Bootstrap.Core.Patterns.defmatch(Bootstrap.Core.Patterns.clause([Bootstrap.Core.Patterns.variable(), Bootstrap.Core.Patterns.variable()],function(alpha,beta) { + return Bootstrap.Core.Patterns.defmatch(Bootstrap.Core.Patterns.clause([Bootstrap.Core.Patterns.variable()],function(x) { return 2; },function(x) { return x === null || x === false; - }),Elixir.Core.Patterns.clause([Elixir.Core.Patterns.wildcard()],function() { + }),Bootstrap.Core.Patterns.clause([Bootstrap.Core.Patterns.wildcard()],function() { return 1; })).call(this,1 == 1); })); @@ -113,19 +113,19 @@ defmodule ElixirScript.Translator.Function.Test do end js_code = """ - const test1 = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.clause([Elixir.Core.Patterns.variable(), Elixir.Core.Patterns.variable()], function(alpha, beta) { - return Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.clause([Elixir.Core.Patterns.variable()], function(x) { + const test1 = Bootstrap.Core.Patterns.defmatch(Bootstrap.Core.Patterns.clause([Bootstrap.Core.Patterns.variable(), Bootstrap.Core.Patterns.variable()], function(alpha, beta) { + return Bootstrap.Core.Patterns.defmatch(Bootstrap.Core.Patterns.clause([Bootstrap.Core.Patterns.variable()], function(x) { return 2; }, function(x) { return x === null || x === false; - }), Elixir.Core.Patterns.clause([Elixir.Core.Patterns.wildcard()], function() { - return Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.clause([Elixir.Core.Patterns.variable()], function(x) { - let [a] = Elixir.Core.Patterns.match(Elixir.Core.Patterns.variable(), 1); + }), Bootstrap.Core.Patterns.clause([Bootstrap.Core.Patterns.wildcard()], function() { + return Bootstrap.Core.Patterns.defmatch(Bootstrap.Core.Patterns.clause([Bootstrap.Core.Patterns.variable()], function(x) { + let [a] = Bootstrap.Core.Patterns.match(Bootstrap.Core.Patterns.variable(), 1); return a; }, function(x) { return x === null || x === false; - }), Elixir.Core.Patterns.clause([Elixir.Core.Patterns.wildcard()], function() { + }), Bootstrap.Core.Patterns.clause([Bootstrap.Core.Patterns.wildcard()], function() { return 4; })).call(this, 2 == 2); })).call(this, 1 == 1); @@ -141,11 +141,11 @@ defmodule ElixirScript.Translator.Function.Test do end js_code = """ - const test1 = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.clause([Elixir.Core.Patterns.variable(), Elixir.Core.Patterns.variable()], function(alpha, beta) { - let [a, b] = Elixir.Core.Patterns.match(Elixir.Core.Patterns.type(Elixir.Core.Tuple, { - values: [Elixir.Core.Patterns.variable(), Elixir.Core.Patterns.variable()] - }), new Elixir.Core.Tuple(1, 2)); - let _ref = new Elixir.Core.Tuple(a, b); + const test1 = Bootstrap.Core.Patterns.defmatch(Bootstrap.Core.Patterns.clause([Bootstrap.Core.Patterns.variable(), Bootstrap.Core.Patterns.variable()], function(alpha, beta) { + let [a, b] = Bootstrap.Core.Patterns.match(Bootstrap.Core.Patterns.type(Bootstrap.Core.Tuple, { + values: [Bootstrap.Core.Patterns.variable(), Bootstrap.Core.Patterns.variable()] + }), new Bootstrap.Core.Tuple(1, 2)); + let _ref = new Bootstrap.Core.Tuple(a, b); return _ref; })); """ @@ -182,7 +182,7 @@ defmodule ElixirScript.Translator.Function.Test do Taco.test1() end - js_code = "Elixir.Core.Functions.call_property(Taco, 'test1')" + js_code = "Bootstrap.Core.Functions.call_property(Taco, 'test1')" assert_translation(ex_ast, js_code) @@ -210,7 +210,7 @@ defmodule ElixirScript.Translator.Function.Test do end js_code = """ - Elixir.Enum.map(list,Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.clause([Elixir.Core.Patterns.variable()],function(x) { + Elixir.Enum.map(list,Bootstrap.Core.Patterns.defmatch(Bootstrap.Core.Patterns.clause([Bootstrap.Core.Patterns.variable()],function(x) { return x * 2; }))) """ @@ -240,15 +240,15 @@ defmodule ElixirScript.Translator.Function.Test do end js_code = """ - const example = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.clause([],function() { + const example = Bootstrap.Core.Patterns.defmatch(Bootstrap.Core.Patterns.clause([],function() { return null; - }),Elixir.Core.Patterns.clause([Elixir.Core.Patterns.variable()],function(oneArg) { + }),Bootstrap.Core.Patterns.clause([Bootstrap.Core.Patterns.variable()],function(oneArg) { return null; - }),Elixir.Core.Patterns.clause([Elixir.Core.Patterns.variable(), Elixir.Core.Patterns.variable()],function(oneArg,twoArg) { + }),Bootstrap.Core.Patterns.clause([Bootstrap.Core.Patterns.variable(), Bootstrap.Core.Patterns.variable()],function(oneArg,twoArg) { return null; - }),Elixir.Core.Patterns.clause([Elixir.Core.Patterns.variable(), Elixir.Core.Patterns.variable(), Elixir.Core.Patterns.variable()],function(oneArg,twoArg,redArg) { + }),Bootstrap.Core.Patterns.clause([Bootstrap.Core.Patterns.variable(), Bootstrap.Core.Patterns.variable(), Bootstrap.Core.Patterns.variable()],function(oneArg,twoArg,redArg) { return null; - }),Elixir.Core.Patterns.clause([Elixir.Core.Patterns.variable(), Elixir.Core.Patterns.variable(), Elixir.Core.Patterns.variable(), Elixir.Core.Patterns.variable()],function(oneArg,twoArg,redArg,blueArg) { + }),Bootstrap.Core.Patterns.clause([Bootstrap.Core.Patterns.variable(), Bootstrap.Core.Patterns.variable(), Bootstrap.Core.Patterns.variable(), Bootstrap.Core.Patterns.variable()],function(oneArg,twoArg,redArg,blueArg) { return null; })); """ @@ -275,15 +275,15 @@ defmodule ElixirScript.Translator.Function.Test do end js_code = """ - const example = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.clause([],function() { + const example = Bootstrap.Core.Patterns.defmatch(Bootstrap.Core.Patterns.clause([],function() { return null; - }),Elixir.Core.Patterns.clause([Elixir.Core.Patterns.variable()],function(oneArg) { + }),Bootstrap.Core.Patterns.clause([Bootstrap.Core.Patterns.variable()],function(oneArg) { return null; - }),Elixir.Core.Patterns.clause([Elixir.Core.Patterns.variable(), Elixir.Core.Patterns.variable()],function(oneArg,twoArg) { + }),Bootstrap.Core.Patterns.clause([Bootstrap.Core.Patterns.variable(), Bootstrap.Core.Patterns.variable()],function(oneArg,twoArg) { return null; - }),Elixir.Core.Patterns.clause([Elixir.Core.Patterns.variable(), Elixir.Core.Patterns.variable(), Elixir.Core.Patterns.variable()],function(oneArg,twoArg,redArg) { + }),Bootstrap.Core.Patterns.clause([Bootstrap.Core.Patterns.variable(), Bootstrap.Core.Patterns.variable(), Bootstrap.Core.Patterns.variable()],function(oneArg,twoArg,redArg) { return null; - }),Elixir.Core.Patterns.clause([Elixir.Core.Patterns.variable(), Elixir.Core.Patterns.variable(), Elixir.Core.Patterns.variable(), Elixir.Core.Patterns.variable()],function(oneArg,twoArg,redArg,blueArg) { + }),Bootstrap.Core.Patterns.clause([Bootstrap.Core.Patterns.variable(), Bootstrap.Core.Patterns.variable(), Bootstrap.Core.Patterns.variable(), Bootstrap.Core.Patterns.variable()],function(oneArg,twoArg,redArg,blueArg) { return null; })); """ @@ -298,7 +298,7 @@ defmodule ElixirScript.Translator.Function.Test do end js_code = """ - const example = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.clause([Elixir.Core.Patterns.variable()],function(oneArg) { + const example = Bootstrap.Core.Patterns.defmatch(Bootstrap.Core.Patterns.clause([Bootstrap.Core.Patterns.variable()],function(oneArg) { return null; })); """ @@ -343,7 +343,7 @@ defmodule ElixirScript.Translator.Function.Test do js_code = """ - const something = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.clause([Elixir.Core.Patterns.variable()],function(one) { + const something = Bootstrap.Core.Patterns.defmatch(Bootstrap.Core.Patterns.clause([Bootstrap.Core.Patterns.variable()],function(one) { return null; },function(one) { return Elixir$ElixirScript$Kernel.is_number(one); @@ -360,7 +360,7 @@ defmodule ElixirScript.Translator.Function.Test do js_code = """ - const something = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.clause([Elixir.Core.Patterns.variable()],function(one) { + const something = Bootstrap.Core.Patterns.defmatch(Bootstrap.Core.Patterns.clause([Bootstrap.Core.Patterns.variable()],function(one) { return null; },function(one) { return Elixir$ElixirScript$Kernel.is_number(one) || Elixir$ElixirScript$Kernel.is_atom(one); @@ -376,7 +376,7 @@ defmodule ElixirScript.Translator.Function.Test do js_code = """ - const something = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.clause([Elixir.Core.Patterns.variable()],function(one) { + const something = Bootstrap.Core.Patterns.defmatch(Bootstrap.Core.Patterns.clause([Bootstrap.Core.Patterns.variable()],function(one) { return null; },function(one) { return Elixir$ElixirScript$Kernel.is_number(one) || Elixir$ElixirScript$Kernel.is_atom(one); @@ -392,10 +392,10 @@ defmodule ElixirScript.Translator.Function.Test do js_code = """ - const something = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.clause([Elixir.Core.Patterns.variable(), Elixir.Core.Patterns.variable()],function(one,two) { + const something = Bootstrap.Core.Patterns.defmatch(Bootstrap.Core.Patterns.clause([Bootstrap.Core.Patterns.variable(), Bootstrap.Core.Patterns.variable()],function(one,two) { return null; },function(one,two) { - return Elixir.Core.Functions.contains(one,Object.freeze([1, 2, 3])); + return Bootstrap.Core.Functions.contains(one,Object.freeze([1, 2, 3])); })); """ @@ -412,11 +412,11 @@ defmodule ElixirScript.Translator.Function.Test do end js_code = """ - const something = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.clause([Elixir.Core.Patterns.variable()],function(one) { + const something = Bootstrap.Core.Patterns.defmatch(Bootstrap.Core.Patterns.clause([Bootstrap.Core.Patterns.variable()],function(one) { return null; },function(one) { - return Elixir.Core.Functions.contains(one,Object.freeze([1, 2, 3])); - }),Elixir.Core.Patterns.clause([Elixir.Core.Patterns.variable()],function(one) { + return Bootstrap.Core.Functions.contains(one,Object.freeze([1, 2, 3])); + }),Bootstrap.Core.Patterns.clause([Bootstrap.Core.Patterns.variable()],function(one) { return null; },function(one) { return Elixir$ElixirScript$Kernel.is_number(one) || Elixir$ElixirScript$Kernel.is_atom(one); @@ -434,7 +434,7 @@ defmodule ElixirScript.Translator.Function.Test do js_code = """ - const something = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.clause([1],function() { + const something = Bootstrap.Core.Patterns.defmatch(Bootstrap.Core.Patterns.clause([1],function() { return null; })); """ @@ -450,7 +450,7 @@ defmodule ElixirScript.Translator.Function.Test do js_code = """ - const something = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.clause([Elixir.Core.Patterns.headTail(Elixir.Core.Patterns.variable(),Elixir.Core.Patterns.variable())],function(apple,fruits) { + const something = Bootstrap.Core.Patterns.defmatch(Bootstrap.Core.Patterns.clause([Bootstrap.Core.Patterns.headTail(Bootstrap.Core.Patterns.variable(),Bootstrap.Core.Patterns.variable())],function(apple,fruits) { return null; })); """ @@ -466,7 +466,7 @@ defmodule ElixirScript.Translator.Function.Test do js_code = """ - const something = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.clause([Object.freeze([Elixir.Core.Patterns.variable(), Elixir.Core.Patterns.variable(), Elixir.Core.Patterns.variable()])],function(apple,pear,banana) { + const something = Bootstrap.Core.Patterns.defmatch(Bootstrap.Core.Patterns.clause([Object.freeze([Bootstrap.Core.Patterns.variable(), Bootstrap.Core.Patterns.variable(), Bootstrap.Core.Patterns.variable()])],function(apple,pear,banana) { return null; })); """ @@ -482,8 +482,8 @@ defmodule ElixirScript.Translator.Function.Test do js_code = """ - const something = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.clause([Elixir.Core.Patterns.type(Elixir.Core.Tuple, { - values: [Elixir.Core.Patterns.variable(), Elixir.Core.Patterns.variable()] + const something = Bootstrap.Core.Patterns.defmatch(Bootstrap.Core.Patterns.clause([Bootstrap.Core.Patterns.type(Bootstrap.Core.Tuple, { + values: [Bootstrap.Core.Patterns.variable(), Bootstrap.Core.Patterns.variable()] })], function(apple, fruits) { return null; })); @@ -500,7 +500,7 @@ defmodule ElixirScript.Translator.Function.Test do js_code = """ - const something = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.clause([Elixir.Core.Patterns.type(AStruct, {})], function() { + const something = Bootstrap.Core.Patterns.defmatch(Bootstrap.Core.Patterns.clause([Bootstrap.Core.Patterns.type(AStruct, {})], function() { return null; })); """ @@ -515,7 +515,7 @@ defmodule ElixirScript.Translator.Function.Test do end js_code = """ - const something = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.clause([Elixir.Core.Patterns.capture(Elixir.Core.Patterns.type(AStruct, {}))], function(a) { + const something = Bootstrap.Core.Patterns.defmatch(Bootstrap.Core.Patterns.clause([Bootstrap.Core.Patterns.capture(Bootstrap.Core.Patterns.type(AStruct, {}))], function(a) { return null; })); """ @@ -529,7 +529,7 @@ defmodule ElixirScript.Translator.Function.Test do end js_code = """ - const something = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.clause([Elixir.Core.Patterns.capture({ + const something = Bootstrap.Core.Patterns.defmatch(Bootstrap.Core.Patterns.clause([Bootstrap.Core.Patterns.capture({ [Symbol.for('which')]: 13 })],function(a) { return null; @@ -547,8 +547,8 @@ defmodule ElixirScript.Translator.Function.Test do js_code = """ - const something = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.clause([Elixir.Core.Patterns.type(AStruct, { - [Symbol.for('key')]: Elixir.Core.Patterns.variable(), [Symbol.for('key1')]: 2 + const something = Bootstrap.Core.Patterns.defmatch(Bootstrap.Core.Patterns.clause([Bootstrap.Core.Patterns.type(AStruct, { + [Symbol.for('key')]: Bootstrap.Core.Patterns.variable(), [Symbol.for('key1')]: 2 })], function(value) { return null; })); @@ -563,8 +563,8 @@ defmodule ElixirScript.Translator.Function.Test do js_code = """ - const something = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.clause([Elixir.Core.Patterns.type(AStruct, { - [Symbol.for('key')]: Elixir.Core.Patterns.variable(), [Symbol.for('key1')]: 2 + const something = Bootstrap.Core.Patterns.defmatch(Bootstrap.Core.Patterns.clause([Bootstrap.Core.Patterns.type(AStruct, { + [Symbol.for('key')]: Bootstrap.Core.Patterns.variable(), [Symbol.for('key1')]: 2 })], function(value) { return null; }, function(value) { @@ -583,7 +583,7 @@ defmodule ElixirScript.Translator.Function.Test do js_code = """ - const something = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.clause([Elixir.Core.Patterns.startsWith('Bearer ')],function(token) { + const something = Bootstrap.Core.Patterns.defmatch(Bootstrap.Core.Patterns.clause([Bootstrap.Core.Patterns.startsWith('Bearer ')],function(token) { return null; })); """ @@ -597,7 +597,7 @@ defmodule ElixirScript.Translator.Function.Test do js_code = """ - const something = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.clause([Elixir.Core.Patterns.startsWith('Bearer '), Elixir.Core.Patterns.variable()],function(token,hotel) { + const something = Bootstrap.Core.Patterns.defmatch(Bootstrap.Core.Patterns.clause([Bootstrap.Core.Patterns.startsWith('Bearer '), Bootstrap.Core.Patterns.variable()],function(token,hotel) { return null; })); """ @@ -611,7 +611,7 @@ defmodule ElixirScript.Translator.Function.Test do js_code = """ - const something = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.clause([Elixir.Core.Patterns.startsWith('Bearer '), Elixir.Core.Patterns.variable(), 1],function(token,hotel) { + const something = Bootstrap.Core.Patterns.defmatch(Bootstrap.Core.Patterns.clause([Bootstrap.Core.Patterns.startsWith('Bearer '), Bootstrap.Core.Patterns.variable(), 1],function(token,hotel) { return null; })); """ @@ -639,15 +639,15 @@ defmodule ElixirScript.Translator.Function.Test do js_code = """ - const something = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.clause([1],function() { + const something = Bootstrap.Core.Patterns.defmatch(Bootstrap.Core.Patterns.clause([1],function() { return null; - }),Elixir.Core.Patterns.clause([2],function() { + }),Bootstrap.Core.Patterns.clause([2],function() { return null; - }),Elixir.Core.Patterns.clause([Elixir.Core.Patterns.variable()],function(one) { + }),Bootstrap.Core.Patterns.clause([Bootstrap.Core.Patterns.variable()],function(one) { return null; },function(one) { return Elixir$ElixirScript$Kernel.is_binary(one); - }),Elixir.Core.Patterns.clause([Elixir.Core.Patterns.variable()],function(one) { + }),Bootstrap.Core.Patterns.clause([Bootstrap.Core.Patterns.variable()],function(one) { return null; })); """ @@ -665,9 +665,9 @@ defmodule ElixirScript.Translator.Function.Test do end js_code = """ - const test1 = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.clause([Elixir.Core.Patterns.variable(), Elixir.Core.Patterns.variable()],function(alpha,beta) { - let [a] = Elixir.Core.Patterns.match(Elixir.Core.Patterns.variable(),1); - let [a1] = Elixir.Core.Patterns.match(Elixir.Core.Patterns.variable(),2); + const test1 = Bootstrap.Core.Patterns.defmatch(Bootstrap.Core.Patterns.clause([Bootstrap.Core.Patterns.variable(), Bootstrap.Core.Patterns.variable()],function(alpha,beta) { + let [a] = Bootstrap.Core.Patterns.match(Bootstrap.Core.Patterns.variable(),1); + let [a1] = Bootstrap.Core.Patterns.match(Bootstrap.Core.Patterns.variable(),2); return a1; })); """ @@ -683,10 +683,10 @@ defmodule ElixirScript.Translator.Function.Test do end js_code = """ - const test1 = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.clause([Elixir.Core.Patterns.variable(), Elixir.Core.Patterns.variable()],function(alpha,beta) { - let [a] = Elixir.Core.Patterns.match(Elixir.Core.Patterns.variable(),1); - let [a1] = Elixir.Core.Patterns.match(Elixir.Core.Patterns.variable(),a); - let [a2] = Elixir.Core.Patterns.match(Elixir.Core.Patterns.variable(),2); + const test1 = Bootstrap.Core.Patterns.defmatch(Bootstrap.Core.Patterns.clause([Bootstrap.Core.Patterns.variable(), Bootstrap.Core.Patterns.variable()],function(alpha,beta) { + let [a] = Bootstrap.Core.Patterns.match(Bootstrap.Core.Patterns.variable(),1); + let [a1] = Bootstrap.Core.Patterns.match(Bootstrap.Core.Patterns.variable(),a); + let [a2] = Bootstrap.Core.Patterns.match(Bootstrap.Core.Patterns.variable(),2); return a2; })); """ @@ -701,9 +701,9 @@ defmodule ElixirScript.Translator.Function.Test do end js_code = """ - const test1 = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.clause([Elixir.Core.Patterns.variable(), Elixir.Core.Patterns.variable()],function(alpha,beta) { - let [a] = Elixir.Core.Patterns.match(Elixir.Core.Patterns.variable(),1); - let [a1,b,c] = Elixir.Core.Patterns.match(Object.freeze([Elixir.Core.Patterns.variable(), Elixir.Core.Patterns.variable(), Elixir.Core.Patterns.variable()]),Object.freeze([a, 2, 3])); + const test1 = Bootstrap.Core.Patterns.defmatch(Bootstrap.Core.Patterns.clause([Bootstrap.Core.Patterns.variable(), Bootstrap.Core.Patterns.variable()],function(alpha,beta) { + let [a] = Bootstrap.Core.Patterns.match(Bootstrap.Core.Patterns.variable(),1); + let [a1,b,c] = Bootstrap.Core.Patterns.match(Object.freeze([Bootstrap.Core.Patterns.variable(), Bootstrap.Core.Patterns.variable(), Bootstrap.Core.Patterns.variable()]),Object.freeze([a, 2, 3])); let _ref = Object.freeze([a1, b, c]); return _ref; })); @@ -721,9 +721,9 @@ defmodule ElixirScript.Translator.Function.Test do end js_code = """ - const test1 = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.clause([Elixir.Core.Patterns.variable(), Elixir.Core.Patterns.variable()],function(alpha__qmark__,beta__emark__) { - let [a__qmark__] = Elixir.Core.Patterns.match(Elixir.Core.Patterns.variable(),1); - let [b__emark__] = Elixir.Core.Patterns.match(Elixir.Core.Patterns.variable(),2); + const test1 = Bootstrap.Core.Patterns.defmatch(Bootstrap.Core.Patterns.clause([Bootstrap.Core.Patterns.variable(), Bootstrap.Core.Patterns.variable()],function(alpha__qmark__,beta__emark__) { + let [a__qmark__] = Bootstrap.Core.Patterns.match(Bootstrap.Core.Patterns.variable(),1); + let [b__emark__] = Bootstrap.Core.Patterns.match(Bootstrap.Core.Patterns.variable(),2); return b__emark__; })); """ @@ -738,7 +738,7 @@ defmodule ElixirScript.Translator.Function.Test do end js_code = """ - const test1 = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.clause([Elixir.Core.Patterns.variable(), Elixir.Core.Patterns.variable(0)],function(alpha,beta) { + const test1 = Bootstrap.Core.Patterns.defmatch(Bootstrap.Core.Patterns.clause([Bootstrap.Core.Patterns.variable(), Bootstrap.Core.Patterns.variable(0)],function(alpha,beta) { return null; })); """ @@ -751,7 +751,7 @@ defmodule ElixirScript.Translator.Function.Test do end js_code = """ - const test1 = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.clause([Elixir.Core.Patterns.variable(Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.clause([Elixir.Core.Patterns.variable()],function(x) { + const test1 = Bootstrap.Core.Patterns.defmatch(Bootstrap.Core.Patterns.clause([Bootstrap.Core.Patterns.variable(Bootstrap.Core.Patterns.defmatch(Bootstrap.Core.Patterns.clause([Bootstrap.Core.Patterns.variable()],function(x) { return x; })))], function(alpha) { @@ -776,21 +776,21 @@ defmodule ElixirScript.Translator.Function.Test do end js_code = """ - const func = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.clause([Elixir.Core.Patterns.variable()], + const func = Bootstrap.Core.Patterns.defmatch(Bootstrap.Core.Patterns.clause([Bootstrap.Core.Patterns.variable()], function(param) { - return Elixir.Core.SpecialForms._try(function() { - return Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.clause([Elixir.Core.Patterns.variable()], function(x) { + return Bootstrap.Core.SpecialForms._try(function() { + return Bootstrap.Core.Patterns.defmatch(Bootstrap.Core.Patterns.clause([Bootstrap.Core.Patterns.variable()], function(x) { return Symbol.for('error'); }, function(x) { return x === null || x === false; }), - Elixir.Core.Patterns.clause([Elixir.Core.Patterns.wildcard()], function() { + Bootstrap.Core.Patterns.clause([Bootstrap.Core.Patterns.wildcard()], function() { return null; })).call(this, true); }, null, - Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.clause([Symbol.for('invalid')], function() { + Bootstrap.Core.Patterns.defmatch(Bootstrap.Core.Patterns.clause([Symbol.for('invalid')], function() { return Symbol.for('error'); })), null, @@ -810,11 +810,11 @@ defmodule ElixirScript.Translator.Function.Test do end js_code = """ - let [key] = Elixir.Core.Patterns.match(Elixir.Core.Patterns.variable(),'test'); + let [key] = Bootstrap.Core.Patterns.match(Bootstrap.Core.Patterns.variable(),'test'); - Elixir.Core.Patterns.defmatch( - Elixir.Core.Patterns.clause( - [Elixir.Core.Patterns.bound(key)], + Bootstrap.Core.Patterns.defmatch( + Bootstrap.Core.Patterns.clause( + [Bootstrap.Core.Patterns.bound(key)], function() { return Symbol.for('ok'); } @@ -833,7 +833,7 @@ defmodule ElixirScript.Translator.Function.Test do js_code = """ - const something = Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.clause([Elixir.Core.Patterns.variable()],function(one) { + const something = Bootstrap.Core.Patterns.defmatch(Bootstrap.Core.Patterns.clause([Bootstrap.Core.Patterns.variable()],function(one) { return null; },function(one) { return Elixir$ElixirScript$Kernel.is_number(one) || Elixir$ElixirScript$Kernel.is_atom(one); diff --git a/test/translator/list_test.exs b/test/translator/list_test.exs index ed25bc2c..cbdbc92b 100644 --- a/test/translator/list_test.exs +++ b/test/translator/list_test.exs @@ -31,7 +31,7 @@ defmodule ElixirScript.Translator.List.Test do assert_translation(ex_ast, js_code) ex_ast = quote do: this.list ++ [4, 5, 6] - js_code = "Elixir.Core.Functions.call_property(this,'list').concat(Object.freeze([4, 5, 6]))" + js_code = "Bootstrap.Core.Functions.call_property(this,'list').concat(Object.freeze([4, 5, 6]))" assert_translation(ex_ast, js_code) end @@ -50,7 +50,7 @@ defmodule ElixirScript.Translator.List.Test do end js_code = """ - Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.clause([Elixir.Core.Patterns.wildcard()],function(){ + Bootstrap.Core.Patterns.defmatch(Bootstrap.Core.Patterns.clause([Bootstrap.Core.Patterns.wildcard()],function(){ return Object.freeze([x]).concat(list); })) """ diff --git a/test/translator/map_test.exs b/test/translator/map_test.exs index f06e701f..a71d62d3 100644 --- a/test/translator/map_test.exs +++ b/test/translator/map_test.exs @@ -45,7 +45,7 @@ defmodule ElixirScript.Translator.Map.Test do test "translate map update" do ex_ast = quote do: %{ map | value: 1 } js_code = """ - Elixir.Core.SpecialForms.map_update(map,Object.freeze({ + Bootstrap.Core.SpecialForms.map_update(map,Object.freeze({ [Symbol.for('value')]: 1 })) """ @@ -62,8 +62,8 @@ defmodule ElixirScript.Translator.Map.Test do test "translate bound map key" do ex_ast = quote do: %{^key => value} = %{key => value} js_code = """ - let [value] = Elixir.Core.Patterns.match( - { [key]: Elixir.Core.Patterns.variable() }, + let [value] = Bootstrap.Core.Patterns.match( + { [key]: Bootstrap.Core.Patterns.variable() }, Object.freeze({ [key]: value }) ); """ diff --git a/test/translator/match_test.exs b/test/translator/match_test.exs index d233b873..898818b7 100644 --- a/test/translator/match_test.exs +++ b/test/translator/match_test.exs @@ -4,12 +4,12 @@ defmodule ElixirScript.Translator.Match.Test do test "translate simple match" do ex_ast = quote do: a = 1 - js_code = "let [a] = Elixir.Core.Patterns.match(Elixir.Core.Patterns.variable(), 1);" + js_code = "let [a] = Bootstrap.Core.Patterns.match(Bootstrap.Core.Patterns.variable(), 1);" assert_translation(ex_ast, js_code) ex_ast = quote do: a = :atom - js_code = "let [a] = Elixir.Core.Patterns.match(Elixir.Core.Patterns.variable(), Symbol.for('atom'));" + js_code = "let [a] = Bootstrap.Core.Patterns.match(Bootstrap.Core.Patterns.variable(), Symbol.for('atom'));" assert_translation(ex_ast, js_code) end @@ -19,20 +19,20 @@ defmodule ElixirScript.Translator.Match.Test do {a, b} = {1, 2} end js_code = """ - let [a, b] = Elixir.Core.Patterns.match(Elixir.Core.Patterns.type(Elixir.Core.Tuple, { - values: [Elixir.Core.Patterns.variable(), Elixir.Core.Patterns.variable()] - }), new Elixir.Core.Tuple(1, 2)); - let _ref = new Elixir.Core.Tuple(a, b); + let [a, b] = Bootstrap.Core.Patterns.match(Bootstrap.Core.Patterns.type(Bootstrap.Core.Tuple, { + values: [Bootstrap.Core.Patterns.variable(), Bootstrap.Core.Patterns.variable()] + }), new Bootstrap.Core.Tuple(1, 2)); + let _ref = new Bootstrap.Core.Tuple(a, b); """ assert_translation(ex_ast, js_code) ex_ast = quote do: {a, _, c} = {1, 2, 3} js_code = """ - let [a, undefined, c] = Elixir.Core.Patterns.match(Elixir.Core.Patterns.type(Elixir.Core.Tuple, { - values: [Elixir.Core.Patterns.variable(), Elixir.Core.Patterns.wildcard(), Elixir.Core.Patterns.variable()] - }), new Elixir.Core.Tuple(1, 2, 3)); - let _ref = new Elixir.Core.Tuple(a, undefined, c); + let [a, undefined, c] = Bootstrap.Core.Patterns.match(Bootstrap.Core.Patterns.type(Bootstrap.Core.Tuple, { + values: [Bootstrap.Core.Patterns.variable(), Bootstrap.Core.Patterns.wildcard(), Bootstrap.Core.Patterns.variable()] + }), new Bootstrap.Core.Tuple(1, 2, 3)); + let _ref = new Bootstrap.Core.Tuple(a, undefined, c); """ assert_translation(ex_ast, js_code) @@ -40,10 +40,10 @@ defmodule ElixirScript.Translator.Match.Test do ex_ast = quote do: {^a, _, c} = {1, 2, 3} js_code = """ - let [, undefined, c] = Elixir.Core.Patterns.match(Elixir.Core.Patterns.type(Elixir.Core.Tuple, { - values: [Elixir.Core.Patterns.bound(a), Elixir.Core.Patterns.wildcard(), Elixir.Core.Patterns.variable()] - }), new Elixir.Core.Tuple(1, 2, 3)); - let _ref = new Elixir.Core.Tuple(undefined, undefined, c); + let [, undefined, c] = Bootstrap.Core.Patterns.match(Bootstrap.Core.Patterns.type(Bootstrap.Core.Tuple, { + values: [Bootstrap.Core.Patterns.bound(a), Bootstrap.Core.Patterns.wildcard(), Bootstrap.Core.Patterns.variable()] + }), new Bootstrap.Core.Tuple(1, 2, 3)); + let _ref = new Bootstrap.Core.Tuple(undefined, undefined, c); """ assert_translation(ex_ast, js_code) @@ -52,7 +52,7 @@ defmodule ElixirScript.Translator.Match.Test do test "translate bound match" do ex_ast = quote do: ^a = 1 js_code = """ - let [] = Elixir.Core.Patterns.match(Elixir.Core.Patterns.bound(a),1); + let [] = Bootstrap.Core.Patterns.match(Bootstrap.Core.Patterns.bound(a),1); """ assert_translation(ex_ast, js_code) @@ -61,7 +61,7 @@ defmodule ElixirScript.Translator.Match.Test do test "translate list match" do ex_ast = quote do: [a, b] = [1, 2] js_code = """ - let [a,b] = Elixir.Core.Patterns.match(Object.freeze([Elixir.Core.Patterns.variable(), Elixir.Core.Patterns.variable()]),Object.freeze([1, 2])); + let [a,b] = Bootstrap.Core.Patterns.match(Object.freeze([Bootstrap.Core.Patterns.variable(), Bootstrap.Core.Patterns.variable()]),Object.freeze([1, 2])); let _ref = Object.freeze([a, b]); """ @@ -71,7 +71,7 @@ defmodule ElixirScript.Translator.Match.Test do test "translate head/tail match" do ex_ast = quote do: [a | b] = [1, 2, 3, 4] js_code = """ - let [a,b] = Elixir.Core.Patterns.match(Elixir.Core.Patterns.headTail(Elixir.Core.Patterns.variable(),Elixir.Core.Patterns.variable()),Object.freeze([1, 2, 3, 4])); + let [a,b] = Bootstrap.Core.Patterns.match(Bootstrap.Core.Patterns.headTail(Bootstrap.Core.Patterns.variable(),Bootstrap.Core.Patterns.variable()),Object.freeze([1, 2, 3, 4])); let _ref = Object.freeze([a, b]); """ diff --git a/test/translator/quote_test.exs b/test/translator/quote_test.exs index 27f7c33d..aef14a89 100644 --- a/test/translator/quote_test.exs +++ b/test/translator/quote_test.exs @@ -28,7 +28,7 @@ defmodule ElixirScript.Translator.Quote.Test do quote do: {1, 2} end - js_code = "new Elixir.Core.Tuple(1, 2)" + js_code = "new Bootstrap.Core.Tuple(1, 2)" assert_translation(ex_ast, js_code) end @@ -39,7 +39,7 @@ defmodule ElixirScript.Translator.Quote.Test do quote do: {1, 2, 3} end - js_code = "new Elixir.Core.Tuple(Symbol.for('{}'), Object.freeze([]), Object.freeze([1, 2, 3]))" + js_code = "new Bootstrap.Core.Tuple(Symbol.for('{}'), Object.freeze([]), Object.freeze([1, 2, 3]))" assert_translation(ex_ast, js_code) end @@ -51,9 +51,9 @@ defmodule ElixirScript.Translator.Quote.Test do end js_code = """ - new Elixir.Core.Tuple( + new Bootstrap.Core.Tuple( Symbol.for('test'), - Object.freeze([new Elixir.Core.Tuple(Symbol.for('context'),Symbol.for('Elixir.ElixirScript.Translator.Quote.Test')), new Elixir.Core.Tuple(Symbol.for('import'),Symbol.for('Elixir.ExUnit.Case'))]),Object.freeze([1]) + Object.freeze([new Bootstrap.Core.Tuple(Symbol.for('context'),Symbol.for('Elixir.ElixirScript.Translator.Quote.Test')), new Bootstrap.Core.Tuple(Symbol.for('import'),Symbol.for('Elixir.ExUnit.Case'))]),Object.freeze([1]) ) """ @@ -67,9 +67,9 @@ defmodule ElixirScript.Translator.Quote.Test do end js_code = """ - new Elixir.Core.Tuple( + new Bootstrap.Core.Tuple( Symbol.for('test'), - Object.freeze([new Elixir.Core.Tuple(Symbol.for('context'), Symbol.for('Elixir.ElixirScript.Translator.Quote.Test')), new Elixir.Core.Tuple(Symbol.for('import'),Symbol.for('Elixir.ExUnit.Case'))]),Object.freeze([new Elixir.Core.Tuple(Symbol.for('x'),Object.freeze([]),Symbol.for('Elixir.ElixirScript.Translator.Quote.Test'))])) + Object.freeze([new Bootstrap.Core.Tuple(Symbol.for('context'), Symbol.for('Elixir.ElixirScript.Translator.Quote.Test')), new Bootstrap.Core.Tuple(Symbol.for('import'),Symbol.for('Elixir.ExUnit.Case'))]),Object.freeze([new Bootstrap.Core.Tuple(Symbol.for('x'),Object.freeze([]),Symbol.for('Elixir.ElixirScript.Translator.Quote.Test'))])) """ assert_translation(ex_ast, js_code) @@ -82,9 +82,9 @@ defmodule ElixirScript.Translator.Quote.Test do end js_code = """ - new Elixir.Core.Tuple( + new Bootstrap.Core.Tuple( Symbol.for('test'), - Object.freeze([new Elixir.Core.Tuple(Symbol.for('context'),Symbol.for('Elixir.ElixirScript.Translator.Quote.Test')), new Elixir.Core.Tuple(Symbol.for('import'),Symbol.for('Elixir.ExUnit.Case'))]),Object.freeze([x]) + Object.freeze([new Bootstrap.Core.Tuple(Symbol.for('context'),Symbol.for('Elixir.ElixirScript.Translator.Quote.Test')), new Bootstrap.Core.Tuple(Symbol.for('import'),Symbol.for('Elixir.ExUnit.Case'))]),Object.freeze([x]) ) """ @@ -98,7 +98,7 @@ defmodule ElixirScript.Translator.Quote.Test do end js_code = """ - new Elixir.Core.Tuple(Symbol.for('sum'),Object.freeze([]),Elixir.Enum.concat(Object.freeze([1]),values,Object.freeze([5]))) + new Bootstrap.Core.Tuple(Symbol.for('sum'),Object.freeze([]),Bootstrap.Enum.concat(Object.freeze([1]),values,Object.freeze([5]))) """ assert_translation(ex_ast, js_code) @@ -112,9 +112,9 @@ defmodule ElixirScript.Translator.Quote.Test do end js_code = """ - new Elixir.Core.Tuple( + new Bootstrap.Core.Tuple( Symbol.for('*'), - Object.freeze([new Elixir.Core.Tuple(Symbol.for('context'), Symbol.for('Elixir.ElixirScript.Translator.Quote.Test')), new Elixir.Core.Tuple(Symbol.for('import'),Symbol.for('Elixir.ElixirScript.Kernel'))]),Object.freeze([x, x]) + Object.freeze([new Bootstrap.Core.Tuple(Symbol.for('context'), Symbol.for('Elixir.ElixirScript.Translator.Quote.Test')), new Bootstrap.Core.Tuple(Symbol.for('import'),Symbol.for('Elixir.ElixirScript.Kernel'))]),Object.freeze([x, x]) ) """ @@ -129,9 +129,9 @@ defmodule ElixirScript.Translator.Quote.Test do end js_code = """ - new Elixir.Core.Tuple( + new Bootstrap.Core.Tuple( Symbol.for('test'), - Object.freeze([new Elixir.Core.Tuple(Symbol.for('context'),Symbol.for('Elixir')), new Elixir.Core.Tuple(Symbol.for('import'),Symbol.for('Elixir.ExUnit.Case'))]),Object.freeze([1]) + Object.freeze([new Bootstrap.Core.Tuple(Symbol.for('context'),Symbol.for('Elixir')), new Bootstrap.Core.Tuple(Symbol.for('import'),Symbol.for('Elixir.ExUnit.Case'))]),Object.freeze([1]) ) """ diff --git a/test/translator/struct_test.exs b/test/translator/struct_test.exs index 50dce2c2..0f50c424 100644 --- a/test/translator/struct_test.exs +++ b/test/translator/struct_test.exs @@ -10,7 +10,7 @@ defmodule ElixirScript.Translator.Struct.Test do end js_code = """ - const Elixir$User = Elixir.Core.Functions.defstruct({ + const Elixir$User = Bootstrap.Core.Functions.defstruct({ [Symbol.for('__struct__')]: Symbol.for('Elixir.User'), [Symbol.for('name')]: 'john', [Symbol.for('age')]: 27 @@ -29,7 +29,7 @@ defmodule ElixirScript.Translator.Struct.Test do end js_code = """ - const Elixir$User = Elixir.Core.Functions.defstruct({ + const Elixir$User = Bootstrap.Core.Functions.defstruct({ [Symbol.for('__struct__')]: Symbol.for('Elixir.User'), [Symbol.for('name')]: null, [Symbol.for('age')]: null @@ -50,7 +50,7 @@ defmodule ElixirScript.Translator.Struct.Test do end js_code = """ - const Elixir$User = Elixir.Core.Functions.defstruct({ + const Elixir$User = Bootstrap.Core.Functions.defstruct({ [Symbol.for('__struct__')]: Symbol.for('Elixir.User'), [Symbol.for('name')]: null, [Symbol.for('age')]: null @@ -68,7 +68,7 @@ defmodule ElixirScript.Translator.Struct.Test do end js_code = """ - const Elixir$User = Elixir.Core.Functions.defstruct({ + const Elixir$User = Bootstrap.Core.Functions.defstruct({ [Symbol.for('__struct__')]: Symbol.for('Elixir.User'), [Symbol.for('name')]: null, [Symbol.for('age')]: null @@ -85,7 +85,7 @@ defmodule ElixirScript.Translator.Struct.Test do end js_code = """ - let [user] = Elixir.Core.Patterns.match(Elixir.Core.Patterns.variable(),Elixir.Core.SpecialForms.map_update(map,Object.freeze({ + let [user] = Bootstrap.Core.Patterns.match(Bootstrap.Core.Patterns.variable(),Bootstrap.Core.SpecialForms.map_update(map,Object.freeze({ [Symbol.for('key')]: value }))); """ @@ -98,7 +98,7 @@ defmodule ElixirScript.Translator.Struct.Test do end js_code = """ - let [user] = Elixir.Core.Patterns.match(Elixir.Core.Patterns.variable(),Elixir.Core.SpecialForms.map_update(map,Object.freeze({ + let [user] = Bootstrap.Core.Patterns.match(Bootstrap.Core.Patterns.variable(),Bootstrap.Core.SpecialForms.map_update(map,Object.freeze({ [Symbol.for('key')]: value, [Symbol.for('key1')]: value1 }))); """ @@ -114,7 +114,7 @@ defmodule ElixirScript.Translator.Struct.Test do end js_code = """ - const Elixir$MyAppError = Elixir.Core.Functions.defexception({ + const Elixir$MyAppError = Bootstrap.Core.Functions.defexception({ [Symbol.for('__struct__')]: Symbol.for('Elixir.MyAppError'), [Symbol.for('__exception__')]: true, [Symbol.for('message')]: 'This is a message' @@ -130,7 +130,7 @@ defmodule ElixirScript.Translator.Struct.Test do end js_code = """ - const Elixir$MyAppError = Elixir.Core.Functions.defexception({ + const Elixir$MyAppError = Bootstrap.Core.Functions.defexception({ [Symbol.for('__struct__')]: Symbol.for('Elixir.MyAppError'), [Symbol.for('__exception__')]: true, [Symbol.for('message')]: null diff --git a/test/translator/try_test.exs b/test/translator/try_test.exs index d165688d..cd90a0d0 100644 --- a/test/translator/try_test.exs +++ b/test/translator/try_test.exs @@ -13,9 +13,9 @@ defmodule ElixirScript.Translator.Try.Test do end js_code = """ - Elixir.Core.SpecialForms._try(function() { + Bootstrap.Core.SpecialForms._try(function() { return do_something_that_may_fail(some_arg); - }, Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.clause([Elixir.Core.Patterns.type(ArgumentError, {})], function() { + }, Bootstrap.Core.Patterns.defmatch(Bootstrap.Core.Patterns.clause([Bootstrap.Core.Patterns.type(ArgumentError, {})], function() { return IO.puts('Invalid argument given'); })), null, null, null) """ @@ -34,9 +34,9 @@ defmodule ElixirScript.Translator.Try.Test do end js_code = """ - Elixir.Core.SpecialForms._try(function() { + Bootstrap.Core.SpecialForms._try(function() { return do_something_that_may_fail(some_arg); - }, Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.clause([Elixir.Core.Patterns.type(ArgumentError, {})], function() { + }, Bootstrap.Core.Patterns.defmatch(Bootstrap.Core.Patterns.clause([Bootstrap.Core.Patterns.type(ArgumentError, {})], function() { return IO.puts('Invalid argument given'); })), null, null, null) """ @@ -55,12 +55,12 @@ defmodule ElixirScript.Translator.Try.Test do end js_code = """ - Elixir.Core.SpecialForms._try(function() { + Bootstrap.Core.SpecialForms._try(function() { return do_something_that_may_fail(some_arg); - },Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.clause([Elixir.Core.Patterns.variable()],function(x) { + },Bootstrap.Core.Patterns.defmatch(Bootstrap.Core.Patterns.clause([Bootstrap.Core.Patterns.variable()],function(x) { return IO.puts('Invalid argument given'); },function(x) { - return Elixir.Core.Functions.contains(x,Object.freeze([ArgumentError.create(Object.freeze({}))])); + return Bootstrap.Core.Functions.contains(x,Object.freeze([ArgumentError.create(Object.freeze({}))])); })),null,null,null) """ @@ -78,9 +78,9 @@ defmodule ElixirScript.Translator.Try.Test do end js_code = """ - Elixir.Core.SpecialForms._try(function() { + Bootstrap.Core.SpecialForms._try(function() { return do_something_that_may_fail(some_arg); - },Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.clause([Elixir.Core.Patterns.variable()],function(x) { + },Bootstrap.Core.Patterns.defmatch(Bootstrap.Core.Patterns.clause([Bootstrap.Core.Patterns.variable()],function(x) { return IO.puts('Invalid argument given'); })),null,null,null) """ @@ -102,11 +102,11 @@ defmodule ElixirScript.Translator.Try.Test do end js_code = """ - Elixir.Core.SpecialForms._try(function() { + Bootstrap.Core.SpecialForms._try(function() { return do_something_that_may_fail(some_arg); - }, Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.clause([Elixir.Core.Patterns.type(ArgumentError, {})], function() { + }, Bootstrap.Core.Patterns.defmatch(Bootstrap.Core.Patterns.clause([Bootstrap.Core.Patterns.type(ArgumentError, {})], function() { return IO.puts('ArgumentError'); - }), Elixir.Core.Patterns.clause([Elixir.Core.Patterns.variable()], function(x) { + }), Bootstrap.Core.Patterns.clause([Bootstrap.Core.Patterns.variable()], function(x) { return IO.puts('x'); })), null, null, null) """ @@ -127,9 +127,9 @@ defmodule ElixirScript.Translator.Try.Test do end js_code = """ - Elixir.Core.SpecialForms._try(function() { + Bootstrap.Core.SpecialForms._try(function() { return do_something_that_may_fail(some_arg); - }, Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.clause([Elixir.Core.Patterns.type(ArgumentError, {})], function() { + }, Bootstrap.Core.Patterns.defmatch(Bootstrap.Core.Patterns.clause([Bootstrap.Core.Patterns.type(ArgumentError, {})], function() { return IO.puts('Invalid argument given'); })), null, null, function() { return IO.puts('This is printed regardless if it failed or succeed'); @@ -149,7 +149,7 @@ defmodule ElixirScript.Translator.Try.Test do end js_code = """ - Elixir.Core.SpecialForms._try(function() { + Bootstrap.Core.SpecialForms._try(function() { return do_something_that_may_fail(some_arg); },null,null,null,function() { return IO.puts('This is printed regardless if it failed or succeed'); @@ -172,13 +172,13 @@ defmodule ElixirScript.Translator.Try.Test do end js_code = """ - Elixir.Core.SpecialForms._try(function() { + Bootstrap.Core.SpecialForms._try(function() { return 1 / x; - }, null, null, Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.clause([Elixir.Core.Patterns.variable()], function(y) { + }, null, null, Bootstrap.Core.Patterns.defmatch(Bootstrap.Core.Patterns.clause([Bootstrap.Core.Patterns.variable()], function(y) { return Symbol.for('small'); }, function(y) { return y < 1 && y > -1; - }), Elixir.Core.Patterns.clause([Elixir.Core.Patterns.wildcard()], function() { + }), Bootstrap.Core.Patterns.clause([Bootstrap.Core.Patterns.wildcard()], function() { return Symbol.for('large'); })), null) """ @@ -200,11 +200,11 @@ defmodule ElixirScript.Translator.Try.Test do end js_code = """ - Elixir.Core.SpecialForms._try(function() { + Bootstrap.Core.SpecialForms._try(function() { return do_something_that_may_fail(some_arg); - }, Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.clause([Elixir.Core.Patterns.type(ArgumentError, {})], function() { + }, Bootstrap.Core.Patterns.defmatch(Bootstrap.Core.Patterns.clause([Bootstrap.Core.Patterns.type(ArgumentError, {})], function() { return IO.puts('Invalid argument given'); - })), Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.clause([Symbol.for('throw'), Symbol.for('Error')], function() { + })), Bootstrap.Core.Patterns.defmatch(Bootstrap.Core.Patterns.clause([Symbol.for('throw'), Symbol.for('Error')], function() { return IO.puts('caught error'); })), null, null) """ diff --git a/test/translator/tuple_test.exs b/test/translator/tuple_test.exs index afe44e63..189c1de9 100644 --- a/test/translator/tuple_test.exs +++ b/test/translator/tuple_test.exs @@ -4,31 +4,31 @@ defmodule ElixirScript.Translator.Tuple.Test do test "translate 2 item tuple" do ex_ast = quote do: {1, 2} - js_code = "new Elixir.Core.Tuple(1, 2)" + js_code = "new Bootstrap.Core.Tuple(1, 2)" assert_translation(ex_ast, js_code) end test "translate multiple item tuple" do ex_ast = quote do: {1, 2, 3, 4, 5} - js_code = "new Elixir.Core.Tuple(1, 2, 3, 4, 5)" + js_code = "new Bootstrap.Core.Tuple(1, 2, 3, 4, 5)" assert_translation(ex_ast, js_code) end test "translate tuples of different typed items" do ex_ast = quote do: {"a", "b", "c"} - js_code = "new Elixir.Core.Tuple('a', 'b', 'c')" + js_code = "new Bootstrap.Core.Tuple('a', 'b', 'c')" assert_translation(ex_ast, js_code) ex_ast = quote do: {:a, :b, :c} - js_code = "new Elixir.Core.Tuple(Symbol.for('a'), Symbol.for('b'), Symbol.for('c'))" + js_code = "new Bootstrap.Core.Tuple(Symbol.for('a'), Symbol.for('b'), Symbol.for('c'))" assert_translation(ex_ast, js_code) ex_ast = quote do: {:a, 2, "c"} - js_code = "new Elixir.Core.Tuple(Symbol.for('a'), 2, 'c')" + js_code = "new Bootstrap.Core.Tuple(Symbol.for('a'), 2, 'c')" assert_translation(ex_ast, js_code) end diff --git a/test/translator/with_test.exs b/test/translator/with_test.exs index 4a1fedb7..37a8afc9 100644 --- a/test/translator/with_test.exs +++ b/test/translator/with_test.exs @@ -11,16 +11,16 @@ defmodule ElixirScript.Translator.With.Test do end js_code = """ - Elixir.Core.SpecialForms._with([Elixir.Core.Patterns.type(Elixir.Core.Tuple,{ - values: [Symbol.for('ok'), Elixir.Core.Patterns.variable()] + Bootstrap.Core.SpecialForms._with([Bootstrap.Core.Patterns.type(Bootstrap.Core.Tuple,{ + values: [Symbol.for('ok'), Bootstrap.Core.Patterns.variable()] }), function() { return Elixir$ElixirScript$Map.fetch(opts,Symbol.for('width')); - }],[Elixir.Core.Patterns.type(Elixir.Core.Tuple,{ - values: [Symbol.for('ok'), Elixir.Core.Patterns.variable()] + }],[Bootstrap.Core.Patterns.type(Bootstrap.Core.Tuple,{ + values: [Symbol.for('ok'), Bootstrap.Core.Patterns.variable()] }), function(width) { return Elixir$ElixirScript$Map.fetch(opts,Symbol.for('height')); }],function(width,height) { - return new Elixir.Core.Tuple(Symbol.for('ok'),width * height); + return new Bootstrap.Core.Tuple(Symbol.for('ok'),width * height); }) """ @@ -36,18 +36,18 @@ defmodule ElixirScript.Translator.With.Test do end js_code = """ - Elixir.Core.SpecialForms._with([Elixir.Core.Patterns.type(Elixir.Core.Tuple,{ - values: [Symbol.for('ok'), Elixir.Core.Patterns.variable()] + Bootstrap.Core.SpecialForms._with([Bootstrap.Core.Patterns.type(Bootstrap.Core.Tuple,{ + values: [Symbol.for('ok'), Bootstrap.Core.Patterns.variable()] }), function() { return Elixir$ElixirScript$Map.fetch(opts,Symbol.for('width')); - }],[Elixir.Core.Patterns.variable(), function(width) { + }],[Bootstrap.Core.Patterns.variable(), function(width) { return width * 2; - }],[Elixir.Core.Patterns.type(Elixir.Core.Tuple,{ - values: [Symbol.for('ok'), Elixir.Core.Patterns.variable()] + }],[Bootstrap.Core.Patterns.type(Bootstrap.Core.Tuple,{ + values: [Symbol.for('ok'), Bootstrap.Core.Patterns.variable()] }), function(width,double_width) { return Elixir$ElixirScript$Map.fetch(opts,Symbol.for('height')); }],function(width,double_width,height) { - return new Elixir.Core.Tuple(Symbol.for('ok'),double_width * height); + return new Bootstrap.Core.Tuple(Symbol.for('ok'),double_width * height); }) """ @@ -65,18 +65,18 @@ defmodule ElixirScript.Translator.With.Test do end js_code = """ - Elixir.Core.SpecialForms._with([Elixir.Core.Patterns.type(Elixir.Core.Tuple,{ - values: [Symbol.for('ok'), Elixir.Core.Patterns.variable()] + Bootstrap.Core.SpecialForms._with([Bootstrap.Core.Patterns.type(Bootstrap.Core.Tuple,{ + values: [Symbol.for('ok'), Bootstrap.Core.Patterns.variable()] }), function() { return Elixir$ElixirScript$Map.fetch(opts,Symbol.for('width')); - }],[Elixir.Core.Patterns.type(Elixir.Core.Tuple,{ - values: [Symbol.for('ok'), Elixir.Core.Patterns.variable()] + }],[Bootstrap.Core.Patterns.type(Bootstrap.Core.Tuple,{ + values: [Symbol.for('ok'), Bootstrap.Core.Patterns.variable()] }), function(width) { return Elixir$ElixirScript$Map.fetch(opts,Symbol.for('height')); }],function(width,height) { - return new Elixir.Core.Tuple(Symbol.for('ok'),width * height); - },Elixir.Core.Patterns.defmatch(Elixir.Core.Patterns.clause([Symbol.for('error')],function() { - return new Elixir.Core.Tuple(Symbol.for('error'),Symbol.for('wrong_data')); + return new Bootstrap.Core.Tuple(Symbol.for('ok'),width * height); + },Bootstrap.Core.Patterns.defmatch(Bootstrap.Core.Patterns.clause([Symbol.for('error')],function() { + return new Bootstrap.Core.Tuple(Symbol.for('error'),Symbol.for('wrong_data')); }))) """ From fa289a42844f1c87010b1e22cda99a5b4a3477df Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Wed, 22 Feb 2017 09:43:54 -0600 Subject: [PATCH 412/860] Add config option to CLI --- lib/elixir_script/cli.ex | 50 ++++++++++++++++++++++++++++++++++++---- 1 file changed, 45 insertions(+), 5 deletions(-) diff --git a/lib/elixir_script/cli.ex b/lib/elixir_script/cli.ex index 1a6e1c70..9b359052 100644 --- a/lib/elixir_script/cli.ex +++ b/lib/elixir_script/cli.ex @@ -7,11 +7,11 @@ defmodule ElixirScript.CLI do output: :string, elixir: :boolean, help: :boolean, core_path: :string, full_build: :boolean, version: :boolean, - watch: :boolean, format: :string + watch: :boolean, format: :string, config: :boolean ] @aliases [ - o: :output, ex: :elixir, h: :help, v: :version, f: :format + o: :output, ex: :elixir, h: :help, v: :version, f: :format, c: :config ] def main(argv) do @@ -43,7 +43,9 @@ defmodule ElixirScript.CLI do usage: elixirscript [options] path to elixir files or the elixir code string if passed the -ex flag + options: + -c --config a path to an elixirscript configuration file -f --format [format] module format of output. options: es (default), common, umd -o --output [path] places output at the given path -ex --elixir read input as elixir code string @@ -52,6 +54,22 @@ defmodule ElixirScript.CLI do only used with the [output] option. When used, Elixir.js is not exported -v --version the current version number -h --help this message + + Will check for an elixirscript.exs file in the current directory. + A specific file can be given with the -c flag. + + A config file contain only a keyword list with have the following format: + [ + input: (string or list) The input path(s), + output: (string) the output path, + format: (atom) the moduel format of the output, + js_modules: (keyword) a list of the js modules that will be used + ] + + All fields are optional and will fallback to flags given + The config option is not compatible with the -ex flag + + """ end @@ -86,9 +104,15 @@ defmodule ElixirScript.CLI do true -> ElixirScript.compile(input, compile_opts) _ -> - input = input - |> Enum.map(fn(x) -> String.split(x, [" ", ","], trim: true) end) - |> List.flatten + config = options + |> Keyword.get(:config, "elixirscript.exs") + |> handle_config + |> Map.new + + input = Map.get(config, :input, handle_input(input)) + {_, config} = Map.pop(config, :input) + + compile_opts = Map.merge(compile_opts, config) ElixirScript.compile_path(input, compile_opts) @@ -109,4 +133,20 @@ defmodule ElixirScript.CLI do end) end + defp handle_input(input) do + input = input + |> Enum.map(fn(x) -> String.split(x, [" ", ","], trim: true) end) + |> List.flatten + end + + + defp handle_config(path) do + if File.exists?(path) do + {config, _} = Code.eval_file(path) + config + else + [] + end + end + end From cfab31275be13a38c195a6b0509651ad54c685f7 Mon Sep 17 00:00:00 2001 From: Matt Dziuban Date: Wed, 22 Feb 2017 11:09:13 -0500 Subject: [PATCH 413/860] Check 'opts' property on regex, not 'flags'. --- lib/std_lib/regex.ex | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/lib/std_lib/regex.ex b/lib/std_lib/regex.ex index 1176b8ac..2d3df412 100644 --- a/lib/std_lib/regex.ex +++ b/lib/std_lib/regex.ex @@ -28,7 +28,7 @@ defmodule ElixirScript.Regex do end def opts(regex) do - regex.flags + regex.opts end def run(regex, string, options \\ []) do @@ -47,7 +47,7 @@ defmodule ElixirScript.Regex do regex end - string.replace(regex, replacement) + string.replace(reg, replacement) end defp do_scan(regex, string, options, results) do @@ -60,7 +60,7 @@ defmodule ElixirScript.Regex do end defp make_global(regex) do - if String.contains?(regex.flags, "g") do + if String.contains?(opts(regex), "g") do regex else JS.new(RegExp, [ source(regex), opts(regex) <> "g" ]) From 13571f6ce38be090c929f1b5f110340208f92fcb Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Wed, 22 Feb 2017 19:04:41 -0600 Subject: [PATCH 414/860] Fix loading issues --- lib/elixir_script/module_systems/common.ex | 6 ++++-- lib/elixir_script/module_systems/es.ex | 10 +++++++--- lib/elixir_script/module_systems/namespace.ex | 10 +++++----- lib/elixir_script/module_systems/umd.ex | 11 +++++++---- lib/elixir_script/passes/consolidate_protocols.ex | 6 +++--- lib/elixir_script/passes/create_js_modules.ex | 2 +- lib/elixir_script/translator/kernel/defimpl.ex | 14 +++++++------- lib/elixir_script/translator/kernel/defprotocol.ex | 11 ++++++----- .../translator/kernel/special_forms/bitstring.ex | 4 ++-- .../translator/kernel/special_forms/call.ex | 2 +- .../translator/kernel/special_forms/fn.ex | 2 +- .../translator/kernel/special_forms/for.ex | 6 +++--- .../translator/kernel/special_forms/identifier.ex | 12 +++++++++++- .../translator/kernel/special_forms/match.ex | 4 ++-- .../translator/kernel/special_forms/primitive.ex | 6 +++--- .../translator/kernel/special_forms/quote.ex | 2 +- .../translator/kernel/special_forms/struct.ex | 2 +- lib/elixir_script/translator/pattern_matching.ex | 2 +- 18 files changed, 66 insertions(+), 46 deletions(-) diff --git a/lib/elixir_script/module_systems/common.ex b/lib/elixir_script/module_systems/common.ex index 795043c1..0b0ed8c6 100644 --- a/lib/elixir_script/module_systems/common.ex +++ b/lib/elixir_script/module_systems/common.ex @@ -22,11 +22,13 @@ defmodule ElixirScript.ModuleSystems.Common do end def import_namespace_module(module_name, from) do - do_import_module(JS.identifier(module_name), from) + js_module_name = ElixirScript.Translator.Identifier.make_namespace_members(module_name) + do_import_module(js_module_name, from) end def import_module(module_name, from) do - do_import_module(JS.identifier(module_name), from) + js_module_name = ElixirScript.Translator.Identifier.make_namespace_members(module_name) + do_import_module(js_module_name, from) end defp do_import_module(ref, file_path) do diff --git a/lib/elixir_script/module_systems/es.ex b/lib/elixir_script/module_systems/es.ex index 348ac6a3..51813427 100644 --- a/lib/elixir_script/module_systems/es.ex +++ b/lib/elixir_script/module_systems/es.ex @@ -22,17 +22,21 @@ defmodule ElixirScript.ModuleSystems.ES do end def import_namespace_module(module_name, from) do + js_module_name = ElixirScript.Translator.Identifier.make_namespace_members(module_name) + import_specifier = JS.import_namespace_specifier( - JS.identifier(module_name), - JS.identifier(module_name) + js_module_name, + js_module_name ) do_import_module([import_specifier], from) end def import_module(import_name, from) do + js_module_name = ElixirScript.Translator.Identifier.make_namespace_members(import_name) + import_specifier = JS.import_default_specifier( - JS.identifier(import_name) + js_module_name ) do_import_module([import_specifier], from) diff --git a/lib/elixir_script/module_systems/namespace.ex b/lib/elixir_script/module_systems/namespace.ex index 9ea3a549..f6164342 100644 --- a/lib/elixir_script/module_systems/namespace.ex +++ b/lib/elixir_script/module_systems/namespace.ex @@ -15,13 +15,13 @@ defmodule ElixirScript.ModuleSystems.Namespace do end end) |> Enum.map(fn {module, path} -> - import_module(module, env) + import_module(module) end) List.wrap(make_namespace_body(module_name, module_imports, body, exports)) end - defp import_module(module_name, env) do + def import_module(module_name) do name = ["Elixir" | Module.split(module_name) ] |> Enum.join("$") declarator = JS.variable_declarator( @@ -30,7 +30,7 @@ defmodule ElixirScript.ModuleSystems.Namespace do JS.member_expression( JS.call_expression( JS.member_expression( - JS.identifier(:Bootstrap), + JS.identifier("Bootstrap"), JS.member_expression( JS.identifier(:Core), JS.member_expression( @@ -54,7 +54,7 @@ defmodule ElixirScript.ModuleSystems.Namespace do _self = JS.call_expression( JS.member_expression( - JS.identifier(:Bootstrap), + JS.identifier("Bootstrap"), JS.member_expression( JS.identifier(:Core), JS.member_expression( @@ -100,7 +100,7 @@ defmodule ElixirScript.ModuleSystems.Namespace do make = JS.member_expression( JS.call_expression( JS.member_expression( - JS.identifier(:Bootstrap), + JS.identifier("Bootstrap"), JS.member_expression( JS.identifier(:Core), JS.member_expression( diff --git a/lib/elixir_script/module_systems/umd.ex b/lib/elixir_script/module_systems/umd.ex index b86cefbf..e36edd7f 100644 --- a/lib/elixir_script/module_systems/umd.ex +++ b/lib/elixir_script/module_systems/umd.ex @@ -22,15 +22,18 @@ defmodule ElixirScript.ModuleSystems.UMD do end def import_namespace_module(module_name, from) do - {JS.identifier(module_name), JS.literal(from)} + js_module_name = ElixirScript.Translator.Identifier.make_namespace_members(module_name) + {js_module_name, JS.literal(from)} end def import_module(module_name, from) do - {JS.identifier(module_name), JS.literal(from)} + js_module_name = ElixirScript.Translator.Identifier.make_namespace_members(module_name) + {js_module_name, JS.literal(from)} end - def import_module(import_name, from) do - {JS.identifier(import_name), JS.literal(from)} + def import_module(module_name, from) do + js_module_name = ElixirScript.Translator.Identifier.make_namespace_members(module_name) + {JS.identifier(module_name), JS.literal(from)} end def export_module(exported_object) do diff --git a/lib/elixir_script/passes/consolidate_protocols.ex b/lib/elixir_script/passes/consolidate_protocols.ex index 0e92b62b..a05e0153 100644 --- a/lib/elixir_script/passes/consolidate_protocols.ex +++ b/lib/elixir_script/passes/consolidate_protocols.ex @@ -71,7 +71,7 @@ defmodule ElixirScript.Passes.ConsolidateProtocols do x = Atom.to_string(Utils.quoted_to_name(impl_data.for)) x = String.to_atom(protocol_name <> ".DefImpl." <> x) name = Utils.name_to_js_name(x) - {x, ""} + ElixirScript.ModuleSystems.Namespace.import_module(x) end) body = Enum.map(implementations, fn({_, impl_data}) -> @@ -92,8 +92,8 @@ defmodule ElixirScript.Passes.ConsolidateProtocols do name: name, module: String.to_atom(protocol_name <> ".DefImpl"), std_lib: {:Elixir, Utils.make_local_file_path(:elixir, compiler_opts.core_path, compiler_opts.root, nil)}, - imports: defimpl_imports, - body: [declaration] ++ body, + imports: [], + body: defimpl_imports ++ [declaration] ++ body, exports: JS.identifier("impls"), app: app_name, type: :consolidated, diff --git a/lib/elixir_script/passes/create_js_modules.ex b/lib/elixir_script/passes/create_js_modules.ex index fef3095a..6fc7eeab 100644 --- a/lib/elixir_script/passes/create_js_modules.ex +++ b/lib/elixir_script/passes/create_js_modules.ex @@ -93,7 +93,7 @@ defmodule ElixirScript.Passes.CreateJSModules do ast = opts.module_formatter.build( [], - [{:Bootstrap, "./Elixir.Bootstrap", true }] ++ opts.js_modules, + [{"Bootstrap", "./Elixir.Bootstrap", true }] ++ opts.js_modules, [elixir, start] ++ body, JS.identifier("Elixir") ) diff --git a/lib/elixir_script/translator/kernel/defimpl.ex b/lib/elixir_script/translator/kernel/defimpl.ex index a09a5acd..0d7e0a1e 100644 --- a/lib/elixir_script/translator/kernel/defimpl.ex +++ b/lib/elixir_script/translator/kernel/defimpl.ex @@ -37,7 +37,7 @@ defmodule ElixirScript.Translator.Defimpl do defp map_to_js({:__aliases__, _, [:Integer]}, _) do JS.member_expression( JS.member_expression( - JS.identifier(:Bootstrap), + JS.identifier("Bootstrap"), JS.identifier(:Core) ), JS.identifier(:Integer) @@ -47,7 +47,7 @@ defmodule ElixirScript.Translator.Defimpl do defp map_to_js({:__aliases__, _, [:Tuple]}, _) do JS.member_expression( JS.member_expression( - JS.identifier(:Bootstrap), + JS.identifier("Bootstrap"), JS.identifier(:Core) ), JS.identifier(:Tuple) @@ -65,7 +65,7 @@ defmodule ElixirScript.Translator.Defimpl do defp map_to_js({:__aliases__, _, [:BitString]}, _) do JS.member_expression( JS.member_expression( - JS.identifier(:Bootstrap), + JS.identifier("Bootstrap"), JS.identifier(:Core) ), JS.identifier(:BitString) @@ -75,7 +75,7 @@ defmodule ElixirScript.Translator.Defimpl do defp map_to_js({:__aliases__, _, [:Float]}, _) do JS.member_expression( JS.member_expression( - JS.identifier(:Bootstrap), + JS.identifier("Bootstrap"), JS.identifier(:Core) ), JS.identifier(:Float) @@ -89,7 +89,7 @@ defmodule ElixirScript.Translator.Defimpl do defp map_to_js({:__aliases__, _, [:PID]}, _) do JS.member_expression( JS.member_expression( - JS.identifier(:Bootstrap), + JS.identifier("Bootstrap"), JS.identifier(:Core) ), JS.identifier(:PID) @@ -98,14 +98,14 @@ defmodule ElixirScript.Translator.Defimpl do defp map_to_js({:__aliases__, _, [:Port]}, _) do JS.member_expression( - JS.identifier(:Bootstrap), + JS.identifier("Bootstrap"), JS.identifier(:Port) ) end defp map_to_js({:__aliases__, _, [:Reference]}, _) do JS.member_expression( - JS.identifier(:Bootstrap), + JS.identifier("Bootstrap"), JS.identifier(:Reference) ) end diff --git a/lib/elixir_script/translator/kernel/defprotocol.ex b/lib/elixir_script/translator/kernel/defprotocol.ex index 45382fa1..9ecdbc7c 100644 --- a/lib/elixir_script/translator/kernel/defprotocol.ex +++ b/lib/elixir_script/translator/kernel/defprotocol.ex @@ -26,7 +26,7 @@ defmodule ElixirScript.Translator.Defprotocol do JS.identifier(Utils.name_to_js_name(name)), JS.call_expression( JS.member_expression( - JS.identifier(:Bootstrap), + JS.identifier("Bootstrap"), JS.member_expression( JS.identifier(:Core), JS.member_expression( @@ -42,7 +42,7 @@ defmodule ElixirScript.Translator.Defprotocol do declaration = JS.variable_declaration([declarator], :const) implementation_name_split = Module.split(name) ++ ["DefImpl"] - implementation_name = Enum.join(implementation_name_split, "$") + implementation_name = Enum.join(["Elixir"] ++ implementation_name_split, "$") implementation_name_module = Module.concat(implementation_name_split) implementations = JS.for_of_statement( @@ -56,7 +56,7 @@ defmodule ElixirScript.Translator.Defprotocol do JS.identifier(implementation_name), JS.call_expression( JS.member_expression( - JS.identifier(:Bootstrap), + JS.identifier("Bootstrap"), JS.member_expression( JS.identifier(:Core), JS.member_expression( @@ -77,11 +77,12 @@ defmodule ElixirScript.Translator.Defprotocol do module_refs = State.get_module_references(env.state, env.module) -- [env.module] imports = Defmodule.process_module_refs(module_refs, env) + defimpl_import = ElixirScript.ModuleSystems.Namespace.import_module(implementation_name_module) %{ name: name, - imports: imports ++ [{implementation_name_module, ""}], - body: body, + imports: imports, + body: [defimpl_import] ++ body, exports: JS.identifier(Utils.name_to_js_name(name)), app_name: app_name, env: env diff --git a/lib/elixir_script/translator/kernel/special_forms/bitstring.ex b/lib/elixir_script/translator/kernel/special_forms/bitstring.ex index 2e2bc2ce..00107d8d 100644 --- a/lib/elixir_script/translator/kernel/special_forms/bitstring.ex +++ b/lib/elixir_script/translator/kernel/special_forms/bitstring.ex @@ -8,7 +8,7 @@ defmodule ElixirScript.Translator.Bitstring do js_ast = JS.new_expression( JS.member_expression( JS.member_expression( - JS.identifier(:Bootstrap), + JS.identifier("Bootstrap"), JS.identifier("Core") ), JS.identifier("BitString") @@ -88,7 +88,7 @@ defmodule ElixirScript.Translator.Bitstring do defp bitstring_class() do JS.member_expression( JS.member_expression( - JS.identifier(:Bootstrap), + JS.identifier("Bootstrap"), JS.identifier("Core") ), JS.identifier("BitString") diff --git a/lib/elixir_script/translator/kernel/special_forms/call.ex b/lib/elixir_script/translator/kernel/special_forms/call.ex index c07f84a6..2fd958e5 100644 --- a/lib/elixir_script/translator/kernel/special_forms/call.ex +++ b/lib/elixir_script/translator/kernel/special_forms/call.ex @@ -17,7 +17,7 @@ defmodule ElixirScript.Translator.Call do js_ast = JS.call_expression( JS.member_expression( JS.member_expression( - JS.identifier(:Bootstrap), + JS.identifier("Bootstrap"), JS.member_expression( JS.identifier("Core"), JS.identifier("Functions") diff --git a/lib/elixir_script/translator/kernel/special_forms/fn.ex b/lib/elixir_script/translator/kernel/special_forms/fn.ex index fc9cb865..ffd6329a 100644 --- a/lib/elixir_script/translator/kernel/special_forms/fn.ex +++ b/lib/elixir_script/translator/kernel/special_forms/fn.ex @@ -8,7 +8,7 @@ defmodule ElixirScript.Translator.Function do @patterns JS.member_expression( JS.member_expression( - JS.identifier(:Bootstrap), + JS.identifier("Bootstrap"), JS.identifier("Core") ), JS.identifier("Patterns") diff --git a/lib/elixir_script/translator/kernel/special_forms/for.ex b/lib/elixir_script/translator/kernel/special_forms/for.ex index c5f8f17e..45c076da 100644 --- a/lib/elixir_script/translator/kernel/special_forms/for.ex +++ b/lib/elixir_script/translator/kernel/special_forms/for.ex @@ -21,7 +21,7 @@ defmodule ElixirScript.Translator.For do JS.member_expression( JS.member_expression( JS.member_expression( - JS.identifier(:Bootstrap), + JS.identifier("Bootstrap"), JS.identifier("Core") ), JS.identifier("Patterns") @@ -59,7 +59,7 @@ defmodule ElixirScript.Translator.For do JS.member_expression( JS.member_expression( JS.member_expression( - JS.identifier(:Bootstrap), + JS.identifier("Bootstrap"), JS.identifier("Core") ), JS.identifier("Patterns") @@ -78,7 +78,7 @@ defmodule ElixirScript.Translator.For do JS.member_expression( JS.member_expression( JS.member_expression( - JS.identifier(:Bootstrap), + JS.identifier("Bootstrap"), JS.identifier("Core") ), JS.identifier("Patterns") diff --git a/lib/elixir_script/translator/kernel/special_forms/identifier.ex b/lib/elixir_script/translator/kernel/special_forms/identifier.ex index 37d9d2b5..433a3e48 100644 --- a/lib/elixir_script/translator/kernel/special_forms/identifier.ex +++ b/lib/elixir_script/translator/kernel/special_forms/identifier.ex @@ -35,7 +35,6 @@ defmodule ElixirScript.Translator.Identifier do :yield ] - def make_identifier({:__aliases__, _, aliases}) do aliases |> Enum.reverse @@ -70,4 +69,15 @@ defmodule ElixirScript.Translator.Identifier do JS.member_expression(make_alias(t), make_identifier(h)) end + def make_namespace_members(module_name) do + case module_name do + m when is_binary(m) -> + String.split(m, ".") + m when is_atom(m) -> + Module.split(m) + end + |> Enum.reverse + |> make_alias + end + end diff --git a/lib/elixir_script/translator/kernel/special_forms/match.ex b/lib/elixir_script/translator/kernel/special_forms/match.ex index 49f44a80..b59ffd64 100644 --- a/lib/elixir_script/translator/kernel/special_forms/match.ex +++ b/lib/elixir_script/translator/kernel/special_forms/match.ex @@ -16,7 +16,7 @@ defmodule ElixirScript.Translator.Match do JS.member_expression( JS.member_expression( JS.member_expression( - JS.identifier(:Bootstrap), + JS.identifier("Bootstrap"), JS.identifier("Core") ), JS.identifier("Patterns") @@ -61,7 +61,7 @@ defmodule ElixirScript.Translator.Match do ref, JS.new_expression( JS.member_expression( - JS.identifier(:Bootstrap), + JS.identifier("Bootstrap"), JS.member_expression( JS.identifier("Core"), JS.identifier("Tuple") diff --git a/lib/elixir_script/translator/kernel/special_forms/primitive.ex b/lib/elixir_script/translator/kernel/special_forms/primitive.ex index 5dbe92b5..292ccbcc 100644 --- a/lib/elixir_script/translator/kernel/special_forms/primitive.ex +++ b/lib/elixir_script/translator/kernel/special_forms/primitive.ex @@ -6,7 +6,7 @@ defmodule ElixirScript.Translator.Primitive do def special_forms() do JS.member_expression( - JS.identifier(:Bootstrap), + JS.identifier("Bootstrap"), JS.member_expression( JS.identifier("Core"), JS.identifier("SpecialForms") @@ -17,7 +17,7 @@ defmodule ElixirScript.Translator.Primitive do def tuple_class() do JS.member_expression( JS.member_expression( - JS.identifier(:Bootstrap), + JS.identifier("Bootstrap"), JS.identifier("Core") ), JS.identifier("Tuple") @@ -27,7 +27,7 @@ defmodule ElixirScript.Translator.Primitive do def list_ast() do JS.member_expression( JS.member_expression( - JS.identifier(:Bootstrap), + JS.identifier("Bootstrap"), JS.member_expression( JS.identifier("Core"), JS.identifier("SpecialForms") diff --git a/lib/elixir_script/translator/kernel/special_forms/quote.ex b/lib/elixir_script/translator/kernel/special_forms/quote.ex index 76033f88..d0b7d03d 100644 --- a/lib/elixir_script/translator/kernel/special_forms/quote.ex +++ b/lib/elixir_script/translator/kernel/special_forms/quote.ex @@ -26,7 +26,7 @@ defmodule ElixirScript.Translator.Quote do JS.call_expression( JS.member_expression( - JS.identifier(:Bootstrap), + JS.identifier("Bootstrap"), JS.member_expression( JS.identifier("Enum"), JS.identifier("concat") diff --git a/lib/elixir_script/translator/kernel/special_forms/struct.ex b/lib/elixir_script/translator/kernel/special_forms/struct.ex index 5aa8d058..b1123545 100644 --- a/lib/elixir_script/translator/kernel/special_forms/struct.ex +++ b/lib/elixir_script/translator/kernel/special_forms/struct.ex @@ -112,7 +112,7 @@ defmodule ElixirScript.Translator.Struct do JS.call_expression( JS.member_expression( JS.member_expression( - JS.identifier(:Bootstrap), + JS.identifier("Bootstrap"), JS.member_expression( JS.identifier("Core"), JS.identifier("Functions") diff --git a/lib/elixir_script/translator/pattern_matching.ex b/lib/elixir_script/translator/pattern_matching.ex index 2934677d..241b7f45 100644 --- a/lib/elixir_script/translator/pattern_matching.ex +++ b/lib/elixir_script/translator/pattern_matching.ex @@ -11,7 +11,7 @@ defmodule ElixirScript.Translator.PatternMatching do @patterns JS.member_expression( JS.member_expression( - JS.identifier(:Bootstrap), + JS.identifier("Bootstrap"), JS.identifier("Core") ), JS.identifier("Patterns") From a292b28cc3e101c49bf8604814965c4ae2d6e8e4 Mon Sep 17 00:00:00 2001 From: Matt Dziuban Date: Wed, 22 Feb 2017 20:30:56 -0500 Subject: [PATCH 415/860] Use `args[0]` as `this` argument when applying function, return result. --- src/javascript/lib/core/functions.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/javascript/lib/core/functions.js b/src/javascript/lib/core/functions.js index f76a2422..4ba9945f 100644 --- a/src/javascript/lib/core/functions.js +++ b/src/javascript/lib/core/functions.js @@ -33,9 +33,9 @@ function call_property(item, property) { function apply(...args) { if (args.length === 2) { - args[0].apply(null, args.slice(1)); + return args[0].apply(args[0], args.slice(1)); } else { - args[0][args[1]].apply(null, args.slice(2)); + return args[0][args[1]].apply(args[0], args.slice(2)); } } From e71a7143a33a1139778c4068b5bbd1656af6f9f2 Mon Sep 17 00:00:00 2001 From: Matt Dziuban Date: Wed, 22 Feb 2017 20:30:59 -0500 Subject: [PATCH 416/860] Fix regex `match?`. --- lib/std_lib/regex.ex | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/lib/std_lib/regex.ex b/lib/std_lib/regex.ex index 2d3df412..17888909 100644 --- a/lib/std_lib/regex.ex +++ b/lib/std_lib/regex.ex @@ -20,7 +20,8 @@ defmodule ElixirScript.Regex do end def match?(regex, string) do - regex.test(string) + reg = if regex?(regex), do: regex, else: compile!(source(regex), opts(regex)) + reg.test(string) end def source(regex) do From a1017dd0219449b322123e01030afb6513ec673a Mon Sep 17 00:00:00 2001 From: Matt Dziuban Date: Wed, 22 Feb 2017 20:31:01 -0500 Subject: [PATCH 417/860] Fix variable naming collisions in list operations. --- lib/std_lib/list.ex | 34 +++++++++++++++++----------------- 1 file changed, 17 insertions(+), 17 deletions(-) diff --git a/lib/std_lib/list.ex b/lib/std_lib/list.ex index 962c224c..9cdfe94d 100644 --- a/lib/std_lib/list.ex +++ b/lib/std_lib/list.ex @@ -1,5 +1,5 @@ defmodule ElixirScript.List do - @moduledoc false + @moduledoc false require JS def duplicate(data, size) do @@ -50,14 +50,14 @@ defmodule ElixirScript.List do if current_index == length(list) do new_list else - new_list = case list[current_index] do + updated = case list[current_index] do ^item -> new_list _ -> new_list ++ [list[current_index]] end - do_delete(list, item, current_index + 1, new_list) + do_delete(list, item, current_index + 1, updated) end end @@ -69,14 +69,14 @@ defmodule ElixirScript.List do if current_index == length(list) do new_list else - new_list = case current_index == index do + updated = case current_index == index do true -> new_list _ -> new_list ++ [list[current_index]] end - do_delete_at(list, index, current_index + 1, new_list) + do_delete_at(list, index, current_index + 1, updated) end end @@ -88,14 +88,14 @@ defmodule ElixirScript.List do if current_index == length(list) do new_list else - new_list = case current_index == index do + updated = case current_index == index do true -> new_list ++ [value, list[current_index]] _ -> new_list ++ [list[current_index]] end - do_insert_at(list, index, value, current_index + 1, new_list) + do_insert_at(list, index, value, current_index + 1, updated) end end @@ -107,14 +107,14 @@ defmodule ElixirScript.List do if current_index == length(list) do new_list else - new_list = case current_index == index do + updated = case current_index == index do true -> new_list ++ [value] _ -> new_list ++ [list[current_index]] end - do_replace_at(list, index, value, current_index + 1, new_list) + do_replace_at(list, index, value, current_index + 1, updated) end end @@ -127,14 +127,14 @@ defmodule ElixirScript.List do if current_index == length(list) do new_list else - new_list = case current_index == index do + updated = case current_index == index do true -> new_list ++ [func.(list[current_index])] _ -> new_list ++ [list[current_index]] end - do_update_at(list, index, func, current_index + 1, new_list) + do_update_at(list, index, func, current_index + 1, updated) end end @@ -169,14 +169,14 @@ defmodule ElixirScript.List do end defp do_flatten(list, flattened_list) do - flattened_list = case hd(list) do + updated = case hd(list) do l when is_list(l) -> flattened_list ++ do_flatten(l, []) item -> flattened_list ++ [item] end - do_flatten(tl(list), flattened_list) + do_flatten(tl(list), updated) end @@ -191,13 +191,13 @@ defmodule ElixirScript.List do defp do_keydelete(list, key, position, new_list) do current_value = hd(list) - new_list = if elem(current_value, position) == key do + updated = if elem(current_value, position) == key do new_list else new_list ++ [current_value] end - do_keydelete(tl(list), key, position, new_list) + do_keydelete(tl(list), key, position, updated) end def keyfind(list, key, position) do @@ -237,13 +237,13 @@ defmodule ElixirScript.List do defp do_keyreplace(list, key, position, new_list, new_tuple) do current_value = hd(list) - new_list = if elem(current_value, position) == key do + updated = if elem(current_value, position) == key do new_list ++ [new_tuple] else new_list ++ [current_value] end - do_keyreplace(tl(list), key, position, new_list, new_tuple) + do_keyreplace(tl(list), key, position, updated, new_tuple) end def zip(list_of_lists) do From 43bc9e60bd090c4342dc308c31c9710abf5fe3ad Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Wed, 22 Feb 2017 19:32:26 -0600 Subject: [PATCH 418/860] Update mix compiler functions --- lib/elixir_script/passes/create_js_modules.ex | 1 - lib/mix/tasks/compile.elixir_script.ex | 3 ++- lib/mix/tasks/elixirscript.watch.ex | 8 ++++++-- 3 files changed, 8 insertions(+), 4 deletions(-) diff --git a/lib/elixir_script/passes/create_js_modules.ex b/lib/elixir_script/passes/create_js_modules.ex index 6fc7eeab..0523a6db 100644 --- a/lib/elixir_script/passes/create_js_modules.ex +++ b/lib/elixir_script/passes/create_js_modules.ex @@ -90,7 +90,6 @@ defmodule ElixirScript.Passes.CreateJSModules do ) ) - ast = opts.module_formatter.build( [], [{"Bootstrap", "./Elixir.Bootstrap", true }] ++ opts.js_modules, diff --git a/lib/mix/tasks/compile.elixir_script.ex b/lib/mix/tasks/compile.elixir_script.ex index b15496d1..b9c6a238 100644 --- a/lib/mix/tasks/compile.elixir_script.ex +++ b/lib/mix/tasks/compile.elixir_script.ex @@ -60,8 +60,9 @@ defmodule Mix.Tasks.Compile.ElixirScript do output_path = Keyword.get(elixirscript_config, :output) format = Keyword.get(elixirscript_config, :format) + js_modules = Keyword.get(elixirscript_config, :js_modules, []) - ElixirScript.compile_path(paths, %{output: output_path, format: format}) + ElixirScript.compile_path(paths, %{output: output_path, format: format, js_modules: js_modules}) :ok end diff --git a/lib/mix/tasks/elixirscript.watch.ex b/lib/mix/tasks/elixirscript.watch.ex index 31d0e3de..ace5bbc6 100644 --- a/lib/mix/tasks/elixirscript.watch.ex +++ b/lib/mix/tasks/elixirscript.watch.ex @@ -28,9 +28,13 @@ defmodule Mix.Tasks.Elixirscript.Watch do elixirscript_config = get_elixirscript_config() input_path = Keyword.get(elixirscript_config, :input) output_path = Keyword.get(elixirscript_config, :output) - format = Keyword.get(elixirscript_config, :format) + format = Keyword.get(elixirscript_config, :format) + js_modules = Keyword.get(elixirscript_config, :js_modules, []) - {:ok, _} = ElixirScript.Watcher.start_link(input_path, %{output: output_path, format: format}) + {:ok, _} = ElixirScript.Watcher.start_link( + input_path, + %{output: output_path, format: format, js_modules: js_modules} + ) :timer.sleep :infinity end From 7d1d82295b7a9c52e4039a09365952c1af934e04 Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Wed, 22 Feb 2017 19:56:39 -0600 Subject: [PATCH 419/860] Update umd test --- CHANGELOG.md | 33 +++++++++++++++++++++++++++++++++ test/translator/umd_test.exs | 7 +++++++ 2 files changed, 40 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index fd131a0c..fc5128c5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,6 +9,39 @@ and this project adheres to [Semantic Versioning](http://semver.org/). ### Added - Multiple `when` clauses in guards - Kernel.defdelegate/2 +- CLI can now take a configuration file. By default it will look for `elixirscript.exs` in the current directory. + A configuration file can be explicitly given using the `-c` flag +- `js_modules` configuration option has been added. This is a keyword list of JavaScript modules that will be used. + ``` + js_modules: [ + {React, "react"}, + {ReactDOM, "react-dom"} + ] + ``` + This is accepted in either the elixirscript.exs file described above or in the `elixir_script` mix configuration + +### Removed +- `@on_js_load` has been removed in favor of having a `start/2` function defined. More info below +- `JS.import` has been removed in favor of defining JavaScript modules used in configuration + +### Changed +- All Modules are now bundled together as one js file. The `Elixir.Bootstrap.js` file is also still created + The exported object has Elixir modules in JavaScript namespaces that are lazily loaded when called. + + To start your application import the bundle according to whichever module format was selected and + then call start giving it the module and the initial args + + ```javascript + //ES module example + import Elixir from './Elixir.App' + Elixir.start(Elixir.App, []) + ``` + + The `start` function will look for a `start/2` function there. + This is analogous to a [Application module callback](https://hexdocs.pm/elixir/Application.html#module-application-module-callback) + + + ## [0.25.0] - 2017-02-19 diff --git a/test/translator/umd_test.exs b/test/translator/umd_test.exs index 9256c3f3..b7421015 100644 --- a/test/translator/umd_test.exs +++ b/test/translator/umd_test.exs @@ -18,6 +18,13 @@ defmodule ElixirScript.Translator.UMD.Test do js_code = """ (function(root, factory) { + if (typeof define === 'function' && define.amd) { + define(['./Elixir.Bootstrap'], factory) + } else if (typeof exports === 'object') { + module.exports = factory(require('./Elixir.Bootstrap')) + } else { + root.returnExports = factory(root.Bootstrap) + } """ assert_translation(ex_ast, js_code, :umd) From d8ebb64142c4549e8953a95ae14e191edcb7c26f Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Wed, 22 Feb 2017 20:37:25 -0600 Subject: [PATCH 420/860] Add std_lib folder to dist --- mix.exs | 1 + 1 file changed, 1 insertion(+) diff --git a/mix.exs b/mix.exs index a8275289..b05cfbf8 100644 --- a/mix.exs +++ b/mix.exs @@ -90,6 +90,7 @@ defmodule ElixirScript.Mixfile do end File.cp_r!("priv/", "#{folder_name}") File.cp!("LICENSE", "#{folder_name}/LICENSE") + File.cp_r!("lib/std_lib", "#{folder_name}/std_lib") System.cmd("tar", ["czf", archive_file_name, folder_name]) From ffc9efad1219f9c383895fb4258ba0cef385c508 Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Wed, 22 Feb 2017 21:25:23 -0600 Subject: [PATCH 421/860] Move std_lib folder to priv. Remove compile_std_lib function and std_lib task --- .travis.yml | 2 +- README.md | 4 +- lib/elixir_script.ex | 63 ++++++++--------------- lib/elixir_script/passes/handle_output.ex | 15 ++---- lib/elixir_script/translator/state.ex | 3 +- mix.exs | 15 ++---- {lib => priv}/std_lib/agent.ex | 0 {lib => priv}/std_lib/atom.ex | 0 {lib => priv}/std_lib/base.ex | 0 {lib => priv}/std_lib/bitwise.ex | 0 {lib => priv}/std_lib/collectable.ex | 0 {lib => priv}/std_lib/enumerable.ex | 0 {lib => priv}/std_lib/integer.ex | 0 {lib => priv}/std_lib/js.ex | 0 {lib => priv}/std_lib/kernel.ex | 0 {lib => priv}/std_lib/keyword.ex | 0 {lib => priv}/std_lib/list.ex | 0 {lib => priv}/std_lib/macro/env.ex | 0 {lib => priv}/std_lib/map.ex | 0 {lib => priv}/std_lib/map_set.ex | 0 {lib => priv}/std_lib/module.ex | 0 {lib => priv}/std_lib/range.ex | 0 {lib => priv}/std_lib/regex.ex | 0 {lib => priv}/std_lib/string.ex | 0 {lib => priv}/std_lib/string/chars.ex | 0 {lib => priv}/std_lib/tuple.ex | 0 test/translator/pattern_matching_test.exs | 20 +++++-- 27 files changed, 48 insertions(+), 74 deletions(-) rename {lib => priv}/std_lib/agent.ex (100%) rename {lib => priv}/std_lib/atom.ex (100%) rename {lib => priv}/std_lib/base.ex (100%) rename {lib => priv}/std_lib/bitwise.ex (100%) rename {lib => priv}/std_lib/collectable.ex (100%) rename {lib => priv}/std_lib/enumerable.ex (100%) rename {lib => priv}/std_lib/integer.ex (100%) rename {lib => priv}/std_lib/js.ex (100%) rename {lib => priv}/std_lib/kernel.ex (100%) rename {lib => priv}/std_lib/keyword.ex (100%) rename {lib => priv}/std_lib/list.ex (100%) rename {lib => priv}/std_lib/macro/env.ex (100%) rename {lib => priv}/std_lib/map.ex (100%) rename {lib => priv}/std_lib/map_set.ex (100%) rename {lib => priv}/std_lib/module.ex (100%) rename {lib => priv}/std_lib/range.ex (100%) rename {lib => priv}/std_lib/regex.ex (100%) rename {lib => priv}/std_lib/string.ex (100%) rename {lib => priv}/std_lib/string/chars.ex (100%) rename {lib => priv}/std_lib/tuple.ex (100%) diff --git a/.travis.yml b/.travis.yml index 55de8f28..30b68c8e 100644 --- a/.travis.yml +++ b/.travis.yml @@ -13,7 +13,7 @@ script: - mix local.hex --force - mix local.rebar --force - mix deps.get - - mix do std_lib, clean, compile + - mix do clean, compile - mix test - npm test notifications: diff --git a/README.md b/README.md index f4e9702f..724895ef 100644 --- a/README.md +++ b/README.md @@ -33,7 +33,7 @@ Get dependencies Compile - mix do std_lib, clean, compile + mix do clean, compile Test @@ -43,7 +43,7 @@ Test Build ============= - MIX_ENV=prod mix do clean, compile, std_lib, dist + MIX_ENV=prod mix do clean, compile, dist This will build a tarball in the dist folder. By default the escript built will look into the folder above it for the diff --git a/lib/elixir_script.ex b/lib/elixir_script.ex index b3da2a31..a37d7146 100644 --- a/lib/elixir_script.ex +++ b/lib/elixir_script.ex @@ -73,12 +73,13 @@ defmodule ElixirScript do |> get_modules_from_quoted |> Enum.map(fn(x) -> %{ast: x, app: :app} end) + data = get_quoted_std_lib() ++ data + result = %{data: data} |> ElixirScript.Passes.Init.execute(opts) |> ElixirScript.Passes.FindModules.execute(opts) |> ElixirScript.Passes.FindLoadOnly.execute(opts) |> ElixirScript.Passes.FindFunctions.execute(opts) - |> ElixirScript.Passes.AddStdLib.execute(opts) |> ElixirScript.Passes.JavaScriptAST.execute(opts) |> ElixirScript.Passes.ConsolidateProtocols.execute(opts) |> ElixirScript.Passes.CreateJSModules.execute(opts) @@ -89,6 +90,15 @@ defmodule ElixirScript do result end + defp get_quoted_std_lib() do + Path.join([get_std_lib_path(), "**", "*.ex"]) + |> Path.wildcard + |> Enum.map(fn path -> File.read!(path) end) + |> Enum.map(&Code.string_to_quoted!(&1)) + |> Enum.flat_map(&get_modules_from_quoted(&1)) + |> Enum.map(fn(x) -> %{ast: x, app: :elixir} end) + end + defp get_modules_from_quoted(quoted) do results = case quoted do {:__block__, _, list} -> @@ -150,6 +160,8 @@ defmodule ElixirScript do |> Map.to_list |> Enum.map(fn {app, path} -> {app, List.wrap(path)} end) + deps = [{:elixir, List.wrap(get_std_lib_path())}] ++ deps + result = %{data: deps} |> ElixirScript.Passes.Init.execute(opts) |> ElixirScript.Passes.ASTFromFile.execute(opts) @@ -157,7 +169,6 @@ defmodule ElixirScript do |> ElixirScript.Passes.FindModules.execute(opts) |> ElixirScript.Passes.FindLoadOnly.execute(opts) |> ElixirScript.Passes.FindFunctions.execute(opts) - |> ElixirScript.Passes.AddStdLib.execute(opts) |> ElixirScript.Passes.JavaScriptAST.execute(opts) |> ElixirScript.Passes.ConsolidateProtocols.execute(opts) |> ElixirScript.Passes.CreateJSModules.execute(opts) @@ -168,45 +179,9 @@ defmodule ElixirScript do result end - @doc false - def get_stdlib_state() do - case @stdlib_state do - {:ok, data} -> - data - {:error, _} -> - raise RuntimeError, message: "Standard Library state not found. Please run `mix std_lib`" - end - end - @doc false def version(), do: @version - @doc false - def compile_std_lib() do - compile_std_lib(Path.join([File.cwd!, "priv"])) - end - - @doc false - def compile_std_lib(output_path) do - opts = build_compiler_options(%{std_lib: true, include_path: true, output: output_path, app: :elixir}) - libs_path = Path.join([__DIR__, "std_lib"]) - - result = %{data: [{:elixir, List.wrap(libs_path)}]} - |> ElixirScript.Passes.Init.execute(opts) - |> ElixirScript.Passes.ASTFromFile.execute(opts) - |> ElixirScript.Passes.FindModules.execute(opts) - |> ElixirScript.Passes.FindLoadOnly.execute(opts) - |> ElixirScript.Passes.FindFunctions.execute(opts) - |> ElixirScript.Passes.JavaScriptAST.execute(opts) - |> ElixirScript.Passes.ConsolidateProtocols.execute(opts) - |> ElixirScript.Passes.CreateJSModules.execute(opts) - |> ElixirScript.Passes.JavaScriptCode.execute(opts) - |> ElixirScript.Passes.JavaScriptName.execute(opts) - |> ElixirScript.Passes.HandleOutput.execute(opts) - - result - end - defp build_compiler_options(opts) do default_options = Map.new |> Map.put(:include_path, false) @@ -237,10 +212,10 @@ defmodule ElixirScript do end @doc """ - Copies the javascript that makes up the ElixirScript stdlib + Copies the javascript that makes up the ElixirScript bootstrap to the specified location """ - def copy_stdlib_to_destination(module_format, destination) do + def copy_bootstrap_to_destination(module_format, destination) do path = Path.join([operating_path, to_string(module_format), "elixir", "Elixir.Bootstrap.js"]) base = Path.basename(path) File.mkdir_p!(destination) @@ -249,11 +224,11 @@ defmodule ElixirScript do #Gets path to js files whether the mix project is available #or when used as an escript - defp operating_path do + defp operating_path() do case @lib_path do nil -> if Code.ensure_loaded?(Mix.Project) do - Mix.Project.build_path <> "/lib/elixir_script/priv" + Path.join([Mix.Project.build_path, "lib", "elixir_script", "priv"]) else split_path = Path.split(Application.app_dir(:elixirscript)) replaced_path = List.delete_at(split_path, length(split_path) - 1) @@ -265,4 +240,8 @@ defmodule ElixirScript do end end + defp get_std_lib_path() do + Path.join([operating_path(), "std_lib"]) + end + end diff --git a/lib/elixir_script/passes/handle_output.ex b/lib/elixir_script/passes/handle_output.ex index 8eb5edc8..e4144ae7 100644 --- a/lib/elixir_script/passes/handle_output.ex +++ b/lib/elixir_script/passes/handle_output.ex @@ -3,17 +3,8 @@ defmodule ElixirScript.Passes.HandleOutput do alias ElixirScript.Translator.State def execute(compiler_data, opts) do - - if Map.get(opts, :std_lib, false) do - State.set_module_data(compiler_data.state, compiler_data.data) - new_std_state = State.serialize(compiler_data.state) - stdlib_state_path = Path.join([File.cwd!(), "lib", "elixir_script", "translator", "stdlib_state.bin"]) - File.write!(stdlib_state_path, new_std_state) - State.stop(compiler_data.state) - else - State.stop(compiler_data.state) - out(compiler_data, opts) - end + State.stop(compiler_data.state) + out(compiler_data, opts) end defp out(compiler_output, %{output: nil} = compiler_opts) do @@ -33,7 +24,7 @@ defmodule ElixirScript.Passes.HandleOutput do defp out(compiler_output, %{output: output_path, core_path: _} = compiler_opts) do if Map.get(compiler_opts, :std_lib, false) == false do - ElixirScript.copy_stdlib_to_destination(compiler_opts.format, output_path) + ElixirScript.copy_bootstrap_to_destination(compiler_opts.format, output_path) end file_name = Path.join([output_path, compiler_output.generated_name]) diff --git a/lib/elixir_script/translator/state.ex b/lib/elixir_script/translator/state.ex index 7ebf5ef4..25d038a0 100644 --- a/lib/elixir_script/translator/state.ex +++ b/lib/elixir_script/translator/state.ex @@ -70,8 +70,7 @@ defmodule ElixirScript.Translator.State do def set_module_data(pid, module_data) do Agent.update(pid, fn state -> - data = Enum.filter(state.modules, fn {module_name, data} -> data.app == :elixir end) - %{ state | modules: Keyword.merge(data, module_data) } + %{ state | modules: Keyword.merge(state.modules, module_data) } end) end diff --git a/mix.exs b/mix.exs index b05cfbf8..77c60865 100644 --- a/mix.exs +++ b/mix.exs @@ -6,6 +6,7 @@ defmodule ElixirScript.Mixfile do app: :elixir_script, version: "0.26.0-dev", elixir: "~> 1.0", + elixirc_paths: elixirc_paths(), escript: escript_config(), deps: deps(), description: description(), @@ -36,6 +37,8 @@ defmodule ElixirScript.Mixfile do ] end + defp elixirc_paths(), do: ["lib", "priv/std_lib"] + defp escript_config do [main_module: ElixirScript.CLI, name: "elixirscript"] end @@ -48,7 +51,7 @@ defmodule ElixirScript.Mixfile do defp package do [ - files: ["lib", "priv/**/*.js", "mix.exs", "README.md", "LICENSE", "CHANGELOG.md"], + files: ["lib", "priv/**/*.*", "mix.exs", "README.md", "LICENSE", "CHANGELOG.md"], maintainers: ["Bryan Joseph"], licenses: ["MIT"], links: %{ @@ -60,14 +63,7 @@ defmodule ElixirScript.Mixfile do defp aliases do [dist: &dist/1, - install: &install/1, - std_lib: &std_lib/1] - end - - def std_lib(_) do - Mix.Task.run "app.start" - {_ , _} = System.cmd("npm", ["run", "build"]) - ElixirScript.compile_std_lib() + install: &install/1] end def dist(_) do @@ -90,7 +86,6 @@ defmodule ElixirScript.Mixfile do end File.cp_r!("priv/", "#{folder_name}") File.cp!("LICENSE", "#{folder_name}/LICENSE") - File.cp_r!("lib/std_lib", "#{folder_name}/std_lib") System.cmd("tar", ["czf", archive_file_name, folder_name]) diff --git a/lib/std_lib/agent.ex b/priv/std_lib/agent.ex similarity index 100% rename from lib/std_lib/agent.ex rename to priv/std_lib/agent.ex diff --git a/lib/std_lib/atom.ex b/priv/std_lib/atom.ex similarity index 100% rename from lib/std_lib/atom.ex rename to priv/std_lib/atom.ex diff --git a/lib/std_lib/base.ex b/priv/std_lib/base.ex similarity index 100% rename from lib/std_lib/base.ex rename to priv/std_lib/base.ex diff --git a/lib/std_lib/bitwise.ex b/priv/std_lib/bitwise.ex similarity index 100% rename from lib/std_lib/bitwise.ex rename to priv/std_lib/bitwise.ex diff --git a/lib/std_lib/collectable.ex b/priv/std_lib/collectable.ex similarity index 100% rename from lib/std_lib/collectable.ex rename to priv/std_lib/collectable.ex diff --git a/lib/std_lib/enumerable.ex b/priv/std_lib/enumerable.ex similarity index 100% rename from lib/std_lib/enumerable.ex rename to priv/std_lib/enumerable.ex diff --git a/lib/std_lib/integer.ex b/priv/std_lib/integer.ex similarity index 100% rename from lib/std_lib/integer.ex rename to priv/std_lib/integer.ex diff --git a/lib/std_lib/js.ex b/priv/std_lib/js.ex similarity index 100% rename from lib/std_lib/js.ex rename to priv/std_lib/js.ex diff --git a/lib/std_lib/kernel.ex b/priv/std_lib/kernel.ex similarity index 100% rename from lib/std_lib/kernel.ex rename to priv/std_lib/kernel.ex diff --git a/lib/std_lib/keyword.ex b/priv/std_lib/keyword.ex similarity index 100% rename from lib/std_lib/keyword.ex rename to priv/std_lib/keyword.ex diff --git a/lib/std_lib/list.ex b/priv/std_lib/list.ex similarity index 100% rename from lib/std_lib/list.ex rename to priv/std_lib/list.ex diff --git a/lib/std_lib/macro/env.ex b/priv/std_lib/macro/env.ex similarity index 100% rename from lib/std_lib/macro/env.ex rename to priv/std_lib/macro/env.ex diff --git a/lib/std_lib/map.ex b/priv/std_lib/map.ex similarity index 100% rename from lib/std_lib/map.ex rename to priv/std_lib/map.ex diff --git a/lib/std_lib/map_set.ex b/priv/std_lib/map_set.ex similarity index 100% rename from lib/std_lib/map_set.ex rename to priv/std_lib/map_set.ex diff --git a/lib/std_lib/module.ex b/priv/std_lib/module.ex similarity index 100% rename from lib/std_lib/module.ex rename to priv/std_lib/module.ex diff --git a/lib/std_lib/range.ex b/priv/std_lib/range.ex similarity index 100% rename from lib/std_lib/range.ex rename to priv/std_lib/range.ex diff --git a/lib/std_lib/regex.ex b/priv/std_lib/regex.ex similarity index 100% rename from lib/std_lib/regex.ex rename to priv/std_lib/regex.ex diff --git a/lib/std_lib/string.ex b/priv/std_lib/string.ex similarity index 100% rename from lib/std_lib/string.ex rename to priv/std_lib/string.ex diff --git a/lib/std_lib/string/chars.ex b/priv/std_lib/string/chars.ex similarity index 100% rename from lib/std_lib/string/chars.ex rename to priv/std_lib/string/chars.ex diff --git a/lib/std_lib/tuple.ex b/priv/std_lib/tuple.ex similarity index 100% rename from lib/std_lib/tuple.ex rename to priv/std_lib/tuple.ex diff --git a/test/translator/pattern_matching_test.exs b/test/translator/pattern_matching_test.exs index 4688f142..b32b8ac3 100644 --- a/test/translator/pattern_matching_test.exs +++ b/test/translator/pattern_matching_test.exs @@ -5,13 +5,23 @@ defmodule ElixirScript.Translator.PatternMatching.Test do alias ElixirScript.Translator.PatternMatching alias ElixirScript.Translator.Map alias ESTree.Tools.Builder, as: JS - - @std_lib_state File.read!(File.cwd!() <> "/lib/elixir_script/translator/stdlib_state.bin") + alias ElixirScript.Translator.State setup do - {:ok, pid} = ElixirScript.Translator.State.start_link(%{env: __ENV__}, []) - ElixirScript.Translator.State.deserialize(pid, @std_lib_state) - scope = ElixirScript.Translator.LexicalScope.module_scope(ElixirScript.Temp, "temp.ex", __ENV__, pid, %{ format: :es, module_formatter: ElixirScript.ModuleSystems.ES }) + {:ok, pid} = State.start_link(%{env: __ENV__}, []) + + State.set_module_data(pid, [{ + ElixirScript.Kernel, + %{app: :elixir, name: ElixirScript.Kernel, ast: {}, functions: []} + }]) + + scope = ElixirScript.Translator.LexicalScope.module_scope( + ElixirScript.Temp, + "temp.ex", + __ENV__, + pid, + %{ format: :es, module_formatter: ElixirScript.ModuleSystems.ES } + ) {:ok, [scope: scope]} end From d79a6dd58d017ebfcb6754579e8ad3e424d1e923 Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Wed, 22 Feb 2017 21:47:26 -0600 Subject: [PATCH 422/860] Prevent standard lib from being loaded --- lib/elixir_script/passes/load_modules.ex | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/lib/elixir_script/passes/load_modules.ex b/lib/elixir_script/passes/load_modules.ex index fe1e9704..5e57fe76 100644 --- a/lib/elixir_script/passes/load_modules.ex +++ b/lib/elixir_script/passes/load_modules.ex @@ -1,11 +1,18 @@ defmodule ElixirScript.Passes.LoadModules do @moduledoc false def execute(compiler_data, _) do - - ex_files = Enum.map(compiler_data.data, fn + ex_files = compiler_data.data + |> Enum.filter(fn + {_, %{app: :elixir}} -> + false + %{app: :elixir} -> + false + _ -> true + end) + |> Enum.map(fn { _, %{path: path} } -> path %{path: path} -> path - end) + end) loaded_modules = case Enum.reverse(ex_files) do [] -> From 5a00840990a7fcda64f3f8f03832e805516f692f Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Thu, 23 Feb 2017 06:20:56 -0600 Subject: [PATCH 423/860] Update README.md and travis.yml --- .travis.yml | 6 +++--- README.md | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.travis.yml b/.travis.yml index 30b68c8e..94a48916 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,9 +1,9 @@ sudo: false language: elixir elixir: - - 1.3.0 + - 1.4.2 otp_release: - - 18.0 + - 19.0 env: - TRAVIS_NODE_VERSION="6" install: @@ -13,7 +13,7 @@ script: - mix local.hex --force - mix local.rebar --force - mix deps.get - - mix do clean, compile + - mix compile - mix test - npm test notifications: diff --git a/README.md b/README.md index 724895ef..dce8097d 100644 --- a/README.md +++ b/README.md @@ -33,7 +33,7 @@ Get dependencies Compile - mix do clean, compile + mix compile Test From 85b1a6bfe393d899a2650f13560113e3f45cb82c Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Thu, 23 Feb 2017 07:23:36 -0600 Subject: [PATCH 424/860] Remove unused code --- lib/elixir_script/compiler/cache.ex | 156 ------------------ lib/elixir_script/passes/add_std_lib.ex | 10 -- lib/elixir_script/passes/deps_paths.ex | 8 - .../passes/find_changed_files.ex | 20 --- lib/elixir_script/passes/find_deps.ex | 85 ---------- lib/elixir_script/passes/remove_unused.ex | 19 --- lib/elixir_script/passes/write_cache.ex | 23 --- test/compiler/cache_test.exs | 47 ------ 8 files changed, 368 deletions(-) delete mode 100644 lib/elixir_script/compiler/cache.ex delete mode 100644 lib/elixir_script/passes/add_std_lib.ex delete mode 100644 lib/elixir_script/passes/deps_paths.ex delete mode 100644 lib/elixir_script/passes/find_changed_files.ex delete mode 100644 lib/elixir_script/passes/find_deps.ex delete mode 100644 lib/elixir_script/passes/remove_unused.ex delete mode 100644 lib/elixir_script/passes/write_cache.ex delete mode 100644 test/compiler/cache_test.exs diff --git a/lib/elixir_script/compiler/cache.ex b/lib/elixir_script/compiler/cache.ex deleted file mode 100644 index e17fb95c..00000000 --- a/lib/elixir_script/compiler/cache.ex +++ /dev/null @@ -1,156 +0,0 @@ -defmodule ElixirScript.Compiler.Cache do - @moduledoc false - require Logger - - def delete(path) do - case get_tmp_file(path) do - nil -> - nil - tmp_file -> - if !File.exists?(tmp_file) do - File.rm(tmp_file) - end - end - end - - def get(path) do - case get_tmp_file(path) do - nil -> - nil - tmp_file -> - if File.exists?(tmp_file) do - case File.read(tmp_file) do - {:ok, data} -> - :erlang.binary_to_term(data) - {:error, reason} -> - Logger.info("Unable to read compiler cache") - Logger.info(reason) - nil - end - else - nil - end - end - end - - def write(path, stats) do - case get_tmp_file(path) do - nil -> - { :error, nil } - tmp_file -> - case File.write(tmp_file, :erlang.term_to_binary(stats)) do - :ok -> - :ok - {:error, reason} -> - Logger.info("Unable to write compiler cache") - Logger.info(reason) - { :error, reason } - end - end - end - - def get_changed_files(old_file_stats, new_file_stats) do - if(length(old_file_stats) != length(new_file_stats)) do - new_file_stats - else - old_file_stats = Enum.sort(old_file_stats, fn {file1, _}, {file2, _} -> file1 < file2 end) - new_file_stats = Enum.sort(new_file_stats, fn {file1, _}, {file2, _} -> file1 < file2 end) - zipped = Enum.zip(old_file_stats, new_file_stats) - - if(Enum.any?(zipped, fn({ {old_file, _} , {new_file, _ } }) -> old_file != new_file end)) do - new_file_stats - else - Enum.reduce(zipped, [], fn({ {_, old_stat} , {_, new_stat } = new }, state) -> - cond do - old_stat.mtime != new_stat.mtime -> - state ++ [new] - true -> - state - end - end) - end - end - end - - def build_file_stats(path) do - Enum.map(path, fn(file) -> - { file, File.stat!(file) } - end) - end - - def new(state) do - %{ - input_files: [], - state: state, - full_build?: true, - version: ElixirScript.version() - } - end - - defp get_tmp_file(path) do - case System.tmp_dir do - nil -> - nil - tmp -> - tmp_dir = Path.join([tmp, "elixirscript"]) - if !File.exists?(tmp_dir) do - case File.mkdir_p(tmp_dir) do - :ok -> - encoded_path = Path.absname(path) |> Path.dirname |> Base.encode64 - Path.join([tmp_dir, encoded_path]) - {:error, reason} -> - Logger.info("Unable to write compiler cache") - Logger.info(reason) - nil - end - else - encoded_path = Path.absname(path) |> Path.dirname |> Base.encode64 - Path.join([tmp_dir, encoded_path]) - end - end - end - - def get_compiler_cache(path, opts) do - refresh_cache = cond do - Map.get(opts, :full_build) -> - true - empty?(opts.output) -> - true - old_version?(opts) -> - true - get(path) == nil -> - true - true -> - false - end - - if refresh_cache do - delete(path) - new(ElixirScript.get_stdlib_state()) - else - %{ get(path) | full_build?: false } - end - end - - defp empty?(path) when is_binary(path) do - case File.ls(path) do - {:ok, []} -> - true - {:error, _} -> - true - _ -> - false - end - end - - defp empty?(_) do - true - end - - defp old_version?(opts) do - cache_version = Map.get(opts, :version, nil) - cache_version == ElixirScript.version() - end - - -end diff --git a/lib/elixir_script/passes/add_std_lib.ex b/lib/elixir_script/passes/add_std_lib.ex deleted file mode 100644 index cfad4105..00000000 --- a/lib/elixir_script/passes/add_std_lib.ex +++ /dev/null @@ -1,10 +0,0 @@ -defmodule ElixirScript.Passes.AddStdLib do - @moduledoc false - alias ElixirScript.Translator.State - - def execute(compiler_data, opts) do - State.deserialize(compiler_data.state, ElixirScript.get_stdlib_state, []) - compiler_data - end - -end diff --git a/lib/elixir_script/passes/deps_paths.ex b/lib/elixir_script/passes/deps_paths.ex deleted file mode 100644 index b0dac9b1..00000000 --- a/lib/elixir_script/passes/deps_paths.ex +++ /dev/null @@ -1,8 +0,0 @@ -defmodule ElixirScript.Passes.DepsPaths do - @moduledoc false - def execute(compiler_data, opts) do - data = [{opts[:app], List.wrap(compiler_data.path)}] - Map.put(compiler_data, :data, data) - end - -end diff --git a/lib/elixir_script/passes/find_changed_files.ex b/lib/elixir_script/passes/find_changed_files.ex deleted file mode 100644 index 9b841bb0..00000000 --- a/lib/elixir_script/passes/find_changed_files.ex +++ /dev/null @@ -1,20 +0,0 @@ -defmodule ElixirScript.Passes.FindChangedFiles do - @moduledoc false - alias ElixirScript.Compiler.Cache - alias ElixirScript.Translator.State - @version Mix.Project.config[:version] - - def execute(compiler_data, opts) do - compiler_cache = Cache.get_compiler_cache(compiler_data.path, opts) - new_file_stats = Enum.map(compiler_data.data, fn({_, data}) -> { data.path, data.stat } end) |> Enum.uniq - - changed_files = Cache.get_changed_files(compiler_cache.input_files, new_file_stats) - |> Enum.map(fn {file, _} -> file end) - - - State.deserialize(compiler_data.state, compiler_cache.state, compiler_data.loaded_modules) - - - Map.put(compiler_data, :changed_files, changed_files) - end -end diff --git a/lib/elixir_script/passes/find_deps.ex b/lib/elixir_script/passes/find_deps.ex deleted file mode 100644 index c3f379aa..00000000 --- a/lib/elixir_script/passes/find_deps.ex +++ /dev/null @@ -1,85 +0,0 @@ -defmodule ElixirScript.Passes.FindDeps do - @moduledoc false - alias ElixirScript.Translator.Utils - - def execute(compiler_data, _) do - data = Enum.map(compiler_data.data, &do_find_dependencies(&1)) - Map.put(compiler_data, :data, data) - end - - defp do_find_dependencies({ module, module_data }) do - {_, deps} = Macro.prewalk(module_data.ast, [], &collect_references(&1, &2)) - { module, Map.put(module_data, :deps, [ElixirScript.Kernel] ++ deps) } - end - - defp collect_references({:import, _, [{{:., _, [{:__aliases__, _, head_import_name}, :{}]}, _, tail_imports }]}, state) do - deps = Enum.map(tail_imports, fn({:__aliases__, context, name}) -> - full_module_name = { :__aliases__, context, head_import_name ++ name } - Utils.quoted_to_name(full_module_name) - end) - - state ++ deps - end - - defp collect_references({:import, _, [{:__aliases__, _, _} = module_name]} = ast, state) do - module_name = Utils.quoted_to_name(module_name) - { ast, state ++ [module_name] } - end - - defp collect_references({:import, _, [{:__aliases__, _, _} = module_name, _]} = ast, state) do - module_name = Utils.quoted_to_name(module_name) - {ast, state ++ [module_name] } - end - - defp collect_references({:alias, _, [{{:., _, [{:__aliases__, _, head_alias_name}, :{}]}, _, tail_aliases }]} = ast, state) do - deps = Enum.map(tail_aliases, fn({:__aliases__, context, name}) -> - full_module_name = { :__aliases__, context, head_alias_name ++ name } - Utils.quoted_to_name(full_module_name) - end) - - { ast, state ++ deps } - end - - defp collect_references({:alias, _, [{:__aliases__, _, _} = module_name] } = ast, state) do - module_name = Utils.quoted_to_name(module_name) - { ast, state ++ [module_name] } - end - - defp collect_references({:alias, _, [{:__aliases__, _, _} = module_name, _]} = ast, state) do - module_name = Utils.quoted_to_name(module_name) - {ast, state ++ [module_name] } - end - - defp collect_references({:require, _, [{{:., _, [{:__aliases__, _, head_alias_name}, :{}]}, _, tail_aliases }]} = ast, state) do - deps = Enum.map(tail_aliases, fn({:__aliases__, context, name}) -> - full_module_name = { :__aliases__, context, head_alias_name ++ name } - Utils.quoted_to_name(full_module_name) - end) - - { ast, state ++ deps } - end - - defp collect_references({:require, _, [{:__aliases__, _, _} = module_name] } = ast, state) do - module_name = Utils.quoted_to_name(module_name) - { ast, state ++ [module_name] } - end - - defp collect_references({:require, _, [{:__aliases__, _, _} = module_name, _]} = ast, state) do - module_name = Utils.quoted_to_name(module_name) - { ast, state ++ [module_name] } - end - - defp collect_references({:., _, [{:__aliases__, _, _} = module_name, _]} = ast, state) do - module_name = Utils.quoted_to_name(module_name) - { ast, state ++ [module_name] } - end - - defp collect_references({{:., _, [{:__aliases__, _, _} = module_name, _]}, _, _ } = ast, state) do - module_name = Utils.quoted_to_name(module_name) - { ast, state ++ [module_name] } - end - - defp collect_references(ast, state) do - { ast, state } - end -end diff --git a/lib/elixir_script/passes/remove_unused.ex b/lib/elixir_script/passes/remove_unused.ex deleted file mode 100644 index 5182adcc..00000000 --- a/lib/elixir_script/passes/remove_unused.ex +++ /dev/null @@ -1,19 +0,0 @@ -defmodule ElixirScript.Passes.RemoveUnused do - @moduledoc false - def execute(compiler_data, opts) do - data = Enum.filter(compiler_data.data, fn({module_name, _}) -> - module_found_in_deps(module_name, compiler_data.data, [opts[:app]]) == true - end) - - Map.put(compiler_data, :data, data) - end - - defp module_found_in_deps(module_name, module_filepath_map, apps_not_to_touch) do - Enum.any?(module_filepath_map, fn - ({_, %{deps: deps, app: app, type: :module}}) -> - Enum.member?(apps_not_to_touch, app) or Enum.member?(deps, module_name) - _ -> - true - end) - end -end diff --git a/lib/elixir_script/passes/write_cache.ex b/lib/elixir_script/passes/write_cache.ex deleted file mode 100644 index 5b023070..00000000 --- a/lib/elixir_script/passes/write_cache.ex +++ /dev/null @@ -1,23 +0,0 @@ -defmodule ElixirScript.Passes.WriteCache do - @moduledoc false - alias ElixirScript.Compiler.Cache - alias ElixirScript.Translator.State - - def execute(compiler_data, opts) do - compiler_cache = Cache.get_compiler_cache(compiler_data.path, opts) - - State.set_module_data(compiler_data.state, compiler_data.data) - new_state = State.serialize(compiler_data.state) - new_file_stats = Enum.filter(compiler_data.data, fn({ _, data }) -> Map.has_key?(data, :path) end) - |> Enum.map(fn({_, data}) -> { data.path, data.stat } end) - |> Enum.uniq - - compiler_cache = %{compiler_cache | input_files: new_file_stats, state: new_state } - - Cache.write(compiler_data.path, compiler_cache) - - compiler_data - end - - -end diff --git a/test/compiler/cache_test.exs b/test/compiler/cache_test.exs deleted file mode 100644 index d31b6f1c..00000000 --- a/test/compiler/cache_test.exs +++ /dev/null @@ -1,47 +0,0 @@ -defmodule ElixirScript.Compiler.Cache.Test do - use ExUnit.Case - alias ElixirScript.Compiler.Cache - - - test "no changes found when old and new are empty" do - old = [] - new = [] - assert Cache.get_changed_files(old, new) == [] - end - - test "all new changes found when old empty and new has files" do - old = [] - new = [{"file.ex", %{mtime: 1}}] - assert Cache.get_changed_files(old, new) == new - end - - test "all new changes found when old not emtpy and new is empty" do - old = [{"file.ex", %{mtime: 1}}] - new = [] - assert Cache.get_changed_files(old, new) == new - end - - test "all new changes found when old and new have same size but different file" do - old = [{"file.ex", %{mtime: 1}}] - new = [{"new_file.ex", %{mtime: 1}}] - assert Cache.get_changed_files(old, new) == new - end - - test "all new changes found when old and new have same file and different size" do - old = [{"file.ex", %{mtime: 1}}] - new = [{"file.ex", %{mtime: 2}}] - assert Cache.get_changed_files(old, new) == new - end - - test "no changes found when old and new have same file and size" do - old = [{"file.ex", %{mtime: 1}}] - new = [{"file.ex", %{mtime: 1}}] - assert Cache.get_changed_files(old, new) == [] - end - - test "all new changes found when old has less files than new" do - old = [{"file.ex", %{mtime: 1}}] - new = [{"file.ex", %{mtime: 1}}, {"new_file.ex", %{mtime: 1}}] - assert Cache.get_changed_files(old, new) == new - end -end From cf726c22b64a7a1a179b71ccf165eb067d4e7dc8 Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Thu, 23 Feb 2017 19:06:52 -0600 Subject: [PATCH 425/860] Add test to make sure Enum.member translates correctly --- test/translator/bug_test.exs | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/test/translator/bug_test.exs b/test/translator/bug_test.exs index 76736e5a..ca382f16 100644 --- a/test/translator/bug_test.exs +++ b/test/translator/bug_test.exs @@ -151,4 +151,16 @@ defmodule ElixirScript.Translator.Bug.Test do assert_translation(ex_ast, js_code) end + test "Enum.member? translates to Bootstrap.Enum.member__qmark__" do + ex_ast = quote do + Enum.member?([1, 2, 3], 1) + end + + js_code = """ + Bootstrap.Enum.member__qmark__(Object.freeze([1, 2, 3]), 1) + """ + + assert_translation(ex_ast, js_code) + end + end From ee8f4ec8b0ab448dd1efe59730ef18565440614b Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Thu, 23 Feb 2017 19:31:02 -0600 Subject: [PATCH 426/860] Fix error with piping JS macros --- priv/std_lib/js.ex | 48 +++++++----------------------------- test/translator/bug_test.exs | 14 ++++++++--- 2 files changed, 19 insertions(+), 43 deletions(-) diff --git a/priv/std_lib/js.ex b/priv/std_lib/js.ex index 9838a6ca..c1f44142 100644 --- a/priv/std_lib/js.ex +++ b/priv/std_lib/js.ex @@ -12,9 +12,7 @@ defmodule JS do ex: JS.new User, ["first_name", "last_name"] """ - defmacro new(module, params) do - end - + defmacro new(module, params) @doc """ Updates an existing JavaScript object. @@ -22,46 +20,22 @@ defmodule JS do ex: JS.update elem, %{"width" => 100} """ - defmacro update(object, map) do - end - - - @doc """ - Imports a JavaScript module. - - Elixir modules can use the normal `import`, `alias` and `require`, - but JavaScript modules work differently and have to be imported - using this. - - If `default` is set to true then it is treated as a default import. - Otherwise it is treated as a namespace import. - - ex: - JS.import A, "a" #translates to "import A from 'a'" - - JS.import A, "a", default: false #translates to "import * as A from 'a'" - """ - defmacro import(module, from, opts \\ [default: true]) do - end + defmacro update(object, map) @doc """ Returns the type of the given value """ - defmacro typeof(value) do - end + defmacro typeof(value) @doc """ Determines if value is an instance of type. """ - defmacro instanceof(value, type) do - end + defmacro instanceof(value, type) @doc """ Throws the term given """ - defmacro throw(term) do - end - + defmacro throw(term) @doc """ Returns a reference to the global JavaScript object. @@ -102,20 +76,17 @@ defmodule JS do @doc """ Yields the current generator function """ - defmacro yield() do - end + defmacro yield() @doc """ Yields the current generator function with the given term """ - defmacro yield(term) do - end + defmacro yield(term) @doc """ Yields control to the given generator """ - defmacro yield_to(gen) do - end + defmacro yield_to(gen) @doc """ Provides a convenient way to create a string-based map. @@ -124,6 +95,5 @@ defmodule JS do one would have to do `%{"a" => "b"}` which turns into `{a: "b"}` in JavaScript. With `Kernel.object`, you can create string keyed maps conveniently, `object(a: "b")` which turns into `{a: "b"}` """ - defmacro object(args) do - end + defmacro object(args) end diff --git a/test/translator/bug_test.exs b/test/translator/bug_test.exs index ca382f16..aa8b84f0 100644 --- a/test/translator/bug_test.exs +++ b/test/translator/bug_test.exs @@ -152,15 +152,21 @@ defmodule ElixirScript.Translator.Bug.Test do end test "Enum.member? translates to Bootstrap.Enum.member__qmark__" do + + end + + test "pipe translates correctly" do ex_ast = quote do - Enum.member?([1, 2, 3], 1) + :document.getElementById("main") |> JS.update(%{"innerHTML" => @html}) end js_code = """ - Bootstrap.Enum.member__qmark__(Object.freeze([1, 2, 3]), 1) + Object.assign(document.getElementById('main'), Object.freeze({ + innerHTML: html + })) """ - assert_translation(ex_ast, js_code) - end + assert_translation(ex_ast, js_code) + end end From 58a306791a23e0ad2756f1f58569e9a566bbd476 Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Fri, 24 Feb 2017 09:24:50 -0600 Subject: [PATCH 427/860] Add test to make sure Elixir.Enum is not in generated javascript code --- test/test_helper.exs | 18 ++++++++++++++++++ test/translator/bug_test.exs | 18 +++++++++++++----- test/translator/capture_test.exs | 4 ++-- test/translator/function_test.exs | 6 +++--- 4 files changed, 36 insertions(+), 10 deletions(-) diff --git a/test/test_helper.exs b/test/test_helper.exs index 16090d48..f23b9de7 100644 --- a/test/test_helper.exs +++ b/test/test_helper.exs @@ -66,4 +66,22 @@ defmodule ElixirScript.TestHelper do #{actual_js_code} """ end + + def refute_translation(ex_ast, js_code) do + refute_translation(ex_ast, js_code, :es) + end + + def refute_translation(ex_ast, js_code, format) do + converted_code = ex_ast_to_js(ex_ast, format) + + refute converted_code |> strip_spaces =~ strip_spaces(js_code), """ + **Code Does Not Match ** + + ***Expected*** + #{js_code} + + ***Actual*** + #{converted_code} + """ + end end diff --git a/test/translator/bug_test.exs b/test/translator/bug_test.exs index aa8b84f0..8ecd911d 100644 --- a/test/translator/bug_test.exs +++ b/test/translator/bug_test.exs @@ -67,11 +67,11 @@ defmodule ElixirScript.Translator.Bug.Test do test "replace !" do ex_ast = quote do - Elixir.Enum.fetch!(data, i) + Bootstrap.Enum.fetch!(data, i) end js_code = """ - Elixir.Enum.fetch__emark__(data, i) + Bootstrap.Enum.fetch__emark__(data, i) """ assert_translation(ex_ast, js_code) @@ -151,9 +151,17 @@ defmodule ElixirScript.Translator.Bug.Test do assert_translation(ex_ast, js_code) end - test "Enum.member? translates to Bootstrap.Enum.member__qmark__" do + test "Elixir.Enum.member__qmark__ does not show up in translation" do + ex_ast = quote do + Enum.member?([1, 2, 3], 1) + end - end + js_code = """ + Elixir.Enum.member__qmark__(Object.freeze([1, 2, 3]), 1) + """ + + refute_translation(ex_ast, js_code) + end test "pipe translates correctly" do ex_ast = quote do @@ -166,7 +174,7 @@ defmodule ElixirScript.Translator.Bug.Test do })) """ - assert_translation(ex_ast, js_code) + assert_translation(ex_ast, js_code) end end diff --git a/test/translator/capture_test.exs b/test/translator/capture_test.exs index ed0e6059..548caeb9 100644 --- a/test/translator/capture_test.exs +++ b/test/translator/capture_test.exs @@ -94,11 +94,11 @@ defmodule ElixirScript.Translator.Capture.Test do test "translate capture operator with anonymous functions as parameters" do ex_ast = quote do - Elixir.Enum.map(items, &process(&1)) + Bootstrap.Enum.map(items, &process(&1)) end js_code = """ - Elixir.Enum.map(items,Bootstrap.Core.Patterns.defmatch(Bootstrap.Core.Patterns.clause([Bootstrap.Core.Patterns.variable()],function(__1) { + Bootstrap.Enum.map(items,Bootstrap.Core.Patterns.defmatch(Bootstrap.Core.Patterns.clause([Bootstrap.Core.Patterns.variable()],function(__1) { return process(__1); }))) """ diff --git a/test/translator/function_test.exs b/test/translator/function_test.exs index 928b74de..55920e2f 100644 --- a/test/translator/function_test.exs +++ b/test/translator/function_test.exs @@ -206,11 +206,11 @@ defmodule ElixirScript.Translator.Function.Test do test "translate anonymous functions" do ex_ast = quote do - Elixir.Enum.map(list, fn(x) -> x * 2 end) + Bootstrap.Enum.map(list, fn(x) -> x * 2 end) end js_code = """ - Elixir.Enum.map(list,Bootstrap.Core.Patterns.defmatch(Bootstrap.Core.Patterns.clause([Bootstrap.Core.Patterns.variable()],function(x) { + Bootstrap.Enum.map(list,Bootstrap.Core.Patterns.defmatch(Bootstrap.Core.Patterns.clause([Bootstrap.Core.Patterns.variable()],function(x) { return x * 2; }))) """ @@ -840,6 +840,6 @@ defmodule ElixirScript.Translator.Function.Test do })); """ - assert_translation(ex_ast, js_code) + assert_translation(ex_ast, js_code) end end From 1d701179d6485e1ced809880d5d7a1ca1195c63c Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Fri, 24 Feb 2017 09:32:11 -0600 Subject: [PATCH 428/860] Update test to make sure Elixir.Enum.member__qmark__ does not show up in output --- test/translator/bug_test.exs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/translator/bug_test.exs b/test/translator/bug_test.exs index 8ecd911d..72f6fa9e 100644 --- a/test/translator/bug_test.exs +++ b/test/translator/bug_test.exs @@ -157,7 +157,7 @@ defmodule ElixirScript.Translator.Bug.Test do end js_code = """ - Elixir.Enum.member__qmark__(Object.freeze([1, 2, 3]), 1) + Elixir.Enum.member__qmark__ """ refute_translation(ex_ast, js_code) From a2de707288ab3af09a3b6361681d3212a0b86765 Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Fri, 24 Feb 2017 15:44:02 -0600 Subject: [PATCH 429/860] compile using Elixir compiler for string and quoted compilation --- lib/elixir_script.ex | 35 +++-- .../passes/load_modules_for_quoted.ex | 28 ++++ test/elixir_script_test.exs | 57 --------- test/prelude/js_test.exs | 18 ++- test/prelude/kernel_test.exs | 4 +- test/translator/access_test.exs | 10 +- test/translator/bitstring_test.exs | 43 +++++-- test/translator/bug_test.exs | 56 +++----- test/translator/capture_test.exs | 22 +++- test/translator/case_test.exs | 109 ++++++---------- test/translator/commonjs_test.exs | 5 +- test/translator/defmodule_test.exs | 45 ++++--- test/translator/for_test.exs | 43 +------ test/translator/function_test.exs | 120 ++++++------------ test/translator/kernel_test.exs | 26 ++-- test/translator/list_test.exs | 16 ++- test/translator/map_test.exs | 28 +++- test/translator/match_test.exs | 11 +- test/translator/quote_test.exs | 6 +- test/translator/struct_test.exs | 26 ++-- test/translator/try_test.exs | 39 +++--- test/translator/umd_test.exs | 5 +- test/translator/with_test.exs | 4 +- 23 files changed, 357 insertions(+), 399 deletions(-) create mode 100644 lib/elixir_script/passes/load_modules_for_quoted.ex delete mode 100644 test/elixir_script_test.exs diff --git a/lib/elixir_script.ex b/lib/elixir_script.ex index a37d7146..879b3ccc 100644 --- a/lib/elixir_script.ex +++ b/lib/elixir_script.ex @@ -41,8 +41,6 @@ defmodule ElixirScript do end # This is the serialized state of the ElixirScript.State module containing references to the standard library - @external_resource stdlib_state_path = Path.join([__DIR__, "elixir_script", "translator", "stdlib_state.bin"]) - @stdlib_state File.read(stdlib_state_path) @lib_path Application.get_env(:elixir_script, :lib_path) @version Mix.Project.config[:version] @@ -73,30 +71,45 @@ defmodule ElixirScript do |> get_modules_from_quoted |> Enum.map(fn(x) -> %{ast: x, app: :app} end) - data = get_quoted_std_lib() ++ data + {loaded_modules, std_lib_quoted} = get_quoted_std_lib() - result = %{data: data} + %{data: std_lib_quoted ++ data, loaded_modules: loaded_modules} |> ElixirScript.Passes.Init.execute(opts) + |> ElixirScript.Passes.LoadModulesForQuoted.execute(opts) |> ElixirScript.Passes.FindModules.execute(opts) |> ElixirScript.Passes.FindLoadOnly.execute(opts) |> ElixirScript.Passes.FindFunctions.execute(opts) |> ElixirScript.Passes.JavaScriptAST.execute(opts) |> ElixirScript.Passes.ConsolidateProtocols.execute(opts) - |> ElixirScript.Passes.CreateJSModules.execute(opts) + |> ElixirScript.Passes.CreateJSModules.execute(opts) |> ElixirScript.Passes.JavaScriptCode.execute(opts) |> ElixirScript.Passes.JavaScriptName.execute(opts) |> ElixirScript.Passes.HandleOutput.execute(opts) - - result end defp get_quoted_std_lib() do - Path.join([get_std_lib_path(), "**", "*.ex"]) + files = [get_std_lib_path(), "**", "*.ex"] + |> Path.join |> Path.wildcard + + loaded_modules = if Code.ensure_loaded?(ElixirScript.Kernel) do + [] + else + case files do + [] -> + [] + files -> + Kernel.ParallelCompiler.files(files) + end + end + + std_lib_quoted = files |> Enum.map(fn path -> File.read!(path) end) |> Enum.map(&Code.string_to_quoted!(&1)) |> Enum.flat_map(&get_modules_from_quoted(&1)) |> Enum.map(fn(x) -> %{ast: x, app: :elixir} end) + + {loaded_modules, std_lib_quoted} end defp get_modules_from_quoted(quoted) do @@ -138,7 +151,7 @@ defmodule ElixirScript do compile_path([path], opts) end - def compile_path(path, opts) when is_list(path) do + def compile_path(path, opts) when is_list(path) do built_opts = build_compiler_options(opts) app_name = cond do @@ -171,7 +184,7 @@ defmodule ElixirScript do |> ElixirScript.Passes.FindFunctions.execute(opts) |> ElixirScript.Passes.JavaScriptAST.execute(opts) |> ElixirScript.Passes.ConsolidateProtocols.execute(opts) - |> ElixirScript.Passes.CreateJSModules.execute(opts) + |> ElixirScript.Passes.CreateJSModules.execute(opts) |> ElixirScript.Passes.JavaScriptCode.execute(opts) |> ElixirScript.Passes.JavaScriptName.execute(opts) |> ElixirScript.Passes.HandleOutput.execute(opts) @@ -241,7 +254,7 @@ defmodule ElixirScript do end defp get_std_lib_path() do - Path.join([operating_path(), "std_lib"]) + Path.join([operating_path(), "std_lib"]) end end diff --git a/lib/elixir_script/passes/load_modules_for_quoted.ex b/lib/elixir_script/passes/load_modules_for_quoted.ex new file mode 100644 index 00000000..7c737dd1 --- /dev/null +++ b/lib/elixir_script/passes/load_modules_for_quoted.ex @@ -0,0 +1,28 @@ +defmodule ElixirScript.Passes.LoadModulesForQuoted do + @moduledoc false + def execute(compiler_data, _) do + quoted = compiler_data.data + |> Enum.filter(fn + {_, %{app: :elixir}} -> + false + %{app: :elixir} -> + false + _ -> true + end) + |> Enum.map(fn + {_, %{ast: ast}} -> ast + %{ast: ast} -> ast + end) + + loaded_modules = Map.get(compiler_data, :loaded_modules, []) + + loaded_modules_from_quoted = quoted + |> Enum.map(&Code.compile_quoted(&1)) + |> List.flatten + |> Enum.map(fn {mod, _} -> mod end) + + + Map.put(compiler_data, :loaded_modules, loaded_modules ++ loaded_modules_from_quoted) + end + +end \ No newline at end of file diff --git a/test/elixir_script_test.exs b/test/elixir_script_test.exs deleted file mode 100644 index fe02d67f..00000000 --- a/test/elixir_script_test.exs +++ /dev/null @@ -1,57 +0,0 @@ -defmodule ElixirScript.Test do - use ExUnit.Case - import ElixirScript.TestHelper - - test "turn javascript ast into javascript code strings" do - js_code = ElixirScript.compile(":atom") - assert_js_matches "Symbol.for('atom')", js_code - end - - - test "parse macros" do - - js_code = ElixirScript.compile(""" - defmodule Animals do - use ElixirScript.Using - - defp something_else() do - ElixirScript.Math.squared(1) - end - - end - """, %{ env: make_custom_env() }) - - assert_js_matches """ - const something_else = Bootstrap.Core.Patterns.defmatch(Bootstrap.Core.Patterns.clause([],function() { - return 1 * 1; - })); - const sandwich = Bootstrap.Core.Patterns.defmatch(Bootstrap.Core.Patterns.clause([],function() { - return null; - })); - """, js_code - end - - - test "set standard lib path" do - - js_code = ElixirScript.compile(""" - defmodule Animals do - use ElixirScript.Using - - defp something_else() do - ElixirScript.Math.squared(1) - end - - end - """, %{ env: make_custom_env(), core_path: "elixirscript"} ) - - assert_js_matches """ - const something_else = Bootstrap.Core.Patterns.defmatch(Bootstrap.Core.Patterns.clause([],function() { - return 1 * 1; - })); - const sandwich = Bootstrap.Core.Patterns.defmatch(Bootstrap.Core.Patterns.clause([],function() { - return null; - })); - """, js_code - end -end diff --git a/test/prelude/js_test.exs b/test/prelude/js_test.exs index 8673a8d8..3cff3835 100644 --- a/test/prelude/js_test.exs +++ b/test/prelude/js_test.exs @@ -4,7 +4,11 @@ defmodule ElixirScript.Lib.JS.Test do test "translate new" do ex_ast = quote do - JS.new A.B, [1, 2, 3] + require JS + + def execute() do + JS.new A.B, [1, 2, 3] + end end js_code = """ @@ -14,7 +18,11 @@ defmodule ElixirScript.Lib.JS.Test do assert_translation(ex_ast, js_code) ex_ast = quote do - JS.new A, [1, 2, 3] + require JS + + def execute() do + JS.new A, [1, 2, 3] + end end js_code = """ @@ -26,7 +34,11 @@ defmodule ElixirScript.Lib.JS.Test do test "translate update" do ex_ast = quote do - JS.update A, %{"b" => [1, 2, 3]} + require JS + + def execute() do + JS.update A, %{"b" => [1, 2, 3]} + end end js_code = """ diff --git a/test/prelude/kernel_test.exs b/test/prelude/kernel_test.exs index 2d90972b..c5f50ae9 100644 --- a/test/prelude/kernel_test.exs +++ b/test/prelude/kernel_test.exs @@ -31,11 +31,11 @@ defmodule ElixirScript.Lib.Elixir.Kernel.Test do test "translate sigil_r with options" do ex_ast = quote do - ~r/foo/ig + ~r/foo/i end js_code = """ - Elixir$ElixirScript$Regex.compile__emark__('foo', 'ig') + Elixir$ElixirScript$Regex.compile__emark__('foo', 'i') """ assert_translation(ex_ast, js_code) diff --git a/test/translator/access_test.exs b/test/translator/access_test.exs index fb7080e1..194c24d7 100644 --- a/test/translator/access_test.exs +++ b/test/translator/access_test.exs @@ -3,14 +3,12 @@ defmodule ElixirScript.Translator.Access.Test do import ElixirScript.TestHelper test "translate access" do - ex_ast = quote do: a[:b] + ex_ast = quote do + a = [] + a[:b] + end js_code = "a[Symbol.for('b')]" assert_translation(ex_ast, js_code) - - ex_ast = quote do: a["b"] - js_code = "a['b']" - - assert_translation(ex_ast, js_code) end end diff --git a/test/translator/bitstring_test.exs b/test/translator/bitstring_test.exs index 82f3e294..2faef0e2 100644 --- a/test/translator/bitstring_test.exs +++ b/test/translator/bitstring_test.exs @@ -15,26 +15,45 @@ defmodule ElixirScript.Translator.Bitstring.Test do ex_ast = quote do: <<1, "foo" :: utf8, "bar" :: utf32>> assert_translation(ex_ast, "new Bootstrap.Core.BitString(Bootstrap.Core.BitString.integer(1), Bootstrap.Core.BitString.utf8('foo'), Bootstrap.Core.BitString.utf32('bar'))") - ex_ast = quote do: <<102 :: integer-native, rest :: binary>> + ex_ast = quote do + rest = "oo" + <<102 :: integer-native, rest :: binary>> + end assert_translation(ex_ast, "new Bootstrap.Core.BitString(Bootstrap.Core.BitString.native(Bootstrap.Core.BitString.integer(102)), Bootstrap.Core.BitString.binary(rest))") - ex_ast = quote do: <<102 :: unsigned-big-integer, rest :: binary>> + ex_ast = quote do + rest = "oo" + <<102 :: unsigned-big-integer, rest :: binary>> + end assert_translation(ex_ast, "new Bootstrap.Core.BitString(Bootstrap.Core.BitString.integer(Bootstrap.Core.BitString.big(Bootstrap.Core.BitString.unsigned(102))), Bootstrap.Core.BitString.binary(rest))") - ex_ast = quote do: <<102, _rest :: size(16)>> - assert_translation(ex_ast, "new Bootstrap.Core.BitString(Bootstrap.Core.BitString.integer(102), Bootstrap.Core.BitString.size(_rest, 16))") + ex_ast = quote do + rest = 100 + <<102, rest :: size(16)>> + end - ex_ast = quote do: <<102, _rest :: size(16)-unit(4)>> - assert_translation(ex_ast, "new Bootstrap.Core.BitString(Bootstrap.Core.BitString.integer(102), Bootstrap.Core.BitString.unit(Bootstrap.Core.BitString.size(_rest, 16), 4))") + assert_translation(ex_ast, "new Bootstrap.Core.BitString(Bootstrap.Core.BitString.integer(102), Bootstrap.Core.BitString.size(rest, 16))") - ex_ast = quote do: <<102, _rest :: 16 * 4>> - assert_translation(ex_ast, "new Bootstrap.Core.BitString(Bootstrap.Core.BitString.integer(102), Bootstrap.Core.BitString.unit(Bootstrap.Core.BitString.size(_rest, 16), 4))") + ex_ast = quote do + rest = 100 + <<102, rest :: size(16)-unit(4)>> + end - ex_ast = quote do: <<102, _rest :: _ * 4>> - assert_translation(ex_ast, "new Bootstrap.Core.BitString(Bootstrap.Core.BitString.integer(102), Bootstrap.Core.BitString.unit(Bootstrap.Core.BitString.size(_rest, undefined), 4))") + assert_translation(ex_ast, "new Bootstrap.Core.BitString(Bootstrap.Core.BitString.integer(102), Bootstrap.Core.BitString.unit(Bootstrap.Core.BitString.size(rest, 16), 4))") - ex_ast = quote do: <<102, _rest :: 16>> - assert_translation(ex_ast, "new Bootstrap.Core.BitString(Bootstrap.Core.BitString.integer(102), Bootstrap.Core.BitString.size(_rest, 16))") + ex_ast = quote do + rest = 100 + <<102, rest :: 16 * 4>> + end + + assert_translation(ex_ast, "new Bootstrap.Core.BitString(Bootstrap.Core.BitString.integer(102), Bootstrap.Core.BitString.unit(Bootstrap.Core.BitString.size(rest, 16), 4))") + + ex_ast = quote do + rest = 100 + <<102, rest :: 16>> + end + + assert_translation(ex_ast, "new Bootstrap.Core.BitString(Bootstrap.Core.BitString.integer(102), Bootstrap.Core.BitString.size(rest, 16))") ex_ast = quote do: << 1, <<2>> >> assert_translation(ex_ast, "new Bootstrap.Core.BitString(Bootstrap.Core.BitString.integer(1), new Bootstrap.Core.BitString(Bootstrap.Core.BitString.integer(2)))") diff --git a/test/translator/bug_test.exs b/test/translator/bug_test.exs index 72f6fa9e..cc0fd7da 100644 --- a/test/translator/bug_test.exs +++ b/test/translator/bug_test.exs @@ -20,16 +20,18 @@ defmodule ElixirScript.Translator.Bug.Test do test "Translate react element" do ex_ast = quote do + def execute() do React.createElement( React.Text, - %{"style" => styles().welcome}, + %{"style" => ""}, "Welcome to React Native!" ) + end end js_code = """ React.createElement(React.Text,Object.freeze({ - style: Bootstrap.Core.Functions.call_property(styles,'welcome') + style: '' }),'Welcome to React Native!') """ @@ -37,37 +39,11 @@ defmodule ElixirScript.Translator.Bug.Test do end - test "correctly not create 2 imports" do - ex_ast = quote do - defmodule App.Todo do - JS.import JQuery, "jquery" - JQuery.(e.target) - end - end - - js_code = """ - JQuery(Bootstrap.Core.Functions.call_property(e,'target')); - """ - - assert_translation(ex_ast, js_code) - end - - test "correctly translate module names when used" do - ex_ast = quote do - @graphic_store App.Stores.GraphicStore.create_store() - end - - js_code = """ - const graphic_store = Bootstrap.Core.Functions.call_property(App.Stores.GraphicStore, 'create_store'); - - """ - - assert_translation(ex_ast, js_code) - end - test "replace !" do ex_ast = quote do - Bootstrap.Enum.fetch!(data, i) + def execute(data, i) do + Enum.fetch!(data, i) + end end js_code = """ @@ -79,7 +55,9 @@ defmodule ElixirScript.Translator.Bug.Test do test "chain calls correctly" do ex_ast = quote do - :this.getRawCanvas().getContext("2d") + def execute() do + :this.getRawCanvas().getContext("2d") + end end js_code = """ @@ -90,7 +68,9 @@ defmodule ElixirScript.Translator.Bug.Test do ex_ast = quote do - :this.getRawCanvas(one).get("fg").getContext("2d") + def execute(one) do + :this.getRawCanvas(one).get("fg").getContext("2d") + end end js_code = """ @@ -104,9 +84,9 @@ defmodule ElixirScript.Translator.Bug.Test do ex_ast = quote do def getDispatcher() do DeLorean.Flux.createDispatcher(%{ - startPainting: fn() -> this.dispatch("startPainting") end, - stopPainting: fn() -> this.dispatch("stopPainting") end, - addPoint: fn(data) -> this.dispatch("addPoint", data) end, + startPainting: fn() -> :this.dispatch("startPainting") end, + stopPainting: fn() -> :this.dispatch("stopPainting") end, + addPoint: fn(data) -> :this.dispatch("addPoint", data) end, getStores: fn() -> %{ graphic: GraphicStore } end }) end @@ -165,7 +145,9 @@ defmodule ElixirScript.Translator.Bug.Test do test "pipe translates correctly" do ex_ast = quote do - :document.getElementById("main") |> JS.update(%{"innerHTML" => @html}) + def execute() do + :document.getElementById("main") |> JS.update(%{"innerHTML" => @html}) + end end js_code = """ diff --git a/test/translator/capture_test.exs b/test/translator/capture_test.exs index 548caeb9..c282dc86 100644 --- a/test/translator/capture_test.exs +++ b/test/translator/capture_test.exs @@ -35,11 +35,11 @@ defmodule ElixirScript.Translator.Capture.Test do test "translate capture operator with function, and arity" do ex_ast = quote do - fun = &local_function/1 + fun = &is_atom/1 end js_code = """ - let [fun] = Bootstrap.Core.Patterns.match(Bootstrap.Core.Patterns.variable(),local_function); + let [fun] = Bootstrap.Core.Patterns.match(Bootstrap.Core.Patterns.variable(),is_atom); """ assert_translation(ex_ast, js_code) @@ -94,11 +94,16 @@ defmodule ElixirScript.Translator.Capture.Test do test "translate capture operator with anonymous functions as parameters" do ex_ast = quote do - Bootstrap.Enum.map(items, &process(&1)) + def process(a) do + end + + def execute() do + Enum.map([], &process(&1)) + end end js_code = """ - Bootstrap.Enum.map(items,Bootstrap.Core.Patterns.defmatch(Bootstrap.Core.Patterns.clause([Bootstrap.Core.Patterns.variable()],function(__1) { + Bootstrap.Enum.map(Object.freeze([]),Bootstrap.Core.Patterns.defmatch(Bootstrap.Core.Patterns.clause([Bootstrap.Core.Patterns.variable()],function(__1) { return process(__1); }))) """ @@ -107,11 +112,16 @@ defmodule ElixirScript.Translator.Capture.Test do ex_ast = quote do - elem.keypress(&process_event(&1)) + def process_event(a) do + end + + def execute() do + Elem.keypress(&process_event(&1)) + end end js_code = """ - elem.keypress(Bootstrap.Core.Patterns.defmatch(Bootstrap.Core.Patterns.clause([Bootstrap.Core.Patterns.variable()],function(__1) { + Elem.keypress(Bootstrap.Core.Patterns.defmatch(Bootstrap.Core.Patterns.clause([Bootstrap.Core.Patterns.variable()],function(__1) { return process_event(__1); }))) """ diff --git a/test/translator/case_test.exs b/test/translator/case_test.exs index 11161e6d..ccdc4161 100644 --- a/test/translator/case_test.exs +++ b/test/translator/case_test.exs @@ -5,15 +5,18 @@ defmodule ElixirScript.Translator.Case.Test do test "translate case" do ex_ast = quote do - case data do - :ok -> value - :error -> nil + def execute() do + data = :ok + case data do + :ok -> 1 + :error -> nil + end end end js_code = """ Bootstrap.Core.Patterns.defmatch(Bootstrap.Core.Patterns.clause([Symbol.for('ok')],function() { - return value; + return 1; }),Bootstrap.Core.Patterns.clause([Symbol.for('error')],function() { return null; })).call(this,data) @@ -22,6 +25,7 @@ defmodule ElixirScript.Translator.Case.Test do assert_translation(ex_ast, js_code) ex_ast = quote do + data = true case data do false -> value = 13 true -> true @@ -42,6 +46,7 @@ defmodule ElixirScript.Translator.Case.Test do ex_ast = quote do + data = :ok case data do false -> value = 13 _ -> true @@ -62,6 +67,7 @@ defmodule ElixirScript.Translator.Case.Test do test "translate case with guard" do ex_ast = quote do + data = :ok case data do number when number in [1,2,3,4] -> value = 13 @@ -86,6 +92,7 @@ defmodule ElixirScript.Translator.Case.Test do test "translate case with multiple guards" do ex_ast = quote do + data = :ok case data do number when number in [1,2,3,4] when number in [4, 3, 2, 1] -> value = 13 @@ -106,16 +113,19 @@ defmodule ElixirScript.Translator.Case.Test do """ assert_translation(ex_ast, js_code) - end + end test "translate case with multiple statements in body" do ex_ast = quote do - case data do - :ok -> - :console.info("info") - Todo.add(data) - :error -> - nil + def execute() do + data = :ok + case data do + :ok -> + :console.info("info") + Todo.add(data) + :error -> + nil + end end end @@ -133,11 +143,14 @@ defmodule ElixirScript.Translator.Case.Test do test "translate case with destructing" do ex_ast = quote do - case data do - { one, two } -> - :console.info(one) - :error -> - nil + def execute() do + data = :ok + case data do + { one, two } -> + :console.info(one) + :error -> + nil + end end end @@ -156,11 +169,14 @@ defmodule ElixirScript.Translator.Case.Test do test "translate case with nested destructing" do ex_ast = quote do - case data do - { {one, two} , three } -> - :console.info(one) - :error -> - nil + def execute() do + data = :error + case data do + { {one, two} , three } -> + :console.info(one) + :error -> + nil + end end end @@ -179,6 +195,7 @@ defmodule ElixirScript.Translator.Case.Test do assert_translation(ex_ast, js_code) ex_ast = quote do + data = :error case data do { one, {two, three} } -> :console.info(one) @@ -200,55 +217,5 @@ defmodule ElixirScript.Translator.Case.Test do """ assert_translation(ex_ast, js_code) - - - ex_ast = quote do - case data do - %AStruct{key: %BStruct{ key2: value }} -> - :console.info(value) - :error -> - nil - end - end - - js_code = """ - Bootstrap.Core.Patterns.defmatch(Bootstrap.Core.Patterns.clause([Bootstrap.Core.Patterns.type(AStruct, { - [Symbol.for('key')]: Bootstrap.Core.Patterns.type(BStruct, { - [Symbol.for('key2')]: Bootstrap.Core.Patterns.variable() - }) - })], function(value) { - return console.info(value); - }), Bootstrap.Core.Patterns.clause([Symbol.for('error')], function() { - return null; - })).call(this, data) - """ - - assert_translation(ex_ast, js_code) - - - ex_ast = quote do - case data do - %AStruct{key: %BStruct{ key2: value, key3: %CStruct{ key4: value2 } }} -> - :console.info(value) - :error -> - nil - end - end - - js_code = """ - Bootstrap.Core.Patterns.defmatch(Bootstrap.Core.Patterns.clause([Bootstrap.Core.Patterns.type(AStruct, { - [Symbol.for('key')]: Bootstrap.Core.Patterns.type(BStruct, { - [Symbol.for('key2')]: Bootstrap.Core.Patterns.variable(), [Symbol.for('key3')]: Bootstrap.Core.Patterns.type(CStruct, { - [Symbol.for('key4')]: Bootstrap.Core.Patterns.variable() - }) - }) - })], function(value, value2) { - return console.info(value); - }), Bootstrap.Core.Patterns.clause([Symbol.for('error')], function() { - return null; - })).call(this, data) - """ - - assert_translation(ex_ast, js_code) end end diff --git a/test/translator/commonjs_test.exs b/test/translator/commonjs_test.exs index 89842df9..187a9cdd 100644 --- a/test/translator/commonjs_test.exs +++ b/test/translator/commonjs_test.exs @@ -5,14 +5,11 @@ defmodule ElixirScript.Translator.CommonJS.Test do test "translate module to commonjs" do ex_ast = quote do defmodule Elephant do - @ul JQuery.("#todo-list") + @ul "#todo-list" def something() do @ul end - - defgenp something_else() do - end end end diff --git a/test/translator/defmodule_test.exs b/test/translator/defmodule_test.exs index f4dd0d3e..4802cb12 100644 --- a/test/translator/defmodule_test.exs +++ b/test/translator/defmodule_test.exs @@ -18,25 +18,32 @@ defmodule ElixirScript.Translator.Defmodule.Test do test "translate defmodules" do ex_ast = quote do defmodule Elephant do - @ul JQuery.("#todo-list") + require JS + @ul "#todo-list" def something() do @ul end - defgenp something_else() do + JS.defgenp something_else() do end end end js_code = """ - const something_else = Bootstrap.Core.Patterns.defmatchgen(Bootstrap.Core.Patterns.clause([],function*() { - return null; - })); - const something = Bootstrap.Core.Patterns.defmatch(Bootstrap.Core.Patterns.clause([],function() { - return ul; - })); - const ul = JQuery('#todo-list'); + const something = Bootstrap.Core.Patterns.defmatchgen(Bootstrap.Core.Patterns.clause([], function*() { + return ul; + })); + + const ul = '#todo-list'; + + const something_else = Bootstrap.Core.Patterns.defmatchgen(Bootstrap.Core.Patterns.clause([], function*() { + return null; + })); + + const __exports = { + something + }; """ assert_translation(ex_ast, js_code) @@ -47,11 +54,11 @@ defmodule ElixirScript.Translator.Defmodule.Test do defmodule Animals do defmodule Elephant do - defstruct trunk: true + defstruct [trunk: true] end def something() do - %Elephant{} + %Animals.Elephant{} end defp something_else() do @@ -84,7 +91,7 @@ defmodule ElixirScript.Translator.Defmodule.Test do def something() do - %Elephant{} + %Animals.Elephant{} end defp something_else() do @@ -105,17 +112,25 @@ defmodule ElixirScript.Translator.Defmodule.Test do test "Pull out module references and make them into imports if modules listed" do ex_ast = quote do - defmodule Animals do - Lions.Tigers.oh_my() + defmodule Lions.Tigers.Bears do + def oh_my() do + end end defmodule Lions.Tigers do + def oh_my() do + end + Lions.Tigers.Bears.oh_my() end + + defmodule Animals do + Lions.Tigers.oh_my() + end end js_code = """ - Bootstrap.Core.Functions.call_property(Lions.Tigers.Bears,'oh_my'); + Bootstrap.Core.Functions.call_property(Elixir$Lions$Tigers$Bears, 'oh_my'); """ assert_translation(ex_ast, js_code) diff --git a/test/translator/for_test.exs b/test/translator/for_test.exs index 4cd22260..afecd45b 100644 --- a/test/translator/for_test.exs +++ b/test/translator/for_test.exs @@ -24,10 +24,10 @@ defmodule ElixirScript.Translator.For.Test do Object.freeze([1, 2, 3, 4]) ) ], - Elixir$ElixirScript$Collectable, + Elixir$ElixirScript$Collectable, Object.freeze([]) ) - """ + """ assert_translation(ex_ast, js_code) end @@ -54,36 +54,6 @@ defmodule ElixirScript.Translator.For.Test do Object.freeze([1, 2, 3, 4]) ) ], - Elixir$ElixirScript$Collectable, - Object.freeze([]) - ) - """ - - assert_translation(ex_ast, js_code) - end - - test "translate for with string" do - ex_ast = quote do - for n <- "Opera", do: n - end - - js_code = """ - Bootstrap.Core.SpecialForms._for( - Bootstrap.Core.Patterns.clause( - [Bootstrap.Core.Patterns.variable()], - function(n) { - return n; - }, - function() { - return true; - } - ), - [ - Bootstrap.Core.Patterns.list_generator( - Bootstrap.Core.Patterns.variable(), - 'Opera' - ) - ], Elixir$ElixirScript$Collectable, Object.freeze([]) ) @@ -117,8 +87,8 @@ defmodule ElixirScript.Translator.For.Test do Bootstrap.Core.Patterns.variable(), Object.freeze([2, 3]) ) - ], - Elixir$ElixirScript$Collectable, + ], + Elixir$ElixirScript$Collectable, Object.freeze([]) ) """ @@ -187,7 +157,7 @@ defmodule ElixirScript.Translator.For.Test do Object.freeze([1, 2, 3, 4, 5, 6]) ) ], - Elixir$ElixirScript$Collectable, + Elixir$ElixirScript$Collectable, Object.freeze([]) ) """ @@ -210,7 +180,7 @@ defmodule ElixirScript.Translator.For.Test do return Elixir$ElixirScript$String.upcase(name); }, function() { return true; - }), + }), [ Bootstrap.Core.Patterns.list_generator(Bootstrap.Core.Patterns.type(Bootstrap.Core.Tuple, { values: [Symbol.for('user'), Bootstrap.Core.Patterns.variable()] @@ -225,6 +195,7 @@ defmodule ElixirScript.Translator.For.Test do test "translate for with bitstring" do ex_ast = quote do + pixels = <<1, 2, 3, 4, 5, 6>> for <> do {r, g, b} end diff --git a/test/translator/function_test.exs b/test/translator/function_test.exs index 55920e2f..ef8331e1 100644 --- a/test/translator/function_test.exs +++ b/test/translator/function_test.exs @@ -2,36 +2,6 @@ defmodule ElixirScript.Translator.Function.Test do use ExUnit.Case import ElixirScript.TestHelper - test "call fun" do - ex_ast = quote do - fun.(:atom) - end - - js_code = """ - fun(Symbol.for('atom')) - """ - - assert_translation(ex_ast, js_code) - - end - - - test "translate function with a macro" do - ex_ast = quote do - def test1() do - ElixirScript.Math.squared(1) - end - end - - js_code = """ - const test1 = Bootstrap.Core.Patterns.defmatch(Bootstrap.Core.Patterns.clause([],function() { - return 1 * 1; - })); - """ - - assert_translation(ex_ast, js_code) - end - test "translate functions" do ex_ast = quote do def test1() do @@ -155,50 +125,45 @@ defmodule ElixirScript.Translator.Function.Test do test "translate function calls" do ex_ast = quote do - test1() - end - - js_code = "test1()" + defmodule Taco do + def test1() do + end + end - assert_translation(ex_ast, js_code) - ex_ast = quote do - test?() + Taco.test1() end - js_code = "test__qmark__()" + js_code = "Bootstrap.Core.Functions.call_property(Elixir$Taco, 'test1')" assert_translation(ex_ast, js_code) ex_ast = quote do - test1(3, 2) - end - - js_code = "test1(3,2)" - - assert_translation(ex_ast, js_code) + defmodule Taco do + def test1(a, b) do + end + end - ex_ast = quote do - Taco.test1() + Taco.test1(3, 2) end - js_code = "Bootstrap.Core.Functions.call_property(Taco, 'test1')" + js_code = "Elixir$Taco.test1(3,2)" assert_translation(ex_ast, js_code) ex_ast = quote do - Taco.test1(3, 2) - end - - js_code = "Taco.test1(3,2)" + defmodule Taco do + def test1(a, b) do + end - assert_translation(ex_ast, js_code) + def test2(a) do + end + end - ex_ast = quote do Taco.test1(Taco.test2(1), 2) end - js_code = "Taco.test1(Taco.test2(1),2)" + js_code = "Elixir$Taco.test1(Elixir$Taco.test2(1),2)" assert_translation(ex_ast, js_code) end @@ -206,7 +171,8 @@ defmodule ElixirScript.Translator.Function.Test do test "translate anonymous functions" do ex_ast = quote do - Bootstrap.Enum.map(list, fn(x) -> x * 2 end) + list = [] + Enum.map(list, fn(x) -> x * 2 end) end js_code = """ @@ -306,25 +272,6 @@ defmodule ElixirScript.Translator.Function.Test do end - test "test |> operator" do - ex_ast = quote do - 1 |> Taco.test - end - - js_code = "Taco.test(1)" - - assert_translation(ex_ast, js_code) - - ex_ast = quote do - 1 |> Taco.test |> Home.hello("hi") - end - - js_code = "Home.hello(Taco.test(1), 'hi')" - - assert_translation(ex_ast, js_code) - end - - test "test Elixir.Kernel function" do ex_ast = quote do is_atom(:atom) @@ -494,13 +441,17 @@ defmodule ElixirScript.Translator.Function.Test do test "pattern match function with struct" do ex_ast = quote do + defmodule AStruct do + defstruct [] + end + def something(%AStruct{}) do end end js_code = """ - const something = Bootstrap.Core.Patterns.defmatch(Bootstrap.Core.Patterns.clause([Bootstrap.Core.Patterns.type(AStruct, {})], function() { + const something = Bootstrap.Core.Patterns.defmatch(Bootstrap.Core.Patterns.clause([Bootstrap.Core.Patterns.type(Elixir$AStruct.Elixir$AStruct, {})], function() { return null; })); """ @@ -510,12 +461,17 @@ defmodule ElixirScript.Translator.Function.Test do test "pattern match function with struct reference" do ex_ast = quote do + defmodule AStruct do + defstruct [] + end + def something(%AStruct{} = a) do end + end js_code = """ - const something = Bootstrap.Core.Patterns.defmatch(Bootstrap.Core.Patterns.clause([Bootstrap.Core.Patterns.capture(Bootstrap.Core.Patterns.type(AStruct, {}))], function(a) { + const something = Bootstrap.Core.Patterns.defmatch(Bootstrap.Core.Patterns.clause([Bootstrap.Core.Patterns.capture(Bootstrap.Core.Patterns.type(Elixir$AStruct.Elixir$AStruct, {}))], function(a) { return null; })); """ @@ -541,13 +497,17 @@ defmodule ElixirScript.Translator.Function.Test do test "pattern match function with struct decontructed" do ex_ast = quote do + defmodule AStruct do + defstruct [:key, :key1] + end + def something(%AStruct{key: value, key1: 2}) do end end js_code = """ - const something = Bootstrap.Core.Patterns.defmatch(Bootstrap.Core.Patterns.clause([Bootstrap.Core.Patterns.type(AStruct, { + const something = Bootstrap.Core.Patterns.defmatch(Bootstrap.Core.Patterns.clause([Bootstrap.Core.Patterns.type(Elixir$AStruct.Elixir$AStruct, { [Symbol.for('key')]: Bootstrap.Core.Patterns.variable(), [Symbol.for('key1')]: 2 })], function(value) { return null; @@ -557,13 +517,17 @@ defmodule ElixirScript.Translator.Function.Test do assert_translation(ex_ast, js_code) ex_ast = quote do + defmodule AStruct do + defstruct [:key, :key1] + end + def something(%AStruct{key: value, key1: 2}) when is_number(value) do end end js_code = """ - const something = Bootstrap.Core.Patterns.defmatch(Bootstrap.Core.Patterns.clause([Bootstrap.Core.Patterns.type(AStruct, { + const something = Bootstrap.Core.Patterns.defmatch(Bootstrap.Core.Patterns.clause([Bootstrap.Core.Patterns.type(Elixir$AStruct.Elixir$AStruct, { [Symbol.for('key')]: Bootstrap.Core.Patterns.variable(), [Symbol.for('key1')]: 2 })], function(value) { return null; diff --git a/test/translator/kernel_test.exs b/test/translator/kernel_test.exs index 533cf51b..c872b4e8 100644 --- a/test/translator/kernel_test.exs +++ b/test/translator/kernel_test.exs @@ -4,7 +4,10 @@ defmodule ElixirScript.Translator.Kernel.Test do test "raise with bitstring" do ex_ast = quote do - raise ArgumentError, "cannot convert list to string. The list must contain only integers, strings or nested such lists; got: #{inspect list}" + def execute() do + list = [] + raise ArgumentError, "cannot convert list to string. The list must contain only integers, strings or nested such lists; got: #{inspect list}" + end end js_code = """ @@ -18,7 +21,9 @@ defmodule ElixirScript.Translator.Kernel.Test do test "raise with string" do ex_ast = quote do - raise ArgumentError, "cannot convert list to string. The list must contain only integers, strings or nested such lists; got" + def execute() do + raise ArgumentError, "cannot convert list to string. The list must contain only integers, strings or nested such lists; got" + end end js_code = """ @@ -43,26 +48,13 @@ defmodule ElixirScript.Translator.Kernel.Test do end - test "apply/2" do - ex_ast = quote do - apply(fun, [1, 2, 3]) - end - - js_code = """ - Elixir$ElixirScript$Kernel.apply(fun, Object.freeze([1, 2, 3])) - """ - - assert_translation(ex_ast, js_code) - - end - test "apply/3" do ex_ast = quote do - apply(Enum, :reverse, [1, 2, 3]) + apply(Enum, :reverse, [[1, 2, 3]]) end js_code = """ - Elixir$ElixirScript$Kernel.apply(Enum,Symbol.for('reverse'),Object.freeze([1, 2, 3])) + Elixir$ElixirScript$Kernel.apply(Enum,Symbol.for('reverse'),Object.freeze([Object.freeze([1, 2, 3])])) """ assert_translation(ex_ast, js_code) diff --git a/test/translator/list_test.exs b/test/translator/list_test.exs index cbdbc92b..c4af1fc4 100644 --- a/test/translator/list_test.exs +++ b/test/translator/list_test.exs @@ -30,14 +30,21 @@ defmodule ElixirScript.Translator.List.Test do assert_translation(ex_ast, js_code) - ex_ast = quote do: this.list ++ [4, 5, 6] - js_code = "Bootstrap.Core.Functions.call_property(this,'list').concat(Object.freeze([4, 5, 6]))" + ex_ast = quote do + list = [] + list ++ [4, 5, 6] + end + js_code = "list.concat(Object.freeze([4, 5, 6]))" assert_translation(ex_ast, js_code) end test "prepend element" do - ex_ast = quote do: [x | list] + ex_ast = quote do + x = 1 + list = [] + [x | list] + end js_code = "Object.freeze([x]).concat(list)" @@ -46,6 +53,9 @@ defmodule ElixirScript.Translator.List.Test do test "prepend element in function" do ex_ast = quote do + x = 1 + list = [] + fn (_) -> [x|list] end end diff --git a/test/translator/map_test.exs b/test/translator/map_test.exs index a71d62d3..75a237d5 100644 --- a/test/translator/map_test.exs +++ b/test/translator/map_test.exs @@ -43,7 +43,11 @@ defmodule ElixirScript.Translator.Map.Test do test "translate map update" do - ex_ast = quote do: %{ map | value: 1 } + ex_ast = quote do + map = %{value: 2} + %{ map | value: 1 } + end + js_code = """ Bootstrap.Core.SpecialForms.map_update(map,Object.freeze({ [Symbol.for('value')]: 1 @@ -54,18 +58,28 @@ defmodule ElixirScript.Translator.Map.Test do end test "translate variable key" do - ex_ast = quote do: %{key => value} + ex_ast = quote do + key = 1 + value = 2 + %{key => value} + end + js_code = "Object.freeze({ [key]: value })" assert_translation(ex_ast, js_code) end test "translate bound map key" do - ex_ast = quote do: %{^key => value} = %{key => value} + ex_ast = quote do + key = 1 + value = 2 + %{^key => value} = %{key => value} + end js_code = """ - let [value] = Bootstrap.Core.Patterns.match( - { [key]: Bootstrap.Core.Patterns.variable() }, - Object.freeze({ [key]: value }) - ); + let [value1] = Bootstrap.Core.Patterns.match({ + [key]: Bootstrap.Core.Patterns.variable() + }, Object.freeze({ + [key]: value + })); """ assert_translation(ex_ast, js_code) end diff --git a/test/translator/match_test.exs b/test/translator/match_test.exs index 898818b7..520dada0 100644 --- a/test/translator/match_test.exs +++ b/test/translator/match_test.exs @@ -38,7 +38,10 @@ defmodule ElixirScript.Translator.Match.Test do assert_translation(ex_ast, js_code) - ex_ast = quote do: {^a, _, c} = {1, 2, 3} + ex_ast = quote do + a = 1 + {^a, _, c} = {1, 2, 3} + end js_code = """ let [, undefined, c] = Bootstrap.Core.Patterns.match(Bootstrap.Core.Patterns.type(Bootstrap.Core.Tuple, { values: [Bootstrap.Core.Patterns.bound(a), Bootstrap.Core.Patterns.wildcard(), Bootstrap.Core.Patterns.variable()] @@ -50,7 +53,11 @@ defmodule ElixirScript.Translator.Match.Test do end test "translate bound match" do - ex_ast = quote do: ^a = 1 + ex_ast = quote do + a = 1 + ^a = 1 + end + js_code = """ let [] = Bootstrap.Core.Patterns.match(Bootstrap.Core.Patterns.bound(a),1); """ diff --git a/test/translator/quote_test.exs b/test/translator/quote_test.exs index aef14a89..2728ea69 100644 --- a/test/translator/quote_test.exs +++ b/test/translator/quote_test.exs @@ -78,6 +78,7 @@ defmodule ElixirScript.Translator.Quote.Test do test "quote function call with unquote" do ex_ast = quote do + x = 1 quote do: test(unquote(x)) end @@ -94,11 +95,11 @@ defmodule ElixirScript.Translator.Quote.Test do test "quote function call with unquote_slicing" do ex_ast = quote do - quote do: sum(1, unquote_splicing(values), 5) + quote do: sum(1, unquote_splicing([1, 2, 3]), 5) end js_code = """ - new Bootstrap.Core.Tuple(Symbol.for('sum'),Object.freeze([]),Bootstrap.Enum.concat(Object.freeze([1]),values,Object.freeze([5]))) + new Bootstrap.Core.Tuple(Symbol.for('sum'), Object.freeze([]), Bootstrap.Enum.concat(Object.freeze([1]), Object.freeze([1, 2, 3]), Object.freeze([5]))) """ assert_translation(ex_ast, js_code) @@ -106,6 +107,7 @@ defmodule ElixirScript.Translator.Quote.Test do test "bind_quoted" do ex_ast = quote do + x = 1 quote bind_quoted: [x: x] do x * x end diff --git a/test/translator/struct_test.exs b/test/translator/struct_test.exs index 0f50c424..3e1745b1 100644 --- a/test/translator/struct_test.exs +++ b/test/translator/struct_test.exs @@ -43,7 +43,7 @@ defmodule ElixirScript.Translator.Struct.Test do test "translate struct creation" do ex_ast = quote do defmodule User do - defstruct :name, :age + defstruct [:name, :age] end user = %User{} @@ -61,7 +61,7 @@ defmodule ElixirScript.Translator.Struct.Test do ex_ast = quote do defmodule User do - defstruct :name, :age + defstruct [:name, :age] end user = %User{name: "John"} @@ -81,12 +81,13 @@ defmodule ElixirScript.Translator.Struct.Test do test "translate struct update" do ex_ast = quote do - user = %{ map | key: value } + map = %{key: nil} + user = %{ map | key: 1 } end js_code = """ let [user] = Bootstrap.Core.Patterns.match(Bootstrap.Core.Patterns.variable(),Bootstrap.Core.SpecialForms.map_update(map,Object.freeze({ - [Symbol.for('key')]: value + [Symbol.for('key')]: 1 }))); """ @@ -94,12 +95,13 @@ defmodule ElixirScript.Translator.Struct.Test do ex_ast = quote do - user = %{ map | key: value, key1: value1 } + map = %{key: nil, key1: nil} + user = %{ map | key: 1, key1: 11 } end js_code = """ let [user] = Bootstrap.Core.Patterns.match(Bootstrap.Core.Patterns.variable(),Bootstrap.Core.SpecialForms.map_update(map,Object.freeze({ - [Symbol.for('key')]: value, [Symbol.for('key1')]: value1 + [Symbol.for('key')]: 1, [Symbol.for('key1')]: 11 }))); """ @@ -145,9 +147,12 @@ defmodule ElixirScript.Translator.Struct.Test do ex_ast = quote do defmodule MyAppError do defexception [:message] - end - raise MyAppError, message: "did not get what was expected" + def do_it() do + raise MyAppError, message: "did not get what was expected" + end + + end end js_code = """ @@ -160,7 +165,10 @@ defmodule ElixirScript.Translator.Struct.Test do ex_ast = quote do - raise "did not get what was expected" + def do_it() do + raise "did not get what was expected" + end + end js_code = """ diff --git a/test/translator/try_test.exs b/test/translator/try_test.exs index cd90a0d0..72c24681 100644 --- a/test/translator/try_test.exs +++ b/test/translator/try_test.exs @@ -5,7 +5,7 @@ defmodule ElixirScript.Translator.Try.Test do test "translate with a rescue with one match" do ex_ast = quote do try do - do_something_that_may_fail(some_arg) + 1 rescue ArgumentError -> IO.puts "Invalid argument given" @@ -14,7 +14,7 @@ defmodule ElixirScript.Translator.Try.Test do js_code = """ Bootstrap.Core.SpecialForms._try(function() { - return do_something_that_may_fail(some_arg); + return 1; }, Bootstrap.Core.Patterns.defmatch(Bootstrap.Core.Patterns.clause([Bootstrap.Core.Patterns.type(ArgumentError, {})], function() { return IO.puts('Invalid argument given'); })), null, null, null) @@ -25,8 +25,9 @@ defmodule ElixirScript.Translator.Try.Test do test "translate with a rescue with a list match" do ex_ast = quote do + try do - do_something_that_may_fail(some_arg) + 1 rescue [ArgumentError] -> IO.puts "Invalid argument given" @@ -35,7 +36,7 @@ defmodule ElixirScript.Translator.Try.Test do js_code = """ Bootstrap.Core.SpecialForms._try(function() { - return do_something_that_may_fail(some_arg); + return 1; }, Bootstrap.Core.Patterns.defmatch(Bootstrap.Core.Patterns.clause([Bootstrap.Core.Patterns.type(ArgumentError, {})], function() { return IO.puts('Invalid argument given'); })), null, null, null) @@ -46,8 +47,9 @@ defmodule ElixirScript.Translator.Try.Test do test "translate with a rescue with an in guard" do ex_ast = quote do + try do - do_something_that_may_fail(some_arg) + 1 rescue x in [ArgumentError] -> IO.puts "Invalid argument given" @@ -56,7 +58,7 @@ defmodule ElixirScript.Translator.Try.Test do js_code = """ Bootstrap.Core.SpecialForms._try(function() { - return do_something_that_may_fail(some_arg); + return 1; },Bootstrap.Core.Patterns.defmatch(Bootstrap.Core.Patterns.clause([Bootstrap.Core.Patterns.variable()],function(x) { return IO.puts('Invalid argument given'); },function(x) { @@ -69,8 +71,9 @@ defmodule ElixirScript.Translator.Try.Test do test "translate with a rescue with an identifier" do ex_ast = quote do + try do - do_something_that_may_fail(some_arg) + 1 rescue x -> IO.puts "Invalid argument given" @@ -79,7 +82,7 @@ defmodule ElixirScript.Translator.Try.Test do js_code = """ Bootstrap.Core.SpecialForms._try(function() { - return do_something_that_may_fail(some_arg); + return 1; },Bootstrap.Core.Patterns.defmatch(Bootstrap.Core.Patterns.clause([Bootstrap.Core.Patterns.variable()],function(x) { return IO.puts('Invalid argument given'); })),null,null,null) @@ -91,8 +94,9 @@ defmodule ElixirScript.Translator.Try.Test do test "translate with a rescue with multiple patterns" do ex_ast = quote do + try do - do_something_that_may_fail(some_arg) + 1 rescue [ArgumentError] -> IO.puts "ArgumentError" @@ -103,7 +107,7 @@ defmodule ElixirScript.Translator.Try.Test do js_code = """ Bootstrap.Core.SpecialForms._try(function() { - return do_something_that_may_fail(some_arg); + return 1; }, Bootstrap.Core.Patterns.defmatch(Bootstrap.Core.Patterns.clause([Bootstrap.Core.Patterns.type(ArgumentError, {})], function() { return IO.puts('ArgumentError'); }), Bootstrap.Core.Patterns.clause([Bootstrap.Core.Patterns.variable()], function(x) { @@ -116,8 +120,9 @@ defmodule ElixirScript.Translator.Try.Test do test "translate with a rescue and after clause" do ex_ast = quote do + try do - do_something_that_may_fail(some_arg) + 1 rescue ArgumentError -> IO.puts "Invalid argument given" @@ -128,7 +133,7 @@ defmodule ElixirScript.Translator.Try.Test do js_code = """ Bootstrap.Core.SpecialForms._try(function() { - return do_something_that_may_fail(some_arg); + return 1; }, Bootstrap.Core.Patterns.defmatch(Bootstrap.Core.Patterns.clause([Bootstrap.Core.Patterns.type(ArgumentError, {})], function() { return IO.puts('Invalid argument given'); })), null, null, function() { @@ -141,8 +146,9 @@ defmodule ElixirScript.Translator.Try.Test do test "translate with an after clause" do ex_ast = quote do + try do - do_something_that_may_fail(some_arg) + 1 after IO.puts "This is printed regardless if it failed or succeed" end @@ -150,7 +156,7 @@ defmodule ElixirScript.Translator.Try.Test do js_code = """ Bootstrap.Core.SpecialForms._try(function() { - return do_something_that_may_fail(some_arg); + return 1; },null,null,null,function() { return IO.puts('This is printed regardless if it failed or succeed'); }) @@ -161,6 +167,7 @@ defmodule ElixirScript.Translator.Try.Test do test "translate else" do ex_ast = quote do + x = 1 try do 1 / x else @@ -189,7 +196,7 @@ defmodule ElixirScript.Translator.Try.Test do test "translate catch" do ex_ast = quote do try do - do_something_that_may_fail(some_arg) + 1 rescue ArgumentError -> IO.puts "Invalid argument given" @@ -201,7 +208,7 @@ defmodule ElixirScript.Translator.Try.Test do js_code = """ Bootstrap.Core.SpecialForms._try(function() { - return do_something_that_may_fail(some_arg); + return 1; }, Bootstrap.Core.Patterns.defmatch(Bootstrap.Core.Patterns.clause([Bootstrap.Core.Patterns.type(ArgumentError, {})], function() { return IO.puts('Invalid argument given'); })), Bootstrap.Core.Patterns.defmatch(Bootstrap.Core.Patterns.clause([Symbol.for('throw'), Symbol.for('Error')], function() { diff --git a/test/translator/umd_test.exs b/test/translator/umd_test.exs index b7421015..b841baef 100644 --- a/test/translator/umd_test.exs +++ b/test/translator/umd_test.exs @@ -5,14 +5,11 @@ defmodule ElixirScript.Translator.UMD.Test do test "translate module to umd" do ex_ast = quote do defmodule Elephant do - @ul JQuery.("#todo-list") + @ul "#todo-list" def something() do @ul end - - defgenp something_else() do - end end end diff --git a/test/translator/with_test.exs b/test/translator/with_test.exs index 37a8afc9..c2d9322b 100644 --- a/test/translator/with_test.exs +++ b/test/translator/with_test.exs @@ -2,9 +2,9 @@ defmodule ElixirScript.Translator.With.Test do use ExUnit.Case import ElixirScript.TestHelper - test "translate with" do ex_ast = quote do + opts = %{} with {:ok, width} <- Map.fetch(opts, :width), {:ok, height} <- Map.fetch(opts, :height), do: {:ok, width * height} @@ -29,6 +29,7 @@ defmodule ElixirScript.Translator.With.Test do test "translate with with bare expression" do ex_ast = quote do + opts = %{} with {:ok, width} <- Map.fetch(opts, :width), double_width = width * 2, {:ok, height} <- Map.fetch(opts, :height), @@ -56,6 +57,7 @@ defmodule ElixirScript.Translator.With.Test do test "translate with with else" do ex_ast = quote do + opts = %{} with {:ok, width} <- Map.fetch(opts, :width), {:ok, height} <- Map.fetch(opts, :height) do {:ok, width * height} From 7e12e635d6538bb78cb2ee0c0a5297967cedd065 Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Fri, 24 Feb 2017 17:26:14 -0600 Subject: [PATCH 430/860] Add translation to rewrite Elixir.Enum to Bootstrap.Enum --- lib/elixir_script/passes/ast_from_file.ex | 6 +++--- lib/elixir_script/translator.ex | 6 +++++- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/lib/elixir_script/passes/ast_from_file.ex b/lib/elixir_script/passes/ast_from_file.ex index 24e656bf..271ccdec 100644 --- a/lib/elixir_script/passes/ast_from_file.ex +++ b/lib/elixir_script/passes/ast_from_file.ex @@ -1,11 +1,11 @@ defmodule ElixirScript.Passes.ASTFromFile do - @moduledoc false + @moduledoc false def execute(compiler_data, opts) do data = Enum.reduce(compiler_data.data, [], fn({dep, paths}, list) -> file_paths = paths - |> Enum.flat_map(fn(path) -> Path.join(path, "**/*.{ex,exs,exjs}") |> Path.wildcard end) + |> Enum.flat_map(fn(path) -> Path.join([path, "**", "*.{ex,exs,exjs}"]) |> Path.wildcard end) |> Enum.reduce([], fn(path, list) -> quoted = path |> File.read! @@ -13,7 +13,7 @@ defmodule ElixirScript.Passes.ASTFromFile do stat = File.stat!(path) - list ++ [%{ path: path, app: dep, stat: stat, ast: quoted }] + list ++ [%{path: path, app: dep, stat: stat, ast: quoted}] end) diff --git a/lib/elixir_script/translator.ex b/lib/elixir_script/translator.ex index bc41ad45..3947f4e5 100644 --- a/lib/elixir_script/translator.ex +++ b/lib/elixir_script/translator.ex @@ -272,6 +272,10 @@ defmodule ElixirScript.Translator do end end + defp do_translate({{:., context1, [{:__aliases__, context2, [:Elixir, :Enum]}, function_name]}, context3, params }, env) do + translate({{:., context1, [{:__aliases__, context2, [:Enum]}, function_name]}, context3, params }, env) + end + defp do_translate({{:., context1, [{:__aliases__, context2, [:Enum]}, function_name]}, context3, params }, env) do translate({{:., context1, [{:__aliases__, context2, [:Bootstrap, :Enum]}, function_name]}, context3, params }, env) end @@ -628,7 +632,7 @@ defmodule ElixirScript.Translator do def create_module_name(module_name, env) do case module_name do {:__aliases__, _, _} -> - candiate_module_name = ElixirScript.Translator.State.get_module_name(env.state, + candiate_module_name = ElixirScript.Translator.State.get_module_name(env.state, Utils.quoted_to_name(module_name)) if ElixirScript.Translator.LexicalScope.get_module_name(env, candiate_module_name) in ElixirScript.Translator.State.list_module_names(env.state) do From c0e1f504d9304daae7cdbcec292ca31864faa013 Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Fri, 24 Feb 2017 23:21:27 -0600 Subject: [PATCH 431/860] refactoring --- lib/elixir_script.ex | 5 -- lib/elixir_script/module_systems/common.ex | 12 +-- lib/elixir_script/module_systems/es.ex | 10 +-- lib/elixir_script/module_systems/namespace.ex | 73 +++++++------------ lib/elixir_script/module_systems/umd.ex | 19 +---- lib/elixir_script/passes/create_js_modules.ex | 2 +- lib/elixir_script/passes/handle_output.ex | 5 +- lib/elixir_script/passes/java_script_name.ex | 8 -- .../kernel/special_forms/identifier.ex | 4 +- 9 files changed, 44 insertions(+), 94 deletions(-) delete mode 100644 lib/elixir_script/passes/java_script_name.ex diff --git a/lib/elixir_script.ex b/lib/elixir_script.ex index 879b3ccc..f8663651 100644 --- a/lib/elixir_script.ex +++ b/lib/elixir_script.ex @@ -83,7 +83,6 @@ defmodule ElixirScript do |> ElixirScript.Passes.ConsolidateProtocols.execute(opts) |> ElixirScript.Passes.CreateJSModules.execute(opts) |> ElixirScript.Passes.JavaScriptCode.execute(opts) - |> ElixirScript.Passes.JavaScriptName.execute(opts) |> ElixirScript.Passes.HandleOutput.execute(opts) end @@ -186,15 +185,11 @@ defmodule ElixirScript do |> ElixirScript.Passes.ConsolidateProtocols.execute(opts) |> ElixirScript.Passes.CreateJSModules.execute(opts) |> ElixirScript.Passes.JavaScriptCode.execute(opts) - |> ElixirScript.Passes.JavaScriptName.execute(opts) |> ElixirScript.Passes.HandleOutput.execute(opts) result end - @doc false - def version(), do: @version - defp build_compiler_options(opts) do default_options = Map.new |> Map.put(:include_path, false) diff --git a/lib/elixir_script/module_systems/common.ex b/lib/elixir_script/module_systems/common.ex index 0b0ed8c6..c3caf08a 100644 --- a/lib/elixir_script/module_systems/common.ex +++ b/lib/elixir_script/module_systems/common.ex @@ -11,8 +11,7 @@ defmodule ElixirScript.ModuleSystems.Common do imports = js_imports |> Enum.map(fn {module, path} -> import_module(module, path) - {module, path, true} -> import_module(module, path) - {module, path, false} -> import_namespace_module(module, path) + {module, path, _} -> import_module(module, path) end) imports = Enum.uniq(imports ++ module_imports) @@ -21,12 +20,7 @@ defmodule ElixirScript.ModuleSystems.Common do imports ++ body ++ export end - def import_namespace_module(module_name, from) do - js_module_name = ElixirScript.Translator.Identifier.make_namespace_members(module_name) - do_import_module(js_module_name, from) - end - - def import_module(module_name, from) do + defp import_module(module_name, from) do js_module_name = ElixirScript.Translator.Identifier.make_namespace_members(module_name) do_import_module(js_module_name, from) end @@ -45,7 +39,7 @@ defmodule ElixirScript.ModuleSystems.Common do end - def export_module(exported_object) do + defp export_module(exported_object) do JS.assignment_expression( :=, JS.member_expression( diff --git a/lib/elixir_script/module_systems/es.ex b/lib/elixir_script/module_systems/es.ex index 51813427..4423d064 100644 --- a/lib/elixir_script/module_systems/es.ex +++ b/lib/elixir_script/module_systems/es.ex @@ -11,8 +11,8 @@ defmodule ElixirScript.ModuleSystems.ES do imports = js_imports |> Enum.map(fn {module, path} -> import_module(module, path) - {module, path, true} -> import_module(module, path) - {module, path, false} -> import_namespace_module(module, path) + {module, path, default: true} -> import_module(module, path) + {module, path, default: false} -> import_namespace_module(module, path) end) imports = Enum.uniq(imports ++ module_imports) @@ -21,7 +21,7 @@ defmodule ElixirScript.ModuleSystems.ES do imports ++ body ++ export end - def import_namespace_module(module_name, from) do + defp import_namespace_module(module_name, from) do js_module_name = ElixirScript.Translator.Identifier.make_namespace_members(module_name) import_specifier = JS.import_namespace_specifier( @@ -32,7 +32,7 @@ defmodule ElixirScript.ModuleSystems.ES do do_import_module([import_specifier], from) end - def import_module(import_name, from) do + defp import_module(import_name, from) do js_module_name = ElixirScript.Translator.Identifier.make_namespace_members(import_name) import_specifier = JS.import_default_specifier( @@ -49,7 +49,7 @@ defmodule ElixirScript.ModuleSystems.ES do ) end - def export_module(exported_object) do + defp export_module(exported_object) do JS.export_default_declaration(exported_object) end diff --git a/lib/elixir_script/module_systems/namespace.ex b/lib/elixir_script/module_systems/namespace.ex index f6164342..709587f1 100644 --- a/lib/elixir_script/module_systems/namespace.ex +++ b/lib/elixir_script/module_systems/namespace.ex @@ -4,6 +4,7 @@ defmodule ElixirScript.ModuleSystems.Namespace do alias ElixirScript.Translator alias ElixirScript.Translator.State alias ElixirScript.Translator.Utils + alias ElixirScript.Translator.Identifier def build(module_name, imports, body, exports, env) do module_imports = imports @@ -21,28 +22,18 @@ defmodule ElixirScript.ModuleSystems.Namespace do List.wrap(make_namespace_body(module_name, module_imports, body, exports)) end + defp module_name_function_call(module_name, function) do + members = ["Elixir"] ++ Module.split(module_name) ++ [function] + Identifier.make_namespace_members(members) + end + def import_module(module_name) do name = ["Elixir" | Module.split(module_name) ] |> Enum.join("$") declarator = JS.variable_declarator( JS.identifier(name), JS.call_expression( - JS.member_expression( - JS.call_expression( - JS.member_expression( - JS.identifier("Bootstrap"), - JS.member_expression( - JS.identifier(:Core), - JS.member_expression( - JS.identifier(:Functions), - JS.identifier(:build_namespace) - ) - ) - ), - [JS.identifier("Elixir"), JS.literal(Utils.name_to_js_file_name(module_name))] - ), - JS.identifier("__load") - ), + module_name_function_call(module_name, "__load"), [JS.identifier("Elixir")] ) ) @@ -50,26 +41,21 @@ defmodule ElixirScript.ModuleSystems.Namespace do JS.variable_declaration([declarator], :const) end + defp build_namespace() do + JS.member_expression( + JS.identifier("Bootstrap"), + JS.member_expression( + JS.identifier(:Core), + JS.member_expression( + JS.identifier(:Functions), + JS.identifier(:build_namespace) + ) + ) + ) + end + defp make_namespace_body(module_name, imports, body, exports) do - _self = - JS.call_expression( - JS.member_expression( - JS.identifier("Bootstrap"), - JS.member_expression( - JS.identifier(:Core), - JS.member_expression( - JS.identifier(:Functions), - JS.identifier(:build_namespace) - ) - ) - ), - [JS.identifier("Elixir"), JS.literal(Utils.name_to_js_file_name(module_name))] - ) - - values = JS.member_expression( - _self, - JS.identifier("__exports") - ) + values = module_name_function_call(module_name, "__exports") _if = JS.if_statement( values, @@ -99,19 +85,10 @@ defmodule ElixirScript.ModuleSystems.Namespace do make = JS.member_expression( JS.call_expression( - JS.member_expression( - JS.identifier("Bootstrap"), - JS.member_expression( - JS.identifier(:Core), - JS.member_expression( - JS.identifier(:Functions), - JS.identifier(:build_namespace) - ) - ) - ), - [JS.identifier("Elixir"), JS.literal(Utils.name_to_js_file_name(module_name))] - ), - JS.identifier("__load") + build_namespace(), + [JS.identifier("Elixir"), JS.literal(Utils.name_to_js_file_name(module_name))] + ), + JS.identifier("__load") ) func_body = JS.block_statement([_if] ++ body ++ [declaration, assign] ++ imports ++ exports) diff --git a/lib/elixir_script/module_systems/umd.ex b/lib/elixir_script/module_systems/umd.ex index e36edd7f..82251037 100644 --- a/lib/elixir_script/module_systems/umd.ex +++ b/lib/elixir_script/module_systems/umd.ex @@ -11,8 +11,7 @@ defmodule ElixirScript.ModuleSystems.UMD do imports = js_imports |> Enum.map(fn {module, path} -> import_module(module, path) - {module, path, true} -> import_module(module, path) - {module, path, false} -> import_namespace_module(module, path) + {module, path, _} -> import_module(module, path) end) imports = Enum.uniq(imports ++ module_imports) @@ -21,26 +20,16 @@ defmodule ElixirScript.ModuleSystems.UMD do List.wrap(make_umd(imports, body, export)) end - def import_namespace_module(module_name, from) do - js_module_name = ElixirScript.Translator.Identifier.make_namespace_members(module_name) - {js_module_name, JS.literal(from)} - end - - def import_module(module_name, from) do + defp import_module(module_name, from) do js_module_name = ElixirScript.Translator.Identifier.make_namespace_members(module_name) {js_module_name, JS.literal(from)} end - def import_module(module_name, from) do - js_module_name = ElixirScript.Translator.Identifier.make_namespace_members(module_name) - {JS.identifier(module_name), JS.literal(from)} - end - - def export_module(exported_object) do + defp export_module(exported_object) do exported_object end - def make_umd(imports, body, exports) do + defp make_umd(imports, body, exports) do import_paths = Enum.map(imports, fn({_, path}) -> path end) import_identifiers = Enum.map(imports, fn({id, _}) -> id end) exports = if is_nil(exports), do: [], else: [JS.return_statement(exports)] diff --git a/lib/elixir_script/passes/create_js_modules.ex b/lib/elixir_script/passes/create_js_modules.ex index 0523a6db..556c7da7 100644 --- a/lib/elixir_script/passes/create_js_modules.ex +++ b/lib/elixir_script/passes/create_js_modules.ex @@ -92,7 +92,7 @@ defmodule ElixirScript.Passes.CreateJSModules do ast = opts.module_formatter.build( [], - [{"Bootstrap", "./Elixir.Bootstrap", true }] ++ opts.js_modules, + [{"Bootstrap", "./Elixir.Bootstrap", default: true }] ++ opts.js_modules, [elixir, start] ++ body, JS.identifier("Elixir") ) diff --git a/lib/elixir_script/passes/handle_output.ex b/lib/elixir_script/passes/handle_output.ex index e4144ae7..382eb2e8 100644 --- a/lib/elixir_script/passes/handle_output.ex +++ b/lib/elixir_script/passes/handle_output.ex @@ -1,6 +1,7 @@ defmodule ElixirScript.Passes.HandleOutput do @moduledoc false alias ElixirScript.Translator.State + @generated_name "Elixir.App.js" def execute(compiler_data, opts) do State.stop(compiler_data.state) @@ -27,7 +28,7 @@ defmodule ElixirScript.Passes.HandleOutput do ElixirScript.copy_bootstrap_to_destination(compiler_opts.format, output_path) end - file_name = Path.join([output_path, compiler_output.generated_name]) + file_name = Path.join([output_path, @generated_name]) if !File.exists?(Path.dirname(file_name)) do File.mkdir_p!(Path.dirname(file_name)) @@ -39,7 +40,7 @@ defmodule ElixirScript.Passes.HandleOutput do defp process_include_path(compiler_output, compiler_opts) do case compiler_opts.include_path do true -> - {compiler_output.generated, compiler_output.generated_name} + {compiler_output.generated, @generated_name} false -> compiler_output.generated end diff --git a/lib/elixir_script/passes/java_script_name.ex b/lib/elixir_script/passes/java_script_name.ex deleted file mode 100644 index 38871341..00000000 --- a/lib/elixir_script/passes/java_script_name.ex +++ /dev/null @@ -1,8 +0,0 @@ -defmodule ElixirScript.Passes.JavaScriptName do - @moduledoc false - alias ElixirScript.Translator.Utils - - def execute(compiler_data, _) do - Map.put(compiler_data, :generated_name, "Elixir.App.js") - end -end diff --git a/lib/elixir_script/translator/kernel/special_forms/identifier.ex b/lib/elixir_script/translator/kernel/special_forms/identifier.ex index 433a3e48..3639432c 100644 --- a/lib/elixir_script/translator/kernel/special_forms/identifier.ex +++ b/lib/elixir_script/translator/kernel/special_forms/identifier.ex @@ -71,6 +71,8 @@ defmodule ElixirScript.Translator.Identifier do def make_namespace_members(module_name) do case module_name do + m when is_list(m) -> + m m when is_binary(m) -> String.split(m, ".") m when is_atom(m) -> @@ -78,6 +80,6 @@ defmodule ElixirScript.Translator.Identifier do end |> Enum.reverse |> make_alias - end + end end From 56cb2c558cbb7390441b982fa663fdd0bf170d5d Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Sat, 25 Feb 2017 07:48:11 -0600 Subject: [PATCH 432/860] Backing out compilation of quoted to compiled_quoted. #249 --- lib/elixir_script.ex | 20 +++----------------- 1 file changed, 3 insertions(+), 17 deletions(-) diff --git a/lib/elixir_script.ex b/lib/elixir_script.ex index f8663651..b80de898 100644 --- a/lib/elixir_script.ex +++ b/lib/elixir_script.ex @@ -71,11 +71,10 @@ defmodule ElixirScript do |> get_modules_from_quoted |> Enum.map(fn(x) -> %{ast: x, app: :app} end) - {loaded_modules, std_lib_quoted} = get_quoted_std_lib() + std_lib_quoted = get_quoted_std_lib() - %{data: std_lib_quoted ++ data, loaded_modules: loaded_modules} + %{data: std_lib_quoted ++ data} |> ElixirScript.Passes.Init.execute(opts) - |> ElixirScript.Passes.LoadModulesForQuoted.execute(opts) |> ElixirScript.Passes.FindModules.execute(opts) |> ElixirScript.Passes.FindLoadOnly.execute(opts) |> ElixirScript.Passes.FindFunctions.execute(opts) @@ -91,24 +90,11 @@ defmodule ElixirScript do |> Path.join |> Path.wildcard - loaded_modules = if Code.ensure_loaded?(ElixirScript.Kernel) do - [] - else - case files do - [] -> - [] - files -> - Kernel.ParallelCompiler.files(files) - end - end - - std_lib_quoted = files + files |> Enum.map(fn path -> File.read!(path) end) |> Enum.map(&Code.string_to_quoted!(&1)) |> Enum.flat_map(&get_modules_from_quoted(&1)) |> Enum.map(fn(x) -> %{ast: x, app: :elixir} end) - - {loaded_modules, std_lib_quoted} end defp get_modules_from_quoted(quoted) do From d2fdc7aa37f405c7d6104d050e650e3c04eab90e Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Sat, 25 Feb 2017 15:26:31 -0600 Subject: [PATCH 433/860] Update module refs to reference module directly. Remove processing of standard lib in tests. --- lib/elixir_script/module_systems/namespace.ex | 20 +- .../passes/consolidate_protocols.ex | 24 +- lib/elixir_script/passes/create_js_modules.ex | 22 +- lib/elixir_script/passes/java_script_ast.ex | 7 +- lib/elixir_script/translator.ex | 94 ++++++-- .../translator/kernel/defimpl.ex | 5 +- .../translator/kernel/defmodule.ex | 10 +- .../translator/kernel/defprotocol.ex | 4 - .../translator/kernel/special_forms/call.ex | 205 ++++++++++++++---- .../kernel/special_forms/capture.ex | 22 +- test/prelude/kernel_test.exs | 5 +- test/translator/atom_test.exs | 2 +- test/translator/bug_test.exs | 2 +- test/translator/capture_test.exs | 4 +- test/translator/defmodule_test.exs | 2 +- test/translator/for_test.exs | 2 +- test/translator/function_test.exs | 22 +- test/translator/kernel_test.exs | 10 +- test/translator/string_test.exs | 8 +- test/translator/with_test.exs | 12 +- 20 files changed, 319 insertions(+), 163 deletions(-) diff --git a/lib/elixir_script/module_systems/namespace.ex b/lib/elixir_script/module_systems/namespace.ex index 709587f1..ba2f0724 100644 --- a/lib/elixir_script/module_systems/namespace.ex +++ b/lib/elixir_script/module_systems/namespace.ex @@ -6,20 +6,8 @@ defmodule ElixirScript.ModuleSystems.Namespace do alias ElixirScript.Translator.Utils alias ElixirScript.Translator.Identifier - def build(module_name, imports, body, exports, env) do - module_imports = imports - |> Enum.filter(fn - {mod, _} -> - case Module.split(mod) do - ["JS"] -> false - _ -> true - end - end) - |> Enum.map(fn {module, path} -> - import_module(module) - end) - - List.wrap(make_namespace_body(module_name, module_imports, body, exports)) + def build(module_name, body, exports, env) do + List.wrap(make_namespace_body(module_name, body, exports)) end defp module_name_function_call(module_name, function) do @@ -54,7 +42,7 @@ defmodule ElixirScript.ModuleSystems.Namespace do ) end - defp make_namespace_body(module_name, imports, body, exports) do + defp make_namespace_body(module_name, body, exports) do values = module_name_function_call(module_name, "__exports") _if = JS.if_statement( @@ -91,7 +79,7 @@ defmodule ElixirScript.ModuleSystems.Namespace do JS.identifier("__load") ) - func_body = JS.block_statement([_if] ++ body ++ [declaration, assign] ++ imports ++ exports) + func_body = JS.block_statement([_if] ++ body ++ [declaration, assign] ++ exports) func = JS.function_expression([JS.identifier("Elixir")], [], func_body) JS.assignment_expression( diff --git a/lib/elixir_script/passes/consolidate_protocols.ex b/lib/elixir_script/passes/consolidate_protocols.ex index a05e0153..2f0a5abe 100644 --- a/lib/elixir_script/passes/consolidate_protocols.ex +++ b/lib/elixir_script/passes/consolidate_protocols.ex @@ -3,6 +3,7 @@ defmodule ElixirScript.Passes.ConsolidateProtocols do alias ESTree.Tools.Builder, as: JS alias ElixirScript.Translator.Utils alias ElixirScript.Translator.State + alias ElixirScript.Translator.Identifier require Logger def execute(compiler_data, opts) do @@ -67,23 +68,21 @@ defmodule ElixirScript.Passes.ConsolidateProtocols do app_name = protocol.app - defimpl_imports = Enum.map(implementations, fn({_, impl_data}) -> - x = Atom.to_string(Utils.quoted_to_name(impl_data.for)) - x = String.to_atom(protocol_name <> ".DefImpl." <> x) - name = Utils.name_to_js_name(x) - ElixirScript.ModuleSystems.Namespace.import_module(x) - end) - body = Enum.map(implementations, fn({_, impl_data}) -> - x = Atom.to_string(Utils.quoted_to_name(impl_data.for)) - x = String.to_atom(protocol_name <> ".DefImpl." <> x) - name = Utils.name_to_js_name(x) + x = Utils.quoted_to_name(impl_data.for) + members = ["Elixir"] ++ Module.split(name) ++ ["DefImpl"] ++ Module.split(x) ++ ["__load"] + ast = JS.call_expression( + Identifier.make_namespace_members(members), + [JS.identifier("Elixir")] + ) + + JS.call_expression( JS.member_expression( JS.identifier("impls"), JS.identifier("push") ), - [JS.identifier(name)] + [ast] ) end) @@ -92,8 +91,7 @@ defmodule ElixirScript.Passes.ConsolidateProtocols do name: name, module: String.to_atom(protocol_name <> ".DefImpl"), std_lib: {:Elixir, Utils.make_local_file_path(:elixir, compiler_opts.core_path, compiler_opts.root, nil)}, - imports: [], - body: defimpl_imports ++ [declaration] ++ body, + body: [declaration] ++ body, exports: JS.identifier("impls"), app: app_name, type: :consolidated, diff --git a/lib/elixir_script/passes/create_js_modules.ex b/lib/elixir_script/passes/create_js_modules.ex index 556c7da7..8de02be2 100644 --- a/lib/elixir_script/passes/create_js_modules.ex +++ b/lib/elixir_script/passes/create_js_modules.ex @@ -9,15 +9,19 @@ defmodule ElixirScript.Passes.CreateJSModules do acc ({module_name, module_data}, acc) -> - body = generate_namespace_module( - module_data.type, - module_name, - Map.get(module_data, :javascript_module, module_data), - opts, - compiler_data.state - ) + if module_data.app == :elixir && opts.import_standard_libs == false do + acc + else + body = generate_namespace_module( + module_data.type, + module_name, + Map.get(module_data, :javascript_module, module_data), + opts, + compiler_data.state + ) - acc ++ List.wrap(body) + acc ++ List.wrap(body) + end end) compiled = compile(namespace_modules, opts) @@ -34,7 +38,6 @@ defmodule ElixirScript.Passes.CreateJSModules do body = ElixirScript.ModuleSystems.Namespace.build( module_name, - js_module.imports, js_module.body, js_module.exports, env @@ -46,7 +49,6 @@ defmodule ElixirScript.Passes.CreateJSModules do defp generate_namespace_module(_, module_name, js_module, _, _) do body = ElixirScript.ModuleSystems.Namespace.build( module_name, - js_module.imports, js_module.body, js_module.exports, js_module.env diff --git a/lib/elixir_script/passes/java_script_ast.ex b/lib/elixir_script/passes/java_script_ast.ex index cc1ef76b..7a95f0eb 100644 --- a/lib/elixir_script/passes/java_script_ast.ex +++ b/lib/elixir_script/passes/java_script_ast.ex @@ -8,7 +8,12 @@ defmodule ElixirScript.Passes.JavaScriptAST do State.set_module_data(compiler_data.state, compiler_data.data) State.set_loaded_modules(compiler_data.state, Map.get(compiler_data, :loaded_modules, [])) - data = Enum.map(State.get_module_data(compiler_data.state), fn({module_name, module_data}) -> + data = compiler_data.state + |> State.get_module_data + |> Enum.reject(fn {_,module_data} -> + module_data.app == :elixir && opts.import_standard_libs == false + end) + |> Enum.map(fn({module_name, module_data}) -> module_data = compile(module_data, opts, compiler_data.state) {module_name, module_data} end) diff --git a/lib/elixir_script/translator.ex b/lib/elixir_script/translator.ex index 3947f4e5..83d07ff6 100644 --- a/lib/elixir_script/translator.ex +++ b/lib/elixir_script/translator.ex @@ -169,7 +169,15 @@ defmodule ElixirScript.Translator do end defp do_translate({:&, _, [{:/, _, [{{:., _, [module_name, function_name]}, _, []}, arity]}]}, env) do - { Capture.make_capture(module_name, function_name, arity, env), env } + module_name = create_module_name2(module_name, env) + js_ast = case module_name do + {mod, :local} -> + Capture.make_capture(mod, function_name, arity, env) + mod -> + Capture.make_extern_capture(mod, function_name, arity, env) + end + + { js_ast, env } end defp do_translate({:&, _, [{:/, _, [{function_name, _, _}, arity]}]}, env) do @@ -236,37 +244,34 @@ defmodule ElixirScript.Translator do end defp do_translate({{:., _, [function_name]}, _, params}, env) do - Call.make_function_call(function_name, params, env) + Call.make_local_function_call(function_name, params, env) end - defp do_translate({:., _, [module_name, function_name]} = ast, env) do - expanded_ast = Macro.expand(ast, env.env) - - if expanded_ast == ast do - module_name = create_module_name(module_name, env) - Call.make_function_or_property_call(module_name, function_name, env) - else - translate(expanded_ast, env) - end + defp do_translate({:., _, [{:__aliases__, _, _} = module_name, function_name]} = ast, env) do + do_translate({{:., [], [module_name, function_name]}, [], []}, env) end - defp do_translate({{:., _, [module_name, function_name]}, _, [] } = ast, env) do + defp do_translate({{:., _, [{:__aliases__, _, _} = module_name, function_name]}, _, [] } = ast, env) do expanded_ast = Macro.expand(ast, env.env) if expanded_ast == ast do - module_name = create_module_name(module_name, env) - Call.make_function_or_property_call(module_name, function_name, env) + module_name = create_module_name2(module_name, env) + case module_name do + {mod, :local} -> + Call.make_module_function_call(mod, function_name, env) + mod -> + Call.make_extern_function_or_property_call(mod, function_name, env) + end else translate(expanded_ast, env) end end - defp do_translate({{:., _, [{:__aliases__, _, _} = module_name]}, _, params} = ast, env) do + defp do_translate({:., _, [module_name, function_name]} = ast, env) do expanded_ast = Macro.expand(ast, env.env) if expanded_ast == ast do - module_name = create_module_name(module_name, env) - Call.make_function_call(module_name, params, env) + Call.make_function_or_property_call(module_name, function_name, env) else translate(expanded_ast, env) end @@ -288,11 +293,36 @@ defmodule ElixirScript.Translator do JSLib.translate_js_function(function_name, params, env) end + defp do_translate({{:., _, [{:__aliases__, _, _} = module_name, function_name]}, _, params } = ast, env) do + expanded_ast = Macro.expand(ast, env.env) + + if expanded_ast == ast do + module_name = create_module_name2(module_name, env) + case module_name do + {mod, :local} -> + Call.make_module_function_call(mod, function_name, params, env) + mod -> + Call.make_extern_function_call(mod, function_name, params, env) + end + else + translate(expanded_ast, env) + end + end + + defp do_translate({{:., _, [module_name, function_name]}, _, params} = ast, env) when is_atom(module_name) and is_atom(function_name) do + expanded_ast = Macro.expand(ast, env.env) + + if expanded_ast == ast do + Call.make_function_call(module_name, function_name, params, env) + else + translate(expanded_ast, env) + end + end + defp do_translate({{:., _, [module_name, function_name]}, _, params } = ast, env) do expanded_ast = Macro.expand(ast, env.env) if expanded_ast == ast do - module_name = create_module_name(module_name, env) Call.make_function_call(module_name, function_name, params, env) else translate(expanded_ast, env) @@ -304,8 +334,13 @@ defmodule ElixirScript.Translator do end defp do_translate({:__aliases__, _, aliases} = ast, env) do - module_name = create_module_name(ast, env) - Call.make_module_name(module_name, env) + module_name = create_module_name2(ast, env) + case module_name do + {mod, :local} -> + Call.make_module_name(mod, env) + mod -> + Call.make_extern_module_name(mod, env) + end end defp do_translate({:__MODULE__, _, _ }, env) do @@ -580,12 +615,12 @@ defmodule ElixirScript.Translator do cond do name_arity in module.functions or name_arity in module.private_functions -> - Call.make_function_call(name, params, env) + Call.make_local_function_call(name, params, env) ElixirScript.Translator.LexicalScope.find_module(env, name_arity) -> imported_module_name = ElixirScript.Translator.LexicalScope.find_module(env, name_arity) - Call.make_function_call(imported_module_name, name, params, env) + Call.make_module_function_call(imported_module_name, name, params, env) true -> - Call.make_function_call(name, params, env) + Call.make_local_function_call(name, params, env) end else @@ -604,7 +639,7 @@ defmodule ElixirScript.Translator do Call.make_function_call(name, [], env) ElixirScript.Translator.LexicalScope.find_module(env, {name, 0}) -> imported_module_name = ElixirScript.Translator.LexicalScope.find_module(env, {name, 0}) - Call.make_function_call(imported_module_name, name, params, env) + Call.make_module_function_call(imported_module_name, name, params, env) true -> { Identifier.make_identifier(name), env } end @@ -645,6 +680,17 @@ defmodule ElixirScript.Translator do end end + def create_module_name2(module_name, env) do + module_name = Utils.quoted_to_name(module_name) + candiate_module_name = ElixirScript.Translator.State.get_module_name(env.state, module_name) + + if ElixirScript.Translator.LexicalScope.get_module_name(env, candiate_module_name) in ElixirScript.Translator.State.list_module_names(env.state) do + { ElixirScript.Translator.LexicalScope.get_module_name(env, candiate_module_name), :local } + else + module_name + end + end + def has_function?(module_name, name_arity, env) do case ElixirScript.Translator.State.get_module(env.state, module_name) do nil -> diff --git a/lib/elixir_script/translator/kernel/defimpl.ex b/lib/elixir_script/translator/kernel/defimpl.ex index 0d7e0a1e..92860e18 100644 --- a/lib/elixir_script/translator/kernel/defimpl.ex +++ b/lib/elixir_script/translator/kernel/defimpl.ex @@ -8,7 +8,7 @@ defmodule ElixirScript.Translator.Defimpl do def make(name, type, body, env) do type = map_to_js(type, env) - {imports, body, export} = Defmodule.process_module(name, body, env) + {body, export} = Defmodule.process_module(name, body, env) protocol_name = Atom.to_string(name) |> String.split(".DefImpl.") |> hd |> String.to_atom @@ -24,8 +24,7 @@ defmodule ElixirScript.Translator.Defimpl do ]) %{ - name: Utils.quoted_to_name({:__aliases__, [], name }), - imports: imports, + name: Utils.quoted_to_name({:__aliases__, [], name }), exports: export, body: body, app_name: State.get_module(env.state, name).app, diff --git a/lib/elixir_script/translator/kernel/defmodule.ex b/lib/elixir_script/translator/kernel/defmodule.ex index 60dc747a..17f1c7c1 100644 --- a/lib/elixir_script/translator/kernel/defmodule.ex +++ b/lib/elixir_script/translator/kernel/defmodule.ex @@ -12,7 +12,6 @@ defmodule ElixirScript.Translator.Defmodule do { body, _ } = translate_body(body, env) %{ name: ElixirScript.Temp, - imports: [], body: body |> Group.inflate_groups, exports: nil, app_name: ElixirScript.Translator.State.get(env.state).compiler_opts.app, @@ -23,7 +22,6 @@ defmodule ElixirScript.Translator.Defmodule do def make_module(module, nil, env) do %{ name: module, - imports: [], body: [], exports: nil, app_name: ElixirScript.Translator.State.get(env.state).compiler_opts.app, @@ -32,12 +30,11 @@ defmodule ElixirScript.Translator.Defmodule do end def make_module(module, body, env) do - {imports, body, exported_object} = process_module(module, body, env) + {body, exported_object} = process_module(module, body, env) app_name = State.get_module(env.state, module).app result = %{ name: Utils.quoted_to_name({:__aliases__, [], module }), - imports: imports, exports: exported_object, body: body, app_name: app_name, @@ -77,11 +74,8 @@ defmodule ElixirScript.Translator.Defmodule do exported_functions = Enum.map(exported_functions, fn({_key, value}) -> value end) private_functions = Enum.map(private_functions, fn({_key, value}) -> value end) - module_refs = State.get_module_references(env.state, env.module) -- [env.module] - imports = process_module_refs(module_refs, env) - body = structs ++ private_functions ++ exported_functions ++ body - {imports, body, exported_object} + {body, exported_object} end def process_module_refs(module_refs, env) do diff --git a/lib/elixir_script/translator/kernel/defprotocol.ex b/lib/elixir_script/translator/kernel/defprotocol.ex index 9ecdbc7c..f41ee42b 100644 --- a/lib/elixir_script/translator/kernel/defprotocol.ex +++ b/lib/elixir_script/translator/kernel/defprotocol.ex @@ -74,14 +74,10 @@ defmodule ElixirScript.Translator.Defprotocol do ) body = body ++ [declaration] ++ [implementations] - - module_refs = State.get_module_references(env.state, env.module) -- [env.module] - imports = Defmodule.process_module_refs(module_refs, env) defimpl_import = ElixirScript.ModuleSystems.Namespace.import_module(implementation_name_module) %{ name: name, - imports: imports, body: [defimpl_import] ++ body, exports: JS.identifier(Utils.name_to_js_name(name)), app_name: app_name, diff --git a/lib/elixir_script/translator/kernel/special_forms/call.ex b/lib/elixir_script/translator/kernel/special_forms/call.ex index 2fd958e5..65ce4c3f 100644 --- a/lib/elixir_script/translator/kernel/special_forms/call.ex +++ b/lib/elixir_script/translator/kernel/special_forms/call.ex @@ -6,14 +6,90 @@ defmodule ElixirScript.Translator.Call do alias ElixirScript.Translator.Identifier def make_module_name(module_name, env) do - the_name = get_module_name_for_function(module_name, env) - { make_module_expression_tree(the_name, false, env), env } + members = ["Elixir"] ++ Module.split(module_name) + { Identifier.make_namespace_members(members), env } end + def make_extern_module_name(module_name, env) do + members = Module.split(module_name) + { Identifier.make_namespace_members(members), env } + end - def make_function_or_property_call(module_name, function_name, env) do - the_name = get_module_name_for_function(module_name, env) + def make_local_function_call({fun, _, nil}, params, env) do + ast = JS.call_expression( + Identifier.make_identifier(fun), + Enum.map(params, &Translator.translate!(&1, env)) + ) + + {ast, env} + end + + def make_local_function_call(function_name, params, env) do + ast = JS.call_expression( + Identifier.make_identifier(function_name), + Enum.map(params, &Translator.translate!(&1, env)) + ) + + {ast, env} + end + + def make_module_function_call(module_name, function_name, params, env) do + members = ["Elixir"] ++ Module.split(module_name) ++ ["__load"] + + ast = JS.call_expression( + JS.member_expression( + JS.call_expression( + Identifier.make_namespace_members(members), + [JS.identifier("Elixir")] + ), + Identifier.make_identifier(function_name) + ), + Enum.map(params, &Translator.translate!(&1, env)) + ) + + {ast, env} + end + + def make_module_function_call(module_name, function_name, env) do + make_module_function_call(module_name, function_name, [], env) + end + + def make_extern_function_or_property_call(module_name, function_name, env) do + members = Module.split(module_name) + Identifier.make_namespace_members(members) + + js_ast = JS.call_expression( + JS.member_expression( + JS.member_expression( + JS.identifier("Bootstrap"), + JS.member_expression( + JS.identifier("Core"), + JS.identifier("Functions") + ) + ), + JS.identifier("call_property") + ), + [ + Identifier.make_namespace_members(members), + Translator.translate!(to_string(function_name), env) + ] + ) + {js_ast, env} + end + + def make_extern_function_call(module_name, function_name, params, env) do + members = Module.split(module_name) ++ [to_string(function_name)] + + ast = JS.call_expression( + Identifier.make_namespace_members(members), + Enum.map(params, &Translator.translate!(&1, env)) + ) + + {ast, env} + end + + def make_function_or_property_call(module_name, function_name, env) do js_ast = JS.call_expression( JS.member_expression( JS.member_expression( @@ -26,7 +102,7 @@ defmodule ElixirScript.Translator.Call do JS.identifier("call_property") ), [ - make_module_expression_tree(the_name, false, env), + Translator.translate!(module_name), Translator.translate!(to_string(function_name), env) ] ) @@ -53,62 +129,104 @@ defmodule ElixirScript.Translator.Call do end end + def make_function_call(module_name, function_name, [], env) when is_atom(module_name) and is_atom(function_name) do + js_ast = JS.call_expression( + JS.member_expression( + JS.member_expression( + JS.identifier("Bootstrap"), + JS.member_expression( + JS.identifier("Core"), + JS.identifier("Functions") + ) + ), + JS.identifier("call_property") + ), + [ + Identifier.make_identifier(module_name), + Translator.translate!(to_string(function_name), env) + ] + ) - def make_function_call(function_name, params, env) when is_tuple(function_name) do - { make_call_expression(function_name, params, env), env } + {js_ast, env} end - def make_function_call(function_name, params, env) do - { make_call_expression(function_name, params, env), env } + def make_function_call(module_name, function_name, params, env) when is_atom(module_name) and is_atom(function_name) do + js_ast = JS.call_expression( + JS.member_expression( + Identifier.make_identifier(module_name), + Identifier.make_identifier(function_name) + ), + Enum.map(params, &Translator.translate!(&1, env)) + ) + + {js_ast, env} end - def make_function_call(module_name, function_name, params, env) when is_list(module_name) do - call = JS.call_expression( + def make_function_call({{:., _, _}, _, _} = module_name, function_name, [], env) do + js_ast = JS.call_expression( JS.member_expression( - Translator.translate!(module_name, env), - Identifier.make_identifier(function_name) + JS.member_expression( + JS.identifier("Bootstrap"), + JS.member_expression( + JS.identifier("Core"), + JS.identifier("Functions") + ) + ), + JS.identifier("call_property") ), - Enum.map(params, &Translator.translate!(&1, env)) + [ + Translator.translate!(module_name, env), + Translator.translate!(to_string(function_name), env) + ] ) - { call, env } + {js_ast, env} end - def make_function_call(module_name, function_name, params, env) do - params = case params do - atom when is_atom(atom) -> - [] - nil -> - [] - _ -> - params - end - - the_name = get_module_name_for_function(module_name, env) - { make_call_expression(the_name, function_name, params, env), env } - end - - defp make_call_expression(module_name, function_name, params, env) do - JS.call_expression( - make_member_expression(module_name, function_name, env), - Enum.map(params, &Translator.translate!(&1, env)) + def make_function_call({{:., _, _}, _, _} = module_name, function_name, params, env) do + js_ast = JS.call_expression( + JS.member_expression( + Translator.translate!(module_name, env), + Identifier.make_identifier(function_name) + ), + Enum.map(params, &Translator.translate!(&1, env)) ) + + {js_ast, env} end - defp make_call_expression(function_name, params, env) when is_tuple(function_name) do - JS.call_expression( - Translator.translate!(function_name, env), - Enum.map(params, &Translator.translate!(&1, env)) + def make_function_call(module_name, function_name, [], env) do + js_ast = JS.call_expression( + JS.member_expression( + JS.member_expression( + JS.identifier("Bootstrap"), + JS.member_expression( + JS.identifier("Core"), + JS.identifier("Functions") + ) + ), + JS.identifier("call_property") + ), + [ + Translator.translate!(module_name, env), + Translator.translate!(to_string(function_name), env) + ] ) - end - defp make_call_expression(function_name, params, env) do - JS.call_expression( - Identifier.make_identifier(function_name), + {js_ast, env} + end + + def make_function_call(module_name, function_name, params, env) do + call = JS.call_expression( + JS.member_expression( + Translator.translate!(module_name, env), + Identifier.make_identifier(function_name) + ), Enum.map(params, &Translator.translate!(&1, env)) ) - end + { call, env } + end def get_js_name([Elixir | _] = list, _) do list @@ -145,8 +263,7 @@ defmodule ElixirScript.Translator.Call do end end - - def make_member_expression(module_name, function_name, env, computed \\ false) do + defp make_member_expression(module_name, function_name, env, computed \\ false) do case module_name do modules when is_list(modules) and length(modules) > 1 -> ast = make_module_expression_tree(modules, computed, env) diff --git a/lib/elixir_script/translator/kernel/special_forms/capture.ex b/lib/elixir_script/translator/kernel/special_forms/capture.ex index 05bb62f7..ec398f95 100644 --- a/lib/elixir_script/translator/kernel/special_forms/capture.ex +++ b/lib/elixir_script/translator/kernel/special_forms/capture.ex @@ -8,17 +8,27 @@ defmodule ElixirScript.Translator.Capture do alias ElixirScript.Translator.Identifier alias ElixirScript.Translator - def make_capture(function_name, arity, env) do + def make_capture(function_name, _, _) do Identifier.make_identifier(function_name) end - def make_capture(module_name, function_name, arity, env) do - JS.member_expression( - Translator.translate!(module_name, env), - JS.identifier(function_name) - ) + def make_capture(module_name, function_name, _, env) do + members = ["Elixir"] ++ Module.split(module_name) ++ ["__load"] + + ast = JS.member_expression( + JS.call_expression( + Identifier.make_namespace_members(members), + [JS.identifier("Elixir")] + ), + Identifier.make_identifier(function_name) + ) end + def make_extern_capture(module_name, function_name, _, env) do + members = Module.split(module_name) ++ [to_string(function_name)] + Identifier.make_namespace_members(members) + end + def find_value_placeholders(ast) do case ast do list when is_list(list) -> diff --git a/test/prelude/kernel_test.exs b/test/prelude/kernel_test.exs index c5f50ae9..251e2e5a 100644 --- a/test/prelude/kernel_test.exs +++ b/test/prelude/kernel_test.exs @@ -8,6 +8,7 @@ defmodule ElixirScript.Lib.Elixir.Kernel.Test do end js_code = """ + Elixir$ElixirScript$Range.Elixir$ElixirScript$Range.create(Object.freeze({ [Symbol.for('first')]: 1, [Symbol.for('last')]: 4 @@ -23,7 +24,7 @@ defmodule ElixirScript.Lib.Elixir.Kernel.Test do end js_code = """ - Elixir$ElixirScript$Regex.compile__emark__('foo','') + Elixir.ElixirScript.Regex.__load(Elixir).compile__emark__('foo', '') """ assert_translation(ex_ast, js_code) @@ -35,7 +36,7 @@ defmodule ElixirScript.Lib.Elixir.Kernel.Test do end js_code = """ - Elixir$ElixirScript$Regex.compile__emark__('foo', 'i') + Elixir.ElixirScript.Regex.__load(Elixir).compile__emark__('foo', 'i') """ assert_translation(ex_ast, js_code) diff --git a/test/translator/atom_test.exs b/test/translator/atom_test.exs index c06273a5..90edfc9d 100644 --- a/test/translator/atom_test.exs +++ b/test/translator/atom_test.exs @@ -9,6 +9,6 @@ defmodule ElixirScript.Translator.Atom.Test do test "Call Atom module" do ex_ast = quote do: Atom.to_string(:atom) - assert_translation(ex_ast, "Elixir$ElixirScript$Atom.to_string(Symbol.for('atom'))") + assert_translation(ex_ast, "Elixir.ElixirScript.Atom.__load(Elixir).to_string(Symbol.for('atom'))") end end diff --git a/test/translator/bug_test.exs b/test/translator/bug_test.exs index cc0fd7da..6e3820a5 100644 --- a/test/translator/bug_test.exs +++ b/test/translator/bug_test.exs @@ -124,7 +124,7 @@ defmodule ElixirScript.Translator.Bug.Test do js_code = """ const my_func = Bootstrap.Core.Patterns.defmatch(Bootstrap.Core.Patterns.clause([Bootstrap.Core.Patterns.variable()],function(x){ - return Object.freeze([Bootstrap.Core.Functions.call_property(x,'a'), Bootstrap.Core.Functions.call_property(x,'b')]); + return Object.freeze([Bootstrap.Core.Functions.call_property(x,'a'), Bootstrap.Core.Functions.call_property(x,'b')]); })); """ diff --git a/test/translator/capture_test.exs b/test/translator/capture_test.exs index c282dc86..ea61fc93 100644 --- a/test/translator/capture_test.exs +++ b/test/translator/capture_test.exs @@ -8,7 +8,7 @@ defmodule ElixirScript.Translator.Capture.Test do end js_code = """ - let [fun] = Bootstrap.Core.Patterns.match(Bootstrap.Core.Patterns.variable(),Elixir$ElixirScript$Kernel.is_atom); + let [fun] = Bootstrap.Core.Patterns.match(Bootstrap.Core.Patterns.variable(), Elixir.ElixirScript.Kernel.__load(Elixir).is_atom); """ assert_translation(ex_ast, js_code) @@ -23,7 +23,7 @@ defmodule ElixirScript.Translator.Capture.Test do js_code = """ let [fun] = Bootstrap.Core.Patterns.match(Bootstrap.Core.Patterns.variable(),Bootstrap.Core.Patterns.defmatch(Bootstrap.Core.Patterns.clause([Bootstrap.Core.Patterns.variable()],function(__1) { - return Elixir$ElixirScript$Kernel.is_atom(__1); + return Elixir.ElixirScript.Kernel.__load(Elixir).is_atom(__1); }))); """ diff --git a/test/translator/defmodule_test.exs b/test/translator/defmodule_test.exs index 4802cb12..acc965e7 100644 --- a/test/translator/defmodule_test.exs +++ b/test/translator/defmodule_test.exs @@ -130,7 +130,7 @@ defmodule ElixirScript.Translator.Defmodule.Test do end js_code = """ - Bootstrap.Core.Functions.call_property(Elixir$Lions$Tigers$Bears, 'oh_my'); + Elixir.Lions.Tigers.Bears.__load(Elixir).oh_my() """ assert_translation(ex_ast, js_code) diff --git a/test/translator/for_test.exs b/test/translator/for_test.exs index afecd45b..faec216e 100644 --- a/test/translator/for_test.exs +++ b/test/translator/for_test.exs @@ -177,7 +177,7 @@ defmodule ElixirScript.Translator.For.Test do Bootstrap.Core.Patterns.clause([Bootstrap.Core.Patterns.type(Bootstrap.Core.Tuple, { values: [Symbol.for('user'), Bootstrap.Core.Patterns.variable()] })], function(name) { - return Elixir$ElixirScript$String.upcase(name); + return Elixir.ElixirScript.String.__load(Elixir).upcase(name); }, function() { return true; }), diff --git a/test/translator/function_test.exs b/test/translator/function_test.exs index ef8331e1..00e25bec 100644 --- a/test/translator/function_test.exs +++ b/test/translator/function_test.exs @@ -134,7 +134,7 @@ defmodule ElixirScript.Translator.Function.Test do Taco.test1() end - js_code = "Bootstrap.Core.Functions.call_property(Elixir$Taco, 'test1')" + js_code = "Elixir.Taco.__load(Elixir).test1()" assert_translation(ex_ast, js_code) @@ -147,7 +147,7 @@ defmodule ElixirScript.Translator.Function.Test do Taco.test1(3, 2) end - js_code = "Elixir$Taco.test1(3,2)" + js_code = "Elixir.Taco.__load(Elixir).test1(3,2)" assert_translation(ex_ast, js_code) @@ -163,7 +163,7 @@ defmodule ElixirScript.Translator.Function.Test do Taco.test1(Taco.test2(1), 2) end - js_code = "Elixir$Taco.test1(Elixir$Taco.test2(1),2)" + js_code = "Elixir.Taco.__load(Elixir).test1(Elixir.Taco.__load(Elixir).test2(1), 2)" assert_translation(ex_ast, js_code) end @@ -277,7 +277,7 @@ defmodule ElixirScript.Translator.Function.Test do is_atom(:atom) end - js_code = "Elixir$ElixirScript$Kernel.is_atom(Symbol.for('atom'))" + js_code = "Elixir.ElixirScript.Kernel.__load(Elixir).is_atom(Symbol.for('atom'))" assert_translation(ex_ast, js_code) end @@ -293,7 +293,7 @@ defmodule ElixirScript.Translator.Function.Test do const something = Bootstrap.Core.Patterns.defmatch(Bootstrap.Core.Patterns.clause([Bootstrap.Core.Patterns.variable()],function(one) { return null; },function(one) { - return Elixir$ElixirScript$Kernel.is_number(one); + return Elixir.ElixirScript.Kernel.__load(Elixir).is_number(one); })); """ @@ -310,7 +310,7 @@ defmodule ElixirScript.Translator.Function.Test do const something = Bootstrap.Core.Patterns.defmatch(Bootstrap.Core.Patterns.clause([Bootstrap.Core.Patterns.variable()],function(one) { return null; },function(one) { - return Elixir$ElixirScript$Kernel.is_number(one) || Elixir$ElixirScript$Kernel.is_atom(one); + return Elixir.ElixirScript.Kernel.__load(Elixir).is_number(one) || Elixir.ElixirScript.Kernel.__load(Elixir).is_atom(one); })); """ @@ -326,7 +326,7 @@ defmodule ElixirScript.Translator.Function.Test do const something = Bootstrap.Core.Patterns.defmatch(Bootstrap.Core.Patterns.clause([Bootstrap.Core.Patterns.variable()],function(one) { return null; },function(one) { - return Elixir$ElixirScript$Kernel.is_number(one) || Elixir$ElixirScript$Kernel.is_atom(one); + return Elixir.ElixirScript.Kernel.__load(Elixir).is_number(one) || Elixir.ElixirScript.Kernel.__load(Elixir).is_atom(one); })); """ @@ -366,7 +366,7 @@ defmodule ElixirScript.Translator.Function.Test do }),Bootstrap.Core.Patterns.clause([Bootstrap.Core.Patterns.variable()],function(one) { return null; },function(one) { - return Elixir$ElixirScript$Kernel.is_number(one) || Elixir$ElixirScript$Kernel.is_atom(one); + return Elixir.ElixirScript.Kernel.__load(Elixir).is_number(one) || Elixir.ElixirScript.Kernel.__load(Elixir).is_atom(one); })); """ assert_translation(ex_ast, js_code) @@ -532,7 +532,7 @@ defmodule ElixirScript.Translator.Function.Test do })], function(value) { return null; }, function(value) { - return Elixir$ElixirScript$Kernel.is_number(value); + return Elixir.ElixirScript.Kernel.__load(Elixir).is_number(value); })); """ @@ -610,7 +610,7 @@ defmodule ElixirScript.Translator.Function.Test do }),Bootstrap.Core.Patterns.clause([Bootstrap.Core.Patterns.variable()],function(one) { return null; },function(one) { - return Elixir$ElixirScript$Kernel.is_binary(one); + return Elixir.ElixirScript.Kernel.__load(Elixir).is_binary(one); }),Bootstrap.Core.Patterns.clause([Bootstrap.Core.Patterns.variable()],function(one) { return null; })); @@ -800,7 +800,7 @@ defmodule ElixirScript.Translator.Function.Test do const something = Bootstrap.Core.Patterns.defmatch(Bootstrap.Core.Patterns.clause([Bootstrap.Core.Patterns.variable()],function(one) { return null; },function(one) { - return Elixir$ElixirScript$Kernel.is_number(one) || Elixir$ElixirScript$Kernel.is_atom(one); + return Elixir.ElixirScript.Kernel.__load(Elixir).is_number(one) || Elixir.ElixirScript.Kernel.__load(Elixir).is_atom(one); })); """ diff --git a/test/translator/kernel_test.exs b/test/translator/kernel_test.exs index c872b4e8..d0041050 100644 --- a/test/translator/kernel_test.exs +++ b/test/translator/kernel_test.exs @@ -12,7 +12,7 @@ defmodule ElixirScript.Translator.Kernel.Test do js_code = """ throw ArgumentError.create(Object.freeze({ - [Symbol.for('message')]: 'cannot convert list to string. The list must contain only integers, strings or nested such lists; got: ' + Elixir$ElixirScript$String$Chars.to_string(inspect(list)) + [Symbol.for('message')]: 'cannot convert list to string. The list must contain only integers, strings or nested such lists; got: ' + Elixir.ElixirScript.String.Chars.__load(Elixir).to_string(inspect(list)) })); """ @@ -41,7 +41,7 @@ defmodule ElixirScript.Translator.Kernel.Test do end js_code = """ - Elixir$ElixirScript$Kernel.max(1, 2) + Elixir.ElixirScript.Kernel.__load(Elixir).max(1, 2) """ assert_translation(ex_ast, js_code) @@ -54,7 +54,7 @@ defmodule ElixirScript.Translator.Kernel.Test do end js_code = """ - Elixir$ElixirScript$Kernel.apply(Enum,Symbol.for('reverse'),Object.freeze([Object.freeze([1, 2, 3])])) + Elixir.ElixirScript.Kernel.__load(Elixir).apply(Enum, Symbol.for('reverse'), Object.freeze([Object.freeze([1, 2, 3])])) """ assert_translation(ex_ast, js_code) @@ -67,7 +67,7 @@ defmodule ElixirScript.Translator.Kernel.Test do end js_code = """ - Elixir$ElixirScript$Kernel.hd(Object.freeze([1, 2, 3])) + Elixir.ElixirScript.Kernel.__load(Elixir).hd(Object.freeze([1, 2, 3])) """ assert_translation(ex_ast, js_code) @@ -80,7 +80,7 @@ defmodule ElixirScript.Translator.Kernel.Test do end js_code = """ - Elixir$ElixirScript$Kernel.tl(Object.freeze([1, 2, 3])) + Elixir.ElixirScript.Kernel.__load(Elixir).tl(Object.freeze([1, 2, 3])) """ assert_translation(ex_ast, js_code) diff --git a/test/translator/string_test.exs b/test/translator/string_test.exs index 16d3d6b9..3eb79606 100644 --- a/test/translator/string_test.exs +++ b/test/translator/string_test.exs @@ -22,22 +22,22 @@ defmodule ElixirScript.Translator.String.Test do test "translate string interpolation" do ex_ast = quote do: "Hello #{"world"}" - assert_translation(ex_ast, "'Hello ' + Elixir$ElixirScript$String$Chars.to_string('world')") + assert_translation(ex_ast, "'Hello ' + Elixir.ElixirScript.String.Chars.__load(Elixir).to_string('world')") ex_ast = quote do: "Hello #{length([])}" - assert_translation(ex_ast, "'Hello ' + Elixir$ElixirScript$String$Chars.to_string(Elixir$ElixirScript$Kernel.length(Object.freeze([])))") + assert_translation(ex_ast, "'Hello ' + Elixir.ElixirScript.String.Chars.__load(Elixir).to_string(Elixir.ElixirScript.Kernel.__load(Elixir).length(Object.freeze([])))") end test "translate multiline string interpolation" do ex_ast = quote do: """ Hello #{length([])} """ - assert_translation(ex_ast, "'Hello ' + (Elixir$ElixirScript$String$Chars.to_string(Elixir$ElixirScript$Kernel.length(Object.freeze([]))) + '\\n')") + assert_translation(ex_ast, "'Hello ' + (Elixir.ElixirScript.String.Chars.__load(Elixir).to_string(Elixir.ElixirScript.Kernel.__load(Elixir).length(Object.freeze([]))) + '\\n')") ex_ast = quote do: """ Hello #{length([])} How are you, #{length([])}? """ - assert_translation(ex_ast, "'Hello ' + (Elixir$ElixirScript$String$Chars.to_string(Elixir$ElixirScript$Kernel.length(Object.freeze([]))) + ('\\nHow are you, ' + (Elixir$ElixirScript$String$Chars.to_string(Elixir$ElixirScript$Kernel.length(Object.freeze([]))) + '?\\n')))") + assert_translation(ex_ast, "'Hello ' + (Elixir.ElixirScript.String.Chars.__load(Elixir).to_string(Elixir.ElixirScript.Kernel.__load(Elixir).length(Object.freeze([]))) + ('\\nHow are you, ' + (Elixir.ElixirScript.String.Chars.__load(Elixir).to_string(Elixir.ElixirScript.Kernel.__load(Elixir).length(Object.freeze([]))) + '?\\n')))") end end diff --git a/test/translator/with_test.exs b/test/translator/with_test.exs index c2d9322b..74133f03 100644 --- a/test/translator/with_test.exs +++ b/test/translator/with_test.exs @@ -14,11 +14,11 @@ defmodule ElixirScript.Translator.With.Test do Bootstrap.Core.SpecialForms._with([Bootstrap.Core.Patterns.type(Bootstrap.Core.Tuple,{ values: [Symbol.for('ok'), Bootstrap.Core.Patterns.variable()] }), function() { - return Elixir$ElixirScript$Map.fetch(opts,Symbol.for('width')); + return Elixir.ElixirScript.Map.__load(Elixir).fetch(opts,Symbol.for('width')); }],[Bootstrap.Core.Patterns.type(Bootstrap.Core.Tuple,{ values: [Symbol.for('ok'), Bootstrap.Core.Patterns.variable()] }), function(width) { - return Elixir$ElixirScript$Map.fetch(opts,Symbol.for('height')); + return Elixir.ElixirScript.Map.__load(Elixir).fetch(opts,Symbol.for('height')); }],function(width,height) { return new Bootstrap.Core.Tuple(Symbol.for('ok'),width * height); }) @@ -40,13 +40,13 @@ defmodule ElixirScript.Translator.With.Test do Bootstrap.Core.SpecialForms._with([Bootstrap.Core.Patterns.type(Bootstrap.Core.Tuple,{ values: [Symbol.for('ok'), Bootstrap.Core.Patterns.variable()] }), function() { - return Elixir$ElixirScript$Map.fetch(opts,Symbol.for('width')); + return Elixir.ElixirScript.Map.__load(Elixir).fetch(opts,Symbol.for('width')); }],[Bootstrap.Core.Patterns.variable(), function(width) { return width * 2; }],[Bootstrap.Core.Patterns.type(Bootstrap.Core.Tuple,{ values: [Symbol.for('ok'), Bootstrap.Core.Patterns.variable()] }), function(width,double_width) { - return Elixir$ElixirScript$Map.fetch(opts,Symbol.for('height')); + return Elixir.ElixirScript.Map.__load(Elixir).fetch(opts,Symbol.for('height')); }],function(width,double_width,height) { return new Bootstrap.Core.Tuple(Symbol.for('ok'),double_width * height); }) @@ -70,11 +70,11 @@ defmodule ElixirScript.Translator.With.Test do Bootstrap.Core.SpecialForms._with([Bootstrap.Core.Patterns.type(Bootstrap.Core.Tuple,{ values: [Symbol.for('ok'), Bootstrap.Core.Patterns.variable()] }), function() { - return Elixir$ElixirScript$Map.fetch(opts,Symbol.for('width')); + return Elixir.ElixirScript.Map.__load(Elixir).fetch(opts,Symbol.for('width')); }],[Bootstrap.Core.Patterns.type(Bootstrap.Core.Tuple,{ values: [Symbol.for('ok'), Bootstrap.Core.Patterns.variable()] }), function(width) { - return Elixir$ElixirScript$Map.fetch(opts,Symbol.for('height')); + return Elixir.ElixirScript.Map.__load(Elixir).fetch(opts,Symbol.for('height')); }],function(width,height) { return new Bootstrap.Core.Tuple(Symbol.for('ok'),width * height); },Bootstrap.Core.Patterns.defmatch(Bootstrap.Core.Patterns.clause([Symbol.for('error')],function() { From 362b04b60cdec7630eab15c613e378cd992d7b36 Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Sat, 25 Feb 2017 15:46:48 -0600 Subject: [PATCH 434/860] Update struct translation to call modules directly --- .../passes/consolidate_protocols.ex | 2 +- .../translator/kernel/special_forms/call.ex | 121 ------------------ .../translator/kernel/special_forms/struct.ex | 12 +- test/prelude/kernel_test.exs | 2 +- test/translator/function_test.exs | 8 +- test/translator/struct_test.exs | 2 +- 6 files changed, 17 insertions(+), 130 deletions(-) diff --git a/lib/elixir_script/passes/consolidate_protocols.ex b/lib/elixir_script/passes/consolidate_protocols.ex index 2f0a5abe..df57a70d 100644 --- a/lib/elixir_script/passes/consolidate_protocols.ex +++ b/lib/elixir_script/passes/consolidate_protocols.ex @@ -70,7 +70,7 @@ defmodule ElixirScript.Passes.ConsolidateProtocols do body = Enum.map(implementations, fn({_, impl_data}) -> x = Utils.quoted_to_name(impl_data.for) - members = ["Elixir"] ++ Module.split(name) ++ ["DefImpl"] ++ Module.split(x) ++ ["__load"] + members = ["Elixir"] ++ Module.split(name) ++ ["DefImpl", "Elixir"] ++ Module.split(x) ++ ["__load"] ast = JS.call_expression( Identifier.make_namespace_members(members), [JS.identifier("Elixir")] diff --git a/lib/elixir_script/translator/kernel/special_forms/call.ex b/lib/elixir_script/translator/kernel/special_forms/call.ex index 65ce4c3f..9225c00d 100644 --- a/lib/elixir_script/translator/kernel/special_forms/call.ex +++ b/lib/elixir_script/translator/kernel/special_forms/call.ex @@ -110,25 +110,6 @@ defmodule ElixirScript.Translator.Call do { js_ast, env } end - - def get_module_name_for_function(module_name, env) do - case module_name do - {:__aliases__, _, name} -> - module_name = Utils.quoted_to_name(name) - get_js_name(module_name, env) - {name, _, _} when is_atom(name) -> - get_js_name(name, env) - {{:., _, [_, _]}, _, _ } = ast -> - ast - {{:., _, [{:__aliases__, _, _}]}, _, _} = ast -> - ast - ast when is_list(ast) -> - ast - name -> - get_js_name(name, env) - end - end - def make_function_call(module_name, function_name, [], env) when is_atom(module_name) and is_atom(function_name) do js_ast = JS.call_expression( JS.member_expression( @@ -227,106 +208,4 @@ defmodule ElixirScript.Translator.Call do { call, env } end - - def get_js_name([Elixir | _] = list, _) do - list - end - - def get_js_name({:__aliases__, _, _} = name, env) do - Utils.quoted_to_name(name) - |> get_js_name(env) - end - - def get_js_name(module_name, env) when is_list(module_name) do - Utils.quoted_to_name({:__aliases__, [], module_name}) - |> get_js_name(env) - end - - def get_js_name(module_name, env) do - - cond do - module_name in env.requires -> - Utils.name_to_js_name(module_name) - - module_name in ElixirScript.Translator.State.list_module_names(env.state) -> - ElixirScript.Translator.State.add_module_reference(env.state, env.module, module_name) - Utils.name_to_js_name(module_name) - - true -> - case Atom.to_string(module_name) do - "Elixir." <> _ -> - {:__aliases__, _, name } = Utils.name_to_quoted(module_name) - name - _ -> - module_name - end - end - end - - defp make_member_expression(module_name, function_name, env, computed \\ false) do - case module_name do - modules when is_list(modules) and length(modules) > 1 -> - ast = make_module_expression_tree(modules, computed, env) - JS.member_expression( - ast, - Identifier.make_identifier(function_name), - computed - ) - modules when is_list(modules) and length(modules) == 1 -> - JS.member_expression( - Identifier.make_identifier(hd(modules)), - Identifier.make_identifier(function_name), - computed - ) - {{:., _, [_module_name, _function_name]}, _, _params } = ast -> - JS.member_expression( - Translator.translate!(ast, env), - Identifier.make_identifier(function_name), - computed - ) - {{:., _, [{:__aliases__, _, _}]}, _, _} = ast -> - JS.member_expression( - Translator.translate!(ast, env), - Identifier.make_identifier(function_name), - computed - ) - {:., _, _} = ast -> - JS.member_expression( - Translator.translate!(ast, env), - Identifier.make_identifier(function_name), - computed - ) - _ -> - JS.member_expression( - Identifier.make_identifier(module_name), - Identifier.make_identifier(function_name), - computed - ) - end - end - - defp make_module_expression_tree([module], computed, env) do - make_module_expression_tree(module, computed, env) - end - - defp make_module_expression_tree(modules, computed, _) when is_list(modules) do - Enum.reduce(modules, nil, fn(x, ast) -> - case ast do - nil -> - JS.member_expression(Identifier.make_identifier(x), nil, computed) - %ESTree.MemberExpression{ property: nil } -> - %{ ast | property: Identifier.make_identifier(x) } - _ -> - JS.member_expression(ast, Identifier.make_identifier(x), computed) - end - end) - end - - defp make_module_expression_tree(module, _, _) when is_binary(module) or is_atom(module) do - Identifier.make_identifier(module) - end - - defp make_module_expression_tree(module, _, env) do - Translator.translate!(module, env) - end end diff --git a/lib/elixir_script/translator/kernel/special_forms/struct.ex b/lib/elixir_script/translator/kernel/special_forms/struct.ex index b1123545..84c5becb 100644 --- a/lib/elixir_script/translator/kernel/special_forms/struct.ex +++ b/lib/elixir_script/translator/kernel/special_forms/struct.ex @@ -13,12 +13,20 @@ defmodule ElixirScript.Translator.Struct do name = ElixirScript.Translator.LexicalScope.get_module_name(env, candiate_module_name) ident = JS.identifier(Utils.name_to_js_name(name)) ElixirScript.Translator.State.add_module_reference(env.state, env.module, name) - JS.member_expression(ident, ident) + + members = ["Elixir"] ++ Module.split(name) ++ ["__load"] + + JS.member_expression( + JS.call_expression( + Identifier.make_namespace_members(members), + [JS.identifier("Elixir")] + ), + ident + ) else Identifier.make_identifier(module_name) end - end def new_struct(module_name, data, env) do diff --git a/test/prelude/kernel_test.exs b/test/prelude/kernel_test.exs index 251e2e5a..c080a158 100644 --- a/test/prelude/kernel_test.exs +++ b/test/prelude/kernel_test.exs @@ -9,7 +9,7 @@ defmodule ElixirScript.Lib.Elixir.Kernel.Test do js_code = """ - Elixir$ElixirScript$Range.Elixir$ElixirScript$Range.create(Object.freeze({ + Elixir.ElixirScript.Range.__load(Elixir).Elixir$ElixirScript$Range.create(Object.freeze({ [Symbol.for('first')]: 1, [Symbol.for('last')]: 4 })) diff --git a/test/translator/function_test.exs b/test/translator/function_test.exs index 00e25bec..77748810 100644 --- a/test/translator/function_test.exs +++ b/test/translator/function_test.exs @@ -451,7 +451,7 @@ defmodule ElixirScript.Translator.Function.Test do js_code = """ - const something = Bootstrap.Core.Patterns.defmatch(Bootstrap.Core.Patterns.clause([Bootstrap.Core.Patterns.type(Elixir$AStruct.Elixir$AStruct, {})], function() { + const something = Bootstrap.Core.Patterns.defmatch(Bootstrap.Core.Patterns.clause([Bootstrap.Core.Patterns.type(Elixir.AStruct.__load(Elixir).Elixir$AStruct, {})], function() { return null; })); """ @@ -471,7 +471,7 @@ defmodule ElixirScript.Translator.Function.Test do end js_code = """ - const something = Bootstrap.Core.Patterns.defmatch(Bootstrap.Core.Patterns.clause([Bootstrap.Core.Patterns.capture(Bootstrap.Core.Patterns.type(Elixir$AStruct.Elixir$AStruct, {}))], function(a) { + const something = Bootstrap.Core.Patterns.defmatch(Bootstrap.Core.Patterns.clause([Bootstrap.Core.Patterns.capture(Bootstrap.Core.Patterns.type(Elixir.AStruct.__load(Elixir).Elixir$AStruct, {}))], function(a) { return null; })); """ @@ -507,7 +507,7 @@ defmodule ElixirScript.Translator.Function.Test do js_code = """ - const something = Bootstrap.Core.Patterns.defmatch(Bootstrap.Core.Patterns.clause([Bootstrap.Core.Patterns.type(Elixir$AStruct.Elixir$AStruct, { + const something = Bootstrap.Core.Patterns.defmatch(Bootstrap.Core.Patterns.clause([Bootstrap.Core.Patterns.type(Elixir.AStruct.__load(Elixir).Elixir$AStruct, { [Symbol.for('key')]: Bootstrap.Core.Patterns.variable(), [Symbol.for('key1')]: 2 })], function(value) { return null; @@ -527,7 +527,7 @@ defmodule ElixirScript.Translator.Function.Test do js_code = """ - const something = Bootstrap.Core.Patterns.defmatch(Bootstrap.Core.Patterns.clause([Bootstrap.Core.Patterns.type(Elixir$AStruct.Elixir$AStruct, { + const something = Bootstrap.Core.Patterns.defmatch(Bootstrap.Core.Patterns.clause([Bootstrap.Core.Patterns.type(Elixir.AStruct.__load(Elixir).Elixir$AStruct, { [Symbol.for('key')]: Bootstrap.Core.Patterns.variable(), [Symbol.for('key1')]: 2 })], function(value) { return null; diff --git a/test/translator/struct_test.exs b/test/translator/struct_test.exs index 3e1745b1..dcc07631 100644 --- a/test/translator/struct_test.exs +++ b/test/translator/struct_test.exs @@ -156,7 +156,7 @@ defmodule ElixirScript.Translator.Struct.Test do end js_code = """ - throw Elixir$MyAppError.Elixir$MyAppError.create(Object.freeze({ + throw Elixir.MyAppError.__load(Elixir).Elixir$MyAppError.create(Object.freeze({ [Symbol.for('message')]: 'did not get what was expected' })); """ From 188f1c0cb780cdc0bfb759cb0f96b0616ed25753 Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Sun, 26 Feb 2017 06:56:58 -0600 Subject: [PATCH 435/860] Remove import_standard_libs option from compile_quoted --- lib/elixir_script.ex | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/elixir_script.ex b/lib/elixir_script.ex index b80de898..044aac76 100644 --- a/lib/elixir_script.ex +++ b/lib/elixir_script.ex @@ -65,7 +65,7 @@ defmodule ElixirScript do @spec compile_quoted(Macro.t, Map.t) :: [binary | {binary, binary} | :ok] def compile_quoted(quoted, opts \\ %{}) do - opts = build_compiler_options(Map.merge(opts, %{import_standard_libs: false})) + opts = build_compiler_options(opts) data = quoted |> get_modules_from_quoted From 6e82a0fd5a57c83a49f228e5cdaf0aff465505bd Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Sun, 26 Feb 2017 12:13:28 -0600 Subject: [PATCH 436/860] Bundle Bootstrap js into output --- lib/elixir_script.ex | 10 +- .../passes/consolidate_protocols.ex | 1 - lib/elixir_script/passes/create_js_modules.ex | 2 +- lib/elixir_script/passes/handle_output.ex | 18 +- lib/mix/tasks/compile.elixir_script.ex | 2 +- package.json | 10 +- rollup.config.js | 8 +- test/translator/umd_test.exs | 6 +- yarn.lock | 2885 +++++++++++++++++ 9 files changed, 2916 insertions(+), 26 deletions(-) create mode 100644 yarn.lock diff --git a/lib/elixir_script.ex b/lib/elixir_script.ex index 044aac76..f9b4b2ac 100644 --- a/lib/elixir_script.ex +++ b/lib/elixir_script.ex @@ -205,12 +205,20 @@ defmodule ElixirScript do ElixirScript.ModuleSystems.ES end + @doc """ + Returns the contents of the bootrstrap js file + """ + def get_bootstrap_js(module_format) do + path = Path.join([operating_path, "build", to_string(module_format),"Elixir.Bootstrap.js"]) + File.read!(path) + end + @doc """ Copies the javascript that makes up the ElixirScript bootstrap to the specified location """ def copy_bootstrap_to_destination(module_format, destination) do - path = Path.join([operating_path, to_string(module_format), "elixir", "Elixir.Bootstrap.js"]) + path = Path.join([operating_path, "build", to_string(module_format),"Elixir.Bootstrap.js"]) base = Path.basename(path) File.mkdir_p!(destination) File.cp!(path, Path.join([destination, base])) diff --git a/lib/elixir_script/passes/consolidate_protocols.ex b/lib/elixir_script/passes/consolidate_protocols.ex index df57a70d..f0c40d2b 100644 --- a/lib/elixir_script/passes/consolidate_protocols.ex +++ b/lib/elixir_script/passes/consolidate_protocols.ex @@ -90,7 +90,6 @@ defmodule ElixirScript.Passes.ConsolidateProtocols do module_data = %{ name: name, module: String.to_atom(protocol_name <> ".DefImpl"), - std_lib: {:Elixir, Utils.make_local_file_path(:elixir, compiler_opts.core_path, compiler_opts.root, nil)}, body: [declaration] ++ body, exports: JS.identifier("impls"), app: app_name, diff --git a/lib/elixir_script/passes/create_js_modules.ex b/lib/elixir_script/passes/create_js_modules.ex index 8de02be2..0986ae7c 100644 --- a/lib/elixir_script/passes/create_js_modules.ex +++ b/lib/elixir_script/passes/create_js_modules.ex @@ -94,7 +94,7 @@ defmodule ElixirScript.Passes.CreateJSModules do ast = opts.module_formatter.build( [], - [{"Bootstrap", "./Elixir.Bootstrap", default: true }] ++ opts.js_modules, + opts.js_modules, [elixir, start] ++ body, JS.identifier("Elixir") ) diff --git a/lib/elixir_script/passes/handle_output.ex b/lib/elixir_script/passes/handle_output.ex index 382eb2e8..56512ac8 100644 --- a/lib/elixir_script/passes/handle_output.ex +++ b/lib/elixir_script/passes/handle_output.ex @@ -17,24 +17,26 @@ defmodule ElixirScript.Passes.HandleOutput do out = compiler_output |> process_include_path(compiler_opts) - case out do - {code, _} -> IO.write(code) - code -> IO.write(code) + code = case out do + {code, _} -> code + code -> code end + + IO.write(concat(code)) end defp out(compiler_output, %{output: output_path, core_path: _} = compiler_opts) do - if Map.get(compiler_opts, :std_lib, false) == false do - ElixirScript.copy_bootstrap_to_destination(compiler_opts.format, output_path) - end - file_name = Path.join([output_path, @generated_name]) if !File.exists?(Path.dirname(file_name)) do File.mkdir_p!(Path.dirname(file_name)) end - File.write!(file_name, compiler_output.generated) + File.write!(file_name, concat(compiler_output.generated)) + end + + defp concat(code) do + "'use strict';\n" <> ElixirScript.get_bootstrap_js("iife") <> "\n" <> code end defp process_include_path(compiler_output, compiler_opts) do diff --git a/lib/mix/tasks/compile.elixir_script.ex b/lib/mix/tasks/compile.elixir_script.ex index b9c6a238..b784afb1 100644 --- a/lib/mix/tasks/compile.elixir_script.ex +++ b/lib/mix/tasks/compile.elixir_script.ex @@ -73,7 +73,7 @@ defmodule Mix.Tasks.Compile.ElixirScript do output_path |> File.ls! |> Enum.each(fn(x) -> - if String.contains?(Path.basename(x), "Elixir.") do + if String.contains?(Path.basename(x), "Elixir.App.js") do File.rm!(Path.join(output_path, x)) end end) diff --git a/package.json b/package.json index 3176dd63..efbbd8d5 100644 --- a/package.json +++ b/package.json @@ -9,10 +9,7 @@ "scripts": { "lint": "eslint src/javascript/lib/**/*.js src/javascript/tests/**/*.js", "lint:fix": "eslint src/javascript/lib/**/*.js src/javascript/tests/**/*.js --fix", - "build": "npm run build:es && npm run build:umd && npm run build:common", - "build:es": "rollup -c rollup.config.js", - "build:umd": "rollup -c rollup.config.js -f umd -o priv/umd/elixir/Elixir.Bootstrap.js", - "build:common": "rollup -c rollup.config.js -f cjs -o priv/common/elixir/Elixir.Bootstrap.js", + "build": "rollup -c rollup.config.js", "clean": "rm -rf priv", "test": "mocha src/javascript/tests --recursive --compilers js:babel-core/register" }, @@ -44,6 +41,7 @@ "mocha": "^2.4.5", "rollup": "^0.41.4", "rollup-plugin-babel": "^2.7.1", - "rollup-plugin-node-resolve": "^2.0.0" + "rollup-plugin-node-resolve": "^2.0.0", + "rollup-plugin-uglify": "^1.0.1" } -} \ No newline at end of file +} diff --git a/rollup.config.js b/rollup.config.js index 4bf6303d..6e2312d3 100644 --- a/rollup.config.js +++ b/rollup.config.js @@ -3,14 +3,12 @@ import babel from "rollup-plugin-babel"; export default { entry: "src/javascript/elixir.js", - dest: "priv/es/elixir/Elixir.Bootstrap.js", - sourceMap: "inline", - format: "es", - moduleName: "Elixir.Bootstrap", + moduleName: "Bootstrap", plugins: [ nodeResolve({ jsnext: true }), babel({ babelrc: false }) - ] + ], + targets: [{ dest: "priv/build/iife/Elixir.Bootstrap.js", format: "iife" }] }; diff --git a/test/translator/umd_test.exs b/test/translator/umd_test.exs index b841baef..1a390e36 100644 --- a/test/translator/umd_test.exs +++ b/test/translator/umd_test.exs @@ -16,11 +16,11 @@ defmodule ElixirScript.Translator.UMD.Test do js_code = """ (function(root, factory) { if (typeof define === 'function' && define.amd) { - define(['./Elixir.Bootstrap'], factory) + define([], factory) } else if (typeof exports === 'object') { - module.exports = factory(require('./Elixir.Bootstrap')) + module.exports = factory() } else { - root.returnExports = factory(root.Bootstrap) + root.returnExports = factory() } """ diff --git a/yarn.lock b/yarn.lock new file mode 100644 index 00000000..57960d44 --- /dev/null +++ b/yarn.lock @@ -0,0 +1,2885 @@ +# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. +# yarn lockfile v1 + + +acorn-jsx@^3.0.0: + version "3.0.1" + resolved "https://registry.yarnpkg.com/acorn-jsx/-/acorn-jsx-3.0.1.tgz#afdf9488fb1ecefc8348f6fb22f464e32a58b36b" + dependencies: + acorn "^3.0.4" + +acorn@4.0.4: + version "4.0.4" + resolved "https://registry.yarnpkg.com/acorn/-/acorn-4.0.4.tgz#17a8d6a7a6c4ef538b814ec9abac2779293bf30a" + +acorn@4.X: + version "4.0.11" + resolved "https://registry.yarnpkg.com/acorn/-/acorn-4.0.11.tgz#edcda3bd937e7556410d42ed5860f67399c794c0" + +acorn@^3.0.4: + version "3.3.0" + resolved "https://registry.yarnpkg.com/acorn/-/acorn-3.3.0.tgz#45e37fb39e8da3f25baee3ff5369e2bb5f22017a" + +ajv-keywords@^1.0.0: + version "1.5.1" + resolved "https://registry.yarnpkg.com/ajv-keywords/-/ajv-keywords-1.5.1.tgz#314dd0a4b3368fad3dfcdc54ede6171b886daf3c" + +ajv@^4.7.0: + version "4.11.3" + resolved "https://registry.yarnpkg.com/ajv/-/ajv-4.11.3.tgz#ce30bdb90d1254f762c75af915fb3a63e7183d22" + dependencies: + co "^4.6.0" + json-stable-stringify "^1.0.1" + +align-text@^0.1.1, align-text@^0.1.3: + version "0.1.4" + resolved "https://registry.yarnpkg.com/align-text/-/align-text-0.1.4.tgz#0cd90a561093f35d0a99256c22b7069433fad117" + dependencies: + kind-of "^3.0.2" + longest "^1.0.1" + repeat-string "^1.5.2" + +amdefine@>=0.0.4: + version "1.0.1" + resolved "https://registry.yarnpkg.com/amdefine/-/amdefine-1.0.1.tgz#4a5282ac164729e93619bcfd3ad151f817ce91f5" + +ansi-escapes@^1.1.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/ansi-escapes/-/ansi-escapes-1.4.0.tgz#d3a8a83b319aa67793662b13e761c7911422306e" + +ansi-regex@^2.0.0: + version "2.1.1" + resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-2.1.1.tgz#c3b33ab5ee360d86e0e628f0468ae7ef27d654df" + +ansi-styles@^2.2.1: + version "2.2.1" + resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-2.2.1.tgz#b432dd3358b634cf75e1e4664368240533c1ddbe" + +archy@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/archy/-/archy-1.0.0.tgz#f9c8c13757cc1dd7bc379ac77b2c62a5c2868c40" + +argparse@^1.0.7: + version "1.0.9" + resolved "https://registry.yarnpkg.com/argparse/-/argparse-1.0.9.tgz#73d83bc263f86e97f8cc4f6bae1b0e90a7d22c86" + dependencies: + sprintf-js "~1.0.2" + +arr-diff@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/arr-diff/-/arr-diff-2.0.0.tgz#8f3b827f955a8bd669697e4a4256ac3ceae356cf" + dependencies: + arr-flatten "^1.0.1" + +arr-flatten@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/arr-flatten/-/arr-flatten-1.0.1.tgz#e5ffe54d45e19f32f216e91eb99c8ce892bb604b" + +array-differ@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/array-differ/-/array-differ-1.0.0.tgz#eff52e3758249d33be402b8bb8e564bb2b5d4031" + +array-union@^1.0.1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/array-union/-/array-union-1.0.2.tgz#9a34410e4f4e3da23dea375be5be70f24778ec39" + dependencies: + array-uniq "^1.0.1" + +array-uniq@^1.0.1, array-uniq@^1.0.2: + version "1.0.3" + resolved "https://registry.yarnpkg.com/array-uniq/-/array-uniq-1.0.3.tgz#af6ac877a25cc7f74e058894753858dfdb24fdb6" + +array-unique@^0.2.1: + version "0.2.1" + resolved "https://registry.yarnpkg.com/array-unique/-/array-unique-0.2.1.tgz#a1d97ccafcbc2625cc70fadceb36a50c58b01a53" + +arrify@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/arrify/-/arrify-1.0.1.tgz#898508da2226f380df904728456849c1501a4b0d" + +assertion-error@^1.0.1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/assertion-error/-/assertion-error-1.0.2.tgz#13ca515d86206da0bac66e834dd397d87581094c" + +async@~0.2.6: + version "0.2.10" + resolved "https://registry.yarnpkg.com/async/-/async-0.2.10.tgz#b6bbe0b0674b9d719708ca38de8c237cb526c3d1" + +atob@~1.1.0: + version "1.1.3" + resolved "https://registry.yarnpkg.com/atob/-/atob-1.1.3.tgz#95f13629b12c3a51a5d215abdce2aa9f32f80773" + +babel-code-frame@^6.16.0, babel-code-frame@^6.22.0: + version "6.22.0" + resolved "https://registry.yarnpkg.com/babel-code-frame/-/babel-code-frame-6.22.0.tgz#027620bee567a88c32561574e7fd0801d33118e4" + dependencies: + chalk "^1.1.0" + esutils "^2.0.2" + js-tokens "^3.0.0" + +babel-core@6, babel-core@^6.0.2, babel-core@^6.23.0, babel-core@^6.7.7: + version "6.23.1" + resolved "https://registry.yarnpkg.com/babel-core/-/babel-core-6.23.1.tgz#c143cb621bb2f621710c220c5d579d15b8a442df" + dependencies: + babel-code-frame "^6.22.0" + babel-generator "^6.23.0" + babel-helpers "^6.23.0" + babel-messages "^6.23.0" + babel-register "^6.23.0" + babel-runtime "^6.22.0" + babel-template "^6.23.0" + babel-traverse "^6.23.1" + babel-types "^6.23.0" + babylon "^6.11.0" + convert-source-map "^1.1.0" + debug "^2.1.1" + json5 "^0.5.0" + lodash "^4.2.0" + minimatch "^3.0.2" + path-is-absolute "^1.0.0" + private "^0.1.6" + slash "^1.0.0" + source-map "^0.5.0" + +babel-generator@^6.23.0: + version "6.23.0" + resolved "https://registry.yarnpkg.com/babel-generator/-/babel-generator-6.23.0.tgz#6b8edab956ef3116f79d8c84c5a3c05f32a74bc5" + dependencies: + babel-messages "^6.23.0" + babel-runtime "^6.22.0" + babel-types "^6.23.0" + detect-indent "^4.0.0" + jsesc "^1.3.0" + lodash "^4.2.0" + source-map "^0.5.0" + trim-right "^1.0.1" + +babel-helper-bindify-decorators@^6.22.0: + version "6.22.0" + resolved "https://registry.yarnpkg.com/babel-helper-bindify-decorators/-/babel-helper-bindify-decorators-6.22.0.tgz#d7f5bc261275941ac62acfc4e20dacfb8a3fe952" + dependencies: + babel-runtime "^6.22.0" + babel-traverse "^6.22.0" + babel-types "^6.22.0" + +babel-helper-builder-binary-assignment-operator-visitor@^6.22.0: + version "6.22.0" + resolved "https://registry.yarnpkg.com/babel-helper-builder-binary-assignment-operator-visitor/-/babel-helper-builder-binary-assignment-operator-visitor-6.22.0.tgz#29df56be144d81bdeac08262bfa41d2c5e91cdcd" + dependencies: + babel-helper-explode-assignable-expression "^6.22.0" + babel-runtime "^6.22.0" + babel-types "^6.22.0" + +babel-helper-builder-react-jsx@^6.23.0: + version "6.23.0" + resolved "https://registry.yarnpkg.com/babel-helper-builder-react-jsx/-/babel-helper-builder-react-jsx-6.23.0.tgz#d53fc8c996e0bc56d0de0fc4cc55a7138395ea4b" + dependencies: + babel-runtime "^6.22.0" + babel-types "^6.23.0" + esutils "^2.0.0" + lodash "^4.2.0" + +babel-helper-call-delegate@^6.22.0: + version "6.22.0" + resolved "https://registry.yarnpkg.com/babel-helper-call-delegate/-/babel-helper-call-delegate-6.22.0.tgz#119921b56120f17e9dae3f74b4f5cc7bcc1b37ef" + dependencies: + babel-helper-hoist-variables "^6.22.0" + babel-runtime "^6.22.0" + babel-traverse "^6.22.0" + babel-types "^6.22.0" + +babel-helper-define-map@^6.23.0: + version "6.23.0" + resolved "https://registry.yarnpkg.com/babel-helper-define-map/-/babel-helper-define-map-6.23.0.tgz#1444f960c9691d69a2ced6a205315f8fd00804e7" + dependencies: + babel-helper-function-name "^6.23.0" + babel-runtime "^6.22.0" + babel-types "^6.23.0" + lodash "^4.2.0" + +babel-helper-explode-assignable-expression@^6.22.0: + version "6.22.0" + resolved "https://registry.yarnpkg.com/babel-helper-explode-assignable-expression/-/babel-helper-explode-assignable-expression-6.22.0.tgz#c97bf76eed3e0bae4048121f2b9dae1a4e7d0478" + dependencies: + babel-runtime "^6.22.0" + babel-traverse "^6.22.0" + babel-types "^6.22.0" + +babel-helper-explode-class@^6.22.0: + version "6.22.0" + resolved "https://registry.yarnpkg.com/babel-helper-explode-class/-/babel-helper-explode-class-6.22.0.tgz#646304924aa6388a516843ba7f1855ef8dfeb69b" + dependencies: + babel-helper-bindify-decorators "^6.22.0" + babel-runtime "^6.22.0" + babel-traverse "^6.22.0" + babel-types "^6.22.0" + +babel-helper-function-name@^6.22.0, babel-helper-function-name@^6.23.0: + version "6.23.0" + resolved "https://registry.yarnpkg.com/babel-helper-function-name/-/babel-helper-function-name-6.23.0.tgz#25742d67175c8903dbe4b6cb9d9e1fcb8dcf23a6" + dependencies: + babel-helper-get-function-arity "^6.22.0" + babel-runtime "^6.22.0" + babel-template "^6.23.0" + babel-traverse "^6.23.0" + babel-types "^6.23.0" + +babel-helper-get-function-arity@^6.22.0: + version "6.22.0" + resolved "https://registry.yarnpkg.com/babel-helper-get-function-arity/-/babel-helper-get-function-arity-6.22.0.tgz#0beb464ad69dc7347410ac6ade9f03a50634f5ce" + dependencies: + babel-runtime "^6.22.0" + babel-types "^6.22.0" + +babel-helper-hoist-variables@^6.22.0: + version "6.22.0" + resolved "https://registry.yarnpkg.com/babel-helper-hoist-variables/-/babel-helper-hoist-variables-6.22.0.tgz#3eacbf731d80705845dd2e9718f600cfb9b4ba72" + dependencies: + babel-runtime "^6.22.0" + babel-types "^6.22.0" + +babel-helper-optimise-call-expression@^6.23.0: + version "6.23.0" + resolved "https://registry.yarnpkg.com/babel-helper-optimise-call-expression/-/babel-helper-optimise-call-expression-6.23.0.tgz#f3ee7eed355b4282138b33d02b78369e470622f5" + dependencies: + babel-runtime "^6.22.0" + babel-types "^6.23.0" + +babel-helper-regex@^6.22.0: + version "6.22.0" + resolved "https://registry.yarnpkg.com/babel-helper-regex/-/babel-helper-regex-6.22.0.tgz#79f532be1647b1f0ee3474b5f5c3da58001d247d" + dependencies: + babel-runtime "^6.22.0" + babel-types "^6.22.0" + lodash "^4.2.0" + +babel-helper-remap-async-to-generator@^6.22.0: + version "6.22.0" + resolved "https://registry.yarnpkg.com/babel-helper-remap-async-to-generator/-/babel-helper-remap-async-to-generator-6.22.0.tgz#2186ae73278ed03b8b15ced089609da981053383" + dependencies: + babel-helper-function-name "^6.22.0" + babel-runtime "^6.22.0" + babel-template "^6.22.0" + babel-traverse "^6.22.0" + babel-types "^6.22.0" + +babel-helper-replace-supers@^6.22.0, babel-helper-replace-supers@^6.23.0: + version "6.23.0" + resolved "https://registry.yarnpkg.com/babel-helper-replace-supers/-/babel-helper-replace-supers-6.23.0.tgz#eeaf8ad9b58ec4337ca94223bacdca1f8d9b4bfd" + dependencies: + babel-helper-optimise-call-expression "^6.23.0" + babel-messages "^6.23.0" + babel-runtime "^6.22.0" + babel-template "^6.23.0" + babel-traverse "^6.23.0" + babel-types "^6.23.0" + +babel-helpers@^6.23.0: + version "6.23.0" + resolved "https://registry.yarnpkg.com/babel-helpers/-/babel-helpers-6.23.0.tgz#4f8f2e092d0b6a8808a4bde79c27f1e2ecf0d992" + dependencies: + babel-runtime "^6.22.0" + babel-template "^6.23.0" + +babel-messages@^6.23.0: + version "6.23.0" + resolved "https://registry.yarnpkg.com/babel-messages/-/babel-messages-6.23.0.tgz#f3cdf4703858035b2a2951c6ec5edf6c62f2630e" + dependencies: + babel-runtime "^6.22.0" + +babel-plugin-check-es2015-constants@^6.22.0: + version "6.22.0" + resolved "https://registry.yarnpkg.com/babel-plugin-check-es2015-constants/-/babel-plugin-check-es2015-constants-6.22.0.tgz#35157b101426fd2ffd3da3f75c7d1e91835bbf8a" + dependencies: + babel-runtime "^6.22.0" + +babel-plugin-external-helpers@^6.4.0: + version "6.22.0" + resolved "https://registry.yarnpkg.com/babel-plugin-external-helpers/-/babel-plugin-external-helpers-6.22.0.tgz#2285f48b02bd5dede85175caf8c62e86adccefa1" + dependencies: + babel-runtime "^6.22.0" + +babel-plugin-syntax-async-functions@^6.8.0: + version "6.13.0" + resolved "https://registry.yarnpkg.com/babel-plugin-syntax-async-functions/-/babel-plugin-syntax-async-functions-6.13.0.tgz#cad9cad1191b5ad634bf30ae0872391e0647be95" + +babel-plugin-syntax-async-generators@^6.5.0: + version "6.13.0" + resolved "https://registry.yarnpkg.com/babel-plugin-syntax-async-generators/-/babel-plugin-syntax-async-generators-6.13.0.tgz#6bc963ebb16eccbae6b92b596eb7f35c342a8b9a" + +babel-plugin-syntax-class-constructor-call@^6.18.0: + version "6.18.0" + resolved "https://registry.yarnpkg.com/babel-plugin-syntax-class-constructor-call/-/babel-plugin-syntax-class-constructor-call-6.18.0.tgz#9cb9d39fe43c8600bec8146456ddcbd4e1a76416" + +babel-plugin-syntax-class-properties@^6.8.0: + version "6.13.0" + resolved "https://registry.yarnpkg.com/babel-plugin-syntax-class-properties/-/babel-plugin-syntax-class-properties-6.13.0.tgz#d7eb23b79a317f8543962c505b827c7d6cac27de" + +babel-plugin-syntax-decorators@^6.13.0: + version "6.13.0" + resolved "https://registry.yarnpkg.com/babel-plugin-syntax-decorators/-/babel-plugin-syntax-decorators-6.13.0.tgz#312563b4dbde3cc806cee3e416cceeaddd11ac0b" + +babel-plugin-syntax-do-expressions@^6.8.0: + version "6.13.0" + resolved "https://registry.yarnpkg.com/babel-plugin-syntax-do-expressions/-/babel-plugin-syntax-do-expressions-6.13.0.tgz#5747756139aa26d390d09410b03744ba07e4796d" + +babel-plugin-syntax-dynamic-import@^6.18.0: + version "6.18.0" + resolved "https://registry.yarnpkg.com/babel-plugin-syntax-dynamic-import/-/babel-plugin-syntax-dynamic-import-6.18.0.tgz#8d6a26229c83745a9982a441051572caa179b1da" + +babel-plugin-syntax-exponentiation-operator@^6.8.0: + version "6.13.0" + resolved "https://registry.yarnpkg.com/babel-plugin-syntax-exponentiation-operator/-/babel-plugin-syntax-exponentiation-operator-6.13.0.tgz#9ee7e8337290da95288201a6a57f4170317830de" + +babel-plugin-syntax-export-extensions@^6.8.0: + version "6.13.0" + resolved "https://registry.yarnpkg.com/babel-plugin-syntax-export-extensions/-/babel-plugin-syntax-export-extensions-6.13.0.tgz#70a1484f0f9089a4e84ad44bac353c95b9b12721" + +babel-plugin-syntax-flow@^6.18.0: + version "6.18.0" + resolved "https://registry.yarnpkg.com/babel-plugin-syntax-flow/-/babel-plugin-syntax-flow-6.18.0.tgz#4c3ab20a2af26aa20cd25995c398c4eb70310c8d" + +babel-plugin-syntax-function-bind@^6.8.0: + version "6.13.0" + resolved "https://registry.yarnpkg.com/babel-plugin-syntax-function-bind/-/babel-plugin-syntax-function-bind-6.13.0.tgz#48c495f177bdf31a981e732f55adc0bdd2601f46" + +babel-plugin-syntax-jsx@^6.3.13, babel-plugin-syntax-jsx@^6.8.0: + version "6.18.0" + resolved "https://registry.yarnpkg.com/babel-plugin-syntax-jsx/-/babel-plugin-syntax-jsx-6.18.0.tgz#0af32a9a6e13ca7a3fd5069e62d7b0f58d0d8946" + +babel-plugin-syntax-object-rest-spread@^6.8.0: + version "6.13.0" + resolved "https://registry.yarnpkg.com/babel-plugin-syntax-object-rest-spread/-/babel-plugin-syntax-object-rest-spread-6.13.0.tgz#fd6536f2bce13836ffa3a5458c4903a597bb3bf5" + +babel-plugin-syntax-trailing-function-commas@^6.22.0: + version "6.22.0" + resolved "https://registry.yarnpkg.com/babel-plugin-syntax-trailing-function-commas/-/babel-plugin-syntax-trailing-function-commas-6.22.0.tgz#ba0360937f8d06e40180a43fe0d5616fff532cf3" + +babel-plugin-transform-async-generator-functions@^6.22.0: + version "6.22.0" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-async-generator-functions/-/babel-plugin-transform-async-generator-functions-6.22.0.tgz#a720a98153a7596f204099cd5409f4b3c05bab46" + dependencies: + babel-helper-remap-async-to-generator "^6.22.0" + babel-plugin-syntax-async-generators "^6.5.0" + babel-runtime "^6.22.0" + +babel-plugin-transform-async-to-generator@^6.22.0: + version "6.22.0" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-async-to-generator/-/babel-plugin-transform-async-to-generator-6.22.0.tgz#194b6938ec195ad36efc4c33a971acf00d8cd35e" + dependencies: + babel-helper-remap-async-to-generator "^6.22.0" + babel-plugin-syntax-async-functions "^6.8.0" + babel-runtime "^6.22.0" + +babel-plugin-transform-class-constructor-call@^6.22.0: + version "6.22.0" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-class-constructor-call/-/babel-plugin-transform-class-constructor-call-6.22.0.tgz#11a4d2216abb5b0eef298b493748f4f2f4869120" + dependencies: + babel-plugin-syntax-class-constructor-call "^6.18.0" + babel-runtime "^6.22.0" + babel-template "^6.22.0" + +babel-plugin-transform-class-properties@^6.22.0, babel-plugin-transform-class-properties@^6.9.1: + version "6.23.0" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-class-properties/-/babel-plugin-transform-class-properties-6.23.0.tgz#187b747ee404399013563c993db038f34754ac3b" + dependencies: + babel-helper-function-name "^6.23.0" + babel-plugin-syntax-class-properties "^6.8.0" + babel-runtime "^6.22.0" + babel-template "^6.23.0" + +babel-plugin-transform-decorators@^6.22.0: + version "6.22.0" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-decorators/-/babel-plugin-transform-decorators-6.22.0.tgz#c03635b27a23b23b7224f49232c237a73988d27c" + dependencies: + babel-helper-explode-class "^6.22.0" + babel-plugin-syntax-decorators "^6.13.0" + babel-runtime "^6.22.0" + babel-template "^6.22.0" + babel-types "^6.22.0" + +babel-plugin-transform-do-expressions@^6.22.0: + version "6.22.0" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-do-expressions/-/babel-plugin-transform-do-expressions-6.22.0.tgz#28ccaf92812d949c2cd1281f690c8fdc468ae9bb" + dependencies: + babel-plugin-syntax-do-expressions "^6.8.0" + babel-runtime "^6.22.0" + +babel-plugin-transform-es2015-arrow-functions@^6.22.0: + version "6.22.0" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-arrow-functions/-/babel-plugin-transform-es2015-arrow-functions-6.22.0.tgz#452692cb711d5f79dc7f85e440ce41b9f244d221" + dependencies: + babel-runtime "^6.22.0" + +babel-plugin-transform-es2015-block-scoped-functions@^6.22.0: + version "6.22.0" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-block-scoped-functions/-/babel-plugin-transform-es2015-block-scoped-functions-6.22.0.tgz#bbc51b49f964d70cb8d8e0b94e820246ce3a6141" + dependencies: + babel-runtime "^6.22.0" + +babel-plugin-transform-es2015-block-scoping@^6.22.0: + version "6.23.0" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-block-scoping/-/babel-plugin-transform-es2015-block-scoping-6.23.0.tgz#e48895cf0b375be148cd7c8879b422707a053b51" + dependencies: + babel-runtime "^6.22.0" + babel-template "^6.23.0" + babel-traverse "^6.23.0" + babel-types "^6.23.0" + lodash "^4.2.0" + +babel-plugin-transform-es2015-classes@^6.22.0, babel-plugin-transform-es2015-classes@^6.9.0: + version "6.23.0" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-classes/-/babel-plugin-transform-es2015-classes-6.23.0.tgz#49b53f326202a2fd1b3bbaa5e2edd8a4f78643c1" + dependencies: + babel-helper-define-map "^6.23.0" + babel-helper-function-name "^6.23.0" + babel-helper-optimise-call-expression "^6.23.0" + babel-helper-replace-supers "^6.23.0" + babel-messages "^6.23.0" + babel-runtime "^6.22.0" + babel-template "^6.23.0" + babel-traverse "^6.23.0" + babel-types "^6.23.0" + +babel-plugin-transform-es2015-computed-properties@^6.22.0: + version "6.22.0" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-computed-properties/-/babel-plugin-transform-es2015-computed-properties-6.22.0.tgz#7c383e9629bba4820c11b0425bdd6290f7f057e7" + dependencies: + babel-runtime "^6.22.0" + babel-template "^6.22.0" + +babel-plugin-transform-es2015-destructuring@^6.22.0: + version "6.23.0" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-destructuring/-/babel-plugin-transform-es2015-destructuring-6.23.0.tgz#997bb1f1ab967f682d2b0876fe358d60e765c56d" + dependencies: + babel-runtime "^6.22.0" + +babel-plugin-transform-es2015-duplicate-keys@^6.22.0: + version "6.22.0" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-duplicate-keys/-/babel-plugin-transform-es2015-duplicate-keys-6.22.0.tgz#672397031c21610d72dd2bbb0ba9fb6277e1c36b" + dependencies: + babel-runtime "^6.22.0" + babel-types "^6.22.0" + +babel-plugin-transform-es2015-for-of@^6.22.0: + version "6.23.0" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-for-of/-/babel-plugin-transform-es2015-for-of-6.23.0.tgz#f47c95b2b613df1d3ecc2fdb7573623c75248691" + dependencies: + babel-runtime "^6.22.0" + +babel-plugin-transform-es2015-function-name@^6.22.0: + version "6.22.0" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-function-name/-/babel-plugin-transform-es2015-function-name-6.22.0.tgz#f5fcc8b09093f9a23c76ac3d9e392c3ec4b77104" + dependencies: + babel-helper-function-name "^6.22.0" + babel-runtime "^6.22.0" + babel-types "^6.22.0" + +babel-plugin-transform-es2015-literals@^6.22.0: + version "6.22.0" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-literals/-/babel-plugin-transform-es2015-literals-6.22.0.tgz#4f54a02d6cd66cf915280019a31d31925377ca2e" + dependencies: + babel-runtime "^6.22.0" + +babel-plugin-transform-es2015-modules-amd@^6.22.0: + version "6.22.0" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-modules-amd/-/babel-plugin-transform-es2015-modules-amd-6.22.0.tgz#bf69cd34889a41c33d90dfb740e0091ccff52f21" + dependencies: + babel-plugin-transform-es2015-modules-commonjs "^6.22.0" + babel-runtime "^6.22.0" + babel-template "^6.22.0" + +babel-plugin-transform-es2015-modules-commonjs@^6.22.0: + version "6.23.0" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-modules-commonjs/-/babel-plugin-transform-es2015-modules-commonjs-6.23.0.tgz#cba7aa6379fb7ec99250e6d46de2973aaffa7b92" + dependencies: + babel-plugin-transform-strict-mode "^6.22.0" + babel-runtime "^6.22.0" + babel-template "^6.23.0" + babel-types "^6.23.0" + +babel-plugin-transform-es2015-modules-systemjs@^6.22.0: + version "6.23.0" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-modules-systemjs/-/babel-plugin-transform-es2015-modules-systemjs-6.23.0.tgz#ae3469227ffac39b0310d90fec73bfdc4f6317b0" + dependencies: + babel-helper-hoist-variables "^6.22.0" + babel-runtime "^6.22.0" + babel-template "^6.23.0" + +babel-plugin-transform-es2015-modules-umd@^6.22.0: + version "6.23.0" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-modules-umd/-/babel-plugin-transform-es2015-modules-umd-6.23.0.tgz#8d284ae2e19ed8fe21d2b1b26d6e7e0fcd94f0f1" + dependencies: + babel-plugin-transform-es2015-modules-amd "^6.22.0" + babel-runtime "^6.22.0" + babel-template "^6.23.0" + +babel-plugin-transform-es2015-object-super@^6.22.0: + version "6.22.0" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-object-super/-/babel-plugin-transform-es2015-object-super-6.22.0.tgz#daa60e114a042ea769dd53fe528fc82311eb98fc" + dependencies: + babel-helper-replace-supers "^6.22.0" + babel-runtime "^6.22.0" + +babel-plugin-transform-es2015-parameters@^6.22.0: + version "6.23.0" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-parameters/-/babel-plugin-transform-es2015-parameters-6.23.0.tgz#3a2aabb70c8af945d5ce386f1a4250625a83ae3b" + dependencies: + babel-helper-call-delegate "^6.22.0" + babel-helper-get-function-arity "^6.22.0" + babel-runtime "^6.22.0" + babel-template "^6.23.0" + babel-traverse "^6.23.0" + babel-types "^6.23.0" + +babel-plugin-transform-es2015-shorthand-properties@^6.22.0: + version "6.22.0" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-shorthand-properties/-/babel-plugin-transform-es2015-shorthand-properties-6.22.0.tgz#8ba776e0affaa60bff21e921403b8a652a2ff723" + dependencies: + babel-runtime "^6.22.0" + babel-types "^6.22.0" + +babel-plugin-transform-es2015-spread@^6.22.0: + version "6.22.0" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-spread/-/babel-plugin-transform-es2015-spread-6.22.0.tgz#d6d68a99f89aedc4536c81a542e8dd9f1746f8d1" + dependencies: + babel-runtime "^6.22.0" + +babel-plugin-transform-es2015-sticky-regex@^6.22.0: + version "6.22.0" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-sticky-regex/-/babel-plugin-transform-es2015-sticky-regex-6.22.0.tgz#ab316829e866ee3f4b9eb96939757d19a5bc4593" + dependencies: + babel-helper-regex "^6.22.0" + babel-runtime "^6.22.0" + babel-types "^6.22.0" + +babel-plugin-transform-es2015-template-literals@^6.22.0: + version "6.22.0" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-template-literals/-/babel-plugin-transform-es2015-template-literals-6.22.0.tgz#a84b3450f7e9f8f1f6839d6d687da84bb1236d8d" + dependencies: + babel-runtime "^6.22.0" + +babel-plugin-transform-es2015-typeof-symbol@^6.22.0: + version "6.23.0" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-typeof-symbol/-/babel-plugin-transform-es2015-typeof-symbol-6.23.0.tgz#dec09f1cddff94b52ac73d505c84df59dcceb372" + dependencies: + babel-runtime "^6.22.0" + +babel-plugin-transform-es2015-unicode-regex@^6.22.0: + version "6.22.0" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-unicode-regex/-/babel-plugin-transform-es2015-unicode-regex-6.22.0.tgz#8d9cc27e7ee1decfe65454fb986452a04a613d20" + dependencies: + babel-helper-regex "^6.22.0" + babel-runtime "^6.22.0" + regexpu-core "^2.0.0" + +babel-plugin-transform-exponentiation-operator@^6.22.0: + version "6.22.0" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-exponentiation-operator/-/babel-plugin-transform-exponentiation-operator-6.22.0.tgz#d57c8335281918e54ef053118ce6eb108468084d" + dependencies: + babel-helper-builder-binary-assignment-operator-visitor "^6.22.0" + babel-plugin-syntax-exponentiation-operator "^6.8.0" + babel-runtime "^6.22.0" + +babel-plugin-transform-export-extensions@^6.22.0: + version "6.22.0" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-export-extensions/-/babel-plugin-transform-export-extensions-6.22.0.tgz#53738b47e75e8218589eea946cbbd39109bbe653" + dependencies: + babel-plugin-syntax-export-extensions "^6.8.0" + babel-runtime "^6.22.0" + +babel-plugin-transform-flow-strip-types@^6.22.0: + version "6.22.0" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-flow-strip-types/-/babel-plugin-transform-flow-strip-types-6.22.0.tgz#84cb672935d43714fdc32bce84568d87441cf7cf" + dependencies: + babel-plugin-syntax-flow "^6.18.0" + babel-runtime "^6.22.0" + +babel-plugin-transform-function-bind@^6.22.0: + version "6.22.0" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-function-bind/-/babel-plugin-transform-function-bind-6.22.0.tgz#c6fb8e96ac296a310b8cf8ea401462407ddf6a97" + dependencies: + babel-plugin-syntax-function-bind "^6.8.0" + babel-runtime "^6.22.0" + +babel-plugin-transform-object-rest-spread@^6.22.0: + version "6.23.0" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-object-rest-spread/-/babel-plugin-transform-object-rest-spread-6.23.0.tgz#875d6bc9be761c58a2ae3feee5dc4895d8c7f921" + dependencies: + babel-plugin-syntax-object-rest-spread "^6.8.0" + babel-runtime "^6.22.0" + +babel-plugin-transform-react-display-name@^6.23.0: + version "6.23.0" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-react-display-name/-/babel-plugin-transform-react-display-name-6.23.0.tgz#4398910c358441dc4cef18787264d0412ed36b37" + dependencies: + babel-runtime "^6.22.0" + +babel-plugin-transform-react-jsx-self@^6.22.0: + version "6.22.0" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-react-jsx-self/-/babel-plugin-transform-react-jsx-self-6.22.0.tgz#df6d80a9da2612a121e6ddd7558bcbecf06e636e" + dependencies: + babel-plugin-syntax-jsx "^6.8.0" + babel-runtime "^6.22.0" + +babel-plugin-transform-react-jsx-source@^6.22.0: + version "6.22.0" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-react-jsx-source/-/babel-plugin-transform-react-jsx-source-6.22.0.tgz#66ac12153f5cd2d17b3c19268f4bf0197f44ecd6" + dependencies: + babel-plugin-syntax-jsx "^6.8.0" + babel-runtime "^6.22.0" + +babel-plugin-transform-react-jsx@^6.23.0: + version "6.23.0" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-react-jsx/-/babel-plugin-transform-react-jsx-6.23.0.tgz#23e892f7f2e759678eb5e4446a8f8e94e81b3470" + dependencies: + babel-helper-builder-react-jsx "^6.23.0" + babel-plugin-syntax-jsx "^6.8.0" + babel-runtime "^6.22.0" + +babel-plugin-transform-regenerator@^6.22.0: + version "6.22.0" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-regenerator/-/babel-plugin-transform-regenerator-6.22.0.tgz#65740593a319c44522157538d690b84094617ea6" + dependencies: + regenerator-transform "0.9.8" + +babel-plugin-transform-strict-mode@^6.22.0: + version "6.22.0" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-strict-mode/-/babel-plugin-transform-strict-mode-6.22.0.tgz#e008df01340fdc87e959da65991b7e05970c8c7c" + dependencies: + babel-runtime "^6.22.0" + babel-types "^6.22.0" + +babel-preset-es2015-rollup@^1.1.1: + version "1.2.0" + resolved "https://registry.yarnpkg.com/babel-preset-es2015-rollup/-/babel-preset-es2015-rollup-1.2.0.tgz#feedf80346e01fa22d4de15e72cde1cefc59bf67" + dependencies: + babel-plugin-external-helpers "^6.4.0" + babel-preset-es2015 "^6.3.13" + modify-babel-preset "^2.1.1" + +babel-preset-es2015@^6.3.13, babel-preset-es2015@^6.6.0: + version "6.22.0" + resolved "https://registry.yarnpkg.com/babel-preset-es2015/-/babel-preset-es2015-6.22.0.tgz#af5a98ecb35eb8af764ad8a5a05eb36dc4386835" + dependencies: + babel-plugin-check-es2015-constants "^6.22.0" + babel-plugin-transform-es2015-arrow-functions "^6.22.0" + babel-plugin-transform-es2015-block-scoped-functions "^6.22.0" + babel-plugin-transform-es2015-block-scoping "^6.22.0" + babel-plugin-transform-es2015-classes "^6.22.0" + babel-plugin-transform-es2015-computed-properties "^6.22.0" + babel-plugin-transform-es2015-destructuring "^6.22.0" + babel-plugin-transform-es2015-duplicate-keys "^6.22.0" + babel-plugin-transform-es2015-for-of "^6.22.0" + babel-plugin-transform-es2015-function-name "^6.22.0" + babel-plugin-transform-es2015-literals "^6.22.0" + babel-plugin-transform-es2015-modules-amd "^6.22.0" + babel-plugin-transform-es2015-modules-commonjs "^6.22.0" + babel-plugin-transform-es2015-modules-systemjs "^6.22.0" + babel-plugin-transform-es2015-modules-umd "^6.22.0" + babel-plugin-transform-es2015-object-super "^6.22.0" + babel-plugin-transform-es2015-parameters "^6.22.0" + babel-plugin-transform-es2015-shorthand-properties "^6.22.0" + babel-plugin-transform-es2015-spread "^6.22.0" + babel-plugin-transform-es2015-sticky-regex "^6.22.0" + babel-plugin-transform-es2015-template-literals "^6.22.0" + babel-plugin-transform-es2015-typeof-symbol "^6.22.0" + babel-plugin-transform-es2015-unicode-regex "^6.22.0" + babel-plugin-transform-regenerator "^6.22.0" + +babel-preset-flow@^6.23.0: + version "6.23.0" + resolved "https://registry.yarnpkg.com/babel-preset-flow/-/babel-preset-flow-6.23.0.tgz#e71218887085ae9a24b5be4169affb599816c49d" + dependencies: + babel-plugin-transform-flow-strip-types "^6.22.0" + +babel-preset-react@^6.5.0: + version "6.23.0" + resolved "https://registry.yarnpkg.com/babel-preset-react/-/babel-preset-react-6.23.0.tgz#eb7cee4de98a3f94502c28565332da9819455195" + dependencies: + babel-plugin-syntax-jsx "^6.3.13" + babel-plugin-transform-react-display-name "^6.23.0" + babel-plugin-transform-react-jsx "^6.23.0" + babel-plugin-transform-react-jsx-self "^6.22.0" + babel-plugin-transform-react-jsx-source "^6.22.0" + babel-preset-flow "^6.23.0" + +babel-preset-stage-0@^6.5.0: + version "6.22.0" + resolved "https://registry.yarnpkg.com/babel-preset-stage-0/-/babel-preset-stage-0-6.22.0.tgz#707eeb5b415da769eff9c42f4547f644f9296ef9" + dependencies: + babel-plugin-transform-do-expressions "^6.22.0" + babel-plugin-transform-function-bind "^6.22.0" + babel-preset-stage-1 "^6.22.0" + +babel-preset-stage-1@^6.22.0: + version "6.22.0" + resolved "https://registry.yarnpkg.com/babel-preset-stage-1/-/babel-preset-stage-1-6.22.0.tgz#7da05bffea6ad5a10aef93e320cfc6dd465dbc1a" + dependencies: + babel-plugin-transform-class-constructor-call "^6.22.0" + babel-plugin-transform-export-extensions "^6.22.0" + babel-preset-stage-2 "^6.22.0" + +babel-preset-stage-2@^6.22.0: + version "6.22.0" + resolved "https://registry.yarnpkg.com/babel-preset-stage-2/-/babel-preset-stage-2-6.22.0.tgz#ccd565f19c245cade394b21216df704a73b27c07" + dependencies: + babel-plugin-syntax-dynamic-import "^6.18.0" + babel-plugin-transform-class-properties "^6.22.0" + babel-plugin-transform-decorators "^6.22.0" + babel-preset-stage-3 "^6.22.0" + +babel-preset-stage-3@^6.22.0: + version "6.22.0" + resolved "https://registry.yarnpkg.com/babel-preset-stage-3/-/babel-preset-stage-3-6.22.0.tgz#a4e92bbace7456fafdf651d7a7657ee0bbca9c2e" + dependencies: + babel-plugin-syntax-trailing-function-commas "^6.22.0" + babel-plugin-transform-async-generator-functions "^6.22.0" + babel-plugin-transform-async-to-generator "^6.22.0" + babel-plugin-transform-exponentiation-operator "^6.22.0" + babel-plugin-transform-object-rest-spread "^6.22.0" + +babel-register@^6.23.0: + version "6.23.0" + resolved "https://registry.yarnpkg.com/babel-register/-/babel-register-6.23.0.tgz#c9aa3d4cca94b51da34826c4a0f9e08145d74ff3" + dependencies: + babel-core "^6.23.0" + babel-runtime "^6.22.0" + core-js "^2.4.0" + home-or-tmp "^2.0.0" + lodash "^4.2.0" + mkdirp "^0.5.1" + source-map-support "^0.4.2" + +babel-runtime@^6.18.0, babel-runtime@^6.22.0: + version "6.23.0" + resolved "https://registry.yarnpkg.com/babel-runtime/-/babel-runtime-6.23.0.tgz#0a9489f144de70efb3ce4300accdb329e2fc543b" + dependencies: + core-js "^2.4.0" + regenerator-runtime "^0.10.0" + +babel-template@^6.22.0, babel-template@^6.23.0: + version "6.23.0" + resolved "https://registry.yarnpkg.com/babel-template/-/babel-template-6.23.0.tgz#04d4f270adbb3aa704a8143ae26faa529238e638" + dependencies: + babel-runtime "^6.22.0" + babel-traverse "^6.23.0" + babel-types "^6.23.0" + babylon "^6.11.0" + lodash "^4.2.0" + +babel-traverse@^6.22.0, babel-traverse@^6.23.0, babel-traverse@^6.23.1: + version "6.23.1" + resolved "https://registry.yarnpkg.com/babel-traverse/-/babel-traverse-6.23.1.tgz#d3cb59010ecd06a97d81310065f966b699e14f48" + dependencies: + babel-code-frame "^6.22.0" + babel-messages "^6.23.0" + babel-runtime "^6.22.0" + babel-types "^6.23.0" + babylon "^6.15.0" + debug "^2.2.0" + globals "^9.0.0" + invariant "^2.2.0" + lodash "^4.2.0" + +babel-types@^6.19.0, babel-types@^6.22.0, babel-types@^6.23.0: + version "6.23.0" + resolved "https://registry.yarnpkg.com/babel-types/-/babel-types-6.23.0.tgz#bb17179d7538bad38cd0c9e115d340f77e7e9acf" + dependencies: + babel-runtime "^6.22.0" + esutils "^2.0.2" + lodash "^4.2.0" + to-fast-properties "^1.0.1" + +babel@^6.5.2: + version "6.23.0" + resolved "https://registry.yarnpkg.com/babel/-/babel-6.23.0.tgz#d0d1e7d803e974765beea3232d4e153c0efb90f4" + +babylon@^6.11.0, babylon@^6.15.0: + version "6.16.1" + resolved "https://registry.yarnpkg.com/babylon/-/babylon-6.16.1.tgz#30c5a22f481978a9e7f8cdfdf496b11d94b404d3" + +balanced-match@^0.4.1: + version "0.4.2" + resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-0.4.2.tgz#cb3f3e3c732dc0f01ee70b403f302e61d7709838" + +beeper@^1.0.0: + version "1.1.1" + resolved "https://registry.yarnpkg.com/beeper/-/beeper-1.1.1.tgz#e6d5ea8c5dad001304a70b22638447f69cb2f809" + +brace-expansion@^1.0.0: + version "1.1.6" + resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.6.tgz#7197d7eaa9b87e648390ea61fc66c84427420df9" + dependencies: + balanced-match "^0.4.1" + concat-map "0.0.1" + +braces@^1.8.2: + version "1.8.5" + resolved "https://registry.yarnpkg.com/braces/-/braces-1.8.5.tgz#ba77962e12dff969d6b76711e914b737857bf6a7" + dependencies: + expand-range "^1.8.1" + preserve "^0.2.0" + repeat-element "^1.1.2" + +browser-resolve@^1.11.0: + version "1.11.2" + resolved "https://registry.yarnpkg.com/browser-resolve/-/browser-resolve-1.11.2.tgz#8ff09b0a2c421718a1051c260b32e48f442938ce" + dependencies: + resolve "1.1.7" + +buffer-shims@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/buffer-shims/-/buffer-shims-1.0.0.tgz#9978ce317388c649ad8793028c3477ef044a8b51" + +builtin-modules@^1.1.0, builtin-modules@^1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/builtin-modules/-/builtin-modules-1.1.1.tgz#270f076c5a72c02f5b65a47df94c5fe3a278892f" + +caller-path@^0.1.0: + version "0.1.0" + resolved "https://registry.yarnpkg.com/caller-path/-/caller-path-0.1.0.tgz#94085ef63581ecd3daa92444a8fe94e82577751f" + dependencies: + callsites "^0.2.0" + +callsites@^0.2.0: + version "0.2.0" + resolved "https://registry.yarnpkg.com/callsites/-/callsites-0.2.0.tgz#afab96262910a7f33c19a5775825c69f34e350ca" + +camelcase@^1.0.2: + version "1.2.1" + resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-1.2.1.tgz#9bb5304d2e0b56698b2c758b08a3eaa9daa58a39" + +center-align@^0.1.1: + version "0.1.3" + resolved "https://registry.yarnpkg.com/center-align/-/center-align-0.1.3.tgz#aa0d32629b6ee972200411cbd4461c907bc2b7ad" + dependencies: + align-text "^0.1.3" + lazy-cache "^1.0.3" + +chai@^3.5.0: + version "3.5.0" + resolved "https://registry.yarnpkg.com/chai/-/chai-3.5.0.tgz#4d02637b067fe958bdbfdd3a40ec56fef7373247" + dependencies: + assertion-error "^1.0.1" + deep-eql "^0.1.3" + type-detect "^1.0.0" + +chalk@^1.0.0, chalk@^1.1.0, chalk@^1.1.1, chalk@^1.1.3: + version "1.1.3" + resolved "https://registry.yarnpkg.com/chalk/-/chalk-1.1.3.tgz#a8115c55e4a702fe4d150abd3872822a7e09fc98" + dependencies: + ansi-styles "^2.2.1" + escape-string-regexp "^1.0.2" + has-ansi "^2.0.0" + strip-ansi "^3.0.0" + supports-color "^2.0.0" + +circular-json@^0.3.1: + version "0.3.1" + resolved "https://registry.yarnpkg.com/circular-json/-/circular-json-0.3.1.tgz#be8b36aefccde8b3ca7aa2d6afc07a37242c0d2d" + +cli-cursor@^1.0.1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/cli-cursor/-/cli-cursor-1.0.2.tgz#64da3f7d56a54412e59794bd62dc35295e8f2987" + dependencies: + restore-cursor "^1.0.1" + +cli-width@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/cli-width/-/cli-width-2.1.0.tgz#b234ca209b29ef66fc518d9b98d5847b00edf00a" + +cliui@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/cliui/-/cliui-2.1.0.tgz#4b475760ff80264c762c3a1719032e91c7fea0d1" + dependencies: + center-align "^0.1.1" + right-align "^0.1.1" + wordwrap "0.0.2" + +clone-stats@^0.0.1: + version "0.0.1" + resolved "https://registry.yarnpkg.com/clone-stats/-/clone-stats-0.0.1.tgz#b88f94a82cf38b8791d58046ea4029ad88ca99d1" + +clone@^0.2.0: + version "0.2.0" + resolved "https://registry.yarnpkg.com/clone/-/clone-0.2.0.tgz#c6126a90ad4f72dbf5acdb243cc37724fe93fc1f" + +clone@^1.0.0, clone@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/clone/-/clone-1.0.2.tgz#260b7a99ebb1edfe247538175f783243cb19d149" + +co@^4.6.0: + version "4.6.0" + resolved "https://registry.yarnpkg.com/co/-/co-4.6.0.tgz#6ea6bdf3d853ae54ccb8e47bfa0bf3f9031fb184" + +code-point-at@^1.0.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/code-point-at/-/code-point-at-1.1.0.tgz#0d070b4d043a5bea33a2f1a40e2edb3d9a4ccf77" + +commander@0.6.1: + version "0.6.1" + resolved "https://registry.yarnpkg.com/commander/-/commander-0.6.1.tgz#fa68a14f6a945d54dbbe50d8cdb3320e9e3b1a06" + +commander@2.3.0: + version "2.3.0" + resolved "https://registry.yarnpkg.com/commander/-/commander-2.3.0.tgz#fd430e889832ec353b9acd1de217c11cb3eef873" + +concat-map@0.0.1: + version "0.0.1" + resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b" + +concat-stream@^1.4.6: + version "1.6.0" + resolved "https://registry.yarnpkg.com/concat-stream/-/concat-stream-1.6.0.tgz#0aac662fd52be78964d5532f694784e70110acf7" + dependencies: + inherits "^2.0.3" + readable-stream "^2.2.2" + typedarray "^0.0.6" + +contains-path@^0.1.0: + version "0.1.0" + resolved "https://registry.yarnpkg.com/contains-path/-/contains-path-0.1.0.tgz#fe8cf184ff6670b6baef01a9d4861a5cbec4120a" + +convert-source-map@1.X, convert-source-map@^1.1.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/convert-source-map/-/convert-source-map-1.4.0.tgz#e3dad195bf61bfe13a7a3c73e9876ec14a0268f3" + +core-js@^2.4.0: + version "2.4.1" + resolved "https://registry.yarnpkg.com/core-js/-/core-js-2.4.1.tgz#4de911e667b0eae9124e34254b53aea6fc618d3e" + +core-util-is@~1.0.0: + version "1.0.2" + resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.2.tgz#b5fd54220aa2bc5ab57aab7140c940754503c1a7" + +css@2.X: + version "2.2.1" + resolved "https://registry.yarnpkg.com/css/-/css-2.2.1.tgz#73a4c81de85db664d4ee674f7d47085e3b2d55dc" + dependencies: + inherits "^2.0.1" + source-map "^0.1.38" + source-map-resolve "^0.3.0" + urix "^0.1.0" + +d@^0.1.1, d@~0.1.1: + version "0.1.1" + resolved "https://registry.yarnpkg.com/d/-/d-0.1.1.tgz#da184c535d18d8ee7ba2aa229b914009fae11309" + dependencies: + es5-ext "~0.10.2" + +dateformat@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/dateformat/-/dateformat-2.0.0.tgz#2743e3abb5c3fc2462e527dca445e04e9f4dee17" + +debug-fabulous@0.0.X: + version "0.0.4" + resolved "https://registry.yarnpkg.com/debug-fabulous/-/debug-fabulous-0.0.4.tgz#fa071c5d87484685424807421ca4b16b0b1a0763" + dependencies: + debug "2.X" + lazy-debug-legacy "0.0.X" + object-assign "4.1.0" + +debug@2.2.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/debug/-/debug-2.2.0.tgz#f87057e995b1a1f6ae6a4960664137bc56f039da" + dependencies: + ms "0.7.1" + +debug@2.X, debug@^2.1.1, debug@^2.2.0: + version "2.6.1" + resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.1.tgz#79855090ba2c4e3115cc7d8769491d58f0491351" + dependencies: + ms "0.7.2" + +decamelize@^1.0.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/decamelize/-/decamelize-1.2.0.tgz#f6534d15148269b20352e7bee26f501f9a191290" + +deep-eql@^0.1.3: + version "0.1.3" + resolved "https://registry.yarnpkg.com/deep-eql/-/deep-eql-0.1.3.tgz#ef558acab8de25206cd713906d74e56930eb69f2" + dependencies: + type-detect "0.1.1" + +deep-is@~0.1.3: + version "0.1.3" + resolved "https://registry.yarnpkg.com/deep-is/-/deep-is-0.1.3.tgz#b369d6fb5dbc13eecf524f91b070feedc357cf34" + +defaults@^1.0.0: + version "1.0.3" + resolved "https://registry.yarnpkg.com/defaults/-/defaults-1.0.3.tgz#c656051e9817d9ff08ed881477f3fe4019f3ef7d" + dependencies: + clone "^1.0.2" + +del@^2.0.2: + version "2.2.2" + resolved "https://registry.yarnpkg.com/del/-/del-2.2.2.tgz#c12c981d067846c84bcaf862cff930d907ffd1a8" + dependencies: + globby "^5.0.0" + is-path-cwd "^1.0.0" + is-path-in-cwd "^1.0.0" + object-assign "^4.0.1" + pify "^2.0.0" + pinkie-promise "^2.0.0" + rimraf "^2.2.8" + +deprecated@^0.0.1: + version "0.0.1" + resolved "https://registry.yarnpkg.com/deprecated/-/deprecated-0.0.1.tgz#f9c9af5464afa1e7a971458a8bdef2aa94d5bb19" + +detect-file@^0.1.0: + version "0.1.0" + resolved "https://registry.yarnpkg.com/detect-file/-/detect-file-0.1.0.tgz#4935dedfd9488648e006b0129566e9386711ea63" + dependencies: + fs-exists-sync "^0.1.0" + +detect-indent@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/detect-indent/-/detect-indent-4.0.0.tgz#f76d064352cdf43a1cb6ce619c4ee3a9475de208" + dependencies: + repeating "^2.0.0" + +detect-newline@2.X: + version "2.1.0" + resolved "https://registry.yarnpkg.com/detect-newline/-/detect-newline-2.1.0.tgz#f41f1c10be4b00e87b5f13da680759f2c5bfd3e2" + +diff@1.4.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/diff/-/diff-1.4.0.tgz#7f28d2eb9ee7b15a97efd89ce63dcfdaa3ccbabf" + +doctrine@1.5.0, doctrine@^1.2.2: + version "1.5.0" + resolved "https://registry.yarnpkg.com/doctrine/-/doctrine-1.5.0.tgz#379dce730f6166f76cefa4e6707a159b02c5a6fa" + dependencies: + esutils "^2.0.2" + isarray "^1.0.0" + +duplexer2@0.0.2: + version "0.0.2" + resolved "https://registry.yarnpkg.com/duplexer2/-/duplexer2-0.0.2.tgz#c614dcf67e2fb14995a91711e5a617e8a60a31db" + dependencies: + readable-stream "~1.1.9" + +end-of-stream@~0.1.5: + version "0.1.5" + resolved "https://registry.yarnpkg.com/end-of-stream/-/end-of-stream-0.1.5.tgz#8e177206c3c80837d85632e8b9359dfe8b2f6eaf" + dependencies: + once "~1.3.0" + +erlang-types@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/erlang-types/-/erlang-types-1.0.0.tgz#e555bd091667498a01d340d18203231dc96d962f" + +es5-ext@^0.10.7, es5-ext@^0.10.8, es5-ext@~0.10.11, es5-ext@~0.10.2, es5-ext@~0.10.7: + version "0.10.12" + resolved "https://registry.yarnpkg.com/es5-ext/-/es5-ext-0.10.12.tgz#aa84641d4db76b62abba5e45fd805ecbab140047" + dependencies: + es6-iterator "2" + es6-symbol "~3.1" + +es6-iterator@2: + version "2.0.0" + resolved "https://registry.yarnpkg.com/es6-iterator/-/es6-iterator-2.0.0.tgz#bd968567d61635e33c0b80727613c9cb4b096bac" + dependencies: + d "^0.1.1" + es5-ext "^0.10.7" + es6-symbol "3" + +es6-map@^0.1.3: + version "0.1.4" + resolved "https://registry.yarnpkg.com/es6-map/-/es6-map-0.1.4.tgz#a34b147be224773a4d7da8072794cefa3632b897" + dependencies: + d "~0.1.1" + es5-ext "~0.10.11" + es6-iterator "2" + es6-set "~0.1.3" + es6-symbol "~3.1.0" + event-emitter "~0.3.4" + +es6-set@~0.1.3: + version "0.1.4" + resolved "https://registry.yarnpkg.com/es6-set/-/es6-set-0.1.4.tgz#9516b6761c2964b92ff479456233a247dc707ce8" + dependencies: + d "~0.1.1" + es5-ext "~0.10.11" + es6-iterator "2" + es6-symbol "3" + event-emitter "~0.3.4" + +es6-symbol@3, es6-symbol@~3.1, es6-symbol@~3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/es6-symbol/-/es6-symbol-3.1.0.tgz#94481c655e7a7cad82eba832d97d5433496d7ffa" + dependencies: + d "~0.1.1" + es5-ext "~0.10.11" + +es6-weak-map@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/es6-weak-map/-/es6-weak-map-2.0.1.tgz#0d2bbd8827eb5fb4ba8f97fbfea50d43db21ea81" + dependencies: + d "^0.1.1" + es5-ext "^0.10.8" + es6-iterator "2" + es6-symbol "3" + +escape-string-regexp@1.0.2, escape-string-regexp@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.2.tgz#4dbc2fe674e71949caf3fb2695ce7f2dc1d9a8d1" + +escape-string-regexp@^1.0.5: + version "1.0.5" + resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4" + +escope@^3.6.0: + version "3.6.0" + resolved "https://registry.yarnpkg.com/escope/-/escope-3.6.0.tgz#e01975e812781a163a6dadfdd80398dc64c889c3" + dependencies: + es6-map "^0.1.3" + es6-weak-map "^2.0.1" + esrecurse "^4.1.0" + estraverse "^4.1.1" + +eslint-config-airbnb-base@^11.1.0: + version "11.1.0" + resolved "https://registry.yarnpkg.com/eslint-config-airbnb-base/-/eslint-config-airbnb-base-11.1.0.tgz#dc9b3ec70b8c74dcbe6d6257c9da3992c39ca2ca" + +eslint-import-resolver-node@^0.2.0: + version "0.2.3" + resolved "https://registry.yarnpkg.com/eslint-import-resolver-node/-/eslint-import-resolver-node-0.2.3.tgz#5add8106e8c928db2cba232bcd9efa846e3da16c" + dependencies: + debug "^2.2.0" + object-assign "^4.0.1" + resolve "^1.1.6" + +eslint-module-utils@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/eslint-module-utils/-/eslint-module-utils-2.0.0.tgz#a6f8c21d901358759cdc35dbac1982ae1ee58bce" + dependencies: + debug "2.2.0" + pkg-dir "^1.0.0" + +eslint-plugin-import@^2.2.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/eslint-plugin-import/-/eslint-plugin-import-2.2.0.tgz#72ba306fad305d67c4816348a4699a4229ac8b4e" + dependencies: + builtin-modules "^1.1.1" + contains-path "^0.1.0" + debug "^2.2.0" + doctrine "1.5.0" + eslint-import-resolver-node "^0.2.0" + eslint-module-utils "^2.0.0" + has "^1.0.1" + lodash.cond "^4.3.0" + minimatch "^3.0.3" + pkg-up "^1.0.0" + +eslint@^3.15.0: + version "3.16.1" + resolved "https://registry.yarnpkg.com/eslint/-/eslint-3.16.1.tgz#9bc31fc7341692cf772e80607508f67d711c5609" + dependencies: + babel-code-frame "^6.16.0" + chalk "^1.1.3" + concat-stream "^1.4.6" + debug "^2.1.1" + doctrine "^1.2.2" + escope "^3.6.0" + espree "^3.4.0" + estraverse "^4.2.0" + esutils "^2.0.2" + file-entry-cache "^2.0.0" + glob "^7.0.3" + globals "^9.14.0" + ignore "^3.2.0" + imurmurhash "^0.1.4" + inquirer "^0.12.0" + is-my-json-valid "^2.10.0" + is-resolvable "^1.0.0" + js-yaml "^3.5.1" + json-stable-stringify "^1.0.0" + levn "^0.3.0" + lodash "^4.0.0" + mkdirp "^0.5.0" + natural-compare "^1.4.0" + optionator "^0.8.2" + path-is-inside "^1.0.1" + pluralize "^1.2.1" + progress "^1.1.8" + require-uncached "^1.0.2" + shelljs "^0.7.5" + strip-bom "^3.0.0" + strip-json-comments "~2.0.1" + table "^3.7.8" + text-table "~0.2.0" + user-home "^2.0.0" + +espree@^3.4.0: + version "3.4.0" + resolved "https://registry.yarnpkg.com/espree/-/espree-3.4.0.tgz#41656fa5628e042878025ef467e78f125cb86e1d" + dependencies: + acorn "4.0.4" + acorn-jsx "^3.0.0" + +esprima@^3.1.1: + version "3.1.3" + resolved "https://registry.yarnpkg.com/esprima/-/esprima-3.1.3.tgz#fdca51cee6133895e3c88d535ce49dbff62a4633" + +esrecurse@^4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/esrecurse/-/esrecurse-4.1.0.tgz#4713b6536adf7f2ac4f327d559e7756bff648220" + dependencies: + estraverse "~4.1.0" + object-assign "^4.0.1" + +estraverse@^4.1.1, estraverse@^4.2.0: + version "4.2.0" + resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-4.2.0.tgz#0dee3fed31fcd469618ce7342099fc1afa0bdb13" + +estraverse@~4.1.0: + version "4.1.1" + resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-4.1.1.tgz#f6caca728933a850ef90661d0e17982ba47111a2" + +estree-walker@^0.2.1: + version "0.2.1" + resolved "https://registry.yarnpkg.com/estree-walker/-/estree-walker-0.2.1.tgz#bdafe8095383d8414d5dc2ecf4c9173b6db9412e" + +esutils@^2.0.0, esutils@^2.0.2: + version "2.0.2" + resolved "https://registry.yarnpkg.com/esutils/-/esutils-2.0.2.tgz#0abf4f1caa5bcb1f7a9d8acc6dea4faaa04bac9b" + +event-emitter@~0.3.4: + version "0.3.4" + resolved "https://registry.yarnpkg.com/event-emitter/-/event-emitter-0.3.4.tgz#8d63ddfb4cfe1fae3b32ca265c4c720222080bb5" + dependencies: + d "~0.1.1" + es5-ext "~0.10.7" + +exit-hook@^1.0.0: + version "1.1.1" + resolved "https://registry.yarnpkg.com/exit-hook/-/exit-hook-1.1.1.tgz#f05ca233b48c05d54fff07765df8507e95c02ff8" + +expand-brackets@^0.1.4: + version "0.1.5" + resolved "https://registry.yarnpkg.com/expand-brackets/-/expand-brackets-0.1.5.tgz#df07284e342a807cd733ac5af72411e581d1177b" + dependencies: + is-posix-bracket "^0.1.0" + +expand-range@^1.8.1: + version "1.8.2" + resolved "https://registry.yarnpkg.com/expand-range/-/expand-range-1.8.2.tgz#a299effd335fe2721ebae8e257ec79644fc85337" + dependencies: + fill-range "^2.1.0" + +expand-tilde@^1.2.1, expand-tilde@^1.2.2: + version "1.2.2" + resolved "https://registry.yarnpkg.com/expand-tilde/-/expand-tilde-1.2.2.tgz#0b81eba897e5a3d31d1c3d102f8f01441e559449" + dependencies: + os-homedir "^1.0.1" + +extend@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/extend/-/extend-3.0.0.tgz#5a474353b9f3353ddd8176dfd37b91c83a46f1d4" + +extglob@^0.3.1: + version "0.3.2" + resolved "https://registry.yarnpkg.com/extglob/-/extglob-0.3.2.tgz#2e18ff3d2f49ab2765cec9023f011daa8d8349a1" + dependencies: + is-extglob "^1.0.0" + +fancy-log@^1.1.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/fancy-log/-/fancy-log-1.3.0.tgz#45be17d02bb9917d60ccffd4995c999e6c8c9948" + dependencies: + chalk "^1.1.1" + time-stamp "^1.0.0" + +fast-levenshtein@~2.0.4: + version "2.0.6" + resolved "https://registry.yarnpkg.com/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz#3d8a5c66883a16a30ca8643e851f19baa7797917" + +figures@^1.3.5: + version "1.7.0" + resolved "https://registry.yarnpkg.com/figures/-/figures-1.7.0.tgz#cbe1e3affcf1cd44b80cadfed28dc793a9701d2e" + dependencies: + escape-string-regexp "^1.0.5" + object-assign "^4.1.0" + +file-entry-cache@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/file-entry-cache/-/file-entry-cache-2.0.0.tgz#c392990c3e684783d838b8c84a45d8a048458361" + dependencies: + flat-cache "^1.2.1" + object-assign "^4.0.1" + +filename-regex@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/filename-regex/-/filename-regex-2.0.0.tgz#996e3e80479b98b9897f15a8a58b3d084e926775" + +fill-range@^2.1.0: + version "2.2.3" + resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-2.2.3.tgz#50b77dfd7e469bc7492470963699fe7a8485a723" + dependencies: + is-number "^2.1.0" + isobject "^2.0.0" + randomatic "^1.1.3" + repeat-element "^1.1.2" + repeat-string "^1.5.2" + +find-index@^0.1.1: + version "0.1.1" + resolved "https://registry.yarnpkg.com/find-index/-/find-index-0.1.1.tgz#675d358b2ca3892d795a1ab47232f8b6e2e0dde4" + +find-up@^1.0.0: + version "1.1.2" + resolved "https://registry.yarnpkg.com/find-up/-/find-up-1.1.2.tgz#6b2e9822b1a2ce0a60ab64d610eccad53cb24d0f" + dependencies: + path-exists "^2.0.0" + pinkie-promise "^2.0.0" + +findup-sync@^0.4.2: + version "0.4.3" + resolved "https://registry.yarnpkg.com/findup-sync/-/findup-sync-0.4.3.tgz#40043929e7bc60adf0b7f4827c4c6e75a0deca12" + dependencies: + detect-file "^0.1.0" + is-glob "^2.0.1" + micromatch "^2.3.7" + resolve-dir "^0.1.0" + +fined@^1.0.1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/fined/-/fined-1.0.2.tgz#5b28424b760d7598960b7ef8480dff8ad3660e97" + dependencies: + expand-tilde "^1.2.1" + lodash.assignwith "^4.0.7" + lodash.isempty "^4.2.1" + lodash.isplainobject "^4.0.4" + lodash.isstring "^4.0.1" + lodash.pick "^4.2.1" + parse-filepath "^1.0.1" + +first-chunk-stream@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/first-chunk-stream/-/first-chunk-stream-1.0.0.tgz#59bfb50cd905f60d7c394cd3d9acaab4e6ad934e" + +flagged-respawn@^0.3.2: + version "0.3.2" + resolved "https://registry.yarnpkg.com/flagged-respawn/-/flagged-respawn-0.3.2.tgz#ff191eddcd7088a675b2610fffc976be9b8074b5" + +flat-cache@^1.2.1: + version "1.2.2" + resolved "https://registry.yarnpkg.com/flat-cache/-/flat-cache-1.2.2.tgz#fa86714e72c21db88601761ecf2f555d1abc6b96" + dependencies: + circular-json "^0.3.1" + del "^2.0.2" + graceful-fs "^4.1.2" + write "^0.2.1" + +for-in@^0.1.5: + version "0.1.6" + resolved "https://registry.yarnpkg.com/for-in/-/for-in-0.1.6.tgz#c9f96e89bfad18a545af5ec3ed352a1d9e5b4dc8" + +for-own@^0.1.4: + version "0.1.4" + resolved "https://registry.yarnpkg.com/for-own/-/for-own-0.1.4.tgz#0149b41a39088c7515f51ebe1c1386d45f935072" + dependencies: + for-in "^0.1.5" + +fs-exists-sync@^0.1.0: + version "0.1.0" + resolved "https://registry.yarnpkg.com/fs-exists-sync/-/fs-exists-sync-0.1.0.tgz#982d6893af918e72d08dec9e8673ff2b5a8d6add" + +fs.realpath@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f" + +function-bind@^1.0.2: + version "1.1.0" + resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.0.tgz#16176714c801798e4e8f2cf7f7529467bb4a5771" + +gaze@^0.5.1: + version "0.5.2" + resolved "https://registry.yarnpkg.com/gaze/-/gaze-0.5.2.tgz#40b709537d24d1d45767db5a908689dfe69ac44f" + dependencies: + globule "~0.1.0" + +generate-function@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/generate-function/-/generate-function-2.0.0.tgz#6858fe7c0969b7d4e9093337647ac79f60dfbe74" + +generate-object-property@^1.1.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/generate-object-property/-/generate-object-property-1.2.0.tgz#9c0e1c40308ce804f4783618b937fa88f99d50d0" + dependencies: + is-property "^1.0.0" + +glob-base@^0.3.0: + version "0.3.0" + resolved "https://registry.yarnpkg.com/glob-base/-/glob-base-0.3.0.tgz#dbb164f6221b1c0b1ccf82aea328b497df0ea3c4" + dependencies: + glob-parent "^2.0.0" + is-glob "^2.0.0" + +glob-parent@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-2.0.0.tgz#81383d72db054fcccf5336daa902f182f6edbb28" + dependencies: + is-glob "^2.0.0" + +glob-stream@^3.1.5: + version "3.1.18" + resolved "https://registry.yarnpkg.com/glob-stream/-/glob-stream-3.1.18.tgz#9170a5f12b790306fdfe598f313f8f7954fd143b" + dependencies: + glob "^4.3.1" + glob2base "^0.0.12" + minimatch "^2.0.1" + ordered-read-streams "^0.1.0" + through2 "^0.6.1" + unique-stream "^1.0.0" + +glob-watcher@^0.0.6: + version "0.0.6" + resolved "https://registry.yarnpkg.com/glob-watcher/-/glob-watcher-0.0.6.tgz#b95b4a8df74b39c83298b0c05c978b4d9a3b710b" + dependencies: + gaze "^0.5.1" + +glob2base@^0.0.12: + version "0.0.12" + resolved "https://registry.yarnpkg.com/glob2base/-/glob2base-0.0.12.tgz#9d419b3e28f12e83a362164a277055922c9c0d56" + dependencies: + find-index "^0.1.1" + +glob@3.2.11: + version "3.2.11" + resolved "https://registry.yarnpkg.com/glob/-/glob-3.2.11.tgz#4a973f635b9190f715d10987d5c00fd2815ebe3d" + dependencies: + inherits "2" + minimatch "0.3" + +glob@^4.3.1: + version "4.5.3" + resolved "https://registry.yarnpkg.com/glob/-/glob-4.5.3.tgz#c6cb73d3226c1efef04de3c56d012f03377ee15f" + dependencies: + inflight "^1.0.4" + inherits "2" + minimatch "^2.0.1" + once "^1.3.0" + +glob@^7.0.0, glob@^7.0.3, glob@^7.0.5: + version "7.1.1" + resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.1.tgz#805211df04faaf1c63a3600306cdf5ade50b2ec8" + dependencies: + fs.realpath "^1.0.0" + inflight "^1.0.4" + inherits "2" + minimatch "^3.0.2" + once "^1.3.0" + path-is-absolute "^1.0.0" + +glob@~3.1.21: + version "3.1.21" + resolved "https://registry.yarnpkg.com/glob/-/glob-3.1.21.tgz#d29e0a055dea5138f4d07ed40e8982e83c2066cd" + dependencies: + graceful-fs "~1.2.0" + inherits "1" + minimatch "~0.2.11" + +global-modules@^0.2.3: + version "0.2.3" + resolved "https://registry.yarnpkg.com/global-modules/-/global-modules-0.2.3.tgz#ea5a3bed42c6d6ce995a4f8a1269b5dae223828d" + dependencies: + global-prefix "^0.1.4" + is-windows "^0.2.0" + +global-prefix@^0.1.4: + version "0.1.5" + resolved "https://registry.yarnpkg.com/global-prefix/-/global-prefix-0.1.5.tgz#8d3bc6b8da3ca8112a160d8d496ff0462bfef78f" + dependencies: + homedir-polyfill "^1.0.0" + ini "^1.3.4" + is-windows "^0.2.0" + which "^1.2.12" + +globals@^9.0.0, globals@^9.14.0: + version "9.16.0" + resolved "https://registry.yarnpkg.com/globals/-/globals-9.16.0.tgz#63e903658171ec2d9f51b1d31de5e2b8dc01fb80" + +globby@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/globby/-/globby-5.0.0.tgz#ebd84667ca0dbb330b99bcfc68eac2bc54370e0d" + dependencies: + array-union "^1.0.1" + arrify "^1.0.0" + glob "^7.0.3" + object-assign "^4.0.1" + pify "^2.0.0" + pinkie-promise "^2.0.0" + +globule@~0.1.0: + version "0.1.0" + resolved "https://registry.yarnpkg.com/globule/-/globule-0.1.0.tgz#d9c8edde1da79d125a151b79533b978676346ae5" + dependencies: + glob "~3.1.21" + lodash "~1.0.1" + minimatch "~0.2.11" + +glogg@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/glogg/-/glogg-1.0.0.tgz#7fe0f199f57ac906cf512feead8f90ee4a284fc5" + dependencies: + sparkles "^1.0.0" + +graceful-fs@4.X, graceful-fs@^4.1.2: + version "4.1.11" + resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.1.11.tgz#0e8bdfe4d1ddb8854d64e04ea7c00e2a026e5658" + +graceful-fs@^3.0.0: + version "3.0.11" + resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-3.0.11.tgz#7613c778a1afea62f25c630a086d7f3acbbdd818" + dependencies: + natives "^1.1.0" + +graceful-fs@~1.2.0: + version "1.2.3" + resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-1.2.3.tgz#15a4806a57547cb2d2dbf27f42e89a8c3451b364" + +growl@1.9.2: + version "1.9.2" + resolved "https://registry.yarnpkg.com/growl/-/growl-1.9.2.tgz#0ea7743715db8d8de2c5ede1775e1b45ac85c02f" + +gulp-babel@^6.1.2: + version "6.1.2" + resolved "https://registry.yarnpkg.com/gulp-babel/-/gulp-babel-6.1.2.tgz#7c0176e4ba3f244c60588a0c4b320a45d1adefce" + dependencies: + babel-core "^6.0.2" + gulp-util "^3.0.0" + object-assign "^4.0.1" + replace-ext "0.0.1" + through2 "^2.0.0" + vinyl-sourcemaps-apply "^0.2.0" + +gulp-sourcemaps@^2.0.0-alpha: + version "2.4.1" + resolved "https://registry.yarnpkg.com/gulp-sourcemaps/-/gulp-sourcemaps-2.4.1.tgz#8f65dc5c0d07b2fd5c88bc60ec7f13e56716bf74" + dependencies: + acorn "4.X" + convert-source-map "1.X" + css "2.X" + debug-fabulous "0.0.X" + detect-newline "2.X" + graceful-fs "4.X" + source-map "0.X" + strip-bom "3.X" + through2 "2.X" + vinyl "1.X" + +gulp-util@^3.0.0: + version "3.0.8" + resolved "https://registry.yarnpkg.com/gulp-util/-/gulp-util-3.0.8.tgz#0054e1e744502e27c04c187c3ecc505dd54bbb4f" + dependencies: + array-differ "^1.0.0" + array-uniq "^1.0.2" + beeper "^1.0.0" + chalk "^1.0.0" + dateformat "^2.0.0" + fancy-log "^1.1.0" + gulplog "^1.0.0" + has-gulplog "^0.1.0" + lodash._reescape "^3.0.0" + lodash._reevaluate "^3.0.0" + lodash._reinterpolate "^3.0.0" + lodash.template "^3.0.0" + minimist "^1.1.0" + multipipe "^0.1.2" + object-assign "^3.0.0" + replace-ext "0.0.1" + through2 "^2.0.0" + vinyl "^0.5.0" + +gulp@^3.9.1: + version "3.9.1" + resolved "https://registry.yarnpkg.com/gulp/-/gulp-3.9.1.tgz#571ce45928dd40af6514fc4011866016c13845b4" + dependencies: + archy "^1.0.0" + chalk "^1.0.0" + deprecated "^0.0.1" + gulp-util "^3.0.0" + interpret "^1.0.0" + liftoff "^2.1.0" + minimist "^1.1.0" + orchestrator "^0.3.0" + pretty-hrtime "^1.0.0" + semver "^4.1.0" + tildify "^1.0.0" + v8flags "^2.0.2" + vinyl-fs "^0.3.0" + +gulplog@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/gulplog/-/gulplog-1.0.0.tgz#e28c4d45d05ecbbed818363ce8f9c5926229ffe5" + dependencies: + glogg "^1.0.0" + +has-ansi@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/has-ansi/-/has-ansi-2.0.0.tgz#34f5049ce1ecdf2b0649af3ef24e45ed35416d91" + dependencies: + ansi-regex "^2.0.0" + +has-gulplog@^0.1.0: + version "0.1.0" + resolved "https://registry.yarnpkg.com/has-gulplog/-/has-gulplog-0.1.0.tgz#6414c82913697da51590397dafb12f22967811ce" + dependencies: + sparkles "^1.0.0" + +has@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/has/-/has-1.0.1.tgz#8461733f538b0837c9361e39a9ab9e9704dc2f28" + dependencies: + function-bind "^1.0.2" + +home-or-tmp@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/home-or-tmp/-/home-or-tmp-2.0.0.tgz#e36c3f2d2cae7d746a857e38d18d5f32a7882db8" + dependencies: + os-homedir "^1.0.0" + os-tmpdir "^1.0.1" + +homedir-polyfill@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/homedir-polyfill/-/homedir-polyfill-1.0.1.tgz#4c2bbc8a758998feebf5ed68580f76d46768b4bc" + dependencies: + parse-passwd "^1.0.0" + +ignore@^3.2.0: + version "3.2.4" + resolved "https://registry.yarnpkg.com/ignore/-/ignore-3.2.4.tgz#4055e03596729a8fabe45a43c100ad5ed815c4e8" + +imurmurhash@^0.1.4: + version "0.1.4" + resolved "https://registry.yarnpkg.com/imurmurhash/-/imurmurhash-0.1.4.tgz#9218b9b2b928a238b13dc4fb6b6d576f231453ea" + +inflight@^1.0.4: + version "1.0.6" + resolved "https://registry.yarnpkg.com/inflight/-/inflight-1.0.6.tgz#49bd6331d7d02d0c09bc910a1075ba8165b56df9" + dependencies: + once "^1.3.0" + wrappy "1" + +inherits@1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/inherits/-/inherits-1.0.2.tgz#ca4309dadee6b54cc0b8d247e8d7c7a0975bdc9b" + +inherits@2, inherits@^2.0.1, inherits@^2.0.3, inherits@~2.0.1: + version "2.0.3" + resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.3.tgz#633c2c83e3da42a502f52466022480f4208261de" + +ini@^1.3.4: + version "1.3.4" + resolved "https://registry.yarnpkg.com/ini/-/ini-1.3.4.tgz#0537cb79daf59b59a1a517dff706c86ec039162e" + +inquirer@^0.12.0: + version "0.12.0" + resolved "https://registry.yarnpkg.com/inquirer/-/inquirer-0.12.0.tgz#1ef2bfd63504df0bc75785fff8c2c41df12f077e" + dependencies: + ansi-escapes "^1.1.0" + ansi-regex "^2.0.0" + chalk "^1.0.0" + cli-cursor "^1.0.1" + cli-width "^2.0.0" + figures "^1.3.5" + lodash "^4.3.0" + readline2 "^1.0.1" + run-async "^0.1.0" + rx-lite "^3.1.2" + string-width "^1.0.1" + strip-ansi "^3.0.0" + through "^2.3.6" + +interpret@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/interpret/-/interpret-1.0.1.tgz#d579fb7f693b858004947af39fa0db49f795602c" + +invariant@^2.2.0: + version "2.2.2" + resolved "https://registry.yarnpkg.com/invariant/-/invariant-2.2.2.tgz#9e1f56ac0acdb6bf303306f338be3b204ae60360" + dependencies: + loose-envify "^1.0.0" + +is-absolute@^0.2.3: + version "0.2.6" + resolved "https://registry.yarnpkg.com/is-absolute/-/is-absolute-0.2.6.tgz#20de69f3db942ef2d87b9c2da36f172235b1b5eb" + dependencies: + is-relative "^0.2.1" + is-windows "^0.2.0" + +is-buffer@^1.0.2: + version "1.1.4" + resolved "https://registry.yarnpkg.com/is-buffer/-/is-buffer-1.1.4.tgz#cfc86ccd5dc5a52fa80489111c6920c457e2d98b" + +is-dotfile@^1.0.0: + version "1.0.2" + resolved "https://registry.yarnpkg.com/is-dotfile/-/is-dotfile-1.0.2.tgz#2c132383f39199f8edc268ca01b9b007d205cc4d" + +is-equal-shallow@^0.1.3: + version "0.1.3" + resolved "https://registry.yarnpkg.com/is-equal-shallow/-/is-equal-shallow-0.1.3.tgz#2238098fc221de0bcfa5d9eac4c45d638aa1c534" + dependencies: + is-primitive "^2.0.0" + +is-extendable@^0.1.1: + version "0.1.1" + resolved "https://registry.yarnpkg.com/is-extendable/-/is-extendable-0.1.1.tgz#62b110e289a471418e3ec36a617d472e301dfc89" + +is-extglob@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/is-extglob/-/is-extglob-1.0.0.tgz#ac468177c4943405a092fc8f29760c6ffc6206c0" + +is-finite@^1.0.0: + version "1.0.2" + resolved "https://registry.yarnpkg.com/is-finite/-/is-finite-1.0.2.tgz#cc6677695602be550ef11e8b4aa6305342b6d0aa" + dependencies: + number-is-nan "^1.0.0" + +is-fullwidth-code-point@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz#ef9e31386f031a7f0d643af82fde50c457ef00cb" + dependencies: + number-is-nan "^1.0.0" + +is-fullwidth-code-point@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz#a3b30a5c4f199183167aaab93beefae3ddfb654f" + +is-glob@^2.0.0, is-glob@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-2.0.1.tgz#d096f926a3ded5600f3fdfd91198cb0888c2d863" + dependencies: + is-extglob "^1.0.0" + +is-my-json-valid@^2.10.0: + version "2.16.0" + resolved "https://registry.yarnpkg.com/is-my-json-valid/-/is-my-json-valid-2.16.0.tgz#f079dd9bfdae65ee2038aae8acbc86ab109e3693" + dependencies: + generate-function "^2.0.0" + generate-object-property "^1.1.0" + jsonpointer "^4.0.0" + xtend "^4.0.0" + +is-number@^2.0.2, is-number@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/is-number/-/is-number-2.1.0.tgz#01fcbbb393463a548f2f466cce16dece49db908f" + dependencies: + kind-of "^3.0.2" + +is-path-cwd@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/is-path-cwd/-/is-path-cwd-1.0.0.tgz#d225ec23132e89edd38fda767472e62e65f1106d" + +is-path-in-cwd@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/is-path-in-cwd/-/is-path-in-cwd-1.0.0.tgz#6477582b8214d602346094567003be8a9eac04dc" + dependencies: + is-path-inside "^1.0.0" + +is-path-inside@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/is-path-inside/-/is-path-inside-1.0.0.tgz#fc06e5a1683fbda13de667aff717bbc10a48f37f" + dependencies: + path-is-inside "^1.0.1" + +is-posix-bracket@^0.1.0: + version "0.1.1" + resolved "https://registry.yarnpkg.com/is-posix-bracket/-/is-posix-bracket-0.1.1.tgz#3334dc79774368e92f016e6fbc0a88f5cd6e6bc4" + +is-primitive@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/is-primitive/-/is-primitive-2.0.0.tgz#207bab91638499c07b2adf240a41a87210034575" + +is-property@^1.0.0: + version "1.0.2" + resolved "https://registry.yarnpkg.com/is-property/-/is-property-1.0.2.tgz#57fe1c4e48474edd65b09911f26b1cd4095dda84" + +is-relative@^0.2.1: + version "0.2.1" + resolved "https://registry.yarnpkg.com/is-relative/-/is-relative-0.2.1.tgz#d27f4c7d516d175fb610db84bbeef23c3bc97aa5" + dependencies: + is-unc-path "^0.1.1" + +is-resolvable@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/is-resolvable/-/is-resolvable-1.0.0.tgz#8df57c61ea2e3c501408d100fb013cf8d6e0cc62" + dependencies: + tryit "^1.0.1" + +is-unc-path@^0.1.1: + version "0.1.2" + resolved "https://registry.yarnpkg.com/is-unc-path/-/is-unc-path-0.1.2.tgz#6ab053a72573c10250ff416a3814c35178af39b9" + dependencies: + unc-path-regex "^0.1.0" + +is-utf8@^0.2.0: + version "0.2.1" + resolved "https://registry.yarnpkg.com/is-utf8/-/is-utf8-0.2.1.tgz#4b0da1442104d1b336340e80797e865cf39f7d72" + +is-windows@^0.2.0: + version "0.2.0" + resolved "https://registry.yarnpkg.com/is-windows/-/is-windows-0.2.0.tgz#de1aa6d63ea29dd248737b69f1ff8b8002d2108c" + +isarray@0.0.1: + version "0.0.1" + resolved "https://registry.yarnpkg.com/isarray/-/isarray-0.0.1.tgz#8a18acfca9a8f4177e09abfc6038939b05d1eedf" + +isarray@1.0.0, isarray@^1.0.0, isarray@~1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/isarray/-/isarray-1.0.0.tgz#bb935d48582cba168c06834957a54a3e07124f11" + +isexe@^1.1.1: + version "1.1.2" + resolved "https://registry.yarnpkg.com/isexe/-/isexe-1.1.2.tgz#36f3e22e60750920f5e7241a476a8c6a42275ad0" + +isobject@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/isobject/-/isobject-2.1.0.tgz#f065561096a3f1da2ef46272f815c840d87e0c89" + dependencies: + isarray "1.0.0" + +jade@0.26.3: + version "0.26.3" + resolved "https://registry.yarnpkg.com/jade/-/jade-0.26.3.tgz#8f10d7977d8d79f2f6ff862a81b0513ccb25686c" + dependencies: + commander "0.6.1" + mkdirp "0.3.0" + +js-tokens@^3.0.0: + version "3.0.1" + resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-3.0.1.tgz#08e9f132484a2c45a30907e9dc4d5567b7f114d7" + +js-yaml@^3.5.1: + version "3.8.1" + resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.8.1.tgz#782ba50200be7b9e5a8537001b7804db3ad02628" + dependencies: + argparse "^1.0.7" + esprima "^3.1.1" + +jsesc@^1.3.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-1.3.0.tgz#46c3fec8c1892b12b0833db9bc7622176dbab34b" + +jsesc@~0.5.0: + version "0.5.0" + resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-0.5.0.tgz#e7dee66e35d6fc16f710fe91d5cf69f70f08911d" + +json-stable-stringify@^1.0.0, json-stable-stringify@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/json-stable-stringify/-/json-stable-stringify-1.0.1.tgz#9a759d39c5f2ff503fd5300646ed445f88c4f9af" + dependencies: + jsonify "~0.0.0" + +json5@^0.5.0: + version "0.5.1" + resolved "https://registry.yarnpkg.com/json5/-/json5-0.5.1.tgz#1eade7acc012034ad84e2396767ead9fa5495821" + +jsonify@~0.0.0: + version "0.0.0" + resolved "https://registry.yarnpkg.com/jsonify/-/jsonify-0.0.0.tgz#2c74b6ee41d93ca51b7b5aaee8f503631d252a73" + +jsonpointer@^4.0.0: + version "4.0.1" + resolved "https://registry.yarnpkg.com/jsonpointer/-/jsonpointer-4.0.1.tgz#4fd92cb34e0e9db3c89c8622ecf51f9b978c6cb9" + +kind-of@^3.0.2: + version "3.1.0" + resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-3.1.0.tgz#475d698a5e49ff5e53d14e3e732429dc8bf4cf47" + dependencies: + is-buffer "^1.0.2" + +lazy-cache@^1.0.3: + version "1.0.4" + resolved "https://registry.yarnpkg.com/lazy-cache/-/lazy-cache-1.0.4.tgz#a1d78fc3a50474cb80845d3b3b6e1da49a446e8e" + +lazy-debug-legacy@0.0.X: + version "0.0.1" + resolved "https://registry.yarnpkg.com/lazy-debug-legacy/-/lazy-debug-legacy-0.0.1.tgz#537716c0776e4cf79e3ed1b621f7658c2911b1b1" + +levn@^0.3.0, levn@~0.3.0: + version "0.3.0" + resolved "https://registry.yarnpkg.com/levn/-/levn-0.3.0.tgz#3b09924edf9f083c0490fdd4c0bc4421e04764ee" + dependencies: + prelude-ls "~1.1.2" + type-check "~0.3.2" + +liftoff@^2.1.0: + version "2.3.0" + resolved "https://registry.yarnpkg.com/liftoff/-/liftoff-2.3.0.tgz#a98f2ff67183d8ba7cfaca10548bd7ff0550b385" + dependencies: + extend "^3.0.0" + findup-sync "^0.4.2" + fined "^1.0.1" + flagged-respawn "^0.3.2" + lodash.isplainobject "^4.0.4" + lodash.isstring "^4.0.1" + lodash.mapvalues "^4.4.0" + rechoir "^0.6.2" + resolve "^1.1.7" + +lodash._basecopy@^3.0.0: + version "3.0.1" + resolved "https://registry.yarnpkg.com/lodash._basecopy/-/lodash._basecopy-3.0.1.tgz#8da0e6a876cf344c0ad8a54882111dd3c5c7ca36" + +lodash._basetostring@^3.0.0: + version "3.0.1" + resolved "https://registry.yarnpkg.com/lodash._basetostring/-/lodash._basetostring-3.0.1.tgz#d1861d877f824a52f669832dcaf3ee15566a07d5" + +lodash._basevalues@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/lodash._basevalues/-/lodash._basevalues-3.0.0.tgz#5b775762802bde3d3297503e26300820fdf661b7" + +lodash._getnative@^3.0.0: + version "3.9.1" + resolved "https://registry.yarnpkg.com/lodash._getnative/-/lodash._getnative-3.9.1.tgz#570bc7dede46d61cdcde687d65d3eecbaa3aaff5" + +lodash._isiterateecall@^3.0.0: + version "3.0.9" + resolved "https://registry.yarnpkg.com/lodash._isiterateecall/-/lodash._isiterateecall-3.0.9.tgz#5203ad7ba425fae842460e696db9cf3e6aac057c" + +lodash._reescape@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/lodash._reescape/-/lodash._reescape-3.0.0.tgz#2b1d6f5dfe07c8a355753e5f27fac7f1cde1616a" + +lodash._reevaluate@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/lodash._reevaluate/-/lodash._reevaluate-3.0.0.tgz#58bc74c40664953ae0b124d806996daca431e2ed" + +lodash._reinterpolate@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/lodash._reinterpolate/-/lodash._reinterpolate-3.0.0.tgz#0ccf2d89166af03b3663c796538b75ac6e114d9d" + +lodash._root@^3.0.0: + version "3.0.1" + resolved "https://registry.yarnpkg.com/lodash._root/-/lodash._root-3.0.1.tgz#fba1c4524c19ee9a5f8136b4609f017cf4ded692" + +lodash.assignwith@^4.0.7: + version "4.2.0" + resolved "https://registry.yarnpkg.com/lodash.assignwith/-/lodash.assignwith-4.2.0.tgz#127a97f02adc41751a954d24b0de17e100e038eb" + +lodash.cond@^4.3.0: + version "4.5.2" + resolved "https://registry.yarnpkg.com/lodash.cond/-/lodash.cond-4.5.2.tgz#f471a1da486be60f6ab955d17115523dd1d255d5" + +lodash.escape@^3.0.0: + version "3.2.0" + resolved "https://registry.yarnpkg.com/lodash.escape/-/lodash.escape-3.2.0.tgz#995ee0dc18c1b48cc92effae71a10aab5b487698" + dependencies: + lodash._root "^3.0.0" + +lodash.isarguments@^3.0.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/lodash.isarguments/-/lodash.isarguments-3.1.0.tgz#2f573d85c6a24289ff00663b491c1d338ff3458a" + +lodash.isarray@^3.0.0: + version "3.0.4" + resolved "https://registry.yarnpkg.com/lodash.isarray/-/lodash.isarray-3.0.4.tgz#79e4eb88c36a8122af86f844aa9bcd851b5fbb55" + +lodash.isempty@^4.2.1: + version "4.4.0" + resolved "https://registry.yarnpkg.com/lodash.isempty/-/lodash.isempty-4.4.0.tgz#6f86cbedd8be4ec987be9aaf33c9684db1b31e7e" + +lodash.isplainobject@^4.0.4: + version "4.0.6" + resolved "https://registry.yarnpkg.com/lodash.isplainobject/-/lodash.isplainobject-4.0.6.tgz#7c526a52d89b45c45cc690b88163be0497f550cb" + +lodash.isstring@^4.0.1: + version "4.0.1" + resolved "https://registry.yarnpkg.com/lodash.isstring/-/lodash.isstring-4.0.1.tgz#d527dfb5456eca7cc9bb95d5daeaf88ba54a5451" + +lodash.keys@^3.0.0: + version "3.1.2" + resolved "https://registry.yarnpkg.com/lodash.keys/-/lodash.keys-3.1.2.tgz#4dbc0472b156be50a0b286855d1bd0b0c656098a" + dependencies: + lodash._getnative "^3.0.0" + lodash.isarguments "^3.0.0" + lodash.isarray "^3.0.0" + +lodash.mapvalues@^4.4.0: + version "4.6.0" + resolved "https://registry.yarnpkg.com/lodash.mapvalues/-/lodash.mapvalues-4.6.0.tgz#1bafa5005de9dd6f4f26668c30ca37230cc9689c" + +lodash.pick@^4.2.1: + version "4.4.0" + resolved "https://registry.yarnpkg.com/lodash.pick/-/lodash.pick-4.4.0.tgz#52f05610fff9ded422611441ed1fc123a03001b3" + +lodash.restparam@^3.0.0: + version "3.6.1" + resolved "https://registry.yarnpkg.com/lodash.restparam/-/lodash.restparam-3.6.1.tgz#936a4e309ef330a7645ed4145986c85ae5b20805" + +lodash.template@^3.0.0: + version "3.6.2" + resolved "https://registry.yarnpkg.com/lodash.template/-/lodash.template-3.6.2.tgz#f8cdecc6169a255be9098ae8b0c53d378931d14f" + dependencies: + lodash._basecopy "^3.0.0" + lodash._basetostring "^3.0.0" + lodash._basevalues "^3.0.0" + lodash._isiterateecall "^3.0.0" + lodash._reinterpolate "^3.0.0" + lodash.escape "^3.0.0" + lodash.keys "^3.0.0" + lodash.restparam "^3.0.0" + lodash.templatesettings "^3.0.0" + +lodash.templatesettings@^3.0.0: + version "3.1.1" + resolved "https://registry.yarnpkg.com/lodash.templatesettings/-/lodash.templatesettings-3.1.1.tgz#fb307844753b66b9f1afa54e262c745307dba8e5" + dependencies: + lodash._reinterpolate "^3.0.0" + lodash.escape "^3.0.0" + +lodash@^4.0.0, lodash@^4.2.0, lodash@^4.3.0: + version "4.17.4" + resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.4.tgz#78203a4d1c328ae1d86dca6460e369b57f4055ae" + +lodash@~1.0.1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/lodash/-/lodash-1.0.2.tgz#8f57560c83b59fc270bd3d561b690043430e2551" + +longest@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/longest/-/longest-1.0.1.tgz#30a0b2da38f73770e8294a0d22e6625ed77d0097" + +loose-envify@^1.0.0: + version "1.3.1" + resolved "https://registry.yarnpkg.com/loose-envify/-/loose-envify-1.3.1.tgz#d1a8ad33fa9ce0e713d65fdd0ac8b748d478c848" + dependencies: + js-tokens "^3.0.0" + +lru-cache@2: + version "2.7.3" + resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-2.7.3.tgz#6d4524e8b955f95d4f5b58851ce21dd72fb4e952" + +map-cache@^0.2.0: + version "0.2.2" + resolved "https://registry.yarnpkg.com/map-cache/-/map-cache-0.2.2.tgz#c32abd0bd6525d9b051645bb4f26ac5dc98a0dbf" + +micromatch@^2.3.7: + version "2.3.11" + resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-2.3.11.tgz#86677c97d1720b363431d04d0d15293bd38c1565" + dependencies: + arr-diff "^2.0.0" + array-unique "^0.2.1" + braces "^1.8.2" + expand-brackets "^0.1.4" + extglob "^0.3.1" + filename-regex "^2.0.0" + is-extglob "^1.0.0" + is-glob "^2.0.1" + kind-of "^3.0.2" + normalize-path "^2.0.1" + object.omit "^2.0.0" + parse-glob "^3.0.4" + regex-cache "^0.4.2" + +minimatch@0.3: + version "0.3.0" + resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-0.3.0.tgz#275d8edaac4f1bb3326472089e7949c8394699dd" + dependencies: + lru-cache "2" + sigmund "~1.0.0" + +minimatch@^2.0.1: + version "2.0.10" + resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-2.0.10.tgz#8d087c39c6b38c001b97fca7ce6d0e1e80afbac7" + dependencies: + brace-expansion "^1.0.0" + +minimatch@^3.0.2, minimatch@^3.0.3: + version "3.0.3" + resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.0.3.tgz#2a4e4090b96b2db06a9d7df01055a62a77c9b774" + dependencies: + brace-expansion "^1.0.0" + +minimatch@~0.2.11: + version "0.2.14" + resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-0.2.14.tgz#c74e780574f63c6f9a090e90efbe6ef53a6a756a" + dependencies: + lru-cache "2" + sigmund "~1.0.0" + +minimist@0.0.8: + version "0.0.8" + resolved "https://registry.yarnpkg.com/minimist/-/minimist-0.0.8.tgz#857fcabfc3397d2625b8228262e86aa7a011b05d" + +minimist@^1.1.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.0.tgz#a35008b20f41383eec1fb914f4cd5df79a264284" + +mkdirp@0.3.0: + version "0.3.0" + resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.3.0.tgz#1bbf5ab1ba827af23575143490426455f481fe1e" + +mkdirp@0.5.1, mkdirp@^0.5.0, mkdirp@^0.5.1: + version "0.5.1" + resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.5.1.tgz#30057438eac6cf7f8c4767f38648d6697d75c903" + dependencies: + minimist "0.0.8" + +mocha@^2.4.5: + version "2.5.3" + resolved "https://registry.yarnpkg.com/mocha/-/mocha-2.5.3.tgz#161be5bdeb496771eb9b35745050b622b5aefc58" + dependencies: + commander "2.3.0" + debug "2.2.0" + diff "1.4.0" + escape-string-regexp "1.0.2" + glob "3.2.11" + growl "1.9.2" + jade "0.26.3" + mkdirp "0.5.1" + supports-color "1.2.0" + to-iso-string "0.0.2" + +modify-babel-preset@^2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/modify-babel-preset/-/modify-babel-preset-2.1.1.tgz#2d3190162ee62fb67aaa3325c242f026322ebbac" + dependencies: + require-relative "^0.8.7" + +ms@0.7.1: + version "0.7.1" + resolved "https://registry.yarnpkg.com/ms/-/ms-0.7.1.tgz#9cd13c03adbff25b65effde7ce864ee952017098" + +ms@0.7.2: + version "0.7.2" + resolved "https://registry.yarnpkg.com/ms/-/ms-0.7.2.tgz#ae25cf2512b3885a1d95d7f037868d8431124765" + +multipipe@^0.1.2: + version "0.1.2" + resolved "https://registry.yarnpkg.com/multipipe/-/multipipe-0.1.2.tgz#2a8f2ddf70eed564dff2d57f1e1a137d9f05078b" + dependencies: + duplexer2 "0.0.2" + +mute-stream@0.0.5: + version "0.0.5" + resolved "https://registry.yarnpkg.com/mute-stream/-/mute-stream-0.0.5.tgz#8fbfabb0a98a253d3184331f9e8deb7372fac6c0" + +natives@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/natives/-/natives-1.1.0.tgz#e9ff841418a6b2ec7a495e939984f78f163e6e31" + +natural-compare@^1.4.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/natural-compare/-/natural-compare-1.4.0.tgz#4abebfeed7541f2c27acfb29bdbbd15c8d5ba4f7" + +normalize-path@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/normalize-path/-/normalize-path-2.0.1.tgz#47886ac1662760d4261b7d979d241709d3ce3f7a" + +number-is-nan@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/number-is-nan/-/number-is-nan-1.0.1.tgz#097b602b53422a522c1afb8790318336941a011d" + +object-assign@4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-4.1.0.tgz#7a3b3d0e98063d43f4c03f2e8ae6cd51a86883a0" + +object-assign@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-3.0.0.tgz#9bedd5ca0897949bca47e7ff408062d549f587f2" + +object-assign@^4.0.1, object-assign@^4.1.0: + version "4.1.1" + resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-4.1.1.tgz#2109adc7965887cfc05cbbd442cac8bfbb360863" + +object.omit@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/object.omit/-/object.omit-2.0.1.tgz#1a9c744829f39dbb858c76ca3579ae2a54ebd1fa" + dependencies: + for-own "^0.1.4" + is-extendable "^0.1.1" + +once@^1.3.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1" + dependencies: + wrappy "1" + +once@~1.3.0: + version "1.3.3" + resolved "https://registry.yarnpkg.com/once/-/once-1.3.3.tgz#b2e261557ce4c314ec8304f3fa82663e4297ca20" + dependencies: + wrappy "1" + +onetime@^1.0.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/onetime/-/onetime-1.1.0.tgz#a1f7838f8314c516f05ecefcbc4ccfe04b4ed789" + +optionator@^0.8.2: + version "0.8.2" + resolved "https://registry.yarnpkg.com/optionator/-/optionator-0.8.2.tgz#364c5e409d3f4d6301d6c0b4c05bba50180aeb64" + dependencies: + deep-is "~0.1.3" + fast-levenshtein "~2.0.4" + levn "~0.3.0" + prelude-ls "~1.1.2" + type-check "~0.3.2" + wordwrap "~1.0.0" + +orchestrator@^0.3.0: + version "0.3.8" + resolved "https://registry.yarnpkg.com/orchestrator/-/orchestrator-0.3.8.tgz#14e7e9e2764f7315fbac184e506c7aa6df94ad7e" + dependencies: + end-of-stream "~0.1.5" + sequencify "~0.0.7" + stream-consume "~0.1.0" + +ordered-read-streams@^0.1.0: + version "0.1.0" + resolved "https://registry.yarnpkg.com/ordered-read-streams/-/ordered-read-streams-0.1.0.tgz#fd565a9af8eb4473ba69b6ed8a34352cb552f126" + +os-homedir@^1.0.0, os-homedir@^1.0.1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/os-homedir/-/os-homedir-1.0.2.tgz#ffbc4988336e0e833de0c168c7ef152121aa7fb3" + +os-tmpdir@^1.0.1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/os-tmpdir/-/os-tmpdir-1.0.2.tgz#bbe67406c79aa85c5cfec766fe5734555dfa1274" + +parse-filepath@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/parse-filepath/-/parse-filepath-1.0.1.tgz#159d6155d43904d16c10ef698911da1e91969b73" + dependencies: + is-absolute "^0.2.3" + map-cache "^0.2.0" + path-root "^0.1.1" + +parse-glob@^3.0.4: + version "3.0.4" + resolved "https://registry.yarnpkg.com/parse-glob/-/parse-glob-3.0.4.tgz#b2c376cfb11f35513badd173ef0bb6e3a388391c" + dependencies: + glob-base "^0.3.0" + is-dotfile "^1.0.0" + is-extglob "^1.0.0" + is-glob "^2.0.0" + +parse-passwd@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/parse-passwd/-/parse-passwd-1.0.0.tgz#6d5b934a456993b23d37f40a382d6f1666a8e5c6" + +path-exists@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-2.1.0.tgz#0feb6c64f0fc518d9a754dd5efb62c7022761f4b" + dependencies: + pinkie-promise "^2.0.0" + +path-is-absolute@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f" + +path-is-inside@^1.0.1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/path-is-inside/-/path-is-inside-1.0.2.tgz#365417dede44430d1c11af61027facf074bdfc53" + +path-parse@^1.0.5: + version "1.0.5" + resolved "https://registry.yarnpkg.com/path-parse/-/path-parse-1.0.5.tgz#3c1adf871ea9cd6c9431b6ea2bd74a0ff055c4c1" + +path-root-regex@^0.1.0: + version "0.1.2" + resolved "https://registry.yarnpkg.com/path-root-regex/-/path-root-regex-0.1.2.tgz#bfccdc8df5b12dc52c8b43ec38d18d72c04ba96d" + +path-root@^0.1.1: + version "0.1.1" + resolved "https://registry.yarnpkg.com/path-root/-/path-root-0.1.1.tgz#9a4a6814cac1c0cd73360a95f32083c8ea4745b7" + dependencies: + path-root-regex "^0.1.0" + +pify@^2.0.0: + version "2.3.0" + resolved "https://registry.yarnpkg.com/pify/-/pify-2.3.0.tgz#ed141a6ac043a849ea588498e7dca8b15330e90c" + +pinkie-promise@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/pinkie-promise/-/pinkie-promise-2.0.1.tgz#2135d6dfa7a358c069ac9b178776288228450ffa" + dependencies: + pinkie "^2.0.0" + +pinkie@^2.0.0: + version "2.0.4" + resolved "https://registry.yarnpkg.com/pinkie/-/pinkie-2.0.4.tgz#72556b80cfa0d48a974e80e77248e80ed4f7f870" + +pkg-dir@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/pkg-dir/-/pkg-dir-1.0.0.tgz#7a4b508a8d5bb2d629d447056ff4e9c9314cf3d4" + dependencies: + find-up "^1.0.0" + +pkg-up@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/pkg-up/-/pkg-up-1.0.0.tgz#3e08fb461525c4421624a33b9f7e6d0af5b05a26" + dependencies: + find-up "^1.0.0" + +pluralize@^1.2.1: + version "1.2.1" + resolved "https://registry.yarnpkg.com/pluralize/-/pluralize-1.2.1.tgz#d1a21483fd22bb41e58a12fa3421823140897c45" + +prelude-ls@~1.1.2: + version "1.1.2" + resolved "https://registry.yarnpkg.com/prelude-ls/-/prelude-ls-1.1.2.tgz#21932a549f5e52ffd9a827f570e04be62a97da54" + +preserve@^0.2.0: + version "0.2.0" + resolved "https://registry.yarnpkg.com/preserve/-/preserve-0.2.0.tgz#815ed1f6ebc65926f865b310c0713bcb3315ce4b" + +pretty-hrtime@^1.0.0: + version "1.0.3" + resolved "https://registry.yarnpkg.com/pretty-hrtime/-/pretty-hrtime-1.0.3.tgz#b7e3ea42435a4c9b2759d99e0f201eb195802ee1" + +private@^0.1.6: + version "0.1.7" + resolved "https://registry.yarnpkg.com/private/-/private-0.1.7.tgz#68ce5e8a1ef0a23bb570cc28537b5332aba63ef1" + +process-nextick-args@~1.0.6: + version "1.0.7" + resolved "https://registry.yarnpkg.com/process-nextick-args/-/process-nextick-args-1.0.7.tgz#150e20b756590ad3f91093f25a4f2ad8bff30ba3" + +progress@^1.1.8: + version "1.1.8" + resolved "https://registry.yarnpkg.com/progress/-/progress-1.1.8.tgz#e260c78f6161cdd9b0e56cc3e0a85de17c7a57be" + +randomatic@^1.1.3: + version "1.1.6" + resolved "https://registry.yarnpkg.com/randomatic/-/randomatic-1.1.6.tgz#110dcabff397e9dcff7c0789ccc0a49adf1ec5bb" + dependencies: + is-number "^2.0.2" + kind-of "^3.0.2" + +"readable-stream@>=1.0.33-1 <1.1.0-0": + version "1.0.34" + resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-1.0.34.tgz#125820e34bc842d2f2aaafafe4c2916ee32c157c" + dependencies: + core-util-is "~1.0.0" + inherits "~2.0.1" + isarray "0.0.1" + string_decoder "~0.10.x" + +readable-stream@^2.1.5, readable-stream@^2.2.2: + version "2.2.3" + resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.2.3.tgz#9cf49463985df016c8ae8813097a9293a9b33729" + dependencies: + buffer-shims "^1.0.0" + core-util-is "~1.0.0" + inherits "~2.0.1" + isarray "~1.0.0" + process-nextick-args "~1.0.6" + string_decoder "~0.10.x" + util-deprecate "~1.0.1" + +readable-stream@~1.1.9: + version "1.1.14" + resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-1.1.14.tgz#7cf4c54ef648e3813084c636dd2079e166c081d9" + dependencies: + core-util-is "~1.0.0" + inherits "~2.0.1" + isarray "0.0.1" + string_decoder "~0.10.x" + +readline2@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/readline2/-/readline2-1.0.1.tgz#41059608ffc154757b715d9989d199ffbf372e35" + dependencies: + code-point-at "^1.0.0" + is-fullwidth-code-point "^1.0.0" + mute-stream "0.0.5" + +rechoir@^0.6.2: + version "0.6.2" + resolved "https://registry.yarnpkg.com/rechoir/-/rechoir-0.6.2.tgz#85204b54dba82d5742e28c96756ef43af50e3384" + dependencies: + resolve "^1.1.6" + +regenerate@^1.2.1: + version "1.3.2" + resolved "https://registry.yarnpkg.com/regenerate/-/regenerate-1.3.2.tgz#d1941c67bad437e1be76433add5b385f95b19260" + +regenerator-runtime@^0.10.0: + version "0.10.3" + resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.10.3.tgz#8c4367a904b51ea62a908ac310bf99ff90a82a3e" + +regenerator-transform@0.9.8: + version "0.9.8" + resolved "https://registry.yarnpkg.com/regenerator-transform/-/regenerator-transform-0.9.8.tgz#0f88bb2bc03932ddb7b6b7312e68078f01026d6c" + dependencies: + babel-runtime "^6.18.0" + babel-types "^6.19.0" + private "^0.1.6" + +regex-cache@^0.4.2: + version "0.4.3" + resolved "https://registry.yarnpkg.com/regex-cache/-/regex-cache-0.4.3.tgz#9b1a6c35d4d0dfcef5711ae651e8e9d3d7114145" + dependencies: + is-equal-shallow "^0.1.3" + is-primitive "^2.0.0" + +regexpu-core@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/regexpu-core/-/regexpu-core-2.0.0.tgz#49d038837b8dcf8bfa5b9a42139938e6ea2ae240" + dependencies: + regenerate "^1.2.1" + regjsgen "^0.2.0" + regjsparser "^0.1.4" + +regjsgen@^0.2.0: + version "0.2.0" + resolved "https://registry.yarnpkg.com/regjsgen/-/regjsgen-0.2.0.tgz#6c016adeac554f75823fe37ac05b92d5a4edb1f7" + +regjsparser@^0.1.4: + version "0.1.5" + resolved "https://registry.yarnpkg.com/regjsparser/-/regjsparser-0.1.5.tgz#7ee8f84dc6fa792d3fd0ae228d24bd949ead205c" + dependencies: + jsesc "~0.5.0" + +repeat-element@^1.1.2: + version "1.1.2" + resolved "https://registry.yarnpkg.com/repeat-element/-/repeat-element-1.1.2.tgz#ef089a178d1483baae4d93eb98b4f9e4e11d990a" + +repeat-string@^1.5.2: + version "1.6.1" + resolved "https://registry.yarnpkg.com/repeat-string/-/repeat-string-1.6.1.tgz#8dcae470e1c88abc2d600fff4a776286da75e637" + +repeating@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/repeating/-/repeating-2.0.1.tgz#5214c53a926d3552707527fbab415dbc08d06dda" + dependencies: + is-finite "^1.0.0" + +replace-ext@0.0.1: + version "0.0.1" + resolved "https://registry.yarnpkg.com/replace-ext/-/replace-ext-0.0.1.tgz#29bbd92078a739f0bcce2b4ee41e837953522924" + +require-relative@^0.8.7: + version "0.8.7" + resolved "https://registry.yarnpkg.com/require-relative/-/require-relative-0.8.7.tgz#7999539fc9e047a37928fa196f8e1563dabd36de" + +require-uncached@^1.0.2: + version "1.0.3" + resolved "https://registry.yarnpkg.com/require-uncached/-/require-uncached-1.0.3.tgz#4e0d56d6c9662fd31e43011c4b95aa49955421d3" + dependencies: + caller-path "^0.1.0" + resolve-from "^1.0.0" + +resolve-dir@^0.1.0: + version "0.1.1" + resolved "https://registry.yarnpkg.com/resolve-dir/-/resolve-dir-0.1.1.tgz#b219259a5602fac5c5c496ad894a6e8cc430261e" + dependencies: + expand-tilde "^1.2.2" + global-modules "^0.2.3" + +resolve-from@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-1.0.1.tgz#26cbfe935d1aeeeabb29bc3fe5aeb01e93d44226" + +resolve-url@~0.2.1: + version "0.2.1" + resolved "https://registry.yarnpkg.com/resolve-url/-/resolve-url-0.2.1.tgz#2c637fe77c893afd2a663fe21aa9080068e2052a" + +resolve@1.1.7: + version "1.1.7" + resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.1.7.tgz#203114d82ad2c5ed9e8e0411b3932875e889e97b" + +resolve@^1.1.6, resolve@^1.1.7: + version "1.3.1" + resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.3.1.tgz#5d0a1632609b6b00a22284293db1d5d973676314" + dependencies: + path-parse "^1.0.5" + +restore-cursor@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/restore-cursor/-/restore-cursor-1.0.1.tgz#34661f46886327fed2991479152252df92daa541" + dependencies: + exit-hook "^1.0.0" + onetime "^1.0.0" + +right-align@^0.1.1: + version "0.1.3" + resolved "https://registry.yarnpkg.com/right-align/-/right-align-0.1.3.tgz#61339b722fe6a3515689210d24e14c96148613ef" + dependencies: + align-text "^0.1.1" + +rimraf@^2.2.8: + version "2.6.1" + resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.6.1.tgz#c2338ec643df7a1b7fe5c54fa86f57428a55f33d" + dependencies: + glob "^7.0.5" + +rollup-plugin-babel@^2.7.1: + version "2.7.1" + resolved "https://registry.yarnpkg.com/rollup-plugin-babel/-/rollup-plugin-babel-2.7.1.tgz#16528197b0f938a1536f44683c7a93d573182f57" + dependencies: + babel-core "6" + babel-plugin-transform-es2015-classes "^6.9.0" + object-assign "^4.1.0" + rollup-pluginutils "^1.5.0" + +rollup-plugin-node-resolve@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/rollup-plugin-node-resolve/-/rollup-plugin-node-resolve-2.0.0.tgz#07e0ae94ac002a3ea36e8f33ca121d9f836b1309" + dependencies: + browser-resolve "^1.11.0" + builtin-modules "^1.1.0" + resolve "^1.1.6" + +rollup-plugin-uglify@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/rollup-plugin-uglify/-/rollup-plugin-uglify-1.0.1.tgz#11d0b0c8bcd2d07e6908f74fd16b0152390b922a" + dependencies: + uglify-js "^2.6.1" + +rollup-pluginutils@^1.5.0: + version "1.5.2" + resolved "https://registry.yarnpkg.com/rollup-pluginutils/-/rollup-pluginutils-1.5.2.tgz#1e156e778f94b7255bfa1b3d0178be8f5c552408" + dependencies: + estree-walker "^0.2.1" + minimatch "^3.0.2" + +rollup@^0.41.4: + version "0.41.4" + resolved "https://registry.yarnpkg.com/rollup/-/rollup-0.41.4.tgz#a970580176329f9ead86854d7fd4c46de752aef8" + dependencies: + source-map-support "^0.4.0" + +run-async@^0.1.0: + version "0.1.0" + resolved "https://registry.yarnpkg.com/run-async/-/run-async-0.1.0.tgz#c8ad4a5e110661e402a7d21b530e009f25f8e389" + dependencies: + once "^1.3.0" + +rx-lite@^3.1.2: + version "3.1.2" + resolved "https://registry.yarnpkg.com/rx-lite/-/rx-lite-3.1.2.tgz#19ce502ca572665f3b647b10939f97fd1615f102" + +semver@^4.1.0: + version "4.3.6" + resolved "https://registry.yarnpkg.com/semver/-/semver-4.3.6.tgz#300bc6e0e86374f7ba61068b5b1ecd57fc6532da" + +sequencify@~0.0.7: + version "0.0.7" + resolved "https://registry.yarnpkg.com/sequencify/-/sequencify-0.0.7.tgz#90cff19d02e07027fd767f5ead3e7b95d1e7380c" + +shelljs@^0.7.5: + version "0.7.6" + resolved "https://registry.yarnpkg.com/shelljs/-/shelljs-0.7.6.tgz#379cccfb56b91c8601e4793356eb5382924de9ad" + dependencies: + glob "^7.0.0" + interpret "^1.0.0" + rechoir "^0.6.2" + +sigmund@~1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/sigmund/-/sigmund-1.0.1.tgz#3ff21f198cad2175f9f3b781853fd94d0d19b590" + +slash@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/slash/-/slash-1.0.0.tgz#c41f2f6c39fc16d1cd17ad4b5d896114ae470d55" + +slice-ansi@0.0.4: + version "0.0.4" + resolved "https://registry.yarnpkg.com/slice-ansi/-/slice-ansi-0.0.4.tgz#edbf8903f66f7ce2f8eafd6ceed65e264c831b35" + +source-map-resolve@^0.3.0: + version "0.3.1" + resolved "https://registry.yarnpkg.com/source-map-resolve/-/source-map-resolve-0.3.1.tgz#610f6122a445b8dd51535a2a71b783dfc1248761" + dependencies: + atob "~1.1.0" + resolve-url "~0.2.1" + source-map-url "~0.3.0" + urix "~0.1.0" + +source-map-support@^0.4.0, source-map-support@^0.4.2: + version "0.4.11" + resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.4.11.tgz#647f939978b38535909530885303daf23279f322" + dependencies: + source-map "^0.5.3" + +source-map-url@~0.3.0: + version "0.3.0" + resolved "https://registry.yarnpkg.com/source-map-url/-/source-map-url-0.3.0.tgz#7ecaf13b57bcd09da8a40c5d269db33799d4aaf9" + +source-map@0.X, source-map@^0.5.0, source-map@^0.5.1, source-map@^0.5.3, source-map@~0.5.1: + version "0.5.6" + resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.5.6.tgz#75ce38f52bf0733c5a7f0c118d81334a2bb5f412" + +source-map@^0.1.38: + version "0.1.43" + resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.1.43.tgz#c24bc146ca517c1471f5dacbe2571b2b7f9e3346" + dependencies: + amdefine ">=0.0.4" + +sparkles@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/sparkles/-/sparkles-1.0.0.tgz#1acbbfb592436d10bbe8f785b7cc6f82815012c3" + +sprintf-js@~1.0.2: + version "1.0.3" + resolved "https://registry.yarnpkg.com/sprintf-js/-/sprintf-js-1.0.3.tgz#04e6926f662895354f3dd015203633b857297e2c" + +stream-consume@~0.1.0: + version "0.1.0" + resolved "https://registry.yarnpkg.com/stream-consume/-/stream-consume-0.1.0.tgz#a41ead1a6d6081ceb79f65b061901b6d8f3d1d0f" + +string-width@^1.0.1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/string-width/-/string-width-1.0.2.tgz#118bdf5b8cdc51a2a7e70d211e07e2b0b9b107d3" + dependencies: + code-point-at "^1.0.0" + is-fullwidth-code-point "^1.0.0" + strip-ansi "^3.0.0" + +string-width@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/string-width/-/string-width-2.0.0.tgz#635c5436cc72a6e0c387ceca278d4e2eec52687e" + dependencies: + is-fullwidth-code-point "^2.0.0" + strip-ansi "^3.0.0" + +string_decoder@~0.10.x: + version "0.10.31" + resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-0.10.31.tgz#62e203bc41766c6c28c9fc84301dab1c5310fa94" + +strip-ansi@^3.0.0: + version "3.0.1" + resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-3.0.1.tgz#6a385fb8853d952d5ff05d0e8aaf94278dc63dcf" + dependencies: + ansi-regex "^2.0.0" + +strip-bom@3.X, strip-bom@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/strip-bom/-/strip-bom-3.0.0.tgz#2334c18e9c759f7bdd56fdef7e9ae3d588e68ed3" + +strip-bom@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/strip-bom/-/strip-bom-1.0.0.tgz#85b8862f3844b5a6d5ec8467a93598173a36f794" + dependencies: + first-chunk-stream "^1.0.0" + is-utf8 "^0.2.0" + +strip-json-comments@~2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-2.0.1.tgz#3c531942e908c2697c0ec344858c286c7ca0a60a" + +supports-color@1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-1.2.0.tgz#ff1ed1e61169d06b3cf2d588e188b18d8847e17e" + +supports-color@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-2.0.0.tgz#535d045ce6b6363fa40117084629995e9df324c7" + +table@^3.7.8: + version "3.8.3" + resolved "https://registry.yarnpkg.com/table/-/table-3.8.3.tgz#2bbc542f0fda9861a755d3947fefd8b3f513855f" + dependencies: + ajv "^4.7.0" + ajv-keywords "^1.0.0" + chalk "^1.1.1" + lodash "^4.0.0" + slice-ansi "0.0.4" + string-width "^2.0.0" + +tailored@2.3.2: + version "2.3.2" + resolved "https://registry.yarnpkg.com/tailored/-/tailored-2.3.2.tgz#4081db326b339dd31048c142d52cda3f95c6a135" + dependencies: + erlang-types "^1.0.0" + +text-table@~0.2.0: + version "0.2.0" + resolved "https://registry.yarnpkg.com/text-table/-/text-table-0.2.0.tgz#7f5ee823ae805207c00af2df4a84ec3fcfa570b4" + +through2@2.X, through2@^2.0.0: + version "2.0.3" + resolved "https://registry.yarnpkg.com/through2/-/through2-2.0.3.tgz#0004569b37c7c74ba39c43f3ced78d1ad94140be" + dependencies: + readable-stream "^2.1.5" + xtend "~4.0.1" + +through2@^0.6.1: + version "0.6.5" + resolved "https://registry.yarnpkg.com/through2/-/through2-0.6.5.tgz#41ab9c67b29d57209071410e1d7a7a968cd3ad48" + dependencies: + readable-stream ">=1.0.33-1 <1.1.0-0" + xtend ">=4.0.0 <4.1.0-0" + +through@^2.3.6: + version "2.3.8" + resolved "https://registry.yarnpkg.com/through/-/through-2.3.8.tgz#0dd4c9ffaabc357960b1b724115d7e0e86a2e1f5" + +tildify@^1.0.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/tildify/-/tildify-1.2.0.tgz#dcec03f55dca9b7aa3e5b04f21817eb56e63588a" + dependencies: + os-homedir "^1.0.0" + +time-stamp@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/time-stamp/-/time-stamp-1.0.1.tgz#9f4bd23559c9365966f3302dbba2b07c6b99b151" + +to-fast-properties@^1.0.1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/to-fast-properties/-/to-fast-properties-1.0.2.tgz#f3f5c0c3ba7299a7ef99427e44633257ade43320" + +to-iso-string@0.0.2: + version "0.0.2" + resolved "https://registry.yarnpkg.com/to-iso-string/-/to-iso-string-0.0.2.tgz#4dc19e664dfccbe25bd8db508b00c6da158255d1" + +trim-right@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/trim-right/-/trim-right-1.0.1.tgz#cb2e1203067e0c8de1f614094b9fe45704ea6003" + +tryit@^1.0.1: + version "1.0.3" + resolved "https://registry.yarnpkg.com/tryit/-/tryit-1.0.3.tgz#393be730a9446fd1ead6da59a014308f36c289cb" + +type-check@~0.3.2: + version "0.3.2" + resolved "https://registry.yarnpkg.com/type-check/-/type-check-0.3.2.tgz#5884cab512cf1d355e3fb784f30804b2b520db72" + dependencies: + prelude-ls "~1.1.2" + +type-detect@0.1.1: + version "0.1.1" + resolved "https://registry.yarnpkg.com/type-detect/-/type-detect-0.1.1.tgz#0ba5ec2a885640e470ea4e8505971900dac58822" + +type-detect@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/type-detect/-/type-detect-1.0.0.tgz#762217cc06db258ec48908a1298e8b95121e8ea2" + +typedarray@^0.0.6: + version "0.0.6" + resolved "https://registry.yarnpkg.com/typedarray/-/typedarray-0.0.6.tgz#867ac74e3864187b1d3d47d996a78ec5c8830777" + +uglify-js@^2.6.1: + version "2.7.5" + resolved "https://registry.yarnpkg.com/uglify-js/-/uglify-js-2.7.5.tgz#4612c0c7baaee2ba7c487de4904ae122079f2ca8" + dependencies: + async "~0.2.6" + source-map "~0.5.1" + uglify-to-browserify "~1.0.0" + yargs "~3.10.0" + +uglify-to-browserify@~1.0.0: + version "1.0.2" + resolved "https://registry.yarnpkg.com/uglify-to-browserify/-/uglify-to-browserify-1.0.2.tgz#6e0924d6bda6b5afe349e39a6d632850a0f882b7" + +unc-path-regex@^0.1.0: + version "0.1.2" + resolved "https://registry.yarnpkg.com/unc-path-regex/-/unc-path-regex-0.1.2.tgz#e73dd3d7b0d7c5ed86fbac6b0ae7d8c6a69d50fa" + +unique-stream@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/unique-stream/-/unique-stream-1.0.0.tgz#d59a4a75427447d9aa6c91e70263f8d26a4b104b" + +urix@^0.1.0, urix@~0.1.0: + version "0.1.0" + resolved "https://registry.yarnpkg.com/urix/-/urix-0.1.0.tgz#da937f7a62e21fec1fd18d49b35c2935067a6c72" + +user-home@^1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/user-home/-/user-home-1.1.1.tgz#2b5be23a32b63a7c9deb8d0f28d485724a3df190" + +user-home@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/user-home/-/user-home-2.0.0.tgz#9c70bfd8169bc1dcbf48604e0f04b8b49cde9e9f" + dependencies: + os-homedir "^1.0.0" + +util-deprecate@~1.0.1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf" + +v8flags@^2.0.2: + version "2.0.11" + resolved "https://registry.yarnpkg.com/v8flags/-/v8flags-2.0.11.tgz#bca8f30f0d6d60612cc2c00641e6962d42ae6881" + dependencies: + user-home "^1.1.1" + +vinyl-fs@^0.3.0: + version "0.3.14" + resolved "https://registry.yarnpkg.com/vinyl-fs/-/vinyl-fs-0.3.14.tgz#9a6851ce1cac1c1cea5fe86c0931d620c2cfa9e6" + dependencies: + defaults "^1.0.0" + glob-stream "^3.1.5" + glob-watcher "^0.0.6" + graceful-fs "^3.0.0" + mkdirp "^0.5.0" + strip-bom "^1.0.0" + through2 "^0.6.1" + vinyl "^0.4.0" + +vinyl-sourcemaps-apply@^0.2.0: + version "0.2.1" + resolved "https://registry.yarnpkg.com/vinyl-sourcemaps-apply/-/vinyl-sourcemaps-apply-0.2.1.tgz#ab6549d61d172c2b1b87be5c508d239c8ef87705" + dependencies: + source-map "^0.5.1" + +vinyl@1.X: + version "1.2.0" + resolved "https://registry.yarnpkg.com/vinyl/-/vinyl-1.2.0.tgz#5c88036cf565e5df05558bfc911f8656df218884" + dependencies: + clone "^1.0.0" + clone-stats "^0.0.1" + replace-ext "0.0.1" + +vinyl@^0.4.0: + version "0.4.6" + resolved "https://registry.yarnpkg.com/vinyl/-/vinyl-0.4.6.tgz#2f356c87a550a255461f36bbeb2a5ba8bf784847" + dependencies: + clone "^0.2.0" + clone-stats "^0.0.1" + +vinyl@^0.5.0: + version "0.5.3" + resolved "https://registry.yarnpkg.com/vinyl/-/vinyl-0.5.3.tgz#b0455b38fc5e0cf30d4325132e461970c2091cde" + dependencies: + clone "^1.0.0" + clone-stats "^0.0.1" + replace-ext "0.0.1" + +which@^1.2.12: + version "1.2.12" + resolved "https://registry.yarnpkg.com/which/-/which-1.2.12.tgz#de67b5e450269f194909ef23ece4ebe416fa1192" + dependencies: + isexe "^1.1.1" + +window-size@0.1.0: + version "0.1.0" + resolved "https://registry.yarnpkg.com/window-size/-/window-size-0.1.0.tgz#5438cd2ea93b202efa3a19fe8887aee7c94f9c9d" + +wordwrap@0.0.2: + version "0.0.2" + resolved "https://registry.yarnpkg.com/wordwrap/-/wordwrap-0.0.2.tgz#b79669bb42ecb409f83d583cad52ca17eaa1643f" + +wordwrap@~1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/wordwrap/-/wordwrap-1.0.0.tgz#27584810891456a4171c8d0226441ade90cbcaeb" + +wrappy@1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f" + +write@^0.2.1: + version "0.2.1" + resolved "https://registry.yarnpkg.com/write/-/write-0.2.1.tgz#5fc03828e264cea3fe91455476f7a3c566cb0757" + dependencies: + mkdirp "^0.5.1" + +"xtend@>=4.0.0 <4.1.0-0", xtend@^4.0.0, xtend@~4.0.1: + version "4.0.1" + resolved "https://registry.yarnpkg.com/xtend/-/xtend-4.0.1.tgz#a5c6d532be656e23db820efb943a1f04998d63af" + +yargs@~3.10.0: + version "3.10.0" + resolved "https://registry.yarnpkg.com/yargs/-/yargs-3.10.0.tgz#f7ee7bd857dd7c1d2d38c0e74efbd681d1431fd1" + dependencies: + camelcase "^1.0.2" + cliui "^2.1.0" + decamelize "^1.0.0" + window-size "0.1.0" From b313a69f833241d6ed9e3f32700a539edab5add7 Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Sun, 26 Feb 2017 12:16:30 -0600 Subject: [PATCH 437/860] Remove copy_bootstrap_to_destination --- lib/elixir_script.ex | 13 +------------ 1 file changed, 1 insertion(+), 12 deletions(-) diff --git a/lib/elixir_script.ex b/lib/elixir_script.ex index f9b4b2ac..659fa607 100644 --- a/lib/elixir_script.ex +++ b/lib/elixir_script.ex @@ -209,19 +209,8 @@ defmodule ElixirScript do Returns the contents of the bootrstrap js file """ def get_bootstrap_js(module_format) do - path = Path.join([operating_path, "build", to_string(module_format),"Elixir.Bootstrap.js"]) + path = Path.join([operating_path, "build", to_string(module_format), "Elixir.Bootstrap.js"]) File.read!(path) - end - - @doc """ - Copies the javascript that makes up the ElixirScript bootstrap - to the specified location - """ - def copy_bootstrap_to_destination(module_format, destination) do - path = Path.join([operating_path, "build", to_string(module_format),"Elixir.Bootstrap.js"]) - base = Path.basename(path) - File.mkdir_p!(destination) - File.cp!(path, Path.join([destination, base])) end #Gets path to js files whether the mix project is available From 758976db7c7b19a0e508354220ef2c993cea63fa Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Sun, 26 Feb 2017 12:21:10 -0600 Subject: [PATCH 438/860] Update changelog --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index fc5128c5..aa8afc9d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -25,7 +25,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/). - `JS.import` has been removed in favor of defining JavaScript modules used in configuration ### Changed -- All Modules are now bundled together as one js file. The `Elixir.Bootstrap.js` file is also still created +- Now bundles all output, including the boostrap code. The exported object has Elixir modules in JavaScript namespaces that are lazily loaded when called. To start your application import the bundle according to whichever module format was selected and From d28fe63cf41018dd9cbd443f573028eb1f803fdb Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Sun, 26 Feb 2017 12:25:06 -0600 Subject: [PATCH 439/860] Update mix clean function --- lib/mix/tasks/compile.elixir_script.ex | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/lib/mix/tasks/compile.elixir_script.ex b/lib/mix/tasks/compile.elixir_script.ex index b784afb1..e5d33169 100644 --- a/lib/mix/tasks/compile.elixir_script.ex +++ b/lib/mix/tasks/compile.elixir_script.ex @@ -70,13 +70,11 @@ defmodule Mix.Tasks.Compile.ElixirScript do elixirscript_config = get_elixirscript_config() output_path = Keyword.get(elixirscript_config, :output) - output_path - |> File.ls! - |> Enum.each(fn(x) -> - if String.contains?(Path.basename(x), "Elixir.App.js") do - File.rm!(Path.join(output_path, x)) - end - end) + path = Path.join([output_path, "Elixir.App.js"]) + + if File.exists?(path) do + File.rm!(path) + end :ok end From 45a3980288e8ab85d9f8920e2e5165effdffbe31 Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Sun, 26 Feb 2017 13:02:16 -0600 Subject: [PATCH 440/860] Remove elixirscript.exs config. Add js-module flag --- CHANGELOG.md | 8 +++-- lib/elixir_script/cli.ex | 76 +++++++++++++++++----------------------- 2 files changed, 37 insertions(+), 47 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index aa8afc9d..bfa77d89 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,8 +9,6 @@ and this project adheres to [Semantic Versioning](http://semver.org/). ### Added - Multiple `when` clauses in guards - Kernel.defdelegate/2 -- CLI can now take a configuration file. By default it will look for `elixirscript.exs` in the current directory. - A configuration file can be explicitly given using the `-c` flag - `js_modules` configuration option has been added. This is a keyword list of JavaScript modules that will be used. ``` js_modules: [ @@ -18,7 +16,11 @@ and this project adheres to [Semantic Versioning](http://semver.org/). {ReactDOM, "react-dom"} ] ``` - This is accepted in either the elixirscript.exs file described above or in the `elixir_script` mix configuration + +- `js-module` flag has been added to the CLI in order to pass js modules. +``` +elixirscript "app/elixirscript" -o dist --js-module React:react --js-module ReactDOM:react-dom +``` ### Removed - `@on_js_load` has been removed in favor of having a `start/2` function defined. More info below diff --git a/lib/elixir_script/cli.ex b/lib/elixir_script/cli.ex index 9b359052..44e03ed1 100644 --- a/lib/elixir_script/cli.ex +++ b/lib/elixir_script/cli.ex @@ -5,13 +5,12 @@ defmodule ElixirScript.CLI do @switches [ output: :string, elixir: :boolean, - help: :boolean, core_path: :string, - full_build: :boolean, version: :boolean, - watch: :boolean, format: :string, config: :boolean + help: :boolean, full_build: :boolean, version: :boolean, + watch: :boolean, format: :string, js_module: [:string, :keep] ] @aliases [ - o: :output, ex: :elixir, h: :help, v: :version, f: :format, c: :config + o: :output, ex: :elixir, h: :help, v: :version, f: :format ] def main(argv) do @@ -45,31 +44,14 @@ defmodule ElixirScript.CLI do the elixir code string if passed the -ex flag options: - -c --config a path to an elixirscript configuration file + --js-module [:] A js module used in your code. ex: React:react + Multiple can be defined -f --format [format] module format of output. options: es (default), common, umd -o --output [path] places output at the given path -ex --elixir read input as elixir code string --full-build informs the compiler to do a full build instead of an incremental one - --core-path import path to the elixirscript standard lib - only used with the [output] option. When used, Elixir.js is not exported -v --version the current version number -h --help this message - - Will check for an elixirscript.exs file in the current directory. - A specific file can be given with the -c flag. - - A config file contain only a keyword list with have the following format: - [ - input: (string or list) The input path(s), - output: (string) the output path, - format: (atom) the moduel format of the output, - js_modules: (keyword) a list of the js modules that will be used - ] - - All fields are optional and will fallback to flags given - The config option is not compatible with the -ex flag - - """ end @@ -92,28 +74,23 @@ defmodule ElixirScript.CLI do def do_process(input, options) do {watch, options} = Keyword.pop(options, :watch, false) + js_modules = Keyword.get_values(options, :js_module) + |> build_js_modules + compile_opts = %{ include_path: true, core_path: Keyword.get(options, :core_path, "Elixir.Bootstrap"), full_build: Keyword.get(options, :full_build, false), output: Keyword.get(options, :output, :stdout), - format: String.to_atom(Keyword.get(options, :format, "es")) + format: String.to_atom(Keyword.get(options, :format, "es")), + js_modules: js_modules } case options[:elixir] do true -> ElixirScript.compile(input, compile_opts) _ -> - config = options - |> Keyword.get(:config, "elixirscript.exs") - |> handle_config - |> Map.new - - input = Map.get(config, :input, handle_input(input)) - {_, config} = Map.pop(config, :input) - - compile_opts = Map.merge(compile_opts, config) - + input = handle_input(input) ElixirScript.compile_path(input, compile_opts) if watch do @@ -134,19 +111,30 @@ defmodule ElixirScript.CLI do end defp handle_input(input) do - input = input - |> Enum.map(fn(x) -> String.split(x, [" ", ","], trim: true) end) - |> List.flatten + input = input + |> Enum.map(fn(x) -> String.split(x, [" ", ","], trim: true) end) + |> List.flatten end + defp build_js_modules(values) do + values + |> Enum.map(fn x -> + [identifier, path] = String.split(x,":", trim: true) + { format_identifier(identifier), format_path(path) } + end) + end - defp handle_config(path) do - if File.exists?(path) do - {config, _} = Code.eval_file(path) - config - else - [] - end + defp format_identifier(id) do + id + |> String.split(".") + |> Module.concat end + + defp format_path(path) do + path + |> String.replace("\"", "") + |> String.replace("`", "") + |> String.replace("'", "") + end end From cf9892cb146ec5400c9b1fc219e66ba36236fd77 Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Sun, 26 Feb 2017 15:56:00 -0600 Subject: [PATCH 441/860] Update umd translation --- lib/elixir_script/module_systems/umd.ex | 2 +- test/translator/umd_test.exs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/elixir_script/module_systems/umd.ex b/lib/elixir_script/module_systems/umd.ex index 82251037..5a94cb5c 100644 --- a/lib/elixir_script/module_systems/umd.ex +++ b/lib/elixir_script/module_systems/umd.ex @@ -85,7 +85,7 @@ defmodule ElixirScript.ModuleSystems.UMD do :=, JS.member_expression( JS.identifier("root"), - JS.identifier("returnExports") + JS.identifier("Elixir") ), JS.call_expression( JS.identifier("factory"), diff --git a/test/translator/umd_test.exs b/test/translator/umd_test.exs index 1a390e36..0acd353a 100644 --- a/test/translator/umd_test.exs +++ b/test/translator/umd_test.exs @@ -20,7 +20,7 @@ defmodule ElixirScript.Translator.UMD.Test do } else if (typeof exports === 'object') { module.exports = factory() } else { - root.returnExports = factory() + root.Elixir = factory() } """ From 3eb7e50758afb71775be4b6f2cdbc9d0649e8ab2 Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Mon, 27 Feb 2017 06:30:08 -0600 Subject: [PATCH 442/860] Update version for release --- CHANGELOG.md | 2 +- mix.exs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index bfa77d89..b575e273 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,7 +4,7 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](http://keepachangelog.com/) and this project adheres to [Semantic Versioning](http://semver.org/). -## [0.26.0] - Unreleased +## [0.26.0] - 2017-02-27 ### Added - Multiple `when` clauses in guards diff --git a/mix.exs b/mix.exs index 77c60865..7369fd35 100644 --- a/mix.exs +++ b/mix.exs @@ -4,7 +4,7 @@ defmodule ElixirScript.Mixfile do def project do [ app: :elixir_script, - version: "0.26.0-dev", + version: "0.26.0", elixir: "~> 1.0", elixirc_paths: elixirc_paths(), escript: escript_config(), From 7d1e332d8cc048f7923cf4cb9dc87919fd700f33 Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Mon, 27 Feb 2017 20:14:03 -0600 Subject: [PATCH 443/860] Update documentation --- CHANGELOG.md | 2 +- GettingStarted.md | 46 ++++++++++++++++++++++------------------------ README.md | 8 ++++++-- 3 files changed, 29 insertions(+), 27 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index b575e273..8e2c8c72 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,7 +9,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/). ### Added - Multiple `when` clauses in guards - Kernel.defdelegate/2 -- `js_modules` configuration option has been added. This is a keyword list of JavaScript modules that will be used. +- `js_modules` configuration option has been added. This is a list of JavaScript modules that will be used. ``` js_modules: [ {React, "react"}, diff --git a/GettingStarted.md b/GettingStarted.md index 3691d4ea..f3abfaca 100644 --- a/GettingStarted.md +++ b/GettingStarted.md @@ -29,27 +29,24 @@ This is the help output of elixirscript path to elixir files or the elixir code string if passed the -ex flag options: + --js-module [:] A js module used in your code. ex: React:react + Multiple can be defined -f --format [format] module format of output. options: es (default), common, umd -o --output [path] places output at the given path -ex --elixir read input as elixir code string --full-build informs the compiler to do a full build instead of an incremental one - --core-path import path to the elixirscript standard lib - only used with the [output] option. When used, Elixir.js is not exported -v --version the current version number -h --help this message the `` is the elixir code string or file path you want to convert from elixir to javascript. Below is an example of using a code string and turning it into JavaScript $ elixirscript ":atom" -ex - Symbol.for('atom') - -It changed the elixir code, `:atom` into the JavaScript code `Symbol.for('atom')`. The `-ex` parameter lets the script know that the input is an Elixir code string instead of a file. elixirscript also takes a path to your `.ex` files as well: $ elixirscript "src" -o "dist" -If you look in the dist folder, you should see 2 folders. `app` contains your code and `elixir` contains the elixirscript standard library files. +If you look in the dist folder you'll see a file called `Elixir.App.js` ### Mix dependency @@ -58,7 +55,7 @@ Adding Elixirscript to your mix project gives you the ability to add it to your Add dependency to your deps in mix.exs: ```elixir - {:elixir_script, "~> 0.25"} + {:elixir_script, "~> 0.26"} ``` Elixirscript uses default input, output and module formats if options are not given. If you wish to change any or all options, add an `elixir_script` key to your project configuration. @@ -69,7 +66,15 @@ Add dependency to your deps in mix.exs: version: "0.1.0", elixir: "~> 1.0", deps: deps, - elixir_script: [ input: "lib/elixirscript", output: "priv/elixirscript", format: :es], + elixir_script: [ + input: "lib/elixirscript", + output: "priv/elixirscript", + format: :es, + js_modules: [ + {React, "react"}, + {ReactDOM, "react-dom"} + ] + ], compilers: [:elixir_script] ++ Mix.compilers ] end @@ -88,6 +93,8 @@ Available options are: * `:umd` - UMD +* `js_modules`: A list of JavaScript imports to add. Each item must be 2-tuple or a 3-tuple. The third element is an optional keyword list of options. + ### Macros Elixirscript supports public macros. Private macros are currently unsupported. @@ -117,27 +124,18 @@ You can call globally scoped modules you would an Elixir module Only works if module begins with a captial letter -#### Importing Modules - -To import modules, first you must `require` the `JS` module. Then import the module using `JS.import` - - defmodule MyModule do - require JS - JS.import React, "react" - - def func() do - React.render(my_component) - end - end - #### The JS module The JS module has many other functions and macros. For more information, check out the docs. #### Frontend Project Boilerplate -There is an [elixirscript frontend boilerplate project](https://github.com/bryanjos/elixirscript-project-boilerplate). This setup uses gulp and webpack to build and bundle assets. +There is an [elixirscript frontend boilerplate project](https://github.com/elixirscript/elixirscript-project-boilerplate). This setup uses gulp and webpack to build and bundle assets. + +#### elixirscript-brunch + +There is an Brunch plugin, [elixirscript-brunch](https://www.npmjs.com/package/elixirscript-brunch). -#### ElixirScript-Brunch +#### -There is an Brunch plugin, [ElixirScript-Brunch](https://www.npmjs.com/package/elixirscript-brunch). There are instructions there on how to use it with Phoenix. \ No newline at end of file +There is also a webpack loader, [elixirscript-loader](https://www.npmjs.com/package/elixirscript-loader). \ No newline at end of file diff --git a/README.md b/README.md index dce8097d..89ca4c9f 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ ## ElixirScript [![Documentation](https://img.shields.io/badge/docs-hexpm-blue.svg)](http://hexdocs.pm/elixir_script/) [![Build](https://travis-ci.org/elixirscript/elixirscript.svg?branch=master)](https://travis-ci.org/elixirscript/elixirscript) [![Deps Status](https://beta.hexfaktor.org/badge/all/github/bryanjos/elixirscript.svg)](https://beta.hexfaktor.org/github/bryanjos/elixirscript) [![Join the chat at https://gitter.im/elixirscript/elixirscript](https://badges.gitter.im/elixirscript/elixirscript.svg)](https://gitter.im/elixirscript/elixirscript?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) -The goal is to convert a subset (or full set) of Elixir code to JavaScript, providing the ability to write JavaScript in Elixir. This is done by taking the Elixir AST and converting it into JavaScript AST and then to JavaScript code. This is done using the [Elixir-ESTree](https://github.com/bryanjos/elixir-estree) library. +The goal is to convert a subset (or full set) of Elixir code to JavaScript, providing the ability to write JavaScript in Elixir. This is done by taking the Elixir AST and converting it into JavaScript AST and then to JavaScript code. This is done using the [Elixir-ESTree](https://github.com/elixirscript/elixir-estree) library. Requirements =========== @@ -65,7 +65,7 @@ Please check the [CONTRIBUTING.md](CONTRIBUTING.md) ### Example projects * [hello](https://github.com/bryanjos/hello) Shows using Phoenix + Elixirscript with file watching -* [Elixirscript frontend boilerplate](https://github.com/bryanjos/elixirscript-project-boilerplate) A boilerplate project for elixirscript frontends +* [Elixirscript frontend boilerplate](https://github.com/elixirscript/elixirscript-project-boilerplate) A boilerplate project for elixirscript frontends * [Elixirscript React example](https://github.com/bryanjos/elixirscript_react) An example of using with React * [Elixirscript AWS Lambda example](https://github.com/bryanjos/elixirscript_lambda) @@ -73,5 +73,9 @@ Please check the [CONTRIBUTING.md](CONTRIBUTING.md) There is a plugin for using ElixirScript in your Brunch project [here](https://www.npmjs.com/package/elixirscript-brunch) +#### Using with Webpack +There is a loader for using ElixirScript in your Webpack project +[here](https://www.npmjs.com/package/elixirscript-loader) + #### 1.0 Roadmap There is a [1.0.0 Milestone](https://github.com/bryanjos/elixirscript/milestones/1.0.0) defined which includes issues that are needed to be cleared before 1.0 can be reached. From 4d491efe0371af45bbe2168b19fb54ca71cc3297 Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Mon, 27 Feb 2017 20:17:54 -0600 Subject: [PATCH 444/860] Update GettingStarted --- GettingStarted.md | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/GettingStarted.md b/GettingStarted.md index f3abfaca..ac7b68c0 100644 --- a/GettingStarted.md +++ b/GettingStarted.md @@ -48,6 +48,26 @@ elixirscript also takes a path to your `.ex` files as well: If you look in the dist folder you'll see a file called `Elixir.App.js` +To start your application import the bundle according to whichever module format was selected and +then call start giving it the module and the initial args. + +Ex. If you have a module like so +```elixir +defmodule Example do + start(type, args) do + :console.log("Hello, world") + end +end +``` + +You would start it like so + +```javascript +//ES module example +import Elixir from './Elixir.App' +Elixir.start(Elixir.Example, []) +``` + ### Mix dependency Adding Elixirscript to your mix project gives you the ability to add it to your list of mix compilers. This means when you `mix compile`, Elixirscript will compile your code as well. From e972eab28d234173a648e82b889aac1e6ce8d8ae Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Mon, 27 Feb 2017 20:24:08 -0600 Subject: [PATCH 445/860] Update for translation --- CHANGELOG.md | 6 ++++++ .../translator/kernel/special_forms/for.ex | 11 ++++++++++- mix.exs | 2 +- package.json | 4 ++-- test/translator/for_test.exs | 14 +++++++------- 5 files changed, 26 insertions(+), 11 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 8e2c8c72..574e2052 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,12 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](http://keepachangelog.com/) and this project adheres to [Semantic Versioning](http://semver.org/). +## [0.26.1] - 2017-02-27 + +### Fixed +- Fixed `for` translation +- Updated documentation + ## [0.26.0] - 2017-02-27 ### Added diff --git a/lib/elixir_script/translator/kernel/special_forms/for.ex b/lib/elixir_script/translator/kernel/special_forms/for.ex index 45c076da..3c6293e4 100644 --- a/lib/elixir_script/translator/kernel/special_forms/for.ex +++ b/lib/elixir_script/translator/kernel/special_forms/for.ex @@ -6,6 +6,7 @@ defmodule ElixirScript.Translator.For do alias ElixirScript.Translator.Primitive alias ElixirScript.Translator.Function alias ElixirScript.Translator.Utils + alias ElixirScript.Translator.Identifier def make_for(generators, env) do ElixirScript.Translator.State.add_module_reference(env.state, env.module, ElixirScript.Collectable) @@ -17,6 +18,14 @@ defmodule ElixirScript.Translator.For do filter = args.filter || JS.function_expression([], [], JS.block_statement([JS.return_statement(JS.identifier("true"))])) fun = args.fun + members = ["Elixir"] ++ Module.split(ElixirScript.Collectable) ++ ["__load"] + + collectable_module = JS.call_expression( + Identifier.make_namespace_members(members), + [JS.identifier("Elixir")] + ) + + expression = JS.call_expression( JS.member_expression( JS.member_expression( @@ -36,7 +45,7 @@ defmodule ElixirScript.Translator.For do Primitive.special_forms(), JS.identifier("_for") ), - [expression, generators, JS.identifier(Utils.name_to_js_name(ElixirScript.Collectable)), into] + [expression, generators, collectable_module, into] ) {js_ast, env} diff --git a/mix.exs b/mix.exs index 7369fd35..1b14c0dd 100644 --- a/mix.exs +++ b/mix.exs @@ -4,7 +4,7 @@ defmodule ElixirScript.Mixfile do def project do [ app: :elixir_script, - version: "0.26.0", + version: "0.26.1", elixir: "~> 1.0", elixirc_paths: elixirc_paths(), escript: escript_config(), diff --git a/package.json b/package.json index efbbd8d5..5387ddfb 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "elixirscript", - "version": "0.25.0", + "version": "0.26.1", "description": "Convert Elixir to JavaScript", "main": "elixir.js", "bin": { @@ -44,4 +44,4 @@ "rollup-plugin-node-resolve": "^2.0.0", "rollup-plugin-uglify": "^1.0.1" } -} +} \ No newline at end of file diff --git a/test/translator/for_test.exs b/test/translator/for_test.exs index faec216e..6826d704 100644 --- a/test/translator/for_test.exs +++ b/test/translator/for_test.exs @@ -24,7 +24,7 @@ defmodule ElixirScript.Translator.For.Test do Object.freeze([1, 2, 3, 4]) ) ], - Elixir$ElixirScript$Collectable, + Elixir.ElixirScript.Collectable.__load(Elixir), Object.freeze([]) ) """ @@ -54,7 +54,7 @@ defmodule ElixirScript.Translator.For.Test do Object.freeze([1, 2, 3, 4]) ) ], - Elixir$ElixirScript$Collectable, + Elixir.ElixirScript.Collectable.__load(Elixir), Object.freeze([]) ) """ @@ -88,7 +88,7 @@ defmodule ElixirScript.Translator.For.Test do Object.freeze([2, 3]) ) ], - Elixir$ElixirScript$Collectable, + Elixir.ElixirScript.Collectable.__load(Elixir), Object.freeze([]) ) """ @@ -126,7 +126,7 @@ defmodule ElixirScript.Translator.For.Test do Object.freeze([2, 3]) ) ], - Elixir$ElixirScript$Collectable, + Elixir.ElixirScript.Collectable.__load(Elixir), Object.freeze([]) ) ); @@ -157,7 +157,7 @@ defmodule ElixirScript.Translator.For.Test do Object.freeze([1, 2, 3, 4, 5, 6]) ) ], - Elixir$ElixirScript$Collectable, + Elixir.ElixirScript.Collectable.__load(Elixir), Object.freeze([]) ) """ @@ -186,7 +186,7 @@ defmodule ElixirScript.Translator.For.Test do values: [Symbol.for('user'), Bootstrap.Core.Patterns.variable()] }), Object.freeze([new Bootstrap.Core.Tuple(Symbol.for('user'), 'john'), new Bootstrap.Core.Tuple(Symbol.for('admin'), 'john'), new Bootstrap.Core.Tuple(Symbol.for('user'), 'meg')])) ], - Elixir$ElixirScript$Collectable, + Elixir.ElixirScript.Collectable.__load(Elixir), Object.freeze([])) """ @@ -218,7 +218,7 @@ defmodule ElixirScript.Translator.For.Test do 'value': Bootstrap.Core.Patterns.variable() }, 8), Bootstrap.Core.BitString.size({ 'value': Bootstrap.Core.Patterns.variable() - }, 8)), pixels)], Elixir$ElixirScript$Collectable, Object.freeze([])) + }, 8)), pixels)], Elixir.ElixirScript.Collectable.__load(Elixir), Object.freeze([])) """ assert_translation(ex_ast, js_code) From 1d0d512a5d5b6669c512728ccbefbcafe30aa5d8 Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Tue, 28 Feb 2017 10:18:14 -0600 Subject: [PATCH 446/860] Update FAQ.md --- FAQ.md | 1 - 1 file changed, 1 deletion(-) diff --git a/FAQ.md b/FAQ.md index 107cd895..dbc25aae 100644 --- a/FAQ.md +++ b/FAQ.md @@ -59,7 +59,6 @@ The compiler to this point has been focused on translating Kernel.SpecialForms a * List * Atom * Range - * Logger * Map * MapSet From 8c6d35bd31f83526b770059b7388967bfba07194 Mon Sep 17 00:00:00 2001 From: Stephan van Diepen Date: Sat, 4 Mar 2017 18:48:47 +0100 Subject: [PATCH 447/860] Rename -ex alias to -e for --elixir --- GettingStarted.md | 6 +++--- lib/elixir_script/cli.ex | 6 +++--- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/GettingStarted.md b/GettingStarted.md index ac7b68c0..8d771930 100644 --- a/GettingStarted.md +++ b/GettingStarted.md @@ -27,20 +27,20 @@ This is the help output of elixirscript usage: elixirscript [options] path to elixir files or - the elixir code string if passed the -ex flag + the elixir code string if passed the -e flag options: --js-module [:] A js module used in your code. ex: React:react Multiple can be defined -f --format [format] module format of output. options: es (default), common, umd -o --output [path] places output at the given path - -ex --elixir read input as elixir code string + -e --elixir read input as elixir code string --full-build informs the compiler to do a full build instead of an incremental one -v --version the current version number -h --help this message the `` is the elixir code string or file path you want to convert from elixir to javascript. Below is an example of using a code string and turning it into JavaScript - $ elixirscript ":atom" -ex + $ elixirscript ":atom" -e elixirscript also takes a path to your `.ex` files as well: diff --git a/lib/elixir_script/cli.ex b/lib/elixir_script/cli.ex index 44e03ed1..5cb750a6 100644 --- a/lib/elixir_script/cli.ex +++ b/lib/elixir_script/cli.ex @@ -10,7 +10,7 @@ defmodule ElixirScript.CLI do ] @aliases [ - o: :output, ex: :elixir, h: :help, v: :version, f: :format + o: :output, e: :elixir, h: :help, v: :version, f: :format ] def main(argv) do @@ -41,14 +41,14 @@ defmodule ElixirScript.CLI do """ usage: elixirscript [options] path to elixir files or - the elixir code string if passed the -ex flag + the elixir code string if passed the -e flag options: --js-module [:] A js module used in your code. ex: React:react Multiple can be defined -f --format [format] module format of output. options: es (default), common, umd -o --output [path] places output at the given path - -ex --elixir read input as elixir code string + -e --elixir read input as elixir code string --full-build informs the compiler to do a full build instead of an incremental one -v --version the current version number -h --help this message From 74e20cb9bb65108d30c16d12788773051a8d0dcf Mon Sep 17 00:00:00 2001 From: Stephan van Diepen Date: Sat, 4 Mar 2017 18:51:18 +0100 Subject: [PATCH 448/860] Add spec for CLI --- test/cli_test.exs | 9 +++++++++ 1 file changed, 9 insertions(+) create mode 100644 test/cli_test.exs diff --git a/test/cli_test.exs b/test/cli_test.exs new file mode 100644 index 00000000..10711ba9 --- /dev/null +++ b/test/cli_test.exs @@ -0,0 +1,9 @@ +defmodule ElixirScript.CLI.Test do + use ExUnit.Case + import ElixirScript.TestHelper + + test "parse_args -e expands to elixir" do + {_, args} = ElixirScript.CLI.parse_args(["1 + 1", "-e"]) + assert args == [elixir: true] + end +end From 340a0e5c5e3a98032e216f4c20a25985ff72bf7e Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Sat, 4 Mar 2017 14:54:12 -0600 Subject: [PATCH 449/860] Allow naming of js file --- lib/elixir_script/passes/handle_output.ex | 18 ++++++++++++++++-- test/cli_test.exs | 1 - test/passes/handle_output_test.exs | 21 +++++++++++++++++++++ 3 files changed, 37 insertions(+), 3 deletions(-) create mode 100644 test/passes/handle_output_test.exs diff --git a/lib/elixir_script/passes/handle_output.ex b/lib/elixir_script/passes/handle_output.ex index 56512ac8..b9e10900 100644 --- a/lib/elixir_script/passes/handle_output.ex +++ b/lib/elixir_script/passes/handle_output.ex @@ -26,7 +26,9 @@ defmodule ElixirScript.Passes.HandleOutput do end defp out(compiler_output, %{output: output_path, core_path: _} = compiler_opts) do - file_name = Path.join([output_path, @generated_name]) + js_name = get_js_name(output_path) + + file_name = Path.join([output_path, js_name]) if !File.exists?(Path.dirname(file_name)) do File.mkdir_p!(Path.dirname(file_name)) @@ -39,10 +41,22 @@ defmodule ElixirScript.Passes.HandleOutput do "'use strict';\n" <> ElixirScript.get_bootstrap_js("iife") <> "\n" <> code end + def get_js_name(nil), do: @generated_name + def get_js_name(:stdout), do: @generated_name + + def get_js_name(output_path) do + case Path.extname(output_path) do + ".js" -> + Path.basename(output_path) + _ -> + @generated_name + end + end + defp process_include_path(compiler_output, compiler_opts) do case compiler_opts.include_path do true -> - {compiler_output.generated, @generated_name} + {compiler_output.generated, get_js_name(compiler_opts.output)} false -> compiler_output.generated end diff --git a/test/cli_test.exs b/test/cli_test.exs index 10711ba9..6fab0232 100644 --- a/test/cli_test.exs +++ b/test/cli_test.exs @@ -1,6 +1,5 @@ defmodule ElixirScript.CLI.Test do use ExUnit.Case - import ElixirScript.TestHelper test "parse_args -e expands to elixir" do {_, args} = ElixirScript.CLI.parse_args(["1 + 1", "-e"]) diff --git a/test/passes/handle_output_test.exs b/test/passes/handle_output_test.exs new file mode 100644 index 00000000..53c8c11f --- /dev/null +++ b/test/passes/handle_output_test.exs @@ -0,0 +1,21 @@ +defmodule ElixirScript.Passes.HandleOutput.Test do + use ExUnit.Case + alias ElixirScript.Passes.HandleOutput + + test "get_js_name output: nil" do + assert HandleOutput.get_js_name(nil) == "Elixir.App.js" + end + + test "get_js_name output: stdout" do + assert HandleOutput.get_js_name(:stdout) == "Elixir.App.js" + end + + test "get_js_name output is directory" do + assert HandleOutput.get_js_name("/path/to/file/") == "Elixir.App.js" + assert HandleOutput.get_js_name("/path/to/file") == "Elixir.App.js" + end + + test "get_js_name output ends in js" do + assert HandleOutput.get_js_name("/path/to/file/myfile.js") == "myfile.js" + end +end \ No newline at end of file From e215e208f64b819de8870292ff1b2d6bf98ddb4d Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Sat, 4 Mar 2017 14:59:11 -0600 Subject: [PATCH 450/860] Fix pathing bug when filename given --- lib/elixir_script/passes/handle_output.ex | 16 +++++++--------- test/passes/handle_output_test.exs | 18 +++++++++--------- 2 files changed, 16 insertions(+), 18 deletions(-) diff --git a/lib/elixir_script/passes/handle_output.ex b/lib/elixir_script/passes/handle_output.ex index b9e10900..30ae42c0 100644 --- a/lib/elixir_script/passes/handle_output.ex +++ b/lib/elixir_script/passes/handle_output.ex @@ -26,9 +26,7 @@ defmodule ElixirScript.Passes.HandleOutput do end defp out(compiler_output, %{output: output_path, core_path: _} = compiler_opts) do - js_name = get_js_name(output_path) - - file_name = Path.join([output_path, js_name]) + file_name = get_js_path(output_path) if !File.exists?(Path.dirname(file_name)) do File.mkdir_p!(Path.dirname(file_name)) @@ -41,22 +39,22 @@ defmodule ElixirScript.Passes.HandleOutput do "'use strict';\n" <> ElixirScript.get_bootstrap_js("iife") <> "\n" <> code end - def get_js_name(nil), do: @generated_name - def get_js_name(:stdout), do: @generated_name + def get_js_path(nil), do: @generated_name + def get_js_path(:stdout), do: @generated_name - def get_js_name(output_path) do + def get_js_path(output_path) do case Path.extname(output_path) do ".js" -> - Path.basename(output_path) + output_path _ -> - @generated_name + Path.join([output_path, @generated_name]) end end defp process_include_path(compiler_output, compiler_opts) do case compiler_opts.include_path do true -> - {compiler_output.generated, get_js_name(compiler_opts.output)} + {compiler_output.generated, get_js_path(compiler_opts.output)} false -> compiler_output.generated end diff --git a/test/passes/handle_output_test.exs b/test/passes/handle_output_test.exs index 53c8c11f..8691a6be 100644 --- a/test/passes/handle_output_test.exs +++ b/test/passes/handle_output_test.exs @@ -2,20 +2,20 @@ defmodule ElixirScript.Passes.HandleOutput.Test do use ExUnit.Case alias ElixirScript.Passes.HandleOutput - test "get_js_name output: nil" do - assert HandleOutput.get_js_name(nil) == "Elixir.App.js" + test "get_js_path output: nil" do + assert HandleOutput.get_js_path(nil) == "Elixir.App.js" end - test "get_js_name output: stdout" do - assert HandleOutput.get_js_name(:stdout) == "Elixir.App.js" + test "get_js_path output: stdout" do + assert HandleOutput.get_js_path(:stdout) == "Elixir.App.js" end - test "get_js_name output is directory" do - assert HandleOutput.get_js_name("/path/to/file/") == "Elixir.App.js" - assert HandleOutput.get_js_name("/path/to/file") == "Elixir.App.js" + test "get_js_path output is directory" do + assert HandleOutput.get_js_path("/path/to/file/") == "/path/to/file/Elixir.App.js" + assert HandleOutput.get_js_path("/path/to/file") == "/path/to/file/Elixir.App.js" end - test "get_js_name output ends in js" do - assert HandleOutput.get_js_name("/path/to/file/myfile.js") == "myfile.js" + test "get_js_path output ends in js" do + assert HandleOutput.get_js_path("/path/to/file/myfile.js") == "/path/to/file/myfile.js" end end \ No newline at end of file From afb69a4299f5f42da4f76cee27a5b140237b9cb9 Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Sat, 4 Mar 2017 15:10:44 -0600 Subject: [PATCH 451/860] Update changelog. Update docs on CLI and mix compile task --- CHANGELOG.md | 6 ++++++ GettingStarted.md | 12 ++++++++---- lib/elixir_script/cli.ex | 3 ++- lib/mix/tasks/compile.elixir_script.ex | 7 +++++-- mix.exs | 2 +- 5 files changed, 22 insertions(+), 8 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 574e2052..c7ba7e10 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,12 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](http://keepachangelog.com/) and this project adheres to [Semantic Versioning](http://semver.org/). +## [0.27.0-dev] + +### Changed +- `-ex` alias is now `-e` +- A filename can be specified for output + ## [0.26.1] - 2017-02-27 ### Fixed diff --git a/GettingStarted.md b/GettingStarted.md index 8d771930..edb35f79 100644 --- a/GettingStarted.md +++ b/GettingStarted.md @@ -31,8 +31,9 @@ This is the help output of elixirscript options: --js-module [:] A js module used in your code. ex: React:react Multiple can be defined - -f --format [format] module format of output. options: es (default), common, umd - -o --output [path] places output at the given path + -f --format [format] module format of output. options: es (default), common, umd + -o --output [path] places output at the given path. + Can be a directory or filename. -e --elixir read input as elixir code string --full-build informs the compiler to do a full build instead of an incremental one -v --version the current version number @@ -88,7 +89,7 @@ Add dependency to your deps in mix.exs: deps: deps, elixir_script: [ input: "lib/elixirscript", - output: "priv/elixirscript", + output: "priv/elixirscript/Elixir.App.js", format: :es, js_modules: [ {React, "react"}, @@ -103,7 +104,10 @@ Available options are: * `input`: The folder to look for Elixirscript files in. (defaults to `lib/elixirscript`) -* `output`: The folder to place generated JavaScript code in. (defaults to `priv/elixirscript`) +* `output`: The path of the generated JavaScript file. (defaults to `priv/elixirscript`) + + If path ends in `.js` then that will be the name of the file. If a directory is given, + file will be named `Elixir.App.js` * `format`: The module format of generated JavaScript code. (defaults to `:es`). Choices are:     diff --git a/lib/elixir_script/cli.ex b/lib/elixir_script/cli.ex index 5cb750a6..e4bbb67e 100644 --- a/lib/elixir_script/cli.ex +++ b/lib/elixir_script/cli.ex @@ -47,7 +47,8 @@ defmodule ElixirScript.CLI do --js-module [:] A js module used in your code. ex: React:react Multiple can be defined -f --format [format] module format of output. options: es (default), common, umd - -o --output [path] places output at the given path + -o --output [path] places output at the given path. + Can be a directory or filename. -e --elixir read input as elixir code string --full-build informs the compiler to do a full build instead of an incremental one -v --version the current version number diff --git a/lib/mix/tasks/compile.elixir_script.ex b/lib/mix/tasks/compile.elixir_script.ex index e5d33169..df25aaa7 100644 --- a/lib/mix/tasks/compile.elixir_script.ex +++ b/lib/mix/tasks/compile.elixir_script.ex @@ -19,7 +19,10 @@ defmodule Mix.Tasks.Compile.ElixirScript do Available options are: * `input`: The folder to look for Elixirscript files in. (defaults to `lib/elixirscript`) - * `output`: The folder to place generated JavaScript code in. (defaults to `priv/elixirscript`) + * `output`: The path of the generated JavaScript file. (defaults to `priv/elixirscript`) + + If path ends in `.js` then that will be the name of the file. If a directory is given, + file will be named `Elixir.App.js` * `format`: The module format of generated JavaScript code. (defaults to `:es`). Choices are: * `:es` - ES Modules @@ -70,7 +73,7 @@ defmodule Mix.Tasks.Compile.ElixirScript do elixirscript_config = get_elixirscript_config() output_path = Keyword.get(elixirscript_config, :output) - path = Path.join([output_path, "Elixir.App.js"]) + path = ElixirScript.Passes.HandleOutput.get_js_path(output_path) if File.exists?(path) do File.rm!(path) diff --git a/mix.exs b/mix.exs index 1b14c0dd..c95354bf 100644 --- a/mix.exs +++ b/mix.exs @@ -4,7 +4,7 @@ defmodule ElixirScript.Mixfile do def project do [ app: :elixir_script, - version: "0.26.1", + version: "0.27.0-dev", elixir: "~> 1.0", elixirc_paths: elixirc_paths(), escript: escript_config(), From a09d6912ebb88be816ee08814c632d426551fd55 Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Sat, 4 Mar 2017 15:29:37 -0600 Subject: [PATCH 452/860] Track module reference use --- lib/elixir_script/passes/handle_output.ex | 2 +- .../translator/kernel/defmodule.ex | 6 -- lib/elixir_script/translator/kernel/js.ex | 19 +----- lib/elixir_script/translator/state.ex | 65 ++++--------------- 4 files changed, 14 insertions(+), 78 deletions(-) diff --git a/lib/elixir_script/passes/handle_output.ex b/lib/elixir_script/passes/handle_output.ex index 30ae42c0..a3bab884 100644 --- a/lib/elixir_script/passes/handle_output.ex +++ b/lib/elixir_script/passes/handle_output.ex @@ -25,7 +25,7 @@ defmodule ElixirScript.Passes.HandleOutput do IO.write(concat(code)) end - defp out(compiler_output, %{output: output_path, core_path: _} = compiler_opts) do + defp out(compiler_output, %{output: output_path, core_path: _}) do file_name = get_js_path(output_path) if !File.exists?(Path.dirname(file_name)) do diff --git a/lib/elixir_script/translator/kernel/defmodule.ex b/lib/elixir_script/translator/kernel/defmodule.ex index 17f1c7c1..d51e62a9 100644 --- a/lib/elixir_script/translator/kernel/defmodule.ex +++ b/lib/elixir_script/translator/kernel/defmodule.ex @@ -78,12 +78,6 @@ defmodule ElixirScript.Translator.Defmodule do {body, exported_object} end - def process_module_refs(module_refs, env) do - Enum.map(module_refs, fn(x) -> - {x, ""} - end) - end - def translate_body(body, env) do { body, env } = Translator.translate(body, env) diff --git a/lib/elixir_script/translator/kernel/js.ex b/lib/elixir_script/translator/kernel/js.ex index 27acde1d..1d7dc8ad 100644 --- a/lib/elixir_script/translator/kernel/js.ex +++ b/lib/elixir_script/translator/kernel/js.ex @@ -3,8 +3,6 @@ defmodule ElixirScript.Translator.JS do alias ESTree.Tools.Builder alias ElixirScript.Translator - alias ElixirScript.Translator.Identifier - alias ElixirScript.Translator.State @doc false def translate_js_function(name, params, env) do @@ -35,7 +33,7 @@ defmodule ElixirScript.Translator.JS do ) end - defp do_translate({:yield, _, []}, env) do + defp do_translate({:yield, _, []}, _) do Builder.yield_expression() end @@ -80,21 +78,6 @@ defmodule ElixirScript.Translator.JS do Translator.translate!(quoted, env) end - defp do_translate({:import, _, [module_name, from, [default: false]]}, env) do - State.add_javascript_module_reference(env.state, env.module, module_name, from, false) - %ElixirScript.Translator.Empty{} - end - - defp do_translate({:import, _, [module_name, from, [default: true]]}, env) do - State.add_javascript_module_reference(env.state, env.module, module_name, from, true) - %ElixirScript.Translator.Empty{} - end - - defp do_translate({:import, _, [module_name, from]}, env) do - State.add_javascript_module_reference(env.state, env.module, module_name, from, true) - %ElixirScript.Translator.Empty{} - end - defp do_translate({:object, _, [args]}, env) do args = Enum.map(args, fn { k, v } when Kernel.is_atom(k) -> diff --git a/lib/elixir_script/translator/state.ex b/lib/elixir_script/translator/state.ex index 25d038a0..85aec85c 100644 --- a/lib/elixir_script/translator/state.ex +++ b/lib/elixir_script/translator/state.ex @@ -15,34 +15,6 @@ defmodule ElixirScript.Translator.State do end) end - def serialize(pid) do - Agent.get(pid, fn(state) -> - modules = state.modules - modules = Enum.map(modules, fn {m, d} -> - d = Map.delete(d, :javascript_ast) - |> Map.delete(:javascript_module) - |> Map.delete(:javascript_code) - |> Map.delete(:javascript_name) - - {m, d} - end) - |> Enum.filter(fn {_, d} -> d.type != :consolidated end) - - state = Map.delete(state, :changed_modules) - |> Map.put(:modules, modules) - - :erlang.term_to_binary(state) - end) - end - - def deserialize(pid, frozen_state, loaded_modules \\ []) do - Agent.update(pid, fn state -> - frozen_state = :erlang.binary_to_term(frozen_state) - modules = Keyword.delete(frozen_state.modules, ElixirScript.Temp) - %{ state | modules: modules, std_lib_map: frozen_state.std_lib_map, loaded_modules: [JS | loaded_modules] } - end) - end - defp build_standard_lib_map() do Map.new |> Map.put(Kernel, ElixirScript.Kernel) @@ -141,11 +113,11 @@ defmodule ElixirScript.Translator.State do def add_module_reference(pid, module_name, module_ref) do Agent.update(pid, fn(state) -> - case Keyword.get(state.modules, do_get_module_name(module_name, state)) do + case Keyword.get(state.modules, do_get_module_name(module_ref, state)) do nil -> state module -> - module = Map.update(module, :deps, [module_ref], fn(x) -> Enum.uniq(x ++ [module_ref]) end) + module = Map.update(module, :refs, [module_name], fn(x) -> Enum.uniq(x ++ [module_name]) end) modules = Keyword.put(state.modules, module.name, module) %{ state | modules: modules } end @@ -157,10 +129,18 @@ defmodule ElixirScript.Translator.State do nil -> [] module -> - Map.get(module, :deps, []) + Map.get(module, :refs, []) end end + def list_module_references(pid) do + Agent.get(pid, fn(state) -> + Enum.map(state.modules, fn {name, module} -> + {name, Map.get(module, :refs, [])} + end) + end) + end + def list_modules(pid) do Agent.get(pid, fn(state) -> Keyword.values(state.modules) @@ -176,26 +156,5 @@ defmodule ElixirScript.Translator.State do def stop(pid) do Agent.stop(pid) end - - def add_javascript_module_reference(pid, module_name, name, path, default \\ true) do - Agent.update(pid, fn(state) -> - case Keyword.get(state.modules, do_get_module_name(module_name, state)) do - nil -> - state - module -> - module = Map.update(module, :js_modules, [{name, path, default}], fn(x) -> Enum.uniq(x ++ [{name, path, default}]) end) - modules = Keyword.put(state.modules, module.name, module) - %{ state | modules: modules } - end - end) - end - - def get_javascript_module_references(pid, module_name) do - case get_module(pid, module_name) do - nil -> - [] - module -> - Map.get(module, :js_modules, []) - end - end end + From 9350d23f15b61b8b23089237f8b7389751783139 Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Sat, 4 Mar 2017 15:54:09 -0600 Subject: [PATCH 453/860] Add __table to root object --- mix.exs | 2 ++ src/javascript/lib/core/functions.js | 40 +++++++++++++++------------- 2 files changed, 24 insertions(+), 18 deletions(-) diff --git a/mix.exs b/mix.exs index c95354bf..e089a658 100644 --- a/mix.exs +++ b/mix.exs @@ -79,6 +79,8 @@ defmodule ElixirScript.Mixfile do File.rm_rf(dist_folder) end + System.cmd("npm", ["run", "build"]) + File.mkdir_p(folder_name <> "/bin") File.cp!("elixirscript", "#{folder_name}/bin/elixirscript") if File.exists?("priv/.DS_Store") do diff --git a/src/javascript/lib/core/functions.js b/src/javascript/lib/core/functions.js index 4ba9945f..8b09d2f0 100644 --- a/src/javascript/lib/core/functions.js +++ b/src/javascript/lib/core/functions.js @@ -1,14 +1,14 @@ -import Protocol from "./protocol"; -import Core from "../core"; +import Protocol from './protocol'; +import Core from '../core'; function call_property(item, property) { let prop = null; if ( - typeof item === "number" || - typeof item === "symbol" || - typeof item === "boolean" || - typeof item === "string" + typeof item === 'number' || + typeof item === 'symbol' || + typeof item === 'boolean' || + typeof item === 'string' ) { if (item[property] !== undefined) { prop = property; @@ -50,15 +50,15 @@ function contains(left, right) { } function get_global() { - if (typeof self !== "undefined") { + if (typeof self !== 'undefined') { return self; - } else if (typeof window !== "undefined") { + } else if (typeof window !== 'undefined') { return window; - } else if (typeof global !== "undefined") { + } else if (typeof global !== 'undefined') { return global; } - throw new Error("No global state found"); + throw new Error('No global state found'); } function defstruct(defaults) { @@ -78,7 +78,7 @@ function defstruct(defaults) { function defexception(defaults) { return class extends Error { constructor(update = {}) { - const message = update.message || ""; + const message = update.message || ''; super(message); const the_values = Object.assign(defaults, update); @@ -86,7 +86,7 @@ function defexception(defaults) { this.name = this.constructor.name; this.message = message; - this[Symbol.for("__exception__")] = true; + this[Symbol.for('__exception__')] = true; Error.captureStackTrace(this, this.constructor.name); } @@ -148,7 +148,7 @@ function update_map(map, property, value) { return add_property_to_map(map, property, value); } - throw "map does not have key"; + throw 'map does not have key'; } function bnot(expr) { @@ -309,9 +309,9 @@ function reverse(list) { function maps_find(key, map) { if (key in get_object_keys(map)) { - return new Core.Tuple(Symbol.for("ok"), map[key]); + return new Core.Tuple(Symbol.for('ok'), map[key]); } - return Symbol.for("error"); + return Symbol.for('error'); } function flatten(list, tail = []) { @@ -378,21 +378,25 @@ function maps_fold(fun, acc, map) { } function build_namespace(ns, ns_string) { - let parts = ns_string.split("."); + let parts = ns_string.split('.'); + const root = ns; let parent = ns; - if (parts[0] === "Elixir") { + if (parts[0] === 'Elixir') { parts = parts.slice(1); } for (const part of parts) { - if (typeof parent[part] === "undefined") { + if (typeof parent[part] === 'undefined') { parent[part] = {}; } parent = parent[part]; } + root.__table = ns.__table || {}; + root.__table[Symbol.for(ns_string)] = parent; + return parent; } From 8a854b612260da503cfb5d2cff488c9bee27582b Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Sat, 4 Mar 2017 18:10:43 -0600 Subject: [PATCH 454/860] Add support for super for defoverridable --- CHANGELOG.md | 4 + FAQ.md | 2 +- lib/elixir_script.ex | 15 ++-- .../passes/handle_overridables.ex | 86 +++++++++++++++++++ lib/elixir_script/translator.ex | 7 ++ priv/std_lib/keyword.ex | 4 + 6 files changed, 109 insertions(+), 9 deletions(-) create mode 100644 lib/elixir_script/passes/handle_overridables.ex diff --git a/CHANGELOG.md b/CHANGELOG.md index c7ba7e10..1f6689ef 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,10 @@ and this project adheres to [Semantic Versioning](http://semver.org/). ## [0.27.0-dev] +### Added +- `super` +- `defoverridable` + ### Changed - `-ex` alias is now `-e` - A filename can be specified for output diff --git a/FAQ.md b/FAQ.md index dbc25aae..3c2ad53e 100644 --- a/FAQ.md +++ b/FAQ.md @@ -38,9 +38,9 @@ The compiler to this point has been focused on translating Kernel.SpecialForms a * `alias` * `__CALLER__` * `__ENV__` + * `super(args)` * Missing - * `super(args)` * `receive` * Caveats diff --git a/lib/elixir_script.ex b/lib/elixir_script.ex index 659fa607..fd218c7c 100644 --- a/lib/elixir_script.ex +++ b/lib/elixir_script.ex @@ -75,8 +75,14 @@ defmodule ElixirScript do %{data: std_lib_quoted ++ data} |> ElixirScript.Passes.Init.execute(opts) + |> shared_passes(opts) + end + + defp shared_passes(compiler_data, opts) do + compiler_data |> ElixirScript.Passes.FindModules.execute(opts) |> ElixirScript.Passes.FindLoadOnly.execute(opts) + |> ElixirScript.Passes.HandleOverridables.execute(opts) |> ElixirScript.Passes.FindFunctions.execute(opts) |> ElixirScript.Passes.JavaScriptAST.execute(opts) |> ElixirScript.Passes.ConsolidateProtocols.execute(opts) @@ -164,14 +170,7 @@ defmodule ElixirScript do |> ElixirScript.Passes.Init.execute(opts) |> ElixirScript.Passes.ASTFromFile.execute(opts) |> ElixirScript.Passes.LoadModules.execute(opts) - |> ElixirScript.Passes.FindModules.execute(opts) - |> ElixirScript.Passes.FindLoadOnly.execute(opts) - |> ElixirScript.Passes.FindFunctions.execute(opts) - |> ElixirScript.Passes.JavaScriptAST.execute(opts) - |> ElixirScript.Passes.ConsolidateProtocols.execute(opts) - |> ElixirScript.Passes.CreateJSModules.execute(opts) - |> ElixirScript.Passes.JavaScriptCode.execute(opts) - |> ElixirScript.Passes.HandleOutput.execute(opts) + |> shared_passes(opts) result end diff --git a/lib/elixir_script/passes/handle_overridables.ex b/lib/elixir_script/passes/handle_overridables.ex new file mode 100644 index 00000000..a226d404 --- /dev/null +++ b/lib/elixir_script/passes/handle_overridables.ex @@ -0,0 +1,86 @@ +defmodule ElixirScript.Passes.HandleOverridables do + @moduledoc false + + def execute(compiler_data, opts) do + new_data = Enum.map(compiler_data.data, fn { module_name, module_data } -> + overridables = get_overridables(module_data.ast) + ast = handle_overridable(module_data.ast, overridables) + module_data = Map.put(module_data, :ast, ast) + + {module_name, module_data} + end) + + Map.put(compiler_data, :data, new_data) + end + + defp get_overridables({:__block__, [], body}) do + defover = Enum.find(body, fn + {:defoverridable, _, _} -> + true + _ -> + false + end) + + if is_nil(defover) do + [] + else + {:defoverridable, _, [overridables]} = defover + overridables + end + end + + defp handle_overridable(ast, []) do + ast + end + + defp handle_overridable({:__block__, [], body}, overridables) do + result = body + |> Enum.reduce(%{overridables: [], overridable_found: false, body: []}, fn + {:def, def_context, [{name, context, params}, function_body] } = ast, %{overridable_found: false} = acc -> + Map.put(acc, :overridables, acc.overridables ++ [ast]) + + {:defoverridable, _, _}, acc -> + Map.put(acc, :overridable_found, true) + x, acc -> + Map.put(acc, :body, acc.body ++ [x]) + end) + + processed_overridables = Enum.map(result.overridables, fn + {:def, def_context, [{name, context, params}, function_body] } = ast -> + arity = get_arity(params) + + found = Enum.any?(result.body, fn + {:def, _, [{name_from_body, _, params_from_body}, _] } -> + if {name, arity} == {name_from_body, get_arity(params_from_body)} do + true + else + false + end + _ -> + false + end) + + if found do + super_name = String.to_atom("__super__" <> to_string(name)) + {:defp, def_context, [{super_name, context, params}, function_body] } + else + ast + end + end) + + body = processed_overridables ++ result.body + {:__block__, [], body} + end + + defp get_arity(params) do + cond do + is_nil(params) -> + 0 + is_atom(params) -> + 0 + true -> + length(params) + end + end + +end \ No newline at end of file diff --git a/lib/elixir_script/translator.ex b/lib/elixir_script/translator.ex index 83d07ff6..a4e30f7b 100644 --- a/lib/elixir_script/translator.ex +++ b/lib/elixir_script/translator.ex @@ -243,6 +243,13 @@ defmodule ElixirScript.Translator do { Map.make_get_property(target, property, env), env } end + defp do_translate({:super, _, params }, env) do + { name, _ } = env.function + super_name = String.to_atom("__super__" <> to_string(name)) + + Call.make_local_function_call(super_name, params, env) + end + defp do_translate({{:., _, [function_name]}, _, params}, env) do Call.make_local_function_call(function_name, params, env) end diff --git a/priv/std_lib/keyword.ex b/priv/std_lib/keyword.ex index c08c71b1..2c91ec9f 100644 --- a/priv/std_lib/keyword.ex +++ b/priv/std_lib/keyword.ex @@ -1,6 +1,10 @@ defmodule ElixirScript.Keyword do @moduledoc false + def new() do + [] + end + def has_key?(kw, key) do do_has_key?(kw, key) end From b715ef98d802389996ef2c67334d7f079a7e406b Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Sat, 4 Mar 2017 18:34:22 -0600 Subject: [PATCH 455/860] Make sure both def and defp are supported --- lib/elixir_script/passes/handle_overridables.ex | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/lib/elixir_script/passes/handle_overridables.ex b/lib/elixir_script/passes/handle_overridables.ex index a226d404..44ae2b90 100644 --- a/lib/elixir_script/passes/handle_overridables.ex +++ b/lib/elixir_script/passes/handle_overridables.ex @@ -1,5 +1,6 @@ defmodule ElixirScript.Passes.HandleOverridables do @moduledoc false + @function_types [:def, :defp] def execute(compiler_data, opts) do new_data = Enum.map(compiler_data.data, fn { module_name, module_data } -> @@ -36,7 +37,7 @@ defmodule ElixirScript.Passes.HandleOverridables do defp handle_overridable({:__block__, [], body}, overridables) do result = body |> Enum.reduce(%{overridables: [], overridable_found: false, body: []}, fn - {:def, def_context, [{name, context, params}, function_body] } = ast, %{overridable_found: false} = acc -> + {type, def_context, [{name, context, params}, function_body] } = ast, %{overridable_found: false} = acc when type in @function_types -> Map.put(acc, :overridables, acc.overridables ++ [ast]) {:defoverridable, _, _}, acc -> @@ -46,11 +47,11 @@ defmodule ElixirScript.Passes.HandleOverridables do end) processed_overridables = Enum.map(result.overridables, fn - {:def, def_context, [{name, context, params}, function_body] } = ast -> + {type, def_context, [{name, context, params}, function_body] } = ast when type in @function_types -> arity = get_arity(params) found = Enum.any?(result.body, fn - {:def, _, [{name_from_body, _, params_from_body}, _] } -> + {type, _, [{name_from_body, _, params_from_body}, _] } -> if {name, arity} == {name_from_body, get_arity(params_from_body)} do true else From 34e81a82149c731a87bbe46d81c7c002875f5204 Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Sun, 5 Mar 2017 15:47:41 -0600 Subject: [PATCH 456/860] Update README.md --- README.md | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 89ca4c9f..12b15a92 100644 --- a/README.md +++ b/README.md @@ -29,7 +29,11 @@ Clone the repo Get dependencies mix deps.get - npm install + yarn + +Create Elixir.Bootstrap.js + + yarn build Compile @@ -38,7 +42,7 @@ Compile Test mix test - npm test + yarn test Build From 09d7205c5a846fbea92d83b709285731e3a7aa58 Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Sun, 5 Mar 2017 15:48:35 -0600 Subject: [PATCH 457/860] Update README.md --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index 12b15a92..41d5886b 100644 --- a/README.md +++ b/README.md @@ -59,6 +59,7 @@ Communication ======== [gitter room](https://gitter.im/elixirscript/elixirscript) + [#elixirscript](https://elixir-lang.slack.com/messages/elixirscript/) on the elixir-lang Slack Contributing From 574767ba3a6fb4553a0a9768c2ed2a2e1572e80f Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Sun, 5 Mar 2017 16:39:36 -0600 Subject: [PATCH 458/860] Update clean command in package.json --- mix.exs | 4 ++-- package.json | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/mix.exs b/mix.exs index e089a658..5da7fda2 100644 --- a/mix.exs +++ b/mix.exs @@ -6,7 +6,7 @@ defmodule ElixirScript.Mixfile do app: :elixir_script, version: "0.27.0-dev", elixir: "~> 1.0", - elixirc_paths: elixirc_paths(), + elixirc_paths: elixirc_paths(), escript: escript_config(), deps: deps(), description: description(), @@ -37,7 +37,7 @@ defmodule ElixirScript.Mixfile do ] end - defp elixirc_paths(), do: ["lib", "priv/std_lib"] + defp elixirc_paths(), do: ["lib", "priv/std_lib"] defp escript_config do [main_module: ElixirScript.CLI, name: "elixirscript"] diff --git a/package.json b/package.json index 5387ddfb..38b4b280 100644 --- a/package.json +++ b/package.json @@ -10,7 +10,7 @@ "lint": "eslint src/javascript/lib/**/*.js src/javascript/tests/**/*.js", "lint:fix": "eslint src/javascript/lib/**/*.js src/javascript/tests/**/*.js --fix", "build": "rollup -c rollup.config.js", - "clean": "rm -rf priv", + "clean": "rm -rf priv/build", "test": "mocha src/javascript/tests --recursive --compilers js:babel-core/register" }, "repository": { @@ -44,4 +44,4 @@ "rollup-plugin-node-resolve": "^2.0.0", "rollup-plugin-uglify": "^1.0.1" } -} \ No newline at end of file +} From 4210c19d04565723319ceb0c7cea245a8af250bb Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Mon, 6 Mar 2017 21:25:40 -0600 Subject: [PATCH 459/860] Refactor out references to Dict --- lib/elixir_script/translator/kernel/defmodule.ex | 16 ++++++++-------- .../translator/kernel/special_forms/for.ex | 8 ++++---- .../translator/kernel/special_forms/try.ex | 10 +++++----- 3 files changed, 17 insertions(+), 17 deletions(-) diff --git a/lib/elixir_script/translator/kernel/defmodule.ex b/lib/elixir_script/translator/kernel/defmodule.ex index d51e62a9..285eab4b 100644 --- a/lib/elixir_script/translator/kernel/defmodule.ex +++ b/lib/elixir_script/translator/kernel/defmodule.ex @@ -188,28 +188,28 @@ defmodule ElixirScript.Translator.Defmodule do end def process_functions(%{ exported: exported, private: private, exported_generators: exported_generators, private_generators: private_generators }, env) do - exported_functions = Enum.map(Dict.keys(exported), fn(key) -> - functions = Dict.get(exported, key) + exported_functions = Enum.map(Map.keys(exported), fn(key) -> + functions = Map.get(exported, key) { functions, _ } = Def.process_function(key, functions, env) { key, functions } end) - exported_generators = Enum.map(Dict.keys(exported_generators), fn(key) -> - functions = Dict.get(exported_generators, key) + exported_generators = Enum.map(Map.keys(exported_generators), fn(key) -> + functions = Map.get(exported_generators, key) { functions, _ } = Def.process_function(key, functions, %{ env | context: :generator}) { key, functions } end) - private_functions = Enum.map(Dict.keys(private), fn(key) -> - functions = Dict.get(private, key) + private_functions = Enum.map(Map.keys(private), fn(key) -> + functions = Map.get(private, key) { functions, _ } = Def.process_function(key, functions, env) { key, functions } end) - private_generators = Enum.map(Dict.keys(private_generators), fn(key) -> - functions = Dict.get(private_generators, key) + private_generators = Enum.map(Map.keys(private_generators), fn(key) -> + functions = Map.get(private_generators, key) { functions, _ } = Def.process_function(key, functions, %{ env | context: :generator}) { key, functions } end) diff --git a/lib/elixir_script/translator/kernel/special_forms/for.ex b/lib/elixir_script/translator/kernel/special_forms/for.ex index 3c6293e4..e690f710 100644 --- a/lib/elixir_script/translator/kernel/special_forms/for.ex +++ b/lib/elixir_script/translator/kernel/special_forms/for.ex @@ -6,13 +6,13 @@ defmodule ElixirScript.Translator.For do alias ElixirScript.Translator.Primitive alias ElixirScript.Translator.Function alias ElixirScript.Translator.Utils - alias ElixirScript.Translator.Identifier + alias ElixirScript.Translator.Identifier def make_for(generators, env) do ElixirScript.Translator.State.add_module_reference(env.state, env.module, ElixirScript.Collectable) args = handle_args(generators, env) - generators = JS.array_expression(args.generators) + generators = JS.array_expression(args.generators) into = args.into || Primitive.make_list_no_translate([]) filter = args.filter || JS.function_expression([], [], JS.block_statement([JS.return_statement(JS.identifier("true"))])) @@ -54,11 +54,11 @@ defmodule ElixirScript.Translator.For do defp handle_args(generators, env) do Enum.reduce(generators, %{generators: [], args: [], filter: nil, fun: nil, into: nil, patterns: []}, fn - ({:<<>>, [], body}, state) -> + ({:<<>>, _, body}, state) -> {bs_parts, collection} = Enum.map_reduce(body, nil, fn {:::, _, _} = ast, state -> {ast, state} - {:<-, [], [var, collection]}, _ -> + {:<-, _, [var, collection]}, _ -> {var, collection} end) diff --git a/lib/elixir_script/translator/kernel/special_forms/try.ex b/lib/elixir_script/translator/kernel/special_forms/try.ex index 81db4a39..c281b6a6 100644 --- a/lib/elixir_script/translator/kernel/special_forms/try.ex +++ b/lib/elixir_script/translator/kernel/special_forms/try.ex @@ -5,11 +5,11 @@ defmodule ElixirScript.Translator.Try do alias ElixirScript.Translator.Primitive def make_try(blocks, env) do - try_block = Dict.get(blocks, :do) - rescue_block = Dict.get(blocks, :rescue, nil) - catch_block = Dict.get(blocks, :catch, nil) - after_block = Dict.get(blocks, :after, nil) - else_block = Dict.get(blocks, :else, nil) + try_block = Keyword.get(blocks, :do) + rescue_block = Keyword.get(blocks, :rescue, nil) + catch_block = Keyword.get(blocks, :catch, nil) + after_block = Keyword.get(blocks, :after, nil) + else_block = Keyword.get(blocks, :else, nil) { translated_body, _ } = Function.prepare_function_body(try_block, env) From a6e6477c8df11a72167679c5fc25bcd9f5dd2306 Mon Sep 17 00:00:00 2001 From: Jody LeCompte Date: Wed, 8 Mar 2017 13:03:09 -0600 Subject: [PATCH 460/860] Beginning credo cleanup * credo configuration altered so that delibarately placed spaces around certain expresions no longer throw errors * Corrected remaining credo errors in elixir_script.ex --- .credo.exs | 2 +- lib/elixir_script.ex | 5 +++-- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/.credo.exs b/.credo.exs index 18abcc24..ea83b9c6 100644 --- a/.credo.exs +++ b/.credo.exs @@ -52,7 +52,7 @@ {Credo.Check.Consistency.MultiAliasImportRequireUse}, {Credo.Check.Consistency.ParameterPatternMatching}, {Credo.Check.Consistency.SpaceAroundOperators}, - {Credo.Check.Consistency.SpaceInParentheses}, + {Credo.Check.Consistency.SpaceInParentheses, false}, {Credo.Check.Consistency.TabsOrSpaces}, # For some checks, like AliasUsage, you can only customize the priority diff --git a/lib/elixir_script.ex b/lib/elixir_script.ex index fd218c7c..bde9904f 100644 --- a/lib/elixir_script.ex +++ b/lib/elixir_script.ex @@ -164,9 +164,9 @@ defmodule ElixirScript do |> Map.to_list |> Enum.map(fn {app, path} -> {app, List.wrap(path)} end) - deps = [{:elixir, List.wrap(get_std_lib_path())}] ++ deps + deps_wrapped = [{:elixir, List.wrap(get_std_lib_path())}] ++ deps - result = %{data: deps} + result = %{data: deps_wrapped} |> ElixirScript.Passes.Init.execute(opts) |> ElixirScript.Passes.ASTFromFile.execute(opts) |> ElixirScript.Passes.LoadModules.execute(opts) @@ -207,6 +207,7 @@ defmodule ElixirScript do @doc """ Returns the contents of the bootrstrap js file """ + @spec get_bootstrap_js(string) :: string def get_bootstrap_js(module_format) do path = Path.join([operating_path, "build", to_string(module_format), "Elixir.Bootstrap.js"]) File.read!(path) From 2f0ccada94bb8a7a1ce1b9262e1e7a877bf227b5 Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Wed, 8 Mar 2017 19:00:55 -0600 Subject: [PATCH 461/860] Make sure mix compiler works in umbrella projects --- .../elixir_script_compile_error.ex | 3 +++ lib/mix/tasks/compile.elixir_script.ex | 21 +++++++++++++------ 2 files changed, 18 insertions(+), 6 deletions(-) create mode 100644 lib/elixir_script/elixir_script_compile_error.ex diff --git a/lib/elixir_script/elixir_script_compile_error.ex b/lib/elixir_script/elixir_script_compile_error.ex new file mode 100644 index 00000000..978d1d84 --- /dev/null +++ b/lib/elixir_script/elixir_script_compile_error.ex @@ -0,0 +1,3 @@ +defmodule ElixirScriptCompileError do + defexception [:message] +end diff --git a/lib/mix/tasks/compile.elixir_script.ex b/lib/mix/tasks/compile.elixir_script.ex index df25aaa7..b02c937d 100644 --- a/lib/mix/tasks/compile.elixir_script.ex +++ b/lib/mix/tasks/compile.elixir_script.ex @@ -1,6 +1,8 @@ defmodule Mix.Tasks.Compile.ElixirScript do use Mix.Task + @recursive true + @moduledoc """ Mix compiler to allow mix to compile Elixirscript source files into JavaScript @@ -16,11 +18,11 @@ defmodule Mix.Tasks.Compile.ElixirScript do compilers: [:elixir_script] ++ Mix.compilers ] end - + Available options are: * `input`: The folder to look for Elixirscript files in. (defaults to `lib/elixirscript`) * `output`: The path of the generated JavaScript file. (defaults to `priv/elixirscript`) - + If path ends in `.js` then that will be the name of the file. If a directory is given, file will be named `Elixir.App.js` * `format`: The module format of generated JavaScript code. (defaults to `:es`). @@ -35,11 +37,19 @@ defmodule Mix.Tasks.Compile.ElixirScript do @spec run(any()) :: :ok def run(_) do - elixirscript_config = get_elixirscript_config() - elixirscript_base = Path.join([Mix.Project.build_path, "elixirscript"]) + do_compile(elixirscript_base, Mix.Project.config[:app]) + :ok + end + + defp do_compile(_, nil) do + raise ElixirScriptCompileError, message: "Unable to find mix project app name" + end + + defp do_compile(elixirscript_base, app) do + elixirscript_config = get_elixirscript_config() File.mkdir_p!(elixirscript_base) - elixirscript_path = Path.join([elixirscript_base, "#{Mix.Project.config[:app]}"]) + elixirscript_path = Path.join([elixirscript_base, "#{app}"]) input_path = elixirscript_config |> Keyword.get(:input) @@ -66,7 +76,6 @@ defmodule Mix.Tasks.Compile.ElixirScript do js_modules = Keyword.get(elixirscript_config, :js_modules, []) ElixirScript.compile_path(paths, %{output: output_path, format: format, js_modules: js_modules}) - :ok end def clean do From 35798f95fea1b9330550f30dc0551bb718d78016 Mon Sep 17 00:00:00 2001 From: Stephan van Diepen Date: Sun, 5 Mar 2017 12:56:45 +0100 Subject: [PATCH 462/860] Add Elixir.load function --- lib/elixir_script/passes/create_js_modules.ex | 22 ++++++++++++++++++- 1 file changed, 21 insertions(+), 1 deletion(-) diff --git a/lib/elixir_script/passes/create_js_modules.ex b/lib/elixir_script/passes/create_js_modules.ex index 0986ae7c..fa81d145 100644 --- a/lib/elixir_script/passes/create_js_modules.ex +++ b/lib/elixir_script/passes/create_js_modules.ex @@ -92,10 +92,30 @@ defmodule ElixirScript.Passes.CreateJSModules do ) ) + load = JS.assignment_expression( + :=, + JS.member_expression( + JS.identifier("Elixir"), + JS.identifier("load") + ), + JS.function_expression( + [JS.identifier(:module)], + [], + JS.block_statement([ + JS.return_statement( + JS.member_expression( + JS.identifier(:module), + JS.identifier("__exports") + ) + ) + ]) + ) + ) + ast = opts.module_formatter.build( [], opts.js_modules, - [elixir, start] ++ body, + [elixir, start, load] ++ body, JS.identifier("Elixir") ) From d363aa735003eb6d057ae41fa6254de3a49da53c Mon Sep 17 00:00:00 2001 From: Stephan van Diepen Date: Fri, 10 Mar 2017 08:53:16 +0100 Subject: [PATCH 463/860] Make sure the module is loaded --- lib/elixir_script/passes/create_js_modules.ex | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/lib/elixir_script/passes/create_js_modules.ex b/lib/elixir_script/passes/create_js_modules.ex index fa81d145..a2eebd52 100644 --- a/lib/elixir_script/passes/create_js_modules.ex +++ b/lib/elixir_script/passes/create_js_modules.ex @@ -103,9 +103,12 @@ defmodule ElixirScript.Passes.CreateJSModules do [], JS.block_statement([ JS.return_statement( - JS.member_expression( - JS.identifier(:module), - JS.identifier("__exports") + JS.call_expression( + JS.member_expression( + JS.identifier(:module), + JS.identifier("__load") + ), + [JS.identifier("Elixir")] ) ) ]) From fe126162655ceb3eb68efa8751ebd4e1cb5c1047 Mon Sep 17 00:00:00 2001 From: Stephan van Diepen Date: Fri, 10 Mar 2017 09:11:13 +0100 Subject: [PATCH 464/860] Extract load function --- lib/elixir_script/passes/create_js_modules.ex | 23 ++++++++++--------- 1 file changed, 12 insertions(+), 11 deletions(-) diff --git a/lib/elixir_script/passes/create_js_modules.ex b/lib/elixir_script/passes/create_js_modules.ex index a2eebd52..7e483196 100644 --- a/lib/elixir_script/passes/create_js_modules.ex +++ b/lib/elixir_script/passes/create_js_modules.ex @@ -92,7 +92,18 @@ defmodule ElixirScript.Passes.CreateJSModules do ) ) - load = JS.assignment_expression( + ast = opts.module_formatter.build( + [], + opts.js_modules, + [elixir, start, load] ++ body, + JS.identifier("Elixir") + ) + + ast + end + + def load do + JS.assignment_expression( :=, JS.member_expression( JS.identifier("Elixir"), @@ -114,15 +125,5 @@ defmodule ElixirScript.Passes.CreateJSModules do ]) ) ) - - ast = opts.module_formatter.build( - [], - opts.js_modules, - [elixir, start, load] ++ body, - JS.identifier("Elixir") - ) - - ast end - end From 33432ad193b9a04b73595332f5aa5bce977407cb Mon Sep 17 00:00:00 2001 From: Stephan van Diepen Date: Fri, 10 Mar 2017 09:11:21 +0100 Subject: [PATCH 465/860] Add load spec --- test/passes/create_js_modules_test.exs | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) create mode 100644 test/passes/create_js_modules_test.exs diff --git a/test/passes/create_js_modules_test.exs b/test/passes/create_js_modules_test.exs new file mode 100644 index 00000000..2b1824d9 --- /dev/null +++ b/test/passes/create_js_modules_test.exs @@ -0,0 +1,20 @@ +defmodule ElixirScript.Passes.CreateJSModules.Test do + use ExUnit.Case + + import ElixirScript.TestHelper + + alias ElixirScript.Passes.CreateJSModules + alias ESTree.Tools.Generator + + test "load" do + load_js = CreateJSModules.load + |> Generator.generate + + expected_js = +"Elixir.load = function(module) { + return module.__load(Elixir); +}" + + assert(load_js == expected_js) + end +end From b04e24d2305ffcfec0c99bc517f6e7172b9489a7 Mon Sep 17 00:00:00 2001 From: Stephan van Diepen Date: Fri, 10 Mar 2017 09:44:41 +0100 Subject: [PATCH 466/860] Extract and test start --- lib/elixir_script/passes/create_js_modules.ex | 22 ++++++++++--------- test/passes/create_js_modules_test.exs | 13 +++++++++++ 2 files changed, 25 insertions(+), 10 deletions(-) diff --git a/lib/elixir_script/passes/create_js_modules.ex b/lib/elixir_script/passes/create_js_modules.ex index 7e483196..dbadb4fe 100644 --- a/lib/elixir_script/passes/create_js_modules.ex +++ b/lib/elixir_script/passes/create_js_modules.ex @@ -65,7 +65,18 @@ defmodule ElixirScript.Passes.CreateJSModules do elixir = JS.variable_declaration([declarator], :const) - start = JS.assignment_expression( + ast = opts.module_formatter.build( + [], + opts.js_modules, + [elixir, start, load] ++ body, + JS.identifier("Elixir") + ) + + ast + end + + def start do + JS.assignment_expression( :=, JS.member_expression( JS.identifier("Elixir"), @@ -91,15 +102,6 @@ defmodule ElixirScript.Passes.CreateJSModules do ]) ) ) - - ast = opts.module_formatter.build( - [], - opts.js_modules, - [elixir, start, load] ++ body, - JS.identifier("Elixir") - ) - - ast end def load do diff --git a/test/passes/create_js_modules_test.exs b/test/passes/create_js_modules_test.exs index 2b1824d9..de07bc1f 100644 --- a/test/passes/create_js_modules_test.exs +++ b/test/passes/create_js_modules_test.exs @@ -6,6 +6,19 @@ defmodule ElixirScript.Passes.CreateJSModules.Test do alias ElixirScript.Passes.CreateJSModules alias ESTree.Tools.Generator + test "start" do + start_js = CreateJSModules.start + |> Generator.generate + + expected_js = +"Elixir.start = function(app, args) { + app.__load(Elixir).start(Symbol.for('normal'), args) +}" + + + assert(start_js == expected_js) + end + test "load" do load_js = CreateJSModules.load |> Generator.generate From 4ca520142ab7b4ef53ce0576f6d3649ca782b624 Mon Sep 17 00:00:00 2001 From: Stephan van Diepen Date: Fri, 10 Mar 2017 09:57:14 +0100 Subject: [PATCH 467/860] Use assert_translation in specs --- test/passes/create_js_modules_test.exs | 35 ++++++++++++-------------- 1 file changed, 16 insertions(+), 19 deletions(-) diff --git a/test/passes/create_js_modules_test.exs b/test/passes/create_js_modules_test.exs index de07bc1f..23b4edc3 100644 --- a/test/passes/create_js_modules_test.exs +++ b/test/passes/create_js_modules_test.exs @@ -7,27 +7,24 @@ defmodule ElixirScript.Passes.CreateJSModules.Test do alias ESTree.Tools.Generator test "start" do - start_js = CreateJSModules.start - |> Generator.generate - - expected_js = -"Elixir.start = function(app, args) { - app.__load(Elixir).start(Symbol.for('normal'), args) -}" - - - assert(start_js == expected_js) + ex_ast = quote do: CreateJSModules.start + js = """ + Elixir.start = function(app, args) { + app.__load(Elixir).start(Symbol.for('normal'), args) + } + """ + + assert_translation(ex_ast, js) end test "load" do - load_js = CreateJSModules.load - |> Generator.generate - - expected_js = -"Elixir.load = function(module) { - return module.__load(Elixir); -}" - - assert(load_js == expected_js) + ex_ast = quote do: CreateJSModules.load + js = """ + Elixir.load = function(module) { + return module.__load(Elixir); + } + """ + + assert_translation(ex_ast, js) end end From fcca1e34cc8de1e50f71eb87d299bfbd2d1f8ee2 Mon Sep 17 00:00:00 2001 From: Stephan van Diepen Date: Fri, 10 Mar 2017 13:35:57 +0100 Subject: [PATCH 468/860] Test elixirscript through executed js --- .gitignore | 1 + test/app/convert-exjs | 3 + test/app/package.json | 19 +++ test/app/spec/main.spec.js | 24 ++++ test/app/spec/setup.spec.js | 15 +++ test/app/src/main.ex | 9 ++ test/app/yarn.lock | 261 ++++++++++++++++++++++++++++++++++++ 7 files changed, 332 insertions(+) create mode 100755 test/app/convert-exjs create mode 100644 test/app/package.json create mode 100644 test/app/spec/main.spec.js create mode 100644 test/app/spec/setup.spec.js create mode 100644 test/app/src/main.ex create mode 100644 test/app/yarn.lock diff --git a/.gitignore b/.gitignore index e0db4469..6eea78e1 100644 --- a/.gitignore +++ b/.gitignore @@ -19,3 +19,4 @@ src/elixirscript priv/**/*.js stdlib_state.bin *.log +test/app/build diff --git a/test/app/convert-exjs b/test/app/convert-exjs new file mode 100755 index 00000000..dc457929 --- /dev/null +++ b/test/app/convert-exjs @@ -0,0 +1,3 @@ +cd ../../ + +mix elixirscript test/app/src/ -f common -o test/app/build/ diff --git a/test/app/package.json b/test/app/package.json new file mode 100644 index 00000000..ca322ce4 --- /dev/null +++ b/test/app/package.json @@ -0,0 +1,19 @@ +{ + "name": "elixirscript-js-app", + "version": "1.0.0", + "description": "", + "main": "index.js", + "scripts": { + "test": "npm run test-unit", + "test-unit": "./convert-exjs && NODE_ENV=test mocha --require co-mocha -R spec --ui bdd 'spec/*.spec.js'" + }, + "author": "", + "license": "ISC", + "devDependencies": { + "chai": "^3.5.0", + "co-mocha": "^1.2.0", + "mocha": "^3.2.0", + "sinon": "^1.17.7", + "sinon-chai": "^2.8.0" + } +} diff --git a/test/app/spec/main.spec.js b/test/app/spec/main.spec.js new file mode 100644 index 00000000..f60c9784 --- /dev/null +++ b/test/app/spec/main.spec.js @@ -0,0 +1,24 @@ +const expect = require('chai').expect; +const sinon = require('sinon'); + +const Elixir = require('../build/Elixir.App'); + +describe('Elixir.start', function () { + it('calls the modules start function', function () { + const callback = sinon.spy(); + + Elixir.start(Elixir.Main, callback); + + expect(callback).to.have.been.calledWith('started'); + }); +}); + +describe('Elixir.load', function () { + it('loads the modules exports', function () { + const main = Elixir.load(Elixir.Main); + + expect(main).to.have.property('start'); + expect(main).to.have.property('hello'); + expect(main.hello()).to.eq('Hello!'); + }); +}); diff --git a/test/app/spec/setup.spec.js b/test/app/spec/setup.spec.js new file mode 100644 index 00000000..b1c0f404 --- /dev/null +++ b/test/app/spec/setup.spec.js @@ -0,0 +1,15 @@ +const sinon = require('sinon'); +const chai = require('chai'); +const sinonChai = require('sinon-chai'); + +before(function () { + chai.use(sinonChai); +}); + +beforeEach(function () { + this.sandbox = sinon.sandbox.create(); +}); + +afterEach(function () { + this.sandbox.restore(); +}); diff --git a/test/app/src/main.ex b/test/app/src/main.ex new file mode 100644 index 00000000..5ddefc6a --- /dev/null +++ b/test/app/src/main.ex @@ -0,0 +1,9 @@ +defmodule Main do + def start(:normal, callback) do + callback.("started") + end + + def hello do + "Hello!" + end +end diff --git a/test/app/yarn.lock b/test/app/yarn.lock new file mode 100644 index 00000000..cb4ea46c --- /dev/null +++ b/test/app/yarn.lock @@ -0,0 +1,261 @@ +# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. +# yarn lockfile v1 + + +assertion-error@^1.0.1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/assertion-error/-/assertion-error-1.0.2.tgz#13ca515d86206da0bac66e834dd397d87581094c" + +balanced-match@^0.4.1: + version "0.4.2" + resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-0.4.2.tgz#cb3f3e3c732dc0f01ee70b403f302e61d7709838" + +brace-expansion@^1.0.0: + version "1.1.6" + resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.6.tgz#7197d7eaa9b87e648390ea61fc66c84427420df9" + dependencies: + balanced-match "^0.4.1" + concat-map "0.0.1" + +browser-stdout@1.3.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/browser-stdout/-/browser-stdout-1.3.0.tgz#f351d32969d32fa5d7a5567154263d928ae3bd1f" + +chai@^3.5.0: + version "3.5.0" + resolved "https://registry.yarnpkg.com/chai/-/chai-3.5.0.tgz#4d02637b067fe958bdbfdd3a40ec56fef7373247" + dependencies: + assertion-error "^1.0.1" + deep-eql "^0.1.3" + type-detect "^1.0.0" + +co-mocha@^1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/co-mocha/-/co-mocha-1.2.0.tgz#d9be35a2a2d16f4b1b0e83f6973401ca4b6660af" + dependencies: + co "^4.0.0" + is-generator "^1.0.1" + +co@^4.0.0: + version "4.6.0" + resolved "https://registry.yarnpkg.com/co/-/co-4.6.0.tgz#6ea6bdf3d853ae54ccb8e47bfa0bf3f9031fb184" + +commander@2.9.0: + version "2.9.0" + resolved "https://registry.yarnpkg.com/commander/-/commander-2.9.0.tgz#9c99094176e12240cb22d6c5146098400fe0f7d4" + dependencies: + graceful-readlink ">= 1.0.0" + +concat-map@0.0.1: + version "0.0.1" + resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b" + +debug@2.2.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/debug/-/debug-2.2.0.tgz#f87057e995b1a1f6ae6a4960664137bc56f039da" + dependencies: + ms "0.7.1" + +deep-eql@^0.1.3: + version "0.1.3" + resolved "https://registry.yarnpkg.com/deep-eql/-/deep-eql-0.1.3.tgz#ef558acab8de25206cd713906d74e56930eb69f2" + dependencies: + type-detect "0.1.1" + +diff@1.4.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/diff/-/diff-1.4.0.tgz#7f28d2eb9ee7b15a97efd89ce63dcfdaa3ccbabf" + +escape-string-regexp@1.0.5: + version "1.0.5" + resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4" + +formatio@1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/formatio/-/formatio-1.1.1.tgz#5ed3ccd636551097383465d996199100e86161e9" + dependencies: + samsam "~1.1" + +fs.realpath@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f" + +glob@7.0.5: + version "7.0.5" + resolved "https://registry.yarnpkg.com/glob/-/glob-7.0.5.tgz#b4202a69099bbb4d292a7c1b95b6682b67ebdc95" + dependencies: + fs.realpath "^1.0.0" + inflight "^1.0.4" + inherits "2" + minimatch "^3.0.2" + once "^1.3.0" + path-is-absolute "^1.0.0" + +"graceful-readlink@>= 1.0.0": + version "1.0.1" + resolved "https://registry.yarnpkg.com/graceful-readlink/-/graceful-readlink-1.0.1.tgz#4cafad76bc62f02fa039b2f94e9a3dd3a391a725" + +growl@1.9.2: + version "1.9.2" + resolved "https://registry.yarnpkg.com/growl/-/growl-1.9.2.tgz#0ea7743715db8d8de2c5ede1775e1b45ac85c02f" + +has-flag@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-1.0.0.tgz#9d9e793165ce017a00f00418c43f942a7b1d11fa" + +inflight@^1.0.4: + version "1.0.6" + resolved "https://registry.yarnpkg.com/inflight/-/inflight-1.0.6.tgz#49bd6331d7d02d0c09bc910a1075ba8165b56df9" + dependencies: + once "^1.3.0" + wrappy "1" + +inherits@2, inherits@2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.1.tgz#b17d08d326b4423e568eff719f91b0b1cbdf69f1" + +is-generator@^1.0.1: + version "1.0.3" + resolved "https://registry.yarnpkg.com/is-generator/-/is-generator-1.0.3.tgz#c14c21057ed36e328db80347966c693f886389f3" + +json3@3.3.2: + version "3.3.2" + resolved "https://registry.yarnpkg.com/json3/-/json3-3.3.2.tgz#3c0434743df93e2f5c42aee7b19bcb483575f4e1" + +lodash._baseassign@^3.0.0: + version "3.2.0" + resolved "https://registry.yarnpkg.com/lodash._baseassign/-/lodash._baseassign-3.2.0.tgz#8c38a099500f215ad09e59f1722fd0c52bfe0a4e" + dependencies: + lodash._basecopy "^3.0.0" + lodash.keys "^3.0.0" + +lodash._basecopy@^3.0.0: + version "3.0.1" + resolved "https://registry.yarnpkg.com/lodash._basecopy/-/lodash._basecopy-3.0.1.tgz#8da0e6a876cf344c0ad8a54882111dd3c5c7ca36" + +lodash._basecreate@^3.0.0: + version "3.0.3" + resolved "https://registry.yarnpkg.com/lodash._basecreate/-/lodash._basecreate-3.0.3.tgz#1bc661614daa7fc311b7d03bf16806a0213cf821" + +lodash._getnative@^3.0.0: + version "3.9.1" + resolved "https://registry.yarnpkg.com/lodash._getnative/-/lodash._getnative-3.9.1.tgz#570bc7dede46d61cdcde687d65d3eecbaa3aaff5" + +lodash._isiterateecall@^3.0.0: + version "3.0.9" + resolved "https://registry.yarnpkg.com/lodash._isiterateecall/-/lodash._isiterateecall-3.0.9.tgz#5203ad7ba425fae842460e696db9cf3e6aac057c" + +lodash.create@3.1.1: + version "3.1.1" + resolved "https://registry.yarnpkg.com/lodash.create/-/lodash.create-3.1.1.tgz#d7f2849f0dbda7e04682bb8cd72ab022461debe7" + dependencies: + lodash._baseassign "^3.0.0" + lodash._basecreate "^3.0.0" + lodash._isiterateecall "^3.0.0" + +lodash.isarguments@^3.0.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/lodash.isarguments/-/lodash.isarguments-3.1.0.tgz#2f573d85c6a24289ff00663b491c1d338ff3458a" + +lodash.isarray@^3.0.0: + version "3.0.4" + resolved "https://registry.yarnpkg.com/lodash.isarray/-/lodash.isarray-3.0.4.tgz#79e4eb88c36a8122af86f844aa9bcd851b5fbb55" + +lodash.keys@^3.0.0: + version "3.1.2" + resolved "https://registry.yarnpkg.com/lodash.keys/-/lodash.keys-3.1.2.tgz#4dbc0472b156be50a0b286855d1bd0b0c656098a" + dependencies: + lodash._getnative "^3.0.0" + lodash.isarguments "^3.0.0" + lodash.isarray "^3.0.0" + +lolex@1.3.2: + version "1.3.2" + resolved "https://registry.yarnpkg.com/lolex/-/lolex-1.3.2.tgz#7c3da62ffcb30f0f5a80a2566ca24e45d8a01f31" + +minimatch@^3.0.2: + version "3.0.3" + resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.0.3.tgz#2a4e4090b96b2db06a9d7df01055a62a77c9b774" + dependencies: + brace-expansion "^1.0.0" + +minimist@0.0.8: + version "0.0.8" + resolved "https://registry.yarnpkg.com/minimist/-/minimist-0.0.8.tgz#857fcabfc3397d2625b8228262e86aa7a011b05d" + +mkdirp@0.5.1: + version "0.5.1" + resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.5.1.tgz#30057438eac6cf7f8c4767f38648d6697d75c903" + dependencies: + minimist "0.0.8" + +mocha@^3.2.0: + version "3.2.0" + resolved "https://registry.yarnpkg.com/mocha/-/mocha-3.2.0.tgz#7dc4f45e5088075171a68896814e6ae9eb7a85e3" + dependencies: + browser-stdout "1.3.0" + commander "2.9.0" + debug "2.2.0" + diff "1.4.0" + escape-string-regexp "1.0.5" + glob "7.0.5" + growl "1.9.2" + json3 "3.3.2" + lodash.create "3.1.1" + mkdirp "0.5.1" + supports-color "3.1.2" + +ms@0.7.1: + version "0.7.1" + resolved "https://registry.yarnpkg.com/ms/-/ms-0.7.1.tgz#9cd13c03adbff25b65effde7ce864ee952017098" + +once@^1.3.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1" + dependencies: + wrappy "1" + +path-is-absolute@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f" + +samsam@1.1.2, samsam@~1.1: + version "1.1.2" + resolved "https://registry.yarnpkg.com/samsam/-/samsam-1.1.2.tgz#bec11fdc83a9fda063401210e40176c3024d1567" + +sinon-chai@^2.8.0: + version "2.8.0" + resolved "https://registry.yarnpkg.com/sinon-chai/-/sinon-chai-2.8.0.tgz#432a9bbfd51a6fc00798f4d2526a829c060687ac" + +sinon@^1.17.7: + version "1.17.7" + resolved "https://registry.yarnpkg.com/sinon/-/sinon-1.17.7.tgz#4542a4f49ba0c45c05eb2e9dd9d203e2b8efe0bf" + dependencies: + formatio "1.1.1" + lolex "1.3.2" + samsam "1.1.2" + util ">=0.10.3 <1" + +supports-color@3.1.2: + version "3.1.2" + resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-3.1.2.tgz#72a262894d9d408b956ca05ff37b2ed8a6e2a2d5" + dependencies: + has-flag "^1.0.0" + +type-detect@0.1.1: + version "0.1.1" + resolved "https://registry.yarnpkg.com/type-detect/-/type-detect-0.1.1.tgz#0ba5ec2a885640e470ea4e8505971900dac58822" + +type-detect@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/type-detect/-/type-detect-1.0.0.tgz#762217cc06db258ec48908a1298e8b95121e8ea2" + +"util@>=0.10.3 <1": + version "0.10.3" + resolved "https://registry.yarnpkg.com/util/-/util-0.10.3.tgz#7afb1afe50805246489e3db7fe0ed379336ac0f9" + dependencies: + inherits "2.0.1" + +wrappy@1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f" From 91d08f25cdc6768a79c5b5c30481afd6dc75128a Mon Sep 17 00:00:00 2001 From: Stephan van Diepen Date: Fri, 10 Mar 2017 16:20:05 +0100 Subject: [PATCH 469/860] Use root package.json for app specs --- package.json | 7 +- test/app/convert-exjs | 4 +- test/app/package.json | 19 --- test/app/yarn.lock | 261 ------------------------------------------ yarn.lock | 37 ++++++ 5 files changed, 45 insertions(+), 283 deletions(-) delete mode 100644 test/app/package.json delete mode 100644 test/app/yarn.lock diff --git a/package.json b/package.json index 38b4b280..1a5d82c4 100644 --- a/package.json +++ b/package.json @@ -11,7 +11,8 @@ "lint:fix": "eslint src/javascript/lib/**/*.js src/javascript/tests/**/*.js --fix", "build": "rollup -c rollup.config.js", "clean": "rm -rf priv/build", - "test": "mocha src/javascript/tests --recursive --compilers js:babel-core/register" + "test": "mocha src/javascript/tests --recursive --compilers js:babel-core/register", + "test-app": "./test/app/convert-exjs && NODE_ENV=test mocha 'test/app/spec/*.spec.js'" }, "repository": { "type": "git", @@ -42,6 +43,8 @@ "rollup": "^0.41.4", "rollup-plugin-babel": "^2.7.1", "rollup-plugin-node-resolve": "^2.0.0", - "rollup-plugin-uglify": "^1.0.1" + "rollup-plugin-uglify": "^1.0.1", + "sinon": "^1.17.7", + "sinon-chai": "^2.8.0" } } diff --git a/test/app/convert-exjs b/test/app/convert-exjs index dc457929..00bd400b 100755 --- a/test/app/convert-exjs +++ b/test/app/convert-exjs @@ -1,3 +1,5 @@ -cd ../../ +BASEDIR=$(dirname "$0") + +cd "$BASEDIR/../../" mix elixirscript test/app/src/ -f common -o test/app/build/ diff --git a/test/app/package.json b/test/app/package.json deleted file mode 100644 index ca322ce4..00000000 --- a/test/app/package.json +++ /dev/null @@ -1,19 +0,0 @@ -{ - "name": "elixirscript-js-app", - "version": "1.0.0", - "description": "", - "main": "index.js", - "scripts": { - "test": "npm run test-unit", - "test-unit": "./convert-exjs && NODE_ENV=test mocha --require co-mocha -R spec --ui bdd 'spec/*.spec.js'" - }, - "author": "", - "license": "ISC", - "devDependencies": { - "chai": "^3.5.0", - "co-mocha": "^1.2.0", - "mocha": "^3.2.0", - "sinon": "^1.17.7", - "sinon-chai": "^2.8.0" - } -} diff --git a/test/app/yarn.lock b/test/app/yarn.lock deleted file mode 100644 index cb4ea46c..00000000 --- a/test/app/yarn.lock +++ /dev/null @@ -1,261 +0,0 @@ -# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. -# yarn lockfile v1 - - -assertion-error@^1.0.1: - version "1.0.2" - resolved "https://registry.yarnpkg.com/assertion-error/-/assertion-error-1.0.2.tgz#13ca515d86206da0bac66e834dd397d87581094c" - -balanced-match@^0.4.1: - version "0.4.2" - resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-0.4.2.tgz#cb3f3e3c732dc0f01ee70b403f302e61d7709838" - -brace-expansion@^1.0.0: - version "1.1.6" - resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.6.tgz#7197d7eaa9b87e648390ea61fc66c84427420df9" - dependencies: - balanced-match "^0.4.1" - concat-map "0.0.1" - -browser-stdout@1.3.0: - version "1.3.0" - resolved "https://registry.yarnpkg.com/browser-stdout/-/browser-stdout-1.3.0.tgz#f351d32969d32fa5d7a5567154263d928ae3bd1f" - -chai@^3.5.0: - version "3.5.0" - resolved "https://registry.yarnpkg.com/chai/-/chai-3.5.0.tgz#4d02637b067fe958bdbfdd3a40ec56fef7373247" - dependencies: - assertion-error "^1.0.1" - deep-eql "^0.1.3" - type-detect "^1.0.0" - -co-mocha@^1.2.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/co-mocha/-/co-mocha-1.2.0.tgz#d9be35a2a2d16f4b1b0e83f6973401ca4b6660af" - dependencies: - co "^4.0.0" - is-generator "^1.0.1" - -co@^4.0.0: - version "4.6.0" - resolved "https://registry.yarnpkg.com/co/-/co-4.6.0.tgz#6ea6bdf3d853ae54ccb8e47bfa0bf3f9031fb184" - -commander@2.9.0: - version "2.9.0" - resolved "https://registry.yarnpkg.com/commander/-/commander-2.9.0.tgz#9c99094176e12240cb22d6c5146098400fe0f7d4" - dependencies: - graceful-readlink ">= 1.0.0" - -concat-map@0.0.1: - version "0.0.1" - resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b" - -debug@2.2.0: - version "2.2.0" - resolved "https://registry.yarnpkg.com/debug/-/debug-2.2.0.tgz#f87057e995b1a1f6ae6a4960664137bc56f039da" - dependencies: - ms "0.7.1" - -deep-eql@^0.1.3: - version "0.1.3" - resolved "https://registry.yarnpkg.com/deep-eql/-/deep-eql-0.1.3.tgz#ef558acab8de25206cd713906d74e56930eb69f2" - dependencies: - type-detect "0.1.1" - -diff@1.4.0: - version "1.4.0" - resolved "https://registry.yarnpkg.com/diff/-/diff-1.4.0.tgz#7f28d2eb9ee7b15a97efd89ce63dcfdaa3ccbabf" - -escape-string-regexp@1.0.5: - version "1.0.5" - resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4" - -formatio@1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/formatio/-/formatio-1.1.1.tgz#5ed3ccd636551097383465d996199100e86161e9" - dependencies: - samsam "~1.1" - -fs.realpath@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f" - -glob@7.0.5: - version "7.0.5" - resolved "https://registry.yarnpkg.com/glob/-/glob-7.0.5.tgz#b4202a69099bbb4d292a7c1b95b6682b67ebdc95" - dependencies: - fs.realpath "^1.0.0" - inflight "^1.0.4" - inherits "2" - minimatch "^3.0.2" - once "^1.3.0" - path-is-absolute "^1.0.0" - -"graceful-readlink@>= 1.0.0": - version "1.0.1" - resolved "https://registry.yarnpkg.com/graceful-readlink/-/graceful-readlink-1.0.1.tgz#4cafad76bc62f02fa039b2f94e9a3dd3a391a725" - -growl@1.9.2: - version "1.9.2" - resolved "https://registry.yarnpkg.com/growl/-/growl-1.9.2.tgz#0ea7743715db8d8de2c5ede1775e1b45ac85c02f" - -has-flag@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-1.0.0.tgz#9d9e793165ce017a00f00418c43f942a7b1d11fa" - -inflight@^1.0.4: - version "1.0.6" - resolved "https://registry.yarnpkg.com/inflight/-/inflight-1.0.6.tgz#49bd6331d7d02d0c09bc910a1075ba8165b56df9" - dependencies: - once "^1.3.0" - wrappy "1" - -inherits@2, inherits@2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.1.tgz#b17d08d326b4423e568eff719f91b0b1cbdf69f1" - -is-generator@^1.0.1: - version "1.0.3" - resolved "https://registry.yarnpkg.com/is-generator/-/is-generator-1.0.3.tgz#c14c21057ed36e328db80347966c693f886389f3" - -json3@3.3.2: - version "3.3.2" - resolved "https://registry.yarnpkg.com/json3/-/json3-3.3.2.tgz#3c0434743df93e2f5c42aee7b19bcb483575f4e1" - -lodash._baseassign@^3.0.0: - version "3.2.0" - resolved "https://registry.yarnpkg.com/lodash._baseassign/-/lodash._baseassign-3.2.0.tgz#8c38a099500f215ad09e59f1722fd0c52bfe0a4e" - dependencies: - lodash._basecopy "^3.0.0" - lodash.keys "^3.0.0" - -lodash._basecopy@^3.0.0: - version "3.0.1" - resolved "https://registry.yarnpkg.com/lodash._basecopy/-/lodash._basecopy-3.0.1.tgz#8da0e6a876cf344c0ad8a54882111dd3c5c7ca36" - -lodash._basecreate@^3.0.0: - version "3.0.3" - resolved "https://registry.yarnpkg.com/lodash._basecreate/-/lodash._basecreate-3.0.3.tgz#1bc661614daa7fc311b7d03bf16806a0213cf821" - -lodash._getnative@^3.0.0: - version "3.9.1" - resolved "https://registry.yarnpkg.com/lodash._getnative/-/lodash._getnative-3.9.1.tgz#570bc7dede46d61cdcde687d65d3eecbaa3aaff5" - -lodash._isiterateecall@^3.0.0: - version "3.0.9" - resolved "https://registry.yarnpkg.com/lodash._isiterateecall/-/lodash._isiterateecall-3.0.9.tgz#5203ad7ba425fae842460e696db9cf3e6aac057c" - -lodash.create@3.1.1: - version "3.1.1" - resolved "https://registry.yarnpkg.com/lodash.create/-/lodash.create-3.1.1.tgz#d7f2849f0dbda7e04682bb8cd72ab022461debe7" - dependencies: - lodash._baseassign "^3.0.0" - lodash._basecreate "^3.0.0" - lodash._isiterateecall "^3.0.0" - -lodash.isarguments@^3.0.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/lodash.isarguments/-/lodash.isarguments-3.1.0.tgz#2f573d85c6a24289ff00663b491c1d338ff3458a" - -lodash.isarray@^3.0.0: - version "3.0.4" - resolved "https://registry.yarnpkg.com/lodash.isarray/-/lodash.isarray-3.0.4.tgz#79e4eb88c36a8122af86f844aa9bcd851b5fbb55" - -lodash.keys@^3.0.0: - version "3.1.2" - resolved "https://registry.yarnpkg.com/lodash.keys/-/lodash.keys-3.1.2.tgz#4dbc0472b156be50a0b286855d1bd0b0c656098a" - dependencies: - lodash._getnative "^3.0.0" - lodash.isarguments "^3.0.0" - lodash.isarray "^3.0.0" - -lolex@1.3.2: - version "1.3.2" - resolved "https://registry.yarnpkg.com/lolex/-/lolex-1.3.2.tgz#7c3da62ffcb30f0f5a80a2566ca24e45d8a01f31" - -minimatch@^3.0.2: - version "3.0.3" - resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.0.3.tgz#2a4e4090b96b2db06a9d7df01055a62a77c9b774" - dependencies: - brace-expansion "^1.0.0" - -minimist@0.0.8: - version "0.0.8" - resolved "https://registry.yarnpkg.com/minimist/-/minimist-0.0.8.tgz#857fcabfc3397d2625b8228262e86aa7a011b05d" - -mkdirp@0.5.1: - version "0.5.1" - resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.5.1.tgz#30057438eac6cf7f8c4767f38648d6697d75c903" - dependencies: - minimist "0.0.8" - -mocha@^3.2.0: - version "3.2.0" - resolved "https://registry.yarnpkg.com/mocha/-/mocha-3.2.0.tgz#7dc4f45e5088075171a68896814e6ae9eb7a85e3" - dependencies: - browser-stdout "1.3.0" - commander "2.9.0" - debug "2.2.0" - diff "1.4.0" - escape-string-regexp "1.0.5" - glob "7.0.5" - growl "1.9.2" - json3 "3.3.2" - lodash.create "3.1.1" - mkdirp "0.5.1" - supports-color "3.1.2" - -ms@0.7.1: - version "0.7.1" - resolved "https://registry.yarnpkg.com/ms/-/ms-0.7.1.tgz#9cd13c03adbff25b65effde7ce864ee952017098" - -once@^1.3.0: - version "1.4.0" - resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1" - dependencies: - wrappy "1" - -path-is-absolute@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f" - -samsam@1.1.2, samsam@~1.1: - version "1.1.2" - resolved "https://registry.yarnpkg.com/samsam/-/samsam-1.1.2.tgz#bec11fdc83a9fda063401210e40176c3024d1567" - -sinon-chai@^2.8.0: - version "2.8.0" - resolved "https://registry.yarnpkg.com/sinon-chai/-/sinon-chai-2.8.0.tgz#432a9bbfd51a6fc00798f4d2526a829c060687ac" - -sinon@^1.17.7: - version "1.17.7" - resolved "https://registry.yarnpkg.com/sinon/-/sinon-1.17.7.tgz#4542a4f49ba0c45c05eb2e9dd9d203e2b8efe0bf" - dependencies: - formatio "1.1.1" - lolex "1.3.2" - samsam "1.1.2" - util ">=0.10.3 <1" - -supports-color@3.1.2: - version "3.1.2" - resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-3.1.2.tgz#72a262894d9d408b956ca05ff37b2ed8a6e2a2d5" - dependencies: - has-flag "^1.0.0" - -type-detect@0.1.1: - version "0.1.1" - resolved "https://registry.yarnpkg.com/type-detect/-/type-detect-0.1.1.tgz#0ba5ec2a885640e470ea4e8505971900dac58822" - -type-detect@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/type-detect/-/type-detect-1.0.0.tgz#762217cc06db258ec48908a1298e8b95121e8ea2" - -"util@>=0.10.3 <1": - version "0.10.3" - resolved "https://registry.yarnpkg.com/util/-/util-0.10.3.tgz#7afb1afe50805246489e3db7fe0ed379336ac0f9" - dependencies: - inherits "2.0.1" - -wrappy@1: - version "1.0.2" - resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f" diff --git a/yarn.lock b/yarn.lock index 57960d44..dd23136f 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1384,6 +1384,12 @@ for-own@^0.1.4: dependencies: for-in "^0.1.5" +formatio@1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/formatio/-/formatio-1.1.1.tgz#5ed3ccd636551097383465d996199100e86161e9" + dependencies: + samsam "~1.1" + fs-exists-sync@^0.1.0: version "0.1.0" resolved "https://registry.yarnpkg.com/fs-exists-sync/-/fs-exists-sync-0.1.0.tgz#982d6893af918e72d08dec9e8673ff2b5a8d6add" @@ -1673,6 +1679,10 @@ inherits@2, inherits@^2.0.1, inherits@^2.0.3, inherits@~2.0.1: version "2.0.3" resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.3.tgz#633c2c83e3da42a502f52466022480f4208261de" +inherits@2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.1.tgz#b17d08d326b4423e568eff719f91b0b1cbdf69f1" + ini@^1.3.4: version "1.3.4" resolved "https://registry.yarnpkg.com/ini/-/ini-1.3.4.tgz#0537cb79daf59b59a1a517dff706c86ec039162e" @@ -2041,6 +2051,10 @@ lodash@~1.0.1: version "1.0.2" resolved "https://registry.yarnpkg.com/lodash/-/lodash-1.0.2.tgz#8f57560c83b59fc270bd3d561b690043430e2551" +lolex@1.3.2: + version "1.3.2" + resolved "https://registry.yarnpkg.com/lolex/-/lolex-1.3.2.tgz#7c3da62ffcb30f0f5a80a2566ca24e45d8a01f31" + longest@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/longest/-/longest-1.0.1.tgz#30a0b2da38f73770e8294a0d22e6625ed77d0097" @@ -2556,6 +2570,10 @@ rx-lite@^3.1.2: version "3.1.2" resolved "https://registry.yarnpkg.com/rx-lite/-/rx-lite-3.1.2.tgz#19ce502ca572665f3b647b10939f97fd1615f102" +samsam@1.1.2, samsam@~1.1: + version "1.1.2" + resolved "https://registry.yarnpkg.com/samsam/-/samsam-1.1.2.tgz#bec11fdc83a9fda063401210e40176c3024d1567" + semver@^4.1.0: version "4.3.6" resolved "https://registry.yarnpkg.com/semver/-/semver-4.3.6.tgz#300bc6e0e86374f7ba61068b5b1ecd57fc6532da" @@ -2576,6 +2594,19 @@ sigmund@~1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/sigmund/-/sigmund-1.0.1.tgz#3ff21f198cad2175f9f3b781853fd94d0d19b590" +sinon-chai@^2.8.0: + version "2.8.0" + resolved "https://registry.yarnpkg.com/sinon-chai/-/sinon-chai-2.8.0.tgz#432a9bbfd51a6fc00798f4d2526a829c060687ac" + +sinon@^1.17.7: + version "1.17.7" + resolved "https://registry.yarnpkg.com/sinon/-/sinon-1.17.7.tgz#4542a4f49ba0c45c05eb2e9dd9d203e2b8efe0bf" + dependencies: + formatio "1.1.1" + lolex "1.3.2" + samsam "1.1.2" + util ">=0.10.3 <1" + slash@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/slash/-/slash-1.0.0.tgz#c41f2f6c39fc16d1cd17ad4b5d896114ae470d55" @@ -2795,6 +2826,12 @@ util-deprecate@~1.0.1: version "1.0.2" resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf" +"util@>=0.10.3 <1": + version "0.10.3" + resolved "https://registry.yarnpkg.com/util/-/util-0.10.3.tgz#7afb1afe50805246489e3db7fe0ed379336ac0f9" + dependencies: + inherits "2.0.1" + v8flags@^2.0.2: version "2.0.11" resolved "https://registry.yarnpkg.com/v8flags/-/v8flags-2.0.11.tgz#bca8f30f0d6d60612cc2c00641e6962d42ae6881" From 7aa13788930894e9ca982795f4aa445500756725 Mon Sep 17 00:00:00 2001 From: Stephan van Diepen Date: Fri, 10 Mar 2017 16:23:35 +0100 Subject: [PATCH 470/860] Run app specs in travis --- .travis.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 94a48916..3846cdde 100644 --- a/.travis.yml +++ b/.travis.yml @@ -16,10 +16,11 @@ script: - mix compile - mix test - npm test + - npm run test-app notifications: webhooks: urls: - https://webhooks.gitter.im/e/fbd8944d285c0696dc41 on_success: always # options: [always|never|change] default: always on_failure: always # options: [always|never|change] default: always - on_start: never # options: [always|never|change] default: always \ No newline at end of file + on_start: never # options: [always|never|change] default: always From 7704f48a8e0d098ba8e68a0bcc4afb2059f75b9b Mon Sep 17 00:00:00 2001 From: Dave Seleno Date: Fri, 10 Mar 2017 10:54:53 -0800 Subject: [PATCH 471/860] fix compiler & credo warnings for lib/elixir_script/passes/find_modules.ex --- lib/elixir_script/passes/find_modules.ex | 102 ++++++++++++----------- 1 file changed, 53 insertions(+), 49 deletions(-) diff --git a/lib/elixir_script/passes/find_modules.ex b/lib/elixir_script/passes/find_modules.ex index 0079aadb..143a77f5 100644 --- a/lib/elixir_script/passes/find_modules.ex +++ b/lib/elixir_script/passes/find_modules.ex @@ -3,6 +3,7 @@ defmodule ElixirScript.Passes.FindModules do alias ElixirScript.Translator.Utils alias ElixirScript.Translator.State + @spec execute(map, map) :: map def execute(compiler_data, opts) do data = Enum.reduce(compiler_data.data, [], fn(data, list) -> quoted = update_quoted(data.ast) @@ -53,15 +54,22 @@ defmodule ElixirScript.Passes.FindModules do { ast, state } end - defp do_module_processing({:defmodule, context1, [{:__aliases__, _, name} = the_alias, [do: body]]}, state, opts) do - { body, inner_modules } = make_inner_module_aliases(name, body) + + defp do_module_processing({:defmodule, _context1, [{:__aliases__, _, name} = the_alias, [do: body]]}, state, opts) do + { body, inner_modules } = make_inner_module_aliases(body) aliases = Enum.map(inner_modules, fn - ({:defmodule, _, [{:__aliases__, _, inner_module_name}, [do: inner_module_body]]}) -> + ({:defmodule, _, [{:__aliases__, _, inner_module_name}, [do: _inner_module_body]]}) -> { :alias, [], [{:__aliases__, [alias: false], name ++ inner_module_name}, [as: {:__aliases__, [alias: false], inner_module_name }] ] } end) - state = Enum.reduce(inner_modules, state, fn + state = do_module_processing_state(inner_modules, state, name, aliases, opts) + + [%{name: Utils.quoted_to_name(the_alias), type: :module, ast: do_module_processing_body(body, aliases, opts) }] ++ state + end + + defp do_module_processing_state(inner_modules, state, name, aliases, opts) do + Enum.reduce(inner_modules, state, fn ({:defmodule, context1, [{:__aliases__, context2, inner_module_name}, [do: inner_module_body]]}, state) -> module_name = Utils.quoted_to_name({:__aliases__, [], tl(name) ++ inner_module_name}) @@ -73,39 +81,36 @@ defmodule ElixirScript.Passes.FindModules do {:defmodule, context1, [{:__aliases__, context2, name ++ inner_module_name}, [do: add_aliases_to_body(inner_module_body, this_module_aliases)]]}, state, opts) end) + end - body = case body do - {:__block__, context, list } -> - list = Enum.map(list, fn - {:use, _, [module, _] } = using -> - {:use, handle_use_expression(using, module, opts) } - {:use, _, [module] } = using -> - {:use, handle_use_expression(using, module, opts) } - ast -> - {:expanded, ast} - end) - |> Enum.reduce([], fn - {:use, ast}, state -> - case ast do - {:__block__, _, list} -> - state ++ list - _ -> - state ++ [ast] - end - - {:expanded, ast}, state -> - state ++ [ast] - end) - - {:__block__, context, list} - - _ -> - body - end - - body = add_aliases_to_body(body, aliases) - - [%{name: Utils.quoted_to_name(the_alias), type: :module, ast: body }] ++ state + defp do_module_processing_body(body, aliases, opts) do + body + |> case do + {:__block__, context, list } -> + list = + list + |> Enum.map(fn + {:use, _, [module, _] } = using -> + {:use, handle_use_expression(using, module, opts) } + {:use, _, [module] } = using -> + {:use, handle_use_expression(using, module, opts) } + ast -> + {:expanded, ast} + end) + |> Enum.reduce([], fn + {:use, {:__block__, _, list}}, state -> + state ++ list + {:use, ast}, state -> + state ++ [ast] + {:expanded, ast}, state -> + state ++ [ast] + end) + + {:__block__, context, list} + _ -> + body + end + |> add_aliases_to_body(aliases) end defp add_aliases_to_body(body, aliases) do @@ -117,23 +122,21 @@ defmodule ElixirScript.Passes.FindModules do end end - defp make_inner_module_aliases(name, body) do + defp make_inner_module_aliases(body) do case body do nil -> { { :__block__, [], [] }, [] } {:__block__, context, list2 } -> - { list2, inner_modules } = Enum.partition(list2, fn(x) -> - case x do - {:defmodule, _, [{:__aliases__, _, inner_module_name}, [do: inner_module_body]]} -> + { list2, inner_modules } = Enum.partition(list2, fn + {:defmodule, _, [{:__aliases__, _, _inner_module_name}, [do: _inner_module_body]]} -> false _ -> true - end end) { {:__block__, context, list2}, inner_modules } - {:defmodule, _, [{:__aliases__, context, inner_module_name}, [do: inner_module_body]]} = mod -> + {:defmodule, _, [{:__aliases__, context, _inner_module_name}, [do: _inner_module_body]]} = mod -> { {:__block__, context, [] }, [mod] } _ -> { body, [] } @@ -162,13 +165,14 @@ defmodule ElixirScript.Passes.FindModules do defp update_quoted(quoted) do Macro.prewalk(quoted, fn ({name, context, parms}) -> - context = if context[:import] == Kernel do - context = Keyword.update!(context, :import, fn(_) -> ElixirScript.Kernel end) - else - context - end - - {name, context, parms} + context = + if context[:import] == Kernel do + Keyword.update!(context, :import, fn(_) -> ElixirScript.Kernel end) + else + context + end + + {name, context, parms} (x) -> x end) From 902d36ae5ec0a096b3b484593c282ef9e4ea9317 Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Fri, 10 Mar 2017 13:50:47 -0600 Subject: [PATCH 472/860] Update .travis.yml --- .travis.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.travis.yml b/.travis.yml index 3846cdde..0ba9bfe9 100644 --- a/.travis.yml +++ b/.travis.yml @@ -14,6 +14,7 @@ script: - mix local.rebar --force - mix deps.get - mix compile + - npm run build - mix test - npm test - npm run test-app From c87dc7083929e1492807ec314f37693dc480098c Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Sat, 11 Mar 2017 19:17:49 -0600 Subject: [PATCH 473/860] Update test commands. Update Changelog --- CHANGELOG.md | 14 ++++++++++-- GettingStarted.md | 20 ++++++++--------- lib/elixir_script/passes/handle_output.ex | 2 +- .../translator/kernel/special_forms/call.ex | 22 +++++++++---------- package.json | 3 ++- test/app/convert-exjs | 5 ----- 6 files changed, 36 insertions(+), 30 deletions(-) delete mode 100755 test/app/convert-exjs diff --git a/CHANGELOG.md b/CHANGELOG.md index 1f6689ef..9a8ad0db 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,11 +9,21 @@ and this project adheres to [Semantic Versioning](http://semver.org/). ### Added - `super` - `defoverridable` +- `Elixir.load` for loading generated JavaScript modules in bundled output. +Unlike `Elixir.start`, this will only call `__load` on the module and return the functions on it + +```javascript +const exports = Elixir.load(Elixir.MyApp); +exports.hello(); +``` ### Changed - `-ex` alias is now `-e` - A filename can be specified for output +### Fixed +- Make sure mix compiler works in umbrella apps + ## [0.26.1] - 2017-02-27 ### Fixed @@ -46,7 +56,7 @@ elixirscript "app/elixirscript" -o dist --js-module React:react --js-module Reac - Now bundles all output, including the boostrap code. The exported object has Elixir modules in JavaScript namespaces that are lazily loaded when called. - To start your application import the bundle according to whichever module format was selected and + To start your application import the bundle according to whichever module format was selected and then call start giving it the module and the initial args ```javascript @@ -67,7 +77,7 @@ elixirscript "app/elixirscript" -o dist --js-module React:react --js-module Reac - Updated elixir_script mix compiler to support compiling elixir_script paths in dependencies if dependency has mix compiler defined as well - Add `Collectable` protocol implementations - Updated `for` implementation to use `Collectable` -- `format` option. Can now specify the module format of output. +- `format` option. Can now specify the module format of output. Choices are: * `:es` (default) for ES Modules * `:umd` for UMD diff --git a/GettingStarted.md b/GettingStarted.md index edb35f79..6d57e4ed 100644 --- a/GettingStarted.md +++ b/GettingStarted.md @@ -30,9 +30,9 @@ This is the help output of elixirscript the elixir code string if passed the -e flag options: --js-module [:] A js module used in your code. ex: React:react - Multiple can be defined + Multiple can be defined -f --format [format] module format of output. options: es (default), common, umd - -o --output [path] places output at the given path. + -o --output [path] places output at the given path. Can be a directory or filename. -e --elixir read input as elixir code string --full-build informs the compiler to do a full build instead of an incremental one @@ -49,10 +49,10 @@ elixirscript also takes a path to your `.ex` files as well: If you look in the dist folder you'll see a file called `Elixir.App.js` -To start your application import the bundle according to whichever module format was selected and +To start your application import the bundle according to whichever module format was selected and then call start giving it the module and the initial args. -Ex. If you have a module like so +Ex. If you have a module like so ```elixir defmodule Example do start(type, args) do @@ -87,14 +87,14 @@ Add dependency to your deps in mix.exs: version: "0.1.0", elixir: "~> 1.0", deps: deps, - elixir_script: [ - input: "lib/elixirscript", - output: "priv/elixirscript/Elixir.App.js", + elixir_script: [ + input: "lib/elixirscript", + output: "priv/elixirscript/Elixir.App.js", format: :es, js_modules: [ {React, "react"}, {ReactDOM, "react-dom"} - ] + ] ], compilers: [:elixir_script] ++ Mix.compilers ] @@ -160,6 +160,6 @@ There is an [elixirscript frontend boilerplate project](https://github.com/elixi There is an Brunch plugin, [elixirscript-brunch](https://www.npmjs.com/package/elixirscript-brunch). -#### +#### elixirscript-loader -There is also a webpack loader, [elixirscript-loader](https://www.npmjs.com/package/elixirscript-loader). \ No newline at end of file +There is also a webpack loader, [elixirscript-loader](https://www.npmjs.com/package/elixirscript-loader). diff --git a/lib/elixir_script/passes/handle_output.ex b/lib/elixir_script/passes/handle_output.ex index a3bab884..eb956cdf 100644 --- a/lib/elixir_script/passes/handle_output.ex +++ b/lib/elixir_script/passes/handle_output.ex @@ -22,7 +22,7 @@ defmodule ElixirScript.Passes.HandleOutput do code -> code end - IO.write(concat(code)) + IO.write(concat(code)) end defp out(compiler_output, %{output: output_path, core_path: _}) do diff --git a/lib/elixir_script/translator/kernel/special_forms/call.ex b/lib/elixir_script/translator/kernel/special_forms/call.ex index 9225c00d..ca3d04eb 100644 --- a/lib/elixir_script/translator/kernel/special_forms/call.ex +++ b/lib/elixir_script/translator/kernel/special_forms/call.ex @@ -22,7 +22,7 @@ defmodule ElixirScript.Translator.Call do ) {ast, env} - end + end def make_local_function_call(function_name, params, env) do ast = JS.call_expression( @@ -42,7 +42,7 @@ defmodule ElixirScript.Translator.Call do Identifier.make_namespace_members(members), [JS.identifier("Elixir")] ), - Identifier.make_identifier(function_name) + Identifier.make_identifier(function_name) ), Enum.map(params, &Translator.translate!(&1, env)) ) @@ -52,7 +52,7 @@ defmodule ElixirScript.Translator.Call do def make_module_function_call(module_name, function_name, env) do make_module_function_call(module_name, function_name, [], env) - end + end def make_extern_function_or_property_call(module_name, function_name, env) do members = Module.split(module_name) @@ -87,7 +87,7 @@ defmodule ElixirScript.Translator.Call do ) {ast, env} - end + end def make_function_or_property_call(module_name, function_name, env) do js_ast = JS.call_expression( @@ -128,19 +128,19 @@ defmodule ElixirScript.Translator.Call do ] ) - {js_ast, env} + {js_ast, env} end def make_function_call(module_name, function_name, params, env) when is_atom(module_name) and is_atom(function_name) do js_ast = JS.call_expression( JS.member_expression( Identifier.make_identifier(module_name), - Identifier.make_identifier(function_name) + Identifier.make_identifier(function_name) ), Enum.map(params, &Translator.translate!(&1, env)) ) - {js_ast, env} + {js_ast, env} end def make_function_call({{:., _, _}, _, _} = module_name, function_name, [], env) do @@ -161,19 +161,19 @@ defmodule ElixirScript.Translator.Call do ] ) - {js_ast, env} + {js_ast, env} end def make_function_call({{:., _, _}, _, _} = module_name, function_name, params, env) do js_ast = JS.call_expression( JS.member_expression( Translator.translate!(module_name, env), - Identifier.make_identifier(function_name) + Identifier.make_identifier(function_name) ), Enum.map(params, &Translator.translate!(&1, env)) ) - {js_ast, env} + {js_ast, env} end def make_function_call(module_name, function_name, [], env) do @@ -195,7 +195,7 @@ defmodule ElixirScript.Translator.Call do ) {js_ast, env} - end + end def make_function_call(module_name, function_name, params, env) do call = JS.call_expression( diff --git a/package.json b/package.json index 1a5d82c4..fea12f0b 100644 --- a/package.json +++ b/package.json @@ -12,7 +12,8 @@ "build": "rollup -c rollup.config.js", "clean": "rm -rf priv/build", "test": "mocha src/javascript/tests --recursive --compilers js:babel-core/register", - "test-app": "./test/app/convert-exjs && NODE_ENV=test mocha 'test/app/spec/*.spec.js'" + "build:test-app": "mix elixirscript test/app/src/ -f common -o test/app/build/", + "test-app": "yarn run build:test-app && NODE_ENV=test mocha 'test/app/spec/*.spec.js'" }, "repository": { "type": "git", diff --git a/test/app/convert-exjs b/test/app/convert-exjs deleted file mode 100755 index 00bd400b..00000000 --- a/test/app/convert-exjs +++ /dev/null @@ -1,5 +0,0 @@ -BASEDIR=$(dirname "$0") - -cd "$BASEDIR/../../" - -mix elixirscript test/app/src/ -f common -o test/app/build/ From edca7ba8e12e7c940ac36cffa47cc1b41bff92fc Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Sat, 11 Mar 2017 19:19:56 -0600 Subject: [PATCH 474/860] Update travis configuration to use yarn --- .travis.yml | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/.travis.yml b/.travis.yml index 0ba9bfe9..c6facb26 100644 --- a/.travis.yml +++ b/.travis.yml @@ -8,16 +8,17 @@ env: - TRAVIS_NODE_VERSION="6" install: - rm -rf ~/.nvm && git clone https://github.com/creationix/nvm.git ~/.nvm && (cd ~/.nvm && git checkout `git describe --abbrev=0 --tags`) && source ~/.nvm/nvm.sh && nvm install $TRAVIS_NODE_VERSION - - npm install + - npm install -g yarn + - yarn script: - mix local.hex --force - mix local.rebar --force - mix deps.get - mix compile - - npm run build + - yarn build - mix test - - npm test - - npm run test-app + - yarn test + - yarn test-app notifications: webhooks: urls: From 23e2aad098789b02542ffe3a0ed6e3a21ae8f974 Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Sat, 11 Mar 2017 20:06:47 -0600 Subject: [PATCH 475/860] Add specs for atom and integer --- priv/std_lib/integer.ex | 10 ++----- test/app/spec/atom.spec.js | 14 +++++++++ test/app/spec/integer.spec.js | 53 +++++++++++++++++++++++++++++++++++ 3 files changed, 70 insertions(+), 7 deletions(-) create mode 100644 test/app/spec/atom.spec.js create mode 100644 test/app/spec/integer.spec.js diff --git a/priv/std_lib/integer.ex b/priv/std_lib/integer.ex index abfee5a2..9aaa64d0 100644 --- a/priv/std_lib/integer.ex +++ b/priv/std_lib/integer.ex @@ -8,16 +8,12 @@ defmodule ElixirScript.Integer do rem(number, 2) != 0 end - def to_char_list(number) do - to_char_list(number, 10) - end - - def to_char_list(number, base) do + def to_char_list(number, base \\ 10) do number.toString(base).split('') end - def parse(bin) do - result = Bootstrap.Core.Functions.get_global().parseInt(bin) + def parse(bin, base \\ 10) do + result = Bootstrap.Core.Functions.get_global().parseInt(bin, base) if Bootstrap.Core.Functions.get_global().isNaN(result) do :error diff --git a/test/app/spec/atom.spec.js b/test/app/spec/atom.spec.js new file mode 100644 index 00000000..89e18673 --- /dev/null +++ b/test/app/spec/atom.spec.js @@ -0,0 +1,14 @@ +const expect = require('chai').expect; +const Elixir = require('../build/Elixir.App'); + +describe('Atom', () => { + it('to_string/1', () => { + const exports = Elixir.load(Elixir.ElixirScript.Atom); + expect(exports.to_string(Symbol.for('héllo'))).to.eq('héllo'); + }); + + it('to_charlist/1', () => { + const exports = Elixir.load(Elixir.ElixirScript.Atom); + expect(exports.to_string(Symbol.for('héllo'))).to.eq('héllo'); + }); +}); diff --git a/test/app/spec/integer.spec.js b/test/app/spec/integer.spec.js new file mode 100644 index 00000000..523d0aca --- /dev/null +++ b/test/app/spec/integer.spec.js @@ -0,0 +1,53 @@ +const expect = require('chai').expect; +const Elixir = require('../build/Elixir.App'); + +describe('Integer', () => { + it('is_odd/1', () => { + const Integer = Elixir.load(Elixir.ElixirScript.Integer); + + expect(Integer.is_odd(0)).to.eq(false); + expect(Integer.is_odd(1)).to.eq(true); + expect(Integer.is_odd(2)).to.eq(false); + expect(Integer.is_odd(3)).to.eq(true); + expect(Integer.is_odd(-1)).to.eq(true); + expect(Integer.is_odd(-2)).to.eq(false); + expect(Integer.is_odd(-3)).to.eq(true); + }); + + it('is_even/1', () => { + const Integer = Elixir.load(Elixir.ElixirScript.Integer); + + expect(Integer.is_even(0)).to.eq(true); + expect(Integer.is_even(1)).to.eq(false); + expect(Integer.is_even(2)).to.eq(true); + expect(Integer.is_even(3)).to.eq(false); + expect(Integer.is_even(-1)).to.eq(false); + expect(Integer.is_even(-2)).to.eq(true); + expect(Integer.is_even(-3)).to.eq(false); + }); + + it('parse/2', () => { + const Integer = Elixir.load(Elixir.ElixirScript.Integer); + expect(Integer.parse('12').values).to.eql([12, '']); + expect(Integer.parse('012').values).to.eql([12, '']); + expect(Integer.parse('+12').values).to.eql([12, '']); + expect(Integer.parse('-12').values).to.eql([-12, '']); + expect(Integer.parse('123456789').values).to.eql([123456789, '']); + expect(Integer.parse('12.5').values).to.eql([12, '.5']); + expect(Integer.parse('7.5e-3').values).to.eql([7, '.5e-3']); + // expect(Integer.parse('12x').values).to.eql([12, 'x']); + expect(Integer.parse('++1')).to.eql(Symbol.for('error')); + expect(Integer.parse('--1')).to.eql(Symbol.for('error')); + expect(Integer.parse('+-1')).to.eql(Symbol.for('error')); + expect(Integer.parse('three')).to.eql(Symbol.for('error')); + + expect(Integer.parse('12', 10).values).to.eql([12, '']); + expect(Integer.parse('-12', 12).values).to.eql([-14, '']); + expect(Integer.parse('12345678', 9).values).to.eql([6053444, '']); + expect(Integer.parse('3.14', 4).values).to.eql([3, '.14']); + expect(Integer.parse('64eb', 16).values).to.eql([25835, '']); + // expect(Integer.parse('64eb', 10).values).to.eql([64, 'eb']); + expect(Integer.parse('10', 2).values).to.eql([2, '']); + expect(Integer.parse('++4', 10)).to.eql(Symbol.for('error')); + }); +}); From 8728ab99c53ef00bac16af8f38c83012ba6dbff7 Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Sat, 11 Mar 2017 20:55:29 -0600 Subject: [PATCH 476/860] Javascript formatting --- gulpfile.js | 16 +++++++--------- rollup.config.js | 14 +++++++------- 2 files changed, 14 insertions(+), 16 deletions(-) diff --git a/gulpfile.js b/gulpfile.js index 8b68b656..ac7ed7db 100644 --- a/gulpfile.js +++ b/gulpfile.js @@ -1,13 +1,11 @@ -var gulp = require('gulp'); -var babel = require('gulp-babel'); -var sourcemaps = require('gulp-sourcemaps'); +const gulp = require('gulp'); +const babel = require('gulp-babel'); +const sourcemaps = require('gulp-sourcemaps'); -var path = './src/javascript'; +const path = './src/javascript'; -gulp.task('build', function() { - return gulp.src([path + '/**/*.js', '!' + path + '/dist_build/**/*.js', '!' + path + '/tests/**/*.js']) +gulp.task('build', () => gulp.src([`${path}/**/*.js`, `!${path}/dist_build/**/*.js`, `!${path}/tests/**/*.js`]) .pipe(sourcemaps.init()) - .pipe(babel({ presets: ["react", "stage-0"], babelrc: false })) + .pipe(babel({ presets: ['react', 'stage-0'], babelrc: false })) .pipe(sourcemaps.write()) - .pipe(gulp.dest('./src/elixirscript')); -}); + .pipe(gulp.dest('./src/elixirscript'))); diff --git a/rollup.config.js b/rollup.config.js index 6e2312d3..1f30fafa 100644 --- a/rollup.config.js +++ b/rollup.config.js @@ -1,14 +1,14 @@ -import nodeResolve from "rollup-plugin-node-resolve"; -import babel from "rollup-plugin-babel"; +import nodeResolve from 'rollup-plugin-node-resolve'; +import babel from 'rollup-plugin-babel'; export default { - entry: "src/javascript/elixir.js", - moduleName: "Bootstrap", + entry: 'src/javascript/elixir.js', + moduleName: 'Bootstrap', plugins: [ nodeResolve({ jsnext: true }), babel({ - babelrc: false - }) + babelrc: false, + }), ], - targets: [{ dest: "priv/build/iife/Elixir.Bootstrap.js", format: "iife" }] + targets: [{ dest: 'priv/build/iife/Elixir.Bootstrap.js', format: 'iife' }], }; From 5d2fda04c84860f6b2c80106741672954fc1c994 Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Sun, 12 Mar 2017 20:57:11 -0500 Subject: [PATCH 477/860] Add more tests for standard lib --- package.json | 2 +- priv/std_lib/tuple.ex | 12 ++++++------ test/app/spec/tuple.spec.js | 29 +++++++++++++++++++++++++++++ 3 files changed, 36 insertions(+), 7 deletions(-) create mode 100644 test/app/spec/tuple.spec.js diff --git a/package.json b/package.json index fea12f0b..10150ccb 100644 --- a/package.json +++ b/package.json @@ -13,7 +13,7 @@ "clean": "rm -rf priv/build", "test": "mocha src/javascript/tests --recursive --compilers js:babel-core/register", "build:test-app": "mix elixirscript test/app/src/ -f common -o test/app/build/", - "test-app": "yarn run build:test-app && NODE_ENV=test mocha 'test/app/spec/*.spec.js'" + "test-app": "yarn run build:test-app && NODE_ENV=test mocha 'test/app/spec/*.spec.js' --compilers js:babel-core/register" }, "repository": { "type": "git", diff --git a/priv/std_lib/tuple.ex b/priv/std_lib/tuple.ex index bed5e717..6751dfa6 100644 --- a/priv/std_lib/tuple.ex +++ b/priv/std_lib/tuple.ex @@ -1,5 +1,5 @@ defmodule ElixirScript.Tuple do - @moduledoc false + @moduledoc false require JS def duplicate(data, size) do @@ -15,7 +15,7 @@ defmodule ElixirScript.Tuple do end def to_list(tuple) do - tuple["value"] + tuple.values end def insert_at(tuple, index, value) do @@ -26,14 +26,14 @@ defmodule ElixirScript.Tuple do if current_index == length(tuple) do list else - list = case index == current_index do + new_list = case index == current_index do true -> list ++ [value, tuple.get(current_index)] false -> list ++ [tuple.get(current_index)] end - do_insert_at(tuple, index, value, current_index + 1, list) + do_insert_at(tuple, index, value, current_index + 1, new_list) end end @@ -45,14 +45,14 @@ defmodule ElixirScript.Tuple do if current_index == length(tuple) do list else - list = case index == current_index do + new_list = case index == current_index do true -> list false -> list ++ [tuple.get(current_index)] end - do_delete_at(tuple, index, current_index + 1, list) + do_delete_at(tuple, index, current_index + 1, new_list) end end diff --git a/test/app/spec/tuple.spec.js b/test/app/spec/tuple.spec.js new file mode 100644 index 00000000..c139aecd --- /dev/null +++ b/test/app/spec/tuple.spec.js @@ -0,0 +1,29 @@ +const expect = require('chai').expect; +const Elixir = require('../build/Elixir.App'); +const Tuple = require('../../../src/javascript/lib/core').default.Tuple; + +describe('Tuple', () => { + it('duplicate/2', () => { + const TupleModule = Elixir.load(Elixir.ElixirScript.Tuple); + expect(TupleModule.duplicate(Symbol.for('foo'), 0).values).to.eql([]); + expect(TupleModule.duplicate(Symbol.for('foo'), 3).values).to.eql([Symbol.for('foo'), Symbol.for('foo'), Symbol.for('foo')]); + }); + + it('insert_at/3', () => { + const TupleModule = Elixir.load(Elixir.ElixirScript.Tuple); + const t = new Tuple(Symbol.for('bar'), Symbol.for('baz')); + expect(TupleModule.insert_at(t, 0, Symbol.for('foo')).values).to.eql([Symbol.for('foo'), Symbol.for('bar'), Symbol.for('baz')]); + }); + + it('append/2', () => { + const TupleModule = Elixir.load(Elixir.ElixirScript.Tuple); + const t = new Tuple(Symbol.for('foo'), Symbol.for('bar')); + expect(TupleModule.append(t, Symbol.for('baz')).values).to.eql([Symbol.for('foo'), Symbol.for('bar'), Symbol.for('baz')]); + }); + + it('delete_at/2', () => { + const TupleModule = Elixir.load(Elixir.ElixirScript.Tuple); + const t = new Tuple(Symbol.for('foo'), Symbol.for('bar'), Symbol.for('baz')); + expect(TupleModule.delete_at(t, 0).values).to.eql([Symbol.for('bar'), Symbol.for('baz')]); + }); +}); From 74fc2432635ed610c6c8972ac98acc77c08cc715 Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Mon, 13 Mar 2017 21:15:45 -0500 Subject: [PATCH 478/860] Add IO module --- lib/elixir_script/translator/state.ex | 4 ++-- priv/std_lib/io.ex | 22 ++++++++++++++++++++++ test/translator/try_test.exs | 22 +++++++++++----------- 3 files changed, 35 insertions(+), 13 deletions(-) create mode 100644 priv/std_lib/io.ex diff --git a/lib/elixir_script/translator/state.ex b/lib/elixir_script/translator/state.ex index 85aec85c..bcc7b7ff 100644 --- a/lib/elixir_script/translator/state.ex +++ b/lib/elixir_script/translator/state.ex @@ -38,6 +38,7 @@ defmodule ElixirScript.Translator.State do |> Map.put(List, ElixirScript.List) |> Map.put(Process, ElixirScript.Process) |> Map.put(Regex, ElixirScript.Regex) + |> Map.put(IO, ElixirScript.IO) end def set_module_data(pid, module_data) do @@ -135,7 +136,7 @@ defmodule ElixirScript.Translator.State do def list_module_references(pid) do Agent.get(pid, fn(state) -> - Enum.map(state.modules, fn {name, module} -> + Enum.map(state.modules, fn {name, module} -> {name, Map.get(module, :refs, [])} end) end) @@ -157,4 +158,3 @@ defmodule ElixirScript.Translator.State do Agent.stop(pid) end end - diff --git a/priv/std_lib/io.ex b/priv/std_lib/io.ex new file mode 100644 index 00000000..f7dff45b --- /dev/null +++ b/priv/std_lib/io.ex @@ -0,0 +1,22 @@ +defmodule ElixirScript.IO do + + def inspect(item, opts \\ []) do + :console.log(item) + item + end + + def puts(device \\ :stdio, item) when is_binary(item) do + case device do + :stdio -> + :console.log(item) + :stderr -> + :console.warn(item) + end + end + + def warn(message) when is_binary(message) do + :console.warn("warning: #{message}") + :console.trace() + end + +end diff --git a/test/translator/try_test.exs b/test/translator/try_test.exs index 72c24681..a53ec60c 100644 --- a/test/translator/try_test.exs +++ b/test/translator/try_test.exs @@ -16,7 +16,7 @@ defmodule ElixirScript.Translator.Try.Test do Bootstrap.Core.SpecialForms._try(function() { return 1; }, Bootstrap.Core.Patterns.defmatch(Bootstrap.Core.Patterns.clause([Bootstrap.Core.Patterns.type(ArgumentError, {})], function() { - return IO.puts('Invalid argument given'); + return Elixir.ElixirScript.IO.__load(Elixir).puts('Invalid argument given'); })), null, null, null) """ @@ -38,7 +38,7 @@ defmodule ElixirScript.Translator.Try.Test do Bootstrap.Core.SpecialForms._try(function() { return 1; }, Bootstrap.Core.Patterns.defmatch(Bootstrap.Core.Patterns.clause([Bootstrap.Core.Patterns.type(ArgumentError, {})], function() { - return IO.puts('Invalid argument given'); + return Elixir.ElixirScript.IO.__load(Elixir).puts('Invalid argument given'); })), null, null, null) """ @@ -60,7 +60,7 @@ defmodule ElixirScript.Translator.Try.Test do Bootstrap.Core.SpecialForms._try(function() { return 1; },Bootstrap.Core.Patterns.defmatch(Bootstrap.Core.Patterns.clause([Bootstrap.Core.Patterns.variable()],function(x) { - return IO.puts('Invalid argument given'); + return Elixir.ElixirScript.IO.__load(Elixir).puts('Invalid argument given'); },function(x) { return Bootstrap.Core.Functions.contains(x,Object.freeze([ArgumentError.create(Object.freeze({}))])); })),null,null,null) @@ -84,7 +84,7 @@ defmodule ElixirScript.Translator.Try.Test do Bootstrap.Core.SpecialForms._try(function() { return 1; },Bootstrap.Core.Patterns.defmatch(Bootstrap.Core.Patterns.clause([Bootstrap.Core.Patterns.variable()],function(x) { - return IO.puts('Invalid argument given'); + return Elixir.ElixirScript.IO.__load(Elixir).puts('Invalid argument given'); })),null,null,null) """ @@ -109,9 +109,9 @@ defmodule ElixirScript.Translator.Try.Test do Bootstrap.Core.SpecialForms._try(function() { return 1; }, Bootstrap.Core.Patterns.defmatch(Bootstrap.Core.Patterns.clause([Bootstrap.Core.Patterns.type(ArgumentError, {})], function() { - return IO.puts('ArgumentError'); + return Elixir.ElixirScript.IO.__load(Elixir).puts('ArgumentError'); }), Bootstrap.Core.Patterns.clause([Bootstrap.Core.Patterns.variable()], function(x) { - return IO.puts('x'); + return Elixir.ElixirScript.IO.__load(Elixir).puts('x'); })), null, null, null) """ @@ -135,9 +135,9 @@ defmodule ElixirScript.Translator.Try.Test do Bootstrap.Core.SpecialForms._try(function() { return 1; }, Bootstrap.Core.Patterns.defmatch(Bootstrap.Core.Patterns.clause([Bootstrap.Core.Patterns.type(ArgumentError, {})], function() { - return IO.puts('Invalid argument given'); + return Elixir.ElixirScript.IO.__load(Elixir).puts('Invalid argument given'); })), null, null, function() { - return IO.puts('This is printed regardless if it failed or succeed'); + return Elixir.ElixirScript.IO.__load(Elixir).puts('This is printed regardless if it failed or succeed'); }) """ @@ -158,7 +158,7 @@ defmodule ElixirScript.Translator.Try.Test do Bootstrap.Core.SpecialForms._try(function() { return 1; },null,null,null,function() { - return IO.puts('This is printed regardless if it failed or succeed'); + return Elixir.ElixirScript.IO.__load(Elixir).puts('This is printed regardless if it failed or succeed'); }) """ @@ -210,9 +210,9 @@ defmodule ElixirScript.Translator.Try.Test do Bootstrap.Core.SpecialForms._try(function() { return 1; }, Bootstrap.Core.Patterns.defmatch(Bootstrap.Core.Patterns.clause([Bootstrap.Core.Patterns.type(ArgumentError, {})], function() { - return IO.puts('Invalid argument given'); + return Elixir.ElixirScript.IO.__load(Elixir).puts('Invalid argument given'); })), Bootstrap.Core.Patterns.defmatch(Bootstrap.Core.Patterns.clause([Symbol.for('throw'), Symbol.for('Error')], function() { - return IO.puts('caught error'); + return Elixir.ElixirScript.IO.__load(Elixir).puts('caught error'); })), null, null) """ From 0c060a0321612ab7215e0dc066f322b55a3cb2b5 Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Mon, 13 Mar 2017 21:21:47 -0500 Subject: [PATCH 479/860] Remove unneeded whitespace --- lib/elixir_script/passes/find_functions.ex | 28 +++++++++++----------- lib/elixir_script/passes/load_modules.ex | 10 ++++---- 2 files changed, 19 insertions(+), 19 deletions(-) diff --git a/lib/elixir_script/passes/find_functions.ex b/lib/elixir_script/passes/find_functions.ex index f78e2d38..0d627984 100644 --- a/lib/elixir_script/passes/find_functions.ex +++ b/lib/elixir_script/passes/find_functions.ex @@ -1,16 +1,16 @@ defmodule ElixirScript.Passes.FindFunctions do - @moduledoc false + @moduledoc false @function_types [:def, :defp, :defgen, :defgenp, :defmacro, :defmacrop] def execute(data, _) do new_data = Enum.map(data.data, fn { module_name, module_data } -> %{ - def: functions, - defp: private_functions, - defgen: generators, - defgenp: private_generators, - defmacro: macros, + def: functions, + defp: private_functions, + defgen: generators, + defgenp: private_generators, + defmacro: macros, defmacrop: private_macros, defdelegate: delegates } = get_functions_from_module(module_data.ast) @@ -54,7 +54,7 @@ defmodule ElixirScript.Passes.FindFunctions do ({:defdelegate, _, [{name, _, params}], _}, state) -> arity = length(params) - add_function_to_map(state, :defdelegate, name, arity) + add_function_to_map(state, :defdelegate, name, arity) _, state -> state @@ -63,12 +63,12 @@ defmodule ElixirScript.Passes.FindFunctions do end defp new_function_map() do - %{ - def: Keyword.new, - defp: Keyword.new, - defgen: Keyword.new, - defgenp: Keyword.new, - defmacro: Keyword.new, + %{ + def: Keyword.new, + defp: Keyword.new, + defgen: Keyword.new, + defgenp: Keyword.new, + defmacro: Keyword.new, defmacrop: Keyword.new, defdelegate: Keyword.new } @@ -89,4 +89,4 @@ defmodule ElixirScript.Passes.FindFunctions do end -end \ No newline at end of file +end diff --git a/lib/elixir_script/passes/load_modules.ex b/lib/elixir_script/passes/load_modules.ex index 5e57fe76..85e2edb2 100644 --- a/lib/elixir_script/passes/load_modules.ex +++ b/lib/elixir_script/passes/load_modules.ex @@ -1,18 +1,18 @@ defmodule ElixirScript.Passes.LoadModules do - @moduledoc false + @moduledoc false def execute(compiler_data, _) do ex_files = compiler_data.data - |> Enum.filter(fn + |> Enum.filter(fn {_, %{app: :elixir}} -> false %{app: :elixir} -> - false + false _ -> true - end) + end) |> Enum.map(fn { _, %{path: path} } -> path %{path: path} -> path - end) + end) loaded_modules = case Enum.reverse(ex_files) do [] -> From d90d902e4ae993ce7a18ace62bc4700f7b3d46a5 Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Mon, 13 Mar 2017 21:32:07 -0500 Subject: [PATCH 480/860] Update changelog --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 9a8ad0db..7de0f193 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,6 +9,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/). ### Added - `super` - `defoverridable` +- `IO.inspect\1`, `IO.puts\1`, `IO.puts\2`, `IO.warn\1` - `Elixir.load` for loading generated JavaScript modules in bundled output. Unlike `Elixir.start`, this will only call `__load` on the module and return the functions on it From f43dd0296d2a9fb3a6baa9304e43aa5f94b17d9c Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Tue, 14 Mar 2017 22:27:13 -0500 Subject: [PATCH 481/860] Access global js items behind JS module --- CHANGELOG.md | 7 ++ lib/elixir_script/translator.ex | 26 ++++--- lib/elixir_script/translator/kernel/js.ex | 83 +++++++++++++++++++++++ priv/std_lib/atom.ex | 4 +- priv/std_lib/base.ex | 4 +- priv/std_lib/integer.ex | 4 +- priv/std_lib/io.ex | 10 +-- priv/std_lib/kernel.ex | 12 ++-- priv/std_lib/map.ex | 4 +- priv/std_lib/regex.ex | 8 +-- priv/std_lib/string.ex | 10 +-- test/translator/js_test.exs | 55 +++++++++++++++ 12 files changed, 188 insertions(+), 39 deletions(-) create mode 100644 test/translator/js_test.exs diff --git a/CHANGELOG.md b/CHANGELOG.md index 7de0f193..8801c9b3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -21,6 +21,13 @@ exports.hello(); ### Changed - `-ex` alias is now `-e` - A filename can be specified for output +- To access global JavaScript functions, modules, and properties, use the `JS` module +```elixir +JS.length # translates to 'length' +JS.alert() # translates to 'alert()' +JS.String.raw("hi") # translate to String.raw('hi') +JS.console.log("hi") # translates to console.log('hi') +``` ### Fixed - Make sure mix compiler works in umbrella apps diff --git a/lib/elixir_script/translator.ex b/lib/elixir_script/translator.ex index a4e30f7b..8c0ebae1 100644 --- a/lib/elixir_script/translator.ex +++ b/lib/elixir_script/translator.ex @@ -71,6 +71,18 @@ defmodule ElixirScript.Translator do js_ast end + defp do_translate({{:., _, [{:__aliases__, _, [:JS]}, function_name]}, _, params }, env) when function_name in @generator_types do + do_translate({function_name, [], params}, env) + end + + defp do_translate({{:., _, [{:__aliases__, _, [:JS]}, function_name]}, _, params }, env) do + JSLib.translate_js_function(function_name, params, env) + end + + defp do_translate({{:., _, [{:__aliases__, context, [:JS | rest]}, function_name]}, _, params }, env) do + JSLib.translate_js_function({:__aliases__, context, rest}, function_name, params, env) + end + defp do_translate(ast, env) when is_number(ast) or is_binary(ast) or is_boolean(ast) or is_nil(ast) do { Primitive.make_literal(ast), env } end @@ -247,7 +259,7 @@ defmodule ElixirScript.Translator do { name, _ } = env.function super_name = String.to_atom("__super__" <> to_string(name)) - Call.make_local_function_call(super_name, params, env) + Call.make_local_function_call(super_name, params, env) end defp do_translate({{:., _, [function_name]}, _, params}, env) do @@ -292,14 +304,6 @@ defmodule ElixirScript.Translator do translate({{:., context1, [{:__aliases__, context2, [:Bootstrap, :Enum]}, function_name]}, context3, params }, env) end - defp do_translate({{:., _, [{:__aliases__, _, [:JS]}, function_name]}, _, params }, env) when function_name in @generator_types do - do_translate({function_name, [], params}, env) - end - - defp do_translate({{:., _, [{:__aliases__, _, [:JS]}, function_name]}, _, params }, env) do - JSLib.translate_js_function(function_name, params, env) - end - defp do_translate({{:., _, [{:__aliases__, _, _} = module_name, function_name]}, _, params } = ast, env) do expanded_ast = Macro.expand(ast, env.env) @@ -324,7 +328,7 @@ defmodule ElixirScript.Translator do else translate(expanded_ast, env) end - end + end defp do_translate({{:., _, [module_name, function_name]}, _, params } = ast, env) do expanded_ast = Macro.expand(ast, env.env) @@ -696,7 +700,7 @@ defmodule ElixirScript.Translator do else module_name end - end + end def has_function?(module_name, name_arity, env) do case ElixirScript.Translator.State.get_module(env.state, module_name) do diff --git a/lib/elixir_script/translator/kernel/js.ex b/lib/elixir_script/translator/kernel/js.ex index 1d7dc8ad..af194137 100644 --- a/lib/elixir_script/translator/kernel/js.ex +++ b/lib/elixir_script/translator/kernel/js.ex @@ -3,6 +3,39 @@ defmodule ElixirScript.Translator.JS do alias ESTree.Tools.Builder alias ElixirScript.Translator + alias ElixirScript.Translator.Utils + alias ElixirScript.Translator.Identifier + + def call_property() do + Builder.member_expression( + Builder.member_expression( + Builder.identifier("Bootstrap"), + Builder.member_expression( + Builder.identifier("Core"), + Builder.identifier("Functions") + ) + ), + Builder.identifier("call_property") + ) + end + + def global() do + Builder.member_expression( + Builder.member_expression( + Builder.identifier("Bootstrap"), + Builder.member_expression( + Builder.identifier("Core"), + Builder.identifier("Functions") + ) + ), + Builder.identifier("get_global") + ) + end + + @doc false + def translate_js_function({:__aliases__, _, module}, name, params, env) do + { do_translate(module, {name, [], params}, env), env } + end @doc false def translate_js_function(name, params, env) do @@ -89,4 +122,54 @@ defmodule ElixirScript.Translator.JS do Translator.translate!({ :%{}, [], args }, env) end + defp do_translate({function, _, []}, env) do + Builder.call_expression( + call_property(), + [ + Builder.call_expression(global(), []), + Translator.translate!(to_string(function), env) + ] + ) + end + + defp do_translate({function, _, params}, env) do + Builder.call_expression( + Builder.member_expression( + Builder.call_expression(global(), []), + Builder.identifier(function) + ), + Enum.map(params, &Translator.translate!(&1, env)) + ) + end + + defp do_translate(module, {function, _, []}, env) do + members = Identifier.make_namespace_members(module) + + Builder.call_expression( + call_property(), + [ + Builder.member_expression( + Builder.call_expression(global(), []), + members + ), + Translator.translate!(to_string(function), env) + ] + ) + end + + defp do_translate(module, {function, _, params}, env) do + members = Identifier.make_namespace_members(module) + + Builder.call_expression( + Builder.member_expression( + Builder.member_expression( + Builder.call_expression(global(), []), + members + ), + Builder.identifier(function) + ), + Enum.map(params, &Translator.translate!(&1, env)) + ) + end + end diff --git a/priv/std_lib/atom.ex b/priv/std_lib/atom.ex index f932c1d2..786ded55 100644 --- a/priv/std_lib/atom.ex +++ b/priv/std_lib/atom.ex @@ -1,5 +1,5 @@ defmodule ElixirScript.Atom do - @moduledoc false + @moduledoc false import Kernel, except: [to_string: 1] def to_char_list(atom) do @@ -7,7 +7,7 @@ defmodule ElixirScript.Atom do end def to_string(atom) do - Symbol.keyFor(atom) + JS.Symbol.keyFor(atom) end end diff --git a/priv/std_lib/base.ex b/priv/std_lib/base.ex index 3e02779f..a91978f9 100644 --- a/priv/std_lib/base.ex +++ b/priv/std_lib/base.ex @@ -1,5 +1,5 @@ defmodule ElixirScript.Base do - @moduledoc false + @moduledoc false def encode64(data) do Bootstrap.Core.b64EncodeUnicode(data) @@ -14,7 +14,7 @@ defmodule ElixirScript.Base do end def decode64!(data) do - Bootstrap.Core.get_global().atob(data) + JS.atob(data) end end diff --git a/priv/std_lib/integer.ex b/priv/std_lib/integer.ex index 9aaa64d0..3a5bb41d 100644 --- a/priv/std_lib/integer.ex +++ b/priv/std_lib/integer.ex @@ -13,9 +13,9 @@ defmodule ElixirScript.Integer do end def parse(bin, base \\ 10) do - result = Bootstrap.Core.Functions.get_global().parseInt(bin, base) + result = JS.parseInt(bin, base) - if Bootstrap.Core.Functions.get_global().isNaN(result) do + if JS.isNaN(result) do :error else case bin.indexOf(".") do diff --git a/priv/std_lib/io.ex b/priv/std_lib/io.ex index f7dff45b..0444da1d 100644 --- a/priv/std_lib/io.ex +++ b/priv/std_lib/io.ex @@ -1,22 +1,22 @@ defmodule ElixirScript.IO do def inspect(item, opts \\ []) do - :console.log(item) + JS.console.log(item) item end def puts(device \\ :stdio, item) when is_binary(item) do case device do :stdio -> - :console.log(item) + JS.console.log(item) :stderr -> - :console.warn(item) + JS.console.warn(item) end end def warn(message) when is_binary(message) do - :console.warn("warning: #{message}") - :console.trace() + JS.console.warn("warning: #{message}") + JS.console.trace() end end diff --git a/priv/std_lib/kernel.ex b/priv/std_lib/kernel.ex index 33ad1b81..1c0a7b3e 100644 --- a/priv/std_lib/kernel.ex +++ b/priv/std_lib/kernel.ex @@ -40,7 +40,7 @@ defmodule ElixirScript.Kernel do end def abs(number) do - Math.abs(number) + JS.Math.abs(number) end def apply(fun, args) do @@ -128,23 +128,23 @@ defmodule ElixirScript.Kernel do end def map_size(term) do - Object.keys(term).length + JS.Object.keys(term).length end def max(first, second) do - Math.max(first, second) + JS.Math.max(first, second) end def min(first, second) do - Math.min(first, second) + JS.Math.min(first, second) end def round(number) do - Math.round(number) + JS.Math.round(number) end def trunc(number) do - Math.floor(number) + JS.Math.floor(number) end def tuple_size(tuple) do diff --git a/priv/std_lib/map.ex b/priv/std_lib/map.ex index e2f3b46e..66a61a48 100644 --- a/priv/std_lib/map.ex +++ b/priv/std_lib/map.ex @@ -1,6 +1,6 @@ defmodule ElixirScript.Map do @moduledoc false - + def new() do %{} end @@ -29,7 +29,7 @@ defmodule ElixirScript.Map do end def values(map) do - Object.values(map) + JS.Object.values(map) end def from_struct(struct) do diff --git a/priv/std_lib/regex.ex b/priv/std_lib/regex.ex index 17888909..e395a5d9 100644 --- a/priv/std_lib/regex.ex +++ b/priv/std_lib/regex.ex @@ -4,7 +4,7 @@ defmodule ElixirScript.Regex do def compile(source, options \\ "") do try do - {:ok, JS.new(RegExp, [source, options])} + {:ok, JS.new(JS.RegExp, [source, options])} rescue x -> {:error, x.message} @@ -12,11 +12,11 @@ defmodule ElixirScript.Regex do end def compile!(source, options \\ "") do - JS.new(RegExp, [source, options]) + JS.new(JS.RegExp, [source, options]) end def regex?(term) do - JS.instanceof(term, RegExp) + JS.instanceof(term, JS.RegExp) end def match?(regex, string) do @@ -64,7 +64,7 @@ defmodule ElixirScript.Regex do if String.contains?(opts(regex), "g") do regex else - JS.new(RegExp, [ source(regex), opts(regex) <> "g" ]) + JS.new(JS.RegExp, [ source(regex), opts(regex) <> "g" ]) end end diff --git a/priv/std_lib/string.ex b/priv/std_lib/string.ex index 2997ab63..d267ae51 100644 --- a/priv/std_lib/string.ex +++ b/priv/std_lib/string.ex @@ -3,11 +3,11 @@ defmodule ElixirScript.String do import Kernel, except: [length: 1] def to_atom(str) do - Symbol.for(str) + JS.Symbol.for(str) end def to_existing_atom(str) do - Symbol.for(str) + JS.Symbol.for(str) end def to_char_list(str) do @@ -15,15 +15,15 @@ defmodule ElixirScript.String do end def to_float(str) do - Bootstrap.Core.get_global().parseFloat(str) + JS.parseFloat(str) end def to_integer(str) do - Bootstrap.Core.get_global().parseInt(str, 10) + JS.parseInt(str, 10) end def to_integer(str, base) do - Bootstrap.Core.get_global().parseInt(str, base) + JS.parseInt(str, base) end def upcase(str) do diff --git a/test/translator/js_test.exs b/test/translator/js_test.exs new file mode 100644 index 00000000..2118dba8 --- /dev/null +++ b/test/translator/js_test.exs @@ -0,0 +1,55 @@ +defmodule ElixirScript.Translator.JS.Test do + use ExUnit.Case + import ElixirScript.TestHelper + + + test "translate global function calls" do + ex_ast = quote do: JS.alert("hi") + js_code = "Bootstrap.Core.Functions.get_global().alert('hi')" + + assert_translation(ex_ast, js_code) + + ex_ast = quote do: JS.back() + js_code = "Bootstrap.Core.Functions.call_property(Bootstrap.Core.Functions.get_global(), 'back')" + + assert_translation(ex_ast, js_code) + end + + test "translate global properties" do + ex_ast = quote do: JS.length + js_code = "Bootstrap.Core.Functions.call_property(Bootstrap.Core.Functions.get_global(), 'length')" + + assert_translation(ex_ast, js_code) + end + + test "translate global module" do + ex_ast = quote do: JS.String.toString() + js_code = "Bootstrap.Core.Functions.call_property(Bootstrap.Core.Functions.get_global().String, 'toString')" + + assert_translation(ex_ast, js_code) + + ex_ast = quote do: JS.String.raw("hi") + js_code = "Bootstrap.Core.Functions.get_global().String.raw('hi')" + + assert_translation(ex_ast, js_code) + + ex_ast = quote do: JS.Something.Other.raw("hi") + js_code = "Bootstrap.Core.Functions.get_global().Something.Other.raw('hi')" + + assert_translation(ex_ast, js_code) + end + + test "translate global lowercase" do + ex_ast = quote do: JS.console.log("hi") + js_code = "Bootstrap.Core.Functions.call_property(Bootstrap.Core.Functions.get_global(), 'console').log('hi')" + + assert_translation(ex_ast, js_code) + + ex_ast = quote do: JS.window.length + js_code = "Bootstrap.Core.Functions.call_property(Bootstrap.Core.Functions.call_property(Bootstrap.Core.Functions.get_global(), 'window'), 'length')" + + assert_translation(ex_ast, js_code) + end + + +end From b2b5da7134b15479e90c9733cf2574776227104f Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Fri, 17 Mar 2017 20:13:52 -0500 Subject: [PATCH 482/860] Update for release --- CHANGELOG.md | 2 +- mix.exs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 8801c9b3..1e2307f5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,7 +4,7 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](http://keepachangelog.com/) and this project adheres to [Semantic Versioning](http://semver.org/). -## [0.27.0-dev] +## [0.27.0] - 2017-03-17 ### Added - `super` diff --git a/mix.exs b/mix.exs index 5da7fda2..6023aa53 100644 --- a/mix.exs +++ b/mix.exs @@ -4,7 +4,7 @@ defmodule ElixirScript.Mixfile do def project do [ app: :elixir_script, - version: "0.27.0-dev", + version: "0.27.0", elixir: "~> 1.0", elixirc_paths: elixirc_paths(), escript: escript_config(), From f7cb855381c65039085f524837174c1e017b0e0a Mon Sep 17 00:00:00 2001 From: Stephan van Diepen Date: Sat, 18 Mar 2017 20:16:31 +0100 Subject: [PATCH 483/860] Add js_module default option documentation --- GettingStarted.md | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/GettingStarted.md b/GettingStarted.md index 6d57e4ed..36c5f1f5 100644 --- a/GettingStarted.md +++ b/GettingStarted.md @@ -93,7 +93,8 @@ Add dependency to your deps in mix.exs: format: :es, js_modules: [ {React, "react"}, - {ReactDOM, "react-dom"} + {ReactDOM, "react-dom"}, + {Phoenix, "phoenix", default: false} ] ], compilers: [:elixir_script] ++ Mix.compilers @@ -117,7 +118,9 @@ Available options are: * `:umd` - UMD -* `js_modules`: A list of JavaScript imports to add. Each item must be 2-tuple or a 3-tuple. The third element is an optional keyword list of options. +* `js_modules`: A list of JavaScript imports to add. Each item must be 2-tuple or a 3-tuple. The third element is an optional keyword list of options: + + * `default` - Defaults to true. Set to false if the imported module has no default export. ### Macros From ec2e5abdf37a9e3dc086228c64cbb3f354237c28 Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Sat, 18 Mar 2017 20:08:46 -0500 Subject: [PATCH 484/860] Reducing javascript functions --- lib/elixir_script/translator/rewriter.ex | 62 +++---- priv/std_lib/agent.ex | 16 +- priv/std_lib/base.ex | 4 +- priv/std_lib/bootstrap/functions.ex | 57 ++++++ priv/std_lib/kernel.ex | 16 +- priv/std_lib/list.ex | 6 +- priv/std_lib/map.ex | 2 +- priv/std_lib/store.ex | 45 +++++ priv/std_lib/string.ex | 2 +- src/javascript/lib/core.js | 12 +- src/javascript/lib/core/functions.js | 215 +---------------------- src/javascript/lib/core/store.js | 46 ----- 12 files changed, 151 insertions(+), 332 deletions(-) create mode 100644 priv/std_lib/bootstrap/functions.ex create mode 100644 priv/std_lib/store.ex delete mode 100644 src/javascript/lib/core/store.js diff --git a/lib/elixir_script/translator/rewriter.ex b/lib/elixir_script/translator/rewriter.ex index c4760a7c..afd1f81b 100644 --- a/lib/elixir_script/translator/rewriter.ex +++ b/lib/elixir_script/translator/rewriter.ex @@ -1,5 +1,5 @@ defmodule ElixirScript.Translator.Rewriter do - @moduledoc false + @moduledoc false # :erlang, :lists, :maps, :beam_lib, :binary, :calendar, :digraph, # :epp, :erl_lint, :erl_internal, :erl_expand_records, :erl_eval, @@ -331,35 +331,27 @@ defmodule ElixirScript.Translator.Rewriter do end def rewrite({{:., _, [:lists, :foldl]}, _, [fun, acc, list]}) do - quote do: Bootstrap.Core.Functions.foldl(unquote(fun), unquote(acc), unquote(list)) + quote do: List.foldl(unquote(fun), unquote(acc), unquote(list)) end def rewrite({{:., _, [:lists, :foldr]}, _, [fun, acc, list]}) do - quote do: Bootstrap.Core.Functions.foldr(unquote(fun), unquote(acc), unquote(list)) + quote do: List.foldr(unquote(fun), unquote(acc), unquote(list)) end def rewrite({{:., _, [:lists, :keymember]}, _, [key, n, list]}) do - quote do: Bootstrap.Core.Functions.keymember(unquote(key), unquote(n), unquote(list)) + quote do: List.keymember?(unquote(list), unquote(key), unquote(n)) end def rewrite({{:., _, [:lists, :keydelete]}, _, [key, n, list]}) do - quote do: Bootstrap.Core.Functions.keydelete(unquote(key), unquote(n), unquote(list)) - end - - def rewrite({{:., _, [:lists, :keystore]}, _, [key, n, list, newtuple]}) do - quote do: Bootstrap.Core.Functions.keystore(unquote(key), unquote(n), unquote(list), unquote(newtuple)) - end - - def rewrite({{:., _, [:lists, :keytake]}, _, [key, n, list]}) do - quote do: Bootstrap.Core.Functions.keystore(unquote(key), unquote(n), unquote(list)) + quote do: List.keydelete(unquote(list), unquote(key), unquote(n)) end def rewrite({{:., _, [:lists, :keyfind]}, _, [key, n, list]}) do - quote do: Bootstrap.Core.Functions.keyfind(unquote(key), unquote(n), unquote(list)) + quote do: List.keyfind(unquote(list), unquote(key), unquote(n)) end def rewrite({{:., _, [:lists, :keyreplace]}, _, [key, n, list, newtuple]}) do - quote do: Bootstrap.Core.Functions.keyreplace(unquote(key), unquote(n), unquote(list), unquote(newtuple)) + quote do: List.keyreplace(unquote(list), unquote(key), unquote(n), unquote(newtuple)) end def rewrite({{:., _, [:lists, :keysort]}, _, [n, tuplelist]}) do @@ -368,27 +360,27 @@ defmodule ElixirScript.Translator.Rewriter do end def rewrite({{:., _, [:lists, :reverse]}, _, [list]}) do - quote do: Bootstrap.Core.Functions.reverse(unquote(list)) + quote do: ElixirScript.Bootstrap.Functions.reverse(unquote(list)) end def rewrite({{:., _, [:lists, :reverse]}, _, [list, tail]}) do - quote do: Bootstrap.Core.Functions.reverse(unquote(list)) ++ unquote(tail) + quote do: ElixirScript.Bootstrap.Functions.reverse(unquote(list)) ++ unquote(tail) end def rewrite({{:., _, [:lists, :flatten]}, _, [list]}) do - quote do: Bootstrap.Core.Functions.flatten(unquote(list)) + quote do: List.flatten(unquote(list)) end def rewrite({{:., _, [:lists, :flatten]}, _, [list, tail]}) do - quote do: Bootstrap.Core.Functions.flatten(unquote(list), unquote(tail)) + quote do: List.flatten(unquote(list), unquote(tail)) end def rewrite({{:., _, [:lists, :delete]}, _, [elem, list]}) do - quote do: Bootstrap.Core.Functions.remove_from_list(unquote(list), unquote(elem)) + quote do: List.delete(unquote(list), unquote(elem)) end def rewrite({{:., _, [:lists, :duplicate]}, _, [n, elem]}) do - quote do: Bootstrap.Core.Functions.duplicate(unquote(n), unquote(elem)) + quote do: List.duplicate(unquote(n), unquote(elem)) end def rewrite({{:., _, [:lists, :mapfoldl]}, _, [fun, acc, list]}) do @@ -437,15 +429,15 @@ defmodule ElixirScript.Translator.Rewriter do end def rewrite({{:., _, [:erlang, :list_to_float]}, _, [list]}) do - quote do: parseFloat(unquote(list)) + quote do: JS.parseFloat(unquote(list)) end def rewrite({{:., _, [:erlang, :list_to_integer]}, _, [list]}) do - quote do: parseInt(unquote(list)) + quote do: JS.parseInt(unquote(list)) end def rewrite({{:., _, [:erlang, :list_to_integer]}, _, [list, base]}) do - quote do: parseInt(unquote(list), unquote(base)) + quote do: JS.parseInt(unquote(list), unquote(base)) end def rewrite({{:., _, [:erlang, :integer_to_binary]}, _, [integer]}) do @@ -481,19 +473,19 @@ defmodule ElixirScript.Translator.Rewriter do end def rewrite({{:., _, [:erlang, :binary_to_float]}, _, [binary]}) do - quote do: parseFloat(unquote(binary)) + quote do: JS.parseFloat(unquote(binary)) end def rewrite({{:., _, [:erlang, :binary_to_integer]}, _, [binary]}) do - quote do: parseInt(unquote(binary)) + quote do: JS.parseInt(unquote(binary)) end def rewrite({{:., _, [:erlang, :binary_to_integer]}, _, [binary, base]}) do - quote do: parseInt(unquote(binary), unquote(base)) + quote do: JS.parseInt(unquote(binary), unquote(base)) end def rewrite({{:., _, [:maps, :is_key]}, _, [key, map]}) do - quote do: unquote(key) in Bootstrap.Core.Functions.get_object_keys(unquote(map)) + quote do: unquote(key) in ElixirScript.Bootstrap.Functions.get_object_keys(unquote(map)) end def rewrite({{:., _, [:maps, :put]}, _, [key, value, map]}) do @@ -501,23 +493,11 @@ defmodule ElixirScript.Translator.Rewriter do end def rewrite({{:., _, [:maps, :update]}, _, [key, value, map]}) do - quote do: Bootstrap.Core.Functions.update_map(unquote(map), unquote(key), unquote(value)) - end - - def rewrite({{:., _, [:maps, :find]}, _, [key, map]}) do - quote do: Bootstrap.Core.Functions.maps_find(unquote(key), unquote(map)) + quote do: Map.update!(unquote(map), unquote(key), fn(_) -> unquote(value) end) end def rewrite({{:., _, [:maps, :remove]}, _, [key, map]}) do quote do: Bootstrap.Core.Functions.delete_property_from_map(unquote(map), unquote(key)) end - def rewrite({{:., _, [:maps, :fold]}, _, [fun, init, map]}) do - quote do: Bootstrap.Core.Functions.maps_fold(unquote(fun), unquote(init), unquote(map)) - end - - def rewrite({{:., _, [:maps, :from_list]}, _, [list]}) do - quote do: Bootstrap.Core.Functions.maps_fold(unquote(list)) - end - end diff --git a/priv/std_lib/agent.ex b/priv/std_lib/agent.ex index 6000058f..6b2559de 100644 --- a/priv/std_lib/agent.ex +++ b/priv/std_lib/agent.ex @@ -11,7 +11,7 @@ defmodule ElixirScript.Agent do nil end - Bootstrap.Core.Store.create(pid, fun.(), name) + ElixirScript.Store.create(pid, fun.(), name) { :ok, pid } end @@ -24,30 +24,30 @@ defmodule ElixirScript.Agent do nil end - Bootstrap.Core.Store.create(pid, fun.(), name) + ElixirScript.Store.create(pid, fun.(), name) { :ok, pid } end def stop(agent) do - Bootstrap.Core.Store.remove(agent) + ElixirScript.Store.remove(agent) :ok end def update(agent, fun) do - current_state = Bootstrap.Core.Store.read(agent) - Bootstrap.Core.Store.update(agent, fun.(current_state)) + current_state = ElixirScript.Store.read(agent) + ElixirScript.Store.update(agent, fun.(current_state)) :ok end def get(agent, fun) do - current_state = Bootstrap.Core.Store.read(agent) + current_state = ElixirScript.Store.read(agent) fun.(current_state) end def get_and_update(agent, fun) do - current_state = Bootstrap.Core.Store.read(agent) + current_state = ElixirScript.Store.read(agent) {val, new_state} = fun.(current_state) - Bootstrap.Core.Store.update(agent, new_state) + ElixirScript.Store.update(agent, new_state) val end diff --git a/priv/std_lib/base.ex b/priv/std_lib/base.ex index a91978f9..c74e0678 100644 --- a/priv/std_lib/base.ex +++ b/priv/std_lib/base.ex @@ -2,11 +2,11 @@ defmodule ElixirScript.Base do @moduledoc false def encode64(data) do - Bootstrap.Core.b64EncodeUnicode(data) + ElixirScript.Bootstrap.b64EncodeUnicode(data) end def decode64(data) do - if Bootstrap.Core.can_decode64(data) do + if ElixirScript.Bootstrap.can_decode64(data) do {:ok, decode64!(data) } else :error diff --git a/priv/std_lib/bootstrap/functions.ex b/priv/std_lib/bootstrap/functions.ex new file mode 100644 index 00000000..6d1e225c --- /dev/null +++ b/priv/std_lib/bootstrap/functions.ex @@ -0,0 +1,57 @@ +defmodule ElixirScript.Bootstrap.Functions do + + def contains(left, []) do + false + end + + def contains(left, [right]) do + match?(left, right) + end + + def contains(left, [h|t]) do + case match?(left, h) do + true -> + true + false -> + contains(left, t) + end + end + + def get_object_keys(obj) do + JS.Object.keys(obj).concat(JS.Object.getOwnPropertySymbols(obj)) + end + + def is_valid_character(codepoint) do + try do + JS.String.fromCodePoint(codepoint) != nil + rescue + _ -> + false + end + end + + def b64EncodeUnicode(str) do + {:ok, regex} = Regex.compile("%([0-9A-F]{2})", "g") + + JS.btoa( + JS.encodeURIComponent(str).replace(regex, fn (match, p1) -> + JS.String.fromCharCode("0x#{p1}") + end) + ) + end + + def can_decode64(data) do + try do + JS.atob(data) + true + rescue + _ -> + false + end + end + + def reverse(list) do + list.concat([]).reverse() + end + +end diff --git a/priv/std_lib/kernel.ex b/priv/std_lib/kernel.ex index 1c0a7b3e..f085f075 100644 --- a/priv/std_lib/kernel.ex +++ b/priv/std_lib/kernel.ex @@ -44,11 +44,11 @@ defmodule ElixirScript.Kernel do end def apply(fun, args) do - Bootstrap.Core.Functions.apply(fun, args) + fun.apply(fun, args) end def apply(module, fun, args) do - Bootstrap.Core.Functions.apply(module, Atom.to_string(fun), args) + module[Atom.to_string(fun)].apply(module[Atom.to_string(fun)], args) end def binary_part(binary, start, len) do @@ -80,7 +80,7 @@ defmodule ElixirScript.Kernel do end def is_float(term) do - is_number(term) && !Number.isInteger(term) + is_number(term) && !JS.Number.isInteger(term) end def is_function(term) do @@ -92,11 +92,11 @@ defmodule ElixirScript.Kernel do end def is_integer(term) do - Number.isInteger(term) + JS.Number.isInteger(term) end def is_list(term) do - Array.isArray(term) + JS.Array.isArray(term) end def is_number(term) do @@ -148,11 +148,11 @@ defmodule ElixirScript.Kernel do end def tuple_size(tuple) do - Bootstrap.Core.Functions.size(tuple) + tuple.count() end def elem(tuple, index) do - Bootstrap.Core.Functions.apply(tuple, "get", [index]) + apply(tuple, :get, [index]) end def is_nil(term) do @@ -193,7 +193,7 @@ defmodule ElixirScript.Kernel do defmacro left in right do quote do - Bootstrap.Core.Functions.contains(unquote(left), unquote(right)) + ElixirScript.Bootstrap.Functions.contains(unquote(left), unquote(right)) end end diff --git a/priv/std_lib/list.ex b/priv/std_lib/list.ex index db553ae6..94728a16 100644 --- a/priv/std_lib/list.ex +++ b/priv/std_lib/list.ex @@ -156,11 +156,7 @@ defmodule ElixirScript.List do do_foldl(tl(list), acc, func, new_list ++ [value]) end - def flatten(list) do - do_flatten(list, []) - end - - def flatten(list, tail) do + def flatten(list, tail \\ []) do do_flatten(list, []) ++ tail end diff --git a/priv/std_lib/map.ex b/priv/std_lib/map.ex index 66a61a48..2f0c4319 100644 --- a/priv/std_lib/map.ex +++ b/priv/std_lib/map.ex @@ -6,7 +6,7 @@ defmodule ElixirScript.Map do end def keys(map) do - Bootstrap.Core.Functions.get_object_keys(map) + ElixirScript.Bootstrap.Functions.get_object_keys(map) end def size(map) do diff --git a/priv/std_lib/store.ex b/priv/std_lib/store.ex new file mode 100644 index 00000000..83955381 --- /dev/null +++ b/priv/std_lib/store.ex @@ -0,0 +1,45 @@ +defmodule ElixirScript.Store do + + defp get_key(key) do + + real_key = case JS.__elixirscript_names__.has(key) do + true -> + JS.__elixirscript_names__.get(key) + false -> + key + end + + + case JS.__elixirscript_store__.has(real_key) do + true -> + real_key + false -> + JS.throw JS.new(JS.Error("Key Not Found")) + end + end + + def create(key, value, name \\ nil) do + if name != nil do + JS.__elixirscript_names__.set(name, key) + end + + JS.__elixirscript_store__.set(key, value) + end + + def update(key, value) do + real_key = get_key(key) + JS.__elixirscript_store__.set(real_key, value) + end + + def read(key) do + real_key = get_key(key) + JS.__elixirscript_store__.get(real_key) + end + + def remove(key) do + real_key = get_key(key) + JS.__elixirscript_store__.delete(real_key) + end + + +end diff --git a/priv/std_lib/string.ex b/priv/std_lib/string.ex index d267ae51..1ff6bcee 100644 --- a/priv/std_lib/string.ex +++ b/priv/std_lib/string.ex @@ -199,6 +199,6 @@ defmodule ElixirScript.String do end def valid_character?(codepoint) do - Bootstrap.Core.Functions.is_valid_character(codepoint) + ElixirScript.Bootstrap.Functions.is_valid_character(codepoint) end end diff --git a/src/javascript/lib/core.js b/src/javascript/lib/core.js index d8bccde4..8b488fb8 100644 --- a/src/javascript/lib/core.js +++ b/src/javascript/lib/core.js @@ -1,11 +1,12 @@ -import Patterns from "tailored"; -import ErlangTypes from "erlang-types"; -import Functions from "./core/functions"; -import SpecialForms from "./core/special_forms"; -import Store from "./core/store"; +import Patterns from 'tailored'; +import ErlangTypes from 'erlang-types'; +import Functions from './core/functions'; +import SpecialForms from './core/special_forms'; class Integer {} class Float {} +Functions.get_global().__elixirscript_store__ = new Map(); +Functions.get_global().__elixirscript_names__ = new Map(); export default { Tuple: ErlangTypes.Tuple, @@ -16,5 +17,4 @@ export default { Float, Functions, SpecialForms, - Store }; diff --git a/src/javascript/lib/core/functions.js b/src/javascript/lib/core/functions.js index 8b09d2f0..99d3b8ec 100644 --- a/src/javascript/lib/core/functions.js +++ b/src/javascript/lib/core/functions.js @@ -31,24 +31,6 @@ function call_property(item, property) { return item[prop]; } -function apply(...args) { - if (args.length === 2) { - return args[0].apply(args[0], args.slice(1)); - } else { - return args[0][args[1]].apply(args[0], args.slice(2)); - } -} - -function contains(left, right) { - for (const x of right) { - if (Core.Patterns.match_or_default(left, x) != null) { - return true; - } - } - - return false; -} - function get_global() { if (typeof self !== 'undefined') { return self; @@ -105,26 +87,6 @@ function defimpl(protocol, type, impl) { protocol.implementation(type, impl); } -function get_object_keys(obj) { - return Object.keys(obj).concat(Object.getOwnPropertySymbols(obj)); -} - -function is_valid_character(codepoint) { - try { - return String.fromCodePoint(codepoint) != null; - } catch (e) { - return false; - } -} - -// https://developer.mozilla.org/en-US/docs/Web/API/WindowBase64/Base64_encoding_and_decoding#Solution_2_%E2%80%93_rewrite_the_DOMs_atob()_and_btoa()_using_JavaScript's_TypedArrays_and_UTF-8 -function b64EncodeUnicode(str) { - return btoa( - encodeURIComponent(str).replace(/%([0-9A-F]{2})/g, (match, p1) => - String.fromCharCode(`0x${p1}`)) - ); -} - function delete_property_from_map(map, property) { const new_map = Object.assign(Object.create(map.constructor.prototype), map); delete new_map[property]; @@ -143,14 +105,6 @@ function add_property_to_map(map, property, value) { return Object.freeze(new_map); } -function update_map(map, property, value) { - if (property in get_object_keys(map)) { - return add_property_to_map(map, property, value); - } - - throw 'map does not have key'; -} - function bnot(expr) { return ~expr; } @@ -201,143 +155,6 @@ function zip(list_of_lists) { return Object.freeze(new_value); } -function can_decode64(data) { - try { - atob(data); - return true; - } catch (e) { - return false; - } -} - -function remove_from_list(list, element) { - let found = false; - - return list.filter(elem => { - if (!found && elem === element) { - found = true; - return false; - } - - return true; - }); -} - -function foldl(fun, acc, list) { - let acc1 = acc; - - for (const el of list) { - acc1 = fun(el, acc1); - } - - return acc1; -} - -function foldr(fun, acc, list) { - let acc1 = acc; - - for (let i = list.length - 1; i >= 0; i--) { - acc1 = fun(list[i], acc1); - } - - return acc1; -} - -function keyfind(key, n, tuplelist) { - for (let i = tuplelist.length - 1; i >= 0; i--) { - if (tuplelist[i].get(n) === key) { - return tuplelist[i]; - } - } - - return false; -} - -function keydelete(key, n, tuplelist) { - for (let i = tuplelist.length - 1; i >= 0; i--) { - if (tuplelist[i].get(n) === key) { - return tuplelist.concat([]).splice(i, 1); - } - } - - return tuplelist; -} - -function keystore(key, n, list, newtuple) { - for (let i = list.length - 1; i >= 0; i--) { - if (list[i].get(n) === key) { - return list.concat([]).splice(i, 1, newtuple); - } - } - - return list.concat([]).push(newtuple); -} - -function keymember(key, n, list) { - for (let i = list.length - 1; i >= 0; i--) { - if (list[i].get(n) === key) { - return true; - } - } - - return false; -} - -function keytake(key, n, list) { - if (!keymember(key, n, list)) { - return false; - } - - const tuple = keyfind(key, n, list); - - return new Core.Tuple(tuple.get(n), tuple, keydelete(key, n, list)); -} - -function keyreplace(key, n, list, newtuple) { - for (let i = list.length - 1; i >= 0; i--) { - if (list[i].get(n) === key) { - return list.concat([]).splice(i, 1, newtuple); - } - } - - return list; -} - -function reverse(list) { - return list.concat([]).reverse(); -} - -function maps_find(key, map) { - if (key in get_object_keys(map)) { - return new Core.Tuple(Symbol.for('ok'), map[key]); - } - return Symbol.for('error'); -} - -function flatten(list, tail = []) { - let new_list = []; - - for (const e of list) { - if (Array.isArray(e)) { - new_list = new_list.concat(flatten(e)); - } else { - new_list.push(e); - } - } - - return Object.freeze(new_list.concat(tail)); -} - -function duplicate(n, elem) { - const list = []; - - for (let i = 0; i < n; i++) { - list.push(elem); - } - - return Object.freeze(list); -} - function mapfoldl(fun, acc, list) { const newlist = []; let new_acc = acc; @@ -367,16 +184,6 @@ function filtermap(fun, list) { return Object.freeze(newlist); } -function maps_fold(fun, acc, map) { - let acc1 = acc; - - for (const k of get_object_keys(map)) { - acc1 = fun(k, map[k], acc1); - } - - return acc1; -} - function build_namespace(ns, ns_string) { let parts = ns_string.split('.'); const root = ns; @@ -402,20 +209,14 @@ function build_namespace(ns, ns_string) { export default { call_property, - apply, - contains, get_global, defstruct, defexception, defprotocol, defimpl, - get_object_keys, - is_valid_character, - b64EncodeUnicode, delete_property_from_map, add_property_to_map, class_to_obj, - can_decode64, bnot, band, bor, @@ -423,21 +224,7 @@ export default { bsr, bxor, zip, - foldl, - foldr, - remove_from_list, - keydelete, - keystore, - keyfind, - keytake, - keyreplace, - reverse, - update_map, - maps_find, - flatten, - duplicate, mapfoldl, filtermap, - maps_fold, - build_namespace + build_namespace, }; diff --git a/src/javascript/lib/core/store.js b/src/javascript/lib/core/store.js deleted file mode 100644 index bf8aa04a..00000000 --- a/src/javascript/lib/core/store.js +++ /dev/null @@ -1,46 +0,0 @@ -const store = new Map(); -const names = new Map(); - -function get_key(key) { - let real_key = key; - - if (names.has(key)) { - real_key = names.get(key); - } - - if (store.has(real_key)) { - return real_key; - } - - return new Error('Key Not Found'); -} - -function create(key, value, name = null) { - if (name != null) { - names.set(name, key); - } - - store.set(key, value); -} - -function update(key, value) { - const real_key = get_key(key); - store.set(real_key, value); -} - -function read(key) { - const real_key = get_key(key); - return store.get(real_key); -} - -function remove(key) { - const real_key = get_key(key); - return store.delete(real_key); -} - -export default { - create, - read, - update, - remove, -}; From b570fd80cf8bf3c09a823974ff90d29c72c8874e Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Sun, 19 Mar 2017 10:28:49 -0500 Subject: [PATCH 485/860] Update tests with references to JavaScript modules --- priv/std_lib/store.ex | 2 +- test/translator/case_test.exs | 4 ++-- test/translator/defdelegate_test.exs | 10 +++++----- test/translator/function_test.exs | 4 ++-- test/translator/try_test.exs | 2 +- 5 files changed, 11 insertions(+), 11 deletions(-) diff --git a/priv/std_lib/store.ex b/priv/std_lib/store.ex index 83955381..70634248 100644 --- a/priv/std_lib/store.ex +++ b/priv/std_lib/store.ex @@ -14,7 +14,7 @@ defmodule ElixirScript.Store do true -> real_key false -> - JS.throw JS.new(JS.Error("Key Not Found")) + JS.throw JS.new(JS.Error, ["Key Not Found"]) end end diff --git a/test/translator/case_test.exs b/test/translator/case_test.exs index ccdc4161..9259bb12 100644 --- a/test/translator/case_test.exs +++ b/test/translator/case_test.exs @@ -81,7 +81,7 @@ defmodule ElixirScript.Translator.Case.Test do let [value] = Bootstrap.Core.Patterns.match(Bootstrap.Core.Patterns.variable(),13); return value; },function(number) { - return Bootstrap.Core.Functions.contains(number,Object.freeze([1, 2, 3, 4])); + return Elixir.ElixirScript.Bootstrap.Functions.__load(Elixir).contains(number,Object.freeze([1, 2, 3, 4])); }),Bootstrap.Core.Patterns.clause([Bootstrap.Core.Patterns.wildcard()],function() { return true; })).call(this,data) @@ -106,7 +106,7 @@ defmodule ElixirScript.Translator.Case.Test do let [value] = Bootstrap.Core.Patterns.match(Bootstrap.Core.Patterns.variable(),13); return value; },function(number) { - return Bootstrap.Core.Functions.contains(number,Object.freeze([1, 2, 3, 4])) || Bootstrap.Core.Functions.contains(number,Object.freeze([4, 3, 2, 1])); + return Elixir.ElixirScript.Bootstrap.Functions.__load(Elixir).contains(number,Object.freeze([1, 2, 3, 4])) || Elixir.ElixirScript.Bootstrap.Functions.__load(Elixir).contains(number,Object.freeze([4, 3, 2, 1])); }),Bootstrap.Core.Patterns.clause([Bootstrap.Core.Patterns.wildcard()],function() { return true; })).call(this,data) diff --git a/test/translator/defdelegate_test.exs b/test/translator/defdelegate_test.exs index d6488ab2..52ef6266 100644 --- a/test/translator/defdelegate_test.exs +++ b/test/translator/defdelegate_test.exs @@ -7,8 +7,8 @@ defmodule ElixirScript.Translator.Defdelegate.Test do js_code = """ const reverse = function(list) { - return Bootstrap.Core.Functions.reverse(list); - }; + return Elixir.ElixirScript.Bootstrap.Functions.__load(Elixir).reverse(list); + }; """ assert_translation(ex_ast, js_code) @@ -19,10 +19,10 @@ defmodule ElixirScript.Translator.Defdelegate.Test do js_code = """ const other_reverse = function(list) { - return Bootstrap.Core.Functions.reverse(list); - }; + return Elixir.ElixirScript.Bootstrap.Functions.__load(Elixir).reverse(list); + }; """ assert_translation(ex_ast, js_code) end -end \ No newline at end of file +end diff --git a/test/translator/function_test.exs b/test/translator/function_test.exs index 77748810..c7d2018f 100644 --- a/test/translator/function_test.exs +++ b/test/translator/function_test.exs @@ -342,7 +342,7 @@ defmodule ElixirScript.Translator.Function.Test do const something = Bootstrap.Core.Patterns.defmatch(Bootstrap.Core.Patterns.clause([Bootstrap.Core.Patterns.variable(), Bootstrap.Core.Patterns.variable()],function(one,two) { return null; },function(one,two) { - return Bootstrap.Core.Functions.contains(one,Object.freeze([1, 2, 3])); + return Elixir.ElixirScript.Bootstrap.Functions.__load(Elixir).contains(one,Object.freeze([1, 2, 3])); })); """ @@ -362,7 +362,7 @@ defmodule ElixirScript.Translator.Function.Test do const something = Bootstrap.Core.Patterns.defmatch(Bootstrap.Core.Patterns.clause([Bootstrap.Core.Patterns.variable()],function(one) { return null; },function(one) { - return Bootstrap.Core.Functions.contains(one,Object.freeze([1, 2, 3])); + return Elixir.ElixirScript.Bootstrap.Functions.__load(Elixir).contains(one,Object.freeze([1, 2, 3])); }),Bootstrap.Core.Patterns.clause([Bootstrap.Core.Patterns.variable()],function(one) { return null; },function(one) { diff --git a/test/translator/try_test.exs b/test/translator/try_test.exs index a53ec60c..eaff9c47 100644 --- a/test/translator/try_test.exs +++ b/test/translator/try_test.exs @@ -62,7 +62,7 @@ defmodule ElixirScript.Translator.Try.Test do },Bootstrap.Core.Patterns.defmatch(Bootstrap.Core.Patterns.clause([Bootstrap.Core.Patterns.variable()],function(x) { return Elixir.ElixirScript.IO.__load(Elixir).puts('Invalid argument given'); },function(x) { - return Bootstrap.Core.Functions.contains(x,Object.freeze([ArgumentError.create(Object.freeze({}))])); + return Elixir.ElixirScript.Bootstrap.Functions.__load(Elixir).contains(x,Object.freeze([ArgumentError.create(Object.freeze({}))])); })),null,null,null) """ From 3c9125b85688c61cf245fbdbb8e86df3e1d84f9a Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Sun, 19 Mar 2017 15:37:02 -0500 Subject: [PATCH 486/860] Implementing more functions in Elixir. Add tests --- lib/elixir_script/translator/kernel/js.ex | 75 +++++++++++++-- lib/elixir_script/translator/rewriter.ex | 12 +-- package.json | 4 +- priv/std_lib/base.ex | 12 ++- priv/std_lib/bitwise.ex | 24 ++--- priv/std_lib/bootstrap/functions.ex | 30 +++--- priv/std_lib/js.ex | 19 +++- priv/std_lib/kernel.ex | 6 +- priv/std_lib/list.ex | 21 ++++- priv/std_lib/map.ex | 6 +- src/javascript/lib/core/functions.js | 110 ---------------------- test/app/spec/bootstrap/functions.spec.js | 28 ++++++ 12 files changed, 179 insertions(+), 168 deletions(-) create mode 100644 test/app/spec/bootstrap/functions.spec.js diff --git a/lib/elixir_script/translator/kernel/js.ex b/lib/elixir_script/translator/kernel/js.ex index af194137..74f9f73a 100644 --- a/lib/elixir_script/translator/kernel/js.ex +++ b/lib/elixir_script/translator/kernel/js.ex @@ -89,6 +89,12 @@ defmodule ElixirScript.Translator.JS do ) end + defp do_translate({:throw, _, [term]}, env) do + Builder.throw_statement( + Translator.translate!(term, env) + ) + end + defp do_translate({:new, _, [module_name, params]}, env) when not is_list(params) do Builder.new_expression( Translator.translate!(module_name, env), @@ -105,21 +111,72 @@ defmodule ElixirScript.Translator.JS do defp do_translate({:update, _, [object, map]}, env) do quoted = quote do - Object.assign(unquote(object), unquote(map)) + JS.Object.assign(unquote(object), unquote(map)) end Translator.translate!(quoted, env) end - defp do_translate({:object, _, [args]}, env) do - args = Enum.map(args, fn - { k, v } when Kernel.is_atom(k) -> - { Atom.to_string(k), v } - pair -> - pair - end) + defp do_translate({:update, _, [object, key, value]}, env) do + Builder.assignment_expression( + :=, + Builder.member_expression( + Translator.translate!(object, env), + Translator.translate!(key, env), + true + ), + Translator.translate!(value, env) + ) + end + + defp do_translate({:import, _, [term]}, env) do + Builder.call_expression( + Builder.identifier("import"), + [Translator.translate!(term, env)] + ) + end + + defp do_translate({:debugger, _, _}, env) do + Builder.debugger_statement() + end + + defp do_translate({:this, _, _}, env) do + Builder.this_expression() + end + + defp do_translate({:__delete__, _, [expr]}, env) do + {result, _} = ElixirScript.Translator.Expression.make_unary_expression(:delete, expr, env) + result + end + + defp do_translate({:__bnot__, _, [expr]}, env) do + {result, _} = ElixirScript.Translator.Expression.make_unary_expression(:"~", expr, env) + result + end + + defp do_translate({:__band__, _, [left, right]}, env) do + {result, _} = ElixirScript.Translator.Expression.make_binary_expression(:&, left, right, env) + result + end + + defp do_translate({:__bor__, _, [left, right]}, env) do + {result, _} = ElixirScript.Translator.Expression.make_binary_expression(:|, left, right, env) + result + end + + defp do_translate({:__bsl__, _, [left, right]}, env) do + {result, _} = ElixirScript.Translator.Expression.make_binary_expression(:"<<", left, right, env) + result + end + + defp do_translate({:__bsr__, _, [left, right]}, env) do + {result, _} = ElixirScript.Translator.Expression.make_binary_expression(:">>", left, right, env) + result + end - Translator.translate!({ :%{}, [], args }, env) + defp do_translate({:__bxor__, _, [left, right]}, env) do + {result, _} = ElixirScript.Translator.Expression.make_binary_expression(:^, left, right, env) + result end defp do_translate({function, _, []}, env) do diff --git a/lib/elixir_script/translator/rewriter.ex b/lib/elixir_script/translator/rewriter.ex index afd1f81b..cd018686 100644 --- a/lib/elixir_script/translator/rewriter.ex +++ b/lib/elixir_script/translator/rewriter.ex @@ -383,10 +383,6 @@ defmodule ElixirScript.Translator.Rewriter do quote do: List.duplicate(unquote(n), unquote(elem)) end - def rewrite({{:., _, [:lists, :mapfoldl]}, _, [fun, acc, list]}) do - quote do: Bootstrap.Core.Functions.mapfoldl(unquote(fun), unquote(acc), unquote(list)) - end - def rewrite({{:., _, [:lists, :sort]}, _, [list]}) do quote do: unquote(list).sort() end @@ -400,10 +396,6 @@ defmodule ElixirScript.Translator.Rewriter do quote do: unquote(list).filter(unquote(pred)) end - def rewrite({{:., _, [:lists, :filtermap]}, _, [fun, list]}) do - quote do: Bootstrap.Core.Functions.filtermap(unquote(fun), unquote(list)) - end - def rewrite({{:., _, [:lists, :concat]}, _, [things]}) do quote do: unquote(things).join("") end @@ -489,7 +481,7 @@ defmodule ElixirScript.Translator.Rewriter do end def rewrite({{:., _, [:maps, :put]}, _, [key, value, map]}) do - quote do: Bootstrap.Core.Functions.add_property_to_map(unquote(map), unquote(key), unquote(value)) + quote do: ElixirScript.Bootstrap.Functions.add_property_to_map(unquote(map), unquote(key), unquote(value)) end def rewrite({{:., _, [:maps, :update]}, _, [key, value, map]}) do @@ -497,7 +489,7 @@ defmodule ElixirScript.Translator.Rewriter do end def rewrite({{:., _, [:maps, :remove]}, _, [key, map]}) do - quote do: Bootstrap.Core.Functions.delete_property_from_map(unquote(map), unquote(key)) + quote do: ElixirScript.Bootstrap.Functions.delete_property_from_map(unquote(map), unquote(key)) end end diff --git a/package.json b/package.json index 10150ccb..bf002ba8 100644 --- a/package.json +++ b/package.json @@ -13,7 +13,7 @@ "clean": "rm -rf priv/build", "test": "mocha src/javascript/tests --recursive --compilers js:babel-core/register", "build:test-app": "mix elixirscript test/app/src/ -f common -o test/app/build/", - "test-app": "yarn run build:test-app && NODE_ENV=test mocha 'test/app/spec/*.spec.js' --compilers js:babel-core/register" + "test-app": "yarn run build:test-app && NODE_ENV=test mocha --recursive 'test/app/spec/**/*.spec.js' --compilers js:babel-core/register" }, "repository": { "type": "git", @@ -48,4 +48,4 @@ "sinon": "^1.17.7", "sinon-chai": "^2.8.0" } -} +} \ No newline at end of file diff --git a/priv/std_lib/base.ex b/priv/std_lib/base.ex index c74e0678..721de66e 100644 --- a/priv/std_lib/base.ex +++ b/priv/std_lib/base.ex @@ -5,8 +5,18 @@ defmodule ElixirScript.Base do ElixirScript.Bootstrap.b64EncodeUnicode(data) end + defp can_decode64(data) do + try do + JS.atob(data) + true + rescue + _ -> + false + end + end + def decode64(data) do - if ElixirScript.Bootstrap.can_decode64(data) do + if can_decode64(data) do {:ok, decode64!(data) } else :error diff --git a/priv/std_lib/bitwise.ex b/priv/std_lib/bitwise.ex index 83d5e1d4..bc92799e 100644 --- a/priv/std_lib/bitwise.ex +++ b/priv/std_lib/bitwise.ex @@ -2,73 +2,73 @@ defmodule ElixirScript.Bitwise do @moduledoc false defmacro bnot(expr) do quote do - Bootstrap.Core.bnot(unquote(expr)) + JS.__bnot__(unquote(expr)) end end defmacro ~~~(expr) do quote do - Bootstrap.Core.bnot(unquote(expr)) + JS.__bnot__(unquote(expr)) end end defmacro band(left, right) do quote do - Bootstrap.Core.band(unquote(left), unquote(right)) + JS.__band__(unquote(left), unquote(right)) end end defmacro left &&& right do quote do - Bootstrap.Core.band(unquote(left), unquote(right)) + JS.__band__(unquote(left), unquote(right)) end end defmacro bor(left, right) do quote do - Bootstrap.Core.bor(unquote(left), unquote(right)) + JS.__bor__(unquote(left), unquote(right)) end end defmacro left ||| right do quote do - Bootstrap.Core.bor(unquote(left), unquote(right)) + JS.__bor__(unquote(left), unquote(right)) end end defmacro bxor(left, right) do quote do - Bootstrap.Core.bxor(unquote(left), unquote(right)) + JS.__bxor__(unquote(left), unquote(right)) end end defmacro left ^^^ right do quote do - Bootstrap.Core.bxor(unquote(left), unquote(right)) + JS.__bxor__(unquote(left), unquote(right)) end end defmacro bsl(left, right) do quote do - Bootstrap.Core.bsl(unquote(left), unquote(right)) + JS.__bsl__(unquote(left), unquote(right)) end end defmacro left <<< right do quote do - Bootstrap.Core.bsl(unquote(left), unquote(right)) + JS.__bsl__(unquote(left), unquote(right)) end end defmacro bsr(left, right) do quote do - Bootstrap.Core.bsr(unquote(left), unquote(right)) + JS.__bsr__(unquote(left), unquote(right)) end end defmacro left >>> right do quote do - Bootstrap.Core.bsr(unquote(left), unquote(right)) + JS.__bsr__(unquote(left), unquote(right)) end end end diff --git a/priv/std_lib/bootstrap/functions.ex b/priv/std_lib/bootstrap/functions.ex index 6d1e225c..cae1efce 100644 --- a/priv/std_lib/bootstrap/functions.ex +++ b/priv/std_lib/bootstrap/functions.ex @@ -8,7 +8,7 @@ defmodule ElixirScript.Bootstrap.Functions do match?(left, right) end - def contains(left, [h|t]) do + def contains(left, [h|t]) do case match?(left, h) do true -> true @@ -40,18 +40,26 @@ defmodule ElixirScript.Bootstrap.Functions do ) end - def can_decode64(data) do - try do - JS.atob(data) - true - rescue - _ -> - false - end - end - def reverse(list) do list.concat([]).reverse() end + def class_to_obj(map) do + JS.Object.assign(JS.new(JS.Object, []), map) + |> JS.Object.freeze + end + +def delete_property_from_map(map, property) do + new_map = JS.Object.assign(JS.Object.create(map.constructor.prototype), map) + JS.delete(new_map[property]) + + JS.Object.freeze(new_map) +end + +def add_property_to_map(map, property, value) do + JS.Object.assign(JS.new(JS.Object, []), map) + |> JS.update(property, value) + |> JS.Object.freeze +end + end diff --git a/priv/std_lib/js.ex b/priv/std_lib/js.ex index c1f44142..d9383a9a 100644 --- a/priv/std_lib/js.ex +++ b/priv/std_lib/js.ex @@ -22,6 +22,14 @@ defmodule JS do """ defmacro update(object, map) + @doc """ + Updates an existing JavaScript object. + + ex: + JS.update elem, "width", 100 + """ + defmacro update(object, key, value) + @doc """ Returns the type of the given value """ @@ -89,11 +97,12 @@ defmodule JS do defmacro yield_to(gen) @doc """ - Provides a convenient way to create a string-based map. + Creates a breakpoint for JavaScript debuggers to stop at + """ + defmacro debugger() - Elixirscript, by default turns the following, `%{a: "b"}` into `{[Symbol.for("a")]: "b"}` in JavaScript. In order to get string keys, - one would have to do `%{"a" => "b"}` which turns into `{a: "b"}` in JavaScript. With `Kernel.object`, you can create string keyed maps - conveniently, `object(a: "b")` which turns into `{a: "b"}` + @doc """ + The current JavaScript context """ - defmacro object(args) + defmacro this() end diff --git a/priv/std_lib/kernel.ex b/priv/std_lib/kernel.ex index f085f075..01cc370a 100644 --- a/priv/std_lib/kernel.ex +++ b/priv/std_lib/kernel.ex @@ -166,10 +166,10 @@ defmodule ElixirScript.Kernel do end end - defmacro match?(left, right) do + defmacro match?(pattern, expr) do quote do - case unquote(right) do - unquote(left) -> + case unquote(expr) do + unquote(pattern) -> true _ -> false diff --git a/priv/std_lib/list.ex b/priv/std_lib/list.ex index 94728a16..156475f7 100644 --- a/priv/std_lib/list.ex +++ b/priv/std_lib/list.ex @@ -242,7 +242,24 @@ defmodule ElixirScript.List do do_keyreplace(tl(list), key, position, updated, new_tuple) end - def zip(list_of_lists) do - Bootstrap.Core.Functions.zip(list_of_lists) + def zip([]) do + [] + end + + def zip(list_of_lists) when is_list(list_of_lists) do + lengths = Enum.map(list_of_lists, fn(list) -> length(list) end) + length = apply(JS.Math, :min, lengths) + do_zip(list_of_lists, 0, length, []) + end + + defp do_zip(list_of_lists, index, length, acc) when index == length do + acc + end + + defp do_zip(list_of_lists, index, length, acc) do + values = Enum.map(list_of_lists, fn(list) -> Enum.at(list, index) end) + item = JS.new(Bootstrap.Core.Tuple, values) + + do_zip(list_of_lists, index + 1, length, acc ++ [item]) end end diff --git a/priv/std_lib/map.ex b/priv/std_lib/map.ex index 2f0c4319..2fca8243 100644 --- a/priv/std_lib/map.ex +++ b/priv/std_lib/map.ex @@ -34,13 +34,13 @@ defmodule ElixirScript.Map do def from_struct(struct) do struct - |> Bootstrap.Core.Functions.class_to_obj + |> ElixirScript.Bootstrap.Functions.class_to_obj |> delete(:__struct__) end def delete(map, key) do map - |> Bootstrap.Core.Functions.delete_property_from_map(key) + |> ElixirScript.Bootstrap.Functions.delete_property_from_map(key) end def equal?(map1, map2) do @@ -123,7 +123,7 @@ defmodule ElixirScript.Map do end def put(map, key, value) do - Bootstrap.Core.Functions.add_property_to_map(map, key, value) + ElixirScript.Bootstrap.Functions.add_property_to_map(map, key, value) end def get(map, key) do diff --git a/src/javascript/lib/core/functions.js b/src/javascript/lib/core/functions.js index 99d3b8ec..e8b9da25 100644 --- a/src/javascript/lib/core/functions.js +++ b/src/javascript/lib/core/functions.js @@ -1,5 +1,4 @@ import Protocol from './protocol'; -import Core from '../core'; function call_property(item, property) { let prop = null; @@ -87,103 +86,6 @@ function defimpl(protocol, type, impl) { protocol.implementation(type, impl); } -function delete_property_from_map(map, property) { - const new_map = Object.assign(Object.create(map.constructor.prototype), map); - delete new_map[property]; - - return Object.freeze(new_map); -} - -function class_to_obj(map) { - const new_map = Object.assign({}, map); - return Object.freeze(new_map); -} - -function add_property_to_map(map, property, value) { - const new_map = Object.assign({}, map); - new_map[property] = value; - return Object.freeze(new_map); -} - -function bnot(expr) { - return ~expr; -} - -function band(left, right) { - return left & right; -} - -function bor(left, right) { - return left | right; -} - -function bsl(left, right) { - return left << right; -} - -function bsr(left, right) { - return left >> right; -} - -function bxor(left, right) { - return left ^ right; -} - -function zip(list_of_lists) { - if (list_of_lists.length === 0) { - return Object.freeze([]); - } - - const new_value = []; - let smallest_length = list_of_lists[0]; - - for (const x of list_of_lists) { - if (x.length < smallest_length) { - smallest_length = x.length; - } - } - - for (let i = 0; i < smallest_length; i++) { - const current_value = []; - for (let j = 0; j < list_of_lists.length; j++) { - current_value.push(list_of_lists[j][i]); - } - - new_value.push(new Core.Tuple(...current_value)); - } - - return Object.freeze(new_value); -} - -function mapfoldl(fun, acc, list) { - const newlist = []; - let new_acc = acc; - - for (const x of list) { - const tup = fun(x, new_acc); - newlist.push(tup.get(0)); - new_acc = tup.get(1); - } - - return new Core.Tuple(Object.freeze(newlist), new_acc); -} - -function filtermap(fun, list) { - const newlist = []; - - for (const x of list) { - const result = fun(x); - - if (result === true) { - newlist.push(x); - } else if (result instanceof Core.Tuple) { - newlist.push(result.get(1)); - } - } - - return Object.freeze(newlist); -} - function build_namespace(ns, ns_string) { let parts = ns_string.split('.'); const root = ns; @@ -214,17 +116,5 @@ export default { defexception, defprotocol, defimpl, - delete_property_from_map, - add_property_to_map, - class_to_obj, - bnot, - band, - bor, - bsl, - bsr, - bxor, - zip, - mapfoldl, - filtermap, build_namespace, }; diff --git a/test/app/spec/bootstrap/functions.spec.js b/test/app/spec/bootstrap/functions.spec.js new file mode 100644 index 00000000..e852b388 --- /dev/null +++ b/test/app/spec/bootstrap/functions.spec.js @@ -0,0 +1,28 @@ +const expect = require('chai').expect; +const Elixir = require('../../build/Elixir.App'); + +describe('Functions', () => { + it('contains', () => { + const Functions = Elixir.load(Elixir.ElixirScript.Bootstrap.Functions); + expect(Functions.contains(1, [])).to.eq(false); + expect(Functions.contains(1, [1, 2, 3])).to.eq(true); + expect(Functions.contains(1, [1])).to.eq(true); + + expect(Functions.contains('apple', [1])).to.eq(false); + }); + + it('get_object_keys', () => { + const Functions = Elixir.load(Elixir.ElixirScript.Bootstrap.Functions); + expect(Functions.get_object_keys({})).to.eql([]); + expect(Functions.get_object_keys({ key: 1 })).to.eql(['key']); + expect( + Functions.get_object_keys({ key: 1, [Symbol.for('hi')]: 2 }), + ).to.eql(['key', Symbol.for('hi')]); + }); + + it('is_valid_character', () => { + const Functions = Elixir.load(Elixir.ElixirScript.Bootstrap.Functions); + expect(Functions.is_valid_character(42)).to.eq(true); + expect(Functions.is_valid_character(NaN)).to.eq(false); + }); +}); From fe9950eafa1850a42960a49a7e6d0032143bce85 Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Sun, 19 Mar 2017 18:55:53 -0500 Subject: [PATCH 487/860] Update implementation of contains --- priv/std_lib/bootstrap/functions.ex | 15 ++++++++++----- test/app/spec/bootstrap/functions.spec.js | 5 +++-- 2 files changed, 13 insertions(+), 7 deletions(-) diff --git a/priv/std_lib/bootstrap/functions.ex b/priv/std_lib/bootstrap/functions.ex index cae1efce..c453e743 100644 --- a/priv/std_lib/bootstrap/functions.ex +++ b/priv/std_lib/bootstrap/functions.ex @@ -5,14 +5,19 @@ defmodule ElixirScript.Bootstrap.Functions do end def contains(left, [right]) do - match?(left, right) + case right do + ^left -> + true + _ -> + false + end end - def contains(left, [h|t]) do - case match?(left, h) do - true -> + def contains(left, [h|t]) do + case h do + ^left -> true - false -> + _ -> contains(left, t) end end diff --git a/test/app/spec/bootstrap/functions.spec.js b/test/app/spec/bootstrap/functions.spec.js index e852b388..2a098233 100644 --- a/test/app/spec/bootstrap/functions.spec.js +++ b/test/app/spec/bootstrap/functions.spec.js @@ -6,8 +6,9 @@ describe('Functions', () => { const Functions = Elixir.load(Elixir.ElixirScript.Bootstrap.Functions); expect(Functions.contains(1, [])).to.eq(false); expect(Functions.contains(1, [1, 2, 3])).to.eq(true); + expect(Functions.contains(4, [1, 2, 3])).to.eq(false); expect(Functions.contains(1, [1])).to.eq(true); - + expect(Functions.contains(4, [1])).to.eq(false); expect(Functions.contains('apple', [1])).to.eq(false); }); @@ -16,7 +17,7 @@ describe('Functions', () => { expect(Functions.get_object_keys({})).to.eql([]); expect(Functions.get_object_keys({ key: 1 })).to.eql(['key']); expect( - Functions.get_object_keys({ key: 1, [Symbol.for('hi')]: 2 }), + Functions.get_object_keys({ key: 1, [Symbol.for('hi')]: 2 }) ).to.eql(['key', Symbol.for('hi')]); }); From 2c90deadad02310b768fe68c9b4ca40775c27b80 Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Mon, 20 Mar 2017 22:15:35 -0500 Subject: [PATCH 488/860] Started adding enum implementation --- lib/elixir_script/translator.ex | 4 + lib/elixir_script/translator/kernel/js.ex | 8 + lib/elixir_script/translator/state.ex | 2 + priv/std_lib/base.ex | 2 +- priv/std_lib/bootstrap/functions.ex | 4 +- priv/std_lib/enum.ex | 289 ++++++++++++++++++++++ priv/std_lib/enum/out_of_bounds_error.ex | 3 + priv/std_lib/enumerable.ex | 4 +- 8 files changed, 311 insertions(+), 5 deletions(-) create mode 100644 priv/std_lib/enum.ex create mode 100644 priv/std_lib/enum/out_of_bounds_error.ex diff --git a/lib/elixir_script/translator.ex b/lib/elixir_script/translator.ex index 8c0ebae1..931ea9b3 100644 --- a/lib/elixir_script/translator.ex +++ b/lib/elixir_script/translator.ex @@ -83,6 +83,10 @@ defmodule ElixirScript.Translator do JSLib.translate_js_function({:__aliases__, context, rest}, function_name, params, env) end + defp do_translate({:__aliases__, context, [:JS | rest]}, env) do + JSLib.translate_js_module({:__aliases__, context, rest}, env) + end + defp do_translate(ast, env) when is_number(ast) or is_binary(ast) or is_boolean(ast) or is_nil(ast) do { Primitive.make_literal(ast), env } end diff --git a/lib/elixir_script/translator/kernel/js.ex b/lib/elixir_script/translator/kernel/js.ex index 74f9f73a..43c1c0d1 100644 --- a/lib/elixir_script/translator/kernel/js.ex +++ b/lib/elixir_script/translator/kernel/js.ex @@ -42,6 +42,14 @@ defmodule ElixirScript.Translator.JS do { do_translate({name, [], params}, env), env } end + def translate_js_module(module, env) do + { do_translate(module, env), env } + end + + defp do_translate({:__aliases__, _, module}, env) do + Identifier.make_namespace_members(module) + end + defp do_translate({op, _, [param]}, env) when op in [:typeof, :delete, :void, :-, :+, :!, :"~"] do Builder.unary_expression( op, diff --git a/lib/elixir_script/translator/state.ex b/lib/elixir_script/translator/state.ex index bcc7b7ff..9f02731f 100644 --- a/lib/elixir_script/translator/state.ex +++ b/lib/elixir_script/translator/state.ex @@ -23,6 +23,8 @@ defmodule ElixirScript.Translator.State do |> Map.put(Collectable, ElixirScript.Collectable) |> Map.put(String.Chars, ElixirScript.String.Chars) |> Map.put(Enumerable, ElixirScript.Enumerable) + |> Map.put(Enum, ElixirScript.Enum) + |> Map.put(Enum.OutOfBoundsError, ElixirScript.Enum.OutOfBoundsError) |> Map.put(Integer, ElixirScript.Integer) |> Map.put(Macro.Env, ElixirScript.Macro.Env) |> Map.put(View, ElixirScript.View) diff --git a/priv/std_lib/base.ex b/priv/std_lib/base.ex index 721de66e..27fcdee9 100644 --- a/priv/std_lib/base.ex +++ b/priv/std_lib/base.ex @@ -2,7 +2,7 @@ defmodule ElixirScript.Base do @moduledoc false def encode64(data) do - ElixirScript.Bootstrap.b64EncodeUnicode(data) + ElixirScript.Bootstrap.Functions.b64EncodeUnicode(data) end defp can_decode64(data) do diff --git a/priv/std_lib/bootstrap/functions.ex b/priv/std_lib/bootstrap/functions.ex index c453e743..e8e0fe93 100644 --- a/priv/std_lib/bootstrap/functions.ex +++ b/priv/std_lib/bootstrap/functions.ex @@ -36,10 +36,10 @@ defmodule ElixirScript.Bootstrap.Functions do end def b64EncodeUnicode(str) do - {:ok, regex} = Regex.compile("%([0-9A-F]{2})", "g") + regex = Regex.compile!("%([0-9A-F]{2})", "g") JS.btoa( - JS.encodeURIComponent(str).replace(regex, fn (match, p1) -> + JS.encodeURIComponent(str).replace(regex, fn (match, p1, _, _) -> JS.String.fromCharCode("0x#{p1}") end) ) diff --git a/priv/std_lib/enum.ex b/priv/std_lib/enum.ex new file mode 100644 index 00000000..a0657478 --- /dev/null +++ b/priv/std_lib/enum.ex @@ -0,0 +1,289 @@ +defmodule ElixirScript.Enum do + + def all?(enumerable, fun \\ fn(x) -> x end) do + {_, acc} = Enumerable.reduce(enumerable, {:cont, true}, fn(item, _) -> + if fun.(item) do + {:cont, true} + else + {:halt, false} + end + end) + + acc + end + + def any?(enumerable, fun \\ fn(x) -> x end) do + {_, acc} = Enumerable.reduce(enumerable, {:cont, true}, fn(item, _) -> + if fun.(item) do + {:halt, true} + else + {:cont, false} + end + end) + + acc + end + + def at(enumerable, n, default \\ nil) do + cond do + n > Enumerable.count(enumerable) -> + default + true -> + result = Enumerable.reduce(enumerable, {:cont, 0}, fn(item, acc) -> + if n == acc do + {:halt, item} + else + {:cont, acc + 1} + end + end) + + case result do + {:cont, _} -> + default + {:halt, item} -> + item + end + end + end + + def concat([enumerable]) do + enumerable + end + + def concat([h | t]) do + h.concat(t) + end + + def count(enumerable) do + {:ok, num} = Enumerable.count(enumerable) + num + end + + def count(enumerable, fun) do + {_, acc} = Enumerable.reduce(enumerable, {:cont, 0}, fn(item, acc) -> + if fun.(item) do + {:cont, acc + 1} + else + {:cont, acc} + end + end) + + acc + end + + def reduce(enumerable, fun) do + {_, result} = Enumerable.reduce(enumerable, {:cont, nil}, fn + item, nil -> + {:cont, {:acc, item}} + item, {:acc, acc} -> + {:cont, {:acc, fun.(item, acc)}} + end) + + result + end + + def reduce(enumerable, acc, fun) do + {_, result} = Enumerable.reduce(enumerable, {:cont, acc}, fn + item, acc -> + {:cont, fun.(item, acc)} + end) + + result + end + + + def map(enumerable, fun) do + reduce(enumerable, [], fn(x, acc) -> + acc ++ fun.(x) + end) + end + + def map_reduce(enumerable, acc, fun) do + reduce(enumerable, {[], acc}, fn(x, {m, acc}) -> + {v, new_acc} = fun.(x, acc) + {m ++ [v], new_acc} + end) + end + + def each(enumerable, fun) do + map(enumerable, fun) + :ok + end + + def empty?(enumerable) do + {:ok, count} = Enumerable.count(enumerable) + count == 0 + end + + def fetch(enumerable, index) do + result = Enumerable.reduce(enumerable, {:cont, 0}, fn(item, acc) -> + if index == acc do + {:halt, {:ok, item}} + else + {:cont, acc + 1} + end + end) + + case result do + {:cont, _} -> + :error + {:halt, item} -> + item + end + end + + def fetch!(enumerable, index) do + case fetch(enumerable, index) do + {:ok, item} -> + item + :error -> + raise Enum.OutOfBoundsError + end + end + + def filter(enumerable, fun) do + reduce(enumerable, [], fn(x, acc) -> + if fun.(x) do + acc ++ [x] + else + acc + end + end) + end + + def filter_map(enumerable, filter, mapper) do + reduce(enumerable, [], fn(x, acc) -> + if filter.(x) do + acc ++ [mapper.(x)] + else + acc + end + end) + end + + def find(enumerable, default \\ nil, fun) do + {_, result} = Enumerable.reduce(enumerable, {:cont, default}, fn(item, acc) -> + if fun.(item) do + {:halt, item} + else + {:cont, default} + end + end) + + result + end + + def member?(enumerable, value) do + {_, result} = Enumerable.reduce(enumerable, {:cont, false}, fn(item, acc) -> + if item == value do + {:halt, true} + else + {:cont, false} + end + end) + + result + end + + def drop(enumerable, count) do + {_, result} = Enumerable.reduce(enumerable, {:cont, {[], 0}}, fn + (item, {taken, drop_count}) -> + if drop_count < count do + {:cont, {[], drop_count + 1 }} + else + {:cont, taken ++ [item]} + end + end) + + result + end + + def drop_while(enumerable, fun) do + {_, result} = Enumerable.reduce(enumerable, {:cont, []}, fn + (item, taken) -> + if fun.(item) do + {:cont, {taken}} + else + {:cont, taken ++ [item]} + end + end) + + result + end + + + def take(enumerable, count) do + if Enumerable.count(enumerable) < count do + enumerable + else + {_, result} = Enumerable.reduce(enumerable, {:cont, {[], 0}}, fn + (item, {taken, taken_count}) -> + if taken_count == count do + {:halt, taken} + else + {:cont, {taken ++ [item], taken_count + 1}} + end + end) + + result + end + end + + def take_every(enumerable, nth) do + {_, {result, _count}} = Enumerable.reduce(enumerable, {:cont, {[], 0}}, fn + (item, {taken, count}) -> + if rem(count, nth) == 0 do + {:cont, {taken ++ [item], count + 1}} + else + {:cont, {taken, count + 1}} + end + end) + + result + end + + def take_while(enumerable, fun) do + {_, result} = Enumerable.reduce(enumerable, {:cont, []}, fn + (item, taken) -> + if fun.(item) do + {:cont, {taken ++ [item]}} + else + {:halt, taken} + end + end) + + result + end + + + def to_list(enumerable) when is_list(enumerable) do + enumerable + end + + def to_list(enumerable) do + map(enumerable, fn x -> x end) + end + + def reverse(enumerable) when is_list(enumerable) do + enumerable.concat([]).reverse() + end + + def reverse(enumerable) do + reduce(enumerable, [], fn(item, acc) -> + [item] ++ acc + end) + end + + def reverse(enumerable, tail) when is_list(enumerable) do + enumerable.concat([]).reverse() ++ tail + end + + def reverse(enumerable, tail) do + result = reduce(enumerable, [], fn(item, acc) -> + [item] ++ acc + end) + + result ++ tail + end + +end \ No newline at end of file diff --git a/priv/std_lib/enum/out_of_bounds_error.ex b/priv/std_lib/enum/out_of_bounds_error.ex new file mode 100644 index 00000000..e8ffb4b2 --- /dev/null +++ b/priv/std_lib/enum/out_of_bounds_error.ex @@ -0,0 +1,3 @@ +defmodule ElixirScript.Enum.OutOfBoundsError do + defexception message: "out of bounds error" +end \ No newline at end of file diff --git a/priv/std_lib/enumerable.ex b/priv/std_lib/enumerable.ex index 0b6d4928..9d7b641d 100644 --- a/priv/std_lib/enumerable.ex +++ b/priv/std_lib/enumerable.ex @@ -7,10 +7,10 @@ end defimpl ElixirScript.Enumerable, for: List do def count(list), - do: length(list) + do: {:ok, length(list) } def member?(list, value), - do: value in list + do: {:ok, value in list } def reduce(_, {:halt, acc}, _fun), do: {:halted, acc} def reduce(list, {:suspend, acc}, fun), do: {:suspended, acc, &reduce(list, &1, fun)} From b452a65c905409c4577c8a53fa6367704f9cb243 Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Tue, 21 Mar 2017 07:38:56 -0500 Subject: [PATCH 489/860] Add more enum functions. Add a way to turn a js iterator to a reducer --- priv/std_lib/enum.ex | 22 ++++++++++++++++++---- priv/std_lib/enumerable.ex | 21 +++++++++------------ src/javascript/lib/core/functions.js | 23 +++++++++++++++++++++++ 3 files changed, 50 insertions(+), 16 deletions(-) diff --git a/priv/std_lib/enum.ex b/priv/std_lib/enum.ex index a0657478..9db72efd 100644 --- a/priv/std_lib/enum.ex +++ b/priv/std_lib/enum.ex @@ -38,9 +38,9 @@ defmodule ElixirScript.Enum do end) case result do - {:cont, _} -> + {:done, _} -> default - {:halt, item} -> + {:halted, item} -> item end end @@ -125,9 +125,9 @@ defmodule ElixirScript.Enum do end) case result do - {:cont, _} -> + {:done, _} -> :error - {:halt, item} -> + {:halted, item} -> item end end @@ -173,6 +173,20 @@ defmodule ElixirScript.Enum do result end + def into(enumerable, collectable) do + {init, fun} = Collectable.into(collectable) + reduce(enumerable, init, fn x, acc -> + fun.(acc, {:cont, x}) + end) + end + + def into(enumerable, collectable, transform) do + {init, fun} = Collectable.into(collectable) + reduce(enumerable, init, fn x, acc -> + fun.(acc, {:cont, transform.(x)}) + end) + end + def member?(enumerable, value) do {_, result} = Enumerable.reduce(enumerable, {:cont, false}, fn(item, acc) -> if item == value do diff --git a/priv/std_lib/enumerable.ex b/priv/std_lib/enumerable.ex index 9d7b641d..889e3f05 100644 --- a/priv/std_lib/enumerable.ex +++ b/priv/std_lib/enumerable.ex @@ -7,24 +7,23 @@ end defimpl ElixirScript.Enumerable, for: List do def count(list), - do: {:ok, length(list) } + do: {:ok, list.length } def member?(list, value), do: {:ok, value in list } - def reduce(_, {:halt, acc}, _fun), do: {:halted, acc} - def reduce(list, {:suspend, acc}, fun), do: {:suspended, acc, &reduce(list, &1, fun)} - def reduce([], {:cont, acc}, _fun), do: {:done, acc} - def reduce([h | t], {:cont, acc}, fun), do: reduce(t, fun.(h, acc), fun) + def reduce(list, acc, fun), do + Bootstrap.Core.Functions.iterator_to_reducer(list, acc, fun) + end end defimpl ElixirScript.Enumerable, for: Map do def count(map) do - {:ok, map_size(map)} + {:ok, map.length} end def member?(map, {key, value}) do - {:ok, match?(^value, Map.get(map, key))} + {:ok, Map.get(map, key) == value } end def member?(_, _) do @@ -32,11 +31,9 @@ defimpl ElixirScript.Enumerable, for: Map do end def reduce(map, acc, fun) do + map + |> Map.to_list + |> Bootstrap.Core.Functions.iterator_to_reducer(acc, fun) do_reduce(Map.to_list(map), acc, fun) end - - defp do_reduce(_, {:halt, acc}, _fun), do: {:halted, acc} - defp do_reduce(list, {:suspend, acc}, fun), do: {:suspended, acc, &do_reduce(list, &1, fun)} - defp do_reduce([], {:cont, acc}, _fun), do: {:done, acc} - defp do_reduce([h | t], {:cont, acc}, fun), do: do_reduce(t, fun.(h, acc), fun) end diff --git a/src/javascript/lib/core/functions.js b/src/javascript/lib/core/functions.js index e8b9da25..52a34def 100644 --- a/src/javascript/lib/core/functions.js +++ b/src/javascript/lib/core/functions.js @@ -1,4 +1,26 @@ import Protocol from './protocol'; +import Core from '../core'; + +function iterator_to_reducer(iterable, acc, fun) { + const iterator = iterable[Symbol.iterator](); + let x = iterator.next(); + let _acc = acc; + + while (x.done === false) { + _acc = fun(x.value, _acc.get(1)); + if (_acc.get(0) === Symbol.for('halt')) { + return new Core.Tuple(Symbol.for('halted'), _acc.get(1)); + } else if (_acc.get(0) === Symbol.for('suspend')) { + return new Core.Tuple(Symbol.for('suspended'), _acc.get(1), new_acc => { + return iterator_to_reducer(iterator, new_acc, fun); + }); + } + + x = iterator.next(); + } + + return new Core.Tuple(Symbol.for('done'), _acc.get(1)); +} function call_property(item, property) { let prop = null; @@ -117,4 +139,5 @@ export default { defprotocol, defimpl, build_namespace, + iterator_to_reducer, }; From acd383fe7073bc0419549fa050f007ae94ce38e2 Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Tue, 21 Mar 2017 07:39:42 -0500 Subject: [PATCH 490/860] Fix incorrect boolean in while statement --- src/javascript/lib/core/functions.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/javascript/lib/core/functions.js b/src/javascript/lib/core/functions.js index 52a34def..1d534464 100644 --- a/src/javascript/lib/core/functions.js +++ b/src/javascript/lib/core/functions.js @@ -6,7 +6,7 @@ function iterator_to_reducer(iterable, acc, fun) { let x = iterator.next(); let _acc = acc; - while (x.done === false) { + while (x.done !== false) { _acc = fun(x.value, _acc.get(1)); if (_acc.get(0) === Symbol.for('halt')) { return new Core.Tuple(Symbol.for('halted'), _acc.get(1)); From f40fc2c7940f20b23f576483351a007d00289a9f Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Tue, 21 Mar 2017 07:40:35 -0500 Subject: [PATCH 491/860] Remove enum.js --- src/javascript/elixir.js | 2 - src/javascript/lib/enum.js | 203 ------------------------------------- 2 files changed, 205 deletions(-) delete mode 100644 src/javascript/lib/enum.js diff --git a/src/javascript/elixir.js b/src/javascript/elixir.js index 1972ade5..3f58d0a3 100644 --- a/src/javascript/elixir.js +++ b/src/javascript/elixir.js @@ -1,7 +1,5 @@ import Core from './lib/core'; -import Enum from './lib/enum'; export default { Core, - Enum }; diff --git a/src/javascript/lib/enum.js b/src/javascript/lib/enum.js deleted file mode 100644 index 13916e50..00000000 --- a/src/javascript/lib/enum.js +++ /dev/null @@ -1,203 +0,0 @@ -import Core from './core'; - -let Enum = { - - all__qmark__: function(collection, fun = (x) => x){ - for(let elem of collection){ - if(!fun(elem)){ - return false; - } - } - - return true; - }, - - any__qmark__: function(collection, fun = (x) => x){ - for(let elem of collection){ - if(fun(elem)){ - return true; - } - } - - return false; - }, - - at: function(collection, n, the_default = null){ - if(n > this.count(collection) || n < 0){ - return the_default; - } - - return collection[n]; - }, - - concat: function(...enumables){ - return enumables[0].concat(enumables[1]); - }, - - count: function(collection, fun = null){ - if(fun == null){ - return collection.length; - } else { - return collection.filter(fun).length; - } - }, - - drop: function(collection, count){ - return collection.slice(count); - }, - - drop_while: function(collection, fun){ - let count = 0; - - for(let elem of collection){ - if(fun(elem)){ - count = count + 1; - }else{ - break; - } - } - - return collection.slice(count); - }, - - each: function(collection, fun){ - for(let elem of collection){ - fun(elem); - } - }, - - empty__qmark__: function(collection){ - return collection.length === 0; - }, - - fetch: function(collection, n){ - if(Array.isArray(collection)){ - if(n < this.count(collection) && n >= 0){ - return new Core.Tuple(Symbol.for("ok"), collection[n]); - }else{ - return Symbol.for("error"); - } - } - - throw new Error("collection is not an Enumerable"); - }, - - fetch__emark__: function(collection, n){ - if(Array.isArray(collection)){ - if(n < this.count(collection) && n >= 0){ - return collection[n]; - }else{ - throw new Error("out of bounds error"); - } - } - - throw new Error("collection is not an Enumerable"); - }, - - filter: function(collection, fun){ - let result = []; - - for(let elem of collection){ - if(fun(elem)){ - result.push(elem); - } - } - - return result; - }, - - filter_map: function(collection, filter, mapper){ - return Enum.map(Enum.filter(collection, filter), mapper); - }, - - find: function(collection, if_none = null, fun){ - for(let elem of collection){ - if(fun(elem)){ - return elem; - } - } - - return if_none; - }, - - into: function(collection, list){ - return list.concat(collection); - }, - - map: function(collection, fun){ - let result = []; - - for(let elem of collection){ - result.push(fun(elem)); - } - - return result; - }, - - map_reduce: function(collection, acc, fun){ - let mapped = Object.freeze([]); - let the_acc = acc; - - for (var i = 0; i < this.count(collection); i++) { - let tuple = fun(collection[i], the_acc); - - the_acc = tuple.get(1); - mapped = Object.freeze(mapped.concat([tuple.get(0)])); - } - - return new Core.Tuple(mapped, the_acc); - }, - - member__qmark__: function(collection, value){ - return collection.includes(value); - }, - - reduce: function(collection, acc, fun){ - let the_acc = acc; - - for (var i = 0; i < this.count(collection); i++) { - let tuple = fun(collection[i], the_acc); - - the_acc = tuple.get(1); - } - - return the_acc; - }, - - take: function(collection, count){ - return collection.slice(0, count); - }, - - take_every: function(collection, nth){ - let result = []; - let index = 0; - - for(let elem of collection){ - if(index % nth === 0){ - result.push(elem); - } - } - - return Object.freeze(result); - }, - - take_while: function(collection, fun){ - let count = 0; - - for(let elem of collection){ - if(fun(elem)){ - count = count + 1; - }else{ - break; - } - } - - return collection.slice(0, count); - }, - - to_list: function(collection){ - return collection; - } -}; - -export default Enum; From 4692ceefecae1c29018997d0042650417d7a9987 Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Tue, 21 Mar 2017 20:17:45 -0500 Subject: [PATCH 492/860] Add tests for Enum module --- lib/elixir_script/translator.ex | 4 - .../translator/pattern_matching.ex | 4 - priv/std_lib/enum.ex | 72 ++++++++++---- priv/std_lib/enumerable.ex | 3 +- priv/std_lib/kernel.ex | 2 +- src/javascript/lib/core/functions.js | 2 +- test/app/spec/enum.spec.js | 94 +++++++++++++++++++ test/translator/kernel_test.exs | 2 +- 8 files changed, 151 insertions(+), 32 deletions(-) create mode 100644 test/app/spec/enum.spec.js diff --git a/lib/elixir_script/translator.ex b/lib/elixir_script/translator.ex index 931ea9b3..10657ef3 100644 --- a/lib/elixir_script/translator.ex +++ b/lib/elixir_script/translator.ex @@ -344,10 +344,6 @@ defmodule ElixirScript.Translator do end end - defp do_translate({:_, _, _}, env) do - { Identifier.make_identifier(:undefined), env } - end - defp do_translate({:__aliases__, _, aliases} = ast, env) do module_name = create_module_name2(ast, env) case module_name do diff --git a/lib/elixir_script/translator/pattern_matching.ex b/lib/elixir_script/translator/pattern_matching.ex index 241b7f45..01abe0b7 100644 --- a/lib/elixir_script/translator/pattern_matching.ex +++ b/lib/elixir_script/translator/pattern_matching.ex @@ -154,10 +154,6 @@ defmodule ElixirScript.Translator.PatternMatching do { [bound(Translator.translate!(value, env))], [nil] } end - defp do_build_match({:_, _, _}, _) do - { [wildcard()], [JS.identifier(:undefined)] } - end - defp do_build_match({:<<>>, _, elements}, env) do params = Enum.reduce(elements, [], fn ({:::, _, [{ variable, _, params }, _]}, state) when is_atom(params) -> diff --git a/priv/std_lib/enum.ex b/priv/std_lib/enum.ex index 9db72efd..caa29e54 100644 --- a/priv/std_lib/enum.ex +++ b/priv/std_lib/enum.ex @@ -25,32 +25,46 @@ defmodule ElixirScript.Enum do end def at(enumerable, n, default \\ nil) do - cond do - n > Enumerable.count(enumerable) -> + index = if n < 0 do + {_, count} = Enumerable.count(enumerable) + count + n + else + n + end + + result = Enumerable.reduce(enumerable, {:cont, 0}, fn(item, acc) -> + if index == acc do + {:halt, item} + else + {:cont, acc + 1} + end + end) + + case result do + {:done, _} -> default - true -> - result = Enumerable.reduce(enumerable, {:cont, 0}, fn(item, acc) -> - if n == acc do - {:halt, item} - else - {:cont, acc + 1} - end - end) + {:halted, item} -> + item + end + end - case result do - {:done, _} -> - default - {:halted, item} -> - item - end - end + def concat([]) do + [] end def concat([enumerable]) do enumerable end + def concat([h, t]) do + h.concat(t) + end + def concat([h | t]) do + h.concat(concat(t)) + end + + def concat(h, t) do h.concat(t) end @@ -199,19 +213,39 @@ defmodule ElixirScript.Enum do result end + def drop(enumerable, count) when count < 0 do + enumerable + |> reverse + |> drop(abs(count)) + |> reverse + end + def drop(enumerable, count) do - {_, result} = Enumerable.reduce(enumerable, {:cont, {[], 0}}, fn + {_, {result, _}} = Enumerable.reduce(enumerable, {:cont, {[], 0}}, fn (item, {taken, drop_count}) -> if drop_count < count do {:cont, {[], drop_count + 1 }} else - {:cont, taken ++ [item]} + {:cont, {taken ++ [item], drop_count}} end end) result end + def drop_every(enumerable, nth) do + {_, {result, _count}} = Enumerable.reduce(enumerable, {:cont, {[], 0}}, fn + (item, {taken, count}) -> + if rem(count, nth) == 0 do + {:cont, {taken, count + 1}} + else + {:cont, {taken ++ [item], count + 1}} + end + end) + + result + end + def drop_while(enumerable, fun) do {_, result} = Enumerable.reduce(enumerable, {:cont, []}, fn (item, taken) -> diff --git a/priv/std_lib/enumerable.ex b/priv/std_lib/enumerable.ex index 889e3f05..b9ff8e7a 100644 --- a/priv/std_lib/enumerable.ex +++ b/priv/std_lib/enumerable.ex @@ -12,7 +12,7 @@ defimpl ElixirScript.Enumerable, for: List do def member?(list, value), do: {:ok, value in list } - def reduce(list, acc, fun), do + def reduce(list, acc, fun) do Bootstrap.Core.Functions.iterator_to_reducer(list, acc, fun) end end @@ -34,6 +34,5 @@ defimpl ElixirScript.Enumerable, for: Map do map |> Map.to_list |> Bootstrap.Core.Functions.iterator_to_reducer(acc, fun) - do_reduce(Map.to_list(map), acc, fun) end end diff --git a/priv/std_lib/kernel.ex b/priv/std_lib/kernel.ex index 01cc370a..1bc4dbe4 100644 --- a/priv/std_lib/kernel.ex +++ b/priv/std_lib/kernel.ex @@ -152,7 +152,7 @@ defmodule ElixirScript.Kernel do end def elem(tuple, index) do - apply(tuple, :get, [index]) + tuple.get(index) end def is_nil(term) do diff --git a/src/javascript/lib/core/functions.js b/src/javascript/lib/core/functions.js index 1d534464..52a34def 100644 --- a/src/javascript/lib/core/functions.js +++ b/src/javascript/lib/core/functions.js @@ -6,7 +6,7 @@ function iterator_to_reducer(iterable, acc, fun) { let x = iterator.next(); let _acc = acc; - while (x.done !== false) { + while (x.done === false) { _acc = fun(x.value, _acc.get(1)); if (_acc.get(0) === Symbol.for('halt')) { return new Core.Tuple(Symbol.for('halted'), _acc.get(1)); diff --git a/test/app/spec/enum.spec.js b/test/app/spec/enum.spec.js new file mode 100644 index 00000000..bbf1757a --- /dev/null +++ b/test/app/spec/enum.spec.js @@ -0,0 +1,94 @@ +const expect = require('chai').expect; +const Elixir = require('../build/Elixir.App'); + +const Enum = Elixir.load(Elixir.ElixirScript.Enum); + +describe('Enum', () => { + it('all?/2', () => { + expect(Enum.all__qmark__([2, 4, 6], x => x % 2 === 0)).to.eql(true); + expect(Enum.all__qmark__([2, 3, 4], x => x % 2 === 0)).to.eql(false); + }); + + it('any?/2', () => { + expect(Enum.any__qmark__([2, 4, 6], x => x % 2 === 1)).to.eql(false); + expect(Enum.any__qmark__([2, 3, 4], x => x % 2 === 1)).to.eql(true); + }); + + it('at/3', () => { + expect(Enum.at([2, 4, 6], 0)).to.eql(2); + expect(Enum.at([2, 4, 6], 2)).to.eql(6); + expect(Enum.at([2, 4, 6], 4)).to.eql(null); + expect(Enum.at([2, 4, 6], 4, Symbol.for('none'))).to.eql( + Symbol.for('none'), + ); + + expect(Enum.at([2, 4, 6], -2)).to.eql(4); + expect(Enum.at([2, 4, 6], -4)).to.eql(null); + }); + + it('concat/1', () => { + expect(Enum.concat([[1, [2], 3], [4], [5, 6]])).to.eql([ + 1, + [2], + 3, + 4, + 5, + 6, + ]); + expect(Enum.concat([[], []])).to.eql([]); + expect(Enum.concat([[]])).to.eql([]); + expect(Enum.concat([])).to.eql([]); + }); + + it('concat/2', () => { + expect(Enum.concat([], [1])).to.eql([1]); + expect(Enum.concat([1, [2], 3], [4, 5])).to.eql([1, [2], 3, 4, 5]); + expect(Enum.concat([], [])).to.eql([]); + }); + + it('count/1', () => { + expect(Enum.count([1, 2, 3])).to.eql(3); + expect(Enum.count([])).to.eql(0); + expect(Enum.count([1, true, false, null])).to.eql(4); + }); + + it('count/2', () => { + expect(Enum.count([1, 2, 3], x => x % 2 === 0)).to.eql(1); + expect(Enum.count([], x => x % 2 === 0)).to.eql(0); + expect(Enum.count([1, true, false, null], x => x)).to.eql(2); + }); + + it('drop/2', () => { + expect(Enum.drop([1, 2, 3], 0)).to.eql([1, 2, 3]); + expect(Enum.drop([1, 2, 3], 1)).to.eql([2, 3]); + expect(Enum.drop([1, 2, 3], 2)).to.eql([3]); + expect(Enum.drop([1, 2, 3], 3)).to.eql([]); + expect(Enum.drop([1, 2, 3], 4)).to.eql([]); + expect(Enum.drop([1, 2, 3], -1)).to.eql([1, 2]); + expect(Enum.drop([1, 2, 3], -2)).to.eql([1]); + expect(Enum.drop([1, 2, 3], -4)).to.eql([]); + }); + + it('drop_every/2', () => { + expect(Enum.drop_every([1, 2, 3, 4, 5, 6, 7, 8, 9, 10], 2)).to.eql([ + 2, + 4, + 6, + 8, + 10, + ]); + + expect(Enum.drop_every([1, 2, 3, 4, 5, 6, 7, 8, 9, 10], 3)).to.eql([ + 2, + 3, + 5, + 6, + 8, + 9, + ]); + + expect(Enum.drop_every([], 2)).to.eql([]); + expect(Enum.drop_every([1, 2], 2)).to.eql([2]); + expect(Enum.drop_every([1, 2, 3], 0)).to.eql([1, 2, 3]); + }); +}); diff --git a/test/translator/kernel_test.exs b/test/translator/kernel_test.exs index d0041050..7c645f73 100644 --- a/test/translator/kernel_test.exs +++ b/test/translator/kernel_test.exs @@ -54,7 +54,7 @@ defmodule ElixirScript.Translator.Kernel.Test do end js_code = """ - Elixir.ElixirScript.Kernel.__load(Elixir).apply(Enum, Symbol.for('reverse'), Object.freeze([Object.freeze([1, 2, 3])])) + Elixir.ElixirScript.Kernel.__load(Elixir).apply(Elixir.ElixirScript.Enum, Symbol.for('reverse'), Object.freeze([Object.freeze([1, 2, 3])])) """ assert_translation(ex_ast, js_code) From 4864fe43199d8e8b0c1e311f7434f77640afa238 Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Wed, 22 Mar 2017 04:40:44 -0500 Subject: [PATCH 493/860] Update wildcard translation --- .../translator/kernel/special_forms/fn.ex | 1 + .../translator/pattern_matching.ex | 4 + priv/std_lib/enum.ex | 26 ++++-- src/javascript/tests/case.spec.js | 40 +++++---- src/javascript/tests/cond.spec.js | 24 ++--- src/javascript/tests/for.spec.js | 86 +++++++++--------- src/javascript/tests/try.spec.js | 40 +++++---- src/javascript/tests/with.spec.js | 89 ++++++++++--------- test/app/spec/enum.spec.js | 18 ++++ test/translator/case_test.exs | 8 +- test/translator/function_test.exs | 8 +- test/translator/list_test.exs | 2 +- test/translator/match_test.exs | 12 +-- test/translator/pattern_matching_test.exs | 2 +- test/translator/try_test.exs | 2 +- 15 files changed, 206 insertions(+), 156 deletions(-) diff --git a/lib/elixir_script/translator/kernel/special_forms/fn.ex b/lib/elixir_script/translator/kernel/special_forms/fn.ex index ffd6329a..4a8b9736 100644 --- a/lib/elixir_script/translator/kernel/special_forms/fn.ex +++ b/lib/elixir_script/translator/kernel/special_forms/fn.ex @@ -136,6 +136,7 @@ defmodule ElixirScript.Translator.Function do end defp make_function_clause(patterns, params, body, guard_body, is_generator?) do + params = Enum.filter(params, fn(x) -> is_nil(x) == false end) arguments = case guard_body do nil -> diff --git a/lib/elixir_script/translator/pattern_matching.ex b/lib/elixir_script/translator/pattern_matching.ex index 01abe0b7..e90c59e5 100644 --- a/lib/elixir_script/translator/pattern_matching.ex +++ b/lib/elixir_script/translator/pattern_matching.ex @@ -154,6 +154,10 @@ defmodule ElixirScript.Translator.PatternMatching do { [bound(Translator.translate!(value, env))], [nil] } end + defp do_build_match({:_, _, _}, _) do + { [parameter()], [JS.identifier(:__ignored__)] } + end + defp do_build_match({:<<>>, _, elements}, env) do params = Enum.reduce(elements, [], fn ({:::, _, [{ variable, _, params }, _]}, state) when is_atom(params) -> diff --git a/priv/std_lib/enum.ex b/priv/std_lib/enum.ex index caa29e54..28bb4848 100644 --- a/priv/std_lib/enum.ex +++ b/priv/std_lib/enum.ex @@ -9,6 +9,8 @@ defmodule ElixirScript.Enum do end end) + IO.inspect acc + acc end @@ -247,18 +249,32 @@ defmodule ElixirScript.Enum do end def drop_while(enumerable, fun) do - {_, result} = Enumerable.reduce(enumerable, {:cont, []}, fn - (item, taken) -> + {_, result} = Enumerable.reduce(enumerable, {:cont, :dropping}, fn + (item, :dropping) -> if fun.(item) do - {:cont, {taken}} + {:cont, :dropping} else - {:cont, taken ++ [item]} + {:cont, [item]} end + + (item, taken) -> + {:cont, taken ++ [item]} end) - result + case result do + :dropping -> + [] + :done -> + [] + _ -> + result + end end + def empty?(enumerable) do + {:ok, count} = Enumerable.count(enumerable) + count == 0 + end def take(enumerable, count) do if Enumerable.count(enumerable) < count do diff --git a/src/javascript/tests/case.spec.js b/src/javascript/tests/case.spec.js index 963c8f0a..9dc4e43e 100644 --- a/src/javascript/tests/case.spec.js +++ b/src/javascript/tests/case.spec.js @@ -1,32 +1,36 @@ -import Core from "../lib/core"; +import Core from '../lib/core'; +import chai from 'chai'; const Patterns = Core.Patterns; const SpecialForms = Core.SpecialForms; const Tuple = Core.Tuple; -import Enum from "../lib/enum"; - -import chai from 'chai'; -var expect = chai.expect; - +const expect = chai.expect; describe('case', () => { - it('case', () => { - let clauses = [ + const clauses = [ Patterns.clause( - [new Tuple(Symbol.for("selector"), Patterns.variable(), Patterns.variable())], - function(i, value){ return value; }, - function(i){ return Kernel.is_integer(i); } + [ + new Tuple( + Symbol.for('selector'), + Patterns.variable(), + Patterns.variable(), + ), + ], + (i, value) => { + return value; + }, + i => { + return Kernel.is_integer(i); + }, ), - Patterns.clause( - [Patterns.variable()], - function(value){ return value; } - ) + Patterns.clause([Patterns.variable()], value => { + return value; + }), ]; - let result = SpecialForms._case("thing", clauses); + const result = SpecialForms._case('thing', clauses); - expect(result).to.equal("thing"); + expect(result).to.equal('thing'); }); - }); diff --git a/src/javascript/tests/cond.spec.js b/src/javascript/tests/cond.spec.js index 2fea8baa..3e16ad18 100644 --- a/src/javascript/tests/cond.spec.js +++ b/src/javascript/tests/cond.spec.js @@ -1,25 +1,19 @@ -import Core from "../lib/core"; -const Patterns = Core.Patterns; -const SpecialForms = Core.SpecialForms; - -import Enum from "../lib/enum"; - import chai from 'chai'; -var expect = chai.expect; +import Core from '../lib/core'; +const SpecialForms = Core.SpecialForms; +const expect = chai.expect; describe('cond', () => { - it('cond', () => { - let clauses = [ - [ 1 + 1 == 1, () => "This will never match"], - [ 2 * 2 != 4, () => "Nor this"], - [ true, () => "This will"], + const clauses = [ + [1 + 1 === 1, () => 'This will never match'], + [2 * 2 !== 4, () => 'Nor this'], + [true, () => 'This will'], ]; - let result = SpecialForms.cond(clauses); + const result = SpecialForms.cond(clauses); - expect(result).to.equal("This will"); + expect(result).to.equal('This will'); }); - }); diff --git a/src/javascript/tests/for.spec.js b/src/javascript/tests/for.spec.js index f872d649..d43cf9d4 100644 --- a/src/javascript/tests/for.spec.js +++ b/src/javascript/tests/for.spec.js @@ -1,13 +1,11 @@ -import Core from "../lib/core"; +import Core from '../lib/core'; +import chai from 'chai'; const Patterns = Core.Patterns; const SpecialForms = Core.SpecialForms; const Tuple = Core.Tuple; const BitString = Core.BitString; -import Enum from "../lib/enum"; - -import chai from "chai"; -var expect = chai.expect; +const expect = chai.expect; const $ = Patterns.variable(); @@ -18,84 +16,84 @@ const collectable = { [ $, Patterns.type(Tuple, { - values: [Symbol.for("cont"), Patterns.variable()] - }) + values: [Symbol.for('cont'), Patterns.variable()], + }), ], - (list, x) => list.concat([x]) + (list, x) => list.concat([x]), ), - Patterns.clause([$, Symbol.for("done")], list => list) + Patterns.clause([$, Symbol.for('done')], list => list), ); return new Tuple([], fun); - } + }, }; -describe("for", () => { - it("simple for", () => { - let gen = Patterns.list_generator($, [1, 2, 3, 4]); - let result = SpecialForms._for( +describe('for', () => { + it('simple for', () => { + const gen = Patterns.list_generator($, [1, 2, 3, 4]); + const result = SpecialForms._for( Patterns.clause([$], x => x * 2), [gen], - collectable + collectable, ); expect(result).to.eql([2, 4, 6, 8]); }); - it("for with multiple generators", () => { + it('for with multiple generators', () => { //for x <- [1, 2], y <- [2, 3], do: x*y - let gen = Patterns.list_generator($, [1, 2]); - let gen2 = Patterns.list_generator($, [2, 3]); - let result = SpecialForms._for( + const gen = Patterns.list_generator($, [1, 2]); + const gen2 = Patterns.list_generator($, [2, 3]); + const result = SpecialForms._for( Patterns.clause([$, $], (x, y) => x * y), [gen, gen2], - collectable + collectable, ); expect(result).to.eql([2, 3, 4, 6]); }); - it("for with filter", () => { + it('for with filter', () => { //for n <- [1, 2, 3, 4, 5, 6], rem(n, 2) == 0, do: n - let gen = Patterns.list_generator($, [1, 2, 3, 4, 5, 6]); - let result = SpecialForms._for( + const gen = Patterns.list_generator($, [1, 2, 3, 4, 5, 6]); + const result = SpecialForms._for( Patterns.clause([$], x => x, x => x % 2 === 0), [gen], - collectable + collectable, ); expect(result).to.eql([2, 4, 6]); }); - it("for with pattern matching", () => { + it('for with pattern matching', () => { //for {:user, name} <- [user: "john", admin: "john", user: "meg"], do // String.upcase(name) //end - let gen = Patterns.list_generator([Symbol.for("user"), $], [ - [Symbol.for("user"), "john"], - [Symbol.for("admin"), "john"], - [Symbol.for("user"), "meg"] + const gen = Patterns.list_generator([Symbol.for('user'), $], [ + [Symbol.for('user'), 'john'], + [Symbol.for('admin'), 'john'], + [Symbol.for('user'), 'meg'], ]); - let result = SpecialForms._for( - Patterns.clause([[Symbol.for("user"), $]], name => name.toUpperCase()), + const result = SpecialForms._for( + Patterns.clause([[Symbol.for('user'), $]], name => name.toUpperCase()), [gen], - collectable + collectable, ); - expect(result).to.eql(["JOHN", "MEG"]); + expect(result).to.eql(['JOHN', 'MEG']); }); - it("for with bitstring", () => { + it('for with bitstring', () => { //for <> >>, do: {r, g, b} - let gen = Patterns.bitstring_generator( + const gen = Patterns.bitstring_generator( Patterns.bitStringMatch( BitString.integer({ value: $ }), BitString.integer({ value: $ }), - BitString.integer({ value: $ }) + BitString.integer({ value: $ }), ), new BitString( BitString.integer(213), @@ -109,28 +107,28 @@ describe("for", () => { BitString.integer(0), BitString.integer(234), BitString.integer(32), - BitString.integer(15) - ) + BitString.integer(15), + ), ); - let expression = Patterns.clause( + const expression = Patterns.clause( [ Patterns.bitStringMatch( BitString.integer({ value: $ }), BitString.integer({ value: $ }), - BitString.integer({ value: $ }) - ) + BitString.integer({ value: $ }), + ), ], - (r, g, b) => new Tuple(r, g, b) + (r, g, b) => new Tuple(r, g, b), ); - let result = SpecialForms._for(expression, [gen], collectable); + const result = SpecialForms._for(expression, [gen], collectable); expect(result).to.eql([ new Tuple(213, 45, 132), new Tuple(64, 76, 32), new Tuple(76, 0, 0), - new Tuple(234, 32, 15) + new Tuple(234, 32, 15), ]); }); }); diff --git a/src/javascript/tests/try.spec.js b/src/javascript/tests/try.spec.js index d4b7cf60..b5d9c658 100644 --- a/src/javascript/tests/try.spec.js +++ b/src/javascript/tests/try.spec.js @@ -1,15 +1,11 @@ -import Core from "../lib/core"; +import Core from '../lib/core'; const Patterns = Core.Patterns; const SpecialForms = Core.SpecialForms; -import Enum from "../lib/enum"; - import chai from 'chai'; -var expect = chai.expect; - +const expect = chai.expect; describe('try', () => { - it('try', () => { /* try do @@ -23,19 +19,31 @@ describe('try', () => { */ - let x = 1; + const x = 1; - let value = SpecialForms._try(function() { + const value = SpecialForms._try( + () => { return 1 / x; - }, null, null, Patterns.defmatch(Patterns.clause([Patterns.variable()], function(y) { - return Symbol.for('small'); - }, function(y) { - return (y < 1) && (y > -1); - }), Patterns.clause([Patterns.wildcard()], function() { - return Symbol.for('large'); - })), null); + }, + null, + null, + Patterns.defmatch( + Patterns.clause( + [Patterns.variable()], + y => { + return Symbol.for('small'); + }, + y => { + return y < 1 && y > -1; + }, + ), + Patterns.clause([Patterns.wildcard()], () => { + return Symbol.for('large'); + }), + ), + null, + ); expect(value).to.equal(Symbol.for('large')); }); - }); diff --git a/src/javascript/tests/with.spec.js b/src/javascript/tests/with.spec.js index 70f5c233..9d5a6609 100644 --- a/src/javascript/tests/with.spec.js +++ b/src/javascript/tests/with.spec.js @@ -1,18 +1,16 @@ -import Core from "../lib/core"; +import Core from '../lib/core'; +import chai from 'chai'; const Patterns = Core.Patterns; const SpecialForms = Core.SpecialForms; const Tuple = Core.Tuple; const MatchError = Core.Patterns.MatchError; -import Enum from "../lib/enum"; - -import chai from 'chai'; -var expect = chai.expect; +const expect = chai.expect; const $ = Patterns.variable(); -function map_fetch(map, key){ - if(key in map){ +function map_fetch(map, key) { + if (key in map) { return new Tuple(Symbol.for('ok'), map[key]); } @@ -20,7 +18,6 @@ function map_fetch(map, key){ } describe('with', () => { - it('normal', () => { /* opts = %{width: 10, height: 15} @@ -32,18 +29,17 @@ describe('with', () => { {:ok, 150} */ - let opts = { width: 10, height: 15 }; + const opts = { width: 10, height: 15 }; - let value = SpecialForms._with( - [new Tuple(Symbol.for('ok'), $), () => map_fetch(opts, "width")], - [new Tuple(Symbol.for('ok'), $), (width) => map_fetch(opts, "height")], - (width, height) => new Tuple(Symbol.for('ok'), width * height) + const value = SpecialForms._with( + [new Tuple(Symbol.for('ok'), $), () => map_fetch(opts, 'width')], + [new Tuple(Symbol.for('ok'), $), width => map_fetch(opts, 'height')], + (width, height) => new Tuple(Symbol.for('ok'), width * height), ); expect(value).to.eql(new Tuple(Symbol.for('ok'), 150)); }); - it('without match', () => { /* opts = %{width: 10} @@ -55,18 +51,17 @@ describe('with', () => { :error */ - let opts = { width: 10 }; + const opts = { width: 10 }; - let value = SpecialForms._with( - [new Tuple(Symbol.for('ok'), $), () => map_fetch(opts, "width")], - [new Tuple(Symbol.for('ok'), $), (width) => map_fetch(opts, "height")], - (width, height) => new Tuple(Symbol.for('ok'), width * height) + const value = SpecialForms._with( + [new Tuple(Symbol.for('ok'), $), () => map_fetch(opts, 'width')], + [new Tuple(Symbol.for('ok'), $), width => map_fetch(opts, 'height')], + (width, height) => new Tuple(Symbol.for('ok'), width * height), ); expect(value).to.eql(Symbol.for('error')); }); - it('bare expression', () => { /* opts = %{width: 10} @@ -79,19 +74,22 @@ describe('with', () => { {:ok, 300} */ - let opts = { width: 10, height: 15 }; - - let value = SpecialForms._with( - [new Tuple(Symbol.for('ok'), $), () => map_fetch(opts, "width")], - [$, (width) => width * 2], - [new Tuple(Symbol.for('ok'), $), (width, double_width) => map_fetch(opts, "height")], - (width, double_width, height) => new Tuple(Symbol.for('ok'), double_width * height) + const opts = { width: 10, height: 15 }; + + const value = SpecialForms._with( + [new Tuple(Symbol.for('ok'), $), () => map_fetch(opts, 'width')], + [$, width => width * 2], + [ + new Tuple(Symbol.for('ok'), $), + (width, double_width) => map_fetch(opts, 'height'), + ], + (width, double_width, height) => + new Tuple(Symbol.for('ok'), double_width * height), ); expect(value).to.eql(new Tuple(Symbol.for('ok'), 300)); }); - it('with else', () => { /* opts = %{width: 10} @@ -106,18 +104,24 @@ describe('with', () => { {:error, :wrong_data} */ - let opts = { width: 10 }; + const opts = { width: 10 }; - let value = SpecialForms._with( - [new Tuple(Symbol.for('ok'), $), () => map_fetch(opts, "width")], - [new Tuple(Symbol.for('ok'), $), (width) => map_fetch(opts, "height")], + const value = SpecialForms._with( + [new Tuple(Symbol.for('ok'), $), () => map_fetch(opts, 'width')], + [new Tuple(Symbol.for('ok'), $), width => map_fetch(opts, 'height')], (width, height) => new Tuple(Symbol.for('ok'), width * height), Patterns.defmatch( - Patterns.clause([Symbol.for('error')], () => new Tuple(Symbol.for('error'), Symbol.for('wrong_data'))) - ) + Patterns.clause( + [Symbol.for('error')], + () => new Tuple(Symbol.for('error'), Symbol.for('wrong_data')), + ), + ), ); - expect(value).to.eql(new Tuple(Symbol.for('error'), Symbol.for('wrong_data'))); + expect(value).to.eql(new Tuple( + Symbol.for('error'), + Symbol.for('wrong_data'), + )); }); it('with else that don`t match', () => { @@ -134,16 +138,19 @@ describe('with', () => { {:error, :wrong_data} */ - let opts = { width: 10 }; + const opts = { width: 10 }; - let withFunction = SpecialForms._with.bind( + const withFunction = SpecialForms._with.bind( null, - [new Tuple(Symbol.for('ok'), $), () => map_fetch(opts, "width")], - [new Tuple(Symbol.for('ok'), $), (width) => map_fetch(opts, "height")], + [new Tuple(Symbol.for('ok'), $), () => map_fetch(opts, 'width')], + [new Tuple(Symbol.for('ok'), $), width => map_fetch(opts, 'height')], (width, height) => new Tuple(Symbol.for('ok'), width * height), Patterns.defmatch( - Patterns.clause([Symbol.for('fail')], () => new Tuple(Symbol.for('error'), Symbol.for('wrong_data'))) - ) + Patterns.clause( + [Symbol.for('fail')], + () => new Tuple(Symbol.for('error'), Symbol.for('wrong_data')), + ), + ), ); expect(withFunction).to.throw(MatchError, 'No match for: Symbol(error)'); diff --git a/test/app/spec/enum.spec.js b/test/app/spec/enum.spec.js index bbf1757a..57d9f212 100644 --- a/test/app/spec/enum.spec.js +++ b/test/app/spec/enum.spec.js @@ -91,4 +91,22 @@ describe('Enum', () => { expect(Enum.drop_every([1, 2], 2)).to.eql([2]); expect(Enum.drop_every([1, 2, 3], 0)).to.eql([1, 2, 3]); }); + + it('drop_while/2', () => { + expect(Enum.drop_while([1, 2, 3, 4, 3, 2, 1], x => x <= 3)).to.eql([ + 4, + 3, + 2, + 1, + ]); + + expect(Enum.drop_while([1, 2, 3], _ => false)).to.eql([1, 2, 3]); + expect(Enum.drop_while([1, 2, 3], x => x <= 3)).to.eql([]); + expect(Enum.drop_while([], _ => false)).to.eql([]); + }); + + it('empty?/1', () => { + expect(Enum.empty__qmark__([])).to.eql(true); + expect(Enum.empty__qmark__([1, 2, 3])).to.eql(false); + }); }); diff --git a/test/translator/case_test.exs b/test/translator/case_test.exs index 9259bb12..08bb8fbb 100644 --- a/test/translator/case_test.exs +++ b/test/translator/case_test.exs @@ -57,7 +57,7 @@ defmodule ElixirScript.Translator.Case.Test do Bootstrap.Core.Patterns.defmatch(Bootstrap.Core.Patterns.clause([false],function() { let [value] = Bootstrap.Core.Patterns.match(Bootstrap.Core.Patterns.variable(),13); return value; - }),Bootstrap.Core.Patterns.clause([Bootstrap.Core.Patterns.wildcard()],function() { + }),Bootstrap.Core.Patterns.clause([Bootstrap.Core.Patterns.variable()],function(__ignored__) { return true; })).call(this,data) """ @@ -71,7 +71,7 @@ defmodule ElixirScript.Translator.Case.Test do case data do number when number in [1,2,3,4] -> value = 13 - _ -> + _ -> true end end @@ -82,7 +82,7 @@ defmodule ElixirScript.Translator.Case.Test do return value; },function(number) { return Elixir.ElixirScript.Bootstrap.Functions.__load(Elixir).contains(number,Object.freeze([1, 2, 3, 4])); - }),Bootstrap.Core.Patterns.clause([Bootstrap.Core.Patterns.wildcard()],function() { + }),Bootstrap.Core.Patterns.clause([Bootstrap.Core.Patterns.variable()],function(__ignored__) { return true; })).call(this,data) """ @@ -107,7 +107,7 @@ defmodule ElixirScript.Translator.Case.Test do return value; },function(number) { return Elixir.ElixirScript.Bootstrap.Functions.__load(Elixir).contains(number,Object.freeze([1, 2, 3, 4])) || Elixir.ElixirScript.Bootstrap.Functions.__load(Elixir).contains(number,Object.freeze([4, 3, 2, 1])); - }),Bootstrap.Core.Patterns.clause([Bootstrap.Core.Patterns.wildcard()],function() { + }),Bootstrap.Core.Patterns.clause([Bootstrap.Core.Patterns.variable()],function(__ignored__) { return true; })).call(this,data) """ diff --git a/test/translator/function_test.exs b/test/translator/function_test.exs index c7d2018f..57088138 100644 --- a/test/translator/function_test.exs +++ b/test/translator/function_test.exs @@ -60,7 +60,7 @@ defmodule ElixirScript.Translator.Function.Test do return 2; },function(x) { return x === null || x === false; - }),Bootstrap.Core.Patterns.clause([Bootstrap.Core.Patterns.wildcard()],function() { + }),Bootstrap.Core.Patterns.clause([Bootstrap.Core.Patterns.variable()],function(__ignored__) { return 1; })).call(this,1 == 1); })); @@ -88,14 +88,14 @@ defmodule ElixirScript.Translator.Function.Test do return 2; }, function(x) { return x === null || x === false; - }), Bootstrap.Core.Patterns.clause([Bootstrap.Core.Patterns.wildcard()], function() { + }), Bootstrap.Core.Patterns.clause([Bootstrap.Core.Patterns.variable()], function(__ignored__) { return Bootstrap.Core.Patterns.defmatch(Bootstrap.Core.Patterns.clause([Bootstrap.Core.Patterns.variable()], function(x) { let [a] = Bootstrap.Core.Patterns.match(Bootstrap.Core.Patterns.variable(), 1); return a; }, function(x) { return x === null || x === false; - }), Bootstrap.Core.Patterns.clause([Bootstrap.Core.Patterns.wildcard()], function() { + }), Bootstrap.Core.Patterns.clause([Bootstrap.Core.Patterns.variable()], function(__ignored__) { return 4; })).call(this, 2 == 2); })).call(this, 1 == 1); @@ -749,7 +749,7 @@ defmodule ElixirScript.Translator.Function.Test do function(x) { return x === null || x === false; }), - Bootstrap.Core.Patterns.clause([Bootstrap.Core.Patterns.wildcard()], function() { + Bootstrap.Core.Patterns.clause([Bootstrap.Core.Patterns.variable()], function(__ignored__) { return null; })).call(this, true); }, diff --git a/test/translator/list_test.exs b/test/translator/list_test.exs index c4af1fc4..39384bfe 100644 --- a/test/translator/list_test.exs +++ b/test/translator/list_test.exs @@ -60,7 +60,7 @@ defmodule ElixirScript.Translator.List.Test do end js_code = """ - Bootstrap.Core.Patterns.defmatch(Bootstrap.Core.Patterns.clause([Bootstrap.Core.Patterns.wildcard()],function(){ + Bootstrap.Core.Patterns.defmatch(Bootstrap.Core.Patterns.clause([Bootstrap.Core.Patterns.variable()],function(__ignored__){ return Object.freeze([x]).concat(list); })) """ diff --git a/test/translator/match_test.exs b/test/translator/match_test.exs index 520dada0..88b13a03 100644 --- a/test/translator/match_test.exs +++ b/test/translator/match_test.exs @@ -29,10 +29,10 @@ defmodule ElixirScript.Translator.Match.Test do ex_ast = quote do: {a, _, c} = {1, 2, 3} js_code = """ - let [a, undefined, c] = Bootstrap.Core.Patterns.match(Bootstrap.Core.Patterns.type(Bootstrap.Core.Tuple, { - values: [Bootstrap.Core.Patterns.variable(), Bootstrap.Core.Patterns.wildcard(), Bootstrap.Core.Patterns.variable()] + let [a, __ignored__, c] = Bootstrap.Core.Patterns.match(Bootstrap.Core.Patterns.type(Bootstrap.Core.Tuple, { + values: [Bootstrap.Core.Patterns.variable(), Bootstrap.Core.Patterns.variable(), Bootstrap.Core.Patterns.variable()] }), new Bootstrap.Core.Tuple(1, 2, 3)); - let _ref = new Bootstrap.Core.Tuple(a, undefined, c); + let _ref = new Bootstrap.Core.Tuple(a, __ignored__, c); """ assert_translation(ex_ast, js_code) @@ -43,10 +43,10 @@ defmodule ElixirScript.Translator.Match.Test do {^a, _, c} = {1, 2, 3} end js_code = """ - let [, undefined, c] = Bootstrap.Core.Patterns.match(Bootstrap.Core.Patterns.type(Bootstrap.Core.Tuple, { - values: [Bootstrap.Core.Patterns.bound(a), Bootstrap.Core.Patterns.wildcard(), Bootstrap.Core.Patterns.variable()] + let [, __ignored__, c] = Bootstrap.Core.Patterns.match(Bootstrap.Core.Patterns.type(Bootstrap.Core.Tuple, { + values: [Bootstrap.Core.Patterns.bound(a), Bootstrap.Core.Patterns.variable(), Bootstrap.Core.Patterns.variable()] }), new Bootstrap.Core.Tuple(1, 2, 3)); - let _ref = new Bootstrap.Core.Tuple(undefined, undefined, c); + let _ref = new Bootstrap.Core.Tuple(undefined, __ignored__, c); """ assert_translation(ex_ast, js_code) diff --git a/test/translator/pattern_matching_test.exs b/test/translator/pattern_matching_test.exs index b32b8ac3..1bebeb22 100644 --- a/test/translator/pattern_matching_test.exs +++ b/test/translator/pattern_matching_test.exs @@ -29,7 +29,7 @@ defmodule ElixirScript.Translator.PatternMatching.Test do test "match wildcard", %{scope: scope} do params = [{:_, [], Test}] result = PatternMatching.build_match(params, scope) - expected_result = {[PatternMatching.wildcard], [JS.identifier(:undefined)]} + expected_result = {[PatternMatching.parameter()], [JS.identifier(:__ignored__)]} assert result == expected_result end diff --git a/test/translator/try_test.exs b/test/translator/try_test.exs index eaff9c47..645e73ec 100644 --- a/test/translator/try_test.exs +++ b/test/translator/try_test.exs @@ -185,7 +185,7 @@ defmodule ElixirScript.Translator.Try.Test do return Symbol.for('small'); }, function(y) { return y < 1 && y > -1; - }), Bootstrap.Core.Patterns.clause([Bootstrap.Core.Patterns.wildcard()], function() { + }), Bootstrap.Core.Patterns.clause([Bootstrap.Core.Patterns.variable()], function(__ignored__) { return Symbol.for('large'); })), null) """ From bab9a91af0f13635c88efc208345674db2b82aaa Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Thu, 23 Mar 2017 22:37:11 -0500 Subject: [PATCH 494/860] Add more test. Fix variable scoping bug --- lib/elixir_script/translator.ex | 9 ++++++++- .../translator/kernel/special_forms/fn.ex | 5 ++--- lib/elixir_script/translator/lexical_scope.ex | 2 +- priv/std_lib/enum.ex | 13 +++++++++---- test/app/spec/enum.spec.js | 14 ++++++++++++++ test/translator/bug_test.exs | 14 ++++++++++++++ 6 files changed, 48 insertions(+), 9 deletions(-) diff --git a/lib/elixir_script/translator.ex b/lib/elixir_script/translator.ex index 10657ef3..1e808d69 100644 --- a/lib/elixir_script/translator.ex +++ b/lib/elixir_script/translator.ex @@ -645,13 +645,20 @@ defmodule ElixirScript.Translator do is_from_js_module(name, params, env) -> do_translate({{:., [], [{:__aliases__, [], [:JS]}, name]}, [], params }, env) ElixirScript.Translator.LexicalScope.has_var?(env, name) -> + name = case env.vars[name] do + 0 -> + name + num -> + String.to_atom("#{name}#{num}") + end + { Identifier.make_identifier(name), env } has_function?(env.module, {name, 0}, env) -> Call.make_function_call(name, [], env) ElixirScript.Translator.LexicalScope.find_module(env, {name, 0}) -> imported_module_name = ElixirScript.Translator.LexicalScope.find_module(env, {name, 0}) Call.make_module_function_call(imported_module_name, name, params, env) - true -> + true -> { Identifier.make_identifier(name), env } end end diff --git a/lib/elixir_script/translator/kernel/special_forms/fn.ex b/lib/elixir_script/translator/kernel/special_forms/fn.ex index 4a8b9736..80a6de81 100644 --- a/lib/elixir_script/translator/kernel/special_forms/fn.ex +++ b/lib/elixir_script/translator/kernel/special_forms/fn.ex @@ -173,9 +173,8 @@ defmodule ElixirScript.Translator.Function do Enum.map_reduce(list, env, fn(x, env) -> Translator.translate(x, env) end) - _ -> - - Enum.map_reduce(List.wrap(body), env, fn(x, env) -> + _ -> + Enum.map_reduce(List.wrap(body), env, fn(x, env) -> Translator.translate(x, env) end) end diff --git a/lib/elixir_script/translator/lexical_scope.ex b/lib/elixir_script/translator/lexical_scope.ex index 0e444c05..36032da5 100644 --- a/lib/elixir_script/translator/lexical_scope.ex +++ b/lib/elixir_script/translator/lexical_scope.ex @@ -124,7 +124,7 @@ defmodule ElixirScript.Translator.LexicalScope do end def function_scope(env, { _, _ } = func) do - %{ env | function: func, caller: env, vars: [] } + %{ env | function: func, caller: env} end def function_scope(env, nil) do diff --git a/priv/std_lib/enum.ex b/priv/std_lib/enum.ex index 28bb4848..1d6c7d87 100644 --- a/priv/std_lib/enum.ex +++ b/priv/std_lib/enum.ex @@ -9,8 +9,6 @@ defmodule ElixirScript.Enum do end end) - IO.inspect acc - acc end @@ -131,9 +129,16 @@ defmodule ElixirScript.Enum do count == 0 end - def fetch(enumerable, index) do + def fetch(enumerable, something_unique) do + something_unique = if something_unique < 0 do + {_, count} = Enumerable.count(enumerable) + count + something_unique + else + something_unique + end + result = Enumerable.reduce(enumerable, {:cont, 0}, fn(item, acc) -> - if index == acc do + if something_unique == acc do {:halt, {:ok, item}} else {:cont, acc + 1} diff --git a/test/app/spec/enum.spec.js b/test/app/spec/enum.spec.js index 57d9f212..3a265bfa 100644 --- a/test/app/spec/enum.spec.js +++ b/test/app/spec/enum.spec.js @@ -1,5 +1,6 @@ const expect = require('chai').expect; const Elixir = require('../build/Elixir.App'); +const Tuple = require('../../../src/javascript/lib/core').default.Tuple; const Enum = Elixir.load(Elixir.ElixirScript.Enum); @@ -109,4 +110,17 @@ describe('Enum', () => { expect(Enum.empty__qmark__([])).to.eql(true); expect(Enum.empty__qmark__([1, 2, 3])).to.eql(false); }); + + it('fetch/2', () => { + expect(Enum.fetch([66], 0)).to.eql(new Tuple(Symbol.for('ok'), 66)); + expect(Enum.fetch([66], -1)).to.eql(new Tuple(Symbol.for('ok'), 66)); + expect(Enum.fetch([66], 1)).to.eql(Symbol.for('error')); + expect(Enum.fetch([66], -2)).to.eql(Symbol.for('error')); + }); + + it('fetch!/2', () => { + expect(Enum.fetch__emark__([2, 4, 6], 0)).to.eql(2); + expect(Enum.fetch__emark__([2, 4, 6], 2)).to.eql(6); + expect(Enum.fetch__emark__([2, 4, 6], -2)).to.eql(4); + }); }); diff --git a/test/translator/bug_test.exs b/test/translator/bug_test.exs index 6e3820a5..7cae994f 100644 --- a/test/translator/bug_test.exs +++ b/test/translator/bug_test.exs @@ -159,4 +159,18 @@ defmodule ElixirScript.Translator.Bug.Test do assert_translation(ex_ast, js_code) end + + test "variable" do + ex_ast = quote do + Enum.fetch([2, 4, 6], 0) + end + + js_code = """ + Object.assign(document.getElementById('main'), Object.freeze({ + innerHTML: html + })) + """ + + assert_translation(ex_ast, js_code) + end end From a23042962c4e86a71e9f1c2b52753f2f8e024677 Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Thu, 23 Mar 2017 22:40:58 -0500 Subject: [PATCH 495/860] Fix test --- test/translator/bug_test.exs | 15 --------------- test/translator/function_test.exs | 2 +- 2 files changed, 1 insertion(+), 16 deletions(-) diff --git a/test/translator/bug_test.exs b/test/translator/bug_test.exs index 7cae994f..2980d8a8 100644 --- a/test/translator/bug_test.exs +++ b/test/translator/bug_test.exs @@ -158,19 +158,4 @@ defmodule ElixirScript.Translator.Bug.Test do assert_translation(ex_ast, js_code) end - - - test "variable" do - ex_ast = quote do - Enum.fetch([2, 4, 6], 0) - end - - js_code = """ - Object.assign(document.getElementById('main'), Object.freeze({ - innerHTML: html - })) - """ - - assert_translation(ex_ast, js_code) - end end diff --git a/test/translator/function_test.exs b/test/translator/function_test.exs index 57088138..5b48c6d0 100644 --- a/test/translator/function_test.exs +++ b/test/translator/function_test.exs @@ -95,7 +95,7 @@ defmodule ElixirScript.Translator.Function.Test do return a; }, function(x) { return x === null || x === false; - }), Bootstrap.Core.Patterns.clause([Bootstrap.Core.Patterns.variable()], function(__ignored__) { + }), Bootstrap.Core.Patterns.clause([Bootstrap.Core.Patterns.variable()], function(__ignored__1) { return 4; })).call(this, 2 == 2); })).call(this, 1 == 1); From c2efe53123ddf3c0603cea634ce108b27d2dfc1d Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Thu, 23 Mar 2017 22:42:07 -0500 Subject: [PATCH 496/860] Renamed something_unique to index --- priv/std_lib/enum.ex | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/priv/std_lib/enum.ex b/priv/std_lib/enum.ex index 1d6c7d87..fded4e3f 100644 --- a/priv/std_lib/enum.ex +++ b/priv/std_lib/enum.ex @@ -129,16 +129,16 @@ defmodule ElixirScript.Enum do count == 0 end - def fetch(enumerable, something_unique) do - something_unique = if something_unique < 0 do + def fetch(enumerable, index) do + index = if index < 0 do {_, count} = Enumerable.count(enumerable) - count + something_unique + count + index else - something_unique + index end result = Enumerable.reduce(enumerable, {:cont, 0}, fn(item, acc) -> - if something_unique == acc do + if index == acc do {:halt, {:ok, item}} else {:cont, acc + 1} From 97188b75cc93cff209ec5530f0bf64f6a2083c73 Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Sun, 26 Mar 2017 16:28:52 -0500 Subject: [PATCH 497/860] Allow for global JS modules and classes to have implementations for protocols --- lib/elixir_script/translator/kernel/defimpl.ex | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/lib/elixir_script/translator/kernel/defimpl.ex b/lib/elixir_script/translator/kernel/defimpl.ex index 92860e18..8c170abd 100644 --- a/lib/elixir_script/translator/kernel/defimpl.ex +++ b/lib/elixir_script/translator/kernel/defimpl.ex @@ -113,6 +113,11 @@ defmodule ElixirScript.Translator.Defimpl do JS.identifier(:Object) end + defp map_to_js({:__aliases__, context, [:JS | rest]}, env) do + ElixirScript.Translator.JS.translate_js_module({:__aliases__, context, rest}, env) + |> elem(0) + end + defp map_to_js({:__aliases__, _, [:Any]}, _) do JS.identifier(:null) end From f75c33a60f01e0bc101180e66518d11e9c07e746 Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Sun, 26 Mar 2017 21:32:28 -0500 Subject: [PATCH 498/860] Add remove_unused option --- CHANGELOG.md | 5 ++++ lib/elixir_script.ex | 2 ++ lib/elixir_script/cli.ex | 6 +++-- lib/elixir_script/passes/remove_unused.ex | 31 +++++++++++++++++++++++ mix.exs | 2 +- 5 files changed, 43 insertions(+), 3 deletions(-) create mode 100644 lib/elixir_script/passes/remove_unused.ex diff --git a/CHANGELOG.md b/CHANGELOG.md index 1e2307f5..91b0d510 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,11 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](http://keepachangelog.com/) and this project adheres to [Semantic Versioning](http://semver.org/). +## [0.28.0-dev] + +### Added +- `remove-unused` option that will remove all unused modules from output + ## [0.27.0] - 2017-03-17 ### Added diff --git a/lib/elixir_script.ex b/lib/elixir_script.ex index bde9904f..298b80c9 100644 --- a/lib/elixir_script.ex +++ b/lib/elixir_script.ex @@ -86,6 +86,7 @@ defmodule ElixirScript do |> ElixirScript.Passes.FindFunctions.execute(opts) |> ElixirScript.Passes.JavaScriptAST.execute(opts) |> ElixirScript.Passes.ConsolidateProtocols.execute(opts) + |> ElixirScript.Passes.RemoveUnused.execute(opts) |> ElixirScript.Passes.CreateJSModules.execute(opts) |> ElixirScript.Passes.JavaScriptCode.execute(opts) |> ElixirScript.Passes.HandleOutput.execute(opts) @@ -187,6 +188,7 @@ defmodule ElixirScript do |> Map.put(:app, :app) |> Map.put(:format, :es) |> Map.put(:js_modules, []) + |> Map.put(:remove_unused, false) options = Map.merge(default_options, opts) Map.put(options, :module_formatter, get_module_formatter(options[:format])) diff --git a/lib/elixir_script/cli.ex b/lib/elixir_script/cli.ex index e4bbb67e..e1e573eb 100644 --- a/lib/elixir_script/cli.ex +++ b/lib/elixir_script/cli.ex @@ -6,7 +6,7 @@ defmodule ElixirScript.CLI do @switches [ output: :string, elixir: :boolean, help: :boolean, full_build: :boolean, version: :boolean, - watch: :boolean, format: :string, js_module: [:string, :keep] + watch: :boolean, format: :string, js_module: [:string, :keep], remove_unused: :boolean ] @aliases [ @@ -50,6 +50,7 @@ defmodule ElixirScript.CLI do -o --output [path] places output at the given path. Can be a directory or filename. -e --elixir read input as elixir code string + --remove-unused Removes unused modules from output --full-build informs the compiler to do a full build instead of an incremental one -v --version the current version number -h --help this message @@ -84,7 +85,8 @@ defmodule ElixirScript.CLI do full_build: Keyword.get(options, :full_build, false), output: Keyword.get(options, :output, :stdout), format: String.to_atom(Keyword.get(options, :format, "es")), - js_modules: js_modules + js_modules: js_modules, + remove_unused: Keyword.get(options, :remove_unused, false) } case options[:elixir] do diff --git a/lib/elixir_script/passes/remove_unused.ex b/lib/elixir_script/passes/remove_unused.ex new file mode 100644 index 00000000..4f6ff8fb --- /dev/null +++ b/lib/elixir_script/passes/remove_unused.ex @@ -0,0 +1,31 @@ +defmodule ElixirScript.Passes.RemoveUnused do + @moduledoc false + alias ElixirScript.Translator.Utils + alias ElixirScript.Translator.State + + def execute(compiler_data, %{remove_unused: false}) do + compiler_data + end + + def execute(compiler_data, opts) do + module_refs = State.list_module_references(compiler_data.state) + + data = Enum.reject(compiler_data.data, fn + {_, %{type: :impl} = module_data} -> + length(module_refs[module_data.implements]) == 0 + {_, %{type: :consolidated} = module_data} -> + length(module_refs[module_data.protocol]) == 0 + {module, module_data} -> + cond do + Enum.member?(module_data.functions, {:start, 2}) -> + false + length(module_refs[module]) > 0 -> + false + true -> + true + end + end) + + %{ compiler_data | data: data } + end +end \ No newline at end of file diff --git a/mix.exs b/mix.exs index 6023aa53..b16da257 100644 --- a/mix.exs +++ b/mix.exs @@ -4,7 +4,7 @@ defmodule ElixirScript.Mixfile do def project do [ app: :elixir_script, - version: "0.27.0", + version: "0.28.0-dev", elixir: "~> 1.0", elixirc_paths: elixirc_paths(), escript: escript_config(), From 0a927fbd77b623bfeaf8ff19f416dca443ea1f6c Mon Sep 17 00:00:00 2001 From: Joel Wietelmann Date: Mon, 27 Mar 2017 17:08:50 -0400 Subject: [PATCH 499/860] Update FAQ.md Grammar nitpick. --- FAQ.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/FAQ.md b/FAQ.md index 3c2ad53e..760b7aa7 100644 --- a/FAQ.md +++ b/FAQ.md @@ -82,7 +82,7 @@ The compiler to this point has been focused on translating Kernel.SpecialForms a ### A. Yes, but realize this is not at 1.0 yet. -You **can** use ElixirScript on your front ends and have it work and interoperate with JavaScript modules. The problem is since most of the standard library is incomplete. +You **can** use ElixirScript on your front ends and have it work and interoperate with JavaScript modules. The problem is that most of the standard library is incomplete. ## Q. Can I use pattern matching? From e42e5953a792acfee41057d215429c30f9dbe5ac Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Mon, 27 Mar 2017 21:50:39 -0500 Subject: [PATCH 500/860] Fixed removed_unused settings --- lib/elixir_script/passes/remove_unused.ex | 6 ++-- lib/elixir_script/translator.ex | 34 +++---------------- .../translator/kernel/special_forms/call.ex | 3 ++ lib/elixir_script/translator/lexical_scope.ex | 6 ++++ lib/elixir_script/translator/state.ex | 26 ++++++-------- test/app/src/main.ex | 2 ++ 6 files changed, 29 insertions(+), 48 deletions(-) diff --git a/lib/elixir_script/passes/remove_unused.ex b/lib/elixir_script/passes/remove_unused.ex index 4f6ff8fb..728f511b 100644 --- a/lib/elixir_script/passes/remove_unused.ex +++ b/lib/elixir_script/passes/remove_unused.ex @@ -12,14 +12,14 @@ defmodule ElixirScript.Passes.RemoveUnused do data = Enum.reject(compiler_data.data, fn {_, %{type: :impl} = module_data} -> - length(module_refs[module_data.implements]) == 0 + length(Keyword.get(module_refs, module_data.implements, [])) == 0 {_, %{type: :consolidated} = module_data} -> - length(module_refs[module_data.protocol]) == 0 + length(Keyword.get(module_refs, module_data.protocol, [])) == 0 {module, module_data} -> cond do Enum.member?(module_data.functions, {:start, 2}) -> false - length(module_refs[module]) > 0 -> + length(Keyword.get(module_refs, module, [])) > 0 -> false true -> true diff --git a/lib/elixir_script/translator.ex b/lib/elixir_script/translator.ex index 1e808d69..5187266e 100644 --- a/lib/elixir_script/translator.ex +++ b/lib/elixir_script/translator.ex @@ -185,7 +185,7 @@ defmodule ElixirScript.Translator do end defp do_translate({:&, _, [{:/, _, [{{:., _, [module_name, function_name]}, _, []}, arity]}]}, env) do - module_name = create_module_name2(module_name, env) + module_name = create_module_name(module_name, env) js_ast = case module_name do {mod, :local} -> Capture.make_capture(mod, function_name, arity, env) @@ -278,7 +278,7 @@ defmodule ElixirScript.Translator do expanded_ast = Macro.expand(ast, env.env) if expanded_ast == ast do - module_name = create_module_name2(module_name, env) + module_name = create_module_name(module_name, env) case module_name do {mod, :local} -> Call.make_module_function_call(mod, function_name, env) @@ -300,19 +300,11 @@ defmodule ElixirScript.Translator do end end - defp do_translate({{:., context1, [{:__aliases__, context2, [:Elixir, :Enum]}, function_name]}, context3, params }, env) do - translate({{:., context1, [{:__aliases__, context2, [:Enum]}, function_name]}, context3, params }, env) - end - - defp do_translate({{:., context1, [{:__aliases__, context2, [:Enum]}, function_name]}, context3, params }, env) do - translate({{:., context1, [{:__aliases__, context2, [:Bootstrap, :Enum]}, function_name]}, context3, params }, env) - end - defp do_translate({{:., _, [{:__aliases__, _, _} = module_name, function_name]}, _, params } = ast, env) do expanded_ast = Macro.expand(ast, env.env) if expanded_ast == ast do - module_name = create_module_name2(module_name, env) + module_name = create_module_name(module_name, env) case module_name do {mod, :local} -> Call.make_module_function_call(mod, function_name, params, env) @@ -345,7 +337,7 @@ defmodule ElixirScript.Translator do end defp do_translate({:__aliases__, _, aliases} = ast, env) do - module_name = create_module_name2(ast, env) + module_name = create_module_name(ast, env) case module_name do {mod, :local} -> Call.make_module_name(mod, env) @@ -640,7 +632,7 @@ defmodule ElixirScript.Translator do end end - defp do_translate({ name, _, params }, env) when is_atom(params) do + defp do_translate({ name, _context, params }, env) when is_atom(params) do cond do is_from_js_module(name, params, env) -> do_translate({{:., [], [{:__aliases__, [], [:JS]}, name]}, [], params }, env) @@ -683,22 +675,6 @@ defmodule ElixirScript.Translator do end def create_module_name(module_name, env) do - case module_name do - {:__aliases__, _, _} -> - candiate_module_name = ElixirScript.Translator.State.get_module_name(env.state, - Utils.quoted_to_name(module_name)) - - if ElixirScript.Translator.LexicalScope.get_module_name(env, candiate_module_name) in ElixirScript.Translator.State.list_module_names(env.state) do - ElixirScript.Translator.LexicalScope.get_module_name(env, candiate_module_name) - else - module_name - end - _ -> - module_name - end - end - - def create_module_name2(module_name, env) do module_name = Utils.quoted_to_name(module_name) candiate_module_name = ElixirScript.Translator.State.get_module_name(env.state, module_name) diff --git a/lib/elixir_script/translator/kernel/special_forms/call.ex b/lib/elixir_script/translator/kernel/special_forms/call.ex index ca3d04eb..9990624d 100644 --- a/lib/elixir_script/translator/kernel/special_forms/call.ex +++ b/lib/elixir_script/translator/kernel/special_forms/call.ex @@ -34,6 +34,8 @@ defmodule ElixirScript.Translator.Call do end def make_module_function_call(module_name, function_name, params, env) do + ElixirScript.Translator.State.add_module_reference(env.state, env.module, module_name) + members = ["Elixir"] ++ Module.split(module_name) ++ ["__load"] ast = JS.call_expression( @@ -51,6 +53,7 @@ defmodule ElixirScript.Translator.Call do end def make_module_function_call(module_name, function_name, env) do + ElixirScript.Translator.State.add_module_reference(env.state, env.module, module_name) make_module_function_call(module_name, function_name, [], env) end diff --git a/lib/elixir_script/translator/lexical_scope.ex b/lib/elixir_script/translator/lexical_scope.ex index 36032da5..f202e549 100644 --- a/lib/elixir_script/translator/lexical_scope.ex +++ b/lib/elixir_script/translator/lexical_scope.ex @@ -228,6 +228,7 @@ defmodule ElixirScript.Translator.LexicalScope do def add_import(env, module_name) do check_for_module_existence(env, module_name) + ElixirScript.Translator.State.add_module_reference(env.state, env.module, module_name) env = if ElixirScript.Translator.State.is_module_loaded?(env.state, module_name) do add_import_macro(env, module_name, []) @@ -247,6 +248,7 @@ defmodule ElixirScript.Translator.LexicalScope do def add_import(env, module_name, [only: :functions]) do module = get_module(env, module_name) + ElixirScript.Translator.State.add_module_reference(env.state, env.module, module_name) %{ env | functions: List.keydelete(env.functions, module_name, 0) ++ [{ module.name, module.functions }], requires: Enum.uniq(env.requires ++ [module.name]) @@ -263,6 +265,7 @@ defmodule ElixirScript.Translator.LexicalScope do def add_import(env, module_name, [only: only]) do check_for_module_existence(env, module_name) + ElixirScript.Translator.State.add_module_reference(env.state, env.module, module_name) env = if ElixirScript.Translator.State.is_module_loaded?(env.state, module_name) do list = module_name.__info__(:macros) @@ -288,6 +291,7 @@ defmodule ElixirScript.Translator.LexicalScope do def add_import(env, module_name, [except: except]) do check_for_module_existence(env, module_name) + ElixirScript.Translator.State.add_module_reference(env.state, env.module, module_name) env = if ElixirScript.Translator.State.is_module_loaded?(env.state, module_name) do list = module_name.__info__(:macros) @@ -312,6 +316,7 @@ defmodule ElixirScript.Translator.LexicalScope do def add_require(env, module_name) do check_for_module_existence(env, module_name) + ElixirScript.Translator.State.add_module_reference(env.state, env.module, module_name) env = if ElixirScript.Translator.State.is_module_loaded?(env.state, module_name) do add_require_macro(env, module_name, []) @@ -329,6 +334,7 @@ defmodule ElixirScript.Translator.LexicalScope do def add_require(env, module_name, alias_name) do check_for_module_existence(env, module_name) + ElixirScript.Translator.State.add_module_reference(env.state, env.module, module_name) env = if ElixirScript.Translator.State.is_module_loaded?(env.state, module_name) do add_require_macro(env, module_name, [as: alias_name]) diff --git a/lib/elixir_script/translator/state.ex b/lib/elixir_script/translator/state.ex index 9f02731f..bb318401 100644 --- a/lib/elixir_script/translator/state.ex +++ b/lib/elixir_script/translator/state.ex @@ -11,7 +11,13 @@ defmodule ElixirScript.Translator.State do def start_link(compiler_opts, loaded_modules) do Agent.start_link(fn -> - %{ compiler_opts: compiler_opts, modules: Keyword.new, std_lib_map: build_standard_lib_map(), loaded_modules: [JS | loaded_modules] } + %{ + compiler_opts: compiler_opts, + modules: Keyword.new, + std_lib_map: build_standard_lib_map(), + loaded_modules: [JS | loaded_modules], + module_references: Keyword.new() + } end) end @@ -120,27 +126,15 @@ defmodule ElixirScript.Translator.State do nil -> state module -> - module = Map.update(module, :refs, [module_name], fn(x) -> Enum.uniq(x ++ [module_name]) end) - modules = Keyword.put(state.modules, module.name, module) - %{ state | modules: modules } + module_references = Keyword.update(state.module_references, module.name, [module_name], fn(x) -> Enum.uniq(x ++ [module_name]) end) + %{ state | module_references: module_references } end end) end - def get_module_references(pid, module_name) do - case get_module(pid, module_name) do - nil -> - [] - module -> - Map.get(module, :refs, []) - end - end - def list_module_references(pid) do Agent.get(pid, fn(state) -> - Enum.map(state.modules, fn {name, module} -> - {name, Map.get(module, :refs, [])} - end) + state.module_references end) end diff --git a/test/app/src/main.ex b/test/app/src/main.ex index 5ddefc6a..61d6451b 100644 --- a/test/app/src/main.ex +++ b/test/app/src/main.ex @@ -1,5 +1,7 @@ defmodule Main do def start(:normal, callback) do + elem({1, 2}, 0) + Enum.map([], fn(x) -> x end) callback.("started") end From ccfc037635a5de2017a35fea7be6d0ce7e193b03 Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Wed, 29 Mar 2017 19:53:53 -0500 Subject: [PATCH 501/860] minify bootstrap javascript --- package.json | 2 +- rollup.config.js | 2 + src/javascript/lib/core/protocol.js | 10 +- yarn.lock | 282 +++++++++++++++++++--------- 4 files changed, 201 insertions(+), 95 deletions(-) diff --git a/package.json b/package.json index bf002ba8..267ad790 100644 --- a/package.json +++ b/package.json @@ -44,7 +44,7 @@ "rollup": "^0.41.4", "rollup-plugin-babel": "^2.7.1", "rollup-plugin-node-resolve": "^2.0.0", - "rollup-plugin-uglify": "^1.0.1", + "rollup-plugin-babili": "^2.0.0", "sinon": "^1.17.7", "sinon-chai": "^2.8.0" } diff --git a/rollup.config.js b/rollup.config.js index 1f30fafa..a318efdf 100644 --- a/rollup.config.js +++ b/rollup.config.js @@ -1,5 +1,6 @@ import nodeResolve from 'rollup-plugin-node-resolve'; import babel from 'rollup-plugin-babel'; +import babili from 'rollup-plugin-babili'; export default { entry: 'src/javascript/elixir.js', @@ -9,6 +10,7 @@ export default { babel({ babelrc: false, }), + babili({}), ], targets: [{ dest: 'priv/build/iife/Elixir.Bootstrap.js', format: 'iife' }], }; diff --git a/src/javascript/lib/core/protocol.js b/src/javascript/lib/core/protocol.js index 936fc59e..52c25426 100644 --- a/src/javascript/lib/core/protocol.js +++ b/src/javascript/lib/core/protocol.js @@ -6,12 +6,8 @@ class Protocol { this.registry = new Map(); this.fallback = null; - for (const funName in spec) { - this[funName] = createFun(funName).bind(this); - } - function createFun(funName) { - return function (...args) { + return function(...args) { const thing = args[0]; let fun = null; @@ -41,6 +37,10 @@ class Protocol { throw new Error(`No implementation found for ${thing}`); }; } + + for (const funName in spec) { + this[funName] = createFun(funName).bind(this); + } } implementation(type, implementation) { diff --git a/yarn.lock b/yarn.lock index dd23136f..a4a74440 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2,6 +2,10 @@ # yarn lockfile v1 +"@comandeer/babel-plugin-banner@^1.0.0": + version "1.0.0" + resolved "https://registry.yarnpkg.com/@comandeer/babel-plugin-banner/-/babel-plugin-banner-1.0.0.tgz#40bcce0bbee084b5b02545a33635d053c248356f" + acorn-jsx@^3.0.0: version "3.0.1" resolved "https://registry.yarnpkg.com/acorn-jsx/-/acorn-jsx-3.0.1.tgz#afdf9488fb1ecefc8348f6fb22f464e32a58b36b" @@ -31,14 +35,6 @@ ajv@^4.7.0: co "^4.6.0" json-stable-stringify "^1.0.1" -align-text@^0.1.1, align-text@^0.1.3: - version "0.1.4" - resolved "https://registry.yarnpkg.com/align-text/-/align-text-0.1.4.tgz#0cd90a561093f35d0a99256c22b7069433fad117" - dependencies: - kind-of "^3.0.2" - longest "^1.0.1" - repeat-string "^1.5.2" - amdefine@>=0.0.4: version "1.0.1" resolved "https://registry.yarnpkg.com/amdefine/-/amdefine-1.0.1.tgz#4a5282ac164729e93619bcfd3ad151f817ce91f5" @@ -101,10 +97,6 @@ assertion-error@^1.0.1: version "1.0.2" resolved "https://registry.yarnpkg.com/assertion-error/-/assertion-error-1.0.2.tgz#13ca515d86206da0bac66e834dd397d87581094c" -async@~0.2.6: - version "0.2.10" - resolved "https://registry.yarnpkg.com/async/-/async-0.2.10.tgz#b6bbe0b0674b9d719708ca38de8c237cb526c3d1" - atob@~1.1.0: version "1.1.3" resolved "https://registry.yarnpkg.com/atob/-/atob-1.1.3.tgz#95f13629b12c3a51a5d215abdce2aa9f32f80773" @@ -117,7 +109,7 @@ babel-code-frame@^6.16.0, babel-code-frame@^6.22.0: esutils "^2.0.2" js-tokens "^3.0.0" -babel-core@6, babel-core@^6.0.2, babel-core@^6.23.0, babel-core@^6.7.7: +babel-core@6, babel-core@^6.0.2, babel-core@^6.21.0, babel-core@^6.23.0, babel-core@^6.7.7: version "6.23.1" resolved "https://registry.yarnpkg.com/babel-core/-/babel-core-6.23.1.tgz#c143cb621bb2f621710c220c5d579d15b8a442df" dependencies: @@ -197,6 +189,10 @@ babel-helper-define-map@^6.23.0: babel-types "^6.23.0" lodash "^4.2.0" +babel-helper-evaluate-path@^0.0.3: + version "0.0.3" + resolved "https://registry.yarnpkg.com/babel-helper-evaluate-path/-/babel-helper-evaluate-path-0.0.3.tgz#1d103ac9d4a59e5d431842212f151785f7ac547b" + babel-helper-explode-assignable-expression@^6.22.0: version "6.22.0" resolved "https://registry.yarnpkg.com/babel-helper-explode-assignable-expression/-/babel-helper-explode-assignable-expression-6.22.0.tgz#c97bf76eed3e0bae4048121f2b9dae1a4e7d0478" @@ -214,6 +210,10 @@ babel-helper-explode-class@^6.22.0: babel-traverse "^6.22.0" babel-types "^6.22.0" +babel-helper-flip-expressions@^0.0.2: + version "0.0.2" + resolved "https://registry.yarnpkg.com/babel-helper-flip-expressions/-/babel-helper-flip-expressions-0.0.2.tgz#7bab2cf61162bc92703e9b298ef512bcf77d6787" + babel-helper-function-name@^6.22.0, babel-helper-function-name@^6.23.0: version "6.23.0" resolved "https://registry.yarnpkg.com/babel-helper-function-name/-/babel-helper-function-name-6.23.0.tgz#25742d67175c8903dbe4b6cb9d9e1fcb8dcf23a6" @@ -238,6 +238,18 @@ babel-helper-hoist-variables@^6.22.0: babel-runtime "^6.22.0" babel-types "^6.22.0" +babel-helper-is-nodes-equiv@^0.0.1: + version "0.0.1" + resolved "https://registry.yarnpkg.com/babel-helper-is-nodes-equiv/-/babel-helper-is-nodes-equiv-0.0.1.tgz#34e9b300b1479ddd98ec77ea0bbe9342dfe39684" + +babel-helper-is-void-0@^0.0.1: + version "0.0.1" + resolved "https://registry.yarnpkg.com/babel-helper-is-void-0/-/babel-helper-is-void-0-0.0.1.tgz#ed74553b883e68226ae45f989a99b02c190f105a" + +babel-helper-mark-eval-scopes@^0.0.3: + version "0.0.3" + resolved "https://registry.yarnpkg.com/babel-helper-mark-eval-scopes/-/babel-helper-mark-eval-scopes-0.0.3.tgz#902f75aeb537336edc35eb9f52b6f09db7785328" + babel-helper-optimise-call-expression@^6.23.0: version "6.23.0" resolved "https://registry.yarnpkg.com/babel-helper-optimise-call-expression/-/babel-helper-optimise-call-expression-6.23.0.tgz#f3ee7eed355b4282138b33d02b78369e470622f5" @@ -263,6 +275,10 @@ babel-helper-remap-async-to-generator@^6.22.0: babel-traverse "^6.22.0" babel-types "^6.22.0" +babel-helper-remove-or-void@^0.0.1: + version "0.0.1" + resolved "https://registry.yarnpkg.com/babel-helper-remove-or-void/-/babel-helper-remove-or-void-0.0.1.tgz#f602790e465acf2dfbe84fb3dd210c43a2dd7262" + babel-helper-replace-supers@^6.22.0, babel-helper-replace-supers@^6.23.0: version "6.23.0" resolved "https://registry.yarnpkg.com/babel-helper-replace-supers/-/babel-helper-replace-supers-6.23.0.tgz#eeaf8ad9b58ec4337ca94223bacdca1f8d9b4bfd" @@ -274,6 +290,10 @@ babel-helper-replace-supers@^6.22.0, babel-helper-replace-supers@^6.23.0: babel-traverse "^6.23.0" babel-types "^6.23.0" +babel-helper-to-multiple-sequence-expressions@^0.0.4: + version "0.0.4" + resolved "https://registry.yarnpkg.com/babel-helper-to-multiple-sequence-expressions/-/babel-helper-to-multiple-sequence-expressions-0.0.4.tgz#d94414b386b6286fbaad77f073dea9b34324b01c" + babel-helpers@^6.23.0: version "6.23.0" resolved "https://registry.yarnpkg.com/babel-helpers/-/babel-helpers-6.23.0.tgz#4f8f2e092d0b6a8808a4bde79c27f1e2ecf0d992" @@ -299,6 +319,71 @@ babel-plugin-external-helpers@^6.4.0: dependencies: babel-runtime "^6.22.0" +babel-plugin-minify-builtins@^0.0.2: + version "0.0.2" + resolved "https://registry.yarnpkg.com/babel-plugin-minify-builtins/-/babel-plugin-minify-builtins-0.0.2.tgz#f3be6121763c0c518d5ef82067cef4b615c9498c" + dependencies: + babel-helper-evaluate-path "^0.0.3" + +babel-plugin-minify-constant-folding@^0.0.4: + version "0.0.4" + resolved "https://registry.yarnpkg.com/babel-plugin-minify-constant-folding/-/babel-plugin-minify-constant-folding-0.0.4.tgz#b6e231026a6035e88ceadd206128d7db2b5c15e6" + dependencies: + babel-helper-evaluate-path "^0.0.3" + jsesc "^2.4.0" + +babel-plugin-minify-dead-code-elimination@^0.1.4: + version "0.1.4" + resolved "https://registry.yarnpkg.com/babel-plugin-minify-dead-code-elimination/-/babel-plugin-minify-dead-code-elimination-0.1.4.tgz#18b6ecfab77c29caca061d8210fa3495001e4fa1" + dependencies: + babel-helper-mark-eval-scopes "^0.0.3" + babel-helper-remove-or-void "^0.0.1" + lodash.some "^4.6.0" + +babel-plugin-minify-flip-comparisons@^0.0.2: + version "0.0.2" + resolved "https://registry.yarnpkg.com/babel-plugin-minify-flip-comparisons/-/babel-plugin-minify-flip-comparisons-0.0.2.tgz#7d0953aa5876ede6118966bda9edecc63bf346ab" + dependencies: + babel-helper-is-void-0 "^0.0.1" + +babel-plugin-minify-guarded-expressions@^0.0.4: + version "0.0.4" + resolved "https://registry.yarnpkg.com/babel-plugin-minify-guarded-expressions/-/babel-plugin-minify-guarded-expressions-0.0.4.tgz#957104a760e6a7ffd967005a7a11621bb42fd11c" + dependencies: + babel-helper-flip-expressions "^0.0.2" + +babel-plugin-minify-infinity@^0.0.3: + version "0.0.3" + resolved "https://registry.yarnpkg.com/babel-plugin-minify-infinity/-/babel-plugin-minify-infinity-0.0.3.tgz#4cc99b61d12b434ce80ad675103335c589cba9a1" + +babel-plugin-minify-mangle-names@^0.0.8: + version "0.0.8" + resolved "https://registry.yarnpkg.com/babel-plugin-minify-mangle-names/-/babel-plugin-minify-mangle-names-0.0.8.tgz#1e2fea856dd742d5697aa26b427e41258a8c5b79" + dependencies: + babel-helper-mark-eval-scopes "^0.0.3" + +babel-plugin-minify-numeric-literals@^0.0.1: + version "0.0.1" + resolved "https://registry.yarnpkg.com/babel-plugin-minify-numeric-literals/-/babel-plugin-minify-numeric-literals-0.0.1.tgz#9597e6c31154d7daf3744d0bd417c144b275bd53" + +babel-plugin-minify-replace@^0.0.1: + version "0.0.1" + resolved "https://registry.yarnpkg.com/babel-plugin-minify-replace/-/babel-plugin-minify-replace-0.0.1.tgz#5d5aea7cb9899245248d1ee9ce7a2fe556a8facc" + +babel-plugin-minify-simplify@^0.0.8: + version "0.0.8" + resolved "https://registry.yarnpkg.com/babel-plugin-minify-simplify/-/babel-plugin-minify-simplify-0.0.8.tgz#597b23327bba4373fed1c51461a689bce9ff4979" + dependencies: + babel-helper-flip-expressions "^0.0.2" + babel-helper-is-nodes-equiv "^0.0.1" + babel-helper-to-multiple-sequence-expressions "^0.0.4" + +babel-plugin-minify-type-constructors@^0.0.4: + version "0.0.4" + resolved "https://registry.yarnpkg.com/babel-plugin-minify-type-constructors/-/babel-plugin-minify-type-constructors-0.0.4.tgz#52d8b623775107523227719ade2d0b7458758b5f" + dependencies: + babel-helper-is-void-0 "^0.0.1" + babel-plugin-syntax-async-functions@^6.8.0: version "6.13.0" resolved "https://registry.yarnpkg.com/babel-plugin-syntax-async-functions/-/babel-plugin-syntax-async-functions-6.13.0.tgz#cad9cad1191b5ad634bf30ae0872391e0647be95" @@ -602,6 +687,24 @@ babel-plugin-transform-function-bind@^6.22.0: babel-plugin-syntax-function-bind "^6.8.0" babel-runtime "^6.22.0" +babel-plugin-transform-inline-consecutive-adds@^0.0.2: + version "0.0.2" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-inline-consecutive-adds/-/babel-plugin-transform-inline-consecutive-adds-0.0.2.tgz#a58fcecfc09c08fbf9373a5a3e70746c03d01fc1" + +babel-plugin-transform-member-expression-literals@^6.8.1: + version "6.8.1" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-member-expression-literals/-/babel-plugin-transform-member-expression-literals-6.8.1.tgz#60b78cb2b814ac71dd6104ef51c496c62e877337" + +babel-plugin-transform-merge-sibling-variables@^6.8.2: + version "6.8.2" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-merge-sibling-variables/-/babel-plugin-transform-merge-sibling-variables-6.8.2.tgz#498acd07481ab340c1bad8b726c2fad1b8f644e5" + +babel-plugin-transform-minify-booleans@^6.8.0: + version "6.8.0" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-minify-booleans/-/babel-plugin-transform-minify-booleans-6.8.0.tgz#b1a48864a727847696b84eae36fa4d085a54b42b" + dependencies: + babel-runtime "^6.0.0" + babel-plugin-transform-object-rest-spread@^6.22.0: version "6.23.0" resolved "https://registry.yarnpkg.com/babel-plugin-transform-object-rest-spread/-/babel-plugin-transform-object-rest-spread-6.23.0.tgz#875d6bc9be761c58a2ae3feee5dc4895d8c7f921" @@ -609,6 +712,10 @@ babel-plugin-transform-object-rest-spread@^6.22.0: babel-plugin-syntax-object-rest-spread "^6.8.0" babel-runtime "^6.22.0" +babel-plugin-transform-property-literals@^6.8.1: + version "6.8.1" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-property-literals/-/babel-plugin-transform-property-literals-6.8.1.tgz#05ed01f6024820b18f1d0495c80fe287176bccd9" + babel-plugin-transform-react-display-name@^6.23.0: version "6.23.0" resolved "https://registry.yarnpkg.com/babel-plugin-transform-react-display-name/-/babel-plugin-transform-react-display-name-6.23.0.tgz#4398910c358441dc4cef18787264d0412ed36b37" @@ -643,6 +750,26 @@ babel-plugin-transform-regenerator@^6.22.0: dependencies: regenerator-transform "0.9.8" +babel-plugin-transform-regexp-constructors@^0.0.6: + version "0.0.6" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-regexp-constructors/-/babel-plugin-transform-regexp-constructors-0.0.6.tgz#0d92607f0d26268296980cb7c1dea5f2dd3e1e20" + +babel-plugin-transform-remove-console@^6.8.1: + version "6.8.1" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-remove-console/-/babel-plugin-transform-remove-console-6.8.1.tgz#38f6a6ca1581e76b75fc2c6fdcf909deadee7d6a" + +babel-plugin-transform-remove-debugger@^6.8.1: + version "6.8.1" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-remove-debugger/-/babel-plugin-transform-remove-debugger-6.8.1.tgz#aabd0be107f8299094defe8e1ba8ccf4b114d07f" + +babel-plugin-transform-remove-undefined@^0.0.5: + version "0.0.5" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-remove-undefined/-/babel-plugin-transform-remove-undefined-0.0.5.tgz#12ef11805e06e861dd2eb0c7cc041d2184b8f410" + +babel-plugin-transform-simplify-comparison-operators@^6.8.1: + version "6.8.1" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-simplify-comparison-operators/-/babel-plugin-transform-simplify-comparison-operators-6.8.1.tgz#a307088e0d1c728081777fba568f4107396ab25c" + babel-plugin-transform-strict-mode@^6.22.0: version "6.22.0" resolved "https://registry.yarnpkg.com/babel-plugin-transform-strict-mode/-/babel-plugin-transform-strict-mode-6.22.0.tgz#e008df01340fdc87e959da65991b7e05970c8c7c" @@ -650,6 +777,40 @@ babel-plugin-transform-strict-mode@^6.22.0: babel-runtime "^6.22.0" babel-types "^6.22.0" +babel-plugin-transform-undefined-to-void@^6.8.0: + version "6.8.0" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-undefined-to-void/-/babel-plugin-transform-undefined-to-void-6.8.0.tgz#bc5b6b4908d3b1262170e67cb3963903ddce167e" + dependencies: + babel-runtime "^6.0.0" + +babel-preset-babili@^0.0.12: + version "0.0.12" + resolved "https://registry.yarnpkg.com/babel-preset-babili/-/babel-preset-babili-0.0.12.tgz#74d79205d54feae6470bc84231da0b9ac9fc7de9" + dependencies: + babel-plugin-minify-builtins "^0.0.2" + babel-plugin-minify-constant-folding "^0.0.4" + babel-plugin-minify-dead-code-elimination "^0.1.4" + babel-plugin-minify-flip-comparisons "^0.0.2" + babel-plugin-minify-guarded-expressions "^0.0.4" + babel-plugin-minify-infinity "^0.0.3" + babel-plugin-minify-mangle-names "^0.0.8" + babel-plugin-minify-numeric-literals "^0.0.1" + babel-plugin-minify-replace "^0.0.1" + babel-plugin-minify-simplify "^0.0.8" + babel-plugin-minify-type-constructors "^0.0.4" + babel-plugin-transform-inline-consecutive-adds "^0.0.2" + babel-plugin-transform-member-expression-literals "^6.8.1" + babel-plugin-transform-merge-sibling-variables "^6.8.2" + babel-plugin-transform-minify-booleans "^6.8.0" + babel-plugin-transform-property-literals "^6.8.1" + babel-plugin-transform-regexp-constructors "^0.0.6" + babel-plugin-transform-remove-console "^6.8.1" + babel-plugin-transform-remove-debugger "^6.8.1" + babel-plugin-transform-remove-undefined "^0.0.5" + babel-plugin-transform-simplify-comparison-operators "^6.8.1" + babel-plugin-transform-undefined-to-void "^6.8.0" + lodash.isplainobject "^4.0.6" + babel-preset-es2015-rollup@^1.1.1: version "1.2.0" resolved "https://registry.yarnpkg.com/babel-preset-es2015-rollup/-/babel-preset-es2015-rollup-1.2.0.tgz#feedf80346e01fa22d4de15e72cde1cefc59bf67" @@ -751,7 +912,7 @@ babel-register@^6.23.0: mkdirp "^0.5.1" source-map-support "^0.4.2" -babel-runtime@^6.18.0, babel-runtime@^6.22.0: +babel-runtime@^6.0.0, babel-runtime@^6.18.0, babel-runtime@^6.22.0: version "6.23.0" resolved "https://registry.yarnpkg.com/babel-runtime/-/babel-runtime-6.23.0.tgz#0a9489f144de70efb3ce4300accdb329e2fc543b" dependencies: @@ -846,17 +1007,6 @@ callsites@^0.2.0: version "0.2.0" resolved "https://registry.yarnpkg.com/callsites/-/callsites-0.2.0.tgz#afab96262910a7f33c19a5775825c69f34e350ca" -camelcase@^1.0.2: - version "1.2.1" - resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-1.2.1.tgz#9bb5304d2e0b56698b2c758b08a3eaa9daa58a39" - -center-align@^0.1.1: - version "0.1.3" - resolved "https://registry.yarnpkg.com/center-align/-/center-align-0.1.3.tgz#aa0d32629b6ee972200411cbd4461c907bc2b7ad" - dependencies: - align-text "^0.1.3" - lazy-cache "^1.0.3" - chai@^3.5.0: version "3.5.0" resolved "https://registry.yarnpkg.com/chai/-/chai-3.5.0.tgz#4d02637b067fe958bdbfdd3a40ec56fef7373247" @@ -889,14 +1039,6 @@ cli-width@^2.0.0: version "2.1.0" resolved "https://registry.yarnpkg.com/cli-width/-/cli-width-2.1.0.tgz#b234ca209b29ef66fc518d9b98d5847b00edf00a" -cliui@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/cliui/-/cliui-2.1.0.tgz#4b475760ff80264c762c3a1719032e91c7fea0d1" - dependencies: - center-align "^0.1.1" - right-align "^0.1.1" - wordwrap "0.0.2" - clone-stats@^0.0.1: version "0.0.1" resolved "https://registry.yarnpkg.com/clone-stats/-/clone-stats-0.0.1.tgz#b88f94a82cf38b8791d58046ea4029ad88ca99d1" @@ -992,10 +1134,6 @@ debug@2.X, debug@^2.1.1, debug@^2.2.0: dependencies: ms "0.7.2" -decamelize@^1.0.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/decamelize/-/decamelize-1.2.0.tgz#f6534d15148269b20352e7bee26f501f9a191290" - deep-eql@^0.1.3: version "0.1.3" resolved "https://registry.yarnpkg.com/deep-eql/-/deep-eql-0.1.3.tgz#ef558acab8de25206cd713906d74e56930eb69f2" @@ -1875,6 +2013,10 @@ jsesc@^1.3.0: version "1.3.0" resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-1.3.0.tgz#46c3fec8c1892b12b0833db9bc7622176dbab34b" +jsesc@^2.4.0: + version "2.4.0" + resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-2.4.0.tgz#8568d223ff69c0b5e081b4f8edf5a23d978c9867" + jsesc@~0.5.0: version "0.5.0" resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-0.5.0.tgz#e7dee66e35d6fc16f710fe91d5cf69f70f08911d" @@ -1903,10 +2045,6 @@ kind-of@^3.0.2: dependencies: is-buffer "^1.0.2" -lazy-cache@^1.0.3: - version "1.0.4" - resolved "https://registry.yarnpkg.com/lazy-cache/-/lazy-cache-1.0.4.tgz#a1d78fc3a50474cb80845d3b3b6e1da49a446e8e" - lazy-debug-legacy@0.0.X: version "0.0.1" resolved "https://registry.yarnpkg.com/lazy-debug-legacy/-/lazy-debug-legacy-0.0.1.tgz#537716c0776e4cf79e3ed1b621f7658c2911b1b1" @@ -1994,7 +2132,7 @@ lodash.isempty@^4.2.1: version "4.4.0" resolved "https://registry.yarnpkg.com/lodash.isempty/-/lodash.isempty-4.4.0.tgz#6f86cbedd8be4ec987be9aaf33c9684db1b31e7e" -lodash.isplainobject@^4.0.4: +lodash.isplainobject@^4.0.4, lodash.isplainobject@^4.0.6: version "4.0.6" resolved "https://registry.yarnpkg.com/lodash.isplainobject/-/lodash.isplainobject-4.0.6.tgz#7c526a52d89b45c45cc690b88163be0497f550cb" @@ -2022,6 +2160,10 @@ lodash.restparam@^3.0.0: version "3.6.1" resolved "https://registry.yarnpkg.com/lodash.restparam/-/lodash.restparam-3.6.1.tgz#936a4e309ef330a7645ed4145986c85ae5b20805" +lodash.some@^4.6.0: + version "4.6.0" + resolved "https://registry.yarnpkg.com/lodash.some/-/lodash.some-4.6.0.tgz#1bb9f314ef6b8baded13b549169b2a945eb68e4d" + lodash.template@^3.0.0: version "3.6.2" resolved "https://registry.yarnpkg.com/lodash.template/-/lodash.template-3.6.2.tgz#f8cdecc6169a255be9098ae8b0c53d378931d14f" @@ -2055,10 +2197,6 @@ lolex@1.3.2: version "1.3.2" resolved "https://registry.yarnpkg.com/lolex/-/lolex-1.3.2.tgz#7c3da62ffcb30f0f5a80a2566ca24e45d8a01f31" -longest@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/longest/-/longest-1.0.1.tgz#30a0b2da38f73770e8294a0d22e6625ed77d0097" - loose-envify@^1.0.0: version "1.3.1" resolved "https://registry.yarnpkg.com/loose-envify/-/loose-envify-1.3.1.tgz#d1a8ad33fa9ce0e713d65fdd0ac8b748d478c848" @@ -2512,12 +2650,6 @@ restore-cursor@^1.0.1: exit-hook "^1.0.0" onetime "^1.0.0" -right-align@^0.1.1: - version "0.1.3" - resolved "https://registry.yarnpkg.com/right-align/-/right-align-0.1.3.tgz#61339b722fe6a3515689210d24e14c96148613ef" - dependencies: - align-text "^0.1.1" - rimraf@^2.2.8: version "2.6.1" resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.6.1.tgz#c2338ec643df7a1b7fe5c54fa86f57428a55f33d" @@ -2533,6 +2665,14 @@ rollup-plugin-babel@^2.7.1: object-assign "^4.1.0" rollup-pluginutils "^1.5.0" +rollup-plugin-babili@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/rollup-plugin-babili/-/rollup-plugin-babili-2.0.0.tgz#3695cb851c661af5f2834836c22ca0822ff9647b" + dependencies: + "@comandeer/babel-plugin-banner" "^1.0.0" + babel-core "^6.21.0" + babel-preset-babili "^0.0.12" + rollup-plugin-node-resolve@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/rollup-plugin-node-resolve/-/rollup-plugin-node-resolve-2.0.0.tgz#07e0ae94ac002a3ea36e8f33ca121d9f836b1309" @@ -2541,12 +2681,6 @@ rollup-plugin-node-resolve@^2.0.0: builtin-modules "^1.1.0" resolve "^1.1.6" -rollup-plugin-uglify@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/rollup-plugin-uglify/-/rollup-plugin-uglify-1.0.1.tgz#11d0b0c8bcd2d07e6908f74fd16b0152390b922a" - dependencies: - uglify-js "^2.6.1" - rollup-pluginutils@^1.5.0: version "1.5.2" resolved "https://registry.yarnpkg.com/rollup-pluginutils/-/rollup-pluginutils-1.5.2.tgz#1e156e778f94b7255bfa1b3d0178be8f5c552408" @@ -2634,7 +2768,7 @@ source-map-url@~0.3.0: version "0.3.0" resolved "https://registry.yarnpkg.com/source-map-url/-/source-map-url-0.3.0.tgz#7ecaf13b57bcd09da8a40c5d269db33799d4aaf9" -source-map@0.X, source-map@^0.5.0, source-map@^0.5.1, source-map@^0.5.3, source-map@~0.5.1: +source-map@0.X, source-map@^0.5.0, source-map@^0.5.1, source-map@^0.5.3: version "0.5.6" resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.5.6.tgz#75ce38f52bf0733c5a7f0c118d81334a2bb5f412" @@ -2787,19 +2921,6 @@ typedarray@^0.0.6: version "0.0.6" resolved "https://registry.yarnpkg.com/typedarray/-/typedarray-0.0.6.tgz#867ac74e3864187b1d3d47d996a78ec5c8830777" -uglify-js@^2.6.1: - version "2.7.5" - resolved "https://registry.yarnpkg.com/uglify-js/-/uglify-js-2.7.5.tgz#4612c0c7baaee2ba7c487de4904ae122079f2ca8" - dependencies: - async "~0.2.6" - source-map "~0.5.1" - uglify-to-browserify "~1.0.0" - yargs "~3.10.0" - -uglify-to-browserify@~1.0.0: - version "1.0.2" - resolved "https://registry.yarnpkg.com/uglify-to-browserify/-/uglify-to-browserify-1.0.2.tgz#6e0924d6bda6b5afe349e39a6d632850a0f882b7" - unc-path-regex@^0.1.0: version "0.1.2" resolved "https://registry.yarnpkg.com/unc-path-regex/-/unc-path-regex-0.1.2.tgz#e73dd3d7b0d7c5ed86fbac6b0ae7d8c6a69d50fa" @@ -2886,14 +3007,6 @@ which@^1.2.12: dependencies: isexe "^1.1.1" -window-size@0.1.0: - version "0.1.0" - resolved "https://registry.yarnpkg.com/window-size/-/window-size-0.1.0.tgz#5438cd2ea93b202efa3a19fe8887aee7c94f9c9d" - -wordwrap@0.0.2: - version "0.0.2" - resolved "https://registry.yarnpkg.com/wordwrap/-/wordwrap-0.0.2.tgz#b79669bb42ecb409f83d583cad52ca17eaa1643f" - wordwrap@~1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/wordwrap/-/wordwrap-1.0.0.tgz#27584810891456a4171c8d0226441ade90cbcaeb" @@ -2911,12 +3024,3 @@ write@^0.2.1: "xtend@>=4.0.0 <4.1.0-0", xtend@^4.0.0, xtend@~4.0.1: version "4.0.1" resolved "https://registry.yarnpkg.com/xtend/-/xtend-4.0.1.tgz#a5c6d532be656e23db820efb943a1f04998d63af" - -yargs@~3.10.0: - version "3.10.0" - resolved "https://registry.yarnpkg.com/yargs/-/yargs-3.10.0.tgz#f7ee7bd857dd7c1d2d38c0e74efbd681d1431fd1" - dependencies: - camelcase "^1.0.2" - cliui "^2.1.0" - decamelize "^1.0.0" - window-size "0.1.0" From 0abc16d2a425870e8ce694bbe4aaab8324565d96 Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Sat, 1 Apr 2017 09:23:27 -0500 Subject: [PATCH 502/860] Fix tests --- test/translator/bug_test.exs | 2 +- test/translator/capture_test.exs | 2 +- test/translator/function_test.exs | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/test/translator/bug_test.exs b/test/translator/bug_test.exs index 2980d8a8..f4474eb1 100644 --- a/test/translator/bug_test.exs +++ b/test/translator/bug_test.exs @@ -47,7 +47,7 @@ defmodule ElixirScript.Translator.Bug.Test do end js_code = """ - Bootstrap.Enum.fetch__emark__(data, i) + Elixir.ElixirScript.Enum.__load(Elixir).fetch__emark__(data, i) """ assert_translation(ex_ast, js_code) diff --git a/test/translator/capture_test.exs b/test/translator/capture_test.exs index ea61fc93..892321ac 100644 --- a/test/translator/capture_test.exs +++ b/test/translator/capture_test.exs @@ -103,7 +103,7 @@ defmodule ElixirScript.Translator.Capture.Test do end js_code = """ - Bootstrap.Enum.map(Object.freeze([]),Bootstrap.Core.Patterns.defmatch(Bootstrap.Core.Patterns.clause([Bootstrap.Core.Patterns.variable()],function(__1) { + Elixir.ElixirScript.Enum.__load(Elixir).map(Object.freeze([]),Bootstrap.Core.Patterns.defmatch(Bootstrap.Core.Patterns.clause([Bootstrap.Core.Patterns.variable()],function(__1) { return process(__1); }))) """ diff --git a/test/translator/function_test.exs b/test/translator/function_test.exs index 5b48c6d0..0f883e30 100644 --- a/test/translator/function_test.exs +++ b/test/translator/function_test.exs @@ -176,7 +176,7 @@ defmodule ElixirScript.Translator.Function.Test do end js_code = """ - Bootstrap.Enum.map(list,Bootstrap.Core.Patterns.defmatch(Bootstrap.Core.Patterns.clause([Bootstrap.Core.Patterns.variable()],function(x) { + Elixir.ElixirScript.Enum.__load(Elixir).map(list,Bootstrap.Core.Patterns.defmatch(Bootstrap.Core.Patterns.clause([Bootstrap.Core.Patterns.variable()],function(x) { return x * 2; }))) """ From 908e97ac60002e93cc1ae5171a70aa620afb1559 Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Sat, 1 Apr 2017 15:23:54 -0500 Subject: [PATCH 503/860] Update tailored dependency --- package.json | 2 +- yarn.lock | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/package.json b/package.json index 267ad790..76c1c998 100644 --- a/package.json +++ b/package.json @@ -23,7 +23,7 @@ "license": "MIT", "dependencies": { "erlang-types": "^1.0.0", - "tailored": "2.3.2" + "tailored": "2.4.1" }, "devDependencies": { "babel": "^6.5.2", diff --git a/yarn.lock b/yarn.lock index a4a74440..c1f5510d 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2849,9 +2849,9 @@ table@^3.7.8: slice-ansi "0.0.4" string-width "^2.0.0" -tailored@2.3.2: - version "2.3.2" - resolved "https://registry.yarnpkg.com/tailored/-/tailored-2.3.2.tgz#4081db326b339dd31048c142d52cda3f95c6a135" +tailored@2.4.1: + version "2.4.1" + resolved "https://registry.yarnpkg.com/tailored/-/tailored-2.4.1.tgz#5fa0988704af192171dfe1299060ec97611225b4" dependencies: erlang-types "^1.0.0" From 605ed18b98ae85f7c24a2d6b84d020b1c0b8219c Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Sat, 1 Apr 2017 15:31:01 -0500 Subject: [PATCH 504/860] Update deps --- .credo.exs | 2 +- mix.exs | 5 ++--- mix.lock | 2 +- 3 files changed, 4 insertions(+), 5 deletions(-) diff --git a/.credo.exs b/.credo.exs index ea83b9c6..5c1f8ef1 100644 --- a/.credo.exs +++ b/.credo.exs @@ -78,7 +78,7 @@ {Credo.Check.Readability.ModuleAttributeNames}, {Credo.Check.Readability.ModuleDoc}, {Credo.Check.Readability.ModuleNames}, - {Credo.Check.Readability.NoParenthesesWhenZeroArity}, + {Credo.Check.Readability.ParenthesesOnZeroArityDefs}, {Credo.Check.Readability.ParenthesesInCondition}, {Credo.Check.Readability.PredicateFunctionNames}, {Credo.Check.Readability.PreferImplicitTry}, diff --git a/mix.exs b/mix.exs index b16da257..c31d1f54 100644 --- a/mix.exs +++ b/mix.exs @@ -14,7 +14,6 @@ defmodule ElixirScript.Mixfile do source_url: "https://github.com/elixirscript/elixirscript", aliases: aliases(), test_coverage: [tool: ExCoveralls], - preferred_cli_env: [coveralls: :test], docs: [ extras: ["GettingStarted.md", "FAQ.md"] ] @@ -32,8 +31,8 @@ defmodule ElixirScript.Mixfile do {:estree, "~> 2.5"}, {:fs, "~> 2.12"}, {:ex_doc, "~> 0.14", only: :dev}, - {:excoveralls, "~> 0.5", only: :test}, - {:credo, "~> 0.4", only: [:dev, :test]} + {:excoveralls, "~> 0.6", only: :test}, + {:credo, "~> 0.7", only: [:dev, :test]} ] end diff --git a/mix.lock b/mix.lock index 2020bc3f..0e03c5b6 100644 --- a/mix.lock +++ b/mix.lock @@ -1,6 +1,6 @@ %{"bunt": {:hex, :bunt, "0.2.0", "951c6e801e8b1d2cbe58ebbd3e616a869061ddadcc4863d0a2182541acae9a38", [:mix], []}, "certifi": {:hex, :certifi, "0.7.0", "861a57f3808f7eb0c2d1802afeaae0fa5de813b0df0979153cbafcd853ababaf", [:rebar3], []}, - "credo": {:hex, :credo, "0.6.1", "a941e2591bd2bd2055dc92b810c174650b40b8290459c89a835af9d59ac4a5f8", [:mix], [{:bunt, "~> 0.2.0", [hex: :bunt, optional: false]}]}, + "credo": {:hex, :credo, "0.7.2", "850463f126c09227994967fdcf8b8ad7684ab220f7727c00bcafc0ac37bd3660", [:mix], [{:bunt, "~> 0.2.0", [hex: :bunt, optional: false]}]}, "earmark": {:hex, :earmark, "1.1.1", "433136b7f2e99cde88b745b3a0cfc3fbc81fe58b918a09b40fce7f00db4d8187", [:mix], []}, "estree": {:hex, :estree, "2.5.1", "c93a8fa8a29886e6a6f6c489ba6dc949b998d2985b189967e41e69a92b58e846", [:mix], []}, "ex_doc": {:hex, :ex_doc, "0.14.5", "c0433c8117e948404d93ca69411dd575ec6be39b47802e81ca8d91017a0cf83c", [:mix], [{:earmark, "~> 1.0", [hex: :earmark, optional: false]}]}, From c6ab0a9e8a5cbc43eb68ee9102928714c627ec05 Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Sun, 2 Apr 2017 05:00:43 -0500 Subject: [PATCH 505/860] Cleaning up javascript environment --- .babelrc | 4 +- .flowconfig | 12 - .travis.yml | 2 +- gulpfile.js | 11 - package.json | 21 +- test/app/spec/setup.spec.js | 6 +- yarn.lock | 1579 ++++++----------------------------- 7 files changed, 249 insertions(+), 1386 deletions(-) delete mode 100644 .flowconfig delete mode 100644 gulpfile.js diff --git a/.babelrc b/.babelrc index 9a615718..6a9be799 100644 --- a/.babelrc +++ b/.babelrc @@ -1,3 +1,5 @@ { - "plugins": ["transform-es2015-modules-commonjs"] + "presets": [ + "env" + ] } \ No newline at end of file diff --git a/.flowconfig b/.flowconfig deleted file mode 100644 index 7f76ba60..00000000 --- a/.flowconfig +++ /dev/null @@ -1,12 +0,0 @@ -[ignore] -.*/dist/.* -.*/build/.* -.*/dist_build/.* -.*/node_modules/.* - -[include] -./priv/javascript - -[libs] - -[options] diff --git a/.travis.yml b/.travis.yml index c6facb26..a1fb4260 100644 --- a/.travis.yml +++ b/.travis.yml @@ -5,7 +5,7 @@ elixir: otp_release: - 19.0 env: - - TRAVIS_NODE_VERSION="6" + - TRAVIS_NODE_VERSION="7" install: - rm -rf ~/.nvm && git clone https://github.com/creationix/nvm.git ~/.nvm && (cd ~/.nvm && git checkout `git describe --abbrev=0 --tags`) && source ~/.nvm/nvm.sh && nvm install $TRAVIS_NODE_VERSION - npm install -g yarn diff --git a/gulpfile.js b/gulpfile.js deleted file mode 100644 index ac7ed7db..00000000 --- a/gulpfile.js +++ /dev/null @@ -1,11 +0,0 @@ -const gulp = require('gulp'); -const babel = require('gulp-babel'); -const sourcemaps = require('gulp-sourcemaps'); - -const path = './src/javascript'; - -gulp.task('build', () => gulp.src([`${path}/**/*.js`, `!${path}/dist_build/**/*.js`, `!${path}/tests/**/*.js`]) - .pipe(sourcemaps.init()) - .pipe(babel({ presets: ['react', 'stage-0'], babelrc: false })) - .pipe(sourcemaps.write()) - .pipe(gulp.dest('./src/elixirscript'))); diff --git a/package.json b/package.json index 76c1c998..5be1f75c 100644 --- a/package.json +++ b/package.json @@ -13,7 +13,7 @@ "clean": "rm -rf priv/build", "test": "mocha src/javascript/tests --recursive --compilers js:babel-core/register", "build:test-app": "mix elixirscript test/app/src/ -f common -o test/app/build/", - "test-app": "yarn run build:test-app && NODE_ENV=test mocha --recursive 'test/app/spec/**/*.spec.js' --compilers js:babel-core/register" + "test-app": "yarn run build:test-app && NODE_ENV=test mocha --recursive 'test/app/spec/**/*.spec.js' --compilers js:babel-register" }, "repository": { "type": "git", @@ -26,25 +26,18 @@ "tailored": "2.4.1" }, "devDependencies": { - "babel": "^6.5.2", - "babel-core": "^6.7.7", - "babel-plugin-transform-class-properties": "^6.9.1", - "babel-preset-es2015": "^6.6.0", - "babel-preset-es2015-rollup": "^1.1.1", - "babel-preset-react": "^6.5.0", - "babel-preset-stage-0": "^6.5.0", + "babel-core": "^6.24.0", + "babel-register": "^6.24.0", + "babel-preset-env": "^1.3.2", "chai": "^3.5.0", "eslint": "^3.15.0", "eslint-config-airbnb-base": "^11.1.0", "eslint-plugin-import": "^2.2.0", - "gulp": "^3.9.1", - "gulp-babel": "^6.1.2", - "gulp-sourcemaps": "^2.0.0-alpha", - "mocha": "^2.4.5", - "rollup": "^0.41.4", + "mocha": "^3.2.0", + "rollup": "^0.41.6", "rollup-plugin-babel": "^2.7.1", - "rollup-plugin-node-resolve": "^2.0.0", "rollup-plugin-babili": "^2.0.0", + "rollup-plugin-node-resolve": "^2.0.0", "sinon": "^1.17.7", "sinon-chai": "^2.8.0" } diff --git a/test/app/spec/setup.spec.js b/test/app/spec/setup.spec.js index b1c0f404..3e9f4714 100644 --- a/test/app/spec/setup.spec.js +++ b/test/app/spec/setup.spec.js @@ -2,14 +2,14 @@ const sinon = require('sinon'); const chai = require('chai'); const sinonChai = require('sinon-chai'); -before(function () { +before(function() { chai.use(sinonChai); }); -beforeEach(function () { +beforeEach(function() { this.sandbox = sinon.sandbox.create(); }); -afterEach(function () { +afterEach(function() { this.sandbox.restore(); }); diff --git a/yarn.lock b/yarn.lock index c1f5510d..c7b7c84c 100644 --- a/yarn.lock +++ b/yarn.lock @@ -12,33 +12,25 @@ acorn-jsx@^3.0.0: dependencies: acorn "^3.0.4" -acorn@4.0.4: - version "4.0.4" - resolved "https://registry.yarnpkg.com/acorn/-/acorn-4.0.4.tgz#17a8d6a7a6c4ef538b814ec9abac2779293bf30a" - -acorn@4.X: - version "4.0.11" - resolved "https://registry.yarnpkg.com/acorn/-/acorn-4.0.11.tgz#edcda3bd937e7556410d42ed5860f67399c794c0" - acorn@^3.0.4: version "3.3.0" resolved "https://registry.yarnpkg.com/acorn/-/acorn-3.3.0.tgz#45e37fb39e8da3f25baee3ff5369e2bb5f22017a" +acorn@^5.0.1: + version "5.0.3" + resolved "https://registry.yarnpkg.com/acorn/-/acorn-5.0.3.tgz#c460df08491463f028ccb82eab3730bf01087b3d" + ajv-keywords@^1.0.0: version "1.5.1" resolved "https://registry.yarnpkg.com/ajv-keywords/-/ajv-keywords-1.5.1.tgz#314dd0a4b3368fad3dfcdc54ede6171b886daf3c" ajv@^4.7.0: - version "4.11.3" - resolved "https://registry.yarnpkg.com/ajv/-/ajv-4.11.3.tgz#ce30bdb90d1254f762c75af915fb3a63e7183d22" + version "4.11.5" + resolved "https://registry.yarnpkg.com/ajv/-/ajv-4.11.5.tgz#b6ee74657b993a01dce44b7944d56f485828d5bd" dependencies: co "^4.6.0" json-stable-stringify "^1.0.1" -amdefine@>=0.0.4: - version "1.0.1" - resolved "https://registry.yarnpkg.com/amdefine/-/amdefine-1.0.1.tgz#4a5282ac164729e93619bcfd3ad151f817ce91f5" - ansi-escapes@^1.1.0: version "1.4.0" resolved "https://registry.yarnpkg.com/ansi-escapes/-/ansi-escapes-1.4.0.tgz#d3a8a83b319aa67793662b13e761c7911422306e" @@ -51,44 +43,22 @@ ansi-styles@^2.2.1: version "2.2.1" resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-2.2.1.tgz#b432dd3358b634cf75e1e4664368240533c1ddbe" -archy@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/archy/-/archy-1.0.0.tgz#f9c8c13757cc1dd7bc379ac77b2c62a5c2868c40" - argparse@^1.0.7: version "1.0.9" resolved "https://registry.yarnpkg.com/argparse/-/argparse-1.0.9.tgz#73d83bc263f86e97f8cc4f6bae1b0e90a7d22c86" dependencies: sprintf-js "~1.0.2" -arr-diff@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/arr-diff/-/arr-diff-2.0.0.tgz#8f3b827f955a8bd669697e4a4256ac3ceae356cf" - dependencies: - arr-flatten "^1.0.1" - -arr-flatten@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/arr-flatten/-/arr-flatten-1.0.1.tgz#e5ffe54d45e19f32f216e91eb99c8ce892bb604b" - -array-differ@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/array-differ/-/array-differ-1.0.0.tgz#eff52e3758249d33be402b8bb8e564bb2b5d4031" - array-union@^1.0.1: version "1.0.2" resolved "https://registry.yarnpkg.com/array-union/-/array-union-1.0.2.tgz#9a34410e4f4e3da23dea375be5be70f24778ec39" dependencies: array-uniq "^1.0.1" -array-uniq@^1.0.1, array-uniq@^1.0.2: +array-uniq@^1.0.1: version "1.0.3" resolved "https://registry.yarnpkg.com/array-uniq/-/array-uniq-1.0.3.tgz#af6ac877a25cc7f74e058894753858dfdb24fdb6" -array-unique@^0.2.1: - version "0.2.1" - resolved "https://registry.yarnpkg.com/array-unique/-/array-unique-0.2.1.tgz#a1d97ccafcbc2625cc70fadceb36a50c58b01a53" - arrify@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/arrify/-/arrify-1.0.1.tgz#898508da2226f380df904728456849c1501a4b0d" @@ -97,10 +67,6 @@ assertion-error@^1.0.1: version "1.0.2" resolved "https://registry.yarnpkg.com/assertion-error/-/assertion-error-1.0.2.tgz#13ca515d86206da0bac66e834dd397d87581094c" -atob@~1.1.0: - version "1.1.3" - resolved "https://registry.yarnpkg.com/atob/-/atob-1.1.3.tgz#95f13629b12c3a51a5d215abdce2aa9f32f80773" - babel-code-frame@^6.16.0, babel-code-frame@^6.22.0: version "6.22.0" resolved "https://registry.yarnpkg.com/babel-code-frame/-/babel-code-frame-6.22.0.tgz#027620bee567a88c32561574e7fd0801d33118e4" @@ -109,15 +75,15 @@ babel-code-frame@^6.16.0, babel-code-frame@^6.22.0: esutils "^2.0.2" js-tokens "^3.0.0" -babel-core@6, babel-core@^6.0.2, babel-core@^6.21.0, babel-core@^6.23.0, babel-core@^6.7.7: - version "6.23.1" - resolved "https://registry.yarnpkg.com/babel-core/-/babel-core-6.23.1.tgz#c143cb621bb2f621710c220c5d579d15b8a442df" +babel-core@6, babel-core@^6.21.0, babel-core@^6.24.0: + version "6.24.0" + resolved "https://registry.yarnpkg.com/babel-core/-/babel-core-6.24.0.tgz#8f36a0a77f5c155aed6f920b844d23ba56742a02" dependencies: babel-code-frame "^6.22.0" - babel-generator "^6.23.0" + babel-generator "^6.24.0" babel-helpers "^6.23.0" babel-messages "^6.23.0" - babel-register "^6.23.0" + babel-register "^6.24.0" babel-runtime "^6.22.0" babel-template "^6.23.0" babel-traverse "^6.23.1" @@ -133,9 +99,9 @@ babel-core@6, babel-core@^6.0.2, babel-core@^6.21.0, babel-core@^6.23.0, babel-c slash "^1.0.0" source-map "^0.5.0" -babel-generator@^6.23.0: - version "6.23.0" - resolved "https://registry.yarnpkg.com/babel-generator/-/babel-generator-6.23.0.tgz#6b8edab956ef3116f79d8c84c5a3c05f32a74bc5" +babel-generator@^6.24.0: + version "6.24.0" + resolved "https://registry.yarnpkg.com/babel-generator/-/babel-generator-6.24.0.tgz#eba270a8cc4ce6e09a61be43465d7c62c1f87c56" dependencies: babel-messages "^6.23.0" babel-runtime "^6.22.0" @@ -146,14 +112,6 @@ babel-generator@^6.23.0: source-map "^0.5.0" trim-right "^1.0.1" -babel-helper-bindify-decorators@^6.22.0: - version "6.22.0" - resolved "https://registry.yarnpkg.com/babel-helper-bindify-decorators/-/babel-helper-bindify-decorators-6.22.0.tgz#d7f5bc261275941ac62acfc4e20dacfb8a3fe952" - dependencies: - babel-runtime "^6.22.0" - babel-traverse "^6.22.0" - babel-types "^6.22.0" - babel-helper-builder-binary-assignment-operator-visitor@^6.22.0: version "6.22.0" resolved "https://registry.yarnpkg.com/babel-helper-builder-binary-assignment-operator-visitor/-/babel-helper-builder-binary-assignment-operator-visitor-6.22.0.tgz#29df56be144d81bdeac08262bfa41d2c5e91cdcd" @@ -162,15 +120,6 @@ babel-helper-builder-binary-assignment-operator-visitor@^6.22.0: babel-runtime "^6.22.0" babel-types "^6.22.0" -babel-helper-builder-react-jsx@^6.23.0: - version "6.23.0" - resolved "https://registry.yarnpkg.com/babel-helper-builder-react-jsx/-/babel-helper-builder-react-jsx-6.23.0.tgz#d53fc8c996e0bc56d0de0fc4cc55a7138395ea4b" - dependencies: - babel-runtime "^6.22.0" - babel-types "^6.23.0" - esutils "^2.0.0" - lodash "^4.2.0" - babel-helper-call-delegate@^6.22.0: version "6.22.0" resolved "https://registry.yarnpkg.com/babel-helper-call-delegate/-/babel-helper-call-delegate-6.22.0.tgz#119921b56120f17e9dae3f74b4f5cc7bcc1b37ef" @@ -201,15 +150,6 @@ babel-helper-explode-assignable-expression@^6.22.0: babel-traverse "^6.22.0" babel-types "^6.22.0" -babel-helper-explode-class@^6.22.0: - version "6.22.0" - resolved "https://registry.yarnpkg.com/babel-helper-explode-class/-/babel-helper-explode-class-6.22.0.tgz#646304924aa6388a516843ba7f1855ef8dfeb69b" - dependencies: - babel-helper-bindify-decorators "^6.22.0" - babel-runtime "^6.22.0" - babel-traverse "^6.22.0" - babel-types "^6.22.0" - babel-helper-flip-expressions@^0.0.2: version "0.0.2" resolved "https://registry.yarnpkg.com/babel-helper-flip-expressions/-/babel-helper-flip-expressions-0.0.2.tgz#7bab2cf61162bc92703e9b298ef512bcf77d6787" @@ -313,12 +253,6 @@ babel-plugin-check-es2015-constants@^6.22.0: dependencies: babel-runtime "^6.22.0" -babel-plugin-external-helpers@^6.4.0: - version "6.22.0" - resolved "https://registry.yarnpkg.com/babel-plugin-external-helpers/-/babel-plugin-external-helpers-6.22.0.tgz#2285f48b02bd5dede85175caf8c62e86adccefa1" - dependencies: - babel-runtime "^6.22.0" - babel-plugin-minify-builtins@^0.0.2: version "0.0.2" resolved "https://registry.yarnpkg.com/babel-plugin-minify-builtins/-/babel-plugin-minify-builtins-0.0.2.tgz#f3be6121763c0c518d5ef82067cef4b615c9498c" @@ -388,66 +322,14 @@ babel-plugin-syntax-async-functions@^6.8.0: version "6.13.0" resolved "https://registry.yarnpkg.com/babel-plugin-syntax-async-functions/-/babel-plugin-syntax-async-functions-6.13.0.tgz#cad9cad1191b5ad634bf30ae0872391e0647be95" -babel-plugin-syntax-async-generators@^6.5.0: - version "6.13.0" - resolved "https://registry.yarnpkg.com/babel-plugin-syntax-async-generators/-/babel-plugin-syntax-async-generators-6.13.0.tgz#6bc963ebb16eccbae6b92b596eb7f35c342a8b9a" - -babel-plugin-syntax-class-constructor-call@^6.18.0: - version "6.18.0" - resolved "https://registry.yarnpkg.com/babel-plugin-syntax-class-constructor-call/-/babel-plugin-syntax-class-constructor-call-6.18.0.tgz#9cb9d39fe43c8600bec8146456ddcbd4e1a76416" - -babel-plugin-syntax-class-properties@^6.8.0: - version "6.13.0" - resolved "https://registry.yarnpkg.com/babel-plugin-syntax-class-properties/-/babel-plugin-syntax-class-properties-6.13.0.tgz#d7eb23b79a317f8543962c505b827c7d6cac27de" - -babel-plugin-syntax-decorators@^6.13.0: - version "6.13.0" - resolved "https://registry.yarnpkg.com/babel-plugin-syntax-decorators/-/babel-plugin-syntax-decorators-6.13.0.tgz#312563b4dbde3cc806cee3e416cceeaddd11ac0b" - -babel-plugin-syntax-do-expressions@^6.8.0: - version "6.13.0" - resolved "https://registry.yarnpkg.com/babel-plugin-syntax-do-expressions/-/babel-plugin-syntax-do-expressions-6.13.0.tgz#5747756139aa26d390d09410b03744ba07e4796d" - -babel-plugin-syntax-dynamic-import@^6.18.0: - version "6.18.0" - resolved "https://registry.yarnpkg.com/babel-plugin-syntax-dynamic-import/-/babel-plugin-syntax-dynamic-import-6.18.0.tgz#8d6a26229c83745a9982a441051572caa179b1da" - babel-plugin-syntax-exponentiation-operator@^6.8.0: version "6.13.0" resolved "https://registry.yarnpkg.com/babel-plugin-syntax-exponentiation-operator/-/babel-plugin-syntax-exponentiation-operator-6.13.0.tgz#9ee7e8337290da95288201a6a57f4170317830de" -babel-plugin-syntax-export-extensions@^6.8.0: - version "6.13.0" - resolved "https://registry.yarnpkg.com/babel-plugin-syntax-export-extensions/-/babel-plugin-syntax-export-extensions-6.13.0.tgz#70a1484f0f9089a4e84ad44bac353c95b9b12721" - -babel-plugin-syntax-flow@^6.18.0: - version "6.18.0" - resolved "https://registry.yarnpkg.com/babel-plugin-syntax-flow/-/babel-plugin-syntax-flow-6.18.0.tgz#4c3ab20a2af26aa20cd25995c398c4eb70310c8d" - -babel-plugin-syntax-function-bind@^6.8.0: - version "6.13.0" - resolved "https://registry.yarnpkg.com/babel-plugin-syntax-function-bind/-/babel-plugin-syntax-function-bind-6.13.0.tgz#48c495f177bdf31a981e732f55adc0bdd2601f46" - -babel-plugin-syntax-jsx@^6.3.13, babel-plugin-syntax-jsx@^6.8.0: - version "6.18.0" - resolved "https://registry.yarnpkg.com/babel-plugin-syntax-jsx/-/babel-plugin-syntax-jsx-6.18.0.tgz#0af32a9a6e13ca7a3fd5069e62d7b0f58d0d8946" - -babel-plugin-syntax-object-rest-spread@^6.8.0: - version "6.13.0" - resolved "https://registry.yarnpkg.com/babel-plugin-syntax-object-rest-spread/-/babel-plugin-syntax-object-rest-spread-6.13.0.tgz#fd6536f2bce13836ffa3a5458c4903a597bb3bf5" - babel-plugin-syntax-trailing-function-commas@^6.22.0: version "6.22.0" resolved "https://registry.yarnpkg.com/babel-plugin-syntax-trailing-function-commas/-/babel-plugin-syntax-trailing-function-commas-6.22.0.tgz#ba0360937f8d06e40180a43fe0d5616fff532cf3" -babel-plugin-transform-async-generator-functions@^6.22.0: - version "6.22.0" - resolved "https://registry.yarnpkg.com/babel-plugin-transform-async-generator-functions/-/babel-plugin-transform-async-generator-functions-6.22.0.tgz#a720a98153a7596f204099cd5409f4b3c05bab46" - dependencies: - babel-helper-remap-async-to-generator "^6.22.0" - babel-plugin-syntax-async-generators "^6.5.0" - babel-runtime "^6.22.0" - babel-plugin-transform-async-to-generator@^6.22.0: version "6.22.0" resolved "https://registry.yarnpkg.com/babel-plugin-transform-async-to-generator/-/babel-plugin-transform-async-to-generator-6.22.0.tgz#194b6938ec195ad36efc4c33a971acf00d8cd35e" @@ -456,40 +338,6 @@ babel-plugin-transform-async-to-generator@^6.22.0: babel-plugin-syntax-async-functions "^6.8.0" babel-runtime "^6.22.0" -babel-plugin-transform-class-constructor-call@^6.22.0: - version "6.22.0" - resolved "https://registry.yarnpkg.com/babel-plugin-transform-class-constructor-call/-/babel-plugin-transform-class-constructor-call-6.22.0.tgz#11a4d2216abb5b0eef298b493748f4f2f4869120" - dependencies: - babel-plugin-syntax-class-constructor-call "^6.18.0" - babel-runtime "^6.22.0" - babel-template "^6.22.0" - -babel-plugin-transform-class-properties@^6.22.0, babel-plugin-transform-class-properties@^6.9.1: - version "6.23.0" - resolved "https://registry.yarnpkg.com/babel-plugin-transform-class-properties/-/babel-plugin-transform-class-properties-6.23.0.tgz#187b747ee404399013563c993db038f34754ac3b" - dependencies: - babel-helper-function-name "^6.23.0" - babel-plugin-syntax-class-properties "^6.8.0" - babel-runtime "^6.22.0" - babel-template "^6.23.0" - -babel-plugin-transform-decorators@^6.22.0: - version "6.22.0" - resolved "https://registry.yarnpkg.com/babel-plugin-transform-decorators/-/babel-plugin-transform-decorators-6.22.0.tgz#c03635b27a23b23b7224f49232c237a73988d27c" - dependencies: - babel-helper-explode-class "^6.22.0" - babel-plugin-syntax-decorators "^6.13.0" - babel-runtime "^6.22.0" - babel-template "^6.22.0" - babel-types "^6.22.0" - -babel-plugin-transform-do-expressions@^6.22.0: - version "6.22.0" - resolved "https://registry.yarnpkg.com/babel-plugin-transform-do-expressions/-/babel-plugin-transform-do-expressions-6.22.0.tgz#28ccaf92812d949c2cd1281f690c8fdc468ae9bb" - dependencies: - babel-plugin-syntax-do-expressions "^6.8.0" - babel-runtime "^6.22.0" - babel-plugin-transform-es2015-arrow-functions@^6.22.0: version "6.22.0" resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-arrow-functions/-/babel-plugin-transform-es2015-arrow-functions-6.22.0.tgz#452692cb711d5f79dc7f85e440ce41b9f244d221" @@ -502,7 +350,7 @@ babel-plugin-transform-es2015-block-scoped-functions@^6.22.0: dependencies: babel-runtime "^6.22.0" -babel-plugin-transform-es2015-block-scoping@^6.22.0: +babel-plugin-transform-es2015-block-scoping@^6.23.0: version "6.23.0" resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-block-scoping/-/babel-plugin-transform-es2015-block-scoping-6.23.0.tgz#e48895cf0b375be148cd7c8879b422707a053b51" dependencies: @@ -512,7 +360,7 @@ babel-plugin-transform-es2015-block-scoping@^6.22.0: babel-types "^6.23.0" lodash "^4.2.0" -babel-plugin-transform-es2015-classes@^6.22.0, babel-plugin-transform-es2015-classes@^6.9.0: +babel-plugin-transform-es2015-classes@^6.23.0, babel-plugin-transform-es2015-classes@^6.9.0: version "6.23.0" resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-classes/-/babel-plugin-transform-es2015-classes-6.23.0.tgz#49b53f326202a2fd1b3bbaa5e2edd8a4f78643c1" dependencies: @@ -533,7 +381,7 @@ babel-plugin-transform-es2015-computed-properties@^6.22.0: babel-runtime "^6.22.0" babel-template "^6.22.0" -babel-plugin-transform-es2015-destructuring@^6.22.0: +babel-plugin-transform-es2015-destructuring@^6.23.0: version "6.23.0" resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-destructuring/-/babel-plugin-transform-es2015-destructuring-6.23.0.tgz#997bb1f1ab967f682d2b0876fe358d60e765c56d" dependencies: @@ -546,7 +394,7 @@ babel-plugin-transform-es2015-duplicate-keys@^6.22.0: babel-runtime "^6.22.0" babel-types "^6.22.0" -babel-plugin-transform-es2015-for-of@^6.22.0: +babel-plugin-transform-es2015-for-of@^6.23.0: version "6.23.0" resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-for-of/-/babel-plugin-transform-es2015-for-of-6.23.0.tgz#f47c95b2b613df1d3ecc2fdb7573623c75248691" dependencies: @@ -566,24 +414,24 @@ babel-plugin-transform-es2015-literals@^6.22.0: dependencies: babel-runtime "^6.22.0" -babel-plugin-transform-es2015-modules-amd@^6.22.0: - version "6.22.0" - resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-modules-amd/-/babel-plugin-transform-es2015-modules-amd-6.22.0.tgz#bf69cd34889a41c33d90dfb740e0091ccff52f21" +babel-plugin-transform-es2015-modules-amd@^6.22.0, babel-plugin-transform-es2015-modules-amd@^6.24.0: + version "6.24.0" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-modules-amd/-/babel-plugin-transform-es2015-modules-amd-6.24.0.tgz#a1911fb9b7ec7e05a43a63c5995007557bcf6a2e" dependencies: - babel-plugin-transform-es2015-modules-commonjs "^6.22.0" + babel-plugin-transform-es2015-modules-commonjs "^6.24.0" babel-runtime "^6.22.0" babel-template "^6.22.0" -babel-plugin-transform-es2015-modules-commonjs@^6.22.0: - version "6.23.0" - resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-modules-commonjs/-/babel-plugin-transform-es2015-modules-commonjs-6.23.0.tgz#cba7aa6379fb7ec99250e6d46de2973aaffa7b92" +babel-plugin-transform-es2015-modules-commonjs@^6.23.0, babel-plugin-transform-es2015-modules-commonjs@^6.24.0: + version "6.24.0" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-modules-commonjs/-/babel-plugin-transform-es2015-modules-commonjs-6.24.0.tgz#e921aefb72c2cc26cb03d107626156413222134f" dependencies: babel-plugin-transform-strict-mode "^6.22.0" babel-runtime "^6.22.0" babel-template "^6.23.0" babel-types "^6.23.0" -babel-plugin-transform-es2015-modules-systemjs@^6.22.0: +babel-plugin-transform-es2015-modules-systemjs@^6.23.0: version "6.23.0" resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-modules-systemjs/-/babel-plugin-transform-es2015-modules-systemjs-6.23.0.tgz#ae3469227ffac39b0310d90fec73bfdc4f6317b0" dependencies: @@ -591,11 +439,11 @@ babel-plugin-transform-es2015-modules-systemjs@^6.22.0: babel-runtime "^6.22.0" babel-template "^6.23.0" -babel-plugin-transform-es2015-modules-umd@^6.22.0: - version "6.23.0" - resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-modules-umd/-/babel-plugin-transform-es2015-modules-umd-6.23.0.tgz#8d284ae2e19ed8fe21d2b1b26d6e7e0fcd94f0f1" +babel-plugin-transform-es2015-modules-umd@^6.23.0: + version "6.24.0" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-modules-umd/-/babel-plugin-transform-es2015-modules-umd-6.24.0.tgz#fd5fa63521cae8d273927c3958afd7c067733450" dependencies: - babel-plugin-transform-es2015-modules-amd "^6.22.0" + babel-plugin-transform-es2015-modules-amd "^6.24.0" babel-runtime "^6.22.0" babel-template "^6.23.0" @@ -606,7 +454,7 @@ babel-plugin-transform-es2015-object-super@^6.22.0: babel-helper-replace-supers "^6.22.0" babel-runtime "^6.22.0" -babel-plugin-transform-es2015-parameters@^6.22.0: +babel-plugin-transform-es2015-parameters@^6.23.0: version "6.23.0" resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-parameters/-/babel-plugin-transform-es2015-parameters-6.23.0.tgz#3a2aabb70c8af945d5ce386f1a4250625a83ae3b" dependencies: @@ -644,7 +492,7 @@ babel-plugin-transform-es2015-template-literals@^6.22.0: dependencies: babel-runtime "^6.22.0" -babel-plugin-transform-es2015-typeof-symbol@^6.22.0: +babel-plugin-transform-es2015-typeof-symbol@^6.23.0: version "6.23.0" resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-typeof-symbol/-/babel-plugin-transform-es2015-typeof-symbol-6.23.0.tgz#dec09f1cddff94b52ac73d505c84df59dcceb372" dependencies: @@ -666,27 +514,6 @@ babel-plugin-transform-exponentiation-operator@^6.22.0: babel-plugin-syntax-exponentiation-operator "^6.8.0" babel-runtime "^6.22.0" -babel-plugin-transform-export-extensions@^6.22.0: - version "6.22.0" - resolved "https://registry.yarnpkg.com/babel-plugin-transform-export-extensions/-/babel-plugin-transform-export-extensions-6.22.0.tgz#53738b47e75e8218589eea946cbbd39109bbe653" - dependencies: - babel-plugin-syntax-export-extensions "^6.8.0" - babel-runtime "^6.22.0" - -babel-plugin-transform-flow-strip-types@^6.22.0: - version "6.22.0" - resolved "https://registry.yarnpkg.com/babel-plugin-transform-flow-strip-types/-/babel-plugin-transform-flow-strip-types-6.22.0.tgz#84cb672935d43714fdc32bce84568d87441cf7cf" - dependencies: - babel-plugin-syntax-flow "^6.18.0" - babel-runtime "^6.22.0" - -babel-plugin-transform-function-bind@^6.22.0: - version "6.22.0" - resolved "https://registry.yarnpkg.com/babel-plugin-transform-function-bind/-/babel-plugin-transform-function-bind-6.22.0.tgz#c6fb8e96ac296a310b8cf8ea401462407ddf6a97" - dependencies: - babel-plugin-syntax-function-bind "^6.8.0" - babel-runtime "^6.22.0" - babel-plugin-transform-inline-consecutive-adds@^0.0.2: version "0.0.2" resolved "https://registry.yarnpkg.com/babel-plugin-transform-inline-consecutive-adds/-/babel-plugin-transform-inline-consecutive-adds-0.0.2.tgz#a58fcecfc09c08fbf9373a5a3e70746c03d01fc1" @@ -705,45 +532,10 @@ babel-plugin-transform-minify-booleans@^6.8.0: dependencies: babel-runtime "^6.0.0" -babel-plugin-transform-object-rest-spread@^6.22.0: - version "6.23.0" - resolved "https://registry.yarnpkg.com/babel-plugin-transform-object-rest-spread/-/babel-plugin-transform-object-rest-spread-6.23.0.tgz#875d6bc9be761c58a2ae3feee5dc4895d8c7f921" - dependencies: - babel-plugin-syntax-object-rest-spread "^6.8.0" - babel-runtime "^6.22.0" - babel-plugin-transform-property-literals@^6.8.1: version "6.8.1" resolved "https://registry.yarnpkg.com/babel-plugin-transform-property-literals/-/babel-plugin-transform-property-literals-6.8.1.tgz#05ed01f6024820b18f1d0495c80fe287176bccd9" -babel-plugin-transform-react-display-name@^6.23.0: - version "6.23.0" - resolved "https://registry.yarnpkg.com/babel-plugin-transform-react-display-name/-/babel-plugin-transform-react-display-name-6.23.0.tgz#4398910c358441dc4cef18787264d0412ed36b37" - dependencies: - babel-runtime "^6.22.0" - -babel-plugin-transform-react-jsx-self@^6.22.0: - version "6.22.0" - resolved "https://registry.yarnpkg.com/babel-plugin-transform-react-jsx-self/-/babel-plugin-transform-react-jsx-self-6.22.0.tgz#df6d80a9da2612a121e6ddd7558bcbecf06e636e" - dependencies: - babel-plugin-syntax-jsx "^6.8.0" - babel-runtime "^6.22.0" - -babel-plugin-transform-react-jsx-source@^6.22.0: - version "6.22.0" - resolved "https://registry.yarnpkg.com/babel-plugin-transform-react-jsx-source/-/babel-plugin-transform-react-jsx-source-6.22.0.tgz#66ac12153f5cd2d17b3c19268f4bf0197f44ecd6" - dependencies: - babel-plugin-syntax-jsx "^6.8.0" - babel-runtime "^6.22.0" - -babel-plugin-transform-react-jsx@^6.23.0: - version "6.23.0" - resolved "https://registry.yarnpkg.com/babel-plugin-transform-react-jsx/-/babel-plugin-transform-react-jsx-6.23.0.tgz#23e892f7f2e759678eb5e4446a8f8e94e81b3470" - dependencies: - babel-helper-builder-react-jsx "^6.23.0" - babel-plugin-syntax-jsx "^6.8.0" - babel-runtime "^6.22.0" - babel-plugin-transform-regenerator@^6.22.0: version "6.22.0" resolved "https://registry.yarnpkg.com/babel-plugin-transform-regenerator/-/babel-plugin-transform-regenerator-6.22.0.tgz#65740593a319c44522157538d690b84094617ea6" @@ -811,100 +603,45 @@ babel-preset-babili@^0.0.12: babel-plugin-transform-undefined-to-void "^6.8.0" lodash.isplainobject "^4.0.6" -babel-preset-es2015-rollup@^1.1.1: - version "1.2.0" - resolved "https://registry.yarnpkg.com/babel-preset-es2015-rollup/-/babel-preset-es2015-rollup-1.2.0.tgz#feedf80346e01fa22d4de15e72cde1cefc59bf67" - dependencies: - babel-plugin-external-helpers "^6.4.0" - babel-preset-es2015 "^6.3.13" - modify-babel-preset "^2.1.1" - -babel-preset-es2015@^6.3.13, babel-preset-es2015@^6.6.0: - version "6.22.0" - resolved "https://registry.yarnpkg.com/babel-preset-es2015/-/babel-preset-es2015-6.22.0.tgz#af5a98ecb35eb8af764ad8a5a05eb36dc4386835" +babel-preset-env@^1.3.2: + version "1.3.2" + resolved "https://registry.yarnpkg.com/babel-preset-env/-/babel-preset-env-1.3.2.tgz#08eabd2bf810c3678069f7e052323419f1448749" dependencies: babel-plugin-check-es2015-constants "^6.22.0" + babel-plugin-syntax-trailing-function-commas "^6.22.0" + babel-plugin-transform-async-to-generator "^6.22.0" babel-plugin-transform-es2015-arrow-functions "^6.22.0" babel-plugin-transform-es2015-block-scoped-functions "^6.22.0" - babel-plugin-transform-es2015-block-scoping "^6.22.0" - babel-plugin-transform-es2015-classes "^6.22.0" + babel-plugin-transform-es2015-block-scoping "^6.23.0" + babel-plugin-transform-es2015-classes "^6.23.0" babel-plugin-transform-es2015-computed-properties "^6.22.0" - babel-plugin-transform-es2015-destructuring "^6.22.0" + babel-plugin-transform-es2015-destructuring "^6.23.0" babel-plugin-transform-es2015-duplicate-keys "^6.22.0" - babel-plugin-transform-es2015-for-of "^6.22.0" + babel-plugin-transform-es2015-for-of "^6.23.0" babel-plugin-transform-es2015-function-name "^6.22.0" babel-plugin-transform-es2015-literals "^6.22.0" babel-plugin-transform-es2015-modules-amd "^6.22.0" - babel-plugin-transform-es2015-modules-commonjs "^6.22.0" - babel-plugin-transform-es2015-modules-systemjs "^6.22.0" - babel-plugin-transform-es2015-modules-umd "^6.22.0" + babel-plugin-transform-es2015-modules-commonjs "^6.23.0" + babel-plugin-transform-es2015-modules-systemjs "^6.23.0" + babel-plugin-transform-es2015-modules-umd "^6.23.0" babel-plugin-transform-es2015-object-super "^6.22.0" - babel-plugin-transform-es2015-parameters "^6.22.0" + babel-plugin-transform-es2015-parameters "^6.23.0" babel-plugin-transform-es2015-shorthand-properties "^6.22.0" babel-plugin-transform-es2015-spread "^6.22.0" babel-plugin-transform-es2015-sticky-regex "^6.22.0" babel-plugin-transform-es2015-template-literals "^6.22.0" - babel-plugin-transform-es2015-typeof-symbol "^6.22.0" + babel-plugin-transform-es2015-typeof-symbol "^6.23.0" babel-plugin-transform-es2015-unicode-regex "^6.22.0" - babel-plugin-transform-regenerator "^6.22.0" - -babel-preset-flow@^6.23.0: - version "6.23.0" - resolved "https://registry.yarnpkg.com/babel-preset-flow/-/babel-preset-flow-6.23.0.tgz#e71218887085ae9a24b5be4169affb599816c49d" - dependencies: - babel-plugin-transform-flow-strip-types "^6.22.0" - -babel-preset-react@^6.5.0: - version "6.23.0" - resolved "https://registry.yarnpkg.com/babel-preset-react/-/babel-preset-react-6.23.0.tgz#eb7cee4de98a3f94502c28565332da9819455195" - dependencies: - babel-plugin-syntax-jsx "^6.3.13" - babel-plugin-transform-react-display-name "^6.23.0" - babel-plugin-transform-react-jsx "^6.23.0" - babel-plugin-transform-react-jsx-self "^6.22.0" - babel-plugin-transform-react-jsx-source "^6.22.0" - babel-preset-flow "^6.23.0" - -babel-preset-stage-0@^6.5.0: - version "6.22.0" - resolved "https://registry.yarnpkg.com/babel-preset-stage-0/-/babel-preset-stage-0-6.22.0.tgz#707eeb5b415da769eff9c42f4547f644f9296ef9" - dependencies: - babel-plugin-transform-do-expressions "^6.22.0" - babel-plugin-transform-function-bind "^6.22.0" - babel-preset-stage-1 "^6.22.0" - -babel-preset-stage-1@^6.22.0: - version "6.22.0" - resolved "https://registry.yarnpkg.com/babel-preset-stage-1/-/babel-preset-stage-1-6.22.0.tgz#7da05bffea6ad5a10aef93e320cfc6dd465dbc1a" - dependencies: - babel-plugin-transform-class-constructor-call "^6.22.0" - babel-plugin-transform-export-extensions "^6.22.0" - babel-preset-stage-2 "^6.22.0" - -babel-preset-stage-2@^6.22.0: - version "6.22.0" - resolved "https://registry.yarnpkg.com/babel-preset-stage-2/-/babel-preset-stage-2-6.22.0.tgz#ccd565f19c245cade394b21216df704a73b27c07" - dependencies: - babel-plugin-syntax-dynamic-import "^6.18.0" - babel-plugin-transform-class-properties "^6.22.0" - babel-plugin-transform-decorators "^6.22.0" - babel-preset-stage-3 "^6.22.0" - -babel-preset-stage-3@^6.22.0: - version "6.22.0" - resolved "https://registry.yarnpkg.com/babel-preset-stage-3/-/babel-preset-stage-3-6.22.0.tgz#a4e92bbace7456fafdf651d7a7657ee0bbca9c2e" - dependencies: - babel-plugin-syntax-trailing-function-commas "^6.22.0" - babel-plugin-transform-async-generator-functions "^6.22.0" - babel-plugin-transform-async-to-generator "^6.22.0" babel-plugin-transform-exponentiation-operator "^6.22.0" - babel-plugin-transform-object-rest-spread "^6.22.0" + babel-plugin-transform-regenerator "^6.22.0" + browserslist "^1.4.0" + invariant "^2.2.2" -babel-register@^6.23.0: - version "6.23.0" - resolved "https://registry.yarnpkg.com/babel-register/-/babel-register-6.23.0.tgz#c9aa3d4cca94b51da34826c4a0f9e08145d74ff3" +babel-register@^6.24.0: + version "6.24.0" + resolved "https://registry.yarnpkg.com/babel-register/-/babel-register-6.24.0.tgz#5e89f8463ba9970356d02eb07dabe3308b080cfd" dependencies: - babel-core "^6.23.0" + babel-core "^6.24.0" babel-runtime "^6.22.0" core-js "^2.4.0" home-or-tmp "^2.0.0" @@ -952,10 +689,6 @@ babel-types@^6.19.0, babel-types@^6.22.0, babel-types@^6.23.0: lodash "^4.2.0" to-fast-properties "^1.0.1" -babel@^6.5.2: - version "6.23.0" - resolved "https://registry.yarnpkg.com/babel/-/babel-6.23.0.tgz#d0d1e7d803e974765beea3232d4e153c0efb90f4" - babylon@^6.11.0, babylon@^6.15.0: version "6.16.1" resolved "https://registry.yarnpkg.com/babylon/-/babylon-6.16.1.tgz#30c5a22f481978a9e7f8cdfdf496b11d94b404d3" @@ -964,10 +697,6 @@ balanced-match@^0.4.1: version "0.4.2" resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-0.4.2.tgz#cb3f3e3c732dc0f01ee70b403f302e61d7709838" -beeper@^1.0.0: - version "1.1.1" - resolved "https://registry.yarnpkg.com/beeper/-/beeper-1.1.1.tgz#e6d5ea8c5dad001304a70b22638447f69cb2f809" - brace-expansion@^1.0.0: version "1.1.6" resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.6.tgz#7197d7eaa9b87e648390ea61fc66c84427420df9" @@ -975,20 +704,23 @@ brace-expansion@^1.0.0: balanced-match "^0.4.1" concat-map "0.0.1" -braces@^1.8.2: - version "1.8.5" - resolved "https://registry.yarnpkg.com/braces/-/braces-1.8.5.tgz#ba77962e12dff969d6b76711e914b737857bf6a7" - dependencies: - expand-range "^1.8.1" - preserve "^0.2.0" - repeat-element "^1.1.2" - browser-resolve@^1.11.0: version "1.11.2" resolved "https://registry.yarnpkg.com/browser-resolve/-/browser-resolve-1.11.2.tgz#8ff09b0a2c421718a1051c260b32e48f442938ce" dependencies: resolve "1.1.7" +browser-stdout@1.3.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/browser-stdout/-/browser-stdout-1.3.0.tgz#f351d32969d32fa5d7a5567154263d928ae3bd1f" + +browserslist@^1.4.0: + version "1.7.7" + resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-1.7.7.tgz#0bd76704258be829b2398bb50e4b62d1a166b0b9" + dependencies: + caniuse-db "^1.0.30000639" + electron-to-chromium "^1.2.7" + buffer-shims@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/buffer-shims/-/buffer-shims-1.0.0.tgz#9978ce317388c649ad8793028c3477ef044a8b51" @@ -1007,6 +739,10 @@ callsites@^0.2.0: version "0.2.0" resolved "https://registry.yarnpkg.com/callsites/-/callsites-0.2.0.tgz#afab96262910a7f33c19a5775825c69f34e350ca" +caniuse-db@^1.0.30000639: + version "1.0.30000646" + resolved "https://registry.yarnpkg.com/caniuse-db/-/caniuse-db-1.0.30000646.tgz#c724b90d61df24286e015fc528d062073c00def4" + chai@^3.5.0: version "3.5.0" resolved "https://registry.yarnpkg.com/chai/-/chai-3.5.0.tgz#4d02637b067fe958bdbfdd3a40ec56fef7373247" @@ -1039,18 +775,6 @@ cli-width@^2.0.0: version "2.1.0" resolved "https://registry.yarnpkg.com/cli-width/-/cli-width-2.1.0.tgz#b234ca209b29ef66fc518d9b98d5847b00edf00a" -clone-stats@^0.0.1: - version "0.0.1" - resolved "https://registry.yarnpkg.com/clone-stats/-/clone-stats-0.0.1.tgz#b88f94a82cf38b8791d58046ea4029ad88ca99d1" - -clone@^0.2.0: - version "0.2.0" - resolved "https://registry.yarnpkg.com/clone/-/clone-0.2.0.tgz#c6126a90ad4f72dbf5acdb243cc37724fe93fc1f" - -clone@^1.0.0, clone@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/clone/-/clone-1.0.2.tgz#260b7a99ebb1edfe247538175f783243cb19d149" - co@^4.6.0: version "4.6.0" resolved "https://registry.yarnpkg.com/co/-/co-4.6.0.tgz#6ea6bdf3d853ae54ccb8e47bfa0bf3f9031fb184" @@ -1059,19 +783,17 @@ code-point-at@^1.0.0: version "1.1.0" resolved "https://registry.yarnpkg.com/code-point-at/-/code-point-at-1.1.0.tgz#0d070b4d043a5bea33a2f1a40e2edb3d9a4ccf77" -commander@0.6.1: - version "0.6.1" - resolved "https://registry.yarnpkg.com/commander/-/commander-0.6.1.tgz#fa68a14f6a945d54dbbe50d8cdb3320e9e3b1a06" - -commander@2.3.0: - version "2.3.0" - resolved "https://registry.yarnpkg.com/commander/-/commander-2.3.0.tgz#fd430e889832ec353b9acd1de217c11cb3eef873" +commander@2.9.0: + version "2.9.0" + resolved "https://registry.yarnpkg.com/commander/-/commander-2.9.0.tgz#9c99094176e12240cb22d6c5146098400fe0f7d4" + dependencies: + graceful-readlink ">= 1.0.0" concat-map@0.0.1: version "0.0.1" resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b" -concat-stream@^1.4.6: +concat-stream@^1.5.2: version "1.6.0" resolved "https://registry.yarnpkg.com/concat-stream/-/concat-stream-1.6.0.tgz#0aac662fd52be78964d5532f694784e70110acf7" dependencies: @@ -1083,9 +805,9 @@ contains-path@^0.1.0: version "0.1.0" resolved "https://registry.yarnpkg.com/contains-path/-/contains-path-0.1.0.tgz#fe8cf184ff6670b6baef01a9d4861a5cbec4120a" -convert-source-map@1.X, convert-source-map@^1.1.0: - version "1.4.0" - resolved "https://registry.yarnpkg.com/convert-source-map/-/convert-source-map-1.4.0.tgz#e3dad195bf61bfe13a7a3c73e9876ec14a0268f3" +convert-source-map@^1.1.0: + version "1.5.0" + resolved "https://registry.yarnpkg.com/convert-source-map/-/convert-source-map-1.5.0.tgz#9acd70851c6d5dfdd93d9282e5edf94a03ff46b5" core-js@^2.4.0: version "2.4.1" @@ -1095,32 +817,11 @@ core-util-is@~1.0.0: version "1.0.2" resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.2.tgz#b5fd54220aa2bc5ab57aab7140c940754503c1a7" -css@2.X: - version "2.2.1" - resolved "https://registry.yarnpkg.com/css/-/css-2.2.1.tgz#73a4c81de85db664d4ee674f7d47085e3b2d55dc" - dependencies: - inherits "^2.0.1" - source-map "^0.1.38" - source-map-resolve "^0.3.0" - urix "^0.1.0" - -d@^0.1.1, d@~0.1.1: - version "0.1.1" - resolved "https://registry.yarnpkg.com/d/-/d-0.1.1.tgz#da184c535d18d8ee7ba2aa229b914009fae11309" - dependencies: - es5-ext "~0.10.2" - -dateformat@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/dateformat/-/dateformat-2.0.0.tgz#2743e3abb5c3fc2462e527dca445e04e9f4dee17" - -debug-fabulous@0.0.X: - version "0.0.4" - resolved "https://registry.yarnpkg.com/debug-fabulous/-/debug-fabulous-0.0.4.tgz#fa071c5d87484685424807421ca4b16b0b1a0763" +d@1: + version "1.0.0" + resolved "https://registry.yarnpkg.com/d/-/d-1.0.0.tgz#754bb5bfe55451da69a58b94d45f4c5b0462d58f" dependencies: - debug "2.X" - lazy-debug-legacy "0.0.X" - object-assign "4.1.0" + es5-ext "^0.10.9" debug@2.2.0: version "2.2.0" @@ -1128,9 +829,9 @@ debug@2.2.0: dependencies: ms "0.7.1" -debug@2.X, debug@^2.1.1, debug@^2.2.0: - version "2.6.1" - resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.1.tgz#79855090ba2c4e3115cc7d8769491d58f0491351" +debug@^2.1.1, debug@^2.2.0: + version "2.6.3" + resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.3.tgz#0f7eb8c30965ec08c72accfa0130c8b79984141d" dependencies: ms "0.7.2" @@ -1144,12 +845,6 @@ deep-is@~0.1.3: version "0.1.3" resolved "https://registry.yarnpkg.com/deep-is/-/deep-is-0.1.3.tgz#b369d6fb5dbc13eecf524f91b070feedc357cf34" -defaults@^1.0.0: - version "1.0.3" - resolved "https://registry.yarnpkg.com/defaults/-/defaults-1.0.3.tgz#c656051e9817d9ff08ed881477f3fe4019f3ef7d" - dependencies: - clone "^1.0.2" - del@^2.0.2: version "2.2.2" resolved "https://registry.yarnpkg.com/del/-/del-2.2.2.tgz#c12c981d067846c84bcaf862cff930d907ffd1a8" @@ -1162,110 +857,91 @@ del@^2.0.2: pinkie-promise "^2.0.0" rimraf "^2.2.8" -deprecated@^0.0.1: - version "0.0.1" - resolved "https://registry.yarnpkg.com/deprecated/-/deprecated-0.0.1.tgz#f9c9af5464afa1e7a971458a8bdef2aa94d5bb19" - -detect-file@^0.1.0: - version "0.1.0" - resolved "https://registry.yarnpkg.com/detect-file/-/detect-file-0.1.0.tgz#4935dedfd9488648e006b0129566e9386711ea63" - dependencies: - fs-exists-sync "^0.1.0" - detect-indent@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/detect-indent/-/detect-indent-4.0.0.tgz#f76d064352cdf43a1cb6ce619c4ee3a9475de208" dependencies: repeating "^2.0.0" -detect-newline@2.X: - version "2.1.0" - resolved "https://registry.yarnpkg.com/detect-newline/-/detect-newline-2.1.0.tgz#f41f1c10be4b00e87b5f13da680759f2c5bfd3e2" - diff@1.4.0: version "1.4.0" resolved "https://registry.yarnpkg.com/diff/-/diff-1.4.0.tgz#7f28d2eb9ee7b15a97efd89ce63dcfdaa3ccbabf" -doctrine@1.5.0, doctrine@^1.2.2: +doctrine@1.5.0: version "1.5.0" resolved "https://registry.yarnpkg.com/doctrine/-/doctrine-1.5.0.tgz#379dce730f6166f76cefa4e6707a159b02c5a6fa" dependencies: esutils "^2.0.2" isarray "^1.0.0" -duplexer2@0.0.2: - version "0.0.2" - resolved "https://registry.yarnpkg.com/duplexer2/-/duplexer2-0.0.2.tgz#c614dcf67e2fb14995a91711e5a617e8a60a31db" +doctrine@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/doctrine/-/doctrine-2.0.0.tgz#c73d8d2909d22291e1a007a395804da8b665fe63" dependencies: - readable-stream "~1.1.9" + esutils "^2.0.2" + isarray "^1.0.0" -end-of-stream@~0.1.5: - version "0.1.5" - resolved "https://registry.yarnpkg.com/end-of-stream/-/end-of-stream-0.1.5.tgz#8e177206c3c80837d85632e8b9359dfe8b2f6eaf" - dependencies: - once "~1.3.0" +electron-to-chromium@^1.2.7: + version "1.3.2" + resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.3.2.tgz#b8ce5c93b308db0e92f6d0435c46ddec8f6363ab" erlang-types@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/erlang-types/-/erlang-types-1.0.0.tgz#e555bd091667498a01d340d18203231dc96d962f" -es5-ext@^0.10.7, es5-ext@^0.10.8, es5-ext@~0.10.11, es5-ext@~0.10.2, es5-ext@~0.10.7: - version "0.10.12" - resolved "https://registry.yarnpkg.com/es5-ext/-/es5-ext-0.10.12.tgz#aa84641d4db76b62abba5e45fd805ecbab140047" +es5-ext@^0.10.14, es5-ext@^0.10.9, es5-ext@~0.10.14: + version "0.10.15" + resolved "https://registry.yarnpkg.com/es5-ext/-/es5-ext-0.10.15.tgz#c330a5934c1ee21284a7c081a86e5fd937c91ea6" dependencies: es6-iterator "2" es6-symbol "~3.1" -es6-iterator@2: - version "2.0.0" - resolved "https://registry.yarnpkg.com/es6-iterator/-/es6-iterator-2.0.0.tgz#bd968567d61635e33c0b80727613c9cb4b096bac" +es6-iterator@2, es6-iterator@^2.0.1, es6-iterator@~2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/es6-iterator/-/es6-iterator-2.0.1.tgz#8e319c9f0453bf575d374940a655920e59ca5512" dependencies: - d "^0.1.1" - es5-ext "^0.10.7" - es6-symbol "3" + d "1" + es5-ext "^0.10.14" + es6-symbol "^3.1" es6-map@^0.1.3: - version "0.1.4" - resolved "https://registry.yarnpkg.com/es6-map/-/es6-map-0.1.4.tgz#a34b147be224773a4d7da8072794cefa3632b897" + version "0.1.5" + resolved "https://registry.yarnpkg.com/es6-map/-/es6-map-0.1.5.tgz#9136e0503dcc06a301690f0bb14ff4e364e949f0" dependencies: - d "~0.1.1" - es5-ext "~0.10.11" - es6-iterator "2" - es6-set "~0.1.3" - es6-symbol "~3.1.0" - event-emitter "~0.3.4" + d "1" + es5-ext "~0.10.14" + es6-iterator "~2.0.1" + es6-set "~0.1.5" + es6-symbol "~3.1.1" + event-emitter "~0.3.5" -es6-set@~0.1.3: - version "0.1.4" - resolved "https://registry.yarnpkg.com/es6-set/-/es6-set-0.1.4.tgz#9516b6761c2964b92ff479456233a247dc707ce8" +es6-set@~0.1.5: + version "0.1.5" + resolved "https://registry.yarnpkg.com/es6-set/-/es6-set-0.1.5.tgz#d2b3ec5d4d800ced818db538d28974db0a73ccb1" dependencies: - d "~0.1.1" - es5-ext "~0.10.11" - es6-iterator "2" - es6-symbol "3" - event-emitter "~0.3.4" + d "1" + es5-ext "~0.10.14" + es6-iterator "~2.0.1" + es6-symbol "3.1.1" + event-emitter "~0.3.5" -es6-symbol@3, es6-symbol@~3.1, es6-symbol@~3.1.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/es6-symbol/-/es6-symbol-3.1.0.tgz#94481c655e7a7cad82eba832d97d5433496d7ffa" +es6-symbol@3.1.1, es6-symbol@^3.1, es6-symbol@^3.1.1, es6-symbol@~3.1, es6-symbol@~3.1.1: + version "3.1.1" + resolved "https://registry.yarnpkg.com/es6-symbol/-/es6-symbol-3.1.1.tgz#bf00ef4fdab6ba1b46ecb7b629b4c7ed5715cc77" dependencies: - d "~0.1.1" - es5-ext "~0.10.11" + d "1" + es5-ext "~0.10.14" es6-weak-map@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/es6-weak-map/-/es6-weak-map-2.0.1.tgz#0d2bbd8827eb5fb4ba8f97fbfea50d43db21ea81" + version "2.0.2" + resolved "https://registry.yarnpkg.com/es6-weak-map/-/es6-weak-map-2.0.2.tgz#5e3ab32251ffd1538a1f8e5ffa1357772f92d96f" dependencies: - d "^0.1.1" - es5-ext "^0.10.8" - es6-iterator "2" - es6-symbol "3" - -escape-string-regexp@1.0.2, escape-string-regexp@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.2.tgz#4dbc2fe674e71949caf3fb2695ce7f2dc1d9a8d1" + d "1" + es5-ext "^0.10.14" + es6-iterator "^2.0.1" + es6-symbol "^3.1.1" -escape-string-regexp@^1.0.5: +escape-string-regexp@1.0.5, escape-string-regexp@^1.0.2, escape-string-regexp@^1.0.5: version "1.0.5" resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4" @@ -1279,8 +955,8 @@ escope@^3.6.0: estraverse "^4.1.1" eslint-config-airbnb-base@^11.1.0: - version "11.1.0" - resolved "https://registry.yarnpkg.com/eslint-config-airbnb-base/-/eslint-config-airbnb-base-11.1.0.tgz#dc9b3ec70b8c74dcbe6d6257c9da3992c39ca2ca" + version "11.1.2" + resolved "https://registry.yarnpkg.com/eslint-config-airbnb-base/-/eslint-config-airbnb-base-11.1.2.tgz#259209a7678bf693e31cbe8f953f206b6aa7ccc3" eslint-import-resolver-node@^0.2.0: version "0.2.3" @@ -1313,16 +989,17 @@ eslint-plugin-import@^2.2.0: pkg-up "^1.0.0" eslint@^3.15.0: - version "3.16.1" - resolved "https://registry.yarnpkg.com/eslint/-/eslint-3.16.1.tgz#9bc31fc7341692cf772e80607508f67d711c5609" + version "3.19.0" + resolved "https://registry.yarnpkg.com/eslint/-/eslint-3.19.0.tgz#c8fc6201c7f40dd08941b87c085767386a679acc" dependencies: babel-code-frame "^6.16.0" chalk "^1.1.3" - concat-stream "^1.4.6" + concat-stream "^1.5.2" debug "^2.1.1" - doctrine "^1.2.2" + doctrine "^2.0.0" escope "^3.6.0" espree "^3.4.0" + esquery "^1.0.0" estraverse "^4.2.0" esutils "^2.0.2" file-entry-cache "^2.0.0" @@ -1352,16 +1029,22 @@ eslint@^3.15.0: user-home "^2.0.0" espree@^3.4.0: - version "3.4.0" - resolved "https://registry.yarnpkg.com/espree/-/espree-3.4.0.tgz#41656fa5628e042878025ef467e78f125cb86e1d" + version "3.4.1" + resolved "https://registry.yarnpkg.com/espree/-/espree-3.4.1.tgz#28a83ab4aaed71ed8fe0f5efe61b76a05c13c4d2" dependencies: - acorn "4.0.4" + acorn "^5.0.1" acorn-jsx "^3.0.0" esprima@^3.1.1: version "3.1.3" resolved "https://registry.yarnpkg.com/esprima/-/esprima-3.1.3.tgz#fdca51cee6133895e3c88d535ce49dbff62a4633" +esquery@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/esquery/-/esquery-1.0.0.tgz#cfba8b57d7fba93f17298a8a006a04cda13d80fa" + dependencies: + estraverse "^4.0.0" + esrecurse@^4.1.0: version "4.1.0" resolved "https://registry.yarnpkg.com/esrecurse/-/esrecurse-4.1.0.tgz#4713b6536adf7f2ac4f327d559e7756bff648220" @@ -1369,7 +1052,7 @@ esrecurse@^4.1.0: estraverse "~4.1.0" object-assign "^4.0.1" -estraverse@^4.1.1, estraverse@^4.2.0: +estraverse@^4.0.0, estraverse@^4.1.1, estraverse@^4.2.0: version "4.2.0" resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-4.2.0.tgz#0dee3fed31fcd469618ce7342099fc1afa0bdb13" @@ -1381,56 +1064,21 @@ estree-walker@^0.2.1: version "0.2.1" resolved "https://registry.yarnpkg.com/estree-walker/-/estree-walker-0.2.1.tgz#bdafe8095383d8414d5dc2ecf4c9173b6db9412e" -esutils@^2.0.0, esutils@^2.0.2: +esutils@^2.0.2: version "2.0.2" resolved "https://registry.yarnpkg.com/esutils/-/esutils-2.0.2.tgz#0abf4f1caa5bcb1f7a9d8acc6dea4faaa04bac9b" -event-emitter@~0.3.4: - version "0.3.4" - resolved "https://registry.yarnpkg.com/event-emitter/-/event-emitter-0.3.4.tgz#8d63ddfb4cfe1fae3b32ca265c4c720222080bb5" +event-emitter@~0.3.5: + version "0.3.5" + resolved "https://registry.yarnpkg.com/event-emitter/-/event-emitter-0.3.5.tgz#df8c69eef1647923c7157b9ce83840610b02cc39" dependencies: - d "~0.1.1" - es5-ext "~0.10.7" + d "1" + es5-ext "~0.10.14" exit-hook@^1.0.0: version "1.1.1" resolved "https://registry.yarnpkg.com/exit-hook/-/exit-hook-1.1.1.tgz#f05ca233b48c05d54fff07765df8507e95c02ff8" -expand-brackets@^0.1.4: - version "0.1.5" - resolved "https://registry.yarnpkg.com/expand-brackets/-/expand-brackets-0.1.5.tgz#df07284e342a807cd733ac5af72411e581d1177b" - dependencies: - is-posix-bracket "^0.1.0" - -expand-range@^1.8.1: - version "1.8.2" - resolved "https://registry.yarnpkg.com/expand-range/-/expand-range-1.8.2.tgz#a299effd335fe2721ebae8e257ec79644fc85337" - dependencies: - fill-range "^2.1.0" - -expand-tilde@^1.2.1, expand-tilde@^1.2.2: - version "1.2.2" - resolved "https://registry.yarnpkg.com/expand-tilde/-/expand-tilde-1.2.2.tgz#0b81eba897e5a3d31d1c3d102f8f01441e559449" - dependencies: - os-homedir "^1.0.1" - -extend@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/extend/-/extend-3.0.0.tgz#5a474353b9f3353ddd8176dfd37b91c83a46f1d4" - -extglob@^0.3.1: - version "0.3.2" - resolved "https://registry.yarnpkg.com/extglob/-/extglob-0.3.2.tgz#2e18ff3d2f49ab2765cec9023f011daa8d8349a1" - dependencies: - is-extglob "^1.0.0" - -fancy-log@^1.1.0: - version "1.3.0" - resolved "https://registry.yarnpkg.com/fancy-log/-/fancy-log-1.3.0.tgz#45be17d02bb9917d60ccffd4995c999e6c8c9948" - dependencies: - chalk "^1.1.1" - time-stamp "^1.0.0" - fast-levenshtein@~2.0.4: version "2.0.6" resolved "https://registry.yarnpkg.com/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz#3d8a5c66883a16a30ca8643e851f19baa7797917" @@ -1449,24 +1097,6 @@ file-entry-cache@^2.0.0: flat-cache "^1.2.1" object-assign "^4.0.1" -filename-regex@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/filename-regex/-/filename-regex-2.0.0.tgz#996e3e80479b98b9897f15a8a58b3d084e926775" - -fill-range@^2.1.0: - version "2.2.3" - resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-2.2.3.tgz#50b77dfd7e469bc7492470963699fe7a8485a723" - dependencies: - is-number "^2.1.0" - isobject "^2.0.0" - randomatic "^1.1.3" - repeat-element "^1.1.2" - repeat-string "^1.5.2" - -find-index@^0.1.1: - version "0.1.1" - resolved "https://registry.yarnpkg.com/find-index/-/find-index-0.1.1.tgz#675d358b2ca3892d795a1ab47232f8b6e2e0dde4" - find-up@^1.0.0: version "1.1.2" resolved "https://registry.yarnpkg.com/find-up/-/find-up-1.1.2.tgz#6b2e9822b1a2ce0a60ab64d610eccad53cb24d0f" @@ -1474,35 +1104,6 @@ find-up@^1.0.0: path-exists "^2.0.0" pinkie-promise "^2.0.0" -findup-sync@^0.4.2: - version "0.4.3" - resolved "https://registry.yarnpkg.com/findup-sync/-/findup-sync-0.4.3.tgz#40043929e7bc60adf0b7f4827c4c6e75a0deca12" - dependencies: - detect-file "^0.1.0" - is-glob "^2.0.1" - micromatch "^2.3.7" - resolve-dir "^0.1.0" - -fined@^1.0.1: - version "1.0.2" - resolved "https://registry.yarnpkg.com/fined/-/fined-1.0.2.tgz#5b28424b760d7598960b7ef8480dff8ad3660e97" - dependencies: - expand-tilde "^1.2.1" - lodash.assignwith "^4.0.7" - lodash.isempty "^4.2.1" - lodash.isplainobject "^4.0.4" - lodash.isstring "^4.0.1" - lodash.pick "^4.2.1" - parse-filepath "^1.0.1" - -first-chunk-stream@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/first-chunk-stream/-/first-chunk-stream-1.0.0.tgz#59bfb50cd905f60d7c394cd3d9acaab4e6ad934e" - -flagged-respawn@^0.3.2: - version "0.3.2" - resolved "https://registry.yarnpkg.com/flagged-respawn/-/flagged-respawn-0.3.2.tgz#ff191eddcd7088a675b2610fffc976be9b8074b5" - flat-cache@^1.2.1: version "1.2.2" resolved "https://registry.yarnpkg.com/flat-cache/-/flat-cache-1.2.2.tgz#fa86714e72c21db88601761ecf2f555d1abc6b96" @@ -1512,26 +1113,12 @@ flat-cache@^1.2.1: graceful-fs "^4.1.2" write "^0.2.1" -for-in@^0.1.5: - version "0.1.6" - resolved "https://registry.yarnpkg.com/for-in/-/for-in-0.1.6.tgz#c9f96e89bfad18a545af5ec3ed352a1d9e5b4dc8" - -for-own@^0.1.4: - version "0.1.4" - resolved "https://registry.yarnpkg.com/for-own/-/for-own-0.1.4.tgz#0149b41a39088c7515f51ebe1c1386d45f935072" - dependencies: - for-in "^0.1.5" - formatio@1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/formatio/-/formatio-1.1.1.tgz#5ed3ccd636551097383465d996199100e86161e9" dependencies: samsam "~1.1" -fs-exists-sync@^0.1.0: - version "0.1.0" - resolved "https://registry.yarnpkg.com/fs-exists-sync/-/fs-exists-sync-0.1.0.tgz#982d6893af918e72d08dec9e8673ff2b5a8d6add" - fs.realpath@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f" @@ -1540,12 +1127,6 @@ function-bind@^1.0.2: version "1.1.0" resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.0.tgz#16176714c801798e4e8f2cf7f7529467bb4a5771" -gaze@^0.5.1: - version "0.5.2" - resolved "https://registry.yarnpkg.com/gaze/-/gaze-0.5.2.tgz#40b709537d24d1d45767db5a908689dfe69ac44f" - dependencies: - globule "~0.1.0" - generate-function@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/generate-function/-/generate-function-2.0.0.tgz#6858fe7c0969b7d4e9093337647ac79f60dfbe74" @@ -1556,57 +1137,16 @@ generate-object-property@^1.1.0: dependencies: is-property "^1.0.0" -glob-base@^0.3.0: - version "0.3.0" - resolved "https://registry.yarnpkg.com/glob-base/-/glob-base-0.3.0.tgz#dbb164f6221b1c0b1ccf82aea328b497df0ea3c4" - dependencies: - glob-parent "^2.0.0" - is-glob "^2.0.0" - -glob-parent@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-2.0.0.tgz#81383d72db054fcccf5336daa902f182f6edbb28" - dependencies: - is-glob "^2.0.0" - -glob-stream@^3.1.5: - version "3.1.18" - resolved "https://registry.yarnpkg.com/glob-stream/-/glob-stream-3.1.18.tgz#9170a5f12b790306fdfe598f313f8f7954fd143b" - dependencies: - glob "^4.3.1" - glob2base "^0.0.12" - minimatch "^2.0.1" - ordered-read-streams "^0.1.0" - through2 "^0.6.1" - unique-stream "^1.0.0" - -glob-watcher@^0.0.6: - version "0.0.6" - resolved "https://registry.yarnpkg.com/glob-watcher/-/glob-watcher-0.0.6.tgz#b95b4a8df74b39c83298b0c05c978b4d9a3b710b" - dependencies: - gaze "^0.5.1" - -glob2base@^0.0.12: - version "0.0.12" - resolved "https://registry.yarnpkg.com/glob2base/-/glob2base-0.0.12.tgz#9d419b3e28f12e83a362164a277055922c9c0d56" - dependencies: - find-index "^0.1.1" - -glob@3.2.11: - version "3.2.11" - resolved "https://registry.yarnpkg.com/glob/-/glob-3.2.11.tgz#4a973f635b9190f715d10987d5c00fd2815ebe3d" - dependencies: - inherits "2" - minimatch "0.3" - -glob@^4.3.1: - version "4.5.3" - resolved "https://registry.yarnpkg.com/glob/-/glob-4.5.3.tgz#c6cb73d3226c1efef04de3c56d012f03377ee15f" +glob@7.0.5: + version "7.0.5" + resolved "https://registry.yarnpkg.com/glob/-/glob-7.0.5.tgz#b4202a69099bbb4d292a7c1b95b6682b67ebdc95" dependencies: + fs.realpath "^1.0.0" inflight "^1.0.4" inherits "2" - minimatch "^2.0.1" + minimatch "^3.0.2" once "^1.3.0" + path-is-absolute "^1.0.0" glob@^7.0.0, glob@^7.0.3, glob@^7.0.5: version "7.1.1" @@ -1619,33 +1159,9 @@ glob@^7.0.0, glob@^7.0.3, glob@^7.0.5: once "^1.3.0" path-is-absolute "^1.0.0" -glob@~3.1.21: - version "3.1.21" - resolved "https://registry.yarnpkg.com/glob/-/glob-3.1.21.tgz#d29e0a055dea5138f4d07ed40e8982e83c2066cd" - dependencies: - graceful-fs "~1.2.0" - inherits "1" - minimatch "~0.2.11" - -global-modules@^0.2.3: - version "0.2.3" - resolved "https://registry.yarnpkg.com/global-modules/-/global-modules-0.2.3.tgz#ea5a3bed42c6d6ce995a4f8a1269b5dae223828d" - dependencies: - global-prefix "^0.1.4" - is-windows "^0.2.0" - -global-prefix@^0.1.4: - version "0.1.5" - resolved "https://registry.yarnpkg.com/global-prefix/-/global-prefix-0.1.5.tgz#8d3bc6b8da3ca8112a160d8d496ff0462bfef78f" - dependencies: - homedir-polyfill "^1.0.0" - ini "^1.3.4" - is-windows "^0.2.0" - which "^1.2.12" - globals@^9.0.0, globals@^9.14.0: - version "9.16.0" - resolved "https://registry.yarnpkg.com/globals/-/globals-9.16.0.tgz#63e903658171ec2d9f51b1d31de5e2b8dc01fb80" + version "9.17.0" + resolved "https://registry.yarnpkg.com/globals/-/globals-9.17.0.tgz#0c0ca696d9b9bb694d2e5470bd37777caad50286" globby@^5.0.0: version "5.0.0" @@ -1658,122 +1174,27 @@ globby@^5.0.0: pify "^2.0.0" pinkie-promise "^2.0.0" -globule@~0.1.0: - version "0.1.0" - resolved "https://registry.yarnpkg.com/globule/-/globule-0.1.0.tgz#d9c8edde1da79d125a151b79533b978676346ae5" - dependencies: - glob "~3.1.21" - lodash "~1.0.1" - minimatch "~0.2.11" - -glogg@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/glogg/-/glogg-1.0.0.tgz#7fe0f199f57ac906cf512feead8f90ee4a284fc5" - dependencies: - sparkles "^1.0.0" - -graceful-fs@4.X, graceful-fs@^4.1.2: +graceful-fs@^4.1.2: version "4.1.11" resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.1.11.tgz#0e8bdfe4d1ddb8854d64e04ea7c00e2a026e5658" -graceful-fs@^3.0.0: - version "3.0.11" - resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-3.0.11.tgz#7613c778a1afea62f25c630a086d7f3acbbdd818" - dependencies: - natives "^1.1.0" - -graceful-fs@~1.2.0: - version "1.2.3" - resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-1.2.3.tgz#15a4806a57547cb2d2dbf27f42e89a8c3451b364" +"graceful-readlink@>= 1.0.0": + version "1.0.1" + resolved "https://registry.yarnpkg.com/graceful-readlink/-/graceful-readlink-1.0.1.tgz#4cafad76bc62f02fa039b2f94e9a3dd3a391a725" growl@1.9.2: version "1.9.2" resolved "https://registry.yarnpkg.com/growl/-/growl-1.9.2.tgz#0ea7743715db8d8de2c5ede1775e1b45ac85c02f" -gulp-babel@^6.1.2: - version "6.1.2" - resolved "https://registry.yarnpkg.com/gulp-babel/-/gulp-babel-6.1.2.tgz#7c0176e4ba3f244c60588a0c4b320a45d1adefce" - dependencies: - babel-core "^6.0.2" - gulp-util "^3.0.0" - object-assign "^4.0.1" - replace-ext "0.0.1" - through2 "^2.0.0" - vinyl-sourcemaps-apply "^0.2.0" - -gulp-sourcemaps@^2.0.0-alpha: - version "2.4.1" - resolved "https://registry.yarnpkg.com/gulp-sourcemaps/-/gulp-sourcemaps-2.4.1.tgz#8f65dc5c0d07b2fd5c88bc60ec7f13e56716bf74" - dependencies: - acorn "4.X" - convert-source-map "1.X" - css "2.X" - debug-fabulous "0.0.X" - detect-newline "2.X" - graceful-fs "4.X" - source-map "0.X" - strip-bom "3.X" - through2 "2.X" - vinyl "1.X" - -gulp-util@^3.0.0: - version "3.0.8" - resolved "https://registry.yarnpkg.com/gulp-util/-/gulp-util-3.0.8.tgz#0054e1e744502e27c04c187c3ecc505dd54bbb4f" - dependencies: - array-differ "^1.0.0" - array-uniq "^1.0.2" - beeper "^1.0.0" - chalk "^1.0.0" - dateformat "^2.0.0" - fancy-log "^1.1.0" - gulplog "^1.0.0" - has-gulplog "^0.1.0" - lodash._reescape "^3.0.0" - lodash._reevaluate "^3.0.0" - lodash._reinterpolate "^3.0.0" - lodash.template "^3.0.0" - minimist "^1.1.0" - multipipe "^0.1.2" - object-assign "^3.0.0" - replace-ext "0.0.1" - through2 "^2.0.0" - vinyl "^0.5.0" - -gulp@^3.9.1: - version "3.9.1" - resolved "https://registry.yarnpkg.com/gulp/-/gulp-3.9.1.tgz#571ce45928dd40af6514fc4011866016c13845b4" - dependencies: - archy "^1.0.0" - chalk "^1.0.0" - deprecated "^0.0.1" - gulp-util "^3.0.0" - interpret "^1.0.0" - liftoff "^2.1.0" - minimist "^1.1.0" - orchestrator "^0.3.0" - pretty-hrtime "^1.0.0" - semver "^4.1.0" - tildify "^1.0.0" - v8flags "^2.0.2" - vinyl-fs "^0.3.0" - -gulplog@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/gulplog/-/gulplog-1.0.0.tgz#e28c4d45d05ecbbed818363ce8f9c5926229ffe5" - dependencies: - glogg "^1.0.0" - has-ansi@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/has-ansi/-/has-ansi-2.0.0.tgz#34f5049ce1ecdf2b0649af3ef24e45ed35416d91" dependencies: ansi-regex "^2.0.0" -has-gulplog@^0.1.0: - version "0.1.0" - resolved "https://registry.yarnpkg.com/has-gulplog/-/has-gulplog-0.1.0.tgz#6414c82913697da51590397dafb12f22967811ce" - dependencies: - sparkles "^1.0.0" +has-flag@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-1.0.0.tgz#9d9e793165ce017a00f00418c43f942a7b1d11fa" has@^1.0.1: version "1.0.1" @@ -1788,15 +1209,9 @@ home-or-tmp@^2.0.0: os-homedir "^1.0.0" os-tmpdir "^1.0.1" -homedir-polyfill@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/homedir-polyfill/-/homedir-polyfill-1.0.1.tgz#4c2bbc8a758998feebf5ed68580f76d46768b4bc" - dependencies: - parse-passwd "^1.0.0" - ignore@^3.2.0: - version "3.2.4" - resolved "https://registry.yarnpkg.com/ignore/-/ignore-3.2.4.tgz#4055e03596729a8fabe45a43c100ad5ed815c4e8" + version "3.2.6" + resolved "https://registry.yarnpkg.com/ignore/-/ignore-3.2.6.tgz#26e8da0644be0bb4cb39516f6c79f0e0f4ffe48c" imurmurhash@^0.1.4: version "0.1.4" @@ -1809,11 +1224,7 @@ inflight@^1.0.4: once "^1.3.0" wrappy "1" -inherits@1: - version "1.0.2" - resolved "https://registry.yarnpkg.com/inherits/-/inherits-1.0.2.tgz#ca4309dadee6b54cc0b8d247e8d7c7a0975bdc9b" - -inherits@2, inherits@^2.0.1, inherits@^2.0.3, inherits@~2.0.1: +inherits@2, inherits@^2.0.3, inherits@~2.0.1: version "2.0.3" resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.3.tgz#633c2c83e3da42a502f52466022480f4208261de" @@ -1821,10 +1232,6 @@ inherits@2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.1.tgz#b17d08d326b4423e568eff719f91b0b1cbdf69f1" -ini@^1.3.4: - version "1.3.4" - resolved "https://registry.yarnpkg.com/ini/-/ini-1.3.4.tgz#0537cb79daf59b59a1a517dff706c86ec039162e" - inquirer@^0.12.0: version "0.12.0" resolved "https://registry.yarnpkg.com/inquirer/-/inquirer-0.12.0.tgz#1ef2bfd63504df0bc75785fff8c2c41df12f077e" @@ -1844,44 +1251,15 @@ inquirer@^0.12.0: through "^2.3.6" interpret@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/interpret/-/interpret-1.0.1.tgz#d579fb7f693b858004947af39fa0db49f795602c" + version "1.0.2" + resolved "https://registry.yarnpkg.com/interpret/-/interpret-1.0.2.tgz#f4f623f0bb7122f15f5717c8e254b8161b5c5b2d" -invariant@^2.2.0: +invariant@^2.2.0, invariant@^2.2.2: version "2.2.2" resolved "https://registry.yarnpkg.com/invariant/-/invariant-2.2.2.tgz#9e1f56ac0acdb6bf303306f338be3b204ae60360" dependencies: loose-envify "^1.0.0" -is-absolute@^0.2.3: - version "0.2.6" - resolved "https://registry.yarnpkg.com/is-absolute/-/is-absolute-0.2.6.tgz#20de69f3db942ef2d87b9c2da36f172235b1b5eb" - dependencies: - is-relative "^0.2.1" - is-windows "^0.2.0" - -is-buffer@^1.0.2: - version "1.1.4" - resolved "https://registry.yarnpkg.com/is-buffer/-/is-buffer-1.1.4.tgz#cfc86ccd5dc5a52fa80489111c6920c457e2d98b" - -is-dotfile@^1.0.0: - version "1.0.2" - resolved "https://registry.yarnpkg.com/is-dotfile/-/is-dotfile-1.0.2.tgz#2c132383f39199f8edc268ca01b9b007d205cc4d" - -is-equal-shallow@^0.1.3: - version "0.1.3" - resolved "https://registry.yarnpkg.com/is-equal-shallow/-/is-equal-shallow-0.1.3.tgz#2238098fc221de0bcfa5d9eac4c45d638aa1c534" - dependencies: - is-primitive "^2.0.0" - -is-extendable@^0.1.1: - version "0.1.1" - resolved "https://registry.yarnpkg.com/is-extendable/-/is-extendable-0.1.1.tgz#62b110e289a471418e3ec36a617d472e301dfc89" - -is-extglob@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/is-extglob/-/is-extglob-1.0.0.tgz#ac468177c4943405a092fc8f29760c6ffc6206c0" - is-finite@^1.0.0: version "1.0.2" resolved "https://registry.yarnpkg.com/is-finite/-/is-finite-1.0.2.tgz#cc6677695602be550ef11e8b4aa6305342b6d0aa" @@ -1898,12 +1276,6 @@ is-fullwidth-code-point@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz#a3b30a5c4f199183167aaab93beefae3ddfb654f" -is-glob@^2.0.0, is-glob@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-2.0.1.tgz#d096f926a3ded5600f3fdfd91198cb0888c2d863" - dependencies: - is-extglob "^1.0.0" - is-my-json-valid@^2.10.0: version "2.16.0" resolved "https://registry.yarnpkg.com/is-my-json-valid/-/is-my-json-valid-2.16.0.tgz#f079dd9bfdae65ee2038aae8acbc86ab109e3693" @@ -1913,12 +1285,6 @@ is-my-json-valid@^2.10.0: jsonpointer "^4.0.0" xtend "^4.0.0" -is-number@^2.0.2, is-number@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/is-number/-/is-number-2.1.0.tgz#01fcbbb393463a548f2f466cce16dece49db908f" - dependencies: - kind-of "^3.0.2" - is-path-cwd@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/is-path-cwd/-/is-path-cwd-1.0.0.tgz#d225ec23132e89edd38fda767472e62e65f1106d" @@ -1935,76 +1301,27 @@ is-path-inside@^1.0.0: dependencies: path-is-inside "^1.0.1" -is-posix-bracket@^0.1.0: - version "0.1.1" - resolved "https://registry.yarnpkg.com/is-posix-bracket/-/is-posix-bracket-0.1.1.tgz#3334dc79774368e92f016e6fbc0a88f5cd6e6bc4" - -is-primitive@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/is-primitive/-/is-primitive-2.0.0.tgz#207bab91638499c07b2adf240a41a87210034575" - is-property@^1.0.0: version "1.0.2" resolved "https://registry.yarnpkg.com/is-property/-/is-property-1.0.2.tgz#57fe1c4e48474edd65b09911f26b1cd4095dda84" -is-relative@^0.2.1: - version "0.2.1" - resolved "https://registry.yarnpkg.com/is-relative/-/is-relative-0.2.1.tgz#d27f4c7d516d175fb610db84bbeef23c3bc97aa5" - dependencies: - is-unc-path "^0.1.1" - is-resolvable@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/is-resolvable/-/is-resolvable-1.0.0.tgz#8df57c61ea2e3c501408d100fb013cf8d6e0cc62" dependencies: tryit "^1.0.1" -is-unc-path@^0.1.1: - version "0.1.2" - resolved "https://registry.yarnpkg.com/is-unc-path/-/is-unc-path-0.1.2.tgz#6ab053a72573c10250ff416a3814c35178af39b9" - dependencies: - unc-path-regex "^0.1.0" - -is-utf8@^0.2.0: - version "0.2.1" - resolved "https://registry.yarnpkg.com/is-utf8/-/is-utf8-0.2.1.tgz#4b0da1442104d1b336340e80797e865cf39f7d72" - -is-windows@^0.2.0: - version "0.2.0" - resolved "https://registry.yarnpkg.com/is-windows/-/is-windows-0.2.0.tgz#de1aa6d63ea29dd248737b69f1ff8b8002d2108c" - -isarray@0.0.1: - version "0.0.1" - resolved "https://registry.yarnpkg.com/isarray/-/isarray-0.0.1.tgz#8a18acfca9a8f4177e09abfc6038939b05d1eedf" - -isarray@1.0.0, isarray@^1.0.0, isarray@~1.0.0: +isarray@^1.0.0, isarray@~1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/isarray/-/isarray-1.0.0.tgz#bb935d48582cba168c06834957a54a3e07124f11" -isexe@^1.1.1: - version "1.1.2" - resolved "https://registry.yarnpkg.com/isexe/-/isexe-1.1.2.tgz#36f3e22e60750920f5e7241a476a8c6a42275ad0" - -isobject@^2.0.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/isobject/-/isobject-2.1.0.tgz#f065561096a3f1da2ef46272f815c840d87e0c89" - dependencies: - isarray "1.0.0" - -jade@0.26.3: - version "0.26.3" - resolved "https://registry.yarnpkg.com/jade/-/jade-0.26.3.tgz#8f10d7977d8d79f2f6ff862a81b0513ccb25686c" - dependencies: - commander "0.6.1" - mkdirp "0.3.0" - js-tokens@^3.0.0: version "3.0.1" resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-3.0.1.tgz#08e9f132484a2c45a30907e9dc4d5567b7f114d7" js-yaml@^3.5.1: - version "3.8.1" - resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.8.1.tgz#782ba50200be7b9e5a8537001b7804db3ad02628" + version "3.8.2" + resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.8.2.tgz#02d3e2c0f6beab20248d412c352203827d786721" dependencies: argparse "^1.0.7" esprima "^3.1.1" @@ -2027,6 +1344,10 @@ json-stable-stringify@^1.0.0, json-stable-stringify@^1.0.1: dependencies: jsonify "~0.0.0" +json3@3.3.2: + version "3.3.2" + resolved "https://registry.yarnpkg.com/json3/-/json3-3.3.2.tgz#3c0434743df93e2f5c42aee7b19bcb483575f4e1" + json5@^0.5.0: version "0.5.1" resolved "https://registry.yarnpkg.com/json5/-/json5-0.5.1.tgz#1eade7acc012034ad84e2396767ead9fa5495821" @@ -2039,16 +1360,6 @@ jsonpointer@^4.0.0: version "4.0.1" resolved "https://registry.yarnpkg.com/jsonpointer/-/jsonpointer-4.0.1.tgz#4fd92cb34e0e9db3c89c8622ecf51f9b978c6cb9" -kind-of@^3.0.2: - version "3.1.0" - resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-3.1.0.tgz#475d698a5e49ff5e53d14e3e732429dc8bf4cf47" - dependencies: - is-buffer "^1.0.2" - -lazy-debug-legacy@0.0.X: - version "0.0.1" - resolved "https://registry.yarnpkg.com/lazy-debug-legacy/-/lazy-debug-legacy-0.0.1.tgz#537716c0776e4cf79e3ed1b621f7658c2911b1b1" - levn@^0.3.0, levn@~0.3.0: version "0.3.0" resolved "https://registry.yarnpkg.com/levn/-/levn-0.3.0.tgz#3b09924edf9f083c0490fdd4c0bc4421e04764ee" @@ -2056,31 +1367,20 @@ levn@^0.3.0, levn@~0.3.0: prelude-ls "~1.1.2" type-check "~0.3.2" -liftoff@^2.1.0: - version "2.3.0" - resolved "https://registry.yarnpkg.com/liftoff/-/liftoff-2.3.0.tgz#a98f2ff67183d8ba7cfaca10548bd7ff0550b385" - dependencies: - extend "^3.0.0" - findup-sync "^0.4.2" - fined "^1.0.1" - flagged-respawn "^0.3.2" - lodash.isplainobject "^4.0.4" - lodash.isstring "^4.0.1" - lodash.mapvalues "^4.4.0" - rechoir "^0.6.2" - resolve "^1.1.7" +lodash._baseassign@^3.0.0: + version "3.2.0" + resolved "https://registry.yarnpkg.com/lodash._baseassign/-/lodash._baseassign-3.2.0.tgz#8c38a099500f215ad09e59f1722fd0c52bfe0a4e" + dependencies: + lodash._basecopy "^3.0.0" + lodash.keys "^3.0.0" lodash._basecopy@^3.0.0: version "3.0.1" resolved "https://registry.yarnpkg.com/lodash._basecopy/-/lodash._basecopy-3.0.1.tgz#8da0e6a876cf344c0ad8a54882111dd3c5c7ca36" -lodash._basetostring@^3.0.0: - version "3.0.1" - resolved "https://registry.yarnpkg.com/lodash._basetostring/-/lodash._basetostring-3.0.1.tgz#d1861d877f824a52f669832dcaf3ee15566a07d5" - -lodash._basevalues@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/lodash._basevalues/-/lodash._basevalues-3.0.0.tgz#5b775762802bde3d3297503e26300820fdf661b7" +lodash._basecreate@^3.0.0: + version "3.0.3" + resolved "https://registry.yarnpkg.com/lodash._basecreate/-/lodash._basecreate-3.0.3.tgz#1bc661614daa7fc311b7d03bf16806a0213cf821" lodash._getnative@^3.0.0: version "3.9.1" @@ -2090,35 +1390,17 @@ lodash._isiterateecall@^3.0.0: version "3.0.9" resolved "https://registry.yarnpkg.com/lodash._isiterateecall/-/lodash._isiterateecall-3.0.9.tgz#5203ad7ba425fae842460e696db9cf3e6aac057c" -lodash._reescape@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/lodash._reescape/-/lodash._reescape-3.0.0.tgz#2b1d6f5dfe07c8a355753e5f27fac7f1cde1616a" - -lodash._reevaluate@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/lodash._reevaluate/-/lodash._reevaluate-3.0.0.tgz#58bc74c40664953ae0b124d806996daca431e2ed" - -lodash._reinterpolate@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/lodash._reinterpolate/-/lodash._reinterpolate-3.0.0.tgz#0ccf2d89166af03b3663c796538b75ac6e114d9d" - -lodash._root@^3.0.0: - version "3.0.1" - resolved "https://registry.yarnpkg.com/lodash._root/-/lodash._root-3.0.1.tgz#fba1c4524c19ee9a5f8136b4609f017cf4ded692" - -lodash.assignwith@^4.0.7: - version "4.2.0" - resolved "https://registry.yarnpkg.com/lodash.assignwith/-/lodash.assignwith-4.2.0.tgz#127a97f02adc41751a954d24b0de17e100e038eb" - lodash.cond@^4.3.0: version "4.5.2" resolved "https://registry.yarnpkg.com/lodash.cond/-/lodash.cond-4.5.2.tgz#f471a1da486be60f6ab955d17115523dd1d255d5" -lodash.escape@^3.0.0: - version "3.2.0" - resolved "https://registry.yarnpkg.com/lodash.escape/-/lodash.escape-3.2.0.tgz#995ee0dc18c1b48cc92effae71a10aab5b487698" +lodash.create@3.1.1: + version "3.1.1" + resolved "https://registry.yarnpkg.com/lodash.create/-/lodash.create-3.1.1.tgz#d7f2849f0dbda7e04682bb8cd72ab022461debe7" dependencies: - lodash._root "^3.0.0" + lodash._baseassign "^3.0.0" + lodash._basecreate "^3.0.0" + lodash._isiterateecall "^3.0.0" lodash.isarguments@^3.0.0: version "3.1.0" @@ -2128,18 +1410,10 @@ lodash.isarray@^3.0.0: version "3.0.4" resolved "https://registry.yarnpkg.com/lodash.isarray/-/lodash.isarray-3.0.4.tgz#79e4eb88c36a8122af86f844aa9bcd851b5fbb55" -lodash.isempty@^4.2.1: - version "4.4.0" - resolved "https://registry.yarnpkg.com/lodash.isempty/-/lodash.isempty-4.4.0.tgz#6f86cbedd8be4ec987be9aaf33c9684db1b31e7e" - -lodash.isplainobject@^4.0.4, lodash.isplainobject@^4.0.6: +lodash.isplainobject@^4.0.6: version "4.0.6" resolved "https://registry.yarnpkg.com/lodash.isplainobject/-/lodash.isplainobject-4.0.6.tgz#7c526a52d89b45c45cc690b88163be0497f550cb" -lodash.isstring@^4.0.1: - version "4.0.1" - resolved "https://registry.yarnpkg.com/lodash.isstring/-/lodash.isstring-4.0.1.tgz#d527dfb5456eca7cc9bb95d5daeaf88ba54a5451" - lodash.keys@^3.0.0: version "3.1.2" resolved "https://registry.yarnpkg.com/lodash.keys/-/lodash.keys-3.1.2.tgz#4dbc0472b156be50a0b286855d1bd0b0c656098a" @@ -2148,51 +1422,14 @@ lodash.keys@^3.0.0: lodash.isarguments "^3.0.0" lodash.isarray "^3.0.0" -lodash.mapvalues@^4.4.0: - version "4.6.0" - resolved "https://registry.yarnpkg.com/lodash.mapvalues/-/lodash.mapvalues-4.6.0.tgz#1bafa5005de9dd6f4f26668c30ca37230cc9689c" - -lodash.pick@^4.2.1: - version "4.4.0" - resolved "https://registry.yarnpkg.com/lodash.pick/-/lodash.pick-4.4.0.tgz#52f05610fff9ded422611441ed1fc123a03001b3" - -lodash.restparam@^3.0.0: - version "3.6.1" - resolved "https://registry.yarnpkg.com/lodash.restparam/-/lodash.restparam-3.6.1.tgz#936a4e309ef330a7645ed4145986c85ae5b20805" - lodash.some@^4.6.0: version "4.6.0" resolved "https://registry.yarnpkg.com/lodash.some/-/lodash.some-4.6.0.tgz#1bb9f314ef6b8baded13b549169b2a945eb68e4d" -lodash.template@^3.0.0: - version "3.6.2" - resolved "https://registry.yarnpkg.com/lodash.template/-/lodash.template-3.6.2.tgz#f8cdecc6169a255be9098ae8b0c53d378931d14f" - dependencies: - lodash._basecopy "^3.0.0" - lodash._basetostring "^3.0.0" - lodash._basevalues "^3.0.0" - lodash._isiterateecall "^3.0.0" - lodash._reinterpolate "^3.0.0" - lodash.escape "^3.0.0" - lodash.keys "^3.0.0" - lodash.restparam "^3.0.0" - lodash.templatesettings "^3.0.0" - -lodash.templatesettings@^3.0.0: - version "3.1.1" - resolved "https://registry.yarnpkg.com/lodash.templatesettings/-/lodash.templatesettings-3.1.1.tgz#fb307844753b66b9f1afa54e262c745307dba8e5" - dependencies: - lodash._reinterpolate "^3.0.0" - lodash.escape "^3.0.0" - lodash@^4.0.0, lodash@^4.2.0, lodash@^4.3.0: version "4.17.4" resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.4.tgz#78203a4d1c328ae1d86dca6460e369b57f4055ae" -lodash@~1.0.1: - version "1.0.2" - resolved "https://registry.yarnpkg.com/lodash/-/lodash-1.0.2.tgz#8f57560c83b59fc270bd3d561b690043430e2551" - lolex@1.3.2: version "1.3.2" resolved "https://registry.yarnpkg.com/lolex/-/lolex-1.3.2.tgz#7c3da62ffcb30f0f5a80a2566ca24e45d8a01f31" @@ -2203,96 +1440,37 @@ loose-envify@^1.0.0: dependencies: js-tokens "^3.0.0" -lru-cache@2: - version "2.7.3" - resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-2.7.3.tgz#6d4524e8b955f95d4f5b58851ce21dd72fb4e952" - -map-cache@^0.2.0: - version "0.2.2" - resolved "https://registry.yarnpkg.com/map-cache/-/map-cache-0.2.2.tgz#c32abd0bd6525d9b051645bb4f26ac5dc98a0dbf" - -micromatch@^2.3.7: - version "2.3.11" - resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-2.3.11.tgz#86677c97d1720b363431d04d0d15293bd38c1565" - dependencies: - arr-diff "^2.0.0" - array-unique "^0.2.1" - braces "^1.8.2" - expand-brackets "^0.1.4" - extglob "^0.3.1" - filename-regex "^2.0.0" - is-extglob "^1.0.0" - is-glob "^2.0.1" - kind-of "^3.0.2" - normalize-path "^2.0.1" - object.omit "^2.0.0" - parse-glob "^3.0.4" - regex-cache "^0.4.2" - -minimatch@0.3: - version "0.3.0" - resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-0.3.0.tgz#275d8edaac4f1bb3326472089e7949c8394699dd" - dependencies: - lru-cache "2" - sigmund "~1.0.0" - -minimatch@^2.0.1: - version "2.0.10" - resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-2.0.10.tgz#8d087c39c6b38c001b97fca7ce6d0e1e80afbac7" - dependencies: - brace-expansion "^1.0.0" - minimatch@^3.0.2, minimatch@^3.0.3: version "3.0.3" resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.0.3.tgz#2a4e4090b96b2db06a9d7df01055a62a77c9b774" dependencies: brace-expansion "^1.0.0" -minimatch@~0.2.11: - version "0.2.14" - resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-0.2.14.tgz#c74e780574f63c6f9a090e90efbe6ef53a6a756a" - dependencies: - lru-cache "2" - sigmund "~1.0.0" - minimist@0.0.8: version "0.0.8" resolved "https://registry.yarnpkg.com/minimist/-/minimist-0.0.8.tgz#857fcabfc3397d2625b8228262e86aa7a011b05d" -minimist@^1.1.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.0.tgz#a35008b20f41383eec1fb914f4cd5df79a264284" - -mkdirp@0.3.0: - version "0.3.0" - resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.3.0.tgz#1bbf5ab1ba827af23575143490426455f481fe1e" - mkdirp@0.5.1, mkdirp@^0.5.0, mkdirp@^0.5.1: version "0.5.1" resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.5.1.tgz#30057438eac6cf7f8c4767f38648d6697d75c903" dependencies: minimist "0.0.8" -mocha@^2.4.5: - version "2.5.3" - resolved "https://registry.yarnpkg.com/mocha/-/mocha-2.5.3.tgz#161be5bdeb496771eb9b35745050b622b5aefc58" +mocha@^3.2.0: + version "3.2.0" + resolved "https://registry.yarnpkg.com/mocha/-/mocha-3.2.0.tgz#7dc4f45e5088075171a68896814e6ae9eb7a85e3" dependencies: - commander "2.3.0" + browser-stdout "1.3.0" + commander "2.9.0" debug "2.2.0" diff "1.4.0" - escape-string-regexp "1.0.2" - glob "3.2.11" + escape-string-regexp "1.0.5" + glob "7.0.5" growl "1.9.2" - jade "0.26.3" + json3 "3.3.2" + lodash.create "3.1.1" mkdirp "0.5.1" - supports-color "1.2.0" - to-iso-string "0.0.2" - -modify-babel-preset@^2.1.1: - version "2.1.1" - resolved "https://registry.yarnpkg.com/modify-babel-preset/-/modify-babel-preset-2.1.1.tgz#2d3190162ee62fb67aaa3325c242f026322ebbac" - dependencies: - require-relative "^0.8.7" + supports-color "3.1.2" ms@0.7.1: version "0.7.1" @@ -2302,63 +1480,28 @@ ms@0.7.2: version "0.7.2" resolved "https://registry.yarnpkg.com/ms/-/ms-0.7.2.tgz#ae25cf2512b3885a1d95d7f037868d8431124765" -multipipe@^0.1.2: - version "0.1.2" - resolved "https://registry.yarnpkg.com/multipipe/-/multipipe-0.1.2.tgz#2a8f2ddf70eed564dff2d57f1e1a137d9f05078b" - dependencies: - duplexer2 "0.0.2" - mute-stream@0.0.5: version "0.0.5" resolved "https://registry.yarnpkg.com/mute-stream/-/mute-stream-0.0.5.tgz#8fbfabb0a98a253d3184331f9e8deb7372fac6c0" -natives@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/natives/-/natives-1.1.0.tgz#e9ff841418a6b2ec7a495e939984f78f163e6e31" - natural-compare@^1.4.0: version "1.4.0" resolved "https://registry.yarnpkg.com/natural-compare/-/natural-compare-1.4.0.tgz#4abebfeed7541f2c27acfb29bdbbd15c8d5ba4f7" -normalize-path@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/normalize-path/-/normalize-path-2.0.1.tgz#47886ac1662760d4261b7d979d241709d3ce3f7a" - number-is-nan@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/number-is-nan/-/number-is-nan-1.0.1.tgz#097b602b53422a522c1afb8790318336941a011d" -object-assign@4.1.0: - version "4.1.0" - resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-4.1.0.tgz#7a3b3d0e98063d43f4c03f2e8ae6cd51a86883a0" - -object-assign@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-3.0.0.tgz#9bedd5ca0897949bca47e7ff408062d549f587f2" - object-assign@^4.0.1, object-assign@^4.1.0: version "4.1.1" resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-4.1.1.tgz#2109adc7965887cfc05cbbd442cac8bfbb360863" -object.omit@^2.0.0: - version "2.0.1" - resolved "https://registry.yarnpkg.com/object.omit/-/object.omit-2.0.1.tgz#1a9c744829f39dbb858c76ca3579ae2a54ebd1fa" - dependencies: - for-own "^0.1.4" - is-extendable "^0.1.1" - once@^1.3.0: version "1.4.0" resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1" dependencies: wrappy "1" -once@~1.3.0: - version "1.3.3" - resolved "https://registry.yarnpkg.com/once/-/once-1.3.3.tgz#b2e261557ce4c314ec8304f3fa82663e4297ca20" - dependencies: - wrappy "1" - onetime@^1.0.0: version "1.1.0" resolved "https://registry.yarnpkg.com/onetime/-/onetime-1.1.0.tgz#a1f7838f8314c516f05ecefcbc4ccfe04b4ed789" @@ -2374,19 +1517,7 @@ optionator@^0.8.2: type-check "~0.3.2" wordwrap "~1.0.0" -orchestrator@^0.3.0: - version "0.3.8" - resolved "https://registry.yarnpkg.com/orchestrator/-/orchestrator-0.3.8.tgz#14e7e9e2764f7315fbac184e506c7aa6df94ad7e" - dependencies: - end-of-stream "~0.1.5" - sequencify "~0.0.7" - stream-consume "~0.1.0" - -ordered-read-streams@^0.1.0: - version "0.1.0" - resolved "https://registry.yarnpkg.com/ordered-read-streams/-/ordered-read-streams-0.1.0.tgz#fd565a9af8eb4473ba69b6ed8a34352cb552f126" - -os-homedir@^1.0.0, os-homedir@^1.0.1: +os-homedir@^1.0.0: version "1.0.2" resolved "https://registry.yarnpkg.com/os-homedir/-/os-homedir-1.0.2.tgz#ffbc4988336e0e833de0c168c7ef152121aa7fb3" @@ -2394,27 +1525,6 @@ os-tmpdir@^1.0.1: version "1.0.2" resolved "https://registry.yarnpkg.com/os-tmpdir/-/os-tmpdir-1.0.2.tgz#bbe67406c79aa85c5cfec766fe5734555dfa1274" -parse-filepath@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/parse-filepath/-/parse-filepath-1.0.1.tgz#159d6155d43904d16c10ef698911da1e91969b73" - dependencies: - is-absolute "^0.2.3" - map-cache "^0.2.0" - path-root "^0.1.1" - -parse-glob@^3.0.4: - version "3.0.4" - resolved "https://registry.yarnpkg.com/parse-glob/-/parse-glob-3.0.4.tgz#b2c376cfb11f35513badd173ef0bb6e3a388391c" - dependencies: - glob-base "^0.3.0" - is-dotfile "^1.0.0" - is-extglob "^1.0.0" - is-glob "^2.0.0" - -parse-passwd@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/parse-passwd/-/parse-passwd-1.0.0.tgz#6d5b934a456993b23d37f40a382d6f1666a8e5c6" - path-exists@^2.0.0: version "2.1.0" resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-2.1.0.tgz#0feb6c64f0fc518d9a754dd5efb62c7022761f4b" @@ -2433,16 +1543,6 @@ path-parse@^1.0.5: version "1.0.5" resolved "https://registry.yarnpkg.com/path-parse/-/path-parse-1.0.5.tgz#3c1adf871ea9cd6c9431b6ea2bd74a0ff055c4c1" -path-root-regex@^0.1.0: - version "0.1.2" - resolved "https://registry.yarnpkg.com/path-root-regex/-/path-root-regex-0.1.2.tgz#bfccdc8df5b12dc52c8b43ec38d18d72c04ba96d" - -path-root@^0.1.1: - version "0.1.1" - resolved "https://registry.yarnpkg.com/path-root/-/path-root-0.1.1.tgz#9a4a6814cac1c0cd73360a95f32083c8ea4745b7" - dependencies: - path-root-regex "^0.1.0" - pify@^2.0.0: version "2.3.0" resolved "https://registry.yarnpkg.com/pify/-/pify-2.3.0.tgz#ed141a6ac043a849ea588498e7dca8b15330e90c" @@ -2477,14 +1577,6 @@ prelude-ls@~1.1.2: version "1.1.2" resolved "https://registry.yarnpkg.com/prelude-ls/-/prelude-ls-1.1.2.tgz#21932a549f5e52ffd9a827f570e04be62a97da54" -preserve@^0.2.0: - version "0.2.0" - resolved "https://registry.yarnpkg.com/preserve/-/preserve-0.2.0.tgz#815ed1f6ebc65926f865b310c0713bcb3315ce4b" - -pretty-hrtime@^1.0.0: - version "1.0.3" - resolved "https://registry.yarnpkg.com/pretty-hrtime/-/pretty-hrtime-1.0.3.tgz#b7e3ea42435a4c9b2759d99e0f201eb195802ee1" - private@^0.1.6: version "0.1.7" resolved "https://registry.yarnpkg.com/private/-/private-0.1.7.tgz#68ce5e8a1ef0a23bb570cc28537b5332aba63ef1" @@ -2497,25 +1589,9 @@ progress@^1.1.8: version "1.1.8" resolved "https://registry.yarnpkg.com/progress/-/progress-1.1.8.tgz#e260c78f6161cdd9b0e56cc3e0a85de17c7a57be" -randomatic@^1.1.3: - version "1.1.6" - resolved "https://registry.yarnpkg.com/randomatic/-/randomatic-1.1.6.tgz#110dcabff397e9dcff7c0789ccc0a49adf1ec5bb" - dependencies: - is-number "^2.0.2" - kind-of "^3.0.2" - -"readable-stream@>=1.0.33-1 <1.1.0-0": - version "1.0.34" - resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-1.0.34.tgz#125820e34bc842d2f2aaafafe4c2916ee32c157c" - dependencies: - core-util-is "~1.0.0" - inherits "~2.0.1" - isarray "0.0.1" - string_decoder "~0.10.x" - -readable-stream@^2.1.5, readable-stream@^2.2.2: - version "2.2.3" - resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.2.3.tgz#9cf49463985df016c8ae8813097a9293a9b33729" +readable-stream@^2.2.2: + version "2.2.6" + resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.2.6.tgz#8b43aed76e71483938d12a8d46c6cf1a00b1f816" dependencies: buffer-shims "^1.0.0" core-util-is "~1.0.0" @@ -2525,15 +1601,6 @@ readable-stream@^2.1.5, readable-stream@^2.2.2: string_decoder "~0.10.x" util-deprecate "~1.0.1" -readable-stream@~1.1.9: - version "1.1.14" - resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-1.1.14.tgz#7cf4c54ef648e3813084c636dd2079e166c081d9" - dependencies: - core-util-is "~1.0.0" - inherits "~2.0.1" - isarray "0.0.1" - string_decoder "~0.10.x" - readline2@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/readline2/-/readline2-1.0.1.tgz#41059608ffc154757b715d9989d199ffbf372e35" @@ -2564,13 +1631,6 @@ regenerator-transform@0.9.8: babel-types "^6.19.0" private "^0.1.6" -regex-cache@^0.4.2: - version "0.4.3" - resolved "https://registry.yarnpkg.com/regex-cache/-/regex-cache-0.4.3.tgz#9b1a6c35d4d0dfcef5711ae651e8e9d3d7114145" - dependencies: - is-equal-shallow "^0.1.3" - is-primitive "^2.0.0" - regexpu-core@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/regexpu-core/-/regexpu-core-2.0.0.tgz#49d038837b8dcf8bfa5b9a42139938e6ea2ae240" @@ -2589,28 +1649,12 @@ regjsparser@^0.1.4: dependencies: jsesc "~0.5.0" -repeat-element@^1.1.2: - version "1.1.2" - resolved "https://registry.yarnpkg.com/repeat-element/-/repeat-element-1.1.2.tgz#ef089a178d1483baae4d93eb98b4f9e4e11d990a" - -repeat-string@^1.5.2: - version "1.6.1" - resolved "https://registry.yarnpkg.com/repeat-string/-/repeat-string-1.6.1.tgz#8dcae470e1c88abc2d600fff4a776286da75e637" - repeating@^2.0.0: version "2.0.1" resolved "https://registry.yarnpkg.com/repeating/-/repeating-2.0.1.tgz#5214c53a926d3552707527fbab415dbc08d06dda" dependencies: is-finite "^1.0.0" -replace-ext@0.0.1: - version "0.0.1" - resolved "https://registry.yarnpkg.com/replace-ext/-/replace-ext-0.0.1.tgz#29bbd92078a739f0bcce2b4ee41e837953522924" - -require-relative@^0.8.7: - version "0.8.7" - resolved "https://registry.yarnpkg.com/require-relative/-/require-relative-0.8.7.tgz#7999539fc9e047a37928fa196f8e1563dabd36de" - require-uncached@^1.0.2: version "1.0.3" resolved "https://registry.yarnpkg.com/require-uncached/-/require-uncached-1.0.3.tgz#4e0d56d6c9662fd31e43011c4b95aa49955421d3" @@ -2618,28 +1662,17 @@ require-uncached@^1.0.2: caller-path "^0.1.0" resolve-from "^1.0.0" -resolve-dir@^0.1.0: - version "0.1.1" - resolved "https://registry.yarnpkg.com/resolve-dir/-/resolve-dir-0.1.1.tgz#b219259a5602fac5c5c496ad894a6e8cc430261e" - dependencies: - expand-tilde "^1.2.2" - global-modules "^0.2.3" - resolve-from@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-1.0.1.tgz#26cbfe935d1aeeeabb29bc3fe5aeb01e93d44226" -resolve-url@~0.2.1: - version "0.2.1" - resolved "https://registry.yarnpkg.com/resolve-url/-/resolve-url-0.2.1.tgz#2c637fe77c893afd2a663fe21aa9080068e2052a" - resolve@1.1.7: version "1.1.7" resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.1.7.tgz#203114d82ad2c5ed9e8e0411b3932875e889e97b" -resolve@^1.1.6, resolve@^1.1.7: - version "1.3.1" - resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.3.1.tgz#5d0a1632609b6b00a22284293db1d5d973676314" +resolve@^1.1.6: + version "1.3.2" + resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.3.2.tgz#1f0442c9e0cbb8136e87b9305f932f46c7f28235" dependencies: path-parse "^1.0.5" @@ -2674,8 +1707,8 @@ rollup-plugin-babili@^2.0.0: babel-preset-babili "^0.0.12" rollup-plugin-node-resolve@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/rollup-plugin-node-resolve/-/rollup-plugin-node-resolve-2.0.0.tgz#07e0ae94ac002a3ea36e8f33ca121d9f836b1309" + version "2.1.1" + resolved "https://registry.yarnpkg.com/rollup-plugin-node-resolve/-/rollup-plugin-node-resolve-2.1.1.tgz#cbb783b0d15b02794d58915350b2f0d902b8ddc8" dependencies: browser-resolve "^1.11.0" builtin-modules "^1.1.0" @@ -2688,9 +1721,9 @@ rollup-pluginutils@^1.5.0: estree-walker "^0.2.1" minimatch "^3.0.2" -rollup@^0.41.4: - version "0.41.4" - resolved "https://registry.yarnpkg.com/rollup/-/rollup-0.41.4.tgz#a970580176329f9ead86854d7fd4c46de752aef8" +rollup@^0.41.6: + version "0.41.6" + resolved "https://registry.yarnpkg.com/rollup/-/rollup-0.41.6.tgz#e0d05497877a398c104d816d2733a718a7a94e2a" dependencies: source-map-support "^0.4.0" @@ -2708,29 +1741,17 @@ samsam@1.1.2, samsam@~1.1: version "1.1.2" resolved "https://registry.yarnpkg.com/samsam/-/samsam-1.1.2.tgz#bec11fdc83a9fda063401210e40176c3024d1567" -semver@^4.1.0: - version "4.3.6" - resolved "https://registry.yarnpkg.com/semver/-/semver-4.3.6.tgz#300bc6e0e86374f7ba61068b5b1ecd57fc6532da" - -sequencify@~0.0.7: - version "0.0.7" - resolved "https://registry.yarnpkg.com/sequencify/-/sequencify-0.0.7.tgz#90cff19d02e07027fd767f5ead3e7b95d1e7380c" - shelljs@^0.7.5: - version "0.7.6" - resolved "https://registry.yarnpkg.com/shelljs/-/shelljs-0.7.6.tgz#379cccfb56b91c8601e4793356eb5382924de9ad" + version "0.7.7" + resolved "https://registry.yarnpkg.com/shelljs/-/shelljs-0.7.7.tgz#b2f5c77ef97148f4b4f6e22682e10bba8667cff1" dependencies: glob "^7.0.0" interpret "^1.0.0" rechoir "^0.6.2" -sigmund@~1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/sigmund/-/sigmund-1.0.1.tgz#3ff21f198cad2175f9f3b781853fd94d0d19b590" - sinon-chai@^2.8.0: - version "2.8.0" - resolved "https://registry.yarnpkg.com/sinon-chai/-/sinon-chai-2.8.0.tgz#432a9bbfd51a6fc00798f4d2526a829c060687ac" + version "2.9.0" + resolved "https://registry.yarnpkg.com/sinon-chai/-/sinon-chai-2.9.0.tgz#34d820042bc9661a14527130d401eb462c49bb84" sinon@^1.17.7: version "1.17.7" @@ -2749,47 +1770,20 @@ slice-ansi@0.0.4: version "0.0.4" resolved "https://registry.yarnpkg.com/slice-ansi/-/slice-ansi-0.0.4.tgz#edbf8903f66f7ce2f8eafd6ceed65e264c831b35" -source-map-resolve@^0.3.0: - version "0.3.1" - resolved "https://registry.yarnpkg.com/source-map-resolve/-/source-map-resolve-0.3.1.tgz#610f6122a445b8dd51535a2a71b783dfc1248761" - dependencies: - atob "~1.1.0" - resolve-url "~0.2.1" - source-map-url "~0.3.0" - urix "~0.1.0" - source-map-support@^0.4.0, source-map-support@^0.4.2: - version "0.4.11" - resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.4.11.tgz#647f939978b38535909530885303daf23279f322" + version "0.4.14" + resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.4.14.tgz#9d4463772598b86271b4f523f6c1f4e02a7d6aef" dependencies: - source-map "^0.5.3" - -source-map-url@~0.3.0: - version "0.3.0" - resolved "https://registry.yarnpkg.com/source-map-url/-/source-map-url-0.3.0.tgz#7ecaf13b57bcd09da8a40c5d269db33799d4aaf9" + source-map "^0.5.6" -source-map@0.X, source-map@^0.5.0, source-map@^0.5.1, source-map@^0.5.3: +source-map@^0.5.0, source-map@^0.5.6: version "0.5.6" resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.5.6.tgz#75ce38f52bf0733c5a7f0c118d81334a2bb5f412" -source-map@^0.1.38: - version "0.1.43" - resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.1.43.tgz#c24bc146ca517c1471f5dacbe2571b2b7f9e3346" - dependencies: - amdefine ">=0.0.4" - -sparkles@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/sparkles/-/sparkles-1.0.0.tgz#1acbbfb592436d10bbe8f785b7cc6f82815012c3" - sprintf-js@~1.0.2: version "1.0.3" resolved "https://registry.yarnpkg.com/sprintf-js/-/sprintf-js-1.0.3.tgz#04e6926f662895354f3dd015203633b857297e2c" -stream-consume@~0.1.0: - version "0.1.0" - resolved "https://registry.yarnpkg.com/stream-consume/-/stream-consume-0.1.0.tgz#a41ead1a6d6081ceb79f65b061901b6d8f3d1d0f" - string-width@^1.0.1: version "1.0.2" resolved "https://registry.yarnpkg.com/string-width/-/string-width-1.0.2.tgz#118bdf5b8cdc51a2a7e70d211e07e2b0b9b107d3" @@ -2815,24 +1809,19 @@ strip-ansi@^3.0.0: dependencies: ansi-regex "^2.0.0" -strip-bom@3.X, strip-bom@^3.0.0: +strip-bom@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/strip-bom/-/strip-bom-3.0.0.tgz#2334c18e9c759f7bdd56fdef7e9ae3d588e68ed3" -strip-bom@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/strip-bom/-/strip-bom-1.0.0.tgz#85b8862f3844b5a6d5ec8467a93598173a36f794" - dependencies: - first-chunk-stream "^1.0.0" - is-utf8 "^0.2.0" - strip-json-comments@~2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-2.0.1.tgz#3c531942e908c2697c0ec344858c286c7ca0a60a" -supports-color@1.2.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-1.2.0.tgz#ff1ed1e61169d06b3cf2d588e188b18d8847e17e" +supports-color@3.1.2: + version "3.1.2" + resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-3.1.2.tgz#72a262894d9d408b956ca05ff37b2ed8a6e2a2d5" + dependencies: + has-flag "^1.0.0" supports-color@^2.0.0: version "2.0.0" @@ -2859,42 +1848,14 @@ text-table@~0.2.0: version "0.2.0" resolved "https://registry.yarnpkg.com/text-table/-/text-table-0.2.0.tgz#7f5ee823ae805207c00af2df4a84ec3fcfa570b4" -through2@2.X, through2@^2.0.0: - version "2.0.3" - resolved "https://registry.yarnpkg.com/through2/-/through2-2.0.3.tgz#0004569b37c7c74ba39c43f3ced78d1ad94140be" - dependencies: - readable-stream "^2.1.5" - xtend "~4.0.1" - -through2@^0.6.1: - version "0.6.5" - resolved "https://registry.yarnpkg.com/through2/-/through2-0.6.5.tgz#41ab9c67b29d57209071410e1d7a7a968cd3ad48" - dependencies: - readable-stream ">=1.0.33-1 <1.1.0-0" - xtend ">=4.0.0 <4.1.0-0" - through@^2.3.6: version "2.3.8" resolved "https://registry.yarnpkg.com/through/-/through-2.3.8.tgz#0dd4c9ffaabc357960b1b724115d7e0e86a2e1f5" -tildify@^1.0.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/tildify/-/tildify-1.2.0.tgz#dcec03f55dca9b7aa3e5b04f21817eb56e63588a" - dependencies: - os-homedir "^1.0.0" - -time-stamp@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/time-stamp/-/time-stamp-1.0.1.tgz#9f4bd23559c9365966f3302dbba2b07c6b99b151" - to-fast-properties@^1.0.1: version "1.0.2" resolved "https://registry.yarnpkg.com/to-fast-properties/-/to-fast-properties-1.0.2.tgz#f3f5c0c3ba7299a7ef99427e44633257ade43320" -to-iso-string@0.0.2: - version "0.0.2" - resolved "https://registry.yarnpkg.com/to-iso-string/-/to-iso-string-0.0.2.tgz#4dc19e664dfccbe25bd8db508b00c6da158255d1" - trim-right@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/trim-right/-/trim-right-1.0.1.tgz#cb2e1203067e0c8de1f614094b9fe45704ea6003" @@ -2921,22 +1882,6 @@ typedarray@^0.0.6: version "0.0.6" resolved "https://registry.yarnpkg.com/typedarray/-/typedarray-0.0.6.tgz#867ac74e3864187b1d3d47d996a78ec5c8830777" -unc-path-regex@^0.1.0: - version "0.1.2" - resolved "https://registry.yarnpkg.com/unc-path-regex/-/unc-path-regex-0.1.2.tgz#e73dd3d7b0d7c5ed86fbac6b0ae7d8c6a69d50fa" - -unique-stream@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/unique-stream/-/unique-stream-1.0.0.tgz#d59a4a75427447d9aa6c91e70263f8d26a4b104b" - -urix@^0.1.0, urix@~0.1.0: - version "0.1.0" - resolved "https://registry.yarnpkg.com/urix/-/urix-0.1.0.tgz#da937f7a62e21fec1fd18d49b35c2935067a6c72" - -user-home@^1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/user-home/-/user-home-1.1.1.tgz#2b5be23a32b63a7c9deb8d0f28d485724a3df190" - user-home@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/user-home/-/user-home-2.0.0.tgz#9c70bfd8169bc1dcbf48604e0f04b8b49cde9e9f" @@ -2953,60 +1898,6 @@ util-deprecate@~1.0.1: dependencies: inherits "2.0.1" -v8flags@^2.0.2: - version "2.0.11" - resolved "https://registry.yarnpkg.com/v8flags/-/v8flags-2.0.11.tgz#bca8f30f0d6d60612cc2c00641e6962d42ae6881" - dependencies: - user-home "^1.1.1" - -vinyl-fs@^0.3.0: - version "0.3.14" - resolved "https://registry.yarnpkg.com/vinyl-fs/-/vinyl-fs-0.3.14.tgz#9a6851ce1cac1c1cea5fe86c0931d620c2cfa9e6" - dependencies: - defaults "^1.0.0" - glob-stream "^3.1.5" - glob-watcher "^0.0.6" - graceful-fs "^3.0.0" - mkdirp "^0.5.0" - strip-bom "^1.0.0" - through2 "^0.6.1" - vinyl "^0.4.0" - -vinyl-sourcemaps-apply@^0.2.0: - version "0.2.1" - resolved "https://registry.yarnpkg.com/vinyl-sourcemaps-apply/-/vinyl-sourcemaps-apply-0.2.1.tgz#ab6549d61d172c2b1b87be5c508d239c8ef87705" - dependencies: - source-map "^0.5.1" - -vinyl@1.X: - version "1.2.0" - resolved "https://registry.yarnpkg.com/vinyl/-/vinyl-1.2.0.tgz#5c88036cf565e5df05558bfc911f8656df218884" - dependencies: - clone "^1.0.0" - clone-stats "^0.0.1" - replace-ext "0.0.1" - -vinyl@^0.4.0: - version "0.4.6" - resolved "https://registry.yarnpkg.com/vinyl/-/vinyl-0.4.6.tgz#2f356c87a550a255461f36bbeb2a5ba8bf784847" - dependencies: - clone "^0.2.0" - clone-stats "^0.0.1" - -vinyl@^0.5.0: - version "0.5.3" - resolved "https://registry.yarnpkg.com/vinyl/-/vinyl-0.5.3.tgz#b0455b38fc5e0cf30d4325132e461970c2091cde" - dependencies: - clone "^1.0.0" - clone-stats "^0.0.1" - replace-ext "0.0.1" - -which@^1.2.12: - version "1.2.12" - resolved "https://registry.yarnpkg.com/which/-/which-1.2.12.tgz#de67b5e450269f194909ef23ece4ebe416fa1192" - dependencies: - isexe "^1.1.1" - wordwrap@~1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/wordwrap/-/wordwrap-1.0.0.tgz#27584810891456a4171c8d0226441ade90cbcaeb" @@ -3021,6 +1912,6 @@ write@^0.2.1: dependencies: mkdirp "^0.5.1" -"xtend@>=4.0.0 <4.1.0-0", xtend@^4.0.0, xtend@~4.0.1: +xtend@^4.0.0: version "4.0.1" resolved "https://registry.yarnpkg.com/xtend/-/xtend-4.0.1.tgz#a5c6d532be656e23db820efb943a1f04998d63af" From dcb7f40d6a3457916cb36c71684e874b70be29b5 Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Mon, 3 Apr 2017 22:58:36 -0500 Subject: [PATCH 506/860] Update tailored dep --- package.json | 2 +- yarn.lock | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/package.json b/package.json index 5be1f75c..9f20f631 100644 --- a/package.json +++ b/package.json @@ -23,7 +23,7 @@ "license": "MIT", "dependencies": { "erlang-types": "^1.0.0", - "tailored": "2.4.1" + "tailored": "2.4.4" }, "devDependencies": { "babel-core": "^6.24.0", diff --git a/yarn.lock b/yarn.lock index c7b7c84c..ea295d82 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1838,9 +1838,9 @@ table@^3.7.8: slice-ansi "0.0.4" string-width "^2.0.0" -tailored@2.4.1: - version "2.4.1" - resolved "https://registry.yarnpkg.com/tailored/-/tailored-2.4.1.tgz#5fa0988704af192171dfe1299060ec97611225b4" +tailored@2.4.4: + version "2.4.4" + resolved "https://registry.yarnpkg.com/tailored/-/tailored-2.4.4.tgz#686642640d9d360cd8d26b8f313cc1203cb520a7" dependencies: erlang-types "^1.0.0" From e29a068fdbad1b0747067b244b74137c55c11b49 Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Tue, 4 Apr 2017 09:17:18 -0500 Subject: [PATCH 507/860] Update tailored to fix matching on tuples --- package.json | 2 +- src/javascript/lib/core/special_forms.js | 11 ++++++----- src/javascript/tests/with.spec.js | 7 +++---- yarn.lock | 6 +++--- 4 files changed, 13 insertions(+), 13 deletions(-) diff --git a/package.json b/package.json index 9f20f631..c9ecbf18 100644 --- a/package.json +++ b/package.json @@ -23,7 +23,7 @@ "license": "MIT", "dependencies": { "erlang-types": "^1.0.0", - "tailored": "2.4.4" + "tailored": "2.4.5" }, "devDependencies": { "babel-core": "^6.24.0", diff --git a/src/javascript/lib/core/special_forms.js b/src/javascript/lib/core/special_forms.js index faac7e94..e308ddf7 100644 --- a/src/javascript/lib/core/special_forms.js +++ b/src/javascript/lib/core/special_forms.js @@ -27,10 +27,10 @@ function _for(expression, generators, collectable_protocol, into = []) { for (const value of generatedValues) { if (expression.guard.apply(this, value)) { - result = fun(result, new Core.Tuple( - Symbol.for('cont'), - expression.fn.apply(this, value), - )); + result = fun( + result, + new Core.Tuple(Symbol.for('cont'), expression.fn.apply(this, value)), + ); } } @@ -39,7 +39,7 @@ function _for(expression, generators, collectable_protocol, into = []) { function run_list_generators(generator, generators) { if (generators.length == 0) { - return generator.map((x) => { + return generator.map(x => { if (Array.isArray(x)) { return x; } @@ -140,6 +140,7 @@ function _with(...args) { } return result; } + argsToPass = argsToPass.concat(patternResult); } diff --git a/src/javascript/tests/with.spec.js b/src/javascript/tests/with.spec.js index 9d5a6609..e1a30150 100644 --- a/src/javascript/tests/with.spec.js +++ b/src/javascript/tests/with.spec.js @@ -118,10 +118,9 @@ describe('with', () => { ), ); - expect(value).to.eql(new Tuple( - Symbol.for('error'), - Symbol.for('wrong_data'), - )); + expect(value).to.eql( + new Tuple(Symbol.for('error'), Symbol.for('wrong_data')), + ); }); it('with else that don`t match', () => { diff --git a/yarn.lock b/yarn.lock index ea295d82..ed077766 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1838,9 +1838,9 @@ table@^3.7.8: slice-ansi "0.0.4" string-width "^2.0.0" -tailored@2.4.4: - version "2.4.4" - resolved "https://registry.yarnpkg.com/tailored/-/tailored-2.4.4.tgz#686642640d9d360cd8d26b8f313cc1203cb520a7" +tailored@2.4.5: + version "2.4.5" + resolved "https://registry.yarnpkg.com/tailored/-/tailored-2.4.5.tgz#c100530d8c2978a0b75228159a46bfe636fa70d6" dependencies: erlang-types "^1.0.0" From f1e3d000ebf4059dbaae455ddb45442a48939310 Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Tue, 4 Apr 2017 09:31:08 -0500 Subject: [PATCH 508/860] Fix tuple pattern creation --- .../translator/pattern_matching.ex | 14 ++--- test/translator/case_test.exs | 40 +++++-------- test/translator/for_test.exs | 44 ++++---------- test/translator/function_test.exs | 22 ++++--- test/translator/match_test.exs | 21 +++---- test/translator/pattern_matching_test.exs | 16 ++--- test/translator/with_test.exs | 58 ++++++++----------- 7 files changed, 81 insertions(+), 134 deletions(-) diff --git a/lib/elixir_script/translator/pattern_matching.ex b/lib/elixir_script/translator/pattern_matching.ex index e90c59e5..6a9be928 100644 --- a/lib/elixir_script/translator/pattern_matching.ex +++ b/lib/elixir_script/translator/pattern_matching.ex @@ -244,14 +244,12 @@ defmodule ElixirScript.Translator.PatternMatching do |> Enum.map(&build_match([&1], env)) |> reduce_patterns - pattern = JS.object_expression([ - JS.property( - JS.identifier("values"), - JS.array_expression(patterns) - ) - ]) - - { [type(Primitive.tuple_class, pattern)], params } + tuple_pattern = JS.new_expression( + Primitive.tuple_class(), + patterns + ) + + { [tuple_pattern], params } end defp do_build_match({:\\, _, [{name, _, _}, default]}, env) do diff --git a/test/translator/case_test.exs b/test/translator/case_test.exs index 08bb8fbb..4a38b333 100644 --- a/test/translator/case_test.exs +++ b/test/translator/case_test.exs @@ -155,13 +155,11 @@ defmodule ElixirScript.Translator.Case.Test do end js_code = """ - Bootstrap.Core.Patterns.defmatch(Bootstrap.Core.Patterns.clause([Bootstrap.Core.Patterns.type(Bootstrap.Core.Tuple, { - values: [Bootstrap.Core.Patterns.variable(), Bootstrap.Core.Patterns.variable()] - })], function(one, two) { - return console.info(one); - }), Bootstrap.Core.Patterns.clause([Symbol.for('error')], function() { - return null; - })).call(this, data) +Bootstrap.Core.Patterns.defmatch(Bootstrap.Core.Patterns.clause([new Bootstrap.Core.Tuple(Bootstrap.Core.Patterns.variable(), Bootstrap.Core.Patterns.variable())], function(one, two) { + return console.info(one); + }), Bootstrap.Core.Patterns.clause([Symbol.for('error')], function() { + return null; + })).call(this, data); """ assert_translation(ex_ast, js_code) @@ -181,15 +179,11 @@ defmodule ElixirScript.Translator.Case.Test do end js_code = """ - Bootstrap.Core.Patterns.defmatch(Bootstrap.Core.Patterns.clause([Bootstrap.Core.Patterns.type(Bootstrap.Core.Tuple, { - values: [Bootstrap.Core.Patterns.type(Bootstrap.Core.Tuple, { - values: [Bootstrap.Core.Patterns.variable(), Bootstrap.Core.Patterns.variable()] - }), Bootstrap.Core.Patterns.variable()] - })], function(one, two, three) { - return console.info(one); - }), Bootstrap.Core.Patterns.clause([Symbol.for('error')], function() { - return null; - })).call(this, data) +Bootstrap.Core.Patterns.defmatch(Bootstrap.Core.Patterns.clause([new Bootstrap.Core.Tuple(new Bootstrap.Core.Tuple(Bootstrap.Core.Patterns.variable(), Bootstrap.Core.Patterns.variable()), Bootstrap.Core.Patterns.variable())], function(one, two, three) { + return console.info(one); + }), Bootstrap.Core.Patterns.clause([Symbol.for('error')], function() { + return null; + })).call(this, data) """ assert_translation(ex_ast, js_code) @@ -205,15 +199,11 @@ defmodule ElixirScript.Translator.Case.Test do end js_code = """ - Bootstrap.Core.Patterns.defmatch(Bootstrap.Core.Patterns.clause([Bootstrap.Core.Patterns.type(Bootstrap.Core.Tuple, { - values: [Bootstrap.Core.Patterns.variable(), Bootstrap.Core.Patterns.type(Bootstrap.Core.Tuple, { - values: [Bootstrap.Core.Patterns.variable(), Bootstrap.Core.Patterns.variable()] - })] - })], function(one, two, three) { - return console.info(one); - }), Bootstrap.Core.Patterns.clause([Symbol.for('error')], function() { - return null; - })).call(this, data) +Bootstrap.Core.Patterns.defmatch(Bootstrap.Core.Patterns.clause([new Bootstrap.Core.Tuple(Bootstrap.Core.Patterns.variable(), new Bootstrap.Core.Tuple(Bootstrap.Core.Patterns.variable(), Bootstrap.Core.Patterns.variable()))], function(one, two, three) { + return console.info(one); + }), Bootstrap.Core.Patterns.clause([Symbol.for('error')], function() { + return null; + })).call(this, data) """ assert_translation(ex_ast, js_code) diff --git a/test/translator/for_test.exs b/test/translator/for_test.exs index 6826d704..60fda4e7 100644 --- a/test/translator/for_test.exs +++ b/test/translator/for_test.exs @@ -8,25 +8,11 @@ defmodule ElixirScript.Translator.For.Test do end js_code = """ - Bootstrap.Core.SpecialForms._for( - Bootstrap.Core.Patterns.clause( - [Bootstrap.Core.Patterns.variable()], - function(n) { - return n * 2; - }, - function() { - return true; - } - ), - [ - Bootstrap.Core.Patterns.list_generator( - Bootstrap.Core.Patterns.variable(), - Object.freeze([1, 2, 3, 4]) - ) - ], - Elixir.ElixirScript.Collectable.__load(Elixir), - Object.freeze([]) - ) + Bootstrap.Core.SpecialForms._for(Bootstrap.Core.Patterns.clause([Bootstrap.Core.Patterns.variable()], function(n) { + return n * 2; + }, function() { + return true; + }), [Bootstrap.Core.Patterns.list_generator(Bootstrap.Core.Patterns.variable(), Object.freeze([1, 2, 3, 4]))], Elixir.ElixirScript.Collectable.__load(Elixir), Object.freeze([])) """ assert_translation(ex_ast, js_code) @@ -173,21 +159,11 @@ defmodule ElixirScript.Translator.For.Test do end js_code = """ - Bootstrap.Core.SpecialForms._for( - Bootstrap.Core.Patterns.clause([Bootstrap.Core.Patterns.type(Bootstrap.Core.Tuple, { - values: [Symbol.for('user'), Bootstrap.Core.Patterns.variable()] - })], function(name) { - return Elixir.ElixirScript.String.__load(Elixir).upcase(name); - }, function() { - return true; - }), - [ - Bootstrap.Core.Patterns.list_generator(Bootstrap.Core.Patterns.type(Bootstrap.Core.Tuple, { - values: [Symbol.for('user'), Bootstrap.Core.Patterns.variable()] - }), Object.freeze([new Bootstrap.Core.Tuple(Symbol.for('user'), 'john'), new Bootstrap.Core.Tuple(Symbol.for('admin'), 'john'), new Bootstrap.Core.Tuple(Symbol.for('user'), 'meg')])) - ], - Elixir.ElixirScript.Collectable.__load(Elixir), - Object.freeze([])) + Bootstrap.Core.SpecialForms._for(Bootstrap.Core.Patterns.clause([new Bootstrap.Core.Tuple(Symbol.for('user'), Bootstrap.Core.Patterns.variable())], function(name) { + return Elixir.ElixirScript.String.__load(Elixir).upcase(name); + }, function() { + return true; + }), [Bootstrap.Core.Patterns.list_generator(new Bootstrap.Core.Tuple(Symbol.for('user'), Bootstrap.Core.Patterns.variable()), Object.freeze([new Bootstrap.Core.Tuple(Symbol.for('user'), 'john'), new Bootstrap.Core.Tuple(Symbol.for('admin'), 'john'), new Bootstrap.Core.Tuple(Symbol.for('user'), 'meg')]))], Elixir.ElixirScript.Collectable.__load(Elixir), Object.freeze([])) """ assert_translation(ex_ast, js_code) diff --git a/test/translator/function_test.exs b/test/translator/function_test.exs index 0f883e30..2f6e6764 100644 --- a/test/translator/function_test.exs +++ b/test/translator/function_test.exs @@ -111,13 +111,13 @@ defmodule ElixirScript.Translator.Function.Test do end js_code = """ - const test1 = Bootstrap.Core.Patterns.defmatch(Bootstrap.Core.Patterns.clause([Bootstrap.Core.Patterns.variable(), Bootstrap.Core.Patterns.variable()], function(alpha, beta) { - let [a, b] = Bootstrap.Core.Patterns.match(Bootstrap.Core.Patterns.type(Bootstrap.Core.Tuple, { - values: [Bootstrap.Core.Patterns.variable(), Bootstrap.Core.Patterns.variable()] - }), new Bootstrap.Core.Tuple(1, 2)); - let _ref = new Bootstrap.Core.Tuple(a, b); - return _ref; - })); + const test1 = Bootstrap.Core.Patterns.defmatch(Bootstrap.Core.Patterns.clause([Bootstrap.Core.Patterns.variable(), Bootstrap.Core.Patterns.variable()], function(alpha, beta) { + let [a, b] = Bootstrap.Core.Patterns.match(new Bootstrap.Core.Tuple(Bootstrap.Core.Patterns.variable(), Bootstrap.Core.Patterns.variable()), new Bootstrap.Core.Tuple(1, 2)); + + let _ref = new Bootstrap.Core.Tuple(a, b); + + return _ref; + })); """ assert_translation(ex_ast, js_code) @@ -429,11 +429,9 @@ defmodule ElixirScript.Translator.Function.Test do js_code = """ - const something = Bootstrap.Core.Patterns.defmatch(Bootstrap.Core.Patterns.clause([Bootstrap.Core.Patterns.type(Bootstrap.Core.Tuple, { - values: [Bootstrap.Core.Patterns.variable(), Bootstrap.Core.Patterns.variable()] - })], function(apple, fruits) { - return null; - })); + const something = Bootstrap.Core.Patterns.defmatch(Bootstrap.Core.Patterns.clause([new Bootstrap.Core.Tuple(Bootstrap.Core.Patterns.variable(), Bootstrap.Core.Patterns.variable())], function(apple, fruits) { + return null; + })); """ assert_translation(ex_ast, js_code) diff --git a/test/translator/match_test.exs b/test/translator/match_test.exs index 88b13a03..639738f6 100644 --- a/test/translator/match_test.exs +++ b/test/translator/match_test.exs @@ -19,20 +19,20 @@ defmodule ElixirScript.Translator.Match.Test do {a, b} = {1, 2} end js_code = """ - let [a, b] = Bootstrap.Core.Patterns.match(Bootstrap.Core.Patterns.type(Bootstrap.Core.Tuple, { - values: [Bootstrap.Core.Patterns.variable(), Bootstrap.Core.Patterns.variable()] - }), new Bootstrap.Core.Tuple(1, 2)); - let _ref = new Bootstrap.Core.Tuple(a, b); + let [a, b] = Bootstrap.Core.Patterns.match( + new Bootstrap.Core.Tuple( + Bootstrap.Core.Patterns.variable(), + Bootstrap.Core.Patterns.variable() + ), + new Bootstrap.Core.Tuple(1, 2) + ); """ assert_translation(ex_ast, js_code) ex_ast = quote do: {a, _, c} = {1, 2, 3} js_code = """ - let [a, __ignored__, c] = Bootstrap.Core.Patterns.match(Bootstrap.Core.Patterns.type(Bootstrap.Core.Tuple, { - values: [Bootstrap.Core.Patterns.variable(), Bootstrap.Core.Patterns.variable(), Bootstrap.Core.Patterns.variable()] - }), new Bootstrap.Core.Tuple(1, 2, 3)); - let _ref = new Bootstrap.Core.Tuple(a, __ignored__, c); + let [a, __ignored__, c] = Bootstrap.Core.Patterns.match(new Bootstrap.Core.Tuple(Bootstrap.Core.Patterns.variable(), Bootstrap.Core.Patterns.variable(), Bootstrap.Core.Patterns.variable()), new Bootstrap.Core.Tuple(1, 2, 3)); """ assert_translation(ex_ast, js_code) @@ -43,10 +43,7 @@ defmodule ElixirScript.Translator.Match.Test do {^a, _, c} = {1, 2, 3} end js_code = """ - let [, __ignored__, c] = Bootstrap.Core.Patterns.match(Bootstrap.Core.Patterns.type(Bootstrap.Core.Tuple, { - values: [Bootstrap.Core.Patterns.bound(a), Bootstrap.Core.Patterns.variable(), Bootstrap.Core.Patterns.variable()] - }), new Bootstrap.Core.Tuple(1, 2, 3)); - let _ref = new Bootstrap.Core.Tuple(undefined, __ignored__, c); + let [, __ignored__, c] = Bootstrap.Core.Patterns.match(new Bootstrap.Core.Tuple(Bootstrap.Core.Patterns.bound(a), Bootstrap.Core.Patterns.variable(), Bootstrap.Core.Patterns.variable()), new Bootstrap.Core.Tuple(1, 2, 3)); """ assert_translation(ex_ast, js_code) diff --git a/test/translator/pattern_matching_test.exs b/test/translator/pattern_matching_test.exs index 1bebeb22..757c438d 100644 --- a/test/translator/pattern_matching_test.exs +++ b/test/translator/pattern_matching_test.exs @@ -193,10 +193,10 @@ defmodule ElixirScript.Translator.PatternMatching.Test do params = [{:{}, [], [1, {:b, [], Elixir}, 3]}] result = PatternMatching.build_match(params, scope ) expected_result = { - [PatternMatching.type(Primitive.tuple_class, JS.object_expression([JS.property( - JS.identifier("values"), - JS.array_expression([JS.literal(1), PatternMatching.parameter, JS.literal(3)]) - ) ] )) ], + [JS.new_expression( + Primitive.tuple_class(), + [JS.literal(1), PatternMatching.parameter, JS.literal(3)] + )], [JS.identifier("b")] } @@ -205,10 +205,10 @@ defmodule ElixirScript.Translator.PatternMatching.Test do params = [{1, {:b, [], Elixir}}] result = PatternMatching.build_match(params, scope ) expected_result = { - [PatternMatching.type(Primitive.tuple_class, JS.object_expression([JS.property( - JS.identifier("values"), - JS.array_expression([JS.literal(1), PatternMatching.parameter]) - ) ] )) ], + [JS.new_expression( + Primitive.tuple_class(), + [JS.literal(1), PatternMatching.parameter] + )], [JS.identifier("b")] } diff --git a/test/translator/with_test.exs b/test/translator/with_test.exs index 74133f03..58c44375 100644 --- a/test/translator/with_test.exs +++ b/test/translator/with_test.exs @@ -11,16 +11,12 @@ defmodule ElixirScript.Translator.With.Test do end js_code = """ - Bootstrap.Core.SpecialForms._with([Bootstrap.Core.Patterns.type(Bootstrap.Core.Tuple,{ - values: [Symbol.for('ok'), Bootstrap.Core.Patterns.variable()] - }), function() { - return Elixir.ElixirScript.Map.__load(Elixir).fetch(opts,Symbol.for('width')); - }],[Bootstrap.Core.Patterns.type(Bootstrap.Core.Tuple,{ - values: [Symbol.for('ok'), Bootstrap.Core.Patterns.variable()] - }), function(width) { - return Elixir.ElixirScript.Map.__load(Elixir).fetch(opts,Symbol.for('height')); - }],function(width,height) { - return new Bootstrap.Core.Tuple(Symbol.for('ok'),width * height); + Bootstrap.Core.SpecialForms._with([new Bootstrap.Core.Tuple(Symbol.for('ok'), Bootstrap.Core.Patterns.variable()), function() { + return Elixir.ElixirScript.Map.__load(Elixir).fetch(opts, Symbol.for('width')); + }], [new Bootstrap.Core.Tuple(Symbol.for('ok'), Bootstrap.Core.Patterns.variable()), function(width) { + return Elixir.ElixirScript.Map.__load(Elixir).fetch(opts, Symbol.for('height')); + }], function(width, height) { + return new Bootstrap.Core.Tuple(Symbol.for('ok'), width * height); }) """ @@ -37,18 +33,14 @@ defmodule ElixirScript.Translator.With.Test do end js_code = """ - Bootstrap.Core.SpecialForms._with([Bootstrap.Core.Patterns.type(Bootstrap.Core.Tuple,{ - values: [Symbol.for('ok'), Bootstrap.Core.Patterns.variable()] - }), function() { - return Elixir.ElixirScript.Map.__load(Elixir).fetch(opts,Symbol.for('width')); - }],[Bootstrap.Core.Patterns.variable(), function(width) { - return width * 2; - }],[Bootstrap.Core.Patterns.type(Bootstrap.Core.Tuple,{ - values: [Symbol.for('ok'), Bootstrap.Core.Patterns.variable()] - }), function(width,double_width) { - return Elixir.ElixirScript.Map.__load(Elixir).fetch(opts,Symbol.for('height')); - }],function(width,double_width,height) { - return new Bootstrap.Core.Tuple(Symbol.for('ok'),double_width * height); + Bootstrap.Core.SpecialForms._with([new Bootstrap.Core.Tuple(Symbol.for('ok'), Bootstrap.Core.Patterns.variable()), function() { + return Elixir.ElixirScript.Map.__load(Elixir).fetch(opts, Symbol.for('width')); + }], [Bootstrap.Core.Patterns.variable(), function(width) { + return width * 2; + }], [new Bootstrap.Core.Tuple(Symbol.for('ok'), Bootstrap.Core.Patterns.variable()), function(width, double_width) { + return Elixir.ElixirScript.Map.__load(Elixir).fetch(opts, Symbol.for('height')); + }], function(width, double_width, height) { + return new Bootstrap.Core.Tuple(Symbol.for('ok'), double_width * height); }) """ @@ -67,19 +59,15 @@ defmodule ElixirScript.Translator.With.Test do end js_code = """ - Bootstrap.Core.SpecialForms._with([Bootstrap.Core.Patterns.type(Bootstrap.Core.Tuple,{ - values: [Symbol.for('ok'), Bootstrap.Core.Patterns.variable()] - }), function() { - return Elixir.ElixirScript.Map.__load(Elixir).fetch(opts,Symbol.for('width')); - }],[Bootstrap.Core.Patterns.type(Bootstrap.Core.Tuple,{ - values: [Symbol.for('ok'), Bootstrap.Core.Patterns.variable()] - }), function(width) { - return Elixir.ElixirScript.Map.__load(Elixir).fetch(opts,Symbol.for('height')); - }],function(width,height) { - return new Bootstrap.Core.Tuple(Symbol.for('ok'),width * height); - },Bootstrap.Core.Patterns.defmatch(Bootstrap.Core.Patterns.clause([Symbol.for('error')],function() { - return new Bootstrap.Core.Tuple(Symbol.for('error'),Symbol.for('wrong_data')); - }))) + Bootstrap.Core.SpecialForms._with([new Bootstrap.Core.Tuple(Symbol.for('ok'), Bootstrap.Core.Patterns.variable()), function() { + return Elixir.ElixirScript.Map.__load(Elixir).fetch(opts, Symbol.for('width')); + }], [new Bootstrap.Core.Tuple(Symbol.for('ok'), Bootstrap.Core.Patterns.variable()), function(width) { + return Elixir.ElixirScript.Map.__load(Elixir).fetch(opts, Symbol.for('height')); + }], function(width, height) { + return new Bootstrap.Core.Tuple(Symbol.for('ok'), width * height); + }, Bootstrap.Core.Patterns.defmatch(Bootstrap.Core.Patterns.clause([Symbol.for('error')], function() { + return new Bootstrap.Core.Tuple(Symbol.for('error'), Symbol.for('wrong_data')); + }))) """ assert_translation(ex_ast, js_code) From f020aca99a99fd9d4bc7f2f953dcd5fbd0d62d3a Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Tue, 4 Apr 2017 18:52:57 -0500 Subject: [PATCH 509/860] Update struct pattern matching to use object matching instead of type --- .../translator/kernel/special_forms/struct.ex | 4 ++ .../translator/pattern_matching.ex | 10 +-- test/translator/function_test.exs | 44 +++++++----- test/translator/pattern_matching_test.exs | 32 ++++++--- test/translator/try_test.exs | 72 +++++++++++-------- 5 files changed, 99 insertions(+), 63 deletions(-) diff --git a/lib/elixir_script/translator/kernel/special_forms/struct.ex b/lib/elixir_script/translator/kernel/special_forms/struct.ex index 84c5becb..c8af4383 100644 --- a/lib/elixir_script/translator/kernel/special_forms/struct.ex +++ b/lib/elixir_script/translator/kernel/special_forms/struct.ex @@ -6,6 +6,10 @@ defmodule ElixirScript.Translator.Struct do alias ElixirScript.Translator.Map alias ElixirScript.Translator.Identifier + def get_struct_module_name(module_name, env) do + ElixirScript.Translator.State.get_module_name(env.state, Utils.quoted_to_name(module_name)) + end + def get_struct_class(module_name, env) do candiate_module_name = ElixirScript.Translator.State.get_module_name(env.state, Utils.quoted_to_name(module_name)) diff --git a/lib/elixir_script/translator/pattern_matching.ex b/lib/elixir_script/translator/pattern_matching.ex index 6a9be928..d03892b5 100644 --- a/lib/elixir_script/translator/pattern_matching.ex +++ b/lib/elixir_script/translator/pattern_matching.ex @@ -8,6 +8,7 @@ defmodule ElixirScript.Translator.PatternMatching do alias ElixirScript.Translator.Map alias ElixirScript.Translator.Struct alias ElixirScript.Translator.Bitstring + alias ElixirScript.Translator.Utils @patterns JS.member_expression( JS.member_expression( @@ -208,11 +209,12 @@ defmodule ElixirScript.Translator.PatternMatching do { JS.object_expression(List.wrap(props)), params } end - defp do_build_match({:%, _, [{:__aliases__, _, _} = name, {:%{}, meta, props}]}, env) do - struct_name = Struct.get_struct_class(name, env) - {pattern, params} = do_build_match({:%{}, meta, props}, env) + defp do_build_match({:%, _, [{:__aliases__, _, name}, {:%{}, meta, props}]}, env) do + module_name = ElixirScript.Translator.State.get_module_name(env.state, Utils.quoted_to_name(name)) + name = Utils.name_to_js_file_name(module_name) + {pattern, params} = do_build_match({:%{}, meta, [__struct__: String.to_atom(name)] ++ props}, env) - { [type(struct_name, pattern)], params } + { pattern, params } end defp do_build_match({:=, _, [{name, _, _}, right]}, env) when not name in [:%, :{}, :__aliases__, :^, :%{}] do diff --git a/test/translator/function_test.exs b/test/translator/function_test.exs index 2f6e6764..eb9e145e 100644 --- a/test/translator/function_test.exs +++ b/test/translator/function_test.exs @@ -449,9 +449,11 @@ defmodule ElixirScript.Translator.Function.Test do js_code = """ - const something = Bootstrap.Core.Patterns.defmatch(Bootstrap.Core.Patterns.clause([Bootstrap.Core.Patterns.type(Elixir.AStruct.__load(Elixir).Elixir$AStruct, {})], function() { - return null; - })); + const something = Bootstrap.Core.Patterns.defmatch(Bootstrap.Core.Patterns.clause([{ + [Symbol.for('__struct__')]: Symbol.for('Elixir.AStruct') + }], function() { + return null; + })); """ assert_translation(ex_ast, js_code) @@ -469,9 +471,11 @@ defmodule ElixirScript.Translator.Function.Test do end js_code = """ - const something = Bootstrap.Core.Patterns.defmatch(Bootstrap.Core.Patterns.clause([Bootstrap.Core.Patterns.capture(Bootstrap.Core.Patterns.type(Elixir.AStruct.__load(Elixir).Elixir$AStruct, {}))], function(a) { - return null; - })); + const something = Bootstrap.Core.Patterns.defmatch(Bootstrap.Core.Patterns.clause([Bootstrap.Core.Patterns.capture({ + [Symbol.for('__struct__')]: Symbol.for('Elixir.AStruct') + })], function(a) { + return null; + })); """ assert_translation(ex_ast, js_code) end @@ -505,11 +509,13 @@ defmodule ElixirScript.Translator.Function.Test do js_code = """ - const something = Bootstrap.Core.Patterns.defmatch(Bootstrap.Core.Patterns.clause([Bootstrap.Core.Patterns.type(Elixir.AStruct.__load(Elixir).Elixir$AStruct, { - [Symbol.for('key')]: Bootstrap.Core.Patterns.variable(), [Symbol.for('key1')]: 2 - })], function(value) { - return null; - })); + const something = Bootstrap.Core.Patterns.defmatch(Bootstrap.Core.Patterns.clause([{ + [Symbol.for('__struct__')]: Symbol.for('Elixir.AStruct'), + [Symbol.for('key')]: Bootstrap.Core.Patterns.variable(), + [Symbol.for('key1')]: 2 + }], function(value) { + return null; + })); """ assert_translation(ex_ast, js_code) @@ -525,13 +531,15 @@ defmodule ElixirScript.Translator.Function.Test do js_code = """ - const something = Bootstrap.Core.Patterns.defmatch(Bootstrap.Core.Patterns.clause([Bootstrap.Core.Patterns.type(Elixir.AStruct.__load(Elixir).Elixir$AStruct, { - [Symbol.for('key')]: Bootstrap.Core.Patterns.variable(), [Symbol.for('key1')]: 2 - })], function(value) { - return null; - }, function(value) { - return Elixir.ElixirScript.Kernel.__load(Elixir).is_number(value); - })); + const something = Bootstrap.Core.Patterns.defmatch(Bootstrap.Core.Patterns.clause([{ + [Symbol.for('__struct__')]: Symbol.for('Elixir.AStruct'), + [Symbol.for('key')]: Bootstrap.Core.Patterns.variable(), + [Symbol.for('key1')]: 2 + }], function(value) { + return null; + }, function(value) { + return Elixir.ElixirScript.Kernel.__load(Elixir).is_number(value); + })); """ assert_translation(ex_ast, js_code) diff --git a/test/translator/pattern_matching_test.exs b/test/translator/pattern_matching_test.exs index 757c438d..75598bc6 100644 --- a/test/translator/pattern_matching_test.exs +++ b/test/translator/pattern_matching_test.exs @@ -112,7 +112,11 @@ defmodule ElixirScript.Translator.PatternMatching.Test do params = [{:%, [], [{:__aliases__, [alias: false], [:Hello]}, {:%{}, [], []}]}] result = PatternMatching.build_match(params, scope ) expected_result = { - [PatternMatching.type(JS.identifier("Hello"), JS.object_expression([]))], + [JS.object_expression([ + JS.property(Primitive.make_atom(:__struct__), + Primitive.make_atom(Hello), + :init, false, false, true), + ])], [] } @@ -123,10 +127,12 @@ defmodule ElixirScript.Translator.PatternMatching.Test do params = [{:%, [], [{:__aliases__, [alias: false], [:Hello]}, {:%{}, [], [key: 1]}]}] result = PatternMatching.build_match(params, scope ) expected_result = { - [PatternMatching.type(JS.identifier("Hello"), JS.object_expression([ - Map.make_property(Translator.translate!(:key, scope ), Translator.translate!(1, scope )) - ])) - ], + [JS.object_expression([ + JS.property(Primitive.make_atom(:__struct__), + Primitive.make_atom(Hello), + :init, false, false, true), + Map.make_property(Translator.translate!(:key, scope ), Translator.translate!(1, scope)) + ])], [] } @@ -137,10 +143,12 @@ defmodule ElixirScript.Translator.PatternMatching.Test do params = [{:%, [], [{:__aliases__, [alias: false], [:Hello]}, {:%{}, [], [key: {:key, [], Elixir}]}]}] result = PatternMatching.build_match(params, scope ) expected_result = { - [PatternMatching.type(JS.identifier("Hello"), JS.object_expression([ - Map.make_property(Translator.translate!(:key, scope ), PatternMatching.parameter) - ])) - ], + [JS.object_expression([ + JS.property(Primitive.make_atom(:__struct__), + Primitive.make_atom(Hello), + :init, false, false, true), + Map.make_property(Translator.translate!(:key, scope ), PatternMatching.parameter()) + ])], [JS.identifier("key")] } @@ -171,7 +179,11 @@ defmodule ElixirScript.Translator.PatternMatching.Test do params = [{:=, [], [{:%, [], [{:__aliases__, [alias: false], [:AStruct]}, {:%{}, [], []}]}, {:a, [], ElixirScript.Translator.Function.Test}]}] result = PatternMatching.build_match(params, scope ) expected_result = { - [PatternMatching.capture(PatternMatching.type(JS.identifier("AStruct"), JS.object_expression([])))], + [PatternMatching.capture(JS.object_expression([ + JS.property(Primitive.make_atom(:__struct__), + Primitive.make_atom(AStruct), + :init, false, false, true), + ]))], [JS.identifier("a")] } diff --git a/test/translator/try_test.exs b/test/translator/try_test.exs index 645e73ec..868a03b2 100644 --- a/test/translator/try_test.exs +++ b/test/translator/try_test.exs @@ -13,11 +13,13 @@ defmodule ElixirScript.Translator.Try.Test do end js_code = """ - Bootstrap.Core.SpecialForms._try(function() { - return 1; - }, Bootstrap.Core.Patterns.defmatch(Bootstrap.Core.Patterns.clause([Bootstrap.Core.Patterns.type(ArgumentError, {})], function() { - return Elixir.ElixirScript.IO.__load(Elixir).puts('Invalid argument given'); - })), null, null, null) + Bootstrap.Core.SpecialForms._try(function() { + return 1; + }, Bootstrap.Core.Patterns.defmatch(Bootstrap.Core.Patterns.clause([{ + [Symbol.for('__struct__')]: Symbol.for('Elixir.ArgumentError') + }], function() { + return Elixir.ElixirScript.IO.__load(Elixir).puts('Invalid argument given'); + })), null, null, null) """ assert_translation(ex_ast, js_code) @@ -35,11 +37,13 @@ defmodule ElixirScript.Translator.Try.Test do end js_code = """ - Bootstrap.Core.SpecialForms._try(function() { - return 1; - }, Bootstrap.Core.Patterns.defmatch(Bootstrap.Core.Patterns.clause([Bootstrap.Core.Patterns.type(ArgumentError, {})], function() { - return Elixir.ElixirScript.IO.__load(Elixir).puts('Invalid argument given'); - })), null, null, null) + Bootstrap.Core.SpecialForms._try(function() { + return 1; + }, Bootstrap.Core.Patterns.defmatch(Bootstrap.Core.Patterns.clause([{ + [Symbol.for('__struct__')]: Symbol.for('Elixir.ArgumentError') + }], function() { + return Elixir.ElixirScript.IO.__load(Elixir).puts('Invalid argument given'); + })), null, null, null) """ assert_translation(ex_ast, js_code) @@ -106,13 +110,15 @@ defmodule ElixirScript.Translator.Try.Test do end js_code = """ - Bootstrap.Core.SpecialForms._try(function() { - return 1; - }, Bootstrap.Core.Patterns.defmatch(Bootstrap.Core.Patterns.clause([Bootstrap.Core.Patterns.type(ArgumentError, {})], function() { - return Elixir.ElixirScript.IO.__load(Elixir).puts('ArgumentError'); - }), Bootstrap.Core.Patterns.clause([Bootstrap.Core.Patterns.variable()], function(x) { - return Elixir.ElixirScript.IO.__load(Elixir).puts('x'); - })), null, null, null) + Bootstrap.Core.SpecialForms._try(function() { + return 1; + }, Bootstrap.Core.Patterns.defmatch(Bootstrap.Core.Patterns.clause([{ + [Symbol.for('__struct__')]: Symbol.for('Elixir.ArgumentError') + }], function() { + return Elixir.ElixirScript.IO.__load(Elixir).puts('ArgumentError'); + }), Bootstrap.Core.Patterns.clause([Bootstrap.Core.Patterns.variable()], function(x) { + return Elixir.ElixirScript.IO.__load(Elixir).puts('x'); + })), null, null, null) """ assert_translation(ex_ast, js_code) @@ -132,13 +138,15 @@ defmodule ElixirScript.Translator.Try.Test do end js_code = """ - Bootstrap.Core.SpecialForms._try(function() { - return 1; - }, Bootstrap.Core.Patterns.defmatch(Bootstrap.Core.Patterns.clause([Bootstrap.Core.Patterns.type(ArgumentError, {})], function() { - return Elixir.ElixirScript.IO.__load(Elixir).puts('Invalid argument given'); - })), null, null, function() { - return Elixir.ElixirScript.IO.__load(Elixir).puts('This is printed regardless if it failed or succeed'); - }) + Bootstrap.Core.SpecialForms._try(function() { + return 1; + }, Bootstrap.Core.Patterns.defmatch(Bootstrap.Core.Patterns.clause([{ + [Symbol.for('__struct__')]: Symbol.for('Elixir.ArgumentError') + }], function() { + return Elixir.ElixirScript.IO.__load(Elixir).puts('Invalid argument given'); + })), null, null, function() { + return Elixir.ElixirScript.IO.__load(Elixir).puts('This is printed regardless if it failed or succeed'); + }) """ assert_translation(ex_ast, js_code) @@ -207,13 +215,15 @@ defmodule ElixirScript.Translator.Try.Test do end js_code = """ - Bootstrap.Core.SpecialForms._try(function() { - return 1; - }, Bootstrap.Core.Patterns.defmatch(Bootstrap.Core.Patterns.clause([Bootstrap.Core.Patterns.type(ArgumentError, {})], function() { - return Elixir.ElixirScript.IO.__load(Elixir).puts('Invalid argument given'); - })), Bootstrap.Core.Patterns.defmatch(Bootstrap.Core.Patterns.clause([Symbol.for('throw'), Symbol.for('Error')], function() { - return Elixir.ElixirScript.IO.__load(Elixir).puts('caught error'); - })), null, null) + Bootstrap.Core.SpecialForms._try(function() { + return 1; + }, Bootstrap.Core.Patterns.defmatch(Bootstrap.Core.Patterns.clause([{ + [Symbol.for('__struct__')]: Symbol.for('Elixir.ArgumentError') + }], function() { + return Elixir.ElixirScript.IO.__load(Elixir).puts('Invalid argument given'); + })), Bootstrap.Core.Patterns.defmatch(Bootstrap.Core.Patterns.clause([Symbol.for('throw'), Symbol.for('Error')], function() { + return Elixir.ElixirScript.IO.__load(Elixir).puts('caught error'); + })), null, null) """ assert_translation(ex_ast, js_code) From 9e67c1a0f8af83fe3f4d6d623586e5b4f2a3a9db Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Wed, 5 Apr 2017 07:08:09 -0500 Subject: [PATCH 510/860] Update incorrect function calls found by compiler --- lib/elixir_script/translator.ex | 2 +- lib/elixir_script/translator/kernel/special_forms/call.ex | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/elixir_script/translator.ex b/lib/elixir_script/translator.ex index 5187266e..ae8e0f49 100644 --- a/lib/elixir_script/translator.ex +++ b/lib/elixir_script/translator.ex @@ -646,7 +646,7 @@ defmodule ElixirScript.Translator do { Identifier.make_identifier(name), env } has_function?(env.module, {name, 0}, env) -> - Call.make_function_call(name, [], env) + Call.make_local_function_call(name, [], env) ElixirScript.Translator.LexicalScope.find_module(env, {name, 0}) -> imported_module_name = ElixirScript.Translator.LexicalScope.find_module(env, {name, 0}) Call.make_module_function_call(imported_module_name, name, params, env) diff --git a/lib/elixir_script/translator/kernel/special_forms/call.ex b/lib/elixir_script/translator/kernel/special_forms/call.ex index 9990624d..2356c5a6 100644 --- a/lib/elixir_script/translator/kernel/special_forms/call.ex +++ b/lib/elixir_script/translator/kernel/special_forms/call.ex @@ -105,7 +105,7 @@ defmodule ElixirScript.Translator.Call do JS.identifier("call_property") ), [ - Translator.translate!(module_name), + Translator.translate!(module_name, env), Translator.translate!(to_string(function_name), env) ] ) From db2f827957a25292410752b03075cd3d8e7a0db1 Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Wed, 5 Apr 2017 22:55:32 -0500 Subject: [PATCH 511/860] Update struct implementation to not use classes --- lib/elixir_script/translator.ex | 16 ++- .../translator/kernel/defmodule.ex | 20 +-- .../translator/kernel/special_forms/map.ex | 18 ++- .../translator/kernel/special_forms/struct.ex | 107 +++++++++++++++ priv/std_lib/map.ex | 3 +- test/prelude/kernel_test.exs | 2 +- test/translator/defmodule_test.exs | 43 +++++- test/translator/map_test.exs | 4 +- test/translator/struct_test.exs | 122 ++++++++++++------ test/translator/try_test.exs | 2 +- 10 files changed, 272 insertions(+), 65 deletions(-) diff --git a/lib/elixir_script/translator.ex b/lib/elixir_script/translator.ex index ae8e0f49..0001e8e9 100644 --- a/lib/elixir_script/translator.ex +++ b/lib/elixir_script/translator.ex @@ -219,7 +219,13 @@ defmodule ElixirScript.Translator do end defp do_translate({:%, _, [alias_info, data]}, env) do - { Struct.new_struct(alias_info, data, env), env } + module = case create_module_name(alias_info, env) do + {module, _} -> + module + module -> + module + end + Call.make_module_function_call(module, :__struct__, [data], env) end defp do_translate({:%{}, _, [{:|, _, [map, data]}]}, env) do @@ -541,12 +547,12 @@ defmodule ElixirScript.Translator do Def.process_delegate(name, params, options, env) end - defp do_translate({:defstruct, _, attributes}, env) do - { Struct.make_defstruct(attributes, env), env } + defp do_translate({:defstruct, _, [attributes]}, env) do + { Struct.make_struct(attributes, env), env } end - defp do_translate({:defexception, _, attributes}, env) do - { Struct.make_defexception(attributes, env), env } + defp do_translate({:defexception, _, [attributes]}, env) do + { Struct.make_struct(attributes ++ [__exception__: true], env), env } end defp do_translate({:defmodule, _, [{:__aliases__, _, module_name_list}, [do: body]]}, env) do diff --git a/lib/elixir_script/translator/kernel/defmodule.ex b/lib/elixir_script/translator/kernel/defmodule.ex index 285eab4b..dd2c76ba 100644 --- a/lib/elixir_script/translator/kernel/defmodule.ex +++ b/lib/elixir_script/translator/kernel/defmodule.ex @@ -51,7 +51,11 @@ defmodule ElixirScript.Translator.Defmodule do { exported_functions, private_functions } = process_functions(functions, env) - {structs, body} = extract_structs_from_body(body, env) + struct_prop = if has_struct?(body) do + [JS.property(Identifier.make_identifier("__struct__"), Identifier.make_identifier("__struct__"), :init, true)] + else + [] + end body = Enum.map(body, fn(x) -> case x do @@ -65,7 +69,7 @@ defmodule ElixirScript.Translator.Defmodule do body = Group.inflate_groups(body) exported_object = JS.object_expression( - make_defstruct_property(module, structs) ++ + struct_prop ++ Enum.map(exported_functions, fn({key, _value}) -> JS.property(Identifier.make_identifier(key), Identifier.make_identifier(key), :init, true) end) @@ -74,7 +78,7 @@ defmodule ElixirScript.Translator.Defmodule do exported_functions = Enum.map(exported_functions, fn({_key, value}) -> value end) private_functions = Enum.map(private_functions, fn({_key, value}) -> value end) - body = structs ++ private_functions ++ exported_functions ++ body + body = private_functions ++ exported_functions ++ body {body, exported_object} end @@ -161,17 +165,17 @@ defmodule ElixirScript.Translator.Defmodule do end) end - def extract_structs_from_body(body, env) do - module_js_name = Utils.name_to_js_name(env.module) - - Enum.partition(body, fn(x) -> + def has_struct?(body) do + val = Enum.find(body, fn(x) -> case x do - %ESTree.VariableDeclaration{declarations: [%ESTree.VariableDeclarator{id: %ESTree.Identifier{name: ^module_js_name} } ] } -> + %ESTree.VariableDeclaration{declarations: [%ESTree.VariableDeclarator{id: %ESTree.Identifier{name: "__struct__"} } ] } -> true _ -> false end end) + + val != nil end defp make_defstruct_property(_, []) do diff --git a/lib/elixir_script/translator/kernel/special_forms/map.ex b/lib/elixir_script/translator/kernel/special_forms/map.ex index 02f17691..77e4382b 100644 --- a/lib/elixir_script/translator/kernel/special_forms/map.ex +++ b/lib/elixir_script/translator/kernel/special_forms/map.ex @@ -67,10 +67,22 @@ defmodule ElixirScript.Translator.Map do js_ast = JS.call_expression( JS.member_expression( - Primitive.special_forms(), - JS.identifier("map_update") + JS.identifier("Object"), + JS.identifier("freeze") ), - [map, data] + [ + JS.call_expression( + JS.member_expression( + JS.identifier("Object"), + JS.identifier("assign") + ), + [ + JS.object_expression([]), + map, + data + ] + ) + ] ) { js_ast, env } diff --git a/lib/elixir_script/translator/kernel/special_forms/struct.ex b/lib/elixir_script/translator/kernel/special_forms/struct.ex index c8af4383..ad3c50d7 100644 --- a/lib/elixir_script/translator/kernel/special_forms/struct.ex +++ b/lib/elixir_script/translator/kernel/special_forms/struct.ex @@ -139,4 +139,111 @@ defmodule ElixirScript.Translator.Struct do JS.variable_declaration([ref_declarator], :const) end + def make_struct(attributes, env) do + struct_name = Map.make_property(Translator.translate!(:__struct__, env), Translator.translate!({:__MODULE__, [], []}, env)) + + defaults = Enum.map(attributes, fn + ({x, y}) -> + Map.make_property( + Translator.translate!(x, env), + Translator.translate!(y, env) + ) + (x) -> + Map.make_property( + Translator.translate!(x, env), + Translator.translate!(nil, env) + ) + end) + + keys = Enum.map(attributes, fn + ({x, _}) -> + Translator.translate!(x, env) + (x) -> + Translator.translate!(x, env) + end) + + keys = JS.array_expression(keys) + defaults = JS.object_expression([struct_name] ++ defaults) + + allowed_keys = JS.variable_declaration([JS.variable_declarator( + JS.identifier("allowed_keys"), + keys + )], :const) + + value_keys = JS.variable_declaration([JS.variable_declarator( + JS.identifier("value_keys"), + JS.call_expression( + JS.member_expression( + JS.identifier("Object"), + JS.identifier("keys") + ), + [JS.identifier("values")] + ) + )], :const) + + every_call = JS.call_expression( + JS.member_expression( + JS.identifier("value_keys"), + JS.identifier("every") + ), + [ + JS.function_expression([JS.identifier("key")], [], JS.block_statement([ + JS.return_statement( + JS.call_expression( + JS.member_expression( + JS.identifier("allowed_keys"), + JS.identifier("includes") + ), + [JS.identifier("key")] + ) + ) + ])) + ] + ) + + every_call_result = JS.variable_declaration([JS.variable_declarator( + JS.identifier("every_call_result"), + every_call + )], :const) + + bottom = JS.if_statement( + JS.identifier("every_call_result"), + JS.block_statement([ + JS.return_statement( + JS.call_expression( + JS.member_expression( + JS.identifier("Object"), + JS.identifier("assign") + ), + [JS.object_expression([]), defaults, JS.identifier("values")] + ) + ) + ]), + JS.block_statement([ + JS.throw_statement( + JS.literal("Unallowed key found") + ) + ]) + ) + + func = JS.function_expression([ + %ESTree.AssignmentPattern{ + left: JS.identifier("values"), + right: JS.object_expression([]) + } + ], + [], + JS.block_statement([ + allowed_keys, + value_keys, + every_call_result, + bottom + ])) + + JS.variable_declaration([JS.variable_declarator( + JS.identifier("__struct__"), + func + )], :const) + end + end diff --git a/priv/std_lib/map.ex b/priv/std_lib/map.ex index 2fca8243..b8e48707 100644 --- a/priv/std_lib/map.ex +++ b/priv/std_lib/map.ex @@ -70,7 +70,8 @@ defmodule ElixirScript.Map do end def merge(map1, map2) do - Bootstrap.Core.SpecialForms.map_update(map1, map2) + JS.Object.assign(%{}, map1, map2) + |> JS.Object.freeze() end def split(map, keys) do diff --git a/test/prelude/kernel_test.exs b/test/prelude/kernel_test.exs index c080a158..e134c61e 100644 --- a/test/prelude/kernel_test.exs +++ b/test/prelude/kernel_test.exs @@ -9,7 +9,7 @@ defmodule ElixirScript.Lib.Elixir.Kernel.Test do js_code = """ - Elixir.ElixirScript.Range.__load(Elixir).Elixir$ElixirScript$Range.create(Object.freeze({ + Elixir.ElixirScript.Range.__load(Elixir).__struct__(Object.freeze({ [Symbol.for('first')]: 1, [Symbol.for('last')]: 4 })) diff --git a/test/translator/defmodule_test.exs b/test/translator/defmodule_test.exs index acc965e7..6d7c8b45 100644 --- a/test/translator/defmodule_test.exs +++ b/test/translator/defmodule_test.exs @@ -68,9 +68,24 @@ defmodule ElixirScript.Translator.Defmodule.Test do end js_code = """ - const Elixir$Animals$Elephant = Bootstrap.Core.Functions.defstruct({ - [Symbol.for('__struct__')]: Symbol.for('Elixir.Animals.Elephant'), [Symbol.for('trunk')]: true - }); + const __struct__ = function(values = {}) { + const allowed_keys = [Symbol.for('trunk')] + + const value_keys = Object.keys(values) + + const every_call_result = value_keys.every(function(key) { + return allowed_keys.includes(key); + }) + + if (every_call_result) { + return Object.assign({}, { + [Symbol.for('__struct__')]: Symbol.for('Elixir.Animals.Elephant'), + [Symbol.for('trunk')]: true + }, values); + } else { + throw 'Unallowed key found'; + } + }; """ assert_translation(ex_ast, js_code) @@ -101,10 +116,24 @@ defmodule ElixirScript.Translator.Defmodule.Test do end js_code = """ - const Elixir$Animals$Elephant$Bear = Bootstrap.Core.Functions.defstruct({ - [Symbol.for('__struct__')]: Symbol.for('Elixir.Animals.Elephant.Bear'), - [Symbol.for('trunk')]: true - }); + const __struct__ = function(values = {}) { + const allowed_keys = [Symbol.for('trunk')] + + const value_keys = Object.keys(values) + + const every_call_result = value_keys.every(function(key) { + return allowed_keys.includes(key); + }) + + if (every_call_result) { + return Object.assign({}, { + [Symbol.for('__struct__')]: Symbol.for('Elixir.Animals.Elephant.Bear'), + [Symbol.for('trunk')]: true + }, values); + } else { + throw 'Unallowed key found'; + } + }; """ assert_translation(ex_ast, js_code) diff --git a/test/translator/map_test.exs b/test/translator/map_test.exs index 75a237d5..8c49fcb6 100644 --- a/test/translator/map_test.exs +++ b/test/translator/map_test.exs @@ -49,9 +49,9 @@ defmodule ElixirScript.Translator.Map.Test do end js_code = """ - Bootstrap.Core.SpecialForms.map_update(map,Object.freeze({ + Object.freeze(Object.assign({}, map, Object.freeze({ [Symbol.for('value')]: 1 - })) + }))) """ assert_translation(ex_ast, js_code) diff --git a/test/translator/struct_test.exs b/test/translator/struct_test.exs index dcc07631..e02a9d60 100644 --- a/test/translator/struct_test.exs +++ b/test/translator/struct_test.exs @@ -10,11 +10,25 @@ defmodule ElixirScript.Translator.Struct.Test do end js_code = """ - const Elixir$User = Bootstrap.Core.Functions.defstruct({ - [Symbol.for('__struct__')]: Symbol.for('Elixir.User'), - [Symbol.for('name')]: 'john', - [Symbol.for('age')]: 27 - }); + const __struct__ = function(values = {}) { + const allowed_keys = [Symbol.for('name'), Symbol.for('age')] + + const value_keys = Object.keys(values) + + const every_call_result = value_keys.every(function(key) { + return allowed_keys.includes(key); + }) + + if (every_call_result) { + return Object.assign({}, { + [Symbol.for('__struct__')]: Symbol.for('Elixir.User'), + [Symbol.for('name')]: 'john', + [Symbol.for('age')]: 27 + }, values); + } else { + throw 'Unallowed key found'; + } + }; """ assert_translation(ex_ast, js_code) @@ -29,11 +43,25 @@ defmodule ElixirScript.Translator.Struct.Test do end js_code = """ - const Elixir$User = Bootstrap.Core.Functions.defstruct({ - [Symbol.for('__struct__')]: Symbol.for('Elixir.User'), - [Symbol.for('name')]: null, - [Symbol.for('age')]: null - }); + const __struct__ = function(values = {}) { + const allowed_keys = [Symbol.for('name'), Symbol.for('age')] + + const value_keys = Object.keys(values) + + const every_call_result = value_keys.every(function(key) { + return allowed_keys.includes(key); + }) + + if (every_call_result) { + return Object.assign({}, { + [Symbol.for('__struct__')]: Symbol.for('Elixir.User'), + [Symbol.for('name')]: null, + [Symbol.for('age')]: null + }, values); + } else { + throw 'Unallowed key found'; + } + }; """ assert_translation(ex_ast, js_code) @@ -50,11 +78,7 @@ defmodule ElixirScript.Translator.Struct.Test do end js_code = """ - const Elixir$User = Bootstrap.Core.Functions.defstruct({ - [Symbol.for('__struct__')]: Symbol.for('Elixir.User'), - [Symbol.for('name')]: null, - [Symbol.for('age')]: null - }); + Elixir.User.__load(Elixir).__struct__(Object.freeze({}) """ assert_translation(ex_ast, js_code) @@ -68,12 +92,7 @@ defmodule ElixirScript.Translator.Struct.Test do end js_code = """ - const Elixir$User = Bootstrap.Core.Functions.defstruct({ - [Symbol.for('__struct__')]: Symbol.for('Elixir.User'), - [Symbol.for('name')]: null, - [Symbol.for('age')]: null - }); - + Elixir.User.__load(Elixir).__struct__(Object.freeze({[Symbol.for('name')]: 'John'}) """ assert_translation(ex_ast, js_code) @@ -86,9 +105,9 @@ defmodule ElixirScript.Translator.Struct.Test do end js_code = """ - let [user] = Bootstrap.Core.Patterns.match(Bootstrap.Core.Patterns.variable(),Bootstrap.Core.SpecialForms.map_update(map,Object.freeze({ - [Symbol.for('key')]: 1 - }))); + let [user] = Bootstrap.Core.Patterns.match(Bootstrap.Core.Patterns.variable(), Object.freeze(Object.assign({}, map, Object.freeze({ + [Symbol.for('key')]: 1 + })))); """ assert_translation(ex_ast, js_code) @@ -100,9 +119,10 @@ defmodule ElixirScript.Translator.Struct.Test do end js_code = """ - let [user] = Bootstrap.Core.Patterns.match(Bootstrap.Core.Patterns.variable(),Bootstrap.Core.SpecialForms.map_update(map,Object.freeze({ - [Symbol.for('key')]: 1, [Symbol.for('key1')]: 11 - }))); + let [user] = Bootstrap.Core.Patterns.match(Bootstrap.Core.Patterns.variable(), Object.freeze(Object.assign({}, map, Object.freeze({ + [Symbol.for('key')]: 1, + [Symbol.for('key1')]: 11 + })))); """ assert_translation(ex_ast, js_code) @@ -116,11 +136,25 @@ defmodule ElixirScript.Translator.Struct.Test do end js_code = """ - const Elixir$MyAppError = Bootstrap.Core.Functions.defexception({ - [Symbol.for('__struct__')]: Symbol.for('Elixir.MyAppError'), - [Symbol.for('__exception__')]: true, - [Symbol.for('message')]: 'This is a message' - }); + const __struct__ = function(values = {}) { + const allowed_keys = [Symbol.for('message'), Symbol.for('__exception__')] + + const value_keys = Object.keys(values) + + const every_call_result = value_keys.every(function(key) { + return allowed_keys.includes(key); + }) + + if (every_call_result) { + return Object.assign({}, { + [Symbol.for('__struct__')]: Symbol.for('Elixir.MyAppError'), + [Symbol.for('message')]: 'This is a message', + [Symbol.for('__exception__')]: true + }, values); + } else { + throw 'Unallowed key found'; + } + }; """ assert_translation(ex_ast, js_code) @@ -132,11 +166,25 @@ defmodule ElixirScript.Translator.Struct.Test do end js_code = """ - const Elixir$MyAppError = Bootstrap.Core.Functions.defexception({ - [Symbol.for('__struct__')]: Symbol.for('Elixir.MyAppError'), - [Symbol.for('__exception__')]: true, - [Symbol.for('message')]: null - }); + const __struct__ = function(values = {}) { + const allowed_keys = [Symbol.for('message'), Symbol.for('__exception__')] + + const value_keys = Object.keys(values) + + const every_call_result = value_keys.every(function(key) { + return allowed_keys.includes(key); + }) + + if (every_call_result) { + return Object.assign({}, { + [Symbol.for('__struct__')]: Symbol.for('Elixir.MyAppError'), + [Symbol.for('message')]: null, + [Symbol.for('__exception__')]: true + }, values); + } else { + throw 'Unallowed key found'; + } + }; """ assert_translation(ex_ast, js_code) diff --git a/test/translator/try_test.exs b/test/translator/try_test.exs index 868a03b2..951f5d65 100644 --- a/test/translator/try_test.exs +++ b/test/translator/try_test.exs @@ -66,7 +66,7 @@ defmodule ElixirScript.Translator.Try.Test do },Bootstrap.Core.Patterns.defmatch(Bootstrap.Core.Patterns.clause([Bootstrap.Core.Patterns.variable()],function(x) { return Elixir.ElixirScript.IO.__load(Elixir).puts('Invalid argument given'); },function(x) { - return Elixir.ElixirScript.Bootstrap.Functions.__load(Elixir).contains(x,Object.freeze([ArgumentError.create(Object.freeze({}))])); + return Elixir.ElixirScript.Bootstrap.Functions.__load(Elixir).contains(x, Object.freeze([Elixir.ArgumentError.__load(Elixir).__struct__(Object.freeze({}))])); })),null,null,null) """ From 76bb6f85bc88abef617e814dd63753a0d0f91643 Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Wed, 5 Apr 2017 22:57:00 -0500 Subject: [PATCH 512/860] Remove js implementations of structs and map update --- src/javascript/lib/core/functions.js | 38 ------------------------ src/javascript/lib/core/special_forms.js | 6 ---- 2 files changed, 44 deletions(-) diff --git a/src/javascript/lib/core/functions.js b/src/javascript/lib/core/functions.js index 52a34def..f6d0e2df 100644 --- a/src/javascript/lib/core/functions.js +++ b/src/javascript/lib/core/functions.js @@ -64,42 +64,6 @@ function get_global() { throw new Error('No global state found'); } -function defstruct(defaults) { - return class { - constructor(update = {}) { - const the_values = Object.assign(defaults, update); - Object.assign(this, the_values); - } - - static create(updates = {}) { - const x = new this(updates); - return Object.freeze(x); - } - }; -} - -function defexception(defaults) { - return class extends Error { - constructor(update = {}) { - const message = update.message || ''; - super(message); - - const the_values = Object.assign(defaults, update); - Object.assign(this, the_values); - - this.name = this.constructor.name; - this.message = message; - this[Symbol.for('__exception__')] = true; - Error.captureStackTrace(this, this.constructor.name); - } - - static create(updates = {}) { - const x = new this(updates); - return Object.freeze(x); - } - }; -} - function defprotocol(spec) { return new Protocol(spec); } @@ -134,8 +98,6 @@ function build_namespace(ns, ns_string) { export default { call_property, get_global, - defstruct, - defexception, defprotocol, defimpl, build_namespace, diff --git a/src/javascript/lib/core/special_forms.js b/src/javascript/lib/core/special_forms.js index e308ddf7..a449bbe8 100644 --- a/src/javascript/lib/core/special_forms.js +++ b/src/javascript/lib/core/special_forms.js @@ -14,12 +14,6 @@ function cond(clauses) { throw new Error(); } -function map_update(map, values) { - return Object.freeze( - Object.assign(Object.create(map.constructor.prototype), map, values), - ); -} - function _for(expression, generators, collectable_protocol, into = []) { let [result, fun] = collectable_protocol.into(into); From b806f991fb8bb8a4d256f7b3e991750025f938fb Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Wed, 5 Apr 2017 22:57:23 -0500 Subject: [PATCH 513/860] Remove map_update export --- src/javascript/lib/core/special_forms.js | 1 - 1 file changed, 1 deletion(-) diff --git a/src/javascript/lib/core/special_forms.js b/src/javascript/lib/core/special_forms.js index a449bbe8..7be8c643 100644 --- a/src/javascript/lib/core/special_forms.js +++ b/src/javascript/lib/core/special_forms.js @@ -144,7 +144,6 @@ function _with(...args) { export default { _case, cond, - map_update, _for, _try, _with, From e1026bc31fa1a937784c58bcfa2fc1a0393b3716 Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Thu, 6 Apr 2017 21:48:32 -0500 Subject: [PATCH 514/860] Fix struct tests. Add js tests to test struct creation --- lib/elixir_script/translator.ex | 36 ++++- .../translator/kernel/defimpl.ex | 12 +- .../translator/kernel/special_forms/struct.ex | 133 ------------------ .../translator/kernel/special_forms/try.ex | 17 ++- lib/elixir_script/translator/state.ex | 1 + priv/std_lib/exceptions.ex | 3 + src/javascript/lib/core/protocol.js | 6 + test/app/spec/exception.spec.js | 51 +++++++ test/app/spec/struct.spec.js | 24 ++++ test/app/src/user.ex | 7 + test/translator/kernel_test.exs | 4 +- test/translator/struct_test.exs | 2 +- test/translator/try_test.exs | 12 +- 13 files changed, 148 insertions(+), 160 deletions(-) create mode 100644 priv/std_lib/exceptions.ex create mode 100644 test/app/spec/exception.spec.js create mode 100644 test/app/spec/struct.spec.js create mode 100644 test/app/src/user.ex diff --git a/lib/elixir_script/translator.ex b/lib/elixir_script/translator.ex index 0001e8e9..bcc20064 100644 --- a/lib/elixir_script/translator.ex +++ b/lib/elixir_script/translator.ex @@ -353,7 +353,15 @@ defmodule ElixirScript.Translator do end defp do_translate({:__MODULE__, _, _ }, env) do - translate(env.module, env) + module_name = create_module_name(env.module, env) + mod = case module_name do + {mod, _} -> + mod + mod -> + mod + end + + translate(mod, env) end defp do_translate({:__block__, _, expressions }, env) do @@ -584,17 +592,31 @@ defmodule ElixirScript.Translator do end defp do_translate({:raise, _, [alias_info, attributes]}, env) when is_list(attributes) do - js_ast = JS.throw_statement( - Struct.new_struct(alias_info, {:%{}, [], attributes }, env) - ) + module = case create_module_name(alias_info, env) do + {module, _} -> + module + module -> + module + end + + {call, _} = Call.make_module_function_call(module, :__struct__, [{:%{}, [], attributes }], env) + + js_ast = JS.throw_statement(call) { js_ast, env } end defp do_translate({:raise, _, [alias_info, message]}, env) do - js_ast = JS.throw_statement( - Struct.new_struct(alias_info, {:%{}, [], [message: message] }, env) - ) + module = case create_module_name(alias_info, env) do + {module, _} -> + module + module -> + module + end + + {call, _} = Call.make_module_function_call(module, :__struct__, [{:%{}, [], [message: message] }], env) + + js_ast = JS.throw_statement(call) { js_ast, env } end diff --git a/lib/elixir_script/translator/kernel/defimpl.ex b/lib/elixir_script/translator/kernel/defimpl.ex index 8c170abd..4f038974 100644 --- a/lib/elixir_script/translator/kernel/defimpl.ex +++ b/lib/elixir_script/translator/kernel/defimpl.ex @@ -124,10 +124,14 @@ defmodule ElixirScript.Translator.Defimpl do defp map_to_js({:__aliases__, _, _} = module, env) do - ElixirScript.Translator.Struct.get_struct_class( - module, - env - ) + module = case ElixirScript.Translator.create_module_name(module, env) do + {module, _} -> + module + module -> + module + end + + ElixirScript.Translator.translate!(module) end end diff --git a/lib/elixir_script/translator/kernel/special_forms/struct.ex b/lib/elixir_script/translator/kernel/special_forms/struct.ex index ad3c50d7..6d9f522f 100644 --- a/lib/elixir_script/translator/kernel/special_forms/struct.ex +++ b/lib/elixir_script/translator/kernel/special_forms/struct.ex @@ -6,139 +6,6 @@ defmodule ElixirScript.Translator.Struct do alias ElixirScript.Translator.Map alias ElixirScript.Translator.Identifier - def get_struct_module_name(module_name, env) do - ElixirScript.Translator.State.get_module_name(env.state, Utils.quoted_to_name(module_name)) - end - - def get_struct_class(module_name, env) do - candiate_module_name = ElixirScript.Translator.State.get_module_name(env.state, Utils.quoted_to_name(module_name)) - - if ElixirScript.Translator.LexicalScope.get_module_name(env, candiate_module_name) in ElixirScript.Translator.State.list_module_names(env.state) do - name = ElixirScript.Translator.LexicalScope.get_module_name(env, candiate_module_name) - ident = JS.identifier(Utils.name_to_js_name(name)) - ElixirScript.Translator.State.add_module_reference(env.state, env.module, name) - - members = ["Elixir"] ++ Module.split(name) ++ ["__load"] - - JS.member_expression( - JS.call_expression( - Identifier.make_namespace_members(members), - [JS.identifier("Elixir")] - ), - ident - ) - - else - Identifier.make_identifier(module_name) - end - end - - def new_struct(module_name, data, env) do - JS.call_expression( - JS.member_expression( - get_struct_class(module_name, env), - JS.identifier(:create) - ), - [Translator.translate!(data, env)] - ) - end - - def make_defstruct(attributes, env) when length(attributes) == 1 do - attributes = Enum.flat_map(attributes, fn(x) -> x end) - - defaults = Enum.map(attributes, fn - ({x, y}) -> - Map.make_property( - Translator.translate!(x, env), - Translator.translate!(y, env) - ) - (attribute) -> - Map.make_property( - Translator.translate!(attribute, env), - Translator.translate!(nil, env) - ) - end) - |> JS.object_expression - - do_make_defstruct(:defstruct, defaults, env) - end - - def make_defstruct(attributes, env) do - defaults = Enum.map(attributes, fn(x) -> - Map.make_property( - Translator.translate!(x, env), - Translator.translate!(nil, env) - ) - end) - |> JS.object_expression - - do_make_defstruct(:defstruct, defaults, env) - end - - def make_defexception(attributes, env) when length(attributes) == 1 do - exception_key_value = Map.make_property(Translator.translate!(:__exception__, env), Translator.translate!(true, env)) - - attributes = Enum.flat_map(attributes, fn(x) -> x end) - - defaults = [exception_key_value] ++ Enum.map(attributes, fn - ({x, y}) -> - Map.make_property( - Translator.translate!(x, env), - Translator.translate!(y, env) - ) - (x) -> - Map.make_property( - Translator.translate!(x, env), - Translator.translate!(nil, env) - ) - end) - |> JS.object_expression - - do_make_defstruct(:defexception, defaults, env) - end - - def make_defexceptions(attributes, env) do - exception_key_value = Map.make_property(Translator.translate!(:__exception__, env), Translator.translate!(true, env)) - - defaults = [exception_key_value] ++ Enum.map(attributes, fn - (x) -> - Map.make_property( - Translator.translate!(x, env), - Translator.translate!(nil, env) - ) - end) - |> JS.object_expression - - do_make_defstruct(:defexception, defaults, env) - end - - defp do_make_defstruct(name, defaults, env) do - struct_name = Map.make_property(Translator.translate!(:__struct__, env), Translator.translate!({:__MODULE__, [], []}, env)) - - defaults = %{ defaults | properties: [struct_name] ++ defaults.properties } - - ref = JS.identifier(Utils.name_to_js_name(env.module)) - - ref_declarator = JS.variable_declarator( - ref, - JS.call_expression( - JS.member_expression( - JS.member_expression( - JS.identifier("Bootstrap"), - JS.member_expression( - JS.identifier("Core"), - JS.identifier("Functions") - ) - ), - JS.identifier(name) - ), - [defaults] - ) - ) - - JS.variable_declaration([ref_declarator], :const) - end - def make_struct(attributes, env) do struct_name = Map.make_property(Translator.translate!(:__struct__, env), Translator.translate!({:__MODULE__, [], []}, env)) diff --git a/lib/elixir_script/translator/kernel/special_forms/try.ex b/lib/elixir_script/translator/kernel/special_forms/try.ex index c281b6a6..94276f23 100644 --- a/lib/elixir_script/translator/kernel/special_forms/try.ex +++ b/lib/elixir_script/translator/kernel/special_forms/try.ex @@ -62,10 +62,10 @@ defmodule ElixirScript.Translator.Try do { func, _ } = Enum.map(rescue_block, fn(x) -> case x do {:->, _, [[{value, _, module}], block]} when not is_list(module) -> - {:->, [], [[{value, [], convert_to_struct(module)}], block]} + {:->, [], [[{value, [], convert_to_struct(module, env)}], block]} {:->, _, [[{:in, meta, [value, error_names]}], block]} -> error_names = Enum.map(error_names, fn(x) -> - convert_to_struct(x) + convert_to_struct(x, env) end) guards = {:in, meta, [value, error_names]} @@ -73,7 +73,7 @@ defmodule ElixirScript.Translator.Try do {:->, [], [ [{:when, [], [value | [guards]]}], block ]} {:->, _, [error_names, block]} -> Enum.map(error_names, fn(x) -> - {:->, [], [[convert_to_struct(x)], block]} + {:->, [], [[convert_to_struct(x, env)], block]} end) end end) @@ -97,13 +97,16 @@ defmodule ElixirScript.Translator.Try do JS.function_expression([], [], translated_body) end - defp convert_to_struct([module]) do - convert_to_struct(module) + defp convert_to_struct([module], env) do + convert_to_struct(module, env) end - defp convert_to_struct(module) do + defp convert_to_struct(module, env) do case module do - {:__aliases__, _, _} = alias_ast-> + {:__aliases__, _, _} = alias_ast -> + alias_ast = ElixirScript.Translator.State.get_module_name(env.state, alias_ast) + |> ElixirScript.Translator.Utils.name_to_quoted + {:%, [], [alias_ast, {:%{}, [], []}]} ast -> ast diff --git a/lib/elixir_script/translator/state.ex b/lib/elixir_script/translator/state.ex index bb318401..fbbc936b 100644 --- a/lib/elixir_script/translator/state.ex +++ b/lib/elixir_script/translator/state.ex @@ -47,6 +47,7 @@ defmodule ElixirScript.Translator.State do |> Map.put(Process, ElixirScript.Process) |> Map.put(Regex, ElixirScript.Regex) |> Map.put(IO, ElixirScript.IO) + |> Map.put(ArgumentError, ElixirScript.ArgumentError) end def set_module_data(pid, module_data) do diff --git a/priv/std_lib/exceptions.ex b/priv/std_lib/exceptions.ex new file mode 100644 index 00000000..cb2ce0c5 --- /dev/null +++ b/priv/std_lib/exceptions.ex @@ -0,0 +1,3 @@ +defmodule ElixirScript.ArgumentError do + defexception message: "argument error" +end \ No newline at end of file diff --git a/src/javascript/lib/core/protocol.js b/src/javascript/lib/core/protocol.js index 52c25426..94f7feb2 100644 --- a/src/javascript/lib/core/protocol.js +++ b/src/javascript/lib/core/protocol.js @@ -23,6 +23,10 @@ class Protocol { typeof thing === 'string' && this.hasImplementation(Core.BitString) ) { fun = this.registry.get(Core.BitString)[funName]; + } else if ( + thing[Symbol.for('__struct__')] && this.hasImplementation(thing) + ) { + fun = this.registry.get(thing[Symbol.for('__struct__')])[funName]; } else if (this.hasImplementation(thing)) { fun = this.registry.get(thing.constructor)[funName]; } else if (this.fallback) { @@ -56,6 +60,8 @@ class Protocol { thing === Core.Integer || thing === Core.Float || thing === Core.BitString ) { return this.registry.has(thing); + } else if (thing[Symbol.for('__struct__')]) { + return this.registry.has(Symbol.for('__struct__')); } return this.registry.has(thing.constructor); diff --git a/test/app/spec/exception.spec.js b/test/app/spec/exception.spec.js new file mode 100644 index 00000000..8efaf8d7 --- /dev/null +++ b/test/app/spec/exception.spec.js @@ -0,0 +1,51 @@ +const expect = require('chai').expect; +const Elixir = require('../build/Elixir.App'); + +describe('Exception', () => { + it('Create Exception', () => { + const ArgumentError = Elixir.load(Elixir.ElixirScript.ArgumentError); + + let struct = ArgumentError.__struct__(); + + expect(Object.getOwnPropertySymbols(struct)).to.eql([ + Symbol.for('__struct__'), + Symbol.for('message'), + Symbol.for('__exception__'), + ]); + + expect(struct[Symbol.for('__struct__')]).to.eql( + Symbol.for('Elixir.ElixirScript.ArgumentError'), + ); + expect(struct[Symbol.for('__exception__')]).to.eql(true); + expect(struct[Symbol.for('message')]).to.eql('argument error'); + + struct = ArgumentError.__struct__({ + [Symbol.for('message')]: 'new argument error', + }); + + expect(struct[Symbol.for('message')]).to.eql('new argument error'); + }); + + it('raise exception', () => { + const User = Elixir.load(Elixir.User); + const ArgumentError = Elixir.load(Elixir.ElixirScript.ArgumentError); + + expect(User.throw_something()).to.throw(ArgumentError.__struct__()); + + let struct = User.__struct__(); + + expect(Object.getOwnPropertySymbols(struct)).to.eql([ + Symbol.for('__struct__'), + Symbol.for('first'), + Symbol.for('last'), + ]); + + expect(struct[Symbol.for('__struct__')]).to.eql(Symbol.for('Elixir.User')); + expect(struct[Symbol.for('first')]).to.eql(null); + expect(struct[Symbol.for('last')]).to.eql(null); + + struct = User.__struct__({ [Symbol.for('first')]: 'John' }); + + expect(struct[Symbol.for('first')]).to.eql('John'); + }); +}); diff --git a/test/app/spec/struct.spec.js b/test/app/spec/struct.spec.js new file mode 100644 index 00000000..768d3afd --- /dev/null +++ b/test/app/spec/struct.spec.js @@ -0,0 +1,24 @@ +const expect = require('chai').expect; +const Elixir = require('../build/Elixir.App'); + +describe('Struct', () => { + it('Create Struct', () => { + const User = Elixir.load(Elixir.User); + + let struct = User.__struct__(); + + expect(Object.getOwnPropertySymbols(struct)).to.eql([ + Symbol.for('__struct__'), + Symbol.for('first'), + Symbol.for('last'), + ]); + + expect(struct[Symbol.for('__struct__')]).to.eql(Symbol.for('Elixir.User')); + expect(struct[Symbol.for('first')]).to.eql(null); + expect(struct[Symbol.for('last')]).to.eql(null); + + struct = User.__struct__({ [Symbol.for('first')]: 'John' }); + + expect(struct[Symbol.for('first')]).to.eql('John'); + }); +}); diff --git a/test/app/src/user.ex b/test/app/src/user.ex new file mode 100644 index 00000000..bcdaf9ed --- /dev/null +++ b/test/app/src/user.ex @@ -0,0 +1,7 @@ +defmodule User do + defstruct [:first, :last] + + def throw_something() do + raise ArgumentError + end +end \ No newline at end of file diff --git a/test/translator/kernel_test.exs b/test/translator/kernel_test.exs index 7c645f73..2438c7f3 100644 --- a/test/translator/kernel_test.exs +++ b/test/translator/kernel_test.exs @@ -11,7 +11,7 @@ defmodule ElixirScript.Translator.Kernel.Test do end js_code = """ - throw ArgumentError.create(Object.freeze({ + throw Elixir.ElixirScript.ArgumentError.__load(Elixir).__struct__(Object.freeze({ [Symbol.for('message')]: 'cannot convert list to string. The list must contain only integers, strings or nested such lists; got: ' + Elixir.ElixirScript.String.Chars.__load(Elixir).to_string(inspect(list)) })); """ @@ -27,7 +27,7 @@ defmodule ElixirScript.Translator.Kernel.Test do end js_code = """ - throw ArgumentError.create(Object.freeze({ + throw Elixir.ElixirScript.ArgumentError.__load(Elixir).__struct__(Object.freeze({ [Symbol.for('message')]: 'cannot convert list to string. The list must contain only integers, strings or nested such lists; got' })); """ diff --git a/test/translator/struct_test.exs b/test/translator/struct_test.exs index e02a9d60..b562a050 100644 --- a/test/translator/struct_test.exs +++ b/test/translator/struct_test.exs @@ -204,7 +204,7 @@ defmodule ElixirScript.Translator.Struct.Test do end js_code = """ - throw Elixir.MyAppError.__load(Elixir).Elixir$MyAppError.create(Object.freeze({ + throw Elixir.MyAppError.__load(Elixir).__struct__(Object.freeze({ [Symbol.for('message')]: 'did not get what was expected' })); """ diff --git a/test/translator/try_test.exs b/test/translator/try_test.exs index 951f5d65..f8728b61 100644 --- a/test/translator/try_test.exs +++ b/test/translator/try_test.exs @@ -16,7 +16,7 @@ defmodule ElixirScript.Translator.Try.Test do Bootstrap.Core.SpecialForms._try(function() { return 1; }, Bootstrap.Core.Patterns.defmatch(Bootstrap.Core.Patterns.clause([{ - [Symbol.for('__struct__')]: Symbol.for('Elixir.ArgumentError') + [Symbol.for('__struct__')]: Symbol.for('Elixir.ElixirScript.ArgumentError') }], function() { return Elixir.ElixirScript.IO.__load(Elixir).puts('Invalid argument given'); })), null, null, null) @@ -40,7 +40,7 @@ defmodule ElixirScript.Translator.Try.Test do Bootstrap.Core.SpecialForms._try(function() { return 1; }, Bootstrap.Core.Patterns.defmatch(Bootstrap.Core.Patterns.clause([{ - [Symbol.for('__struct__')]: Symbol.for('Elixir.ArgumentError') + [Symbol.for('__struct__')]: Symbol.for('Elixir.ElixirScript.ArgumentError') }], function() { return Elixir.ElixirScript.IO.__load(Elixir).puts('Invalid argument given'); })), null, null, null) @@ -66,7 +66,7 @@ defmodule ElixirScript.Translator.Try.Test do },Bootstrap.Core.Patterns.defmatch(Bootstrap.Core.Patterns.clause([Bootstrap.Core.Patterns.variable()],function(x) { return Elixir.ElixirScript.IO.__load(Elixir).puts('Invalid argument given'); },function(x) { - return Elixir.ElixirScript.Bootstrap.Functions.__load(Elixir).contains(x, Object.freeze([Elixir.ArgumentError.__load(Elixir).__struct__(Object.freeze({}))])); + return Elixir.ElixirScript.Bootstrap.Functions.__load(Elixir).contains(x, Object.freeze([Elixir.ElixirScript.ArgumentError.__load(Elixir).__struct__(Object.freeze({}))])); })),null,null,null) """ @@ -113,7 +113,7 @@ defmodule ElixirScript.Translator.Try.Test do Bootstrap.Core.SpecialForms._try(function() { return 1; }, Bootstrap.Core.Patterns.defmatch(Bootstrap.Core.Patterns.clause([{ - [Symbol.for('__struct__')]: Symbol.for('Elixir.ArgumentError') + [Symbol.for('__struct__')]: Symbol.for('Elixir.ElixirScript.ArgumentError') }], function() { return Elixir.ElixirScript.IO.__load(Elixir).puts('ArgumentError'); }), Bootstrap.Core.Patterns.clause([Bootstrap.Core.Patterns.variable()], function(x) { @@ -141,7 +141,7 @@ defmodule ElixirScript.Translator.Try.Test do Bootstrap.Core.SpecialForms._try(function() { return 1; }, Bootstrap.Core.Patterns.defmatch(Bootstrap.Core.Patterns.clause([{ - [Symbol.for('__struct__')]: Symbol.for('Elixir.ArgumentError') + [Symbol.for('__struct__')]: Symbol.for('Elixir.ElixirScript.ArgumentError') }], function() { return Elixir.ElixirScript.IO.__load(Elixir).puts('Invalid argument given'); })), null, null, function() { @@ -218,7 +218,7 @@ defmodule ElixirScript.Translator.Try.Test do Bootstrap.Core.SpecialForms._try(function() { return 1; }, Bootstrap.Core.Patterns.defmatch(Bootstrap.Core.Patterns.clause([{ - [Symbol.for('__struct__')]: Symbol.for('Elixir.ArgumentError') + [Symbol.for('__struct__')]: Symbol.for('Elixir.ElixirScript.ArgumentError') }], function() { return Elixir.ElixirScript.IO.__load(Elixir).puts('Invalid argument given'); })), Bootstrap.Core.Patterns.defmatch(Bootstrap.Core.Patterns.clause([Symbol.for('throw'), Symbol.for('Error')], function() { From 6a285df260164152ec648b489e9e83d7d4d6738b Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Fri, 7 Apr 2017 01:03:23 -0500 Subject: [PATCH 515/860] Fix new implementation of structs with protocol implementations --- lib/elixir_script/translator.ex | 15 +++++++++++++ .../translator/kernel/defimpl.ex | 2 +- src/javascript/lib/core/protocol.js | 2 +- test/app/spec/exception.spec.js | 22 +++++-------------- test/app/spec/struct.spec.js | 12 ++++++++++ test/app/src/user.ex | 10 +++++++++ 6 files changed, 44 insertions(+), 19 deletions(-) diff --git a/lib/elixir_script/translator.ex b/lib/elixir_script/translator.ex index bcc20064..ca71c476 100644 --- a/lib/elixir_script/translator.ex +++ b/lib/elixir_script/translator.ex @@ -621,6 +621,21 @@ defmodule ElixirScript.Translator do { js_ast, env } end + defp do_translate({:raise, _, [{:__aliases__, _, _} = alias_info]}, env) do + module = case create_module_name(alias_info, env) do + {module, _} -> + module + module -> + module + end + + {call, _} = Call.make_module_function_call(module, :__struct__, [], env) + + js_ast = JS.throw_statement(call) + + { js_ast, env } + end + defp do_translate({:raise, _, [message]}, env) do js_ast = JS.throw_statement( JS.object_expression( diff --git a/lib/elixir_script/translator/kernel/defimpl.ex b/lib/elixir_script/translator/kernel/defimpl.ex index 4f038974..0e1dde5d 100644 --- a/lib/elixir_script/translator/kernel/defimpl.ex +++ b/lib/elixir_script/translator/kernel/defimpl.ex @@ -131,7 +131,7 @@ defmodule ElixirScript.Translator.Defimpl do module end - ElixirScript.Translator.translate!(module) + ElixirScript.Translator.translate!(module, env) end end diff --git a/src/javascript/lib/core/protocol.js b/src/javascript/lib/core/protocol.js index 94f7feb2..02fb4f08 100644 --- a/src/javascript/lib/core/protocol.js +++ b/src/javascript/lib/core/protocol.js @@ -61,7 +61,7 @@ class Protocol { ) { return this.registry.has(thing); } else if (thing[Symbol.for('__struct__')]) { - return this.registry.has(Symbol.for('__struct__')); + return this.registry.has(thing[Symbol.for('__struct__')]); } return this.registry.has(thing.constructor); diff --git a/test/app/spec/exception.spec.js b/test/app/spec/exception.spec.js index 8efaf8d7..7e3f19db 100644 --- a/test/app/spec/exception.spec.js +++ b/test/app/spec/exception.spec.js @@ -30,22 +30,10 @@ describe('Exception', () => { const User = Elixir.load(Elixir.User); const ArgumentError = Elixir.load(Elixir.ElixirScript.ArgumentError); - expect(User.throw_something()).to.throw(ArgumentError.__struct__()); - - let struct = User.__struct__(); - - expect(Object.getOwnPropertySymbols(struct)).to.eql([ - Symbol.for('__struct__'), - Symbol.for('first'), - Symbol.for('last'), - ]); - - expect(struct[Symbol.for('__struct__')]).to.eql(Symbol.for('Elixir.User')); - expect(struct[Symbol.for('first')]).to.eql(null); - expect(struct[Symbol.for('last')]).to.eql(null); - - struct = User.__struct__({ [Symbol.for('first')]: 'John' }); - - expect(struct[Symbol.for('first')]).to.eql('John'); + try { + User.throw_something(); + } catch (e) { + expect(e[Symbol.for('message')]).to.eql('argument error'); + } }); }); diff --git a/test/app/spec/struct.spec.js b/test/app/spec/struct.spec.js index 768d3afd..765ea491 100644 --- a/test/app/spec/struct.spec.js +++ b/test/app/spec/struct.spec.js @@ -21,4 +21,16 @@ describe('Struct', () => { expect(struct[Symbol.for('first')]).to.eql('John'); }); + + it('Protocol', () => { + const User = Elixir.load(Elixir.User); + const StringChars = Elixir.load(Elixir.ElixirScript.String.Chars); + + const struct = User.__struct__({ + [Symbol.for('first')]: 'John', + [Symbol.for('last')]: 'Doe', + }); + + expect(StringChars.to_string(struct)).to.eql('JohnDoe'); + }); }); diff --git a/test/app/src/user.ex b/test/app/src/user.ex index bcdaf9ed..2781433d 100644 --- a/test/app/src/user.ex +++ b/test/app/src/user.ex @@ -4,4 +4,14 @@ defmodule User do def throw_something() do raise ArgumentError end +end + +defimpl String.Chars, for: User do + def to_string(nil) do + "" + end + + def to_string(user) do + user.first <> user.last + end end \ No newline at end of file From 1842c66f0f573b802f8b7cb2d0aeb1847517adb4 Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Sat, 8 Apr 2017 10:01:13 -0500 Subject: [PATCH 516/860] Remove tests for map_update --- src/javascript/tests/special_forms.spec.js | 33 ---------------------- 1 file changed, 33 deletions(-) delete mode 100644 src/javascript/tests/special_forms.spec.js diff --git a/src/javascript/tests/special_forms.spec.js b/src/javascript/tests/special_forms.spec.js deleted file mode 100644 index cc540546..00000000 --- a/src/javascript/tests/special_forms.spec.js +++ /dev/null @@ -1,33 +0,0 @@ -import Core from "../lib/core"; -const SpecialForms = Core.SpecialForms; - -import chai from 'chai'; -var expect = chai.expect; - -describe('SpecialForms', function(){ - - describe('map_update', function(){ - it('creates new object', function(){ - const foo = Object.freeze({foo: "bar", fizz: "buzz"}); - const bar = SpecialForms.map_update(foo, {baz: "bar", fizz: "fizzbuzz"}); - - expect(foo instanceof Object).to.equal(bar instanceof Object); - expect(foo.foo).to.equal(bar.foo); - expect(bar.fizz).to.equal("fizzbuzz"); - expect(foo === bar).to.equal(false); - }); - - it('creates new class', function(){ - function MyClass(foo){ - this.foo = foo; - } - - const foo = new MyClass("bar"); - const bar = SpecialForms.map_update(foo, {baz: "bar", fizz: "fizzbuzz"}); - - expect(foo instanceof MyClass).to.equal(bar instanceof MyClass); - expect(foo.foo).to.equal(bar.foo); - expect(bar.fizz).to.equal("fizzbuzz"); - }); - }); -}); From 0e899a57189d28ef7c40a7b41b66014f26052c96 Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Sat, 8 Apr 2017 10:16:38 -0500 Subject: [PATCH 517/860] Make standard lib map by iterating over elixir modules --- lib/elixir_script/translator/state.ex | 36 ++++++++------------------- 1 file changed, 10 insertions(+), 26 deletions(-) diff --git a/lib/elixir_script/translator/state.ex b/lib/elixir_script/translator/state.ex index fbbc936b..b5fff798 100644 --- a/lib/elixir_script/translator/state.ex +++ b/lib/elixir_script/translator/state.ex @@ -22,32 +22,16 @@ defmodule ElixirScript.Translator.State do end defp build_standard_lib_map() do - Map.new - |> Map.put(Kernel, ElixirScript.Kernel) - |> Map.put(Tuple, ElixirScript.Tuple) - |> Map.put(Atom, ElixirScript.Atom) - |> Map.put(Collectable, ElixirScript.Collectable) - |> Map.put(String.Chars, ElixirScript.String.Chars) - |> Map.put(Enumerable, ElixirScript.Enumerable) - |> Map.put(Enum, ElixirScript.Enum) - |> Map.put(Enum.OutOfBoundsError, ElixirScript.Enum.OutOfBoundsError) - |> Map.put(Integer, ElixirScript.Integer) - |> Map.put(Macro.Env, ElixirScript.Macro.Env) - |> Map.put(View, ElixirScript.View) - |> Map.put(Agent, ElixirScript.Agent) - |> Map.put(Range, ElixirScript.Range) - |> Map.put(String, ElixirScript.String) - |> Map.put(Base, ElixirScript.Base) - |> Map.put(Module, ElixirScript.Module) - |> Map.put(Map, ElixirScript.Map) - |> Map.put(Keyword, ElixirScript.Keyword) - |> Map.put(Bitwise, ElixirScript.Bitwise) - |> Map.put(MapSet, ElixirScript.MapSet) - |> Map.put(List, ElixirScript.List) - |> Map.put(Process, ElixirScript.Process) - |> Map.put(Regex, ElixirScript.Regex) - |> Map.put(IO, ElixirScript.IO) - |> Map.put(ArgumentError, ElixirScript.ArgumentError) + Application.spec(:elixir, :modules) + |> Enum.reduce(Map.new, fn(x, acc) -> + try do + elixirscript_module = (["ElixirScript"] ++ Module.split(x)) |> Module.concat() + Map.put(acc, x, elixirscript_module) + rescue + FunctionClauseError -> + acc + end + end) end def set_module_data(pid, module_data) do From e03a42e8b2940ea2b23e9d5fcf4bbd8e8e92d762 Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Sun, 9 Apr 2017 09:41:58 -0500 Subject: [PATCH 518/860] Add file of supported Elixir modules and functions --- Supported.md | 2004 ++++++++++++++++++++++++++++ lib/elixir_script/gen/supported.ex | 70 + lib/elixir_script/translator.ex | 5 - mix.exs | 9 +- priv/std_lib/exceptions.ex | 4 + priv/std_lib/kernel.ex | 4 + 6 files changed, 2090 insertions(+), 6 deletions(-) create mode 100644 Supported.md create mode 100644 lib/elixir_script/gen/supported.ex diff --git a/Supported.md b/Supported.md new file mode 100644 index 00000000..42a37640 --- /dev/null +++ b/Supported.md @@ -0,0 +1,2004 @@ +# Supported Elixir Modules +## BadStructError +- [ ] __struct__/0 +- [ ] __struct__/1 +- [ ] exception/1 +- [ ] message/1 +## Collectable.List +- [X] __impl__/1 +- [X] into/1 +## Inspect.Float +- [ ] __impl__/1 +- [ ] inspect/2 +## String.Chars.Version.Requirement +- [ ] __impl__/1 +- [ ] to_string/1 +## Inspect.NaiveDateTime +- [ ] __impl__/1 +- [ ] inspect/2 +## Inspect.MapSet +- [ ] __impl__/1 +- [ ] inspect/2 +## Inspect +- [ ] __protocol__/1 +- [ ] impl_for/1 +- [ ] impl_for!/1 +- [ ] inspect/2 +## Inspect.Range +- [ ] __impl__/1 +- [ ] inspect/2 +## ArgumentError +- [X] __struct__/0 +- [X] __struct__/1 +- [X] exception/1 +- [X] message/1 +## Base +- [ ] decode16/1 +- [ ] decode16/2 +- [ ] decode16!/1 +- [ ] decode16!/2 +- [ ] decode32/1 +- [ ] decode32/2 +- [ ] decode32!/1 +- [ ] decode32!/2 +- [X] decode64/1 +- [ ] decode64/2 +- [X] decode64!/1 +- [ ] decode64!/2 +- [ ] encode16/1 +- [ ] encode16/2 +- [ ] encode32/1 +- [ ] encode32/2 +- [X] encode64/1 +- [ ] encode64/2 +- [ ] hex_decode32/1 +- [ ] hex_decode32/2 +- [ ] hex_decode32!/1 +- [ ] hex_decode32!/2 +- [ ] hex_encode32/1 +- [ ] hex_encode32/2 +- [ ] url_decode64/1 +- [ ] url_decode64/2 +- [ ] url_decode64!/1 +- [ ] url_decode64!/2 +- [ ] url_encode64/1 +- [ ] url_encode64/2 +## Macro.Env +- [X] __struct__/0 +- [X] __struct__/1 +- [ ] in_guard?/1 +- [ ] in_match?/1 +- [ ] location/1 +- [ ] stacktrace/1 +## Collectable.Map +- [X] __impl__/1 +- [X] into/1 +## Inspect.Regex +- [ ] __impl__/1 +- [ ] inspect/2 +## Behaviour +- [ ] __using__/1 +- [ ] defcallback/1 +- [ ] defmacrocallback/1 +## Collectable +- [X] __protocol__/1 +- [X] impl_for/1 +- [X] impl_for!/1 +- [X] into/1 +## String.Chars.Time +- [ ] __impl__/1 +- [ ] to_string/1 +## String.Chars.Atom +- [X] __impl__/1 +- [X] to_string/1 +## String.Chars +- [X] __protocol__/1 +- [X] impl_for/1 +- [X] impl_for!/1 +- [X] to_string/1 +## Integer +- [ ] digits/1 +- [ ] digits/2 +- [ ] floor_div/2 +- [ ] mod/2 +- [X] parse/1 +- [X] parse/2 +- [X] to_char_list/1 +- [ ] to_charlist/1 +- [ ] to_charlist/2 +- [ ] to_string/1 +- [ ] to_string/2 +- [ ] undigits/1 +- [ ] undigits/2 +- [X] is_even/1 +- [X] is_odd/1 +## String.Chars.NaiveDateTime +- [ ] __impl__/1 +- [ ] to_string/1 +## Inspect.Any +- [ ] __impl__/1 +- [ ] inspect/2 +## BadMapError +- [ ] __struct__/0 +- [ ] __struct__/1 +- [ ] exception/1 +- [ ] message/1 +## BadArityError +- [ ] __struct__/0 +- [ ] __struct__/1 +- [ ] exception/1 +- [ ] message/1 +## Kernel +- [X] !=/2 +- [X] !==/2 +- [X] */2 +- [X] +/1 +- [X] +/2 +- [X] ++/2 +- [X] -/1 +- [X] -/2 +- [X] --/2 +- [X] //2 +- [X] /2 +- [X] >=/2 +- [X] abs/1 +- [X] apply/2 +- [X] apply/3 +- [X] binary_part/3 +- [ ] bit_size/1 +- [ ] byte_size/1 +- [X] div/2 +- [X] elem/2 +- [ ] exit/1 +- [ ] function_exported?/3 +- [ ] get_and_update_in/3 +- [ ] get_in/2 +- [X] hd/1 +- [ ] inspect/1 +- [ ] inspect/2 +- [X] is_atom/1 +- [X] is_binary/1 +- [X] is_bitstring/1 +- [X] is_boolean/1 +- [X] is_float/1 +- [X] is_function/1 +- [X] is_function/2 +- [X] is_integer/1 +- [X] is_list/1 +- [X] is_map/1 +- [X] is_number/1 +- [X] is_pid/1 +- [X] is_port/1 +- [X] is_reference/1 +- [X] is_tuple/1 +- [X] length/1 +- [ ] macro_exported?/3 +- [ ] make_ref/0 +- [X] map_size/1 +- [X] max/2 +- [X] min/2 +- [ ] node/0 +- [ ] node/1 +- [ ] not/1 +- [ ] pop_in/2 +- [ ] put_elem/3 +- [ ] put_in/3 +- [X] rem/2 +- [X] round/1 +- [ ] self/0 +- [ ] send/2 +- [ ] spawn/1 +- [ ] spawn/3 +- [ ] spawn_link/1 +- [ ] spawn_link/3 +- [ ] spawn_monitor/1 +- [ ] spawn_monitor/3 +- [ ] struct/1 +- [ ] struct/2 +- [ ] struct!/1 +- [ ] struct!/2 +- [X] throw/1 +- [X] tl/1 +- [X] trunc/1 +- [X] tuple_size/1 +- [ ] update_in/3 +- [X] !/1 +- [X] &&/2 +- [X] ../2 +- [X] <>/2 +- [X] @/1 +- [ ] alias!/1 +- [X] and/2 +- [ ] binding/0 +- [ ] binding/1 +- [X] def/1 +- [X] def/2 +- [X] defdelegate/2 +- [X] defexception/1 +- [X] defimpl/2 +- [X] defimpl/3 +- [X] defmacro/1 +- [X] defmacro/2 +- [ ] defmacrop/1 +- [ ] defmacrop/2 +- [X] defmodule/2 +- [X] defoverridable/1 +- [X] defp/1 +- [X] defp/2 +- [X] defprotocol/2 +- [X] defstruct/1 +- [ ] destructure/2 +- [ ] get_and_update_in/2 +- [X] if/2 +- [X] in/2 +- [X] is_nil/1 +- [X] match?/2 +- [X] or/2 +- [ ] pop_in/1 +- [ ] put_in/2 +- [ ] raise/1 +- [ ] raise/2 +- [ ] reraise/2 +- [ ] reraise/3 +- [ ] sigil_C/2 +- [ ] sigil_D/2 +- [ ] sigil_N/2 +- [ ] sigil_R/2 +- [ ] sigil_S/2 +- [ ] sigil_T/2 +- [ ] sigil_W/2 +- [ ] sigil_c/2 +- [X] sigil_r/2 +- [ ] sigil_s/2 +- [ ] sigil_w/2 +- [ ] to_char_list/1 +- [ ] to_charlist/1 +- [X] to_string/1 +- [X] unless/2 +- [ ] update_in/2 +- [X] use/1 +- [X] use/2 +- [ ] var!/1 +- [ ] var!/2 +- [X] |>/2 +- [X] ||/2 +## Kernel.ParallelCompiler +- [ ] files/1 +- [ ] files/2 +- [ ] files_to_path/2 +- [ ] files_to_path/3 +## File.Stream +- [ ] __build__/3 +- [ ] __struct__/0 +- [ ] __struct__/1 +## Inspect.List +- [ ] __impl__/1 +- [ ] inspect/2 +- [ ] keyword/2 +- [ ] keyword?/1 +- [ ] printable?/1 +## Path.Wildcard +- [ ] list_dir/1 +- [ ] read_link_info/1 +## SyntaxError +- [ ] __struct__/0 +- [ ] __struct__/1 +- [ ] exception/1 +- [ ] message/1 +## List.Chars.List +- [ ] __impl__/1 +- [ ] to_charlist/1 +## CaseClauseError +- [ ] __struct__/0 +- [ ] __struct__/1 +- [ ] exception/1 +- [ ] message/1 +## Path +- [ ] absname/1 +- [ ] absname/2 +- [ ] basename/1 +- [ ] basename/2 +- [ ] dirname/1 +- [ ] expand/1 +- [ ] expand/2 +- [ ] extname/1 +- [ ] join/1 +- [ ] join/2 +- [ ] relative/1 +- [ ] relative_to/2 +- [ ] relative_to_cwd/1 +- [ ] rootname/1 +- [ ] rootname/2 +- [ ] split/1 +- [ ] type/1 +- [ ] wildcard/1 +- [ ] wildcard/2 +## UnicodeConversionError +- [ ] __struct__/0 +- [ ] __struct__/1 +- [ ] exception/1 +- [ ] message/1 +## String.Chars.BitString +- [X] __impl__/1 +- [X] to_string/1 +## DateTime +- [ ] __struct__/0 +- [ ] __struct__/1 +- [ ] compare/2 +- [ ] from_iso8601/1 +- [ ] from_naive/2 +- [ ] from_naive!/2 +- [ ] from_unix/1 +- [ ] from_unix/2 +- [ ] from_unix!/1 +- [ ] from_unix!/2 +- [ ] to_date/1 +- [ ] to_iso8601/1 +- [ ] to_naive/1 +- [ ] to_string/1 +- [ ] to_time/1 +- [ ] to_unix/1 +- [ ] to_unix/2 +- [ ] utc_now/0 +## String.Chars.Float +- [X] __impl__/1 +- [X] to_string/1 +## Collectable.File.Stream +- [ ] __impl__/1 +- [ ] into/1 +## String.Chars.URI +- [ ] __impl__/1 +- [ ] to_string/1 +## CompileError +- [ ] __struct__/0 +- [ ] __struct__/1 +- [ ] exception/1 +- [ ] message/1 +## File +- [ ] cd/1 +- [ ] cd!/1 +- [ ] cd!/2 +- [ ] chgrp/2 +- [ ] chgrp!/2 +- [ ] chmod/2 +- [ ] chmod!/2 +- [ ] chown/2 +- [ ] chown!/2 +- [ ] close/1 +- [ ] copy/2 +- [ ] copy/3 +- [ ] copy!/2 +- [ ] copy!/3 +- [ ] cp/2 +- [ ] cp/3 +- [ ] cp!/2 +- [ ] cp!/3 +- [ ] cp_r/2 +- [ ] cp_r/3 +- [ ] cp_r!/2 +- [ ] cp_r!/3 +- [ ] cwd/0 +- [ ] cwd!/0 +- [ ] dir?/1 +- [ ] exists?/1 +- [ ] ln_s/2 +- [ ] ls/0 +- [ ] ls/1 +- [ ] ls!/0 +- [ ] ls!/1 +- [ ] lstat/1 +- [ ] lstat/2 +- [ ] lstat!/1 +- [ ] lstat!/2 +- [ ] mkdir/1 +- [ ] mkdir!/1 +- [ ] mkdir_p/1 +- [ ] mkdir_p!/1 +- [ ] open/1 +- [ ] open/2 +- [ ] open/3 +- [ ] open!/1 +- [ ] open!/2 +- [ ] open!/3 +- [ ] read/1 +- [ ] read!/1 +- [ ] regular?/1 +- [ ] rename/2 +- [ ] rm/1 +- [ ] rm!/1 +- [ ] rm_rf/1 +- [ ] rm_rf!/1 +- [ ] rmdir/1 +- [ ] rmdir!/1 +- [ ] stat/1 +- [ ] stat/2 +- [ ] stat!/1 +- [ ] stat!/2 +- [ ] stream!/1 +- [ ] stream!/2 +- [ ] stream!/3 +- [ ] touch/1 +- [ ] touch/2 +- [ ] touch!/1 +- [ ] touch!/2 +- [ ] write/2 +- [ ] write/3 +- [ ] write!/2 +- [ ] write!/3 +- [ ] write_stat/2 +- [ ] write_stat/3 +- [ ] write_stat!/2 +- [ ] write_stat!/3 +## Dict +- [ ] delete/2 +- [ ] drop/2 +- [ ] empty/1 +- [ ] equal?/2 +- [ ] fetch/2 +- [ ] fetch!/2 +- [ ] get/2 +- [ ] get/3 +- [ ] get_and_update/3 +- [ ] get_lazy/3 +- [ ] has_key?/2 +- [ ] keys/1 +- [ ] merge/2 +- [ ] merge/3 +- [ ] pop/2 +- [ ] pop/3 +- [ ] pop_lazy/3 +- [ ] put/3 +- [ ] put_new/3 +- [ ] put_new_lazy/3 +- [ ] size/1 +- [ ] split/2 +- [ ] take/2 +- [ ] to_list/1 +- [ ] update/4 +- [ ] update!/3 +- [ ] values/1 +- [ ] __using__/1 +## Version.Requirement +- [ ] __struct__/0 +- [ ] __struct__/1 +## String +- [X] at/2 +- [X] capitalize/1 +- [ ] chunk/2 +- [X] codepoints/1 +- [X] contains?/2 +- [X] downcase/1 +- [X] duplicate/2 +- [X] ends_with?/2 +- [ ] equivalent?/2 +- [X] first/1 +- [X] graphemes/1 +- [ ] jaro_distance/2 +- [X] last/1 +- [X] length/1 +- [ ] ljust/2 +- [ ] ljust/3 +- [ ] lstrip/1 +- [ ] lstrip/2 +- [X] match?/2 +- [ ] myers_difference/2 +- [X] next_codepoint/1 +- [X] next_grapheme/1 +- [ ] next_grapheme_size/1 +- [ ] normalize/2 +- [ ] pad_leading/2 +- [ ] pad_leading/3 +- [ ] pad_trailing/2 +- [ ] pad_trailing/3 +- [ ] printable?/1 +- [ ] replace/3 +- [ ] replace/4 +- [ ] replace_leading/3 +- [ ] replace_prefix/3 +- [ ] replace_suffix/3 +- [ ] replace_trailing/3 +- [X] reverse/1 +- [ ] rjust/2 +- [ ] rjust/3 +- [ ] rstrip/1 +- [ ] rstrip/2 +- [ ] slice/2 +- [ ] slice/3 +- [X] split/1 +- [X] split/2 +- [X] split/3 +- [ ] split_at/2 +- [ ] splitter/2 +- [ ] splitter/3 +- [X] starts_with?/2 +- [ ] strip/1 +- [ ] strip/2 +- [X] to_atom/1 +- [X] to_char_list/1 +- [ ] to_charlist/1 +- [X] to_existing_atom/1 +- [X] to_float/1 +- [X] to_integer/1 +- [X] to_integer/2 +- [ ] trim/1 +- [ ] trim/2 +- [ ] trim_leading/1 +- [ ] trim_leading/2 +- [ ] trim_trailing/1 +- [ ] trim_trailing/2 +- [X] upcase/1 +- [ ] valid?/1 +- [X] valid_character?/1 +## Record.Extractor +- [ ] extract/2 +- [ ] extract_all/1 +## Collectable.HashSet +- [ ] __impl__/1 +- [ ] into/1 +## String.Unicode +- [ ] codepoints/1 +- [ ] graphemes/1 +- [ ] length/1 +- [ ] next_codepoint/1 +- [ ] next_grapheme_size/1 +- [ ] split_at/2 +- [ ] version/0 +## ErlangError +- [ ] __struct__/0 +- [ ] __struct__/1 +- [ ] exception/1 +- [ ] message/1 +- [ ] normalize/2 +## File.Stat +- [ ] __struct__/0 +- [ ] __struct__/1 +- [ ] from_record/1 +- [ ] to_record/1 +## Inspect.Version +- [ ] __impl__/1 +- [ ] inspect/2 +## RuntimeError +- [X] __struct__/0 +- [X] __struct__/1 +- [X] exception/1 +- [X] message/1 +## Range +- [X] __struct__/0 +- [X] __struct__/1 +- [X] new/2 +- [X] range?/1 +## Exception +- [ ] exception?/1 +- [ ] format/2 +- [ ] format/3 +- [ ] format_banner/2 +- [ ] format_banner/3 +- [ ] format_exit/1 +- [ ] format_fa/2 +- [ ] format_file_line/2 +- [ ] format_file_line/3 +- [ ] format_mfa/3 +- [ ] format_stacktrace/0 +- [ ] format_stacktrace/1 +- [ ] format_stacktrace_entry/1 +- [ ] message/1 +- [ ] normalize/2 +- [ ] normalize/3 +## Inspect.Function +- [ ] __impl__/1 +- [ ] inspect/2 +## Enumerable.GenEvent.Stream +- [ ] __impl__/1 +- [ ] count/1 +- [ ] member?/2 +- [ ] reduce/3 +## Enum.OutOfBoundsError +- [X] __struct__/0 +- [X] __struct__/1 +- [X] exception/1 +- [X] message/1 +## Enumerable.Range +- [ ] __impl__/1 +- [ ] count/1 +- [ ] member?/2 +- [ ] reduce/3 +## Date +- [ ] __struct__/0 +- [ ] __struct__/1 +- [ ] compare/2 +- [ ] day_of_week/1 +- [ ] days_in_month/1 +- [ ] from_erl/1 +- [ ] from_erl!/1 +- [ ] from_iso8601/1 +- [ ] from_iso8601!/1 +- [ ] leap_year?/1 +- [ ] new/3 +- [ ] to_erl/1 +- [ ] to_iso8601/1 +- [ ] to_string/1 +- [ ] utc_today/0 +## Inspect.Time +- [ ] __impl__/1 +- [ ] inspect/2 +## String.Casing +- [ ] downcase/1 +- [ ] titlecase_once/1 +- [ ] upcase/1 +## Regex.CompileError +- [ ] __struct__/0 +- [ ] __struct__/1 +- [ ] exception/1 +- [ ] message/1 +## Supervisor.Spec +- [ ] supervise/2 +- [ ] supervisor/2 +- [ ] supervisor/3 +- [ ] worker/2 +- [ ] worker/3 +## Collectable.MapSet +- [ ] __impl__/1 +- [ ] into/1 +## StringIO +- [ ] close/1 +- [ ] code_change/3 +- [ ] contents/1 +- [ ] flush/1 +- [ ] handle_call/3 +- [ ] handle_cast/2 +- [ ] handle_info/2 +- [ ] init/1 +- [ ] open/1 +- [ ] open/2 +- [ ] terminate/2 +## Inspect.Port +- [ ] __impl__/1 +- [ ] inspect/2 +## GenEvent.Stream +- [ ] __struct__/0 +- [ ] __struct__/1 +- [ ] code_change/3 +- [ ] handle_call/2 +- [ ] handle_event/2 +- [ ] handle_info/2 +- [ ] init/1 +- [ ] terminate/2 +## Protocol.UndefinedError +- [ ] __struct__/0 +- [ ] __struct__/1 +- [ ] exception/1 +- [ ] message/1 +## BadFunctionError +- [ ] __struct__/0 +- [ ] __struct__/1 +- [ ] exception/1 +- [ ] message/1 +## Time +- [ ] __struct__/0 +- [ ] __struct__/1 +- [ ] compare/2 +- [ ] from_erl/1 +- [ ] from_erl/2 +- [ ] from_erl!/1 +- [ ] from_erl!/2 +- [ ] from_iso8601/1 +- [ ] from_iso8601!/1 +- [ ] new/3 +- [ ] new/4 +- [ ] to_erl/1 +- [ ] to_iso8601/1 +- [ ] to_string/1 +- [ ] utc_now/0 +## List.Chars.BitString +- [ ] __impl__/1 +- [ ] to_charlist/1 +## Registry +- [ ] dispatch/3 +- [ ] keys/2 +- [ ] lookup/2 +- [ ] match/3 +- [ ] meta/2 +- [ ] put_meta/3 +- [ ] register/3 +- [ ] register_name/2 +- [ ] send/2 +- [ ] start_link/2 +- [ ] start_link/3 +- [ ] unregister/2 +- [ ] unregister_name/1 +- [ ] update_value/3 +- [ ] whereis_name/1 +## List.Chars.Float +- [ ] __impl__/1 +- [ ] to_charlist/1 +## Code.LoadError +- [ ] __struct__/0 +- [ ] __struct__/1 +- [ ] exception/1 +- [ ] message/1 +## ArithmeticError +- [ ] __struct__/0 +- [ ] __struct__/1 +- [ ] exception/1 +- [ ] message/1 +## String.Chars.List +- [X] __impl__/1 +- [X] to_string/1 +## Inspect.BitString +- [ ] __impl__/1 +- [ ] escape/2 +- [ ] escape_char/1 +- [ ] inspect/2 +## Inspect.HashSet +- [ ] __impl__/1 +- [ ] inspect/2 +## String.Chars.DateTime +- [ ] __impl__/1 +- [ ] to_string/1 +## Inspect.Map +- [ ] __impl__/1 +- [ ] inspect/2 +- [ ] inspect/3 +## HashDict +- [ ] __struct__/0 +- [ ] __struct__/1 +- [ ] delete/2 +- [ ] dict_delete/2 +- [ ] drop/2 +- [ ] equal?/2 +- [ ] fetch/2 +- [ ] fetch!/2 +- [ ] get/2 +- [ ] get/3 +- [ ] get_and_update/3 +- [ ] get_lazy/3 +- [ ] has_key?/2 +- [ ] keys/1 +- [ ] merge/2 +- [ ] merge/3 +- [ ] new/0 +- [ ] pop/2 +- [ ] pop/3 +- [ ] pop_lazy/3 +- [ ] put/3 +- [ ] put_new/3 +- [ ] put_new_lazy/3 +- [ ] reduce/3 +- [ ] size/1 +- [ ] split/2 +- [ ] take/2 +- [ ] to_list/1 +- [ ] update/4 +- [ ] update!/3 +- [ ] values/1 +## NaiveDateTime +- [ ] __struct__/0 +- [ ] __struct__/1 +- [ ] add/2 +- [ ] add/3 +- [ ] compare/2 +- [ ] diff/2 +- [ ] diff/3 +- [ ] from_erl/1 +- [ ] from_erl/2 +- [ ] from_erl!/1 +- [ ] from_erl!/2 +- [ ] from_iso8601/1 +- [ ] from_iso8601!/1 +- [ ] new/2 +- [ ] new/6 +- [ ] new/7 +- [ ] to_date/1 +- [ ] to_erl/1 +- [ ] to_iso8601/1 +- [ ] to_string/1 +- [ ] to_time/1 +- [ ] utc_now/0 +## IO.ANSI +- [ ] black/0 +- [ ] black_background/0 +- [ ] blink_off/0 +- [ ] blink_rapid/0 +- [ ] blink_slow/0 +- [ ] blue/0 +- [ ] blue_background/0 +- [ ] bright/0 +- [ ] clear/0 +- [ ] clear_line/0 +- [ ] color/1 +- [ ] color/3 +- [ ] color_background/1 +- [ ] color_background/3 +- [ ] conceal/0 +- [ ] crossed_out/0 +- [ ] cyan/0 +- [ ] cyan_background/0 +- [ ] default_background/0 +- [ ] default_color/0 +- [ ] enabled?/0 +- [ ] encircled/0 +- [ ] faint/0 +- [ ] font_1/0 +- [ ] font_2/0 +- [ ] font_3/0 +- [ ] font_4/0 +- [ ] font_5/0 +- [ ] font_6/0 +- [ ] font_7/0 +- [ ] font_8/0 +- [ ] font_9/0 +- [ ] format/1 +- [ ] format/2 +- [ ] format_fragment/1 +- [ ] format_fragment/2 +- [ ] framed/0 +- [ ] green/0 +- [ ] green_background/0 +- [ ] home/0 +- [ ] inverse/0 +- [ ] inverse_off/0 +- [ ] italic/0 +- [ ] light_black/0 +- [ ] light_black_background/0 +- [ ] light_blue/0 +- [ ] light_blue_background/0 +- [ ] light_cyan/0 +- [ ] light_cyan_background/0 +- [ ] light_green/0 +- [ ] light_green_background/0 +- [ ] light_magenta/0 +- [ ] light_magenta_background/0 +- [ ] light_red/0 +- [ ] light_red_background/0 +- [ ] light_white/0 +- [ ] light_white_background/0 +- [ ] light_yellow/0 +- [ ] light_yellow_background/0 +- [ ] magenta/0 +- [ ] magenta_background/0 +- [ ] no_underline/0 +- [ ] normal/0 +- [ ] not_framed_encircled/0 +- [ ] not_italic/0 +- [ ] not_overlined/0 +- [ ] overlined/0 +- [ ] primary_font/0 +- [ ] red/0 +- [ ] red_background/0 +- [ ] reset/0 +- [ ] reverse/0 +- [ ] reverse_off/0 +- [ ] underline/0 +- [ ] white/0 +- [ ] white_background/0 +- [ ] yellow/0 +- [ ] yellow_background/0 +## Module +- [ ] add_doc/5 +- [ ] add_doc/6 +- [ ] compile_doc/6 +- [ ] concat/1 +- [ ] concat/2 +- [ ] create/3 +- [ ] defines?/2 +- [ ] defines?/3 +- [ ] definitions_in/1 +- [ ] definitions_in/2 +- [ ] delete_attribute/2 +- [ ] eval_quoted/2 +- [ ] eval_quoted/3 +- [ ] eval_quoted/4 +- [ ] get_attribute/2 +- [ ] get_attribute/3 +- [ ] make_overridable/2 +- [ ] open?/1 +- [ ] overridable?/2 +- [ ] put_attribute/3 +- [ ] put_attribute/5 +- [ ] register_attribute/3 +- [ ] safe_concat/1 +- [ ] safe_concat/2 +- [ ] split/1 +- [ ] store_typespec/3 +## IO +- [ ] binread/1 +- [ ] binread/2 +- [ ] binstream/2 +- [ ] binwrite/1 +- [ ] binwrite/2 +- [ ] chardata_to_string/1 +- [ ] each_binstream/2 +- [ ] each_stream/2 +- [ ] getn/1 +- [ ] getn/2 +- [ ] getn/3 +- [ ] gets/1 +- [ ] gets/2 +- [X] inspect/1 +- [X] inspect/2 +- [ ] inspect/3 +- [ ] iodata_length/1 +- [ ] iodata_to_binary/1 +- [X] puts/1 +- [X] puts/2 +- [ ] read/1 +- [ ] read/2 +- [ ] stream/2 +- [X] warn/1 +- [ ] warn/2 +- [ ] write/1 +- [ ] write/2 +## MatchError +- [ ] __struct__/0 +- [ ] __struct__/1 +- [ ] exception/1 +- [ ] message/1 +## Enumerable.HashSet +- [ ] __impl__/1 +- [ ] count/1 +- [ ] member?/2 +- [ ] reduce/3 +## Enumerable.HashDict +- [ ] __impl__/1 +- [ ] count/1 +- [ ] member?/2 +- [ ] reduce/3 +## Agent +- [ ] cast/2 +- [ ] cast/4 +- [X] get/2 +- [ ] get/3 +- [ ] get/4 +- [ ] get/5 +- [X] get_and_update/2 +- [ ] get_and_update/3 +- [ ] get_and_update/4 +- [ ] get_and_update/5 +- [X] start/1 +- [X] start/2 +- [ ] start/3 +- [ ] start/4 +- [X] start_link/1 +- [X] start_link/2 +- [ ] start_link/3 +- [ ] start_link/4 +- [X] stop/1 +- [ ] stop/2 +- [ ] stop/3 +- [X] update/2 +- [ ] update/3 +- [ ] update/4 +- [ ] update/5 +## String.Chars.Version +- [ ] __impl__/1 +- [ ] to_string/1 +## System +- [ ] argv/0 +- [ ] argv/1 +- [ ] at_exit/1 +- [ ] build_info/0 +- [ ] cmd/2 +- [ ] cmd/3 +- [ ] compiled_endianness/0 +- [ ] convert_time_unit/3 +- [ ] cwd/0 +- [ ] cwd!/0 +- [ ] delete_env/1 +- [ ] endianness/0 +- [ ] find_executable/1 +- [ ] get_env/0 +- [ ] get_env/1 +- [ ] get_pid/0 +- [ ] halt/0 +- [ ] halt/1 +- [ ] monotonic_time/0 +- [ ] monotonic_time/1 +- [ ] os_time/0 +- [ ] os_time/1 +- [ ] otp_release/0 +- [ ] put_env/1 +- [ ] put_env/2 +- [ ] schedulers/0 +- [ ] schedulers_online/0 +- [ ] stacktrace/0 +- [ ] system_time/0 +- [ ] system_time/1 +- [ ] time_offset/0 +- [ ] time_offset/1 +- [ ] tmp_dir/0 +- [ ] tmp_dir!/0 +- [ ] unique_integer/0 +- [ ] unique_integer/1 +- [ ] user_home/0 +- [ ] user_home!/0 +- [ ] version/0 +## Inspect.Tuple +- [ ] __impl__/1 +- [ ] inspect/2 +## Collectable.BitString +- [X] __impl__/1 +- [X] into/1 +## Enumerable.Map +- [X] __impl__/1 +- [X] count/1 +- [X] member?/2 +- [X] reduce/3 +## Enum.EmptyError +- [ ] __struct__/0 +- [ ] __struct__/1 +- [ ] exception/1 +- [ ] message/1 +## GenEvent +- [ ] ack_notify/2 +- [ ] add_handler/3 +- [ ] add_mon_handler/3 +- [ ] call/3 +- [ ] call/4 +- [ ] format_status/2 +- [ ] init_hib/4 +- [ ] init_it/6 +- [ ] notify/2 +- [ ] remove_handler/3 +- [ ] start/0 +- [ ] start/1 +- [ ] start_link/0 +- [ ] start_link/1 +- [ ] stop/1 +- [ ] stop/2 +- [ ] stop/3 +- [ ] stream/1 +- [ ] stream/2 +- [ ] swap_handler/5 +- [ ] swap_mon_handler/5 +- [ ] sync_notify/2 +- [ ] system_code_change/4 +- [ ] system_continue/3 +- [ ] system_get_state/1 +- [ ] system_replace_state/2 +- [ ] system_terminate/4 +- [ ] which_handlers/1 +- [ ] __using__/1 +## Inspect.Error +- [ ] __struct__/0 +- [ ] __struct__/1 +- [ ] exception/1 +- [ ] message/1 +## Enumerable.List +- [X] __impl__/1 +- [X] count/1 +- [X] member?/2 +- [X] reduce/3 +## OptionParser.ParseError +- [ ] __struct__/0 +- [ ] __struct__/1 +- [ ] exception/1 +- [ ] message/1 +## Map +- [X] delete/2 +- [X] drop/2 +- [X] equal?/2 +- [X] fetch/2 +- [X] fetch!/2 +- [X] from_struct/1 +- [X] get/2 +- [X] get/3 +- [X] get_and_update/3 +- [ ] get_and_update!/3 +- [X] get_lazy/3 +- [X] has_key?/2 +- [X] keys/1 +- [X] merge/2 +- [ ] merge/3 +- [X] new/0 +- [ ] new/1 +- [ ] new/2 +- [X] pop/2 +- [X] pop/3 +- [X] pop_lazy/3 +- [X] put/3 +- [X] put_new/3 +- [X] put_new_lazy/3 +- [X] size/1 +- [X] split/2 +- [X] take/2 +- [X] to_list/1 +- [X] update/4 +- [X] update!/3 +- [X] values/1 +## OptionParser +- [ ] get_option_key/1 +- [ ] next/1 +- [ ] next/2 +- [ ] parse/1 +- [ ] parse/2 +- [ ] parse!/1 +- [ ] parse!/2 +- [ ] parse_head/1 +- [ ] parse_head/2 +- [ ] parse_head!/1 +- [ ] parse_head!/2 +- [ ] split/1 +- [ ] to_argv/1 +- [ ] to_argv/2 +## Kernel.ErrorHandler +- [ ] ensure_compiled/2 +- [ ] ensure_loaded/1 +- [ ] undefined_function/3 +- [ ] undefined_lambda/3 +## List.Chars.Integer +- [ ] __impl__/1 +- [ ] to_charlist/1 +## HashSet +- [ ] __struct__/0 +- [ ] __struct__/1 +- [ ] delete/2 +- [ ] difference/2 +- [ ] disjoint?/2 +- [ ] equal?/2 +- [ ] intersection/2 +- [ ] member?/2 +- [ ] new/0 +- [ ] put/2 +- [ ] reduce/3 +- [ ] size/1 +- [ ] subset?/2 +- [ ] to_list/1 +- [ ] union/2 +## Inspect.Date +- [ ] __impl__/1 +- [ ] inspect/2 +## Code +- [ ] append_path/1 +- [ ] available_compiler_options/0 +- [ ] compile_quoted/1 +- [ ] compile_quoted/2 +- [ ] compile_string/1 +- [ ] compile_string/2 +- [ ] compiler_options/0 +- [ ] compiler_options/1 +- [ ] delete_path/1 +- [ ] ensure_compiled/1 +- [ ] ensure_compiled?/1 +- [ ] ensure_loaded/1 +- [ ] ensure_loaded?/1 +- [ ] eval_file/1 +- [ ] eval_file/2 +- [ ] eval_quoted/1 +- [ ] eval_quoted/2 +- [ ] eval_quoted/3 +- [ ] eval_string/1 +- [ ] eval_string/2 +- [ ] eval_string/3 +- [ ] get_docs/2 +- [ ] load_file/1 +- [ ] load_file/2 +- [ ] loaded_files/0 +- [ ] prepend_path/1 +- [ ] require_file/1 +- [ ] require_file/2 +- [ ] string_to_quoted/1 +- [ ] string_to_quoted/2 +- [ ] string_to_quoted!/1 +- [ ] string_to_quoted!/2 +- [ ] unload_files/1 +## Kernel.SpecialForms +- [X] %/2 +- [X] %{}/1 +- [X] &/1 +- [X] ./2 +- [X] ::/2 +- [X] <<>>/1 +- [X] =/2 +- [X] ^/1 +- [X] __CALLER__/0 +- [X] __DIR__/0 +- [X] __ENV__/0 +- [X] __MODULE__/0 +- [X] __aliases__/1 +- [X] __block__/1 +- [X] alias/2 +- [X] case/2 +- [X] cond/1 +- [X] fn/1 +- [X] for/1 +- [X] import/2 +- [X] quote/2 +- [ ] receive/1 +- [X] require/2 +- [X] super/1 +- [X] try/1 +- [X] unquote/1 +- [X] unquote_splicing/1 +- [X] with/1 +- [X] {}/1 +## Tuple +- [X] append/2 +- [X] delete_at/2 +- [X] duplicate/2 +- [X] insert_at/3 +- [X] to_list/1 +## SystemLimitError +- [ ] __struct__/0 +- [ ] __struct__/1 +- [ ] exception/1 +- [ ] message/1 +## Bitwise +- [X] &&&/2 +- [X] <<>>/2 +- [X] ^^^/2 +- [ ] __using__/1 +- [X] band/2 +- [X] bnot/1 +- [X] bor/2 +- [X] bsl/2 +- [X] bsr/2 +- [X] bxor/2 +- [X] |||/2 +- [X] ~~~/1 +## String.Chars.Integer +- [X] __impl__/1 +- [X] to_string/1 +## Inspect.Reference +- [ ] __impl__/1 +- [ ] inspect/2 +## IO.StreamError +- [ ] __struct__/0 +- [ ] __struct__/1 +- [ ] exception/1 +- [ ] message/1 +## Process +- [ ] alive?/1 +- [ ] cancel_timer/1 +- [ ] delete/1 +- [ ] demonitor/1 +- [ ] demonitor/2 +- [ ] exit/2 +- [ ] flag/2 +- [ ] flag/3 +- [ ] get/0 +- [ ] get/1 +- [ ] get/2 +- [ ] get_keys/0 +- [ ] get_keys/1 +- [ ] group_leader/0 +- [ ] group_leader/2 +- [ ] hibernate/3 +- [ ] info/1 +- [ ] info/2 +- [ ] link/1 +- [ ] list/0 +- [ ] monitor/1 +- [ ] put/2 +- [ ] read_timer/1 +- [ ] register/2 +- [ ] registered/0 +- [ ] send/3 +- [ ] send_after/3 +- [ ] send_after/4 +- [ ] sleep/1 +- [ ] spawn/2 +- [ ] spawn/4 +- [ ] unlink/1 +- [ ] unregister/1 +- [ ] whereis/1 +## Protocol +- [ ] __builtin__/0 +- [ ] __derive__/3 +- [ ] __ensure_defimpl__/3 +- [ ] __functions_spec__/1 +- [ ] __impl__/2 +- [ ] __protocol__/2 +- [ ] __spec__?/3 +- [ ] assert_impl!/2 +- [ ] assert_protocol!/1 +- [ ] consolidate/2 +- [ ] consolidated?/1 +- [ ] extract_impls/2 +- [ ] extract_protocols/1 +- [ ] def/1 +- [ ] derive/2 +- [ ] derive/3 +## UndefinedFunctionError +- [ ] __struct__/0 +- [ ] __struct__/1 +- [ ] exception/1 +- [ ] message/1 +## Version.InvalidVersionError +- [ ] __struct__/0 +- [ ] __struct__/1 +- [ ] exception/1 +- [ ] message/1 +## Task +- [ ] __struct__/0 +- [ ] __struct__/1 +- [ ] async/1 +- [ ] async/3 +- [ ] async_stream/2 +- [ ] async_stream/3 +- [ ] async_stream/4 +- [ ] async_stream/5 +- [ ] await/1 +- [ ] await/2 +- [ ] find/2 +- [ ] shutdown/1 +- [ ] shutdown/2 +- [ ] start/1 +- [ ] start/3 +- [ ] start_link/1 +- [ ] start_link/3 +- [ ] yield/1 +- [ ] yield/2 +- [ ] yield_many/1 +- [ ] yield_many/2 +## Float +- [ ] ceil/1 +- [ ] ceil/2 +- [ ] floor/1 +- [ ] floor/2 +- [ ] parse/1 +- [ ] ratio/1 +- [ ] round/1 +- [ ] round/2 +- [ ] to_char_list/1 +- [ ] to_char_list/2 +- [ ] to_charlist/1 +- [ ] to_string/1 +- [ ] to_string/2 +## Supervisor +- [ ] count_children/1 +- [ ] delete_child/2 +- [ ] restart_child/2 +- [ ] start_child/2 +- [ ] start_link/2 +- [ ] start_link/3 +- [ ] stop/1 +- [ ] stop/2 +- [ ] stop/3 +- [ ] terminate_child/2 +- [ ] which_children/1 +- [ ] __using__/1 +## Enumerable +- [X] __protocol__/1 +- [X] count/1 +- [X] impl_for/1 +- [X] impl_for!/1 +- [X] member?/2 +- [X] reduce/3 +## Enum +- [X] all?/1 +- [X] all?/2 +- [X] any?/1 +- [X] any?/2 +- [X] at/2 +- [X] at/3 +- [ ] chunk/2 +- [ ] chunk/3 +- [ ] chunk/4 +- [ ] chunk_by/2 +- [X] concat/1 +- [X] concat/2 +- [X] count/1 +- [X] count/2 +- [ ] dedup/1 +- [ ] dedup_by/2 +- [X] drop/2 +- [X] drop_every/2 +- [X] drop_while/2 +- [X] each/2 +- [X] empty?/1 +- [X] fetch/2 +- [X] fetch!/2 +- [X] filter/2 +- [X] filter_map/3 +- [X] find/2 +- [X] find/3 +- [ ] find_index/2 +- [ ] find_value/2 +- [ ] find_value/3 +- [ ] flat_map/2 +- [ ] flat_map_reduce/3 +- [ ] group_by/2 +- [ ] group_by/3 +- [ ] intersperse/2 +- [X] into/2 +- [X] into/3 +- [ ] join/1 +- [ ] join/2 +- [X] map/2 +- [ ] map_every/3 +- [ ] map_join/2 +- [ ] map_join/3 +- [X] map_reduce/3 +- [ ] max/1 +- [ ] max/2 +- [ ] max_by/2 +- [ ] max_by/3 +- [X] member?/2 +- [ ] min/1 +- [ ] min/2 +- [ ] min_by/2 +- [ ] min_by/3 +- [ ] min_max/1 +- [ ] min_max/2 +- [ ] min_max_by/2 +- [ ] min_max_by/3 +- [ ] partition/2 +- [ ] random/1 +- [X] reduce/2 +- [X] reduce/3 +- [ ] reduce_while/3 +- [ ] reject/2 +- [X] reverse/1 +- [X] reverse/2 +- [ ] reverse_slice/3 +- [ ] scan/2 +- [ ] scan/3 +- [ ] shuffle/1 +- [ ] slice/2 +- [ ] slice/3 +- [ ] sort/1 +- [ ] sort/2 +- [ ] sort_by/2 +- [ ] sort_by/3 +- [ ] split/2 +- [ ] split_while/2 +- [ ] split_with/2 +- [ ] sum/1 +- [X] take/2 +- [X] take_every/2 +- [ ] take_random/2 +- [X] take_while/2 +- [X] to_list/1 +- [ ] uniq/1 +- [ ] uniq/2 +- [ ] uniq_by/2 +- [ ] unzip/1 +- [ ] with_index/1 +- [ ] with_index/2 +- [ ] zip/1 +- [ ] zip/2 +## Keyword +- [ ] delete/2 +- [ ] delete/3 +- [ ] delete_first/2 +- [ ] drop/2 +- [ ] equal?/2 +- [ ] fetch/2 +- [ ] fetch!/2 +- [X] get/2 +- [X] get/3 +- [ ] get_and_update/3 +- [ ] get_and_update!/3 +- [ ] get_lazy/3 +- [ ] get_values/2 +- [X] has_key?/2 +- [ ] keys/1 +- [ ] keyword?/1 +- [ ] merge/2 +- [ ] merge/3 +- [X] new/0 +- [ ] new/1 +- [ ] new/2 +- [ ] pop/2 +- [ ] pop/3 +- [ ] pop_first/2 +- [ ] pop_first/3 +- [ ] pop_lazy/3 +- [ ] put/3 +- [ ] put_new/3 +- [ ] put_new_lazy/3 +- [ ] size/1 +- [ ] split/2 +- [ ] take/2 +- [ ] to_list/1 +- [ ] update/4 +- [ ] update!/3 +- [ ] values/1 +## Collectable.HashDict +- [ ] __impl__/1 +- [ ] into/1 +## Enumerable.File.Stream +- [ ] __impl__/1 +- [ ] count/1 +- [ ] member?/2 +- [ ] reduce/3 +## Access +- [ ] all/0 +- [ ] at/1 +- [ ] elem/1 +- [ ] fetch/2 +- [ ] get/2 +- [ ] get/3 +- [ ] get_and_update/3 +- [ ] key/1 +- [ ] key/2 +- [ ] key!/1 +- [ ] pop/2 +## IO.Stream +- [ ] __build__/3 +- [ ] __struct__/0 +- [ ] __struct__/1 +## Enumerable.Stream +- [ ] __impl__/1 +- [ ] count/1 +- [ ] member?/2 +- [ ] reduce/3 +## Stream +- [ ] __struct__/0 +- [ ] __struct__/1 +- [ ] chunk/2 +- [ ] chunk/3 +- [ ] chunk/4 +- [ ] chunk_by/2 +- [ ] concat/1 +- [ ] concat/2 +- [ ] cycle/1 +- [ ] dedup/1 +- [ ] dedup_by/2 +- [ ] drop/2 +- [ ] drop_every/2 +- [ ] drop_while/2 +- [ ] each/2 +- [ ] filter/2 +- [ ] filter_map/3 +- [ ] flat_map/2 +- [ ] interval/1 +- [ ] into/2 +- [ ] into/3 +- [ ] iterate/2 +- [ ] map/2 +- [ ] map_every/3 +- [ ] reject/2 +- [ ] repeatedly/1 +- [ ] resource/3 +- [ ] run/1 +- [ ] scan/2 +- [ ] scan/3 +- [ ] take/2 +- [ ] take_every/2 +- [ ] take_while/2 +- [ ] timer/1 +- [ ] transform/3 +- [ ] transform/4 +- [ ] unfold/2 +- [ ] uniq/1 +- [ ] uniq/2 +- [ ] uniq_by/2 +- [ ] with_index/1 +- [ ] with_index/2 +- [ ] zip/1 +- [ ] zip/2 +## Task.Supervisor +- [ ] async/2 +- [ ] async/4 +- [ ] async_nolink/2 +- [ ] async_nolink/4 +- [ ] async_stream/3 +- [ ] async_stream/4 +- [ ] async_stream/5 +- [ ] async_stream/6 +- [ ] async_stream_nolink/3 +- [ ] async_stream_nolink/4 +- [ ] async_stream_nolink/5 +- [ ] async_stream_nolink/6 +- [ ] children/1 +- [ ] start_child/2 +- [ ] start_child/4 +- [ ] start_link/0 +- [ ] start_link/1 +- [ ] terminate_child/2 +## Inspect.Version.Requirement +- [ ] __impl__/1 +- [ ] inspect/2 +## TryClauseError +- [ ] __struct__/0 +- [ ] __struct__/1 +- [ ] exception/1 +- [ ] message/1 +## Version +- [ ] __struct__/0 +- [ ] __struct__/1 +- [ ] compare/2 +- [ ] compile_requirement/1 +- [ ] match?/2 +- [ ] match?/3 +- [ ] parse/1 +- [ ] parse!/1 +- [ ] parse_requirement/1 +## Record +- [ ] __access__/4 +- [ ] __access__/5 +- [ ] __fields__/2 +- [ ] __keyword__/3 +- [ ] extract/2 +- [ ] extract_all/1 +- [ ] defrecord/2 +- [ ] defrecord/3 +- [ ] defrecordp/2 +- [ ] defrecordp/3 +- [ ] is_record/1 +- [ ] is_record/2 +## CondClauseError +- [ ] __struct__/0 +- [ ] __struct__/1 +- [ ] exception/1 +- [ ] message/1 +## Inspect.Integer +- [ ] __impl__/1 +- [ ] inspect/2 +## List +- [X] delete/2 +- [X] delete_at/2 +- [X] duplicate/2 +- [X] first/1 +- [X] flatten/1 +- [X] flatten/2 +- [X] foldl/3 +- [X] foldr/3 +- [X] insert_at/3 +- [X] keydelete/3 +- [X] keyfind/3 +- [X] keyfind/4 +- [X] keymember?/3 +- [X] keyreplace/4 +- [ ] keysort/2 +- [ ] keystore/4 +- [ ] keytake/3 +- [X] last/1 +- [ ] myers_difference/2 +- [ ] pop_at/2 +- [ ] pop_at/3 +- [X] replace_at/3 +- [ ] to_atom/1 +- [ ] to_existing_atom/1 +- [ ] to_float/1 +- [ ] to_integer/1 +- [ ] to_integer/2 +- [ ] to_string/1 +- [X] to_tuple/1 +- [X] update_at/3 +- [X] wrap/1 +- [X] zip/1 +## Regex +- [ ] __struct__/0 +- [ ] __struct__/1 +- [X] compile/1 +- [X] compile/2 +- [X] compile!/1 +- [X] compile!/2 +- [ ] escape/1 +- [X] match?/2 +- [ ] named_captures/2 +- [ ] named_captures/3 +- [ ] names/1 +- [X] opts/1 +- [ ] re_pattern/1 +- [X] regex?/1 +- [X] replace/3 +- [X] replace/4 +- [X] run/2 +- [X] run/3 +- [X] scan/2 +- [X] scan/3 +- [X] source/1 +- [ ] split/2 +- [ ] split/3 +- [ ] unescape_map/1 +## Collectable.IO.Stream +- [ ] __impl__/1 +- [ ] into/1 +## File.Error +- [ ] __struct__/0 +- [ ] __struct__/1 +- [ ] exception/1 +- [ ] message/1 +## Inspect.Algebra +- [ ] break/0 +- [ ] break/1 +- [ ] color/3 +- [ ] concat/1 +- [ ] concat/2 +- [ ] empty/0 +- [ ] fold_doc/2 +- [ ] format/2 +- [ ] glue/2 +- [ ] glue/3 +- [ ] group/1 +- [ ] line/2 +- [ ] nest/2 +- [ ] space/2 +- [ ] surround/3 +- [ ] surround_many/5 +- [ ] surround_many/6 +- [ ] to_doc/2 +## Node +- [ ] alive?/0 +- [ ] connect/1 +- [ ] disconnect/1 +- [ ] get_cookie/0 +- [ ] list/0 +- [ ] list/1 +- [ ] monitor/2 +- [ ] monitor/3 +- [ ] ping/1 +- [ ] self/0 +- [ ] set_cookie/1 +- [ ] set_cookie/2 +- [ ] spawn/2 +- [ ] spawn/3 +- [ ] spawn/4 +- [ ] spawn/5 +- [ ] spawn_link/2 +- [ ] spawn_link/4 +- [ ] start/1 +- [ ] start/2 +- [ ] start/3 +- [ ] stop/0 +## File.CopyError +- [ ] __struct__/0 +- [ ] __struct__/1 +- [ ] exception/1 +- [ ] message/1 +## Port +- [ ] close/1 +- [ ] command/2 +- [ ] command/3 +- [ ] connect/2 +- [ ] info/1 +- [ ] info/2 +- [ ] list/0 +- [ ] open/2 +## Enumerable.MapSet +- [ ] __impl__/1 +- [ ] count/1 +- [ ] member?/2 +- [ ] reduce/3 +## Inspect.Stream +- [ ] __impl__/1 +- [ ] inspect/2 +## Kernel.ParallelRequire +- [ ] files/1 +- [ ] files/2 +## FunctionClauseError +- [ ] __struct__/0 +- [ ] __struct__/1 +- [ ] exception/1 +- [ ] message/1 +## Enumerable.Function +- [ ] __impl__/1 +- [ ] count/1 +- [ ] member?/2 +- [ ] reduce/3 +## GenServer +- [ ] abcast/2 +- [ ] abcast/3 +- [ ] call/2 +- [ ] call/3 +- [ ] cast/2 +- [ ] multi_call/2 +- [ ] multi_call/3 +- [ ] multi_call/4 +- [ ] reply/2 +- [ ] start/2 +- [ ] start/3 +- [ ] start_link/2 +- [ ] start_link/3 +- [ ] stop/1 +- [ ] stop/2 +- [ ] stop/3 +- [ ] whereis/1 +- [ ] __using__/1 +## List.Chars +- [ ] __protocol__/1 +- [ ] impl_for/1 +- [ ] impl_for!/1 +- [ ] to_char_list/1 +- [ ] to_charlist/1 +## Inspect.Atom +- [ ] __impl__/1 +- [ ] inspect/1 +- [ ] inspect/2 +## Inspect.HashDict +- [ ] __impl__/1 +- [ ] inspect/2 +## Enumerable.IO.Stream +- [ ] __impl__/1 +- [ ] count/1 +- [ ] member?/2 +- [ ] reduce/3 +## Kernel.Typespec +- [ ] beam_callbacks/1 +- [ ] beam_specs/1 +- [ ] beam_typedocs/1 +- [ ] beam_types/1 +- [ ] define_spec/3 +- [ ] define_type/3 +- [ ] define_type/4 +- [ ] defines_callback?/3 +- [ ] defines_spec?/3 +- [ ] defines_type?/3 +- [ ] defspec/3 +- [ ] deftype/3 +- [ ] spec_to_ast/2 +- [ ] spec_to_signature/1 +- [ ] translate_spec/3 +- [ ] translate_type/3 +- [ ] type_to_ast/1 +- [ ] type_to_signature/1 +- [ ] defcallback/1 +- [ ] defmacrocallback/1 +- [ ] defopaque/1 +- [ ] defoptional_callbacks/1 +- [ ] defspec/1 +- [ ] deftype/1 +- [ ] deftypep/1 +## KeyError +- [ ] __struct__/0 +- [ ] __struct__/1 +- [ ] exception/1 +- [ ] message/1 +## MapSet +- [X] __struct__/0 +- [X] __struct__/1 +- [X] delete/2 +- [X] difference/2 +- [X] disjoint?/2 +- [X] equal?/2 +- [X] intersection/2 +- [X] member?/2 +- [X] new/0 +- [ ] new/1 +- [ ] new/2 +- [X] put/2 +- [X] size/1 +- [X] subset?/2 +- [X] to_list/1 +- [X] union/2 +## Macro +- [ ] camelize/1 +- [ ] decompose_call/1 +- [ ] escape/1 +- [ ] escape/2 +- [ ] expand/2 +- [ ] expand_once/2 +- [ ] pipe/3 +- [ ] pipe_warning/1 +- [ ] postwalk/2 +- [ ] postwalk/3 +- [ ] prewalk/2 +- [ ] prewalk/3 +- [ ] to_string/1 +- [ ] to_string/2 +- [ ] traverse/4 +- [ ] underscore/1 +- [ ] unescape_string/1 +- [ ] unescape_string/2 +- [ ] unescape_tokens/1 +- [ ] unescape_tokens/2 +- [ ] unpipe/1 +- [ ] update_meta/2 +- [ ] validate/1 +- [ ] var/2 +- [ ] binary_ops/0 +- [ ] unary_ops/0 +## URI +- [ ] __struct__/0 +- [ ] __struct__/1 +- [ ] char_reserved?/1 +- [ ] char_unescaped?/1 +- [ ] char_unreserved?/1 +- [ ] decode/1 +- [ ] decode_query/1 +- [ ] decode_query/2 +- [ ] decode_www_form/1 +- [ ] default_port/1 +- [ ] default_port/2 +- [ ] encode/1 +- [ ] encode/2 +- [ ] encode_query/1 +- [ ] encode_www_form/1 +- [ ] merge/2 +- [ ] parse/1 +- [ ] path_to_segments/1 +- [ ] query_decoder/1 +- [ ] to_string/1 +## Inspect.Opts +- [ ] __struct__/0 +- [ ] __struct__/1 +## Atom +- [X] to_char_list/1 +- [ ] to_charlist/1 +- [X] to_string/1 +## TokenMissingError +- [ ] __struct__/0 +- [ ] __struct__/1 +- [ ] exception/1 +- [ ] message/1 +## BadBooleanError +- [ ] __struct__/0 +- [ ] __struct__/1 +- [ ] exception/1 +- [ ] message/1 +## String.Chars.Date +- [ ] __impl__/1 +- [ ] to_string/1 +## Set +- [ ] delete/2 +- [ ] difference/2 +- [ ] disjoint?/2 +- [ ] empty/1 +- [ ] equal?/2 +- [ ] intersection/2 +- [ ] member?/2 +- [ ] put/2 +- [ ] size/1 +- [ ] subset?/2 +- [ ] to_list/1 +- [ ] union/2 +## WithClauseError +- [ ] __struct__/0 +- [ ] __struct__/1 +- [ ] exception/1 +- [ ] message/1 +## List.Chars.Atom +- [ ] __impl__/1 +- [ ] to_charlist/1 +## Version.InvalidRequirementError +- [ ] __struct__/0 +- [ ] __struct__/1 +- [ ] exception/1 +- [ ] message/1 +## Application +- [ ] app_dir/1 +- [ ] app_dir/2 +- [ ] delete_env/2 +- [ ] delete_env/3 +- [ ] ensure_all_started/1 +- [ ] ensure_all_started/2 +- [ ] ensure_started/1 +- [ ] ensure_started/2 +- [ ] fetch_env/2 +- [ ] fetch_env!/2 +- [ ] format_error/1 +- [ ] get_all_env/1 +- [ ] get_application/1 +- [ ] get_env/2 +- [ ] get_env/3 +- [ ] load/1 +- [ ] loaded_applications/0 +- [ ] put_env/3 +- [ ] put_env/4 +- [ ] spec/1 +- [ ] spec/2 +- [ ] start/1 +- [ ] start/2 +- [ ] started_applications/0 +- [ ] started_applications/1 +- [ ] stop/1 +- [ ] unload/1 +- [ ] __using__/1 +## Inspect.PID +- [ ] __impl__/1 +- [ ] inspect/2 +## Calendar.ISO +- [ ] date/3 +- [ ] date_to_iso8601/3 +- [ ] date_to_string/3 +- [ ] datetime_to_iso8601/11 +- [ ] datetime_to_string/11 +- [ ] day_of_week/3 +- [ ] days_in_month/2 +- [ ] from_unix/2 +- [ ] leap_year?/1 +- [ ] naive_datetime_to_iso8601/7 +- [ ] naive_datetime_to_string/7 +- [ ] parse_microsecond/1 +- [ ] parse_offset/1 +- [ ] time_to_iso8601/4 +- [ ] time_to_string/4 diff --git a/lib/elixir_script/gen/supported.ex b/lib/elixir_script/gen/supported.ex new file mode 100644 index 00000000..422c3670 --- /dev/null +++ b/lib/elixir_script/gen/supported.ex @@ -0,0 +1,70 @@ +defmodule ElixirScript.Gen.Supported do + @moduledoc false + @private_modules [ + Kernel.Utils, + String.Normalizer, + Version.Parser, + IO.ANSI.Sequence, + Version.Parser.DSL, + String.Break, + IO.ANSI.Docs, + Kernel.LexicalTracker, + Task.Supervised, + Supervisor.Default, + Registry.Partition, + Module.LocalsTracker, + Kernel.CLI, + Registry.Supervisor, + Stream.Reducers, + Agent.Server, + ] + + def generate() do + File.open!("Supported.md", [:write], &write_to_file/1) + end + + def write_to_file(file) do + IO.puts(file, "# Supported Elixir Modules") + module_map = get_module_map() + + Enum.each(module_map, fn({elixir_module, elixir_script_module}) -> + IO.puts(file, "## #{inspect elixir_module}") + exports = elixir_module.__info__(:functions) ++ elixir_module.__info__(:macros) + elixir_script_exports = if Code.ensure_loaded?(elixir_script_module) do + elixir_script_module.__info__(:functions) ++ elixir_script_module.__info__(:macros) + else + [] + end + + Enum.each(exports, fn({func, arity}) -> + if Enum.member?(elixir_script_exports, {func, arity}) do + IO.puts(file, "- [X] #{func}/#{arity}") + else + IO.puts(file, "- [ ] #{func}/#{arity}") + end + end) + end) + end + + defp get_module_map() do + Application.spec(:elixir, :modules) + |> Enum.filter(&is_public(&1)) + |> Enum.reduce(Map.new, fn(x, acc) -> + try do + elixirscript_module = (["ElixirScript"] ++ Module.split(x)) |> Module.concat() + Map.put(acc, x, elixirscript_module) + rescue + FunctionClauseError -> + acc + end + end) + end + + defp is_public(m) when m in @private_modules do + false + end + + defp is_public(_) do + true + end +end \ No newline at end of file diff --git a/lib/elixir_script/translator.ex b/lib/elixir_script/translator.ex index ca71c476..d8c11001 100644 --- a/lib/elixir_script/translator.ex +++ b/lib/elixir_script/translator.ex @@ -167,11 +167,6 @@ defmodule ElixirScript.Translator do Expression.make_binary_expression(:%, left, right, env) end - defp do_translate({:throw, _, [params]}, env) do - { result, env } = translate(params, env) - { JS.throw_statement(result), env } - end - defp do_translate({:<>, context, [left, right]}, env) do translate({:+, context, [left, right]}, env) end diff --git a/mix.exs b/mix.exs index c31d1f54..869e92d8 100644 --- a/mix.exs +++ b/mix.exs @@ -62,7 +62,8 @@ defmodule ElixirScript.Mixfile do defp aliases do [dist: &dist/1, - install: &install/1] + install: &install/1, + supported: &supported/1] end def dist(_) do @@ -105,4 +106,10 @@ defmodule ElixirScript.Mixfile do IO.puts("installed at /usr/local/elixirscript") end + def supported(_) do + Mix.Task.run "app.start" + + ElixirScript.Gen.Supported.generate() + end + end diff --git a/priv/std_lib/exceptions.ex b/priv/std_lib/exceptions.ex index cb2ce0c5..4f723003 100644 --- a/priv/std_lib/exceptions.ex +++ b/priv/std_lib/exceptions.ex @@ -1,3 +1,7 @@ defmodule ElixirScript.ArgumentError do defexception message: "argument error" +end + +defmodule ElixirScript.RuntimeError do + defexception message: "runtime error" end \ No newline at end of file diff --git a/priv/std_lib/kernel.ex b/priv/std_lib/kernel.ex index 1bc4dbe4..83978563 100644 --- a/priv/std_lib/kernel.ex +++ b/priv/std_lib/kernel.ex @@ -202,4 +202,8 @@ defmodule ElixirScript.Kernel do %ElixirScript.Range{ first: unquote(first), last: unquote(last) } end end + + def throw(term) do + JS.throw(term) + end end From c2a86ec1b53e8ac32b8b0f5b3d67f994b7682c07 Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Sun, 9 Apr 2017 09:44:54 -0500 Subject: [PATCH 519/860] Update supported.md with description --- Supported.md | 3 +++ lib/elixir_script/gen/supported.ex | 1 + 2 files changed, 4 insertions(+) diff --git a/Supported.md b/Supported.md index 42a37640..6b339f91 100644 --- a/Supported.md +++ b/Supported.md @@ -1,4 +1,7 @@ # Supported Elixir Modules + +List all public modules in the Elixir Standard Libary. If a function or macro is supported in ElixirScript, it is checked + ## BadStructError - [ ] __struct__/0 - [ ] __struct__/1 diff --git a/lib/elixir_script/gen/supported.ex b/lib/elixir_script/gen/supported.ex index 422c3670..0f3adfaa 100644 --- a/lib/elixir_script/gen/supported.ex +++ b/lib/elixir_script/gen/supported.ex @@ -25,6 +25,7 @@ defmodule ElixirScript.Gen.Supported do def write_to_file(file) do IO.puts(file, "# Supported Elixir Modules") + IO.puts(file, "List all public modules in the Elixir Standard Libary. If a function or macro is supported in ElixirScript, it is checked") module_map = get_module_map() Enum.each(module_map, fn({elixir_module, elixir_script_module}) -> From 5914b3cb7b26411b0150dc031a73ddebce20e03b Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Sun, 9 Apr 2017 09:59:36 -0500 Subject: [PATCH 520/860] Check of raise --- Supported.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Supported.md b/Supported.md index 6b339f91..4f331299 100644 --- a/Supported.md +++ b/Supported.md @@ -244,8 +244,8 @@ List all public modules in the Elixir Standard Libary. If a function or macro is - [X] or/2 - [ ] pop_in/1 - [ ] put_in/2 -- [ ] raise/1 -- [ ] raise/2 +- [X] raise/1 +- [X] raise/2 - [ ] reraise/2 - [ ] reraise/3 - [ ] sigil_C/2 From fe5dce7d805ea87edf8462ac7346ae04bb094493 Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Sun, 9 Apr 2017 11:14:26 -0500 Subject: [PATCH 521/860] Update docs --- CONTRIBUTING.md | 17 ++++--- FAQ.md | 72 +----------------------------- lib/elixir_script/gen/supported.ex | 2 +- mix.exs | 2 +- 4 files changed, 11 insertions(+), 82 deletions(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 511aa424..b9884e8a 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -64,27 +64,26 @@ found in Elixir in ElixirScript. ElixirScript is broken up into the following parts: * The compiler, written in Elixir -* The standard library modules, mostly written in Elixir +* The standard library modules, written in Elixir * The javascript core The ElixirScript compiler is in the `lib` folder of the project. Here is where Elixir code is converted into JavaScript. -The standard library modules are in the `lib/std_lib` folder. +The standard library modules are in the `priv/std_lib` folder. The JavaScript code is in the `src/javascript`. -This is where features such as pattern matching and the standard library are implemented. +This is where features such as pattern matching and the special forms are implemented. The ElixirScript tests can be run using `mix test` -The JavaScript tests can be run using `npm test` +The JavaScript tests can be run using `yarn test` Please make sure all tests pass after making changes. Also make sure to include tests for the changes you made. -Contributing to the JavaScript code may be the easiest and most rewarding changes. -Don't see a feature, module or function from Elixir in ElixirScript yet? You can implement it -in the JavaScript code. +Contributing to the standard library may be the easiest and most rewarding changes. +Don't see a module, function or macro from Elixir in ElixirScript yet? You can help by implementing it. ## Pull requests @@ -119,7 +118,7 @@ in order to craft an excellent pull request: # Navigate to the newly cloned directory cd elixirscript # Assign the original repo to a remote called "upstream" - git remote add upstream https://github.com/bryanjos/elixirscript + git remote add upstream https://github.com/elixirscript/elixirscript ``` 2. If you cloned a while ago, get the latest changes from upstream: @@ -150,7 +149,7 @@ in order to craft an excellent pull request: ```sh mix test - npm test + yarn test ``` This is needed to ensure your changes can diff --git a/FAQ.md b/FAQ.md index 760b7aa7..92ba2f7e 100644 --- a/FAQ.md +++ b/FAQ.md @@ -6,77 +6,7 @@ # Q. How much is implemented? -### A. Most of Kernel.SpecialForms as well as some modules in the Standard Library - -The compiler to this point has been focused on translating Kernel.SpecialForms and Kernel. Below is a list of what is complete, incomplete, as well as missing - -#### Kernel.SpecialForms - -* Complete - * `__DIR__` - * `__MODULE__` - * `^var` - * `&expr` - * `for` - * `%{}` - * `{args}` - * `<>` - * `fn [clauses] end` - * `cond(clauses)` - * `__block__` - * `__aliases__` - * `unquote` - * `unquote_splicing` - * `%` - * `left.right` - * `quote` - * `import` - * `case` - * `left = right` - * `require` - * `left :: right` - * `alias` - * `__CALLER__` - * `__ENV__` - * `super(args)` - -* Missing - * `receive` - -* Caveats - * `quote` - ignores `context` options - * `left = right` does not support full unification yet. - ```elixir - a = 1 # works as expected - - 1 = a # may not work currently, but in some cases it will - ``` - - -#### Completed Modules - - * Tuple - * List - * Atom - * Range - * Map - * MapSet - -#### Incomplete Modules - - * Kernel - * Enum - * Agent - * Integer - * Keyword - * Base - * String - * Bitwise - * Set - -#### Missing Modules - * Everything else - +### A. Check out the [Supported Modules, Functions, and Macros](Supported.md) ## Q. Can I use it today? diff --git a/lib/elixir_script/gen/supported.ex b/lib/elixir_script/gen/supported.ex index 0f3adfaa..17ec8263 100644 --- a/lib/elixir_script/gen/supported.ex +++ b/lib/elixir_script/gen/supported.ex @@ -29,7 +29,7 @@ defmodule ElixirScript.Gen.Supported do module_map = get_module_map() Enum.each(module_map, fn({elixir_module, elixir_script_module}) -> - IO.puts(file, "## #{inspect elixir_module}") + IO.puts(file, "## #{inspect elixir_module}") exports = elixir_module.__info__(:functions) ++ elixir_module.__info__(:macros) elixir_script_exports = if Code.ensure_loaded?(elixir_script_module) do elixir_script_module.__info__(:functions) ++ elixir_script_module.__info__(:macros) diff --git a/mix.exs b/mix.exs index 869e92d8..8b257ebb 100644 --- a/mix.exs +++ b/mix.exs @@ -15,7 +15,7 @@ defmodule ElixirScript.Mixfile do aliases: aliases(), test_coverage: [tool: ExCoveralls], docs: [ - extras: ["GettingStarted.md", "FAQ.md"] + extras: ["GettingStarted.md", "FAQ.md", "Supported.md"] ] ] end From e1a6b21d3e59ae8039cfc388e17f04d53a6612c3 Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Sun, 9 Apr 2017 19:48:07 -0500 Subject: [PATCH 522/860] Getting global js state once on start --- CHANGELOG.md | 1 + lib/elixir_script/translator/kernel/js.ex | 15 ++++++--------- priv/std_lib/js.ex | 2 +- src/javascript/lib/core.js | 21 +++++++++++++++++++-- src/javascript/lib/core/functions.js | 13 ------------- test/translator/js_test.exs | 16 ++++++++-------- 6 files changed, 35 insertions(+), 33 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 91b0d510..710e2cbd 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/). ### Added - `remove-unused` option that will remove all unused modules from output +- reimplemented structs to avoid creating JavaScript classes ## [0.27.0] - 2017-03-17 diff --git a/lib/elixir_script/translator/kernel/js.ex b/lib/elixir_script/translator/kernel/js.ex index 43c1c0d1..ea0c52e6 100644 --- a/lib/elixir_script/translator/kernel/js.ex +++ b/lib/elixir_script/translator/kernel/js.ex @@ -23,12 +23,9 @@ defmodule ElixirScript.Translator.JS do Builder.member_expression( Builder.member_expression( Builder.identifier("Bootstrap"), - Builder.member_expression( - Builder.identifier("Core"), - Builder.identifier("Functions") - ) + Builder.identifier("Core") ), - Builder.identifier("get_global") + Builder.identifier("global") ) end @@ -191,7 +188,7 @@ defmodule ElixirScript.Translator.JS do Builder.call_expression( call_property(), [ - Builder.call_expression(global(), []), + global(), Translator.translate!(to_string(function), env) ] ) @@ -200,7 +197,7 @@ defmodule ElixirScript.Translator.JS do defp do_translate({function, _, params}, env) do Builder.call_expression( Builder.member_expression( - Builder.call_expression(global(), []), + global(), Builder.identifier(function) ), Enum.map(params, &Translator.translate!(&1, env)) @@ -214,7 +211,7 @@ defmodule ElixirScript.Translator.JS do call_property(), [ Builder.member_expression( - Builder.call_expression(global(), []), + global(), members ), Translator.translate!(to_string(function), env) @@ -228,7 +225,7 @@ defmodule ElixirScript.Translator.JS do Builder.call_expression( Builder.member_expression( Builder.member_expression( - Builder.call_expression(global(), []), + global(), members ), Builder.identifier(function) diff --git a/priv/std_lib/js.ex b/priv/std_lib/js.ex index d9383a9a..3e3db5ac 100644 --- a/priv/std_lib/js.ex +++ b/priv/std_lib/js.ex @@ -52,7 +52,7 @@ defmodule JS do In node this would be the global object. """ def global() do - Bootstrap.Core.Functions.get_global() + Bootstrap.Core.global() end @doc """ diff --git a/src/javascript/lib/core.js b/src/javascript/lib/core.js index 8b488fb8..366a6a6a 100644 --- a/src/javascript/lib/core.js +++ b/src/javascript/lib/core.js @@ -5,8 +5,24 @@ import SpecialForms from './core/special_forms'; class Integer {} class Float {} -Functions.get_global().__elixirscript_store__ = new Map(); -Functions.get_global().__elixirscript_names__ = new Map(); + +function get_global() { + if (typeof self !== 'undefined') { + return self; + } else if (typeof window !== 'undefined') { + return window; + } else if (typeof global !== 'undefined') { + return global; + } + + console.warn('No global state found'); + return null; +} + +const globalState = get_global(); + +globalState.__elixirscript_store__ = new Map(); +globalState.__elixirscript_names__ = new Map(); export default { Tuple: ErlangTypes.Tuple, @@ -17,4 +33,5 @@ export default { Float, Functions, SpecialForms, + global: globalState, }; diff --git a/src/javascript/lib/core/functions.js b/src/javascript/lib/core/functions.js index f6d0e2df..d0d21099 100644 --- a/src/javascript/lib/core/functions.js +++ b/src/javascript/lib/core/functions.js @@ -52,18 +52,6 @@ function call_property(item, property) { return item[prop]; } -function get_global() { - if (typeof self !== 'undefined') { - return self; - } else if (typeof window !== 'undefined') { - return window; - } else if (typeof global !== 'undefined') { - return global; - } - - throw new Error('No global state found'); -} - function defprotocol(spec) { return new Protocol(spec); } @@ -97,7 +85,6 @@ function build_namespace(ns, ns_string) { export default { call_property, - get_global, defprotocol, defimpl, build_namespace, diff --git a/test/translator/js_test.exs b/test/translator/js_test.exs index 2118dba8..7dde65f2 100644 --- a/test/translator/js_test.exs +++ b/test/translator/js_test.exs @@ -5,48 +5,48 @@ defmodule ElixirScript.Translator.JS.Test do test "translate global function calls" do ex_ast = quote do: JS.alert("hi") - js_code = "Bootstrap.Core.Functions.get_global().alert('hi')" + js_code = "Bootstrap.Core.global.alert('hi')" assert_translation(ex_ast, js_code) ex_ast = quote do: JS.back() - js_code = "Bootstrap.Core.Functions.call_property(Bootstrap.Core.Functions.get_global(), 'back')" + js_code = "Bootstrap.Core.Functions.call_property(Bootstrap.Core.global, 'back')" assert_translation(ex_ast, js_code) end test "translate global properties" do ex_ast = quote do: JS.length - js_code = "Bootstrap.Core.Functions.call_property(Bootstrap.Core.Functions.get_global(), 'length')" + js_code = "Bootstrap.Core.Functions.call_property(Bootstrap.Core.global, 'length')" assert_translation(ex_ast, js_code) end test "translate global module" do ex_ast = quote do: JS.String.toString() - js_code = "Bootstrap.Core.Functions.call_property(Bootstrap.Core.Functions.get_global().String, 'toString')" + js_code = "Bootstrap.Core.Functions.call_property(Bootstrap.Core.global.String, 'toString')" assert_translation(ex_ast, js_code) ex_ast = quote do: JS.String.raw("hi") - js_code = "Bootstrap.Core.Functions.get_global().String.raw('hi')" + js_code = "Bootstrap.Core.global.String.raw('hi')" assert_translation(ex_ast, js_code) ex_ast = quote do: JS.Something.Other.raw("hi") - js_code = "Bootstrap.Core.Functions.get_global().Something.Other.raw('hi')" + js_code = "Bootstrap.Core.global.Something.Other.raw('hi')" assert_translation(ex_ast, js_code) end test "translate global lowercase" do ex_ast = quote do: JS.console.log("hi") - js_code = "Bootstrap.Core.Functions.call_property(Bootstrap.Core.Functions.get_global(), 'console').log('hi')" + js_code = "Bootstrap.Core.Functions.call_property(Bootstrap.Core.global, 'console').log('hi')" assert_translation(ex_ast, js_code) ex_ast = quote do: JS.window.length - js_code = "Bootstrap.Core.Functions.call_property(Bootstrap.Core.Functions.call_property(Bootstrap.Core.Functions.get_global(), 'window'), 'length')" + js_code = "Bootstrap.Core.Functions.call_property(Bootstrap.Core.Functions.call_property(Bootstrap.Core.global, 'window'), 'length')" assert_translation(ex_ast, js_code) end From 455113ea5d45bdd92d11640c085ef09cb86113af Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Sun, 9 Apr 2017 20:05:34 -0500 Subject: [PATCH 523/860] Update supported generator to order modules --- Supported.md | 3963 ++++++++++++++-------------- lib/elixir_script/gen/supported.ex | 114 +- 2 files changed, 2085 insertions(+), 1992 deletions(-) diff --git a/Supported.md b/Supported.md index 4f331299..69be84e1 100644 --- a/Supported.md +++ b/Supported.md @@ -1,2007 +1,2006 @@ # Supported Elixir Modules - List all public modules in the Elixir Standard Libary. If a function or macro is supported in ElixirScript, it is checked - -## BadStructError -- [ ] __struct__/0 -- [ ] __struct__/1 -- [ ] exception/1 -- [ ] message/1 -## Collectable.List -- [X] __impl__/1 -- [X] into/1 -## Inspect.Float -- [ ] __impl__/1 -- [ ] inspect/2 -## String.Chars.Version.Requirement -- [ ] __impl__/1 -- [ ] to_string/1 -## Inspect.NaiveDateTime -- [ ] __impl__/1 -- [ ] inspect/2 -## Inspect.MapSet -- [ ] __impl__/1 -- [ ] inspect/2 -## Inspect -- [ ] __protocol__/1 -- [ ] impl_for/1 -- [ ] impl_for!/1 -- [ ] inspect/2 -## Inspect.Range -- [ ] __impl__/1 -- [ ] inspect/2 +## Access +- [ ] `all/0` +- [ ] `at/1` +- [ ] `elem/1` +- [ ] `fetch/2` +- [ ] `get/2` +- [ ] `get/3` +- [ ] `get_and_update/3` +- [ ] `key/1` +- [ ] `key/2` +- [ ] `key!/1` +- [ ] `pop/2` +## Agent +- [ ] `cast/2` +- [ ] `cast/4` +- [X] `get/2` +- [ ] `get/3` +- [ ] `get/4` +- [ ] `get/5` +- [X] `get_and_update/2` +- [ ] `get_and_update/3` +- [ ] `get_and_update/4` +- [ ] `get_and_update/5` +- [X] `start/1` +- [X] `start/2` +- [ ] `start/3` +- [ ] `start/4` +- [X] `start_link/1` +- [X] `start_link/2` +- [ ] `start_link/3` +- [ ] `start_link/4` +- [X] `stop/1` +- [ ] `stop/2` +- [ ] `stop/3` +- [X] `update/2` +- [ ] `update/3` +- [ ] `update/4` +- [ ] `update/5` +## Application +- [ ] `app_dir/1` +- [ ] `app_dir/2` +- [ ] `delete_env/2` +- [ ] `delete_env/3` +- [ ] `ensure_all_started/1` +- [ ] `ensure_all_started/2` +- [ ] `ensure_started/1` +- [ ] `ensure_started/2` +- [ ] `fetch_env/2` +- [ ] `fetch_env!/2` +- [ ] `format_error/1` +- [ ] `get_all_env/1` +- [ ] `get_application/1` +- [ ] `get_env/2` +- [ ] `get_env/3` +- [ ] `load/1` +- [ ] `loaded_applications/0` +- [ ] `put_env/3` +- [ ] `put_env/4` +- [ ] `spec/1` +- [ ] `spec/2` +- [ ] `start/1` +- [ ] `start/2` +- [ ] `started_applications/0` +- [ ] `started_applications/1` +- [ ] `stop/1` +- [ ] `unload/1` +- [ ] `__using__/1` ## ArgumentError -- [X] __struct__/0 -- [X] __struct__/1 -- [X] exception/1 -- [X] message/1 +- [X] `__struct__/0` +- [X] `__struct__/1` +- [X] `exception/1` +- [X] `message/1` +## ArithmeticError +- [ ] `__struct__/0` +- [ ] `__struct__/1` +- [ ] `exception/1` +- [ ] `message/1` +## Atom +- [X] `to_char_list/1` +- [ ] `to_charlist/1` +- [X] `to_string/1` +## BadArityError +- [ ] `__struct__/0` +- [ ] `__struct__/1` +- [ ] `exception/1` +- [ ] `message/1` +## BadBooleanError +- [ ] `__struct__/0` +- [ ] `__struct__/1` +- [ ] `exception/1` +- [ ] `message/1` +## BadFunctionError +- [ ] `__struct__/0` +- [ ] `__struct__/1` +- [ ] `exception/1` +- [ ] `message/1` +## BadMapError +- [ ] `__struct__/0` +- [ ] `__struct__/1` +- [ ] `exception/1` +- [ ] `message/1` +## BadStructError +- [ ] `__struct__/0` +- [ ] `__struct__/1` +- [ ] `exception/1` +- [ ] `message/1` ## Base -- [ ] decode16/1 -- [ ] decode16/2 -- [ ] decode16!/1 -- [ ] decode16!/2 -- [ ] decode32/1 -- [ ] decode32/2 -- [ ] decode32!/1 -- [ ] decode32!/2 -- [X] decode64/1 -- [ ] decode64/2 -- [X] decode64!/1 -- [ ] decode64!/2 -- [ ] encode16/1 -- [ ] encode16/2 -- [ ] encode32/1 -- [ ] encode32/2 -- [X] encode64/1 -- [ ] encode64/2 -- [ ] hex_decode32/1 -- [ ] hex_decode32/2 -- [ ] hex_decode32!/1 -- [ ] hex_decode32!/2 -- [ ] hex_encode32/1 -- [ ] hex_encode32/2 -- [ ] url_decode64/1 -- [ ] url_decode64/2 -- [ ] url_decode64!/1 -- [ ] url_decode64!/2 -- [ ] url_encode64/1 -- [ ] url_encode64/2 -## Macro.Env -- [X] __struct__/0 -- [X] __struct__/1 -- [ ] in_guard?/1 -- [ ] in_match?/1 -- [ ] location/1 -- [ ] stacktrace/1 -## Collectable.Map -- [X] __impl__/1 -- [X] into/1 -## Inspect.Regex -- [ ] __impl__/1 -- [ ] inspect/2 +- [ ] `decode16/1` +- [ ] `decode16/2` +- [ ] `decode16!/1` +- [ ] `decode16!/2` +- [ ] `decode32/1` +- [ ] `decode32/2` +- [ ] `decode32!/1` +- [ ] `decode32!/2` +- [X] `decode64/1` +- [ ] `decode64/2` +- [X] `decode64!/1` +- [ ] `decode64!/2` +- [ ] `encode16/1` +- [ ] `encode16/2` +- [ ] `encode32/1` +- [ ] `encode32/2` +- [X] `encode64/1` +- [ ] `encode64/2` +- [ ] `hex_decode32/1` +- [ ] `hex_decode32/2` +- [ ] `hex_decode32!/1` +- [ ] `hex_decode32!/2` +- [ ] `hex_encode32/1` +- [ ] `hex_encode32/2` +- [ ] `url_decode64/1` +- [ ] `url_decode64/2` +- [ ] `url_decode64!/1` +- [ ] `url_decode64!/2` +- [ ] `url_encode64/1` +- [ ] `url_encode64/2` ## Behaviour -- [ ] __using__/1 -- [ ] defcallback/1 -- [ ] defmacrocallback/1 -## Collectable -- [X] __protocol__/1 -- [X] impl_for/1 -- [X] impl_for!/1 -- [X] into/1 -## String.Chars.Time -- [ ] __impl__/1 -- [ ] to_string/1 -## String.Chars.Atom -- [X] __impl__/1 -- [X] to_string/1 -## String.Chars -- [X] __protocol__/1 -- [X] impl_for/1 -- [X] impl_for!/1 -- [X] to_string/1 -## Integer -- [ ] digits/1 -- [ ] digits/2 -- [ ] floor_div/2 -- [ ] mod/2 -- [X] parse/1 -- [X] parse/2 -- [X] to_char_list/1 -- [ ] to_charlist/1 -- [ ] to_charlist/2 -- [ ] to_string/1 -- [ ] to_string/2 -- [ ] undigits/1 -- [ ] undigits/2 -- [X] is_even/1 -- [X] is_odd/1 -## String.Chars.NaiveDateTime -- [ ] __impl__/1 -- [ ] to_string/1 -## Inspect.Any -- [ ] __impl__/1 -- [ ] inspect/2 -## BadMapError -- [ ] __struct__/0 -- [ ] __struct__/1 -- [ ] exception/1 -- [ ] message/1 -## BadArityError -- [ ] __struct__/0 -- [ ] __struct__/1 -- [ ] exception/1 -- [ ] message/1 -## Kernel -- [X] !=/2 -- [X] !==/2 -- [X] */2 -- [X] +/1 -- [X] +/2 -- [X] ++/2 -- [X] -/1 -- [X] -/2 -- [X] --/2 -- [X] //2 -- [X] /2 -- [X] >=/2 -- [X] abs/1 -- [X] apply/2 -- [X] apply/3 -- [X] binary_part/3 -- [ ] bit_size/1 -- [ ] byte_size/1 -- [X] div/2 -- [X] elem/2 -- [ ] exit/1 -- [ ] function_exported?/3 -- [ ] get_and_update_in/3 -- [ ] get_in/2 -- [X] hd/1 -- [ ] inspect/1 -- [ ] inspect/2 -- [X] is_atom/1 -- [X] is_binary/1 -- [X] is_bitstring/1 -- [X] is_boolean/1 -- [X] is_float/1 -- [X] is_function/1 -- [X] is_function/2 -- [X] is_integer/1 -- [X] is_list/1 -- [X] is_map/1 -- [X] is_number/1 -- [X] is_pid/1 -- [X] is_port/1 -- [X] is_reference/1 -- [X] is_tuple/1 -- [X] length/1 -- [ ] macro_exported?/3 -- [ ] make_ref/0 -- [X] map_size/1 -- [X] max/2 -- [X] min/2 -- [ ] node/0 -- [ ] node/1 -- [ ] not/1 -- [ ] pop_in/2 -- [ ] put_elem/3 -- [ ] put_in/3 -- [X] rem/2 -- [X] round/1 -- [ ] self/0 -- [ ] send/2 -- [ ] spawn/1 -- [ ] spawn/3 -- [ ] spawn_link/1 -- [ ] spawn_link/3 -- [ ] spawn_monitor/1 -- [ ] spawn_monitor/3 -- [ ] struct/1 -- [ ] struct/2 -- [ ] struct!/1 -- [ ] struct!/2 -- [X] throw/1 -- [X] tl/1 -- [X] trunc/1 -- [X] tuple_size/1 -- [ ] update_in/3 -- [X] !/1 -- [X] &&/2 -- [X] ../2 -- [X] <>/2 -- [X] @/1 -- [ ] alias!/1 -- [X] and/2 -- [ ] binding/0 -- [ ] binding/1 -- [X] def/1 -- [X] def/2 -- [X] defdelegate/2 -- [X] defexception/1 -- [X] defimpl/2 -- [X] defimpl/3 -- [X] defmacro/1 -- [X] defmacro/2 -- [ ] defmacrop/1 -- [ ] defmacrop/2 -- [X] defmodule/2 -- [X] defoverridable/1 -- [X] defp/1 -- [X] defp/2 -- [X] defprotocol/2 -- [X] defstruct/1 -- [ ] destructure/2 -- [ ] get_and_update_in/2 -- [X] if/2 -- [X] in/2 -- [X] is_nil/1 -- [X] match?/2 -- [X] or/2 -- [ ] pop_in/1 -- [ ] put_in/2 -- [X] raise/1 -- [X] raise/2 -- [ ] reraise/2 -- [ ] reraise/3 -- [ ] sigil_C/2 -- [ ] sigil_D/2 -- [ ] sigil_N/2 -- [ ] sigil_R/2 -- [ ] sigil_S/2 -- [ ] sigil_T/2 -- [ ] sigil_W/2 -- [ ] sigil_c/2 -- [X] sigil_r/2 -- [ ] sigil_s/2 -- [ ] sigil_w/2 -- [ ] to_char_list/1 -- [ ] to_charlist/1 -- [X] to_string/1 -- [X] unless/2 -- [ ] update_in/2 -- [X] use/1 -- [X] use/2 -- [ ] var!/1 -- [ ] var!/2 -- [X] |>/2 -- [X] ||/2 -## Kernel.ParallelCompiler -- [ ] files/1 -- [ ] files/2 -- [ ] files_to_path/2 -- [ ] files_to_path/3 -## File.Stream -- [ ] __build__/3 -- [ ] __struct__/0 -- [ ] __struct__/1 -## Inspect.List -- [ ] __impl__/1 -- [ ] inspect/2 -- [ ] keyword/2 -- [ ] keyword?/1 -- [ ] printable?/1 -## Path.Wildcard -- [ ] list_dir/1 -- [ ] read_link_info/1 -## SyntaxError -- [ ] __struct__/0 -- [ ] __struct__/1 -- [ ] exception/1 -- [ ] message/1 -## List.Chars.List -- [ ] __impl__/1 -- [ ] to_charlist/1 +- [ ] `__using__/1` +- [ ] `defcallback/1` +- [ ] `defmacrocallback/1` +## Bitwise +- [X] `&&&/2` +- [X] `<<>>/2` +- [X] `^^^/2` +- [ ] `__using__/1` +- [X] `band/2` +- [X] `bnot/1` +- [X] `bor/2` +- [X] `bsl/2` +- [X] `bsr/2` +- [X] `bxor/2` +- [X] `|||/2` +- [X] `~~~/1` +## Calendar +## Calendar.ISO +- [ ] `date/3` +- [ ] `date_to_iso8601/3` +- [ ] `date_to_string/3` +- [ ] `datetime_to_iso8601/11` +- [ ] `datetime_to_string/11` +- [ ] `day_of_week/3` +- [ ] `days_in_month/2` +- [ ] `from_unix/2` +- [ ] `leap_year?/1` +- [ ] `naive_datetime_to_iso8601/7` +- [ ] `naive_datetime_to_string/7` +- [ ] `parse_microsecond/1` +- [ ] `parse_offset/1` +- [ ] `time_to_iso8601/4` +- [ ] `time_to_string/4` ## CaseClauseError -- [ ] __struct__/0 -- [ ] __struct__/1 -- [ ] exception/1 -- [ ] message/1 -## Path -- [ ] absname/1 -- [ ] absname/2 -- [ ] basename/1 -- [ ] basename/2 -- [ ] dirname/1 -- [ ] expand/1 -- [ ] expand/2 -- [ ] extname/1 -- [ ] join/1 -- [ ] join/2 -- [ ] relative/1 -- [ ] relative_to/2 -- [ ] relative_to_cwd/1 -- [ ] rootname/1 -- [ ] rootname/2 -- [ ] split/1 -- [ ] type/1 -- [ ] wildcard/1 -- [ ] wildcard/2 -## UnicodeConversionError -- [ ] __struct__/0 -- [ ] __struct__/1 -- [ ] exception/1 -- [ ] message/1 -## String.Chars.BitString -- [X] __impl__/1 -- [X] to_string/1 -## DateTime -- [ ] __struct__/0 -- [ ] __struct__/1 -- [ ] compare/2 -- [ ] from_iso8601/1 -- [ ] from_naive/2 -- [ ] from_naive!/2 -- [ ] from_unix/1 -- [ ] from_unix/2 -- [ ] from_unix!/1 -- [ ] from_unix!/2 -- [ ] to_date/1 -- [ ] to_iso8601/1 -- [ ] to_naive/1 -- [ ] to_string/1 -- [ ] to_time/1 -- [ ] to_unix/1 -- [ ] to_unix/2 -- [ ] utc_now/0 -## String.Chars.Float -- [X] __impl__/1 -- [X] to_string/1 +- [ ] `__struct__/0` +- [ ] `__struct__/1` +- [ ] `exception/1` +- [ ] `message/1` +## Code +- [ ] `append_path/1` +- [ ] `available_compiler_options/0` +- [ ] `compile_quoted/1` +- [ ] `compile_quoted/2` +- [ ] `compile_string/1` +- [ ] `compile_string/2` +- [ ] `compiler_options/0` +- [ ] `compiler_options/1` +- [ ] `delete_path/1` +- [ ] `ensure_compiled/1` +- [ ] `ensure_compiled?/1` +- [ ] `ensure_loaded/1` +- [ ] `ensure_loaded?/1` +- [ ] `eval_file/1` +- [ ] `eval_file/2` +- [ ] `eval_quoted/1` +- [ ] `eval_quoted/2` +- [ ] `eval_quoted/3` +- [ ] `eval_string/1` +- [ ] `eval_string/2` +- [ ] `eval_string/3` +- [ ] `get_docs/2` +- [ ] `load_file/1` +- [ ] `load_file/2` +- [ ] `loaded_files/0` +- [ ] `prepend_path/1` +- [ ] `require_file/1` +- [ ] `require_file/2` +- [ ] `string_to_quoted/1` +- [ ] `string_to_quoted/2` +- [ ] `string_to_quoted!/1` +- [ ] `string_to_quoted!/2` +- [ ] `unload_files/1` +## Code.LoadError +- [ ] `__struct__/0` +- [ ] `__struct__/1` +- [ ] `exception/1` +- [ ] `message/1` +## Collectable +- [X] `__protocol__/1` +- [X] `impl_for/1` +- [X] `impl_for!/1` +- [X] `into/1` +## Collectable.BitString +- [X] `__impl__/1` +- [X] `into/1` ## Collectable.File.Stream -- [ ] __impl__/1 -- [ ] into/1 -## String.Chars.URI -- [ ] __impl__/1 -- [ ] to_string/1 +- [ ] `__impl__/1` +- [ ] `into/1` +## Collectable.HashDict +- [ ] `__impl__/1` +- [ ] `into/1` +## Collectable.HashSet +- [ ] `__impl__/1` +- [ ] `into/1` +## Collectable.IO.Stream +- [ ] `__impl__/1` +- [ ] `into/1` +## Collectable.List +- [X] `__impl__/1` +- [X] `into/1` +## Collectable.Map +- [X] `__impl__/1` +- [X] `into/1` +## Collectable.MapSet +- [ ] `__impl__/1` +- [ ] `into/1` ## CompileError -- [ ] __struct__/0 -- [ ] __struct__/1 -- [ ] exception/1 -- [ ] message/1 -## File -- [ ] cd/1 -- [ ] cd!/1 -- [ ] cd!/2 -- [ ] chgrp/2 -- [ ] chgrp!/2 -- [ ] chmod/2 -- [ ] chmod!/2 -- [ ] chown/2 -- [ ] chown!/2 -- [ ] close/1 -- [ ] copy/2 -- [ ] copy/3 -- [ ] copy!/2 -- [ ] copy!/3 -- [ ] cp/2 -- [ ] cp/3 -- [ ] cp!/2 -- [ ] cp!/3 -- [ ] cp_r/2 -- [ ] cp_r/3 -- [ ] cp_r!/2 -- [ ] cp_r!/3 -- [ ] cwd/0 -- [ ] cwd!/0 -- [ ] dir?/1 -- [ ] exists?/1 -- [ ] ln_s/2 -- [ ] ls/0 -- [ ] ls/1 -- [ ] ls!/0 -- [ ] ls!/1 -- [ ] lstat/1 -- [ ] lstat/2 -- [ ] lstat!/1 -- [ ] lstat!/2 -- [ ] mkdir/1 -- [ ] mkdir!/1 -- [ ] mkdir_p/1 -- [ ] mkdir_p!/1 -- [ ] open/1 -- [ ] open/2 -- [ ] open/3 -- [ ] open!/1 -- [ ] open!/2 -- [ ] open!/3 -- [ ] read/1 -- [ ] read!/1 -- [ ] regular?/1 -- [ ] rename/2 -- [ ] rm/1 -- [ ] rm!/1 -- [ ] rm_rf/1 -- [ ] rm_rf!/1 -- [ ] rmdir/1 -- [ ] rmdir!/1 -- [ ] stat/1 -- [ ] stat/2 -- [ ] stat!/1 -- [ ] stat!/2 -- [ ] stream!/1 -- [ ] stream!/2 -- [ ] stream!/3 -- [ ] touch/1 -- [ ] touch/2 -- [ ] touch!/1 -- [ ] touch!/2 -- [ ] write/2 -- [ ] write/3 -- [ ] write!/2 -- [ ] write!/3 -- [ ] write_stat/2 -- [ ] write_stat/3 -- [ ] write_stat!/2 -- [ ] write_stat!/3 +- [ ] `__struct__/0` +- [ ] `__struct__/1` +- [ ] `exception/1` +- [ ] `message/1` +## CondClauseError +- [ ] `__struct__/0` +- [ ] `__struct__/1` +- [ ] `exception/1` +- [ ] `message/1` +## Date +- [ ] `__struct__/0` +- [ ] `__struct__/1` +- [ ] `compare/2` +- [ ] `day_of_week/1` +- [ ] `days_in_month/1` +- [ ] `from_erl/1` +- [ ] `from_erl!/1` +- [ ] `from_iso8601/1` +- [ ] `from_iso8601!/1` +- [ ] `leap_year?/1` +- [ ] `new/3` +- [ ] `to_erl/1` +- [ ] `to_iso8601/1` +- [ ] `to_string/1` +- [ ] `utc_today/0` +## DateTime +- [ ] `__struct__/0` +- [ ] `__struct__/1` +- [ ] `compare/2` +- [ ] `from_iso8601/1` +- [ ] `from_naive/2` +- [ ] `from_naive!/2` +- [ ] `from_unix/1` +- [ ] `from_unix/2` +- [ ] `from_unix!/1` +- [ ] `from_unix!/2` +- [ ] `to_date/1` +- [ ] `to_iso8601/1` +- [ ] `to_naive/1` +- [ ] `to_string/1` +- [ ] `to_time/1` +- [ ] `to_unix/1` +- [ ] `to_unix/2` +- [ ] `utc_now/0` ## Dict -- [ ] delete/2 -- [ ] drop/2 -- [ ] empty/1 -- [ ] equal?/2 -- [ ] fetch/2 -- [ ] fetch!/2 -- [ ] get/2 -- [ ] get/3 -- [ ] get_and_update/3 -- [ ] get_lazy/3 -- [ ] has_key?/2 -- [ ] keys/1 -- [ ] merge/2 -- [ ] merge/3 -- [ ] pop/2 -- [ ] pop/3 -- [ ] pop_lazy/3 -- [ ] put/3 -- [ ] put_new/3 -- [ ] put_new_lazy/3 -- [ ] size/1 -- [ ] split/2 -- [ ] take/2 -- [ ] to_list/1 -- [ ] update/4 -- [ ] update!/3 -- [ ] values/1 -- [ ] __using__/1 -## Version.Requirement -- [ ] __struct__/0 -- [ ] __struct__/1 -## String -- [X] at/2 -- [X] capitalize/1 -- [ ] chunk/2 -- [X] codepoints/1 -- [X] contains?/2 -- [X] downcase/1 -- [X] duplicate/2 -- [X] ends_with?/2 -- [ ] equivalent?/2 -- [X] first/1 -- [X] graphemes/1 -- [ ] jaro_distance/2 -- [X] last/1 -- [X] length/1 -- [ ] ljust/2 -- [ ] ljust/3 -- [ ] lstrip/1 -- [ ] lstrip/2 -- [X] match?/2 -- [ ] myers_difference/2 -- [X] next_codepoint/1 -- [X] next_grapheme/1 -- [ ] next_grapheme_size/1 -- [ ] normalize/2 -- [ ] pad_leading/2 -- [ ] pad_leading/3 -- [ ] pad_trailing/2 -- [ ] pad_trailing/3 -- [ ] printable?/1 -- [ ] replace/3 -- [ ] replace/4 -- [ ] replace_leading/3 -- [ ] replace_prefix/3 -- [ ] replace_suffix/3 -- [ ] replace_trailing/3 -- [X] reverse/1 -- [ ] rjust/2 -- [ ] rjust/3 -- [ ] rstrip/1 -- [ ] rstrip/2 -- [ ] slice/2 -- [ ] slice/3 -- [X] split/1 -- [X] split/2 -- [X] split/3 -- [ ] split_at/2 -- [ ] splitter/2 -- [ ] splitter/3 -- [X] starts_with?/2 -- [ ] strip/1 -- [ ] strip/2 -- [X] to_atom/1 -- [X] to_char_list/1 -- [ ] to_charlist/1 -- [X] to_existing_atom/1 -- [X] to_float/1 -- [X] to_integer/1 -- [X] to_integer/2 -- [ ] trim/1 -- [ ] trim/2 -- [ ] trim_leading/1 -- [ ] trim_leading/2 -- [ ] trim_trailing/1 -- [ ] trim_trailing/2 -- [X] upcase/1 -- [ ] valid?/1 -- [X] valid_character?/1 -## Record.Extractor -- [ ] extract/2 -- [ ] extract_all/1 -## Collectable.HashSet -- [ ] __impl__/1 -- [ ] into/1 -## String.Unicode -- [ ] codepoints/1 -- [ ] graphemes/1 -- [ ] length/1 -- [ ] next_codepoint/1 -- [ ] next_grapheme_size/1 -- [ ] split_at/2 -- [ ] version/0 -## ErlangError -- [ ] __struct__/0 -- [ ] __struct__/1 -- [ ] exception/1 -- [ ] message/1 -- [ ] normalize/2 -## File.Stat -- [ ] __struct__/0 -- [ ] __struct__/1 -- [ ] from_record/1 -- [ ] to_record/1 -## Inspect.Version -- [ ] __impl__/1 -- [ ] inspect/2 -## RuntimeError -- [X] __struct__/0 -- [X] __struct__/1 -- [X] exception/1 -- [X] message/1 -## Range -- [X] __struct__/0 -- [X] __struct__/1 -- [X] new/2 -- [X] range?/1 -## Exception -- [ ] exception?/1 -- [ ] format/2 -- [ ] format/3 -- [ ] format_banner/2 -- [ ] format_banner/3 -- [ ] format_exit/1 -- [ ] format_fa/2 -- [ ] format_file_line/2 -- [ ] format_file_line/3 -- [ ] format_mfa/3 -- [ ] format_stacktrace/0 -- [ ] format_stacktrace/1 -- [ ] format_stacktrace_entry/1 -- [ ] message/1 -- [ ] normalize/2 -- [ ] normalize/3 -## Inspect.Function -- [ ] __impl__/1 -- [ ] inspect/2 -## Enumerable.GenEvent.Stream -- [ ] __impl__/1 -- [ ] count/1 -- [ ] member?/2 -- [ ] reduce/3 +- [ ] `delete/2` +- [ ] `drop/2` +- [ ] `empty/1` +- [ ] `equal?/2` +- [ ] `fetch/2` +- [ ] `fetch!/2` +- [ ] `get/2` +- [ ] `get/3` +- [ ] `get_and_update/3` +- [ ] `get_lazy/3` +- [ ] `has_key?/2` +- [ ] `keys/1` +- [ ] `merge/2` +- [ ] `merge/3` +- [ ] `pop/2` +- [ ] `pop/3` +- [ ] `pop_lazy/3` +- [ ] `put/3` +- [ ] `put_new/3` +- [ ] `put_new_lazy/3` +- [ ] `size/1` +- [ ] `split/2` +- [ ] `take/2` +- [ ] `to_list/1` +- [ ] `update/4` +- [ ] `update!/3` +- [ ] `values/1` +- [ ] `__using__/1` +## Enum +- [X] `all?/1` +- [X] `all?/2` +- [X] `any?/1` +- [X] `any?/2` +- [X] `at/2` +- [X] `at/3` +- [ ] `chunk/2` +- [ ] `chunk/3` +- [ ] `chunk/4` +- [ ] `chunk_by/2` +- [X] `concat/1` +- [X] `concat/2` +- [X] `count/1` +- [X] `count/2` +- [ ] `dedup/1` +- [ ] `dedup_by/2` +- [X] `drop/2` +- [X] `drop_every/2` +- [X] `drop_while/2` +- [X] `each/2` +- [X] `empty?/1` +- [X] `fetch/2` +- [X] `fetch!/2` +- [X] `filter/2` +- [X] `filter_map/3` +- [X] `find/2` +- [X] `find/3` +- [ ] `find_index/2` +- [ ] `find_value/2` +- [ ] `find_value/3` +- [ ] `flat_map/2` +- [ ] `flat_map_reduce/3` +- [ ] `group_by/2` +- [ ] `group_by/3` +- [ ] `intersperse/2` +- [X] `into/2` +- [X] `into/3` +- [ ] `join/1` +- [ ] `join/2` +- [X] `map/2` +- [ ] `map_every/3` +- [ ] `map_join/2` +- [ ] `map_join/3` +- [X] `map_reduce/3` +- [ ] `max/1` +- [ ] `max/2` +- [ ] `max_by/2` +- [ ] `max_by/3` +- [X] `member?/2` +- [ ] `min/1` +- [ ] `min/2` +- [ ] `min_by/2` +- [ ] `min_by/3` +- [ ] `min_max/1` +- [ ] `min_max/2` +- [ ] `min_max_by/2` +- [ ] `min_max_by/3` +- [ ] `partition/2` +- [ ] `random/1` +- [X] `reduce/2` +- [X] `reduce/3` +- [ ] `reduce_while/3` +- [ ] `reject/2` +- [X] `reverse/1` +- [X] `reverse/2` +- [ ] `reverse_slice/3` +- [ ] `scan/2` +- [ ] `scan/3` +- [ ] `shuffle/1` +- [ ] `slice/2` +- [ ] `slice/3` +- [ ] `sort/1` +- [ ] `sort/2` +- [ ] `sort_by/2` +- [ ] `sort_by/3` +- [ ] `split/2` +- [ ] `split_while/2` +- [ ] `split_with/2` +- [ ] `sum/1` +- [X] `take/2` +- [X] `take_every/2` +- [ ] `take_random/2` +- [X] `take_while/2` +- [X] `to_list/1` +- [ ] `uniq/1` +- [ ] `uniq/2` +- [ ] `uniq_by/2` +- [ ] `unzip/1` +- [ ] `with_index/1` +- [ ] `with_index/2` +- [ ] `zip/1` +- [ ] `zip/2` +## Enum.EmptyError +- [ ] `__struct__/0` +- [ ] `__struct__/1` +- [ ] `exception/1` +- [ ] `message/1` ## Enum.OutOfBoundsError -- [X] __struct__/0 -- [X] __struct__/1 -- [X] exception/1 -- [X] message/1 +- [X] `__struct__/0` +- [X] `__struct__/1` +- [X] `exception/1` +- [X] `message/1` +## Enumerable +- [X] `__protocol__/1` +- [X] `count/1` +- [X] `impl_for/1` +- [X] `impl_for!/1` +- [X] `member?/2` +- [X] `reduce/3` +## Enumerable.File.Stream +- [ ] `__impl__/1` +- [ ] `count/1` +- [ ] `member?/2` +- [ ] `reduce/3` +## Enumerable.Function +- [ ] `__impl__/1` +- [ ] `count/1` +- [ ] `member?/2` +- [ ] `reduce/3` +## Enumerable.GenEvent.Stream +- [ ] `__impl__/1` +- [ ] `count/1` +- [ ] `member?/2` +- [ ] `reduce/3` +## Enumerable.HashDict +- [ ] `__impl__/1` +- [ ] `count/1` +- [ ] `member?/2` +- [ ] `reduce/3` +## Enumerable.HashSet +- [ ] `__impl__/1` +- [ ] `count/1` +- [ ] `member?/2` +- [ ] `reduce/3` +## Enumerable.IO.Stream +- [ ] `__impl__/1` +- [ ] `count/1` +- [ ] `member?/2` +- [ ] `reduce/3` +## Enumerable.List +- [X] `__impl__/1` +- [X] `count/1` +- [X] `member?/2` +- [X] `reduce/3` +## Enumerable.Map +- [X] `__impl__/1` +- [X] `count/1` +- [X] `member?/2` +- [X] `reduce/3` +## Enumerable.MapSet +- [ ] `__impl__/1` +- [ ] `count/1` +- [ ] `member?/2` +- [ ] `reduce/3` ## Enumerable.Range -- [ ] __impl__/1 -- [ ] count/1 -- [ ] member?/2 -- [ ] reduce/3 -## Date -- [ ] __struct__/0 -- [ ] __struct__/1 -- [ ] compare/2 -- [ ] day_of_week/1 -- [ ] days_in_month/1 -- [ ] from_erl/1 -- [ ] from_erl!/1 -- [ ] from_iso8601/1 -- [ ] from_iso8601!/1 -- [ ] leap_year?/1 -- [ ] new/3 -- [ ] to_erl/1 -- [ ] to_iso8601/1 -- [ ] to_string/1 -- [ ] utc_today/0 -## Inspect.Time -- [ ] __impl__/1 -- [ ] inspect/2 -## String.Casing -- [ ] downcase/1 -- [ ] titlecase_once/1 -- [ ] upcase/1 -## Regex.CompileError -- [ ] __struct__/0 -- [ ] __struct__/1 -- [ ] exception/1 -- [ ] message/1 -## Supervisor.Spec -- [ ] supervise/2 -- [ ] supervisor/2 -- [ ] supervisor/3 -- [ ] worker/2 -- [ ] worker/3 -## Collectable.MapSet -- [ ] __impl__/1 -- [ ] into/1 -## StringIO -- [ ] close/1 -- [ ] code_change/3 -- [ ] contents/1 -- [ ] flush/1 -- [ ] handle_call/3 -- [ ] handle_cast/2 -- [ ] handle_info/2 -- [ ] init/1 -- [ ] open/1 -- [ ] open/2 -- [ ] terminate/2 -## Inspect.Port -- [ ] __impl__/1 -- [ ] inspect/2 +- [ ] `__impl__/1` +- [ ] `count/1` +- [ ] `member?/2` +- [ ] `reduce/3` +## Enumerable.Stream +- [ ] `__impl__/1` +- [ ] `count/1` +- [ ] `member?/2` +- [ ] `reduce/3` +## ErlangError +- [ ] `__struct__/0` +- [ ] `__struct__/1` +- [ ] `exception/1` +- [ ] `message/1` +- [ ] `normalize/2` +## Exception +- [ ] `exception?/1` +- [ ] `format/2` +- [ ] `format/3` +- [ ] `format_banner/2` +- [ ] `format_banner/3` +- [ ] `format_exit/1` +- [ ] `format_fa/2` +- [ ] `format_file_line/2` +- [ ] `format_file_line/3` +- [ ] `format_mfa/3` +- [ ] `format_stacktrace/0` +- [ ] `format_stacktrace/1` +- [ ] `format_stacktrace_entry/1` +- [ ] `message/1` +- [ ] `normalize/2` +- [ ] `normalize/3` +## File +- [ ] `cd/1` +- [ ] `cd!/1` +- [ ] `cd!/2` +- [ ] `chgrp/2` +- [ ] `chgrp!/2` +- [ ] `chmod/2` +- [ ] `chmod!/2` +- [ ] `chown/2` +- [ ] `chown!/2` +- [ ] `close/1` +- [ ] `copy/2` +- [ ] `copy/3` +- [ ] `copy!/2` +- [ ] `copy!/3` +- [ ] `cp/2` +- [ ] `cp/3` +- [ ] `cp!/2` +- [ ] `cp!/3` +- [ ] `cp_r/2` +- [ ] `cp_r/3` +- [ ] `cp_r!/2` +- [ ] `cp_r!/3` +- [ ] `cwd/0` +- [ ] `cwd!/0` +- [ ] `dir?/1` +- [ ] `exists?/1` +- [ ] `ln_s/2` +- [ ] `ls/0` +- [ ] `ls/1` +- [ ] `ls!/0` +- [ ] `ls!/1` +- [ ] `lstat/1` +- [ ] `lstat/2` +- [ ] `lstat!/1` +- [ ] `lstat!/2` +- [ ] `mkdir/1` +- [ ] `mkdir!/1` +- [ ] `mkdir_p/1` +- [ ] `mkdir_p!/1` +- [ ] `open/1` +- [ ] `open/2` +- [ ] `open/3` +- [ ] `open!/1` +- [ ] `open!/2` +- [ ] `open!/3` +- [ ] `read/1` +- [ ] `read!/1` +- [ ] `regular?/1` +- [ ] `rename/2` +- [ ] `rm/1` +- [ ] `rm!/1` +- [ ] `rm_rf/1` +- [ ] `rm_rf!/1` +- [ ] `rmdir/1` +- [ ] `rmdir!/1` +- [ ] `stat/1` +- [ ] `stat/2` +- [ ] `stat!/1` +- [ ] `stat!/2` +- [ ] `stream!/1` +- [ ] `stream!/2` +- [ ] `stream!/3` +- [ ] `touch/1` +- [ ] `touch/2` +- [ ] `touch!/1` +- [ ] `touch!/2` +- [ ] `write/2` +- [ ] `write/3` +- [ ] `write!/2` +- [ ] `write!/3` +- [ ] `write_stat/2` +- [ ] `write_stat/3` +- [ ] `write_stat!/2` +- [ ] `write_stat!/3` +## File.CopyError +- [ ] `__struct__/0` +- [ ] `__struct__/1` +- [ ] `exception/1` +- [ ] `message/1` +## File.Error +- [ ] `__struct__/0` +- [ ] `__struct__/1` +- [ ] `exception/1` +- [ ] `message/1` +## File.Stat +- [ ] `__struct__/0` +- [ ] `__struct__/1` +- [ ] `from_record/1` +- [ ] `to_record/1` +## File.Stream +- [ ] `__build__/3` +- [ ] `__struct__/0` +- [ ] `__struct__/1` +## Float +- [ ] `ceil/1` +- [ ] `ceil/2` +- [ ] `floor/1` +- [ ] `floor/2` +- [ ] `parse/1` +- [ ] `ratio/1` +- [ ] `round/1` +- [ ] `round/2` +- [ ] `to_char_list/1` +- [ ] `to_char_list/2` +- [ ] `to_charlist/1` +- [ ] `to_string/1` +- [ ] `to_string/2` +## FunctionClauseError +- [ ] `__struct__/0` +- [ ] `__struct__/1` +- [ ] `exception/1` +- [ ] `message/1` +## GenEvent +- [ ] `ack_notify/2` +- [ ] `add_handler/3` +- [ ] `add_mon_handler/3` +- [ ] `call/3` +- [ ] `call/4` +- [ ] `format_status/2` +- [ ] `init_hib/4` +- [ ] `init_it/6` +- [ ] `notify/2` +- [ ] `remove_handler/3` +- [ ] `start/0` +- [ ] `start/1` +- [ ] `start_link/0` +- [ ] `start_link/1` +- [ ] `stop/1` +- [ ] `stop/2` +- [ ] `stop/3` +- [ ] `stream/1` +- [ ] `stream/2` +- [ ] `swap_handler/5` +- [ ] `swap_mon_handler/5` +- [ ] `sync_notify/2` +- [ ] `system_code_change/4` +- [ ] `system_continue/3` +- [ ] `system_get_state/1` +- [ ] `system_replace_state/2` +- [ ] `system_terminate/4` +- [ ] `which_handlers/1` +- [ ] `__using__/1` ## GenEvent.Stream -- [ ] __struct__/0 -- [ ] __struct__/1 -- [ ] code_change/3 -- [ ] handle_call/2 -- [ ] handle_event/2 -- [ ] handle_info/2 -- [ ] init/1 -- [ ] terminate/2 -## Protocol.UndefinedError -- [ ] __struct__/0 -- [ ] __struct__/1 -- [ ] exception/1 -- [ ] message/1 -## BadFunctionError -- [ ] __struct__/0 -- [ ] __struct__/1 -- [ ] exception/1 -- [ ] message/1 -## Time -- [ ] __struct__/0 -- [ ] __struct__/1 -- [ ] compare/2 -- [ ] from_erl/1 -- [ ] from_erl/2 -- [ ] from_erl!/1 -- [ ] from_erl!/2 -- [ ] from_iso8601/1 -- [ ] from_iso8601!/1 -- [ ] new/3 -- [ ] new/4 -- [ ] to_erl/1 -- [ ] to_iso8601/1 -- [ ] to_string/1 -- [ ] utc_now/0 -## List.Chars.BitString -- [ ] __impl__/1 -- [ ] to_charlist/1 -## Registry -- [ ] dispatch/3 -- [ ] keys/2 -- [ ] lookup/2 -- [ ] match/3 -- [ ] meta/2 -- [ ] put_meta/3 -- [ ] register/3 -- [ ] register_name/2 -- [ ] send/2 -- [ ] start_link/2 -- [ ] start_link/3 -- [ ] unregister/2 -- [ ] unregister_name/1 -- [ ] update_value/3 -- [ ] whereis_name/1 -## List.Chars.Float -- [ ] __impl__/1 -- [ ] to_charlist/1 -## Code.LoadError -- [ ] __struct__/0 -- [ ] __struct__/1 -- [ ] exception/1 -- [ ] message/1 -## ArithmeticError -- [ ] __struct__/0 -- [ ] __struct__/1 -- [ ] exception/1 -- [ ] message/1 -## String.Chars.List -- [X] __impl__/1 -- [X] to_string/1 +- [ ] `__struct__/0` +- [ ] `__struct__/1` +- [ ] `code_change/3` +- [ ] `handle_call/2` +- [ ] `handle_event/2` +- [ ] `handle_info/2` +- [ ] `init/1` +- [ ] `terminate/2` +## GenServer +- [ ] `abcast/2` +- [ ] `abcast/3` +- [ ] `call/2` +- [ ] `call/3` +- [ ] `cast/2` +- [ ] `multi_call/2` +- [ ] `multi_call/3` +- [ ] `multi_call/4` +- [ ] `reply/2` +- [ ] `start/2` +- [ ] `start/3` +- [ ] `start_link/2` +- [ ] `start_link/3` +- [ ] `stop/1` +- [ ] `stop/2` +- [ ] `stop/3` +- [ ] `whereis/1` +- [ ] `__using__/1` +## HashDict +- [ ] `__struct__/0` +- [ ] `__struct__/1` +- [ ] `delete/2` +- [ ] `dict_delete/2` +- [ ] `drop/2` +- [ ] `equal?/2` +- [ ] `fetch/2` +- [ ] `fetch!/2` +- [ ] `get/2` +- [ ] `get/3` +- [ ] `get_and_update/3` +- [ ] `get_lazy/3` +- [ ] `has_key?/2` +- [ ] `keys/1` +- [ ] `merge/2` +- [ ] `merge/3` +- [ ] `new/0` +- [ ] `pop/2` +- [ ] `pop/3` +- [ ] `pop_lazy/3` +- [ ] `put/3` +- [ ] `put_new/3` +- [ ] `put_new_lazy/3` +- [ ] `reduce/3` +- [ ] `size/1` +- [ ] `split/2` +- [ ] `take/2` +- [ ] `to_list/1` +- [ ] `update/4` +- [ ] `update!/3` +- [ ] `values/1` +## HashSet +- [ ] `__struct__/0` +- [ ] `__struct__/1` +- [ ] `delete/2` +- [ ] `difference/2` +- [ ] `disjoint?/2` +- [ ] `equal?/2` +- [ ] `intersection/2` +- [ ] `member?/2` +- [ ] `new/0` +- [ ] `put/2` +- [ ] `reduce/3` +- [ ] `size/1` +- [ ] `subset?/2` +- [ ] `to_list/1` +- [ ] `union/2` +## IO +- [ ] `binread/1` +- [ ] `binread/2` +- [ ] `binstream/2` +- [ ] `binwrite/1` +- [ ] `binwrite/2` +- [ ] `chardata_to_string/1` +- [ ] `each_binstream/2` +- [ ] `each_stream/2` +- [ ] `getn/1` +- [ ] `getn/2` +- [ ] `getn/3` +- [ ] `gets/1` +- [ ] `gets/2` +- [X] `inspect/1` +- [X] `inspect/2` +- [ ] `inspect/3` +- [ ] `iodata_length/1` +- [ ] `iodata_to_binary/1` +- [X] `puts/1` +- [X] `puts/2` +- [ ] `read/1` +- [ ] `read/2` +- [ ] `stream/2` +- [X] `warn/1` +- [ ] `warn/2` +- [ ] `write/1` +- [ ] `write/2` +## IO.ANSI +- [ ] `black/0` +- [ ] `black_background/0` +- [ ] `blink_off/0` +- [ ] `blink_rapid/0` +- [ ] `blink_slow/0` +- [ ] `blue/0` +- [ ] `blue_background/0` +- [ ] `bright/0` +- [ ] `clear/0` +- [ ] `clear_line/0` +- [ ] `color/1` +- [ ] `color/3` +- [ ] `color_background/1` +- [ ] `color_background/3` +- [ ] `conceal/0` +- [ ] `crossed_out/0` +- [ ] `cyan/0` +- [ ] `cyan_background/0` +- [ ] `default_background/0` +- [ ] `default_color/0` +- [ ] `enabled?/0` +- [ ] `encircled/0` +- [ ] `faint/0` +- [ ] `font_1/0` +- [ ] `font_2/0` +- [ ] `font_3/0` +- [ ] `font_4/0` +- [ ] `font_5/0` +- [ ] `font_6/0` +- [ ] `font_7/0` +- [ ] `font_8/0` +- [ ] `font_9/0` +- [ ] `format/1` +- [ ] `format/2` +- [ ] `format_fragment/1` +- [ ] `format_fragment/2` +- [ ] `framed/0` +- [ ] `green/0` +- [ ] `green_background/0` +- [ ] `home/0` +- [ ] `inverse/0` +- [ ] `inverse_off/0` +- [ ] `italic/0` +- [ ] `light_black/0` +- [ ] `light_black_background/0` +- [ ] `light_blue/0` +- [ ] `light_blue_background/0` +- [ ] `light_cyan/0` +- [ ] `light_cyan_background/0` +- [ ] `light_green/0` +- [ ] `light_green_background/0` +- [ ] `light_magenta/0` +- [ ] `light_magenta_background/0` +- [ ] `light_red/0` +- [ ] `light_red_background/0` +- [ ] `light_white/0` +- [ ] `light_white_background/0` +- [ ] `light_yellow/0` +- [ ] `light_yellow_background/0` +- [ ] `magenta/0` +- [ ] `magenta_background/0` +- [ ] `no_underline/0` +- [ ] `normal/0` +- [ ] `not_framed_encircled/0` +- [ ] `not_italic/0` +- [ ] `not_overlined/0` +- [ ] `overlined/0` +- [ ] `primary_font/0` +- [ ] `red/0` +- [ ] `red_background/0` +- [ ] `reset/0` +- [ ] `reverse/0` +- [ ] `reverse_off/0` +- [ ] `underline/0` +- [ ] `white/0` +- [ ] `white_background/0` +- [ ] `yellow/0` +- [ ] `yellow_background/0` +## IO.Stream +- [ ] `__build__/3` +- [ ] `__struct__/0` +- [ ] `__struct__/1` +## IO.StreamError +- [ ] `__struct__/0` +- [ ] `__struct__/1` +- [ ] `exception/1` +- [ ] `message/1` +## Inspect +- [ ] `__protocol__/1` +- [ ] `impl_for/1` +- [ ] `impl_for!/1` +- [ ] `inspect/2` +## Inspect.Algebra +- [ ] `break/0` +- [ ] `break/1` +- [ ] `color/3` +- [ ] `concat/1` +- [ ] `concat/2` +- [ ] `empty/0` +- [ ] `fold_doc/2` +- [ ] `format/2` +- [ ] `glue/2` +- [ ] `glue/3` +- [ ] `group/1` +- [ ] `line/2` +- [ ] `nest/2` +- [ ] `space/2` +- [ ] `surround/3` +- [ ] `surround_many/5` +- [ ] `surround_many/6` +- [ ] `to_doc/2` +## Inspect.Any +- [ ] `__impl__/1` +- [ ] `inspect/2` +## Inspect.Atom +- [ ] `__impl__/1` +- [ ] `inspect/1` +- [ ] `inspect/2` ## Inspect.BitString -- [ ] __impl__/1 -- [ ] escape/2 -- [ ] escape_char/1 -- [ ] inspect/2 +- [ ] `__impl__/1` +- [ ] `escape/2` +- [ ] `escape_char/1` +- [ ] `inspect/2` +## Inspect.Date +- [ ] `__impl__/1` +- [ ] `inspect/2` +## Inspect.Error +- [ ] `__struct__/0` +- [ ] `__struct__/1` +- [ ] `exception/1` +- [ ] `message/1` +## Inspect.Float +- [ ] `__impl__/1` +- [ ] `inspect/2` +## Inspect.Function +- [ ] `__impl__/1` +- [ ] `inspect/2` +## Inspect.HashDict +- [ ] `__impl__/1` +- [ ] `inspect/2` ## Inspect.HashSet -- [ ] __impl__/1 -- [ ] inspect/2 -## String.Chars.DateTime -- [ ] __impl__/1 -- [ ] to_string/1 +- [ ] `__impl__/1` +- [ ] `inspect/2` +## Inspect.Integer +- [ ] `__impl__/1` +- [ ] `inspect/2` +## Inspect.List +- [ ] `__impl__/1` +- [ ] `inspect/2` +- [ ] `keyword/2` +- [ ] `keyword?/1` +- [ ] `printable?/1` ## Inspect.Map -- [ ] __impl__/1 -- [ ] inspect/2 -- [ ] inspect/3 -## HashDict -- [ ] __struct__/0 -- [ ] __struct__/1 -- [ ] delete/2 -- [ ] dict_delete/2 -- [ ] drop/2 -- [ ] equal?/2 -- [ ] fetch/2 -- [ ] fetch!/2 -- [ ] get/2 -- [ ] get/3 -- [ ] get_and_update/3 -- [ ] get_lazy/3 -- [ ] has_key?/2 -- [ ] keys/1 -- [ ] merge/2 -- [ ] merge/3 -- [ ] new/0 -- [ ] pop/2 -- [ ] pop/3 -- [ ] pop_lazy/3 -- [ ] put/3 -- [ ] put_new/3 -- [ ] put_new_lazy/3 -- [ ] reduce/3 -- [ ] size/1 -- [ ] split/2 -- [ ] take/2 -- [ ] to_list/1 -- [ ] update/4 -- [ ] update!/3 -- [ ] values/1 -## NaiveDateTime -- [ ] __struct__/0 -- [ ] __struct__/1 -- [ ] add/2 -- [ ] add/3 -- [ ] compare/2 -- [ ] diff/2 -- [ ] diff/3 -- [ ] from_erl/1 -- [ ] from_erl/2 -- [ ] from_erl!/1 -- [ ] from_erl!/2 -- [ ] from_iso8601/1 -- [ ] from_iso8601!/1 -- [ ] new/2 -- [ ] new/6 -- [ ] new/7 -- [ ] to_date/1 -- [ ] to_erl/1 -- [ ] to_iso8601/1 -- [ ] to_string/1 -- [ ] to_time/1 -- [ ] utc_now/0 -## IO.ANSI -- [ ] black/0 -- [ ] black_background/0 -- [ ] blink_off/0 -- [ ] blink_rapid/0 -- [ ] blink_slow/0 -- [ ] blue/0 -- [ ] blue_background/0 -- [ ] bright/0 -- [ ] clear/0 -- [ ] clear_line/0 -- [ ] color/1 -- [ ] color/3 -- [ ] color_background/1 -- [ ] color_background/3 -- [ ] conceal/0 -- [ ] crossed_out/0 -- [ ] cyan/0 -- [ ] cyan_background/0 -- [ ] default_background/0 -- [ ] default_color/0 -- [ ] enabled?/0 -- [ ] encircled/0 -- [ ] faint/0 -- [ ] font_1/0 -- [ ] font_2/0 -- [ ] font_3/0 -- [ ] font_4/0 -- [ ] font_5/0 -- [ ] font_6/0 -- [ ] font_7/0 -- [ ] font_8/0 -- [ ] font_9/0 -- [ ] format/1 -- [ ] format/2 -- [ ] format_fragment/1 -- [ ] format_fragment/2 -- [ ] framed/0 -- [ ] green/0 -- [ ] green_background/0 -- [ ] home/0 -- [ ] inverse/0 -- [ ] inverse_off/0 -- [ ] italic/0 -- [ ] light_black/0 -- [ ] light_black_background/0 -- [ ] light_blue/0 -- [ ] light_blue_background/0 -- [ ] light_cyan/0 -- [ ] light_cyan_background/0 -- [ ] light_green/0 -- [ ] light_green_background/0 -- [ ] light_magenta/0 -- [ ] light_magenta_background/0 -- [ ] light_red/0 -- [ ] light_red_background/0 -- [ ] light_white/0 -- [ ] light_white_background/0 -- [ ] light_yellow/0 -- [ ] light_yellow_background/0 -- [ ] magenta/0 -- [ ] magenta_background/0 -- [ ] no_underline/0 -- [ ] normal/0 -- [ ] not_framed_encircled/0 -- [ ] not_italic/0 -- [ ] not_overlined/0 -- [ ] overlined/0 -- [ ] primary_font/0 -- [ ] red/0 -- [ ] red_background/0 -- [ ] reset/0 -- [ ] reverse/0 -- [ ] reverse_off/0 -- [ ] underline/0 -- [ ] white/0 -- [ ] white_background/0 -- [ ] yellow/0 -- [ ] yellow_background/0 -## Module -- [ ] add_doc/5 -- [ ] add_doc/6 -- [ ] compile_doc/6 -- [ ] concat/1 -- [ ] concat/2 -- [ ] create/3 -- [ ] defines?/2 -- [ ] defines?/3 -- [ ] definitions_in/1 -- [ ] definitions_in/2 -- [ ] delete_attribute/2 -- [ ] eval_quoted/2 -- [ ] eval_quoted/3 -- [ ] eval_quoted/4 -- [ ] get_attribute/2 -- [ ] get_attribute/3 -- [ ] make_overridable/2 -- [ ] open?/1 -- [ ] overridable?/2 -- [ ] put_attribute/3 -- [ ] put_attribute/5 -- [ ] register_attribute/3 -- [ ] safe_concat/1 -- [ ] safe_concat/2 -- [ ] split/1 -- [ ] store_typespec/3 -## IO -- [ ] binread/1 -- [ ] binread/2 -- [ ] binstream/2 -- [ ] binwrite/1 -- [ ] binwrite/2 -- [ ] chardata_to_string/1 -- [ ] each_binstream/2 -- [ ] each_stream/2 -- [ ] getn/1 -- [ ] getn/2 -- [ ] getn/3 -- [ ] gets/1 -- [ ] gets/2 -- [X] inspect/1 -- [X] inspect/2 -- [ ] inspect/3 -- [ ] iodata_length/1 -- [ ] iodata_to_binary/1 -- [X] puts/1 -- [X] puts/2 -- [ ] read/1 -- [ ] read/2 -- [ ] stream/2 -- [X] warn/1 -- [ ] warn/2 -- [ ] write/1 -- [ ] write/2 -## MatchError -- [ ] __struct__/0 -- [ ] __struct__/1 -- [ ] exception/1 -- [ ] message/1 -## Enumerable.HashSet -- [ ] __impl__/1 -- [ ] count/1 -- [ ] member?/2 -- [ ] reduce/3 -## Enumerable.HashDict -- [ ] __impl__/1 -- [ ] count/1 -- [ ] member?/2 -- [ ] reduce/3 -## Agent -- [ ] cast/2 -- [ ] cast/4 -- [X] get/2 -- [ ] get/3 -- [ ] get/4 -- [ ] get/5 -- [X] get_and_update/2 -- [ ] get_and_update/3 -- [ ] get_and_update/4 -- [ ] get_and_update/5 -- [X] start/1 -- [X] start/2 -- [ ] start/3 -- [ ] start/4 -- [X] start_link/1 -- [X] start_link/2 -- [ ] start_link/3 -- [ ] start_link/4 -- [X] stop/1 -- [ ] stop/2 -- [ ] stop/3 -- [X] update/2 -- [ ] update/3 -- [ ] update/4 -- [ ] update/5 -## String.Chars.Version -- [ ] __impl__/1 -- [ ] to_string/1 -## System -- [ ] argv/0 -- [ ] argv/1 -- [ ] at_exit/1 -- [ ] build_info/0 -- [ ] cmd/2 -- [ ] cmd/3 -- [ ] compiled_endianness/0 -- [ ] convert_time_unit/3 -- [ ] cwd/0 -- [ ] cwd!/0 -- [ ] delete_env/1 -- [ ] endianness/0 -- [ ] find_executable/1 -- [ ] get_env/0 -- [ ] get_env/1 -- [ ] get_pid/0 -- [ ] halt/0 -- [ ] halt/1 -- [ ] monotonic_time/0 -- [ ] monotonic_time/1 -- [ ] os_time/0 -- [ ] os_time/1 -- [ ] otp_release/0 -- [ ] put_env/1 -- [ ] put_env/2 -- [ ] schedulers/0 -- [ ] schedulers_online/0 -- [ ] stacktrace/0 -- [ ] system_time/0 -- [ ] system_time/1 -- [ ] time_offset/0 -- [ ] time_offset/1 -- [ ] tmp_dir/0 -- [ ] tmp_dir!/0 -- [ ] unique_integer/0 -- [ ] unique_integer/1 -- [ ] user_home/0 -- [ ] user_home!/0 -- [ ] version/0 +- [ ] `__impl__/1` +- [ ] `inspect/2` +- [ ] `inspect/3` +## Inspect.MapSet +- [ ] `__impl__/1` +- [ ] `inspect/2` +## Inspect.NaiveDateTime +- [ ] `__impl__/1` +- [ ] `inspect/2` +## Inspect.Opts +- [ ] `__struct__/0` +- [ ] `__struct__/1` +## Inspect.PID +- [ ] `__impl__/1` +- [ ] `inspect/2` +## Inspect.Port +- [ ] `__impl__/1` +- [ ] `inspect/2` +## Inspect.Range +- [ ] `__impl__/1` +- [ ] `inspect/2` +## Inspect.Reference +- [ ] `__impl__/1` +- [ ] `inspect/2` +## Inspect.Regex +- [ ] `__impl__/1` +- [ ] `inspect/2` +## Inspect.Stream +- [ ] `__impl__/1` +- [ ] `inspect/2` +## Inspect.Time +- [ ] `__impl__/1` +- [ ] `inspect/2` ## Inspect.Tuple -- [ ] __impl__/1 -- [ ] inspect/2 -## Collectable.BitString -- [X] __impl__/1 -- [X] into/1 -## Enumerable.Map -- [X] __impl__/1 -- [X] count/1 -- [X] member?/2 -- [X] reduce/3 -## Enum.EmptyError -- [ ] __struct__/0 -- [ ] __struct__/1 -- [ ] exception/1 -- [ ] message/1 -## GenEvent -- [ ] ack_notify/2 -- [ ] add_handler/3 -- [ ] add_mon_handler/3 -- [ ] call/3 -- [ ] call/4 -- [ ] format_status/2 -- [ ] init_hib/4 -- [ ] init_it/6 -- [ ] notify/2 -- [ ] remove_handler/3 -- [ ] start/0 -- [ ] start/1 -- [ ] start_link/0 -- [ ] start_link/1 -- [ ] stop/1 -- [ ] stop/2 -- [ ] stop/3 -- [ ] stream/1 -- [ ] stream/2 -- [ ] swap_handler/5 -- [ ] swap_mon_handler/5 -- [ ] sync_notify/2 -- [ ] system_code_change/4 -- [ ] system_continue/3 -- [ ] system_get_state/1 -- [ ] system_replace_state/2 -- [ ] system_terminate/4 -- [ ] which_handlers/1 -- [ ] __using__/1 -## Inspect.Error -- [ ] __struct__/0 -- [ ] __struct__/1 -- [ ] exception/1 -- [ ] message/1 -## Enumerable.List -- [X] __impl__/1 -- [X] count/1 -- [X] member?/2 -- [X] reduce/3 -## OptionParser.ParseError -- [ ] __struct__/0 -- [ ] __struct__/1 -- [ ] exception/1 -- [ ] message/1 -## Map -- [X] delete/2 -- [X] drop/2 -- [X] equal?/2 -- [X] fetch/2 -- [X] fetch!/2 -- [X] from_struct/1 -- [X] get/2 -- [X] get/3 -- [X] get_and_update/3 -- [ ] get_and_update!/3 -- [X] get_lazy/3 -- [X] has_key?/2 -- [X] keys/1 -- [X] merge/2 -- [ ] merge/3 -- [X] new/0 -- [ ] new/1 -- [ ] new/2 -- [X] pop/2 -- [X] pop/3 -- [X] pop_lazy/3 -- [X] put/3 -- [X] put_new/3 -- [X] put_new_lazy/3 -- [X] size/1 -- [X] split/2 -- [X] take/2 -- [X] to_list/1 -- [X] update/4 -- [X] update!/3 -- [X] values/1 -## OptionParser -- [ ] get_option_key/1 -- [ ] next/1 -- [ ] next/2 -- [ ] parse/1 -- [ ] parse/2 -- [ ] parse!/1 -- [ ] parse!/2 -- [ ] parse_head/1 -- [ ] parse_head/2 -- [ ] parse_head!/1 -- [ ] parse_head!/2 -- [ ] split/1 -- [ ] to_argv/1 -- [ ] to_argv/2 +- [ ] `__impl__/1` +- [ ] `inspect/2` +## Inspect.Version +- [ ] `__impl__/1` +- [ ] `inspect/2` +## Inspect.Version.Requirement +- [ ] `__impl__/1` +- [ ] `inspect/2` +## Integer +- [ ] `digits/1` +- [ ] `digits/2` +- [ ] `floor_div/2` +- [ ] `mod/2` +- [X] `parse/1` +- [X] `parse/2` +- [X] `to_char_list/1` +- [ ] `to_charlist/1` +- [ ] `to_charlist/2` +- [ ] `to_string/1` +- [ ] `to_string/2` +- [ ] `undigits/1` +- [ ] `undigits/2` +- [X] `is_even/1` +- [X] `is_odd/1` +## Kernel +- [X] `!=/2` +- [X] `!==/2` +- [X] `*/2` +- [X] `+/1` +- [X] `+/2` +- [X] `++/2` +- [X] `-/1` +- [X] `-/2` +- [X] `--/2` +- [X] `//2` +- [X] `/2` +- [X] `>=/2` +- [X] `abs/1` +- [X] `apply/2` +- [X] `apply/3` +- [X] `binary_part/3` +- [ ] `bit_size/1` +- [ ] `byte_size/1` +- [X] `div/2` +- [X] `elem/2` +- [ ] `exit/1` +- [ ] `function_exported?/3` +- [ ] `get_and_update_in/3` +- [ ] `get_in/2` +- [X] `hd/1` +- [ ] `inspect/1` +- [ ] `inspect/2` +- [X] `is_atom/1` +- [X] `is_binary/1` +- [X] `is_bitstring/1` +- [X] `is_boolean/1` +- [X] `is_float/1` +- [X] `is_function/1` +- [X] `is_function/2` +- [X] `is_integer/1` +- [X] `is_list/1` +- [X] `is_map/1` +- [X] `is_number/1` +- [X] `is_pid/1` +- [X] `is_port/1` +- [X] `is_reference/1` +- [X] `is_tuple/1` +- [X] `length/1` +- [ ] `macro_exported?/3` +- [ ] `make_ref/0` +- [X] `map_size/1` +- [X] `max/2` +- [X] `min/2` +- [ ] `node/0` +- [ ] `node/1` +- [ ] `not/1` +- [ ] `pop_in/2` +- [ ] `put_elem/3` +- [ ] `put_in/3` +- [X] `rem/2` +- [X] `round/1` +- [ ] `self/0` +- [ ] `send/2` +- [ ] `spawn/1` +- [ ] `spawn/3` +- [ ] `spawn_link/1` +- [ ] `spawn_link/3` +- [ ] `spawn_monitor/1` +- [ ] `spawn_monitor/3` +- [ ] `struct/1` +- [ ] `struct/2` +- [ ] `struct!/1` +- [ ] `struct!/2` +- [X] `throw/1` +- [X] `tl/1` +- [X] `trunc/1` +- [X] `tuple_size/1` +- [ ] `update_in/3` +- [X] `!/1` +- [X] `&&/2` +- [X] `../2` +- [X] `<>/2` +- [X] `@/1` +- [ ] `alias!/1` +- [X] `and/2` +- [ ] `binding/0` +- [ ] `binding/1` +- [X] `def/1` +- [X] `def/2` +- [X] `defdelegate/2` +- [X] `defexception/1` +- [X] `defimpl/2` +- [X] `defimpl/3` +- [X] `defmacro/1` +- [X] `defmacro/2` +- [X] `defmacrop/1` +- [X] `defmacrop/2` +- [X] `defmodule/2` +- [X] `defoverridable/1` +- [X] `defp/1` +- [X] `defp/2` +- [X] `defprotocol/2` +- [X] `defstruct/1` +- [ ] `destructure/2` +- [ ] `get_and_update_in/2` +- [X] `if/2` +- [X] `in/2` +- [X] `is_nil/1` +- [X] `match?/2` +- [X] `or/2` +- [ ] `pop_in/1` +- [ ] `put_in/2` +- [X] `raise/1` +- [X] `raise/2` +- [ ] `reraise/2` +- [ ] `reraise/3` +- [ ] `sigil_C/2` +- [ ] `sigil_D/2` +- [ ] `sigil_N/2` +- [ ] `sigil_R/2` +- [ ] `sigil_S/2` +- [ ] `sigil_T/2` +- [ ] `sigil_W/2` +- [ ] `sigil_c/2` +- [X] `sigil_r/2` +- [ ] `sigil_s/2` +- [ ] `sigil_w/2` +- [ ] `to_char_list/1` +- [ ] `to_charlist/1` +- [X] `to_string/1` +- [X] `unless/2` +- [ ] `update_in/2` +- [X] `use/1` +- [X] `use/2` +- [ ] `var!/1` +- [ ] `var!/2` +- [X] `|>/2` +- [X] `||/2` ## Kernel.ErrorHandler -- [ ] ensure_compiled/2 -- [ ] ensure_loaded/1 -- [ ] undefined_function/3 -- [ ] undefined_lambda/3 -## List.Chars.Integer -- [ ] __impl__/1 -- [ ] to_charlist/1 -## HashSet -- [ ] __struct__/0 -- [ ] __struct__/1 -- [ ] delete/2 -- [ ] difference/2 -- [ ] disjoint?/2 -- [ ] equal?/2 -- [ ] intersection/2 -- [ ] member?/2 -- [ ] new/0 -- [ ] put/2 -- [ ] reduce/3 -- [ ] size/1 -- [ ] subset?/2 -- [ ] to_list/1 -- [ ] union/2 -## Inspect.Date -- [ ] __impl__/1 -- [ ] inspect/2 -## Code -- [ ] append_path/1 -- [ ] available_compiler_options/0 -- [ ] compile_quoted/1 -- [ ] compile_quoted/2 -- [ ] compile_string/1 -- [ ] compile_string/2 -- [ ] compiler_options/0 -- [ ] compiler_options/1 -- [ ] delete_path/1 -- [ ] ensure_compiled/1 -- [ ] ensure_compiled?/1 -- [ ] ensure_loaded/1 -- [ ] ensure_loaded?/1 -- [ ] eval_file/1 -- [ ] eval_file/2 -- [ ] eval_quoted/1 -- [ ] eval_quoted/2 -- [ ] eval_quoted/3 -- [ ] eval_string/1 -- [ ] eval_string/2 -- [ ] eval_string/3 -- [ ] get_docs/2 -- [ ] load_file/1 -- [ ] load_file/2 -- [ ] loaded_files/0 -- [ ] prepend_path/1 -- [ ] require_file/1 -- [ ] require_file/2 -- [ ] string_to_quoted/1 -- [ ] string_to_quoted/2 -- [ ] string_to_quoted!/1 -- [ ] string_to_quoted!/2 -- [ ] unload_files/1 +- [ ] `ensure_compiled/2` +- [ ] `ensure_loaded/1` +- [ ] `undefined_function/3` +- [ ] `undefined_lambda/3` +## Kernel.ParallelCompiler +- [ ] `files/1` +- [ ] `files/2` +- [ ] `files_to_path/2` +- [ ] `files_to_path/3` +## Kernel.ParallelRequire +- [ ] `files/1` +- [ ] `files/2` ## Kernel.SpecialForms -- [X] %/2 -- [X] %{}/1 -- [X] &/1 -- [X] ./2 -- [X] ::/2 -- [X] <<>>/1 -- [X] =/2 -- [X] ^/1 -- [X] __CALLER__/0 -- [X] __DIR__/0 -- [X] __ENV__/0 -- [X] __MODULE__/0 -- [X] __aliases__/1 -- [X] __block__/1 -- [X] alias/2 -- [X] case/2 -- [X] cond/1 -- [X] fn/1 -- [X] for/1 -- [X] import/2 -- [X] quote/2 -- [ ] receive/1 -- [X] require/2 -- [X] super/1 -- [X] try/1 -- [X] unquote/1 -- [X] unquote_splicing/1 -- [X] with/1 -- [X] {}/1 -## Tuple -- [X] append/2 -- [X] delete_at/2 -- [X] duplicate/2 -- [X] insert_at/3 -- [X] to_list/1 -## SystemLimitError -- [ ] __struct__/0 -- [ ] __struct__/1 -- [ ] exception/1 -- [ ] message/1 -## Bitwise -- [X] &&&/2 -- [X] <<>>/2 -- [X] ^^^/2 -- [ ] __using__/1 -- [X] band/2 -- [X] bnot/1 -- [X] bor/2 -- [X] bsl/2 -- [X] bsr/2 -- [X] bxor/2 -- [X] |||/2 -- [X] ~~~/1 -## String.Chars.Integer -- [X] __impl__/1 -- [X] to_string/1 -## Inspect.Reference -- [ ] __impl__/1 -- [ ] inspect/2 -## IO.StreamError -- [ ] __struct__/0 -- [ ] __struct__/1 -- [ ] exception/1 -- [ ] message/1 +- [X] `%/2` +- [X] `%{}/1` +- [X] `&/1` +- [X] `./2` +- [X] `::/2` +- [X] `<<>>/1` +- [X] `=/2` +- [X] `^/1` +- [X] `__CALLER__/0` +- [X] `__DIR__/0` +- [X] `__ENV__/0` +- [X] `__MODULE__/0` +- [X] `__aliases__/1` +- [X] `__block__/1` +- [X] `alias/2` +- [X] `case/2` +- [X] `cond/1` +- [X] `fn/1` +- [X] `for/1` +- [X] `import/2` +- [X] `quote/2` +- [ ] `receive/1` +- [X] `require/2` +- [X] `super/1` +- [X] `try/1` +- [X] `unquote/1` +- [X] `unquote_splicing/1` +- [X] `with/1` +- [X] `{}/1` +## Kernel.Typespec +- [ ] `beam_callbacks/1` +- [ ] `beam_specs/1` +- [ ] `beam_typedocs/1` +- [ ] `beam_types/1` +- [ ] `define_spec/3` +- [ ] `define_type/3` +- [ ] `define_type/4` +- [ ] `defines_callback?/3` +- [ ] `defines_spec?/3` +- [ ] `defines_type?/3` +- [ ] `defspec/3` +- [ ] `deftype/3` +- [ ] `spec_to_ast/2` +- [ ] `spec_to_signature/1` +- [ ] `translate_spec/3` +- [ ] `translate_type/3` +- [ ] `type_to_ast/1` +- [ ] `type_to_signature/1` +- [ ] `defcallback/1` +- [ ] `defmacrocallback/1` +- [ ] `defopaque/1` +- [ ] `defoptional_callbacks/1` +- [ ] `defspec/1` +- [ ] `deftype/1` +- [ ] `deftypep/1` +## KeyError +- [ ] `__struct__/0` +- [ ] `__struct__/1` +- [ ] `exception/1` +- [ ] `message/1` +## Keyword +- [ ] `delete/2` +- [ ] `delete/3` +- [ ] `delete_first/2` +- [ ] `drop/2` +- [ ] `equal?/2` +- [ ] `fetch/2` +- [ ] `fetch!/2` +- [X] `get/2` +- [X] `get/3` +- [ ] `get_and_update/3` +- [ ] `get_and_update!/3` +- [ ] `get_lazy/3` +- [ ] `get_values/2` +- [X] `has_key?/2` +- [ ] `keys/1` +- [ ] `keyword?/1` +- [ ] `merge/2` +- [ ] `merge/3` +- [X] `new/0` +- [ ] `new/1` +- [ ] `new/2` +- [ ] `pop/2` +- [ ] `pop/3` +- [ ] `pop_first/2` +- [ ] `pop_first/3` +- [ ] `pop_lazy/3` +- [ ] `put/3` +- [ ] `put_new/3` +- [ ] `put_new_lazy/3` +- [ ] `size/1` +- [ ] `split/2` +- [ ] `take/2` +- [ ] `to_list/1` +- [ ] `update/4` +- [ ] `update!/3` +- [ ] `values/1` +## List +- [X] `delete/2` +- [X] `delete_at/2` +- [X] `duplicate/2` +- [X] `first/1` +- [X] `flatten/1` +- [X] `flatten/2` +- [X] `foldl/3` +- [X] `foldr/3` +- [X] `insert_at/3` +- [X] `keydelete/3` +- [X] `keyfind/3` +- [X] `keyfind/4` +- [X] `keymember?/3` +- [X] `keyreplace/4` +- [ ] `keysort/2` +- [ ] `keystore/4` +- [ ] `keytake/3` +- [X] `last/1` +- [ ] `myers_difference/2` +- [ ] `pop_at/2` +- [ ] `pop_at/3` +- [X] `replace_at/3` +- [ ] `to_atom/1` +- [ ] `to_existing_atom/1` +- [ ] `to_float/1` +- [ ] `to_integer/1` +- [ ] `to_integer/2` +- [ ] `to_string/1` +- [X] `to_tuple/1` +- [X] `update_at/3` +- [X] `wrap/1` +- [X] `zip/1` +## List.Chars +- [ ] `__protocol__/1` +- [ ] `impl_for/1` +- [ ] `impl_for!/1` +- [ ] `to_char_list/1` +- [ ] `to_charlist/1` +## List.Chars.Atom +- [ ] `__impl__/1` +- [ ] `to_charlist/1` +## List.Chars.BitString +- [ ] `__impl__/1` +- [ ] `to_charlist/1` +## List.Chars.Float +- [ ] `__impl__/1` +- [ ] `to_charlist/1` +## List.Chars.Integer +- [ ] `__impl__/1` +- [ ] `to_charlist/1` +## List.Chars.List +- [ ] `__impl__/1` +- [ ] `to_charlist/1` +## Macro +- [ ] `camelize/1` +- [ ] `decompose_call/1` +- [ ] `escape/1` +- [ ] `escape/2` +- [ ] `expand/2` +- [ ] `expand_once/2` +- [ ] `pipe/3` +- [ ] `pipe_warning/1` +- [ ] `postwalk/2` +- [ ] `postwalk/3` +- [ ] `prewalk/2` +- [ ] `prewalk/3` +- [ ] `to_string/1` +- [ ] `to_string/2` +- [ ] `traverse/4` +- [ ] `underscore/1` +- [ ] `unescape_string/1` +- [ ] `unescape_string/2` +- [ ] `unescape_tokens/1` +- [ ] `unescape_tokens/2` +- [ ] `unpipe/1` +- [ ] `update_meta/2` +- [ ] `validate/1` +- [ ] `var/2` +- [ ] `binary_ops/0` +- [ ] `unary_ops/0` +## Macro.Env +- [X] `__struct__/0` +- [X] `__struct__/1` +- [ ] `in_guard?/1` +- [ ] `in_match?/1` +- [ ] `location/1` +- [ ] `stacktrace/1` +## Map +- [X] `delete/2` +- [X] `drop/2` +- [X] `equal?/2` +- [X] `fetch/2` +- [X] `fetch!/2` +- [X] `from_struct/1` +- [X] `get/2` +- [X] `get/3` +- [X] `get_and_update/3` +- [ ] `get_and_update!/3` +- [X] `get_lazy/3` +- [X] `has_key?/2` +- [X] `keys/1` +- [X] `merge/2` +- [ ] `merge/3` +- [X] `new/0` +- [ ] `new/1` +- [ ] `new/2` +- [X] `pop/2` +- [X] `pop/3` +- [X] `pop_lazy/3` +- [X] `put/3` +- [X] `put_new/3` +- [X] `put_new_lazy/3` +- [X] `size/1` +- [X] `split/2` +- [X] `take/2` +- [X] `to_list/1` +- [X] `update/4` +- [X] `update!/3` +- [X] `values/1` +## MapSet +- [X] `__struct__/0` +- [X] `__struct__/1` +- [X] `delete/2` +- [X] `difference/2` +- [X] `disjoint?/2` +- [X] `equal?/2` +- [X] `intersection/2` +- [X] `member?/2` +- [X] `new/0` +- [ ] `new/1` +- [ ] `new/2` +- [X] `put/2` +- [X] `size/1` +- [X] `subset?/2` +- [X] `to_list/1` +- [X] `union/2` +## MatchError +- [ ] `__struct__/0` +- [ ] `__struct__/1` +- [ ] `exception/1` +- [ ] `message/1` +## Module +- [ ] `add_doc/5` +- [ ] `add_doc/6` +- [ ] `compile_doc/6` +- [ ] `concat/1` +- [ ] `concat/2` +- [ ] `create/3` +- [ ] `defines?/2` +- [ ] `defines?/3` +- [ ] `definitions_in/1` +- [ ] `definitions_in/2` +- [ ] `delete_attribute/2` +- [ ] `eval_quoted/2` +- [ ] `eval_quoted/3` +- [ ] `eval_quoted/4` +- [ ] `get_attribute/2` +- [ ] `get_attribute/3` +- [ ] `make_overridable/2` +- [ ] `open?/1` +- [ ] `overridable?/2` +- [ ] `put_attribute/3` +- [ ] `put_attribute/5` +- [ ] `register_attribute/3` +- [ ] `safe_concat/1` +- [ ] `safe_concat/2` +- [ ] `split/1` +- [ ] `store_typespec/3` +## NaiveDateTime +- [ ] `__struct__/0` +- [ ] `__struct__/1` +- [ ] `add/2` +- [ ] `add/3` +- [ ] `compare/2` +- [ ] `diff/2` +- [ ] `diff/3` +- [ ] `from_erl/1` +- [ ] `from_erl/2` +- [ ] `from_erl!/1` +- [ ] `from_erl!/2` +- [ ] `from_iso8601/1` +- [ ] `from_iso8601!/1` +- [ ] `new/2` +- [ ] `new/6` +- [ ] `new/7` +- [ ] `to_date/1` +- [ ] `to_erl/1` +- [ ] `to_iso8601/1` +- [ ] `to_string/1` +- [ ] `to_time/1` +- [ ] `utc_now/0` +## Node +- [ ] `alive?/0` +- [ ] `connect/1` +- [ ] `disconnect/1` +- [ ] `get_cookie/0` +- [ ] `list/0` +- [ ] `list/1` +- [ ] `monitor/2` +- [ ] `monitor/3` +- [ ] `ping/1` +- [ ] `self/0` +- [ ] `set_cookie/1` +- [ ] `set_cookie/2` +- [ ] `spawn/2` +- [ ] `spawn/3` +- [ ] `spawn/4` +- [ ] `spawn/5` +- [ ] `spawn_link/2` +- [ ] `spawn_link/4` +- [ ] `start/1` +- [ ] `start/2` +- [ ] `start/3` +- [ ] `stop/0` +## OptionParser +- [ ] `get_option_key/1` +- [ ] `next/1` +- [ ] `next/2` +- [ ] `parse/1` +- [ ] `parse/2` +- [ ] `parse!/1` +- [ ] `parse!/2` +- [ ] `parse_head/1` +- [ ] `parse_head/2` +- [ ] `parse_head!/1` +- [ ] `parse_head!/2` +- [ ] `split/1` +- [ ] `to_argv/1` +- [ ] `to_argv/2` +## OptionParser.ParseError +- [ ] `__struct__/0` +- [ ] `__struct__/1` +- [ ] `exception/1` +- [ ] `message/1` +## Path +- [ ] `absname/1` +- [ ] `absname/2` +- [ ] `basename/1` +- [ ] `basename/2` +- [ ] `dirname/1` +- [ ] `expand/1` +- [ ] `expand/2` +- [ ] `extname/1` +- [ ] `join/1` +- [ ] `join/2` +- [ ] `relative/1` +- [ ] `relative_to/2` +- [ ] `relative_to_cwd/1` +- [ ] `rootname/1` +- [ ] `rootname/2` +- [ ] `split/1` +- [ ] `type/1` +- [ ] `wildcard/1` +- [ ] `wildcard/2` +## Path.Wildcard +- [ ] `list_dir/1` +- [ ] `read_link_info/1` +## Port +- [ ] `close/1` +- [ ] `command/2` +- [ ] `command/3` +- [ ] `connect/2` +- [ ] `info/1` +- [ ] `info/2` +- [ ] `list/0` +- [ ] `open/2` ## Process -- [ ] alive?/1 -- [ ] cancel_timer/1 -- [ ] delete/1 -- [ ] demonitor/1 -- [ ] demonitor/2 -- [ ] exit/2 -- [ ] flag/2 -- [ ] flag/3 -- [ ] get/0 -- [ ] get/1 -- [ ] get/2 -- [ ] get_keys/0 -- [ ] get_keys/1 -- [ ] group_leader/0 -- [ ] group_leader/2 -- [ ] hibernate/3 -- [ ] info/1 -- [ ] info/2 -- [ ] link/1 -- [ ] list/0 -- [ ] monitor/1 -- [ ] put/2 -- [ ] read_timer/1 -- [ ] register/2 -- [ ] registered/0 -- [ ] send/3 -- [ ] send_after/3 -- [ ] send_after/4 -- [ ] sleep/1 -- [ ] spawn/2 -- [ ] spawn/4 -- [ ] unlink/1 -- [ ] unregister/1 -- [ ] whereis/1 +- [ ] `alive?/1` +- [ ] `cancel_timer/1` +- [ ] `delete/1` +- [ ] `demonitor/1` +- [ ] `demonitor/2` +- [ ] `exit/2` +- [ ] `flag/2` +- [ ] `flag/3` +- [ ] `get/0` +- [ ] `get/1` +- [ ] `get/2` +- [ ] `get_keys/0` +- [ ] `get_keys/1` +- [ ] `group_leader/0` +- [ ] `group_leader/2` +- [ ] `hibernate/3` +- [ ] `info/1` +- [ ] `info/2` +- [ ] `link/1` +- [ ] `list/0` +- [ ] `monitor/1` +- [ ] `put/2` +- [ ] `read_timer/1` +- [ ] `register/2` +- [ ] `registered/0` +- [ ] `send/3` +- [ ] `send_after/3` +- [ ] `send_after/4` +- [ ] `sleep/1` +- [ ] `spawn/2` +- [ ] `spawn/4` +- [ ] `unlink/1` +- [ ] `unregister/1` +- [ ] `whereis/1` ## Protocol -- [ ] __builtin__/0 -- [ ] __derive__/3 -- [ ] __ensure_defimpl__/3 -- [ ] __functions_spec__/1 -- [ ] __impl__/2 -- [ ] __protocol__/2 -- [ ] __spec__?/3 -- [ ] assert_impl!/2 -- [ ] assert_protocol!/1 -- [ ] consolidate/2 -- [ ] consolidated?/1 -- [ ] extract_impls/2 -- [ ] extract_protocols/1 -- [ ] def/1 -- [ ] derive/2 -- [ ] derive/3 -## UndefinedFunctionError -- [ ] __struct__/0 -- [ ] __struct__/1 -- [ ] exception/1 -- [ ] message/1 -## Version.InvalidVersionError -- [ ] __struct__/0 -- [ ] __struct__/1 -- [ ] exception/1 -- [ ] message/1 -## Task -- [ ] __struct__/0 -- [ ] __struct__/1 -- [ ] async/1 -- [ ] async/3 -- [ ] async_stream/2 -- [ ] async_stream/3 -- [ ] async_stream/4 -- [ ] async_stream/5 -- [ ] await/1 -- [ ] await/2 -- [ ] find/2 -- [ ] shutdown/1 -- [ ] shutdown/2 -- [ ] start/1 -- [ ] start/3 -- [ ] start_link/1 -- [ ] start_link/3 -- [ ] yield/1 -- [ ] yield/2 -- [ ] yield_many/1 -- [ ] yield_many/2 -## Float -- [ ] ceil/1 -- [ ] ceil/2 -- [ ] floor/1 -- [ ] floor/2 -- [ ] parse/1 -- [ ] ratio/1 -- [ ] round/1 -- [ ] round/2 -- [ ] to_char_list/1 -- [ ] to_char_list/2 -- [ ] to_charlist/1 -- [ ] to_string/1 -- [ ] to_string/2 -## Supervisor -- [ ] count_children/1 -- [ ] delete_child/2 -- [ ] restart_child/2 -- [ ] start_child/2 -- [ ] start_link/2 -- [ ] start_link/3 -- [ ] stop/1 -- [ ] stop/2 -- [ ] stop/3 -- [ ] terminate_child/2 -- [ ] which_children/1 -- [ ] __using__/1 -## Enumerable -- [X] __protocol__/1 -- [X] count/1 -- [X] impl_for/1 -- [X] impl_for!/1 -- [X] member?/2 -- [X] reduce/3 -## Enum -- [X] all?/1 -- [X] all?/2 -- [X] any?/1 -- [X] any?/2 -- [X] at/2 -- [X] at/3 -- [ ] chunk/2 -- [ ] chunk/3 -- [ ] chunk/4 -- [ ] chunk_by/2 -- [X] concat/1 -- [X] concat/2 -- [X] count/1 -- [X] count/2 -- [ ] dedup/1 -- [ ] dedup_by/2 -- [X] drop/2 -- [X] drop_every/2 -- [X] drop_while/2 -- [X] each/2 -- [X] empty?/1 -- [X] fetch/2 -- [X] fetch!/2 -- [X] filter/2 -- [X] filter_map/3 -- [X] find/2 -- [X] find/3 -- [ ] find_index/2 -- [ ] find_value/2 -- [ ] find_value/3 -- [ ] flat_map/2 -- [ ] flat_map_reduce/3 -- [ ] group_by/2 -- [ ] group_by/3 -- [ ] intersperse/2 -- [X] into/2 -- [X] into/3 -- [ ] join/1 -- [ ] join/2 -- [X] map/2 -- [ ] map_every/3 -- [ ] map_join/2 -- [ ] map_join/3 -- [X] map_reduce/3 -- [ ] max/1 -- [ ] max/2 -- [ ] max_by/2 -- [ ] max_by/3 -- [X] member?/2 -- [ ] min/1 -- [ ] min/2 -- [ ] min_by/2 -- [ ] min_by/3 -- [ ] min_max/1 -- [ ] min_max/2 -- [ ] min_max_by/2 -- [ ] min_max_by/3 -- [ ] partition/2 -- [ ] random/1 -- [X] reduce/2 -- [X] reduce/3 -- [ ] reduce_while/3 -- [ ] reject/2 -- [X] reverse/1 -- [X] reverse/2 -- [ ] reverse_slice/3 -- [ ] scan/2 -- [ ] scan/3 -- [ ] shuffle/1 -- [ ] slice/2 -- [ ] slice/3 -- [ ] sort/1 -- [ ] sort/2 -- [ ] sort_by/2 -- [ ] sort_by/3 -- [ ] split/2 -- [ ] split_while/2 -- [ ] split_with/2 -- [ ] sum/1 -- [X] take/2 -- [X] take_every/2 -- [ ] take_random/2 -- [X] take_while/2 -- [X] to_list/1 -- [ ] uniq/1 -- [ ] uniq/2 -- [ ] uniq_by/2 -- [ ] unzip/1 -- [ ] with_index/1 -- [ ] with_index/2 -- [ ] zip/1 -- [ ] zip/2 -## Keyword -- [ ] delete/2 -- [ ] delete/3 -- [ ] delete_first/2 -- [ ] drop/2 -- [ ] equal?/2 -- [ ] fetch/2 -- [ ] fetch!/2 -- [X] get/2 -- [X] get/3 -- [ ] get_and_update/3 -- [ ] get_and_update!/3 -- [ ] get_lazy/3 -- [ ] get_values/2 -- [X] has_key?/2 -- [ ] keys/1 -- [ ] keyword?/1 -- [ ] merge/2 -- [ ] merge/3 -- [X] new/0 -- [ ] new/1 -- [ ] new/2 -- [ ] pop/2 -- [ ] pop/3 -- [ ] pop_first/2 -- [ ] pop_first/3 -- [ ] pop_lazy/3 -- [ ] put/3 -- [ ] put_new/3 -- [ ] put_new_lazy/3 -- [ ] size/1 -- [ ] split/2 -- [ ] take/2 -- [ ] to_list/1 -- [ ] update/4 -- [ ] update!/3 -- [ ] values/1 -## Collectable.HashDict -- [ ] __impl__/1 -- [ ] into/1 -## Enumerable.File.Stream -- [ ] __impl__/1 -- [ ] count/1 -- [ ] member?/2 -- [ ] reduce/3 -## Access -- [ ] all/0 -- [ ] at/1 -- [ ] elem/1 -- [ ] fetch/2 -- [ ] get/2 -- [ ] get/3 -- [ ] get_and_update/3 -- [ ] key/1 -- [ ] key/2 -- [ ] key!/1 -- [ ] pop/2 -## IO.Stream -- [ ] __build__/3 -- [ ] __struct__/0 -- [ ] __struct__/1 -## Enumerable.Stream -- [ ] __impl__/1 -- [ ] count/1 -- [ ] member?/2 -- [ ] reduce/3 +- [ ] `__builtin__/0` +- [ ] `__derive__/3` +- [ ] `__ensure_defimpl__/3` +- [ ] `__functions_spec__/1` +- [ ] `__impl__/2` +- [ ] `__protocol__/2` +- [ ] `__spec__?/3` +- [ ] `assert_impl!/2` +- [ ] `assert_protocol!/1` +- [ ] `consolidate/2` +- [ ] `consolidated?/1` +- [ ] `extract_impls/2` +- [ ] `extract_protocols/1` +- [ ] `def/1` +- [ ] `derive/2` +- [ ] `derive/3` +## Protocol.UndefinedError +- [ ] `__struct__/0` +- [ ] `__struct__/1` +- [ ] `exception/1` +- [ ] `message/1` +## Range +- [X] `__struct__/0` +- [X] `__struct__/1` +- [X] `new/2` +- [X] `range?/1` +## Record +- [ ] `__access__/4` +- [ ] `__access__/5` +- [ ] `__fields__/2` +- [ ] `__keyword__/3` +- [ ] `extract/2` +- [ ] `extract_all/1` +- [ ] `defrecord/2` +- [ ] `defrecord/3` +- [ ] `defrecordp/2` +- [ ] `defrecordp/3` +- [ ] `is_record/1` +- [ ] `is_record/2` +## Record.Extractor +- [ ] `extract/2` +- [ ] `extract_all/1` +## Regex +- [ ] `__struct__/0` +- [ ] `__struct__/1` +- [X] `compile/1` +- [X] `compile/2` +- [X] `compile!/1` +- [X] `compile!/2` +- [ ] `escape/1` +- [X] `match?/2` +- [ ] `named_captures/2` +- [ ] `named_captures/3` +- [ ] `names/1` +- [X] `opts/1` +- [ ] `re_pattern/1` +- [X] `regex?/1` +- [X] `replace/3` +- [X] `replace/4` +- [X] `run/2` +- [X] `run/3` +- [X] `scan/2` +- [X] `scan/3` +- [X] `source/1` +- [ ] `split/2` +- [ ] `split/3` +- [ ] `unescape_map/1` +## Regex.CompileError +- [ ] `__struct__/0` +- [ ] `__struct__/1` +- [ ] `exception/1` +- [ ] `message/1` +## Registry +- [ ] `dispatch/3` +- [ ] `keys/2` +- [ ] `lookup/2` +- [ ] `match/3` +- [ ] `meta/2` +- [ ] `put_meta/3` +- [ ] `register/3` +- [ ] `register_name/2` +- [ ] `send/2` +- [ ] `start_link/2` +- [ ] `start_link/3` +- [ ] `unregister/2` +- [ ] `unregister_name/1` +- [ ] `update_value/3` +- [ ] `whereis_name/1` +## RuntimeError +- [X] `__struct__/0` +- [X] `__struct__/1` +- [X] `exception/1` +- [X] `message/1` +## Set +- [ ] `delete/2` +- [ ] `difference/2` +- [ ] `disjoint?/2` +- [ ] `empty/1` +- [ ] `equal?/2` +- [ ] `intersection/2` +- [ ] `member?/2` +- [ ] `put/2` +- [ ] `size/1` +- [ ] `subset?/2` +- [ ] `to_list/1` +- [ ] `union/2` ## Stream -- [ ] __struct__/0 -- [ ] __struct__/1 -- [ ] chunk/2 -- [ ] chunk/3 -- [ ] chunk/4 -- [ ] chunk_by/2 -- [ ] concat/1 -- [ ] concat/2 -- [ ] cycle/1 -- [ ] dedup/1 -- [ ] dedup_by/2 -- [ ] drop/2 -- [ ] drop_every/2 -- [ ] drop_while/2 -- [ ] each/2 -- [ ] filter/2 -- [ ] filter_map/3 -- [ ] flat_map/2 -- [ ] interval/1 -- [ ] into/2 -- [ ] into/3 -- [ ] iterate/2 -- [ ] map/2 -- [ ] map_every/3 -- [ ] reject/2 -- [ ] repeatedly/1 -- [ ] resource/3 -- [ ] run/1 -- [ ] scan/2 -- [ ] scan/3 -- [ ] take/2 -- [ ] take_every/2 -- [ ] take_while/2 -- [ ] timer/1 -- [ ] transform/3 -- [ ] transform/4 -- [ ] unfold/2 -- [ ] uniq/1 -- [ ] uniq/2 -- [ ] uniq_by/2 -- [ ] with_index/1 -- [ ] with_index/2 -- [ ] zip/1 -- [ ] zip/2 +- [ ] `__struct__/0` +- [ ] `__struct__/1` +- [ ] `chunk/2` +- [ ] `chunk/3` +- [ ] `chunk/4` +- [ ] `chunk_by/2` +- [ ] `concat/1` +- [ ] `concat/2` +- [ ] `cycle/1` +- [ ] `dedup/1` +- [ ] `dedup_by/2` +- [ ] `drop/2` +- [ ] `drop_every/2` +- [ ] `drop_while/2` +- [ ] `each/2` +- [ ] `filter/2` +- [ ] `filter_map/3` +- [ ] `flat_map/2` +- [ ] `interval/1` +- [ ] `into/2` +- [ ] `into/3` +- [ ] `iterate/2` +- [ ] `map/2` +- [ ] `map_every/3` +- [ ] `reject/2` +- [ ] `repeatedly/1` +- [ ] `resource/3` +- [ ] `run/1` +- [ ] `scan/2` +- [ ] `scan/3` +- [ ] `take/2` +- [ ] `take_every/2` +- [ ] `take_while/2` +- [ ] `timer/1` +- [ ] `transform/3` +- [ ] `transform/4` +- [ ] `unfold/2` +- [ ] `uniq/1` +- [ ] `uniq/2` +- [ ] `uniq_by/2` +- [ ] `with_index/1` +- [ ] `with_index/2` +- [ ] `zip/1` +- [ ] `zip/2` +## String +- [X] `at/2` +- [X] `capitalize/1` +- [ ] `chunk/2` +- [X] `codepoints/1` +- [X] `contains?/2` +- [X] `downcase/1` +- [X] `duplicate/2` +- [X] `ends_with?/2` +- [ ] `equivalent?/2` +- [X] `first/1` +- [X] `graphemes/1` +- [ ] `jaro_distance/2` +- [X] `last/1` +- [X] `length/1` +- [ ] `ljust/2` +- [ ] `ljust/3` +- [ ] `lstrip/1` +- [ ] `lstrip/2` +- [X] `match?/2` +- [ ] `myers_difference/2` +- [X] `next_codepoint/1` +- [X] `next_grapheme/1` +- [ ] `next_grapheme_size/1` +- [ ] `normalize/2` +- [ ] `pad_leading/2` +- [ ] `pad_leading/3` +- [ ] `pad_trailing/2` +- [ ] `pad_trailing/3` +- [ ] `printable?/1` +- [ ] `replace/3` +- [ ] `replace/4` +- [ ] `replace_leading/3` +- [ ] `replace_prefix/3` +- [ ] `replace_suffix/3` +- [ ] `replace_trailing/3` +- [X] `reverse/1` +- [ ] `rjust/2` +- [ ] `rjust/3` +- [ ] `rstrip/1` +- [ ] `rstrip/2` +- [ ] `slice/2` +- [ ] `slice/3` +- [X] `split/1` +- [X] `split/2` +- [X] `split/3` +- [ ] `split_at/2` +- [ ] `splitter/2` +- [ ] `splitter/3` +- [X] `starts_with?/2` +- [ ] `strip/1` +- [ ] `strip/2` +- [X] `to_atom/1` +- [X] `to_char_list/1` +- [ ] `to_charlist/1` +- [X] `to_existing_atom/1` +- [X] `to_float/1` +- [X] `to_integer/1` +- [X] `to_integer/2` +- [ ] `trim/1` +- [ ] `trim/2` +- [ ] `trim_leading/1` +- [ ] `trim_leading/2` +- [ ] `trim_trailing/1` +- [ ] `trim_trailing/2` +- [X] `upcase/1` +- [ ] `valid?/1` +- [X] `valid_character?/1` +## String.Casing +- [ ] `downcase/1` +- [ ] `titlecase_once/1` +- [ ] `upcase/1` +## String.Chars +- [X] `__protocol__/1` +- [X] `impl_for/1` +- [X] `impl_for!/1` +- [X] `to_string/1` +## String.Chars.Atom +- [X] `__impl__/1` +- [X] `to_string/1` +## String.Chars.BitString +- [X] `__impl__/1` +- [X] `to_string/1` +## String.Chars.Date +- [ ] `__impl__/1` +- [ ] `to_string/1` +## String.Chars.DateTime +- [ ] `__impl__/1` +- [ ] `to_string/1` +## String.Chars.Float +- [X] `__impl__/1` +- [X] `to_string/1` +## String.Chars.Integer +- [X] `__impl__/1` +- [X] `to_string/1` +## String.Chars.List +- [X] `__impl__/1` +- [X] `to_string/1` +## String.Chars.NaiveDateTime +- [ ] `__impl__/1` +- [ ] `to_string/1` +## String.Chars.Time +- [ ] `__impl__/1` +- [ ] `to_string/1` +## String.Chars.URI +- [ ] `__impl__/1` +- [ ] `to_string/1` +## String.Chars.Version +- [ ] `__impl__/1` +- [ ] `to_string/1` +## String.Chars.Version.Requirement +- [ ] `__impl__/1` +- [ ] `to_string/1` +## String.Unicode +- [ ] `codepoints/1` +- [ ] `graphemes/1` +- [ ] `length/1` +- [ ] `next_codepoint/1` +- [ ] `next_grapheme_size/1` +- [ ] `split_at/2` +- [ ] `version/0` +## StringIO +- [ ] `close/1` +- [ ] `code_change/3` +- [ ] `contents/1` +- [ ] `flush/1` +- [ ] `handle_call/3` +- [ ] `handle_cast/2` +- [ ] `handle_info/2` +- [ ] `init/1` +- [ ] `open/1` +- [ ] `open/2` +- [ ] `terminate/2` +## Supervisor +- [ ] `count_children/1` +- [ ] `delete_child/2` +- [ ] `restart_child/2` +- [ ] `start_child/2` +- [ ] `start_link/2` +- [ ] `start_link/3` +- [ ] `stop/1` +- [ ] `stop/2` +- [ ] `stop/3` +- [ ] `terminate_child/2` +- [ ] `which_children/1` +- [ ] `__using__/1` +## Supervisor.Spec +- [ ] `supervise/2` +- [ ] `supervisor/2` +- [ ] `supervisor/3` +- [ ] `worker/2` +- [ ] `worker/3` +## SyntaxError +- [ ] `__struct__/0` +- [ ] `__struct__/1` +- [ ] `exception/1` +- [ ] `message/1` +## System +- [ ] `argv/0` +- [ ] `argv/1` +- [ ] `at_exit/1` +- [ ] `build_info/0` +- [ ] `cmd/2` +- [ ] `cmd/3` +- [ ] `compiled_endianness/0` +- [ ] `convert_time_unit/3` +- [ ] `cwd/0` +- [ ] `cwd!/0` +- [ ] `delete_env/1` +- [ ] `endianness/0` +- [ ] `find_executable/1` +- [ ] `get_env/0` +- [ ] `get_env/1` +- [ ] `get_pid/0` +- [ ] `halt/0` +- [ ] `halt/1` +- [ ] `monotonic_time/0` +- [ ] `monotonic_time/1` +- [ ] `os_time/0` +- [ ] `os_time/1` +- [ ] `otp_release/0` +- [ ] `put_env/1` +- [ ] `put_env/2` +- [ ] `schedulers/0` +- [ ] `schedulers_online/0` +- [ ] `stacktrace/0` +- [ ] `system_time/0` +- [ ] `system_time/1` +- [ ] `time_offset/0` +- [ ] `time_offset/1` +- [ ] `tmp_dir/0` +- [ ] `tmp_dir!/0` +- [ ] `unique_integer/0` +- [ ] `unique_integer/1` +- [ ] `user_home/0` +- [ ] `user_home!/0` +- [ ] `version/0` +## SystemLimitError +- [ ] `__struct__/0` +- [ ] `__struct__/1` +- [ ] `exception/1` +- [ ] `message/1` +## Task +- [ ] `__struct__/0` +- [ ] `__struct__/1` +- [ ] `async/1` +- [ ] `async/3` +- [ ] `async_stream/2` +- [ ] `async_stream/3` +- [ ] `async_stream/4` +- [ ] `async_stream/5` +- [ ] `await/1` +- [ ] `await/2` +- [ ] `find/2` +- [ ] `shutdown/1` +- [ ] `shutdown/2` +- [ ] `start/1` +- [ ] `start/3` +- [ ] `start_link/1` +- [ ] `start_link/3` +- [ ] `yield/1` +- [ ] `yield/2` +- [ ] `yield_many/1` +- [ ] `yield_many/2` ## Task.Supervisor -- [ ] async/2 -- [ ] async/4 -- [ ] async_nolink/2 -- [ ] async_nolink/4 -- [ ] async_stream/3 -- [ ] async_stream/4 -- [ ] async_stream/5 -- [ ] async_stream/6 -- [ ] async_stream_nolink/3 -- [ ] async_stream_nolink/4 -- [ ] async_stream_nolink/5 -- [ ] async_stream_nolink/6 -- [ ] children/1 -- [ ] start_child/2 -- [ ] start_child/4 -- [ ] start_link/0 -- [ ] start_link/1 -- [ ] terminate_child/2 -## Inspect.Version.Requirement -- [ ] __impl__/1 -- [ ] inspect/2 +- [ ] `async/2` +- [ ] `async/4` +- [ ] `async_nolink/2` +- [ ] `async_nolink/4` +- [ ] `async_stream/3` +- [ ] `async_stream/4` +- [ ] `async_stream/5` +- [ ] `async_stream/6` +- [ ] `async_stream_nolink/3` +- [ ] `async_stream_nolink/4` +- [ ] `async_stream_nolink/5` +- [ ] `async_stream_nolink/6` +- [ ] `children/1` +- [ ] `start_child/2` +- [ ] `start_child/4` +- [ ] `start_link/0` +- [ ] `start_link/1` +- [ ] `terminate_child/2` +## Time +- [ ] `__struct__/0` +- [ ] `__struct__/1` +- [ ] `compare/2` +- [ ] `from_erl/1` +- [ ] `from_erl/2` +- [ ] `from_erl!/1` +- [ ] `from_erl!/2` +- [ ] `from_iso8601/1` +- [ ] `from_iso8601!/1` +- [ ] `new/3` +- [ ] `new/4` +- [ ] `to_erl/1` +- [ ] `to_iso8601/1` +- [ ] `to_string/1` +- [ ] `utc_now/0` +## TokenMissingError +- [ ] `__struct__/0` +- [ ] `__struct__/1` +- [ ] `exception/1` +- [ ] `message/1` ## TryClauseError -- [ ] __struct__/0 -- [ ] __struct__/1 -- [ ] exception/1 -- [ ] message/1 -## Version -- [ ] __struct__/0 -- [ ] __struct__/1 -- [ ] compare/2 -- [ ] compile_requirement/1 -- [ ] match?/2 -- [ ] match?/3 -- [ ] parse/1 -- [ ] parse!/1 -- [ ] parse_requirement/1 -## Record -- [ ] __access__/4 -- [ ] __access__/5 -- [ ] __fields__/2 -- [ ] __keyword__/3 -- [ ] extract/2 -- [ ] extract_all/1 -- [ ] defrecord/2 -- [ ] defrecord/3 -- [ ] defrecordp/2 -- [ ] defrecordp/3 -- [ ] is_record/1 -- [ ] is_record/2 -## CondClauseError -- [ ] __struct__/0 -- [ ] __struct__/1 -- [ ] exception/1 -- [ ] message/1 -## Inspect.Integer -- [ ] __impl__/1 -- [ ] inspect/2 -## List -- [X] delete/2 -- [X] delete_at/2 -- [X] duplicate/2 -- [X] first/1 -- [X] flatten/1 -- [X] flatten/2 -- [X] foldl/3 -- [X] foldr/3 -- [X] insert_at/3 -- [X] keydelete/3 -- [X] keyfind/3 -- [X] keyfind/4 -- [X] keymember?/3 -- [X] keyreplace/4 -- [ ] keysort/2 -- [ ] keystore/4 -- [ ] keytake/3 -- [X] last/1 -- [ ] myers_difference/2 -- [ ] pop_at/2 -- [ ] pop_at/3 -- [X] replace_at/3 -- [ ] to_atom/1 -- [ ] to_existing_atom/1 -- [ ] to_float/1 -- [ ] to_integer/1 -- [ ] to_integer/2 -- [ ] to_string/1 -- [X] to_tuple/1 -- [X] update_at/3 -- [X] wrap/1 -- [X] zip/1 -## Regex -- [ ] __struct__/0 -- [ ] __struct__/1 -- [X] compile/1 -- [X] compile/2 -- [X] compile!/1 -- [X] compile!/2 -- [ ] escape/1 -- [X] match?/2 -- [ ] named_captures/2 -- [ ] named_captures/3 -- [ ] names/1 -- [X] opts/1 -- [ ] re_pattern/1 -- [X] regex?/1 -- [X] replace/3 -- [X] replace/4 -- [X] run/2 -- [X] run/3 -- [X] scan/2 -- [X] scan/3 -- [X] source/1 -- [ ] split/2 -- [ ] split/3 -- [ ] unescape_map/1 -## Collectable.IO.Stream -- [ ] __impl__/1 -- [ ] into/1 -## File.Error -- [ ] __struct__/0 -- [ ] __struct__/1 -- [ ] exception/1 -- [ ] message/1 -## Inspect.Algebra -- [ ] break/0 -- [ ] break/1 -- [ ] color/3 -- [ ] concat/1 -- [ ] concat/2 -- [ ] empty/0 -- [ ] fold_doc/2 -- [ ] format/2 -- [ ] glue/2 -- [ ] glue/3 -- [ ] group/1 -- [ ] line/2 -- [ ] nest/2 -- [ ] space/2 -- [ ] surround/3 -- [ ] surround_many/5 -- [ ] surround_many/6 -- [ ] to_doc/2 -## Node -- [ ] alive?/0 -- [ ] connect/1 -- [ ] disconnect/1 -- [ ] get_cookie/0 -- [ ] list/0 -- [ ] list/1 -- [ ] monitor/2 -- [ ] monitor/3 -- [ ] ping/1 -- [ ] self/0 -- [ ] set_cookie/1 -- [ ] set_cookie/2 -- [ ] spawn/2 -- [ ] spawn/3 -- [ ] spawn/4 -- [ ] spawn/5 -- [ ] spawn_link/2 -- [ ] spawn_link/4 -- [ ] start/1 -- [ ] start/2 -- [ ] start/3 -- [ ] stop/0 -## File.CopyError -- [ ] __struct__/0 -- [ ] __struct__/1 -- [ ] exception/1 -- [ ] message/1 -## Port -- [ ] close/1 -- [ ] command/2 -- [ ] command/3 -- [ ] connect/2 -- [ ] info/1 -- [ ] info/2 -- [ ] list/0 -- [ ] open/2 -## Enumerable.MapSet -- [ ] __impl__/1 -- [ ] count/1 -- [ ] member?/2 -- [ ] reduce/3 -## Inspect.Stream -- [ ] __impl__/1 -- [ ] inspect/2 -## Kernel.ParallelRequire -- [ ] files/1 -- [ ] files/2 -## FunctionClauseError -- [ ] __struct__/0 -- [ ] __struct__/1 -- [ ] exception/1 -- [ ] message/1 -## Enumerable.Function -- [ ] __impl__/1 -- [ ] count/1 -- [ ] member?/2 -- [ ] reduce/3 -## GenServer -- [ ] abcast/2 -- [ ] abcast/3 -- [ ] call/2 -- [ ] call/3 -- [ ] cast/2 -- [ ] multi_call/2 -- [ ] multi_call/3 -- [ ] multi_call/4 -- [ ] reply/2 -- [ ] start/2 -- [ ] start/3 -- [ ] start_link/2 -- [ ] start_link/3 -- [ ] stop/1 -- [ ] stop/2 -- [ ] stop/3 -- [ ] whereis/1 -- [ ] __using__/1 -## List.Chars -- [ ] __protocol__/1 -- [ ] impl_for/1 -- [ ] impl_for!/1 -- [ ] to_char_list/1 -- [ ] to_charlist/1 -## Inspect.Atom -- [ ] __impl__/1 -- [ ] inspect/1 -- [ ] inspect/2 -## Inspect.HashDict -- [ ] __impl__/1 -- [ ] inspect/2 -## Enumerable.IO.Stream -- [ ] __impl__/1 -- [ ] count/1 -- [ ] member?/2 -- [ ] reduce/3 -## Kernel.Typespec -- [ ] beam_callbacks/1 -- [ ] beam_specs/1 -- [ ] beam_typedocs/1 -- [ ] beam_types/1 -- [ ] define_spec/3 -- [ ] define_type/3 -- [ ] define_type/4 -- [ ] defines_callback?/3 -- [ ] defines_spec?/3 -- [ ] defines_type?/3 -- [ ] defspec/3 -- [ ] deftype/3 -- [ ] spec_to_ast/2 -- [ ] spec_to_signature/1 -- [ ] translate_spec/3 -- [ ] translate_type/3 -- [ ] type_to_ast/1 -- [ ] type_to_signature/1 -- [ ] defcallback/1 -- [ ] defmacrocallback/1 -- [ ] defopaque/1 -- [ ] defoptional_callbacks/1 -- [ ] defspec/1 -- [ ] deftype/1 -- [ ] deftypep/1 -## KeyError -- [ ] __struct__/0 -- [ ] __struct__/1 -- [ ] exception/1 -- [ ] message/1 -## MapSet -- [X] __struct__/0 -- [X] __struct__/1 -- [X] delete/2 -- [X] difference/2 -- [X] disjoint?/2 -- [X] equal?/2 -- [X] intersection/2 -- [X] member?/2 -- [X] new/0 -- [ ] new/1 -- [ ] new/2 -- [X] put/2 -- [X] size/1 -- [X] subset?/2 -- [X] to_list/1 -- [X] union/2 -## Macro -- [ ] camelize/1 -- [ ] decompose_call/1 -- [ ] escape/1 -- [ ] escape/2 -- [ ] expand/2 -- [ ] expand_once/2 -- [ ] pipe/3 -- [ ] pipe_warning/1 -- [ ] postwalk/2 -- [ ] postwalk/3 -- [ ] prewalk/2 -- [ ] prewalk/3 -- [ ] to_string/1 -- [ ] to_string/2 -- [ ] traverse/4 -- [ ] underscore/1 -- [ ] unescape_string/1 -- [ ] unescape_string/2 -- [ ] unescape_tokens/1 -- [ ] unescape_tokens/2 -- [ ] unpipe/1 -- [ ] update_meta/2 -- [ ] validate/1 -- [ ] var/2 -- [ ] binary_ops/0 -- [ ] unary_ops/0 +- [ ] `__struct__/0` +- [ ] `__struct__/1` +- [ ] `exception/1` +- [ ] `message/1` +## Tuple +- [X] `append/2` +- [X] `delete_at/2` +- [X] `duplicate/2` +- [X] `insert_at/3` +- [X] `to_list/1` ## URI -- [ ] __struct__/0 -- [ ] __struct__/1 -- [ ] char_reserved?/1 -- [ ] char_unescaped?/1 -- [ ] char_unreserved?/1 -- [ ] decode/1 -- [ ] decode_query/1 -- [ ] decode_query/2 -- [ ] decode_www_form/1 -- [ ] default_port/1 -- [ ] default_port/2 -- [ ] encode/1 -- [ ] encode/2 -- [ ] encode_query/1 -- [ ] encode_www_form/1 -- [ ] merge/2 -- [ ] parse/1 -- [ ] path_to_segments/1 -- [ ] query_decoder/1 -- [ ] to_string/1 -## Inspect.Opts -- [ ] __struct__/0 -- [ ] __struct__/1 -## Atom -- [X] to_char_list/1 -- [ ] to_charlist/1 -- [X] to_string/1 -## TokenMissingError -- [ ] __struct__/0 -- [ ] __struct__/1 -- [ ] exception/1 -- [ ] message/1 -## BadBooleanError -- [ ] __struct__/0 -- [ ] __struct__/1 -- [ ] exception/1 -- [ ] message/1 -## String.Chars.Date -- [ ] __impl__/1 -- [ ] to_string/1 -## Set -- [ ] delete/2 -- [ ] difference/2 -- [ ] disjoint?/2 -- [ ] empty/1 -- [ ] equal?/2 -- [ ] intersection/2 -- [ ] member?/2 -- [ ] put/2 -- [ ] size/1 -- [ ] subset?/2 -- [ ] to_list/1 -- [ ] union/2 -## WithClauseError -- [ ] __struct__/0 -- [ ] __struct__/1 -- [ ] exception/1 -- [ ] message/1 -## List.Chars.Atom -- [ ] __impl__/1 -- [ ] to_charlist/1 +- [ ] `__struct__/0` +- [ ] `__struct__/1` +- [ ] `char_reserved?/1` +- [ ] `char_unescaped?/1` +- [ ] `char_unreserved?/1` +- [ ] `decode/1` +- [ ] `decode_query/1` +- [ ] `decode_query/2` +- [ ] `decode_www_form/1` +- [ ] `default_port/1` +- [ ] `default_port/2` +- [ ] `encode/1` +- [ ] `encode/2` +- [ ] `encode_query/1` +- [ ] `encode_www_form/1` +- [ ] `merge/2` +- [ ] `parse/1` +- [ ] `path_to_segments/1` +- [ ] `query_decoder/1` +- [ ] `to_string/1` +## UndefinedFunctionError +- [ ] `__struct__/0` +- [ ] `__struct__/1` +- [ ] `exception/1` +- [ ] `message/1` +## UnicodeConversionError +- [ ] `__struct__/0` +- [ ] `__struct__/1` +- [ ] `exception/1` +- [ ] `message/1` +## Version +- [ ] `__struct__/0` +- [ ] `__struct__/1` +- [ ] `compare/2` +- [ ] `compile_requirement/1` +- [ ] `match?/2` +- [ ] `match?/3` +- [ ] `parse/1` +- [ ] `parse!/1` +- [ ] `parse_requirement/1` ## Version.InvalidRequirementError -- [ ] __struct__/0 -- [ ] __struct__/1 -- [ ] exception/1 -- [ ] message/1 -## Application -- [ ] app_dir/1 -- [ ] app_dir/2 -- [ ] delete_env/2 -- [ ] delete_env/3 -- [ ] ensure_all_started/1 -- [ ] ensure_all_started/2 -- [ ] ensure_started/1 -- [ ] ensure_started/2 -- [ ] fetch_env/2 -- [ ] fetch_env!/2 -- [ ] format_error/1 -- [ ] get_all_env/1 -- [ ] get_application/1 -- [ ] get_env/2 -- [ ] get_env/3 -- [ ] load/1 -- [ ] loaded_applications/0 -- [ ] put_env/3 -- [ ] put_env/4 -- [ ] spec/1 -- [ ] spec/2 -- [ ] start/1 -- [ ] start/2 -- [ ] started_applications/0 -- [ ] started_applications/1 -- [ ] stop/1 -- [ ] unload/1 -- [ ] __using__/1 -## Inspect.PID -- [ ] __impl__/1 -- [ ] inspect/2 -## Calendar.ISO -- [ ] date/3 -- [ ] date_to_iso8601/3 -- [ ] date_to_string/3 -- [ ] datetime_to_iso8601/11 -- [ ] datetime_to_string/11 -- [ ] day_of_week/3 -- [ ] days_in_month/2 -- [ ] from_unix/2 -- [ ] leap_year?/1 -- [ ] naive_datetime_to_iso8601/7 -- [ ] naive_datetime_to_string/7 -- [ ] parse_microsecond/1 -- [ ] parse_offset/1 -- [ ] time_to_iso8601/4 -- [ ] time_to_string/4 +- [ ] `__struct__/0` +- [ ] `__struct__/1` +- [ ] `exception/1` +- [ ] `message/1` +## Version.InvalidVersionError +- [ ] `__struct__/0` +- [ ] `__struct__/1` +- [ ] `exception/1` +- [ ] `message/1` +## Version.Requirement +- [ ] `__struct__/0` +- [ ] `__struct__/1` +## WithClauseError +- [ ] `__struct__/0` +- [ ] `__struct__/1` +- [ ] `exception/1` +- [ ] `message/1` diff --git a/lib/elixir_script/gen/supported.ex b/lib/elixir_script/gen/supported.ex index 17ec8263..904ac938 100644 --- a/lib/elixir_script/gen/supported.ex +++ b/lib/elixir_script/gen/supported.ex @@ -26,34 +26,39 @@ defmodule ElixirScript.Gen.Supported do def write_to_file(file) do IO.puts(file, "# Supported Elixir Modules") IO.puts(file, "List all public modules in the Elixir Standard Libary. If a function or macro is supported in ElixirScript, it is checked") - module_map = get_module_map() + module_map = get_module_list() Enum.each(module_map, fn({elixir_module, elixir_script_module}) -> IO.puts(file, "## #{inspect elixir_module}") exports = elixir_module.__info__(:functions) ++ elixir_module.__info__(:macros) - elixir_script_exports = if Code.ensure_loaded?(elixir_script_module) do - elixir_script_module.__info__(:functions) ++ elixir_script_module.__info__(:macros) - else - [] + + elixir_script_exports = cond do + elixir_script_module == ElixirScript.Kernel.SpecialForms -> + extra(elixir_script_module) + Code.ensure_loaded?(elixir_script_module) -> + elixir_script_module.__info__(:functions) ++ elixir_script_module.__info__(:macros) ++ extra(elixir_script_module) + true -> + [] end Enum.each(exports, fn({func, arity}) -> if Enum.member?(elixir_script_exports, {func, arity}) do - IO.puts(file, "- [X] #{func}/#{arity}") + IO.puts(file, "- [X] `#{func}/#{arity}`") else - IO.puts(file, "- [ ] #{func}/#{arity}") + IO.puts(file, "- [ ] `#{func}/#{arity}`") end end) end) end - defp get_module_map() do + defp get_module_list() do Application.spec(:elixir, :modules) |> Enum.filter(&is_public(&1)) - |> Enum.reduce(Map.new, fn(x, acc) -> + |> Enum.sort(fn(x, y) -> to_string(x) >= to_string(y) end) + |> Enum.reduce(Keyword.new, fn(x, acc) -> try do elixirscript_module = (["ElixirScript"] ++ Module.split(x)) |> Module.concat() - Map.put(acc, x, elixirscript_module) + Keyword.put(acc, x, elixirscript_module) rescue FunctionClauseError -> acc @@ -68,4 +73,93 @@ defmodule ElixirScript.Gen.Supported do defp is_public(_) do true end + + defp extra(ElixirScript.Kernel.SpecialForms) do + [ + %: 2, + %{}: 1, + &: 1, + ".": 2, + "::": 2, + <<>>: 1, + =: 2, + ^: 1, + __CALLER__: 0, + __DIR__: 0, + __ENV__: 0, + __MODULE__: 0, + __aliases__: 1, + __block__: 1, + alias: 2, + case: 2, + cond: 1, + fn: 1, + for: 1, + import: 2, + quote: 2, + require: 2, + super: 1, + try: 1, + unquote: 1, + unquote_splicing: 1, + with: 1, + {}: 1, + ] + end + + defp extra(ElixirScript.Kernel) do + [ + !=: 2, + !==: 2, + *: 2, + +: 1, + +: 2, + ++: 2, + -: 1, + -: 2, + --: 2, + /: 2, + <: 2, + <=: 2, + ==: 2, + ===: 2, + =~: 2, + >: 2, + >=: 2, + div: 2, + rem: 2, + !: 1, + &&: 2, + <>: 2, + @: 1, + and: 2, + def: 1, + def: 2, + defdelegate: 2, + defexception: 1, + defimpl: 2, + defimpl: 3, + defmacro: 1, + defmacro: 2, + defmacrop: 1, + defmacrop: 2, + defmodule: 2, + defoverridable: 1, + defp: 1, + defp: 2, + defprotocol: 2, + defstruct: 1, + raise: 1, + raise: 2, + or: 2, + use: 1, + use: 2, + ||: 2, + ] + end + + + defp extra(_) do + [] + end end \ No newline at end of file From 2b38d06a639c30416750213f71b22c6a8097ba92 Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Tue, 11 Apr 2017 22:04:00 -0500 Subject: [PATCH 524/860] Add __info__ to each module --- lib/elixir_script/translator.ex | 9 +++-- .../translator/kernel/defmodule.ex | 38 ++++++++++++++++++- test/translator/defmodule_test.exs | 20 +++++++--- 3 files changed, 56 insertions(+), 11 deletions(-) diff --git a/lib/elixir_script/translator.ex b/lib/elixir_script/translator.ex index d8c11001..d71914a9 100644 --- a/lib/elixir_script/translator.ex +++ b/lib/elixir_script/translator.ex @@ -523,15 +523,18 @@ defmodule ElixirScript.Translator do end defp do_translate({function, _, [{:when, _, [{name, _, _params} | _guards] }, _] } = ast, env) when function in @generator_types do - Def.process_function(name, [ast], %{ env | context: :generator}) + {js_ast, _} = Def.process_function(name, [ast], %{ env | context: :generator}) + {js_ast, env} end defp do_translate({function, _, [{name, _, params}, _]} = ast, env) when function in @generator_types and is_atom(params) do - Def.process_function(name, [ast], %{ env | context: :generator}) + {js_ast, _} = Def.process_function(name, [ast], %{ env | context: :generator}) + {js_ast, env} end defp do_translate({function, _, [{name, _, _params}, _]} = ast, env) when function in @generator_types do - Def.process_function(name, [ast], %{ env | context: :generator}) + {js_ast, _} = Def.process_function(name, [ast], %{ env | context: :generator}) + {js_ast, env} end defp do_translate({function, _, [{:when, _, [{name, _, _params} | _guards] }, _] } = ast, env) when function in @function_types do diff --git a/lib/elixir_script/translator/kernel/defmodule.ex b/lib/elixir_script/translator/kernel/defmodule.ex index dd2c76ba..eb77bc00 100644 --- a/lib/elixir_script/translator/kernel/defmodule.ex +++ b/lib/elixir_script/translator/kernel/defmodule.ex @@ -57,6 +57,8 @@ defmodule ElixirScript.Translator.Defmodule do [] end + info_prop = [JS.property(Identifier.make_identifier("__info__"), Identifier.make_identifier("__info__"), :init, true)] + body = Enum.map(body, fn(x) -> case x do %ESTree.CallExpression{} -> @@ -69,7 +71,7 @@ defmodule ElixirScript.Translator.Defmodule do body = Group.inflate_groups(body) exported_object = JS.object_expression( - struct_prop ++ + info_prop ++ struct_prop ++ Enum.map(exported_functions, fn({key, _value}) -> JS.property(Identifier.make_identifier(key), Identifier.make_identifier(key), :init, true) end) @@ -78,7 +80,7 @@ defmodule ElixirScript.Translator.Defmodule do exported_functions = Enum.map(exported_functions, fn({_key, value}) -> value end) private_functions = Enum.map(private_functions, fn({_key, value}) -> value end) - body = private_functions ++ exported_functions ++ body + body = private_functions ++ exported_functions ++ [make_info_function(env)] ++ body {body, exported_object} end @@ -230,4 +232,36 @@ defmodule ElixirScript.Translator.Defmodule do JS.variable_declaration([declarator], :const) end + def make_info_function(env) do + functions = Keyword.get(env.functions, env.module, []) + macros = Keyword.get(env.macros, env.module, []) + + info_case = quote do + case kind do + :functions -> + unquote(functions) + :macros -> + unquote(macros) + :module -> + unquote(env.module) + end + end + + translated_case = ElixirScript.Translator.translate!(info_case, env) + + declarator = JS.variable_declarator( + Identifier.make_identifier("__info__"), + JS.function_expression( + [JS.identifier("kind")], + [], + JS.block_statement([ + JS.return_statement(translated_case) + ]) + ) + ) + + JS.variable_declaration([declarator], :const) + + end + end diff --git a/test/translator/defmodule_test.exs b/test/translator/defmodule_test.exs index 6d7c8b45..8719b2a9 100644 --- a/test/translator/defmodule_test.exs +++ b/test/translator/defmodule_test.exs @@ -9,7 +9,9 @@ defmodule ElixirScript.Translator.Defmodule.Test do end js_code = """ - const __exports = {}; + const __exports = { + __info__ + }; """ assert_translation(ex_ast, js_code) @@ -31,19 +33,25 @@ defmodule ElixirScript.Translator.Defmodule.Test do end js_code = """ - const something = Bootstrap.Core.Patterns.defmatchgen(Bootstrap.Core.Patterns.clause([], function*() { + const something = Bootstrap.Core.Patterns.defmatch(Bootstrap.Core.Patterns.clause([], function() { return ul; })); + const __info__ = function(kind) { + return Bootstrap.Core.Patterns.defmatch(Bootstrap.Core.Patterns.clause([Symbol.for('functions')], function() { + return Object.freeze([new Bootstrap.Core.Tuple(Symbol.for('something'), 0)]); + }), Bootstrap.Core.Patterns.clause([Symbol.for('macros')], function() { + return Object.freeze([]); + }), Bootstrap.Core.Patterns.clause([Symbol.for('module')], function() { + return Symbol.for('Elixir.Elephant'); + })).call(this, kind); + }; + const ul = '#todo-list'; const something_else = Bootstrap.Core.Patterns.defmatchgen(Bootstrap.Core.Patterns.clause([], function*() { return null; })); - - const __exports = { - something - }; """ assert_translation(ex_ast, js_code) From 11f2f9f8a350fd3964221fd874a2ecdbb414924f Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Sun, 16 Apr 2017 19:18:14 -0500 Subject: [PATCH 525/860] Update estree dep --- mix.exs | 4 ++-- mix.lock | 20 ++++++++++---------- 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/mix.exs b/mix.exs index 8b257ebb..2a84943b 100644 --- a/mix.exs +++ b/mix.exs @@ -28,9 +28,9 @@ defmodule ElixirScript.Mixfile do defp deps do [ - {:estree, "~> 2.5"}, + {:estree, "~> 2.6"}, {:fs, "~> 2.12"}, - {:ex_doc, "~> 0.14", only: :dev}, + {:ex_doc, "~> 0.15", only: :dev}, {:excoveralls, "~> 0.6", only: :test}, {:credo, "~> 0.7", only: [:dev, :test]} ] diff --git a/mix.lock b/mix.lock index 0e03c5b6..b6b6b0d2 100644 --- a/mix.lock +++ b/mix.lock @@ -1,15 +1,15 @@ %{"bunt": {:hex, :bunt, "0.2.0", "951c6e801e8b1d2cbe58ebbd3e616a869061ddadcc4863d0a2182541acae9a38", [:mix], []}, - "certifi": {:hex, :certifi, "0.7.0", "861a57f3808f7eb0c2d1802afeaae0fa5de813b0df0979153cbafcd853ababaf", [:rebar3], []}, - "credo": {:hex, :credo, "0.7.2", "850463f126c09227994967fdcf8b8ad7684ab220f7727c00bcafc0ac37bd3660", [:mix], [{:bunt, "~> 0.2.0", [hex: :bunt, optional: false]}]}, - "earmark": {:hex, :earmark, "1.1.1", "433136b7f2e99cde88b745b3a0cfc3fbc81fe58b918a09b40fce7f00db4d8187", [:mix], []}, - "estree": {:hex, :estree, "2.5.1", "c93a8fa8a29886e6a6f6c489ba6dc949b998d2985b189967e41e69a92b58e846", [:mix], []}, - "ex_doc": {:hex, :ex_doc, "0.14.5", "c0433c8117e948404d93ca69411dd575ec6be39b47802e81ca8d91017a0cf83c", [:mix], [{:earmark, "~> 1.0", [hex: :earmark, optional: false]}]}, - "excoveralls": {:hex, :excoveralls, "0.6.2", "0e993d096f1fbb6e70a3daced5c89aac066bda6bce57829622aa2d1e2b338cfb", [:mix], [{:exjsx, "~> 3.0", [hex: :exjsx, optional: false]}, {:hackney, ">= 0.12.0", [hex: :hackney, optional: false]}]}, - "exjsx": {:hex, :exjsx, "3.2.1", "1bc5bf1e4fd249104178f0885030bcd75a4526f4d2a1e976f4b428d347614f0f", [:mix], [{:jsx, "~> 2.8.0", [hex: :jsx, optional: false]}]}, + "certifi": {:hex, :certifi, "1.0.0", "1c787a85b1855ba354f0b8920392c19aa1d06b0ee1362f9141279620a5be2039", [:rebar3], []}, + "credo": {:hex, :credo, "0.7.3", "9827ab04002186af1aec014a811839a06f72aaae6cd5eed3919b248c8767dbf3", [:mix], [{:bunt, "~> 0.2.0", [hex: :bunt, optional: false]}]}, + "earmark": {:hex, :earmark, "1.2.0", "bf1ce17aea43ab62f6943b97bd6e3dc032ce45d4f787504e3adf738e54b42f3a", [:mix], []}, + "estree": {:hex, :estree, "2.6.0", "86a301b0c355fa55c19e7ef9dceb1b1e983c6df526a2b7846818a38c258fc3fb", [:mix], []}, + "ex_doc": {:hex, :ex_doc, "0.15.1", "d5f9d588fd802152516fccfdb96d6073753f77314fcfee892b15b6724ca0d596", [:mix], [{:earmark, "~> 1.1", [hex: :earmark, optional: false]}]}, + "excoveralls": {:hex, :excoveralls, "0.6.3", "894bf9254890a4aac1d1165da08145a72700ff42d8cb6ce8195a584cb2a4b374", [:mix], [{:exjsx, "~> 3.0", [hex: :exjsx, optional: false]}, {:hackney, ">= 0.12.0", [hex: :hackney, optional: false]}]}, + "exjsx": {:hex, :exjsx, "3.2.1", "1bc5bf1e4fd249104178f0885030bcd75a4526f4d2a1e976f4b428d347614f0f", [], [{:jsx, "~> 2.8.0", [hex: :jsx, optional: false]}]}, "fs": {:hex, :fs, "2.12.0", "ad631efacc9a5683c8eaa1b274e24fa64a1b8eb30747e9595b93bec7e492e25e", [:rebar3], []}, - "hackney": {:hex, :hackney, "1.6.5", "8c025ee397ac94a184b0743c73b33b96465e85f90a02e210e86df6cbafaa5065", [:rebar3], [{:certifi, "0.7.0", [hex: :certifi, optional: false]}, {:idna, "1.2.0", [hex: :idna, optional: false]}, {:metrics, "1.0.1", [hex: :metrics, optional: false]}, {:mimerl, "1.0.2", [hex: :mimerl, optional: false]}, {:ssl_verify_fun, "1.1.1", [hex: :ssl_verify_fun, optional: false]}]}, - "idna": {:hex, :idna, "1.2.0", "ac62ee99da068f43c50dc69acf700e03a62a348360126260e87f2b54eced86b2", [:rebar3], []}, + "hackney": {:hex, :hackney, "1.7.1", "e238c52c5df3c3b16ce613d3a51c7220a784d734879b1e231c9babd433ac1cb4", [:rebar3], [{:certifi, "1.0.0", [hex: :certifi, optional: false]}, {:idna, "4.0.0", [hex: :idna, optional: false]}, {:metrics, "1.0.1", [hex: :metrics, optional: false]}, {:mimerl, "1.0.2", [hex: :mimerl, optional: false]}, {:ssl_verify_fun, "1.1.1", [hex: :ssl_verify_fun, optional: false]}]}, + "idna": {:hex, :idna, "4.0.0", "10aaa9f79d0b12cf0def53038547855b91144f1bfcc0ec73494f38bb7b9c4961", [:rebar3], []}, "jsx": {:hex, :jsx, "2.8.2", "7acc7d785b5abe8a6e9adbde926a24e481f29956dd8b4df49e3e4e7bcc92a018", [:mix, :rebar3], []}, - "metrics": {:hex, :metrics, "1.0.1", "25f094dea2cda98213cecc3aeff09e940299d950904393b2a29d191c346a8486", [:rebar3], []}, + "metrics": {:hex, :metrics, "1.0.1", "25f094dea2cda98213cecc3aeff09e940299d950904393b2a29d191c346a8486", [], []}, "mimerl": {:hex, :mimerl, "1.0.2", "993f9b0e084083405ed8252b99460c4f0563e41729ab42d9074fd5e52439be88", [], []}, "ssl_verify_fun": {:hex, :ssl_verify_fun, "1.1.1", "28a4d65b7f59893bc2c7de786dec1e1555bd742d336043fe644ae956c3497fbe", [:make, :rebar], []}} From 547862e23fad79abbfac56b23a5752016f61de45 Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Sun, 16 Apr 2017 19:19:40 -0500 Subject: [PATCH 526/860] Add js module to atom table --- lib/elixir_script/passes/create_js_modules.ex | 40 ++++++++++++++++++- priv/std_lib/range.ex | 4 +- src/javascript/lib/core/functions.js | 4 +- 3 files changed, 43 insertions(+), 5 deletions(-) diff --git a/lib/elixir_script/passes/create_js_modules.ex b/lib/elixir_script/passes/create_js_modules.ex index dbadb4fe..d9e5bb53 100644 --- a/lib/elixir_script/passes/create_js_modules.ex +++ b/lib/elixir_script/passes/create_js_modules.ex @@ -65,10 +65,15 @@ defmodule ElixirScript.Passes.CreateJSModules do elixir = JS.variable_declaration([declarator], :const) + table_additions = Enum.map(opts.js_modules, fn + {module, path} -> add_import_to_table(module) + {module, path, _} -> add_import_to_table(module) + end) + ast = opts.module_formatter.build( [], opts.js_modules, - [elixir, start, load] ++ body, + [elixir, create_atom_table(), start, load] ++ table_additions ++ body, JS.identifier("Elixir") ) @@ -128,4 +133,37 @@ defmodule ElixirScript.Passes.CreateJSModules do ) ) end + + defp create_atom_table() do + JS.assignment_expression( + :=, + JS.member_expression( + JS.identifier("Elixir"), + JS.identifier("__table__") + ), + JS.object_expression([]) + ) + end + + defp add_import_to_table(module_name) do + ref = ElixirScript.Translator.Identifier.make_namespace_members(module_name) + JS.assignment_expression( + :=, + JS.member_expression( + JS.member_expression( + JS.identifier("Elixir"), + JS.identifier("__table__") + ), + JS.call_expression( + JS.member_expression( + JS.identifier("Symbol"), + JS.identifier("for") + ), + [JS.literal(ref.name)] + ), + true + ), + ref + ) + end end diff --git a/priv/std_lib/range.ex b/priv/std_lib/range.ex index 9ae8bffe..7f53b13e 100644 --- a/priv/std_lib/range.ex +++ b/priv/std_lib/range.ex @@ -3,10 +3,10 @@ defmodule ElixirScript.Range do defstruct first: nil, last: nil def new(first, last) do - %ElixirScript.Range{first: first, last: last} + %Range{first: first, last: last} end - def range?(%ElixirScript.Range{}), do: true + def range?(%Range{}), do: true def range?(_), do: false end diff --git a/src/javascript/lib/core/functions.js b/src/javascript/lib/core/functions.js index d0d21099..9df6ba34 100644 --- a/src/javascript/lib/core/functions.js +++ b/src/javascript/lib/core/functions.js @@ -77,8 +77,8 @@ function build_namespace(ns, ns_string) { parent = parent[part]; } - root.__table = ns.__table || {}; - root.__table[Symbol.for(ns_string)] = parent; + root.__table__ = ns.__table__ || {}; + root.__table__[Symbol.for(ns_string)] = parent; return parent; } From e5c433ef94db29cf4ef1020d086bac9eb59255b5 Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Wed, 26 Apr 2017 05:19:27 -0500 Subject: [PATCH 527/860] Add JavaScript Interoperability documentation --- GettingStarted.md | 27 +---------- JavascriptInterop.md | 113 +++++++++++++++++++++++++++++++++++++++++++ mix.exs | 2 +- 3 files changed, 115 insertions(+), 27 deletions(-) create mode 100644 JavascriptInterop.md diff --git a/GettingStarted.md b/GettingStarted.md index 36c5f1f5..95fe5f4a 100644 --- a/GettingStarted.md +++ b/GettingStarted.md @@ -128,32 +128,7 @@ Elixirscript supports public macros. Private macros are currently unsupported. ### JavaScript Interop -Elixirscript has a couple of ways of interacting with JavaScript. - -#### Globally scoped functions - -Use the erlang module syntax, to call JavaScript functions in the global scope. - - # Calling alert - :window.alert("hi") - - # console - :console.log("hello") - - # document - :document.getElementById("main") - -#### Globally scoped modules - -You can call globally scoped modules you would an Elixir module - - Date.now() - -Only works if module begins with a captial letter - -#### The JS module - -The JS module has many other functions and macros. For more information, check out the docs. +Check out the [JavaScript Interoperability](JavaScriptInterop.html) documentation #### Frontend Project Boilerplate diff --git a/JavascriptInterop.md b/JavascriptInterop.md new file mode 100644 index 00000000..13095e2f --- /dev/null +++ b/JavascriptInterop.md @@ -0,0 +1,113 @@ +# JavaScript Interoperability + +## ElixirScript Calling JavaScript + +### JS module + +The `JS` module has functions and macros that help with interacting with JavaScript. +These mostly correspond to JavaScript keywords that may be useful. + +```elixir +# Calling the JavaScript Debugger +JS.debugger() + +# Getting the type of a value +JS.typeof(my_value) + +# Creating a new JavaScript Map +map = JS.new(JS.Map, []) +``` + +### Accessing Global Objects, Functions, and Properties + +In order to interact with JavaScript things in the global scope, append "JS" to them. The global scope corresponds to whatever the global object is in the JavaScript environment you are in. For example, in a browser this would be `window` or `self`: + +```elixir +# Calling alert +JS.alert("hello") + +# Calling a method on Object +JS.Object.keys(my_object) + +# Creating a new JavaScript Date +JS.new(JS.Date, []) + +# Getting the outer width +JS.outerWidth +``` + +### JavaScript modules + +ElixirScript can use JavaScript modules from the supported modules systems. +In order to do so, you must tell ElixirScript about them upfront. + +If using ElixirScript in a mix project, you can do so inside of the ElixirScript configuration keyword list + +```elixir + def project do + [ + app: :my_project, + elixir_script: [ + format: :es, + js_modules: [ + {React, "react"}, + {ReactDOM, "react-dom"} + ] + ] + ] + end +``` + +Or if using the CLI, you can do so by passing each module via the `js-module` flag + +``` +elixirscript "app/elixirscript" -o dist --js-module React:react --js-module ReactDOM:react-dom +``` + +Interacting with these modules works the same as interacting with an ElixirScript module + +```elixir +React.createElement(...) +``` + +## JavaScript Calling ElixirScript + + In order to start an ElixirScript application, you must first import it using whichever JavaScript module system you are using and then call `Elixir.start` + + ```Elixir + # Our ElixirScript module + + defmodule Main do + def start(:normal, args) do + JS.console.log(args) + end + end + + ``` + + ```javascript + //ES module example + import Elixir from './Elixir.App' + Elixir.start(Elixir.Main, [1, 2, 3]) + ``` + + In the above example, we have an ElixirScript module, `Main` with a `start/2` function. This function is the entry point into your ElixirScript application. when we call `Elixir.start`, we give it this module's name (All modules when compiled begin with `Elixir.`) and a list of the initial args. + + + If you want to use an ElixirScript module inside of your JavaScript code, you can do so using `Elixir.load`. + + ```Elixir + # Our ElixirScript module + + defmodule MyModule do + def hi() do + JS.alert("hello") + end + end + ``` + + + ```javascript + const MyModule = Elixir.load(Elixir.MyModule); + MyModule.hi() + ``` \ No newline at end of file diff --git a/mix.exs b/mix.exs index 2a84943b..a9b380f3 100644 --- a/mix.exs +++ b/mix.exs @@ -15,7 +15,7 @@ defmodule ElixirScript.Mixfile do aliases: aliases(), test_coverage: [tool: ExCoveralls], docs: [ - extras: ["GettingStarted.md", "FAQ.md", "Supported.md"] + extras: ["GettingStarted.md", "FAQ.md", "Supported.md", "JavaScriptInterop.md"] ] ] end From e483e17571571174d9b035eeda14e491ae4a3289 Mon Sep 17 00:00:00 2001 From: Connor Rigby Date: Fri, 5 May 2017 15:01:12 -0700 Subject: [PATCH 528/860] Fix typo in GettingStarted.md --- GettingStarted.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/GettingStarted.md b/GettingStarted.md index 95fe5f4a..10059635 100644 --- a/GettingStarted.md +++ b/GettingStarted.md @@ -75,7 +75,7 @@ Adding Elixirscript to your mix project gives you the ability to add it to your Add dependency to your deps in mix.exs: - ```elixir +```elixir {:elixir_script, "~> 0.26"} ``` @@ -100,6 +100,7 @@ Add dependency to your deps in mix.exs: compilers: [:elixir_script] ++ Mix.compilers ] end +``` Available options are: From 1f7434c4c13fd0e29ad2b53d0a941fbe5c8b867d Mon Sep 17 00:00:00 2001 From: Connor Rigby Date: Fri, 5 May 2017 15:02:05 -0700 Subject: [PATCH 529/860] Update GettingStarted.md --- GettingStarted.md | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/GettingStarted.md b/GettingStarted.md index 10059635..cab117a3 100644 --- a/GettingStarted.md +++ b/GettingStarted.md @@ -75,12 +75,13 @@ Adding Elixirscript to your mix project gives you the ability to add it to your Add dependency to your deps in mix.exs: -```elixir +``` elixir {:elixir_script, "~> 0.26"} - ``` +``` Elixirscript uses default input, output and module formats if options are not given. If you wish to change any or all options, add an `elixir_script` key to your project configuration. - + +``` elixir def project do [ app: :my_app, From 7e215c77f1c894073b4a0098211247e114f74000 Mon Sep 17 00:00:00 2001 From: Connor Rigby Date: Fri, 5 May 2017 15:02:50 -0700 Subject: [PATCH 530/860] Update GettingStarted.md --- GettingStarted.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/GettingStarted.md b/GettingStarted.md index cab117a3..6870c716 100644 --- a/GettingStarted.md +++ b/GettingStarted.md @@ -76,10 +76,10 @@ Adding Elixirscript to your mix project gives you the ability to add it to your Add dependency to your deps in mix.exs: ``` elixir - {:elixir_script, "~> 0.26"} +{:elixir_script, "~> 0.26"} ``` - Elixirscript uses default input, output and module formats if options are not given. If you wish to change any or all options, add an `elixir_script` key to your project configuration. +Elixirscript uses default input, output and module formats if options are not given. If you wish to change any or all options, add an `elixir_script` key to your project configuration. ``` elixir def project do From abca9e267cadc83bf418c38c6cb426520e7728ba Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Thu, 11 May 2017 05:47:41 -0500 Subject: [PATCH 531/860] add .tool-versions file --- .tool-versions | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 .tool-versions diff --git a/.tool-versions b/.tool-versions new file mode 100644 index 00000000..88fcc8d5 --- /dev/null +++ b/.tool-versions @@ -0,0 +1,3 @@ +elixir 1.4.2 +erlang 19.3 +nodejs 7.10.0 \ No newline at end of file From fe909acccebfffecfb2c4688993724ce4aca668a Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Thu, 11 May 2017 20:22:22 -0500 Subject: [PATCH 532/860] Update .tool-versions --- .tool-versions | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.tool-versions b/.tool-versions index 88fcc8d5..822dfebc 100644 --- a/.tool-versions +++ b/.tool-versions @@ -1,3 +1,3 @@ -elixir 1.4.2 -erlang 19.3 +elixir 1.5.0-dev +erlang ref-OTP-20.0-rc1 nodejs 7.10.0 \ No newline at end of file From 8fa0fce8f0d3a7fdc09fd21cb3fb3d2ce19b0a78 Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Fri, 19 May 2017 10:42:02 -0400 Subject: [PATCH 533/860] Got compilation working with new version of elixir --- lib/elixir_script/experimental/backend.ex | 33 + lib/elixir_script/experimental/clause.ex | 115 +++ .../experimental/examples/example.ex | 11 + .../experimental/examples/size.ex | 22 + lib/elixir_script/experimental/form.ex | 187 ++++ .../experimental/forms/bitstring.ex | 147 +++ lib/elixir_script/experimental/forms/call.ex | 45 + lib/elixir_script/experimental/forms/for.ex | 128 +++ lib/elixir_script/experimental/forms/map.ex | 61 ++ lib/elixir_script/experimental/forms/match.ex | 95 ++ .../experimental/forms/pattern.ex | 142 +++ .../experimental/forms/struct.ex | 20 + lib/elixir_script/experimental/forms/try.ex | 98 ++ lib/elixir_script/experimental/function.ex | 48 + .../experimental/functions/erlang.ex | 909 ++++++++++++++++++ .../experimental/functions/lists.ex | 114 +++ .../experimental/functions/maps.ex | 38 + lib/elixir_script/experimental/module.ex | 88 ++ .../experimental/module_state.ex | 21 + lib/elixir_script/next/beam.ex | 19 + lib/elixir_script/next/compiler.ex | 82 ++ lib/elixir_script/next/state.ex | 42 + lib/elixir_script/passes/create_js_modules.ex | 2 +- .../kernel/special_forms/identifier.ex | 7 +- test/beam_test.exs | 8 + 25 files changed, 2480 insertions(+), 2 deletions(-) create mode 100644 lib/elixir_script/experimental/backend.ex create mode 100644 lib/elixir_script/experimental/clause.ex create mode 100644 lib/elixir_script/experimental/examples/example.ex create mode 100644 lib/elixir_script/experimental/examples/size.ex create mode 100644 lib/elixir_script/experimental/form.ex create mode 100644 lib/elixir_script/experimental/forms/bitstring.ex create mode 100644 lib/elixir_script/experimental/forms/call.ex create mode 100644 lib/elixir_script/experimental/forms/for.ex create mode 100644 lib/elixir_script/experimental/forms/map.ex create mode 100644 lib/elixir_script/experimental/forms/match.ex create mode 100644 lib/elixir_script/experimental/forms/pattern.ex create mode 100644 lib/elixir_script/experimental/forms/struct.ex create mode 100644 lib/elixir_script/experimental/forms/try.ex create mode 100644 lib/elixir_script/experimental/function.ex create mode 100644 lib/elixir_script/experimental/functions/erlang.ex create mode 100644 lib/elixir_script/experimental/functions/lists.ex create mode 100644 lib/elixir_script/experimental/functions/maps.ex create mode 100644 lib/elixir_script/experimental/module.ex create mode 100644 lib/elixir_script/experimental/module_state.ex create mode 100644 lib/elixir_script/next/beam.ex create mode 100644 lib/elixir_script/next/compiler.ex create mode 100644 lib/elixir_script/next/state.ex create mode 100644 test/beam_test.exs diff --git a/lib/elixir_script/experimental/backend.ex b/lib/elixir_script/experimental/backend.ex new file mode 100644 index 00000000..a5d3d4e0 --- /dev/null +++ b/lib/elixir_script/experimental/backend.ex @@ -0,0 +1,33 @@ +defmodule ElixirScript.Experimental.Backend do + alias ElixirScript.Experimental.Module + alias ESTree.Tools.Generator + alias ElixirScript.Experimental.ModuleState + + def compile(line, file, module, attrs, defs, unreachable, opts) do + # Print all arguments + #IO.inspect binding() + + # Compile module to JavaScript AST + js_ast = Module.compile(line, file, module, attrs, defs, unreachable, opts) + + # Generate JavaScript code string + js_code = Generator.generate(js_ast) + + #IO.puts js_code + + write_js(module, js_code) + # Invoke the default backend - it returns the compiled beam binary + :elixir_erl.compile(line, file, module, attrs, defs, unreachable, opts) + end + + defp write_js(module, js_code) do + output_dir = Path.join([Mix.Project.build_path(), "_javascript"]) + + if !File.exists?(output_dir) do + File.mkdir_p!(output_dir) + end + + output_path = Path.join([output_dir, "#{module}.js"]) + File.write!(output_path, js_code) + end +end diff --git a/lib/elixir_script/experimental/clause.ex b/lib/elixir_script/experimental/clause.ex new file mode 100644 index 00000000..29327f77 --- /dev/null +++ b/lib/elixir_script/experimental/clause.ex @@ -0,0 +1,115 @@ +defmodule ElixirScript.Experimental.Clause do + alias ESTree.Tools.Builder, as: J + alias ElixirScript.Experimental.Form + alias ElixirScript.Experimental.Forms.Pattern + + @moduledoc """ + Handles translation of all of the clause ASTs + """ + + @patterns J.member_expression( + J.member_expression( + J.identifier("Bootstrap"), + J.identifier("Core") + ), + J.identifier("Patterns") + ) + + def compile({ _, args, guards, body}, state) do + {patterns, params} = Pattern.compile(args, state) + guard = compile_guard(params, guards, state) + + body = case body do + nil -> + J.identifier("null") + {:__block__, _, block_body} -> + Enum.map(block_body, &Form.compile(&1, state)) + |> List.flatten + _ -> + Form.compile(body, state) + end + + body = return_last_statement(body) + + J.call_expression( + J.member_expression( + @patterns, + J.identifier("clause") + ), + [ + J.array_expression(patterns), + J.function_expression( + params, + [], + J.block_statement(body) + ), + guard + ] + ) + end + + def compile({:->, _, [[{:when, _, params}], body ]}, state) do + guards = List.last(params) + params = params |> Enum.reverse |> tl |> Enum.reverse + + compile({[], params, guards, body}, state) + end + + def compile({:->, _, [params, body]}, state) do + compile({[], params, [], body}, state) + end + + def return_last_statement(body) do + body + |> List.wrap + |> Enum.reverse + |> do_return_last_statement + |> Enum.reverse + end + + defp do_return_last_statement([%ESTree.ThrowStatement{} = ast]) do + [ast] + end + + defp do_return_last_statement([head]) do + [J.return_statement(head)] + end + + defp do_return_last_statement([%ESTree.ThrowStatement{} = head | tail]) do + [head] ++ tail + end + + defp do_return_last_statement([head | tail]) do + [J.return_statement(head)] ++ tail + end + + defp compile_guard(params, guards, state) do + + guards = guards + |> List.wrap + |> Enum.reverse + |> process_guards + |> Form.compile(state) + + J.function_expression( + params, + [], + J.block_statement([ + J.return_statement(guards) + ]) + ) + + end + + defp process_guards([]) do + true + end + + defp process_guards([guard]) do + guard + end + + defp process_guards([head | tail]) do + {{:., [], [:erlang, :orelse]}, [], [process_guards(tail), head]} + end +end diff --git a/lib/elixir_script/experimental/examples/example.ex b/lib/elixir_script/experimental/examples/example.ex new file mode 100644 index 00000000..c6914c21 --- /dev/null +++ b/lib/elixir_script/experimental/examples/example.ex @@ -0,0 +1,11 @@ +defmodule Example do + @compile {:undocumented_elixir_backend_option, ElixirScript.Experimental.Backend} + + defstruct [:name] + + def new() do + JS.Map.new() + Hello.hi() + end + +end diff --git a/lib/elixir_script/experimental/examples/size.ex b/lib/elixir_script/experimental/examples/size.ex new file mode 100644 index 00000000..e16baa30 --- /dev/null +++ b/lib/elixir_script/experimental/examples/size.ex @@ -0,0 +1,22 @@ +defprotocol Example.Size do + @compile {:undocumented_elixir_backend_option, ElixirScript.Experimental.Backend} + def size(data) +end + +defimpl Example.Size, for: BitString do + @compile {:undocumented_elixir_backend_option, ElixirScript.Experimental.Backend} + + def size(string), do: byte_size(string) +end + +defimpl Example.Size, for: Map do + @compile {:undocumented_elixir_backend_option, ElixirScript.Experimental.Backend} + + def size(map), do: map_size(map) +end + +defimpl Example.Size, for: Tuple do + @compile {:undocumented_elixir_backend_option, ElixirScript.Experimental.Backend} + + def size(tuple), do: tuple_size(tuple) +end \ No newline at end of file diff --git a/lib/elixir_script/experimental/form.ex b/lib/elixir_script/experimental/form.ex new file mode 100644 index 00000000..6c9a7c06 --- /dev/null +++ b/lib/elixir_script/experimental/form.ex @@ -0,0 +1,187 @@ +defmodule ElixirScript.Experimental.Form do + alias ESTree.Tools.Builder, as: J + alias ElixirScript.Experimental.Forms.{Map, Bitstring, Match, Call, Try, For, Struct} + alias ElixirScript.Experimental.Functions.{Erlang, Lists, Maps} + alias ElixirScript.Translator.Identifier + alias ElixirScript.Experimental.Clause + + @moduledoc """ + Handles translation of all forms that are not functions or clauses + """ + + def compile(nil, _) do + J.identifier("null") + end + + def compile(form, _) when is_boolean(form) when is_integer(form) when is_float(form) when is_binary(form) do + J.literal(form) + end + + def compile(form, state) when is_list(form) do + J.array_expression( + Enum.map(form, &compile(&1, state)) + ) + end + + def compile(form, state) when is_atom(form) do + if ElixirScript.Experimental.Module.is_elixir_module(form) do + members = ["Elixir"] ++ Module.split(form) + J.identifier(Enum.join(members, "_")) + else + J.call_expression( + J.member_expression( + J.identifier("Symbol"), + J.identifier("for") + ), + [J.literal(form)] + ) + end + end + + def compile({a, b}, state) do + compile({:{}, [], [a, b]}, state) + end + + def compile({:{}, _, elements}, state) do + J.call_expression( + J.member_expression( + J.member_expression( + J.identifier("Bootstrap"), + J.identifier("Core") + ), + J.identifier("Tuple") + ), + Enum.map(elements, &compile(&1, state)) + ) + end + + def compile({:%{}, _, _} = map, state) do + Map.compile(map, state) + end + + def compile({:<<>>, _, _} = bitstring, state) do + Bitstring.compile(bitstring, state) + end + + def compile({:=, _, [left, right]} = match, state) do + Match.compile(match, state) + end + + def compile({:%, _, [_, _]} = ast, state) do + Struct.compile(ast, state) + end + + def compile({:for, _, _} = ast, state) do + For.compile(ast, state) + end + + def compile({:case, _, [condition, [do: clauses]]}, state) do + func = J.call_expression( + J.member_expression( + ElixirScript.Experimental.Function.patterns_ast(), + J.identifier("defmatch") + ), + Enum.map(clauses, &Clause.compile(&1, state)) + ) + + J.call_expression( + J.member_expression( func, J.identifier("call")), + [J.identifier(:this), compile(condition, state)] + ) + end + + def compile({:cond, _, [[do: clauses]]}, state) do + processed_clauses = Enum.map(clauses, fn({:->, _, [clause, clause_body]}) -> + translated_body = Enum.map(List.wrap(clause_body), &compile(&1, state)) + |> Clause.return_last_statement + translated_body = J.function_expression([], [], J.block_statement(translated_body)) + + translated_clause = compile(hd(clause), state) + + + J.array_expression([translated_clause, translated_body]) + end) + + + cond_function = J.member_expression( + J.member_expression( + J.identifier("Bootstrap"), + J.member_expression( + J.identifier("Core"), + J.identifier("SpecialForms") + ) + ), + J.identifier("cond") + ) + + J.call_expression( + cond_function, + processed_clauses + ) + end + + def compile({:receive, context, _}, state) do + line = Keyword.get(context, :line, 1) + raise ElixirScriptCompileError, message: "Line: #{line} receive not supported" + end + + def compile({:try, _, [blocks]}, state) do + Try.compile(blocks, state) + end + + def compile({:fn, _, clauses}, state) do + J.call_expression( + J.member_expression( + ElixirScript.Experimental.Function.patterns_ast(), + J.identifier("defmatch") + ), + Enum.map(clauses, &Clause.compile(&1, state)) + ) + end + + def compile({{:., _, [:erlang, _]}, _, _} = ast, state) do + Erlang.rewrite(ast, state) + end + + def compile({{:., _, [:lists, _]}, _, _} = ast, state) do + Lists.rewrite(ast, state) + end + + def compile({{:., _, [:maps, _]}, _, _} = ast, state) do + Maps.rewrite(ast, state) + end + + def compile({{:., _, [_, _]}, _, _} = ast, state) do + Call.compile(ast, state) + end + + def compile({:super, context, params}, state) do + {function_name, _} = Keyword.fetch!(context, :function) + IO.inspect {"HERE!!!!", function_name} + + J.call_expression( + ElixirScript.Translator.Identifier.make_function_name(function_name, length(params)), + Enum.map(params, &compile(&1, state)) + ) + end + + def compile({function_name, _, params}, state) when is_list(params) do + case function_name do + a when is_atom(a) -> + J.call_expression( + ElixirScript.Translator.Identifier.make_function_name(function_name, length(params)), + Enum.map(params, &compile(&1, state)) + ) + _ -> + J.call_expression( + compile(function_name, state), + Enum.map(params, &compile(&1, state)) + ) + end + end + + def compile({var, _, _}, state) do + ElixirScript.Translator.Identifier.make_identifier(var) + end + +end diff --git a/lib/elixir_script/experimental/forms/bitstring.ex b/lib/elixir_script/experimental/forms/bitstring.ex new file mode 100644 index 00000000..ed978e5a --- /dev/null +++ b/lib/elixir_script/experimental/forms/bitstring.ex @@ -0,0 +1,147 @@ +defmodule ElixirScript.Experimental.Forms.Bitstring do + @moduledoc false + alias ESTree.Tools.Builder, as: JS + alias ElixirScript.Experimental.Form + + + def compile({:<<>>, _, elements}, state) do + js_ast = JS.new_expression( + JS.member_expression( + JS.member_expression( + JS.identifier("Bootstrap"), + JS.identifier("Core") + ), + JS.identifier("BitString") + ), + Enum.map(elements, &compile_element(&1, state)) + ) + + js_ast + end + + def compile_element(element, state) when is_number(element) do + do_compile_element({:integer, Form.compile(element, state)}) + end + + def compile_element(element, state) when is_binary(element) do + do_compile_element({:binary, Form.compile(element, state)}) + end + + def compile_element({:<<>>, [], elements}, state) do + {ast, _} = compile(elements, state) + ast + end + + def compile_element({:::, _, [element, {type, _, _}]}, state) when type in [:integer, :float, :bitstring, :bits, :binary, :bytes, :utf8, :utf16, :utf32, :signed, :unsigned] do + do_compile_element({type, translate_element(element, state)}) + end + + def compile_element({:::, _, [element, {type, _, params}]}, state) when type in [:size, :unit] do + do_compile_element({type, translate_element(element, state), Enum.map(params, &translate_element(&1, state))}) + end + + def compile_element({:::, _, [element, {:*, _, [size, unit]}]}, state) do + size_ast = do_compile_element({:size, translate_element(element, state), [translate_element(size, state)]}) + do_compile_element({:unit, size_ast, [translate_element(unit, state)]}) + end + + def compile_element({:::, _, [element, {:-, _, types}]}, state) do + handle_type_adjectives({:-, [], types}, translate_element(element, state), state) + end + + def compile_element({:::, _, [element, size]}, state) do + do_compile_element({:size, translate_element(element, state), [translate_element(size, state)]}) + end + + def compile_element(element, state) do + do_compile_element({:binary, translate_element(element, state)}) + end + + def translate_element(ElixirScript.Translator.PatternMatching, _) do + JS.object_expression([JS.property( + JS.literal("value"), + ElixirScript.Translator.PatternMatching.parameter() + ) + ]) + end + + def translate_element(element, state) do + Form.compile(element, state) + end + + defp handle_type_adjectives({:-, _, types}, ast, state) do + Enum.reduce(types, ast, fn(type, current_ast) -> + case type do + {:-, _, sub_types} -> + handle_type_adjectives({:-, [], sub_types}, current_ast, state) + {:*, _, [size, unit]} -> + size_ast = do_compile_element({:size, current_ast, [Form.compile(size, state)]}) + do_compile_element({:unit, size_ast, [Form.compile(unit, state)]}) + {the_type, _, params} when is_list(params) -> + do_compile_element({the_type, current_ast, Enum.map(params, &Form.compile(&1, state))}) + {the_type, _, _} -> + do_compile_element({the_type, current_ast}) + end + end) + end + + defp bitstring_class() do + JS.member_expression( + JS.member_expression( + JS.identifier("Bootstrap"), + JS.identifier("Core") + ), + JS.identifier("BitString") + ) + end + + defp do_compile_element({type, ast}) do + JS.call_expression( + JS.member_expression( + bitstring_class, + JS.identifier(type) + ), + [ + ast + ] + ) + end + + defp do_compile_element({type, ast, params}) when is_list(params) do + JS.call_expression( + JS.member_expression( + bitstring_class, + JS.identifier(type) + ), + [ + ast + ] ++ params + ) + end + + def make_interpolated_string(elements, state) do + translated_elements = Enum.map(elements, fn(x)-> + case x do + elem when is_binary(elem) -> + Form.compile(elem, state) + {:::, _, data} -> + Form.compile(hd(data), state) + end + end) + + { do_make_interpolated_string(tl(translated_elements), hd(translated_elements)) } + end + + defp do_make_interpolated_string([], ast, _) do + ast + end + + defp do_make_interpolated_string(elements, ast) do + JS.binary_expression( + :+, + ast, + do_make_interpolated_string(tl(elements), hd(elements)) + ) + end + +end diff --git a/lib/elixir_script/experimental/forms/call.ex b/lib/elixir_script/experimental/forms/call.ex new file mode 100644 index 00000000..efd578c3 --- /dev/null +++ b/lib/elixir_script/experimental/forms/call.ex @@ -0,0 +1,45 @@ +defmodule ElixirScript.Experimental.Forms.Call do + alias ESTree.Tools.Builder, as: J + alias ElixirScript.Experimental.Form + alias ElixirScript.Translator.Identifier + alias ElixirScript.State, as: ModuleState + + def compile({{:., _, [module, function]}, _, params}, state) do + function_name = cond do + ElixirScript.Experimental.Module.is_js_module(module, state) -> + ElixirScript.Translator.Identifier.make_extern_function_name(function) + ElixirScript.Experimental.Module.is_elixir_module(module) -> + if ModuleState.get_module(state.pid, module) == nil do + ElixirScript.Experimental.Module.compile(module, state.pid) + end + ElixirScript.Translator.Identifier.make_function_name(function, length(params)) + true -> + ElixirScript.Translator.Identifier.make_function_name(function, length(params)) + end + + J.call_expression( + J.member_expression( + process_module_name(module, state), + function_name + ), + Enum.map(params, &Form.compile(&1, state)) + ) + end + + defp process_module_name(module, state) when is_atom(module) do + cond do + ElixirScript.Experimental.Module.is_js_module(module, state) -> + members = tl(Module.split(module)) + Identifier.make_namespace_members(members) + ElixirScript.Experimental.Module.is_elixir_module(module) -> + members = ["Elixir"] ++ Module.split(module) + J.identifier(Enum.join(members, "_")) + true -> + ElixirScript.Translator.Identifier.make_identifier(module) + end + end + + defp process_module_name(module, state) do + Form.compile(module, state) + end +end diff --git a/lib/elixir_script/experimental/forms/for.ex b/lib/elixir_script/experimental/forms/for.ex new file mode 100644 index 00000000..b98604e6 --- /dev/null +++ b/lib/elixir_script/experimental/forms/for.ex @@ -0,0 +1,128 @@ +defmodule ElixirScript.Experimental.Forms.For do + alias ESTree.Tools.Builder, as: JS + alias ElixirScript.Experimental.Form + alias ElixirScript.Experimental.Clause + alias ElixirScript.Experimental.Forms.{Pattern} + + def compile({:for, _, generators}, state) do + args = handle_args(generators, state) + + generators = JS.array_expression(args.generators) + + into = args.into || JS.array_expression([]) + filter = args.filter || JS.function_expression([], [], JS.block_statement([JS.return_statement(JS.identifier("true"))])) + fun = args.fun + + + expression = JS.call_expression( + JS.member_expression( + JS.member_expression( + JS.member_expression( + JS.identifier("Bootstrap"), + JS.identifier("Core") + ), + JS.identifier("Patterns") + ), + JS.identifier("clause") + ), + [JS.array_expression(args.patterns), fun, filter] + ) + + collectable = JS.member_expression( + JS.identifier("Elixir"), + JS.identifier("Collectable") + ) + + JS.call_expression( + JS.member_expression( + JS.member_expression( + JS.identifier("Bootstrap"), + JS.member_expression( + JS.identifier("Core"), + JS.identifier("SpecialForms") + ) + ), + JS.identifier("_for") + ), + [expression, generators, collectable, into] + ) + end + + defp handle_args(generators, module_state) do + Enum.reduce(generators, %{generators: [], args: [], filter: nil, fun: nil, into: nil, patterns: []}, fn + + ({:<<>>, _, body}, state) -> + {bs_parts, collection} = Enum.map_reduce(body, nil, fn + {:::, _, _} = ast, state -> + {ast, state} + {:<-, _, [var, collection]}, _ -> + {var, collection} + end) + + {patterns, params} = Pattern.compile([{:<<>>, [], bs_parts}], module_state) + + gen = JS.call_expression( + JS.member_expression( + JS.member_expression( + JS.member_expression( + JS.identifier("Bootstrap"), + JS.identifier("Core") + ), + JS.identifier("Patterns") + ), + JS.identifier("bitstring_generator") + ), + [hd(patterns), Form.compile(collection, module_state)] + ) + + %{state | generators: state.generators ++ [gen], args: state.args ++ params, patterns: state.patterns ++ patterns} + + ({:<-, _, [identifier, enum]}, state) -> + {patterns, params} = Pattern.compile([identifier], module_state) + + gen = JS.call_expression( + JS.member_expression( + JS.member_expression( + JS.member_expression( + JS.identifier("Bootstrap"), + JS.identifier("Core") + ), + JS.identifier("Patterns") + ), + JS.identifier("list_generator") + ), + [hd(patterns), Form.compile(enum, module_state)] + ) + + %{state | generators: state.generators ++ [gen], args: state.args ++ params, patterns: state.patterns ++ patterns} + ([into: expression], state) -> + %{state | into: Form.compile(expression, module_state)} + + ([into: expression, do: expression2], state) -> + fun = create_function_expression(expression2, state, module_state) + + %{state | into: Form.compile(expression, module_state), fun: fun} + + ([do: expression], state) -> + fun = create_function_expression(expression, state, module_state) + + %{state | fun: fun} + (filter, state) -> + fun = create_function_expression(filter, state, module_state) + + %{state | filter: fun} + end) + end + + + defp create_function_expression(ast, state, module_state) do + ast = Enum.map(List.wrap(ast), &Form.compile(&1, module_state)) + |> Clause.return_last_statement + + JS.function_expression( + state.args, + [], + JS.block_statement(ast) + ) + end +end diff --git a/lib/elixir_script/experimental/forms/map.ex b/lib/elixir_script/experimental/forms/map.ex new file mode 100644 index 00000000..bac66534 --- /dev/null +++ b/lib/elixir_script/experimental/forms/map.ex @@ -0,0 +1,61 @@ +defmodule ElixirScript.Experimental.Forms.Map do + alias ESTree.Tools.Builder, as: J + alias ElixirScript.Experimental.Form + + def compile({:%{}, _, [{:|, _, [map, new_values]}]}, state) do + map = Form.compile(map, state) + data = Form.compile({:%{}, [], new_values}, state) + + J.call_expression( + J.member_expression( + J.member_expression( + J.identifier("Bootstrap"), + J.member_expression( + J.identifier("Core"), + J.identifier("SpecialForms") + ) + ), + J.identifier("map_update") + ), + [map, data] + ) + end + + def compile({:%{}, _, properties}, state) do + properties + |> Enum.map(fn + ({x, y}) -> + case x do + {_, _, nil } -> + J.property(Form.compile(x, state), Form.compile(y, state), :init, false, false, true) + _ -> + make_property(Form.compile(x, state), Form.compile(y, state)) + end + end) + |> J.object_expression + end + + def make_property(%ESTree.Identifier{} = key, value) do + J.property(key, value) + end + + def make_property(%ESTree.Literal{value: k}, value) when is_binary(k) do + key = case String.contains?(k, "-") do + true -> + J.literal(k) + false -> + ElixirScript.Translator.Identifier.make_identifier(k) + end + + J.property(key, value) + end + + def make_property(key, value) do + J.property(key, value, :init, false, false, true) + end + + def make_shorthand_property(%ESTree.Identifier{} = key) do + J.property(key, key, :init, true) + end + +end diff --git a/lib/elixir_script/experimental/forms/match.ex b/lib/elixir_script/experimental/forms/match.ex new file mode 100644 index 00000000..9d0275c7 --- /dev/null +++ b/lib/elixir_script/experimental/forms/match.ex @@ -0,0 +1,95 @@ +defmodule ElixirScript.Experimental.Forms.Match do + alias ESTree.Tools.Builder, as: J + alias ElixirScript.Experimental.Form + alias ElixirScript.Experimental.Forms.{Pattern} + + def compile({:=, _, [left, right]}, state) do + right_ast = Form.compile(right, state) + + { patterns, params } = Pattern.compile([left], state) + + declarator = J.variable_declarator( + J.array_pattern(params), + J.call_expression( + J.member_expression( + J.member_expression( + J.member_expression( + J.identifier("Bootstrap"), + J.identifier("Core") + ), + J.identifier("Patterns") + ), + J.identifier("match") + ), + [hd(patterns), right_ast] + ) + ) + + array_pattern = J.variable_declaration([declarator], :let) + + js_ast = case left do + list when is_list(list) -> + make_list_ref(array_pattern, params, state) + { _, _ } -> + make_tuple_ref(array_pattern, params) + {:{}, _, _ } -> + make_tuple_ref(array_pattern, params) + _ -> + array_pattern + end + + js_ast + end + + + defp make_list_ref(array_pattern, params, state) do + {ref, params} = make_params(params) + + ref_declarator = J.variable_declarator( + ref, + J.array_expression( + Enum.map(params, &Form.compile(&1, state)) + ) + ) + + make_variable_declaration_and_group(ref_declarator, array_pattern) + end + + defp make_tuple_ref(array_pattern, params) do + {ref, params} = make_params(params) + + ref_declarator = J.variable_declarator( + ref, + J.new_expression( + J.member_expression( + J.identifier("Bootstrap"), + J.member_expression( + J.identifier("Core"), + J.identifier("Tuple") + ) + ), + params + ) + ) + + make_variable_declaration_and_group(ref_declarator, array_pattern) + end + + + defp make_params(params) do + ref = J.identifier("_ref") + + params = Enum.map(params, fn + (nil) -> J.identifier(:undefined) + (x) -> x + end) + + { ref, params } + end + + defp make_variable_declaration_and_group(ref_declarator, array_pattern) do + ref_declaration = J.variable_declaration([ref_declarator], :let) + [array_pattern, ref_declaration] + end + +end \ No newline at end of file diff --git a/lib/elixir_script/experimental/forms/pattern.ex b/lib/elixir_script/experimental/forms/pattern.ex new file mode 100644 index 00000000..c745b020 --- /dev/null +++ b/lib/elixir_script/experimental/forms/pattern.ex @@ -0,0 +1,142 @@ +defmodule ElixirScript.Experimental.Forms.Pattern do + alias ElixirScript.Translator.PatternMatching, as: PM + alias ESTree.Tools.Builder, as: J + alias ElixirScript.Experimental.Form + alias ElixirScript.Experimental.Forms.{Bitstring, Map} + + @moduledoc """ + Handles all pattern matching translations + """ + + def compile(patterns, state) do + patterns + |> Enum.reduce({[], []}, fn + x, { patterns, params } -> + {pattern, param} = process_pattern(x, state) + { patterns ++ List.wrap(pattern), params ++ List.wrap(param) } + end) + end + + defp process_pattern(term, state) when is_number(term) or is_binary(term) or is_boolean(term) or is_atom(term) or is_nil(term) do + { [Form.compile(term, state)], [] } + end + + defp process_pattern({:^, _, [value]}, state) do + { [PM.bound(Form.compile(value, state))], [nil] } + end + + defp process_pattern({:_, _, _}, _) do + { [PM.wildcard()], [J.identifier(:_)] } + end + + defp process_pattern({a, b}, state) do + process_pattern({:{}, [], [a, b] }, state) + end + + defp process_pattern({:{}, _, elements }, state) do + { patterns, params } = elements + |> Enum.map(&compile([&1], state)) + |> reduce_patterns(state) + + pattern = J.object_expression([ + J.property( + J.identifier("values"), + J.array_expression(patterns) + ) + ]) + + tuple = J.member_expression( + J.member_expression( + J.identifier("Bootstrap"), + J.identifier("Core") + ), + J.identifier("Tuple") + ) + + { [PM.type(tuple, pattern)], params } + end + + defp process_pattern(list, state) when is_list(list) do + { patterns, params } = list + |> Enum.map(&compile([&1], state)) + |> reduce_patterns(state) + + {[J.array_expression(patterns)], params} + end + + defp process_pattern({:%{}, _, props}, state) do + properties = Enum.map(props, fn({key, value}) -> + {pattern, params} = process_pattern(value, state) + property = case key do + {:^, _, [the_key]} -> + J.property(Form.compile(the_key, state), hd(List.wrap(pattern)), :init, false, false, true) + _ -> + Map.make_property(Form.compile(key, state), hd(List.wrap(pattern))) + end + + { property, params } + end) + + {props, params} = Enum.reduce(properties, {[], []}, fn({prop, param}, {props, params}) -> + { props ++ [prop], params ++ param } + end) + + { J.object_expression(List.wrap(props)), params } + end + + defp process_pattern({:<<>>, _, elements}, state) do + params = Enum.reduce(elements, [], fn + ({:::, _, [{ variable, _, params }, _]}, state) when is_nil(params) + when is_list(params) and length(params) == 0 -> + state ++ [ElixirScript.Translator.Identifier.make_identifier(variable)] + _, state -> + state + end) + + elements = Enum.map(elements, fn + ({:::, context, [{ _, _, params }, options]}) when is_atom(params) -> + Bitstring.compile_element({:::, context, [ElixirScript.Translator.PatternMatching, options]}, state) + x -> + Bitstring.compile_element(x, state) + end) + + { [PM.bitstring_match(elements)], params } + end + + defp process_pattern([{:|, _, [head, tail]}], state) do + { head_patterns, head_params } = process_pattern(head, state) + { tail_patterns, tail_params } = process_pattern(tail, state) + params = head_params ++ tail_params + + { [PM.head_tail(hd(head_patterns), hd(tail_patterns))], params } + end + + defp process_pattern({:<>, _, [prefix, value]}, state) do + { [PM.starts_with(prefix)], [Form.compile(value, state)] } + end + + defp process_pattern({:=, _, [{name, _, _}, right]}, state) do + unify(name, right, state) + end + + defp process_pattern({:=, _, [left, {name, _, _}]}, state) do + unify(name, left, state) + end + + defp process_pattern({var, _, _}, _) do + { [PM.parameter()], [ElixirScript.Translator.Identifier.make_identifier(var)] } + end + + defp reduce_patterns(patterns, _) do + patterns + |> Enum.reduce({ [], [] }, fn({ pattern, new_param }, { patterns, new_params }) -> + { patterns ++ List.wrap(pattern), new_params ++ List.wrap(new_param) } + end) + end + + defp unify(target, source, state) do + { patterns, params } = compile([source], state) + { [PM.capture(hd(patterns))], params ++ [ElixirScript.Translator.Identifier.make_identifier(target)] } + end + +end diff --git a/lib/elixir_script/experimental/forms/struct.ex b/lib/elixir_script/experimental/forms/struct.ex new file mode 100644 index 00000000..7aebfa78 --- /dev/null +++ b/lib/elixir_script/experimental/forms/struct.ex @@ -0,0 +1,20 @@ +defmodule ElixirScript.Experimental.Forms.Struct do + alias ESTree.Tools.Builder, as: J + alias ElixirScript.Experimental.Form + alias ElixirScript.Translator.Identifier + + def compile({:%, _, [module, params]}, state) do + J.call_expression( + J.member_expression( + process_module_name(module), + J.identifier("__struct__1") + ), + [Form.compile(params, state)] + ) + end + + defp process_module_name(module) do + members = ["Elixir"] ++ Module.split(module) + Identifier.make_namespace_members(members) + end +end diff --git a/lib/elixir_script/experimental/forms/try.ex b/lib/elixir_script/experimental/forms/try.ex new file mode 100644 index 00000000..effe3fbd --- /dev/null +++ b/lib/elixir_script/experimental/forms/try.ex @@ -0,0 +1,98 @@ +defmodule ElixirScript.Experimental.Forms.Try do + @moduledoc false + alias ESTree.Tools.Builder, as: JS + alias ElixirScript.Experimental.Clause + alias ElixirScript.Experimental.Form + + def compile(blocks, state) do + try_block = Keyword.get(blocks, :do) + rescue_block = Keyword.get(blocks, :rescue, nil) + catch_block = Keyword.get(blocks, :catch, nil) + after_block = Keyword.get(blocks, :after, nil) + else_block = Keyword.get(blocks, :else, nil) + + translated_body = prepare_function_body(try_block, state) + + translated_body = JS.block_statement(translated_body) + try_block = JS.function_expression([], [], translated_body) + + rescue_block = if rescue_block do + process_rescue_block(rescue_block, state) + else + JS.identifier(:null) + end + + catch_block = if catch_block do + Form.compile({:fn, [], catch_block}, state) + else + JS.identifier(:null) + end + + after_block = if after_block do + process_after_block(after_block, state) + else + JS.identifier(:null) + end + + else_block = if else_block do + Form.compile({:fn, [], else_block}, state) + else + JS.identifier(:null) + end + + js_ast = JS.call_expression( + JS.member_expression( + JS.member_expression( + JS.identifier("Bootstrap"), + JS.member_expression( + JS.identifier("Core"), + JS.identifier("SpecialForms") + ) + ), + JS.identifier("_try") + ), + [ + try_block, + rescue_block, + catch_block, + else_block, + after_block + ] + ) + + js_ast + end + + defp process_rescue_block(rescue_block, state) do + processed_clauses = Enum.map(rescue_block, fn + {:->, _, [ [{:in, _, [param, names]} = pattern], body]} -> + Clause.compile({[], [param], [{{:., [], [Enum, :member?]}, [], [param, names]}], body}, state) + {:->, _, [ [param], body]} -> + Clause.compile({[], [param], [], body}, state) + end) + + + JS.call_expression( + JS.member_expression( + ElixirScript.Experimental.Function.patterns_ast(), + JS.identifier("defmatch") + ), + processed_clauses + ) + + end + + defp process_after_block(after_block, state) do + translated_body = prepare_function_body(after_block, state) + translated_body = JS.block_statement(translated_body) + + JS.function_expression([], [], translated_body) + end + + defp prepare_function_body(body, state) do + body + |> List.wrap + |> Enum.map(&Form.compile(&1, state)) + |> Clause.return_last_statement + end +end diff --git a/lib/elixir_script/experimental/function.ex b/lib/elixir_script/experimental/function.ex new file mode 100644 index 00000000..1ac7a330 --- /dev/null +++ b/lib/elixir_script/experimental/function.ex @@ -0,0 +1,48 @@ +defmodule ElixirScript.Experimental.Function do + alias ESTree.Tools.Builder, as: J + alias ElixirScript.Experimental.Clause + + @moduledoc """ + Translates the given Elixir function AST into the + equivalent JavaScript AST. Function names are + + """ + + def patterns_ast() do + J.member_expression( + J.member_expression( + J.identifier("Bootstrap"), + J.identifier("Core") + ), + J.identifier("Patterns") + ) + end + + def compile({{name, arity}, type, _, clauses}, state) do + clauses = Enum.map(clauses, fn(clause) -> + + # Walk the AST and add the function to the context. + # This information is used when translating "super" + Macro.prewalk(clause, fn + {subject, context, params} -> + {subject, Keyword.put(context, :function, {name, arity}), params } + ast -> + ast + end) + end) + + + declarator = J.variable_declarator( + ElixirScript.Translator.Identifier.make_function_name(name, arity), + J.call_expression( + J.member_expression( + patterns_ast(), + J.identifier("defmatch") + ), + Enum.map(clauses, &Clause.compile(&1, state)) + ) + ) + + J.variable_declaration([declarator], :const) + end +end diff --git a/lib/elixir_script/experimental/functions/erlang.ex b/lib/elixir_script/experimental/functions/erlang.ex new file mode 100644 index 00000000..cbe63f26 --- /dev/null +++ b/lib/elixir_script/experimental/functions/erlang.ex @@ -0,0 +1,909 @@ +defmodule ElixirScript.Experimental.Functions.Erlang do + @moduledoc false + alias ESTree.Tools.Builder, as: J + alias ElixirScript.Experimental.Form + + def rewrite({{:., _, [:erlang, :abs]}, _, [number]}, state) do + J.call_expression( + J.member_expression( + J.identifier("Math"), + J.identifier("abs") + ), + [Form.compile(number, state)] + ) + end + + def rewrite({{:., _, [:erlang, :apply]}, _, [fun, args]}, state) do + J.call_expression( + J.member_expression( + Form.compile(fun, state), + J.identifier("apply") + ), + [Form.compile(fun, state), J.array_expression(Enum.map(args, &Form.compile(&1, state)))] + ) + end + + def rewrite({{:., _, [:erlang, :apply]}, _, [module, fun, args]}, state) do + mod = J.member_expression( + Form.compile(module, state), + Form.compile(fun, state) + ) + + J.call_expression( + J.member_expression( + mod, + J.identifier("apply") + ), + [mod, J.array_expression(Enum.map(args, &Form.compile(&1, state)))] + ) + end + + def rewrite({{:., _, [:erlang, :binary_part]}, _, [binary, start, length]}, state) do + J.call_expression( + J.member_expression( + Form.compile(binary, state), + J.identifier("substring") + ), + [Form.compile(start, state), Form.compile(length, state)] + ) + end + + def rewrite({{:., _, [:erlang, :bit_size]}, _, [bitstring]}, state) do + J.call_expression( + J.member_expression( + Form.compile(bitstring, state), + J.identifier("bit_size") + ), + [] + ) + end + + def rewrite({{:., _, [:erlang, :byte_size]}, _, [bitstring]}, state) do + J.call_expression( + J.member_expression( + Form.compile(bitstring, state), + J.identifier("byte_size") + ), + [] + ) + end + + def rewrite({{:., _, [:erlang, :div]}, _, [left, right]}, state) do + J.binary_expression( + :/, + Form.compile(left, state), + Form.compile(right, state) + ) + end + + def rewrite({{:., _, [:erlang, :exit]}, _, [reason]}, _) do + J.literal(0) + end + + def rewrite({{:., _, [:erlang, :hd]}, _, [list]}, state) do + J.member_expression( + Form.compile(list, state), + J.literal(0), + true + ) + end + + def rewrite({{:., _, [:erlang, :is_atom]}, _, [term]}, state) do + J.binary_expression( + :typeof, + Form.compile(term, state), + J.literal("symbol") + ) + end + + def rewrite({{:., _, [:erlang, :is_binary]}, _, [term]}, state) do + J.binary_expression( + :typeof, + Form.compile(term, state), + J.literal("string") + ) + end + + def rewrite({{:., _, [:erlang, :is_bitstring]}, _, [term]}, state) do + J.binary_expression( + :||, + J.binary_expression( + :typeof, + Form.compile(term, state), + J.literal("string") + ), + J.binary_expression( + :instanceof, + Form.compile(term, state), + J.member_expression( + J.member_expression( + J.identifier("Bootstrap"), + J.identifier("Core") + ), + J.identifier("BitString") + ) + ) + ) + end + + def rewrite({{:., _, [:erlang, :is_boolean]}, _, [term]}, state) do + J.binary_expression( + :||, + J.binary_expression( + :typeof, + Form.compile(term, state), + J.literal("boolean") + ), + J.binary_expression( + :instanceof, + Form.compile(term, state), + J.identifier("Boolean") + ) + ) + end + + def rewrite({{:., _, [:erlang, :is_float]}, _, [term]}, state) do + J.binary_expression( + :||, + J.binary_expression( + :typeof, + Form.compile(term, state), + J.literal("number") + ), + J.binary_expression( + :&&, + J.binary_expression( + :instanceof, + Form.compile(term, state), + J.identifier("Number") + ), + J.unary_expression( + :!, + true, + J.call_expression( + J.member_expression( + J.identifier("Number"), + J.identifier("isInteger") + ), + [Form.compile(term, state)] + ) + ) + ) + ) + end + + def rewrite({{:., _, [:erlang, :is_function]}, _, [term]}, state) do + J.binary_expression( + :||, + J.binary_expression( + :typeof, + Form.compile(term, state), + J.literal("function") + ), + J.binary_expression( + :instanceof, + Form.compile(term, state), + J.identifier("Function") + ) + ) + end + + def rewrite({{:., _, [:erlang, :is_function]}, _, [term, _]}, state) do + J.binary_expression( + :||, + J.binary_expression( + :typeof, + Form.compile(term, state), + J.literal("function") + ), + J.binary_expression( + :instanceof, + Form.compile(term, state), + J.identifier("Function") + ) + ) + end + + def rewrite({{:., _, [:erlang, :is_integer]}, _, [term]}, state) do + J.call_expression( + J.member_expression( + J.identifier("Number"), + J.identifier("isInteger") + ), + [Form.compile(term, state)] + ) + end + + def rewrite({{:., _, [:erlang, :is_list]}, _, [term]}, state) do + J.call_expression( + J.member_expression( + J.identifier("Array"), + J.identifier("isArray") + ), + [Form.compile(term, state)] + ) + end + + def rewrite({{:., _, [:erlang, :is_number]}, _, [term]}, state) do + J.binary_expression( + :||, + J.binary_expression( + :typeof, + Form.compile(term, state), + J.literal("number") + ), + J.binary_expression( + :instanceof, + Form.compile(term, state), + J.identifier("Number") + ) + ) + end + + def rewrite({{:., _, [:erlang, :is_pid]}, _, [term]}, state) do + J.binary_expression( + :instanceof, + Form.compile(term, state), + J.member_expression( + J.member_expression( + J.identifier("Bootstrap"), + J.identifier("Core") + ), + J.identifier("PID") + ) + ) + end + + def rewrite({{:., _, [:erlang, :is_port]}, _, [_term]}, state) do + J.literal(false) + end + + def rewrite({{:., _, [:erlang, :is_reference]}, _, [_term]}, state) do + J.literal(false) + end + + def rewrite({{:., _, [:erlang, :is_tuple]}, _, [term]}, state) do + J.binary_expression( + :instanceof, + Form.compile(term, state), + J.member_expression( + J.member_expression( + J.identifier("Bootstrap"), + J.identifier("Core") + ), + J.identifier("Tuple") + ) + ) + end + + def rewrite({{:., _, [:erlang, :is_map]}, _, [term]}, state) do + J.binary_expression( + :||, + J.binary_expression( + :typeof, + Form.compile(term, state), + J.literal("object") + ), + J.binary_expression( + :instanceof, + Form.compile(term, state), + J.identifier("Object") + ) + ) + end + + def rewrite({{:., _, [:erlang, :length]}, _, [list]}, state) do + J.member_expression( + Form.compile(list, state), + J.identifier("length") + ) + end + + def rewrite({{:., _, [:erlang, :make_ref]}, _, []}, state) do + J.literal(false) + end + + def rewrite({{:., _, [:erlang, :map_size]}, _, [map]}, state) do + J.member_expression( + J.call_expression( + J.member_expression( + J.identifier("Object"), + J.identifier("keys") + ), + [Form.compile(map, state)] + ), + J.identifier("length") + ) + end + + def rewrite({{:., _, [:erlang, :max]}, _, [first, second]}, state) do + J.call_expression( + J.member_expression( + J.identifier("Math"), + J.identifier("max") + ), + [Form.compile(first, state), Form.compile(second, state)] + ) + end + + def rewrite({{:., _, [:erlang, :min]}, _, [first, second]}, state) do + J.call_expression( + J.member_expression( + J.identifier("Math"), + J.identifier("min") + ), + [Form.compile(first, state), Form.compile(second, state)] + ) + end + + def rewrite({{:., _, [:erlang, :node]}, _, []}, state) do + J.identifier("nonode@nohost") + end + + def rewrite({{:., _, [:erlang, :node]}, _, [_]}, state) do + J.identifier("nonode@nohost") + end + + def rewrite({{:., _, [:erlang, :rem]}, _, [first, second]}, state) do + J.binary_expression( + :%, + Form.compile(first, state), + Form.compile(second, state) + ) + end + + def rewrite({{:., _, [:erlang, :round]}, _, [number]}, state) do + J.call_expression( + J.member_expression( + J.identifier("Math"), + J.identifier("round") + ), + [Form.compile(number, state)] + ) + end + + def rewrite({{:., _, [:erlang, :send]}, _, [dest, msg]}, state) do + raise ":erlang.send not supported" + end + + def rewrite({{:., _, [:erlang, :self]}, _, []}, state) do + raise ":erlang.self not supported" + end + + def rewrite({{:., _, [:erlang, :spawn]}, _, [_fun]}, state) do + raise ":erlang.spawn not supported" + end + + def rewrite({{:., _, [:erlang, :spawn]}, _, [_module, _fun, _args]}, state) do + raise ":erlang.spawn not supported" + end + + def rewrite({{:., _, [:erlang, :spawn_link]}, _, [_fun]}, state) do + raise ":erlang.spawn_link not supported" + end + + def rewrite({{:., _, [:erlang, :spawn_link]}, _, [_module, _fun, _args]}, state) do + raise ":erlang.spawn_link not supported" + end + + def rewrite({{:., _, [:erlang, :spawn_monitor]}, _, [_fun]}, state) do + raise ":erlang.spawn_monitor not supported" + end + + def rewrite({{:., _, [:erlang, :spawn_monitor]}, _, [_module, _fun, _args]}, state) do + raise ":erlang.spawn_monitor not supported" + end + + def rewrite({{:., _, [:erlang, :throw]}, _, [term]}, state) do + J.throw_statement( + Form.compile(term, state) + ) + end + + def rewrite({{:., _, [:erlang, :tl]}, _, [list]}, state) do + J.call_expression( + J.member_expression( + Form.compile(list, state), + J.identifier("splice") + ), + [J.literal(1)] + ) + end + + def rewrite({{:., _, [:erlang, :trunc]}, _, [number]}, state) do + J.call_expression( + J.member_expression( + J.identifier("Math"), + J.identifier("floor") + ), + [Form.compile(number, state)] + ) + end + + def rewrite({{:., _, [:erlang, :tuple_size]}, _, [tuple]}, state) do + J.member_expression( + Form.compile(tuple, state), + J.identifier("length") + ) + end + + def rewrite({{:., _, [:erlang, operator]}, _, [left, right]}, state) when operator in [:+, :-, :*, :/, :<, :>, :>=, :==] do + J.binary_expression( + operator, + Form.compile(left, state), + Form.compile(right, state) + ) + end + + def rewrite({{:., _, [:erlang, operator]}, _, [value]}, state) when operator in [:+, :-] do + J.unary_expression( + operator, + true, + Form.compile(value, state) + ) + end + + def rewrite({{:., _, [:erlang, :++]}, _, [left, right]}, state) do + J.call_expression( + J.member_expression( + Form.compile(left, state), + J.identifier("concat") + ), + [Form.compile(right, state)] + ) + end + + def rewrite({{:., _, [:erlang, :--]}, _, [list, element]}, state) do + J.call_expression( + J.member_expression( + Form.compile(list, state), + J.identifier("slice") + ), + [ + J.binary_expression( + :+, + J.call_expression( + J.member_expression( + Form.compile(list, state), + J.identifier("indexOf") + ), + [Form.compile(element, state)] + ), + J.literal(1) + ) + ] + ) + end + + def rewrite({{:., _, [:erlang, :not]}, _, [value]}, state) do + J.unary_expression( + :!, + true, + Form.compile(value, state) + ) + end + + def rewrite({{:., _, [:erlang, :"=<"]}, _, [left, right]}, state) do + J.binary_expression( + :<=, + Form.compile(left, state), + Form.compile(right, state) + ) + end + + def rewrite({{:., _, [:erlang, :"/="]}, _, [left, right]}, state) do + J.binary_expression( + :!=, + Form.compile(left, state), + Form.compile(right, state) + ) + end + + def rewrite({{:., _, [:erlang, :"=:="]}, _, [left, right]}, state) do + J.binary_expression( + :===, + Form.compile(left, state), + Form.compile(right, state) + ) + end + + def rewrite({{:., _, [:erlang, :"=/="]}, _, [left, right]}, state) do + J.binary_expression( + :!==, + Form.compile(left, state), + Form.compile(right, state) + ) + end + + def rewrite({{:., _, [:erlang, :element]}, _, [index, tuple]}, state) do + J.call_expression( + J.member_expression( + Form.compile(tuple, state), + J.identifier("get") + ), + [ + J.binary_expression( + :-, + Form.compile(index, state), + J.literal(1) + ) + ] + ) + end + + def rewrite({{:., _, [:erlang, :setelement]}, _, [index, tuple, value]}, state) do + J.call_expression( + J.member_expression( + Form.compile(tuple, state), + J.identifier("put_elem") + ), + [ + J.binary_expression( + :-, + Form.compile(index, state), + J.literal(1) + ), + Form.compile(value, state) + ] + ) + + quote do: unquote(tuple).put_elem(unquote(index) - 1, unquote(value)) + end + + def rewrite({{:., _, [:erlang, :orelse]}, _, [left, right]}, state) do + J.binary_expression( + :||, + Form.compile(left, state), + Form.compile(right, state) + ) + end + + def rewrite({{:., _, [:erlang, :or]}, _, [left, right]}, state) do + J.binary_expression( + :||, + Form.compile(left, state), + Form.compile(right, state) + ) + end + + def rewrite({{:., _, [:erlang, :andalso]}, _, [left, right]}, state) do + J.binary_expression( + :&&, + Form.compile(left, state), + Form.compile(right, state) + ) + end + + def rewrite({{:., _, [:erlang, :error]}, _, [error]}, state) do + J.throw_statement( + Form.compile(error, state) + ) + end + + def rewrite({{:., _, [:erlang, :raise]}, _, [_class, reason, _stacktrace]}, state) do + J.throw_statement( + Form.compile(reason, state) + ) + end + + def rewrite({{:., _, [:erlang, :atom_to_binary]}, _, [atom, _]}, state) do + J.call_expression( + J.member_expression( + J.identifier("Symbol"), + J.identifier("keyFor") + ), + [Form.compile(atom, state)] + ) + end + + def rewrite({{:., _, [:erlang, :atom_to_list]}, _, [atom]}, state) do + J.call_expression( + J.member_expression( + J.call_expression( + J.member_expression( + J.identifier("Symbol"), + J.identifier("keyFor") + ), + [Form.compile(atom, state)] + ), + J.identifier("split") + ), + [J.literal("")] + ) + end + + def rewrite({{:., _, [:erlang, :bnot]}, _, [expr]}, state) do + J.unary_expression( + :"~", + true, + Form.compile(expr, state) + ) + end + + def rewrite({{:., _, [:erlang, :band]}, _, [left, right]}, state) do + J.binary_expression( + :&, + Form.compile(left, state), + Form.compile(right, state) + ) + end + + def rewrite({{:., _, [:erlang, :bor]}, _, [left, right]}, state) do + J.binary_expression( + :|, + Form.compile(left, state), + Form.compile(right, state) + ) + end + + def rewrite({{:., _, [:erlang, :bxor]}, _, [left, right]}, state) do + J.binary_expression( + :^, + Form.compile(left, state), + Form.compile(right, state) + ) + end + + def rewrite({{:., _, [:erlang, :bsl]}, _, [left, right]}, state) do + J.binary_expression( + :"<<", + Form.compile(left, state), + Form.compile(right, state) + ) + end + + def rewrite({{:., _, [:erlang, :bsr]}, _, [left, right]}, state) do + J.binary_expression( + :">>", + Form.compile(left, state), + Form.compile(right, state) + ) + end + + def rewrite({{:., _, [:erlang, :function_exported]}, _, [_, _, _]}, state) do + J.literal(true) + end + + def rewrite({{:., _, [:erlang, :make_tuple]}, _, [size, data]}, state) do + J.new_expression( + J.member_expression( + J.member_expression( + J.identifier("Bootstrap"), + J.identifier("Core") + ), + J.identifier("Tuple") + ), + [] + ) + end + + def rewrite({{:., _, [:erlang, :insert_element]}, _, [index, tuple, term]}, state) do + J.call_expression( + J.member_expression( + Form.compile(tuple, state), + J.identifier("put_elem") + ), + [ + J.binary_expression( + :-, + Form.compile(index, state), + J.literal(1) + ), + Form.compile(term, state) + ] + ) + end + + def rewrite({{:., _, [:erlang, :tuple_to_list]}, _, [tuple]}, state) do + J.member_expression( + Form.compile(tuple, state), + J.identifier("values") + ) + end + + def rewrite({{:., _, [:erlang, :append_element]}, _, [tuple, value]}, state) do + J.call_expression( + J.member_expression( + Form.compile(tuple, state), + J.identifier("put_elem") + ), + [ + J.member_expression( + Form.compile(tuple, state), + J.identifier("length") + ), + Form.compile(value, state) + ] + ) + end + + def rewrite({{:., _, [:erlang, :delete_element]}, _, [index, tuple]}, state) do + J.call_expression( + J.member_expression( + Form.compile(tuple, state), + J.identifier("remove_elem") + ), + [Form.compile(index, state)] + ) + end + + def rewrite({{:., _, [:erlang, :binary_to_atom]}, _, [binary, _]}, state) do + J.call_expression( + J.member_expression( + J.identifier("Symbol"), + J.identifier("for") + ), + [Form.compile(binary, state)] + ) + end + + def rewrite({{:., _, [:erlang, :binary_to_existing_atom]}, _, [binary, _]}, state) do + J.call_expression( + J.member_expression( + J.identifier("Symbol"), + J.identifier("for") + ), + [Form.compile(binary, state)] + ) + end + + def rewrite({{:., _, [:erlang, :list_to_atom]}, _, [char_list]}, state) do + J.call_expression( + J.member_expression( + J.identifier("Symbol"), + J.identifier("for") + ), + [Form.compile(char_list, state)] + ) + end + + def rewrite({{:., _, [:erlang, :list_to_existing_atom]}, _, [char_list]}, state) do + J.call_expression( + J.member_expression( + J.identifier("Symbol"), + J.identifier("for") + ), + [Form.compile(char_list, state)] + ) + end + + def rewrite({{:., _, [:erlang, :list_to_tuple]}, _, [list]}, state) do + J.new_expression( + J.member_expression( + J.member_expression( + J.identifier("Bootstrap"), + J.identifier("Core") + ), + J.identifier("Tuple") + ), + [ + J.rest_element( + Form.compile(list, state) + ) + ] + ) + end + + def rewrite({{:., _, [:erlang, :list_to_float]}, _, [list]}, state) do + J.call_expression( + J.identifier("parseFloat"), + [Form.compile(list, state)] + ) + end + + def rewrite({{:., _, [:erlang, :list_to_integer]}, _, [list]}, state) do + J.call_expression( + J.identifier("parseInt"), + [Form.compile(list, state)] + ) + end + + def rewrite({{:., _, [:erlang, :list_to_integer]}, _, [list, base]}, state) do + J.call_expression( + J.identifier("parseInt"), + [Form.compile(list, state), Form.compile(base, state)] + ) + end + + def rewrite({{:., _, [:erlang, :integer_to_binary]}, _, [integer]}, state) do + J.call_expression( + J.member_expression( + Form.compile(integer, state), + J.identifier("toString") + ), + [] + ) + end + + def rewrite({{:., _, [:erlang, :integer_to_binary]}, _, [integer, base]}, state) do + J.call_expression( + J.member_expression( + Form.compile(integer, state), + J.identifier("toString") + ), + [Form.compile(base, state)] + ) + end + + def rewrite({{:., _, [:erlang, :integer_to_list]}, _, [integer]}, state) do + J.call_expression( + J.member_expression( + Form.compile(integer, state), + J.identifier("toString") + ), + [] + ) + end + + def rewrite({{:., _, [:erlang, :integer_to_list]}, _, [integer, base]}, state) do + J.call_expression( + J.member_expression( + Form.compile(integer, state), + J.identifier("toString") + ), + [Form.compile(base, state)] + ) + end + + def rewrite({{:., _, [:erlang, :float_to_binary]}, _, [float]}, state) do + J.call_expression( + J.member_expression( + Form.compile(float, state), + J.identifier("toString") + ), + [] + ) + end + + def rewrite({{:., _, [:erlang, :float_to_binary]}, _, [float, base]}, state) do + J.call_expression( + J.member_expression( + Form.compile(float, state), + J.identifier("toString") + ), + [Form.compile(base, state)] + ) + end + + def rewrite({{:., _, [:erlang, :float_to_list]}, _, [float]}, state) do + J.call_expression( + J.member_expression( + Form.compile(float, state), + J.identifier("toString") + ), + [] + ) + end + + def rewrite({{:., _, [:erlang, :float_to_list]}, _, [float, base]}, state) do + J.call_expression( + J.member_expression( + Form.compile(float, state), + J.identifier("toString") + ), + [Form.compile(base, state)] + ) + end + + def rewrite({{:., _, [:erlang, :binary_to_float]}, _, [binary]}, state) do + J.call_expression( + J.identifier("parseFloat"), + [Form.compile(binary, state)] + ) + end + + def rewrite({{:., _, [:erlang, :binary_to_integer]}, _, [binary]}, state) do + J.call_expression( + J.identifier("parseInt"), + [Form.compile(binary, state)] + ) + end + + def rewrite({{:., _, [:erlang, :binary_to_integer]}, _, [binary, base]}, state) do + J.call_expression( + J.identifier("parseInt"), + [Form.compile(binary, state), Form.compile(base, state)] + ) + end + +end diff --git a/lib/elixir_script/experimental/functions/lists.ex b/lib/elixir_script/experimental/functions/lists.ex new file mode 100644 index 00000000..e28a0128 --- /dev/null +++ b/lib/elixir_script/experimental/functions/lists.ex @@ -0,0 +1,114 @@ +defmodule ElixirScript.Experimental.Functions.Lists do + @moduledoc false + alias ESTree.Tools.Builder, as: J + alias ElixirScript.Experimental.Form + + def rewrite({{:., _, [:lists, :map]}, _, [fun, list]}, state) do + J.call_expression( + J.member_expression( + Form.compile(list, state), + J.identifier("map") + ), + [Form.compile(fun, state)] + ) + end + + def rewrite({{:., _, [:lists, :member]}, _, [elem, list]}, state) do + J.binary_expression( + :>, + J.call_expression( + J.member_expression( + Form.compile(list, state), + J.identifier("indexOf") + ), + [Form.compile(elem, state)] + ), + J.unary_expression( + :-, + true, + J.literal(1) + ) + ) + end + + def rewrite({{:., _, [:lists, :reverse]}, _, [list]}, state) do + J.call_expression( + J.member_expression( + J.call_expression( + J.member_expression( + Form.compile(list, state), + J.identifier("concat") + ), + [J.array_expression([])] + ), + J.identifier("reverse") + ), + [] + ) + end + + def rewrite({{:., _, [:lists, :reverse]}, _, [list, tail]}, state) do + J.call_expression( + J.member_expression( + J.call_expression( + J.member_expression( + J.call_expression( + J.member_expression( + Form.compile(list, state), + J.identifier("concat") + ), + [J.array_expression([])] + ), + J.identifier("reverse") + ), + [] + ), + J.identifier("concat") + ), + [Form.compile(tail, state)] + ) + end + + def rewrite({{:., _, [:lists, :sort]}, _, [list]}, state) do + J.call_expression( + J.member_expression( + J.call_expression( + J.member_expression( + Form.compile(list, state), + J.identifier("concat") + ), + [J.array_expression([])] + ), + J.identifier("sort") + ), + [] + ) + end + + def rewrite({{:., _, [:lists, :filter]}, _, [pred, list]}, state) do + J.call_expression( + J.member_expression( + Form.compile(list, state), + J.identifier("filter") + ), + [Form.compile(pred, state)] + ) + end + + def rewrite({{:., _, [:lists, :delete]}, _, [elem, list]}, state) do + J.call_expression( + J.member_expression( + J.member_expression( + J.member_expression( + J.identifier("Bootstrap"), + J.identifier("Core") + ), + J.identifier("Functions") + ), + J.identifier("remove_from_list") + ), + [Form.compile(list, state), Form.compile(elem, state)] + ) + end + +end diff --git a/lib/elixir_script/experimental/functions/maps.ex b/lib/elixir_script/experimental/functions/maps.ex new file mode 100644 index 00000000..8e4d1377 --- /dev/null +++ b/lib/elixir_script/experimental/functions/maps.ex @@ -0,0 +1,38 @@ +defmodule ElixirScript.Experimental.Functions.Maps do + @moduledoc false + alias ESTree.Tools.Builder, as: J + alias ElixirScript.Experimental.Form + + def rewrite({{:., _, [:maps, :update]}, _, [key, value, map]}, state) do + J.call_expression( + J.member_expression( + J.member_expression( + J.member_expression( + J.identifier("Bootstrap"), + J.identifier("Core") + ), + J.identifier("Functions") + ), + J.identifier("update_map") + ), + [Form.compile(map, state), Form.compile(key, state), Form.compile(value, state)] + ) + end + + def rewrite({{:., _, [:maps, :find]}, _, [key, map]}, state) do + J.call_expression( + J.member_expression( + J.member_expression( + J.member_expression( + J.identifier("Bootstrap"), + J.identifier("Core") + ), + J.identifier("Functions") + ), + J.identifier("update_map") + ), + [Form.compile(key, state), Form.compile(map, state)] + ) + end + +end diff --git a/lib/elixir_script/experimental/module.ex b/lib/elixir_script/experimental/module.ex new file mode 100644 index 00000000..25d384eb --- /dev/null +++ b/lib/elixir_script/experimental/module.ex @@ -0,0 +1,88 @@ +defmodule ElixirScript.Experimental.Module do + alias ESTree.Tools.Builder, as: J + alias ElixirScript.Experimental.Function + alias ElixirScript.Translator.Identifier + alias ElixirScript.State, as: ModuleState + + @moduledoc """ + Upper level module that handles compilation + """ + + def compile(module, pid) do + info = case ElixirScript.Beam.debug_info(module) do + {:ok, info} -> + info + {:error, error} -> + raise "An error occurred while compiling #{inspect module}: #{error}" + end + + %{ + attributes: _attrs, + compile_opts: _compile_opts, + definitions: defs, + file: _file, + line: _line, + module: ^module, + unreachable: unreachable + } = info + + state = %{ + pid: pid + } + + reachable_defs = Enum.filter(defs, fn + { name, _, _, _} -> not(name in unreachable) + { _, type, _, _} when type in [:defmacro, :defmacrop] -> false + _ -> true + end) + + module_info = %{module: module, defs: defs} + ModuleState.put_module(pid, module, module_info) + + compiled_functions = reachable_defs + |> Enum.map(&Function.compile(&1, state)) + + exports = make_exports(reachable_defs) + + js_ast = ElixirScript.ModuleSystems.Namespace.build( + module, + compiled_functions, + exports, + nil + ) + + ModuleState.put_module(pid, module, Map.put(module_info, :js_ast, hd(js_ast))) + end + + defp make_exports(reachable_defs) do + exports = Enum.reduce(reachable_defs, [], fn + {{name, arity}, :def, _, _}, list -> + function_name = ElixirScript.Translator.Identifier.make_function_name(name, arity) + list ++ [J.property(function_name, function_name, :init, true)] + _, list -> + list + end) + + J.object_expression(exports) + end + + def is_elixir_module(module) when is_atom(module) do + first_char = String.first(to_string(module)) + Regex.match?(~r/[A-Z]/, first_char) + end + + def is_elixir_module(_) do + false + end + + def is_js_module(module, state) do + cond do + module in ModuleState.get_javascript_modules(state.pid) -> + true + is_elixir_module(module) and hd(Module.split(module)) == "JS" -> + true + true -> + false + end + end +end diff --git a/lib/elixir_script/experimental/module_state.ex b/lib/elixir_script/experimental/module_state.ex new file mode 100644 index 00000000..dbd21825 --- /dev/null +++ b/lib/elixir_script/experimental/module_state.ex @@ -0,0 +1,21 @@ +defmodule ElixirScript.Experimental.ModuleState do + def start_link(module) do + Agent.start_link(fn -> %{ module: module, refs: [] } end) + end + + def stop(pid) do + Agent.stop(pid) + end + + def put_module_ref(pid, module) do + Agent.update(pid, fn(x) -> + %{x | refs: Enum.uniq([module | x.refs]) } + end) + end + + def get_module_refs(pid) do + Agent.get(pid, fn(x) -> + x.refs + end) + end +end \ No newline at end of file diff --git a/lib/elixir_script/next/beam.ex b/lib/elixir_script/next/beam.ex new file mode 100644 index 00000000..975ec593 --- /dev/null +++ b/lib/elixir_script/next/beam.ex @@ -0,0 +1,19 @@ +defmodule ElixirScript.Beam do + + @spec debug_info(atom) :: {:ok | :error, map | binary} + def debug_info(module) when is_atom(module) do + with {_, beam, _} <- :code.get_object_code(module), + {:ok, {^module, [debug_info: {:debug_info_v1, backend, data}]}} <- :beam_lib.chunks(beam, [:debug_info]) do + backend.debug_info(:elixir_v1, module, data, []) + else + :error -> + {:error, "Unknown module"} + {:error,:beam_lib,{:unknown_chunk,"non_existing.beam",:debug_info}} -> + {:error, "Unsupported version of Erlang"} + {:error,:beam_lib,{:file_error,"non_existing.beam",:enoent}} -> + {:error, "Debug info not available"} + end + + end + +end \ No newline at end of file diff --git a/lib/elixir_script/next/compiler.ex b/lib/elixir_script/next/compiler.ex new file mode 100644 index 00000000..44c99b45 --- /dev/null +++ b/lib/elixir_script/next/compiler.ex @@ -0,0 +1,82 @@ +defmodule ElixirScript.Compiler do + alias ESTree.Tools.{Builder, Generator} + + def compile(entry_modules, opts \\ []) do + opts = build_compiler_options(opts) + {:ok, pid} = ElixirScript.State.start_link(opts) + + modules = List.wrap(entry_modules) + Enum.each(modules, fn(module) -> + case ElixirScript.State.get_module(pid, module) do + nil -> + ElixirScript.Experimental.Module.compile(module, pid) + _ -> + nil + end + end) + + modules = ElixirScript.State.list_modules(pid) + |> Enum.map(fn {_module, info} -> info.js_ast end) + + bundle(modules, opts) + + ElixirScript.State.stop(pid) + end + + defp bundle(modules, opts) do + ElixirScript.Passes.CreateJSModules.compile(modules, opts) + + js_code = modules + |> ElixirScript.Passes.CreateJSModules.compile(opts) + |> List.wrap + |> Builder.program + |> prepare_js_ast + |> Generator.generate + + concat(js_code) + end + + defp concat(code) do + "'use strict';\n" <> ElixirScript.get_bootstrap_js("iife") <> "\n" <> code + end + + defp prepare_js_ast(js_ast) do + case js_ast do + modules when is_list(modules) -> + modules + |> Enum.reduce([], &(&2 ++ &1.body)) + |> Builder.program + %ElixirScript.Translator.Group{body: body} -> + Builder.program(body) + %ElixirScript.Translator.Empty{} -> + Builder.program([]) + _ -> + js_ast + end + end + + defp build_compiler_options(opts) do + default_options = Map.new + |> Map.put(:full_build, false) + |> Map.put(:output, nil) + |> Map.put(:app, :app) + |> Map.put(:format, :es) + |> Map.put(:js_modules, Keyword.get(opts, :js_modules, [])) + |> Map.put(:remove_unused, false) + + options = default_options + Map.put(options, :module_formatter, get_module_formatter(options[:format])) + end + + defp get_module_formatter(:umd) do + ElixirScript.ModuleSystems.UMD + end + + defp get_module_formatter(:common) do + ElixirScript.ModuleSystems.Common + end + + defp get_module_formatter(_) do + ElixirScript.ModuleSystems.ES + end +end \ No newline at end of file diff --git a/lib/elixir_script/next/state.ex b/lib/elixir_script/next/state.ex new file mode 100644 index 00000000..18418929 --- /dev/null +++ b/lib/elixir_script/next/state.ex @@ -0,0 +1,42 @@ +defmodule ElixirScript.State do + def start_link(compiler_opts) do + Agent.start_link(fn -> + %{ + compiler_opts: compiler_opts, + modules: Keyword.new, + refs: [] + } + end) + end + + def stop(pid) do + Agent.stop(pid) + end + + def get_module(pid, module) do + Agent.get(pid, fn(state) -> + Keyword.get(state.modules, module) + end) + end + + def put_module(pid, module, value) do + Agent.update(pid, fn(state) -> + %{ state | modules: Keyword.put(state.modules, module, value) } + end) + end + + def get_javascript_modules(pid) do + Agent.get(pid, fn(state) -> + Keyword.get(state.compiler_opts, :js_modules, []) + |> Enum.map(fn({module_name, _path}) -> + module_name + end) + end) + end + + def list_modules(pid) do + Agent.get(pid, fn(state) -> + state.modules + end) + end +end \ No newline at end of file diff --git a/lib/elixir_script/passes/create_js_modules.ex b/lib/elixir_script/passes/create_js_modules.ex index d9e5bb53..a0cff524 100644 --- a/lib/elixir_script/passes/create_js_modules.ex +++ b/lib/elixir_script/passes/create_js_modules.ex @@ -57,7 +57,7 @@ defmodule ElixirScript.Passes.CreateJSModules do body end - defp compile(body, opts) do + def compile(body, opts) do declarator = JS.variable_declarator( JS.identifier("Elixir"), JS.object_expression([]) diff --git a/lib/elixir_script/translator/kernel/special_forms/identifier.ex b/lib/elixir_script/translator/kernel/special_forms/identifier.ex index 3639432c..2542260c 100644 --- a/lib/elixir_script/translator/kernel/special_forms/identifier.ex +++ b/lib/elixir_script/translator/kernel/special_forms/identifier.ex @@ -80,6 +80,11 @@ defmodule ElixirScript.Translator.Identifier do end |> Enum.reverse |> make_alias - end + end + + def make_function_name(name, arity) when is_atom(name) do + name = filter_name(name) + JS.identifier("#{name}#{arity}") + end end diff --git a/test/beam_test.exs b/test/beam_test.exs new file mode 100644 index 00000000..5d52e87e --- /dev/null +++ b/test/beam_test.exs @@ -0,0 +1,8 @@ +defmodule ElixirScript.Beam.Test do + use ExUnit.Case + + test "can get ast from beam" do + assert {:ok, map} = ElixirScript.Beam.debug_info(Atom) + IO.inspect map + end +end From a3d529fb8e7fad0111ddf59099fa7b93de8e802e Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Sun, 21 May 2017 15:33:56 -0500 Subject: [PATCH 534/860] Compile protocol implementations. --- lib/elixir_script/experimental/clause.ex | 7 ++ .../experimental/examples/example.ex | 7 +- lib/elixir_script/experimental/form.ex | 12 +-- lib/elixir_script/experimental/forms/for.ex | 4 + lib/elixir_script/experimental/forms/match.ex | 11 +-- .../experimental/forms/pattern.ex | 1 - lib/elixir_script/experimental/function.ex | 13 +--- .../experimental/functions/erlang.ex | 75 ++++++++++--------- .../experimental/functions/lists.ex | 64 ++++++++++++++++ .../experimental/functions/maps.ex | 47 ++++++++++++ lib/elixir_script/experimental/module.ex | 29 ++++++- lib/elixir_script/next/beam.ex | 25 ++++++- lib/elixir_script/next/compiler.ex | 9 ++- lib/elixir_script/next/state.ex | 2 +- .../kernel/special_forms/identifier.ex | 4 + test/beam_test.exs | 1 - 16 files changed, 234 insertions(+), 77 deletions(-) diff --git a/lib/elixir_script/experimental/clause.ex b/lib/elixir_script/experimental/clause.ex index 29327f77..ea61a39c 100644 --- a/lib/elixir_script/experimental/clause.ex +++ b/lib/elixir_script/experimental/clause.ex @@ -25,6 +25,9 @@ defmodule ElixirScript.Experimental.Clause do {:__block__, _, block_body} -> Enum.map(block_body, &Form.compile(&1, state)) |> List.flatten + b when is_list(b) -> + Enum.map(b, &Form.compile(&1, state)) + |> List.flatten _ -> Form.compile(body, state) end @@ -83,6 +86,10 @@ defmodule ElixirScript.Experimental.Clause do [J.return_statement(head)] ++ tail end + defp do_return_last_statement([]) do + [J.return_statement(J.identifier("null"))] + end + defp compile_guard(params, guards, state) do guards = guards diff --git a/lib/elixir_script/experimental/examples/example.ex b/lib/elixir_script/experimental/examples/example.ex index c6914c21..2761f632 100644 --- a/lib/elixir_script/experimental/examples/example.ex +++ b/lib/elixir_script/experimental/examples/example.ex @@ -1,11 +1,6 @@ defmodule Example do - @compile {:undocumented_elixir_backend_option, ElixirScript.Experimental.Backend} - - defstruct [:name] - def new() do - JS.Map.new() - Hello.hi() + Base.encode16("foobar") end end diff --git a/lib/elixir_script/experimental/form.ex b/lib/elixir_script/experimental/form.ex index 6c9a7c06..9778d4f8 100644 --- a/lib/elixir_script/experimental/form.ex +++ b/lib/elixir_script/experimental/form.ex @@ -1,6 +1,6 @@ defmodule ElixirScript.Experimental.Form do alias ESTree.Tools.Builder, as: J - alias ElixirScript.Experimental.Forms.{Map, Bitstring, Match, Call, Try, For, Struct} + alias ElixirScript.Experimental.Forms.{Bitstring, Match, Call, Try, For, Struct} alias ElixirScript.Experimental.Functions.{Erlang, Lists, Maps} alias ElixirScript.Translator.Identifier alias ElixirScript.Experimental.Clause @@ -25,7 +25,7 @@ defmodule ElixirScript.Experimental.Form do def compile(form, state) when is_atom(form) do if ElixirScript.Experimental.Module.is_elixir_module(form) do - members = ["Elixir"] ++ Module.split(form) + members = if form == Elixir, do: ["Elixir"], else: ["Elixir"] ++ Module.split(form) J.identifier(Enum.join(members, "_")) else J.call_expression( @@ -56,7 +56,7 @@ defmodule ElixirScript.Experimental.Form do end def compile({:%{}, _, _} = map, state) do - Map.compile(map, state) + ElixirScript.Experimental.Forms.Map.compile(map, state) end def compile({:<<>>, _, _} = bitstring, state) do @@ -122,7 +122,8 @@ defmodule ElixirScript.Experimental.Form do def compile({:receive, context, _}, state) do line = Keyword.get(context, :line, 1) - raise ElixirScriptCompileError, message: "Line: #{line} receive not supported" + #raise ElixirScriptCompileError, message: "Line: #{line} receive not supported" + J.call_expression(J.identifier(:receive), []) end def compile({:try, _, [blocks]}, state) do @@ -156,8 +157,7 @@ defmodule ElixirScript.Experimental.Form do end def compile({:super, context, params}, state) do - {function_name, _} = Keyword.fetch!(context, :function) - IO.inspect {"HERE!!!!", function_name} + {function_name, _} = Map.get(state, :function) J.call_expression( ElixirScript.Translator.Identifier.make_function_name(function_name, length(params)), diff --git a/lib/elixir_script/experimental/forms/for.ex b/lib/elixir_script/experimental/forms/for.ex index b98604e6..1313aedd 100644 --- a/lib/elixir_script/experimental/forms/for.ex +++ b/lib/elixir_script/experimental/forms/for.ex @@ -48,6 +48,10 @@ defmodule ElixirScript.Experimental.Forms.For do ) end + defp handle_args(nil, module_state) do + %{generators: [], args: [], filter: nil, fun: nil, into: nil, patterns: []} + end + defp handle_args(generators, module_state) do Enum.reduce(generators, %{generators: [], args: [], filter: nil, fun: nil, into: nil, patterns: []}, fn diff --git a/lib/elixir_script/experimental/forms/match.ex b/lib/elixir_script/experimental/forms/match.ex index 9d0275c7..3e40b2f4 100644 --- a/lib/elixir_script/experimental/forms/match.ex +++ b/lib/elixir_script/experimental/forms/match.ex @@ -45,13 +45,7 @@ defmodule ElixirScript.Experimental.Forms.Match do defp make_list_ref(array_pattern, params, state) do {ref, params} = make_params(params) - ref_declarator = J.variable_declarator( - ref, - J.array_expression( - Enum.map(params, &Form.compile(&1, state)) - ) - ) - + ref_declarator = J.variable_declarator(ref, J.array_expression(params)) make_variable_declaration_and_group(ref_declarator, array_pattern) end @@ -89,7 +83,8 @@ defmodule ElixirScript.Experimental.Forms.Match do defp make_variable_declaration_and_group(ref_declarator, array_pattern) do ref_declaration = J.variable_declaration([ref_declarator], :let) - [array_pattern, ref_declaration] + #[array_pattern, ref_declaration] + array_pattern end end \ No newline at end of file diff --git a/lib/elixir_script/experimental/forms/pattern.ex b/lib/elixir_script/experimental/forms/pattern.ex index c745b020..1b6edf22 100644 --- a/lib/elixir_script/experimental/forms/pattern.ex +++ b/lib/elixir_script/experimental/forms/pattern.ex @@ -138,5 +138,4 @@ defmodule ElixirScript.Experimental.Forms.Pattern do { patterns, params } = compile([source], state) { [PM.capture(hd(patterns))], params ++ [ElixirScript.Translator.Identifier.make_identifier(target)] } end - end diff --git a/lib/elixir_script/experimental/function.ex b/lib/elixir_script/experimental/function.ex index 1ac7a330..b16f18f6 100644 --- a/lib/elixir_script/experimental/function.ex +++ b/lib/elixir_script/experimental/function.ex @@ -19,18 +19,7 @@ defmodule ElixirScript.Experimental.Function do end def compile({{name, arity}, type, _, clauses}, state) do - clauses = Enum.map(clauses, fn(clause) -> - - # Walk the AST and add the function to the context. - # This information is used when translating "super" - Macro.prewalk(clause, fn - {subject, context, params} -> - {subject, Keyword.put(context, :function, {name, arity}), params } - ast -> - ast - end) - end) - + state = Map.put(state, :function, {name, arity}) declarator = J.variable_declarator( ElixirScript.Translator.Identifier.make_function_name(name, arity), diff --git a/lib/elixir_script/experimental/functions/erlang.ex b/lib/elixir_script/experimental/functions/erlang.ex index cbe63f26..0d813a40 100644 --- a/lib/elixir_script/experimental/functions/erlang.ex +++ b/lib/elixir_script/experimental/functions/erlang.ex @@ -19,7 +19,7 @@ defmodule ElixirScript.Experimental.Functions.Erlang do Form.compile(fun, state), J.identifier("apply") ), - [Form.compile(fun, state), J.array_expression(Enum.map(args, &Form.compile(&1, state)))] + [Form.compile(fun, state), J.array_expression(Enum.map(List.wrap(args), &Form.compile(&1, state)))] ) end @@ -34,7 +34,7 @@ defmodule ElixirScript.Experimental.Functions.Erlang do mod, J.identifier("apply") ), - [mod, J.array_expression(Enum.map(args, &Form.compile(&1, state)))] + [mod, J.array_expression(Enum.map(List.wrap(args), &Form.compile(&1, state)))] ) end @@ -362,37 +362,37 @@ defmodule ElixirScript.Experimental.Functions.Erlang do ) end - def rewrite({{:., _, [:erlang, :send]}, _, [dest, msg]}, state) do - raise ":erlang.send not supported" - end - - def rewrite({{:., _, [:erlang, :self]}, _, []}, state) do - raise ":erlang.self not supported" - end - - def rewrite({{:., _, [:erlang, :spawn]}, _, [_fun]}, state) do - raise ":erlang.spawn not supported" - end - - def rewrite({{:., _, [:erlang, :spawn]}, _, [_module, _fun, _args]}, state) do - raise ":erlang.spawn not supported" - end - - def rewrite({{:., _, [:erlang, :spawn_link]}, _, [_fun]}, state) do - raise ":erlang.spawn_link not supported" - end - - def rewrite({{:., _, [:erlang, :spawn_link]}, _, [_module, _fun, _args]}, state) do - raise ":erlang.spawn_link not supported" - end - - def rewrite({{:., _, [:erlang, :spawn_monitor]}, _, [_fun]}, state) do - raise ":erlang.spawn_monitor not supported" - end - - def rewrite({{:., _, [:erlang, :spawn_monitor]}, _, [_module, _fun, _args]}, state) do - raise ":erlang.spawn_monitor not supported" - end +# def rewrite({{:., _, [:erlang, :send]}, _, [dest, msg]}, state) do +# raise ":erlang.send not supported" +# end +# +# def rewrite({{:., _, [:erlang, :self]}, _, []}, state) do +# raise ":erlang.self not supported" +# end +# +# def rewrite({{:., _, [:erlang, :spawn]}, _, [_fun]}, state) do +# raise ":erlang.spawn not supported" +# end +# +# def rewrite({{:., _, [:erlang, :spawn]}, _, [_module, _fun, _args]}, state) do +# raise ":erlang.spawn not supported" +# end +# +# def rewrite({{:., _, [:erlang, :spawn_link]}, _, [_fun]}, state) do +# raise ":erlang.spawn_link not supported" +# end +# +# def rewrite({{:., _, [:erlang, :spawn_link]}, _, [_module, _fun, _args]}, state) do +# raise ":erlang.spawn_link not supported" +# end +# +# def rewrite({{:., _, [:erlang, :spawn_monitor]}, _, [_fun]}, state) do +# raise ":erlang.spawn_monitor not supported" +# end +# +# def rewrite({{:., _, [:erlang, :spawn_monitor]}, _, [_module, _fun, _args]}, state) do +# raise ":erlang.spawn_monitor not supported" +# end def rewrite({{:., _, [:erlang, :throw]}, _, [term]}, state) do J.throw_statement( @@ -546,8 +546,6 @@ defmodule ElixirScript.Experimental.Functions.Erlang do Form.compile(value, state) ] ) - - quote do: unquote(tuple).put_elem(unquote(index) - 1, unquote(value)) end def rewrite({{:., _, [:erlang, :orelse]}, _, [left, right]}, state) do @@ -906,4 +904,11 @@ defmodule ElixirScript.Experimental.Functions.Erlang do ) end + def rewrite({{:., _, [:erlang, _]}, _, _}, state) do + J.call_expression( + J.identifier("toString"), + [] + ) + end + end diff --git a/lib/elixir_script/experimental/functions/lists.ex b/lib/elixir_script/experimental/functions/lists.ex index e28a0128..1c1c2a39 100644 --- a/lib/elixir_script/experimental/functions/lists.ex +++ b/lib/elixir_script/experimental/functions/lists.ex @@ -111,4 +111,68 @@ defmodule ElixirScript.Experimental.Functions.Lists do ) end + def rewrite({{:., _, [:lists, _]}, _, [elem, list]}, state) do + J.call_expression( + J.member_expression( + J.member_expression( + J.member_expression( + J.identifier("Bootstrap"), + J.identifier("Core") + ), + J.identifier("Functions") + ), + J.identifier("remove_from_list") + ), + [Form.compile(list, state), Form.compile(elem, state)] + ) + end + + def rewrite({{:., _, [:lists, _]}, _, [elem, list, _, _]}, state) do + J.call_expression( + J.member_expression( + J.member_expression( + J.member_expression( + J.identifier("Bootstrap"), + J.identifier("Core") + ), + J.identifier("Functions") + ), + J.identifier("remove_from_list") + ), + [Form.compile(list, state), Form.compile(elem, state)] + ) + end + + def rewrite({{:., _, [:lists, _]}, _, [elem, list, _]}, state) do + J.call_expression( + J.member_expression( + J.member_expression( + J.member_expression( + J.identifier("Bootstrap"), + J.identifier("Core") + ), + J.identifier("Functions") + ), + J.identifier("remove_from_list") + ), + [Form.compile(list, state), Form.compile(elem, state)] + ) + end + + def rewrite({{:., _, [:lists, _]}, _, [list]}, state) do + J.call_expression( + J.member_expression( + J.call_expression( + J.member_expression( + Form.compile(list, state), + J.identifier("concat") + ), + [J.array_expression([])] + ), + J.identifier("reverse") + ), + [] + ) + end + end diff --git a/lib/elixir_script/experimental/functions/maps.ex b/lib/elixir_script/experimental/functions/maps.ex index 8e4d1377..4e528d8a 100644 --- a/lib/elixir_script/experimental/functions/maps.ex +++ b/lib/elixir_script/experimental/functions/maps.ex @@ -35,4 +35,51 @@ defmodule ElixirScript.Experimental.Functions.Maps do ) end + def rewrite({{:., _, [:maps, :put]}, _, [key, map, _]}, state) do + J.call_expression( + J.member_expression( + J.member_expression( + J.member_expression( + J.identifier("Bootstrap"), + J.identifier("Core") + ), + J.identifier("Functions") + ), + J.identifier("update_map") + ), + [Form.compile(key, state), Form.compile(map, state)] + ) + end + + def rewrite({{:., _, [:maps, :is_key]}, _, [key, map]}, state) do + J.call_expression( + J.member_expression( + J.member_expression( + J.member_expression( + J.identifier("Bootstrap"), + J.identifier("Core") + ), + J.identifier("Functions") + ), + J.identifier("update_map") + ), + [Form.compile(key, state), Form.compile(map, state)] + ) + end + + def rewrite({{:., _, [:maps, _]}, _, _}, state) do + J.call_expression( + J.member_expression( + J.member_expression( + J.member_expression( + J.identifier("Bootstrap"), + J.identifier("Core") + ), + J.identifier("Functions") + ), + J.identifier("update_map") + ), + [] + ) + end end diff --git a/lib/elixir_script/experimental/module.ex b/lib/elixir_script/experimental/module.ex index 25d384eb..8aba34b3 100644 --- a/lib/elixir_script/experimental/module.ex +++ b/lib/elixir_script/experimental/module.ex @@ -9,13 +9,18 @@ defmodule ElixirScript.Experimental.Module do """ def compile(module, pid) do + IO.inspect "Compiling #{inspect module}" info = case ElixirScript.Beam.debug_info(module) do {:ok, info} -> - info + compile_module(module, info, pid) + {:ok, module, implementations} -> + compile_protocol(module, implementations, pid) {:error, error} -> raise "An error occurred while compiling #{inspect module}: #{error}" end + end + defp compile_module(module, info, pid) do %{ attributes: _attrs, compile_opts: _compile_opts, @@ -51,7 +56,13 @@ defmodule ElixirScript.Experimental.Module do nil ) - ModuleState.put_module(pid, module, Map.put(module_info, :js_ast, hd(js_ast))) + ModuleState.put_module(pid, module, Map.put(module_info, :js_ast, hd(js_ast))) + end + + defp compile_protocol(module, implementations, pid) do + ModuleState.put_module(pid, module, %{}) + + Enum.each(implementations, fn({impl, info}) -> compile_module(impl, info, pid) end) end defp make_exports(reachable_defs) do @@ -66,9 +77,19 @@ defmodule ElixirScript.Experimental.Module do J.object_expression(exports) end + def is_elixir_module(Elixir) do + true + end + def is_elixir_module(module) when is_atom(module) do - first_char = String.first(to_string(module)) - Regex.match?(~r/[A-Z]/, first_char) + str_module = Atom.to_string(module) + + case str_module do + "Elixir." <> _ -> + true + _ -> + false + end end def is_elixir_module(_) do diff --git a/lib/elixir_script/next/beam.ex b/lib/elixir_script/next/beam.ex index 975ec593..8272eeeb 100644 --- a/lib/elixir_script/next/beam.ex +++ b/lib/elixir_script/next/beam.ex @@ -3,8 +3,14 @@ defmodule ElixirScript.Beam do @spec debug_info(atom) :: {:ok | :error, map | binary} def debug_info(module) when is_atom(module) do with {_, beam, _} <- :code.get_object_code(module), - {:ok, {^module, [debug_info: {:debug_info_v1, backend, data}]}} <- :beam_lib.chunks(beam, [:debug_info]) do - backend.debug_info(:elixir_v1, module, data, []) + {:ok, {^module, [debug_info: {:debug_info_v1, backend, data}]}} <- :beam_lib.chunks(beam, [:debug_info]), + {:ok, {^module, attribute_info}} = :beam_lib.chunks(beam, [:attributes]) do + + if Keyword.get(attribute_info[:attributes], :protocol) do + get_protocol_implementations(module) + else + backend.debug_info(:elixir_v1, module, data, []) + end else :error -> {:error, "Unknown module"} @@ -13,7 +19,22 @@ defmodule ElixirScript.Beam do {:error,:beam_lib,{:file_error,"non_existing.beam",:enoent}} -> {:error, "Debug info not available"} end + end + + defp get_protocol_implementations(module) do + implementations = module + |> Protocol.extract_impls(:code.get_path()) + |> Enum.map(fn(x) -> Module.concat([module, x]) end) + |> Enum.map(fn(x) -> + case debug_info(x) do + {:ok, info} -> + {x, info} + _ -> + raise "Unable to compile protocol implementation #{inspect x}" + end + end) + {:ok, module, implementations} end end \ No newline at end of file diff --git a/lib/elixir_script/next/compiler.ex b/lib/elixir_script/next/compiler.ex index 44c99b45..586988bb 100644 --- a/lib/elixir_script/next/compiler.ex +++ b/lib/elixir_script/next/compiler.ex @@ -16,7 +16,14 @@ defmodule ElixirScript.Compiler do end) modules = ElixirScript.State.list_modules(pid) - |> Enum.map(fn {_module, info} -> info.js_ast end) + |> Enum.filter_map( + fn {_, info} -> Map.has_key?(info, :js_ast) end, + fn {_module, info} -> + info.js_ast + end + ) + + Enum.map() bundle(modules, opts) diff --git a/lib/elixir_script/next/state.ex b/lib/elixir_script/next/state.ex index 18418929..bd0f4735 100644 --- a/lib/elixir_script/next/state.ex +++ b/lib/elixir_script/next/state.ex @@ -27,7 +27,7 @@ defmodule ElixirScript.State do def get_javascript_modules(pid) do Agent.get(pid, fn(state) -> - Keyword.get(state.compiler_opts, :js_modules, []) + Map.get(state.compiler_opts, :js_modules, []) |> Enum.map(fn({module_name, _path}) -> module_name end) diff --git a/lib/elixir_script/translator/kernel/special_forms/identifier.ex b/lib/elixir_script/translator/kernel/special_forms/identifier.ex index 2542260c..d44bb6b7 100644 --- a/lib/elixir_script/translator/kernel/special_forms/identifier.ex +++ b/lib/elixir_script/translator/kernel/special_forms/identifier.ex @@ -51,6 +51,10 @@ defmodule ElixirScript.Translator.Identifier do |> JS.identifier end + defp filter_name(name) when is_tuple(name) do + name + end + defp filter_name(reserved_word) when reserved_word in @js_reserved_words do "__#{Atom.to_string(reserved_word)}__" end diff --git a/test/beam_test.exs b/test/beam_test.exs index 5d52e87e..bfcbb798 100644 --- a/test/beam_test.exs +++ b/test/beam_test.exs @@ -3,6 +3,5 @@ defmodule ElixirScript.Beam.Test do test "can get ast from beam" do assert {:ok, map} = ElixirScript.Beam.debug_info(Atom) - IO.inspect map end end From 82ca2c640aa26198ed906a72726455e65436c7fa Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Mon, 22 May 2017 22:13:32 -0500 Subject: [PATCH 535/860] Add pass to find used modules and functions --- lib/elixir_script/experimental/forms/for.ex | 10 +- lib/elixir_script/next/compiler.ex | 11 +- lib/elixir_script/next/find_used.ex | 248 ++++++++++++++++++++ 3 files changed, 259 insertions(+), 10 deletions(-) create mode 100644 lib/elixir_script/next/find_used.ex diff --git a/lib/elixir_script/experimental/forms/for.ex b/lib/elixir_script/experimental/forms/for.ex index 1313aedd..bf623836 100644 --- a/lib/elixir_script/experimental/forms/for.ex +++ b/lib/elixir_script/experimental/forms/for.ex @@ -57,11 +57,11 @@ defmodule ElixirScript.Experimental.Forms.For do ({:<<>>, _, body}, state) -> {bs_parts, collection} = Enum.map_reduce(body, nil, fn - {:::, _, _} = ast, state -> - {ast, state} - {:<-, _, [var, collection]}, _ -> - {var, collection} - end) + {:::, _, _} = ast, state -> + {ast, state} + {:<-, _, [var, collection]}, _ -> + {var, collection} + end) {patterns, params} = Pattern.compile([{:<<>>, [], bs_parts}], module_state) diff --git a/lib/elixir_script/next/compiler.ex b/lib/elixir_script/next/compiler.ex index 586988bb..4895604b 100644 --- a/lib/elixir_script/next/compiler.ex +++ b/lib/elixir_script/next/compiler.ex @@ -5,8 +5,10 @@ defmodule ElixirScript.Compiler do opts = build_compiler_options(opts) {:ok, pid} = ElixirScript.State.start_link(opts) - modules = List.wrap(entry_modules) - Enum.each(modules, fn(module) -> + entry_modules + |> List.wrap + |> ElixirScript.FindUsed.find_used(pid) + |> Enum.each(fn(module) -> case ElixirScript.State.get_module(pid, module) do nil -> ElixirScript.Experimental.Module.compile(module, pid) @@ -15,7 +17,8 @@ defmodule ElixirScript.Compiler do end end) - modules = ElixirScript.State.list_modules(pid) + modules = pid + |> ElixirScript.State.list_modules |> Enum.filter_map( fn {_, info} -> Map.has_key?(info, :js_ast) end, fn {_module, info} -> @@ -23,8 +26,6 @@ defmodule ElixirScript.Compiler do end ) - Enum.map() - bundle(modules, opts) ElixirScript.State.stop(pid) diff --git a/lib/elixir_script/next/find_used.ex b/lib/elixir_script/next/find_used.ex new file mode 100644 index 00000000..a534f5aa --- /dev/null +++ b/lib/elixir_script/next/find_used.ex @@ -0,0 +1,248 @@ +defmodule ElixirScript.FindUsed do + alias ElixirScript.State, as: ModuleState + + def find_used(modules, pid) do + Enum.each(List.wrap(modules), fn(module) -> + if ElixirScript.State.get_module(pid, module) == nil do + execute(module, pid) + end + end) + end + + defp execute(module, pid) do + case ElixirScript.Beam.debug_info(module) do + {:ok, info} -> + walk_module(module, info, pid) + {:ok, module, implementations} -> + walk_protocol(module, implementations, pid) + {:error, error} -> + raise "An error occurred while compiling #{inspect module}: #{error}" + end + end + + defp walk_module(module, info, pid) do + %{ + attributes: _attrs, + walk_opts: _walk_opts, + definitions: defs, + file: _file, + line: _line, + module: ^module, + unreachable: unreachable + } = info + + module_info = %{module: module, info: info} + ModuleState.put_module(pid, module, module_info) + + reachable_defs = Enum.filter(defs, fn + { _, type, _, _} when type in [:defmacro, :defmacrop] -> false + { name, _, _, _} -> not(name in unreachable) + _ -> true + end) + + state = %{ + pid: pid + } + + Enum.each(reachable_defs, &walk(&1, state)) + + end + + defp walk_protocol(module, implementations, pid) do + ModuleState.put_module(pid, module, %{}) + Enum.each(implementations, fn({impl, info}) -> walk_module(impl, info, pid) end) + end + + defp walk({{_name, _arity}, _type, _, clauses}, state) do + Enum.each(clauses, &walk(&1, state)) + end + + defp walk({ _, _args, _guards, body}, state) do + case body do + nil -> + nil + {:__block__, _, block_body} -> + Enum.map(block_body, &walk(&1, state)) + b when is_list(b) -> + Enum.map(b, &walk(&1, state)) + _ -> + walk(body, state) + end + end + + defp walk({:->, _, [[{:when, _, params}], body ]}, state) do + guards = List.last(params) + params = params |> Enum.reverse |> tl |> Enum.reverse + + walk({[], params, guards, body}, state) + end + + defp walk({:->, _, [params, body]}, state) do + walk({[], params, [], body}, state) + end + + defp walk(nil, _) do + nil + end + + defp walk(form, _) when is_boolean(form) when is_integer(form) when is_float(form) when is_binary(form) do + nil + end + + defp walk(form, state) when is_list(form) do + Enum.each(form, &walk(&1, state)) + end + + defp walk(form, state) when is_atom(form) do + if ElixirScript.Experimental.Module.is_elixir_module(form) do + if ModuleState.get_module(state.pid, form) == nil do + execute(form, state.pid) + end + end + end + + defp walk({a, b}, state) do + walk({:{}, [], [a, b]}, state) + end + + defp walk({:{}, _, elements}, state) do + Enum.each(elements, &walk(&1, state)) + end + + defp walk({:%{}, _, properties}, state) do + Enum.each(properties, fn (val) -> walk(val, state) end) + end + + defp walk({:<<>>, _, elements}, state) do + Enum.each(elements, fn (val) -> walk(val, state) end) + end + + defp walk({:=, _, [left, right]}, state) do + walk(left, state) + walk(right, state) + end + + defp walk({:%, _, [module, params]}, state) do + if ElixirScript.Experimental.Module.is_elixir_module(module) do + if ModuleState.get_module(state.pid, module) == nil do + execute(module, state.pid) + end + end + Enum.each(params, &walk(&1, state)) + end + + defp walk({:for, _, generators}, state) do + Enum.each(generators, fn + {:<<>>, _, body} -> + walk(body, state) + + {:<-, _, [identifier, enum]} -> + walk(identifier, state) + walk(enum, state) + + [into: expression] -> + walk(expression, state) + + [into: expression, do: expression2] -> + walk(expression, state) + walk(expression2, state) + + [do: expression] -> + walk(expression, state) + + filter -> + walk(filter, state) + end) + end + + defp walk({:case, _, [condition, [do: clauses]]}, state) do + Enum.each(clauses, &walk(&1, state)) + walk(condition, state) + end + + defp walk({:cond, _, [[do: clauses]]}, state) do + Enum.each(clauses, fn({:->, _, [clause, clause_body]}) -> + Enum.each(List.wrap(clause_body), &walk(&1, state)) + walk(hd(clause), state) + end) + end + + defp walk({:receive, _context, _}, _state) do + nil + end + + defp walk({:try, _, [blocks]}, state) do + try_block = Keyword.get(blocks, :do) + rescue_block = Keyword.get(blocks, :rescue, nil) + catch_block = Keyword.get(blocks, :catch, nil) + after_block = Keyword.get(blocks, :after, nil) + else_block = Keyword.get(blocks, :else, nil) + + Enum.each(List.wrap(try_block), &walk(&1, state)) + + if rescue_block do + Enum.each(rescue_block, fn + {:->, _, [ [{:in, _, [param, names]}], body]} -> + walk({[], [param], [{{:., [], [Enum, :member?]}, [], [param, names]}], body}, state) + {:->, _, [ [param], body]} -> + walk({[], [param], [], body}, state) + end) + end + + if catch_block do + walk({:fn, [], catch_block}, state) + end + + if after_block do + Enum.each(List.wrap(after_block), &walk(&1, state)) + end + + if else_block do + walk({:fn, [], else_block}, state) + end + end + + defp walk({:fn, _, clauses}, state) do + Enum.each(clauses, &walk(&1, state)) + end + + defp walk({{:., _, [:erlang, _]}, _, _}, _state) do + nil + end + + defp walk({{:., _, [:lists, _]}, _, _}, _state) do + nil + end + + defp walk({{:., _, [:maps, _]}, _, _}, _state) do + nil + end + + defp walk({{:., _, [module, _]}, _, params}, state) do + cond do + ElixirScript.Experimental.Module.is_js_module(module, state) -> + nil + ElixirScript.Experimental.Module.is_elixir_module(module) -> + if ModuleState.get_module(state.pid, module) == nil do + execute(module, state.pid) + end + true -> + nil + end + + Enum.each(params, &walk(&1, state)) + end + + defp walk({:super, _, params}, state) do + Enum.each(params, &walk(&1, state)) + end + + defp walk({_, _, params}, state) when is_list(params) do + Enum.each(params, &walk(&1, state)) + end + + defp walk({_, _, _}, _state) do + nil + end + +end \ No newline at end of file From db214817c0cf17b5b5f987a177986e9bb801ccda Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Mon, 22 May 2017 23:06:01 -0500 Subject: [PATCH 536/860] Fix used crawling --- lib/elixir_script/experimental/backend.ex | 33 --------------- .../experimental/examples/example.ex | 6 ++- lib/elixir_script/experimental/forms/call.ex | 6 --- lib/elixir_script/experimental/module.ex | 33 +++------------ lib/elixir_script/next/compiler.ex | 21 +++++----- lib/elixir_script/next/find_used.ex | 41 +++++++++---------- lib/elixir_script/next/state.ex | 15 +++++++ .../kernel/special_forms/identifier.ex | 4 ++ 8 files changed, 61 insertions(+), 98 deletions(-) delete mode 100644 lib/elixir_script/experimental/backend.ex diff --git a/lib/elixir_script/experimental/backend.ex b/lib/elixir_script/experimental/backend.ex deleted file mode 100644 index a5d3d4e0..00000000 --- a/lib/elixir_script/experimental/backend.ex +++ /dev/null @@ -1,33 +0,0 @@ -defmodule ElixirScript.Experimental.Backend do - alias ElixirScript.Experimental.Module - alias ESTree.Tools.Generator - alias ElixirScript.Experimental.ModuleState - - def compile(line, file, module, attrs, defs, unreachable, opts) do - # Print all arguments - #IO.inspect binding() - - # Compile module to JavaScript AST - js_ast = Module.compile(line, file, module, attrs, defs, unreachable, opts) - - # Generate JavaScript code string - js_code = Generator.generate(js_ast) - - #IO.puts js_code - - write_js(module, js_code) - # Invoke the default backend - it returns the compiled beam binary - :elixir_erl.compile(line, file, module, attrs, defs, unreachable, opts) - end - - defp write_js(module, js_code) do - output_dir = Path.join([Mix.Project.build_path(), "_javascript"]) - - if !File.exists?(output_dir) do - File.mkdir_p!(output_dir) - end - - output_path = Path.join([output_dir, "#{module}.js"]) - File.write!(output_path, js_code) - end -end diff --git a/lib/elixir_script/experimental/examples/example.ex b/lib/elixir_script/experimental/examples/example.ex index 2761f632..677bf0f8 100644 --- a/lib/elixir_script/experimental/examples/example.ex +++ b/lib/elixir_script/experimental/examples/example.ex @@ -1,6 +1,10 @@ defmodule Example do def new() do - Base.encode16("foobar") + newnew() + end + + def newnew() do + Atom.to_string("hello") end end diff --git a/lib/elixir_script/experimental/forms/call.ex b/lib/elixir_script/experimental/forms/call.ex index efd578c3..062abc05 100644 --- a/lib/elixir_script/experimental/forms/call.ex +++ b/lib/elixir_script/experimental/forms/call.ex @@ -2,17 +2,11 @@ defmodule ElixirScript.Experimental.Forms.Call do alias ESTree.Tools.Builder, as: J alias ElixirScript.Experimental.Form alias ElixirScript.Translator.Identifier - alias ElixirScript.State, as: ModuleState def compile({{:., _, [module, function]}, _, params}, state) do function_name = cond do ElixirScript.Experimental.Module.is_js_module(module, state) -> ElixirScript.Translator.Identifier.make_extern_function_name(function) - ElixirScript.Experimental.Module.is_elixir_module(module) -> - if ModuleState.get_module(state.pid, module) == nil do - ElixirScript.Experimental.Module.compile(module, state.pid) - end - ElixirScript.Translator.Identifier.make_function_name(function, length(params)) true -> ElixirScript.Translator.Identifier.make_function_name(function, length(params)) end diff --git a/lib/elixir_script/experimental/module.ex b/lib/elixir_script/experimental/module.ex index 8aba34b3..3d30a09d 100644 --- a/lib/elixir_script/experimental/module.ex +++ b/lib/elixir_script/experimental/module.ex @@ -8,19 +8,7 @@ defmodule ElixirScript.Experimental.Module do Upper level module that handles compilation """ - def compile(module, pid) do - IO.inspect "Compiling #{inspect module}" - info = case ElixirScript.Beam.debug_info(module) do - {:ok, info} -> - compile_module(module, info, pid) - {:ok, module, implementations} -> - compile_protocol(module, implementations, pid) - {:error, error} -> - raise "An error occurred while compiling #{inspect module}: #{error}" - end - end - - defp compile_module(module, info, pid) do + def compile(module, info, pid) do %{ attributes: _attrs, compile_opts: _compile_opts, @@ -28,7 +16,8 @@ defmodule ElixirScript.Experimental.Module do file: _file, line: _line, module: ^module, - unreachable: unreachable + unreachable: _unreachable, + used: used } = info state = %{ @@ -36,14 +25,10 @@ defmodule ElixirScript.Experimental.Module do } reachable_defs = Enum.filter(defs, fn - { name, _, _, _} -> not(name in unreachable) - { _, type, _, _} when type in [:defmacro, :defmacrop] -> false - _ -> true + { name, _, _, _} -> name in used + _ -> false end) - module_info = %{module: module, defs: defs} - ModuleState.put_module(pid, module, module_info) - compiled_functions = reachable_defs |> Enum.map(&Function.compile(&1, state)) @@ -56,13 +41,7 @@ defmodule ElixirScript.Experimental.Module do nil ) - ModuleState.put_module(pid, module, Map.put(module_info, :js_ast, hd(js_ast))) - end - - defp compile_protocol(module, implementations, pid) do - ModuleState.put_module(pid, module, %{}) - - Enum.each(implementations, fn({impl, info}) -> compile_module(impl, info, pid) end) + ModuleState.put_module(pid, module, Map.put(info, :js_ast, hd(js_ast))) end defp make_exports(reachable_defs) do diff --git a/lib/elixir_script/next/compiler.ex b/lib/elixir_script/next/compiler.ex index 4895604b..f826bfc6 100644 --- a/lib/elixir_script/next/compiler.ex +++ b/lib/elixir_script/next/compiler.ex @@ -5,21 +5,21 @@ defmodule ElixirScript.Compiler do opts = build_compiler_options(opts) {:ok, pid} = ElixirScript.State.start_link(opts) + IO.puts "Finding used modules and functions" entry_modules |> List.wrap |> ElixirScript.FindUsed.find_used(pid) - |> Enum.each(fn(module) -> - case ElixirScript.State.get_module(pid, module) do - nil -> - ElixirScript.Experimental.Module.compile(module, pid) - _ -> - nil - end + + modules = ElixirScript.State.list_modules(pid) + + IO.puts "Compiling" + Enum.each(modules, fn({module, info}) -> + ElixirScript.Experimental.Module.compile(module, info, pid) end) - modules = pid - |> ElixirScript.State.list_modules - |> Enum.filter_map( + modules = ElixirScript.State.list_modules(pid) + + modules = Enum.filter_map(modules, fn {_, info} -> Map.has_key?(info, :js_ast) end, fn {_module, info} -> info.js_ast @@ -42,6 +42,7 @@ defmodule ElixirScript.Compiler do |> Generator.generate concat(js_code) + |> IO.puts end defp concat(code) do diff --git a/lib/elixir_script/next/find_used.ex b/lib/elixir_script/next/find_used.ex index a534f5aa..4a44c71f 100644 --- a/lib/elixir_script/next/find_used.ex +++ b/lib/elixir_script/next/find_used.ex @@ -10,6 +10,7 @@ defmodule ElixirScript.FindUsed do end defp execute(module, pid) do + IO.inspect module case ElixirScript.Beam.debug_info(module) do {:ok, info} -> walk_module(module, info, pid) @@ -23,7 +24,7 @@ defmodule ElixirScript.FindUsed do defp walk_module(module, info, pid) do %{ attributes: _attrs, - walk_opts: _walk_opts, + compile_opts: _compile_opts, definitions: defs, file: _file, line: _line, @@ -31,8 +32,7 @@ defmodule ElixirScript.FindUsed do unreachable: unreachable } = info - module_info = %{module: module, info: info} - ModuleState.put_module(pid, module, module_info) + ModuleState.put_module(pid, module, info) reachable_defs = Enum.filter(defs, fn { _, type, _, _} when type in [:defmacro, :defmacrop] -> false @@ -41,7 +41,8 @@ defmodule ElixirScript.FindUsed do end) state = %{ - pid: pid + pid: pid, + module: module } Enum.each(reachable_defs, &walk(&1, state)) @@ -81,25 +82,17 @@ defmodule ElixirScript.FindUsed do walk({[], params, [], body}, state) end - defp walk(nil, _) do - nil - end - - defp walk(form, _) when is_boolean(form) when is_integer(form) when is_float(form) when is_binary(form) do - nil - end - defp walk(form, state) when is_list(form) do Enum.each(form, &walk(&1, state)) end - defp walk(form, state) when is_atom(form) do - if ElixirScript.Experimental.Module.is_elixir_module(form) do - if ModuleState.get_module(state.pid, form) == nil do - execute(form, state.pid) - end - end - end + #defp walk(form, state) when is_atom(form) do + #if ElixirScript.Experimental.Module.is_elixir_module(form) do + # if ModuleState.get_module(state.pid, form) == nil do + # execute(form, state.pid) + # end + #end + #end defp walk({a, b}, state) do walk({:{}, [], [a, b]}, state) @@ -218,7 +211,7 @@ defmodule ElixirScript.FindUsed do nil end - defp walk({{:., _, [module, _]}, _, params}, state) do + defp walk({{:., _, [module, function]}, _, params}, state) do cond do ElixirScript.Experimental.Module.is_js_module(module, state) -> nil @@ -226,6 +219,7 @@ defmodule ElixirScript.FindUsed do if ModuleState.get_module(state.pid, module) == nil do execute(module, state.pid) end + ModuleState.add_used(state.pid, module, {function, length(params)}) true -> nil end @@ -237,11 +231,16 @@ defmodule ElixirScript.FindUsed do Enum.each(params, &walk(&1, state)) end + defp walk({function, _, params}, state) when is_atom(function) and is_list(params) do + ModuleState.add_used(state.pid, state.module, {function, length(params)}) + Enum.each(params, &walk(&1, state)) + end + defp walk({_, _, params}, state) when is_list(params) do Enum.each(params, &walk(&1, state)) end - defp walk({_, _, _}, _state) do + defp walk(_, _) do nil end diff --git a/lib/elixir_script/next/state.ex b/lib/elixir_script/next/state.ex index bd0f4735..ccc837bf 100644 --- a/lib/elixir_script/next/state.ex +++ b/lib/elixir_script/next/state.ex @@ -21,10 +21,25 @@ defmodule ElixirScript.State do def put_module(pid, module, value) do Agent.update(pid, fn(state) -> + value = Map.put(value, :used, []) %{ state | modules: Keyword.put(state.modules, module, value) } end) end + def add_used(pid, module, {_function, _arity} = func) do + Agent.update(pid, fn(state) -> + module_info = Keyword.get(state.modules, module) + + used = Map.get(module_info, :used, []) + used = used ++ [func] + + module_info = Map.put(module_info, :used, used) + modules = Keyword.put(state.modules, module, module_info) + + %{ state | modules: modules } + end) + end + def get_javascript_modules(pid) do Agent.get(pid, fn(state) -> Map.get(state.compiler_opts, :js_modules, []) diff --git a/lib/elixir_script/translator/kernel/special_forms/identifier.ex b/lib/elixir_script/translator/kernel/special_forms/identifier.ex index d44bb6b7..99586343 100644 --- a/lib/elixir_script/translator/kernel/special_forms/identifier.ex +++ b/lib/elixir_script/translator/kernel/special_forms/identifier.ex @@ -91,4 +91,8 @@ defmodule ElixirScript.Translator.Identifier do JS.identifier("#{name}#{arity}") end + def make_extern_function_name(name) do + JS.identifier("#{name}") + end + end From dc5d1ba165f8189155ddc9fb68e6e4b8042517d0 Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Fri, 26 May 2017 20:40:18 -0500 Subject: [PATCH 537/860] Refactor file paths and add documentation --- .tool-versions | 2 +- .../experimental/examples/size.ex | 22 ------- lib/elixir_script/next/beam.ex | 7 ++ lib/elixir_script/next/compiler.ex | 60 ++--------------- .../next/{ => passes}/find_used.ex | 24 ++++--- lib/elixir_script/next/passes/translate.ex | 64 +++++++++++++++++++ .../passes/translate}/clause.ex | 6 +- .../passes/translate}/examples/example.ex | 0 .../next/passes/translate/examples/size.ex | 22 +++++++ .../passes/translate}/form.ex | 16 ++--- .../passes/translate}/forms/bitstring.ex | 4 +- .../passes/translate}/forms/call.ex | 10 +-- .../passes/translate}/forms/for.ex | 8 +-- .../passes/translate}/forms/map.ex | 4 +- .../passes/translate}/forms/match.ex | 6 +- .../passes/translate}/forms/pattern.ex | 6 +- .../passes/translate}/forms/struct.ex | 4 +- .../passes/translate}/forms/try.ex | 8 +-- .../passes/translate}/function.ex | 4 +- .../passes/translate}/functions/erlang.ex | 4 +- .../passes/translate}/functions/lists.ex | 4 +- .../passes/translate}/functions/maps.ex | 4 +- .../passes/translate}/module.ex | 19 +++--- .../passes/translate}/module_state.ex | 2 +- lib/elixir_script/next/state.ex | 10 +++ mix.lock | 30 ++++----- 26 files changed, 197 insertions(+), 153 deletions(-) delete mode 100644 lib/elixir_script/experimental/examples/size.ex rename lib/elixir_script/next/{ => passes}/find_used.ex (89%) create mode 100644 lib/elixir_script/next/passes/translate.ex rename lib/elixir_script/{experimental => next/passes/translate}/clause.ex (94%) rename lib/elixir_script/{experimental => next/passes/translate}/examples/example.ex (100%) create mode 100644 lib/elixir_script/next/passes/translate/examples/size.ex rename lib/elixir_script/{experimental => next/passes/translate}/form.ex (90%) rename lib/elixir_script/{experimental => next/passes/translate}/forms/bitstring.ex (97%) rename lib/elixir_script/{experimental => next/passes/translate}/forms/call.ex (77%) rename lib/elixir_script/{experimental => next/passes/translate}/forms/for.ex (95%) rename lib/elixir_script/{experimental => next/passes/translate}/forms/map.ex (94%) rename lib/elixir_script/{experimental => next/passes/translate}/forms/match.ex (93%) rename lib/elixir_script/{experimental => next/passes/translate}/forms/pattern.ex (96%) rename lib/elixir_script/{experimental => next/passes/translate}/forms/struct.ex (83%) rename lib/elixir_script/{experimental => next/passes/translate}/forms/try.ex (92%) rename lib/elixir_script/{experimental => next/passes/translate}/function.ex (90%) rename lib/elixir_script/{experimental => next/passes/translate}/functions/erlang.ex (99%) rename lib/elixir_script/{experimental => next/passes/translate}/functions/lists.ex (97%) rename lib/elixir_script/{experimental => next/passes/translate}/functions/maps.ex (95%) rename lib/elixir_script/{experimental => next/passes/translate}/module.ex (82%) rename lib/elixir_script/{experimental => next/passes/translate}/module_state.ex (87%) diff --git a/.tool-versions b/.tool-versions index 822dfebc..09178de1 100644 --- a/.tool-versions +++ b/.tool-versions @@ -1,3 +1,3 @@ -elixir 1.5.0-dev erlang ref-OTP-20.0-rc1 +elixir ref-9825280 nodejs 7.10.0 \ No newline at end of file diff --git a/lib/elixir_script/experimental/examples/size.ex b/lib/elixir_script/experimental/examples/size.ex deleted file mode 100644 index e16baa30..00000000 --- a/lib/elixir_script/experimental/examples/size.ex +++ /dev/null @@ -1,22 +0,0 @@ -defprotocol Example.Size do - @compile {:undocumented_elixir_backend_option, ElixirScript.Experimental.Backend} - def size(data) -end - -defimpl Example.Size, for: BitString do - @compile {:undocumented_elixir_backend_option, ElixirScript.Experimental.Backend} - - def size(string), do: byte_size(string) -end - -defimpl Example.Size, for: Map do - @compile {:undocumented_elixir_backend_option, ElixirScript.Experimental.Backend} - - def size(map), do: map_size(map) -end - -defimpl Example.Size, for: Tuple do - @compile {:undocumented_elixir_backend_option, ElixirScript.Experimental.Backend} - - def size(tuple), do: tuple_size(tuple) -end \ No newline at end of file diff --git a/lib/elixir_script/next/beam.ex b/lib/elixir_script/next/beam.ex index 8272eeeb..c6183758 100644 --- a/lib/elixir_script/next/beam.ex +++ b/lib/elixir_script/next/beam.ex @@ -1,5 +1,12 @@ defmodule ElixirScript.Beam do + @moduledoc false + @doc """ + Takes a module and finds the expanded AST + from the debug info inside the beam file. + For protocols, this will return a list of + all the protocol implementations + """ @spec debug_info(atom) :: {:ok | :error, map | binary} def debug_info(module) when is_atom(module) do with {_, beam, _} <- :code.get_object_code(module), diff --git a/lib/elixir_script/next/compiler.ex b/lib/elixir_script/next/compiler.ex index f826bfc6..864fa645 100644 --- a/lib/elixir_script/next/compiler.ex +++ b/lib/elixir_script/next/compiler.ex @@ -1,6 +1,9 @@ defmodule ElixirScript.Compiler do - alias ESTree.Tools.{Builder, Generator} - + @moduledoc """ + Compiles the given modules to JavaScript. + """ + + @spec compile([atom], []) :: nil def compile(entry_modules, opts \\ []) do opts = build_compiler_options(opts) {:ok, pid} = ElixirScript.State.start_link(opts) @@ -8,70 +11,21 @@ defmodule ElixirScript.Compiler do IO.puts "Finding used modules and functions" entry_modules |> List.wrap - |> ElixirScript.FindUsed.find_used(pid) - - modules = ElixirScript.State.list_modules(pid) + |> ElixirScript.FindUsed.execute(pid) IO.puts "Compiling" - Enum.each(modules, fn({module, info}) -> - ElixirScript.Experimental.Module.compile(module, info, pid) - end) - modules = ElixirScript.State.list_modules(pid) - modules = Enum.filter_map(modules, - fn {_, info} -> Map.has_key?(info, :js_ast) end, - fn {_module, info} -> - info.js_ast - end - ) - - bundle(modules, opts) + ElixirScript.Translate.execute(modules, pid) ElixirScript.State.stop(pid) end - defp bundle(modules, opts) do - ElixirScript.Passes.CreateJSModules.compile(modules, opts) - - js_code = modules - |> ElixirScript.Passes.CreateJSModules.compile(opts) - |> List.wrap - |> Builder.program - |> prepare_js_ast - |> Generator.generate - - concat(js_code) - |> IO.puts - end - - defp concat(code) do - "'use strict';\n" <> ElixirScript.get_bootstrap_js("iife") <> "\n" <> code - end - - defp prepare_js_ast(js_ast) do - case js_ast do - modules when is_list(modules) -> - modules - |> Enum.reduce([], &(&2 ++ &1.body)) - |> Builder.program - %ElixirScript.Translator.Group{body: body} -> - Builder.program(body) - %ElixirScript.Translator.Empty{} -> - Builder.program([]) - _ -> - js_ast - end - end - defp build_compiler_options(opts) do default_options = Map.new - |> Map.put(:full_build, false) |> Map.put(:output, nil) - |> Map.put(:app, :app) |> Map.put(:format, :es) |> Map.put(:js_modules, Keyword.get(opts, :js_modules, [])) - |> Map.put(:remove_unused, false) options = default_options Map.put(options, :module_formatter, get_module_formatter(options[:format])) diff --git a/lib/elixir_script/next/find_used.ex b/lib/elixir_script/next/passes/find_used.ex similarity index 89% rename from lib/elixir_script/next/find_used.ex rename to lib/elixir_script/next/passes/find_used.ex index 4a44c71f..8a19d9e6 100644 --- a/lib/elixir_script/next/find_used.ex +++ b/lib/elixir_script/next/passes/find_used.ex @@ -1,16 +1,22 @@ defmodule ElixirScript.FindUsed do + @moduledoc false alias ElixirScript.State, as: ModuleState - def find_used(modules, pid) do + @doc """ + Takes a list of entry modules and finds modules they use along with + documenting the functions used. The data collected about used functions + is used to filter only the used functions for compilation + """ + @spec execute([atom], pid) :: nil + def execute(modules, pid) do Enum.each(List.wrap(modules), fn(module) -> if ElixirScript.State.get_module(pid, module) == nil do - execute(module, pid) + do_execute(module, pid) end end) end - defp execute(module, pid) do - IO.inspect module + defp do_execute(module, pid) do case ElixirScript.Beam.debug_info(module) do {:ok, info} -> walk_module(module, info, pid) @@ -87,7 +93,7 @@ defmodule ElixirScript.FindUsed do end #defp walk(form, state) when is_atom(form) do - #if ElixirScript.Experimental.Module.is_elixir_module(form) do + #if ElixirScript.Translate.Module.is_elixir_module(form) do # if ModuleState.get_module(state.pid, form) == nil do # execute(form, state.pid) # end @@ -116,9 +122,9 @@ defmodule ElixirScript.FindUsed do end defp walk({:%, _, [module, params]}, state) do - if ElixirScript.Experimental.Module.is_elixir_module(module) do + if ElixirScript.Translate.Module.is_elixir_module(module) do if ModuleState.get_module(state.pid, module) == nil do - execute(module, state.pid) + do_execute(module, state.pid) end end Enum.each(params, &walk(&1, state)) @@ -213,9 +219,9 @@ defmodule ElixirScript.FindUsed do defp walk({{:., _, [module, function]}, _, params}, state) do cond do - ElixirScript.Experimental.Module.is_js_module(module, state) -> + ElixirScript.Translate.Module.is_js_module(module, state) -> nil - ElixirScript.Experimental.Module.is_elixir_module(module) -> + ElixirScript.Translate.Module.is_elixir_module(module) -> if ModuleState.get_module(state.pid, module) == nil do execute(module, state.pid) end diff --git a/lib/elixir_script/next/passes/translate.ex b/lib/elixir_script/next/passes/translate.ex new file mode 100644 index 00000000..5319086a --- /dev/null +++ b/lib/elixir_script/next/passes/translate.ex @@ -0,0 +1,64 @@ +defmodule ElixirScript.Translate do + @moduledoc false + + alias ElixirScript.State, as: ModuleState + alias ESTree.Tools.{Builder, Generator} + + @doc """ + Takes a list of modules and translates their ast into + JavaScript AST. The modules are the ones collected from + the FindUsed pass. + """ + @spec execute([atom], pid) :: nil + def execute(modules, pid) do + Enum.each(modules, fn({module, info}) -> + ElixirScript.Translate.Module.compile(module, info, pid) + end) + + modules = ElixirScript.State.list_modules(pid) + + modules = Enum.filter_map(modules, + fn {_, info} -> Map.has_key?(info, :js_ast) end, + fn {_module, info} -> + info.js_ast + end + ) + + opts = ModuleState.get_compiler_opts(pid) + + bundle(modules, opts) + end + + defp bundle(modules, opts) do + ElixirScript.Passes.CreateJSModules.compile(modules, opts) + + js_code = modules + |> ElixirScript.Passes.CreateJSModules.compile(opts) + |> List.wrap + |> Builder.program + |> prepare_js_ast + |> Generator.generate + + concat(js_code) + |> IO.puts + end + + defp concat(code) do + "'use strict';\n" <> ElixirScript.get_bootstrap_js("iife") <> "\n" <> code + end + + defp prepare_js_ast(js_ast) do + case js_ast do + modules when is_list(modules) -> + modules + |> Enum.reduce([], &(&2 ++ &1.body)) + |> Builder.program + %ElixirScript.Translator.Group{body: body} -> + Builder.program(body) + %ElixirScript.Translator.Empty{} -> + Builder.program([]) + _ -> + js_ast + end + end +end diff --git a/lib/elixir_script/experimental/clause.ex b/lib/elixir_script/next/passes/translate/clause.ex similarity index 94% rename from lib/elixir_script/experimental/clause.ex rename to lib/elixir_script/next/passes/translate/clause.ex index ea61a39c..ca1553ee 100644 --- a/lib/elixir_script/experimental/clause.ex +++ b/lib/elixir_script/next/passes/translate/clause.ex @@ -1,7 +1,7 @@ -defmodule ElixirScript.Experimental.Clause do +defmodule ElixirScript.Translate.Clause do alias ESTree.Tools.Builder, as: J - alias ElixirScript.Experimental.Form - alias ElixirScript.Experimental.Forms.Pattern + alias ElixirScript.Translate.Form + alias ElixirScript.Translate.Forms.Pattern @moduledoc """ Handles translation of all of the clause ASTs diff --git a/lib/elixir_script/experimental/examples/example.ex b/lib/elixir_script/next/passes/translate/examples/example.ex similarity index 100% rename from lib/elixir_script/experimental/examples/example.ex rename to lib/elixir_script/next/passes/translate/examples/example.ex diff --git a/lib/elixir_script/next/passes/translate/examples/size.ex b/lib/elixir_script/next/passes/translate/examples/size.ex new file mode 100644 index 00000000..d2a2619d --- /dev/null +++ b/lib/elixir_script/next/passes/translate/examples/size.ex @@ -0,0 +1,22 @@ +defprotocol Example.Size do + @compile {:undocumented_elixir_backend_option, ElixirScript.Translate.Backend} + def size(data) +end + +defimpl Example.Size, for: BitString do + @compile {:undocumented_elixir_backend_option, ElixirScript.Translate.Backend} + + def size(string), do: byte_size(string) +end + +defimpl Example.Size, for: Map do + @compile {:undocumented_elixir_backend_option, ElixirScript.Translate.Backend} + + def size(map), do: map_size(map) +end + +defimpl Example.Size, for: Tuple do + @compile {:undocumented_elixir_backend_option, ElixirScript.Translate.Backend} + + def size(tuple), do: tuple_size(tuple) +end \ No newline at end of file diff --git a/lib/elixir_script/experimental/form.ex b/lib/elixir_script/next/passes/translate/form.ex similarity index 90% rename from lib/elixir_script/experimental/form.ex rename to lib/elixir_script/next/passes/translate/form.ex index 9778d4f8..e325071f 100644 --- a/lib/elixir_script/experimental/form.ex +++ b/lib/elixir_script/next/passes/translate/form.ex @@ -1,9 +1,9 @@ -defmodule ElixirScript.Experimental.Form do +defmodule ElixirScript.Translate.Form do alias ESTree.Tools.Builder, as: J - alias ElixirScript.Experimental.Forms.{Bitstring, Match, Call, Try, For, Struct} - alias ElixirScript.Experimental.Functions.{Erlang, Lists, Maps} + alias ElixirScript.Translate.Forms.{Bitstring, Match, Call, Try, For, Struct} + alias ElixirScript.Translate.Functions.{Erlang, Lists, Maps} alias ElixirScript.Translator.Identifier - alias ElixirScript.Experimental.Clause + alias ElixirScript.Translate.Clause @moduledoc """ Handles translation of all forms that are not functions or clauses @@ -24,7 +24,7 @@ defmodule ElixirScript.Experimental.Form do end def compile(form, state) when is_atom(form) do - if ElixirScript.Experimental.Module.is_elixir_module(form) do + if ElixirScript.Translate.Module.is_elixir_module(form) do members = if form == Elixir, do: ["Elixir"], else: ["Elixir"] ++ Module.split(form) J.identifier(Enum.join(members, "_")) else @@ -56,7 +56,7 @@ defmodule ElixirScript.Experimental.Form do end def compile({:%{}, _, _} = map, state) do - ElixirScript.Experimental.Forms.Map.compile(map, state) + ElixirScript.Translate.Forms.Map.compile(map, state) end def compile({:<<>>, _, _} = bitstring, state) do @@ -78,7 +78,7 @@ defmodule ElixirScript.Experimental.Form do def compile({:case, _, [condition, [do: clauses]]}, state) do func = J.call_expression( J.member_expression( - ElixirScript.Experimental.Function.patterns_ast(), + ElixirScript.Translate.Function.patterns_ast(), J.identifier("defmatch") ), Enum.map(clauses, &Clause.compile(&1, state)) @@ -133,7 +133,7 @@ defmodule ElixirScript.Experimental.Form do def compile({:fn, _, clauses}, state) do J.call_expression( J.member_expression( - ElixirScript.Experimental.Function.patterns_ast(), + ElixirScript.Translate.Function.patterns_ast(), J.identifier("defmatch") ), Enum.map(clauses, &Clause.compile(&1, state)) diff --git a/lib/elixir_script/experimental/forms/bitstring.ex b/lib/elixir_script/next/passes/translate/forms/bitstring.ex similarity index 97% rename from lib/elixir_script/experimental/forms/bitstring.ex rename to lib/elixir_script/next/passes/translate/forms/bitstring.ex index ed978e5a..e6d23408 100644 --- a/lib/elixir_script/experimental/forms/bitstring.ex +++ b/lib/elixir_script/next/passes/translate/forms/bitstring.ex @@ -1,7 +1,7 @@ -defmodule ElixirScript.Experimental.Forms.Bitstring do +defmodule ElixirScript.Translate.Forms.Bitstring do @moduledoc false alias ESTree.Tools.Builder, as: JS - alias ElixirScript.Experimental.Form + alias ElixirScript.Translate.Form def compile({:<<>>, _, elements}, state) do diff --git a/lib/elixir_script/experimental/forms/call.ex b/lib/elixir_script/next/passes/translate/forms/call.ex similarity index 77% rename from lib/elixir_script/experimental/forms/call.ex rename to lib/elixir_script/next/passes/translate/forms/call.ex index 062abc05..0715538a 100644 --- a/lib/elixir_script/experimental/forms/call.ex +++ b/lib/elixir_script/next/passes/translate/forms/call.ex @@ -1,11 +1,11 @@ -defmodule ElixirScript.Experimental.Forms.Call do +defmodule ElixirScript.Translate.Forms.Call do alias ESTree.Tools.Builder, as: J - alias ElixirScript.Experimental.Form + alias ElixirScript.Translate.Form alias ElixirScript.Translator.Identifier def compile({{:., _, [module, function]}, _, params}, state) do function_name = cond do - ElixirScript.Experimental.Module.is_js_module(module, state) -> + ElixirScript.Translate.Module.is_js_module(module, state) -> ElixirScript.Translator.Identifier.make_extern_function_name(function) true -> ElixirScript.Translator.Identifier.make_function_name(function, length(params)) @@ -22,10 +22,10 @@ defmodule ElixirScript.Experimental.Forms.Call do defp process_module_name(module, state) when is_atom(module) do cond do - ElixirScript.Experimental.Module.is_js_module(module, state) -> + ElixirScript.Translate.Module.is_js_module(module, state) -> members = tl(Module.split(module)) Identifier.make_namespace_members(members) - ElixirScript.Experimental.Module.is_elixir_module(module) -> + ElixirScript.Translate.Module.is_elixir_module(module) -> members = ["Elixir"] ++ Module.split(module) J.identifier(Enum.join(members, "_")) true -> diff --git a/lib/elixir_script/experimental/forms/for.ex b/lib/elixir_script/next/passes/translate/forms/for.ex similarity index 95% rename from lib/elixir_script/experimental/forms/for.ex rename to lib/elixir_script/next/passes/translate/forms/for.ex index bf623836..5c8aeb42 100644 --- a/lib/elixir_script/experimental/forms/for.ex +++ b/lib/elixir_script/next/passes/translate/forms/for.ex @@ -1,8 +1,8 @@ -defmodule ElixirScript.Experimental.Forms.For do +defmodule ElixirScript.Translate.Forms.For do alias ESTree.Tools.Builder, as: JS - alias ElixirScript.Experimental.Form - alias ElixirScript.Experimental.Clause - alias ElixirScript.Experimental.Forms.{Pattern} + alias ElixirScript.Translate.Form + alias ElixirScript.Translate.Clause + alias ElixirScript.Translate.Forms.{Pattern} def compile({:for, _, generators}, state) do args = handle_args(generators, state) diff --git a/lib/elixir_script/experimental/forms/map.ex b/lib/elixir_script/next/passes/translate/forms/map.ex similarity index 94% rename from lib/elixir_script/experimental/forms/map.ex rename to lib/elixir_script/next/passes/translate/forms/map.ex index bac66534..a33624ef 100644 --- a/lib/elixir_script/experimental/forms/map.ex +++ b/lib/elixir_script/next/passes/translate/forms/map.ex @@ -1,6 +1,6 @@ -defmodule ElixirScript.Experimental.Forms.Map do +defmodule ElixirScript.Translate.Forms.Map do alias ESTree.Tools.Builder, as: J - alias ElixirScript.Experimental.Form + alias ElixirScript.Translate.Form def compile({:%{}, _, [{:|, _, [map, new_values]}]}, state) do map = Form.compile(map, state) diff --git a/lib/elixir_script/experimental/forms/match.ex b/lib/elixir_script/next/passes/translate/forms/match.ex similarity index 93% rename from lib/elixir_script/experimental/forms/match.ex rename to lib/elixir_script/next/passes/translate/forms/match.ex index 3e40b2f4..67fabcc2 100644 --- a/lib/elixir_script/experimental/forms/match.ex +++ b/lib/elixir_script/next/passes/translate/forms/match.ex @@ -1,7 +1,7 @@ -defmodule ElixirScript.Experimental.Forms.Match do +defmodule ElixirScript.Translate.Forms.Match do alias ESTree.Tools.Builder, as: J - alias ElixirScript.Experimental.Form - alias ElixirScript.Experimental.Forms.{Pattern} + alias ElixirScript.Translate.Form + alias ElixirScript.Translate.Forms.{Pattern} def compile({:=, _, [left, right]}, state) do right_ast = Form.compile(right, state) diff --git a/lib/elixir_script/experimental/forms/pattern.ex b/lib/elixir_script/next/passes/translate/forms/pattern.ex similarity index 96% rename from lib/elixir_script/experimental/forms/pattern.ex rename to lib/elixir_script/next/passes/translate/forms/pattern.ex index 1b6edf22..5ed3ba6b 100644 --- a/lib/elixir_script/experimental/forms/pattern.ex +++ b/lib/elixir_script/next/passes/translate/forms/pattern.ex @@ -1,8 +1,8 @@ -defmodule ElixirScript.Experimental.Forms.Pattern do +defmodule ElixirScript.Translate.Forms.Pattern do alias ElixirScript.Translator.PatternMatching, as: PM alias ESTree.Tools.Builder, as: J - alias ElixirScript.Experimental.Form - alias ElixirScript.Experimental.Forms.{Bitstring, Map} + alias ElixirScript.Translate.Form + alias ElixirScript.Translate.Forms.{Bitstring, Map} @moduledoc """ Handles all pattern matching translations diff --git a/lib/elixir_script/experimental/forms/struct.ex b/lib/elixir_script/next/passes/translate/forms/struct.ex similarity index 83% rename from lib/elixir_script/experimental/forms/struct.ex rename to lib/elixir_script/next/passes/translate/forms/struct.ex index 7aebfa78..4b4e83fd 100644 --- a/lib/elixir_script/experimental/forms/struct.ex +++ b/lib/elixir_script/next/passes/translate/forms/struct.ex @@ -1,6 +1,6 @@ -defmodule ElixirScript.Experimental.Forms.Struct do +defmodule ElixirScript.Translate.Forms.Struct do alias ESTree.Tools.Builder, as: J - alias ElixirScript.Experimental.Form + alias ElixirScript.Translate.Form alias ElixirScript.Translator.Identifier def compile({:%, _, [module, params]}, state) do diff --git a/lib/elixir_script/experimental/forms/try.ex b/lib/elixir_script/next/passes/translate/forms/try.ex similarity index 92% rename from lib/elixir_script/experimental/forms/try.ex rename to lib/elixir_script/next/passes/translate/forms/try.ex index effe3fbd..940bc7ae 100644 --- a/lib/elixir_script/experimental/forms/try.ex +++ b/lib/elixir_script/next/passes/translate/forms/try.ex @@ -1,8 +1,8 @@ -defmodule ElixirScript.Experimental.Forms.Try do +defmodule ElixirScript.Translate.Forms.Try do @moduledoc false alias ESTree.Tools.Builder, as: JS - alias ElixirScript.Experimental.Clause - alias ElixirScript.Experimental.Form + alias ElixirScript.Translate.Clause + alias ElixirScript.Translate.Form def compile(blocks, state) do try_block = Keyword.get(blocks, :do) @@ -74,7 +74,7 @@ defmodule ElixirScript.Experimental.Forms.Try do JS.call_expression( JS.member_expression( - ElixirScript.Experimental.Function.patterns_ast(), + ElixirScript.Translate.Function.patterns_ast(), JS.identifier("defmatch") ), processed_clauses diff --git a/lib/elixir_script/experimental/function.ex b/lib/elixir_script/next/passes/translate/function.ex similarity index 90% rename from lib/elixir_script/experimental/function.ex rename to lib/elixir_script/next/passes/translate/function.ex index b16f18f6..b3204e65 100644 --- a/lib/elixir_script/experimental/function.ex +++ b/lib/elixir_script/next/passes/translate/function.ex @@ -1,6 +1,6 @@ -defmodule ElixirScript.Experimental.Function do +defmodule ElixirScript.Translate.Function do alias ESTree.Tools.Builder, as: J - alias ElixirScript.Experimental.Clause + alias ElixirScript.Translate.Clause @moduledoc """ Translates the given Elixir function AST into the diff --git a/lib/elixir_script/experimental/functions/erlang.ex b/lib/elixir_script/next/passes/translate/functions/erlang.ex similarity index 99% rename from lib/elixir_script/experimental/functions/erlang.ex rename to lib/elixir_script/next/passes/translate/functions/erlang.ex index 0d813a40..2fe056fc 100644 --- a/lib/elixir_script/experimental/functions/erlang.ex +++ b/lib/elixir_script/next/passes/translate/functions/erlang.ex @@ -1,7 +1,7 @@ -defmodule ElixirScript.Experimental.Functions.Erlang do +defmodule ElixirScript.Translate.Functions.Erlang do @moduledoc false alias ESTree.Tools.Builder, as: J - alias ElixirScript.Experimental.Form + alias ElixirScript.Translate.Form def rewrite({{:., _, [:erlang, :abs]}, _, [number]}, state) do J.call_expression( diff --git a/lib/elixir_script/experimental/functions/lists.ex b/lib/elixir_script/next/passes/translate/functions/lists.ex similarity index 97% rename from lib/elixir_script/experimental/functions/lists.ex rename to lib/elixir_script/next/passes/translate/functions/lists.ex index 1c1c2a39..db2d7d73 100644 --- a/lib/elixir_script/experimental/functions/lists.ex +++ b/lib/elixir_script/next/passes/translate/functions/lists.ex @@ -1,7 +1,7 @@ -defmodule ElixirScript.Experimental.Functions.Lists do +defmodule ElixirScript.Translate.Functions.Lists do @moduledoc false alias ESTree.Tools.Builder, as: J - alias ElixirScript.Experimental.Form + alias ElixirScript.Translate.Form def rewrite({{:., _, [:lists, :map]}, _, [fun, list]}, state) do J.call_expression( diff --git a/lib/elixir_script/experimental/functions/maps.ex b/lib/elixir_script/next/passes/translate/functions/maps.ex similarity index 95% rename from lib/elixir_script/experimental/functions/maps.ex rename to lib/elixir_script/next/passes/translate/functions/maps.ex index 4e528d8a..2db82ecf 100644 --- a/lib/elixir_script/experimental/functions/maps.ex +++ b/lib/elixir_script/next/passes/translate/functions/maps.ex @@ -1,7 +1,7 @@ -defmodule ElixirScript.Experimental.Functions.Maps do +defmodule ElixirScript.Translate.Functions.Maps do @moduledoc false alias ESTree.Tools.Builder, as: J - alias ElixirScript.Experimental.Form + alias ElixirScript.Translate.Form def rewrite({{:., _, [:maps, :update]}, _, [key, value, map]}, state) do J.call_expression( diff --git a/lib/elixir_script/experimental/module.ex b/lib/elixir_script/next/passes/translate/module.ex similarity index 82% rename from lib/elixir_script/experimental/module.ex rename to lib/elixir_script/next/passes/translate/module.ex index 3d30a09d..dd5b142b 100644 --- a/lib/elixir_script/experimental/module.ex +++ b/lib/elixir_script/next/passes/translate/module.ex @@ -1,13 +1,14 @@ -defmodule ElixirScript.Experimental.Module do +defmodule ElixirScript.Translate.Module do + @moduledoc false alias ESTree.Tools.Builder, as: J - alias ElixirScript.Experimental.Function + alias ElixirScript.Translate.Function alias ElixirScript.Translator.Identifier alias ElixirScript.State, as: ModuleState - @moduledoc """ - Upper level module that handles compilation + @doc """ + Translate the given module's ast to + JavaScript AST """ - def compile(module, info, pid) do %{ attributes: _attrs, @@ -24,15 +25,17 @@ defmodule ElixirScript.Experimental.Module do pid: pid } - reachable_defs = Enum.filter(defs, fn + # Filter so that we only have the + # Used functions to compile + used_defs = Enum.filter(defs, fn { name, _, _, _} -> name in used _ -> false end) - compiled_functions = reachable_defs + compiled_functions = used_defs |> Enum.map(&Function.compile(&1, state)) - exports = make_exports(reachable_defs) + exports = make_exports(used_defs) js_ast = ElixirScript.ModuleSystems.Namespace.build( module, diff --git a/lib/elixir_script/experimental/module_state.ex b/lib/elixir_script/next/passes/translate/module_state.ex similarity index 87% rename from lib/elixir_script/experimental/module_state.ex rename to lib/elixir_script/next/passes/translate/module_state.ex index dbd21825..8e2afdd2 100644 --- a/lib/elixir_script/experimental/module_state.ex +++ b/lib/elixir_script/next/passes/translate/module_state.ex @@ -1,4 +1,4 @@ -defmodule ElixirScript.Experimental.ModuleState do +defmodule ElixirScript.Translate.ModuleState do def start_link(module) do Agent.start_link(fn -> %{ module: module, refs: [] } end) end diff --git a/lib/elixir_script/next/state.ex b/lib/elixir_script/next/state.ex index ccc837bf..711d8244 100644 --- a/lib/elixir_script/next/state.ex +++ b/lib/elixir_script/next/state.ex @@ -1,4 +1,8 @@ defmodule ElixirScript.State do + @moduledoc false + + # Holds the state for the ElixirScript compiler + def start_link(compiler_opts) do Agent.start_link(fn -> %{ @@ -13,6 +17,12 @@ defmodule ElixirScript.State do Agent.stop(pid) end + def get_compiler_opts(pid) do + Agent.get(pid, fn(state) -> + state.compiler_opts + end) + end + def get_module(pid, module) do Agent.get(pid, fn(state) -> Keyword.get(state.modules, module) diff --git a/mix.lock b/mix.lock index b6b6b0d2..353e11a0 100644 --- a/mix.lock +++ b/mix.lock @@ -1,15 +1,15 @@ -%{"bunt": {:hex, :bunt, "0.2.0", "951c6e801e8b1d2cbe58ebbd3e616a869061ddadcc4863d0a2182541acae9a38", [:mix], []}, - "certifi": {:hex, :certifi, "1.0.0", "1c787a85b1855ba354f0b8920392c19aa1d06b0ee1362f9141279620a5be2039", [:rebar3], []}, - "credo": {:hex, :credo, "0.7.3", "9827ab04002186af1aec014a811839a06f72aaae6cd5eed3919b248c8767dbf3", [:mix], [{:bunt, "~> 0.2.0", [hex: :bunt, optional: false]}]}, - "earmark": {:hex, :earmark, "1.2.0", "bf1ce17aea43ab62f6943b97bd6e3dc032ce45d4f787504e3adf738e54b42f3a", [:mix], []}, - "estree": {:hex, :estree, "2.6.0", "86a301b0c355fa55c19e7ef9dceb1b1e983c6df526a2b7846818a38c258fc3fb", [:mix], []}, - "ex_doc": {:hex, :ex_doc, "0.15.1", "d5f9d588fd802152516fccfdb96d6073753f77314fcfee892b15b6724ca0d596", [:mix], [{:earmark, "~> 1.1", [hex: :earmark, optional: false]}]}, - "excoveralls": {:hex, :excoveralls, "0.6.3", "894bf9254890a4aac1d1165da08145a72700ff42d8cb6ce8195a584cb2a4b374", [:mix], [{:exjsx, "~> 3.0", [hex: :exjsx, optional: false]}, {:hackney, ">= 0.12.0", [hex: :hackney, optional: false]}]}, - "exjsx": {:hex, :exjsx, "3.2.1", "1bc5bf1e4fd249104178f0885030bcd75a4526f4d2a1e976f4b428d347614f0f", [], [{:jsx, "~> 2.8.0", [hex: :jsx, optional: false]}]}, - "fs": {:hex, :fs, "2.12.0", "ad631efacc9a5683c8eaa1b274e24fa64a1b8eb30747e9595b93bec7e492e25e", [:rebar3], []}, - "hackney": {:hex, :hackney, "1.7.1", "e238c52c5df3c3b16ce613d3a51c7220a784d734879b1e231c9babd433ac1cb4", [:rebar3], [{:certifi, "1.0.0", [hex: :certifi, optional: false]}, {:idna, "4.0.0", [hex: :idna, optional: false]}, {:metrics, "1.0.1", [hex: :metrics, optional: false]}, {:mimerl, "1.0.2", [hex: :mimerl, optional: false]}, {:ssl_verify_fun, "1.1.1", [hex: :ssl_verify_fun, optional: false]}]}, - "idna": {:hex, :idna, "4.0.0", "10aaa9f79d0b12cf0def53038547855b91144f1bfcc0ec73494f38bb7b9c4961", [:rebar3], []}, - "jsx": {:hex, :jsx, "2.8.2", "7acc7d785b5abe8a6e9adbde926a24e481f29956dd8b4df49e3e4e7bcc92a018", [:mix, :rebar3], []}, - "metrics": {:hex, :metrics, "1.0.1", "25f094dea2cda98213cecc3aeff09e940299d950904393b2a29d191c346a8486", [], []}, - "mimerl": {:hex, :mimerl, "1.0.2", "993f9b0e084083405ed8252b99460c4f0563e41729ab42d9074fd5e52439be88", [], []}, - "ssl_verify_fun": {:hex, :ssl_verify_fun, "1.1.1", "28a4d65b7f59893bc2c7de786dec1e1555bd742d336043fe644ae956c3497fbe", [:make, :rebar], []}} +%{"bunt": {:hex, :bunt, "0.2.0", "951c6e801e8b1d2cbe58ebbd3e616a869061ddadcc4863d0a2182541acae9a38", [:mix], [], "hexpm"}, + "certifi": {:hex, :certifi, "1.0.0", "1c787a85b1855ba354f0b8920392c19aa1d06b0ee1362f9141279620a5be2039", [:rebar3], [], "hexpm"}, + "credo": {:hex, :credo, "0.7.3", "9827ab04002186af1aec014a811839a06f72aaae6cd5eed3919b248c8767dbf3", [:mix], [{:bunt, "~> 0.2.0", [hex: :bunt, repo: "hexpm", optional: false]}], "hexpm"}, + "earmark": {:hex, :earmark, "1.2.0", "bf1ce17aea43ab62f6943b97bd6e3dc032ce45d4f787504e3adf738e54b42f3a", [:mix], [], "hexpm"}, + "estree": {:hex, :estree, "2.6.0", "86a301b0c355fa55c19e7ef9dceb1b1e983c6df526a2b7846818a38c258fc3fb", [:mix], [], "hexpm"}, + "ex_doc": {:hex, :ex_doc, "0.15.1", "d5f9d588fd802152516fccfdb96d6073753f77314fcfee892b15b6724ca0d596", [:mix], [{:earmark, "~> 1.1", [hex: :earmark, repo: "hexpm", optional: false]}], "hexpm"}, + "excoveralls": {:hex, :excoveralls, "0.6.3", "894bf9254890a4aac1d1165da08145a72700ff42d8cb6ce8195a584cb2a4b374", [:mix], [{:exjsx, "~> 3.0", [hex: :exjsx, repo: "hexpm", optional: false]}, {:hackney, ">= 0.12.0", [hex: :hackney, repo: "hexpm", optional: false]}], "hexpm"}, + "exjsx": {:hex, :exjsx, "3.2.1", "1bc5bf1e4fd249104178f0885030bcd75a4526f4d2a1e976f4b428d347614f0f", [:mix], [{:jsx, "~> 2.8.0", [hex: :jsx, repo: "hexpm", optional: false]}], "hexpm"}, + "fs": {:hex, :fs, "2.12.0", "ad631efacc9a5683c8eaa1b274e24fa64a1b8eb30747e9595b93bec7e492e25e", [:rebar3], [], "hexpm"}, + "hackney": {:hex, :hackney, "1.7.1", "e238c52c5df3c3b16ce613d3a51c7220a784d734879b1e231c9babd433ac1cb4", [:rebar3], [{:certifi, "1.0.0", [hex: :certifi, repo: "hexpm", optional: false]}, {:idna, "4.0.0", [hex: :idna, repo: "hexpm", optional: false]}, {:metrics, "1.0.1", [hex: :metrics, repo: "hexpm", optional: false]}, {:mimerl, "1.0.2", [hex: :mimerl, repo: "hexpm", optional: false]}, {:ssl_verify_fun, "1.1.1", [hex: :ssl_verify_fun, repo: "hexpm", optional: false]}], "hexpm"}, + "idna": {:hex, :idna, "4.0.0", "10aaa9f79d0b12cf0def53038547855b91144f1bfcc0ec73494f38bb7b9c4961", [:rebar3], [], "hexpm"}, + "jsx": {:hex, :jsx, "2.8.2", "7acc7d785b5abe8a6e9adbde926a24e481f29956dd8b4df49e3e4e7bcc92a018", [:mix, :rebar3], [], "hexpm"}, + "metrics": {:hex, :metrics, "1.0.1", "25f094dea2cda98213cecc3aeff09e940299d950904393b2a29d191c346a8486", [:rebar3], [], "hexpm"}, + "mimerl": {:hex, :mimerl, "1.0.2", "993f9b0e084083405ed8252b99460c4f0563e41729ab42d9074fd5e52439be88", [:rebar3], [], "hexpm"}, + "ssl_verify_fun": {:hex, :ssl_verify_fun, "1.1.1", "28a4d65b7f59893bc2c7de786dec1e1555bd742d336043fe644ae956c3497fbe", [:make, :rebar], [], "hexpm"}} From 69e85ab80ce74d620b6c98579ce5b2b5f032d16e Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Fri, 26 May 2017 21:06:37 -0500 Subject: [PATCH 538/860] Remove rewrite of erlang functions. Add erlang compat layer in javascript --- .../next/passes/translate/form.ex | 31 +- .../next/passes/translate/functions/erlang.ex | 914 ------------------ .../next/passes/translate/functions/lists.ex | 178 ---- .../next/passes/translate/functions/maps.ex | 85 -- src/javascript/lib/core.js | 6 + .../lib/core/erlang_compat/erlang.js | 1 + .../lib/core/erlang_compat/lists.js | 1 + src/javascript/lib/core/erlang_compat/maps.js | 1 + 8 files changed, 26 insertions(+), 1191 deletions(-) delete mode 100644 lib/elixir_script/next/passes/translate/functions/erlang.ex delete mode 100644 lib/elixir_script/next/passes/translate/functions/lists.ex delete mode 100644 lib/elixir_script/next/passes/translate/functions/maps.ex create mode 100644 src/javascript/lib/core/erlang_compat/erlang.js create mode 100644 src/javascript/lib/core/erlang_compat/lists.js create mode 100644 src/javascript/lib/core/erlang_compat/maps.js diff --git a/lib/elixir_script/next/passes/translate/form.ex b/lib/elixir_script/next/passes/translate/form.ex index e325071f..5d69280a 100644 --- a/lib/elixir_script/next/passes/translate/form.ex +++ b/lib/elixir_script/next/passes/translate/form.ex @@ -13,7 +13,7 @@ defmodule ElixirScript.Translate.Form do J.identifier("null") end - def compile(form, _) when is_boolean(form) when is_integer(form) when is_float(form) when is_binary(form) do + def compile(form, _) when is_boolean(form) or is_integer(form) or is_float(form) or is_binary(form) do J.literal(form) end @@ -120,10 +120,9 @@ defmodule ElixirScript.Translate.Form do ) end - def compile({:receive, context, _}, state) do + def compile({:receive, context, _}, _state) do line = Keyword.get(context, :line, 1) - #raise ElixirScriptCompileError, message: "Line: #{line} receive not supported" - J.call_expression(J.identifier(:receive), []) + raise ElixirScriptCompileError, message: "Line: #{line} receive not supported" end def compile({:try, _, [blocks]}, state) do @@ -140,16 +139,20 @@ defmodule ElixirScript.Translate.Form do ) end - def compile({{:., _, [:erlang, _]}, _, _} = ast, state) do - Erlang.rewrite(ast, state) - end - - def compile({{:., _, [:lists, _]}, _, _} = ast, state) do - Lists.rewrite(ast, state) - end - - def compile({{:., _, [:maps, _]}, _, _} = ast, state) do - Maps.rewrite(ast, state) + def compile({{:., _, [module, function]}, _, params}, state) when module in [:erlang, :lists, :maps] do + J.call_expression( + J.member_expression( + J.member_expression( + J.member_expression( + J.identifier("Bootstrap"), + J.identifier("Core") + ), + J.identifier(module) + ), + J.identifier(function) + ), + Enum.map(params, &compile(&1, state)) + ) end def compile({{:., _, [_, _]}, _, _} = ast, state) do diff --git a/lib/elixir_script/next/passes/translate/functions/erlang.ex b/lib/elixir_script/next/passes/translate/functions/erlang.ex deleted file mode 100644 index 2fe056fc..00000000 --- a/lib/elixir_script/next/passes/translate/functions/erlang.ex +++ /dev/null @@ -1,914 +0,0 @@ -defmodule ElixirScript.Translate.Functions.Erlang do - @moduledoc false - alias ESTree.Tools.Builder, as: J - alias ElixirScript.Translate.Form - - def rewrite({{:., _, [:erlang, :abs]}, _, [number]}, state) do - J.call_expression( - J.member_expression( - J.identifier("Math"), - J.identifier("abs") - ), - [Form.compile(number, state)] - ) - end - - def rewrite({{:., _, [:erlang, :apply]}, _, [fun, args]}, state) do - J.call_expression( - J.member_expression( - Form.compile(fun, state), - J.identifier("apply") - ), - [Form.compile(fun, state), J.array_expression(Enum.map(List.wrap(args), &Form.compile(&1, state)))] - ) - end - - def rewrite({{:., _, [:erlang, :apply]}, _, [module, fun, args]}, state) do - mod = J.member_expression( - Form.compile(module, state), - Form.compile(fun, state) - ) - - J.call_expression( - J.member_expression( - mod, - J.identifier("apply") - ), - [mod, J.array_expression(Enum.map(List.wrap(args), &Form.compile(&1, state)))] - ) - end - - def rewrite({{:., _, [:erlang, :binary_part]}, _, [binary, start, length]}, state) do - J.call_expression( - J.member_expression( - Form.compile(binary, state), - J.identifier("substring") - ), - [Form.compile(start, state), Form.compile(length, state)] - ) - end - - def rewrite({{:., _, [:erlang, :bit_size]}, _, [bitstring]}, state) do - J.call_expression( - J.member_expression( - Form.compile(bitstring, state), - J.identifier("bit_size") - ), - [] - ) - end - - def rewrite({{:., _, [:erlang, :byte_size]}, _, [bitstring]}, state) do - J.call_expression( - J.member_expression( - Form.compile(bitstring, state), - J.identifier("byte_size") - ), - [] - ) - end - - def rewrite({{:., _, [:erlang, :div]}, _, [left, right]}, state) do - J.binary_expression( - :/, - Form.compile(left, state), - Form.compile(right, state) - ) - end - - def rewrite({{:., _, [:erlang, :exit]}, _, [reason]}, _) do - J.literal(0) - end - - def rewrite({{:., _, [:erlang, :hd]}, _, [list]}, state) do - J.member_expression( - Form.compile(list, state), - J.literal(0), - true - ) - end - - def rewrite({{:., _, [:erlang, :is_atom]}, _, [term]}, state) do - J.binary_expression( - :typeof, - Form.compile(term, state), - J.literal("symbol") - ) - end - - def rewrite({{:., _, [:erlang, :is_binary]}, _, [term]}, state) do - J.binary_expression( - :typeof, - Form.compile(term, state), - J.literal("string") - ) - end - - def rewrite({{:., _, [:erlang, :is_bitstring]}, _, [term]}, state) do - J.binary_expression( - :||, - J.binary_expression( - :typeof, - Form.compile(term, state), - J.literal("string") - ), - J.binary_expression( - :instanceof, - Form.compile(term, state), - J.member_expression( - J.member_expression( - J.identifier("Bootstrap"), - J.identifier("Core") - ), - J.identifier("BitString") - ) - ) - ) - end - - def rewrite({{:., _, [:erlang, :is_boolean]}, _, [term]}, state) do - J.binary_expression( - :||, - J.binary_expression( - :typeof, - Form.compile(term, state), - J.literal("boolean") - ), - J.binary_expression( - :instanceof, - Form.compile(term, state), - J.identifier("Boolean") - ) - ) - end - - def rewrite({{:., _, [:erlang, :is_float]}, _, [term]}, state) do - J.binary_expression( - :||, - J.binary_expression( - :typeof, - Form.compile(term, state), - J.literal("number") - ), - J.binary_expression( - :&&, - J.binary_expression( - :instanceof, - Form.compile(term, state), - J.identifier("Number") - ), - J.unary_expression( - :!, - true, - J.call_expression( - J.member_expression( - J.identifier("Number"), - J.identifier("isInteger") - ), - [Form.compile(term, state)] - ) - ) - ) - ) - end - - def rewrite({{:., _, [:erlang, :is_function]}, _, [term]}, state) do - J.binary_expression( - :||, - J.binary_expression( - :typeof, - Form.compile(term, state), - J.literal("function") - ), - J.binary_expression( - :instanceof, - Form.compile(term, state), - J.identifier("Function") - ) - ) - end - - def rewrite({{:., _, [:erlang, :is_function]}, _, [term, _]}, state) do - J.binary_expression( - :||, - J.binary_expression( - :typeof, - Form.compile(term, state), - J.literal("function") - ), - J.binary_expression( - :instanceof, - Form.compile(term, state), - J.identifier("Function") - ) - ) - end - - def rewrite({{:., _, [:erlang, :is_integer]}, _, [term]}, state) do - J.call_expression( - J.member_expression( - J.identifier("Number"), - J.identifier("isInteger") - ), - [Form.compile(term, state)] - ) - end - - def rewrite({{:., _, [:erlang, :is_list]}, _, [term]}, state) do - J.call_expression( - J.member_expression( - J.identifier("Array"), - J.identifier("isArray") - ), - [Form.compile(term, state)] - ) - end - - def rewrite({{:., _, [:erlang, :is_number]}, _, [term]}, state) do - J.binary_expression( - :||, - J.binary_expression( - :typeof, - Form.compile(term, state), - J.literal("number") - ), - J.binary_expression( - :instanceof, - Form.compile(term, state), - J.identifier("Number") - ) - ) - end - - def rewrite({{:., _, [:erlang, :is_pid]}, _, [term]}, state) do - J.binary_expression( - :instanceof, - Form.compile(term, state), - J.member_expression( - J.member_expression( - J.identifier("Bootstrap"), - J.identifier("Core") - ), - J.identifier("PID") - ) - ) - end - - def rewrite({{:., _, [:erlang, :is_port]}, _, [_term]}, state) do - J.literal(false) - end - - def rewrite({{:., _, [:erlang, :is_reference]}, _, [_term]}, state) do - J.literal(false) - end - - def rewrite({{:., _, [:erlang, :is_tuple]}, _, [term]}, state) do - J.binary_expression( - :instanceof, - Form.compile(term, state), - J.member_expression( - J.member_expression( - J.identifier("Bootstrap"), - J.identifier("Core") - ), - J.identifier("Tuple") - ) - ) - end - - def rewrite({{:., _, [:erlang, :is_map]}, _, [term]}, state) do - J.binary_expression( - :||, - J.binary_expression( - :typeof, - Form.compile(term, state), - J.literal("object") - ), - J.binary_expression( - :instanceof, - Form.compile(term, state), - J.identifier("Object") - ) - ) - end - - def rewrite({{:., _, [:erlang, :length]}, _, [list]}, state) do - J.member_expression( - Form.compile(list, state), - J.identifier("length") - ) - end - - def rewrite({{:., _, [:erlang, :make_ref]}, _, []}, state) do - J.literal(false) - end - - def rewrite({{:., _, [:erlang, :map_size]}, _, [map]}, state) do - J.member_expression( - J.call_expression( - J.member_expression( - J.identifier("Object"), - J.identifier("keys") - ), - [Form.compile(map, state)] - ), - J.identifier("length") - ) - end - - def rewrite({{:., _, [:erlang, :max]}, _, [first, second]}, state) do - J.call_expression( - J.member_expression( - J.identifier("Math"), - J.identifier("max") - ), - [Form.compile(first, state), Form.compile(second, state)] - ) - end - - def rewrite({{:., _, [:erlang, :min]}, _, [first, second]}, state) do - J.call_expression( - J.member_expression( - J.identifier("Math"), - J.identifier("min") - ), - [Form.compile(first, state), Form.compile(second, state)] - ) - end - - def rewrite({{:., _, [:erlang, :node]}, _, []}, state) do - J.identifier("nonode@nohost") - end - - def rewrite({{:., _, [:erlang, :node]}, _, [_]}, state) do - J.identifier("nonode@nohost") - end - - def rewrite({{:., _, [:erlang, :rem]}, _, [first, second]}, state) do - J.binary_expression( - :%, - Form.compile(first, state), - Form.compile(second, state) - ) - end - - def rewrite({{:., _, [:erlang, :round]}, _, [number]}, state) do - J.call_expression( - J.member_expression( - J.identifier("Math"), - J.identifier("round") - ), - [Form.compile(number, state)] - ) - end - -# def rewrite({{:., _, [:erlang, :send]}, _, [dest, msg]}, state) do -# raise ":erlang.send not supported" -# end -# -# def rewrite({{:., _, [:erlang, :self]}, _, []}, state) do -# raise ":erlang.self not supported" -# end -# -# def rewrite({{:., _, [:erlang, :spawn]}, _, [_fun]}, state) do -# raise ":erlang.spawn not supported" -# end -# -# def rewrite({{:., _, [:erlang, :spawn]}, _, [_module, _fun, _args]}, state) do -# raise ":erlang.spawn not supported" -# end -# -# def rewrite({{:., _, [:erlang, :spawn_link]}, _, [_fun]}, state) do -# raise ":erlang.spawn_link not supported" -# end -# -# def rewrite({{:., _, [:erlang, :spawn_link]}, _, [_module, _fun, _args]}, state) do -# raise ":erlang.spawn_link not supported" -# end -# -# def rewrite({{:., _, [:erlang, :spawn_monitor]}, _, [_fun]}, state) do -# raise ":erlang.spawn_monitor not supported" -# end -# -# def rewrite({{:., _, [:erlang, :spawn_monitor]}, _, [_module, _fun, _args]}, state) do -# raise ":erlang.spawn_monitor not supported" -# end - - def rewrite({{:., _, [:erlang, :throw]}, _, [term]}, state) do - J.throw_statement( - Form.compile(term, state) - ) - end - - def rewrite({{:., _, [:erlang, :tl]}, _, [list]}, state) do - J.call_expression( - J.member_expression( - Form.compile(list, state), - J.identifier("splice") - ), - [J.literal(1)] - ) - end - - def rewrite({{:., _, [:erlang, :trunc]}, _, [number]}, state) do - J.call_expression( - J.member_expression( - J.identifier("Math"), - J.identifier("floor") - ), - [Form.compile(number, state)] - ) - end - - def rewrite({{:., _, [:erlang, :tuple_size]}, _, [tuple]}, state) do - J.member_expression( - Form.compile(tuple, state), - J.identifier("length") - ) - end - - def rewrite({{:., _, [:erlang, operator]}, _, [left, right]}, state) when operator in [:+, :-, :*, :/, :<, :>, :>=, :==] do - J.binary_expression( - operator, - Form.compile(left, state), - Form.compile(right, state) - ) - end - - def rewrite({{:., _, [:erlang, operator]}, _, [value]}, state) when operator in [:+, :-] do - J.unary_expression( - operator, - true, - Form.compile(value, state) - ) - end - - def rewrite({{:., _, [:erlang, :++]}, _, [left, right]}, state) do - J.call_expression( - J.member_expression( - Form.compile(left, state), - J.identifier("concat") - ), - [Form.compile(right, state)] - ) - end - - def rewrite({{:., _, [:erlang, :--]}, _, [list, element]}, state) do - J.call_expression( - J.member_expression( - Form.compile(list, state), - J.identifier("slice") - ), - [ - J.binary_expression( - :+, - J.call_expression( - J.member_expression( - Form.compile(list, state), - J.identifier("indexOf") - ), - [Form.compile(element, state)] - ), - J.literal(1) - ) - ] - ) - end - - def rewrite({{:., _, [:erlang, :not]}, _, [value]}, state) do - J.unary_expression( - :!, - true, - Form.compile(value, state) - ) - end - - def rewrite({{:., _, [:erlang, :"=<"]}, _, [left, right]}, state) do - J.binary_expression( - :<=, - Form.compile(left, state), - Form.compile(right, state) - ) - end - - def rewrite({{:., _, [:erlang, :"/="]}, _, [left, right]}, state) do - J.binary_expression( - :!=, - Form.compile(left, state), - Form.compile(right, state) - ) - end - - def rewrite({{:., _, [:erlang, :"=:="]}, _, [left, right]}, state) do - J.binary_expression( - :===, - Form.compile(left, state), - Form.compile(right, state) - ) - end - - def rewrite({{:., _, [:erlang, :"=/="]}, _, [left, right]}, state) do - J.binary_expression( - :!==, - Form.compile(left, state), - Form.compile(right, state) - ) - end - - def rewrite({{:., _, [:erlang, :element]}, _, [index, tuple]}, state) do - J.call_expression( - J.member_expression( - Form.compile(tuple, state), - J.identifier("get") - ), - [ - J.binary_expression( - :-, - Form.compile(index, state), - J.literal(1) - ) - ] - ) - end - - def rewrite({{:., _, [:erlang, :setelement]}, _, [index, tuple, value]}, state) do - J.call_expression( - J.member_expression( - Form.compile(tuple, state), - J.identifier("put_elem") - ), - [ - J.binary_expression( - :-, - Form.compile(index, state), - J.literal(1) - ), - Form.compile(value, state) - ] - ) - end - - def rewrite({{:., _, [:erlang, :orelse]}, _, [left, right]}, state) do - J.binary_expression( - :||, - Form.compile(left, state), - Form.compile(right, state) - ) - end - - def rewrite({{:., _, [:erlang, :or]}, _, [left, right]}, state) do - J.binary_expression( - :||, - Form.compile(left, state), - Form.compile(right, state) - ) - end - - def rewrite({{:., _, [:erlang, :andalso]}, _, [left, right]}, state) do - J.binary_expression( - :&&, - Form.compile(left, state), - Form.compile(right, state) - ) - end - - def rewrite({{:., _, [:erlang, :error]}, _, [error]}, state) do - J.throw_statement( - Form.compile(error, state) - ) - end - - def rewrite({{:., _, [:erlang, :raise]}, _, [_class, reason, _stacktrace]}, state) do - J.throw_statement( - Form.compile(reason, state) - ) - end - - def rewrite({{:., _, [:erlang, :atom_to_binary]}, _, [atom, _]}, state) do - J.call_expression( - J.member_expression( - J.identifier("Symbol"), - J.identifier("keyFor") - ), - [Form.compile(atom, state)] - ) - end - - def rewrite({{:., _, [:erlang, :atom_to_list]}, _, [atom]}, state) do - J.call_expression( - J.member_expression( - J.call_expression( - J.member_expression( - J.identifier("Symbol"), - J.identifier("keyFor") - ), - [Form.compile(atom, state)] - ), - J.identifier("split") - ), - [J.literal("")] - ) - end - - def rewrite({{:., _, [:erlang, :bnot]}, _, [expr]}, state) do - J.unary_expression( - :"~", - true, - Form.compile(expr, state) - ) - end - - def rewrite({{:., _, [:erlang, :band]}, _, [left, right]}, state) do - J.binary_expression( - :&, - Form.compile(left, state), - Form.compile(right, state) - ) - end - - def rewrite({{:., _, [:erlang, :bor]}, _, [left, right]}, state) do - J.binary_expression( - :|, - Form.compile(left, state), - Form.compile(right, state) - ) - end - - def rewrite({{:., _, [:erlang, :bxor]}, _, [left, right]}, state) do - J.binary_expression( - :^, - Form.compile(left, state), - Form.compile(right, state) - ) - end - - def rewrite({{:., _, [:erlang, :bsl]}, _, [left, right]}, state) do - J.binary_expression( - :"<<", - Form.compile(left, state), - Form.compile(right, state) - ) - end - - def rewrite({{:., _, [:erlang, :bsr]}, _, [left, right]}, state) do - J.binary_expression( - :">>", - Form.compile(left, state), - Form.compile(right, state) - ) - end - - def rewrite({{:., _, [:erlang, :function_exported]}, _, [_, _, _]}, state) do - J.literal(true) - end - - def rewrite({{:., _, [:erlang, :make_tuple]}, _, [size, data]}, state) do - J.new_expression( - J.member_expression( - J.member_expression( - J.identifier("Bootstrap"), - J.identifier("Core") - ), - J.identifier("Tuple") - ), - [] - ) - end - - def rewrite({{:., _, [:erlang, :insert_element]}, _, [index, tuple, term]}, state) do - J.call_expression( - J.member_expression( - Form.compile(tuple, state), - J.identifier("put_elem") - ), - [ - J.binary_expression( - :-, - Form.compile(index, state), - J.literal(1) - ), - Form.compile(term, state) - ] - ) - end - - def rewrite({{:., _, [:erlang, :tuple_to_list]}, _, [tuple]}, state) do - J.member_expression( - Form.compile(tuple, state), - J.identifier("values") - ) - end - - def rewrite({{:., _, [:erlang, :append_element]}, _, [tuple, value]}, state) do - J.call_expression( - J.member_expression( - Form.compile(tuple, state), - J.identifier("put_elem") - ), - [ - J.member_expression( - Form.compile(tuple, state), - J.identifier("length") - ), - Form.compile(value, state) - ] - ) - end - - def rewrite({{:., _, [:erlang, :delete_element]}, _, [index, tuple]}, state) do - J.call_expression( - J.member_expression( - Form.compile(tuple, state), - J.identifier("remove_elem") - ), - [Form.compile(index, state)] - ) - end - - def rewrite({{:., _, [:erlang, :binary_to_atom]}, _, [binary, _]}, state) do - J.call_expression( - J.member_expression( - J.identifier("Symbol"), - J.identifier("for") - ), - [Form.compile(binary, state)] - ) - end - - def rewrite({{:., _, [:erlang, :binary_to_existing_atom]}, _, [binary, _]}, state) do - J.call_expression( - J.member_expression( - J.identifier("Symbol"), - J.identifier("for") - ), - [Form.compile(binary, state)] - ) - end - - def rewrite({{:., _, [:erlang, :list_to_atom]}, _, [char_list]}, state) do - J.call_expression( - J.member_expression( - J.identifier("Symbol"), - J.identifier("for") - ), - [Form.compile(char_list, state)] - ) - end - - def rewrite({{:., _, [:erlang, :list_to_existing_atom]}, _, [char_list]}, state) do - J.call_expression( - J.member_expression( - J.identifier("Symbol"), - J.identifier("for") - ), - [Form.compile(char_list, state)] - ) - end - - def rewrite({{:., _, [:erlang, :list_to_tuple]}, _, [list]}, state) do - J.new_expression( - J.member_expression( - J.member_expression( - J.identifier("Bootstrap"), - J.identifier("Core") - ), - J.identifier("Tuple") - ), - [ - J.rest_element( - Form.compile(list, state) - ) - ] - ) - end - - def rewrite({{:., _, [:erlang, :list_to_float]}, _, [list]}, state) do - J.call_expression( - J.identifier("parseFloat"), - [Form.compile(list, state)] - ) - end - - def rewrite({{:., _, [:erlang, :list_to_integer]}, _, [list]}, state) do - J.call_expression( - J.identifier("parseInt"), - [Form.compile(list, state)] - ) - end - - def rewrite({{:., _, [:erlang, :list_to_integer]}, _, [list, base]}, state) do - J.call_expression( - J.identifier("parseInt"), - [Form.compile(list, state), Form.compile(base, state)] - ) - end - - def rewrite({{:., _, [:erlang, :integer_to_binary]}, _, [integer]}, state) do - J.call_expression( - J.member_expression( - Form.compile(integer, state), - J.identifier("toString") - ), - [] - ) - end - - def rewrite({{:., _, [:erlang, :integer_to_binary]}, _, [integer, base]}, state) do - J.call_expression( - J.member_expression( - Form.compile(integer, state), - J.identifier("toString") - ), - [Form.compile(base, state)] - ) - end - - def rewrite({{:., _, [:erlang, :integer_to_list]}, _, [integer]}, state) do - J.call_expression( - J.member_expression( - Form.compile(integer, state), - J.identifier("toString") - ), - [] - ) - end - - def rewrite({{:., _, [:erlang, :integer_to_list]}, _, [integer, base]}, state) do - J.call_expression( - J.member_expression( - Form.compile(integer, state), - J.identifier("toString") - ), - [Form.compile(base, state)] - ) - end - - def rewrite({{:., _, [:erlang, :float_to_binary]}, _, [float]}, state) do - J.call_expression( - J.member_expression( - Form.compile(float, state), - J.identifier("toString") - ), - [] - ) - end - - def rewrite({{:., _, [:erlang, :float_to_binary]}, _, [float, base]}, state) do - J.call_expression( - J.member_expression( - Form.compile(float, state), - J.identifier("toString") - ), - [Form.compile(base, state)] - ) - end - - def rewrite({{:., _, [:erlang, :float_to_list]}, _, [float]}, state) do - J.call_expression( - J.member_expression( - Form.compile(float, state), - J.identifier("toString") - ), - [] - ) - end - - def rewrite({{:., _, [:erlang, :float_to_list]}, _, [float, base]}, state) do - J.call_expression( - J.member_expression( - Form.compile(float, state), - J.identifier("toString") - ), - [Form.compile(base, state)] - ) - end - - def rewrite({{:., _, [:erlang, :binary_to_float]}, _, [binary]}, state) do - J.call_expression( - J.identifier("parseFloat"), - [Form.compile(binary, state)] - ) - end - - def rewrite({{:., _, [:erlang, :binary_to_integer]}, _, [binary]}, state) do - J.call_expression( - J.identifier("parseInt"), - [Form.compile(binary, state)] - ) - end - - def rewrite({{:., _, [:erlang, :binary_to_integer]}, _, [binary, base]}, state) do - J.call_expression( - J.identifier("parseInt"), - [Form.compile(binary, state), Form.compile(base, state)] - ) - end - - def rewrite({{:., _, [:erlang, _]}, _, _}, state) do - J.call_expression( - J.identifier("toString"), - [] - ) - end - -end diff --git a/lib/elixir_script/next/passes/translate/functions/lists.ex b/lib/elixir_script/next/passes/translate/functions/lists.ex deleted file mode 100644 index db2d7d73..00000000 --- a/lib/elixir_script/next/passes/translate/functions/lists.ex +++ /dev/null @@ -1,178 +0,0 @@ -defmodule ElixirScript.Translate.Functions.Lists do - @moduledoc false - alias ESTree.Tools.Builder, as: J - alias ElixirScript.Translate.Form - - def rewrite({{:., _, [:lists, :map]}, _, [fun, list]}, state) do - J.call_expression( - J.member_expression( - Form.compile(list, state), - J.identifier("map") - ), - [Form.compile(fun, state)] - ) - end - - def rewrite({{:., _, [:lists, :member]}, _, [elem, list]}, state) do - J.binary_expression( - :>, - J.call_expression( - J.member_expression( - Form.compile(list, state), - J.identifier("indexOf") - ), - [Form.compile(elem, state)] - ), - J.unary_expression( - :-, - true, - J.literal(1) - ) - ) - end - - def rewrite({{:., _, [:lists, :reverse]}, _, [list]}, state) do - J.call_expression( - J.member_expression( - J.call_expression( - J.member_expression( - Form.compile(list, state), - J.identifier("concat") - ), - [J.array_expression([])] - ), - J.identifier("reverse") - ), - [] - ) - end - - def rewrite({{:., _, [:lists, :reverse]}, _, [list, tail]}, state) do - J.call_expression( - J.member_expression( - J.call_expression( - J.member_expression( - J.call_expression( - J.member_expression( - Form.compile(list, state), - J.identifier("concat") - ), - [J.array_expression([])] - ), - J.identifier("reverse") - ), - [] - ), - J.identifier("concat") - ), - [Form.compile(tail, state)] - ) - end - - def rewrite({{:., _, [:lists, :sort]}, _, [list]}, state) do - J.call_expression( - J.member_expression( - J.call_expression( - J.member_expression( - Form.compile(list, state), - J.identifier("concat") - ), - [J.array_expression([])] - ), - J.identifier("sort") - ), - [] - ) - end - - def rewrite({{:., _, [:lists, :filter]}, _, [pred, list]}, state) do - J.call_expression( - J.member_expression( - Form.compile(list, state), - J.identifier("filter") - ), - [Form.compile(pred, state)] - ) - end - - def rewrite({{:., _, [:lists, :delete]}, _, [elem, list]}, state) do - J.call_expression( - J.member_expression( - J.member_expression( - J.member_expression( - J.identifier("Bootstrap"), - J.identifier("Core") - ), - J.identifier("Functions") - ), - J.identifier("remove_from_list") - ), - [Form.compile(list, state), Form.compile(elem, state)] - ) - end - - def rewrite({{:., _, [:lists, _]}, _, [elem, list]}, state) do - J.call_expression( - J.member_expression( - J.member_expression( - J.member_expression( - J.identifier("Bootstrap"), - J.identifier("Core") - ), - J.identifier("Functions") - ), - J.identifier("remove_from_list") - ), - [Form.compile(list, state), Form.compile(elem, state)] - ) - end - - def rewrite({{:., _, [:lists, _]}, _, [elem, list, _, _]}, state) do - J.call_expression( - J.member_expression( - J.member_expression( - J.member_expression( - J.identifier("Bootstrap"), - J.identifier("Core") - ), - J.identifier("Functions") - ), - J.identifier("remove_from_list") - ), - [Form.compile(list, state), Form.compile(elem, state)] - ) - end - - def rewrite({{:., _, [:lists, _]}, _, [elem, list, _]}, state) do - J.call_expression( - J.member_expression( - J.member_expression( - J.member_expression( - J.identifier("Bootstrap"), - J.identifier("Core") - ), - J.identifier("Functions") - ), - J.identifier("remove_from_list") - ), - [Form.compile(list, state), Form.compile(elem, state)] - ) - end - - def rewrite({{:., _, [:lists, _]}, _, [list]}, state) do - J.call_expression( - J.member_expression( - J.call_expression( - J.member_expression( - Form.compile(list, state), - J.identifier("concat") - ), - [J.array_expression([])] - ), - J.identifier("reverse") - ), - [] - ) - end - -end diff --git a/lib/elixir_script/next/passes/translate/functions/maps.ex b/lib/elixir_script/next/passes/translate/functions/maps.ex deleted file mode 100644 index 2db82ecf..00000000 --- a/lib/elixir_script/next/passes/translate/functions/maps.ex +++ /dev/null @@ -1,85 +0,0 @@ -defmodule ElixirScript.Translate.Functions.Maps do - @moduledoc false - alias ESTree.Tools.Builder, as: J - alias ElixirScript.Translate.Form - - def rewrite({{:., _, [:maps, :update]}, _, [key, value, map]}, state) do - J.call_expression( - J.member_expression( - J.member_expression( - J.member_expression( - J.identifier("Bootstrap"), - J.identifier("Core") - ), - J.identifier("Functions") - ), - J.identifier("update_map") - ), - [Form.compile(map, state), Form.compile(key, state), Form.compile(value, state)] - ) - end - - def rewrite({{:., _, [:maps, :find]}, _, [key, map]}, state) do - J.call_expression( - J.member_expression( - J.member_expression( - J.member_expression( - J.identifier("Bootstrap"), - J.identifier("Core") - ), - J.identifier("Functions") - ), - J.identifier("update_map") - ), - [Form.compile(key, state), Form.compile(map, state)] - ) - end - - def rewrite({{:., _, [:maps, :put]}, _, [key, map, _]}, state) do - J.call_expression( - J.member_expression( - J.member_expression( - J.member_expression( - J.identifier("Bootstrap"), - J.identifier("Core") - ), - J.identifier("Functions") - ), - J.identifier("update_map") - ), - [Form.compile(key, state), Form.compile(map, state)] - ) - end - - def rewrite({{:., _, [:maps, :is_key]}, _, [key, map]}, state) do - J.call_expression( - J.member_expression( - J.member_expression( - J.member_expression( - J.identifier("Bootstrap"), - J.identifier("Core") - ), - J.identifier("Functions") - ), - J.identifier("update_map") - ), - [Form.compile(key, state), Form.compile(map, state)] - ) - end - - def rewrite({{:., _, [:maps, _]}, _, _}, state) do - J.call_expression( - J.member_expression( - J.member_expression( - J.member_expression( - J.identifier("Bootstrap"), - J.identifier("Core") - ), - J.identifier("Functions") - ), - J.identifier("update_map") - ), - [] - ) - end -end diff --git a/src/javascript/lib/core.js b/src/javascript/lib/core.js index 366a6a6a..bacfe6fe 100644 --- a/src/javascript/lib/core.js +++ b/src/javascript/lib/core.js @@ -2,6 +2,9 @@ import Patterns from 'tailored'; import ErlangTypes from 'erlang-types'; import Functions from './core/functions'; import SpecialForms from './core/special_forms'; +import erlang from './core/erlang_compat/erlang'; +import maps from './core/erlang_compat/maps'; +import lists from './core/erlang_compat/lists'; class Integer {} class Float {} @@ -34,4 +37,7 @@ export default { Functions, SpecialForms, global: globalState, + erlang, + maps, + lists, }; diff --git a/src/javascript/lib/core/erlang_compat/erlang.js b/src/javascript/lib/core/erlang_compat/erlang.js new file mode 100644 index 00000000..ff8b4c56 --- /dev/null +++ b/src/javascript/lib/core/erlang_compat/erlang.js @@ -0,0 +1 @@ +export default {}; diff --git a/src/javascript/lib/core/erlang_compat/lists.js b/src/javascript/lib/core/erlang_compat/lists.js new file mode 100644 index 00000000..ff8b4c56 --- /dev/null +++ b/src/javascript/lib/core/erlang_compat/lists.js @@ -0,0 +1 @@ +export default {}; diff --git a/src/javascript/lib/core/erlang_compat/maps.js b/src/javascript/lib/core/erlang_compat/maps.js new file mode 100644 index 00000000..ff8b4c56 --- /dev/null +++ b/src/javascript/lib/core/erlang_compat/maps.js @@ -0,0 +1 @@ +export default {}; From 73f313583a6e19cfa119070da4c4e67d8d100603 Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Sun, 28 May 2017 08:46:53 -0500 Subject: [PATCH 539/860] Remove references to experimental backend --- .tool-versions | 2 +- README.md | 3 +- lib/elixir_script/next/beam.ex | 2 + lib/elixir_script/next/passes/find_used.ex | 37 +++++++++++-------- lib/elixir_script/next/passes/translate.ex | 2 +- .../next/passes/translate/examples/example.ex | 6 +-- .../next/passes/translate/examples/size.ex | 6 --- .../next/passes/translate/module.ex | 10 ++++- .../lib/core/erlang_compat/erlang.js | 2 + .../lib/core/erlang_compat/lists.js | 2 + src/javascript/lib/core/erlang_compat/maps.js | 2 + 11 files changed, 43 insertions(+), 31 deletions(-) diff --git a/.tool-versions b/.tool-versions index 09178de1..d588b60f 100644 --- a/.tool-versions +++ b/.tool-versions @@ -1,3 +1,3 @@ erlang ref-OTP-20.0-rc1 -elixir ref-9825280 +elixir ref-9873e42 nodejs 7.10.0 \ No newline at end of file diff --git a/README.md b/README.md index 41d5886b..300f89b5 100644 --- a/README.md +++ b/README.md @@ -4,7 +4,8 @@ The goal is to convert a subset (or full set) of Elixir code to JavaScript, prov Requirements =========== -* Elixir +* Erlang 20 or greater +* Elixir 1.5 or greater * Node (only for development) Usage diff --git a/lib/elixir_script/next/beam.ex b/lib/elixir_script/next/beam.ex index c6183758..7660eaa0 100644 --- a/lib/elixir_script/next/beam.ex +++ b/lib/elixir_script/next/beam.ex @@ -23,6 +23,8 @@ defmodule ElixirScript.Beam do {:error, "Unknown module"} {:error,:beam_lib,{:unknown_chunk,"non_existing.beam",:debug_info}} -> {:error, "Unsupported version of Erlang"} + {:error,:beam_lib,{:missing_chunk, _ , _}} -> + {:error, "Debug info not available"} {:error,:beam_lib,{:file_error,"non_existing.beam",:enoent}} -> {:error, "Debug info not available"} end diff --git a/lib/elixir_script/next/passes/find_used.ex b/lib/elixir_script/next/passes/find_used.ex index 8a19d9e6..07cde8f0 100644 --- a/lib/elixir_script/next/passes/find_used.ex +++ b/lib/elixir_script/next/passes/find_used.ex @@ -2,6 +2,19 @@ defmodule ElixirScript.FindUsed do @moduledoc false alias ElixirScript.State, as: ModuleState + @erlang_modules [ + :erlang, + :maps, + :lists, + :gen, + :elixir_errors, + :supervisor, + :application, + :code, + :elixir_utils, + :file + ] + @doc """ Takes a list of entry modules and finds modules they use along with documenting the functions used. The data collected about used functions @@ -127,7 +140,8 @@ defmodule ElixirScript.FindUsed do do_execute(module, state.pid) end end - Enum.each(params, &walk(&1, state)) + + walk(params, state) end defp walk({:for, _, generators}, state) do @@ -181,11 +195,11 @@ defmodule ElixirScript.FindUsed do if rescue_block do Enum.each(rescue_block, fn - {:->, _, [ [{:in, _, [param, names]}], body]} -> - walk({[], [param], [{{:., [], [Enum, :member?]}, [], [param, names]}], body}, state) - {:->, _, [ [param], body]} -> - walk({[], [param], [], body}, state) - end) + {:->, _, [ [{:in, _, [param, names]}], body]} -> + walk({[], [param], [{{:., [], [Enum, :member?]}, [], [param, names]}], body}, state) + {:->, _, [ [param], body]} -> + walk({[], [param], [], body}, state) + end) end if catch_block do @@ -205,15 +219,8 @@ defmodule ElixirScript.FindUsed do Enum.each(clauses, &walk(&1, state)) end - defp walk({{:., _, [:erlang, _]}, _, _}, _state) do - nil - end - - defp walk({{:., _, [:lists, _]}, _, _}, _state) do - nil - end - - defp walk({{:., _, [:maps, _]}, _, _}, _state) do + defp walk({{:., _, [module, function]}, _, params}, _state) when module in @erlang_modules do + IO.inspect {module, function, length(params)} nil end diff --git a/lib/elixir_script/next/passes/translate.ex b/lib/elixir_script/next/passes/translate.ex index 5319086a..8d1660d7 100644 --- a/lib/elixir_script/next/passes/translate.ex +++ b/lib/elixir_script/next/passes/translate.ex @@ -40,7 +40,7 @@ defmodule ElixirScript.Translate do |> Generator.generate concat(js_code) - |> IO.puts + #|> IO.puts end defp concat(code) do diff --git a/lib/elixir_script/next/passes/translate/examples/example.ex b/lib/elixir_script/next/passes/translate/examples/example.ex index 677bf0f8..cc1dfdf0 100644 --- a/lib/elixir_script/next/passes/translate/examples/example.ex +++ b/lib/elixir_script/next/passes/translate/examples/example.ex @@ -1,10 +1,6 @@ defmodule Example do def new() do - newnew() - end - - def newnew() do - Atom.to_string("hello") + Base.encode16("hello") end end diff --git a/lib/elixir_script/next/passes/translate/examples/size.ex b/lib/elixir_script/next/passes/translate/examples/size.ex index d2a2619d..10dadd44 100644 --- a/lib/elixir_script/next/passes/translate/examples/size.ex +++ b/lib/elixir_script/next/passes/translate/examples/size.ex @@ -1,22 +1,16 @@ defprotocol Example.Size do - @compile {:undocumented_elixir_backend_option, ElixirScript.Translate.Backend} def size(data) end defimpl Example.Size, for: BitString do - @compile {:undocumented_elixir_backend_option, ElixirScript.Translate.Backend} def size(string), do: byte_size(string) end defimpl Example.Size, for: Map do - @compile {:undocumented_elixir_backend_option, ElixirScript.Translate.Backend} - def size(map), do: map_size(map) end defimpl Example.Size, for: Tuple do - @compile {:undocumented_elixir_backend_option, ElixirScript.Translate.Backend} - def size(tuple), do: tuple_size(tuple) end \ No newline at end of file diff --git a/lib/elixir_script/next/passes/translate/module.ex b/lib/elixir_script/next/passes/translate/module.ex index dd5b142b..04daa366 100644 --- a/lib/elixir_script/next/passes/translate/module.ex +++ b/lib/elixir_script/next/passes/translate/module.ex @@ -17,7 +17,7 @@ defmodule ElixirScript.Translate.Module do file: _file, line: _line, module: ^module, - unreachable: _unreachable, + unreachable: unreachable, used: used } = info @@ -27,7 +27,13 @@ defmodule ElixirScript.Translate.Module do # Filter so that we only have the # Used functions to compile - used_defs = Enum.filter(defs, fn + used_defs = defs + |> Enum.filter(fn + { _, type, _, _} when type in [:defmacro, :defmacrop] -> false + { name, _, _, _} -> not(name in unreachable) + _ -> true + end) + |> Enum.filter(fn { name, _, _, _} -> name in used _ -> false end) diff --git a/src/javascript/lib/core/erlang_compat/erlang.js b/src/javascript/lib/core/erlang_compat/erlang.js index ff8b4c56..d1b75509 100644 --- a/src/javascript/lib/core/erlang_compat/erlang.js +++ b/src/javascript/lib/core/erlang_compat/erlang.js @@ -1 +1,3 @@ +// http://erlang.org/doc/man/erlang.html + export default {}; diff --git a/src/javascript/lib/core/erlang_compat/lists.js b/src/javascript/lib/core/erlang_compat/lists.js index ff8b4c56..245b967c 100644 --- a/src/javascript/lib/core/erlang_compat/lists.js +++ b/src/javascript/lib/core/erlang_compat/lists.js @@ -1 +1,3 @@ +// http://erlang.org/doc/man/lists.html + export default {}; diff --git a/src/javascript/lib/core/erlang_compat/maps.js b/src/javascript/lib/core/erlang_compat/maps.js index ff8b4c56..f7269751 100644 --- a/src/javascript/lib/core/erlang_compat/maps.js +++ b/src/javascript/lib/core/erlang_compat/maps.js @@ -1 +1,3 @@ +// http://erlang.org/doc/man/maps.html + export default {}; From 030fb4d37aa7e55353c1e2c2b91fb3d043f2fbd0 Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Sun, 28 May 2017 11:07:55 -0500 Subject: [PATCH 540/860] Switch to ava for JavaScript testing. Add some implementations and tests for erlang compat. Add new pass to compiler for handling output --- .gitignore | 1 + lib/elixir_script/compile_error.ex | 3 + .../elixir_script_compile_error.ex | 3 - lib/elixir_script/next/beam.ex | 3 +- lib/elixir_script/next/compiler.ex | 15 +- lib/elixir_script/next/passes/output.ex | 74 + lib/elixir_script/next/passes/translate.ex | 46 - .../next/passes/translate/examples/example.ex | 4 +- .../next/passes/translate/form.ex | 4 +- .../next/passes/translate/module.ex | 1 + lib/elixir_script/passes/create_js_modules.ex | 2 +- lib/mix/tasks/compile.elixir_script.ex | 2 +- package.json | 21 +- .../lib/core/erlang_compat/erlang.js | 12 +- .../lib/core/erlang_compat/lists.js | 8 +- src/javascript/lib/core/erlang_compat/maps.js | 34 +- src/javascript/tests/case.spec.js | 51 +- src/javascript/tests/cond.spec.js | 21 +- .../tests/core/erlang_compat/erlang_spec.js | 15 + .../tests/core/erlang_compat/lists_spec.js | 6 + .../tests/core/erlang_compat/maps_spec.js | 22 + src/javascript/tests/core/functions.spec.js | 24 +- src/javascript/tests/for.spec.js | 179 +- src/javascript/tests/try.spec.js | 56 +- src/javascript/tests/with.spec.js | 152 +- test/app/spec/atom.spec.js | 14 - test/app/spec/bootstrap/functions.spec.js | 29 - test/app/spec/enum.spec.js | 126 - test/app/spec/exception.spec.js | 39 - test/app/spec/integer.spec.js | 53 - test/app/spec/main.spec.js | 24 +- test/app/spec/setup.spec.js | 15 - test/app/spec/struct.spec.js | 36 - test/app/spec/tuple.spec.js | 29 - yarn.lock | 2522 +++++++++++++++-- 35 files changed, 2803 insertions(+), 843 deletions(-) create mode 100644 lib/elixir_script/compile_error.ex delete mode 100644 lib/elixir_script/elixir_script_compile_error.ex create mode 100644 lib/elixir_script/next/passes/output.ex create mode 100644 src/javascript/tests/core/erlang_compat/erlang_spec.js create mode 100644 src/javascript/tests/core/erlang_compat/lists_spec.js create mode 100644 src/javascript/tests/core/erlang_compat/maps_spec.js delete mode 100644 test/app/spec/atom.spec.js delete mode 100644 test/app/spec/bootstrap/functions.spec.js delete mode 100644 test/app/spec/enum.spec.js delete mode 100644 test/app/spec/exception.spec.js delete mode 100644 test/app/spec/integer.spec.js delete mode 100644 test/app/spec/setup.spec.js delete mode 100644 test/app/spec/struct.spec.js delete mode 100644 test/app/spec/tuple.spec.js diff --git a/.gitignore b/.gitignore index 6eea78e1..382f0cac 100644 --- a/.gitignore +++ b/.gitignore @@ -19,4 +19,5 @@ src/elixirscript priv/**/*.js stdlib_state.bin *.log +.nyc_output test/app/build diff --git a/lib/elixir_script/compile_error.ex b/lib/elixir_script/compile_error.ex new file mode 100644 index 00000000..fea01237 --- /dev/null +++ b/lib/elixir_script/compile_error.ex @@ -0,0 +1,3 @@ +defmodule ElixirScript.CompileError do + defexception [:message] +end diff --git a/lib/elixir_script/elixir_script_compile_error.ex b/lib/elixir_script/elixir_script_compile_error.ex deleted file mode 100644 index 978d1d84..00000000 --- a/lib/elixir_script/elixir_script_compile_error.ex +++ /dev/null @@ -1,3 +0,0 @@ -defmodule ElixirScriptCompileError do - defexception [:message] -end diff --git a/lib/elixir_script/next/beam.ex b/lib/elixir_script/next/beam.ex index 7660eaa0..d9838c28 100644 --- a/lib/elixir_script/next/beam.ex +++ b/lib/elixir_script/next/beam.ex @@ -9,7 +9,8 @@ defmodule ElixirScript.Beam do """ @spec debug_info(atom) :: {:ok | :error, map | binary} def debug_info(module) when is_atom(module) do - with {_, beam, _} <- :code.get_object_code(module), + #TODO: Get modified date from _beam_path to check for cached version? + with {_, beam, _beam_path} <- :code.get_object_code(module), {:ok, {^module, [debug_info: {:debug_info_v1, backend, data}]}} <- :beam_lib.chunks(beam, [:debug_info]), {:ok, {^module, attribute_info}} = :beam_lib.chunks(beam, [:attributes]) do diff --git a/lib/elixir_script/next/compiler.ex b/lib/elixir_script/next/compiler.ex index 864fa645..0fa7bb21 100644 --- a/lib/elixir_script/next/compiler.ex +++ b/lib/elixir_script/next/compiler.ex @@ -5,7 +5,7 @@ defmodule ElixirScript.Compiler do @spec compile([atom], []) :: nil def compile(entry_modules, opts \\ []) do - opts = build_compiler_options(opts) + opts = build_compiler_options(opts, entry_modules) {:ok, pid} = ElixirScript.State.start_link(opts) IO.puts "Finding used modules and functions" @@ -15,19 +15,24 @@ defmodule ElixirScript.Compiler do IO.puts "Compiling" modules = ElixirScript.State.list_modules(pid) - ElixirScript.Translate.execute(modules, pid) + + IO.puts "Building Output" + modules = ElixirScript.State.list_modules(pid) + ElixirScript.Output.execute(modules, pid) ElixirScript.State.stop(pid) end - defp build_compiler_options(opts) do + defp build_compiler_options(opts, entry_modules) do default_options = Map.new - |> Map.put(:output, nil) - |> Map.put(:format, :es) + |> Map.put(:output, Keyword.get(opts, :output)) + |> Map.put(:format, Keyword.get(opts, :format, :es)) |> Map.put(:js_modules, Keyword.get(opts, :js_modules, [])) + |> Map.put(:entry_modules, entry_modules) options = default_options + IO.inspect options Map.put(options, :module_formatter, get_module_formatter(options[:format])) end diff --git a/lib/elixir_script/next/passes/output.ex b/lib/elixir_script/next/passes/output.ex new file mode 100644 index 00000000..f2cdd164 --- /dev/null +++ b/lib/elixir_script/next/passes/output.ex @@ -0,0 +1,74 @@ +defmodule ElixirScript.Output do + @moduledoc false + + alias ElixirScript.State, as: ModuleState + alias ESTree.Tools.{Builder, Generator} + @generated_name "Elixir.App.js" + + @doc """ + Takes outputs the JavaScript code in the specified output + """ + @spec execute([atom], pid) :: nil + def execute(modules, pid) do + modules = Enum.filter_map(modules, fn {_, info} -> Map.has_key?(info, :js_ast) end, + fn {_module, info} -> + info.js_ast + end + ) + + opts = ModuleState.get_compiler_opts(pid) + + bundle(modules, opts) + |> output(Map.get(opts, :output)) + end + + defp bundle(modules, opts) do + ElixirScript.Passes.CreateJSModules.compile(modules, opts) + + js_code = modules + |> ElixirScript.Passes.CreateJSModules.compile(opts) + |> List.wrap + |> Builder.program + |> prepare_js_ast + |> Generator.generate + + concat(js_code) + end + + defp concat(code) do + "'use strict';\n" <> ElixirScript.get_bootstrap_js("iife") <> "\n" <> code + end + + defp prepare_js_ast(js_ast) do + case js_ast do + modules when is_list(modules) -> + modules + |> Enum.reduce([], &(&2 ++ &1.body)) + |> Builder.program + %ElixirScript.Translator.Group{body: body} -> + Builder.program(body) + %ElixirScript.Translator.Empty{} -> + Builder.program([]) + _ -> + js_ast + end + end + + defp output(code, nil), do: code + defp output(code, :stdout), do: IO.puts(code) + + defp output(code, path) do + file_name = case Path.extname(path) do + ".js" -> + path + _ -> + Path.join([path, @generated_name]) + end + + if !File.exists?(Path.dirname(file_name)) do + File.mkdir_p!(Path.dirname(file_name)) + end + + File.write!(file_name, code) + end +end \ No newline at end of file diff --git a/lib/elixir_script/next/passes/translate.ex b/lib/elixir_script/next/passes/translate.ex index 8d1660d7..b32a05bb 100644 --- a/lib/elixir_script/next/passes/translate.ex +++ b/lib/elixir_script/next/passes/translate.ex @@ -14,51 +14,5 @@ defmodule ElixirScript.Translate do Enum.each(modules, fn({module, info}) -> ElixirScript.Translate.Module.compile(module, info, pid) end) - - modules = ElixirScript.State.list_modules(pid) - - modules = Enum.filter_map(modules, - fn {_, info} -> Map.has_key?(info, :js_ast) end, - fn {_module, info} -> - info.js_ast - end - ) - - opts = ModuleState.get_compiler_opts(pid) - - bundle(modules, opts) - end - - defp bundle(modules, opts) do - ElixirScript.Passes.CreateJSModules.compile(modules, opts) - - js_code = modules - |> ElixirScript.Passes.CreateJSModules.compile(opts) - |> List.wrap - |> Builder.program - |> prepare_js_ast - |> Generator.generate - - concat(js_code) - #|> IO.puts - end - - defp concat(code) do - "'use strict';\n" <> ElixirScript.get_bootstrap_js("iife") <> "\n" <> code - end - - defp prepare_js_ast(js_ast) do - case js_ast do - modules when is_list(modules) -> - modules - |> Enum.reduce([], &(&2 ++ &1.body)) - |> Builder.program - %ElixirScript.Translator.Group{body: body} -> - Builder.program(body) - %ElixirScript.Translator.Empty{} -> - Builder.program([]) - _ -> - js_ast - end end end diff --git a/lib/elixir_script/next/passes/translate/examples/example.ex b/lib/elixir_script/next/passes/translate/examples/example.ex index cc1dfdf0..02f457a1 100644 --- a/lib/elixir_script/next/passes/translate/examples/example.ex +++ b/lib/elixir_script/next/passes/translate/examples/example.ex @@ -1,6 +1,6 @@ defmodule Example do - def new() do - Base.encode16("hello") + def start(_, _) do + Atom.to_string(:gravity) end end diff --git a/lib/elixir_script/next/passes/translate/form.ex b/lib/elixir_script/next/passes/translate/form.ex index 5d69280a..b8f3952b 100644 --- a/lib/elixir_script/next/passes/translate/form.ex +++ b/lib/elixir_script/next/passes/translate/form.ex @@ -122,7 +122,7 @@ defmodule ElixirScript.Translate.Form do def compile({:receive, context, _}, _state) do line = Keyword.get(context, :line, 1) - raise ElixirScriptCompileError, message: "Line: #{line} receive not supported" + raise ElixirScript.CompileError, message: "Line: #{line} receive not supported" end def compile({:try, _, [blocks]}, state) do @@ -149,7 +149,7 @@ defmodule ElixirScript.Translate.Form do ), J.identifier(module) ), - J.identifier(function) + ElixirScript.Translator.Identifier.make_function_name(function, length(params)) ), Enum.map(params, &compile(&1, state)) ) diff --git a/lib/elixir_script/next/passes/translate/module.ex b/lib/elixir_script/next/passes/translate/module.ex index 04daa366..6d3f96bf 100644 --- a/lib/elixir_script/next/passes/translate/module.ex +++ b/lib/elixir_script/next/passes/translate/module.ex @@ -34,6 +34,7 @@ defmodule ElixirScript.Translate.Module do _ -> true end) |> Enum.filter(fn + { {:start, 2}, _, _, _ } -> true { name, _, _, _} -> name in used _ -> false end) diff --git a/lib/elixir_script/passes/create_js_modules.ex b/lib/elixir_script/passes/create_js_modules.ex index a0cff524..2ba89848 100644 --- a/lib/elixir_script/passes/create_js_modules.ex +++ b/lib/elixir_script/passes/create_js_modules.ex @@ -100,7 +100,7 @@ defmodule ElixirScript.Passes.CreateJSModules do ), [JS.identifier("Elixir")] ), - JS.identifier("start") + JS.identifier("start2") ), [ElixirScript.Translator.Primitive.make_atom(:normal), JS.identifier(:args)] ) diff --git a/lib/mix/tasks/compile.elixir_script.ex b/lib/mix/tasks/compile.elixir_script.ex index b02c937d..e448a117 100644 --- a/lib/mix/tasks/compile.elixir_script.ex +++ b/lib/mix/tasks/compile.elixir_script.ex @@ -43,7 +43,7 @@ defmodule Mix.Tasks.Compile.ElixirScript do end defp do_compile(_, nil) do - raise ElixirScriptCompileError, message: "Unable to find mix project app name" + raise ElixirScript.CompileError, message: "Unable to find mix project app name" end defp do_compile(elixirscript_base, app) do diff --git a/package.json b/package.json index c9ecbf18..90b86fb4 100644 --- a/package.json +++ b/package.json @@ -11,9 +11,9 @@ "lint:fix": "eslint src/javascript/lib/**/*.js src/javascript/tests/**/*.js --fix", "build": "rollup -c rollup.config.js", "clean": "rm -rf priv/build", - "test": "mocha src/javascript/tests --recursive --compilers js:babel-core/register", + "test": "nyc ava src/javascript/tests", "build:test-app": "mix elixirscript test/app/src/ -f common -o test/app/build/", - "test-app": "yarn run build:test-app && NODE_ENV=test mocha --recursive 'test/app/spec/**/*.spec.js' --compilers js:babel-register" + "test-app": "yarn run build:test-app && NODE_ENV=test ava 'test/app/spec/**/*.spec.js'" }, "repository": { "type": "git", @@ -26,19 +26,26 @@ "tailored": "2.4.5" }, "devDependencies": { + "ava": "^0.19.1", "babel-core": "^6.24.0", - "babel-register": "^6.24.0", "babel-preset-env": "^1.3.2", - "chai": "^3.5.0", + "babel-register": "^6.24.0", "eslint": "^3.15.0", "eslint-config-airbnb-base": "^11.1.0", "eslint-plugin-import": "^2.2.0", - "mocha": "^3.2.0", + "nyc": "^10.3.2", "rollup": "^0.41.6", "rollup-plugin-babel": "^2.7.1", "rollup-plugin-babili": "^2.0.0", "rollup-plugin-node-resolve": "^2.0.0", - "sinon": "^1.17.7", - "sinon-chai": "^2.8.0" + "sinon": "^1.17.7" + }, + "ava": { + "require": [ + "babel-register" + ], + "babel": { + "babelrc": true + } } } \ No newline at end of file diff --git a/src/javascript/lib/core/erlang_compat/erlang.js b/src/javascript/lib/core/erlang_compat/erlang.js index d1b75509..6de89420 100644 --- a/src/javascript/lib/core/erlang_compat/erlang.js +++ b/src/javascript/lib/core/erlang_compat/erlang.js @@ -1,3 +1,13 @@ // http://erlang.org/doc/man/erlang.html -export default {}; +function atom_to_binary2(atom, encoding = Symbol.for('utf8')) { + if (encoding !== Symbol.for('utf8')) { + throw new Error(`unsupported encoding ${encoding}`); + } + + return Symbol.keyFor(atom); +} + +export default { + atom_to_binary2, +}; diff --git a/src/javascript/lib/core/erlang_compat/lists.js b/src/javascript/lib/core/erlang_compat/lists.js index 245b967c..1d2814df 100644 --- a/src/javascript/lib/core/erlang_compat/lists.js +++ b/src/javascript/lib/core/erlang_compat/lists.js @@ -1,3 +1,9 @@ // http://erlang.org/doc/man/lists.html -export default {}; +function reverse1(list) { + return [...list].reverse(); +} + +export default { + reverse1, +}; diff --git a/src/javascript/lib/core/erlang_compat/maps.js b/src/javascript/lib/core/erlang_compat/maps.js index f7269751..97e42b91 100644 --- a/src/javascript/lib/core/erlang_compat/maps.js +++ b/src/javascript/lib/core/erlang_compat/maps.js @@ -1,3 +1,35 @@ // http://erlang.org/doc/man/maps.html +import ErlangTypes from 'erlang-types'; -export default {}; +const OK = Symbol.for('ok'); +const ERROR = Symbol.for('error'); +const BADMAP = Symbol.for('badmap'); + +function find2(key, map) { + if (map instanceof Object === false) { + return new ErlangTypes.Tuple(BADMAP, map); + } + + const value = map[key]; + + if (typeof value !== 'undefined') { + return new ErlangTypes.Tuple(OK, value); + } + + return ERROR; +} + +function fold3(fun, init, map) { + let acc = init; + + for (const [key, value] of Object.entries(map)) { + acc = fun(key, value, acc); + } + + return acc; +} + +export default { + find2, + fold3, +}; diff --git a/src/javascript/tests/case.spec.js b/src/javascript/tests/case.spec.js index 9dc4e43e..4b143edc 100644 --- a/src/javascript/tests/case.spec.js +++ b/src/javascript/tests/case.spec.js @@ -1,36 +1,33 @@ +import test from 'ava'; import Core from '../lib/core'; -import chai from 'chai'; + const Patterns = Core.Patterns; const SpecialForms = Core.SpecialForms; const Tuple = Core.Tuple; -const expect = chai.expect; - -describe('case', () => { - it('case', () => { - const clauses = [ - Patterns.clause( - [ - new Tuple( - Symbol.for('selector'), - Patterns.variable(), - Patterns.variable(), - ), - ], - (i, value) => { - return value; - }, - i => { - return Kernel.is_integer(i); - }, - ), - Patterns.clause([Patterns.variable()], value => { +test('case', t => { + const clauses = [ + Patterns.clause( + [ + new Tuple( + Symbol.for('selector'), + Patterns.variable(), + Patterns.variable() + ), + ], + (i, value) => { return value; - }), - ]; + }, + i => { + return Kernel.is_integer(i); + } + ), + Patterns.clause([Patterns.variable()], value => { + return value; + }), + ]; - const result = SpecialForms._case('thing', clauses); + const result = SpecialForms._case('thing', clauses); - expect(result).to.equal('thing'); - }); + t.is(result, 'thing'); }); diff --git a/src/javascript/tests/cond.spec.js b/src/javascript/tests/cond.spec.js index 3e16ad18..c5d66aed 100644 --- a/src/javascript/tests/cond.spec.js +++ b/src/javascript/tests/cond.spec.js @@ -1,19 +1,16 @@ -import chai from 'chai'; +import test from 'ava'; import Core from '../lib/core'; const SpecialForms = Core.SpecialForms; -const expect = chai.expect; -describe('cond', () => { - it('cond', () => { - const clauses = [ - [1 + 1 === 1, () => 'This will never match'], - [2 * 2 !== 4, () => 'Nor this'], - [true, () => 'This will'], - ]; +test('cond', t => { + const clauses = [ + [1 + 1 === 1, () => 'This will never match'], + [2 * 2 !== 4, () => 'Nor this'], + [true, () => 'This will'], + ]; - const result = SpecialForms.cond(clauses); + const result = SpecialForms.cond(clauses); - expect(result).to.equal('This will'); - }); + t.is(result, 'This will'); }); diff --git a/src/javascript/tests/core/erlang_compat/erlang_spec.js b/src/javascript/tests/core/erlang_compat/erlang_spec.js new file mode 100644 index 00000000..299f56f5 --- /dev/null +++ b/src/javascript/tests/core/erlang_compat/erlang_spec.js @@ -0,0 +1,15 @@ +import test from 'ava'; +import Core from '../../../lib/core'; + +test('atom_to_binary2', t => { + t.is(Core.erlang.atom_to_binary2(Symbol.for('error')), 'error'); + t.is( + Core.erlang.atom_to_binary2(Symbol.for('error'), Symbol.for('utf8')), + 'error' + ); + + t.throws( + () => Core.erlang.atom_to_binary2(Symbol.for('error'), Symbol.for('utf16')), + Error + ); +}); diff --git a/src/javascript/tests/core/erlang_compat/lists_spec.js b/src/javascript/tests/core/erlang_compat/lists_spec.js new file mode 100644 index 00000000..e86e6d46 --- /dev/null +++ b/src/javascript/tests/core/erlang_compat/lists_spec.js @@ -0,0 +1,6 @@ +import test from 'ava'; +import Core from '../../../lib/core'; + +test('reverse1', t => { + t.deepEqual(Core.lists.reverse1([1, 2, 3]), [3, 2, 1]); +}); diff --git a/src/javascript/tests/core/erlang_compat/maps_spec.js b/src/javascript/tests/core/erlang_compat/maps_spec.js new file mode 100644 index 00000000..41d78acd --- /dev/null +++ b/src/javascript/tests/core/erlang_compat/maps_spec.js @@ -0,0 +1,22 @@ +import test from 'ava'; +import Core from '../../../lib/core'; + +test('find2', t => { + let myMap = {}; + let result = Core.maps.find2('t', myMap); + t.is(result, Symbol.for('error')); + + myMap = 'Hello'; + result = Core.maps.find2('t', myMap); + t.deepEqual(result.values, [Symbol.for('badmap'), myMap]); + + myMap = { t: 'b' }; + result = Core.maps.find2('t', myMap); + t.deepEqual(result.values, [Symbol.for('ok'), 'b']); +}); + +test('fold3', t => { + let myMap = { a: 1, b: 2 }; + let result = Core.maps.fold3((k, v, acc) => acc + v, 0, myMap); + t.is(result, 3); +}); diff --git a/src/javascript/tests/core/functions.spec.js b/src/javascript/tests/core/functions.spec.js index 698d8c3c..f9076d44 100644 --- a/src/javascript/tests/core/functions.spec.js +++ b/src/javascript/tests/core/functions.spec.js @@ -1,18 +1,14 @@ +import test from 'ava'; import Core from '../../lib/core'; const Functions = Core.Functions; -import chai from 'chai'; -const expect = chai.expect; - -describe('Functions', () => { - it('call_property', () => { - expect(Functions.call_property(1, 'toString')).to.equal('1'); - expect(Functions.call_property([], 'toString')).to.equal(''); - expect(Functions.call_property([], 'length')).to.equal(0); - expect(Functions.call_property('', 'toString')).to.equal(''); - expect(Functions.call_property('', 'length')).to.equal(0); - expect(Functions.call_property(Symbol('test'), 'toString')).to.equal('Symbol(test)'); - expect(Functions.call_property({ completed: false }, 'completed')).to.equal(false); - expect(Functions.call_property({ id: 0 }, 'id')).to.equal(0); - }); +test('call_property', t => { + t.is(Functions.call_property(1, 'toString'), '1'); + t.is(Functions.call_property([], 'toString'), ''); + t.is(Functions.call_property([], 'length'), 0); + t.is(Functions.call_property('', 'toString'), ''); + t.is(Functions.call_property('', 'length'), 0); + t.is(Functions.call_property(Symbol('test'), 'toString'), 'Symbol(test)'); + t.is(Functions.call_property({ completed: false }, 'completed'), false); + t.is(Functions.call_property({ id: 0 }, 'id'), 0); }); diff --git a/src/javascript/tests/for.spec.js b/src/javascript/tests/for.spec.js index d43cf9d4..52e29d48 100644 --- a/src/javascript/tests/for.spec.js +++ b/src/javascript/tests/for.spec.js @@ -1,12 +1,10 @@ +import test from 'ava'; import Core from '../lib/core'; -import chai from 'chai'; const Patterns = Core.Patterns; const SpecialForms = Core.SpecialForms; const Tuple = Core.Tuple; const BitString = Core.BitString; -const expect = chai.expect; - const $ = Patterns.variable(); const collectable = { @@ -19,116 +17,117 @@ const collectable = { values: [Symbol.for('cont'), Patterns.variable()], }), ], - (list, x) => list.concat([x]), + (list, x) => list.concat([x]) ), - Patterns.clause([$, Symbol.for('done')], list => list), + Patterns.clause([$, Symbol.for('done')], list => list) ); return new Tuple([], fun); }, }; -describe('for', () => { - it('simple for', () => { - const gen = Patterns.list_generator($, [1, 2, 3, 4]); - const result = SpecialForms._for( - Patterns.clause([$], x => x * 2), - [gen], - collectable, - ); +test('simple for', t => { + const gen = Patterns.list_generator($, [1, 2, 3, 4]); + const result = SpecialForms._for( + Patterns.clause([$], x => x * 2), + [gen], + collectable + ); - expect(result).to.eql([2, 4, 6, 8]); - }); + t.deepEqual(result, [2, 4, 6, 8]); +}); - it('for with multiple generators', () => { - //for x <- [1, 2], y <- [2, 3], do: x*y +test('for with multiple generators', t => { + //for x <- [1, 2], y <- [2, 3], do: x*y - const gen = Patterns.list_generator($, [1, 2]); - const gen2 = Patterns.list_generator($, [2, 3]); - const result = SpecialForms._for( - Patterns.clause([$, $], (x, y) => x * y), - [gen, gen2], - collectable, - ); + const gen = Patterns.list_generator($, [1, 2]); + const gen2 = Patterns.list_generator($, [2, 3]); + const result = SpecialForms._for( + Patterns.clause([$, $], (x, y) => x * y), + [gen, gen2], + collectable + ); - expect(result).to.eql([2, 3, 4, 6]); - }); + t.deepEqual(result, [2, 3, 4, 6]); +}); - it('for with filter', () => { - //for n <- [1, 2, 3, 4, 5, 6], rem(n, 2) == 0, do: n - const gen = Patterns.list_generator($, [1, 2, 3, 4, 5, 6]); - const result = SpecialForms._for( - Patterns.clause([$], x => x, x => x % 2 === 0), - [gen], - collectable, - ); +test('for with filter', t => { + //for n <- [1, 2, 3, 4, 5, 6], rem(n, 2) == 0, do: n + const gen = Patterns.list_generator($, [1, 2, 3, 4, 5, 6]); + const result = SpecialForms._for( + Patterns.clause([$], x => x, x => x % 2 === 0), + [gen], + collectable + ); - expect(result).to.eql([2, 4, 6]); - }); + t.deepEqual(result, [2, 4, 6]); +}); - it('for with pattern matching', () => { - //for {:user, name} <- [user: "john", admin: "john", user: "meg"], do - // String.upcase(name) - //end +test('for with pattern matching', t => { + //for {:user, name} <- [user: "john", admin: "john", user: "meg"], do + // String.upcase(name) + //end - const gen = Patterns.list_generator([Symbol.for('user'), $], [ + const gen = Patterns.list_generator( + [Symbol.for('user'), $], + [ [Symbol.for('user'), 'john'], [Symbol.for('admin'), 'john'], [Symbol.for('user'), 'meg'], - ]); - - const result = SpecialForms._for( - Patterns.clause([[Symbol.for('user'), $]], name => name.toUpperCase()), - [gen], - collectable, - ); + ] + ); - expect(result).to.eql(['JOHN', 'MEG']); - }); + const result = SpecialForms._for( + Patterns.clause([[Symbol.for('user'), $]], name => name.toUpperCase()), + [gen], + collectable + ); - it('for with bitstring', () => { - //for <> >>, do: {r, g, b} + t.deepEqual(result, ['JOHN', 'MEG']); +}); - const gen = Patterns.bitstring_generator( +test('for with bitstring', t => { + //for <> >>, do: {r, g, b} + + const gen = Patterns.bitstring_generator( + Patterns.bitStringMatch( + BitString.integer({ value: $ }), + BitString.integer({ value: $ }), + BitString.integer({ value: $ }) + ), + new BitString( + BitString.integer(213), + BitString.integer(45), + BitString.integer(132), + BitString.integer(64), + BitString.integer(76), + BitString.integer(32), + BitString.integer(76), + BitString.integer(0), + BitString.integer(0), + BitString.integer(234), + BitString.integer(32), + BitString.integer(15) + ) + ); + + const expression = Patterns.clause( + [ Patterns.bitStringMatch( BitString.integer({ value: $ }), BitString.integer({ value: $ }), - BitString.integer({ value: $ }), + BitString.integer({ value: $ }) ), - new BitString( - BitString.integer(213), - BitString.integer(45), - BitString.integer(132), - BitString.integer(64), - BitString.integer(76), - BitString.integer(32), - BitString.integer(76), - BitString.integer(0), - BitString.integer(0), - BitString.integer(234), - BitString.integer(32), - BitString.integer(15), - ), - ); - - const expression = Patterns.clause( - [ - Patterns.bitStringMatch( - BitString.integer({ value: $ }), - BitString.integer({ value: $ }), - BitString.integer({ value: $ }), - ), - ], - (r, g, b) => new Tuple(r, g, b), - ); - - const result = SpecialForms._for(expression, [gen], collectable); - - expect(result).to.eql([ - new Tuple(213, 45, 132), - new Tuple(64, 76, 32), - new Tuple(76, 0, 0), - new Tuple(234, 32, 15), - ]); - }); + ], + (r, g, b) => new Tuple(r, g, b) + ); + + const result = SpecialForms._for(expression, [gen], collectable); + + t.deepEqual(result, [ + new Tuple(213, 45, 132), + new Tuple(64, 76, 32), + new Tuple(76, 0, 0), + new Tuple(234, 32, 15), + ]); }); diff --git a/src/javascript/tests/try.spec.js b/src/javascript/tests/try.spec.js index b5d9c658..440c7df9 100644 --- a/src/javascript/tests/try.spec.js +++ b/src/javascript/tests/try.spec.js @@ -1,13 +1,10 @@ +import test from 'ava'; import Core from '../lib/core'; const Patterns = Core.Patterns; const SpecialForms = Core.SpecialForms; -import chai from 'chai'; -const expect = chai.expect; - -describe('try', () => { - it('try', () => { - /* +test('try', t => { + /* try do 1 / x else @@ -19,31 +16,30 @@ describe('try', () => { */ - const x = 1; + const x = 1; - const value = SpecialForms._try( - () => { - return 1 / x; - }, - null, - null, - Patterns.defmatch( - Patterns.clause( - [Patterns.variable()], - y => { - return Symbol.for('small'); - }, - y => { - return y < 1 && y > -1; - }, - ), - Patterns.clause([Patterns.wildcard()], () => { - return Symbol.for('large'); - }), + const value = SpecialForms._try( + () => { + return 1 / x; + }, + null, + null, + Patterns.defmatch( + Patterns.clause( + [Patterns.variable()], + y => { + return Symbol.for('small'); + }, + y => { + return y < 1 && y > -1; + } ), - null, - ); + Patterns.clause([Patterns.wildcard()], () => { + return Symbol.for('large'); + }) + ), + null + ); - expect(value).to.equal(Symbol.for('large')); - }); + t.is(value, Symbol.for('large')); }); diff --git a/src/javascript/tests/with.spec.js b/src/javascript/tests/with.spec.js index e1a30150..d57322d8 100644 --- a/src/javascript/tests/with.spec.js +++ b/src/javascript/tests/with.spec.js @@ -1,12 +1,10 @@ import Core from '../lib/core'; -import chai from 'chai'; +import test from 'ava'; const Patterns = Core.Patterns; const SpecialForms = Core.SpecialForms; const Tuple = Core.Tuple; const MatchError = Core.Patterns.MatchError; -const expect = chai.expect; - const $ = Patterns.variable(); function map_fetch(map, key) { @@ -17,9 +15,8 @@ function map_fetch(map, key) { return Symbol.for('error'); } -describe('with', () => { - it('normal', () => { - /* +test('with', t => { + /* opts = %{width: 10, height: 15} with {:ok, width} <- Map.fetch(opts, :width), @@ -29,19 +26,19 @@ describe('with', () => { {:ok, 150} */ - const opts = { width: 10, height: 15 }; + const opts = { width: 10, height: 15 }; - const value = SpecialForms._with( - [new Tuple(Symbol.for('ok'), $), () => map_fetch(opts, 'width')], - [new Tuple(Symbol.for('ok'), $), width => map_fetch(opts, 'height')], - (width, height) => new Tuple(Symbol.for('ok'), width * height), - ); + const value = SpecialForms._with( + [new Tuple(Symbol.for('ok'), $), () => map_fetch(opts, 'width')], + [new Tuple(Symbol.for('ok'), $), width => map_fetch(opts, 'height')], + (width, height) => new Tuple(Symbol.for('ok'), width * height) + ); - expect(value).to.eql(new Tuple(Symbol.for('ok'), 150)); - }); + t.deepEqual(value, new Tuple(Symbol.for('ok'), 150)); +}); - it('without match', () => { - /* +test('with without match', t => { + /* opts = %{width: 10} with {:ok, width} <- Map.fetch(opts, :width), @@ -51,19 +48,19 @@ describe('with', () => { :error */ - const opts = { width: 10 }; + const opts = { width: 10 }; - const value = SpecialForms._with( - [new Tuple(Symbol.for('ok'), $), () => map_fetch(opts, 'width')], - [new Tuple(Symbol.for('ok'), $), width => map_fetch(opts, 'height')], - (width, height) => new Tuple(Symbol.for('ok'), width * height), - ); + const value = SpecialForms._with( + [new Tuple(Symbol.for('ok'), $), () => map_fetch(opts, 'width')], + [new Tuple(Symbol.for('ok'), $), width => map_fetch(opts, 'height')], + (width, height) => new Tuple(Symbol.for('ok'), width * height) + ); - expect(value).to.eql(Symbol.for('error')); - }); + t.deepEqual(value, Symbol.for('error')); +}); - it('bare expression', () => { - /* +test('with bare expression', t => { + /* opts = %{width: 10} with {:ok, width} <- Map.fetch(opts, :width), @@ -74,24 +71,24 @@ describe('with', () => { {:ok, 300} */ - const opts = { width: 10, height: 15 }; + const opts = { width: 10, height: 15 }; - const value = SpecialForms._with( - [new Tuple(Symbol.for('ok'), $), () => map_fetch(opts, 'width')], - [$, width => width * 2], - [ - new Tuple(Symbol.for('ok'), $), - (width, double_width) => map_fetch(opts, 'height'), - ], - (width, double_width, height) => - new Tuple(Symbol.for('ok'), double_width * height), - ); + const value = SpecialForms._with( + [new Tuple(Symbol.for('ok'), $), () => map_fetch(opts, 'width')], + [$, width => width * 2], + [ + new Tuple(Symbol.for('ok'), $), + (width, double_width) => map_fetch(opts, 'height'), + ], + (width, double_width, height) => + new Tuple(Symbol.for('ok'), double_width * height) + ); - expect(value).to.eql(new Tuple(Symbol.for('ok'), 300)); - }); + t.deepEqual(value, new Tuple(Symbol.for('ok'), 300)); +}); - it('with else', () => { - /* +test('with else', t => { + /* opts = %{width: 10} with {:ok, width} <- Map.fetch(opts, :width), @@ -104,27 +101,25 @@ describe('with', () => { {:error, :wrong_data} */ - const opts = { width: 10 }; - - const value = SpecialForms._with( - [new Tuple(Symbol.for('ok'), $), () => map_fetch(opts, 'width')], - [new Tuple(Symbol.for('ok'), $), width => map_fetch(opts, 'height')], - (width, height) => new Tuple(Symbol.for('ok'), width * height), - Patterns.defmatch( - Patterns.clause( - [Symbol.for('error')], - () => new Tuple(Symbol.for('error'), Symbol.for('wrong_data')), - ), - ), - ); - - expect(value).to.eql( - new Tuple(Symbol.for('error'), Symbol.for('wrong_data')), - ); - }); - - it('with else that don`t match', () => { - /* + const opts = { width: 10 }; + + const value = SpecialForms._with( + [new Tuple(Symbol.for('ok'), $), () => map_fetch(opts, 'width')], + [new Tuple(Symbol.for('ok'), $), width => map_fetch(opts, 'height')], + (width, height) => new Tuple(Symbol.for('ok'), width * height), + Patterns.defmatch( + Patterns.clause( + [Symbol.for('error')], + () => new Tuple(Symbol.for('error'), Symbol.for('wrong_data')) + ) + ) + ); + + t.deepEqual(value, new Tuple(Symbol.for('error'), Symbol.for('wrong_data'))); +}); + +test('with else that don`t match', t => { + /* opts = %{width: 10} with {:ok, width} <- Map.fetch(opts, :width), @@ -137,21 +132,20 @@ describe('with', () => { {:error, :wrong_data} */ - const opts = { width: 10 }; - - const withFunction = SpecialForms._with.bind( - null, - [new Tuple(Symbol.for('ok'), $), () => map_fetch(opts, 'width')], - [new Tuple(Symbol.for('ok'), $), width => map_fetch(opts, 'height')], - (width, height) => new Tuple(Symbol.for('ok'), width * height), - Patterns.defmatch( - Patterns.clause( - [Symbol.for('fail')], - () => new Tuple(Symbol.for('error'), Symbol.for('wrong_data')), - ), - ), - ); - - expect(withFunction).to.throw(MatchError, 'No match for: Symbol(error)'); - }); + const opts = { width: 10 }; + + const withFunction = SpecialForms._with.bind( + null, + [new Tuple(Symbol.for('ok'), $), () => map_fetch(opts, 'width')], + [new Tuple(Symbol.for('ok'), $), width => map_fetch(opts, 'height')], + (width, height) => new Tuple(Symbol.for('ok'), width * height), + Patterns.defmatch( + Patterns.clause( + [Symbol.for('fail')], + () => new Tuple(Symbol.for('error'), Symbol.for('wrong_data')) + ) + ) + ); + + t.throws(withFunction, MatchError); }); diff --git a/test/app/spec/atom.spec.js b/test/app/spec/atom.spec.js deleted file mode 100644 index 89e18673..00000000 --- a/test/app/spec/atom.spec.js +++ /dev/null @@ -1,14 +0,0 @@ -const expect = require('chai').expect; -const Elixir = require('../build/Elixir.App'); - -describe('Atom', () => { - it('to_string/1', () => { - const exports = Elixir.load(Elixir.ElixirScript.Atom); - expect(exports.to_string(Symbol.for('héllo'))).to.eq('héllo'); - }); - - it('to_charlist/1', () => { - const exports = Elixir.load(Elixir.ElixirScript.Atom); - expect(exports.to_string(Symbol.for('héllo'))).to.eq('héllo'); - }); -}); diff --git a/test/app/spec/bootstrap/functions.spec.js b/test/app/spec/bootstrap/functions.spec.js deleted file mode 100644 index 2a098233..00000000 --- a/test/app/spec/bootstrap/functions.spec.js +++ /dev/null @@ -1,29 +0,0 @@ -const expect = require('chai').expect; -const Elixir = require('../../build/Elixir.App'); - -describe('Functions', () => { - it('contains', () => { - const Functions = Elixir.load(Elixir.ElixirScript.Bootstrap.Functions); - expect(Functions.contains(1, [])).to.eq(false); - expect(Functions.contains(1, [1, 2, 3])).to.eq(true); - expect(Functions.contains(4, [1, 2, 3])).to.eq(false); - expect(Functions.contains(1, [1])).to.eq(true); - expect(Functions.contains(4, [1])).to.eq(false); - expect(Functions.contains('apple', [1])).to.eq(false); - }); - - it('get_object_keys', () => { - const Functions = Elixir.load(Elixir.ElixirScript.Bootstrap.Functions); - expect(Functions.get_object_keys({})).to.eql([]); - expect(Functions.get_object_keys({ key: 1 })).to.eql(['key']); - expect( - Functions.get_object_keys({ key: 1, [Symbol.for('hi')]: 2 }) - ).to.eql(['key', Symbol.for('hi')]); - }); - - it('is_valid_character', () => { - const Functions = Elixir.load(Elixir.ElixirScript.Bootstrap.Functions); - expect(Functions.is_valid_character(42)).to.eq(true); - expect(Functions.is_valid_character(NaN)).to.eq(false); - }); -}); diff --git a/test/app/spec/enum.spec.js b/test/app/spec/enum.spec.js deleted file mode 100644 index 3a265bfa..00000000 --- a/test/app/spec/enum.spec.js +++ /dev/null @@ -1,126 +0,0 @@ -const expect = require('chai').expect; -const Elixir = require('../build/Elixir.App'); -const Tuple = require('../../../src/javascript/lib/core').default.Tuple; - -const Enum = Elixir.load(Elixir.ElixirScript.Enum); - -describe('Enum', () => { - it('all?/2', () => { - expect(Enum.all__qmark__([2, 4, 6], x => x % 2 === 0)).to.eql(true); - expect(Enum.all__qmark__([2, 3, 4], x => x % 2 === 0)).to.eql(false); - }); - - it('any?/2', () => { - expect(Enum.any__qmark__([2, 4, 6], x => x % 2 === 1)).to.eql(false); - expect(Enum.any__qmark__([2, 3, 4], x => x % 2 === 1)).to.eql(true); - }); - - it('at/3', () => { - expect(Enum.at([2, 4, 6], 0)).to.eql(2); - expect(Enum.at([2, 4, 6], 2)).to.eql(6); - expect(Enum.at([2, 4, 6], 4)).to.eql(null); - expect(Enum.at([2, 4, 6], 4, Symbol.for('none'))).to.eql( - Symbol.for('none'), - ); - - expect(Enum.at([2, 4, 6], -2)).to.eql(4); - expect(Enum.at([2, 4, 6], -4)).to.eql(null); - }); - - it('concat/1', () => { - expect(Enum.concat([[1, [2], 3], [4], [5, 6]])).to.eql([ - 1, - [2], - 3, - 4, - 5, - 6, - ]); - expect(Enum.concat([[], []])).to.eql([]); - expect(Enum.concat([[]])).to.eql([]); - expect(Enum.concat([])).to.eql([]); - }); - - it('concat/2', () => { - expect(Enum.concat([], [1])).to.eql([1]); - expect(Enum.concat([1, [2], 3], [4, 5])).to.eql([1, [2], 3, 4, 5]); - expect(Enum.concat([], [])).to.eql([]); - }); - - it('count/1', () => { - expect(Enum.count([1, 2, 3])).to.eql(3); - expect(Enum.count([])).to.eql(0); - expect(Enum.count([1, true, false, null])).to.eql(4); - }); - - it('count/2', () => { - expect(Enum.count([1, 2, 3], x => x % 2 === 0)).to.eql(1); - expect(Enum.count([], x => x % 2 === 0)).to.eql(0); - expect(Enum.count([1, true, false, null], x => x)).to.eql(2); - }); - - it('drop/2', () => { - expect(Enum.drop([1, 2, 3], 0)).to.eql([1, 2, 3]); - expect(Enum.drop([1, 2, 3], 1)).to.eql([2, 3]); - expect(Enum.drop([1, 2, 3], 2)).to.eql([3]); - expect(Enum.drop([1, 2, 3], 3)).to.eql([]); - expect(Enum.drop([1, 2, 3], 4)).to.eql([]); - expect(Enum.drop([1, 2, 3], -1)).to.eql([1, 2]); - expect(Enum.drop([1, 2, 3], -2)).to.eql([1]); - expect(Enum.drop([1, 2, 3], -4)).to.eql([]); - }); - - it('drop_every/2', () => { - expect(Enum.drop_every([1, 2, 3, 4, 5, 6, 7, 8, 9, 10], 2)).to.eql([ - 2, - 4, - 6, - 8, - 10, - ]); - - expect(Enum.drop_every([1, 2, 3, 4, 5, 6, 7, 8, 9, 10], 3)).to.eql([ - 2, - 3, - 5, - 6, - 8, - 9, - ]); - - expect(Enum.drop_every([], 2)).to.eql([]); - expect(Enum.drop_every([1, 2], 2)).to.eql([2]); - expect(Enum.drop_every([1, 2, 3], 0)).to.eql([1, 2, 3]); - }); - - it('drop_while/2', () => { - expect(Enum.drop_while([1, 2, 3, 4, 3, 2, 1], x => x <= 3)).to.eql([ - 4, - 3, - 2, - 1, - ]); - - expect(Enum.drop_while([1, 2, 3], _ => false)).to.eql([1, 2, 3]); - expect(Enum.drop_while([1, 2, 3], x => x <= 3)).to.eql([]); - expect(Enum.drop_while([], _ => false)).to.eql([]); - }); - - it('empty?/1', () => { - expect(Enum.empty__qmark__([])).to.eql(true); - expect(Enum.empty__qmark__([1, 2, 3])).to.eql(false); - }); - - it('fetch/2', () => { - expect(Enum.fetch([66], 0)).to.eql(new Tuple(Symbol.for('ok'), 66)); - expect(Enum.fetch([66], -1)).to.eql(new Tuple(Symbol.for('ok'), 66)); - expect(Enum.fetch([66], 1)).to.eql(Symbol.for('error')); - expect(Enum.fetch([66], -2)).to.eql(Symbol.for('error')); - }); - - it('fetch!/2', () => { - expect(Enum.fetch__emark__([2, 4, 6], 0)).to.eql(2); - expect(Enum.fetch__emark__([2, 4, 6], 2)).to.eql(6); - expect(Enum.fetch__emark__([2, 4, 6], -2)).to.eql(4); - }); -}); diff --git a/test/app/spec/exception.spec.js b/test/app/spec/exception.spec.js deleted file mode 100644 index 7e3f19db..00000000 --- a/test/app/spec/exception.spec.js +++ /dev/null @@ -1,39 +0,0 @@ -const expect = require('chai').expect; -const Elixir = require('../build/Elixir.App'); - -describe('Exception', () => { - it('Create Exception', () => { - const ArgumentError = Elixir.load(Elixir.ElixirScript.ArgumentError); - - let struct = ArgumentError.__struct__(); - - expect(Object.getOwnPropertySymbols(struct)).to.eql([ - Symbol.for('__struct__'), - Symbol.for('message'), - Symbol.for('__exception__'), - ]); - - expect(struct[Symbol.for('__struct__')]).to.eql( - Symbol.for('Elixir.ElixirScript.ArgumentError'), - ); - expect(struct[Symbol.for('__exception__')]).to.eql(true); - expect(struct[Symbol.for('message')]).to.eql('argument error'); - - struct = ArgumentError.__struct__({ - [Symbol.for('message')]: 'new argument error', - }); - - expect(struct[Symbol.for('message')]).to.eql('new argument error'); - }); - - it('raise exception', () => { - const User = Elixir.load(Elixir.User); - const ArgumentError = Elixir.load(Elixir.ElixirScript.ArgumentError); - - try { - User.throw_something(); - } catch (e) { - expect(e[Symbol.for('message')]).to.eql('argument error'); - } - }); -}); diff --git a/test/app/spec/integer.spec.js b/test/app/spec/integer.spec.js deleted file mode 100644 index 523d0aca..00000000 --- a/test/app/spec/integer.spec.js +++ /dev/null @@ -1,53 +0,0 @@ -const expect = require('chai').expect; -const Elixir = require('../build/Elixir.App'); - -describe('Integer', () => { - it('is_odd/1', () => { - const Integer = Elixir.load(Elixir.ElixirScript.Integer); - - expect(Integer.is_odd(0)).to.eq(false); - expect(Integer.is_odd(1)).to.eq(true); - expect(Integer.is_odd(2)).to.eq(false); - expect(Integer.is_odd(3)).to.eq(true); - expect(Integer.is_odd(-1)).to.eq(true); - expect(Integer.is_odd(-2)).to.eq(false); - expect(Integer.is_odd(-3)).to.eq(true); - }); - - it('is_even/1', () => { - const Integer = Elixir.load(Elixir.ElixirScript.Integer); - - expect(Integer.is_even(0)).to.eq(true); - expect(Integer.is_even(1)).to.eq(false); - expect(Integer.is_even(2)).to.eq(true); - expect(Integer.is_even(3)).to.eq(false); - expect(Integer.is_even(-1)).to.eq(false); - expect(Integer.is_even(-2)).to.eq(true); - expect(Integer.is_even(-3)).to.eq(false); - }); - - it('parse/2', () => { - const Integer = Elixir.load(Elixir.ElixirScript.Integer); - expect(Integer.parse('12').values).to.eql([12, '']); - expect(Integer.parse('012').values).to.eql([12, '']); - expect(Integer.parse('+12').values).to.eql([12, '']); - expect(Integer.parse('-12').values).to.eql([-12, '']); - expect(Integer.parse('123456789').values).to.eql([123456789, '']); - expect(Integer.parse('12.5').values).to.eql([12, '.5']); - expect(Integer.parse('7.5e-3').values).to.eql([7, '.5e-3']); - // expect(Integer.parse('12x').values).to.eql([12, 'x']); - expect(Integer.parse('++1')).to.eql(Symbol.for('error')); - expect(Integer.parse('--1')).to.eql(Symbol.for('error')); - expect(Integer.parse('+-1')).to.eql(Symbol.for('error')); - expect(Integer.parse('three')).to.eql(Symbol.for('error')); - - expect(Integer.parse('12', 10).values).to.eql([12, '']); - expect(Integer.parse('-12', 12).values).to.eql([-14, '']); - expect(Integer.parse('12345678', 9).values).to.eql([6053444, '']); - expect(Integer.parse('3.14', 4).values).to.eql([3, '.14']); - expect(Integer.parse('64eb', 16).values).to.eql([25835, '']); - // expect(Integer.parse('64eb', 10).values).to.eql([64, 'eb']); - expect(Integer.parse('10', 2).values).to.eql([2, '']); - expect(Integer.parse('++4', 10)).to.eql(Symbol.for('error')); - }); -}); diff --git a/test/app/spec/main.spec.js b/test/app/spec/main.spec.js index f60c9784..9d5ceac0 100644 --- a/test/app/spec/main.spec.js +++ b/test/app/spec/main.spec.js @@ -1,24 +1,20 @@ -const expect = require('chai').expect; +import test from 'ava'; const sinon = require('sinon'); const Elixir = require('../build/Elixir.App'); -describe('Elixir.start', function () { - it('calls the modules start function', function () { - const callback = sinon.spy(); +test('Elixir.start:calls the modules start function', t => { + const callback = sinon.spy(); - Elixir.start(Elixir.Main, callback); + Elixir.start(Elixir.Main, callback); - expect(callback).to.have.been.calledWith('started'); - }); + t.true(callback.called); }); -describe('Elixir.load', function () { - it('loads the modules exports', function () { - const main = Elixir.load(Elixir.Main); +test('Elixir.load:loads the modules exports', t => { + const main = Elixir.load(Elixir.Main); - expect(main).to.have.property('start'); - expect(main).to.have.property('hello'); - expect(main.hello()).to.eq('Hello!'); - }); + t.truthy(main.start); + t.truthy(main.hello); + t.is(main.hello(), 'Hello!'); }); diff --git a/test/app/spec/setup.spec.js b/test/app/spec/setup.spec.js deleted file mode 100644 index 3e9f4714..00000000 --- a/test/app/spec/setup.spec.js +++ /dev/null @@ -1,15 +0,0 @@ -const sinon = require('sinon'); -const chai = require('chai'); -const sinonChai = require('sinon-chai'); - -before(function() { - chai.use(sinonChai); -}); - -beforeEach(function() { - this.sandbox = sinon.sandbox.create(); -}); - -afterEach(function() { - this.sandbox.restore(); -}); diff --git a/test/app/spec/struct.spec.js b/test/app/spec/struct.spec.js deleted file mode 100644 index 765ea491..00000000 --- a/test/app/spec/struct.spec.js +++ /dev/null @@ -1,36 +0,0 @@ -const expect = require('chai').expect; -const Elixir = require('../build/Elixir.App'); - -describe('Struct', () => { - it('Create Struct', () => { - const User = Elixir.load(Elixir.User); - - let struct = User.__struct__(); - - expect(Object.getOwnPropertySymbols(struct)).to.eql([ - Symbol.for('__struct__'), - Symbol.for('first'), - Symbol.for('last'), - ]); - - expect(struct[Symbol.for('__struct__')]).to.eql(Symbol.for('Elixir.User')); - expect(struct[Symbol.for('first')]).to.eql(null); - expect(struct[Symbol.for('last')]).to.eql(null); - - struct = User.__struct__({ [Symbol.for('first')]: 'John' }); - - expect(struct[Symbol.for('first')]).to.eql('John'); - }); - - it('Protocol', () => { - const User = Elixir.load(Elixir.User); - const StringChars = Elixir.load(Elixir.ElixirScript.String.Chars); - - const struct = User.__struct__({ - [Symbol.for('first')]: 'John', - [Symbol.for('last')]: 'Doe', - }); - - expect(StringChars.to_string(struct)).to.eql('JohnDoe'); - }); -}); diff --git a/test/app/spec/tuple.spec.js b/test/app/spec/tuple.spec.js deleted file mode 100644 index c139aecd..00000000 --- a/test/app/spec/tuple.spec.js +++ /dev/null @@ -1,29 +0,0 @@ -const expect = require('chai').expect; -const Elixir = require('../build/Elixir.App'); -const Tuple = require('../../../src/javascript/lib/core').default.Tuple; - -describe('Tuple', () => { - it('duplicate/2', () => { - const TupleModule = Elixir.load(Elixir.ElixirScript.Tuple); - expect(TupleModule.duplicate(Symbol.for('foo'), 0).values).to.eql([]); - expect(TupleModule.duplicate(Symbol.for('foo'), 3).values).to.eql([Symbol.for('foo'), Symbol.for('foo'), Symbol.for('foo')]); - }); - - it('insert_at/3', () => { - const TupleModule = Elixir.load(Elixir.ElixirScript.Tuple); - const t = new Tuple(Symbol.for('bar'), Symbol.for('baz')); - expect(TupleModule.insert_at(t, 0, Symbol.for('foo')).values).to.eql([Symbol.for('foo'), Symbol.for('bar'), Symbol.for('baz')]); - }); - - it('append/2', () => { - const TupleModule = Elixir.load(Elixir.ElixirScript.Tuple); - const t = new Tuple(Symbol.for('foo'), Symbol.for('bar')); - expect(TupleModule.append(t, Symbol.for('baz')).values).to.eql([Symbol.for('foo'), Symbol.for('bar'), Symbol.for('baz')]); - }); - - it('delete_at/2', () => { - const TupleModule = Elixir.load(Elixir.ElixirScript.Tuple); - const t = new Tuple(Symbol.for('foo'), Symbol.for('bar'), Symbol.for('baz')); - expect(TupleModule.delete_at(t, 0).values).to.eql([Symbol.for('bar'), Symbol.for('baz')]); - }); -}); diff --git a/yarn.lock b/yarn.lock index ed077766..c96129c7 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2,10 +2,49 @@ # yarn lockfile v1 +"@ava/babel-plugin-throws-helper@^2.0.0": + version "2.0.0" + resolved "https://registry.yarnpkg.com/@ava/babel-plugin-throws-helper/-/babel-plugin-throws-helper-2.0.0.tgz#2fc1fe3c211a71071a4eca7b8f7af5842cd1ae7c" + +"@ava/babel-preset-stage-4@^1.0.0": + version "1.0.0" + resolved "https://registry.yarnpkg.com/@ava/babel-preset-stage-4/-/babel-preset-stage-4-1.0.0.tgz#a613b5e152f529305422546b072d47facfb26291" + dependencies: + babel-plugin-check-es2015-constants "^6.8.0" + babel-plugin-syntax-trailing-function-commas "^6.20.0" + babel-plugin-transform-async-to-generator "^6.16.0" + babel-plugin-transform-es2015-destructuring "^6.19.0" + babel-plugin-transform-es2015-function-name "^6.9.0" + babel-plugin-transform-es2015-modules-commonjs "^6.18.0" + babel-plugin-transform-es2015-parameters "^6.21.0" + babel-plugin-transform-es2015-spread "^6.8.0" + babel-plugin-transform-es2015-sticky-regex "^6.8.0" + babel-plugin-transform-es2015-unicode-regex "^6.11.0" + babel-plugin-transform-exponentiation-operator "^6.8.0" + package-hash "^1.2.0" + +"@ava/babel-preset-transform-test-files@^3.0.0": + version "3.0.0" + resolved "https://registry.yarnpkg.com/@ava/babel-preset-transform-test-files/-/babel-preset-transform-test-files-3.0.0.tgz#cded1196a8d8d9381a509240ab92e91a5ec069f7" + dependencies: + "@ava/babel-plugin-throws-helper" "^2.0.0" + babel-plugin-espower "^2.3.2" + +"@ava/pretty-format@^1.1.0": + version "1.1.0" + resolved "https://registry.yarnpkg.com/@ava/pretty-format/-/pretty-format-1.1.0.tgz#d0a57d25eb9aeab9643bdd1a030642b91c123e28" + dependencies: + ansi-styles "^2.2.1" + esutils "^2.0.2" + "@comandeer/babel-plugin-banner@^1.0.0": version "1.0.0" resolved "https://registry.yarnpkg.com/@comandeer/babel-plugin-banner/-/babel-plugin-banner-1.0.0.tgz#40bcce0bbee084b5b02545a33635d053c248356f" +abbrev@1: + version "1.1.0" + resolved "https://registry.yarnpkg.com/abbrev/-/abbrev-1.1.0.tgz#d0554c2256636e2f56e7c2e5ad183f859428d81f" + acorn-jsx@^3.0.0: version "3.0.1" resolved "https://registry.yarnpkg.com/acorn-jsx/-/acorn-jsx-3.0.1.tgz#afdf9488fb1ecefc8348f6fb22f464e32a58b36b" @@ -24,13 +63,31 @@ ajv-keywords@^1.0.0: version "1.5.1" resolved "https://registry.yarnpkg.com/ajv-keywords/-/ajv-keywords-1.5.1.tgz#314dd0a4b3368fad3dfcdc54ede6171b886daf3c" -ajv@^4.7.0: +ajv@^4.7.0, ajv@^4.9.1: version "4.11.5" resolved "https://registry.yarnpkg.com/ajv/-/ajv-4.11.5.tgz#b6ee74657b993a01dce44b7944d56f485828d5bd" dependencies: co "^4.6.0" json-stable-stringify "^1.0.1" +align-text@^0.1.1, align-text@^0.1.3: + version "0.1.4" + resolved "https://registry.yarnpkg.com/align-text/-/align-text-0.1.4.tgz#0cd90a561093f35d0a99256c22b7069433fad117" + dependencies: + kind-of "^3.0.2" + longest "^1.0.1" + repeat-string "^1.5.2" + +amdefine@>=0.0.4: + version "1.0.1" + resolved "https://registry.yarnpkg.com/amdefine/-/amdefine-1.0.1.tgz#4a5282ac164729e93619bcfd3ad151f817ce91f5" + +ansi-align@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/ansi-align/-/ansi-align-2.0.0.tgz#c36aeccba563b89ceb556f3690f0b1d9e3547f7f" + dependencies: + string-width "^2.0.0" + ansi-escapes@^1.1.0: version "1.4.0" resolved "https://registry.yarnpkg.com/ansi-escapes/-/ansi-escapes-1.4.0.tgz#d3a8a83b319aa67793662b13e761c7911422306e" @@ -43,29 +100,218 @@ ansi-styles@^2.2.1: version "2.2.1" resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-2.2.1.tgz#b432dd3358b634cf75e1e4664368240533c1ddbe" +ansi-styles@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-3.0.0.tgz#5404e93a544c4fec7f048262977bebfe3155e0c1" + dependencies: + color-convert "^1.0.0" + +ansi-styles@~1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-1.0.0.tgz#cb102df1c56f5123eab8b67cd7b98027a0279178" + +anymatch@^1.3.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/anymatch/-/anymatch-1.3.0.tgz#a3e52fa39168c825ff57b0248126ce5a8ff95507" + dependencies: + arrify "^1.0.0" + micromatch "^2.1.5" + +append-transform@^0.4.0: + version "0.4.0" + resolved "https://registry.yarnpkg.com/append-transform/-/append-transform-0.4.0.tgz#d76ebf8ca94d276e247a36bad44a4b74ab611991" + dependencies: + default-require-extensions "^1.0.0" + +aproba@^1.0.3: + version "1.1.1" + resolved "https://registry.yarnpkg.com/aproba/-/aproba-1.1.1.tgz#95d3600f07710aa0e9298c726ad5ecf2eacbabab" + +archy@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/archy/-/archy-1.0.0.tgz#f9c8c13757cc1dd7bc379ac77b2c62a5c2868c40" + +are-we-there-yet@~1.1.2: + version "1.1.4" + resolved "https://registry.yarnpkg.com/are-we-there-yet/-/are-we-there-yet-1.1.4.tgz#bb5dca382bb94f05e15194373d16fd3ba1ca110d" + dependencies: + delegates "^1.0.0" + readable-stream "^2.0.6" + argparse@^1.0.7: version "1.0.9" resolved "https://registry.yarnpkg.com/argparse/-/argparse-1.0.9.tgz#73d83bc263f86e97f8cc4f6bae1b0e90a7d22c86" dependencies: sprintf-js "~1.0.2" +arr-diff@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/arr-diff/-/arr-diff-2.0.0.tgz#8f3b827f955a8bd669697e4a4256ac3ceae356cf" + dependencies: + arr-flatten "^1.0.1" + +arr-exclude@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/arr-exclude/-/arr-exclude-1.0.0.tgz#dfc7c2e552a270723ccda04cf3128c8cbfe5c631" + +arr-flatten@^1.0.1: + version "1.0.3" + resolved "https://registry.yarnpkg.com/arr-flatten/-/arr-flatten-1.0.3.tgz#a274ed85ac08849b6bd7847c4580745dc51adfb1" + +array-differ@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/array-differ/-/array-differ-1.0.0.tgz#eff52e3758249d33be402b8bb8e564bb2b5d4031" + +array-find-index@^1.0.1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/array-find-index/-/array-find-index-1.0.2.tgz#df010aa1287e164bbda6f9723b0a96a1ec4187a1" + array-union@^1.0.1: version "1.0.2" resolved "https://registry.yarnpkg.com/array-union/-/array-union-1.0.2.tgz#9a34410e4f4e3da23dea375be5be70f24778ec39" dependencies: array-uniq "^1.0.1" -array-uniq@^1.0.1: +array-uniq@^1.0.1, array-uniq@^1.0.2: version "1.0.3" resolved "https://registry.yarnpkg.com/array-uniq/-/array-uniq-1.0.3.tgz#af6ac877a25cc7f74e058894753858dfdb24fdb6" -arrify@^1.0.0: +array-unique@^0.2.1: + version "0.2.1" + resolved "https://registry.yarnpkg.com/array-unique/-/array-unique-0.2.1.tgz#a1d97ccafcbc2625cc70fadceb36a50c58b01a53" + +arrify@^1.0.0, arrify@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/arrify/-/arrify-1.0.1.tgz#898508da2226f380df904728456849c1501a4b0d" -assertion-error@^1.0.1: - version "1.0.2" - resolved "https://registry.yarnpkg.com/assertion-error/-/assertion-error-1.0.2.tgz#13ca515d86206da0bac66e834dd397d87581094c" +asn1@~0.2.3: + version "0.2.3" + resolved "https://registry.yarnpkg.com/asn1/-/asn1-0.2.3.tgz#dac8787713c9966849fc8180777ebe9c1ddf3b86" + +assert-plus@1.0.0, assert-plus@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/assert-plus/-/assert-plus-1.0.0.tgz#f12e0f3c5d77b0b1cdd9146942e4e96c1e4dd525" + +assert-plus@^0.2.0: + version "0.2.0" + resolved "https://registry.yarnpkg.com/assert-plus/-/assert-plus-0.2.0.tgz#d74e1b87e7affc0db8aadb7021f3fe48101ab234" + +async-each@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/async-each/-/async-each-1.0.1.tgz#19d386a1d9edc6e7c1c85d388aedbcc56d33602d" + +async@^1.4.0: + version "1.5.2" + resolved "https://registry.yarnpkg.com/async/-/async-1.5.2.tgz#ec6a61ae56480c0c3cb241c95618e20892f9672a" + +asynckit@^0.4.0: + version "0.4.0" + resolved "https://registry.yarnpkg.com/asynckit/-/asynckit-0.4.0.tgz#c79ed97f7f34cb8f2ba1bc9790bcc366474b4b79" + +auto-bind@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/auto-bind/-/auto-bind-1.1.0.tgz#93b864dc7ee01a326281775d5c75ca0a751e5961" + +ava-init@^0.2.0: + version "0.2.0" + resolved "https://registry.yarnpkg.com/ava-init/-/ava-init-0.2.0.tgz#9304c8b4c357d66e3dfdae1fbff47b1199d5c55d" + dependencies: + arr-exclude "^1.0.0" + execa "^0.5.0" + has-yarn "^1.0.0" + read-pkg-up "^2.0.0" + write-pkg "^2.0.0" + +ava@^0.19.1: + version "0.19.1" + resolved "https://registry.yarnpkg.com/ava/-/ava-0.19.1.tgz#43dd82435ad19b3980ffca2488f05daab940b273" + dependencies: + "@ava/babel-preset-stage-4" "^1.0.0" + "@ava/babel-preset-transform-test-files" "^3.0.0" + "@ava/pretty-format" "^1.1.0" + arr-flatten "^1.0.1" + array-union "^1.0.1" + array-uniq "^1.0.2" + arrify "^1.0.0" + auto-bind "^1.1.0" + ava-init "^0.2.0" + babel-code-frame "^6.16.0" + babel-core "^6.17.0" + bluebird "^3.0.0" + caching-transform "^1.0.0" + chalk "^1.0.0" + chokidar "^1.4.2" + clean-stack "^1.1.1" + clean-yaml-object "^0.1.0" + cli-cursor "^2.1.0" + cli-spinners "^1.0.0" + cli-truncate "^1.0.0" + co-with-promise "^4.6.0" + code-excerpt "^2.1.0" + common-path-prefix "^1.0.0" + convert-source-map "^1.2.0" + core-assert "^0.2.0" + currently-unhandled "^0.4.1" + debug "^2.2.0" + diff "^3.0.1" + diff-match-patch "^1.0.0" + dot-prop "^4.1.0" + empower-core "^0.6.1" + equal-length "^1.0.0" + figures "^2.0.0" + find-cache-dir "^0.1.1" + fn-name "^2.0.0" + get-port "^3.0.0" + globby "^6.0.0" + has-flag "^2.0.0" + hullabaloo-config-manager "^1.0.0" + ignore-by-default "^1.0.0" + indent-string "^3.0.0" + is-ci "^1.0.7" + is-generator-fn "^1.0.0" + is-obj "^1.0.0" + is-observable "^0.2.0" + is-promise "^2.1.0" + jest-diff "19.0.0" + jest-snapshot "19.0.2" + js-yaml "^3.8.2" + last-line-stream "^1.0.0" + lodash.debounce "^4.0.3" + lodash.difference "^4.3.0" + lodash.flatten "^4.2.0" + lodash.isequal "^4.5.0" + loud-rejection "^1.2.0" + matcher "^0.1.1" + md5-hex "^2.0.0" + meow "^3.7.0" + mkdirp "^0.5.1" + ms "^0.7.1" + multimatch "^2.1.0" + observable-to-promise "^0.5.0" + option-chain "^0.1.0" + package-hash "^2.0.0" + pkg-conf "^2.0.0" + plur "^2.0.0" + pretty-ms "^2.0.0" + require-precompiled "^0.1.0" + resolve-cwd "^1.0.0" + slash "^1.0.0" + source-map-support "^0.4.0" + stack-utils "^1.0.0" + strip-ansi "^3.0.1" + strip-bom-buf "^1.0.0" + supports-color "^3.2.3" + time-require "^0.1.2" + unique-temp-dir "^1.0.0" + update-notifier "^2.1.0" + +aws-sign2@~0.6.0: + version "0.6.0" + resolved "https://registry.yarnpkg.com/aws-sign2/-/aws-sign2-0.6.0.tgz#14342dd38dbcc94d0e5b87d763cd63612c0e794f" + +aws4@^1.2.1: + version "1.6.0" + resolved "https://registry.yarnpkg.com/aws4/-/aws4-1.6.0.tgz#83ef5ca860b2b32e4a0deedee8c771b9db57471e" babel-code-frame@^6.16.0, babel-code-frame@^6.22.0: version "6.22.0" @@ -75,7 +321,7 @@ babel-code-frame@^6.16.0, babel-code-frame@^6.22.0: esutils "^2.0.2" js-tokens "^3.0.0" -babel-core@6, babel-core@^6.21.0, babel-core@^6.24.0: +babel-core@6, babel-core@^6.17.0, babel-core@^6.21.0, babel-core@^6.24.0: version "6.24.0" resolved "https://registry.yarnpkg.com/babel-core/-/babel-core-6.24.0.tgz#8f36a0a77f5c155aed6f920b844d23ba56742a02" dependencies: @@ -99,7 +345,7 @@ babel-core@6, babel-core@^6.21.0, babel-core@^6.24.0: slash "^1.0.0" source-map "^0.5.0" -babel-generator@^6.24.0: +babel-generator@^6.1.0, babel-generator@^6.18.0, babel-generator@^6.24.0: version "6.24.0" resolved "https://registry.yarnpkg.com/babel-generator/-/babel-generator-6.24.0.tgz#eba270a8cc4ce6e09a61be43465d7c62c1f87c56" dependencies: @@ -247,12 +493,24 @@ babel-messages@^6.23.0: dependencies: babel-runtime "^6.22.0" -babel-plugin-check-es2015-constants@^6.22.0: +babel-plugin-check-es2015-constants@^6.22.0, babel-plugin-check-es2015-constants@^6.8.0: version "6.22.0" resolved "https://registry.yarnpkg.com/babel-plugin-check-es2015-constants/-/babel-plugin-check-es2015-constants-6.22.0.tgz#35157b101426fd2ffd3da3f75c7d1e91835bbf8a" dependencies: babel-runtime "^6.22.0" +babel-plugin-espower@^2.3.2: + version "2.3.2" + resolved "https://registry.yarnpkg.com/babel-plugin-espower/-/babel-plugin-espower-2.3.2.tgz#5516b8fcdb26c9f0e1d8160749f6e4c65e71271e" + dependencies: + babel-generator "^6.1.0" + babylon "^6.1.0" + call-matcher "^1.0.0" + core-js "^2.0.0" + espower-location-detector "^1.0.0" + espurify "^1.6.0" + estraverse "^4.1.1" + babel-plugin-minify-builtins@^0.0.2: version "0.0.2" resolved "https://registry.yarnpkg.com/babel-plugin-minify-builtins/-/babel-plugin-minify-builtins-0.0.2.tgz#f3be6121763c0c518d5ef82067cef4b615c9498c" @@ -326,11 +584,11 @@ babel-plugin-syntax-exponentiation-operator@^6.8.0: version "6.13.0" resolved "https://registry.yarnpkg.com/babel-plugin-syntax-exponentiation-operator/-/babel-plugin-syntax-exponentiation-operator-6.13.0.tgz#9ee7e8337290da95288201a6a57f4170317830de" -babel-plugin-syntax-trailing-function-commas@^6.22.0: +babel-plugin-syntax-trailing-function-commas@^6.20.0, babel-plugin-syntax-trailing-function-commas@^6.22.0: version "6.22.0" resolved "https://registry.yarnpkg.com/babel-plugin-syntax-trailing-function-commas/-/babel-plugin-syntax-trailing-function-commas-6.22.0.tgz#ba0360937f8d06e40180a43fe0d5616fff532cf3" -babel-plugin-transform-async-to-generator@^6.22.0: +babel-plugin-transform-async-to-generator@^6.16.0, babel-plugin-transform-async-to-generator@^6.22.0: version "6.22.0" resolved "https://registry.yarnpkg.com/babel-plugin-transform-async-to-generator/-/babel-plugin-transform-async-to-generator-6.22.0.tgz#194b6938ec195ad36efc4c33a971acf00d8cd35e" dependencies: @@ -381,7 +639,7 @@ babel-plugin-transform-es2015-computed-properties@^6.22.0: babel-runtime "^6.22.0" babel-template "^6.22.0" -babel-plugin-transform-es2015-destructuring@^6.23.0: +babel-plugin-transform-es2015-destructuring@^6.19.0, babel-plugin-transform-es2015-destructuring@^6.23.0: version "6.23.0" resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-destructuring/-/babel-plugin-transform-es2015-destructuring-6.23.0.tgz#997bb1f1ab967f682d2b0876fe358d60e765c56d" dependencies: @@ -400,7 +658,7 @@ babel-plugin-transform-es2015-for-of@^6.23.0: dependencies: babel-runtime "^6.22.0" -babel-plugin-transform-es2015-function-name@^6.22.0: +babel-plugin-transform-es2015-function-name@^6.22.0, babel-plugin-transform-es2015-function-name@^6.9.0: version "6.22.0" resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-function-name/-/babel-plugin-transform-es2015-function-name-6.22.0.tgz#f5fcc8b09093f9a23c76ac3d9e392c3ec4b77104" dependencies: @@ -422,7 +680,7 @@ babel-plugin-transform-es2015-modules-amd@^6.22.0, babel-plugin-transform-es2015 babel-runtime "^6.22.0" babel-template "^6.22.0" -babel-plugin-transform-es2015-modules-commonjs@^6.23.0, babel-plugin-transform-es2015-modules-commonjs@^6.24.0: +babel-plugin-transform-es2015-modules-commonjs@^6.18.0, babel-plugin-transform-es2015-modules-commonjs@^6.23.0, babel-plugin-transform-es2015-modules-commonjs@^6.24.0: version "6.24.0" resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-modules-commonjs/-/babel-plugin-transform-es2015-modules-commonjs-6.24.0.tgz#e921aefb72c2cc26cb03d107626156413222134f" dependencies: @@ -454,7 +712,7 @@ babel-plugin-transform-es2015-object-super@^6.22.0: babel-helper-replace-supers "^6.22.0" babel-runtime "^6.22.0" -babel-plugin-transform-es2015-parameters@^6.23.0: +babel-plugin-transform-es2015-parameters@^6.21.0, babel-plugin-transform-es2015-parameters@^6.23.0: version "6.23.0" resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-parameters/-/babel-plugin-transform-es2015-parameters-6.23.0.tgz#3a2aabb70c8af945d5ce386f1a4250625a83ae3b" dependencies: @@ -472,13 +730,13 @@ babel-plugin-transform-es2015-shorthand-properties@^6.22.0: babel-runtime "^6.22.0" babel-types "^6.22.0" -babel-plugin-transform-es2015-spread@^6.22.0: +babel-plugin-transform-es2015-spread@^6.22.0, babel-plugin-transform-es2015-spread@^6.8.0: version "6.22.0" resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-spread/-/babel-plugin-transform-es2015-spread-6.22.0.tgz#d6d68a99f89aedc4536c81a542e8dd9f1746f8d1" dependencies: babel-runtime "^6.22.0" -babel-plugin-transform-es2015-sticky-regex@^6.22.0: +babel-plugin-transform-es2015-sticky-regex@^6.22.0, babel-plugin-transform-es2015-sticky-regex@^6.8.0: version "6.22.0" resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-sticky-regex/-/babel-plugin-transform-es2015-sticky-regex-6.22.0.tgz#ab316829e866ee3f4b9eb96939757d19a5bc4593" dependencies: @@ -498,7 +756,7 @@ babel-plugin-transform-es2015-typeof-symbol@^6.23.0: dependencies: babel-runtime "^6.22.0" -babel-plugin-transform-es2015-unicode-regex@^6.22.0: +babel-plugin-transform-es2015-unicode-regex@^6.11.0, babel-plugin-transform-es2015-unicode-regex@^6.22.0: version "6.22.0" resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-unicode-regex/-/babel-plugin-transform-es2015-unicode-regex-6.22.0.tgz#8d9cc27e7ee1decfe65454fb986452a04a613d20" dependencies: @@ -506,7 +764,7 @@ babel-plugin-transform-es2015-unicode-regex@^6.22.0: babel-runtime "^6.22.0" regexpu-core "^2.0.0" -babel-plugin-transform-exponentiation-operator@^6.22.0: +babel-plugin-transform-exponentiation-operator@^6.22.0, babel-plugin-transform-exponentiation-operator@^6.8.0: version "6.22.0" resolved "https://registry.yarnpkg.com/babel-plugin-transform-exponentiation-operator/-/babel-plugin-transform-exponentiation-operator-6.22.0.tgz#d57c8335281918e54ef053118ce6eb108468084d" dependencies: @@ -656,7 +914,7 @@ babel-runtime@^6.0.0, babel-runtime@^6.18.0, babel-runtime@^6.22.0: core-js "^2.4.0" regenerator-runtime "^0.10.0" -babel-template@^6.22.0, babel-template@^6.23.0: +babel-template@^6.16.0, babel-template@^6.22.0, babel-template@^6.23.0: version "6.23.0" resolved "https://registry.yarnpkg.com/babel-template/-/babel-template-6.23.0.tgz#04d4f270adbb3aa704a8143ae26faa529238e638" dependencies: @@ -666,7 +924,7 @@ babel-template@^6.22.0, babel-template@^6.23.0: babylon "^6.11.0" lodash "^4.2.0" -babel-traverse@^6.22.0, babel-traverse@^6.23.0, babel-traverse@^6.23.1: +babel-traverse@^6.18.0, babel-traverse@^6.22.0, babel-traverse@^6.23.0, babel-traverse@^6.23.1: version "6.23.1" resolved "https://registry.yarnpkg.com/babel-traverse/-/babel-traverse-6.23.1.tgz#d3cb59010ecd06a97d81310065f966b699e14f48" dependencies: @@ -680,7 +938,7 @@ babel-traverse@^6.22.0, babel-traverse@^6.23.0, babel-traverse@^6.23.1: invariant "^2.2.0" lodash "^4.2.0" -babel-types@^6.19.0, babel-types@^6.22.0, babel-types@^6.23.0: +babel-types@^6.18.0, babel-types@^6.19.0, babel-types@^6.22.0, babel-types@^6.23.0: version "6.23.0" resolved "https://registry.yarnpkg.com/babel-types/-/babel-types-6.23.0.tgz#bb17179d7538bad38cd0c9e115d340f77e7e9acf" dependencies: @@ -689,7 +947,7 @@ babel-types@^6.19.0, babel-types@^6.22.0, babel-types@^6.23.0: lodash "^4.2.0" to-fast-properties "^1.0.1" -babylon@^6.11.0, babylon@^6.15.0: +babylon@^6.1.0, babylon@^6.11.0, babylon@^6.13.0, babylon@^6.15.0: version "6.16.1" resolved "https://registry.yarnpkg.com/babylon/-/babylon-6.16.1.tgz#30c5a22f481978a9e7f8cdfdf496b11d94b404d3" @@ -697,6 +955,44 @@ balanced-match@^0.4.1: version "0.4.2" resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-0.4.2.tgz#cb3f3e3c732dc0f01ee70b403f302e61d7709838" +bcrypt-pbkdf@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.1.tgz#63bc5dcb61331b92bc05fd528953c33462a06f8d" + dependencies: + tweetnacl "^0.14.3" + +binary-extensions@^1.0.0: + version "1.8.0" + resolved "https://registry.yarnpkg.com/binary-extensions/-/binary-extensions-1.8.0.tgz#48ec8d16df4377eae5fa5884682480af4d95c774" + +block-stream@*: + version "0.0.9" + resolved "https://registry.yarnpkg.com/block-stream/-/block-stream-0.0.9.tgz#13ebfe778a03205cfe03751481ebb4b3300c126a" + dependencies: + inherits "~2.0.0" + +bluebird@^3.0.0: + version "3.5.0" + resolved "https://registry.yarnpkg.com/bluebird/-/bluebird-3.5.0.tgz#791420d7f551eea2897453a8a77653f96606d67c" + +boom@2.x.x: + version "2.10.1" + resolved "https://registry.yarnpkg.com/boom/-/boom-2.10.1.tgz#39c8918ceff5799f83f9492a848f625add0c766f" + dependencies: + hoek "2.x.x" + +boxen@^1.0.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/boxen/-/boxen-1.1.0.tgz#b1b69dd522305e807a99deee777dbd6e5167b102" + dependencies: + ansi-align "^2.0.0" + camelcase "^4.0.0" + chalk "^1.1.1" + cli-boxes "^1.0.0" + string-width "^2.0.0" + term-size "^0.1.0" + widest-line "^1.0.0" + brace-expansion@^1.0.0: version "1.1.6" resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.6.tgz#7197d7eaa9b87e648390ea61fc66c84427420df9" @@ -704,16 +1000,20 @@ brace-expansion@^1.0.0: balanced-match "^0.4.1" concat-map "0.0.1" +braces@^1.8.2: + version "1.8.5" + resolved "https://registry.yarnpkg.com/braces/-/braces-1.8.5.tgz#ba77962e12dff969d6b76711e914b737857bf6a7" + dependencies: + expand-range "^1.8.1" + preserve "^0.2.0" + repeat-element "^1.1.2" + browser-resolve@^1.11.0: version "1.11.2" resolved "https://registry.yarnpkg.com/browser-resolve/-/browser-resolve-1.11.2.tgz#8ff09b0a2c421718a1051c260b32e48f442938ce" dependencies: resolve "1.1.7" -browser-stdout@1.3.0: - version "1.3.0" - resolved "https://registry.yarnpkg.com/browser-stdout/-/browser-stdout-1.3.0.tgz#f351d32969d32fa5d7a5567154263d928ae3bd1f" - browserslist@^1.4.0: version "1.7.7" resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-1.7.7.tgz#0bd76704258be829b2398bb50e4b62d1a166b0b9" @@ -721,14 +1021,39 @@ browserslist@^1.4.0: caniuse-db "^1.0.30000639" electron-to-chromium "^1.2.7" +buf-compare@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/buf-compare/-/buf-compare-1.0.1.tgz#fef28da8b8113a0a0db4430b0b6467b69730b34a" + buffer-shims@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/buffer-shims/-/buffer-shims-1.0.0.tgz#9978ce317388c649ad8793028c3477ef044a8b51" -builtin-modules@^1.1.0, builtin-modules@^1.1.1: +builtin-modules@^1.0.0, builtin-modules@^1.1.0, builtin-modules@^1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/builtin-modules/-/builtin-modules-1.1.1.tgz#270f076c5a72c02f5b65a47df94c5fe3a278892f" +caching-transform@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/caching-transform/-/caching-transform-1.0.1.tgz#6dbdb2f20f8d8fbce79f3e94e9d1742dcdf5c0a1" + dependencies: + md5-hex "^1.2.0" + mkdirp "^0.5.1" + write-file-atomic "^1.1.4" + +call-matcher@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/call-matcher/-/call-matcher-1.0.1.tgz#5134d077984f712a54dad3cbf62de28dce416ca8" + dependencies: + core-js "^2.0.0" + deep-equal "^1.0.0" + espurify "^1.6.0" + estraverse "^4.0.0" + +call-signature@0.0.2: + version "0.0.2" + resolved "https://registry.yarnpkg.com/call-signature/-/call-signature-0.0.2.tgz#a84abc825a55ef4cb2b028bd74e205a65b9a4996" + caller-path@^0.1.0: version "0.1.0" resolved "https://registry.yarnpkg.com/caller-path/-/caller-path-0.1.0.tgz#94085ef63581ecd3daa92444a8fe94e82577751f" @@ -739,17 +1064,55 @@ callsites@^0.2.0: version "0.2.0" resolved "https://registry.yarnpkg.com/callsites/-/callsites-0.2.0.tgz#afab96262910a7f33c19a5775825c69f34e350ca" +camelcase-keys@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/camelcase-keys/-/camelcase-keys-2.1.0.tgz#308beeaffdf28119051efa1d932213c91b8f92e7" + dependencies: + camelcase "^2.0.0" + map-obj "^1.0.0" + +camelcase@^1.0.2: + version "1.2.1" + resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-1.2.1.tgz#9bb5304d2e0b56698b2c758b08a3eaa9daa58a39" + +camelcase@^2.0.0: + version "2.1.1" + resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-2.1.1.tgz#7c1d16d679a1bbe59ca02cacecfb011e201f5a1f" + +camelcase@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-3.0.0.tgz#32fc4b9fcdaf845fcdf7e73bb97cac2261f0ab0a" + +camelcase@^4.0.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-4.1.0.tgz#d545635be1e33c542649c69173e5de6acfae34dd" + caniuse-db@^1.0.30000639: version "1.0.30000646" resolved "https://registry.yarnpkg.com/caniuse-db/-/caniuse-db-1.0.30000646.tgz#c724b90d61df24286e015fc528d062073c00def4" -chai@^3.5.0: - version "3.5.0" - resolved "https://registry.yarnpkg.com/chai/-/chai-3.5.0.tgz#4d02637b067fe958bdbfdd3a40ec56fef7373247" +capture-stack-trace@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/capture-stack-trace/-/capture-stack-trace-1.0.0.tgz#4a6fa07399c26bba47f0b2496b4d0fb408c5550d" + +caseless@~0.12.0: + version "0.12.0" + resolved "https://registry.yarnpkg.com/caseless/-/caseless-0.12.0.tgz#1b681c21ff84033c826543090689420d187151dc" + +center-align@^0.1.1: + version "0.1.3" + resolved "https://registry.yarnpkg.com/center-align/-/center-align-0.1.3.tgz#aa0d32629b6ee972200411cbd4461c907bc2b7ad" + dependencies: + align-text "^0.1.3" + lazy-cache "^1.0.3" + +chalk@^0.4.0: + version "0.4.0" + resolved "https://registry.yarnpkg.com/chalk/-/chalk-0.4.0.tgz#5199a3ddcd0c1efe23bc08c1b027b06176e0c64f" dependencies: - assertion-error "^1.0.1" - deep-eql "^0.1.3" - type-detect "^1.0.0" + ansi-styles "~1.0.0" + has-color "~0.1.0" + strip-ansi "~0.1.0" chalk@^1.0.0, chalk@^1.1.0, chalk@^1.1.1, chalk@^1.1.3: version "1.1.3" @@ -761,33 +1124,127 @@ chalk@^1.0.0, chalk@^1.1.0, chalk@^1.1.1, chalk@^1.1.3: strip-ansi "^3.0.0" supports-color "^2.0.0" +chokidar@^1.4.2: + version "1.7.0" + resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-1.7.0.tgz#798e689778151c8076b4b360e5edd28cda2bb468" + dependencies: + anymatch "^1.3.0" + async-each "^1.0.0" + glob-parent "^2.0.0" + inherits "^2.0.1" + is-binary-path "^1.0.0" + is-glob "^2.0.0" + path-is-absolute "^1.0.0" + readdirp "^2.0.0" + optionalDependencies: + fsevents "^1.0.0" + +ci-info@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/ci-info/-/ci-info-1.0.0.tgz#dc5285f2b4e251821683681c381c3388f46ec534" + circular-json@^0.3.1: version "0.3.1" resolved "https://registry.yarnpkg.com/circular-json/-/circular-json-0.3.1.tgz#be8b36aefccde8b3ca7aa2d6afc07a37242c0d2d" +clean-stack@^1.1.1: + version "1.3.0" + resolved "https://registry.yarnpkg.com/clean-stack/-/clean-stack-1.3.0.tgz#9e821501ae979986c46b1d66d2d432db2fd4ae31" + +clean-yaml-object@^0.1.0: + version "0.1.0" + resolved "https://registry.yarnpkg.com/clean-yaml-object/-/clean-yaml-object-0.1.0.tgz#63fb110dc2ce1a84dc21f6d9334876d010ae8b68" + +cli-boxes@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/cli-boxes/-/cli-boxes-1.0.0.tgz#4fa917c3e59c94a004cd61f8ee509da651687143" + cli-cursor@^1.0.1: version "1.0.2" resolved "https://registry.yarnpkg.com/cli-cursor/-/cli-cursor-1.0.2.tgz#64da3f7d56a54412e59794bd62dc35295e8f2987" dependencies: restore-cursor "^1.0.1" +cli-cursor@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/cli-cursor/-/cli-cursor-2.1.0.tgz#b35dac376479facc3e94747d41d0d0f5238ffcb5" + dependencies: + restore-cursor "^2.0.0" + +cli-spinners@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/cli-spinners/-/cli-spinners-1.0.0.tgz#ef987ed3d48391ac3dab9180b406a742180d6e6a" + +cli-truncate@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/cli-truncate/-/cli-truncate-1.0.0.tgz#21eb91f47b3f6560f004db77a769b4668d9c5518" + dependencies: + slice-ansi "0.0.4" + string-width "^2.0.0" + cli-width@^2.0.0: version "2.1.0" resolved "https://registry.yarnpkg.com/cli-width/-/cli-width-2.1.0.tgz#b234ca209b29ef66fc518d9b98d5847b00edf00a" +cliui@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/cliui/-/cliui-2.1.0.tgz#4b475760ff80264c762c3a1719032e91c7fea0d1" + dependencies: + center-align "^0.1.1" + right-align "^0.1.1" + wordwrap "0.0.2" + +cliui@^3.2.0: + version "3.2.0" + resolved "https://registry.yarnpkg.com/cliui/-/cliui-3.2.0.tgz#120601537a916d29940f934da3b48d585a39213d" + dependencies: + string-width "^1.0.1" + strip-ansi "^3.0.1" + wrap-ansi "^2.0.0" + +co-with-promise@^4.6.0: + version "4.6.0" + resolved "https://registry.yarnpkg.com/co-with-promise/-/co-with-promise-4.6.0.tgz#413e7db6f5893a60b942cf492c4bec93db415ab7" + dependencies: + pinkie-promise "^1.0.0" + co@^4.6.0: version "4.6.0" resolved "https://registry.yarnpkg.com/co/-/co-4.6.0.tgz#6ea6bdf3d853ae54ccb8e47bfa0bf3f9031fb184" +code-excerpt@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/code-excerpt/-/code-excerpt-2.1.0.tgz#5dcc081e88f4a7e3b554e9e35d7ef232d47f8147" + dependencies: + convert-to-spaces "^1.0.1" + code-point-at@^1.0.0: version "1.1.0" resolved "https://registry.yarnpkg.com/code-point-at/-/code-point-at-1.1.0.tgz#0d070b4d043a5bea33a2f1a40e2edb3d9a4ccf77" -commander@2.9.0: - version "2.9.0" - resolved "https://registry.yarnpkg.com/commander/-/commander-2.9.0.tgz#9c99094176e12240cb22d6c5146098400fe0f7d4" +color-convert@^1.0.0: + version "1.9.0" + resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-1.9.0.tgz#1accf97dd739b983bf994d56fec8f95853641b7a" + dependencies: + color-name "^1.1.1" + +color-name@^1.1.1: + version "1.1.2" + resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.2.tgz#5c8ab72b64bd2215d617ae9559ebb148475cf98d" + +combined-stream@^1.0.5, combined-stream@~1.0.5: + version "1.0.5" + resolved "https://registry.yarnpkg.com/combined-stream/-/combined-stream-1.0.5.tgz#938370a57b4a51dea2c77c15d5c5fdf895164009" dependencies: - graceful-readlink ">= 1.0.0" + delayed-stream "~1.0.0" + +common-path-prefix@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/common-path-prefix/-/common-path-prefix-1.0.0.tgz#cd52f6f0712e0baab97d6f9732874f22f47752c0" + +commondir@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/commondir/-/commondir-1.0.1.tgz#ddd800da0c66127393cca5950ea968a3aaf1253b" concat-map@0.0.1: version "0.0.1" @@ -801,15 +1258,41 @@ concat-stream@^1.5.2: readable-stream "^2.2.2" typedarray "^0.0.6" +configstore@^3.0.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/configstore/-/configstore-3.1.0.tgz#45df907073e26dfa1cf4b2d52f5b60545eaa11d1" + dependencies: + dot-prop "^4.1.0" + graceful-fs "^4.1.2" + make-dir "^1.0.0" + unique-string "^1.0.0" + write-file-atomic "^2.0.0" + xdg-basedir "^3.0.0" + +console-control-strings@^1.0.0, console-control-strings@~1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/console-control-strings/-/console-control-strings-1.1.0.tgz#3d7cf4464db6446ea644bf4b39507f9851008e8e" + contains-path@^0.1.0: version "0.1.0" resolved "https://registry.yarnpkg.com/contains-path/-/contains-path-0.1.0.tgz#fe8cf184ff6670b6baef01a9d4861a5cbec4120a" -convert-source-map@^1.1.0: +convert-source-map@^1.1.0, convert-source-map@^1.2.0, convert-source-map@^1.3.0: version "1.5.0" resolved "https://registry.yarnpkg.com/convert-source-map/-/convert-source-map-1.5.0.tgz#9acd70851c6d5dfdd93d9282e5edf94a03ff46b5" -core-js@^2.4.0: +convert-to-spaces@^1.0.1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/convert-to-spaces/-/convert-to-spaces-1.0.2.tgz#7e3e48bbe6d997b1417ddca2868204b4d3d85715" + +core-assert@^0.2.0: + version "0.2.1" + resolved "https://registry.yarnpkg.com/core-assert/-/core-assert-0.2.1.tgz#f85e2cf9bfed28f773cc8b3fa5c5b69bdc02fe3f" + dependencies: + buf-compare "^1.0.0" + is-error "^2.2.0" + +core-js@^2.0.0, core-js@^2.4.0: version "2.4.1" resolved "https://registry.yarnpkg.com/core-js/-/core-js-2.4.1.tgz#4de911e667b0eae9124e34254b53aea6fc618d3e" @@ -817,34 +1300,96 @@ core-util-is@~1.0.0: version "1.0.2" resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.2.tgz#b5fd54220aa2bc5ab57aab7140c940754503c1a7" +create-error-class@^3.0.0: + version "3.0.2" + resolved "https://registry.yarnpkg.com/create-error-class/-/create-error-class-3.0.2.tgz#06be7abef947a3f14a30fd610671d401bca8b7b6" + dependencies: + capture-stack-trace "^1.0.0" + +cross-spawn-async@^2.1.1: + version "2.2.5" + resolved "https://registry.yarnpkg.com/cross-spawn-async/-/cross-spawn-async-2.2.5.tgz#845ff0c0834a3ded9d160daca6d390906bb288cc" + dependencies: + lru-cache "^4.0.0" + which "^1.2.8" + +cross-spawn@^4, cross-spawn@^4.0.0: + version "4.0.2" + resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-4.0.2.tgz#7b9247621c23adfdd3856004a823cbe397424d41" + dependencies: + lru-cache "^4.0.1" + which "^1.2.9" + +cryptiles@2.x.x: + version "2.0.5" + resolved "https://registry.yarnpkg.com/cryptiles/-/cryptiles-2.0.5.tgz#3bdfecdc608147c1c67202fa291e7dca59eaa3b8" + dependencies: + boom "2.x.x" + +crypto-random-string@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/crypto-random-string/-/crypto-random-string-1.0.0.tgz#a230f64f568310e1498009940790ec99545bca7e" + +currently-unhandled@^0.4.1: + version "0.4.1" + resolved "https://registry.yarnpkg.com/currently-unhandled/-/currently-unhandled-0.4.1.tgz#988df33feab191ef799a61369dd76c17adf957ea" + dependencies: + array-find-index "^1.0.1" + d@1: version "1.0.0" resolved "https://registry.yarnpkg.com/d/-/d-1.0.0.tgz#754bb5bfe55451da69a58b94d45f4c5b0462d58f" dependencies: es5-ext "^0.10.9" +dashdash@^1.12.0: + version "1.14.1" + resolved "https://registry.yarnpkg.com/dashdash/-/dashdash-1.14.1.tgz#853cfa0f7cbe2fed5de20326b8dd581035f6e2f0" + dependencies: + assert-plus "^1.0.0" + +date-time@^0.1.1: + version "0.1.1" + resolved "https://registry.yarnpkg.com/date-time/-/date-time-0.1.1.tgz#ed2f6d93d9790ce2fd66d5b5ff3edd5bbcbf3b07" + +debug-log@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/debug-log/-/debug-log-1.0.1.tgz#2307632d4c04382b8df8a32f70b895046d52745f" + debug@2.2.0: version "2.2.0" resolved "https://registry.yarnpkg.com/debug/-/debug-2.2.0.tgz#f87057e995b1a1f6ae6a4960664137bc56f039da" dependencies: ms "0.7.1" -debug@^2.1.1, debug@^2.2.0: +debug@^2.1.1, debug@^2.2.0, debug@^2.6.3: version "2.6.3" resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.3.tgz#0f7eb8c30965ec08c72accfa0130c8b79984141d" dependencies: ms "0.7.2" -deep-eql@^0.1.3: - version "0.1.3" - resolved "https://registry.yarnpkg.com/deep-eql/-/deep-eql-0.1.3.tgz#ef558acab8de25206cd713906d74e56930eb69f2" - dependencies: - type-detect "0.1.1" +decamelize@^1.0.0, decamelize@^1.1.1, decamelize@^1.1.2: + version "1.2.0" + resolved "https://registry.yarnpkg.com/decamelize/-/decamelize-1.2.0.tgz#f6534d15148269b20352e7bee26f501f9a191290" + +deep-equal@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/deep-equal/-/deep-equal-1.0.1.tgz#f5d260292b660e084eff4cdbc9f08ad3247448b5" + +deep-extend@~0.4.0: + version "0.4.2" + resolved "https://registry.yarnpkg.com/deep-extend/-/deep-extend-0.4.2.tgz#48b699c27e334bf89f10892be432f6e4c7d34a7f" deep-is@~0.1.3: version "0.1.3" resolved "https://registry.yarnpkg.com/deep-is/-/deep-is-0.1.3.tgz#b369d6fb5dbc13eecf524f91b070feedc357cf34" +default-require-extensions@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/default-require-extensions/-/default-require-extensions-1.0.0.tgz#f37ea15d3e13ffd9b437d33e1a75b5fb97874cb8" + dependencies: + strip-bom "^2.0.0" + del@^2.0.2: version "2.2.2" resolved "https://registry.yarnpkg.com/del/-/del-2.2.2.tgz#c12c981d067846c84bcaf862cff930d907ffd1a8" @@ -857,15 +1402,31 @@ del@^2.0.2: pinkie-promise "^2.0.0" rimraf "^2.2.8" +delayed-stream@~1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/delayed-stream/-/delayed-stream-1.0.0.tgz#df3ae199acadfb7d440aaae0b29e2272b24ec619" + +delegates@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/delegates/-/delegates-1.0.0.tgz#84c6e159b81904fdca59a0ef44cd870d31250f9a" + detect-indent@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/detect-indent/-/detect-indent-4.0.0.tgz#f76d064352cdf43a1cb6ce619c4ee3a9475de208" dependencies: repeating "^2.0.0" -diff@1.4.0: - version "1.4.0" - resolved "https://registry.yarnpkg.com/diff/-/diff-1.4.0.tgz#7f28d2eb9ee7b15a97efd89ce63dcfdaa3ccbabf" +detect-indent@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/detect-indent/-/detect-indent-5.0.0.tgz#3871cc0a6a002e8c3e5b3cf7f336264675f06b9d" + +diff-match-patch@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/diff-match-patch/-/diff-match-patch-1.0.0.tgz#1cc3c83a490d67f95d91e39f6ad1f2e086b63048" + +diff@^3.0.0, diff@^3.0.1: + version "3.2.0" + resolved "https://registry.yarnpkg.com/diff/-/diff-3.2.0.tgz#c9ce393a4b7cbd0b058a725c93df299027868ff9" doctrine@1.5.0: version "1.5.0" @@ -881,14 +1442,47 @@ doctrine@^2.0.0: esutils "^2.0.2" isarray "^1.0.0" +dot-prop@^4.1.0: + version "4.1.1" + resolved "https://registry.yarnpkg.com/dot-prop/-/dot-prop-4.1.1.tgz#a8493f0b7b5eeec82525b5c7587fa7de7ca859c1" + dependencies: + is-obj "^1.0.0" + +duplexer3@^0.1.4: + version "0.1.4" + resolved "https://registry.yarnpkg.com/duplexer3/-/duplexer3-0.1.4.tgz#ee01dd1cac0ed3cbc7fdbea37dc0a8f1ce002ce2" + +ecc-jsbn@~0.1.1: + version "0.1.1" + resolved "https://registry.yarnpkg.com/ecc-jsbn/-/ecc-jsbn-0.1.1.tgz#0fc73a9ed5f0d53c38193398523ef7e543777505" + dependencies: + jsbn "~0.1.0" + electron-to-chromium@^1.2.7: version "1.3.2" resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.3.2.tgz#b8ce5c93b308db0e92f6d0435c46ddec8f6363ab" +empower-core@^0.6.1: + version "0.6.1" + resolved "https://registry.yarnpkg.com/empower-core/-/empower-core-0.6.1.tgz#6c187f502fcef7554d57933396aac655483772b1" + dependencies: + call-signature "0.0.2" + core-js "^2.0.0" + +equal-length@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/equal-length/-/equal-length-1.0.1.tgz#21ca112d48ab24b4e1e7ffc0e5339d31fdfc274c" + erlang-types@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/erlang-types/-/erlang-types-1.0.0.tgz#e555bd091667498a01d340d18203231dc96d962f" +error-ex@^1.2.0: + version "1.3.1" + resolved "https://registry.yarnpkg.com/error-ex/-/error-ex-1.3.1.tgz#f855a86ce61adc4e8621c3cda21e7a7612c3a8dc" + dependencies: + is-arrayish "^0.2.1" + es5-ext@^0.10.14, es5-ext@^0.10.9, es5-ext@~0.10.14: version "0.10.15" resolved "https://registry.yarnpkg.com/es5-ext/-/es5-ext-0.10.15.tgz#c330a5934c1ee21284a7c081a86e5fd937c91ea6" @@ -896,6 +1490,10 @@ es5-ext@^0.10.14, es5-ext@^0.10.9, es5-ext@~0.10.14: es6-iterator "2" es6-symbol "~3.1" +es6-error@^4.0.1, es6-error@^4.0.2: + version "4.0.2" + resolved "https://registry.yarnpkg.com/es6-error/-/es6-error-4.0.2.tgz#eec5c726eacef51b7f6b73c20db6e1b13b069c98" + es6-iterator@2, es6-iterator@^2.0.1, es6-iterator@~2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/es6-iterator/-/es6-iterator-2.0.1.tgz#8e319c9f0453bf575d374940a655920e59ca5512" @@ -941,7 +1539,7 @@ es6-weak-map@^2.0.1: es6-iterator "^2.0.1" es6-symbol "^3.1.1" -escape-string-regexp@1.0.5, escape-string-regexp@^1.0.2, escape-string-regexp@^1.0.5: +escape-string-regexp@^1.0.2, escape-string-regexp@^1.0.4, escape-string-regexp@^1.0.5: version "1.0.5" resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4" @@ -1028,6 +1626,15 @@ eslint@^3.15.0: text-table "~0.2.0" user-home "^2.0.0" +espower-location-detector@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/espower-location-detector/-/espower-location-detector-1.0.0.tgz#a17b7ecc59d30e179e2bef73fb4137704cb331b5" + dependencies: + is-url "^1.2.1" + path-is-absolute "^1.0.0" + source-map "^0.5.0" + xtend "^4.0.0" + espree@^3.4.0: version "3.4.1" resolved "https://registry.yarnpkg.com/espree/-/espree-3.4.1.tgz#28a83ab4aaed71ed8fe0f5efe61b76a05c13c4d2" @@ -1039,6 +1646,12 @@ esprima@^3.1.1: version "3.1.3" resolved "https://registry.yarnpkg.com/esprima/-/esprima-3.1.3.tgz#fdca51cee6133895e3c88d535ce49dbff62a4633" +espurify@^1.6.0: + version "1.7.0" + resolved "https://registry.yarnpkg.com/espurify/-/espurify-1.7.0.tgz#1c5cf6cbccc32e6f639380bd4f991fab9ba9d226" + dependencies: + core-js "^2.0.0" + esquery@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/esquery/-/esquery-1.0.0.tgz#cfba8b57d7fba93f17298a8a006a04cda13d80fa" @@ -1075,14 +1688,63 @@ event-emitter@~0.3.5: d "1" es5-ext "~0.10.14" +execa@^0.4.0: + version "0.4.0" + resolved "https://registry.yarnpkg.com/execa/-/execa-0.4.0.tgz#4eb6467a36a095fabb2970ff9d5e3fb7bce6ebc3" + dependencies: + cross-spawn-async "^2.1.1" + is-stream "^1.1.0" + npm-run-path "^1.0.0" + object-assign "^4.0.1" + path-key "^1.0.0" + strip-eof "^1.0.0" + +execa@^0.5.0: + version "0.5.1" + resolved "https://registry.yarnpkg.com/execa/-/execa-0.5.1.tgz#de3fb85cb8d6e91c85bcbceb164581785cb57b36" + dependencies: + cross-spawn "^4.0.0" + get-stream "^2.2.0" + is-stream "^1.1.0" + npm-run-path "^2.0.0" + p-finally "^1.0.0" + signal-exit "^3.0.0" + strip-eof "^1.0.0" + exit-hook@^1.0.0: version "1.1.1" resolved "https://registry.yarnpkg.com/exit-hook/-/exit-hook-1.1.1.tgz#f05ca233b48c05d54fff07765df8507e95c02ff8" -fast-levenshtein@~2.0.4: - version "2.0.6" - resolved "https://registry.yarnpkg.com/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz#3d8a5c66883a16a30ca8643e851f19baa7797917" - +expand-brackets@^0.1.4: + version "0.1.5" + resolved "https://registry.yarnpkg.com/expand-brackets/-/expand-brackets-0.1.5.tgz#df07284e342a807cd733ac5af72411e581d1177b" + dependencies: + is-posix-bracket "^0.1.0" + +expand-range@^1.8.1: + version "1.8.2" + resolved "https://registry.yarnpkg.com/expand-range/-/expand-range-1.8.2.tgz#a299effd335fe2721ebae8e257ec79644fc85337" + dependencies: + fill-range "^2.1.0" + +extend@~3.0.0: + version "3.0.1" + resolved "https://registry.yarnpkg.com/extend/-/extend-3.0.1.tgz#a755ea7bc1adfcc5a31ce7e762dbaadc5e636444" + +extglob@^0.3.1: + version "0.3.2" + resolved "https://registry.yarnpkg.com/extglob/-/extglob-0.3.2.tgz#2e18ff3d2f49ab2765cec9023f011daa8d8349a1" + dependencies: + is-extglob "^1.0.0" + +extsprintf@1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/extsprintf/-/extsprintf-1.0.2.tgz#e1080e0658e300b06294990cc70e1502235fd550" + +fast-levenshtein@~2.0.4: + version "2.0.6" + resolved "https://registry.yarnpkg.com/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz#3d8a5c66883a16a30ca8643e851f19baa7797917" + figures@^1.3.5: version "1.7.0" resolved "https://registry.yarnpkg.com/figures/-/figures-1.7.0.tgz#cbe1e3affcf1cd44b80cadfed28dc793a9701d2e" @@ -1090,6 +1752,12 @@ figures@^1.3.5: escape-string-regexp "^1.0.5" object-assign "^4.1.0" +figures@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/figures/-/figures-2.0.0.tgz#3ab1a2d2a62c8bfb431a0c94cb797a2fce27c962" + dependencies: + escape-string-regexp "^1.0.5" + file-entry-cache@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/file-entry-cache/-/file-entry-cache-2.0.0.tgz#c392990c3e684783d838b8c84a45d8a048458361" @@ -1097,13 +1765,41 @@ file-entry-cache@^2.0.0: flat-cache "^1.2.1" object-assign "^4.0.1" -find-up@^1.0.0: +filename-regex@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/filename-regex/-/filename-regex-2.0.1.tgz#c1c4b9bee3e09725ddb106b75c1e301fe2f18b26" + +fill-range@^2.1.0: + version "2.2.3" + resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-2.2.3.tgz#50b77dfd7e469bc7492470963699fe7a8485a723" + dependencies: + is-number "^2.1.0" + isobject "^2.0.0" + randomatic "^1.1.3" + repeat-element "^1.1.2" + repeat-string "^1.5.2" + +find-cache-dir@^0.1.1: + version "0.1.1" + resolved "https://registry.yarnpkg.com/find-cache-dir/-/find-cache-dir-0.1.1.tgz#c8defae57c8a52a8a784f9e31c57c742e993a0b9" + dependencies: + commondir "^1.0.1" + mkdirp "^0.5.1" + pkg-dir "^1.0.0" + +find-up@^1.0.0, find-up@^1.1.2: version "1.1.2" resolved "https://registry.yarnpkg.com/find-up/-/find-up-1.1.2.tgz#6b2e9822b1a2ce0a60ab64d610eccad53cb24d0f" dependencies: path-exists "^2.0.0" pinkie-promise "^2.0.0" +find-up@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/find-up/-/find-up-2.1.0.tgz#45d1b7e506c717ddd482775a2b77920a3c0c57a7" + dependencies: + locate-path "^2.0.0" + flat-cache@^1.2.1: version "1.2.2" resolved "https://registry.yarnpkg.com/flat-cache/-/flat-cache-1.2.2.tgz#fa86714e72c21db88601761ecf2f555d1abc6b96" @@ -1113,6 +1809,39 @@ flat-cache@^1.2.1: graceful-fs "^4.1.2" write "^0.2.1" +fn-name@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/fn-name/-/fn-name-2.0.1.tgz#5214d7537a4d06a4a301c0cc262feb84188002e7" + +for-in@^1.0.1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/for-in/-/for-in-1.0.2.tgz#81068d295a8142ec0ac726c6e2200c30fb6d5e80" + +for-own@^0.1.4: + version "0.1.5" + resolved "https://registry.yarnpkg.com/for-own/-/for-own-0.1.5.tgz#5265c681a4f294dabbf17c9509b6763aa84510ce" + dependencies: + for-in "^1.0.1" + +foreground-child@^1.3.3, foreground-child@^1.5.3: + version "1.5.6" + resolved "https://registry.yarnpkg.com/foreground-child/-/foreground-child-1.5.6.tgz#4fd71ad2dfde96789b980a5c0a295937cb2f5ce9" + dependencies: + cross-spawn "^4" + signal-exit "^3.0.0" + +forever-agent@~0.6.1: + version "0.6.1" + resolved "https://registry.yarnpkg.com/forever-agent/-/forever-agent-0.6.1.tgz#fbc71f0c41adeb37f96c577ad1ed42d8fdacca91" + +form-data@~2.1.1: + version "2.1.4" + resolved "https://registry.yarnpkg.com/form-data/-/form-data-2.1.4.tgz#33c183acf193276ecaa98143a69e94bfee1750d1" + dependencies: + asynckit "^0.4.0" + combined-stream "^1.0.5" + mime-types "^2.1.12" + formatio@1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/formatio/-/formatio-1.1.1.tgz#5ed3ccd636551097383465d996199100e86161e9" @@ -1123,10 +1852,47 @@ fs.realpath@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f" +fsevents@^1.0.0: + version "1.1.1" + resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-1.1.1.tgz#f19fd28f43eeaf761680e519a203c4d0b3d31aff" + dependencies: + nan "^2.3.0" + node-pre-gyp "^0.6.29" + +fstream-ignore@^1.0.5: + version "1.0.5" + resolved "https://registry.yarnpkg.com/fstream-ignore/-/fstream-ignore-1.0.5.tgz#9c31dae34767018fe1d249b24dada67d092da105" + dependencies: + fstream "^1.0.0" + inherits "2" + minimatch "^3.0.0" + +fstream@^1.0.0, fstream@^1.0.10, fstream@^1.0.2: + version "1.0.11" + resolved "https://registry.yarnpkg.com/fstream/-/fstream-1.0.11.tgz#5c1fb1f117477114f0632a0eb4b71b3cb0fd3171" + dependencies: + graceful-fs "^4.1.2" + inherits "~2.0.0" + mkdirp ">=0.5 0" + rimraf "2" + function-bind@^1.0.2: version "1.1.0" resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.0.tgz#16176714c801798e4e8f2cf7f7529467bb4a5771" +gauge@~2.7.3: + version "2.7.4" + resolved "https://registry.yarnpkg.com/gauge/-/gauge-2.7.4.tgz#2c03405c7538c39d7eb37b317022e325fb018bf7" + dependencies: + aproba "^1.0.3" + console-control-strings "^1.0.0" + has-unicode "^2.0.0" + object-assign "^4.1.0" + signal-exit "^3.0.0" + string-width "^1.0.1" + strip-ansi "^3.0.1" + wide-align "^1.1.0" + generate-function@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/generate-function/-/generate-function-2.0.0.tgz#6858fe7c0969b7d4e9093337647ac79f60dfbe74" @@ -1137,18 +1903,49 @@ generate-object-property@^1.1.0: dependencies: is-property "^1.0.0" -glob@7.0.5: - version "7.0.5" - resolved "https://registry.yarnpkg.com/glob/-/glob-7.0.5.tgz#b4202a69099bbb4d292a7c1b95b6682b67ebdc95" +get-caller-file@^1.0.1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/get-caller-file/-/get-caller-file-1.0.2.tgz#f702e63127e7e231c160a80c1554acb70d5047e5" + +get-port@^3.0.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/get-port/-/get-port-3.1.0.tgz#ef01b18a84ca6486970ff99e54446141a73ffd3e" + +get-stdin@^4.0.1: + version "4.0.1" + resolved "https://registry.yarnpkg.com/get-stdin/-/get-stdin-4.0.1.tgz#b968c6b0a04384324902e8bf1a5df32579a450fe" + +get-stream@^2.2.0: + version "2.3.1" + resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-2.3.1.tgz#5f38f93f346009666ee0150a054167f91bdd95de" dependencies: - fs.realpath "^1.0.0" - inflight "^1.0.4" - inherits "2" - minimatch "^3.0.2" - once "^1.3.0" - path-is-absolute "^1.0.0" + object-assign "^4.0.1" + pinkie-promise "^2.0.0" -glob@^7.0.0, glob@^7.0.3, glob@^7.0.5: +get-stream@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-3.0.0.tgz#8e943d1358dc37555054ecbe2edb05aa174ede14" + +getpass@^0.1.1: + version "0.1.7" + resolved "https://registry.yarnpkg.com/getpass/-/getpass-0.1.7.tgz#5eff8e3e684d569ae4cb2b1282604e8ba62149fa" + dependencies: + assert-plus "^1.0.0" + +glob-base@^0.3.0: + version "0.3.0" + resolved "https://registry.yarnpkg.com/glob-base/-/glob-base-0.3.0.tgz#dbb164f6221b1c0b1ccf82aea328b497df0ea3c4" + dependencies: + glob-parent "^2.0.0" + is-glob "^2.0.0" + +glob-parent@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-2.0.0.tgz#81383d72db054fcccf5336daa902f182f6edbb28" + dependencies: + is-glob "^2.0.0" + +glob@^7.0.0, glob@^7.0.3, glob@^7.0.5, glob@^7.0.6: version "7.1.1" resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.1.tgz#805211df04faaf1c63a3600306cdf5ade50b2ec8" dependencies: @@ -1174,17 +1971,56 @@ globby@^5.0.0: pify "^2.0.0" pinkie-promise "^2.0.0" -graceful-fs@^4.1.2: +globby@^6.0.0: + version "6.1.0" + resolved "https://registry.yarnpkg.com/globby/-/globby-6.1.0.tgz#f5a6d70e8395e21c858fb0489d64df02424d506c" + dependencies: + array-union "^1.0.1" + glob "^7.0.3" + object-assign "^4.0.1" + pify "^2.0.0" + pinkie-promise "^2.0.0" + +got@^6.7.1: + version "6.7.1" + resolved "https://registry.yarnpkg.com/got/-/got-6.7.1.tgz#240cd05785a9a18e561dc1b44b41c763ef1e8db0" + dependencies: + create-error-class "^3.0.0" + duplexer3 "^0.1.4" + get-stream "^3.0.0" + is-redirect "^1.0.0" + is-retry-allowed "^1.0.0" + is-stream "^1.0.0" + lowercase-keys "^1.0.0" + safe-buffer "^5.0.1" + timed-out "^4.0.0" + unzip-response "^2.0.1" + url-parse-lax "^1.0.0" + +graceful-fs@^4.1.11, graceful-fs@^4.1.2, graceful-fs@^4.1.6: version "4.1.11" resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.1.11.tgz#0e8bdfe4d1ddb8854d64e04ea7c00e2a026e5658" -"graceful-readlink@>= 1.0.0": - version "1.0.1" - resolved "https://registry.yarnpkg.com/graceful-readlink/-/graceful-readlink-1.0.1.tgz#4cafad76bc62f02fa039b2f94e9a3dd3a391a725" +handlebars@^4.0.3: + version "4.0.10" + resolved "https://registry.yarnpkg.com/handlebars/-/handlebars-4.0.10.tgz#3d30c718b09a3d96f23ea4cc1f403c4d3ba9ff4f" + dependencies: + async "^1.4.0" + optimist "^0.6.1" + source-map "^0.4.4" + optionalDependencies: + uglify-js "^2.6" + +har-schema@^1.0.5: + version "1.0.5" + resolved "https://registry.yarnpkg.com/har-schema/-/har-schema-1.0.5.tgz#d263135f43307c02c602afc8fe95970c0151369e" -growl@1.9.2: - version "1.9.2" - resolved "https://registry.yarnpkg.com/growl/-/growl-1.9.2.tgz#0ea7743715db8d8de2c5ede1775e1b45ac85c02f" +har-validator@~4.2.1: + version "4.2.1" + resolved "https://registry.yarnpkg.com/har-validator/-/har-validator-4.2.1.tgz#33481d0f1bbff600dd203d75812a6a5fba002e2a" + dependencies: + ajv "^4.9.1" + har-schema "^1.0.5" has-ansi@^2.0.0: version "2.0.0" @@ -1192,16 +2028,45 @@ has-ansi@^2.0.0: dependencies: ansi-regex "^2.0.0" +has-color@~0.1.0: + version "0.1.7" + resolved "https://registry.yarnpkg.com/has-color/-/has-color-0.1.7.tgz#67144a5260c34fc3cca677d041daf52fe7b78b2f" + has-flag@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-1.0.0.tgz#9d9e793165ce017a00f00418c43f942a7b1d11fa" +has-flag@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-2.0.0.tgz#e8207af1cc7b30d446cc70b734b5e8be18f88d51" + +has-unicode@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/has-unicode/-/has-unicode-2.0.1.tgz#e0e6fe6a28cf51138855e086d1691e771de2a8b9" + +has-yarn@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/has-yarn/-/has-yarn-1.0.0.tgz#89e25db604b725c8f5976fff0addc921b828a5a7" + has@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/has/-/has-1.0.1.tgz#8461733f538b0837c9361e39a9ab9e9704dc2f28" dependencies: function-bind "^1.0.2" +hawk@~3.1.3: + version "3.1.3" + resolved "https://registry.yarnpkg.com/hawk/-/hawk-3.1.3.tgz#078444bd7c1640b0fe540d2c9b73d59678e8e1c4" + dependencies: + boom "2.x.x" + cryptiles "2.x.x" + hoek "2.x.x" + sntp "1.x.x" + +hoek@2.x.x: + version "2.16.3" + resolved "https://registry.yarnpkg.com/hoek/-/hoek-2.16.3.tgz#20bb7403d3cea398e91dc4710a8ff1b8274a25ed" + home-or-tmp@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/home-or-tmp/-/home-or-tmp-2.0.0.tgz#e36c3f2d2cae7d746a857e38d18d5f32a7882db8" @@ -1209,6 +2074,40 @@ home-or-tmp@^2.0.0: os-homedir "^1.0.0" os-tmpdir "^1.0.1" +hosted-git-info@^2.1.4: + version "2.4.2" + resolved "https://registry.yarnpkg.com/hosted-git-info/-/hosted-git-info-2.4.2.tgz#0076b9f46a270506ddbaaea56496897460612a67" + +http-signature@~1.1.0: + version "1.1.1" + resolved "https://registry.yarnpkg.com/http-signature/-/http-signature-1.1.1.tgz#df72e267066cd0ac67fb76adf8e134a8fbcf91bf" + dependencies: + assert-plus "^0.2.0" + jsprim "^1.2.2" + sshpk "^1.7.0" + +hullabaloo-config-manager@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/hullabaloo-config-manager/-/hullabaloo-config-manager-1.0.1.tgz#c72be7ba249a67c99b6ba3eb1f55837fa01acd8f" + dependencies: + dot-prop "^4.1.0" + es6-error "^4.0.2" + graceful-fs "^4.1.11" + indent-string "^3.1.0" + json5 "^0.5.1" + lodash.clonedeep "^4.5.0" + lodash.clonedeepwith "^4.5.0" + lodash.isequal "^4.5.0" + lodash.merge "^4.6.0" + md5-hex "^2.0.0" + package-hash "^2.0.0" + pkg-dir "^1.0.0" + resolve-from "^2.0.0" + +ignore-by-default@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/ignore-by-default/-/ignore-by-default-1.0.1.tgz#48ca6d72f6c6a3af00a9ad4ae6876be3889e2b09" + ignore@^3.2.0: version "3.2.6" resolved "https://registry.yarnpkg.com/ignore/-/ignore-3.2.6.tgz#26e8da0644be0bb4cb39516f6c79f0e0f4ffe48c" @@ -1217,6 +2116,16 @@ imurmurhash@^0.1.4: version "0.1.4" resolved "https://registry.yarnpkg.com/imurmurhash/-/imurmurhash-0.1.4.tgz#9218b9b2b928a238b13dc4fb6b6d576f231453ea" +indent-string@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/indent-string/-/indent-string-2.1.0.tgz#8e2d48348742121b4a8218b7a137e9a52049dc80" + dependencies: + repeating "^2.0.0" + +indent-string@^3.0.0, indent-string@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/indent-string/-/indent-string-3.1.0.tgz#08ff4334603388399b329e6b9538dc7a3cf5de7d" + inflight@^1.0.4: version "1.0.6" resolved "https://registry.yarnpkg.com/inflight/-/inflight-1.0.6.tgz#49bd6331d7d02d0c09bc910a1075ba8165b56df9" @@ -1224,7 +2133,7 @@ inflight@^1.0.4: once "^1.3.0" wrappy "1" -inherits@2, inherits@^2.0.3, inherits@~2.0.1: +inherits@2, inherits@^2.0.1, inherits@^2.0.3, inherits@~2.0.0, inherits@~2.0.1: version "2.0.3" resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.3.tgz#633c2c83e3da42a502f52466022480f4208261de" @@ -1232,6 +2141,10 @@ inherits@2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.1.tgz#b17d08d326b4423e568eff719f91b0b1cbdf69f1" +ini@~1.3.0: + version "1.3.4" + resolved "https://registry.yarnpkg.com/ini/-/ini-1.3.4.tgz#0537cb79daf59b59a1a517dff706c86ec039162e" + inquirer@^0.12.0: version "0.12.0" resolved "https://registry.yarnpkg.com/inquirer/-/inquirer-0.12.0.tgz#1ef2bfd63504df0bc75785fff8c2c41df12f077e" @@ -1260,7 +2173,63 @@ invariant@^2.2.0, invariant@^2.2.2: dependencies: loose-envify "^1.0.0" -is-finite@^1.0.0: +invert-kv@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/invert-kv/-/invert-kv-1.0.0.tgz#104a8e4aaca6d3d8cd157a8ef8bfab2d7a3ffdb6" + +irregular-plurals@^1.0.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/irregular-plurals/-/irregular-plurals-1.2.0.tgz#38f299834ba8c00c30be9c554e137269752ff3ac" + +is-arrayish@^0.2.1: + version "0.2.1" + resolved "https://registry.yarnpkg.com/is-arrayish/-/is-arrayish-0.2.1.tgz#77c99840527aa8ecb1a8ba697b80645a7a926a9d" + +is-binary-path@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/is-binary-path/-/is-binary-path-1.0.1.tgz#75f16642b480f187a711c814161fd3a4a7655898" + dependencies: + binary-extensions "^1.0.0" + +is-buffer@^1.1.5: + version "1.1.5" + resolved "https://registry.yarnpkg.com/is-buffer/-/is-buffer-1.1.5.tgz#1f3b26ef613b214b88cbca23cc6c01d87961eecc" + +is-builtin-module@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/is-builtin-module/-/is-builtin-module-1.0.0.tgz#540572d34f7ac3119f8f76c30cbc1b1e037affbe" + dependencies: + builtin-modules "^1.0.0" + +is-ci@^1.0.7: + version "1.0.10" + resolved "https://registry.yarnpkg.com/is-ci/-/is-ci-1.0.10.tgz#f739336b2632365061a9d48270cd56ae3369318e" + dependencies: + ci-info "^1.0.0" + +is-dotfile@^1.0.0: + version "1.0.2" + resolved "https://registry.yarnpkg.com/is-dotfile/-/is-dotfile-1.0.2.tgz#2c132383f39199f8edc268ca01b9b007d205cc4d" + +is-equal-shallow@^0.1.3: + version "0.1.3" + resolved "https://registry.yarnpkg.com/is-equal-shallow/-/is-equal-shallow-0.1.3.tgz#2238098fc221de0bcfa5d9eac4c45d638aa1c534" + dependencies: + is-primitive "^2.0.0" + +is-error@^2.2.0: + version "2.2.1" + resolved "https://registry.yarnpkg.com/is-error/-/is-error-2.2.1.tgz#684a96d84076577c98f4cdb40c6d26a5123bf19c" + +is-extendable@^0.1.1: + version "0.1.1" + resolved "https://registry.yarnpkg.com/is-extendable/-/is-extendable-0.1.1.tgz#62b110e289a471418e3ec36a617d472e301dfc89" + +is-extglob@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/is-extglob/-/is-extglob-1.0.0.tgz#ac468177c4943405a092fc8f29760c6ffc6206c0" + +is-finite@^1.0.0, is-finite@^1.0.1: version "1.0.2" resolved "https://registry.yarnpkg.com/is-finite/-/is-finite-1.0.2.tgz#cc6677695602be550ef11e8b4aa6305342b6d0aa" dependencies: @@ -1276,6 +2245,16 @@ is-fullwidth-code-point@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz#a3b30a5c4f199183167aaab93beefae3ddfb654f" +is-generator-fn@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/is-generator-fn/-/is-generator-fn-1.0.0.tgz#969d49e1bb3329f6bb7f09089be26578b2ddd46a" + +is-glob@^2.0.0, is-glob@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-2.0.1.tgz#d096f926a3ded5600f3fdfd91198cb0888c2d863" + dependencies: + is-extglob "^1.0.0" + is-my-json-valid@^2.10.0: version "2.16.0" resolved "https://registry.yarnpkg.com/is-my-json-valid/-/is-my-json-valid-2.16.0.tgz#f079dd9bfdae65ee2038aae8acbc86ab109e3693" @@ -1285,6 +2264,26 @@ is-my-json-valid@^2.10.0: jsonpointer "^4.0.0" xtend "^4.0.0" +is-npm@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/is-npm/-/is-npm-1.0.0.tgz#f2fb63a65e4905b406c86072765a1a4dc793b9f4" + +is-number@^2.0.2, is-number@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/is-number/-/is-number-2.1.0.tgz#01fcbbb393463a548f2f466cce16dece49db908f" + dependencies: + kind-of "^3.0.2" + +is-obj@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/is-obj/-/is-obj-1.0.1.tgz#3e4729ac1f5fde025cd7d83a896dab9f4f67db0f" + +is-observable@^0.2.0: + version "0.2.0" + resolved "https://registry.yarnpkg.com/is-observable/-/is-observable-0.2.0.tgz#b361311d83c6e5d726cabf5e250b0237106f5ae2" + dependencies: + symbol-observable "^0.2.2" + is-path-cwd@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/is-path-cwd/-/is-path-cwd-1.0.0.tgz#d225ec23132e89edd38fda767472e62e65f1106d" @@ -1301,31 +2300,207 @@ is-path-inside@^1.0.0: dependencies: path-is-inside "^1.0.1" +is-plain-obj@^1.0.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/is-plain-obj/-/is-plain-obj-1.1.0.tgz#71a50c8429dfca773c92a390a4a03b39fcd51d3e" + +is-posix-bracket@^0.1.0: + version "0.1.1" + resolved "https://registry.yarnpkg.com/is-posix-bracket/-/is-posix-bracket-0.1.1.tgz#3334dc79774368e92f016e6fbc0a88f5cd6e6bc4" + +is-primitive@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/is-primitive/-/is-primitive-2.0.0.tgz#207bab91638499c07b2adf240a41a87210034575" + +is-promise@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/is-promise/-/is-promise-2.1.0.tgz#79a2a9ece7f096e80f36d2b2f3bc16c1ff4bf3fa" + is-property@^1.0.0: version "1.0.2" resolved "https://registry.yarnpkg.com/is-property/-/is-property-1.0.2.tgz#57fe1c4e48474edd65b09911f26b1cd4095dda84" +is-redirect@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/is-redirect/-/is-redirect-1.0.0.tgz#1d03dded53bd8db0f30c26e4f95d36fc7c87dc24" + is-resolvable@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/is-resolvable/-/is-resolvable-1.0.0.tgz#8df57c61ea2e3c501408d100fb013cf8d6e0cc62" dependencies: tryit "^1.0.1" -isarray@^1.0.0, isarray@~1.0.0: +is-retry-allowed@^1.0.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/is-retry-allowed/-/is-retry-allowed-1.1.0.tgz#11a060568b67339444033d0125a61a20d564fb34" + +is-stream@^1.0.0, is-stream@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/is-stream/-/is-stream-1.1.0.tgz#12d4a3dd4e68e0b79ceb8dbc84173ae80d91ca44" + +is-typedarray@~1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/is-typedarray/-/is-typedarray-1.0.0.tgz#e479c80858df0c1b11ddda6940f96011fcda4a9a" + +is-url@^1.2.1: + version "1.2.2" + resolved "https://registry.yarnpkg.com/is-url/-/is-url-1.2.2.tgz#498905a593bf47cc2d9e7f738372bbf7696c7f26" + +is-utf8@^0.2.0, is-utf8@^0.2.1: + version "0.2.1" + resolved "https://registry.yarnpkg.com/is-utf8/-/is-utf8-0.2.1.tgz#4b0da1442104d1b336340e80797e865cf39f7d72" + +isarray@1.0.0, isarray@^1.0.0, isarray@~1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/isarray/-/isarray-1.0.0.tgz#bb935d48582cba168c06834957a54a3e07124f11" +isexe@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/isexe/-/isexe-2.0.0.tgz#e8fbf374dc556ff8947a10dcb0572d633f2cfa10" + +isobject@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/isobject/-/isobject-2.1.0.tgz#f065561096a3f1da2ef46272f815c840d87e0c89" + dependencies: + isarray "1.0.0" + +isstream@~0.1.2: + version "0.1.2" + resolved "https://registry.yarnpkg.com/isstream/-/isstream-0.1.2.tgz#47e63f7af55afa6f92e1500e690eb8b8529c099a" + +istanbul-lib-coverage@^1.1.0, istanbul-lib-coverage@^1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/istanbul-lib-coverage/-/istanbul-lib-coverage-1.1.1.tgz#73bfb998885299415c93d38a3e9adf784a77a9da" + +istanbul-lib-hook@^1.0.6: + version "1.0.7" + resolved "https://registry.yarnpkg.com/istanbul-lib-hook/-/istanbul-lib-hook-1.0.7.tgz#dd6607f03076578fe7d6f2a630cf143b49bacddc" + dependencies: + append-transform "^0.4.0" + +istanbul-lib-instrument@^1.7.1: + version "1.7.2" + resolved "https://registry.yarnpkg.com/istanbul-lib-instrument/-/istanbul-lib-instrument-1.7.2.tgz#6014b03d3470fb77638d5802508c255c06312e56" + dependencies: + babel-generator "^6.18.0" + babel-template "^6.16.0" + babel-traverse "^6.18.0" + babel-types "^6.18.0" + babylon "^6.13.0" + istanbul-lib-coverage "^1.1.1" + semver "^5.3.0" + +istanbul-lib-report@^1.1.0: + version "1.1.1" + resolved "https://registry.yarnpkg.com/istanbul-lib-report/-/istanbul-lib-report-1.1.1.tgz#f0e55f56655ffa34222080b7a0cd4760e1405fc9" + dependencies: + istanbul-lib-coverage "^1.1.1" + mkdirp "^0.5.1" + path-parse "^1.0.5" + supports-color "^3.1.2" + +istanbul-lib-source-maps@^1.2.0: + version "1.2.1" + resolved "https://registry.yarnpkg.com/istanbul-lib-source-maps/-/istanbul-lib-source-maps-1.2.1.tgz#a6fe1acba8ce08eebc638e572e294d267008aa0c" + dependencies: + debug "^2.6.3" + istanbul-lib-coverage "^1.1.1" + mkdirp "^0.5.1" + rimraf "^2.6.1" + source-map "^0.5.3" + +istanbul-reports@^1.1.0: + version "1.1.1" + resolved "https://registry.yarnpkg.com/istanbul-reports/-/istanbul-reports-1.1.1.tgz#042be5c89e175bc3f86523caab29c014e77fee4e" + dependencies: + handlebars "^4.0.3" + +jest-diff@19.0.0, jest-diff@^19.0.0: + version "19.0.0" + resolved "https://registry.yarnpkg.com/jest-diff/-/jest-diff-19.0.0.tgz#d1563cfc56c8b60232988fbc05d4d16ed90f063c" + dependencies: + chalk "^1.1.3" + diff "^3.0.0" + jest-matcher-utils "^19.0.0" + pretty-format "^19.0.0" + +jest-file-exists@^19.0.0: + version "19.0.0" + resolved "https://registry.yarnpkg.com/jest-file-exists/-/jest-file-exists-19.0.0.tgz#cca2e587a11ec92e24cfeab3f8a94d657f3fceb8" + +jest-matcher-utils@^19.0.0: + version "19.0.0" + resolved "https://registry.yarnpkg.com/jest-matcher-utils/-/jest-matcher-utils-19.0.0.tgz#5ecd9b63565d2b001f61fbf7ec4c7f537964564d" + dependencies: + chalk "^1.1.3" + pretty-format "^19.0.0" + +jest-message-util@^19.0.0: + version "19.0.0" + resolved "https://registry.yarnpkg.com/jest-message-util/-/jest-message-util-19.0.0.tgz#721796b89c0e4d761606f9ba8cb828a3b6246416" + dependencies: + chalk "^1.1.1" + micromatch "^2.3.11" + +jest-mock@^19.0.0: + version "19.0.0" + resolved "https://registry.yarnpkg.com/jest-mock/-/jest-mock-19.0.0.tgz#67038641e9607ab2ce08ec4a8cb83aabbc899d01" + +jest-snapshot@19.0.2: + version "19.0.2" + resolved "https://registry.yarnpkg.com/jest-snapshot/-/jest-snapshot-19.0.2.tgz#9c1b216214f7187c38bfd5c70b1efab16b0ff50b" + dependencies: + chalk "^1.1.3" + jest-diff "^19.0.0" + jest-file-exists "^19.0.0" + jest-matcher-utils "^19.0.0" + jest-util "^19.0.2" + natural-compare "^1.4.0" + pretty-format "^19.0.0" + +jest-util@^19.0.2: + version "19.0.2" + resolved "https://registry.yarnpkg.com/jest-util/-/jest-util-19.0.2.tgz#e0a0232a2ab9e6b2b53668bdb3534c2b5977ed41" + dependencies: + chalk "^1.1.1" + graceful-fs "^4.1.6" + jest-file-exists "^19.0.0" + jest-message-util "^19.0.0" + jest-mock "^19.0.0" + jest-validate "^19.0.2" + leven "^2.0.0" + mkdirp "^0.5.1" + +jest-validate@^19.0.2: + version "19.0.2" + resolved "https://registry.yarnpkg.com/jest-validate/-/jest-validate-19.0.2.tgz#dc534df5f1278d5b63df32b14241d4dbf7244c0c" + dependencies: + chalk "^1.1.1" + jest-matcher-utils "^19.0.0" + leven "^2.0.0" + pretty-format "^19.0.0" + +jodid25519@^1.0.0: + version "1.0.2" + resolved "https://registry.yarnpkg.com/jodid25519/-/jodid25519-1.0.2.tgz#06d4912255093419477d425633606e0e90782967" + dependencies: + jsbn "~0.1.0" + js-tokens@^3.0.0: version "3.0.1" resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-3.0.1.tgz#08e9f132484a2c45a30907e9dc4d5567b7f114d7" -js-yaml@^3.5.1: +js-yaml@^3.5.1, js-yaml@^3.8.2: version "3.8.2" resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.8.2.tgz#02d3e2c0f6beab20248d412c352203827d786721" dependencies: argparse "^1.0.7" esprima "^3.1.1" +jsbn@~0.1.0: + version "0.1.1" + resolved "https://registry.yarnpkg.com/jsbn/-/jsbn-0.1.1.tgz#a5e654c2e5a2deb5f201d96cefbca80c0ef2f513" + jsesc@^1.3.0: version "1.3.0" resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-1.3.0.tgz#46c3fec8c1892b12b0833db9bc7622176dbab34b" @@ -1338,17 +2513,21 @@ jsesc@~0.5.0: version "0.5.0" resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-0.5.0.tgz#e7dee66e35d6fc16f710fe91d5cf69f70f08911d" +json-schema@0.2.3: + version "0.2.3" + resolved "https://registry.yarnpkg.com/json-schema/-/json-schema-0.2.3.tgz#b480c892e59a2f05954ce727bd3f2a4e882f9e13" + json-stable-stringify@^1.0.0, json-stable-stringify@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/json-stable-stringify/-/json-stable-stringify-1.0.1.tgz#9a759d39c5f2ff503fd5300646ed445f88c4f9af" dependencies: jsonify "~0.0.0" -json3@3.3.2: - version "3.3.2" - resolved "https://registry.yarnpkg.com/json3/-/json3-3.3.2.tgz#3c0434743df93e2f5c42aee7b19bcb483575f4e1" +json-stringify-safe@~5.0.1: + version "5.0.1" + resolved "https://registry.yarnpkg.com/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz#1296a2d58fd45f19a0f6ce01d65701e2c735b6eb" -json5@^0.5.0: +json5@^0.5.0, json5@^0.5.1: version "0.5.1" resolved "https://registry.yarnpkg.com/json5/-/json5-0.5.1.tgz#1eade7acc012034ad84e2396767ead9fa5495821" @@ -1360,6 +2539,51 @@ jsonpointer@^4.0.0: version "4.0.1" resolved "https://registry.yarnpkg.com/jsonpointer/-/jsonpointer-4.0.1.tgz#4fd92cb34e0e9db3c89c8622ecf51f9b978c6cb9" +jsprim@^1.2.2: + version "1.4.0" + resolved "https://registry.yarnpkg.com/jsprim/-/jsprim-1.4.0.tgz#a3b87e40298d8c380552d8cc7628a0bb95a22918" + dependencies: + assert-plus "1.0.0" + extsprintf "1.0.2" + json-schema "0.2.3" + verror "1.3.6" + +kind-of@^3.0.2: + version "3.2.2" + resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-3.2.2.tgz#31ea21a734bab9bbb0f32466d893aea51e4a3c64" + dependencies: + is-buffer "^1.1.5" + +last-line-stream@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/last-line-stream/-/last-line-stream-1.0.0.tgz#d1b64d69f86ff24af2d04883a2ceee14520a5600" + dependencies: + through2 "^2.0.0" + +latest-version@^3.0.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/latest-version/-/latest-version-3.1.0.tgz#a205383fea322b33b5ae3b18abee0dc2f356ee15" + dependencies: + package-json "^4.0.0" + +lazy-cache@^1.0.3: + version "1.0.4" + resolved "https://registry.yarnpkg.com/lazy-cache/-/lazy-cache-1.0.4.tgz#a1d78fc3a50474cb80845d3b3b6e1da49a446e8e" + +lazy-req@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/lazy-req/-/lazy-req-2.0.0.tgz#c9450a363ecdda2e6f0c70132ad4f37f8f06f2b4" + +lcid@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/lcid/-/lcid-1.0.0.tgz#308accafa0bc483a3867b4b6f2b9506251d1b835" + dependencies: + invert-kv "^1.0.0" + +leven@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/leven/-/leven-2.1.0.tgz#c2e7a9f772094dee9d34202ae8acce4687875580" + levn@^0.3.0, levn@~0.3.0: version "0.3.0" resolved "https://registry.yarnpkg.com/levn/-/levn-0.3.0.tgz#3b09924edf9f083c0490fdd4c0bc4421e04764ee" @@ -1367,60 +2591,71 @@ levn@^0.3.0, levn@~0.3.0: prelude-ls "~1.1.2" type-check "~0.3.2" -lodash._baseassign@^3.0.0: - version "3.2.0" - resolved "https://registry.yarnpkg.com/lodash._baseassign/-/lodash._baseassign-3.2.0.tgz#8c38a099500f215ad09e59f1722fd0c52bfe0a4e" +load-json-file@^1.0.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/load-json-file/-/load-json-file-1.1.0.tgz#956905708d58b4bab4c2261b04f59f31c99374c0" dependencies: - lodash._basecopy "^3.0.0" - lodash.keys "^3.0.0" + graceful-fs "^4.1.2" + parse-json "^2.2.0" + pify "^2.0.0" + pinkie-promise "^2.0.0" + strip-bom "^2.0.0" -lodash._basecopy@^3.0.0: - version "3.0.1" - resolved "https://registry.yarnpkg.com/lodash._basecopy/-/lodash._basecopy-3.0.1.tgz#8da0e6a876cf344c0ad8a54882111dd3c5c7ca36" +load-json-file@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/load-json-file/-/load-json-file-2.0.0.tgz#7947e42149af80d696cbf797bcaabcfe1fe29ca8" + dependencies: + graceful-fs "^4.1.2" + parse-json "^2.2.0" + pify "^2.0.0" + strip-bom "^3.0.0" -lodash._basecreate@^3.0.0: - version "3.0.3" - resolved "https://registry.yarnpkg.com/lodash._basecreate/-/lodash._basecreate-3.0.3.tgz#1bc661614daa7fc311b7d03bf16806a0213cf821" +locate-path@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-2.0.0.tgz#2b568b265eec944c6d9c0de9c3dbbbca0354cd8e" + dependencies: + p-locate "^2.0.0" + path-exists "^3.0.0" -lodash._getnative@^3.0.0: - version "3.9.1" - resolved "https://registry.yarnpkg.com/lodash._getnative/-/lodash._getnative-3.9.1.tgz#570bc7dede46d61cdcde687d65d3eecbaa3aaff5" +lodash.clonedeep@^4.5.0: + version "4.5.0" + resolved "https://registry.yarnpkg.com/lodash.clonedeep/-/lodash.clonedeep-4.5.0.tgz#e23f3f9c4f8fbdde872529c1071857a086e5ccef" -lodash._isiterateecall@^3.0.0: - version "3.0.9" - resolved "https://registry.yarnpkg.com/lodash._isiterateecall/-/lodash._isiterateecall-3.0.9.tgz#5203ad7ba425fae842460e696db9cf3e6aac057c" +lodash.clonedeepwith@^4.5.0: + version "4.5.0" + resolved "https://registry.yarnpkg.com/lodash.clonedeepwith/-/lodash.clonedeepwith-4.5.0.tgz#6ee30573a03a1a60d670a62ef33c10cf1afdbdd4" lodash.cond@^4.3.0: version "4.5.2" resolved "https://registry.yarnpkg.com/lodash.cond/-/lodash.cond-4.5.2.tgz#f471a1da486be60f6ab955d17115523dd1d255d5" -lodash.create@3.1.1: - version "3.1.1" - resolved "https://registry.yarnpkg.com/lodash.create/-/lodash.create-3.1.1.tgz#d7f2849f0dbda7e04682bb8cd72ab022461debe7" - dependencies: - lodash._baseassign "^3.0.0" - lodash._basecreate "^3.0.0" - lodash._isiterateecall "^3.0.0" +lodash.debounce@^4.0.3: + version "4.0.8" + resolved "https://registry.yarnpkg.com/lodash.debounce/-/lodash.debounce-4.0.8.tgz#82d79bff30a67c4005ffd5e2515300ad9ca4d7af" -lodash.isarguments@^3.0.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/lodash.isarguments/-/lodash.isarguments-3.1.0.tgz#2f573d85c6a24289ff00663b491c1d338ff3458a" +lodash.difference@^4.3.0: + version "4.5.0" + resolved "https://registry.yarnpkg.com/lodash.difference/-/lodash.difference-4.5.0.tgz#9ccb4e505d486b91651345772885a2df27fd017c" -lodash.isarray@^3.0.0: - version "3.0.4" - resolved "https://registry.yarnpkg.com/lodash.isarray/-/lodash.isarray-3.0.4.tgz#79e4eb88c36a8122af86f844aa9bcd851b5fbb55" +lodash.flatten@^4.2.0: + version "4.4.0" + resolved "https://registry.yarnpkg.com/lodash.flatten/-/lodash.flatten-4.4.0.tgz#f31c22225a9632d2bbf8e4addbef240aa765a61f" + +lodash.flattendeep@^4.4.0: + version "4.4.0" + resolved "https://registry.yarnpkg.com/lodash.flattendeep/-/lodash.flattendeep-4.4.0.tgz#fb030917f86a3134e5bc9bec0d69e0013ddfedb2" + +lodash.isequal@^4.5.0: + version "4.5.0" + resolved "https://registry.yarnpkg.com/lodash.isequal/-/lodash.isequal-4.5.0.tgz#415c4478f2bcc30120c22ce10ed3226f7d3e18e0" lodash.isplainobject@^4.0.6: version "4.0.6" resolved "https://registry.yarnpkg.com/lodash.isplainobject/-/lodash.isplainobject-4.0.6.tgz#7c526a52d89b45c45cc690b88163be0497f550cb" -lodash.keys@^3.0.0: - version "3.1.2" - resolved "https://registry.yarnpkg.com/lodash.keys/-/lodash.keys-3.1.2.tgz#4dbc0472b156be50a0b286855d1bd0b0c656098a" - dependencies: - lodash._getnative "^3.0.0" - lodash.isarguments "^3.0.0" - lodash.isarray "^3.0.0" +lodash.merge@^4.6.0: + version "4.6.0" + resolved "https://registry.yarnpkg.com/lodash.merge/-/lodash.merge-4.6.0.tgz#69884ba144ac33fe699737a6086deffadd0f89c5" lodash.some@^4.6.0: version "4.6.0" @@ -1434,69 +2669,284 @@ lolex@1.3.2: version "1.3.2" resolved "https://registry.yarnpkg.com/lolex/-/lolex-1.3.2.tgz#7c3da62ffcb30f0f5a80a2566ca24e45d8a01f31" +longest@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/longest/-/longest-1.0.1.tgz#30a0b2da38f73770e8294a0d22e6625ed77d0097" + loose-envify@^1.0.0: version "1.3.1" resolved "https://registry.yarnpkg.com/loose-envify/-/loose-envify-1.3.1.tgz#d1a8ad33fa9ce0e713d65fdd0ac8b748d478c848" dependencies: js-tokens "^3.0.0" -minimatch@^3.0.2, minimatch@^3.0.3: +loud-rejection@^1.0.0, loud-rejection@^1.2.0: + version "1.6.0" + resolved "https://registry.yarnpkg.com/loud-rejection/-/loud-rejection-1.6.0.tgz#5b46f80147edee578870f086d04821cf998e551f" + dependencies: + currently-unhandled "^0.4.1" + signal-exit "^3.0.0" + +lowercase-keys@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/lowercase-keys/-/lowercase-keys-1.0.0.tgz#4e3366b39e7f5457e35f1324bdf6f88d0bfc7306" + +lru-cache@^4.0.0, lru-cache@^4.0.1: + version "4.0.2" + resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-4.0.2.tgz#1d17679c069cda5d040991a09dbc2c0db377e55e" + dependencies: + pseudomap "^1.0.1" + yallist "^2.0.0" + +make-dir@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/make-dir/-/make-dir-1.0.0.tgz#97a011751e91dd87cfadef58832ebb04936de978" + dependencies: + pify "^2.3.0" + +map-obj@^1.0.0, map-obj@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/map-obj/-/map-obj-1.0.1.tgz#d933ceb9205d82bdcf4886f6742bdc2b4dea146d" + +matcher@^0.1.1: + version "0.1.2" + resolved "https://registry.yarnpkg.com/matcher/-/matcher-0.1.2.tgz#ef20cbde64c24c50cc61af5b83ee0b1b8ff00101" + dependencies: + escape-string-regexp "^1.0.4" + +md5-hex@^1.2.0, md5-hex@^1.3.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/md5-hex/-/md5-hex-1.3.0.tgz#d2c4afe983c4370662179b8cad145219135046c4" + dependencies: + md5-o-matic "^0.1.1" + +md5-hex@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/md5-hex/-/md5-hex-2.0.0.tgz#d0588e9f1c74954492ecd24ac0ac6ce997d92e33" + dependencies: + md5-o-matic "^0.1.1" + +md5-o-matic@^0.1.1: + version "0.1.1" + resolved "https://registry.yarnpkg.com/md5-o-matic/-/md5-o-matic-0.1.1.tgz#822bccd65e117c514fab176b25945d54100a03c3" + +meow@^3.7.0: + version "3.7.0" + resolved "https://registry.yarnpkg.com/meow/-/meow-3.7.0.tgz#72cb668b425228290abbfa856892587308a801fb" + dependencies: + camelcase-keys "^2.0.0" + decamelize "^1.1.2" + loud-rejection "^1.0.0" + map-obj "^1.0.1" + minimist "^1.1.3" + normalize-package-data "^2.3.4" + object-assign "^4.0.1" + read-pkg-up "^1.0.1" + redent "^1.0.0" + trim-newlines "^1.0.0" + +merge-source-map@^1.0.2: + version "1.0.3" + resolved "https://registry.yarnpkg.com/merge-source-map/-/merge-source-map-1.0.3.tgz#da1415f2722a5119db07b14c4f973410863a2abf" + dependencies: + source-map "^0.5.3" + +micromatch@^2.1.5, micromatch@^2.3.11: + version "2.3.11" + resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-2.3.11.tgz#86677c97d1720b363431d04d0d15293bd38c1565" + dependencies: + arr-diff "^2.0.0" + array-unique "^0.2.1" + braces "^1.8.2" + expand-brackets "^0.1.4" + extglob "^0.3.1" + filename-regex "^2.0.0" + is-extglob "^1.0.0" + is-glob "^2.0.1" + kind-of "^3.0.2" + normalize-path "^2.0.1" + object.omit "^2.0.0" + parse-glob "^3.0.4" + regex-cache "^0.4.2" + +mime-db@~1.27.0: + version "1.27.0" + resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.27.0.tgz#820f572296bbd20ec25ed55e5b5de869e5436eb1" + +mime-types@^2.1.12, mime-types@~2.1.7: + version "2.1.15" + resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.15.tgz#a4ebf5064094569237b8cf70046776d09fc92aed" + dependencies: + mime-db "~1.27.0" + +mimic-fn@^1.0.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/mimic-fn/-/mimic-fn-1.1.0.tgz#e667783d92e89dbd342818b5230b9d62a672ad18" + +minimatch@^3.0.0, minimatch@^3.0.2, minimatch@^3.0.3: version "3.0.3" resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.0.3.tgz#2a4e4090b96b2db06a9d7df01055a62a77c9b774" dependencies: brace-expansion "^1.0.0" -minimist@0.0.8: +minimist@0.0.8, minimist@~0.0.1: version "0.0.8" resolved "https://registry.yarnpkg.com/minimist/-/minimist-0.0.8.tgz#857fcabfc3397d2625b8228262e86aa7a011b05d" -mkdirp@0.5.1, mkdirp@^0.5.0, mkdirp@^0.5.1: +minimist@^1.1.3, minimist@^1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.0.tgz#a35008b20f41383eec1fb914f4cd5df79a264284" + +"mkdirp@>=0.5 0", mkdirp@^0.5.0, mkdirp@^0.5.1: version "0.5.1" resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.5.1.tgz#30057438eac6cf7f8c4767f38648d6697d75c903" dependencies: minimist "0.0.8" -mocha@^3.2.0: - version "3.2.0" - resolved "https://registry.yarnpkg.com/mocha/-/mocha-3.2.0.tgz#7dc4f45e5088075171a68896814e6ae9eb7a85e3" - dependencies: - browser-stdout "1.3.0" - commander "2.9.0" - debug "2.2.0" - diff "1.4.0" - escape-string-regexp "1.0.5" - glob "7.0.5" - growl "1.9.2" - json3 "3.3.2" - lodash.create "3.1.1" - mkdirp "0.5.1" - supports-color "3.1.2" - ms@0.7.1: version "0.7.1" resolved "https://registry.yarnpkg.com/ms/-/ms-0.7.1.tgz#9cd13c03adbff25b65effde7ce864ee952017098" -ms@0.7.2: +ms@0.7.2, ms@^0.7.1: version "0.7.2" resolved "https://registry.yarnpkg.com/ms/-/ms-0.7.2.tgz#ae25cf2512b3885a1d95d7f037868d8431124765" +multimatch@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/multimatch/-/multimatch-2.1.0.tgz#9c7906a22fb4c02919e2f5f75161b4cdbd4b2a2b" + dependencies: + array-differ "^1.0.0" + array-union "^1.0.1" + arrify "^1.0.0" + minimatch "^3.0.0" + mute-stream@0.0.5: version "0.0.5" resolved "https://registry.yarnpkg.com/mute-stream/-/mute-stream-0.0.5.tgz#8fbfabb0a98a253d3184331f9e8deb7372fac6c0" +nan@^2.3.0: + version "2.6.2" + resolved "https://registry.yarnpkg.com/nan/-/nan-2.6.2.tgz#e4ff34e6c95fdfb5aecc08de6596f43605a7db45" + natural-compare@^1.4.0: version "1.4.0" resolved "https://registry.yarnpkg.com/natural-compare/-/natural-compare-1.4.0.tgz#4abebfeed7541f2c27acfb29bdbbd15c8d5ba4f7" +node-pre-gyp@^0.6.29: + version "0.6.34" + resolved "https://registry.yarnpkg.com/node-pre-gyp/-/node-pre-gyp-0.6.34.tgz#94ad1c798a11d7fc67381b50d47f8cc18d9799f7" + dependencies: + mkdirp "^0.5.1" + nopt "^4.0.1" + npmlog "^4.0.2" + rc "^1.1.7" + request "^2.81.0" + rimraf "^2.6.1" + semver "^5.3.0" + tar "^2.2.1" + tar-pack "^3.4.0" + +nopt@^4.0.1: + version "4.0.1" + resolved "https://registry.yarnpkg.com/nopt/-/nopt-4.0.1.tgz#d0d4685afd5415193c8c7505602d0d17cd64474d" + dependencies: + abbrev "1" + osenv "^0.1.4" + +normalize-package-data@^2.3.2, normalize-package-data@^2.3.4: + version "2.3.8" + resolved "https://registry.yarnpkg.com/normalize-package-data/-/normalize-package-data-2.3.8.tgz#d819eda2a9dedbd1ffa563ea4071d936782295bb" + dependencies: + hosted-git-info "^2.1.4" + is-builtin-module "^1.0.0" + semver "2 || 3 || 4 || 5" + validate-npm-package-license "^3.0.1" + +normalize-path@^2.0.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/normalize-path/-/normalize-path-2.1.1.tgz#1ab28b556e198363a8c1a6f7e6fa20137fe6aed9" + dependencies: + remove-trailing-separator "^1.0.1" + +npm-run-path@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/npm-run-path/-/npm-run-path-1.0.0.tgz#f5c32bf595fe81ae927daec52e82f8b000ac3c8f" + dependencies: + path-key "^1.0.0" + +npm-run-path@^2.0.0: + version "2.0.2" + resolved "https://registry.yarnpkg.com/npm-run-path/-/npm-run-path-2.0.2.tgz#35a9232dfa35d7067b4cb2ddf2357b1871536c5f" + dependencies: + path-key "^2.0.0" + +npmlog@^4.0.2: + version "4.1.0" + resolved "https://registry.yarnpkg.com/npmlog/-/npmlog-4.1.0.tgz#dc59bee85f64f00ed424efb2af0783df25d1c0b5" + dependencies: + are-we-there-yet "~1.1.2" + console-control-strings "~1.1.0" + gauge "~2.7.3" + set-blocking "~2.0.0" + number-is-nan@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/number-is-nan/-/number-is-nan-1.0.1.tgz#097b602b53422a522c1afb8790318336941a011d" +nyc@^10.3.2: + version "10.3.2" + resolved "https://registry.yarnpkg.com/nyc/-/nyc-10.3.2.tgz#f27f4d91f2a9db36c24f574ff5c6efff0233de46" + dependencies: + archy "^1.0.0" + arrify "^1.0.1" + caching-transform "^1.0.0" + convert-source-map "^1.3.0" + debug-log "^1.0.1" + default-require-extensions "^1.0.0" + find-cache-dir "^0.1.1" + find-up "^1.1.2" + foreground-child "^1.5.3" + glob "^7.0.6" + istanbul-lib-coverage "^1.1.0" + istanbul-lib-hook "^1.0.6" + istanbul-lib-instrument "^1.7.1" + istanbul-lib-report "^1.1.0" + istanbul-lib-source-maps "^1.2.0" + istanbul-reports "^1.1.0" + md5-hex "^1.2.0" + merge-source-map "^1.0.2" + micromatch "^2.3.11" + mkdirp "^0.5.0" + resolve-from "^2.0.0" + rimraf "^2.5.4" + signal-exit "^3.0.1" + spawn-wrap "1.2.4" + test-exclude "^4.1.0" + yargs "^7.1.0" + yargs-parser "^5.0.0" + +oauth-sign@~0.8.1: + version "0.8.2" + resolved "https://registry.yarnpkg.com/oauth-sign/-/oauth-sign-0.8.2.tgz#46a6ab7f0aead8deae9ec0565780b7d4efeb9d43" + object-assign@^4.0.1, object-assign@^4.1.0: version "4.1.1" resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-4.1.1.tgz#2109adc7965887cfc05cbbd442cac8bfbb360863" -once@^1.3.0: +object.omit@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/object.omit/-/object.omit-2.0.1.tgz#1a9c744829f39dbb858c76ca3579ae2a54ebd1fa" + dependencies: + for-own "^0.1.4" + is-extendable "^0.1.1" + +observable-to-promise@^0.5.0: + version "0.5.0" + resolved "https://registry.yarnpkg.com/observable-to-promise/-/observable-to-promise-0.5.0.tgz#c828f0f0dc47e9f86af8a4977c5d55076ce7a91f" + dependencies: + is-observable "^0.2.0" + symbol-observable "^1.0.4" + +once@^1.3.0, once@^1.3.3: version "1.4.0" resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1" dependencies: @@ -1506,6 +2956,25 @@ onetime@^1.0.0: version "1.1.0" resolved "https://registry.yarnpkg.com/onetime/-/onetime-1.1.0.tgz#a1f7838f8314c516f05ecefcbc4ccfe04b4ed789" +onetime@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/onetime/-/onetime-2.0.1.tgz#067428230fd67443b2794b22bba528b6867962d4" + dependencies: + mimic-fn "^1.0.0" + +optimist@^0.6.1: + version "0.6.1" + resolved "https://registry.yarnpkg.com/optimist/-/optimist-0.6.1.tgz#da3ea74686fa21a19a111c326e90eb15a0196686" + dependencies: + minimist "~0.0.1" + wordwrap "~0.0.2" + +option-chain@^0.1.0: + version "0.1.1" + resolved "https://registry.yarnpkg.com/option-chain/-/option-chain-0.1.1.tgz#e9b811e006f1c0f54802f28295bfc8970f8dcfbd" + dependencies: + object-assign "^4.0.1" + optionator@^0.8.2: version "0.8.2" resolved "https://registry.yarnpkg.com/optionator/-/optionator-0.8.2.tgz#364c5e409d3f4d6301d6c0b4c05bba50180aeb64" @@ -1517,20 +2986,98 @@ optionator@^0.8.2: type-check "~0.3.2" wordwrap "~1.0.0" -os-homedir@^1.0.0: +os-homedir@^1.0.0, os-homedir@^1.0.1: version "1.0.2" resolved "https://registry.yarnpkg.com/os-homedir/-/os-homedir-1.0.2.tgz#ffbc4988336e0e833de0c168c7ef152121aa7fb3" -os-tmpdir@^1.0.1: +os-locale@^1.4.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/os-locale/-/os-locale-1.4.0.tgz#20f9f17ae29ed345e8bde583b13d2009803c14d9" + dependencies: + lcid "^1.0.0" + +os-tmpdir@^1.0.0, os-tmpdir@^1.0.1: version "1.0.2" resolved "https://registry.yarnpkg.com/os-tmpdir/-/os-tmpdir-1.0.2.tgz#bbe67406c79aa85c5cfec766fe5734555dfa1274" +osenv@^0.1.4: + version "0.1.4" + resolved "https://registry.yarnpkg.com/osenv/-/osenv-0.1.4.tgz#42fe6d5953df06c8064be6f176c3d05aaaa34644" + dependencies: + os-homedir "^1.0.0" + os-tmpdir "^1.0.0" + +p-finally@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/p-finally/-/p-finally-1.0.0.tgz#3fbcfb15b899a44123b34b6dcc18b724336a2cae" + +p-limit@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-1.1.0.tgz#b07ff2d9a5d88bec806035895a2bab66a27988bc" + +p-locate@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-2.0.0.tgz#20a0103b222a70c8fd39cc2e580680f3dde5ec43" + dependencies: + p-limit "^1.1.0" + +package-hash@^1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/package-hash/-/package-hash-1.2.0.tgz#003e56cd57b736a6ed6114cc2b81542672770e44" + dependencies: + md5-hex "^1.3.0" + +package-hash@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/package-hash/-/package-hash-2.0.0.tgz#78ae326c89e05a4d813b68601977af05c00d2a0d" + dependencies: + graceful-fs "^4.1.11" + lodash.flattendeep "^4.4.0" + md5-hex "^2.0.0" + release-zalgo "^1.0.0" + +package-json@^4.0.0: + version "4.0.1" + resolved "https://registry.yarnpkg.com/package-json/-/package-json-4.0.1.tgz#8869a0401253661c4c4ca3da6c2121ed555f5eed" + dependencies: + got "^6.7.1" + registry-auth-token "^3.0.1" + registry-url "^3.0.3" + semver "^5.1.0" + +parse-glob@^3.0.4: + version "3.0.4" + resolved "https://registry.yarnpkg.com/parse-glob/-/parse-glob-3.0.4.tgz#b2c376cfb11f35513badd173ef0bb6e3a388391c" + dependencies: + glob-base "^0.3.0" + is-dotfile "^1.0.0" + is-extglob "^1.0.0" + is-glob "^2.0.0" + +parse-json@^2.2.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/parse-json/-/parse-json-2.2.0.tgz#f480f40434ef80741f8469099f8dea18f55a4dc9" + dependencies: + error-ex "^1.2.0" + +parse-ms@^0.1.0: + version "0.1.2" + resolved "https://registry.yarnpkg.com/parse-ms/-/parse-ms-0.1.2.tgz#dd3fa25ed6c2efc7bdde12ad9b46c163aa29224e" + +parse-ms@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/parse-ms/-/parse-ms-1.0.1.tgz#56346d4749d78f23430ca0c713850aef91aa361d" + path-exists@^2.0.0: version "2.1.0" resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-2.1.0.tgz#0feb6c64f0fc518d9a754dd5efb62c7022761f4b" dependencies: pinkie-promise "^2.0.0" +path-exists@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-3.0.0.tgz#ce0ebeaa5f78cb18925ea7d810d7b59b010fd515" + path-is-absolute@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f" @@ -1539,24 +3086,67 @@ path-is-inside@^1.0.1: version "1.0.2" resolved "https://registry.yarnpkg.com/path-is-inside/-/path-is-inside-1.0.2.tgz#365417dede44430d1c11af61027facf074bdfc53" +path-key@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/path-key/-/path-key-1.0.0.tgz#5d53d578019646c0d68800db4e146e6bdc2ac7af" + +path-key@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/path-key/-/path-key-2.0.1.tgz#411cadb574c5a140d3a4b1910d40d80cc9f40b40" + path-parse@^1.0.5: version "1.0.5" resolved "https://registry.yarnpkg.com/path-parse/-/path-parse-1.0.5.tgz#3c1adf871ea9cd6c9431b6ea2bd74a0ff055c4c1" -pify@^2.0.0: +path-type@^1.0.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/path-type/-/path-type-1.1.0.tgz#59c44f7ee491da704da415da5a4070ba4f8fe441" + dependencies: + graceful-fs "^4.1.2" + pify "^2.0.0" + pinkie-promise "^2.0.0" + +path-type@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/path-type/-/path-type-2.0.0.tgz#f012ccb8415b7096fc2daa1054c3d72389594c73" + dependencies: + pify "^2.0.0" + +performance-now@^0.2.0: + version "0.2.0" + resolved "https://registry.yarnpkg.com/performance-now/-/performance-now-0.2.0.tgz#33ef30c5c77d4ea21c5a53869d91b56d8f2555e5" + +pify@^2.0.0, pify@^2.3.0: version "2.3.0" resolved "https://registry.yarnpkg.com/pify/-/pify-2.3.0.tgz#ed141a6ac043a849ea588498e7dca8b15330e90c" +pinkie-promise@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/pinkie-promise/-/pinkie-promise-1.0.0.tgz#d1da67f5482563bb7cf57f286ae2822ecfbf3670" + dependencies: + pinkie "^1.0.0" + pinkie-promise@^2.0.0: version "2.0.1" resolved "https://registry.yarnpkg.com/pinkie-promise/-/pinkie-promise-2.0.1.tgz#2135d6dfa7a358c069ac9b178776288228450ffa" dependencies: pinkie "^2.0.0" +pinkie@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/pinkie/-/pinkie-1.0.0.tgz#5a47f28ba1015d0201bda7bf0f358e47bec8c7e4" + pinkie@^2.0.0: version "2.0.4" resolved "https://registry.yarnpkg.com/pinkie/-/pinkie-2.0.4.tgz#72556b80cfa0d48a974e80e77248e80ed4f7f870" +pkg-conf@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/pkg-conf/-/pkg-conf-2.0.0.tgz#071c87650403bccfb9c627f58751bfe47c067279" + dependencies: + find-up "^2.0.0" + load-json-file "^2.0.0" + pkg-dir@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/pkg-dir/-/pkg-dir-1.0.0.tgz#7a4b508a8d5bb2d629d447056ff4e9c9314cf3d4" @@ -1569,6 +3159,16 @@ pkg-up@^1.0.0: dependencies: find-up "^1.0.0" +plur@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/plur/-/plur-1.0.0.tgz#db85c6814f5e5e5a3b49efc28d604fec62975156" + +plur@^2.0.0: + version "2.1.2" + resolved "https://registry.yarnpkg.com/plur/-/plur-2.1.2.tgz#7482452c1a0f508e3e344eaec312c91c29dc655a" + dependencies: + irregular-plurals "^1.0.0" + pluralize@^1.2.1: version "1.2.1" resolved "https://registry.yarnpkg.com/pluralize/-/pluralize-1.2.1.tgz#d1a21483fd22bb41e58a12fa3421823140897c45" @@ -1577,6 +3177,34 @@ prelude-ls@~1.1.2: version "1.1.2" resolved "https://registry.yarnpkg.com/prelude-ls/-/prelude-ls-1.1.2.tgz#21932a549f5e52ffd9a827f570e04be62a97da54" +prepend-http@^1.0.1: + version "1.0.4" + resolved "https://registry.yarnpkg.com/prepend-http/-/prepend-http-1.0.4.tgz#d4f4562b0ce3696e41ac52d0e002e57a635dc6dc" + +preserve@^0.2.0: + version "0.2.0" + resolved "https://registry.yarnpkg.com/preserve/-/preserve-0.2.0.tgz#815ed1f6ebc65926f865b310c0713bcb3315ce4b" + +pretty-format@^19.0.0: + version "19.0.0" + resolved "https://registry.yarnpkg.com/pretty-format/-/pretty-format-19.0.0.tgz#56530d32acb98a3fa4851c4e2b9d37b420684c84" + dependencies: + ansi-styles "^3.0.0" + +pretty-ms@^0.2.1: + version "0.2.2" + resolved "https://registry.yarnpkg.com/pretty-ms/-/pretty-ms-0.2.2.tgz#da879a682ff33a37011046f13d627f67c73b84f6" + dependencies: + parse-ms "^0.1.0" + +pretty-ms@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/pretty-ms/-/pretty-ms-2.1.0.tgz#4257c256df3fb0b451d6affaab021884126981dc" + dependencies: + is-finite "^1.0.1" + parse-ms "^1.0.0" + plur "^1.0.0" + private@^0.1.6: version "0.1.7" resolved "https://registry.yarnpkg.com/private/-/private-0.1.7.tgz#68ce5e8a1ef0a23bb570cc28537b5332aba63ef1" @@ -1589,7 +3217,65 @@ progress@^1.1.8: version "1.1.8" resolved "https://registry.yarnpkg.com/progress/-/progress-1.1.8.tgz#e260c78f6161cdd9b0e56cc3e0a85de17c7a57be" -readable-stream@^2.2.2: +pseudomap@^1.0.1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/pseudomap/-/pseudomap-1.0.2.tgz#f052a28da70e618917ef0a8ac34c1ae5a68286b3" + +punycode@^1.4.1: + version "1.4.1" + resolved "https://registry.yarnpkg.com/punycode/-/punycode-1.4.1.tgz#c0d5a63b2718800ad8e1eb0fa5269c84dd41845e" + +qs@~6.4.0: + version "6.4.0" + resolved "https://registry.yarnpkg.com/qs/-/qs-6.4.0.tgz#13e26d28ad6b0ffaa91312cd3bf708ed351e7233" + +randomatic@^1.1.3: + version "1.1.6" + resolved "https://registry.yarnpkg.com/randomatic/-/randomatic-1.1.6.tgz#110dcabff397e9dcff7c0789ccc0a49adf1ec5bb" + dependencies: + is-number "^2.0.2" + kind-of "^3.0.2" + +rc@^1.0.1, rc@^1.1.6, rc@^1.1.7: + version "1.2.1" + resolved "https://registry.yarnpkg.com/rc/-/rc-1.2.1.tgz#2e03e8e42ee450b8cb3dce65be1bf8974e1dfd95" + dependencies: + deep-extend "~0.4.0" + ini "~1.3.0" + minimist "^1.2.0" + strip-json-comments "~2.0.1" + +read-pkg-up@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/read-pkg-up/-/read-pkg-up-1.0.1.tgz#9d63c13276c065918d57f002a57f40a1b643fb02" + dependencies: + find-up "^1.0.0" + read-pkg "^1.0.0" + +read-pkg-up@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/read-pkg-up/-/read-pkg-up-2.0.0.tgz#6b72a8048984e0c41e79510fd5e9fa99b3b549be" + dependencies: + find-up "^2.0.0" + read-pkg "^2.0.0" + +read-pkg@^1.0.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/read-pkg/-/read-pkg-1.1.0.tgz#f5ffaa5ecd29cb31c0474bca7d756b6bb29e3f28" + dependencies: + load-json-file "^1.0.0" + normalize-package-data "^2.3.2" + path-type "^1.0.0" + +read-pkg@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/read-pkg/-/read-pkg-2.0.0.tgz#8ef1c0623c6a6db0dc6713c4bfac46332b2368f8" + dependencies: + load-json-file "^2.0.0" + normalize-package-data "^2.3.2" + path-type "^2.0.0" + +readable-stream@^2.0.2, readable-stream@^2.0.6, readable-stream@^2.1.4, readable-stream@^2.1.5, readable-stream@^2.2.2: version "2.2.6" resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.2.6.tgz#8b43aed76e71483938d12a8d46c6cf1a00b1f816" dependencies: @@ -1601,6 +3287,15 @@ readable-stream@^2.2.2: string_decoder "~0.10.x" util-deprecate "~1.0.1" +readdirp@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/readdirp/-/readdirp-2.1.0.tgz#4ed0ad060df3073300c48440373f72d1cc642d78" + dependencies: + graceful-fs "^4.1.2" + minimatch "^3.0.2" + readable-stream "^2.0.2" + set-immediate-shim "^1.0.1" + readline2@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/readline2/-/readline2-1.0.1.tgz#41059608ffc154757b715d9989d199ffbf372e35" @@ -1615,6 +3310,13 @@ rechoir@^0.6.2: dependencies: resolve "^1.1.6" +redent@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/redent/-/redent-1.0.0.tgz#cf916ab1fd5f1f16dfb20822dd6ec7f730c2afde" + dependencies: + indent-string "^2.1.0" + strip-indent "^1.0.1" + regenerate@^1.2.1: version "1.3.2" resolved "https://registry.yarnpkg.com/regenerate/-/regenerate-1.3.2.tgz#d1941c67bad437e1be76433add5b385f95b19260" @@ -1631,6 +3333,13 @@ regenerator-transform@0.9.8: babel-types "^6.19.0" private "^0.1.6" +regex-cache@^0.4.2: + version "0.4.3" + resolved "https://registry.yarnpkg.com/regex-cache/-/regex-cache-0.4.3.tgz#9b1a6c35d4d0dfcef5711ae651e8e9d3d7114145" + dependencies: + is-equal-shallow "^0.1.3" + is-primitive "^2.0.0" + regexpu-core@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/regexpu-core/-/regexpu-core-2.0.0.tgz#49d038837b8dcf8bfa5b9a42139938e6ea2ae240" @@ -1639,6 +3348,19 @@ regexpu-core@^2.0.0: regjsgen "^0.2.0" regjsparser "^0.1.4" +registry-auth-token@^3.0.1: + version "3.3.1" + resolved "https://registry.yarnpkg.com/registry-auth-token/-/registry-auth-token-3.3.1.tgz#fb0d3289ee0d9ada2cbb52af5dfe66cb070d3006" + dependencies: + rc "^1.1.6" + safe-buffer "^5.0.1" + +registry-url@^3.0.3: + version "3.1.0" + resolved "https://registry.yarnpkg.com/registry-url/-/registry-url-3.1.0.tgz#3d4ef870f73dde1d77f0cf9a381432444e174942" + dependencies: + rc "^1.0.1" + regjsgen@^0.2.0: version "0.2.0" resolved "https://registry.yarnpkg.com/regjsgen/-/regjsgen-0.2.0.tgz#6c016adeac554f75823fe37ac05b92d5a4edb1f7" @@ -1649,12 +3371,69 @@ regjsparser@^0.1.4: dependencies: jsesc "~0.5.0" +release-zalgo@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/release-zalgo/-/release-zalgo-1.0.0.tgz#09700b7e5074329739330e535c5a90fb67851730" + dependencies: + es6-error "^4.0.1" + +remove-trailing-separator@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/remove-trailing-separator/-/remove-trailing-separator-1.0.1.tgz#615ebb96af559552d4bf4057c8436d486ab63cc4" + +repeat-element@^1.1.2: + version "1.1.2" + resolved "https://registry.yarnpkg.com/repeat-element/-/repeat-element-1.1.2.tgz#ef089a178d1483baae4d93eb98b4f9e4e11d990a" + +repeat-string@^1.5.2: + version "1.6.1" + resolved "https://registry.yarnpkg.com/repeat-string/-/repeat-string-1.6.1.tgz#8dcae470e1c88abc2d600fff4a776286da75e637" + repeating@^2.0.0: version "2.0.1" resolved "https://registry.yarnpkg.com/repeating/-/repeating-2.0.1.tgz#5214c53a926d3552707527fbab415dbc08d06dda" dependencies: is-finite "^1.0.0" +request@^2.81.0: + version "2.81.0" + resolved "https://registry.yarnpkg.com/request/-/request-2.81.0.tgz#c6928946a0e06c5f8d6f8a9333469ffda46298a0" + dependencies: + aws-sign2 "~0.6.0" + aws4 "^1.2.1" + caseless "~0.12.0" + combined-stream "~1.0.5" + extend "~3.0.0" + forever-agent "~0.6.1" + form-data "~2.1.1" + har-validator "~4.2.1" + hawk "~3.1.3" + http-signature "~1.1.0" + is-typedarray "~1.0.0" + isstream "~0.1.2" + json-stringify-safe "~5.0.1" + mime-types "~2.1.7" + oauth-sign "~0.8.1" + performance-now "^0.2.0" + qs "~6.4.0" + safe-buffer "^5.0.1" + stringstream "~0.0.4" + tough-cookie "~2.3.0" + tunnel-agent "^0.6.0" + uuid "^3.0.0" + +require-directory@^2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/require-directory/-/require-directory-2.1.1.tgz#8c64ad5fd30dab1c976e2344ffe7f792a6a6df42" + +require-main-filename@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/require-main-filename/-/require-main-filename-1.0.1.tgz#97f717b69d48784f5f526a6c5aa8ffdda055a4d1" + +require-precompiled@^0.1.0: + version "0.1.0" + resolved "https://registry.yarnpkg.com/require-precompiled/-/require-precompiled-0.1.0.tgz#5a1b52eb70ebed43eb982e974c85ab59571e56fa" + require-uncached@^1.0.2: version "1.0.3" resolved "https://registry.yarnpkg.com/require-uncached/-/require-uncached-1.0.3.tgz#4e0d56d6c9662fd31e43011c4b95aa49955421d3" @@ -1662,10 +3441,20 @@ require-uncached@^1.0.2: caller-path "^0.1.0" resolve-from "^1.0.0" +resolve-cwd@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/resolve-cwd/-/resolve-cwd-1.0.0.tgz#4eaeea41ed040d1702457df64a42b2b07d246f9f" + dependencies: + resolve-from "^2.0.0" + resolve-from@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-1.0.1.tgz#26cbfe935d1aeeeabb29bc3fe5aeb01e93d44226" +resolve-from@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-2.0.0.tgz#9480ab20e94ffa1d9e80a804c7ea147611966b57" + resolve@1.1.7: version "1.1.7" resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.1.7.tgz#203114d82ad2c5ed9e8e0411b3932875e889e97b" @@ -1683,7 +3472,20 @@ restore-cursor@^1.0.1: exit-hook "^1.0.0" onetime "^1.0.0" -rimraf@^2.2.8: +restore-cursor@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/restore-cursor/-/restore-cursor-2.0.0.tgz#9f7ee287f82fd326d4fd162923d62129eee0dfaf" + dependencies: + onetime "^2.0.0" + signal-exit "^3.0.2" + +right-align@^0.1.1: + version "0.1.3" + resolved "https://registry.yarnpkg.com/right-align/-/right-align-0.1.3.tgz#61339b722fe6a3515689210d24e14c96148613ef" + dependencies: + align-text "^0.1.1" + +rimraf@2, rimraf@^2.2.8, rimraf@^2.3.3, rimraf@^2.5.1, rimraf@^2.5.4, rimraf@^2.6.1: version "2.6.1" resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.6.1.tgz#c2338ec643df7a1b7fe5c54fa86f57428a55f33d" dependencies: @@ -1737,10 +3539,32 @@ rx-lite@^3.1.2: version "3.1.2" resolved "https://registry.yarnpkg.com/rx-lite/-/rx-lite-3.1.2.tgz#19ce502ca572665f3b647b10939f97fd1615f102" +safe-buffer@^5.0.1: + version "5.0.1" + resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.0.1.tgz#d263ca54696cd8a306b5ca6551e92de57918fbe7" + samsam@1.1.2, samsam@~1.1: version "1.1.2" resolved "https://registry.yarnpkg.com/samsam/-/samsam-1.1.2.tgz#bec11fdc83a9fda063401210e40176c3024d1567" +semver-diff@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/semver-diff/-/semver-diff-2.1.0.tgz#4bbb8437c8d37e4b0cf1a68fd726ec6d645d6d36" + dependencies: + semver "^5.0.3" + +"semver@2 || 3 || 4 || 5", semver@^5.0.3, semver@^5.1.0, semver@^5.3.0: + version "5.3.0" + resolved "https://registry.yarnpkg.com/semver/-/semver-5.3.0.tgz#9b2ce5d3de02d17c6012ad326aa6b4d0cf54f94f" + +set-blocking@^2.0.0, set-blocking@~2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/set-blocking/-/set-blocking-2.0.0.tgz#045f9782d011ae9a6803ddd382b24392b3d890f7" + +set-immediate-shim@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/set-immediate-shim/-/set-immediate-shim-1.0.1.tgz#4b2b1b27eb808a9f8dcc481a58e5e56f599f3f61" + shelljs@^0.7.5: version "0.7.7" resolved "https://registry.yarnpkg.com/shelljs/-/shelljs-0.7.7.tgz#b2f5c77ef97148f4b4f6e22682e10bba8667cff1" @@ -1749,9 +3573,13 @@ shelljs@^0.7.5: interpret "^1.0.0" rechoir "^0.6.2" -sinon-chai@^2.8.0: - version "2.9.0" - resolved "https://registry.yarnpkg.com/sinon-chai/-/sinon-chai-2.9.0.tgz#34d820042bc9661a14527130d401eb462c49bb84" +signal-exit@^2.0.0: + version "2.1.2" + resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-2.1.2.tgz#375879b1f92ebc3b334480d038dc546a6d558564" + +signal-exit@^3.0.0, signal-exit@^3.0.1, signal-exit@^3.0.2: + version "3.0.2" + resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.2.tgz#b5fdc08f1287ea1178628e415e25132b73646c6d" sinon@^1.17.7: version "1.17.7" @@ -1770,21 +3598,87 @@ slice-ansi@0.0.4: version "0.0.4" resolved "https://registry.yarnpkg.com/slice-ansi/-/slice-ansi-0.0.4.tgz#edbf8903f66f7ce2f8eafd6ceed65e264c831b35" +slide@^1.1.5: + version "1.1.6" + resolved "https://registry.yarnpkg.com/slide/-/slide-1.1.6.tgz#56eb027d65b4d2dce6cb2e2d32c4d4afc9e1d707" + +sntp@1.x.x: + version "1.0.9" + resolved "https://registry.yarnpkg.com/sntp/-/sntp-1.0.9.tgz#6541184cc90aeea6c6e7b35e2659082443c66198" + dependencies: + hoek "2.x.x" + +sort-keys@^1.1.1, sort-keys@^1.1.2: + version "1.1.2" + resolved "https://registry.yarnpkg.com/sort-keys/-/sort-keys-1.1.2.tgz#441b6d4d346798f1b4e49e8920adfba0e543f9ad" + dependencies: + is-plain-obj "^1.0.0" + source-map-support@^0.4.0, source-map-support@^0.4.2: version "0.4.14" resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.4.14.tgz#9d4463772598b86271b4f523f6c1f4e02a7d6aef" dependencies: source-map "^0.5.6" -source-map@^0.5.0, source-map@^0.5.6: +source-map@^0.4.4: + version "0.4.4" + resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.4.4.tgz#eba4f5da9c0dc999de68032d8b4f76173652036b" + dependencies: + amdefine ">=0.0.4" + +source-map@^0.5.0, source-map@^0.5.3, source-map@^0.5.6, source-map@~0.5.1: version "0.5.6" resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.5.6.tgz#75ce38f52bf0733c5a7f0c118d81334a2bb5f412" +spawn-wrap@1.2.4: + version "1.2.4" + resolved "https://registry.yarnpkg.com/spawn-wrap/-/spawn-wrap-1.2.4.tgz#920eb211a769c093eebfbd5b0e7a5d2e68ab2e40" + dependencies: + foreground-child "^1.3.3" + mkdirp "^0.5.0" + os-homedir "^1.0.1" + rimraf "^2.3.3" + signal-exit "^2.0.0" + which "^1.2.4" + +spdx-correct@~1.0.0: + version "1.0.2" + resolved "https://registry.yarnpkg.com/spdx-correct/-/spdx-correct-1.0.2.tgz#4b3073d933ff51f3912f03ac5519498a4150db40" + dependencies: + spdx-license-ids "^1.0.2" + +spdx-expression-parse@~1.0.0: + version "1.0.4" + resolved "https://registry.yarnpkg.com/spdx-expression-parse/-/spdx-expression-parse-1.0.4.tgz#9bdf2f20e1f40ed447fbe273266191fced51626c" + +spdx-license-ids@^1.0.2: + version "1.2.2" + resolved "https://registry.yarnpkg.com/spdx-license-ids/-/spdx-license-ids-1.2.2.tgz#c9df7a3424594ade6bd11900d596696dc06bac57" + sprintf-js@~1.0.2: version "1.0.3" resolved "https://registry.yarnpkg.com/sprintf-js/-/sprintf-js-1.0.3.tgz#04e6926f662895354f3dd015203633b857297e2c" -string-width@^1.0.1: +sshpk@^1.7.0: + version "1.13.0" + resolved "https://registry.yarnpkg.com/sshpk/-/sshpk-1.13.0.tgz#ff2a3e4fd04497555fed97b39a0fd82fafb3a33c" + dependencies: + asn1 "~0.2.3" + assert-plus "^1.0.0" + dashdash "^1.12.0" + getpass "^0.1.1" + optionalDependencies: + bcrypt-pbkdf "^1.0.0" + ecc-jsbn "~0.1.1" + jodid25519 "^1.0.0" + jsbn "~0.1.0" + tweetnacl "~0.14.0" + +stack-utils@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/stack-utils/-/stack-utils-1.0.1.tgz#d4f33ab54e8e38778b0ca5cfd3b3afb12db68620" + +string-width@^1.0.1, string-width@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/string-width/-/string-width-1.0.2.tgz#118bdf5b8cdc51a2a7e70d211e07e2b0b9b107d3" dependencies: @@ -1803,30 +3697,68 @@ string_decoder@~0.10.x: version "0.10.31" resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-0.10.31.tgz#62e203bc41766c6c28c9fc84301dab1c5310fa94" -strip-ansi@^3.0.0: +stringstream@~0.0.4: + version "0.0.5" + resolved "https://registry.yarnpkg.com/stringstream/-/stringstream-0.0.5.tgz#4e484cd4de5a0bbbee18e46307710a8a81621878" + +strip-ansi@^3.0.0, strip-ansi@^3.0.1: version "3.0.1" resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-3.0.1.tgz#6a385fb8853d952d5ff05d0e8aaf94278dc63dcf" dependencies: ansi-regex "^2.0.0" +strip-ansi@~0.1.0: + version "0.1.1" + resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-0.1.1.tgz#39e8a98d044d150660abe4a6808acf70bb7bc991" + +strip-bom-buf@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/strip-bom-buf/-/strip-bom-buf-1.0.0.tgz#1cb45aaf57530f4caf86c7f75179d2c9a51dd572" + dependencies: + is-utf8 "^0.2.1" + +strip-bom@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/strip-bom/-/strip-bom-2.0.0.tgz#6219a85616520491f35788bdbf1447a99c7e6b0e" + dependencies: + is-utf8 "^0.2.0" + strip-bom@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/strip-bom/-/strip-bom-3.0.0.tgz#2334c18e9c759f7bdd56fdef7e9ae3d588e68ed3" +strip-eof@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/strip-eof/-/strip-eof-1.0.0.tgz#bb43ff5598a6eb05d89b59fcd129c983313606bf" + +strip-indent@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/strip-indent/-/strip-indent-1.0.1.tgz#0c7962a6adefa7bbd4ac366460a638552ae1a0a2" + dependencies: + get-stdin "^4.0.1" + strip-json-comments@~2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-2.0.1.tgz#3c531942e908c2697c0ec344858c286c7ca0a60a" -supports-color@3.1.2: - version "3.1.2" - resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-3.1.2.tgz#72a262894d9d408b956ca05ff37b2ed8a6e2a2d5" - dependencies: - has-flag "^1.0.0" - supports-color@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-2.0.0.tgz#535d045ce6b6363fa40117084629995e9df324c7" +supports-color@^3.1.2, supports-color@^3.2.3: + version "3.2.3" + resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-3.2.3.tgz#65ac0504b3954171d8a64946b2ae3cbb8a5f54f6" + dependencies: + has-flag "^1.0.0" + +symbol-observable@^0.2.2: + version "0.2.4" + resolved "https://registry.yarnpkg.com/symbol-observable/-/symbol-observable-0.2.4.tgz#95a83db26186d6af7e7a18dbd9760a2f86d08f40" + +symbol-observable@^1.0.4: + version "1.0.4" + resolved "https://registry.yarnpkg.com/symbol-observable/-/symbol-observable-1.0.4.tgz#29bf615d4aa7121bdd898b22d4b3f9bc4e2aa03d" + table@^3.7.8: version "3.8.3" resolved "https://registry.yarnpkg.com/table/-/table-3.8.3.tgz#2bbc542f0fda9861a755d3947fefd8b3f513855f" @@ -1844,18 +3776,85 @@ tailored@2.4.5: dependencies: erlang-types "^1.0.0" -text-table@~0.2.0: +tar-pack@^3.4.0: + version "3.4.0" + resolved "https://registry.yarnpkg.com/tar-pack/-/tar-pack-3.4.0.tgz#23be2d7f671a8339376cbdb0b8fe3fdebf317984" + dependencies: + debug "^2.2.0" + fstream "^1.0.10" + fstream-ignore "^1.0.5" + once "^1.3.3" + readable-stream "^2.1.4" + rimraf "^2.5.1" + tar "^2.2.1" + uid-number "^0.0.6" + +tar@^2.2.1: + version "2.2.1" + resolved "https://registry.yarnpkg.com/tar/-/tar-2.2.1.tgz#8e4d2a256c0e2185c6b18ad694aec968b83cb1d1" + dependencies: + block-stream "*" + fstream "^1.0.2" + inherits "2" + +term-size@^0.1.0: + version "0.1.1" + resolved "https://registry.yarnpkg.com/term-size/-/term-size-0.1.1.tgz#87360b96396cab5760963714cda0d0cbeecad9ca" + dependencies: + execa "^0.4.0" + +test-exclude@^4.1.0: + version "4.1.1" + resolved "https://registry.yarnpkg.com/test-exclude/-/test-exclude-4.1.1.tgz#4d84964b0966b0087ecc334a2ce002d3d9341e26" + dependencies: + arrify "^1.0.1" + micromatch "^2.3.11" + object-assign "^4.1.0" + read-pkg-up "^1.0.1" + require-main-filename "^1.0.1" + +text-table@^0.2.0, text-table@~0.2.0: version "0.2.0" resolved "https://registry.yarnpkg.com/text-table/-/text-table-0.2.0.tgz#7f5ee823ae805207c00af2df4a84ec3fcfa570b4" +through2@^2.0.0: + version "2.0.3" + resolved "https://registry.yarnpkg.com/through2/-/through2-2.0.3.tgz#0004569b37c7c74ba39c43f3ced78d1ad94140be" + dependencies: + readable-stream "^2.1.5" + xtend "~4.0.1" + through@^2.3.6: version "2.3.8" resolved "https://registry.yarnpkg.com/through/-/through-2.3.8.tgz#0dd4c9ffaabc357960b1b724115d7e0e86a2e1f5" +time-require@^0.1.2: + version "0.1.2" + resolved "https://registry.yarnpkg.com/time-require/-/time-require-0.1.2.tgz#f9e12cb370fc2605e11404582ba54ef5ca2b2d98" + dependencies: + chalk "^0.4.0" + date-time "^0.1.1" + pretty-ms "^0.2.1" + text-table "^0.2.0" + +timed-out@^4.0.0: + version "4.0.1" + resolved "https://registry.yarnpkg.com/timed-out/-/timed-out-4.0.1.tgz#f32eacac5a175bea25d7fab565ab3ed8741ef56f" + to-fast-properties@^1.0.1: version "1.0.2" resolved "https://registry.yarnpkg.com/to-fast-properties/-/to-fast-properties-1.0.2.tgz#f3f5c0c3ba7299a7ef99427e44633257ade43320" +tough-cookie@~2.3.0: + version "2.3.2" + resolved "https://registry.yarnpkg.com/tough-cookie/-/tough-cookie-2.3.2.tgz#f081f76e4c85720e6c37a5faced737150d84072a" + dependencies: + punycode "^1.4.1" + +trim-newlines@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/trim-newlines/-/trim-newlines-1.0.0.tgz#5887966bb582a4503a41eb524f7d35011815a613" + trim-right@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/trim-right/-/trim-right-1.0.1.tgz#cb2e1203067e0c8de1f614094b9fe45704ea6003" @@ -1864,24 +3863,84 @@ tryit@^1.0.1: version "1.0.3" resolved "https://registry.yarnpkg.com/tryit/-/tryit-1.0.3.tgz#393be730a9446fd1ead6da59a014308f36c289cb" +tunnel-agent@^0.6.0: + version "0.6.0" + resolved "https://registry.yarnpkg.com/tunnel-agent/-/tunnel-agent-0.6.0.tgz#27a5dea06b36b04a0a9966774b290868f0fc40fd" + dependencies: + safe-buffer "^5.0.1" + +tweetnacl@^0.14.3, tweetnacl@~0.14.0: + version "0.14.5" + resolved "https://registry.yarnpkg.com/tweetnacl/-/tweetnacl-0.14.5.tgz#5ae68177f192d4456269d108afa93ff8743f4f64" + type-check@~0.3.2: version "0.3.2" resolved "https://registry.yarnpkg.com/type-check/-/type-check-0.3.2.tgz#5884cab512cf1d355e3fb784f30804b2b520db72" dependencies: prelude-ls "~1.1.2" -type-detect@0.1.1: - version "0.1.1" - resolved "https://registry.yarnpkg.com/type-detect/-/type-detect-0.1.1.tgz#0ba5ec2a885640e470ea4e8505971900dac58822" - -type-detect@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/type-detect/-/type-detect-1.0.0.tgz#762217cc06db258ec48908a1298e8b95121e8ea2" - typedarray@^0.0.6: version "0.0.6" resolved "https://registry.yarnpkg.com/typedarray/-/typedarray-0.0.6.tgz#867ac74e3864187b1d3d47d996a78ec5c8830777" +uglify-js@^2.6: + version "2.8.27" + resolved "https://registry.yarnpkg.com/uglify-js/-/uglify-js-2.8.27.tgz#47787f912b0f242e5b984343be8e35e95f694c9c" + dependencies: + source-map "~0.5.1" + yargs "~3.10.0" + optionalDependencies: + uglify-to-browserify "~1.0.0" + +uglify-to-browserify@~1.0.0: + version "1.0.2" + resolved "https://registry.yarnpkg.com/uglify-to-browserify/-/uglify-to-browserify-1.0.2.tgz#6e0924d6bda6b5afe349e39a6d632850a0f882b7" + +uid-number@^0.0.6: + version "0.0.6" + resolved "https://registry.yarnpkg.com/uid-number/-/uid-number-0.0.6.tgz#0ea10e8035e8eb5b8e4449f06da1c730663baa81" + +uid2@0.0.3: + version "0.0.3" + resolved "https://registry.yarnpkg.com/uid2/-/uid2-0.0.3.tgz#483126e11774df2f71b8b639dcd799c376162b82" + +unique-string@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/unique-string/-/unique-string-1.0.0.tgz#9e1057cca851abb93398f8b33ae187b99caec11a" + dependencies: + crypto-random-string "^1.0.0" + +unique-temp-dir@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/unique-temp-dir/-/unique-temp-dir-1.0.0.tgz#6dce95b2681ca003eebfb304a415f9cbabcc5385" + dependencies: + mkdirp "^0.5.1" + os-tmpdir "^1.0.1" + uid2 "0.0.3" + +unzip-response@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/unzip-response/-/unzip-response-2.0.1.tgz#d2f0f737d16b0615e72a6935ed04214572d56f97" + +update-notifier@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/update-notifier/-/update-notifier-2.1.0.tgz#ec0c1e53536b76647a24b77cb83966d9315123d9" + dependencies: + boxen "^1.0.0" + chalk "^1.0.0" + configstore "^3.0.0" + is-npm "^1.0.0" + latest-version "^3.0.0" + lazy-req "^2.0.0" + semver-diff "^2.0.0" + xdg-basedir "^3.0.0" + +url-parse-lax@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/url-parse-lax/-/url-parse-lax-1.0.0.tgz#7af8f303645e9bd79a272e7a14ac68bc0609da73" + dependencies: + prepend-http "^1.0.1" + user-home@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/user-home/-/user-home-2.0.0.tgz#9c70bfd8169bc1dcbf48604e0f04b8b49cde9e9f" @@ -1898,20 +3957,153 @@ util-deprecate@~1.0.1: dependencies: inherits "2.0.1" +uuid@^3.0.0: + version "3.0.1" + resolved "https://registry.yarnpkg.com/uuid/-/uuid-3.0.1.tgz#6544bba2dfda8c1cf17e629a3a305e2bb1fee6c1" + +validate-npm-package-license@^3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/validate-npm-package-license/-/validate-npm-package-license-3.0.1.tgz#2804babe712ad3379459acfbe24746ab2c303fbc" + dependencies: + spdx-correct "~1.0.0" + spdx-expression-parse "~1.0.0" + +verror@1.3.6: + version "1.3.6" + resolved "https://registry.yarnpkg.com/verror/-/verror-1.3.6.tgz#cff5df12946d297d2baaefaa2689e25be01c005c" + dependencies: + extsprintf "1.0.2" + +which-module@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/which-module/-/which-module-1.0.0.tgz#bba63ca861948994ff307736089e3b96026c2a4f" + +which@^1.2.4, which@^1.2.8, which@^1.2.9: + version "1.2.14" + resolved "https://registry.yarnpkg.com/which/-/which-1.2.14.tgz#9a87c4378f03e827cecaf1acdf56c736c01c14e5" + dependencies: + isexe "^2.0.0" + +wide-align@^1.1.0: + version "1.1.2" + resolved "https://registry.yarnpkg.com/wide-align/-/wide-align-1.1.2.tgz#571e0f1b0604636ebc0dfc21b0339bbe31341710" + dependencies: + string-width "^1.0.2" + +widest-line@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/widest-line/-/widest-line-1.0.0.tgz#0c09c85c2a94683d0d7eaf8ee097d564bf0e105c" + dependencies: + string-width "^1.0.1" + +window-size@0.1.0: + version "0.1.0" + resolved "https://registry.yarnpkg.com/window-size/-/window-size-0.1.0.tgz#5438cd2ea93b202efa3a19fe8887aee7c94f9c9d" + +wordwrap@0.0.2, wordwrap@~0.0.2: + version "0.0.2" + resolved "https://registry.yarnpkg.com/wordwrap/-/wordwrap-0.0.2.tgz#b79669bb42ecb409f83d583cad52ca17eaa1643f" + wordwrap@~1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/wordwrap/-/wordwrap-1.0.0.tgz#27584810891456a4171c8d0226441ade90cbcaeb" +wrap-ansi@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-2.1.0.tgz#d8fc3d284dd05794fe84973caecdd1cf824fdd85" + dependencies: + string-width "^1.0.1" + strip-ansi "^3.0.1" + wrappy@1: version "1.0.2" resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f" +write-file-atomic@^1.1.4: + version "1.3.4" + resolved "https://registry.yarnpkg.com/write-file-atomic/-/write-file-atomic-1.3.4.tgz#f807a4f0b1d9e913ae7a48112e6cc3af1991b45f" + dependencies: + graceful-fs "^4.1.11" + imurmurhash "^0.1.4" + slide "^1.1.5" + +write-file-atomic@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/write-file-atomic/-/write-file-atomic-2.1.0.tgz#1769f4b551eedce419f0505deae2e26763542d37" + dependencies: + graceful-fs "^4.1.11" + imurmurhash "^0.1.4" + slide "^1.1.5" + +write-json-file@^2.0.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/write-json-file/-/write-json-file-2.2.0.tgz#51862506bbb3b619eefab7859f1fd6c6d0530876" + dependencies: + detect-indent "^5.0.0" + graceful-fs "^4.1.2" + make-dir "^1.0.0" + pify "^2.0.0" + sort-keys "^1.1.1" + write-file-atomic "^2.0.0" + +write-pkg@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/write-pkg/-/write-pkg-2.1.0.tgz#353aa44c39c48c21440f5c08ce6abd46141c9c08" + dependencies: + sort-keys "^1.1.2" + write-json-file "^2.0.0" + write@^0.2.1: version "0.2.1" resolved "https://registry.yarnpkg.com/write/-/write-0.2.1.tgz#5fc03828e264cea3fe91455476f7a3c566cb0757" dependencies: mkdirp "^0.5.1" -xtend@^4.0.0: +xdg-basedir@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/xdg-basedir/-/xdg-basedir-3.0.0.tgz#496b2cc109eca8dbacfe2dc72b603c17c5870ad4" + +xtend@^4.0.0, xtend@~4.0.1: version "4.0.1" resolved "https://registry.yarnpkg.com/xtend/-/xtend-4.0.1.tgz#a5c6d532be656e23db820efb943a1f04998d63af" + +y18n@^3.2.1: + version "3.2.1" + resolved "https://registry.yarnpkg.com/y18n/-/y18n-3.2.1.tgz#6d15fba884c08679c0d77e88e7759e811e07fa41" + +yallist@^2.0.0: + version "2.1.2" + resolved "https://registry.yarnpkg.com/yallist/-/yallist-2.1.2.tgz#1c11f9218f076089a47dd512f93c6699a6a81d52" + +yargs-parser@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-5.0.0.tgz#275ecf0d7ffe05c77e64e7c86e4cd94bf0e1228a" + dependencies: + camelcase "^3.0.0" + +yargs@^7.1.0: + version "7.1.0" + resolved "https://registry.yarnpkg.com/yargs/-/yargs-7.1.0.tgz#6ba318eb16961727f5d284f8ea003e8d6154d0c8" + dependencies: + camelcase "^3.0.0" + cliui "^3.2.0" + decamelize "^1.1.1" + get-caller-file "^1.0.1" + os-locale "^1.4.0" + read-pkg-up "^1.0.1" + require-directory "^2.1.1" + require-main-filename "^1.0.1" + set-blocking "^2.0.0" + string-width "^1.0.2" + which-module "^1.0.0" + y18n "^3.2.1" + yargs-parser "^5.0.0" + +yargs@~3.10.0: + version "3.10.0" + resolved "https://registry.yarnpkg.com/yargs/-/yargs-3.10.0.tgz#f7ee7bd857dd7c1d2d38c0e74efbd681d1431fd1" + dependencies: + camelcase "^1.0.2" + cliui "^2.1.0" + decamelize "^1.0.0" + window-size "0.1.0" From 33fe54e5dc2ffd486bf06b0fcded40a2901a6dac Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Mon, 29 May 2017 10:23:42 -0500 Subject: [PATCH 541/860] Consolidation of protocols --- lib/elixir_script/next/passes/find_used.ex | 43 +++-- lib/elixir_script/next/passes/translate.ex | 5 +- .../next/passes/translate/examples/example.ex | 2 +- .../next/passes/translate/module.ex | 37 ++-- .../next/passes/translate/protocol.ex | 180 ++++++++++++++++++ 5 files changed, 239 insertions(+), 28 deletions(-) create mode 100644 lib/elixir_script/next/passes/translate/protocol.ex diff --git a/lib/elixir_script/next/passes/find_used.ex b/lib/elixir_script/next/passes/find_used.ex index 07cde8f0..43faf4f4 100644 --- a/lib/elixir_script/next/passes/find_used.ex +++ b/lib/elixir_script/next/passes/find_used.ex @@ -69,8 +69,21 @@ defmodule ElixirScript.FindUsed do end defp walk_protocol(module, implementations, pid) do - ModuleState.put_module(pid, module, %{}) - Enum.each(implementations, fn({impl, info}) -> walk_module(impl, info, pid) end) + impls = Enum.map(implementations, fn {impl, %{attributes: attrs}} -> + protocol_impl = Keyword.fetch!(attrs, :protocol_impl) + impl_for = Keyword.fetch!(protocol_impl, :for) + {impl, impl_for} + end) + + first_implementation_functions = implementations |> hd |> elem(1) |> Map.get(:definitions) + + functions = Enum.map(first_implementation_functions, fn { name, _, _, _} -> name end) + + ModuleState.put_module(pid, module, %{protocol: true, impls: impls, functions: functions}) + + Enum.each(implementations, fn {impl, info} -> + walk_module(impl, info, pid) + end) end defp walk({{_name, _arity}, _type, _, clauses}, state) do @@ -105,13 +118,13 @@ defmodule ElixirScript.FindUsed do Enum.each(form, &walk(&1, state)) end - #defp walk(form, state) when is_atom(form) do - #if ElixirScript.Translate.Module.is_elixir_module(form) do - # if ModuleState.get_module(state.pid, form) == nil do - # execute(form, state.pid) - # end - #end - #end + defp walk(form, state) when is_atom(form) and form not in [BitString, Function, PID, Port, Reference, Any, Elixir] do + if ElixirScript.Translate.Module.is_elixir_module(form) do + if ModuleState.get_module(state.pid, form) == nil do + execute(form, state.pid) + end + end + end defp walk({a, b}, state) do walk({:{}, [], [a, b]}, state) @@ -219,6 +232,14 @@ defmodule ElixirScript.FindUsed do Enum.each(clauses, &walk(&1, state)) end + defp walk({{:., _, [:erlang, :apply]}, _, [module, function, params]}, state) do + walk({{:., [], [module, function]}, [], params}, state) + end + + defp walk({{:., _, [:erlang, :apply]}, _, [function, params]}, state) do + walk({function, [], params}, state) + end + defp walk({{:., _, [module, function]}, _, params}, _state) when module in @erlang_modules do IO.inspect {module, function, length(params)} nil @@ -237,11 +258,11 @@ defmodule ElixirScript.FindUsed do nil end - Enum.each(params, &walk(&1, state)) + walk(params, state) end defp walk({:super, _, params}, state) do - Enum.each(params, &walk(&1, state)) + walk(params, state) end defp walk({function, _, params}, state) when is_atom(function) and is_list(params) do diff --git a/lib/elixir_script/next/passes/translate.ex b/lib/elixir_script/next/passes/translate.ex index b32a05bb..8341a30a 100644 --- a/lib/elixir_script/next/passes/translate.ex +++ b/lib/elixir_script/next/passes/translate.ex @@ -11,8 +11,9 @@ defmodule ElixirScript.Translate do """ @spec execute([atom], pid) :: nil def execute(modules, pid) do - Enum.each(modules, fn({module, info}) -> - ElixirScript.Translate.Module.compile(module, info, pid) + Enum.each(modules, fn + {module, info} -> + ElixirScript.Translate.Module.compile(module, info, pid) end) end end diff --git a/lib/elixir_script/next/passes/translate/examples/example.ex b/lib/elixir_script/next/passes/translate/examples/example.ex index 02f457a1..2fc91703 100644 --- a/lib/elixir_script/next/passes/translate/examples/example.ex +++ b/lib/elixir_script/next/passes/translate/examples/example.ex @@ -1,6 +1,6 @@ defmodule Example do def start(_, _) do - Atom.to_string(:gravity) + Base.encode16("Hello") end end diff --git a/lib/elixir_script/next/passes/translate/module.ex b/lib/elixir_script/next/passes/translate/module.ex index 6d3f96bf..eb64d7ad 100644 --- a/lib/elixir_script/next/passes/translate/module.ex +++ b/lib/elixir_script/next/passes/translate/module.ex @@ -9,9 +9,13 @@ defmodule ElixirScript.Translate.Module do Translate the given module's ast to JavaScript AST """ + def compile(module, %{protocol: true} = info, pid) do + ElixirScript.Translate.Protocol.compile(module, info, pid) + end + def compile(module, info, pid) do %{ - attributes: _attrs, + attributes: attrs, compile_opts: _compile_opts, definitions: defs, file: _file, @@ -27,17 +31,22 @@ defmodule ElixirScript.Translate.Module do # Filter so that we only have the # Used functions to compile - used_defs = defs - |> Enum.filter(fn - { _, type, _, _} when type in [:defmacro, :defmacrop] -> false - { name, _, _, _} -> not(name in unreachable) - _ -> true - end) - |> Enum.filter(fn - { {:start, 2}, _, _, _ } -> true - { name, _, _, _} -> name in used - _ -> false - end) + reachable_defs = Enum.filter(defs, fn + { _, type, _, _} when type in [:defmacro, :defmacrop] -> false + { name, _, _, _} -> not(name in unreachable) + _ -> true + end) + + used_defs = if Keyword.has_key?(attrs, :protocol_impl) do + reachable_defs + else + Enum.filter(reachable_defs, fn + { {:start, 2}, _, _, _ } -> true + { name, _, _, _} -> name in used + _ -> false + end) + end + compiled_functions = used_defs |> Enum.map(&Function.compile(&1, state)) @@ -57,8 +66,8 @@ defmodule ElixirScript.Translate.Module do defp make_exports(reachable_defs) do exports = Enum.reduce(reachable_defs, [], fn {{name, arity}, :def, _, _}, list -> - function_name = ElixirScript.Translator.Identifier.make_function_name(name, arity) - list ++ [J.property(function_name, function_name, :init, true)] + function_name = ElixirScript.Translator.Identifier.make_function_name(name, arity) + list ++ [J.property(function_name, function_name, :init, true)] _, list -> list end) diff --git a/lib/elixir_script/next/passes/translate/protocol.ex b/lib/elixir_script/next/passes/translate/protocol.ex new file mode 100644 index 00000000..0b549292 --- /dev/null +++ b/lib/elixir_script/next/passes/translate/protocol.ex @@ -0,0 +1,180 @@ +defmodule ElixirScript.Translate.Protocol do + @moduledoc false + alias ESTree.Tools.Builder, as: J + alias ElixirScript.Translate.Function + alias ElixirScript.Translate.Form + alias ElixirScript.Translator.Identifier + alias ElixirScript.State, as: ModuleState + + + @doc """ + This compiles and consolidates the given protocol + """ + def compile(module, %{protocol: true, impls: impls, functions: functions} = info, pid) do + object = Enum.map(functions, fn {function, arity} -> + {Identifier.make_function_name(function, arity), J.function_expression([], [], J.block_statement([]))} + end) + |> Enum.map(fn({key, value}) -> ElixirScript.Translate.Forms.Map.make_property(key, value) end) + |> J.object_expression + + declarator = J.variable_declarator( + J.identifier("protocol"), + J.call_expression( + J.member_expression( + J.identifier("Bootstrap"), + J.member_expression( + J.identifier(:Core), + J.member_expression( + J.identifier(:Functions), + J.identifier(:defprotocol) + ) + ) + ), + [object] + ) + ) + + declaration = J.variable_declaration([declarator], :const) + + body = build_implementations(impls, pid) + + body = [declaration] ++ body + + js_ast = ElixirScript.ModuleSystems.Namespace.build( + module, + body, + J.identifier("protocol"), + nil + ) + + ModuleState.put_module(pid, module, Map.put(info, :js_ast, hd(js_ast))) + end + + defp build_implementations(impls, pid) do + Enum.map(impls, fn({impl, impl_for}) -> + members = ["Elixir"] ++ Module.split(impl) ++ ["__load"] + + ast = J.call_expression( + Identifier.make_namespace_members(members), + [J.identifier("Elixir")] + ) + + J.call_expression( + J.member_expression( + J.identifier("Bootstrap"), + J.member_expression( + J.identifier(:Core), + J.member_expression( + J.identifier(:Functions), + J.identifier(:defimpl) + ) + ) + ), + [ + J.identifier("protocol"), + map_to_js(impl_for), + ast + ] + ) + end) + end + + defp map_to_js(Integer) do + J.member_expression( + J.member_expression( + J.identifier("Bootstrap"), + J.identifier(:Core) + ), + J.identifier(:Integer) + ) + end + + defp map_to_js(Tuple) do + J.member_expression( + J.member_expression( + J.identifier("Bootstrap"), + J.identifier(:Core) + ), + J.identifier(:Tuple) + ) + end + + defp map_to_js(Atom) do + J.identifier(:Symbol) + end + + defp map_to_js(List) do + J.identifier(:Array) + end + + defp map_to_js(BitString) do + J.member_expression( + J.member_expression( + J.identifier("Bootstrap"), + J.identifier(:Core) + ), + J.identifier(:BitString) + ) + end + + defp map_to_js(Float) do + J.member_expression( + J.member_expression( + J.identifier("Bootstrap"), + J.identifier(:Core) + ), + J.identifier(:Float) + ) + end + + defp map_to_js(Function) do + J.identifier(:Function) + end + + defp map_to_js(PID) do + J.member_expression( + J.member_expression( + J.identifier("Bootstrap"), + J.identifier(:Core) + ), + J.identifier(:PID) + ) + end + + defp map_to_js(Port) do + J.member_expression( + J.identifier("Bootstrap"), + J.identifier(:Port) + ) + end + + defp map_to_js(Reference) do + J.member_expression( + J.identifier("Bootstrap"), + J.identifier(:Reference) + ) + end + + defp map_to_js(Map) do + J.identifier(:Object) + end + + defp map_to_js(Any) do + J.identifier(:null) + end + + defp map_to_js(module) when is_atom(module) do + case Module.split(module) do + ["JS" | rest] -> + Identifier.make_namespace_members(rest) + split_module -> + J.call_expression( + J.member_expression( + J.identifier("Symbol"), + J.identifier("for") + ), + [J.literal(module)] + ) + end + end +end \ No newline at end of file From 25adee94ec317dfe563e19c24c63bda42281b3db Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Mon, 29 May 2017 12:04:41 -0500 Subject: [PATCH 542/860] Inlining erlang operators to javascript ones --- .../next/passes/translate/examples/example.ex | 2 +- .../next/passes/translate/form.ex | 190 +++++++++++++++++- .../lib/core/erlang_compat/erlang.js | 20 ++ .../tests/core/erlang_compat/erlang_spec.js | 21 ++ 4 files changed, 230 insertions(+), 3 deletions(-) diff --git a/lib/elixir_script/next/passes/translate/examples/example.ex b/lib/elixir_script/next/passes/translate/examples/example.ex index 2fc91703..b34d3f63 100644 --- a/lib/elixir_script/next/passes/translate/examples/example.ex +++ b/lib/elixir_script/next/passes/translate/examples/example.ex @@ -1,6 +1,6 @@ defmodule Example do def start(_, _) do - Base.encode16("Hello") + 1 + 1 end end diff --git a/lib/elixir_script/next/passes/translate/form.ex b/lib/elixir_script/next/passes/translate/form.ex index b8f3952b..72184546 100644 --- a/lib/elixir_script/next/passes/translate/form.ex +++ b/lib/elixir_script/next/passes/translate/form.ex @@ -5,6 +5,19 @@ defmodule ElixirScript.Translate.Form do alias ElixirScript.Translator.Identifier alias ElixirScript.Translate.Clause + @erlang_modules [ + :erlang, + :maps, + :lists, + :gen, + :elixir_errors, + :supervisor, + :application, + :code, + :elixir_utils, + :file + ] + @moduledoc """ Handles translation of all forms that are not functions or clauses """ @@ -63,7 +76,7 @@ defmodule ElixirScript.Translate.Form do Bitstring.compile(bitstring, state) end - def compile({:=, _, [left, right]} = match, state) do + def compile({:=, _, [_, _]} = match, state) do Match.compile(match, state) end @@ -139,7 +152,180 @@ defmodule ElixirScript.Translate.Form do ) end - def compile({{:., _, [module, function]}, _, params}, state) when module in [:erlang, :lists, :maps] do + def compile({{:., _, [:erlang, function]}, _, [first]}, state) when function in [:+, :-] do + J.unary_expression( + function, + compile(first, state), + true + ) + end + + def compile({{:., _, [:erlang, :not]}, _, [first]}, state) do + J.unary_expression( + :!, + compile(first, state), + true + ) + end + + def compile({{:., _, [:erlang, :bnot]}, _, [first]}, state) do + J.unary_expression( + :"~", + compile(first, state), + true + ) + end + + def compile({{:., _, [:erlang, :=]}, _, [_, _] = match}, state) do + Match.compile(match, state) + end + + def compile({{:., _, [:erlang, function]}, _, [first, second]}, state) when function in [:+, :-, :*, :/, :==, :>=] do + J.binary_expression( + function, + compile(first, state), + compile(second, state) + ) + end + + def compile({{:., _, [:erlang, :"/="]}, _, [first, second]}, state) do + J.binary_expression( + :!=, + compile(first, state), + compile(second, state) + ) + end + + def compile({{:., _, [:erlang, :"=<"]}, _, [first, second]}, state) do + J.binary_expression( + :<=, + compile(first, state), + compile(second, state) + ) + end + + def compile({{:., _, [:erlang, :"=:="]}, _, [first, second]}, state) do + J.binary_expression( + :===, + compile(first, state), + compile(second, state) + ) + end + + def compile({{:., _, [:erlang, :"=/="]}, _, [first, second]}, state) do + J.binary_expression( + :!==, + compile(first, state), + compile(second, state) + ) + end + + def compile({{:., _, [:erlang, function]}, _, [first, second]}, state) when function in [:andalso, :and] do + J.binary_expression( + :&&, + compile(first, state), + compile(second, state) + ) + end + + def compile({{:., _, [:erlang, function]}, _, [first, second]}, state) when function in [:orelse, :or] do + J.binary_expression( + :||, + compile(first, state), + compile(second, state) + ) + end + + def compile({{:., _, [:erlang, :div]}, _, [first, second]}, state) do + J.binary_expression( + :/, + compile(first, state), + compile(second, state) + ) + end + + def compile({{:., _, [:erlang, :rem]}, _, [first, second]}, state) do + J.binary_expression( + :mod, + compile(first, state), + compile(second, state) + ) + end + + def compile({{:., _, [:erlang, :band]}, _, [first, second]}, state) do + J.binary_expression( + :&, + compile(first, state), + compile(second, state) + ) + end + + def compile({{:., _, [:erlang, :bor]}, _, [first, second]}, state) do + J.binary_expression( + :|, + compile(first, state), + compile(second, state) + ) + end + + def compile({{:., _, [:erlang, :bsl]}, _, [first, second]}, state) do + J.binary_expression( + :"<<", + compile(first, state), + compile(second, state) + ) + end + + def compile({{:., _, [:erlang, :bsl]}, _, [first, second]}, state) do + J.binary_expression( + :">>", + compile(first, state), + compile(second, state) + ) + end + + def compile({{:., _, [:erlang, :bxor]}, _, [first, second]}, state) do + J.binary_expression( + :">>", + compile(first, state), + compile(second, state) + ) + end + + def compile({{:., _, [:erlang, :++]}, _, [_, _] = params}, state) do + J.call_expression( + J.member_expression( + J.member_expression( + J.member_expression( + J.identifier("Bootstrap"), + J.identifier("Core") + ), + J.identifier(:erlang) + ), + J.identifier("list_concatenation2") + ), + Enum.map(params, &compile(&1, state)) + ) + end + + def compile({{:., _, [:erlang, :--]}, _, [_, _] = params}, state) do + J.call_expression( + J.member_expression( + J.member_expression( + J.member_expression( + J.identifier("Bootstrap"), + J.identifier("Core") + ), + J.identifier(:erlang) + ), + J.identifier("list_substraction2") + ), + Enum.map(params, &compile(&1, state)) + ) + end + + + def compile({{:., _, [module, function]}, _, params}, state) when module in @erlang_modules do J.call_expression( J.member_expression( J.member_expression( diff --git a/src/javascript/lib/core/erlang_compat/erlang.js b/src/javascript/lib/core/erlang_compat/erlang.js index 6de89420..0b09676c 100644 --- a/src/javascript/lib/core/erlang_compat/erlang.js +++ b/src/javascript/lib/core/erlang_compat/erlang.js @@ -8,6 +8,26 @@ function atom_to_binary2(atom, encoding = Symbol.for('utf8')) { return Symbol.keyFor(atom); } +function list_concatenation2(list1, list2) { + return list1.concat(list2); +} + +function list_subtraction2(list1, list2) { + const list = [...list1]; + + for (const item of list2) { + const index = list.indexOf(item); + + if (index > -1) { + list.splice(index, 1); + } + } + + return list; +} + export default { atom_to_binary2, + list_concatenation2, + list_subtraction2, }; diff --git a/src/javascript/tests/core/erlang_compat/erlang_spec.js b/src/javascript/tests/core/erlang_compat/erlang_spec.js index 299f56f5..31460192 100644 --- a/src/javascript/tests/core/erlang_compat/erlang_spec.js +++ b/src/javascript/tests/core/erlang_compat/erlang_spec.js @@ -13,3 +13,24 @@ test('atom_to_binary2', t => { Error ); }); + +test('list_concatenation2', t => { + t.deepEqual(Core.erlang.list_concatenation2([], []), []); + t.deepEqual(Core.erlang.list_concatenation2([1], []), [1]); + t.deepEqual(Core.erlang.list_concatenation2([1, 2, 3], [4, 5, 6]), [ + 1, + 2, + 3, + 4, + 5, + 6, + ]); +}); + +test('list_subtraction2', t => { + t.deepEqual(Core.erlang.list_subtraction2([], []), []); + t.deepEqual(Core.erlang.list_subtraction2([1], []), [1]); + t.deepEqual(Core.erlang.list_subtraction2([1, 2, 3], [4, 5, 6]), [1, 2, 3]); + t.deepEqual(Core.erlang.list_subtraction2([1, 2, 3], [1, 2, 3]), []); + t.deepEqual(Core.erlang.list_subtraction2([1, 2, 3], [1, 2]), [3]); +}); From 8410fd4d817da9c795cd01398767636f850b922a Mon Sep 17 00:00:00 2001 From: Joe Ellis Date: Mon, 29 May 2017 14:59:11 -0500 Subject: [PATCH 543/860] Remove some credo warnings --- .credo.exs | 4 ++-- lib/elixir_script/cli.ex | 10 +++++----- lib/elixir_script/passes/java_script_ast.ex | 6 +++--- lib/elixir_script/passes/java_script_code.ex | 3 ++- .../translator/kernel/special_forms/bitstring.ex | 2 +- .../translator/kernel/special_forms/fn.ex | 6 +++--- .../translator/kernel/special_forms/quote.ex | 2 +- lib/elixir_script/watcher.ex | 2 +- 8 files changed, 18 insertions(+), 17 deletions(-) diff --git a/.credo.exs b/.credo.exs index 5c1f8ef1..916e4f57 100644 --- a/.credo.exs +++ b/.credo.exs @@ -98,9 +98,9 @@ {Credo.Check.Refactor.NegatedConditionsInUnless}, {Credo.Check.Refactor.NegatedConditionsWithElse}, {Credo.Check.Refactor.Nesting}, - {Credo.Check.Refactor.PipeChainStart}, + {Credo.Check.Refactor.PipeChainStart, false}, {Credo.Check.Refactor.UnlessWithElse}, - {Credo.Check.Refactor.VariableRebinding}, + {Credo.Check.Refactor.VariableRebinding, false}, {Credo.Check.Warning.BoolOperationOnSameValues}, {Credo.Check.Warning.IExPry}, diff --git a/lib/elixir_script/cli.ex b/lib/elixir_script/cli.ex index e1e573eb..4bc60ab7 100644 --- a/lib/elixir_script/cli.ex +++ b/lib/elixir_script/cli.ex @@ -45,9 +45,9 @@ defmodule ElixirScript.CLI do options: --js-module [:] A js module used in your code. ex: React:react - Multiple can be defined + Multiple can be defined -f --format [format] module format of output. options: es (default), common, umd - -o --output [path] places output at the given path. + -o --output [path] places output at the given path. Can be a directory or filename. -e --elixir read input as elixir code string --remove-unused Removes unused modules from output @@ -121,8 +121,8 @@ defmodule ElixirScript.CLI do defp build_js_modules(values) do values - |> Enum.map(fn x -> - [identifier, path] = String.split(x,":", trim: true) + |> Enum.map(fn x -> + [identifier, path] = String.split(x, ":", trim: true) { format_identifier(identifier), format_path(path) } end) end @@ -132,7 +132,7 @@ defmodule ElixirScript.CLI do |> String.split(".") |> Module.concat end - + defp format_path(path) do path diff --git a/lib/elixir_script/passes/java_script_ast.ex b/lib/elixir_script/passes/java_script_ast.ex index 7a95f0eb..9b0ab7e0 100644 --- a/lib/elixir_script/passes/java_script_ast.ex +++ b/lib/elixir_script/passes/java_script_ast.ex @@ -8,12 +8,12 @@ defmodule ElixirScript.Passes.JavaScriptAST do State.set_module_data(compiler_data.state, compiler_data.data) State.set_loaded_modules(compiler_data.state, Map.get(compiler_data, :loaded_modules, [])) - data = compiler_data.state + data = compiler_data.state |> State.get_module_data - |> Enum.reject(fn {_,module_data} -> + |> Enum.reject(fn {_, module_data} -> module_data.app == :elixir && opts.import_standard_libs == false end) - |> Enum.map(fn({module_name, module_data}) -> + |> Enum.map(fn({module_name, module_data}) -> module_data = compile(module_data, opts, compiler_data.state) {module_name, module_data} end) diff --git a/lib/elixir_script/passes/java_script_code.ex b/lib/elixir_script/passes/java_script_code.ex index 7eb2f7ef..37e212ba 100644 --- a/lib/elixir_script/passes/java_script_code.ex +++ b/lib/elixir_script/passes/java_script_code.ex @@ -1,6 +1,7 @@ defmodule ElixirScript.Passes.JavaScriptCode do @moduledoc false - alias ESTree.Tools.{Builder, Generator} + alias ESTree.Tools.Builder + alias ESTree.Tools.Generator def execute(compiler_data, _) do parent = self diff --git a/lib/elixir_script/translator/kernel/special_forms/bitstring.ex b/lib/elixir_script/translator/kernel/special_forms/bitstring.ex index 00107d8d..bf0dc832 100644 --- a/lib/elixir_script/translator/kernel/special_forms/bitstring.ex +++ b/lib/elixir_script/translator/kernel/special_forms/bitstring.ex @@ -120,7 +120,7 @@ defmodule ElixirScript.Translator.Bitstring do end def make_interpolated_string(elements, env) do - translated_elements = Enum.map(elements, fn(x)-> + translated_elements = Enum.map(elements, fn(x) -> case x do elem when is_binary(elem) -> Translator.translate!(elem, env) diff --git a/lib/elixir_script/translator/kernel/special_forms/fn.ex b/lib/elixir_script/translator/kernel/special_forms/fn.ex index 80a6de81..5e0afb65 100644 --- a/lib/elixir_script/translator/kernel/special_forms/fn.ex +++ b/lib/elixir_script/translator/kernel/special_forms/fn.ex @@ -30,7 +30,7 @@ defmodule ElixirScript.Translator.Function do ({_, _, [{:when, _, [{_, _, params}, guards]}, body]}) -> body = convert_to_try(body) - process_function_body(params, body, env, name, guards) + process_function_body(params, body, env, name, guards) ({_, _, [{_, _, params}, body]}) -> body = convert_to_try(body) @@ -212,7 +212,7 @@ defmodule ElixirScript.Translator.Function do return_statement = case declaration do %ESTree.ArrayPattern{elements: elements} -> - if(length(elements) == 1) do + if length(elements) == 1 do JS.return_statement(hd(declaration.elements)) else JS.return_statement(JS.array_expression(declaration.elements)) @@ -233,7 +233,7 @@ defmodule ElixirScript.Translator.Function do end - list = Enum.take(list, length(list)-1) + list = Enum.take(list, length(list) - 1) |> Enum.map(fn(x) -> case x do %ESTree.MemberExpression{} -> diff --git a/lib/elixir_script/translator/kernel/special_forms/quote.ex b/lib/elixir_script/translator/kernel/special_forms/quote.ex index d0b7d03d..63341757 100644 --- a/lib/elixir_script/translator/kernel/special_forms/quote.ex +++ b/lib/elixir_script/translator/kernel/special_forms/quote.ex @@ -15,7 +15,7 @@ defmodule ElixirScript.Translator.Quote do (_) -> false end) - if(has_unquote_splicing) do + if has_unquote_splicing do expr = Enum.map(expr, fn ({:unquote_splicing, _, [param]}) -> make_unquote_slicing(param, env) diff --git a/lib/elixir_script/watcher.ex b/lib/elixir_script/watcher.ex index b54cc03e..2b7134d6 100644 --- a/lib/elixir_script/watcher.ex +++ b/lib/elixir_script/watcher.ex @@ -23,7 +23,7 @@ defmodule ElixirScript.Watcher do try do if input_changed?(to_string(path), state) do - Logger.debug "Event: #{inspect event} Path: #{path}" + Logger.debug fn -> "Event: #{inspect event} Path: #{path}" end ElixirScript.compile_path(state[:input], state[:options]) end rescue From cd9001d0987587ca44ec2ea935c04c23692844cd Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Mon, 29 May 2017 16:25:02 -0500 Subject: [PATCH 544/860] Make receive a runtime error. Add warning when receive is encountered. Refactor how functions are implemented --- Supported.md | 2006 ----------------- lib/elixir_script/gen/supported.ex | 165 -- lib/elixir_script/next/compiler.ex | 1 - .../next/passes/translate/clause.ex | 2 +- .../next/passes/translate/examples/example.ex | 12 +- .../next/passes/translate/form.ex | 9 +- .../next/passes/translate/forms/receive.ex | 26 + .../next/passes/translate/function.ex | 100 +- .../next/passes/translate/module.ex | 1 + src/javascript/lib/core/special_forms.js | 9 +- 10 files changed, 148 insertions(+), 2183 deletions(-) delete mode 100644 Supported.md delete mode 100644 lib/elixir_script/gen/supported.ex create mode 100644 lib/elixir_script/next/passes/translate/forms/receive.ex diff --git a/Supported.md b/Supported.md deleted file mode 100644 index 69be84e1..00000000 --- a/Supported.md +++ /dev/null @@ -1,2006 +0,0 @@ -# Supported Elixir Modules -List all public modules in the Elixir Standard Libary. If a function or macro is supported in ElixirScript, it is checked -## Access -- [ ] `all/0` -- [ ] `at/1` -- [ ] `elem/1` -- [ ] `fetch/2` -- [ ] `get/2` -- [ ] `get/3` -- [ ] `get_and_update/3` -- [ ] `key/1` -- [ ] `key/2` -- [ ] `key!/1` -- [ ] `pop/2` -## Agent -- [ ] `cast/2` -- [ ] `cast/4` -- [X] `get/2` -- [ ] `get/3` -- [ ] `get/4` -- [ ] `get/5` -- [X] `get_and_update/2` -- [ ] `get_and_update/3` -- [ ] `get_and_update/4` -- [ ] `get_and_update/5` -- [X] `start/1` -- [X] `start/2` -- [ ] `start/3` -- [ ] `start/4` -- [X] `start_link/1` -- [X] `start_link/2` -- [ ] `start_link/3` -- [ ] `start_link/4` -- [X] `stop/1` -- [ ] `stop/2` -- [ ] `stop/3` -- [X] `update/2` -- [ ] `update/3` -- [ ] `update/4` -- [ ] `update/5` -## Application -- [ ] `app_dir/1` -- [ ] `app_dir/2` -- [ ] `delete_env/2` -- [ ] `delete_env/3` -- [ ] `ensure_all_started/1` -- [ ] `ensure_all_started/2` -- [ ] `ensure_started/1` -- [ ] `ensure_started/2` -- [ ] `fetch_env/2` -- [ ] `fetch_env!/2` -- [ ] `format_error/1` -- [ ] `get_all_env/1` -- [ ] `get_application/1` -- [ ] `get_env/2` -- [ ] `get_env/3` -- [ ] `load/1` -- [ ] `loaded_applications/0` -- [ ] `put_env/3` -- [ ] `put_env/4` -- [ ] `spec/1` -- [ ] `spec/2` -- [ ] `start/1` -- [ ] `start/2` -- [ ] `started_applications/0` -- [ ] `started_applications/1` -- [ ] `stop/1` -- [ ] `unload/1` -- [ ] `__using__/1` -## ArgumentError -- [X] `__struct__/0` -- [X] `__struct__/1` -- [X] `exception/1` -- [X] `message/1` -## ArithmeticError -- [ ] `__struct__/0` -- [ ] `__struct__/1` -- [ ] `exception/1` -- [ ] `message/1` -## Atom -- [X] `to_char_list/1` -- [ ] `to_charlist/1` -- [X] `to_string/1` -## BadArityError -- [ ] `__struct__/0` -- [ ] `__struct__/1` -- [ ] `exception/1` -- [ ] `message/1` -## BadBooleanError -- [ ] `__struct__/0` -- [ ] `__struct__/1` -- [ ] `exception/1` -- [ ] `message/1` -## BadFunctionError -- [ ] `__struct__/0` -- [ ] `__struct__/1` -- [ ] `exception/1` -- [ ] `message/1` -## BadMapError -- [ ] `__struct__/0` -- [ ] `__struct__/1` -- [ ] `exception/1` -- [ ] `message/1` -## BadStructError -- [ ] `__struct__/0` -- [ ] `__struct__/1` -- [ ] `exception/1` -- [ ] `message/1` -## Base -- [ ] `decode16/1` -- [ ] `decode16/2` -- [ ] `decode16!/1` -- [ ] `decode16!/2` -- [ ] `decode32/1` -- [ ] `decode32/2` -- [ ] `decode32!/1` -- [ ] `decode32!/2` -- [X] `decode64/1` -- [ ] `decode64/2` -- [X] `decode64!/1` -- [ ] `decode64!/2` -- [ ] `encode16/1` -- [ ] `encode16/2` -- [ ] `encode32/1` -- [ ] `encode32/2` -- [X] `encode64/1` -- [ ] `encode64/2` -- [ ] `hex_decode32/1` -- [ ] `hex_decode32/2` -- [ ] `hex_decode32!/1` -- [ ] `hex_decode32!/2` -- [ ] `hex_encode32/1` -- [ ] `hex_encode32/2` -- [ ] `url_decode64/1` -- [ ] `url_decode64/2` -- [ ] `url_decode64!/1` -- [ ] `url_decode64!/2` -- [ ] `url_encode64/1` -- [ ] `url_encode64/2` -## Behaviour -- [ ] `__using__/1` -- [ ] `defcallback/1` -- [ ] `defmacrocallback/1` -## Bitwise -- [X] `&&&/2` -- [X] `<<>>/2` -- [X] `^^^/2` -- [ ] `__using__/1` -- [X] `band/2` -- [X] `bnot/1` -- [X] `bor/2` -- [X] `bsl/2` -- [X] `bsr/2` -- [X] `bxor/2` -- [X] `|||/2` -- [X] `~~~/1` -## Calendar -## Calendar.ISO -- [ ] `date/3` -- [ ] `date_to_iso8601/3` -- [ ] `date_to_string/3` -- [ ] `datetime_to_iso8601/11` -- [ ] `datetime_to_string/11` -- [ ] `day_of_week/3` -- [ ] `days_in_month/2` -- [ ] `from_unix/2` -- [ ] `leap_year?/1` -- [ ] `naive_datetime_to_iso8601/7` -- [ ] `naive_datetime_to_string/7` -- [ ] `parse_microsecond/1` -- [ ] `parse_offset/1` -- [ ] `time_to_iso8601/4` -- [ ] `time_to_string/4` -## CaseClauseError -- [ ] `__struct__/0` -- [ ] `__struct__/1` -- [ ] `exception/1` -- [ ] `message/1` -## Code -- [ ] `append_path/1` -- [ ] `available_compiler_options/0` -- [ ] `compile_quoted/1` -- [ ] `compile_quoted/2` -- [ ] `compile_string/1` -- [ ] `compile_string/2` -- [ ] `compiler_options/0` -- [ ] `compiler_options/1` -- [ ] `delete_path/1` -- [ ] `ensure_compiled/1` -- [ ] `ensure_compiled?/1` -- [ ] `ensure_loaded/1` -- [ ] `ensure_loaded?/1` -- [ ] `eval_file/1` -- [ ] `eval_file/2` -- [ ] `eval_quoted/1` -- [ ] `eval_quoted/2` -- [ ] `eval_quoted/3` -- [ ] `eval_string/1` -- [ ] `eval_string/2` -- [ ] `eval_string/3` -- [ ] `get_docs/2` -- [ ] `load_file/1` -- [ ] `load_file/2` -- [ ] `loaded_files/0` -- [ ] `prepend_path/1` -- [ ] `require_file/1` -- [ ] `require_file/2` -- [ ] `string_to_quoted/1` -- [ ] `string_to_quoted/2` -- [ ] `string_to_quoted!/1` -- [ ] `string_to_quoted!/2` -- [ ] `unload_files/1` -## Code.LoadError -- [ ] `__struct__/0` -- [ ] `__struct__/1` -- [ ] `exception/1` -- [ ] `message/1` -## Collectable -- [X] `__protocol__/1` -- [X] `impl_for/1` -- [X] `impl_for!/1` -- [X] `into/1` -## Collectable.BitString -- [X] `__impl__/1` -- [X] `into/1` -## Collectable.File.Stream -- [ ] `__impl__/1` -- [ ] `into/1` -## Collectable.HashDict -- [ ] `__impl__/1` -- [ ] `into/1` -## Collectable.HashSet -- [ ] `__impl__/1` -- [ ] `into/1` -## Collectable.IO.Stream -- [ ] `__impl__/1` -- [ ] `into/1` -## Collectable.List -- [X] `__impl__/1` -- [X] `into/1` -## Collectable.Map -- [X] `__impl__/1` -- [X] `into/1` -## Collectable.MapSet -- [ ] `__impl__/1` -- [ ] `into/1` -## CompileError -- [ ] `__struct__/0` -- [ ] `__struct__/1` -- [ ] `exception/1` -- [ ] `message/1` -## CondClauseError -- [ ] `__struct__/0` -- [ ] `__struct__/1` -- [ ] `exception/1` -- [ ] `message/1` -## Date -- [ ] `__struct__/0` -- [ ] `__struct__/1` -- [ ] `compare/2` -- [ ] `day_of_week/1` -- [ ] `days_in_month/1` -- [ ] `from_erl/1` -- [ ] `from_erl!/1` -- [ ] `from_iso8601/1` -- [ ] `from_iso8601!/1` -- [ ] `leap_year?/1` -- [ ] `new/3` -- [ ] `to_erl/1` -- [ ] `to_iso8601/1` -- [ ] `to_string/1` -- [ ] `utc_today/0` -## DateTime -- [ ] `__struct__/0` -- [ ] `__struct__/1` -- [ ] `compare/2` -- [ ] `from_iso8601/1` -- [ ] `from_naive/2` -- [ ] `from_naive!/2` -- [ ] `from_unix/1` -- [ ] `from_unix/2` -- [ ] `from_unix!/1` -- [ ] `from_unix!/2` -- [ ] `to_date/1` -- [ ] `to_iso8601/1` -- [ ] `to_naive/1` -- [ ] `to_string/1` -- [ ] `to_time/1` -- [ ] `to_unix/1` -- [ ] `to_unix/2` -- [ ] `utc_now/0` -## Dict -- [ ] `delete/2` -- [ ] `drop/2` -- [ ] `empty/1` -- [ ] `equal?/2` -- [ ] `fetch/2` -- [ ] `fetch!/2` -- [ ] `get/2` -- [ ] `get/3` -- [ ] `get_and_update/3` -- [ ] `get_lazy/3` -- [ ] `has_key?/2` -- [ ] `keys/1` -- [ ] `merge/2` -- [ ] `merge/3` -- [ ] `pop/2` -- [ ] `pop/3` -- [ ] `pop_lazy/3` -- [ ] `put/3` -- [ ] `put_new/3` -- [ ] `put_new_lazy/3` -- [ ] `size/1` -- [ ] `split/2` -- [ ] `take/2` -- [ ] `to_list/1` -- [ ] `update/4` -- [ ] `update!/3` -- [ ] `values/1` -- [ ] `__using__/1` -## Enum -- [X] `all?/1` -- [X] `all?/2` -- [X] `any?/1` -- [X] `any?/2` -- [X] `at/2` -- [X] `at/3` -- [ ] `chunk/2` -- [ ] `chunk/3` -- [ ] `chunk/4` -- [ ] `chunk_by/2` -- [X] `concat/1` -- [X] `concat/2` -- [X] `count/1` -- [X] `count/2` -- [ ] `dedup/1` -- [ ] `dedup_by/2` -- [X] `drop/2` -- [X] `drop_every/2` -- [X] `drop_while/2` -- [X] `each/2` -- [X] `empty?/1` -- [X] `fetch/2` -- [X] `fetch!/2` -- [X] `filter/2` -- [X] `filter_map/3` -- [X] `find/2` -- [X] `find/3` -- [ ] `find_index/2` -- [ ] `find_value/2` -- [ ] `find_value/3` -- [ ] `flat_map/2` -- [ ] `flat_map_reduce/3` -- [ ] `group_by/2` -- [ ] `group_by/3` -- [ ] `intersperse/2` -- [X] `into/2` -- [X] `into/3` -- [ ] `join/1` -- [ ] `join/2` -- [X] `map/2` -- [ ] `map_every/3` -- [ ] `map_join/2` -- [ ] `map_join/3` -- [X] `map_reduce/3` -- [ ] `max/1` -- [ ] `max/2` -- [ ] `max_by/2` -- [ ] `max_by/3` -- [X] `member?/2` -- [ ] `min/1` -- [ ] `min/2` -- [ ] `min_by/2` -- [ ] `min_by/3` -- [ ] `min_max/1` -- [ ] `min_max/2` -- [ ] `min_max_by/2` -- [ ] `min_max_by/3` -- [ ] `partition/2` -- [ ] `random/1` -- [X] `reduce/2` -- [X] `reduce/3` -- [ ] `reduce_while/3` -- [ ] `reject/2` -- [X] `reverse/1` -- [X] `reverse/2` -- [ ] `reverse_slice/3` -- [ ] `scan/2` -- [ ] `scan/3` -- [ ] `shuffle/1` -- [ ] `slice/2` -- [ ] `slice/3` -- [ ] `sort/1` -- [ ] `sort/2` -- [ ] `sort_by/2` -- [ ] `sort_by/3` -- [ ] `split/2` -- [ ] `split_while/2` -- [ ] `split_with/2` -- [ ] `sum/1` -- [X] `take/2` -- [X] `take_every/2` -- [ ] `take_random/2` -- [X] `take_while/2` -- [X] `to_list/1` -- [ ] `uniq/1` -- [ ] `uniq/2` -- [ ] `uniq_by/2` -- [ ] `unzip/1` -- [ ] `with_index/1` -- [ ] `with_index/2` -- [ ] `zip/1` -- [ ] `zip/2` -## Enum.EmptyError -- [ ] `__struct__/0` -- [ ] `__struct__/1` -- [ ] `exception/1` -- [ ] `message/1` -## Enum.OutOfBoundsError -- [X] `__struct__/0` -- [X] `__struct__/1` -- [X] `exception/1` -- [X] `message/1` -## Enumerable -- [X] `__protocol__/1` -- [X] `count/1` -- [X] `impl_for/1` -- [X] `impl_for!/1` -- [X] `member?/2` -- [X] `reduce/3` -## Enumerable.File.Stream -- [ ] `__impl__/1` -- [ ] `count/1` -- [ ] `member?/2` -- [ ] `reduce/3` -## Enumerable.Function -- [ ] `__impl__/1` -- [ ] `count/1` -- [ ] `member?/2` -- [ ] `reduce/3` -## Enumerable.GenEvent.Stream -- [ ] `__impl__/1` -- [ ] `count/1` -- [ ] `member?/2` -- [ ] `reduce/3` -## Enumerable.HashDict -- [ ] `__impl__/1` -- [ ] `count/1` -- [ ] `member?/2` -- [ ] `reduce/3` -## Enumerable.HashSet -- [ ] `__impl__/1` -- [ ] `count/1` -- [ ] `member?/2` -- [ ] `reduce/3` -## Enumerable.IO.Stream -- [ ] `__impl__/1` -- [ ] `count/1` -- [ ] `member?/2` -- [ ] `reduce/3` -## Enumerable.List -- [X] `__impl__/1` -- [X] `count/1` -- [X] `member?/2` -- [X] `reduce/3` -## Enumerable.Map -- [X] `__impl__/1` -- [X] `count/1` -- [X] `member?/2` -- [X] `reduce/3` -## Enumerable.MapSet -- [ ] `__impl__/1` -- [ ] `count/1` -- [ ] `member?/2` -- [ ] `reduce/3` -## Enumerable.Range -- [ ] `__impl__/1` -- [ ] `count/1` -- [ ] `member?/2` -- [ ] `reduce/3` -## Enumerable.Stream -- [ ] `__impl__/1` -- [ ] `count/1` -- [ ] `member?/2` -- [ ] `reduce/3` -## ErlangError -- [ ] `__struct__/0` -- [ ] `__struct__/1` -- [ ] `exception/1` -- [ ] `message/1` -- [ ] `normalize/2` -## Exception -- [ ] `exception?/1` -- [ ] `format/2` -- [ ] `format/3` -- [ ] `format_banner/2` -- [ ] `format_banner/3` -- [ ] `format_exit/1` -- [ ] `format_fa/2` -- [ ] `format_file_line/2` -- [ ] `format_file_line/3` -- [ ] `format_mfa/3` -- [ ] `format_stacktrace/0` -- [ ] `format_stacktrace/1` -- [ ] `format_stacktrace_entry/1` -- [ ] `message/1` -- [ ] `normalize/2` -- [ ] `normalize/3` -## File -- [ ] `cd/1` -- [ ] `cd!/1` -- [ ] `cd!/2` -- [ ] `chgrp/2` -- [ ] `chgrp!/2` -- [ ] `chmod/2` -- [ ] `chmod!/2` -- [ ] `chown/2` -- [ ] `chown!/2` -- [ ] `close/1` -- [ ] `copy/2` -- [ ] `copy/3` -- [ ] `copy!/2` -- [ ] `copy!/3` -- [ ] `cp/2` -- [ ] `cp/3` -- [ ] `cp!/2` -- [ ] `cp!/3` -- [ ] `cp_r/2` -- [ ] `cp_r/3` -- [ ] `cp_r!/2` -- [ ] `cp_r!/3` -- [ ] `cwd/0` -- [ ] `cwd!/0` -- [ ] `dir?/1` -- [ ] `exists?/1` -- [ ] `ln_s/2` -- [ ] `ls/0` -- [ ] `ls/1` -- [ ] `ls!/0` -- [ ] `ls!/1` -- [ ] `lstat/1` -- [ ] `lstat/2` -- [ ] `lstat!/1` -- [ ] `lstat!/2` -- [ ] `mkdir/1` -- [ ] `mkdir!/1` -- [ ] `mkdir_p/1` -- [ ] `mkdir_p!/1` -- [ ] `open/1` -- [ ] `open/2` -- [ ] `open/3` -- [ ] `open!/1` -- [ ] `open!/2` -- [ ] `open!/3` -- [ ] `read/1` -- [ ] `read!/1` -- [ ] `regular?/1` -- [ ] `rename/2` -- [ ] `rm/1` -- [ ] `rm!/1` -- [ ] `rm_rf/1` -- [ ] `rm_rf!/1` -- [ ] `rmdir/1` -- [ ] `rmdir!/1` -- [ ] `stat/1` -- [ ] `stat/2` -- [ ] `stat!/1` -- [ ] `stat!/2` -- [ ] `stream!/1` -- [ ] `stream!/2` -- [ ] `stream!/3` -- [ ] `touch/1` -- [ ] `touch/2` -- [ ] `touch!/1` -- [ ] `touch!/2` -- [ ] `write/2` -- [ ] `write/3` -- [ ] `write!/2` -- [ ] `write!/3` -- [ ] `write_stat/2` -- [ ] `write_stat/3` -- [ ] `write_stat!/2` -- [ ] `write_stat!/3` -## File.CopyError -- [ ] `__struct__/0` -- [ ] `__struct__/1` -- [ ] `exception/1` -- [ ] `message/1` -## File.Error -- [ ] `__struct__/0` -- [ ] `__struct__/1` -- [ ] `exception/1` -- [ ] `message/1` -## File.Stat -- [ ] `__struct__/0` -- [ ] `__struct__/1` -- [ ] `from_record/1` -- [ ] `to_record/1` -## File.Stream -- [ ] `__build__/3` -- [ ] `__struct__/0` -- [ ] `__struct__/1` -## Float -- [ ] `ceil/1` -- [ ] `ceil/2` -- [ ] `floor/1` -- [ ] `floor/2` -- [ ] `parse/1` -- [ ] `ratio/1` -- [ ] `round/1` -- [ ] `round/2` -- [ ] `to_char_list/1` -- [ ] `to_char_list/2` -- [ ] `to_charlist/1` -- [ ] `to_string/1` -- [ ] `to_string/2` -## FunctionClauseError -- [ ] `__struct__/0` -- [ ] `__struct__/1` -- [ ] `exception/1` -- [ ] `message/1` -## GenEvent -- [ ] `ack_notify/2` -- [ ] `add_handler/3` -- [ ] `add_mon_handler/3` -- [ ] `call/3` -- [ ] `call/4` -- [ ] `format_status/2` -- [ ] `init_hib/4` -- [ ] `init_it/6` -- [ ] `notify/2` -- [ ] `remove_handler/3` -- [ ] `start/0` -- [ ] `start/1` -- [ ] `start_link/0` -- [ ] `start_link/1` -- [ ] `stop/1` -- [ ] `stop/2` -- [ ] `stop/3` -- [ ] `stream/1` -- [ ] `stream/2` -- [ ] `swap_handler/5` -- [ ] `swap_mon_handler/5` -- [ ] `sync_notify/2` -- [ ] `system_code_change/4` -- [ ] `system_continue/3` -- [ ] `system_get_state/1` -- [ ] `system_replace_state/2` -- [ ] `system_terminate/4` -- [ ] `which_handlers/1` -- [ ] `__using__/1` -## GenEvent.Stream -- [ ] `__struct__/0` -- [ ] `__struct__/1` -- [ ] `code_change/3` -- [ ] `handle_call/2` -- [ ] `handle_event/2` -- [ ] `handle_info/2` -- [ ] `init/1` -- [ ] `terminate/2` -## GenServer -- [ ] `abcast/2` -- [ ] `abcast/3` -- [ ] `call/2` -- [ ] `call/3` -- [ ] `cast/2` -- [ ] `multi_call/2` -- [ ] `multi_call/3` -- [ ] `multi_call/4` -- [ ] `reply/2` -- [ ] `start/2` -- [ ] `start/3` -- [ ] `start_link/2` -- [ ] `start_link/3` -- [ ] `stop/1` -- [ ] `stop/2` -- [ ] `stop/3` -- [ ] `whereis/1` -- [ ] `__using__/1` -## HashDict -- [ ] `__struct__/0` -- [ ] `__struct__/1` -- [ ] `delete/2` -- [ ] `dict_delete/2` -- [ ] `drop/2` -- [ ] `equal?/2` -- [ ] `fetch/2` -- [ ] `fetch!/2` -- [ ] `get/2` -- [ ] `get/3` -- [ ] `get_and_update/3` -- [ ] `get_lazy/3` -- [ ] `has_key?/2` -- [ ] `keys/1` -- [ ] `merge/2` -- [ ] `merge/3` -- [ ] `new/0` -- [ ] `pop/2` -- [ ] `pop/3` -- [ ] `pop_lazy/3` -- [ ] `put/3` -- [ ] `put_new/3` -- [ ] `put_new_lazy/3` -- [ ] `reduce/3` -- [ ] `size/1` -- [ ] `split/2` -- [ ] `take/2` -- [ ] `to_list/1` -- [ ] `update/4` -- [ ] `update!/3` -- [ ] `values/1` -## HashSet -- [ ] `__struct__/0` -- [ ] `__struct__/1` -- [ ] `delete/2` -- [ ] `difference/2` -- [ ] `disjoint?/2` -- [ ] `equal?/2` -- [ ] `intersection/2` -- [ ] `member?/2` -- [ ] `new/0` -- [ ] `put/2` -- [ ] `reduce/3` -- [ ] `size/1` -- [ ] `subset?/2` -- [ ] `to_list/1` -- [ ] `union/2` -## IO -- [ ] `binread/1` -- [ ] `binread/2` -- [ ] `binstream/2` -- [ ] `binwrite/1` -- [ ] `binwrite/2` -- [ ] `chardata_to_string/1` -- [ ] `each_binstream/2` -- [ ] `each_stream/2` -- [ ] `getn/1` -- [ ] `getn/2` -- [ ] `getn/3` -- [ ] `gets/1` -- [ ] `gets/2` -- [X] `inspect/1` -- [X] `inspect/2` -- [ ] `inspect/3` -- [ ] `iodata_length/1` -- [ ] `iodata_to_binary/1` -- [X] `puts/1` -- [X] `puts/2` -- [ ] `read/1` -- [ ] `read/2` -- [ ] `stream/2` -- [X] `warn/1` -- [ ] `warn/2` -- [ ] `write/1` -- [ ] `write/2` -## IO.ANSI -- [ ] `black/0` -- [ ] `black_background/0` -- [ ] `blink_off/0` -- [ ] `blink_rapid/0` -- [ ] `blink_slow/0` -- [ ] `blue/0` -- [ ] `blue_background/0` -- [ ] `bright/0` -- [ ] `clear/0` -- [ ] `clear_line/0` -- [ ] `color/1` -- [ ] `color/3` -- [ ] `color_background/1` -- [ ] `color_background/3` -- [ ] `conceal/0` -- [ ] `crossed_out/0` -- [ ] `cyan/0` -- [ ] `cyan_background/0` -- [ ] `default_background/0` -- [ ] `default_color/0` -- [ ] `enabled?/0` -- [ ] `encircled/0` -- [ ] `faint/0` -- [ ] `font_1/0` -- [ ] `font_2/0` -- [ ] `font_3/0` -- [ ] `font_4/0` -- [ ] `font_5/0` -- [ ] `font_6/0` -- [ ] `font_7/0` -- [ ] `font_8/0` -- [ ] `font_9/0` -- [ ] `format/1` -- [ ] `format/2` -- [ ] `format_fragment/1` -- [ ] `format_fragment/2` -- [ ] `framed/0` -- [ ] `green/0` -- [ ] `green_background/0` -- [ ] `home/0` -- [ ] `inverse/0` -- [ ] `inverse_off/0` -- [ ] `italic/0` -- [ ] `light_black/0` -- [ ] `light_black_background/0` -- [ ] `light_blue/0` -- [ ] `light_blue_background/0` -- [ ] `light_cyan/0` -- [ ] `light_cyan_background/0` -- [ ] `light_green/0` -- [ ] `light_green_background/0` -- [ ] `light_magenta/0` -- [ ] `light_magenta_background/0` -- [ ] `light_red/0` -- [ ] `light_red_background/0` -- [ ] `light_white/0` -- [ ] `light_white_background/0` -- [ ] `light_yellow/0` -- [ ] `light_yellow_background/0` -- [ ] `magenta/0` -- [ ] `magenta_background/0` -- [ ] `no_underline/0` -- [ ] `normal/0` -- [ ] `not_framed_encircled/0` -- [ ] `not_italic/0` -- [ ] `not_overlined/0` -- [ ] `overlined/0` -- [ ] `primary_font/0` -- [ ] `red/0` -- [ ] `red_background/0` -- [ ] `reset/0` -- [ ] `reverse/0` -- [ ] `reverse_off/0` -- [ ] `underline/0` -- [ ] `white/0` -- [ ] `white_background/0` -- [ ] `yellow/0` -- [ ] `yellow_background/0` -## IO.Stream -- [ ] `__build__/3` -- [ ] `__struct__/0` -- [ ] `__struct__/1` -## IO.StreamError -- [ ] `__struct__/0` -- [ ] `__struct__/1` -- [ ] `exception/1` -- [ ] `message/1` -## Inspect -- [ ] `__protocol__/1` -- [ ] `impl_for/1` -- [ ] `impl_for!/1` -- [ ] `inspect/2` -## Inspect.Algebra -- [ ] `break/0` -- [ ] `break/1` -- [ ] `color/3` -- [ ] `concat/1` -- [ ] `concat/2` -- [ ] `empty/0` -- [ ] `fold_doc/2` -- [ ] `format/2` -- [ ] `glue/2` -- [ ] `glue/3` -- [ ] `group/1` -- [ ] `line/2` -- [ ] `nest/2` -- [ ] `space/2` -- [ ] `surround/3` -- [ ] `surround_many/5` -- [ ] `surround_many/6` -- [ ] `to_doc/2` -## Inspect.Any -- [ ] `__impl__/1` -- [ ] `inspect/2` -## Inspect.Atom -- [ ] `__impl__/1` -- [ ] `inspect/1` -- [ ] `inspect/2` -## Inspect.BitString -- [ ] `__impl__/1` -- [ ] `escape/2` -- [ ] `escape_char/1` -- [ ] `inspect/2` -## Inspect.Date -- [ ] `__impl__/1` -- [ ] `inspect/2` -## Inspect.Error -- [ ] `__struct__/0` -- [ ] `__struct__/1` -- [ ] `exception/1` -- [ ] `message/1` -## Inspect.Float -- [ ] `__impl__/1` -- [ ] `inspect/2` -## Inspect.Function -- [ ] `__impl__/1` -- [ ] `inspect/2` -## Inspect.HashDict -- [ ] `__impl__/1` -- [ ] `inspect/2` -## Inspect.HashSet -- [ ] `__impl__/1` -- [ ] `inspect/2` -## Inspect.Integer -- [ ] `__impl__/1` -- [ ] `inspect/2` -## Inspect.List -- [ ] `__impl__/1` -- [ ] `inspect/2` -- [ ] `keyword/2` -- [ ] `keyword?/1` -- [ ] `printable?/1` -## Inspect.Map -- [ ] `__impl__/1` -- [ ] `inspect/2` -- [ ] `inspect/3` -## Inspect.MapSet -- [ ] `__impl__/1` -- [ ] `inspect/2` -## Inspect.NaiveDateTime -- [ ] `__impl__/1` -- [ ] `inspect/2` -## Inspect.Opts -- [ ] `__struct__/0` -- [ ] `__struct__/1` -## Inspect.PID -- [ ] `__impl__/1` -- [ ] `inspect/2` -## Inspect.Port -- [ ] `__impl__/1` -- [ ] `inspect/2` -## Inspect.Range -- [ ] `__impl__/1` -- [ ] `inspect/2` -## Inspect.Reference -- [ ] `__impl__/1` -- [ ] `inspect/2` -## Inspect.Regex -- [ ] `__impl__/1` -- [ ] `inspect/2` -## Inspect.Stream -- [ ] `__impl__/1` -- [ ] `inspect/2` -## Inspect.Time -- [ ] `__impl__/1` -- [ ] `inspect/2` -## Inspect.Tuple -- [ ] `__impl__/1` -- [ ] `inspect/2` -## Inspect.Version -- [ ] `__impl__/1` -- [ ] `inspect/2` -## Inspect.Version.Requirement -- [ ] `__impl__/1` -- [ ] `inspect/2` -## Integer -- [ ] `digits/1` -- [ ] `digits/2` -- [ ] `floor_div/2` -- [ ] `mod/2` -- [X] `parse/1` -- [X] `parse/2` -- [X] `to_char_list/1` -- [ ] `to_charlist/1` -- [ ] `to_charlist/2` -- [ ] `to_string/1` -- [ ] `to_string/2` -- [ ] `undigits/1` -- [ ] `undigits/2` -- [X] `is_even/1` -- [X] `is_odd/1` -## Kernel -- [X] `!=/2` -- [X] `!==/2` -- [X] `*/2` -- [X] `+/1` -- [X] `+/2` -- [X] `++/2` -- [X] `-/1` -- [X] `-/2` -- [X] `--/2` -- [X] `//2` -- [X] `/2` -- [X] `>=/2` -- [X] `abs/1` -- [X] `apply/2` -- [X] `apply/3` -- [X] `binary_part/3` -- [ ] `bit_size/1` -- [ ] `byte_size/1` -- [X] `div/2` -- [X] `elem/2` -- [ ] `exit/1` -- [ ] `function_exported?/3` -- [ ] `get_and_update_in/3` -- [ ] `get_in/2` -- [X] `hd/1` -- [ ] `inspect/1` -- [ ] `inspect/2` -- [X] `is_atom/1` -- [X] `is_binary/1` -- [X] `is_bitstring/1` -- [X] `is_boolean/1` -- [X] `is_float/1` -- [X] `is_function/1` -- [X] `is_function/2` -- [X] `is_integer/1` -- [X] `is_list/1` -- [X] `is_map/1` -- [X] `is_number/1` -- [X] `is_pid/1` -- [X] `is_port/1` -- [X] `is_reference/1` -- [X] `is_tuple/1` -- [X] `length/1` -- [ ] `macro_exported?/3` -- [ ] `make_ref/0` -- [X] `map_size/1` -- [X] `max/2` -- [X] `min/2` -- [ ] `node/0` -- [ ] `node/1` -- [ ] `not/1` -- [ ] `pop_in/2` -- [ ] `put_elem/3` -- [ ] `put_in/3` -- [X] `rem/2` -- [X] `round/1` -- [ ] `self/0` -- [ ] `send/2` -- [ ] `spawn/1` -- [ ] `spawn/3` -- [ ] `spawn_link/1` -- [ ] `spawn_link/3` -- [ ] `spawn_monitor/1` -- [ ] `spawn_monitor/3` -- [ ] `struct/1` -- [ ] `struct/2` -- [ ] `struct!/1` -- [ ] `struct!/2` -- [X] `throw/1` -- [X] `tl/1` -- [X] `trunc/1` -- [X] `tuple_size/1` -- [ ] `update_in/3` -- [X] `!/1` -- [X] `&&/2` -- [X] `../2` -- [X] `<>/2` -- [X] `@/1` -- [ ] `alias!/1` -- [X] `and/2` -- [ ] `binding/0` -- [ ] `binding/1` -- [X] `def/1` -- [X] `def/2` -- [X] `defdelegate/2` -- [X] `defexception/1` -- [X] `defimpl/2` -- [X] `defimpl/3` -- [X] `defmacro/1` -- [X] `defmacro/2` -- [X] `defmacrop/1` -- [X] `defmacrop/2` -- [X] `defmodule/2` -- [X] `defoverridable/1` -- [X] `defp/1` -- [X] `defp/2` -- [X] `defprotocol/2` -- [X] `defstruct/1` -- [ ] `destructure/2` -- [ ] `get_and_update_in/2` -- [X] `if/2` -- [X] `in/2` -- [X] `is_nil/1` -- [X] `match?/2` -- [X] `or/2` -- [ ] `pop_in/1` -- [ ] `put_in/2` -- [X] `raise/1` -- [X] `raise/2` -- [ ] `reraise/2` -- [ ] `reraise/3` -- [ ] `sigil_C/2` -- [ ] `sigil_D/2` -- [ ] `sigil_N/2` -- [ ] `sigil_R/2` -- [ ] `sigil_S/2` -- [ ] `sigil_T/2` -- [ ] `sigil_W/2` -- [ ] `sigil_c/2` -- [X] `sigil_r/2` -- [ ] `sigil_s/2` -- [ ] `sigil_w/2` -- [ ] `to_char_list/1` -- [ ] `to_charlist/1` -- [X] `to_string/1` -- [X] `unless/2` -- [ ] `update_in/2` -- [X] `use/1` -- [X] `use/2` -- [ ] `var!/1` -- [ ] `var!/2` -- [X] `|>/2` -- [X] `||/2` -## Kernel.ErrorHandler -- [ ] `ensure_compiled/2` -- [ ] `ensure_loaded/1` -- [ ] `undefined_function/3` -- [ ] `undefined_lambda/3` -## Kernel.ParallelCompiler -- [ ] `files/1` -- [ ] `files/2` -- [ ] `files_to_path/2` -- [ ] `files_to_path/3` -## Kernel.ParallelRequire -- [ ] `files/1` -- [ ] `files/2` -## Kernel.SpecialForms -- [X] `%/2` -- [X] `%{}/1` -- [X] `&/1` -- [X] `./2` -- [X] `::/2` -- [X] `<<>>/1` -- [X] `=/2` -- [X] `^/1` -- [X] `__CALLER__/0` -- [X] `__DIR__/0` -- [X] `__ENV__/0` -- [X] `__MODULE__/0` -- [X] `__aliases__/1` -- [X] `__block__/1` -- [X] `alias/2` -- [X] `case/2` -- [X] `cond/1` -- [X] `fn/1` -- [X] `for/1` -- [X] `import/2` -- [X] `quote/2` -- [ ] `receive/1` -- [X] `require/2` -- [X] `super/1` -- [X] `try/1` -- [X] `unquote/1` -- [X] `unquote_splicing/1` -- [X] `with/1` -- [X] `{}/1` -## Kernel.Typespec -- [ ] `beam_callbacks/1` -- [ ] `beam_specs/1` -- [ ] `beam_typedocs/1` -- [ ] `beam_types/1` -- [ ] `define_spec/3` -- [ ] `define_type/3` -- [ ] `define_type/4` -- [ ] `defines_callback?/3` -- [ ] `defines_spec?/3` -- [ ] `defines_type?/3` -- [ ] `defspec/3` -- [ ] `deftype/3` -- [ ] `spec_to_ast/2` -- [ ] `spec_to_signature/1` -- [ ] `translate_spec/3` -- [ ] `translate_type/3` -- [ ] `type_to_ast/1` -- [ ] `type_to_signature/1` -- [ ] `defcallback/1` -- [ ] `defmacrocallback/1` -- [ ] `defopaque/1` -- [ ] `defoptional_callbacks/1` -- [ ] `defspec/1` -- [ ] `deftype/1` -- [ ] `deftypep/1` -## KeyError -- [ ] `__struct__/0` -- [ ] `__struct__/1` -- [ ] `exception/1` -- [ ] `message/1` -## Keyword -- [ ] `delete/2` -- [ ] `delete/3` -- [ ] `delete_first/2` -- [ ] `drop/2` -- [ ] `equal?/2` -- [ ] `fetch/2` -- [ ] `fetch!/2` -- [X] `get/2` -- [X] `get/3` -- [ ] `get_and_update/3` -- [ ] `get_and_update!/3` -- [ ] `get_lazy/3` -- [ ] `get_values/2` -- [X] `has_key?/2` -- [ ] `keys/1` -- [ ] `keyword?/1` -- [ ] `merge/2` -- [ ] `merge/3` -- [X] `new/0` -- [ ] `new/1` -- [ ] `new/2` -- [ ] `pop/2` -- [ ] `pop/3` -- [ ] `pop_first/2` -- [ ] `pop_first/3` -- [ ] `pop_lazy/3` -- [ ] `put/3` -- [ ] `put_new/3` -- [ ] `put_new_lazy/3` -- [ ] `size/1` -- [ ] `split/2` -- [ ] `take/2` -- [ ] `to_list/1` -- [ ] `update/4` -- [ ] `update!/3` -- [ ] `values/1` -## List -- [X] `delete/2` -- [X] `delete_at/2` -- [X] `duplicate/2` -- [X] `first/1` -- [X] `flatten/1` -- [X] `flatten/2` -- [X] `foldl/3` -- [X] `foldr/3` -- [X] `insert_at/3` -- [X] `keydelete/3` -- [X] `keyfind/3` -- [X] `keyfind/4` -- [X] `keymember?/3` -- [X] `keyreplace/4` -- [ ] `keysort/2` -- [ ] `keystore/4` -- [ ] `keytake/3` -- [X] `last/1` -- [ ] `myers_difference/2` -- [ ] `pop_at/2` -- [ ] `pop_at/3` -- [X] `replace_at/3` -- [ ] `to_atom/1` -- [ ] `to_existing_atom/1` -- [ ] `to_float/1` -- [ ] `to_integer/1` -- [ ] `to_integer/2` -- [ ] `to_string/1` -- [X] `to_tuple/1` -- [X] `update_at/3` -- [X] `wrap/1` -- [X] `zip/1` -## List.Chars -- [ ] `__protocol__/1` -- [ ] `impl_for/1` -- [ ] `impl_for!/1` -- [ ] `to_char_list/1` -- [ ] `to_charlist/1` -## List.Chars.Atom -- [ ] `__impl__/1` -- [ ] `to_charlist/1` -## List.Chars.BitString -- [ ] `__impl__/1` -- [ ] `to_charlist/1` -## List.Chars.Float -- [ ] `__impl__/1` -- [ ] `to_charlist/1` -## List.Chars.Integer -- [ ] `__impl__/1` -- [ ] `to_charlist/1` -## List.Chars.List -- [ ] `__impl__/1` -- [ ] `to_charlist/1` -## Macro -- [ ] `camelize/1` -- [ ] `decompose_call/1` -- [ ] `escape/1` -- [ ] `escape/2` -- [ ] `expand/2` -- [ ] `expand_once/2` -- [ ] `pipe/3` -- [ ] `pipe_warning/1` -- [ ] `postwalk/2` -- [ ] `postwalk/3` -- [ ] `prewalk/2` -- [ ] `prewalk/3` -- [ ] `to_string/1` -- [ ] `to_string/2` -- [ ] `traverse/4` -- [ ] `underscore/1` -- [ ] `unescape_string/1` -- [ ] `unescape_string/2` -- [ ] `unescape_tokens/1` -- [ ] `unescape_tokens/2` -- [ ] `unpipe/1` -- [ ] `update_meta/2` -- [ ] `validate/1` -- [ ] `var/2` -- [ ] `binary_ops/0` -- [ ] `unary_ops/0` -## Macro.Env -- [X] `__struct__/0` -- [X] `__struct__/1` -- [ ] `in_guard?/1` -- [ ] `in_match?/1` -- [ ] `location/1` -- [ ] `stacktrace/1` -## Map -- [X] `delete/2` -- [X] `drop/2` -- [X] `equal?/2` -- [X] `fetch/2` -- [X] `fetch!/2` -- [X] `from_struct/1` -- [X] `get/2` -- [X] `get/3` -- [X] `get_and_update/3` -- [ ] `get_and_update!/3` -- [X] `get_lazy/3` -- [X] `has_key?/2` -- [X] `keys/1` -- [X] `merge/2` -- [ ] `merge/3` -- [X] `new/0` -- [ ] `new/1` -- [ ] `new/2` -- [X] `pop/2` -- [X] `pop/3` -- [X] `pop_lazy/3` -- [X] `put/3` -- [X] `put_new/3` -- [X] `put_new_lazy/3` -- [X] `size/1` -- [X] `split/2` -- [X] `take/2` -- [X] `to_list/1` -- [X] `update/4` -- [X] `update!/3` -- [X] `values/1` -## MapSet -- [X] `__struct__/0` -- [X] `__struct__/1` -- [X] `delete/2` -- [X] `difference/2` -- [X] `disjoint?/2` -- [X] `equal?/2` -- [X] `intersection/2` -- [X] `member?/2` -- [X] `new/0` -- [ ] `new/1` -- [ ] `new/2` -- [X] `put/2` -- [X] `size/1` -- [X] `subset?/2` -- [X] `to_list/1` -- [X] `union/2` -## MatchError -- [ ] `__struct__/0` -- [ ] `__struct__/1` -- [ ] `exception/1` -- [ ] `message/1` -## Module -- [ ] `add_doc/5` -- [ ] `add_doc/6` -- [ ] `compile_doc/6` -- [ ] `concat/1` -- [ ] `concat/2` -- [ ] `create/3` -- [ ] `defines?/2` -- [ ] `defines?/3` -- [ ] `definitions_in/1` -- [ ] `definitions_in/2` -- [ ] `delete_attribute/2` -- [ ] `eval_quoted/2` -- [ ] `eval_quoted/3` -- [ ] `eval_quoted/4` -- [ ] `get_attribute/2` -- [ ] `get_attribute/3` -- [ ] `make_overridable/2` -- [ ] `open?/1` -- [ ] `overridable?/2` -- [ ] `put_attribute/3` -- [ ] `put_attribute/5` -- [ ] `register_attribute/3` -- [ ] `safe_concat/1` -- [ ] `safe_concat/2` -- [ ] `split/1` -- [ ] `store_typespec/3` -## NaiveDateTime -- [ ] `__struct__/0` -- [ ] `__struct__/1` -- [ ] `add/2` -- [ ] `add/3` -- [ ] `compare/2` -- [ ] `diff/2` -- [ ] `diff/3` -- [ ] `from_erl/1` -- [ ] `from_erl/2` -- [ ] `from_erl!/1` -- [ ] `from_erl!/2` -- [ ] `from_iso8601/1` -- [ ] `from_iso8601!/1` -- [ ] `new/2` -- [ ] `new/6` -- [ ] `new/7` -- [ ] `to_date/1` -- [ ] `to_erl/1` -- [ ] `to_iso8601/1` -- [ ] `to_string/1` -- [ ] `to_time/1` -- [ ] `utc_now/0` -## Node -- [ ] `alive?/0` -- [ ] `connect/1` -- [ ] `disconnect/1` -- [ ] `get_cookie/0` -- [ ] `list/0` -- [ ] `list/1` -- [ ] `monitor/2` -- [ ] `monitor/3` -- [ ] `ping/1` -- [ ] `self/0` -- [ ] `set_cookie/1` -- [ ] `set_cookie/2` -- [ ] `spawn/2` -- [ ] `spawn/3` -- [ ] `spawn/4` -- [ ] `spawn/5` -- [ ] `spawn_link/2` -- [ ] `spawn_link/4` -- [ ] `start/1` -- [ ] `start/2` -- [ ] `start/3` -- [ ] `stop/0` -## OptionParser -- [ ] `get_option_key/1` -- [ ] `next/1` -- [ ] `next/2` -- [ ] `parse/1` -- [ ] `parse/2` -- [ ] `parse!/1` -- [ ] `parse!/2` -- [ ] `parse_head/1` -- [ ] `parse_head/2` -- [ ] `parse_head!/1` -- [ ] `parse_head!/2` -- [ ] `split/1` -- [ ] `to_argv/1` -- [ ] `to_argv/2` -## OptionParser.ParseError -- [ ] `__struct__/0` -- [ ] `__struct__/1` -- [ ] `exception/1` -- [ ] `message/1` -## Path -- [ ] `absname/1` -- [ ] `absname/2` -- [ ] `basename/1` -- [ ] `basename/2` -- [ ] `dirname/1` -- [ ] `expand/1` -- [ ] `expand/2` -- [ ] `extname/1` -- [ ] `join/1` -- [ ] `join/2` -- [ ] `relative/1` -- [ ] `relative_to/2` -- [ ] `relative_to_cwd/1` -- [ ] `rootname/1` -- [ ] `rootname/2` -- [ ] `split/1` -- [ ] `type/1` -- [ ] `wildcard/1` -- [ ] `wildcard/2` -## Path.Wildcard -- [ ] `list_dir/1` -- [ ] `read_link_info/1` -## Port -- [ ] `close/1` -- [ ] `command/2` -- [ ] `command/3` -- [ ] `connect/2` -- [ ] `info/1` -- [ ] `info/2` -- [ ] `list/0` -- [ ] `open/2` -## Process -- [ ] `alive?/1` -- [ ] `cancel_timer/1` -- [ ] `delete/1` -- [ ] `demonitor/1` -- [ ] `demonitor/2` -- [ ] `exit/2` -- [ ] `flag/2` -- [ ] `flag/3` -- [ ] `get/0` -- [ ] `get/1` -- [ ] `get/2` -- [ ] `get_keys/0` -- [ ] `get_keys/1` -- [ ] `group_leader/0` -- [ ] `group_leader/2` -- [ ] `hibernate/3` -- [ ] `info/1` -- [ ] `info/2` -- [ ] `link/1` -- [ ] `list/0` -- [ ] `monitor/1` -- [ ] `put/2` -- [ ] `read_timer/1` -- [ ] `register/2` -- [ ] `registered/0` -- [ ] `send/3` -- [ ] `send_after/3` -- [ ] `send_after/4` -- [ ] `sleep/1` -- [ ] `spawn/2` -- [ ] `spawn/4` -- [ ] `unlink/1` -- [ ] `unregister/1` -- [ ] `whereis/1` -## Protocol -- [ ] `__builtin__/0` -- [ ] `__derive__/3` -- [ ] `__ensure_defimpl__/3` -- [ ] `__functions_spec__/1` -- [ ] `__impl__/2` -- [ ] `__protocol__/2` -- [ ] `__spec__?/3` -- [ ] `assert_impl!/2` -- [ ] `assert_protocol!/1` -- [ ] `consolidate/2` -- [ ] `consolidated?/1` -- [ ] `extract_impls/2` -- [ ] `extract_protocols/1` -- [ ] `def/1` -- [ ] `derive/2` -- [ ] `derive/3` -## Protocol.UndefinedError -- [ ] `__struct__/0` -- [ ] `__struct__/1` -- [ ] `exception/1` -- [ ] `message/1` -## Range -- [X] `__struct__/0` -- [X] `__struct__/1` -- [X] `new/2` -- [X] `range?/1` -## Record -- [ ] `__access__/4` -- [ ] `__access__/5` -- [ ] `__fields__/2` -- [ ] `__keyword__/3` -- [ ] `extract/2` -- [ ] `extract_all/1` -- [ ] `defrecord/2` -- [ ] `defrecord/3` -- [ ] `defrecordp/2` -- [ ] `defrecordp/3` -- [ ] `is_record/1` -- [ ] `is_record/2` -## Record.Extractor -- [ ] `extract/2` -- [ ] `extract_all/1` -## Regex -- [ ] `__struct__/0` -- [ ] `__struct__/1` -- [X] `compile/1` -- [X] `compile/2` -- [X] `compile!/1` -- [X] `compile!/2` -- [ ] `escape/1` -- [X] `match?/2` -- [ ] `named_captures/2` -- [ ] `named_captures/3` -- [ ] `names/1` -- [X] `opts/1` -- [ ] `re_pattern/1` -- [X] `regex?/1` -- [X] `replace/3` -- [X] `replace/4` -- [X] `run/2` -- [X] `run/3` -- [X] `scan/2` -- [X] `scan/3` -- [X] `source/1` -- [ ] `split/2` -- [ ] `split/3` -- [ ] `unescape_map/1` -## Regex.CompileError -- [ ] `__struct__/0` -- [ ] `__struct__/1` -- [ ] `exception/1` -- [ ] `message/1` -## Registry -- [ ] `dispatch/3` -- [ ] `keys/2` -- [ ] `lookup/2` -- [ ] `match/3` -- [ ] `meta/2` -- [ ] `put_meta/3` -- [ ] `register/3` -- [ ] `register_name/2` -- [ ] `send/2` -- [ ] `start_link/2` -- [ ] `start_link/3` -- [ ] `unregister/2` -- [ ] `unregister_name/1` -- [ ] `update_value/3` -- [ ] `whereis_name/1` -## RuntimeError -- [X] `__struct__/0` -- [X] `__struct__/1` -- [X] `exception/1` -- [X] `message/1` -## Set -- [ ] `delete/2` -- [ ] `difference/2` -- [ ] `disjoint?/2` -- [ ] `empty/1` -- [ ] `equal?/2` -- [ ] `intersection/2` -- [ ] `member?/2` -- [ ] `put/2` -- [ ] `size/1` -- [ ] `subset?/2` -- [ ] `to_list/1` -- [ ] `union/2` -## Stream -- [ ] `__struct__/0` -- [ ] `__struct__/1` -- [ ] `chunk/2` -- [ ] `chunk/3` -- [ ] `chunk/4` -- [ ] `chunk_by/2` -- [ ] `concat/1` -- [ ] `concat/2` -- [ ] `cycle/1` -- [ ] `dedup/1` -- [ ] `dedup_by/2` -- [ ] `drop/2` -- [ ] `drop_every/2` -- [ ] `drop_while/2` -- [ ] `each/2` -- [ ] `filter/2` -- [ ] `filter_map/3` -- [ ] `flat_map/2` -- [ ] `interval/1` -- [ ] `into/2` -- [ ] `into/3` -- [ ] `iterate/2` -- [ ] `map/2` -- [ ] `map_every/3` -- [ ] `reject/2` -- [ ] `repeatedly/1` -- [ ] `resource/3` -- [ ] `run/1` -- [ ] `scan/2` -- [ ] `scan/3` -- [ ] `take/2` -- [ ] `take_every/2` -- [ ] `take_while/2` -- [ ] `timer/1` -- [ ] `transform/3` -- [ ] `transform/4` -- [ ] `unfold/2` -- [ ] `uniq/1` -- [ ] `uniq/2` -- [ ] `uniq_by/2` -- [ ] `with_index/1` -- [ ] `with_index/2` -- [ ] `zip/1` -- [ ] `zip/2` -## String -- [X] `at/2` -- [X] `capitalize/1` -- [ ] `chunk/2` -- [X] `codepoints/1` -- [X] `contains?/2` -- [X] `downcase/1` -- [X] `duplicate/2` -- [X] `ends_with?/2` -- [ ] `equivalent?/2` -- [X] `first/1` -- [X] `graphemes/1` -- [ ] `jaro_distance/2` -- [X] `last/1` -- [X] `length/1` -- [ ] `ljust/2` -- [ ] `ljust/3` -- [ ] `lstrip/1` -- [ ] `lstrip/2` -- [X] `match?/2` -- [ ] `myers_difference/2` -- [X] `next_codepoint/1` -- [X] `next_grapheme/1` -- [ ] `next_grapheme_size/1` -- [ ] `normalize/2` -- [ ] `pad_leading/2` -- [ ] `pad_leading/3` -- [ ] `pad_trailing/2` -- [ ] `pad_trailing/3` -- [ ] `printable?/1` -- [ ] `replace/3` -- [ ] `replace/4` -- [ ] `replace_leading/3` -- [ ] `replace_prefix/3` -- [ ] `replace_suffix/3` -- [ ] `replace_trailing/3` -- [X] `reverse/1` -- [ ] `rjust/2` -- [ ] `rjust/3` -- [ ] `rstrip/1` -- [ ] `rstrip/2` -- [ ] `slice/2` -- [ ] `slice/3` -- [X] `split/1` -- [X] `split/2` -- [X] `split/3` -- [ ] `split_at/2` -- [ ] `splitter/2` -- [ ] `splitter/3` -- [X] `starts_with?/2` -- [ ] `strip/1` -- [ ] `strip/2` -- [X] `to_atom/1` -- [X] `to_char_list/1` -- [ ] `to_charlist/1` -- [X] `to_existing_atom/1` -- [X] `to_float/1` -- [X] `to_integer/1` -- [X] `to_integer/2` -- [ ] `trim/1` -- [ ] `trim/2` -- [ ] `trim_leading/1` -- [ ] `trim_leading/2` -- [ ] `trim_trailing/1` -- [ ] `trim_trailing/2` -- [X] `upcase/1` -- [ ] `valid?/1` -- [X] `valid_character?/1` -## String.Casing -- [ ] `downcase/1` -- [ ] `titlecase_once/1` -- [ ] `upcase/1` -## String.Chars -- [X] `__protocol__/1` -- [X] `impl_for/1` -- [X] `impl_for!/1` -- [X] `to_string/1` -## String.Chars.Atom -- [X] `__impl__/1` -- [X] `to_string/1` -## String.Chars.BitString -- [X] `__impl__/1` -- [X] `to_string/1` -## String.Chars.Date -- [ ] `__impl__/1` -- [ ] `to_string/1` -## String.Chars.DateTime -- [ ] `__impl__/1` -- [ ] `to_string/1` -## String.Chars.Float -- [X] `__impl__/1` -- [X] `to_string/1` -## String.Chars.Integer -- [X] `__impl__/1` -- [X] `to_string/1` -## String.Chars.List -- [X] `__impl__/1` -- [X] `to_string/1` -## String.Chars.NaiveDateTime -- [ ] `__impl__/1` -- [ ] `to_string/1` -## String.Chars.Time -- [ ] `__impl__/1` -- [ ] `to_string/1` -## String.Chars.URI -- [ ] `__impl__/1` -- [ ] `to_string/1` -## String.Chars.Version -- [ ] `__impl__/1` -- [ ] `to_string/1` -## String.Chars.Version.Requirement -- [ ] `__impl__/1` -- [ ] `to_string/1` -## String.Unicode -- [ ] `codepoints/1` -- [ ] `graphemes/1` -- [ ] `length/1` -- [ ] `next_codepoint/1` -- [ ] `next_grapheme_size/1` -- [ ] `split_at/2` -- [ ] `version/0` -## StringIO -- [ ] `close/1` -- [ ] `code_change/3` -- [ ] `contents/1` -- [ ] `flush/1` -- [ ] `handle_call/3` -- [ ] `handle_cast/2` -- [ ] `handle_info/2` -- [ ] `init/1` -- [ ] `open/1` -- [ ] `open/2` -- [ ] `terminate/2` -## Supervisor -- [ ] `count_children/1` -- [ ] `delete_child/2` -- [ ] `restart_child/2` -- [ ] `start_child/2` -- [ ] `start_link/2` -- [ ] `start_link/3` -- [ ] `stop/1` -- [ ] `stop/2` -- [ ] `stop/3` -- [ ] `terminate_child/2` -- [ ] `which_children/1` -- [ ] `__using__/1` -## Supervisor.Spec -- [ ] `supervise/2` -- [ ] `supervisor/2` -- [ ] `supervisor/3` -- [ ] `worker/2` -- [ ] `worker/3` -## SyntaxError -- [ ] `__struct__/0` -- [ ] `__struct__/1` -- [ ] `exception/1` -- [ ] `message/1` -## System -- [ ] `argv/0` -- [ ] `argv/1` -- [ ] `at_exit/1` -- [ ] `build_info/0` -- [ ] `cmd/2` -- [ ] `cmd/3` -- [ ] `compiled_endianness/0` -- [ ] `convert_time_unit/3` -- [ ] `cwd/0` -- [ ] `cwd!/0` -- [ ] `delete_env/1` -- [ ] `endianness/0` -- [ ] `find_executable/1` -- [ ] `get_env/0` -- [ ] `get_env/1` -- [ ] `get_pid/0` -- [ ] `halt/0` -- [ ] `halt/1` -- [ ] `monotonic_time/0` -- [ ] `monotonic_time/1` -- [ ] `os_time/0` -- [ ] `os_time/1` -- [ ] `otp_release/0` -- [ ] `put_env/1` -- [ ] `put_env/2` -- [ ] `schedulers/0` -- [ ] `schedulers_online/0` -- [ ] `stacktrace/0` -- [ ] `system_time/0` -- [ ] `system_time/1` -- [ ] `time_offset/0` -- [ ] `time_offset/1` -- [ ] `tmp_dir/0` -- [ ] `tmp_dir!/0` -- [ ] `unique_integer/0` -- [ ] `unique_integer/1` -- [ ] `user_home/0` -- [ ] `user_home!/0` -- [ ] `version/0` -## SystemLimitError -- [ ] `__struct__/0` -- [ ] `__struct__/1` -- [ ] `exception/1` -- [ ] `message/1` -## Task -- [ ] `__struct__/0` -- [ ] `__struct__/1` -- [ ] `async/1` -- [ ] `async/3` -- [ ] `async_stream/2` -- [ ] `async_stream/3` -- [ ] `async_stream/4` -- [ ] `async_stream/5` -- [ ] `await/1` -- [ ] `await/2` -- [ ] `find/2` -- [ ] `shutdown/1` -- [ ] `shutdown/2` -- [ ] `start/1` -- [ ] `start/3` -- [ ] `start_link/1` -- [ ] `start_link/3` -- [ ] `yield/1` -- [ ] `yield/2` -- [ ] `yield_many/1` -- [ ] `yield_many/2` -## Task.Supervisor -- [ ] `async/2` -- [ ] `async/4` -- [ ] `async_nolink/2` -- [ ] `async_nolink/4` -- [ ] `async_stream/3` -- [ ] `async_stream/4` -- [ ] `async_stream/5` -- [ ] `async_stream/6` -- [ ] `async_stream_nolink/3` -- [ ] `async_stream_nolink/4` -- [ ] `async_stream_nolink/5` -- [ ] `async_stream_nolink/6` -- [ ] `children/1` -- [ ] `start_child/2` -- [ ] `start_child/4` -- [ ] `start_link/0` -- [ ] `start_link/1` -- [ ] `terminate_child/2` -## Time -- [ ] `__struct__/0` -- [ ] `__struct__/1` -- [ ] `compare/2` -- [ ] `from_erl/1` -- [ ] `from_erl/2` -- [ ] `from_erl!/1` -- [ ] `from_erl!/2` -- [ ] `from_iso8601/1` -- [ ] `from_iso8601!/1` -- [ ] `new/3` -- [ ] `new/4` -- [ ] `to_erl/1` -- [ ] `to_iso8601/1` -- [ ] `to_string/1` -- [ ] `utc_now/0` -## TokenMissingError -- [ ] `__struct__/0` -- [ ] `__struct__/1` -- [ ] `exception/1` -- [ ] `message/1` -## TryClauseError -- [ ] `__struct__/0` -- [ ] `__struct__/1` -- [ ] `exception/1` -- [ ] `message/1` -## Tuple -- [X] `append/2` -- [X] `delete_at/2` -- [X] `duplicate/2` -- [X] `insert_at/3` -- [X] `to_list/1` -## URI -- [ ] `__struct__/0` -- [ ] `__struct__/1` -- [ ] `char_reserved?/1` -- [ ] `char_unescaped?/1` -- [ ] `char_unreserved?/1` -- [ ] `decode/1` -- [ ] `decode_query/1` -- [ ] `decode_query/2` -- [ ] `decode_www_form/1` -- [ ] `default_port/1` -- [ ] `default_port/2` -- [ ] `encode/1` -- [ ] `encode/2` -- [ ] `encode_query/1` -- [ ] `encode_www_form/1` -- [ ] `merge/2` -- [ ] `parse/1` -- [ ] `path_to_segments/1` -- [ ] `query_decoder/1` -- [ ] `to_string/1` -## UndefinedFunctionError -- [ ] `__struct__/0` -- [ ] `__struct__/1` -- [ ] `exception/1` -- [ ] `message/1` -## UnicodeConversionError -- [ ] `__struct__/0` -- [ ] `__struct__/1` -- [ ] `exception/1` -- [ ] `message/1` -## Version -- [ ] `__struct__/0` -- [ ] `__struct__/1` -- [ ] `compare/2` -- [ ] `compile_requirement/1` -- [ ] `match?/2` -- [ ] `match?/3` -- [ ] `parse/1` -- [ ] `parse!/1` -- [ ] `parse_requirement/1` -## Version.InvalidRequirementError -- [ ] `__struct__/0` -- [ ] `__struct__/1` -- [ ] `exception/1` -- [ ] `message/1` -## Version.InvalidVersionError -- [ ] `__struct__/0` -- [ ] `__struct__/1` -- [ ] `exception/1` -- [ ] `message/1` -## Version.Requirement -- [ ] `__struct__/0` -- [ ] `__struct__/1` -## WithClauseError -- [ ] `__struct__/0` -- [ ] `__struct__/1` -- [ ] `exception/1` -- [ ] `message/1` diff --git a/lib/elixir_script/gen/supported.ex b/lib/elixir_script/gen/supported.ex deleted file mode 100644 index 904ac938..00000000 --- a/lib/elixir_script/gen/supported.ex +++ /dev/null @@ -1,165 +0,0 @@ -defmodule ElixirScript.Gen.Supported do - @moduledoc false - @private_modules [ - Kernel.Utils, - String.Normalizer, - Version.Parser, - IO.ANSI.Sequence, - Version.Parser.DSL, - String.Break, - IO.ANSI.Docs, - Kernel.LexicalTracker, - Task.Supervised, - Supervisor.Default, - Registry.Partition, - Module.LocalsTracker, - Kernel.CLI, - Registry.Supervisor, - Stream.Reducers, - Agent.Server, - ] - - def generate() do - File.open!("Supported.md", [:write], &write_to_file/1) - end - - def write_to_file(file) do - IO.puts(file, "# Supported Elixir Modules") - IO.puts(file, "List all public modules in the Elixir Standard Libary. If a function or macro is supported in ElixirScript, it is checked") - module_map = get_module_list() - - Enum.each(module_map, fn({elixir_module, elixir_script_module}) -> - IO.puts(file, "## #{inspect elixir_module}") - exports = elixir_module.__info__(:functions) ++ elixir_module.__info__(:macros) - - elixir_script_exports = cond do - elixir_script_module == ElixirScript.Kernel.SpecialForms -> - extra(elixir_script_module) - Code.ensure_loaded?(elixir_script_module) -> - elixir_script_module.__info__(:functions) ++ elixir_script_module.__info__(:macros) ++ extra(elixir_script_module) - true -> - [] - end - - Enum.each(exports, fn({func, arity}) -> - if Enum.member?(elixir_script_exports, {func, arity}) do - IO.puts(file, "- [X] `#{func}/#{arity}`") - else - IO.puts(file, "- [ ] `#{func}/#{arity}`") - end - end) - end) - end - - defp get_module_list() do - Application.spec(:elixir, :modules) - |> Enum.filter(&is_public(&1)) - |> Enum.sort(fn(x, y) -> to_string(x) >= to_string(y) end) - |> Enum.reduce(Keyword.new, fn(x, acc) -> - try do - elixirscript_module = (["ElixirScript"] ++ Module.split(x)) |> Module.concat() - Keyword.put(acc, x, elixirscript_module) - rescue - FunctionClauseError -> - acc - end - end) - end - - defp is_public(m) when m in @private_modules do - false - end - - defp is_public(_) do - true - end - - defp extra(ElixirScript.Kernel.SpecialForms) do - [ - %: 2, - %{}: 1, - &: 1, - ".": 2, - "::": 2, - <<>>: 1, - =: 2, - ^: 1, - __CALLER__: 0, - __DIR__: 0, - __ENV__: 0, - __MODULE__: 0, - __aliases__: 1, - __block__: 1, - alias: 2, - case: 2, - cond: 1, - fn: 1, - for: 1, - import: 2, - quote: 2, - require: 2, - super: 1, - try: 1, - unquote: 1, - unquote_splicing: 1, - with: 1, - {}: 1, - ] - end - - defp extra(ElixirScript.Kernel) do - [ - !=: 2, - !==: 2, - *: 2, - +: 1, - +: 2, - ++: 2, - -: 1, - -: 2, - --: 2, - /: 2, - <: 2, - <=: 2, - ==: 2, - ===: 2, - =~: 2, - >: 2, - >=: 2, - div: 2, - rem: 2, - !: 1, - &&: 2, - <>: 2, - @: 1, - and: 2, - def: 1, - def: 2, - defdelegate: 2, - defexception: 1, - defimpl: 2, - defimpl: 3, - defmacro: 1, - defmacro: 2, - defmacrop: 1, - defmacrop: 2, - defmodule: 2, - defoverridable: 1, - defp: 1, - defp: 2, - defprotocol: 2, - defstruct: 1, - raise: 1, - raise: 2, - or: 2, - use: 1, - use: 2, - ||: 2, - ] - end - - - defp extra(_) do - [] - end -end \ No newline at end of file diff --git a/lib/elixir_script/next/compiler.ex b/lib/elixir_script/next/compiler.ex index 0fa7bb21..e93317d6 100644 --- a/lib/elixir_script/next/compiler.ex +++ b/lib/elixir_script/next/compiler.ex @@ -32,7 +32,6 @@ defmodule ElixirScript.Compiler do |> Map.put(:entry_modules, entry_modules) options = default_options - IO.inspect options Map.put(options, :module_formatter, get_module_formatter(options[:format])) end diff --git a/lib/elixir_script/next/passes/translate/clause.ex b/lib/elixir_script/next/passes/translate/clause.ex index ca1553ee..eafbce62 100644 --- a/lib/elixir_script/next/passes/translate/clause.ex +++ b/lib/elixir_script/next/passes/translate/clause.ex @@ -90,7 +90,7 @@ defmodule ElixirScript.Translate.Clause do [J.return_statement(J.identifier("null"))] end - defp compile_guard(params, guards, state) do + def compile_guard(params, guards, state) do guards = guards |> List.wrap diff --git a/lib/elixir_script/next/passes/translate/examples/example.ex b/lib/elixir_script/next/passes/translate/examples/example.ex index b34d3f63..768b9970 100644 --- a/lib/elixir_script/next/passes/translate/examples/example.ex +++ b/lib/elixir_script/next/passes/translate/examples/example.ex @@ -1,6 +1,16 @@ defmodule Example do def start(_, _) do - 1 + 1 +receive do + {:selector, i, value} when is_integer(i) -> + value + value when is_atom(value) -> + value + _ -> + IO.puts :stderr, "Unexpected message received" +after + 5000 -> + IO.puts :stderr, "No message in 5 seconds" +end end end diff --git a/lib/elixir_script/next/passes/translate/form.ex b/lib/elixir_script/next/passes/translate/form.ex index 72184546..9cc1abc0 100644 --- a/lib/elixir_script/next/passes/translate/form.ex +++ b/lib/elixir_script/next/passes/translate/form.ex @@ -1,9 +1,10 @@ defmodule ElixirScript.Translate.Form do alias ESTree.Tools.Builder, as: J - alias ElixirScript.Translate.Forms.{Bitstring, Match, Call, Try, For, Struct} + alias ElixirScript.Translate.Forms.{Bitstring, Match, Call, Try, For, Struct, Receive} alias ElixirScript.Translate.Functions.{Erlang, Lists, Maps} alias ElixirScript.Translator.Identifier alias ElixirScript.Translate.Clause + require Logger @erlang_modules [ :erlang, @@ -133,9 +134,11 @@ defmodule ElixirScript.Translate.Form do ) end - def compile({:receive, context, _}, _state) do + def compile({:receive, context, [blocks]}, state) do line = Keyword.get(context, :line, 1) - raise ElixirScript.CompileError, message: "Line: #{line} receive not supported" + {function, arity} = Map.get(state, :function) + Logger.warn "receive not supported, Module: #{inspect state.module}, Function: #{function}/#{arity}, Line: #{line}" + Receive.compile(blocks, state) end def compile({:try, _, [blocks]}, state) do diff --git a/lib/elixir_script/next/passes/translate/forms/receive.ex b/lib/elixir_script/next/passes/translate/forms/receive.ex new file mode 100644 index 00000000..99a25c7e --- /dev/null +++ b/lib/elixir_script/next/passes/translate/forms/receive.ex @@ -0,0 +1,26 @@ +defmodule ElixirScript.Translate.Forms.Receive do + @moduledoc false + alias ESTree.Tools.Builder, as: J + + def compile(blocks, state) do + receive_block = Keyword.get(blocks, :do) + after_block = Keyword.get(blocks, :after, nil) + + receive_function = J.member_expression( + J.member_expression( + J.identifier("Bootstrap"), + J.member_expression( + J.identifier("Core"), + J.identifier("SpecialForms") + ) + ), + J.identifier("receive") + ) + + J.call_expression( + receive_function, + [] + ) + + end +end \ No newline at end of file diff --git a/lib/elixir_script/next/passes/translate/function.ex b/lib/elixir_script/next/passes/translate/function.ex index b3204e65..50d83a2d 100644 --- a/lib/elixir_script/next/passes/translate/function.ex +++ b/lib/elixir_script/next/passes/translate/function.ex @@ -1,6 +1,8 @@ defmodule ElixirScript.Translate.Function do alias ESTree.Tools.Builder, as: J alias ElixirScript.Translate.Clause + alias ElixirScript.Translate.Forms.Pattern + alias ElixirScript.Translate.Form @moduledoc """ Translates the given Elixir function AST into the @@ -20,18 +22,108 @@ defmodule ElixirScript.Translate.Function do def compile({{name, arity}, type, _, clauses}, state) do state = Map.put(state, :function, {name, arity}) + clauses = compile_clauses(clauses, state) + + arg_matches_declarator = J.variable_declarator( + J.identifier("__arg_matches__"), + J.identifier("null") + ) + + arg_matches_declaration = J.variable_declaration([arg_matches_declarator], :let) declarator = J.variable_declarator( ElixirScript.Translator.Identifier.make_function_name(name, arity), - J.call_expression( + J.function_expression( + [J.rest_element(J.identifier("__function_args__"))], + [], + J.block_statement([ + arg_matches_declaration, + clauses, + J.throw_statement( + J.call_expression( + J.member_expression( + patterns_ast(), + J.identifier("MatchError") + ), + [J.identifier("__function_args__")] + ) + ) + ]) + ) + ) + + J.variable_declaration([declarator], :const) + end + + defp compile_clauses(clauses, state) do + clauses + |> Enum.map(&compile_clause(&1, state)) + |> Enum.map(fn {patterns, params, guards, body} -> + IO.inspect guards + match_or_default_call = J.call_expression( J.member_expression( patterns_ast(), - J.identifier("defmatch") + J.identifier("match_or_default") + ), + [J.array_expression(patterns), J.identifier("__function_args__"), guards] + ) + + J.if_statement( + J.binary_expression( + :!==, + J.assignment_expression(:=, J.identifier("__arg_matches__"), match_or_default_call), + J.identifier("null") ), - Enum.map(clauses, &Clause.compile(&1, state)) + J.block_statement(body) ) + end) + |> Enum.reverse + |> Enum.reduce(nil, fn + if_ast, nil -> + if_ast + if_ast, ast -> + %{if_ast | alternate: ast} + end) + end + + defp compile_clause({ _, args, guards, body}, state) do + {patterns, params} = Pattern.compile(args, state) + guard = Clause.compile_guard(params, guards, state) + + body = case body do + nil -> + J.identifier("null") + {:__block__, _, block_body} -> + Enum.map(block_body, &Form.compile(&1, state)) + |> List.flatten + b when is_list(b) -> + Enum.map(b, &Form.compile(&1, state)) + |> List.flatten + _ -> + Form.compile(body, state) + end + + body = Clause.return_last_statement(body) + + declarator = J.variable_declarator( + J.array_expression(params), + J.identifier("__arg_matches__") ) - J.variable_declaration([declarator], :const) + declaration = J.variable_declaration([declarator], :const) + + body = [declaration] ++ body + {patterns, params, guard, body} + end + + defp compile_clause({:->, _, [[{:when, _, params}], body ]}, state) do + guards = List.last(params) + params = params |> Enum.reverse |> tl |> Enum.reverse + + compile_clause({[], params, guards, body}, state) + end + + defp compile_clause({:->, _, [params, body]}, state) do + compile_clause({[], params, [], body}, state) end end diff --git a/lib/elixir_script/next/passes/translate/module.ex b/lib/elixir_script/next/passes/translate/module.ex index eb64d7ad..8b7c02d2 100644 --- a/lib/elixir_script/next/passes/translate/module.ex +++ b/lib/elixir_script/next/passes/translate/module.ex @@ -26,6 +26,7 @@ defmodule ElixirScript.Translate.Module do } = info state = %{ + module: module, pid: pid } diff --git a/src/javascript/lib/core/special_forms.js b/src/javascript/lib/core/special_forms.js index 7be8c643..b093fee6 100644 --- a/src/javascript/lib/core/special_forms.js +++ b/src/javascript/lib/core/special_forms.js @@ -23,7 +23,7 @@ function _for(expression, generators, collectable_protocol, into = []) { if (expression.guard.apply(this, value)) { result = fun( result, - new Core.Tuple(Symbol.for('cont'), expression.fn.apply(this, value)), + new Core.Tuple(Symbol.for('cont'), expression.fn.apply(this, value)) ); } } @@ -57,7 +57,7 @@ function _try( rescue_function, catch_fun, else_function, - after_function, + after_function ) { let result = null; @@ -141,10 +141,15 @@ function _with(...args) { return successFunction(...argsToPass); } +function receive(clauses, after) { + console.warn('Receive not supported'); +} + export default { _case, cond, _for, _try, _with, + receive, }; From 037b29b108d2b0fd4e415cd1a940d5a86f8b3d63 Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Tue, 30 May 2017 22:03:40 -0500 Subject: [PATCH 545/860] passing along state in order to increment variable count --- lib/elixir_script/next/passes/find_used.ex | 1 - .../next/passes/translate/clause.ex | 25 ++- .../next/passes/translate/examples/example.ex | 13 +- .../next/passes/translate/form.ex | 149 ++++++++++++------ .../next/passes/translate/forms/bitstring.ex | 18 +-- .../next/passes/translate/forms/call.ex | 6 +- .../next/passes/translate/forms/for.ex | 23 +-- .../next/passes/translate/forms/map.ex | 20 ++- .../next/passes/translate/forms/match.ex | 9 +- .../next/passes/translate/forms/pattern.ex | 45 +++++- .../next/passes/translate/forms/receive.ex | 3 +- .../next/passes/translate/forms/struct.ex | 6 +- .../next/passes/translate/forms/try.ex | 19 ++- .../next/passes/translate/function.ex | 17 +- .../next/passes/translate/module.ex | 4 +- 15 files changed, 239 insertions(+), 119 deletions(-) diff --git a/lib/elixir_script/next/passes/find_used.ex b/lib/elixir_script/next/passes/find_used.ex index 43faf4f4..b0bf6fbd 100644 --- a/lib/elixir_script/next/passes/find_used.ex +++ b/lib/elixir_script/next/passes/find_used.ex @@ -241,7 +241,6 @@ defmodule ElixirScript.FindUsed do end defp walk({{:., _, [module, function]}, _, params}, _state) when module in @erlang_modules do - IO.inspect {module, function, length(params)} nil end diff --git a/lib/elixir_script/next/passes/translate/clause.ex b/lib/elixir_script/next/passes/translate/clause.ex index eafbce62..57f0abce 100644 --- a/lib/elixir_script/next/passes/translate/clause.ex +++ b/lib/elixir_script/next/passes/translate/clause.ex @@ -16,7 +16,7 @@ defmodule ElixirScript.Translate.Clause do ) def compile({ _, args, guards, body}, state) do - {patterns, params} = Pattern.compile(args, state) + {patterns, params, state} = Pattern.compile(args, state) guard = compile_guard(params, guards, state) body = case body do @@ -34,7 +34,7 @@ defmodule ElixirScript.Translate.Clause do body = return_last_statement(body) - J.call_expression( + ast = J.call_expression( J.member_expression( @patterns, J.identifier("clause") @@ -49,6 +49,8 @@ defmodule ElixirScript.Translate.Clause do guard ] ) + + { ast, state } end def compile({:->, _, [[{:when, _, params}], body ]}, state) do @@ -74,6 +76,23 @@ defmodule ElixirScript.Translate.Clause do [ast] end + defp do_return_last_statement([%ESTree.VariableDeclaration{} = head | tail]) do + declaration = hd(head.declarations).id + + return_statement = case declaration do + %ESTree.ArrayPattern{elements: elements} -> + if(length(elements) == 1) do + J.return_statement(hd(declaration.elements)) + else + J.return_statement(J.array_expression(declaration.elements)) + end + _ -> + J.return_statement(declaration) + end + + [return_statement, head] ++ tail + end + defp do_return_last_statement([head]) do [J.return_statement(head)] end @@ -96,7 +115,7 @@ defmodule ElixirScript.Translate.Clause do |> List.wrap |> Enum.reverse |> process_guards - |> Form.compile(state) + |> Form.compile!(state) J.function_expression( params, diff --git a/lib/elixir_script/next/passes/translate/examples/example.ex b/lib/elixir_script/next/passes/translate/examples/example.ex index 768b9970..5db58d5a 100644 --- a/lib/elixir_script/next/passes/translate/examples/example.ex +++ b/lib/elixir_script/next/passes/translate/examples/example.ex @@ -1,16 +1,7 @@ defmodule Example do def start(_, _) do -receive do - {:selector, i, value} when is_integer(i) -> - value - value when is_atom(value) -> - value - _ -> - IO.puts :stderr, "Unexpected message received" -after - 5000 -> - IO.puts :stderr, "No message in 5 seconds" -end + a = 1 + a = 2 end end diff --git a/lib/elixir_script/next/passes/translate/form.ex b/lib/elixir_script/next/passes/translate/form.ex index 9cc1abc0..b8181a25 100644 --- a/lib/elixir_script/next/passes/translate/form.ex +++ b/lib/elixir_script/next/passes/translate/form.ex @@ -23,32 +23,42 @@ defmodule ElixirScript.Translate.Form do Handles translation of all forms that are not functions or clauses """ - def compile(nil, _) do - J.identifier("null") + def compile!(ast, state) do + {js_ast, _} = compile(ast, state) + + js_ast + end + + def compile(nil, state) do + { J.identifier("null"), state } end - def compile(form, _) when is_boolean(form) or is_integer(form) or is_float(form) or is_binary(form) do - J.literal(form) + def compile(form, state) when is_boolean(form) or is_integer(form) or is_float(form) or is_binary(form) do + { J.literal(form), state } end def compile(form, state) when is_list(form) do - J.array_expression( - Enum.map(form, &compile(&1, state)) + ast = J.array_expression( + Enum.map(form, &compile!(&1, state)) ) + + { ast, state } end def compile(form, state) when is_atom(form) do if ElixirScript.Translate.Module.is_elixir_module(form) do members = if form == Elixir, do: ["Elixir"], else: ["Elixir"] ++ Module.split(form) - J.identifier(Enum.join(members, "_")) + { J.identifier(Enum.join(members, "_")), state } else - J.call_expression( + ast = J.call_expression( J.member_expression( J.identifier("Symbol"), J.identifier("for") ), [J.literal(form)] ) + + { ast, state } end end @@ -57,7 +67,7 @@ defmodule ElixirScript.Translate.Form do end def compile({:{}, _, elements}, state) do - J.call_expression( + ast = J.call_expression( J.member_expression( J.member_expression( J.identifier("Bootstrap"), @@ -65,7 +75,7 @@ defmodule ElixirScript.Translate.Form do ), J.identifier("Tuple") ), - Enum.map(elements, &compile(&1, state)) + Enum.map(elements, &compile!(&1, state)) ) end @@ -95,19 +105,22 @@ defmodule ElixirScript.Translate.Form do ElixirScript.Translate.Function.patterns_ast(), J.identifier("defmatch") ), - Enum.map(clauses, &Clause.compile(&1, state)) + Enum.map(clauses, fn x -> Clause.compile(x, state) |> elem(0) end) ) - J.call_expression( + ast = J.call_expression( J.member_expression( func, J.identifier("call")), [J.identifier(:this), compile(condition, state)] ) + + { ast, state } end def compile({:cond, _, [[do: clauses]]}, state) do processed_clauses = Enum.map(clauses, fn({:->, _, [clause, clause_body]}) -> - translated_body = Enum.map(List.wrap(clause_body), &compile(&1, state)) - |> Clause.return_last_statement + { translated_body, state } = Enum.map_reduce(List.wrap(clause_body), state, &compile(&1, &2)) + + translated_body = Clause.return_last_statement(translated_body) translated_body = J.function_expression([], [], J.block_statement(translated_body)) translated_clause = compile(hd(clause), state) @@ -128,10 +141,12 @@ defmodule ElixirScript.Translate.Form do J.identifier("cond") ) - J.call_expression( + ast = J.call_expression( cond_function, processed_clauses ) + + { ast, state } end def compile({:receive, context, [blocks]}, state) do @@ -146,37 +161,47 @@ defmodule ElixirScript.Translate.Form do end def compile({:fn, _, clauses}, state) do - J.call_expression( + {clauses_ast, _} = Enum.map_reduce(clauses, state, &Clause.compile(&1, &2)) + + ast = J.call_expression( J.member_expression( ElixirScript.Translate.Function.patterns_ast(), J.identifier("defmatch") ), - Enum.map(clauses, &Clause.compile(&1, state)) + clauses_ast ) + + {ast, state} end def compile({{:., _, [:erlang, function]}, _, [first]}, state) when function in [:+, :-] do - J.unary_expression( + ast = J.unary_expression( function, compile(first, state), true ) + + {ast, state} end def compile({{:., _, [:erlang, :not]}, _, [first]}, state) do - J.unary_expression( + ast = J.unary_expression( :!, compile(first, state), true ) + + {ast, state} end def compile({{:., _, [:erlang, :bnot]}, _, [first]}, state) do - J.unary_expression( + ast = J.unary_expression( :"~", compile(first, state), true ) + + {ast, state} end def compile({{:., _, [:erlang, :=]}, _, [_, _] = match}, state) do @@ -184,119 +209,147 @@ defmodule ElixirScript.Translate.Form do end def compile({{:., _, [:erlang, function]}, _, [first, second]}, state) when function in [:+, :-, :*, :/, :==, :>=] do - J.binary_expression( + ast = J.binary_expression( function, compile(first, state), compile(second, state) ) + + {ast, state} end def compile({{:., _, [:erlang, :"/="]}, _, [first, second]}, state) do - J.binary_expression( + ast = J.binary_expression( :!=, compile(first, state), compile(second, state) ) + + {ast, state} end def compile({{:., _, [:erlang, :"=<"]}, _, [first, second]}, state) do - J.binary_expression( + ast = J.binary_expression( :<=, compile(first, state), compile(second, state) ) + + {ast, state} end def compile({{:., _, [:erlang, :"=:="]}, _, [first, second]}, state) do - J.binary_expression( + ast = J.binary_expression( :===, compile(first, state), compile(second, state) ) + + {ast, state} end def compile({{:., _, [:erlang, :"=/="]}, _, [first, second]}, state) do - J.binary_expression( + ast = J.binary_expression( :!==, compile(first, state), compile(second, state) ) + + {ast, state} end def compile({{:., _, [:erlang, function]}, _, [first, second]}, state) when function in [:andalso, :and] do - J.binary_expression( + ast = J.binary_expression( :&&, compile(first, state), compile(second, state) ) + + {ast, state} end def compile({{:., _, [:erlang, function]}, _, [first, second]}, state) when function in [:orelse, :or] do - J.binary_expression( + ast = J.binary_expression( :||, compile(first, state), compile(second, state) ) + + {ast, state} end def compile({{:., _, [:erlang, :div]}, _, [first, second]}, state) do - J.binary_expression( + ast = J.binary_expression( :/, compile(first, state), compile(second, state) ) + + {ast, state} end def compile({{:., _, [:erlang, :rem]}, _, [first, second]}, state) do - J.binary_expression( + ast = J.binary_expression( :mod, compile(first, state), compile(second, state) ) + + {ast, state} end def compile({{:., _, [:erlang, :band]}, _, [first, second]}, state) do - J.binary_expression( + ast = J.binary_expression( :&, compile(first, state), compile(second, state) ) + + {ast, state} end def compile({{:., _, [:erlang, :bor]}, _, [first, second]}, state) do - J.binary_expression( + ast = J.binary_expression( :|, compile(first, state), compile(second, state) ) + + {ast, state} end def compile({{:., _, [:erlang, :bsl]}, _, [first, second]}, state) do - J.binary_expression( + ast = J.binary_expression( :"<<", compile(first, state), compile(second, state) ) + + {ast, state} end def compile({{:., _, [:erlang, :bsl]}, _, [first, second]}, state) do - J.binary_expression( + ast = J.binary_expression( :">>", compile(first, state), compile(second, state) ) + + {ast, state} end def compile({{:., _, [:erlang, :bxor]}, _, [first, second]}, state) do - J.binary_expression( + ast = J.binary_expression( :">>", compile(first, state), compile(second, state) ) + + {ast, state} end def compile({{:., _, [:erlang, :++]}, _, [_, _] = params}, state) do - J.call_expression( + ast = J.call_expression( J.member_expression( J.member_expression( J.member_expression( @@ -309,10 +362,12 @@ defmodule ElixirScript.Translate.Form do ), Enum.map(params, &compile(&1, state)) ) + + {ast, state} end def compile({{:., _, [:erlang, :--]}, _, [_, _] = params}, state) do - J.call_expression( + ast = J.call_expression( J.member_expression( J.member_expression( J.member_expression( @@ -325,11 +380,13 @@ defmodule ElixirScript.Translate.Form do ), Enum.map(params, &compile(&1, state)) ) + + {ast, state} end def compile({{:., _, [module, function]}, _, params}, state) when module in @erlang_modules do - J.call_expression( + ast = J.call_expression( J.member_expression( J.member_expression( J.member_expression( @@ -340,7 +397,7 @@ defmodule ElixirScript.Translate.Form do ), ElixirScript.Translator.Identifier.make_function_name(function, length(params)) ), - Enum.map(params, &compile(&1, state)) + Enum.map(params, &compile!(&1, state)) ) end @@ -351,29 +408,33 @@ defmodule ElixirScript.Translate.Form do def compile({:super, context, params}, state) do {function_name, _} = Map.get(state, :function) - J.call_expression( + ast = J.call_expression( ElixirScript.Translator.Identifier.make_function_name(function_name, length(params)), - Enum.map(params, &compile(&1, state)) + Enum.map(params, &compile!(&1, state)) ) + + {ast, state} end def compile({function_name, _, params}, state) when is_list(params) do - case function_name do + ast = case function_name do a when is_atom(a) -> J.call_expression( ElixirScript.Translator.Identifier.make_function_name(function_name, length(params)), - Enum.map(params, &compile(&1, state)) + Enum.map(params, &compile!(&1, state)) ) _ -> J.call_expression( compile(function_name, state), - Enum.map(params, &compile(&1, state)) + Enum.map(params, &compile!(&1, state)) ) end + + {ast, state} end def compile({var, _, _}, state) do - ElixirScript.Translator.Identifier.make_identifier(var) + { ElixirScript.Translator.Identifier.make_identifier(var), state } end end diff --git a/lib/elixir_script/next/passes/translate/forms/bitstring.ex b/lib/elixir_script/next/passes/translate/forms/bitstring.ex index e6d23408..14af8f2b 100644 --- a/lib/elixir_script/next/passes/translate/forms/bitstring.ex +++ b/lib/elixir_script/next/passes/translate/forms/bitstring.ex @@ -16,15 +16,15 @@ defmodule ElixirScript.Translate.Forms.Bitstring do Enum.map(elements, &compile_element(&1, state)) ) - js_ast + { js_ast, state } end def compile_element(element, state) when is_number(element) do - do_compile_element({:integer, Form.compile(element, state)}) + do_compile_element({:integer, Form.compile!(element, state)}) end def compile_element(element, state) when is_binary(element) do - do_compile_element({:binary, Form.compile(element, state)}) + do_compile_element({:binary, Form.compile!(element, state)}) end def compile_element({:<<>>, [], elements}, state) do @@ -66,7 +66,7 @@ defmodule ElixirScript.Translate.Forms.Bitstring do end def translate_element(element, state) do - Form.compile(element, state) + Form.compile!(element, state) end defp handle_type_adjectives({:-, _, types}, ast, state) do @@ -75,10 +75,10 @@ defmodule ElixirScript.Translate.Forms.Bitstring do {:-, _, sub_types} -> handle_type_adjectives({:-, [], sub_types}, current_ast, state) {:*, _, [size, unit]} -> - size_ast = do_compile_element({:size, current_ast, [Form.compile(size, state)]}) - do_compile_element({:unit, size_ast, [Form.compile(unit, state)]}) + size_ast = do_compile_element({:size, current_ast, [Form.compile!(size, state)]}) + do_compile_element({:unit, size_ast, [Form.compile!(unit, state)]}) {the_type, _, params} when is_list(params) -> - do_compile_element({the_type, current_ast, Enum.map(params, &Form.compile(&1, state))}) + do_compile_element({the_type, current_ast, Enum.map(params, &Form.compile!(&1, state))}) {the_type, _, _} -> do_compile_element({the_type, current_ast}) end @@ -123,9 +123,9 @@ defmodule ElixirScript.Translate.Forms.Bitstring do translated_elements = Enum.map(elements, fn(x)-> case x do elem when is_binary(elem) -> - Form.compile(elem, state) + Form.compile!(elem, state) {:::, _, data} -> - Form.compile(hd(data), state) + Form.compile!(hd(data), state) end end) diff --git a/lib/elixir_script/next/passes/translate/forms/call.ex b/lib/elixir_script/next/passes/translate/forms/call.ex index 0715538a..cd6cb269 100644 --- a/lib/elixir_script/next/passes/translate/forms/call.ex +++ b/lib/elixir_script/next/passes/translate/forms/call.ex @@ -11,13 +11,15 @@ defmodule ElixirScript.Translate.Forms.Call do ElixirScript.Translator.Identifier.make_function_name(function, length(params)) end - J.call_expression( + ast = J.call_expression( J.member_expression( process_module_name(module, state), function_name ), - Enum.map(params, &Form.compile(&1, state)) + Enum.map(params, &Form.compile!(&1, state)) ) + + {ast, state} end defp process_module_name(module, state) when is_atom(module) do diff --git a/lib/elixir_script/next/passes/translate/forms/for.ex b/lib/elixir_script/next/passes/translate/forms/for.ex index 5c8aeb42..930b6a10 100644 --- a/lib/elixir_script/next/passes/translate/forms/for.ex +++ b/lib/elixir_script/next/passes/translate/forms/for.ex @@ -33,7 +33,7 @@ defmodule ElixirScript.Translate.Forms.For do JS.identifier("Collectable") ) - JS.call_expression( + ast = JS.call_expression( JS.member_expression( JS.member_expression( JS.identifier("Bootstrap"), @@ -46,6 +46,8 @@ defmodule ElixirScript.Translate.Forms.For do ), [expression, generators, collectable, into] ) + + {ast, state} end defp handle_args(nil, module_state) do @@ -63,7 +65,7 @@ defmodule ElixirScript.Translate.Forms.For do {var, collection} end) - {patterns, params} = Pattern.compile([{:<<>>, [], bs_parts}], module_state) + {patterns, params, state} = Pattern.compile([{:<<>>, [], bs_parts}], module_state) gen = JS.call_expression( JS.member_expression( @@ -76,13 +78,13 @@ defmodule ElixirScript.Translate.Forms.For do ), JS.identifier("bitstring_generator") ), - [hd(patterns), Form.compile(collection, module_state)] + [hd(patterns), Form.compile!(collection, module_state)] ) %{state | generators: state.generators ++ [gen], args: state.args ++ params, patterns: state.patterns ++ patterns} ({:<-, _, [identifier, enum]}, state) -> - {patterns, params} = Pattern.compile([identifier], module_state) + {patterns, params, module_state} = Pattern.compile([identifier], module_state) gen = JS.call_expression( JS.member_expression( @@ -95,17 +97,17 @@ defmodule ElixirScript.Translate.Forms.For do ), JS.identifier("list_generator") ), - [hd(patterns), Form.compile(enum, module_state)] + [hd(patterns), Form.compile!(enum, module_state)] ) %{state | generators: state.generators ++ [gen], args: state.args ++ params, patterns: state.patterns ++ patterns} ([into: expression], state) -> - %{state | into: Form.compile(expression, module_state)} + %{state | into: Form.compile!(expression, module_state)} ([into: expression, do: expression2], state) -> fun = create_function_expression(expression2, state, module_state) - %{state | into: Form.compile(expression, module_state), fun: fun} + %{state | into: Form.compile!(expression, module_state), fun: fun} ([do: expression], state) -> fun = create_function_expression(expression, state, module_state) @@ -120,8 +122,11 @@ defmodule ElixirScript.Translate.Forms.For do defp create_function_expression(ast, state, module_state) do - ast = Enum.map(List.wrap(ast), &Form.compile(&1, module_state)) - |> Clause.return_last_statement + { ast, module_state } = Enum.map_reduce(List.wrap(ast), module_state, fn x, acc_state -> + Form.compile(x, acc_state) + end) + + ast = Clause.return_last_statement(ast) JS.function_expression( state.args, diff --git a/lib/elixir_script/next/passes/translate/forms/map.ex b/lib/elixir_script/next/passes/translate/forms/map.ex index a33624ef..54aa74de 100644 --- a/lib/elixir_script/next/passes/translate/forms/map.ex +++ b/lib/elixir_script/next/passes/translate/forms/map.ex @@ -3,10 +3,10 @@ defmodule ElixirScript.Translate.Forms.Map do alias ElixirScript.Translate.Form def compile({:%{}, _, [{:|, _, [map, new_values]}]}, state) do - map = Form.compile(map, state) - data = Form.compile({:%{}, [], new_values}, state) + { map, state } = Form.compile(map, state) + { data, state } = Form.compile({:%{}, [], new_values}, state) - J.call_expression( + ast = J.call_expression( J.member_expression( J.member_expression( J.identifier("Bootstrap"), @@ -19,20 +19,28 @@ defmodule ElixirScript.Translate.Forms.Map do ), [map, data] ) + + { ast, state } end def compile({:%{}, _, properties}, state) do - properties + ast = properties |> Enum.map(fn ({x, y}) -> case x do {_, _, nil } -> - J.property(Form.compile(x, state), Form.compile(y, state), :init, false, false, true) + {key, _} = Form.compile(x, state) + {value, _} = Form.compile(y, state) + J.property(key, value, :init, false, false, true) _ -> - make_property(Form.compile(x, state), Form.compile(y, state)) + {key, _} = Form.compile(x, state) + {value, _} = Form.compile(y, state) + make_property(key, value) end end) |> J.object_expression + + {ast, state} end def make_property(%ESTree.Identifier{} = key, value) do diff --git a/lib/elixir_script/next/passes/translate/forms/match.ex b/lib/elixir_script/next/passes/translate/forms/match.ex index 67fabcc2..9dbd453c 100644 --- a/lib/elixir_script/next/passes/translate/forms/match.ex +++ b/lib/elixir_script/next/passes/translate/forms/match.ex @@ -4,9 +4,9 @@ defmodule ElixirScript.Translate.Forms.Match do alias ElixirScript.Translate.Forms.{Pattern} def compile({:=, _, [left, right]}, state) do - right_ast = Form.compile(right, state) + { right_ast, state } = Form.compile(right, state) - { patterns, params } = Pattern.compile([left], state) + { patterns, params, state } = Pattern.compile([left], state) declarator = J.variable_declarator( J.array_pattern(params), @@ -38,7 +38,7 @@ defmodule ElixirScript.Translate.Forms.Match do array_pattern end - js_ast + { js_ast, state } end @@ -83,8 +83,7 @@ defmodule ElixirScript.Translate.Forms.Match do defp make_variable_declaration_and_group(ref_declarator, array_pattern) do ref_declaration = J.variable_declaration([ref_declarator], :let) - #[array_pattern, ref_declaration] - array_pattern + [array_pattern, ref_declaration] end end \ No newline at end of file diff --git a/lib/elixir_script/next/passes/translate/forms/pattern.ex b/lib/elixir_script/next/passes/translate/forms/pattern.ex index 5ed3ba6b..08c5fa5d 100644 --- a/lib/elixir_script/next/passes/translate/forms/pattern.ex +++ b/lib/elixir_script/next/passes/translate/forms/pattern.ex @@ -2,7 +2,7 @@ defmodule ElixirScript.Translate.Forms.Pattern do alias ElixirScript.Translator.PatternMatching, as: PM alias ESTree.Tools.Builder, as: J alias ElixirScript.Translate.Form - alias ElixirScript.Translate.Forms.{Bitstring, Map} + alias ElixirScript.Translate.Forms.{Bitstring} @moduledoc """ Handles all pattern matching translations @@ -15,14 +15,43 @@ defmodule ElixirScript.Translate.Forms.Pattern do {pattern, param} = process_pattern(x, state) { patterns ++ List.wrap(pattern), params ++ List.wrap(param) } end) + |> update_env(state) + end + + defp update_env({ patterns, params }, state) do + { params, state } = Enum.map_reduce(params, state, fn + (%ESTree.Identifier{name: :undefined} = param, state) -> + { param, state } + + (%ESTree.Identifier{} = param, state) -> + state = update_variable(param.name, state) + new_name = get_variable_name(param.name, state) + + { %{ param | name: new_name }, state } + + (param, state) -> + { param, state } + end) + + { patterns, params, state } + end + + defp get_variable_name(function, state) do + number = Map.get(state.vars, function) + String.to_atom("#{function}#{number}") + end + + defp update_variable(name, state) do + vars = Map.update(state.vars, name, 0, fn val -> val + 1 end) + Map.put(state, :vars, vars) end defp process_pattern(term, state) when is_number(term) or is_binary(term) or is_boolean(term) or is_atom(term) or is_nil(term) do - { [Form.compile(term, state)], [] } + { [Form.compile!(term, state)], [] } end defp process_pattern({:^, _, [value]}, state) do - { [PM.bound(Form.compile(value, state))], [nil] } + { [PM.bound(Form.compile!(value, state))], [nil] } end defp process_pattern({:_, _, _}, _) do @@ -34,7 +63,7 @@ defmodule ElixirScript.Translate.Forms.Pattern do end defp process_pattern({:{}, _, elements }, state) do - { patterns, params } = elements + { patterns, params, state } = elements |> Enum.map(&compile([&1], state)) |> reduce_patterns(state) @@ -57,7 +86,7 @@ defmodule ElixirScript.Translate.Forms.Pattern do end defp process_pattern(list, state) when is_list(list) do - { patterns, params } = list + { patterns, params, state } = list |> Enum.map(&compile([&1], state)) |> reduce_patterns(state) @@ -69,9 +98,9 @@ defmodule ElixirScript.Translate.Forms.Pattern do {pattern, params} = process_pattern(value, state) property = case key do {:^, _, [the_key]} -> - J.property(Form.compile(the_key, state), hd(List.wrap(pattern)), :init, false, false, true) + J.property(Form.compile!(the_key, state), hd(List.wrap(pattern)), :init, false, false, true) _ -> - Map.make_property(Form.compile(key, state), hd(List.wrap(pattern))) + ElixirScript.Translate.Forms.Map.make_property(Form.compile!(key, state), hd(List.wrap(pattern))) end { property, params } @@ -112,7 +141,7 @@ defmodule ElixirScript.Translate.Forms.Pattern do end defp process_pattern({:<>, _, [prefix, value]}, state) do - { [PM.starts_with(prefix)], [Form.compile(value, state)] } + { [PM.starts_with(prefix)], [Form.compile!(value, state)] } end defp process_pattern({:=, _, [{name, _, _}, right]}, state) do diff --git a/lib/elixir_script/next/passes/translate/forms/receive.ex b/lib/elixir_script/next/passes/translate/forms/receive.ex index 99a25c7e..8d021a7e 100644 --- a/lib/elixir_script/next/passes/translate/forms/receive.ex +++ b/lib/elixir_script/next/passes/translate/forms/receive.ex @@ -17,10 +17,11 @@ defmodule ElixirScript.Translate.Forms.Receive do J.identifier("receive") ) - J.call_expression( + ast = J.call_expression( receive_function, [] ) + { ast, state } end end \ No newline at end of file diff --git a/lib/elixir_script/next/passes/translate/forms/struct.ex b/lib/elixir_script/next/passes/translate/forms/struct.ex index 4b4e83fd..e88bc492 100644 --- a/lib/elixir_script/next/passes/translate/forms/struct.ex +++ b/lib/elixir_script/next/passes/translate/forms/struct.ex @@ -4,13 +4,15 @@ defmodule ElixirScript.Translate.Forms.Struct do alias ElixirScript.Translator.Identifier def compile({:%, _, [module, params]}, state) do - J.call_expression( + ast = J.call_expression( J.member_expression( process_module_name(module), J.identifier("__struct__1") ), - [Form.compile(params, state)] + [Form.compile!(params, state)] ) + + { ast, state } end defp process_module_name(module) do diff --git a/lib/elixir_script/next/passes/translate/forms/try.ex b/lib/elixir_script/next/passes/translate/forms/try.ex index 940bc7ae..dafaacb3 100644 --- a/lib/elixir_script/next/passes/translate/forms/try.ex +++ b/lib/elixir_script/next/passes/translate/forms/try.ex @@ -23,7 +23,7 @@ defmodule ElixirScript.Translate.Forms.Try do end catch_block = if catch_block do - Form.compile({:fn, [], catch_block}, state) + Form.compile!({:fn, [], catch_block}, state) else JS.identifier(:null) end @@ -35,7 +35,7 @@ defmodule ElixirScript.Translate.Forms.Try do end else_block = if else_block do - Form.compile({:fn, [], else_block}, state) + Form.compile!({:fn, [], else_block}, state) else JS.identifier(:null) end @@ -60,15 +60,17 @@ defmodule ElixirScript.Translate.Forms.Try do ] ) - js_ast + { js_ast, state } end defp process_rescue_block(rescue_block, state) do processed_clauses = Enum.map(rescue_block, fn {:->, _, [ [{:in, _, [param, names]} = pattern], body]} -> - Clause.compile({[], [param], [{{:., [], [Enum, :member?]}, [], [param, names]}], body}, state) + {ast, _} = Clause.compile({[], [param], [{{:., [], [Enum, :member?]}, [], [param, names]}], body}, state) + ast {:->, _, [ [param], body]} -> - Clause.compile({[], [param], [], body}, state) + {ast, _} = Clause.compile({[], [param], [], body}, state) + ast end) @@ -90,9 +92,10 @@ defmodule ElixirScript.Translate.Forms.Try do end defp prepare_function_body(body, state) do - body + {ast, state} = body |> List.wrap - |> Enum.map(&Form.compile(&1, state)) - |> Clause.return_last_statement + |> Enum.map_reduce(state, &Form.compile(&1, &2)) + + Clause.return_last_statement(ast) end end diff --git a/lib/elixir_script/next/passes/translate/function.ex b/lib/elixir_script/next/passes/translate/function.ex index 50d83a2d..1844ad31 100644 --- a/lib/elixir_script/next/passes/translate/function.ex +++ b/lib/elixir_script/next/passes/translate/function.ex @@ -52,14 +52,13 @@ defmodule ElixirScript.Translate.Function do ) ) - J.variable_declaration([declarator], :const) + { J.variable_declaration([declarator], :const), state } end defp compile_clauses(clauses, state) do clauses |> Enum.map(&compile_clause(&1, state)) |> Enum.map(fn {patterns, params, guards, body} -> - IO.inspect guards match_or_default_call = J.call_expression( J.member_expression( patterns_ast(), @@ -87,20 +86,22 @@ defmodule ElixirScript.Translate.Function do end defp compile_clause({ _, args, guards, body}, state) do - {patterns, params} = Pattern.compile(args, state) + state = Map.put(state, :vars, %{}) + + {patterns, params, state} = Pattern.compile(args, state) guard = Clause.compile_guard(params, guards, state) body = case body do nil -> J.identifier("null") {:__block__, _, block_body} -> - Enum.map(block_body, &Form.compile(&1, state)) - |> List.flatten + {list, _} = Enum.map_reduce(block_body, state, &Form.compile(&1, &2)) + List.flatten(list) b when is_list(b) -> - Enum.map(b, &Form.compile(&1, state)) - |> List.flatten + {list, _} = Enum.map_reduce(b, state, &Form.compile(&1, &2)) + List.flatten(list) _ -> - Form.compile(body, state) + Form.compile!(body, state) end body = Clause.return_last_statement(body) diff --git a/lib/elixir_script/next/passes/translate/module.ex b/lib/elixir_script/next/passes/translate/module.ex index 8b7c02d2..79a7b3fb 100644 --- a/lib/elixir_script/next/passes/translate/module.ex +++ b/lib/elixir_script/next/passes/translate/module.ex @@ -49,8 +49,8 @@ defmodule ElixirScript.Translate.Module do end - compiled_functions = used_defs - |> Enum.map(&Function.compile(&1, state)) + { compiled_functions, _ } = used_defs + |> Enum.map_reduce(state, &Function.compile(&1, &2)) exports = make_exports(used_defs) From 7150eeeef92726afa4f4366eab9609c9c5849f4a Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Wed, 31 May 2017 19:57:27 -0500 Subject: [PATCH 546/860] Update elixirscript cli and mix task to use new compiler --- lib/elixir_script/cli.ex | 48 +++++++++----------- lib/elixir_script/watcher.ex | 2 +- lib/mix/tasks/compile.elixir_script.ex | 63 +++++++++----------------- lib/mix/tasks/elixirscript.watch.ex | 38 ++-------------- mix.exs | 16 ++----- package.json | 2 +- test/{app/src => support}/main.ex | 0 test/{app/src => support}/user.ex | 0 8 files changed, 54 insertions(+), 115 deletions(-) rename test/{app/src => support}/main.ex (100%) rename test/{app/src => support}/user.ex (100%) diff --git a/lib/elixir_script/cli.ex b/lib/elixir_script/cli.ex index e1e573eb..6910d561 100644 --- a/lib/elixir_script/cli.ex +++ b/lib/elixir_script/cli.ex @@ -4,13 +4,19 @@ defmodule ElixirScript.CLI do @app_version Mix.Project.config()[:version] @switches [ - output: :string, elixir: :boolean, - help: :boolean, full_build: :boolean, version: :boolean, - watch: :boolean, format: :string, js_module: [:string, :keep], remove_unused: :boolean + output: :string, + help: :boolean, + version: :boolean, + watch: :boolean, + format: :string, + js_module: [:string, :keep] ] @aliases [ - o: :output, e: :elixir, h: :help, v: :version, f: :format + o: :output, + h: :help, + v: :version, + f: :format ] def main(argv) do @@ -39,9 +45,8 @@ defmodule ElixirScript.CLI do def help_message() do """ - usage: elixirscript [options] - path to elixir files or - the elixir code string if passed the -e flag + usage: elixirscript [options] + the entry module of your application options: --js-module [:] A js module used in your code. ex: React:react @@ -49,9 +54,6 @@ defmodule ElixirScript.CLI do -f --format [format] module format of output. options: es (default), common, umd -o --output [path] places output at the given path. Can be a directory or filename. - -e --elixir read input as elixir code string - --remove-unused Removes unused modules from output - --full-build informs the compiler to do a full build instead of an incremental one -v --version the current version number -h --help this message """ @@ -79,27 +81,18 @@ defmodule ElixirScript.CLI do js_modules = Keyword.get_values(options, :js_module) |> build_js_modules - compile_opts = %{ - include_path: true, - core_path: Keyword.get(options, :core_path, "Elixir.Bootstrap"), - full_build: Keyword.get(options, :full_build, false), + compile_opts = [ output: Keyword.get(options, :output, :stdout), format: String.to_atom(Keyword.get(options, :format, "es")), js_modules: js_modules, - remove_unused: Keyword.get(options, :remove_unused, false) - } + ] - case options[:elixir] do - true -> - ElixirScript.compile(input, compile_opts) - _ -> - input = handle_input(input) - ElixirScript.compile_path(input, compile_opts) - - if watch do - ElixirScript.Watcher.start_link(input, compile_opts) - :timer.sleep :infinity - end + input = handle_input(input) + ElixirScript.Compiler.compile(input, compile_opts) + + if watch do + ElixirScript.Watcher.start_link(input, compile_opts) + :timer.sleep :infinity end end @@ -117,6 +110,7 @@ defmodule ElixirScript.CLI do input = input |> Enum.map(fn(x) -> String.split(x, [" ", ","], trim: true) end) |> List.flatten + |> Enum.map(fn(x) -> Module.concat([x]) end) end defp build_js_modules(values) do diff --git a/lib/elixir_script/watcher.ex b/lib/elixir_script/watcher.ex index b54cc03e..8d484de1 100644 --- a/lib/elixir_script/watcher.ex +++ b/lib/elixir_script/watcher.ex @@ -24,7 +24,7 @@ defmodule ElixirScript.Watcher do try do if input_changed?(to_string(path), state) do Logger.debug "Event: #{inspect event} Path: #{path}" - ElixirScript.compile_path(state[:input], state[:options]) + ElixirScript.Compiler.compile(state[:input], state[:options]) end rescue x -> diff --git a/lib/mix/tasks/compile.elixir_script.ex b/lib/mix/tasks/compile.elixir_script.ex index e448a117..0abf7e9c 100644 --- a/lib/mix/tasks/compile.elixir_script.ex +++ b/lib/mix/tasks/compile.elixir_script.ex @@ -14,13 +14,13 @@ defmodule Mix.Tasks.Compile.ElixirScript do version: "0.1.0", elixir: "~> 1.0", deps: deps, - elixir_script: [ input: "src/exjs", output: "dest/js"], - compilers: [:elixir_script] ++ Mix.compilers + elixir_script: [ entry: Example, output: "dest/js"], + compilers: Mix.compilers ++ [:elixir_script] ] end Available options are: - * `input`: The folder to look for Elixirscript files in. (defaults to `lib/elixirscript`) + * `input`: The module or modules that are the entry to your application (required) * `output`: The path of the generated JavaScript file. (defaults to `priv/elixirscript`) If path ends in `.js` then that will be the name of the file. If a directory is given, @@ -47,50 +47,30 @@ defmodule Mix.Tasks.Compile.ElixirScript do end defp do_compile(elixirscript_base, app) do - elixirscript_config = get_elixirscript_config() - File.mkdir_p!(elixirscript_base) - elixirscript_path = Path.join([elixirscript_base, "#{app}"]) - - input_path = elixirscript_config - |> Keyword.get(:input) - |> List.wrap - |> Enum.map(fn(path) -> - Path.absname(path) - end) - |> Enum.join("\n") - - File.write!(elixirscript_path, input_path) - - paths = [elixirscript_base, "*"] - |> Path.join() - |> Path.wildcard - |> Enum.map(fn(path) -> - app = Path.basename(path) - paths = path |> File.read!() |> String.split("\n") - {app, paths} - end) - |> Map.new - - output_path = Keyword.get(elixirscript_config, :output) - format = Keyword.get(elixirscript_config, :format) - js_modules = Keyword.get(elixirscript_config, :js_modules, []) - - ElixirScript.compile_path(paths, %{output: output_path, format: format, js_modules: js_modules}) + + {input, opts} = get_compiler_params() + ElixirScript.compiler.compile(input, opts) end def clean do - elixirscript_config = get_elixirscript_config() - output_path = Keyword.get(elixirscript_config, :output) - - path = ElixirScript.Passes.HandleOutput.get_js_path(output_path) - - if File.exists?(path) do - File.rm!(path) - end - + #TODO: Figure out how to clean :ok end + @doc false + def get_compiler_params() do + elixirscript_config = get_elixirscript_config() + input = Keyword.fetch!(elixirscript_config, :input) + opts = [ + output: Keyword.get(elixirscript_config, :output), + format: Keyword.get(elixirscript_config, :format), + js_modules: Keyword.get(elixirscript_config, :js_modules, []) + ] + + {input, opts} + end + + defp get_elixirscript_config() do config = Mix.Project.config exjs_config = cond do @@ -107,7 +87,6 @@ defmodule Mix.Tasks.Compile.ElixirScript do defp defaults() do [ - input: "lib/elixirscript", output: "priv/elixirscript", format: :es ] diff --git a/lib/mix/tasks/elixirscript.watch.ex b/lib/mix/tasks/elixirscript.watch.ex index ace5bbc6..5235d700 100644 --- a/lib/mix/tasks/elixirscript.watch.ex +++ b/lib/mix/tasks/elixirscript.watch.ex @@ -14,51 +14,23 @@ defmodule Mix.Tasks.Elixirscript.Watch do version: "0.1.0", elixir: "~> 1.0", deps: deps, - elixir_script: [ input: "src/exjs", output: "dest/js"], - compilers: [:elixir_script] ++ Mix.compilers + elixir_script: [ input: Example, output: "dest/js"], + compilers: Mix.compilers ++ [:elixir_script] ] end """ - - def run(_) do Mix.Task.run "app.start" - elixirscript_config = get_elixirscript_config() - input_path = Keyword.get(elixirscript_config, :input) - output_path = Keyword.get(elixirscript_config, :output) - format = Keyword.get(elixirscript_config, :format) - js_modules = Keyword.get(elixirscript_config, :js_modules, []) + {input, opts} = Mix.Tasks.Compile.ElixirScript.get_compiler_params() {:ok, _} = ElixirScript.Watcher.start_link( - input_path, - %{output: output_path, format: format, js_modules: js_modules} + input, + opts ) :timer.sleep :infinity end - defp get_elixirscript_config() do - config = Mix.Project.config - exjs_config = cond do - Keyword.has_key?(config, :elixir_script) -> - Keyword.get(config, :elixir_script, []) - Keyword.has_key?(config, :elixirscript) -> - Keyword.get(config, :elixirscript, []) - true -> - defaults() - end - - Keyword.merge(defaults(), exjs_config) - end - - defp defaults() do - [ - input: "lib/elixirscript", - output: "priv/elixirscript", - format: :es - ] - end - end diff --git a/mix.exs b/mix.exs index a9b380f3..8a5a9573 100644 --- a/mix.exs +++ b/mix.exs @@ -5,8 +5,8 @@ defmodule ElixirScript.Mixfile do [ app: :elixir_script, version: "0.28.0-dev", - elixir: "~> 1.0", - elixirc_paths: elixirc_paths(), + elixir: "~> 1.5-dev", + elixirc_paths: elixirc_paths(Mix.env), escript: escript_config(), deps: deps(), description: description(), @@ -36,7 +36,8 @@ defmodule ElixirScript.Mixfile do ] end - defp elixirc_paths(), do: ["lib", "priv/std_lib"] + defp elixirc_paths(:test), do: ["lib", "priv/std_lib", "test/support"] + defp elixirc_paths(_), do: ["lib", "priv/std_lib"] defp escript_config do [main_module: ElixirScript.CLI, name: "elixirscript"] @@ -62,8 +63,7 @@ defmodule ElixirScript.Mixfile do defp aliases do [dist: &dist/1, - install: &install/1, - supported: &supported/1] + install: &install/1] end def dist(_) do @@ -106,10 +106,4 @@ defmodule ElixirScript.Mixfile do IO.puts("installed at /usr/local/elixirscript") end - def supported(_) do - Mix.Task.run "app.start" - - ElixirScript.Gen.Supported.generate() - end - end diff --git a/package.json b/package.json index 90b86fb4..55cc3f34 100644 --- a/package.json +++ b/package.json @@ -12,7 +12,7 @@ "build": "rollup -c rollup.config.js", "clean": "rm -rf priv/build", "test": "nyc ava src/javascript/tests", - "build:test-app": "mix elixirscript test/app/src/ -f common -o test/app/build/", + "build:test-app": "MIX_ENV=test mix elixirscript Main -f common -o test/app/build/", "test-app": "yarn run build:test-app && NODE_ENV=test ava 'test/app/spec/**/*.spec.js'" }, "repository": { diff --git a/test/app/src/main.ex b/test/support/main.ex similarity index 100% rename from test/app/src/main.ex rename to test/support/main.ex diff --git a/test/app/src/user.ex b/test/support/user.ex similarity index 100% rename from test/app/src/user.ex rename to test/support/user.ex From 30aa2fab7ed59e77ef1b1fedc9b6392c819fb7ae Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Wed, 31 May 2017 22:00:48 -0500 Subject: [PATCH 547/860] Fix some compilation errors found from testing --- .../next/passes/translate/examples/example.ex | 3 +- .../next/passes/translate/form.ex | 25 +++++++++++++---- .../next/passes/translate/forms/pattern.ex | 28 +++++++++++++------ 3 files changed, 41 insertions(+), 15 deletions(-) diff --git a/lib/elixir_script/next/passes/translate/examples/example.ex b/lib/elixir_script/next/passes/translate/examples/example.ex index 5db58d5a..6d09d63f 100644 --- a/lib/elixir_script/next/passes/translate/examples/example.ex +++ b/lib/elixir_script/next/passes/translate/examples/example.ex @@ -1,7 +1,8 @@ defmodule Example do def start(_, _) do a = 1 - a = 2 + [d, b, c] = [1, 2, 3] + [e | g] = [1, 2, 3] end end diff --git a/lib/elixir_script/next/passes/translate/form.ex b/lib/elixir_script/next/passes/translate/form.ex index b8181a25..9024fde1 100644 --- a/lib/elixir_script/next/passes/translate/form.ex +++ b/lib/elixir_script/next/passes/translate/form.ex @@ -46,20 +46,20 @@ defmodule ElixirScript.Translate.Form do end def compile(form, state) when is_atom(form) do - if ElixirScript.Translate.Module.is_elixir_module(form) do + ast = if ElixirScript.Translate.Module.is_elixir_module(form) do members = if form == Elixir, do: ["Elixir"], else: ["Elixir"] ++ Module.split(form) - { J.identifier(Enum.join(members, "_")), state } + J.identifier(Enum.join(members, "_")) else - ast = J.call_expression( + J.call_expression( J.member_expression( J.identifier("Symbol"), J.identifier("for") ), [J.literal(form)] ) - - { ast, state } end + + { ast, state } end def compile({a, b}, state) do @@ -77,6 +77,8 @@ defmodule ElixirScript.Translate.Form do ), Enum.map(elements, &compile!(&1, state)) ) + + {ast, state} end def compile({:%{}, _, _} = map, state) do @@ -384,6 +386,15 @@ defmodule ElixirScript.Translate.Form do {ast, state} end + def compile({{:., _, [function_name]}, _, params}, state) do + ast = J.call_expression( + compile!(function_name, state), + Enum.map(params, &compile!(&1, state)) + ) + + {ast, state} + end + def compile({{:., _, [module, function]}, _, params}, state) when module in @erlang_modules do ast = J.call_expression( @@ -399,6 +410,8 @@ defmodule ElixirScript.Translate.Form do ), Enum.map(params, &compile!(&1, state)) ) + + {ast, state} end def compile({{:., _, [_, _]}, _, _} = ast, state) do @@ -425,7 +438,7 @@ defmodule ElixirScript.Translate.Form do ) _ -> J.call_expression( - compile(function_name, state), + compile!(function_name, state), Enum.map(params, &compile!(&1, state)) ) end diff --git a/lib/elixir_script/next/passes/translate/forms/pattern.ex b/lib/elixir_script/next/passes/translate/forms/pattern.ex index 08c5fa5d..8cbab551 100644 --- a/lib/elixir_script/next/passes/translate/forms/pattern.ex +++ b/lib/elixir_script/next/passes/translate/forms/pattern.ex @@ -10,12 +10,16 @@ defmodule ElixirScript.Translate.Forms.Pattern do def compile(patterns, state) do patterns - |> Enum.reduce({[], []}, fn + |> do_compile(state) + |> update_env(state) + end + + defp do_compile(patterns, state) do + Enum.reduce(patterns, {[], []}, fn x, { patterns, params } -> {pattern, param} = process_pattern(x, state) { patterns ++ List.wrap(pattern), params ++ List.wrap(param) } - end) - |> update_env(state) + end) end defp update_env({ patterns, params }, state) do @@ -63,8 +67,8 @@ defmodule ElixirScript.Translate.Forms.Pattern do end defp process_pattern({:{}, _, elements }, state) do - { patterns, params, state } = elements - |> Enum.map(&compile([&1], state)) + { patterns, params } = elements + |> Enum.map(&do_compile([&1], state)) |> reduce_patterns(state) pattern = J.object_expression([ @@ -86,13 +90,21 @@ defmodule ElixirScript.Translate.Forms.Pattern do end defp process_pattern(list, state) when is_list(list) do - { patterns, params, state } = list - |> Enum.map(&compile([&1], state)) + { patterns, params } = list + |> Enum.map(&do_compile([&1], state)) |> reduce_patterns(state) {[J.array_expression(patterns)], params} end + defp process_pattern({:|, _, [head, tail]}, state) do + { head_patterns, head_params } = process_pattern(head, state) + { tail_patterns, tail_params } = process_pattern(tail, state) + params = head_params ++ tail_params + + { [PM.head_tail(hd(head_patterns), hd(tail_patterns))], params } + end + defp process_pattern({:%{}, _, props}, state) do properties = Enum.map(props, fn({key, value}) -> {pattern, params} = process_pattern(value, state) @@ -164,7 +176,7 @@ defmodule ElixirScript.Translate.Forms.Pattern do end defp unify(target, source, state) do - { patterns, params } = compile([source], state) + { patterns, params } = do_compile([source], state) { [PM.capture(hd(patterns))], params ++ [ElixirScript.Translator.Identifier.make_identifier(target)] } end end From e5dabf516a7dff3e8447a106887603b4996e5a74 Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Thu, 1 Jun 2017 19:23:43 -0500 Subject: [PATCH 548/860] Combining functions with same names and different arities --- .../next/passes/translate/clause.ex | 4 +-- .../next/passes/translate/examples/example.ex | 1 - .../next/passes/translate/form.ex | 8 +++--- .../next/passes/translate/forms/call.ex | 2 +- .../next/passes/translate/forms/for.ex | 4 +-- .../next/passes/translate/forms/try.ex | 4 +-- .../next/passes/translate/function.ex | 2 +- .../next/passes/translate/module.ex | 16 +++++++++-- .../next/passes/translate/protocol.ex | 4 +-- .../kernel/special_forms/identifier.ex | 4 +-- .../lib/core/erlang_compat/erlang.js | 12 ++++---- .../lib/core/erlang_compat/lists.js | 4 +-- src/javascript/lib/core/erlang_compat/maps.js | 8 +++--- .../tests/core/erlang_compat/erlang_spec.js | 28 +++++++++---------- .../tests/core/erlang_compat/lists_spec.js | 4 +-- .../tests/core/erlang_compat/maps_spec.js | 14 +++++----- 16 files changed, 64 insertions(+), 55 deletions(-) diff --git a/lib/elixir_script/next/passes/translate/clause.ex b/lib/elixir_script/next/passes/translate/clause.ex index 57f0abce..1747c8a3 100644 --- a/lib/elixir_script/next/passes/translate/clause.ex +++ b/lib/elixir_script/next/passes/translate/clause.ex @@ -41,7 +41,7 @@ defmodule ElixirScript.Translate.Clause do ), [ J.array_expression(patterns), - J.function_expression( + J.arrow_function_expression( params, [], J.block_statement(body) @@ -117,7 +117,7 @@ defmodule ElixirScript.Translate.Clause do |> process_guards |> Form.compile!(state) - J.function_expression( + J.arrow_function_expression( params, [], J.block_statement([ diff --git a/lib/elixir_script/next/passes/translate/examples/example.ex b/lib/elixir_script/next/passes/translate/examples/example.ex index 6d09d63f..438be849 100644 --- a/lib/elixir_script/next/passes/translate/examples/example.ex +++ b/lib/elixir_script/next/passes/translate/examples/example.ex @@ -4,5 +4,4 @@ defmodule Example do [d, b, c] = [1, 2, 3] [e | g] = [1, 2, 3] end - end diff --git a/lib/elixir_script/next/passes/translate/form.ex b/lib/elixir_script/next/passes/translate/form.ex index 9024fde1..32d7af28 100644 --- a/lib/elixir_script/next/passes/translate/form.ex +++ b/lib/elixir_script/next/passes/translate/form.ex @@ -123,7 +123,7 @@ defmodule ElixirScript.Translate.Form do { translated_body, state } = Enum.map_reduce(List.wrap(clause_body), state, &compile(&1, &2)) translated_body = Clause.return_last_statement(translated_body) - translated_body = J.function_expression([], [], J.block_statement(translated_body)) + translated_body = J.arrow_function_expression([], [], J.block_statement(translated_body)) translated_clause = compile(hd(clause), state) @@ -406,7 +406,7 @@ defmodule ElixirScript.Translate.Form do ), J.identifier(module) ), - ElixirScript.Translator.Identifier.make_function_name(function, length(params)) + ElixirScript.Translator.Identifier.make_function_name(function) ), Enum.map(params, &compile!(&1, state)) ) @@ -422,7 +422,7 @@ defmodule ElixirScript.Translate.Form do {function_name, _} = Map.get(state, :function) ast = J.call_expression( - ElixirScript.Translator.Identifier.make_function_name(function_name, length(params)), + ElixirScript.Translator.Identifier.make_function_name(function_name), Enum.map(params, &compile!(&1, state)) ) @@ -433,7 +433,7 @@ defmodule ElixirScript.Translate.Form do ast = case function_name do a when is_atom(a) -> J.call_expression( - ElixirScript.Translator.Identifier.make_function_name(function_name, length(params)), + ElixirScript.Translator.Identifier.make_function_name(function_name), Enum.map(params, &compile!(&1, state)) ) _ -> diff --git a/lib/elixir_script/next/passes/translate/forms/call.ex b/lib/elixir_script/next/passes/translate/forms/call.ex index cd6cb269..704330bd 100644 --- a/lib/elixir_script/next/passes/translate/forms/call.ex +++ b/lib/elixir_script/next/passes/translate/forms/call.ex @@ -8,7 +8,7 @@ defmodule ElixirScript.Translate.Forms.Call do ElixirScript.Translate.Module.is_js_module(module, state) -> ElixirScript.Translator.Identifier.make_extern_function_name(function) true -> - ElixirScript.Translator.Identifier.make_function_name(function, length(params)) + ElixirScript.Translator.Identifier.make_function_name(function) end ast = J.call_expression( diff --git a/lib/elixir_script/next/passes/translate/forms/for.ex b/lib/elixir_script/next/passes/translate/forms/for.ex index 930b6a10..940773da 100644 --- a/lib/elixir_script/next/passes/translate/forms/for.ex +++ b/lib/elixir_script/next/passes/translate/forms/for.ex @@ -10,7 +10,7 @@ defmodule ElixirScript.Translate.Forms.For do generators = JS.array_expression(args.generators) into = args.into || JS.array_expression([]) - filter = args.filter || JS.function_expression([], [], JS.block_statement([JS.return_statement(JS.identifier("true"))])) + filter = args.filter || JS.arrow_function_expression([], [], JS.block_statement([JS.return_statement(JS.identifier("true"))])) fun = args.fun @@ -128,7 +128,7 @@ defmodule ElixirScript.Translate.Forms.For do ast = Clause.return_last_statement(ast) - JS.function_expression( + JS.arrow_function_expression( state.args, [], JS.block_statement(ast) diff --git a/lib/elixir_script/next/passes/translate/forms/try.ex b/lib/elixir_script/next/passes/translate/forms/try.ex index dafaacb3..52bf3076 100644 --- a/lib/elixir_script/next/passes/translate/forms/try.ex +++ b/lib/elixir_script/next/passes/translate/forms/try.ex @@ -14,7 +14,7 @@ defmodule ElixirScript.Translate.Forms.Try do translated_body = prepare_function_body(try_block, state) translated_body = JS.block_statement(translated_body) - try_block = JS.function_expression([], [], translated_body) + try_block = JS.arrow_function_expression([], [], translated_body) rescue_block = if rescue_block do process_rescue_block(rescue_block, state) @@ -88,7 +88,7 @@ defmodule ElixirScript.Translate.Forms.Try do translated_body = prepare_function_body(after_block, state) translated_body = JS.block_statement(translated_body) - JS.function_expression([], [], translated_body) + JS.arrow_function_expression([], [], translated_body) end defp prepare_function_body(body, state) do diff --git a/lib/elixir_script/next/passes/translate/function.ex b/lib/elixir_script/next/passes/translate/function.ex index 1844ad31..aee6819c 100644 --- a/lib/elixir_script/next/passes/translate/function.ex +++ b/lib/elixir_script/next/passes/translate/function.ex @@ -32,7 +32,7 @@ defmodule ElixirScript.Translate.Function do arg_matches_declaration = J.variable_declaration([arg_matches_declarator], :let) declarator = J.variable_declarator( - ElixirScript.Translator.Identifier.make_function_name(name, arity), + ElixirScript.Translator.Identifier.make_function_name(name), J.function_expression( [J.rest_element(J.identifier("__function_args__"))], [], diff --git a/lib/elixir_script/next/passes/translate/module.ex b/lib/elixir_script/next/passes/translate/module.ex index 79a7b3fb..e447f9b2 100644 --- a/lib/elixir_script/next/passes/translate/module.ex +++ b/lib/elixir_script/next/passes/translate/module.ex @@ -48,11 +48,21 @@ defmodule ElixirScript.Translate.Module do end) end + #we combine our function arities + combined_defs = used_defs + |> Enum.sort(fn { {name1, arity1}, _, _, _ }, { {name2, arity2}, _, _, _ } -> "#{name1}#{arity1}" < "#{name2}#{arity2}" end) + |> Enum.group_by(fn {{name, _}, _, _, _ } -> name end) + |> Enum.map(fn {group, funs} -> + {_, type, _, _} = hd(funs) + Enum.reduce(funs, {{group, nil}, type, [], []}, fn {_, _, _, clauses}, {name, type, context, acc_clauses} -> + {name, type, context, acc_clauses ++ clauses} + end) + end) - { compiled_functions, _ } = used_defs + { compiled_functions, _ } = combined_defs |> Enum.map_reduce(state, &Function.compile(&1, &2)) - exports = make_exports(used_defs) + exports = make_exports(combined_defs) js_ast = ElixirScript.ModuleSystems.Namespace.build( module, @@ -67,7 +77,7 @@ defmodule ElixirScript.Translate.Module do defp make_exports(reachable_defs) do exports = Enum.reduce(reachable_defs, [], fn {{name, arity}, :def, _, _}, list -> - function_name = ElixirScript.Translator.Identifier.make_function_name(name, arity) + function_name = ElixirScript.Translator.Identifier.make_identifier(name) list ++ [J.property(function_name, function_name, :init, true)] _, list -> list diff --git a/lib/elixir_script/next/passes/translate/protocol.ex b/lib/elixir_script/next/passes/translate/protocol.ex index 0b549292..d64375bd 100644 --- a/lib/elixir_script/next/passes/translate/protocol.ex +++ b/lib/elixir_script/next/passes/translate/protocol.ex @@ -11,8 +11,8 @@ defmodule ElixirScript.Translate.Protocol do This compiles and consolidates the given protocol """ def compile(module, %{protocol: true, impls: impls, functions: functions} = info, pid) do - object = Enum.map(functions, fn {function, arity} -> - {Identifier.make_function_name(function, arity), J.function_expression([], [], J.block_statement([]))} + object = Enum.map(functions, fn {function, _} -> + {Identifier.make_function_name(function), J.function_expression([], [], J.block_statement([]))} end) |> Enum.map(fn({key, value}) -> ElixirScript.Translate.Forms.Map.make_property(key, value) end) |> J.object_expression diff --git a/lib/elixir_script/translator/kernel/special_forms/identifier.ex b/lib/elixir_script/translator/kernel/special_forms/identifier.ex index 99586343..584082e6 100644 --- a/lib/elixir_script/translator/kernel/special_forms/identifier.ex +++ b/lib/elixir_script/translator/kernel/special_forms/identifier.ex @@ -86,9 +86,9 @@ defmodule ElixirScript.Translator.Identifier do |> make_alias end - def make_function_name(name, arity) when is_atom(name) do + def make_function_name(name) when is_atom(name) do name = filter_name(name) - JS.identifier("#{name}#{arity}") + JS.identifier(name) end def make_extern_function_name(name) do diff --git a/src/javascript/lib/core/erlang_compat/erlang.js b/src/javascript/lib/core/erlang_compat/erlang.js index 0b09676c..81b89a66 100644 --- a/src/javascript/lib/core/erlang_compat/erlang.js +++ b/src/javascript/lib/core/erlang_compat/erlang.js @@ -1,6 +1,6 @@ // http://erlang.org/doc/man/erlang.html -function atom_to_binary2(atom, encoding = Symbol.for('utf8')) { +function atom_to_binary(atom, encoding = Symbol.for('utf8')) { if (encoding !== Symbol.for('utf8')) { throw new Error(`unsupported encoding ${encoding}`); } @@ -8,11 +8,11 @@ function atom_to_binary2(atom, encoding = Symbol.for('utf8')) { return Symbol.keyFor(atom); } -function list_concatenation2(list1, list2) { +function list_concatenation(list1, list2) { return list1.concat(list2); } -function list_subtraction2(list1, list2) { +function list_subtraction(list1, list2) { const list = [...list1]; for (const item of list2) { @@ -27,7 +27,7 @@ function list_subtraction2(list1, list2) { } export default { - atom_to_binary2, - list_concatenation2, - list_subtraction2, + atom_to_binary, + list_concatenation, + list_subtraction, }; diff --git a/src/javascript/lib/core/erlang_compat/lists.js b/src/javascript/lib/core/erlang_compat/lists.js index 1d2814df..8157461d 100644 --- a/src/javascript/lib/core/erlang_compat/lists.js +++ b/src/javascript/lib/core/erlang_compat/lists.js @@ -1,9 +1,9 @@ // http://erlang.org/doc/man/lists.html -function reverse1(list) { +function reverse(list) { return [...list].reverse(); } export default { - reverse1, + reverse, }; diff --git a/src/javascript/lib/core/erlang_compat/maps.js b/src/javascript/lib/core/erlang_compat/maps.js index 97e42b91..fdda87d3 100644 --- a/src/javascript/lib/core/erlang_compat/maps.js +++ b/src/javascript/lib/core/erlang_compat/maps.js @@ -5,7 +5,7 @@ const OK = Symbol.for('ok'); const ERROR = Symbol.for('error'); const BADMAP = Symbol.for('badmap'); -function find2(key, map) { +function find(key, map) { if (map instanceof Object === false) { return new ErlangTypes.Tuple(BADMAP, map); } @@ -19,7 +19,7 @@ function find2(key, map) { return ERROR; } -function fold3(fun, init, map) { +function fold(fun, init, map) { let acc = init; for (const [key, value] of Object.entries(map)) { @@ -30,6 +30,6 @@ function fold3(fun, init, map) { } export default { - find2, - fold3, + find, + fold, }; diff --git a/src/javascript/tests/core/erlang_compat/erlang_spec.js b/src/javascript/tests/core/erlang_compat/erlang_spec.js index 31460192..6bc6d4d0 100644 --- a/src/javascript/tests/core/erlang_compat/erlang_spec.js +++ b/src/javascript/tests/core/erlang_compat/erlang_spec.js @@ -1,23 +1,23 @@ import test from 'ava'; import Core from '../../../lib/core'; -test('atom_to_binary2', t => { - t.is(Core.erlang.atom_to_binary2(Symbol.for('error')), 'error'); +test('atom_to_binary', t => { + t.is(Core.erlang.atom_to_binary(Symbol.for('error')), 'error'); t.is( - Core.erlang.atom_to_binary2(Symbol.for('error'), Symbol.for('utf8')), + Core.erlang.atom_to_binary(Symbol.for('error'), Symbol.for('utf8')), 'error' ); t.throws( - () => Core.erlang.atom_to_binary2(Symbol.for('error'), Symbol.for('utf16')), + () => Core.erlang.atom_to_binary(Symbol.for('error'), Symbol.for('utf16')), Error ); }); -test('list_concatenation2', t => { - t.deepEqual(Core.erlang.list_concatenation2([], []), []); - t.deepEqual(Core.erlang.list_concatenation2([1], []), [1]); - t.deepEqual(Core.erlang.list_concatenation2([1, 2, 3], [4, 5, 6]), [ +test('list_concatenation', t => { + t.deepEqual(Core.erlang.list_concatenation([], []), []); + t.deepEqual(Core.erlang.list_concatenation([1], []), [1]); + t.deepEqual(Core.erlang.list_concatenation([1, 2, 3], [4, 5, 6]), [ 1, 2, 3, @@ -27,10 +27,10 @@ test('list_concatenation2', t => { ]); }); -test('list_subtraction2', t => { - t.deepEqual(Core.erlang.list_subtraction2([], []), []); - t.deepEqual(Core.erlang.list_subtraction2([1], []), [1]); - t.deepEqual(Core.erlang.list_subtraction2([1, 2, 3], [4, 5, 6]), [1, 2, 3]); - t.deepEqual(Core.erlang.list_subtraction2([1, 2, 3], [1, 2, 3]), []); - t.deepEqual(Core.erlang.list_subtraction2([1, 2, 3], [1, 2]), [3]); +test('list_subtraction', t => { + t.deepEqual(Core.erlang.list_subtraction([], []), []); + t.deepEqual(Core.erlang.list_subtraction([1], []), [1]); + t.deepEqual(Core.erlang.list_subtraction([1, 2, 3], [4, 5, 6]), [1, 2, 3]); + t.deepEqual(Core.erlang.list_subtraction([1, 2, 3], [1, 2, 3]), []); + t.deepEqual(Core.erlang.list_subtraction([1, 2, 3], [1, 2]), [3]); }); diff --git a/src/javascript/tests/core/erlang_compat/lists_spec.js b/src/javascript/tests/core/erlang_compat/lists_spec.js index e86e6d46..4e3fbb4e 100644 --- a/src/javascript/tests/core/erlang_compat/lists_spec.js +++ b/src/javascript/tests/core/erlang_compat/lists_spec.js @@ -1,6 +1,6 @@ import test from 'ava'; import Core from '../../../lib/core'; -test('reverse1', t => { - t.deepEqual(Core.lists.reverse1([1, 2, 3]), [3, 2, 1]); +test('reverse', t => { + t.deepEqual(Core.lists.reverse([1, 2, 3]), [3, 2, 1]); }); diff --git a/src/javascript/tests/core/erlang_compat/maps_spec.js b/src/javascript/tests/core/erlang_compat/maps_spec.js index 41d78acd..805c7172 100644 --- a/src/javascript/tests/core/erlang_compat/maps_spec.js +++ b/src/javascript/tests/core/erlang_compat/maps_spec.js @@ -1,22 +1,22 @@ import test from 'ava'; import Core from '../../../lib/core'; -test('find2', t => { +test('find', t => { let myMap = {}; - let result = Core.maps.find2('t', myMap); + let result = Core.maps.find('t', myMap); t.is(result, Symbol.for('error')); myMap = 'Hello'; - result = Core.maps.find2('t', myMap); + result = Core.maps.find('t', myMap); t.deepEqual(result.values, [Symbol.for('badmap'), myMap]); myMap = { t: 'b' }; - result = Core.maps.find2('t', myMap); + result = Core.maps.find('t', myMap); t.deepEqual(result.values, [Symbol.for('ok'), 'b']); }); -test('fold3', t => { - let myMap = { a: 1, b: 2 }; - let result = Core.maps.fold3((k, v, acc) => acc + v, 0, myMap); +test('fold', t => { + const myMap = { a: 1, b: 2 }; + const result = Core.maps.fold((k, v, acc) => acc + v, 0, myMap); t.is(result, 3); }); From a125a003433f8af19ae713553d2d42b7d45e4fa0 Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Fri, 2 Jun 2017 07:42:23 -0500 Subject: [PATCH 549/860] Add remote test. --- .../next/passes/translate/clause.ex | 10 +- .../next/passes/translate/examples/example.ex | 11 +- .../next/passes/translate/form.ex | 277 +----------------- .../next/passes/translate/forms/call.ex | 41 --- .../next/passes/translate/forms/pattern.ex | 6 +- .../next/passes/translate/forms/remote.ex | 163 +++++++++++ .../kernel/special_forms/identifier.ex | 2 +- .../lib/core/erlang_compat/erlang.js | 118 ++++++++ .../passes/translate/forms/remote_test.exs | 14 + 9 files changed, 322 insertions(+), 320 deletions(-) delete mode 100644 lib/elixir_script/next/passes/translate/forms/call.ex create mode 100644 lib/elixir_script/next/passes/translate/forms/remote.ex create mode 100644 test/next/passes/translate/forms/remote_test.exs diff --git a/lib/elixir_script/next/passes/translate/clause.ex b/lib/elixir_script/next/passes/translate/clause.ex index 1747c8a3..dca321a1 100644 --- a/lib/elixir_script/next/passes/translate/clause.ex +++ b/lib/elixir_script/next/passes/translate/clause.ex @@ -23,13 +23,13 @@ defmodule ElixirScript.Translate.Clause do nil -> J.identifier("null") {:__block__, _, block_body} -> - Enum.map(block_body, &Form.compile(&1, state)) - |> List.flatten + {list, _} = Enum.map_reduce(block_body, state, &Form.compile(&1, &2)) + List.flatten(list) b when is_list(b) -> - Enum.map(b, &Form.compile(&1, state)) - |> List.flatten + {list, _} = Enum.map_reduce(b, state, &Form.compile(&1, &2)) + List.flatten(list) _ -> - Form.compile(body, state) + Form.compile!(body, state) end body = return_last_statement(body) diff --git a/lib/elixir_script/next/passes/translate/examples/example.ex b/lib/elixir_script/next/passes/translate/examples/example.ex index 438be849..49367a3d 100644 --- a/lib/elixir_script/next/passes/translate/examples/example.ex +++ b/lib/elixir_script/next/passes/translate/examples/example.ex @@ -1,7 +1,10 @@ defmodule Example do - def start(_, _) do - a = 1 - [d, b, c] = [1, 2, 3] - [e | g] = [1, 2, 3] + def start(v, _) do + case v do + :normal -> + "yolo" + _ -> + "yolo too" + end end end diff --git a/lib/elixir_script/next/passes/translate/form.ex b/lib/elixir_script/next/passes/translate/form.ex index 32d7af28..55aefe78 100644 --- a/lib/elixir_script/next/passes/translate/form.ex +++ b/lib/elixir_script/next/passes/translate/form.ex @@ -1,24 +1,11 @@ defmodule ElixirScript.Translate.Form do alias ESTree.Tools.Builder, as: J - alias ElixirScript.Translate.Forms.{Bitstring, Match, Call, Try, For, Struct, Receive} + alias ElixirScript.Translate.Forms.{Bitstring, Match, Try, For, Struct, Receive, Remote} alias ElixirScript.Translate.Functions.{Erlang, Lists, Maps} alias ElixirScript.Translator.Identifier alias ElixirScript.Translate.Clause require Logger - @erlang_modules [ - :erlang, - :maps, - :lists, - :gen, - :elixir_errors, - :supervisor, - :application, - :code, - :elixir_utils, - :file - ] - @moduledoc """ Handles translation of all forms that are not functions or clauses """ @@ -112,7 +99,7 @@ defmodule ElixirScript.Translate.Form do ast = J.call_expression( J.member_expression( func, J.identifier("call")), - [J.identifier(:this), compile(condition, state)] + [J.identifier(:this), compile!(condition, state)] ) { ast, state } @@ -176,276 +163,30 @@ defmodule ElixirScript.Translate.Form do {ast, state} end - def compile({{:., _, [:erlang, function]}, _, [first]}, state) when function in [:+, :-] do - ast = J.unary_expression( - function, - compile(first, state), - true - ) - - {ast, state} - end - - def compile({{:., _, [:erlang, :not]}, _, [first]}, state) do - ast = J.unary_expression( - :!, - compile(first, state), - true - ) - - {ast, state} - end - - def compile({{:., _, [:erlang, :bnot]}, _, [first]}, state) do - ast = J.unary_expression( - :"~", - compile(first, state), - true - ) - - {ast, state} - end - - def compile({{:., _, [:erlang, :=]}, _, [_, _] = match}, state) do - Match.compile(match, state) - end - - def compile({{:., _, [:erlang, function]}, _, [first, second]}, state) when function in [:+, :-, :*, :/, :==, :>=] do - ast = J.binary_expression( - function, - compile(first, state), - compile(second, state) - ) - - {ast, state} - end - - def compile({{:., _, [:erlang, :"/="]}, _, [first, second]}, state) do - ast = J.binary_expression( - :!=, - compile(first, state), - compile(second, state) - ) - - {ast, state} - end - - def compile({{:., _, [:erlang, :"=<"]}, _, [first, second]}, state) do - ast = J.binary_expression( - :<=, - compile(first, state), - compile(second, state) - ) - - {ast, state} - end - - def compile({{:., _, [:erlang, :"=:="]}, _, [first, second]}, state) do - ast = J.binary_expression( - :===, - compile(first, state), - compile(second, state) - ) - - {ast, state} - end - - def compile({{:., _, [:erlang, :"=/="]}, _, [first, second]}, state) do - ast = J.binary_expression( - :!==, - compile(first, state), - compile(second, state) - ) - - {ast, state} - end - - def compile({{:., _, [:erlang, function]}, _, [first, second]}, state) when function in [:andalso, :and] do - ast = J.binary_expression( - :&&, - compile(first, state), - compile(second, state) - ) - - {ast, state} - end - - def compile({{:., _, [:erlang, function]}, _, [first, second]}, state) when function in [:orelse, :or] do - ast = J.binary_expression( - :||, - compile(first, state), - compile(second, state) - ) - - {ast, state} - end - - def compile({{:., _, [:erlang, :div]}, _, [first, second]}, state) do - ast = J.binary_expression( - :/, - compile(first, state), - compile(second, state) - ) - - {ast, state} - end - - def compile({{:., _, [:erlang, :rem]}, _, [first, second]}, state) do - ast = J.binary_expression( - :mod, - compile(first, state), - compile(second, state) - ) - - {ast, state} - end - - def compile({{:., _, [:erlang, :band]}, _, [first, second]}, state) do - ast = J.binary_expression( - :&, - compile(first, state), - compile(second, state) - ) - - {ast, state} - end - - def compile({{:., _, [:erlang, :bor]}, _, [first, second]}, state) do - ast = J.binary_expression( - :|, - compile(first, state), - compile(second, state) - ) - - {ast, state} - end - - def compile({{:., _, [:erlang, :bsl]}, _, [first, second]}, state) do - ast = J.binary_expression( - :"<<", - compile(first, state), - compile(second, state) - ) - - {ast, state} - end - - def compile({{:., _, [:erlang, :bsl]}, _, [first, second]}, state) do - ast = J.binary_expression( - :">>", - compile(first, state), - compile(second, state) - ) - - {ast, state} - end - - def compile({{:., _, [:erlang, :bxor]}, _, [first, second]}, state) do - ast = J.binary_expression( - :">>", - compile(first, state), - compile(second, state) - ) - - {ast, state} - end - - def compile({{:., _, [:erlang, :++]}, _, [_, _] = params}, state) do - ast = J.call_expression( - J.member_expression( - J.member_expression( - J.member_expression( - J.identifier("Bootstrap"), - J.identifier("Core") - ), - J.identifier(:erlang) - ), - J.identifier("list_concatenation2") - ), - Enum.map(params, &compile(&1, state)) - ) - - {ast, state} - end - - def compile({{:., _, [:erlang, :--]}, _, [_, _] = params}, state) do - ast = J.call_expression( - J.member_expression( - J.member_expression( - J.member_expression( - J.identifier("Bootstrap"), - J.identifier("Core") - ), - J.identifier(:erlang) - ), - J.identifier("list_substraction2") - ), - Enum.map(params, &compile(&1, state)) - ) - - {ast, state} - end - - def compile({{:., _, [function_name]}, _, params}, state) do - ast = J.call_expression( - compile!(function_name, state), - Enum.map(params, &compile!(&1, state)) - ) - - {ast, state} + def compile({:., _, call} = ast, state) when is_list(call) do + Remote.compile(ast, state) end + def compile({:super, context, params}, state) when is_list(params) do + {function_name, _} = Map.get(state, :function) - def compile({{:., _, [module, function]}, _, params}, state) when module in @erlang_modules do ast = J.call_expression( - J.member_expression( - J.member_expression( - J.member_expression( - J.identifier("Bootstrap"), - J.identifier("Core") - ), - J.identifier(module) - ), - ElixirScript.Translator.Identifier.make_function_name(function) - ), + ElixirScript.Translator.Identifier.make_function_name(function_name), Enum.map(params, &compile!(&1, state)) ) {ast, state} end - def compile({{:., _, [_, _]}, _, _} = ast, state) do - Call.compile(ast, state) - end - - def compile({:super, context, params}, state) do - {function_name, _} = Map.get(state, :function) - + def compile({function, _, params}, state) when is_list(params) do ast = J.call_expression( - ElixirScript.Translator.Identifier.make_function_name(function_name), + compile!(function, state), Enum.map(params, &compile!(&1, state)) ) {ast, state} end - def compile({function_name, _, params}, state) when is_list(params) do - ast = case function_name do - a when is_atom(a) -> - J.call_expression( - ElixirScript.Translator.Identifier.make_function_name(function_name), - Enum.map(params, &compile!(&1, state)) - ) - _ -> - J.call_expression( - compile!(function_name, state), - Enum.map(params, &compile!(&1, state)) - ) - end - - {ast, state} - end - def compile({var, _, _}, state) do { ElixirScript.Translator.Identifier.make_identifier(var), state } end diff --git a/lib/elixir_script/next/passes/translate/forms/call.ex b/lib/elixir_script/next/passes/translate/forms/call.ex deleted file mode 100644 index 704330bd..00000000 --- a/lib/elixir_script/next/passes/translate/forms/call.ex +++ /dev/null @@ -1,41 +0,0 @@ -defmodule ElixirScript.Translate.Forms.Call do - alias ESTree.Tools.Builder, as: J - alias ElixirScript.Translate.Form - alias ElixirScript.Translator.Identifier - - def compile({{:., _, [module, function]}, _, params}, state) do - function_name = cond do - ElixirScript.Translate.Module.is_js_module(module, state) -> - ElixirScript.Translator.Identifier.make_extern_function_name(function) - true -> - ElixirScript.Translator.Identifier.make_function_name(function) - end - - ast = J.call_expression( - J.member_expression( - process_module_name(module, state), - function_name - ), - Enum.map(params, &Form.compile!(&1, state)) - ) - - {ast, state} - end - - defp process_module_name(module, state) when is_atom(module) do - cond do - ElixirScript.Translate.Module.is_js_module(module, state) -> - members = tl(Module.split(module)) - Identifier.make_namespace_members(members) - ElixirScript.Translate.Module.is_elixir_module(module) -> - members = ["Elixir"] ++ Module.split(module) - J.identifier(Enum.join(members, "_")) - true -> - ElixirScript.Translator.Identifier.make_identifier(module) - end - end - - defp process_module_name(module, state) do - Form.compile(module, state) - end -end diff --git a/lib/elixir_script/next/passes/translate/forms/pattern.ex b/lib/elixir_script/next/passes/translate/forms/pattern.ex index 8cbab551..bb5f29ab 100644 --- a/lib/elixir_script/next/passes/translate/forms/pattern.ex +++ b/lib/elixir_script/next/passes/translate/forms/pattern.ex @@ -122,7 +122,7 @@ defmodule ElixirScript.Translate.Forms.Pattern do { props ++ [prop], params ++ param } end) - { J.object_expression(List.wrap(props)), params } + { [J.object_expression(List.wrap(props))], params } end defp process_pattern({:<<>>, _, elements}, state) do @@ -152,6 +152,10 @@ defmodule ElixirScript.Translate.Forms.Pattern do { [PM.head_tail(hd(head_patterns), hd(tail_patterns))], params } end + defp process_pattern({{:., _, [:erlang, :++]}, _, [prefix, value]}, state) do + { [PM.starts_with(prefix)], [Form.compile!(value, state)] } + end + defp process_pattern({:<>, _, [prefix, value]}, state) do { [PM.starts_with(prefix)], [Form.compile!(value, state)] } end diff --git a/lib/elixir_script/next/passes/translate/forms/remote.ex b/lib/elixir_script/next/passes/translate/forms/remote.ex new file mode 100644 index 00000000..5736e752 --- /dev/null +++ b/lib/elixir_script/next/passes/translate/forms/remote.ex @@ -0,0 +1,163 @@ +defmodule ElixirScript.Translate.Forms.Remote do + alias ESTree.Tools.Builder, as: J + alias ElixirScript.Translate.Form + alias ElixirScript.Translator.Identifier + + @erlang_modules [ + :erlang, + :maps, + :lists, + :gen, + :elixir_errors, + :supervisor, + :application, + :code, + :elixir_utils, + :file + ] + + def compile({:., _, [:erlang, :+]}, state) do + ast = erlang_compat_function("erlang", "plus") + { ast, state } + end + + def compile({:., _, [:erlang, :-]}, state) do + ast = erlang_compat_function("erlang", "minus") + { ast, state } + end + + def compile({:., _, [:erlang, :*]}, state) do + ast = erlang_compat_function("erlang", "multiply") + { ast, state } + end + + def compile({:., _, [:erlang, :/]}, state) do + ast = erlang_compat_function("erlang", "div") + { ast, state } + end + + def compile({:., _, [:erlang, :==]}, state) do + ast = erlang_compat_function("erlang", "equal") + { ast, state } + end + + def compile({:., _, [:erlang, :>]}, state) do + ast = erlang_compat_function("erlang", "greaterThan") + { ast, state } + end + + def compile({:., _, [:erlang, :>=]}, state) do + ast = erlang_compat_function("erlang", "greaterThanOrEqualTo") + { ast, state } + end + + def compile({:., _, [:erlang, :"/="]}, state) do + ast = erlang_compat_function("erlang", "doesNotEqual") + { ast, state } + end + + def compile({:., _, [:erlang, :"<"]}, state) do + ast = erlang_compat_function("erlang", "lessThan") + { ast, state } + end + + def compile({:., _, [:erlang, :"=<"]}, state) do + ast = erlang_compat_function("erlang", "lessThanOrEqualTo") + { ast, state } + end + + def compile({:., _, [:erlang, :"=:="]}, state) do + ast = erlang_compat_function("erlang", "strictlyEqual") + { ast, state } + end + + def compile({:., _, [:erlang, :"=/="]}, state) do + ast = erlang_compat_function("erlang", "doesNotStrictlyEqual") + { ast, state } + end + + def compile({:., _, [:erlang, function]}, state) when function in [:andalso, :and] do + ast = erlang_compat_function("erlang", "and") + { ast, state } + end + + def compile({:., _, [:erlang, function]}, state) when function in [:orelse, :or] do + ast = erlang_compat_function("erlang", "or") + { ast, state } + end + + def compile({:., _, [:erlang, :++]}, state) do + ast = erlang_compat_function("erlang", "list_concatenation") + { ast, state } + end + + def compile({:., _, [:erlang, :--]}, state) do + ast = erlang_compat_function("erlang", "list_substraction") + { ast, state } + end + + def compile({:., _, [module, function]}, state) when module in @erlang_modules do + ast = J.member_expression( + J.member_expression( + J.member_expression( + J.identifier("Bootstrap"), + J.identifier("Core") + ), + J.identifier(module) + ), + ElixirScript.Translator.Identifier.make_function_name(function) + ) + + { ast, state } + end + + def compile({:., _, [function_name]}, state) do + Form.compile(function_name, state) + end + + def compile({:., _, [module, function]}, state) do + function_name = cond do + ElixirScript.Translate.Module.is_js_module(module, state) -> + ElixirScript.Translator.Identifier.make_extern_function_name(function) + true -> + ElixirScript.Translator.Identifier.make_function_name(function) + end + + ast = J.member_expression( + process_module_name(module, state), + function_name + ) + + {ast, state} + end + + defp process_module_name(module, state) when is_atom(module) do + cond do + ElixirScript.Translate.Module.is_js_module(module, state) -> + members = tl(Module.split(module)) + Identifier.make_namespace_members(members) + ElixirScript.Translate.Module.is_elixir_module(module) -> + members = ["Elixir"] ++ Module.split(module) + J.identifier(Enum.join(members, "_")) + true -> + ElixirScript.Translator.Identifier.make_identifier(module) + end + end + + defp process_module_name(module, state) do + Form.compile!(module, state) + end + + defp erlang_compat_function(module, function) do + J.member_expression( + J.member_expression( + J.member_expression( + J.identifier("Bootstrap"), + J.identifier("Core") + ), + J.identifier(module) + ), + ElixirScript.Translator.Identifier.make_function_name(function) + ) + end +end \ No newline at end of file diff --git a/lib/elixir_script/translator/kernel/special_forms/identifier.ex b/lib/elixir_script/translator/kernel/special_forms/identifier.ex index 584082e6..850c6417 100644 --- a/lib/elixir_script/translator/kernel/special_forms/identifier.ex +++ b/lib/elixir_script/translator/kernel/special_forms/identifier.ex @@ -86,7 +86,7 @@ defmodule ElixirScript.Translator.Identifier do |> make_alias end - def make_function_name(name) when is_atom(name) do + def make_function_name(name) do name = filter_name(name) JS.identifier(name) end diff --git a/src/javascript/lib/core/erlang_compat/erlang.js b/src/javascript/lib/core/erlang_compat/erlang.js index 81b89a66..9847b836 100644 --- a/src/javascript/lib/core/erlang_compat/erlang.js +++ b/src/javascript/lib/core/erlang_compat/erlang.js @@ -26,8 +26,126 @@ function list_subtraction(list1, list2) { return list; } +function plus(left, right) { + if (!right) { + return +left; + } + + return left + right; +} + +function minus(left, right) { + if (!right) { + return -left; + } + + return left - right; +} + +function multiply(left, right) { + return left * right; +} + +function div(left, right) { + return left / right; +} + +function equal(left, right) { + return left == right; +} + +function doesNotEqual(left, right) { + return left != right; +} + +function greaterThan(left, right) { + return left > right; +} + +function greaterThanOrEqualTo(left, right) { + return left >= right; +} + +function lessThan(left, right) { + return left < right; +} + +function lessThanOrEqualTo(left, right) { + return left <= right; +} + +function strictlyEqual(left, right) { + return left === right; +} + +function doesNotStrictlyEqual(left, right) { + return left !== right; +} + +function and(left, right) { + return left && right; +} + +function or(left, right) { + return left || right; +} + +function not(x) { + return !x; +} + +function rem(left, right) { + return left % right; +} + +function band(left, right) { + return left & right; +} + +function bor(left, right) { + return left | right; +} + +function bnot(x) { + return ~x; +} + +function bsl(left, right) { + return left << right; +} + +function bsr(left, right) { + return left >> right; +} + +function bxor(left, right) { + return left ^ right; +} + export default { atom_to_binary, list_concatenation, list_subtraction, + plus, + minus, + multiply, + div, + equal, + greaterThan, + greaterThanOrEqualTo, + lessThan, + lessThanOrEqualTo, + doesNotEqual, + strictlyEqual, + doesNotStrictlyEqual, + and, + or, + not, + rem, + band, + bor, + bsl, + bsr, + bxor, + bnot, }; diff --git a/test/next/passes/translate/forms/remote_test.exs b/test/next/passes/translate/forms/remote_test.exs new file mode 100644 index 00000000..95f7f750 --- /dev/null +++ b/test/next/passes/translate/forms/remote_test.exs @@ -0,0 +1,14 @@ +defmodule ElixirScript.Translate.Forms.Remote.Test do + use ExUnit.Case + alias ElixirScript.Translate.Forms.Remote + alias ESTree.Tools.Builder, as: J + + test "call to variable" do + ast = {:., [line: 644], [{:fun, [line: 644], nil}]} + state = %{function: {:each, nil}, module: Enum, vars: %{:_ => 0, "entry" => 0, "enumerable" => 0, "fun" => 0}} + + {js_ast, _} = Remote.compile(ast, state) + assert js_ast == J.identifier("fun") + end + +end \ No newline at end of file From d8bd1d6bd3ae8045223f3eb64c689bcfea53c140 Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Fri, 2 Jun 2017 20:51:09 -0500 Subject: [PATCH 550/860] Fixed bugs from testing. Got app test working again --- .../next/passes/translate/clause.ex | 5 +++- .../next/passes/translate/form.ex | 27 ++++++++++++++----- .../next/passes/translate/forms/for.ex | 6 +++-- .../next/passes/translate/forms/pattern.ex | 2 +- .../next/passes/translate/forms/try.ex | 4 ++- .../next/passes/translate/function.ex | 3 ++- lib/elixir_script/passes/create_js_modules.ex | 2 +- test/app/spec/main.spec.js | 10 +------ test/support/main.ex | 8 +----- 9 files changed, 37 insertions(+), 30 deletions(-) diff --git a/lib/elixir_script/next/passes/translate/clause.ex b/lib/elixir_script/next/passes/translate/clause.ex index dca321a1..1816ab34 100644 --- a/lib/elixir_script/next/passes/translate/clause.ex +++ b/lib/elixir_script/next/passes/translate/clause.ex @@ -30,9 +30,12 @@ defmodule ElixirScript.Translate.Clause do List.flatten(list) _ -> Form.compile!(body, state) + |> List.wrap + |> List.flatten end - body = return_last_statement(body) + body = body + |> return_last_statement ast = J.call_expression( J.member_expression( diff --git a/lib/elixir_script/next/passes/translate/form.ex b/lib/elixir_script/next/passes/translate/form.ex index 55aefe78..dad4b9b4 100644 --- a/lib/elixir_script/next/passes/translate/form.ex +++ b/lib/elixir_script/next/passes/translate/form.ex @@ -1,6 +1,6 @@ defmodule ElixirScript.Translate.Form do alias ESTree.Tools.Builder, as: J - alias ElixirScript.Translate.Forms.{Bitstring, Match, Try, For, Struct, Receive, Remote} + alias ElixirScript.Translate.Forms.{Bitstring, Match, Try, For, Struct, Receive, Remote, Pattern} alias ElixirScript.Translate.Functions.{Erlang, Lists, Maps} alias ElixirScript.Translator.Identifier alias ElixirScript.Translate.Clause @@ -62,7 +62,7 @@ defmodule ElixirScript.Translate.Form do ), J.identifier("Tuple") ), - Enum.map(elements, &compile!(&1, state)) + Enum.map(elements, &compile!(&1, state)) |> List.flatten ) {ast, state} @@ -94,7 +94,7 @@ defmodule ElixirScript.Translate.Form do ElixirScript.Translate.Function.patterns_ast(), J.identifier("defmatch") ), - Enum.map(clauses, fn x -> Clause.compile(x, state) |> elem(0) end) + Enum.map(clauses, fn x -> Clause.compile(x, state) |> elem(0) end) |> List.flatten ) ast = J.call_expression( @@ -109,10 +109,13 @@ defmodule ElixirScript.Translate.Form do processed_clauses = Enum.map(clauses, fn({:->, _, [clause, clause_body]}) -> { translated_body, state } = Enum.map_reduce(List.wrap(clause_body), state, &compile(&1, &2)) - translated_body = Clause.return_last_statement(translated_body) + translated_body = translated_body + |> List.flatten + |> Clause.return_last_statement + translated_body = J.arrow_function_expression([], [], J.block_statement(translated_body)) - translated_clause = compile(hd(clause), state) + { translated_clause, _ } = compile(hd(clause), state) J.array_expression([translated_clause, translated_body]) @@ -172,7 +175,16 @@ defmodule ElixirScript.Translate.Form do ast = J.call_expression( ElixirScript.Translator.Identifier.make_function_name(function_name), - Enum.map(params, &compile!(&1, state)) + Enum.map(params, &compile!(&1, state)) |> List.flatten + ) + + {ast, state} + end + + def compile({var, _, params}, state) when is_list(params) and is_atom(var) do + ast = J.call_expression( + ElixirScript.Translator.Identifier.make_function_name(var), + Enum.map(params, &compile!(&1, state)) |> List.flatten ) {ast, state} @@ -181,13 +193,14 @@ defmodule ElixirScript.Translate.Form do def compile({function, _, params}, state) when is_list(params) do ast = J.call_expression( compile!(function, state), - Enum.map(params, &compile!(&1, state)) + Enum.map(params, &compile!(&1, state)) |> List.flatten ) {ast, state} end def compile({var, _, _}, state) do + var = Pattern.get_variable_name(to_string(var), state) { ElixirScript.Translator.Identifier.make_identifier(var), state } end diff --git a/lib/elixir_script/next/passes/translate/forms/for.ex b/lib/elixir_script/next/passes/translate/forms/for.ex index 940773da..8e67424d 100644 --- a/lib/elixir_script/next/passes/translate/forms/for.ex +++ b/lib/elixir_script/next/passes/translate/forms/for.ex @@ -65,7 +65,7 @@ defmodule ElixirScript.Translate.Forms.For do {var, collection} end) - {patterns, params, state} = Pattern.compile([{:<<>>, [], bs_parts}], module_state) + {patterns, params, module_state} = Pattern.compile([{:<<>>, [], bs_parts}], module_state) gen = JS.call_expression( JS.member_expression( @@ -126,7 +126,9 @@ defmodule ElixirScript.Translate.Forms.For do Form.compile(x, acc_state) end) - ast = Clause.return_last_statement(ast) + ast = ast + |> List.flatten + |> Clause.return_last_statement JS.arrow_function_expression( state.args, diff --git a/lib/elixir_script/next/passes/translate/forms/pattern.ex b/lib/elixir_script/next/passes/translate/forms/pattern.ex index bb5f29ab..8cccd93d 100644 --- a/lib/elixir_script/next/passes/translate/forms/pattern.ex +++ b/lib/elixir_script/next/passes/translate/forms/pattern.ex @@ -40,7 +40,7 @@ defmodule ElixirScript.Translate.Forms.Pattern do { patterns, params, state } end - defp get_variable_name(function, state) do + def get_variable_name(function, state) do number = Map.get(state.vars, function) String.to_atom("#{function}#{number}") end diff --git a/lib/elixir_script/next/passes/translate/forms/try.ex b/lib/elixir_script/next/passes/translate/forms/try.ex index 52bf3076..4488e49c 100644 --- a/lib/elixir_script/next/passes/translate/forms/try.ex +++ b/lib/elixir_script/next/passes/translate/forms/try.ex @@ -96,6 +96,8 @@ defmodule ElixirScript.Translate.Forms.Try do |> List.wrap |> Enum.map_reduce(state, &Form.compile(&1, &2)) - Clause.return_last_statement(ast) + ast + |> List.flatten + |> Clause.return_last_statement end end diff --git a/lib/elixir_script/next/passes/translate/function.ex b/lib/elixir_script/next/passes/translate/function.ex index aee6819c..9dd6726b 100644 --- a/lib/elixir_script/next/passes/translate/function.ex +++ b/lib/elixir_script/next/passes/translate/function.ex @@ -104,7 +104,8 @@ defmodule ElixirScript.Translate.Function do Form.compile!(body, state) end - body = Clause.return_last_statement(body) + body = body + |> Clause.return_last_statement declarator = J.variable_declarator( J.array_expression(params), diff --git a/lib/elixir_script/passes/create_js_modules.ex b/lib/elixir_script/passes/create_js_modules.ex index 2ba89848..a0cff524 100644 --- a/lib/elixir_script/passes/create_js_modules.ex +++ b/lib/elixir_script/passes/create_js_modules.ex @@ -100,7 +100,7 @@ defmodule ElixirScript.Passes.CreateJSModules do ), [JS.identifier("Elixir")] ), - JS.identifier("start2") + JS.identifier("start") ), [ElixirScript.Translator.Primitive.make_atom(:normal), JS.identifier(:args)] ) diff --git a/test/app/spec/main.spec.js b/test/app/spec/main.spec.js index 9d5ceac0..eb44ba0e 100644 --- a/test/app/spec/main.spec.js +++ b/test/app/spec/main.spec.js @@ -6,15 +6,7 @@ const Elixir = require('../build/Elixir.App'); test('Elixir.start:calls the modules start function', t => { const callback = sinon.spy(); - Elixir.start(Elixir.Main, callback); + Elixir.start(Elixir.Main, [callback]); t.true(callback.called); }); - -test('Elixir.load:loads the modules exports', t => { - const main = Elixir.load(Elixir.Main); - - t.truthy(main.start); - t.truthy(main.hello); - t.is(main.hello(), 'Hello!'); -}); diff --git a/test/support/main.ex b/test/support/main.ex index 61d6451b..a18d3d90 100644 --- a/test/support/main.ex +++ b/test/support/main.ex @@ -1,11 +1,5 @@ defmodule Main do - def start(:normal, callback) do - elem({1, 2}, 0) - Enum.map([], fn(x) -> x end) + def start(:normal, [callback]) do callback.("started") end - - def hello do - "Hello!" - end end From 9375656db8e06e6d994e6c09549560af75d779a5 Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Sat, 3 Jun 2017 03:57:58 -0500 Subject: [PATCH 551/860] Correct ++ pattern matching implementation. Temp fix for travis CI build --- .travis.yml | 13 +++++++++---- .../next/passes/translate/forms/pattern.ex | 16 ++++------------ lib/elixir_script/translator/state.ex | 2 ++ test/cli_test.exs | 6 +++--- test/next/passes/translate/forms/remote_test.exs | 2 +- 5 files changed, 19 insertions(+), 20 deletions(-) diff --git a/.travis.yml b/.travis.yml index a1fb4260..3b000081 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,15 +1,20 @@ sudo: false -language: elixir -elixir: - - 1.4.2 +language: erlang +#language: elixir +#elixir: +# - 1.5.0 otp_release: - - 19.0 + - 20.0-rc1 env: - TRAVIS_NODE_VERSION="7" install: - rm -rf ~/.nvm && git clone https://github.com/creationix/nvm.git ~/.nvm && (cd ~/.nvm && git checkout `git describe --abbrev=0 --tags`) && source ~/.nvm/nvm.sh && nvm install $TRAVIS_NODE_VERSION - npm install -g yarn - yarn +before_script: + - wget http://s3.hex.pm/builds/elixir/master.zip + - unzip -d elixir master.zip + - export PATH=$(pwd)/elixir/bin:${PATH} script: - mix local.hex --force - mix local.rebar --force diff --git a/lib/elixir_script/next/passes/translate/forms/pattern.ex b/lib/elixir_script/next/passes/translate/forms/pattern.ex index 8cccd93d..6b120564 100644 --- a/lib/elixir_script/next/passes/translate/forms/pattern.ex +++ b/lib/elixir_script/next/passes/translate/forms/pattern.ex @@ -105,6 +105,10 @@ defmodule ElixirScript.Translate.Forms.Pattern do { [PM.head_tail(hd(head_patterns), hd(tail_patterns))], params } end + defp process_pattern({{:., _, [:erlang, :++]}, context, [head, tail]}, state) do + process_pattern({:|, context, [head, tail]}, state) + end + defp process_pattern({:%{}, _, props}, state) do properties = Enum.map(props, fn({key, value}) -> {pattern, params} = process_pattern(value, state) @@ -144,18 +148,6 @@ defmodule ElixirScript.Translate.Forms.Pattern do { [PM.bitstring_match(elements)], params } end - defp process_pattern([{:|, _, [head, tail]}], state) do - { head_patterns, head_params } = process_pattern(head, state) - { tail_patterns, tail_params } = process_pattern(tail, state) - params = head_params ++ tail_params - - { [PM.head_tail(hd(head_patterns), hd(tail_patterns))], params } - end - - defp process_pattern({{:., _, [:erlang, :++]}, _, [prefix, value]}, state) do - { [PM.starts_with(prefix)], [Form.compile!(value, state)] } - end - defp process_pattern({:<>, _, [prefix, value]}, state) do { [PM.starts_with(prefix)], [Form.compile!(value, state)] } end diff --git a/lib/elixir_script/translator/state.ex b/lib/elixir_script/translator/state.ex index b5fff798..a7f27da3 100644 --- a/lib/elixir_script/translator/state.ex +++ b/lib/elixir_script/translator/state.ex @@ -30,6 +30,8 @@ defmodule ElixirScript.Translator.State do rescue FunctionClauseError -> acc + ArgumentError -> + acc end end) end diff --git a/test/cli_test.exs b/test/cli_test.exs index 6fab0232..05244867 100644 --- a/test/cli_test.exs +++ b/test/cli_test.exs @@ -1,8 +1,8 @@ defmodule ElixirScript.CLI.Test do use ExUnit.Case - test "parse_args -e expands to elixir" do - {_, args} = ElixirScript.CLI.parse_args(["1 + 1", "-e"]) - assert args == [elixir: true] + test "parse_args -js-module includes js module" do + {_, args} = ElixirScript.CLI.parse_args(["Example", "--js-module", "React:react"]) + assert args == [js_module: "React:react"] end end diff --git a/test/next/passes/translate/forms/remote_test.exs b/test/next/passes/translate/forms/remote_test.exs index 95f7f750..c4de0df5 100644 --- a/test/next/passes/translate/forms/remote_test.exs +++ b/test/next/passes/translate/forms/remote_test.exs @@ -8,7 +8,7 @@ defmodule ElixirScript.Translate.Forms.Remote.Test do state = %{function: {:each, nil}, module: Enum, vars: %{:_ => 0, "entry" => 0, "enumerable" => 0, "fun" => 0}} {js_ast, _} = Remote.compile(ast, state) - assert js_ast == J.identifier("fun") + assert js_ast == J.identifier("fun0") end end \ No newline at end of file From 495d023473a675e3f3a0b366a1c07e3d0a4543a0 Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Sat, 3 Jun 2017 04:05:32 -0500 Subject: [PATCH 552/860] Trying elixir master in travis config --- .travis.yml | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-) diff --git a/.travis.yml b/.travis.yml index 3b000081..147b09f6 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,8 +1,7 @@ sudo: false -language: erlang -#language: elixir -#elixir: -# - 1.5.0 +language: elixir +elixir: + - master otp_release: - 20.0-rc1 env: @@ -11,10 +10,6 @@ install: - rm -rf ~/.nvm && git clone https://github.com/creationix/nvm.git ~/.nvm && (cd ~/.nvm && git checkout `git describe --abbrev=0 --tags`) && source ~/.nvm/nvm.sh && nvm install $TRAVIS_NODE_VERSION - npm install -g yarn - yarn -before_script: - - wget http://s3.hex.pm/builds/elixir/master.zip - - unzip -d elixir master.zip - - export PATH=$(pwd)/elixir/bin:${PATH} script: - mix local.hex --force - mix local.rebar --force From 672cc5c28a40476095c42ed6faa0fe9f1e73101a Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Sat, 3 Jun 2017 04:11:57 -0500 Subject: [PATCH 553/860] Updating travis config again --- .travis.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index 147b09f6..c24a0e1a 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,7 +1,7 @@ sudo: false language: elixir elixir: - - master + - 1.5.0-dev otp_release: - 20.0-rc1 env: @@ -11,8 +11,8 @@ install: - npm install -g yarn - yarn script: - - mix local.hex --force - mix local.rebar --force + - mix local.hex --force - mix deps.get - mix compile - yarn build From eb20acfe3f403b10f8eea2dcb84d56c9a8756521 Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Sun, 4 Jun 2017 19:29:41 -0500 Subject: [PATCH 554/860] Add some tests for the Form module --- .../next/passes/translate/examples/example.ex | 9 +- .../next/passes/translate/form.ex | 17 ++- .../next/passes/translate/forms/remote.ex | 21 ++- .../next/passes/translate/forms/struct.ex | 22 ---- .../next/passes/translate/module.ex | 13 ++ test/next/passes/translate/form_test.exs | 121 ++++++++++++++++++ 6 files changed, 165 insertions(+), 38 deletions(-) delete mode 100644 lib/elixir_script/next/passes/translate/forms/struct.ex create mode 100644 test/next/passes/translate/form_test.exs diff --git a/lib/elixir_script/next/passes/translate/examples/example.ex b/lib/elixir_script/next/passes/translate/examples/example.ex index 49367a3d..dd298938 100644 --- a/lib/elixir_script/next/passes/translate/examples/example.ex +++ b/lib/elixir_script/next/passes/translate/examples/example.ex @@ -1,10 +1,5 @@ defmodule Example do - def start(v, _) do - case v do - :normal -> - "yolo" - _ -> - "yolo too" - end + def start(_, _) do + -1 end end diff --git a/lib/elixir_script/next/passes/translate/form.ex b/lib/elixir_script/next/passes/translate/form.ex index dad4b9b4..917663be 100644 --- a/lib/elixir_script/next/passes/translate/form.ex +++ b/lib/elixir_script/next/passes/translate/form.ex @@ -1,6 +1,6 @@ defmodule ElixirScript.Translate.Form do alias ESTree.Tools.Builder, as: J - alias ElixirScript.Translate.Forms.{Bitstring, Match, Try, For, Struct, Receive, Remote, Pattern} + alias ElixirScript.Translate.Forms.{Bitstring, Match, Try, For, Receive, Remote, Pattern} alias ElixirScript.Translate.Functions.{Erlang, Lists, Maps} alias ElixirScript.Translator.Identifier alias ElixirScript.Translate.Clause @@ -34,8 +34,7 @@ defmodule ElixirScript.Translate.Form do def compile(form, state) when is_atom(form) do ast = if ElixirScript.Translate.Module.is_elixir_module(form) do - members = if form == Elixir, do: ["Elixir"], else: ["Elixir"] ++ Module.split(form) - J.identifier(Enum.join(members, "_")) + Remote.process_module_name(form, state) else J.call_expression( J.member_expression( @@ -80,8 +79,16 @@ defmodule ElixirScript.Translate.Form do Match.compile(match, state) end - def compile({:%, _, [_, _]} = ast, state) do - Struct.compile(ast, state) + def compile({:%, _, [module, params]}, state) do + ast = J.call_expression( + J.member_expression( + Remote.process_module_name(module), + J.identifier("__struct__") + ), + [Form.compile!(params, state)] + ) + + { ast, state } end def compile({:for, _, _} = ast, state) do diff --git a/lib/elixir_script/next/passes/translate/forms/remote.ex b/lib/elixir_script/next/passes/translate/forms/remote.ex index 5736e752..6b7d0df6 100644 --- a/lib/elixir_script/next/passes/translate/forms/remote.ex +++ b/lib/elixir_script/next/passes/translate/forms/remote.ex @@ -1,4 +1,6 @@ defmodule ElixirScript.Translate.Forms.Remote do + @moduledoc false + alias ESTree.Tools.Builder, as: J alias ElixirScript.Translate.Form alias ElixirScript.Translator.Identifier @@ -16,6 +18,13 @@ defmodule ElixirScript.Translate.Forms.Remote do :file ] + @doc """ + Compiles functions into JavaScript AST. + These are not actual function calls, but + the function identifiers themselves. Also + includes function heads for converting some + erlang functions into JavaScript functions. + """ def compile({:., _, [:erlang, :+]}, state) do ast = erlang_compat_function("erlang", "plus") { ast, state } @@ -131,20 +140,24 @@ defmodule ElixirScript.Translate.Forms.Remote do {ast, state} end - defp process_module_name(module, state) when is_atom(module) do + def process_module_name(module, state) when is_atom(module) do cond do ElixirScript.Translate.Module.is_js_module(module, state) -> members = tl(Module.split(module)) Identifier.make_namespace_members(members) ElixirScript.Translate.Module.is_elixir_module(module) -> - members = ["Elixir"] ++ Module.split(module) - J.identifier(Enum.join(members, "_")) + members = ["Elixir"] ++ Module.split(module) ++ ["__load"] + + J.call_expression( + Identifier.make_namespace_members(members), + [J.identifier("Elixir")] + ) true -> ElixirScript.Translator.Identifier.make_identifier(module) end end - defp process_module_name(module, state) do + def process_module_name(module, state) do Form.compile!(module, state) end diff --git a/lib/elixir_script/next/passes/translate/forms/struct.ex b/lib/elixir_script/next/passes/translate/forms/struct.ex deleted file mode 100644 index e88bc492..00000000 --- a/lib/elixir_script/next/passes/translate/forms/struct.ex +++ /dev/null @@ -1,22 +0,0 @@ -defmodule ElixirScript.Translate.Forms.Struct do - alias ESTree.Tools.Builder, as: J - alias ElixirScript.Translate.Form - alias ElixirScript.Translator.Identifier - - def compile({:%, _, [module, params]}, state) do - ast = J.call_expression( - J.member_expression( - process_module_name(module), - J.identifier("__struct__1") - ), - [Form.compile!(params, state)] - ) - - { ast, state } - end - - defp process_module_name(module) do - members = ["Elixir"] ++ Module.split(module) - Identifier.make_namespace_members(members) - end -end diff --git a/lib/elixir_script/next/passes/translate/module.ex b/lib/elixir_script/next/passes/translate/module.ex index e447f9b2..89b8388e 100644 --- a/lib/elixir_script/next/passes/translate/module.ex +++ b/lib/elixir_script/next/passes/translate/module.ex @@ -14,6 +14,9 @@ defmodule ElixirScript.Translate.Module do end def compile(module, info, pid) do + if Atom.to_string(module) == "Elixir.Example" do + IO.inspect info + end %{ attributes: attrs, compile_opts: _compile_opts, @@ -86,6 +89,10 @@ defmodule ElixirScript.Translate.Module do J.object_expression(exports) end + @doc """ + Determins if the given atom + is an Elixir function + """ def is_elixir_module(Elixir) do true end @@ -105,6 +112,12 @@ defmodule ElixirScript.Translate.Module do false end + @doc """ + Determines is given function is a JS module. + A JS module is either one that begins with "JS" + or is a module defined from the js_modules compiler + opt + """ def is_js_module(module, state) do cond do module in ModuleState.get_javascript_modules(state.pid) -> diff --git a/test/next/passes/translate/form_test.exs b/test/next/passes/translate/form_test.exs new file mode 100644 index 00000000..e93dab3b --- /dev/null +++ b/test/next/passes/translate/form_test.exs @@ -0,0 +1,121 @@ +defmodule ElixirScript.Translate.Forms.Test do + use ExUnit.Case + alias ElixirScript.Translate.Form + alias ElixirScript.Translator.Identifier + alias ESTree.Tools.Builder, as: J + + + setup_all do + {:ok, pid} = ElixirScript.State.start_link(%{}) + + state = %{ + pid: pid + } + + [state: state] + end + + test "integer" do + ast = 1 + state = %{} + + {js_ast, _} = Form.compile(ast, state) + assert js_ast == J.literal(1) + end + + test "boolean" do + ast = true + state = %{} + + {js_ast, _} = Form.compile(ast, state) + assert js_ast == J.literal(true) + end + + test "float" do + ast = 1.0 + state = %{} + + {js_ast, _} = Form.compile(ast, state) + assert js_ast == J.literal(1.0) + end + + test "binary" do + ast = "hello" + state = %{} + + {js_ast, _} = Form.compile(ast, state) + assert js_ast == J.literal("hello") + end + + test "atom" do + ast = :tiger + state = %{} + + {js_ast, _} = Form.compile(ast, state) + assert js_ast == J.call_expression( + J.member_expression( + J.identifier("Symbol"), + J.identifier("for") + ), + [J.literal(:tiger)] + ) + end + + test "module", %{state: state} do + ast = IO + + {js_ast, _} = Form.compile(ast, state) + assert js_ast == J.call_expression( + Identifier.make_namespace_members(["Elixir", "IO", "__load"]), + [J.identifier("Elixir")] + ) + end + + test "tuple" do + ast = {1, 2} + state = %{} + + {js_ast, _} = Form.compile(ast, state) + assert js_ast == J.call_expression( + J.member_expression( + J.member_expression( + J.identifier("Bootstrap"), + J.identifier("Core") + ), + J.identifier("Tuple") + ), + [J.literal(1), J.literal(2)] + ) + end + + test "list" do + ast = [1, 2] + state = %{} + + {js_ast, _} = Form.compile(ast, state) + assert js_ast == J.array_expression([J.literal(1), J.literal(2)]) + end + + test "super" do + ast = {:super, [], [1]} + state = %{function: {:my_function, nil}} + + {js_ast, _} = Form.compile(ast, state) + assert js_ast == J.call_expression( + J.identifier("my_function"), + [J.literal(1)] + ) + end + + test "local function" do + ast = {:my_function, [], [1]} + state = %{} + + {js_ast, _} = Form.compile(ast, state) + assert js_ast == J.call_expression( + J.identifier("my_function"), + [J.literal(1)] + ) + end + +end \ No newline at end of file From da96e97034504d768a096ed04cd5fbbe197803ac Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Fri, 9 Jun 2017 17:55:22 -0500 Subject: [PATCH 555/860] More updates from testing --- .../next/passes/translate/form.ex | 4 +- .../next/passes/translate/forms/map.ex | 16 ++-- .../next/passes/translate/forms/receive.ex | 8 +- .../next/passes/translate/module.ex | 8 ++ test/next/passes/translate/forms/map_test.exs | 74 +++++++++++++++++++ .../passes/translate/forms/receive_test.exs | 26 +++++++ .../passes/translate/forms/remote_test.exs | 4 +- 7 files changed, 125 insertions(+), 15 deletions(-) create mode 100644 test/next/passes/translate/forms/map_test.exs create mode 100644 test/next/passes/translate/forms/receive_test.exs diff --git a/lib/elixir_script/next/passes/translate/form.ex b/lib/elixir_script/next/passes/translate/form.ex index 917663be..58b95de0 100644 --- a/lib/elixir_script/next/passes/translate/form.ex +++ b/lib/elixir_script/next/passes/translate/form.ex @@ -82,10 +82,10 @@ defmodule ElixirScript.Translate.Form do def compile({:%, _, [module, params]}, state) do ast = J.call_expression( J.member_expression( - Remote.process_module_name(module), + Remote.process_module_name(module, state), J.identifier("__struct__") ), - [Form.compile!(params, state)] + [compile!(params, state)] ) { ast, state } diff --git a/lib/elixir_script/next/passes/translate/forms/map.ex b/lib/elixir_script/next/passes/translate/forms/map.ex index 54aa74de..ce1ee7f5 100644 --- a/lib/elixir_script/next/passes/translate/forms/map.ex +++ b/lib/elixir_script/next/passes/translate/forms/map.ex @@ -8,16 +8,14 @@ defmodule ElixirScript.Translate.Forms.Map do ast = J.call_expression( J.member_expression( - J.member_expression( - J.identifier("Bootstrap"), - J.member_expression( - J.identifier("Core"), - J.identifier("SpecialForms") - ) - ), - J.identifier("map_update") + J.identifier("Object"), + J.identifier("assign") ), - [map, data] + [ + J.object_expression([]), + map, + data + ] ) { ast, state } diff --git a/lib/elixir_script/next/passes/translate/forms/receive.ex b/lib/elixir_script/next/passes/translate/forms/receive.ex index 8d021a7e..6a51bf24 100644 --- a/lib/elixir_script/next/passes/translate/forms/receive.ex +++ b/lib/elixir_script/next/passes/translate/forms/receive.ex @@ -2,9 +2,13 @@ defmodule ElixirScript.Translate.Forms.Receive do @moduledoc false alias ESTree.Tools.Builder, as: J + @doc """ + receive is not supported just yet, but we compile it + to a stub function for now + """ def compile(blocks, state) do - receive_block = Keyword.get(blocks, :do) - after_block = Keyword.get(blocks, :after, nil) + _receive_block = Keyword.get(blocks, :do) + _after_block = Keyword.get(blocks, :after, nil) receive_function = J.member_expression( J.member_expression( diff --git a/lib/elixir_script/next/passes/translate/module.ex b/lib/elixir_script/next/passes/translate/module.ex index 89b8388e..7ea9752e 100644 --- a/lib/elixir_script/next/passes/translate/module.ex +++ b/lib/elixir_script/next/passes/translate/module.ex @@ -2,6 +2,7 @@ defmodule ElixirScript.Translate.Module do @moduledoc false alias ESTree.Tools.Builder, as: J alias ElixirScript.Translate.Function + alias ElixirScript.Translate.Form alias ElixirScript.Translator.Identifier alias ElixirScript.State, as: ModuleState @@ -86,6 +87,13 @@ defmodule ElixirScript.Translate.Module do list end) + # Add an attribute to use to determine if this is a module + # Will be used by the is_atom implementation + exports ++ [ElixirScript.Translate.Forms.Map.make_property( + Form.compile!("__MODULE__", %{}), + Form.compile!(true, %{}) + )] + J.object_expression(exports) end diff --git a/test/next/passes/translate/forms/map_test.exs b/test/next/passes/translate/forms/map_test.exs new file mode 100644 index 00000000..ad826766 --- /dev/null +++ b/test/next/passes/translate/forms/map_test.exs @@ -0,0 +1,74 @@ +defmodule ElixirScript.Translate.Forms.Map.Test do + use ExUnit.Case + alias ElixirScript.Translate.Form + alias ESTree.Tools.Builder, as: J + + test "map with atom key" do + properties = [a: 1] + ast = {:%{}, [], properties} + state = %{} + + {js_ast, _} = Form.compile(ast, state) + assert js_ast == J.object_expression([ + J.property( + J.call_expression( + J.member_expression( + J.identifier("Symbol"), + J.identifier("for") + ), + [J.literal(:a)] + ), + J.literal(1), + :init, false, false, true + ) + ]) + end + + test "map with string key" do + properties = [{"a", 1}] + ast = {:%{}, [], properties} + state = %{} + + {js_ast, _} = Form.compile(ast, state) + assert js_ast == J.object_expression([ + J.property( + J.identifier("a"), + J.literal(1) + ) + ]) + end + + + test "map update" do + properties = [{"a", 1}] + map_ast = {:%{}, [], properties} + new_values = [{"a", 2}] + state = %{} + + ast = {:%{}, [], [{:|, [], [map_ast, new_values]}]} + + {js_ast, _} = Form.compile(ast, state) + assert js_ast == J.call_expression( + J.member_expression( + J.identifier("Object"), + J.identifier("assign") + ), + [ + J.object_expression([]), + J.object_expression([ + J.property( + J.identifier("a"), + J.literal(1) + ) + ]), + J.object_expression([ + J.property( + J.identifier("a"), + J.literal(2) + ) + ]) + ] + ) + end + +end \ No newline at end of file diff --git a/test/next/passes/translate/forms/receive_test.exs b/test/next/passes/translate/forms/receive_test.exs new file mode 100644 index 00000000..32d55f67 --- /dev/null +++ b/test/next/passes/translate/forms/receive_test.exs @@ -0,0 +1,26 @@ +defmodule ElixirScript.Translate.Forms.Receive.Test do + use ExUnit.Case + alias ElixirScript.Translate.Form + alias ESTree.Tools.Builder, as: J + + test "call to variable" do + ast = {:receive, [line: 644], [[do: 1, after: 2]]} + state = %{function: {:each, nil}, module: __MODULE__} + + {js_ast, _} = Form.compile(ast, state) + assert js_ast == J.call_expression( + J.member_expression( + J.member_expression( + J.identifier("Bootstrap"), + J.member_expression( + J.identifier("Core"), + J.identifier("SpecialForms") + ) + ), + J.identifier("receive") + ), + [] + ) + end + +end \ No newline at end of file diff --git a/test/next/passes/translate/forms/remote_test.exs b/test/next/passes/translate/forms/remote_test.exs index c4de0df5..993108d9 100644 --- a/test/next/passes/translate/forms/remote_test.exs +++ b/test/next/passes/translate/forms/remote_test.exs @@ -1,13 +1,13 @@ defmodule ElixirScript.Translate.Forms.Remote.Test do use ExUnit.Case - alias ElixirScript.Translate.Forms.Remote + alias ElixirScript.Translate.Form alias ESTree.Tools.Builder, as: J test "call to variable" do ast = {:., [line: 644], [{:fun, [line: 644], nil}]} state = %{function: {:each, nil}, module: Enum, vars: %{:_ => 0, "entry" => 0, "enumerable" => 0, "fun" => 0}} - {js_ast, _} = Remote.compile(ast, state) + {js_ast, _} = Form.compile(ast, state) assert js_ast == J.identifier("fun0") end From 626602f014c367d942449cafb639f47e7ad8872e Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Fri, 9 Jun 2017 18:01:27 -0500 Subject: [PATCH 556/860] Update travis.yml --- .travis.yml | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/.travis.yml b/.travis.yml index c24a0e1a..91f6a3b3 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,7 +1,5 @@ sudo: false -language: elixir -elixir: - - 1.5.0-dev +language: erlang otp_release: - 20.0-rc1 env: @@ -10,11 +8,14 @@ install: - rm -rf ~/.nvm && git clone https://github.com/creationix/nvm.git ~/.nvm && (cd ~/.nvm && git checkout `git describe --abbrev=0 --tags`) && source ~/.nvm/nvm.sh && nvm install $TRAVIS_NODE_VERSION - npm install -g yarn - yarn -script: +before_script: + - wget http://s3.hex.pm/builds/elixir/master.zip + - unzip -d elixir master.zip + - export PATH=$(pwd)/elixir/bin:${PATH} - mix local.rebar --force - mix local.hex --force - mix deps.get - - mix compile +script: - yarn build - mix test - yarn test From 2d98dd641452337085e43e3c0bac9ab7c1dcbf14 Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Fri, 9 Jun 2017 18:30:53 -0500 Subject: [PATCH 557/860] Add is_* functions --- .../lib/core/erlang_compat/erlang.js | 71 +++++++++++++++++++ 1 file changed, 71 insertions(+) diff --git a/src/javascript/lib/core/erlang_compat/erlang.js b/src/javascript/lib/core/erlang_compat/erlang.js index 9847b836..eb3f78c6 100644 --- a/src/javascript/lib/core/erlang_compat/erlang.js +++ b/src/javascript/lib/core/erlang_compat/erlang.js @@ -1,4 +1,5 @@ // http://erlang.org/doc/man/erlang.html +import ErlangTypes from 'erlang-types'; function atom_to_binary(atom, encoding = Symbol.for('utf8')) { if (encoding !== Symbol.for('utf8')) { @@ -122,6 +123,62 @@ function bxor(left, right) { return left ^ right; } +function is_atom(value) { + return value instanceof Symbol || value.__MODULE__ === true; +} + +function is_bitstring(value) { + return value instanceof ErlangTypes.BitString; +} + +function is_boolean(value) { + return value instanceof Boolean; +} + +function is_float(value) { + return value instanceof Number && !Number.isInteger(value); +} + +function is_function(value) { + return value instanceof Function; +} + +function is_integer(value) { + return Number.isInteger(value); +} + +function is_list(value) { + return Array.isArray(value); +} + +function is_map(value) { + return value instanceof Object; +} + +function is_number(value) { + return value instanceof Number; +} + +function is_pid(value) { + return value instanceof ErlangTypes.PID; +} + +function is_port() { + return false; +} + +function is_reference(value) { + return value instanceof ErlangTypes.Reference; +} + +function is_tuple(value) { + return value instanceof ErlangTypes.Tuple; +} + +function is_binary(value) { + return value instanceof String; +} + export default { atom_to_binary, list_concatenation, @@ -148,4 +205,18 @@ export default { bsr, bxor, bnot, + is_bitstring, + is_boolean, + is_float, + is_function, + is_integer, + is_list, + is_map, + is_number, + is_pid, + is_port, + is_reference, + is_tuple, + is_atom, + is_binary, }; From 0d62e2dabe4886d502cc53c671d5e694b8ed5fbe Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Fri, 9 Jun 2017 20:59:00 -0500 Subject: [PATCH 558/860] Fix issue where Elixir module was crashing module name processing --- lib/elixir_script/next/passes/output.ex | 12 +++++++++--- .../next/passes/translate/forms/remote.ex | 9 ++++++++- lib/elixir_script/next/passes/translate/module.ex | 8 +++----- 3 files changed, 20 insertions(+), 9 deletions(-) diff --git a/lib/elixir_script/next/passes/output.ex b/lib/elixir_script/next/passes/output.ex index f2cdd164..925897ab 100644 --- a/lib/elixir_script/next/passes/output.ex +++ b/lib/elixir_script/next/passes/output.ex @@ -36,7 +36,8 @@ defmodule ElixirScript.Output do end defp concat(code) do - "'use strict';\n" <> ElixirScript.get_bootstrap_js("iife") <> "\n" <> code + bootstrap_code = ElixirScript.get_bootstrap_js("iife") + "'use strict';\n#{bootstrap_code}\n#{code}" end defp prepare_js_ast(js_ast) do @@ -54,8 +55,13 @@ defmodule ElixirScript.Output do end end - defp output(code, nil), do: code - defp output(code, :stdout), do: IO.puts(code) + defp output(code, nil) do + code + end + + defp output(code, :stdout) do + IO.puts(code) + end defp output(code, path) do file_name = case Path.extname(path) do diff --git a/lib/elixir_script/next/passes/translate/forms/remote.ex b/lib/elixir_script/next/passes/translate/forms/remote.ex index 6b7d0df6..bb881afe 100644 --- a/lib/elixir_script/next/passes/translate/forms/remote.ex +++ b/lib/elixir_script/next/passes/translate/forms/remote.ex @@ -144,7 +144,14 @@ defmodule ElixirScript.Translate.Forms.Remote do cond do ElixirScript.Translate.Module.is_js_module(module, state) -> members = tl(Module.split(module)) - Identifier.make_namespace_members(members) + Identifier.make_namespace_members(members) + module === Elixir -> + members = ["Elixir", "__load"] + + J.call_expression( + Identifier.make_namespace_members(members), + [J.identifier("Elixir")] + ) ElixirScript.Translate.Module.is_elixir_module(module) -> members = ["Elixir"] ++ Module.split(module) ++ ["__load"] diff --git a/lib/elixir_script/next/passes/translate/module.ex b/lib/elixir_script/next/passes/translate/module.ex index 7ea9752e..e16fbe8d 100644 --- a/lib/elixir_script/next/passes/translate/module.ex +++ b/lib/elixir_script/next/passes/translate/module.ex @@ -101,15 +101,11 @@ defmodule ElixirScript.Translate.Module do Determins if the given atom is an Elixir function """ - def is_elixir_module(Elixir) do - true - end - def is_elixir_module(module) when is_atom(module) do str_module = Atom.to_string(module) case str_module do - "Elixir." <> _ -> + "Elixir" <> _ -> true _ -> false @@ -130,6 +126,8 @@ defmodule ElixirScript.Translate.Module do cond do module in ModuleState.get_javascript_modules(state.pid) -> true + module === Elixir -> + false is_elixir_module(module) and hd(Module.split(module)) == "JS" -> true true -> From e95aa8ba89705caa282022421e3a840eff2519c5 Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Sun, 11 Jun 2017 10:33:05 -0500 Subject: [PATCH 559/860] Optimizations to not compile or output modules with no public functions --- lib/elixir_script/next/compiler.ex | 17 +- .../next/passes/find_used_functions.ex | 254 ++++++++++++++++++ .../{find_used.ex => find_used_modules.ex} | 25 +- .../next/passes/translate/module.ex | 42 +-- lib/elixir_script/next/state.ex | 7 + 5 files changed, 301 insertions(+), 44 deletions(-) create mode 100644 lib/elixir_script/next/passes/find_used_functions.ex rename lib/elixir_script/next/passes/{find_used.ex => find_used_modules.ex} (92%) diff --git a/lib/elixir_script/next/compiler.ex b/lib/elixir_script/next/compiler.ex index e93317d6..faf38459 100644 --- a/lib/elixir_script/next/compiler.ex +++ b/lib/elixir_script/next/compiler.ex @@ -3,15 +3,24 @@ defmodule ElixirScript.Compiler do Compiles the given modules to JavaScript. """ + @doc """ + Takes either a module name or a list of module names as + the entry point(s) of an application/library. From there + it will determine which modules and functions are needed + to be compiled. + """ @spec compile([atom], []) :: nil def compile(entry_modules, opts \\ []) do opts = build_compiler_options(opts, entry_modules) {:ok, pid} = ElixirScript.State.start_link(opts) - IO.puts "Finding used modules and functions" - entry_modules - |> List.wrap - |> ElixirScript.FindUsed.execute(pid) + entry_modules = List.wrap(entry_modules) + + IO.puts "Finding used modules" + ElixirScript.FindUsedModules.execute(entry_modules, pid) + + IO.puts "Finding used functions" + ElixirScript.FindUsedFunctions.execute(entry_modules, pid) IO.puts "Compiling" modules = ElixirScript.State.list_modules(pid) diff --git a/lib/elixir_script/next/passes/find_used_functions.ex b/lib/elixir_script/next/passes/find_used_functions.ex new file mode 100644 index 00000000..30af88af --- /dev/null +++ b/lib/elixir_script/next/passes/find_used_functions.ex @@ -0,0 +1,254 @@ +defmodule ElixirScript.FindUsedFunctions do + @moduledoc false + alias ElixirScript.State, as: ModuleState + + @doc """ + Takes a list of entry modules and finds modules they use along with + documenting the functions used. The data collected about used functions + is used to filter only the used functions for compilation + """ + @spec execute([atom], pid) :: nil + def execute(entry_modules, pid) do + Enum.each(entry_modules, fn + module -> + walk_module(module, pid) + end) + end + + defp walk_module(module, pid) do + %{ + attributes: _attrs, + compile_opts: _compile_opts, + definitions: defs, + file: _file, + line: _line, + module: ^module, + unreachable: unreachable + } = ModuleState.get_module(pid, module) + + reachable_defs = Enum.filter(defs, fn + { _, type, _, _} when type in [:defmacro, :defmacrop] -> false + { name, _, _, _} -> not(name in unreachable) + _ -> true + end) + + state = %{ + pid: pid, + module: module + } + + Enum.each(reachable_defs, fn({name, _type, _, _clauses}) -> + ModuleState.add_used(state.pid, module, name) + end) + + Enum.each(reachable_defs, &walk(&1, state)) + end + + defp walk_module(module, function, arity, pid) do + function = {function, arity} + + unless ModuleState.has_used?(pid, module, function) do + %{ + attributes: _attrs, + compile_opts: _compile_opts, + definitions: defs, + file: _file, + line: _line, + module: ^module, + unreachable: unreachable + } = ModuleState.get_module(pid, module) + + state = %{ + pid: pid, + module: module + } + + reachable_defs = Enum.filter(defs, fn + { _, type, _, _} when type in [:defmacro, :defmacrop] -> false + { name, _, _, _} -> not(name in [function]) + _ -> true + end) + + Enum.each(reachable_defs, fn({name, _type, _, _clauses}) -> + ModuleState.add_used(state.pid, module, name) + end) + + Enum.each(reachable_defs, &walk(&1, state)) + end + end + + defp walk({{_name, _arity}, _type, _, clauses}, state) do + Enum.each(clauses, &walk(&1, state)) + end + + defp walk({ _, _args, _guards, body}, state) do + case body do + nil -> + nil + {:__block__, _, block_body} -> + Enum.map(block_body, &walk(&1, state)) + b when is_list(b) -> + Enum.map(b, &walk(&1, state)) + _ -> + walk(body, state) + end + end + + defp walk({:->, _, [[{:when, _, params}], body ]}, state) do + guards = List.last(params) + params = params |> Enum.reverse |> tl |> Enum.reverse + + walk({[], params, guards, body}, state) + end + + defp walk({:->, _, [params, body]}, state) do + walk({[], params, [], body}, state) + end + + defp walk(form, state) when is_list(form) do + Enum.each(form, &walk(&1, state)) + end + + defp walk({a, b}, state) do + walk({:{}, [], [a, b]}, state) + end + + defp walk({:{}, _, elements}, state) do + Enum.each(elements, &walk(&1, state)) + end + + defp walk({:%{}, _, properties}, state) do + Enum.each(properties, fn (val) -> walk(val, state) end) + end + + defp walk({:<<>>, _, elements}, state) do + Enum.each(elements, fn (val) -> walk(val, state) end) + end + + defp walk({:=, _, [left, right]}, state) do + walk(left, state) + walk(right, state) + end + + defp walk({:%, _, [module, params]}, state) do + walk(params, state) + end + + defp walk({:for, _, generators}, state) do + Enum.each(generators, fn + {:<<>>, _, body} -> + walk(body, state) + + {:<-, _, [identifier, enum]} -> + walk(identifier, state) + walk(enum, state) + + [into: expression] -> + walk(expression, state) + + [into: expression, do: expression2] -> + walk(expression, state) + walk(expression2, state) + + [do: expression] -> + walk(expression, state) + + filter -> + walk(filter, state) + end) + end + + defp walk({:case, _, [condition, [do: clauses]]}, state) do + Enum.each(clauses, &walk(&1, state)) + walk(condition, state) + end + + defp walk({:cond, _, [[do: clauses]]}, state) do + Enum.each(clauses, fn({:->, _, [clause, clause_body]}) -> + Enum.each(List.wrap(clause_body), &walk(&1, state)) + walk(hd(clause), state) + end) + end + + defp walk({:receive, _context, _}, _state) do + nil + end + + defp walk({:try, _, [blocks]}, state) do + try_block = Keyword.get(blocks, :do) + rescue_block = Keyword.get(blocks, :rescue, nil) + catch_block = Keyword.get(blocks, :catch, nil) + after_block = Keyword.get(blocks, :after, nil) + else_block = Keyword.get(blocks, :else, nil) + + Enum.each(List.wrap(try_block), &walk(&1, state)) + + if rescue_block do + Enum.each(rescue_block, fn + {:->, _, [ [{:in, _, [param, names]}], body]} -> + walk({[], [param], [{{:., [], [Enum, :member?]}, [], [param, names]}], body}, state) + {:->, _, [ [param], body]} -> + walk({[], [param], [], body}, state) + end) + end + + if catch_block do + walk({:fn, [], catch_block}, state) + end + + if after_block do + Enum.each(List.wrap(after_block), &walk(&1, state)) + end + + if else_block do + walk({:fn, [], else_block}, state) + end + end + + defp walk({:fn, _, clauses}, state) do + Enum.each(clauses, &walk(&1, state)) + end + + defp walk({{:., _, [:erlang, :apply]}, _, [module, function, params]}, state) do + walk({{:., [], [module, function]}, [], params}, state) + end + + defp walk({{:., _, [:erlang, :apply]}, _, [function, params]}, state) do + walk({function, [], params}, state) + end + + defp walk({{:., _, [module, function]}, _, params}, state) do + cond do + ElixirScript.Translate.Module.is_js_module(module, state) -> + nil + ElixirScript.Translate.Module.is_elixir_module(module) -> + walk_module(module, function, length(params), state.pid) + true -> + nil + end + + walk(params, state) + end + + defp walk({:super, _, params}, state) do + walk(params, state) + end + + defp walk({function, _, params}, state) when function in [:|, :::] do + nil + end + + defp walk({function, _, params}, state) when is_atom(function) and is_list(params) do + walk_module(state.module, function, length(params), state.pid) + Enum.each(params, &walk(&1, state)) + end + + defp walk({_, _, params}, state) when is_list(params) do + Enum.each(params, &walk(&1, state)) + end + + defp walk(_, _) do + nil + end + +end \ No newline at end of file diff --git a/lib/elixir_script/next/passes/find_used.ex b/lib/elixir_script/next/passes/find_used_modules.ex similarity index 92% rename from lib/elixir_script/next/passes/find_used.ex rename to lib/elixir_script/next/passes/find_used_modules.ex index b0bf6fbd..466b1bd6 100644 --- a/lib/elixir_script/next/passes/find_used.ex +++ b/lib/elixir_script/next/passes/find_used_modules.ex @@ -1,24 +1,9 @@ -defmodule ElixirScript.FindUsed do +defmodule ElixirScript.FindUsedModules do @moduledoc false - alias ElixirScript.State, as: ModuleState - - @erlang_modules [ - :erlang, - :maps, - :lists, - :gen, - :elixir_errors, - :supervisor, - :application, - :code, - :elixir_utils, - :file - ] + alias ElixirScript.State, as: ModuleState @doc """ - Takes a list of entry modules and finds modules they use along with - documenting the functions used. The data collected about used functions - is used to filter only the used functions for compilation + Takes a list of entry modules and finds modules they use. """ @spec execute([atom], pid) :: nil def execute(modules, pid) do @@ -240,10 +225,6 @@ defmodule ElixirScript.FindUsed do walk({function, [], params}, state) end - defp walk({{:., _, [module, function]}, _, params}, _state) when module in @erlang_modules do - nil - end - defp walk({{:., _, [module, function]}, _, params}, state) do cond do ElixirScript.Translate.Module.is_js_module(module, state) -> diff --git a/lib/elixir_script/next/passes/translate/module.ex b/lib/elixir_script/next/passes/translate/module.ex index e16fbe8d..86b48e5e 100644 --- a/lib/elixir_script/next/passes/translate/module.ex +++ b/lib/elixir_script/next/passes/translate/module.ex @@ -15,9 +15,6 @@ defmodule ElixirScript.Translate.Module do end def compile(module, info, pid) do - if Atom.to_string(module) == "Elixir.Example" do - IO.inspect info - end %{ attributes: attrs, compile_opts: _compile_opts, @@ -53,7 +50,30 @@ defmodule ElixirScript.Translate.Module do end #we combine our function arities - combined_defs = used_defs + combined_defs = combine_defs(used_defs) + exports = make_exports(combined_defs) + + # Don't skip compilation and output of modules that don't have + # any public functions + case exports do + %ESTree.ObjectExpression{ properties: [] } -> + ModuleState.put_module(pid, module, Map.put(info, :js_ast, J.program([]))) + _ -> + { compiled_functions, _ } = Enum.map_reduce(combined_defs, state, &Function.compile(&1, &2)) + + js_ast = ElixirScript.ModuleSystems.Namespace.build( + module, + compiled_functions, + exports, + nil + ) + + ModuleState.put_module(pid, module, Map.put(info, :js_ast, hd(js_ast))) + end + end + + defp combine_defs(used_defs) do + used_defs |> Enum.sort(fn { {name1, arity1}, _, _, _ }, { {name2, arity2}, _, _, _ } -> "#{name1}#{arity1}" < "#{name2}#{arity2}" end) |> Enum.group_by(fn {{name, _}, _, _, _ } -> name end) |> Enum.map(fn {group, funs} -> @@ -62,20 +82,6 @@ defmodule ElixirScript.Translate.Module do {name, type, context, acc_clauses ++ clauses} end) end) - - { compiled_functions, _ } = combined_defs - |> Enum.map_reduce(state, &Function.compile(&1, &2)) - - exports = make_exports(combined_defs) - - js_ast = ElixirScript.ModuleSystems.Namespace.build( - module, - compiled_functions, - exports, - nil - ) - - ModuleState.put_module(pid, module, Map.put(info, :js_ast, hd(js_ast))) end defp make_exports(reachable_defs) do diff --git a/lib/elixir_script/next/state.ex b/lib/elixir_script/next/state.ex index 711d8244..b199e9e8 100644 --- a/lib/elixir_script/next/state.ex +++ b/lib/elixir_script/next/state.ex @@ -36,6 +36,13 @@ defmodule ElixirScript.State do end) end + def has_used?(pid, module, func) do + Agent.get(pid, fn(state) -> + module_info = Keyword.get(state.modules, module) + Enum.find(module_info.used, fn(x) -> x == func end) != nil + end) + end + def add_used(pid, module, {_function, _arity} = func) do Agent.update(pid, fn(state) -> module_info = Keyword.get(state.modules, module) From 374b06130710445b1f67afafc5a1ca8205106554 Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Sun, 11 Jun 2017 11:42:52 -0500 Subject: [PATCH 560/860] Update version and CHANGELOG.md --- CHANGELOG.md | 2 +- mix.exs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 710e2cbd..b484b9e3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,7 +4,7 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](http://keepachangelog.com/) and this project adheres to [Semantic Versioning](http://semver.org/). -## [0.28.0-dev] +## [0.28.0] - 2017-06-11 ### Added - `remove-unused` option that will remove all unused modules from output diff --git a/mix.exs b/mix.exs index a9b380f3..3be99d87 100644 --- a/mix.exs +++ b/mix.exs @@ -4,7 +4,7 @@ defmodule ElixirScript.Mixfile do def project do [ app: :elixir_script, - version: "0.28.0-dev", + version: "0.28.0", elixir: "~> 1.0", elixirc_paths: elixirc_paths(), escript: escript_config(), From 6e2f8f34b54b82c46d940a0ad5dbe615c34f53e5 Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Sun, 11 Jun 2017 14:21:32 -0500 Subject: [PATCH 561/860] Save mix.exs from merge --- lib/elixir_script/next/beam.ex | 12 ++++++++++++ mix.exs | 6 ------ 2 files changed, 12 insertions(+), 6 deletions(-) diff --git a/lib/elixir_script/next/beam.ex b/lib/elixir_script/next/beam.ex index d9838c28..f9611c5a 100644 --- a/lib/elixir_script/next/beam.ex +++ b/lib/elixir_script/next/beam.ex @@ -8,6 +8,18 @@ defmodule ElixirScript.Beam do all the protocol implementations """ @spec debug_info(atom) :: {:ok | :error, map | binary} + def debug_info(module) + + #Replacing String module with our ElixirScript's version + def debug_info(String) do + case debug_info(ElixirScript.String) do + {:ok, info} -> + {:ok, Map.put(info, :module, String)} + e -> + e + end + end + def debug_info(module) when is_atom(module) do #TODO: Get modified date from _beam_path to check for cached version? with {_, beam, _beam_path} <- :code.get_object_code(module), diff --git a/mix.exs b/mix.exs index cbe149f9..8a5a9573 100644 --- a/mix.exs +++ b/mix.exs @@ -4,15 +4,9 @@ defmodule ElixirScript.Mixfile do def project do [ app: :elixir_script, -<<<<<<< HEAD version: "0.28.0-dev", elixir: "~> 1.5-dev", elixirc_paths: elixirc_paths(Mix.env), -======= - version: "0.28.0", - elixir: "~> 1.0", - elixirc_paths: elixirc_paths(), ->>>>>>> master escript: escript_config(), deps: deps(), description: description(), From 48e3225e2861c5f368d3d931a73f921f987ac3b8 Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Sun, 11 Jun 2017 17:23:15 -0500 Subject: [PATCH 562/860] Fixes from compiler testing. Replace String compilation with ElixirScript.String --- .tool-versions | 6 +-- .../next/passes/find_used_functions.ex | 42 ++++++++----------- .../next/passes/find_used_modules.ex | 17 +++++--- .../next/passes/translate/examples/example.ex | 5 --- .../next/passes/translate/examples/size.ex | 16 ------- .../next/passes/translate/form.ex | 14 ++++++- .../next/passes/translate/forms/remote.ex | 20 ++++++++- .../next/passes/translate/module.ex | 2 +- .../next/passes/translate/module_state.ex | 21 ---------- priv/std_lib/string.ex | 7 +++- 10 files changed, 71 insertions(+), 79 deletions(-) delete mode 100644 lib/elixir_script/next/passes/translate/examples/example.ex delete mode 100644 lib/elixir_script/next/passes/translate/examples/size.ex delete mode 100644 lib/elixir_script/next/passes/translate/module_state.ex diff --git a/.tool-versions b/.tool-versions index d588b60f..e84347ce 100644 --- a/.tool-versions +++ b/.tool-versions @@ -1,3 +1,3 @@ -erlang ref-OTP-20.0-rc1 -elixir ref-9873e42 -nodejs 7.10.0 \ No newline at end of file +erlang ref-OTP-20.0-rc2 +elixir ref-d19a92b +nodejs 8.1.0 \ No newline at end of file diff --git a/lib/elixir_script/next/passes/find_used_functions.ex b/lib/elixir_script/next/passes/find_used_functions.ex index 30af88af..4fef005e 100644 --- a/lib/elixir_script/next/passes/find_used_functions.ex +++ b/lib/elixir_script/next/passes/find_used_functions.ex @@ -46,34 +46,23 @@ defmodule ElixirScript.FindUsedFunctions do defp walk_module(module, function, arity, pid) do function = {function, arity} - unless ModuleState.has_used?(pid, module, function) do - %{ - attributes: _attrs, - compile_opts: _compile_opts, - definitions: defs, - file: _file, - line: _line, - module: ^module, - unreachable: unreachable - } = ModuleState.get_module(pid, module) + info = ModuleState.get_module(pid, module) state = %{ pid: pid, module: module } - reachable_defs = Enum.filter(defs, fn - { _, type, _, _} when type in [:defmacro, :defmacrop] -> false - { name, _, _, _} -> not(name in [function]) - _ -> true - end) - - Enum.each(reachable_defs, fn({name, _type, _, _clauses}) -> - ModuleState.add_used(state.pid, module, name) - end) + reachable_def = Enum.find(Map.get(info, :definitions, []), fn { name, _, _, _} -> name == function end) - Enum.each(reachable_defs, &walk(&1, state)) + case reachable_def do + nil -> + nil + {name, _type, _, _clauses} = func -> + ModuleState.add_used(state.pid, module, name) + walk(func, state) + end end end @@ -105,6 +94,15 @@ defmodule ElixirScript.FindUsedFunctions do walk({[], params, [], body}, state) end + defp walk({:|, _, [head, tail]}, state) do + walk(head, state) + walk(tail, state) + end + + defp walk({:::, _, _}, state) do + nil + end + defp walk(form, state) when is_list(form) do Enum.each(form, &walk(&1, state)) end @@ -234,10 +232,6 @@ defmodule ElixirScript.FindUsedFunctions do walk(params, state) end - defp walk({function, _, params}, state) when function in [:|, :::] do - nil - end - defp walk({function, _, params}, state) when is_atom(function) and is_list(params) do walk_module(state.module, function, length(params), state.pid) Enum.each(params, &walk(&1, state)) diff --git a/lib/elixir_script/next/passes/find_used_modules.ex b/lib/elixir_script/next/passes/find_used_modules.ex index 466b1bd6..a74848fa 100644 --- a/lib/elixir_script/next/passes/find_used_modules.ex +++ b/lib/elixir_script/next/passes/find_used_modules.ex @@ -99,12 +99,21 @@ defmodule ElixirScript.FindUsedModules do walk({[], params, [], body}, state) end + defp walk({:|, _, [head, tail]}, state) do + walk(head, state) + walk(tail, state) + end + + defp walk({:::, _, _}, state) do + nil + end + defp walk(form, state) when is_list(form) do Enum.each(form, &walk(&1, state)) end defp walk(form, state) when is_atom(form) and form not in [BitString, Function, PID, Port, Reference, Any, Elixir] do - if ElixirScript.Translate.Module.is_elixir_module(form) do + if ElixirScript.Translate.Module.is_elixir_module(form) and !ElixirScript.Translate.Module.is_js_module(form, state) do if ModuleState.get_module(state.pid, form) == nil do execute(form, state.pid) end @@ -133,7 +142,7 @@ defmodule ElixirScript.FindUsedModules do end defp walk({:%, _, [module, params]}, state) do - if ElixirScript.Translate.Module.is_elixir_module(module) do + if ElixirScript.Translate.Module.is_elixir_module(module) and !ElixirScript.Translate.Module.is_js_module(module, state) do if ModuleState.get_module(state.pid, module) == nil do do_execute(module, state.pid) end @@ -233,7 +242,6 @@ defmodule ElixirScript.FindUsedModules do if ModuleState.get_module(state.pid, module) == nil do execute(module, state.pid) end - ModuleState.add_used(state.pid, module, {function, length(params)}) true -> nil end @@ -245,8 +253,7 @@ defmodule ElixirScript.FindUsedModules do walk(params, state) end - defp walk({function, _, params}, state) when is_atom(function) and is_list(params) do - ModuleState.add_used(state.pid, state.module, {function, length(params)}) + defp walk({function, _, params}, state) when is_atom(function) and is_list(params) do Enum.each(params, &walk(&1, state)) end diff --git a/lib/elixir_script/next/passes/translate/examples/example.ex b/lib/elixir_script/next/passes/translate/examples/example.ex deleted file mode 100644 index dd298938..00000000 --- a/lib/elixir_script/next/passes/translate/examples/example.ex +++ /dev/null @@ -1,5 +0,0 @@ -defmodule Example do - def start(_, _) do - -1 - end -end diff --git a/lib/elixir_script/next/passes/translate/examples/size.ex b/lib/elixir_script/next/passes/translate/examples/size.ex deleted file mode 100644 index 10dadd44..00000000 --- a/lib/elixir_script/next/passes/translate/examples/size.ex +++ /dev/null @@ -1,16 +0,0 @@ -defprotocol Example.Size do - def size(data) -end - -defimpl Example.Size, for: BitString do - - def size(string), do: byte_size(string) -end - -defimpl Example.Size, for: Map do - def size(map), do: map_size(map) -end - -defimpl Example.Size, for: Tuple do - def size(tuple), do: tuple_size(tuple) -end \ No newline at end of file diff --git a/lib/elixir_script/next/passes/translate/form.ex b/lib/elixir_script/next/passes/translate/form.ex index 58b95de0..2c2d2a1e 100644 --- a/lib/elixir_script/next/passes/translate/form.ex +++ b/lib/elixir_script/next/passes/translate/form.ex @@ -24,6 +24,18 @@ defmodule ElixirScript.Translate.Form do { J.literal(form), state } end + def compile({:|, _, [head, tail]}, state) do + ast = J.call_expression( + J.member_expression( + J.array_expression([compile!(head, state)]), + J.identifier("concat") + ), + [compile!(tail, state)] + ) + + { ast, state } + end + def compile(form, state) when is_list(form) do ast = J.array_expression( Enum.map(form, &compile!(&1, state)) @@ -151,7 +163,7 @@ defmodule ElixirScript.Translate.Form do def compile({:receive, context, [blocks]}, state) do line = Keyword.get(context, :line, 1) {function, arity} = Map.get(state, :function) - Logger.warn "receive not supported, Module: #{inspect state.module}, Function: #{function}/#{arity}, Line: #{line}" + Logger.warn "receive not supported, Module: #{inspect state.module}, Function: #{function}, Line: #{line}" Receive.compile(blocks, state) end diff --git a/lib/elixir_script/next/passes/translate/forms/remote.ex b/lib/elixir_script/next/passes/translate/forms/remote.ex index bb881afe..f28543a8 100644 --- a/lib/elixir_script/next/passes/translate/forms/remote.ex +++ b/lib/elixir_script/next/passes/translate/forms/remote.ex @@ -143,8 +143,7 @@ defmodule ElixirScript.Translate.Forms.Remote do def process_module_name(module, state) when is_atom(module) do cond do ElixirScript.Translate.Module.is_js_module(module, state) -> - members = tl(Module.split(module)) - Identifier.make_namespace_members(members) + process_js_module_name(module, state) module === Elixir -> members = ["Elixir", "__load"] @@ -168,6 +167,23 @@ defmodule ElixirScript.Translate.Forms.Remote do Form.compile!(module, state) end + defp process_js_module_name(module, state) do + case Module.split(module) do + ["JS"] -> + J.member_expression( + J.member_expression( + J.identifier("Bootstrap"), + J.identifier("Core") + ), + J.identifier("global") + ) + ["JS" | rest] -> + Identifier.make_namespace_members(rest) + x -> + Identifier.make_namespace_members(x) + end + end + defp erlang_compat_function(module, function) do J.member_expression( J.member_expression( diff --git a/lib/elixir_script/next/passes/translate/module.ex b/lib/elixir_script/next/passes/translate/module.ex index 86b48e5e..b18d02da 100644 --- a/lib/elixir_script/next/passes/translate/module.ex +++ b/lib/elixir_script/next/passes/translate/module.ex @@ -57,7 +57,7 @@ defmodule ElixirScript.Translate.Module do # any public functions case exports do %ESTree.ObjectExpression{ properties: [] } -> - ModuleState.put_module(pid, module, Map.put(info, :js_ast, J.program([]))) + nil _ -> { compiled_functions, _ } = Enum.map_reduce(combined_defs, state, &Function.compile(&1, &2)) diff --git a/lib/elixir_script/next/passes/translate/module_state.ex b/lib/elixir_script/next/passes/translate/module_state.ex deleted file mode 100644 index 8e2afdd2..00000000 --- a/lib/elixir_script/next/passes/translate/module_state.ex +++ /dev/null @@ -1,21 +0,0 @@ -defmodule ElixirScript.Translate.ModuleState do - def start_link(module) do - Agent.start_link(fn -> %{ module: module, refs: [] } end) - end - - def stop(pid) do - Agent.stop(pid) - end - - def put_module_ref(pid, module) do - Agent.update(pid, fn(x) -> - %{x | refs: Enum.uniq([module | x.refs]) } - end) - end - - def get_module_refs(pid) do - Agent.get(pid, fn(x) -> - x.refs - end) - end -end \ No newline at end of file diff --git a/priv/std_lib/string.ex b/priv/std_lib/string.ex index 1ff6bcee..3d5465bc 100644 --- a/priv/std_lib/string.ex +++ b/priv/std_lib/string.ex @@ -199,6 +199,11 @@ defmodule ElixirScript.String do end def valid_character?(codepoint) do - ElixirScript.Bootstrap.Functions.is_valid_character(codepoint) + try do + JS.String.fromCodePoint(codepoint) != nil + rescue + _ -> + false + end end end From 1189826772715b80a1aba7bfea8ab63737d21bf1 Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Sun, 11 Jun 2017 19:17:28 -0500 Subject: [PATCH 563/860] Skip loading JS module --- lib/elixir_script/next/passes/find_used_functions.ex | 4 ++++ lib/elixir_script/next/passes/find_used_modules.ex | 4 ++++ 2 files changed, 8 insertions(+) diff --git a/lib/elixir_script/next/passes/find_used_functions.ex b/lib/elixir_script/next/passes/find_used_functions.ex index 4fef005e..a13c15e0 100644 --- a/lib/elixir_script/next/passes/find_used_functions.ex +++ b/lib/elixir_script/next/passes/find_used_functions.ex @@ -215,6 +215,10 @@ defmodule ElixirScript.FindUsedFunctions do walk({function, [], params}, state) end + defp walk({{:., _, [JS, _]}, _, params}, state) do + walk(params, state) + end + defp walk({{:., _, [module, function]}, _, params}, state) do cond do ElixirScript.Translate.Module.is_js_module(module, state) -> diff --git a/lib/elixir_script/next/passes/find_used_modules.ex b/lib/elixir_script/next/passes/find_used_modules.ex index a74848fa..e68ca080 100644 --- a/lib/elixir_script/next/passes/find_used_modules.ex +++ b/lib/elixir_script/next/passes/find_used_modules.ex @@ -234,6 +234,10 @@ defmodule ElixirScript.FindUsedModules do walk({function, [], params}, state) end + defp walk({{:., _, [JS, _]}, _, params}, state) do + walk(params, state) + end + defp walk({{:., _, [module, function]}, _, params}, state) do cond do ElixirScript.Translate.Module.is_js_module(module, state) -> From 26d9dcfa8bba1d99a9528a9cd39fcb0647196342 Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Mon, 12 Jun 2017 20:22:09 -0500 Subject: [PATCH 564/860] Add module to handle JS function calls --- GettingStarted.md | 95 ++------------ JavascriptInterop.md | 6 - lib/elixir_script/next/passes/output.ex | 9 +- .../next/passes/output/js_module.ex | 116 ++++++++++++++++++ .../next/passes/translate/form.ex | 12 +- .../next/passes/translate/forms/js.ex | 69 +++++++++++ .../next/passes/translate/forms/map.ex | 2 +- .../next/passes/translate/forms/pattern.ex | 6 +- .../next/passes/translate/forms/remote.ex | 13 +- .../next/passes/translate/function.ex | 2 +- .../next/passes/translate/identifier.ex | 92 ++++++++++++++ .../next/passes/translate/module.ex | 4 +- .../next/passes/translate/protocol.ex | 2 +- lib/elixir_script/watcher.ex | 12 +- mix.exs | 2 +- 15 files changed, 315 insertions(+), 127 deletions(-) create mode 100644 lib/elixir_script/next/passes/output/js_module.ex create mode 100644 lib/elixir_script/next/passes/translate/forms/js.ex create mode 100644 lib/elixir_script/next/passes/translate/identifier.ex diff --git a/GettingStarted.md b/GettingStarted.md index 6870c716..c5b4681b 100644 --- a/GettingStarted.md +++ b/GettingStarted.md @@ -1,85 +1,16 @@ # Getting Started with ElixirScript -The intent of this guide is to get you started with ElixirScript. It will give you instructions on using ElixirScript. I will go over the two ways you can use Elixirscript: - -* As a CLI -* As a mix dependency - -### CLI - -**macOS**: Elixirscript is available via homebrew `brew install elixirscript`. For everyone else, please read below - -Step 1: Get CLI - -You can download the elixirscript CLI from the [releases page on github](https://github.com/bryanjos/elixirscript/releases). It is a tar file named elixirscript.tar.gz. - -Step 2: Untar - -Next, untar elixirscript.tar.gz - - tar -xvzf elixirscript.tar.gz - -You will want to put the bin folder from the uncompressed folder into your path. This should allow you to use the elixirscript CLI. - -Step 3: Use - -This is the help output of elixirscript - - usage: elixirscript [options] - path to elixir files or - the elixir code string if passed the -e flag - options: - --js-module [:] A js module used in your code. ex: React:react - Multiple can be defined - -f --format [format] module format of output. options: es (default), common, umd - -o --output [path] places output at the given path. - Can be a directory or filename. - -e --elixir read input as elixir code string - --full-build informs the compiler to do a full build instead of an incremental one - -v --version the current version number - -h --help this message - -the `` is the elixir code string or file path you want to convert from elixir to javascript. Below is an example of using a code string and turning it into JavaScript - - $ elixirscript ":atom" -e - -elixirscript also takes a path to your `.ex` files as well: - - $ elixirscript "src" -o "dist" - -If you look in the dist folder you'll see a file called `Elixir.App.js` - -To start your application import the bundle according to whichever module format was selected and -then call start giving it the module and the initial args. - -Ex. If you have a module like so -```elixir -defmodule Example do - start(type, args) do - :console.log("Hello, world") - end -end -``` - -You would start it like so - -```javascript -//ES module example -import Elixir from './Elixir.App' -Elixir.start(Elixir.Example, []) -``` - -### Mix dependency +The intent of this guide is to get you started with ElixirScript. It will give you instructions on using ElixirScript. Adding Elixirscript to your mix project gives you the ability to add it to your list of mix compilers. This means when you `mix compile`, Elixirscript will compile your code as well. Add dependency to your deps in mix.exs: ``` elixir -{:elixir_script, "~> 0.26"} +{:elixir_script, "~> 0.29"} ``` -Elixirscript uses default input, output and module formats if options are not given. If you wish to change any or all options, add an `elixir_script` key to your project configuration. +Elixirscript uses default output and module formats if options are not given. If you wish to change any or all options, add an `elixir_script` key to your project configuration. ``` elixir def project do @@ -89,7 +20,7 @@ Elixirscript uses default input, output and module formats if options are not gi elixir: "~> 1.0", deps: deps, elixir_script: [ - input: "lib/elixirscript", + input: MyEntryModule, output: "priv/elixirscript/Elixir.App.js", format: :es, js_modules: [ @@ -98,14 +29,14 @@ Elixirscript uses default input, output and module formats if options are not gi {Phoenix, "phoenix", default: false} ] ], - compilers: [:elixir_script] ++ Mix.compilers + compilers: Mix.compilers ++ [:elixir_script] ] end ``` Available options are: -* `input`: The folder to look for Elixirscript files in. (defaults to `lib/elixirscript`) +* `input`: The entry module(s) for your application or library * `output`: The path of the generated JavaScript file. (defaults to `priv/elixirscript`) @@ -126,20 +57,8 @@ Available options are: ### Macros -Elixirscript supports public macros. Private macros are currently unsupported. +Elixirscript supports all macros ### JavaScript Interop Check out the [JavaScript Interoperability](JavaScriptInterop.html) documentation - -#### Frontend Project Boilerplate - -There is an [elixirscript frontend boilerplate project](https://github.com/elixirscript/elixirscript-project-boilerplate). This setup uses gulp and webpack to build and bundle assets. - -#### elixirscript-brunch - -There is an Brunch plugin, [elixirscript-brunch](https://www.npmjs.com/package/elixirscript-brunch). - -#### elixirscript-loader - -There is also a webpack loader, [elixirscript-loader](https://www.npmjs.com/package/elixirscript-loader). diff --git a/JavascriptInterop.md b/JavascriptInterop.md index 13095e2f..db0c0e45 100644 --- a/JavascriptInterop.md +++ b/JavascriptInterop.md @@ -58,12 +58,6 @@ If using ElixirScript in a mix project, you can do so inside of the ElixirScript end ``` -Or if using the CLI, you can do so by passing each module via the `js-module` flag - -``` -elixirscript "app/elixirscript" -o dist --js-module React:react --js-module ReactDOM:react-dom -``` - Interacting with these modules works the same as interacting with an ElixirScript module ```elixir diff --git a/lib/elixir_script/next/passes/output.ex b/lib/elixir_script/next/passes/output.ex index 925897ab..cec29f28 100644 --- a/lib/elixir_script/next/passes/output.ex +++ b/lib/elixir_script/next/passes/output.ex @@ -23,16 +23,13 @@ defmodule ElixirScript.Output do end defp bundle(modules, opts) do - ElixirScript.Passes.CreateJSModules.compile(modules, opts) - - js_code = modules - |> ElixirScript.Passes.CreateJSModules.compile(opts) + modules + |> ElixirScript.Output.JSModule.compile(opts) |> List.wrap |> Builder.program |> prepare_js_ast |> Generator.generate - - concat(js_code) + |> concat end defp concat(code) do diff --git a/lib/elixir_script/next/passes/output/js_module.ex b/lib/elixir_script/next/passes/output/js_module.ex new file mode 100644 index 00000000..60eba1e9 --- /dev/null +++ b/lib/elixir_script/next/passes/output/js_module.ex @@ -0,0 +1,116 @@ +defmodule ElixirScript.Output.JSModule do + @moduledoc false + + alias ESTree.Tools.Builder, as: J + + def compile(body, opts) do + declarator = J.variable_declarator( + J.identifier("Elixir"), + J.object_expression([]) + ) + + elixir = J.variable_declaration([declarator], :const) + + table_additions = Enum.map(opts.js_modules, fn + {module, path} -> add_import_to_table(module) + {module, path, _} -> add_import_to_table(module) + end) + + ast = opts.module_formatter.build( + [], + opts.js_modules, + [elixir, create_atom_table(), start, load] ++ table_additions ++ body, + J.identifier("Elixir") + ) + + ast + end + + def start do + J.assignment_expression( + :=, + J.member_expression( + J.identifier("Elixir"), + J.identifier("start") + ), + J.function_expression( + [J.identifier(:app), J.identifier(:args)], + [], + J.block_statement([ + J.call_expression( + J.member_expression( + J.call_expression( + J.member_expression( + J.identifier(:app), + J.identifier("__load") + ), + [J.identifier("Elixir")] + ), + J.identifier("start") + ), + [ElixirScript.Translator.Primitive.make_atom(:normal), J.identifier(:args)] + ) + ]) + ) + ) + end + + def load do + J.assignment_expression( + :=, + J.member_expression( + J.identifier("Elixir"), + J.identifier("load") + ), + J.function_expression( + [J.identifier(:module)], + [], + J.block_statement([ + J.return_statement( + J.call_expression( + J.member_expression( + J.identifier(:module), + J.identifier("__load") + ), + [J.identifier("Elixir")] + ) + ) + ]) + ) + ) + end + + defp create_atom_table() do + J.assignment_expression( + :=, + J.member_expression( + J.identifier("Elixir"), + J.identifier("__table__") + ), + J.object_expression([]) + ) + end + + defp add_import_to_table(module_name) do + ref = ElixirScript.Translate.Identifier.make_namespace_members(module_name) + J.assignment_expression( + :=, + J.member_expression( + J.member_expression( + J.identifier("Elixir"), + J.identifier("__table__") + ), + J.call_expression( + J.member_expression( + J.identifier("Symbol"), + J.identifier("for") + ), + [J.literal(ref.name)] + ), + true + ), + ref + ) + end + +end \ No newline at end of file diff --git a/lib/elixir_script/next/passes/translate/form.ex b/lib/elixir_script/next/passes/translate/form.ex index 2c2d2a1e..b049af01 100644 --- a/lib/elixir_script/next/passes/translate/form.ex +++ b/lib/elixir_script/next/passes/translate/form.ex @@ -2,7 +2,7 @@ defmodule ElixirScript.Translate.Form do alias ESTree.Tools.Builder, as: J alias ElixirScript.Translate.Forms.{Bitstring, Match, Try, For, Receive, Remote, Pattern} alias ElixirScript.Translate.Functions.{Erlang, Lists, Maps} - alias ElixirScript.Translator.Identifier + alias ElixirScript.Translate.Identifier alias ElixirScript.Translate.Clause require Logger @@ -185,6 +185,10 @@ defmodule ElixirScript.Translate.Form do {ast, state} end + def compile({{:., _, [JS, _]}, _, _} = ast, state) do + ElixirScript.Translate.Forms.JS.compile(ast, state) + end + def compile({:., _, call} = ast, state) when is_list(call) do Remote.compile(ast, state) end @@ -193,7 +197,7 @@ defmodule ElixirScript.Translate.Form do {function_name, _} = Map.get(state, :function) ast = J.call_expression( - ElixirScript.Translator.Identifier.make_function_name(function_name), + ElixirScript.Translate.Identifier.make_function_name(function_name), Enum.map(params, &compile!(&1, state)) |> List.flatten ) @@ -202,7 +206,7 @@ defmodule ElixirScript.Translate.Form do def compile({var, _, params}, state) when is_list(params) and is_atom(var) do ast = J.call_expression( - ElixirScript.Translator.Identifier.make_function_name(var), + ElixirScript.Translate.Identifier.make_function_name(var), Enum.map(params, &compile!(&1, state)) |> List.flatten ) @@ -220,7 +224,7 @@ defmodule ElixirScript.Translate.Form do def compile({var, _, _}, state) do var = Pattern.get_variable_name(to_string(var), state) - { ElixirScript.Translator.Identifier.make_identifier(var), state } + { ElixirScript.Translate.Identifier.make_identifier(var), state } end end diff --git a/lib/elixir_script/next/passes/translate/forms/js.ex b/lib/elixir_script/next/passes/translate/forms/js.ex new file mode 100644 index 00000000..11250f99 --- /dev/null +++ b/lib/elixir_script/next/passes/translate/forms/js.ex @@ -0,0 +1,69 @@ +defmodule ElixirScript.Translate.Forms.JS do + @moduledoc false + alias ESTree.Tools.Builder, as: J + alias ElixirScript.Translate.Form + + def global() do + Builder.member_expression( + Builder.member_expression( + Builder.identifier("Bootstrap"), + Builder.identifier("Core") + ), + Builder.identifier("global") + ) + end + + def compile({{:., _, [JS, :debugger]}, _, _}, state) do + ast = J.debugger_statement() + {ast, state} + end + + def compile({{:., _, [JS, :this]}, _, _}, state) do + ast = J.this_expression() + {ast, state} + end + + def compile({{:., _, [JS, :new]}, _, [module, params]}, state) do + members = Module.split(module) + + params = case params do + p when is_list(p) -> + Enum.map(params, &Form.compile!(&1, state)) + p -> + [J.rest_element(Form.compile!(params, state))] + end + + ast = J.new_expression( + ElixirScript.Translate.Identifier.make_namespace_members(members), + params + ) + + {ast, state} + end + + defp do_translate({{:., _, [JS, :throw]}, _, [term]}, state) do + ast = J.throw_statement( + Form.compile!(term, state) + ) + + {ast, state} + end + + defp do_translate({{:., _, [JS, :import]}, _, [term]}, state) do + ast = J.call_expression( + J.identifier("import"), + [Form.compile!(term, state)] + ) + + {ast, state} + end + + defp do_translate({{:., _, [JS, function]}, _, params}, state) do + ast = J.call_expression( + J.identifier(function), + Enum.map(params, &Form.compile!(&1, state)) + ) + + {ast, state} + end +end \ No newline at end of file diff --git a/lib/elixir_script/next/passes/translate/forms/map.ex b/lib/elixir_script/next/passes/translate/forms/map.ex index ce1ee7f5..49480138 100644 --- a/lib/elixir_script/next/passes/translate/forms/map.ex +++ b/lib/elixir_script/next/passes/translate/forms/map.ex @@ -50,7 +50,7 @@ defmodule ElixirScript.Translate.Forms.Map do true -> J.literal(k) false -> - ElixirScript.Translator.Identifier.make_identifier(k) + ElixirScript.Translate.Identifier.make_identifier(k) end J.property(key, value) diff --git a/lib/elixir_script/next/passes/translate/forms/pattern.ex b/lib/elixir_script/next/passes/translate/forms/pattern.ex index 6b120564..d0f07d07 100644 --- a/lib/elixir_script/next/passes/translate/forms/pattern.ex +++ b/lib/elixir_script/next/passes/translate/forms/pattern.ex @@ -133,7 +133,7 @@ defmodule ElixirScript.Translate.Forms.Pattern do params = Enum.reduce(elements, [], fn ({:::, _, [{ variable, _, params }, _]}, state) when is_nil(params) when is_list(params) and length(params) == 0 -> - state ++ [ElixirScript.Translator.Identifier.make_identifier(variable)] + state ++ [ElixirScript.Translate.Identifier.make_identifier(variable)] _, state -> state end) @@ -161,7 +161,7 @@ defmodule ElixirScript.Translate.Forms.Pattern do end defp process_pattern({var, _, _}, _) do - { [PM.parameter()], [ElixirScript.Translator.Identifier.make_identifier(var)] } + { [PM.parameter()], [ElixirScript.Translate.Identifier.make_identifier(var)] } end defp reduce_patterns(patterns, _) do @@ -173,6 +173,6 @@ defmodule ElixirScript.Translate.Forms.Pattern do defp unify(target, source, state) do { patterns, params } = do_compile([source], state) - { [PM.capture(hd(patterns))], params ++ [ElixirScript.Translator.Identifier.make_identifier(target)] } + { [PM.capture(hd(patterns))], params ++ [ElixirScript.Translate.Identifier.make_identifier(target)] } end end diff --git a/lib/elixir_script/next/passes/translate/forms/remote.ex b/lib/elixir_script/next/passes/translate/forms/remote.ex index f28543a8..6d4a751a 100644 --- a/lib/elixir_script/next/passes/translate/forms/remote.ex +++ b/lib/elixir_script/next/passes/translate/forms/remote.ex @@ -3,7 +3,7 @@ defmodule ElixirScript.Translate.Forms.Remote do alias ESTree.Tools.Builder, as: J alias ElixirScript.Translate.Form - alias ElixirScript.Translator.Identifier + alias ElixirScript.Translate.Identifier @erlang_modules [ :erlang, @@ -25,6 +25,7 @@ defmodule ElixirScript.Translate.Forms.Remote do includes function heads for converting some erlang functions into JavaScript functions. """ + def compile({:., _, [:erlang, :+]}, state) do ast = erlang_compat_function("erlang", "plus") { ast, state } @@ -114,7 +115,7 @@ defmodule ElixirScript.Translate.Forms.Remote do ), J.identifier(module) ), - ElixirScript.Translator.Identifier.make_function_name(function) + ElixirScript.Translate.Identifier.make_function_name(function) ) { ast, state } @@ -127,9 +128,9 @@ defmodule ElixirScript.Translate.Forms.Remote do def compile({:., _, [module, function]}, state) do function_name = cond do ElixirScript.Translate.Module.is_js_module(module, state) -> - ElixirScript.Translator.Identifier.make_extern_function_name(function) + ElixirScript.Translate.Identifier.make_extern_function_name(function) true -> - ElixirScript.Translator.Identifier.make_function_name(function) + ElixirScript.Translate.Identifier.make_function_name(function) end ast = J.member_expression( @@ -159,7 +160,7 @@ defmodule ElixirScript.Translate.Forms.Remote do [J.identifier("Elixir")] ) true -> - ElixirScript.Translator.Identifier.make_identifier(module) + ElixirScript.Translate.Identifier.make_identifier(module) end end @@ -193,7 +194,7 @@ defmodule ElixirScript.Translate.Forms.Remote do ), J.identifier(module) ), - ElixirScript.Translator.Identifier.make_function_name(function) + ElixirScript.Translate.Identifier.make_function_name(function) ) end end \ No newline at end of file diff --git a/lib/elixir_script/next/passes/translate/function.ex b/lib/elixir_script/next/passes/translate/function.ex index 9dd6726b..ad5a5e6f 100644 --- a/lib/elixir_script/next/passes/translate/function.ex +++ b/lib/elixir_script/next/passes/translate/function.ex @@ -32,7 +32,7 @@ defmodule ElixirScript.Translate.Function do arg_matches_declaration = J.variable_declaration([arg_matches_declarator], :let) declarator = J.variable_declarator( - ElixirScript.Translator.Identifier.make_function_name(name), + ElixirScript.Translate.Identifier.make_function_name(name), J.function_expression( [J.rest_element(J.identifier("__function_args__"))], [], diff --git a/lib/elixir_script/next/passes/translate/identifier.ex b/lib/elixir_script/next/passes/translate/identifier.ex new file mode 100644 index 00000000..5c95e03a --- /dev/null +++ b/lib/elixir_script/next/passes/translate/identifier.ex @@ -0,0 +1,92 @@ +defmodule ElixirScript.Translate.Identifier do + @moduledoc false + alias ESTree.Tools.Builder, as: J + + @js_reserved_words [ + :break, + :case, + :class, + :const, + :continue, + :debugger, + :default, + :delete, + :do, + :else, + :export, + :extends, + :finally, + :function, + :if, + :import, + :in, + :instanceof, + :new, + :return, + :super, + :switch, + :throw, + :try, + :typeof, + :var, + :void, + :while, + :with, + :yield + ] + + def make_identifier([ast]) do + make_identifier(ast) + end + + def make_identifier(ast) do + ast + |> filter_name + |> J.identifier + end + + defp filter_name(name) when is_tuple(name) do + name + end + + defp filter_name(reserved_word) when reserved_word in @js_reserved_words do + "__#{Atom.to_string(reserved_word)}__" + end + + defp filter_name(name) do + to_string(name) + |> String.replace("?", "__qmark__") + |> String.replace("!", "__emark__") + end + + defp make_alias([x]) do + make_identifier(x) + end + + defp make_alias([h|t]) do + J.member_expression(make_alias(t), make_identifier(h)) + end + + def make_namespace_members(module_name) do + case module_name do + m when is_list(m) -> + m + m when is_binary(m) -> + String.split(m, ".") + m when is_atom(m) -> + Module.split(m) + end + |> Enum.reverse + |> make_alias + end + + def make_function_name(name) do + name = filter_name(name) + J.identifier(name) + end + + def make_extern_function_name(name) do + J.identifier("#{name}") + end + +end diff --git a/lib/elixir_script/next/passes/translate/module.ex b/lib/elixir_script/next/passes/translate/module.ex index b18d02da..68e2388d 100644 --- a/lib/elixir_script/next/passes/translate/module.ex +++ b/lib/elixir_script/next/passes/translate/module.ex @@ -3,7 +3,7 @@ defmodule ElixirScript.Translate.Module do alias ESTree.Tools.Builder, as: J alias ElixirScript.Translate.Function alias ElixirScript.Translate.Form - alias ElixirScript.Translator.Identifier + alias ElixirScript.Translate.Identifier alias ElixirScript.State, as: ModuleState @doc """ @@ -87,7 +87,7 @@ defmodule ElixirScript.Translate.Module do defp make_exports(reachable_defs) do exports = Enum.reduce(reachable_defs, [], fn {{name, arity}, :def, _, _}, list -> - function_name = ElixirScript.Translator.Identifier.make_identifier(name) + function_name = ElixirScript.Translate.Identifier.make_identifier(name) list ++ [J.property(function_name, function_name, :init, true)] _, list -> list diff --git a/lib/elixir_script/next/passes/translate/protocol.ex b/lib/elixir_script/next/passes/translate/protocol.ex index d64375bd..baaed852 100644 --- a/lib/elixir_script/next/passes/translate/protocol.ex +++ b/lib/elixir_script/next/passes/translate/protocol.ex @@ -3,7 +3,7 @@ defmodule ElixirScript.Translate.Protocol do alias ESTree.Tools.Builder, as: J alias ElixirScript.Translate.Function alias ElixirScript.Translate.Form - alias ElixirScript.Translator.Identifier + alias ElixirScript.Translate.Identifier alias ElixirScript.State, as: ModuleState diff --git a/lib/elixir_script/watcher.ex b/lib/elixir_script/watcher.ex index 8d484de1..5f6de96c 100644 --- a/lib/elixir_script/watcher.ex +++ b/lib/elixir_script/watcher.ex @@ -35,15 +35,11 @@ defmodule ElixirScript.Watcher do end defp input_changed?(path, state) do - file = Path.basename(path) - - case file do - "." <> _ -> - false + case Path.extname(path) do + ".beam" -> + true _ -> - Enum.any?(List.wrap(state[:input]), fn(x) -> - path == Path.absname(Path.join([x, file])) - end) + false end end end diff --git a/mix.exs b/mix.exs index 8a5a9573..83839435 100644 --- a/mix.exs +++ b/mix.exs @@ -4,7 +4,7 @@ defmodule ElixirScript.Mixfile do def project do [ app: :elixir_script, - version: "0.28.0-dev", + version: "0.29.0-dev", elixir: "~> 1.5-dev", elixirc_paths: elixirc_paths(Mix.env), escript: escript_config(), From 6d4d62575b549580b23b707f75eeba1c55018657 Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Tue, 13 Jun 2017 02:15:08 -0500 Subject: [PATCH 565/860] Some fixes for pattern compilation --- .../next/passes/translate/form.ex | 20 ++++++++- .../next/passes/translate/forms/js.ex | 41 +++++++++++++++---- .../next/passes/translate/forms/pattern.ex | 8 +++- .../next/passes/translate/forms/try.ex | 10 ++--- .../next/passes/translate/function.ex | 17 ++++++++ src/javascript/lib/core/functions.js | 8 ++++ test/support/main.ex | 7 ++++ 7 files changed, 93 insertions(+), 18 deletions(-) diff --git a/lib/elixir_script/next/passes/translate/form.ex b/lib/elixir_script/next/passes/translate/form.ex index b049af01..195f2aa6 100644 --- a/lib/elixir_script/next/passes/translate/form.ex +++ b/lib/elixir_script/next/passes/translate/form.ex @@ -65,7 +65,7 @@ defmodule ElixirScript.Translate.Form do end def compile({:{}, _, elements}, state) do - ast = J.call_expression( + ast = J.new_expression( J.member_expression( J.member_expression( J.identifier("Bootstrap"), @@ -79,6 +79,15 @@ defmodule ElixirScript.Translate.Form do {ast, state} end + def compile({:&, _, [{:/, _, [{{:., _, [_module, _function]} = ast, [], []}, _]}]}, state) do + Remote.compile(ast, state) + end + + def compile({:&, _, [{:/, _, [{var, _, _}, _]}]}, state) do + ast = ElixirScript.Translate.Identifier.make_function_name(var) + {ast, state} + end + def compile({:%{}, _, _} = map, state) do ElixirScript.Translate.Forms.Map.compile(map, state) end @@ -213,6 +222,15 @@ defmodule ElixirScript.Translate.Form do {ast, state} end + def compile({function, _, []}, state) do + ast = J.call_expression( + ElixirScript.Translate.Forms.JS.call_property(), + [compile!(function, state)] + ) + + {ast, state} + end + def compile({function, _, params}, state) when is_list(params) do ast = J.call_expression( compile!(function, state), diff --git a/lib/elixir_script/next/passes/translate/forms/js.ex b/lib/elixir_script/next/passes/translate/forms/js.ex index 11250f99..49da8f7b 100644 --- a/lib/elixir_script/next/passes/translate/forms/js.ex +++ b/lib/elixir_script/next/passes/translate/forms/js.ex @@ -3,13 +3,26 @@ defmodule ElixirScript.Translate.Forms.JS do alias ESTree.Tools.Builder, as: J alias ElixirScript.Translate.Form + def call_property() do + J.member_expression( + J.member_expression( + J.identifier("Bootstrap"), + J.member_expression( + J.identifier("Core"), + J.identifier("Functions") + ) + ), + J.identifier("call_property") + ) + end + def global() do - Builder.member_expression( - Builder.member_expression( - Builder.identifier("Bootstrap"), - Builder.identifier("Core") + J.member_expression( + J.member_expression( + J.identifier("Bootstrap"), + J.identifier("Core") ), - Builder.identifier("global") + J.identifier("global") ) end @@ -41,7 +54,7 @@ defmodule ElixirScript.Translate.Forms.JS do {ast, state} end - defp do_translate({{:., _, [JS, :throw]}, _, [term]}, state) do + def compile({{:., _, [JS, :throw]}, _, [term]}, state) do ast = J.throw_statement( Form.compile!(term, state) ) @@ -49,7 +62,7 @@ defmodule ElixirScript.Translate.Forms.JS do {ast, state} end - defp do_translate({{:., _, [JS, :import]}, _, [term]}, state) do + def compile({{:., _, [JS, :import]}, _, [term]}, state) do ast = J.call_expression( J.identifier("import"), [Form.compile!(term, state)] @@ -58,7 +71,19 @@ defmodule ElixirScript.Translate.Forms.JS do {ast, state} end - defp do_translate({{:., _, [JS, function]}, _, params}, state) do + def compile({{:., _, [JS, function]}, _, []}, state) do + ast = J.call_expression( + call_property(), + [ + global(), + Form.compile!(to_string(function), state) + ] + ) + + {ast, state} + end + + def compile({{:., _, [JS, function]}, _, params}, state) do ast = J.call_expression( J.identifier(function), Enum.map(params, &Form.compile!(&1, state)) diff --git a/lib/elixir_script/next/passes/translate/forms/pattern.ex b/lib/elixir_script/next/passes/translate/forms/pattern.ex index d0f07d07..17f16e6d 100644 --- a/lib/elixir_script/next/passes/translate/forms/pattern.ex +++ b/lib/elixir_script/next/passes/translate/forms/pattern.ex @@ -109,6 +109,10 @@ defmodule ElixirScript.Translate.Forms.Pattern do process_pattern({:|, context, [head, tail]}, state) end + defp process_pattern({:%, _, [module, {:%{}, _, props}]}, state) do + process_pattern({:%{}, [], [__struct__: module] ++ props}, state) + end + defp process_pattern({:%{}, _, props}, state) do properties = Enum.map(props, fn({key, value}) -> {pattern, params} = process_pattern(value, state) @@ -152,11 +156,11 @@ defmodule ElixirScript.Translate.Forms.Pattern do { [PM.starts_with(prefix)], [Form.compile!(value, state)] } end - defp process_pattern({:=, _, [{name, _, _}, right]}, state) do + defp process_pattern({:=, _, [{name, _, _}, right]}, state) when not name in [:%, :{}, :^, :%{}, :<<>>] do unify(name, right, state) end - defp process_pattern({:=, _, [left, {name, _, _}]}, state) do + defp process_pattern({:=, _, [left, {name, _, _}]}, state) when not name in [:%, :{}, :^, :%{}, :<<>>] do unify(name, left, state) end diff --git a/lib/elixir_script/next/passes/translate/forms/try.ex b/lib/elixir_script/next/passes/translate/forms/try.ex index 4488e49c..2729e39f 100644 --- a/lib/elixir_script/next/passes/translate/forms/try.ex +++ b/lib/elixir_script/next/passes/translate/forms/try.ex @@ -2,7 +2,7 @@ defmodule ElixirScript.Translate.Forms.Try do @moduledoc false alias ESTree.Tools.Builder, as: JS alias ElixirScript.Translate.Clause - alias ElixirScript.Translate.Form + alias ElixirScript.Translate.{Form, Function} def compile(blocks, state) do try_block = Keyword.get(blocks, :do) @@ -92,12 +92,8 @@ defmodule ElixirScript.Translate.Forms.Try do end defp prepare_function_body(body, state) do - {ast, state} = body - |> List.wrap - |> Enum.map_reduce(state, &Form.compile(&1, &2)) + {ast, state} = Function.compile_block(body, state) - ast - |> List.flatten - |> Clause.return_last_statement + Clause.return_last_statement(ast) end end diff --git a/lib/elixir_script/next/passes/translate/function.ex b/lib/elixir_script/next/passes/translate/function.ex index ad5a5e6f..457a3df8 100644 --- a/lib/elixir_script/next/passes/translate/function.ex +++ b/lib/elixir_script/next/passes/translate/function.ex @@ -128,4 +128,21 @@ defmodule ElixirScript.Translate.Function do defp compile_clause({:->, _, [params, body]}, state) do compile_clause({[], params, [], body}, state) end + + def compile_block(block, state) do + ast = case block do + nil -> + J.identifier("null") + {:__block__, _, block_body} -> + {list, _} = Enum.map_reduce(block_body, state, &Form.compile(&1, &2)) + List.flatten(list) + b when is_list(b) -> + {list, _} = Enum.map_reduce(b, state, &Form.compile(&1, &2)) + List.flatten(list) + _ -> + Form.compile!(block, state) + end + + {ast, state} + end end diff --git a/src/javascript/lib/core/functions.js b/src/javascript/lib/core/functions.js index 9df6ba34..423f323a 100644 --- a/src/javascript/lib/core/functions.js +++ b/src/javascript/lib/core/functions.js @@ -23,6 +23,14 @@ function iterator_to_reducer(iterable, acc, fun) { } function call_property(item, property) { + if (!property) { + if (item instanceof Function) { + return item(); + } + + return item; + } + let prop = null; if ( diff --git a/test/support/main.ex b/test/support/main.ex index a18d3d90..66ec84e4 100644 --- a/test/support/main.ex +++ b/test/support/main.ex @@ -1,5 +1,12 @@ defmodule Main do def start(:normal, [callback]) do callback.("started") + user = %User{} + user.first + draw() + end + + defp draw() do + JS.console.log("Here") end end From 14412ca8bab60f91861fb1ef0ed04a85790a6629 Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Thu, 15 Jun 2017 19:42:51 -0500 Subject: [PATCH 566/860] Turned named functions into function declarations. Fixed bugs where assignment was in case and cond expressions --- lib/elixir_script/next/passes/translate/form.ex | 12 ++++++++++-- .../next/passes/translate/forms/match.ex | 16 +++++++++++++++- .../next/passes/translate/function.ex | 10 ++++------ 3 files changed, 29 insertions(+), 9 deletions(-) diff --git a/lib/elixir_script/next/passes/translate/form.ex b/lib/elixir_script/next/passes/translate/form.ex index 195f2aa6..e9db55c3 100644 --- a/lib/elixir_script/next/passes/translate/form.ex +++ b/lib/elixir_script/next/passes/translate/form.ex @@ -116,6 +116,15 @@ defmodule ElixirScript.Translate.Form do For.compile(ast, state) end + def compile({:case, _, [{:=, _, [left, _]} = match, [do: clauses]]}, state) do + {match_ast, state} = compile(match, state) + {case_ast, state} = compile({:case, [], [left, [do: clauses]]}, state) + + match_ast = List.wrap(match_ast) + + { match_ast ++ [case_ast], state } + end + def compile({:case, _, [condition, [do: clauses]]}, state) do func = J.call_expression( J.member_expression( @@ -135,10 +144,9 @@ defmodule ElixirScript.Translate.Form do def compile({:cond, _, [[do: clauses]]}, state) do processed_clauses = Enum.map(clauses, fn({:->, _, [clause, clause_body]}) -> - { translated_body, state } = Enum.map_reduce(List.wrap(clause_body), state, &compile(&1, &2)) + { translated_body, state } = ElixirScript.Translate.Function.compile_block(clause_body, state) translated_body = translated_body - |> List.flatten |> Clause.return_last_statement translated_body = J.arrow_function_expression([], [], J.block_statement(translated_body)) diff --git a/lib/elixir_script/next/passes/translate/forms/match.ex b/lib/elixir_script/next/passes/translate/forms/match.ex index 9dbd453c..6a2a8613 100644 --- a/lib/elixir_script/next/passes/translate/forms/match.ex +++ b/lib/elixir_script/next/passes/translate/forms/match.ex @@ -6,6 +6,13 @@ defmodule ElixirScript.Translate.Forms.Match do def compile({:=, _, [left, right]}, state) do { right_ast, state } = Form.compile(right, state) + {var_dec, right_ast} = case right_ast do + [variable_declaration, x] -> + {variable_declaration, x} + x -> + {nil, x} + end + { patterns, params, state } = Pattern.compile([left], state) declarator = J.variable_declarator( @@ -35,7 +42,14 @@ defmodule ElixirScript.Translate.Forms.Match do {:{}, _, _ } -> make_tuple_ref(array_pattern, params) _ -> - array_pattern + List.wrap(array_pattern) + end + + js_ast = case var_dec do + nil -> + js_ast + x -> + [x] ++ js_ast end { js_ast, state } diff --git a/lib/elixir_script/next/passes/translate/function.ex b/lib/elixir_script/next/passes/translate/function.ex index 457a3df8..1740164d 100644 --- a/lib/elixir_script/next/passes/translate/function.ex +++ b/lib/elixir_script/next/passes/translate/function.ex @@ -31,9 +31,8 @@ defmodule ElixirScript.Translate.Function do arg_matches_declaration = J.variable_declaration([arg_matches_declarator], :let) - declarator = J.variable_declarator( - ElixirScript.Translate.Identifier.make_function_name(name), - J.function_expression( + function_dec = J.function_declaration( + ElixirScript.Translate.Identifier.make_function_name(name), [J.rest_element(J.identifier("__function_args__"))], [], J.block_statement([ @@ -50,9 +49,8 @@ defmodule ElixirScript.Translate.Function do ) ]) ) - ) - { J.variable_declaration([declarator], :const), state } + { function_dec, state } end defp compile_clauses(clauses, state) do @@ -145,4 +143,4 @@ defmodule ElixirScript.Translate.Function do {ast, state} end -end +end \ No newline at end of file From 660cd718d408022593fcd578be9c6e51363a9603 Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Thu, 15 Jun 2017 20:59:29 -0500 Subject: [PATCH 567/860] Made it so variables defined in parameters work --- .../next/passes/find_used_functions.ex | 2 + .../next/passes/translate/form.ex | 62 +++++++++++++------ .../next/passes/translate/function.ex | 39 +++++++++++- 3 files changed, 82 insertions(+), 21 deletions(-) diff --git a/lib/elixir_script/next/passes/find_used_functions.ex b/lib/elixir_script/next/passes/find_used_functions.ex index a13c15e0..6285f446 100644 --- a/lib/elixir_script/next/passes/find_used_functions.ex +++ b/lib/elixir_script/next/passes/find_used_functions.ex @@ -129,6 +129,8 @@ defmodule ElixirScript.FindUsedFunctions do end defp walk({:%, _, [module, params]}, state) do + ModuleState.add_used(state.pid, module, {:__struct__, 0}) + ModuleState.add_used(state.pid, module, {:__struct__, 1}) walk(params, state) end diff --git a/lib/elixir_script/next/passes/translate/form.ex b/lib/elixir_script/next/passes/translate/form.ex index e9db55c3..f530e8cb 100644 --- a/lib/elixir_script/next/passes/translate/form.ex +++ b/lib/elixir_script/next/passes/translate/form.ex @@ -188,18 +188,8 @@ defmodule ElixirScript.Translate.Form do Try.compile(blocks, state) end - def compile({:fn, _, clauses}, state) do - {clauses_ast, _} = Enum.map_reduce(clauses, state, &Clause.compile(&1, &2)) - - ast = J.call_expression( - J.member_expression( - ElixirScript.Translate.Function.patterns_ast(), - J.identifier("defmatch") - ), - clauses_ast - ) - - {ast, state} + def compile({:fn, _, _} = ast, state) do + ElixirScript.Translate.Function.compile(ast, state) end def compile({{:., _, [JS, _]}, _, _} = ast, state) do @@ -212,22 +202,35 @@ defmodule ElixirScript.Translate.Form do def compile({:super, context, params}, state) when is_list(params) do {function_name, _} = Map.get(state, :function) + {var_decs, params} = compile_params(params, state) ast = J.call_expression( ElixirScript.Translate.Identifier.make_function_name(function_name), - Enum.map(params, &compile!(&1, state)) |> List.flatten + params ) - {ast, state} + case var_decs do + [] -> + {ast, state} + _ -> + {var_decs ++ List.wrap(ast), state} + end end def compile({var, _, params}, state) when is_list(params) and is_atom(var) do + {var_decs, params} = compile_params(params, state) + ast = J.call_expression( ElixirScript.Translate.Identifier.make_function_name(var), - Enum.map(params, &compile!(&1, state)) |> List.flatten + params ) - {ast, state} + case var_decs do + [] -> + {ast, state} + _ -> + {var_decs ++ List.wrap(ast), state} + end end def compile({function, _, []}, state) do @@ -240,17 +243,38 @@ defmodule ElixirScript.Translate.Form do end def compile({function, _, params}, state) when is_list(params) do + {var_decs, params} = compile_params(params, state) + ast = J.call_expression( compile!(function, state), - Enum.map(params, &compile!(&1, state)) |> List.flatten + params ) - {ast, state} + case var_decs do + [] -> + {ast, state} + _ -> + {var_decs ++ List.wrap(ast), state} + end end - def compile({var, _, _}, state) do + def compile({var, _, _} = ast, state) do var = Pattern.get_variable_name(to_string(var), state) { ElixirScript.Translate.Identifier.make_identifier(var), state } end + defp compile_params(params, state) do + {params, var_decs} = Enum.map_reduce(params, [], fn + ({:=, _, [left, _]} = ast, acc) -> + {ast, state} = compile(ast, state) + left = compile!(left, state) + + {left, acc ++ List.wrap(ast)} + (x, acc) -> + {compile!(x, state), acc} + end) + + {var_decs, params} + end + end diff --git a/lib/elixir_script/next/passes/translate/function.ex b/lib/elixir_script/next/passes/translate/function.ex index 1740164d..d50a0be9 100644 --- a/lib/elixir_script/next/passes/translate/function.ex +++ b/lib/elixir_script/next/passes/translate/function.ex @@ -20,7 +20,38 @@ defmodule ElixirScript.Translate.Function do ) end - def compile({{name, arity}, type, _, clauses}, state) do + def compile({:fn, _, clauses}, state) do + clauses = compile_clauses(clauses, state) + + arg_matches_declarator = J.variable_declarator( + J.identifier("__arg_matches__"), + J.identifier("null") + ) + + arg_matches_declaration = J.variable_declaration([arg_matches_declarator], :let) + + function_dec = J.arrow_function_expression( + [J.rest_element(J.identifier("__function_args__"))], + [], + J.block_statement([ + arg_matches_declaration, + clauses, + J.throw_statement( + J.call_expression( + J.member_expression( + patterns_ast(), + J.identifier("MatchError") + ), + [J.identifier("__function_args__")] + ) + ) + ]) + ) + + { function_dec, state } + end + + def compile({{name, arity}, _type, _, clauses}, state) do state = Map.put(state, :function, {name, arity}) clauses = compile_clauses(clauses, state) @@ -84,7 +115,11 @@ defmodule ElixirScript.Translate.Function do end defp compile_clause({ _, args, guards, body}, state) do - state = Map.put(state, :vars, %{}) + state = if !Map.has_key?(state, :vars) do + Map.put(state, :vars, %{}) + else + state + end {patterns, params, state} = Pattern.compile(args, state) guard = Clause.compile_guard(params, guards, state) From 50500776fcc4ccaf5538dad8bd26eb1e0ad47e9a Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Fri, 16 Jun 2017 23:10:59 -0500 Subject: [PATCH 568/860] Crawling protocol implementation functions to make sure to get used functions --- .../next/passes/find_used_functions.ex | 58 +++++++++++------ .../next/passes/find_used_modules.ex | 63 ++++++++++--------- .../next/passes/translate/forms/pattern.ex | 2 +- .../next/passes/translate/module.ex | 1 + test/support/main.ex | 7 --- 5 files changed, 76 insertions(+), 55 deletions(-) diff --git a/lib/elixir_script/next/passes/find_used_functions.ex b/lib/elixir_script/next/passes/find_used_functions.ex index 6285f446..e656a580 100644 --- a/lib/elixir_script/next/passes/find_used_functions.ex +++ b/lib/elixir_script/next/passes/find_used_functions.ex @@ -13,6 +13,14 @@ defmodule ElixirScript.FindUsedFunctions do module -> walk_module(module, pid) end) + + modules = ElixirScript.State.list_modules(pid) + Enum.each(modules, fn + {module, info} -> + if get_in(info, [:attributes, :protocol_impl]) do + walk_module(module, pid) + end + end) end defp walk_module(module, pid) do @@ -71,16 +79,7 @@ defmodule ElixirScript.FindUsedFunctions do end defp walk({ _, _args, _guards, body}, state) do - case body do - nil -> - nil - {:__block__, _, block_body} -> - Enum.map(block_body, &walk(&1, state)) - b when is_list(b) -> - Enum.map(b, &walk(&1, state)) - _ -> - walk(body, state) - end + walk_block(body, state) end defp walk({:->, _, [[{:when, _, params}], body ]}, state) do @@ -112,7 +111,7 @@ defmodule ElixirScript.FindUsedFunctions do end defp walk({:{}, _, elements}, state) do - Enum.each(elements, &walk(&1, state)) + walk(elements, state) end defp walk({:%{}, _, properties}, state) do @@ -148,10 +147,10 @@ defmodule ElixirScript.FindUsedFunctions do [into: expression, do: expression2] -> walk(expression, state) - walk(expression2, state) + walk_block(expression2, state) [do: expression] -> - walk(expression, state) + walk_block(expression, state) filter -> walk(filter, state) @@ -170,8 +169,15 @@ defmodule ElixirScript.FindUsedFunctions do end) end - defp walk({:receive, _context, _}, _state) do - nil + defp walk({:receive, _context, blocks}, state) do + do_block = Keyword.get(blocks, :do) + after_block = Keyword.get(blocks, :after, nil) + + walk_block(do_block, state) + + if after_block do + Enum.each(List.wrap(after_block), &walk(&1, state)) + end end defp walk({:try, _, [blocks]}, state) do @@ -181,7 +187,7 @@ defmodule ElixirScript.FindUsedFunctions do after_block = Keyword.get(blocks, :after, nil) else_block = Keyword.get(blocks, :else, nil) - Enum.each(List.wrap(try_block), &walk(&1, state)) + walk_block(try_block, state) if rescue_block do Enum.each(rescue_block, fn @@ -240,15 +246,29 @@ defmodule ElixirScript.FindUsedFunctions do defp walk({function, _, params}, state) when is_atom(function) and is_list(params) do walk_module(state.module, function, length(params), state.pid) - Enum.each(params, &walk(&1, state)) + walk(params, state) end - defp walk({_, _, params}, state) when is_list(params) do - Enum.each(params, &walk(&1, state)) + defp walk({value, _, params}, state) when is_list(params) do + walk(value, state) + walk(params, state) end defp walk(_, _) do nil end + defp walk_block(block, state) do + case block do + nil -> + nil + {:__block__, _, block_body} -> + Enum.each(block_body, &walk(&1, state)) + b when is_list(b) -> + Enum.each(b, &walk(&1, state)) + _ -> + walk(block, state) + end + end + end \ No newline at end of file diff --git a/lib/elixir_script/next/passes/find_used_modules.ex b/lib/elixir_script/next/passes/find_used_modules.ex index e68ca080..bbb70cfd 100644 --- a/lib/elixir_script/next/passes/find_used_modules.ex +++ b/lib/elixir_script/next/passes/find_used_modules.ex @@ -68,7 +68,7 @@ defmodule ElixirScript.FindUsedModules do Enum.each(implementations, fn {impl, info} -> walk_module(impl, info, pid) - end) + end) end defp walk({{_name, _arity}, _type, _, clauses}, state) do @@ -76,16 +76,7 @@ defmodule ElixirScript.FindUsedModules do end defp walk({ _, _args, _guards, body}, state) do - case body do - nil -> - nil - {:__block__, _, block_body} -> - Enum.map(block_body, &walk(&1, state)) - b when is_list(b) -> - Enum.map(b, &walk(&1, state)) - _ -> - walk(body, state) - end + walk_block(body, state) end defp walk({:->, _, [[{:when, _, params}], body ]}, state) do @@ -165,10 +156,10 @@ defmodule ElixirScript.FindUsedModules do [into: expression, do: expression2] -> walk(expression, state) - walk(expression2, state) + walk_block(expression2, state) [do: expression] -> - walk(expression, state) + walk_block(expression, state) filter -> walk(filter, state) @@ -187,8 +178,15 @@ defmodule ElixirScript.FindUsedModules do end) end - defp walk({:receive, _context, _}, _state) do - nil + defp walk({:receive, _context, blocks}, state) do + do_block = Keyword.get(blocks, :do) + after_block = Keyword.get(blocks, :after, nil) + + walk_block(do_block, state) + + if after_block do + Enum.each(List.wrap(after_block), &walk(&1, state)) + end end defp walk({:try, _, [blocks]}, state) do @@ -198,7 +196,7 @@ defmodule ElixirScript.FindUsedModules do after_block = Keyword.get(blocks, :after, nil) else_block = Keyword.get(blocks, :else, nil) - Enum.each(List.wrap(try_block), &walk(&1, state)) + walk_block(try_block, state) if rescue_block do Enum.each(rescue_block, fn @@ -234,11 +232,11 @@ defmodule ElixirScript.FindUsedModules do walk({function, [], params}, state) end - defp walk({{:., _, [JS, _]}, _, params}, state) do - walk(params, state) + defp walk({:., _, [JS, _]}, state) do + nil end - defp walk({{:., _, [module, function]}, _, params}, state) do + defp walk({:., _, [module, function]}, state) do cond do ElixirScript.Translate.Module.is_js_module(module, state) -> nil @@ -247,26 +245,35 @@ defmodule ElixirScript.FindUsedModules do execute(module, state.pid) end true -> - nil + walk(module, state) + walk(function, state) end - - walk(params, state) end defp walk({:super, _, params}, state) do walk(params, state) end - defp walk({function, _, params}, state) when is_atom(function) and is_list(params) do - Enum.each(params, &walk(&1, state)) - end - - defp walk({_, _, params}, state) when is_list(params) do - Enum.each(params, &walk(&1, state)) + defp walk({function, _, params}, state) when is_list(params) do + walk(function, state) + walk(params, state) end defp walk(_, _) do nil end + defp walk_block(block, state) do + case block do + nil -> + nil + {:__block__, _, block_body} -> + Enum.each(block_body, &walk(&1, state)) + b when is_list(b) -> + Enum.each(b, &walk(&1, state)) + _ -> + walk(block, state) + end + end + end \ No newline at end of file diff --git a/lib/elixir_script/next/passes/translate/forms/pattern.ex b/lib/elixir_script/next/passes/translate/forms/pattern.ex index 17f16e6d..803a725c 100644 --- a/lib/elixir_script/next/passes/translate/forms/pattern.ex +++ b/lib/elixir_script/next/passes/translate/forms/pattern.ex @@ -55,7 +55,7 @@ defmodule ElixirScript.Translate.Forms.Pattern do end defp process_pattern({:^, _, [value]}, state) do - { [PM.bound(Form.compile!(value, state))], [nil] } + { [PM.bound(Form.compile!(value, state))], [] } end defp process_pattern({:_, _, _}, _) do diff --git a/lib/elixir_script/next/passes/translate/module.ex b/lib/elixir_script/next/passes/translate/module.ex index 68e2388d..7dda9eae 100644 --- a/lib/elixir_script/next/passes/translate/module.ex +++ b/lib/elixir_script/next/passes/translate/module.ex @@ -44,6 +44,7 @@ defmodule ElixirScript.Translate.Module do else Enum.filter(reachable_defs, fn { {:start, 2}, _, _, _ } -> true + { {:__struct__, _}, _, _, _ } -> true { name, _, _, _} -> name in used _ -> false end) diff --git a/test/support/main.ex b/test/support/main.ex index 66ec84e4..a18d3d90 100644 --- a/test/support/main.ex +++ b/test/support/main.ex @@ -1,12 +1,5 @@ defmodule Main do def start(:normal, [callback]) do callback.("started") - user = %User{} - user.first - draw() - end - - defp draw() do - JS.console.log("Here") end end From 62306b7774a6902c19dc71d29f40b04249ab61f4 Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Thu, 22 Jun 2017 21:53:53 -0500 Subject: [PATCH 569/860] Updated pattern matching library and erlang types library --- .tool-versions | 2 +- .../next/passes/translate/forms/pattern.ex | 44 +- .../next/passes/translate/function.ex | 4 +- .../next/passes/translate/module.ex | 18 +- package.json | 6 +- rollup.config.js | 2 +- src/javascript/lib/core/protocol.js | 28 +- test/support/main.ex | 1 + yarn.lock | 755 +++++++++--------- 9 files changed, 452 insertions(+), 408 deletions(-) diff --git a/.tool-versions b/.tool-versions index e84347ce..3f0ad299 100644 --- a/.tool-versions +++ b/.tool-versions @@ -1,3 +1,3 @@ -erlang ref-OTP-20.0-rc2 +erlang 20.0 elixir ref-d19a92b nodejs 8.1.0 \ No newline at end of file diff --git a/lib/elixir_script/next/passes/translate/forms/pattern.ex b/lib/elixir_script/next/passes/translate/forms/pattern.ex index 803a725c..14e4f4f9 100644 --- a/lib/elixir_script/next/passes/translate/forms/pattern.ex +++ b/lib/elixir_script/next/passes/translate/forms/pattern.ex @@ -59,7 +59,7 @@ defmodule ElixirScript.Translate.Forms.Pattern do end defp process_pattern({:_, _, _}, _) do - { [PM.wildcard()], [J.identifier(:_)] } + { [PM.parameter()], [J.identifier(:_)] } end defp process_pattern({a, b}, state) do @@ -110,20 +110,40 @@ defmodule ElixirScript.Translate.Forms.Pattern do end defp process_pattern({:%, _, [module, {:%{}, _, props}]}, state) do - process_pattern({:%{}, [], [__struct__: module] ++ props}, state) + process_pattern({:%{}, [], [__module__struct__: module] ++ props}, state) end defp process_pattern({:%{}, _, props}, state) do - properties = Enum.map(props, fn({key, value}) -> - {pattern, params} = process_pattern(value, state) - property = case key do - {:^, _, [the_key]} -> - J.property(Form.compile!(the_key, state), hd(List.wrap(pattern)), :init, false, false, true) - _ -> - ElixirScript.Translate.Forms.Map.make_property(Form.compile!(key, state), hd(List.wrap(pattern))) - end - - { property, params } + properties = Enum.map(props, fn + {:__module__struct__, module} -> + a = J.object_expression([%ESTree.Property{ + key: J.identifier("__MODULE__"), + value: J.call_expression( + J.member_expression( + J.identifier("Symbol"), + J.identifier("for") + ), + [J.literal(to_string(module))] + ) + }]) + + property = ElixirScript.Translate.Forms.Map.make_property( + Form.compile!(:__struct__, state), + a + ) + + { property, [] } + + {key, value} -> + {pattern, params} = process_pattern(value, state) + property = case key do + {:^, _, [the_key]} -> + J.property(Form.compile!(the_key, state), hd(List.wrap(pattern)), :init, false, false, true) + _ -> + ElixirScript.Translate.Forms.Map.make_property(Form.compile!(key, state), hd(List.wrap(pattern))) + end + + { property, params } end) {props, params} = Enum.reduce(properties, {[], []}, fn({prop, param}, {props, params}) -> diff --git a/lib/elixir_script/next/passes/translate/function.ex b/lib/elixir_script/next/passes/translate/function.ex index d50a0be9..ba6e1fc1 100644 --- a/lib/elixir_script/next/passes/translate/function.ex +++ b/lib/elixir_script/next/passes/translate/function.ex @@ -37,7 +37,7 @@ defmodule ElixirScript.Translate.Function do arg_matches_declaration, clauses, J.throw_statement( - J.call_expression( + J.new_expression( J.member_expression( patterns_ast(), J.identifier("MatchError") @@ -70,7 +70,7 @@ defmodule ElixirScript.Translate.Function do arg_matches_declaration, clauses, J.throw_statement( - J.call_expression( + J.new_expression( J.member_expression( patterns_ast(), J.identifier("MatchError") diff --git a/lib/elixir_script/next/passes/translate/module.ex b/lib/elixir_script/next/passes/translate/module.ex index 7dda9eae..9f716f80 100644 --- a/lib/elixir_script/next/passes/translate/module.ex +++ b/lib/elixir_script/next/passes/translate/module.ex @@ -52,7 +52,7 @@ defmodule ElixirScript.Translate.Module do #we combine our function arities combined_defs = combine_defs(used_defs) - exports = make_exports(combined_defs) + exports = make_exports(module, combined_defs) # Don't skip compilation and output of modules that don't have # any public functions @@ -85,7 +85,7 @@ defmodule ElixirScript.Translate.Module do end) end - defp make_exports(reachable_defs) do + defp make_exports(module, reachable_defs) do exports = Enum.reduce(reachable_defs, [], fn {{name, arity}, :def, _, _}, list -> function_name = ElixirScript.Translate.Identifier.make_identifier(name) @@ -96,10 +96,16 @@ defmodule ElixirScript.Translate.Module do # Add an attribute to use to determine if this is a module # Will be used by the is_atom implementation - exports ++ [ElixirScript.Translate.Forms.Map.make_property( - Form.compile!("__MODULE__", %{}), - Form.compile!(true, %{}) - )] + exports = exports ++ [%ESTree.Property{ + key: J.identifier("__MODULE__"), + value: J.call_expression( + J.member_expression( + J.identifier("Symbol"), + J.identifier("for") + ), + [J.literal(to_string(module))] + ) + }] J.object_expression(exports) end diff --git a/package.json b/package.json index 55cc3f34..23da045b 100644 --- a/package.json +++ b/package.json @@ -22,8 +22,8 @@ "author": "", "license": "MIT", "dependencies": { - "erlang-types": "^1.0.0", - "tailored": "2.4.5" + "erlang-types": "^1.0.1", + "tailored": "^2.4.6" }, "devDependencies": { "ava": "^0.19.1", @@ -48,4 +48,4 @@ "babelrc": true } } -} \ No newline at end of file +} diff --git a/rollup.config.js b/rollup.config.js index a318efdf..c06836ac 100644 --- a/rollup.config.js +++ b/rollup.config.js @@ -10,7 +10,7 @@ export default { babel({ babelrc: false, }), - babili({}), + //babili({}), ], targets: [{ dest: 'priv/build/iife/Elixir.Bootstrap.js', format: 'iife' }], }; diff --git a/src/javascript/lib/core/protocol.js b/src/javascript/lib/core/protocol.js index 02fb4f08..5ae04ddf 100644 --- a/src/javascript/lib/core/protocol.js +++ b/src/javascript/lib/core/protocol.js @@ -11,7 +11,12 @@ class Protocol { const thing = args[0]; let fun = null; - if (Number.isInteger(thing) && this.hasImplementation(Core.Integer)) { + if (thing === null && this.hasImplementation(Symbol('null'))) { + fun = this.registry.get(Symbol)[funName]; + } else if ( + Number.isInteger(thing) && + this.hasImplementation(Core.Integer) + ) { fun = this.registry.get(Core.Integer)[funName]; } else if ( typeof thing === 'number' && @@ -20,14 +25,19 @@ class Protocol { ) { fun = this.registry.get(Core.Float)[funName]; } else if ( - typeof thing === 'string' && this.hasImplementation(Core.BitString) + typeof thing === 'string' && + this.hasImplementation(Core.BitString) ) { fun = this.registry.get(Core.BitString)[funName]; } else if ( - thing[Symbol.for('__struct__')] && this.hasImplementation(thing) + thing && + thing[Symbol.for('__struct__')] && + this.hasImplementation(thing) ) { - fun = this.registry.get(thing[Symbol.for('__struct__')])[funName]; - } else if (this.hasImplementation(thing)) { + fun = this.registry.get(thing[Symbol.for('__struct__')].__MODULE__)[ + funName + ]; + } else if (thing !== null && this.hasImplementation(thing)) { fun = this.registry.get(thing.constructor)[funName]; } else if (this.fallback) { fun = this.fallback[funName]; @@ -57,11 +67,13 @@ class Protocol { hasImplementation(thing) { if ( - thing === Core.Integer || thing === Core.Float || thing === Core.BitString + thing === Core.Integer || + thing === Core.Float || + thing === Core.BitString ) { return this.registry.has(thing); - } else if (thing[Symbol.for('__struct__')]) { - return this.registry.has(thing[Symbol.for('__struct__')]); + } else if (thing && thing[Symbol.for('__struct__')]) { + return this.registry.has(thing[Symbol.for('__struct__')].__MODULE__); } return this.registry.has(thing.constructor); diff --git a/test/support/main.ex b/test/support/main.ex index a18d3d90..c37a6f0e 100644 --- a/test/support/main.ex +++ b/test/support/main.ex @@ -1,5 +1,6 @@ defmodule Main do def start(:normal, [callback]) do callback.("started") + Enum.each(1..5, fn(x) -> JS.console.log(x) end) end end diff --git a/yarn.lock b/yarn.lock index c96129c7..7ceffecc 100644 --- a/yarn.lock +++ b/yarn.lock @@ -7,8 +7,8 @@ resolved "https://registry.yarnpkg.com/@ava/babel-plugin-throws-helper/-/babel-plugin-throws-helper-2.0.0.tgz#2fc1fe3c211a71071a4eca7b8f7af5842cd1ae7c" "@ava/babel-preset-stage-4@^1.0.0": - version "1.0.0" - resolved "https://registry.yarnpkg.com/@ava/babel-preset-stage-4/-/babel-preset-stage-4-1.0.0.tgz#a613b5e152f529305422546b072d47facfb26291" + version "1.1.0" + resolved "https://registry.yarnpkg.com/@ava/babel-preset-stage-4/-/babel-preset-stage-4-1.1.0.tgz#ae60be881a0babf7d35f52aba770d1f6194f76bd" dependencies: babel-plugin-check-es2015-constants "^6.8.0" babel-plugin-syntax-trailing-function-commas "^6.20.0" @@ -64,8 +64,8 @@ ajv-keywords@^1.0.0: resolved "https://registry.yarnpkg.com/ajv-keywords/-/ajv-keywords-1.5.1.tgz#314dd0a4b3368fad3dfcdc54ede6171b886daf3c" ajv@^4.7.0, ajv@^4.9.1: - version "4.11.5" - resolved "https://registry.yarnpkg.com/ajv/-/ajv-4.11.5.tgz#b6ee74657b993a01dce44b7944d56f485828d5bd" + version "4.11.8" + resolved "https://registry.yarnpkg.com/ajv/-/ajv-4.11.8.tgz#82ffb02b29e662ae53bdc20af15947706739c536" dependencies: co "^4.6.0" json-stable-stringify "^1.0.1" @@ -101,8 +101,8 @@ ansi-styles@^2.2.1: resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-2.2.1.tgz#b432dd3358b634cf75e1e4664368240533c1ddbe" ansi-styles@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-3.0.0.tgz#5404e93a544c4fec7f048262977bebfe3155e0c1" + version "3.1.0" + resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-3.1.0.tgz#09c202d5c917ec23188caa5c9cb9179cd9547750" dependencies: color-convert "^1.0.0" @@ -124,8 +124,8 @@ append-transform@^0.4.0: default-require-extensions "^1.0.0" aproba@^1.0.3: - version "1.1.1" - resolved "https://registry.yarnpkg.com/aproba/-/aproba-1.1.1.tgz#95d3600f07710aa0e9298c726ad5ecf2eacbabab" + version "1.1.2" + resolved "https://registry.yarnpkg.com/aproba/-/aproba-1.1.2.tgz#45c6629094de4e96f693ef7eab74ae079c240fc1" archy@^1.0.0: version "1.0.0" @@ -321,20 +321,20 @@ babel-code-frame@^6.16.0, babel-code-frame@^6.22.0: esutils "^2.0.2" js-tokens "^3.0.0" -babel-core@6, babel-core@^6.17.0, babel-core@^6.21.0, babel-core@^6.24.0: - version "6.24.0" - resolved "https://registry.yarnpkg.com/babel-core/-/babel-core-6.24.0.tgz#8f36a0a77f5c155aed6f920b844d23ba56742a02" +babel-core@6, babel-core@^6.17.0, babel-core@^6.21.0, babel-core@^6.24.0, babel-core@^6.24.1: + version "6.25.0" + resolved "https://registry.yarnpkg.com/babel-core/-/babel-core-6.25.0.tgz#7dd42b0463c742e9d5296deb3ec67a9322dad729" dependencies: babel-code-frame "^6.22.0" - babel-generator "^6.24.0" - babel-helpers "^6.23.0" + babel-generator "^6.25.0" + babel-helpers "^6.24.1" babel-messages "^6.23.0" - babel-register "^6.24.0" + babel-register "^6.24.1" babel-runtime "^6.22.0" - babel-template "^6.23.0" - babel-traverse "^6.23.1" - babel-types "^6.23.0" - babylon "^6.11.0" + babel-template "^6.25.0" + babel-traverse "^6.25.0" + babel-types "^6.25.0" + babylon "^6.17.2" convert-source-map "^1.1.0" debug "^2.1.1" json5 "^0.5.0" @@ -345,84 +345,84 @@ babel-core@6, babel-core@^6.17.0, babel-core@^6.21.0, babel-core@^6.24.0: slash "^1.0.0" source-map "^0.5.0" -babel-generator@^6.1.0, babel-generator@^6.18.0, babel-generator@^6.24.0: - version "6.24.0" - resolved "https://registry.yarnpkg.com/babel-generator/-/babel-generator-6.24.0.tgz#eba270a8cc4ce6e09a61be43465d7c62c1f87c56" +babel-generator@^6.1.0, babel-generator@^6.18.0, babel-generator@^6.25.0: + version "6.25.0" + resolved "https://registry.yarnpkg.com/babel-generator/-/babel-generator-6.25.0.tgz#33a1af70d5f2890aeb465a4a7793c1df6a9ea9fc" dependencies: babel-messages "^6.23.0" babel-runtime "^6.22.0" - babel-types "^6.23.0" + babel-types "^6.25.0" detect-indent "^4.0.0" jsesc "^1.3.0" lodash "^4.2.0" source-map "^0.5.0" trim-right "^1.0.1" -babel-helper-builder-binary-assignment-operator-visitor@^6.22.0: - version "6.22.0" - resolved "https://registry.yarnpkg.com/babel-helper-builder-binary-assignment-operator-visitor/-/babel-helper-builder-binary-assignment-operator-visitor-6.22.0.tgz#29df56be144d81bdeac08262bfa41d2c5e91cdcd" +babel-helper-builder-binary-assignment-operator-visitor@^6.24.1: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-helper-builder-binary-assignment-operator-visitor/-/babel-helper-builder-binary-assignment-operator-visitor-6.24.1.tgz#cce4517ada356f4220bcae8a02c2b346f9a56664" dependencies: - babel-helper-explode-assignable-expression "^6.22.0" + babel-helper-explode-assignable-expression "^6.24.1" babel-runtime "^6.22.0" - babel-types "^6.22.0" + babel-types "^6.24.1" -babel-helper-call-delegate@^6.22.0: - version "6.22.0" - resolved "https://registry.yarnpkg.com/babel-helper-call-delegate/-/babel-helper-call-delegate-6.22.0.tgz#119921b56120f17e9dae3f74b4f5cc7bcc1b37ef" +babel-helper-call-delegate@^6.24.1: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-helper-call-delegate/-/babel-helper-call-delegate-6.24.1.tgz#ece6aacddc76e41c3461f88bfc575bd0daa2df8d" dependencies: - babel-helper-hoist-variables "^6.22.0" + babel-helper-hoist-variables "^6.24.1" babel-runtime "^6.22.0" - babel-traverse "^6.22.0" - babel-types "^6.22.0" + babel-traverse "^6.24.1" + babel-types "^6.24.1" -babel-helper-define-map@^6.23.0: - version "6.23.0" - resolved "https://registry.yarnpkg.com/babel-helper-define-map/-/babel-helper-define-map-6.23.0.tgz#1444f960c9691d69a2ced6a205315f8fd00804e7" +babel-helper-define-map@^6.24.1: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-helper-define-map/-/babel-helper-define-map-6.24.1.tgz#7a9747f258d8947d32d515f6aa1c7bd02204a080" dependencies: - babel-helper-function-name "^6.23.0" + babel-helper-function-name "^6.24.1" babel-runtime "^6.22.0" - babel-types "^6.23.0" + babel-types "^6.24.1" lodash "^4.2.0" babel-helper-evaluate-path@^0.0.3: version "0.0.3" resolved "https://registry.yarnpkg.com/babel-helper-evaluate-path/-/babel-helper-evaluate-path-0.0.3.tgz#1d103ac9d4a59e5d431842212f151785f7ac547b" -babel-helper-explode-assignable-expression@^6.22.0: - version "6.22.0" - resolved "https://registry.yarnpkg.com/babel-helper-explode-assignable-expression/-/babel-helper-explode-assignable-expression-6.22.0.tgz#c97bf76eed3e0bae4048121f2b9dae1a4e7d0478" +babel-helper-explode-assignable-expression@^6.24.1: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-helper-explode-assignable-expression/-/babel-helper-explode-assignable-expression-6.24.1.tgz#f25b82cf7dc10433c55f70592d5746400ac22caa" dependencies: babel-runtime "^6.22.0" - babel-traverse "^6.22.0" - babel-types "^6.22.0" + babel-traverse "^6.24.1" + babel-types "^6.24.1" babel-helper-flip-expressions@^0.0.2: version "0.0.2" resolved "https://registry.yarnpkg.com/babel-helper-flip-expressions/-/babel-helper-flip-expressions-0.0.2.tgz#7bab2cf61162bc92703e9b298ef512bcf77d6787" -babel-helper-function-name@^6.22.0, babel-helper-function-name@^6.23.0: - version "6.23.0" - resolved "https://registry.yarnpkg.com/babel-helper-function-name/-/babel-helper-function-name-6.23.0.tgz#25742d67175c8903dbe4b6cb9d9e1fcb8dcf23a6" +babel-helper-function-name@^6.24.1: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-helper-function-name/-/babel-helper-function-name-6.24.1.tgz#d3475b8c03ed98242a25b48351ab18399d3580a9" dependencies: - babel-helper-get-function-arity "^6.22.0" + babel-helper-get-function-arity "^6.24.1" babel-runtime "^6.22.0" - babel-template "^6.23.0" - babel-traverse "^6.23.0" - babel-types "^6.23.0" + babel-template "^6.24.1" + babel-traverse "^6.24.1" + babel-types "^6.24.1" -babel-helper-get-function-arity@^6.22.0: - version "6.22.0" - resolved "https://registry.yarnpkg.com/babel-helper-get-function-arity/-/babel-helper-get-function-arity-6.22.0.tgz#0beb464ad69dc7347410ac6ade9f03a50634f5ce" +babel-helper-get-function-arity@^6.24.1: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-helper-get-function-arity/-/babel-helper-get-function-arity-6.24.1.tgz#8f7782aa93407c41d3aa50908f89b031b1b6853d" dependencies: babel-runtime "^6.22.0" - babel-types "^6.22.0" + babel-types "^6.24.1" -babel-helper-hoist-variables@^6.22.0: - version "6.22.0" - resolved "https://registry.yarnpkg.com/babel-helper-hoist-variables/-/babel-helper-hoist-variables-6.22.0.tgz#3eacbf731d80705845dd2e9718f600cfb9b4ba72" +babel-helper-hoist-variables@^6.24.1: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-helper-hoist-variables/-/babel-helper-hoist-variables-6.24.1.tgz#1ecb27689c9d25513eadbc9914a73f5408be7a76" dependencies: babel-runtime "^6.22.0" - babel-types "^6.22.0" + babel-types "^6.24.1" babel-helper-is-nodes-equiv@^0.0.1: version "0.0.1" @@ -436,56 +436,60 @@ babel-helper-mark-eval-scopes@^0.0.3: version "0.0.3" resolved "https://registry.yarnpkg.com/babel-helper-mark-eval-scopes/-/babel-helper-mark-eval-scopes-0.0.3.tgz#902f75aeb537336edc35eb9f52b6f09db7785328" -babel-helper-optimise-call-expression@^6.23.0: - version "6.23.0" - resolved "https://registry.yarnpkg.com/babel-helper-optimise-call-expression/-/babel-helper-optimise-call-expression-6.23.0.tgz#f3ee7eed355b4282138b33d02b78369e470622f5" +babel-helper-mark-eval-scopes@^0.1.1: + version "0.1.1" + resolved "https://registry.yarnpkg.com/babel-helper-mark-eval-scopes/-/babel-helper-mark-eval-scopes-0.1.1.tgz#4554345edf9f2549427bd2098e530253f8af2992" + +babel-helper-optimise-call-expression@^6.24.1: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-helper-optimise-call-expression/-/babel-helper-optimise-call-expression-6.24.1.tgz#f7a13427ba9f73f8f4fa993c54a97882d1244257" dependencies: babel-runtime "^6.22.0" - babel-types "^6.23.0" + babel-types "^6.24.1" -babel-helper-regex@^6.22.0: - version "6.22.0" - resolved "https://registry.yarnpkg.com/babel-helper-regex/-/babel-helper-regex-6.22.0.tgz#79f532be1647b1f0ee3474b5f5c3da58001d247d" +babel-helper-regex@^6.24.1: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-helper-regex/-/babel-helper-regex-6.24.1.tgz#d36e22fab1008d79d88648e32116868128456ce8" dependencies: babel-runtime "^6.22.0" - babel-types "^6.22.0" + babel-types "^6.24.1" lodash "^4.2.0" -babel-helper-remap-async-to-generator@^6.22.0: - version "6.22.0" - resolved "https://registry.yarnpkg.com/babel-helper-remap-async-to-generator/-/babel-helper-remap-async-to-generator-6.22.0.tgz#2186ae73278ed03b8b15ced089609da981053383" +babel-helper-remap-async-to-generator@^6.24.1: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-helper-remap-async-to-generator/-/babel-helper-remap-async-to-generator-6.24.1.tgz#5ec581827ad723fecdd381f1c928390676e4551b" dependencies: - babel-helper-function-name "^6.22.0" + babel-helper-function-name "^6.24.1" babel-runtime "^6.22.0" - babel-template "^6.22.0" - babel-traverse "^6.22.0" - babel-types "^6.22.0" + babel-template "^6.24.1" + babel-traverse "^6.24.1" + babel-types "^6.24.1" -babel-helper-remove-or-void@^0.0.1: - version "0.0.1" - resolved "https://registry.yarnpkg.com/babel-helper-remove-or-void/-/babel-helper-remove-or-void-0.0.1.tgz#f602790e465acf2dfbe84fb3dd210c43a2dd7262" +babel-helper-remove-or-void@^0.1.1: + version "0.1.1" + resolved "https://registry.yarnpkg.com/babel-helper-remove-or-void/-/babel-helper-remove-or-void-0.1.1.tgz#9d7e1856dc6fafcb41b283a416730dc1844f66d7" -babel-helper-replace-supers@^6.22.0, babel-helper-replace-supers@^6.23.0: - version "6.23.0" - resolved "https://registry.yarnpkg.com/babel-helper-replace-supers/-/babel-helper-replace-supers-6.23.0.tgz#eeaf8ad9b58ec4337ca94223bacdca1f8d9b4bfd" +babel-helper-replace-supers@^6.24.1: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-helper-replace-supers/-/babel-helper-replace-supers-6.24.1.tgz#bf6dbfe43938d17369a213ca8a8bf74b6a90ab1a" dependencies: - babel-helper-optimise-call-expression "^6.23.0" + babel-helper-optimise-call-expression "^6.24.1" babel-messages "^6.23.0" babel-runtime "^6.22.0" - babel-template "^6.23.0" - babel-traverse "^6.23.0" - babel-types "^6.23.0" + babel-template "^6.24.1" + babel-traverse "^6.24.1" + babel-types "^6.24.1" babel-helper-to-multiple-sequence-expressions@^0.0.4: version "0.0.4" resolved "https://registry.yarnpkg.com/babel-helper-to-multiple-sequence-expressions/-/babel-helper-to-multiple-sequence-expressions-0.0.4.tgz#d94414b386b6286fbaad77f073dea9b34324b01c" -babel-helpers@^6.23.0: - version "6.23.0" - resolved "https://registry.yarnpkg.com/babel-helpers/-/babel-helpers-6.23.0.tgz#4f8f2e092d0b6a8808a4bde79c27f1e2ecf0d992" +babel-helpers@^6.24.1: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-helpers/-/babel-helpers-6.24.1.tgz#3471de9caec388e5c850e597e58a26ddf37602b2" dependencies: babel-runtime "^6.22.0" - babel-template "^6.23.0" + babel-template "^6.24.1" babel-messages@^6.23.0: version "6.23.0" @@ -525,11 +529,11 @@ babel-plugin-minify-constant-folding@^0.0.4: jsesc "^2.4.0" babel-plugin-minify-dead-code-elimination@^0.1.4: - version "0.1.4" - resolved "https://registry.yarnpkg.com/babel-plugin-minify-dead-code-elimination/-/babel-plugin-minify-dead-code-elimination-0.1.4.tgz#18b6ecfab77c29caca061d8210fa3495001e4fa1" + version "0.1.7" + resolved "https://registry.yarnpkg.com/babel-plugin-minify-dead-code-elimination/-/babel-plugin-minify-dead-code-elimination-0.1.7.tgz#774f536f347b98393a27baa717872968813c342c" dependencies: - babel-helper-mark-eval-scopes "^0.0.3" - babel-helper-remove-or-void "^0.0.1" + babel-helper-mark-eval-scopes "^0.1.1" + babel-helper-remove-or-void "^0.1.1" lodash.some "^4.6.0" babel-plugin-minify-flip-comparisons@^0.0.2: @@ -589,10 +593,10 @@ babel-plugin-syntax-trailing-function-commas@^6.20.0, babel-plugin-syntax-traili resolved "https://registry.yarnpkg.com/babel-plugin-syntax-trailing-function-commas/-/babel-plugin-syntax-trailing-function-commas-6.22.0.tgz#ba0360937f8d06e40180a43fe0d5616fff532cf3" babel-plugin-transform-async-to-generator@^6.16.0, babel-plugin-transform-async-to-generator@^6.22.0: - version "6.22.0" - resolved "https://registry.yarnpkg.com/babel-plugin-transform-async-to-generator/-/babel-plugin-transform-async-to-generator-6.22.0.tgz#194b6938ec195ad36efc4c33a971acf00d8cd35e" + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-async-to-generator/-/babel-plugin-transform-async-to-generator-6.24.1.tgz#6536e378aff6cb1d5517ac0e40eb3e9fc8d08761" dependencies: - babel-helper-remap-async-to-generator "^6.22.0" + babel-helper-remap-async-to-generator "^6.24.1" babel-plugin-syntax-async-functions "^6.8.0" babel-runtime "^6.22.0" @@ -609,35 +613,35 @@ babel-plugin-transform-es2015-block-scoped-functions@^6.22.0: babel-runtime "^6.22.0" babel-plugin-transform-es2015-block-scoping@^6.23.0: - version "6.23.0" - resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-block-scoping/-/babel-plugin-transform-es2015-block-scoping-6.23.0.tgz#e48895cf0b375be148cd7c8879b422707a053b51" + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-block-scoping/-/babel-plugin-transform-es2015-block-scoping-6.24.1.tgz#76c295dc3a4741b1665adfd3167215dcff32a576" dependencies: babel-runtime "^6.22.0" - babel-template "^6.23.0" - babel-traverse "^6.23.0" - babel-types "^6.23.0" + babel-template "^6.24.1" + babel-traverse "^6.24.1" + babel-types "^6.24.1" lodash "^4.2.0" babel-plugin-transform-es2015-classes@^6.23.0, babel-plugin-transform-es2015-classes@^6.9.0: - version "6.23.0" - resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-classes/-/babel-plugin-transform-es2015-classes-6.23.0.tgz#49b53f326202a2fd1b3bbaa5e2edd8a4f78643c1" + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-classes/-/babel-plugin-transform-es2015-classes-6.24.1.tgz#5a4c58a50c9c9461e564b4b2a3bfabc97a2584db" dependencies: - babel-helper-define-map "^6.23.0" - babel-helper-function-name "^6.23.0" - babel-helper-optimise-call-expression "^6.23.0" - babel-helper-replace-supers "^6.23.0" + babel-helper-define-map "^6.24.1" + babel-helper-function-name "^6.24.1" + babel-helper-optimise-call-expression "^6.24.1" + babel-helper-replace-supers "^6.24.1" babel-messages "^6.23.0" babel-runtime "^6.22.0" - babel-template "^6.23.0" - babel-traverse "^6.23.0" - babel-types "^6.23.0" + babel-template "^6.24.1" + babel-traverse "^6.24.1" + babel-types "^6.24.1" babel-plugin-transform-es2015-computed-properties@^6.22.0: - version "6.22.0" - resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-computed-properties/-/babel-plugin-transform-es2015-computed-properties-6.22.0.tgz#7c383e9629bba4820c11b0425bdd6290f7f057e7" + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-computed-properties/-/babel-plugin-transform-es2015-computed-properties-6.24.1.tgz#6fe2a8d16895d5634f4cd999b6d3480a308159b3" dependencies: babel-runtime "^6.22.0" - babel-template "^6.22.0" + babel-template "^6.24.1" babel-plugin-transform-es2015-destructuring@^6.19.0, babel-plugin-transform-es2015-destructuring@^6.23.0: version "6.23.0" @@ -646,11 +650,11 @@ babel-plugin-transform-es2015-destructuring@^6.19.0, babel-plugin-transform-es20 babel-runtime "^6.22.0" babel-plugin-transform-es2015-duplicate-keys@^6.22.0: - version "6.22.0" - resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-duplicate-keys/-/babel-plugin-transform-es2015-duplicate-keys-6.22.0.tgz#672397031c21610d72dd2bbb0ba9fb6277e1c36b" + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-duplicate-keys/-/babel-plugin-transform-es2015-duplicate-keys-6.24.1.tgz#73eb3d310ca969e3ef9ec91c53741a6f1576423e" dependencies: babel-runtime "^6.22.0" - babel-types "^6.22.0" + babel-types "^6.24.1" babel-plugin-transform-es2015-for-of@^6.23.0: version "6.23.0" @@ -659,12 +663,12 @@ babel-plugin-transform-es2015-for-of@^6.23.0: babel-runtime "^6.22.0" babel-plugin-transform-es2015-function-name@^6.22.0, babel-plugin-transform-es2015-function-name@^6.9.0: - version "6.22.0" - resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-function-name/-/babel-plugin-transform-es2015-function-name-6.22.0.tgz#f5fcc8b09093f9a23c76ac3d9e392c3ec4b77104" + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-function-name/-/babel-plugin-transform-es2015-function-name-6.24.1.tgz#834c89853bc36b1af0f3a4c5dbaa94fd8eacaa8b" dependencies: - babel-helper-function-name "^6.22.0" + babel-helper-function-name "^6.24.1" babel-runtime "^6.22.0" - babel-types "^6.22.0" + babel-types "^6.24.1" babel-plugin-transform-es2015-literals@^6.22.0: version "6.22.0" @@ -672,63 +676,63 @@ babel-plugin-transform-es2015-literals@^6.22.0: dependencies: babel-runtime "^6.22.0" -babel-plugin-transform-es2015-modules-amd@^6.22.0, babel-plugin-transform-es2015-modules-amd@^6.24.0: - version "6.24.0" - resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-modules-amd/-/babel-plugin-transform-es2015-modules-amd-6.24.0.tgz#a1911fb9b7ec7e05a43a63c5995007557bcf6a2e" +babel-plugin-transform-es2015-modules-amd@^6.22.0, babel-plugin-transform-es2015-modules-amd@^6.24.1: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-modules-amd/-/babel-plugin-transform-es2015-modules-amd-6.24.1.tgz#3b3e54017239842d6d19c3011c4bd2f00a00d154" dependencies: - babel-plugin-transform-es2015-modules-commonjs "^6.24.0" + babel-plugin-transform-es2015-modules-commonjs "^6.24.1" babel-runtime "^6.22.0" - babel-template "^6.22.0" + babel-template "^6.24.1" -babel-plugin-transform-es2015-modules-commonjs@^6.18.0, babel-plugin-transform-es2015-modules-commonjs@^6.23.0, babel-plugin-transform-es2015-modules-commonjs@^6.24.0: - version "6.24.0" - resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-modules-commonjs/-/babel-plugin-transform-es2015-modules-commonjs-6.24.0.tgz#e921aefb72c2cc26cb03d107626156413222134f" +babel-plugin-transform-es2015-modules-commonjs@^6.18.0, babel-plugin-transform-es2015-modules-commonjs@^6.23.0, babel-plugin-transform-es2015-modules-commonjs@^6.24.1: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-modules-commonjs/-/babel-plugin-transform-es2015-modules-commonjs-6.24.1.tgz#d3e310b40ef664a36622200097c6d440298f2bfe" dependencies: - babel-plugin-transform-strict-mode "^6.22.0" + babel-plugin-transform-strict-mode "^6.24.1" babel-runtime "^6.22.0" - babel-template "^6.23.0" - babel-types "^6.23.0" + babel-template "^6.24.1" + babel-types "^6.24.1" babel-plugin-transform-es2015-modules-systemjs@^6.23.0: - version "6.23.0" - resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-modules-systemjs/-/babel-plugin-transform-es2015-modules-systemjs-6.23.0.tgz#ae3469227ffac39b0310d90fec73bfdc4f6317b0" + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-modules-systemjs/-/babel-plugin-transform-es2015-modules-systemjs-6.24.1.tgz#ff89a142b9119a906195f5f106ecf305d9407d23" dependencies: - babel-helper-hoist-variables "^6.22.0" + babel-helper-hoist-variables "^6.24.1" babel-runtime "^6.22.0" - babel-template "^6.23.0" + babel-template "^6.24.1" babel-plugin-transform-es2015-modules-umd@^6.23.0: - version "6.24.0" - resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-modules-umd/-/babel-plugin-transform-es2015-modules-umd-6.24.0.tgz#fd5fa63521cae8d273927c3958afd7c067733450" + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-modules-umd/-/babel-plugin-transform-es2015-modules-umd-6.24.1.tgz#ac997e6285cd18ed6176adb607d602344ad38468" dependencies: - babel-plugin-transform-es2015-modules-amd "^6.24.0" + babel-plugin-transform-es2015-modules-amd "^6.24.1" babel-runtime "^6.22.0" - babel-template "^6.23.0" + babel-template "^6.24.1" babel-plugin-transform-es2015-object-super@^6.22.0: - version "6.22.0" - resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-object-super/-/babel-plugin-transform-es2015-object-super-6.22.0.tgz#daa60e114a042ea769dd53fe528fc82311eb98fc" + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-object-super/-/babel-plugin-transform-es2015-object-super-6.24.1.tgz#24cef69ae21cb83a7f8603dad021f572eb278f8d" dependencies: - babel-helper-replace-supers "^6.22.0" + babel-helper-replace-supers "^6.24.1" babel-runtime "^6.22.0" babel-plugin-transform-es2015-parameters@^6.21.0, babel-plugin-transform-es2015-parameters@^6.23.0: - version "6.23.0" - resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-parameters/-/babel-plugin-transform-es2015-parameters-6.23.0.tgz#3a2aabb70c8af945d5ce386f1a4250625a83ae3b" + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-parameters/-/babel-plugin-transform-es2015-parameters-6.24.1.tgz#57ac351ab49caf14a97cd13b09f66fdf0a625f2b" dependencies: - babel-helper-call-delegate "^6.22.0" - babel-helper-get-function-arity "^6.22.0" + babel-helper-call-delegate "^6.24.1" + babel-helper-get-function-arity "^6.24.1" babel-runtime "^6.22.0" - babel-template "^6.23.0" - babel-traverse "^6.23.0" - babel-types "^6.23.0" + babel-template "^6.24.1" + babel-traverse "^6.24.1" + babel-types "^6.24.1" babel-plugin-transform-es2015-shorthand-properties@^6.22.0: - version "6.22.0" - resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-shorthand-properties/-/babel-plugin-transform-es2015-shorthand-properties-6.22.0.tgz#8ba776e0affaa60bff21e921403b8a652a2ff723" + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-shorthand-properties/-/babel-plugin-transform-es2015-shorthand-properties-6.24.1.tgz#24f875d6721c87661bbd99a4622e51f14de38aa0" dependencies: babel-runtime "^6.22.0" - babel-types "^6.22.0" + babel-types "^6.24.1" babel-plugin-transform-es2015-spread@^6.22.0, babel-plugin-transform-es2015-spread@^6.8.0: version "6.22.0" @@ -737,12 +741,12 @@ babel-plugin-transform-es2015-spread@^6.22.0, babel-plugin-transform-es2015-spre babel-runtime "^6.22.0" babel-plugin-transform-es2015-sticky-regex@^6.22.0, babel-plugin-transform-es2015-sticky-regex@^6.8.0: - version "6.22.0" - resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-sticky-regex/-/babel-plugin-transform-es2015-sticky-regex-6.22.0.tgz#ab316829e866ee3f4b9eb96939757d19a5bc4593" + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-sticky-regex/-/babel-plugin-transform-es2015-sticky-regex-6.24.1.tgz#00c1cdb1aca71112cdf0cf6126c2ed6b457ccdbc" dependencies: - babel-helper-regex "^6.22.0" + babel-helper-regex "^6.24.1" babel-runtime "^6.22.0" - babel-types "^6.22.0" + babel-types "^6.24.1" babel-plugin-transform-es2015-template-literals@^6.22.0: version "6.22.0" @@ -757,18 +761,18 @@ babel-plugin-transform-es2015-typeof-symbol@^6.23.0: babel-runtime "^6.22.0" babel-plugin-transform-es2015-unicode-regex@^6.11.0, babel-plugin-transform-es2015-unicode-regex@^6.22.0: - version "6.22.0" - resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-unicode-regex/-/babel-plugin-transform-es2015-unicode-regex-6.22.0.tgz#8d9cc27e7ee1decfe65454fb986452a04a613d20" + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-unicode-regex/-/babel-plugin-transform-es2015-unicode-regex-6.24.1.tgz#d38b12f42ea7323f729387f18a7c5ae1faeb35e9" dependencies: - babel-helper-regex "^6.22.0" + babel-helper-regex "^6.24.1" babel-runtime "^6.22.0" regexpu-core "^2.0.0" babel-plugin-transform-exponentiation-operator@^6.22.0, babel-plugin-transform-exponentiation-operator@^6.8.0: - version "6.22.0" - resolved "https://registry.yarnpkg.com/babel-plugin-transform-exponentiation-operator/-/babel-plugin-transform-exponentiation-operator-6.22.0.tgz#d57c8335281918e54ef053118ce6eb108468084d" + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-exponentiation-operator/-/babel-plugin-transform-exponentiation-operator-6.24.1.tgz#2ab0c9c7f3098fa48907772bb813fe41e8de3a0e" dependencies: - babel-helper-builder-binary-assignment-operator-visitor "^6.22.0" + babel-helper-builder-binary-assignment-operator-visitor "^6.24.1" babel-plugin-syntax-exponentiation-operator "^6.8.0" babel-runtime "^6.22.0" @@ -777,61 +781,59 @@ babel-plugin-transform-inline-consecutive-adds@^0.0.2: resolved "https://registry.yarnpkg.com/babel-plugin-transform-inline-consecutive-adds/-/babel-plugin-transform-inline-consecutive-adds-0.0.2.tgz#a58fcecfc09c08fbf9373a5a3e70746c03d01fc1" babel-plugin-transform-member-expression-literals@^6.8.1: - version "6.8.1" - resolved "https://registry.yarnpkg.com/babel-plugin-transform-member-expression-literals/-/babel-plugin-transform-member-expression-literals-6.8.1.tgz#60b78cb2b814ac71dd6104ef51c496c62e877337" + version "6.8.4" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-member-expression-literals/-/babel-plugin-transform-member-expression-literals-6.8.4.tgz#05679bc40596b91293401959aa1620ab1b2be437" babel-plugin-transform-merge-sibling-variables@^6.8.2: - version "6.8.2" - resolved "https://registry.yarnpkg.com/babel-plugin-transform-merge-sibling-variables/-/babel-plugin-transform-merge-sibling-variables-6.8.2.tgz#498acd07481ab340c1bad8b726c2fad1b8f644e5" + version "6.8.5" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-merge-sibling-variables/-/babel-plugin-transform-merge-sibling-variables-6.8.5.tgz#03abdf107c61241913eb268ddede6d5bc541862c" babel-plugin-transform-minify-booleans@^6.8.0: - version "6.8.0" - resolved "https://registry.yarnpkg.com/babel-plugin-transform-minify-booleans/-/babel-plugin-transform-minify-booleans-6.8.0.tgz#b1a48864a727847696b84eae36fa4d085a54b42b" - dependencies: - babel-runtime "^6.0.0" + version "6.8.2" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-minify-booleans/-/babel-plugin-transform-minify-booleans-6.8.2.tgz#8451579f706e702c1e1ab2756de5c8ea369cf07c" babel-plugin-transform-property-literals@^6.8.1: - version "6.8.1" - resolved "https://registry.yarnpkg.com/babel-plugin-transform-property-literals/-/babel-plugin-transform-property-literals-6.8.1.tgz#05ed01f6024820b18f1d0495c80fe287176bccd9" + version "6.8.4" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-property-literals/-/babel-plugin-transform-property-literals-6.8.4.tgz#6ad311110b80a192a56efb5ddf4fe3ca6f7a61da" + dependencies: + esutils "^2.0.2" babel-plugin-transform-regenerator@^6.22.0: - version "6.22.0" - resolved "https://registry.yarnpkg.com/babel-plugin-transform-regenerator/-/babel-plugin-transform-regenerator-6.22.0.tgz#65740593a319c44522157538d690b84094617ea6" + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-regenerator/-/babel-plugin-transform-regenerator-6.24.1.tgz#b8da305ad43c3c99b4848e4fe4037b770d23c418" dependencies: - regenerator-transform "0.9.8" + regenerator-transform "0.9.11" babel-plugin-transform-regexp-constructors@^0.0.6: version "0.0.6" resolved "https://registry.yarnpkg.com/babel-plugin-transform-regexp-constructors/-/babel-plugin-transform-regexp-constructors-0.0.6.tgz#0d92607f0d26268296980cb7c1dea5f2dd3e1e20" babel-plugin-transform-remove-console@^6.8.1: - version "6.8.1" - resolved "https://registry.yarnpkg.com/babel-plugin-transform-remove-console/-/babel-plugin-transform-remove-console-6.8.1.tgz#38f6a6ca1581e76b75fc2c6fdcf909deadee7d6a" + version "6.8.4" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-remove-console/-/babel-plugin-transform-remove-console-6.8.4.tgz#41fddac19a729a4c3dd7ef2964eac07b096f9a8f" babel-plugin-transform-remove-debugger@^6.8.1: - version "6.8.1" - resolved "https://registry.yarnpkg.com/babel-plugin-transform-remove-debugger/-/babel-plugin-transform-remove-debugger-6.8.1.tgz#aabd0be107f8299094defe8e1ba8ccf4b114d07f" + version "6.8.4" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-remove-debugger/-/babel-plugin-transform-remove-debugger-6.8.4.tgz#f85704a08adaa71b55d77005b5b94e9b9df21f6e" babel-plugin-transform-remove-undefined@^0.0.5: version "0.0.5" resolved "https://registry.yarnpkg.com/babel-plugin-transform-remove-undefined/-/babel-plugin-transform-remove-undefined-0.0.5.tgz#12ef11805e06e861dd2eb0c7cc041d2184b8f410" babel-plugin-transform-simplify-comparison-operators@^6.8.1: - version "6.8.1" - resolved "https://registry.yarnpkg.com/babel-plugin-transform-simplify-comparison-operators/-/babel-plugin-transform-simplify-comparison-operators-6.8.1.tgz#a307088e0d1c728081777fba568f4107396ab25c" + version "6.8.4" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-simplify-comparison-operators/-/babel-plugin-transform-simplify-comparison-operators-6.8.4.tgz#2aa24a262d664c8cb3e125a306c798d7a2de08d5" -babel-plugin-transform-strict-mode@^6.22.0: - version "6.22.0" - resolved "https://registry.yarnpkg.com/babel-plugin-transform-strict-mode/-/babel-plugin-transform-strict-mode-6.22.0.tgz#e008df01340fdc87e959da65991b7e05970c8c7c" +babel-plugin-transform-strict-mode@^6.24.1: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-strict-mode/-/babel-plugin-transform-strict-mode-6.24.1.tgz#d5faf7aa578a65bbe591cf5edae04a0c67020758" dependencies: babel-runtime "^6.22.0" - babel-types "^6.22.0" + babel-types "^6.24.1" babel-plugin-transform-undefined-to-void@^6.8.0: - version "6.8.0" - resolved "https://registry.yarnpkg.com/babel-plugin-transform-undefined-to-void/-/babel-plugin-transform-undefined-to-void-6.8.0.tgz#bc5b6b4908d3b1262170e67cb3963903ddce167e" - dependencies: - babel-runtime "^6.0.0" + version "6.8.2" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-undefined-to-void/-/babel-plugin-transform-undefined-to-void-6.8.2.tgz#fe2b1d294eb05e87524eb93724dea6e2c3d66fa1" babel-preset-babili@^0.0.12: version "0.0.12" @@ -862,8 +864,8 @@ babel-preset-babili@^0.0.12: lodash.isplainobject "^4.0.6" babel-preset-env@^1.3.2: - version "1.3.2" - resolved "https://registry.yarnpkg.com/babel-preset-env/-/babel-preset-env-1.3.2.tgz#08eabd2bf810c3678069f7e052323419f1448749" + version "1.5.2" + resolved "https://registry.yarnpkg.com/babel-preset-env/-/babel-preset-env-1.5.2.tgz#cd4ae90a6e94b709f97374b33e5f8b983556adef" dependencies: babel-plugin-check-es2015-constants "^6.22.0" babel-plugin-syntax-trailing-function-commas "^6.22.0" @@ -892,14 +894,15 @@ babel-preset-env@^1.3.2: babel-plugin-transform-es2015-unicode-regex "^6.22.0" babel-plugin-transform-exponentiation-operator "^6.22.0" babel-plugin-transform-regenerator "^6.22.0" - browserslist "^1.4.0" + browserslist "^2.1.2" invariant "^2.2.2" + semver "^5.3.0" -babel-register@^6.24.0: - version "6.24.0" - resolved "https://registry.yarnpkg.com/babel-register/-/babel-register-6.24.0.tgz#5e89f8463ba9970356d02eb07dabe3308b080cfd" +babel-register@^6.24.0, babel-register@^6.24.1: + version "6.24.1" + resolved "https://registry.yarnpkg.com/babel-register/-/babel-register-6.24.1.tgz#7e10e13a2f71065bdfad5a1787ba45bca6ded75f" dependencies: - babel-core "^6.24.0" + babel-core "^6.24.1" babel-runtime "^6.22.0" core-js "^2.4.0" home-or-tmp "^2.0.0" @@ -907,53 +910,53 @@ babel-register@^6.24.0: mkdirp "^0.5.1" source-map-support "^0.4.2" -babel-runtime@^6.0.0, babel-runtime@^6.18.0, babel-runtime@^6.22.0: +babel-runtime@^6.18.0, babel-runtime@^6.22.0: version "6.23.0" resolved "https://registry.yarnpkg.com/babel-runtime/-/babel-runtime-6.23.0.tgz#0a9489f144de70efb3ce4300accdb329e2fc543b" dependencies: core-js "^2.4.0" regenerator-runtime "^0.10.0" -babel-template@^6.16.0, babel-template@^6.22.0, babel-template@^6.23.0: - version "6.23.0" - resolved "https://registry.yarnpkg.com/babel-template/-/babel-template-6.23.0.tgz#04d4f270adbb3aa704a8143ae26faa529238e638" +babel-template@^6.16.0, babel-template@^6.24.1, babel-template@^6.25.0: + version "6.25.0" + resolved "https://registry.yarnpkg.com/babel-template/-/babel-template-6.25.0.tgz#665241166b7c2aa4c619d71e192969552b10c071" dependencies: babel-runtime "^6.22.0" - babel-traverse "^6.23.0" - babel-types "^6.23.0" - babylon "^6.11.0" + babel-traverse "^6.25.0" + babel-types "^6.25.0" + babylon "^6.17.2" lodash "^4.2.0" -babel-traverse@^6.18.0, babel-traverse@^6.22.0, babel-traverse@^6.23.0, babel-traverse@^6.23.1: - version "6.23.1" - resolved "https://registry.yarnpkg.com/babel-traverse/-/babel-traverse-6.23.1.tgz#d3cb59010ecd06a97d81310065f966b699e14f48" +babel-traverse@^6.18.0, babel-traverse@^6.24.1, babel-traverse@^6.25.0: + version "6.25.0" + resolved "https://registry.yarnpkg.com/babel-traverse/-/babel-traverse-6.25.0.tgz#2257497e2fcd19b89edc13c4c91381f9512496f1" dependencies: babel-code-frame "^6.22.0" babel-messages "^6.23.0" babel-runtime "^6.22.0" - babel-types "^6.23.0" - babylon "^6.15.0" + babel-types "^6.25.0" + babylon "^6.17.2" debug "^2.2.0" globals "^9.0.0" invariant "^2.2.0" lodash "^4.2.0" -babel-types@^6.18.0, babel-types@^6.19.0, babel-types@^6.22.0, babel-types@^6.23.0: - version "6.23.0" - resolved "https://registry.yarnpkg.com/babel-types/-/babel-types-6.23.0.tgz#bb17179d7538bad38cd0c9e115d340f77e7e9acf" +babel-types@^6.18.0, babel-types@^6.19.0, babel-types@^6.24.1, babel-types@^6.25.0: + version "6.25.0" + resolved "https://registry.yarnpkg.com/babel-types/-/babel-types-6.25.0.tgz#70afb248d5660e5d18f811d91c8303b54134a18e" dependencies: babel-runtime "^6.22.0" esutils "^2.0.2" lodash "^4.2.0" to-fast-properties "^1.0.1" -babylon@^6.1.0, babylon@^6.11.0, babylon@^6.13.0, babylon@^6.15.0: - version "6.16.1" - resolved "https://registry.yarnpkg.com/babylon/-/babylon-6.16.1.tgz#30c5a22f481978a9e7f8cdfdf496b11d94b404d3" +babylon@^6.1.0, babylon@^6.13.0, babylon@^6.17.2: + version "6.17.4" + resolved "https://registry.yarnpkg.com/babylon/-/babylon-6.17.4.tgz#3e8b7402b88d22c3423e137a1577883b15ff869a" -balanced-match@^0.4.1: - version "0.4.2" - resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-0.4.2.tgz#cb3f3e3c732dc0f01ee70b403f302e61d7709838" +balanced-match@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.0.tgz#89b4d199ab2bee49de164ea02b89ce462d71b767" bcrypt-pbkdf@^1.0.0: version "1.0.1" @@ -993,11 +996,11 @@ boxen@^1.0.0: term-size "^0.1.0" widest-line "^1.0.0" -brace-expansion@^1.0.0: - version "1.1.6" - resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.6.tgz#7197d7eaa9b87e648390ea61fc66c84427420df9" +brace-expansion@^1.1.7: + version "1.1.8" + resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.8.tgz#c07b211c7c952ec1f8efd51a77ef0d1d3990a292" dependencies: - balanced-match "^0.4.1" + balanced-match "^1.0.0" concat-map "0.0.1" braces@^1.8.2: @@ -1014,21 +1017,17 @@ browser-resolve@^1.11.0: dependencies: resolve "1.1.7" -browserslist@^1.4.0: - version "1.7.7" - resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-1.7.7.tgz#0bd76704258be829b2398bb50e4b62d1a166b0b9" +browserslist@^2.1.2: + version "2.1.5" + resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-2.1.5.tgz#e882550df3d1cd6d481c1a3e0038f2baf13a4711" dependencies: - caniuse-db "^1.0.30000639" - electron-to-chromium "^1.2.7" + caniuse-lite "^1.0.30000684" + electron-to-chromium "^1.3.14" buf-compare@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/buf-compare/-/buf-compare-1.0.1.tgz#fef28da8b8113a0a0db4430b0b6467b69730b34a" -buffer-shims@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/buffer-shims/-/buffer-shims-1.0.0.tgz#9978ce317388c649ad8793028c3477ef044a8b51" - builtin-modules@^1.0.0, builtin-modules@^1.1.0, builtin-modules@^1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/builtin-modules/-/builtin-modules-1.1.1.tgz#270f076c5a72c02f5b65a47df94c5fe3a278892f" @@ -1087,9 +1086,9 @@ camelcase@^4.0.0: version "4.1.0" resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-4.1.0.tgz#d545635be1e33c542649c69173e5de6acfae34dd" -caniuse-db@^1.0.30000639: - version "1.0.30000646" - resolved "https://registry.yarnpkg.com/caniuse-db/-/caniuse-db-1.0.30000646.tgz#c724b90d61df24286e015fc528d062073c00def4" +caniuse-lite@^1.0.30000684: + version "1.0.30000693" + resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30000693.tgz#c9c6298697c71fdf6cb13eefe8aa93926f2f8613" capture-stack-trace@^1.0.0: version "1.0.0" @@ -1356,17 +1355,11 @@ debug-log@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/debug-log/-/debug-log-1.0.1.tgz#2307632d4c04382b8df8a32f70b895046d52745f" -debug@2.2.0: - version "2.2.0" - resolved "https://registry.yarnpkg.com/debug/-/debug-2.2.0.tgz#f87057e995b1a1f6ae6a4960664137bc56f039da" +debug@^2.1.1, debug@^2.2.0, debug@^2.6.3, debug@^2.6.8: + version "2.6.8" + resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.8.tgz#e731531ca2ede27d188222427da17821d68ff4fc" dependencies: - ms "0.7.1" - -debug@^2.1.1, debug@^2.2.0, debug@^2.6.3: - version "2.6.3" - resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.3.tgz#0f7eb8c30965ec08c72accfa0130c8b79984141d" - dependencies: - ms "0.7.2" + ms "2.0.0" decamelize@^1.0.0, decamelize@^1.1.1, decamelize@^1.1.2: version "1.2.0" @@ -1458,13 +1451,13 @@ ecc-jsbn@~0.1.1: dependencies: jsbn "~0.1.0" -electron-to-chromium@^1.2.7: - version "1.3.2" - resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.3.2.tgz#b8ce5c93b308db0e92f6d0435c46ddec8f6363ab" +electron-to-chromium@^1.3.14: + version "1.3.14" + resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.3.14.tgz#64af0f9efd3c3c6acd57d71f83b49ca7ee9c4b43" empower-core@^0.6.1: - version "0.6.1" - resolved "https://registry.yarnpkg.com/empower-core/-/empower-core-0.6.1.tgz#6c187f502fcef7554d57933396aac655483772b1" + version "0.6.2" + resolved "https://registry.yarnpkg.com/empower-core/-/empower-core-0.6.2.tgz#5adef566088e31fba80ba0a36df47d7094169144" dependencies: call-signature "0.0.2" core-js "^2.0.0" @@ -1473,9 +1466,9 @@ equal-length@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/equal-length/-/equal-length-1.0.1.tgz#21ca112d48ab24b4e1e7ffc0e5339d31fdfc274c" -erlang-types@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/erlang-types/-/erlang-types-1.0.0.tgz#e555bd091667498a01d340d18203231dc96d962f" +erlang-types@^1.0.0, erlang-types@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/erlang-types/-/erlang-types-1.0.1.tgz#943a57a9324e0d0edc0273690a8c702686d9b780" error-ex@^1.2.0: version "1.3.1" @@ -1484,8 +1477,8 @@ error-ex@^1.2.0: is-arrayish "^0.2.1" es5-ext@^0.10.14, es5-ext@^0.10.9, es5-ext@~0.10.14: - version "0.10.15" - resolved "https://registry.yarnpkg.com/es5-ext/-/es5-ext-0.10.15.tgz#c330a5934c1ee21284a7c081a86e5fd937c91ea6" + version "0.10.23" + resolved "https://registry.yarnpkg.com/es5-ext/-/es5-ext-0.10.23.tgz#7578b51be974207a5487821b56538c224e4e7b38" dependencies: es6-iterator "2" es6-symbol "~3.1" @@ -1553,8 +1546,8 @@ escope@^3.6.0: estraverse "^4.1.1" eslint-config-airbnb-base@^11.1.0: - version "11.1.2" - resolved "https://registry.yarnpkg.com/eslint-config-airbnb-base/-/eslint-config-airbnb-base-11.1.2.tgz#259209a7678bf693e31cbe8f953f206b6aa7ccc3" + version "11.2.0" + resolved "https://registry.yarnpkg.com/eslint-config-airbnb-base/-/eslint-config-airbnb-base-11.2.0.tgz#19a9dc4481a26f70904545ec040116876018f853" eslint-import-resolver-node@^0.2.0: version "0.2.3" @@ -1565,26 +1558,26 @@ eslint-import-resolver-node@^0.2.0: resolve "^1.1.6" eslint-module-utils@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/eslint-module-utils/-/eslint-module-utils-2.0.0.tgz#a6f8c21d901358759cdc35dbac1982ae1ee58bce" + version "2.1.1" + resolved "https://registry.yarnpkg.com/eslint-module-utils/-/eslint-module-utils-2.1.1.tgz#abaec824177613b8a95b299639e1b6facf473449" dependencies: - debug "2.2.0" + debug "^2.6.8" pkg-dir "^1.0.0" eslint-plugin-import@^2.2.0: - version "2.2.0" - resolved "https://registry.yarnpkg.com/eslint-plugin-import/-/eslint-plugin-import-2.2.0.tgz#72ba306fad305d67c4816348a4699a4229ac8b4e" + version "2.5.0" + resolved "https://registry.yarnpkg.com/eslint-plugin-import/-/eslint-plugin-import-2.5.0.tgz#293b5ea7910a901a05a47ccdd7546e611725406c" dependencies: builtin-modules "^1.1.1" contains-path "^0.1.0" - debug "^2.2.0" + debug "^2.6.8" doctrine "1.5.0" eslint-import-resolver-node "^0.2.0" eslint-module-utils "^2.0.0" has "^1.0.1" lodash.cond "^4.3.0" minimatch "^3.0.3" - pkg-up "^1.0.0" + read-pkg-up "^2.0.0" eslint@^3.15.0: version "3.19.0" @@ -1636,8 +1629,8 @@ espower-location-detector@^1.0.0: xtend "^4.0.0" espree@^3.4.0: - version "3.4.1" - resolved "https://registry.yarnpkg.com/espree/-/espree-3.4.1.tgz#28a83ab4aaed71ed8fe0f5efe61b76a05c13c4d2" + version "3.4.3" + resolved "https://registry.yarnpkg.com/espree/-/espree-3.4.3.tgz#2910b5ccd49ce893c2ffffaab4fd8b3a31b82374" dependencies: acorn "^5.0.1" acorn-jsx "^3.0.0" @@ -1659,20 +1652,16 @@ esquery@^1.0.0: estraverse "^4.0.0" esrecurse@^4.1.0: - version "4.1.0" - resolved "https://registry.yarnpkg.com/esrecurse/-/esrecurse-4.1.0.tgz#4713b6536adf7f2ac4f327d559e7756bff648220" + version "4.2.0" + resolved "https://registry.yarnpkg.com/esrecurse/-/esrecurse-4.2.0.tgz#fa9568d98d3823f9a41d91e902dcab9ea6e5b163" dependencies: - estraverse "~4.1.0" + estraverse "^4.1.0" object-assign "^4.0.1" -estraverse@^4.0.0, estraverse@^4.1.1, estraverse@^4.2.0: +estraverse@^4.0.0, estraverse@^4.1.0, estraverse@^4.1.1, estraverse@^4.2.0: version "4.2.0" resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-4.2.0.tgz#0dee3fed31fcd469618ce7342099fc1afa0bdb13" -estraverse@~4.1.0: - version "4.1.1" - resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-4.1.1.tgz#f6caca728933a850ef90661d0e17982ba47111a2" - estree-walker@^0.2.1: version "0.2.1" resolved "https://registry.yarnpkg.com/estree-walker/-/estree-walker-0.2.1.tgz#bdafe8095383d8414d5dc2ecf4c9173b6db9412e" @@ -1794,7 +1783,7 @@ find-up@^1.0.0, find-up@^1.1.2: path-exists "^2.0.0" pinkie-promise "^2.0.0" -find-up@^2.0.0: +find-up@^2.0.0, find-up@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/find-up/-/find-up-2.1.0.tgz#45d1b7e506c717ddd482775a2b77920a3c0c57a7" dependencies: @@ -1853,11 +1842,11 @@ fs.realpath@^1.0.0: resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f" fsevents@^1.0.0: - version "1.1.1" - resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-1.1.1.tgz#f19fd28f43eeaf761680e519a203c4d0b3d31aff" + version "1.1.2" + resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-1.1.2.tgz#3282b713fb3ad80ede0e9fcf4611b5aa6fc033f4" dependencies: nan "^2.3.0" - node-pre-gyp "^0.6.29" + node-pre-gyp "^0.6.36" fstream-ignore@^1.0.5: version "1.0.5" @@ -1946,19 +1935,19 @@ glob-parent@^2.0.0: is-glob "^2.0.0" glob@^7.0.0, glob@^7.0.3, glob@^7.0.5, glob@^7.0.6: - version "7.1.1" - resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.1.tgz#805211df04faaf1c63a3600306cdf5ade50b2ec8" + version "7.1.2" + resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.2.tgz#c19c9df9a028702d678612384a6552404c636d15" dependencies: fs.realpath "^1.0.0" inflight "^1.0.4" inherits "2" - minimatch "^3.0.2" + minimatch "^3.0.4" once "^1.3.0" path-is-absolute "^1.0.0" globals@^9.0.0, globals@^9.14.0: - version "9.17.0" - resolved "https://registry.yarnpkg.com/globals/-/globals-9.17.0.tgz#0c0ca696d9b9bb694d2e5470bd37777caad50286" + version "9.18.0" + resolved "https://registry.yarnpkg.com/globals/-/globals-9.18.0.tgz#aa3896b3e69b487f17e31ed2143d69a8e30c2d8a" globby@^5.0.0: version "5.0.0" @@ -2087,8 +2076,8 @@ http-signature@~1.1.0: sshpk "^1.7.0" hullabaloo-config-manager@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/hullabaloo-config-manager/-/hullabaloo-config-manager-1.0.1.tgz#c72be7ba249a67c99b6ba3eb1f55837fa01acd8f" + version "1.1.1" + resolved "https://registry.yarnpkg.com/hullabaloo-config-manager/-/hullabaloo-config-manager-1.1.1.tgz#1d9117813129ad035fd9e8477eaf066911269fe3" dependencies: dot-prop "^4.1.0" es6-error "^4.0.2" @@ -2101,16 +2090,21 @@ hullabaloo-config-manager@^1.0.0: lodash.merge "^4.6.0" md5-hex "^2.0.0" package-hash "^2.0.0" - pkg-dir "^1.0.0" - resolve-from "^2.0.0" + pkg-dir "^2.0.0" + resolve-from "^3.0.0" + safe-buffer "^5.0.1" ignore-by-default@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/ignore-by-default/-/ignore-by-default-1.0.1.tgz#48ca6d72f6c6a3af00a9ad4ae6876be3889e2b09" ignore@^3.2.0: - version "3.2.6" - resolved "https://registry.yarnpkg.com/ignore/-/ignore-3.2.6.tgz#26e8da0644be0bb4cb39516f6c79f0e0f4ffe48c" + version "3.3.3" + resolved "https://registry.yarnpkg.com/ignore/-/ignore-3.3.3.tgz#432352e57accd87ab3110e82d3fea0e47812156d" + +import-lazy@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/import-lazy/-/import-lazy-2.1.0.tgz#05698e3d45c88e8d7e9d92cb0584e77f096f3e43" imurmurhash@^0.1.4: version "0.1.4" @@ -2133,7 +2127,7 @@ inflight@^1.0.4: once "^1.3.0" wrappy "1" -inherits@2, inherits@^2.0.1, inherits@^2.0.3, inherits@~2.0.0, inherits@~2.0.1: +inherits@2, inherits@^2.0.1, inherits@^2.0.3, inherits@~2.0.0, inherits@~2.0.3: version "2.0.3" resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.3.tgz#633c2c83e3da42a502f52466022480f4208261de" @@ -2164,8 +2158,8 @@ inquirer@^0.12.0: through "^2.3.6" interpret@^1.0.0: - version "1.0.2" - resolved "https://registry.yarnpkg.com/interpret/-/interpret-1.0.2.tgz#f4f623f0bb7122f15f5717c8e254b8161b5c5b2d" + version "1.0.3" + resolved "https://registry.yarnpkg.com/interpret/-/interpret-1.0.3.tgz#cbc35c62eeee73f19ab7b10a801511401afc0f90" invariant@^2.2.0, invariant@^2.2.2: version "2.2.2" @@ -2208,8 +2202,8 @@ is-ci@^1.0.7: ci-info "^1.0.0" is-dotfile@^1.0.0: - version "1.0.2" - resolved "https://registry.yarnpkg.com/is-dotfile/-/is-dotfile-1.0.2.tgz#2c132383f39199f8edc268ca01b9b007d205cc4d" + version "1.0.3" + resolved "https://registry.yarnpkg.com/is-dotfile/-/is-dotfile-1.0.3.tgz#a6a2f32ffd2dfb04f5ca25ecd0f6b83cf798a1e1" is-equal-shallow@^0.1.3: version "0.1.3" @@ -2268,12 +2262,18 @@ is-npm@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/is-npm/-/is-npm-1.0.0.tgz#f2fb63a65e4905b406c86072765a1a4dc793b9f4" -is-number@^2.0.2, is-number@^2.1.0: +is-number@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/is-number/-/is-number-2.1.0.tgz#01fcbbb393463a548f2f466cce16dece49db908f" dependencies: kind-of "^3.0.2" +is-number@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/is-number/-/is-number-3.0.0.tgz#24fd6201a4782cf50561c810276afc7d12d71195" + dependencies: + kind-of "^3.0.2" + is-obj@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/is-obj/-/is-obj-1.0.1.tgz#3e4729ac1f5fde025cd7d83a896dab9f4f67db0f" @@ -2480,19 +2480,13 @@ jest-validate@^19.0.2: leven "^2.0.0" pretty-format "^19.0.0" -jodid25519@^1.0.0: - version "1.0.2" - resolved "https://registry.yarnpkg.com/jodid25519/-/jodid25519-1.0.2.tgz#06d4912255093419477d425633606e0e90782967" - dependencies: - jsbn "~0.1.0" - js-tokens@^3.0.0: version "3.0.1" resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-3.0.1.tgz#08e9f132484a2c45a30907e9dc4d5567b7f114d7" js-yaml@^3.5.1, js-yaml@^3.8.2: - version "3.8.2" - resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.8.2.tgz#02d3e2c0f6beab20248d412c352203827d786721" + version "3.8.4" + resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.8.4.tgz#520b4564f86573ba96662af85a8cafa7b4b5a6f6" dependencies: argparse "^1.0.7" esprima "^3.1.1" @@ -2506,8 +2500,8 @@ jsesc@^1.3.0: resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-1.3.0.tgz#46c3fec8c1892b12b0833db9bc7622176dbab34b" jsesc@^2.4.0: - version "2.4.0" - resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-2.4.0.tgz#8568d223ff69c0b5e081b4f8edf5a23d978c9867" + version "2.5.1" + resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-2.5.1.tgz#e421a2a8e20d6b0819df28908f782526b96dd1fe" jsesc@~0.5.0: version "0.5.0" @@ -2554,6 +2548,12 @@ kind-of@^3.0.2: dependencies: is-buffer "^1.1.5" +kind-of@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-4.0.0.tgz#20813df3d712928b207378691a45066fae72dd57" + dependencies: + is-buffer "^1.1.5" + last-line-stream@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/last-line-stream/-/last-line-stream-1.0.0.tgz#d1b64d69f86ff24af2d04883a2ceee14520a5600" @@ -2570,10 +2570,6 @@ lazy-cache@^1.0.3: version "1.0.4" resolved "https://registry.yarnpkg.com/lazy-cache/-/lazy-cache-1.0.4.tgz#a1d78fc3a50474cb80845d3b3b6e1da49a446e8e" -lazy-req@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/lazy-req/-/lazy-req-2.0.0.tgz#c9450a363ecdda2e6f0c70132ad4f37f8f06f2b4" - lcid@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/lcid/-/lcid-1.0.0.tgz#308accafa0bc483a3867b4b6f2b9506251d1b835" @@ -2691,11 +2687,11 @@ lowercase-keys@^1.0.0: resolved "https://registry.yarnpkg.com/lowercase-keys/-/lowercase-keys-1.0.0.tgz#4e3366b39e7f5457e35f1324bdf6f88d0bfc7306" lru-cache@^4.0.0, lru-cache@^4.0.1: - version "4.0.2" - resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-4.0.2.tgz#1d17679c069cda5d040991a09dbc2c0db377e55e" + version "4.1.1" + resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-4.1.1.tgz#622e32e82488b49279114a4f9ecf45e7cd6bba55" dependencies: - pseudomap "^1.0.1" - yallist "^2.0.0" + pseudomap "^1.0.2" + yallist "^2.1.2" make-dir@^1.0.0: version "1.0.0" @@ -2745,10 +2741,10 @@ meow@^3.7.0: trim-newlines "^1.0.0" merge-source-map@^1.0.2: - version "1.0.3" - resolved "https://registry.yarnpkg.com/merge-source-map/-/merge-source-map-1.0.3.tgz#da1415f2722a5119db07b14c4f973410863a2abf" + version "1.0.4" + resolved "https://registry.yarnpkg.com/merge-source-map/-/merge-source-map-1.0.4.tgz#a5de46538dae84d4114cc5ea02b4772a6346701f" dependencies: - source-map "^0.5.3" + source-map "^0.5.6" micromatch@^2.1.5, micromatch@^2.3.11: version "2.3.11" @@ -2782,11 +2778,11 @@ mimic-fn@^1.0.0: version "1.1.0" resolved "https://registry.yarnpkg.com/mimic-fn/-/mimic-fn-1.1.0.tgz#e667783d92e89dbd342818b5230b9d62a672ad18" -minimatch@^3.0.0, minimatch@^3.0.2, minimatch@^3.0.3: - version "3.0.3" - resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.0.3.tgz#2a4e4090b96b2db06a9d7df01055a62a77c9b774" +minimatch@^3.0.0, minimatch@^3.0.2, minimatch@^3.0.3, minimatch@^3.0.4: + version "3.0.4" + resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.0.4.tgz#5166e286457f03306064be5497e8dbb0c3d32083" dependencies: - brace-expansion "^1.0.0" + brace-expansion "^1.1.7" minimist@0.0.8, minimist@~0.0.1: version "0.0.8" @@ -2802,13 +2798,13 @@ minimist@^1.1.3, minimist@^1.2.0: dependencies: minimist "0.0.8" -ms@0.7.1: - version "0.7.1" - resolved "https://registry.yarnpkg.com/ms/-/ms-0.7.1.tgz#9cd13c03adbff25b65effde7ce864ee952017098" +ms@2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/ms/-/ms-2.0.0.tgz#5608aeadfc00be6c2901df5f9861788de0d597c8" -ms@0.7.2, ms@^0.7.1: - version "0.7.2" - resolved "https://registry.yarnpkg.com/ms/-/ms-0.7.2.tgz#ae25cf2512b3885a1d95d7f037868d8431124765" +ms@^0.7.1: + version "0.7.3" + resolved "https://registry.yarnpkg.com/ms/-/ms-0.7.3.tgz#708155a5e44e33f5fd0fc53e81d0d40a91be1fff" multimatch@^2.1.0: version "2.1.0" @@ -2831,9 +2827,9 @@ natural-compare@^1.4.0: version "1.4.0" resolved "https://registry.yarnpkg.com/natural-compare/-/natural-compare-1.4.0.tgz#4abebfeed7541f2c27acfb29bdbbd15c8d5ba4f7" -node-pre-gyp@^0.6.29: - version "0.6.34" - resolved "https://registry.yarnpkg.com/node-pre-gyp/-/node-pre-gyp-0.6.34.tgz#94ad1c798a11d7fc67381b50d47f8cc18d9799f7" +node-pre-gyp@^0.6.36: + version "0.6.36" + resolved "https://registry.yarnpkg.com/node-pre-gyp/-/node-pre-gyp-0.6.36.tgz#db604112cb74e0d477554e9b505b17abddfab786" dependencies: mkdirp "^0.5.1" nopt "^4.0.1" @@ -3153,11 +3149,11 @@ pkg-dir@^1.0.0: dependencies: find-up "^1.0.0" -pkg-up@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/pkg-up/-/pkg-up-1.0.0.tgz#3e08fb461525c4421624a33b9f7e6d0af5b05a26" +pkg-dir@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/pkg-dir/-/pkg-dir-2.0.0.tgz#f6d5d1109e19d63edf428e0bd57e12777615334b" dependencies: - find-up "^1.0.0" + find-up "^2.1.0" plur@^1.0.0: version "1.0.0" @@ -3217,7 +3213,7 @@ progress@^1.1.8: version "1.1.8" resolved "https://registry.yarnpkg.com/progress/-/progress-1.1.8.tgz#e260c78f6161cdd9b0e56cc3e0a85de17c7a57be" -pseudomap@^1.0.1: +pseudomap@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/pseudomap/-/pseudomap-1.0.2.tgz#f052a28da70e618917ef0a8ac34c1ae5a68286b3" @@ -3230,11 +3226,11 @@ qs@~6.4.0: resolved "https://registry.yarnpkg.com/qs/-/qs-6.4.0.tgz#13e26d28ad6b0ffaa91312cd3bf708ed351e7233" randomatic@^1.1.3: - version "1.1.6" - resolved "https://registry.yarnpkg.com/randomatic/-/randomatic-1.1.6.tgz#110dcabff397e9dcff7c0789ccc0a49adf1ec5bb" + version "1.1.7" + resolved "https://registry.yarnpkg.com/randomatic/-/randomatic-1.1.7.tgz#c7abe9cc8b87c0baa876b19fde83fd464797e38c" dependencies: - is-number "^2.0.2" - kind-of "^3.0.2" + is-number "^3.0.0" + kind-of "^4.0.0" rc@^1.0.1, rc@^1.1.6, rc@^1.1.7: version "1.2.1" @@ -3276,15 +3272,15 @@ read-pkg@^2.0.0: path-type "^2.0.0" readable-stream@^2.0.2, readable-stream@^2.0.6, readable-stream@^2.1.4, readable-stream@^2.1.5, readable-stream@^2.2.2: - version "2.2.6" - resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.2.6.tgz#8b43aed76e71483938d12a8d46c6cf1a00b1f816" + version "2.3.2" + resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.3.2.tgz#5a04df05e4f57fe3f0dc68fdd11dc5c97c7e6f4d" dependencies: - buffer-shims "^1.0.0" core-util-is "~1.0.0" - inherits "~2.0.1" + inherits "~2.0.3" isarray "~1.0.0" process-nextick-args "~1.0.6" - string_decoder "~0.10.x" + safe-buffer "~5.1.0" + string_decoder "~1.0.0" util-deprecate "~1.0.1" readdirp@^2.0.0: @@ -3322,12 +3318,12 @@ regenerate@^1.2.1: resolved "https://registry.yarnpkg.com/regenerate/-/regenerate-1.3.2.tgz#d1941c67bad437e1be76433add5b385f95b19260" regenerator-runtime@^0.10.0: - version "0.10.3" - resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.10.3.tgz#8c4367a904b51ea62a908ac310bf99ff90a82a3e" + version "0.10.5" + resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.10.5.tgz#336c3efc1220adcedda2c9fab67b5a7955a33658" -regenerator-transform@0.9.8: - version "0.9.8" - resolved "https://registry.yarnpkg.com/regenerator-transform/-/regenerator-transform-0.9.8.tgz#0f88bb2bc03932ddb7b6b7312e68078f01026d6c" +regenerator-transform@0.9.11: + version "0.9.11" + resolved "https://registry.yarnpkg.com/regenerator-transform/-/regenerator-transform-0.9.11.tgz#3a7d067520cb7b7176769eb5ff868691befe1283" dependencies: babel-runtime "^6.18.0" babel-types "^6.19.0" @@ -3378,8 +3374,8 @@ release-zalgo@^1.0.0: es6-error "^4.0.1" remove-trailing-separator@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/remove-trailing-separator/-/remove-trailing-separator-1.0.1.tgz#615ebb96af559552d4bf4057c8436d486ab63cc4" + version "1.0.2" + resolved "https://registry.yarnpkg.com/remove-trailing-separator/-/remove-trailing-separator-1.0.2.tgz#69b062d978727ad14dc6b56ba4ab772fd8d70511" repeat-element@^1.1.2: version "1.1.2" @@ -3455,13 +3451,17 @@ resolve-from@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-2.0.0.tgz#9480ab20e94ffa1d9e80a804c7ea147611966b57" +resolve-from@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-3.0.0.tgz#b22c7af7d9d6881bc8b6e653335eebcb0a188748" + resolve@1.1.7: version "1.1.7" resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.1.7.tgz#203114d82ad2c5ed9e8e0411b3932875e889e97b" resolve@^1.1.6: - version "1.3.2" - resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.3.2.tgz#1f0442c9e0cbb8136e87b9305f932f46c7f28235" + version "1.3.3" + resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.3.3.tgz#655907c3469a8680dc2de3a275a8fdd69691f0e5" dependencies: path-parse "^1.0.5" @@ -3539,9 +3539,9 @@ rx-lite@^3.1.2: version "3.1.2" resolved "https://registry.yarnpkg.com/rx-lite/-/rx-lite-3.1.2.tgz#19ce502ca572665f3b647b10939f97fd1615f102" -safe-buffer@^5.0.1: - version "5.0.1" - resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.0.1.tgz#d263ca54696cd8a306b5ca6551e92de57918fbe7" +safe-buffer@^5.0.1, safe-buffer@~5.1.0: + version "5.1.1" + resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.1.tgz#893312af69b2123def71f57889001671eeb2c853" samsam@1.1.2, samsam@~1.1: version "1.1.2" @@ -3566,8 +3566,8 @@ set-immediate-shim@^1.0.1: resolved "https://registry.yarnpkg.com/set-immediate-shim/-/set-immediate-shim-1.0.1.tgz#4b2b1b27eb808a9f8dcc481a58e5e56f599f3f61" shelljs@^0.7.5: - version "0.7.7" - resolved "https://registry.yarnpkg.com/shelljs/-/shelljs-0.7.7.tgz#b2f5c77ef97148f4b4f6e22682e10bba8667cff1" + version "0.7.8" + resolved "https://registry.yarnpkg.com/shelljs/-/shelljs-0.7.8.tgz#decbcf874b0d1e5fb72e14b164a9683048e9acb3" dependencies: glob "^7.0.0" interpret "^1.0.0" @@ -3615,8 +3615,8 @@ sort-keys@^1.1.1, sort-keys@^1.1.2: is-plain-obj "^1.0.0" source-map-support@^0.4.0, source-map-support@^0.4.2: - version "0.4.14" - resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.4.14.tgz#9d4463772598b86271b4f523f6c1f4e02a7d6aef" + version "0.4.15" + resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.4.15.tgz#03202df65c06d2bd8c7ec2362a193056fef8d3b1" dependencies: source-map "^0.5.6" @@ -3660,8 +3660,8 @@ sprintf-js@~1.0.2: resolved "https://registry.yarnpkg.com/sprintf-js/-/sprintf-js-1.0.3.tgz#04e6926f662895354f3dd015203633b857297e2c" sshpk@^1.7.0: - version "1.13.0" - resolved "https://registry.yarnpkg.com/sshpk/-/sshpk-1.13.0.tgz#ff2a3e4fd04497555fed97b39a0fd82fafb3a33c" + version "1.13.1" + resolved "https://registry.yarnpkg.com/sshpk/-/sshpk-1.13.1.tgz#512df6da6287144316dc4c18fe1cf1d940739be3" dependencies: asn1 "~0.2.3" assert-plus "^1.0.0" @@ -3670,7 +3670,6 @@ sshpk@^1.7.0: optionalDependencies: bcrypt-pbkdf "^1.0.0" ecc-jsbn "~0.1.1" - jodid25519 "^1.0.0" jsbn "~0.1.0" tweetnacl "~0.14.0" @@ -3693,9 +3692,11 @@ string-width@^2.0.0: is-fullwidth-code-point "^2.0.0" strip-ansi "^3.0.0" -string_decoder@~0.10.x: - version "0.10.31" - resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-0.10.31.tgz#62e203bc41766c6c28c9fc84301dab1c5310fa94" +string_decoder@~1.0.0: + version "1.0.3" + resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.0.3.tgz#0fc67d7c141825de94282dd536bec6b9bce860ab" + dependencies: + safe-buffer "~5.1.0" stringstream@~0.0.4: version "0.0.5" @@ -3770,9 +3771,9 @@ table@^3.7.8: slice-ansi "0.0.4" string-width "^2.0.0" -tailored@2.4.5: - version "2.4.5" - resolved "https://registry.yarnpkg.com/tailored/-/tailored-2.4.5.tgz#c100530d8c2978a0b75228159a46bfe636fa70d6" +tailored@^2.4.6: + version "2.4.6" + resolved "https://registry.yarnpkg.com/tailored/-/tailored-2.4.6.tgz#1425d01bfc0e69ae0f8edb7030f82d6f0239d00f" dependencies: erlang-types "^1.0.0" @@ -3842,8 +3843,8 @@ timed-out@^4.0.0: resolved "https://registry.yarnpkg.com/timed-out/-/timed-out-4.0.1.tgz#f32eacac5a175bea25d7fab565ab3ed8741ef56f" to-fast-properties@^1.0.1: - version "1.0.2" - resolved "https://registry.yarnpkg.com/to-fast-properties/-/to-fast-properties-1.0.2.tgz#f3f5c0c3ba7299a7ef99427e44633257ade43320" + version "1.0.3" + resolved "https://registry.yarnpkg.com/to-fast-properties/-/to-fast-properties-1.0.3.tgz#b83571fa4d8c25b82e231b06e3a3055de4ca1a47" tough-cookie@~2.3.0: version "2.3.2" @@ -3884,8 +3885,8 @@ typedarray@^0.0.6: resolved "https://registry.yarnpkg.com/typedarray/-/typedarray-0.0.6.tgz#867ac74e3864187b1d3d47d996a78ec5c8830777" uglify-js@^2.6: - version "2.8.27" - resolved "https://registry.yarnpkg.com/uglify-js/-/uglify-js-2.8.27.tgz#47787f912b0f242e5b984343be8e35e95f694c9c" + version "2.8.29" + resolved "https://registry.yarnpkg.com/uglify-js/-/uglify-js-2.8.29.tgz#29c5733148057bb4e1f75df35b7a9cb72e6a59dd" dependencies: source-map "~0.5.1" yargs "~3.10.0" @@ -3923,15 +3924,15 @@ unzip-response@^2.0.1: resolved "https://registry.yarnpkg.com/unzip-response/-/unzip-response-2.0.1.tgz#d2f0f737d16b0615e72a6935ed04214572d56f97" update-notifier@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/update-notifier/-/update-notifier-2.1.0.tgz#ec0c1e53536b76647a24b77cb83966d9315123d9" + version "2.2.0" + resolved "https://registry.yarnpkg.com/update-notifier/-/update-notifier-2.2.0.tgz#1b5837cf90c0736d88627732b661c138f86de72f" dependencies: boxen "^1.0.0" chalk "^1.0.0" configstore "^3.0.0" + import-lazy "^2.1.0" is-npm "^1.0.0" latest-version "^3.0.0" - lazy-req "^2.0.0" semver-diff "^2.0.0" xdg-basedir "^3.0.0" @@ -3958,8 +3959,8 @@ util-deprecate@~1.0.1: inherits "2.0.1" uuid@^3.0.0: - version "3.0.1" - resolved "https://registry.yarnpkg.com/uuid/-/uuid-3.0.1.tgz#6544bba2dfda8c1cf17e629a3a305e2bb1fee6c1" + version "3.1.0" + resolved "https://registry.yarnpkg.com/uuid/-/uuid-3.1.0.tgz#3dd3d3e790abc24d7b0d3a034ffababe28ebbc04" validate-npm-package-license@^3.0.1: version "3.0.1" @@ -4000,10 +4001,14 @@ window-size@0.1.0: version "0.1.0" resolved "https://registry.yarnpkg.com/window-size/-/window-size-0.1.0.tgz#5438cd2ea93b202efa3a19fe8887aee7c94f9c9d" -wordwrap@0.0.2, wordwrap@~0.0.2: +wordwrap@0.0.2: version "0.0.2" resolved "https://registry.yarnpkg.com/wordwrap/-/wordwrap-0.0.2.tgz#b79669bb42ecb409f83d583cad52ca17eaa1643f" +wordwrap@~0.0.2: + version "0.0.3" + resolved "https://registry.yarnpkg.com/wordwrap/-/wordwrap-0.0.3.tgz#a3d5da6cd5c0bc0008d37234bbaf1bed63059107" + wordwrap@~1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/wordwrap/-/wordwrap-1.0.0.tgz#27584810891456a4171c8d0226441ade90cbcaeb" @@ -4071,7 +4076,7 @@ y18n@^3.2.1: version "3.2.1" resolved "https://registry.yarnpkg.com/y18n/-/y18n-3.2.1.tgz#6d15fba884c08679c0d77e88e7759e811e07fa41" -yallist@^2.0.0: +yallist@^2.1.2: version "2.1.2" resolved "https://registry.yarnpkg.com/yallist/-/yallist-2.1.2.tgz#1c11f9218f076089a47dd512f93c6699a6a81d52" From 2b887244cfab89f902176ca9e948b3a1e7ce8ce4 Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Thu, 22 Jun 2017 21:54:26 -0500 Subject: [PATCH 570/860] Add .vscode to gitignore --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index 382f0cac..9a234b19 100644 --- a/.gitignore +++ b/.gitignore @@ -21,3 +21,4 @@ stdlib_state.bin *.log .nyc_output test/app/build +.vscode From f510f1e67d00982ff20e2562c22249945b26eb0d Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Sun, 25 Jun 2017 14:54:38 -0500 Subject: [PATCH 571/860] Update .travis.yml to use elixir 1.5-rc.0. Add foreach implementation to lists --- .tool-versions | 2 +- .travis.yml | 19 +++++++++---------- .../lib/core/erlang_compat/lists.js | 7 +++++++ test/support/main.ex | 2 +- 4 files changed, 18 insertions(+), 12 deletions(-) diff --git a/.tool-versions b/.tool-versions index 3f0ad299..1c908046 100644 --- a/.tool-versions +++ b/.tool-versions @@ -1,3 +1,3 @@ erlang 20.0 -elixir ref-d19a92b +elixir ref-v1.5.0-rc.0 nodejs 8.1.0 \ No newline at end of file diff --git a/.travis.yml b/.travis.yml index 91f6a3b3..3333d660 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,21 +1,20 @@ sudo: false -language: erlang +language: elixir +elixir: + - 1.5.0-rc.0 otp_release: - - 20.0-rc1 + - 20.0 env: - - TRAVIS_NODE_VERSION="7" + - TRAVIS_NODE_VERSION="8" install: - rm -rf ~/.nvm && git clone https://github.com/creationix/nvm.git ~/.nvm && (cd ~/.nvm && git checkout `git describe --abbrev=0 --tags`) && source ~/.nvm/nvm.sh && nvm install $TRAVIS_NODE_VERSION - npm install -g yarn - yarn -before_script: - - wget http://s3.hex.pm/builds/elixir/master.zip - - unzip -d elixir master.zip - - export PATH=$(pwd)/elixir/bin:${PATH} - - mix local.rebar --force +script: - mix local.hex --force + - mix local.rebar --force - mix deps.get -script: + - mix compile - yarn build - mix test - yarn test @@ -26,4 +25,4 @@ notifications: - https://webhooks.gitter.im/e/fbd8944d285c0696dc41 on_success: always # options: [always|never|change] default: always on_failure: always # options: [always|never|change] default: always - on_start: never # options: [always|never|change] default: always + on_start: never # options: [always|never|change] default: always \ No newline at end of file diff --git a/src/javascript/lib/core/erlang_compat/lists.js b/src/javascript/lib/core/erlang_compat/lists.js index 8157461d..a926fab9 100644 --- a/src/javascript/lib/core/erlang_compat/lists.js +++ b/src/javascript/lib/core/erlang_compat/lists.js @@ -4,6 +4,13 @@ function reverse(list) { return [...list].reverse(); } +function foreach(fun, list) { + list.forEach(x => fun(x)); + + return Symbol.for('ok'); +} + export default { reverse, + foreach, }; diff --git a/test/support/main.ex b/test/support/main.ex index c37a6f0e..ec6b49bd 100644 --- a/test/support/main.ex +++ b/test/support/main.ex @@ -1,6 +1,6 @@ defmodule Main do def start(:normal, [callback]) do callback.("started") - Enum.each(1..5, fn(x) -> JS.console.log(x) end) + Enum.each(%{a: 1}, fn(x) -> JS.console.log(x) end) end end From f07fac7669de578d3cfad2c0f67e80f601875aee Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Sun, 25 Jun 2017 15:06:52 -0500 Subject: [PATCH 572/860] Fix tests. --- test/next/passes/translate/form_test.exs | 2 +- test/support/main.ex | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/test/next/passes/translate/form_test.exs b/test/next/passes/translate/form_test.exs index e93dab3b..5d8dc95c 100644 --- a/test/next/passes/translate/form_test.exs +++ b/test/next/passes/translate/form_test.exs @@ -76,7 +76,7 @@ defmodule ElixirScript.Translate.Forms.Test do state = %{} {js_ast, _} = Form.compile(ast, state) - assert js_ast == J.call_expression( + assert js_ast == J.new_expression( J.member_expression( J.member_expression( J.identifier("Bootstrap"), diff --git a/test/support/main.ex b/test/support/main.ex index ec6b49bd..a18d3d90 100644 --- a/test/support/main.ex +++ b/test/support/main.ex @@ -1,6 +1,5 @@ defmodule Main do def start(:normal, [callback]) do callback.("started") - Enum.each(%{a: 1}, fn(x) -> JS.console.log(x) end) end end From 4080313f57ccc96d63b5c8231d4a69a501994624 Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Sun, 25 Jun 2017 17:22:31 -0500 Subject: [PATCH 573/860] Update documentation --- CONTRIBUTING.md | 12 +++--------- FAQ.md | 27 --------------------------- README.md | 20 +------------------- 3 files changed, 4 insertions(+), 55 deletions(-) delete mode 100644 FAQ.md diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index b9884e8a..9be626f1 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -18,7 +18,7 @@ Good bug reports are extremely helpful - thank you! Guidelines for bug reports: 1. **Use the GitHub issue search** — [check if the issue has already been - reported](https://github.com/bryanjos/elixirscript/search?type=Issues). + reported](https://github.com/elixirscript/elixirscript/search?type=Issues). 2. **Check if the issue has been fixed** — try to reproduce it using the `master` branch in the repository. @@ -64,16 +64,13 @@ found in Elixir in ElixirScript. ElixirScript is broken up into the following parts: * The compiler, written in Elixir -* The standard library modules, written in Elixir -* The javascript core +* The JavaScript core The ElixirScript compiler is in the `lib` folder of the project. Here is where Elixir code is converted into JavaScript. -The standard library modules are in the `priv/std_lib` folder. - The JavaScript code is in the `src/javascript`. -This is where features such as pattern matching and the special forms are implemented. +This is where the special forms and the Erlang Compatibility Layer are defined The ElixirScript tests can be run using `mix test` @@ -82,9 +79,6 @@ The JavaScript tests can be run using `yarn test` Please make sure all tests pass after making changes. Also make sure to include tests for the changes you made. -Contributing to the standard library may be the easiest and most rewarding changes. -Don't see a module, function or macro from Elixir in ElixirScript yet? You can help by implementing it. - ## Pull requests Good pull requests - patches, improvements, new features - are a fantastic diff --git a/FAQ.md b/FAQ.md deleted file mode 100644 index 92ba2f7e..00000000 --- a/FAQ.md +++ /dev/null @@ -1,27 +0,0 @@ -# FAQ - -# Q. How do I get started? - -### A. Check out the [Getting Started](GettingStarted.md) Guide for more info. - -# Q. How much is implemented? - -### A. Check out the [Supported Modules, Functions, and Macros](Supported.md) - -## Q. Can I use it today? - -### A. Yes, but realize this is not at 1.0 yet. - -You **can** use ElixirScript on your front ends and have it work and interoperate with JavaScript modules. The problem is that most of the standard library is incomplete. - -## Q. Can I use pattern matching? - -### A. Yes - -## Q. Can I use processes? - -### A. ElixirScript does not support processes - -## Q. What about OTP? - -### A. ElixirScript does not support OTP diff --git a/README.md b/README.md index 300f89b5..a3a106c0 100644 --- a/README.md +++ b/README.md @@ -5,7 +5,7 @@ The goal is to convert a subset (or full set) of Elixir code to JavaScript, prov Requirements =========== * Erlang 20 or greater -* Elixir 1.5 or greater +* Elixir 1.5 or greater (must be compiled with Erlang 20 or greater) * Node (only for development) Usage @@ -67,21 +67,3 @@ Contributing ======== Please check the [CONTRIBUTING.md](CONTRIBUTING.md) - - -### Example projects -* [hello](https://github.com/bryanjos/hello) Shows using Phoenix + Elixirscript with file watching -* [Elixirscript frontend boilerplate](https://github.com/elixirscript/elixirscript-project-boilerplate) A boilerplate project for elixirscript frontends -* [Elixirscript React example](https://github.com/bryanjos/elixirscript_react) An example of using with React -* [Elixirscript AWS Lambda example](https://github.com/bryanjos/elixirscript_lambda) - -#### Using with Brunch -There is a plugin for using ElixirScript in your Brunch project -[here](https://www.npmjs.com/package/elixirscript-brunch) - -#### Using with Webpack -There is a loader for using ElixirScript in your Webpack project -[here](https://www.npmjs.com/package/elixirscript-loader) - -#### 1.0 Roadmap -There is a [1.0.0 Milestone](https://github.com/bryanjos/elixirscript/milestones/1.0.0) defined which includes issues that are needed to be cleared before 1.0 can be reached. From 01a51b395c05a227b759544d61f849d498d272bf Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Sun, 25 Jun 2017 18:22:56 -0500 Subject: [PATCH 574/860] Removed old compiler code and promoted new compiler code --- lib/elixir_script.ex | 238 ----- lib/elixir_script/{next => }/beam.ex | 0 lib/elixir_script/{next => }/compiler.ex | 0 lib/elixir_script/lib/js.ex | 40 + .../elixir_script/lib}/string.ex | 13 +- lib/elixir_script/module_systems/common.ex | 2 +- lib/elixir_script/module_systems/es.ex | 4 +- lib/elixir_script/module_systems/namespace.ex | 6 +- lib/elixir_script/module_systems/umd.ex | 2 +- lib/elixir_script/passes/ast_from_file.ex | 26 - .../passes/consolidate_protocols.ex | 103 --- lib/elixir_script/passes/create_js_modules.ex | 169 ---- lib/elixir_script/passes/find_functions.ex | 92 -- lib/elixir_script/passes/find_load_only.ex | 33 - lib/elixir_script/passes/find_modules.ex | 181 ---- .../{next => }/passes/find_used_functions.ex | 0 .../{next => }/passes/find_used_modules.ex | 0 lib/elixir_script/passes/handle_output.ex | 62 -- .../passes/handle_overridables.ex | 87 -- lib/elixir_script/passes/init.ex | 10 - lib/elixir_script/passes/java_script_ast.ex | 43 - lib/elixir_script/passes/java_script_code.ex | 32 - lib/elixir_script/passes/load_modules.ex | 27 - .../passes/load_modules_for_quoted.ex | 28 - lib/elixir_script/{next => }/passes/output.ex | 12 +- .../{next => }/passes/output/js_module.ex | 10 +- lib/elixir_script/passes/remove_unused.ex | 31 - .../{next => }/passes/translate.ex | 0 .../{next => }/passes/translate/clause.ex | 0 .../{next => }/passes/translate/form.ex | 0 .../passes/translate/forms/bitstring.ex | 4 +- .../{next => }/passes/translate/forms/for.ex | 0 .../{next => }/passes/translate/forms/js.ex | 0 .../{next => }/passes/translate/forms/map.ex | 0 .../passes/translate/forms/match.ex | 0 .../passes/translate/forms/pattern.ex | 4 +- .../translate/forms/pattern/patterns.ex | 114 +++ .../passes/translate/forms/receive.ex | 0 .../passes/translate/forms/remote.ex | 0 .../{next => }/passes/translate/forms/try.ex | 0 .../{next => }/passes/translate/function.ex | 0 .../{next => }/passes/translate/identifier.ex | 0 .../{next => }/passes/translate/module.ex | 0 .../{next => }/passes/translate/protocol.ex | 0 lib/elixir_script/{next => }/state.ex | 0 lib/elixir_script/translator.ex | 738 ---------------- lib/elixir_script/translator/empty.ex | 8 - lib/elixir_script/translator/group.ex | 30 - lib/elixir_script/translator/kernel/def.ex | 39 - .../translator/kernel/defimpl.ex | 137 --- .../translator/kernel/defmodule.ex | 267 ------ .../translator/kernel/defprotocol.ex | 93 -- .../translator/kernel/expression.ex | 18 - lib/elixir_script/translator/kernel/js.ex | 237 ----- .../kernel/special_forms/bitstring.ex | 147 ---- .../translator/kernel/special_forms/block.ex | 14 - .../translator/kernel/special_forms/call.ex | 214 ----- .../kernel/special_forms/capture.ex | 44 - .../translator/kernel/special_forms/case.ex | 17 - .../translator/kernel/special_forms/cond.ex | 34 - .../translator/kernel/special_forms/fn.ex | 254 ------ .../translator/kernel/special_forms/for.ex | 130 --- .../kernel/special_forms/identifier.ex | 98 --- .../translator/kernel/special_forms/map.ex | 91 -- .../translator/kernel/special_forms/match.ex | 93 -- .../kernel/special_forms/primitive.ex | 99 --- .../translator/kernel/special_forms/quote.ex | 87 -- .../translator/kernel/special_forms/struct.ex | 116 --- .../translator/kernel/special_forms/try.ex | 115 --- .../translator/kernel/special_forms/with.ex | 52 -- lib/elixir_script/translator/lexical_scope.ex | 394 --------- .../translator/pattern_matching.ex | 278 ------ lib/elixir_script/translator/rewriter.ex | 495 ----------- lib/elixir_script/translator/state.ex | 143 --- .../translator/unsupported_error.ex | 8 - lib/elixir_script/translator/utils.ex | 65 -- lib/mix/tasks/compile.elixir_script.ex | 2 +- priv/std_lib/agent.ex | 54 -- priv/std_lib/atom.ex | 13 - priv/std_lib/base.ex | 30 - priv/std_lib/bitwise.ex | 74 -- priv/std_lib/bootstrap/functions.ex | 70 -- priv/std_lib/collectable.ex | 34 - priv/std_lib/enum.ex | 358 -------- priv/std_lib/enum/out_of_bounds_error.ex | 3 - priv/std_lib/enumerable.ex | 38 - priv/std_lib/exceptions.ex | 7 - priv/std_lib/integer.ex | 29 - priv/std_lib/io.ex | 22 - priv/std_lib/js.ex | 108 --- priv/std_lib/kernel.ex | 209 ----- priv/std_lib/keyword.ex | 46 - priv/std_lib/list.ex | 265 ------ priv/std_lib/macro/env.ex | 37 - priv/std_lib/map.ex | 204 ----- priv/std_lib/map_set.ex | 100 --- priv/std_lib/module.ex | 9 - priv/std_lib/range.ex | 12 - priv/std_lib/regex.ex | 71 -- priv/std_lib/store.ex | 45 - priv/std_lib/string/chars.ex | 48 -- priv/std_lib/tuple.ex | 63 -- rollup.config.js | 5 +- .../lib/core/erlang_compat/erlang.js | 40 +- test/cli_test.exs | 8 - test/passes/create_js_modules_test.exs | 30 - test/passes/handle_output_test.exs | 21 - .../{next => }/passes/translate/form_test.exs | 2 +- .../passes/translate/forms/map_test.exs | 0 .../passes/translate/forms/receive_test.exs | 0 .../passes/translate/forms/remote_test.exs | 0 test/prelude/js_test.exs | 52 -- test/prelude/kernel_test.exs | 44 - test/support/main.ex | 3 + test/test_helper.exs | 84 -- test/translator/access_test.exs | 14 - test/translator/atom_test.exs | 14 - test/translator/bitstring_test.exs | 95 -- test/translator/bitwise_test.exs | 15 - test/translator/bug_test.exs | 161 ---- test/translator/capture_test.exs | 131 --- test/translator/case_test.exs | 211 ----- test/translator/commonjs_test.exs | 22 - test/translator/cond_test.exs | 58 -- test/translator/defdelegate_test.exs | 28 - test/translator/defmodule_test.exs | 176 ---- test/translator/for_test.exs | 202 ----- test/translator/function_test.exs | 815 ------------------ test/translator/js_test.exs | 55 -- test/translator/kernel_test.exs | 89 -- test/translator/list_test.exs | 70 -- test/translator/map_test.exs | 87 -- test/translator/match_test.exs | 84 -- test/translator/nil_test.exs | 9 - test/translator/number_test.exs | 18 - test/translator/pattern_matching_test.exs | 257 ------ test/translator/quote_test.exs | 142 --- test/translator/string_test.exs | 43 - test/translator/struct_test.exs | 233 ----- test/translator/try_test.exs | 231 ----- test/translator/tuple_test.exs | 35 - test/translator/umd_test.exs | 29 - test/translator/with_test.exs | 75 -- 143 files changed, 224 insertions(+), 11343 deletions(-) rename lib/elixir_script/{next => }/beam.ex (100%) rename lib/elixir_script/{next => }/compiler.ex (100%) create mode 100644 lib/elixir_script/lib/js.ex rename {priv/std_lib => lib/elixir_script/lib}/string.ex (94%) delete mode 100644 lib/elixir_script/passes/ast_from_file.ex delete mode 100644 lib/elixir_script/passes/consolidate_protocols.ex delete mode 100644 lib/elixir_script/passes/create_js_modules.ex delete mode 100644 lib/elixir_script/passes/find_functions.ex delete mode 100644 lib/elixir_script/passes/find_load_only.ex delete mode 100644 lib/elixir_script/passes/find_modules.ex rename lib/elixir_script/{next => }/passes/find_used_functions.ex (100%) rename lib/elixir_script/{next => }/passes/find_used_modules.ex (100%) delete mode 100644 lib/elixir_script/passes/handle_output.ex delete mode 100644 lib/elixir_script/passes/handle_overridables.ex delete mode 100644 lib/elixir_script/passes/init.ex delete mode 100644 lib/elixir_script/passes/java_script_ast.ex delete mode 100644 lib/elixir_script/passes/java_script_code.ex delete mode 100644 lib/elixir_script/passes/load_modules.ex delete mode 100644 lib/elixir_script/passes/load_modules_for_quoted.ex rename lib/elixir_script/{next => }/passes/output.ex (85%) rename lib/elixir_script/{next => }/passes/output/js_module.ex (92%) delete mode 100644 lib/elixir_script/passes/remove_unused.ex rename lib/elixir_script/{next => }/passes/translate.ex (100%) rename lib/elixir_script/{next => }/passes/translate/clause.ex (100%) rename lib/elixir_script/{next => }/passes/translate/form.ex (100%) rename lib/elixir_script/{next => }/passes/translate/forms/bitstring.ex (96%) rename lib/elixir_script/{next => }/passes/translate/forms/for.ex (100%) rename lib/elixir_script/{next => }/passes/translate/forms/js.ex (100%) rename lib/elixir_script/{next => }/passes/translate/forms/map.ex (100%) rename lib/elixir_script/{next => }/passes/translate/forms/match.ex (100%) rename lib/elixir_script/{next => }/passes/translate/forms/pattern.ex (98%) create mode 100644 lib/elixir_script/passes/translate/forms/pattern/patterns.ex rename lib/elixir_script/{next => }/passes/translate/forms/receive.ex (100%) rename lib/elixir_script/{next => }/passes/translate/forms/remote.ex (100%) rename lib/elixir_script/{next => }/passes/translate/forms/try.ex (100%) rename lib/elixir_script/{next => }/passes/translate/function.ex (100%) rename lib/elixir_script/{next => }/passes/translate/identifier.ex (100%) rename lib/elixir_script/{next => }/passes/translate/module.ex (100%) rename lib/elixir_script/{next => }/passes/translate/protocol.ex (100%) rename lib/elixir_script/{next => }/state.ex (100%) delete mode 100644 lib/elixir_script/translator.ex delete mode 100644 lib/elixir_script/translator/empty.ex delete mode 100644 lib/elixir_script/translator/group.ex delete mode 100644 lib/elixir_script/translator/kernel/def.ex delete mode 100644 lib/elixir_script/translator/kernel/defimpl.ex delete mode 100644 lib/elixir_script/translator/kernel/defmodule.ex delete mode 100644 lib/elixir_script/translator/kernel/defprotocol.ex delete mode 100644 lib/elixir_script/translator/kernel/expression.ex delete mode 100644 lib/elixir_script/translator/kernel/js.ex delete mode 100644 lib/elixir_script/translator/kernel/special_forms/bitstring.ex delete mode 100644 lib/elixir_script/translator/kernel/special_forms/block.ex delete mode 100644 lib/elixir_script/translator/kernel/special_forms/call.ex delete mode 100644 lib/elixir_script/translator/kernel/special_forms/capture.ex delete mode 100644 lib/elixir_script/translator/kernel/special_forms/case.ex delete mode 100644 lib/elixir_script/translator/kernel/special_forms/cond.ex delete mode 100644 lib/elixir_script/translator/kernel/special_forms/fn.ex delete mode 100644 lib/elixir_script/translator/kernel/special_forms/for.ex delete mode 100644 lib/elixir_script/translator/kernel/special_forms/identifier.ex delete mode 100644 lib/elixir_script/translator/kernel/special_forms/map.ex delete mode 100644 lib/elixir_script/translator/kernel/special_forms/match.ex delete mode 100644 lib/elixir_script/translator/kernel/special_forms/primitive.ex delete mode 100644 lib/elixir_script/translator/kernel/special_forms/quote.ex delete mode 100644 lib/elixir_script/translator/kernel/special_forms/struct.ex delete mode 100644 lib/elixir_script/translator/kernel/special_forms/try.ex delete mode 100644 lib/elixir_script/translator/kernel/special_forms/with.ex delete mode 100644 lib/elixir_script/translator/lexical_scope.ex delete mode 100644 lib/elixir_script/translator/pattern_matching.ex delete mode 100644 lib/elixir_script/translator/rewriter.ex delete mode 100644 lib/elixir_script/translator/state.ex delete mode 100644 lib/elixir_script/translator/unsupported_error.ex delete mode 100644 lib/elixir_script/translator/utils.ex delete mode 100644 priv/std_lib/agent.ex delete mode 100644 priv/std_lib/atom.ex delete mode 100644 priv/std_lib/base.ex delete mode 100644 priv/std_lib/bitwise.ex delete mode 100644 priv/std_lib/bootstrap/functions.ex delete mode 100644 priv/std_lib/collectable.ex delete mode 100644 priv/std_lib/enum.ex delete mode 100644 priv/std_lib/enum/out_of_bounds_error.ex delete mode 100644 priv/std_lib/enumerable.ex delete mode 100644 priv/std_lib/exceptions.ex delete mode 100644 priv/std_lib/integer.ex delete mode 100644 priv/std_lib/io.ex delete mode 100644 priv/std_lib/js.ex delete mode 100644 priv/std_lib/kernel.ex delete mode 100644 priv/std_lib/keyword.ex delete mode 100644 priv/std_lib/list.ex delete mode 100644 priv/std_lib/macro/env.ex delete mode 100644 priv/std_lib/map.ex delete mode 100644 priv/std_lib/map_set.ex delete mode 100644 priv/std_lib/module.ex delete mode 100644 priv/std_lib/range.ex delete mode 100644 priv/std_lib/regex.ex delete mode 100644 priv/std_lib/store.ex delete mode 100644 priv/std_lib/string/chars.ex delete mode 100644 priv/std_lib/tuple.ex delete mode 100644 test/cli_test.exs delete mode 100644 test/passes/create_js_modules_test.exs delete mode 100644 test/passes/handle_output_test.exs rename test/{next => }/passes/translate/form_test.exs (98%) rename test/{next => }/passes/translate/forms/map_test.exs (100%) rename test/{next => }/passes/translate/forms/receive_test.exs (100%) rename test/{next => }/passes/translate/forms/remote_test.exs (100%) delete mode 100644 test/prelude/js_test.exs delete mode 100644 test/prelude/kernel_test.exs delete mode 100644 test/translator/access_test.exs delete mode 100644 test/translator/atom_test.exs delete mode 100644 test/translator/bitstring_test.exs delete mode 100644 test/translator/bitwise_test.exs delete mode 100644 test/translator/bug_test.exs delete mode 100644 test/translator/capture_test.exs delete mode 100644 test/translator/case_test.exs delete mode 100644 test/translator/commonjs_test.exs delete mode 100644 test/translator/cond_test.exs delete mode 100644 test/translator/defdelegate_test.exs delete mode 100644 test/translator/defmodule_test.exs delete mode 100644 test/translator/for_test.exs delete mode 100644 test/translator/function_test.exs delete mode 100644 test/translator/js_test.exs delete mode 100644 test/translator/kernel_test.exs delete mode 100644 test/translator/list_test.exs delete mode 100644 test/translator/map_test.exs delete mode 100644 test/translator/match_test.exs delete mode 100644 test/translator/nil_test.exs delete mode 100644 test/translator/number_test.exs delete mode 100644 test/translator/pattern_matching_test.exs delete mode 100644 test/translator/quote_test.exs delete mode 100644 test/translator/string_test.exs delete mode 100644 test/translator/struct_test.exs delete mode 100644 test/translator/try_test.exs delete mode 100644 test/translator/tuple_test.exs delete mode 100644 test/translator/umd_test.exs delete mode 100644 test/translator/with_test.exs diff --git a/lib/elixir_script.ex b/lib/elixir_script.ex index 298b80c9..d92c6861 100644 --- a/lib/elixir_script.ex +++ b/lib/elixir_script.ex @@ -1,240 +1,2 @@ defmodule ElixirScript do - require Logger - - @moduledoc """ - Translates Elixir into JavaScript. - - All compile functions return a list of - transpiled javascript code or a tuple consisting of - the file name for the code and the transpiled javascript code. - - All compile functions also take an optional opts parameter - that controls transpiler output. - - Available options are: - * `:include_path` - a boolean controlling whether to return just the JavaScript code - or a tuple of the file name and the JavaScript code - * `:core_path` - The es6 import path used to import the elixirscript core. - When using this option, the Elixir.js file is not exported - * `:full_build` - For compile_path, tells the compiler to perform a full build instead of incremental one - * `:output` - option to tell compiler how to output data - * `nil`: Return as list - * `:stdout`: Write to standard out - * `path (string)`: Write to specified path - """ - - defmacro __using__(_) do - quote do - import Kernel, except: [ - if: 2, unless: 2, abs: 1, apply: 2, apply: 3, binary_part: 3, hd: 1, - tl: 1, is_atom: 1, is_binary: 1, is_bitstring: 1, is_boolean: 1, is_float: 1, - is_function: 1, is_function: 2, is_integer: 1, is_list: 1, is_number: 1, - is_pid: 1, is_tuple: 1, is_map: 1, is_port: 1, is_reference: 1, length: 1, - map_size: 1, max: 2, min: 2, round: 1, trunc: 1, tuple_size: 1, elem: 2, is_nil: 1, - make_ref: 1, spawn: 1, spawn: 3, spawn_link: 1, spawn_link: 3, spawn_monitor: 1, - spawn_monitor: 3, send: 2, self: 0, match?: 2, to_string: 1, "|>": 2, in: 2, "..": 2, - sigil_r: 2 - ] - import ElixirScript.Kernel - require JS - end - end - - # This is the serialized state of the ElixirScript.State module containing references to the standard library - @lib_path Application.get_env(:elixir_script, :lib_path) - @version Mix.Project.config[:version] - - @doc """ - Compiles the given Elixir code string - """ - @spec compile(binary, Map.t) :: [binary | {binary, binary} | :ok] - def compile(elixir_code, opts \\ %{}) do - elixir_code - |> List.wrap - |> Enum.map(fn(x) -> - x - |> Code.string_to_quoted! - |> compile_quoted(opts) - end) - |> List.flatten - end - - @doc """ - Compiles the given Elixir code in quoted form - """ - @spec compile_quoted(Macro.t, Map.t) :: [binary | {binary, binary} | :ok] - def compile_quoted(quoted, opts \\ %{}) do - - opts = build_compiler_options(opts) - - data = quoted - |> get_modules_from_quoted - |> Enum.map(fn(x) -> %{ast: x, app: :app} end) - - std_lib_quoted = get_quoted_std_lib() - - %{data: std_lib_quoted ++ data} - |> ElixirScript.Passes.Init.execute(opts) - |> shared_passes(opts) - end - - defp shared_passes(compiler_data, opts) do - compiler_data - |> ElixirScript.Passes.FindModules.execute(opts) - |> ElixirScript.Passes.FindLoadOnly.execute(opts) - |> ElixirScript.Passes.HandleOverridables.execute(opts) - |> ElixirScript.Passes.FindFunctions.execute(opts) - |> ElixirScript.Passes.JavaScriptAST.execute(opts) - |> ElixirScript.Passes.ConsolidateProtocols.execute(opts) - |> ElixirScript.Passes.RemoveUnused.execute(opts) - |> ElixirScript.Passes.CreateJSModules.execute(opts) - |> ElixirScript.Passes.JavaScriptCode.execute(opts) - |> ElixirScript.Passes.HandleOutput.execute(opts) - end - - defp get_quoted_std_lib() do - files = [get_std_lib_path(), "**", "*.ex"] - |> Path.join - |> Path.wildcard - - files - |> Enum.map(fn path -> File.read!(path) end) - |> Enum.map(&Code.string_to_quoted!(&1)) - |> Enum.flat_map(&get_modules_from_quoted(&1)) - |> Enum.map(fn(x) -> %{ast: x, app: :elixir} end) - end - - defp get_modules_from_quoted(quoted) do - results = case quoted do - {:__block__, _, list} -> - {modules, not_modules} = Enum.partition(list, - fn - {type, _, _ } when type in [:defprotocol, :defimpl, :defmodule] -> - true - _ -> - false - end) - - temp_module = case not_modules do - [] -> - [] - _ -> - [{:defmodule, [], [{:__aliases__, [], [:ElixirScript, :Temp]}, [do: { :__block__, [], not_modules }]]}] - end - - modules ++ temp_module - - {type, _, _ } = x when type in [:defprotocol, :defimpl, :defmodule] -> - x - x -> - {:defmodule, [], [{:__aliases__, [], [:ElixirScript, :Temp]}, [do: { :__block__, [], [x] }]]} - end - - List.wrap(results) - end - - @doc """ - Compiles the elixir files found at the given path - """ - @spec compile_path(binary | [binary] | map, Map.t) :: [binary | {binary, binary} | :ok] - def compile_path(path, opts \\ %{}) - - def compile_path(path, opts) when is_binary(path) do - compile_path([path], opts) - end - - def compile_path(path, opts) when is_list(path) do - built_opts = build_compiler_options(opts) - - app_name = cond do - !is_nil(built_opts[:app]) -> - built_opts[:app] - Code.ensure_loaded?(Mix) -> - Mix.Project.config()[:app] - true -> - :app - end - - compile_path(Map.put(%{}, app_name, path), opts) - end - - def compile_path(path, opts) do - opts = build_compiler_options(opts) - - deps = path - |> Map.to_list - |> Enum.map(fn {app, path} -> {app, List.wrap(path)} end) - - deps_wrapped = [{:elixir, List.wrap(get_std_lib_path())}] ++ deps - - result = %{data: deps_wrapped} - |> ElixirScript.Passes.Init.execute(opts) - |> ElixirScript.Passes.ASTFromFile.execute(opts) - |> ElixirScript.Passes.LoadModules.execute(opts) - |> shared_passes(opts) - - result - end - - defp build_compiler_options(opts) do - default_options = Map.new - |> Map.put(:include_path, false) - |> Map.put(:root, nil) - |> Map.put(:env, __ENV__) - |> Map.put(:import_standard_libs, true) - |> Map.put(:core_path, "Elixir.Bootstrap") - |> Map.put(:full_build, false) - |> Map.put(:output, nil) - |> Map.put(:app, :app) - |> Map.put(:format, :es) - |> Map.put(:js_modules, []) - |> Map.put(:remove_unused, false) - - options = Map.merge(default_options, opts) - Map.put(options, :module_formatter, get_module_formatter(options[:format])) - end - - defp get_module_formatter(:umd) do - ElixirScript.ModuleSystems.UMD - end - - defp get_module_formatter(:common) do - ElixirScript.ModuleSystems.Common - end - - defp get_module_formatter(_) do - ElixirScript.ModuleSystems.ES - end - - @doc """ - Returns the contents of the bootrstrap js file - """ - @spec get_bootstrap_js(string) :: string - def get_bootstrap_js(module_format) do - path = Path.join([operating_path, "build", to_string(module_format), "Elixir.Bootstrap.js"]) - File.read!(path) - end - - #Gets path to js files whether the mix project is available - #or when used as an escript - defp operating_path() do - case @lib_path do - nil -> - if Code.ensure_loaded?(Mix.Project) do - Path.join([Mix.Project.build_path, "lib", "elixir_script", "priv"]) - else - split_path = Path.split(Application.app_dir(:elixirscript)) - replaced_path = List.delete_at(split_path, length(split_path) - 1) - replaced_path = List.delete_at(replaced_path, length(replaced_path) - 1) - Path.join(replaced_path) - end - lib_path -> - lib_path - end - end - - defp get_std_lib_path() do - Path.join([operating_path(), "std_lib"]) - end - end diff --git a/lib/elixir_script/next/beam.ex b/lib/elixir_script/beam.ex similarity index 100% rename from lib/elixir_script/next/beam.ex rename to lib/elixir_script/beam.ex diff --git a/lib/elixir_script/next/compiler.ex b/lib/elixir_script/compiler.ex similarity index 100% rename from lib/elixir_script/next/compiler.ex rename to lib/elixir_script/compiler.ex diff --git a/lib/elixir_script/lib/js.ex b/lib/elixir_script/lib/js.ex new file mode 100644 index 00000000..990a2110 --- /dev/null +++ b/lib/elixir_script/lib/js.ex @@ -0,0 +1,40 @@ +defmodule JS do + @moduledoc """ + This module defines macros and functions which implement + JavaScript functionality that may not translate easily to + Elixir. For instance, creating a new object + """ + + @doc """ + Creates new JavaScript objects. + + ex: + JS.new User, ["first_name", "last_name"] + """ + defmacro new(module, params) + + @doc """ + Returns the type of the given value + """ + defmacro typeof(value) + + @doc """ + Determines if value is an instance of type. + """ + defmacro instanceof(value, type) + + @doc """ + Throws the term given + """ + defmacro throw(term) + + @doc """ + Creates a breakpoint for JavaScript debuggers to stop at + """ + defmacro debugger() + + @doc """ + The current JavaScript context + """ + defmacro this() +end diff --git a/priv/std_lib/string.ex b/lib/elixir_script/lib/string.ex similarity index 94% rename from priv/std_lib/string.ex rename to lib/elixir_script/lib/string.ex index 3d5465bc..6ace3e43 100644 --- a/priv/std_lib/string.ex +++ b/lib/elixir_script/lib/string.ex @@ -3,11 +3,11 @@ defmodule ElixirScript.String do import Kernel, except: [length: 1] def to_atom(str) do - JS.Symbol.for(str) + :erlang.binary_to_atom(str, :utf8) end def to_existing_atom(str) do - JS.Symbol.for(str) + :erlang.binary_to_existing_atom(str, :utf8) end def to_char_list(str) do @@ -198,12 +198,7 @@ defmodule ElixirScript.String do do_codepoints(str.substr(1), codepoint_list ++ [first(str).codePointAt(0)]) end - def valid_character?(codepoint) do - try do - JS.String.fromCodePoint(codepoint) != nil - rescue - _ -> - false - end + def valid?(str) do + is_binary(str) end end diff --git a/lib/elixir_script/module_systems/common.ex b/lib/elixir_script/module_systems/common.ex index c3caf08a..f5c01065 100644 --- a/lib/elixir_script/module_systems/common.ex +++ b/lib/elixir_script/module_systems/common.ex @@ -21,7 +21,7 @@ defmodule ElixirScript.ModuleSystems.Common do end defp import_module(module_name, from) do - js_module_name = ElixirScript.Translator.Identifier.make_namespace_members(module_name) + js_module_name = ElixirScript.Translate.Identifier.make_namespace_members(module_name) do_import_module(js_module_name, from) end diff --git a/lib/elixir_script/module_systems/es.ex b/lib/elixir_script/module_systems/es.ex index 4423d064..81f5bd4c 100644 --- a/lib/elixir_script/module_systems/es.ex +++ b/lib/elixir_script/module_systems/es.ex @@ -22,7 +22,7 @@ defmodule ElixirScript.ModuleSystems.ES do end defp import_namespace_module(module_name, from) do - js_module_name = ElixirScript.Translator.Identifier.make_namespace_members(module_name) + js_module_name = ElixirScript.Translate.Identifier.make_namespace_members(module_name) import_specifier = JS.import_namespace_specifier( js_module_name, @@ -33,7 +33,7 @@ defmodule ElixirScript.ModuleSystems.ES do end defp import_module(import_name, from) do - js_module_name = ElixirScript.Translator.Identifier.make_namespace_members(import_name) + js_module_name = ElixirScript.Translate.Identifier.make_namespace_members(import_name) import_specifier = JS.import_default_specifier( js_module_name diff --git a/lib/elixir_script/module_systems/namespace.ex b/lib/elixir_script/module_systems/namespace.ex index ba2f0724..92caa561 100644 --- a/lib/elixir_script/module_systems/namespace.ex +++ b/lib/elixir_script/module_systems/namespace.ex @@ -4,7 +4,7 @@ defmodule ElixirScript.ModuleSystems.Namespace do alias ElixirScript.Translator alias ElixirScript.Translator.State alias ElixirScript.Translator.Utils - alias ElixirScript.Translator.Identifier + alias ElixirScript.Translate.Identifier def build(module_name, body, exports, env) do List.wrap(make_namespace_body(module_name, body, exports)) @@ -69,12 +69,12 @@ defmodule ElixirScript.ModuleSystems.Namespace do JS.identifier("__exports") ) - exports = [JS.return_statement(JS.identifier("__exports"))] + exports = [JS.return_statement(JS.identifier("__exports"))] make = JS.member_expression( JS.call_expression( build_namespace(), - [JS.identifier("Elixir"), JS.literal(Utils.name_to_js_file_name(module_name))] + [JS.identifier("Elixir"), JS.literal(Enum.join(["Elixir"] ++ Module.split(module_name), "."))] ), JS.identifier("__load") ) diff --git a/lib/elixir_script/module_systems/umd.ex b/lib/elixir_script/module_systems/umd.ex index 5a94cb5c..c0f0d7a6 100644 --- a/lib/elixir_script/module_systems/umd.ex +++ b/lib/elixir_script/module_systems/umd.ex @@ -21,7 +21,7 @@ defmodule ElixirScript.ModuleSystems.UMD do end defp import_module(module_name, from) do - js_module_name = ElixirScript.Translator.Identifier.make_namespace_members(module_name) + js_module_name = ElixirScript.Translate.Identifier.make_namespace_members(module_name) {js_module_name, JS.literal(from)} end diff --git a/lib/elixir_script/passes/ast_from_file.ex b/lib/elixir_script/passes/ast_from_file.ex deleted file mode 100644 index 271ccdec..00000000 --- a/lib/elixir_script/passes/ast_from_file.ex +++ /dev/null @@ -1,26 +0,0 @@ -defmodule ElixirScript.Passes.ASTFromFile do - @moduledoc false - - def execute(compiler_data, opts) do - data = Enum.reduce(compiler_data.data, [], fn({dep, paths}, list) -> - - file_paths = paths - |> Enum.flat_map(fn(path) -> Path.join([path, "**", "*.{ex,exs,exjs}"]) |> Path.wildcard end) - |> Enum.reduce([], fn(path, list) -> - quoted = path - |> File.read! - |> Code.string_to_quoted! - - stat = File.stat!(path) - - list ++ [%{path: path, app: dep, stat: stat, ast: quoted}] - end) - - - list ++ file_paths - end) - - Map.put(compiler_data, :data, data) - end - -end diff --git a/lib/elixir_script/passes/consolidate_protocols.ex b/lib/elixir_script/passes/consolidate_protocols.ex deleted file mode 100644 index f0c40d2b..00000000 --- a/lib/elixir_script/passes/consolidate_protocols.ex +++ /dev/null @@ -1,103 +0,0 @@ -defmodule ElixirScript.Passes.ConsolidateProtocols do - @moduledoc false - alias ESTree.Tools.Builder, as: JS - alias ElixirScript.Translator.Utils - alias ElixirScript.Translator.State - alias ElixirScript.Translator.Identifier - require Logger - - def execute(compiler_data, opts) do - State.set_module_data(compiler_data.state, compiler_data.data) - data = State.get_module_data(compiler_data.state) - - only_protocols_and_impls = Enum.filter(data, fn - ({_, %{type: :module}}) -> - false - ({_, %{type: :consolidated}}) -> - false - _ -> - true - end) - - grouped = group_protocol_data(only_protocols_and_impls) - consolidated_protocols = update_protocols(grouped, opts) - - data = Enum.reduce(consolidated_protocols, data, fn({ key, value }, d) -> Keyword.put(d, key, value) end) - - %{ compiler_data | data: data } - end - - - defp group_protocol_data(data) do - Enum.reduce(data, %{}, fn({module_name, module_data} = dat, state) -> - if module_data.type == :protocol do - existing = Map.get(state, module_name, %{}) - existing = Map.put(existing, :protocol, dat) - Map.put(state, module_name, existing) - else - existing = Map.get(state, module_data.implements, %{}) - existing_protocol_data = Map.get(existing, :impls, []) - existing_protocol_data = existing_protocol_data ++ [dat] - existing = Map.put(existing, :impls, existing_protocol_data) - Map.put(state, module_data.implements, existing) - end - end) - end - - defp update_protocols(grouped_protocol_data, opts) do - Enum.map(grouped_protocol_data, fn - ({ protocol_name, %{ protocol: protocol, impls: impls } }) -> - make_defimpl(protocol_name, protocol, Enum.uniq(impls), opts) - - ({ protocol_name, %{ protocol: protocol } }) -> - make_defimpl(protocol_name, protocol, [], opts) - end) - end - - defp make_defimpl(name, {_, protocol}, implementations, compiler_opts) do - declarator = JS.variable_declarator( - JS.identifier("impls"), - JS.array_expression([]) - ) - - declaration = JS.variable_declaration([declarator], :let) - - default = JS.export_default_declaration(JS.identifier("impls")) - - protocol_name = Atom.to_string(name) - - app_name = protocol.app - - body = Enum.map(implementations, fn({_, impl_data}) -> - x = Utils.quoted_to_name(impl_data.for) - members = ["Elixir"] ++ Module.split(name) ++ ["DefImpl", "Elixir"] ++ Module.split(x) ++ ["__load"] - ast = JS.call_expression( - Identifier.make_namespace_members(members), - [JS.identifier("Elixir")] - ) - - - JS.call_expression( - JS.member_expression( - JS.identifier("impls"), - JS.identifier("push") - ), - [ast] - ) - end) - - module_name = String.to_atom(protocol_name <> ".DefImpl") - module_data = %{ - name: name, - module: String.to_atom(protocol_name <> ".DefImpl"), - body: [declaration] ++ body, - exports: JS.identifier("impls"), - app: app_name, - type: :consolidated, - protocol: name - } - - {module_name, module_data} - end - -end diff --git a/lib/elixir_script/passes/create_js_modules.ex b/lib/elixir_script/passes/create_js_modules.ex deleted file mode 100644 index a0cff524..00000000 --- a/lib/elixir_script/passes/create_js_modules.ex +++ /dev/null @@ -1,169 +0,0 @@ -defmodule ElixirScript.Passes.CreateJSModules do - @moduledoc false - alias ElixirScript.Translator.Utils - alias ESTree.Tools.Builder, as: JS - - def execute(compiler_data, opts) do - namespace_modules = Enum.reduce(compiler_data.data, [], fn - ({_, %{load_only: true} = module_data}, acc) -> - acc - - ({module_name, module_data}, acc) -> - if module_data.app == :elixir && opts.import_standard_libs == false do - acc - else - body = generate_namespace_module( - module_data.type, - module_name, - Map.get(module_data, :javascript_module, module_data), - opts, - compiler_data.state - ) - - acc ++ List.wrap(body) - end - end) - - compiled = compile(namespace_modules, opts) - Map.put(compiler_data, :compiled, compiled) - end - - defp generate_namespace_module(:consolidated, module_name, js_module, opts, state) do - env = ElixirScript.Translator.LexicalScope.module_scope( - js_module.name, - Utils.name_to_js_file_name(js_module.name) <> ".js", - opts.env, - state, - opts) - - body = ElixirScript.ModuleSystems.Namespace.build( - module_name, - js_module.body, - js_module.exports, - env - ) - - body - end - - defp generate_namespace_module(_, module_name, js_module, _, _) do - body = ElixirScript.ModuleSystems.Namespace.build( - module_name, - js_module.body, - js_module.exports, - js_module.env - ) - - body - end - - def compile(body, opts) do - declarator = JS.variable_declarator( - JS.identifier("Elixir"), - JS.object_expression([]) - ) - - elixir = JS.variable_declaration([declarator], :const) - - table_additions = Enum.map(opts.js_modules, fn - {module, path} -> add_import_to_table(module) - {module, path, _} -> add_import_to_table(module) - end) - - ast = opts.module_formatter.build( - [], - opts.js_modules, - [elixir, create_atom_table(), start, load] ++ table_additions ++ body, - JS.identifier("Elixir") - ) - - ast - end - - def start do - JS.assignment_expression( - :=, - JS.member_expression( - JS.identifier("Elixir"), - JS.identifier("start") - ), - JS.function_expression( - [JS.identifier(:app), JS.identifier(:args)], - [], - JS.block_statement([ - JS.call_expression( - JS.member_expression( - JS.call_expression( - JS.member_expression( - JS.identifier(:app), - JS.identifier("__load") - ), - [JS.identifier("Elixir")] - ), - JS.identifier("start") - ), - [ElixirScript.Translator.Primitive.make_atom(:normal), JS.identifier(:args)] - ) - ]) - ) - ) - end - - def load do - JS.assignment_expression( - :=, - JS.member_expression( - JS.identifier("Elixir"), - JS.identifier("load") - ), - JS.function_expression( - [JS.identifier(:module)], - [], - JS.block_statement([ - JS.return_statement( - JS.call_expression( - JS.member_expression( - JS.identifier(:module), - JS.identifier("__load") - ), - [JS.identifier("Elixir")] - ) - ) - ]) - ) - ) - end - - defp create_atom_table() do - JS.assignment_expression( - :=, - JS.member_expression( - JS.identifier("Elixir"), - JS.identifier("__table__") - ), - JS.object_expression([]) - ) - end - - defp add_import_to_table(module_name) do - ref = ElixirScript.Translator.Identifier.make_namespace_members(module_name) - JS.assignment_expression( - :=, - JS.member_expression( - JS.member_expression( - JS.identifier("Elixir"), - JS.identifier("__table__") - ), - JS.call_expression( - JS.member_expression( - JS.identifier("Symbol"), - JS.identifier("for") - ), - [JS.literal(ref.name)] - ), - true - ), - ref - ) - end -end diff --git a/lib/elixir_script/passes/find_functions.ex b/lib/elixir_script/passes/find_functions.ex deleted file mode 100644 index 0d627984..00000000 --- a/lib/elixir_script/passes/find_functions.ex +++ /dev/null @@ -1,92 +0,0 @@ -defmodule ElixirScript.Passes.FindFunctions do - @moduledoc false - @function_types [:def, :defp, :defgen, :defgenp, :defmacro, :defmacrop] - - def execute(data, _) do - new_data = Enum.map(data.data, fn { module_name, module_data } -> - - %{ - def: functions, - defp: private_functions, - defgen: generators, - defgenp: private_generators, - defmacro: macros, - defmacrop: private_macros, - defdelegate: delegates - } = get_functions_from_module(module_data.ast) - - module_data = Map.put(module_data, :functions, functions ++ generators ++ delegates) - |> Map.put(:private_functions, private_functions ++ private_generators) - |> Map.put(:macros, macros) - |> Map.put(:private_macros, private_macros) - - {module_name, module_data} - end) - - %{data | data: new_data} - end - - defp get_functions_from_module({:__block__, _, list}) do - Enum.reduce(list, new_function_map(), fn - ({type, _, [{:when, _, [{name, _, params} | _guards] }, _] }, state) when type in @function_types and is_atom(params) -> - arity = 0 - add_function_to_map(state, type, name, arity) - - ({type, _, [{:when, _, [{name, _, params} | _guards] }, _] }, state) when type in @function_types -> - arity = if is_nil(params), do: 0, else: length(params) - add_function_to_map(state, type, name, arity) - - ({type, _, [{name, _, params}, _]}, state) when type in @function_types and is_atom(params) -> - arity = 0 - add_function_to_map(state, type, name, arity) - - ({type, _, [{name, _, params}, _]}, state) when type in @function_types -> - arity = if is_nil(params), do: 0, else: length(params) - add_function_to_map(state, type, name, arity) - - ({type, _, [{name, _, params}]}, state) when is_atom(params) and type in @function_types -> - arity = 0 - add_function_to_map(state, type, name, arity) - - ({type, _, [{name, _, params}]}, state) when type in @function_types -> - arity = length(params) - add_function_to_map(state, type, name, arity) - - ({:defdelegate, _, [{name, _, params}], _}, state) -> - arity = length(params) - add_function_to_map(state, :defdelegate, name, arity) - - _, state -> - state - - end) - end - - defp new_function_map() do - %{ - def: Keyword.new, - defp: Keyword.new, - defgen: Keyword.new, - defgenp: Keyword.new, - defmacro: Keyword.new, - defmacrop: Keyword.new, - defdelegate: Keyword.new - } - end - - defp get_functions_from_module(_) do - new_function_map() - end - - defp add_function_to_map(map, type, name, arity) do - list = Map.get(map, type) - - if {name, arity} in list do - map - else - Map.put(map, type, list ++ [{ name, arity }]) - end - end - - -end diff --git a/lib/elixir_script/passes/find_load_only.ex b/lib/elixir_script/passes/find_load_only.ex deleted file mode 100644 index 86fb0754..00000000 --- a/lib/elixir_script/passes/find_load_only.ex +++ /dev/null @@ -1,33 +0,0 @@ -defmodule ElixirScript.Passes.FindLoadOnly do - @moduledoc false - - def execute(compiler_data, opts) do - data = compiler_data.data - |> Enum.map(fn({module_name, module_data}) -> - - {_, load_only} = Macro.prewalk(module_data.ast, false, fn - ({:@, _, [{:load_only, _, [true]}]} = ast, state) -> - {ast, true} - - ({:@, _, [{:load_only, _, [false]}]} = ast, state) -> - {ast, false} - - ({:@, _, [{:load_only, _, []}]} = ast, state) -> - {ast, true} - - (ast, state) -> - {ast, state} - end) - - { module_name, Map.put(module_data, :load_only, load_only) } - - end) - - - - %{ compiler_data | data: data } - end - - - -end diff --git a/lib/elixir_script/passes/find_modules.ex b/lib/elixir_script/passes/find_modules.ex deleted file mode 100644 index 143a77f5..00000000 --- a/lib/elixir_script/passes/find_modules.ex +++ /dev/null @@ -1,181 +0,0 @@ -defmodule ElixirScript.Passes.FindModules do - @moduledoc false - alias ElixirScript.Translator.Utils - alias ElixirScript.Translator.State - - @spec execute(map, map) :: map - def execute(compiler_data, opts) do - data = Enum.reduce(compiler_data.data, [], fn(data, list) -> - quoted = update_quoted(data.ast) - { _, modules } = Macro.postwalk(quoted, [], &get_defmodules(&1, &2, opts, compiler_data)) - - modules = Enum.map(modules, fn(x) -> { x.name, Map.merge(data, x) } end) - list ++ modules - end) - - Map.put(compiler_data, :data, data) - end - - defp get_defmodules({:defprotocol, _, [{:__aliases__, _, _} = the_alias, [do: {:__block__, _, _} = block]]} = ast, state, _, _) do - s = %{ name: Utils.quoted_to_name(the_alias), type: :protocol, ast: block } - { ast, state ++ [s] } - end - - defp get_defmodules({:defprotocol, _, [{:__aliases__, _, _} = the_alias, [do: spec]]} = ast, state, _, _) do - s = %{ name: Utils.quoted_to_name(the_alias), type: :protocol, ast: {:__block__, [], [spec]} } - { ast, state ++ [s] } - end - - defp get_defmodules({:defimpl, _, [ the_alias, [for: {:__aliases__, _, type_name} = type], [do: {:__block__, context, spec}] ]} = ast, state, _, compiler_data) do - {:__aliases__, _, original_name} = Utils.name_to_quoted(State.get_module_name(compiler_data.state, the_alias)) - name = original_name ++ [DefImpl] ++ [Elixir] ++ type_name - s = %{name: Utils.quoted_to_name({:__aliases__, [], name}), type: :impl, for: type, ast: {:__block__, context, spec}, implements: Utils.quoted_to_name({:__aliases__, [], original_name}) } - { ast, state ++ [s] } - end - - defp get_defmodules({:defimpl, _, [ the_alias, [for: {:__aliases__, _, type_name} = type], [do: spec] ]} = ast, state, _, compiler_data) do - {:__aliases__, _, original_name} = Utils.name_to_quoted(State.get_module_name(compiler_data.state, the_alias)) - name = original_name ++ [DefImpl] ++ [Elixir] ++ type_name - s = %{name: Utils.quoted_to_name({:__aliases__, [], name}), type: :impl, for: type, ast: {:__block__, [], [spec]}, implements: Utils.quoted_to_name({:__aliases__, [], original_name}) } - { ast, state ++ [s] } - end - - defp get_defmodules({:defmodule, _, [{:__aliases__, _, [:ElixirScript, :Temp]}, [do: body]]} = ast, state, _, _) do - s = %{name: ElixirScript.Temp, type: :module, ast: body } - { ast, state ++ [s] } - end - - - defp get_defmodules({:defmodule, _, [{:__aliases__, _, _}, [do: _]]} = ast, state, opts, _) do - { ast, do_module_processing(ast, state, opts) } - end - - defp get_defmodules(ast, state, _, _) do - { ast, state } - end - - - defp do_module_processing({:defmodule, _context1, [{:__aliases__, _, name} = the_alias, [do: body]]}, state, opts) do - { body, inner_modules } = make_inner_module_aliases(body) - - aliases = Enum.map(inner_modules, fn - ({:defmodule, _, [{:__aliases__, _, inner_module_name}, [do: _inner_module_body]]}) -> - { :alias, [], [{:__aliases__, [alias: false], name ++ inner_module_name}, [as: {:__aliases__, [alias: false], inner_module_name }] ] } - end) - - state = do_module_processing_state(inner_modules, state, name, aliases, opts) - - [%{name: Utils.quoted_to_name(the_alias), type: :module, ast: do_module_processing_body(body, aliases, opts) }] ++ state - end - - defp do_module_processing_state(inner_modules, state, name, aliases, opts) do - Enum.reduce(inner_modules, state, fn - ({:defmodule, context1, [{:__aliases__, context2, inner_module_name}, [do: inner_module_body]]}, state) -> - - module_name = Utils.quoted_to_name({:__aliases__, [], tl(name) ++ inner_module_name}) - state = Enum.reject(state, fn(x) -> x.name == module_name end) - - this_module_aliases = aliases -- [{ :alias, [], [{:__aliases__, [alias: false], name ++ inner_module_name}, [as: {:__aliases__, [alias: false], inner_module_name }] ] }] - - do_module_processing( - {:defmodule, context1, [{:__aliases__, context2, name ++ inner_module_name}, [do: add_aliases_to_body(inner_module_body, this_module_aliases)]]}, - state, opts) - end) - end - - defp do_module_processing_body(body, aliases, opts) do - body - |> case do - {:__block__, context, list } -> - list = - list - |> Enum.map(fn - {:use, _, [module, _] } = using -> - {:use, handle_use_expression(using, module, opts) } - {:use, _, [module] } = using -> - {:use, handle_use_expression(using, module, opts) } - ast -> - {:expanded, ast} - end) - |> Enum.reduce([], fn - {:use, {:__block__, _, list}}, state -> - state ++ list - {:use, ast}, state -> - state ++ [ast] - {:expanded, ast}, state -> - state ++ [ast] - end) - - {:__block__, context, list} - _ -> - body - end - |> add_aliases_to_body(aliases) - end - - defp add_aliases_to_body(body, aliases) do - case body do - { :__block__, context, body } -> - { :__block__, context, aliases ++ List.wrap(body) } - _ -> - { :__block__, [], aliases ++ List.wrap(body) } - end - end - - defp make_inner_module_aliases(body) do - case body do - nil -> - { { :__block__, [], [] }, [] } - - {:__block__, context, list2 } -> - { list2, inner_modules } = Enum.partition(list2, fn - {:defmodule, _, [{:__aliases__, _, _inner_module_name}, [do: _inner_module_body]]} -> - false - _ -> - true - end) - - { {:__block__, context, list2}, inner_modules } - {:defmodule, _, [{:__aliases__, context, _inner_module_name}, [do: _inner_module_body]]} = mod -> - { {:__block__, context, [] }, [mod] } - _ -> - { body, [] } - end - end - - defp handle_use_expression(using_ast, module, opts) do - module = Utils.quoted_to_name(module) - - eval = """ - require #{inspect module} - __ENV__ - """ - {env, _} = Code.eval_string(eval, [], opts.env) - - - case Macro.expand(using_ast, env) do - {:__block__, _, - [{:__block__, _, - [{:require, _, _}, - {{:., _, [_, :__using__]}, _, _} = ast]}]} -> - Macro.expand_once(ast, env) - end - end - - defp update_quoted(quoted) do - Macro.prewalk(quoted, fn - ({name, context, parms}) -> - context = - if context[:import] == Kernel do - Keyword.update!(context, :import, fn(_) -> ElixirScript.Kernel end) - else - context - end - - {name, context, parms} - (x) -> - x - end) - end - -end diff --git a/lib/elixir_script/next/passes/find_used_functions.ex b/lib/elixir_script/passes/find_used_functions.ex similarity index 100% rename from lib/elixir_script/next/passes/find_used_functions.ex rename to lib/elixir_script/passes/find_used_functions.ex diff --git a/lib/elixir_script/next/passes/find_used_modules.ex b/lib/elixir_script/passes/find_used_modules.ex similarity index 100% rename from lib/elixir_script/next/passes/find_used_modules.ex rename to lib/elixir_script/passes/find_used_modules.ex diff --git a/lib/elixir_script/passes/handle_output.ex b/lib/elixir_script/passes/handle_output.ex deleted file mode 100644 index eb956cdf..00000000 --- a/lib/elixir_script/passes/handle_output.ex +++ /dev/null @@ -1,62 +0,0 @@ -defmodule ElixirScript.Passes.HandleOutput do - @moduledoc false - alias ElixirScript.Translator.State - @generated_name "Elixir.App.js" - - def execute(compiler_data, opts) do - State.stop(compiler_data.state) - out(compiler_data, opts) - end - - defp out(compiler_output, %{output: nil} = compiler_opts) do - compiler_output - |> process_include_path(compiler_opts) - end - - defp out(compiler_output, %{output: :stdout} = compiler_opts) do - out = compiler_output - |> process_include_path(compiler_opts) - - code = case out do - {code, _} -> code - code -> code - end - - IO.write(concat(code)) - end - - defp out(compiler_output, %{output: output_path, core_path: _}) do - file_name = get_js_path(output_path) - - if !File.exists?(Path.dirname(file_name)) do - File.mkdir_p!(Path.dirname(file_name)) - end - - File.write!(file_name, concat(compiler_output.generated)) - end - - defp concat(code) do - "'use strict';\n" <> ElixirScript.get_bootstrap_js("iife") <> "\n" <> code - end - - def get_js_path(nil), do: @generated_name - def get_js_path(:stdout), do: @generated_name - - def get_js_path(output_path) do - case Path.extname(output_path) do - ".js" -> - output_path - _ -> - Path.join([output_path, @generated_name]) - end - end - - defp process_include_path(compiler_output, compiler_opts) do - case compiler_opts.include_path do - true -> - {compiler_output.generated, get_js_path(compiler_opts.output)} - false -> - compiler_output.generated - end - end -end diff --git a/lib/elixir_script/passes/handle_overridables.ex b/lib/elixir_script/passes/handle_overridables.ex deleted file mode 100644 index 44ae2b90..00000000 --- a/lib/elixir_script/passes/handle_overridables.ex +++ /dev/null @@ -1,87 +0,0 @@ -defmodule ElixirScript.Passes.HandleOverridables do - @moduledoc false - @function_types [:def, :defp] - - def execute(compiler_data, opts) do - new_data = Enum.map(compiler_data.data, fn { module_name, module_data } -> - overridables = get_overridables(module_data.ast) - ast = handle_overridable(module_data.ast, overridables) - module_data = Map.put(module_data, :ast, ast) - - {module_name, module_data} - end) - - Map.put(compiler_data, :data, new_data) - end - - defp get_overridables({:__block__, [], body}) do - defover = Enum.find(body, fn - {:defoverridable, _, _} -> - true - _ -> - false - end) - - if is_nil(defover) do - [] - else - {:defoverridable, _, [overridables]} = defover - overridables - end - end - - defp handle_overridable(ast, []) do - ast - end - - defp handle_overridable({:__block__, [], body}, overridables) do - result = body - |> Enum.reduce(%{overridables: [], overridable_found: false, body: []}, fn - {type, def_context, [{name, context, params}, function_body] } = ast, %{overridable_found: false} = acc when type in @function_types -> - Map.put(acc, :overridables, acc.overridables ++ [ast]) - - {:defoverridable, _, _}, acc -> - Map.put(acc, :overridable_found, true) - x, acc -> - Map.put(acc, :body, acc.body ++ [x]) - end) - - processed_overridables = Enum.map(result.overridables, fn - {type, def_context, [{name, context, params}, function_body] } = ast when type in @function_types -> - arity = get_arity(params) - - found = Enum.any?(result.body, fn - {type, _, [{name_from_body, _, params_from_body}, _] } -> - if {name, arity} == {name_from_body, get_arity(params_from_body)} do - true - else - false - end - _ -> - false - end) - - if found do - super_name = String.to_atom("__super__" <> to_string(name)) - {:defp, def_context, [{super_name, context, params}, function_body] } - else - ast - end - end) - - body = processed_overridables ++ result.body - {:__block__, [], body} - end - - defp get_arity(params) do - cond do - is_nil(params) -> - 0 - is_atom(params) -> - 0 - true -> - length(params) - end - end - -end \ No newline at end of file diff --git a/lib/elixir_script/passes/init.ex b/lib/elixir_script/passes/init.ex deleted file mode 100644 index 3ac9d5d9..00000000 --- a/lib/elixir_script/passes/init.ex +++ /dev/null @@ -1,10 +0,0 @@ -defmodule ElixirScript.Passes.Init do - @moduledoc false - alias ElixirScript.Translator.State - - def execute(compiler_data, opts) do - {:ok, pid} = State.start_link(opts, []) - Map.put(compiler_data, :state, pid) - end - -end diff --git a/lib/elixir_script/passes/java_script_ast.ex b/lib/elixir_script/passes/java_script_ast.ex deleted file mode 100644 index 9b0ab7e0..00000000 --- a/lib/elixir_script/passes/java_script_ast.ex +++ /dev/null @@ -1,43 +0,0 @@ -defmodule ElixirScript.Passes.JavaScriptAST do - @moduledoc false - alias ElixirScript.Translator.Utils - alias ElixirScript.Translator.State - - def execute(compiler_data, opts) do - - State.set_module_data(compiler_data.state, compiler_data.data) - State.set_loaded_modules(compiler_data.state, Map.get(compiler_data, :loaded_modules, [])) - - data = compiler_data.state - |> State.get_module_data - |> Enum.reject(fn {_, module_data} -> - module_data.app == :elixir && opts.import_standard_libs == false - end) - |> Enum.map(fn({module_name, module_data}) -> - module_data = compile(module_data, opts, compiler_data.state) - {module_name, module_data} - end) - - %{ compiler_data | data: data } - end - - defp compile(%{load_only: true} = module_data, opts, state) do - module_data - end - - defp compile(module_data, opts, state) do - - env = ElixirScript.Translator.LexicalScope.module_scope(module_data.name, Utils.name_to_js_file_name(module_data.name) <> ".js", opts.env, state, opts) - - module = case module_data.type do - :module -> - ElixirScript.Translator.Defmodule.make_module(module_data.name, module_data.ast, env) - :protocol -> - ElixirScript.Translator.Defprotocol.make(module_data.name, module_data.functions, env) - :impl -> - ElixirScript.Translator.Defimpl.make(module_data.name, module_data.for, module_data.ast, env) - end - - Map.put(module_data, :javascript_module, module) - end -end diff --git a/lib/elixir_script/passes/java_script_code.ex b/lib/elixir_script/passes/java_script_code.ex deleted file mode 100644 index 37e212ba..00000000 --- a/lib/elixir_script/passes/java_script_code.ex +++ /dev/null @@ -1,32 +0,0 @@ -defmodule ElixirScript.Passes.JavaScriptCode do - @moduledoc false - alias ESTree.Tools.Builder - alias ESTree.Tools.Generator - - def execute(compiler_data, _) do - parent = self - - js_code = compiler_data.compiled - |> List.wrap - |> Builder.program - |> prepare_js_ast - |> Generator.generate - - Map.put(compiler_data, :generated, js_code) - end - - defp prepare_js_ast(js_ast) do - case js_ast do - modules when is_list(modules) -> - modules - |> Enum.reduce([], &(&2 ++ &1.body)) - |> Builder.program - %ElixirScript.Translator.Group{body: body} -> - Builder.program(body) - %ElixirScript.Translator.Empty{} -> - Builder.program([]) - _ -> - js_ast - end - end -end diff --git a/lib/elixir_script/passes/load_modules.ex b/lib/elixir_script/passes/load_modules.ex deleted file mode 100644 index 85e2edb2..00000000 --- a/lib/elixir_script/passes/load_modules.ex +++ /dev/null @@ -1,27 +0,0 @@ -defmodule ElixirScript.Passes.LoadModules do - @moduledoc false - def execute(compiler_data, _) do - ex_files = compiler_data.data - |> Enum.filter(fn - {_, %{app: :elixir}} -> - false - %{app: :elixir} -> - false - _ -> true - end) - |> Enum.map(fn - { _, %{path: path} } -> path - %{path: path} -> path - end) - - loaded_modules = case Enum.reverse(ex_files) do - [] -> - [] - files -> - Kernel.ParallelCompiler.files(files) - end - - Map.put(compiler_data, :loaded_modules, loaded_modules) - end - -end diff --git a/lib/elixir_script/passes/load_modules_for_quoted.ex b/lib/elixir_script/passes/load_modules_for_quoted.ex deleted file mode 100644 index 7c737dd1..00000000 --- a/lib/elixir_script/passes/load_modules_for_quoted.ex +++ /dev/null @@ -1,28 +0,0 @@ -defmodule ElixirScript.Passes.LoadModulesForQuoted do - @moduledoc false - def execute(compiler_data, _) do - quoted = compiler_data.data - |> Enum.filter(fn - {_, %{app: :elixir}} -> - false - %{app: :elixir} -> - false - _ -> true - end) - |> Enum.map(fn - {_, %{ast: ast}} -> ast - %{ast: ast} -> ast - end) - - loaded_modules = Map.get(compiler_data, :loaded_modules, []) - - loaded_modules_from_quoted = quoted - |> Enum.map(&Code.compile_quoted(&1)) - |> List.flatten - |> Enum.map(fn {mod, _} -> mod end) - - - Map.put(compiler_data, :loaded_modules, loaded_modules ++ loaded_modules_from_quoted) - end - -end \ No newline at end of file diff --git a/lib/elixir_script/next/passes/output.ex b/lib/elixir_script/passes/output.ex similarity index 85% rename from lib/elixir_script/next/passes/output.ex rename to lib/elixir_script/passes/output.ex index cec29f28..9b175f90 100644 --- a/lib/elixir_script/next/passes/output.ex +++ b/lib/elixir_script/passes/output.ex @@ -33,20 +33,22 @@ defmodule ElixirScript.Output do end defp concat(code) do - bootstrap_code = ElixirScript.get_bootstrap_js("iife") + bootstrap_code = get_bootstrap_js() "'use strict';\n#{bootstrap_code}\n#{code}" end + defp get_bootstrap_js() do + operating_path = Path.join([Mix.Project.build_path, "lib", "elixir_script", "priv"]) + path = Path.join([operating_path, "build", "iife", "Elixir.Bootstrap.js"]) + File.read!(path) + end + defp prepare_js_ast(js_ast) do case js_ast do modules when is_list(modules) -> modules |> Enum.reduce([], &(&2 ++ &1.body)) |> Builder.program - %ElixirScript.Translator.Group{body: body} -> - Builder.program(body) - %ElixirScript.Translator.Empty{} -> - Builder.program([]) _ -> js_ast end diff --git a/lib/elixir_script/next/passes/output/js_module.ex b/lib/elixir_script/passes/output/js_module.ex similarity index 92% rename from lib/elixir_script/next/passes/output/js_module.ex rename to lib/elixir_script/passes/output/js_module.ex index 60eba1e9..c0aa3346 100644 --- a/lib/elixir_script/next/passes/output/js_module.ex +++ b/lib/elixir_script/passes/output/js_module.ex @@ -27,6 +27,14 @@ defmodule ElixirScript.Output.JSModule do end def start do + normal = J.call_expression( + J.member_expression( + J.identifier("Symbol"), + J.identifier("for") + ), + [J.literal("normal")] + ) + J.assignment_expression( :=, J.member_expression( @@ -48,7 +56,7 @@ defmodule ElixirScript.Output.JSModule do ), J.identifier("start") ), - [ElixirScript.Translator.Primitive.make_atom(:normal), J.identifier(:args)] + [normal, J.identifier(:args)] ) ]) ) diff --git a/lib/elixir_script/passes/remove_unused.ex b/lib/elixir_script/passes/remove_unused.ex deleted file mode 100644 index 728f511b..00000000 --- a/lib/elixir_script/passes/remove_unused.ex +++ /dev/null @@ -1,31 +0,0 @@ -defmodule ElixirScript.Passes.RemoveUnused do - @moduledoc false - alias ElixirScript.Translator.Utils - alias ElixirScript.Translator.State - - def execute(compiler_data, %{remove_unused: false}) do - compiler_data - end - - def execute(compiler_data, opts) do - module_refs = State.list_module_references(compiler_data.state) - - data = Enum.reject(compiler_data.data, fn - {_, %{type: :impl} = module_data} -> - length(Keyword.get(module_refs, module_data.implements, [])) == 0 - {_, %{type: :consolidated} = module_data} -> - length(Keyword.get(module_refs, module_data.protocol, [])) == 0 - {module, module_data} -> - cond do - Enum.member?(module_data.functions, {:start, 2}) -> - false - length(Keyword.get(module_refs, module, [])) > 0 -> - false - true -> - true - end - end) - - %{ compiler_data | data: data } - end -end \ No newline at end of file diff --git a/lib/elixir_script/next/passes/translate.ex b/lib/elixir_script/passes/translate.ex similarity index 100% rename from lib/elixir_script/next/passes/translate.ex rename to lib/elixir_script/passes/translate.ex diff --git a/lib/elixir_script/next/passes/translate/clause.ex b/lib/elixir_script/passes/translate/clause.ex similarity index 100% rename from lib/elixir_script/next/passes/translate/clause.ex rename to lib/elixir_script/passes/translate/clause.ex diff --git a/lib/elixir_script/next/passes/translate/form.ex b/lib/elixir_script/passes/translate/form.ex similarity index 100% rename from lib/elixir_script/next/passes/translate/form.ex rename to lib/elixir_script/passes/translate/form.ex diff --git a/lib/elixir_script/next/passes/translate/forms/bitstring.ex b/lib/elixir_script/passes/translate/forms/bitstring.ex similarity index 96% rename from lib/elixir_script/next/passes/translate/forms/bitstring.ex rename to lib/elixir_script/passes/translate/forms/bitstring.ex index 14af8f2b..dfe5f495 100644 --- a/lib/elixir_script/next/passes/translate/forms/bitstring.ex +++ b/lib/elixir_script/passes/translate/forms/bitstring.ex @@ -57,10 +57,10 @@ defmodule ElixirScript.Translate.Forms.Bitstring do do_compile_element({:binary, translate_element(element, state)}) end - def translate_element(ElixirScript.Translator.PatternMatching, _) do + def translate_element(ElixirScript.Translate.Forms.Pattern.Patterns, _) do JS.object_expression([JS.property( JS.literal("value"), - ElixirScript.Translator.PatternMatching.parameter() + ElixirScript.Translate.Forms.Pattern.Patterns.parameter() ) ]) end diff --git a/lib/elixir_script/next/passes/translate/forms/for.ex b/lib/elixir_script/passes/translate/forms/for.ex similarity index 100% rename from lib/elixir_script/next/passes/translate/forms/for.ex rename to lib/elixir_script/passes/translate/forms/for.ex diff --git a/lib/elixir_script/next/passes/translate/forms/js.ex b/lib/elixir_script/passes/translate/forms/js.ex similarity index 100% rename from lib/elixir_script/next/passes/translate/forms/js.ex rename to lib/elixir_script/passes/translate/forms/js.ex diff --git a/lib/elixir_script/next/passes/translate/forms/map.ex b/lib/elixir_script/passes/translate/forms/map.ex similarity index 100% rename from lib/elixir_script/next/passes/translate/forms/map.ex rename to lib/elixir_script/passes/translate/forms/map.ex diff --git a/lib/elixir_script/next/passes/translate/forms/match.ex b/lib/elixir_script/passes/translate/forms/match.ex similarity index 100% rename from lib/elixir_script/next/passes/translate/forms/match.ex rename to lib/elixir_script/passes/translate/forms/match.ex diff --git a/lib/elixir_script/next/passes/translate/forms/pattern.ex b/lib/elixir_script/passes/translate/forms/pattern.ex similarity index 98% rename from lib/elixir_script/next/passes/translate/forms/pattern.ex rename to lib/elixir_script/passes/translate/forms/pattern.ex index 14e4f4f9..89587f5f 100644 --- a/lib/elixir_script/next/passes/translate/forms/pattern.ex +++ b/lib/elixir_script/passes/translate/forms/pattern.ex @@ -1,5 +1,5 @@ defmodule ElixirScript.Translate.Forms.Pattern do - alias ElixirScript.Translator.PatternMatching, as: PM + alias ElixirScript.Translate.Forms.Pattern.Patterns, as: PM alias ESTree.Tools.Builder, as: J alias ElixirScript.Translate.Form alias ElixirScript.Translate.Forms.{Bitstring} @@ -164,7 +164,7 @@ defmodule ElixirScript.Translate.Forms.Pattern do elements = Enum.map(elements, fn ({:::, context, [{ _, _, params }, options]}) when is_atom(params) -> - Bitstring.compile_element({:::, context, [ElixirScript.Translator.PatternMatching, options]}, state) + Bitstring.compile_element({:::, context, [ElixirScript.Translate.Forms.Pattern.Patterns, options]}, state) x -> Bitstring.compile_element(x, state) end) diff --git a/lib/elixir_script/passes/translate/forms/pattern/patterns.ex b/lib/elixir_script/passes/translate/forms/pattern/patterns.ex new file mode 100644 index 00000000..d914080f --- /dev/null +++ b/lib/elixir_script/passes/translate/forms/pattern/patterns.ex @@ -0,0 +1,114 @@ +defmodule ElixirScript.Translate.Forms.Pattern.Patterns do + alias ESTree.Tools.Builder, as: J + + @patterns J.member_expression( + J.member_expression( + J.identifier("Bootstrap"), + J.identifier("Core") + ), + J.identifier("Patterns") + ) + + @wildcard J.member_expression( + @patterns, + J.identifier(:wildcard) + ) + + @parameter J.member_expression( + @patterns, + J.identifier(:variable) + ) + + @head_tail J.member_expression( + @patterns, + J.identifier(:headTail) + ) + + @starts_with J.member_expression( + @patterns, + J.identifier(:startsWith) + ) + + @capture J.member_expression( + @patterns, + J.identifier(:capture) + ) + + @bound J.member_expression( + @patterns, + J.identifier(:bound) + ) + + @_type J.member_expression( + @patterns, + J.identifier(:type) + ) + + @bitstring_match J.member_expression( + @patterns, + J.identifier(:bitStringMatch) + ) + + def wildcard() do + J.call_expression( + @wildcard, + [] + ) + end + + def parameter() do + J.call_expression( + @parameter, + [] + ) + end + + def parameter(default_value) do + J.call_expression( + @parameter, + [default_value] + ) + end + + def head_tail(headParameter, tailParameter) do + J.call_expression( + @head_tail, + [headParameter, tailParameter] + ) + end + + def starts_with(prefix) do + J.call_expression( + @starts_with, + [J.literal(prefix)] + ) + end + + def capture(value) do + J.call_expression( + @capture, + [value] + ) + end + + def bound(value) do + J.call_expression( + @bound, + [value] + ) + end + + def type(prototype, value) do + J.call_expression( + @_type, + [prototype, value] + ) + end + + def bitstring_match(values) do + J.call_expression( + @bitstring_match, + values + ) + end +end \ No newline at end of file diff --git a/lib/elixir_script/next/passes/translate/forms/receive.ex b/lib/elixir_script/passes/translate/forms/receive.ex similarity index 100% rename from lib/elixir_script/next/passes/translate/forms/receive.ex rename to lib/elixir_script/passes/translate/forms/receive.ex diff --git a/lib/elixir_script/next/passes/translate/forms/remote.ex b/lib/elixir_script/passes/translate/forms/remote.ex similarity index 100% rename from lib/elixir_script/next/passes/translate/forms/remote.ex rename to lib/elixir_script/passes/translate/forms/remote.ex diff --git a/lib/elixir_script/next/passes/translate/forms/try.ex b/lib/elixir_script/passes/translate/forms/try.ex similarity index 100% rename from lib/elixir_script/next/passes/translate/forms/try.ex rename to lib/elixir_script/passes/translate/forms/try.ex diff --git a/lib/elixir_script/next/passes/translate/function.ex b/lib/elixir_script/passes/translate/function.ex similarity index 100% rename from lib/elixir_script/next/passes/translate/function.ex rename to lib/elixir_script/passes/translate/function.ex diff --git a/lib/elixir_script/next/passes/translate/identifier.ex b/lib/elixir_script/passes/translate/identifier.ex similarity index 100% rename from lib/elixir_script/next/passes/translate/identifier.ex rename to lib/elixir_script/passes/translate/identifier.ex diff --git a/lib/elixir_script/next/passes/translate/module.ex b/lib/elixir_script/passes/translate/module.ex similarity index 100% rename from lib/elixir_script/next/passes/translate/module.ex rename to lib/elixir_script/passes/translate/module.ex diff --git a/lib/elixir_script/next/passes/translate/protocol.ex b/lib/elixir_script/passes/translate/protocol.ex similarity index 100% rename from lib/elixir_script/next/passes/translate/protocol.ex rename to lib/elixir_script/passes/translate/protocol.ex diff --git a/lib/elixir_script/next/state.ex b/lib/elixir_script/state.ex similarity index 100% rename from lib/elixir_script/next/state.ex rename to lib/elixir_script/state.ex diff --git a/lib/elixir_script/translator.ex b/lib/elixir_script/translator.ex deleted file mode 100644 index d71914a9..00000000 --- a/lib/elixir_script/translator.ex +++ /dev/null @@ -1,738 +0,0 @@ -defmodule ElixirScript.Translator do - @moduledoc false - alias ElixirScript.Translator.Primitive - alias ElixirScript.Translator.Identifier - alias ElixirScript.Translator.Expression - alias ElixirScript.Translator.Match - alias ElixirScript.Translator.Map - alias ElixirScript.Translator.Function - alias ElixirScript.Translator.Call - alias ElixirScript.Translator.Def - alias ElixirScript.Translator.Capture - alias ElixirScript.Translator.Cond - alias ElixirScript.Translator.Case - alias ElixirScript.Translator.For - alias ElixirScript.Translator.Try - alias ElixirScript.Translator.With - alias ElixirScript.Translator.Block - alias ElixirScript.Translator.Struct - alias ElixirScript.Translator.Defmodule - alias ElixirScript.Translator.Utils - alias ElixirScript.Translator.Bitstring - alias ElixirScript.Translator.Quote - alias ElixirScript.Translator.Utils - alias ElixirScript.Translator.JS, as: JSLib - alias ESTree.Tools.Builder, as: JS - alias ElixirScript.Translator.Rewriter - - # A list of erlang modules. These are rewritten into equivalent - # JavaScript functions using ElixirScript.Translator.Rewriter - @erlang_modules [ - :erlang, - :maps, - :lists, - :gen, - :elixir_errors, - :supervisor, - :application, - :code, - :elixir_utils, - :file - ] - - @module_attributes_to_ignore [ - :doc, :moduledoc, :type, :typep, :spec, - :opaque, :callback, :macrocallback, :after_compile, - :before_compile, :behaviour, :compile, :file, - :on_definition, :on_load, :dialyzer, :vsn, :external_resource - ] - - @function_types [:def, :defp, :defgen, :defgenp] - @generator_types [:defgen, :defgenp] - - - @doc """ - Translates the given Elixir AST to JavaScript AST. The given `env` is a `ElixirScript.Macro.Env` - used to track the variables, imports, aliases, and scopes like `Macro.Env`. The JavaScript AST and - the an updated `ElixirScript.Macro.Env` is returned - """ - @spec translate(term, ElixirScript.Macro.Env.t) :: { ESTree.Node.t, ElixirScript.Macro.Env.t } - def translate(ast, env) do - do_translate(ast, env) - end - - - @doc """ - Same as `translate/2`, but returns only the JavaScript AST - """ - @spec translate!(term, ElixirScript.Macro.Env.t) :: ESTree.Node.t - def translate!(ast, env) do - { js_ast, _ } = translate(ast, env) - js_ast - end - - defp do_translate({{:., _, [{:__aliases__, _, [:JS]}, function_name]}, _, params }, env) when function_name in @generator_types do - do_translate({function_name, [], params}, env) - end - - defp do_translate({{:., _, [{:__aliases__, _, [:JS]}, function_name]}, _, params }, env) do - JSLib.translate_js_function(function_name, params, env) - end - - defp do_translate({{:., _, [{:__aliases__, context, [:JS | rest]}, function_name]}, _, params }, env) do - JSLib.translate_js_function({:__aliases__, context, rest}, function_name, params, env) - end - - defp do_translate({:__aliases__, context, [:JS | rest]}, env) do - JSLib.translate_js_module({:__aliases__, context, rest}, env) - end - - defp do_translate(ast, env) when is_number(ast) or is_binary(ast) or is_boolean(ast) or is_nil(ast) do - { Primitive.make_literal(ast), env } - end - - defp do_translate(ast, env) when is_atom(ast) do - { Primitive.make_atom(ast), env } - end - - defp do_translate([ {:|, _, [left, right] } ], env) do - quoted = quote do - [unquote(left)].concat(unquote(right)) - end - - translate(quoted, env) - end - - defp do_translate(ast, env) when is_list(ast) do - Primitive.make_list(ast, env) - end - - defp do_translate({ one, two }, env) do - quoted = quote do - JS.new(Bootstrap.Core.Tuple, [unquote(one), unquote(two)]) - end - - translate(quoted, env) - end - - defp do_translate({operator, _, [value]}, env) when operator in [:-, :!, :+] do - Expression.make_unary_expression(operator, value, env) - end - - defp do_translate({:not, _, [value]}, env) do - Expression.make_unary_expression(:!, value, env) - end - - defp do_translate({:"~~~", _, [value]}, env) do - Expression.make_unary_expression(:"~~~", value, env) - end - - defp do_translate({operator, _, [left, right]}, env) when operator in [:+, :-, :/, :*, :==, :!=, :&&, :||, :>, :<, :>=, :<=, :===, :!==, :"**"] do - Expression.make_binary_expression(operator, left, right, env) - end - - defp do_translate({:&&&, _, [left, right]}, env) do - Expression.make_binary_expression(:&, left, right, env) - end - - defp do_translate({:<<<, _, [left, right]}, env) do - Expression.make_binary_expression(:<, left, right, env) - end - - defp do_translate({:>>>, _, [left, right]}, env) do - Expression.make_binary_expression(:^, left, right, env) - end - - defp do_translate({:^^^, _, [left, right]}, env) do - Expression.make_binary_expression(:^, left, right, env) - end - - defp do_translate({:|||, _, [left, right]}, env) do - Expression.make_binary_expression(:|, left, right, env) - end - - defp do_translate({:and, _, [left, right]}, env) do - Expression.make_binary_expression(:&&, left, right, env) - end - - defp do_translate({:or, _, [left, right]}, env) do - Expression.make_binary_expression(:||, left, right, env) - end - - defp do_translate({:div, _, [left, right]}, env) do - Expression.make_binary_expression(:/, left, right, env) - end - - defp do_translate({:rem, _, [left, right]}, env) do - Expression.make_binary_expression(:%, left, right, env) - end - - defp do_translate({:<>, context, [left, right]}, env) do - translate({:+, context, [left, right]}, env) - end - - defp do_translate({:++, _, [left, right]}, env) do - translate({{:., [], [left, :concat]}, [], [right]}, env) - end - - defp do_translate({:&, _, [number]}, env) when is_number(number) do - { Identifier.make_identifier(String.to_atom("__#{number}")), env } - end - - defp do_translate({:&, _, [{:/, _, [{{:., _, [module_name, function_name]}, _, []}, arity]}]}, env) do - module_name = create_module_name(module_name, env) - js_ast = case module_name do - {mod, :local} -> - Capture.make_capture(mod, function_name, arity, env) - mod -> - Capture.make_extern_capture(mod, function_name, arity, env) - end - - { js_ast, env } - end - - defp do_translate({:&, _, [{:/, _, [{function_name, _, _}, arity]}]}, env) do - { Capture.make_capture(function_name, arity, env), env } - end - - defp do_translate({:&, _, [body]}, env) do - params = Capture.find_value_placeholders(body) |> List.flatten - Function.make_anonymous_function([{:->, [], [params, body]}], env) - end - - defp do_translate({:@, _, [{name, _, _}]}, env) - when name in @module_attributes_to_ignore do - { %ElixirScript.Translator.Empty{}, env } - end - - defp do_translate({:@, _, [{name, _, [value]}]}, env) do - { Defmodule.make_attribute(name, value, env), env } - end - - defp do_translate({:@, _, [{name, _, _}]}, env) do - { Identifier.make_identifier(name), env } - end - - defp do_translate({:%, _, [alias_info, data]}, env) do - module = case create_module_name(alias_info, env) do - {module, _} -> - module - module -> - module - end - Call.make_module_function_call(module, :__struct__, [data], env) - end - - defp do_translate({:%{}, _, [{:|, _, [map, data]}]}, env) do - Map.make_map_update(map, data, env) - end - - defp do_translate({:%{}, _, properties}, env) do - { Map.make_object(properties, env), env } - end - - defp do_translate({:<<>>, _, elements}, env) do - is_interpolated_string = Enum.all?(elements, fn(x) -> - case x do - b when is_binary(b) -> - true - {:::, _, [_target, {:binary, _, _}]} -> - true - _ -> - false - end - end) - - case is_interpolated_string do - true -> - Bitstring.make_interpolated_string(elements, env) - _ -> - Bitstring.make_bitstring(elements, env) - end - end - - defp do_translate({{:., _, [erlang_module, _]}, _, _} = erlang_function_call, env) when erlang_module in @erlang_modules do - Rewriter.rewrite(erlang_function_call) - |> translate(env) - end - - defp do_translate({{:., _, [Access, :get]}, _, [target, property]}, env) do - { Map.make_get_property(target, property, env), env } - end - - defp do_translate({:super, _, params }, env) do - { name, _ } = env.function - super_name = String.to_atom("__super__" <> to_string(name)) - - Call.make_local_function_call(super_name, params, env) - end - - defp do_translate({{:., _, [function_name]}, _, params}, env) do - Call.make_local_function_call(function_name, params, env) - end - - defp do_translate({:., _, [{:__aliases__, _, _} = module_name, function_name]} = ast, env) do - do_translate({{:., [], [module_name, function_name]}, [], []}, env) - end - - defp do_translate({{:., _, [{:__aliases__, _, _} = module_name, function_name]}, _, [] } = ast, env) do - expanded_ast = Macro.expand(ast, env.env) - - if expanded_ast == ast do - module_name = create_module_name(module_name, env) - case module_name do - {mod, :local} -> - Call.make_module_function_call(mod, function_name, env) - mod -> - Call.make_extern_function_or_property_call(mod, function_name, env) - end - else - translate(expanded_ast, env) - end - end - - defp do_translate({:., _, [module_name, function_name]} = ast, env) do - expanded_ast = Macro.expand(ast, env.env) - - if expanded_ast == ast do - Call.make_function_or_property_call(module_name, function_name, env) - else - translate(expanded_ast, env) - end - end - - defp do_translate({{:., _, [{:__aliases__, _, _} = module_name, function_name]}, _, params } = ast, env) do - expanded_ast = Macro.expand(ast, env.env) - - if expanded_ast == ast do - module_name = create_module_name(module_name, env) - case module_name do - {mod, :local} -> - Call.make_module_function_call(mod, function_name, params, env) - mod -> - Call.make_extern_function_call(mod, function_name, params, env) - end - else - translate(expanded_ast, env) - end - end - - defp do_translate({{:., _, [module_name, function_name]}, _, params} = ast, env) when is_atom(module_name) and is_atom(function_name) do - expanded_ast = Macro.expand(ast, env.env) - - if expanded_ast == ast do - Call.make_function_call(module_name, function_name, params, env) - else - translate(expanded_ast, env) - end - end - - defp do_translate({{:., _, [module_name, function_name]}, _, params } = ast, env) do - expanded_ast = Macro.expand(ast, env.env) - - if expanded_ast == ast do - Call.make_function_call(module_name, function_name, params, env) - else - translate(expanded_ast, env) - end - end - - defp do_translate({:__aliases__, _, aliases} = ast, env) do - module_name = create_module_name(ast, env) - case module_name do - {mod, :local} -> - Call.make_module_name(mod, env) - mod -> - Call.make_extern_module_name(mod, env) - end - end - - defp do_translate({:__MODULE__, _, _ }, env) do - module_name = create_module_name(env.module, env) - mod = case module_name do - {mod, _} -> - mod - mod -> - mod - end - - translate(mod, env) - end - - defp do_translate({:__block__, _, expressions }, env) do - Block.make_block(expressions, env) - end - - defp do_translate({:__DIR__, _, _}, env) do - case env.file do - nil -> - { JS.identifier(:null), env } - filepath -> - { JS.literal(Path.dirname(filepath)), env } - end - end - - defp do_translate({:try, _, [ blocks ]}, env) do - Try.make_try(blocks, env) - end - - defp do_translate({:with, _, args }, env ) do - With.make_with(args, env) - end - - defp do_translate({:super, _, _expressions }, _ ) do - raise ElixirScript.Translator.UnsupportedError, "super" - end - - defp do_translate({:__CALLER__, _, _expressions }, env) do - env_to_translate = ElixirScript.Translator.LexicalScope.caller(env) - - quoted = Macro.escape(env_to_translate) - translate(quoted, env) - end - - defp do_translate({:__ENV__, _, _expressions }, env) do - env_to_translate = ElixirScript.Translator.LexicalScope.env(env) - - quoted = Macro.escape(env_to_translate) - translate(quoted, env) - end - - defp do_translate({:quote, _, [[do: expr]]}, env) do - { Quote.make_quote([], expr, env), env } - end - - defp do_translate({:quote, _, [opts, [do: expr]]}, env) do - { Quote.make_quote(opts, expr, env), env } - end - - defp do_translate({:import, _, [{{:., _, [{:__aliases__, _, head_import_name}, :{}]}, _, tail_imports }]}, env) do - env = Enum.reduce(tail_imports, env, fn({:__aliases__, context, name}, acc) -> - full_module_name = { :__aliases__, context, head_import_name ++ name } - - module_name = Utils.quoted_to_name(full_module_name) - ElixirScript.Translator.LexicalScope.add_import(acc, module_name) - end) - - { %ElixirScript.Translator.Empty{}, env } - end - - - defp do_translate({:import, _, [{:__aliases__, _, _} = module_name]}, env) do - module_name = Utils.quoted_to_name(module_name) - - env = ElixirScript.Translator.LexicalScope.add_import(env, module_name) - { %ElixirScript.Translator.Empty{}, env } - end - - defp do_translate({:import, _, [{:__aliases__, _, _} = module_name, options]}, env) do - module_name = Utils.quoted_to_name(module_name) - - env = ElixirScript.Translator.LexicalScope.add_import(env, module_name, options) - - { %ElixirScript.Translator.Empty{}, env } - end - - defp do_translate({:alias, _, [{{:., _, [{:__aliases__, _, head_alias_name}, :{}]}, _, tail_aliases }]}, env) do - env = Enum.reduce(tail_aliases, env, fn({:__aliases__, context, name}, acc) -> - full_module_name = { :__aliases__, context, head_alias_name ++ name } - - module_name = Utils.quoted_to_name(full_module_name) - alias_name = Utils.quoted_to_name({:__aliases__, [], [List.last(name)] }) - - ElixirScript.Translator.LexicalScope.add_alias(acc, module_name, alias_name) - end) - - { %ElixirScript.Translator.Empty{}, env } - end - - defp do_translate({:alias, _, [{:__aliases__, _, _} = module_name] }, env) do - {_, _, name} = module_name - name = [List.last(name)] - - module_name = Utils.quoted_to_name(module_name) - alias_name = Utils.quoted_to_name({:__aliases__, [], name }) - - env = ElixirScript.Translator.LexicalScope.add_alias(env, module_name, alias_name) - { %ElixirScript.Translator.Empty{}, env } - end - - defp do_translate({:alias, _, [{:__aliases__, _, _} = module_name, [as: {:__aliases__, _, _} = alias_name]]}, env) do - module_name = Utils.quoted_to_name(module_name) - alias_name = Utils.quoted_to_name(alias_name) - - env = ElixirScript.Translator.LexicalScope.add_alias(env, module_name, alias_name) - { %ElixirScript.Translator.Empty{}, env } - end - - defp do_translate({:require, _, [{{:., _, [{:__aliases__, _, head_require_name}, :{}]}, _, tail_requires }]}, env) do - env = Enum.reduce(tail_requires, env, fn({:__aliases__, context, name}, acc) -> - full_module_name = { :__aliases__, context, head_require_name ++ name } - - module_name = Utils.quoted_to_name(full_module_name) - ElixirScript.Translator.LexicalScope.add_require(acc, module_name) - end) - - { %ElixirScript.Translator.Empty{}, env } - end - - defp do_translate({:require, _, [{:__aliases__, _, _} = module_name] }, env) do - module_name = Utils.quoted_to_name(module_name) - env = ElixirScript.Translator.LexicalScope.add_require(env, module_name) - { %ElixirScript.Translator.Empty{}, env } - end - - defp do_translate({:require, _, [{:__aliases__, _, _} = module_name, [as: {:__aliases__, _, _} = alias_name]]}, env) do - module_name = Utils.quoted_to_name(module_name) - alias_name = Utils.quoted_to_name(alias_name) - - env = ElixirScript.Translator.LexicalScope.add_require(env, module_name, alias_name) - { %ElixirScript.Translator.Empty{}, env } - end - - defp do_translate({:case, _, [condition, [do: clauses]]}, env) do - Case.make_case(condition, clauses, env) - end - - defp do_translate({:cond, _, [[do: clauses]]}, env) do - Cond.make_cond(clauses, env) - end - - defp do_translate({:for, _, generators}, env) do - For.make_for(generators, env) - end - - defp do_translate({:fn, _, clauses}, env) do - Function.make_anonymous_function(clauses, env) - end - - defp do_translate({:receive, _, _ }, _) do - raise ElixirScript.Translator.UnsupportedError, "receive" - end - - defp do_translate({:{}, _, elements}, env) do - quoted = quote do - JS.new(Bootstrap.Core.Tuple, unquote(elements)) - end - - translate(quoted, env) - end - - defp do_translate({:=, _, [left, right]}, env) do - Match.make_match(left, right, env) - end - - defp do_translate({function, _, [{:when, _, [{name, _, _params} | _guards] }, _] } = ast, env) when function in @generator_types do - {js_ast, _} = Def.process_function(name, [ast], %{ env | context: :generator}) - {js_ast, env} - end - - defp do_translate({function, _, [{name, _, params}, _]} = ast, env) when function in @generator_types and is_atom(params) do - {js_ast, _} = Def.process_function(name, [ast], %{ env | context: :generator}) - {js_ast, env} - end - - defp do_translate({function, _, [{name, _, _params}, _]} = ast, env) when function in @generator_types do - {js_ast, _} = Def.process_function(name, [ast], %{ env | context: :generator}) - {js_ast, env} - end - - defp do_translate({function, _, [{:when, _, [{name, _, _params} | _guards] }, _] } = ast, env) when function in @function_types do - Def.process_function(name, [ast], env) - end - - defp do_translate({function, _, [{name, _, params}, _]} = ast, env) when function in @function_types and is_atom(params) do - Def.process_function(name, [ast], env) - end - - defp do_translate({function, _, [{name, _, _params}, _]} = ast, env) when function in @function_types do - Def.process_function(name, [ast], env) - end - - defp do_translate({:defdelegate, _, [{name, _, params}, options]}, env) do - Def.process_delegate(name, params, options, env) - end - - defp do_translate({:defstruct, _, [attributes]}, env) do - { Struct.make_struct(attributes, env), env } - end - - defp do_translate({:defexception, _, [attributes]}, env) do - { Struct.make_struct(attributes ++ [__exception__: true], env), env } - end - - defp do_translate({:defmodule, _, [{:__aliases__, _, module_name_list}, [do: body]]}, env) do - { Defmodule.make_module(module_name_list, body, env), env } - end - - defp do_translate({:defprotocol, _, _}, env) do - { %ElixirScript.Translator.Empty{}, env } - end - - defp do_translate({:defmacro, _, _}, env) do - { %ElixirScript.Translator.Empty{}, env } - end - - defp do_translate({:defmacrop, _, _}, env) do - { %ElixirScript.Translator.Empty{}, env } - end - - defp do_translate({:defimpl, _, _}, env) do - { %ElixirScript.Translator.Empty{}, env } - end - - defp do_translate({:|, _, [item, list]}, env) do - quoted = quote do - [unquote(item)].concat(unquote(list)) - end - - translate(quoted, env) - end - - defp do_translate({:raise, _, [alias_info, attributes]}, env) when is_list(attributes) do - module = case create_module_name(alias_info, env) do - {module, _} -> - module - module -> - module - end - - {call, _} = Call.make_module_function_call(module, :__struct__, [{:%{}, [], attributes }], env) - - js_ast = JS.throw_statement(call) - - { js_ast, env } - end - - defp do_translate({:raise, _, [alias_info, message]}, env) do - module = case create_module_name(alias_info, env) do - {module, _} -> - module - module -> - module - end - - {call, _} = Call.make_module_function_call(module, :__struct__, [{:%{}, [], [message: message] }], env) - - js_ast = JS.throw_statement(call) - - { js_ast, env } - end - - defp do_translate({:raise, _, [{:__aliases__, _, _} = alias_info]}, env) do - module = case create_module_name(alias_info, env) do - {module, _} -> - module - module -> - module - end - - {call, _} = Call.make_module_function_call(module, :__struct__, [], env) - - js_ast = JS.throw_statement(call) - - { js_ast, env } - end - - defp do_translate({:raise, _, [message]}, env) do - js_ast = JS.throw_statement( - JS.object_expression( - [ - Map.make_property(translate!(:__struct__, env), translate!(:RuntimeError, env)), - Map.make_property(translate!(:__exception__, env), translate!(true, env)), - Map.make_property(translate!(:message, env), translate!(message, env)) - ] - ) - ) - - { js_ast, env } - end - - defp do_translate({name, _, params} = ast, env) when is_list(params) do - if is_from_js_module(name, params, env) do - do_translate({{:., [], [{:__aliases__, [], [:JS]}, name]}, [], params }, env) - else - expanded_ast = Macro.expand(ast, env.env) - if expanded_ast == ast do - name_arity = {name, length(params)} - module = ElixirScript.Translator.State.get_module(env.state, env.module) - - cond do - name_arity in module.functions or name_arity in module.private_functions -> - Call.make_local_function_call(name, params, env) - ElixirScript.Translator.LexicalScope.find_module(env, name_arity) -> - imported_module_name = ElixirScript.Translator.LexicalScope.find_module(env, name_arity) - Call.make_module_function_call(imported_module_name, name, params, env) - true -> - Call.make_local_function_call(name, params, env) - end - - else - translate(expanded_ast, env) - end - end - end - - defp do_translate({ name, _context, params }, env) when is_atom(params) do - cond do - is_from_js_module(name, params, env) -> - do_translate({{:., [], [{:__aliases__, [], [:JS]}, name]}, [], params }, env) - ElixirScript.Translator.LexicalScope.has_var?(env, name) -> - name = case env.vars[name] do - 0 -> - name - num -> - String.to_atom("#{name}#{num}") - end - - { Identifier.make_identifier(name), env } - has_function?(env.module, {name, 0}, env) -> - Call.make_local_function_call(name, [], env) - ElixirScript.Translator.LexicalScope.find_module(env, {name, 0}) -> - imported_module_name = ElixirScript.Translator.LexicalScope.find_module(env, {name, 0}) - Call.make_module_function_call(imported_module_name, name, params, env) - true -> - { Identifier.make_identifier(name), env } - end - end - - defp is_from_js_module(name, params, env) do - func = if is_list(params) do - {name, length(params)} - else - {name, 0} - end - - {_, macros} = Enum.find(env.env.macros, {nil, []}, fn({k, v}) -> to_string(k) == "Elixir.JS" end) - {_, functions} = Enum.find(env.env.functions, {nil, []}, fn({k, v}) -> to_string(k) == "Elixir.JS" end) - - js = macros ++ functions - - if func in js do - true - else - false - end - end - - def create_module_name(module_name, env) do - module_name = Utils.quoted_to_name(module_name) - candiate_module_name = ElixirScript.Translator.State.get_module_name(env.state, module_name) - - if ElixirScript.Translator.LexicalScope.get_module_name(env, candiate_module_name) in ElixirScript.Translator.State.list_module_names(env.state) do - { ElixirScript.Translator.LexicalScope.get_module_name(env, candiate_module_name), :local } - else - module_name - end - end - - def has_function?(module_name, name_arity, env) do - case ElixirScript.Translator.State.get_module(env.state, module_name) do - nil -> - false - module -> - name_arity in module.functions or name_arity in module.private_functions - end - end - -end diff --git a/lib/elixir_script/translator/empty.ex b/lib/elixir_script/translator/empty.ex deleted file mode 100644 index 1456cc4f..00000000 --- a/lib/elixir_script/translator/empty.ex +++ /dev/null @@ -1,8 +0,0 @@ -defmodule ElixirScript.Translator.Empty do - @moduledoc false - - # Represents no translation to JS AST - - @type t :: %ElixirScript.Translator.Empty{} - defstruct type: "Empty" -end diff --git a/lib/elixir_script/translator/group.ex b/lib/elixir_script/translator/group.ex deleted file mode 100644 index 391315ff..00000000 --- a/lib/elixir_script/translator/group.ex +++ /dev/null @@ -1,30 +0,0 @@ -defmodule ElixirScript.Translator.Group do - @moduledoc false - - # Represents a collection of JavaScript AST. - # Contents in body are expanded within outer AST before JS code generation - - @type t :: %ElixirScript.Translator.Group{ - type: binary, - body: [ESTree.Statement.t] - } - defstruct type: "Group", body: [] - - def inflate_groups(body) do - Enum.map(body, fn(x) -> - case x do - %ElixirScript.Translator.Empty{} -> - [] - %ElixirScript.Translator.Group{body: group_body} -> - group_body - %ESTree.BlockStatement{} -> - %ESTree.BlockStatement{ body: inflate_groups(x.body) } - %ESTree.IfStatement{} -> - %{x | consequent: inflate_groups(x.consequent), alternate: inflate_groups(x.alternate) } - _ -> - x - end - end) - |> List.flatten - end -end diff --git a/lib/elixir_script/translator/kernel/def.ex b/lib/elixir_script/translator/kernel/def.ex deleted file mode 100644 index 6fee1fb1..00000000 --- a/lib/elixir_script/translator/kernel/def.ex +++ /dev/null @@ -1,39 +0,0 @@ -defmodule ElixirScript.Translator.Def do - @moduledoc false - alias ESTree.Tools.Builder, as: JS - alias ElixirScript.Translator.Function - alias ElixirScript.Translator.Identifier - alias ElixirScript.Translator - - def process_function(name, functions, env) do - { result, _ } = Function.make_anonymous_function(functions, env, name) - - declarator = JS.variable_declarator( - Identifier.make_identifier(name), - result - ) - - { JS.variable_declaration([declarator], :const), env } - end - - def process_delegate(name, params, options, env) do - translated_params = Enum.map(params, &Translator.translate!(&1, env)) - to = options[:to] - as = options[:as] || name - - function = JS.function_expression(translated_params, [], - JS.block_statement([ - JS.return_statement( - Translator.translate!({{:., [], [to, as]}, [], params}, env) - ) - ]) - ) - - declarator = JS.variable_declarator( - Identifier.make_identifier(name), - function - ) - - { JS.variable_declaration([declarator], :const), env } - end -end diff --git a/lib/elixir_script/translator/kernel/defimpl.ex b/lib/elixir_script/translator/kernel/defimpl.ex deleted file mode 100644 index 0e1dde5d..00000000 --- a/lib/elixir_script/translator/kernel/defimpl.ex +++ /dev/null @@ -1,137 +0,0 @@ -defmodule ElixirScript.Translator.Defimpl do - @moduledoc false - alias ESTree.Tools.Builder, as: JS - alias ElixirScript.Translator.Defmodule - alias ElixirScript.Translator.State - alias ElixirScript.Translator.Utils - - def make(name, type, body, env) do - - type = map_to_js(type, env) - {body, export} = Defmodule.process_module(name, body, env) - - protocol_name = Atom.to_string(name) |> String.split(".DefImpl.") |> hd |> String.to_atom - - export = JS.object_expression([ - JS.property( - JS.literal("Type"), - type - ), - JS.property( - JS.literal("Implementation"), - export - ) - ]) - - %{ - name: Utils.quoted_to_name({:__aliases__, [], name }), - exports: export, - body: body, - app_name: State.get_module(env.state, name).app, - protocol: protocol_name, - env: env - } - end - - defp map_to_js({:__aliases__, _, [:Integer]}, _) do - JS.member_expression( - JS.member_expression( - JS.identifier("Bootstrap"), - JS.identifier(:Core) - ), - JS.identifier(:Integer) - ) - end - - defp map_to_js({:__aliases__, _, [:Tuple]}, _) do - JS.member_expression( - JS.member_expression( - JS.identifier("Bootstrap"), - JS.identifier(:Core) - ), - JS.identifier(:Tuple) - ) - end - - defp map_to_js({:__aliases__, _, [:Atom]}, _) do - JS.identifier(:Symbol) - end - - defp map_to_js({:__aliases__, _, [:List]}, _) do - JS.identifier(:Array) - end - - defp map_to_js({:__aliases__, _, [:BitString]}, _) do - JS.member_expression( - JS.member_expression( - JS.identifier("Bootstrap"), - JS.identifier(:Core) - ), - JS.identifier(:BitString) - ) - end - - defp map_to_js({:__aliases__, _, [:Float]}, _) do - JS.member_expression( - JS.member_expression( - JS.identifier("Bootstrap"), - JS.identifier(:Core) - ), - JS.identifier(:Float) - ) - end - - defp map_to_js({:__aliases__, _, [:Function]}, _) do - JS.identifier(:Function) - end - - defp map_to_js({:__aliases__, _, [:PID]}, _) do - JS.member_expression( - JS.member_expression( - JS.identifier("Bootstrap"), - JS.identifier(:Core) - ), - JS.identifier(:PID) - ) - end - - defp map_to_js({:__aliases__, _, [:Port]}, _) do - JS.member_expression( - JS.identifier("Bootstrap"), - JS.identifier(:Port) - ) - end - - defp map_to_js({:__aliases__, _, [:Reference]}, _) do - JS.member_expression( - JS.identifier("Bootstrap"), - JS.identifier(:Reference) - ) - end - - defp map_to_js({:__aliases__, _, [:Map]}, _) do - JS.identifier(:Object) - end - - defp map_to_js({:__aliases__, context, [:JS | rest]}, env) do - ElixirScript.Translator.JS.translate_js_module({:__aliases__, context, rest}, env) - |> elem(0) - end - - defp map_to_js({:__aliases__, _, [:Any]}, _) do - JS.identifier(:null) - end - - - defp map_to_js({:__aliases__, _, _} = module, env) do - module = case ElixirScript.Translator.create_module_name(module, env) do - {module, _} -> - module - module -> - module - end - - ElixirScript.Translator.translate!(module, env) - end - -end diff --git a/lib/elixir_script/translator/kernel/defmodule.ex b/lib/elixir_script/translator/kernel/defmodule.ex deleted file mode 100644 index eb77bc00..00000000 --- a/lib/elixir_script/translator/kernel/defmodule.ex +++ /dev/null @@ -1,267 +0,0 @@ -defmodule ElixirScript.Translator.Defmodule do - @moduledoc false - alias ESTree.Tools.Builder, as: JS - alias ElixirScript.Translator - alias ElixirScript.Translator.State - alias ElixirScript.Translator.Utils - alias ElixirScript.Translator.Group - alias ElixirScript.Translator.Def - alias ElixirScript.Translator.Identifier - - def make_module(ElixirScript.Temp, body, env) do - { body, _ } = translate_body(body, env) - %{ - name: ElixirScript.Temp, - body: body |> Group.inflate_groups, - exports: nil, - app_name: ElixirScript.Translator.State.get(env.state).compiler_opts.app, - env: env - } - end - - def make_module(module, nil, env) do - %{ - name: module, - body: [], - exports: nil, - app_name: ElixirScript.Translator.State.get(env.state).compiler_opts.app, - env: env - } - end - - def make_module(module, body, env) do - {body, exported_object} = process_module(module, body, env) - app_name = State.get_module(env.state, module).app - - result = %{ - name: Utils.quoted_to_name({:__aliases__, [], module }), - exports: exported_object, - body: body, - app_name: app_name, - env: env - } - - result - end - - def process_module(module, body, env) do - { body, functions } = extract_functions_from_module(body) - - { body, env } = translate_body(body, env) - - { exported_functions, private_functions } = process_functions(functions, env) - - struct_prop = if has_struct?(body) do - [JS.property(Identifier.make_identifier("__struct__"), Identifier.make_identifier("__struct__"), :init, true)] - else - [] - end - - info_prop = [JS.property(Identifier.make_identifier("__info__"), Identifier.make_identifier("__info__"), :init, true)] - - body = Enum.map(body, fn(x) -> - case x do - %ESTree.CallExpression{} -> - JS.expression_statement(x) - _ -> - x - end - end) - - body = Group.inflate_groups(body) - - exported_object = JS.object_expression( - info_prop ++ struct_prop ++ - Enum.map(exported_functions, fn({key, _value}) -> - JS.property(Identifier.make_identifier(key), Identifier.make_identifier(key), :init, true) - end) - ) - - exported_functions = Enum.map(exported_functions, fn({_key, value}) -> value end) - private_functions = Enum.map(private_functions, fn({_key, value}) -> value end) - - body = private_functions ++ exported_functions ++ [make_info_function(env)] ++ body - {body, exported_object} - end - - def translate_body(body, env) do - { body, env } = Translator.translate(body, env) - - body = case body do - [%ESTree.BlockStatement{ body: body }] -> - body - %ESTree.BlockStatement{ body: body } -> - body - _ -> - List.wrap(body) - end - - { body, env } - end - - def extract_functions_from_module({:__block__, meta, body_list}) do - { body_list, functions } = Enum.map_reduce(body_list, - %{exported: Map.new(), private: Map.new(), exported_generators: Map.new(), private_generators: Map.new()}, fn - ({:def, _, [{:when, _, [{name, _, _} | _guards] }, _] } = function, state) -> - { - nil, - %{ state | exported: Map.put(state.exported, name, Map.get(state.exported, name, []) ++ [function]) } - } - ({:def, _, [{name, _, _}, _]} = function, state) -> - { - nil, - %{ state | exported: Map.put(state.exported, name, Map.get(state.exported, name, []) ++ [function]) } - } - ({:defp, _, [{:when, _, [{name, _, _} | _guards] }, _] } = function, state) -> - { - nil, - %{ state | private: Map.put(state.private, name, Map.get(state.private, name, []) ++ [function]) } - } - ({:defp, _, [{name, _, _}, _]} = function, state) -> - { - nil, - %{ state | private: Map.put(state.private, name, Map.get(state.private, name, []) ++ [function]) } - } - ({:defgen, _, [{:when, _, [{name, _, _} | _guards] }, _] } = function, state) -> - { - nil, - %{ state | exported_generators: Map.put(state.exported_generators, name, Map.get(state.exported_generators, name, []) ++ [function]) } - } - ({:defgen, _, [{name, _, _}, _]} = function, state) -> - { - nil, - %{ state | exported_generators: Map.put(state.exported_generators, name, Map.get(state.exported_generators, name, []) ++ [function]) } - } - ({:defgenp, _, [{:when, _, [{name, _, _} | _guards] }, _] } = function, state) -> - { - nil, - %{ state | private_generators: Map.put(state.private_generators, name, Map.get(state.private_generators, name, []) ++ [function]) } - } - ({:defgenp, _, [{name, _, _}, _]} = function, state) -> - { - nil, - %{ state | private_generators: Map.put(state.private_generators, name, Map.get(state.private_generators, name, []) ++ [function]) } - } - (x, state) -> - { x, state } - end) - - body_list = Enum.filter(body_list, fn(x) -> !is_nil(x) end) - body = {:__block__, meta, body_list} - - { body, functions } - end - - def extract_functions_from_module(body) do - extract_functions_from_module({:__block__, [], List.wrap(body)}) - end - - def extract_imports_from_body(body) do - Enum.partition(body, fn(x) -> - case x do - %ESTree.ImportDeclaration{} -> - true - _ -> - false - end - end) - end - - def has_struct?(body) do - val = Enum.find(body, fn(x) -> - case x do - %ESTree.VariableDeclaration{declarations: [%ESTree.VariableDeclarator{id: %ESTree.Identifier{name: "__struct__"} } ] } -> - true - _ -> - false - end - end) - - val != nil - end - - defp make_defstruct_property(_, []) do - [] - end - - defp make_defstruct_property(module_name, [the_struct]) do - module_js_name = Utils.name_to_js_name(module_name) - - case the_struct do - %ESTree.VariableDeclaration{declarations: [%ESTree.VariableDeclarator{id: %ESTree.Identifier{name: ^module_js_name} } ] } -> - [JS.property(JS.identifier(module_js_name), JS.identifier(module_js_name), :init, true)] - end - end - - def process_functions(%{ exported: exported, private: private, exported_generators: exported_generators, private_generators: private_generators }, env) do - exported_functions = Enum.map(Map.keys(exported), fn(key) -> - functions = Map.get(exported, key) - - { functions, _ } = Def.process_function(key, functions, env) - { key, functions } - end) - - exported_generators = Enum.map(Map.keys(exported_generators), fn(key) -> - functions = Map.get(exported_generators, key) - - { functions, _ } = Def.process_function(key, functions, %{ env | context: :generator}) - { key, functions } - end) - - private_functions = Enum.map(Map.keys(private), fn(key) -> - functions = Map.get(private, key) - { functions, _ } = Def.process_function(key, functions, env) - { key, functions } - end) - - private_generators = Enum.map(Map.keys(private_generators), fn(key) -> - functions = Map.get(private_generators, key) - { functions, _ } = Def.process_function(key, functions, %{ env | context: :generator}) - { key, functions } - end) - - { exported_functions ++ exported_generators, private_functions ++ private_generators } - end - - def make_attribute(name, value, env) do - declarator = JS.variable_declarator( - Identifier.make_identifier(name), - ElixirScript.Translator.translate!(value, env) - ) - - JS.variable_declaration([declarator], :const) - end - - def make_info_function(env) do - functions = Keyword.get(env.functions, env.module, []) - macros = Keyword.get(env.macros, env.module, []) - - info_case = quote do - case kind do - :functions -> - unquote(functions) - :macros -> - unquote(macros) - :module -> - unquote(env.module) - end - end - - translated_case = ElixirScript.Translator.translate!(info_case, env) - - declarator = JS.variable_declarator( - Identifier.make_identifier("__info__"), - JS.function_expression( - [JS.identifier("kind")], - [], - JS.block_statement([ - JS.return_statement(translated_case) - ]) - ) - ) - - JS.variable_declaration([declarator], :const) - - end - -end diff --git a/lib/elixir_script/translator/kernel/defprotocol.ex b/lib/elixir_script/translator/kernel/defprotocol.ex deleted file mode 100644 index f41ee42b..00000000 --- a/lib/elixir_script/translator/kernel/defprotocol.ex +++ /dev/null @@ -1,93 +0,0 @@ -defmodule ElixirScript.Translator.Defprotocol do - @moduledoc false - - alias ESTree.Tools.Builder, as: JS - alias ElixirScript.Translator.Defmodule - alias ElixirScript.Translator.Map - alias ElixirScript.Translator.Utils - alias ElixirScript.Translator.State - alias ElixirScript.Translator.Identifier - require Logger - - @doc """ - Takes a protocol and turns it into a module - """ - def make(name, functions, env) do - { body, _ } = Defmodule.translate_body( {:__block__, [], [] }, env) - app_name = State.get_module(env.state, name).app - - object = process_spec_functions(functions) - |> Enum.map(fn({key, value}) -> - Map.make_property(Identifier.make_identifier(key), value) - end) - |> JS.object_expression - - declarator = JS.variable_declarator( - JS.identifier(Utils.name_to_js_name(name)), - JS.call_expression( - JS.member_expression( - JS.identifier("Bootstrap"), - JS.member_expression( - JS.identifier(:Core), - JS.member_expression( - JS.identifier(:Functions), - JS.identifier(:defprotocol) - ) - ) - ), - [object] - ) - ) - - declaration = JS.variable_declaration([declarator], :const) - - implementation_name_split = Module.split(name) ++ ["DefImpl"] - implementation_name = Enum.join(["Elixir"] ++ implementation_name_split, "$") - implementation_name_module = Module.concat(implementation_name_split) - - implementations = JS.for_of_statement( - JS.variable_declaration([JS.variable_declarator( - JS.object_pattern([ - JS.assignment_property(JS.identifier("Type")), - JS.assignment_property(JS.identifier("Implementation")) - ]), - nil - )], :let), - JS.identifier(implementation_name), - JS.call_expression( - JS.member_expression( - JS.identifier("Bootstrap"), - JS.member_expression( - JS.identifier(:Core), - JS.member_expression( - JS.identifier(:Functions), - JS.identifier(:defimpl) - ) - ) - ), - [ - JS.identifier(Utils.name_to_js_name(name)), - JS.identifier("Type"), - JS.identifier("Implementation") - ] - ) - ) - - body = body ++ [declaration] ++ [implementations] - defimpl_import = ElixirScript.ModuleSystems.Namespace.import_module(implementation_name_module) - - %{ - name: name, - body: [defimpl_import] ++ body, - exports: JS.identifier(Utils.name_to_js_name(name)), - app_name: app_name, - env: env - } - end - - defp process_spec_functions(functions) do - Enum.map(Keyword.keys(functions), fn(function_name) -> - {function_name, JS.function_expression([], [], JS.block_statement([]))} - end) - end -end diff --git a/lib/elixir_script/translator/kernel/expression.ex b/lib/elixir_script/translator/kernel/expression.ex deleted file mode 100644 index 583e52a4..00000000 --- a/lib/elixir_script/translator/kernel/expression.ex +++ /dev/null @@ -1,18 +0,0 @@ -defmodule ElixirScript.Translator.Expression do - @moduledoc false - alias ESTree.Tools.Builder - alias ElixirScript.Translator - - def make_unary_expression(operator, expr, env) do - { js_ast, env } = Translator.translate(expr, env) - { Builder.unary_expression(operator, true, js_ast), env } - end - - def make_binary_expression(operator, left, right, env) do - { left, _ } = Translator.translate(left, env) - { right, _ } = Translator.translate(right, env) - - { Builder.binary_expression(operator, left, right), env } - end - -end diff --git a/lib/elixir_script/translator/kernel/js.ex b/lib/elixir_script/translator/kernel/js.ex deleted file mode 100644 index ea0c52e6..00000000 --- a/lib/elixir_script/translator/kernel/js.ex +++ /dev/null @@ -1,237 +0,0 @@ -defmodule ElixirScript.Translator.JS do - @moduledoc false - - alias ESTree.Tools.Builder - alias ElixirScript.Translator - alias ElixirScript.Translator.Utils - alias ElixirScript.Translator.Identifier - - def call_property() do - Builder.member_expression( - Builder.member_expression( - Builder.identifier("Bootstrap"), - Builder.member_expression( - Builder.identifier("Core"), - Builder.identifier("Functions") - ) - ), - Builder.identifier("call_property") - ) - end - - def global() do - Builder.member_expression( - Builder.member_expression( - Builder.identifier("Bootstrap"), - Builder.identifier("Core") - ), - Builder.identifier("global") - ) - end - - @doc false - def translate_js_function({:__aliases__, _, module}, name, params, env) do - { do_translate(module, {name, [], params}, env), env } - end - - @doc false - def translate_js_function(name, params, env) do - { do_translate({name, [], params}, env), env } - end - - def translate_js_module(module, env) do - { do_translate(module, env), env } - end - - defp do_translate({:__aliases__, _, module}, env) do - Identifier.make_namespace_members(module) - end - - defp do_translate({op, _, [param]}, env) when op in [:typeof, :delete, :void, :-, :+, :!, :"~"] do - Builder.unary_expression( - op, - true, - Translator.translate!(param, env) - ) - end - - defp do_translate({op, _, [value, type]}, env) when op in [:"**", :==, :!=, :===, :!==, :<, :<=, :>, :>=, :"<<", :">>", :<<<, :+, :-, :*, :/, :%, :|, :^, :&, :in, :instanceof] do - Builder.binary_expression( - op, - Translator.translate!(value, env), - Translator.translate!(type, env) - ) - end - - defp do_translate({op, _, [value, type]}, env) when op in [:||, :&&] do - Builder.logical_expression( - op, - Translator.translate!(value, env), - Translator.translate!(type, env) - ) - end - - defp do_translate({:yield, _, []}, _) do - Builder.yield_expression() - end - - defp do_translate({:yield, _, [term]}, env) do - Builder.yield_expression( - Translator.translate!(term, env) - ) - end - - defp do_translate({:yield_to, _, [term]}, env) do - Builder.yield_expression( - Translator.translate!(term, env), - true - ) - end - - defp do_translate({:throw, _, [term]}, env) do - Builder.throw_statement( - Translator.translate!(term, env) - ) - end - - defp do_translate({:throw, _, [term]}, env) do - Builder.throw_statement( - Translator.translate!(term, env) - ) - end - - defp do_translate({:new, _, [module_name, params]}, env) when not is_list(params) do - Builder.new_expression( - Translator.translate!(module_name, env), - [Builder.rest_element(Translator.translate!(params, env))] - ) - end - - defp do_translate({:new, _, [module_name, params]}, env) do - Builder.new_expression( - Translator.translate!(module_name, env), - Enum.map(params, &Translator.translate!(&1, env)) - ) - end - - defp do_translate({:update, _, [object, map]}, env) do - quoted = quote do - JS.Object.assign(unquote(object), unquote(map)) - end - - Translator.translate!(quoted, env) - end - - defp do_translate({:update, _, [object, key, value]}, env) do - Builder.assignment_expression( - :=, - Builder.member_expression( - Translator.translate!(object, env), - Translator.translate!(key, env), - true - ), - Translator.translate!(value, env) - ) - end - - defp do_translate({:import, _, [term]}, env) do - Builder.call_expression( - Builder.identifier("import"), - [Translator.translate!(term, env)] - ) - end - - defp do_translate({:debugger, _, _}, env) do - Builder.debugger_statement() - end - - defp do_translate({:this, _, _}, env) do - Builder.this_expression() - end - - defp do_translate({:__delete__, _, [expr]}, env) do - {result, _} = ElixirScript.Translator.Expression.make_unary_expression(:delete, expr, env) - result - end - - defp do_translate({:__bnot__, _, [expr]}, env) do - {result, _} = ElixirScript.Translator.Expression.make_unary_expression(:"~", expr, env) - result - end - - defp do_translate({:__band__, _, [left, right]}, env) do - {result, _} = ElixirScript.Translator.Expression.make_binary_expression(:&, left, right, env) - result - end - - defp do_translate({:__bor__, _, [left, right]}, env) do - {result, _} = ElixirScript.Translator.Expression.make_binary_expression(:|, left, right, env) - result - end - - defp do_translate({:__bsl__, _, [left, right]}, env) do - {result, _} = ElixirScript.Translator.Expression.make_binary_expression(:"<<", left, right, env) - result - end - - defp do_translate({:__bsr__, _, [left, right]}, env) do - {result, _} = ElixirScript.Translator.Expression.make_binary_expression(:">>", left, right, env) - result - end - - defp do_translate({:__bxor__, _, [left, right]}, env) do - {result, _} = ElixirScript.Translator.Expression.make_binary_expression(:^, left, right, env) - result - end - - defp do_translate({function, _, []}, env) do - Builder.call_expression( - call_property(), - [ - global(), - Translator.translate!(to_string(function), env) - ] - ) - end - - defp do_translate({function, _, params}, env) do - Builder.call_expression( - Builder.member_expression( - global(), - Builder.identifier(function) - ), - Enum.map(params, &Translator.translate!(&1, env)) - ) - end - - defp do_translate(module, {function, _, []}, env) do - members = Identifier.make_namespace_members(module) - - Builder.call_expression( - call_property(), - [ - Builder.member_expression( - global(), - members - ), - Translator.translate!(to_string(function), env) - ] - ) - end - - defp do_translate(module, {function, _, params}, env) do - members = Identifier.make_namespace_members(module) - - Builder.call_expression( - Builder.member_expression( - Builder.member_expression( - global(), - members - ), - Builder.identifier(function) - ), - Enum.map(params, &Translator.translate!(&1, env)) - ) - end - -end diff --git a/lib/elixir_script/translator/kernel/special_forms/bitstring.ex b/lib/elixir_script/translator/kernel/special_forms/bitstring.ex deleted file mode 100644 index bf0dc832..00000000 --- a/lib/elixir_script/translator/kernel/special_forms/bitstring.ex +++ /dev/null @@ -1,147 +0,0 @@ -defmodule ElixirScript.Translator.Bitstring do - @moduledoc false - alias ESTree.Tools.Builder, as: JS - alias ElixirScript.Translator - - - def make_bitstring(elements, env) do - js_ast = JS.new_expression( - JS.member_expression( - JS.member_expression( - JS.identifier("Bootstrap"), - JS.identifier("Core") - ), - JS.identifier("BitString") - ), - Enum.map(elements, &make_bitstring_element(&1, env)) - ) - - { js_ast, env } - end - - def make_bitstring_element(element, env) when is_number(element) do - do_make_bitstring_element({:integer, Translator.translate!(element, env)}) - end - - def make_bitstring_element(element, env) when is_binary(element) do - do_make_bitstring_element({:binary, Translator.translate!(element, env)}) - end - - def make_bitstring_element({:<<>>, [], elements}, env) do - {ast, _} = make_bitstring(elements, env) - ast - end - - def make_bitstring_element({:::, _, [element, {type, _, _}]}, env) when type in [:integer, :float, :bitstring, :bits, :binary, :bytes, :utf8, :utf16, :utf32, :signed, :unsigned] do - do_make_bitstring_element({type, translate_element(element, env)}) - end - - def make_bitstring_element({:::, _, [element, {type, _, params}]}, env) when type in [:size, :unit] do - do_make_bitstring_element({type, translate_element(element, env), Enum.map(params, &translate_element(&1, env))}) - end - - def make_bitstring_element({:::, _, [element, {:*, _, [size, unit]}]}, env) do - size_ast = do_make_bitstring_element({:size, translate_element(element, env), [translate_element(size, env)]}) - do_make_bitstring_element({:unit, size_ast, [translate_element(unit, env)]}) - end - - def make_bitstring_element({:::, _, [element, {:-, _, types}]}, env) do - handle_type_adjectives({:-, [], types}, translate_element(element, env), env) - end - - def make_bitstring_element({:::, _, [element, size]}, env) do - do_make_bitstring_element({:size, translate_element(element, env), [translate_element(size, env)]}) - end - - def make_bitstring_element(element, env) do - do_make_bitstring_element({:binary, translate_element(element, env)}) - end - - def translate_element(ElixirScript.Translator.PatternMatching, _) do - JS.object_expression([JS.property( - JS.literal("value"), - ElixirScript.Translator.PatternMatching.parameter() - ) - ]) - end - - def translate_element(element, env) do - Translator.translate!(element, env) - end - - defp handle_type_adjectives({:-, _, types}, ast, env) do - Enum.reduce(types, ast, fn(type, current_ast) -> - case type do - {:-, _, sub_types} -> - handle_type_adjectives({:-, [], sub_types}, current_ast, env) - {:*, _, [size, unit]} -> - size_ast = do_make_bitstring_element({:size, current_ast, [Translator.translate!(size, env)]}) - do_make_bitstring_element({:unit, size_ast, [Translator.translate!(unit, env)]}) - {the_type, _, params} when is_list(params) -> - do_make_bitstring_element({the_type, current_ast, Enum.map(params, &Translator.translate!(&1, env))}) - {the_type, _, _} -> - do_make_bitstring_element({the_type, current_ast}) - end - end) - end - - defp bitstring_class() do - JS.member_expression( - JS.member_expression( - JS.identifier("Bootstrap"), - JS.identifier("Core") - ), - JS.identifier("BitString") - ) - end - - defp do_make_bitstring_element({type, ast}) do - JS.call_expression( - JS.member_expression( - bitstring_class, - JS.identifier(type) - ), - [ - ast - ] - ) - end - - defp do_make_bitstring_element({type, ast, params}) when is_list(params) do - JS.call_expression( - JS.member_expression( - bitstring_class, - JS.identifier(type) - ), - [ - ast - ] ++ params - ) - end - - def make_interpolated_string(elements, env) do - translated_elements = Enum.map(elements, fn(x) -> - case x do - elem when is_binary(elem) -> - Translator.translate!(elem, env) - {:::, _, data} -> - Translator.translate!(hd(data), env) - end - end) - - { do_make_interpolated_string(tl(translated_elements), hd(translated_elements), env), env } - end - - defp do_make_interpolated_string([], ast, _) do - ast - end - - defp do_make_interpolated_string(elements, ast, env) do - JS.binary_expression( - :+, - ast, - do_make_interpolated_string(tl(elements), hd(elements), env) - ) - end - -end diff --git a/lib/elixir_script/translator/kernel/special_forms/block.ex b/lib/elixir_script/translator/kernel/special_forms/block.ex deleted file mode 100644 index 52689574..00000000 --- a/lib/elixir_script/translator/kernel/special_forms/block.ex +++ /dev/null @@ -1,14 +0,0 @@ -defmodule ElixirScript.Translator.Block do - @moduledoc false - alias ESTree.Tools.Builder, as: JS - alias ElixirScript.Translator - - def make_block(expressions, env) do - { list, env } = Enum.map_reduce(expressions, env, fn(x, updated_env) -> - Translator.translate(x, updated_env) - end) - - { JS.block_statement(list), env } - end - -end diff --git a/lib/elixir_script/translator/kernel/special_forms/call.ex b/lib/elixir_script/translator/kernel/special_forms/call.ex deleted file mode 100644 index 2356c5a6..00000000 --- a/lib/elixir_script/translator/kernel/special_forms/call.ex +++ /dev/null @@ -1,214 +0,0 @@ -defmodule ElixirScript.Translator.Call do - @moduledoc false - alias ESTree.Tools.Builder, as: JS - alias ElixirScript.Translator - alias ElixirScript.Translator.Utils - alias ElixirScript.Translator.Identifier - - def make_module_name(module_name, env) do - members = ["Elixir"] ++ Module.split(module_name) - { Identifier.make_namespace_members(members), env } - end - - def make_extern_module_name(module_name, env) do - members = Module.split(module_name) - { Identifier.make_namespace_members(members), env } - end - - def make_local_function_call({fun, _, nil}, params, env) do - ast = JS.call_expression( - Identifier.make_identifier(fun), - Enum.map(params, &Translator.translate!(&1, env)) - ) - - {ast, env} - end - - def make_local_function_call(function_name, params, env) do - ast = JS.call_expression( - Identifier.make_identifier(function_name), - Enum.map(params, &Translator.translate!(&1, env)) - ) - - {ast, env} - end - - def make_module_function_call(module_name, function_name, params, env) do - ElixirScript.Translator.State.add_module_reference(env.state, env.module, module_name) - - members = ["Elixir"] ++ Module.split(module_name) ++ ["__load"] - - ast = JS.call_expression( - JS.member_expression( - JS.call_expression( - Identifier.make_namespace_members(members), - [JS.identifier("Elixir")] - ), - Identifier.make_identifier(function_name) - ), - Enum.map(params, &Translator.translate!(&1, env)) - ) - - {ast, env} - end - - def make_module_function_call(module_name, function_name, env) do - ElixirScript.Translator.State.add_module_reference(env.state, env.module, module_name) - make_module_function_call(module_name, function_name, [], env) - end - - def make_extern_function_or_property_call(module_name, function_name, env) do - members = Module.split(module_name) - Identifier.make_namespace_members(members) - - js_ast = JS.call_expression( - JS.member_expression( - JS.member_expression( - JS.identifier("Bootstrap"), - JS.member_expression( - JS.identifier("Core"), - JS.identifier("Functions") - ) - ), - JS.identifier("call_property") - ), - [ - Identifier.make_namespace_members(members), - Translator.translate!(to_string(function_name), env) - ] - ) - - {js_ast, env} - end - - def make_extern_function_call(module_name, function_name, params, env) do - members = Module.split(module_name) ++ [to_string(function_name)] - - ast = JS.call_expression( - Identifier.make_namespace_members(members), - Enum.map(params, &Translator.translate!(&1, env)) - ) - - {ast, env} - end - - def make_function_or_property_call(module_name, function_name, env) do - js_ast = JS.call_expression( - JS.member_expression( - JS.member_expression( - JS.identifier("Bootstrap"), - JS.member_expression( - JS.identifier("Core"), - JS.identifier("Functions") - ) - ), - JS.identifier("call_property") - ), - [ - Translator.translate!(module_name, env), - Translator.translate!(to_string(function_name), env) - ] - ) - - { js_ast, env } - end - - def make_function_call(module_name, function_name, [], env) when is_atom(module_name) and is_atom(function_name) do - js_ast = JS.call_expression( - JS.member_expression( - JS.member_expression( - JS.identifier("Bootstrap"), - JS.member_expression( - JS.identifier("Core"), - JS.identifier("Functions") - ) - ), - JS.identifier("call_property") - ), - [ - Identifier.make_identifier(module_name), - Translator.translate!(to_string(function_name), env) - ] - ) - - {js_ast, env} - end - - def make_function_call(module_name, function_name, params, env) when is_atom(module_name) and is_atom(function_name) do - js_ast = JS.call_expression( - JS.member_expression( - Identifier.make_identifier(module_name), - Identifier.make_identifier(function_name) - ), - Enum.map(params, &Translator.translate!(&1, env)) - ) - - {js_ast, env} - end - - def make_function_call({{:., _, _}, _, _} = module_name, function_name, [], env) do - js_ast = JS.call_expression( - JS.member_expression( - JS.member_expression( - JS.identifier("Bootstrap"), - JS.member_expression( - JS.identifier("Core"), - JS.identifier("Functions") - ) - ), - JS.identifier("call_property") - ), - [ - Translator.translate!(module_name, env), - Translator.translate!(to_string(function_name), env) - ] - ) - - {js_ast, env} - end - - def make_function_call({{:., _, _}, _, _} = module_name, function_name, params, env) do - js_ast = JS.call_expression( - JS.member_expression( - Translator.translate!(module_name, env), - Identifier.make_identifier(function_name) - ), - Enum.map(params, &Translator.translate!(&1, env)) - ) - - {js_ast, env} - end - - def make_function_call(module_name, function_name, [], env) do - js_ast = JS.call_expression( - JS.member_expression( - JS.member_expression( - JS.identifier("Bootstrap"), - JS.member_expression( - JS.identifier("Core"), - JS.identifier("Functions") - ) - ), - JS.identifier("call_property") - ), - [ - Translator.translate!(module_name, env), - Translator.translate!(to_string(function_name), env) - ] - ) - - {js_ast, env} - end - - def make_function_call(module_name, function_name, params, env) do - call = JS.call_expression( - JS.member_expression( - Translator.translate!(module_name, env), - Identifier.make_identifier(function_name) - ), - Enum.map(params, &Translator.translate!(&1, env)) - ) - - { call, env } - end -end diff --git a/lib/elixir_script/translator/kernel/special_forms/capture.ex b/lib/elixir_script/translator/kernel/special_forms/capture.ex deleted file mode 100644 index ec398f95..00000000 --- a/lib/elixir_script/translator/kernel/special_forms/capture.ex +++ /dev/null @@ -1,44 +0,0 @@ -defmodule ElixirScript.Translator.Capture do - @moduledoc false - - alias ESTree.Tools.Builder, as: JS - alias ElixirScript.Translator.PatternMatching - alias ElixirScript.Translator.Function - alias ElixirScript.Translator.Call - alias ElixirScript.Translator.Identifier - alias ElixirScript.Translator - - def make_capture(function_name, _, _) do - Identifier.make_identifier(function_name) - end - - def make_capture(module_name, function_name, _, env) do - members = ["Elixir"] ++ Module.split(module_name) ++ ["__load"] - - ast = JS.member_expression( - JS.call_expression( - Identifier.make_namespace_members(members), - [JS.identifier("Elixir")] - ), - Identifier.make_identifier(function_name) - ) - end - - def make_extern_capture(module_name, function_name, _, env) do - members = Module.split(module_name) ++ [to_string(function_name)] - Identifier.make_namespace_members(members) - end - - def find_value_placeholders(ast) do - case ast do - list when is_list(list) -> - Enum.map(list, &find_value_placeholders(&1)) - {:&, _, [number]} when is_number(number) -> - [{String.to_atom("__#{number}"), [], ElixirScript.Translator.Capture}] - tuple when is_tuple(tuple) -> - Enum.map(Tuple.to_list(tuple), &find_value_placeholders(&1)) - _ -> - [] - end - end -end diff --git a/lib/elixir_script/translator/kernel/special_forms/case.ex b/lib/elixir_script/translator/kernel/special_forms/case.ex deleted file mode 100644 index 5d1215e3..00000000 --- a/lib/elixir_script/translator/kernel/special_forms/case.ex +++ /dev/null @@ -1,17 +0,0 @@ -defmodule ElixirScript.Translator.Case do - @moduledoc false - alias ESTree.Tools.Builder, as: JS - alias ElixirScript.Translator - alias ElixirScript.Translator.Function - - def make_case(condition, clauses, env) do - { func, env } = Function.make_anonymous_function(clauses, env) - - js_ast = JS.call_expression( - JS.member_expression( func, JS.identifier("call")), - [JS.identifier(:this), Translator.translate!(condition, env)] - ) - - { js_ast, env } - end -end diff --git a/lib/elixir_script/translator/kernel/special_forms/cond.ex b/lib/elixir_script/translator/kernel/special_forms/cond.ex deleted file mode 100644 index a9959972..00000000 --- a/lib/elixir_script/translator/kernel/special_forms/cond.ex +++ /dev/null @@ -1,34 +0,0 @@ -defmodule ElixirScript.Translator.Cond do - @moduledoc false - - alias ESTree.Tools.Builder, as: JS - alias ElixirScript.Translator - alias ElixirScript.Translator.Primitive - alias ElixirScript.Translator.Function - - def make_cond(clauses, env) do - js_ast = JS.call_expression( - JS.member_expression( - Primitive.special_forms(), - JS.identifier("cond") - ), - process_cond(clauses, env) - ) - - { js_ast, env } - end - - defp process_cond(clauses, env) do - Enum.map(clauses, fn({:->, _, [clause, clause_body]}) -> - { translated_body, env } = Function.prepare_function_body(clause_body, env) - - translated_body = JS.block_statement(translated_body) - function = JS.function_expression([], [], translated_body) - translated_clause = Translator.translate!(hd(clause), env) - - - Primitive.make_list_no_translate([translated_clause, function]) - end) - end - -end diff --git a/lib/elixir_script/translator/kernel/special_forms/fn.ex b/lib/elixir_script/translator/kernel/special_forms/fn.ex deleted file mode 100644 index 5e0afb65..00000000 --- a/lib/elixir_script/translator/kernel/special_forms/fn.ex +++ /dev/null @@ -1,254 +0,0 @@ -defmodule ElixirScript.Translator.Function do - @moduledoc false - alias ESTree.Tools.Builder, as: JS - alias ElixirScript.Translator - alias ElixirScript.Translator.Group - alias ElixirScript.Translator.PatternMatching - alias ElixirScript.Translator.Block - - @patterns JS.member_expression( - JS.member_expression( - JS.identifier("Bootstrap"), - JS.identifier("Core") - ), - JS.identifier("Patterns") - ) - - @spec make_anonymous_function(list(), ElixirScript.Translator.LexicalScope.t, binary | atom) :: tuple() - def make_anonymous_function(functions, env, name \\ nil) - - def make_anonymous_function(functions, env, name) do - clauses = functions - |> Enum.map(fn - ({:->, _, [[{:when, _, params}], body ]}) -> - guards = List.last(params) - params = params |> Enum.reverse |> tl |> Enum.reverse - process_function_body(params, body, env, name, guards) - - ({:->, _, [params, body]}) -> - process_function_body(params, body, env, name) - - ({_, _, [{:when, _, [{_, _, params}, guards]}, body]}) -> - body = convert_to_try(body) - process_function_body(params, body, env, name, guards) - - ({_, _, [{_, _, params}, body]}) -> - body = convert_to_try(body) - process_function_body(params, body, env, name) - - ({_, _, [{_, _, params}]}) -> - process_function_body(params, [], env, name) - end) - - {make_defmatch(clauses, env.context == :generator), env} - end - - defp convert_to_try([do: body]) do - body - end - - defp convert_to_try(function_kw_list) do - {:__block__, [], [{:try, [], [function_kw_list]}]} - end - - defp make_defmatch(clauses, true) do - JS.call_expression( - JS.member_expression( - @patterns, - JS.identifier("defmatchgen") - ), - clauses - ) - end - - defp make_defmatch(clauses, _) do - JS.call_expression( - JS.member_expression( - @patterns, - JS.identifier("defmatch") - ), - clauses - ) - end - - defp process_function_body(params, body, env, name, guards \\ nil) do - env = ElixirScript.Translator.LexicalScope.function_scope(env, {name, get_arity(params)}) - - {patterns, params, env} = process_params(params, env) - {body, _} = make_function_body(body, env) - - if guards do - guards = case guards do - {:when, _, whens} -> - whens - wh -> - List.wrap(wh) - end - - guards = guards - |> Enum.reverse - |> process_guards - - {guard_body, _} = prepare_function_body(guards, %{env | context: :guard}) - - guard_body = JS.block_statement(guard_body) - make_function_clause(patterns, params, body, guard_body, env.context == :generator) - else - make_function_clause(patterns, params, body, nil, env.context == :generator) - end - end - - defp process_guards([guard]) do - guard - end - - defp process_guards([head | tail]) do - {:or, [], [process_guards(tail), head]} - end - - defp wrap_params(params) when is_atom(params), do: [] - defp wrap_params(params), do: List.wrap(params) - - @spec make_function_body(list | tuple, ElixirScript.Translator.LexicalScope.t) :: tuple() - def make_function_body(body, env) do - {body, _} = body - |> prepare_function_body(env) - - - {JS.block_statement(body), env} - end - - defp get_arity(params) when is_atom(params), do: 0 - defp get_arity(params) when is_tuple(params), do: 1 - defp get_arity(params), do: length(params) - - defp make_params(params) do - Enum.filter(params, fn - (%ESTree.Identifier{name: :undefined}) -> false - (_) -> true - end) - end - - defp process_params(params, env) do - params = wrap_params(params) - {patterns, params, env} = PatternMatching.process_match(params, env) - {patterns, make_params(params), env} - end - - defp make_function_clause(patterns, params, body, guard_body, is_generator?) do - params = Enum.filter(params, fn(x) -> is_nil(x) == false end) - - arguments = case guard_body do - nil -> - [ - JS.array_expression(patterns), - JS.function_expression(params, [], body, is_generator?) - ] - _ -> - [ - JS.array_expression(patterns), - JS.function_expression(params, [], body, is_generator?), - JS.function_expression(params, [], guard_body) - ] - end - - - JS.call_expression( - JS.member_expression( - @patterns, - JS.identifier("clause") - ), - arguments - ) - end - - def prepare_function_body(body, env) do - {list, env} = case body do - nil -> - {[], env} - list when is_list(list) -> - t = Translator.translate!(list, env) - {[t], env} - {:__block__, _, list} -> - Enum.map_reduce(list, env, fn(x, env) -> - Translator.translate(x, env) - end) - _ -> - Enum.map_reduce(List.wrap(body), env, fn(x, env) -> - Translator.translate(x, env) - end) - end - - list = Group.inflate_groups(list) - |> return_last_expression - - {list, env} - end - - defp return_last_expression(nil) do - nil - end - - defp return_last_expression([]) do - [JS.return_statement(JS.literal(nil))] - end - - defp return_last_expression(%ESTree.BlockStatement{} = block) do - %ESTree.BlockStatement{block | body: return_last_expression(block.body)} - end - - defp return_last_expression(list) when is_list(list) do - last_item = List.last(list) - - last_item = case last_item do - %ESTree.YieldExpression{} -> - JS.return_statement(last_item) - %ESTree.Literal{} -> - JS.return_statement(last_item) - %ESTree.Identifier{} -> - JS.return_statement(last_item) - %ESTree.VariableDeclaration{} -> - declaration = hd(last_item.declarations).id - - return_statement = case declaration do - %ESTree.ArrayPattern{elements: elements} -> - if length(elements) == 1 do - JS.return_statement(hd(declaration.elements)) - else - JS.return_statement(JS.array_expression(declaration.elements)) - end - _ -> - JS.return_statement(declaration) - end - - [last_item, return_statement] - %ESTree.BlockStatement{} -> - last_item = %ESTree.BlockStatement{last_item | body: return_last_expression(last_item.body)} - _ -> - if String.contains?(last_item.type, "Expression") do - JS.return_statement(last_item) - else - [last_item, JS.return_statement(JS.literal(nil))] - end - end - - - list = Enum.take(list, length(list) - 1) - |> Enum.map(fn(x) -> - case x do - %ESTree.MemberExpression{} -> - JS.expression_statement(x) - %ESTree.CallExpression{} -> - JS.expression_statement(x) - _ -> - x - end - end) - - if is_list(last_item) do - list ++ last_item - else - list ++ [last_item] - end - end -end diff --git a/lib/elixir_script/translator/kernel/special_forms/for.ex b/lib/elixir_script/translator/kernel/special_forms/for.ex deleted file mode 100644 index e690f710..00000000 --- a/lib/elixir_script/translator/kernel/special_forms/for.ex +++ /dev/null @@ -1,130 +0,0 @@ -defmodule ElixirScript.Translator.For do - @moduledoc false - alias ESTree.Tools.Builder, as: JS - alias ElixirScript.Translator - alias ElixirScript.Translator.PatternMatching - alias ElixirScript.Translator.Primitive - alias ElixirScript.Translator.Function - alias ElixirScript.Translator.Utils - alias ElixirScript.Translator.Identifier - - def make_for(generators, env) do - ElixirScript.Translator.State.add_module_reference(env.state, env.module, ElixirScript.Collectable) - args = handle_args(generators, env) - - generators = JS.array_expression(args.generators) - - into = args.into || Primitive.make_list_no_translate([]) - filter = args.filter || JS.function_expression([], [], JS.block_statement([JS.return_statement(JS.identifier("true"))])) - fun = args.fun - - members = ["Elixir"] ++ Module.split(ElixirScript.Collectable) ++ ["__load"] - - collectable_module = JS.call_expression( - Identifier.make_namespace_members(members), - [JS.identifier("Elixir")] - ) - - - expression = JS.call_expression( - JS.member_expression( - JS.member_expression( - JS.member_expression( - JS.identifier("Bootstrap"), - JS.identifier("Core") - ), - JS.identifier("Patterns") - ), - JS.identifier("clause") - ), - [JS.array_expression(args.patterns), fun, filter] - ) - - js_ast = JS.call_expression( - JS.member_expression( - Primitive.special_forms(), - JS.identifier("_for") - ), - [expression, generators, collectable_module, into] - ) - - {js_ast, env} - end - - defp handle_args(generators, env) do - Enum.reduce(generators, %{generators: [], args: [], filter: nil, fun: nil, into: nil, patterns: []}, fn - - ({:<<>>, _, body}, state) -> - {bs_parts, collection} = Enum.map_reduce(body, nil, fn - {:::, _, _} = ast, state -> - {ast, state} - {:<-, _, [var, collection]}, _ -> - {var, collection} - end) - - {patterns, params, env} = PatternMatching.process_match([{:<<>>, [], bs_parts}], env) - - gen = JS.call_expression( - JS.member_expression( - JS.member_expression( - JS.member_expression( - JS.identifier("Bootstrap"), - JS.identifier("Core") - ), - JS.identifier("Patterns") - ), - JS.identifier("bitstring_generator") - ), - [hd(patterns), Translator.translate!(collection, env)] - ) - - %{state | generators: state.generators ++ [gen], args: state.args ++ params, patterns: state.patterns ++ patterns} - - ({:<-, _, [identifier, enum]}, state) -> - {patterns, params, env} = PatternMatching.process_match([identifier], env) - - gen = JS.call_expression( - JS.member_expression( - JS.member_expression( - JS.member_expression( - JS.identifier("Bootstrap"), - JS.identifier("Core") - ), - JS.identifier("Patterns") - ), - JS.identifier("list_generator") - ), - [hd(patterns), Translator.translate!(enum, env)] - ) - - %{state | generators: state.generators ++ [gen], args: state.args ++ params, patterns: state.patterns ++ patterns} - ([into: expression], state) -> - %{state | into: Translator.translate(expression, env)} - - ([into: expression, do: expression2], state) -> - fun = create_function_expression(expression2, env, state) - - %{state | into: Translator.translate!(expression, env), fun: fun} - - ([do: expression], state) -> - fun = create_function_expression(expression, env, state) - - %{state | fun: fun} - (filter, state) -> - fun = create_function_expression(filter, env, state) - - %{state | filter: fun} - end) - end - - - defp create_function_expression(ast, env, state) do - {ast, _} = Function.make_function_body(ast, env) - - JS.function_expression( - state.args, - [], - ast - ) - end -end diff --git a/lib/elixir_script/translator/kernel/special_forms/identifier.ex b/lib/elixir_script/translator/kernel/special_forms/identifier.ex deleted file mode 100644 index 850c6417..00000000 --- a/lib/elixir_script/translator/kernel/special_forms/identifier.ex +++ /dev/null @@ -1,98 +0,0 @@ -defmodule ElixirScript.Translator.Identifier do - @moduledoc false - alias ESTree.Tools.Builder, as: JS - - @js_reserved_words [ - :break, - :case, - :class, - :const, - :continue, - :debugger, - :default, - :delete, - :do, - :else, - :export, - :extends, - :finally, - :function, - :if, - :import, - :in, - :instanceof, - :new, - :return, - :super, - :switch, - :throw, - :try, - :typeof, - :var, - :void, - :while, - :with, - :yield - ] - - def make_identifier({:__aliases__, _, aliases}) do - aliases - |> Enum.reverse - |> make_alias - end - - def make_identifier([ast]) do - make_identifier(ast) - end - - def make_identifier(ast) do - ast - |> filter_name - |> JS.identifier - end - - defp filter_name(name) when is_tuple(name) do - name - end - - defp filter_name(reserved_word) when reserved_word in @js_reserved_words do - "__#{Atom.to_string(reserved_word)}__" - end - - defp filter_name(name) do - to_string(name) - |> String.replace("?", "__qmark__") - |> String.replace("!", "__emark__") - end - - defp make_alias([x]) do - make_identifier(x) - end - - defp make_alias([h|t]) do - JS.member_expression(make_alias(t), make_identifier(h)) - end - - def make_namespace_members(module_name) do - case module_name do - m when is_list(m) -> - m - m when is_binary(m) -> - String.split(m, ".") - m when is_atom(m) -> - Module.split(m) - end - |> Enum.reverse - |> make_alias - end - - def make_function_name(name) do - name = filter_name(name) - JS.identifier(name) - end - - def make_extern_function_name(name) do - JS.identifier("#{name}") - end - -end diff --git a/lib/elixir_script/translator/kernel/special_forms/map.ex b/lib/elixir_script/translator/kernel/special_forms/map.ex deleted file mode 100644 index 77e4382b..00000000 --- a/lib/elixir_script/translator/kernel/special_forms/map.ex +++ /dev/null @@ -1,91 +0,0 @@ -defmodule ElixirScript.Translator.Map do - @moduledoc false - alias ESTree.Tools.Builder, as: JS - alias ElixirScript.Translator - alias ElixirScript.Translator.Primitive - - def make_map(object_expression) do - JS.call_expression( - JS.member_expression( - JS.identifier(:Object), - JS.identifier(:freeze) - ), - [object_expression] - ) - end - - def make_get_property(target, property, env) do - JS.member_expression( - Translator.translate!(target, env), - Translator.translate!(property, env), - true - ) - end - - def make_object(properties, env) do - properties - |> Enum.map(fn - ({x, {:__aliases__, _, [value]}}) -> make_property(Translator.translate!(x, env), JS.identifier(value)) - ({x, y}) -> - case x do - {_, _, atom } when is_atom(atom) -> - JS.property(Translator.translate!(x, env), Translator.translate!(y, env), :init, false, false, true) - _ -> - make_property(Translator.translate!(x, env), Translator.translate!(y, env)) - end - end) - |> JS.object_expression - |> make_map - end - - def make_property(%ESTree.Identifier{} = key, value) do - JS.property(key, value) - end - - def make_property(%ESTree.Literal{value: k}, value) when is_binary(k) do - key = case String.contains?(k, "-") do - true -> - JS.literal(k) - false -> - JS.identifier(k) - end - - JS.property(key, value) - end - - def make_property(key, value) do - JS.property(key, value, :init, false, false, true) - end - - def make_shorthand_property(%ESTree.Identifier{} = key) do - JS.property(key, key, :init, true) - end - - def make_map_update(map, data, env) do - map = Translator.translate!(map, env) - data = Translator.translate!({:%{}, [], data}, env) - - js_ast = JS.call_expression( - JS.member_expression( - JS.identifier("Object"), - JS.identifier("freeze") - ), - [ - JS.call_expression( - JS.member_expression( - JS.identifier("Object"), - JS.identifier("assign") - ), - [ - JS.object_expression([]), - map, - data - ] - ) - ] - ) - - { js_ast, env } - end - -end diff --git a/lib/elixir_script/translator/kernel/special_forms/match.ex b/lib/elixir_script/translator/kernel/special_forms/match.ex deleted file mode 100644 index b59ffd64..00000000 --- a/lib/elixir_script/translator/kernel/special_forms/match.ex +++ /dev/null @@ -1,93 +0,0 @@ -defmodule ElixirScript.Translator.Match do - @moduledoc false - alias ESTree.Tools.Builder, as: JS - alias ElixirScript.Translator - alias ElixirScript.Translator.PatternMatching - alias ElixirScript.Translator.Primitive - - def make_match(left, right, env) do - { right_ast, env } = Translator.translate(right, env) - - { patterns, params, env } = PatternMatching.process_match([left], env) - - declarator = JS.variable_declarator( - JS.array_pattern(params), - JS.call_expression( - JS.member_expression( - JS.member_expression( - JS.member_expression( - JS.identifier("Bootstrap"), - JS.identifier("Core") - ), - JS.identifier("Patterns") - ), - JS.identifier("match") - ), - [hd(patterns), right_ast] - ) - ) - - array_pattern = JS.variable_declaration([declarator], :let) - - js_ast = case left do - list when is_list(list) -> - make_list_ref(array_pattern, params) - { _, _ } -> - make_tuple_ref(array_pattern, params) - {:{}, _, _ } -> - make_tuple_ref(array_pattern, params) - _ -> - array_pattern - end - - { js_ast, env } - end - - defp make_list_ref(array_pattern, params) do - {ref, params} = make_params(params) - - ref_declarator = JS.variable_declarator( - ref, - Primitive.do_make_list(params) - ) - - make_variable_declaration_and_group(ref_declarator, array_pattern) - end - - defp make_tuple_ref(array_pattern, params) do - {ref, params} = make_params(params) - - ref_declarator = JS.variable_declarator( - ref, - JS.new_expression( - JS.member_expression( - JS.identifier("Bootstrap"), - JS.member_expression( - JS.identifier("Core"), - JS.identifier("Tuple") - ) - ), - params - ) - ) - - make_variable_declaration_and_group(ref_declarator, array_pattern) - end - - - defp make_params(params) do - ref = JS.identifier("_ref") - - params = Enum.map(params, fn - (nil) -> JS.identifier(:undefined) - (x) -> x - end) - - { ref, params } - end - - defp make_variable_declaration_and_group(ref_declarator, array_pattern) do - ref_declaration = JS.variable_declaration([ref_declarator], :let) - %ElixirScript.Translator.Group{ body: [array_pattern, ref_declaration] } - end -end diff --git a/lib/elixir_script/translator/kernel/special_forms/primitive.ex b/lib/elixir_script/translator/kernel/special_forms/primitive.ex deleted file mode 100644 index 292ccbcc..00000000 --- a/lib/elixir_script/translator/kernel/special_forms/primitive.ex +++ /dev/null @@ -1,99 +0,0 @@ -defmodule ElixirScript.Translator.Primitive do - @moduledoc false - alias ESTree.Tools.Builder, as: JS - alias ElixirScript.Translator - alias ElixirScript.Translator.Quote - - def special_forms() do - JS.member_expression( - JS.identifier("Bootstrap"), - JS.member_expression( - JS.identifier("Core"), - JS.identifier("SpecialForms") - ) - ) - end - - def tuple_class() do - JS.member_expression( - JS.member_expression( - JS.identifier("Bootstrap"), - JS.identifier("Core") - ), - JS.identifier("Tuple") - ) - end - - def list_ast() do - JS.member_expression( - JS.member_expression( - JS.identifier("Bootstrap"), - JS.member_expression( - JS.identifier("Core"), - JS.identifier("SpecialForms") - ) - ), - JS.identifier("list") - ) - end - - def make_atom(ast) when is_atom(ast) do - JS.call_expression( - JS.member_expression( - JS.identifier("Symbol"), - JS.identifier("for") - ), - [JS.literal(ast)] - ) - end - - def make_literal(ast) when is_number(ast) or is_binary(ast) or is_boolean(ast) or is_nil(ast) do - JS.literal(ast) - end - - def make_list(ast, env) when is_list(ast) do - js_ast = Enum.map(ast, &Translator.translate!(&1, env)) - |> do_make_list - - { js_ast, env } - end - - def make_list_quoted(opts, ast, env) when is_list(ast) do - Enum.map(ast, fn(x) -> Quote.make_quote(opts, x, env) end) - |> do_make_list - end - - def make_list_no_translate(ast) when is_list(ast) do - do_make_list(ast) - end - - def do_make_list(ast) do - JS.call_expression( - JS.member_expression( - JS.identifier("Object"), - JS.identifier("freeze") - ), - [JS.array_expression(ast)] - ) - end - - def make_tuple({ one, two }, env) do - make_tuple([one, two], env) - end - - def make_tuple(elements, env) do - list = Enum.map(elements, &Translator.translate!(&1, env)) - - js_ast = JS.new_expression(tuple_class, list) - - { js_ast, env } - end - - def make_tuple_quoted(opts, elements, env) do - JS.new_expression( - tuple_class, - Enum.map(elements, fn(x) -> Quote.make_quote(opts, x, env) end) - ) - end - -end diff --git a/lib/elixir_script/translator/kernel/special_forms/quote.ex b/lib/elixir_script/translator/kernel/special_forms/quote.ex deleted file mode 100644 index 63341757..00000000 --- a/lib/elixir_script/translator/kernel/special_forms/quote.ex +++ /dev/null @@ -1,87 +0,0 @@ -defmodule ElixirScript.Translator.Quote do - @moduledoc false - - alias ESTree.Tools.Builder, as: JS - alias ElixirScript.Translator - alias ElixirScript.Translator.Primitive - - def make_quote(_opts, expr, env) when is_number(expr) or is_binary(expr) or is_boolean(expr) or is_nil(expr) or is_atom(expr) do - Translator.translate!(expr, env) - end - - def make_quote(opts, expr, env) when is_list(expr) do - has_unquote_splicing = Enum.any?(expr, fn - ({:unquote_splicing, _, _}) -> true - (_) -> false - end) - - if has_unquote_splicing do - expr = Enum.map(expr, fn - ({:unquote_splicing, _, [param]}) -> - make_unquote_slicing(param, env) - (x) -> - Primitive.make_list_no_translate([make_quote(opts, x, env)]) - end - ) - - JS.call_expression( - JS.member_expression( - JS.identifier("Bootstrap"), - JS.member_expression( - JS.identifier("Enum"), - JS.identifier("concat") - ) - ), - expr - ) - else - Primitive.make_list_quoted(opts, expr, env) - end - end - - def make_quote(opts, {one, two}, env) do - Primitive.make_tuple_quoted(opts, [one, two], env) - end - - def make_quote([unquote: false] = opts, {:unquote, context, params}, env) do - Primitive.make_tuple_quoted(opts, [:unquote, context, params], env) - end - - def make_quote([context: {_, _, [new_context]}] = opts, {name, context, params}, env) do - updated_context = Keyword.put(context, :context, new_context) - Primitive.make_tuple_quoted(opts, [name, updated_context, params], env) - end - - def make_quote(_, {:alias!, _, [the_alias]}, _) do - the_alias - end - - def make_quote(_, {:unquote, _, [param]}, env) do - make_unquote(param, env) - end - - def make_quote(opts, {name, context, elements }, env) do - if is_in_bind_quoted(opts[:bind_quoted], name) do - Translator.translate!({name, context, elements }, env) - else - Primitive.make_tuple_quoted(opts, [name, context, elements], env) - end - end - - def make_unquote(expr, env) do - Translator.translate!(expr, env) - end - - def make_unquote_slicing(expr, env) do - Translator.translate!(expr, env) - end - - defp is_in_bind_quoted(nil, _) do - false - end - - defp is_in_bind_quoted(binds, name) do - binds[name] != nil - end - -end diff --git a/lib/elixir_script/translator/kernel/special_forms/struct.ex b/lib/elixir_script/translator/kernel/special_forms/struct.ex deleted file mode 100644 index 6d9f522f..00000000 --- a/lib/elixir_script/translator/kernel/special_forms/struct.ex +++ /dev/null @@ -1,116 +0,0 @@ -defmodule ElixirScript.Translator.Struct do - @moduledoc false - alias ESTree.Tools.Builder, as: JS - alias ElixirScript.Translator - alias ElixirScript.Translator.Utils - alias ElixirScript.Translator.Map - alias ElixirScript.Translator.Identifier - - def make_struct(attributes, env) do - struct_name = Map.make_property(Translator.translate!(:__struct__, env), Translator.translate!({:__MODULE__, [], []}, env)) - - defaults = Enum.map(attributes, fn - ({x, y}) -> - Map.make_property( - Translator.translate!(x, env), - Translator.translate!(y, env) - ) - (x) -> - Map.make_property( - Translator.translate!(x, env), - Translator.translate!(nil, env) - ) - end) - - keys = Enum.map(attributes, fn - ({x, _}) -> - Translator.translate!(x, env) - (x) -> - Translator.translate!(x, env) - end) - - keys = JS.array_expression(keys) - defaults = JS.object_expression([struct_name] ++ defaults) - - allowed_keys = JS.variable_declaration([JS.variable_declarator( - JS.identifier("allowed_keys"), - keys - )], :const) - - value_keys = JS.variable_declaration([JS.variable_declarator( - JS.identifier("value_keys"), - JS.call_expression( - JS.member_expression( - JS.identifier("Object"), - JS.identifier("keys") - ), - [JS.identifier("values")] - ) - )], :const) - - every_call = JS.call_expression( - JS.member_expression( - JS.identifier("value_keys"), - JS.identifier("every") - ), - [ - JS.function_expression([JS.identifier("key")], [], JS.block_statement([ - JS.return_statement( - JS.call_expression( - JS.member_expression( - JS.identifier("allowed_keys"), - JS.identifier("includes") - ), - [JS.identifier("key")] - ) - ) - ])) - ] - ) - - every_call_result = JS.variable_declaration([JS.variable_declarator( - JS.identifier("every_call_result"), - every_call - )], :const) - - bottom = JS.if_statement( - JS.identifier("every_call_result"), - JS.block_statement([ - JS.return_statement( - JS.call_expression( - JS.member_expression( - JS.identifier("Object"), - JS.identifier("assign") - ), - [JS.object_expression([]), defaults, JS.identifier("values")] - ) - ) - ]), - JS.block_statement([ - JS.throw_statement( - JS.literal("Unallowed key found") - ) - ]) - ) - - func = JS.function_expression([ - %ESTree.AssignmentPattern{ - left: JS.identifier("values"), - right: JS.object_expression([]) - } - ], - [], - JS.block_statement([ - allowed_keys, - value_keys, - every_call_result, - bottom - ])) - - JS.variable_declaration([JS.variable_declarator( - JS.identifier("__struct__"), - func - )], :const) - end - -end diff --git a/lib/elixir_script/translator/kernel/special_forms/try.ex b/lib/elixir_script/translator/kernel/special_forms/try.ex deleted file mode 100644 index 94276f23..00000000 --- a/lib/elixir_script/translator/kernel/special_forms/try.ex +++ /dev/null @@ -1,115 +0,0 @@ -defmodule ElixirScript.Translator.Try do - @moduledoc false - alias ESTree.Tools.Builder, as: JS - alias ElixirScript.Translator.Function - alias ElixirScript.Translator.Primitive - - def make_try(blocks, env) do - try_block = Keyword.get(blocks, :do) - rescue_block = Keyword.get(blocks, :rescue, nil) - catch_block = Keyword.get(blocks, :catch, nil) - after_block = Keyword.get(blocks, :after, nil) - else_block = Keyword.get(blocks, :else, nil) - - { translated_body, _ } = Function.prepare_function_body(try_block, env) - - translated_body = JS.block_statement(translated_body) - try_block = JS.function_expression([], [], translated_body) - - rescue_block = if rescue_block do - process_rescue_block(rescue_block, env) - else - JS.identifier(:null) - end - - catch_block = if catch_block do - process_catch_block(catch_block, env) - else - JS.identifier(:null) - end - - after_block = if after_block do - process_after_block(after_block, env) - else - JS.identifier(:null) - end - - else_block = if else_block do - Function.make_anonymous_function(else_block, env) - |> elem(0) - else - JS.identifier(:null) - end - - js_ast = JS.call_expression( - JS.member_expression( - Primitive.special_forms(), - JS.identifier("_try") - ), - [ - try_block, - rescue_block, - catch_block, - else_block, - after_block - ] - ) - - { js_ast, env } - end - - defp process_rescue_block(rescue_block, env) do - { func, _ } = Enum.map(rescue_block, fn(x) -> - case x do - {:->, _, [[{value, _, module}], block]} when not is_list(module) -> - {:->, [], [[{value, [], convert_to_struct(module, env)}], block]} - {:->, _, [[{:in, meta, [value, error_names]}], block]} -> - error_names = Enum.map(error_names, fn(x) -> - convert_to_struct(x, env) - end) - - guards = {:in, meta, [value, error_names]} - - {:->, [], [ [{:when, [], [value | [guards]]}], block ]} - {:->, _, [error_names, block]} -> - Enum.map(error_names, fn(x) -> - {:->, [], [[convert_to_struct(x, env)], block]} - end) - end - end) - |> List.flatten - |> Function.make_anonymous_function(env) - - func - end - - defp process_catch_block(catch_block, env) do - {func, _} = catch_block - |> Function.make_anonymous_function(env) - - func - end - - defp process_after_block(after_block, env) do - { translated_body, _ } = Function.prepare_function_body(after_block, env) - translated_body = JS.block_statement(translated_body) - - JS.function_expression([], [], translated_body) - end - - defp convert_to_struct([module], env) do - convert_to_struct(module, env) - end - - defp convert_to_struct(module, env) do - case module do - {:__aliases__, _, _} = alias_ast -> - alias_ast = ElixirScript.Translator.State.get_module_name(env.state, alias_ast) - |> ElixirScript.Translator.Utils.name_to_quoted - - {:%, [], [alias_ast, {:%{}, [], []}]} - ast -> - ast - end - end -end diff --git a/lib/elixir_script/translator/kernel/special_forms/with.ex b/lib/elixir_script/translator/kernel/special_forms/with.ex deleted file mode 100644 index dbd8b7bf..00000000 --- a/lib/elixir_script/translator/kernel/special_forms/with.ex +++ /dev/null @@ -1,52 +0,0 @@ -defmodule ElixirScript.Translator.With do - @moduledoc false - - alias ESTree.Tools.Builder, as: JS - alias ElixirScript.Translator.Function - alias ElixirScript.Translator.Primitive - alias ElixirScript.Translator.PatternMatching - - def make_with(args, env) do - result = Enum.reduce(args, %{ expressions: [], arguments: [] }, fn - {symbol, _, [pattern, expr] }, state when symbol in [:<-, :=] -> - {body , _} = Function.prepare_function_body(expr, env) - translated_body = JS.block_statement(body) - expr_function = JS.function_expression(state.arguments, [], translated_body) - - { patterns, params, _ } = PatternMatching.process_match([pattern], env) - - %{state | arguments: state.arguments ++ params, - expressions: state.expressions ++ [ JS.array_expression([hd(patterns), expr_function]) ] } - - [do: expr], state -> - expr_function = process_do_block(expr, state.arguments, env) - - %{state | expressions: state.expressions ++ [ expr_function ] } - [do: do_expr, else: else_expr], state -> - do_function = process_do_block(do_expr, state.arguments, env) - - { else_function, _ } = Function.make_anonymous_function(else_expr, env) - - %{state | expressions: state.expressions ++ [ do_function, else_function ] } - end) - - expressions = result.expressions - - js_ast = JS.call_expression( - JS.member_expression( - Primitive.special_forms(), - JS.identifier("_with") - ), - expressions - ) - - { js_ast, env } - - end - - defp process_do_block(expr, arguments, env) do - {body , _} = Function.prepare_function_body(expr, env) - translated_body = JS.block_statement(body) - JS.function_expression(arguments, [], translated_body) - end -end diff --git a/lib/elixir_script/translator/lexical_scope.ex b/lib/elixir_script/translator/lexical_scope.ex deleted file mode 100644 index f202e549..00000000 --- a/lib/elixir_script/translator/lexical_scope.ex +++ /dev/null @@ -1,394 +0,0 @@ -defmodule ElixirScript.Translator.LexicalScope do - @moduledoc false - - @type t :: %ElixirScript.Translator.LexicalScope{ - module: atom, - file: binary, - line: non_neg_integer, - function: { atom, non_neg_integer } | nil, - context: :match | :guard | :generator | nil, - aliases: [{atom, atom}], - requires: [atom], - functions: [{atom, [{ atom, non_neg_integer }]}], - macros: [{atom, [{ atom, non_neg_integer }]}], - macro_aliases: [{atom, {integer, atom}}], - context_modules: [atom], - vars: [{atom, atom | non_neg_integer}], - export_vars: [{atom, atom | non_neg_integer}] | nil, - lexical_tracker: nil, - caller: t | nil, - env: nil, - state: pid, - format: atom, - module_formatter: atom - } - - defstruct [ - module: nil, - file: nil, - line: 0, - function: nil, - context: nil, - aliases: [], - requires: [], - functions: [], - macros: [], - macro_aliases: [], - context_modules: [], - vars: [], - export_vars: nil, - lexical_tracker: nil, - caller: nil, - env: nil, - state: nil, - format: :es, - module_formatter: ElixirScript.ModuleSystems.ES - ] - - def env(scope) do - %Macro.Env{ - module: scope.module, - file: scope.file, - line: scope.line, - function: scope.function, - context: scope.context, - aliases: scope.aliases, - requires: scope.requires, - functions: scope.functions, - macros: scope.macros, - macro_aliases: scope.macro_aliases, - context_modules: scope.context_modules, - vars: Enum.map(scope.vars, fn({key, _}) -> {key, nil} end), - export_vars: scope.export_vars, - lexical_tracker: scope.lexical_tracker - } - end - - def caller(scope) do - %Macro.Env{ - module: scope.caller.module, - file: scope.caller.file, - line: scope.caller.line, - function: scope.caller.function, - context: scope.caller.context, - aliases: scope.caller.aliases, - requires: scope.caller.requires, - functions: scope.caller.functions, - macros: scope.caller.macros, - macro_aliases: scope.caller.macro_aliases, - context_modules: scope.caller.context_modules, - vars: Enum.map(scope.vars, fn({key, _}) -> {key, nil} end), - export_vars: scope.caller.export_vars, - lexical_tracker: scope.caller.lexical_tracker - } - end - - def module_scope(ElixirScript.Temp, filename, env, state, opts) do - - env = %ElixirScript.Translator.LexicalScope { - module: ElixirScript.Temp, file: filename, requires: [], - functions: [], - macros: [], - env: env, - state: state, - format: opts.format, - module_formatter: opts.module_formatter - } - - add_import(env, ElixirScript.Kernel) - end - - def module_scope(module_name, filename, env, state, opts) do - module = ElixirScript.Translator.State.get_module(state, module_name) - - env = %ElixirScript.Translator.LexicalScope { - module: module_name, file: filename, requires: [], - functions: [{ module.name, module.functions}], - macros: [{module.name, module.macros}], - env: env, - state: state, - format: opts.format, - module_formatter: opts.module_formatter - } - - env = add_import(env, ElixirScript.Kernel) - - cond do - module_name == JS -> - env - ElixirScript.Translator.State.is_module_loaded?(env.state, module_name) and length(module.macros) > 0 -> - add_import(env, module_name, [only: :macros]) - true -> - env - end - end - - def function_scope(env, { _, _ } = func) do - %{ env | function: func, caller: env} - end - - def function_scope(env, nil) do - %{ env | function: nil, caller: env } - end - - def find_module(env, name_arity) do - result = Enum.find(env.functions ++ env.macros, fn({_, functions}) -> - name_arity in functions - end) - - if result == nil do - nil - else - elem(result, 0) - end - - end - - def add_var(env, variable_name) when is_binary(variable_name) do - add_var(env, String.to_atom(variable_name)) - end - - def add_var(env, variable_name) do - %{ env | vars: Keyword.update(env.vars, variable_name, 0, &(&1 + 1)) } - end - - def get_var(env, variable_name) when is_binary(variable_name) do - get_var(env, String.to_atom(variable_name)) - end - - def get_var(env, variable_name) do - count = Keyword.get(env.vars, variable_name, nil) - - case count do - nil -> - nil - 0 -> - String.to_atom(Atom.to_string(variable_name)) - _ -> - String.to_atom(Atom.to_string(variable_name) <> to_string(count)) - end - end - - def has_var?(env, variable_name) when is_binary(variable_name) do - has_var?(env, String.to_atom(variable_name)) - end - - def has_var?(env, variable_name) do - Keyword.get(env.vars, variable_name, nil) != nil - end - - defp get_module(env, Kernel) do - get_module(env, ElixirScript.Kernel) - end - - defp get_module(env, module_name) do - module = ElixirScript.Translator.State.get_module(env.state, get_module_name(env, module_name)) - - unless module do - module_name = case module_name do - {:__aliases__, _, _} -> - ElixirScript.Translator.Utils.quoted_to_name(module_name) - |> Atom.to_string - |> String.split(".") - |> tl - |> Enum.join(".") - _ -> - module_name - end - - raise "Module #{inspect module_name} not found" - end - - if Map.get(module, :load_only, false) == false do - ElixirScript.Translator.State.add_module_reference(env.state, env.module, module.name) - end - - module - end - - defp has_module?(env, module_name) do - try do - module = get_module(env, module_name) - case module do - %{load_only: true} -> - false - _ -> - true - end - rescue - _ -> - false - end - end - - def add_alias(env, module_name, alias_name) do - module = get_module(env, module_name) - %{ env | aliases: Enum.uniq(env.aliases ++ [{alias_name, module.name}]) } - end - - def add_import(env, module_name) do - check_for_module_existence(env, module_name) - ElixirScript.Translator.State.add_module_reference(env.state, env.module, module_name) - - env = if ElixirScript.Translator.State.is_module_loaded?(env.state, module_name) do - add_import_macro(env, module_name, []) - else - env - end - - if has_module?(env, module_name) do - module = get_module(env, module_name) - %{ env | requires: Enum.uniq(env.requires ++ [module.name]), - functions: env.functions ++ [{ module.name, module.functions }] - } - else - env - end - end - - def add_import(env, module_name, [only: :functions]) do - module = get_module(env, module_name) - ElixirScript.Translator.State.add_module_reference(env.state, env.module, module_name) - - %{ env | functions: List.keydelete(env.functions, module_name, 0) ++ [{ module.name, module.functions }], - requires: Enum.uniq(env.requires ++ [module.name]) - } - end - - def add_import(env, module_name, [only: :macros]) do - if !ElixirScript.Translator.State.is_module_loaded?(env.state, module_name) do - raise "Module #{inspect module_name} not found" - end - - add_import_macro(env, module_name, [only: :macros]) - end - - def add_import(env, module_name, [only: only]) do - check_for_module_existence(env, module_name) - ElixirScript.Translator.State.add_module_reference(env.state, env.module, module_name) - - env = if ElixirScript.Translator.State.is_module_loaded?(env.state, module_name) do - list = module_name.__info__(:macros) - list = Enum.filter(list, fn(mac) -> mac in only end) - add_import_macro(env, module_name, [only: list]) - else - env - end - - if has_module?(env, module_name) do - module = get_module(env, module_name) - - functions = Enum.filter(module.functions, fn(func) -> - func in only - end) - - %{ env | requires: Enum.uniq(env.requires ++ [module.name]), - functions: List.keydelete(env.functions, module.name, 0) ++ [{ module.name, functions }] } - else - env - end - end - - def add_import(env, module_name, [except: except]) do - check_for_module_existence(env, module_name) - ElixirScript.Translator.State.add_module_reference(env.state, env.module, module_name) - - env = if ElixirScript.Translator.State.is_module_loaded?(env.state, module_name) do - list = module_name.__info__(:macros) - list = Enum.filter(list, fn(mac) -> mac in except end) - add_import_macro(env, module_name, [except: list]) - else - env - end - - if has_module?(env, module_name) do - module = get_module(env, module_name) - {_, current_functions } = List.keyfind(env.functions, module.name, 0, { module.name, module.functions }) - - functions = Enum.filter(current_functions, fn(func) -> not(func in except) end) - - %{ env | requires: env.requires ++ [module.name], - functions: List.keydelete(env.functions, module.name, 0) ++ [{ module.name, functions }] } - else - env - end - end - - def add_require(env, module_name) do - check_for_module_existence(env, module_name) - ElixirScript.Translator.State.add_module_reference(env.state, env.module, module_name) - - env = if ElixirScript.Translator.State.is_module_loaded?(env.state, module_name) do - add_require_macro(env, module_name, []) - else - env - end - - if has_module?(env, module_name) do - module = get_module(env, module_name) - %{ env | requires: Enum.uniq(env.requires ++ [module.name]) } - else - env - end - end - - def add_require(env, module_name, alias_name) do - check_for_module_existence(env, module_name) - ElixirScript.Translator.State.add_module_reference(env.state, env.module, module_name) - - env = if ElixirScript.Translator.State.is_module_loaded?(env.state, module_name) do - add_require_macro(env, module_name, [as: alias_name]) - else - env - end - - if has_module?(env, module_name) do - module = get_module(env, module_name) - %{ env | aliases: Enum.uniq(env.aliases ++ [{alias_name, module.name}]), - requires: Enum.uniq(env.requires ++ [module.name]) } - else - env - end - end - - def get_module_name(env, module_name) do - module_name = ElixirScript.Translator.State.get_module_name(env.state, module_name) - - if Keyword.has_key?(env.aliases, module_name) do - Keyword.fetch!(env.aliases, module_name) - else - module_name - end - - end - - defp check_for_module_existence(env, module_name) do - if ElixirScript.Translator.State.is_module_loaded?(env.state, module_name) == false and has_module?(env, module_name) == false do - raise "Module #{inspect module_name} not found" - end - end - - - defp add_import_macro(elixirscript_env, module, opts) do - eval = """ - import #{inspect module}, #{inspect opts} - __ENV__ - """ - - do_macro(eval, elixirscript_env) - end - - defp add_require_macro(elixirscript_env, module, opts) do - eval = """ - require #{inspect module}, #{inspect opts} - __ENV__ - """ - - do_macro(eval, elixirscript_env) - end - - defp do_macro(eval, elixirscript_env) do - {env, _} = Code.eval_string(eval, [], elixirscript_env.env) - %{ elixirscript_env | env: env } - end -end diff --git a/lib/elixir_script/translator/pattern_matching.ex b/lib/elixir_script/translator/pattern_matching.ex deleted file mode 100644 index d03892b5..00000000 --- a/lib/elixir_script/translator/pattern_matching.ex +++ /dev/null @@ -1,278 +0,0 @@ -defmodule ElixirScript.Translator.PatternMatching do - @moduledoc false - - alias ESTree.Tools.Builder, as: JS - alias ElixirScript.Translator - alias ElixirScript.Translator.Primitive - alias ElixirScript.Translator.Identifier - alias ElixirScript.Translator.Map - alias ElixirScript.Translator.Struct - alias ElixirScript.Translator.Bitstring - alias ElixirScript.Translator.Utils - - @patterns JS.member_expression( - JS.member_expression( - JS.identifier("Bootstrap"), - JS.identifier("Core") - ), - JS.identifier("Patterns") - ) - - @wildcard JS.member_expression( - @patterns, - JS.identifier(:wildcard) - ) - - @parameter JS.member_expression( - @patterns, - JS.identifier(:variable) - ) - - @head_tail JS.member_expression( - @patterns, - JS.identifier(:headTail) - ) - - @starts_with JS.member_expression( - @patterns, - JS.identifier(:startsWith) - ) - - @capture JS.member_expression( - @patterns, - JS.identifier(:capture) - ) - - @bound JS.member_expression( - @patterns, - JS.identifier(:bound) - ) - - @_type JS.member_expression( - @patterns, - JS.identifier(:type) - ) - - @bitstring_match JS.member_expression( - @patterns, - JS.identifier(:bitStringMatch) - ) - - def wildcard() do - JS.call_expression( - @wildcard, - [] - ) - end - - def parameter() do - JS.call_expression( - @parameter, - [] - ) - end - - def parameter(default_value) do - JS.call_expression( - @parameter, - [default_value] - ) - end - - def head_tail(headParameter, tailParameter) do - JS.call_expression( - @head_tail, - [headParameter, tailParameter] - ) - end - - def starts_with(prefix) do - JS.call_expression( - @starts_with, - [JS.literal(prefix)] - ) - end - - def capture(value) do - JS.call_expression( - @capture, - [value] - ) - end - - def bound(value) do - JS.call_expression( - @bound, - [value] - ) - end - - def type(prototype, value) do - JS.call_expression( - @_type, - [prototype, value] - ) - end - - def bitstring_match(values) do - JS.call_expression( - @bitstring_match, - values - ) - end - - - def process_match(params, env) do - build_match(params, env) - |> update_env(env) - end - - defp update_env({ patterns, params }, env) do - - { params, env } = Enum.map_reduce(params, env, fn - (%ESTree.Identifier{name: :undefined} = param, env) -> - { param, env } - - (%ESTree.Identifier{} = param, env) -> - env = ElixirScript.Translator.LexicalScope.add_var(env, param.name) - new_name = ElixirScript.Translator.LexicalScope.get_var(env, param.name) - - { %{ param | name: new_name }, env } - - (param, env) -> - { param, env } - end) - - { patterns, params, env } - end - - def build_match(params, env) do - Enum.map(params, &do_build_match(&1, env)) - |> reduce_patterns - end - - defp do_build_match({:^, _, [value]}, env) do - { [bound(Translator.translate!(value, env))], [nil] } - end - - defp do_build_match({:_, _, _}, _) do - { [parameter()], [JS.identifier(:__ignored__)] } - end - - defp do_build_match({:<<>>, _, elements}, env) do - params = Enum.reduce(elements, [], fn - ({:::, _, [{ variable, _, params }, _]}, state) when is_atom(params) -> - state ++ [JS.identifier(variable)] - _, state -> - state - end) - - elements = Enum.map(elements, fn - ({:::, context, [{ _, _, params }, options]}) when is_atom(params) -> - Bitstring.make_bitstring_element({:::, context, [ElixirScript.Translator.PatternMatching, options]}, env) - x -> - Bitstring.make_bitstring_element(x, env) - end) - - { [bitstring_match(elements)], params } - end - - defp do_build_match([{:|, _, [head, tail]}], env) do - { head_patterns, head_params } = do_build_match(head, env) - { tail_patterns, tail_params } = do_build_match(tail, env) - params = head_params ++ tail_params - - { [head_tail(hd(head_patterns), hd(tail_patterns))], params } - end - - defp do_build_match({:<>, _, [prefix, value]}, env) do - { [starts_with(prefix)], [Translator.translate!(value, env)] } - end - - defp do_build_match({:%{}, _, props}, env) do - properties = Enum.map(props, fn({key, value}) -> - {pattern, params} = do_build_match(value, env) - property = case key do - {:^, _, [the_key]} -> - JS.property(Translator.translate!(the_key, env), hd(List.wrap(pattern)), :init, false, false, true) - _ -> - Map.make_property(Translator.translate!(key, env), hd(List.wrap(pattern))) - end - - { property, params } - end) - - {props, params} = Enum.reduce(properties, {[], []}, fn({prop, param}, {props, params}) -> - { props ++ [prop], params ++ param } - end) - - { JS.object_expression(List.wrap(props)), params } - end - - defp do_build_match({:%, _, [{:__aliases__, _, name}, {:%{}, meta, props}]}, env) do - module_name = ElixirScript.Translator.State.get_module_name(env.state, Utils.quoted_to_name(name)) - name = Utils.name_to_js_file_name(module_name) - {pattern, params} = do_build_match({:%{}, meta, [__struct__: String.to_atom(name)] ++ props}, env) - - { pattern, params } - end - - defp do_build_match({:=, _, [{name, _, _}, right]}, env) when not name in [:%, :{}, :__aliases__, :^, :%{}] do - unify(name, right, env) - end - - defp do_build_match({:=, _, [left, {name, _, _}]}, env) when not name in [:%, :{}, :__aliases__, :^, :%{}] do - unify(name, left, env) - end - - defp do_build_match(list, env) when is_list(list) do - { patterns, params } = list - |> Enum.map(&build_match([&1], env)) - |> reduce_patterns - - {[Primitive.make_list_no_translate(patterns)], params} - end - - defp do_build_match(term, env) when is_number(term) or is_binary(term) or is_boolean(term) or is_atom(term) or is_nil(term) do - { [Translator.translate!(term, env)], [] } - end - - defp do_build_match({ one, two }, env) do - do_build_match({:{}, [], [one, two]}, env) - end - - defp do_build_match({:{}, _, list}, env) do - { patterns, params } = list - |> Enum.map(&build_match([&1], env)) - |> reduce_patterns - - tuple_pattern = JS.new_expression( - Primitive.tuple_class(), - patterns - ) - - { [tuple_pattern], params } - end - - defp do_build_match({:\\, _, [{name, _, _}, default]}, env) do - { [parameter(Translator.translate!(default, env))], [Identifier.make_identifier(name)] } - end - - - defp do_build_match({name, _, _}, _) do - { [parameter()], [Identifier.make_identifier(name)] } - end - - defp reduce_patterns(patterns) do - patterns - |> Enum.reduce({ [], [] }, fn({ pattern, new_param }, { patterns, new_params }) -> - { patterns ++ List.wrap(pattern), new_params ++ List.wrap(new_param) } - end) - end - - defp unify(target, source, env) do - { patterns, params } = build_match([source], env) - { [capture(hd(patterns))], params ++ [Identifier.make_identifier(target)] } - end - -end diff --git a/lib/elixir_script/translator/rewriter.ex b/lib/elixir_script/translator/rewriter.ex deleted file mode 100644 index cd018686..00000000 --- a/lib/elixir_script/translator/rewriter.ex +++ /dev/null @@ -1,495 +0,0 @@ -defmodule ElixirScript.Translator.Rewriter do - @moduledoc false - - # :erlang, :lists, :maps, :beam_lib, :binary, :calendar, :digraph, - # :epp, :erl_lint, :erl_internal, :erl_expand_records, :erl_eval, - # :ets, :filename, :gen_event, :gen_server, :io, :io_lib, :math, - # :ordsets, :proc_lib, :rand, :re, :sets, :supervisor,:sys, :timer, - # :unicode, :os, :application, :code, :gen_tcp, :error_logger, :gen, - # :file - # http://erlang.org/doc/applications.html - - - def rewrite({{:., _, [:erlang, :abs]}, _, [number]}) do - quote do: Math.abs(unquote(number)) - end - - def rewrite({{:., _, [:erlang, :apply]}, _, [fun, args]}) do - quote do: unquote(fun).apply(nil, unquote(args)) - end - - def rewrite({{:., _, [:erlang, :apply]}, _, [module, fun, args]}) do - quote do: unquote(module).unquote(fun).apply(nil, unquote(args)) - end - - def rewrite({{:., _, [:erlang, :binary_part]}, _, [binary, start, length]})do - quote do: unquote(binary).substring(unquote(start), unquote(length)) - end - - def rewrite({{:., _, [:erlang, :bit_size]}, _, [bitstring]})do - quote do: unquote(bitstring).bit_size - end - - def rewrite({{:., _, [:erlang, :byte_size]}, _, [bitstring]})do - quote do: unquote(bitstring).byte_size - end - - def rewrite({{:., _, [:erlang, :div]}, _, [left, right]}) do - quote do: unquote(left) / unquote(right) - end - - def rewrite({{:., _, [:erlang, :exit]}, _, [reason]}) do - # TODO: implement exit - quote do: nil - end - - def rewrite({{:., _, [:erlang, :hd]}, _, [list]}) do - quote do: unquote(list)[0] - end - - def rewrite({{:., _, [:erlang, :is_atom]}, _, [term]}) do - quote do: JS.typeof(unquote(term)) === "symbol" - end - - def rewrite({{:., _, [:erlang, :is_binary]}, _, [term]}) do - quote do: JS.typeof(unquote(term)) === "string" - end - - def rewrite({{:., _, [:erlang, :is_bitstring]}, _, [term]}) do - quote do: is_binary(unquote(term)) || JS.instanceof(unquote(term), Bootstrap.Core.BitString) - end - - def rewrite({{:., _, [:erlang, :is_boolean]}, _, [term]}) do - quote do: JS.typeof(unquote(term)) === "boolean" || JS.instanceof(unquote(term), Boolean) - end - - def rewrite({{:., _, [:erlang, :is_float]}, _, [term]}) do - quote do: (JS.typeof(unquote(term)) === "number" || JS.instanceof(unquote(term), Number)) && !Number.isInteger(unquote(term)) - end - - def rewrite({{:., _, [:erlang, :is_function]}, _, [term]}) do - quote do: JS.typeof(unquote(term)) === "function" || JS.instanceof(unquote(term), Function) - end - - def rewrite({{:., _, [:erlang, :is_function]}, _, [term, _]}) do - quote do: JS.typeof(unquote(term)) === "function" || JS.instanceof(unquote(term), Function) - end - - def rewrite({{:., _, [:erlang, :is_integer]}, _, [term]}) do - quote do: Number.isInteger(unquote(term)) - end - - def rewrite({{:., _, [:erlang, :is_list]}, _, [term]}) do - quote do: Array.isArray(unquote(term)) - end - - def rewrite({{:., _, [:erlang, :is_number]}, _, [term]}) do - quote do: JS.typeof(unquote(term)) === "number" || JS.instanceof(unquote(term), Number) - end - - def rewrite({{:., _, [:erlang, :is_pid]}, _, [term]}) do - quote do: JS.instanceof(unquote(term), Bootstrap.Core.PID) - end - - def rewrite({{:., _, [:erlang, :is_port]}, _, [_term]}) do - #TODO implement is_port - quote do: false - end - - def rewrite({{:., _, [:erlang, :is_reference]}, _, [_term]}) do - #TODO implement is_reference - quote do: false - end - - def rewrite({{:., _, [:erlang, :is_tuple]}, _, [term]}) do - quote do: JS.instanceof(unquote(term), Bootstrap.Core.Tuple) - end - - def rewrite({{:., _, [:erlang, :is_map]}, _, [term]}) do - quote do: JS.typeof(unquote(term)) === "object" || JS.instanceof(unquote(term), Object) - end - - def rewrite({{:., _, [:erlang, :length]}, _, [list]}) do - quote do: unquote(list).length - end - - def rewrite({{:., _, [:erlang, :make_ref]}, _, []}) do - #TODO: implement make_ref - quote do: nil - end - - def rewrite({{:., _, [:erlang, :map_size]}, _, [map]}) do - quote do: Object.keys(unquote(map)).length - end - - def rewrite({{:., _, [:erlang, :max]}, _, [first, second]}) do - quote do: Math.max(unquote(first), unquote(second)) - end - - def rewrite({{:., _, [:erlang, :min]}, _, [first, second]}) do - quote do: Math.min(unquote(first), unquote(second)) - end - - def rewrite({{:., _, [:erlang, :node]}, _, []}) do - quote do: :nonode@nohost - end - - def rewrite({{:., _, [:erlang, :node]}, _, [_]}) do - quote do: :nonode@nohost - end - - def rewrite({{:., _, [:erlang, :rem]}, _, [first, second]}) do - {:%, [], [first, second]} - end - - def rewrite({{:., _, [:erlang, :round]}, _, [number]}) do - quote do: Math.round(unquote(number)) - end - - def rewrite({{:., _, [:erlang, :send]}, _, [dest, msg]}) do - #TODO implement send - quote do: unquote(msg) - end - - def rewrite({{:., _, [:erlang, :self]}, _, []}) do - #TODO: implement self - quote do: nil - end - - def rewrite({{:., _, [:erlang, :spawn]}, _, [_fun]}) do - #TODO: implement spawn - quote do: nil - end - - def rewrite({{:., _, [:erlang, :spawn]}, _, [_module, _fun, _args]}) do - #TODO: implement spawn - quote do: nil - end - - def rewrite({{:., _, [:erlang, :spawn_link]}, _, [_fun]}) do - #TODO: implement spawn_link - quote do: nil - end - - def rewrite({{:., _, [:erlang, :spawn_link]}, _, [_module, _fun, _args]}) do - #TODO: implement spawn_link - quote do: nil - end - - def rewrite({{:., _, [:erlang, :spawn_monitor]}, _, [_fun]}) do - #TODO: implement spawn_monitor - quote do: nil - end - - def rewrite({{:., _, [:erlang, :spawn_monitor]}, _, [_module, _fun, _args]}) do - #TODO: implement spawn_monitor - quote do: nil - end - - def rewrite({{:., _, [:erlang, :throw]}, _, [term]}) do - quote do: JS.throw(unquote(term)) - end - - def rewrite({{:., _, [:erlang, :tl]}, _, [list]}) do - quote do: unquote(list).splice(1) - end - - def rewrite({{:., _, [:erlang, :trunc]}, _, [number]}) do - quote do: Math.floor(unquote(number)) - end - - def rewrite({{:., _, [:erlang, :tuple_size]}, _, [tuple]}) do - quote do: unquote(tuple).length - end - - def rewrite({{:., _, [:erlang, operator]}, _, [left, right]}) when operator in [:+, :-, :*, :/, :<, :>, :>=, :==] do - {operator, [], [left, right]} - end - - def rewrite({{:., _, [:erlang, operator]}, _, [value]}) when operator in [:+, :-] do - {operator, [], [value]} - end - - def rewrite({{:., _, [:erlang, :++]}, _, [left, right]}) do - quote do: unquote(left).concat(unquote(right)) - end - - def rewrite({{:., _, [:erlang, :--]}, _, [list, element]}) do - quote do: unquote(list).slice(unquote(list).indexOf(unquote(element)) + 1) - end - - def rewrite({{:., _, [:erlang, :not]}, _, [value]}) do - {:!, [], [value]} - end - - def rewrite({{:., _, [:erlang, :"=<"]}, _, [left, right]}) do - {:<=, [], [left, right]} - end - - def rewrite({{:., _, [:erlang, :"/="]}, _, [left, right]}) do - {:!=, [], [left, right]} - end - - def rewrite({{:., _, [:erlang, :"=:="]}, _, [left, right]}) do - {:===, [], [left, right]} - end - - def rewrite({{:., _, [:erlang, :"=/="]}, _, [left, right]}) do - {:!==, [], [left, right]} - end - - def rewrite({{:., _, [:erlang, :element]}, _, [index, tuple]}) do - quote do: unquote(tuple).get(unquote(index) - 1) - end - - def rewrite({{:., _, [:erlang, :setelement]}, _, [index, tuple, value]}) do - quote do: unquote(tuple).put_elem(unquote(index) - 1, unquote(value)) - end - - def rewrite({{:., _, [:erlang, :orelse]}, _, [left, right]}) do - {:||, [], [left, right]} - end - - def rewrite({{:., _, [:erlang, :or]}, _, [left, right]}) do - {:||, [], [left, right]} - end - - def rewrite({{:., _, [:erlang, :andalso]}, _, [left, right]}) do - {:&&, [], [left, right]} - end - - def rewrite({{:., _, [:erlang, :error]}, _, [error]}) do - quote do: JS.throw(unquote(error)) - end - - def rewrite({{:., _, [:erlang, :raise]}, _, [_class, reason, _stacktrace]}) do - quote do: JS.throw(unquote(reason)) - end - - def rewrite({{:., _, [:erlang, :atom_to_binary]}, _, [atom, _]}) do - quote do: Symbol.keyFor(unquote(atom)) - end - - def rewrite({{:., _, [:erlang, :atom_to_list]}, _, [atom]}) do - quote do: to_string(unquote(atom)).split("") - end - - def rewrite({{:., _, [:erlang, :bnot]}, _, [expr]}) do - {:"~", [], [expr]} - end - - def rewrite({{:., _, [:erlang, :band]}, _, [left, right]}) do - {:&, [], [left, right]} - end - - def rewrite({{:., _, [:erlang, :bor]}, _, [left, right]}) do - {:|, [], [left, right]} - end - - def rewrite({{:., _, [:erlang, :bxor]}, _, [left, right]}) do - {:^, [], [left, right]} - end - - def rewrite({{:., _, [:erlang, :bsl]}, _, [left, right]}) do - {:"<<", [], [left, right]} - end - - def rewrite({{:., _, [:erlang, :bsr]}, _, [left, right]}) do - {:">>", [], [left, right]} - end - - def rewrite({{:., _, [:erlang, :function_exported]}, _, [_, _, _]}) do - quote do: true - end - - def rewrite({{:., _, [:erlang, :make_tuple]}, _, [size, data]}) do - quote do: JS.new(Bootstrap.Core.Tuple, List.duplicate(unquote(size), unquote(data))) - end - - def rewrite({{:., _, [:erlang, :insert_element]}, _, [index, tuple, term]}) do - quote do: unquote(tuple).put_elem(unquote(index) - 1, unquote(term)) - end - - def rewrite({{:., _, [:erlang, :tuple_to_list]}, _, [tuple]}) do - quote do: unquote(tuple).values - end - - def rewrite({{:., _, [:erlang, :append_element]}, _, [tuple, value]}) do - quote do: unquote(tuple).put_elem(unquote(tuple).length, unquote(value)) - end - - def rewrite({{:., _, [:erlang, :delete_element]}, _, [index, tuple]}) do - quote do: unquote(tuple).remove_elem(unquote(index)) - end - - def rewrite({{:., _, [:lists, :map]}, _, [fun, list]}) do - quote do: unquote(list).map(unquote(fun)) - end - - def rewrite({{:., _, [:lists, :member]}, _, [elem, list]}) do - quote do: unquote(list).indexOf(unquote(elem)) > -1 - end - - def rewrite({{:., _, [:lists, :foldl]}, _, [fun, acc, list]}) do - quote do: List.foldl(unquote(fun), unquote(acc), unquote(list)) - end - - def rewrite({{:., _, [:lists, :foldr]}, _, [fun, acc, list]}) do - quote do: List.foldr(unquote(fun), unquote(acc), unquote(list)) - end - - def rewrite({{:., _, [:lists, :keymember]}, _, [key, n, list]}) do - quote do: List.keymember?(unquote(list), unquote(key), unquote(n)) - end - - def rewrite({{:., _, [:lists, :keydelete]}, _, [key, n, list]}) do - quote do: List.keydelete(unquote(list), unquote(key), unquote(n)) - end - - def rewrite({{:., _, [:lists, :keyfind]}, _, [key, n, list]}) do - quote do: List.keyfind(unquote(list), unquote(key), unquote(n)) - end - - def rewrite({{:., _, [:lists, :keyreplace]}, _, [key, n, list, newtuple]}) do - quote do: List.keyreplace(unquote(list), unquote(key), unquote(n), unquote(newtuple)) - end - - def rewrite({{:., _, [:lists, :keysort]}, _, [n, tuplelist]}) do - #TODO: implement keysort - quote do: unquote(tuplelist) - end - - def rewrite({{:., _, [:lists, :reverse]}, _, [list]}) do - quote do: ElixirScript.Bootstrap.Functions.reverse(unquote(list)) - end - - def rewrite({{:., _, [:lists, :reverse]}, _, [list, tail]}) do - quote do: ElixirScript.Bootstrap.Functions.reverse(unquote(list)) ++ unquote(tail) - end - - def rewrite({{:., _, [:lists, :flatten]}, _, [list]}) do - quote do: List.flatten(unquote(list)) - end - - def rewrite({{:., _, [:lists, :flatten]}, _, [list, tail]}) do - quote do: List.flatten(unquote(list), unquote(tail)) - end - - def rewrite({{:., _, [:lists, :delete]}, _, [elem, list]}) do - quote do: List.delete(unquote(list), unquote(elem)) - end - - def rewrite({{:., _, [:lists, :duplicate]}, _, [n, elem]}) do - quote do: List.duplicate(unquote(n), unquote(elem)) - end - - def rewrite({{:., _, [:lists, :sort]}, _, [list]}) do - quote do: unquote(list).sort() - end - - #TODO: Implement sort - def rewrite({{:., _, [:lists, :sort]}, _, [_fun, list]}) do - quote do: unquote(list) - end - - def rewrite({{:., _, [:lists, :filter]}, _, [pred, list]}) do - quote do: unquote(list).filter(unquote(pred)) - end - - def rewrite({{:., _, [:lists, :concat]}, _, [things]}) do - quote do: unquote(things).join("") - end - - def rewrite({{:., _, [:erlang, :binary_to_atom]}, _, [binary, _]}) do - quote do: Symbol.for(unquote(binary)) - end - - def rewrite({{:., _, [:erlang, :binary_to_existing_atom]}, _, [binary, _]}) do - quote do: Symbol.for(unquote(binary)) - end - - def rewrite({{:., _, [:erlang, :list_to_atom]}, _, [char_list]}) do - quote do: Symbol.for(unquote(char_list)) - end - - def rewrite({{:., _, [:erlang, :list_to_existing_atom]}, _, [char_list]}) do - quote do: Symbol.for(unquote(char_list)) - end - - def rewrite({{:., _, [:erlang, :list_to_tuple]}, _, [list]}) do - quote do: JS.new(Bootstrap.Core.Tuple, unquote(list)) - end - - def rewrite({{:., _, [:erlang, :list_to_float]}, _, [list]}) do - quote do: JS.parseFloat(unquote(list)) - end - - def rewrite({{:., _, [:erlang, :list_to_integer]}, _, [list]}) do - quote do: JS.parseInt(unquote(list)) - end - - def rewrite({{:., _, [:erlang, :list_to_integer]}, _, [list, base]}) do - quote do: JS.parseInt(unquote(list), unquote(base)) - end - - def rewrite({{:., _, [:erlang, :integer_to_binary]}, _, [integer]}) do - quote do: unquote(integer).toString() - end - - def rewrite({{:., _, [:erlang, :integer_to_binary]}, _, [integer, base]}) do - quote do: unquote(integer).toString(unquote(base)) - end - - def rewrite({{:., _, [:erlang, :integer_to_list]}, _, [integer]}) do - quote do: unquote(integer).toString() - end - - def rewrite({{:., _, [:erlang, :integer_to_list]}, _, [integer, base]}) do - quote do: unquote(integer).toString(unquote(base)) - end - - def rewrite({{:., _, [:erlang, :float_to_binary]}, _, [float]}) do - quote do: unquote(float).toString() - end - - def rewrite({{:., _, [:erlang, :float_to_binary]}, _, [float, base]}) do - quote do: unquote(float).toString(unquote(base)) - end - - def rewrite({{:., _, [:erlang, :float_to_list]}, _, [float]}) do - quote do: unquote(float).toString() - end - - def rewrite({{:., _, [:erlang, :float_to_list]}, _, [float, base]}) do - quote do: unquote(float).toString(unquote(base)) - end - - def rewrite({{:., _, [:erlang, :binary_to_float]}, _, [binary]}) do - quote do: JS.parseFloat(unquote(binary)) - end - - def rewrite({{:., _, [:erlang, :binary_to_integer]}, _, [binary]}) do - quote do: JS.parseInt(unquote(binary)) - end - - def rewrite({{:., _, [:erlang, :binary_to_integer]}, _, [binary, base]}) do - quote do: JS.parseInt(unquote(binary), unquote(base)) - end - - def rewrite({{:., _, [:maps, :is_key]}, _, [key, map]}) do - quote do: unquote(key) in ElixirScript.Bootstrap.Functions.get_object_keys(unquote(map)) - end - - def rewrite({{:., _, [:maps, :put]}, _, [key, value, map]}) do - quote do: ElixirScript.Bootstrap.Functions.add_property_to_map(unquote(map), unquote(key), unquote(value)) - end - - def rewrite({{:., _, [:maps, :update]}, _, [key, value, map]}) do - quote do: Map.update!(unquote(map), unquote(key), fn(_) -> unquote(value) end) - end - - def rewrite({{:., _, [:maps, :remove]}, _, [key, map]}) do - quote do: ElixirScript.Bootstrap.Functions.delete_property_from_map(unquote(map), unquote(key)) - end - -end diff --git a/lib/elixir_script/translator/state.ex b/lib/elixir_script/translator/state.ex deleted file mode 100644 index a7f27da3..00000000 --- a/lib/elixir_script/translator/state.ex +++ /dev/null @@ -1,143 +0,0 @@ -# This agent holds references to the compiler options, a map all of the modules, and -# a map of modules that define the standard library. -# -# The modules map has the module's name a the key and a ElixirScript.Module struct as the value. -# -# The std_lib_map holds a mapping of the Elixir standard lib module to the -# version implemented here in ElixirScript. -defmodule ElixirScript.Translator.State do - @moduledoc false - alias ElixirScript.Translator.Utils - - def start_link(compiler_opts, loaded_modules) do - Agent.start_link(fn -> - %{ - compiler_opts: compiler_opts, - modules: Keyword.new, - std_lib_map: build_standard_lib_map(), - loaded_modules: [JS | loaded_modules], - module_references: Keyword.new() - } - end) - end - - defp build_standard_lib_map() do - Application.spec(:elixir, :modules) - |> Enum.reduce(Map.new, fn(x, acc) -> - try do - elixirscript_module = (["ElixirScript"] ++ Module.split(x)) |> Module.concat() - Map.put(acc, x, elixirscript_module) - rescue - FunctionClauseError -> - acc - ArgumentError -> - acc - end - end) - end - - def set_module_data(pid, module_data) do - Agent.update(pid, fn state -> - %{ state | modules: Keyword.merge(state.modules, module_data) } - end) - end - - def get_module_data(pid) do - Agent.get(pid, fn state -> - state.modules - end) - end - - def set_loaded_modules(pid, modules) do - Agent.update(pid, fn state -> - %{ state | loaded_modules: [ JS | modules ] } - end) - end - - def get(pid) do - Agent.get(pid, &(&1)) - end - - def get_module_name(pid, {:__aliases__, _, _} = name) do - get_module_name(pid, Utils.quoted_to_name(name)) - end - - def get_module_name(pid, module_name) do - Agent.get(pid, fn(state) -> - do_get_module_name(module_name, state) - end) - end - - defp do_get_module_name(module_name, state) do - std_lib_map = state.std_lib_map - case Map.get(std_lib_map, module_name) do - nil -> - module_name - actual_module_name -> - actual_module_name - end - end - - def is_module_loaded?(pid, module) when is_atom(module) do - Agent.get(pid, fn(state) -> - (module in state.loaded_modules) - end) - end - - def is_module_loaded?(pid, {:__aliases__, _, _} = module) do - - is_module_loaded?(pid, Utils.quoted_to_name(module)) - end - - def get_module(pid, module) when is_atom(module) do - do_get_module(pid, module) - end - - def get_module(pid, {:__aliases__, _, _} = name) do - do_get_module(pid, Utils.quoted_to_name(name)) - end - - def get_module(pid, module_name_list) when is_list(module_name_list) do - do_get_module(pid, Utils.quoted_to_name({:__aliases__, [], module_name_list})) - end - - defp do_get_module(pid, name) do - Agent.get(pid, fn(state) -> - Keyword.get(state.modules, do_get_module_name(name, state)) - end) - end - - def add_module_reference(pid, module_name, module_ref) do - Agent.update(pid, fn(state) -> - case Keyword.get(state.modules, do_get_module_name(module_ref, state)) do - nil -> - state - module -> - module_references = Keyword.update(state.module_references, module.name, [module_name], fn(x) -> Enum.uniq(x ++ [module_name]) end) - %{ state | module_references: module_references } - end - end) - end - - def list_module_references(pid) do - Agent.get(pid, fn(state) -> - state.module_references - end) - end - - def list_modules(pid) do - Agent.get(pid, fn(state) -> - Keyword.values(state.modules) - end) - end - - def list_module_names(pid) do - Agent.get(pid, fn(state) -> - Keyword.keys(state.modules) - end) - end - - def stop(pid) do - Agent.stop(pid) - end -end diff --git a/lib/elixir_script/translator/unsupported_error.ex b/lib/elixir_script/translator/unsupported_error.ex deleted file mode 100644 index 34bb1b6d..00000000 --- a/lib/elixir_script/translator/unsupported_error.ex +++ /dev/null @@ -1,8 +0,0 @@ -defmodule ElixirScript.Translator.UnsupportedError do - defexception [:message] - - def exception(value) do - msg = "Currently unsupported #{inspect value}" - %ElixirScript.Translator.UnsupportedError{message: msg} - end -end diff --git a/lib/elixir_script/translator/utils.ex b/lib/elixir_script/translator/utils.ex deleted file mode 100644 index e0611980..00000000 --- a/lib/elixir_script/translator/utils.ex +++ /dev/null @@ -1,65 +0,0 @@ -defmodule ElixirScript.Translator.Utils do - @moduledoc false - - def quoted_to_name(the_alias) do - {name, _} = Code.eval_quoted(the_alias) - name - end - - def name_to_quoted(name) when is_list(name) do - { :__aliases__, [], name } - end - - def name_to_quoted(name) do - name = name - |> Module.split - |> Enum.map(fn x -> String.to_atom(x) end) - - { :__aliases__, [], name } - end - - def name_to_js_name(name) do - { :__aliases__, _, name } = name_to_quoted(name) - Enum.join([:Elixir] ++ name, "$") - end - - def name_to_js_file_name(name) do - { :__aliases__, _, name } = name_to_quoted(name) - Enum.join([:Elixir] ++ name, ".") - end - - def make_local_file_path(module_app_name, file_name, env) do - root = ElixirScript.Translator.State.get(env.state).compiler_opts.root - app_name = if is_binary(module_app_name), do: module_app_name, else: to_string(module_app_name) - - case root do - nil -> - Path.join(["..", app_name, file_name]) - root -> - Path.join([root, app_name, file_name]) - end - end - - def make_local_file_path(file_name, env) do - root = ElixirScript.Translator.State.get(env.state).compiler_opts.root - - case root do - nil -> - Path.join([".", file_name]) - root -> - Path.join([root, file_name]) - end - end - - def make_local_file_path(module_app_name, file_name, root, _) do - app_name = to_string(module_app_name) - - case root do - nil -> - Path.join(["..", app_name, file_name]) - root -> - Path.join([root, app_name, file_name]) - end - end - -end diff --git a/lib/mix/tasks/compile.elixir_script.ex b/lib/mix/tasks/compile.elixir_script.ex index 0abf7e9c..a7926b79 100644 --- a/lib/mix/tasks/compile.elixir_script.ex +++ b/lib/mix/tasks/compile.elixir_script.ex @@ -49,7 +49,7 @@ defmodule Mix.Tasks.Compile.ElixirScript do defp do_compile(elixirscript_base, app) do {input, opts} = get_compiler_params() - ElixirScript.compiler.compile(input, opts) + ElixirScript.Compiler.compile(input, opts) end def clean do diff --git a/priv/std_lib/agent.ex b/priv/std_lib/agent.ex deleted file mode 100644 index 6b2559de..00000000 --- a/priv/std_lib/agent.ex +++ /dev/null @@ -1,54 +0,0 @@ -defmodule ElixirScript.Agent do - @moduledoc false - require JS - - def start(fun, options \\ []) do - pid = JS.new Bootstrap.Core.PID, [] - - name = if Elixir.Keyword.has_key?(options, :name) do - Elixir.Keyword.get(options, :name) - else - nil - end - - ElixirScript.Store.create(pid, fun.(), name) - { :ok, pid } - end - - def start_link(fun, options \\ []) do - pid = JS.new Bootstrap.Core.PID, [] - - name = if Elixir.Keyword.has_key?(options, :name) do - Elixir.Keyword.get(options, :name) - else - nil - end - - ElixirScript.Store.create(pid, fun.(), name) - { :ok, pid } - end - - def stop(agent) do - ElixirScript.Store.remove(agent) - :ok - end - - def update(agent, fun) do - current_state = ElixirScript.Store.read(agent) - ElixirScript.Store.update(agent, fun.(current_state)) - :ok - end - - def get(agent, fun) do - current_state = ElixirScript.Store.read(agent) - fun.(current_state) - end - - def get_and_update(agent, fun) do - current_state = ElixirScript.Store.read(agent) - {val, new_state} = fun.(current_state) - ElixirScript.Store.update(agent, new_state) - val - end - -end diff --git a/priv/std_lib/atom.ex b/priv/std_lib/atom.ex deleted file mode 100644 index 786ded55..00000000 --- a/priv/std_lib/atom.ex +++ /dev/null @@ -1,13 +0,0 @@ -defmodule ElixirScript.Atom do - @moduledoc false - import Kernel, except: [to_string: 1] - - def to_char_list(atom) do - to_string(atom).split("") - end - - def to_string(atom) do - JS.Symbol.keyFor(atom) - end - -end diff --git a/priv/std_lib/base.ex b/priv/std_lib/base.ex deleted file mode 100644 index 27fcdee9..00000000 --- a/priv/std_lib/base.ex +++ /dev/null @@ -1,30 +0,0 @@ -defmodule ElixirScript.Base do - @moduledoc false - - def encode64(data) do - ElixirScript.Bootstrap.Functions.b64EncodeUnicode(data) - end - - defp can_decode64(data) do - try do - JS.atob(data) - true - rescue - _ -> - false - end - end - - def decode64(data) do - if can_decode64(data) do - {:ok, decode64!(data) } - else - :error - end - end - - def decode64!(data) do - JS.atob(data) - end - -end diff --git a/priv/std_lib/bitwise.ex b/priv/std_lib/bitwise.ex deleted file mode 100644 index bc92799e..00000000 --- a/priv/std_lib/bitwise.ex +++ /dev/null @@ -1,74 +0,0 @@ -defmodule ElixirScript.Bitwise do - @moduledoc false - defmacro bnot(expr) do - quote do - JS.__bnot__(unquote(expr)) - end - end - - defmacro ~~~(expr) do - quote do - JS.__bnot__(unquote(expr)) - end - end - - defmacro band(left, right) do - quote do - JS.__band__(unquote(left), unquote(right)) - end - end - - defmacro left &&& right do - quote do - JS.__band__(unquote(left), unquote(right)) - end - end - - defmacro bor(left, right) do - quote do - JS.__bor__(unquote(left), unquote(right)) - end - end - - defmacro left ||| right do - quote do - JS.__bor__(unquote(left), unquote(right)) - end - end - - defmacro bxor(left, right) do - quote do - JS.__bxor__(unquote(left), unquote(right)) - end - end - - defmacro left ^^^ right do - quote do - JS.__bxor__(unquote(left), unquote(right)) - end - end - - defmacro bsl(left, right) do - quote do - JS.__bsl__(unquote(left), unquote(right)) - end - end - - defmacro left <<< right do - quote do - JS.__bsl__(unquote(left), unquote(right)) - end - end - - defmacro bsr(left, right) do - quote do - JS.__bsr__(unquote(left), unquote(right)) - end - end - - defmacro left >>> right do - quote do - JS.__bsr__(unquote(left), unquote(right)) - end - end -end diff --git a/priv/std_lib/bootstrap/functions.ex b/priv/std_lib/bootstrap/functions.ex deleted file mode 100644 index e8e0fe93..00000000 --- a/priv/std_lib/bootstrap/functions.ex +++ /dev/null @@ -1,70 +0,0 @@ -defmodule ElixirScript.Bootstrap.Functions do - - def contains(left, []) do - false - end - - def contains(left, [right]) do - case right do - ^left -> - true - _ -> - false - end - end - - def contains(left, [h|t]) do - case h do - ^left -> - true - _ -> - contains(left, t) - end - end - - def get_object_keys(obj) do - JS.Object.keys(obj).concat(JS.Object.getOwnPropertySymbols(obj)) - end - - def is_valid_character(codepoint) do - try do - JS.String.fromCodePoint(codepoint) != nil - rescue - _ -> - false - end - end - - def b64EncodeUnicode(str) do - regex = Regex.compile!("%([0-9A-F]{2})", "g") - - JS.btoa( - JS.encodeURIComponent(str).replace(regex, fn (match, p1, _, _) -> - JS.String.fromCharCode("0x#{p1}") - end) - ) - end - - def reverse(list) do - list.concat([]).reverse() - end - - def class_to_obj(map) do - JS.Object.assign(JS.new(JS.Object, []), map) - |> JS.Object.freeze - end - -def delete_property_from_map(map, property) do - new_map = JS.Object.assign(JS.Object.create(map.constructor.prototype), map) - JS.delete(new_map[property]) - - JS.Object.freeze(new_map) -end - -def add_property_to_map(map, property, value) do - JS.Object.assign(JS.new(JS.Object, []), map) - |> JS.update(property, value) - |> JS.Object.freeze -end - -end diff --git a/priv/std_lib/collectable.ex b/priv/std_lib/collectable.ex deleted file mode 100644 index 6950b962..00000000 --- a/priv/std_lib/collectable.ex +++ /dev/null @@ -1,34 +0,0 @@ -defprotocol ElixirScript.Collectable do - @moduledoc false - def into(collectable) -end - -defimpl ElixirScript.Collectable, for: List do - def into(original) do - {[], fn - list, {:cont, x} -> list ++ [x] - list, :done -> original ++ list - _, :halt -> :ok - end} - end -end - -defimpl ElixirScript.Collectable, for: BitString do - def into(original) do - {original, fn - acc, {:cont, x} when is_bitstring(x) -> <> - acc, :done -> acc - _, :halt -> :ok - end} - end -end - -defimpl ElixirScript.Collectable, for: Map do - def into(original) do - {original, fn - map, {:cont, {k, v}} -> Map.put(map, k, v) - map, :done -> map - _, :halt -> :ok - end} - end -end \ No newline at end of file diff --git a/priv/std_lib/enum.ex b/priv/std_lib/enum.ex deleted file mode 100644 index fded4e3f..00000000 --- a/priv/std_lib/enum.ex +++ /dev/null @@ -1,358 +0,0 @@ -defmodule ElixirScript.Enum do - - def all?(enumerable, fun \\ fn(x) -> x end) do - {_, acc} = Enumerable.reduce(enumerable, {:cont, true}, fn(item, _) -> - if fun.(item) do - {:cont, true} - else - {:halt, false} - end - end) - - acc - end - - def any?(enumerable, fun \\ fn(x) -> x end) do - {_, acc} = Enumerable.reduce(enumerable, {:cont, true}, fn(item, _) -> - if fun.(item) do - {:halt, true} - else - {:cont, false} - end - end) - - acc - end - - def at(enumerable, n, default \\ nil) do - index = if n < 0 do - {_, count} = Enumerable.count(enumerable) - count + n - else - n - end - - result = Enumerable.reduce(enumerable, {:cont, 0}, fn(item, acc) -> - if index == acc do - {:halt, item} - else - {:cont, acc + 1} - end - end) - - case result do - {:done, _} -> - default - {:halted, item} -> - item - end - end - - def concat([]) do - [] - end - - def concat([enumerable]) do - enumerable - end - - def concat([h, t]) do - h.concat(t) - end - - def concat([h | t]) do - h.concat(concat(t)) - end - - def concat(h, t) do - h.concat(t) - end - - def count(enumerable) do - {:ok, num} = Enumerable.count(enumerable) - num - end - - def count(enumerable, fun) do - {_, acc} = Enumerable.reduce(enumerable, {:cont, 0}, fn(item, acc) -> - if fun.(item) do - {:cont, acc + 1} - else - {:cont, acc} - end - end) - - acc - end - - def reduce(enumerable, fun) do - {_, result} = Enumerable.reduce(enumerable, {:cont, nil}, fn - item, nil -> - {:cont, {:acc, item}} - item, {:acc, acc} -> - {:cont, {:acc, fun.(item, acc)}} - end) - - result - end - - def reduce(enumerable, acc, fun) do - {_, result} = Enumerable.reduce(enumerable, {:cont, acc}, fn - item, acc -> - {:cont, fun.(item, acc)} - end) - - result - end - - - def map(enumerable, fun) do - reduce(enumerable, [], fn(x, acc) -> - acc ++ fun.(x) - end) - end - - def map_reduce(enumerable, acc, fun) do - reduce(enumerable, {[], acc}, fn(x, {m, acc}) -> - {v, new_acc} = fun.(x, acc) - {m ++ [v], new_acc} - end) - end - - def each(enumerable, fun) do - map(enumerable, fun) - :ok - end - - def empty?(enumerable) do - {:ok, count} = Enumerable.count(enumerable) - count == 0 - end - - def fetch(enumerable, index) do - index = if index < 0 do - {_, count} = Enumerable.count(enumerable) - count + index - else - index - end - - result = Enumerable.reduce(enumerable, {:cont, 0}, fn(item, acc) -> - if index == acc do - {:halt, {:ok, item}} - else - {:cont, acc + 1} - end - end) - - case result do - {:done, _} -> - :error - {:halted, item} -> - item - end - end - - def fetch!(enumerable, index) do - case fetch(enumerable, index) do - {:ok, item} -> - item - :error -> - raise Enum.OutOfBoundsError - end - end - - def filter(enumerable, fun) do - reduce(enumerable, [], fn(x, acc) -> - if fun.(x) do - acc ++ [x] - else - acc - end - end) - end - - def filter_map(enumerable, filter, mapper) do - reduce(enumerable, [], fn(x, acc) -> - if filter.(x) do - acc ++ [mapper.(x)] - else - acc - end - end) - end - - def find(enumerable, default \\ nil, fun) do - {_, result} = Enumerable.reduce(enumerable, {:cont, default}, fn(item, acc) -> - if fun.(item) do - {:halt, item} - else - {:cont, default} - end - end) - - result - end - - def into(enumerable, collectable) do - {init, fun} = Collectable.into(collectable) - reduce(enumerable, init, fn x, acc -> - fun.(acc, {:cont, x}) - end) - end - - def into(enumerable, collectable, transform) do - {init, fun} = Collectable.into(collectable) - reduce(enumerable, init, fn x, acc -> - fun.(acc, {:cont, transform.(x)}) - end) - end - - def member?(enumerable, value) do - {_, result} = Enumerable.reduce(enumerable, {:cont, false}, fn(item, acc) -> - if item == value do - {:halt, true} - else - {:cont, false} - end - end) - - result - end - - def drop(enumerable, count) when count < 0 do - enumerable - |> reverse - |> drop(abs(count)) - |> reverse - end - - def drop(enumerable, count) do - {_, {result, _}} = Enumerable.reduce(enumerable, {:cont, {[], 0}}, fn - (item, {taken, drop_count}) -> - if drop_count < count do - {:cont, {[], drop_count + 1 }} - else - {:cont, {taken ++ [item], drop_count}} - end - end) - - result - end - - def drop_every(enumerable, nth) do - {_, {result, _count}} = Enumerable.reduce(enumerable, {:cont, {[], 0}}, fn - (item, {taken, count}) -> - if rem(count, nth) == 0 do - {:cont, {taken, count + 1}} - else - {:cont, {taken ++ [item], count + 1}} - end - end) - - result - end - - def drop_while(enumerable, fun) do - {_, result} = Enumerable.reduce(enumerable, {:cont, :dropping}, fn - (item, :dropping) -> - if fun.(item) do - {:cont, :dropping} - else - {:cont, [item]} - end - - (item, taken) -> - {:cont, taken ++ [item]} - end) - - case result do - :dropping -> - [] - :done -> - [] - _ -> - result - end - end - - def empty?(enumerable) do - {:ok, count} = Enumerable.count(enumerable) - count == 0 - end - - def take(enumerable, count) do - if Enumerable.count(enumerable) < count do - enumerable - else - {_, result} = Enumerable.reduce(enumerable, {:cont, {[], 0}}, fn - (item, {taken, taken_count}) -> - if taken_count == count do - {:halt, taken} - else - {:cont, {taken ++ [item], taken_count + 1}} - end - end) - - result - end - end - - def take_every(enumerable, nth) do - {_, {result, _count}} = Enumerable.reduce(enumerable, {:cont, {[], 0}}, fn - (item, {taken, count}) -> - if rem(count, nth) == 0 do - {:cont, {taken ++ [item], count + 1}} - else - {:cont, {taken, count + 1}} - end - end) - - result - end - - def take_while(enumerable, fun) do - {_, result} = Enumerable.reduce(enumerable, {:cont, []}, fn - (item, taken) -> - if fun.(item) do - {:cont, {taken ++ [item]}} - else - {:halt, taken} - end - end) - - result - end - - - def to_list(enumerable) when is_list(enumerable) do - enumerable - end - - def to_list(enumerable) do - map(enumerable, fn x -> x end) - end - - def reverse(enumerable) when is_list(enumerable) do - enumerable.concat([]).reverse() - end - - def reverse(enumerable) do - reduce(enumerable, [], fn(item, acc) -> - [item] ++ acc - end) - end - - def reverse(enumerable, tail) when is_list(enumerable) do - enumerable.concat([]).reverse() ++ tail - end - - def reverse(enumerable, tail) do - result = reduce(enumerable, [], fn(item, acc) -> - [item] ++ acc - end) - - result ++ tail - end - -end \ No newline at end of file diff --git a/priv/std_lib/enum/out_of_bounds_error.ex b/priv/std_lib/enum/out_of_bounds_error.ex deleted file mode 100644 index e8ffb4b2..00000000 --- a/priv/std_lib/enum/out_of_bounds_error.ex +++ /dev/null @@ -1,3 +0,0 @@ -defmodule ElixirScript.Enum.OutOfBoundsError do - defexception message: "out of bounds error" -end \ No newline at end of file diff --git a/priv/std_lib/enumerable.ex b/priv/std_lib/enumerable.ex deleted file mode 100644 index b9ff8e7a..00000000 --- a/priv/std_lib/enumerable.ex +++ /dev/null @@ -1,38 +0,0 @@ -defprotocol ElixirScript.Enumerable do - @moduledoc false - def reduce(enumerable, acc, fun) - def member?(enumerable, element) - def count(enumerable) -end - -defimpl ElixirScript.Enumerable, for: List do - def count(list), - do: {:ok, list.length } - - def member?(list, value), - do: {:ok, value in list } - - def reduce(list, acc, fun) do - Bootstrap.Core.Functions.iterator_to_reducer(list, acc, fun) - end -end - -defimpl ElixirScript.Enumerable, for: Map do - def count(map) do - {:ok, map.length} - end - - def member?(map, {key, value}) do - {:ok, Map.get(map, key) == value } - end - - def member?(_, _) do - {:ok, false} - end - - def reduce(map, acc, fun) do - map - |> Map.to_list - |> Bootstrap.Core.Functions.iterator_to_reducer(acc, fun) - end -end diff --git a/priv/std_lib/exceptions.ex b/priv/std_lib/exceptions.ex deleted file mode 100644 index 4f723003..00000000 --- a/priv/std_lib/exceptions.ex +++ /dev/null @@ -1,7 +0,0 @@ -defmodule ElixirScript.ArgumentError do - defexception message: "argument error" -end - -defmodule ElixirScript.RuntimeError do - defexception message: "runtime error" -end \ No newline at end of file diff --git a/priv/std_lib/integer.ex b/priv/std_lib/integer.ex deleted file mode 100644 index 3a5bb41d..00000000 --- a/priv/std_lib/integer.ex +++ /dev/null @@ -1,29 +0,0 @@ -defmodule ElixirScript.Integer do - @moduledoc false - def is_even(number) do - rem(number, 2) == 0 - end - - def is_odd(number) do - rem(number, 2) != 0 - end - - def to_char_list(number, base \\ 10) do - number.toString(base).split('') - end - - def parse(bin, base \\ 10) do - result = JS.parseInt(bin, base) - - if JS.isNaN(result) do - :error - else - case bin.indexOf(".") do - index_of_dot when index_of_dot < 0 -> - {result, ""} - index_of_dot -> - {result, bin.substring(index_of_dot)} - end - end - end -end diff --git a/priv/std_lib/io.ex b/priv/std_lib/io.ex deleted file mode 100644 index 0444da1d..00000000 --- a/priv/std_lib/io.ex +++ /dev/null @@ -1,22 +0,0 @@ -defmodule ElixirScript.IO do - - def inspect(item, opts \\ []) do - JS.console.log(item) - item - end - - def puts(device \\ :stdio, item) when is_binary(item) do - case device do - :stdio -> - JS.console.log(item) - :stderr -> - JS.console.warn(item) - end - end - - def warn(message) when is_binary(message) do - JS.console.warn("warning: #{message}") - JS.console.trace() - end - -end diff --git a/priv/std_lib/js.ex b/priv/std_lib/js.ex deleted file mode 100644 index 3e3db5ac..00000000 --- a/priv/std_lib/js.ex +++ /dev/null @@ -1,108 +0,0 @@ -defmodule JS do - @moduledoc """ - This module defines macros and functions which implement - JavaScript functionality that may not translate easily to - Elixir. For instance, creating a new object, or updating - an existing one. - """ - - @doc """ - Creates new JavaScript objects. - - ex: - JS.new User, ["first_name", "last_name"] - """ - defmacro new(module, params) - - @doc """ - Updates an existing JavaScript object. - - ex: - JS.update elem, %{"width" => 100} - """ - defmacro update(object, map) - - @doc """ - Updates an existing JavaScript object. - - ex: - JS.update elem, "width", 100 - """ - defmacro update(object, key, value) - - @doc """ - Returns the type of the given value - """ - defmacro typeof(value) - - @doc """ - Determines if value is an instance of type. - """ - defmacro instanceof(value, type) - - @doc """ - Throws the term given - """ - defmacro throw(term) - - @doc """ - Returns a reference to the global JavaScript object. - - In browsers this would be window or self. - In node this would be the global object. - """ - def global() do - Bootstrap.Core.global() - end - - @doc """ - Defines a generator. This is compiled into a generator function in JavaScript. - defgen and defgenp are currently the only ways to use process in Elixirscript right now. - """ - defmacro defgen(call, expr \\ nil) do - quote do - def unquote(call), unquote(expr) - end - end - - @doc """ - Defines a private generator. This is compiled into a generator function in JavaScript. - """ - defmacro defgenp(call, expr \\ nil) do - quote do - defp unquote(call), unquote(expr) - end - end - - @doc """ - Determines if term is a generator - """ - def is_generator(term) do - term.constructor.name === "GeneratorFunction" - end - - @doc """ - Yields the current generator function - """ - defmacro yield() - - @doc """ - Yields the current generator function with the given term - """ - defmacro yield(term) - - @doc """ - Yields control to the given generator - """ - defmacro yield_to(gen) - - @doc """ - Creates a breakpoint for JavaScript debuggers to stop at - """ - defmacro debugger() - - @doc """ - The current JavaScript context - """ - defmacro this() -end diff --git a/priv/std_lib/kernel.ex b/priv/std_lib/kernel.ex deleted file mode 100644 index 83978563..00000000 --- a/priv/std_lib/kernel.ex +++ /dev/null @@ -1,209 +0,0 @@ -defmodule ElixirScript.Kernel do - @moduledoc false - import Kernel, only: [defmodule: 2, def: 1, def: 2, defp: 2, - defmacro: 1, defmacro: 2, defmacrop: 2, ||: 2, !: 1, - ++: 2, in: 2, &&: 2, ===: 2, @: 1, sigil_r: 2] - require JS - - - defmacro if(condition, clauses) do - build_if(condition, clauses) - end - - defp build_if(condition, do: do_clause) do - build_if(condition, do: do_clause, else: nil) - end - - defp build_if(condition, do: do_clause, else: else_clause) do - quote do - case unquote(condition) do - x when x in [false, nil] -> - unquote(else_clause) - _ -> - unquote(do_clause) - end - end - end - - defmacro unless(condition, clauses) do - build_unless(condition, clauses) - end - - defp build_unless(condition, do: do_clause) do - build_unless(condition, do: do_clause, else: nil) - end - - defp build_unless(condition, do: do_clause, else: else_clause) do - quote do - if(unquote(condition), do: unquote(else_clause), else: unquote(do_clause)) - end - end - - def abs(number) do - JS.Math.abs(number) - end - - def apply(fun, args) do - fun.apply(fun, args) - end - - def apply(module, fun, args) do - module[Atom.to_string(fun)].apply(module[Atom.to_string(fun)], args) - end - - def binary_part(binary, start, len) do - binary.substring(start, len) - end - - def hd(list) do - list[0] - end - - def tl(list) do - list.slice(1) - end - - def is_atom(term) do - JS.typeof(term) === "symbol" - end - - def is_binary(term) do - JS.typeof(term) === "string" - end - - def is_bitstring(term) do - is_binary(term) || JS.instanceof(term, Bootstrap.Core.BitString) - end - - def is_boolean(term) do - JS.typeof(term) === "boolean" || JS.instanceof(term, Boolean) - end - - def is_float(term) do - is_number(term) && !JS.Number.isInteger(term) - end - - def is_function(term) do - is_function(term, 0) - end - - def is_function(term, _) do - JS.typeof(term) === "function" || JS.instanceof(term, Function) - end - - def is_integer(term) do - JS.Number.isInteger(term) - end - - def is_list(term) do - JS.Array.isArray(term) - end - - def is_number(term) do - JS.typeof(term) === "number" || JS.instanceof(term, Number) - end - - def is_pid(term) do - JS.instanceof(term, Bootstrap.Core.PID) - end - - def is_tuple(term) do - JS.instanceof(term, Bootstrap.Core.Tuple) - end - - def is_map(term) do - JS.typeof(term) === "object" || JS.instanceof(term, Object) - end - - def is_port(_) do - false - end - - def is_reference(_) do - false - end - - def length(term) do - term.length - end - - def map_size(term) do - JS.Object.keys(term).length - end - - def max(first, second) do - JS.Math.max(first, second) - end - - def min(first, second) do - JS.Math.min(first, second) - end - - def round(number) do - JS.Math.round(number) - end - - def trunc(number) do - JS.Math.floor(number) - end - - def tuple_size(tuple) do - tuple.count() - end - - def elem(tuple, index) do - tuple.get(index) - end - - def is_nil(term) do - term === nil - end - - defmacro sigil_r({:<<>>, _meta, [string]}, options) do - str_options = List.to_string(options) - quote do - Regex.compile!(unquote(string), unquote(str_options)) - end - end - - defmacro match?(pattern, expr) do - quote do - case unquote(expr) do - unquote(pattern) -> - true - _ -> - false - end - end - end - - defmacro to_string(arg) when Kernel.is_binary(arg) do - arg - end - - defmacro to_string(arg) do - quote do - String.Chars.to_string(unquote(arg)) - end - end - - defmacro left |> {fun, context, params} do - {fun, context, [left] ++ params } - end - - defmacro left in right do - quote do - ElixirScript.Bootstrap.Functions.contains(unquote(left), unquote(right)) - end - end - - defmacro first .. last do - quote do - %ElixirScript.Range{ first: unquote(first), last: unquote(last) } - end - end - - def throw(term) do - JS.throw(term) - end -end diff --git a/priv/std_lib/keyword.ex b/priv/std_lib/keyword.ex deleted file mode 100644 index 2c91ec9f..00000000 --- a/priv/std_lib/keyword.ex +++ /dev/null @@ -1,46 +0,0 @@ -defmodule ElixirScript.Keyword do - @moduledoc false - - def new() do - [] - end - - def has_key?(kw, key) do - do_has_key?(kw, key) - end - - defp do_has_key?([], _) do - false - end - - defp do_has_key?(kw, key) do - case hd(kw) do - {the_key, _} when the_key == key -> - true - _ -> - do_has_key?(tl(kw), key) - end - end - - def get(kw, key) do - get(kw, key, nil) - end - - def get(kw, key, default_value) do - case has_key?(kw, key) do - true -> - do_get(kw, key) - false -> - default_value - end - end - - defp do_get(kw, key) do - case hd(kw) do - { kw_key, value } when kw_key == key -> - value - _ -> - do_get(tl(kw), key) - end - end -end diff --git a/priv/std_lib/list.ex b/priv/std_lib/list.ex deleted file mode 100644 index 156475f7..00000000 --- a/priv/std_lib/list.ex +++ /dev/null @@ -1,265 +0,0 @@ -defmodule ElixirScript.List do - @moduledoc false - require JS - - def duplicate(data, size) do - do_duplicate(data, size, []) - end - - defp do_duplicate(_, 0, list) do - list - end - - defp do_duplicate(data, size, list) do - do_duplicate(data, size - 1, list ++ [data]) - end - - def to_tuple(list) do - JS.new(Bootstrap.Core.Tuple, list) - end - - def wrap(list) when is_list(list), do: list - def wrap(nil), do: [] - def wrap(term), do: [term] - - def append(list, term) do - concat(list, [term]) - end - - def prepend(list, term) do - concat([term], list) - end - - def concat(list_a, list_b) do - list_a.concat(list_b) - end - - def first(list) do - list[0] - end - - def last(list) do - list[length(list) - 1] - end - - def delete(list, item) do - do_delete(list, item, 0, []) - end - - defp do_delete(list, item, current_index, new_list) do - if current_index == length(list) do - new_list - else - updated = case list[current_index] do - ^item -> - new_list - _ -> - new_list ++ [list[current_index]] - end - - do_delete(list, item, current_index + 1, updated) - end - end - - def delete_at(list, index) do - do_delete_at(list, index, 0, []) - end - - defp do_delete_at(list, index, current_index, new_list) do - if current_index == length(list) do - new_list - else - updated = case current_index == index do - true -> - new_list - _ -> - new_list ++ [list[current_index]] - end - - do_delete_at(list, index, current_index + 1, updated) - end - end - - def insert_at(list, index, value) do - do_insert_at(list, index, value, 0, []) - end - - defp do_insert_at(list, index, value, current_index, new_list) do - if current_index == length(list) do - new_list - else - updated = case current_index == index do - true -> - new_list ++ [value, list[current_index]] - _ -> - new_list ++ [list[current_index]] - end - - do_insert_at(list, index, value, current_index + 1, updated) - end - end - - def replace_at(list, index, value) do - do_replace_at(list, index, value, 0, []) - end - - defp do_replace_at(list, index, value, current_index, new_list) do - if current_index == length(list) do - new_list - else - updated = case current_index == index do - true -> - new_list ++ [value] - _ -> - new_list ++ [list[current_index]] - end - - do_replace_at(list, index, value, current_index + 1, updated) - end - end - - - def update_at(list, index, func) do - do_update_at(list, index, func, 0, []) - end - - defp do_update_at(list, index, func, current_index, new_list) do - if current_index == length(list) do - new_list - else - updated = case current_index == index do - true -> - new_list ++ [func.(list[current_index])] - _ -> - new_list ++ [list[current_index]] - end - - do_update_at(list, index, func, current_index + 1, updated) - end - end - - - def foldl(list, acc, func) do - do_foldl(list, acc, func, []) - end - - def foldr(list, acc, func) do - do_foldl(list.concat([]).reverse(), acc, func, []) - end - - defp do_foldl([], acc, _, new_list) do - { acc, new_list } - end - - defp do_foldl(list, acc, func, new_list) do - { acc, value } = func.(hd(list), acc) - do_foldl(tl(list), acc, func, new_list ++ [value]) - end - - def flatten(list, tail \\ []) do - do_flatten(list, []) ++ tail - end - - defp do_flatten([], flattened_list) do - flattened_list - end - - defp do_flatten(list, flattened_list) do - updated = case hd(list) do - l when is_list(l) -> - flattened_list ++ do_flatten(l, []) - item -> - flattened_list ++ [item] - end - - do_flatten(tl(list), updated) - end - - - def keydelete(list, key, position) do - do_keydelete(list, key, position, []) - end - - defp do_keydelete([], _, _, new_list) do - new_list - end - - defp do_keydelete(list, key, position, new_list) do - current_value = hd(list) - - updated = if elem(current_value, position) == key do - new_list - else - new_list ++ [current_value] - end - - do_keydelete(tl(list), key, position, updated) - end - - def keyfind(list, key, position) do - do_keyfind(list, key, position, nil) - end - - def keyfind(list, key, position, default) do - do_keyfind(list, key, position, default) - end - - defp do_keyfind([], _, _, default) do - default - end - - defp do_keyfind(list, key, position, default) do - current_value = hd(list) - - if elem(current_value, position) == key do - current_value - else - do_keyfind(tl(list), key, position, default) - end - end - - def keymember?(list, key, position) do - keyfind(list, key, position) != nil - end - - def keyreplace(list, key, position, new_tuple) do - do_keyreplace(list, key, position, [], new_tuple) - end - - defp do_keyreplace([], _, _, new_list, _) do - new_list - end - - defp do_keyreplace(list, key, position, new_list, new_tuple) do - current_value = hd(list) - - updated = if elem(current_value, position) == key do - new_list ++ [new_tuple] - else - new_list ++ [current_value] - end - - do_keyreplace(tl(list), key, position, updated, new_tuple) - end - - def zip([]) do - [] - end - - def zip(list_of_lists) when is_list(list_of_lists) do - lengths = Enum.map(list_of_lists, fn(list) -> length(list) end) - length = apply(JS.Math, :min, lengths) - do_zip(list_of_lists, 0, length, []) - end - - defp do_zip(list_of_lists, index, length, acc) when index == length do - acc - end - - defp do_zip(list_of_lists, index, length, acc) do - values = Enum.map(list_of_lists, fn(list) -> Enum.at(list, index) end) - item = JS.new(Bootstrap.Core.Tuple, values) - - do_zip(list_of_lists, index + 1, length, acc ++ [item]) - end -end diff --git a/priv/std_lib/macro/env.ex b/priv/std_lib/macro/env.ex deleted file mode 100644 index 1528e2c8..00000000 --- a/priv/std_lib/macro/env.ex +++ /dev/null @@ -1,37 +0,0 @@ -defmodule ElixirScript.Macro.Env do - @moduledoc false - - @type t :: %ElixirScript.Macro.Env{ - module: atom, - file: binary, - line: non_neg_integer, - function: { atom, non_neg_integer } | nil, - context: :match | :guard | :generator | nil, - aliases: [{atom, atom}], - requires: [atom], - functions: [{atom, [{ atom, non_neg_integer }]}], - macros: [{atom, [{ atom, non_neg_integer }]}], - macro_aliases: [{atom, {integer, atom}}], - context_modules: [atom], - vars: [{atom, atom | non_neg_integer}], - export_vars: [{atom, atom | non_neg_integer}] | nil, - lexical_tracker: nil - } - - defstruct [ - module: nil, - file: nil, - line: 0, - function: nil, - context: nil, - aliases: [], - requires: [], - functions: [], - macros: [], - macro_aliases: [], - context_modules: [], - vars: [], - export_vars: nil, - lexical_tracker: nil - ] -end diff --git a/priv/std_lib/map.ex b/priv/std_lib/map.ex deleted file mode 100644 index b8e48707..00000000 --- a/priv/std_lib/map.ex +++ /dev/null @@ -1,204 +0,0 @@ -defmodule ElixirScript.Map do - @moduledoc false - - def new() do - %{} - end - - def keys(map) do - ElixirScript.Bootstrap.Functions.get_object_keys(map) - end - - def size(map) do - keys(map).length - end - - def to_list(map) do - do_to_list(map, []) - end - - def do_to_list(map, list) do - case size(map) do - 0 -> - list - _ -> - key = hd(keys(map)) - value = map[key] - do_to_list(Map.delete(map, key), list ++ [{key, value}]) - end - end - - def values(map) do - JS.Object.values(map) - end - - def from_struct(struct) do - struct - |> ElixirScript.Bootstrap.Functions.class_to_obj - |> delete(:__struct__) - end - - def delete(map, key) do - map - |> ElixirScript.Bootstrap.Functions.delete_property_from_map(key) - end - - def equal?(map1, map2) do - map1 === map2 - end - - def fetch!(map, key) do - case key in keys(map) do - true -> - map[key] - false -> - raise "#{key} not found in map" - end - end - - def fetch(map, key) do - case key in keys(map) do - true -> - { :ok, map[key] } - false -> - :error - end - end - - def has_key?(map, key) do - key in keys(map) - end - - def merge(map1, map2) do - JS.Object.assign(%{}, map1, map2) - |> JS.Object.freeze() - end - - def split(map, keys) do - do_split(map, keys, { %{}, %{} }) - end - - defp do_split(_, [], split_tuple) do - split_tuple - end - - defp do_split(map, keys, { key_map, non_key_map }) do - key = hd(keys) - - new_split_tuple = case key in keys(map) do - true -> - { Map.put(key_map, key, map[key]), non_key_map } - false -> - { key_map, Map.put(non_key_map, key, map[key]) } - end - - do_split(map, tl(keys), new_split_tuple) - end - - def take(map, keys) do - {key_map, _} = split(map, keys) - key_map - end - - def drop(map, keys) do - {_, non_key_map} = split(map, keys) - non_key_map - end - - def put_new(map, key, value) do - case key in keys(map) do - true -> - map - false -> - Map.put(map, key, value) - end - end - - def put_new_lazy(map, key, func) do - case key in keys(map) do - true -> - map - false -> - Map.put(map, key, func.()) - end - end - - def put(map, key, value) do - ElixirScript.Bootstrap.Functions.add_property_to_map(map, key, value) - end - - def get(map, key) do - get(map, key, nil) - end - - def get(map, key, default_value) do - case key in keys(map) do - true -> - map[key] - false -> - default_value - end - end - - def get_lazy(map, key, func) do - case key in keys(map) do - true -> - func.(map[key]) - false -> - func.() - end - end - - def get_and_update(map, key, func) do - case key in keys(map) do - true -> - { nil, map } - false -> - new_value = func.(map[key]) - { new_value, Map.put(map, key, new_value) } - end - end - - def pop(map, key) do - pop(map, key, nil) - end - - def pop(map, key, default_value) do - case key in keys(map) do - true -> - { map[key], Map.delete(map, key) } - false -> - { default_value, map } - end - end - - def pop_lazy(map, key, func) do - case key in keys(map) do - true -> - { func.(map[key]), Map.delete(map, key) } - false -> - { func.(), map } - end - end - - - def update!(map, key, func) do - case key in keys(map) do - true -> - Map.put(map, key, func.(map[key])) - false -> - raise "#{key} not found in map" - end - end - - - def update(map, key, initial, func) do - case key in keys(map) do - true -> - Map.put(map, key, func.(map[key])) - false -> - Map.put(map, key, initial) - end - end - -end diff --git a/priv/std_lib/map_set.ex b/priv/std_lib/map_set.ex deleted file mode 100644 index a22fe57b..00000000 --- a/priv/std_lib/map_set.ex +++ /dev/null @@ -1,100 +0,0 @@ -defmodule ElixirScript.MapSet do - @moduledoc false - defstruct set: [] - - def new() do - %MapSet{} - end - - def size(set) do - length(set.set) - end - - def to_list(set) do - set.set - end - - def delete(set, term) do - %{ set | set: Elixir.List.remove(set.set, term) } - end - - def put(set, term) do - case member?(set, term) do - false -> - %{ set | set: set.set ++ term } - true -> - set - end - end - - def member?(set, term) do - set.set.indexOf(term) >= 0 - end - - def equal?(set1, set2) do - set1 === set2 - end - - def difference(set1, set2) do - do_difference(to_list(set1), set2, new()) - end - - def do_difference([], _, difference_set) do - difference_set - end - - def do_difference(set1_list, set2, difference_set) do - term = hd(set1_list) - case member?(set2, term) do - true -> - do_difference(tl(set1_list), set2, difference_set) - false -> - do_difference(tl(set1_list), set2, %{ difference_set | set: difference_set.set ++ [term]}) - end - end - - def intersection(set1, set2) do - do_intersection(to_list(set1), set2, new()) - end - - def do_intersection([], _, intersection_set) do - intersection_set - end - - def do_intersection(set1_list, set2, intersection_set) do - term = hd(set1_list) - case member?(set2, term) do - false -> - do_intersection(tl(set1_list), set2, intersection_set) - true -> - do_intersection(tl(set1_list), set2, %{ intersection_set | set: intersection_set.set ++ [term]}) - end - end - - def union(set1, set2) do - %{ set1 | set: set1.set ++ set2.set} - end - - def disjoint?(set1, set2) do - size(intersection(set1, set2)) == 0 - end - - def subset?(set1, set2) do - do_subset?(to_list(set1), set2) - end - - def do_subset?([], _) do - true - end - - def do_subset?(set1_list, set2) do - term = hd(set1_list) - case member?(set2, term) do - false -> - false - true -> - do_subset?(tl(set1_list), set2) - end - end - -end diff --git a/priv/std_lib/module.ex b/priv/std_lib/module.ex deleted file mode 100644 index f1454a5d..00000000 --- a/priv/std_lib/module.ex +++ /dev/null @@ -1,9 +0,0 @@ -defmodule ElixirScript.Module do - @moduledoc false - - defstruct name: nil, - functions: Keyword.new, private_functions: Keyword.new, - body: nil, js_imports: [], module_refs: [], type: :module, - impls: Map.new, impl_type: nil, app_name: nil - -end diff --git a/priv/std_lib/range.ex b/priv/std_lib/range.ex deleted file mode 100644 index 7f53b13e..00000000 --- a/priv/std_lib/range.ex +++ /dev/null @@ -1,12 +0,0 @@ -defmodule ElixirScript.Range do - @moduledoc false - defstruct first: nil, last: nil - - def new(first, last) do - %Range{first: first, last: last} - end - - def range?(%Range{}), do: true - def range?(_), do: false - -end diff --git a/priv/std_lib/regex.ex b/priv/std_lib/regex.ex deleted file mode 100644 index e395a5d9..00000000 --- a/priv/std_lib/regex.ex +++ /dev/null @@ -1,71 +0,0 @@ -defmodule ElixirScript.Regex do - @moduledoc false - require JS - - def compile(source, options \\ "") do - try do - {:ok, JS.new(JS.RegExp, [source, options])} - rescue - x -> - {:error, x.message} - end - end - - def compile!(source, options \\ "") do - JS.new(JS.RegExp, [source, options]) - end - - def regex?(term) do - JS.instanceof(term, JS.RegExp) - end - - def match?(regex, string) do - reg = if regex?(regex), do: regex, else: compile!(source(regex), opts(regex)) - reg.test(string) - end - - def source(regex) do - regex.source - end - - def opts(regex) do - regex.opts - end - - def run(regex, string, options \\ []) do - regex.exec(string) - end - - def scan(regex, string, options \\ []) do - reg = make_global(regex) - do_scan(reg, string, options, []) - end - - def replace(regex, string, replacement, options \\ []) do - reg = if Keyword.get(options, :global, true) do - make_global(regex) - else - regex - end - - string.replace(reg, replacement) - end - - defp do_scan(regex, string, options, results) do - case run(regex, string, options) do - nil -> - results - match -> - do_scan(regex, string, options, results ++ match) - end - end - - defp make_global(regex) do - if String.contains?(opts(regex), "g") do - regex - else - JS.new(JS.RegExp, [ source(regex), opts(regex) <> "g" ]) - end - end - -end diff --git a/priv/std_lib/store.ex b/priv/std_lib/store.ex deleted file mode 100644 index 70634248..00000000 --- a/priv/std_lib/store.ex +++ /dev/null @@ -1,45 +0,0 @@ -defmodule ElixirScript.Store do - - defp get_key(key) do - - real_key = case JS.__elixirscript_names__.has(key) do - true -> - JS.__elixirscript_names__.get(key) - false -> - key - end - - - case JS.__elixirscript_store__.has(real_key) do - true -> - real_key - false -> - JS.throw JS.new(JS.Error, ["Key Not Found"]) - end - end - - def create(key, value, name \\ nil) do - if name != nil do - JS.__elixirscript_names__.set(name, key) - end - - JS.__elixirscript_store__.set(key, value) - end - - def update(key, value) do - real_key = get_key(key) - JS.__elixirscript_store__.set(real_key, value) - end - - def read(key) do - real_key = get_key(key) - JS.__elixirscript_store__.get(real_key) - end - - def remove(key) do - real_key = get_key(key) - JS.__elixirscript_store__.delete(real_key) - end - - -end diff --git a/priv/std_lib/string/chars.ex b/priv/std_lib/string/chars.ex deleted file mode 100644 index ae5d0227..00000000 --- a/priv/std_lib/string/chars.ex +++ /dev/null @@ -1,48 +0,0 @@ -defprotocol ElixirScript.String.Chars do - @moduledoc false - def to_string(item) -end - -defimpl ElixirScript.String.Chars, for: Atom do - def to_string(nil) do - "" - end - - def to_string(atom) do - Atom.to_string(atom) - end -end - -defimpl ElixirScript.String.Chars, for: BitString do - def to_string(thing) when is_binary(thing) do - thing - end - - def to_string(thing) do - thing.toString() - end -end - -defimpl ElixirScript.String.Chars, for: List do - def to_string(list) do - list.toString() - end -end - -defimpl ElixirScript.String.Chars, for: Tuple do - def to_string(tuple) do - tuple.toString() - end -end - -defimpl ElixirScript.String.Chars, for: Integer do - def to_string(integer) do - integer.toString() - end -end - -defimpl ElixirScript.String.Chars, for: Float do - def to_string(float) do - float.toString() - end -end diff --git a/priv/std_lib/tuple.ex b/priv/std_lib/tuple.ex deleted file mode 100644 index 6751dfa6..00000000 --- a/priv/std_lib/tuple.ex +++ /dev/null @@ -1,63 +0,0 @@ -defmodule ElixirScript.Tuple do - @moduledoc false - require JS - - def duplicate(data, size) do - JS.new(Bootstrap.Core.Tuple, do_duplicate(data, size, [])) - end - - defp do_duplicate(_, 0, list) do - list - end - - defp do_duplicate(data, size, list) do - do_duplicate(data, size - 1, list ++ [data]) - end - - def to_list(tuple) do - tuple.values - end - - def insert_at(tuple, index, value) do - JS.new(Bootstrap.Core.Tuple, do_insert_at(tuple, index, value, 0, [])) - end - - defp do_insert_at(tuple, index, value, current_index, list) do - if current_index == length(tuple) do - list - else - new_list = case index == current_index do - true -> - list ++ [value, tuple.get(current_index)] - false -> - list ++ [tuple.get(current_index)] - end - - do_insert_at(tuple, index, value, current_index + 1, new_list) - end - end - - def delete_at(tuple, index) do - JS.new(Bootstrap.Core.Tuple, do_delete_at(tuple, index, 0, [])) - end - - defp do_delete_at(tuple, index, current_index, list) do - if current_index == length(tuple) do - list - else - new_list = case index == current_index do - true -> - list - false -> - list ++ [tuple.get(current_index)] - end - - do_delete_at(tuple, index, current_index + 1, new_list) - end - end - - def append(tuple, value) do - JS.new(Bootstrap.Core.Tuple, to_list(tuple) ++ [value]) - end - -end diff --git a/rollup.config.js b/rollup.config.js index c06836ac..9fe0ae32 100644 --- a/rollup.config.js +++ b/rollup.config.js @@ -10,7 +10,10 @@ export default { babel({ babelrc: false, }), - //babili({}), + babili({ + keepFnName: true, + keepClassName: true, + }), ], targets: [{ dest: 'priv/build/iife/Elixir.Bootstrap.js', format: 'iife' }], }; diff --git a/src/javascript/lib/core/erlang_compat/erlang.js b/src/javascript/lib/core/erlang_compat/erlang.js index eb3f78c6..3ca28bf6 100644 --- a/src/javascript/lib/core/erlang_compat/erlang.js +++ b/src/javascript/lib/core/erlang_compat/erlang.js @@ -6,9 +6,25 @@ function atom_to_binary(atom, encoding = Symbol.for('utf8')) { throw new Error(`unsupported encoding ${encoding}`); } + if (atom.__MODULE__) { + return Symbol.keyFor(atom.__MODULE__); + } + return Symbol.keyFor(atom); } +function binary_to_atom(binary, encoding = Symbol.for('utf8')) { + if (encoding !== Symbol.for('utf8')) { + throw new Error(`unsupported encoding ${encoding}`); + } + + return Symbol.for(binary); +} + +function binary_to_existing_atom(binary, encoding = Symbol.for('utf8')) { + return binary_to_atom(binary, encoding); +} + function list_concatenation(list1, list2) { return list1.concat(list2); } @@ -124,7 +140,9 @@ function bxor(left, right) { } function is_atom(value) { - return value instanceof Symbol || value.__MODULE__ === true; + return ( + typeof value === 'symbol' || value instanceof Symbol || value.__MODULE__ + ); } function is_bitstring(value) { @@ -132,15 +150,19 @@ function is_bitstring(value) { } function is_boolean(value) { - return value instanceof Boolean; + return typeof value === 'boolean' || value instanceof Boolean; +} + +function is_number(value) { + return typeof value === 'number' || value instanceof Number; } function is_float(value) { - return value instanceof Number && !Number.isInteger(value); + return is_number(value) && !Number.isInteger(value); } function is_function(value) { - return value instanceof Function; + return typeof value === 'function' || value instanceof Function; } function is_integer(value) { @@ -152,11 +174,7 @@ function is_list(value) { } function is_map(value) { - return value instanceof Object; -} - -function is_number(value) { - return value instanceof Number; + return typeof value === 'object' || value instanceof Object; } function is_pid(value) { @@ -176,11 +194,13 @@ function is_tuple(value) { } function is_binary(value) { - return value instanceof String; + return typeof value === 'string' || value instanceof String; } export default { atom_to_binary, + binary_to_atom, + binary_to_existing_atom, list_concatenation, list_subtraction, plus, diff --git a/test/cli_test.exs b/test/cli_test.exs deleted file mode 100644 index 05244867..00000000 --- a/test/cli_test.exs +++ /dev/null @@ -1,8 +0,0 @@ -defmodule ElixirScript.CLI.Test do - use ExUnit.Case - - test "parse_args -js-module includes js module" do - {_, args} = ElixirScript.CLI.parse_args(["Example", "--js-module", "React:react"]) - assert args == [js_module: "React:react"] - end -end diff --git a/test/passes/create_js_modules_test.exs b/test/passes/create_js_modules_test.exs deleted file mode 100644 index 23b4edc3..00000000 --- a/test/passes/create_js_modules_test.exs +++ /dev/null @@ -1,30 +0,0 @@ -defmodule ElixirScript.Passes.CreateJSModules.Test do - use ExUnit.Case - - import ElixirScript.TestHelper - - alias ElixirScript.Passes.CreateJSModules - alias ESTree.Tools.Generator - - test "start" do - ex_ast = quote do: CreateJSModules.start - js = """ - Elixir.start = function(app, args) { - app.__load(Elixir).start(Symbol.for('normal'), args) - } - """ - - assert_translation(ex_ast, js) - end - - test "load" do - ex_ast = quote do: CreateJSModules.load - js = """ - Elixir.load = function(module) { - return module.__load(Elixir); - } - """ - - assert_translation(ex_ast, js) - end -end diff --git a/test/passes/handle_output_test.exs b/test/passes/handle_output_test.exs deleted file mode 100644 index 8691a6be..00000000 --- a/test/passes/handle_output_test.exs +++ /dev/null @@ -1,21 +0,0 @@ -defmodule ElixirScript.Passes.HandleOutput.Test do - use ExUnit.Case - alias ElixirScript.Passes.HandleOutput - - test "get_js_path output: nil" do - assert HandleOutput.get_js_path(nil) == "Elixir.App.js" - end - - test "get_js_path output: stdout" do - assert HandleOutput.get_js_path(:stdout) == "Elixir.App.js" - end - - test "get_js_path output is directory" do - assert HandleOutput.get_js_path("/path/to/file/") == "/path/to/file/Elixir.App.js" - assert HandleOutput.get_js_path("/path/to/file") == "/path/to/file/Elixir.App.js" - end - - test "get_js_path output ends in js" do - assert HandleOutput.get_js_path("/path/to/file/myfile.js") == "/path/to/file/myfile.js" - end -end \ No newline at end of file diff --git a/test/next/passes/translate/form_test.exs b/test/passes/translate/form_test.exs similarity index 98% rename from test/next/passes/translate/form_test.exs rename to test/passes/translate/form_test.exs index 5d8dc95c..50dcd93f 100644 --- a/test/next/passes/translate/form_test.exs +++ b/test/passes/translate/form_test.exs @@ -1,7 +1,7 @@ defmodule ElixirScript.Translate.Forms.Test do use ExUnit.Case alias ElixirScript.Translate.Form - alias ElixirScript.Translator.Identifier + alias ElixirScript.Translate.Identifier alias ESTree.Tools.Builder, as: J diff --git a/test/next/passes/translate/forms/map_test.exs b/test/passes/translate/forms/map_test.exs similarity index 100% rename from test/next/passes/translate/forms/map_test.exs rename to test/passes/translate/forms/map_test.exs diff --git a/test/next/passes/translate/forms/receive_test.exs b/test/passes/translate/forms/receive_test.exs similarity index 100% rename from test/next/passes/translate/forms/receive_test.exs rename to test/passes/translate/forms/receive_test.exs diff --git a/test/next/passes/translate/forms/remote_test.exs b/test/passes/translate/forms/remote_test.exs similarity index 100% rename from test/next/passes/translate/forms/remote_test.exs rename to test/passes/translate/forms/remote_test.exs diff --git a/test/prelude/js_test.exs b/test/prelude/js_test.exs deleted file mode 100644 index 3cff3835..00000000 --- a/test/prelude/js_test.exs +++ /dev/null @@ -1,52 +0,0 @@ -defmodule ElixirScript.Lib.JS.Test do - use ExUnit.Case - import ElixirScript.TestHelper - - test "translate new" do - ex_ast = quote do - require JS - - def execute() do - JS.new A.B, [1, 2, 3] - end - end - - js_code = """ - new A.B(1, 2, 3) - """ - - assert_translation(ex_ast, js_code) - - ex_ast = quote do - require JS - - def execute() do - JS.new A, [1, 2, 3] - end - end - - js_code = """ - new A(1, 2, 3) - """ - - assert_translation(ex_ast, js_code) - end - - test "translate update" do - ex_ast = quote do - require JS - - def execute() do - JS.update A, %{"b" => [1, 2, 3]} - end - end - - js_code = """ - Object.assign(A, Object.freeze({ - b: Object.freeze([1, 2, 3]) - })) - """ - - assert_translation(ex_ast, js_code) - end -end diff --git a/test/prelude/kernel_test.exs b/test/prelude/kernel_test.exs deleted file mode 100644 index e134c61e..00000000 --- a/test/prelude/kernel_test.exs +++ /dev/null @@ -1,44 +0,0 @@ -defmodule ElixirScript.Lib.Elixir.Kernel.Test do - use ExUnit.Case - import ElixirScript.TestHelper - - test "translate range" do - ex_ast = quote do - 1..4 - end - - js_code = """ - - Elixir.ElixirScript.Range.__load(Elixir).__struct__(Object.freeze({ - [Symbol.for('first')]: 1, - [Symbol.for('last')]: 4 - })) - """ - - assert_translation(ex_ast, js_code) - end - - test "translate sigil_r" do - ex_ast = quote do - ~r/foo/ - end - - js_code = """ - Elixir.ElixirScript.Regex.__load(Elixir).compile__emark__('foo', '') - """ - - assert_translation(ex_ast, js_code) - end - - test "translate sigil_r with options" do - ex_ast = quote do - ~r/foo/i - end - - js_code = """ - Elixir.ElixirScript.Regex.__load(Elixir).compile__emark__('foo', 'i') - """ - - assert_translation(ex_ast, js_code) - end -end diff --git a/test/support/main.ex b/test/support/main.ex index a18d3d90..ec70a46a 100644 --- a/test/support/main.ex +++ b/test/support/main.ex @@ -1,5 +1,8 @@ defmodule Main do def start(:normal, [callback]) do callback.("started") + + JS.console.log String.valid?("a") + JS.console.log String.valid?(1) end end diff --git a/test/test_helper.exs b/test/test_helper.exs index f23b9de7..30fac768 100644 --- a/test/test_helper.exs +++ b/test/test_helper.exs @@ -1,87 +1,3 @@ exclude = if Node.alive?, do: [], else: [skip: true] ExUnit.start(exclude: exclude) - -defmodule ElixirScript.Math do - defmacro squared(x) do - quote do - unquote(x) * unquote(x) - end - end -end - -defmodule ElixirScript.Using do - defmacro __using__(_) do - quote do - def sandwich() do - end - end - end -end - -defmodule ElixirScript.TestHelper do - use ExUnit.Case - - def make_custom_env do - use ElixirScript - require ElixirScript.Math - require ElixirScript.Using - __ENV__ - end - - def ex_ast_to_js(ex_ast, format) do - ElixirScript.compile_quoted(ex_ast, %{ env: make_custom_env(), import_standard_libs: false, format: format }) - end - - def strip_spaces(js) do - js |> String.replace(~r/\s+/, "") - end - - def assert_translation(ex_ast, js_code) do - assert_translation(ex_ast, js_code, :es) - end - - def assert_translation(ex_ast, js_code, format) do - converted_code = ex_ast_to_js(ex_ast, format) - - assert converted_code |> strip_spaces =~ strip_spaces(js_code), """ - **Code Does Not Match ** - - ***Expected*** - #{js_code} - - ***Actual*** - #{converted_code} - """ - end - - def assert_js_matches(expected_js_code, actual_js_code) do - assert strip_spaces(hd(List.wrap(actual_js_code))) =~ strip_spaces(expected_js_code), """ - **Code Does Not Match ** - - ***Expected*** - #{expected_js_code} - - ***Actual*** - #{actual_js_code} - """ - end - - def refute_translation(ex_ast, js_code) do - refute_translation(ex_ast, js_code, :es) - end - - def refute_translation(ex_ast, js_code, format) do - converted_code = ex_ast_to_js(ex_ast, format) - - refute converted_code |> strip_spaces =~ strip_spaces(js_code), """ - **Code Does Not Match ** - - ***Expected*** - #{js_code} - - ***Actual*** - #{converted_code} - """ - end -end diff --git a/test/translator/access_test.exs b/test/translator/access_test.exs deleted file mode 100644 index 194c24d7..00000000 --- a/test/translator/access_test.exs +++ /dev/null @@ -1,14 +0,0 @@ -defmodule ElixirScript.Translator.Access.Test do - use ExUnit.Case - import ElixirScript.TestHelper - - test "translate access" do - ex_ast = quote do - a = [] - a[:b] - end - js_code = "a[Symbol.for('b')]" - - assert_translation(ex_ast, js_code) - end -end diff --git a/test/translator/atom_test.exs b/test/translator/atom_test.exs deleted file mode 100644 index 90edfc9d..00000000 --- a/test/translator/atom_test.exs +++ /dev/null @@ -1,14 +0,0 @@ -defmodule ElixirScript.Translator.Atom.Test do - use ExUnit.Case - import ElixirScript.TestHelper - - test "translate atom" do - ex_ast = quote do: :atom - assert_translation(ex_ast, "Symbol.for('atom')") - end - - test "Call Atom module" do - ex_ast = quote do: Atom.to_string(:atom) - assert_translation(ex_ast, "Elixir.ElixirScript.Atom.__load(Elixir).to_string(Symbol.for('atom'))") - end -end diff --git a/test/translator/bitstring_test.exs b/test/translator/bitstring_test.exs deleted file mode 100644 index 2faef0e2..00000000 --- a/test/translator/bitstring_test.exs +++ /dev/null @@ -1,95 +0,0 @@ -defmodule ElixirScript.Translator.Bitstring.Test do - use ExUnit.Case - import ElixirScript.TestHelper - - test "translate bitstring" do - ex_ast = quote do: <<1, 2, 3>> - assert_translation(ex_ast, "new Bootstrap.Core.BitString(Bootstrap.Core.BitString.integer(1), Bootstrap.Core.BitString.integer(2), Bootstrap.Core.BitString.integer(3))") - - ex_ast = quote do: <<1, "foo">> - assert_translation(ex_ast, "new Bootstrap.Core.BitString(Bootstrap.Core.BitString.integer(1), Bootstrap.Core.BitString.binary('foo'))") - - ex_ast = quote do: <<1, "foo" :: binary>> - assert_translation(ex_ast, "new Bootstrap.Core.BitString(Bootstrap.Core.BitString.integer(1), Bootstrap.Core.BitString.binary('foo'))") - - ex_ast = quote do: <<1, "foo" :: utf8, "bar" :: utf32>> - assert_translation(ex_ast, "new Bootstrap.Core.BitString(Bootstrap.Core.BitString.integer(1), Bootstrap.Core.BitString.utf8('foo'), Bootstrap.Core.BitString.utf32('bar'))") - - ex_ast = quote do - rest = "oo" - <<102 :: integer-native, rest :: binary>> - end - assert_translation(ex_ast, "new Bootstrap.Core.BitString(Bootstrap.Core.BitString.native(Bootstrap.Core.BitString.integer(102)), Bootstrap.Core.BitString.binary(rest))") - - ex_ast = quote do - rest = "oo" - <<102 :: unsigned-big-integer, rest :: binary>> - end - assert_translation(ex_ast, "new Bootstrap.Core.BitString(Bootstrap.Core.BitString.integer(Bootstrap.Core.BitString.big(Bootstrap.Core.BitString.unsigned(102))), Bootstrap.Core.BitString.binary(rest))") - - ex_ast = quote do - rest = 100 - <<102, rest :: size(16)>> - end - - assert_translation(ex_ast, "new Bootstrap.Core.BitString(Bootstrap.Core.BitString.integer(102), Bootstrap.Core.BitString.size(rest, 16))") - - ex_ast = quote do - rest = 100 - <<102, rest :: size(16)-unit(4)>> - end - - assert_translation(ex_ast, "new Bootstrap.Core.BitString(Bootstrap.Core.BitString.integer(102), Bootstrap.Core.BitString.unit(Bootstrap.Core.BitString.size(rest, 16), 4))") - - ex_ast = quote do - rest = 100 - <<102, rest :: 16 * 4>> - end - - assert_translation(ex_ast, "new Bootstrap.Core.BitString(Bootstrap.Core.BitString.integer(102), Bootstrap.Core.BitString.unit(Bootstrap.Core.BitString.size(rest, 16), 4))") - - ex_ast = quote do - rest = 100 - <<102, rest :: 16>> - end - - assert_translation(ex_ast, "new Bootstrap.Core.BitString(Bootstrap.Core.BitString.integer(102), Bootstrap.Core.BitString.size(rest, 16))") - - ex_ast = quote do: << 1, <<2>> >> - assert_translation(ex_ast, "new Bootstrap.Core.BitString(Bootstrap.Core.BitString.integer(1), new Bootstrap.Core.BitString(Bootstrap.Core.BitString.integer(2)))") - end - - test "translate pattern matching bitstring" do - ex_ast = quote do: <> = <<"Frank the Walrus">> - js_code = """ - let [name,species] = Bootstrap.Core.Patterns.match(Bootstrap.Core.Patterns.bitStringMatch(Bootstrap.Core.BitString.size(Bootstrap.Core.BitString.binary({ - 'value': Bootstrap.Core.Patterns.variable() - }),5),Bootstrap.Core.BitString.binary(' the '),Bootstrap.Core.BitString.binary({ - 'value': Bootstrap.Core.Patterns.variable() - })),'Frank the Walrus'); - """ - - assert_translation(ex_ast, js_code) - - - ex_ast = quote do: <> = <<-100>> - js_code = """ - let [int] = Bootstrap.Core.Patterns.match(Bootstrap.Core.Patterns.bitStringMatch(Bootstrap.Core.BitString.integer({ - 'value': Bootstrap.Core.Patterns.variable() - })),new Bootstrap.Core.BitString(Bootstrap.Core.BitString.binary(-100))); - """ - - assert_translation(ex_ast, js_code) - - - ex_ast = quote do: <<-100::signed, _rest::binary>> = <<-100, "foo">> - js_code = """ - let [_rest] = Bootstrap.Core.Patterns.match(Bootstrap.Core.Patterns.bitStringMatch(Bootstrap.Core.BitString.signed(-100),Bootstrap.Core.BitString.binary({ - 'value': Bootstrap.Core.Patterns.variable() - })),new Bootstrap.Core.BitString(Bootstrap.Core.BitString.binary(-100),Bootstrap.Core.BitString.binary('foo'))); - """ - - assert_translation(ex_ast, js_code) - end - -end diff --git a/test/translator/bitwise_test.exs b/test/translator/bitwise_test.exs deleted file mode 100644 index 0f9f6a57..00000000 --- a/test/translator/bitwise_test.exs +++ /dev/null @@ -1,15 +0,0 @@ -defmodule ElixirScript.Translator.Bitwise.Test do - use ExUnit.Case - import ElixirScript.TestHelper - - test "bitwise when imported" do - ex_ast = quote do - import Bitwise - 1 &&& 2 - end - - js_code = "1 & 2" - - assert_translation(ex_ast, js_code) - end -end diff --git a/test/translator/bug_test.exs b/test/translator/bug_test.exs deleted file mode 100644 index f4474eb1..00000000 --- a/test/translator/bug_test.exs +++ /dev/null @@ -1,161 +0,0 @@ -defmodule ElixirScript.Translator.Bug.Test do - use ExUnit.Case - import ElixirScript.TestHelper - - test "Translate function with 0 arguments" do - ex_ast = quote do - def test do - :atom - end - end - - js_code = """ - const test = Bootstrap.Core.Patterns.defmatch(Bootstrap.Core.Patterns.clause([],function(){ - return Symbol.for('atom'); - })); - """ - - assert_translation(ex_ast, js_code) - end - - test "Translate react element" do - ex_ast = quote do - def execute() do - React.createElement( - React.Text, - %{"style" => ""}, - "Welcome to React Native!" - ) - end - end - - js_code = """ - React.createElement(React.Text,Object.freeze({ - style: '' - }),'Welcome to React Native!') - """ - - assert_translation(ex_ast, js_code) - - end - - test "replace !" do - ex_ast = quote do - def execute(data, i) do - Enum.fetch!(data, i) - end - end - - js_code = """ - Elixir.ElixirScript.Enum.__load(Elixir).fetch__emark__(data, i) - """ - - assert_translation(ex_ast, js_code) - end - - test "chain calls correctly" do - ex_ast = quote do - def execute() do - :this.getRawCanvas().getContext("2d") - end - end - - js_code = """ - Bootstrap.Core.Functions.call_property(this, 'getRawCanvas').getContext('2d') - """ - - assert_translation(ex_ast, js_code) - - - ex_ast = quote do - def execute(one) do - :this.getRawCanvas(one).get("fg").getContext("2d") - end - end - - js_code = """ - this.getRawCanvas(one).get('fg').getContext('2d') - """ - - assert_translation(ex_ast, js_code) - end - - test "correctly call multi-module functions" do - ex_ast = quote do - def getDispatcher() do - DeLorean.Flux.createDispatcher(%{ - startPainting: fn() -> :this.dispatch("startPainting") end, - stopPainting: fn() -> :this.dispatch("stopPainting") end, - addPoint: fn(data) -> :this.dispatch("addPoint", data) end, - getStores: fn() -> %{ graphic: GraphicStore } end - }) - end - end - - - js_code = """ - const getDispatcher = Bootstrap.Core.Patterns.defmatch(Bootstrap.Core.Patterns.clause([],function() { - return DeLorean.Flux.createDispatcher(Object.freeze({ - [Symbol.for('startPainting')]: Bootstrap.Core.Patterns.defmatch(Bootstrap.Core.Patterns.clause([],function() { - return this.dispatch('startPainting'); - })), [Symbol.for('stopPainting')]: Bootstrap.Core.Patterns.defmatch(Bootstrap.Core.Patterns.clause([],function() { - return this.dispatch('stopPainting'); - })), [Symbol.for('addPoint')]: Bootstrap.Core.Patterns.defmatch(Bootstrap.Core.Patterns.clause([Bootstrap.Core.Patterns.variable()],function(data) { - return this.dispatch('addPoint',data); - })), [Symbol.for('getStores')]: Bootstrap.Core.Patterns.defmatch(Bootstrap.Core.Patterns.clause([],function() { - return Object.freeze({ - [Symbol.for('graphic')]: GraphicStore - }); - })) - })); - })); - """ - - assert_translation(ex_ast, js_code) - end - - - test "test array returns correctly" do - ex_ast = quote do - def my_func(x) do - [x.a, x.b] - end - end - - js_code = """ - const my_func = Bootstrap.Core.Patterns.defmatch(Bootstrap.Core.Patterns.clause([Bootstrap.Core.Patterns.variable()],function(x){ - return Object.freeze([Bootstrap.Core.Functions.call_property(x,'a'), Bootstrap.Core.Functions.call_property(x,'b')]); - })); - """ - - assert_translation(ex_ast, js_code) - end - - test "Elixir.Enum.member__qmark__ does not show up in translation" do - ex_ast = quote do - Enum.member?([1, 2, 3], 1) - end - - js_code = """ - Elixir.Enum.member__qmark__ - """ - - refute_translation(ex_ast, js_code) - end - - test "pipe translates correctly" do - ex_ast = quote do - def execute() do - :document.getElementById("main") |> JS.update(%{"innerHTML" => @html}) - end - end - - js_code = """ - Object.assign(document.getElementById('main'), Object.freeze({ - innerHTML: html - })) - """ - - assert_translation(ex_ast, js_code) - end -end diff --git a/test/translator/capture_test.exs b/test/translator/capture_test.exs deleted file mode 100644 index 892321ac..00000000 --- a/test/translator/capture_test.exs +++ /dev/null @@ -1,131 +0,0 @@ -defmodule ElixirScript.Translator.Capture.Test do - use ExUnit.Case - import ElixirScript.TestHelper - - test "translate capture operator with Module, function, and arity" do - ex_ast = quote do - fun = &Elixir.Kernel.is_atom/1 - end - - js_code = """ - let [fun] = Bootstrap.Core.Patterns.match(Bootstrap.Core.Patterns.variable(), Elixir.ElixirScript.Kernel.__load(Elixir).is_atom); - """ - - assert_translation(ex_ast, js_code) - - end - - test "translate capture operator with function, and parameters" do - - ex_ast = quote do - fun = &is_atom(&1) - end - - js_code = """ - let [fun] = Bootstrap.Core.Patterns.match(Bootstrap.Core.Patterns.variable(),Bootstrap.Core.Patterns.defmatch(Bootstrap.Core.Patterns.clause([Bootstrap.Core.Patterns.variable()],function(__1) { - return Elixir.ElixirScript.Kernel.__load(Elixir).is_atom(__1); - }))); - """ - - assert_translation(ex_ast, js_code) - - - end - - test "translate capture operator with function, and arity" do - - ex_ast = quote do - fun = &is_atom/1 - end - - js_code = """ - let [fun] = Bootstrap.Core.Patterns.match(Bootstrap.Core.Patterns.variable(),is_atom); - """ - - assert_translation(ex_ast, js_code) - - end - - test "translate capture operator with anonymous function" do - - ex_ast = quote do - fun = &(&1 * 2) - end - - js_code = """ - let [fun] = Bootstrap.Core.Patterns.match(Bootstrap.Core.Patterns.variable(),Bootstrap.Core.Patterns.defmatch(Bootstrap.Core.Patterns.clause([Bootstrap.Core.Patterns.variable()],function(__1) { - return __1 * 2; - }))); - """ - - assert_translation(ex_ast, js_code) - - end - - test "translate capture operator with anonymous function tuple" do - - ex_ast = quote do - fun = &{&1, &2} - end - - js_code = """ - let [fun] = Bootstrap.Core.Patterns.match(Bootstrap.Core.Patterns.variable(),Bootstrap.Core.Patterns.defmatch(Bootstrap.Core.Patterns.clause([Bootstrap.Core.Patterns.variable(), Bootstrap.Core.Patterns.variable()],function(__1,__2) { - return new Bootstrap.Core.Tuple(__1,__2); - }))); - """ - - assert_translation(ex_ast, js_code) - - ex_ast = quote do - fun = &{&1, &2, &3} - end - - js_code = """ - let [fun] = Bootstrap.Core.Patterns.match(Bootstrap.Core.Patterns.variable(),Bootstrap.Core.Patterns.defmatch(Bootstrap.Core.Patterns.clause([Bootstrap.Core.Patterns.variable(), Bootstrap.Core.Patterns.variable(), Bootstrap.Core.Patterns.variable()],function(__1,__2,__3) { - return new Bootstrap.Core.Tuple(__1,__2,__3); - }))); - """ - - assert_translation(ex_ast, js_code) - - - end - - test "translate capture operator with anonymous functions as parameters" do - - ex_ast = quote do - def process(a) do - end - - def execute() do - Enum.map([], &process(&1)) - end - end - - js_code = """ - Elixir.ElixirScript.Enum.__load(Elixir).map(Object.freeze([]),Bootstrap.Core.Patterns.defmatch(Bootstrap.Core.Patterns.clause([Bootstrap.Core.Patterns.variable()],function(__1) { - return process(__1); - }))) - """ - - assert_translation(ex_ast, js_code) - - - ex_ast = quote do - def process_event(a) do - end - - def execute() do - Elem.keypress(&process_event(&1)) - end - end - - js_code = """ - Elem.keypress(Bootstrap.Core.Patterns.defmatch(Bootstrap.Core.Patterns.clause([Bootstrap.Core.Patterns.variable()],function(__1) { - return process_event(__1); - }))) - """ - - assert_translation(ex_ast, js_code) - end -end diff --git a/test/translator/case_test.exs b/test/translator/case_test.exs deleted file mode 100644 index 4a38b333..00000000 --- a/test/translator/case_test.exs +++ /dev/null @@ -1,211 +0,0 @@ -defmodule ElixirScript.Translator.Case.Test do - use ExUnit.Case - import ElixirScript.TestHelper - - test "translate case" do - - ex_ast = quote do - def execute() do - data = :ok - case data do - :ok -> 1 - :error -> nil - end - end - end - - js_code = """ - Bootstrap.Core.Patterns.defmatch(Bootstrap.Core.Patterns.clause([Symbol.for('ok')],function() { - return 1; - }),Bootstrap.Core.Patterns.clause([Symbol.for('error')],function() { - return null; - })).call(this,data) - """ - - assert_translation(ex_ast, js_code) - - ex_ast = quote do - data = true - case data do - false -> value = 13 - true -> true - end - end - - js_code = """ - Bootstrap.Core.Patterns.defmatch(Bootstrap.Core.Patterns.clause([false],function() { - let [value] = Bootstrap.Core.Patterns.match(Bootstrap.Core.Patterns.variable(),13); - return value; - }),Bootstrap.Core.Patterns.clause([true],function() { - return true; - })).call(this,data) - """ - - assert_translation(ex_ast, js_code) - - - - ex_ast = quote do - data = :ok - case data do - false -> value = 13 - _ -> true - end - end - - js_code = """ - Bootstrap.Core.Patterns.defmatch(Bootstrap.Core.Patterns.clause([false],function() { - let [value] = Bootstrap.Core.Patterns.match(Bootstrap.Core.Patterns.variable(),13); - return value; - }),Bootstrap.Core.Patterns.clause([Bootstrap.Core.Patterns.variable()],function(__ignored__) { - return true; - })).call(this,data) - """ - - assert_translation(ex_ast, js_code) - end - - test "translate case with guard" do - ex_ast = quote do - data = :ok - case data do - number when number in [1,2,3,4] -> - value = 13 - _ -> - true - end - end - - js_code = """ - Bootstrap.Core.Patterns.defmatch(Bootstrap.Core.Patterns.clause([Bootstrap.Core.Patterns.variable()],function(number) { - let [value] = Bootstrap.Core.Patterns.match(Bootstrap.Core.Patterns.variable(),13); - return value; - },function(number) { - return Elixir.ElixirScript.Bootstrap.Functions.__load(Elixir).contains(number,Object.freeze([1, 2, 3, 4])); - }),Bootstrap.Core.Patterns.clause([Bootstrap.Core.Patterns.variable()],function(__ignored__) { - return true; - })).call(this,data) - """ - - assert_translation(ex_ast, js_code) - end - - test "translate case with multiple guards" do - ex_ast = quote do - data = :ok - case data do - number when number in [1,2,3,4] when number in [4, 3, 2, 1] -> - value = 13 - _ -> - true - end - end - - js_code = """ - Bootstrap.Core.Patterns.defmatch(Bootstrap.Core.Patterns.clause([Bootstrap.Core.Patterns.variable()],function(number) { - let [value] = Bootstrap.Core.Patterns.match(Bootstrap.Core.Patterns.variable(),13); - return value; - },function(number) { - return Elixir.ElixirScript.Bootstrap.Functions.__load(Elixir).contains(number,Object.freeze([1, 2, 3, 4])) || Elixir.ElixirScript.Bootstrap.Functions.__load(Elixir).contains(number,Object.freeze([4, 3, 2, 1])); - }),Bootstrap.Core.Patterns.clause([Bootstrap.Core.Patterns.variable()],function(__ignored__) { - return true; - })).call(this,data) - """ - - assert_translation(ex_ast, js_code) - end - - test "translate case with multiple statements in body" do - ex_ast = quote do - def execute() do - data = :ok - case data do - :ok -> - :console.info("info") - Todo.add(data) - :error -> - nil - end - end - end - - js_code = """ - Bootstrap.Core.Patterns.defmatch(Bootstrap.Core.Patterns.clause([Symbol.for('ok')],function() { - console.info('info'); - return Todo.add(data); - }),Bootstrap.Core.Patterns.clause([Symbol.for('error')],function() { - return null; - })).call(this,data) - """ - - assert_translation(ex_ast, js_code) - end - - test "translate case with destructing" do - ex_ast = quote do - def execute() do - data = :ok - case data do - { one, two } -> - :console.info(one) - :error -> - nil - end - end - end - - js_code = """ -Bootstrap.Core.Patterns.defmatch(Bootstrap.Core.Patterns.clause([new Bootstrap.Core.Tuple(Bootstrap.Core.Patterns.variable(), Bootstrap.Core.Patterns.variable())], function(one, two) { - return console.info(one); - }), Bootstrap.Core.Patterns.clause([Symbol.for('error')], function() { - return null; - })).call(this, data); - """ - - assert_translation(ex_ast, js_code) - end - - test "translate case with nested destructing" do - ex_ast = quote do - def execute() do - data = :error - case data do - { {one, two} , three } -> - :console.info(one) - :error -> - nil - end - end - end - - js_code = """ -Bootstrap.Core.Patterns.defmatch(Bootstrap.Core.Patterns.clause([new Bootstrap.Core.Tuple(new Bootstrap.Core.Tuple(Bootstrap.Core.Patterns.variable(), Bootstrap.Core.Patterns.variable()), Bootstrap.Core.Patterns.variable())], function(one, two, three) { - return console.info(one); - }), Bootstrap.Core.Patterns.clause([Symbol.for('error')], function() { - return null; - })).call(this, data) - """ - - assert_translation(ex_ast, js_code) - - ex_ast = quote do - data = :error - case data do - { one, {two, three} } -> - :console.info(one) - :error -> - nil - end - end - - js_code = """ -Bootstrap.Core.Patterns.defmatch(Bootstrap.Core.Patterns.clause([new Bootstrap.Core.Tuple(Bootstrap.Core.Patterns.variable(), new Bootstrap.Core.Tuple(Bootstrap.Core.Patterns.variable(), Bootstrap.Core.Patterns.variable()))], function(one, two, three) { - return console.info(one); - }), Bootstrap.Core.Patterns.clause([Symbol.for('error')], function() { - return null; - })).call(this, data) - """ - - assert_translation(ex_ast, js_code) - end -end diff --git a/test/translator/commonjs_test.exs b/test/translator/commonjs_test.exs deleted file mode 100644 index 187a9cdd..00000000 --- a/test/translator/commonjs_test.exs +++ /dev/null @@ -1,22 +0,0 @@ -defmodule ElixirScript.Translator.CommonJS.Test do - use ExUnit.Case - import ElixirScript.TestHelper - - test "translate module to commonjs" do - ex_ast = quote do - defmodule Elephant do - @ul "#todo-list" - - def something() do - @ul - end - end - end - - js_code = """ - module.exports = Elixir - """ - - assert_translation(ex_ast, js_code, :common) - end -end diff --git a/test/translator/cond_test.exs b/test/translator/cond_test.exs deleted file mode 100644 index 8b5f605d..00000000 --- a/test/translator/cond_test.exs +++ /dev/null @@ -1,58 +0,0 @@ -defmodule ElixirScript.Translator.Cond.Test do - use ExUnit.Case - import ElixirScript.TestHelper - - test "translate cond" do - ex_ast = quote do - cond do - 1 + 1 == 1 -> - "This will never match" - 2 * 2 != 4 -> - "Nor this" - true -> - "This will" - end - end - - js_code = """ - Bootstrap.Core.SpecialForms.cond(Object.freeze([1 + 1 == 1, function() { - return 'This will never match'; - }]),Object.freeze([2 * 2 != 4, function() { - return 'Nor this'; - }]),Object.freeze([true, function() { - return 'This will'; - }])) - """ - - assert_translation(ex_ast, js_code) - - ex_ast = quote do - cond do - 1 + 1 == 1 -> - a = 1 - "This will never match" - 2 * 2 != 4 -> - a = 2 - "Nor this" - true -> - a = 3 - "This will" - end - end - - js_code = """ - Bootstrap.Core.SpecialForms.cond(Object.freeze([1 + 1 == 1, function() { - let [a] = Bootstrap.Core.Patterns.match(Bootstrap.Core.Patterns.variable(),1); - return 'This will never match'; - }]),Object.freeze([2 * 2 != 4, function() { - let [a] = Bootstrap.Core.Patterns.match(Bootstrap.Core.Patterns.variable(),2); - return 'Nor this'; - }]),Object.freeze([true, function() { - let [a] = Bootstrap.Core.Patterns.match(Bootstrap.Core.Patterns.variable(),3); - return 'This will'; - }])) - """ - - assert_translation(ex_ast, js_code) - end -end diff --git a/test/translator/defdelegate_test.exs b/test/translator/defdelegate_test.exs deleted file mode 100644 index 52ef6266..00000000 --- a/test/translator/defdelegate_test.exs +++ /dev/null @@ -1,28 +0,0 @@ -defmodule ElixirScript.Translator.Defdelegate.Test do - use ExUnit.Case - import ElixirScript.TestHelper - - test "translate defdelegate" do - ex_ast = quote do: defdelegate reverse(list), to: :lists - - js_code = """ - const reverse = function(list) { - return Elixir.ElixirScript.Bootstrap.Functions.__load(Elixir).reverse(list); - }; - """ - - assert_translation(ex_ast, js_code) - end - - test "translate defdelegate as another name" do - ex_ast = quote do: defdelegate other_reverse(list), to: :lists, as: :reverse - - js_code = """ - const other_reverse = function(list) { - return Elixir.ElixirScript.Bootstrap.Functions.__load(Elixir).reverse(list); - }; - """ - - assert_translation(ex_ast, js_code) - end -end diff --git a/test/translator/defmodule_test.exs b/test/translator/defmodule_test.exs deleted file mode 100644 index 8719b2a9..00000000 --- a/test/translator/defmodule_test.exs +++ /dev/null @@ -1,176 +0,0 @@ -defmodule ElixirScript.Translator.Defmodule.Test do - use ExUnit.Case - import ElixirScript.TestHelper - - test "translate empty module" do - ex_ast = quote do - defmodule Elephant do - end - end - - js_code = """ - const __exports = { - __info__ - }; - """ - - assert_translation(ex_ast, js_code) - end - - test "translate defmodules" do - ex_ast = quote do - defmodule Elephant do - require JS - @ul "#todo-list" - - def something() do - @ul - end - - JS.defgenp something_else() do - end - end - end - - js_code = """ - const something = Bootstrap.Core.Patterns.defmatch(Bootstrap.Core.Patterns.clause([], function() { - return ul; - })); - - const __info__ = function(kind) { - return Bootstrap.Core.Patterns.defmatch(Bootstrap.Core.Patterns.clause([Symbol.for('functions')], function() { - return Object.freeze([new Bootstrap.Core.Tuple(Symbol.for('something'), 0)]); - }), Bootstrap.Core.Patterns.clause([Symbol.for('macros')], function() { - return Object.freeze([]); - }), Bootstrap.Core.Patterns.clause([Symbol.for('module')], function() { - return Symbol.for('Elixir.Elephant'); - })).call(this, kind); - }; - - const ul = '#todo-list'; - - const something_else = Bootstrap.Core.Patterns.defmatchgen(Bootstrap.Core.Patterns.clause([], function*() { - return null; - })); - """ - - assert_translation(ex_ast, js_code) - end - - test "translate modules with inner modules" do - ex_ast = quote do - defmodule Animals do - - defmodule Elephant do - defstruct [trunk: true] - end - - def something() do - %Animals.Elephant{} - end - - defp something_else() do - end - - end - end - - js_code = """ - const __struct__ = function(values = {}) { - const allowed_keys = [Symbol.for('trunk')] - - const value_keys = Object.keys(values) - - const every_call_result = value_keys.every(function(key) { - return allowed_keys.includes(key); - }) - - if (every_call_result) { - return Object.assign({}, { - [Symbol.for('__struct__')]: Symbol.for('Elixir.Animals.Elephant'), - [Symbol.for('trunk')]: true - }, values); - } else { - throw 'Unallowed key found'; - } - }; - """ - - assert_translation(ex_ast, js_code) - end - - - test "translate modules with inner module that has inner module" do - ex_ast = quote do - defmodule Animals do - - defmodule Elephant do - defstruct trunk: true - - defmodule Bear do - defstruct trunk: true - end - end - - - def something() do - %Animals.Elephant{} - end - - defp something_else() do - end - - end - end - - js_code = """ - const __struct__ = function(values = {}) { - const allowed_keys = [Symbol.for('trunk')] - - const value_keys = Object.keys(values) - - const every_call_result = value_keys.every(function(key) { - return allowed_keys.includes(key); - }) - - if (every_call_result) { - return Object.assign({}, { - [Symbol.for('__struct__')]: Symbol.for('Elixir.Animals.Elephant.Bear'), - [Symbol.for('trunk')]: true - }, values); - } else { - throw 'Unallowed key found'; - } - }; - """ - - assert_translation(ex_ast, js_code) - end - - test "Pull out module references and make them into imports if modules listed" do - ex_ast = quote do - defmodule Lions.Tigers.Bears do - def oh_my() do - end - end - - defmodule Lions.Tigers do - def oh_my() do - end - - Lions.Tigers.Bears.oh_my() - end - - defmodule Animals do - Lions.Tigers.oh_my() - end - end - - js_code = """ - Elixir.Lions.Tigers.Bears.__load(Elixir).oh_my() - """ - - assert_translation(ex_ast, js_code) - end - -end diff --git a/test/translator/for_test.exs b/test/translator/for_test.exs deleted file mode 100644 index 60fda4e7..00000000 --- a/test/translator/for_test.exs +++ /dev/null @@ -1,202 +0,0 @@ -defmodule ElixirScript.Translator.For.Test do - use ExUnit.Case - import ElixirScript.TestHelper - - test "translate simple for" do - ex_ast = quote do - for n <- [1, 2, 3, 4], do: n * 2 - end - - js_code = """ - Bootstrap.Core.SpecialForms._for(Bootstrap.Core.Patterns.clause([Bootstrap.Core.Patterns.variable()], function(n) { - return n * 2; - }, function() { - return true; - }), [Bootstrap.Core.Patterns.list_generator(Bootstrap.Core.Patterns.variable(), Object.freeze([1, 2, 3, 4]))], Elixir.ElixirScript.Collectable.__load(Elixir), Object.freeze([])) - """ - - assert_translation(ex_ast, js_code) - end - - test "translate simple for with into" do - ex_ast = quote do - for n <- [1, 2, 3, 4], into: [], do: n * 2 - end - - js_code = """ - Bootstrap.Core.SpecialForms._for( - Bootstrap.Core.Patterns.clause( - [Bootstrap.Core.Patterns.variable()], - function(n) { - return n * 2; - }, - function() { - return true; - } - ), - [ - Bootstrap.Core.Patterns.list_generator( - Bootstrap.Core.Patterns.variable(), - Object.freeze([1, 2, 3, 4]) - ) - ], - Elixir.ElixirScript.Collectable.__load(Elixir), - Object.freeze([]) - ) - """ - - assert_translation(ex_ast, js_code) - end - - test "translate multiple generator for" do - ex_ast = quote do - for x <- [1, 2], y <- [2, 3], do: x*y - end - - js_code = """ - Bootstrap.Core.SpecialForms._for( - Bootstrap.Core.Patterns.clause( - [Bootstrap.Core.Patterns.variable(), Bootstrap.Core.Patterns.variable()], - function(x, y) { - return x * y; - }, - function() { - return true; - } - ), - [ - Bootstrap.Core.Patterns.list_generator( - Bootstrap.Core.Patterns.variable(), - Object.freeze([1, 2]) - ), - Bootstrap.Core.Patterns.list_generator( - Bootstrap.Core.Patterns.variable(), - Object.freeze([2, 3]) - ) - ], - Elixir.ElixirScript.Collectable.__load(Elixir), - Object.freeze([]) - ) - """ - - assert_translation(ex_ast, js_code) - end - - test "translate multiple generator for, assignment, and do block" do - ex_ast = quote do - r = for x <- [1, 2], y <- [2, 3] do - x*y - end - end - - js_code = """ - let [r] = Bootstrap.Core.Patterns.match( - Bootstrap.Core.Patterns.variable(), - Bootstrap.Core.SpecialForms._for( - Bootstrap.Core.Patterns.clause( - [Bootstrap.Core.Patterns.variable(), Bootstrap.Core.Patterns.variable()], - function(x, y) { - return x * y; - }, - function() { - return true; - } - ), - [ - Bootstrap.Core.Patterns.list_generator( - Bootstrap.Core.Patterns.variable(), - Object.freeze([1, 2]) - ), - Bootstrap.Core.Patterns.list_generator( - Bootstrap.Core.Patterns.variable(), - Object.freeze([2, 3]) - ) - ], - Elixir.ElixirScript.Collectable.__load(Elixir), - Object.freeze([]) - ) - ); - """ - - assert_translation(ex_ast, js_code) - end - - test "translate for with filter" do - ex_ast = quote do - for n <- [1, 2, 3, 4, 5, 6], rem(n, 2) == 0, do: n - end - - js_code = """ - Bootstrap.Core.SpecialForms._for( - Bootstrap.Core.Patterns.clause( - [Bootstrap.Core.Patterns.variable()], - function(n) { - return n; - }, - function(n) { - return n % 2 == 0; - } - ), - [ - Bootstrap.Core.Patterns.list_generator( - Bootstrap.Core.Patterns.variable(), - Object.freeze([1, 2, 3, 4, 5, 6]) - ) - ], - Elixir.ElixirScript.Collectable.__load(Elixir), - Object.freeze([]) - ) - """ - - assert_translation(ex_ast, js_code) - end - - test "translate for with pattern matched input" do - ex_ast = quote do - for {:user, name} <- [user: "john", admin: "john", user: "meg"] do - Elixir.String.upcase(name) - end - end - - js_code = """ - Bootstrap.Core.SpecialForms._for(Bootstrap.Core.Patterns.clause([new Bootstrap.Core.Tuple(Symbol.for('user'), Bootstrap.Core.Patterns.variable())], function(name) { - return Elixir.ElixirScript.String.__load(Elixir).upcase(name); - }, function() { - return true; - }), [Bootstrap.Core.Patterns.list_generator(new Bootstrap.Core.Tuple(Symbol.for('user'), Bootstrap.Core.Patterns.variable()), Object.freeze([new Bootstrap.Core.Tuple(Symbol.for('user'), 'john'), new Bootstrap.Core.Tuple(Symbol.for('admin'), 'john'), new Bootstrap.Core.Tuple(Symbol.for('user'), 'meg')]))], Elixir.ElixirScript.Collectable.__load(Elixir), Object.freeze([])) - """ - - assert_translation(ex_ast, js_code) - end - - test "translate for with bitstring" do - ex_ast = quote do - pixels = <<1, 2, 3, 4, 5, 6>> - for <> do - {r, g, b} - end - end - - js_code = """ - Bootstrap.Core.SpecialForms._for(Bootstrap.Core.Patterns.clause([Bootstrap.Core.Patterns.bitStringMatch(Bootstrap.Core.BitString.size({ - 'value': Bootstrap.Core.Patterns.variable() - }, 8), Bootstrap.Core.BitString.size({ - 'value': Bootstrap.Core.Patterns.variable() - }, 8), Bootstrap.Core.BitString.size({ - 'value': Bootstrap.Core.Patterns.variable() - }, 8))], function(r, g, b) { - return new Bootstrap.Core.Tuple(r, g, b); - }, function() { - return true; - }), [Bootstrap.Core.Patterns.bitstring_generator(Bootstrap.Core.Patterns.bitStringMatch(Bootstrap.Core.BitString.size({ - 'value': Bootstrap.Core.Patterns.variable() - }, 8), Bootstrap.Core.BitString.size({ - 'value': Bootstrap.Core.Patterns.variable() - }, 8), Bootstrap.Core.BitString.size({ - 'value': Bootstrap.Core.Patterns.variable() - }, 8)), pixels)], Elixir.ElixirScript.Collectable.__load(Elixir), Object.freeze([])) - """ - - assert_translation(ex_ast, js_code) - end -end diff --git a/test/translator/function_test.exs b/test/translator/function_test.exs deleted file mode 100644 index eb9e145e..00000000 --- a/test/translator/function_test.exs +++ /dev/null @@ -1,815 +0,0 @@ -defmodule ElixirScript.Translator.Function.Test do - use ExUnit.Case - import ElixirScript.TestHelper - - test "translate functions" do - ex_ast = quote do - def test1() do - end - end - - js_code = """ - const test1 = Bootstrap.Core.Patterns.defmatch(Bootstrap.Core.Patterns.clause([],function() { - return null; - })); - """ - - assert_translation(ex_ast, js_code) - - ex_ast = quote do - def test1(alpha, beta) do - end - end - - js_code = """ - const test1 = Bootstrap.Core.Patterns.defmatch(Bootstrap.Core.Patterns.clause([Bootstrap.Core.Patterns.variable(), Bootstrap.Core.Patterns.variable()],function(alpha,beta) { - return null; - })); - """ - - assert_translation(ex_ast, js_code) - - ex_ast = quote do - def test1(alpha, beta) do - a = alpha - end - end - - js_code = """ - const test1 = Bootstrap.Core.Patterns.defmatch(Bootstrap.Core.Patterns.clause([Bootstrap.Core.Patterns.variable(), Bootstrap.Core.Patterns.variable()],function(alpha,beta) { - let [a] = Bootstrap.Core.Patterns.match(Bootstrap.Core.Patterns.variable(),alpha); - return a; - })); - """ - - assert_translation(ex_ast, js_code) - - ex_ast = quote do - def test1(alpha, beta) do - if 1 == 1 do - 1 - else - 2 - end - end - end - - js_code = """ - const test1 = Bootstrap.Core.Patterns.defmatch(Bootstrap.Core.Patterns.clause([Bootstrap.Core.Patterns.variable(), Bootstrap.Core.Patterns.variable()],function(alpha,beta) { - return Bootstrap.Core.Patterns.defmatch(Bootstrap.Core.Patterns.clause([Bootstrap.Core.Patterns.variable()],function(x) { - return 2; - },function(x) { - return x === null || x === false; - }),Bootstrap.Core.Patterns.clause([Bootstrap.Core.Patterns.variable()],function(__ignored__) { - return 1; - })).call(this,1 == 1); - })); - """ - - assert_translation(ex_ast, js_code) - - ex_ast = quote do - def test1(alpha, beta) do - if 1 == 1 do - if 2 == 2 do - 4 - else - a = 1 - end - else - 2 - end - end - end - - js_code = """ - const test1 = Bootstrap.Core.Patterns.defmatch(Bootstrap.Core.Patterns.clause([Bootstrap.Core.Patterns.variable(), Bootstrap.Core.Patterns.variable()], function(alpha, beta) { - return Bootstrap.Core.Patterns.defmatch(Bootstrap.Core.Patterns.clause([Bootstrap.Core.Patterns.variable()], function(x) { - return 2; - }, function(x) { - return x === null || x === false; - }), Bootstrap.Core.Patterns.clause([Bootstrap.Core.Patterns.variable()], function(__ignored__) { - return Bootstrap.Core.Patterns.defmatch(Bootstrap.Core.Patterns.clause([Bootstrap.Core.Patterns.variable()], function(x) { - let [a] = Bootstrap.Core.Patterns.match(Bootstrap.Core.Patterns.variable(), 1); - - return a; - }, function(x) { - return x === null || x === false; - }), Bootstrap.Core.Patterns.clause([Bootstrap.Core.Patterns.variable()], function(__ignored__1) { - return 4; - })).call(this, 2 == 2); - })).call(this, 1 == 1); - })); - """ - - assert_translation(ex_ast, js_code) - - ex_ast = quote do - def test1(alpha, beta) do - {a, b} = {1, 2} - end - end - - js_code = """ - const test1 = Bootstrap.Core.Patterns.defmatch(Bootstrap.Core.Patterns.clause([Bootstrap.Core.Patterns.variable(), Bootstrap.Core.Patterns.variable()], function(alpha, beta) { - let [a, b] = Bootstrap.Core.Patterns.match(new Bootstrap.Core.Tuple(Bootstrap.Core.Patterns.variable(), Bootstrap.Core.Patterns.variable()), new Bootstrap.Core.Tuple(1, 2)); - - let _ref = new Bootstrap.Core.Tuple(a, b); - - return _ref; - })); - """ - - assert_translation(ex_ast, js_code) - end - - test "translate function calls" do - ex_ast = quote do - defmodule Taco do - def test1() do - end - end - - - Taco.test1() - end - - js_code = "Elixir.Taco.__load(Elixir).test1()" - - assert_translation(ex_ast, js_code) - - ex_ast = quote do - defmodule Taco do - def test1(a, b) do - end - end - - Taco.test1(3, 2) - end - - js_code = "Elixir.Taco.__load(Elixir).test1(3,2)" - - assert_translation(ex_ast, js_code) - - ex_ast = quote do - defmodule Taco do - def test1(a, b) do - end - - def test2(a) do - end - end - - Taco.test1(Taco.test2(1), 2) - end - - js_code = "Elixir.Taco.__load(Elixir).test1(Elixir.Taco.__load(Elixir).test2(1), 2)" - - assert_translation(ex_ast, js_code) - end - - - test "translate anonymous functions" do - ex_ast = quote do - list = [] - Enum.map(list, fn(x) -> x * 2 end) - end - - js_code = """ - Elixir.ElixirScript.Enum.__load(Elixir).map(list,Bootstrap.Core.Patterns.defmatch(Bootstrap.Core.Patterns.clause([Bootstrap.Core.Patterns.variable()],function(x) { - return x * 2; - }))) - """ - - assert_translation(ex_ast, js_code) - end - - test "translate function arity" do - ex_ast = quote do - defmodule Example do - - defp example() do - end - - defp example(oneArg) do - end - - defp example(oneArg, twoArg) do - end - - defp example(oneArg, twoArg, redArg) do - end - - defp example(oneArg, twoArg, redArg, blueArg) do - end - end - end - - js_code = """ - const example = Bootstrap.Core.Patterns.defmatch(Bootstrap.Core.Patterns.clause([],function() { - return null; - }),Bootstrap.Core.Patterns.clause([Bootstrap.Core.Patterns.variable()],function(oneArg) { - return null; - }),Bootstrap.Core.Patterns.clause([Bootstrap.Core.Patterns.variable(), Bootstrap.Core.Patterns.variable()],function(oneArg,twoArg) { - return null; - }),Bootstrap.Core.Patterns.clause([Bootstrap.Core.Patterns.variable(), Bootstrap.Core.Patterns.variable(), Bootstrap.Core.Patterns.variable()],function(oneArg,twoArg,redArg) { - return null; - }),Bootstrap.Core.Patterns.clause([Bootstrap.Core.Patterns.variable(), Bootstrap.Core.Patterns.variable(), Bootstrap.Core.Patterns.variable(), Bootstrap.Core.Patterns.variable()],function(oneArg,twoArg,redArg,blueArg) { - return null; - })); - """ - assert_translation(ex_ast, js_code) - - - ex_ast = quote do - defmodule Example do - def example() do - end - - def example(oneArg) do - end - - def example(oneArg, twoArg) do - end - - def example(oneArg, twoArg, redArg) do - end - - def example(oneArg, twoArg, redArg, blueArg) do - end - end - end - - js_code = """ - const example = Bootstrap.Core.Patterns.defmatch(Bootstrap.Core.Patterns.clause([],function() { - return null; - }),Bootstrap.Core.Patterns.clause([Bootstrap.Core.Patterns.variable()],function(oneArg) { - return null; - }),Bootstrap.Core.Patterns.clause([Bootstrap.Core.Patterns.variable(), Bootstrap.Core.Patterns.variable()],function(oneArg,twoArg) { - return null; - }),Bootstrap.Core.Patterns.clause([Bootstrap.Core.Patterns.variable(), Bootstrap.Core.Patterns.variable(), Bootstrap.Core.Patterns.variable()],function(oneArg,twoArg,redArg) { - return null; - }),Bootstrap.Core.Patterns.clause([Bootstrap.Core.Patterns.variable(), Bootstrap.Core.Patterns.variable(), Bootstrap.Core.Patterns.variable(), Bootstrap.Core.Patterns.variable()],function(oneArg,twoArg,redArg,blueArg) { - return null; - })); - """ - assert_translation(ex_ast, js_code) - - - ex_ast = quote do - defmodule Example do - def example(oneArg) do - end - end - end - - js_code = """ - const example = Bootstrap.Core.Patterns.defmatch(Bootstrap.Core.Patterns.clause([Bootstrap.Core.Patterns.variable()],function(oneArg) { - return null; - })); - """ - assert_translation(ex_ast, js_code) - - end - - test "test Elixir.Kernel function" do - ex_ast = quote do - is_atom(:atom) - end - - js_code = "Elixir.ElixirScript.Kernel.__load(Elixir).is_atom(Symbol.for('atom'))" - - assert_translation(ex_ast, js_code) - end - - test "guards" do - ex_ast = quote do - def something(one) when is_number(one) do - end - end - - - js_code = """ - const something = Bootstrap.Core.Patterns.defmatch(Bootstrap.Core.Patterns.clause([Bootstrap.Core.Patterns.variable()],function(one) { - return null; - },function(one) { - return Elixir.ElixirScript.Kernel.__load(Elixir).is_number(one); - })); - """ - - assert_translation(ex_ast, js_code) - - - ex_ast = quote do - def something(one) when is_number(one) or is_atom(one) do - end - end - - - js_code = """ - const something = Bootstrap.Core.Patterns.defmatch(Bootstrap.Core.Patterns.clause([Bootstrap.Core.Patterns.variable()],function(one) { - return null; - },function(one) { - return Elixir.ElixirScript.Kernel.__load(Elixir).is_number(one) || Elixir.ElixirScript.Kernel.__load(Elixir).is_atom(one); - })); - """ - - assert_translation(ex_ast, js_code) - - ex_ast = quote do - defp something(one) when is_number(one) or is_atom(one) do - end - end - - - js_code = """ - const something = Bootstrap.Core.Patterns.defmatch(Bootstrap.Core.Patterns.clause([Bootstrap.Core.Patterns.variable()],function(one) { - return null; - },function(one) { - return Elixir.ElixirScript.Kernel.__load(Elixir).is_number(one) || Elixir.ElixirScript.Kernel.__load(Elixir).is_atom(one); - })); - """ - - assert_translation(ex_ast, js_code) - - ex_ast = quote do - defp something(one, two) when one in [1, 2, 3] do - end - end - - - js_code = """ - const something = Bootstrap.Core.Patterns.defmatch(Bootstrap.Core.Patterns.clause([Bootstrap.Core.Patterns.variable(), Bootstrap.Core.Patterns.variable()],function(one,two) { - return null; - },function(one,two) { - return Elixir.ElixirScript.Bootstrap.Functions.__load(Elixir).contains(one,Object.freeze([1, 2, 3])); - })); - """ - - assert_translation(ex_ast, js_code) - - ex_ast = quote do - defmodule Example do - def something(one) when one in [1, 2, 3] do - end - - def something(one) when is_number(one) or is_atom(one) do - end - end - end - - js_code = """ - const something = Bootstrap.Core.Patterns.defmatch(Bootstrap.Core.Patterns.clause([Bootstrap.Core.Patterns.variable()],function(one) { - return null; - },function(one) { - return Elixir.ElixirScript.Bootstrap.Functions.__load(Elixir).contains(one,Object.freeze([1, 2, 3])); - }),Bootstrap.Core.Patterns.clause([Bootstrap.Core.Patterns.variable()],function(one) { - return null; - },function(one) { - return Elixir.ElixirScript.Kernel.__load(Elixir).is_number(one) || Elixir.ElixirScript.Kernel.__load(Elixir).is_atom(one); - })); - """ - assert_translation(ex_ast, js_code) - - end - - test "pattern match function with literal" do - ex_ast = quote do - def something(1) do - end - end - - - js_code = """ - const something = Bootstrap.Core.Patterns.defmatch(Bootstrap.Core.Patterns.clause([1],function() { - return null; - })); - """ - - assert_translation(ex_ast, js_code) - end - - test "pattern match function with list" do - ex_ast = quote do - def something([apple | fruits]) do - end - end - - - js_code = """ - const something = Bootstrap.Core.Patterns.defmatch(Bootstrap.Core.Patterns.clause([Bootstrap.Core.Patterns.headTail(Bootstrap.Core.Patterns.variable(),Bootstrap.Core.Patterns.variable())],function(apple,fruits) { - return null; - })); - """ - - assert_translation(ex_ast, js_code) - end - - test "pattern match function with multiple items in list" do - ex_ast = quote do - def something([apple, pear, banana]) do - end - end - - - js_code = """ - const something = Bootstrap.Core.Patterns.defmatch(Bootstrap.Core.Patterns.clause([Object.freeze([Bootstrap.Core.Patterns.variable(), Bootstrap.Core.Patterns.variable(), Bootstrap.Core.Patterns.variable()])],function(apple,pear,banana) { - return null; - })); - """ - - assert_translation(ex_ast, js_code) - end - - test "pattern match function with tuple" do - ex_ast = quote do - def something({ apple , fruits }) do - end - end - - - js_code = """ - const something = Bootstrap.Core.Patterns.defmatch(Bootstrap.Core.Patterns.clause([new Bootstrap.Core.Tuple(Bootstrap.Core.Patterns.variable(), Bootstrap.Core.Patterns.variable())], function(apple, fruits) { - return null; - })); - """ - - assert_translation(ex_ast, js_code) - end - - test "pattern match function with struct" do - ex_ast = quote do - defmodule AStruct do - defstruct [] - end - - def something(%AStruct{}) do - end - end - - - js_code = """ - const something = Bootstrap.Core.Patterns.defmatch(Bootstrap.Core.Patterns.clause([{ - [Symbol.for('__struct__')]: Symbol.for('Elixir.AStruct') - }], function() { - return null; - })); - """ - - assert_translation(ex_ast, js_code) - end - - test "pattern match function with struct reference" do - ex_ast = quote do - defmodule AStruct do - defstruct [] - end - - def something(%AStruct{} = a) do - end - - end - - js_code = """ - const something = Bootstrap.Core.Patterns.defmatch(Bootstrap.Core.Patterns.clause([Bootstrap.Core.Patterns.capture({ - [Symbol.for('__struct__')]: Symbol.for('Elixir.AStruct') - })], function(a) { - return null; - })); - """ - assert_translation(ex_ast, js_code) - end - - test "pattern match function with map reference" do - ex_ast = quote do - def something(%{ which: 13 } = a) do - end - end - - js_code = """ - const something = Bootstrap.Core.Patterns.defmatch(Bootstrap.Core.Patterns.clause([Bootstrap.Core.Patterns.capture({ - [Symbol.for('which')]: 13 - })],function(a) { - return null; - })); - """ - - assert_translation(ex_ast, js_code) - end - - test "pattern match function with struct decontructed" do - ex_ast = quote do - defmodule AStruct do - defstruct [:key, :key1] - end - - def something(%AStruct{key: value, key1: 2}) do - end - end - - - js_code = """ - const something = Bootstrap.Core.Patterns.defmatch(Bootstrap.Core.Patterns.clause([{ - [Symbol.for('__struct__')]: Symbol.for('Elixir.AStruct'), - [Symbol.for('key')]: Bootstrap.Core.Patterns.variable(), - [Symbol.for('key1')]: 2 - }], function(value) { - return null; - })); - """ - - assert_translation(ex_ast, js_code) - - ex_ast = quote do - defmodule AStruct do - defstruct [:key, :key1] - end - - def something(%AStruct{key: value, key1: 2}) when is_number(value) do - end - end - - - js_code = """ - const something = Bootstrap.Core.Patterns.defmatch(Bootstrap.Core.Patterns.clause([{ - [Symbol.for('__struct__')]: Symbol.for('Elixir.AStruct'), - [Symbol.for('key')]: Bootstrap.Core.Patterns.variable(), - [Symbol.for('key1')]: 2 - }], function(value) { - return null; - }, function(value) { - return Elixir.ElixirScript.Kernel.__load(Elixir).is_number(value); - })); - """ - - assert_translation(ex_ast, js_code) - end - - test "pattern match function with binary part" do - ex_ast = quote do - def something("Bearer " <> token) do - end - end - - - js_code = """ - const something = Bootstrap.Core.Patterns.defmatch(Bootstrap.Core.Patterns.clause([Bootstrap.Core.Patterns.startsWith('Bearer ')],function(token) { - return null; - })); - """ - - assert_translation(ex_ast, js_code) - - ex_ast = quote do - def something("Bearer " <> token, hotel) do - end - end - - - js_code = """ - const something = Bootstrap.Core.Patterns.defmatch(Bootstrap.Core.Patterns.clause([Bootstrap.Core.Patterns.startsWith('Bearer '), Bootstrap.Core.Patterns.variable()],function(token,hotel) { - return null; - })); - """ - - assert_translation(ex_ast, js_code) - - ex_ast = quote do - def something("Bearer " <> token, hotel, 1) do - end - end - - - js_code = """ - const something = Bootstrap.Core.Patterns.defmatch(Bootstrap.Core.Patterns.clause([Bootstrap.Core.Patterns.startsWith('Bearer '), Bootstrap.Core.Patterns.variable(), 1],function(token,hotel) { - return null; - })); - """ - - assert_translation(ex_ast, js_code) - end - - test "combine pattern matched functions of same arity" do - ex_ast = quote do - defmodule Example do - def something(1) do - end - - def something(2) do - end - - def something(one) when is_binary(one) do - end - - def something(one) do - end - end - - end - - - js_code = """ - const something = Bootstrap.Core.Patterns.defmatch(Bootstrap.Core.Patterns.clause([1],function() { - return null; - }),Bootstrap.Core.Patterns.clause([2],function() { - return null; - }),Bootstrap.Core.Patterns.clause([Bootstrap.Core.Patterns.variable()],function(one) { - return null; - },function(one) { - return Elixir.ElixirScript.Kernel.__load(Elixir).is_binary(one); - }),Bootstrap.Core.Patterns.clause([Bootstrap.Core.Patterns.variable()],function(one) { - return null; - })); - """ - - assert_translation(ex_ast, js_code) - - end - - test "translate varible declaration correctly" do - ex_ast = quote do - def test1(alpha, beta) do - a = 1 - a = 2 - end - end - - js_code = """ - const test1 = Bootstrap.Core.Patterns.defmatch(Bootstrap.Core.Patterns.clause([Bootstrap.Core.Patterns.variable(), Bootstrap.Core.Patterns.variable()],function(alpha,beta) { - let [a] = Bootstrap.Core.Patterns.match(Bootstrap.Core.Patterns.variable(),1); - let [a1] = Bootstrap.Core.Patterns.match(Bootstrap.Core.Patterns.variable(),2); - return a1; - })); - """ - - assert_translation(ex_ast, js_code) - - ex_ast = quote do - def test1(alpha, beta) do - a = 1 - a = a - a = 2 - end - end - - js_code = """ - const test1 = Bootstrap.Core.Patterns.defmatch(Bootstrap.Core.Patterns.clause([Bootstrap.Core.Patterns.variable(), Bootstrap.Core.Patterns.variable()],function(alpha,beta) { - let [a] = Bootstrap.Core.Patterns.match(Bootstrap.Core.Patterns.variable(),1); - let [a1] = Bootstrap.Core.Patterns.match(Bootstrap.Core.Patterns.variable(),a); - let [a2] = Bootstrap.Core.Patterns.match(Bootstrap.Core.Patterns.variable(),2); - return a2; - })); - """ - - assert_translation(ex_ast, js_code) - - ex_ast = quote do - def test1(alpha, beta) do - a = 1 - [a, b, c] = [a, 2, 3] - end - end - - js_code = """ - const test1 = Bootstrap.Core.Patterns.defmatch(Bootstrap.Core.Patterns.clause([Bootstrap.Core.Patterns.variable(), Bootstrap.Core.Patterns.variable()],function(alpha,beta) { - let [a] = Bootstrap.Core.Patterns.match(Bootstrap.Core.Patterns.variable(),1); - let [a1,b,c] = Bootstrap.Core.Patterns.match(Object.freeze([Bootstrap.Core.Patterns.variable(), Bootstrap.Core.Patterns.variable(), Bootstrap.Core.Patterns.variable()]),Object.freeze([a, 2, 3])); - let _ref = Object.freeze([a1, b, c]); - return _ref; - })); - """ - - assert_translation(ex_ast, js_code) - end - - test "translate function variables with ? or !" do - ex_ast = quote do - def test1(alpha?, beta!) do - a? = 1 - b! = 2 - end - end - - js_code = """ - const test1 = Bootstrap.Core.Patterns.defmatch(Bootstrap.Core.Patterns.clause([Bootstrap.Core.Patterns.variable(), Bootstrap.Core.Patterns.variable()],function(alpha__qmark__,beta__emark__) { - let [a__qmark__] = Bootstrap.Core.Patterns.match(Bootstrap.Core.Patterns.variable(),1); - let [b__emark__] = Bootstrap.Core.Patterns.match(Bootstrap.Core.Patterns.variable(),2); - return b__emark__; - })); - """ - - assert_translation(ex_ast, js_code) - end - - test "translate function params with defaults" do - ex_ast = quote do - def test1(alpha, beta \\ 0) do - end - end - - js_code = """ - const test1 = Bootstrap.Core.Patterns.defmatch(Bootstrap.Core.Patterns.clause([Bootstrap.Core.Patterns.variable(), Bootstrap.Core.Patterns.variable(0)],function(alpha,beta) { - return null; - })); - """ - - assert_translation(ex_ast, js_code) - - ex_ast = quote do - def test1(alpha \\ fn x -> x end) do - end - end - - js_code = """ - const test1 = Bootstrap.Core.Patterns.defmatch(Bootstrap.Core.Patterns.clause([Bootstrap.Core.Patterns.variable(Bootstrap.Core.Patterns.defmatch(Bootstrap.Core.Patterns.clause([Bootstrap.Core.Patterns.variable()],function(x) { - return x; - })))], - function(alpha) { - return null; - })); - """ - - assert_translation(ex_ast, js_code) - end - - test "def with catch" do - ex_ast = quote do - defp func(param) do - if true do - nil - else - :error - end - catch - :invalid -> :error - end - end - - js_code = """ - const func = Bootstrap.Core.Patterns.defmatch(Bootstrap.Core.Patterns.clause([Bootstrap.Core.Patterns.variable()], - function(param) { - return Bootstrap.Core.SpecialForms._try(function() { - return Bootstrap.Core.Patterns.defmatch(Bootstrap.Core.Patterns.clause([Bootstrap.Core.Patterns.variable()], function(x) { - return Symbol.for('error'); - }, - function(x) { - return x === null || x === false; - }), - Bootstrap.Core.Patterns.clause([Bootstrap.Core.Patterns.variable()], function(__ignored__) { - return null; - })).call(this, true); - }, - null, - Bootstrap.Core.Patterns.defmatch(Bootstrap.Core.Patterns.clause([Symbol.for('invalid')], function() { - return Symbol.for('error'); - })), - null, - null - ); - })); - """ - - assert_translation(ex_ast, js_code) - end - - - test "translate anonymous function with variable bound" do - ex_ast = quote do - key = "test" - fn ^key -> :ok end - end - - js_code = """ - let [key] = Bootstrap.Core.Patterns.match(Bootstrap.Core.Patterns.variable(),'test'); - - Bootstrap.Core.Patterns.defmatch( - Bootstrap.Core.Patterns.clause( - [Bootstrap.Core.Patterns.bound(key)], - function() { - return Symbol.for('ok'); - } - ) - ) - """ - - assert_translation(ex_ast, js_code) - end - - test "multiple when guards" do - ex_ast = quote do - def something(one) when is_number(one) when is_atom(one) do - end - end - - - js_code = """ - const something = Bootstrap.Core.Patterns.defmatch(Bootstrap.Core.Patterns.clause([Bootstrap.Core.Patterns.variable()],function(one) { - return null; - },function(one) { - return Elixir.ElixirScript.Kernel.__load(Elixir).is_number(one) || Elixir.ElixirScript.Kernel.__load(Elixir).is_atom(one); - })); - """ - - assert_translation(ex_ast, js_code) - end -end diff --git a/test/translator/js_test.exs b/test/translator/js_test.exs deleted file mode 100644 index 7dde65f2..00000000 --- a/test/translator/js_test.exs +++ /dev/null @@ -1,55 +0,0 @@ -defmodule ElixirScript.Translator.JS.Test do - use ExUnit.Case - import ElixirScript.TestHelper - - - test "translate global function calls" do - ex_ast = quote do: JS.alert("hi") - js_code = "Bootstrap.Core.global.alert('hi')" - - assert_translation(ex_ast, js_code) - - ex_ast = quote do: JS.back() - js_code = "Bootstrap.Core.Functions.call_property(Bootstrap.Core.global, 'back')" - - assert_translation(ex_ast, js_code) - end - - test "translate global properties" do - ex_ast = quote do: JS.length - js_code = "Bootstrap.Core.Functions.call_property(Bootstrap.Core.global, 'length')" - - assert_translation(ex_ast, js_code) - end - - test "translate global module" do - ex_ast = quote do: JS.String.toString() - js_code = "Bootstrap.Core.Functions.call_property(Bootstrap.Core.global.String, 'toString')" - - assert_translation(ex_ast, js_code) - - ex_ast = quote do: JS.String.raw("hi") - js_code = "Bootstrap.Core.global.String.raw('hi')" - - assert_translation(ex_ast, js_code) - - ex_ast = quote do: JS.Something.Other.raw("hi") - js_code = "Bootstrap.Core.global.Something.Other.raw('hi')" - - assert_translation(ex_ast, js_code) - end - - test "translate global lowercase" do - ex_ast = quote do: JS.console.log("hi") - js_code = "Bootstrap.Core.Functions.call_property(Bootstrap.Core.global, 'console').log('hi')" - - assert_translation(ex_ast, js_code) - - ex_ast = quote do: JS.window.length - js_code = "Bootstrap.Core.Functions.call_property(Bootstrap.Core.Functions.call_property(Bootstrap.Core.global, 'window'), 'length')" - - assert_translation(ex_ast, js_code) - end - - -end diff --git a/test/translator/kernel_test.exs b/test/translator/kernel_test.exs deleted file mode 100644 index 2438c7f3..00000000 --- a/test/translator/kernel_test.exs +++ /dev/null @@ -1,89 +0,0 @@ -defmodule ElixirScript.Translator.Kernel.Test do - use ExUnit.Case - import ElixirScript.TestHelper - - test "raise with bitstring" do - ex_ast = quote do - def execute() do - list = [] - raise ArgumentError, "cannot convert list to string. The list must contain only integers, strings or nested such lists; got: #{inspect list}" - end - end - - js_code = """ - throw Elixir.ElixirScript.ArgumentError.__load(Elixir).__struct__(Object.freeze({ - [Symbol.for('message')]: 'cannot convert list to string. The list must contain only integers, strings or nested such lists; got: ' + Elixir.ElixirScript.String.Chars.__load(Elixir).to_string(inspect(list)) - })); - """ - - assert_translation(ex_ast, js_code) - end - - test "raise with string" do - ex_ast = quote do - def execute() do - raise ArgumentError, "cannot convert list to string. The list must contain only integers, strings or nested such lists; got" - end - end - - js_code = """ - throw Elixir.ElixirScript.ArgumentError.__load(Elixir).__struct__(Object.freeze({ - [Symbol.for('message')]: 'cannot convert list to string. The list must contain only integers, strings or nested such lists; got' - })); - """ - - assert_translation(ex_ast, js_code) - end - - test "max" do - ex_ast = quote do - max(1, 2) - end - - js_code = """ - Elixir.ElixirScript.Kernel.__load(Elixir).max(1, 2) - """ - - assert_translation(ex_ast, js_code) - - end - - test "apply/3" do - ex_ast = quote do - apply(Enum, :reverse, [[1, 2, 3]]) - end - - js_code = """ - Elixir.ElixirScript.Kernel.__load(Elixir).apply(Elixir.ElixirScript.Enum, Symbol.for('reverse'), Object.freeze([Object.freeze([1, 2, 3])])) - """ - - assert_translation(ex_ast, js_code) - - end - - test "hd" do - ex_ast = quote do - hd([1, 2, 3]) - end - - js_code = """ - Elixir.ElixirScript.Kernel.__load(Elixir).hd(Object.freeze([1, 2, 3])) - """ - - assert_translation(ex_ast, js_code) - - end - - test "tl" do - ex_ast = quote do - tl([1, 2, 3]) - end - - js_code = """ - Elixir.ElixirScript.Kernel.__load(Elixir).tl(Object.freeze([1, 2, 3])) - """ - - assert_translation(ex_ast, js_code) - - end -end diff --git a/test/translator/list_test.exs b/test/translator/list_test.exs deleted file mode 100644 index 39384bfe..00000000 --- a/test/translator/list_test.exs +++ /dev/null @@ -1,70 +0,0 @@ -defmodule ElixirScript.Translator.List.Test do - use ExUnit.Case - import ElixirScript.TestHelper - - test "translate list" do - ex_ast = quote do: [1, 2, 3] - js_code = "Object.freeze([1, 2, 3])" - - assert_translation(ex_ast, js_code) - - ex_ast = quote do: ["a", "b", "c"] - js_code = "Object.freeze(['a', 'b', 'c'])" - - assert_translation(ex_ast, js_code) - - ex_ast = quote do: [:a, :b, :c] - js_code = "Object.freeze([Symbol.for('a'), Symbol.for('b'), Symbol.for('c')])" - - assert_translation(ex_ast, js_code) - - ex_ast = quote do: [:a, 2, "c"] - js_code = "Object.freeze([Symbol.for('a'), 2, 'c'])" - - assert_translation(ex_ast, js_code) - end - - test "concatenate lists" do - ex_ast = quote do: [1, 2, 3] ++ [4, 5, 6] - js_code = "Object.freeze([1, 2, 3]).concat(Object.freeze([4, 5, 6]))" - - assert_translation(ex_ast, js_code) - - ex_ast = quote do - list = [] - list ++ [4, 5, 6] - end - js_code = "list.concat(Object.freeze([4, 5, 6]))" - - assert_translation(ex_ast, js_code) - end - - test "prepend element" do - ex_ast = quote do - x = 1 - list = [] - [x | list] - end - - js_code = "Object.freeze([x]).concat(list)" - - assert_translation(ex_ast, js_code) - end - - test "prepend element in function" do - ex_ast = quote do - x = 1 - list = [] - - fn (_) -> [x|list] end - end - - js_code = """ - Bootstrap.Core.Patterns.defmatch(Bootstrap.Core.Patterns.clause([Bootstrap.Core.Patterns.variable()],function(__ignored__){ - return Object.freeze([x]).concat(list); - })) - """ - - assert_translation(ex_ast, js_code) - end -end diff --git a/test/translator/map_test.exs b/test/translator/map_test.exs deleted file mode 100644 index 8c49fcb6..00000000 --- a/test/translator/map_test.exs +++ /dev/null @@ -1,87 +0,0 @@ -defmodule ElixirScript.Translator.Map.Test do - use ExUnit.Case - import ElixirScript.TestHelper - - test "translate empty map" do - ex_ast = quote do: %{} - js_code = "Object.freeze({})" - - assert_translation(ex_ast, js_code) - end - - test "translate map with elements" do - ex_ast = quote do: %{one: "one", two: "two"} - js_code = "Object.freeze({[Symbol.for('one')]: 'one', [Symbol.for('two')]: 'two'})" - - assert_translation(ex_ast, js_code) - end - - test "translate map within map" do - ex_ast = quote do: %{one: "one", two: %{three: "three"}} - js_code = """ - Object.freeze({ - [Symbol.for('one')]: 'one', - [Symbol.for('two')]: Object.freeze({ - [Symbol.for('three')]: 'three' - }) - }) - """ - - assert_translation(ex_ast, js_code) - end - - test "translate map with string keys" do - ex_ast = quote do: %{"one" => "one", "two" => "two"} - js_code = """ - Object.freeze({ - one: 'one', two: 'two' - }) - """ - - assert_translation(ex_ast, js_code) - end - - - test "translate map update" do - ex_ast = quote do - map = %{value: 2} - %{ map | value: 1 } - end - - js_code = """ - Object.freeze(Object.assign({}, map, Object.freeze({ - [Symbol.for('value')]: 1 - }))) - """ - - assert_translation(ex_ast, js_code) - end - - test "translate variable key" do - ex_ast = quote do - key = 1 - value = 2 - %{key => value} - end - - js_code = "Object.freeze({ [key]: value })" - assert_translation(ex_ast, js_code) - end - - test "translate bound map key" do - ex_ast = quote do - key = 1 - value = 2 - %{^key => value} = %{key => value} - end - js_code = """ - let [value1] = Bootstrap.Core.Patterns.match({ - [key]: Bootstrap.Core.Patterns.variable() - }, Object.freeze({ - [key]: value - })); - """ - assert_translation(ex_ast, js_code) - end - -end diff --git a/test/translator/match_test.exs b/test/translator/match_test.exs deleted file mode 100644 index 639738f6..00000000 --- a/test/translator/match_test.exs +++ /dev/null @@ -1,84 +0,0 @@ -defmodule ElixirScript.Translator.Match.Test do - use ExUnit.Case - import ElixirScript.TestHelper - - test "translate simple match" do - ex_ast = quote do: a = 1 - js_code = "let [a] = Bootstrap.Core.Patterns.match(Bootstrap.Core.Patterns.variable(), 1);" - - assert_translation(ex_ast, js_code) - - ex_ast = quote do: a = :atom - js_code = "let [a] = Bootstrap.Core.Patterns.match(Bootstrap.Core.Patterns.variable(), Symbol.for('atom'));" - - assert_translation(ex_ast, js_code) - end - - test "translate tuple match" do - ex_ast = quote do - {a, b} = {1, 2} - end - js_code = """ - let [a, b] = Bootstrap.Core.Patterns.match( - new Bootstrap.Core.Tuple( - Bootstrap.Core.Patterns.variable(), - Bootstrap.Core.Patterns.variable() - ), - new Bootstrap.Core.Tuple(1, 2) - ); - """ - - assert_translation(ex_ast, js_code) - - ex_ast = quote do: {a, _, c} = {1, 2, 3} - js_code = """ - let [a, __ignored__, c] = Bootstrap.Core.Patterns.match(new Bootstrap.Core.Tuple(Bootstrap.Core.Patterns.variable(), Bootstrap.Core.Patterns.variable(), Bootstrap.Core.Patterns.variable()), new Bootstrap.Core.Tuple(1, 2, 3)); - """ - - assert_translation(ex_ast, js_code) - - - ex_ast = quote do - a = 1 - {^a, _, c} = {1, 2, 3} - end - js_code = """ - let [, __ignored__, c] = Bootstrap.Core.Patterns.match(new Bootstrap.Core.Tuple(Bootstrap.Core.Patterns.bound(a), Bootstrap.Core.Patterns.variable(), Bootstrap.Core.Patterns.variable()), new Bootstrap.Core.Tuple(1, 2, 3)); - """ - - assert_translation(ex_ast, js_code) - end - - test "translate bound match" do - ex_ast = quote do - a = 1 - ^a = 1 - end - - js_code = """ - let [] = Bootstrap.Core.Patterns.match(Bootstrap.Core.Patterns.bound(a),1); - """ - - assert_translation(ex_ast, js_code) - end - - test "translate list match" do - ex_ast = quote do: [a, b] = [1, 2] - js_code = """ - let [a,b] = Bootstrap.Core.Patterns.match(Object.freeze([Bootstrap.Core.Patterns.variable(), Bootstrap.Core.Patterns.variable()]),Object.freeze([1, 2])); - let _ref = Object.freeze([a, b]); - """ - - assert_translation(ex_ast, js_code) - end - - test "translate head/tail match" do - ex_ast = quote do: [a | b] = [1, 2, 3, 4] - js_code = """ - let [a,b] = Bootstrap.Core.Patterns.match(Bootstrap.Core.Patterns.headTail(Bootstrap.Core.Patterns.variable(),Bootstrap.Core.Patterns.variable()),Object.freeze([1, 2, 3, 4])); - let _ref = Object.freeze([a, b]); - """ - - assert_translation(ex_ast, js_code) - end -end diff --git a/test/translator/nil_test.exs b/test/translator/nil_test.exs deleted file mode 100644 index 4c77bed1..00000000 --- a/test/translator/nil_test.exs +++ /dev/null @@ -1,9 +0,0 @@ -defmodule ElixirScript.Translator.Nil.Test do - use ExUnit.Case - import ElixirScript.TestHelper - - test "translate nil" do - ex_ast = quote do: nil - assert_translation(ex_ast, "null") - end -end diff --git a/test/translator/number_test.exs b/test/translator/number_test.exs deleted file mode 100644 index 6d2fe4f4..00000000 --- a/test/translator/number_test.exs +++ /dev/null @@ -1,18 +0,0 @@ -defmodule ElixirScript.Translator.Number.Test do - use ExUnit.Case - import ElixirScript.TestHelper - - test "translate numbers" do - ex_ast = quote do: 1 - assert_translation(ex_ast, "1") - - ex_ast = quote do: 1_000 - assert_translation(ex_ast, "1000") - - ex_ast = quote do: 1.1 - assert_translation(ex_ast, "1.1") - - ex_ast = quote do: -1.1 - assert_translation(ex_ast, "-1.1") - end -end diff --git a/test/translator/pattern_matching_test.exs b/test/translator/pattern_matching_test.exs deleted file mode 100644 index 75598bc6..00000000 --- a/test/translator/pattern_matching_test.exs +++ /dev/null @@ -1,257 +0,0 @@ -defmodule ElixirScript.Translator.PatternMatching.Test do - use ExUnit.Case - alias ElixirScript.Translator - alias ElixirScript.Translator.Primitive - alias ElixirScript.Translator.PatternMatching - alias ElixirScript.Translator.Map - alias ESTree.Tools.Builder, as: JS - alias ElixirScript.Translator.State - - setup do - {:ok, pid} = State.start_link(%{env: __ENV__}, []) - - State.set_module_data(pid, [{ - ElixirScript.Kernel, - %{app: :elixir, name: ElixirScript.Kernel, ast: {}, functions: []} - }]) - - scope = ElixirScript.Translator.LexicalScope.module_scope( - ElixirScript.Temp, - "temp.ex", - __ENV__, - pid, - %{ format: :es, module_formatter: ElixirScript.ModuleSystems.ES } - ) - - {:ok, [scope: scope]} - end - - test "match wildcard", %{scope: scope} do - params = [{:_, [], Test}] - result = PatternMatching.build_match(params, scope) - expected_result = {[PatternMatching.parameter()], [JS.identifier(:__ignored__)]} - - assert result == expected_result - end - - test "match one identifier param", %{scope: scope} do - params = [{:a, [], Test}] - result = PatternMatching.build_match(params, scope ) - expected_result = {[PatternMatching.parameter], [JS.identifier("a")]} - - assert result == expected_result - end - - test "match multiple identifier params", %{scope: scope} do - params = [{:a, [], Test}, {:b, [], Test}, {:c, [], Test}] - result = PatternMatching.build_match(params, scope ) - expected_result = { - List.duplicate(PatternMatching.parameter, 3), - [JS.identifier("a"), JS.identifier("b"), JS.identifier("c")] - } - - assert result == expected_result - end - - test "match head and tail param", %{scope: scope} do - params = [[{:|, [], [{:head, [], Elixir}, {:tail, [], Elixir}]}]] - result = PatternMatching.build_match(params, scope ) - expected_result = { - [PatternMatching.head_tail(PatternMatching.parameter, PatternMatching.parameter)], - [JS.identifier("head"), JS.identifier("tail")] - } - - assert result == expected_result - end - - test "match prefix param", %{scope: scope} do - params = [{:<>, [context: Elixir, import: Elixir.Kernel], ["Bearer ", {:token, [], Elixir}]}] - result = PatternMatching.build_match(params, scope ) - expected_result = { - [PatternMatching.starts_with("Bearer ")], - [JS.identifier("token")] - } - - assert result == expected_result - end - - test "match list", %{scope: scope} do - params = [[{:a, [], Elixir}, {:b, [], Elixir}, {:c, [], Elixir}]] - result = PatternMatching.build_match(params, scope ) - expected_result = { - [Primitive.make_list_no_translate(List.duplicate(PatternMatching.parameter, 3))], - [JS.identifier("a"), JS.identifier("b"), JS.identifier("c")] - } - - assert result == expected_result - end - - test "match list with a literal", %{scope: scope} do - params = [[1, {:b, [], Elixir}, {:c, [], Elixir}]] - result = PatternMatching.build_match(params, scope ) - expected_result = { - [Primitive.make_list_no_translate([JS.literal(1), PatternMatching.parameter, PatternMatching.parameter])], - [JS.identifier("b"), JS.identifier("c")] - } - - assert result == expected_result - end - - test "match number", %{scope: scope} do - params = [1] - result = PatternMatching.build_match(params, scope ) - expected_result = { - [JS.literal(1)], - [] - } - - assert result == expected_result - end - - test "match struct pattern", %{scope: scope} do - params = [{:%, [], [{:__aliases__, [alias: false], [:Hello]}, {:%{}, [], []}]}] - result = PatternMatching.build_match(params, scope ) - expected_result = { - [JS.object_expression([ - JS.property(Primitive.make_atom(:__struct__), - Primitive.make_atom(Hello), - :init, false, false, true), - ])], - [] - } - - assert result == expected_result - end - - test "match struct pattern with property", %{scope: scope} do - params = [{:%, [], [{:__aliases__, [alias: false], [:Hello]}, {:%{}, [], [key: 1]}]}] - result = PatternMatching.build_match(params, scope ) - expected_result = { - [JS.object_expression([ - JS.property(Primitive.make_atom(:__struct__), - Primitive.make_atom(Hello), - :init, false, false, true), - Map.make_property(Translator.translate!(:key, scope ), Translator.translate!(1, scope)) - ])], - [] - } - - assert result == expected_result - end - - test "match struct pattern with property param", %{scope: scope} do - params = [{:%, [], [{:__aliases__, [alias: false], [:Hello]}, {:%{}, [], [key: {:key, [], Elixir}]}]}] - result = PatternMatching.build_match(params, scope ) - expected_result = { - [JS.object_expression([ - JS.property(Primitive.make_atom(:__struct__), - Primitive.make_atom(Hello), - :init, false, false, true), - Map.make_property(Translator.translate!(:key, scope ), PatternMatching.parameter()) - ])], - [JS.identifier("key")] - } - - assert result == expected_result - end - - test "capture parameter when assigning it", %{scope: scope} do - params = [{:=, [], [1, {:a, [], Elixir}]}] - result = PatternMatching.build_match(params, scope ) - expected_result = { - [PatternMatching.capture(JS.literal(1))], - [JS.identifier("a")] - } - - assert result == expected_result - - - params = [{:=, [], [{:a, [], Elixir}, 1]}] - result = PatternMatching.build_match(params, scope ) - expected_result = { - [PatternMatching.capture(JS.literal(1))], - [JS.identifier("a")] - } - - assert result == expected_result - - - params = [{:=, [], [{:%, [], [{:__aliases__, [alias: false], [:AStruct]}, {:%{}, [], []}]}, {:a, [], ElixirScript.Translator.Function.Test}]}] - result = PatternMatching.build_match(params, scope ) - expected_result = { - [PatternMatching.capture(JS.object_expression([ - JS.property(Primitive.make_atom(:__struct__), - Primitive.make_atom(AStruct), - :init, false, false, true), - ]))], - [JS.identifier("a")] - } - - assert result == expected_result - end - - test "match and assign list", %{scope: scope} do - params = [{:=, [], [[{:a, [], Elixir}, {:b, [], Elixir}, {:c, [], Elixir}], {:d, [], Elixir}]}] - result = PatternMatching.build_match(params, scope ) - expected_result = { - [PatternMatching.capture(Primitive.make_list_no_translate([PatternMatching.parameter, PatternMatching.parameter, PatternMatching.parameter]))], - [JS.identifier("a"), JS.identifier("b"), JS.identifier("c"), JS.identifier("d")] - } - - assert result == expected_result - end - - test "match on tuple", %{scope: scope} do - params = [{:{}, [], [1, {:b, [], Elixir}, 3]}] - result = PatternMatching.build_match(params, scope ) - expected_result = { - [JS.new_expression( - Primitive.tuple_class(), - [JS.literal(1), PatternMatching.parameter, JS.literal(3)] - )], - [JS.identifier("b")] - } - - assert result == expected_result - - params = [{1, {:b, [], Elixir}}] - result = PatternMatching.build_match(params, scope ) - expected_result = { - [JS.new_expression( - Primitive.tuple_class(), - [JS.literal(1), PatternMatching.parameter] - )], - [JS.identifier("b")] - } - - assert result == expected_result - end - - test "match on map", %{scope: scope} do - params = [{:%{}, [], [which: 13]}] - result = PatternMatching.build_match(params, scope ) - - expected_result = { - [JS.object_expression([ - Map.make_property(Translator.translate!(:which, scope ), JS.literal(13)) - ])], - [] - } - - assert result == expected_result - end - - - test "match on bound value", %{scope: scope} do - params = [{:^, [], [{:a, [], Elixir}]}] - result = PatternMatching.build_match(params, scope ) - - expected_result = { - [PatternMatching.bound(JS.identifier("a"))], - [nil] - } - - assert result == expected_result - end - -end diff --git a/test/translator/quote_test.exs b/test/translator/quote_test.exs deleted file mode 100644 index 2728ea69..00000000 --- a/test/translator/quote_test.exs +++ /dev/null @@ -1,142 +0,0 @@ -defmodule ElixirScript.Translator.Quote.Test do - use ExUnit.Case - import ElixirScript.TestHelper - - test "quote number" do - ex_ast = quote do - quote do: 1 - end - - js_code = "1" - - assert_translation(ex_ast, js_code) - end - - test "quote atom" do - ex_ast = quote do - quote do: :time - end - - js_code = "Symbol.for('time')" - - assert_translation(ex_ast, js_code) - end - - - test "quote 2 element tuple" do - ex_ast = quote do - quote do: {1, 2} - end - - js_code = "new Bootstrap.Core.Tuple(1, 2)" - - assert_translation(ex_ast, js_code) - end - - - test "quote 3 element tuple" do - ex_ast = quote do - quote do: {1, 2, 3} - end - - js_code = "new Bootstrap.Core.Tuple(Symbol.for('{}'), Object.freeze([]), Object.freeze([1, 2, 3]))" - - assert_translation(ex_ast, js_code) - end - - - test "quote function call" do - ex_ast = quote do - quote do: test(1) - end - - js_code = """ - new Bootstrap.Core.Tuple( - Symbol.for('test'), - Object.freeze([new Bootstrap.Core.Tuple(Symbol.for('context'),Symbol.for('Elixir.ElixirScript.Translator.Quote.Test')), new Bootstrap.Core.Tuple(Symbol.for('import'),Symbol.for('Elixir.ExUnit.Case'))]),Object.freeze([1]) - ) - """ - - assert_translation(ex_ast, js_code) - end - - - test "quote function with variable" do - ex_ast = quote do - quote do: test(x) - end - - js_code = """ - new Bootstrap.Core.Tuple( - Symbol.for('test'), - Object.freeze([new Bootstrap.Core.Tuple(Symbol.for('context'), Symbol.for('Elixir.ElixirScript.Translator.Quote.Test')), new Bootstrap.Core.Tuple(Symbol.for('import'),Symbol.for('Elixir.ExUnit.Case'))]),Object.freeze([new Bootstrap.Core.Tuple(Symbol.for('x'),Object.freeze([]),Symbol.for('Elixir.ElixirScript.Translator.Quote.Test'))])) - """ - - assert_translation(ex_ast, js_code) - end - - - test "quote function call with unquote" do - ex_ast = quote do - x = 1 - quote do: test(unquote(x)) - end - - js_code = """ - new Bootstrap.Core.Tuple( - Symbol.for('test'), - Object.freeze([new Bootstrap.Core.Tuple(Symbol.for('context'),Symbol.for('Elixir.ElixirScript.Translator.Quote.Test')), new Bootstrap.Core.Tuple(Symbol.for('import'),Symbol.for('Elixir.ExUnit.Case'))]),Object.freeze([x]) - ) - """ - - assert_translation(ex_ast, js_code) - end - - - test "quote function call with unquote_slicing" do - ex_ast = quote do - quote do: sum(1, unquote_splicing([1, 2, 3]), 5) - end - - js_code = """ - new Bootstrap.Core.Tuple(Symbol.for('sum'), Object.freeze([]), Bootstrap.Enum.concat(Object.freeze([1]), Object.freeze([1, 2, 3]), Object.freeze([5]))) - """ - - assert_translation(ex_ast, js_code) - end - - test "bind_quoted" do - ex_ast = quote do - x = 1 - quote bind_quoted: [x: x] do - x * x - end - end - - js_code = """ - new Bootstrap.Core.Tuple( - Symbol.for('*'), - Object.freeze([new Bootstrap.Core.Tuple(Symbol.for('context'), Symbol.for('Elixir.ElixirScript.Translator.Quote.Test')), new Bootstrap.Core.Tuple(Symbol.for('import'),Symbol.for('Elixir.ElixirScript.Kernel'))]),Object.freeze([x, x]) - ) - """ - - assert_translation(ex_ast, js_code) - end - - test "quote with context option" do - ex_ast = quote do - quote context: Elixir do - test(1) - end - end - - js_code = """ - new Bootstrap.Core.Tuple( - Symbol.for('test'), - Object.freeze([new Bootstrap.Core.Tuple(Symbol.for('context'),Symbol.for('Elixir')), new Bootstrap.Core.Tuple(Symbol.for('import'),Symbol.for('Elixir.ExUnit.Case'))]),Object.freeze([1]) - ) - """ - - assert_translation(ex_ast, js_code) - end -end diff --git a/test/translator/string_test.exs b/test/translator/string_test.exs deleted file mode 100644 index 3eb79606..00000000 --- a/test/translator/string_test.exs +++ /dev/null @@ -1,43 +0,0 @@ -defmodule ElixirScript.Translator.String.Test do - use ExUnit.Case - import ElixirScript.TestHelper - - test "translate string" do - ex_ast = quote do: "Hello" - assert_translation(ex_ast, "'Hello'") - end - - test "translate multiline string" do - ex_ast = quote do: """ - Hello - This is another line - """ - assert_translation(ex_ast, "'Hello\\nThis is another line\\n'") - end - - test "translate string concatenation" do - ex_ast = quote do: "Hello" <> "World" - assert_translation(ex_ast, "'Hello' + 'World'") - end - - test "translate string interpolation" do - ex_ast = quote do: "Hello #{"world"}" - assert_translation(ex_ast, "'Hello ' + Elixir.ElixirScript.String.Chars.__load(Elixir).to_string('world')") - - ex_ast = quote do: "Hello #{length([])}" - assert_translation(ex_ast, "'Hello ' + Elixir.ElixirScript.String.Chars.__load(Elixir).to_string(Elixir.ElixirScript.Kernel.__load(Elixir).length(Object.freeze([])))") - end - - test "translate multiline string interpolation" do - ex_ast = quote do: """ - Hello #{length([])} - """ - assert_translation(ex_ast, "'Hello ' + (Elixir.ElixirScript.String.Chars.__load(Elixir).to_string(Elixir.ElixirScript.Kernel.__load(Elixir).length(Object.freeze([]))) + '\\n')") - - ex_ast = quote do: """ - Hello #{length([])} - How are you, #{length([])}? - """ - assert_translation(ex_ast, "'Hello ' + (Elixir.ElixirScript.String.Chars.__load(Elixir).to_string(Elixir.ElixirScript.Kernel.__load(Elixir).length(Object.freeze([]))) + ('\\nHow are you, ' + (Elixir.ElixirScript.String.Chars.__load(Elixir).to_string(Elixir.ElixirScript.Kernel.__load(Elixir).length(Object.freeze([]))) + '?\\n')))") - end -end diff --git a/test/translator/struct_test.exs b/test/translator/struct_test.exs deleted file mode 100644 index b562a050..00000000 --- a/test/translator/struct_test.exs +++ /dev/null @@ -1,233 +0,0 @@ -defmodule ElixirScript.Translator.Struct.Test do - use ExUnit.Case - import ElixirScript.TestHelper - - test "translate struct with default values" do - ex_ast = quote do - defmodule User do - defstruct name: "john", age: 27 - end - end - - js_code = """ - const __struct__ = function(values = {}) { - const allowed_keys = [Symbol.for('name'), Symbol.for('age')] - - const value_keys = Object.keys(values) - - const every_call_result = value_keys.every(function(key) { - return allowed_keys.includes(key); - }) - - if (every_call_result) { - return Object.assign({}, { - [Symbol.for('__struct__')]: Symbol.for('Elixir.User'), - [Symbol.for('name')]: 'john', - [Symbol.for('age')]: 27 - }, values); - } else { - throw 'Unallowed key found'; - } - }; - """ - - assert_translation(ex_ast, js_code) - end - - test "translate struct without default values" do - - ex_ast = quote do - defmodule User do - defstruct [:name, :age] - end - end - - js_code = """ - const __struct__ = function(values = {}) { - const allowed_keys = [Symbol.for('name'), Symbol.for('age')] - - const value_keys = Object.keys(values) - - const every_call_result = value_keys.every(function(key) { - return allowed_keys.includes(key); - }) - - if (every_call_result) { - return Object.assign({}, { - [Symbol.for('__struct__')]: Symbol.for('Elixir.User'), - [Symbol.for('name')]: null, - [Symbol.for('age')]: null - }, values); - } else { - throw 'Unallowed key found'; - } - }; - """ - - assert_translation(ex_ast, js_code) - - end - - test "translate struct creation" do - ex_ast = quote do - defmodule User do - defstruct [:name, :age] - end - - user = %User{} - end - - js_code = """ - Elixir.User.__load(Elixir).__struct__(Object.freeze({}) - """ - - assert_translation(ex_ast, js_code) - - ex_ast = quote do - defmodule User do - defstruct [:name, :age] - end - - user = %User{name: "John"} - end - - js_code = """ - Elixir.User.__load(Elixir).__struct__(Object.freeze({[Symbol.for('name')]: 'John'}) - """ - - assert_translation(ex_ast, js_code) - end - - test "translate struct update" do - ex_ast = quote do - map = %{key: nil} - user = %{ map | key: 1 } - end - - js_code = """ - let [user] = Bootstrap.Core.Patterns.match(Bootstrap.Core.Patterns.variable(), Object.freeze(Object.assign({}, map, Object.freeze({ - [Symbol.for('key')]: 1 - })))); - """ - - assert_translation(ex_ast, js_code) - - - ex_ast = quote do - map = %{key: nil, key1: nil} - user = %{ map | key: 1, key1: 11 } - end - - js_code = """ - let [user] = Bootstrap.Core.Patterns.match(Bootstrap.Core.Patterns.variable(), Object.freeze(Object.assign({}, map, Object.freeze({ - [Symbol.for('key')]: 1, - [Symbol.for('key1')]: 11 - })))); - """ - - assert_translation(ex_ast, js_code) - end - - test "translate defexception" do - ex_ast = quote do - defmodule MyAppError do - defexception message: "This is a message" - end - end - - js_code = """ - const __struct__ = function(values = {}) { - const allowed_keys = [Symbol.for('message'), Symbol.for('__exception__')] - - const value_keys = Object.keys(values) - - const every_call_result = value_keys.every(function(key) { - return allowed_keys.includes(key); - }) - - if (every_call_result) { - return Object.assign({}, { - [Symbol.for('__struct__')]: Symbol.for('Elixir.MyAppError'), - [Symbol.for('message')]: 'This is a message', - [Symbol.for('__exception__')]: true - }, values); - } else { - throw 'Unallowed key found'; - } - }; - """ - - assert_translation(ex_ast, js_code) - - ex_ast = quote do - defmodule MyAppError do - defexception [:message] - end - end - - js_code = """ - const __struct__ = function(values = {}) { - const allowed_keys = [Symbol.for('message'), Symbol.for('__exception__')] - - const value_keys = Object.keys(values) - - const every_call_result = value_keys.every(function(key) { - return allowed_keys.includes(key); - }) - - if (every_call_result) { - return Object.assign({}, { - [Symbol.for('__struct__')]: Symbol.for('Elixir.MyAppError'), - [Symbol.for('message')]: null, - [Symbol.for('__exception__')]: true - }, values); - } else { - throw 'Unallowed key found'; - } - }; - """ - - assert_translation(ex_ast, js_code) - - end - - test "translate raise exception" do - ex_ast = quote do - defmodule MyAppError do - defexception [:message] - - def do_it() do - raise MyAppError, message: "did not get what was expected" - end - - end - end - - js_code = """ - throw Elixir.MyAppError.__load(Elixir).__struct__(Object.freeze({ - [Symbol.for('message')]: 'did not get what was expected' - })); - """ - - assert_translation(ex_ast, js_code) - - - ex_ast = quote do - def do_it() do - raise "did not get what was expected" - end - - end - - js_code = """ - throw { - [Symbol.for('__struct__')]: Symbol.for('RuntimeError'), - [Symbol.for('__exception__')]: true, - [Symbol.for('message')]: 'did not get what was expected' - }; - """ - - assert_translation(ex_ast, js_code) - - end -end diff --git a/test/translator/try_test.exs b/test/translator/try_test.exs deleted file mode 100644 index f8728b61..00000000 --- a/test/translator/try_test.exs +++ /dev/null @@ -1,231 +0,0 @@ -defmodule ElixirScript.Translator.Try.Test do - use ExUnit.Case - import ElixirScript.TestHelper - - test "translate with a rescue with one match" do - ex_ast = quote do - try do - 1 - rescue - ArgumentError -> - IO.puts "Invalid argument given" - end - end - - js_code = """ - Bootstrap.Core.SpecialForms._try(function() { - return 1; - }, Bootstrap.Core.Patterns.defmatch(Bootstrap.Core.Patterns.clause([{ - [Symbol.for('__struct__')]: Symbol.for('Elixir.ElixirScript.ArgumentError') - }], function() { - return Elixir.ElixirScript.IO.__load(Elixir).puts('Invalid argument given'); - })), null, null, null) - """ - - assert_translation(ex_ast, js_code) - end - - test "translate with a rescue with a list match" do - ex_ast = quote do - - try do - 1 - rescue - [ArgumentError] -> - IO.puts "Invalid argument given" - end - end - - js_code = """ - Bootstrap.Core.SpecialForms._try(function() { - return 1; - }, Bootstrap.Core.Patterns.defmatch(Bootstrap.Core.Patterns.clause([{ - [Symbol.for('__struct__')]: Symbol.for('Elixir.ElixirScript.ArgumentError') - }], function() { - return Elixir.ElixirScript.IO.__load(Elixir).puts('Invalid argument given'); - })), null, null, null) - """ - - assert_translation(ex_ast, js_code) - end - - test "translate with a rescue with an in guard" do - ex_ast = quote do - - try do - 1 - rescue - x in [ArgumentError] -> - IO.puts "Invalid argument given" - end - end - - js_code = """ - Bootstrap.Core.SpecialForms._try(function() { - return 1; - },Bootstrap.Core.Patterns.defmatch(Bootstrap.Core.Patterns.clause([Bootstrap.Core.Patterns.variable()],function(x) { - return Elixir.ElixirScript.IO.__load(Elixir).puts('Invalid argument given'); - },function(x) { - return Elixir.ElixirScript.Bootstrap.Functions.__load(Elixir).contains(x, Object.freeze([Elixir.ElixirScript.ArgumentError.__load(Elixir).__struct__(Object.freeze({}))])); - })),null,null,null) - """ - - assert_translation(ex_ast, js_code) - end - - test "translate with a rescue with an identifier" do - ex_ast = quote do - - try do - 1 - rescue - x -> - IO.puts "Invalid argument given" - end - end - - js_code = """ - Bootstrap.Core.SpecialForms._try(function() { - return 1; - },Bootstrap.Core.Patterns.defmatch(Bootstrap.Core.Patterns.clause([Bootstrap.Core.Patterns.variable()],function(x) { - return Elixir.ElixirScript.IO.__load(Elixir).puts('Invalid argument given'); - })),null,null,null) - """ - - assert_translation(ex_ast, js_code) - end - - - test "translate with a rescue with multiple patterns" do - ex_ast = quote do - - try do - 1 - rescue - [ArgumentError] -> - IO.puts "ArgumentError" - x -> - IO.puts "x" - end - end - - js_code = """ - Bootstrap.Core.SpecialForms._try(function() { - return 1; - }, Bootstrap.Core.Patterns.defmatch(Bootstrap.Core.Patterns.clause([{ - [Symbol.for('__struct__')]: Symbol.for('Elixir.ElixirScript.ArgumentError') - }], function() { - return Elixir.ElixirScript.IO.__load(Elixir).puts('ArgumentError'); - }), Bootstrap.Core.Patterns.clause([Bootstrap.Core.Patterns.variable()], function(x) { - return Elixir.ElixirScript.IO.__load(Elixir).puts('x'); - })), null, null, null) - """ - - assert_translation(ex_ast, js_code) - end - - test "translate with a rescue and after clause" do - ex_ast = quote do - - try do - 1 - rescue - ArgumentError -> - IO.puts "Invalid argument given" - after - IO.puts "This is printed regardless if it failed or succeed" - end - end - - js_code = """ - Bootstrap.Core.SpecialForms._try(function() { - return 1; - }, Bootstrap.Core.Patterns.defmatch(Bootstrap.Core.Patterns.clause([{ - [Symbol.for('__struct__')]: Symbol.for('Elixir.ElixirScript.ArgumentError') - }], function() { - return Elixir.ElixirScript.IO.__load(Elixir).puts('Invalid argument given'); - })), null, null, function() { - return Elixir.ElixirScript.IO.__load(Elixir).puts('This is printed regardless if it failed or succeed'); - }) - """ - - assert_translation(ex_ast, js_code) - end - - test "translate with an after clause" do - ex_ast = quote do - - try do - 1 - after - IO.puts "This is printed regardless if it failed or succeed" - end - end - - js_code = """ - Bootstrap.Core.SpecialForms._try(function() { - return 1; - },null,null,null,function() { - return Elixir.ElixirScript.IO.__load(Elixir).puts('This is printed regardless if it failed or succeed'); - }) - """ - - assert_translation(ex_ast, js_code) - end - - test "translate else" do - ex_ast = quote do - x = 1 - try do - 1 / x - else - y when y < 1 and y > -1 -> - :small - _ -> - :large - end - end - - js_code = """ - Bootstrap.Core.SpecialForms._try(function() { - return 1 / x; - }, null, null, Bootstrap.Core.Patterns.defmatch(Bootstrap.Core.Patterns.clause([Bootstrap.Core.Patterns.variable()], function(y) { - return Symbol.for('small'); - }, function(y) { - return y < 1 && y > -1; - }), Bootstrap.Core.Patterns.clause([Bootstrap.Core.Patterns.variable()], function(__ignored__) { - return Symbol.for('large'); - })), null) - """ - - assert_translation(ex_ast, js_code) - end - - test "translate catch" do - ex_ast = quote do - try do - 1 - rescue - ArgumentError -> - IO.puts "Invalid argument given" - catch - :throw, :Error -> - IO.puts "caught error" - end - end - - js_code = """ - Bootstrap.Core.SpecialForms._try(function() { - return 1; - }, Bootstrap.Core.Patterns.defmatch(Bootstrap.Core.Patterns.clause([{ - [Symbol.for('__struct__')]: Symbol.for('Elixir.ElixirScript.ArgumentError') - }], function() { - return Elixir.ElixirScript.IO.__load(Elixir).puts('Invalid argument given'); - })), Bootstrap.Core.Patterns.defmatch(Bootstrap.Core.Patterns.clause([Symbol.for('throw'), Symbol.for('Error')], function() { - return Elixir.ElixirScript.IO.__load(Elixir).puts('caught error'); - })), null, null) - """ - - assert_translation(ex_ast, js_code) - end -end diff --git a/test/translator/tuple_test.exs b/test/translator/tuple_test.exs deleted file mode 100644 index 189c1de9..00000000 --- a/test/translator/tuple_test.exs +++ /dev/null @@ -1,35 +0,0 @@ -defmodule ElixirScript.Translator.Tuple.Test do - use ExUnit.Case - import ElixirScript.TestHelper - - test "translate 2 item tuple" do - ex_ast = quote do: {1, 2} - js_code = "new Bootstrap.Core.Tuple(1, 2)" - - assert_translation(ex_ast, js_code) - end - - test "translate multiple item tuple" do - ex_ast = quote do: {1, 2, 3, 4, 5} - js_code = "new Bootstrap.Core.Tuple(1, 2, 3, 4, 5)" - - assert_translation(ex_ast, js_code) - end - - test "translate tuples of different typed items" do - ex_ast = quote do: {"a", "b", "c"} - js_code = "new Bootstrap.Core.Tuple('a', 'b', 'c')" - - assert_translation(ex_ast, js_code) - - ex_ast = quote do: {:a, :b, :c} - js_code = "new Bootstrap.Core.Tuple(Symbol.for('a'), Symbol.for('b'), Symbol.for('c'))" - - assert_translation(ex_ast, js_code) - - ex_ast = quote do: {:a, 2, "c"} - js_code = "new Bootstrap.Core.Tuple(Symbol.for('a'), 2, 'c')" - - assert_translation(ex_ast, js_code) - end -end diff --git a/test/translator/umd_test.exs b/test/translator/umd_test.exs deleted file mode 100644 index 0acd353a..00000000 --- a/test/translator/umd_test.exs +++ /dev/null @@ -1,29 +0,0 @@ -defmodule ElixirScript.Translator.UMD.Test do - use ExUnit.Case - import ElixirScript.TestHelper - - test "translate module to umd" do - ex_ast = quote do - defmodule Elephant do - @ul "#todo-list" - - def something() do - @ul - end - end - end - - js_code = """ - (function(root, factory) { - if (typeof define === 'function' && define.amd) { - define([], factory) - } else if (typeof exports === 'object') { - module.exports = factory() - } else { - root.Elixir = factory() - } - """ - - assert_translation(ex_ast, js_code, :umd) - end -end \ No newline at end of file diff --git a/test/translator/with_test.exs b/test/translator/with_test.exs deleted file mode 100644 index 58c44375..00000000 --- a/test/translator/with_test.exs +++ /dev/null @@ -1,75 +0,0 @@ -defmodule ElixirScript.Translator.With.Test do - use ExUnit.Case - import ElixirScript.TestHelper - - test "translate with" do - ex_ast = quote do - opts = %{} - with {:ok, width} <- Map.fetch(opts, :width), - {:ok, height} <- Map.fetch(opts, :height), - do: {:ok, width * height} - end - - js_code = """ - Bootstrap.Core.SpecialForms._with([new Bootstrap.Core.Tuple(Symbol.for('ok'), Bootstrap.Core.Patterns.variable()), function() { - return Elixir.ElixirScript.Map.__load(Elixir).fetch(opts, Symbol.for('width')); - }], [new Bootstrap.Core.Tuple(Symbol.for('ok'), Bootstrap.Core.Patterns.variable()), function(width) { - return Elixir.ElixirScript.Map.__load(Elixir).fetch(opts, Symbol.for('height')); - }], function(width, height) { - return new Bootstrap.Core.Tuple(Symbol.for('ok'), width * height); - }) - """ - - assert_translation(ex_ast, js_code) - end - - test "translate with with bare expression" do - ex_ast = quote do - opts = %{} - with {:ok, width} <- Map.fetch(opts, :width), - double_width = width * 2, - {:ok, height} <- Map.fetch(opts, :height), - do: {:ok, double_width * height} - end - - js_code = """ - Bootstrap.Core.SpecialForms._with([new Bootstrap.Core.Tuple(Symbol.for('ok'), Bootstrap.Core.Patterns.variable()), function() { - return Elixir.ElixirScript.Map.__load(Elixir).fetch(opts, Symbol.for('width')); - }], [Bootstrap.Core.Patterns.variable(), function(width) { - return width * 2; - }], [new Bootstrap.Core.Tuple(Symbol.for('ok'), Bootstrap.Core.Patterns.variable()), function(width, double_width) { - return Elixir.ElixirScript.Map.__load(Elixir).fetch(opts, Symbol.for('height')); - }], function(width, double_width, height) { - return new Bootstrap.Core.Tuple(Symbol.for('ok'), double_width * height); - }) - """ - - assert_translation(ex_ast, js_code) - end - - test "translate with with else" do - ex_ast = quote do - opts = %{} - with {:ok, width} <- Map.fetch(opts, :width), - {:ok, height} <- Map.fetch(opts, :height) do - {:ok, width * height} - else - :error -> {:error, :wrong_data} - end - end - - js_code = """ - Bootstrap.Core.SpecialForms._with([new Bootstrap.Core.Tuple(Symbol.for('ok'), Bootstrap.Core.Patterns.variable()), function() { - return Elixir.ElixirScript.Map.__load(Elixir).fetch(opts, Symbol.for('width')); - }], [new Bootstrap.Core.Tuple(Symbol.for('ok'), Bootstrap.Core.Patterns.variable()), function(width) { - return Elixir.ElixirScript.Map.__load(Elixir).fetch(opts, Symbol.for('height')); - }], function(width, height) { - return new Bootstrap.Core.Tuple(Symbol.for('ok'), width * height); - }, Bootstrap.Core.Patterns.defmatch(Bootstrap.Core.Patterns.clause([Symbol.for('error')], function() { - return new Bootstrap.Core.Tuple(Symbol.for('error'), Symbol.for('wrong_data')); - }))) - """ - - assert_translation(ex_ast, js_code) - end -end From 6ff7c750ac03b18db8644b9ee24afd197fcf5c47 Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Sun, 25 Jun 2017 19:52:04 -0500 Subject: [PATCH 575/860] Add more tests --- .gitignore | 1 + lib/elixir_script.ex | 1 + lib/elixir_script/cli.ex | 8 +-- lib/elixir_script/compiler.ex | 4 +- lib/elixir_script/module_systems/common.ex | 4 +- lib/elixir_script/module_systems/es.ex | 4 -- lib/elixir_script/module_systems/namespace.ex | 17 ------ lib/elixir_script/module_systems/umd.ex | 4 -- lib/elixir_script/passes/find_used_modules.ex | 2 +- lib/elixir_script/passes/output.ex | 16 +++-- lib/elixir_script/passes/translate/clause.ex | 2 +- lib/elixir_script/passes/translate/form.ex | 7 ++- .../passes/translate/forms/bitstring.ex | 2 +- .../passes/translate/forms/for.ex | 7 ++- .../passes/translate/forms/map.ex | 1 + .../passes/translate/forms/match.ex | 4 +- .../passes/translate/forms/pattern.ex | 2 +- .../translate/forms/pattern/patterns.ex | 2 + .../passes/translate/forms/remote.ex | 8 +-- .../passes/translate/forms/try.ex | 3 +- .../passes/translate/function.ex | 9 ++- lib/elixir_script/passes/translate/module.ex | 4 +- .../passes/translate/protocol.ex | 4 +- lib/elixir_script/state.ex | 7 ++- lib/elixir_script/watcher.ex | 4 +- lib/mix/tasks/compile.elixir_script.ex | 10 ++- mix.exs | 61 +++---------------- mix.lock | 21 ++++--- test/beam_test.exs | 16 ++++- test/cli_test.exs | 8 +++ test/compiler_test.exs | 49 +++++++++++++++ test/support/user.ex | 17 ------ 32 files changed, 155 insertions(+), 154 deletions(-) create mode 100644 test/cli_test.exs create mode 100644 test/compiler_test.exs delete mode 100644 test/support/user.ex diff --git a/.gitignore b/.gitignore index 9a234b19..ee4d5234 100644 --- a/.gitignore +++ b/.gitignore @@ -22,3 +22,4 @@ stdlib_state.bin .nyc_output test/app/build .vscode +cover diff --git a/lib/elixir_script.ex b/lib/elixir_script.ex index d92c6861..d69317d6 100644 --- a/lib/elixir_script.ex +++ b/lib/elixir_script.ex @@ -1,2 +1,3 @@ defmodule ElixirScript do + @moduledoc false end diff --git a/lib/elixir_script/cli.ex b/lib/elixir_script/cli.ex index ab8af630..9bd4daea 100644 --- a/lib/elixir_script/cli.ex +++ b/lib/elixir_script/cli.ex @@ -19,12 +19,6 @@ defmodule ElixirScript.CLI do f: :format ] - def main(argv) do - argv - |> parse_args - |> process - end - def parse_args(args) do { options, input, errors } = OptionParser.parse(args, switches: @switches, aliases: @aliases) @@ -43,7 +37,7 @@ defmodule ElixirScript.CLI do end - def help_message() do + defp help_message() do """ usage: elixirscript [options] the entry module of your application diff --git a/lib/elixir_script/compiler.ex b/lib/elixir_script/compiler.ex index faf38459..5dc1195d 100644 --- a/lib/elixir_script/compiler.ex +++ b/lib/elixir_script/compiler.ex @@ -28,9 +28,11 @@ defmodule ElixirScript.Compiler do IO.puts "Building Output" modules = ElixirScript.State.list_modules(pid) - ElixirScript.Output.execute(modules, pid) + result = ElixirScript.Output.execute(modules, pid) ElixirScript.State.stop(pid) + + result end defp build_compiler_options(opts, entry_modules) do diff --git a/lib/elixir_script/module_systems/common.ex b/lib/elixir_script/module_systems/common.ex index f5c01065..f4c00837 100644 --- a/lib/elixir_script/module_systems/common.ex +++ b/lib/elixir_script/module_systems/common.ex @@ -2,8 +2,7 @@ defmodule ElixirScript.ModuleSystems.Common do @moduledoc false alias ESTree.Tools.Builder, as: JS alias ElixirScript.Translator - alias ElixirScript.Translator.State - alias ElixirScript.Translator.Utils + alias ElixirScript.Translator.{State, Utils} def build(imports, js_imports, body, exports) do module_imports = Enum.map(imports, fn {module, path} -> import_module(module, path) end) @@ -11,7 +10,6 @@ defmodule ElixirScript.ModuleSystems.Common do imports = js_imports |> Enum.map(fn {module, path} -> import_module(module, path) - {module, path, _} -> import_module(module, path) end) imports = Enum.uniq(imports ++ module_imports) diff --git a/lib/elixir_script/module_systems/es.ex b/lib/elixir_script/module_systems/es.ex index 81f5bd4c..3e92049c 100644 --- a/lib/elixir_script/module_systems/es.ex +++ b/lib/elixir_script/module_systems/es.ex @@ -1,9 +1,6 @@ defmodule ElixirScript.ModuleSystems.ES do @moduledoc false alias ESTree.Tools.Builder, as: JS - alias ElixirScript.Translator - alias ElixirScript.Translator.State - alias ElixirScript.Translator.Utils def build(imports, js_imports, body, exports) do module_imports = Enum.map(imports, fn {module, path} -> import_module(module, path) end) @@ -11,7 +8,6 @@ defmodule ElixirScript.ModuleSystems.ES do imports = js_imports |> Enum.map(fn {module, path} -> import_module(module, path) - {module, path, default: true} -> import_module(module, path) {module, path, default: false} -> import_namespace_module(module, path) end) diff --git a/lib/elixir_script/module_systems/namespace.ex b/lib/elixir_script/module_systems/namespace.ex index 92caa561..200ae0c3 100644 --- a/lib/elixir_script/module_systems/namespace.ex +++ b/lib/elixir_script/module_systems/namespace.ex @@ -1,9 +1,6 @@ defmodule ElixirScript.ModuleSystems.Namespace do @moduledoc false alias ESTree.Tools.Builder, as: JS - alias ElixirScript.Translator - alias ElixirScript.Translator.State - alias ElixirScript.Translator.Utils alias ElixirScript.Translate.Identifier def build(module_name, body, exports, env) do @@ -15,20 +12,6 @@ defmodule ElixirScript.ModuleSystems.Namespace do Identifier.make_namespace_members(members) end - def import_module(module_name) do - name = ["Elixir" | Module.split(module_name) ] |> Enum.join("$") - - declarator = JS.variable_declarator( - JS.identifier(name), - JS.call_expression( - module_name_function_call(module_name, "__load"), - [JS.identifier("Elixir")] - ) - ) - - JS.variable_declaration([declarator], :const) - end - defp build_namespace() do JS.member_expression( JS.identifier("Bootstrap"), diff --git a/lib/elixir_script/module_systems/umd.ex b/lib/elixir_script/module_systems/umd.ex index c0f0d7a6..4aefe6d3 100644 --- a/lib/elixir_script/module_systems/umd.ex +++ b/lib/elixir_script/module_systems/umd.ex @@ -1,9 +1,6 @@ defmodule ElixirScript.ModuleSystems.UMD do @moduledoc false alias ESTree.Tools.Builder, as: JS - alias ElixirScript.Translator - alias ElixirScript.Translator.State - alias ElixirScript.Translator.Utils def build(imports, js_imports, body, exports) do module_imports = Enum.map(imports, fn {module, path} -> import_module(module, path) end) @@ -11,7 +8,6 @@ defmodule ElixirScript.ModuleSystems.UMD do imports = js_imports |> Enum.map(fn {module, path} -> import_module(module, path) - {module, path, _} -> import_module(module, path) end) imports = Enum.uniq(imports ++ module_imports) diff --git a/lib/elixir_script/passes/find_used_modules.ex b/lib/elixir_script/passes/find_used_modules.ex index bbb70cfd..fcdadbc0 100644 --- a/lib/elixir_script/passes/find_used_modules.ex +++ b/lib/elixir_script/passes/find_used_modules.ex @@ -21,7 +21,7 @@ defmodule ElixirScript.FindUsedModules do {:ok, module, implementations} -> walk_protocol(module, implementations, pid) {:error, error} -> - raise "An error occurred while compiling #{inspect module}: #{error}" + raise ElixirScript.CompileError, "An error occurred while compiling #{inspect module}: #{error}" end end diff --git a/lib/elixir_script/passes/output.ex b/lib/elixir_script/passes/output.ex index 9b175f90..f5804cc8 100644 --- a/lib/elixir_script/passes/output.ex +++ b/lib/elixir_script/passes/output.ex @@ -63,12 +63,7 @@ defmodule ElixirScript.Output do end defp output(code, path) do - file_name = case Path.extname(path) do - ".js" -> - path - _ -> - Path.join([path, @generated_name]) - end + file_name = get_output_file_name(path) if !File.exists?(Path.dirname(file_name)) do File.mkdir_p!(Path.dirname(file_name)) @@ -76,4 +71,13 @@ defmodule ElixirScript.Output do File.write!(file_name, code) end + + def get_output_file_name(path) do + case Path.extname(path) do + ".js" -> + path + _ -> + Path.join([path, @generated_name]) + end + end end \ No newline at end of file diff --git a/lib/elixir_script/passes/translate/clause.ex b/lib/elixir_script/passes/translate/clause.ex index 1816ab34..79512ab0 100644 --- a/lib/elixir_script/passes/translate/clause.ex +++ b/lib/elixir_script/passes/translate/clause.ex @@ -84,7 +84,7 @@ defmodule ElixirScript.Translate.Clause do return_statement = case declaration do %ESTree.ArrayPattern{elements: elements} -> - if(length(elements) == 1) do + if length(elements) == 1 do J.return_statement(hd(declaration.elements)) else J.return_statement(J.array_expression(declaration.elements)) diff --git a/lib/elixir_script/passes/translate/form.ex b/lib/elixir_script/passes/translate/form.ex index f530e8cb..662ee8be 100644 --- a/lib/elixir_script/passes/translate/form.ex +++ b/lib/elixir_script/passes/translate/form.ex @@ -2,8 +2,7 @@ defmodule ElixirScript.Translate.Form do alias ESTree.Tools.Builder, as: J alias ElixirScript.Translate.Forms.{Bitstring, Match, Try, For, Receive, Remote, Pattern} alias ElixirScript.Translate.Functions.{Erlang, Lists, Maps} - alias ElixirScript.Translate.Identifier - alias ElixirScript.Translate.Clause + alias ElixirScript.Translate.{Identifier, Clause} require Logger @moduledoc """ @@ -180,7 +179,9 @@ defmodule ElixirScript.Translate.Form do def compile({:receive, context, [blocks]}, state) do line = Keyword.get(context, :line, 1) {function, arity} = Map.get(state, :function) - Logger.warn "receive not supported, Module: #{inspect state.module}, Function: #{function}, Line: #{line}" + Logger.warn fn() -> + "receive not supported, Module: #{inspect state.module}, Function: #{function}, Line: #{line}" + end Receive.compile(blocks, state) end diff --git a/lib/elixir_script/passes/translate/forms/bitstring.ex b/lib/elixir_script/passes/translate/forms/bitstring.ex index dfe5f495..0221e82c 100644 --- a/lib/elixir_script/passes/translate/forms/bitstring.ex +++ b/lib/elixir_script/passes/translate/forms/bitstring.ex @@ -120,7 +120,7 @@ defmodule ElixirScript.Translate.Forms.Bitstring do end def make_interpolated_string(elements, state) do - translated_elements = Enum.map(elements, fn(x)-> + translated_elements = Enum.map(elements, fn(x) -> case x do elem when is_binary(elem) -> Form.compile!(elem, state) diff --git a/lib/elixir_script/passes/translate/forms/for.ex b/lib/elixir_script/passes/translate/forms/for.ex index 8e67424d..063fbe39 100644 --- a/lib/elixir_script/passes/translate/forms/for.ex +++ b/lib/elixir_script/passes/translate/forms/for.ex @@ -1,8 +1,9 @@ defmodule ElixirScript.Translate.Forms.For do + @moduledoc false + alias ESTree.Tools.Builder, as: JS - alias ElixirScript.Translate.Form - alias ElixirScript.Translate.Clause - alias ElixirScript.Translate.Forms.{Pattern} + alias ElixirScript.Translate.{Form, Clause} + alias ElixirScript.Translate.Forms.Pattern def compile({:for, _, generators}, state) do args = handle_args(generators, state) diff --git a/lib/elixir_script/passes/translate/forms/map.ex b/lib/elixir_script/passes/translate/forms/map.ex index 49480138..5bc27ba6 100644 --- a/lib/elixir_script/passes/translate/forms/map.ex +++ b/lib/elixir_script/passes/translate/forms/map.ex @@ -1,4 +1,5 @@ defmodule ElixirScript.Translate.Forms.Map do + @moduledoc false alias ESTree.Tools.Builder, as: J alias ElixirScript.Translate.Form diff --git a/lib/elixir_script/passes/translate/forms/match.ex b/lib/elixir_script/passes/translate/forms/match.ex index 6a2a8613..2ef9037c 100644 --- a/lib/elixir_script/passes/translate/forms/match.ex +++ b/lib/elixir_script/passes/translate/forms/match.ex @@ -1,7 +1,9 @@ defmodule ElixirScript.Translate.Forms.Match do + @moduledoc false + alias ESTree.Tools.Builder, as: J alias ElixirScript.Translate.Form - alias ElixirScript.Translate.Forms.{Pattern} + alias ElixirScript.Translate.Forms.Pattern def compile({:=, _, [left, right]}, state) do { right_ast, state } = Form.compile(right, state) diff --git a/lib/elixir_script/passes/translate/forms/pattern.ex b/lib/elixir_script/passes/translate/forms/pattern.ex index 89587f5f..a96f589f 100644 --- a/lib/elixir_script/passes/translate/forms/pattern.ex +++ b/lib/elixir_script/passes/translate/forms/pattern.ex @@ -2,7 +2,7 @@ defmodule ElixirScript.Translate.Forms.Pattern do alias ElixirScript.Translate.Forms.Pattern.Patterns, as: PM alias ESTree.Tools.Builder, as: J alias ElixirScript.Translate.Form - alias ElixirScript.Translate.Forms.{Bitstring} + alias ElixirScript.Translate.Forms.Bitstring @moduledoc """ Handles all pattern matching translations diff --git a/lib/elixir_script/passes/translate/forms/pattern/patterns.ex b/lib/elixir_script/passes/translate/forms/pattern/patterns.ex index d914080f..bb8401a3 100644 --- a/lib/elixir_script/passes/translate/forms/pattern/patterns.ex +++ b/lib/elixir_script/passes/translate/forms/pattern/patterns.ex @@ -1,4 +1,6 @@ defmodule ElixirScript.Translate.Forms.Pattern.Patterns do + @moduledoc false + alias ESTree.Tools.Builder, as: J @patterns J.member_expression( diff --git a/lib/elixir_script/passes/translate/forms/remote.ex b/lib/elixir_script/passes/translate/forms/remote.ex index 6d4a751a..b6c8c192 100644 --- a/lib/elixir_script/passes/translate/forms/remote.ex +++ b/lib/elixir_script/passes/translate/forms/remote.ex @@ -2,8 +2,7 @@ defmodule ElixirScript.Translate.Forms.Remote do @moduledoc false alias ESTree.Tools.Builder, as: J - alias ElixirScript.Translate.Form - alias ElixirScript.Translate.Identifier + alias ElixirScript.Translate.{Form, Identifier} @erlang_modules [ :erlang, @@ -126,10 +125,9 @@ defmodule ElixirScript.Translate.Forms.Remote do end def compile({:., _, [module, function]}, state) do - function_name = cond do - ElixirScript.Translate.Module.is_js_module(module, state) -> + function_name = if ElixirScript.Translate.Module.is_js_module(module, state) do ElixirScript.Translate.Identifier.make_extern_function_name(function) - true -> + else ElixirScript.Translate.Identifier.make_function_name(function) end diff --git a/lib/elixir_script/passes/translate/forms/try.ex b/lib/elixir_script/passes/translate/forms/try.ex index 2729e39f..b7c0f225 100644 --- a/lib/elixir_script/passes/translate/forms/try.ex +++ b/lib/elixir_script/passes/translate/forms/try.ex @@ -1,8 +1,7 @@ defmodule ElixirScript.Translate.Forms.Try do @moduledoc false alias ESTree.Tools.Builder, as: JS - alias ElixirScript.Translate.Clause - alias ElixirScript.Translate.{Form, Function} + alias ElixirScript.Translate.{Form, Function, Clause} def compile(blocks, state) do try_block = Keyword.get(blocks, :do) diff --git a/lib/elixir_script/passes/translate/function.ex b/lib/elixir_script/passes/translate/function.ex index ba6e1fc1..23e13f20 100644 --- a/lib/elixir_script/passes/translate/function.ex +++ b/lib/elixir_script/passes/translate/function.ex @@ -1,8 +1,7 @@ defmodule ElixirScript.Translate.Function do alias ESTree.Tools.Builder, as: J - alias ElixirScript.Translate.Clause + alias ElixirScript.Translate.{Clause, Form} alias ElixirScript.Translate.Forms.Pattern - alias ElixirScript.Translate.Form @moduledoc """ Translates the given Elixir function AST into the @@ -115,10 +114,10 @@ defmodule ElixirScript.Translate.Function do end defp compile_clause({ _, args, guards, body}, state) do - state = if !Map.has_key?(state, :vars) do - Map.put(state, :vars, %{}) - else + state = if Map.has_key?(state, :vars) do state + else + Map.put(state, :vars, %{}) end {patterns, params, state} = Pattern.compile(args, state) diff --git a/lib/elixir_script/passes/translate/module.ex b/lib/elixir_script/passes/translate/module.ex index 9f716f80..c46dc80e 100644 --- a/lib/elixir_script/passes/translate/module.ex +++ b/lib/elixir_script/passes/translate/module.ex @@ -1,9 +1,7 @@ defmodule ElixirScript.Translate.Module do @moduledoc false alias ESTree.Tools.Builder, as: J - alias ElixirScript.Translate.Function - alias ElixirScript.Translate.Form - alias ElixirScript.Translate.Identifier + alias ElixirScript.Translate.{Function, Form, Identifier} alias ElixirScript.State, as: ModuleState @doc """ diff --git a/lib/elixir_script/passes/translate/protocol.ex b/lib/elixir_script/passes/translate/protocol.ex index baaed852..0a02a17e 100644 --- a/lib/elixir_script/passes/translate/protocol.ex +++ b/lib/elixir_script/passes/translate/protocol.ex @@ -1,9 +1,7 @@ defmodule ElixirScript.Translate.Protocol do @moduledoc false alias ESTree.Tools.Builder, as: J - alias ElixirScript.Translate.Function - alias ElixirScript.Translate.Form - alias ElixirScript.Translate.Identifier + alias ElixirScript.Translate.{Function, Form, Identifier} alias ElixirScript.State, as: ModuleState diff --git a/lib/elixir_script/state.ex b/lib/elixir_script/state.ex index b199e9e8..b65c7189 100644 --- a/lib/elixir_script/state.ex +++ b/lib/elixir_script/state.ex @@ -60,8 +60,11 @@ defmodule ElixirScript.State do def get_javascript_modules(pid) do Agent.get(pid, fn(state) -> Map.get(state.compiler_opts, :js_modules, []) - |> Enum.map(fn({module_name, _path}) -> - module_name + |> Enum.map(fn + {module_name, _path} -> + module_name + {module_name, _path, _opts} -> + module_name end) end) end diff --git a/lib/elixir_script/watcher.ex b/lib/elixir_script/watcher.ex index 5f6de96c..7f1e6e1d 100644 --- a/lib/elixir_script/watcher.ex +++ b/lib/elixir_script/watcher.ex @@ -23,7 +23,9 @@ defmodule ElixirScript.Watcher do try do if input_changed?(to_string(path), state) do - Logger.debug "Event: #{inspect event} Path: #{path}" + Logger.debug fn() -> + "Event: #{inspect event} Path: #{path}" + end ElixirScript.Compiler.compile(state[:input], state[:options]) end rescue diff --git a/lib/mix/tasks/compile.elixir_script.ex b/lib/mix/tasks/compile.elixir_script.ex index a7926b79..eec94c8d 100644 --- a/lib/mix/tasks/compile.elixir_script.ex +++ b/lib/mix/tasks/compile.elixir_script.ex @@ -53,7 +53,15 @@ defmodule Mix.Tasks.Compile.ElixirScript do end def clean do - #TODO: Figure out how to clean + {input, opts} = get_compiler_params() + + case opts[:output] do + path when is_binary(path) -> + file_name = ElixirScript.Output.get_output_file_name(path) + File.rm!(file_name) + _ -> + nil + end :ok end diff --git a/mix.exs b/mix.exs index 83839435..8bd543b2 100644 --- a/mix.exs +++ b/mix.exs @@ -7,7 +7,6 @@ defmodule ElixirScript.Mixfile do version: "0.29.0-dev", elixir: "~> 1.5-dev", elixirc_paths: elixirc_paths(Mix.env), - escript: escript_config(), deps: deps(), description: description(), package: package(), @@ -15,7 +14,7 @@ defmodule ElixirScript.Mixfile do aliases: aliases(), test_coverage: [tool: ExCoveralls], docs: [ - extras: ["GettingStarted.md", "FAQ.md", "Supported.md", "JavaScriptInterop.md"] + extras: ["GettingStarted.md", "JavaScriptInterop.md"] ] ] end @@ -29,19 +28,15 @@ defmodule ElixirScript.Mixfile do defp deps do [ {:estree, "~> 2.6"}, - {:fs, "~> 2.12"}, - {:ex_doc, "~> 0.15", only: :dev}, - {:excoveralls, "~> 0.6", only: :test}, - {:credo, "~> 0.7", only: [:dev, :test]} + {:fs, "~> 3.4"}, + {:ex_doc, "~> 0.16", only: :dev}, + {:excoveralls, "~> 0.7", only: :test}, + {:credo, "~> 0.8", only: [:dev, :test]} ] end - defp elixirc_paths(:test), do: ["lib", "priv/std_lib", "test/support"] - defp elixirc_paths(_), do: ["lib", "priv/std_lib"] - - defp escript_config do - [main_module: ElixirScript.CLI, name: "elixirscript"] - end + defp elixirc_paths(:test), do: ["lib", "test/support"] + defp elixirc_paths(_), do: ["lib"] defp description do """ @@ -62,48 +57,12 @@ defmodule ElixirScript.Mixfile do end defp aliases do - [dist: &dist/1, - install: &install/1] - end - - def dist(_) do - Mix.Task.run "app.start" - - dist_folder = "dist" - folder_name = "#{dist_folder}/elixirscript" - archive_file_name = "#{dist_folder}/elixirscript.tar.gz" - - Mix.Tasks.Escript.Build.run([]) - - if File.exists?(dist_folder) do - File.rm_rf(dist_folder) - end - - System.cmd("npm", ["run", "build"]) - - File.mkdir_p(folder_name <> "/bin") - File.cp!("elixirscript", "#{folder_name}/bin/elixirscript") - if File.exists?("priv/.DS_Store") do - File.rm!("priv/.DS_Store") - end - File.cp_r!("priv/", "#{folder_name}") - File.cp!("LICENSE", "#{folder_name}/LICENSE") - - System.cmd("tar", ["czf", archive_file_name, folder_name]) - - File.rm_rf(folder_name) + [build_js: &build_js/1] end - def install(_) do + def build_js(_) do Mix.Task.run "app.start" - - System.cmd("tar", ["-zxvf", "dist/elixirscript.tar.gz"]) - - File.rm_rf!("/usr/local/elixirscript") - - System.cmd("mv", ["dist/elixirscript", "/usr/local/elixirscript"]) - - IO.puts("installed at /usr/local/elixirscript") + System.cmd("yarn", ["build"]) end end diff --git a/mix.lock b/mix.lock index 353e11a0..9de5d64f 100644 --- a/mix.lock +++ b/mix.lock @@ -1,15 +1,16 @@ %{"bunt": {:hex, :bunt, "0.2.0", "951c6e801e8b1d2cbe58ebbd3e616a869061ddadcc4863d0a2182541acae9a38", [:mix], [], "hexpm"}, - "certifi": {:hex, :certifi, "1.0.0", "1c787a85b1855ba354f0b8920392c19aa1d06b0ee1362f9141279620a5be2039", [:rebar3], [], "hexpm"}, - "credo": {:hex, :credo, "0.7.3", "9827ab04002186af1aec014a811839a06f72aaae6cd5eed3919b248c8767dbf3", [:mix], [{:bunt, "~> 0.2.0", [hex: :bunt, repo: "hexpm", optional: false]}], "hexpm"}, - "earmark": {:hex, :earmark, "1.2.0", "bf1ce17aea43ab62f6943b97bd6e3dc032ce45d4f787504e3adf738e54b42f3a", [:mix], [], "hexpm"}, + "certifi": {:hex, :certifi, "1.2.1", "c3904f192bd5284e5b13f20db3ceac9626e14eeacfbb492e19583cf0e37b22be", [:rebar3], [], "hexpm"}, + "credo": {:hex, :credo, "0.8.1", "137efcc99b4bc507c958ba9b5dff70149e971250813cbe7d4537ec7e36997402", [:mix], [{:bunt, "~> 0.2.0", [hex: :bunt, repo: "hexpm", optional: false]}], "hexpm"}, + "earmark": {:hex, :earmark, "1.2.2", "f718159d6b65068e8daeef709ccddae5f7fdc770707d82e7d126f584cd925b74", [:mix], [], "hexpm"}, "estree": {:hex, :estree, "2.6.0", "86a301b0c355fa55c19e7ef9dceb1b1e983c6df526a2b7846818a38c258fc3fb", [:mix], [], "hexpm"}, - "ex_doc": {:hex, :ex_doc, "0.15.1", "d5f9d588fd802152516fccfdb96d6073753f77314fcfee892b15b6724ca0d596", [:mix], [{:earmark, "~> 1.1", [hex: :earmark, repo: "hexpm", optional: false]}], "hexpm"}, - "excoveralls": {:hex, :excoveralls, "0.6.3", "894bf9254890a4aac1d1165da08145a72700ff42d8cb6ce8195a584cb2a4b374", [:mix], [{:exjsx, "~> 3.0", [hex: :exjsx, repo: "hexpm", optional: false]}, {:hackney, ">= 0.12.0", [hex: :hackney, repo: "hexpm", optional: false]}], "hexpm"}, - "exjsx": {:hex, :exjsx, "3.2.1", "1bc5bf1e4fd249104178f0885030bcd75a4526f4d2a1e976f4b428d347614f0f", [:mix], [{:jsx, "~> 2.8.0", [hex: :jsx, repo: "hexpm", optional: false]}], "hexpm"}, - "fs": {:hex, :fs, "2.12.0", "ad631efacc9a5683c8eaa1b274e24fa64a1b8eb30747e9595b93bec7e492e25e", [:rebar3], [], "hexpm"}, - "hackney": {:hex, :hackney, "1.7.1", "e238c52c5df3c3b16ce613d3a51c7220a784d734879b1e231c9babd433ac1cb4", [:rebar3], [{:certifi, "1.0.0", [hex: :certifi, repo: "hexpm", optional: false]}, {:idna, "4.0.0", [hex: :idna, repo: "hexpm", optional: false]}, {:metrics, "1.0.1", [hex: :metrics, repo: "hexpm", optional: false]}, {:mimerl, "1.0.2", [hex: :mimerl, repo: "hexpm", optional: false]}, {:ssl_verify_fun, "1.1.1", [hex: :ssl_verify_fun, repo: "hexpm", optional: false]}], "hexpm"}, - "idna": {:hex, :idna, "4.0.0", "10aaa9f79d0b12cf0def53038547855b91144f1bfcc0ec73494f38bb7b9c4961", [:rebar3], [], "hexpm"}, + "ex_doc": {:hex, :ex_doc, "0.16.1", "b4b8a23602b4ce0e9a5a960a81260d1f7b29635b9652c67e95b0c2f7ccee5e81", [:mix], [{:earmark, "~> 1.1", [hex: :earmark, repo: "hexpm", optional: false]}], "hexpm"}, + "excoveralls": {:hex, :excoveralls, "0.7.0", "05cb3332c2b0f799df3ab90eb7df1ae5a147c86776e91792848a12b7ed87242f", [:mix], [{:exjsx, ">= 3.0.0", [hex: :exjsx, repo: "hexpm", optional: false]}, {:hackney, ">= 0.12.0", [hex: :hackney, repo: "hexpm", optional: false]}], "hexpm"}, + "exjsx": {:hex, :exjsx, "4.0.0", "60548841e0212df401e38e63c0078ec57b33e7ea49b032c796ccad8cde794b5c", [:mix], [{:jsx, "~> 2.8.0", [hex: :jsx, repo: "hexpm", optional: false]}], "hexpm"}, + "fs": {:hex, :fs, "3.4.0", "6d18575c250b415b3cad559e6f97a4c822516c7bc2c10bfbb2493a8f230f5132", [:rebar3], [], "hexpm"}, + "hackney": {:hex, :hackney, "1.8.6", "21a725db3569b3fb11a6af17d5c5f654052ce9624219f1317e8639183de4a423", [:rebar3], [{:certifi, "1.2.1", [hex: :certifi, repo: "hexpm", optional: false]}, {:idna, "5.0.2", [hex: :idna, repo: "hexpm", optional: false]}, {:metrics, "1.0.1", [hex: :metrics, repo: "hexpm", optional: false]}, {:mimerl, "1.0.2", [hex: :mimerl, repo: "hexpm", optional: false]}, {:ssl_verify_fun, "1.1.1", [hex: :ssl_verify_fun, repo: "hexpm", optional: false]}], "hexpm"}, + "idna": {:hex, :idna, "5.0.2", "ac203208ada855d95dc591a764b6e87259cb0e2a364218f215ad662daa8cd6b4", [:rebar3], [{:unicode_util_compat, "0.2.0", [hex: :unicode_util_compat, repo: "hexpm", optional: false]}], "hexpm"}, "jsx": {:hex, :jsx, "2.8.2", "7acc7d785b5abe8a6e9adbde926a24e481f29956dd8b4df49e3e4e7bcc92a018", [:mix, :rebar3], [], "hexpm"}, "metrics": {:hex, :metrics, "1.0.1", "25f094dea2cda98213cecc3aeff09e940299d950904393b2a29d191c346a8486", [:rebar3], [], "hexpm"}, "mimerl": {:hex, :mimerl, "1.0.2", "993f9b0e084083405ed8252b99460c4f0563e41729ab42d9074fd5e52439be88", [:rebar3], [], "hexpm"}, - "ssl_verify_fun": {:hex, :ssl_verify_fun, "1.1.1", "28a4d65b7f59893bc2c7de786dec1e1555bd742d336043fe644ae956c3497fbe", [:make, :rebar], [], "hexpm"}} + "ssl_verify_fun": {:hex, :ssl_verify_fun, "1.1.1", "28a4d65b7f59893bc2c7de786dec1e1555bd742d336043fe644ae956c3497fbe", [:make, :rebar], [], "hexpm"}, + "unicode_util_compat": {:hex, :unicode_util_compat, "0.2.0", "dbbccf6781821b1c0701845eaf966c9b6d83d7c3bfc65ca2b78b88b8678bfa35", [:rebar3], [], "hexpm"}} diff --git a/test/beam_test.exs b/test/beam_test.exs index bfcbb798..43c45880 100644 --- a/test/beam_test.exs +++ b/test/beam_test.exs @@ -2,6 +2,20 @@ defmodule ElixirScript.Beam.Test do use ExUnit.Case test "can get ast from beam" do - assert {:ok, map} = ElixirScript.Beam.debug_info(Atom) + assert {:ok, _} = ElixirScript.Beam.debug_info(Atom) + end + + test "errors when not found" do + assert {:error, _} = ElixirScript.Beam.debug_info(Some.Module) + end + + test "can get ast from beam that is protocol" do + assert {:ok, Enumerable, _} = ElixirScript.Beam.debug_info(Enumerable) + end + + test "replaces String with ElixirScript.String" do + assert {:ok, map} = ElixirScript.Beam.debug_info(String) + assert {:ok, map2} = ElixirScript.Beam.debug_info(ElixirScript.String) + assert map.definitions == map2.definitions end end diff --git a/test/cli_test.exs b/test/cli_test.exs new file mode 100644 index 00000000..2826670d --- /dev/null +++ b/test/cli_test.exs @@ -0,0 +1,8 @@ +defmodule ElixirScript.CLI.Test do + use ExUnit.Case + + test "parse_args" do + {_, args} = ElixirScript.CLI.parse_args(["Atom", "--format", "umd"]) + assert args == [format: "umd"] + end +end \ No newline at end of file diff --git a/test/compiler_test.exs b/test/compiler_test.exs new file mode 100644 index 00000000..c154e67c --- /dev/null +++ b/test/compiler_test.exs @@ -0,0 +1,49 @@ +defmodule ElixirScript.Compiler.Test do + use ExUnit.Case + + test "Can compile one entry module" do + result = ElixirScript.Compiler.compile(Version) + assert is_binary(result) + end + + test "Can compile multiple entry modules" do + result = ElixirScript.Compiler.compile([Atom, String]) + assert is_binary(result) + end + + test "Error on unknown module" do + assert_raise ElixirScript.CompileError, fn -> + ElixirScript.Compiler.compile(SomeModule) + end + end + + test "Output format: es" do + result = ElixirScript.Compiler.compile(Atom, [format: :es, js_modules: [{React, "react"}, {ReactDOM, "react-dom", default: false}]]) + assert result =~ "export default Elixir" + end + + test "Output format: umd" do + result = ElixirScript.Compiler.compile(Atom, [format: :umd, js_modules: [{React, "react"}]]) + assert result =~ "factory" + end + + test "Output format: common" do + result = ElixirScript.Compiler.compile(Atom, [format: :common, js_modules: [{React, "react"}]]) + assert result =~ "module.exports = Elixir" + end + + test "Output file with default name" do + path = System.tmp_dir() + + result = ElixirScript.Compiler.compile(Atom, [output: path]) + assert File.exists?(Path.join([path, "Elixir.App.js"])) + end + + test "Output file with custom name" do + path = System.tmp_dir() + path = Path.join([path, "myfile.js"]) + + result = ElixirScript.Compiler.compile(Atom, [output: path]) + assert File.exists?(path) + end +end \ No newline at end of file diff --git a/test/support/user.ex b/test/support/user.ex deleted file mode 100644 index 2781433d..00000000 --- a/test/support/user.ex +++ /dev/null @@ -1,17 +0,0 @@ -defmodule User do - defstruct [:first, :last] - - def throw_something() do - raise ArgumentError - end -end - -defimpl String.Chars, for: User do - def to_string(nil) do - "" - end - - def to_string(user) do - user.first <> user.last - end -end \ No newline at end of file From bac9b99153516d253835013d4844204e8f3485a5 Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Sun, 25 Jun 2017 21:07:14 -0500 Subject: [PATCH 576/860] More CLI tests. Add JS tests --- .../translate/forms/pattern/patterns.ex | 19 ---- .../passes/translate/identifier.ex | 10 -- test/cli_test.exs | 31 ++++++ test/passes/translate/forms/js_test.exs | 105 ++++++++++++++++++ 4 files changed, 136 insertions(+), 29 deletions(-) create mode 100644 test/passes/translate/forms/js_test.exs diff --git a/lib/elixir_script/passes/translate/forms/pattern/patterns.ex b/lib/elixir_script/passes/translate/forms/pattern/patterns.ex index bb8401a3..70154334 100644 --- a/lib/elixir_script/passes/translate/forms/pattern/patterns.ex +++ b/lib/elixir_script/passes/translate/forms/pattern/patterns.ex @@ -11,11 +11,6 @@ defmodule ElixirScript.Translate.Forms.Pattern.Patterns do J.identifier("Patterns") ) - @wildcard J.member_expression( - @patterns, - J.identifier(:wildcard) - ) - @parameter J.member_expression( @patterns, J.identifier(:variable) @@ -51,13 +46,6 @@ defmodule ElixirScript.Translate.Forms.Pattern.Patterns do J.identifier(:bitStringMatch) ) - def wildcard() do - J.call_expression( - @wildcard, - [] - ) - end - def parameter() do J.call_expression( @parameter, @@ -65,13 +53,6 @@ defmodule ElixirScript.Translate.Forms.Pattern.Patterns do ) end - def parameter(default_value) do - J.call_expression( - @parameter, - [default_value] - ) - end - def head_tail(headParameter, tailParameter) do J.call_expression( @head_tail, diff --git a/lib/elixir_script/passes/translate/identifier.ex b/lib/elixir_script/passes/translate/identifier.ex index 5c95e03a..b5c287dd 100644 --- a/lib/elixir_script/passes/translate/identifier.ex +++ b/lib/elixir_script/passes/translate/identifier.ex @@ -35,20 +35,12 @@ defmodule ElixirScript.Translate.Identifier do :yield ] - def make_identifier([ast]) do - make_identifier(ast) - end - def make_identifier(ast) do ast |> filter_name |> J.identifier end - defp filter_name(name) when is_tuple(name) do - name - end - defp filter_name(reserved_word) when reserved_word in @js_reserved_words do "__#{Atom.to_string(reserved_word)}__" end @@ -71,8 +63,6 @@ defmodule ElixirScript.Translate.Identifier do case module_name do m when is_list(m) -> m - m when is_binary(m) -> - String.split(m, ".") m when is_atom(m) -> Module.split(m) end diff --git a/test/cli_test.exs b/test/cli_test.exs index 2826670d..53589cc9 100644 --- a/test/cli_test.exs +++ b/test/cli_test.exs @@ -1,8 +1,39 @@ defmodule ElixirScript.CLI.Test do use ExUnit.Case + import ExUnit.CaptureIO test "parse_args" do {_, args} = ElixirScript.CLI.parse_args(["Atom", "--format", "umd"]) assert args == [format: "umd"] end + + test "process help" do + assert capture_io(fn -> + ElixirScript.CLI.process(:help) + end) =~ "usage: elixirscript [options]" + end + + test "process version" do + assert capture_io(fn -> + ElixirScript.CLI.process(:version) + end) =~ Mix.Project.config()[:version] + end + + test "process unknown" do + assert capture_io(fn -> + ElixirScript.CLI.process({"", [unknown: ""]}) + end) =~ "usage: elixirscript [options]" + end + + test "process input" do + assert capture_io(fn -> + ElixirScript.CLI.process({["Atom"], []}) + end) =~ "export default Elixir" + end + + test "process js modules" do + assert capture_io(fn -> + ElixirScript.CLI.process({["Atom"], [js_module: "React:react"]}) + end) =~ "import React from 'react'" + end end \ No newline at end of file diff --git a/test/passes/translate/forms/js_test.exs b/test/passes/translate/forms/js_test.exs new file mode 100644 index 00000000..c6d7c121 --- /dev/null +++ b/test/passes/translate/forms/js_test.exs @@ -0,0 +1,105 @@ +defmodule ElixirScript.Translate.Forms.JS.Test do + use ExUnit.Case + alias ElixirScript.Translate.Form + alias ESTree.Tools.Builder, as: J + + setup_all do + {:ok, pid} = ElixirScript.State.start_link(%{}) + + state = %{ + pid: pid, + vars: %{} + } + + [state: state] + end + + test "debugger" do + ast = {{:., [], [JS, :debugger]}, [], []} + state = %{function: {:each, nil}, module: Enum, vars: %{:_ => 0, "entry" => 0, "enumerable" => 0, "fun" => 0}} + + {js_ast, _} = Form.compile(ast, state) + assert js_ast == J.debugger_statement() + end + + test "this" do + ast = {{:., [], [JS, :this]}, [], []} + state = %{function: {:each, nil}, module: Enum, vars: %{:_ => 0, "entry" => 0, "enumerable" => 0, "fun" => 0}} + + {js_ast, _} = Form.compile(ast, state) + assert js_ast == J.this_expression() + end + + test "new" do + ast = {{:., [], [JS, :new]}, [], [BLT, ["bacon", "lettuce", "tomato"]]} + state = %{function: {:each, nil}, module: Enum, vars: %{:_ => 0, "entry" => 0, "enumerable" => 0, "fun" => 0}} + + {js_ast, _} = Form.compile(ast, state) + assert js_ast == J.new_expression( + J.identifier("BLT"), + [ + J.literal("bacon"), + J.literal("lettuce"), + J.literal("tomato") + ] + ) + end + + + test "throw" do + ast = {{:., [], [JS, :throw]}, [], [1]} + state = %{function: {:each, nil}, module: Enum, vars: %{:_ => 0, "entry" => 0, "enumerable" => 0, "fun" => 0}} + + {js_ast, _} = Form.compile(ast, state) + assert js_ast == J.throw_statement(J.literal(1)) + end + + test "import" do + ast = {{:., [], [JS, :import]}, [], ["react"]} + state = %{function: {:each, nil}, module: Enum, vars: %{:_ => 0, "entry" => 0, "enumerable" => 0, "fun" => 0}} + + {js_ast, _} = Form.compile(ast, state) + assert js_ast == J.call_expression( + J.identifier("import"), + [J.literal("react")] + ) + end + + test "global function or property" do + ast = {{:., [], [JS, :self]}, [], []} + state = %{function: {:each, nil}, module: Enum, vars: %{:_ => 0, "entry" => 0, "enumerable" => 0, "fun" => 0}} + + {js_ast, _} = Form.compile(ast, state) + assert js_ast == J.call_expression( + ElixirScript.Translate.Forms.JS.call_property(), + [ + ElixirScript.Translate.Forms.JS.global(), + J.literal("self") + ] + ) + end + + test "global function with params" do + ast = {{:., [], [JS, :self]}, [], ["something"]} + state = %{function: {:each, nil}, module: Enum, vars: %{:_ => 0, "entry" => 0, "enumerable" => 0, "fun" => 0}} + + {js_ast, _} = Form.compile(ast, state) + assert js_ast == J.call_expression( + J.identifier(:self), + [J.literal("something")] + ) + end + + test "JavaScript module call", %{state: state} do + ast = {{:., [], [JS.Object, :keys]}, [], [{:obj, [], nil}]} + + {js_ast, _} = Form.compile(ast, state) + assert js_ast == J.call_expression( + J.member_expression( + J.identifier("Object"), + J.identifier("keys") + ), + [J.identifier("obj")] + ) + end +end \ No newline at end of file From 72323bf42b56b071f090b1a0f008d0284c37b92c Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Sun, 25 Jun 2017 21:09:40 -0500 Subject: [PATCH 577/860] Show cover information in travis tests --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 3333d660..859e3269 100644 --- a/.travis.yml +++ b/.travis.yml @@ -16,7 +16,7 @@ script: - mix deps.get - mix compile - yarn build - - mix test + - mix test --cover - yarn test - yarn test-app notifications: From 98c68911cff32b8ed9162ae2bfe8e90a482a7075 Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Mon, 26 Jun 2017 19:52:35 -0500 Subject: [PATCH 578/860] Try to update elixir version in travis.yml and use otp 20 --- .travis.yml | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/.travis.yml b/.travis.yml index 859e3269..ce075d5f 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,7 +1,5 @@ sudo: false -language: elixir -elixir: - - 1.5.0-rc.0 +language: erlang otp_release: - 20.0 env: @@ -10,13 +8,16 @@ install: - rm -rf ~/.nvm && git clone https://github.com/creationix/nvm.git ~/.nvm && (cd ~/.nvm && git checkout `git describe --abbrev=0 --tags`) && source ~/.nvm/nvm.sh && nvm install $TRAVIS_NODE_VERSION - npm install -g yarn - yarn -script: - - mix local.hex --force +before_script: + - wget https://repo.hex.pm/builds/elixir/v1.5.0-rc.0-otp-20.zip + - unzip -d elixir v1.5.0-rc.0-otp-20.zip + - export PATH=$(pwd)/elixir/bin:${PATH} - mix local.rebar --force + - mix local.hex --force - mix deps.get - - mix compile +script: - yarn build - - mix test --cover + - mix test - yarn test - yarn test-app notifications: From ed4dbcc67894950d067f6382a60d1b978c3d23b8 Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Tue, 27 Jun 2017 21:29:24 -0500 Subject: [PATCH 579/860] Add all lists functions used in List module --- .../lib/core/erlang_compat/lists.js | 145 ++++++++++++++++++ .../tests/core/erlang_compat/lists_spec.js | 22 +++ 2 files changed, 167 insertions(+) diff --git a/src/javascript/lib/core/erlang_compat/lists.js b/src/javascript/lib/core/erlang_compat/lists.js index a926fab9..c9e4eacc 100644 --- a/src/javascript/lib/core/erlang_compat/lists.js +++ b/src/javascript/lib/core/erlang_compat/lists.js @@ -1,4 +1,5 @@ // http://erlang.org/doc/man/lists.html +import ErlangTypes from 'erlang-types'; function reverse(list) { return [...list].reverse(); @@ -10,7 +11,151 @@ function foreach(fun, list) { return Symbol.for('ok'); } +function duplicate(n, elem) { + const list = []; + + while (list.length < n) { + list.push(elem); + } + + return list; +} + +function flatten(deepList, tail = []) { + const val = deepList.reduce((acc, value) => { + if (Array.isArray(value)) { + return acc.concat(flatten(value)); + } + + return acc.concat(value); + }, []); + + return val.concat(tail); +} + +function foldl(fun, acc0, list) { + return list.reduce((acc, value) => { + return fun(value, acc); + }, acc0); +} + +function foldr(fun, acc0, list) { + return foldl(fun, acc0, reverse(list)); +} + +function keyfind(key, n, tupleList) { + for (const tuple of tupleList) { + if (tuple.get(n) === key) { + return tuple; + } + } + + return false; +} + +function keymember(key, n, tupleList) { + if (keyfind(key, n, tupleList) === false) { + return false; + } + + return true; +} + +function keyreplace(key, n, tupleList, newTuple) { + const newTupleList = [...tupleList]; + + for (let index = 0; index < newTupleList.length; index++) { + if (newTupleList[index].get(n) === key) { + newTupleList[index] = newTuple; + return newTupleList; + } + } + + return newTupleList; +} + +function keysort(n, tupleList) { + const newTupleList = [...tupleList]; + + return newTupleList.sort((a, b) => { + if (a.get(n) < b.get(n)) { + return -1; + } else if (a.get(n) > b.get(n)) { + return 1; + } + + return 0; + }); +} + +function keystore(key, n, tupleList, newTuple) { + const newTupleList = [...tupleList]; + + for (let index = 0; index < newTupleList.length; index++) { + if (newTupleList[index].get(n) === key) { + newTupleList[index] = newTuple; + return newTupleList; + } + } + + return newTupleList.concat(newTuple); +} + +function keydelete(key, n, tupleList) { + const newTupleList = []; + let deleted = false; + + for (let index = 0; index < tupleList.length; index++) { + if (deleted === false && tupleList[index].get(n) === key) { + deleted = true; + } else { + newTupleList.push(tupleList[index]); + } + } + + return newTupleList; +} + +function keytake(key, n, tupleList) { + const result = keyfind(key, n, tupleList); + + if (result !== false) { + return new ErlangTypes.Tuple( + result.get(n), + result, + keydelete(key, n, tupleList) + ); + } + + return false; +} + +function mapfoldl(fun, acc0, list1) { + const listResult = []; + let accResult = acc0; + + for (const item of list1) { + const tuple = fun(item, accResult); + listResult.push(tuple.get(0)); + accResult = tuple.get(1); + } + + return new ErlangTypes.Tuple(listResult, accResult); +} + export default { reverse, foreach, + duplicate, + flatten, + foldl, + foldr, + keydelete, + keyfind, + keymember, + keyreplace, + keysort, + keystore, + keytake, + mapfoldl, }; diff --git a/src/javascript/tests/core/erlang_compat/lists_spec.js b/src/javascript/tests/core/erlang_compat/lists_spec.js index 4e3fbb4e..491abd15 100644 --- a/src/javascript/tests/core/erlang_compat/lists_spec.js +++ b/src/javascript/tests/core/erlang_compat/lists_spec.js @@ -4,3 +4,25 @@ import Core from '../../../lib/core'; test('reverse', t => { t.deepEqual(Core.lists.reverse([1, 2, 3]), [3, 2, 1]); }); + +test('duplicate', t => { + t.deepEqual(Core.lists.duplicate(0, 1), []); + t.deepEqual(Core.lists.duplicate(1, 1), [1]); + t.deepEqual(Core.lists.duplicate(2, 1), [1, 1]); +}); + +test('flatten', t => { + t.deepEqual(Core.lists.flatten([1, 2, 3]), [1, 2, 3]); + t.deepEqual(Core.lists.flatten([1, [[2], 3]]), [1, 2, 3]); +}); + +test('foldl', t => { + t.deepEqual(Core.lists.foldl((v, acc) => acc + v, 0, [1, 2, 3]), 6); +}); + +test('foldr', t => { + t.deepEqual( + Core.lists.foldr((v, acc) => acc + v.toString(), '', [1, 2, 3]), + '321' + ); +}); From e009885941795a9c39a1f793358b15d492c1da15 Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Tue, 27 Jun 2017 21:33:35 -0500 Subject: [PATCH 580/860] Add map function to lists module --- src/javascript/lib/core/erlang_compat/lists.js | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/javascript/lib/core/erlang_compat/lists.js b/src/javascript/lib/core/erlang_compat/lists.js index c9e4eacc..1c9a3974 100644 --- a/src/javascript/lib/core/erlang_compat/lists.js +++ b/src/javascript/lib/core/erlang_compat/lists.js @@ -143,6 +143,10 @@ function mapfoldl(fun, acc0, list1) { return new ErlangTypes.Tuple(listResult, accResult); } +function map(fun, list) { + return list.map(value => fun(value)); +} + export default { reverse, foreach, @@ -158,4 +162,5 @@ export default { keystore, keytake, mapfoldl, + map, }; From 2a4808fc169fb6f36e36f23b0e1e8aaa3c91a077 Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Wed, 28 Jun 2017 20:42:58 -0500 Subject: [PATCH 581/860] Add more lists functions --- .../lib/core/erlang_compat/lists.js | 80 +++++++++++++++++++ 1 file changed, 80 insertions(+) diff --git a/src/javascript/lib/core/erlang_compat/lists.js b/src/javascript/lib/core/erlang_compat/lists.js index 1c9a3974..d2de47b5 100644 --- a/src/javascript/lib/core/erlang_compat/lists.js +++ b/src/javascript/lib/core/erlang_compat/lists.js @@ -143,10 +143,83 @@ function mapfoldl(fun, acc0, list1) { return new ErlangTypes.Tuple(listResult, accResult); } +function concat(things) { + return things.map(v => v.toString()).join(); +} + function map(fun, list) { return list.map(value => fun(value)); } +function filter(pred, list1) { + return list1.filter(x => pred(x)); +} + +function filtermap(fun, list1) { + const list2 = []; + + for (const item of list1) { + const value = fun(item); + + if (value === true) { + list2.push(item); + } else if (value instanceof ErlangTypes.Tuple && value.get(0) === true) { + list2.push(value.get(1)); + } + } + + return list2; +} + +function member(elem, list) { + for (const item of list) { + if (item === elem) { + return true; + } + } + + return false; +} + +function all(pred, list) { + for (const item of list) { + if (pred(item) === false) { + return false; + } + } + + return true; +} + +function any(pred, list) { + for (const item of list) { + if (pred(item) === true) { + return true; + } + } + + return false; +} + +function splitwith(pred, list) { + let switchToList2 = false; + const list1 = []; + const list2 = []; + + for (const item of list) { + if (switchToList2 === true) { + list2.push(item); + } else if (pred(item) === true) { + list1.push(item); + } else { + switchToList2 = true; + list2.push(item); + } + } + + return new ErlangTypes.Tuple(list1, list2); +} + export default { reverse, foreach, @@ -162,5 +235,12 @@ export default { keystore, keytake, mapfoldl, + concat, map, + filter, + filtermap, + member, + all, + any, + splitwith, }; From 82f57f4af7ffa9fa62add04b29d54350189860b0 Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Wed, 28 Jun 2017 20:48:50 -0500 Subject: [PATCH 582/860] Add lists.sort --- .../lib/core/erlang_compat/lists.js | 21 +++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/src/javascript/lib/core/erlang_compat/lists.js b/src/javascript/lib/core/erlang_compat/lists.js index d2de47b5..52db1b08 100644 --- a/src/javascript/lib/core/erlang_compat/lists.js +++ b/src/javascript/lib/core/erlang_compat/lists.js @@ -220,6 +220,26 @@ function splitwith(pred, list) { return new ErlangTypes.Tuple(list1, list2); } +function sort(...args) { + if (args.length === 1) { + const list2 = [...args[0]]; + return list2.sort(); + } + + const fun = args[0]; + const list2 = [...args[1]]; + + return list2.sort((a, b) => { + const result = fun(a, b); + + if (result === true) { + return -1; + } + + return 1; + }); +} + export default { reverse, foreach, @@ -243,4 +263,5 @@ export default { all, any, splitwith, + sort, }; From a4edc213aabba8429db42c57a4f81d32eff8f82d Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Thu, 29 Jun 2017 02:50:34 -0500 Subject: [PATCH 583/860] Add maps functions found in Map module --- src/javascript/lib/core/erlang_compat/maps.js | 135 +++++++++++++++++- 1 file changed, 134 insertions(+), 1 deletion(-) diff --git a/src/javascript/lib/core/erlang_compat/maps.js b/src/javascript/lib/core/erlang_compat/maps.js index fdda87d3..c29c795e 100644 --- a/src/javascript/lib/core/erlang_compat/maps.js +++ b/src/javascript/lib/core/erlang_compat/maps.js @@ -1,12 +1,14 @@ // http://erlang.org/doc/man/maps.html import ErlangTypes from 'erlang-types'; +import erlang from './erlang'; const OK = Symbol.for('ok'); const ERROR = Symbol.for('error'); const BADMAP = Symbol.for('badmap'); +const BADKEY = Symbol.for('badkey'); function find(key, map) { - if (map instanceof Object === false) { + if (erlang.is_map(map) === false) { return new ErlangTypes.Tuple(BADMAP, map); } @@ -29,7 +31,138 @@ function fold(fun, init, map) { return acc; } +function remove(key, map1) { + if (erlang.is_map(map1) === false) { + return new ErlangTypes.Tuple(BADMAP, map1); + } + + const map2 = { ...map1 }; + + delete map2[key]; + + return map2; +} + +function to_list(map) { + if (erlang.is_map(map) === false) { + return new ErlangTypes.Tuple(BADMAP, map); + } + + return Object.entries(map).map(entry => { + return ErlangTypes.Tuple(...entry); + }); +} + +function from_list(list) { + return list.reduce((acc, item) => { + const [key, value] = item; + acc[key] = value; + + return acc; + }, {}); +} + +function keys(map) { + if (erlang.is_map(map) === false) { + return new ErlangTypes.Tuple(BADMAP, map); + } + + return Object.keys(map); +} + +function values(map) { + if (erlang.is_map(map) === false) { + return new ErlangTypes.Tuple(BADMAP, map); + } + + return Object.values(map); +} + +function is_key(key, map) { + return map.hasOwnProperty(key); +} + +function put(key, value, map1) { + if (erlang.is_map(map1) === false) { + return new ErlangTypes.Tuple(BADMAP, map1); + } + + const map2 = { ...map1, [key]: value }; + + return map2; +} + +function merge(map1, map2) { + if (erlang.is_map(map1) === false) { + return new ErlangTypes.Tuple(BADMAP, map1); + } + + if (erlang.is_map(map2) === false) { + return new ErlangTypes.Tuple(BADMAP, map2); + } + + return { ...map1, ...map2 }; +} + +function update(key, value, map1) { + if (erlang.is_map(map1) === false) { + return new ErlangTypes.Tuple(BADMAP, map1); + } + + if (is_key(key) === false) { + return new ErlangTypes.Tuple(BADKEY, key); + } + + return { ...map1, [key]: value }; +} + +function get(...args) { + const key = args[0]; + const map = args[1]; + + if (erlang.is_map(map) === false) { + return new ErlangTypes.Tuple(BADMAP, map); + } + + if (is_key(key)) { + return map[key]; + } + + if (args.length === 3) { + return args[2]; + } + + return new ErlangTypes.Tuple(BADKEY, key); +} + +function take(key, map1) { + if (erlang.is_map(map1) === false) { + return new ErlangTypes.Tuple(BADMAP, map1); + } + + if (!is_key(key)) { + return ERROR; + } + + const value = map1[key]; + const map2 = { ...map1 }; + delete map2[key]; + + return new ErlangTypes.Tuple(value, map2); +} + export default { find, fold, + remove, + to_list, + from_list, + keys, + values, + is_key, + put, + merge, + update, + get, + take, }; From 863df936c2bcbae067e19ede6ddf48c9e6d41c80 Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Thu, 29 Jun 2017 03:01:26 -0500 Subject: [PATCH 584/860] Remove spread operator calls with Object.assign --- src/javascript/lib/core/erlang_compat/maps.js | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/javascript/lib/core/erlang_compat/maps.js b/src/javascript/lib/core/erlang_compat/maps.js index c29c795e..7319dbf3 100644 --- a/src/javascript/lib/core/erlang_compat/maps.js +++ b/src/javascript/lib/core/erlang_compat/maps.js @@ -36,7 +36,7 @@ function remove(key, map1) { return new ErlangTypes.Tuple(BADMAP, map1); } - const map2 = { ...map1 }; + const map2 = Object.assign({}, map1); delete map2[key]; @@ -87,7 +87,7 @@ function put(key, value, map1) { return new ErlangTypes.Tuple(BADMAP, map1); } - const map2 = { ...map1, [key]: value }; + const map2 = Object.assign({}, map1, { [key]: value }); return map2; } @@ -101,7 +101,7 @@ function merge(map1, map2) { return new ErlangTypes.Tuple(BADMAP, map2); } - return { ...map1, ...map2 }; + return Object.assign({}, map1, map2); } function update(key, value, map1) { @@ -113,7 +113,7 @@ function update(key, value, map1) { return new ErlangTypes.Tuple(BADKEY, key); } - return { ...map1, [key]: value }; + return Object.assign({}, map1, { [key]: value }); } function get(...args) { @@ -145,7 +145,7 @@ function take(key, map1) { } const value = map1[key]; - const map2 = { ...map1 }; + const map2 = Object.assign({}, map1); delete map2[key]; return new ErlangTypes.Tuple(value, map2); From d9874df6516825e228474b5230f47ef9d43342c3 Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Fri, 30 Jun 2017 06:04:23 -0500 Subject: [PATCH 585/860] Fix index off by one issues. Add tuple functions --- .../lib/core/erlang_compat/erlang.js | 55 +++++++++++++++++++ .../lib/core/erlang_compat/lists.js | 14 ++--- 2 files changed, 62 insertions(+), 7 deletions(-) diff --git a/src/javascript/lib/core/erlang_compat/erlang.js b/src/javascript/lib/core/erlang_compat/erlang.js index 3ca28bf6..8eee209e 100644 --- a/src/javascript/lib/core/erlang_compat/erlang.js +++ b/src/javascript/lib/core/erlang_compat/erlang.js @@ -197,6 +197,54 @@ function is_binary(value) { return typeof value === 'string' || value instanceof String; } +function element(n, tuple) { + return tuple.get(n - 1); +} + +function setelement(index, tuple1, value) { + const tupleData = [...tuple1.data]; + + tupleData[index - 1] = value; + + return new ErlangTypes.Tuple(...tupleData); +} + +function make_tuple(arity, initialValue) { + const list = []; + + for (let i = 0; i < arity; i++) { + list.push(initialValue); + } + + return new ErlangTypes.Tuple(...list); +} + +function insert_element(index, tuple, term) { + const list = [...tuple.data]; + list.splice(index - 1, 0, term); + + return new ErlangTypes.Tuple(...list); +} + +function append_element(tuple, term) { + const list = [...tuple.data]; + list.push(term); + + return new ErlangTypes.Tuple(...list); +} + +function delete_element(index, tuple) { + const list = [...tuple.data]; + list.splice(index - 1, 1); + + return new ErlangTypes.Tuple(...list); +} + +function tuple_to_list(tuple) { + const list = [...tuple.data]; + return list; +} + export default { atom_to_binary, binary_to_atom, @@ -239,4 +287,11 @@ export default { is_tuple, is_atom, is_binary, + element, + setelement, + make_tuple, + insert_element, + append_element, + delete_element, + tuple_to_list, }; diff --git a/src/javascript/lib/core/erlang_compat/lists.js b/src/javascript/lib/core/erlang_compat/lists.js index 52db1b08..b06cc30d 100644 --- a/src/javascript/lib/core/erlang_compat/lists.js +++ b/src/javascript/lib/core/erlang_compat/lists.js @@ -45,7 +45,7 @@ function foldr(fun, acc0, list) { function keyfind(key, n, tupleList) { for (const tuple of tupleList) { - if (tuple.get(n) === key) { + if (tuple.get(n - 1) === key) { return tuple; } } @@ -65,7 +65,7 @@ function keyreplace(key, n, tupleList, newTuple) { const newTupleList = [...tupleList]; for (let index = 0; index < newTupleList.length; index++) { - if (newTupleList[index].get(n) === key) { + if (newTupleList[index].get(n - 1) === key) { newTupleList[index] = newTuple; return newTupleList; } @@ -78,9 +78,9 @@ function keysort(n, tupleList) { const newTupleList = [...tupleList]; return newTupleList.sort((a, b) => { - if (a.get(n) < b.get(n)) { + if (a.get(n - 1) < b.get(n - 1)) { return -1; - } else if (a.get(n) > b.get(n)) { + } else if (a.get(n - 1) > b.get(n - 1)) { return 1; } @@ -92,7 +92,7 @@ function keystore(key, n, tupleList, newTuple) { const newTupleList = [...tupleList]; for (let index = 0; index < newTupleList.length; index++) { - if (newTupleList[index].get(n) === key) { + if (newTupleList[index].get(n - 1) === key) { newTupleList[index] = newTuple; return newTupleList; } @@ -106,7 +106,7 @@ function keydelete(key, n, tupleList) { let deleted = false; for (let index = 0; index < tupleList.length; index++) { - if (deleted === false && tupleList[index].get(n) === key) { + if (deleted === false && tupleList[index].get(n - 1) === key) { deleted = true; } else { newTupleList.push(tupleList[index]); @@ -121,7 +121,7 @@ function keytake(key, n, tupleList) { if (result !== false) { return new ErlangTypes.Tuple( - result.get(n), + result.get(n - 1), result, keydelete(key, n, tupleList) ); From 739208aa2602d2aafb52b11b804f2cfb11ad1b3d Mon Sep 17 00:00:00 2001 From: Craig Spaeth Date: Sat, 1 Jul 2017 13:16:55 -0400 Subject: [PATCH 586/860] Use spread operator to fix cond function --- src/javascript/lib/core/special_forms.js | 2 +- src/javascript/tests/cond.spec.js | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/javascript/lib/core/special_forms.js b/src/javascript/lib/core/special_forms.js index b093fee6..fbb830cd 100644 --- a/src/javascript/lib/core/special_forms.js +++ b/src/javascript/lib/core/special_forms.js @@ -4,7 +4,7 @@ function _case(condition, clauses) { return Core.Patterns.defmatch(...clauses)(condition); } -function cond(clauses) { +function cond(...clauses) { for (const clause of clauses) { if (clause[0]) { return clause[1](); diff --git a/src/javascript/tests/cond.spec.js b/src/javascript/tests/cond.spec.js index c5d66aed..6d1d87e8 100644 --- a/src/javascript/tests/cond.spec.js +++ b/src/javascript/tests/cond.spec.js @@ -10,7 +10,7 @@ test('cond', t => { [true, () => 'This will'], ]; - const result = SpecialForms.cond(clauses); + const result = SpecialForms.cond(...clauses); t.is(result, 'This will'); }); From 9e8dc4203e76bd537f0c3cbbccc4eb2a5df8b769 Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Sat, 1 Jul 2017 17:00:33 -0500 Subject: [PATCH 587/860] Update confusing comment. Fix some warnings in Module --- lib/elixir_script/passes/translate/module.ex | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/lib/elixir_script/passes/translate/module.ex b/lib/elixir_script/passes/translate/module.ex index c46dc80e..b6184ac2 100644 --- a/lib/elixir_script/passes/translate/module.ex +++ b/lib/elixir_script/passes/translate/module.ex @@ -1,7 +1,7 @@ defmodule ElixirScript.Translate.Module do @moduledoc false alias ESTree.Tools.Builder, as: J - alias ElixirScript.Translate.{Function, Form, Identifier} + alias ElixirScript.Translate.Function alias ElixirScript.State, as: ModuleState @doc """ @@ -28,7 +28,7 @@ defmodule ElixirScript.Translate.Module do module: module, pid: pid } - + # Filter so that we only have the # Used functions to compile reachable_defs = Enum.filter(defs, fn @@ -52,8 +52,7 @@ defmodule ElixirScript.Translate.Module do combined_defs = combine_defs(used_defs) exports = make_exports(module, combined_defs) - # Don't skip compilation and output of modules that don't have - # any public functions + # If there are no public exports, skip compilation case exports do %ESTree.ObjectExpression{ properties: [] } -> nil @@ -85,7 +84,7 @@ defmodule ElixirScript.Translate.Module do defp make_exports(module, reachable_defs) do exports = Enum.reduce(reachable_defs, [], fn - {{name, arity}, :def, _, _}, list -> + {{name, _arity}, :def, _, _}, list -> function_name = ElixirScript.Translate.Identifier.make_identifier(name) list ++ [J.property(function_name, function_name, :init, true)] _, list -> From c9ef9084eb7d42c0e779c2864ae6b0b1c6fc9da1 Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Sat, 1 Jul 2017 17:05:04 -0500 Subject: [PATCH 588/860] Update README.md --- README.md | 48 ++++++++++++++---------------------------------- 1 file changed, 14 insertions(+), 34 deletions(-) diff --git a/README.md b/README.md index a3a106c0..5f78b35d 100644 --- a/README.md +++ b/README.md @@ -14,47 +14,27 @@ Usage Please check the [Getting Started Guide](GettingStarted.md) for usage -FAQ, Limitations -======== - -Please check the [FAQ](FAQ.md) - - Development =========== -Clone the repo - - git clone git@github.com:bryanjos/elixirscript.git - -Get dependencies +```bash +# Clone the repo +git clone git@github.com:bryanjos/elixirscript.git - mix deps.get - yarn +#Get dependencies +mix deps.get +yarn -Create Elixir.Bootstrap.js - - yarn build - -Compile - - mix compile - -Test - - mix test - yarn test - +# Create Elixir.Bootstrap.js +yarn build -Build -============= - MIX_ENV=prod mix do clean, compile, dist +# Compile +mix compile -This will build a tarball in the dist folder. -By default the escript built will look into the folder above it for the -core JavaScript files needed for ElixirScript. To change the location, -update the `lib_path` config variable in the `:elixir_script` config block -to the path to look in and then do a clean build. +# Test +mix test +yarn test +``` Communication ======== From c655d9951d8a6602873e58c2be03ca54f13ea7fc Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Sat, 1 Jul 2017 17:21:19 -0500 Subject: [PATCH 589/860] Fix a bunch of lints --- lib/elixir_script/beam.ex | 6 +-- lib/elixir_script/cli.ex | 10 ++--- lib/elixir_script/compiler.ex | 4 +- lib/elixir_script/lib/string.ex | 3 -- lib/elixir_script/module_systems/common.ex | 2 +- lib/elixir_script/module_systems/namespace.ex | 6 +-- lib/elixir_script/module_systems/umd.ex | 6 ++- .../passes/find_used_functions.ex | 14 +++---- lib/elixir_script/passes/find_used_modules.ex | 18 ++++----- lib/elixir_script/passes/output.ex | 8 ++-- lib/elixir_script/passes/output/js_module.ex | 2 +- lib/elixir_script/passes/translate/form.ex | 4 +- .../passes/translate/forms/js.ex | 2 +- .../passes/translate/forms/map.ex | 2 +- .../passes/translate/forms/pattern.ex | 4 +- .../translate/forms/pattern/patterns.ex | 2 +- .../passes/translate/forms/receive.ex | 2 +- .../passes/translate/forms/remote.ex | 38 +++++++++---------- .../passes/translate/function.ex | 18 ++++++--- .../passes/translate/identifier.ex | 2 +- lib/elixir_script/passes/translate/module.ex | 8 ++-- .../passes/translate/protocol.ex | 2 +- lib/elixir_script/state.ex | 6 +-- lib/mix/tasks/compile.elixir_script.ex | 2 +- lib/mix/tasks/elixirscript.watch.ex | 4 +- 25 files changed, 90 insertions(+), 85 deletions(-) diff --git a/lib/elixir_script/beam.ex b/lib/elixir_script/beam.ex index f9611c5a..a5a3aa46 100644 --- a/lib/elixir_script/beam.ex +++ b/lib/elixir_script/beam.ex @@ -8,8 +8,8 @@ defmodule ElixirScript.Beam do all the protocol implementations """ @spec debug_info(atom) :: {:ok | :error, map | binary} - def debug_info(module) - + def debug_info(module) + #Replacing String module with our ElixirScript's version def debug_info(String) do case debug_info(ElixirScript.String) do @@ -19,7 +19,7 @@ defmodule ElixirScript.Beam do e end end - + def debug_info(module) when is_atom(module) do #TODO: Get modified date from _beam_path to check for cached version? with {_, beam, _beam_path} <- :code.get_object_code(module), diff --git a/lib/elixir_script/cli.ex b/lib/elixir_script/cli.ex index 9bd4daea..9fc992ba 100644 --- a/lib/elixir_script/cli.ex +++ b/lib/elixir_script/cli.ex @@ -5,17 +5,17 @@ defmodule ElixirScript.CLI do @switches [ output: :string, - help: :boolean, + help: :boolean, version: :boolean, - watch: :boolean, - format: :string, + watch: :boolean, + format: :string, js_module: [:string, :keep] ] @aliases [ o: :output, - h: :help, - v: :version, + h: :help, + v: :version, f: :format ] diff --git a/lib/elixir_script/compiler.ex b/lib/elixir_script/compiler.ex index 5dc1195d..79fe7238 100644 --- a/lib/elixir_script/compiler.ex +++ b/lib/elixir_script/compiler.ex @@ -21,7 +21,7 @@ defmodule ElixirScript.Compiler do IO.puts "Finding used functions" ElixirScript.FindUsedFunctions.execute(entry_modules, pid) - + IO.puts "Compiling" modules = ElixirScript.State.list_modules(pid) ElixirScript.Translate.execute(modules, pid) @@ -29,7 +29,7 @@ defmodule ElixirScript.Compiler do IO.puts "Building Output" modules = ElixirScript.State.list_modules(pid) result = ElixirScript.Output.execute(modules, pid) - + ElixirScript.State.stop(pid) result diff --git a/lib/elixir_script/lib/string.ex b/lib/elixir_script/lib/string.ex index 6ace3e43..1ad3d9bf 100644 --- a/lib/elixir_script/lib/string.ex +++ b/lib/elixir_script/lib/string.ex @@ -137,7 +137,6 @@ defmodule ElixirScript.String do end end - def ends_with?(str, suffix) when is_binary(suffix) do str.endsWith(suffix) end @@ -163,7 +162,6 @@ defmodule ElixirScript.String do str.repeat(n) end - def contains?(str, s) when is_binary(s) do str.indexOf(s) > -1 end @@ -185,7 +183,6 @@ defmodule ElixirScript.String do end end - def codepoints(str) do do_codepoints(str, []) end diff --git a/lib/elixir_script/module_systems/common.ex b/lib/elixir_script/module_systems/common.ex index f4c00837..9554e687 100644 --- a/lib/elixir_script/module_systems/common.ex +++ b/lib/elixir_script/module_systems/common.ex @@ -19,7 +19,7 @@ defmodule ElixirScript.ModuleSystems.Common do end defp import_module(module_name, from) do - js_module_name = ElixirScript.Translate.Identifier.make_namespace_members(module_name) + js_module_name = ElixirScript.Translate.Identifier.make_namespace_members(module_name) do_import_module(js_module_name, from) end diff --git a/lib/elixir_script/module_systems/namespace.ex b/lib/elixir_script/module_systems/namespace.ex index 200ae0c3..4a4cf96d 100644 --- a/lib/elixir_script/module_systems/namespace.ex +++ b/lib/elixir_script/module_systems/namespace.ex @@ -22,7 +22,7 @@ defmodule ElixirScript.ModuleSystems.Namespace do JS.identifier(:build_namespace) ) ) - ) + ) end defp make_namespace_body(module_name, body, exports) do @@ -35,7 +35,7 @@ defmodule ElixirScript.ModuleSystems.Namespace do exports = if is_nil(exports) do JS.object_expression([]) - else + else exports end @@ -44,7 +44,7 @@ defmodule ElixirScript.ModuleSystems.Namespace do exports ) - declaration = JS.variable_declaration([declarator], :const) + declaration = JS.variable_declaration([declarator], :const) assign = JS.assignment_expression( :=, diff --git a/lib/elixir_script/module_systems/umd.ex b/lib/elixir_script/module_systems/umd.ex index 4aefe6d3..e9894c24 100644 --- a/lib/elixir_script/module_systems/umd.ex +++ b/lib/elixir_script/module_systems/umd.ex @@ -3,7 +3,9 @@ defmodule ElixirScript.ModuleSystems.UMD do alias ESTree.Tools.Builder, as: JS def build(imports, js_imports, body, exports) do - module_imports = Enum.map(imports, fn {module, path} -> import_module(module, path) end) + module_imports = Enum.map(imports, fn + {module, path} -> import_module(module, path) + end) imports = js_imports |> Enum.map(fn @@ -17,7 +19,7 @@ defmodule ElixirScript.ModuleSystems.UMD do end defp import_module(module_name, from) do - js_module_name = ElixirScript.Translate.Identifier.make_namespace_members(module_name) + js_module_name = ElixirScript.Translate.Identifier.make_namespace_members(module_name) {js_module_name, JS.literal(from)} end diff --git a/lib/elixir_script/passes/find_used_functions.ex b/lib/elixir_script/passes/find_used_functions.ex index e656a580..af659000 100644 --- a/lib/elixir_script/passes/find_used_functions.ex +++ b/lib/elixir_script/passes/find_used_functions.ex @@ -1,6 +1,6 @@ defmodule ElixirScript.FindUsedFunctions do @moduledoc false - alias ElixirScript.State, as: ModuleState + alias ElixirScript.State, as: ModuleState @doc """ Takes a list of entry modules and finds modules they use along with @@ -25,12 +25,12 @@ defmodule ElixirScript.FindUsedFunctions do defp walk_module(module, pid) do %{ - attributes: _attrs, + attributes: _attrs, compile_opts: _compile_opts, definitions: defs, file: _file, - line: _line, - module: ^module, + line: _line, + module: ^module, unreachable: unreachable } = ModuleState.get_module(pid, module) @@ -48,7 +48,7 @@ defmodule ElixirScript.FindUsedFunctions do Enum.each(reachable_defs, fn({name, _type, _, _clauses}) -> ModuleState.add_used(state.pid, module, name) end) - + Enum.each(reachable_defs, &walk(&1, state)) end @@ -171,7 +171,7 @@ defmodule ElixirScript.FindUsedFunctions do defp walk({:receive, _context, blocks}, state) do do_block = Keyword.get(blocks, :do) - after_block = Keyword.get(blocks, :after, nil) + after_block = Keyword.get(blocks, :after, nil) walk_block(do_block, state) @@ -234,7 +234,7 @@ defmodule ElixirScript.FindUsedFunctions do ElixirScript.Translate.Module.is_elixir_module(module) -> walk_module(module, function, length(params), state.pid) true -> - nil + nil end walk(params, state) diff --git a/lib/elixir_script/passes/find_used_modules.ex b/lib/elixir_script/passes/find_used_modules.ex index fcdadbc0..5c7cd5d7 100644 --- a/lib/elixir_script/passes/find_used_modules.ex +++ b/lib/elixir_script/passes/find_used_modules.ex @@ -1,6 +1,6 @@ defmodule ElixirScript.FindUsedModules do @moduledoc false - alias ElixirScript.State, as: ModuleState + alias ElixirScript.State, as: ModuleState @doc """ Takes a list of entry modules and finds modules they use. @@ -27,12 +27,12 @@ defmodule ElixirScript.FindUsedModules do defp walk_module(module, info, pid) do %{ - attributes: _attrs, + attributes: _attrs, compile_opts: _compile_opts, definitions: defs, file: _file, - line: _line, - module: ^module, + line: _line, + module: ^module, unreachable: unreachable } = info @@ -65,9 +65,9 @@ defmodule ElixirScript.FindUsedModules do functions = Enum.map(first_implementation_functions, fn { name, _, _, _} -> name end) ModuleState.put_module(pid, module, %{protocol: true, impls: impls, functions: functions}) - + Enum.each(implementations, fn {impl, info} -> - walk_module(impl, info, pid) + walk_module(impl, info, pid) end) end @@ -180,7 +180,7 @@ defmodule ElixirScript.FindUsedModules do defp walk({:receive, _context, blocks}, state) do do_block = Keyword.get(blocks, :do) - after_block = Keyword.get(blocks, :after, nil) + after_block = Keyword.get(blocks, :after, nil) walk_block(do_block, state) @@ -246,7 +246,7 @@ defmodule ElixirScript.FindUsedModules do end true -> walk(module, state) - walk(function, state) + walk(function, state) end end @@ -255,7 +255,7 @@ defmodule ElixirScript.FindUsedModules do end defp walk({function, _, params}, state) when is_list(params) do - walk(function, state) + walk(function, state) walk(params, state) end diff --git a/lib/elixir_script/passes/output.ex b/lib/elixir_script/passes/output.ex index f5804cc8..f4c1cb4a 100644 --- a/lib/elixir_script/passes/output.ex +++ b/lib/elixir_script/passes/output.ex @@ -11,8 +11,8 @@ defmodule ElixirScript.Output do @spec execute([atom], pid) :: nil def execute(modules, pid) do modules = Enum.filter_map(modules, fn {_, info} -> Map.has_key?(info, :js_ast) end, - fn {_module, info} -> - info.js_ast + fn {_module, info} -> + info.js_ast end ) @@ -58,7 +58,7 @@ defmodule ElixirScript.Output do code end - defp output(code, :stdout) do + defp output(code, :stdout) do IO.puts(code) end @@ -78,6 +78,6 @@ defmodule ElixirScript.Output do path _ -> Path.join([path, @generated_name]) - end + end end end \ No newline at end of file diff --git a/lib/elixir_script/passes/output/js_module.ex b/lib/elixir_script/passes/output/js_module.ex index c0aa3346..8be907ca 100644 --- a/lib/elixir_script/passes/output/js_module.ex +++ b/lib/elixir_script/passes/output/js_module.ex @@ -111,7 +111,7 @@ defmodule ElixirScript.Output.JSModule do J.call_expression( J.member_expression( J.identifier("Symbol"), - J.identifier("for") + J.identifier("for") ), [J.literal(ref.name)] ), diff --git a/lib/elixir_script/passes/translate/form.ex b/lib/elixir_script/passes/translate/form.ex index 662ee8be..f03f6b84 100644 --- a/lib/elixir_script/passes/translate/form.ex +++ b/lib/elixir_script/passes/translate/form.ex @@ -144,10 +144,10 @@ defmodule ElixirScript.Translate.Form do def compile({:cond, _, [[do: clauses]]}, state) do processed_clauses = Enum.map(clauses, fn({:->, _, [clause, clause_body]}) -> { translated_body, state } = ElixirScript.Translate.Function.compile_block(clause_body, state) - + translated_body = translated_body |> Clause.return_last_statement - + translated_body = J.arrow_function_expression([], [], J.block_statement(translated_body)) { translated_clause, _ } = compile(hd(clause), state) diff --git a/lib/elixir_script/passes/translate/forms/js.ex b/lib/elixir_script/passes/translate/forms/js.ex index 49da8f7b..9cf77604 100644 --- a/lib/elixir_script/passes/translate/forms/js.ex +++ b/lib/elixir_script/passes/translate/forms/js.ex @@ -91,4 +91,4 @@ defmodule ElixirScript.Translate.Forms.JS do {ast, state} end -end \ No newline at end of file +end diff --git a/lib/elixir_script/passes/translate/forms/map.ex b/lib/elixir_script/passes/translate/forms/map.ex index 5bc27ba6..28518a92 100644 --- a/lib/elixir_script/passes/translate/forms/map.ex +++ b/lib/elixir_script/passes/translate/forms/map.ex @@ -15,7 +15,7 @@ defmodule ElixirScript.Translate.Forms.Map do [ J.object_expression([]), map, - data + data ] ) diff --git a/lib/elixir_script/passes/translate/forms/pattern.ex b/lib/elixir_script/passes/translate/forms/pattern.ex index a96f589f..93b7c6fb 100644 --- a/lib/elixir_script/passes/translate/forms/pattern.ex +++ b/lib/elixir_script/passes/translate/forms/pattern.ex @@ -19,7 +19,7 @@ defmodule ElixirScript.Translate.Forms.Pattern do x, { patterns, params } -> {pattern, param} = process_pattern(x, state) { patterns ++ List.wrap(pattern), params ++ List.wrap(param) } - end) + end) end defp update_env({ patterns, params }, state) do @@ -102,7 +102,7 @@ defmodule ElixirScript.Translate.Forms.Pattern do { tail_patterns, tail_params } = process_pattern(tail, state) params = head_params ++ tail_params - { [PM.head_tail(hd(head_patterns), hd(tail_patterns))], params } + { [PM.head_tail(hd(head_patterns), hd(tail_patterns))], params } end defp process_pattern({{:., _, [:erlang, :++]}, context, [head, tail]}, state) do diff --git a/lib/elixir_script/passes/translate/forms/pattern/patterns.ex b/lib/elixir_script/passes/translate/forms/pattern/patterns.ex index 70154334..21f313f5 100644 --- a/lib/elixir_script/passes/translate/forms/pattern/patterns.ex +++ b/lib/elixir_script/passes/translate/forms/pattern/patterns.ex @@ -2,7 +2,7 @@ defmodule ElixirScript.Translate.Forms.Pattern.Patterns do @moduledoc false alias ESTree.Tools.Builder, as: J - + @patterns J.member_expression( J.member_expression( J.identifier("Bootstrap"), diff --git a/lib/elixir_script/passes/translate/forms/receive.ex b/lib/elixir_script/passes/translate/forms/receive.ex index 6a51bf24..a23897e5 100644 --- a/lib/elixir_script/passes/translate/forms/receive.ex +++ b/lib/elixir_script/passes/translate/forms/receive.ex @@ -28,4 +28,4 @@ defmodule ElixirScript.Translate.Forms.Receive do { ast, state } end -end \ No newline at end of file +end diff --git a/lib/elixir_script/passes/translate/forms/remote.ex b/lib/elixir_script/passes/translate/forms/remote.ex index b6c8c192..213f9a00 100644 --- a/lib/elixir_script/passes/translate/forms/remote.ex +++ b/lib/elixir_script/passes/translate/forms/remote.ex @@ -27,67 +27,67 @@ defmodule ElixirScript.Translate.Forms.Remote do def compile({:., _, [:erlang, :+]}, state) do ast = erlang_compat_function("erlang", "plus") - { ast, state } + { ast, state } end def compile({:., _, [:erlang, :-]}, state) do ast = erlang_compat_function("erlang", "minus") - { ast, state } + { ast, state } end def compile({:., _, [:erlang, :*]}, state) do ast = erlang_compat_function("erlang", "multiply") - { ast, state } + { ast, state } end def compile({:., _, [:erlang, :/]}, state) do ast = erlang_compat_function("erlang", "div") - { ast, state } + { ast, state } end def compile({:., _, [:erlang, :==]}, state) do ast = erlang_compat_function("erlang", "equal") - { ast, state } + { ast, state } end def compile({:., _, [:erlang, :>]}, state) do ast = erlang_compat_function("erlang", "greaterThan") - { ast, state } + { ast, state } end def compile({:., _, [:erlang, :>=]}, state) do ast = erlang_compat_function("erlang", "greaterThanOrEqualTo") - { ast, state } + { ast, state } end def compile({:., _, [:erlang, :"/="]}, state) do ast = erlang_compat_function("erlang", "doesNotEqual") - { ast, state } + { ast, state } end def compile({:., _, [:erlang, :"<"]}, state) do ast = erlang_compat_function("erlang", "lessThan") - { ast, state } + { ast, state } end def compile({:., _, [:erlang, :"=<"]}, state) do ast = erlang_compat_function("erlang", "lessThanOrEqualTo") - { ast, state } + { ast, state } end def compile({:., _, [:erlang, :"=:="]}, state) do ast = erlang_compat_function("erlang", "strictlyEqual") - { ast, state } + { ast, state } end def compile({:., _, [:erlang, :"=/="]}, state) do ast = erlang_compat_function("erlang", "doesNotStrictlyEqual") - { ast, state } + { ast, state } end def compile({:., _, [:erlang, function]}, state) when function in [:andalso, :and] do ast = erlang_compat_function("erlang", "and") - { ast, state } + { ast, state } end def compile({:., _, [:erlang, function]}, state) when function in [:orelse, :or] do @@ -97,12 +97,12 @@ defmodule ElixirScript.Translate.Forms.Remote do def compile({:., _, [:erlang, :++]}, state) do ast = erlang_compat_function("erlang", "list_concatenation") - { ast, state } + { ast, state } end def compile({:., _, [:erlang, :--]}, state) do ast = erlang_compat_function("erlang", "list_substraction") - { ast, state } + { ast, state } end def compile({:., _, [module, function]}, state) when module in @erlang_modules do @@ -123,12 +123,12 @@ defmodule ElixirScript.Translate.Forms.Remote do def compile({:., _, [function_name]}, state) do Form.compile(function_name, state) end - + def compile({:., _, [module, function]}, state) do function_name = if ElixirScript.Translate.Module.is_js_module(module, state) do ElixirScript.Translate.Identifier.make_extern_function_name(function) else - ElixirScript.Translate.Identifier.make_function_name(function) + ElixirScript.Translate.Identifier.make_function_name(function) end ast = J.member_expression( @@ -179,7 +179,7 @@ defmodule ElixirScript.Translate.Forms.Remote do ["JS" | rest] -> Identifier.make_namespace_members(rest) x -> - Identifier.make_namespace_members(x) + Identifier.make_namespace_members(x) end end @@ -193,6 +193,6 @@ defmodule ElixirScript.Translate.Forms.Remote do J.identifier(module) ), ElixirScript.Translate.Identifier.make_function_name(function) - ) + ) end end \ No newline at end of file diff --git a/lib/elixir_script/passes/translate/function.ex b/lib/elixir_script/passes/translate/function.ex index 23e13f20..a31a93fc 100644 --- a/lib/elixir_script/passes/translate/function.ex +++ b/lib/elixir_script/passes/translate/function.ex @@ -27,9 +27,12 @@ defmodule ElixirScript.Translate.Function do J.identifier("null") ) - arg_matches_declaration = J.variable_declaration([arg_matches_declarator], :let) + arg_matches_declaration = J.variable_declaration( + [arg_matches_declarator], + :let + ) - function_dec = J.arrow_function_expression( + function_dec = J.arrow_function_expression( [J.rest_element(J.identifier("__function_args__"))], [], J.block_statement([ @@ -59,10 +62,13 @@ defmodule ElixirScript.Translate.Function do J.identifier("null") ) - arg_matches_declaration = J.variable_declaration([arg_matches_declarator], :let) + arg_matches_declaration = J.variable_declaration( + [arg_matches_declarator], + :let + ) function_dec = J.function_declaration( - ElixirScript.Translate.Identifier.make_function_name(name), + ElixirScript.Translate.Identifier.make_function_name(name), [J.rest_element(J.identifier("__function_args__"))], [], J.block_statement([ @@ -105,7 +111,7 @@ defmodule ElixirScript.Translate.Function do ) end) |> Enum.reverse - |> Enum.reduce(nil, fn + |> Enum.reduce(nil, fn if_ast, nil -> if_ast if_ast, ast -> @@ -136,7 +142,7 @@ defmodule ElixirScript.Translate.Function do Form.compile!(body, state) end - body = body + body = body |> Clause.return_last_statement declarator = J.variable_declarator( diff --git a/lib/elixir_script/passes/translate/identifier.ex b/lib/elixir_script/passes/translate/identifier.ex index b5c287dd..e91c02d2 100644 --- a/lib/elixir_script/passes/translate/identifier.ex +++ b/lib/elixir_script/passes/translate/identifier.ex @@ -76,7 +76,7 @@ defmodule ElixirScript.Translate.Identifier do end def make_extern_function_name(name) do - J.identifier("#{name}") + J.identifier("#{name}") end end diff --git a/lib/elixir_script/passes/translate/module.ex b/lib/elixir_script/passes/translate/module.ex index b6184ac2..310b455d 100644 --- a/lib/elixir_script/passes/translate/module.ex +++ b/lib/elixir_script/passes/translate/module.ex @@ -14,12 +14,12 @@ defmodule ElixirScript.Translate.Module do def compile(module, info, pid) do %{ - attributes: attrs, + attributes: attrs, compile_opts: _compile_opts, definitions: defs, file: _file, - line: _line, - module: ^module, + line: _line, + module: ^module, unreachable: unreachable, used: used } = info @@ -58,7 +58,7 @@ defmodule ElixirScript.Translate.Module do nil _ -> { compiled_functions, _ } = Enum.map_reduce(combined_defs, state, &Function.compile(&1, &2)) - + js_ast = ElixirScript.ModuleSystems.Namespace.build( module, compiled_functions, diff --git a/lib/elixir_script/passes/translate/protocol.ex b/lib/elixir_script/passes/translate/protocol.ex index 0a02a17e..8dc5deaa 100644 --- a/lib/elixir_script/passes/translate/protocol.ex +++ b/lib/elixir_script/passes/translate/protocol.ex @@ -45,7 +45,7 @@ defmodule ElixirScript.Translate.Protocol do nil ) - ModuleState.put_module(pid, module, Map.put(info, :js_ast, hd(js_ast))) + ModuleState.put_module(pid, module, Map.put(info, :js_ast, hd(js_ast))) end defp build_implementations(impls, pid) do diff --git a/lib/elixir_script/state.ex b/lib/elixir_script/state.ex index b65c7189..f7e82449 100644 --- a/lib/elixir_script/state.ex +++ b/lib/elixir_script/state.ex @@ -6,7 +6,7 @@ defmodule ElixirScript.State do def start_link(compiler_opts) do Agent.start_link(fn -> %{ - compiler_opts: compiler_opts, + compiler_opts: compiler_opts, modules: Keyword.new, refs: [] } @@ -46,7 +46,7 @@ defmodule ElixirScript.State do def add_used(pid, module, {_function, _arity} = func) do Agent.update(pid, fn(state) -> module_info = Keyword.get(state.modules, module) - + used = Map.get(module_info, :used, []) used = used ++ [func] @@ -72,6 +72,6 @@ defmodule ElixirScript.State do def list_modules(pid) do Agent.get(pid, fn(state) -> state.modules - end) + end) end end \ No newline at end of file diff --git a/lib/mix/tasks/compile.elixir_script.ex b/lib/mix/tasks/compile.elixir_script.ex index eec94c8d..85a8871b 100644 --- a/lib/mix/tasks/compile.elixir_script.ex +++ b/lib/mix/tasks/compile.elixir_script.ex @@ -73,7 +73,7 @@ defmodule Mix.Tasks.Compile.ElixirScript do output: Keyword.get(elixirscript_config, :output), format: Keyword.get(elixirscript_config, :format), js_modules: Keyword.get(elixirscript_config, :js_modules, []) - ] + ] {input, opts} end diff --git a/lib/mix/tasks/elixirscript.watch.ex b/lib/mix/tasks/elixirscript.watch.ex index 5235d700..a2d654ef 100644 --- a/lib/mix/tasks/elixirscript.watch.ex +++ b/lib/mix/tasks/elixirscript.watch.ex @@ -23,10 +23,10 @@ defmodule Mix.Tasks.Elixirscript.Watch do def run(_) do Mix.Task.run "app.start" - {input, opts} = Mix.Tasks.Compile.ElixirScript.get_compiler_params() + {input, opts} = Mix.Tasks.Compile.ElixirScript.get_compiler_params() {:ok, _} = ElixirScript.Watcher.start_link( - input, + input, opts ) From 634cc0510e2d8ecf6f3688eafe90a3ed4e8176f3 Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Sat, 1 Jul 2017 22:42:04 -0500 Subject: [PATCH 590/860] Add erlang functions used in Kernel --- .../passes/translate/function.ex | 34 ++++---- .../lib/core/erlang_compat/erlang.js | 79 +++++++++++++++++++ 2 files changed, 96 insertions(+), 17 deletions(-) diff --git a/lib/elixir_script/passes/translate/function.ex b/lib/elixir_script/passes/translate/function.ex index a31a93fc..e98200b2 100644 --- a/lib/elixir_script/passes/translate/function.ex +++ b/lib/elixir_script/passes/translate/function.ex @@ -68,23 +68,23 @@ defmodule ElixirScript.Translate.Function do ) function_dec = J.function_declaration( - ElixirScript.Translate.Identifier.make_function_name(name), - [J.rest_element(J.identifier("__function_args__"))], - [], - J.block_statement([ - arg_matches_declaration, - clauses, - J.throw_statement( - J.new_expression( - J.member_expression( - patterns_ast(), - J.identifier("MatchError") - ), - [J.identifier("__function_args__")] - ) - ) - ]) - ) + ElixirScript.Translate.Identifier.make_function_name(name), + [J.rest_element(J.identifier("__function_args__"))], + [], + J.block_statement([ + arg_matches_declaration, + clauses, + J.throw_statement( + J.new_expression( + J.member_expression( + patterns_ast(), + J.identifier("MatchError") + ), + [J.identifier("__function_args__")] + ) + ) + ]) + ) { function_dec, state } end diff --git a/src/javascript/lib/core/erlang_compat/erlang.js b/src/javascript/lib/core/erlang_compat/erlang.js index 8eee209e..0fd5a647 100644 --- a/src/javascript/lib/core/erlang_compat/erlang.js +++ b/src/javascript/lib/core/erlang_compat/erlang.js @@ -245,6 +245,70 @@ function tuple_to_list(tuple) { return list; } +function abs(number) { + return Math.abs(number); +} + +function apply(...args) { + if (args.length === 2) { + return args[0].apply(this, ...args[1]); + } + + return args[0][atom_to_binary(args[1])].apply(this, ...args[2]); +} + +function binary_part(binary, start, length) { + return binary.substring(start, start + length); +} + +function bit_size(bitstring) { + return bitstring.bit_size; +} + +function byte_size(bitstring) { + return bitstring.byte_size; +} + +function hd(list) { + return list[0]; +} + +function length(list) { + return list.length; +} + +function make_ref() { + return new ErlangTypes.Reference(); +} + +function map_size(map) { + return Object.keys(map).length; +} + +function max(first, second) { + return Math.max(first, second); +} + +function min(first, second) { + return Math.min(first, second); +} + +function round(number) { + return Math.round(number); +} + +function tl(list) { + return list.slice(1); +} + +function trunc(number) { + return Math.trunc(number); +} + +function tuple_size(tuple) { + return tuple.length; +} + export default { atom_to_binary, binary_to_atom, @@ -294,4 +358,19 @@ export default { append_element, delete_element, tuple_to_list, + abs, + apply, + binary_part, + bit_size, + byte_size, + hd, + length, + make_ref, + map_size, + max, + min, + round, + tl, + trunc, + tuple_size }; From cc32253e64ff18128262c0e63639b0c36a48ad0c Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Sun, 2 Jul 2017 20:34:42 -0500 Subject: [PATCH 591/860] Fix some lints. Fixed implementations of some map functions --- .../passes/translate/forms/pattern.ex | 7 ++-- src/javascript/lib/core/erlang_compat/maps.js | 34 +++++++++++++++---- test/support/main.ex | 3 +- 3 files changed, 33 insertions(+), 11 deletions(-) diff --git a/lib/elixir_script/passes/translate/forms/pattern.ex b/lib/elixir_script/passes/translate/forms/pattern.ex index 93b7c6fb..134b8ca8 100644 --- a/lib/elixir_script/passes/translate/forms/pattern.ex +++ b/lib/elixir_script/passes/translate/forms/pattern.ex @@ -4,10 +4,12 @@ defmodule ElixirScript.Translate.Forms.Pattern do alias ElixirScript.Translate.Form alias ElixirScript.Translate.Forms.Bitstring - @moduledoc """ + @moduledoc false + + @doc """ Handles all pattern matching translations """ - + @spec compile(list(), map()) :: { list(), list(), map() } def compile(patterns, state) do patterns |> do_compile(state) @@ -40,6 +42,7 @@ defmodule ElixirScript.Translate.Forms.Pattern do { patterns, params, state } end + @spec get_variable_name(atom(), map()) :: atom() def get_variable_name(function, state) do number = Map.get(state.vars, function) String.to_atom("#{function}#{number}") diff --git a/src/javascript/lib/core/erlang_compat/maps.js b/src/javascript/lib/core/erlang_compat/maps.js index 7319dbf3..6178eba7 100644 --- a/src/javascript/lib/core/erlang_compat/maps.js +++ b/src/javascript/lib/core/erlang_compat/maps.js @@ -24,7 +24,7 @@ function find(key, map) { function fold(fun, init, map) { let acc = init; - for (const [key, value] of Object.entries(map)) { + for (const [key, value] of to_list(map)) { acc = fun(key, value, acc); } @@ -48,9 +48,13 @@ function to_list(map) { return new ErlangTypes.Tuple(BADMAP, map); } - return Object.entries(map).map(entry => { - return ErlangTypes.Tuple(...entry); - }); + const list = []; + + for (const key of keys(map)) { + list.push(new ErlangTypes.Tuple(key, map[key])); + } + + return list; } function from_list(list) { @@ -67,7 +71,17 @@ function keys(map) { return new ErlangTypes.Tuple(BADMAP, map); } - return Object.keys(map); + const keys = []; + + for (const key of Object.getOwnPropertySymbols(map)) { + keys.push(key); + } + + for (const key of Object.getOwnPropertyNames(map)) { + keys.push(key); + } + + return keys; } function values(map) { @@ -75,7 +89,13 @@ function values(map) { return new ErlangTypes.Tuple(BADMAP, map); } - return Object.values(map); + const theValues = []; + + for (const key of keys(map)) { + theValues.push(map[key]); + } + + return theValues; } function is_key(key, map) { @@ -164,5 +184,5 @@ export default { merge, update, get, - take, + take }; diff --git a/test/support/main.ex b/test/support/main.ex index ec70a46a..64562538 100644 --- a/test/support/main.ex +++ b/test/support/main.ex @@ -2,7 +2,6 @@ defmodule Main do def start(:normal, [callback]) do callback.("started") - JS.console.log String.valid?("a") - JS.console.log String.valid?(1) + Enum.each(1..3, fn x -> JS.console.log(x) end) end end From 71356dc3d82a75b7c426b4915c423416c5e1adc6 Mon Sep 17 00:00:00 2001 From: Artsy Date: Mon, 3 Jul 2017 18:09:46 -0400 Subject: [PATCH 592/860] Fixed compilation of functions that return array values --- lib/elixir_script/passes/translate/function.ex | 2 +- test/passes/translate/form_test.exs | 13 +++++++++++++ 2 files changed, 14 insertions(+), 1 deletion(-) diff --git a/lib/elixir_script/passes/translate/function.ex b/lib/elixir_script/passes/translate/function.ex index e98200b2..0c74fdd8 100644 --- a/lib/elixir_script/passes/translate/function.ex +++ b/lib/elixir_script/passes/translate/function.ex @@ -137,7 +137,7 @@ defmodule ElixirScript.Translate.Function do List.flatten(list) b when is_list(b) -> {list, _} = Enum.map_reduce(b, state, &Form.compile(&1, &2)) - List.flatten(list) + J.array_expression(list) _ -> Form.compile!(body, state) end diff --git a/test/passes/translate/form_test.exs b/test/passes/translate/form_test.exs index 50dcd93f..f7106473 100644 --- a/test/passes/translate/form_test.exs +++ b/test/passes/translate/form_test.exs @@ -118,4 +118,17 @@ defmodule ElixirScript.Translate.Forms.Test do ) end + test "function returning an array" do + ast = {:fn, [], [{:foo, [], [], [1, 2, 3]}]} + state = %{} + + {js_ast, _} = Form.compile(ast, state) + return_statement = Enum.at(Enum.at(js_ast.body.body, 1).consequent.body, 1) + + assert return_statement.argument == J.array_expression([ + J.literal(1), + J.literal(2), + J.literal(3) + ]) + end end \ No newline at end of file From 20f893dd61ff2d9e5a438a9fc9b85133c1900e59 Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Tue, 4 Jul 2017 15:47:53 -0500 Subject: [PATCH 593/860] Remove a bunch of warnings --- lib/elixir_script/cli.ex | 4 ++-- lib/elixir_script/module_systems/common.ex | 2 -- lib/elixir_script/module_systems/namespace.ex | 6 +++--- .../passes/find_used_functions.ex | 2 +- lib/elixir_script/passes/find_used_modules.ex | 4 ++-- lib/elixir_script/passes/output.ex | 5 +++-- lib/elixir_script/passes/output/js_module.ex | 6 +++--- lib/elixir_script/passes/translate.ex | 3 --- lib/elixir_script/passes/translate/form.ex | 9 ++++----- .../passes/translate/forms/bitstring.ex | 4 ++-- .../passes/translate/forms/for.ex | 4 ++-- lib/elixir_script/passes/translate/forms/js.ex | 2 +- .../passes/translate/forms/match.ex | 4 ++-- .../passes/translate/forms/remote.ex | 2 +- .../passes/translate/forms/try.ex | 4 ++-- lib/elixir_script/passes/translate/function.ex | 18 ++---------------- lib/elixir_script/passes/translate/module.ex | 3 +-- lib/elixir_script/passes/translate/protocol.ex | 11 +++++------ lib/elixir_script/watcher.ex | 4 ++-- lib/mix/tasks/compile.elixir_script.ex | 13 +++---------- 20 files changed, 41 insertions(+), 69 deletions(-) diff --git a/lib/elixir_script/cli.ex b/lib/elixir_script/cli.ex index 9fc992ba..fd27b355 100644 --- a/lib/elixir_script/cli.ex +++ b/lib/elixir_script/cli.ex @@ -54,7 +54,7 @@ defmodule ElixirScript.CLI do end def process(:help) do - IO.write help_message + IO.write help_message() end def process(:version) do @@ -101,7 +101,7 @@ defmodule ElixirScript.CLI do end defp handle_input(input) do - input = input + input |> Enum.map(fn(x) -> String.split(x, [" ", ","], trim: true) end) |> List.flatten |> Enum.map(fn(x) -> Module.concat([x]) end) diff --git a/lib/elixir_script/module_systems/common.ex b/lib/elixir_script/module_systems/common.ex index 9554e687..3236f92b 100644 --- a/lib/elixir_script/module_systems/common.ex +++ b/lib/elixir_script/module_systems/common.ex @@ -1,8 +1,6 @@ defmodule ElixirScript.ModuleSystems.Common do @moduledoc false alias ESTree.Tools.Builder, as: JS - alias ElixirScript.Translator - alias ElixirScript.Translator.{State, Utils} def build(imports, js_imports, body, exports) do module_imports = Enum.map(imports, fn {module, path} -> import_module(module, path) end) diff --git a/lib/elixir_script/module_systems/namespace.ex b/lib/elixir_script/module_systems/namespace.ex index 4a4cf96d..08e7aa4b 100644 --- a/lib/elixir_script/module_systems/namespace.ex +++ b/lib/elixir_script/module_systems/namespace.ex @@ -3,7 +3,7 @@ defmodule ElixirScript.ModuleSystems.Namespace do alias ESTree.Tools.Builder, as: JS alias ElixirScript.Translate.Identifier - def build(module_name, body, exports, env) do + def build(module_name, body, exports) do List.wrap(make_namespace_body(module_name, body, exports)) end @@ -28,7 +28,7 @@ defmodule ElixirScript.ModuleSystems.Namespace do defp make_namespace_body(module_name, body, exports) do values = module_name_function_call(module_name, "__exports") - _if = JS.if_statement( + js_if = JS.if_statement( values, JS.return_statement(values) ) @@ -62,7 +62,7 @@ defmodule ElixirScript.ModuleSystems.Namespace do JS.identifier("__load") ) - func_body = JS.block_statement([_if] ++ body ++ [declaration, assign] ++ exports) + func_body = JS.block_statement([js_if] ++ body ++ [declaration, assign] ++ exports) func = JS.function_expression([JS.identifier("Elixir")], [], func_body) JS.assignment_expression( diff --git a/lib/elixir_script/passes/find_used_functions.ex b/lib/elixir_script/passes/find_used_functions.ex index af659000..30d2919f 100644 --- a/lib/elixir_script/passes/find_used_functions.ex +++ b/lib/elixir_script/passes/find_used_functions.ex @@ -98,7 +98,7 @@ defmodule ElixirScript.FindUsedFunctions do walk(tail, state) end - defp walk({:::, _, _}, state) do + defp walk({:::, _, _}, _) do nil end diff --git a/lib/elixir_script/passes/find_used_modules.ex b/lib/elixir_script/passes/find_used_modules.ex index 5c7cd5d7..1a8bddf2 100644 --- a/lib/elixir_script/passes/find_used_modules.ex +++ b/lib/elixir_script/passes/find_used_modules.ex @@ -95,7 +95,7 @@ defmodule ElixirScript.FindUsedModules do walk(tail, state) end - defp walk({:::, _, _}, state) do + defp walk({:::, _, _}, _) do nil end @@ -232,7 +232,7 @@ defmodule ElixirScript.FindUsedModules do walk({function, [], params}, state) end - defp walk({:., _, [JS, _]}, state) do + defp walk({:., _, [JS, _]}, _) do nil end diff --git a/lib/elixir_script/passes/output.ex b/lib/elixir_script/passes/output.ex index f4c1cb4a..14872ba0 100644 --- a/lib/elixir_script/passes/output.ex +++ b/lib/elixir_script/passes/output.ex @@ -10,8 +10,9 @@ defmodule ElixirScript.Output do """ @spec execute([atom], pid) :: nil def execute(modules, pid) do - modules = Enum.filter_map(modules, fn {_, info} -> Map.has_key?(info, :js_ast) end, - fn {_module, info} -> + modules = modules + |> Enum.filter(fn {_, info} -> Map.has_key?(info, :js_ast) end) + |> Enum.map(fn {_module, info} -> info.js_ast end ) diff --git a/lib/elixir_script/passes/output/js_module.ex b/lib/elixir_script/passes/output/js_module.ex index 8be907ca..75eb960f 100644 --- a/lib/elixir_script/passes/output/js_module.ex +++ b/lib/elixir_script/passes/output/js_module.ex @@ -12,14 +12,14 @@ defmodule ElixirScript.Output.JSModule do elixir = J.variable_declaration([declarator], :const) table_additions = Enum.map(opts.js_modules, fn - {module, path} -> add_import_to_table(module) - {module, path, _} -> add_import_to_table(module) + {module, _} -> add_import_to_table(module) + {module, _, _} -> add_import_to_table(module) end) ast = opts.module_formatter.build( [], opts.js_modules, - [elixir, create_atom_table(), start, load] ++ table_additions ++ body, + [elixir, create_atom_table(), start(), load()] ++ table_additions ++ body, J.identifier("Elixir") ) diff --git a/lib/elixir_script/passes/translate.ex b/lib/elixir_script/passes/translate.ex index 8341a30a..11f89339 100644 --- a/lib/elixir_script/passes/translate.ex +++ b/lib/elixir_script/passes/translate.ex @@ -1,9 +1,6 @@ defmodule ElixirScript.Translate do @moduledoc false - alias ElixirScript.State, as: ModuleState - alias ESTree.Tools.{Builder, Generator} - @doc """ Takes a list of modules and translates their ast into JavaScript AST. The modules are the ones collected from diff --git a/lib/elixir_script/passes/translate/form.ex b/lib/elixir_script/passes/translate/form.ex index f03f6b84..dd1395fb 100644 --- a/lib/elixir_script/passes/translate/form.ex +++ b/lib/elixir_script/passes/translate/form.ex @@ -1,8 +1,7 @@ defmodule ElixirScript.Translate.Form do alias ESTree.Tools.Builder, as: J alias ElixirScript.Translate.Forms.{Bitstring, Match, Try, For, Receive, Remote, Pattern} - alias ElixirScript.Translate.Functions.{Erlang, Lists, Maps} - alias ElixirScript.Translate.{Identifier, Clause} + alias ElixirScript.Translate.Clause require Logger @moduledoc """ @@ -178,7 +177,7 @@ defmodule ElixirScript.Translate.Form do def compile({:receive, context, [blocks]}, state) do line = Keyword.get(context, :line, 1) - {function, arity} = Map.get(state, :function) + {function, _arity} = Map.get(state, :function) Logger.warn fn() -> "receive not supported, Module: #{inspect state.module}, Function: #{function}, Line: #{line}" end @@ -201,7 +200,7 @@ defmodule ElixirScript.Translate.Form do Remote.compile(ast, state) end - def compile({:super, context, params}, state) when is_list(params) do + def compile({:super, _, params}, state) when is_list(params) do {function_name, _} = Map.get(state, :function) {var_decs, params} = compile_params(params, state) @@ -259,7 +258,7 @@ defmodule ElixirScript.Translate.Form do end end - def compile({var, _, _} = ast, state) do + def compile({var, _, _}, state) do var = Pattern.get_variable_name(to_string(var), state) { ElixirScript.Translate.Identifier.make_identifier(var), state } end diff --git a/lib/elixir_script/passes/translate/forms/bitstring.ex b/lib/elixir_script/passes/translate/forms/bitstring.ex index 0221e82c..751af14f 100644 --- a/lib/elixir_script/passes/translate/forms/bitstring.ex +++ b/lib/elixir_script/passes/translate/forms/bitstring.ex @@ -98,7 +98,7 @@ defmodule ElixirScript.Translate.Forms.Bitstring do defp do_compile_element({type, ast}) do JS.call_expression( JS.member_expression( - bitstring_class, + bitstring_class(), JS.identifier(type) ), [ @@ -110,7 +110,7 @@ defmodule ElixirScript.Translate.Forms.Bitstring do defp do_compile_element({type, ast, params}) when is_list(params) do JS.call_expression( JS.member_expression( - bitstring_class, + bitstring_class(), JS.identifier(type) ), [ diff --git a/lib/elixir_script/passes/translate/forms/for.ex b/lib/elixir_script/passes/translate/forms/for.ex index 063fbe39..a04733cd 100644 --- a/lib/elixir_script/passes/translate/forms/for.ex +++ b/lib/elixir_script/passes/translate/forms/for.ex @@ -51,7 +51,7 @@ defmodule ElixirScript.Translate.Forms.For do {ast, state} end - defp handle_args(nil, module_state) do + defp handle_args(nil, _) do %{generators: [], args: [], filter: nil, fun: nil, into: nil, patterns: []} end @@ -123,7 +123,7 @@ defmodule ElixirScript.Translate.Forms.For do defp create_function_expression(ast, state, module_state) do - { ast, module_state } = Enum.map_reduce(List.wrap(ast), module_state, fn x, acc_state -> + { ast, _ } = Enum.map_reduce(List.wrap(ast), module_state, fn x, acc_state -> Form.compile(x, acc_state) end) diff --git a/lib/elixir_script/passes/translate/forms/js.ex b/lib/elixir_script/passes/translate/forms/js.ex index 9cf77604..bb49deb3 100644 --- a/lib/elixir_script/passes/translate/forms/js.ex +++ b/lib/elixir_script/passes/translate/forms/js.ex @@ -42,7 +42,7 @@ defmodule ElixirScript.Translate.Forms.JS do params = case params do p when is_list(p) -> Enum.map(params, &Form.compile!(&1, state)) - p -> + _ -> [J.rest_element(Form.compile!(params, state))] end diff --git a/lib/elixir_script/passes/translate/forms/match.ex b/lib/elixir_script/passes/translate/forms/match.ex index 2ef9037c..1f31bf75 100644 --- a/lib/elixir_script/passes/translate/forms/match.ex +++ b/lib/elixir_script/passes/translate/forms/match.ex @@ -38,7 +38,7 @@ defmodule ElixirScript.Translate.Forms.Match do js_ast = case left do list when is_list(list) -> - make_list_ref(array_pattern, params, state) + make_list_ref(array_pattern, params) { _, _ } -> make_tuple_ref(array_pattern, params) {:{}, _, _ } -> @@ -58,7 +58,7 @@ defmodule ElixirScript.Translate.Forms.Match do end - defp make_list_ref(array_pattern, params, state) do + defp make_list_ref(array_pattern, params) do {ref, params} = make_params(params) ref_declarator = J.variable_declarator(ref, J.array_expression(params)) diff --git a/lib/elixir_script/passes/translate/forms/remote.ex b/lib/elixir_script/passes/translate/forms/remote.ex index 213f9a00..66740877 100644 --- a/lib/elixir_script/passes/translate/forms/remote.ex +++ b/lib/elixir_script/passes/translate/forms/remote.ex @@ -166,7 +166,7 @@ defmodule ElixirScript.Translate.Forms.Remote do Form.compile!(module, state) end - defp process_js_module_name(module, state) do + defp process_js_module_name(module, _) do case Module.split(module) do ["JS"] -> J.member_expression( diff --git a/lib/elixir_script/passes/translate/forms/try.ex b/lib/elixir_script/passes/translate/forms/try.ex index b7c0f225..0df1df1f 100644 --- a/lib/elixir_script/passes/translate/forms/try.ex +++ b/lib/elixir_script/passes/translate/forms/try.ex @@ -64,7 +64,7 @@ defmodule ElixirScript.Translate.Forms.Try do defp process_rescue_block(rescue_block, state) do processed_clauses = Enum.map(rescue_block, fn - {:->, _, [ [{:in, _, [param, names]} = pattern], body]} -> + {:->, _, [ [{:in, _, [param, names]}], body]} -> {ast, _} = Clause.compile({[], [param], [{{:., [], [Enum, :member?]}, [], [param, names]}], body}, state) ast {:->, _, [ [param], body]} -> @@ -91,7 +91,7 @@ defmodule ElixirScript.Translate.Forms.Try do end defp prepare_function_body(body, state) do - {ast, state} = Function.compile_block(body, state) + {ast, _} = Function.compile_block(body, state) Clause.return_last_statement(ast) end diff --git a/lib/elixir_script/passes/translate/function.ex b/lib/elixir_script/passes/translate/function.ex index 0c74fdd8..148fe2ad 100644 --- a/lib/elixir_script/passes/translate/function.ex +++ b/lib/elixir_script/passes/translate/function.ex @@ -92,7 +92,7 @@ defmodule ElixirScript.Translate.Function do defp compile_clauses(clauses, state) do clauses |> Enum.map(&compile_clause(&1, state)) - |> Enum.map(fn {patterns, params, guards, body} -> + |> Enum.map(fn {patterns, _params, guards, body} -> match_or_default_call = J.call_expression( J.member_expression( patterns_ast(), @@ -129,18 +129,7 @@ defmodule ElixirScript.Translate.Function do {patterns, params, state} = Pattern.compile(args, state) guard = Clause.compile_guard(params, guards, state) - body = case body do - nil -> - J.identifier("null") - {:__block__, _, block_body} -> - {list, _} = Enum.map_reduce(block_body, state, &Form.compile(&1, &2)) - List.flatten(list) - b when is_list(b) -> - {list, _} = Enum.map_reduce(b, state, &Form.compile(&1, &2)) - J.array_expression(list) - _ -> - Form.compile!(body, state) - end + {body, _state} = compile_block(body, state) body = body |> Clause.return_last_statement @@ -174,9 +163,6 @@ defmodule ElixirScript.Translate.Function do {:__block__, _, block_body} -> {list, _} = Enum.map_reduce(block_body, state, &Form.compile(&1, &2)) List.flatten(list) - b when is_list(b) -> - {list, _} = Enum.map_reduce(b, state, &Form.compile(&1, &2)) - List.flatten(list) _ -> Form.compile!(block, state) end diff --git a/lib/elixir_script/passes/translate/module.ex b/lib/elixir_script/passes/translate/module.ex index 310b455d..54ca1c7e 100644 --- a/lib/elixir_script/passes/translate/module.ex +++ b/lib/elixir_script/passes/translate/module.ex @@ -62,8 +62,7 @@ defmodule ElixirScript.Translate.Module do js_ast = ElixirScript.ModuleSystems.Namespace.build( module, compiled_functions, - exports, - nil + exports ) ModuleState.put_module(pid, module, Map.put(info, :js_ast, hd(js_ast))) diff --git a/lib/elixir_script/passes/translate/protocol.ex b/lib/elixir_script/passes/translate/protocol.ex index 8dc5deaa..d487a391 100644 --- a/lib/elixir_script/passes/translate/protocol.ex +++ b/lib/elixir_script/passes/translate/protocol.ex @@ -1,7 +1,7 @@ defmodule ElixirScript.Translate.Protocol do @moduledoc false alias ESTree.Tools.Builder, as: J - alias ElixirScript.Translate.{Function, Form, Identifier} + alias ElixirScript.Translate.{Function, Identifier} alias ElixirScript.State, as: ModuleState @@ -34,21 +34,20 @@ defmodule ElixirScript.Translate.Protocol do declaration = J.variable_declaration([declarator], :const) - body = build_implementations(impls, pid) + body = build_implementations(impls) body = [declaration] ++ body js_ast = ElixirScript.ModuleSystems.Namespace.build( module, body, - J.identifier("protocol"), - nil + J.identifier("protocol") ) ModuleState.put_module(pid, module, Map.put(info, :js_ast, hd(js_ast))) end - defp build_implementations(impls, pid) do + defp build_implementations(impls) do Enum.map(impls, fn({impl, impl_for}) -> members = ["Elixir"] ++ Module.split(impl) ++ ["__load"] @@ -165,7 +164,7 @@ defmodule ElixirScript.Translate.Protocol do case Module.split(module) do ["JS" | rest] -> Identifier.make_namespace_members(rest) - split_module -> + _ -> J.call_expression( J.member_expression( J.identifier("Symbol"), diff --git a/lib/elixir_script/watcher.ex b/lib/elixir_script/watcher.ex index 7f1e6e1d..00584d08 100644 --- a/lib/elixir_script/watcher.ex +++ b/lib/elixir_script/watcher.ex @@ -22,7 +22,7 @@ defmodule ElixirScript.Watcher do def handle_info({_pid, {:fs, :file_event}, {path, event}}, state) do try do - if input_changed?(to_string(path), state) do + if input_changed?(to_string(path)) do Logger.debug fn() -> "Event: #{inspect event} Path: #{path}" end @@ -36,7 +36,7 @@ defmodule ElixirScript.Watcher do {:noreply, state} end - defp input_changed?(path, state) do + defp input_changed?(path) do case Path.extname(path) do ".beam" -> true diff --git a/lib/mix/tasks/compile.elixir_script.ex b/lib/mix/tasks/compile.elixir_script.ex index 85a8871b..b01abbcb 100644 --- a/lib/mix/tasks/compile.elixir_script.ex +++ b/lib/mix/tasks/compile.elixir_script.ex @@ -37,23 +37,17 @@ defmodule Mix.Tasks.Compile.ElixirScript do @spec run(any()) :: :ok def run(_) do - elixirscript_base = Path.join([Mix.Project.build_path, "elixirscript"]) - do_compile(elixirscript_base, Mix.Project.config[:app]) + do_compile() :ok end - defp do_compile(_, nil) do - raise ElixirScript.CompileError, message: "Unable to find mix project app name" - end - - defp do_compile(elixirscript_base, app) do - + defp do_compile() do {input, opts} = get_compiler_params() ElixirScript.Compiler.compile(input, opts) end def clean do - {input, opts} = get_compiler_params() + {_, opts} = get_compiler_params() case opts[:output] do path when is_binary(path) -> @@ -78,7 +72,6 @@ defmodule Mix.Tasks.Compile.ElixirScript do {input, opts} end - defp get_elixirscript_config() do config = Mix.Project.config exjs_config = cond do From 128218eb33e85177ef81511bcb716db077c6227c Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Tue, 4 Jul 2017 16:34:25 -0500 Subject: [PATCH 594/860] Add string interpolation --- .../passes/find_used_functions.ex | 4 +-- lib/elixir_script/passes/find_used_modules.ex | 4 +-- lib/elixir_script/passes/translate/form.ex | 19 ++++++++++-- .../passes/translate/forms/bitstring.ex | 13 ++++++-- .../passes/translate/forms/bitstring_test.exs | 30 +++++++++++++++++++ 5 files changed, 62 insertions(+), 8 deletions(-) create mode 100644 test/passes/translate/forms/bitstring_test.exs diff --git a/lib/elixir_script/passes/find_used_functions.ex b/lib/elixir_script/passes/find_used_functions.ex index 30d2919f..234805e0 100644 --- a/lib/elixir_script/passes/find_used_functions.ex +++ b/lib/elixir_script/passes/find_used_functions.ex @@ -98,8 +98,8 @@ defmodule ElixirScript.FindUsedFunctions do walk(tail, state) end - defp walk({:::, _, _}, _) do - nil + defp walk({:::, _, [target, _type]}, state) do + walk(target, state) end defp walk(form, state) when is_list(form) do diff --git a/lib/elixir_script/passes/find_used_modules.ex b/lib/elixir_script/passes/find_used_modules.ex index 1a8bddf2..5823ec65 100644 --- a/lib/elixir_script/passes/find_used_modules.ex +++ b/lib/elixir_script/passes/find_used_modules.ex @@ -95,8 +95,8 @@ defmodule ElixirScript.FindUsedModules do walk(tail, state) end - defp walk({:::, _, _}, _) do - nil + defp walk({:::, _, [target, _type]}, state) do + walk(target, state) end defp walk(form, state) when is_list(form) do diff --git a/lib/elixir_script/passes/translate/form.ex b/lib/elixir_script/passes/translate/form.ex index dd1395fb..314fa624 100644 --- a/lib/elixir_script/passes/translate/form.ex +++ b/lib/elixir_script/passes/translate/form.ex @@ -90,8 +90,23 @@ defmodule ElixirScript.Translate.Form do ElixirScript.Translate.Forms.Map.compile(map, state) end - def compile({:<<>>, _, _} = bitstring, state) do - Bitstring.compile(bitstring, state) + def compile({:<<>>, _, elements} = bitstring, state) do + is_interpolated_string = Enum.all?(elements, fn(x) -> + case x do + b when is_binary(b) -> + true + {:::, _, [_target, {:binary, _, _}]} -> + true + _ -> + false + end + end) + + if is_interpolated_string do + Bitstring.make_interpolated_string(elements, state) + else + Bitstring.compile(bitstring, state) + end end def compile({:=, _, [_, _]} = match, state) do diff --git a/lib/elixir_script/passes/translate/forms/bitstring.ex b/lib/elixir_script/passes/translate/forms/bitstring.ex index 751af14f..1490f74f 100644 --- a/lib/elixir_script/passes/translate/forms/bitstring.ex +++ b/lib/elixir_script/passes/translate/forms/bitstring.ex @@ -129,10 +129,19 @@ defmodule ElixirScript.Translate.Forms.Bitstring do end end) - { do_make_interpolated_string(tl(translated_elements), hd(translated_elements)) } + result = case translated_elements do + [] -> + JS.literal('') + [element] -> + do_make_interpolated_string([], hd(translated_elements)) + elements -> + do_make_interpolated_string(tl(elements), hd(elements)) + end + + {result, state} end - defp do_make_interpolated_string([], ast, _) do + defp do_make_interpolated_string([], ast) do ast end diff --git a/test/passes/translate/forms/bitstring_test.exs b/test/passes/translate/forms/bitstring_test.exs new file mode 100644 index 00000000..73e0e0fa --- /dev/null +++ b/test/passes/translate/forms/bitstring_test.exs @@ -0,0 +1,30 @@ +defmodule ElixirScript.Translate.Forms.Bitstring.Test do + use ExUnit.Case + alias ElixirScript.Translate.Form + alias ESTree.Tools.Builder, as: J + + setup_all do + {:ok, pid} = ElixirScript.State.start_link(%{}) + + state = %{ + pid: pid, + vars: %{} + } + + [state: state] + end + + test "string interpolation", %{state: state} do + ast = {:<<>>, [line: 5], + [{:::, [], ["Hello, ", {:binary, [], []}]}, + {:::, [line: 5], + [{{:., [line: 5], [String.Chars, :to_string]}, [line: 5], + [{:name, [line: 5], nil}]}, {:binary, [], []}]}]} + + {js_ast, _} = Form.compile(ast, state) + assert js_ast.type == "BinaryExpression" + assert js_ast.left == J.literal("Hello, ") + assert js_ast.right.type == "CallExpression" + end + +end \ No newline at end of file From cbdb1f3938c4041f4aab26294b2b72e64d0db2d8 Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Tue, 4 Jul 2017 17:16:26 -0500 Subject: [PATCH 595/860] Update tailored dependency --- package.json | 2 +- yarn.lock | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/package.json b/package.json index 23da045b..a7d6ce42 100644 --- a/package.json +++ b/package.json @@ -23,7 +23,7 @@ "license": "MIT", "dependencies": { "erlang-types": "^1.0.1", - "tailored": "^2.4.6" + "tailored": "^2.4.7" }, "devDependencies": { "ava": "^0.19.1", diff --git a/yarn.lock b/yarn.lock index 7ceffecc..b3274706 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3771,9 +3771,9 @@ table@^3.7.8: slice-ansi "0.0.4" string-width "^2.0.0" -tailored@^2.4.6: - version "2.4.6" - resolved "https://registry.yarnpkg.com/tailored/-/tailored-2.4.6.tgz#1425d01bfc0e69ae0f8edb7030f82d6f0239d00f" +tailored@^2.4.7: + version "2.4.7" + resolved "https://registry.yarnpkg.com/tailored/-/tailored-2.4.7.tgz#1d90846b4885631be00cfd8bc9f56b0dec1686bf" dependencies: erlang-types "^1.0.0" From b57c2b137f643bfb6243ba6b5cc10132daec7463 Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Wed, 5 Jul 2017 21:18:07 -0500 Subject: [PATCH 596/860] Updated from testing --- lib/elixir_script/beam.ex | 10 ++++ lib/elixir_script/lib/agent.ex | 53 +++++++++++++++++++ lib/elixir_script/lib/store.ex | 43 +++++++++++++++ .../passes/find_used_functions.ex | 7 +-- lib/elixir_script/passes/find_used_modules.ex | 5 ++ lib/elixir_script/passes/translate/form.ex | 9 ++++ .../passes/translate/forms/js.ex | 7 +++ .../passes/translate/forms/pattern.ex | 15 ++++++ package.json | 2 +- rollup.config.js | 14 ++--- .../lib/core/erlang_compat/erlang.js | 10 ++-- .../lib/core/erlang_compat/lists.js | 2 +- src/javascript/lib/core/erlang_compat/maps.js | 2 +- src/javascript/lib/core/functions.js | 6 +-- test/support/main.ex | 6 ++- yarn.lock | 6 +-- 16 files changed, 172 insertions(+), 25 deletions(-) create mode 100644 lib/elixir_script/lib/agent.ex create mode 100644 lib/elixir_script/lib/store.ex diff --git a/lib/elixir_script/beam.ex b/lib/elixir_script/beam.ex index a5a3aa46..d8cb7213 100644 --- a/lib/elixir_script/beam.ex +++ b/lib/elixir_script/beam.ex @@ -20,6 +20,16 @@ defmodule ElixirScript.Beam do end end + #Replacing Agent module with our ElixirScript's version + def debug_info(Agent) do + case debug_info(ElixirScript.Agent) do + {:ok, info} -> + {:ok, Map.put(info, :module, Agent)} + e -> + e + end + end + def debug_info(module) when is_atom(module) do #TODO: Get modified date from _beam_path to check for cached version? with {_, beam, _beam_path} <- :code.get_object_code(module), diff --git a/lib/elixir_script/lib/agent.ex b/lib/elixir_script/lib/agent.ex new file mode 100644 index 00000000..8ae7b1eb --- /dev/null +++ b/lib/elixir_script/lib/agent.ex @@ -0,0 +1,53 @@ +defmodule ElixirScript.Agent do + @moduledoc false + + def start(fun, options \\ []) do + pid = JS.new JS.Bootstrap.Core.PID, [] + + name = if Keyword.has_key?(options, :name) do + Keyword.get(options, :name) + else + nil + end + + ElixirScript.Store.create(pid, fun.(), name) + { :ok, pid } + end + + def start_link(fun, options \\ []) do + pid = JS.new JS.Bootstrap.Core.PID, [] + + name = if Keyword.has_key?(options, :name) do + Keyword.get(options, :name) + else + nil + end + + ElixirScript.Store.create(pid, fun.(), name) + { :ok, pid } + end + + def stop(agent) do + ElixirScript.Store.remove(agent) + :ok + end + + def update(agent, fun) do + current_state = ElixirScript.Store.read(agent) + ElixirScript.Store.update(agent, fun.(current_state)) + :ok + end + + def get(agent, fun) do + current_state = ElixirScript.Store.read(agent) + fun.(current_state) + end + + def get_and_update(agent, fun) do + current_state = ElixirScript.Store.read(agent) + {val, new_state} = fun.(current_state) + ElixirScript.Store.update(agent, new_state) + val + end + +end \ No newline at end of file diff --git a/lib/elixir_script/lib/store.ex b/lib/elixir_script/lib/store.ex new file mode 100644 index 00000000..ad5b777c --- /dev/null +++ b/lib/elixir_script/lib/store.ex @@ -0,0 +1,43 @@ +defmodule ElixirScript.Store do + + defp get_key(key) do + real_key = case JS.__elixirscript_names__.has(key) do + true -> + JS.__elixirscript_names__.get(key) + false -> + key + end + + case JS.__elixirscript_store__.has(real_key) do + true -> + real_key + false -> + JS.throw JS.new(JS.Error, ["Key Not Found"]) + end + end + + def create(key, value, name \\ nil) do + if name != nil do + JS.__elixirscript_names__.set(name, key) + end + + JS.__elixirscript_store__.set(key, value) + end + + def update(key, value) do + real_key = get_key(key) + JS.__elixirscript_store__.set(real_key, value) + end + + def read(key) do + real_key = get_key(key) + JS.__elixirscript_store__.get(real_key) + end + + def remove(key) do + real_key = get_key(key) + JS.__elixirscript_store__.delete(real_key) + end + + +end \ No newline at end of file diff --git a/lib/elixir_script/passes/find_used_functions.ex b/lib/elixir_script/passes/find_used_functions.ex index 234805e0..50177616 100644 --- a/lib/elixir_script/passes/find_used_functions.ex +++ b/lib/elixir_script/passes/find_used_functions.ex @@ -36,7 +36,8 @@ defmodule ElixirScript.FindUsedFunctions do reachable_defs = Enum.filter(defs, fn { _, type, _, _} when type in [:defmacro, :defmacrop] -> false - { name, _, _, _} -> not(name in unreachable) + { name, _, _, _} -> + not(name in unreachable) _ -> true end) @@ -128,8 +129,8 @@ defmodule ElixirScript.FindUsedFunctions do end defp walk({:%, _, [module, params]}, state) do - ModuleState.add_used(state.pid, module, {:__struct__, 0}) - ModuleState.add_used(state.pid, module, {:__struct__, 1}) + walk_module(module, :__struct__, 0, state.pid) + walk_module(module, :__struct__, 1, state.pid) walk(params, state) end diff --git a/lib/elixir_script/passes/find_used_modules.ex b/lib/elixir_script/passes/find_used_modules.ex index 5823ec65..ccd94136 100644 --- a/lib/elixir_script/passes/find_used_modules.ex +++ b/lib/elixir_script/passes/find_used_modules.ex @@ -232,6 +232,11 @@ defmodule ElixirScript.FindUsedModules do walk({function, [], params}, state) end + defp walk({{:., _, [module, function]} = ast, _, params}, state) do + walk(ast, state) + walk(params, state) + end + defp walk({:., _, [JS, _]}, _) do nil end diff --git a/lib/elixir_script/passes/translate/form.ex b/lib/elixir_script/passes/translate/form.ex index 314fa624..385156da 100644 --- a/lib/elixir_script/passes/translate/form.ex +++ b/lib/elixir_script/passes/translate/form.ex @@ -207,6 +207,15 @@ defmodule ElixirScript.Translate.Form do ElixirScript.Translate.Function.compile(ast, state) end + def compile({{:., _, [{_, _, nil} = var, func_or_prop]}, _, []}, state) do + ast = J.call_expression( + ElixirScript.Translate.Forms.JS.call_property(), + [compile!(var, state), J.literal(to_string(func_or_prop))] + ) + + {ast, state} + end + def compile({{:., _, [JS, _]}, _, _} = ast, state) do ElixirScript.Translate.Forms.JS.compile(ast, state) end diff --git a/lib/elixir_script/passes/translate/forms/js.ex b/lib/elixir_script/passes/translate/forms/js.ex index bb49deb3..80c8cca9 100644 --- a/lib/elixir_script/passes/translate/forms/js.ex +++ b/lib/elixir_script/passes/translate/forms/js.ex @@ -39,6 +39,13 @@ defmodule ElixirScript.Translate.Forms.JS do def compile({{:., _, [JS, :new]}, _, [module, params]}, state) do members = Module.split(module) + members = case members do + ["JS" | rest] -> + rest + x -> + x + end + params = case params do p when is_list(p) -> Enum.map(params, &Form.compile!(&1, state)) diff --git a/lib/elixir_script/passes/translate/forms/pattern.ex b/lib/elixir_script/passes/translate/forms/pattern.ex index 134b8ca8..a721295b 100644 --- a/lib/elixir_script/passes/translate/forms/pattern.ex +++ b/lib/elixir_script/passes/translate/forms/pattern.ex @@ -118,6 +118,21 @@ defmodule ElixirScript.Translate.Forms.Pattern do defp process_pattern({:%{}, _, props}, state) do properties = Enum.map(props, fn + {:__module__struct__, {_, _, nil} = var } -> + {pattern, params} = process_pattern(var, state) + + a = J.object_expression([%ESTree.Property{ + key: J.identifier("__MODULE__"), + value: hd(List.wrap(pattern)) + }]) + + property = ElixirScript.Translate.Forms.Map.make_property( + Form.compile!(:__struct__, state), + a + ) + + { property, params } + {:__module__struct__, module} -> a = J.object_expression([%ESTree.Property{ key: J.identifier("__MODULE__"), diff --git a/package.json b/package.json index a7d6ce42..cb87365b 100644 --- a/package.json +++ b/package.json @@ -23,7 +23,7 @@ "license": "MIT", "dependencies": { "erlang-types": "^1.0.1", - "tailored": "^2.4.7" + "tailored": "^2.4.8" }, "devDependencies": { "ava": "^0.19.1", diff --git a/rollup.config.js b/rollup.config.js index 9fe0ae32..70fa4aef 100644 --- a/rollup.config.js +++ b/rollup.config.js @@ -8,12 +8,12 @@ export default { plugins: [ nodeResolve({ jsnext: true }), babel({ - babelrc: false, - }), - babili({ - keepFnName: true, - keepClassName: true, - }), + babelrc: false + }) + //babili({ + // keepFnName: true, + // keepClassName: true, + //}), ], - targets: [{ dest: 'priv/build/iife/Elixir.Bootstrap.js', format: 'iife' }], + targets: [{ dest: 'priv/build/iife/Elixir.Bootstrap.js', format: 'iife' }] }; diff --git a/src/javascript/lib/core/erlang_compat/erlang.js b/src/javascript/lib/core/erlang_compat/erlang.js index 0fd5a647..aefbf7b7 100644 --- a/src/javascript/lib/core/erlang_compat/erlang.js +++ b/src/javascript/lib/core/erlang_compat/erlang.js @@ -202,7 +202,7 @@ function element(n, tuple) { } function setelement(index, tuple1, value) { - const tupleData = [...tuple1.data]; + const tupleData = [...tuple1.values]; tupleData[index - 1] = value; @@ -220,28 +220,28 @@ function make_tuple(arity, initialValue) { } function insert_element(index, tuple, term) { - const list = [...tuple.data]; + const list = [...tuple.values]; list.splice(index - 1, 0, term); return new ErlangTypes.Tuple(...list); } function append_element(tuple, term) { - const list = [...tuple.data]; + const list = [...tuple.values]; list.push(term); return new ErlangTypes.Tuple(...list); } function delete_element(index, tuple) { - const list = [...tuple.data]; + const list = [...tuple.values]; list.splice(index - 1, 1); return new ErlangTypes.Tuple(...list); } function tuple_to_list(tuple) { - const list = [...tuple.data]; + const list = [...tuple.values]; return list; } diff --git a/src/javascript/lib/core/erlang_compat/lists.js b/src/javascript/lib/core/erlang_compat/lists.js index b06cc30d..9e9daf43 100644 --- a/src/javascript/lib/core/erlang_compat/lists.js +++ b/src/javascript/lib/core/erlang_compat/lists.js @@ -263,5 +263,5 @@ export default { all, any, splitwith, - sort, + sort }; diff --git a/src/javascript/lib/core/erlang_compat/maps.js b/src/javascript/lib/core/erlang_compat/maps.js index 6178eba7..142a031f 100644 --- a/src/javascript/lib/core/erlang_compat/maps.js +++ b/src/javascript/lib/core/erlang_compat/maps.js @@ -129,7 +129,7 @@ function update(key, value, map1) { return new ErlangTypes.Tuple(BADMAP, map1); } - if (is_key(key) === false) { + if (is_key(key, map1) === false) { return new ErlangTypes.Tuple(BADKEY, key); } diff --git a/src/javascript/lib/core/functions.js b/src/javascript/lib/core/functions.js index 423f323a..d315dab9 100644 --- a/src/javascript/lib/core/functions.js +++ b/src/javascript/lib/core/functions.js @@ -24,7 +24,7 @@ function iterator_to_reducer(iterable, acc, fun) { function call_property(item, property) { if (!property) { - if (item instanceof Function) { + if (item instanceof Function || typeof item === 'function') { return item(); } @@ -54,7 +54,7 @@ function call_property(item, property) { throw new Error(`Property ${property} not found in ${item}`); } - if (item[prop] instanceof Function) { + if (item[prop] instanceof Function || typeof item[prop] === 'function') { return item[prop](); } return item[prop]; @@ -96,5 +96,5 @@ export default { defprotocol, defimpl, build_namespace, - iterator_to_reducer, + iterator_to_reducer }; diff --git a/test/support/main.ex b/test/support/main.ex index 64562538..ef0460e0 100644 --- a/test/support/main.ex +++ b/test/support/main.ex @@ -2,6 +2,10 @@ defmodule Main do def start(:normal, [callback]) do callback.("started") - Enum.each(1..3, fn x -> JS.console.log(x) end) + JS.fetch("/api/todo").then(fn(response) -> + response.json() + end).catch(fn(err) -> + :console.debug(err) + end) end end diff --git a/yarn.lock b/yarn.lock index b3274706..731d3082 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3771,9 +3771,9 @@ table@^3.7.8: slice-ansi "0.0.4" string-width "^2.0.0" -tailored@^2.4.7: - version "2.4.7" - resolved "https://registry.yarnpkg.com/tailored/-/tailored-2.4.7.tgz#1d90846b4885631be00cfd8bc9f56b0dec1686bf" +tailored@^2.4.8: + version "2.4.8" + resolved "https://registry.yarnpkg.com/tailored/-/tailored-2.4.8.tgz#adef8f95aa621068d5735f970ceb458d689e6de5" dependencies: erlang-types "^1.0.0" From 57cdb747d34185a2d2d5855100b9fc90c7133322 Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Sat, 8 Jul 2017 04:38:14 -0500 Subject: [PATCH 597/860] Updated tailored dep --- package.json | 2 +- yarn.lock | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/package.json b/package.json index cb87365b..bb34b229 100644 --- a/package.json +++ b/package.json @@ -23,7 +23,7 @@ "license": "MIT", "dependencies": { "erlang-types": "^1.0.1", - "tailored": "^2.4.8" + "tailored": "^2.4.9" }, "devDependencies": { "ava": "^0.19.1", diff --git a/yarn.lock b/yarn.lock index 731d3082..241ad9e7 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3771,9 +3771,9 @@ table@^3.7.8: slice-ansi "0.0.4" string-width "^2.0.0" -tailored@^2.4.8: - version "2.4.8" - resolved "https://registry.yarnpkg.com/tailored/-/tailored-2.4.8.tgz#adef8f95aa621068d5735f970ceb458d689e6de5" +tailored@^2.4.9: + version "2.4.9" + resolved "https://registry.yarnpkg.com/tailored/-/tailored-2.4.9.tgz#b06ea7e8eab054860062b076e7e1d0e33e0fa983" dependencies: erlang-types "^1.0.0" From 15d467cc2a0d630961698a62079a56cb20c60547 Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Sat, 8 Jul 2017 04:40:18 -0500 Subject: [PATCH 598/860] Revert changes main.ex --- test/support/main.ex | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/test/support/main.ex b/test/support/main.ex index ef0460e0..64562538 100644 --- a/test/support/main.ex +++ b/test/support/main.ex @@ -2,10 +2,6 @@ defmodule Main do def start(:normal, [callback]) do callback.("started") - JS.fetch("/api/todo").then(fn(response) -> - response.json() - end).catch(fn(err) -> - :console.debug(err) - end) + Enum.each(1..3, fn x -> JS.console.log(x) end) end end From c07fce0bae35d0a3092a86f9a38dd09aa8d640bd Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Sat, 8 Jul 2017 04:42:38 -0500 Subject: [PATCH 599/860] Uncomment minification options --- rollup.config.js | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/rollup.config.js b/rollup.config.js index 70fa4aef..a69d9169 100644 --- a/rollup.config.js +++ b/rollup.config.js @@ -9,11 +9,11 @@ export default { nodeResolve({ jsnext: true }), babel({ babelrc: false + }), + babili({ + keepFnName: true, + keepClassName: true }) - //babili({ - // keepFnName: true, - // keepClassName: true, - //}), ], targets: [{ dest: 'priv/build/iife/Elixir.Bootstrap.js', format: 'iife' }] }; From 579dbcbebcdc88eb815575d77d91a8bd3f116dea Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Mon, 10 Jul 2017 08:38:11 -0500 Subject: [PATCH 600/860] Add FFI for javascript interop --- lib/elixir_script/ffi.ex | 15 ++++++ lib/elixir_script/lib/agent.ex | 20 ++++---- lib/elixir_script/lib/store.ex | 45 +++--------------- lib/elixir_script/passes/output.ex | 6 +-- lib/elixir_script/passes/output/js_module.ex | 6 +-- .../passes/translate/forms/remote.ex | 15 +----- lib/elixir_script/passes/translate/module.ex | 10 ++-- lib/elixir_script/state.ex | 36 ++++++++++++-- src/javascript/lib/core.js | 4 +- src/javascript/lib/core/store.js | 47 +++++++++++++++++++ test/support/json.ex | 6 +++ test/support/main.ex | 2 + 12 files changed, 135 insertions(+), 77 deletions(-) create mode 100644 lib/elixir_script/ffi.ex create mode 100644 src/javascript/lib/core/store.js create mode 100644 test/support/json.ex diff --git a/lib/elixir_script/ffi.ex b/lib/elixir_script/ffi.ex new file mode 100644 index 00000000..ff14b80b --- /dev/null +++ b/lib/elixir_script/ffi.ex @@ -0,0 +1,15 @@ +defmodule ElixirScript.FFI do + defmacro __using__(opts) do + quote do + import ElixirScript.FFI + Module.register_attribute __MODULE__, :__foreign_info__, persist: true + @__foreign_info__ %{path: unquote(Keyword.get(opts, :path, nil))} + end + end + + defmacro foreign({name, _, args}) do + quote do + def unquote(name)(unquote_splicing(args)), do: nil + end + end +end \ No newline at end of file diff --git a/lib/elixir_script/lib/agent.ex b/lib/elixir_script/lib/agent.ex index 8ae7b1eb..cb444941 100644 --- a/lib/elixir_script/lib/agent.ex +++ b/lib/elixir_script/lib/agent.ex @@ -2,51 +2,47 @@ defmodule ElixirScript.Agent do @moduledoc false def start(fun, options \\ []) do - pid = JS.new JS.Bootstrap.Core.PID, [] - name = if Keyword.has_key?(options, :name) do Keyword.get(options, :name) else nil end - ElixirScript.Store.create(pid, fun.(), name) + pid = Bootstrap.Core.Store.create(fun.(), name) { :ok, pid } end def start_link(fun, options \\ []) do - pid = JS.new JS.Bootstrap.Core.PID, [] - name = if Keyword.has_key?(options, :name) do Keyword.get(options, :name) else nil end - ElixirScript.Store.create(pid, fun.(), name) + pid = Bootstrap.Core.Store.create(fun.(), name) { :ok, pid } end def stop(agent) do - ElixirScript.Store.remove(agent) + Bootstrap.Core.Store.remove(agent) :ok end def update(agent, fun) do - current_state = ElixirScript.Store.read(agent) - ElixirScript.Store.update(agent, fun.(current_state)) + current_state = Bootstrap.Core.Store.read(agent) + Bootstrap.Core.Store.update(agent, fun.(current_state)) :ok end def get(agent, fun) do - current_state = ElixirScript.Store.read(agent) + current_state = Bootstrap.Core.Store.read(agent) fun.(current_state) end def get_and_update(agent, fun) do - current_state = ElixirScript.Store.read(agent) + current_state = Bootstrap.Core.Store.read(agent) {val, new_state} = fun.(current_state) - ElixirScript.Store.update(agent, new_state) + Bootstrap.Core.Store.update(agent, new_state) val end diff --git a/lib/elixir_script/lib/store.ex b/lib/elixir_script/lib/store.ex index ad5b777c..dd6b4a7a 100644 --- a/lib/elixir_script/lib/store.ex +++ b/lib/elixir_script/lib/store.ex @@ -1,43 +1,12 @@ -defmodule ElixirScript.Store do +defmodule Bootstrap.Core.Store do + @moduledoc false + use ElixirScript.FFI - defp get_key(key) do - real_key = case JS.__elixirscript_names__.has(key) do - true -> - JS.__elixirscript_names__.get(key) - false -> - key - end + foreign create(value, name \\ nil) - case JS.__elixirscript_store__.has(real_key) do - true -> - real_key - false -> - JS.throw JS.new(JS.Error, ["Key Not Found"]) - end - end - - def create(key, value, name \\ nil) do - if name != nil do - JS.__elixirscript_names__.set(name, key) - end - - JS.__elixirscript_store__.set(key, value) - end - - def update(key, value) do - real_key = get_key(key) - JS.__elixirscript_store__.set(real_key, value) - end - - def read(key) do - real_key = get_key(key) - JS.__elixirscript_store__.get(real_key) - end - - def remove(key) do - real_key = get_key(key) - JS.__elixirscript_store__.delete(real_key) - end + foreign update(key, value) + foreign read(key) + foreign remove(key) end \ No newline at end of file diff --git a/lib/elixir_script/passes/output.ex b/lib/elixir_script/passes/output.ex index 14872ba0..a2d3e2fc 100644 --- a/lib/elixir_script/passes/output.ex +++ b/lib/elixir_script/passes/output.ex @@ -19,13 +19,13 @@ defmodule ElixirScript.Output do opts = ModuleState.get_compiler_opts(pid) - bundle(modules, opts) + bundle(modules, opts, ModuleState.js_modules(pid)) |> output(Map.get(opts, :output)) end - defp bundle(modules, opts) do + defp bundle(modules, opts, js_modules) do modules - |> ElixirScript.Output.JSModule.compile(opts) + |> ElixirScript.Output.JSModule.compile(opts, js_modules) |> List.wrap |> Builder.program |> prepare_js_ast diff --git a/lib/elixir_script/passes/output/js_module.ex b/lib/elixir_script/passes/output/js_module.ex index 75eb960f..79f22a83 100644 --- a/lib/elixir_script/passes/output/js_module.ex +++ b/lib/elixir_script/passes/output/js_module.ex @@ -3,7 +3,7 @@ defmodule ElixirScript.Output.JSModule do alias ESTree.Tools.Builder, as: J - def compile(body, opts) do + def compile(body, opts, js_modules) do declarator = J.variable_declarator( J.identifier("Elixir"), J.object_expression([]) @@ -11,14 +11,14 @@ defmodule ElixirScript.Output.JSModule do elixir = J.variable_declaration([declarator], :const) - table_additions = Enum.map(opts.js_modules, fn + table_additions = Enum.map(js_modules, fn {module, _} -> add_import_to_table(module) {module, _, _} -> add_import_to_table(module) end) ast = opts.module_formatter.build( [], - opts.js_modules, + js_modules, [elixir, create_atom_table(), start(), load()] ++ table_additions ++ body, J.identifier("Elixir") ) diff --git a/lib/elixir_script/passes/translate/forms/remote.ex b/lib/elixir_script/passes/translate/forms/remote.ex index 66740877..93b186cc 100644 --- a/lib/elixir_script/passes/translate/forms/remote.ex +++ b/lib/elixir_script/passes/translate/forms/remote.ex @@ -167,20 +167,7 @@ defmodule ElixirScript.Translate.Forms.Remote do end defp process_js_module_name(module, _) do - case Module.split(module) do - ["JS"] -> - J.member_expression( - J.member_expression( - J.identifier("Bootstrap"), - J.identifier("Core") - ), - J.identifier("global") - ) - ["JS" | rest] -> - Identifier.make_namespace_members(rest) - x -> - Identifier.make_namespace_members(x) - end + Identifier.make_namespace_members(module) end defp erlang_compat_function(module, function) do diff --git a/lib/elixir_script/passes/translate/module.ex b/lib/elixir_script/passes/translate/module.ex index 54ca1c7e..049bfda0 100644 --- a/lib/elixir_script/passes/translate/module.ex +++ b/lib/elixir_script/passes/translate/module.ex @@ -12,6 +12,12 @@ defmodule ElixirScript.Translate.Module do ElixirScript.Translate.Protocol.compile(module, info, pid) end + def compile(module, %{attributes: [__foreign_info__: %{path: path}]}, pid) do + ModuleState.put_javascript_module(pid, module, path) + + nil + end + def compile(module, info, pid) do %{ attributes: attrs, @@ -133,12 +139,10 @@ defmodule ElixirScript.Translate.Module do """ def is_js_module(module, state) do cond do - module in ModuleState.get_javascript_modules(state.pid) -> + module in ModuleState.list_javascript_modules(state.pid) -> true module === Elixir -> false - is_elixir_module(module) and hd(Module.split(module)) == "JS" -> - true true -> false end diff --git a/lib/elixir_script/state.ex b/lib/elixir_script/state.ex index f7e82449..464f43eb 100644 --- a/lib/elixir_script/state.ex +++ b/lib/elixir_script/state.ex @@ -8,7 +8,8 @@ defmodule ElixirScript.State do %{ compiler_opts: compiler_opts, modules: Keyword.new, - refs: [] + refs: [], + js_modules: [] } end) end @@ -57,9 +58,18 @@ defmodule ElixirScript.State do end) end - def get_javascript_modules(pid) do + def put_javascript_module(pid, module, path) do + Agent.update(pid, fn(state) -> + js_modules = Map.get(state, :js_modules, []) + js_modules = js_modules ++ [{module, path}] + + %{ state | js_modules: js_modules } + end) + end + + def list_javascript_modules(pid) do Agent.get(pid, fn(state) -> - Map.get(state.compiler_opts, :js_modules, []) + state.js_modules |> Enum.map(fn {module_name, _path} -> module_name @@ -69,6 +79,26 @@ defmodule ElixirScript.State do end) end + def js_modules(pid) do + Agent.get(pid, fn(state) -> + state.js_modules + |> Enum.filter(fn + {_, nil} -> false + _ -> true + end) + end) + end + + def list_foreign_modules(pid) do + Agent.get(pid, fn(state) -> + state.modules + |> Enum.filter(fn + (%{attributes: [__foreign_info__: _]}) -> true + (_) -> false + end) + end) + end + def list_modules(pid) do Agent.get(pid, fn(state) -> state.modules diff --git a/src/javascript/lib/core.js b/src/javascript/lib/core.js index bacfe6fe..b1c85c9e 100644 --- a/src/javascript/lib/core.js +++ b/src/javascript/lib/core.js @@ -5,6 +5,7 @@ import SpecialForms from './core/special_forms'; import erlang from './core/erlang_compat/erlang'; import maps from './core/erlang_compat/maps'; import lists from './core/erlang_compat/lists'; +import Store from './core/store'; class Integer {} class Float {} @@ -36,8 +37,9 @@ export default { Float, Functions, SpecialForms, + Store, global: globalState, erlang, maps, - lists, + lists }; diff --git a/src/javascript/lib/core/store.js b/src/javascript/lib/core/store.js new file mode 100644 index 00000000..f0ebc0ec --- /dev/null +++ b/src/javascript/lib/core/store.js @@ -0,0 +1,47 @@ +import Core from '../core'; + +function get_key(key) { + let real_key = key; + + if (__elixirscript_names__.has(key)) { + real_key = __elixirscript_names__.get(key); + } + + if (__elixirscript_store__.has(real_key)) { + return real_key; + } + + throw new Error(`Key ${real_key} not found`); +} + +function create(value, name = null) { + const key = new Core.PID(); + + if (name !== null) { + __elixirscript_names__.set(name, key); + } + + __elixirscript_store__.set(key, value); +} + +function update(key, value) { + const real_key = get_key(key); + __elixirscript_store__.set(real_key, value); +} + +function read(key) { + const real_key = get_key(key); + __elixirscript_store__.get(real_key); +} + +function remove(key) { + const real_key = get_key(key); + __elixirscript_store__.delete(real_key); +} + +export default { + create, + update, + read, + remove +}; diff --git a/test/support/json.ex b/test/support/json.ex new file mode 100644 index 00000000..a3c7e349 --- /dev/null +++ b/test/support/json.ex @@ -0,0 +1,6 @@ +defmodule JSON do + use ElixirScript.FFI + + foreign stringify(map) + foreign parse(string) +end \ No newline at end of file diff --git a/test/support/main.ex b/test/support/main.ex index 64562538..d32cd32e 100644 --- a/test/support/main.ex +++ b/test/support/main.ex @@ -2,6 +2,8 @@ defmodule Main do def start(:normal, [callback]) do callback.("started") + JSON.stringify(%{}) + Enum.each(1..3, fn x -> JS.console.log(x) end) end end From f27942b975ad8825a1b5004b1fd5bd9f61ed68c7 Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Wed, 12 Jul 2017 09:00:38 -0500 Subject: [PATCH 601/860] Updated FFI to always assume there will be a js module at an assumed path --- lib/elixir_script/ffi.ex | 10 +++++-- lib/elixir_script/module_systems/common.ex | 6 ++-- lib/elixir_script/module_systems/es.ex | 16 ++-------- lib/elixir_script/module_systems/umd.ex | 4 +-- lib/elixir_script/passes/output.ex | 6 ++++ lib/elixir_script/passes/output/js_module.ex | 29 +------------------ .../passes/translate/forms/remote.ex | 6 ++-- lib/elixir_script/passes/translate/module.ex | 4 +-- lib/elixir_script/state.ex | 22 +++++++------- test/support/json.ex | 2 +- 10 files changed, 41 insertions(+), 64 deletions(-) diff --git a/lib/elixir_script/ffi.ex b/lib/elixir_script/ffi.ex index ff14b80b..890a6913 100644 --- a/lib/elixir_script/ffi.ex +++ b/lib/elixir_script/ffi.ex @@ -1,9 +1,15 @@ defmodule ElixirScript.FFI do - defmacro __using__(opts) do + defmacro __using__(_) do + js_path = Path.join([".", Macro.underscore(__MODULE__)]) + + js_name = __MODULE__ + |> Module.split() + |> Enum.join("_") + quote do import ElixirScript.FFI Module.register_attribute __MODULE__, :__foreign_info__, persist: true - @__foreign_info__ %{path: unquote(Keyword.get(opts, :path, nil))} + @__foreign_info__ %{path: unquote(js_path), name: unquote(js_name)} end end diff --git a/lib/elixir_script/module_systems/common.ex b/lib/elixir_script/module_systems/common.ex index 3236f92b..2f4da76b 100644 --- a/lib/elixir_script/module_systems/common.ex +++ b/lib/elixir_script/module_systems/common.ex @@ -7,7 +7,7 @@ defmodule ElixirScript.ModuleSystems.Common do imports = js_imports |> Enum.map(fn - {module, path} -> import_module(module, path) + {_module, name, path} -> import_module(name, path) end) imports = Enum.uniq(imports ++ module_imports) @@ -16,8 +16,8 @@ defmodule ElixirScript.ModuleSystems.Common do imports ++ body ++ export end - defp import_module(module_name, from) do - js_module_name = ElixirScript.Translate.Identifier.make_namespace_members(module_name) + defp import_module(name, from) do + js_module_name = JS.identifier(name) do_import_module(js_module_name, from) end diff --git a/lib/elixir_script/module_systems/es.ex b/lib/elixir_script/module_systems/es.ex index 3e92049c..72cd042a 100644 --- a/lib/elixir_script/module_systems/es.ex +++ b/lib/elixir_script/module_systems/es.ex @@ -7,8 +7,7 @@ defmodule ElixirScript.ModuleSystems.ES do imports = js_imports |> Enum.map(fn - {module, path} -> import_module(module, path) - {module, path, default: false} -> import_namespace_module(module, path) + {_module, name, path} -> import_module(name, path) end) imports = Enum.uniq(imports ++ module_imports) @@ -17,19 +16,8 @@ defmodule ElixirScript.ModuleSystems.ES do imports ++ body ++ export end - defp import_namespace_module(module_name, from) do - js_module_name = ElixirScript.Translate.Identifier.make_namespace_members(module_name) - - import_specifier = JS.import_namespace_specifier( - js_module_name, - js_module_name - ) - - do_import_module([import_specifier], from) - end - defp import_module(import_name, from) do - js_module_name = ElixirScript.Translate.Identifier.make_namespace_members(import_name) + js_module_name = JS.identifier(import_name) import_specifier = JS.import_default_specifier( js_module_name diff --git a/lib/elixir_script/module_systems/umd.ex b/lib/elixir_script/module_systems/umd.ex index e9894c24..fcd30795 100644 --- a/lib/elixir_script/module_systems/umd.ex +++ b/lib/elixir_script/module_systems/umd.ex @@ -9,7 +9,7 @@ defmodule ElixirScript.ModuleSystems.UMD do imports = js_imports |> Enum.map(fn - {module, path} -> import_module(module, path) + {_module, name, path} -> import_module(name, path) end) imports = Enum.uniq(imports ++ module_imports) @@ -19,7 +19,7 @@ defmodule ElixirScript.ModuleSystems.UMD do end defp import_module(module_name, from) do - js_module_name = ElixirScript.Translate.Identifier.make_namespace_members(module_name) + js_module_name = JS.identifier(module_name) {js_module_name, JS.literal(from)} end diff --git a/lib/elixir_script/passes/output.ex b/lib/elixir_script/passes/output.ex index a2d3e2fc..26522a4b 100644 --- a/lib/elixir_script/passes/output.ex +++ b/lib/elixir_script/passes/output.ex @@ -19,6 +19,12 @@ defmodule ElixirScript.Output do opts = ModuleState.get_compiler_opts(pid) + #TODO: Combine Mix.Project.config()[:app] with Mix.Project.deps_paths() to + # get app names. + # File.exists? Path.join([:code.priv_dir(app), "src", "elixir_script"]) + # to find out if app has interop files. + # If so, copy files and directories to output folder + bundle(modules, opts, ModuleState.js_modules(pid)) |> output(Map.get(opts, :output)) end diff --git a/lib/elixir_script/passes/output/js_module.ex b/lib/elixir_script/passes/output/js_module.ex index 79f22a83..a5cea45f 100644 --- a/lib/elixir_script/passes/output/js_module.ex +++ b/lib/elixir_script/passes/output/js_module.ex @@ -11,15 +11,10 @@ defmodule ElixirScript.Output.JSModule do elixir = J.variable_declaration([declarator], :const) - table_additions = Enum.map(js_modules, fn - {module, _} -> add_import_to_table(module) - {module, _, _} -> add_import_to_table(module) - end) - ast = opts.module_formatter.build( [], js_modules, - [elixir, create_atom_table(), start(), load()] ++ table_additions ++ body, + [elixir, create_atom_table(), start(), load()] ++ body, J.identifier("Elixir") ) @@ -99,26 +94,4 @@ defmodule ElixirScript.Output.JSModule do ) end - defp add_import_to_table(module_name) do - ref = ElixirScript.Translate.Identifier.make_namespace_members(module_name) - J.assignment_expression( - :=, - J.member_expression( - J.member_expression( - J.identifier("Elixir"), - J.identifier("__table__") - ), - J.call_expression( - J.member_expression( - J.identifier("Symbol"), - J.identifier("for") - ), - [J.literal(ref.name)] - ), - true - ), - ref - ) - end - end \ No newline at end of file diff --git a/lib/elixir_script/passes/translate/forms/remote.ex b/lib/elixir_script/passes/translate/forms/remote.ex index 93b186cc..c0ea3363 100644 --- a/lib/elixir_script/passes/translate/forms/remote.ex +++ b/lib/elixir_script/passes/translate/forms/remote.ex @@ -3,6 +3,7 @@ defmodule ElixirScript.Translate.Forms.Remote do alias ESTree.Tools.Builder, as: J alias ElixirScript.Translate.{Form, Identifier} + alias ElixirScript.State, as: ModuleState @erlang_modules [ :erlang, @@ -166,8 +167,9 @@ defmodule ElixirScript.Translate.Forms.Remote do Form.compile!(module, state) end - defp process_js_module_name(module, _) do - Identifier.make_namespace_members(module) + defp process_js_module_name(module, state) do + name = ModuleState.get_js_module_name(state.pid, module) + J.identifier(name) end defp erlang_compat_function(module, function) do diff --git a/lib/elixir_script/passes/translate/module.ex b/lib/elixir_script/passes/translate/module.ex index 049bfda0..df98c5c1 100644 --- a/lib/elixir_script/passes/translate/module.ex +++ b/lib/elixir_script/passes/translate/module.ex @@ -12,8 +12,8 @@ defmodule ElixirScript.Translate.Module do ElixirScript.Translate.Protocol.compile(module, info, pid) end - def compile(module, %{attributes: [__foreign_info__: %{path: path}]}, pid) do - ModuleState.put_javascript_module(pid, module, path) + def compile(module, %{attributes: [__foreign_info__: %{path: path, name: name}]}, pid) do + ModuleState.put_javascript_module(pid, name, path) nil end diff --git a/lib/elixir_script/state.ex b/lib/elixir_script/state.ex index 464f43eb..ed47108d 100644 --- a/lib/elixir_script/state.ex +++ b/lib/elixir_script/state.ex @@ -58,10 +58,10 @@ defmodule ElixirScript.State do end) end - def put_javascript_module(pid, module, path) do + def put_javascript_module(pid, module, name, path) do Agent.update(pid, fn(state) -> js_modules = Map.get(state, :js_modules, []) - js_modules = js_modules ++ [{module, path}] + js_modules = js_modules ++ [{module, name, path}] %{ state | js_modules: js_modules } end) @@ -71,10 +71,8 @@ defmodule ElixirScript.State do Agent.get(pid, fn(state) -> state.js_modules |> Enum.map(fn - {module_name, _path} -> - module_name - {module_name, _path, _opts} -> - module_name + {module, _name, _path} -> + module end) end) end @@ -82,10 +80,14 @@ defmodule ElixirScript.State do def js_modules(pid) do Agent.get(pid, fn(state) -> state.js_modules - |> Enum.filter(fn - {_, nil} -> false - _ -> true - end) + end) + end + + def get_js_module_name(pid, module) do + Agent.get(pid, fn(state) -> + {_, name, _} = state.js_modules + |> Enum.find(fn {m, _, _} -> module == m end) + name end) end diff --git a/test/support/json.ex b/test/support/json.ex index a3c7e349..d87ff485 100644 --- a/test/support/json.ex +++ b/test/support/json.ex @@ -1,4 +1,4 @@ -defmodule JSON do +defmodule Data.JSON do use ElixirScript.FFI foreign stringify(map) From b15c487e2d29f0d3c74f7a04cb9046a2ad437ff2 Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Thu, 13 Jul 2017 21:40:44 -0500 Subject: [PATCH 602/860] Add global option to FFI. Fixed copy of js files to output path --- lib/elixir_script/cli.ex | 33 +---------- lib/elixir_script/compiler.ex | 1 - lib/elixir_script/ffi.ex | 14 ++--- lib/elixir_script/lib/store.ex | 2 +- lib/elixir_script/lib/string.ex | 6 +- lib/elixir_script/passes/find_used_modules.ex | 14 ++++- lib/elixir_script/passes/output.ex | 55 +++++++++++++++---- .../passes/translate/forms/remote.ex | 9 ++- lib/elixir_script/passes/translate/module.ex | 7 ++- lib/elixir_script/state.ex | 1 - lib/mix/tasks/compile.elixir_script.ex | 3 +- .../lib/core/erlang_compat/erlang.js | 12 +++- test/cli_test.exs | 6 -- test/passes/translate/forms/js_test.exs | 38 ------------- test/support/main.ex | 6 +- 15 files changed, 93 insertions(+), 114 deletions(-) diff --git a/lib/elixir_script/cli.ex b/lib/elixir_script/cli.ex index fd27b355..79ffcd80 100644 --- a/lib/elixir_script/cli.ex +++ b/lib/elixir_script/cli.ex @@ -8,8 +8,7 @@ defmodule ElixirScript.CLI do help: :boolean, version: :boolean, watch: :boolean, - format: :string, - js_module: [:string, :keep] + format: :string ] @aliases [ @@ -43,8 +42,6 @@ defmodule ElixirScript.CLI do the entry module of your application options: - --js-module [:] A js module used in your code. ex: React:react - Multiple can be defined -f --format [format] module format of output. options: es (default), common, umd -o --output [path] places output at the given path. Can be a directory or filename. @@ -72,13 +69,9 @@ defmodule ElixirScript.CLI do def do_process(input, options) do {watch, options} = Keyword.pop(options, :watch, false) - js_modules = Keyword.get_values(options, :js_module) - |> build_js_modules - compile_opts = [ output: Keyword.get(options, :output, :stdout), - format: String.to_atom(Keyword.get(options, :format, "es")), - js_modules: js_modules, + format: String.to_atom(Keyword.get(options, :format, "es")) ] input = handle_input(input) @@ -106,26 +99,4 @@ defmodule ElixirScript.CLI do |> List.flatten |> Enum.map(fn(x) -> Module.concat([x]) end) end - - defp build_js_modules(values) do - values - |> Enum.map(fn x -> - [identifier, path] = String.split(x, ":", trim: true) - { format_identifier(identifier), format_path(path) } - end) - end - - defp format_identifier(id) do - id - |> String.split(".") - |> Module.concat - end - - - defp format_path(path) do - path - |> String.replace("\"", "") - |> String.replace("`", "") - |> String.replace("'", "") - end end diff --git a/lib/elixir_script/compiler.ex b/lib/elixir_script/compiler.ex index 79fe7238..1c2d9c85 100644 --- a/lib/elixir_script/compiler.ex +++ b/lib/elixir_script/compiler.ex @@ -39,7 +39,6 @@ defmodule ElixirScript.Compiler do default_options = Map.new |> Map.put(:output, Keyword.get(opts, :output)) |> Map.put(:format, Keyword.get(opts, :format, :es)) - |> Map.put(:js_modules, Keyword.get(opts, :js_modules, [])) |> Map.put(:entry_modules, entry_modules) options = default_options diff --git a/lib/elixir_script/ffi.ex b/lib/elixir_script/ffi.ex index 890a6913..80114588 100644 --- a/lib/elixir_script/ffi.ex +++ b/lib/elixir_script/ffi.ex @@ -1,15 +1,13 @@ defmodule ElixirScript.FFI do - defmacro __using__(_) do - js_path = Path.join([".", Macro.underscore(__MODULE__)]) - - js_name = __MODULE__ - |> Module.split() - |> Enum.join("_") - + defmacro __using__(opts) do quote do import ElixirScript.FFI Module.register_attribute __MODULE__, :__foreign_info__, persist: true - @__foreign_info__ %{path: unquote(js_path), name: unquote(js_name)} + @__foreign_info__ %{ + path: Macro.underscore(__MODULE__), + name: Enum.join(Module.split(__MODULE__), "_"), + global: unquote(Keyword.get(opts, :global, false)) + } end end diff --git a/lib/elixir_script/lib/store.ex b/lib/elixir_script/lib/store.ex index dd6b4a7a..14447d9d 100644 --- a/lib/elixir_script/lib/store.ex +++ b/lib/elixir_script/lib/store.ex @@ -1,6 +1,6 @@ defmodule Bootstrap.Core.Store do @moduledoc false - use ElixirScript.FFI + use ElixirScript.FFI, global: true foreign create(value, name \\ nil) diff --git a/lib/elixir_script/lib/string.ex b/lib/elixir_script/lib/string.ex index 1ad3d9bf..d692f815 100644 --- a/lib/elixir_script/lib/string.ex +++ b/lib/elixir_script/lib/string.ex @@ -15,15 +15,15 @@ defmodule ElixirScript.String do end def to_float(str) do - JS.parseFloat(str) + :erlang.binary_to_float(str) end def to_integer(str) do - JS.parseInt(str, 10) + :erlang.binary_to_integer(str) end def to_integer(str, base) do - JS.parseInt(str, base) + :erlang.binary_to_integer(str, base) end def upcase(str) do diff --git a/lib/elixir_script/passes/find_used_modules.ex b/lib/elixir_script/passes/find_used_modules.ex index ccd94136..e352a935 100644 --- a/lib/elixir_script/passes/find_used_modules.ex +++ b/lib/elixir_script/passes/find_used_modules.ex @@ -25,6 +25,16 @@ defmodule ElixirScript.FindUsedModules do end end + defp walk_module(module, %{attributes: [__foreign_info__: %{path: path, name: name, global: global}]} = info, pid) do + path = if global, do: nil, else: path + name = if global, do: module, else: name + + ModuleState.put_javascript_module(pid, module, name, path) + ModuleState.put_module(pid, module, info) + + nil + end + defp walk_module(module, info, pid) do %{ attributes: _attrs, @@ -232,7 +242,7 @@ defmodule ElixirScript.FindUsedModules do walk({function, [], params}, state) end - defp walk({{:., _, [module, function]} = ast, _, params}, state) do + defp walk({{:., _, [_module, _function]} = ast, _, params}, state) do walk(ast, state) walk(params, state) end @@ -243,8 +253,6 @@ defmodule ElixirScript.FindUsedModules do defp walk({:., _, [module, function]}, state) do cond do - ElixirScript.Translate.Module.is_js_module(module, state) -> - nil ElixirScript.Translate.Module.is_elixir_module(module) -> if ModuleState.get_module(state.pid, module) == nil do execute(module, state.pid) diff --git a/lib/elixir_script/passes/output.ex b/lib/elixir_script/passes/output.ex index 26522a4b..7b6575b1 100644 --- a/lib/elixir_script/passes/output.ex +++ b/lib/elixir_script/passes/output.ex @@ -19,14 +19,18 @@ defmodule ElixirScript.Output do opts = ModuleState.get_compiler_opts(pid) - #TODO: Combine Mix.Project.config()[:app] with Mix.Project.deps_paths() to - # get app names. - # File.exists? Path.join([:code.priv_dir(app), "src", "elixir_script"]) - # to find out if app has interop files. - # If so, copy files and directories to output folder - - bundle(modules, opts, ModuleState.js_modules(pid)) - |> output(Map.get(opts, :output)) + js_modules = ModuleState.js_modules(pid) + |> Enum.filter(fn + {_module, _name, nil} -> false + _ -> true + end) + |> Enum.map(fn + {module, name, path} -> + {module, name, Path.join(".", path)} + end) + + bundle(modules, opts, js_modules) + |> output(Map.get(opts, :output), js_modules) end defp bundle(modules, opts, js_modules) do @@ -61,21 +65,27 @@ defmodule ElixirScript.Output do end end - defp output(code, nil) do + defp output(code, nil, _) do code end - defp output(code, :stdout) do + defp output(code, :stdout, _) do IO.puts(code) end - defp output(code, path) do + defp output(code, path, js_modules) do file_name = get_output_file_name(path) if !File.exists?(Path.dirname(file_name)) do File.mkdir_p!(Path.dirname(file_name)) end + apps = get_app_names() + output_dir = Path.dirname(file_name) + Enum.each(js_modules, fn({_, _, path}) -> + copy_javascript_module(apps, output_dir, path) + end) + File.write!(file_name, code) end @@ -87,4 +97,27 @@ defmodule ElixirScript.Output do Path.join([path, @generated_name]) end end + + defp get_app_names() do + Mix.Project.config()[:app] + deps = Mix.Project.deps_paths() + |> Map.keys + + [Mix.Project.config()[:app]] ++ deps + end + + defp copy_javascript_module(apps, output_dir, js_module_path) do + Enum.each(apps, fn(app) -> + full_path = Path.join([:code.priv_dir(app), "elixir_script", js_module_path]) <> ".js" + + if File.exists?(full_path) do + js_output_path = Path.join(output_dir, js_module_path) <> ".js" + if !File.exists?(Path.dirname(js_output_path)) do + File.mkdir_p!(Path.dirname(js_output_path)) + end + + File.cp(full_path, js_output_path) + end + end) + end end \ No newline at end of file diff --git a/lib/elixir_script/passes/translate/forms/remote.ex b/lib/elixir_script/passes/translate/forms/remote.ex index c0ea3363..8651e557 100644 --- a/lib/elixir_script/passes/translate/forms/remote.ex +++ b/lib/elixir_script/passes/translate/forms/remote.ex @@ -168,8 +168,13 @@ defmodule ElixirScript.Translate.Forms.Remote do end defp process_js_module_name(module, state) do - name = ModuleState.get_js_module_name(state.pid, module) - J.identifier(name) + case ModuleState.get_js_module_name(state.pid, module) do + name when is_atom(name) -> + members = Module.split(module) + Identifier.make_namespace_members(members) + name -> + J.identifier(name) + end end defp erlang_compat_function(module, function) do diff --git a/lib/elixir_script/passes/translate/module.ex b/lib/elixir_script/passes/translate/module.ex index df98c5c1..7dde8c3e 100644 --- a/lib/elixir_script/passes/translate/module.ex +++ b/lib/elixir_script/passes/translate/module.ex @@ -12,8 +12,11 @@ defmodule ElixirScript.Translate.Module do ElixirScript.Translate.Protocol.compile(module, info, pid) end - def compile(module, %{attributes: [__foreign_info__: %{path: path, name: name}]}, pid) do - ModuleState.put_javascript_module(pid, name, path) + def compile(module, %{attributes: [__foreign_info__: %{path: path, name: name, global: global}]}, pid) do + path = if global, do: nil, else: path + name = if global, do: module, else: name + + ModuleState.put_javascript_module(pid, module, name, path) nil end diff --git a/lib/elixir_script/state.ex b/lib/elixir_script/state.ex index ed47108d..50ff4cb7 100644 --- a/lib/elixir_script/state.ex +++ b/lib/elixir_script/state.ex @@ -62,7 +62,6 @@ defmodule ElixirScript.State do Agent.update(pid, fn(state) -> js_modules = Map.get(state, :js_modules, []) js_modules = js_modules ++ [{module, name, path}] - %{ state | js_modules: js_modules } end) end diff --git a/lib/mix/tasks/compile.elixir_script.ex b/lib/mix/tasks/compile.elixir_script.ex index b01abbcb..1e6067e2 100644 --- a/lib/mix/tasks/compile.elixir_script.ex +++ b/lib/mix/tasks/compile.elixir_script.ex @@ -65,8 +65,7 @@ defmodule Mix.Tasks.Compile.ElixirScript do input = Keyword.fetch!(elixirscript_config, :input) opts = [ output: Keyword.get(elixirscript_config, :output), - format: Keyword.get(elixirscript_config, :format), - js_modules: Keyword.get(elixirscript_config, :js_modules, []) + format: Keyword.get(elixirscript_config, :format) ] {input, opts} diff --git a/src/javascript/lib/core/erlang_compat/erlang.js b/src/javascript/lib/core/erlang_compat/erlang.js index aefbf7b7..5a0bc2d4 100644 --- a/src/javascript/lib/core/erlang_compat/erlang.js +++ b/src/javascript/lib/core/erlang_compat/erlang.js @@ -309,6 +309,14 @@ function tuple_size(tuple) { return tuple.length; } +function binary_to_float(str) { + return parseFloat(str); +} + +function binary_to_integer(str, base = 10) { + return parseInt(str, base); +} + export default { atom_to_binary, binary_to_atom, @@ -372,5 +380,7 @@ export default { round, tl, trunc, - tuple_size + tuple_size, + binary_to_float, + binary_to_integer }; diff --git a/test/cli_test.exs b/test/cli_test.exs index 53589cc9..b08c1d93 100644 --- a/test/cli_test.exs +++ b/test/cli_test.exs @@ -30,10 +30,4 @@ defmodule ElixirScript.CLI.Test do ElixirScript.CLI.process({["Atom"], []}) end) =~ "export default Elixir" end - - test "process js modules" do - assert capture_io(fn -> - ElixirScript.CLI.process({["Atom"], [js_module: "React:react"]}) - end) =~ "import React from 'react'" - end end \ No newline at end of file diff --git a/test/passes/translate/forms/js_test.exs b/test/passes/translate/forms/js_test.exs index c6d7c121..31bf2af3 100644 --- a/test/passes/translate/forms/js_test.exs +++ b/test/passes/translate/forms/js_test.exs @@ -64,42 +64,4 @@ defmodule ElixirScript.Translate.Forms.JS.Test do [J.literal("react")] ) end - - test "global function or property" do - ast = {{:., [], [JS, :self]}, [], []} - state = %{function: {:each, nil}, module: Enum, vars: %{:_ => 0, "entry" => 0, "enumerable" => 0, "fun" => 0}} - - {js_ast, _} = Form.compile(ast, state) - assert js_ast == J.call_expression( - ElixirScript.Translate.Forms.JS.call_property(), - [ - ElixirScript.Translate.Forms.JS.global(), - J.literal("self") - ] - ) - end - - test "global function with params" do - ast = {{:., [], [JS, :self]}, [], ["something"]} - state = %{function: {:each, nil}, module: Enum, vars: %{:_ => 0, "entry" => 0, "enumerable" => 0, "fun" => 0}} - - {js_ast, _} = Form.compile(ast, state) - assert js_ast == J.call_expression( - J.identifier(:self), - [J.literal("something")] - ) - end - - test "JavaScript module call", %{state: state} do - ast = {{:., [], [JS.Object, :keys]}, [], [{:obj, [], nil}]} - - {js_ast, _} = Form.compile(ast, state) - assert js_ast == J.call_expression( - J.member_expression( - J.identifier("Object"), - J.identifier("keys") - ), - [J.identifier("obj")] - ) - end end \ No newline at end of file diff --git a/test/support/main.ex b/test/support/main.ex index d32cd32e..99e3158b 100644 --- a/test/support/main.ex +++ b/test/support/main.ex @@ -1,9 +1,7 @@ defmodule Main do def start(:normal, [callback]) do callback.("started") - - JSON.stringify(%{}) - - Enum.each(1..3, fn x -> JS.console.log(x) end) + Agent.start(fn() -> nil end) + Data.JSON.stringify(%{}) end end From ce9d1d3fd83ca5a2250b93a5fa17ee00b872b5aa Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Thu, 13 Jul 2017 21:55:47 -0500 Subject: [PATCH 603/860] Update documentation --- CHANGELOG.md | 8 ++++++++ lib/elixir_script/ffi.ex | 4 ++++ lib/elixir_script/passes/translate/function.ex | 3 +-- 3 files changed, 13 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index b484b9e3..e3f5598c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,14 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](http://keepachangelog.com/) and this project adheres to [Semantic Versioning](http://semver.org/). +## [Unreleased] + +### Added +- ElixirScript now has an FFI layer for interoperability with JavaScript. For more details, see documentation at `ElixirScript.FFI` + +### Changed +- Compiler has been completely rewritten. ElixirScript now requires Erlang 20+ and Elixir 1.5+ + ## [0.28.0] - 2017-06-11 ### Added diff --git a/lib/elixir_script/ffi.ex b/lib/elixir_script/ffi.ex index 80114588..9c8e0363 100644 --- a/lib/elixir_script/ffi.ex +++ b/lib/elixir_script/ffi.ex @@ -1,4 +1,8 @@ defmodule ElixirScript.FFI do + @moduledoc """ + The foreign function interface for interoperability with JavaScript. + """ + defmacro __using__(opts) do quote do import ElixirScript.FFI diff --git a/lib/elixir_script/passes/translate/function.ex b/lib/elixir_script/passes/translate/function.ex index 148fe2ad..ecd353cf 100644 --- a/lib/elixir_script/passes/translate/function.ex +++ b/lib/elixir_script/passes/translate/function.ex @@ -5,8 +5,7 @@ defmodule ElixirScript.Translate.Function do @moduledoc """ Translates the given Elixir function AST into the - equivalent JavaScript AST. Function names are - + equivalent JavaScript AST. """ def patterns_ast() do From f4d45872c0183254116ee7901c8c8e39ac0153cc Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Thu, 13 Jul 2017 22:26:01 -0500 Subject: [PATCH 604/860] Update documentation for FFI module --- lib/elixir_script/ffi.ex | 29 +++++++++++++++++++++++++++++ test/support/main.ex | 2 -- 2 files changed, 29 insertions(+), 2 deletions(-) diff --git a/lib/elixir_script/ffi.ex b/lib/elixir_script/ffi.ex index 9c8e0363..a8130194 100644 --- a/lib/elixir_script/ffi.ex +++ b/lib/elixir_script/ffi.ex @@ -1,6 +1,35 @@ defmodule ElixirScript.FFI do @moduledoc """ The foreign function interface for interoperability with JavaScript. + + Define foreign modules with `use ElixirScript.FFI`. + Next to define functions for the foreign module, use the `foreign` macro. + + Here is an example of a foreign module for a JSON module + + ```elixir + defmodule MyApp.JSON do + use ElixirScript.FFI + + foreign stringify(map) + foreign parse(string) + end + ``` + + Foreign modules must have an equivalent JavaScript module. + ElixirScript expects JavaScript modules to be in the `priv/elixir_script` directory. + These modules will be copied to the output directory upon compilation. + + In the example, a JavaScript file must be at `priv/elixir_script/my_app/json.js`. + It looks like this + ```javascript + export default { + stringify: JSON.stringify, + parse: JSON.parse + } + ``` + + The JavaScript module must export a default object with the foreign functions defined in the Elixir module """ defmacro __using__(opts) do diff --git a/test/support/main.ex b/test/support/main.ex index 99e3158b..a18d3d90 100644 --- a/test/support/main.ex +++ b/test/support/main.ex @@ -1,7 +1,5 @@ defmodule Main do def start(:normal, [callback]) do callback.("started") - Agent.start(fn() -> nil end) - Data.JSON.stringify(%{}) end end From 69c327451670ca596e1994db8fae242d240c99a0 Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Fri, 14 Jul 2017 20:21:57 -0500 Subject: [PATCH 605/860] Update FFI documentation --- JavascriptInterop.md | 58 +++++++++++++--------------------------- lib/elixir_script/ffi.ex | 24 +++++++++++------ 2 files changed, 35 insertions(+), 47 deletions(-) diff --git a/JavascriptInterop.md b/JavascriptInterop.md index db0c0e45..de8bf745 100644 --- a/JavascriptInterop.md +++ b/JavascriptInterop.md @@ -13,55 +13,35 @@ JS.debugger() # Getting the type of a value JS.typeof(my_value) - -# Creating a new JavaScript Map -map = JS.new(JS.Map, []) ``` -### Accessing Global Objects, Functions, and Properties - -In order to interact with JavaScript things in the global scope, append "JS" to them. The global scope corresponds to whatever the global object is in the JavaScript environment you are in. For example, in a browser this would be `window` or `self`: +### Foreign Function Interface -```elixir -# Calling alert -JS.alert("hello") +ElixirScript calls JavaScript modules through a Foreign Function Interface (FFI). A foreign module is defined by creating a new module and adding `use ElixirScript.FFI` to it. -# Calling a method on Object -JS.Object.keys(my_object) +Here is an example of a foreign module for a JSON module -# Creating a new JavaScript Date -JS.new(JS.Date, []) +```elixir +defmodule MyApp.JSON do + use ElixirScript.FFI -# Getting the outer width -JS.outerWidth + foreign stringify(map) + foreign parse(string) +end ``` -### JavaScript modules - -ElixirScript can use JavaScript modules from the supported modules systems. -In order to do so, you must tell ElixirScript about them upfront. +Foreign modules map to JavaScript files that export functions defined with the `foreign` macro. +ElixirScript expects JavaScript modules to be in the `priv/elixir_script` directory. +These modules are copied to the output directory upon compilation. -If using ElixirScript in a mix project, you can do so inside of the ElixirScript configuration keyword list +For our example, a JavaScript file must be placed at `priv/elixir_script/my_app/json.js`. -```elixir - def project do - [ - app: :my_project, - elixir_script: [ - format: :es, - js_modules: [ - {React, "react"}, - {ReactDOM, "react-dom"} - ] - ] - ] - end -``` - -Interacting with these modules works the same as interacting with an ElixirScript module - -```elixir -React.createElement(...) +It looks like this +```javascript +export default { + stringify: JSON.stringify, + parse: JSON.parse +} ``` ## JavaScript Calling ElixirScript diff --git a/lib/elixir_script/ffi.ex b/lib/elixir_script/ffi.ex index a8130194..abffc29b 100644 --- a/lib/elixir_script/ffi.ex +++ b/lib/elixir_script/ffi.ex @@ -1,9 +1,9 @@ defmodule ElixirScript.FFI do @moduledoc """ - The foreign function interface for interoperability with JavaScript. + The foreign function interface for interacting with JavaScript - Define foreign modules with `use ElixirScript.FFI`. - Next to define functions for the foreign module, use the `foreign` macro. + To define a foreign module, make a new module and add `use ElixirScript.FFI`. to it + To define foreign functions, use the `foreign` macro. Here is an example of a foreign module for a JSON module @@ -16,11 +16,12 @@ defmodule ElixirScript.FFI do end ``` - Foreign modules must have an equivalent JavaScript module. + Foreign modules map to JavaScript files that export functions defined with the `foreign` macro. ElixirScript expects JavaScript modules to be in the `priv/elixir_script` directory. - These modules will be copied to the output directory upon compilation. + These modules are copied to the output directory upon compilation. + + For our example, a JavaScript file must be placed at `priv/elixir_script/my_app/json.js`. - In the example, a JavaScript file must be at `priv/elixir_script/my_app/json.js`. It looks like this ```javascript export default { @@ -28,8 +29,6 @@ defmodule ElixirScript.FFI do parse: JSON.parse } ``` - - The JavaScript module must export a default object with the foreign functions defined in the Elixir module """ defmacro __using__(opts) do @@ -44,6 +43,15 @@ defmodule ElixirScript.FFI do end end + @doc """ + Defines a JavaScript function to be called from Elixir modules + + To define a foreign function, pass the name and arguments to `foreign` + + ```elixir + foreign my_js_function(arg1, arg2, arg3) + ``` + """ defmacro foreign({name, _, args}) do quote do def unquote(name)(unquote_splicing(args)), do: nil From f5b09cb6e047f7b9d4c1b9fa31ff65fe9deead48 Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Fri, 14 Jul 2017 20:44:43 -0500 Subject: [PATCH 606/860] Add test for FFI output. Refactor debug_info for ElixirScript replacements --- lib/elixir_script/beam.ex | 18 ++++-------------- test/compiler_test.exs | 8 +++++++- test/support/main.ex | 2 ++ 3 files changed, 13 insertions(+), 15 deletions(-) diff --git a/lib/elixir_script/beam.ex b/lib/elixir_script/beam.ex index d8cb7213..e850d837 100644 --- a/lib/elixir_script/beam.ex +++ b/lib/elixir_script/beam.ex @@ -10,21 +10,11 @@ defmodule ElixirScript.Beam do @spec debug_info(atom) :: {:ok | :error, map | binary} def debug_info(module) - #Replacing String module with our ElixirScript's version - def debug_info(String) do - case debug_info(ElixirScript.String) do + #Replace some modules with ElixirScript versions + def debug_info(module) when module in [String, Agent] do + case debug_info(Module.concat(ElixirScript, module)) do {:ok, info} -> - {:ok, Map.put(info, :module, String)} - e -> - e - end - end - - #Replacing Agent module with our ElixirScript's version - def debug_info(Agent) do - case debug_info(ElixirScript.Agent) do - {:ok, info} -> - {:ok, Map.put(info, :module, Agent)} + {:ok, Map.put(info, :module, module)} e -> e end diff --git a/test/compiler_test.exs b/test/compiler_test.exs index c154e67c..5651ec05 100644 --- a/test/compiler_test.exs +++ b/test/compiler_test.exs @@ -6,8 +6,14 @@ defmodule ElixirScript.Compiler.Test do assert is_binary(result) end + test "Use defined module with FFI module" do + result = ElixirScript.Compiler.compile(Main) + assert is_binary(result) + assert result =~ "import Data_JSON from './data/json'" + end + test "Can compile multiple entry modules" do - result = ElixirScript.Compiler.compile([Atom, String]) + result = ElixirScript.Compiler.compile([Atom, String, Agent]) assert is_binary(result) end diff --git a/test/support/main.ex b/test/support/main.ex index a18d3d90..8cdf51d8 100644 --- a/test/support/main.ex +++ b/test/support/main.ex @@ -1,5 +1,7 @@ defmodule Main do def start(:normal, [callback]) do callback.("started") + + Data.JSON.stringify(1) end end From 95efb4b1b481b754d7b76698806ebd2a04d62e42 Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Fri, 14 Jul 2017 20:47:20 -0500 Subject: [PATCH 607/860] Test FFI JavaScript file moved to output folder --- test/compiler_test.exs | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/test/compiler_test.exs b/test/compiler_test.exs index 5651ec05..a2a3cce3 100644 --- a/test/compiler_test.exs +++ b/test/compiler_test.exs @@ -52,4 +52,12 @@ defmodule ElixirScript.Compiler.Test do result = ElixirScript.Compiler.compile(Atom, [output: path]) assert File.exists?(path) end + + test "Output with FFI" do + path = System.tmp_dir() + + result = ElixirScript.Compiler.compile(Main, [output: path]) + assert File.exists?(Path.join([path, "Elixir.App.js"])) + assert File.exists?(Path.join([path, "data", "json.js"])) + end end \ No newline at end of file From 43636b34351078e6de553a742a9ebafd86fefb77 Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Sat, 15 Jul 2017 07:20:56 -0500 Subject: [PATCH 608/860] Remove test json ffi module --- test/compiler_test.exs | 14 -------------- test/support/json.ex | 6 ------ test/support/main.ex | 2 -- 3 files changed, 22 deletions(-) delete mode 100644 test/support/json.ex diff --git a/test/compiler_test.exs b/test/compiler_test.exs index a2a3cce3..f41aa7bf 100644 --- a/test/compiler_test.exs +++ b/test/compiler_test.exs @@ -6,12 +6,6 @@ defmodule ElixirScript.Compiler.Test do assert is_binary(result) end - test "Use defined module with FFI module" do - result = ElixirScript.Compiler.compile(Main) - assert is_binary(result) - assert result =~ "import Data_JSON from './data/json'" - end - test "Can compile multiple entry modules" do result = ElixirScript.Compiler.compile([Atom, String, Agent]) assert is_binary(result) @@ -52,12 +46,4 @@ defmodule ElixirScript.Compiler.Test do result = ElixirScript.Compiler.compile(Atom, [output: path]) assert File.exists?(path) end - - test "Output with FFI" do - path = System.tmp_dir() - - result = ElixirScript.Compiler.compile(Main, [output: path]) - assert File.exists?(Path.join([path, "Elixir.App.js"])) - assert File.exists?(Path.join([path, "data", "json.js"])) - end end \ No newline at end of file diff --git a/test/support/json.ex b/test/support/json.ex deleted file mode 100644 index d87ff485..00000000 --- a/test/support/json.ex +++ /dev/null @@ -1,6 +0,0 @@ -defmodule Data.JSON do - use ElixirScript.FFI - - foreign stringify(map) - foreign parse(string) -end \ No newline at end of file diff --git a/test/support/main.ex b/test/support/main.ex index 8cdf51d8..a18d3d90 100644 --- a/test/support/main.ex +++ b/test/support/main.ex @@ -1,7 +1,5 @@ defmodule Main do def start(:normal, [callback]) do callback.("started") - - Data.JSON.stringify(1) end end From 729927ce28c2ad6b766eede9ff9859eeddc28319 Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Sat, 15 Jul 2017 07:41:58 -0500 Subject: [PATCH 609/860] Refactoring. Update dependencies --- lib/elixir_script/passes/translate/forms/remote.ex | 6 +----- lib/elixir_script/passes/translate/identifier.ex | 4 ---- mix.lock | 6 +++--- 3 files changed, 4 insertions(+), 12 deletions(-) diff --git a/lib/elixir_script/passes/translate/forms/remote.ex b/lib/elixir_script/passes/translate/forms/remote.ex index 8651e557..c09a065d 100644 --- a/lib/elixir_script/passes/translate/forms/remote.ex +++ b/lib/elixir_script/passes/translate/forms/remote.ex @@ -126,11 +126,7 @@ defmodule ElixirScript.Translate.Forms.Remote do end def compile({:., _, [module, function]}, state) do - function_name = if ElixirScript.Translate.Module.is_js_module(module, state) do - ElixirScript.Translate.Identifier.make_extern_function_name(function) - else - ElixirScript.Translate.Identifier.make_function_name(function) - end + function_name = ElixirScript.Translate.Identifier.make_function_name(function) ast = J.member_expression( process_module_name(module, state), diff --git a/lib/elixir_script/passes/translate/identifier.ex b/lib/elixir_script/passes/translate/identifier.ex index e91c02d2..a619f1fa 100644 --- a/lib/elixir_script/passes/translate/identifier.ex +++ b/lib/elixir_script/passes/translate/identifier.ex @@ -75,8 +75,4 @@ defmodule ElixirScript.Translate.Identifier do J.identifier(name) end - def make_extern_function_name(name) do - J.identifier("#{name}") - end - end diff --git a/mix.lock b/mix.lock index 9de5d64f..992c5f2f 100644 --- a/mix.lock +++ b/mix.lock @@ -1,10 +1,10 @@ %{"bunt": {:hex, :bunt, "0.2.0", "951c6e801e8b1d2cbe58ebbd3e616a869061ddadcc4863d0a2182541acae9a38", [:mix], [], "hexpm"}, "certifi": {:hex, :certifi, "1.2.1", "c3904f192bd5284e5b13f20db3ceac9626e14eeacfbb492e19583cf0e37b22be", [:rebar3], [], "hexpm"}, - "credo": {:hex, :credo, "0.8.1", "137efcc99b4bc507c958ba9b5dff70149e971250813cbe7d4537ec7e36997402", [:mix], [{:bunt, "~> 0.2.0", [hex: :bunt, repo: "hexpm", optional: false]}], "hexpm"}, + "credo": {:hex, :credo, "0.8.3", "efe6e9078de64cefdd25d8df7a97292e29e63f42a8988990340eaf1f40d93224", [:mix], [{:bunt, "~> 0.2.0", [hex: :bunt, repo: "hexpm", optional: false]}], "hexpm"}, "earmark": {:hex, :earmark, "1.2.2", "f718159d6b65068e8daeef709ccddae5f7fdc770707d82e7d126f584cd925b74", [:mix], [], "hexpm"}, "estree": {:hex, :estree, "2.6.0", "86a301b0c355fa55c19e7ef9dceb1b1e983c6df526a2b7846818a38c258fc3fb", [:mix], [], "hexpm"}, - "ex_doc": {:hex, :ex_doc, "0.16.1", "b4b8a23602b4ce0e9a5a960a81260d1f7b29635b9652c67e95b0c2f7ccee5e81", [:mix], [{:earmark, "~> 1.1", [hex: :earmark, repo: "hexpm", optional: false]}], "hexpm"}, - "excoveralls": {:hex, :excoveralls, "0.7.0", "05cb3332c2b0f799df3ab90eb7df1ae5a147c86776e91792848a12b7ed87242f", [:mix], [{:exjsx, ">= 3.0.0", [hex: :exjsx, repo: "hexpm", optional: false]}, {:hackney, ">= 0.12.0", [hex: :hackney, repo: "hexpm", optional: false]}], "hexpm"}, + "ex_doc": {:hex, :ex_doc, "0.16.2", "3b3e210ebcd85a7c76b4e73f85c5640c011d2a0b2f06dcdf5acdb2ae904e5084", [:mix], [{:earmark, "~> 1.1", [hex: :earmark, repo: "hexpm", optional: false]}], "hexpm"}, + "excoveralls": {:hex, :excoveralls, "0.7.1", "3dd659db19c290692b5e2c4a2365ae6d4488091a1ba58f62dcbdaa0c03da5491", [:mix], [{:exjsx, ">= 3.0.0", [hex: :exjsx, repo: "hexpm", optional: false]}, {:hackney, ">= 0.12.0", [hex: :hackney, repo: "hexpm", optional: false]}], "hexpm"}, "exjsx": {:hex, :exjsx, "4.0.0", "60548841e0212df401e38e63c0078ec57b33e7ea49b032c796ccad8cde794b5c", [:mix], [{:jsx, "~> 2.8.0", [hex: :jsx, repo: "hexpm", optional: false]}], "hexpm"}, "fs": {:hex, :fs, "3.4.0", "6d18575c250b415b3cad559e6f97a4c822516c7bc2c10bfbb2493a8f230f5132", [:rebar3], [], "hexpm"}, "hackney": {:hex, :hackney, "1.8.6", "21a725db3569b3fb11a6af17d5c5f654052ce9624219f1317e8639183de4a423", [:rebar3], [{:certifi, "1.2.1", [hex: :certifi, repo: "hexpm", optional: false]}, {:idna, "5.0.2", [hex: :idna, repo: "hexpm", optional: false]}, {:metrics, "1.0.1", [hex: :metrics, repo: "hexpm", optional: false]}, {:mimerl, "1.0.2", [hex: :mimerl, repo: "hexpm", optional: false]}, {:ssl_verify_fun, "1.1.1", [hex: :ssl_verify_fun, repo: "hexpm", optional: false]}], "hexpm"}, From caa147895af9f0bd542354427ed1b31fd5e8309d Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Sat, 15 Jul 2017 07:51:58 -0500 Subject: [PATCH 610/860] Add ffi test --- test/ffi_test.exs | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) create mode 100644 test/ffi_test.exs diff --git a/test/ffi_test.exs b/test/ffi_test.exs new file mode 100644 index 00000000..dbbaa77d --- /dev/null +++ b/test/ffi_test.exs @@ -0,0 +1,17 @@ +defmodule ElixirScript.FFI.Test do + use ExUnit.Case + + defmodule MyTestModule do + use ElixirScript.FFI + + foreign my_test_function(arg1, arg2) + end + + test "FFI module has __foreign_info__ attribute" do + assert Keyword.has_key?(MyTestModule.__info__(:attributes), :__foreign_info__) + end + + test "FFI module makes foreign function" do + assert Keyword.has_key?(MyTestModule.__info__(:functions), :my_test_function) + end +end \ No newline at end of file From 5ea4512ccfb377923b611b483282974fc1ed81c2 Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Sat, 15 Jul 2017 23:06:49 -0500 Subject: [PATCH 611/860] Implement with special form --- .tool-versions | 4 +- .../passes/find_used_functions.ex | 25 +++++++- lib/elixir_script/passes/find_used_modules.ex | 25 +++++++- lib/elixir_script/passes/translate/form.ex | 6 +- .../passes/translate/forms/with.ex | 61 +++++++++++++++++++ package.json | 4 +- src/javascript/lib/core/special_forms.js | 2 +- src/javascript/tests/with.spec.js | 3 +- test/support/main.ex | 10 +++ 9 files changed, 130 insertions(+), 10 deletions(-) create mode 100644 lib/elixir_script/passes/translate/forms/with.ex diff --git a/.tool-versions b/.tool-versions index 1c908046..1c12341c 100644 --- a/.tool-versions +++ b/.tool-versions @@ -1,3 +1,3 @@ erlang 20.0 -elixir ref-v1.5.0-rc.0 -nodejs 8.1.0 \ No newline at end of file +elixir ref-v1.5.0-rc.1 +nodejs 8.1.0 diff --git a/lib/elixir_script/passes/find_used_functions.ex b/lib/elixir_script/passes/find_used_functions.ex index 50177616..853749ce 100644 --- a/lib/elixir_script/passes/find_used_functions.ex +++ b/lib/elixir_script/passes/find_used_functions.ex @@ -216,6 +216,29 @@ defmodule ElixirScript.FindUsedFunctions do Enum.each(clauses, &walk(&1, state)) end + defp walk({:with, _, args}, state) do + Enum.each(args, fn + {:<-, _, [left, right]} -> + walk(left, state) + walk(right, state) + + {:=, _, [left, right]} -> + walk(left, state) + walk(right, state) + + [do: expression] -> + walk_block(expression, state) + + [do: expression, else: elses] -> + walk_block(expression, state) + Enum.each(elses, fn + {:->, _, [left, right]} -> + walk(left, state) + walk(right, state) + end) + end) + end + defp walk({{:., _, [:erlang, :apply]}, _, [module, function, params]}, state) do walk({{:., [], [module, function]}, [], params}, state) end @@ -272,4 +295,4 @@ defmodule ElixirScript.FindUsedFunctions do end end -end \ No newline at end of file +end diff --git a/lib/elixir_script/passes/find_used_modules.ex b/lib/elixir_script/passes/find_used_modules.ex index e352a935..8b2f066d 100644 --- a/lib/elixir_script/passes/find_used_modules.ex +++ b/lib/elixir_script/passes/find_used_modules.ex @@ -234,6 +234,29 @@ defmodule ElixirScript.FindUsedModules do Enum.each(clauses, &walk(&1, state)) end + defp walk({:with, _, args}, state) do + Enum.each(args, fn + {:<-, _, [left, right]} -> + walk(left, state) + walk(right, state) + + {:=, _, [left, right]} -> + walk(left, state) + walk(right, state) + + [do: expression] -> + walk_block(expression, state) + + [do: expression, else: elses] -> + walk_block(expression, state) + Enum.each(elses, fn + {:->, _, [left, right]} -> + walk(left, state) + walk(right, state) + end) + end) + end + defp walk({{:., _, [:erlang, :apply]}, _, [module, function, params]}, state) do walk({{:., [], [module, function]}, [], params}, state) end @@ -289,4 +312,4 @@ defmodule ElixirScript.FindUsedModules do end end -end \ No newline at end of file +end diff --git a/lib/elixir_script/passes/translate/form.ex b/lib/elixir_script/passes/translate/form.ex index 385156da..31776b3d 100644 --- a/lib/elixir_script/passes/translate/form.ex +++ b/lib/elixir_script/passes/translate/form.ex @@ -1,6 +1,6 @@ defmodule ElixirScript.Translate.Form do alias ESTree.Tools.Builder, as: J - alias ElixirScript.Translate.Forms.{Bitstring, Match, Try, For, Receive, Remote, Pattern} + alias ElixirScript.Translate.Forms.{Bitstring, Match, Try, For, Receive, Remote, Pattern, With} alias ElixirScript.Translate.Clause require Logger @@ -203,6 +203,10 @@ defmodule ElixirScript.Translate.Form do Try.compile(blocks, state) end + def compile({:with, _, args}, state) do + With.compile(args, state) + end + def compile({:fn, _, _} = ast, state) do ElixirScript.Translate.Function.compile(ast, state) end diff --git a/lib/elixir_script/passes/translate/forms/with.ex b/lib/elixir_script/passes/translate/forms/with.ex new file mode 100644 index 00000000..ad78ce22 --- /dev/null +++ b/lib/elixir_script/passes/translate/forms/with.ex @@ -0,0 +1,61 @@ +defmodule ElixirScript.Translate.Forms.With do + @moduledoc false + alias ESTree.Tools.Builder, as: JS + alias ElixirScript.Translate.{Function, Clause} + alias ElixirScript.Translate.Forms.Pattern + + + def compile(args, module_state) do + result = Enum.reduce(args, %{ expressions: [], arguments: [], module_state: module_state }, fn + {symbol, _, [pattern, body] }, state when symbol in [:<-, :=] -> + {ast, module_state} = Function.compile_block(body, state.module_state) + body = Clause.return_last_statement(ast) + expr_function = JS.arrow_function_expression(state.arguments, [], JS.block_statement(body)) + + { patterns, params, module_state } = Pattern.compile([pattern], module_state) + + %{state | arguments: state.arguments ++ params, + expressions: state.expressions ++ [ JS.array_expression([hd(patterns), expr_function]) ], + module_state: module_state + } + + [do: expr], state -> + expr_function = process_block(expr, state.arguments, state.module_state) + + %{state | expressions: state.expressions ++ [ expr_function ] } + [do: do_expr, else: else_expr], state -> + do_function = process_block(do_expr, state.arguments, state.module_state) + + { else_function, _ } = Function.compile({:fn, [], else_expr}, state.module_state) + + %{state | expressions: state.expressions ++ [ do_function, else_function ] } + end) + + expressions = result.expressions + + js_ast = JS.call_expression( + JS.member_expression( + JS.member_expression( + JS.identifier("Bootstrap"), + JS.member_expression( + JS.identifier("Core"), + JS.identifier("SpecialForms") + ) + ), + JS.identifier("_with") + ), + expressions + ) + + { js_ast, module_state } + + end + + + defp process_block(body, arguments, module_state) do + {ast, _} = Function.compile_block(body, module_state) + + body = Clause.return_last_statement(ast) + JS.arrow_function_expression(arguments, [], JS.block_statement(body)) + end +end diff --git a/package.json b/package.json index bb34b229..882c88a0 100644 --- a/package.json +++ b/package.json @@ -41,9 +41,7 @@ "sinon": "^1.17.7" }, "ava": { - "require": [ - "babel-register" - ], + "require": ["babel-register"], "babel": { "babelrc": true } diff --git a/src/javascript/lib/core/special_forms.js b/src/javascript/lib/core/special_forms.js index fbb830cd..fe00aa6d 100644 --- a/src/javascript/lib/core/special_forms.js +++ b/src/javascript/lib/core/special_forms.js @@ -151,5 +151,5 @@ export default { _for, _try, _with, - receive, + receive }; diff --git a/src/javascript/tests/with.spec.js b/src/javascript/tests/with.spec.js index d57322d8..924c844b 100644 --- a/src/javascript/tests/with.spec.js +++ b/src/javascript/tests/with.spec.js @@ -1,5 +1,6 @@ import Core from '../lib/core'; import test from 'ava'; + const Patterns = Core.Patterns; const SpecialForms = Core.SpecialForms; const Tuple = Core.Tuple; @@ -78,7 +79,7 @@ test('with bare expression', t => { [$, width => width * 2], [ new Tuple(Symbol.for('ok'), $), - (width, double_width) => map_fetch(opts, 'height'), + (width, double_width) => map_fetch(opts, 'height') ], (width, double_width, height) => new Tuple(Symbol.for('ok'), double_width * height) diff --git a/test/support/main.ex b/test/support/main.ex index a18d3d90..94946a83 100644 --- a/test/support/main.ex +++ b/test/support/main.ex @@ -1,5 +1,15 @@ defmodule Main do def start(:normal, [callback]) do callback.("started") + + opts = %{width: 10, height: 15} + with {:ok, width} <- Map.fetch(opts, :width), + {:ok, height} <- Map.fetch(opts, :height) + do + {:ok, width * height} + else + :error -> + {:error, :wrong_data} + end end end From d2be43293d27a0172f92c5d72567811fdb2a1b44 Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Sat, 15 Jul 2017 23:11:45 -0500 Subject: [PATCH 612/860] Update travis ci config --- .travis.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.travis.yml b/.travis.yml index ce075d5f..e4ec9f8e 100644 --- a/.travis.yml +++ b/.travis.yml @@ -9,8 +9,8 @@ install: - npm install -g yarn - yarn before_script: - - wget https://repo.hex.pm/builds/elixir/v1.5.0-rc.0-otp-20.zip - - unzip -d elixir v1.5.0-rc.0-otp-20.zip + - wget https://repo.hex.pm/builds/elixir/v1.5.0-rc.1-otp-20.zip + - unzip -d elixir v1.5.0-rc.1-otp-20.zip - export PATH=$(pwd)/elixir/bin:${PATH} - mix local.rebar --force - mix local.hex --force @@ -26,4 +26,4 @@ notifications: - https://webhooks.gitter.im/e/fbd8944d285c0696dc41 on_success: always # options: [always|never|change] default: always on_failure: always # options: [always|never|change] default: always - on_start: never # options: [always|never|change] default: always \ No newline at end of file + on_start: never # options: [always|never|change] default: always From 02259bd967adf2fcc34546018c495ee616c76853 Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Sat, 15 Jul 2017 23:26:41 -0500 Subject: [PATCH 613/860] Rename JS module to ElixirScript.JS --- CHANGELOG.md | 1 + JavascriptInterop.md | 14 ++++----- lib/elixir_script/lib/js.ex | 4 +-- .../passes/find_used_functions.ex | 2 +- lib/elixir_script/passes/find_used_modules.ex | 2 +- lib/elixir_script/passes/translate/form.ex | 2 +- .../passes/translate/forms/bitstring.ex | 2 +- .../passes/translate/forms/js.ex | 31 +++---------------- test/passes/translate/forms/js_test.exs | 12 +++---- 9 files changed, 25 insertions(+), 45 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index e3f5598c..10cd0b98 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,6 +11,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/). ### Changed - Compiler has been completely rewritten. ElixirScript now requires Erlang 20+ and Elixir 1.5+ +- `JS` module renamed to `ElixirScript.JS` ## [0.28.0] - 2017-06-11 diff --git a/JavascriptInterop.md b/JavascriptInterop.md index de8bf745..438a2781 100644 --- a/JavascriptInterop.md +++ b/JavascriptInterop.md @@ -2,17 +2,17 @@ ## ElixirScript Calling JavaScript -### JS module +### ElixirScript.JS module -The `JS` module has functions and macros that help with interacting with JavaScript. +The `ElixirScript.JS` module has functions and macros that help with interacting with JavaScript. These mostly correspond to JavaScript keywords that may be useful. ```elixir # Calling the JavaScript Debugger -JS.debugger() +ElixirScript.JS.debugger() # Getting the type of a value -JS.typeof(my_value) +ElixirScript.JS.typeof(my_value) ``` ### Foreign Function Interface @@ -53,7 +53,7 @@ export default { defmodule Main do def start(:normal, args) do - JS.console.log(args) + args end end @@ -75,7 +75,7 @@ export default { defmodule MyModule do def hi() do - JS.alert("hello") + "hello" end end ``` @@ -84,4 +84,4 @@ export default { ```javascript const MyModule = Elixir.load(Elixir.MyModule); MyModule.hi() - ``` \ No newline at end of file + ``` diff --git a/lib/elixir_script/lib/js.ex b/lib/elixir_script/lib/js.ex index 990a2110..dc584638 100644 --- a/lib/elixir_script/lib/js.ex +++ b/lib/elixir_script/lib/js.ex @@ -1,4 +1,4 @@ -defmodule JS do +defmodule ElixirScript.JS do @moduledoc """ This module defines macros and functions which implement JavaScript functionality that may not translate easily to @@ -9,7 +9,7 @@ defmodule JS do Creates new JavaScript objects. ex: - JS.new User, ["first_name", "last_name"] + ElixirScript.JS.new User, ["first_name", "last_name"] """ defmacro new(module, params) diff --git a/lib/elixir_script/passes/find_used_functions.ex b/lib/elixir_script/passes/find_used_functions.ex index 853749ce..b7ffdcf6 100644 --- a/lib/elixir_script/passes/find_used_functions.ex +++ b/lib/elixir_script/passes/find_used_functions.ex @@ -247,7 +247,7 @@ defmodule ElixirScript.FindUsedFunctions do walk({function, [], params}, state) end - defp walk({{:., _, [JS, _]}, _, params}, state) do + defp walk({{:., _, [ElixirScript.JS, _]}, _, params}, state) do walk(params, state) end diff --git a/lib/elixir_script/passes/find_used_modules.ex b/lib/elixir_script/passes/find_used_modules.ex index 8b2f066d..b7ebddc7 100644 --- a/lib/elixir_script/passes/find_used_modules.ex +++ b/lib/elixir_script/passes/find_used_modules.ex @@ -270,7 +270,7 @@ defmodule ElixirScript.FindUsedModules do walk(params, state) end - defp walk({:., _, [JS, _]}, _) do + defp walk({:., _, [ElixirScript.JS, _]}, _) do nil end diff --git a/lib/elixir_script/passes/translate/form.ex b/lib/elixir_script/passes/translate/form.ex index 31776b3d..5c843e5d 100644 --- a/lib/elixir_script/passes/translate/form.ex +++ b/lib/elixir_script/passes/translate/form.ex @@ -220,7 +220,7 @@ defmodule ElixirScript.Translate.Form do {ast, state} end - def compile({{:., _, [JS, _]}, _, _} = ast, state) do + def compile({{:., _, [ElixirScript.JS, _]}, _, _} = ast, state) do ElixirScript.Translate.Forms.JS.compile(ast, state) end diff --git a/lib/elixir_script/passes/translate/forms/bitstring.ex b/lib/elixir_script/passes/translate/forms/bitstring.ex index 1490f74f..3a2a1d5c 100644 --- a/lib/elixir_script/passes/translate/forms/bitstring.ex +++ b/lib/elixir_script/passes/translate/forms/bitstring.ex @@ -132,7 +132,7 @@ defmodule ElixirScript.Translate.Forms.Bitstring do result = case translated_elements do [] -> JS.literal('') - [element] -> + [_] -> do_make_interpolated_string([], hd(translated_elements)) elements -> do_make_interpolated_string(tl(elements), hd(elements)) diff --git a/lib/elixir_script/passes/translate/forms/js.ex b/lib/elixir_script/passes/translate/forms/js.ex index 80c8cca9..d3e74e89 100644 --- a/lib/elixir_script/passes/translate/forms/js.ex +++ b/lib/elixir_script/passes/translate/forms/js.ex @@ -26,17 +26,17 @@ defmodule ElixirScript.Translate.Forms.JS do ) end - def compile({{:., _, [JS, :debugger]}, _, _}, state) do + def compile({{:., _, [ElixirScript.JS, :debugger]}, _, _}, state) do ast = J.debugger_statement() {ast, state} end - def compile({{:., _, [JS, :this]}, _, _}, state) do + def compile({{:., _, [ElixirScript.JS, :this]}, _, _}, state) do ast = J.this_expression() {ast, state} end - def compile({{:., _, [JS, :new]}, _, [module, params]}, state) do + def compile({{:., _, [ElixirScript.JS, :new]}, _, [module, params]}, state) do members = Module.split(module) members = case members do @@ -61,7 +61,7 @@ defmodule ElixirScript.Translate.Forms.JS do {ast, state} end - def compile({{:., _, [JS, :throw]}, _, [term]}, state) do + def compile({{:., _, [ElixirScript.JS, :throw]}, _, [term]}, state) do ast = J.throw_statement( Form.compile!(term, state) ) @@ -69,7 +69,7 @@ defmodule ElixirScript.Translate.Forms.JS do {ast, state} end - def compile({{:., _, [JS, :import]}, _, [term]}, state) do + def compile({{:., _, [ElixirScript.JS, :import]}, _, [term]}, state) do ast = J.call_expression( J.identifier("import"), [Form.compile!(term, state)] @@ -77,25 +77,4 @@ defmodule ElixirScript.Translate.Forms.JS do {ast, state} end - - def compile({{:., _, [JS, function]}, _, []}, state) do - ast = J.call_expression( - call_property(), - [ - global(), - Form.compile!(to_string(function), state) - ] - ) - - {ast, state} - end - - def compile({{:., _, [JS, function]}, _, params}, state) do - ast = J.call_expression( - J.identifier(function), - Enum.map(params, &Form.compile!(&1, state)) - ) - - {ast, state} - end end diff --git a/test/passes/translate/forms/js_test.exs b/test/passes/translate/forms/js_test.exs index 31bf2af3..635c1994 100644 --- a/test/passes/translate/forms/js_test.exs +++ b/test/passes/translate/forms/js_test.exs @@ -15,7 +15,7 @@ defmodule ElixirScript.Translate.Forms.JS.Test do end test "debugger" do - ast = {{:., [], [JS, :debugger]}, [], []} + ast = {{:., [], [ElixirScript.JS, :debugger]}, [], []} state = %{function: {:each, nil}, module: Enum, vars: %{:_ => 0, "entry" => 0, "enumerable" => 0, "fun" => 0}} {js_ast, _} = Form.compile(ast, state) @@ -23,7 +23,7 @@ defmodule ElixirScript.Translate.Forms.JS.Test do end test "this" do - ast = {{:., [], [JS, :this]}, [], []} + ast = {{:., [], [ElixirScript.JS, :this]}, [], []} state = %{function: {:each, nil}, module: Enum, vars: %{:_ => 0, "entry" => 0, "enumerable" => 0, "fun" => 0}} {js_ast, _} = Form.compile(ast, state) @@ -31,7 +31,7 @@ defmodule ElixirScript.Translate.Forms.JS.Test do end test "new" do - ast = {{:., [], [JS, :new]}, [], [BLT, ["bacon", "lettuce", "tomato"]]} + ast = {{:., [], [ElixirScript.JS, :new]}, [], [BLT, ["bacon", "lettuce", "tomato"]]} state = %{function: {:each, nil}, module: Enum, vars: %{:_ => 0, "entry" => 0, "enumerable" => 0, "fun" => 0}} {js_ast, _} = Form.compile(ast, state) @@ -47,7 +47,7 @@ defmodule ElixirScript.Translate.Forms.JS.Test do test "throw" do - ast = {{:., [], [JS, :throw]}, [], [1]} + ast = {{:., [], [ElixirScript.JS, :throw]}, [], [1]} state = %{function: {:each, nil}, module: Enum, vars: %{:_ => 0, "entry" => 0, "enumerable" => 0, "fun" => 0}} {js_ast, _} = Form.compile(ast, state) @@ -55,7 +55,7 @@ defmodule ElixirScript.Translate.Forms.JS.Test do end test "import" do - ast = {{:., [], [JS, :import]}, [], ["react"]} + ast = {{:., [], [ElixirScript.JS, :import]}, [], ["react"]} state = %{function: {:each, nil}, module: Enum, vars: %{:_ => 0, "entry" => 0, "enumerable" => 0, "fun" => 0}} {js_ast, _} = Form.compile(ast, state) @@ -64,4 +64,4 @@ defmodule ElixirScript.Translate.Forms.JS.Test do [J.literal("react")] ) end -end \ No newline at end of file +end From 2425a563cb5739076aeb39763172edf062366fda Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Sat, 15 Jul 2017 23:44:57 -0500 Subject: [PATCH 614/860] Add ElixirScript.JS.mutate --- CHANGELOG.md | 2 + lib/elixir_script/lib/js.ex | 14 +++++ .../passes/translate/forms/js.ex | 41 +++++++++++---- test/passes/translate/forms/js_test.exs | 51 +++++++++++++++++++ 4 files changed, 98 insertions(+), 10 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 10cd0b98..c164ace1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,8 @@ and this project adheres to [Semantic Versioning](http://semver.org/). ### Added - ElixirScript now has an FFI layer for interoperability with JavaScript. For more details, see documentation at `ElixirScript.FFI` +- ElixirScript.JS.mutate/2 +- ElixirScript.JS.mutate/3 ### Changed - Compiler has been completely rewritten. ElixirScript now requires Erlang 20+ and Elixir 1.5+ diff --git a/lib/elixir_script/lib/js.ex b/lib/elixir_script/lib/js.ex index dc584638..2c14151c 100644 --- a/lib/elixir_script/lib/js.ex +++ b/lib/elixir_script/lib/js.ex @@ -37,4 +37,18 @@ defmodule ElixirScript.JS do The current JavaScript context """ defmacro this() + + @doc """ + Mutates an existing JavaScript object. + ex: + ElixirScript.JS.mutate elem, %{"width" => 100} + """ + defmacro update(object, map) + + @doc """ + Mutates an existing JavaScript object. + ex: + ElixirScript.JS.mutate elem, "width", 100 + """ + defmacro update(object, key, value) end diff --git a/lib/elixir_script/passes/translate/forms/js.ex b/lib/elixir_script/passes/translate/forms/js.ex index d3e74e89..c33f121e 100644 --- a/lib/elixir_script/passes/translate/forms/js.ex +++ b/lib/elixir_script/passes/translate/forms/js.ex @@ -16,16 +16,6 @@ defmodule ElixirScript.Translate.Forms.JS do ) end - def global() do - J.member_expression( - J.member_expression( - J.identifier("Bootstrap"), - J.identifier("Core") - ), - J.identifier("global") - ) - end - def compile({{:., _, [ElixirScript.JS, :debugger]}, _, _}, state) do ast = J.debugger_statement() {ast, state} @@ -77,4 +67,35 @@ defmodule ElixirScript.Translate.Forms.JS do {ast, state} end + + def compile({{:., _, [ElixirScript.JS, :mutate]}, _, [object, map]}, state) do + ast = J.call_expression( + J.member_expression( + J.identifier("Object"), + J.identifier("assign") + ), + [ + Form.compile!(object, state), + Form.compile!(map, state) + ] + ) + + {ast, state} + end + + def compile({{:., _, [ElixirScript.JS, :mutate]}, _, [object, key, value]}, state) do + ast = J.assignment_expression( + :=, + J.member_expression( + Form.compile!(object, state), + Form.compile!(key, state), + true + ), + [ + Form.compile!(value, state) + ] + ) + + {ast, state} + end end diff --git a/test/passes/translate/forms/js_test.exs b/test/passes/translate/forms/js_test.exs index 635c1994..7afd866c 100644 --- a/test/passes/translate/forms/js_test.exs +++ b/test/passes/translate/forms/js_test.exs @@ -64,4 +64,55 @@ defmodule ElixirScript.Translate.Forms.JS.Test do [J.literal("react")] ) end + + test "mutate/2" do + properties = [{"a", 1}] + map_ast = {:%{}, [], properties} + + ast = {{:., [], [ElixirScript.JS, :mutate]}, [], [{:%{}, [], []}, map_ast]} + state = %{function: {:each, nil}, module: Enum, vars: %{:_ => 0, "entry" => 0, "enumerable" => 0, "fun" => 0}} + + {js_ast, _} = Form.compile(ast, state) + assert js_ast == J.call_expression( + J.member_expression( + J.identifier("Object"), + J.identifier("assign") + ), + [ + J.object_expression([]), + J.object_expression([ + J.property( + J.identifier("a"), + J.literal(1) + ) + ]) + ] + ) + end + + test "mutate/3" do + properties = [{"a", 1}] + map_ast = {:%{}, [], properties} + + ast = {{:., [], [ElixirScript.JS, :mutate]}, [], [map_ast, "a", 2]} + state = %{function: {:each, nil}, module: Enum, vars: %{:_ => 0, "entry" => 0, "enumerable" => 0, "fun" => 0}} + + {js_ast, _} = Form.compile(ast, state) + assert js_ast == J.assignment_expression( + :=, + J.member_expression( + J.object_expression([ + J.property( + J.identifier("a"), + J.literal(1) + ) + ]), + J.literal("a"), + true + ), + [ + J.literal(2) + ] + ) + end end From cf321a5743f54c779cbf698a017bd2a3ea1bf6a4 Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Sun, 16 Jul 2017 08:46:57 -0500 Subject: [PATCH 615/860] Update tailored. Add names to variables. --- lib/elixir_script/passes/translate/forms/pattern.ex | 2 +- .../passes/translate/forms/pattern/patterns.ex | 9 ++++++++- package.json | 6 ++++-- test/support/main.ex | 10 ---------- yarn.lock | 6 +++--- 5 files changed, 16 insertions(+), 17 deletions(-) diff --git a/lib/elixir_script/passes/translate/forms/pattern.ex b/lib/elixir_script/passes/translate/forms/pattern.ex index a721295b..3c87995c 100644 --- a/lib/elixir_script/passes/translate/forms/pattern.ex +++ b/lib/elixir_script/passes/translate/forms/pattern.ex @@ -203,7 +203,7 @@ defmodule ElixirScript.Translate.Forms.Pattern do end defp process_pattern({var, _, _}, _) do - { [PM.parameter()], [ElixirScript.Translate.Identifier.make_identifier(var)] } + { [PM.parameter(J.literal(to_string(var)))], [ElixirScript.Translate.Identifier.make_identifier(var)] } end defp reduce_patterns(patterns, _) do diff --git a/lib/elixir_script/passes/translate/forms/pattern/patterns.ex b/lib/elixir_script/passes/translate/forms/pattern/patterns.ex index 21f313f5..8b9f4e54 100644 --- a/lib/elixir_script/passes/translate/forms/pattern/patterns.ex +++ b/lib/elixir_script/passes/translate/forms/pattern/patterns.ex @@ -53,6 +53,13 @@ defmodule ElixirScript.Translate.Forms.Pattern.Patterns do ) end + def parameter(name) do + J.call_expression( + @parameter, + [name] + ) + end + def head_tail(headParameter, tailParameter) do J.call_expression( @head_tail, @@ -94,4 +101,4 @@ defmodule ElixirScript.Translate.Forms.Pattern.Patterns do values ) end -end \ No newline at end of file +end diff --git a/package.json b/package.json index 882c88a0..d7d2c1a3 100644 --- a/package.json +++ b/package.json @@ -23,7 +23,7 @@ "license": "MIT", "dependencies": { "erlang-types": "^1.0.1", - "tailored": "^2.4.9" + "tailored": "^2.5.0" }, "devDependencies": { "ava": "^0.19.1", @@ -41,7 +41,9 @@ "sinon": "^1.17.7" }, "ava": { - "require": ["babel-register"], + "require": [ + "babel-register" + ], "babel": { "babelrc": true } diff --git a/test/support/main.ex b/test/support/main.ex index 94946a83..a18d3d90 100644 --- a/test/support/main.ex +++ b/test/support/main.ex @@ -1,15 +1,5 @@ defmodule Main do def start(:normal, [callback]) do callback.("started") - - opts = %{width: 10, height: 15} - with {:ok, width} <- Map.fetch(opts, :width), - {:ok, height} <- Map.fetch(opts, :height) - do - {:ok, width * height} - else - :error -> - {:error, :wrong_data} - end end end diff --git a/yarn.lock b/yarn.lock index 241ad9e7..1d33ab2c 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3771,9 +3771,9 @@ table@^3.7.8: slice-ansi "0.0.4" string-width "^2.0.0" -tailored@^2.4.9: - version "2.4.9" - resolved "https://registry.yarnpkg.com/tailored/-/tailored-2.4.9.tgz#b06ea7e8eab054860062b076e7e1d0e33e0fa983" +tailored@^2.5.0: + version "2.5.0" + resolved "https://registry.yarnpkg.com/tailored/-/tailored-2.5.0.tgz#55055ea25e018951ecfc9adf39177f178fcde63e" dependencies: erlang-types "^1.0.0" From ca8c7ed212d55bf0099fafd6ac5c1f342ee19b96 Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Sun, 16 Jul 2017 10:56:05 -0500 Subject: [PATCH 616/860] Rename Bootstrap to ElixirScript --- README.md | 4 ++-- lib/elixir_script/lib/agent.ex | 18 ++++++++--------- lib/elixir_script/lib/store.ex | 4 ++-- lib/elixir_script/module_systems/namespace.ex | 4 ++-- lib/elixir_script/passes/output.ex | 4 ++-- lib/elixir_script/passes/translate/clause.ex | 2 +- lib/elixir_script/passes/translate/form.ex | 4 ++-- .../passes/translate/forms/bitstring.ex | 4 ++-- .../passes/translate/forms/for.ex | 8 ++++---- .../passes/translate/forms/js.ex | 2 +- .../passes/translate/forms/match.ex | 6 +++--- .../passes/translate/forms/pattern.ex | 2 +- .../translate/forms/pattern/patterns.ex | 2 +- .../passes/translate/forms/receive.ex | 2 +- .../passes/translate/forms/remote.ex | 6 +++--- .../passes/translate/forms/try.ex | 2 +- .../passes/translate/forms/with.ex | 2 +- .../passes/translate/function.ex | 4 ++-- .../passes/translate/protocol.ex | 20 +++++++++---------- rollup.config.js | 4 ++-- test/passes/translate/form_test.exs | 4 ++-- test/passes/translate/forms/receive_test.exs | 4 ++-- 22 files changed, 56 insertions(+), 56 deletions(-) diff --git a/README.md b/README.md index 5f78b35d..40bb0e11 100644 --- a/README.md +++ b/README.md @@ -24,8 +24,8 @@ git clone git@github.com:bryanjos/elixirscript.git #Get dependencies mix deps.get yarn - -# Create Elixir.Bootstrap.js + +# Create ElixirScript.Core.js yarn build # Compile diff --git a/lib/elixir_script/lib/agent.ex b/lib/elixir_script/lib/agent.ex index cb444941..4048350f 100644 --- a/lib/elixir_script/lib/agent.ex +++ b/lib/elixir_script/lib/agent.ex @@ -8,7 +8,7 @@ defmodule ElixirScript.Agent do nil end - pid = Bootstrap.Core.Store.create(fun.(), name) + pid = ElixirScript.Core.Store.create(fun.(), name) { :ok, pid } end @@ -19,31 +19,31 @@ defmodule ElixirScript.Agent do nil end - pid = Bootstrap.Core.Store.create(fun.(), name) + pid = ElixirScript.Core.Store.create(fun.(), name) { :ok, pid } end def stop(agent) do - Bootstrap.Core.Store.remove(agent) + ElixirScript.Core.Store.remove(agent) :ok end def update(agent, fun) do - current_state = Bootstrap.Core.Store.read(agent) - Bootstrap.Core.Store.update(agent, fun.(current_state)) + current_state = ElixirScript.Core.Store.read(agent) + ElixirScript.Core.Store.update(agent, fun.(current_state)) :ok end def get(agent, fun) do - current_state = Bootstrap.Core.Store.read(agent) + current_state = ElixirScript.Core.Store.read(agent) fun.(current_state) end def get_and_update(agent, fun) do - current_state = Bootstrap.Core.Store.read(agent) + current_state = ElixirScript.Core.Store.read(agent) {val, new_state} = fun.(current_state) - Bootstrap.Core.Store.update(agent, new_state) + ElixirScript.Core.Store.update(agent, new_state) val end -end \ No newline at end of file +end diff --git a/lib/elixir_script/lib/store.ex b/lib/elixir_script/lib/store.ex index 14447d9d..5c2efa23 100644 --- a/lib/elixir_script/lib/store.ex +++ b/lib/elixir_script/lib/store.ex @@ -1,4 +1,4 @@ -defmodule Bootstrap.Core.Store do +defmodule ElixirScript.Core.Store do @moduledoc false use ElixirScript.FFI, global: true @@ -9,4 +9,4 @@ defmodule Bootstrap.Core.Store do foreign read(key) foreign remove(key) -end \ No newline at end of file +end diff --git a/lib/elixir_script/module_systems/namespace.ex b/lib/elixir_script/module_systems/namespace.ex index 08e7aa4b..8af407ac 100644 --- a/lib/elixir_script/module_systems/namespace.ex +++ b/lib/elixir_script/module_systems/namespace.ex @@ -14,7 +14,7 @@ defmodule ElixirScript.ModuleSystems.Namespace do defp build_namespace() do JS.member_expression( - JS.identifier("Bootstrap"), + JS.identifier("ElixirScript"), JS.member_expression( JS.identifier(:Core), JS.member_expression( @@ -71,4 +71,4 @@ defmodule ElixirScript.ModuleSystems.Namespace do func ) end -end \ No newline at end of file +end diff --git a/lib/elixir_script/passes/output.ex b/lib/elixir_script/passes/output.ex index 7b6575b1..2042e718 100644 --- a/lib/elixir_script/passes/output.ex +++ b/lib/elixir_script/passes/output.ex @@ -50,7 +50,7 @@ defmodule ElixirScript.Output do defp get_bootstrap_js() do operating_path = Path.join([Mix.Project.build_path, "lib", "elixir_script", "priv"]) - path = Path.join([operating_path, "build", "iife", "Elixir.Bootstrap.js"]) + path = Path.join([operating_path, "build", "iife", "ElixirScript.Core.js"]) File.read!(path) end @@ -120,4 +120,4 @@ defmodule ElixirScript.Output do end end) end -end \ No newline at end of file +end diff --git a/lib/elixir_script/passes/translate/clause.ex b/lib/elixir_script/passes/translate/clause.ex index 79512ab0..3cebc738 100644 --- a/lib/elixir_script/passes/translate/clause.ex +++ b/lib/elixir_script/passes/translate/clause.ex @@ -9,7 +9,7 @@ defmodule ElixirScript.Translate.Clause do @patterns J.member_expression( J.member_expression( - J.identifier("Bootstrap"), + J.identifier("ElixirScript"), J.identifier("Core") ), J.identifier("Patterns") diff --git a/lib/elixir_script/passes/translate/form.ex b/lib/elixir_script/passes/translate/form.ex index 5c843e5d..c6e1ab2e 100644 --- a/lib/elixir_script/passes/translate/form.ex +++ b/lib/elixir_script/passes/translate/form.ex @@ -66,7 +66,7 @@ defmodule ElixirScript.Translate.Form do ast = J.new_expression( J.member_expression( J.member_expression( - J.identifier("Bootstrap"), + J.identifier("ElixirScript"), J.identifier("Core") ), J.identifier("Tuple") @@ -173,7 +173,7 @@ defmodule ElixirScript.Translate.Form do cond_function = J.member_expression( J.member_expression( - J.identifier("Bootstrap"), + J.identifier("ElixirScript"), J.member_expression( J.identifier("Core"), J.identifier("SpecialForms") diff --git a/lib/elixir_script/passes/translate/forms/bitstring.ex b/lib/elixir_script/passes/translate/forms/bitstring.ex index 3a2a1d5c..0db3e2ef 100644 --- a/lib/elixir_script/passes/translate/forms/bitstring.ex +++ b/lib/elixir_script/passes/translate/forms/bitstring.ex @@ -8,7 +8,7 @@ defmodule ElixirScript.Translate.Forms.Bitstring do js_ast = JS.new_expression( JS.member_expression( JS.member_expression( - JS.identifier("Bootstrap"), + JS.identifier("ElixirScript"), JS.identifier("Core") ), JS.identifier("BitString") @@ -88,7 +88,7 @@ defmodule ElixirScript.Translate.Forms.Bitstring do defp bitstring_class() do JS.member_expression( JS.member_expression( - JS.identifier("Bootstrap"), + JS.identifier("ElixirScript"), JS.identifier("Core") ), JS.identifier("BitString") diff --git a/lib/elixir_script/passes/translate/forms/for.ex b/lib/elixir_script/passes/translate/forms/for.ex index a04733cd..c7f84ce3 100644 --- a/lib/elixir_script/passes/translate/forms/for.ex +++ b/lib/elixir_script/passes/translate/forms/for.ex @@ -19,7 +19,7 @@ defmodule ElixirScript.Translate.Forms.For do JS.member_expression( JS.member_expression( JS.member_expression( - JS.identifier("Bootstrap"), + JS.identifier("ElixirScript"), JS.identifier("Core") ), JS.identifier("Patterns") @@ -37,7 +37,7 @@ defmodule ElixirScript.Translate.Forms.For do ast = JS.call_expression( JS.member_expression( JS.member_expression( - JS.identifier("Bootstrap"), + JS.identifier("ElixirScript"), JS.member_expression( JS.identifier("Core"), JS.identifier("SpecialForms") @@ -72,7 +72,7 @@ defmodule ElixirScript.Translate.Forms.For do JS.member_expression( JS.member_expression( JS.member_expression( - JS.identifier("Bootstrap"), + JS.identifier("ElixirScript"), JS.identifier("Core") ), JS.identifier("Patterns") @@ -91,7 +91,7 @@ defmodule ElixirScript.Translate.Forms.For do JS.member_expression( JS.member_expression( JS.member_expression( - JS.identifier("Bootstrap"), + JS.identifier("ElixirScript"), JS.identifier("Core") ), JS.identifier("Patterns") diff --git a/lib/elixir_script/passes/translate/forms/js.ex b/lib/elixir_script/passes/translate/forms/js.ex index c33f121e..b4c7c614 100644 --- a/lib/elixir_script/passes/translate/forms/js.ex +++ b/lib/elixir_script/passes/translate/forms/js.ex @@ -6,7 +6,7 @@ defmodule ElixirScript.Translate.Forms.JS do def call_property() do J.member_expression( J.member_expression( - J.identifier("Bootstrap"), + J.identifier("ElixirScript"), J.member_expression( J.identifier("Core"), J.identifier("Functions") diff --git a/lib/elixir_script/passes/translate/forms/match.ex b/lib/elixir_script/passes/translate/forms/match.ex index 1f31bf75..aeaac2ee 100644 --- a/lib/elixir_script/passes/translate/forms/match.ex +++ b/lib/elixir_script/passes/translate/forms/match.ex @@ -23,7 +23,7 @@ defmodule ElixirScript.Translate.Forms.Match do J.member_expression( J.member_expression( J.member_expression( - J.identifier("Bootstrap"), + J.identifier("ElixirScript"), J.identifier("Core") ), J.identifier("Patterns") @@ -72,7 +72,7 @@ defmodule ElixirScript.Translate.Forms.Match do ref, J.new_expression( J.member_expression( - J.identifier("Bootstrap"), + J.identifier("ElixirScript"), J.member_expression( J.identifier("Core"), J.identifier("Tuple") @@ -102,4 +102,4 @@ defmodule ElixirScript.Translate.Forms.Match do [array_pattern, ref_declaration] end -end \ No newline at end of file +end diff --git a/lib/elixir_script/passes/translate/forms/pattern.ex b/lib/elixir_script/passes/translate/forms/pattern.ex index 3c87995c..d52407dc 100644 --- a/lib/elixir_script/passes/translate/forms/pattern.ex +++ b/lib/elixir_script/passes/translate/forms/pattern.ex @@ -83,7 +83,7 @@ defmodule ElixirScript.Translate.Forms.Pattern do tuple = J.member_expression( J.member_expression( - J.identifier("Bootstrap"), + J.identifier("ElixirScript"), J.identifier("Core") ), J.identifier("Tuple") diff --git a/lib/elixir_script/passes/translate/forms/pattern/patterns.ex b/lib/elixir_script/passes/translate/forms/pattern/patterns.ex index 8b9f4e54..0aef2d3f 100644 --- a/lib/elixir_script/passes/translate/forms/pattern/patterns.ex +++ b/lib/elixir_script/passes/translate/forms/pattern/patterns.ex @@ -5,7 +5,7 @@ defmodule ElixirScript.Translate.Forms.Pattern.Patterns do @patterns J.member_expression( J.member_expression( - J.identifier("Bootstrap"), + J.identifier("ElixirScript"), J.identifier("Core") ), J.identifier("Patterns") diff --git a/lib/elixir_script/passes/translate/forms/receive.ex b/lib/elixir_script/passes/translate/forms/receive.ex index a23897e5..c097ffeb 100644 --- a/lib/elixir_script/passes/translate/forms/receive.ex +++ b/lib/elixir_script/passes/translate/forms/receive.ex @@ -12,7 +12,7 @@ defmodule ElixirScript.Translate.Forms.Receive do receive_function = J.member_expression( J.member_expression( - J.identifier("Bootstrap"), + J.identifier("ElixirScript"), J.member_expression( J.identifier("Core"), J.identifier("SpecialForms") diff --git a/lib/elixir_script/passes/translate/forms/remote.ex b/lib/elixir_script/passes/translate/forms/remote.ex index c09a065d..622fc3c0 100644 --- a/lib/elixir_script/passes/translate/forms/remote.ex +++ b/lib/elixir_script/passes/translate/forms/remote.ex @@ -110,7 +110,7 @@ defmodule ElixirScript.Translate.Forms.Remote do ast = J.member_expression( J.member_expression( J.member_expression( - J.identifier("Bootstrap"), + J.identifier("ElixirScript"), J.identifier("Core") ), J.identifier(module) @@ -177,7 +177,7 @@ defmodule ElixirScript.Translate.Forms.Remote do J.member_expression( J.member_expression( J.member_expression( - J.identifier("Bootstrap"), + J.identifier("ElixirScript"), J.identifier("Core") ), J.identifier(module) @@ -185,4 +185,4 @@ defmodule ElixirScript.Translate.Forms.Remote do ElixirScript.Translate.Identifier.make_function_name(function) ) end -end \ No newline at end of file +end diff --git a/lib/elixir_script/passes/translate/forms/try.ex b/lib/elixir_script/passes/translate/forms/try.ex index 0df1df1f..1d6f0754 100644 --- a/lib/elixir_script/passes/translate/forms/try.ex +++ b/lib/elixir_script/passes/translate/forms/try.ex @@ -42,7 +42,7 @@ defmodule ElixirScript.Translate.Forms.Try do js_ast = JS.call_expression( JS.member_expression( JS.member_expression( - JS.identifier("Bootstrap"), + JS.identifier("ElixirScript"), JS.member_expression( JS.identifier("Core"), JS.identifier("SpecialForms") diff --git a/lib/elixir_script/passes/translate/forms/with.ex b/lib/elixir_script/passes/translate/forms/with.ex index ad78ce22..73fe466d 100644 --- a/lib/elixir_script/passes/translate/forms/with.ex +++ b/lib/elixir_script/passes/translate/forms/with.ex @@ -36,7 +36,7 @@ defmodule ElixirScript.Translate.Forms.With do js_ast = JS.call_expression( JS.member_expression( JS.member_expression( - JS.identifier("Bootstrap"), + JS.identifier("ElixirScript"), JS.member_expression( JS.identifier("Core"), JS.identifier("SpecialForms") diff --git a/lib/elixir_script/passes/translate/function.ex b/lib/elixir_script/passes/translate/function.ex index ecd353cf..fe67824c 100644 --- a/lib/elixir_script/passes/translate/function.ex +++ b/lib/elixir_script/passes/translate/function.ex @@ -11,7 +11,7 @@ defmodule ElixirScript.Translate.Function do def patterns_ast() do J.member_expression( J.member_expression( - J.identifier("Bootstrap"), + J.identifier("ElixirScript"), J.identifier("Core") ), J.identifier("Patterns") @@ -168,4 +168,4 @@ defmodule ElixirScript.Translate.Function do {ast, state} end -end \ No newline at end of file +end diff --git a/lib/elixir_script/passes/translate/protocol.ex b/lib/elixir_script/passes/translate/protocol.ex index d487a391..e6c1747b 100644 --- a/lib/elixir_script/passes/translate/protocol.ex +++ b/lib/elixir_script/passes/translate/protocol.ex @@ -19,7 +19,7 @@ defmodule ElixirScript.Translate.Protocol do J.identifier("protocol"), J.call_expression( J.member_expression( - J.identifier("Bootstrap"), + J.identifier("ElixirScript"), J.member_expression( J.identifier(:Core), J.member_expression( @@ -58,7 +58,7 @@ defmodule ElixirScript.Translate.Protocol do J.call_expression( J.member_expression( - J.identifier("Bootstrap"), + J.identifier("ElixirScript"), J.member_expression( J.identifier(:Core), J.member_expression( @@ -79,7 +79,7 @@ defmodule ElixirScript.Translate.Protocol do defp map_to_js(Integer) do J.member_expression( J.member_expression( - J.identifier("Bootstrap"), + J.identifier("ElixirScript"), J.identifier(:Core) ), J.identifier(:Integer) @@ -89,7 +89,7 @@ defmodule ElixirScript.Translate.Protocol do defp map_to_js(Tuple) do J.member_expression( J.member_expression( - J.identifier("Bootstrap"), + J.identifier("ElixirScript"), J.identifier(:Core) ), J.identifier(:Tuple) @@ -107,7 +107,7 @@ defmodule ElixirScript.Translate.Protocol do defp map_to_js(BitString) do J.member_expression( J.member_expression( - J.identifier("Bootstrap"), + J.identifier("ElixirScript"), J.identifier(:Core) ), J.identifier(:BitString) @@ -117,7 +117,7 @@ defmodule ElixirScript.Translate.Protocol do defp map_to_js(Float) do J.member_expression( J.member_expression( - J.identifier("Bootstrap"), + J.identifier("ElixirScript"), J.identifier(:Core) ), J.identifier(:Float) @@ -131,7 +131,7 @@ defmodule ElixirScript.Translate.Protocol do defp map_to_js(PID) do J.member_expression( J.member_expression( - J.identifier("Bootstrap"), + J.identifier("ElixirScript"), J.identifier(:Core) ), J.identifier(:PID) @@ -140,14 +140,14 @@ defmodule ElixirScript.Translate.Protocol do defp map_to_js(Port) do J.member_expression( - J.identifier("Bootstrap"), + J.identifier("ElixirScript"), J.identifier(:Port) ) end defp map_to_js(Reference) do J.member_expression( - J.identifier("Bootstrap"), + J.identifier("ElixirScript"), J.identifier(:Reference) ) end @@ -174,4 +174,4 @@ defmodule ElixirScript.Translate.Protocol do ) end end -end \ No newline at end of file +end diff --git a/rollup.config.js b/rollup.config.js index a69d9169..b175860a 100644 --- a/rollup.config.js +++ b/rollup.config.js @@ -4,7 +4,7 @@ import babili from 'rollup-plugin-babili'; export default { entry: 'src/javascript/elixir.js', - moduleName: 'Bootstrap', + moduleName: 'ElixirScript', plugins: [ nodeResolve({ jsnext: true }), babel({ @@ -15,5 +15,5 @@ export default { keepClassName: true }) ], - targets: [{ dest: 'priv/build/iife/Elixir.Bootstrap.js', format: 'iife' }] + targets: [{ dest: 'priv/build/iife/ElixirScript.Core.js', format: 'iife' }] }; diff --git a/test/passes/translate/form_test.exs b/test/passes/translate/form_test.exs index f7106473..0e5a353f 100644 --- a/test/passes/translate/form_test.exs +++ b/test/passes/translate/form_test.exs @@ -79,7 +79,7 @@ defmodule ElixirScript.Translate.Forms.Test do assert js_ast == J.new_expression( J.member_expression( J.member_expression( - J.identifier("Bootstrap"), + J.identifier("ElixirScript"), J.identifier("Core") ), J.identifier("Tuple") @@ -131,4 +131,4 @@ defmodule ElixirScript.Translate.Forms.Test do J.literal(3) ]) end -end \ No newline at end of file +end diff --git a/test/passes/translate/forms/receive_test.exs b/test/passes/translate/forms/receive_test.exs index 32d55f67..5d3d1509 100644 --- a/test/passes/translate/forms/receive_test.exs +++ b/test/passes/translate/forms/receive_test.exs @@ -11,7 +11,7 @@ defmodule ElixirScript.Translate.Forms.Receive.Test do assert js_ast == J.call_expression( J.member_expression( J.member_expression( - J.identifier("Bootstrap"), + J.identifier("ElixirScript"), J.member_expression( J.identifier("Core"), J.identifier("SpecialForms") @@ -23,4 +23,4 @@ defmodule ElixirScript.Translate.Forms.Receive.Test do ) end -end \ No newline at end of file +end From 6ba4ec77db3ee6c3c5236537224cd09820850ef0 Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Sun, 16 Jul 2017 11:07:45 -0500 Subject: [PATCH 617/860] Remove warnings for FFI modules by adding underscore to args --- lib/elixir_script/ffi.ex | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/lib/elixir_script/ffi.ex b/lib/elixir_script/ffi.ex index abffc29b..3ee1ea94 100644 --- a/lib/elixir_script/ffi.ex +++ b/lib/elixir_script/ffi.ex @@ -53,8 +53,21 @@ defmodule ElixirScript.FFI do ``` """ defmacro foreign({name, _, args}) do + args = Enum.map(args, fn + {:\\, meta0, [{name, meta, atom}, value]}-> + name = String.to_atom("_" <> Atom.to_string(name)) + {:\\, meta0, [{name, meta, atom}, value]} + + {name, meta, atom} -> + name = String.to_atom("_" <> Atom.to_string(name)) + {name, meta, atom} + + other -> + other + end) + quote do def unquote(name)(unquote_splicing(args)), do: nil end end -end \ No newline at end of file +end From f3170b43b209f1ce7a18e5ad77f1f3e0a12d3d11 Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Sun, 16 Jul 2017 16:17:53 -0500 Subject: [PATCH 618/860] Checking in built js file to use in examples --- .gitignore | 1 - priv/build/iife/ElixirScript.Core.js | 6 ++++++ src/javascript/lib/core/store.js | 8 ++++---- 3 files changed, 10 insertions(+), 5 deletions(-) create mode 100644 priv/build/iife/ElixirScript.Core.js diff --git a/.gitignore b/.gitignore index ee4d5234..ba8707b5 100644 --- a/.gitignore +++ b/.gitignore @@ -16,7 +16,6 @@ index.js .tern-port test/std_lib_compile_test.exs src/elixirscript -priv/**/*.js stdlib_state.bin *.log .nyc_output diff --git a/priv/build/iife/ElixirScript.Core.js b/priv/build/iife/ElixirScript.Core.js new file mode 100644 index 00000000..42ff134f --- /dev/null +++ b/priv/build/iife/ElixirScript.Core.js @@ -0,0 +1,6 @@ +var _NumberisInteger=Number.isInteger,_StringfromCharCode=String.fromCharCode,ElixirScript=function(){'use strict';/* @flow */function namedVariableResult(E,F){return new NamedVariableResult(E,F)}/* @flow */function is_number(E){return'number'==typeof E}function is_string(E){return'string'==typeof E}function is_boolean(E){return'boolean'==typeof E}function is_symbol(E){return'symbol'==typeof E}function is_object(E){return'object'==typeof E}function is_variable(E){return E instanceof Variable}function is_null(E){return null===E}function is_array(E){return Array.isArray(E)}function is_function(E){return'[object Function]'==Object.prototype.toString.call(E)}function resolveNull(){return function(F){return is_null(F)}}function resolveWildcard(){return function(){return!0}}function resolveObject(E){let F={};const G=Object.keys(E).concat(Object.getOwnPropertySymbols(E));for(let H of G)F[H]=buildMatch(E[H]);return function(H,I){if(!is_object(H)||E.length>H.length)return!1;for(let J of G)if(!(J in H)||!F[J](H[J],I))return!1;return!0}}function getSize(E,F){return E*F/8}function arraysEqual(E,F){if(E===F)return!0;if(null==E||null==F)return!1;if(E.length!=F.length)return!1;for(var G=0;Gh.integer(G));return new h(...F)}function resolveNoMatch(){return function(){return!1}}function buildMatch(E){if(null===E)return resolveNull(E);if('undefined'==typeof E)return resolveWildcard(E);const F=E.constructor.prototype,G=k.get(F);return G?G(E):'object'==typeof E?resolveObject(E):resolveNoMatch()}function defmatchgen(...E){const F=getArityMap(E);return function*(...G){let[H,I]=findMatchingFunction(G,F);return yield*H.apply(this,I)}}function findMatchingFunction(E,F){if(F.has(E.length)){const G=F.get(E.length);let H=null,I=null;for(let J of G){let K=[];E=fillInOptionalValues(E,J.arity,J.optionals);const L=J.pattern(E,K),[M,N]=checkNamedVariables(K);if(L&&N&&J.guard.apply(this,M)){H=J.fn,I=M;break}}if(!H)throw console.error('No match for:',E),new MatchError(E);return[H,I]}throw console.error('Arity of',E.length,'not found. No match for:',E),new MatchError(E)}function getArityMap(E){let F=new Map;for(const G of E){const H=getArityRange(G);for(const I of H){let J=[];F.has(I)&&(J=F.get(I)),J.push(G),F.set(I,J)}}return F}function getArityRange(E){const F=E.arity-E.optionals.length,G=E.arity;let H=[F];for(;H[H.length-1]!=G;)H.push(H[H.length-1]+1);return H}function getOptionalValues(E){let F=[];for(let G=0;G!0,H=null){let I=[],J=buildMatch(E);const K=J(F,I),[L,M]=checkNamedVariables(I);return K&&M&&G.apply(this,L)?L:H}function run_generators(E,F){if(0==F.length)return E.map((G)=>{return Array.isArray(G)?G:[G]});const G=F.pop();let H=[];for(let I of G())for(let J of E)H.push([I].concat(J));return run_generators(H,F)}function iterator_to_reducer(E,F,G){const H=E[Symbol.iterator]();let I=H.next(),J=F;for(;!1===I.done;){if(J=G(I.value,J.get(1)),J.get(0)===Symbol.for('halt'))return new C.Tuple(Symbol.for('halted'),J.get(1));if(J.get(0)===Symbol.for('suspend'))return new C.Tuple(Symbol.for('suspended'),J.get(1),(K)=>{return iterator_to_reducer(H,K,G)});I=H.next()}return new C.Tuple(Symbol.for('done'),J.get(1))}function run_list_generators(E,F){if(0==F.length)return E.map((I)=>{return Array.isArray(I)?I:[I]});const G=F.pop(),H=[];for(const I of G())for(const J of E)H.push([I].concat(J));return run_list_generators(H,F)}// http://erlang.org/doc/man/erlang.html +function atom_to_binary(E,F=Symbol.for('utf8')){if(F!==Symbol.for('utf8'))throw new Error(`unsupported encoding ${F}`);return E.__MODULE__?Symbol.keyFor(E.__MODULE__):Symbol.keyFor(E)}function binary_to_atom(E,F=Symbol.for('utf8')){if(F!==Symbol.for('utf8'))throw new Error(`unsupported encoding ${F}`);return Symbol.for(E)}function is_number$1(E){return'number'==typeof E||E instanceof Number}function to_list(E){if(!1===q.is_map(E))return new g.Tuple(u,E);const F=[];for(const G of keys(E))F.push(new g.Tuple(G,E[G]));return F}function keys(E){if(!1===q.is_map(E))return new g.Tuple(u,E);const F=[];for(const G of Object.getOwnPropertySymbols(E))F.push(G);for(const G of Object.getOwnPropertyNames(E))F.push(G);return F}function is_key(E,F){return F.hasOwnProperty(E)}// http://erlang.org/doc/man/lists.html +function reverse(E){return[...E].reverse()}function flatten(E,F=[]){const G=E.reduce((H,I)=>{return Array.isArray(I)?H.concat(flatten(I)):H.concat(I)},[]);return G.concat(F)}function foldl(E,F,G){return G.reduce((H,I)=>{return E(I,H)},F)}function keyfind(E,F,G){for(const H of G)if(H.get(F-1)===E)return H;return!1}function keydelete(E,F,G){const H=[];let I=!1;for(let J=0;JBitString$1.integer(I));return new BitString$1(...H)}[Symbol.iterator](){return this.value[Symbol.iterator]()}toString(){var E,F='';for(E=0;E>'}process(E){let F=[];var G;for(G=0;GH?F.push(H):2048>H?F.push(192|H>>6,128|63&H):55296>H||57344<=H?F.push(224|H>>12,128|63&H>>6,128|63&H):(G++,H=65536+((1023&H)<<10|1023&E.charCodeAt(G)),F.push(240|H>>18,128|63&H>>12,128|63&H>>6,128|63&H));return F}static toUTF16Array(E){for(var H,F=[],G=0;G=H?(F.push(0),F.push(H)):(F.push(255&H>>8),F.push(255&H));return F}static toUTF32Array(E){for(var H,F=[],G=0;G=H?(F.push(0),F.push(0),F.push(0),F.push(H)):(F.push(0),F.push(0),F.push(255&H>>8),F.push(255&H));return F}//http://stackoverflow.com/questions/2003493/javascript-float-from-to-bits +static float32ToBytes(E){var F=[],G=new ArrayBuffer(4);new Float32Array(G)[0]=E;let H=new Uint32Array(G)[0];return F.push(255&H>>24),F.push(255&H>>16),F.push(255&H>>8),F.push(255&H),F}static float64ToBytes(E){var F=[],G=new ArrayBuffer(8);new Float64Array(G)[0]=E;var H=new Uint32Array(G)[0],I=new Uint32Array(G)[1];return F.push(255&I>>24),F.push(255&I>>16),F.push(255&I>>8),F.push(255&I),F.push(255&H>>24),F.push(255&H>>16),F.push(255&H>>8),F.push(255&H),F}}var g={Tuple,PID:class PID{constructor(){++c,this.id=c}toString(){return'PID#<0.'+this.id+'.0>'}},Reference:class Reference{constructor(){++d,this.id=d,this.ref=Symbol()}toString(){return'Ref#<0.0.0.'+this.id+'>'}},BitString:BitString$1};/* @flow */const h=g.BitString,k=new Map;k.set(Variable.prototype,function resolveVariable(E){return function(F,G){return null===E.name||E.name.startsWith('_')?G.push(F):G.push(namedVariableResult(E.name,F)),!0}}),k.set(Wildcard.prototype,resolveWildcard),k.set(HeadTail.prototype,function resolveHeadTail(){return function(E,F){if(!is_array(E)||2>E.length)return!1;const G=E[0],H=E.slice(1);return F.push(G),F.push(H),!0}}),k.set(StartsWith.prototype,function resolveStartsWith(E){const F=E.prefix;return function(G,H){return is_string(G)&&G.startsWith(F)&&(H.push(G.substring(F.length)),!0)}}),k.set(Capture.prototype,function resolveCapture(E){const F=buildMatch(E.value);return function(G,H){return!!F(G,H)&&(H.push(G),!0)}}),k.set(Bound.prototype,function resolveBound(E){return function(F){return typeof F==typeof E.value&&F===E.value}}),k.set(Type.prototype,function resolveType(E){return function(F,G){if(F instanceof E.type){const H=buildMatch(E.objPattern);return H(F,G)}return!1}}),k.set(BitStringMatch.prototype,function resolveBitString(E){let F=[];for(let H of E.values)if(is_variable(H.value)){let I=getSize(H.unit,H.size);fillArray(F,I)}else F=F.concat(new h(H).value);let G=E.values;return function(H,I){let J=null;if(!is_string(H)&&!(H instanceof h))return!1;J=is_string(H)?new h(h.binary(H)):H;let K=0;for(let M,L=0;LbuildMatch(G));return function(G,H){return is_array(G)&&G.length==E.length&&G.every(function(I,J){return F[J](G[J],H)})}}),k.set(String.prototype,function resolveString(E){return function(F){return is_string(F)&&F===E}}),k.set(Boolean.prototype,function resolveBoolean(E){return function(F){return is_boolean(F)&&F===E}}),k.set(Function.prototype,function resolveFunction(E){return function(F){return is_function(F)&&F===E}}),k.set(Object.prototype,resolveObject);class MatchError extends Error{constructor(E){if(super(),'symbol'==typeof E)this.message='No match for: '+E.toString();else if(Array.isArray(E)){let F=E.map((G)=>{return null===G?'null':'undefined'==typeof G?'undefined':G.toString()});this.message='No match for: '+F}else this.message='No match for: '+E;this.stack=new Error().stack,this.name=this.constructor.name}}class Clause{constructor(E,F,G=()=>!0){this.pattern=buildMatch(E),this.arity=E.length,this.optionals=getOptionalValues(E),this.fn=F,this.guard=G}}const l=Symbol();// https://github.com/airportyh/protomorphism +class Protocol{constructor(E){function createFun(F){return function(...G){const H=G[0];let I=null;if(null===H&&this.hasImplementation(Symbol('null'))?I=this.registry.get(Symbol)[F]:_NumberisInteger(H)&&this.hasImplementation(C.Integer)?I=this.registry.get(C.Integer)[F]:'number'==typeof H&&!_NumberisInteger(H)&&this.hasImplementation(C.Float)?I=this.registry.get(C.Float)[F]:'string'==typeof H&&this.hasImplementation(C.BitString)?I=this.registry.get(C.BitString)[F]:H&&H[Symbol.for('__struct__')]&&this.hasImplementation(H)?I=this.registry.get(H[Symbol.for('__struct__')].__MODULE__)[F]:null!==H&&this.hasImplementation(H)?I=this.registry.get(H.constructor)[F]:this.fallback&&(I=this.fallback[F]),null!=I){const J=I.apply(this,G);return J}throw new Error(`No implementation found for ${H}`)}}for(const F in this.registry=new Map,this.fallback=null,E)this[F]=createFun(F).bind(this)}implementation(E,F){null===E?this.fallback=F:this.registry.set(E,F)}hasImplementation(E){return E===C.Integer||E===C.Float||E===C.BitString?this.registry.has(E):E&&E[Symbol.for('__struct__')]?this.registry.has(E[Symbol.for('__struct__')].__MODULE__):this.registry.has(E.constructor)}}var q={atom_to_binary,binary_to_atom,binary_to_existing_atom:function binary_to_existing_atom(E,F=Symbol.for('utf8')){return binary_to_atom(E,F)},list_concatenation:function list_concatenation(E,F){return E.concat(F)},list_subtraction:function list_subtraction(E,F){const G=[...E];for(const H of F){const I=G.indexOf(H);-1F},greaterThanOrEqualTo:function greaterThanOrEqualTo(E,F){return E>=F},lessThan:function lessThan(E,F){return E>F},bxor:function bxor(E,F){return E^F},bnot:function bnot(E){return~E},is_bitstring:function is_bitstring$1(E){return E instanceof g.BitString},is_boolean:function is_boolean$1(E){return'boolean'==typeof E||E instanceof Boolean},is_float:function is_float(E){return is_number$1(E)&&!_NumberisInteger(E)},is_function:function is_function$1(E){return'function'==typeof E||E instanceof Function},is_integer:function is_integer(E){return _NumberisInteger(E)},is_list:function is_list(E){return Array.isArray(E)},is_map:function is_map(E){return'object'==typeof E||E instanceof Object},is_number:is_number$1,is_pid:function is_pid(E){return E instanceof g.PID},is_port:function is_port(){return!1},is_reference:function is_reference(E){return E instanceof g.Reference},is_tuple:function is_tuple(E){return E instanceof g.Tuple},is_atom:function is_atom(E){return'symbol'==typeof E||E instanceof Symbol||E.__MODULE__},is_binary:function is_binary(E){return'string'==typeof E||E instanceof String},element:function element(E,F){return F.get(E-1)},setelement:function setelement(E,F,G){const H=[...F.values];return H[E-1]=G,new g.Tuple(...H)},make_tuple:function make_tuple(E,F){const G=[];for(let H=0;H!0){let H=[],I=buildMatch(E);const J=I(F,H),[K,L]=checkNamedVariables(H);if(J&&L&&G.apply(this,K))return K;throw console.error('No match for:',F),new MatchError(F)},MatchError,variable:function variable(E=null,F=Symbol.for('tailored.no_value')){return new Variable(E,F)},wildcard:function wildcard(){return new Wildcard},startsWith:function startsWith(E){return new StartsWith(E)},capture:function capture(E){return new Capture(E)},headTail:function headTail(){return new HeadTail},type:function type(E,F={}){return new Type(E,F)},bound:function bound(E){return new Bound(E)},Clause,clause:function clause(E,F,G=()=>!0){return new Clause(E,F,G)},bitStringMatch:function bitStringMatch(...E){return new BitStringMatch(...E)},match_or_default,defmatchgen,list_comprehension:function list_comprehension(E,F){const G=run_generators(F.pop()(),F);let H=[];for(let I of G)E.guard.apply(this,I)&&H.push(E.fn.apply(this,I));return H},list_generator:function list_generator(E,F){return function(){let G=[];for(let H of F){const I=match_or_default(E,H,()=>!0,l);if(I!=l){const[J]=I;G.push(J)}}return G}},bitstring_generator:function bitstring_generator(E,F){return function(){let G=[],H=F.slice(0,E.byte_size()),I=1;for(;H.byte_size==E.byte_size();){const J=match_or_default(E,H,()=>!0,l);J!=l&&G.push(J),H=F.slice(E.byte_size()*I,E.byte_size()*(I+1)),I++}return G}},bitstring_comprehension:function bitstring_comprehension(E,F){const G=run_generators(F.pop()(),F);let H=[];for(let I of G)E.guard.apply(this,I)&&H.push(E.fn.apply(this,I));return H=H.map((I)=>g.BitString.integer(I)),new g.BitString(...H)},defmatchGen:function defmatchGen(...E){return defmatchgen(...E)},defmatchAsync:function defmatchAsync(...E){const F=getArityMap(E);return async function(...G){if(F.has(G.length)){const H=F.get(G.length);let I=null,J=null;for(let K of H){let L=[];G=fillInOptionalValues(G,K.arity,K.optionals);const M=K.pattern(G,L),[N,O]=checkNamedVariables(L);if(M&&O&&(await K.guard.apply(this,L))){I=K.fn,J=L;break}}if(!I)throw console.error('No match for:',G),new MatchError(G);return I.apply(this,J)}throw console.error('Arity of',G.length,'not found. No match for:',G),new MatchError(G)}}},Integer:class Integer{},Float:class Float{},Functions:{call_property:function call_property(E,F){if(!F)return E instanceof Function||'function'==typeof E?E():E;let G=null;if('number'==typeof E||'symbol'==typeof E||'boolean'==typeof E||'string'==typeof E?void 0===E[F]?void 0!==E[Symbol.for(F)]&&(G=Symbol.for(F)):G=F:F in E?G=F:Symbol.for(F)in E&&(G=Symbol.for(F)),null===G)throw new Error(`Property ${F} not found in ${E}`);return E[G]instanceof Function||'function'==typeof E[G]?E[G]():E[G]},defprotocol:function defprotocol(E){return new Protocol(E)},defimpl:function defimpl(E,F,G){E.implementation(F,G)},build_namespace:function build_namespace(E,F){let G=F.split('.');const H=E;let I=E;'Elixir'===G[0]&&(G=G.slice(1));for(const J of G)'undefined'==typeof I[J]&&(I[J]={}),I=I[J];return H.__table__=E.__table__||{},H.__table__[Symbol.for(F)]=I,I},iterator_to_reducer},SpecialForms:{_case:function _case(E,F){return C.Patterns.defmatch(...F)(E)},cond:function cond(...E){for(const F of E)if(F[0])return F[1]();throw new Error},_for:function _for(E,F,G,H=[]){let[I,J]=G.into(H);const K=run_list_generators(F.pop()(),F);for(const L of K)E.guard.apply(this,L)&&(I=J(I,new C.Tuple(Symbol.for('cont'),E.fn.apply(this,L))));return J(I,Symbol.for('done'))},_try:function _try(E,F,G,H,I){let J=null;try{J=E()}catch(K){let L=null;if(F)try{return L=F(K),L}catch(M){if(M instanceof C.Patterns.MatchError)throw M}if(G)try{return L=G(K),L}catch(M){if(M instanceof C.Patterns.MatchError)throw M}throw K}finally{I&&I()}if(H)try{return H(J)}catch(K){if(K instanceof C.Patterns.MatchError)throw new Error('No Match Found in Else');throw K}else return J},_with:function _with(...E){let F=[],G=null,H=null;'function'==typeof E[E.length-2]?[G,H]=E.splice(-2):G=E.pop();for(let I=0;I{const[H,I]=G;return F[H]=I,F},{})},keys,values:function values$1(E){if(!1===q.is_map(E))return new g.Tuple(u,E);const F=[];for(const G of keys(E))F.push(E[G]);return F},is_key,put:function put(E,F,G){if(!1===q.is_map(G))return new g.Tuple(u,G);const H=Object.assign({},G,{[E]:F});return H},merge:function merge(E,F){return!1===q.is_map(E)?new g.Tuple(u,E):!1===q.is_map(F)?new g.Tuple(u,F):Object.assign({},E,F)},update:function update(E,F,G){return!1===q.is_map(G)?new g.Tuple(u,G):!1===is_key(E,G)?new g.Tuple(w,E):Object.assign({},G,{[E]:F})},get:function get(...E){const F=E[0],G=E[1];return!1===q.is_map(G)?new g.Tuple(u,G):is_key(F)?G[F]:3===E.length?E[2]:new g.Tuple(w,F)},take:function take(E,F){if(!1===q.is_map(F))return new g.Tuple(u,F);if(!is_key(E))return t;const G=F[E],H=Object.assign({},F);return delete H[E],new g.Tuple(G,H)}},lists:{reverse,foreach:function foreach(E,F){return F.forEach((G)=>E(G)),Symbol.for('ok')},duplicate:function duplicate(E,F){const G=[];for(;G.length{return H.get(E-1)I.get(E-1)?1:0})},keystore:function keystore(E,F,G,H){const I=[...G];for(let J=0;JF.toString()).join()},map:function map(E,F){return F.map((G)=>E(G))},filter:function filter(E,F){return F.filter((G)=>E(G))},filtermap:function filtermap(E,F){const G=[];for(const H of F){const I=E(H);!0===I?G.push(H):I instanceof g.Tuple&&!0===I.get(0)&&G.push(I.get(1))}return G},member:function member(E,F){for(const G of F)if(G===E)return!0;return!1},all:function all(E,F){for(const G of F)if(!1===E(G))return!1;return!0},any:function any(E,F){for(const G of F)if(!0===E(G))return!0;return!1},splitwith:function splitwith(E,F){let G=!1;const H=[],I=[];for(const J of F)!0==G?I.push(J):!0===E(J)?H.push(J):(G=!0,I.push(J));return new g.Tuple(H,I)},sort:function sort(...E){if(1===E.length){const H=[...E[0]];return H.sort()}const F=E[0],G=[...E[1]];return G.sort((H,I)=>{const J=F(H,I);return!0===J?-1:1})}}};return{Core:C}}(); diff --git a/src/javascript/lib/core/store.js b/src/javascript/lib/core/store.js index f0ebc0ec..5dc364d8 100644 --- a/src/javascript/lib/core/store.js +++ b/src/javascript/lib/core/store.js @@ -21,22 +21,22 @@ function create(value, name = null) { __elixirscript_names__.set(name, key); } - __elixirscript_store__.set(key, value); + return __elixirscript_store__.set(key, value); } function update(key, value) { const real_key = get_key(key); - __elixirscript_store__.set(real_key, value); + return __elixirscript_store__.set(real_key, value); } function read(key) { const real_key = get_key(key); - __elixirscript_store__.get(real_key); + return __elixirscript_store__.get(real_key); } function remove(key) { const real_key = get_key(key); - __elixirscript_store__.delete(real_key); + return __elixirscript_store__.delete(real_key); } export default { From b3277f8c01f20e9c2c00557a55af8b08f10f3857 Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Sun, 16 Jul 2017 16:47:27 -0500 Subject: [PATCH 619/860] Update super implementation --- lib/elixir_script/passes/translate/form.ex | 2 +- test/passes/translate/form_test.exs | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/lib/elixir_script/passes/translate/form.ex b/lib/elixir_script/passes/translate/form.ex index c6e1ab2e..70e2af99 100644 --- a/lib/elixir_script/passes/translate/form.ex +++ b/lib/elixir_script/passes/translate/form.ex @@ -228,7 +228,7 @@ defmodule ElixirScript.Translate.Form do Remote.compile(ast, state) end - def compile({:super, _, params}, state) when is_list(params) do + def compile({:super, _, [_ | params]}, state) when is_list(params) do {function_name, _} = Map.get(state, :function) {var_decs, params} = compile_params(params, state) diff --git a/test/passes/translate/form_test.exs b/test/passes/translate/form_test.exs index 0e5a353f..ea154950 100644 --- a/test/passes/translate/form_test.exs +++ b/test/passes/translate/form_test.exs @@ -97,8 +97,8 @@ defmodule ElixirScript.Translate.Forms.Test do end test "super" do - ast = {:super, [], [1]} - state = %{function: {:my_function, nil}} + ast = {:super, [], [{:def, :my_function}, 1]} + state = %{function: {:my_function, nil}, vars: %{}} {js_ast, _} = Form.compile(ast, state) assert js_ast == J.call_expression( From c27de808312c47f2d425458165873c06abb41896 Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Mon, 17 Jul 2017 20:17:11 -0500 Subject: [PATCH 620/860] Update node dependencies --- package.json | 20 +- priv/build/iife/ElixirScript.Core.js | 12 +- yarn.lock | 1073 ++++++++++++-------------- 3 files changed, 516 insertions(+), 589 deletions(-) diff --git a/package.json b/package.json index d7d2c1a3..8e013597 100644 --- a/package.json +++ b/package.json @@ -23,22 +23,22 @@ "license": "MIT", "dependencies": { "erlang-types": "^1.0.1", - "tailored": "^2.5.0" + "tailored": "^2.6.0" }, "devDependencies": { - "ava": "^0.19.1", + "ava": "^0.21.0", "babel-core": "^6.24.0", - "babel-preset-env": "^1.3.2", + "babel-preset-env": "^1.6.0", "babel-register": "^6.24.0", - "eslint": "^3.15.0", + "eslint": "^4.2.0", "eslint-config-airbnb-base": "^11.1.0", - "eslint-plugin-import": "^2.2.0", - "nyc": "^10.3.2", - "rollup": "^0.41.6", + "eslint-plugin-import": "^2.7.0", + "nyc": "^11.0.3", + "rollup": "^0.45.2", "rollup-plugin-babel": "^2.7.1", - "rollup-plugin-babili": "^2.0.0", - "rollup-plugin-node-resolve": "^2.0.0", - "sinon": "^1.17.7" + "rollup-plugin-babili": "^3.1.0", + "rollup-plugin-node-resolve": "^3.0.0", + "sinon": "^2.3.8" }, "ava": { "require": [ diff --git a/priv/build/iife/ElixirScript.Core.js b/priv/build/iife/ElixirScript.Core.js index 42ff134f..a6c133c6 100644 --- a/priv/build/iife/ElixirScript.Core.js +++ b/priv/build/iife/ElixirScript.Core.js @@ -1,6 +1,6 @@ -var _NumberisInteger=Number.isInteger,_StringfromCharCode=String.fromCharCode,ElixirScript=function(){'use strict';/* @flow */function namedVariableResult(E,F){return new NamedVariableResult(E,F)}/* @flow */function is_number(E){return'number'==typeof E}function is_string(E){return'string'==typeof E}function is_boolean(E){return'boolean'==typeof E}function is_symbol(E){return'symbol'==typeof E}function is_object(E){return'object'==typeof E}function is_variable(E){return E instanceof Variable}function is_null(E){return null===E}function is_array(E){return Array.isArray(E)}function is_function(E){return'[object Function]'==Object.prototype.toString.call(E)}function resolveNull(){return function(F){return is_null(F)}}function resolveWildcard(){return function(){return!0}}function resolveObject(E){let F={};const G=Object.keys(E).concat(Object.getOwnPropertySymbols(E));for(let H of G)F[H]=buildMatch(E[H]);return function(H,I){if(!is_object(H)||E.length>H.length)return!1;for(let J of G)if(!(J in H)||!F[J](H[J],I))return!1;return!0}}function getSize(E,F){return E*F/8}function arraysEqual(E,F){if(E===F)return!0;if(null==E||null==F)return!1;if(E.length!=F.length)return!1;for(var G=0;Gh.integer(G));return new h(...F)}function resolveNoMatch(){return function(){return!1}}function buildMatch(E){if(null===E)return resolveNull(E);if('undefined'==typeof E)return resolveWildcard(E);const F=E.constructor.prototype,G=k.get(F);return G?G(E):'object'==typeof E?resolveObject(E):resolveNoMatch()}function defmatchgen(...E){const F=getArityMap(E);return function*(...G){let[H,I]=findMatchingFunction(G,F);return yield*H.apply(this,I)}}function findMatchingFunction(E,F){if(F.has(E.length)){const G=F.get(E.length);let H=null,I=null;for(let J of G){let K=[];E=fillInOptionalValues(E,J.arity,J.optionals);const L=J.pattern(E,K),[M,N]=checkNamedVariables(K);if(L&&N&&J.guard.apply(this,M)){H=J.fn,I=M;break}}if(!H)throw console.error('No match for:',E),new MatchError(E);return[H,I]}throw console.error('Arity of',E.length,'not found. No match for:',E),new MatchError(E)}function getArityMap(E){let F=new Map;for(const G of E){const H=getArityRange(G);for(const I of H){let J=[];F.has(I)&&(J=F.get(I)),J.push(G),F.set(I,J)}}return F}function getArityRange(E){const F=E.arity-E.optionals.length,G=E.arity;let H=[F];for(;H[H.length-1]!=G;)H.push(H[H.length-1]+1);return H}function getOptionalValues(E){let F=[];for(let G=0;G!0,H=null){let I=[],J=buildMatch(E);const K=J(F,I),[L,M]=checkNamedVariables(I);return K&&M&&G.apply(this,L)?L:H}function run_generators(E,F){if(0==F.length)return E.map((G)=>{return Array.isArray(G)?G:[G]});const G=F.pop();let H=[];for(let I of G())for(let J of E)H.push([I].concat(J));return run_generators(H,F)}function iterator_to_reducer(E,F,G){const H=E[Symbol.iterator]();let I=H.next(),J=F;for(;!1===I.done;){if(J=G(I.value,J.get(1)),J.get(0)===Symbol.for('halt'))return new C.Tuple(Symbol.for('halted'),J.get(1));if(J.get(0)===Symbol.for('suspend'))return new C.Tuple(Symbol.for('suspended'),J.get(1),(K)=>{return iterator_to_reducer(H,K,G)});I=H.next()}return new C.Tuple(Symbol.for('done'),J.get(1))}function run_list_generators(E,F){if(0==F.length)return E.map((I)=>{return Array.isArray(I)?I:[I]});const G=F.pop(),H=[];for(const I of G())for(const J of E)H.push([I].concat(J));return run_list_generators(H,F)}// http://erlang.org/doc/man/erlang.html -function atom_to_binary(E,F=Symbol.for('utf8')){if(F!==Symbol.for('utf8'))throw new Error(`unsupported encoding ${F}`);return E.__MODULE__?Symbol.keyFor(E.__MODULE__):Symbol.keyFor(E)}function binary_to_atom(E,F=Symbol.for('utf8')){if(F!==Symbol.for('utf8'))throw new Error(`unsupported encoding ${F}`);return Symbol.for(E)}function is_number$1(E){return'number'==typeof E||E instanceof Number}function to_list(E){if(!1===q.is_map(E))return new g.Tuple(u,E);const F=[];for(const G of keys(E))F.push(new g.Tuple(G,E[G]));return F}function keys(E){if(!1===q.is_map(E))return new g.Tuple(u,E);const F=[];for(const G of Object.getOwnPropertySymbols(E))F.push(G);for(const G of Object.getOwnPropertyNames(E))F.push(G);return F}function is_key(E,F){return F.hasOwnProperty(E)}// http://erlang.org/doc/man/lists.html -function reverse(E){return[...E].reverse()}function flatten(E,F=[]){const G=E.reduce((H,I)=>{return Array.isArray(I)?H.concat(flatten(I)):H.concat(I)},[]);return G.concat(F)}function foldl(E,F,G){return G.reduce((H,I)=>{return E(I,H)},F)}function keyfind(E,F,G){for(const H of G)if(H.get(F-1)===E)return H;return!1}function keydelete(E,F,G){const H=[];let I=!1;for(let J=0;JBitString$1.integer(I));return new BitString$1(...H)}[Symbol.iterator](){return this.value[Symbol.iterator]()}toString(){var E,F='';for(E=0;E>'}process(E){let F=[];var G;for(G=0;GH?F.push(H):2048>H?F.push(192|H>>6,128|63&H):55296>H||57344<=H?F.push(224|H>>12,128|63&H>>6,128|63&H):(G++,H=65536+((1023&H)<<10|1023&E.charCodeAt(G)),F.push(240|H>>18,128|63&H>>12,128|63&H>>6,128|63&H));return F}static toUTF16Array(E){for(var H,F=[],G=0;G=H?(F.push(0),F.push(H)):(F.push(255&H>>8),F.push(255&H));return F}static toUTF32Array(E){for(var H,F=[],G=0;G=H?(F.push(0),F.push(0),F.push(0),F.push(H)):(F.push(0),F.push(0),F.push(255&H>>8),F.push(255&H));return F}//http://stackoverflow.com/questions/2003493/javascript-float-from-to-bits -static float32ToBytes(E){var F=[],G=new ArrayBuffer(4);new Float32Array(G)[0]=E;let H=new Uint32Array(G)[0];return F.push(255&H>>24),F.push(255&H>>16),F.push(255&H>>8),F.push(255&H),F}static float64ToBytes(E){var F=[],G=new ArrayBuffer(8);new Float64Array(G)[0]=E;var H=new Uint32Array(G)[0],I=new Uint32Array(G)[1];return F.push(255&I>>24),F.push(255&I>>16),F.push(255&I>>8),F.push(255&I),F.push(255&H>>24),F.push(255&H>>16),F.push(255&H>>8),F.push(255&H),F}}var g={Tuple,PID:class PID{constructor(){++c,this.id=c}toString(){return'PID#<0.'+this.id+'.0>'}},Reference:class Reference{constructor(){++d,this.id=d,this.ref=Symbol()}toString(){return'Ref#<0.0.0.'+this.id+'>'}},BitString:BitString$1};/* @flow */const h=g.BitString,k=new Map;k.set(Variable.prototype,function resolveVariable(E){return function(F,G){return null===E.name||E.name.startsWith('_')?G.push(F):G.push(namedVariableResult(E.name,F)),!0}}),k.set(Wildcard.prototype,resolveWildcard),k.set(HeadTail.prototype,function resolveHeadTail(){return function(E,F){if(!is_array(E)||2>E.length)return!1;const G=E[0],H=E.slice(1);return F.push(G),F.push(H),!0}}),k.set(StartsWith.prototype,function resolveStartsWith(E){const F=E.prefix;return function(G,H){return is_string(G)&&G.startsWith(F)&&(H.push(G.substring(F.length)),!0)}}),k.set(Capture.prototype,function resolveCapture(E){const F=buildMatch(E.value);return function(G,H){return!!F(G,H)&&(H.push(G),!0)}}),k.set(Bound.prototype,function resolveBound(E){return function(F){return typeof F==typeof E.value&&F===E.value}}),k.set(Type.prototype,function resolveType(E){return function(F,G){if(F instanceof E.type){const H=buildMatch(E.objPattern);return H(F,G)}return!1}}),k.set(BitStringMatch.prototype,function resolveBitString(E){let F=[];for(let H of E.values)if(is_variable(H.value)){let I=getSize(H.unit,H.size);fillArray(F,I)}else F=F.concat(new h(H).value);let G=E.values;return function(H,I){let J=null;if(!is_string(H)&&!(H instanceof h))return!1;J=is_string(H)?new h(h.binary(H)):H;let K=0;for(let M,L=0;LbuildMatch(G));return function(G,H){return is_array(G)&&G.length==E.length&&G.every(function(I,J){return F[J](G[J],H)})}}),k.set(String.prototype,function resolveString(E){return function(F){return is_string(F)&&F===E}}),k.set(Boolean.prototype,function resolveBoolean(E){return function(F){return is_boolean(F)&&F===E}}),k.set(Function.prototype,function resolveFunction(E){return function(F){return is_function(F)&&F===E}}),k.set(Object.prototype,resolveObject);class MatchError extends Error{constructor(E){if(super(),'symbol'==typeof E)this.message='No match for: '+E.toString();else if(Array.isArray(E)){let F=E.map((G)=>{return null===G?'null':'undefined'==typeof G?'undefined':G.toString()});this.message='No match for: '+F}else this.message='No match for: '+E;this.stack=new Error().stack,this.name=this.constructor.name}}class Clause{constructor(E,F,G=()=>!0){this.pattern=buildMatch(E),this.arity=E.length,this.optionals=getOptionalValues(E),this.fn=F,this.guard=G}}const l=Symbol();// https://github.com/airportyh/protomorphism -class Protocol{constructor(E){function createFun(F){return function(...G){const H=G[0];let I=null;if(null===H&&this.hasImplementation(Symbol('null'))?I=this.registry.get(Symbol)[F]:_NumberisInteger(H)&&this.hasImplementation(C.Integer)?I=this.registry.get(C.Integer)[F]:'number'==typeof H&&!_NumberisInteger(H)&&this.hasImplementation(C.Float)?I=this.registry.get(C.Float)[F]:'string'==typeof H&&this.hasImplementation(C.BitString)?I=this.registry.get(C.BitString)[F]:H&&H[Symbol.for('__struct__')]&&this.hasImplementation(H)?I=this.registry.get(H[Symbol.for('__struct__')].__MODULE__)[F]:null!==H&&this.hasImplementation(H)?I=this.registry.get(H.constructor)[F]:this.fallback&&(I=this.fallback[F]),null!=I){const J=I.apply(this,G);return J}throw new Error(`No implementation found for ${H}`)}}for(const F in this.registry=new Map,this.fallback=null,E)this[F]=createFun(F).bind(this)}implementation(E,F){null===E?this.fallback=F:this.registry.set(E,F)}hasImplementation(E){return E===C.Integer||E===C.Float||E===C.BitString?this.registry.has(E):E&&E[Symbol.for('__struct__')]?this.registry.has(E[Symbol.for('__struct__')].__MODULE__):this.registry.has(E.constructor)}}var q={atom_to_binary,binary_to_atom,binary_to_existing_atom:function binary_to_existing_atom(E,F=Symbol.for('utf8')){return binary_to_atom(E,F)},list_concatenation:function list_concatenation(E,F){return E.concat(F)},list_subtraction:function list_subtraction(E,F){const G=[...E];for(const H of F){const I=G.indexOf(H);-1F},greaterThanOrEqualTo:function greaterThanOrEqualTo(E,F){return E>=F},lessThan:function lessThan(E,F){return E>F},bxor:function bxor(E,F){return E^F},bnot:function bnot(E){return~E},is_bitstring:function is_bitstring$1(E){return E instanceof g.BitString},is_boolean:function is_boolean$1(E){return'boolean'==typeof E||E instanceof Boolean},is_float:function is_float(E){return is_number$1(E)&&!_NumberisInteger(E)},is_function:function is_function$1(E){return'function'==typeof E||E instanceof Function},is_integer:function is_integer(E){return _NumberisInteger(E)},is_list:function is_list(E){return Array.isArray(E)},is_map:function is_map(E){return'object'==typeof E||E instanceof Object},is_number:is_number$1,is_pid:function is_pid(E){return E instanceof g.PID},is_port:function is_port(){return!1},is_reference:function is_reference(E){return E instanceof g.Reference},is_tuple:function is_tuple(E){return E instanceof g.Tuple},is_atom:function is_atom(E){return'symbol'==typeof E||E instanceof Symbol||E.__MODULE__},is_binary:function is_binary(E){return'string'==typeof E||E instanceof String},element:function element(E,F){return F.get(E-1)},setelement:function setelement(E,F,G){const H=[...F.values];return H[E-1]=G,new g.Tuple(...H)},make_tuple:function make_tuple(E,F){const G=[];for(let H=0;H!0){let H=[],I=buildMatch(E);const J=I(F,H),[K,L]=checkNamedVariables(H);if(J&&L&&G.apply(this,K))return K;throw console.error('No match for:',F),new MatchError(F)},MatchError,variable:function variable(E=null,F=Symbol.for('tailored.no_value')){return new Variable(E,F)},wildcard:function wildcard(){return new Wildcard},startsWith:function startsWith(E){return new StartsWith(E)},capture:function capture(E){return new Capture(E)},headTail:function headTail(){return new HeadTail},type:function type(E,F={}){return new Type(E,F)},bound:function bound(E){return new Bound(E)},Clause,clause:function clause(E,F,G=()=>!0){return new Clause(E,F,G)},bitStringMatch:function bitStringMatch(...E){return new BitStringMatch(...E)},match_or_default,defmatchgen,list_comprehension:function list_comprehension(E,F){const G=run_generators(F.pop()(),F);let H=[];for(let I of G)E.guard.apply(this,I)&&H.push(E.fn.apply(this,I));return H},list_generator:function list_generator(E,F){return function(){let G=[];for(let H of F){const I=match_or_default(E,H,()=>!0,l);if(I!=l){const[J]=I;G.push(J)}}return G}},bitstring_generator:function bitstring_generator(E,F){return function(){let G=[],H=F.slice(0,E.byte_size()),I=1;for(;H.byte_size==E.byte_size();){const J=match_or_default(E,H,()=>!0,l);J!=l&&G.push(J),H=F.slice(E.byte_size()*I,E.byte_size()*(I+1)),I++}return G}},bitstring_comprehension:function bitstring_comprehension(E,F){const G=run_generators(F.pop()(),F);let H=[];for(let I of G)E.guard.apply(this,I)&&H.push(E.fn.apply(this,I));return H=H.map((I)=>g.BitString.integer(I)),new g.BitString(...H)},defmatchGen:function defmatchGen(...E){return defmatchgen(...E)},defmatchAsync:function defmatchAsync(...E){const F=getArityMap(E);return async function(...G){if(F.has(G.length)){const H=F.get(G.length);let I=null,J=null;for(let K of H){let L=[];G=fillInOptionalValues(G,K.arity,K.optionals);const M=K.pattern(G,L),[N,O]=checkNamedVariables(L);if(M&&O&&(await K.guard.apply(this,L))){I=K.fn,J=L;break}}if(!I)throw console.error('No match for:',G),new MatchError(G);return I.apply(this,J)}throw console.error('Arity of',G.length,'not found. No match for:',G),new MatchError(G)}}},Integer:class Integer{},Float:class Float{},Functions:{call_property:function call_property(E,F){if(!F)return E instanceof Function||'function'==typeof E?E():E;let G=null;if('number'==typeof E||'symbol'==typeof E||'boolean'==typeof E||'string'==typeof E?void 0===E[F]?void 0!==E[Symbol.for(F)]&&(G=Symbol.for(F)):G=F:F in E?G=F:Symbol.for(F)in E&&(G=Symbol.for(F)),null===G)throw new Error(`Property ${F} not found in ${E}`);return E[G]instanceof Function||'function'==typeof E[G]?E[G]():E[G]},defprotocol:function defprotocol(E){return new Protocol(E)},defimpl:function defimpl(E,F,G){E.implementation(F,G)},build_namespace:function build_namespace(E,F){let G=F.split('.');const H=E;let I=E;'Elixir'===G[0]&&(G=G.slice(1));for(const J of G)'undefined'==typeof I[J]&&(I[J]={}),I=I[J];return H.__table__=E.__table__||{},H.__table__[Symbol.for(F)]=I,I},iterator_to_reducer},SpecialForms:{_case:function _case(E,F){return C.Patterns.defmatch(...F)(E)},cond:function cond(...E){for(const F of E)if(F[0])return F[1]();throw new Error},_for:function _for(E,F,G,H=[]){let[I,J]=G.into(H);const K=run_list_generators(F.pop()(),F);for(const L of K)E.guard.apply(this,L)&&(I=J(I,new C.Tuple(Symbol.for('cont'),E.fn.apply(this,L))));return J(I,Symbol.for('done'))},_try:function _try(E,F,G,H,I){let J=null;try{J=E()}catch(K){let L=null;if(F)try{return L=F(K),L}catch(M){if(M instanceof C.Patterns.MatchError)throw M}if(G)try{return L=G(K),L}catch(M){if(M instanceof C.Patterns.MatchError)throw M}throw K}finally{I&&I()}if(H)try{return H(J)}catch(K){if(K instanceof C.Patterns.MatchError)throw new Error('No Match Found in Else');throw K}else return J},_with:function _with(...E){let F=[],G=null,H=null;'function'==typeof E[E.length-2]?[G,H]=E.splice(-2):G=E.pop();for(let I=0;I{const[H,I]=G;return F[H]=I,F},{})},keys,values:function values$1(E){if(!1===q.is_map(E))return new g.Tuple(u,E);const F=[];for(const G of keys(E))F.push(E[G]);return F},is_key,put:function put(E,F,G){if(!1===q.is_map(G))return new g.Tuple(u,G);const H=Object.assign({},G,{[E]:F});return H},merge:function merge(E,F){return!1===q.is_map(E)?new g.Tuple(u,E):!1===q.is_map(F)?new g.Tuple(u,F):Object.assign({},E,F)},update:function update(E,F,G){return!1===q.is_map(G)?new g.Tuple(u,G):!1===is_key(E,G)?new g.Tuple(w,E):Object.assign({},G,{[E]:F})},get:function get(...E){const F=E[0],G=E[1];return!1===q.is_map(G)?new g.Tuple(u,G):is_key(F)?G[F]:3===E.length?E[2]:new g.Tuple(w,F)},take:function take(E,F){if(!1===q.is_map(F))return new g.Tuple(u,F);if(!is_key(E))return t;const G=F[E],H=Object.assign({},F);return delete H[E],new g.Tuple(G,H)}},lists:{reverse,foreach:function foreach(E,F){return F.forEach((G)=>E(G)),Symbol.for('ok')},duplicate:function duplicate(E,F){const G=[];for(;G.length{return H.get(E-1)I.get(E-1)?1:0})},keystore:function keystore(E,F,G,H){const I=[...G];for(let J=0;JF.toString()).join()},map:function map(E,F){return F.map((G)=>E(G))},filter:function filter(E,F){return F.filter((G)=>E(G))},filtermap:function filtermap(E,F){const G=[];for(const H of F){const I=E(H);!0===I?G.push(H):I instanceof g.Tuple&&!0===I.get(0)&&G.push(I.get(1))}return G},member:function member(E,F){for(const G of F)if(G===E)return!0;return!1},all:function all(E,F){for(const G of F)if(!1===E(G))return!1;return!0},any:function any(E,F){for(const G of F)if(!0===E(G))return!0;return!1},splitwith:function splitwith(E,F){let G=!1;const H=[],I=[];for(const J of F)!0==G?I.push(J):!0===E(J)?H.push(J):(G=!0,I.push(J));return new g.Tuple(H,I)},sort:function sort(...E){if(1===E.length){const H=[...E[0]];return H.sort()}const F=E[0],G=[...E[1]];return G.sort((H,I)=>{const J=F(H,I);return!0===J?-1:1})}}};return{Core:C}}(); +var ElixirScript=function(){'use strict';/* @flow */function namedVariableResult(a,b){return new NamedVariableResult(a,b)}/* @flow */function is_number(a){return'number'==typeof a}function is_string(a){return'string'==typeof a}function is_boolean(a){return'boolean'==typeof a}function is_symbol(a){return'symbol'==typeof a}function is_object(a){return'object'==typeof a}function is_variable(a){return a instanceof Variable}function is_null(a){return null===a}function is_array(a){return Array.isArray(a)}function is_function(a){return'[object Function]'==Object.prototype.toString.call(a)}function is_map(a){return a instanceof Map}function resolveNull(){return function(a){return is_null(a)}}function resolveWildcard(){return function(){return!0}}function resolveObject(a){let b={};const c=Object.keys(a).concat(Object.getOwnPropertySymbols(a));for(let d of c)b[d]=buildMatch(a[d]);return function(d,e){if(!is_object(d)||a.length>d.length)return!1;for(let a of c)if(!(a in d)||!b[a](d[a],e))return!1;return!0}}function getSize(a,b){return a*b/8}function arraysEqual(c,a){if(c===a)return!0;if(null==c||null==a)return!1;if(c.length!=a.length)return!1;for(var b=0;be.integer(a));return new e(...b)}function resolveNoMatch(){return function(){return!1}}function buildMatch(a){if(null===a)return resolveNull(a);if('undefined'==typeof a)return resolveWildcard(a);const b=a.constructor.prototype,c=f.get(b);return c?c(a):'object'==typeof a?resolveObject(a):resolveNoMatch()}function defmatchgen(...a){const b=getArityMap(a);return function*(...a){let[c,d]=findMatchingFunction(a,b);return yield*c.apply(this,d)}}function findMatchingFunction(a,b){if(b.has(a.length)){const c=b.get(a.length);let d=null,e=null;for(let b of c){let c=[];a=fillInOptionalValues(a,b.arity,b.optionals);const f=b.pattern(a,c),[g,h]=checkNamedVariables(c);if(f&&h&&b.guard.apply(this,g)){d=b.fn,e=g;break}}if(!d)throw console.error('No match for:',a),new MatchError(a);return[d,e]}throw console.error('Arity of',a.length,'not found. No match for:',a),new MatchError(a)}function getArityMap(a){let b=new Map;for(const c of a){const a=getArityRange(c);for(const d of a){let a=[];b.has(d)&&(a=b.get(d)),a.push(c),b.set(d,a)}}return b}function getArityRange(a){const b=a.arity-a.optionals.length,c=a.arity;let d=[b];for(;d[d.length-1]!=c;)d.push(d[d.length-1]+1);return d}function getOptionalValues(a){let b=[];for(let c=0;c!0,d=null){let e=[],f=buildMatch(a);const g=f(b,e),[h,i]=checkNamedVariables(e);return g&&i&&c.apply(this,h)?h:d}function run_generators(a,b){if(0==b.length)return a.map((a)=>{return Array.isArray(a)?a:[a]});const c=b.pop();let d=[];for(let e of c())for(let b of a)d.push([e].concat(b));return run_generators(d,b)}function iterator_to_reducer(a,b,c){const d=a[Symbol.iterator]();let e=d.next(),f=b;for(;!1===e.done;){if(f=c(e.value,f.get(1)),f.get(0)===Symbol.for('halt'))return new n.Tuple(Symbol.for('halted'),f.get(1));if(f.get(0)===Symbol.for('suspend'))return new n.Tuple(Symbol.for('suspended'),f.get(1),(a)=>{return iterator_to_reducer(d,a,c)});e=d.next()}return new n.Tuple(Symbol.for('done'),f.get(1))}function run_list_generators(a,b){if(0==b.length)return a.map((a)=>{return Array.isArray(a)?a:[a]});const c=b.pop(),d=[];for(const e of c())for(const b of a)d.push([e].concat(b));return run_list_generators(d,b)}// http://erlang.org/doc/man/erlang.html +function atom_to_binary(a,b=Symbol.for('utf8')){if(b!==Symbol.for('utf8'))throw new Error(`unsupported encoding ${b}`);return a.__MODULE__?Symbol.keyFor(a.__MODULE__):Symbol.keyFor(a)}function binary_to_atom(a,b=Symbol.for('utf8')){if(b!==Symbol.for('utf8'))throw new Error(`unsupported encoding ${b}`);return Symbol.for(a)}function is_number$1(a){return'number'==typeof a||a instanceof Number}function to_list(a){if(!1===h.is_map(a))return new d.Tuple(k,a);const b=[];for(const c of keys(a))b.push(new d.Tuple(c,a[c]));return b}function keys(a){if(!1===h.is_map(a))return new d.Tuple(k,a);const b=[];for(const c of Object.getOwnPropertySymbols(a))b.push(c);for(const c of Object.getOwnPropertyNames(a))b.push(c);return b}function is_key(a,b){return b.hasOwnProperty(a)}// http://erlang.org/doc/man/lists.html +function reverse(a){return[...a]}function flatten(a,b=[]){const c=a.reduce((a,b)=>{return Array.isArray(b)?a.concat(flatten(b)):a.concat(b)},[]);return c.concat(b)}function foldl(a,b,c){return c.reduce((b,c)=>{return a(c,b)},b)}function keyfind(a,b,c){for(const d of c)if(d.get(b-1)===a)return d;return!1}function keydelete(a,b,c){const d=[];let e=!1;for(let f=0;fBitString$1.integer(a));return new BitString$1(...d)}[Symbol.iterator](){return this.value[Symbol.iterator]()}toString(){var a,b='';for(a=0;a>'}process(a){let b=[];var c;for(c=0;cb?c.push(b):2048>b?c.push(192|b>>6,128|63&b):55296>b||57344<=b?c.push(224|b>>12,128|63&b>>6,128|63&b):(d++,b=65536+((1023&b)<<10|1023&a.charCodeAt(d)),c.push(240|b>>18,128|63&b>>12,128|63&b>>6,128|63&b));return c}static toUTF16Array(a){for(var b,c=[],d=0;d=b?(c.push(0),c.push(b)):(c.push(255&b>>8),c.push(255&b));return c}static toUTF32Array(a){for(var b,c=[],d=0;d=b?(c.push(0),c.push(0),c.push(0),c.push(b)):(c.push(0),c.push(0),c.push(255&b>>8),c.push(255&b));return c}//http://stackoverflow.com/questions/2003493/javascript-float-from-to-bits +static float32ToBytes(a){var b=[],c=new ArrayBuffer(4);new Float32Array(c)[0]=a;let d=new Uint32Array(c)[0];return b.push(255&d>>24),b.push(255&d>>16),b.push(255&d>>8),b.push(255&d),b}static float64ToBytes(a){var b=[],c=new ArrayBuffer(8);new Float64Array(c)[0]=a;var d=new Uint32Array(c)[0],e=new Uint32Array(c)[1];return b.push(255&e>>24),b.push(255&e>>16),b.push(255&e>>8),b.push(255&e),b.push(255&d>>24),b.push(255&d>>16),b.push(255&d>>8),b.push(255&d),b}}var d={Tuple,PID:class PID{constructor(){++b,this.id=b}toString(){return'PID#<0.'+this.id+'.0>'}},Reference:class Reference{constructor(){++c,this.id=c,this.ref=Symbol()}toString(){return'Ref#<0.0.0.'+this.id+'>'}},BitString:BitString$1};/* @flow */const e=d.BitString,f=new Map;f.set(Variable.prototype,function resolveVariable(a){return function(b,c){return null===a.name||a.name.startsWith('_')?c.push(b):c.push(namedVariableResult(a.name,b)),!0}}),f.set(Wildcard.prototype,resolveWildcard),f.set(HeadTail.prototype,function resolveHeadTail(){return function(a,b){if(!is_array(a)||2>a.length)return!1;const c=a[0],d=a.slice(1);return b.push(c),b.push(d),!0}}),f.set(StartsWith.prototype,function resolveStartsWith(a){const b=a.prefix;return function(a,c){return is_string(a)&&a.startsWith(b)&&(c.push(a.substring(b.length)),!0)}}),f.set(Capture.prototype,function resolveCapture(a){const b=buildMatch(a.value);return function(a,c){return!!b(a,c)&&(c.push(a),!0)}}),f.set(Bound.prototype,function resolveBound(a){return function(b){return typeof b==typeof a.value&&b===a.value}}),f.set(Type.prototype,function resolveType(a){return function(b,c){if(b instanceof a.type){const d=buildMatch(a.objPattern);return d(b,c)}return!1}}),f.set(BitStringMatch.prototype,function resolveBitString(a){let b=[];for(let c of a.values)if(is_variable(c.value)){let a=getSize(c.unit,c.size);fillArray(b,a)}else b=b.concat(new e(c).value);let c=a.values;return function(a,d){var f=String.fromCharCode;let g=null;if(!is_string(a)&&!(a instanceof e))return!1;g=is_string(a)?new e(e.binary(a)):a;let h=0;for(let e,j=0;jd.size)return!1;for(let a of c)if(!d.has(a)||!b.get(a)(d.get(a),e))return!1;return!0}}),f.set(Array.prototype,function resolveArray(a){const b=a.map((a)=>buildMatch(a));return function(c,d){return is_array(c)&&c.length==a.length&&c.every(function(a,e){return b[e](c[e],d)})}}),f.set(String.prototype,function resolveString(a){return function(b){return is_string(b)&&b===a}}),f.set(Boolean.prototype,function resolveBoolean(a){return function(b){return is_boolean(b)&&b===a}}),f.set(Function.prototype,function resolveFunction(a){return function(b){return is_function(b)&&b===a}}),f.set(Object.prototype,resolveObject);class MatchError extends Error{constructor(a){if(super(),'symbol'==typeof a)this.message='No match for: '+a.toString();else if(Array.isArray(a)){let b=a.map((a)=>{return null===a?'null':'undefined'==typeof a?'undefined':a.toString()});this.message='No match for: '+b}else this.message='No match for: '+a;this.stack=new Error().stack,this.name=this.constructor.name}}class Clause{constructor(a,b,c=()=>!0){this.pattern=buildMatch(a),this.arity=a.length,this.optionals=getOptionalValues(a),this.fn=b,this.guard=c}}const g=Symbol();// https://github.com/airportyh/protomorphism +class Protocol{constructor(b){function createFun(b){return function(...c){const d=c[0];let e=null;if(null===d&&this.hasImplementation(Symbol('null'))?e=this.registry.get(Symbol)[b]:a(d)&&this.hasImplementation(n.Integer)?e=this.registry.get(n.Integer)[b]:'number'==typeof d&&!a(d)&&this.hasImplementation(n.Float)?e=this.registry.get(n.Float)[b]:'string'==typeof d&&this.hasImplementation(n.BitString)?e=this.registry.get(n.BitString)[b]:d&&d[Symbol.for('__struct__')]&&this.hasImplementation(d)?e=this.registry.get(d[Symbol.for('__struct__')].__MODULE__)[b]:null!==d&&this.hasImplementation(d)?e=this.registry.get(d.constructor)[b]:this.fallback&&(e=this.fallback[b]),null!=e){const a=e.apply(this,c);return a}throw new Error(`No implementation found for ${d}`)}}for(const a in this.registry=new Map,this.fallback=null,b)this[a]=createFun(a).bind(this)}implementation(a,b){null===a?this.fallback=b:this.registry.set(a,b)}hasImplementation(a){if(a===n.Integer||a===n.Float||a===n.BitString)return this.registry.has(a);return a&&a[Symbol.for('__struct__')]?this.registry.has(a[Symbol.for('__struct__')].__MODULE__):this.registry.has(a.constructor)}}var h={atom_to_binary,binary_to_atom,binary_to_existing_atom:function binary_to_existing_atom(a,b=Symbol.for('utf8')){return binary_to_atom(a,b)},list_concatenation:function list_concatenation(a,b){return a.concat(b)},list_subtraction:function list_subtraction(a,b){const c=[...a];for(const d of b){const a=c.indexOf(d);-1b},greaterThanOrEqualTo:function greaterThanOrEqualTo(a,b){return a>=b},lessThan:function lessThan(a,b){return a>b},bxor:function bxor(a,b){return a^b},bnot:function bnot(a){return~a},is_bitstring:function is_bitstring$1(a){return a instanceof d.BitString},is_boolean:function is_boolean$1(a){return'boolean'==typeof a||a instanceof Boolean},is_float:function is_float(b){return is_number$1(b)&&!a(b)},is_function:function is_function$1(a){return'function'==typeof a||a instanceof Function},is_integer:function is_integer(b){return a(b)},is_list:function is_list(a){return Array.isArray(a)},is_map:function is_map$1(a){return'object'==typeof a||a instanceof Object},is_number:is_number$1,is_pid:function is_pid(a){return a instanceof d.PID},is_port:function is_port(){return!1},is_reference:function is_reference(a){return a instanceof d.Reference},is_tuple:function is_tuple(a){return a instanceof d.Tuple},is_atom:function is_atom(a){return'symbol'==typeof a||a instanceof Symbol||a.__MODULE__},is_binary:function is_binary(a){return'string'==typeof a||a instanceof String},element:function element(a,b){return b.get(a-1)},setelement:function setelement(a,b,c){const e=[...b.values];return e[a-1]=c,new d.Tuple(...e)},make_tuple:function make_tuple(a,b){const c=[];for(let d=0;d!0){let d=[],e=buildMatch(a);const f=e(b,d),[g,h]=checkNamedVariables(d);if(f&&h&&c.apply(this,g))return g;throw console.error('No match for:',b),new MatchError(b)},MatchError,variable:function variable(a=null,b=Symbol.for('tailored.no_value')){return new Variable(a,b)},wildcard:function wildcard(){return new Wildcard},startsWith:function startsWith(a){return new StartsWith(a)},capture:function capture(a){return new Capture(a)},headTail:function headTail(){return new HeadTail},type:function a(a,b={}){return new Type(a,b)},bound:function bound(a){return new Bound(a)},Clause,clause:function clause(a,b,c=()=>!0){return new Clause(a,b,c)},bitStringMatch:function bitStringMatch(...a){return new BitStringMatch(...a)},match_or_default,defmatchgen,list_comprehension:function list_comprehension(a,b){const c=run_generators(b.pop()(),b);let d=[];for(let e of c)a.guard.apply(this,e)&&d.push(a.fn.apply(this,e));return d},list_generator:function list_generator(a,b){return function(){let c=[];for(let d of b){const b=match_or_default(a,d,()=>!0,g);if(b!=g){const[a]=b;c.push(a)}}return c}},bitstring_generator:function bitstring_generator(a,b){return function(){let c=[],d=b.slice(0,a.byte_size()),e=1;for(;d.byte_size==a.byte_size();){const f=match_or_default(a,d,()=>!0,g);if(f!=g){c.push(f)}d=b.slice(a.byte_size()*e,a.byte_size()*(e+1)),e++}return c}},bitstring_comprehension:function bitstring_comprehension(a,b){const c=run_generators(b.pop()(),b);let e=[];for(let d of c)a.guard.apply(this,d)&&e.push(a.fn.apply(this,d));return e=e.map((a)=>d.BitString.integer(a)),new d.BitString(...e)},defmatchGen:function defmatchGen(...a){return defmatchgen(...a)},defmatchAsync:function defmatchAsync(...a){const b=getArityMap(a);return async function(...a){if(b.has(a.length)){const c=b.get(a.length);let d=null,e=null;for(let b of c){let c=[];a=fillInOptionalValues(a,b.arity,b.optionals);const f=b.pattern(a,c),[g,h]=checkNamedVariables(c);if(f&&h&&(await b.guard.apply(this,c))){d=b.fn,e=c;break}}if(!d)throw console.error('No match for:',a),new MatchError(a);return d.apply(this,e)}throw console.error('Arity of',a.length,'not found. No match for:',a),new MatchError(a)}}},Integer:class Integer{},Float:class Float{},Functions:{call_property:function call_property(a,b){if(!b)return a instanceof Function||'function'==typeof a?a():a;let c=null;if('number'==typeof a||'symbol'==typeof a||'boolean'==typeof a||'string'==typeof a?void 0===a[b]?void 0!==a[Symbol.for(b)]&&(c=Symbol.for(b)):c=b:b in a?c=b:Symbol.for(b)in a&&(c=Symbol.for(b)),null===c)throw new Error(`Property ${b} not found in ${a}`);return a[c]instanceof Function||'function'==typeof a[c]?a[c]():a[c]},defprotocol:function defprotocol(a){return new Protocol(a)},defimpl:function defimpl(a,b,c){a.implementation(b,c)},build_namespace:function build_namespace(a,b){let c=b.split('.');const d=a;let e=a;'Elixir'===c[0]&&(c=c.slice(1));for(const d of c)'undefined'==typeof e[d]&&(e[d]={}),e=e[d];return d.__table__=a.__table__||{},d.__table__[Symbol.for(b)]=e,e},iterator_to_reducer},SpecialForms:{_case:function _case(a,b){return n.Patterns.defmatch(...b)(a)},cond:function cond(...a){for(const b of a)if(b[0])return b[1]();throw new Error},_for:function _for(a,b,c,d=[]){let[e,f]=c.into(d);const g=run_list_generators(b.pop()(),b);for(const h of g)a.guard.apply(this,h)&&(e=f(e,new n.Tuple(Symbol.for('cont'),a.fn.apply(this,h))));return f(e,Symbol.for('done'))},_try:function _try(a,b,c,d,e){let f=null;try{f=a()}catch(a){let d=null;if(b)try{return d=b(a),d}catch(a){if(a instanceof n.Patterns.MatchError)throw a}if(c)try{return d=c(a),d}catch(a){if(a instanceof n.Patterns.MatchError)throw a}throw a}finally{e&&e()}if(d)try{return d(f)}catch(a){if(a instanceof n.Patterns.MatchError)throw new Error('No Match Found in Else');throw a}else return f},_with:function _with(...a){let b=[],c=null,d=null;'function'==typeof a[a.length-2]?[c,d]=a.splice(-2):c=a.pop();for(let c=0;c{const[c,d]=b;return a[c]=d,a},{})},keys,values:function values$1(a){if(!1===h.is_map(a))return new d.Tuple(k,a);const b=[];for(const c of keys(a))b.push(a[c]);return b},is_key,put:function put(a,b,c){if(!1===h.is_map(c))return new d.Tuple(k,c);const e=Object.assign({},c,{[a]:b});return e},merge:function merge(a,b){return!1===h.is_map(a)?new d.Tuple(k,a):!1===h.is_map(b)?new d.Tuple(k,b):Object.assign({},a,b)},update:function update(a,b,c){return!1===h.is_map(c)?new d.Tuple(k,c):!1===is_key(a,c)?new d.Tuple(l,a):Object.assign({},c,{[a]:b})},get:function get(...a){const b=a[0],c=a[1];return!1===h.is_map(c)?new d.Tuple(k,c):is_key(b)?c[b]:3===a.length?a[2]:new d.Tuple(l,b)},take:function take(a,b){if(!1===h.is_map(b))return new d.Tuple(k,b);if(!is_key(a))return j;const c=b[a],e=Object.assign({},b);return delete e[a],new d.Tuple(c,e)}},lists:{reverse,foreach:function foreach(a,b){return b.forEach((b)=>a(b)),Symbol.for('ok')},duplicate:function duplicate(a,b){const c=[];for(;c.length{if(d.get(c-1)a.get(c-1)?1:0})},keystore:function keystore(a,b,c,d){const e=[...c];for(let f=0;fa.toString()).join()},map:function map(a,b){return b.map((b)=>a(b))},filter:function filter(a,b){return b.filter((b)=>a(b))},filtermap:function filtermap(a,b){const c=[];for(const e of b){const b=a(e);!0===b?c.push(e):b instanceof d.Tuple&&!0===b.get(0)&&c.push(b.get(1))}return c},member:function member(a,b){for(const c of b)if(c===a)return!0;return!1},all:function all(a,b){for(const c of b)if(!1===a(c))return!1;return!0},any:function any(a,b){for(const c of b)if(!0===a(c))return!0;return!1},splitwith:function splitwith(a,b){let c=!1;const e=[],f=[];for(const d of b)!0==c?f.push(d):!0===a(d)?e.push(d):(c=!0,f.push(d));return new d.Tuple(e,f)},sort:function sort(...a){if(1===a.length){const b=[...a[0]];return b.sort()}const c=a[0],b=[...a[1]];return b.sort((d,a)=>{const b=c(d,a);return!0===b?-1:1})}}};return{Core:n}}(); diff --git a/yarn.lock b/yarn.lock index 1d33ab2c..4c47311a 100644 --- a/yarn.lock +++ b/yarn.lock @@ -6,7 +6,7 @@ version "2.0.0" resolved "https://registry.yarnpkg.com/@ava/babel-plugin-throws-helper/-/babel-plugin-throws-helper-2.0.0.tgz#2fc1fe3c211a71071a4eca7b8f7af5842cd1ae7c" -"@ava/babel-preset-stage-4@^1.0.0": +"@ava/babel-preset-stage-4@^1.1.0": version "1.1.0" resolved "https://registry.yarnpkg.com/@ava/babel-preset-stage-4/-/babel-preset-stage-4-1.1.0.tgz#ae60be881a0babf7d35f52aba770d1f6194f76bd" dependencies: @@ -30,17 +30,24 @@ "@ava/babel-plugin-throws-helper" "^2.0.0" babel-plugin-espower "^2.3.2" -"@ava/pretty-format@^1.1.0": - version "1.1.0" - resolved "https://registry.yarnpkg.com/@ava/pretty-format/-/pretty-format-1.1.0.tgz#d0a57d25eb9aeab9643bdd1a030642b91c123e28" +"@ava/write-file-atomic@^2.2.0": + version "2.2.0" + resolved "https://registry.yarnpkg.com/@ava/write-file-atomic/-/write-file-atomic-2.2.0.tgz#d625046f3495f1f5e372135f473909684b429247" dependencies: - ansi-styles "^2.2.1" - esutils "^2.0.2" + graceful-fs "^4.1.11" + imurmurhash "^0.1.4" + slide "^1.1.5" "@comandeer/babel-plugin-banner@^1.0.0": version "1.0.0" resolved "https://registry.yarnpkg.com/@comandeer/babel-plugin-banner/-/babel-plugin-banner-1.0.0.tgz#40bcce0bbee084b5b02545a33635d053c248356f" +"@concordance/react@^1.0.0": + version "1.0.0" + resolved "https://registry.yarnpkg.com/@concordance/react/-/react-1.0.0.tgz#fcf3cad020e5121bfd1c61d05bc3516aac25f734" + dependencies: + arrify "^1.0.1" + abbrev@1: version "1.1.0" resolved "https://registry.yarnpkg.com/abbrev/-/abbrev-1.1.0.tgz#d0554c2256636e2f56e7c2e5ad183f859428d81f" @@ -70,6 +77,15 @@ ajv@^4.7.0, ajv@^4.9.1: co "^4.6.0" json-stable-stringify "^1.0.1" +ajv@^5.2.0: + version "5.2.2" + resolved "https://registry.yarnpkg.com/ajv/-/ajv-5.2.2.tgz#47c68d69e86f5d953103b0074a9430dc63da5e39" + dependencies: + co "^4.6.0" + fast-deep-equal "^1.0.0" + json-schema-traverse "^0.3.0" + json-stable-stringify "^1.0.1" + align-text@^0.1.1, align-text@^0.1.3: version "0.1.4" resolved "https://registry.yarnpkg.com/align-text/-/align-text-0.1.4.tgz#0cd90a561093f35d0a99256c22b7069433fad117" @@ -88,19 +104,23 @@ ansi-align@^2.0.0: dependencies: string-width "^2.0.0" -ansi-escapes@^1.1.0: - version "1.4.0" - resolved "https://registry.yarnpkg.com/ansi-escapes/-/ansi-escapes-1.4.0.tgz#d3a8a83b319aa67793662b13e761c7911422306e" +ansi-escapes@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/ansi-escapes/-/ansi-escapes-2.0.0.tgz#5bae52be424878dd9783e8910e3fc2922e83c81b" ansi-regex@^2.0.0: version "2.1.1" resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-2.1.1.tgz#c3b33ab5ee360d86e0e628f0468ae7ef27d654df" +ansi-regex@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-3.0.0.tgz#ed0317c322064f79466c02966bddb605ab37d998" + ansi-styles@^2.2.1: version "2.2.1" resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-2.2.1.tgz#b432dd3358b634cf75e1e4664368240533c1ddbe" -ansi-styles@^3.0.0: +ansi-styles@^3.1.0: version "3.1.0" resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-3.1.0.tgz#09c202d5c917ec23188caa5c9cb9179cd9547750" dependencies: @@ -222,24 +242,26 @@ ava-init@^0.2.0: read-pkg-up "^2.0.0" write-pkg "^2.0.0" -ava@^0.19.1: - version "0.19.1" - resolved "https://registry.yarnpkg.com/ava/-/ava-0.19.1.tgz#43dd82435ad19b3980ffca2488f05daab940b273" +ava@^0.21.0: + version "0.21.0" + resolved "https://registry.yarnpkg.com/ava/-/ava-0.21.0.tgz#cd8d8ea3546f57150dea38548b9f72f8ca583d29" dependencies: - "@ava/babel-preset-stage-4" "^1.0.0" + "@ava/babel-preset-stage-4" "^1.1.0" "@ava/babel-preset-transform-test-files" "^3.0.0" - "@ava/pretty-format" "^1.1.0" + "@ava/write-file-atomic" "^2.2.0" + "@concordance/react" "^1.0.0" + ansi-escapes "^2.0.0" + ansi-styles "^3.1.0" arr-flatten "^1.0.1" array-union "^1.0.1" array-uniq "^1.0.2" arrify "^1.0.0" auto-bind "^1.1.0" ava-init "^0.2.0" - babel-code-frame "^6.16.0" babel-core "^6.17.0" bluebird "^3.0.0" caching-transform "^1.0.0" - chalk "^1.0.0" + chalk "^2.0.1" chokidar "^1.4.2" clean-stack "^1.1.1" clean-yaml-object "^0.1.0" @@ -249,59 +271,59 @@ ava@^0.19.1: co-with-promise "^4.6.0" code-excerpt "^2.1.0" common-path-prefix "^1.0.0" + concordance "^3.0.0" convert-source-map "^1.2.0" core-assert "^0.2.0" currently-unhandled "^0.4.1" debug "^2.2.0" - diff "^3.0.1" - diff-match-patch "^1.0.0" dot-prop "^4.1.0" empower-core "^0.6.1" equal-length "^1.0.0" figures "^2.0.0" - find-cache-dir "^0.1.1" + find-cache-dir "^1.0.0" fn-name "^2.0.0" get-port "^3.0.0" globby "^6.0.0" has-flag "^2.0.0" - hullabaloo-config-manager "^1.0.0" + hullabaloo-config-manager "^1.1.0" ignore-by-default "^1.0.0" + import-local "^0.1.1" indent-string "^3.0.0" is-ci "^1.0.7" is-generator-fn "^1.0.0" is-obj "^1.0.0" is-observable "^0.2.0" is-promise "^2.1.0" - jest-diff "19.0.0" - jest-snapshot "19.0.2" js-yaml "^3.8.2" last-line-stream "^1.0.0" + lodash.clonedeepwith "^4.5.0" lodash.debounce "^4.0.3" lodash.difference "^4.3.0" lodash.flatten "^4.2.0" - lodash.isequal "^4.5.0" loud-rejection "^1.2.0" - matcher "^0.1.1" + make-dir "^1.0.0" + matcher "^1.0.0" md5-hex "^2.0.0" meow "^3.7.0" - mkdirp "^0.5.1" - ms "^0.7.1" + ms "^2.0.0" multimatch "^2.1.0" observable-to-promise "^0.5.0" - option-chain "^0.1.0" + option-chain "^1.0.0" package-hash "^2.0.0" pkg-conf "^2.0.0" plur "^2.0.0" pretty-ms "^2.0.0" require-precompiled "^0.1.0" - resolve-cwd "^1.0.0" + resolve-cwd "^2.0.0" + safe-buffer "^5.1.1" slash "^1.0.0" source-map-support "^0.4.0" stack-utils "^1.0.0" - strip-ansi "^3.0.1" + strip-ansi "^4.0.0" strip-bom-buf "^1.0.0" - supports-color "^3.2.3" + supports-color "^4.0.0" time-require "^0.1.2" + trim-off-newlines "^1.0.1" unique-temp-dir "^1.0.0" update-notifier "^2.1.0" @@ -313,7 +335,7 @@ aws4@^1.2.1: version "1.6.0" resolved "https://registry.yarnpkg.com/aws4/-/aws4-1.6.0.tgz#83ef5ca860b2b32e4a0deedee8c771b9db57471e" -babel-code-frame@^6.16.0, babel-code-frame@^6.22.0: +babel-code-frame@^6.22.0: version "6.22.0" resolved "https://registry.yarnpkg.com/babel-code-frame/-/babel-code-frame-6.22.0.tgz#027620bee567a88c32561574e7fd0801d33118e4" dependencies: @@ -384,9 +406,9 @@ babel-helper-define-map@^6.24.1: babel-types "^6.24.1" lodash "^4.2.0" -babel-helper-evaluate-path@^0.0.3: - version "0.0.3" - resolved "https://registry.yarnpkg.com/babel-helper-evaluate-path/-/babel-helper-evaluate-path-0.0.3.tgz#1d103ac9d4a59e5d431842212f151785f7ac547b" +babel-helper-evaluate-path@^0.1.0: + version "0.1.0" + resolved "https://registry.yarnpkg.com/babel-helper-evaluate-path/-/babel-helper-evaluate-path-0.1.0.tgz#95d98c4ea36150483db2e7d3ec9e1954a72629cb" babel-helper-explode-assignable-expression@^6.24.1: version "6.24.1" @@ -396,9 +418,9 @@ babel-helper-explode-assignable-expression@^6.24.1: babel-traverse "^6.24.1" babel-types "^6.24.1" -babel-helper-flip-expressions@^0.0.2: - version "0.0.2" - resolved "https://registry.yarnpkg.com/babel-helper-flip-expressions/-/babel-helper-flip-expressions-0.0.2.tgz#7bab2cf61162bc92703e9b298ef512bcf77d6787" +babel-helper-flip-expressions@^0.1.2: + version "0.1.2" + resolved "https://registry.yarnpkg.com/babel-helper-flip-expressions/-/babel-helper-flip-expressions-0.1.2.tgz#77f6652f9de9c42401d827bd46ebd2109e3ef18a" babel-helper-function-name@^6.24.1: version "6.24.1" @@ -428,13 +450,9 @@ babel-helper-is-nodes-equiv@^0.0.1: version "0.0.1" resolved "https://registry.yarnpkg.com/babel-helper-is-nodes-equiv/-/babel-helper-is-nodes-equiv-0.0.1.tgz#34e9b300b1479ddd98ec77ea0bbe9342dfe39684" -babel-helper-is-void-0@^0.0.1: - version "0.0.1" - resolved "https://registry.yarnpkg.com/babel-helper-is-void-0/-/babel-helper-is-void-0-0.0.1.tgz#ed74553b883e68226ae45f989a99b02c190f105a" - -babel-helper-mark-eval-scopes@^0.0.3: - version "0.0.3" - resolved "https://registry.yarnpkg.com/babel-helper-mark-eval-scopes/-/babel-helper-mark-eval-scopes-0.0.3.tgz#902f75aeb537336edc35eb9f52b6f09db7785328" +babel-helper-is-void-0@^0.1.1: + version "0.1.1" + resolved "https://registry.yarnpkg.com/babel-helper-is-void-0/-/babel-helper-is-void-0-0.1.1.tgz#72f21a3abba0bef3837f9174fca731aed9a02888" babel-helper-mark-eval-scopes@^0.1.1: version "0.1.1" @@ -480,9 +498,9 @@ babel-helper-replace-supers@^6.24.1: babel-traverse "^6.24.1" babel-types "^6.24.1" -babel-helper-to-multiple-sequence-expressions@^0.0.4: - version "0.0.4" - resolved "https://registry.yarnpkg.com/babel-helper-to-multiple-sequence-expressions/-/babel-helper-to-multiple-sequence-expressions-0.0.4.tgz#d94414b386b6286fbaad77f073dea9b34324b01c" +babel-helper-to-multiple-sequence-expressions@^0.1.1: + version "0.1.1" + resolved "https://registry.yarnpkg.com/babel-helper-to-multiple-sequence-expressions/-/babel-helper-to-multiple-sequence-expressions-0.1.1.tgz#5f1b832b39e4acf954e9137f0251395c71196b35" babel-helpers@^6.24.1: version "6.24.1" @@ -515,20 +533,19 @@ babel-plugin-espower@^2.3.2: espurify "^1.6.0" estraverse "^4.1.1" -babel-plugin-minify-builtins@^0.0.2: - version "0.0.2" - resolved "https://registry.yarnpkg.com/babel-plugin-minify-builtins/-/babel-plugin-minify-builtins-0.0.2.tgz#f3be6121763c0c518d5ef82067cef4b615c9498c" +babel-plugin-minify-builtins@^0.1.3: + version "0.1.3" + resolved "https://registry.yarnpkg.com/babel-plugin-minify-builtins/-/babel-plugin-minify-builtins-0.1.3.tgz#4f21a7dcb51f91a04ea71d47ff0e8e3b05fec021" dependencies: - babel-helper-evaluate-path "^0.0.3" + babel-helper-evaluate-path "^0.1.0" -babel-plugin-minify-constant-folding@^0.0.4: - version "0.0.4" - resolved "https://registry.yarnpkg.com/babel-plugin-minify-constant-folding/-/babel-plugin-minify-constant-folding-0.0.4.tgz#b6e231026a6035e88ceadd206128d7db2b5c15e6" +babel-plugin-minify-constant-folding@^0.1.3: + version "0.1.3" + resolved "https://registry.yarnpkg.com/babel-plugin-minify-constant-folding/-/babel-plugin-minify-constant-folding-0.1.3.tgz#57bd172adf8b8d74ad7c99612eb950414ebea3ca" dependencies: - babel-helper-evaluate-path "^0.0.3" - jsesc "^2.4.0" + babel-helper-evaluate-path "^0.1.0" -babel-plugin-minify-dead-code-elimination@^0.1.4: +babel-plugin-minify-dead-code-elimination@^0.1.7: version "0.1.7" resolved "https://registry.yarnpkg.com/babel-plugin-minify-dead-code-elimination/-/babel-plugin-minify-dead-code-elimination-0.1.7.tgz#774f536f347b98393a27baa717872968813c342c" dependencies: @@ -536,49 +553,49 @@ babel-plugin-minify-dead-code-elimination@^0.1.4: babel-helper-remove-or-void "^0.1.1" lodash.some "^4.6.0" -babel-plugin-minify-flip-comparisons@^0.0.2: - version "0.0.2" - resolved "https://registry.yarnpkg.com/babel-plugin-minify-flip-comparisons/-/babel-plugin-minify-flip-comparisons-0.0.2.tgz#7d0953aa5876ede6118966bda9edecc63bf346ab" +babel-plugin-minify-flip-comparisons@^0.1.2: + version "0.1.2" + resolved "https://registry.yarnpkg.com/babel-plugin-minify-flip-comparisons/-/babel-plugin-minify-flip-comparisons-0.1.2.tgz#e286b40b7599b18dfea195071e4279465cfc1884" dependencies: - babel-helper-is-void-0 "^0.0.1" + babel-helper-is-void-0 "^0.1.1" -babel-plugin-minify-guarded-expressions@^0.0.4: - version "0.0.4" - resolved "https://registry.yarnpkg.com/babel-plugin-minify-guarded-expressions/-/babel-plugin-minify-guarded-expressions-0.0.4.tgz#957104a760e6a7ffd967005a7a11621bb42fd11c" +babel-plugin-minify-guarded-expressions@^0.1.2: + version "0.1.2" + resolved "https://registry.yarnpkg.com/babel-plugin-minify-guarded-expressions/-/babel-plugin-minify-guarded-expressions-0.1.2.tgz#dfc3d473b0362d9605d3ce0ac1e22328c60d1007" dependencies: - babel-helper-flip-expressions "^0.0.2" + babel-helper-flip-expressions "^0.1.2" -babel-plugin-minify-infinity@^0.0.3: - version "0.0.3" - resolved "https://registry.yarnpkg.com/babel-plugin-minify-infinity/-/babel-plugin-minify-infinity-0.0.3.tgz#4cc99b61d12b434ce80ad675103335c589cba9a1" +babel-plugin-minify-infinity@^0.1.2: + version "0.1.2" + resolved "https://registry.yarnpkg.com/babel-plugin-minify-infinity/-/babel-plugin-minify-infinity-0.1.2.tgz#5f1cf67ddedcba13c8a00da832542df0091a1cd4" -babel-plugin-minify-mangle-names@^0.0.8: - version "0.0.8" - resolved "https://registry.yarnpkg.com/babel-plugin-minify-mangle-names/-/babel-plugin-minify-mangle-names-0.0.8.tgz#1e2fea856dd742d5697aa26b427e41258a8c5b79" +babel-plugin-minify-mangle-names@^0.1.3: + version "0.1.3" + resolved "https://registry.yarnpkg.com/babel-plugin-minify-mangle-names/-/babel-plugin-minify-mangle-names-0.1.3.tgz#bfa24661a6794fb03833587e55828b65449e06fe" dependencies: - babel-helper-mark-eval-scopes "^0.0.3" + babel-helper-mark-eval-scopes "^0.1.1" -babel-plugin-minify-numeric-literals@^0.0.1: - version "0.0.1" - resolved "https://registry.yarnpkg.com/babel-plugin-minify-numeric-literals/-/babel-plugin-minify-numeric-literals-0.0.1.tgz#9597e6c31154d7daf3744d0bd417c144b275bd53" +babel-plugin-minify-numeric-literals@^0.1.1: + version "0.1.1" + resolved "https://registry.yarnpkg.com/babel-plugin-minify-numeric-literals/-/babel-plugin-minify-numeric-literals-0.1.1.tgz#d4b8b0c925f874714ee33ee4b26678583d7ce7fb" -babel-plugin-minify-replace@^0.0.1: - version "0.0.1" - resolved "https://registry.yarnpkg.com/babel-plugin-minify-replace/-/babel-plugin-minify-replace-0.0.1.tgz#5d5aea7cb9899245248d1ee9ce7a2fe556a8facc" +babel-plugin-minify-replace@^0.1.2: + version "0.1.2" + resolved "https://registry.yarnpkg.com/babel-plugin-minify-replace/-/babel-plugin-minify-replace-0.1.2.tgz#b90b9e71ab4d3b36325629a91beabe13b0b16ac1" -babel-plugin-minify-simplify@^0.0.8: - version "0.0.8" - resolved "https://registry.yarnpkg.com/babel-plugin-minify-simplify/-/babel-plugin-minify-simplify-0.0.8.tgz#597b23327bba4373fed1c51461a689bce9ff4979" +babel-plugin-minify-simplify@^0.1.2: + version "0.1.2" + resolved "https://registry.yarnpkg.com/babel-plugin-minify-simplify/-/babel-plugin-minify-simplify-0.1.2.tgz#a968f1658fdeb2fc759e81fe331d89829df0f6b9" dependencies: - babel-helper-flip-expressions "^0.0.2" + babel-helper-flip-expressions "^0.1.2" babel-helper-is-nodes-equiv "^0.0.1" - babel-helper-to-multiple-sequence-expressions "^0.0.4" + babel-helper-to-multiple-sequence-expressions "^0.1.1" -babel-plugin-minify-type-constructors@^0.0.4: - version "0.0.4" - resolved "https://registry.yarnpkg.com/babel-plugin-minify-type-constructors/-/babel-plugin-minify-type-constructors-0.0.4.tgz#52d8b623775107523227719ade2d0b7458758b5f" +babel-plugin-minify-type-constructors@^0.1.2: + version "0.1.2" + resolved "https://registry.yarnpkg.com/babel-plugin-minify-type-constructors/-/babel-plugin-minify-type-constructors-0.1.2.tgz#db53c5b76cb8e2fcd45d862f17104c78761337ee" dependencies: - babel-helper-is-void-0 "^0.0.1" + babel-helper-is-void-0 "^0.1.1" babel-plugin-syntax-async-functions@^6.8.0: version "6.13.0" @@ -776,23 +793,23 @@ babel-plugin-transform-exponentiation-operator@^6.22.0, babel-plugin-transform-e babel-plugin-syntax-exponentiation-operator "^6.8.0" babel-runtime "^6.22.0" -babel-plugin-transform-inline-consecutive-adds@^0.0.2: - version "0.0.2" - resolved "https://registry.yarnpkg.com/babel-plugin-transform-inline-consecutive-adds/-/babel-plugin-transform-inline-consecutive-adds-0.0.2.tgz#a58fcecfc09c08fbf9373a5a3e70746c03d01fc1" +babel-plugin-transform-inline-consecutive-adds@^0.1.2: + version "0.1.2" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-inline-consecutive-adds/-/babel-plugin-transform-inline-consecutive-adds-0.1.2.tgz#5442e9f1c19c78a7899f8a4dee6fd481f61001f5" -babel-plugin-transform-member-expression-literals@^6.8.1: +babel-plugin-transform-member-expression-literals@^6.8.4: version "6.8.4" resolved "https://registry.yarnpkg.com/babel-plugin-transform-member-expression-literals/-/babel-plugin-transform-member-expression-literals-6.8.4.tgz#05679bc40596b91293401959aa1620ab1b2be437" -babel-plugin-transform-merge-sibling-variables@^6.8.2: +babel-plugin-transform-merge-sibling-variables@^6.8.5: version "6.8.5" resolved "https://registry.yarnpkg.com/babel-plugin-transform-merge-sibling-variables/-/babel-plugin-transform-merge-sibling-variables-6.8.5.tgz#03abdf107c61241913eb268ddede6d5bc541862c" -babel-plugin-transform-minify-booleans@^6.8.0: +babel-plugin-transform-minify-booleans@^6.8.2: version "6.8.2" resolved "https://registry.yarnpkg.com/babel-plugin-transform-minify-booleans/-/babel-plugin-transform-minify-booleans-6.8.2.tgz#8451579f706e702c1e1ab2756de5c8ea369cf07c" -babel-plugin-transform-property-literals@^6.8.1: +babel-plugin-transform-property-literals@^6.8.4: version "6.8.4" resolved "https://registry.yarnpkg.com/babel-plugin-transform-property-literals/-/babel-plugin-transform-property-literals-6.8.4.tgz#6ad311110b80a192a56efb5ddf4fe3ca6f7a61da" dependencies: @@ -804,23 +821,23 @@ babel-plugin-transform-regenerator@^6.22.0: dependencies: regenerator-transform "0.9.11" -babel-plugin-transform-regexp-constructors@^0.0.6: - version "0.0.6" - resolved "https://registry.yarnpkg.com/babel-plugin-transform-regexp-constructors/-/babel-plugin-transform-regexp-constructors-0.0.6.tgz#0d92607f0d26268296980cb7c1dea5f2dd3e1e20" +babel-plugin-transform-regexp-constructors@^0.1.1: + version "0.1.1" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-regexp-constructors/-/babel-plugin-transform-regexp-constructors-0.1.1.tgz#312ab7487cc88a1c62ee25ea1b6087e89b87799c" -babel-plugin-transform-remove-console@^6.8.1: +babel-plugin-transform-remove-console@^6.8.4: version "6.8.4" resolved "https://registry.yarnpkg.com/babel-plugin-transform-remove-console/-/babel-plugin-transform-remove-console-6.8.4.tgz#41fddac19a729a4c3dd7ef2964eac07b096f9a8f" -babel-plugin-transform-remove-debugger@^6.8.1: +babel-plugin-transform-remove-debugger@^6.8.4: version "6.8.4" resolved "https://registry.yarnpkg.com/babel-plugin-transform-remove-debugger/-/babel-plugin-transform-remove-debugger-6.8.4.tgz#f85704a08adaa71b55d77005b5b94e9b9df21f6e" -babel-plugin-transform-remove-undefined@^0.0.5: - version "0.0.5" - resolved "https://registry.yarnpkg.com/babel-plugin-transform-remove-undefined/-/babel-plugin-transform-remove-undefined-0.0.5.tgz#12ef11805e06e861dd2eb0c7cc041d2184b8f410" +babel-plugin-transform-remove-undefined@^0.1.2: + version "0.1.2" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-remove-undefined/-/babel-plugin-transform-remove-undefined-0.1.2.tgz#e1ebf51110f6b1e0665f28382ef73f95e5023652" -babel-plugin-transform-simplify-comparison-operators@^6.8.1: +babel-plugin-transform-simplify-comparison-operators@^6.8.4: version "6.8.4" resolved "https://registry.yarnpkg.com/babel-plugin-transform-simplify-comparison-operators/-/babel-plugin-transform-simplify-comparison-operators-6.8.4.tgz#2aa24a262d664c8cb3e125a306c798d7a2de08d5" @@ -831,41 +848,41 @@ babel-plugin-transform-strict-mode@^6.24.1: babel-runtime "^6.22.0" babel-types "^6.24.1" -babel-plugin-transform-undefined-to-void@^6.8.0: +babel-plugin-transform-undefined-to-void@^6.8.2: version "6.8.2" resolved "https://registry.yarnpkg.com/babel-plugin-transform-undefined-to-void/-/babel-plugin-transform-undefined-to-void-6.8.2.tgz#fe2b1d294eb05e87524eb93724dea6e2c3d66fa1" -babel-preset-babili@^0.0.12: - version "0.0.12" - resolved "https://registry.yarnpkg.com/babel-preset-babili/-/babel-preset-babili-0.0.12.tgz#74d79205d54feae6470bc84231da0b9ac9fc7de9" - dependencies: - babel-plugin-minify-builtins "^0.0.2" - babel-plugin-minify-constant-folding "^0.0.4" - babel-plugin-minify-dead-code-elimination "^0.1.4" - babel-plugin-minify-flip-comparisons "^0.0.2" - babel-plugin-minify-guarded-expressions "^0.0.4" - babel-plugin-minify-infinity "^0.0.3" - babel-plugin-minify-mangle-names "^0.0.8" - babel-plugin-minify-numeric-literals "^0.0.1" - babel-plugin-minify-replace "^0.0.1" - babel-plugin-minify-simplify "^0.0.8" - babel-plugin-minify-type-constructors "^0.0.4" - babel-plugin-transform-inline-consecutive-adds "^0.0.2" - babel-plugin-transform-member-expression-literals "^6.8.1" - babel-plugin-transform-merge-sibling-variables "^6.8.2" - babel-plugin-transform-minify-booleans "^6.8.0" - babel-plugin-transform-property-literals "^6.8.1" - babel-plugin-transform-regexp-constructors "^0.0.6" - babel-plugin-transform-remove-console "^6.8.1" - babel-plugin-transform-remove-debugger "^6.8.1" - babel-plugin-transform-remove-undefined "^0.0.5" - babel-plugin-transform-simplify-comparison-operators "^6.8.1" - babel-plugin-transform-undefined-to-void "^6.8.0" +babel-preset-babili@^0.1.2: + version "0.1.4" + resolved "https://registry.yarnpkg.com/babel-preset-babili/-/babel-preset-babili-0.1.4.tgz#ad9d6651002f5bc3f07cab300781167f54724bf2" + dependencies: + babel-plugin-minify-builtins "^0.1.3" + babel-plugin-minify-constant-folding "^0.1.3" + babel-plugin-minify-dead-code-elimination "^0.1.7" + babel-plugin-minify-flip-comparisons "^0.1.2" + babel-plugin-minify-guarded-expressions "^0.1.2" + babel-plugin-minify-infinity "^0.1.2" + babel-plugin-minify-mangle-names "^0.1.3" + babel-plugin-minify-numeric-literals "^0.1.1" + babel-plugin-minify-replace "^0.1.2" + babel-plugin-minify-simplify "^0.1.2" + babel-plugin-minify-type-constructors "^0.1.2" + babel-plugin-transform-inline-consecutive-adds "^0.1.2" + babel-plugin-transform-member-expression-literals "^6.8.4" + babel-plugin-transform-merge-sibling-variables "^6.8.5" + babel-plugin-transform-minify-booleans "^6.8.2" + babel-plugin-transform-property-literals "^6.8.4" + babel-plugin-transform-regexp-constructors "^0.1.1" + babel-plugin-transform-remove-console "^6.8.4" + babel-plugin-transform-remove-debugger "^6.8.4" + babel-plugin-transform-remove-undefined "^0.1.2" + babel-plugin-transform-simplify-comparison-operators "^6.8.4" + babel-plugin-transform-undefined-to-void "^6.8.2" lodash.isplainobject "^4.0.6" -babel-preset-env@^1.3.2: - version "1.5.2" - resolved "https://registry.yarnpkg.com/babel-preset-env/-/babel-preset-env-1.5.2.tgz#cd4ae90a6e94b709f97374b33e5f8b983556adef" +babel-preset-env@^1.6.0: + version "1.6.0" + resolved "https://registry.yarnpkg.com/babel-preset-env/-/babel-preset-env-1.6.0.tgz#2de1c782a780a0a5d605d199c957596da43c44e4" dependencies: babel-plugin-check-es2015-constants "^6.22.0" babel-plugin-syntax-trailing-function-commas "^6.22.0" @@ -950,7 +967,7 @@ babel-types@^6.18.0, babel-types@^6.19.0, babel-types@^6.24.1, babel-types@^6.25 lodash "^4.2.0" to-fast-properties "^1.0.1" -babylon@^6.1.0, babylon@^6.13.0, babylon@^6.17.2: +babylon@^6.1.0, babylon@^6.17.2, babylon@^6.17.4: version "6.17.4" resolved "https://registry.yarnpkg.com/babylon/-/babylon-6.17.4.tgz#3e8b7402b88d22c3423e137a1577883b15ff869a" @@ -1082,7 +1099,7 @@ camelcase@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-3.0.0.tgz#32fc4b9fcdaf845fcdf7e73bb97cac2261f0ab0a" -camelcase@^4.0.0: +camelcase@^4.0.0, camelcase@^4.1.0: version "4.1.0" resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-4.1.0.tgz#d545635be1e33c542649c69173e5de6acfae34dd" @@ -1123,6 +1140,14 @@ chalk@^1.0.0, chalk@^1.1.0, chalk@^1.1.1, chalk@^1.1.3: strip-ansi "^3.0.0" supports-color "^2.0.0" +chalk@^2.0.0, chalk@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.0.1.tgz#dbec49436d2ae15f536114e76d14656cdbc0f44d" + dependencies: + ansi-styles "^3.1.0" + escape-string-regexp "^1.0.5" + supports-color "^4.0.0" + chokidar@^1.4.2: version "1.7.0" resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-1.7.0.tgz#798e689778151c8076b4b360e5edd28cda2bb468" @@ -1158,12 +1183,6 @@ cli-boxes@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/cli-boxes/-/cli-boxes-1.0.0.tgz#4fa917c3e59c94a004cd61f8ee509da651687143" -cli-cursor@^1.0.1: - version "1.0.2" - resolved "https://registry.yarnpkg.com/cli-cursor/-/cli-cursor-1.0.2.tgz#64da3f7d56a54412e59794bd62dc35295e8f2987" - dependencies: - restore-cursor "^1.0.1" - cli-cursor@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/cli-cursor/-/cli-cursor-2.1.0.tgz#b35dac376479facc3e94747d41d0d0f5238ffcb5" @@ -1249,7 +1268,7 @@ concat-map@0.0.1: version "0.0.1" resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b" -concat-stream@^1.5.2: +concat-stream@^1.6.0: version "1.6.0" resolved "https://registry.yarnpkg.com/concat-stream/-/concat-stream-1.6.0.tgz#0aac662fd52be78964d5532f694784e70110acf7" dependencies: @@ -1257,6 +1276,22 @@ concat-stream@^1.5.2: readable-stream "^2.2.2" typedarray "^0.0.6" +concordance@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/concordance/-/concordance-3.0.0.tgz#b2286af54405fc995fc7345b0b106d8dd073cb29" + dependencies: + date-time "^2.1.0" + esutils "^2.0.2" + fast-diff "^1.1.1" + function-name-support "^0.2.0" + js-string-escape "^1.0.1" + lodash.clonedeep "^4.5.0" + lodash.flattendeep "^4.4.0" + lodash.merge "^4.6.0" + md5-hex "^2.0.0" + semver "^5.3.0" + well-known-symbols "^1.0.0" + configstore@^3.0.0: version "3.1.0" resolved "https://registry.yarnpkg.com/configstore/-/configstore-3.1.0.tgz#45df907073e26dfa1cf4b2d52f5b60545eaa11d1" @@ -1335,12 +1370,6 @@ currently-unhandled@^0.4.1: dependencies: array-find-index "^1.0.1" -d@1: - version "1.0.0" - resolved "https://registry.yarnpkg.com/d/-/d-1.0.0.tgz#754bb5bfe55451da69a58b94d45f4c5b0462d58f" - dependencies: - es5-ext "^0.10.9" - dashdash@^1.12.0: version "1.14.1" resolved "https://registry.yarnpkg.com/dashdash/-/dashdash-1.14.1.tgz#853cfa0f7cbe2fed5de20326b8dd581035f6e2f0" @@ -1351,6 +1380,12 @@ date-time@^0.1.1: version "0.1.1" resolved "https://registry.yarnpkg.com/date-time/-/date-time-0.1.1.tgz#ed2f6d93d9790ce2fd66d5b5ff3edd5bbcbf3b07" +date-time@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/date-time/-/date-time-2.1.0.tgz#0286d1b4c769633b3ca13e1e62558d2dbdc2eba2" + dependencies: + time-zone "^1.0.0" + debug-log@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/debug-log/-/debug-log-1.0.1.tgz#2307632d4c04382b8df8a32f70b895046d52745f" @@ -1413,13 +1448,9 @@ detect-indent@^5.0.0: version "5.0.0" resolved "https://registry.yarnpkg.com/detect-indent/-/detect-indent-5.0.0.tgz#3871cc0a6a002e8c3e5b3cf7f336264675f06b9d" -diff-match-patch@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/diff-match-patch/-/diff-match-patch-1.0.0.tgz#1cc3c83a490d67f95d91e39f6ad1f2e086b63048" - -diff@^3.0.0, diff@^3.0.1: - version "3.2.0" - resolved "https://registry.yarnpkg.com/diff/-/diff-3.2.0.tgz#c9ce393a4b7cbd0b058a725c93df299027868ff9" +diff@^3.1.0: + version "3.3.0" + resolved "https://registry.yarnpkg.com/diff/-/diff-3.3.0.tgz#056695150d7aa93237ca7e378ac3b1682b7963b9" doctrine@1.5.0: version "1.5.0" @@ -1466,7 +1497,7 @@ equal-length@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/equal-length/-/equal-length-1.0.1.tgz#21ca112d48ab24b4e1e7ffc0e5339d31fdfc274c" -erlang-types@^1.0.0, erlang-types@^1.0.1: +erlang-types@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/erlang-types/-/erlang-types-1.0.1.tgz#943a57a9324e0d0edc0273690a8c702686d9b780" @@ -1476,148 +1507,91 @@ error-ex@^1.2.0: dependencies: is-arrayish "^0.2.1" -es5-ext@^0.10.14, es5-ext@^0.10.9, es5-ext@~0.10.14: - version "0.10.23" - resolved "https://registry.yarnpkg.com/es5-ext/-/es5-ext-0.10.23.tgz#7578b51be974207a5487821b56538c224e4e7b38" - dependencies: - es6-iterator "2" - es6-symbol "~3.1" - es6-error@^4.0.1, es6-error@^4.0.2: version "4.0.2" resolved "https://registry.yarnpkg.com/es6-error/-/es6-error-4.0.2.tgz#eec5c726eacef51b7f6b73c20db6e1b13b069c98" -es6-iterator@2, es6-iterator@^2.0.1, es6-iterator@~2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/es6-iterator/-/es6-iterator-2.0.1.tgz#8e319c9f0453bf575d374940a655920e59ca5512" - dependencies: - d "1" - es5-ext "^0.10.14" - es6-symbol "^3.1" - -es6-map@^0.1.3: - version "0.1.5" - resolved "https://registry.yarnpkg.com/es6-map/-/es6-map-0.1.5.tgz#9136e0503dcc06a301690f0bb14ff4e364e949f0" - dependencies: - d "1" - es5-ext "~0.10.14" - es6-iterator "~2.0.1" - es6-set "~0.1.5" - es6-symbol "~3.1.1" - event-emitter "~0.3.5" - -es6-set@~0.1.5: - version "0.1.5" - resolved "https://registry.yarnpkg.com/es6-set/-/es6-set-0.1.5.tgz#d2b3ec5d4d800ced818db538d28974db0a73ccb1" - dependencies: - d "1" - es5-ext "~0.10.14" - es6-iterator "~2.0.1" - es6-symbol "3.1.1" - event-emitter "~0.3.5" - -es6-symbol@3.1.1, es6-symbol@^3.1, es6-symbol@^3.1.1, es6-symbol@~3.1, es6-symbol@~3.1.1: - version "3.1.1" - resolved "https://registry.yarnpkg.com/es6-symbol/-/es6-symbol-3.1.1.tgz#bf00ef4fdab6ba1b46ecb7b629b4c7ed5715cc77" - dependencies: - d "1" - es5-ext "~0.10.14" - -es6-weak-map@^2.0.1: - version "2.0.2" - resolved "https://registry.yarnpkg.com/es6-weak-map/-/es6-weak-map-2.0.2.tgz#5e3ab32251ffd1538a1f8e5ffa1357772f92d96f" - dependencies: - d "1" - es5-ext "^0.10.14" - es6-iterator "^2.0.1" - es6-symbol "^3.1.1" - escape-string-regexp@^1.0.2, escape-string-regexp@^1.0.4, escape-string-regexp@^1.0.5: version "1.0.5" resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4" -escope@^3.6.0: - version "3.6.0" - resolved "https://registry.yarnpkg.com/escope/-/escope-3.6.0.tgz#e01975e812781a163a6dadfdd80398dc64c889c3" - dependencies: - es6-map "^0.1.3" - es6-weak-map "^2.0.1" - esrecurse "^4.1.0" - estraverse "^4.1.1" - eslint-config-airbnb-base@^11.1.0: version "11.2.0" resolved "https://registry.yarnpkg.com/eslint-config-airbnb-base/-/eslint-config-airbnb-base-11.2.0.tgz#19a9dc4481a26f70904545ec040116876018f853" -eslint-import-resolver-node@^0.2.0: - version "0.2.3" - resolved "https://registry.yarnpkg.com/eslint-import-resolver-node/-/eslint-import-resolver-node-0.2.3.tgz#5add8106e8c928db2cba232bcd9efa846e3da16c" +eslint-import-resolver-node@^0.3.1: + version "0.3.1" + resolved "https://registry.yarnpkg.com/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.1.tgz#4422574cde66a9a7b099938ee4d508a199e0e3cc" dependencies: - debug "^2.2.0" - object-assign "^4.0.1" - resolve "^1.1.6" + debug "^2.6.8" + resolve "^1.2.0" -eslint-module-utils@^2.0.0: +eslint-module-utils@^2.1.1: version "2.1.1" resolved "https://registry.yarnpkg.com/eslint-module-utils/-/eslint-module-utils-2.1.1.tgz#abaec824177613b8a95b299639e1b6facf473449" dependencies: debug "^2.6.8" pkg-dir "^1.0.0" -eslint-plugin-import@^2.2.0: - version "2.5.0" - resolved "https://registry.yarnpkg.com/eslint-plugin-import/-/eslint-plugin-import-2.5.0.tgz#293b5ea7910a901a05a47ccdd7546e611725406c" +eslint-plugin-import@^2.7.0: + version "2.7.0" + resolved "https://registry.yarnpkg.com/eslint-plugin-import/-/eslint-plugin-import-2.7.0.tgz#21de33380b9efb55f5ef6d2e210ec0e07e7fa69f" dependencies: builtin-modules "^1.1.1" contains-path "^0.1.0" debug "^2.6.8" doctrine "1.5.0" - eslint-import-resolver-node "^0.2.0" - eslint-module-utils "^2.0.0" + eslint-import-resolver-node "^0.3.1" + eslint-module-utils "^2.1.1" has "^1.0.1" lodash.cond "^4.3.0" minimatch "^3.0.3" read-pkg-up "^2.0.0" -eslint@^3.15.0: - version "3.19.0" - resolved "https://registry.yarnpkg.com/eslint/-/eslint-3.19.0.tgz#c8fc6201c7f40dd08941b87c085767386a679acc" +eslint-scope@^3.7.1: + version "3.7.1" + resolved "https://registry.yarnpkg.com/eslint-scope/-/eslint-scope-3.7.1.tgz#3d63c3edfda02e06e01a452ad88caacc7cdcb6e8" dependencies: - babel-code-frame "^6.16.0" + esrecurse "^4.1.0" + estraverse "^4.1.1" + +eslint@^4.2.0: + version "4.2.0" + resolved "https://registry.yarnpkg.com/eslint/-/eslint-4.2.0.tgz#a2b3184111b198e02e9c7f3cca625a5e01c56b3d" + dependencies: + ajv "^5.2.0" + babel-code-frame "^6.22.0" chalk "^1.1.3" - concat-stream "^1.5.2" - debug "^2.1.1" + concat-stream "^1.6.0" + debug "^2.6.8" doctrine "^2.0.0" - escope "^3.6.0" - espree "^3.4.0" + eslint-scope "^3.7.1" + espree "^3.4.3" esquery "^1.0.0" estraverse "^4.2.0" esutils "^2.0.2" file-entry-cache "^2.0.0" - glob "^7.0.3" - globals "^9.14.0" - ignore "^3.2.0" + glob "^7.1.2" + globals "^9.17.0" + ignore "^3.3.3" imurmurhash "^0.1.4" - inquirer "^0.12.0" - is-my-json-valid "^2.10.0" + inquirer "^3.0.6" is-resolvable "^1.0.0" - js-yaml "^3.5.1" - json-stable-stringify "^1.0.0" + js-yaml "^3.8.4" + json-stable-stringify "^1.0.1" levn "^0.3.0" - lodash "^4.0.0" - mkdirp "^0.5.0" + lodash "^4.17.4" + minimatch "^3.0.2" + mkdirp "^0.5.1" natural-compare "^1.4.0" optionator "^0.8.2" - path-is-inside "^1.0.1" - pluralize "^1.2.1" - progress "^1.1.8" - require-uncached "^1.0.2" - shelljs "^0.7.5" - strip-bom "^3.0.0" + path-is-inside "^1.0.2" + pluralize "^4.0.0" + progress "^2.0.0" + require-uncached "^1.0.3" strip-json-comments "~2.0.1" - table "^3.7.8" + table "^4.0.1" text-table "~0.2.0" - user-home "^2.0.0" espower-location-detector@^1.0.0: version "1.0.0" @@ -1628,7 +1602,7 @@ espower-location-detector@^1.0.0: source-map "^0.5.0" xtend "^4.0.0" -espree@^3.4.0: +espree@^3.4.3: version "3.4.3" resolved "https://registry.yarnpkg.com/espree/-/espree-3.4.3.tgz#2910b5ccd49ce893c2ffffaab4fd8b3a31b82374" dependencies: @@ -1670,13 +1644,6 @@ esutils@^2.0.2: version "2.0.2" resolved "https://registry.yarnpkg.com/esutils/-/esutils-2.0.2.tgz#0abf4f1caa5bcb1f7a9d8acc6dea4faaa04bac9b" -event-emitter@~0.3.5: - version "0.3.5" - resolved "https://registry.yarnpkg.com/event-emitter/-/event-emitter-0.3.5.tgz#df8c69eef1647923c7157b9ce83840610b02cc39" - dependencies: - d "1" - es5-ext "~0.10.14" - execa@^0.4.0: version "0.4.0" resolved "https://registry.yarnpkg.com/execa/-/execa-0.4.0.tgz#4eb6467a36a095fabb2970ff9d5e3fb7bce6ebc3" @@ -1700,10 +1667,6 @@ execa@^0.5.0: signal-exit "^3.0.0" strip-eof "^1.0.0" -exit-hook@^1.0.0: - version "1.1.1" - resolved "https://registry.yarnpkg.com/exit-hook/-/exit-hook-1.1.1.tgz#f05ca233b48c05d54fff07765df8507e95c02ff8" - expand-brackets@^0.1.4: version "0.1.5" resolved "https://registry.yarnpkg.com/expand-brackets/-/expand-brackets-0.1.5.tgz#df07284e342a807cd733ac5af72411e581d1177b" @@ -1720,6 +1683,14 @@ extend@~3.0.0: version "3.0.1" resolved "https://registry.yarnpkg.com/extend/-/extend-3.0.1.tgz#a755ea7bc1adfcc5a31ce7e762dbaadc5e636444" +external-editor@^2.0.4: + version "2.0.4" + resolved "https://registry.yarnpkg.com/external-editor/-/external-editor-2.0.4.tgz#1ed9199da9cbfe2ef2f7a31b2fde8b0d12368972" + dependencies: + iconv-lite "^0.4.17" + jschardet "^1.4.2" + tmp "^0.0.31" + extglob@^0.3.1: version "0.3.2" resolved "https://registry.yarnpkg.com/extglob/-/extglob-0.3.2.tgz#2e18ff3d2f49ab2765cec9023f011daa8d8349a1" @@ -1730,17 +1701,18 @@ extsprintf@1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/extsprintf/-/extsprintf-1.0.2.tgz#e1080e0658e300b06294990cc70e1502235fd550" +fast-deep-equal@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-1.0.0.tgz#96256a3bc975595eb36d82e9929d060d893439ff" + +fast-diff@^1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/fast-diff/-/fast-diff-1.1.1.tgz#0aea0e4e605b6a2189f0e936d4b7fbaf1b7cfd9b" + fast-levenshtein@~2.0.4: version "2.0.6" resolved "https://registry.yarnpkg.com/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz#3d8a5c66883a16a30ca8643e851f19baa7797917" -figures@^1.3.5: - version "1.7.0" - resolved "https://registry.yarnpkg.com/figures/-/figures-1.7.0.tgz#cbe1e3affcf1cd44b80cadfed28dc793a9701d2e" - dependencies: - escape-string-regexp "^1.0.5" - object-assign "^4.1.0" - figures@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/figures/-/figures-2.0.0.tgz#3ab1a2d2a62c8bfb431a0c94cb797a2fce27c962" @@ -1776,7 +1748,15 @@ find-cache-dir@^0.1.1: mkdirp "^0.5.1" pkg-dir "^1.0.0" -find-up@^1.0.0, find-up@^1.1.2: +find-cache-dir@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/find-cache-dir/-/find-cache-dir-1.0.0.tgz#9288e3e9e3cc3748717d39eade17cf71fc30ee6f" + dependencies: + commondir "^1.0.1" + make-dir "^1.0.0" + pkg-dir "^2.0.0" + +find-up@^1.0.0: version "1.1.2" resolved "https://registry.yarnpkg.com/find-up/-/find-up-1.1.2.tgz#6b2e9822b1a2ce0a60ab64d610eccad53cb24d0f" dependencies: @@ -1812,7 +1792,7 @@ for-own@^0.1.4: dependencies: for-in "^1.0.1" -foreground-child@^1.3.3, foreground-child@^1.5.3: +foreground-child@^1.5.3, foreground-child@^1.5.6: version "1.5.6" resolved "https://registry.yarnpkg.com/foreground-child/-/foreground-child-1.5.6.tgz#4fd71ad2dfde96789b980a5c0a295937cb2f5ce9" dependencies: @@ -1831,11 +1811,11 @@ form-data@~2.1.1: combined-stream "^1.0.5" mime-types "^2.1.12" -formatio@1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/formatio/-/formatio-1.1.1.tgz#5ed3ccd636551097383465d996199100e86161e9" +formatio@1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/formatio/-/formatio-1.2.0.tgz#f3b2167d9068c4698a8d51f4f760a39a54d818eb" dependencies: - samsam "~1.1" + samsam "1.x" fs.realpath@^1.0.0: version "1.0.0" @@ -1869,6 +1849,10 @@ function-bind@^1.0.2: version "1.1.0" resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.0.tgz#16176714c801798e4e8f2cf7f7529467bb4a5771" +function-name-support@^0.2.0: + version "0.2.0" + resolved "https://registry.yarnpkg.com/function-name-support/-/function-name-support-0.2.0.tgz#55d3bfaa6eafd505a50f9bc81fdf57564a0bb071" + gauge@~2.7.3: version "2.7.4" resolved "https://registry.yarnpkg.com/gauge/-/gauge-2.7.4.tgz#2c03405c7538c39d7eb37b317022e325fb018bf7" @@ -1882,16 +1866,6 @@ gauge@~2.7.3: strip-ansi "^3.0.1" wide-align "^1.1.0" -generate-function@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/generate-function/-/generate-function-2.0.0.tgz#6858fe7c0969b7d4e9093337647ac79f60dfbe74" - -generate-object-property@^1.1.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/generate-object-property/-/generate-object-property-1.2.0.tgz#9c0e1c40308ce804f4783618b937fa88f99d50d0" - dependencies: - is-property "^1.0.0" - get-caller-file@^1.0.1: version "1.0.2" resolved "https://registry.yarnpkg.com/get-caller-file/-/get-caller-file-1.0.2.tgz#f702e63127e7e231c160a80c1554acb70d5047e5" @@ -1934,7 +1908,7 @@ glob-parent@^2.0.0: dependencies: is-glob "^2.0.0" -glob@^7.0.0, glob@^7.0.3, glob@^7.0.5, glob@^7.0.6: +glob@^7.0.3, glob@^7.0.5, glob@^7.0.6, glob@^7.1.2: version "7.1.2" resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.2.tgz#c19c9df9a028702d678612384a6552404c636d15" dependencies: @@ -1945,7 +1919,7 @@ glob@^7.0.0, glob@^7.0.3, glob@^7.0.5, glob@^7.0.6: once "^1.3.0" path-is-absolute "^1.0.0" -globals@^9.0.0, globals@^9.14.0: +globals@^9.0.0, globals@^9.17.0: version "9.18.0" resolved "https://registry.yarnpkg.com/globals/-/globals-9.18.0.tgz#aa3896b3e69b487f17e31ed2143d69a8e30c2d8a" @@ -1986,7 +1960,7 @@ got@^6.7.1: unzip-response "^2.0.1" url-parse-lax "^1.0.0" -graceful-fs@^4.1.11, graceful-fs@^4.1.2, graceful-fs@^4.1.6: +graceful-fs@^4.1.11, graceful-fs@^4.1.2: version "4.1.11" resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.1.11.tgz#0e8bdfe4d1ddb8854d64e04ea7c00e2a026e5658" @@ -2075,7 +2049,7 @@ http-signature@~1.1.0: jsprim "^1.2.2" sshpk "^1.7.0" -hullabaloo-config-manager@^1.0.0: +hullabaloo-config-manager@^1.1.0: version "1.1.1" resolved "https://registry.yarnpkg.com/hullabaloo-config-manager/-/hullabaloo-config-manager-1.1.1.tgz#1d9117813129ad035fd9e8477eaf066911269fe3" dependencies: @@ -2094,11 +2068,15 @@ hullabaloo-config-manager@^1.0.0: resolve-from "^3.0.0" safe-buffer "^5.0.1" +iconv-lite@^0.4.17: + version "0.4.18" + resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.18.tgz#23d8656b16aae6742ac29732ea8f0336a4789cf2" + ignore-by-default@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/ignore-by-default/-/ignore-by-default-1.0.1.tgz#48ca6d72f6c6a3af00a9ad4ae6876be3889e2b09" -ignore@^3.2.0: +ignore@^3.3.3: version "3.3.3" resolved "https://registry.yarnpkg.com/ignore/-/ignore-3.3.3.tgz#432352e57accd87ab3110e82d3fea0e47812156d" @@ -2106,6 +2084,13 @@ import-lazy@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/import-lazy/-/import-lazy-2.1.0.tgz#05698e3d45c88e8d7e9d92cb0584e77f096f3e43" +import-local@^0.1.1: + version "0.1.1" + resolved "https://registry.yarnpkg.com/import-local/-/import-local-0.1.1.tgz#b1179572aacdc11c6a91009fb430dbcab5f668a8" + dependencies: + pkg-dir "^2.0.0" + resolve-cwd "^2.0.0" + imurmurhash@^0.1.4: version "0.1.4" resolved "https://registry.yarnpkg.com/imurmurhash/-/imurmurhash-0.1.4.tgz#9218b9b2b928a238b13dc4fb6b6d576f231453ea" @@ -2131,36 +2116,29 @@ inherits@2, inherits@^2.0.1, inherits@^2.0.3, inherits@~2.0.0, inherits@~2.0.3: version "2.0.3" resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.3.tgz#633c2c83e3da42a502f52466022480f4208261de" -inherits@2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.1.tgz#b17d08d326b4423e568eff719f91b0b1cbdf69f1" - ini@~1.3.0: version "1.3.4" resolved "https://registry.yarnpkg.com/ini/-/ini-1.3.4.tgz#0537cb79daf59b59a1a517dff706c86ec039162e" -inquirer@^0.12.0: - version "0.12.0" - resolved "https://registry.yarnpkg.com/inquirer/-/inquirer-0.12.0.tgz#1ef2bfd63504df0bc75785fff8c2c41df12f077e" +inquirer@^3.0.6: + version "3.2.0" + resolved "https://registry.yarnpkg.com/inquirer/-/inquirer-3.2.0.tgz#45b44c2160c729d7578c54060b3eed94487bb42b" dependencies: - ansi-escapes "^1.1.0" - ansi-regex "^2.0.0" - chalk "^1.0.0" - cli-cursor "^1.0.1" + ansi-escapes "^2.0.0" + chalk "^2.0.0" + cli-cursor "^2.1.0" cli-width "^2.0.0" - figures "^1.3.5" + external-editor "^2.0.4" + figures "^2.0.0" lodash "^4.3.0" - readline2 "^1.0.1" - run-async "^0.1.0" - rx-lite "^3.1.2" - string-width "^1.0.1" - strip-ansi "^3.0.0" + mute-stream "0.0.7" + run-async "^2.2.0" + rx-lite "^4.0.8" + rx-lite-aggregates "^4.0.8" + string-width "^2.1.0" + strip-ansi "^4.0.0" through "^2.3.6" -interpret@^1.0.0: - version "1.0.3" - resolved "https://registry.yarnpkg.com/interpret/-/interpret-1.0.3.tgz#cbc35c62eeee73f19ab7b10a801511401afc0f90" - invariant@^2.2.0, invariant@^2.2.2: version "2.2.2" resolved "https://registry.yarnpkg.com/invariant/-/invariant-2.2.2.tgz#9e1f56ac0acdb6bf303306f338be3b204ae60360" @@ -2249,14 +2227,9 @@ is-glob@^2.0.0, is-glob@^2.0.1: dependencies: is-extglob "^1.0.0" -is-my-json-valid@^2.10.0: - version "2.16.0" - resolved "https://registry.yarnpkg.com/is-my-json-valid/-/is-my-json-valid-2.16.0.tgz#f079dd9bfdae65ee2038aae8acbc86ab109e3693" - dependencies: - generate-function "^2.0.0" - generate-object-property "^1.1.0" - jsonpointer "^4.0.0" - xtend "^4.0.0" +is-module@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/is-module/-/is-module-1.0.0.tgz#3258fb69f78c14d5b815d664336b4cffb6441591" is-npm@^1.0.0: version "1.0.0" @@ -2316,10 +2289,6 @@ is-promise@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/is-promise/-/is-promise-2.1.0.tgz#79a2a9ece7f096e80f36d2b2f3bc16c1ff4bf3fa" -is-property@^1.0.0: - version "1.0.2" - resolved "https://registry.yarnpkg.com/is-property/-/is-property-1.0.2.tgz#57fe1c4e48474edd65b09911f26b1cd4095dda84" - is-redirect@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/is-redirect/-/is-redirect-1.0.0.tgz#1d03dded53bd8db0f30c26e4f95d36fc7c87dc24" @@ -2350,6 +2319,10 @@ is-utf8@^0.2.0, is-utf8@^0.2.1: version "0.2.1" resolved "https://registry.yarnpkg.com/is-utf8/-/is-utf8-0.2.1.tgz#4b0da1442104d1b336340e80797e865cf39f7d72" +isarray@0.0.1: + version "0.0.1" + resolved "https://registry.yarnpkg.com/isarray/-/isarray-0.0.1.tgz#8a18acfca9a8f4177e09abfc6038939b05d1eedf" + isarray@1.0.0, isarray@^1.0.0, isarray@~1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/isarray/-/isarray-1.0.0.tgz#bb935d48582cba168c06834957a54a3e07124f11" @@ -2368,29 +2341,29 @@ isstream@~0.1.2: version "0.1.2" resolved "https://registry.yarnpkg.com/isstream/-/isstream-0.1.2.tgz#47e63f7af55afa6f92e1500e690eb8b8529c099a" -istanbul-lib-coverage@^1.1.0, istanbul-lib-coverage@^1.1.1: +istanbul-lib-coverage@^1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/istanbul-lib-coverage/-/istanbul-lib-coverage-1.1.1.tgz#73bfb998885299415c93d38a3e9adf784a77a9da" -istanbul-lib-hook@^1.0.6: +istanbul-lib-hook@^1.0.7: version "1.0.7" resolved "https://registry.yarnpkg.com/istanbul-lib-hook/-/istanbul-lib-hook-1.0.7.tgz#dd6607f03076578fe7d6f2a630cf143b49bacddc" dependencies: append-transform "^0.4.0" -istanbul-lib-instrument@^1.7.1: - version "1.7.2" - resolved "https://registry.yarnpkg.com/istanbul-lib-instrument/-/istanbul-lib-instrument-1.7.2.tgz#6014b03d3470fb77638d5802508c255c06312e56" +istanbul-lib-instrument@^1.7.3: + version "1.7.4" + resolved "https://registry.yarnpkg.com/istanbul-lib-instrument/-/istanbul-lib-instrument-1.7.4.tgz#e9fd920e4767f3d19edc765e2d6b3f5ccbd0eea8" dependencies: babel-generator "^6.18.0" babel-template "^6.16.0" babel-traverse "^6.18.0" babel-types "^6.18.0" - babylon "^6.13.0" + babylon "^6.17.4" istanbul-lib-coverage "^1.1.1" semver "^5.3.0" -istanbul-lib-report@^1.1.0: +istanbul-lib-report@^1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/istanbul-lib-report/-/istanbul-lib-report-1.1.1.tgz#f0e55f56655ffa34222080b7a0cd4760e1405fc9" dependencies: @@ -2399,7 +2372,7 @@ istanbul-lib-report@^1.1.0: path-parse "^1.0.5" supports-color "^3.1.2" -istanbul-lib-source-maps@^1.2.0: +istanbul-lib-source-maps@^1.2.1: version "1.2.1" resolved "https://registry.yarnpkg.com/istanbul-lib-source-maps/-/istanbul-lib-source-maps-1.2.1.tgz#a6fe1acba8ce08eebc638e572e294d267008aa0c" dependencies: @@ -2409,82 +2382,21 @@ istanbul-lib-source-maps@^1.2.0: rimraf "^2.6.1" source-map "^0.5.3" -istanbul-reports@^1.1.0: +istanbul-reports@^1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/istanbul-reports/-/istanbul-reports-1.1.1.tgz#042be5c89e175bc3f86523caab29c014e77fee4e" dependencies: handlebars "^4.0.3" -jest-diff@19.0.0, jest-diff@^19.0.0: - version "19.0.0" - resolved "https://registry.yarnpkg.com/jest-diff/-/jest-diff-19.0.0.tgz#d1563cfc56c8b60232988fbc05d4d16ed90f063c" - dependencies: - chalk "^1.1.3" - diff "^3.0.0" - jest-matcher-utils "^19.0.0" - pretty-format "^19.0.0" - -jest-file-exists@^19.0.0: - version "19.0.0" - resolved "https://registry.yarnpkg.com/jest-file-exists/-/jest-file-exists-19.0.0.tgz#cca2e587a11ec92e24cfeab3f8a94d657f3fceb8" - -jest-matcher-utils@^19.0.0: - version "19.0.0" - resolved "https://registry.yarnpkg.com/jest-matcher-utils/-/jest-matcher-utils-19.0.0.tgz#5ecd9b63565d2b001f61fbf7ec4c7f537964564d" - dependencies: - chalk "^1.1.3" - pretty-format "^19.0.0" - -jest-message-util@^19.0.0: - version "19.0.0" - resolved "https://registry.yarnpkg.com/jest-message-util/-/jest-message-util-19.0.0.tgz#721796b89c0e4d761606f9ba8cb828a3b6246416" - dependencies: - chalk "^1.1.1" - micromatch "^2.3.11" - -jest-mock@^19.0.0: - version "19.0.0" - resolved "https://registry.yarnpkg.com/jest-mock/-/jest-mock-19.0.0.tgz#67038641e9607ab2ce08ec4a8cb83aabbc899d01" - -jest-snapshot@19.0.2: - version "19.0.2" - resolved "https://registry.yarnpkg.com/jest-snapshot/-/jest-snapshot-19.0.2.tgz#9c1b216214f7187c38bfd5c70b1efab16b0ff50b" - dependencies: - chalk "^1.1.3" - jest-diff "^19.0.0" - jest-file-exists "^19.0.0" - jest-matcher-utils "^19.0.0" - jest-util "^19.0.2" - natural-compare "^1.4.0" - pretty-format "^19.0.0" - -jest-util@^19.0.2: - version "19.0.2" - resolved "https://registry.yarnpkg.com/jest-util/-/jest-util-19.0.2.tgz#e0a0232a2ab9e6b2b53668bdb3534c2b5977ed41" - dependencies: - chalk "^1.1.1" - graceful-fs "^4.1.6" - jest-file-exists "^19.0.0" - jest-message-util "^19.0.0" - jest-mock "^19.0.0" - jest-validate "^19.0.2" - leven "^2.0.0" - mkdirp "^0.5.1" - -jest-validate@^19.0.2: - version "19.0.2" - resolved "https://registry.yarnpkg.com/jest-validate/-/jest-validate-19.0.2.tgz#dc534df5f1278d5b63df32b14241d4dbf7244c0c" - dependencies: - chalk "^1.1.1" - jest-matcher-utils "^19.0.0" - leven "^2.0.0" - pretty-format "^19.0.0" +js-string-escape@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/js-string-escape/-/js-string-escape-1.0.1.tgz#e2625badbc0d67c7533e9edc1068c587ae4137ef" js-tokens@^3.0.0: version "3.0.1" resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-3.0.1.tgz#08e9f132484a2c45a30907e9dc4d5567b7f114d7" -js-yaml@^3.5.1, js-yaml@^3.8.2: +js-yaml@^3.8.2, js-yaml@^3.8.4: version "3.8.4" resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.8.4.tgz#520b4564f86573ba96662af85a8cafa7b4b5a6f6" dependencies: @@ -2495,23 +2407,27 @@ jsbn@~0.1.0: version "0.1.1" resolved "https://registry.yarnpkg.com/jsbn/-/jsbn-0.1.1.tgz#a5e654c2e5a2deb5f201d96cefbca80c0ef2f513" +jschardet@^1.4.2: + version "1.5.0" + resolved "https://registry.yarnpkg.com/jschardet/-/jschardet-1.5.0.tgz#a61f310306a5a71188e1b1acd08add3cfbb08b1e" + jsesc@^1.3.0: version "1.3.0" resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-1.3.0.tgz#46c3fec8c1892b12b0833db9bc7622176dbab34b" -jsesc@^2.4.0: - version "2.5.1" - resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-2.5.1.tgz#e421a2a8e20d6b0819df28908f782526b96dd1fe" - jsesc@~0.5.0: version "0.5.0" resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-0.5.0.tgz#e7dee66e35d6fc16f710fe91d5cf69f70f08911d" +json-schema-traverse@^0.3.0: + version "0.3.1" + resolved "https://registry.yarnpkg.com/json-schema-traverse/-/json-schema-traverse-0.3.1.tgz#349a6d44c53a51de89b40805c5d5e59b417d3340" + json-schema@0.2.3: version "0.2.3" resolved "https://registry.yarnpkg.com/json-schema/-/json-schema-0.2.3.tgz#b480c892e59a2f05954ce727bd3f2a4e882f9e13" -json-stable-stringify@^1.0.0, json-stable-stringify@^1.0.1: +json-stable-stringify@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/json-stable-stringify/-/json-stable-stringify-1.0.1.tgz#9a759d39c5f2ff503fd5300646ed445f88c4f9af" dependencies: @@ -2529,10 +2445,6 @@ jsonify@~0.0.0: version "0.0.0" resolved "https://registry.yarnpkg.com/jsonify/-/jsonify-0.0.0.tgz#2c74b6ee41d93ca51b7b5aaee8f503631d252a73" -jsonpointer@^4.0.0: - version "4.0.1" - resolved "https://registry.yarnpkg.com/jsonpointer/-/jsonpointer-4.0.1.tgz#4fd92cb34e0e9db3c89c8622ecf51f9b978c6cb9" - jsprim@^1.2.2: version "1.4.0" resolved "https://registry.yarnpkg.com/jsprim/-/jsprim-1.4.0.tgz#a3b87e40298d8c380552d8cc7628a0bb95a22918" @@ -2576,10 +2488,6 @@ lcid@^1.0.0: dependencies: invert-kv "^1.0.0" -leven@^2.0.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/leven/-/leven-2.1.0.tgz#c2e7a9f772094dee9d34202ae8acce4687875580" - levn@^0.3.0, levn@~0.3.0: version "0.3.0" resolved "https://registry.yarnpkg.com/levn/-/levn-0.3.0.tgz#3b09924edf9f083c0490fdd4c0bc4421e04764ee" @@ -2657,13 +2565,13 @@ lodash.some@^4.6.0: version "4.6.0" resolved "https://registry.yarnpkg.com/lodash.some/-/lodash.some-4.6.0.tgz#1bb9f314ef6b8baded13b549169b2a945eb68e4d" -lodash@^4.0.0, lodash@^4.2.0, lodash@^4.3.0: +lodash@^4.0.0, lodash@^4.17.4, lodash@^4.2.0, lodash@^4.3.0: version "4.17.4" resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.4.tgz#78203a4d1c328ae1d86dca6460e369b57f4055ae" -lolex@1.3.2: - version "1.3.2" - resolved "https://registry.yarnpkg.com/lolex/-/lolex-1.3.2.tgz#7c3da62ffcb30f0f5a80a2566ca24e45d8a01f31" +lolex@^1.6.0: + version "1.6.0" + resolved "https://registry.yarnpkg.com/lolex/-/lolex-1.6.0.tgz#3a9a0283452a47d7439e72731b9e07d7386e49f6" longest@^1.0.1: version "1.0.1" @@ -2703,9 +2611,9 @@ map-obj@^1.0.0, map-obj@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/map-obj/-/map-obj-1.0.1.tgz#d933ceb9205d82bdcf4886f6742bdc2b4dea146d" -matcher@^0.1.1: - version "0.1.2" - resolved "https://registry.yarnpkg.com/matcher/-/matcher-0.1.2.tgz#ef20cbde64c24c50cc61af5b83ee0b1b8ff00101" +matcher@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/matcher/-/matcher-1.0.0.tgz#aaf0c4816eb69b92094674175625f3466b0e3e19" dependencies: escape-string-regexp "^1.0.4" @@ -2725,6 +2633,12 @@ md5-o-matic@^0.1.1: version "0.1.1" resolved "https://registry.yarnpkg.com/md5-o-matic/-/md5-o-matic-0.1.1.tgz#822bccd65e117c514fab176b25945d54100a03c3" +mem@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/mem/-/mem-1.1.0.tgz#5edd52b485ca1d900fe64895505399a0dfa45f76" + dependencies: + mimic-fn "^1.0.0" + meow@^3.7.0: version "3.7.0" resolved "https://registry.yarnpkg.com/meow/-/meow-3.7.0.tgz#72cb668b425228290abbfa856892587308a801fb" @@ -2798,14 +2712,10 @@ minimist@^1.1.3, minimist@^1.2.0: dependencies: minimist "0.0.8" -ms@2.0.0: +ms@2.0.0, ms@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/ms/-/ms-2.0.0.tgz#5608aeadfc00be6c2901df5f9861788de0d597c8" -ms@^0.7.1: - version "0.7.3" - resolved "https://registry.yarnpkg.com/ms/-/ms-0.7.3.tgz#708155a5e44e33f5fd0fc53e81d0d40a91be1fff" - multimatch@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/multimatch/-/multimatch-2.1.0.tgz#9c7906a22fb4c02919e2f5f75161b4cdbd4b2a2b" @@ -2815,14 +2725,18 @@ multimatch@^2.1.0: arrify "^1.0.0" minimatch "^3.0.0" -mute-stream@0.0.5: - version "0.0.5" - resolved "https://registry.yarnpkg.com/mute-stream/-/mute-stream-0.0.5.tgz#8fbfabb0a98a253d3184331f9e8deb7372fac6c0" +mute-stream@0.0.7: + version "0.0.7" + resolved "https://registry.yarnpkg.com/mute-stream/-/mute-stream-0.0.7.tgz#3075ce93bc21b8fab43e1bc4da7e8115ed1e7bab" nan@^2.3.0: version "2.6.2" resolved "https://registry.yarnpkg.com/nan/-/nan-2.6.2.tgz#e4ff34e6c95fdfb5aecc08de6596f43605a7db45" +native-promise-only@^0.8.1: + version "0.8.1" + resolved "https://registry.yarnpkg.com/native-promise-only/-/native-promise-only-0.8.1.tgz#20a318c30cb45f71fe7adfbf7b21c99c1472ef11" + natural-compare@^1.4.0: version "1.4.0" resolved "https://registry.yarnpkg.com/natural-compare/-/natural-compare-1.4.0.tgz#4abebfeed7541f2c27acfb29bdbbd15c8d5ba4f7" @@ -2888,9 +2802,9 @@ number-is-nan@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/number-is-nan/-/number-is-nan-1.0.1.tgz#097b602b53422a522c1afb8790318336941a011d" -nyc@^10.3.2: - version "10.3.2" - resolved "https://registry.yarnpkg.com/nyc/-/nyc-10.3.2.tgz#f27f4d91f2a9db36c24f574ff5c6efff0233de46" +nyc@^11.0.3: + version "11.0.3" + resolved "https://registry.yarnpkg.com/nyc/-/nyc-11.0.3.tgz#0c28bc669a851621709bf7a08503034bee3812b6" dependencies: archy "^1.0.0" arrify "^1.0.1" @@ -2899,15 +2813,15 @@ nyc@^10.3.2: debug-log "^1.0.1" default-require-extensions "^1.0.0" find-cache-dir "^0.1.1" - find-up "^1.1.2" + find-up "^2.1.0" foreground-child "^1.5.3" glob "^7.0.6" - istanbul-lib-coverage "^1.1.0" - istanbul-lib-hook "^1.0.6" - istanbul-lib-instrument "^1.7.1" - istanbul-lib-report "^1.1.0" - istanbul-lib-source-maps "^1.2.0" - istanbul-reports "^1.1.0" + istanbul-lib-coverage "^1.1.1" + istanbul-lib-hook "^1.0.7" + istanbul-lib-instrument "^1.7.3" + istanbul-lib-report "^1.1.1" + istanbul-lib-source-maps "^1.2.1" + istanbul-reports "^1.1.1" md5-hex "^1.2.0" merge-source-map "^1.0.2" micromatch "^2.3.11" @@ -2915,9 +2829,9 @@ nyc@^10.3.2: resolve-from "^2.0.0" rimraf "^2.5.4" signal-exit "^3.0.1" - spawn-wrap "1.2.4" - test-exclude "^4.1.0" - yargs "^7.1.0" + spawn-wrap "^1.3.7" + test-exclude "^4.1.1" + yargs "^8.0.1" yargs-parser "^5.0.0" oauth-sign@~0.8.1: @@ -2948,10 +2862,6 @@ once@^1.3.0, once@^1.3.3: dependencies: wrappy "1" -onetime@^1.0.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/onetime/-/onetime-1.1.0.tgz#a1f7838f8314c516f05ecefcbc4ccfe04b4ed789" - onetime@^2.0.0: version "2.0.1" resolved "https://registry.yarnpkg.com/onetime/-/onetime-2.0.1.tgz#067428230fd67443b2794b22bba528b6867962d4" @@ -2965,11 +2875,9 @@ optimist@^0.6.1: minimist "~0.0.1" wordwrap "~0.0.2" -option-chain@^0.1.0: - version "0.1.1" - resolved "https://registry.yarnpkg.com/option-chain/-/option-chain-0.1.1.tgz#e9b811e006f1c0f54802f28295bfc8970f8dcfbd" - dependencies: - object-assign "^4.0.1" +option-chain@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/option-chain/-/option-chain-1.0.0.tgz#938d73bd4e1783f948d34023644ada23669e30f2" optionator@^0.8.2: version "0.8.2" @@ -2986,13 +2894,15 @@ os-homedir@^1.0.0, os-homedir@^1.0.1: version "1.0.2" resolved "https://registry.yarnpkg.com/os-homedir/-/os-homedir-1.0.2.tgz#ffbc4988336e0e833de0c168c7ef152121aa7fb3" -os-locale@^1.4.0: - version "1.4.0" - resolved "https://registry.yarnpkg.com/os-locale/-/os-locale-1.4.0.tgz#20f9f17ae29ed345e8bde583b13d2009803c14d9" +os-locale@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/os-locale/-/os-locale-2.0.0.tgz#15918ded510522b81ee7ae5a309d54f639fc39a4" dependencies: + execa "^0.5.0" lcid "^1.0.0" + mem "^1.1.0" -os-tmpdir@^1.0.0, os-tmpdir@^1.0.1: +os-tmpdir@^1.0.0, os-tmpdir@^1.0.1, os-tmpdir@~1.0.1: version "1.0.2" resolved "https://registry.yarnpkg.com/os-tmpdir/-/os-tmpdir-1.0.2.tgz#bbe67406c79aa85c5cfec766fe5734555dfa1274" @@ -3078,7 +2988,7 @@ path-is-absolute@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f" -path-is-inside@^1.0.1: +path-is-inside@^1.0.1, path-is-inside@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/path-is-inside/-/path-is-inside-1.0.2.tgz#365417dede44430d1c11af61027facf074bdfc53" @@ -3094,6 +3004,12 @@ path-parse@^1.0.5: version "1.0.5" resolved "https://registry.yarnpkg.com/path-parse/-/path-parse-1.0.5.tgz#3c1adf871ea9cd6c9431b6ea2bd74a0ff055c4c1" +path-to-regexp@^1.7.0: + version "1.7.0" + resolved "https://registry.yarnpkg.com/path-to-regexp/-/path-to-regexp-1.7.0.tgz#59fde0f435badacba103a84e9d3bc64e96b9937d" + dependencies: + isarray "0.0.1" + path-type@^1.0.0: version "1.1.0" resolved "https://registry.yarnpkg.com/path-type/-/path-type-1.1.0.tgz#59c44f7ee491da704da415da5a4070ba4f8fe441" @@ -3165,9 +3081,9 @@ plur@^2.0.0: dependencies: irregular-plurals "^1.0.0" -pluralize@^1.2.1: - version "1.2.1" - resolved "https://registry.yarnpkg.com/pluralize/-/pluralize-1.2.1.tgz#d1a21483fd22bb41e58a12fa3421823140897c45" +pluralize@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/pluralize/-/pluralize-4.0.0.tgz#59b708c1c0190a2f692f1c7618c446b052fd1762" prelude-ls@~1.1.2: version "1.1.2" @@ -3181,12 +3097,6 @@ preserve@^0.2.0: version "0.2.0" resolved "https://registry.yarnpkg.com/preserve/-/preserve-0.2.0.tgz#815ed1f6ebc65926f865b310c0713bcb3315ce4b" -pretty-format@^19.0.0: - version "19.0.0" - resolved "https://registry.yarnpkg.com/pretty-format/-/pretty-format-19.0.0.tgz#56530d32acb98a3fa4851c4e2b9d37b420684c84" - dependencies: - ansi-styles "^3.0.0" - pretty-ms@^0.2.1: version "0.2.2" resolved "https://registry.yarnpkg.com/pretty-ms/-/pretty-ms-0.2.2.tgz#da879a682ff33a37011046f13d627f67c73b84f6" @@ -3209,9 +3119,9 @@ process-nextick-args@~1.0.6: version "1.0.7" resolved "https://registry.yarnpkg.com/process-nextick-args/-/process-nextick-args-1.0.7.tgz#150e20b756590ad3f91093f25a4f2ad8bff30ba3" -progress@^1.1.8: - version "1.1.8" - resolved "https://registry.yarnpkg.com/progress/-/progress-1.1.8.tgz#e260c78f6161cdd9b0e56cc3e0a85de17c7a57be" +progress@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/progress/-/progress-2.0.0.tgz#8a1be366bf8fc23db2bd23f10c6fe920b4389d1f" pseudomap@^1.0.2: version "1.0.2" @@ -3292,20 +3202,6 @@ readdirp@^2.0.0: readable-stream "^2.0.2" set-immediate-shim "^1.0.1" -readline2@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/readline2/-/readline2-1.0.1.tgz#41059608ffc154757b715d9989d199ffbf372e35" - dependencies: - code-point-at "^1.0.0" - is-fullwidth-code-point "^1.0.0" - mute-stream "0.0.5" - -rechoir@^0.6.2: - version "0.6.2" - resolved "https://registry.yarnpkg.com/rechoir/-/rechoir-0.6.2.tgz#85204b54dba82d5742e28c96756ef43af50e3384" - dependencies: - resolve "^1.1.6" - redent@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/redent/-/redent-1.0.0.tgz#cf916ab1fd5f1f16dfb20822dd6ec7f730c2afde" @@ -3430,18 +3326,18 @@ require-precompiled@^0.1.0: version "0.1.0" resolved "https://registry.yarnpkg.com/require-precompiled/-/require-precompiled-0.1.0.tgz#5a1b52eb70ebed43eb982e974c85ab59571e56fa" -require-uncached@^1.0.2: +require-uncached@^1.0.3: version "1.0.3" resolved "https://registry.yarnpkg.com/require-uncached/-/require-uncached-1.0.3.tgz#4e0d56d6c9662fd31e43011c4b95aa49955421d3" dependencies: caller-path "^0.1.0" resolve-from "^1.0.0" -resolve-cwd@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/resolve-cwd/-/resolve-cwd-1.0.0.tgz#4eaeea41ed040d1702457df64a42b2b07d246f9f" +resolve-cwd@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/resolve-cwd/-/resolve-cwd-2.0.0.tgz#00a9f7387556e27038eae232caa372a6a59b665a" dependencies: - resolve-from "^2.0.0" + resolve-from "^3.0.0" resolve-from@^1.0.0: version "1.0.1" @@ -3459,19 +3355,12 @@ resolve@1.1.7: version "1.1.7" resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.1.7.tgz#203114d82ad2c5ed9e8e0411b3932875e889e97b" -resolve@^1.1.6: +resolve@^1.1.6, resolve@^1.2.0: version "1.3.3" resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.3.3.tgz#655907c3469a8680dc2de3a275a8fdd69691f0e5" dependencies: path-parse "^1.0.5" -restore-cursor@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/restore-cursor/-/restore-cursor-1.0.1.tgz#34661f46886327fed2991479152252df92daa541" - dependencies: - exit-hook "^1.0.0" - onetime "^1.0.0" - restore-cursor@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/restore-cursor/-/restore-cursor-2.0.0.tgz#9f7ee287f82fd326d4fd162923d62129eee0dfaf" @@ -3500,20 +3389,21 @@ rollup-plugin-babel@^2.7.1: object-assign "^4.1.0" rollup-pluginutils "^1.5.0" -rollup-plugin-babili@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/rollup-plugin-babili/-/rollup-plugin-babili-2.0.0.tgz#3695cb851c661af5f2834836c22ca0822ff9647b" +rollup-plugin-babili@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/rollup-plugin-babili/-/rollup-plugin-babili-3.1.0.tgz#27ada043a0ed021050a712528f68ed641888b5dc" dependencies: "@comandeer/babel-plugin-banner" "^1.0.0" babel-core "^6.21.0" - babel-preset-babili "^0.0.12" + babel-preset-babili "^0.1.2" -rollup-plugin-node-resolve@^2.0.0: - version "2.1.1" - resolved "https://registry.yarnpkg.com/rollup-plugin-node-resolve/-/rollup-plugin-node-resolve-2.1.1.tgz#cbb783b0d15b02794d58915350b2f0d902b8ddc8" +rollup-plugin-node-resolve@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/rollup-plugin-node-resolve/-/rollup-plugin-node-resolve-3.0.0.tgz#8b897c4c3030d5001277b0514b25d2ca09683ee0" dependencies: browser-resolve "^1.11.0" builtin-modules "^1.1.0" + is-module "^1.0.0" resolve "^1.1.6" rollup-pluginutils@^1.5.0: @@ -3523,29 +3413,35 @@ rollup-pluginutils@^1.5.0: estree-walker "^0.2.1" minimatch "^3.0.2" -rollup@^0.41.6: - version "0.41.6" - resolved "https://registry.yarnpkg.com/rollup/-/rollup-0.41.6.tgz#e0d05497877a398c104d816d2733a718a7a94e2a" +rollup@^0.45.2: + version "0.45.2" + resolved "https://registry.yarnpkg.com/rollup/-/rollup-0.45.2.tgz#63a284c2b31234656f24e9e9717fabb6a7f0fa43" dependencies: source-map-support "^0.4.0" -run-async@^0.1.0: - version "0.1.0" - resolved "https://registry.yarnpkg.com/run-async/-/run-async-0.1.0.tgz#c8ad4a5e110661e402a7d21b530e009f25f8e389" +run-async@^2.2.0: + version "2.3.0" + resolved "https://registry.yarnpkg.com/run-async/-/run-async-2.3.0.tgz#0371ab4ae0bdd720d4166d7dfda64ff7a445a6c0" dependencies: - once "^1.3.0" + is-promise "^2.1.0" + +rx-lite-aggregates@^4.0.8: + version "4.0.8" + resolved "https://registry.yarnpkg.com/rx-lite-aggregates/-/rx-lite-aggregates-4.0.8.tgz#753b87a89a11c95467c4ac1626c4efc4e05c67be" + dependencies: + rx-lite "*" -rx-lite@^3.1.2: - version "3.1.2" - resolved "https://registry.yarnpkg.com/rx-lite/-/rx-lite-3.1.2.tgz#19ce502ca572665f3b647b10939f97fd1615f102" +rx-lite@*, rx-lite@^4.0.8: + version "4.0.8" + resolved "https://registry.yarnpkg.com/rx-lite/-/rx-lite-4.0.8.tgz#0b1e11af8bc44836f04a6407e92da42467b79444" -safe-buffer@^5.0.1, safe-buffer@~5.1.0: +safe-buffer@^5.0.1, safe-buffer@^5.1.1, safe-buffer@~5.1.0: version "5.1.1" resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.1.tgz#893312af69b2123def71f57889001671eeb2c853" -samsam@1.1.2, samsam@~1.1: - version "1.1.2" - resolved "https://registry.yarnpkg.com/samsam/-/samsam-1.1.2.tgz#bec11fdc83a9fda063401210e40176c3024d1567" +samsam@1.x, samsam@^1.1.3: + version "1.2.1" + resolved "https://registry.yarnpkg.com/samsam/-/samsam-1.2.1.tgz#edd39093a3184370cb859243b2bdf255e7d8ea67" semver-diff@^2.0.0: version "2.1.0" @@ -3565,30 +3461,22 @@ set-immediate-shim@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/set-immediate-shim/-/set-immediate-shim-1.0.1.tgz#4b2b1b27eb808a9f8dcc481a58e5e56f599f3f61" -shelljs@^0.7.5: - version "0.7.8" - resolved "https://registry.yarnpkg.com/shelljs/-/shelljs-0.7.8.tgz#decbcf874b0d1e5fb72e14b164a9683048e9acb3" - dependencies: - glob "^7.0.0" - interpret "^1.0.0" - rechoir "^0.6.2" - -signal-exit@^2.0.0: - version "2.1.2" - resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-2.1.2.tgz#375879b1f92ebc3b334480d038dc546a6d558564" - signal-exit@^3.0.0, signal-exit@^3.0.1, signal-exit@^3.0.2: version "3.0.2" resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.2.tgz#b5fdc08f1287ea1178628e415e25132b73646c6d" -sinon@^1.17.7: - version "1.17.7" - resolved "https://registry.yarnpkg.com/sinon/-/sinon-1.17.7.tgz#4542a4f49ba0c45c05eb2e9dd9d203e2b8efe0bf" +sinon@^2.3.8: + version "2.3.8" + resolved "https://registry.yarnpkg.com/sinon/-/sinon-2.3.8.tgz#31de06fed8fba3a671e576dd96d0a5863796f25c" dependencies: - formatio "1.1.1" - lolex "1.3.2" - samsam "1.1.2" - util ">=0.10.3 <1" + diff "^3.1.0" + formatio "1.2.0" + lolex "^1.6.0" + native-promise-only "^0.8.1" + path-to-regexp "^1.7.0" + samsam "^1.1.3" + text-encoding "0.6.4" + type-detect "^4.0.0" slash@^1.0.0: version "1.0.0" @@ -3630,15 +3518,15 @@ source-map@^0.5.0, source-map@^0.5.3, source-map@^0.5.6, source-map@~0.5.1: version "0.5.6" resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.5.6.tgz#75ce38f52bf0733c5a7f0c118d81334a2bb5f412" -spawn-wrap@1.2.4: - version "1.2.4" - resolved "https://registry.yarnpkg.com/spawn-wrap/-/spawn-wrap-1.2.4.tgz#920eb211a769c093eebfbd5b0e7a5d2e68ab2e40" +spawn-wrap@^1.3.7: + version "1.3.8" + resolved "https://registry.yarnpkg.com/spawn-wrap/-/spawn-wrap-1.3.8.tgz#fa2a79b990cbb0bb0018dca6748d88367b19ec31" dependencies: - foreground-child "^1.3.3" + foreground-child "^1.5.6" mkdirp "^0.5.0" os-homedir "^1.0.1" rimraf "^2.3.3" - signal-exit "^2.0.0" + signal-exit "^3.0.2" which "^1.2.4" spdx-correct@~1.0.0: @@ -3692,6 +3580,13 @@ string-width@^2.0.0: is-fullwidth-code-point "^2.0.0" strip-ansi "^3.0.0" +string-width@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/string-width/-/string-width-2.1.0.tgz#030664561fc146c9423ec7d978fe2457437fe6d0" + dependencies: + is-fullwidth-code-point "^2.0.0" + strip-ansi "^4.0.0" + string_decoder@~1.0.0: version "1.0.3" resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.0.3.tgz#0fc67d7c141825de94282dd536bec6b9bce860ab" @@ -3708,6 +3603,12 @@ strip-ansi@^3.0.0, strip-ansi@^3.0.1: dependencies: ansi-regex "^2.0.0" +strip-ansi@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-4.0.0.tgz#a8479022eb1ac368a871389b635262c505ee368f" + dependencies: + ansi-regex "^3.0.0" + strip-ansi@~0.1.0: version "0.1.1" resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-0.1.1.tgz#39e8a98d044d150660abe4a6808acf70bb7bc991" @@ -3746,12 +3647,18 @@ supports-color@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-2.0.0.tgz#535d045ce6b6363fa40117084629995e9df324c7" -supports-color@^3.1.2, supports-color@^3.2.3: +supports-color@^3.1.2: version "3.2.3" resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-3.2.3.tgz#65ac0504b3954171d8a64946b2ae3cbb8a5f54f6" dependencies: has-flag "^1.0.0" +supports-color@^4.0.0: + version "4.2.0" + resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-4.2.0.tgz#ad986dc7eb2315d009b4d77c8169c2231a684037" + dependencies: + has-flag "^2.0.0" + symbol-observable@^0.2.2: version "0.2.4" resolved "https://registry.yarnpkg.com/symbol-observable/-/symbol-observable-0.2.4.tgz#95a83db26186d6af7e7a18dbd9760a2f86d08f40" @@ -3760,9 +3667,9 @@ symbol-observable@^1.0.4: version "1.0.4" resolved "https://registry.yarnpkg.com/symbol-observable/-/symbol-observable-1.0.4.tgz#29bf615d4aa7121bdd898b22d4b3f9bc4e2aa03d" -table@^3.7.8: - version "3.8.3" - resolved "https://registry.yarnpkg.com/table/-/table-3.8.3.tgz#2bbc542f0fda9861a755d3947fefd8b3f513855f" +table@^4.0.1: + version "4.0.1" + resolved "https://registry.yarnpkg.com/table/-/table-4.0.1.tgz#a8116c133fac2c61f4a420ab6cdf5c4d61f0e435" dependencies: ajv "^4.7.0" ajv-keywords "^1.0.0" @@ -3771,11 +3678,11 @@ table@^3.7.8: slice-ansi "0.0.4" string-width "^2.0.0" -tailored@^2.5.0: - version "2.5.0" - resolved "https://registry.yarnpkg.com/tailored/-/tailored-2.5.0.tgz#55055ea25e018951ecfc9adf39177f178fcde63e" +tailored@^2.6.0: + version "2.6.0" + resolved "https://registry.yarnpkg.com/tailored/-/tailored-2.6.0.tgz#70ae98b8f8bfb25ce320290c103cbc23aae4cf2a" dependencies: - erlang-types "^1.0.0" + erlang-types "^1.0.1" tar-pack@^3.4.0: version "3.4.0" @@ -3804,7 +3711,7 @@ term-size@^0.1.0: dependencies: execa "^0.4.0" -test-exclude@^4.1.0: +test-exclude@^4.1.1: version "4.1.1" resolved "https://registry.yarnpkg.com/test-exclude/-/test-exclude-4.1.1.tgz#4d84964b0966b0087ecc334a2ce002d3d9341e26" dependencies: @@ -3814,6 +3721,10 @@ test-exclude@^4.1.0: read-pkg-up "^1.0.1" require-main-filename "^1.0.1" +text-encoding@0.6.4: + version "0.6.4" + resolved "https://registry.yarnpkg.com/text-encoding/-/text-encoding-0.6.4.tgz#e399a982257a276dae428bb92845cb71bdc26d19" + text-table@^0.2.0, text-table@~0.2.0: version "0.2.0" resolved "https://registry.yarnpkg.com/text-table/-/text-table-0.2.0.tgz#7f5ee823ae805207c00af2df4a84ec3fcfa570b4" @@ -3838,10 +3749,20 @@ time-require@^0.1.2: pretty-ms "^0.2.1" text-table "^0.2.0" +time-zone@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/time-zone/-/time-zone-1.0.0.tgz#99c5bf55958966af6d06d83bdf3800dc82faec5d" + timed-out@^4.0.0: version "4.0.1" resolved "https://registry.yarnpkg.com/timed-out/-/timed-out-4.0.1.tgz#f32eacac5a175bea25d7fab565ab3ed8741ef56f" +tmp@^0.0.31: + version "0.0.31" + resolved "https://registry.yarnpkg.com/tmp/-/tmp-0.0.31.tgz#8f38ab9438e17315e5dbd8b3657e8bfb277ae4a7" + dependencies: + os-tmpdir "~1.0.1" + to-fast-properties@^1.0.1: version "1.0.3" resolved "https://registry.yarnpkg.com/to-fast-properties/-/to-fast-properties-1.0.3.tgz#b83571fa4d8c25b82e231b06e3a3055de4ca1a47" @@ -3856,6 +3777,10 @@ trim-newlines@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/trim-newlines/-/trim-newlines-1.0.0.tgz#5887966bb582a4503a41eb524f7d35011815a613" +trim-off-newlines@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/trim-off-newlines/-/trim-off-newlines-1.0.1.tgz#9f9ba9d9efa8764c387698bcbfeb2c848f11adb3" + trim-right@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/trim-right/-/trim-right-1.0.1.tgz#cb2e1203067e0c8de1f614094b9fe45704ea6003" @@ -3880,6 +3805,10 @@ type-check@~0.3.2: dependencies: prelude-ls "~1.1.2" +type-detect@^4.0.0: + version "4.0.3" + resolved "https://registry.yarnpkg.com/type-detect/-/type-detect-4.0.3.tgz#0e3f2670b44099b0b46c284d136a7ef49c74c2ea" + typedarray@^0.0.6: version "0.0.6" resolved "https://registry.yarnpkg.com/typedarray/-/typedarray-0.0.6.tgz#867ac74e3864187b1d3d47d996a78ec5c8830777" @@ -3942,22 +3871,10 @@ url-parse-lax@^1.0.0: dependencies: prepend-http "^1.0.1" -user-home@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/user-home/-/user-home-2.0.0.tgz#9c70bfd8169bc1dcbf48604e0f04b8b49cde9e9f" - dependencies: - os-homedir "^1.0.0" - util-deprecate@~1.0.1: version "1.0.2" resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf" -"util@>=0.10.3 <1": - version "0.10.3" - resolved "https://registry.yarnpkg.com/util/-/util-0.10.3.tgz#7afb1afe50805246489e3db7fe0ed379336ac0f9" - dependencies: - inherits "2.0.1" - uuid@^3.0.0: version "3.1.0" resolved "https://registry.yarnpkg.com/uuid/-/uuid-3.1.0.tgz#3dd3d3e790abc24d7b0d3a034ffababe28ebbc04" @@ -3975,9 +3892,13 @@ verror@1.3.6: dependencies: extsprintf "1.0.2" -which-module@^1.0.0: +well-known-symbols@^1.0.0: version "1.0.0" - resolved "https://registry.yarnpkg.com/which-module/-/which-module-1.0.0.tgz#bba63ca861948994ff307736089e3b96026c2a4f" + resolved "https://registry.yarnpkg.com/well-known-symbols/-/well-known-symbols-1.0.0.tgz#73c78ae81a7726a8fa598e2880801c8b16225518" + +which-module@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/which-module/-/which-module-2.0.0.tgz#d9ef07dce77b9902b8a3a8fa4b31c3e3f7e6e87a" which@^1.2.4, which@^1.2.8, which@^1.2.9: version "1.2.14" @@ -4086,23 +4007,29 @@ yargs-parser@^5.0.0: dependencies: camelcase "^3.0.0" -yargs@^7.1.0: - version "7.1.0" - resolved "https://registry.yarnpkg.com/yargs/-/yargs-7.1.0.tgz#6ba318eb16961727f5d284f8ea003e8d6154d0c8" +yargs-parser@^7.0.0: + version "7.0.0" + resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-7.0.0.tgz#8d0ac42f16ea55debd332caf4c4038b3e3f5dfd9" dependencies: - camelcase "^3.0.0" + camelcase "^4.1.0" + +yargs@^8.0.1: + version "8.0.2" + resolved "https://registry.yarnpkg.com/yargs/-/yargs-8.0.2.tgz#6299a9055b1cefc969ff7e79c1d918dceb22c360" + dependencies: + camelcase "^4.1.0" cliui "^3.2.0" decamelize "^1.1.1" get-caller-file "^1.0.1" - os-locale "^1.4.0" - read-pkg-up "^1.0.1" + os-locale "^2.0.0" + read-pkg-up "^2.0.0" require-directory "^2.1.1" require-main-filename "^1.0.1" set-blocking "^2.0.0" - string-width "^1.0.2" - which-module "^1.0.0" + string-width "^2.0.0" + which-module "^2.0.0" y18n "^3.2.1" - yargs-parser "^5.0.0" + yargs-parser "^7.0.0" yargs@~3.10.0: version "3.10.0" From 2afdfb8ef194cc34b6deb481eb2e475913198e19 Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Mon, 17 Jul 2017 23:13:35 -0500 Subject: [PATCH 621/860] Translate map to JavaScript map --- .babelrc | 6 +-- .tool-versions | 2 +- .../passes/translate/forms/map.ex | 51 +++++++++--------- .../passes/translate/forms/pattern.ex | 53 ++++++++++++------- .../passes/translate/protocol.ex | 2 +- package.json | 6 +-- priv/build/iife/ElixirScript.Core.js | 8 +-- .../lib/core/erlang_compat/erlang.js | 4 +- src/javascript/lib/core/erlang_compat/maps.js | 53 +++++++------------ src/javascript/lib/core/functions.js | 22 ++++++++ src/javascript/lib/core/protocol.js | 12 ++--- test/support/main.ex | 2 + yarn.lock | 17 ++++-- 13 files changed, 135 insertions(+), 103 deletions(-) diff --git a/.babelrc b/.babelrc index 6a9be799..002b4aa0 100644 --- a/.babelrc +++ b/.babelrc @@ -1,5 +1,3 @@ { - "presets": [ - "env" - ] -} \ No newline at end of file + "presets": ["env"] +} diff --git a/.tool-versions b/.tool-versions index 1c12341c..0a498367 100644 --- a/.tool-versions +++ b/.tool-versions @@ -1,3 +1,3 @@ erlang 20.0 elixir ref-v1.5.0-rc.1 -nodejs 8.1.0 +nodejs 8.1.4 diff --git a/lib/elixir_script/passes/translate/forms/map.ex b/lib/elixir_script/passes/translate/forms/map.ex index 28518a92..5f23e0e5 100644 --- a/lib/elixir_script/passes/translate/forms/map.ex +++ b/lib/elixir_script/passes/translate/forms/map.ex @@ -5,17 +5,19 @@ defmodule ElixirScript.Translate.Forms.Map do def compile({:%{}, _, [{:|, _, [map, new_values]}]}, state) do { map, state } = Form.compile(map, state) - { data, state } = Form.compile({:%{}, [], new_values}, state) + data = Enum.map(new_values, fn {x, y} -> + J.array_expression([ + Form.compile!(x, state), + Form.compile!(y, state) + ]) + end) - ast = J.call_expression( - J.member_expression( - J.identifier("Object"), - J.identifier("assign") - ), + ast = J.new_expression( + J.identifier("Map"), [ - J.object_expression([]), - map, - data + J.array_expression( + [J.spread_element(map)] ++ data + ) ] ) @@ -23,21 +25,22 @@ defmodule ElixirScript.Translate.Forms.Map do end def compile({:%{}, _, properties}, state) do - ast = properties - |> Enum.map(fn - ({x, y}) -> - case x do - {_, _, nil } -> - {key, _} = Form.compile(x, state) - {value, _} = Form.compile(y, state) - J.property(key, value, :init, false, false, true) - _ -> - {key, _} = Form.compile(x, state) - {value, _} = Form.compile(y, state) - make_property(key, value) - end - end) - |> J.object_expression + ast = J.new_expression( + J.identifier("Map"), + [ + J.array_expression( + Enum.map(properties, fn + {x, y} -> + J.array_expression( + [ + Form.compile!(x, state), + Form.compile!(y, state) + ] + ) + end) + ) + ] + ) {ast, state} end diff --git a/lib/elixir_script/passes/translate/forms/pattern.ex b/lib/elixir_script/passes/translate/forms/pattern.ex index d52407dc..9dc2a101 100644 --- a/lib/elixir_script/passes/translate/forms/pattern.ex +++ b/lib/elixir_script/passes/translate/forms/pattern.ex @@ -122,33 +122,33 @@ defmodule ElixirScript.Translate.Forms.Pattern do {pattern, params} = process_pattern(var, state) a = J.object_expression([%ESTree.Property{ - key: J.identifier("__MODULE__"), - value: hd(List.wrap(pattern)) - }]) + key: J.identifier("__MODULE__"), + value: hd(List.wrap(pattern)) + }]) - property = ElixirScript.Translate.Forms.Map.make_property( + property = J.array_expression([ Form.compile!(:__struct__, state), a - ) + ]) { property, params } {:__module__struct__, module} -> a = J.object_expression([%ESTree.Property{ - key: J.identifier("__MODULE__"), - value: J.call_expression( - J.member_expression( - J.identifier("Symbol"), - J.identifier("for") - ), - [J.literal(to_string(module))] - ) - }]) - - property = ElixirScript.Translate.Forms.Map.make_property( + key: J.identifier("__MODULE__"), + value: J.call_expression( + J.member_expression( + J.identifier("Symbol"), + J.identifier("for") + ), + [J.literal(to_string(module))] + ) + }]) + + property = J.array_expression([ Form.compile!(:__struct__, state), a - ) + ]) { property, [] } @@ -156,9 +156,15 @@ defmodule ElixirScript.Translate.Forms.Pattern do {pattern, params} = process_pattern(value, state) property = case key do {:^, _, [the_key]} -> - J.property(Form.compile!(the_key, state), hd(List.wrap(pattern)), :init, false, false, true) + J.array_expression([ + Form.compile!(the_key, state), + hd(List.wrap(pattern)) + ]) _ -> - ElixirScript.Translate.Forms.Map.make_property(Form.compile!(key, state), hd(List.wrap(pattern))) + J.array_expression([ + Form.compile!(key, state), + hd(List.wrap(pattern)) + ]) end { property, params } @@ -168,7 +174,14 @@ defmodule ElixirScript.Translate.Forms.Pattern do { props ++ [prop], params ++ param } end) - { [J.object_expression(List.wrap(props))], params } + ast = J.new_expression( + J.identifier("Map"), + [ + J.array_expression(List.wrap(props)) + ] + ) + + { [ast], params } end defp process_pattern({:<<>>, _, elements}, state) do diff --git a/lib/elixir_script/passes/translate/protocol.ex b/lib/elixir_script/passes/translate/protocol.ex index e6c1747b..48ea1585 100644 --- a/lib/elixir_script/passes/translate/protocol.ex +++ b/lib/elixir_script/passes/translate/protocol.ex @@ -153,7 +153,7 @@ defmodule ElixirScript.Translate.Protocol do end defp map_to_js(Map) do - J.identifier(:Object) + J.identifier(:Map) end defp map_to_js(Any) do diff --git a/package.json b/package.json index 8e013597..c243103e 100644 --- a/package.json +++ b/package.json @@ -23,7 +23,7 @@ "license": "MIT", "dependencies": { "erlang-types": "^1.0.1", - "tailored": "^2.6.0" + "tailored": "^2.6.1" }, "devDependencies": { "ava": "^0.21.0", @@ -41,9 +41,7 @@ "sinon": "^2.3.8" }, "ava": { - "require": [ - "babel-register" - ], + "require": ["babel-register"], "babel": { "babelrc": true } diff --git a/priv/build/iife/ElixirScript.Core.js b/priv/build/iife/ElixirScript.Core.js index a6c133c6..45c27597 100644 --- a/priv/build/iife/ElixirScript.Core.js +++ b/priv/build/iife/ElixirScript.Core.js @@ -1,6 +1,6 @@ var ElixirScript=function(){'use strict';/* @flow */function namedVariableResult(a,b){return new NamedVariableResult(a,b)}/* @flow */function is_number(a){return'number'==typeof a}function is_string(a){return'string'==typeof a}function is_boolean(a){return'boolean'==typeof a}function is_symbol(a){return'symbol'==typeof a}function is_object(a){return'object'==typeof a}function is_variable(a){return a instanceof Variable}function is_null(a){return null===a}function is_array(a){return Array.isArray(a)}function is_function(a){return'[object Function]'==Object.prototype.toString.call(a)}function is_map(a){return a instanceof Map}function resolveNull(){return function(a){return is_null(a)}}function resolveWildcard(){return function(){return!0}}function resolveObject(a){let b={};const c=Object.keys(a).concat(Object.getOwnPropertySymbols(a));for(let d of c)b[d]=buildMatch(a[d]);return function(d,e){if(!is_object(d)||a.length>d.length)return!1;for(let a of c)if(!(a in d)||!b[a](d[a],e))return!1;return!0}}function getSize(a,b){return a*b/8}function arraysEqual(c,a){if(c===a)return!0;if(null==c||null==a)return!1;if(c.length!=a.length)return!1;for(var b=0;be.integer(a));return new e(...b)}function resolveNoMatch(){return function(){return!1}}function buildMatch(a){if(null===a)return resolveNull(a);if('undefined'==typeof a)return resolveWildcard(a);const b=a.constructor.prototype,c=f.get(b);return c?c(a):'object'==typeof a?resolveObject(a):resolveNoMatch()}function defmatchgen(...a){const b=getArityMap(a);return function*(...a){let[c,d]=findMatchingFunction(a,b);return yield*c.apply(this,d)}}function findMatchingFunction(a,b){if(b.has(a.length)){const c=b.get(a.length);let d=null,e=null;for(let b of c){let c=[];a=fillInOptionalValues(a,b.arity,b.optionals);const f=b.pattern(a,c),[g,h]=checkNamedVariables(c);if(f&&h&&b.guard.apply(this,g)){d=b.fn,e=g;break}}if(!d)throw console.error('No match for:',a),new MatchError(a);return[d,e]}throw console.error('Arity of',a.length,'not found. No match for:',a),new MatchError(a)}function getArityMap(a){let b=new Map;for(const c of a){const a=getArityRange(c);for(const d of a){let a=[];b.has(d)&&(a=b.get(d)),a.push(c),b.set(d,a)}}return b}function getArityRange(a){const b=a.arity-a.optionals.length,c=a.arity;let d=[b];for(;d[d.length-1]!=c;)d.push(d[d.length-1]+1);return d}function getOptionalValues(a){let b=[];for(let c=0;c!0,d=null){let e=[],f=buildMatch(a);const g=f(b,e),[h,i]=checkNamedVariables(e);return g&&i&&c.apply(this,h)?h:d}function run_generators(a,b){if(0==b.length)return a.map((a)=>{return Array.isArray(a)?a:[a]});const c=b.pop();let d=[];for(let e of c())for(let b of a)d.push([e].concat(b));return run_generators(d,b)}function iterator_to_reducer(a,b,c){const d=a[Symbol.iterator]();let e=d.next(),f=b;for(;!1===e.done;){if(f=c(e.value,f.get(1)),f.get(0)===Symbol.for('halt'))return new n.Tuple(Symbol.for('halted'),f.get(1));if(f.get(0)===Symbol.for('suspend'))return new n.Tuple(Symbol.for('suspended'),f.get(1),(a)=>{return iterator_to_reducer(d,a,c)});e=d.next()}return new n.Tuple(Symbol.for('done'),f.get(1))}function run_list_generators(a,b){if(0==b.length)return a.map((a)=>{return Array.isArray(a)?a:[a]});const c=b.pop(),d=[];for(const e of c())for(const b of a)d.push([e].concat(b));return run_list_generators(d,b)}// http://erlang.org/doc/man/erlang.html -function atom_to_binary(a,b=Symbol.for('utf8')){if(b!==Symbol.for('utf8'))throw new Error(`unsupported encoding ${b}`);return a.__MODULE__?Symbol.keyFor(a.__MODULE__):Symbol.keyFor(a)}function binary_to_atom(a,b=Symbol.for('utf8')){if(b!==Symbol.for('utf8'))throw new Error(`unsupported encoding ${b}`);return Symbol.for(a)}function is_number$1(a){return'number'==typeof a||a instanceof Number}function to_list(a){if(!1===h.is_map(a))return new d.Tuple(k,a);const b=[];for(const c of keys(a))b.push(new d.Tuple(c,a[c]));return b}function keys(a){if(!1===h.is_map(a))return new d.Tuple(k,a);const b=[];for(const c of Object.getOwnPropertySymbols(a))b.push(c);for(const c of Object.getOwnPropertyNames(a))b.push(c);return b}function is_key(a,b){return b.hasOwnProperty(a)}// http://erlang.org/doc/man/lists.html +function atom_to_binary(a,b=Symbol.for('utf8')){if(b!==Symbol.for('utf8'))throw new Error(`unsupported encoding ${b}`);return a.__MODULE__?Symbol.keyFor(a.__MODULE__):Symbol.keyFor(a)}function binary_to_atom(a,b=Symbol.for('utf8')){if(b!==Symbol.for('utf8'))throw new Error(`unsupported encoding ${b}`);return Symbol.for(a)}function is_number$1(a){return'number'==typeof a||a instanceof Number}function is_key(a,b){return b.has(a)}// http://erlang.org/doc/man/lists.html function reverse(a){return[...a]}function flatten(a,b=[]){const c=a.reduce((a,b)=>{return Array.isArray(b)?a.concat(flatten(b)):a.concat(b)},[]);return c.concat(b)}function foldl(a,b,c){return c.reduce((b,c)=>{return a(c,b)},b)}function keyfind(a,b,c){for(const d of c)if(d.get(b-1)===a)return d;return!1}function keydelete(a,b,c){const d=[];let e=!1;for(let f=0;fBitString$1.integer(a));return new BitString$1(...d)}[Symbol.iterator](){return this.value[Symbol.iterator]()}toString(){var a,b='';for(a=0;a>'}process(a){let b=[];var c;for(c=0;cb?c.push(b):2048>b?c.push(192|b>>6,128|63&b):55296>b||57344<=b?c.push(224|b>>12,128|63&b>>6,128|63&b):(d++,b=65536+((1023&b)<<10|1023&a.charCodeAt(d)),c.push(240|b>>18,128|63&b>>12,128|63&b>>6,128|63&b));return c}static toUTF16Array(a){for(var b,c=[],d=0;d=b?(c.push(0),c.push(b)):(c.push(255&b>>8),c.push(255&b));return c}static toUTF32Array(a){for(var b,c=[],d=0;d=b?(c.push(0),c.push(0),c.push(0),c.push(b)):(c.push(0),c.push(0),c.push(255&b>>8),c.push(255&b));return c}//http://stackoverflow.com/questions/2003493/javascript-float-from-to-bits -static float32ToBytes(a){var b=[],c=new ArrayBuffer(4);new Float32Array(c)[0]=a;let d=new Uint32Array(c)[0];return b.push(255&d>>24),b.push(255&d>>16),b.push(255&d>>8),b.push(255&d),b}static float64ToBytes(a){var b=[],c=new ArrayBuffer(8);new Float64Array(c)[0]=a;var d=new Uint32Array(c)[0],e=new Uint32Array(c)[1];return b.push(255&e>>24),b.push(255&e>>16),b.push(255&e>>8),b.push(255&e),b.push(255&d>>24),b.push(255&d>>16),b.push(255&d>>8),b.push(255&d),b}}var d={Tuple,PID:class PID{constructor(){++b,this.id=b}toString(){return'PID#<0.'+this.id+'.0>'}},Reference:class Reference{constructor(){++c,this.id=c,this.ref=Symbol()}toString(){return'Ref#<0.0.0.'+this.id+'>'}},BitString:BitString$1};/* @flow */const e=d.BitString,f=new Map;f.set(Variable.prototype,function resolveVariable(a){return function(b,c){return null===a.name||a.name.startsWith('_')?c.push(b):c.push(namedVariableResult(a.name,b)),!0}}),f.set(Wildcard.prototype,resolveWildcard),f.set(HeadTail.prototype,function resolveHeadTail(){return function(a,b){if(!is_array(a)||2>a.length)return!1;const c=a[0],d=a.slice(1);return b.push(c),b.push(d),!0}}),f.set(StartsWith.prototype,function resolveStartsWith(a){const b=a.prefix;return function(a,c){return is_string(a)&&a.startsWith(b)&&(c.push(a.substring(b.length)),!0)}}),f.set(Capture.prototype,function resolveCapture(a){const b=buildMatch(a.value);return function(a,c){return!!b(a,c)&&(c.push(a),!0)}}),f.set(Bound.prototype,function resolveBound(a){return function(b){return typeof b==typeof a.value&&b===a.value}}),f.set(Type.prototype,function resolveType(a){return function(b,c){if(b instanceof a.type){const d=buildMatch(a.objPattern);return d(b,c)}return!1}}),f.set(BitStringMatch.prototype,function resolveBitString(a){let b=[];for(let c of a.values)if(is_variable(c.value)){let a=getSize(c.unit,c.size);fillArray(b,a)}else b=b.concat(new e(c).value);let c=a.values;return function(a,d){var f=String.fromCharCode;let g=null;if(!is_string(a)&&!(a instanceof e))return!1;g=is_string(a)?new e(e.binary(a)):a;let h=0;for(let e,j=0;jd.size)return!1;for(let a of c)if(!d.has(a)||!b.get(a)(d.get(a),e))return!1;return!0}}),f.set(Array.prototype,function resolveArray(a){const b=a.map((a)=>buildMatch(a));return function(c,d){return is_array(c)&&c.length==a.length&&c.every(function(a,e){return b[e](c[e],d)})}}),f.set(String.prototype,function resolveString(a){return function(b){return is_string(b)&&b===a}}),f.set(Boolean.prototype,function resolveBoolean(a){return function(b){return is_boolean(b)&&b===a}}),f.set(Function.prototype,function resolveFunction(a){return function(b){return is_function(b)&&b===a}}),f.set(Object.prototype,resolveObject);class MatchError extends Error{constructor(a){if(super(),'symbol'==typeof a)this.message='No match for: '+a.toString();else if(Array.isArray(a)){let b=a.map((a)=>{return null===a?'null':'undefined'==typeof a?'undefined':a.toString()});this.message='No match for: '+b}else this.message='No match for: '+a;this.stack=new Error().stack,this.name=this.constructor.name}}class Clause{constructor(a,b,c=()=>!0){this.pattern=buildMatch(a),this.arity=a.length,this.optionals=getOptionalValues(a),this.fn=b,this.guard=c}}const g=Symbol();// https://github.com/airportyh/protomorphism -class Protocol{constructor(b){function createFun(b){return function(...c){const d=c[0];let e=null;if(null===d&&this.hasImplementation(Symbol('null'))?e=this.registry.get(Symbol)[b]:a(d)&&this.hasImplementation(n.Integer)?e=this.registry.get(n.Integer)[b]:'number'==typeof d&&!a(d)&&this.hasImplementation(n.Float)?e=this.registry.get(n.Float)[b]:'string'==typeof d&&this.hasImplementation(n.BitString)?e=this.registry.get(n.BitString)[b]:d&&d[Symbol.for('__struct__')]&&this.hasImplementation(d)?e=this.registry.get(d[Symbol.for('__struct__')].__MODULE__)[b]:null!==d&&this.hasImplementation(d)?e=this.registry.get(d.constructor)[b]:this.fallback&&(e=this.fallback[b]),null!=e){const a=e.apply(this,c);return a}throw new Error(`No implementation found for ${d}`)}}for(const a in this.registry=new Map,this.fallback=null,b)this[a]=createFun(a).bind(this)}implementation(a,b){null===a?this.fallback=b:this.registry.set(a,b)}hasImplementation(a){if(a===n.Integer||a===n.Float||a===n.BitString)return this.registry.has(a);return a&&a[Symbol.for('__struct__')]?this.registry.has(a[Symbol.for('__struct__')].__MODULE__):this.registry.has(a.constructor)}}var h={atom_to_binary,binary_to_atom,binary_to_existing_atom:function binary_to_existing_atom(a,b=Symbol.for('utf8')){return binary_to_atom(a,b)},list_concatenation:function list_concatenation(a,b){return a.concat(b)},list_subtraction:function list_subtraction(a,b){const c=[...a];for(const d of b){const a=c.indexOf(d);-1b},greaterThanOrEqualTo:function greaterThanOrEqualTo(a,b){return a>=b},lessThan:function lessThan(a,b){return a>b},bxor:function bxor(a,b){return a^b},bnot:function bnot(a){return~a},is_bitstring:function is_bitstring$1(a){return a instanceof d.BitString},is_boolean:function is_boolean$1(a){return'boolean'==typeof a||a instanceof Boolean},is_float:function is_float(b){return is_number$1(b)&&!a(b)},is_function:function is_function$1(a){return'function'==typeof a||a instanceof Function},is_integer:function is_integer(b){return a(b)},is_list:function is_list(a){return Array.isArray(a)},is_map:function is_map$1(a){return'object'==typeof a||a instanceof Object},is_number:is_number$1,is_pid:function is_pid(a){return a instanceof d.PID},is_port:function is_port(){return!1},is_reference:function is_reference(a){return a instanceof d.Reference},is_tuple:function is_tuple(a){return a instanceof d.Tuple},is_atom:function is_atom(a){return'symbol'==typeof a||a instanceof Symbol||a.__MODULE__},is_binary:function is_binary(a){return'string'==typeof a||a instanceof String},element:function element(a,b){return b.get(a-1)},setelement:function setelement(a,b,c){const e=[...b.values];return e[a-1]=c,new d.Tuple(...e)},make_tuple:function make_tuple(a,b){const c=[];for(let d=0;d!0){let d=[],e=buildMatch(a);const f=e(b,d),[g,h]=checkNamedVariables(d);if(f&&h&&c.apply(this,g))return g;throw console.error('No match for:',b),new MatchError(b)},MatchError,variable:function variable(a=null,b=Symbol.for('tailored.no_value')){return new Variable(a,b)},wildcard:function wildcard(){return new Wildcard},startsWith:function startsWith(a){return new StartsWith(a)},capture:function capture(a){return new Capture(a)},headTail:function headTail(){return new HeadTail},type:function a(a,b={}){return new Type(a,b)},bound:function bound(a){return new Bound(a)},Clause,clause:function clause(a,b,c=()=>!0){return new Clause(a,b,c)},bitStringMatch:function bitStringMatch(...a){return new BitStringMatch(...a)},match_or_default,defmatchgen,list_comprehension:function list_comprehension(a,b){const c=run_generators(b.pop()(),b);let d=[];for(let e of c)a.guard.apply(this,e)&&d.push(a.fn.apply(this,e));return d},list_generator:function list_generator(a,b){return function(){let c=[];for(let d of b){const b=match_or_default(a,d,()=>!0,g);if(b!=g){const[a]=b;c.push(a)}}return c}},bitstring_generator:function bitstring_generator(a,b){return function(){let c=[],d=b.slice(0,a.byte_size()),e=1;for(;d.byte_size==a.byte_size();){const f=match_or_default(a,d,()=>!0,g);if(f!=g){c.push(f)}d=b.slice(a.byte_size()*e,a.byte_size()*(e+1)),e++}return c}},bitstring_comprehension:function bitstring_comprehension(a,b){const c=run_generators(b.pop()(),b);let e=[];for(let d of c)a.guard.apply(this,d)&&e.push(a.fn.apply(this,d));return e=e.map((a)=>d.BitString.integer(a)),new d.BitString(...e)},defmatchGen:function defmatchGen(...a){return defmatchgen(...a)},defmatchAsync:function defmatchAsync(...a){const b=getArityMap(a);return async function(...a){if(b.has(a.length)){const c=b.get(a.length);let d=null,e=null;for(let b of c){let c=[];a=fillInOptionalValues(a,b.arity,b.optionals);const f=b.pattern(a,c),[g,h]=checkNamedVariables(c);if(f&&h&&(await b.guard.apply(this,c))){d=b.fn,e=c;break}}if(!d)throw console.error('No match for:',a),new MatchError(a);return d.apply(this,e)}throw console.error('Arity of',a.length,'not found. No match for:',a),new MatchError(a)}}},Integer:class Integer{},Float:class Float{},Functions:{call_property:function call_property(a,b){if(!b)return a instanceof Function||'function'==typeof a?a():a;let c=null;if('number'==typeof a||'symbol'==typeof a||'boolean'==typeof a||'string'==typeof a?void 0===a[b]?void 0!==a[Symbol.for(b)]&&(c=Symbol.for(b)):c=b:b in a?c=b:Symbol.for(b)in a&&(c=Symbol.for(b)),null===c)throw new Error(`Property ${b} not found in ${a}`);return a[c]instanceof Function||'function'==typeof a[c]?a[c]():a[c]},defprotocol:function defprotocol(a){return new Protocol(a)},defimpl:function defimpl(a,b,c){a.implementation(b,c)},build_namespace:function build_namespace(a,b){let c=b.split('.');const d=a;let e=a;'Elixir'===c[0]&&(c=c.slice(1));for(const d of c)'undefined'==typeof e[d]&&(e[d]={}),e=e[d];return d.__table__=a.__table__||{},d.__table__[Symbol.for(b)]=e,e},iterator_to_reducer},SpecialForms:{_case:function _case(a,b){return n.Patterns.defmatch(...b)(a)},cond:function cond(...a){for(const b of a)if(b[0])return b[1]();throw new Error},_for:function _for(a,b,c,d=[]){let[e,f]=c.into(d);const g=run_list_generators(b.pop()(),b);for(const h of g)a.guard.apply(this,h)&&(e=f(e,new n.Tuple(Symbol.for('cont'),a.fn.apply(this,h))));return f(e,Symbol.for('done'))},_try:function _try(a,b,c,d,e){let f=null;try{f=a()}catch(a){let d=null;if(b)try{return d=b(a),d}catch(a){if(a instanceof n.Patterns.MatchError)throw a}if(c)try{return d=c(a),d}catch(a){if(a instanceof n.Patterns.MatchError)throw a}throw a}finally{e&&e()}if(d)try{return d(f)}catch(a){if(a instanceof n.Patterns.MatchError)throw new Error('No Match Found in Else');throw a}else return f},_with:function _with(...a){let b=[],c=null,d=null;'function'==typeof a[a.length-2]?[c,d]=a.splice(-2):c=a.pop();for(let c=0;c{const[c,d]=b;return a[c]=d,a},{})},keys,values:function values$1(a){if(!1===h.is_map(a))return new d.Tuple(k,a);const b=[];for(const c of keys(a))b.push(a[c]);return b},is_key,put:function put(a,b,c){if(!1===h.is_map(c))return new d.Tuple(k,c);const e=Object.assign({},c,{[a]:b});return e},merge:function merge(a,b){return!1===h.is_map(a)?new d.Tuple(k,a):!1===h.is_map(b)?new d.Tuple(k,b):Object.assign({},a,b)},update:function update(a,b,c){return!1===h.is_map(c)?new d.Tuple(k,c):!1===is_key(a,c)?new d.Tuple(l,a):Object.assign({},c,{[a]:b})},get:function get(...a){const b=a[0],c=a[1];return!1===h.is_map(c)?new d.Tuple(k,c):is_key(b)?c[b]:3===a.length?a[2]:new d.Tuple(l,b)},take:function take(a,b){if(!1===h.is_map(b))return new d.Tuple(k,b);if(!is_key(a))return j;const c=b[a],e=Object.assign({},b);return delete e[a],new d.Tuple(c,e)}},lists:{reverse,foreach:function foreach(a,b){return b.forEach((b)=>a(b)),Symbol.for('ok')},duplicate:function duplicate(a,b){const c=[];for(;c.length{if(d.get(c-1)a.get(c-1)?1:0})},keystore:function keystore(a,b,c,d){const e=[...c];for(let f=0;fa.toString()).join()},map:function map(a,b){return b.map((b)=>a(b))},filter:function filter(a,b){return b.filter((b)=>a(b))},filtermap:function filtermap(a,b){const c=[];for(const e of b){const b=a(e);!0===b?c.push(e):b instanceof d.Tuple&&!0===b.get(0)&&c.push(b.get(1))}return c},member:function member(a,b){for(const c of b)if(c===a)return!0;return!1},all:function all(a,b){for(const c of b)if(!1===a(c))return!1;return!0},any:function any(a,b){for(const c of b)if(!0===a(c))return!0;return!1},splitwith:function splitwith(a,b){let c=!1;const e=[],f=[];for(const d of b)!0==c?f.push(d):!0===a(d)?e.push(d):(c=!0,f.push(d));return new d.Tuple(e,f)},sort:function sort(...a){if(1===a.length){const b=[...a[0]];return b.sort()}const c=a[0],b=[...a[1]];return b.sort((d,a)=>{const b=c(d,a);return!0===b?-1:1})}}};return{Core:n}}(); +static float32ToBytes(a){var b=[],c=new ArrayBuffer(4);new Float32Array(c)[0]=a;let d=new Uint32Array(c)[0];return b.push(255&d>>24),b.push(255&d>>16),b.push(255&d>>8),b.push(255&d),b}static float64ToBytes(a){var b=[],c=new ArrayBuffer(8);new Float64Array(c)[0]=a;var d=new Uint32Array(c)[0],e=new Uint32Array(c)[1];return b.push(255&e>>24),b.push(255&e>>16),b.push(255&e>>8),b.push(255&e),b.push(255&d>>24),b.push(255&d>>16),b.push(255&d>>8),b.push(255&d),b}}var d={Tuple,PID:class PID{constructor(){++b,this.id=b}toString(){return'PID#<0.'+this.id+'.0>'}},Reference:class Reference{constructor(){++c,this.id=c,this.ref=Symbol()}toString(){return'Ref#<0.0.0.'+this.id+'>'}},BitString:BitString$1};/* @flow */const e=d.BitString,f=new Map;f.set(Variable.prototype,function resolveVariable(a){return function(b,c){return null===a.name||a.name.startsWith('_')?c.push(b):c.push(namedVariableResult(a.name,b)),!0}}),f.set(Wildcard.prototype,resolveWildcard),f.set(HeadTail.prototype,function resolveHeadTail(){return function(a,b){if(!is_array(a)||2>a.length)return!1;const c=a[0],d=a.slice(1);return b.push(c),b.push(d),!0}}),f.set(StartsWith.prototype,function resolveStartsWith(a){const b=a.prefix;return function(a,c){return is_string(a)&&a.startsWith(b)&&(c.push(a.substring(b.length)),!0)}}),f.set(Capture.prototype,function resolveCapture(a){const b=buildMatch(a.value);return function(a,c){return!!b(a,c)&&(c.push(a),!0)}}),f.set(Bound.prototype,function resolveBound(a){return function(b){return typeof b==typeof a.value&&b===a.value}}),f.set(Type.prototype,function resolveType(a){return function(b,c){if(b instanceof a.type){const d=buildMatch(a.objPattern);return d(b,c)}return!1}}),f.set(BitStringMatch.prototype,function resolveBitString(a){let b=[];for(let c of a.values)if(is_variable(c.value)){let a=getSize(c.unit,c.size);fillArray(b,a)}else b=b.concat(new e(c).value);let c=a.values;return function(a,d){var f=String.fromCharCode;let g=null;if(!is_string(a)&&!(a instanceof e))return!1;g=is_string(a)?new e(e.binary(a)):a;let h=0;for(let e,j=0;jd.size)return!1;for(let a of c)if(!d.has(a)||!b.get(a)(d.get(a),e))return!1;return!0}}),f.set(Array.prototype,function resolveArray(a){const b=a.map((a)=>buildMatch(a));return function(c,d){return is_array(c)&&c.length==a.length&&c.every(function(a,e){return b[e](c[e],d)})}}),f.set(String.prototype,function resolveString(a){return function(b){return is_string(b)&&b===a}}),f.set(Boolean.prototype,function resolveBoolean(a){return function(b){return is_boolean(b)&&b===a}}),f.set(Function.prototype,function resolveFunction(a){return function(b){return is_function(b)&&b===a}}),f.set(Object.prototype,resolveObject);class MatchError extends Error{constructor(a){if(super(),'symbol'==typeof a)this.message='No match for: '+a.toString();else if(Array.isArray(a)){let b=a.map((a)=>{return null===a?'null':'undefined'==typeof a?'undefined':a.toString()});this.message='No match for: '+b}else this.message='No match for: '+a;this.stack=new Error().stack,this.name=this.constructor.name}}class Clause{constructor(a,b,c=()=>!0){this.pattern=buildMatch(a),this.arity=a.length,this.optionals=getOptionalValues(a),this.fn=b,this.guard=c}}const g=Symbol();// https://github.com/airportyh/protomorphism +class Protocol{constructor(b){function createFun(b){return function(...c){const d=c[0];let e=null;if(null===d&&this.hasImplementation(Symbol('null'))?e=this.registry.get(Symbol)[b]:a(d)&&this.hasImplementation(n.Integer)?e=this.registry.get(n.Integer)[b]:'number'==typeof d&&!a(d)&&this.hasImplementation(n.Float)?e=this.registry.get(n.Float)[b]:'string'==typeof d&&this.hasImplementation(n.BitString)?e=this.registry.get(n.BitString)[b]:d&&d.has(Symbol.for('__struct__'))&&this.hasImplementation(d)?e=this.registry.get(d.get(Symbol.for('__struct__')).__MODULE__)[b]:null!==d&&this.hasImplementation(d)?e=this.registry.get(d.constructor)[b]:this.fallback&&(e=this.fallback[b]),null!=e){const a=e.apply(this,c);return a}throw new Error(`No implementation found for ${d}`)}}for(const a in this.registry=new Map,this.fallback=null,b)this[a]=createFun(a).bind(this)}implementation(a,b){null===a?this.fallback=b:this.registry.set(a,b)}hasImplementation(a){if(a===n.Integer||a===n.Float||a===n.BitString)return this.registry.has(a);return a&&a.has(Symbol.for('__struct__'))?this.registry.has(a.get(Symbol.for('__struct__')).__MODULE__):this.registry.has(a.constructor)}}var h={atom_to_binary,binary_to_atom,binary_to_existing_atom:function binary_to_existing_atom(a,b=Symbol.for('utf8')){return binary_to_atom(a,b)},list_concatenation:function list_concatenation(a,b){return a.concat(b)},list_subtraction:function list_subtraction(a,b){const c=[...a];for(const d of b){const a=c.indexOf(d);-1b},greaterThanOrEqualTo:function greaterThanOrEqualTo(a,b){return a>=b},lessThan:function lessThan(a,b){return a>b},bxor:function bxor(a,b){return a^b},bnot:function bnot(a){return~a},is_bitstring:function is_bitstring$1(a){return a instanceof d.BitString},is_boolean:function is_boolean$1(a){return'boolean'==typeof a||a instanceof Boolean},is_float:function is_float(b){return is_number$1(b)&&!a(b)},is_function:function is_function$1(a){return'function'==typeof a||a instanceof Function},is_integer:function is_integer(b){return a(b)},is_list:function is_list(a){return Array.isArray(a)},is_map:function is_map$1(a){return a instanceof Map},is_number:is_number$1,is_pid:function is_pid(a){return a instanceof d.PID},is_port:function is_port(){return!1},is_reference:function is_reference(a){return a instanceof d.Reference},is_tuple:function is_tuple(a){return a instanceof d.Tuple},is_atom:function is_atom(a){return'symbol'==typeof a||a instanceof Symbol||a.__MODULE__},is_binary:function is_binary(a){return'string'==typeof a||a instanceof String},element:function element(a,b){return b.get(a-1)},setelement:function setelement(a,b,c){const e=[...b.values];return e[a-1]=c,new d.Tuple(...e)},make_tuple:function make_tuple(a,b){const c=[];for(let d=0;d!0){let d=[],e=buildMatch(a);const f=e(b,d),[g,h]=checkNamedVariables(d);if(f&&h&&c.apply(this,g))return g;throw console.error('No match for:',b),new MatchError(b)},MatchError,variable:function variable(a=null,b=Symbol.for('tailored.no_value')){return new Variable(a,b)},wildcard:function wildcard(){return new Wildcard},startsWith:function startsWith(a){return new StartsWith(a)},capture:function capture(a){return new Capture(a)},headTail:function headTail(){return new HeadTail},type:function a(a,b={}){return new Type(a,b)},bound:function bound(a){return new Bound(a)},Clause,clause:function clause(a,b,c=()=>!0){return new Clause(a,b,c)},bitStringMatch:function bitStringMatch(...a){return new BitStringMatch(...a)},match_or_default,defmatchgen,list_comprehension:function list_comprehension(a,b){const c=run_generators(b.pop()(),b);let d=[];for(let e of c)a.guard.apply(this,e)&&d.push(a.fn.apply(this,e));return d},list_generator:function list_generator(a,b){return function(){let c=[];for(let d of b){const b=match_or_default(a,d,()=>!0,g);if(b!=g){const[a]=b;c.push(a)}}return c}},bitstring_generator:function bitstring_generator(a,b){return function(){let c=[],d=b.slice(0,a.byte_size()),e=1;for(;d.byte_size==a.byte_size();){const f=match_or_default(a,d,()=>!0,g);if(f!=g){c.push(f)}d=b.slice(a.byte_size()*e,a.byte_size()*(e+1)),e++}return c}},bitstring_comprehension:function bitstring_comprehension(a,b){const c=run_generators(b.pop()(),b);let e=[];for(let d of c)a.guard.apply(this,d)&&e.push(a.fn.apply(this,d));return e=e.map((a)=>d.BitString.integer(a)),new d.BitString(...e)},defmatchGen:function defmatchGen(...a){return defmatchgen(...a)},defmatchAsync:function defmatchAsync(...a){const b=getArityMap(a);return async function(...a){if(b.has(a.length)){const c=b.get(a.length);let d=null,e=null;for(let b of c){let c=[];a=fillInOptionalValues(a,b.arity,b.optionals);const f=b.pattern(a,c),[g,h]=checkNamedVariables(c);if(f&&h&&(await b.guard.apply(this,c))){d=b.fn,e=c;break}}if(!d)throw console.error('No match for:',a),new MatchError(a);return d.apply(this,e)}throw console.error('Arity of',a.length,'not found. No match for:',a),new MatchError(a)}}},Integer:class Integer{},Float:class Float{},Functions:{call_property:function call_property(a,b){if(!b)return a instanceof Function||'function'==typeof a?a():a;if(a instanceof Map){let c=null;if(a.has(b)?c=b:a.has(Symbol.for(b))&&(c=Symbol.for(b)),null===c)throw new Error(`Property ${b} not found in ${a}`);return a.get(c)instanceof Function||'function'==typeof a.get(c)?a.get(c)():a.get(c)}let c=null;if('number'==typeof a||'symbol'==typeof a||'boolean'==typeof a||'string'==typeof a?void 0===a[b]?void 0!==a[Symbol.for(b)]&&(c=Symbol.for(b)):c=b:b in a?c=b:Symbol.for(b)in a&&(c=Symbol.for(b)),null===c)throw new Error(`Property ${b} not found in ${a}`);return a[c]instanceof Function||'function'==typeof a[c]?a[c]():a[c]},defprotocol:function defprotocol(a){return new Protocol(a)},defimpl:function defimpl(a,b,c){a.implementation(b,c)},build_namespace:function build_namespace(a,b){let c=b.split('.');const d=a;let e=a;'Elixir'===c[0]&&(c=c.slice(1));for(const d of c)'undefined'==typeof e[d]&&(e[d]={}),e=e[d];return d.__table__=a.__table__||{},d.__table__[Symbol.for(b)]=e,e},iterator_to_reducer},SpecialForms:{_case:function _case(a,b){return n.Patterns.defmatch(...b)(a)},cond:function cond(...a){for(const b of a)if(b[0])return b[1]();throw new Error},_for:function _for(a,b,c,d=[]){let[e,f]=c.into(d);const g=run_list_generators(b.pop()(),b);for(const h of g)a.guard.apply(this,h)&&(e=f(e,new n.Tuple(Symbol.for('cont'),a.fn.apply(this,h))));return f(e,Symbol.for('done'))},_try:function _try(a,b,c,d,e){let f=null;try{f=a()}catch(a){let d=null;if(b)try{return d=b(a),d}catch(a){if(a instanceof n.Patterns.MatchError)throw a}if(c)try{return d=c(a),d}catch(a){if(a instanceof n.Patterns.MatchError)throw a}throw a}finally{e&&e()}if(d)try{return d(f)}catch(a){if(a instanceof n.Patterns.MatchError)throw new Error('No Match Found in Else');throw a}else return f},_with:function _with(...a){let b=[],c=null,d=null;'function'==typeof a[a.length-2]?[c,d]=a.splice(-2):c=a.pop();for(let c=0;c{const[c,d]=b;return a.set(c,d),a},new Map)},keys:function keys(a){return!1===h.is_map(a)?new d.Tuple(k,a):Array.from(a.keys())},values:function values$1(a){return!1===h.is_map(a)?new d.Tuple(k,a):Array.from(a.values())},is_key,put:function put(a,b,c){if(!1===h.is_map(c))return new d.Tuple(k,c);const e=new Map(c);return e.set(a,b),e},merge:function merge(a,b){return!1===h.is_map(a)?new d.Tuple(k,a):!1===h.is_map(b)?new d.Tuple(k,b):new Map([...a,...b])},update:function update(a,b,c){return!1===h.is_map(c)?new d.Tuple(k,c):!1===is_key(a,c)?new d.Tuple(l,a):new Map([...c,[a,b]])},get:function get(...a){const b=a[0],c=a[1];return!1===h.is_map(c)?new d.Tuple(k,c):is_key(b)?c.get(b):3===a.length?a[2]:new d.Tuple(l,b)},take:function take(a,b){if(!1===h.is_map(b))return new d.Tuple(k,b);if(!is_key(a))return j;const c=b.get(a),e=new Map(b);return e.delete(a),new d.Tuple(c,e)}},lists:{reverse,foreach:function foreach(a,b){return b.forEach((b)=>a(b)),Symbol.for('ok')},duplicate:function duplicate(a,b){const c=[];for(;c.length{if(d.get(c-1)a.get(c-1)?1:0})},keystore:function keystore(a,b,c,d){const e=[...c];for(let f=0;fa.toString()).join()},map:function map(a,b){return b.map((b)=>a(b))},filter:function filter(a,b){return b.filter((b)=>a(b))},filtermap:function filtermap(a,b){const c=[];for(const e of b){const b=a(e);!0===b?c.push(e):b instanceof d.Tuple&&!0===b.get(0)&&c.push(b.get(1))}return c},member:function member(a,b){for(const c of b)if(c===a)return!0;return!1},all:function all(a,b){for(const c of b)if(!1===a(c))return!1;return!0},any:function any(a,b){for(const c of b)if(!0===a(c))return!0;return!1},splitwith:function splitwith(a,b){let c=!1;const e=[],f=[];for(const d of b)!0==c?f.push(d):!0===a(d)?e.push(d):(c=!0,f.push(d));return new d.Tuple(e,f)},sort:function sort(...a){if(1===a.length){const b=[...a[0]];return b.sort()}const c=a[0],b=[...a[1]];return b.sort((d,a)=>{const b=c(d,a);return!0===b?-1:1})}}};return{Core:n}}(); diff --git a/src/javascript/lib/core/erlang_compat/erlang.js b/src/javascript/lib/core/erlang_compat/erlang.js index 5a0bc2d4..338c3a2b 100644 --- a/src/javascript/lib/core/erlang_compat/erlang.js +++ b/src/javascript/lib/core/erlang_compat/erlang.js @@ -174,7 +174,7 @@ function is_list(value) { } function is_map(value) { - return typeof value === 'object' || value instanceof Object; + return value instanceof Map; } function is_pid(value) { @@ -282,7 +282,7 @@ function make_ref() { } function map_size(map) { - return Object.keys(map).length; + return map.size; } function max(first, second) { diff --git a/src/javascript/lib/core/erlang_compat/maps.js b/src/javascript/lib/core/erlang_compat/maps.js index 142a031f..9f0686c3 100644 --- a/src/javascript/lib/core/erlang_compat/maps.js +++ b/src/javascript/lib/core/erlang_compat/maps.js @@ -12,7 +12,7 @@ function find(key, map) { return new ErlangTypes.Tuple(BADMAP, map); } - const value = map[key]; + const value = map.get(key); if (typeof value !== 'undefined') { return new ErlangTypes.Tuple(OK, value); @@ -24,7 +24,7 @@ function find(key, map) { function fold(fun, init, map) { let acc = init; - for (const [key, value] of to_list(map)) { + for (const [key, value] of map.entries()) { acc = fun(key, value, acc); } @@ -36,9 +36,9 @@ function remove(key, map1) { return new ErlangTypes.Tuple(BADMAP, map1); } - const map2 = Object.assign({}, map1); + const map2 = new Map(map1); - delete map2[key]; + map2.delete(key); return map2; } @@ -50,8 +50,8 @@ function to_list(map) { const list = []; - for (const key of keys(map)) { - list.push(new ErlangTypes.Tuple(key, map[key])); + for (const [key, value] of map.entries()) { + list.push(new ErlangTypes.Tuple(key, value)); } return list; @@ -60,10 +60,10 @@ function to_list(map) { function from_list(list) { return list.reduce((acc, item) => { const [key, value] = item; - acc[key] = value; + acc.set(key, value); return acc; - }, {}); + }, new Map()); } function keys(map) { @@ -71,17 +71,7 @@ function keys(map) { return new ErlangTypes.Tuple(BADMAP, map); } - const keys = []; - - for (const key of Object.getOwnPropertySymbols(map)) { - keys.push(key); - } - - for (const key of Object.getOwnPropertyNames(map)) { - keys.push(key); - } - - return keys; + return Array.from(map.keys()); } function values(map) { @@ -89,17 +79,11 @@ function values(map) { return new ErlangTypes.Tuple(BADMAP, map); } - const theValues = []; - - for (const key of keys(map)) { - theValues.push(map[key]); - } - - return theValues; + return Array.from(map.values()); } function is_key(key, map) { - return map.hasOwnProperty(key); + return map.has(key); } function put(key, value, map1) { @@ -107,7 +91,8 @@ function put(key, value, map1) { return new ErlangTypes.Tuple(BADMAP, map1); } - const map2 = Object.assign({}, map1, { [key]: value }); + const map2 = new Map(map1); + map2.set(key, value); return map2; } @@ -121,7 +106,7 @@ function merge(map1, map2) { return new ErlangTypes.Tuple(BADMAP, map2); } - return Object.assign({}, map1, map2); + return new Map([...map1, ...map2]); } function update(key, value, map1) { @@ -133,7 +118,7 @@ function update(key, value, map1) { return new ErlangTypes.Tuple(BADKEY, key); } - return Object.assign({}, map1, { [key]: value }); + return new Map([...map1, [key, value]]); } function get(...args) { @@ -145,7 +130,7 @@ function get(...args) { } if (is_key(key)) { - return map[key]; + return map.get(key); } if (args.length === 3) { @@ -164,9 +149,9 @@ function take(key, map1) { return ERROR; } - const value = map1[key]; - const map2 = Object.assign({}, map1); - delete map2[key]; + const value = map1.get(key); + const map2 = new Map(map1); + map2.delete(key); return new ErlangTypes.Tuple(value, map2); } diff --git a/src/javascript/lib/core/functions.js b/src/javascript/lib/core/functions.js index d315dab9..97a18379 100644 --- a/src/javascript/lib/core/functions.js +++ b/src/javascript/lib/core/functions.js @@ -31,6 +31,28 @@ function call_property(item, property) { return item; } + if (item instanceof Map) { + let prop = null; + + if (item.has(property)) { + prop = property; + } else if (item.has(Symbol.for(property))) { + prop = Symbol.for(property); + } + + if (prop === null) { + throw new Error(`Property ${property} not found in ${item}`); + } + + if ( + item.get(prop) instanceof Function || + typeof item.get(prop) === 'function' + ) { + return item.get(prop)(); + } + return item.get(prop); + } + let prop = null; if ( diff --git a/src/javascript/lib/core/protocol.js b/src/javascript/lib/core/protocol.js index 5ae04ddf..ac292a81 100644 --- a/src/javascript/lib/core/protocol.js +++ b/src/javascript/lib/core/protocol.js @@ -31,12 +31,12 @@ class Protocol { fun = this.registry.get(Core.BitString)[funName]; } else if ( thing && - thing[Symbol.for('__struct__')] && + thing.has(Symbol.for('__struct__')) && this.hasImplementation(thing) ) { - fun = this.registry.get(thing[Symbol.for('__struct__')].__MODULE__)[ - funName - ]; + fun = this.registry.get( + thing.get(Symbol.for('__struct__')).__MODULE__ + )[funName]; } else if (thing !== null && this.hasImplementation(thing)) { fun = this.registry.get(thing.constructor)[funName]; } else if (this.fallback) { @@ -72,8 +72,8 @@ class Protocol { thing === Core.BitString ) { return this.registry.has(thing); - } else if (thing && thing[Symbol.for('__struct__')]) { - return this.registry.has(thing[Symbol.for('__struct__')].__MODULE__); + } else if (thing && thing.has(Symbol.for('__struct__'))) { + return this.registry.has(thing.get(Symbol.for('__struct__')).__MODULE__); } return this.registry.has(thing.constructor); diff --git a/test/support/main.ex b/test/support/main.ex index a18d3d90..a2260e63 100644 --- a/test/support/main.ex +++ b/test/support/main.ex @@ -1,5 +1,7 @@ defmodule Main do def start(:normal, [callback]) do callback.("started") + + Enum.map(1..5, fn(x) -> x * 2 end) end end diff --git a/yarn.lock b/yarn.lock index 4c47311a..0c91a8ec 100644 --- a/yarn.lock +++ b/yarn.lock @@ -605,6 +605,10 @@ babel-plugin-syntax-exponentiation-operator@^6.8.0: version "6.13.0" resolved "https://registry.yarnpkg.com/babel-plugin-syntax-exponentiation-operator/-/babel-plugin-syntax-exponentiation-operator-6.13.0.tgz#9ee7e8337290da95288201a6a57f4170317830de" +babel-plugin-syntax-object-rest-spread@^6.8.0: + version "6.13.0" + resolved "https://registry.yarnpkg.com/babel-plugin-syntax-object-rest-spread/-/babel-plugin-syntax-object-rest-spread-6.13.0.tgz#fd6536f2bce13836ffa3a5458c4903a597bb3bf5" + babel-plugin-syntax-trailing-function-commas@^6.20.0, babel-plugin-syntax-trailing-function-commas@^6.22.0: version "6.22.0" resolved "https://registry.yarnpkg.com/babel-plugin-syntax-trailing-function-commas/-/babel-plugin-syntax-trailing-function-commas-6.22.0.tgz#ba0360937f8d06e40180a43fe0d5616fff532cf3" @@ -809,6 +813,13 @@ babel-plugin-transform-minify-booleans@^6.8.2: version "6.8.2" resolved "https://registry.yarnpkg.com/babel-plugin-transform-minify-booleans/-/babel-plugin-transform-minify-booleans-6.8.2.tgz#8451579f706e702c1e1ab2756de5c8ea369cf07c" +babel-plugin-transform-object-rest-spread@^6.23.0: + version "6.23.0" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-object-rest-spread/-/babel-plugin-transform-object-rest-spread-6.23.0.tgz#875d6bc9be761c58a2ae3feee5dc4895d8c7f921" + dependencies: + babel-plugin-syntax-object-rest-spread "^6.8.0" + babel-runtime "^6.22.0" + babel-plugin-transform-property-literals@^6.8.4: version "6.8.4" resolved "https://registry.yarnpkg.com/babel-plugin-transform-property-literals/-/babel-plugin-transform-property-literals-6.8.4.tgz#6ad311110b80a192a56efb5ddf4fe3ca6f7a61da" @@ -3678,9 +3689,9 @@ table@^4.0.1: slice-ansi "0.0.4" string-width "^2.0.0" -tailored@^2.6.0: - version "2.6.0" - resolved "https://registry.yarnpkg.com/tailored/-/tailored-2.6.0.tgz#70ae98b8f8bfb25ce320290c103cbc23aae4cf2a" +tailored@^2.6.1: + version "2.6.1" + resolved "https://registry.yarnpkg.com/tailored/-/tailored-2.6.1.tgz#afac1114f4622eceba11d87fcc35b42a658ded84" dependencies: erlang-types "^1.0.1" From 049d1b4444102652ae0c7e3372e798221189ba19 Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Wed, 19 Jul 2017 20:24:48 -0500 Subject: [PATCH 622/860] Remove mutate/2 Fix broken tests --- CHANGELOG.md | 1 - lib/elixir_script/lib/js.ex | 9 +-- test/passes/translate/forms/js_test.exs | 34 +-------- test/passes/translate/forms/map_test.exs | 87 +++++++++++++----------- 4 files changed, 52 insertions(+), 79 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index c164ace1..fb472034 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,7 +8,6 @@ and this project adheres to [Semantic Versioning](http://semver.org/). ### Added - ElixirScript now has an FFI layer for interoperability with JavaScript. For more details, see documentation at `ElixirScript.FFI` -- ElixirScript.JS.mutate/2 - ElixirScript.JS.mutate/3 ### Changed diff --git a/lib/elixir_script/lib/js.ex b/lib/elixir_script/lib/js.ex index 2c14151c..44f55f5a 100644 --- a/lib/elixir_script/lib/js.ex +++ b/lib/elixir_script/lib/js.ex @@ -38,17 +38,10 @@ defmodule ElixirScript.JS do """ defmacro this() - @doc """ - Mutates an existing JavaScript object. - ex: - ElixirScript.JS.mutate elem, %{"width" => 100} - """ - defmacro update(object, map) - @doc """ Mutates an existing JavaScript object. ex: ElixirScript.JS.mutate elem, "width", 100 """ - defmacro update(object, key, value) + defmacro mutate(object, key, value) end diff --git a/test/passes/translate/forms/js_test.exs b/test/passes/translate/forms/js_test.exs index 7afd866c..d9f556cd 100644 --- a/test/passes/translate/forms/js_test.exs +++ b/test/passes/translate/forms/js_test.exs @@ -65,48 +65,18 @@ defmodule ElixirScript.Translate.Forms.JS.Test do ) end - test "mutate/2" do - properties = [{"a", 1}] - map_ast = {:%{}, [], properties} - - ast = {{:., [], [ElixirScript.JS, :mutate]}, [], [{:%{}, [], []}, map_ast]} - state = %{function: {:each, nil}, module: Enum, vars: %{:_ => 0, "entry" => 0, "enumerable" => 0, "fun" => 0}} - - {js_ast, _} = Form.compile(ast, state) - assert js_ast == J.call_expression( - J.member_expression( - J.identifier("Object"), - J.identifier("assign") - ), - [ - J.object_expression([]), - J.object_expression([ - J.property( - J.identifier("a"), - J.literal(1) - ) - ]) - ] - ) - end - test "mutate/3" do properties = [{"a", 1}] map_ast = {:%{}, [], properties} - ast = {{:., [], [ElixirScript.JS, :mutate]}, [], [map_ast, "a", 2]} + ast = {{:., [], [ElixirScript.JS, :mutate]}, [], [{:entry, [], nil}, "a", 2]} state = %{function: {:each, nil}, module: Enum, vars: %{:_ => 0, "entry" => 0, "enumerable" => 0, "fun" => 0}} {js_ast, _} = Form.compile(ast, state) assert js_ast == J.assignment_expression( :=, J.member_expression( - J.object_expression([ - J.property( - J.identifier("a"), - J.literal(1) - ) - ]), + J.identifier("entry0"), J.literal("a"), true ), diff --git a/test/passes/translate/forms/map_test.exs b/test/passes/translate/forms/map_test.exs index ad826766..a94b454a 100644 --- a/test/passes/translate/forms/map_test.exs +++ b/test/passes/translate/forms/map_test.exs @@ -9,19 +9,23 @@ defmodule ElixirScript.Translate.Forms.Map.Test do state = %{} {js_ast, _} = Form.compile(ast, state) - assert js_ast == J.object_expression([ - J.property( - J.call_expression( - J.member_expression( - J.identifier("Symbol"), - J.identifier("for") - ), - [J.literal(:a)] - ), - J.literal(1), - :init, false, false, true - ) - ]) + assert js_ast == J.new_expression( + J.identifier("Map"), + [ + J.array_expression([ + J.array_expression([ + J.call_expression( + J.member_expression( + J.identifier("Symbol"), + J.identifier("for") + ), + [J.literal(:a)] + ), + J.literal(1), + ]) + ]) + ] + ) end test "map with string key" do @@ -30,12 +34,17 @@ defmodule ElixirScript.Translate.Forms.Map.Test do state = %{} {js_ast, _} = Form.compile(ast, state) - assert js_ast == J.object_expression([ - J.property( - J.identifier("a"), - J.literal(1) - ) - ]) + assert js_ast == J.new_expression( + J.identifier("Map"), + [ + J.array_expression([ + J.array_expression([ + J.literal("a"), + J.literal(1), + ]) + ]) + ] + ) end @@ -47,28 +56,30 @@ defmodule ElixirScript.Translate.Forms.Map.Test do ast = {:%{}, [], [{:|, [], [map_ast, new_values]}]} + map_ast = J.new_expression( + J.identifier("Map"), + [ + J.array_expression([ + J.array_expression([ + J.literal("a"), + J.literal(1), + ]) + ]) + ] + ) + {js_ast, _} = Form.compile(ast, state) - assert js_ast == J.call_expression( - J.member_expression( - J.identifier("Object"), - J.identifier("assign") - ), + assert js_ast == J.new_expression( + J.identifier("Map"), [ - J.object_expression([]), - J.object_expression([ - J.property( - J.identifier("a"), - J.literal(1) - ) - ]), - J.object_expression([ - J.property( - J.identifier("a"), - J.literal(2) - ) - ]) + J.array_expression( + [J.spread_element(map_ast)] ++ [J.array_expression([ + J.literal("a"), + J.literal(2) + ])] + ) ] ) end -end \ No newline at end of file +end From cf00817fff9e288b67151c69cb15078ba7d55590 Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Thu, 20 Jul 2017 19:53:51 -0500 Subject: [PATCH 623/860] Add ElixirScript.JS.map_to_object/1 --- lib/elixir_script/lib/js.ex | 10 ++++++++++ .../passes/translate/forms/js.ex | 20 ++++++++++++++++++- priv/build/iife/ElixirScript.Core.js | 4 ++-- src/javascript/lib/core/functions.js | 17 +++++++++++++++- 4 files changed, 47 insertions(+), 4 deletions(-) diff --git a/lib/elixir_script/lib/js.ex b/lib/elixir_script/lib/js.ex index 44f55f5a..8e255cfc 100644 --- a/lib/elixir_script/lib/js.ex +++ b/lib/elixir_script/lib/js.ex @@ -44,4 +44,14 @@ defmodule ElixirScript.JS do ElixirScript.JS.mutate elem, "width", 100 """ defmacro mutate(object, key, value) + + + @doc """ + Takes the given map and returns an object + Throws an error if any key is not a + number, binary, or atom + ex: + ElixirScript.JS.map_to_object(%{my: "map"}) + """ + defmacro map_to_object(object) end diff --git a/lib/elixir_script/passes/translate/forms/js.ex b/lib/elixir_script/passes/translate/forms/js.ex index b4c7c614..a55f0899 100644 --- a/lib/elixir_script/passes/translate/forms/js.ex +++ b/lib/elixir_script/passes/translate/forms/js.ex @@ -91,8 +91,26 @@ defmodule ElixirScript.Translate.Forms.JS do Form.compile!(key, state), true ), + Form.compile!(value, state) + ) + + {ast, state} + end + + def compile({{:., _, [ElixirScript.JS, :map_to_object]}, _, [object]}, state) do + ast = J.call_expression( + J.member_expression( + J.member_expression( + J.identifier("ElixirScript"), + J.member_expression( + J.identifier("Core"), + J.identifier("Functions") + ) + ), + J.identifier("map_to_object") + ), [ - Form.compile!(value, state) + Form.compile!(object, state) ] ) diff --git a/priv/build/iife/ElixirScript.Core.js b/priv/build/iife/ElixirScript.Core.js index 45c27597..42035b8b 100644 --- a/priv/build/iife/ElixirScript.Core.js +++ b/priv/build/iife/ElixirScript.Core.js @@ -1,6 +1,6 @@ -var ElixirScript=function(){'use strict';/* @flow */function namedVariableResult(a,b){return new NamedVariableResult(a,b)}/* @flow */function is_number(a){return'number'==typeof a}function is_string(a){return'string'==typeof a}function is_boolean(a){return'boolean'==typeof a}function is_symbol(a){return'symbol'==typeof a}function is_object(a){return'object'==typeof a}function is_variable(a){return a instanceof Variable}function is_null(a){return null===a}function is_array(a){return Array.isArray(a)}function is_function(a){return'[object Function]'==Object.prototype.toString.call(a)}function is_map(a){return a instanceof Map}function resolveNull(){return function(a){return is_null(a)}}function resolveWildcard(){return function(){return!0}}function resolveObject(a){let b={};const c=Object.keys(a).concat(Object.getOwnPropertySymbols(a));for(let d of c)b[d]=buildMatch(a[d]);return function(d,e){if(!is_object(d)||a.length>d.length)return!1;for(let a of c)if(!(a in d)||!b[a](d[a],e))return!1;return!0}}function getSize(a,b){return a*b/8}function arraysEqual(c,a){if(c===a)return!0;if(null==c||null==a)return!1;if(c.length!=a.length)return!1;for(var b=0;be.integer(a));return new e(...b)}function resolveNoMatch(){return function(){return!1}}function buildMatch(a){if(null===a)return resolveNull(a);if('undefined'==typeof a)return resolveWildcard(a);const b=a.constructor.prototype,c=f.get(b);return c?c(a):'object'==typeof a?resolveObject(a):resolveNoMatch()}function defmatchgen(...a){const b=getArityMap(a);return function*(...a){let[c,d]=findMatchingFunction(a,b);return yield*c.apply(this,d)}}function findMatchingFunction(a,b){if(b.has(a.length)){const c=b.get(a.length);let d=null,e=null;for(let b of c){let c=[];a=fillInOptionalValues(a,b.arity,b.optionals);const f=b.pattern(a,c),[g,h]=checkNamedVariables(c);if(f&&h&&b.guard.apply(this,g)){d=b.fn,e=g;break}}if(!d)throw console.error('No match for:',a),new MatchError(a);return[d,e]}throw console.error('Arity of',a.length,'not found. No match for:',a),new MatchError(a)}function getArityMap(a){let b=new Map;for(const c of a){const a=getArityRange(c);for(const d of a){let a=[];b.has(d)&&(a=b.get(d)),a.push(c),b.set(d,a)}}return b}function getArityRange(a){const b=a.arity-a.optionals.length,c=a.arity;let d=[b];for(;d[d.length-1]!=c;)d.push(d[d.length-1]+1);return d}function getOptionalValues(a){let b=[];for(let c=0;c!0,d=null){let e=[],f=buildMatch(a);const g=f(b,e),[h,i]=checkNamedVariables(e);return g&&i&&c.apply(this,h)?h:d}function run_generators(a,b){if(0==b.length)return a.map((a)=>{return Array.isArray(a)?a:[a]});const c=b.pop();let d=[];for(let e of c())for(let b of a)d.push([e].concat(b));return run_generators(d,b)}function iterator_to_reducer(a,b,c){const d=a[Symbol.iterator]();let e=d.next(),f=b;for(;!1===e.done;){if(f=c(e.value,f.get(1)),f.get(0)===Symbol.for('halt'))return new n.Tuple(Symbol.for('halted'),f.get(1));if(f.get(0)===Symbol.for('suspend'))return new n.Tuple(Symbol.for('suspended'),f.get(1),(a)=>{return iterator_to_reducer(d,a,c)});e=d.next()}return new n.Tuple(Symbol.for('done'),f.get(1))}function run_list_generators(a,b){if(0==b.length)return a.map((a)=>{return Array.isArray(a)?a:[a]});const c=b.pop(),d=[];for(const e of c())for(const b of a)d.push([e].concat(b));return run_list_generators(d,b)}// http://erlang.org/doc/man/erlang.html +var ElixirScript=function(){'use strict';/* @flow */function namedVariableResult(a,b){return new NamedVariableResult(a,b)}/* @flow */function is_number(a){return'number'==typeof a}function is_string(a){return'string'==typeof a}function is_boolean(a){return'boolean'==typeof a}function is_symbol(a){return'symbol'==typeof a}function is_object(a){return'object'==typeof a}function is_variable(a){return a instanceof Variable}function is_null(a){return null===a}function is_array(a){return Array.isArray(a)}function is_function(a){return'[object Function]'==Object.prototype.toString.call(a)}function is_map(a){return a instanceof Map}function resolveNull(){return function(a){return is_null(a)}}function resolveWildcard(){return function(){return!0}}function resolveObject(a){let b={};const c=Object.keys(a).concat(Object.getOwnPropertySymbols(a));for(let d of c)b[d]=buildMatch(a[d]);return function(d,e){if(!is_object(d)||a.length>d.length)return!1;for(let a of c)if(!(a in d)||!b[a](d[a],e))return!1;return!0}}function getSize(a,b){return a*b/8}function arraysEqual(c,a){if(c===a)return!0;if(null==c||null==a)return!1;if(c.length!=a.length)return!1;for(var b=0;be.integer(a));return new e(...b)}function resolveNoMatch(){return function(){return!1}}function buildMatch(a){if(null===a)return resolveNull(a);if('undefined'==typeof a)return resolveWildcard(a);const b=a.constructor.prototype,c=f.get(b);return c?c(a):'object'==typeof a?resolveObject(a):resolveNoMatch()}function defmatchgen(...a){const b=getArityMap(a);return function*(...a){let[c,d]=findMatchingFunction(a,b);return yield*c.apply(this,d)}}function findMatchingFunction(a,b){if(b.has(a.length)){const c=b.get(a.length);let d=null,e=null;for(let b of c){let c=[];a=fillInOptionalValues(a,b.arity,b.optionals);const f=b.pattern(a,c),[g,h]=checkNamedVariables(c);if(f&&h&&b.guard.apply(this,g)){d=b.fn,e=g;break}}if(!d)throw console.error('No match for:',a),new MatchError(a);return[d,e]}throw console.error('Arity of',a.length,'not found. No match for:',a),new MatchError(a)}function getArityMap(a){let b=new Map;for(const c of a){const a=getArityRange(c);for(const d of a){let a=[];b.has(d)&&(a=b.get(d)),a.push(c),b.set(d,a)}}return b}function getArityRange(a){const b=a.arity-a.optionals.length,c=a.arity;let d=[b];for(;d[d.length-1]!=c;)d.push(d[d.length-1]+1);return d}function getOptionalValues(a){let b=[];for(let c=0;c!0,d=null){let e=[],f=buildMatch(a);const g=f(b,e),[h,i]=checkNamedVariables(e);return g&&i&&c.apply(this,h)?h:d}function run_generators(a,b){if(0==b.length)return a.map((a)=>{return Array.isArray(a)?a:[a]});const c=b.pop();let d=[];for(let e of c())for(let b of a)d.push([e].concat(b));return run_generators(d,b)}function iterator_to_reducer(a,b,c){const d=a[Symbol.iterator]();let e=d.next(),f=b;for(;!1===e.done;){if(f=c(e.value,f.get(1)),f.get(0)===Symbol.for('halt'))return new n.Tuple(Symbol.for('halted'),f.get(1));if(f.get(0)===Symbol.for('suspend'))return new n.Tuple(Symbol.for('suspended'),f.get(1),(a)=>{return iterator_to_reducer(d,a,c)});e=d.next()}return new n.Tuple(Symbol.for('done'),f.get(1))}function map_to_object(a){const b={};for(const[c,d]of a.entries())b[c]=d instanceof Map?map_to_object(d):d;return b}function run_list_generators(a,b){if(0==b.length)return a.map((a)=>{return Array.isArray(a)?a:[a]});const c=b.pop(),d=[];for(const e of c())for(const b of a)d.push([e].concat(b));return run_list_generators(d,b)}// http://erlang.org/doc/man/erlang.html function atom_to_binary(a,b=Symbol.for('utf8')){if(b!==Symbol.for('utf8'))throw new Error(`unsupported encoding ${b}`);return a.__MODULE__?Symbol.keyFor(a.__MODULE__):Symbol.keyFor(a)}function binary_to_atom(a,b=Symbol.for('utf8')){if(b!==Symbol.for('utf8'))throw new Error(`unsupported encoding ${b}`);return Symbol.for(a)}function is_number$1(a){return'number'==typeof a||a instanceof Number}function is_key(a,b){return b.has(a)}// http://erlang.org/doc/man/lists.html function reverse(a){return[...a]}function flatten(a,b=[]){const c=a.reduce((a,b)=>{return Array.isArray(b)?a.concat(flatten(b)):a.concat(b)},[]);return c.concat(b)}function foldl(a,b,c){return c.reduce((b,c)=>{return a(c,b)},b)}function keyfind(a,b,c){for(const d of c)if(d.get(b-1)===a)return d;return!1}function keydelete(a,b,c){const d=[];let e=!1;for(let f=0;fBitString$1.integer(a));return new BitString$1(...d)}[Symbol.iterator](){return this.value[Symbol.iterator]()}toString(){var a,b='';for(a=0;a>'}process(a){let b=[];var c;for(c=0;cb?c.push(b):2048>b?c.push(192|b>>6,128|63&b):55296>b||57344<=b?c.push(224|b>>12,128|63&b>>6,128|63&b):(d++,b=65536+((1023&b)<<10|1023&a.charCodeAt(d)),c.push(240|b>>18,128|63&b>>12,128|63&b>>6,128|63&b));return c}static toUTF16Array(a){for(var b,c=[],d=0;d=b?(c.push(0),c.push(b)):(c.push(255&b>>8),c.push(255&b));return c}static toUTF32Array(a){for(var b,c=[],d=0;d=b?(c.push(0),c.push(0),c.push(0),c.push(b)):(c.push(0),c.push(0),c.push(255&b>>8),c.push(255&b));return c}//http://stackoverflow.com/questions/2003493/javascript-float-from-to-bits static float32ToBytes(a){var b=[],c=new ArrayBuffer(4);new Float32Array(c)[0]=a;let d=new Uint32Array(c)[0];return b.push(255&d>>24),b.push(255&d>>16),b.push(255&d>>8),b.push(255&d),b}static float64ToBytes(a){var b=[],c=new ArrayBuffer(8);new Float64Array(c)[0]=a;var d=new Uint32Array(c)[0],e=new Uint32Array(c)[1];return b.push(255&e>>24),b.push(255&e>>16),b.push(255&e>>8),b.push(255&e),b.push(255&d>>24),b.push(255&d>>16),b.push(255&d>>8),b.push(255&d),b}}var d={Tuple,PID:class PID{constructor(){++b,this.id=b}toString(){return'PID#<0.'+this.id+'.0>'}},Reference:class Reference{constructor(){++c,this.id=c,this.ref=Symbol()}toString(){return'Ref#<0.0.0.'+this.id+'>'}},BitString:BitString$1};/* @flow */const e=d.BitString,f=new Map;f.set(Variable.prototype,function resolveVariable(a){return function(b,c){return null===a.name||a.name.startsWith('_')?c.push(b):c.push(namedVariableResult(a.name,b)),!0}}),f.set(Wildcard.prototype,resolveWildcard),f.set(HeadTail.prototype,function resolveHeadTail(){return function(a,b){if(!is_array(a)||2>a.length)return!1;const c=a[0],d=a.slice(1);return b.push(c),b.push(d),!0}}),f.set(StartsWith.prototype,function resolveStartsWith(a){const b=a.prefix;return function(a,c){return is_string(a)&&a.startsWith(b)&&(c.push(a.substring(b.length)),!0)}}),f.set(Capture.prototype,function resolveCapture(a){const b=buildMatch(a.value);return function(a,c){return!!b(a,c)&&(c.push(a),!0)}}),f.set(Bound.prototype,function resolveBound(a){return function(b){return typeof b==typeof a.value&&b===a.value}}),f.set(Type.prototype,function resolveType(a){return function(b,c){if(b instanceof a.type){const d=buildMatch(a.objPattern);return d(b,c)}return!1}}),f.set(BitStringMatch.prototype,function resolveBitString(a){let b=[];for(let c of a.values)if(is_variable(c.value)){let a=getSize(c.unit,c.size);fillArray(b,a)}else b=b.concat(new e(c).value);let c=a.values;return function(a,d){var f=String.fromCharCode;let g=null;if(!is_string(a)&&!(a instanceof e))return!1;g=is_string(a)?new e(e.binary(a)):a;let h=0;for(let e,j=0;jd.size)return!1;for(let a of c)if(!d.has(a)||!b.get(a)(d.get(a),e))return!1;return!0}}),f.set(Array.prototype,function resolveArray(a){const b=a.map((a)=>buildMatch(a));return function(c,d){return is_array(c)&&c.length==a.length&&c.every(function(a,e){return b[e](c[e],d)})}}),f.set(String.prototype,function resolveString(a){return function(b){return is_string(b)&&b===a}}),f.set(Boolean.prototype,function resolveBoolean(a){return function(b){return is_boolean(b)&&b===a}}),f.set(Function.prototype,function resolveFunction(a){return function(b){return is_function(b)&&b===a}}),f.set(Object.prototype,resolveObject);class MatchError extends Error{constructor(a){if(super(),'symbol'==typeof a)this.message='No match for: '+a.toString();else if(Array.isArray(a)){let b=a.map((a)=>{return null===a?'null':'undefined'==typeof a?'undefined':a.toString()});this.message='No match for: '+b}else this.message='No match for: '+a;this.stack=new Error().stack,this.name=this.constructor.name}}class Clause{constructor(a,b,c=()=>!0){this.pattern=buildMatch(a),this.arity=a.length,this.optionals=getOptionalValues(a),this.fn=b,this.guard=c}}const g=Symbol();// https://github.com/airportyh/protomorphism class Protocol{constructor(b){function createFun(b){return function(...c){const d=c[0];let e=null;if(null===d&&this.hasImplementation(Symbol('null'))?e=this.registry.get(Symbol)[b]:a(d)&&this.hasImplementation(n.Integer)?e=this.registry.get(n.Integer)[b]:'number'==typeof d&&!a(d)&&this.hasImplementation(n.Float)?e=this.registry.get(n.Float)[b]:'string'==typeof d&&this.hasImplementation(n.BitString)?e=this.registry.get(n.BitString)[b]:d&&d.has(Symbol.for('__struct__'))&&this.hasImplementation(d)?e=this.registry.get(d.get(Symbol.for('__struct__')).__MODULE__)[b]:null!==d&&this.hasImplementation(d)?e=this.registry.get(d.constructor)[b]:this.fallback&&(e=this.fallback[b]),null!=e){const a=e.apply(this,c);return a}throw new Error(`No implementation found for ${d}`)}}for(const a in this.registry=new Map,this.fallback=null,b)this[a]=createFun(a).bind(this)}implementation(a,b){null===a?this.fallback=b:this.registry.set(a,b)}hasImplementation(a){if(a===n.Integer||a===n.Float||a===n.BitString)return this.registry.has(a);return a&&a.has(Symbol.for('__struct__'))?this.registry.has(a.get(Symbol.for('__struct__')).__MODULE__):this.registry.has(a.constructor)}}var h={atom_to_binary,binary_to_atom,binary_to_existing_atom:function binary_to_existing_atom(a,b=Symbol.for('utf8')){return binary_to_atom(a,b)},list_concatenation:function list_concatenation(a,b){return a.concat(b)},list_subtraction:function list_subtraction(a,b){const c=[...a];for(const d of b){const a=c.indexOf(d);-1b},greaterThanOrEqualTo:function greaterThanOrEqualTo(a,b){return a>=b},lessThan:function lessThan(a,b){return a>b},bxor:function bxor(a,b){return a^b},bnot:function bnot(a){return~a},is_bitstring:function is_bitstring$1(a){return a instanceof d.BitString},is_boolean:function is_boolean$1(a){return'boolean'==typeof a||a instanceof Boolean},is_float:function is_float(b){return is_number$1(b)&&!a(b)},is_function:function is_function$1(a){return'function'==typeof a||a instanceof Function},is_integer:function is_integer(b){return a(b)},is_list:function is_list(a){return Array.isArray(a)},is_map:function is_map$1(a){return a instanceof Map},is_number:is_number$1,is_pid:function is_pid(a){return a instanceof d.PID},is_port:function is_port(){return!1},is_reference:function is_reference(a){return a instanceof d.Reference},is_tuple:function is_tuple(a){return a instanceof d.Tuple},is_atom:function is_atom(a){return'symbol'==typeof a||a instanceof Symbol||a.__MODULE__},is_binary:function is_binary(a){return'string'==typeof a||a instanceof String},element:function element(a,b){return b.get(a-1)},setelement:function setelement(a,b,c){const e=[...b.values];return e[a-1]=c,new d.Tuple(...e)},make_tuple:function make_tuple(a,b){const c=[];for(let d=0;d!0){let d=[],e=buildMatch(a);const f=e(b,d),[g,h]=checkNamedVariables(d);if(f&&h&&c.apply(this,g))return g;throw console.error('No match for:',b),new MatchError(b)},MatchError,variable:function variable(a=null,b=Symbol.for('tailored.no_value')){return new Variable(a,b)},wildcard:function wildcard(){return new Wildcard},startsWith:function startsWith(a){return new StartsWith(a)},capture:function capture(a){return new Capture(a)},headTail:function headTail(){return new HeadTail},type:function a(a,b={}){return new Type(a,b)},bound:function bound(a){return new Bound(a)},Clause,clause:function clause(a,b,c=()=>!0){return new Clause(a,b,c)},bitStringMatch:function bitStringMatch(...a){return new BitStringMatch(...a)},match_or_default,defmatchgen,list_comprehension:function list_comprehension(a,b){const c=run_generators(b.pop()(),b);let d=[];for(let e of c)a.guard.apply(this,e)&&d.push(a.fn.apply(this,e));return d},list_generator:function list_generator(a,b){return function(){let c=[];for(let d of b){const b=match_or_default(a,d,()=>!0,g);if(b!=g){const[a]=b;c.push(a)}}return c}},bitstring_generator:function bitstring_generator(a,b){return function(){let c=[],d=b.slice(0,a.byte_size()),e=1;for(;d.byte_size==a.byte_size();){const f=match_or_default(a,d,()=>!0,g);if(f!=g){c.push(f)}d=b.slice(a.byte_size()*e,a.byte_size()*(e+1)),e++}return c}},bitstring_comprehension:function bitstring_comprehension(a,b){const c=run_generators(b.pop()(),b);let e=[];for(let d of c)a.guard.apply(this,d)&&e.push(a.fn.apply(this,d));return e=e.map((a)=>d.BitString.integer(a)),new d.BitString(...e)},defmatchGen:function defmatchGen(...a){return defmatchgen(...a)},defmatchAsync:function defmatchAsync(...a){const b=getArityMap(a);return async function(...a){if(b.has(a.length)){const c=b.get(a.length);let d=null,e=null;for(let b of c){let c=[];a=fillInOptionalValues(a,b.arity,b.optionals);const f=b.pattern(a,c),[g,h]=checkNamedVariables(c);if(f&&h&&(await b.guard.apply(this,c))){d=b.fn,e=c;break}}if(!d)throw console.error('No match for:',a),new MatchError(a);return d.apply(this,e)}throw console.error('Arity of',a.length,'not found. No match for:',a),new MatchError(a)}}},Integer:class Integer{},Float:class Float{},Functions:{call_property:function call_property(a,b){if(!b)return a instanceof Function||'function'==typeof a?a():a;if(a instanceof Map){let c=null;if(a.has(b)?c=b:a.has(Symbol.for(b))&&(c=Symbol.for(b)),null===c)throw new Error(`Property ${b} not found in ${a}`);return a.get(c)instanceof Function||'function'==typeof a.get(c)?a.get(c)():a.get(c)}let c=null;if('number'==typeof a||'symbol'==typeof a||'boolean'==typeof a||'string'==typeof a?void 0===a[b]?void 0!==a[Symbol.for(b)]&&(c=Symbol.for(b)):c=b:b in a?c=b:Symbol.for(b)in a&&(c=Symbol.for(b)),null===c)throw new Error(`Property ${b} not found in ${a}`);return a[c]instanceof Function||'function'==typeof a[c]?a[c]():a[c]},defprotocol:function defprotocol(a){return new Protocol(a)},defimpl:function defimpl(a,b,c){a.implementation(b,c)},build_namespace:function build_namespace(a,b){let c=b.split('.');const d=a;let e=a;'Elixir'===c[0]&&(c=c.slice(1));for(const d of c)'undefined'==typeof e[d]&&(e[d]={}),e=e[d];return d.__table__=a.__table__||{},d.__table__[Symbol.for(b)]=e,e},iterator_to_reducer},SpecialForms:{_case:function _case(a,b){return n.Patterns.defmatch(...b)(a)},cond:function cond(...a){for(const b of a)if(b[0])return b[1]();throw new Error},_for:function _for(a,b,c,d=[]){let[e,f]=c.into(d);const g=run_list_generators(b.pop()(),b);for(const h of g)a.guard.apply(this,h)&&(e=f(e,new n.Tuple(Symbol.for('cont'),a.fn.apply(this,h))));return f(e,Symbol.for('done'))},_try:function _try(a,b,c,d,e){let f=null;try{f=a()}catch(a){let d=null;if(b)try{return d=b(a),d}catch(a){if(a instanceof n.Patterns.MatchError)throw a}if(c)try{return d=c(a),d}catch(a){if(a instanceof n.Patterns.MatchError)throw a}throw a}finally{e&&e()}if(d)try{return d(f)}catch(a){if(a instanceof n.Patterns.MatchError)throw new Error('No Match Found in Else');throw a}else return f},_with:function _with(...a){let b=[],c=null,d=null;'function'==typeof a[a.length-2]?[c,d]=a.splice(-2):c=a.pop();for(let c=0;c{const[c,d]=b;return a.set(c,d),a},new Map)},keys:function keys(a){return!1===h.is_map(a)?new d.Tuple(k,a):Array.from(a.keys())},values:function values$1(a){return!1===h.is_map(a)?new d.Tuple(k,a):Array.from(a.values())},is_key,put:function put(a,b,c){if(!1===h.is_map(c))return new d.Tuple(k,c);const e=new Map(c);return e.set(a,b),e},merge:function merge(a,b){return!1===h.is_map(a)?new d.Tuple(k,a):!1===h.is_map(b)?new d.Tuple(k,b):new Map([...a,...b])},update:function update(a,b,c){return!1===h.is_map(c)?new d.Tuple(k,c):!1===is_key(a,c)?new d.Tuple(l,a):new Map([...c,[a,b]])},get:function get(...a){const b=a[0],c=a[1];return!1===h.is_map(c)?new d.Tuple(k,c):is_key(b)?c.get(b):3===a.length?a[2]:new d.Tuple(l,b)},take:function take(a,b){if(!1===h.is_map(b))return new d.Tuple(k,b);if(!is_key(a))return j;const c=b.get(a),e=new Map(b);return e.delete(a),new d.Tuple(c,e)}},lists:{reverse,foreach:function foreach(a,b){return b.forEach((b)=>a(b)),Symbol.for('ok')},duplicate:function duplicate(a,b){const c=[];for(;c.length{if(d.get(c-1)a.get(c-1)?1:0})},keystore:function keystore(a,b,c,d){const e=[...c];for(let f=0;fa.toString()).join()},map:function map(a,b){return b.map((b)=>a(b))},filter:function filter(a,b){return b.filter((b)=>a(b))},filtermap:function filtermap(a,b){const c=[];for(const e of b){const b=a(e);!0===b?c.push(e):b instanceof d.Tuple&&!0===b.get(0)&&c.push(b.get(1))}return c},member:function member(a,b){for(const c of b)if(c===a)return!0;return!1},all:function all(a,b){for(const c of b)if(!1===a(c))return!1;return!0},any:function any(a,b){for(const c of b)if(!0===a(c))return!0;return!1},splitwith:function splitwith(a,b){let c=!1;const e=[],f=[];for(const d of b)!0==c?f.push(d):!0===a(d)?e.push(d):(c=!0,f.push(d));return new d.Tuple(e,f)},sort:function sort(...a){if(1===a.length){const b=[...a[0]];return b.sort()}const c=a[0],b=[...a[1]];return b.sort((d,a)=>{const b=c(d,a);return!0===b?-1:1})}}};return{Core:n}}(); +const i=Symbol.for('ok'),j=Symbol.for('error'),k=Symbol.for('badmap'),l=Symbol.for('badkey');const m=function get_global(){return'undefined'==typeof self?'undefined'==typeof window?'undefined'==typeof global?(console.warn('No global state found'),null):global:window:self}();m.__elixirscript_store__=new Map,m.__elixirscript_names__=new Map;var n={Tuple:d.Tuple,PID:d.PID,BitString:d.BitString,Patterns:{defmatch:function defmatch(...a){const b=getArityMap(a);return function(...a){let[c,d]=findMatchingFunction(a,b);return c.apply(this,d)}},match:function match(a,b,c=()=>!0){let d=[],e=buildMatch(a);const f=e(b,d),[g,h]=checkNamedVariables(d);if(f&&h&&c.apply(this,g))return g;throw console.error('No match for:',b),new MatchError(b)},MatchError,variable:function variable(a=null,b=Symbol.for('tailored.no_value')){return new Variable(a,b)},wildcard:function wildcard(){return new Wildcard},startsWith:function startsWith(a){return new StartsWith(a)},capture:function capture(a){return new Capture(a)},headTail:function headTail(){return new HeadTail},type:function a(a,b={}){return new Type(a,b)},bound:function bound(a){return new Bound(a)},Clause,clause:function clause(a,b,c=()=>!0){return new Clause(a,b,c)},bitStringMatch:function bitStringMatch(...a){return new BitStringMatch(...a)},match_or_default,defmatchgen,list_comprehension:function list_comprehension(a,b){const c=run_generators(b.pop()(),b);let d=[];for(let e of c)a.guard.apply(this,e)&&d.push(a.fn.apply(this,e));return d},list_generator:function list_generator(a,b){return function(){let c=[];for(let d of b){const b=match_or_default(a,d,()=>!0,g);if(b!=g){const[a]=b;c.push(a)}}return c}},bitstring_generator:function bitstring_generator(a,b){return function(){let c=[],d=b.slice(0,a.byte_size()),e=1;for(;d.byte_size==a.byte_size();){const f=match_or_default(a,d,()=>!0,g);if(f!=g){c.push(f)}d=b.slice(a.byte_size()*e,a.byte_size()*(e+1)),e++}return c}},bitstring_comprehension:function bitstring_comprehension(a,b){const c=run_generators(b.pop()(),b);let e=[];for(let d of c)a.guard.apply(this,d)&&e.push(a.fn.apply(this,d));return e=e.map((a)=>d.BitString.integer(a)),new d.BitString(...e)},defmatchGen:function defmatchGen(...a){return defmatchgen(...a)},defmatchAsync:function defmatchAsync(...a){const b=getArityMap(a);return async function(...a){if(b.has(a.length)){const c=b.get(a.length);let d=null,e=null;for(let b of c){let c=[];a=fillInOptionalValues(a,b.arity,b.optionals);const f=b.pattern(a,c),[g,h]=checkNamedVariables(c);if(f&&h&&(await b.guard.apply(this,c))){d=b.fn,e=c;break}}if(!d)throw console.error('No match for:',a),new MatchError(a);return d.apply(this,e)}throw console.error('Arity of',a.length,'not found. No match for:',a),new MatchError(a)}}},Integer:class Integer{},Float:class Float{},Functions:{call_property:function call_property(a,b){if(!b)return a instanceof Function||'function'==typeof a?a():a;if(a instanceof Map){let c=null;if(a.has(b)?c=b:a.has(Symbol.for(b))&&(c=Symbol.for(b)),null===c)throw new Error(`Property ${b} not found in ${a}`);return a.get(c)instanceof Function||'function'==typeof a.get(c)?a.get(c)():a.get(c)}let c=null;if('number'==typeof a||'symbol'==typeof a||'boolean'==typeof a||'string'==typeof a?void 0===a[b]?void 0!==a[Symbol.for(b)]&&(c=Symbol.for(b)):c=b:b in a?c=b:Symbol.for(b)in a&&(c=Symbol.for(b)),null===c)throw new Error(`Property ${b} not found in ${a}`);return a[c]instanceof Function||'function'==typeof a[c]?a[c]():a[c]},defprotocol:function defprotocol(a){return new Protocol(a)},defimpl:function defimpl(a,b,c){a.implementation(b,c)},build_namespace:function build_namespace(a,b){let c=b.split('.');const d=a;let e=a;'Elixir'===c[0]&&(c=c.slice(1));for(const d of c)'undefined'==typeof e[d]&&(e[d]={}),e=e[d];return d.__table__=a.__table__||{},d.__table__[Symbol.for(b)]=e,e},iterator_to_reducer,map_to_object},SpecialForms:{_case:function _case(a,b){return n.Patterns.defmatch(...b)(a)},cond:function cond(...a){for(const b of a)if(b[0])return b[1]();throw new Error},_for:function _for(a,b,c,d=[]){let[e,f]=c.into(d);const g=run_list_generators(b.pop()(),b);for(const h of g)a.guard.apply(this,h)&&(e=f(e,new n.Tuple(Symbol.for('cont'),a.fn.apply(this,h))));return f(e,Symbol.for('done'))},_try:function _try(a,b,c,d,e){let f=null;try{f=a()}catch(a){let d=null;if(b)try{return d=b(a),d}catch(a){if(a instanceof n.Patterns.MatchError)throw a}if(c)try{return d=c(a),d}catch(a){if(a instanceof n.Patterns.MatchError)throw a}throw a}finally{e&&e()}if(d)try{return d(f)}catch(a){if(a instanceof n.Patterns.MatchError)throw new Error('No Match Found in Else');throw a}else return f},_with:function _with(...a){let b=[],c=null,d=null;'function'==typeof a[a.length-2]?[c,d]=a.splice(-2):c=a.pop();for(let c=0;c{const[c,d]=b;return a.set(c,d),a},new Map)},keys:function keys(a){return!1===h.is_map(a)?new d.Tuple(k,a):Array.from(a.keys())},values:function values$1(a){return!1===h.is_map(a)?new d.Tuple(k,a):Array.from(a.values())},is_key,put:function put(a,b,c){if(!1===h.is_map(c))return new d.Tuple(k,c);const e=new Map(c);return e.set(a,b),e},merge:function merge(a,b){return!1===h.is_map(a)?new d.Tuple(k,a):!1===h.is_map(b)?new d.Tuple(k,b):new Map([...a,...b])},update:function update(a,b,c){return!1===h.is_map(c)?new d.Tuple(k,c):!1===is_key(a,c)?new d.Tuple(l,a):new Map([...c,[a,b]])},get:function get(...a){const b=a[0],c=a[1];return!1===h.is_map(c)?new d.Tuple(k,c):is_key(b)?c.get(b):3===a.length?a[2]:new d.Tuple(l,b)},take:function take(a,b){if(!1===h.is_map(b))return new d.Tuple(k,b);if(!is_key(a))return j;const c=b.get(a),e=new Map(b);return e.delete(a),new d.Tuple(c,e)}},lists:{reverse,foreach:function foreach(a,b){return b.forEach((b)=>a(b)),Symbol.for('ok')},duplicate:function duplicate(a,b){const c=[];for(;c.length{if(d.get(c-1)a.get(c-1)?1:0})},keystore:function keystore(a,b,c,d){const e=[...c];for(let f=0;fa.toString()).join()},map:function map(a,b){return b.map((b)=>a(b))},filter:function filter(a,b){return b.filter((b)=>a(b))},filtermap:function filtermap(a,b){const c=[];for(const e of b){const b=a(e);!0===b?c.push(e):b instanceof d.Tuple&&!0===b.get(0)&&c.push(b.get(1))}return c},member:function member(a,b){for(const c of b)if(c===a)return!0;return!1},all:function all(a,b){for(const c of b)if(!1===a(c))return!1;return!0},any:function any(a,b){for(const c of b)if(!0===a(c))return!0;return!1},splitwith:function splitwith(a,b){let c=!1;const e=[],f=[];for(const d of b)!0==c?f.push(d):!0===a(d)?e.push(d):(c=!0,f.push(d));return new d.Tuple(e,f)},sort:function sort(...a){if(1===a.length){const b=[...a[0]];return b.sort()}const c=a[0],b=[...a[1]];return b.sort((d,a)=>{const b=c(d,a);return!0===b?-1:1})}}};return{Core:n}}(); diff --git a/src/javascript/lib/core/functions.js b/src/javascript/lib/core/functions.js index 97a18379..4fdabcac 100644 --- a/src/javascript/lib/core/functions.js +++ b/src/javascript/lib/core/functions.js @@ -113,10 +113,25 @@ function build_namespace(ns, ns_string) { return parent; } +function map_to_object(map) { + const object = {}; + + for (const [key, value] of map.entries()) { + if (value instanceof Map) { + object[key] = map_to_object(value); + } else { + object[key] = value; + } + } + + return object; +} + export default { call_property, defprotocol, defimpl, build_namespace, - iterator_to_reducer + iterator_to_reducer, + map_to_object }; From f7c8ac87d7469d182e2efb0e63488de735dd49a0 Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Thu, 20 Jul 2017 19:54:41 -0500 Subject: [PATCH 624/860] Add ElixirScript.JS.map_to_object/1 --- CHANGELOG.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index fb472034..38eb4911 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,7 +8,8 @@ and this project adheres to [Semantic Versioning](http://semver.org/). ### Added - ElixirScript now has an FFI layer for interoperability with JavaScript. For more details, see documentation at `ElixirScript.FFI` -- ElixirScript.JS.mutate/3 +- `ElixirScript.JS.mutate/3` +- `ElixirScript.JS.map_to_object/1` ### Changed - Compiler has been completely rewritten. ElixirScript now requires Erlang 20+ and Elixir 1.5+ From 6b9d3b11854fdb1bcf19dd93c3c90946db427c5f Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Thu, 20 Jul 2017 21:54:51 -0500 Subject: [PATCH 625/860] Revert changes to main.ex. Add map_to_object/1 test --- test/passes/translate/forms/js_test.exs | 25 +++++++++++++++++++++---- test/support/main.ex | 2 -- 2 files changed, 21 insertions(+), 6 deletions(-) diff --git a/test/passes/translate/forms/js_test.exs b/test/passes/translate/forms/js_test.exs index d9f556cd..60571603 100644 --- a/test/passes/translate/forms/js_test.exs +++ b/test/passes/translate/forms/js_test.exs @@ -66,9 +66,6 @@ defmodule ElixirScript.Translate.Forms.JS.Test do end test "mutate/3" do - properties = [{"a", 1}] - map_ast = {:%{}, [], properties} - ast = {{:., [], [ElixirScript.JS, :mutate]}, [], [{:entry, [], nil}, "a", 2]} state = %{function: {:each, nil}, module: Enum, vars: %{:_ => 0, "entry" => 0, "enumerable" => 0, "fun" => 0}} @@ -80,8 +77,28 @@ defmodule ElixirScript.Translate.Forms.JS.Test do J.literal("a"), true ), + J.literal(2) + ) + end + + test "map_to_object/1" do + ast = {{:., [], [ElixirScript.JS, :map_to_object]}, [], [{:entry, [], nil}]} + state = %{function: {:each, nil}, module: Enum, vars: %{:_ => 0, "entry" => 0, "enumerable" => 0, "fun" => 0}} + + {js_ast, _} = Form.compile(ast, state) + assert js_ast == J.call_expression( + J.member_expression( + J.member_expression( + J.identifier("ElixirScript"), + J.member_expression( + J.identifier("Core"), + J.identifier("Functions") + ) + ), + J.identifier("map_to_object") + ), [ - J.literal(2) + J.identifier("entry0") ] ) end diff --git a/test/support/main.ex b/test/support/main.ex index a2260e63..a18d3d90 100644 --- a/test/support/main.ex +++ b/test/support/main.ex @@ -1,7 +1,5 @@ defmodule Main do def start(:normal, [callback]) do callback.("started") - - Enum.map(1..5, fn(x) -> x * 2 end) end end From 673e6c0c3d965dcff5b657522bb339ca8ba42b89 Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Thu, 20 Jul 2017 22:01:39 -0500 Subject: [PATCH 626/860] Fix broken maps tests --- src/javascript/tests/core/erlang_compat/maps_spec.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/javascript/tests/core/erlang_compat/maps_spec.js b/src/javascript/tests/core/erlang_compat/maps_spec.js index 805c7172..ddb69aa9 100644 --- a/src/javascript/tests/core/erlang_compat/maps_spec.js +++ b/src/javascript/tests/core/erlang_compat/maps_spec.js @@ -2,7 +2,7 @@ import test from 'ava'; import Core from '../../../lib/core'; test('find', t => { - let myMap = {}; + let myMap = new Map(); let result = Core.maps.find('t', myMap); t.is(result, Symbol.for('error')); @@ -10,13 +10,13 @@ test('find', t => { result = Core.maps.find('t', myMap); t.deepEqual(result.values, [Symbol.for('badmap'), myMap]); - myMap = { t: 'b' }; + myMap = new Map([['t', 'b']]); result = Core.maps.find('t', myMap); t.deepEqual(result.values, [Symbol.for('ok'), 'b']); }); test('fold', t => { - const myMap = { a: 1, b: 2 }; + const myMap = new Map([['a', 1], ['b', 2]]); const result = Core.maps.fold((k, v, acc) => acc + v, 0, myMap); t.is(result, 3); }); From 48f1e3e675eb54a5da8e1d40f1edac131b5c1f93 Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Thu, 20 Jul 2017 22:21:18 -0500 Subject: [PATCH 627/860] Update to Elixir 1.5-rc.2 and nodejs 8.2.0 --- .tool-versions | 4 ++-- .travis.yml | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.tool-versions b/.tool-versions index 0a498367..8dbeeb38 100644 --- a/.tool-versions +++ b/.tool-versions @@ -1,3 +1,3 @@ erlang 20.0 -elixir ref-v1.5.0-rc.1 -nodejs 8.1.4 +elixir ref-v1.5.0-rc.2 +nodejs 8.2.0 diff --git a/.travis.yml b/.travis.yml index e4ec9f8e..ed00c03d 100644 --- a/.travis.yml +++ b/.travis.yml @@ -9,8 +9,8 @@ install: - npm install -g yarn - yarn before_script: - - wget https://repo.hex.pm/builds/elixir/v1.5.0-rc.1-otp-20.zip - - unzip -d elixir v1.5.0-rc.1-otp-20.zip + - wget https://repo.hex.pm/builds/elixir/v1.5.0-rc.2-otp-20.zip + - unzip -d elixir v1.5.0-rc.2-otp-20.zip - export PATH=$(pwd)/elixir/bin:${PATH} - mix local.rebar --force - mix local.hex --force From 18d75af4d99e67e5bc6f137ffdca2cd8d54e3253 Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Thu, 20 Jul 2017 22:51:14 -0500 Subject: [PATCH 628/860] Add erlang.process_info shim and erlang_compat.elixir_errors.warn --- priv/build/iife/ElixirScript.Core.js | 2564 ++++++++++++++++- src/javascript/lib/core.js | 4 +- .../lib/core/erlang_compat/elixir_errors.js | 10 + .../lib/core/erlang_compat/erlang.js | 15 +- 4 files changed, 2585 insertions(+), 8 deletions(-) create mode 100644 src/javascript/lib/core/erlang_compat/elixir_errors.js diff --git a/priv/build/iife/ElixirScript.Core.js b/priv/build/iife/ElixirScript.Core.js index 42035b8b..2ffba822 100644 --- a/priv/build/iife/ElixirScript.Core.js +++ b/priv/build/iife/ElixirScript.Core.js @@ -1,6 +1,2558 @@ -var ElixirScript=function(){'use strict';/* @flow */function namedVariableResult(a,b){return new NamedVariableResult(a,b)}/* @flow */function is_number(a){return'number'==typeof a}function is_string(a){return'string'==typeof a}function is_boolean(a){return'boolean'==typeof a}function is_symbol(a){return'symbol'==typeof a}function is_object(a){return'object'==typeof a}function is_variable(a){return a instanceof Variable}function is_null(a){return null===a}function is_array(a){return Array.isArray(a)}function is_function(a){return'[object Function]'==Object.prototype.toString.call(a)}function is_map(a){return a instanceof Map}function resolveNull(){return function(a){return is_null(a)}}function resolveWildcard(){return function(){return!0}}function resolveObject(a){let b={};const c=Object.keys(a).concat(Object.getOwnPropertySymbols(a));for(let d of c)b[d]=buildMatch(a[d]);return function(d,e){if(!is_object(d)||a.length>d.length)return!1;for(let a of c)if(!(a in d)||!b[a](d[a],e))return!1;return!0}}function getSize(a,b){return a*b/8}function arraysEqual(c,a){if(c===a)return!0;if(null==c||null==a)return!1;if(c.length!=a.length)return!1;for(var b=0;be.integer(a));return new e(...b)}function resolveNoMatch(){return function(){return!1}}function buildMatch(a){if(null===a)return resolveNull(a);if('undefined'==typeof a)return resolveWildcard(a);const b=a.constructor.prototype,c=f.get(b);return c?c(a):'object'==typeof a?resolveObject(a):resolveNoMatch()}function defmatchgen(...a){const b=getArityMap(a);return function*(...a){let[c,d]=findMatchingFunction(a,b);return yield*c.apply(this,d)}}function findMatchingFunction(a,b){if(b.has(a.length)){const c=b.get(a.length);let d=null,e=null;for(let b of c){let c=[];a=fillInOptionalValues(a,b.arity,b.optionals);const f=b.pattern(a,c),[g,h]=checkNamedVariables(c);if(f&&h&&b.guard.apply(this,g)){d=b.fn,e=g;break}}if(!d)throw console.error('No match for:',a),new MatchError(a);return[d,e]}throw console.error('Arity of',a.length,'not found. No match for:',a),new MatchError(a)}function getArityMap(a){let b=new Map;for(const c of a){const a=getArityRange(c);for(const d of a){let a=[];b.has(d)&&(a=b.get(d)),a.push(c),b.set(d,a)}}return b}function getArityRange(a){const b=a.arity-a.optionals.length,c=a.arity;let d=[b];for(;d[d.length-1]!=c;)d.push(d[d.length-1]+1);return d}function getOptionalValues(a){let b=[];for(let c=0;c!0,d=null){let e=[],f=buildMatch(a);const g=f(b,e),[h,i]=checkNamedVariables(e);return g&&i&&c.apply(this,h)?h:d}function run_generators(a,b){if(0==b.length)return a.map((a)=>{return Array.isArray(a)?a:[a]});const c=b.pop();let d=[];for(let e of c())for(let b of a)d.push([e].concat(b));return run_generators(d,b)}function iterator_to_reducer(a,b,c){const d=a[Symbol.iterator]();let e=d.next(),f=b;for(;!1===e.done;){if(f=c(e.value,f.get(1)),f.get(0)===Symbol.for('halt'))return new n.Tuple(Symbol.for('halted'),f.get(1));if(f.get(0)===Symbol.for('suspend'))return new n.Tuple(Symbol.for('suspended'),f.get(1),(a)=>{return iterator_to_reducer(d,a,c)});e=d.next()}return new n.Tuple(Symbol.for('done'),f.get(1))}function map_to_object(a){const b={};for(const[c,d]of a.entries())b[c]=d instanceof Map?map_to_object(d):d;return b}function run_list_generators(a,b){if(0==b.length)return a.map((a)=>{return Array.isArray(a)?a:[a]});const c=b.pop(),d=[];for(const e of c())for(const b of a)d.push([e].concat(b));return run_list_generators(d,b)}// http://erlang.org/doc/man/erlang.html -function atom_to_binary(a,b=Symbol.for('utf8')){if(b!==Symbol.for('utf8'))throw new Error(`unsupported encoding ${b}`);return a.__MODULE__?Symbol.keyFor(a.__MODULE__):Symbol.keyFor(a)}function binary_to_atom(a,b=Symbol.for('utf8')){if(b!==Symbol.for('utf8'))throw new Error(`unsupported encoding ${b}`);return Symbol.for(a)}function is_number$1(a){return'number'==typeof a||a instanceof Number}function is_key(a,b){return b.has(a)}// http://erlang.org/doc/man/lists.html -function reverse(a){return[...a]}function flatten(a,b=[]){const c=a.reduce((a,b)=>{return Array.isArray(b)?a.concat(flatten(b)):a.concat(b)},[]);return c.concat(b)}function foldl(a,b,c){return c.reduce((b,c)=>{return a(c,b)},b)}function keyfind(a,b,c){for(const d of c)if(d.get(b-1)===a)return d;return!1}function keydelete(a,b,c){const d=[];let e=!1;for(let f=0;fBitString$1.integer(a));return new BitString$1(...d)}[Symbol.iterator](){return this.value[Symbol.iterator]()}toString(){var a,b='';for(a=0;a>'}process(a){let b=[];var c;for(c=0;cb?c.push(b):2048>b?c.push(192|b>>6,128|63&b):55296>b||57344<=b?c.push(224|b>>12,128|63&b>>6,128|63&b):(d++,b=65536+((1023&b)<<10|1023&a.charCodeAt(d)),c.push(240|b>>18,128|63&b>>12,128|63&b>>6,128|63&b));return c}static toUTF16Array(a){for(var b,c=[],d=0;d=b?(c.push(0),c.push(b)):(c.push(255&b>>8),c.push(255&b));return c}static toUTF32Array(a){for(var b,c=[],d=0;d=b?(c.push(0),c.push(0),c.push(0),c.push(b)):(c.push(0),c.push(0),c.push(255&b>>8),c.push(255&b));return c}//http://stackoverflow.com/questions/2003493/javascript-float-from-to-bits -static float32ToBytes(a){var b=[],c=new ArrayBuffer(4);new Float32Array(c)[0]=a;let d=new Uint32Array(c)[0];return b.push(255&d>>24),b.push(255&d>>16),b.push(255&d>>8),b.push(255&d),b}static float64ToBytes(a){var b=[],c=new ArrayBuffer(8);new Float64Array(c)[0]=a;var d=new Uint32Array(c)[0],e=new Uint32Array(c)[1];return b.push(255&e>>24),b.push(255&e>>16),b.push(255&e>>8),b.push(255&e),b.push(255&d>>24),b.push(255&d>>16),b.push(255&d>>8),b.push(255&d),b}}var d={Tuple,PID:class PID{constructor(){++b,this.id=b}toString(){return'PID#<0.'+this.id+'.0>'}},Reference:class Reference{constructor(){++c,this.id=c,this.ref=Symbol()}toString(){return'Ref#<0.0.0.'+this.id+'>'}},BitString:BitString$1};/* @flow */const e=d.BitString,f=new Map;f.set(Variable.prototype,function resolveVariable(a){return function(b,c){return null===a.name||a.name.startsWith('_')?c.push(b):c.push(namedVariableResult(a.name,b)),!0}}),f.set(Wildcard.prototype,resolveWildcard),f.set(HeadTail.prototype,function resolveHeadTail(){return function(a,b){if(!is_array(a)||2>a.length)return!1;const c=a[0],d=a.slice(1);return b.push(c),b.push(d),!0}}),f.set(StartsWith.prototype,function resolveStartsWith(a){const b=a.prefix;return function(a,c){return is_string(a)&&a.startsWith(b)&&(c.push(a.substring(b.length)),!0)}}),f.set(Capture.prototype,function resolveCapture(a){const b=buildMatch(a.value);return function(a,c){return!!b(a,c)&&(c.push(a),!0)}}),f.set(Bound.prototype,function resolveBound(a){return function(b){return typeof b==typeof a.value&&b===a.value}}),f.set(Type.prototype,function resolveType(a){return function(b,c){if(b instanceof a.type){const d=buildMatch(a.objPattern);return d(b,c)}return!1}}),f.set(BitStringMatch.prototype,function resolveBitString(a){let b=[];for(let c of a.values)if(is_variable(c.value)){let a=getSize(c.unit,c.size);fillArray(b,a)}else b=b.concat(new e(c).value);let c=a.values;return function(a,d){var f=String.fromCharCode;let g=null;if(!is_string(a)&&!(a instanceof e))return!1;g=is_string(a)?new e(e.binary(a)):a;let h=0;for(let e,j=0;jd.size)return!1;for(let a of c)if(!d.has(a)||!b.get(a)(d.get(a),e))return!1;return!0}}),f.set(Array.prototype,function resolveArray(a){const b=a.map((a)=>buildMatch(a));return function(c,d){return is_array(c)&&c.length==a.length&&c.every(function(a,e){return b[e](c[e],d)})}}),f.set(String.prototype,function resolveString(a){return function(b){return is_string(b)&&b===a}}),f.set(Boolean.prototype,function resolveBoolean(a){return function(b){return is_boolean(b)&&b===a}}),f.set(Function.prototype,function resolveFunction(a){return function(b){return is_function(b)&&b===a}}),f.set(Object.prototype,resolveObject);class MatchError extends Error{constructor(a){if(super(),'symbol'==typeof a)this.message='No match for: '+a.toString();else if(Array.isArray(a)){let b=a.map((a)=>{return null===a?'null':'undefined'==typeof a?'undefined':a.toString()});this.message='No match for: '+b}else this.message='No match for: '+a;this.stack=new Error().stack,this.name=this.constructor.name}}class Clause{constructor(a,b,c=()=>!0){this.pattern=buildMatch(a),this.arity=a.length,this.optionals=getOptionalValues(a),this.fn=b,this.guard=c}}const g=Symbol();// https://github.com/airportyh/protomorphism -class Protocol{constructor(b){function createFun(b){return function(...c){const d=c[0];let e=null;if(null===d&&this.hasImplementation(Symbol('null'))?e=this.registry.get(Symbol)[b]:a(d)&&this.hasImplementation(n.Integer)?e=this.registry.get(n.Integer)[b]:'number'==typeof d&&!a(d)&&this.hasImplementation(n.Float)?e=this.registry.get(n.Float)[b]:'string'==typeof d&&this.hasImplementation(n.BitString)?e=this.registry.get(n.BitString)[b]:d&&d.has(Symbol.for('__struct__'))&&this.hasImplementation(d)?e=this.registry.get(d.get(Symbol.for('__struct__')).__MODULE__)[b]:null!==d&&this.hasImplementation(d)?e=this.registry.get(d.constructor)[b]:this.fallback&&(e=this.fallback[b]),null!=e){const a=e.apply(this,c);return a}throw new Error(`No implementation found for ${d}`)}}for(const a in this.registry=new Map,this.fallback=null,b)this[a]=createFun(a).bind(this)}implementation(a,b){null===a?this.fallback=b:this.registry.set(a,b)}hasImplementation(a){if(a===n.Integer||a===n.Float||a===n.BitString)return this.registry.has(a);return a&&a.has(Symbol.for('__struct__'))?this.registry.has(a.get(Symbol.for('__struct__')).__MODULE__):this.registry.has(a.constructor)}}var h={atom_to_binary,binary_to_atom,binary_to_existing_atom:function binary_to_existing_atom(a,b=Symbol.for('utf8')){return binary_to_atom(a,b)},list_concatenation:function list_concatenation(a,b){return a.concat(b)},list_subtraction:function list_subtraction(a,b){const c=[...a];for(const d of b){const a=c.indexOf(d);-1b},greaterThanOrEqualTo:function greaterThanOrEqualTo(a,b){return a>=b},lessThan:function lessThan(a,b){return a>b},bxor:function bxor(a,b){return a^b},bnot:function bnot(a){return~a},is_bitstring:function is_bitstring$1(a){return a instanceof d.BitString},is_boolean:function is_boolean$1(a){return'boolean'==typeof a||a instanceof Boolean},is_float:function is_float(b){return is_number$1(b)&&!a(b)},is_function:function is_function$1(a){return'function'==typeof a||a instanceof Function},is_integer:function is_integer(b){return a(b)},is_list:function is_list(a){return Array.isArray(a)},is_map:function is_map$1(a){return a instanceof Map},is_number:is_number$1,is_pid:function is_pid(a){return a instanceof d.PID},is_port:function is_port(){return!1},is_reference:function is_reference(a){return a instanceof d.Reference},is_tuple:function is_tuple(a){return a instanceof d.Tuple},is_atom:function is_atom(a){return'symbol'==typeof a||a instanceof Symbol||a.__MODULE__},is_binary:function is_binary(a){return'string'==typeof a||a instanceof String},element:function element(a,b){return b.get(a-1)},setelement:function setelement(a,b,c){const e=[...b.values];return e[a-1]=c,new d.Tuple(...e)},make_tuple:function make_tuple(a,b){const c=[];for(let d=0;d!0){let d=[],e=buildMatch(a);const f=e(b,d),[g,h]=checkNamedVariables(d);if(f&&h&&c.apply(this,g))return g;throw console.error('No match for:',b),new MatchError(b)},MatchError,variable:function variable(a=null,b=Symbol.for('tailored.no_value')){return new Variable(a,b)},wildcard:function wildcard(){return new Wildcard},startsWith:function startsWith(a){return new StartsWith(a)},capture:function capture(a){return new Capture(a)},headTail:function headTail(){return new HeadTail},type:function a(a,b={}){return new Type(a,b)},bound:function bound(a){return new Bound(a)},Clause,clause:function clause(a,b,c=()=>!0){return new Clause(a,b,c)},bitStringMatch:function bitStringMatch(...a){return new BitStringMatch(...a)},match_or_default,defmatchgen,list_comprehension:function list_comprehension(a,b){const c=run_generators(b.pop()(),b);let d=[];for(let e of c)a.guard.apply(this,e)&&d.push(a.fn.apply(this,e));return d},list_generator:function list_generator(a,b){return function(){let c=[];for(let d of b){const b=match_or_default(a,d,()=>!0,g);if(b!=g){const[a]=b;c.push(a)}}return c}},bitstring_generator:function bitstring_generator(a,b){return function(){let c=[],d=b.slice(0,a.byte_size()),e=1;for(;d.byte_size==a.byte_size();){const f=match_or_default(a,d,()=>!0,g);if(f!=g){c.push(f)}d=b.slice(a.byte_size()*e,a.byte_size()*(e+1)),e++}return c}},bitstring_comprehension:function bitstring_comprehension(a,b){const c=run_generators(b.pop()(),b);let e=[];for(let d of c)a.guard.apply(this,d)&&e.push(a.fn.apply(this,d));return e=e.map((a)=>d.BitString.integer(a)),new d.BitString(...e)},defmatchGen:function defmatchGen(...a){return defmatchgen(...a)},defmatchAsync:function defmatchAsync(...a){const b=getArityMap(a);return async function(...a){if(b.has(a.length)){const c=b.get(a.length);let d=null,e=null;for(let b of c){let c=[];a=fillInOptionalValues(a,b.arity,b.optionals);const f=b.pattern(a,c),[g,h]=checkNamedVariables(c);if(f&&h&&(await b.guard.apply(this,c))){d=b.fn,e=c;break}}if(!d)throw console.error('No match for:',a),new MatchError(a);return d.apply(this,e)}throw console.error('Arity of',a.length,'not found. No match for:',a),new MatchError(a)}}},Integer:class Integer{},Float:class Float{},Functions:{call_property:function call_property(a,b){if(!b)return a instanceof Function||'function'==typeof a?a():a;if(a instanceof Map){let c=null;if(a.has(b)?c=b:a.has(Symbol.for(b))&&(c=Symbol.for(b)),null===c)throw new Error(`Property ${b} not found in ${a}`);return a.get(c)instanceof Function||'function'==typeof a.get(c)?a.get(c)():a.get(c)}let c=null;if('number'==typeof a||'symbol'==typeof a||'boolean'==typeof a||'string'==typeof a?void 0===a[b]?void 0!==a[Symbol.for(b)]&&(c=Symbol.for(b)):c=b:b in a?c=b:Symbol.for(b)in a&&(c=Symbol.for(b)),null===c)throw new Error(`Property ${b} not found in ${a}`);return a[c]instanceof Function||'function'==typeof a[c]?a[c]():a[c]},defprotocol:function defprotocol(a){return new Protocol(a)},defimpl:function defimpl(a,b,c){a.implementation(b,c)},build_namespace:function build_namespace(a,b){let c=b.split('.');const d=a;let e=a;'Elixir'===c[0]&&(c=c.slice(1));for(const d of c)'undefined'==typeof e[d]&&(e[d]={}),e=e[d];return d.__table__=a.__table__||{},d.__table__[Symbol.for(b)]=e,e},iterator_to_reducer,map_to_object},SpecialForms:{_case:function _case(a,b){return n.Patterns.defmatch(...b)(a)},cond:function cond(...a){for(const b of a)if(b[0])return b[1]();throw new Error},_for:function _for(a,b,c,d=[]){let[e,f]=c.into(d);const g=run_list_generators(b.pop()(),b);for(const h of g)a.guard.apply(this,h)&&(e=f(e,new n.Tuple(Symbol.for('cont'),a.fn.apply(this,h))));return f(e,Symbol.for('done'))},_try:function _try(a,b,c,d,e){let f=null;try{f=a()}catch(a){let d=null;if(b)try{return d=b(a),d}catch(a){if(a instanceof n.Patterns.MatchError)throw a}if(c)try{return d=c(a),d}catch(a){if(a instanceof n.Patterns.MatchError)throw a}throw a}finally{e&&e()}if(d)try{return d(f)}catch(a){if(a instanceof n.Patterns.MatchError)throw new Error('No Match Found in Else');throw a}else return f},_with:function _with(...a){let b=[],c=null,d=null;'function'==typeof a[a.length-2]?[c,d]=a.splice(-2):c=a.pop();for(let c=0;c{const[c,d]=b;return a.set(c,d),a},new Map)},keys:function keys(a){return!1===h.is_map(a)?new d.Tuple(k,a):Array.from(a.keys())},values:function values$1(a){return!1===h.is_map(a)?new d.Tuple(k,a):Array.from(a.values())},is_key,put:function put(a,b,c){if(!1===h.is_map(c))return new d.Tuple(k,c);const e=new Map(c);return e.set(a,b),e},merge:function merge(a,b){return!1===h.is_map(a)?new d.Tuple(k,a):!1===h.is_map(b)?new d.Tuple(k,b):new Map([...a,...b])},update:function update(a,b,c){return!1===h.is_map(c)?new d.Tuple(k,c):!1===is_key(a,c)?new d.Tuple(l,a):new Map([...c,[a,b]])},get:function get(...a){const b=a[0],c=a[1];return!1===h.is_map(c)?new d.Tuple(k,c):is_key(b)?c.get(b):3===a.length?a[2]:new d.Tuple(l,b)},take:function take(a,b){if(!1===h.is_map(b))return new d.Tuple(k,b);if(!is_key(a))return j;const c=b.get(a),e=new Map(b);return e.delete(a),new d.Tuple(c,e)}},lists:{reverse,foreach:function foreach(a,b){return b.forEach((b)=>a(b)),Symbol.for('ok')},duplicate:function duplicate(a,b){const c=[];for(;c.length{if(d.get(c-1)a.get(c-1)?1:0})},keystore:function keystore(a,b,c,d){const e=[...c];for(let f=0;fa.toString()).join()},map:function map(a,b){return b.map((b)=>a(b))},filter:function filter(a,b){return b.filter((b)=>a(b))},filtermap:function filtermap(a,b){const c=[];for(const e of b){const b=a(e);!0===b?c.push(e):b instanceof d.Tuple&&!0===b.get(0)&&c.push(b.get(1))}return c},member:function member(a,b){for(const c of b)if(c===a)return!0;return!1},all:function all(a,b){for(const c of b)if(!1===a(c))return!1;return!0},any:function any(a,b){for(const c of b)if(!0===a(c))return!0;return!1},splitwith:function splitwith(a,b){let c=!1;const e=[],f=[];for(const d of b)!0==c?f.push(d):!0===a(d)?e.push(d):(c=!0,f.push(d));return new d.Tuple(e,f)},sort:function sort(...a){if(1===a.length){const b=[...a[0]];return b.sort()}const c=a[0],b=[...a[1]];return b.sort((d,a)=>{const b=c(d,a);return!0===b?-1:1})}}};return{Core:n}}(); +var ElixirScript = (function () { +'use strict'; + +/* @flow */ + +class Variable { + constructor(name = null, default_value = Symbol.for('tailored.no_value')) { + this.name = name; + this.default_value = default_value; + } +} + +class Wildcard { + constructor() {} +} + +class StartsWith { + constructor(prefix) { + this.prefix = prefix; + } +} + +class Capture { + constructor(value) { + this.value = value; + } +} + +class HeadTail { + constructor() {} +} + +class Type { + constructor(type, objPattern = {}) { + this.type = type; + this.objPattern = objPattern; + } +} + +class Bound { + constructor(value) { + this.value = value; + } +} + +class BitStringMatch { + constructor(...values) { + this.values = values; + } + + length() { + return values.length; + } + + bit_size() { + return this.byte_size() * 8; + } + + byte_size() { + let s = 0; + + for (let val of this.values) { + s = s + val.unit * val.size / 8; + } + + return s; + } + + getValue(index) { + return this.values(index); + } + + getSizeOfValue(index) { + let val = this.getValue(index); + return val.unit * val.size; + } + + getTypeOfValue(index) { + return this.getValue(index).type; + } +} + +class NamedVariableResult { + constructor(name, value) { + this.name = name; + this.value = value; + } +} + +function variable(name = null, default_value = Symbol.for('tailored.no_value')) { + return new Variable(name, default_value); +} + +function wildcard() { + return new Wildcard(); +} + +function startsWith(prefix) { + return new StartsWith(prefix); +} + +function capture(value) { + return new Capture(value); +} + +function headTail() { + return new HeadTail(); +} + +function type(type, objPattern = {}) { + return new Type(type, objPattern); +} + +function bound(value) { + return new Bound(value); +} + +function bitStringMatch(...values) { + return new BitStringMatch(...values); +} + +function namedVariableResult(name, value) { + return new NamedVariableResult(name, value); +} + +/* @flow */ + +function is_number(value) { + return typeof value === 'number'; +} + +function is_string(value) { + return typeof value === 'string'; +} + +function is_boolean(value) { + return typeof value === 'boolean'; +} + +function is_symbol(value) { + return typeof value === 'symbol'; +} + +function is_object(value) { + return typeof value === 'object'; +} + +function is_variable(value) { + return value instanceof Variable; +} + +function is_null(value) { + return value === null; +} + +function is_array(value) { + return Array.isArray(value); +} + +function is_function(value) { + return Object.prototype.toString.call(value) == '[object Function]'; +} + +function is_map(value) { + return value instanceof Map; +} + +class Tuple { + constructor(...args) { + this.values = Object.freeze(args); + this.length = this.values.length; + } + + get(index) { + return this.values[index]; + } + + count() { + return this.values.length; + } + + [Symbol.iterator]() { + return this.values[Symbol.iterator](); + } + + toString() { + let i, + s = ''; + for (i = 0; i < this.values.length; i++) { + if (s !== '') { + s += ', '; + } + + const stringToAppend = this.values[i] ? this.values[i].toString() : ''; + + s += stringToAppend; + } + + return '{' + s + '}'; + } + + put_elem(index, elem) { + if (index === this.length) { + let new_values = this.values.concat([elem]); + return new Tuple(...new_values); + } + + let new_values = this.values.concat([]); + new_values.splice(index, 0, elem); + return new Tuple(...new_values); + } + + remove_elem(index) { + let new_values = this.values.concat([]); + new_values.splice(index, 1); + return new Tuple(...new_values); + } +} + +let process_counter = -1; + +class PID { + constructor() { + process_counter = process_counter + 1; + this.id = process_counter; + } + + toString() { + return 'PID#<0.' + this.id + '.0>'; + } +} + +let ref_counter = -1; + +class Reference { + constructor() { + ref_counter = ref_counter + 1; + this.id = ref_counter; + this.ref = Symbol(); + } + + toString() { + return 'Ref#<0.0.0.' + this.id + '>'; + } +} + +class BitString$1 { + constructor(...args) { + this.value = Object.freeze(this.process(args)); + this.length = this.value.length; + this.bit_size = this.length * 8; + this.byte_size = this.length; + } + + get(index) { + return this.value[index]; + } + + count() { + return this.value.length; + } + + slice(start, end = null) { + let s = this.value.slice(start, end); + let ms = s.map(elem => BitString$1.integer(elem)); + return new BitString$1(...ms); + } + + [Symbol.iterator]() { + return this.value[Symbol.iterator](); + } + + toString() { + var i, + s = ''; + for (i = 0; i < this.count(); i++) { + if (s !== '') { + s += ', '; + } + s += this.get(i).toString(); + } + + return '<<' + s + '>>'; + } + + process(bitStringParts) { + let processed_values = []; + + var i; + for (i = 0; i < bitStringParts.length; i++) { + let processed_value = this['process_' + bitStringParts[i].type](bitStringParts[i]); + + for (let attr of bitStringParts[i].attributes) { + processed_value = this['process_' + attr](processed_value); + } + + processed_values = processed_values.concat(processed_value); + } + + return processed_values; + } + + process_integer(value) { + return value.value; + } + + process_float(value) { + if (value.size === 64) { + return BitString$1.float64ToBytes(value.value); + } else if (value.size === 32) { + return BitString$1.float32ToBytes(value.value); + } + + throw new Error('Invalid size for float'); + } + + process_bitstring(value) { + return value.value.value; + } + + process_binary(value) { + return BitString$1.toUTF8Array(value.value); + } + + process_utf8(value) { + return BitString$1.toUTF8Array(value.value); + } + + process_utf16(value) { + return BitString$1.toUTF16Array(value.value); + } + + process_utf32(value) { + return BitString$1.toUTF32Array(value.value); + } + + process_signed(value) { + return new Uint8Array([value])[0]; + } + + process_unsigned(value) { + return value; + } + + process_native(value) { + return value; + } + + process_big(value) { + return value; + } + + process_little(value) { + return value.reverse(); + } + + process_size(value) { + return value; + } + + process_unit(value) { + return value; + } + + static integer(value) { + return BitString$1.wrap(value, { type: 'integer', unit: 1, size: 8 }); + } + + static float(value) { + return BitString$1.wrap(value, { type: 'float', unit: 1, size: 64 }); + } + + static bitstring(value) { + return BitString$1.wrap(value, { + type: 'bitstring', + unit: 1, + size: value.bit_size + }); + } + + static bits(value) { + return BitString$1.bitstring(value); + } + + static binary(value) { + return BitString$1.wrap(value, { + type: 'binary', + unit: 8, + size: value.length + }); + } + + static bytes(value) { + return BitString$1.binary(value); + } + + static utf8(value) { + return BitString$1.wrap(value, { type: 'utf8', unit: 1, size: value.length }); + } + + static utf16(value) { + return BitString$1.wrap(value, { + type: 'utf16', + unit: 1, + size: value.length * 2 + }); + } + + static utf32(value) { + return BitString$1.wrap(value, { + type: 'utf32', + unit: 1, + size: value.length * 4 + }); + } + + static signed(value) { + return BitString$1.wrap(value, {}, 'signed'); + } + + static unsigned(value) { + return BitString$1.wrap(value, {}, 'unsigned'); + } + + static native(value) { + return BitString$1.wrap(value, {}, 'native'); + } + + static big(value) { + return BitString$1.wrap(value, {}, 'big'); + } + + static little(value) { + return BitString$1.wrap(value, {}, 'little'); + } + + static size(value, count) { + return BitString$1.wrap(value, { size: count }); + } + + static unit(value, count) { + return BitString$1.wrap(value, { unit: count }); + } + + static wrap(value, opt, new_attribute = null) { + let the_value = value; + + if (!(value instanceof Object)) { + the_value = { value: value, attributes: [] }; + } + + the_value = Object.assign(the_value, opt); + + if (new_attribute) { + the_value.attributes.push(new_attribute); + } + + return the_value; + } + + static toUTF8Array(str) { + var utf8 = []; + for (var i = 0; i < str.length; i++) { + var charcode = str.charCodeAt(i); + if (charcode < 0x80) { + utf8.push(charcode); + } else if (charcode < 0x800) { + utf8.push(0xc0 | charcode >> 6, 0x80 | charcode & 0x3f); + } else if (charcode < 0xd800 || charcode >= 0xe000) { + utf8.push(0xe0 | charcode >> 12, 0x80 | charcode >> 6 & 0x3f, 0x80 | charcode & 0x3f); + } else { + // surrogate pair + i++; + // UTF-16 encodes 0x10000-0x10FFFF by + // subtracting 0x10000 and splitting the + // 20 bits of 0x0-0xFFFFF into two halves + charcode = 0x10000 + ((charcode & 0x3ff) << 10 | str.charCodeAt(i) & 0x3ff); + utf8.push(0xf0 | charcode >> 18, 0x80 | charcode >> 12 & 0x3f, 0x80 | charcode >> 6 & 0x3f, 0x80 | charcode & 0x3f); + } + } + return utf8; + } + + static toUTF16Array(str) { + var utf16 = []; + for (var i = 0; i < str.length; i++) { + var codePoint = str.codePointAt(i); + + if (codePoint <= 255) { + utf16.push(0); + utf16.push(codePoint); + } else { + utf16.push(codePoint >> 8 & 0xff); + utf16.push(codePoint & 0xff); + } + } + return utf16; + } + + static toUTF32Array(str) { + var utf32 = []; + for (var i = 0; i < str.length; i++) { + var codePoint = str.codePointAt(i); + + if (codePoint <= 255) { + utf32.push(0); + utf32.push(0); + utf32.push(0); + utf32.push(codePoint); + } else { + utf32.push(0); + utf32.push(0); + utf32.push(codePoint >> 8 & 0xff); + utf32.push(codePoint & 0xff); + } + } + return utf32; + } + + //http://stackoverflow.com/questions/2003493/javascript-float-from-to-bits + static float32ToBytes(f) { + var bytes = []; + + var buf = new ArrayBuffer(4); + new Float32Array(buf)[0] = f; + + let intVersion = new Uint32Array(buf)[0]; + + bytes.push(intVersion >> 24 & 0xff); + bytes.push(intVersion >> 16 & 0xff); + bytes.push(intVersion >> 8 & 0xff); + bytes.push(intVersion & 0xff); + + return bytes; + } + + static float64ToBytes(f) { + var bytes = []; + + var buf = new ArrayBuffer(8); + new Float64Array(buf)[0] = f; + + var intVersion1 = new Uint32Array(buf)[0]; + var intVersion2 = new Uint32Array(buf)[1]; + + bytes.push(intVersion2 >> 24 & 0xff); + bytes.push(intVersion2 >> 16 & 0xff); + bytes.push(intVersion2 >> 8 & 0xff); + bytes.push(intVersion2 & 0xff); + + bytes.push(intVersion1 >> 24 & 0xff); + bytes.push(intVersion1 >> 16 & 0xff); + bytes.push(intVersion1 >> 8 & 0xff); + bytes.push(intVersion1 & 0xff); + + return bytes; + } +} + +var ErlangTypes = { + Tuple, + PID, + Reference, + BitString: BitString$1 +}; + +/* @flow */ + +const BitString = ErlangTypes.BitString; + +function resolveSymbol(pattern) { + return function (value) { + return is_symbol(value) && value === pattern; + }; +} + +function resolveString(pattern) { + return function (value) { + return is_string(value) && value === pattern; + }; +} + +function resolveNumber(pattern) { + return function (value) { + return is_number(value) && value === pattern; + }; +} + +function resolveBoolean(pattern) { + return function (value) { + return is_boolean(value) && value === pattern; + }; +} + +function resolveFunction(pattern) { + return function (value) { + return is_function(value) && value === pattern; + }; +} + +function resolveNull(pattern) { + return function (value) { + return is_null(value); + }; +} + +function resolveBound(pattern) { + return function (value, args) { + if (typeof value === typeof pattern.value && value === pattern.value) { + return true; + } + + return false; + }; +} + +function resolveWildcard() { + return function () { + return true; + }; +} + +function resolveVariable(pattern) { + return function (value, args) { + if (pattern.name === null || pattern.name.startsWith('_')) { + args.push(value); + } else { + args.push(namedVariableResult(pattern.name, value)); + } + + return true; + }; +} + +function resolveHeadTail() { + return function (value, args) { + if (!is_array(value) || value.length < 2) { + return false; + } + + const head = value[0]; + const tail = value.slice(1); + + args.push(head); + args.push(tail); + + return true; + }; +} + +function resolveCapture(pattern) { + const matches = buildMatch(pattern.value); + + return function (value, args) { + if (matches(value, args)) { + args.push(value); + return true; + } + + return false; + }; +} + +function resolveStartsWith(pattern) { + const prefix = pattern.prefix; + + return function (value, args) { + if (is_string(value) && value.startsWith(prefix)) { + args.push(value.substring(prefix.length)); + return true; + } + + return false; + }; +} + +function resolveType(pattern) { + return function (value, args) { + if (value instanceof pattern.type) { + const matches = buildMatch(pattern.objPattern); + return matches(value, args); + } + + return false; + }; +} + +function resolveArray(pattern) { + const matches = pattern.map(x => buildMatch(x)); + + return function (value, args) { + if (!is_array(value) || value.length != pattern.length) { + return false; + } + + return value.every(function (v, i) { + return matches[i](value[i], args); + }); + }; +} + +function resolveMap(pattern) { + let matches = new Map(); + + const keys = Array.from(pattern.keys()); + + for (let key of keys) { + matches.set(key, buildMatch(pattern.get(key))); + } + + return function (value, args) { + if (!is_map(value) || pattern.size > value.size) { + return false; + } + + for (let key of keys) { + if (!value.has(key) || !matches.get(key)(value.get(key), args)) { + return false; + } + } + + return true; + }; +} + +function resolveObject(pattern) { + let matches = {}; + + const keys = Object.keys(pattern).concat(Object.getOwnPropertySymbols(pattern)); + + for (let key of keys) { + matches[key] = buildMatch(pattern[key]); + } + + return function (value, args) { + if (!is_object(value) || pattern.length > value.length) { + return false; + } + + for (let key of keys) { + if (!(key in value) || !matches[key](value[key], args)) { + return false; + } + } + + return true; + }; +} + +function resolveBitString(pattern) { + let patternBitString = []; + + for (let bitstringMatchPart of pattern.values) { + if (is_variable(bitstringMatchPart.value)) { + let size = getSize(bitstringMatchPart.unit, bitstringMatchPart.size); + fillArray(patternBitString, size); + } else { + patternBitString = patternBitString.concat(new BitString(bitstringMatchPart).value); + } + } + + let patternValues = pattern.values; + + return function (value, args) { + let bsValue = null; + + if (!is_string(value) && !(value instanceof BitString)) { + return false; + } + + if (is_string(value)) { + bsValue = new BitString(BitString.binary(value)); + } else { + bsValue = value; + } + + let beginningIndex = 0; + + for (let i = 0; i < patternValues.length; i++) { + let bitstringMatchPart = patternValues[i]; + + if (is_variable(bitstringMatchPart.value) && bitstringMatchPart.type == 'binary' && bitstringMatchPart.size === undefined && i < patternValues.length - 1) { + throw new Error('a binary field without size is only allowed at the end of a binary pattern'); + } + + let size = 0; + let bsValueArrayPart = []; + let patternBitStringArrayPart = []; + size = getSize(bitstringMatchPart.unit, bitstringMatchPart.size); + + if (i === patternValues.length - 1) { + bsValueArrayPart = bsValue.value.slice(beginningIndex); + patternBitStringArrayPart = patternBitString.slice(beginningIndex); + } else { + bsValueArrayPart = bsValue.value.slice(beginningIndex, beginningIndex + size); + patternBitStringArrayPart = patternBitString.slice(beginningIndex, beginningIndex + size); + } + + if (is_variable(bitstringMatchPart.value)) { + switch (bitstringMatchPart.type) { + case 'integer': + if (bitstringMatchPart.attributes && bitstringMatchPart.attributes.indexOf('signed') != -1) { + args.push(new Int8Array([bsValueArrayPart[0]])[0]); + } else { + args.push(new Uint8Array([bsValueArrayPart[0]])[0]); + } + break; + + case 'float': + if (size === 64) { + args.push(Float64Array.from(bsValueArrayPart)[0]); + } else if (size === 32) { + args.push(Float32Array.from(bsValueArrayPart)[0]); + } else { + return false; + } + break; + + case 'bitstring': + args.push(createBitString(bsValueArrayPart)); + break; + + case 'binary': + args.push(String.fromCharCode.apply(null, new Uint8Array(bsValueArrayPart))); + break; + + case 'utf8': + args.push(String.fromCharCode.apply(null, new Uint8Array(bsValueArrayPart))); + break; + + case 'utf16': + args.push(String.fromCharCode.apply(null, new Uint16Array(bsValueArrayPart))); + break; + + case 'utf32': + args.push(String.fromCharCode.apply(null, new Uint32Array(bsValueArrayPart))); + break; + + default: + return false; + } + } else if (!arraysEqual(bsValueArrayPart, patternBitStringArrayPart)) { + return false; + } + + beginningIndex = beginningIndex + size; + } + + return true; + }; +} + +function getSize(unit, size) { + return unit * size / 8; +} + +function arraysEqual(a, b) { + if (a === b) return true; + if (a == null || b == null) return false; + if (a.length != b.length) return false; + + for (var i = 0; i < a.length; ++i) { + if (a[i] !== b[i]) return false; + } + + return true; +} + +function fillArray(arr, num) { + for (let i = 0; i < num; i++) { + arr.push(0); + } +} + +function createBitString(arr) { + let integerParts = arr.map(elem => BitString.integer(elem)); + return new BitString(...integerParts); +} + +function resolveNoMatch() { + return function () { + return false; + }; +} + +const patternMap = new Map(); +patternMap.set(Variable.prototype, resolveVariable); +patternMap.set(Wildcard.prototype, resolveWildcard); +patternMap.set(HeadTail.prototype, resolveHeadTail); +patternMap.set(StartsWith.prototype, resolveStartsWith); +patternMap.set(Capture.prototype, resolveCapture); +patternMap.set(Bound.prototype, resolveBound); +patternMap.set(Type.prototype, resolveType); +patternMap.set(BitStringMatch.prototype, resolveBitString); +patternMap.set(Number.prototype, resolveNumber); +patternMap.set(Symbol.prototype, resolveSymbol); +patternMap.set(Map.prototype, resolveMap); +patternMap.set(Array.prototype, resolveArray); +patternMap.set(String.prototype, resolveString); +patternMap.set(Boolean.prototype, resolveBoolean); +patternMap.set(Function.prototype, resolveFunction); +patternMap.set(Object.prototype, resolveObject); + +function buildMatch(pattern) { + if (pattern === null) { + return resolveNull(pattern); + } + + if (typeof pattern === 'undefined') { + return resolveWildcard(pattern); + } + + const type$$1 = pattern.constructor.prototype; + const resolver = patternMap.get(type$$1); + + if (resolver) { + return resolver(pattern); + } + + if (typeof pattern === 'object') { + return resolveObject(pattern); + } + + return resolveNoMatch(); +} + +class MatchError extends Error { + constructor(arg) { + super(); + + if (typeof arg === 'symbol') { + this.message = 'No match for: ' + arg.toString(); + } else if (Array.isArray(arg)) { + let mappedValues = arg.map(x => { + if (x === null) { + return 'null'; + } else if (typeof x === 'undefined') { + return 'undefined'; + } + + return x.toString(); + }); + + this.message = 'No match for: ' + mappedValues; + } else { + this.message = 'No match for: ' + arg; + } + + this.stack = new Error().stack; + this.name = this.constructor.name; + } +} + +class Clause { + constructor(pattern, fn, guard = () => true) { + this.pattern = buildMatch(pattern); + this.arity = pattern.length; + this.optionals = getOptionalValues(pattern); + this.fn = fn; + this.guard = guard; + } +} + +function clause(pattern, fn, guard = () => true) { + return new Clause(pattern, fn, guard); +} + + + +function defmatch(...clauses) { + const arities = getArityMap(clauses); + + return function (...args) { + let [funcToCall, params] = findMatchingFunction(args, arities); + return funcToCall.apply(this, params); + }; +} + +function defmatchgen(...clauses) { + const arities = getArityMap(clauses); + + return function* (...args) { + let [funcToCall, params] = findMatchingFunction(args, arities); + return yield* funcToCall.apply(this, params); + }; +} + +function defmatchGen(...args) { + return defmatchgen(...args); +} + +function defmatchAsync(...clauses) { + const arities = getArityMap(clauses); + + return async function (...args) { + if (arities.has(args.length)) { + const arityClauses = arities.get(args.length); + + let funcToCall = null; + let params = null; + for (let processedClause of arityClauses) { + let result = []; + args = fillInOptionalValues(args, processedClause.arity, processedClause.optionals); + + const doesMatch = processedClause.pattern(args, result); + const [filteredResult, allNamesMatch] = checkNamedVariables(result); + + if (doesMatch && allNamesMatch && (await processedClause.guard.apply(this, result))) { + funcToCall = processedClause.fn; + params = result; + break; + } + } + + if (!funcToCall) { + console.error('No match for:', args); + throw new MatchError(args); + } + + return funcToCall.apply(this, params); + } else { + console.error('Arity of', args.length, 'not found. No match for:', args); + throw new MatchError(args); + } + }; +} + +function findMatchingFunction(args, arities) { + if (arities.has(args.length)) { + const arityClauses = arities.get(args.length); + + let funcToCall = null; + let params = null; + for (let processedClause of arityClauses) { + let result = []; + args = fillInOptionalValues(args, processedClause.arity, processedClause.optionals); + + const doesMatch = processedClause.pattern(args, result); + const [filteredResult, allNamesMatch] = checkNamedVariables(result); + + if (doesMatch && allNamesMatch && processedClause.guard.apply(this, filteredResult)) { + funcToCall = processedClause.fn; + params = filteredResult; + break; + } + } + + if (!funcToCall) { + console.error('No match for:', args); + throw new MatchError(args); + } + + return [funcToCall, params]; + } else { + console.error('Arity of', args.length, 'not found. No match for:', args); + throw new MatchError(args); + } +} + +function getArityMap(clauses) { + let map = new Map(); + + for (const clause of clauses) { + const range = getArityRange(clause); + + for (const arity of range) { + let arityClauses = []; + + if (map.has(arity)) { + arityClauses = map.get(arity); + } + + arityClauses.push(clause); + map.set(arity, arityClauses); + } + } + + return map; +} + +function getArityRange(clause) { + const min = clause.arity - clause.optionals.length; + const max = clause.arity; + + let range = [min]; + + while (range[range.length - 1] != max) { + range.push(range[range.length - 1] + 1); + } + + return range; +} + +function getOptionalValues(pattern) { + let optionals = []; + + for (let i = 0; i < pattern.length; i++) { + if (pattern[i] instanceof Variable && pattern[i].default_value != Symbol.for('tailored.no_value')) { + optionals.push([i, pattern[i].default_value]); + } + } + + return optionals; +} + +function fillInOptionalValues(args, arity, optionals) { + if (args.length === arity || optionals.length === 0) { + return args; + } + + if (args.length + optionals.length < arity) { + return args; + } + + let numberOfOptionalsToFill = arity - args.length; + let optionalsToRemove = optionals.length - numberOfOptionalsToFill; + + let optionalsToUse = optionals.slice(optionalsToRemove); + + for (let [index, value] of optionalsToUse) { + args.splice(index, 0, value); + if (args.length === arity) { + break; + } + } + + return args; +} + +function match(pattern, expr, guard = () => true) { + let result = []; + let processedPattern = buildMatch(pattern); + const doesMatch = processedPattern(expr, result); + const [filteredResult, allNamesMatch] = checkNamedVariables(result); + + if (doesMatch && allNamesMatch && guard.apply(this, filteredResult)) { + return filteredResult; + } else { + console.error('No match for:', expr); + throw new MatchError(expr); + } +} + +function checkNamedVariables(results) { + const namesMap = {}; + const filteredResults = []; + + for (let i = 0; i < results.length; i++) { + const current = results[i]; + if (current instanceof NamedVariableResult) { + if (namesMap[current.name] && namesMap[current.name] !== current.value) { + return [results, false]; + } else if (namesMap[current.name] && namesMap[current.name] === current.value) { + filteredResults.push(current.value); + } else { + namesMap[current.name] = current.value; + filteredResults.push(current.value); + } + } else { + filteredResults.push(current); + } + } + + return [filteredResults, true]; +} + +function match_or_default(pattern, expr, guard = () => true, default_value = null) { + let result = []; + let processedPattern = buildMatch(pattern); + const doesMatch = processedPattern(expr, result); + const [filteredResult, allNamesMatch] = checkNamedVariables(result); + + if (doesMatch && allNamesMatch && guard.apply(this, filteredResult)) { + return filteredResult; + } else { + return default_value; + } +} + +const NO_MATCH = Symbol(); + +function bitstring_generator(pattern, bitstring) { + return function () { + let returnResult = []; + let bsSlice = bitstring.slice(0, pattern.byte_size()); + let i = 1; + + while (bsSlice.byte_size == pattern.byte_size()) { + const result = match_or_default(pattern, bsSlice, () => true, NO_MATCH); + + if (result != NO_MATCH) { + const [value] = result; + returnResult.push(result); + } + + bsSlice = bitstring.slice(pattern.byte_size() * i, pattern.byte_size() * (i + 1)); + + i++; + } + + return returnResult; + }; +} + +function list_generator(pattern, list) { + return function () { + let returnResult = []; + for (let i of list) { + const result = match_or_default(pattern, i, () => true, NO_MATCH); + if (result != NO_MATCH) { + const [value] = result; + returnResult.push(value); + } + } + + return returnResult; + }; +} + +function list_comprehension(expression, generators) { + const generatedValues = run_generators(generators.pop()(), generators); + + let result = []; + + for (let value of generatedValues) { + if (expression.guard.apply(this, value)) { + result.push(expression.fn.apply(this, value)); + } + } + + return result; +} + +function run_generators(generator, generators) { + if (generators.length == 0) { + return generator.map(x => { + if (Array.isArray(x)) { + return x; + } else { + return [x]; + } + }); + } else { + const list = generators.pop(); + + let next_gen = []; + for (let j of list()) { + for (let i of generator) { + next_gen.push([j].concat(i)); + } + } + + return run_generators(next_gen, generators); + } +} + +function bitstring_comprehension(expression, generators) { + const generatedValues = run_generators(generators.pop()(), generators); + + let result = []; + + for (let value of generatedValues) { + if (expression.guard.apply(this, value)) { + result.push(expression.fn.apply(this, value)); + } + } + + result = result.map(x => ErlangTypes.BitString.integer(x)); + return new ErlangTypes.BitString(...result); +} + +var Patterns = { + defmatch, + match, + MatchError, + variable, + wildcard, + startsWith, + capture, + headTail, + type, + bound, + Clause, + clause, + bitStringMatch, + match_or_default, + defmatchgen, + list_comprehension, + list_generator, + bitstring_generator, + bitstring_comprehension, + defmatchGen, + defmatchAsync +}; + +// https://github.com/airportyh/protomorphism +class Protocol { + constructor(spec) { + this.registry = new Map(); + this.fallback = null; + + function createFun(funName) { + return function (...args) { + const thing = args[0]; + let fun = null; + + if (thing === null && this.hasImplementation(Symbol('null'))) { + fun = this.registry.get(Symbol)[funName]; + } else if (Number.isInteger(thing) && this.hasImplementation(Core.Integer)) { + fun = this.registry.get(Core.Integer)[funName]; + } else if (typeof thing === 'number' && !Number.isInteger(thing) && this.hasImplementation(Core.Float)) { + fun = this.registry.get(Core.Float)[funName]; + } else if (typeof thing === 'string' && this.hasImplementation(Core.BitString)) { + fun = this.registry.get(Core.BitString)[funName]; + } else if (thing && thing.has(Symbol.for('__struct__')) && this.hasImplementation(thing)) { + fun = this.registry.get(thing.get(Symbol.for('__struct__')).__MODULE__)[funName]; + } else if (thing !== null && this.hasImplementation(thing)) { + fun = this.registry.get(thing.constructor)[funName]; + } else if (this.fallback) { + fun = this.fallback[funName]; + } + + if (fun != null) { + const retval = fun.apply(this, args); + return retval; + } + + throw new Error(`No implementation found for ${thing}`); + }; + } + + for (const funName in spec) { + this[funName] = createFun(funName).bind(this); + } + } + + implementation(type, implementation) { + if (type === null) { + this.fallback = implementation; + } else { + this.registry.set(type, implementation); + } + } + + hasImplementation(thing) { + if (thing === Core.Integer || thing === Core.Float || thing === Core.BitString) { + return this.registry.has(thing); + } else if (thing && thing.has(Symbol.for('__struct__'))) { + return this.registry.has(thing.get(Symbol.for('__struct__')).__MODULE__); + } + + return this.registry.has(thing.constructor); + } +} + +function iterator_to_reducer(iterable, acc, fun) { + const iterator = iterable[Symbol.iterator](); + let x = iterator.next(); + let _acc = acc; + + while (x.done === false) { + _acc = fun(x.value, _acc.get(1)); + if (_acc.get(0) === Symbol.for('halt')) { + return new Core.Tuple(Symbol.for('halted'), _acc.get(1)); + } else if (_acc.get(0) === Symbol.for('suspend')) { + return new Core.Tuple(Symbol.for('suspended'), _acc.get(1), new_acc => { + return iterator_to_reducer(iterator, new_acc, fun); + }); + } + + x = iterator.next(); + } + + return new Core.Tuple(Symbol.for('done'), _acc.get(1)); +} + +function call_property(item, property) { + if (!property) { + if (item instanceof Function || typeof item === 'function') { + return item(); + } + + return item; + } + + if (item instanceof Map) { + let prop = null; + + if (item.has(property)) { + prop = property; + } else if (item.has(Symbol.for(property))) { + prop = Symbol.for(property); + } + + if (prop === null) { + throw new Error(`Property ${property} not found in ${item}`); + } + + if (item.get(prop) instanceof Function || typeof item.get(prop) === 'function') { + return item.get(prop)(); + } + return item.get(prop); + } + + let prop = null; + + if (typeof item === 'number' || typeof item === 'symbol' || typeof item === 'boolean' || typeof item === 'string') { + if (item[property] !== undefined) { + prop = property; + } else if (item[Symbol.for(property)] !== undefined) { + prop = Symbol.for(property); + } + } else if (property in item) { + prop = property; + } else if (Symbol.for(property) in item) { + prop = Symbol.for(property); + } + + if (prop === null) { + throw new Error(`Property ${property} not found in ${item}`); + } + + if (item[prop] instanceof Function || typeof item[prop] === 'function') { + return item[prop](); + } + return item[prop]; +} + +function defprotocol(spec) { + return new Protocol(spec); +} + +function defimpl(protocol, type, impl) { + protocol.implementation(type, impl); +} + +function build_namespace(ns, ns_string) { + let parts = ns_string.split('.'); + const root = ns; + let parent = ns; + + if (parts[0] === 'Elixir') { + parts = parts.slice(1); + } + + for (const part of parts) { + if (typeof parent[part] === 'undefined') { + parent[part] = {}; + } + + parent = parent[part]; + } + + root.__table__ = ns.__table__ || {}; + root.__table__[Symbol.for(ns_string)] = parent; + + return parent; +} + +function map_to_object(map) { + const object = {}; + + for (const [key, value] of map.entries()) { + if (value instanceof Map) { + object[key] = map_to_object(value); + } else { + object[key] = value; + } + } + + return object; +} + +var Functions = { + call_property, + defprotocol, + defimpl, + build_namespace, + iterator_to_reducer, + map_to_object +}; + +function _case(condition, clauses) { + return Core.Patterns.defmatch(...clauses)(condition); +} + +function cond(...clauses) { + for (const clause of clauses) { + if (clause[0]) { + return clause[1](); + } + } + + throw new Error(); +} + +function _for(expression, generators, collectable_protocol, into = []) { + let [result, fun] = collectable_protocol.into(into); + + const generatedValues = run_list_generators(generators.pop()(), generators); + + for (const value of generatedValues) { + if (expression.guard.apply(this, value)) { + result = fun(result, new Core.Tuple(Symbol.for('cont'), expression.fn.apply(this, value))); + } + } + + return fun(result, Symbol.for('done')); +} + +function run_list_generators(generator, generators) { + if (generators.length == 0) { + return generator.map(x => { + if (Array.isArray(x)) { + return x; + } + return [x]; + }); + } + const list = generators.pop(); + + const next_gen = []; + for (const j of list()) { + for (const i of generator) { + next_gen.push([j].concat(i)); + } + } + + return run_list_generators(next_gen, generators); +} + +function _try(do_fun, rescue_function, catch_fun, else_function, after_function) { + let result = null; + + try { + result = do_fun(); + } catch (e) { + let ex_result = null; + + if (rescue_function) { + try { + ex_result = rescue_function(e); + return ex_result; + } catch (ex) { + if (ex instanceof Core.Patterns.MatchError) { + throw ex; + } + } + } + + if (catch_fun) { + try { + ex_result = catch_fun(e); + return ex_result; + } catch (ex) { + if (ex instanceof Core.Patterns.MatchError) { + throw ex; + } + } + } + + throw e; + } finally { + if (after_function) { + after_function(); + } + } + + if (else_function) { + try { + return else_function(result); + } catch (ex) { + if (ex instanceof Core.Patterns.MatchError) { + throw new Error('No Match Found in Else'); + } + + throw ex; + } + } else { + return result; + } +} + +function _with(...args) { + let argsToPass = []; + let successFunction = null; + let elseFunction = null; + + if (typeof args[args.length - 2] === 'function') { + [successFunction, elseFunction] = args.splice(-2); + } else { + successFunction = args.pop(); + } + + for (let i = 0; i < args.length; i++) { + const [pattern, func] = args[i]; + + const result = func(...argsToPass); + + const patternResult = Core.Patterns.match_or_default(pattern, result); + + if (patternResult == null) { + if (elseFunction) { + return elseFunction.call(null, result); + } + return result; + } + + argsToPass = argsToPass.concat(patternResult); + } + + return successFunction(...argsToPass); +} + +function receive(clauses, after) { + console.warn('Receive not supported'); +} + +var SpecialForms = { + _case, + cond, + _for, + _try, + _with, + receive +}; + +// http://erlang.org/doc/man/erlang.html +function atom_to_binary(atom, encoding = Symbol.for('utf8')) { + if (encoding !== Symbol.for('utf8')) { + throw new Error(`unsupported encoding ${encoding}`); + } + + if (atom.__MODULE__) { + return Symbol.keyFor(atom.__MODULE__); + } + + return Symbol.keyFor(atom); +} + +function binary_to_atom(binary, encoding = Symbol.for('utf8')) { + if (encoding !== Symbol.for('utf8')) { + throw new Error(`unsupported encoding ${encoding}`); + } + + return Symbol.for(binary); +} + +function binary_to_existing_atom(binary, encoding = Symbol.for('utf8')) { + return binary_to_atom(binary, encoding); +} + +function list_concatenation(list1, list2) { + return list1.concat(list2); +} + +function list_subtraction(list1, list2) { + const list = [...list1]; + + for (const item of list2) { + const index = list.indexOf(item); + + if (index > -1) { + list.splice(index, 1); + } + } + + return list; +} + +function plus(left, right) { + if (!right) { + return +left; + } + + return left + right; +} + +function minus(left, right) { + if (!right) { + return -left; + } + + return left - right; +} + +function multiply(left, right) { + return left * right; +} + +function div(left, right) { + return left / right; +} + +function equal(left, right) { + return left == right; +} + +function doesNotEqual(left, right) { + return left != right; +} + +function greaterThan(left, right) { + return left > right; +} + +function greaterThanOrEqualTo(left, right) { + return left >= right; +} + +function lessThan(left, right) { + return left < right; +} + +function lessThanOrEqualTo(left, right) { + return left <= right; +} + +function strictlyEqual(left, right) { + return left === right; +} + +function doesNotStrictlyEqual(left, right) { + return left !== right; +} + +function and(left, right) { + return left && right; +} + +function or(left, right) { + return left || right; +} + +function not(x) { + return !x; +} + +function rem(left, right) { + return left % right; +} + +function band(left, right) { + return left & right; +} + +function bor(left, right) { + return left | right; +} + +function bnot(x) { + return ~x; +} + +function bsl(left, right) { + return left << right; +} + +function bsr(left, right) { + return left >> right; +} + +function bxor(left, right) { + return left ^ right; +} + +function is_atom(value) { + return typeof value === 'symbol' || value instanceof Symbol || value.__MODULE__; +} + +function is_bitstring$1(value) { + return value instanceof ErlangTypes.BitString; +} + +function is_boolean$1(value) { + return typeof value === 'boolean' || value instanceof Boolean; +} + +function is_number$1(value) { + return typeof value === 'number' || value instanceof Number; +} + +function is_float(value) { + return is_number$1(value) && !Number.isInteger(value); +} + +function is_function$1(value) { + return typeof value === 'function' || value instanceof Function; +} + +function is_integer(value) { + return Number.isInteger(value); +} + +function is_list(value) { + return Array.isArray(value); +} + +function is_map$1(value) { + return value instanceof Map; +} + +function is_pid(value) { + return value instanceof ErlangTypes.PID; +} + +function is_port() { + return false; +} + +function is_reference(value) { + return value instanceof ErlangTypes.Reference; +} + +function is_tuple(value) { + return value instanceof ErlangTypes.Tuple; +} + +function is_binary(value) { + return typeof value === 'string' || value instanceof String; +} + +function element(n, tuple) { + return tuple.get(n - 1); +} + +function setelement(index, tuple1, value) { + const tupleData = [...tuple1.values]; + + tupleData[index - 1] = value; + + return new ErlangTypes.Tuple(...tupleData); +} + +function make_tuple(arity, initialValue) { + const list = []; + + for (let i = 0; i < arity; i++) { + list.push(initialValue); + } + + return new ErlangTypes.Tuple(...list); +} + +function insert_element(index, tuple, term) { + const list = [...tuple.values]; + list.splice(index - 1, 0, term); + + return new ErlangTypes.Tuple(...list); +} + +function append_element(tuple, term) { + const list = [...tuple.values]; + list.push(term); + + return new ErlangTypes.Tuple(...list); +} + +function delete_element(index, tuple) { + const list = [...tuple.values]; + list.splice(index - 1, 1); + + return new ErlangTypes.Tuple(...list); +} + +function tuple_to_list(tuple) { + const list = [...tuple.values]; + return list; +} + +function abs(number) { + return Math.abs(number); +} + +function apply(...args) { + if (args.length === 2) { + return args[0].apply(this, ...args[1]); + } + + return args[0][atom_to_binary(args[1])].apply(this, ...args[2]); +} + +function binary_part(binary, start, length) { + return binary.substring(start, start + length); +} + +function bit_size(bitstring) { + return bitstring.bit_size; +} + +function byte_size(bitstring) { + return bitstring.byte_size; +} + +function hd(list) { + return list[0]; +} + +function length(list) { + return list.length; +} + +function make_ref() { + return new ErlangTypes.Reference(); +} + +function map_size(map) { + return map.size; +} + +function max(first, second) { + return Math.max(first, second); +} + +function min(first, second) { + return Math.min(first, second); +} + +function round(number) { + return Math.round(number); +} + +function tl(list) { + return list.slice(1); +} + +function trunc(number) { + return Math.trunc(number); +} + +function tuple_size(tuple) { + return tuple.length; +} + +function binary_to_float(str) { + return parseFloat(str); +} + +function binary_to_integer(str, base = 10) { + return parseInt(str, base); +} + +function process_info(pid, item) { + if (item) { + if (item === Symbol.for('current_stacktrace')) { + return new ErlangTypes.Tuple(item, []); + } + + return new ErlangTypes.Tuple(item, null); + } + + return []; +} + +var erlang = { + atom_to_binary, + binary_to_atom, + binary_to_existing_atom, + list_concatenation, + list_subtraction, + plus, + minus, + multiply, + div, + equal, + greaterThan, + greaterThanOrEqualTo, + lessThan, + lessThanOrEqualTo, + doesNotEqual, + strictlyEqual, + doesNotStrictlyEqual, + and, + or, + not, + rem, + band, + bor, + bsl, + bsr, + bxor, + bnot, + is_bitstring: is_bitstring$1, + is_boolean: is_boolean$1, + is_float, + is_function: is_function$1, + is_integer, + is_list, + is_map: is_map$1, + is_number: is_number$1, + is_pid, + is_port, + is_reference, + is_tuple, + is_atom, + is_binary, + element, + setelement, + make_tuple, + insert_element, + append_element, + delete_element, + tuple_to_list, + abs, + apply, + binary_part, + bit_size, + byte_size, + hd, + length, + make_ref, + map_size, + max, + min, + round, + tl, + trunc, + tuple_size, + binary_to_float, + binary_to_integer, + process_info +}; + +// http://erlang.org/doc/man/maps.html +const OK = Symbol.for('ok'); +const ERROR = Symbol.for('error'); +const BADMAP = Symbol.for('badmap'); +const BADKEY = Symbol.for('badkey'); + +function find(key, map) { + if (erlang.is_map(map) === false) { + return new ErlangTypes.Tuple(BADMAP, map); + } + + const value = map.get(key); + + if (typeof value !== 'undefined') { + return new ErlangTypes.Tuple(OK, value); + } + + return ERROR; +} + +function fold(fun, init, map) { + let acc = init; + + for (const [key, value] of map.entries()) { + acc = fun(key, value, acc); + } + + return acc; +} + +function remove(key, map1) { + if (erlang.is_map(map1) === false) { + return new ErlangTypes.Tuple(BADMAP, map1); + } + + const map2 = new Map(map1); + + map2.delete(key); + + return map2; +} + +function to_list(map) { + if (erlang.is_map(map) === false) { + return new ErlangTypes.Tuple(BADMAP, map); + } + + const list = []; + + for (const [key, value] of map.entries()) { + list.push(new ErlangTypes.Tuple(key, value)); + } + + return list; +} + +function from_list(list) { + return list.reduce((acc, item) => { + const [key, value] = item; + acc.set(key, value); + + return acc; + }, new Map()); +} + +function keys(map) { + if (erlang.is_map(map) === false) { + return new ErlangTypes.Tuple(BADMAP, map); + } + + return Array.from(map.keys()); +} + +function values$1(map) { + if (erlang.is_map(map) === false) { + return new ErlangTypes.Tuple(BADMAP, map); + } + + return Array.from(map.values()); +} + +function is_key(key, map) { + return map.has(key); +} + +function put(key, value, map1) { + if (erlang.is_map(map1) === false) { + return new ErlangTypes.Tuple(BADMAP, map1); + } + + const map2 = new Map(map1); + map2.set(key, value); + + return map2; +} + +function merge(map1, map2) { + if (erlang.is_map(map1) === false) { + return new ErlangTypes.Tuple(BADMAP, map1); + } + + if (erlang.is_map(map2) === false) { + return new ErlangTypes.Tuple(BADMAP, map2); + } + + return new Map([...map1, ...map2]); +} + +function update(key, value, map1) { + if (erlang.is_map(map1) === false) { + return new ErlangTypes.Tuple(BADMAP, map1); + } + + if (is_key(key, map1) === false) { + return new ErlangTypes.Tuple(BADKEY, key); + } + + return new Map([...map1, [key, value]]); +} + +function get(...args) { + const key = args[0]; + const map = args[1]; + + if (erlang.is_map(map) === false) { + return new ErlangTypes.Tuple(BADMAP, map); + } + + if (is_key(key)) { + return map.get(key); + } + + if (args.length === 3) { + return args[2]; + } + + return new ErlangTypes.Tuple(BADKEY, key); +} + +function take(key, map1) { + if (erlang.is_map(map1) === false) { + return new ErlangTypes.Tuple(BADMAP, map1); + } + + if (!is_key(key)) { + return ERROR; + } + + const value = map1.get(key); + const map2 = new Map(map1); + map2.delete(key); + + return new ErlangTypes.Tuple(value, map2); +} + +var maps = { + find, + fold, + remove, + to_list, + from_list, + keys, + values: values$1, + is_key, + put, + merge, + update, + get, + take +}; + +// http://erlang.org/doc/man/lists.html +function reverse(list) { + return [...list].reverse(); +} + +function foreach(fun, list) { + list.forEach(x => fun(x)); + + return Symbol.for('ok'); +} + +function duplicate(n, elem) { + const list = []; + + while (list.length < n) { + list.push(elem); + } + + return list; +} + +function flatten(deepList, tail = []) { + const val = deepList.reduce((acc, value) => { + if (Array.isArray(value)) { + return acc.concat(flatten(value)); + } + + return acc.concat(value); + }, []); + + return val.concat(tail); +} + +function foldl(fun, acc0, list) { + return list.reduce((acc, value) => { + return fun(value, acc); + }, acc0); +} + +function foldr(fun, acc0, list) { + return foldl(fun, acc0, reverse(list)); +} + +function keyfind(key, n, tupleList) { + for (const tuple of tupleList) { + if (tuple.get(n - 1) === key) { + return tuple; + } + } + + return false; +} + +function keymember(key, n, tupleList) { + if (keyfind(key, n, tupleList) === false) { + return false; + } + + return true; +} + +function keyreplace(key, n, tupleList, newTuple) { + const newTupleList = [...tupleList]; + + for (let index = 0; index < newTupleList.length; index++) { + if (newTupleList[index].get(n - 1) === key) { + newTupleList[index] = newTuple; + return newTupleList; + } + } + + return newTupleList; +} + +function keysort(n, tupleList) { + const newTupleList = [...tupleList]; + + return newTupleList.sort((a, b) => { + if (a.get(n - 1) < b.get(n - 1)) { + return -1; + } else if (a.get(n - 1) > b.get(n - 1)) { + return 1; + } + + return 0; + }); +} + +function keystore(key, n, tupleList, newTuple) { + const newTupleList = [...tupleList]; + + for (let index = 0; index < newTupleList.length; index++) { + if (newTupleList[index].get(n - 1) === key) { + newTupleList[index] = newTuple; + return newTupleList; + } + } + + return newTupleList.concat(newTuple); +} + +function keydelete(key, n, tupleList) { + const newTupleList = []; + let deleted = false; + + for (let index = 0; index < tupleList.length; index++) { + if (deleted === false && tupleList[index].get(n - 1) === key) { + deleted = true; + } else { + newTupleList.push(tupleList[index]); + } + } + + return newTupleList; +} + +function keytake(key, n, tupleList) { + const result = keyfind(key, n, tupleList); + + if (result !== false) { + return new ErlangTypes.Tuple(result.get(n - 1), result, keydelete(key, n, tupleList)); + } + + return false; +} + +function mapfoldl(fun, acc0, list1) { + const listResult = []; + let accResult = acc0; + + for (const item of list1) { + const tuple = fun(item, accResult); + listResult.push(tuple.get(0)); + accResult = tuple.get(1); + } + + return new ErlangTypes.Tuple(listResult, accResult); +} + +function concat(things) { + return things.map(v => v.toString()).join(); +} + +function map(fun, list) { + return list.map(value => fun(value)); +} + +function filter(pred, list1) { + return list1.filter(x => pred(x)); +} + +function filtermap(fun, list1) { + const list2 = []; + + for (const item of list1) { + const value = fun(item); + + if (value === true) { + list2.push(item); + } else if (value instanceof ErlangTypes.Tuple && value.get(0) === true) { + list2.push(value.get(1)); + } + } + + return list2; +} + +function member(elem, list) { + for (const item of list) { + if (item === elem) { + return true; + } + } + + return false; +} + +function all(pred, list) { + for (const item of list) { + if (pred(item) === false) { + return false; + } + } + + return true; +} + +function any(pred, list) { + for (const item of list) { + if (pred(item) === true) { + return true; + } + } + + return false; +} + +function splitwith(pred, list) { + let switchToList2 = false; + const list1 = []; + const list2 = []; + + for (const item of list) { + if (switchToList2 === true) { + list2.push(item); + } else if (pred(item) === true) { + list1.push(item); + } else { + switchToList2 = true; + list2.push(item); + } + } + + return new ErlangTypes.Tuple(list1, list2); +} + +function sort(...args) { + if (args.length === 1) { + const list2 = [...args[0]]; + return list2.sort(); + } + + const fun = args[0]; + const list2 = [...args[1]]; + + return list2.sort((a, b) => { + const result = fun(a, b); + + if (result === true) { + return -1; + } + + return 1; + }); +} + +var lists = { + reverse, + foreach, + duplicate, + flatten, + foldl, + foldr, + keydelete, + keyfind, + keymember, + keyreplace, + keysort, + keystore, + keytake, + mapfoldl, + concat, + map, + filter, + filtermap, + member, + all, + any, + splitwith, + sort +}; + +function warn(message) { + const messageString = message.join(''); + console.warn(`warning ${messageString}`); + + return Symbol.for('ok'); +} + +var elixir_errors = { + warn +}; + +function get_key(key) { + let real_key = key; + + if (__elixirscript_names__.has(key)) { + real_key = __elixirscript_names__.get(key); + } + + if (__elixirscript_store__.has(real_key)) { + return real_key; + } + + throw new Error(`Key ${real_key} not found`); +} + +function create(value, name = null) { + const key = new Core.PID(); + + if (name !== null) { + __elixirscript_names__.set(name, key); + } + + return __elixirscript_store__.set(key, value); +} + +function update$1(key, value) { + const real_key = get_key(key); + return __elixirscript_store__.set(real_key, value); +} + +function read(key) { + const real_key = get_key(key); + return __elixirscript_store__.get(real_key); +} + +function remove$1(key) { + const real_key = get_key(key); + return __elixirscript_store__.delete(real_key); +} + +var Store = { + create, + update: update$1, + read, + remove: remove$1 +}; + +class Integer {} +class Float {} + +function get_global() { + if (typeof self !== 'undefined') { + return self; + } else if (typeof window !== 'undefined') { + return window; + } else if (typeof global !== 'undefined') { + return global; + } + + console.warn('No global state found'); + return null; +} + +const globalState = get_global(); + +globalState.__elixirscript_store__ = new Map(); +globalState.__elixirscript_names__ = new Map(); + +var Core = { + Tuple: ErlangTypes.Tuple, + PID: ErlangTypes.PID, + BitString: ErlangTypes.BitString, + Patterns, + Integer, + Float, + Functions, + SpecialForms, + Store, + global: globalState, + erlang, + maps, + lists, + elixir_errors +}; + +var elixir = { + Core +}; + +return elixir; + +}()); diff --git a/src/javascript/lib/core.js b/src/javascript/lib/core.js index b1c85c9e..f0e5277f 100644 --- a/src/javascript/lib/core.js +++ b/src/javascript/lib/core.js @@ -5,6 +5,7 @@ import SpecialForms from './core/special_forms'; import erlang from './core/erlang_compat/erlang'; import maps from './core/erlang_compat/maps'; import lists from './core/erlang_compat/lists'; +import elixir_errors from './core/erlang_compat/elixir_errors'; import Store from './core/store'; class Integer {} @@ -41,5 +42,6 @@ export default { global: globalState, erlang, maps, - lists + lists, + elixir_errors }; diff --git a/src/javascript/lib/core/erlang_compat/elixir_errors.js b/src/javascript/lib/core/erlang_compat/elixir_errors.js new file mode 100644 index 00000000..67efd473 --- /dev/null +++ b/src/javascript/lib/core/erlang_compat/elixir_errors.js @@ -0,0 +1,10 @@ +function warn(message) { + const messageString = message.join(''); + console.warn(`warning: ${messageString}`); + + return Symbol.for('ok'); +} + +export default { + warn +}; diff --git a/src/javascript/lib/core/erlang_compat/erlang.js b/src/javascript/lib/core/erlang_compat/erlang.js index 338c3a2b..670d9047 100644 --- a/src/javascript/lib/core/erlang_compat/erlang.js +++ b/src/javascript/lib/core/erlang_compat/erlang.js @@ -317,6 +317,18 @@ function binary_to_integer(str, base = 10) { return parseInt(str, base); } +function process_info(pid, item) { + if (item) { + if (item === Symbol.for('current_stacktrace')) { + return new ErlangTypes.Tuple(item, []); + } + + return new ErlangTypes.Tuple(item, null); + } + + return []; +} + export default { atom_to_binary, binary_to_atom, @@ -382,5 +394,6 @@ export default { trunc, tuple_size, binary_to_float, - binary_to_integer + binary_to_integer, + process_info }; From dc01dc76ea23afa43e5b63d6b2e275a21596a6c9 Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Thu, 20 Jul 2017 22:52:43 -0500 Subject: [PATCH 629/860] minify ElixirScript.Core.js --- priv/build/iife/ElixirScript.Core.js | 2564 +------------------------- 1 file changed, 6 insertions(+), 2558 deletions(-) diff --git a/priv/build/iife/ElixirScript.Core.js b/priv/build/iife/ElixirScript.Core.js index 2ffba822..f97d3ed7 100644 --- a/priv/build/iife/ElixirScript.Core.js +++ b/priv/build/iife/ElixirScript.Core.js @@ -1,2558 +1,6 @@ -var ElixirScript = (function () { -'use strict'; - -/* @flow */ - -class Variable { - constructor(name = null, default_value = Symbol.for('tailored.no_value')) { - this.name = name; - this.default_value = default_value; - } -} - -class Wildcard { - constructor() {} -} - -class StartsWith { - constructor(prefix) { - this.prefix = prefix; - } -} - -class Capture { - constructor(value) { - this.value = value; - } -} - -class HeadTail { - constructor() {} -} - -class Type { - constructor(type, objPattern = {}) { - this.type = type; - this.objPattern = objPattern; - } -} - -class Bound { - constructor(value) { - this.value = value; - } -} - -class BitStringMatch { - constructor(...values) { - this.values = values; - } - - length() { - return values.length; - } - - bit_size() { - return this.byte_size() * 8; - } - - byte_size() { - let s = 0; - - for (let val of this.values) { - s = s + val.unit * val.size / 8; - } - - return s; - } - - getValue(index) { - return this.values(index); - } - - getSizeOfValue(index) { - let val = this.getValue(index); - return val.unit * val.size; - } - - getTypeOfValue(index) { - return this.getValue(index).type; - } -} - -class NamedVariableResult { - constructor(name, value) { - this.name = name; - this.value = value; - } -} - -function variable(name = null, default_value = Symbol.for('tailored.no_value')) { - return new Variable(name, default_value); -} - -function wildcard() { - return new Wildcard(); -} - -function startsWith(prefix) { - return new StartsWith(prefix); -} - -function capture(value) { - return new Capture(value); -} - -function headTail() { - return new HeadTail(); -} - -function type(type, objPattern = {}) { - return new Type(type, objPattern); -} - -function bound(value) { - return new Bound(value); -} - -function bitStringMatch(...values) { - return new BitStringMatch(...values); -} - -function namedVariableResult(name, value) { - return new NamedVariableResult(name, value); -} - -/* @flow */ - -function is_number(value) { - return typeof value === 'number'; -} - -function is_string(value) { - return typeof value === 'string'; -} - -function is_boolean(value) { - return typeof value === 'boolean'; -} - -function is_symbol(value) { - return typeof value === 'symbol'; -} - -function is_object(value) { - return typeof value === 'object'; -} - -function is_variable(value) { - return value instanceof Variable; -} - -function is_null(value) { - return value === null; -} - -function is_array(value) { - return Array.isArray(value); -} - -function is_function(value) { - return Object.prototype.toString.call(value) == '[object Function]'; -} - -function is_map(value) { - return value instanceof Map; -} - -class Tuple { - constructor(...args) { - this.values = Object.freeze(args); - this.length = this.values.length; - } - - get(index) { - return this.values[index]; - } - - count() { - return this.values.length; - } - - [Symbol.iterator]() { - return this.values[Symbol.iterator](); - } - - toString() { - let i, - s = ''; - for (i = 0; i < this.values.length; i++) { - if (s !== '') { - s += ', '; - } - - const stringToAppend = this.values[i] ? this.values[i].toString() : ''; - - s += stringToAppend; - } - - return '{' + s + '}'; - } - - put_elem(index, elem) { - if (index === this.length) { - let new_values = this.values.concat([elem]); - return new Tuple(...new_values); - } - - let new_values = this.values.concat([]); - new_values.splice(index, 0, elem); - return new Tuple(...new_values); - } - - remove_elem(index) { - let new_values = this.values.concat([]); - new_values.splice(index, 1); - return new Tuple(...new_values); - } -} - -let process_counter = -1; - -class PID { - constructor() { - process_counter = process_counter + 1; - this.id = process_counter; - } - - toString() { - return 'PID#<0.' + this.id + '.0>'; - } -} - -let ref_counter = -1; - -class Reference { - constructor() { - ref_counter = ref_counter + 1; - this.id = ref_counter; - this.ref = Symbol(); - } - - toString() { - return 'Ref#<0.0.0.' + this.id + '>'; - } -} - -class BitString$1 { - constructor(...args) { - this.value = Object.freeze(this.process(args)); - this.length = this.value.length; - this.bit_size = this.length * 8; - this.byte_size = this.length; - } - - get(index) { - return this.value[index]; - } - - count() { - return this.value.length; - } - - slice(start, end = null) { - let s = this.value.slice(start, end); - let ms = s.map(elem => BitString$1.integer(elem)); - return new BitString$1(...ms); - } - - [Symbol.iterator]() { - return this.value[Symbol.iterator](); - } - - toString() { - var i, - s = ''; - for (i = 0; i < this.count(); i++) { - if (s !== '') { - s += ', '; - } - s += this.get(i).toString(); - } - - return '<<' + s + '>>'; - } - - process(bitStringParts) { - let processed_values = []; - - var i; - for (i = 0; i < bitStringParts.length; i++) { - let processed_value = this['process_' + bitStringParts[i].type](bitStringParts[i]); - - for (let attr of bitStringParts[i].attributes) { - processed_value = this['process_' + attr](processed_value); - } - - processed_values = processed_values.concat(processed_value); - } - - return processed_values; - } - - process_integer(value) { - return value.value; - } - - process_float(value) { - if (value.size === 64) { - return BitString$1.float64ToBytes(value.value); - } else if (value.size === 32) { - return BitString$1.float32ToBytes(value.value); - } - - throw new Error('Invalid size for float'); - } - - process_bitstring(value) { - return value.value.value; - } - - process_binary(value) { - return BitString$1.toUTF8Array(value.value); - } - - process_utf8(value) { - return BitString$1.toUTF8Array(value.value); - } - - process_utf16(value) { - return BitString$1.toUTF16Array(value.value); - } - - process_utf32(value) { - return BitString$1.toUTF32Array(value.value); - } - - process_signed(value) { - return new Uint8Array([value])[0]; - } - - process_unsigned(value) { - return value; - } - - process_native(value) { - return value; - } - - process_big(value) { - return value; - } - - process_little(value) { - return value.reverse(); - } - - process_size(value) { - return value; - } - - process_unit(value) { - return value; - } - - static integer(value) { - return BitString$1.wrap(value, { type: 'integer', unit: 1, size: 8 }); - } - - static float(value) { - return BitString$1.wrap(value, { type: 'float', unit: 1, size: 64 }); - } - - static bitstring(value) { - return BitString$1.wrap(value, { - type: 'bitstring', - unit: 1, - size: value.bit_size - }); - } - - static bits(value) { - return BitString$1.bitstring(value); - } - - static binary(value) { - return BitString$1.wrap(value, { - type: 'binary', - unit: 8, - size: value.length - }); - } - - static bytes(value) { - return BitString$1.binary(value); - } - - static utf8(value) { - return BitString$1.wrap(value, { type: 'utf8', unit: 1, size: value.length }); - } - - static utf16(value) { - return BitString$1.wrap(value, { - type: 'utf16', - unit: 1, - size: value.length * 2 - }); - } - - static utf32(value) { - return BitString$1.wrap(value, { - type: 'utf32', - unit: 1, - size: value.length * 4 - }); - } - - static signed(value) { - return BitString$1.wrap(value, {}, 'signed'); - } - - static unsigned(value) { - return BitString$1.wrap(value, {}, 'unsigned'); - } - - static native(value) { - return BitString$1.wrap(value, {}, 'native'); - } - - static big(value) { - return BitString$1.wrap(value, {}, 'big'); - } - - static little(value) { - return BitString$1.wrap(value, {}, 'little'); - } - - static size(value, count) { - return BitString$1.wrap(value, { size: count }); - } - - static unit(value, count) { - return BitString$1.wrap(value, { unit: count }); - } - - static wrap(value, opt, new_attribute = null) { - let the_value = value; - - if (!(value instanceof Object)) { - the_value = { value: value, attributes: [] }; - } - - the_value = Object.assign(the_value, opt); - - if (new_attribute) { - the_value.attributes.push(new_attribute); - } - - return the_value; - } - - static toUTF8Array(str) { - var utf8 = []; - for (var i = 0; i < str.length; i++) { - var charcode = str.charCodeAt(i); - if (charcode < 0x80) { - utf8.push(charcode); - } else if (charcode < 0x800) { - utf8.push(0xc0 | charcode >> 6, 0x80 | charcode & 0x3f); - } else if (charcode < 0xd800 || charcode >= 0xe000) { - utf8.push(0xe0 | charcode >> 12, 0x80 | charcode >> 6 & 0x3f, 0x80 | charcode & 0x3f); - } else { - // surrogate pair - i++; - // UTF-16 encodes 0x10000-0x10FFFF by - // subtracting 0x10000 and splitting the - // 20 bits of 0x0-0xFFFFF into two halves - charcode = 0x10000 + ((charcode & 0x3ff) << 10 | str.charCodeAt(i) & 0x3ff); - utf8.push(0xf0 | charcode >> 18, 0x80 | charcode >> 12 & 0x3f, 0x80 | charcode >> 6 & 0x3f, 0x80 | charcode & 0x3f); - } - } - return utf8; - } - - static toUTF16Array(str) { - var utf16 = []; - for (var i = 0; i < str.length; i++) { - var codePoint = str.codePointAt(i); - - if (codePoint <= 255) { - utf16.push(0); - utf16.push(codePoint); - } else { - utf16.push(codePoint >> 8 & 0xff); - utf16.push(codePoint & 0xff); - } - } - return utf16; - } - - static toUTF32Array(str) { - var utf32 = []; - for (var i = 0; i < str.length; i++) { - var codePoint = str.codePointAt(i); - - if (codePoint <= 255) { - utf32.push(0); - utf32.push(0); - utf32.push(0); - utf32.push(codePoint); - } else { - utf32.push(0); - utf32.push(0); - utf32.push(codePoint >> 8 & 0xff); - utf32.push(codePoint & 0xff); - } - } - return utf32; - } - - //http://stackoverflow.com/questions/2003493/javascript-float-from-to-bits - static float32ToBytes(f) { - var bytes = []; - - var buf = new ArrayBuffer(4); - new Float32Array(buf)[0] = f; - - let intVersion = new Uint32Array(buf)[0]; - - bytes.push(intVersion >> 24 & 0xff); - bytes.push(intVersion >> 16 & 0xff); - bytes.push(intVersion >> 8 & 0xff); - bytes.push(intVersion & 0xff); - - return bytes; - } - - static float64ToBytes(f) { - var bytes = []; - - var buf = new ArrayBuffer(8); - new Float64Array(buf)[0] = f; - - var intVersion1 = new Uint32Array(buf)[0]; - var intVersion2 = new Uint32Array(buf)[1]; - - bytes.push(intVersion2 >> 24 & 0xff); - bytes.push(intVersion2 >> 16 & 0xff); - bytes.push(intVersion2 >> 8 & 0xff); - bytes.push(intVersion2 & 0xff); - - bytes.push(intVersion1 >> 24 & 0xff); - bytes.push(intVersion1 >> 16 & 0xff); - bytes.push(intVersion1 >> 8 & 0xff); - bytes.push(intVersion1 & 0xff); - - return bytes; - } -} - -var ErlangTypes = { - Tuple, - PID, - Reference, - BitString: BitString$1 -}; - -/* @flow */ - -const BitString = ErlangTypes.BitString; - -function resolveSymbol(pattern) { - return function (value) { - return is_symbol(value) && value === pattern; - }; -} - -function resolveString(pattern) { - return function (value) { - return is_string(value) && value === pattern; - }; -} - -function resolveNumber(pattern) { - return function (value) { - return is_number(value) && value === pattern; - }; -} - -function resolveBoolean(pattern) { - return function (value) { - return is_boolean(value) && value === pattern; - }; -} - -function resolveFunction(pattern) { - return function (value) { - return is_function(value) && value === pattern; - }; -} - -function resolveNull(pattern) { - return function (value) { - return is_null(value); - }; -} - -function resolveBound(pattern) { - return function (value, args) { - if (typeof value === typeof pattern.value && value === pattern.value) { - return true; - } - - return false; - }; -} - -function resolveWildcard() { - return function () { - return true; - }; -} - -function resolveVariable(pattern) { - return function (value, args) { - if (pattern.name === null || pattern.name.startsWith('_')) { - args.push(value); - } else { - args.push(namedVariableResult(pattern.name, value)); - } - - return true; - }; -} - -function resolveHeadTail() { - return function (value, args) { - if (!is_array(value) || value.length < 2) { - return false; - } - - const head = value[0]; - const tail = value.slice(1); - - args.push(head); - args.push(tail); - - return true; - }; -} - -function resolveCapture(pattern) { - const matches = buildMatch(pattern.value); - - return function (value, args) { - if (matches(value, args)) { - args.push(value); - return true; - } - - return false; - }; -} - -function resolveStartsWith(pattern) { - const prefix = pattern.prefix; - - return function (value, args) { - if (is_string(value) && value.startsWith(prefix)) { - args.push(value.substring(prefix.length)); - return true; - } - - return false; - }; -} - -function resolveType(pattern) { - return function (value, args) { - if (value instanceof pattern.type) { - const matches = buildMatch(pattern.objPattern); - return matches(value, args); - } - - return false; - }; -} - -function resolveArray(pattern) { - const matches = pattern.map(x => buildMatch(x)); - - return function (value, args) { - if (!is_array(value) || value.length != pattern.length) { - return false; - } - - return value.every(function (v, i) { - return matches[i](value[i], args); - }); - }; -} - -function resolveMap(pattern) { - let matches = new Map(); - - const keys = Array.from(pattern.keys()); - - for (let key of keys) { - matches.set(key, buildMatch(pattern.get(key))); - } - - return function (value, args) { - if (!is_map(value) || pattern.size > value.size) { - return false; - } - - for (let key of keys) { - if (!value.has(key) || !matches.get(key)(value.get(key), args)) { - return false; - } - } - - return true; - }; -} - -function resolveObject(pattern) { - let matches = {}; - - const keys = Object.keys(pattern).concat(Object.getOwnPropertySymbols(pattern)); - - for (let key of keys) { - matches[key] = buildMatch(pattern[key]); - } - - return function (value, args) { - if (!is_object(value) || pattern.length > value.length) { - return false; - } - - for (let key of keys) { - if (!(key in value) || !matches[key](value[key], args)) { - return false; - } - } - - return true; - }; -} - -function resolveBitString(pattern) { - let patternBitString = []; - - for (let bitstringMatchPart of pattern.values) { - if (is_variable(bitstringMatchPart.value)) { - let size = getSize(bitstringMatchPart.unit, bitstringMatchPart.size); - fillArray(patternBitString, size); - } else { - patternBitString = patternBitString.concat(new BitString(bitstringMatchPart).value); - } - } - - let patternValues = pattern.values; - - return function (value, args) { - let bsValue = null; - - if (!is_string(value) && !(value instanceof BitString)) { - return false; - } - - if (is_string(value)) { - bsValue = new BitString(BitString.binary(value)); - } else { - bsValue = value; - } - - let beginningIndex = 0; - - for (let i = 0; i < patternValues.length; i++) { - let bitstringMatchPart = patternValues[i]; - - if (is_variable(bitstringMatchPart.value) && bitstringMatchPart.type == 'binary' && bitstringMatchPart.size === undefined && i < patternValues.length - 1) { - throw new Error('a binary field without size is only allowed at the end of a binary pattern'); - } - - let size = 0; - let bsValueArrayPart = []; - let patternBitStringArrayPart = []; - size = getSize(bitstringMatchPart.unit, bitstringMatchPart.size); - - if (i === patternValues.length - 1) { - bsValueArrayPart = bsValue.value.slice(beginningIndex); - patternBitStringArrayPart = patternBitString.slice(beginningIndex); - } else { - bsValueArrayPart = bsValue.value.slice(beginningIndex, beginningIndex + size); - patternBitStringArrayPart = patternBitString.slice(beginningIndex, beginningIndex + size); - } - - if (is_variable(bitstringMatchPart.value)) { - switch (bitstringMatchPart.type) { - case 'integer': - if (bitstringMatchPart.attributes && bitstringMatchPart.attributes.indexOf('signed') != -1) { - args.push(new Int8Array([bsValueArrayPart[0]])[0]); - } else { - args.push(new Uint8Array([bsValueArrayPart[0]])[0]); - } - break; - - case 'float': - if (size === 64) { - args.push(Float64Array.from(bsValueArrayPart)[0]); - } else if (size === 32) { - args.push(Float32Array.from(bsValueArrayPart)[0]); - } else { - return false; - } - break; - - case 'bitstring': - args.push(createBitString(bsValueArrayPart)); - break; - - case 'binary': - args.push(String.fromCharCode.apply(null, new Uint8Array(bsValueArrayPart))); - break; - - case 'utf8': - args.push(String.fromCharCode.apply(null, new Uint8Array(bsValueArrayPart))); - break; - - case 'utf16': - args.push(String.fromCharCode.apply(null, new Uint16Array(bsValueArrayPart))); - break; - - case 'utf32': - args.push(String.fromCharCode.apply(null, new Uint32Array(bsValueArrayPart))); - break; - - default: - return false; - } - } else if (!arraysEqual(bsValueArrayPart, patternBitStringArrayPart)) { - return false; - } - - beginningIndex = beginningIndex + size; - } - - return true; - }; -} - -function getSize(unit, size) { - return unit * size / 8; -} - -function arraysEqual(a, b) { - if (a === b) return true; - if (a == null || b == null) return false; - if (a.length != b.length) return false; - - for (var i = 0; i < a.length; ++i) { - if (a[i] !== b[i]) return false; - } - - return true; -} - -function fillArray(arr, num) { - for (let i = 0; i < num; i++) { - arr.push(0); - } -} - -function createBitString(arr) { - let integerParts = arr.map(elem => BitString.integer(elem)); - return new BitString(...integerParts); -} - -function resolveNoMatch() { - return function () { - return false; - }; -} - -const patternMap = new Map(); -patternMap.set(Variable.prototype, resolveVariable); -patternMap.set(Wildcard.prototype, resolveWildcard); -patternMap.set(HeadTail.prototype, resolveHeadTail); -patternMap.set(StartsWith.prototype, resolveStartsWith); -patternMap.set(Capture.prototype, resolveCapture); -patternMap.set(Bound.prototype, resolveBound); -patternMap.set(Type.prototype, resolveType); -patternMap.set(BitStringMatch.prototype, resolveBitString); -patternMap.set(Number.prototype, resolveNumber); -patternMap.set(Symbol.prototype, resolveSymbol); -patternMap.set(Map.prototype, resolveMap); -patternMap.set(Array.prototype, resolveArray); -patternMap.set(String.prototype, resolveString); -patternMap.set(Boolean.prototype, resolveBoolean); -patternMap.set(Function.prototype, resolveFunction); -patternMap.set(Object.prototype, resolveObject); - -function buildMatch(pattern) { - if (pattern === null) { - return resolveNull(pattern); - } - - if (typeof pattern === 'undefined') { - return resolveWildcard(pattern); - } - - const type$$1 = pattern.constructor.prototype; - const resolver = patternMap.get(type$$1); - - if (resolver) { - return resolver(pattern); - } - - if (typeof pattern === 'object') { - return resolveObject(pattern); - } - - return resolveNoMatch(); -} - -class MatchError extends Error { - constructor(arg) { - super(); - - if (typeof arg === 'symbol') { - this.message = 'No match for: ' + arg.toString(); - } else if (Array.isArray(arg)) { - let mappedValues = arg.map(x => { - if (x === null) { - return 'null'; - } else if (typeof x === 'undefined') { - return 'undefined'; - } - - return x.toString(); - }); - - this.message = 'No match for: ' + mappedValues; - } else { - this.message = 'No match for: ' + arg; - } - - this.stack = new Error().stack; - this.name = this.constructor.name; - } -} - -class Clause { - constructor(pattern, fn, guard = () => true) { - this.pattern = buildMatch(pattern); - this.arity = pattern.length; - this.optionals = getOptionalValues(pattern); - this.fn = fn; - this.guard = guard; - } -} - -function clause(pattern, fn, guard = () => true) { - return new Clause(pattern, fn, guard); -} - - - -function defmatch(...clauses) { - const arities = getArityMap(clauses); - - return function (...args) { - let [funcToCall, params] = findMatchingFunction(args, arities); - return funcToCall.apply(this, params); - }; -} - -function defmatchgen(...clauses) { - const arities = getArityMap(clauses); - - return function* (...args) { - let [funcToCall, params] = findMatchingFunction(args, arities); - return yield* funcToCall.apply(this, params); - }; -} - -function defmatchGen(...args) { - return defmatchgen(...args); -} - -function defmatchAsync(...clauses) { - const arities = getArityMap(clauses); - - return async function (...args) { - if (arities.has(args.length)) { - const arityClauses = arities.get(args.length); - - let funcToCall = null; - let params = null; - for (let processedClause of arityClauses) { - let result = []; - args = fillInOptionalValues(args, processedClause.arity, processedClause.optionals); - - const doesMatch = processedClause.pattern(args, result); - const [filteredResult, allNamesMatch] = checkNamedVariables(result); - - if (doesMatch && allNamesMatch && (await processedClause.guard.apply(this, result))) { - funcToCall = processedClause.fn; - params = result; - break; - } - } - - if (!funcToCall) { - console.error('No match for:', args); - throw new MatchError(args); - } - - return funcToCall.apply(this, params); - } else { - console.error('Arity of', args.length, 'not found. No match for:', args); - throw new MatchError(args); - } - }; -} - -function findMatchingFunction(args, arities) { - if (arities.has(args.length)) { - const arityClauses = arities.get(args.length); - - let funcToCall = null; - let params = null; - for (let processedClause of arityClauses) { - let result = []; - args = fillInOptionalValues(args, processedClause.arity, processedClause.optionals); - - const doesMatch = processedClause.pattern(args, result); - const [filteredResult, allNamesMatch] = checkNamedVariables(result); - - if (doesMatch && allNamesMatch && processedClause.guard.apply(this, filteredResult)) { - funcToCall = processedClause.fn; - params = filteredResult; - break; - } - } - - if (!funcToCall) { - console.error('No match for:', args); - throw new MatchError(args); - } - - return [funcToCall, params]; - } else { - console.error('Arity of', args.length, 'not found. No match for:', args); - throw new MatchError(args); - } -} - -function getArityMap(clauses) { - let map = new Map(); - - for (const clause of clauses) { - const range = getArityRange(clause); - - for (const arity of range) { - let arityClauses = []; - - if (map.has(arity)) { - arityClauses = map.get(arity); - } - - arityClauses.push(clause); - map.set(arity, arityClauses); - } - } - - return map; -} - -function getArityRange(clause) { - const min = clause.arity - clause.optionals.length; - const max = clause.arity; - - let range = [min]; - - while (range[range.length - 1] != max) { - range.push(range[range.length - 1] + 1); - } - - return range; -} - -function getOptionalValues(pattern) { - let optionals = []; - - for (let i = 0; i < pattern.length; i++) { - if (pattern[i] instanceof Variable && pattern[i].default_value != Symbol.for('tailored.no_value')) { - optionals.push([i, pattern[i].default_value]); - } - } - - return optionals; -} - -function fillInOptionalValues(args, arity, optionals) { - if (args.length === arity || optionals.length === 0) { - return args; - } - - if (args.length + optionals.length < arity) { - return args; - } - - let numberOfOptionalsToFill = arity - args.length; - let optionalsToRemove = optionals.length - numberOfOptionalsToFill; - - let optionalsToUse = optionals.slice(optionalsToRemove); - - for (let [index, value] of optionalsToUse) { - args.splice(index, 0, value); - if (args.length === arity) { - break; - } - } - - return args; -} - -function match(pattern, expr, guard = () => true) { - let result = []; - let processedPattern = buildMatch(pattern); - const doesMatch = processedPattern(expr, result); - const [filteredResult, allNamesMatch] = checkNamedVariables(result); - - if (doesMatch && allNamesMatch && guard.apply(this, filteredResult)) { - return filteredResult; - } else { - console.error('No match for:', expr); - throw new MatchError(expr); - } -} - -function checkNamedVariables(results) { - const namesMap = {}; - const filteredResults = []; - - for (let i = 0; i < results.length; i++) { - const current = results[i]; - if (current instanceof NamedVariableResult) { - if (namesMap[current.name] && namesMap[current.name] !== current.value) { - return [results, false]; - } else if (namesMap[current.name] && namesMap[current.name] === current.value) { - filteredResults.push(current.value); - } else { - namesMap[current.name] = current.value; - filteredResults.push(current.value); - } - } else { - filteredResults.push(current); - } - } - - return [filteredResults, true]; -} - -function match_or_default(pattern, expr, guard = () => true, default_value = null) { - let result = []; - let processedPattern = buildMatch(pattern); - const doesMatch = processedPattern(expr, result); - const [filteredResult, allNamesMatch] = checkNamedVariables(result); - - if (doesMatch && allNamesMatch && guard.apply(this, filteredResult)) { - return filteredResult; - } else { - return default_value; - } -} - -const NO_MATCH = Symbol(); - -function bitstring_generator(pattern, bitstring) { - return function () { - let returnResult = []; - let bsSlice = bitstring.slice(0, pattern.byte_size()); - let i = 1; - - while (bsSlice.byte_size == pattern.byte_size()) { - const result = match_or_default(pattern, bsSlice, () => true, NO_MATCH); - - if (result != NO_MATCH) { - const [value] = result; - returnResult.push(result); - } - - bsSlice = bitstring.slice(pattern.byte_size() * i, pattern.byte_size() * (i + 1)); - - i++; - } - - return returnResult; - }; -} - -function list_generator(pattern, list) { - return function () { - let returnResult = []; - for (let i of list) { - const result = match_or_default(pattern, i, () => true, NO_MATCH); - if (result != NO_MATCH) { - const [value] = result; - returnResult.push(value); - } - } - - return returnResult; - }; -} - -function list_comprehension(expression, generators) { - const generatedValues = run_generators(generators.pop()(), generators); - - let result = []; - - for (let value of generatedValues) { - if (expression.guard.apply(this, value)) { - result.push(expression.fn.apply(this, value)); - } - } - - return result; -} - -function run_generators(generator, generators) { - if (generators.length == 0) { - return generator.map(x => { - if (Array.isArray(x)) { - return x; - } else { - return [x]; - } - }); - } else { - const list = generators.pop(); - - let next_gen = []; - for (let j of list()) { - for (let i of generator) { - next_gen.push([j].concat(i)); - } - } - - return run_generators(next_gen, generators); - } -} - -function bitstring_comprehension(expression, generators) { - const generatedValues = run_generators(generators.pop()(), generators); - - let result = []; - - for (let value of generatedValues) { - if (expression.guard.apply(this, value)) { - result.push(expression.fn.apply(this, value)); - } - } - - result = result.map(x => ErlangTypes.BitString.integer(x)); - return new ErlangTypes.BitString(...result); -} - -var Patterns = { - defmatch, - match, - MatchError, - variable, - wildcard, - startsWith, - capture, - headTail, - type, - bound, - Clause, - clause, - bitStringMatch, - match_or_default, - defmatchgen, - list_comprehension, - list_generator, - bitstring_generator, - bitstring_comprehension, - defmatchGen, - defmatchAsync -}; - -// https://github.com/airportyh/protomorphism -class Protocol { - constructor(spec) { - this.registry = new Map(); - this.fallback = null; - - function createFun(funName) { - return function (...args) { - const thing = args[0]; - let fun = null; - - if (thing === null && this.hasImplementation(Symbol('null'))) { - fun = this.registry.get(Symbol)[funName]; - } else if (Number.isInteger(thing) && this.hasImplementation(Core.Integer)) { - fun = this.registry.get(Core.Integer)[funName]; - } else if (typeof thing === 'number' && !Number.isInteger(thing) && this.hasImplementation(Core.Float)) { - fun = this.registry.get(Core.Float)[funName]; - } else if (typeof thing === 'string' && this.hasImplementation(Core.BitString)) { - fun = this.registry.get(Core.BitString)[funName]; - } else if (thing && thing.has(Symbol.for('__struct__')) && this.hasImplementation(thing)) { - fun = this.registry.get(thing.get(Symbol.for('__struct__')).__MODULE__)[funName]; - } else if (thing !== null && this.hasImplementation(thing)) { - fun = this.registry.get(thing.constructor)[funName]; - } else if (this.fallback) { - fun = this.fallback[funName]; - } - - if (fun != null) { - const retval = fun.apply(this, args); - return retval; - } - - throw new Error(`No implementation found for ${thing}`); - }; - } - - for (const funName in spec) { - this[funName] = createFun(funName).bind(this); - } - } - - implementation(type, implementation) { - if (type === null) { - this.fallback = implementation; - } else { - this.registry.set(type, implementation); - } - } - - hasImplementation(thing) { - if (thing === Core.Integer || thing === Core.Float || thing === Core.BitString) { - return this.registry.has(thing); - } else if (thing && thing.has(Symbol.for('__struct__'))) { - return this.registry.has(thing.get(Symbol.for('__struct__')).__MODULE__); - } - - return this.registry.has(thing.constructor); - } -} - -function iterator_to_reducer(iterable, acc, fun) { - const iterator = iterable[Symbol.iterator](); - let x = iterator.next(); - let _acc = acc; - - while (x.done === false) { - _acc = fun(x.value, _acc.get(1)); - if (_acc.get(0) === Symbol.for('halt')) { - return new Core.Tuple(Symbol.for('halted'), _acc.get(1)); - } else if (_acc.get(0) === Symbol.for('suspend')) { - return new Core.Tuple(Symbol.for('suspended'), _acc.get(1), new_acc => { - return iterator_to_reducer(iterator, new_acc, fun); - }); - } - - x = iterator.next(); - } - - return new Core.Tuple(Symbol.for('done'), _acc.get(1)); -} - -function call_property(item, property) { - if (!property) { - if (item instanceof Function || typeof item === 'function') { - return item(); - } - - return item; - } - - if (item instanceof Map) { - let prop = null; - - if (item.has(property)) { - prop = property; - } else if (item.has(Symbol.for(property))) { - prop = Symbol.for(property); - } - - if (prop === null) { - throw new Error(`Property ${property} not found in ${item}`); - } - - if (item.get(prop) instanceof Function || typeof item.get(prop) === 'function') { - return item.get(prop)(); - } - return item.get(prop); - } - - let prop = null; - - if (typeof item === 'number' || typeof item === 'symbol' || typeof item === 'boolean' || typeof item === 'string') { - if (item[property] !== undefined) { - prop = property; - } else if (item[Symbol.for(property)] !== undefined) { - prop = Symbol.for(property); - } - } else if (property in item) { - prop = property; - } else if (Symbol.for(property) in item) { - prop = Symbol.for(property); - } - - if (prop === null) { - throw new Error(`Property ${property} not found in ${item}`); - } - - if (item[prop] instanceof Function || typeof item[prop] === 'function') { - return item[prop](); - } - return item[prop]; -} - -function defprotocol(spec) { - return new Protocol(spec); -} - -function defimpl(protocol, type, impl) { - protocol.implementation(type, impl); -} - -function build_namespace(ns, ns_string) { - let parts = ns_string.split('.'); - const root = ns; - let parent = ns; - - if (parts[0] === 'Elixir') { - parts = parts.slice(1); - } - - for (const part of parts) { - if (typeof parent[part] === 'undefined') { - parent[part] = {}; - } - - parent = parent[part]; - } - - root.__table__ = ns.__table__ || {}; - root.__table__[Symbol.for(ns_string)] = parent; - - return parent; -} - -function map_to_object(map) { - const object = {}; - - for (const [key, value] of map.entries()) { - if (value instanceof Map) { - object[key] = map_to_object(value); - } else { - object[key] = value; - } - } - - return object; -} - -var Functions = { - call_property, - defprotocol, - defimpl, - build_namespace, - iterator_to_reducer, - map_to_object -}; - -function _case(condition, clauses) { - return Core.Patterns.defmatch(...clauses)(condition); -} - -function cond(...clauses) { - for (const clause of clauses) { - if (clause[0]) { - return clause[1](); - } - } - - throw new Error(); -} - -function _for(expression, generators, collectable_protocol, into = []) { - let [result, fun] = collectable_protocol.into(into); - - const generatedValues = run_list_generators(generators.pop()(), generators); - - for (const value of generatedValues) { - if (expression.guard.apply(this, value)) { - result = fun(result, new Core.Tuple(Symbol.for('cont'), expression.fn.apply(this, value))); - } - } - - return fun(result, Symbol.for('done')); -} - -function run_list_generators(generator, generators) { - if (generators.length == 0) { - return generator.map(x => { - if (Array.isArray(x)) { - return x; - } - return [x]; - }); - } - const list = generators.pop(); - - const next_gen = []; - for (const j of list()) { - for (const i of generator) { - next_gen.push([j].concat(i)); - } - } - - return run_list_generators(next_gen, generators); -} - -function _try(do_fun, rescue_function, catch_fun, else_function, after_function) { - let result = null; - - try { - result = do_fun(); - } catch (e) { - let ex_result = null; - - if (rescue_function) { - try { - ex_result = rescue_function(e); - return ex_result; - } catch (ex) { - if (ex instanceof Core.Patterns.MatchError) { - throw ex; - } - } - } - - if (catch_fun) { - try { - ex_result = catch_fun(e); - return ex_result; - } catch (ex) { - if (ex instanceof Core.Patterns.MatchError) { - throw ex; - } - } - } - - throw e; - } finally { - if (after_function) { - after_function(); - } - } - - if (else_function) { - try { - return else_function(result); - } catch (ex) { - if (ex instanceof Core.Patterns.MatchError) { - throw new Error('No Match Found in Else'); - } - - throw ex; - } - } else { - return result; - } -} - -function _with(...args) { - let argsToPass = []; - let successFunction = null; - let elseFunction = null; - - if (typeof args[args.length - 2] === 'function') { - [successFunction, elseFunction] = args.splice(-2); - } else { - successFunction = args.pop(); - } - - for (let i = 0; i < args.length; i++) { - const [pattern, func] = args[i]; - - const result = func(...argsToPass); - - const patternResult = Core.Patterns.match_or_default(pattern, result); - - if (patternResult == null) { - if (elseFunction) { - return elseFunction.call(null, result); - } - return result; - } - - argsToPass = argsToPass.concat(patternResult); - } - - return successFunction(...argsToPass); -} - -function receive(clauses, after) { - console.warn('Receive not supported'); -} - -var SpecialForms = { - _case, - cond, - _for, - _try, - _with, - receive -}; - -// http://erlang.org/doc/man/erlang.html -function atom_to_binary(atom, encoding = Symbol.for('utf8')) { - if (encoding !== Symbol.for('utf8')) { - throw new Error(`unsupported encoding ${encoding}`); - } - - if (atom.__MODULE__) { - return Symbol.keyFor(atom.__MODULE__); - } - - return Symbol.keyFor(atom); -} - -function binary_to_atom(binary, encoding = Symbol.for('utf8')) { - if (encoding !== Symbol.for('utf8')) { - throw new Error(`unsupported encoding ${encoding}`); - } - - return Symbol.for(binary); -} - -function binary_to_existing_atom(binary, encoding = Symbol.for('utf8')) { - return binary_to_atom(binary, encoding); -} - -function list_concatenation(list1, list2) { - return list1.concat(list2); -} - -function list_subtraction(list1, list2) { - const list = [...list1]; - - for (const item of list2) { - const index = list.indexOf(item); - - if (index > -1) { - list.splice(index, 1); - } - } - - return list; -} - -function plus(left, right) { - if (!right) { - return +left; - } - - return left + right; -} - -function minus(left, right) { - if (!right) { - return -left; - } - - return left - right; -} - -function multiply(left, right) { - return left * right; -} - -function div(left, right) { - return left / right; -} - -function equal(left, right) { - return left == right; -} - -function doesNotEqual(left, right) { - return left != right; -} - -function greaterThan(left, right) { - return left > right; -} - -function greaterThanOrEqualTo(left, right) { - return left >= right; -} - -function lessThan(left, right) { - return left < right; -} - -function lessThanOrEqualTo(left, right) { - return left <= right; -} - -function strictlyEqual(left, right) { - return left === right; -} - -function doesNotStrictlyEqual(left, right) { - return left !== right; -} - -function and(left, right) { - return left && right; -} - -function or(left, right) { - return left || right; -} - -function not(x) { - return !x; -} - -function rem(left, right) { - return left % right; -} - -function band(left, right) { - return left & right; -} - -function bor(left, right) { - return left | right; -} - -function bnot(x) { - return ~x; -} - -function bsl(left, right) { - return left << right; -} - -function bsr(left, right) { - return left >> right; -} - -function bxor(left, right) { - return left ^ right; -} - -function is_atom(value) { - return typeof value === 'symbol' || value instanceof Symbol || value.__MODULE__; -} - -function is_bitstring$1(value) { - return value instanceof ErlangTypes.BitString; -} - -function is_boolean$1(value) { - return typeof value === 'boolean' || value instanceof Boolean; -} - -function is_number$1(value) { - return typeof value === 'number' || value instanceof Number; -} - -function is_float(value) { - return is_number$1(value) && !Number.isInteger(value); -} - -function is_function$1(value) { - return typeof value === 'function' || value instanceof Function; -} - -function is_integer(value) { - return Number.isInteger(value); -} - -function is_list(value) { - return Array.isArray(value); -} - -function is_map$1(value) { - return value instanceof Map; -} - -function is_pid(value) { - return value instanceof ErlangTypes.PID; -} - -function is_port() { - return false; -} - -function is_reference(value) { - return value instanceof ErlangTypes.Reference; -} - -function is_tuple(value) { - return value instanceof ErlangTypes.Tuple; -} - -function is_binary(value) { - return typeof value === 'string' || value instanceof String; -} - -function element(n, tuple) { - return tuple.get(n - 1); -} - -function setelement(index, tuple1, value) { - const tupleData = [...tuple1.values]; - - tupleData[index - 1] = value; - - return new ErlangTypes.Tuple(...tupleData); -} - -function make_tuple(arity, initialValue) { - const list = []; - - for (let i = 0; i < arity; i++) { - list.push(initialValue); - } - - return new ErlangTypes.Tuple(...list); -} - -function insert_element(index, tuple, term) { - const list = [...tuple.values]; - list.splice(index - 1, 0, term); - - return new ErlangTypes.Tuple(...list); -} - -function append_element(tuple, term) { - const list = [...tuple.values]; - list.push(term); - - return new ErlangTypes.Tuple(...list); -} - -function delete_element(index, tuple) { - const list = [...tuple.values]; - list.splice(index - 1, 1); - - return new ErlangTypes.Tuple(...list); -} - -function tuple_to_list(tuple) { - const list = [...tuple.values]; - return list; -} - -function abs(number) { - return Math.abs(number); -} - -function apply(...args) { - if (args.length === 2) { - return args[0].apply(this, ...args[1]); - } - - return args[0][atom_to_binary(args[1])].apply(this, ...args[2]); -} - -function binary_part(binary, start, length) { - return binary.substring(start, start + length); -} - -function bit_size(bitstring) { - return bitstring.bit_size; -} - -function byte_size(bitstring) { - return bitstring.byte_size; -} - -function hd(list) { - return list[0]; -} - -function length(list) { - return list.length; -} - -function make_ref() { - return new ErlangTypes.Reference(); -} - -function map_size(map) { - return map.size; -} - -function max(first, second) { - return Math.max(first, second); -} - -function min(first, second) { - return Math.min(first, second); -} - -function round(number) { - return Math.round(number); -} - -function tl(list) { - return list.slice(1); -} - -function trunc(number) { - return Math.trunc(number); -} - -function tuple_size(tuple) { - return tuple.length; -} - -function binary_to_float(str) { - return parseFloat(str); -} - -function binary_to_integer(str, base = 10) { - return parseInt(str, base); -} - -function process_info(pid, item) { - if (item) { - if (item === Symbol.for('current_stacktrace')) { - return new ErlangTypes.Tuple(item, []); - } - - return new ErlangTypes.Tuple(item, null); - } - - return []; -} - -var erlang = { - atom_to_binary, - binary_to_atom, - binary_to_existing_atom, - list_concatenation, - list_subtraction, - plus, - minus, - multiply, - div, - equal, - greaterThan, - greaterThanOrEqualTo, - lessThan, - lessThanOrEqualTo, - doesNotEqual, - strictlyEqual, - doesNotStrictlyEqual, - and, - or, - not, - rem, - band, - bor, - bsl, - bsr, - bxor, - bnot, - is_bitstring: is_bitstring$1, - is_boolean: is_boolean$1, - is_float, - is_function: is_function$1, - is_integer, - is_list, - is_map: is_map$1, - is_number: is_number$1, - is_pid, - is_port, - is_reference, - is_tuple, - is_atom, - is_binary, - element, - setelement, - make_tuple, - insert_element, - append_element, - delete_element, - tuple_to_list, - abs, - apply, - binary_part, - bit_size, - byte_size, - hd, - length, - make_ref, - map_size, - max, - min, - round, - tl, - trunc, - tuple_size, - binary_to_float, - binary_to_integer, - process_info -}; - -// http://erlang.org/doc/man/maps.html -const OK = Symbol.for('ok'); -const ERROR = Symbol.for('error'); -const BADMAP = Symbol.for('badmap'); -const BADKEY = Symbol.for('badkey'); - -function find(key, map) { - if (erlang.is_map(map) === false) { - return new ErlangTypes.Tuple(BADMAP, map); - } - - const value = map.get(key); - - if (typeof value !== 'undefined') { - return new ErlangTypes.Tuple(OK, value); - } - - return ERROR; -} - -function fold(fun, init, map) { - let acc = init; - - for (const [key, value] of map.entries()) { - acc = fun(key, value, acc); - } - - return acc; -} - -function remove(key, map1) { - if (erlang.is_map(map1) === false) { - return new ErlangTypes.Tuple(BADMAP, map1); - } - - const map2 = new Map(map1); - - map2.delete(key); - - return map2; -} - -function to_list(map) { - if (erlang.is_map(map) === false) { - return new ErlangTypes.Tuple(BADMAP, map); - } - - const list = []; - - for (const [key, value] of map.entries()) { - list.push(new ErlangTypes.Tuple(key, value)); - } - - return list; -} - -function from_list(list) { - return list.reduce((acc, item) => { - const [key, value] = item; - acc.set(key, value); - - return acc; - }, new Map()); -} - -function keys(map) { - if (erlang.is_map(map) === false) { - return new ErlangTypes.Tuple(BADMAP, map); - } - - return Array.from(map.keys()); -} - -function values$1(map) { - if (erlang.is_map(map) === false) { - return new ErlangTypes.Tuple(BADMAP, map); - } - - return Array.from(map.values()); -} - -function is_key(key, map) { - return map.has(key); -} - -function put(key, value, map1) { - if (erlang.is_map(map1) === false) { - return new ErlangTypes.Tuple(BADMAP, map1); - } - - const map2 = new Map(map1); - map2.set(key, value); - - return map2; -} - -function merge(map1, map2) { - if (erlang.is_map(map1) === false) { - return new ErlangTypes.Tuple(BADMAP, map1); - } - - if (erlang.is_map(map2) === false) { - return new ErlangTypes.Tuple(BADMAP, map2); - } - - return new Map([...map1, ...map2]); -} - -function update(key, value, map1) { - if (erlang.is_map(map1) === false) { - return new ErlangTypes.Tuple(BADMAP, map1); - } - - if (is_key(key, map1) === false) { - return new ErlangTypes.Tuple(BADKEY, key); - } - - return new Map([...map1, [key, value]]); -} - -function get(...args) { - const key = args[0]; - const map = args[1]; - - if (erlang.is_map(map) === false) { - return new ErlangTypes.Tuple(BADMAP, map); - } - - if (is_key(key)) { - return map.get(key); - } - - if (args.length === 3) { - return args[2]; - } - - return new ErlangTypes.Tuple(BADKEY, key); -} - -function take(key, map1) { - if (erlang.is_map(map1) === false) { - return new ErlangTypes.Tuple(BADMAP, map1); - } - - if (!is_key(key)) { - return ERROR; - } - - const value = map1.get(key); - const map2 = new Map(map1); - map2.delete(key); - - return new ErlangTypes.Tuple(value, map2); -} - -var maps = { - find, - fold, - remove, - to_list, - from_list, - keys, - values: values$1, - is_key, - put, - merge, - update, - get, - take -}; - -// http://erlang.org/doc/man/lists.html -function reverse(list) { - return [...list].reverse(); -} - -function foreach(fun, list) { - list.forEach(x => fun(x)); - - return Symbol.for('ok'); -} - -function duplicate(n, elem) { - const list = []; - - while (list.length < n) { - list.push(elem); - } - - return list; -} - -function flatten(deepList, tail = []) { - const val = deepList.reduce((acc, value) => { - if (Array.isArray(value)) { - return acc.concat(flatten(value)); - } - - return acc.concat(value); - }, []); - - return val.concat(tail); -} - -function foldl(fun, acc0, list) { - return list.reduce((acc, value) => { - return fun(value, acc); - }, acc0); -} - -function foldr(fun, acc0, list) { - return foldl(fun, acc0, reverse(list)); -} - -function keyfind(key, n, tupleList) { - for (const tuple of tupleList) { - if (tuple.get(n - 1) === key) { - return tuple; - } - } - - return false; -} - -function keymember(key, n, tupleList) { - if (keyfind(key, n, tupleList) === false) { - return false; - } - - return true; -} - -function keyreplace(key, n, tupleList, newTuple) { - const newTupleList = [...tupleList]; - - for (let index = 0; index < newTupleList.length; index++) { - if (newTupleList[index].get(n - 1) === key) { - newTupleList[index] = newTuple; - return newTupleList; - } - } - - return newTupleList; -} - -function keysort(n, tupleList) { - const newTupleList = [...tupleList]; - - return newTupleList.sort((a, b) => { - if (a.get(n - 1) < b.get(n - 1)) { - return -1; - } else if (a.get(n - 1) > b.get(n - 1)) { - return 1; - } - - return 0; - }); -} - -function keystore(key, n, tupleList, newTuple) { - const newTupleList = [...tupleList]; - - for (let index = 0; index < newTupleList.length; index++) { - if (newTupleList[index].get(n - 1) === key) { - newTupleList[index] = newTuple; - return newTupleList; - } - } - - return newTupleList.concat(newTuple); -} - -function keydelete(key, n, tupleList) { - const newTupleList = []; - let deleted = false; - - for (let index = 0; index < tupleList.length; index++) { - if (deleted === false && tupleList[index].get(n - 1) === key) { - deleted = true; - } else { - newTupleList.push(tupleList[index]); - } - } - - return newTupleList; -} - -function keytake(key, n, tupleList) { - const result = keyfind(key, n, tupleList); - - if (result !== false) { - return new ErlangTypes.Tuple(result.get(n - 1), result, keydelete(key, n, tupleList)); - } - - return false; -} - -function mapfoldl(fun, acc0, list1) { - const listResult = []; - let accResult = acc0; - - for (const item of list1) { - const tuple = fun(item, accResult); - listResult.push(tuple.get(0)); - accResult = tuple.get(1); - } - - return new ErlangTypes.Tuple(listResult, accResult); -} - -function concat(things) { - return things.map(v => v.toString()).join(); -} - -function map(fun, list) { - return list.map(value => fun(value)); -} - -function filter(pred, list1) { - return list1.filter(x => pred(x)); -} - -function filtermap(fun, list1) { - const list2 = []; - - for (const item of list1) { - const value = fun(item); - - if (value === true) { - list2.push(item); - } else if (value instanceof ErlangTypes.Tuple && value.get(0) === true) { - list2.push(value.get(1)); - } - } - - return list2; -} - -function member(elem, list) { - for (const item of list) { - if (item === elem) { - return true; - } - } - - return false; -} - -function all(pred, list) { - for (const item of list) { - if (pred(item) === false) { - return false; - } - } - - return true; -} - -function any(pred, list) { - for (const item of list) { - if (pred(item) === true) { - return true; - } - } - - return false; -} - -function splitwith(pred, list) { - let switchToList2 = false; - const list1 = []; - const list2 = []; - - for (const item of list) { - if (switchToList2 === true) { - list2.push(item); - } else if (pred(item) === true) { - list1.push(item); - } else { - switchToList2 = true; - list2.push(item); - } - } - - return new ErlangTypes.Tuple(list1, list2); -} - -function sort(...args) { - if (args.length === 1) { - const list2 = [...args[0]]; - return list2.sort(); - } - - const fun = args[0]; - const list2 = [...args[1]]; - - return list2.sort((a, b) => { - const result = fun(a, b); - - if (result === true) { - return -1; - } - - return 1; - }); -} - -var lists = { - reverse, - foreach, - duplicate, - flatten, - foldl, - foldr, - keydelete, - keyfind, - keymember, - keyreplace, - keysort, - keystore, - keytake, - mapfoldl, - concat, - map, - filter, - filtermap, - member, - all, - any, - splitwith, - sort -}; - -function warn(message) { - const messageString = message.join(''); - console.warn(`warning ${messageString}`); - - return Symbol.for('ok'); -} - -var elixir_errors = { - warn -}; - -function get_key(key) { - let real_key = key; - - if (__elixirscript_names__.has(key)) { - real_key = __elixirscript_names__.get(key); - } - - if (__elixirscript_store__.has(real_key)) { - return real_key; - } - - throw new Error(`Key ${real_key} not found`); -} - -function create(value, name = null) { - const key = new Core.PID(); - - if (name !== null) { - __elixirscript_names__.set(name, key); - } - - return __elixirscript_store__.set(key, value); -} - -function update$1(key, value) { - const real_key = get_key(key); - return __elixirscript_store__.set(real_key, value); -} - -function read(key) { - const real_key = get_key(key); - return __elixirscript_store__.get(real_key); -} - -function remove$1(key) { - const real_key = get_key(key); - return __elixirscript_store__.delete(real_key); -} - -var Store = { - create, - update: update$1, - read, - remove: remove$1 -}; - -class Integer {} -class Float {} - -function get_global() { - if (typeof self !== 'undefined') { - return self; - } else if (typeof window !== 'undefined') { - return window; - } else if (typeof global !== 'undefined') { - return global; - } - - console.warn('No global state found'); - return null; -} - -const globalState = get_global(); - -globalState.__elixirscript_store__ = new Map(); -globalState.__elixirscript_names__ = new Map(); - -var Core = { - Tuple: ErlangTypes.Tuple, - PID: ErlangTypes.PID, - BitString: ErlangTypes.BitString, - Patterns, - Integer, - Float, - Functions, - SpecialForms, - Store, - global: globalState, - erlang, - maps, - lists, - elixir_errors -}; - -var elixir = { - Core -}; - -return elixir; - -}()); +var ElixirScript=function(){'use strict';/* @flow */function namedVariableResult(a,b){return new NamedVariableResult(a,b)}/* @flow */function is_number(a){return'number'==typeof a}function is_string(a){return'string'==typeof a}function is_boolean(a){return'boolean'==typeof a}function is_symbol(a){return'symbol'==typeof a}function is_object(a){return'object'==typeof a}function is_variable(a){return a instanceof Variable}function is_null(a){return null===a}function is_array(a){return Array.isArray(a)}function is_function(a){return'[object Function]'==Object.prototype.toString.call(a)}function is_map(a){return a instanceof Map}function resolveNull(){return function(a){return is_null(a)}}function resolveWildcard(){return function(){return!0}}function resolveObject(a){let b={};const c=Object.keys(a).concat(Object.getOwnPropertySymbols(a));for(let d of c)b[d]=buildMatch(a[d]);return function(d,e){if(!is_object(d)||a.length>d.length)return!1;for(let a of c)if(!(a in d)||!b[a](d[a],e))return!1;return!0}}function getSize(a,b){return a*b/8}function arraysEqual(c,a){if(c===a)return!0;if(null==c||null==a)return!1;if(c.length!=a.length)return!1;for(var b=0;be.integer(a));return new e(...b)}function resolveNoMatch(){return function(){return!1}}function buildMatch(a){if(null===a)return resolveNull(a);if('undefined'==typeof a)return resolveWildcard(a);const b=a.constructor.prototype,c=f.get(b);return c?c(a):'object'==typeof a?resolveObject(a):resolveNoMatch()}function defmatchgen(...a){const b=getArityMap(a);return function*(...a){let[c,d]=findMatchingFunction(a,b);return yield*c.apply(this,d)}}function findMatchingFunction(a,b){if(b.has(a.length)){const c=b.get(a.length);let d=null,e=null;for(let b of c){let c=[];a=fillInOptionalValues(a,b.arity,b.optionals);const f=b.pattern(a,c),[g,h]=checkNamedVariables(c);if(f&&h&&b.guard.apply(this,g)){d=b.fn,e=g;break}}if(!d)throw console.error('No match for:',a),new MatchError(a);return[d,e]}throw console.error('Arity of',a.length,'not found. No match for:',a),new MatchError(a)}function getArityMap(a){let b=new Map;for(const c of a){const a=getArityRange(c);for(const d of a){let a=[];b.has(d)&&(a=b.get(d)),a.push(c),b.set(d,a)}}return b}function getArityRange(a){const b=a.arity-a.optionals.length,c=a.arity;let d=[b];for(;d[d.length-1]!=c;)d.push(d[d.length-1]+1);return d}function getOptionalValues(a){let b=[];for(let c=0;c!0,d=null){let e=[],f=buildMatch(a);const g=f(b,e),[h,i]=checkNamedVariables(e);return g&&i&&c.apply(this,h)?h:d}function run_generators(a,b){if(0==b.length)return a.map((a)=>{return Array.isArray(a)?a:[a]});const c=b.pop();let d=[];for(let e of c())for(let b of a)d.push([e].concat(b));return run_generators(d,b)}function iterator_to_reducer(a,b,c){const d=a[Symbol.iterator]();let e=d.next(),f=b;for(;!1===e.done;){if(f=c(e.value,f.get(1)),f.get(0)===Symbol.for('halt'))return new n.Tuple(Symbol.for('halted'),f.get(1));if(f.get(0)===Symbol.for('suspend'))return new n.Tuple(Symbol.for('suspended'),f.get(1),(a)=>{return iterator_to_reducer(d,a,c)});e=d.next()}return new n.Tuple(Symbol.for('done'),f.get(1))}function map_to_object(a){const b={};for(const[c,d]of a.entries())b[c]=d instanceof Map?map_to_object(d):d;return b}function run_list_generators(a,b){if(0==b.length)return a.map((a)=>{return Array.isArray(a)?a:[a]});const c=b.pop(),d=[];for(const e of c())for(const b of a)d.push([e].concat(b));return run_list_generators(d,b)}// http://erlang.org/doc/man/erlang.html +function atom_to_binary(a,b=Symbol.for('utf8')){if(b!==Symbol.for('utf8'))throw new Error(`unsupported encoding ${b}`);return a.__MODULE__?Symbol.keyFor(a.__MODULE__):Symbol.keyFor(a)}function binary_to_atom(a,b=Symbol.for('utf8')){if(b!==Symbol.for('utf8'))throw new Error(`unsupported encoding ${b}`);return Symbol.for(a)}function is_number$1(a){return'number'==typeof a||a instanceof Number}function is_key(a,b){return b.has(a)}// http://erlang.org/doc/man/lists.html +function reverse(a){return[...a]}function flatten(a,b=[]){const c=a.reduce((a,b)=>{return Array.isArray(b)?a.concat(flatten(b)):a.concat(b)},[]);return c.concat(b)}function foldl(a,b,c){return c.reduce((b,c)=>{return a(c,b)},b)}function keyfind(a,b,c){for(const d of c)if(d.get(b-1)===a)return d;return!1}function keydelete(a,b,c){const d=[];let e=!1;for(let f=0;fBitString$1.integer(a));return new BitString$1(...d)}[Symbol.iterator](){return this.value[Symbol.iterator]()}toString(){var a,b='';for(a=0;a>'}process(a){let b=[];var c;for(c=0;cb?c.push(b):2048>b?c.push(192|b>>6,128|63&b):55296>b||57344<=b?c.push(224|b>>12,128|63&b>>6,128|63&b):(d++,b=65536+((1023&b)<<10|1023&a.charCodeAt(d)),c.push(240|b>>18,128|63&b>>12,128|63&b>>6,128|63&b));return c}static toUTF16Array(a){for(var b,c=[],d=0;d=b?(c.push(0),c.push(b)):(c.push(255&b>>8),c.push(255&b));return c}static toUTF32Array(a){for(var b,c=[],d=0;d=b?(c.push(0),c.push(0),c.push(0),c.push(b)):(c.push(0),c.push(0),c.push(255&b>>8),c.push(255&b));return c}//http://stackoverflow.com/questions/2003493/javascript-float-from-to-bits +static float32ToBytes(a){var b=[],c=new ArrayBuffer(4);new Float32Array(c)[0]=a;let d=new Uint32Array(c)[0];return b.push(255&d>>24),b.push(255&d>>16),b.push(255&d>>8),b.push(255&d),b}static float64ToBytes(a){var b=[],c=new ArrayBuffer(8);new Float64Array(c)[0]=a;var d=new Uint32Array(c)[0],e=new Uint32Array(c)[1];return b.push(255&e>>24),b.push(255&e>>16),b.push(255&e>>8),b.push(255&e),b.push(255&d>>24),b.push(255&d>>16),b.push(255&d>>8),b.push(255&d),b}}var d={Tuple,PID:class PID{constructor(){++b,this.id=b}toString(){return'PID#<0.'+this.id+'.0>'}},Reference:class Reference{constructor(){++c,this.id=c,this.ref=Symbol()}toString(){return'Ref#<0.0.0.'+this.id+'>'}},BitString:BitString$1};/* @flow */const e=d.BitString,f=new Map;f.set(Variable.prototype,function resolveVariable(a){return function(b,c){return null===a.name||a.name.startsWith('_')?c.push(b):c.push(namedVariableResult(a.name,b)),!0}}),f.set(Wildcard.prototype,resolveWildcard),f.set(HeadTail.prototype,function resolveHeadTail(){return function(a,b){if(!is_array(a)||2>a.length)return!1;const c=a[0],d=a.slice(1);return b.push(c),b.push(d),!0}}),f.set(StartsWith.prototype,function resolveStartsWith(a){const b=a.prefix;return function(a,c){return is_string(a)&&a.startsWith(b)&&(c.push(a.substring(b.length)),!0)}}),f.set(Capture.prototype,function resolveCapture(a){const b=buildMatch(a.value);return function(a,c){return!!b(a,c)&&(c.push(a),!0)}}),f.set(Bound.prototype,function resolveBound(a){return function(b){return typeof b==typeof a.value&&b===a.value}}),f.set(Type.prototype,function resolveType(a){return function(b,c){if(b instanceof a.type){const d=buildMatch(a.objPattern);return d(b,c)}return!1}}),f.set(BitStringMatch.prototype,function resolveBitString(a){let b=[];for(let c of a.values)if(is_variable(c.value)){let a=getSize(c.unit,c.size);fillArray(b,a)}else b=b.concat(new e(c).value);let c=a.values;return function(a,d){var f=String.fromCharCode;let g=null;if(!is_string(a)&&!(a instanceof e))return!1;g=is_string(a)?new e(e.binary(a)):a;let h=0;for(let e,j=0;jd.size)return!1;for(let a of c)if(!d.has(a)||!b.get(a)(d.get(a),e))return!1;return!0}}),f.set(Array.prototype,function resolveArray(a){const b=a.map((a)=>buildMatch(a));return function(c,d){return is_array(c)&&c.length==a.length&&c.every(function(a,e){return b[e](c[e],d)})}}),f.set(String.prototype,function resolveString(a){return function(b){return is_string(b)&&b===a}}),f.set(Boolean.prototype,function resolveBoolean(a){return function(b){return is_boolean(b)&&b===a}}),f.set(Function.prototype,function resolveFunction(a){return function(b){return is_function(b)&&b===a}}),f.set(Object.prototype,resolveObject);class MatchError extends Error{constructor(a){if(super(),'symbol'==typeof a)this.message='No match for: '+a.toString();else if(Array.isArray(a)){let b=a.map((a)=>{return null===a?'null':'undefined'==typeof a?'undefined':a.toString()});this.message='No match for: '+b}else this.message='No match for: '+a;this.stack=new Error().stack,this.name=this.constructor.name}}class Clause{constructor(a,b,c=()=>!0){this.pattern=buildMatch(a),this.arity=a.length,this.optionals=getOptionalValues(a),this.fn=b,this.guard=c}}const g=Symbol();// https://github.com/airportyh/protomorphism +class Protocol{constructor(b){function createFun(b){return function(...c){const d=c[0];let e=null;if(null===d&&this.hasImplementation(Symbol('null'))?e=this.registry.get(Symbol)[b]:a(d)&&this.hasImplementation(n.Integer)?e=this.registry.get(n.Integer)[b]:'number'==typeof d&&!a(d)&&this.hasImplementation(n.Float)?e=this.registry.get(n.Float)[b]:'string'==typeof d&&this.hasImplementation(n.BitString)?e=this.registry.get(n.BitString)[b]:d&&d.has(Symbol.for('__struct__'))&&this.hasImplementation(d)?e=this.registry.get(d.get(Symbol.for('__struct__')).__MODULE__)[b]:null!==d&&this.hasImplementation(d)?e=this.registry.get(d.constructor)[b]:this.fallback&&(e=this.fallback[b]),null!=e){const a=e.apply(this,c);return a}throw new Error(`No implementation found for ${d}`)}}for(const a in this.registry=new Map,this.fallback=null,b)this[a]=createFun(a).bind(this)}implementation(a,b){null===a?this.fallback=b:this.registry.set(a,b)}hasImplementation(a){if(a===n.Integer||a===n.Float||a===n.BitString)return this.registry.has(a);return a&&a.has(Symbol.for('__struct__'))?this.registry.has(a.get(Symbol.for('__struct__')).__MODULE__):this.registry.has(a.constructor)}}var h={atom_to_binary,binary_to_atom,binary_to_existing_atom:function binary_to_existing_atom(a,b=Symbol.for('utf8')){return binary_to_atom(a,b)},list_concatenation:function list_concatenation(a,b){return a.concat(b)},list_subtraction:function list_subtraction(a,b){const c=[...a];for(const d of b){const a=c.indexOf(d);-1b},greaterThanOrEqualTo:function greaterThanOrEqualTo(a,b){return a>=b},lessThan:function lessThan(a,b){return a>b},bxor:function bxor(a,b){return a^b},bnot:function bnot(a){return~a},is_bitstring:function is_bitstring$1(a){return a instanceof d.BitString},is_boolean:function is_boolean$1(a){return'boolean'==typeof a||a instanceof Boolean},is_float:function is_float(b){return is_number$1(b)&&!a(b)},is_function:function is_function$1(a){return'function'==typeof a||a instanceof Function},is_integer:function is_integer(b){return a(b)},is_list:function is_list(a){return Array.isArray(a)},is_map:function is_map$1(a){return a instanceof Map},is_number:is_number$1,is_pid:function is_pid(a){return a instanceof d.PID},is_port:function is_port(){return!1},is_reference:function is_reference(a){return a instanceof d.Reference},is_tuple:function is_tuple(a){return a instanceof d.Tuple},is_atom:function is_atom(a){return'symbol'==typeof a||a instanceof Symbol||a.__MODULE__},is_binary:function is_binary(a){return'string'==typeof a||a instanceof String},element:function element(a,b){return b.get(a-1)},setelement:function setelement(a,b,c){const e=[...b.values];return e[a-1]=c,new d.Tuple(...e)},make_tuple:function make_tuple(a,b){const c=[];for(let d=0;d!0){let d=[],e=buildMatch(a);const f=e(b,d),[g,h]=checkNamedVariables(d);if(f&&h&&c.apply(this,g))return g;throw console.error('No match for:',b),new MatchError(b)},MatchError,variable:function variable(a=null,b=Symbol.for('tailored.no_value')){return new Variable(a,b)},wildcard:function wildcard(){return new Wildcard},startsWith:function startsWith(a){return new StartsWith(a)},capture:function capture(a){return new Capture(a)},headTail:function headTail(){return new HeadTail},type:function a(a,b={}){return new Type(a,b)},bound:function bound(a){return new Bound(a)},Clause,clause:function clause(a,b,c=()=>!0){return new Clause(a,b,c)},bitStringMatch:function bitStringMatch(...a){return new BitStringMatch(...a)},match_or_default,defmatchgen,list_comprehension:function list_comprehension(a,b){const c=run_generators(b.pop()(),b);let d=[];for(let e of c)a.guard.apply(this,e)&&d.push(a.fn.apply(this,e));return d},list_generator:function list_generator(a,b){return function(){let c=[];for(let d of b){const b=match_or_default(a,d,()=>!0,g);if(b!=g){const[a]=b;c.push(a)}}return c}},bitstring_generator:function bitstring_generator(a,b){return function(){let c=[],d=b.slice(0,a.byte_size()),e=1;for(;d.byte_size==a.byte_size();){const f=match_or_default(a,d,()=>!0,g);if(f!=g){c.push(f)}d=b.slice(a.byte_size()*e,a.byte_size()*(e+1)),e++}return c}},bitstring_comprehension:function bitstring_comprehension(a,b){const c=run_generators(b.pop()(),b);let e=[];for(let d of c)a.guard.apply(this,d)&&e.push(a.fn.apply(this,d));return e=e.map((a)=>d.BitString.integer(a)),new d.BitString(...e)},defmatchGen:function defmatchGen(...a){return defmatchgen(...a)},defmatchAsync:function defmatchAsync(...a){const b=getArityMap(a);return async function(...a){if(b.has(a.length)){const c=b.get(a.length);let d=null,e=null;for(let b of c){let c=[];a=fillInOptionalValues(a,b.arity,b.optionals);const f=b.pattern(a,c),[g,h]=checkNamedVariables(c);if(f&&h&&(await b.guard.apply(this,c))){d=b.fn,e=c;break}}if(!d)throw console.error('No match for:',a),new MatchError(a);return d.apply(this,e)}throw console.error('Arity of',a.length,'not found. No match for:',a),new MatchError(a)}}},Integer:class Integer{},Float:class Float{},Functions:{call_property:function call_property(a,b){if(!b)return a instanceof Function||'function'==typeof a?a():a;if(a instanceof Map){let c=null;if(a.has(b)?c=b:a.has(Symbol.for(b))&&(c=Symbol.for(b)),null===c)throw new Error(`Property ${b} not found in ${a}`);return a.get(c)instanceof Function||'function'==typeof a.get(c)?a.get(c)():a.get(c)}let c=null;if('number'==typeof a||'symbol'==typeof a||'boolean'==typeof a||'string'==typeof a?void 0===a[b]?void 0!==a[Symbol.for(b)]&&(c=Symbol.for(b)):c=b:b in a?c=b:Symbol.for(b)in a&&(c=Symbol.for(b)),null===c)throw new Error(`Property ${b} not found in ${a}`);return a[c]instanceof Function||'function'==typeof a[c]?a[c]():a[c]},defprotocol:function defprotocol(a){return new Protocol(a)},defimpl:function defimpl(a,b,c){a.implementation(b,c)},build_namespace:function build_namespace(a,b){let c=b.split('.');const d=a;let e=a;'Elixir'===c[0]&&(c=c.slice(1));for(const d of c)'undefined'==typeof e[d]&&(e[d]={}),e=e[d];return d.__table__=a.__table__||{},d.__table__[Symbol.for(b)]=e,e},iterator_to_reducer,map_to_object},SpecialForms:{_case:function _case(a,b){return n.Patterns.defmatch(...b)(a)},cond:function cond(...a){for(const b of a)if(b[0])return b[1]();throw new Error},_for:function _for(a,b,c,d=[]){let[e,f]=c.into(d);const g=run_list_generators(b.pop()(),b);for(const h of g)a.guard.apply(this,h)&&(e=f(e,new n.Tuple(Symbol.for('cont'),a.fn.apply(this,h))));return f(e,Symbol.for('done'))},_try:function _try(a,b,c,d,e){let f=null;try{f=a()}catch(a){let d=null;if(b)try{return d=b(a),d}catch(a){if(a instanceof n.Patterns.MatchError)throw a}if(c)try{return d=c(a),d}catch(a){if(a instanceof n.Patterns.MatchError)throw a}throw a}finally{e&&e()}if(d)try{return d(f)}catch(a){if(a instanceof n.Patterns.MatchError)throw new Error('No Match Found in Else');throw a}else return f},_with:function _with(...a){let b=[],c=null,d=null;'function'==typeof a[a.length-2]?[c,d]=a.splice(-2):c=a.pop();for(let c=0;c{const[c,d]=b;return a.set(c,d),a},new Map)},keys:function keys(a){return!1===h.is_map(a)?new d.Tuple(k,a):Array.from(a.keys())},values:function values$1(a){return!1===h.is_map(a)?new d.Tuple(k,a):Array.from(a.values())},is_key,put:function put(a,b,c){if(!1===h.is_map(c))return new d.Tuple(k,c);const e=new Map(c);return e.set(a,b),e},merge:function merge(a,b){return!1===h.is_map(a)?new d.Tuple(k,a):!1===h.is_map(b)?new d.Tuple(k,b):new Map([...a,...b])},update:function update(a,b,c){return!1===h.is_map(c)?new d.Tuple(k,c):!1===is_key(a,c)?new d.Tuple(l,a):new Map([...c,[a,b]])},get:function get(...a){const b=a[0],c=a[1];return!1===h.is_map(c)?new d.Tuple(k,c):is_key(b)?c.get(b):3===a.length?a[2]:new d.Tuple(l,b)},take:function take(a,b){if(!1===h.is_map(b))return new d.Tuple(k,b);if(!is_key(a))return j;const c=b.get(a),e=new Map(b);return e.delete(a),new d.Tuple(c,e)}},lists:{reverse,foreach:function foreach(a,b){return b.forEach((b)=>a(b)),Symbol.for('ok')},duplicate:function duplicate(a,b){const c=[];for(;c.length{if(d.get(c-1)a.get(c-1)?1:0})},keystore:function keystore(a,b,c,d){const e=[...c];for(let f=0;fa.toString()).join()},map:function map(a,b){return b.map((b)=>a(b))},filter:function filter(a,b){return b.filter((b)=>a(b))},filtermap:function filtermap(a,b){const c=[];for(const e of b){const b=a(e);!0===b?c.push(e):b instanceof d.Tuple&&!0===b.get(0)&&c.push(b.get(1))}return c},member:function member(a,b){for(const c of b)if(c===a)return!0;return!1},all:function all(a,b){for(const c of b)if(!1===a(c))return!1;return!0},any:function any(a,b){for(const c of b)if(!0===a(c))return!0;return!1},splitwith:function splitwith(a,b){let c=!1;const e=[],f=[];for(const d of b)!0==c?f.push(d):!0===a(d)?e.push(d):(c=!0,f.push(d));return new d.Tuple(e,f)},sort:function sort(...a){if(1===a.length){const b=[...a[0]];return b.sort()}const c=a[0],b=[...a[1]];return b.sort((d,a)=>{const b=c(d,a);return!0===b?-1:1})}},elixir_errors:{warn:function warn(a){const b=a.join('');return console.warn(`warning: ${b}`),Symbol.for('ok')}}};return{Core:n}}(); From 31721a84cd9976260542b7a6dc2f76fd8db144ca Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Fri, 21 Jul 2017 07:38:24 -0500 Subject: [PATCH 630/860] Add erlang functions, iolist_to_binary and io_size --- priv/build/iife/ElixirScript.Core.js | 4 +-- .../lib/core/erlang_compat/erlang.js | 30 ++++++++++++++++++- 2 files changed, 31 insertions(+), 3 deletions(-) diff --git a/priv/build/iife/ElixirScript.Core.js b/priv/build/iife/ElixirScript.Core.js index f97d3ed7..82295b52 100644 --- a/priv/build/iife/ElixirScript.Core.js +++ b/priv/build/iife/ElixirScript.Core.js @@ -1,6 +1,6 @@ var ElixirScript=function(){'use strict';/* @flow */function namedVariableResult(a,b){return new NamedVariableResult(a,b)}/* @flow */function is_number(a){return'number'==typeof a}function is_string(a){return'string'==typeof a}function is_boolean(a){return'boolean'==typeof a}function is_symbol(a){return'symbol'==typeof a}function is_object(a){return'object'==typeof a}function is_variable(a){return a instanceof Variable}function is_null(a){return null===a}function is_array(a){return Array.isArray(a)}function is_function(a){return'[object Function]'==Object.prototype.toString.call(a)}function is_map(a){return a instanceof Map}function resolveNull(){return function(a){return is_null(a)}}function resolveWildcard(){return function(){return!0}}function resolveObject(a){let b={};const c=Object.keys(a).concat(Object.getOwnPropertySymbols(a));for(let d of c)b[d]=buildMatch(a[d]);return function(d,e){if(!is_object(d)||a.length>d.length)return!1;for(let a of c)if(!(a in d)||!b[a](d[a],e))return!1;return!0}}function getSize(a,b){return a*b/8}function arraysEqual(c,a){if(c===a)return!0;if(null==c||null==a)return!1;if(c.length!=a.length)return!1;for(var b=0;be.integer(a));return new e(...b)}function resolveNoMatch(){return function(){return!1}}function buildMatch(a){if(null===a)return resolveNull(a);if('undefined'==typeof a)return resolveWildcard(a);const b=a.constructor.prototype,c=f.get(b);return c?c(a):'object'==typeof a?resolveObject(a):resolveNoMatch()}function defmatchgen(...a){const b=getArityMap(a);return function*(...a){let[c,d]=findMatchingFunction(a,b);return yield*c.apply(this,d)}}function findMatchingFunction(a,b){if(b.has(a.length)){const c=b.get(a.length);let d=null,e=null;for(let b of c){let c=[];a=fillInOptionalValues(a,b.arity,b.optionals);const f=b.pattern(a,c),[g,h]=checkNamedVariables(c);if(f&&h&&b.guard.apply(this,g)){d=b.fn,e=g;break}}if(!d)throw console.error('No match for:',a),new MatchError(a);return[d,e]}throw console.error('Arity of',a.length,'not found. No match for:',a),new MatchError(a)}function getArityMap(a){let b=new Map;for(const c of a){const a=getArityRange(c);for(const d of a){let a=[];b.has(d)&&(a=b.get(d)),a.push(c),b.set(d,a)}}return b}function getArityRange(a){const b=a.arity-a.optionals.length,c=a.arity;let d=[b];for(;d[d.length-1]!=c;)d.push(d[d.length-1]+1);return d}function getOptionalValues(a){let b=[];for(let c=0;c!0,d=null){let e=[],f=buildMatch(a);const g=f(b,e),[h,i]=checkNamedVariables(e);return g&&i&&c.apply(this,h)?h:d}function run_generators(a,b){if(0==b.length)return a.map((a)=>{return Array.isArray(a)?a:[a]});const c=b.pop();let d=[];for(let e of c())for(let b of a)d.push([e].concat(b));return run_generators(d,b)}function iterator_to_reducer(a,b,c){const d=a[Symbol.iterator]();let e=d.next(),f=b;for(;!1===e.done;){if(f=c(e.value,f.get(1)),f.get(0)===Symbol.for('halt'))return new n.Tuple(Symbol.for('halted'),f.get(1));if(f.get(0)===Symbol.for('suspend'))return new n.Tuple(Symbol.for('suspended'),f.get(1),(a)=>{return iterator_to_reducer(d,a,c)});e=d.next()}return new n.Tuple(Symbol.for('done'),f.get(1))}function map_to_object(a){const b={};for(const[c,d]of a.entries())b[c]=d instanceof Map?map_to_object(d):d;return b}function run_list_generators(a,b){if(0==b.length)return a.map((a)=>{return Array.isArray(a)?a:[a]});const c=b.pop(),d=[];for(const e of c())for(const b of a)d.push([e].concat(b));return run_list_generators(d,b)}// http://erlang.org/doc/man/erlang.html -function atom_to_binary(a,b=Symbol.for('utf8')){if(b!==Symbol.for('utf8'))throw new Error(`unsupported encoding ${b}`);return a.__MODULE__?Symbol.keyFor(a.__MODULE__):Symbol.keyFor(a)}function binary_to_atom(a,b=Symbol.for('utf8')){if(b!==Symbol.for('utf8'))throw new Error(`unsupported encoding ${b}`);return Symbol.for(a)}function is_number$1(a){return'number'==typeof a||a instanceof Number}function is_key(a,b){return b.has(a)}// http://erlang.org/doc/man/lists.html +function atom_to_binary(a,b=Symbol.for('utf8')){if(b!==Symbol.for('utf8'))throw new Error(`unsupported encoding ${b}`);return a.__MODULE__?Symbol.keyFor(a.__MODULE__):Symbol.keyFor(a)}function binary_to_atom(a,b=Symbol.for('utf8')){if(b!==Symbol.for('utf8'))throw new Error(`unsupported encoding ${b}`);return Symbol.for(a)}function is_bitstring$1(a){return a instanceof d.BitString}function is_number$1(a){return'number'==typeof a||a instanceof Number}function is_integer(b){return a(b)}function is_binary(a){return'string'==typeof a||a instanceof String}function iolist_to_binary(a){var b=String.fromCodePoint;if(is_binary(a))return a;if(is_bitstring$1(a))return b(...a.value);const c=a.reduce((a,c)=>{if(is_integer(c))return a+b(c);return is_bitstring$1(c)?a+b(...c.value):a+iolist_to_binary(c)},'');return c}function is_key(a,b){return b.has(a)}// http://erlang.org/doc/man/lists.html function reverse(a){return[...a]}function flatten(a,b=[]){const c=a.reduce((a,b)=>{return Array.isArray(b)?a.concat(flatten(b)):a.concat(b)},[]);return c.concat(b)}function foldl(a,b,c){return c.reduce((b,c)=>{return a(c,b)},b)}function keyfind(a,b,c){for(const d of c)if(d.get(b-1)===a)return d;return!1}function keydelete(a,b,c){const d=[];let e=!1;for(let f=0;fBitString$1.integer(a));return new BitString$1(...d)}[Symbol.iterator](){return this.value[Symbol.iterator]()}toString(){var a,b='';for(a=0;a>'}process(a){let b=[];var c;for(c=0;cb?c.push(b):2048>b?c.push(192|b>>6,128|63&b):55296>b||57344<=b?c.push(224|b>>12,128|63&b>>6,128|63&b):(d++,b=65536+((1023&b)<<10|1023&a.charCodeAt(d)),c.push(240|b>>18,128|63&b>>12,128|63&b>>6,128|63&b));return c}static toUTF16Array(a){for(var b,c=[],d=0;d=b?(c.push(0),c.push(b)):(c.push(255&b>>8),c.push(255&b));return c}static toUTF32Array(a){for(var b,c=[],d=0;d=b?(c.push(0),c.push(0),c.push(0),c.push(b)):(c.push(0),c.push(0),c.push(255&b>>8),c.push(255&b));return c}//http://stackoverflow.com/questions/2003493/javascript-float-from-to-bits static float32ToBytes(a){var b=[],c=new ArrayBuffer(4);new Float32Array(c)[0]=a;let d=new Uint32Array(c)[0];return b.push(255&d>>24),b.push(255&d>>16),b.push(255&d>>8),b.push(255&d),b}static float64ToBytes(a){var b=[],c=new ArrayBuffer(8);new Float64Array(c)[0]=a;var d=new Uint32Array(c)[0],e=new Uint32Array(c)[1];return b.push(255&e>>24),b.push(255&e>>16),b.push(255&e>>8),b.push(255&e),b.push(255&d>>24),b.push(255&d>>16),b.push(255&d>>8),b.push(255&d),b}}var d={Tuple,PID:class PID{constructor(){++b,this.id=b}toString(){return'PID#<0.'+this.id+'.0>'}},Reference:class Reference{constructor(){++c,this.id=c,this.ref=Symbol()}toString(){return'Ref#<0.0.0.'+this.id+'>'}},BitString:BitString$1};/* @flow */const e=d.BitString,f=new Map;f.set(Variable.prototype,function resolveVariable(a){return function(b,c){return null===a.name||a.name.startsWith('_')?c.push(b):c.push(namedVariableResult(a.name,b)),!0}}),f.set(Wildcard.prototype,resolveWildcard),f.set(HeadTail.prototype,function resolveHeadTail(){return function(a,b){if(!is_array(a)||2>a.length)return!1;const c=a[0],d=a.slice(1);return b.push(c),b.push(d),!0}}),f.set(StartsWith.prototype,function resolveStartsWith(a){const b=a.prefix;return function(a,c){return is_string(a)&&a.startsWith(b)&&(c.push(a.substring(b.length)),!0)}}),f.set(Capture.prototype,function resolveCapture(a){const b=buildMatch(a.value);return function(a,c){return!!b(a,c)&&(c.push(a),!0)}}),f.set(Bound.prototype,function resolveBound(a){return function(b){return typeof b==typeof a.value&&b===a.value}}),f.set(Type.prototype,function resolveType(a){return function(b,c){if(b instanceof a.type){const d=buildMatch(a.objPattern);return d(b,c)}return!1}}),f.set(BitStringMatch.prototype,function resolveBitString(a){let b=[];for(let c of a.values)if(is_variable(c.value)){let a=getSize(c.unit,c.size);fillArray(b,a)}else b=b.concat(new e(c).value);let c=a.values;return function(a,d){var f=String.fromCharCode;let g=null;if(!is_string(a)&&!(a instanceof e))return!1;g=is_string(a)?new e(e.binary(a)):a;let h=0;for(let e,j=0;jd.size)return!1;for(let a of c)if(!d.has(a)||!b.get(a)(d.get(a),e))return!1;return!0}}),f.set(Array.prototype,function resolveArray(a){const b=a.map((a)=>buildMatch(a));return function(c,d){return is_array(c)&&c.length==a.length&&c.every(function(a,e){return b[e](c[e],d)})}}),f.set(String.prototype,function resolveString(a){return function(b){return is_string(b)&&b===a}}),f.set(Boolean.prototype,function resolveBoolean(a){return function(b){return is_boolean(b)&&b===a}}),f.set(Function.prototype,function resolveFunction(a){return function(b){return is_function(b)&&b===a}}),f.set(Object.prototype,resolveObject);class MatchError extends Error{constructor(a){if(super(),'symbol'==typeof a)this.message='No match for: '+a.toString();else if(Array.isArray(a)){let b=a.map((a)=>{return null===a?'null':'undefined'==typeof a?'undefined':a.toString()});this.message='No match for: '+b}else this.message='No match for: '+a;this.stack=new Error().stack,this.name=this.constructor.name}}class Clause{constructor(a,b,c=()=>!0){this.pattern=buildMatch(a),this.arity=a.length,this.optionals=getOptionalValues(a),this.fn=b,this.guard=c}}const g=Symbol();// https://github.com/airportyh/protomorphism -class Protocol{constructor(b){function createFun(b){return function(...c){const d=c[0];let e=null;if(null===d&&this.hasImplementation(Symbol('null'))?e=this.registry.get(Symbol)[b]:a(d)&&this.hasImplementation(n.Integer)?e=this.registry.get(n.Integer)[b]:'number'==typeof d&&!a(d)&&this.hasImplementation(n.Float)?e=this.registry.get(n.Float)[b]:'string'==typeof d&&this.hasImplementation(n.BitString)?e=this.registry.get(n.BitString)[b]:d&&d.has(Symbol.for('__struct__'))&&this.hasImplementation(d)?e=this.registry.get(d.get(Symbol.for('__struct__')).__MODULE__)[b]:null!==d&&this.hasImplementation(d)?e=this.registry.get(d.constructor)[b]:this.fallback&&(e=this.fallback[b]),null!=e){const a=e.apply(this,c);return a}throw new Error(`No implementation found for ${d}`)}}for(const a in this.registry=new Map,this.fallback=null,b)this[a]=createFun(a).bind(this)}implementation(a,b){null===a?this.fallback=b:this.registry.set(a,b)}hasImplementation(a){if(a===n.Integer||a===n.Float||a===n.BitString)return this.registry.has(a);return a&&a.has(Symbol.for('__struct__'))?this.registry.has(a.get(Symbol.for('__struct__')).__MODULE__):this.registry.has(a.constructor)}}var h={atom_to_binary,binary_to_atom,binary_to_existing_atom:function binary_to_existing_atom(a,b=Symbol.for('utf8')){return binary_to_atom(a,b)},list_concatenation:function list_concatenation(a,b){return a.concat(b)},list_subtraction:function list_subtraction(a,b){const c=[...a];for(const d of b){const a=c.indexOf(d);-1b},greaterThanOrEqualTo:function greaterThanOrEqualTo(a,b){return a>=b},lessThan:function lessThan(a,b){return a>b},bxor:function bxor(a,b){return a^b},bnot:function bnot(a){return~a},is_bitstring:function is_bitstring$1(a){return a instanceof d.BitString},is_boolean:function is_boolean$1(a){return'boolean'==typeof a||a instanceof Boolean},is_float:function is_float(b){return is_number$1(b)&&!a(b)},is_function:function is_function$1(a){return'function'==typeof a||a instanceof Function},is_integer:function is_integer(b){return a(b)},is_list:function is_list(a){return Array.isArray(a)},is_map:function is_map$1(a){return a instanceof Map},is_number:is_number$1,is_pid:function is_pid(a){return a instanceof d.PID},is_port:function is_port(){return!1},is_reference:function is_reference(a){return a instanceof d.Reference},is_tuple:function is_tuple(a){return a instanceof d.Tuple},is_atom:function is_atom(a){return'symbol'==typeof a||a instanceof Symbol||a.__MODULE__},is_binary:function is_binary(a){return'string'==typeof a||a instanceof String},element:function element(a,b){return b.get(a-1)},setelement:function setelement(a,b,c){const e=[...b.values];return e[a-1]=c,new d.Tuple(...e)},make_tuple:function make_tuple(a,b){const c=[];for(let d=0;db},greaterThanOrEqualTo:function greaterThanOrEqualTo(a,b){return a>=b},lessThan:function lessThan(a,b){return a>b},bxor:function bxor(a,b){return a^b},bnot:function bnot(a){return~a},is_bitstring:is_bitstring$1,is_boolean:function is_boolean$1(a){return'boolean'==typeof a||a instanceof Boolean},is_float:function is_float(b){return is_number$1(b)&&!a(b)},is_function:function is_function$1(a){return'function'==typeof a||a instanceof Function},is_integer,is_list:function is_list(a){return Array.isArray(a)},is_map:function is_map$1(a){return a instanceof Map},is_number:is_number$1,is_pid:function is_pid(a){return a instanceof d.PID},is_port:function is_port(){return!1},is_reference:function is_reference(a){return a instanceof d.Reference},is_tuple:function is_tuple(a){return a instanceof d.Tuple},is_atom:function is_atom(a){return'symbol'==typeof a||a instanceof Symbol||a.__MODULE__},is_binary,element:function element(a,b){return b.get(a-1)},setelement:function setelement(a,b,c){const e=[...b.values];return e[a-1]=c,new d.Tuple(...e)},make_tuple:function make_tuple(a,b){const c=[];for(let d=0;d!0){let d=[],e=buildMatch(a);const f=e(b,d),[g,h]=checkNamedVariables(d);if(f&&h&&c.apply(this,g))return g;throw console.error('No match for:',b),new MatchError(b)},MatchError,variable:function variable(a=null,b=Symbol.for('tailored.no_value')){return new Variable(a,b)},wildcard:function wildcard(){return new Wildcard},startsWith:function startsWith(a){return new StartsWith(a)},capture:function capture(a){return new Capture(a)},headTail:function headTail(){return new HeadTail},type:function a(a,b={}){return new Type(a,b)},bound:function bound(a){return new Bound(a)},Clause,clause:function clause(a,b,c=()=>!0){return new Clause(a,b,c)},bitStringMatch:function bitStringMatch(...a){return new BitStringMatch(...a)},match_or_default,defmatchgen,list_comprehension:function list_comprehension(a,b){const c=run_generators(b.pop()(),b);let d=[];for(let e of c)a.guard.apply(this,e)&&d.push(a.fn.apply(this,e));return d},list_generator:function list_generator(a,b){return function(){let c=[];for(let d of b){const b=match_or_default(a,d,()=>!0,g);if(b!=g){const[a]=b;c.push(a)}}return c}},bitstring_generator:function bitstring_generator(a,b){return function(){let c=[],d=b.slice(0,a.byte_size()),e=1;for(;d.byte_size==a.byte_size();){const f=match_or_default(a,d,()=>!0,g);if(f!=g){c.push(f)}d=b.slice(a.byte_size()*e,a.byte_size()*(e+1)),e++}return c}},bitstring_comprehension:function bitstring_comprehension(a,b){const c=run_generators(b.pop()(),b);let e=[];for(let d of c)a.guard.apply(this,d)&&e.push(a.fn.apply(this,d));return e=e.map((a)=>d.BitString.integer(a)),new d.BitString(...e)},defmatchGen:function defmatchGen(...a){return defmatchgen(...a)},defmatchAsync:function defmatchAsync(...a){const b=getArityMap(a);return async function(...a){if(b.has(a.length)){const c=b.get(a.length);let d=null,e=null;for(let b of c){let c=[];a=fillInOptionalValues(a,b.arity,b.optionals);const f=b.pattern(a,c),[g,h]=checkNamedVariables(c);if(f&&h&&(await b.guard.apply(this,c))){d=b.fn,e=c;break}}if(!d)throw console.error('No match for:',a),new MatchError(a);return d.apply(this,e)}throw console.error('Arity of',a.length,'not found. No match for:',a),new MatchError(a)}}},Integer:class Integer{},Float:class Float{},Functions:{call_property:function call_property(a,b){if(!b)return a instanceof Function||'function'==typeof a?a():a;if(a instanceof Map){let c=null;if(a.has(b)?c=b:a.has(Symbol.for(b))&&(c=Symbol.for(b)),null===c)throw new Error(`Property ${b} not found in ${a}`);return a.get(c)instanceof Function||'function'==typeof a.get(c)?a.get(c)():a.get(c)}let c=null;if('number'==typeof a||'symbol'==typeof a||'boolean'==typeof a||'string'==typeof a?void 0===a[b]?void 0!==a[Symbol.for(b)]&&(c=Symbol.for(b)):c=b:b in a?c=b:Symbol.for(b)in a&&(c=Symbol.for(b)),null===c)throw new Error(`Property ${b} not found in ${a}`);return a[c]instanceof Function||'function'==typeof a[c]?a[c]():a[c]},defprotocol:function defprotocol(a){return new Protocol(a)},defimpl:function defimpl(a,b,c){a.implementation(b,c)},build_namespace:function build_namespace(a,b){let c=b.split('.');const d=a;let e=a;'Elixir'===c[0]&&(c=c.slice(1));for(const d of c)'undefined'==typeof e[d]&&(e[d]={}),e=e[d];return d.__table__=a.__table__||{},d.__table__[Symbol.for(b)]=e,e},iterator_to_reducer,map_to_object},SpecialForms:{_case:function _case(a,b){return n.Patterns.defmatch(...b)(a)},cond:function cond(...a){for(const b of a)if(b[0])return b[1]();throw new Error},_for:function _for(a,b,c,d=[]){let[e,f]=c.into(d);const g=run_list_generators(b.pop()(),b);for(const h of g)a.guard.apply(this,h)&&(e=f(e,new n.Tuple(Symbol.for('cont'),a.fn.apply(this,h))));return f(e,Symbol.for('done'))},_try:function _try(a,b,c,d,e){let f=null;try{f=a()}catch(a){let d=null;if(b)try{return d=b(a),d}catch(a){if(a instanceof n.Patterns.MatchError)throw a}if(c)try{return d=c(a),d}catch(a){if(a instanceof n.Patterns.MatchError)throw a}throw a}finally{e&&e()}if(d)try{return d(f)}catch(a){if(a instanceof n.Patterns.MatchError)throw new Error('No Match Found in Else');throw a}else return f},_with:function _with(...a){let b=[],c=null,d=null;'function'==typeof a[a.length-2]?[c,d]=a.splice(-2):c=a.pop();for(let c=0;c{const[c,d]=b;return a.set(c,d),a},new Map)},keys:function keys(a){return!1===h.is_map(a)?new d.Tuple(k,a):Array.from(a.keys())},values:function values$1(a){return!1===h.is_map(a)?new d.Tuple(k,a):Array.from(a.values())},is_key,put:function put(a,b,c){if(!1===h.is_map(c))return new d.Tuple(k,c);const e=new Map(c);return e.set(a,b),e},merge:function merge(a,b){return!1===h.is_map(a)?new d.Tuple(k,a):!1===h.is_map(b)?new d.Tuple(k,b):new Map([...a,...b])},update:function update(a,b,c){return!1===h.is_map(c)?new d.Tuple(k,c):!1===is_key(a,c)?new d.Tuple(l,a):new Map([...c,[a,b]])},get:function get(...a){const b=a[0],c=a[1];return!1===h.is_map(c)?new d.Tuple(k,c):is_key(b)?c.get(b):3===a.length?a[2]:new d.Tuple(l,b)},take:function take(a,b){if(!1===h.is_map(b))return new d.Tuple(k,b);if(!is_key(a))return j;const c=b.get(a),e=new Map(b);return e.delete(a),new d.Tuple(c,e)}},lists:{reverse,foreach:function foreach(a,b){return b.forEach((b)=>a(b)),Symbol.for('ok')},duplicate:function duplicate(a,b){const c=[];for(;c.length{if(d.get(c-1)a.get(c-1)?1:0})},keystore:function keystore(a,b,c,d){const e=[...c];for(let f=0;fa.toString()).join()},map:function map(a,b){return b.map((b)=>a(b))},filter:function filter(a,b){return b.filter((b)=>a(b))},filtermap:function filtermap(a,b){const c=[];for(const e of b){const b=a(e);!0===b?c.push(e):b instanceof d.Tuple&&!0===b.get(0)&&c.push(b.get(1))}return c},member:function member(a,b){for(const c of b)if(c===a)return!0;return!1},all:function all(a,b){for(const c of b)if(!1===a(c))return!1;return!0},any:function any(a,b){for(const c of b)if(!0===a(c))return!0;return!1},splitwith:function splitwith(a,b){let c=!1;const e=[],f=[];for(const d of b)!0==c?f.push(d):!0===a(d)?e.push(d):(c=!0,f.push(d));return new d.Tuple(e,f)},sort:function sort(...a){if(1===a.length){const b=[...a[0]];return b.sort()}const c=a[0],b=[...a[1]];return b.sort((d,a)=>{const b=c(d,a);return!0===b?-1:1})}},elixir_errors:{warn:function warn(a){const b=a.join('');return console.warn(`warning: ${b}`),Symbol.for('ok')}}};return{Core:n}}(); diff --git a/src/javascript/lib/core/erlang_compat/erlang.js b/src/javascript/lib/core/erlang_compat/erlang.js index 670d9047..74c34ccf 100644 --- a/src/javascript/lib/core/erlang_compat/erlang.js +++ b/src/javascript/lib/core/erlang_compat/erlang.js @@ -329,6 +329,32 @@ function process_info(pid, item) { return []; } +function iolist_to_binary(ioListOrBinary) { + if (is_binary(ioListOrBinary)) { + return ioListOrBinary; + } + + if (is_bitstring(ioListOrBinary)) { + return String.fromCodePoint(...ioListOrBinary.value); + } + + const value = ioListOrBinary.reduce((acc, current) => { + if (is_integer(current)) { + return acc + String.fromCodePoint(current); + } else if (is_bitstring(current)) { + return acc + String.fromCodePoint(...current.value); + } + + return acc + iolist_to_binary(current); + }, ''); + + return value; +} + +function io_size(ioListOrBinary) { + return iolist_to_binary(ioListOrBinary).length; +} + export default { atom_to_binary, binary_to_atom, @@ -395,5 +421,7 @@ export default { tuple_size, binary_to_float, binary_to_integer, - process_info + process_info, + iolist_to_binary, + io_size }; From 9ed0e5ff4eefd5221d46081be30bab20bd14c84f Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Fri, 21 Jul 2017 07:57:58 -0500 Subject: [PATCH 631/860] Add io.put_chars --- .../passes/translate/forms/remote.ex | 3 ++- priv/build/iife/ElixirScript.Core.js | 12 +++++------ src/javascript/lib/core.js | 4 +++- src/javascript/lib/core/erlang_compat/io.js | 21 +++++++++++++++++++ 4 files changed, 32 insertions(+), 8 deletions(-) create mode 100644 src/javascript/lib/core/erlang_compat/io.js diff --git a/lib/elixir_script/passes/translate/forms/remote.ex b/lib/elixir_script/passes/translate/forms/remote.ex index 622fc3c0..38c2acc1 100644 --- a/lib/elixir_script/passes/translate/forms/remote.ex +++ b/lib/elixir_script/passes/translate/forms/remote.ex @@ -15,7 +15,8 @@ defmodule ElixirScript.Translate.Forms.Remote do :application, :code, :elixir_utils, - :file + :file, + :io ] @doc """ diff --git a/priv/build/iife/ElixirScript.Core.js b/priv/build/iife/ElixirScript.Core.js index 82295b52..a076e953 100644 --- a/priv/build/iife/ElixirScript.Core.js +++ b/priv/build/iife/ElixirScript.Core.js @@ -1,6 +1,6 @@ -var ElixirScript=function(){'use strict';/* @flow */function namedVariableResult(a,b){return new NamedVariableResult(a,b)}/* @flow */function is_number(a){return'number'==typeof a}function is_string(a){return'string'==typeof a}function is_boolean(a){return'boolean'==typeof a}function is_symbol(a){return'symbol'==typeof a}function is_object(a){return'object'==typeof a}function is_variable(a){return a instanceof Variable}function is_null(a){return null===a}function is_array(a){return Array.isArray(a)}function is_function(a){return'[object Function]'==Object.prototype.toString.call(a)}function is_map(a){return a instanceof Map}function resolveNull(){return function(a){return is_null(a)}}function resolveWildcard(){return function(){return!0}}function resolveObject(a){let b={};const c=Object.keys(a).concat(Object.getOwnPropertySymbols(a));for(let d of c)b[d]=buildMatch(a[d]);return function(d,e){if(!is_object(d)||a.length>d.length)return!1;for(let a of c)if(!(a in d)||!b[a](d[a],e))return!1;return!0}}function getSize(a,b){return a*b/8}function arraysEqual(c,a){if(c===a)return!0;if(null==c||null==a)return!1;if(c.length!=a.length)return!1;for(var b=0;be.integer(a));return new e(...b)}function resolveNoMatch(){return function(){return!1}}function buildMatch(a){if(null===a)return resolveNull(a);if('undefined'==typeof a)return resolveWildcard(a);const b=a.constructor.prototype,c=f.get(b);return c?c(a):'object'==typeof a?resolveObject(a):resolveNoMatch()}function defmatchgen(...a){const b=getArityMap(a);return function*(...a){let[c,d]=findMatchingFunction(a,b);return yield*c.apply(this,d)}}function findMatchingFunction(a,b){if(b.has(a.length)){const c=b.get(a.length);let d=null,e=null;for(let b of c){let c=[];a=fillInOptionalValues(a,b.arity,b.optionals);const f=b.pattern(a,c),[g,h]=checkNamedVariables(c);if(f&&h&&b.guard.apply(this,g)){d=b.fn,e=g;break}}if(!d)throw console.error('No match for:',a),new MatchError(a);return[d,e]}throw console.error('Arity of',a.length,'not found. No match for:',a),new MatchError(a)}function getArityMap(a){let b=new Map;for(const c of a){const a=getArityRange(c);for(const d of a){let a=[];b.has(d)&&(a=b.get(d)),a.push(c),b.set(d,a)}}return b}function getArityRange(a){const b=a.arity-a.optionals.length,c=a.arity;let d=[b];for(;d[d.length-1]!=c;)d.push(d[d.length-1]+1);return d}function getOptionalValues(a){let b=[];for(let c=0;c!0,d=null){let e=[],f=buildMatch(a);const g=f(b,e),[h,i]=checkNamedVariables(e);return g&&i&&c.apply(this,h)?h:d}function run_generators(a,b){if(0==b.length)return a.map((a)=>{return Array.isArray(a)?a:[a]});const c=b.pop();let d=[];for(let e of c())for(let b of a)d.push([e].concat(b));return run_generators(d,b)}function iterator_to_reducer(a,b,c){const d=a[Symbol.iterator]();let e=d.next(),f=b;for(;!1===e.done;){if(f=c(e.value,f.get(1)),f.get(0)===Symbol.for('halt'))return new n.Tuple(Symbol.for('halted'),f.get(1));if(f.get(0)===Symbol.for('suspend'))return new n.Tuple(Symbol.for('suspended'),f.get(1),(a)=>{return iterator_to_reducer(d,a,c)});e=d.next()}return new n.Tuple(Symbol.for('done'),f.get(1))}function map_to_object(a){const b={};for(const[c,d]of a.entries())b[c]=d instanceof Map?map_to_object(d):d;return b}function run_list_generators(a,b){if(0==b.length)return a.map((a)=>{return Array.isArray(a)?a:[a]});const c=b.pop(),d=[];for(const e of c())for(const b of a)d.push([e].concat(b));return run_list_generators(d,b)}// http://erlang.org/doc/man/erlang.html -function atom_to_binary(a,b=Symbol.for('utf8')){if(b!==Symbol.for('utf8'))throw new Error(`unsupported encoding ${b}`);return a.__MODULE__?Symbol.keyFor(a.__MODULE__):Symbol.keyFor(a)}function binary_to_atom(a,b=Symbol.for('utf8')){if(b!==Symbol.for('utf8'))throw new Error(`unsupported encoding ${b}`);return Symbol.for(a)}function is_bitstring$1(a){return a instanceof d.BitString}function is_number$1(a){return'number'==typeof a||a instanceof Number}function is_integer(b){return a(b)}function is_binary(a){return'string'==typeof a||a instanceof String}function iolist_to_binary(a){var b=String.fromCodePoint;if(is_binary(a))return a;if(is_bitstring$1(a))return b(...a.value);const c=a.reduce((a,c)=>{if(is_integer(c))return a+b(c);return is_bitstring$1(c)?a+b(...c.value):a+iolist_to_binary(c)},'');return c}function is_key(a,b){return b.has(a)}// http://erlang.org/doc/man/lists.html -function reverse(a){return[...a]}function flatten(a,b=[]){const c=a.reduce((a,b)=>{return Array.isArray(b)?a.concat(flatten(b)):a.concat(b)},[]);return c.concat(b)}function foldl(a,b,c){return c.reduce((b,c)=>{return a(c,b)},b)}function keyfind(a,b,c){for(const d of c)if(d.get(b-1)===a)return d;return!1}function keydelete(a,b,c){const d=[];let e=!1;for(let f=0;fBitString$1.integer(a));return new BitString$1(...d)}[Symbol.iterator](){return this.value[Symbol.iterator]()}toString(){var a,b='';for(a=0;a>'}process(a){let b=[];var c;for(c=0;cb?c.push(b):2048>b?c.push(192|b>>6,128|63&b):55296>b||57344<=b?c.push(224|b>>12,128|63&b>>6,128|63&b):(d++,b=65536+((1023&b)<<10|1023&a.charCodeAt(d)),c.push(240|b>>18,128|63&b>>12,128|63&b>>6,128|63&b));return c}static toUTF16Array(a){for(var b,c=[],d=0;d=b?(c.push(0),c.push(b)):(c.push(255&b>>8),c.push(255&b));return c}static toUTF32Array(a){for(var b,c=[],d=0;d=b?(c.push(0),c.push(0),c.push(0),c.push(b)):(c.push(0),c.push(0),c.push(255&b>>8),c.push(255&b));return c}//http://stackoverflow.com/questions/2003493/javascript-float-from-to-bits -static float32ToBytes(a){var b=[],c=new ArrayBuffer(4);new Float32Array(c)[0]=a;let d=new Uint32Array(c)[0];return b.push(255&d>>24),b.push(255&d>>16),b.push(255&d>>8),b.push(255&d),b}static float64ToBytes(a){var b=[],c=new ArrayBuffer(8);new Float64Array(c)[0]=a;var d=new Uint32Array(c)[0],e=new Uint32Array(c)[1];return b.push(255&e>>24),b.push(255&e>>16),b.push(255&e>>8),b.push(255&e),b.push(255&d>>24),b.push(255&d>>16),b.push(255&d>>8),b.push(255&d),b}}var d={Tuple,PID:class PID{constructor(){++b,this.id=b}toString(){return'PID#<0.'+this.id+'.0>'}},Reference:class Reference{constructor(){++c,this.id=c,this.ref=Symbol()}toString(){return'Ref#<0.0.0.'+this.id+'>'}},BitString:BitString$1};/* @flow */const e=d.BitString,f=new Map;f.set(Variable.prototype,function resolveVariable(a){return function(b,c){return null===a.name||a.name.startsWith('_')?c.push(b):c.push(namedVariableResult(a.name,b)),!0}}),f.set(Wildcard.prototype,resolveWildcard),f.set(HeadTail.prototype,function resolveHeadTail(){return function(a,b){if(!is_array(a)||2>a.length)return!1;const c=a[0],d=a.slice(1);return b.push(c),b.push(d),!0}}),f.set(StartsWith.prototype,function resolveStartsWith(a){const b=a.prefix;return function(a,c){return is_string(a)&&a.startsWith(b)&&(c.push(a.substring(b.length)),!0)}}),f.set(Capture.prototype,function resolveCapture(a){const b=buildMatch(a.value);return function(a,c){return!!b(a,c)&&(c.push(a),!0)}}),f.set(Bound.prototype,function resolveBound(a){return function(b){return typeof b==typeof a.value&&b===a.value}}),f.set(Type.prototype,function resolveType(a){return function(b,c){if(b instanceof a.type){const d=buildMatch(a.objPattern);return d(b,c)}return!1}}),f.set(BitStringMatch.prototype,function resolveBitString(a){let b=[];for(let c of a.values)if(is_variable(c.value)){let a=getSize(c.unit,c.size);fillArray(b,a)}else b=b.concat(new e(c).value);let c=a.values;return function(a,d){var f=String.fromCharCode;let g=null;if(!is_string(a)&&!(a instanceof e))return!1;g=is_string(a)?new e(e.binary(a)):a;let h=0;for(let e,j=0;jd.size)return!1;for(let a of c)if(!d.has(a)||!b.get(a)(d.get(a),e))return!1;return!0}}),f.set(Array.prototype,function resolveArray(a){const b=a.map((a)=>buildMatch(a));return function(c,d){return is_array(c)&&c.length==a.length&&c.every(function(a,e){return b[e](c[e],d)})}}),f.set(String.prototype,function resolveString(a){return function(b){return is_string(b)&&b===a}}),f.set(Boolean.prototype,function resolveBoolean(a){return function(b){return is_boolean(b)&&b===a}}),f.set(Function.prototype,function resolveFunction(a){return function(b){return is_function(b)&&b===a}}),f.set(Object.prototype,resolveObject);class MatchError extends Error{constructor(a){if(super(),'symbol'==typeof a)this.message='No match for: '+a.toString();else if(Array.isArray(a)){let b=a.map((a)=>{return null===a?'null':'undefined'==typeof a?'undefined':a.toString()});this.message='No match for: '+b}else this.message='No match for: '+a;this.stack=new Error().stack,this.name=this.constructor.name}}class Clause{constructor(a,b,c=()=>!0){this.pattern=buildMatch(a),this.arity=a.length,this.optionals=getOptionalValues(a),this.fn=b,this.guard=c}}const g=Symbol();// https://github.com/airportyh/protomorphism -class Protocol{constructor(b){function createFun(b){return function(...c){const d=c[0];let e=null;if(null===d&&this.hasImplementation(Symbol('null'))?e=this.registry.get(Symbol)[b]:a(d)&&this.hasImplementation(n.Integer)?e=this.registry.get(n.Integer)[b]:'number'==typeof d&&!a(d)&&this.hasImplementation(n.Float)?e=this.registry.get(n.Float)[b]:'string'==typeof d&&this.hasImplementation(n.BitString)?e=this.registry.get(n.BitString)[b]:d&&d.has(Symbol.for('__struct__'))&&this.hasImplementation(d)?e=this.registry.get(d.get(Symbol.for('__struct__')).__MODULE__)[b]:null!==d&&this.hasImplementation(d)?e=this.registry.get(d.constructor)[b]:this.fallback&&(e=this.fallback[b]),null!=e){const a=e.apply(this,c);return a}throw new Error(`No implementation found for ${d}`)}}for(const a in this.registry=new Map,this.fallback=null,b)this[a]=createFun(a).bind(this)}implementation(a,b){null===a?this.fallback=b:this.registry.set(a,b)}hasImplementation(a){if(a===n.Integer||a===n.Float||a===n.BitString)return this.registry.has(a);return a&&a.has(Symbol.for('__struct__'))?this.registry.has(a.get(Symbol.for('__struct__')).__MODULE__):this.registry.has(a.constructor)}}var h={atom_to_binary,binary_to_atom,binary_to_existing_atom:function binary_to_existing_atom(a,b=Symbol.for('utf8')){return binary_to_atom(a,b)},list_concatenation:function list_concatenation(a,b){return a.concat(b)},list_subtraction:function list_subtraction(a,b){const c=[...a];for(const d of b){const a=c.indexOf(d);-1b},greaterThanOrEqualTo:function greaterThanOrEqualTo(a,b){return a>=b},lessThan:function lessThan(a,b){return a>b},bxor:function bxor(a,b){return a^b},bnot:function bnot(a){return~a},is_bitstring:is_bitstring$1,is_boolean:function is_boolean$1(a){return'boolean'==typeof a||a instanceof Boolean},is_float:function is_float(b){return is_number$1(b)&&!a(b)},is_function:function is_function$1(a){return'function'==typeof a||a instanceof Function},is_integer,is_list:function is_list(a){return Array.isArray(a)},is_map:function is_map$1(a){return a instanceof Map},is_number:is_number$1,is_pid:function is_pid(a){return a instanceof d.PID},is_port:function is_port(){return!1},is_reference:function is_reference(a){return a instanceof d.Reference},is_tuple:function is_tuple(a){return a instanceof d.Tuple},is_atom:function is_atom(a){return'symbol'==typeof a||a instanceof Symbol||a.__MODULE__},is_binary,element:function element(a,b){return b.get(a-1)},setelement:function setelement(a,b,c){const e=[...b.values];return e[a-1]=c,new d.Tuple(...e)},make_tuple:function make_tuple(a,b){const c=[];for(let d=0;d!0){let d=[],e=buildMatch(a);const f=e(b,d),[g,h]=checkNamedVariables(d);if(f&&h&&c.apply(this,g))return g;throw console.error('No match for:',b),new MatchError(b)},MatchError,variable:function variable(a=null,b=Symbol.for('tailored.no_value')){return new Variable(a,b)},wildcard:function wildcard(){return new Wildcard},startsWith:function startsWith(a){return new StartsWith(a)},capture:function capture(a){return new Capture(a)},headTail:function headTail(){return new HeadTail},type:function a(a,b={}){return new Type(a,b)},bound:function bound(a){return new Bound(a)},Clause,clause:function clause(a,b,c=()=>!0){return new Clause(a,b,c)},bitStringMatch:function bitStringMatch(...a){return new BitStringMatch(...a)},match_or_default,defmatchgen,list_comprehension:function list_comprehension(a,b){const c=run_generators(b.pop()(),b);let d=[];for(let e of c)a.guard.apply(this,e)&&d.push(a.fn.apply(this,e));return d},list_generator:function list_generator(a,b){return function(){let c=[];for(let d of b){const b=match_or_default(a,d,()=>!0,g);if(b!=g){const[a]=b;c.push(a)}}return c}},bitstring_generator:function bitstring_generator(a,b){return function(){let c=[],d=b.slice(0,a.byte_size()),e=1;for(;d.byte_size==a.byte_size();){const f=match_or_default(a,d,()=>!0,g);if(f!=g){c.push(f)}d=b.slice(a.byte_size()*e,a.byte_size()*(e+1)),e++}return c}},bitstring_comprehension:function bitstring_comprehension(a,b){const c=run_generators(b.pop()(),b);let e=[];for(let d of c)a.guard.apply(this,d)&&e.push(a.fn.apply(this,d));return e=e.map((a)=>d.BitString.integer(a)),new d.BitString(...e)},defmatchGen:function defmatchGen(...a){return defmatchgen(...a)},defmatchAsync:function defmatchAsync(...a){const b=getArityMap(a);return async function(...a){if(b.has(a.length)){const c=b.get(a.length);let d=null,e=null;for(let b of c){let c=[];a=fillInOptionalValues(a,b.arity,b.optionals);const f=b.pattern(a,c),[g,h]=checkNamedVariables(c);if(f&&h&&(await b.guard.apply(this,c))){d=b.fn,e=c;break}}if(!d)throw console.error('No match for:',a),new MatchError(a);return d.apply(this,e)}throw console.error('Arity of',a.length,'not found. No match for:',a),new MatchError(a)}}},Integer:class Integer{},Float:class Float{},Functions:{call_property:function call_property(a,b){if(!b)return a instanceof Function||'function'==typeof a?a():a;if(a instanceof Map){let c=null;if(a.has(b)?c=b:a.has(Symbol.for(b))&&(c=Symbol.for(b)),null===c)throw new Error(`Property ${b} not found in ${a}`);return a.get(c)instanceof Function||'function'==typeof a.get(c)?a.get(c)():a.get(c)}let c=null;if('number'==typeof a||'symbol'==typeof a||'boolean'==typeof a||'string'==typeof a?void 0===a[b]?void 0!==a[Symbol.for(b)]&&(c=Symbol.for(b)):c=b:b in a?c=b:Symbol.for(b)in a&&(c=Symbol.for(b)),null===c)throw new Error(`Property ${b} not found in ${a}`);return a[c]instanceof Function||'function'==typeof a[c]?a[c]():a[c]},defprotocol:function defprotocol(a){return new Protocol(a)},defimpl:function defimpl(a,b,c){a.implementation(b,c)},build_namespace:function build_namespace(a,b){let c=b.split('.');const d=a;let e=a;'Elixir'===c[0]&&(c=c.slice(1));for(const d of c)'undefined'==typeof e[d]&&(e[d]={}),e=e[d];return d.__table__=a.__table__||{},d.__table__[Symbol.for(b)]=e,e},iterator_to_reducer,map_to_object},SpecialForms:{_case:function _case(a,b){return n.Patterns.defmatch(...b)(a)},cond:function cond(...a){for(const b of a)if(b[0])return b[1]();throw new Error},_for:function _for(a,b,c,d=[]){let[e,f]=c.into(d);const g=run_list_generators(b.pop()(),b);for(const h of g)a.guard.apply(this,h)&&(e=f(e,new n.Tuple(Symbol.for('cont'),a.fn.apply(this,h))));return f(e,Symbol.for('done'))},_try:function _try(a,b,c,d,e){let f=null;try{f=a()}catch(a){let d=null;if(b)try{return d=b(a),d}catch(a){if(a instanceof n.Patterns.MatchError)throw a}if(c)try{return d=c(a),d}catch(a){if(a instanceof n.Patterns.MatchError)throw a}throw a}finally{e&&e()}if(d)try{return d(f)}catch(a){if(a instanceof n.Patterns.MatchError)throw new Error('No Match Found in Else');throw a}else return f},_with:function _with(...a){let b=[],c=null,d=null;'function'==typeof a[a.length-2]?[c,d]=a.splice(-2):c=a.pop();for(let c=0;c{const[c,d]=b;return a.set(c,d),a},new Map)},keys:function keys(a){return!1===h.is_map(a)?new d.Tuple(k,a):Array.from(a.keys())},values:function values$1(a){return!1===h.is_map(a)?new d.Tuple(k,a):Array.from(a.values())},is_key,put:function put(a,b,c){if(!1===h.is_map(c))return new d.Tuple(k,c);const e=new Map(c);return e.set(a,b),e},merge:function merge(a,b){return!1===h.is_map(a)?new d.Tuple(k,a):!1===h.is_map(b)?new d.Tuple(k,b):new Map([...a,...b])},update:function update(a,b,c){return!1===h.is_map(c)?new d.Tuple(k,c):!1===is_key(a,c)?new d.Tuple(l,a):new Map([...c,[a,b]])},get:function get(...a){const b=a[0],c=a[1];return!1===h.is_map(c)?new d.Tuple(k,c):is_key(b)?c.get(b):3===a.length?a[2]:new d.Tuple(l,b)},take:function take(a,b){if(!1===h.is_map(b))return new d.Tuple(k,b);if(!is_key(a))return j;const c=b.get(a),e=new Map(b);return e.delete(a),new d.Tuple(c,e)}},lists:{reverse,foreach:function foreach(a,b){return b.forEach((b)=>a(b)),Symbol.for('ok')},duplicate:function duplicate(a,b){const c=[];for(;c.length{if(d.get(c-1)a.get(c-1)?1:0})},keystore:function keystore(a,b,c,d){const e=[...c];for(let f=0;fa.toString()).join()},map:function map(a,b){return b.map((b)=>a(b))},filter:function filter(a,b){return b.filter((b)=>a(b))},filtermap:function filtermap(a,b){const c=[];for(const e of b){const b=a(e);!0===b?c.push(e):b instanceof d.Tuple&&!0===b.get(0)&&c.push(b.get(1))}return c},member:function member(a,b){for(const c of b)if(c===a)return!0;return!1},all:function all(a,b){for(const c of b)if(!1===a(c))return!1;return!0},any:function any(a,b){for(const c of b)if(!0===a(c))return!0;return!1},splitwith:function splitwith(a,b){let c=!1;const e=[],f=[];for(const d of b)!0==c?f.push(d):!0===a(d)?e.push(d):(c=!0,f.push(d));return new d.Tuple(e,f)},sort:function sort(...a){if(1===a.length){const b=[...a[0]];return b.sort()}const c=a[0],b=[...a[1]];return b.sort((d,a)=>{const b=c(d,a);return!0===b?-1:1})}},elixir_errors:{warn:function warn(a){const b=a.join('');return console.warn(`warning: ${b}`),Symbol.for('ok')}}};return{Core:n}}(); +var ElixirScript=function(){'use strict';/* @flow */function namedVariableResult(a,b){return new NamedVariableResult(a,b)}/* @flow */function is_number(a){return'number'==typeof a}function is_string(a){return'string'==typeof a}function is_boolean(a){return'boolean'==typeof a}function is_symbol(a){return'symbol'==typeof a}function is_object(a){return'object'==typeof a}function is_variable(a){return a instanceof Variable}function is_null(a){return null===a}function is_array(a){return Array.isArray(a)}function is_function(a){return'[object Function]'==Object.prototype.toString.call(a)}function is_map(a){return a instanceof Map}function resolveNull(){return function(a){return is_null(a)}}function resolveWildcard(){return function(){return!0}}function resolveObject(a){let b={};const c=Object.keys(a).concat(Object.getOwnPropertySymbols(a));for(let d of c)b[d]=buildMatch(a[d]);return function(d,e){if(!is_object(d)||a.length>d.length)return!1;for(let a of c)if(!(a in d)||!b[a](d[a],e))return!1;return!0}}function getSize(a,b){return a*b/8}function arraysEqual(c,a){if(c===a)return!0;if(null==c||null==a)return!1;if(c.length!=a.length)return!1;for(var b=0;bf.integer(a));return new f(...b)}function resolveNoMatch(){return function(){return!1}}function buildMatch(a){if(null===a)return resolveNull(a);if('undefined'==typeof a)return resolveWildcard(a);const b=a.constructor.prototype,c=g.get(b);return c?c(a):'object'==typeof a?resolveObject(a):resolveNoMatch()}function defmatchgen(...a){const b=getArityMap(a);return function*(...a){let[c,d]=findMatchingFunction(a,b);return yield*c.apply(this,d)}}function findMatchingFunction(a,b){if(b.has(a.length)){const c=b.get(a.length);let d=null,e=null;for(let b of c){let c=[];a=fillInOptionalValues(a,b.arity,b.optionals);const f=b.pattern(a,c),[g,h]=checkNamedVariables(c);if(f&&h&&b.guard.apply(this,g)){d=b.fn,e=g;break}}if(!d)throw console.error('No match for:',a),new MatchError(a);return[d,e]}throw console.error('Arity of',a.length,'not found. No match for:',a),new MatchError(a)}function getArityMap(a){let b=new Map;for(const c of a){const a=getArityRange(c);for(const d of a){let a=[];b.has(d)&&(a=b.get(d)),a.push(c),b.set(d,a)}}return b}function getArityRange(a){const b=a.arity-a.optionals.length,c=a.arity;let d=[b];for(;d[d.length-1]!=c;)d.push(d[d.length-1]+1);return d}function getOptionalValues(a){let b=[];for(let c=0;c!0,d=null){let e=[],f=buildMatch(a);const g=f(b,e),[h,i]=checkNamedVariables(e);return g&&i&&c.apply(this,h)?h:d}function run_generators(a,b){if(0==b.length)return a.map((a)=>{return Array.isArray(a)?a:[a]});const c=b.pop();let d=[];for(let e of c())for(let b of a)d.push([e].concat(b));return run_generators(d,b)}function iterator_to_reducer(a,b,c){const d=a[Symbol.iterator]();let e=d.next(),f=b;for(;!1===e.done;){if(f=c(e.value,f.get(1)),f.get(0)===Symbol.for('halt'))return new o.Tuple(Symbol.for('halted'),f.get(1));if(f.get(0)===Symbol.for('suspend'))return new o.Tuple(Symbol.for('suspended'),f.get(1),(a)=>{return iterator_to_reducer(d,a,c)});e=d.next()}return new o.Tuple(Symbol.for('done'),f.get(1))}function map_to_object(a){const b={};for(const[c,d]of a.entries())b[c]=d instanceof Map?map_to_object(d):d;return b}function run_list_generators(a,b){if(0==b.length)return a.map((a)=>{return Array.isArray(a)?a:[a]});const c=b.pop(),d=[];for(const e of c())for(const b of a)d.push([e].concat(b));return run_list_generators(d,b)}// http://erlang.org/doc/man/erlang.html +function atom_to_binary(a,b=Symbol.for('utf8')){if(b!==Symbol.for('utf8'))throw new Error(`unsupported encoding ${b}`);return a.__MODULE__?Symbol.keyFor(a.__MODULE__):Symbol.keyFor(a)}function binary_to_atom(a,b=Symbol.for('utf8')){if(b!==Symbol.for('utf8'))throw new Error(`unsupported encoding ${b}`);return Symbol.for(a)}function is_bitstring$1(a){return a instanceof e.BitString}function is_number$1(a){return'number'==typeof a||a instanceof Number}function is_integer(a){return b(a)}function is_binary(a){return'string'==typeof a||a instanceof String}function iolist_to_binary(b){if(is_binary(b))return b;if(is_bitstring$1(b))return a(...b.value);const c=b.reduce((b,c)=>{if(is_integer(c))return b+a(c);return is_bitstring$1(c)?b+a(...c.value):b+iolist_to_binary(c)},'');return c}function is_key(a,b){return b.has(a)}// http://erlang.org/doc/man/lists.html +function reverse(a){return[...a]}function flatten(a,b=[]){const c=a.reduce((a,b)=>{return Array.isArray(b)?a.concat(flatten(b)):a.concat(b)},[]);return c.concat(b)}function foldl(a,b,c){return c.reduce((b,c)=>{return a(c,b)},b)}function keyfind(a,b,c){for(const d of c)if(d.get(b-1)===a)return d;return!1}function keydelete(a,b,c){const d=[];let e=!1;for(let f=0;fBitString$1.integer(a));return new BitString$1(...d)}[Symbol.iterator](){return this.value[Symbol.iterator]()}toString(){var a,b='';for(a=0;a>'}process(a){let b=[];var c;for(c=0;cb?c.push(b):2048>b?c.push(192|b>>6,128|63&b):55296>b||57344<=b?c.push(224|b>>12,128|63&b>>6,128|63&b):(d++,b=65536+((1023&b)<<10|1023&a.charCodeAt(d)),c.push(240|b>>18,128|63&b>>12,128|63&b>>6,128|63&b));return c}static toUTF16Array(a){for(var b,c=[],d=0;d=b?(c.push(0),c.push(b)):(c.push(255&b>>8),c.push(255&b));return c}static toUTF32Array(a){for(var b,c=[],d=0;d=b?(c.push(0),c.push(0),c.push(0),c.push(b)):(c.push(0),c.push(0),c.push(255&b>>8),c.push(255&b));return c}//http://stackoverflow.com/questions/2003493/javascript-float-from-to-bits +static float32ToBytes(a){var b=[],c=new ArrayBuffer(4);new Float32Array(c)[0]=a;let d=new Uint32Array(c)[0];return b.push(255&d>>24),b.push(255&d>>16),b.push(255&d>>8),b.push(255&d),b}static float64ToBytes(a){var b=[],c=new ArrayBuffer(8);new Float64Array(c)[0]=a;var d=new Uint32Array(c)[0],e=new Uint32Array(c)[1];return b.push(255&e>>24),b.push(255&e>>16),b.push(255&e>>8),b.push(255&e),b.push(255&d>>24),b.push(255&d>>16),b.push(255&d>>8),b.push(255&d),b}}var e={Tuple,PID:class PID{constructor(){++c,this.id=c}toString(){return'PID#<0.'+this.id+'.0>'}},Reference:class Reference{constructor(){++d,this.id=d,this.ref=Symbol()}toString(){return'Ref#<0.0.0.'+this.id+'>'}},BitString:BitString$1};/* @flow */const f=e.BitString,g=new Map;g.set(Variable.prototype,function resolveVariable(a){return function(b,c){return null===a.name||a.name.startsWith('_')?c.push(b):c.push(namedVariableResult(a.name,b)),!0}}),g.set(Wildcard.prototype,resolveWildcard),g.set(HeadTail.prototype,function resolveHeadTail(){return function(a,b){if(!is_array(a)||2>a.length)return!1;const c=a[0],d=a.slice(1);return b.push(c),b.push(d),!0}}),g.set(StartsWith.prototype,function resolveStartsWith(a){const b=a.prefix;return function(a,c){return is_string(a)&&a.startsWith(b)&&(c.push(a.substring(b.length)),!0)}}),g.set(Capture.prototype,function resolveCapture(a){const b=buildMatch(a.value);return function(a,c){return!!b(a,c)&&(c.push(a),!0)}}),g.set(Bound.prototype,function resolveBound(a){return function(b){return typeof b==typeof a.value&&b===a.value}}),g.set(Type.prototype,function resolveType(a){return function(b,c){if(b instanceof a.type){const d=buildMatch(a.objPattern);return d(b,c)}return!1}}),g.set(BitStringMatch.prototype,function resolveBitString(a){let b=[];for(let c of a.values)if(is_variable(c.value)){let a=getSize(c.unit,c.size);fillArray(b,a)}else b=b.concat(new f(c).value);let c=a.values;return function(a,d){var e=String.fromCharCode;let g=null;if(!is_string(a)&&!(a instanceof f))return!1;g=is_string(a)?new f(f.binary(a)):a;let h=0;for(let f,j=0;jd.size)return!1;for(let a of c)if(!d.has(a)||!b.get(a)(d.get(a),e))return!1;return!0}}),g.set(Array.prototype,function resolveArray(a){const b=a.map((a)=>buildMatch(a));return function(c,d){return is_array(c)&&c.length==a.length&&c.every(function(a,e){return b[e](c[e],d)})}}),g.set(String.prototype,function resolveString(a){return function(b){return is_string(b)&&b===a}}),g.set(Boolean.prototype,function resolveBoolean(a){return function(b){return is_boolean(b)&&b===a}}),g.set(Function.prototype,function resolveFunction(a){return function(b){return is_function(b)&&b===a}}),g.set(Object.prototype,resolveObject);class MatchError extends Error{constructor(a){if(super(),'symbol'==typeof a)this.message='No match for: '+a.toString();else if(Array.isArray(a)){let b=a.map((a)=>{return null===a?'null':'undefined'==typeof a?'undefined':a.toString()});this.message='No match for: '+b}else this.message='No match for: '+a;this.stack=new Error().stack,this.name=this.constructor.name}}class Clause{constructor(a,b,c=()=>!0){this.pattern=buildMatch(a),this.arity=a.length,this.optionals=getOptionalValues(a),this.fn=b,this.guard=c}}const h=Symbol();// https://github.com/airportyh/protomorphism +class Protocol{constructor(a){function createFun(a){return function(...c){const d=c[0];let e=null;if(null===d&&this.hasImplementation(Symbol('null'))?e=this.registry.get(Symbol)[a]:b(d)&&this.hasImplementation(o.Integer)?e=this.registry.get(o.Integer)[a]:'number'==typeof d&&!b(d)&&this.hasImplementation(o.Float)?e=this.registry.get(o.Float)[a]:'string'==typeof d&&this.hasImplementation(o.BitString)?e=this.registry.get(o.BitString)[a]:d&&d.has(Symbol.for('__struct__'))&&this.hasImplementation(d)?e=this.registry.get(d.get(Symbol.for('__struct__')).__MODULE__)[a]:null!==d&&this.hasImplementation(d)?e=this.registry.get(d.constructor)[a]:this.fallback&&(e=this.fallback[a]),null!=e){const a=e.apply(this,c);return a}throw new Error(`No implementation found for ${d}`)}}for(const b in this.registry=new Map,this.fallback=null,a)this[b]=createFun(b).bind(this)}implementation(a,b){null===a?this.fallback=b:this.registry.set(a,b)}hasImplementation(a){if(a===o.Integer||a===o.Float||a===o.BitString)return this.registry.has(a);return a&&a.has(Symbol.for('__struct__'))?this.registry.has(a.get(Symbol.for('__struct__')).__MODULE__):this.registry.has(a.constructor)}}var i={atom_to_binary,binary_to_atom,binary_to_existing_atom:function binary_to_existing_atom(a,b=Symbol.for('utf8')){return binary_to_atom(a,b)},list_concatenation:function list_concatenation(a,b){return a.concat(b)},list_subtraction:function list_subtraction(a,b){const c=[...a];for(const d of b){const a=c.indexOf(d);-1b},greaterThanOrEqualTo:function greaterThanOrEqualTo(a,b){return a>=b},lessThan:function lessThan(a,b){return a>b},bxor:function bxor(a,b){return a^b},bnot:function bnot(a){return~a},is_bitstring:is_bitstring$1,is_boolean:function is_boolean$1(a){return'boolean'==typeof a||a instanceof Boolean},is_float:function is_float(a){return is_number$1(a)&&!b(a)},is_function:function is_function$1(a){return'function'==typeof a||a instanceof Function},is_integer,is_list:function is_list(a){return Array.isArray(a)},is_map:function is_map$1(a){return a instanceof Map},is_number:is_number$1,is_pid:function is_pid(a){return a instanceof e.PID},is_port:function is_port(){return!1},is_reference:function is_reference(a){return a instanceof e.Reference},is_tuple:function is_tuple(a){return a instanceof e.Tuple},is_atom:function is_atom(a){return'symbol'==typeof a||a instanceof Symbol||a.__MODULE__},is_binary,element:function element(a,b){return b.get(a-1)},setelement:function setelement(a,b,c){const d=[...b.values];return d[a-1]=c,new e.Tuple(...d)},make_tuple:function make_tuple(a,b){const c=[];for(let d=0;d!0){let d=[],e=buildMatch(a);const f=e(b,d),[g,h]=checkNamedVariables(d);if(f&&h&&c.apply(this,g))return g;throw console.error('No match for:',b),new MatchError(b)},MatchError,variable:function variable(a=null,b=Symbol.for('tailored.no_value')){return new Variable(a,b)},wildcard:function wildcard(){return new Wildcard},startsWith:function startsWith(a){return new StartsWith(a)},capture:function capture(a){return new Capture(a)},headTail:function headTail(){return new HeadTail},type:function a(a,b={}){return new Type(a,b)},bound:function bound(a){return new Bound(a)},Clause,clause:function clause(a,b,c=()=>!0){return new Clause(a,b,c)},bitStringMatch:function bitStringMatch(...a){return new BitStringMatch(...a)},match_or_default,defmatchgen,list_comprehension:function list_comprehension(a,b){const c=run_generators(b.pop()(),b);let d=[];for(let e of c)a.guard.apply(this,e)&&d.push(a.fn.apply(this,e));return d},list_generator:function list_generator(a,b){return function(){let c=[];for(let d of b){const b=match_or_default(a,d,()=>!0,h);if(b!=h){const[a]=b;c.push(a)}}return c}},bitstring_generator:function bitstring_generator(a,b){return function(){let c=[],d=b.slice(0,a.byte_size()),e=1;for(;d.byte_size==a.byte_size();){const f=match_or_default(a,d,()=>!0,h);if(f!=h){c.push(f)}d=b.slice(a.byte_size()*e,a.byte_size()*(e+1)),e++}return c}},bitstring_comprehension:function bitstring_comprehension(a,b){const c=run_generators(b.pop()(),b);let d=[];for(let e of c)a.guard.apply(this,e)&&d.push(a.fn.apply(this,e));return d=d.map((a)=>e.BitString.integer(a)),new e.BitString(...d)},defmatchGen:function defmatchGen(...a){return defmatchgen(...a)},defmatchAsync:function defmatchAsync(...a){const b=getArityMap(a);return async function(...a){if(b.has(a.length)){const c=b.get(a.length);let d=null,e=null;for(let b of c){let c=[];a=fillInOptionalValues(a,b.arity,b.optionals);const f=b.pattern(a,c),[g,h]=checkNamedVariables(c);if(f&&h&&(await b.guard.apply(this,c))){d=b.fn,e=c;break}}if(!d)throw console.error('No match for:',a),new MatchError(a);return d.apply(this,e)}throw console.error('Arity of',a.length,'not found. No match for:',a),new MatchError(a)}}},Integer:class Integer{},Float:class Float{},Functions:{call_property:function call_property(a,b){if(!b)return a instanceof Function||'function'==typeof a?a():a;if(a instanceof Map){let c=null;if(a.has(b)?c=b:a.has(Symbol.for(b))&&(c=Symbol.for(b)),null===c)throw new Error(`Property ${b} not found in ${a}`);return a.get(c)instanceof Function||'function'==typeof a.get(c)?a.get(c)():a.get(c)}let c=null;if('number'==typeof a||'symbol'==typeof a||'boolean'==typeof a||'string'==typeof a?void 0===a[b]?void 0!==a[Symbol.for(b)]&&(c=Symbol.for(b)):c=b:b in a?c=b:Symbol.for(b)in a&&(c=Symbol.for(b)),null===c)throw new Error(`Property ${b} not found in ${a}`);return a[c]instanceof Function||'function'==typeof a[c]?a[c]():a[c]},defprotocol:function defprotocol(a){return new Protocol(a)},defimpl:function defimpl(a,b,c){a.implementation(b,c)},build_namespace:function build_namespace(a,b){let c=b.split('.');const d=a;let e=a;'Elixir'===c[0]&&(c=c.slice(1));for(const d of c)'undefined'==typeof e[d]&&(e[d]={}),e=e[d];return d.__table__=a.__table__||{},d.__table__[Symbol.for(b)]=e,e},iterator_to_reducer,map_to_object},SpecialForms:{_case:function _case(a,b){return o.Patterns.defmatch(...b)(a)},cond:function cond(...a){for(const b of a)if(b[0])return b[1]();throw new Error},_for:function _for(a,b,c,d=[]){let[e,f]=c.into(d);const g=run_list_generators(b.pop()(),b);for(const h of g)a.guard.apply(this,h)&&(e=f(e,new o.Tuple(Symbol.for('cont'),a.fn.apply(this,h))));return f(e,Symbol.for('done'))},_try:function _try(a,b,c,d,e){let f=null;try{f=a()}catch(a){let d=null;if(b)try{return d=b(a),d}catch(a){if(a instanceof o.Patterns.MatchError)throw a}if(c)try{return d=c(a),d}catch(a){if(a instanceof o.Patterns.MatchError)throw a}throw a}finally{e&&e()}if(d)try{return d(f)}catch(a){if(a instanceof o.Patterns.MatchError)throw new Error('No Match Found in Else');throw a}else return f},_with:function _with(...a){let b=[],c=null,d=null;'function'==typeof a[a.length-2]?[c,d]=a.splice(-2):c=a.pop();for(let c=0;c{const[c,d]=b;return a.set(c,d),a},new Map)},keys:function keys(a){return!1===i.is_map(a)?new e.Tuple(l,a):Array.from(a.keys())},values:function values$1(a){return!1===i.is_map(a)?new e.Tuple(l,a):Array.from(a.values())},is_key,put:function put(a,b,c){if(!1===i.is_map(c))return new e.Tuple(l,c);const d=new Map(c);return d.set(a,b),d},merge:function merge(a,b){return!1===i.is_map(a)?new e.Tuple(l,a):!1===i.is_map(b)?new e.Tuple(l,b):new Map([...a,...b])},update:function update(a,b,c){return!1===i.is_map(c)?new e.Tuple(l,c):!1===is_key(a,c)?new e.Tuple(m,a):new Map([...c,[a,b]])},get:function get(...a){const b=a[0],c=a[1];return!1===i.is_map(c)?new e.Tuple(l,c):is_key(b)?c.get(b):3===a.length?a[2]:new e.Tuple(m,b)},take:function take(a,b){if(!1===i.is_map(b))return new e.Tuple(l,b);if(!is_key(a))return k;const c=b.get(a),d=new Map(b);return d.delete(a),new e.Tuple(c,d)}},lists:{reverse,foreach:function foreach(a,b){return b.forEach((b)=>a(b)),Symbol.for('ok')},duplicate:function duplicate(a,b){const c=[];for(;c.length{if(d.get(c-1)a.get(c-1)?1:0})},keystore:function keystore(a,b,c,d){const e=[...c];for(let f=0;fa.toString()).join()},map:function map(a,b){return b.map((b)=>a(b))},filter:function filter(a,b){return b.filter((b)=>a(b))},filtermap:function filtermap(a,b){const c=[];for(const d of b){const b=a(d);!0===b?c.push(d):b instanceof e.Tuple&&!0===b.get(0)&&c.push(b.get(1))}return c},member:function member(a,b){for(const c of b)if(c===a)return!0;return!1},all:function all(a,b){for(const c of b)if(!1===a(c))return!1;return!0},any:function any(a,b){for(const c of b)if(!0===a(c))return!0;return!1},splitwith:function splitwith(a,b){let c=!1;const d=[],f=[];for(const e of b)!0==c?f.push(e):!0===a(e)?d.push(e):(c=!0,f.push(e));return new e.Tuple(d,f)},sort:function sort(...a){if(1===a.length){const b=[...a[0]];return b.sort()}const c=a[0],b=[...a[1]];return b.sort((d,a)=>{const b=c(d,a);return!0===b?-1:1})}},elixir_errors:{warn:function warn(a){const b=a.join('');return console.warn(`warning: ${b}`),Symbol.for('ok')}},io:{put_chars:function put_chars(b,c){let d=null;return d=Array.isArray(c)?a(...c):c,b===Symbol.for('stderr')?console.error(d):console.log(d),Symbol.for('ok')}}};return{Core:o}}(); diff --git a/src/javascript/lib/core.js b/src/javascript/lib/core.js index f0e5277f..d2677323 100644 --- a/src/javascript/lib/core.js +++ b/src/javascript/lib/core.js @@ -6,6 +6,7 @@ import erlang from './core/erlang_compat/erlang'; import maps from './core/erlang_compat/maps'; import lists from './core/erlang_compat/lists'; import elixir_errors from './core/erlang_compat/elixir_errors'; +import io from './core/erlang_compat/io'; import Store from './core/store'; class Integer {} @@ -43,5 +44,6 @@ export default { erlang, maps, lists, - elixir_errors + elixir_errors, + io }; diff --git a/src/javascript/lib/core/erlang_compat/io.js b/src/javascript/lib/core/erlang_compat/io.js new file mode 100644 index 00000000..9d7eccb3 --- /dev/null +++ b/src/javascript/lib/core/erlang_compat/io.js @@ -0,0 +1,21 @@ +function put_chars(ioDevice, charData) { + let dataToWrite = null; + + if (Array.isArray(charData)) { + dataToWrite = String.fromCodePoint(...charData); + } else { + dataToWrite = charData; + } + + if (ioDevice === Symbol.for('stderr')) { + console.error(dataToWrite); + } else { + console.log(dataToWrite); + } + + return Symbol.for('ok'); +} + +export default { + put_chars +}; From ba2b4d3f6eea02f9f7e4bcca5dbd24dece147d15 Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Fri, 21 Jul 2017 21:10:55 -0500 Subject: [PATCH 632/860] Updated find_used_functions to walk super calls Added integer_to_binary to erlang.js --- lib/elixir_script/passes/find_used_functions.ex | 3 ++- lib/elixir_script/passes/find_used_modules.ex | 2 +- lib/elixir_script/passes/translate/form.ex | 6 ++++++ priv/build/iife/ElixirScript.Core.js | 2 +- src/javascript/lib/core/erlang_compat/erlang.js | 7 ++++++- 5 files changed, 16 insertions(+), 4 deletions(-) diff --git a/lib/elixir_script/passes/find_used_functions.ex b/lib/elixir_script/passes/find_used_functions.ex index b7ffdcf6..c77cddcc 100644 --- a/lib/elixir_script/passes/find_used_functions.ex +++ b/lib/elixir_script/passes/find_used_functions.ex @@ -264,7 +264,8 @@ defmodule ElixirScript.FindUsedFunctions do walk(params, state) end - defp walk({:super, _, params}, state) do + defp walk({:super, _, [{_, function} | params]}, state) do + walk_module(state.module, function, length(params), state.pid) walk(params, state) end diff --git a/lib/elixir_script/passes/find_used_modules.ex b/lib/elixir_script/passes/find_used_modules.ex index b7ebddc7..ee65f7a0 100644 --- a/lib/elixir_script/passes/find_used_modules.ex +++ b/lib/elixir_script/passes/find_used_modules.ex @@ -286,7 +286,7 @@ defmodule ElixirScript.FindUsedModules do end end - defp walk({:super, _, params}, state) do + defp walk({:super, _, [{_, _} | params]}, state) do walk(params, state) end diff --git a/lib/elixir_script/passes/translate/form.ex b/lib/elixir_script/passes/translate/form.ex index 70e2af99..f8d6eeaa 100644 --- a/lib/elixir_script/passes/translate/form.ex +++ b/lib/elixir_script/passes/translate/form.ex @@ -286,6 +286,12 @@ defmodule ElixirScript.Translate.Form do end end + def compile({:default, _, _}, state) do + var = :__default__ + var = Pattern.get_variable_name(to_string(var), state) + { ElixirScript.Translate.Identifier.make_identifier(var), state } + end + def compile({var, _, _}, state) do var = Pattern.get_variable_name(to_string(var), state) { ElixirScript.Translate.Identifier.make_identifier(var), state } diff --git a/priv/build/iife/ElixirScript.Core.js b/priv/build/iife/ElixirScript.Core.js index a076e953..2a8420a5 100644 --- a/priv/build/iife/ElixirScript.Core.js +++ b/priv/build/iife/ElixirScript.Core.js @@ -2,5 +2,5 @@ var ElixirScript=function(){'use strict';/* @flow */function namedVariableResult function atom_to_binary(a,b=Symbol.for('utf8')){if(b!==Symbol.for('utf8'))throw new Error(`unsupported encoding ${b}`);return a.__MODULE__?Symbol.keyFor(a.__MODULE__):Symbol.keyFor(a)}function binary_to_atom(a,b=Symbol.for('utf8')){if(b!==Symbol.for('utf8'))throw new Error(`unsupported encoding ${b}`);return Symbol.for(a)}function is_bitstring$1(a){return a instanceof e.BitString}function is_number$1(a){return'number'==typeof a||a instanceof Number}function is_integer(a){return b(a)}function is_binary(a){return'string'==typeof a||a instanceof String}function iolist_to_binary(b){if(is_binary(b))return b;if(is_bitstring$1(b))return a(...b.value);const c=b.reduce((b,c)=>{if(is_integer(c))return b+a(c);return is_bitstring$1(c)?b+a(...c.value):b+iolist_to_binary(c)},'');return c}function is_key(a,b){return b.has(a)}// http://erlang.org/doc/man/lists.html function reverse(a){return[...a]}function flatten(a,b=[]){const c=a.reduce((a,b)=>{return Array.isArray(b)?a.concat(flatten(b)):a.concat(b)},[]);return c.concat(b)}function foldl(a,b,c){return c.reduce((b,c)=>{return a(c,b)},b)}function keyfind(a,b,c){for(const d of c)if(d.get(b-1)===a)return d;return!1}function keydelete(a,b,c){const d=[];let e=!1;for(let f=0;fBitString$1.integer(a));return new BitString$1(...d)}[Symbol.iterator](){return this.value[Symbol.iterator]()}toString(){var a,b='';for(a=0;a>'}process(a){let b=[];var c;for(c=0;cb?c.push(b):2048>b?c.push(192|b>>6,128|63&b):55296>b||57344<=b?c.push(224|b>>12,128|63&b>>6,128|63&b):(d++,b=65536+((1023&b)<<10|1023&a.charCodeAt(d)),c.push(240|b>>18,128|63&b>>12,128|63&b>>6,128|63&b));return c}static toUTF16Array(a){for(var b,c=[],d=0;d=b?(c.push(0),c.push(b)):(c.push(255&b>>8),c.push(255&b));return c}static toUTF32Array(a){for(var b,c=[],d=0;d=b?(c.push(0),c.push(0),c.push(0),c.push(b)):(c.push(0),c.push(0),c.push(255&b>>8),c.push(255&b));return c}//http://stackoverflow.com/questions/2003493/javascript-float-from-to-bits static float32ToBytes(a){var b=[],c=new ArrayBuffer(4);new Float32Array(c)[0]=a;let d=new Uint32Array(c)[0];return b.push(255&d>>24),b.push(255&d>>16),b.push(255&d>>8),b.push(255&d),b}static float64ToBytes(a){var b=[],c=new ArrayBuffer(8);new Float64Array(c)[0]=a;var d=new Uint32Array(c)[0],e=new Uint32Array(c)[1];return b.push(255&e>>24),b.push(255&e>>16),b.push(255&e>>8),b.push(255&e),b.push(255&d>>24),b.push(255&d>>16),b.push(255&d>>8),b.push(255&d),b}}var e={Tuple,PID:class PID{constructor(){++c,this.id=c}toString(){return'PID#<0.'+this.id+'.0>'}},Reference:class Reference{constructor(){++d,this.id=d,this.ref=Symbol()}toString(){return'Ref#<0.0.0.'+this.id+'>'}},BitString:BitString$1};/* @flow */const f=e.BitString,g=new Map;g.set(Variable.prototype,function resolveVariable(a){return function(b,c){return null===a.name||a.name.startsWith('_')?c.push(b):c.push(namedVariableResult(a.name,b)),!0}}),g.set(Wildcard.prototype,resolveWildcard),g.set(HeadTail.prototype,function resolveHeadTail(){return function(a,b){if(!is_array(a)||2>a.length)return!1;const c=a[0],d=a.slice(1);return b.push(c),b.push(d),!0}}),g.set(StartsWith.prototype,function resolveStartsWith(a){const b=a.prefix;return function(a,c){return is_string(a)&&a.startsWith(b)&&(c.push(a.substring(b.length)),!0)}}),g.set(Capture.prototype,function resolveCapture(a){const b=buildMatch(a.value);return function(a,c){return!!b(a,c)&&(c.push(a),!0)}}),g.set(Bound.prototype,function resolveBound(a){return function(b){return typeof b==typeof a.value&&b===a.value}}),g.set(Type.prototype,function resolveType(a){return function(b,c){if(b instanceof a.type){const d=buildMatch(a.objPattern);return d(b,c)}return!1}}),g.set(BitStringMatch.prototype,function resolveBitString(a){let b=[];for(let c of a.values)if(is_variable(c.value)){let a=getSize(c.unit,c.size);fillArray(b,a)}else b=b.concat(new f(c).value);let c=a.values;return function(a,d){var e=String.fromCharCode;let g=null;if(!is_string(a)&&!(a instanceof f))return!1;g=is_string(a)?new f(f.binary(a)):a;let h=0;for(let f,j=0;jd.size)return!1;for(let a of c)if(!d.has(a)||!b.get(a)(d.get(a),e))return!1;return!0}}),g.set(Array.prototype,function resolveArray(a){const b=a.map((a)=>buildMatch(a));return function(c,d){return is_array(c)&&c.length==a.length&&c.every(function(a,e){return b[e](c[e],d)})}}),g.set(String.prototype,function resolveString(a){return function(b){return is_string(b)&&b===a}}),g.set(Boolean.prototype,function resolveBoolean(a){return function(b){return is_boolean(b)&&b===a}}),g.set(Function.prototype,function resolveFunction(a){return function(b){return is_function(b)&&b===a}}),g.set(Object.prototype,resolveObject);class MatchError extends Error{constructor(a){if(super(),'symbol'==typeof a)this.message='No match for: '+a.toString();else if(Array.isArray(a)){let b=a.map((a)=>{return null===a?'null':'undefined'==typeof a?'undefined':a.toString()});this.message='No match for: '+b}else this.message='No match for: '+a;this.stack=new Error().stack,this.name=this.constructor.name}}class Clause{constructor(a,b,c=()=>!0){this.pattern=buildMatch(a),this.arity=a.length,this.optionals=getOptionalValues(a),this.fn=b,this.guard=c}}const h=Symbol();// https://github.com/airportyh/protomorphism -class Protocol{constructor(a){function createFun(a){return function(...c){const d=c[0];let e=null;if(null===d&&this.hasImplementation(Symbol('null'))?e=this.registry.get(Symbol)[a]:b(d)&&this.hasImplementation(o.Integer)?e=this.registry.get(o.Integer)[a]:'number'==typeof d&&!b(d)&&this.hasImplementation(o.Float)?e=this.registry.get(o.Float)[a]:'string'==typeof d&&this.hasImplementation(o.BitString)?e=this.registry.get(o.BitString)[a]:d&&d.has(Symbol.for('__struct__'))&&this.hasImplementation(d)?e=this.registry.get(d.get(Symbol.for('__struct__')).__MODULE__)[a]:null!==d&&this.hasImplementation(d)?e=this.registry.get(d.constructor)[a]:this.fallback&&(e=this.fallback[a]),null!=e){const a=e.apply(this,c);return a}throw new Error(`No implementation found for ${d}`)}}for(const b in this.registry=new Map,this.fallback=null,a)this[b]=createFun(b).bind(this)}implementation(a,b){null===a?this.fallback=b:this.registry.set(a,b)}hasImplementation(a){if(a===o.Integer||a===o.Float||a===o.BitString)return this.registry.has(a);return a&&a.has(Symbol.for('__struct__'))?this.registry.has(a.get(Symbol.for('__struct__')).__MODULE__):this.registry.has(a.constructor)}}var i={atom_to_binary,binary_to_atom,binary_to_existing_atom:function binary_to_existing_atom(a,b=Symbol.for('utf8')){return binary_to_atom(a,b)},list_concatenation:function list_concatenation(a,b){return a.concat(b)},list_subtraction:function list_subtraction(a,b){const c=[...a];for(const d of b){const a=c.indexOf(d);-1b},greaterThanOrEqualTo:function greaterThanOrEqualTo(a,b){return a>=b},lessThan:function lessThan(a,b){return a>b},bxor:function bxor(a,b){return a^b},bnot:function bnot(a){return~a},is_bitstring:is_bitstring$1,is_boolean:function is_boolean$1(a){return'boolean'==typeof a||a instanceof Boolean},is_float:function is_float(a){return is_number$1(a)&&!b(a)},is_function:function is_function$1(a){return'function'==typeof a||a instanceof Function},is_integer,is_list:function is_list(a){return Array.isArray(a)},is_map:function is_map$1(a){return a instanceof Map},is_number:is_number$1,is_pid:function is_pid(a){return a instanceof e.PID},is_port:function is_port(){return!1},is_reference:function is_reference(a){return a instanceof e.Reference},is_tuple:function is_tuple(a){return a instanceof e.Tuple},is_atom:function is_atom(a){return'symbol'==typeof a||a instanceof Symbol||a.__MODULE__},is_binary,element:function element(a,b){return b.get(a-1)},setelement:function setelement(a,b,c){const d=[...b.values];return d[a-1]=c,new e.Tuple(...d)},make_tuple:function make_tuple(a,b){const c=[];for(let d=0;db},greaterThanOrEqualTo:function greaterThanOrEqualTo(a,b){return a>=b},lessThan:function lessThan(a,b){return a>b},bxor:function bxor(a,b){return a^b},bnot:function bnot(a){return~a},is_bitstring:is_bitstring$1,is_boolean:function is_boolean$1(a){return'boolean'==typeof a||a instanceof Boolean},is_float:function is_float(a){return is_number$1(a)&&!b(a)},is_function:function is_function$1(a){return'function'==typeof a||a instanceof Function},is_integer,is_list:function is_list(a){return Array.isArray(a)},is_map:function is_map$1(a){return a instanceof Map},is_number:is_number$1,is_pid:function is_pid(a){return a instanceof e.PID},is_port:function is_port(){return!1},is_reference:function is_reference(a){return a instanceof e.Reference},is_tuple:function is_tuple(a){return a instanceof e.Tuple},is_atom:function is_atom(a){return'symbol'==typeof a||a instanceof Symbol||a.__MODULE__},is_binary,element:function element(a,b){return b.get(a-1)},setelement:function setelement(a,b,c){const d=[...b.values];return d[a-1]=c,new e.Tuple(...d)},make_tuple:function make_tuple(a,b){const c=[];for(let d=0;d!0){let d=[],e=buildMatch(a);const f=e(b,d),[g,h]=checkNamedVariables(d);if(f&&h&&c.apply(this,g))return g;throw console.error('No match for:',b),new MatchError(b)},MatchError,variable:function variable(a=null,b=Symbol.for('tailored.no_value')){return new Variable(a,b)},wildcard:function wildcard(){return new Wildcard},startsWith:function startsWith(a){return new StartsWith(a)},capture:function capture(a){return new Capture(a)},headTail:function headTail(){return new HeadTail},type:function a(a,b={}){return new Type(a,b)},bound:function bound(a){return new Bound(a)},Clause,clause:function clause(a,b,c=()=>!0){return new Clause(a,b,c)},bitStringMatch:function bitStringMatch(...a){return new BitStringMatch(...a)},match_or_default,defmatchgen,list_comprehension:function list_comprehension(a,b){const c=run_generators(b.pop()(),b);let d=[];for(let e of c)a.guard.apply(this,e)&&d.push(a.fn.apply(this,e));return d},list_generator:function list_generator(a,b){return function(){let c=[];for(let d of b){const b=match_or_default(a,d,()=>!0,h);if(b!=h){const[a]=b;c.push(a)}}return c}},bitstring_generator:function bitstring_generator(a,b){return function(){let c=[],d=b.slice(0,a.byte_size()),e=1;for(;d.byte_size==a.byte_size();){const f=match_or_default(a,d,()=>!0,h);if(f!=h){c.push(f)}d=b.slice(a.byte_size()*e,a.byte_size()*(e+1)),e++}return c}},bitstring_comprehension:function bitstring_comprehension(a,b){const c=run_generators(b.pop()(),b);let d=[];for(let e of c)a.guard.apply(this,e)&&d.push(a.fn.apply(this,e));return d=d.map((a)=>e.BitString.integer(a)),new e.BitString(...d)},defmatchGen:function defmatchGen(...a){return defmatchgen(...a)},defmatchAsync:function defmatchAsync(...a){const b=getArityMap(a);return async function(...a){if(b.has(a.length)){const c=b.get(a.length);let d=null,e=null;for(let b of c){let c=[];a=fillInOptionalValues(a,b.arity,b.optionals);const f=b.pattern(a,c),[g,h]=checkNamedVariables(c);if(f&&h&&(await b.guard.apply(this,c))){d=b.fn,e=c;break}}if(!d)throw console.error('No match for:',a),new MatchError(a);return d.apply(this,e)}throw console.error('Arity of',a.length,'not found. No match for:',a),new MatchError(a)}}},Integer:class Integer{},Float:class Float{},Functions:{call_property:function call_property(a,b){if(!b)return a instanceof Function||'function'==typeof a?a():a;if(a instanceof Map){let c=null;if(a.has(b)?c=b:a.has(Symbol.for(b))&&(c=Symbol.for(b)),null===c)throw new Error(`Property ${b} not found in ${a}`);return a.get(c)instanceof Function||'function'==typeof a.get(c)?a.get(c)():a.get(c)}let c=null;if('number'==typeof a||'symbol'==typeof a||'boolean'==typeof a||'string'==typeof a?void 0===a[b]?void 0!==a[Symbol.for(b)]&&(c=Symbol.for(b)):c=b:b in a?c=b:Symbol.for(b)in a&&(c=Symbol.for(b)),null===c)throw new Error(`Property ${b} not found in ${a}`);return a[c]instanceof Function||'function'==typeof a[c]?a[c]():a[c]},defprotocol:function defprotocol(a){return new Protocol(a)},defimpl:function defimpl(a,b,c){a.implementation(b,c)},build_namespace:function build_namespace(a,b){let c=b.split('.');const d=a;let e=a;'Elixir'===c[0]&&(c=c.slice(1));for(const d of c)'undefined'==typeof e[d]&&(e[d]={}),e=e[d];return d.__table__=a.__table__||{},d.__table__[Symbol.for(b)]=e,e},iterator_to_reducer,map_to_object},SpecialForms:{_case:function _case(a,b){return o.Patterns.defmatch(...b)(a)},cond:function cond(...a){for(const b of a)if(b[0])return b[1]();throw new Error},_for:function _for(a,b,c,d=[]){let[e,f]=c.into(d);const g=run_list_generators(b.pop()(),b);for(const h of g)a.guard.apply(this,h)&&(e=f(e,new o.Tuple(Symbol.for('cont'),a.fn.apply(this,h))));return f(e,Symbol.for('done'))},_try:function _try(a,b,c,d,e){let f=null;try{f=a()}catch(a){let d=null;if(b)try{return d=b(a),d}catch(a){if(a instanceof o.Patterns.MatchError)throw a}if(c)try{return d=c(a),d}catch(a){if(a instanceof o.Patterns.MatchError)throw a}throw a}finally{e&&e()}if(d)try{return d(f)}catch(a){if(a instanceof o.Patterns.MatchError)throw new Error('No Match Found in Else');throw a}else return f},_with:function _with(...a){let b=[],c=null,d=null;'function'==typeof a[a.length-2]?[c,d]=a.splice(-2):c=a.pop();for(let c=0;c{const[c,d]=b;return a.set(c,d),a},new Map)},keys:function keys(a){return!1===i.is_map(a)?new e.Tuple(l,a):Array.from(a.keys())},values:function values$1(a){return!1===i.is_map(a)?new e.Tuple(l,a):Array.from(a.values())},is_key,put:function put(a,b,c){if(!1===i.is_map(c))return new e.Tuple(l,c);const d=new Map(c);return d.set(a,b),d},merge:function merge(a,b){return!1===i.is_map(a)?new e.Tuple(l,a):!1===i.is_map(b)?new e.Tuple(l,b):new Map([...a,...b])},update:function update(a,b,c){return!1===i.is_map(c)?new e.Tuple(l,c):!1===is_key(a,c)?new e.Tuple(m,a):new Map([...c,[a,b]])},get:function get(...a){const b=a[0],c=a[1];return!1===i.is_map(c)?new e.Tuple(l,c):is_key(b)?c.get(b):3===a.length?a[2]:new e.Tuple(m,b)},take:function take(a,b){if(!1===i.is_map(b))return new e.Tuple(l,b);if(!is_key(a))return k;const c=b.get(a),d=new Map(b);return d.delete(a),new e.Tuple(c,d)}},lists:{reverse,foreach:function foreach(a,b){return b.forEach((b)=>a(b)),Symbol.for('ok')},duplicate:function duplicate(a,b){const c=[];for(;c.length{if(d.get(c-1)a.get(c-1)?1:0})},keystore:function keystore(a,b,c,d){const e=[...c];for(let f=0;fa.toString()).join()},map:function map(a,b){return b.map((b)=>a(b))},filter:function filter(a,b){return b.filter((b)=>a(b))},filtermap:function filtermap(a,b){const c=[];for(const d of b){const b=a(d);!0===b?c.push(d):b instanceof e.Tuple&&!0===b.get(0)&&c.push(b.get(1))}return c},member:function member(a,b){for(const c of b)if(c===a)return!0;return!1},all:function all(a,b){for(const c of b)if(!1===a(c))return!1;return!0},any:function any(a,b){for(const c of b)if(!0===a(c))return!0;return!1},splitwith:function splitwith(a,b){let c=!1;const d=[],f=[];for(const e of b)!0==c?f.push(e):!0===a(e)?d.push(e):(c=!0,f.push(e));return new e.Tuple(d,f)},sort:function sort(...a){if(1===a.length){const b=[...a[0]];return b.sort()}const c=a[0],b=[...a[1]];return b.sort((d,a)=>{const b=c(d,a);return!0===b?-1:1})}},elixir_errors:{warn:function warn(a){const b=a.join('');return console.warn(`warning: ${b}`),Symbol.for('ok')}},io:{put_chars:function put_chars(b,c){let d=null;return d=Array.isArray(c)?a(...c):c,b===Symbol.for('stderr')?console.error(d):console.log(d),Symbol.for('ok')}}};return{Core:o}}(); diff --git a/src/javascript/lib/core/erlang_compat/erlang.js b/src/javascript/lib/core/erlang_compat/erlang.js index 74c34ccf..69c0a4c7 100644 --- a/src/javascript/lib/core/erlang_compat/erlang.js +++ b/src/javascript/lib/core/erlang_compat/erlang.js @@ -355,6 +355,10 @@ function io_size(ioListOrBinary) { return iolist_to_binary(ioListOrBinary).length; } +function integer_to_binary(integer, base = 10) { + return integer.toString(base); +} + export default { atom_to_binary, binary_to_atom, @@ -423,5 +427,6 @@ export default { binary_to_integer, process_info, iolist_to_binary, - io_size + io_size, + integer_to_binary }; From fae3337f44787c08c8e9fe3f6bf3084c3a749c67 Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Fri, 21 Jul 2017 21:36:23 -0500 Subject: [PATCH 633/860] Translate erlang binary and unary operators to javascript one --- lib/elixir_script/passes/translate/form.ex | 80 +++++++++++++++++++ .../passes/translate/forms/remote.ex | 70 ---------------- priv/build/iife/ElixirScript.Core.js | 2 +- .../lib/core/erlang_compat/erlang.js | 73 ----------------- 4 files changed, 81 insertions(+), 144 deletions(-) diff --git a/lib/elixir_script/passes/translate/form.ex b/lib/elixir_script/passes/translate/form.ex index f8d6eeaa..1ba9b7ff 100644 --- a/lib/elixir_script/passes/translate/form.ex +++ b/lib/elixir_script/passes/translate/form.ex @@ -211,6 +211,86 @@ defmodule ElixirScript.Translate.Form do ElixirScript.Translate.Function.compile(ast, state) end + def compile({{:., _, [:erlang, op]}, _, [item]}, state) when op in [:+, :-] do + ast = J.unary_expression( + op, + true, + compile!(item, state) + ) + + {ast, state} + end + + def compile({{:., _, [:erlang, op]}, _, [left, right]}, state) when op in [:+, :-, :*, :/, :==, :>, :<, :>=] do + ast = J.binary_expression( + op, + compile!(left, state), + compile!(right, state) + ) + + {ast, state} + end + + def compile({{:., _, [:erlang, :"=<"]}, _, [left, right]}, state) do + ast = J.binary_expression( + :<=, + compile!(left, state), + compile!(right, state) + ) + + {ast, state} + end + + def compile({{:., _, [:erlang, :"=:="]}, _, [left, right]}, state) do + ast = J.binary_expression( + :===, + compile!(left, state), + compile!(right, state) + ) + + {ast, state} + end + + def compile({{:., _, [:erlang, :"=/="]}, _, [left, right]}, state) do + ast = J.binary_expression( + :!==, + compile!(left, state), + compile!(right, state) + ) + + {ast, state} + end + + def compile({{:., _, [:erlang, :"/="]}, _, [left, right]}, state) do + ast = J.binary_expression( + :!=, + compile!(left, state), + compile!(right, state) + ) + + {ast, state} + end + + def compile({{:., _, [:erlang, op]}, _, [left, right]}, state) when op in [:andalso, :and] do + ast = J.binary_expression( + :&&, + compile!(left, state), + compile!(right, state) + ) + + {ast, state} + end + + def compile({{:., _, [:erlang, op]}, _, [left, right]}, state) when op in [:orelse, :or] do + ast = J.binary_expression( + :||, + compile!(left, state), + compile!(right, state) + ) + + {ast, state} + end + def compile({{:., _, [{_, _, nil} = var, func_or_prop]}, _, []}, state) do ast = J.call_expression( ElixirScript.Translate.Forms.JS.call_property(), diff --git a/lib/elixir_script/passes/translate/forms/remote.ex b/lib/elixir_script/passes/translate/forms/remote.ex index 38c2acc1..fe8590ad 100644 --- a/lib/elixir_script/passes/translate/forms/remote.ex +++ b/lib/elixir_script/passes/translate/forms/remote.ex @@ -27,76 +27,6 @@ defmodule ElixirScript.Translate.Forms.Remote do erlang functions into JavaScript functions. """ - def compile({:., _, [:erlang, :+]}, state) do - ast = erlang_compat_function("erlang", "plus") - { ast, state } - end - - def compile({:., _, [:erlang, :-]}, state) do - ast = erlang_compat_function("erlang", "minus") - { ast, state } - end - - def compile({:., _, [:erlang, :*]}, state) do - ast = erlang_compat_function("erlang", "multiply") - { ast, state } - end - - def compile({:., _, [:erlang, :/]}, state) do - ast = erlang_compat_function("erlang", "div") - { ast, state } - end - - def compile({:., _, [:erlang, :==]}, state) do - ast = erlang_compat_function("erlang", "equal") - { ast, state } - end - - def compile({:., _, [:erlang, :>]}, state) do - ast = erlang_compat_function("erlang", "greaterThan") - { ast, state } - end - - def compile({:., _, [:erlang, :>=]}, state) do - ast = erlang_compat_function("erlang", "greaterThanOrEqualTo") - { ast, state } - end - - def compile({:., _, [:erlang, :"/="]}, state) do - ast = erlang_compat_function("erlang", "doesNotEqual") - { ast, state } - end - - def compile({:., _, [:erlang, :"<"]}, state) do - ast = erlang_compat_function("erlang", "lessThan") - { ast, state } - end - - def compile({:., _, [:erlang, :"=<"]}, state) do - ast = erlang_compat_function("erlang", "lessThanOrEqualTo") - { ast, state } - end - - def compile({:., _, [:erlang, :"=:="]}, state) do - ast = erlang_compat_function("erlang", "strictlyEqual") - { ast, state } - end - - def compile({:., _, [:erlang, :"=/="]}, state) do - ast = erlang_compat_function("erlang", "doesNotStrictlyEqual") - { ast, state } - end - - def compile({:., _, [:erlang, function]}, state) when function in [:andalso, :and] do - ast = erlang_compat_function("erlang", "and") - { ast, state } - end - - def compile({:., _, [:erlang, function]}, state) when function in [:orelse, :or] do - ast = erlang_compat_function("erlang", "or") - { ast, state } - end - def compile({:., _, [:erlang, :++]}, state) do ast = erlang_compat_function("erlang", "list_concatenation") { ast, state } diff --git a/priv/build/iife/ElixirScript.Core.js b/priv/build/iife/ElixirScript.Core.js index 2a8420a5..31cff94d 100644 --- a/priv/build/iife/ElixirScript.Core.js +++ b/priv/build/iife/ElixirScript.Core.js @@ -2,5 +2,5 @@ var ElixirScript=function(){'use strict';/* @flow */function namedVariableResult function atom_to_binary(a,b=Symbol.for('utf8')){if(b!==Symbol.for('utf8'))throw new Error(`unsupported encoding ${b}`);return a.__MODULE__?Symbol.keyFor(a.__MODULE__):Symbol.keyFor(a)}function binary_to_atom(a,b=Symbol.for('utf8')){if(b!==Symbol.for('utf8'))throw new Error(`unsupported encoding ${b}`);return Symbol.for(a)}function is_bitstring$1(a){return a instanceof e.BitString}function is_number$1(a){return'number'==typeof a||a instanceof Number}function is_integer(a){return b(a)}function is_binary(a){return'string'==typeof a||a instanceof String}function iolist_to_binary(b){if(is_binary(b))return b;if(is_bitstring$1(b))return a(...b.value);const c=b.reduce((b,c)=>{if(is_integer(c))return b+a(c);return is_bitstring$1(c)?b+a(...c.value):b+iolist_to_binary(c)},'');return c}function is_key(a,b){return b.has(a)}// http://erlang.org/doc/man/lists.html function reverse(a){return[...a]}function flatten(a,b=[]){const c=a.reduce((a,b)=>{return Array.isArray(b)?a.concat(flatten(b)):a.concat(b)},[]);return c.concat(b)}function foldl(a,b,c){return c.reduce((b,c)=>{return a(c,b)},b)}function keyfind(a,b,c){for(const d of c)if(d.get(b-1)===a)return d;return!1}function keydelete(a,b,c){const d=[];let e=!1;for(let f=0;fBitString$1.integer(a));return new BitString$1(...d)}[Symbol.iterator](){return this.value[Symbol.iterator]()}toString(){var a,b='';for(a=0;a>'}process(a){let b=[];var c;for(c=0;cb?c.push(b):2048>b?c.push(192|b>>6,128|63&b):55296>b||57344<=b?c.push(224|b>>12,128|63&b>>6,128|63&b):(d++,b=65536+((1023&b)<<10|1023&a.charCodeAt(d)),c.push(240|b>>18,128|63&b>>12,128|63&b>>6,128|63&b));return c}static toUTF16Array(a){for(var b,c=[],d=0;d=b?(c.push(0),c.push(b)):(c.push(255&b>>8),c.push(255&b));return c}static toUTF32Array(a){for(var b,c=[],d=0;d=b?(c.push(0),c.push(0),c.push(0),c.push(b)):(c.push(0),c.push(0),c.push(255&b>>8),c.push(255&b));return c}//http://stackoverflow.com/questions/2003493/javascript-float-from-to-bits static float32ToBytes(a){var b=[],c=new ArrayBuffer(4);new Float32Array(c)[0]=a;let d=new Uint32Array(c)[0];return b.push(255&d>>24),b.push(255&d>>16),b.push(255&d>>8),b.push(255&d),b}static float64ToBytes(a){var b=[],c=new ArrayBuffer(8);new Float64Array(c)[0]=a;var d=new Uint32Array(c)[0],e=new Uint32Array(c)[1];return b.push(255&e>>24),b.push(255&e>>16),b.push(255&e>>8),b.push(255&e),b.push(255&d>>24),b.push(255&d>>16),b.push(255&d>>8),b.push(255&d),b}}var e={Tuple,PID:class PID{constructor(){++c,this.id=c}toString(){return'PID#<0.'+this.id+'.0>'}},Reference:class Reference{constructor(){++d,this.id=d,this.ref=Symbol()}toString(){return'Ref#<0.0.0.'+this.id+'>'}},BitString:BitString$1};/* @flow */const f=e.BitString,g=new Map;g.set(Variable.prototype,function resolveVariable(a){return function(b,c){return null===a.name||a.name.startsWith('_')?c.push(b):c.push(namedVariableResult(a.name,b)),!0}}),g.set(Wildcard.prototype,resolveWildcard),g.set(HeadTail.prototype,function resolveHeadTail(){return function(a,b){if(!is_array(a)||2>a.length)return!1;const c=a[0],d=a.slice(1);return b.push(c),b.push(d),!0}}),g.set(StartsWith.prototype,function resolveStartsWith(a){const b=a.prefix;return function(a,c){return is_string(a)&&a.startsWith(b)&&(c.push(a.substring(b.length)),!0)}}),g.set(Capture.prototype,function resolveCapture(a){const b=buildMatch(a.value);return function(a,c){return!!b(a,c)&&(c.push(a),!0)}}),g.set(Bound.prototype,function resolveBound(a){return function(b){return typeof b==typeof a.value&&b===a.value}}),g.set(Type.prototype,function resolveType(a){return function(b,c){if(b instanceof a.type){const d=buildMatch(a.objPattern);return d(b,c)}return!1}}),g.set(BitStringMatch.prototype,function resolveBitString(a){let b=[];for(let c of a.values)if(is_variable(c.value)){let a=getSize(c.unit,c.size);fillArray(b,a)}else b=b.concat(new f(c).value);let c=a.values;return function(a,d){var e=String.fromCharCode;let g=null;if(!is_string(a)&&!(a instanceof f))return!1;g=is_string(a)?new f(f.binary(a)):a;let h=0;for(let f,j=0;jd.size)return!1;for(let a of c)if(!d.has(a)||!b.get(a)(d.get(a),e))return!1;return!0}}),g.set(Array.prototype,function resolveArray(a){const b=a.map((a)=>buildMatch(a));return function(c,d){return is_array(c)&&c.length==a.length&&c.every(function(a,e){return b[e](c[e],d)})}}),g.set(String.prototype,function resolveString(a){return function(b){return is_string(b)&&b===a}}),g.set(Boolean.prototype,function resolveBoolean(a){return function(b){return is_boolean(b)&&b===a}}),g.set(Function.prototype,function resolveFunction(a){return function(b){return is_function(b)&&b===a}}),g.set(Object.prototype,resolveObject);class MatchError extends Error{constructor(a){if(super(),'symbol'==typeof a)this.message='No match for: '+a.toString();else if(Array.isArray(a)){let b=a.map((a)=>{return null===a?'null':'undefined'==typeof a?'undefined':a.toString()});this.message='No match for: '+b}else this.message='No match for: '+a;this.stack=new Error().stack,this.name=this.constructor.name}}class Clause{constructor(a,b,c=()=>!0){this.pattern=buildMatch(a),this.arity=a.length,this.optionals=getOptionalValues(a),this.fn=b,this.guard=c}}const h=Symbol();// https://github.com/airportyh/protomorphism -class Protocol{constructor(a){function createFun(a){return function(...c){const d=c[0];let e=null;if(null===d&&this.hasImplementation(Symbol('null'))?e=this.registry.get(Symbol)[a]:b(d)&&this.hasImplementation(o.Integer)?e=this.registry.get(o.Integer)[a]:'number'==typeof d&&!b(d)&&this.hasImplementation(o.Float)?e=this.registry.get(o.Float)[a]:'string'==typeof d&&this.hasImplementation(o.BitString)?e=this.registry.get(o.BitString)[a]:d&&d.has(Symbol.for('__struct__'))&&this.hasImplementation(d)?e=this.registry.get(d.get(Symbol.for('__struct__')).__MODULE__)[a]:null!==d&&this.hasImplementation(d)?e=this.registry.get(d.constructor)[a]:this.fallback&&(e=this.fallback[a]),null!=e){const a=e.apply(this,c);return a}throw new Error(`No implementation found for ${d}`)}}for(const b in this.registry=new Map,this.fallback=null,a)this[b]=createFun(b).bind(this)}implementation(a,b){null===a?this.fallback=b:this.registry.set(a,b)}hasImplementation(a){if(a===o.Integer||a===o.Float||a===o.BitString)return this.registry.has(a);return a&&a.has(Symbol.for('__struct__'))?this.registry.has(a.get(Symbol.for('__struct__')).__MODULE__):this.registry.has(a.constructor)}}var i={atom_to_binary,binary_to_atom,binary_to_existing_atom:function binary_to_existing_atom(a,b=Symbol.for('utf8')){return binary_to_atom(a,b)},list_concatenation:function list_concatenation(a,b){return a.concat(b)},list_subtraction:function list_subtraction(a,b){const c=[...a];for(const d of b){const a=c.indexOf(d);-1b},greaterThanOrEqualTo:function greaterThanOrEqualTo(a,b){return a>=b},lessThan:function lessThan(a,b){return a>b},bxor:function bxor(a,b){return a^b},bnot:function bnot(a){return~a},is_bitstring:is_bitstring$1,is_boolean:function is_boolean$1(a){return'boolean'==typeof a||a instanceof Boolean},is_float:function is_float(a){return is_number$1(a)&&!b(a)},is_function:function is_function$1(a){return'function'==typeof a||a instanceof Function},is_integer,is_list:function is_list(a){return Array.isArray(a)},is_map:function is_map$1(a){return a instanceof Map},is_number:is_number$1,is_pid:function is_pid(a){return a instanceof e.PID},is_port:function is_port(){return!1},is_reference:function is_reference(a){return a instanceof e.Reference},is_tuple:function is_tuple(a){return a instanceof e.Tuple},is_atom:function is_atom(a){return'symbol'==typeof a||a instanceof Symbol||a.__MODULE__},is_binary,element:function element(a,b){return b.get(a-1)},setelement:function setelement(a,b,c){const d=[...b.values];return d[a-1]=c,new e.Tuple(...d)},make_tuple:function make_tuple(a,b){const c=[];for(let d=0;d>b},bxor:function bxor(a,b){return a^b},bnot:function bnot(a){return~a},is_bitstring:is_bitstring$1,is_boolean:function is_boolean$1(a){return'boolean'==typeof a||a instanceof Boolean},is_float:function is_float(a){return is_number$1(a)&&!b(a)},is_function:function is_function$1(a){return'function'==typeof a||a instanceof Function},is_integer,is_list:function is_list(a){return Array.isArray(a)},is_map:function is_map$1(a){return a instanceof Map},is_number:is_number$1,is_pid:function is_pid(a){return a instanceof e.PID},is_port:function is_port(){return!1},is_reference:function is_reference(a){return a instanceof e.Reference},is_tuple:function is_tuple(a){return a instanceof e.Tuple},is_atom:function is_atom(a){return'symbol'==typeof a||a instanceof Symbol||a.__MODULE__},is_binary,element:function element(a,b){return b.get(a-1)},setelement:function setelement(a,b,c){const d=[...b.values];return d[a-1]=c,new e.Tuple(...d)},make_tuple:function make_tuple(a,b){const c=[];for(let d=0;d!0){let d=[],e=buildMatch(a);const f=e(b,d),[g,h]=checkNamedVariables(d);if(f&&h&&c.apply(this,g))return g;throw console.error('No match for:',b),new MatchError(b)},MatchError,variable:function variable(a=null,b=Symbol.for('tailored.no_value')){return new Variable(a,b)},wildcard:function wildcard(){return new Wildcard},startsWith:function startsWith(a){return new StartsWith(a)},capture:function capture(a){return new Capture(a)},headTail:function headTail(){return new HeadTail},type:function a(a,b={}){return new Type(a,b)},bound:function bound(a){return new Bound(a)},Clause,clause:function clause(a,b,c=()=>!0){return new Clause(a,b,c)},bitStringMatch:function bitStringMatch(...a){return new BitStringMatch(...a)},match_or_default,defmatchgen,list_comprehension:function list_comprehension(a,b){const c=run_generators(b.pop()(),b);let d=[];for(let e of c)a.guard.apply(this,e)&&d.push(a.fn.apply(this,e));return d},list_generator:function list_generator(a,b){return function(){let c=[];for(let d of b){const b=match_or_default(a,d,()=>!0,h);if(b!=h){const[a]=b;c.push(a)}}return c}},bitstring_generator:function bitstring_generator(a,b){return function(){let c=[],d=b.slice(0,a.byte_size()),e=1;for(;d.byte_size==a.byte_size();){const f=match_or_default(a,d,()=>!0,h);if(f!=h){c.push(f)}d=b.slice(a.byte_size()*e,a.byte_size()*(e+1)),e++}return c}},bitstring_comprehension:function bitstring_comprehension(a,b){const c=run_generators(b.pop()(),b);let d=[];for(let e of c)a.guard.apply(this,e)&&d.push(a.fn.apply(this,e));return d=d.map((a)=>e.BitString.integer(a)),new e.BitString(...d)},defmatchGen:function defmatchGen(...a){return defmatchgen(...a)},defmatchAsync:function defmatchAsync(...a){const b=getArityMap(a);return async function(...a){if(b.has(a.length)){const c=b.get(a.length);let d=null,e=null;for(let b of c){let c=[];a=fillInOptionalValues(a,b.arity,b.optionals);const f=b.pattern(a,c),[g,h]=checkNamedVariables(c);if(f&&h&&(await b.guard.apply(this,c))){d=b.fn,e=c;break}}if(!d)throw console.error('No match for:',a),new MatchError(a);return d.apply(this,e)}throw console.error('Arity of',a.length,'not found. No match for:',a),new MatchError(a)}}},Integer:class Integer{},Float:class Float{},Functions:{call_property:function call_property(a,b){if(!b)return a instanceof Function||'function'==typeof a?a():a;if(a instanceof Map){let c=null;if(a.has(b)?c=b:a.has(Symbol.for(b))&&(c=Symbol.for(b)),null===c)throw new Error(`Property ${b} not found in ${a}`);return a.get(c)instanceof Function||'function'==typeof a.get(c)?a.get(c)():a.get(c)}let c=null;if('number'==typeof a||'symbol'==typeof a||'boolean'==typeof a||'string'==typeof a?void 0===a[b]?void 0!==a[Symbol.for(b)]&&(c=Symbol.for(b)):c=b:b in a?c=b:Symbol.for(b)in a&&(c=Symbol.for(b)),null===c)throw new Error(`Property ${b} not found in ${a}`);return a[c]instanceof Function||'function'==typeof a[c]?a[c]():a[c]},defprotocol:function defprotocol(a){return new Protocol(a)},defimpl:function defimpl(a,b,c){a.implementation(b,c)},build_namespace:function build_namespace(a,b){let c=b.split('.');const d=a;let e=a;'Elixir'===c[0]&&(c=c.slice(1));for(const d of c)'undefined'==typeof e[d]&&(e[d]={}),e=e[d];return d.__table__=a.__table__||{},d.__table__[Symbol.for(b)]=e,e},iterator_to_reducer,map_to_object},SpecialForms:{_case:function _case(a,b){return o.Patterns.defmatch(...b)(a)},cond:function cond(...a){for(const b of a)if(b[0])return b[1]();throw new Error},_for:function _for(a,b,c,d=[]){let[e,f]=c.into(d);const g=run_list_generators(b.pop()(),b);for(const h of g)a.guard.apply(this,h)&&(e=f(e,new o.Tuple(Symbol.for('cont'),a.fn.apply(this,h))));return f(e,Symbol.for('done'))},_try:function _try(a,b,c,d,e){let f=null;try{f=a()}catch(a){let d=null;if(b)try{return d=b(a),d}catch(a){if(a instanceof o.Patterns.MatchError)throw a}if(c)try{return d=c(a),d}catch(a){if(a instanceof o.Patterns.MatchError)throw a}throw a}finally{e&&e()}if(d)try{return d(f)}catch(a){if(a instanceof o.Patterns.MatchError)throw new Error('No Match Found in Else');throw a}else return f},_with:function _with(...a){let b=[],c=null,d=null;'function'==typeof a[a.length-2]?[c,d]=a.splice(-2):c=a.pop();for(let c=0;c{const[c,d]=b;return a.set(c,d),a},new Map)},keys:function keys(a){return!1===i.is_map(a)?new e.Tuple(l,a):Array.from(a.keys())},values:function values$1(a){return!1===i.is_map(a)?new e.Tuple(l,a):Array.from(a.values())},is_key,put:function put(a,b,c){if(!1===i.is_map(c))return new e.Tuple(l,c);const d=new Map(c);return d.set(a,b),d},merge:function merge(a,b){return!1===i.is_map(a)?new e.Tuple(l,a):!1===i.is_map(b)?new e.Tuple(l,b):new Map([...a,...b])},update:function update(a,b,c){return!1===i.is_map(c)?new e.Tuple(l,c):!1===is_key(a,c)?new e.Tuple(m,a):new Map([...c,[a,b]])},get:function get(...a){const b=a[0],c=a[1];return!1===i.is_map(c)?new e.Tuple(l,c):is_key(b)?c.get(b):3===a.length?a[2]:new e.Tuple(m,b)},take:function take(a,b){if(!1===i.is_map(b))return new e.Tuple(l,b);if(!is_key(a))return k;const c=b.get(a),d=new Map(b);return d.delete(a),new e.Tuple(c,d)}},lists:{reverse,foreach:function foreach(a,b){return b.forEach((b)=>a(b)),Symbol.for('ok')},duplicate:function duplicate(a,b){const c=[];for(;c.length{if(d.get(c-1)a.get(c-1)?1:0})},keystore:function keystore(a,b,c,d){const e=[...c];for(let f=0;fa.toString()).join()},map:function map(a,b){return b.map((b)=>a(b))},filter:function filter(a,b){return b.filter((b)=>a(b))},filtermap:function filtermap(a,b){const c=[];for(const d of b){const b=a(d);!0===b?c.push(d):b instanceof e.Tuple&&!0===b.get(0)&&c.push(b.get(1))}return c},member:function member(a,b){for(const c of b)if(c===a)return!0;return!1},all:function all(a,b){for(const c of b)if(!1===a(c))return!1;return!0},any:function any(a,b){for(const c of b)if(!0===a(c))return!0;return!1},splitwith:function splitwith(a,b){let c=!1;const d=[],f=[];for(const e of b)!0==c?f.push(e):!0===a(e)?d.push(e):(c=!0,f.push(e));return new e.Tuple(d,f)},sort:function sort(...a){if(1===a.length){const b=[...a[0]];return b.sort()}const c=a[0],b=[...a[1]];return b.sort((d,a)=>{const b=c(d,a);return!0===b?-1:1})}},elixir_errors:{warn:function warn(a){const b=a.join('');return console.warn(`warning: ${b}`),Symbol.for('ok')}},io:{put_chars:function put_chars(b,c){let d=null;return d=Array.isArray(c)?a(...c):c,b===Symbol.for('stderr')?console.error(d):console.log(d),Symbol.for('ok')}}};return{Core:o}}(); diff --git a/src/javascript/lib/core/erlang_compat/erlang.js b/src/javascript/lib/core/erlang_compat/erlang.js index 69c0a4c7..94eea63e 100644 --- a/src/javascript/lib/core/erlang_compat/erlang.js +++ b/src/javascript/lib/core/erlang_compat/erlang.js @@ -43,70 +43,10 @@ function list_subtraction(list1, list2) { return list; } -function plus(left, right) { - if (!right) { - return +left; - } - - return left + right; -} - -function minus(left, right) { - if (!right) { - return -left; - } - - return left - right; -} - -function multiply(left, right) { - return left * right; -} - function div(left, right) { return left / right; } -function equal(left, right) { - return left == right; -} - -function doesNotEqual(left, right) { - return left != right; -} - -function greaterThan(left, right) { - return left > right; -} - -function greaterThanOrEqualTo(left, right) { - return left >= right; -} - -function lessThan(left, right) { - return left < right; -} - -function lessThanOrEqualTo(left, right) { - return left <= right; -} - -function strictlyEqual(left, right) { - return left === right; -} - -function doesNotStrictlyEqual(left, right) { - return left !== right; -} - -function and(left, right) { - return left && right; -} - -function or(left, right) { - return left || right; -} - function not(x) { return !x; } @@ -365,20 +305,7 @@ export default { binary_to_existing_atom, list_concatenation, list_subtraction, - plus, - minus, - multiply, div, - equal, - greaterThan, - greaterThanOrEqualTo, - lessThan, - lessThanOrEqualTo, - doesNotEqual, - strictlyEqual, - doesNotStrictlyEqual, - and, - or, not, rem, band, From 4f982c02eb453a72fd806c0ca311940ec1b25ef5 Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Sat, 22 Jul 2017 09:41:13 -0500 Subject: [PATCH 634/860] Add binary.copy erlang function to compat layer Upgrade tailored version. Now ignores variables that begin with underscores. Updated pattern.ex to follow suit --- .../passes/translate/forms/pattern.ex | 10 +++++++++- .../passes/translate/forms/remote.ex | 3 ++- package.json | 4 ++-- priv/build/iife/ElixirScript.Core.js | 4 ++-- src/javascript/lib/core.js | 4 +++- src/javascript/lib/core/erlang_compat/binary.js | 7 +++++++ test/support/main.ex | 2 ++ yarn.lock | 17 +++-------------- 8 files changed, 30 insertions(+), 21 deletions(-) create mode 100644 src/javascript/lib/core/erlang_compat/binary.js diff --git a/lib/elixir_script/passes/translate/forms/pattern.ex b/lib/elixir_script/passes/translate/forms/pattern.ex index 9dc2a101..7a86da69 100644 --- a/lib/elixir_script/passes/translate/forms/pattern.ex +++ b/lib/elixir_script/passes/translate/forms/pattern.ex @@ -62,7 +62,7 @@ defmodule ElixirScript.Translate.Forms.Pattern do end defp process_pattern({:_, _, _}, _) do - { [PM.parameter()], [J.identifier(:_)] } + { [PM.parameter(J.literal("_"))], [] } end defp process_pattern({a, b}, state) do @@ -92,6 +92,14 @@ defmodule ElixirScript.Translate.Forms.Pattern do { [PM.type(tuple, pattern)], params } end + defp process_pattern([{:|, _, [head, tail]}], state) do + { head_patterns, head_params } = process_pattern(head, state) + { tail_patterns, tail_params } = process_pattern(tail, state) + params = head_params ++ tail_params + + { [PM.head_tail(hd(head_patterns), hd(tail_patterns))], params } + end + defp process_pattern(list, state) when is_list(list) do { patterns, params } = list |> Enum.map(&do_compile([&1], state)) diff --git a/lib/elixir_script/passes/translate/forms/remote.ex b/lib/elixir_script/passes/translate/forms/remote.ex index fe8590ad..59f23bc4 100644 --- a/lib/elixir_script/passes/translate/forms/remote.ex +++ b/lib/elixir_script/passes/translate/forms/remote.ex @@ -16,7 +16,8 @@ defmodule ElixirScript.Translate.Forms.Remote do :code, :elixir_utils, :file, - :io + :io, + :binary ] @doc """ diff --git a/package.json b/package.json index c243103e..d9d19d63 100644 --- a/package.json +++ b/package.json @@ -13,7 +13,7 @@ "clean": "rm -rf priv/build", "test": "nyc ava src/javascript/tests", "build:test-app": "MIX_ENV=test mix elixirscript Main -f common -o test/app/build/", - "test-app": "yarn run build:test-app && NODE_ENV=test ava 'test/app/spec/**/*.spec.js'" + "test-app": "yarn build:test-app && NODE_ENV=test ava 'test/app/spec/**/*.spec.js'" }, "repository": { "type": "git", @@ -23,7 +23,7 @@ "license": "MIT", "dependencies": { "erlang-types": "^1.0.1", - "tailored": "^2.6.1" + "tailored": "^2.6.3" }, "devDependencies": { "ava": "^0.21.0", diff --git a/priv/build/iife/ElixirScript.Core.js b/priv/build/iife/ElixirScript.Core.js index 31cff94d..5ee7a960 100644 --- a/priv/build/iife/ElixirScript.Core.js +++ b/priv/build/iife/ElixirScript.Core.js @@ -1,6 +1,6 @@ var ElixirScript=function(){'use strict';/* @flow */function namedVariableResult(a,b){return new NamedVariableResult(a,b)}/* @flow */function is_number(a){return'number'==typeof a}function is_string(a){return'string'==typeof a}function is_boolean(a){return'boolean'==typeof a}function is_symbol(a){return'symbol'==typeof a}function is_object(a){return'object'==typeof a}function is_variable(a){return a instanceof Variable}function is_null(a){return null===a}function is_array(a){return Array.isArray(a)}function is_function(a){return'[object Function]'==Object.prototype.toString.call(a)}function is_map(a){return a instanceof Map}function resolveNull(){return function(a){return is_null(a)}}function resolveWildcard(){return function(){return!0}}function resolveObject(a){let b={};const c=Object.keys(a).concat(Object.getOwnPropertySymbols(a));for(let d of c)b[d]=buildMatch(a[d]);return function(d,e){if(!is_object(d)||a.length>d.length)return!1;for(let a of c)if(!(a in d)||!b[a](d[a],e))return!1;return!0}}function getSize(a,b){return a*b/8}function arraysEqual(c,a){if(c===a)return!0;if(null==c||null==a)return!1;if(c.length!=a.length)return!1;for(var b=0;bf.integer(a));return new f(...b)}function resolveNoMatch(){return function(){return!1}}function buildMatch(a){if(null===a)return resolveNull(a);if('undefined'==typeof a)return resolveWildcard(a);const b=a.constructor.prototype,c=g.get(b);return c?c(a):'object'==typeof a?resolveObject(a):resolveNoMatch()}function defmatchgen(...a){const b=getArityMap(a);return function*(...a){let[c,d]=findMatchingFunction(a,b);return yield*c.apply(this,d)}}function findMatchingFunction(a,b){if(b.has(a.length)){const c=b.get(a.length);let d=null,e=null;for(let b of c){let c=[];a=fillInOptionalValues(a,b.arity,b.optionals);const f=b.pattern(a,c),[g,h]=checkNamedVariables(c);if(f&&h&&b.guard.apply(this,g)){d=b.fn,e=g;break}}if(!d)throw console.error('No match for:',a),new MatchError(a);return[d,e]}throw console.error('Arity of',a.length,'not found. No match for:',a),new MatchError(a)}function getArityMap(a){let b=new Map;for(const c of a){const a=getArityRange(c);for(const d of a){let a=[];b.has(d)&&(a=b.get(d)),a.push(c),b.set(d,a)}}return b}function getArityRange(a){const b=a.arity-a.optionals.length,c=a.arity;let d=[b];for(;d[d.length-1]!=c;)d.push(d[d.length-1]+1);return d}function getOptionalValues(a){let b=[];for(let c=0;c!0,d=null){let e=[],f=buildMatch(a);const g=f(b,e),[h,i]=checkNamedVariables(e);return g&&i&&c.apply(this,h)?h:d}function run_generators(a,b){if(0==b.length)return a.map((a)=>{return Array.isArray(a)?a:[a]});const c=b.pop();let d=[];for(let e of c())for(let b of a)d.push([e].concat(b));return run_generators(d,b)}function iterator_to_reducer(a,b,c){const d=a[Symbol.iterator]();let e=d.next(),f=b;for(;!1===e.done;){if(f=c(e.value,f.get(1)),f.get(0)===Symbol.for('halt'))return new o.Tuple(Symbol.for('halted'),f.get(1));if(f.get(0)===Symbol.for('suspend'))return new o.Tuple(Symbol.for('suspended'),f.get(1),(a)=>{return iterator_to_reducer(d,a,c)});e=d.next()}return new o.Tuple(Symbol.for('done'),f.get(1))}function map_to_object(a){const b={};for(const[c,d]of a.entries())b[c]=d instanceof Map?map_to_object(d):d;return b}function run_list_generators(a,b){if(0==b.length)return a.map((a)=>{return Array.isArray(a)?a:[a]});const c=b.pop(),d=[];for(const e of c())for(const b of a)d.push([e].concat(b));return run_list_generators(d,b)}// http://erlang.org/doc/man/erlang.html function atom_to_binary(a,b=Symbol.for('utf8')){if(b!==Symbol.for('utf8'))throw new Error(`unsupported encoding ${b}`);return a.__MODULE__?Symbol.keyFor(a.__MODULE__):Symbol.keyFor(a)}function binary_to_atom(a,b=Symbol.for('utf8')){if(b!==Symbol.for('utf8'))throw new Error(`unsupported encoding ${b}`);return Symbol.for(a)}function is_bitstring$1(a){return a instanceof e.BitString}function is_number$1(a){return'number'==typeof a||a instanceof Number}function is_integer(a){return b(a)}function is_binary(a){return'string'==typeof a||a instanceof String}function iolist_to_binary(b){if(is_binary(b))return b;if(is_bitstring$1(b))return a(...b.value);const c=b.reduce((b,c)=>{if(is_integer(c))return b+a(c);return is_bitstring$1(c)?b+a(...c.value):b+iolist_to_binary(c)},'');return c}function is_key(a,b){return b.has(a)}// http://erlang.org/doc/man/lists.html function reverse(a){return[...a]}function flatten(a,b=[]){const c=a.reduce((a,b)=>{return Array.isArray(b)?a.concat(flatten(b)):a.concat(b)},[]);return c.concat(b)}function foldl(a,b,c){return c.reduce((b,c)=>{return a(c,b)},b)}function keyfind(a,b,c){for(const d of c)if(d.get(b-1)===a)return d;return!1}function keydelete(a,b,c){const d=[];let e=!1;for(let f=0;fBitString$1.integer(a));return new BitString$1(...d)}[Symbol.iterator](){return this.value[Symbol.iterator]()}toString(){var a,b='';for(a=0;a>'}process(a){let b=[];var c;for(c=0;cb?c.push(b):2048>b?c.push(192|b>>6,128|63&b):55296>b||57344<=b?c.push(224|b>>12,128|63&b>>6,128|63&b):(d++,b=65536+((1023&b)<<10|1023&a.charCodeAt(d)),c.push(240|b>>18,128|63&b>>12,128|63&b>>6,128|63&b));return c}static toUTF16Array(a){for(var b,c=[],d=0;d=b?(c.push(0),c.push(b)):(c.push(255&b>>8),c.push(255&b));return c}static toUTF32Array(a){for(var b,c=[],d=0;d=b?(c.push(0),c.push(0),c.push(0),c.push(b)):(c.push(0),c.push(0),c.push(255&b>>8),c.push(255&b));return c}//http://stackoverflow.com/questions/2003493/javascript-float-from-to-bits -static float32ToBytes(a){var b=[],c=new ArrayBuffer(4);new Float32Array(c)[0]=a;let d=new Uint32Array(c)[0];return b.push(255&d>>24),b.push(255&d>>16),b.push(255&d>>8),b.push(255&d),b}static float64ToBytes(a){var b=[],c=new ArrayBuffer(8);new Float64Array(c)[0]=a;var d=new Uint32Array(c)[0],e=new Uint32Array(c)[1];return b.push(255&e>>24),b.push(255&e>>16),b.push(255&e>>8),b.push(255&e),b.push(255&d>>24),b.push(255&d>>16),b.push(255&d>>8),b.push(255&d),b}}var e={Tuple,PID:class PID{constructor(){++c,this.id=c}toString(){return'PID#<0.'+this.id+'.0>'}},Reference:class Reference{constructor(){++d,this.id=d,this.ref=Symbol()}toString(){return'Ref#<0.0.0.'+this.id+'>'}},BitString:BitString$1};/* @flow */const f=e.BitString,g=new Map;g.set(Variable.prototype,function resolveVariable(a){return function(b,c){return null===a.name||a.name.startsWith('_')?c.push(b):c.push(namedVariableResult(a.name,b)),!0}}),g.set(Wildcard.prototype,resolveWildcard),g.set(HeadTail.prototype,function resolveHeadTail(){return function(a,b){if(!is_array(a)||2>a.length)return!1;const c=a[0],d=a.slice(1);return b.push(c),b.push(d),!0}}),g.set(StartsWith.prototype,function resolveStartsWith(a){const b=a.prefix;return function(a,c){return is_string(a)&&a.startsWith(b)&&(c.push(a.substring(b.length)),!0)}}),g.set(Capture.prototype,function resolveCapture(a){const b=buildMatch(a.value);return function(a,c){return!!b(a,c)&&(c.push(a),!0)}}),g.set(Bound.prototype,function resolveBound(a){return function(b){return typeof b==typeof a.value&&b===a.value}}),g.set(Type.prototype,function resolveType(a){return function(b,c){if(b instanceof a.type){const d=buildMatch(a.objPattern);return d(b,c)}return!1}}),g.set(BitStringMatch.prototype,function resolveBitString(a){let b=[];for(let c of a.values)if(is_variable(c.value)){let a=getSize(c.unit,c.size);fillArray(b,a)}else b=b.concat(new f(c).value);let c=a.values;return function(a,d){var e=String.fromCharCode;let g=null;if(!is_string(a)&&!(a instanceof f))return!1;g=is_string(a)?new f(f.binary(a)):a;let h=0;for(let f,j=0;jd.size)return!1;for(let a of c)if(!d.has(a)||!b.get(a)(d.get(a),e))return!1;return!0}}),g.set(Array.prototype,function resolveArray(a){const b=a.map((a)=>buildMatch(a));return function(c,d){return is_array(c)&&c.length==a.length&&c.every(function(a,e){return b[e](c[e],d)})}}),g.set(String.prototype,function resolveString(a){return function(b){return is_string(b)&&b===a}}),g.set(Boolean.prototype,function resolveBoolean(a){return function(b){return is_boolean(b)&&b===a}}),g.set(Function.prototype,function resolveFunction(a){return function(b){return is_function(b)&&b===a}}),g.set(Object.prototype,resolveObject);class MatchError extends Error{constructor(a){if(super(),'symbol'==typeof a)this.message='No match for: '+a.toString();else if(Array.isArray(a)){let b=a.map((a)=>{return null===a?'null':'undefined'==typeof a?'undefined':a.toString()});this.message='No match for: '+b}else this.message='No match for: '+a;this.stack=new Error().stack,this.name=this.constructor.name}}class Clause{constructor(a,b,c=()=>!0){this.pattern=buildMatch(a),this.arity=a.length,this.optionals=getOptionalValues(a),this.fn=b,this.guard=c}}const h=Symbol();// https://github.com/airportyh/protomorphism +static float32ToBytes(a){var b=[],c=new ArrayBuffer(4);new Float32Array(c)[0]=a;let d=new Uint32Array(c)[0];return b.push(255&d>>24),b.push(255&d>>16),b.push(255&d>>8),b.push(255&d),b}static float64ToBytes(a){var b=[],c=new ArrayBuffer(8);new Float64Array(c)[0]=a;var d=new Uint32Array(c)[0],e=new Uint32Array(c)[1];return b.push(255&e>>24),b.push(255&e>>16),b.push(255&e>>8),b.push(255&e),b.push(255&d>>24),b.push(255&d>>16),b.push(255&d>>8),b.push(255&d),b}}var e={Tuple,PID:class PID{constructor(){++c,this.id=c}toString(){return'PID#<0.'+this.id+'.0>'}},Reference:class Reference{constructor(){++d,this.id=d,this.ref=Symbol()}toString(){return'Ref#<0.0.0.'+this.id+'>'}},BitString:BitString$1};/* @flow */const f=e.BitString,g=new Map;g.set(Variable.prototype,function resolveVariable(a){return function(b,c){return null===a.name?c.push(b):!a.name.startsWith('_')&&c.push(namedVariableResult(a.name,b)),!0}}),g.set(Wildcard.prototype,resolveWildcard),g.set(HeadTail.prototype,function resolveHeadTail(){return function(a,b){if(!is_array(a)||0===a.length)return!1;const c=a[0],d=a.slice(1);return b.push(c),b.push(d),!0}}),g.set(StartsWith.prototype,function resolveStartsWith(a){const b=a.prefix;return function(a,c){return is_string(a)&&a.startsWith(b)&&(c.push(a.substring(b.length)),!0)}}),g.set(Capture.prototype,function resolveCapture(a){const b=buildMatch(a.value);return function(a,c){return!!b(a,c)&&(c.push(a),!0)}}),g.set(Bound.prototype,function resolveBound(a){return function(b){return typeof b==typeof a.value&&b===a.value}}),g.set(Type.prototype,function resolveType(a){return function(b,c){if(b instanceof a.type){const d=buildMatch(a.objPattern);return d(b,c)}return!1}}),g.set(BitStringMatch.prototype,function resolveBitString(a){let b=[];for(let c of a.values)if(is_variable(c.value)){let a=getSize(c.unit,c.size);fillArray(b,a)}else b=b.concat(new f(c).value);let c=a.values;return function(a,d){var e=String.fromCharCode;let g=null;if(!is_string(a)&&!(a instanceof f))return!1;g=is_string(a)?new f(f.binary(a)):a;let h=0;for(let f,j=0;jd.size)return!1;for(let a of c)if(!d.has(a)||!b.get(a)(d.get(a),e))return!1;return!0}}),g.set(Array.prototype,function resolveArray(a){const b=a.map((a)=>buildMatch(a));return function(c,d){return is_array(c)&&c.length==a.length&&c.every(function(a,e){return b[e](c[e],d)})}}),g.set(String.prototype,function resolveString(a){return function(b){return is_string(b)&&b===a}}),g.set(Boolean.prototype,function resolveBoolean(a){return function(b){return is_boolean(b)&&b===a}}),g.set(Function.prototype,function resolveFunction(a){return function(b){return is_function(b)&&b===a}}),g.set(Object.prototype,resolveObject);class MatchError extends Error{constructor(a){if(super(),'symbol'==typeof a)this.message='No match for: '+a.toString();else if(Array.isArray(a)){let b=a.map((a)=>{return null===a?'null':'undefined'==typeof a?'undefined':a.toString()});this.message='No match for: '+b}else this.message='No match for: '+a;this.stack=new Error().stack,this.name=this.constructor.name}}class Clause{constructor(a,b,c=()=>!0){this.pattern=buildMatch(a),this.arity=a.length,this.optionals=getOptionalValues(a),this.fn=b,this.guard=c}}const h=Symbol();// https://github.com/airportyh/protomorphism class Protocol{constructor(a){function createFun(a){return function(...c){const d=c[0];let e=null;if(null===d&&this.hasImplementation(Symbol('null'))?e=this.registry.get(Symbol)[a]:b(d)&&this.hasImplementation(o.Integer)?e=this.registry.get(o.Integer)[a]:'number'==typeof d&&!b(d)&&this.hasImplementation(o.Float)?e=this.registry.get(o.Float)[a]:'string'==typeof d&&this.hasImplementation(o.BitString)?e=this.registry.get(o.BitString)[a]:d&&d.has(Symbol.for('__struct__'))&&this.hasImplementation(d)?e=this.registry.get(d.get(Symbol.for('__struct__')).__MODULE__)[a]:null!==d&&this.hasImplementation(d)?e=this.registry.get(d.constructor)[a]:this.fallback&&(e=this.fallback[a]),null!=e){const a=e.apply(this,c);return a}throw new Error(`No implementation found for ${d}`)}}for(const b in this.registry=new Map,this.fallback=null,a)this[b]=createFun(b).bind(this)}implementation(a,b){null===a?this.fallback=b:this.registry.set(a,b)}hasImplementation(a){if(a===o.Integer||a===o.Float||a===o.BitString)return this.registry.has(a);return a&&a.has(Symbol.for('__struct__'))?this.registry.has(a.get(Symbol.for('__struct__')).__MODULE__):this.registry.has(a.constructor)}}var i={atom_to_binary,binary_to_atom,binary_to_existing_atom:function binary_to_existing_atom(a,b=Symbol.for('utf8')){return binary_to_atom(a,b)},list_concatenation:function list_concatenation(a,b){return a.concat(b)},list_subtraction:function list_subtraction(a,b){const c=[...a];for(const d of b){const a=c.indexOf(d);-1>b},bxor:function bxor(a,b){return a^b},bnot:function bnot(a){return~a},is_bitstring:is_bitstring$1,is_boolean:function is_boolean$1(a){return'boolean'==typeof a||a instanceof Boolean},is_float:function is_float(a){return is_number$1(a)&&!b(a)},is_function:function is_function$1(a){return'function'==typeof a||a instanceof Function},is_integer,is_list:function is_list(a){return Array.isArray(a)},is_map:function is_map$1(a){return a instanceof Map},is_number:is_number$1,is_pid:function is_pid(a){return a instanceof e.PID},is_port:function is_port(){return!1},is_reference:function is_reference(a){return a instanceof e.Reference},is_tuple:function is_tuple(a){return a instanceof e.Tuple},is_atom:function is_atom(a){return'symbol'==typeof a||a instanceof Symbol||a.__MODULE__},is_binary,element:function element(a,b){return b.get(a-1)},setelement:function setelement(a,b,c){const d=[...b.values];return d[a-1]=c,new e.Tuple(...d)},make_tuple:function make_tuple(a,b){const c=[];for(let d=0;d!0){let d=[],e=buildMatch(a);const f=e(b,d),[g,h]=checkNamedVariables(d);if(f&&h&&c.apply(this,g))return g;throw console.error('No match for:',b),new MatchError(b)},MatchError,variable:function variable(a=null,b=Symbol.for('tailored.no_value')){return new Variable(a,b)},wildcard:function wildcard(){return new Wildcard},startsWith:function startsWith(a){return new StartsWith(a)},capture:function capture(a){return new Capture(a)},headTail:function headTail(){return new HeadTail},type:function a(a,b={}){return new Type(a,b)},bound:function bound(a){return new Bound(a)},Clause,clause:function clause(a,b,c=()=>!0){return new Clause(a,b,c)},bitStringMatch:function bitStringMatch(...a){return new BitStringMatch(...a)},match_or_default,defmatchgen,list_comprehension:function list_comprehension(a,b){const c=run_generators(b.pop()(),b);let d=[];for(let e of c)a.guard.apply(this,e)&&d.push(a.fn.apply(this,e));return d},list_generator:function list_generator(a,b){return function(){let c=[];for(let d of b){const b=match_or_default(a,d,()=>!0,h);if(b!=h){const[a]=b;c.push(a)}}return c}},bitstring_generator:function bitstring_generator(a,b){return function(){let c=[],d=b.slice(0,a.byte_size()),e=1;for(;d.byte_size==a.byte_size();){const f=match_or_default(a,d,()=>!0,h);if(f!=h){c.push(f)}d=b.slice(a.byte_size()*e,a.byte_size()*(e+1)),e++}return c}},bitstring_comprehension:function bitstring_comprehension(a,b){const c=run_generators(b.pop()(),b);let d=[];for(let e of c)a.guard.apply(this,e)&&d.push(a.fn.apply(this,e));return d=d.map((a)=>e.BitString.integer(a)),new e.BitString(...d)},defmatchGen:function defmatchGen(...a){return defmatchgen(...a)},defmatchAsync:function defmatchAsync(...a){const b=getArityMap(a);return async function(...a){if(b.has(a.length)){const c=b.get(a.length);let d=null,e=null;for(let b of c){let c=[];a=fillInOptionalValues(a,b.arity,b.optionals);const f=b.pattern(a,c),[g,h]=checkNamedVariables(c);if(f&&h&&(await b.guard.apply(this,c))){d=b.fn,e=c;break}}if(!d)throw console.error('No match for:',a),new MatchError(a);return d.apply(this,e)}throw console.error('Arity of',a.length,'not found. No match for:',a),new MatchError(a)}}},Integer:class Integer{},Float:class Float{},Functions:{call_property:function call_property(a,b){if(!b)return a instanceof Function||'function'==typeof a?a():a;if(a instanceof Map){let c=null;if(a.has(b)?c=b:a.has(Symbol.for(b))&&(c=Symbol.for(b)),null===c)throw new Error(`Property ${b} not found in ${a}`);return a.get(c)instanceof Function||'function'==typeof a.get(c)?a.get(c)():a.get(c)}let c=null;if('number'==typeof a||'symbol'==typeof a||'boolean'==typeof a||'string'==typeof a?void 0===a[b]?void 0!==a[Symbol.for(b)]&&(c=Symbol.for(b)):c=b:b in a?c=b:Symbol.for(b)in a&&(c=Symbol.for(b)),null===c)throw new Error(`Property ${b} not found in ${a}`);return a[c]instanceof Function||'function'==typeof a[c]?a[c]():a[c]},defprotocol:function defprotocol(a){return new Protocol(a)},defimpl:function defimpl(a,b,c){a.implementation(b,c)},build_namespace:function build_namespace(a,b){let c=b.split('.');const d=a;let e=a;'Elixir'===c[0]&&(c=c.slice(1));for(const d of c)'undefined'==typeof e[d]&&(e[d]={}),e=e[d];return d.__table__=a.__table__||{},d.__table__[Symbol.for(b)]=e,e},iterator_to_reducer,map_to_object},SpecialForms:{_case:function _case(a,b){return o.Patterns.defmatch(...b)(a)},cond:function cond(...a){for(const b of a)if(b[0])return b[1]();throw new Error},_for:function _for(a,b,c,d=[]){let[e,f]=c.into(d);const g=run_list_generators(b.pop()(),b);for(const h of g)a.guard.apply(this,h)&&(e=f(e,new o.Tuple(Symbol.for('cont'),a.fn.apply(this,h))));return f(e,Symbol.for('done'))},_try:function _try(a,b,c,d,e){let f=null;try{f=a()}catch(a){let d=null;if(b)try{return d=b(a),d}catch(a){if(a instanceof o.Patterns.MatchError)throw a}if(c)try{return d=c(a),d}catch(a){if(a instanceof o.Patterns.MatchError)throw a}throw a}finally{e&&e()}if(d)try{return d(f)}catch(a){if(a instanceof o.Patterns.MatchError)throw new Error('No Match Found in Else');throw a}else return f},_with:function _with(...a){let b=[],c=null,d=null;'function'==typeof a[a.length-2]?[c,d]=a.splice(-2):c=a.pop();for(let c=0;c{const[c,d]=b;return a.set(c,d),a},new Map)},keys:function keys(a){return!1===i.is_map(a)?new e.Tuple(l,a):Array.from(a.keys())},values:function values$1(a){return!1===i.is_map(a)?new e.Tuple(l,a):Array.from(a.values())},is_key,put:function put(a,b,c){if(!1===i.is_map(c))return new e.Tuple(l,c);const d=new Map(c);return d.set(a,b),d},merge:function merge(a,b){return!1===i.is_map(a)?new e.Tuple(l,a):!1===i.is_map(b)?new e.Tuple(l,b):new Map([...a,...b])},update:function update(a,b,c){return!1===i.is_map(c)?new e.Tuple(l,c):!1===is_key(a,c)?new e.Tuple(m,a):new Map([...c,[a,b]])},get:function get(...a){const b=a[0],c=a[1];return!1===i.is_map(c)?new e.Tuple(l,c):is_key(b)?c.get(b):3===a.length?a[2]:new e.Tuple(m,b)},take:function take(a,b){if(!1===i.is_map(b))return new e.Tuple(l,b);if(!is_key(a))return k;const c=b.get(a),d=new Map(b);return d.delete(a),new e.Tuple(c,d)}},lists:{reverse,foreach:function foreach(a,b){return b.forEach((b)=>a(b)),Symbol.for('ok')},duplicate:function duplicate(a,b){const c=[];for(;c.length{if(d.get(c-1)a.get(c-1)?1:0})},keystore:function keystore(a,b,c,d){const e=[...c];for(let f=0;fa.toString()).join()},map:function map(a,b){return b.map((b)=>a(b))},filter:function filter(a,b){return b.filter((b)=>a(b))},filtermap:function filtermap(a,b){const c=[];for(const d of b){const b=a(d);!0===b?c.push(d):b instanceof e.Tuple&&!0===b.get(0)&&c.push(b.get(1))}return c},member:function member(a,b){for(const c of b)if(c===a)return!0;return!1},all:function all(a,b){for(const c of b)if(!1===a(c))return!1;return!0},any:function any(a,b){for(const c of b)if(!0===a(c))return!0;return!1},splitwith:function splitwith(a,b){let c=!1;const d=[],f=[];for(const e of b)!0==c?f.push(e):!0===a(e)?d.push(e):(c=!0,f.push(e));return new e.Tuple(d,f)},sort:function sort(...a){if(1===a.length){const b=[...a[0]];return b.sort()}const c=a[0],b=[...a[1]];return b.sort((d,a)=>{const b=c(d,a);return!0===b?-1:1})}},elixir_errors:{warn:function warn(a){const b=a.join('');return console.warn(`warning: ${b}`),Symbol.for('ok')}},io:{put_chars:function put_chars(b,c){let d=null;return d=Array.isArray(c)?a(...c):c,b===Symbol.for('stderr')?console.error(d):console.log(d),Symbol.for('ok')}}};return{Core:o}}(); +const j=Symbol.for('ok'),k=Symbol.for('error'),l=Symbol.for('badmap'),m=Symbol.for('badkey');const n=function get_global(){return'undefined'==typeof self?'undefined'==typeof window?'undefined'==typeof global?(console.warn('No global state found'),null):global:window:self}();n.__elixirscript_store__=new Map,n.__elixirscript_names__=new Map;var o={Tuple:e.Tuple,PID:e.PID,BitString:e.BitString,Patterns:{defmatch:function defmatch(...a){const b=getArityMap(a);return function(...a){let[c,d]=findMatchingFunction(a,b);return c.apply(this,d)}},match:function match(a,b,c=()=>!0){let d=[],e=buildMatch(a);const f=e(b,d),[g,h]=checkNamedVariables(d);if(f&&h&&c.apply(this,g))return g;throw console.error('No match for:',b),new MatchError(b)},MatchError,variable:function variable(a=null,b=Symbol.for('tailored.no_value')){return new Variable(a,b)},wildcard:function wildcard(){return new Wildcard},startsWith:function startsWith(a){return new StartsWith(a)},capture:function capture(a){return new Capture(a)},headTail:function headTail(){return new HeadTail},type:function a(a,b={}){return new Type(a,b)},bound:function bound(a){return new Bound(a)},Clause,clause:function clause(a,b,c=()=>!0){return new Clause(a,b,c)},bitStringMatch:function bitStringMatch(...a){return new BitStringMatch(...a)},match_or_default,defmatchgen,list_comprehension:function list_comprehension(a,b){const c=run_generators(b.pop()(),b);let d=[];for(let e of c)a.guard.apply(this,e)&&d.push(a.fn.apply(this,e));return d},list_generator:function list_generator(a,b){return function(){let c=[];for(let d of b){const b=match_or_default(a,d,()=>!0,h);if(b!=h){const[a]=b;c.push(a)}}return c}},bitstring_generator:function bitstring_generator(a,b){return function(){let c=[],d=b.slice(0,a.byte_size()),e=1;for(;d.byte_size==a.byte_size();){const f=match_or_default(a,d,()=>!0,h);if(f!=h){c.push(f)}d=b.slice(a.byte_size()*e,a.byte_size()*(e+1)),e++}return c}},bitstring_comprehension:function bitstring_comprehension(a,b){const c=run_generators(b.pop()(),b);let d=[];for(let e of c)a.guard.apply(this,e)&&d.push(a.fn.apply(this,e));return d=d.map((a)=>e.BitString.integer(a)),new e.BitString(...d)},defmatchGen:function defmatchGen(...a){return defmatchgen(...a)},defmatchAsync:function defmatchAsync(...a){const b=getArityMap(a);return async function(...a){if(b.has(a.length)){const c=b.get(a.length);let d=null,e=null;for(let b of c){let c=[];a=fillInOptionalValues(a,b.arity,b.optionals);const f=b.pattern(a,c),[g,h]=checkNamedVariables(c);if(f&&h&&(await b.guard.apply(this,c))){d=b.fn,e=c;break}}if(!d)throw console.error('No match for:',a),new MatchError(a);return d.apply(this,e)}throw console.error('Arity of',a.length,'not found. No match for:',a),new MatchError(a)}}},Integer:class Integer{},Float:class Float{},Functions:{call_property:function call_property(a,b){if(!b)return a instanceof Function||'function'==typeof a?a():a;if(a instanceof Map){let c=null;if(a.has(b)?c=b:a.has(Symbol.for(b))&&(c=Symbol.for(b)),null===c)throw new Error(`Property ${b} not found in ${a}`);return a.get(c)instanceof Function||'function'==typeof a.get(c)?a.get(c)():a.get(c)}let c=null;if('number'==typeof a||'symbol'==typeof a||'boolean'==typeof a||'string'==typeof a?void 0===a[b]?void 0!==a[Symbol.for(b)]&&(c=Symbol.for(b)):c=b:b in a?c=b:Symbol.for(b)in a&&(c=Symbol.for(b)),null===c)throw new Error(`Property ${b} not found in ${a}`);return a[c]instanceof Function||'function'==typeof a[c]?a[c]():a[c]},defprotocol:function defprotocol(a){return new Protocol(a)},defimpl:function defimpl(a,b,c){a.implementation(b,c)},build_namespace:function build_namespace(a,b){let c=b.split('.');const d=a;let e=a;'Elixir'===c[0]&&(c=c.slice(1));for(const d of c)'undefined'==typeof e[d]&&(e[d]={}),e=e[d];return d.__table__=a.__table__||{},d.__table__[Symbol.for(b)]=e,e},iterator_to_reducer,map_to_object},SpecialForms:{_case:function _case(a,b){return o.Patterns.defmatch(...b)(a)},cond:function cond(...a){for(const b of a)if(b[0])return b[1]();throw new Error},_for:function _for(a,b,c,d=[]){let[e,f]=c.into(d);const g=run_list_generators(b.pop()(),b);for(const h of g)a.guard.apply(this,h)&&(e=f(e,new o.Tuple(Symbol.for('cont'),a.fn.apply(this,h))));return f(e,Symbol.for('done'))},_try:function _try(a,b,c,d,e){let f=null;try{f=a()}catch(a){let d=null;if(b)try{return d=b(a),d}catch(a){if(a instanceof o.Patterns.MatchError)throw a}if(c)try{return d=c(a),d}catch(a){if(a instanceof o.Patterns.MatchError)throw a}throw a}finally{e&&e()}if(d)try{return d(f)}catch(a){if(a instanceof o.Patterns.MatchError)throw new Error('No Match Found in Else');throw a}else return f},_with:function _with(...a){let b=[],c=null,d=null;'function'==typeof a[a.length-2]?[c,d]=a.splice(-2):c=a.pop();for(let c=0;c{const[c,d]=b;return a.set(c,d),a},new Map)},keys:function keys(a){return!1===i.is_map(a)?new e.Tuple(l,a):Array.from(a.keys())},values:function values$1(a){return!1===i.is_map(a)?new e.Tuple(l,a):Array.from(a.values())},is_key,put:function put(a,b,c){if(!1===i.is_map(c))return new e.Tuple(l,c);const d=new Map(c);return d.set(a,b),d},merge:function merge(a,b){return!1===i.is_map(a)?new e.Tuple(l,a):!1===i.is_map(b)?new e.Tuple(l,b):new Map([...a,...b])},update:function update(a,b,c){return!1===i.is_map(c)?new e.Tuple(l,c):!1===is_key(a,c)?new e.Tuple(m,a):new Map([...c,[a,b]])},get:function get(...a){const b=a[0],c=a[1];return!1===i.is_map(c)?new e.Tuple(l,c):is_key(b)?c.get(b):3===a.length?a[2]:new e.Tuple(m,b)},take:function take(a,b){if(!1===i.is_map(b))return new e.Tuple(l,b);if(!is_key(a))return k;const c=b.get(a),d=new Map(b);return d.delete(a),new e.Tuple(c,d)}},lists:{reverse,foreach:function foreach(a,b){return b.forEach((b)=>a(b)),Symbol.for('ok')},duplicate:function duplicate(a,b){const c=[];for(;c.length{if(d.get(c-1)a.get(c-1)?1:0})},keystore:function keystore(a,b,c,d){const e=[...c];for(let f=0;fa.toString()).join()},map:function map(a,b){return b.map((b)=>a(b))},filter:function filter(a,b){return b.filter((b)=>a(b))},filtermap:function filtermap(a,b){const c=[];for(const d of b){const b=a(d);!0===b?c.push(d):b instanceof e.Tuple&&!0===b.get(0)&&c.push(b.get(1))}return c},member:function member(a,b){for(const c of b)if(c===a)return!0;return!1},all:function all(a,b){for(const c of b)if(!1===a(c))return!1;return!0},any:function any(a,b){for(const c of b)if(!0===a(c))return!0;return!1},splitwith:function splitwith(a,b){let c=!1;const d=[],f=[];for(const e of b)!0==c?f.push(e):!0===a(e)?d.push(e):(c=!0,f.push(e));return new e.Tuple(d,f)},sort:function sort(...a){if(1===a.length){const b=[...a[0]];return b.sort()}const c=a[0],b=[...a[1]];return b.sort((d,a)=>{const b=c(d,a);return!0===b?-1:1})}},elixir_errors:{warn:function warn(a){const b=a.join('');return console.warn(`warning: ${b}`),Symbol.for('ok')}},io:{put_chars:function put_chars(b,c){let d=null;return d=Array.isArray(c)?a(...c):c,b===Symbol.for('stderr')?console.error(d):console.log(d),Symbol.for('ok')}},binary:{copy:function copy(a,b=1){return a.repeat(b)}}};return{Core:o}}(); diff --git a/src/javascript/lib/core.js b/src/javascript/lib/core.js index d2677323..f47e61bd 100644 --- a/src/javascript/lib/core.js +++ b/src/javascript/lib/core.js @@ -7,6 +7,7 @@ import maps from './core/erlang_compat/maps'; import lists from './core/erlang_compat/lists'; import elixir_errors from './core/erlang_compat/elixir_errors'; import io from './core/erlang_compat/io'; +import binary from './core/erlang_compat/binary'; import Store from './core/store'; class Integer {} @@ -45,5 +46,6 @@ export default { maps, lists, elixir_errors, - io + io, + binary }; diff --git a/src/javascript/lib/core/erlang_compat/binary.js b/src/javascript/lib/core/erlang_compat/binary.js new file mode 100644 index 00000000..0e0c8f96 --- /dev/null +++ b/src/javascript/lib/core/erlang_compat/binary.js @@ -0,0 +1,7 @@ +function copy(subject, n = 1) { + return subject.repeat(n); +} + +export default { + copy +}; diff --git a/test/support/main.ex b/test/support/main.ex index a18d3d90..5d94e7ac 100644 --- a/test/support/main.ex +++ b/test/support/main.ex @@ -1,5 +1,7 @@ defmodule Main do def start(:normal, [callback]) do callback.("started") + + IO.inspect 1 end end diff --git a/yarn.lock b/yarn.lock index 0c91a8ec..ebbc6518 100644 --- a/yarn.lock +++ b/yarn.lock @@ -605,10 +605,6 @@ babel-plugin-syntax-exponentiation-operator@^6.8.0: version "6.13.0" resolved "https://registry.yarnpkg.com/babel-plugin-syntax-exponentiation-operator/-/babel-plugin-syntax-exponentiation-operator-6.13.0.tgz#9ee7e8337290da95288201a6a57f4170317830de" -babel-plugin-syntax-object-rest-spread@^6.8.0: - version "6.13.0" - resolved "https://registry.yarnpkg.com/babel-plugin-syntax-object-rest-spread/-/babel-plugin-syntax-object-rest-spread-6.13.0.tgz#fd6536f2bce13836ffa3a5458c4903a597bb3bf5" - babel-plugin-syntax-trailing-function-commas@^6.20.0, babel-plugin-syntax-trailing-function-commas@^6.22.0: version "6.22.0" resolved "https://registry.yarnpkg.com/babel-plugin-syntax-trailing-function-commas/-/babel-plugin-syntax-trailing-function-commas-6.22.0.tgz#ba0360937f8d06e40180a43fe0d5616fff532cf3" @@ -813,13 +809,6 @@ babel-plugin-transform-minify-booleans@^6.8.2: version "6.8.2" resolved "https://registry.yarnpkg.com/babel-plugin-transform-minify-booleans/-/babel-plugin-transform-minify-booleans-6.8.2.tgz#8451579f706e702c1e1ab2756de5c8ea369cf07c" -babel-plugin-transform-object-rest-spread@^6.23.0: - version "6.23.0" - resolved "https://registry.yarnpkg.com/babel-plugin-transform-object-rest-spread/-/babel-plugin-transform-object-rest-spread-6.23.0.tgz#875d6bc9be761c58a2ae3feee5dc4895d8c7f921" - dependencies: - babel-plugin-syntax-object-rest-spread "^6.8.0" - babel-runtime "^6.22.0" - babel-plugin-transform-property-literals@^6.8.4: version "6.8.4" resolved "https://registry.yarnpkg.com/babel-plugin-transform-property-literals/-/babel-plugin-transform-property-literals-6.8.4.tgz#6ad311110b80a192a56efb5ddf4fe3ca6f7a61da" @@ -3689,9 +3678,9 @@ table@^4.0.1: slice-ansi "0.0.4" string-width "^2.0.0" -tailored@^2.6.1: - version "2.6.1" - resolved "https://registry.yarnpkg.com/tailored/-/tailored-2.6.1.tgz#afac1114f4622eceba11d87fcc35b42a658ded84" +tailored@^2.6.3: + version "2.6.3" + resolved "https://registry.yarnpkg.com/tailored/-/tailored-2.6.3.tgz#27d1069dd3f5b2f2009d6437efcb26c595bccfda" dependencies: erlang-types "^1.0.1" From 7f48f5a30a38ba23d4be1dd260b945741f213a21 Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Sat, 22 Jul 2017 09:43:40 -0500 Subject: [PATCH 635/860] Revert changes to main.ex --- test/support/main.ex | 2 -- 1 file changed, 2 deletions(-) diff --git a/test/support/main.ex b/test/support/main.ex index 5d94e7ac..a18d3d90 100644 --- a/test/support/main.ex +++ b/test/support/main.ex @@ -1,7 +1,5 @@ defmodule Main do def start(:normal, [callback]) do callback.("started") - - IO.inspect 1 end end From 439208eb82263132eb93113c4f5b0b251792dcbb Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Sun, 23 Jul 2017 14:16:29 -0500 Subject: [PATCH 636/860] Update erlang.iolist_to_binary to flatten given iolist Also update to io.put_chars to call iolist_to_binary before outputting data --- priv/build/iife/ElixirScript.Core.js | 12 ++++++------ src/javascript/lib/core/erlang_compat/erlang.js | 13 +++++++++++-- src/javascript/lib/core/erlang_compat/io.js | 10 +++------- 3 files changed, 20 insertions(+), 15 deletions(-) diff --git a/priv/build/iife/ElixirScript.Core.js b/priv/build/iife/ElixirScript.Core.js index 5ee7a960..850b7ab7 100644 --- a/priv/build/iife/ElixirScript.Core.js +++ b/priv/build/iife/ElixirScript.Core.js @@ -1,6 +1,6 @@ -var ElixirScript=function(){'use strict';/* @flow */function namedVariableResult(a,b){return new NamedVariableResult(a,b)}/* @flow */function is_number(a){return'number'==typeof a}function is_string(a){return'string'==typeof a}function is_boolean(a){return'boolean'==typeof a}function is_symbol(a){return'symbol'==typeof a}function is_object(a){return'object'==typeof a}function is_variable(a){return a instanceof Variable}function is_null(a){return null===a}function is_array(a){return Array.isArray(a)}function is_function(a){return'[object Function]'==Object.prototype.toString.call(a)}function is_map(a){return a instanceof Map}function resolveNull(){return function(a){return is_null(a)}}function resolveWildcard(){return function(){return!0}}function resolveObject(a){let b={};const c=Object.keys(a).concat(Object.getOwnPropertySymbols(a));for(let d of c)b[d]=buildMatch(a[d]);return function(d,e){if(!is_object(d)||a.length>d.length)return!1;for(let a of c)if(!(a in d)||!b[a](d[a],e))return!1;return!0}}function getSize(a,b){return a*b/8}function arraysEqual(c,a){if(c===a)return!0;if(null==c||null==a)return!1;if(c.length!=a.length)return!1;for(var b=0;bf.integer(a));return new f(...b)}function resolveNoMatch(){return function(){return!1}}function buildMatch(a){if(null===a)return resolveNull(a);if('undefined'==typeof a)return resolveWildcard(a);const b=a.constructor.prototype,c=g.get(b);return c?c(a):'object'==typeof a?resolveObject(a):resolveNoMatch()}function defmatchgen(...a){const b=getArityMap(a);return function*(...a){let[c,d]=findMatchingFunction(a,b);return yield*c.apply(this,d)}}function findMatchingFunction(a,b){if(b.has(a.length)){const c=b.get(a.length);let d=null,e=null;for(let b of c){let c=[];a=fillInOptionalValues(a,b.arity,b.optionals);const f=b.pattern(a,c),[g,h]=checkNamedVariables(c);if(f&&h&&b.guard.apply(this,g)){d=b.fn,e=g;break}}if(!d)throw console.error('No match for:',a),new MatchError(a);return[d,e]}throw console.error('Arity of',a.length,'not found. No match for:',a),new MatchError(a)}function getArityMap(a){let b=new Map;for(const c of a){const a=getArityRange(c);for(const d of a){let a=[];b.has(d)&&(a=b.get(d)),a.push(c),b.set(d,a)}}return b}function getArityRange(a){const b=a.arity-a.optionals.length,c=a.arity;let d=[b];for(;d[d.length-1]!=c;)d.push(d[d.length-1]+1);return d}function getOptionalValues(a){let b=[];for(let c=0;c!0,d=null){let e=[],f=buildMatch(a);const g=f(b,e),[h,i]=checkNamedVariables(e);return g&&i&&c.apply(this,h)?h:d}function run_generators(a,b){if(0==b.length)return a.map((a)=>{return Array.isArray(a)?a:[a]});const c=b.pop();let d=[];for(let e of c())for(let b of a)d.push([e].concat(b));return run_generators(d,b)}function iterator_to_reducer(a,b,c){const d=a[Symbol.iterator]();let e=d.next(),f=b;for(;!1===e.done;){if(f=c(e.value,f.get(1)),f.get(0)===Symbol.for('halt'))return new o.Tuple(Symbol.for('halted'),f.get(1));if(f.get(0)===Symbol.for('suspend'))return new o.Tuple(Symbol.for('suspended'),f.get(1),(a)=>{return iterator_to_reducer(d,a,c)});e=d.next()}return new o.Tuple(Symbol.for('done'),f.get(1))}function map_to_object(a){const b={};for(const[c,d]of a.entries())b[c]=d instanceof Map?map_to_object(d):d;return b}function run_list_generators(a,b){if(0==b.length)return a.map((a)=>{return Array.isArray(a)?a:[a]});const c=b.pop(),d=[];for(const e of c())for(const b of a)d.push([e].concat(b));return run_list_generators(d,b)}// http://erlang.org/doc/man/erlang.html -function atom_to_binary(a,b=Symbol.for('utf8')){if(b!==Symbol.for('utf8'))throw new Error(`unsupported encoding ${b}`);return a.__MODULE__?Symbol.keyFor(a.__MODULE__):Symbol.keyFor(a)}function binary_to_atom(a,b=Symbol.for('utf8')){if(b!==Symbol.for('utf8'))throw new Error(`unsupported encoding ${b}`);return Symbol.for(a)}function is_bitstring$1(a){return a instanceof e.BitString}function is_number$1(a){return'number'==typeof a||a instanceof Number}function is_integer(a){return b(a)}function is_binary(a){return'string'==typeof a||a instanceof String}function iolist_to_binary(b){if(is_binary(b))return b;if(is_bitstring$1(b))return a(...b.value);const c=b.reduce((b,c)=>{if(is_integer(c))return b+a(c);return is_bitstring$1(c)?b+a(...c.value):b+iolist_to_binary(c)},'');return c}function is_key(a,b){return b.has(a)}// http://erlang.org/doc/man/lists.html -function reverse(a){return[...a]}function flatten(a,b=[]){const c=a.reduce((a,b)=>{return Array.isArray(b)?a.concat(flatten(b)):a.concat(b)},[]);return c.concat(b)}function foldl(a,b,c){return c.reduce((b,c)=>{return a(c,b)},b)}function keyfind(a,b,c){for(const d of c)if(d.get(b-1)===a)return d;return!1}function keydelete(a,b,c){const d=[];let e=!1;for(let f=0;fBitString$1.integer(a));return new BitString$1(...d)}[Symbol.iterator](){return this.value[Symbol.iterator]()}toString(){var a,b='';for(a=0;a>'}process(a){let b=[];var c;for(c=0;cb?c.push(b):2048>b?c.push(192|b>>6,128|63&b):55296>b||57344<=b?c.push(224|b>>12,128|63&b>>6,128|63&b):(d++,b=65536+((1023&b)<<10|1023&a.charCodeAt(d)),c.push(240|b>>18,128|63&b>>12,128|63&b>>6,128|63&b));return c}static toUTF16Array(a){for(var b,c=[],d=0;d=b?(c.push(0),c.push(b)):(c.push(255&b>>8),c.push(255&b));return c}static toUTF32Array(a){for(var b,c=[],d=0;d=b?(c.push(0),c.push(0),c.push(0),c.push(b)):(c.push(0),c.push(0),c.push(255&b>>8),c.push(255&b));return c}//http://stackoverflow.com/questions/2003493/javascript-float-from-to-bits -static float32ToBytes(a){var b=[],c=new ArrayBuffer(4);new Float32Array(c)[0]=a;let d=new Uint32Array(c)[0];return b.push(255&d>>24),b.push(255&d>>16),b.push(255&d>>8),b.push(255&d),b}static float64ToBytes(a){var b=[],c=new ArrayBuffer(8);new Float64Array(c)[0]=a;var d=new Uint32Array(c)[0],e=new Uint32Array(c)[1];return b.push(255&e>>24),b.push(255&e>>16),b.push(255&e>>8),b.push(255&e),b.push(255&d>>24),b.push(255&d>>16),b.push(255&d>>8),b.push(255&d),b}}var e={Tuple,PID:class PID{constructor(){++c,this.id=c}toString(){return'PID#<0.'+this.id+'.0>'}},Reference:class Reference{constructor(){++d,this.id=d,this.ref=Symbol()}toString(){return'Ref#<0.0.0.'+this.id+'>'}},BitString:BitString$1};/* @flow */const f=e.BitString,g=new Map;g.set(Variable.prototype,function resolveVariable(a){return function(b,c){return null===a.name?c.push(b):!a.name.startsWith('_')&&c.push(namedVariableResult(a.name,b)),!0}}),g.set(Wildcard.prototype,resolveWildcard),g.set(HeadTail.prototype,function resolveHeadTail(){return function(a,b){if(!is_array(a)||0===a.length)return!1;const c=a[0],d=a.slice(1);return b.push(c),b.push(d),!0}}),g.set(StartsWith.prototype,function resolveStartsWith(a){const b=a.prefix;return function(a,c){return is_string(a)&&a.startsWith(b)&&(c.push(a.substring(b.length)),!0)}}),g.set(Capture.prototype,function resolveCapture(a){const b=buildMatch(a.value);return function(a,c){return!!b(a,c)&&(c.push(a),!0)}}),g.set(Bound.prototype,function resolveBound(a){return function(b){return typeof b==typeof a.value&&b===a.value}}),g.set(Type.prototype,function resolveType(a){return function(b,c){if(b instanceof a.type){const d=buildMatch(a.objPattern);return d(b,c)}return!1}}),g.set(BitStringMatch.prototype,function resolveBitString(a){let b=[];for(let c of a.values)if(is_variable(c.value)){let a=getSize(c.unit,c.size);fillArray(b,a)}else b=b.concat(new f(c).value);let c=a.values;return function(a,d){var e=String.fromCharCode;let g=null;if(!is_string(a)&&!(a instanceof f))return!1;g=is_string(a)?new f(f.binary(a)):a;let h=0;for(let f,j=0;jd.size)return!1;for(let a of c)if(!d.has(a)||!b.get(a)(d.get(a),e))return!1;return!0}}),g.set(Array.prototype,function resolveArray(a){const b=a.map((a)=>buildMatch(a));return function(c,d){return is_array(c)&&c.length==a.length&&c.every(function(a,e){return b[e](c[e],d)})}}),g.set(String.prototype,function resolveString(a){return function(b){return is_string(b)&&b===a}}),g.set(Boolean.prototype,function resolveBoolean(a){return function(b){return is_boolean(b)&&b===a}}),g.set(Function.prototype,function resolveFunction(a){return function(b){return is_function(b)&&b===a}}),g.set(Object.prototype,resolveObject);class MatchError extends Error{constructor(a){if(super(),'symbol'==typeof a)this.message='No match for: '+a.toString();else if(Array.isArray(a)){let b=a.map((a)=>{return null===a?'null':'undefined'==typeof a?'undefined':a.toString()});this.message='No match for: '+b}else this.message='No match for: '+a;this.stack=new Error().stack,this.name=this.constructor.name}}class Clause{constructor(a,b,c=()=>!0){this.pattern=buildMatch(a),this.arity=a.length,this.optionals=getOptionalValues(a),this.fn=b,this.guard=c}}const h=Symbol();// https://github.com/airportyh/protomorphism -class Protocol{constructor(a){function createFun(a){return function(...c){const d=c[0];let e=null;if(null===d&&this.hasImplementation(Symbol('null'))?e=this.registry.get(Symbol)[a]:b(d)&&this.hasImplementation(o.Integer)?e=this.registry.get(o.Integer)[a]:'number'==typeof d&&!b(d)&&this.hasImplementation(o.Float)?e=this.registry.get(o.Float)[a]:'string'==typeof d&&this.hasImplementation(o.BitString)?e=this.registry.get(o.BitString)[a]:d&&d.has(Symbol.for('__struct__'))&&this.hasImplementation(d)?e=this.registry.get(d.get(Symbol.for('__struct__')).__MODULE__)[a]:null!==d&&this.hasImplementation(d)?e=this.registry.get(d.constructor)[a]:this.fallback&&(e=this.fallback[a]),null!=e){const a=e.apply(this,c);return a}throw new Error(`No implementation found for ${d}`)}}for(const b in this.registry=new Map,this.fallback=null,a)this[b]=createFun(b).bind(this)}implementation(a,b){null===a?this.fallback=b:this.registry.set(a,b)}hasImplementation(a){if(a===o.Integer||a===o.Float||a===o.BitString)return this.registry.has(a);return a&&a.has(Symbol.for('__struct__'))?this.registry.has(a.get(Symbol.for('__struct__')).__MODULE__):this.registry.has(a.constructor)}}var i={atom_to_binary,binary_to_atom,binary_to_existing_atom:function binary_to_existing_atom(a,b=Symbol.for('utf8')){return binary_to_atom(a,b)},list_concatenation:function list_concatenation(a,b){return a.concat(b)},list_subtraction:function list_subtraction(a,b){const c=[...a];for(const d of b){const a=c.indexOf(d);-1>b},bxor:function bxor(a,b){return a^b},bnot:function bnot(a){return~a},is_bitstring:is_bitstring$1,is_boolean:function is_boolean$1(a){return'boolean'==typeof a||a instanceof Boolean},is_float:function is_float(a){return is_number$1(a)&&!b(a)},is_function:function is_function$1(a){return'function'==typeof a||a instanceof Function},is_integer,is_list:function is_list(a){return Array.isArray(a)},is_map:function is_map$1(a){return a instanceof Map},is_number:is_number$1,is_pid:function is_pid(a){return a instanceof e.PID},is_port:function is_port(){return!1},is_reference:function is_reference(a){return a instanceof e.Reference},is_tuple:function is_tuple(a){return a instanceof e.Tuple},is_atom:function is_atom(a){return'symbol'==typeof a||a instanceof Symbol||a.__MODULE__},is_binary,element:function element(a,b){return b.get(a-1)},setelement:function setelement(a,b,c){const d=[...b.values];return d[a-1]=c,new e.Tuple(...d)},make_tuple:function make_tuple(a,b){const c=[];for(let d=0;d!0){let d=[],e=buildMatch(a);const f=e(b,d),[g,h]=checkNamedVariables(d);if(f&&h&&c.apply(this,g))return g;throw console.error('No match for:',b),new MatchError(b)},MatchError,variable:function variable(a=null,b=Symbol.for('tailored.no_value')){return new Variable(a,b)},wildcard:function wildcard(){return new Wildcard},startsWith:function startsWith(a){return new StartsWith(a)},capture:function capture(a){return new Capture(a)},headTail:function headTail(){return new HeadTail},type:function a(a,b={}){return new Type(a,b)},bound:function bound(a){return new Bound(a)},Clause,clause:function clause(a,b,c=()=>!0){return new Clause(a,b,c)},bitStringMatch:function bitStringMatch(...a){return new BitStringMatch(...a)},match_or_default,defmatchgen,list_comprehension:function list_comprehension(a,b){const c=run_generators(b.pop()(),b);let d=[];for(let e of c)a.guard.apply(this,e)&&d.push(a.fn.apply(this,e));return d},list_generator:function list_generator(a,b){return function(){let c=[];for(let d of b){const b=match_or_default(a,d,()=>!0,h);if(b!=h){const[a]=b;c.push(a)}}return c}},bitstring_generator:function bitstring_generator(a,b){return function(){let c=[],d=b.slice(0,a.byte_size()),e=1;for(;d.byte_size==a.byte_size();){const f=match_or_default(a,d,()=>!0,h);if(f!=h){c.push(f)}d=b.slice(a.byte_size()*e,a.byte_size()*(e+1)),e++}return c}},bitstring_comprehension:function bitstring_comprehension(a,b){const c=run_generators(b.pop()(),b);let d=[];for(let e of c)a.guard.apply(this,e)&&d.push(a.fn.apply(this,e));return d=d.map((a)=>e.BitString.integer(a)),new e.BitString(...d)},defmatchGen:function defmatchGen(...a){return defmatchgen(...a)},defmatchAsync:function defmatchAsync(...a){const b=getArityMap(a);return async function(...a){if(b.has(a.length)){const c=b.get(a.length);let d=null,e=null;for(let b of c){let c=[];a=fillInOptionalValues(a,b.arity,b.optionals);const f=b.pattern(a,c),[g,h]=checkNamedVariables(c);if(f&&h&&(await b.guard.apply(this,c))){d=b.fn,e=c;break}}if(!d)throw console.error('No match for:',a),new MatchError(a);return d.apply(this,e)}throw console.error('Arity of',a.length,'not found. No match for:',a),new MatchError(a)}}},Integer:class Integer{},Float:class Float{},Functions:{call_property:function call_property(a,b){if(!b)return a instanceof Function||'function'==typeof a?a():a;if(a instanceof Map){let c=null;if(a.has(b)?c=b:a.has(Symbol.for(b))&&(c=Symbol.for(b)),null===c)throw new Error(`Property ${b} not found in ${a}`);return a.get(c)instanceof Function||'function'==typeof a.get(c)?a.get(c)():a.get(c)}let c=null;if('number'==typeof a||'symbol'==typeof a||'boolean'==typeof a||'string'==typeof a?void 0===a[b]?void 0!==a[Symbol.for(b)]&&(c=Symbol.for(b)):c=b:b in a?c=b:Symbol.for(b)in a&&(c=Symbol.for(b)),null===c)throw new Error(`Property ${b} not found in ${a}`);return a[c]instanceof Function||'function'==typeof a[c]?a[c]():a[c]},defprotocol:function defprotocol(a){return new Protocol(a)},defimpl:function defimpl(a,b,c){a.implementation(b,c)},build_namespace:function build_namespace(a,b){let c=b.split('.');const d=a;let e=a;'Elixir'===c[0]&&(c=c.slice(1));for(const d of c)'undefined'==typeof e[d]&&(e[d]={}),e=e[d];return d.__table__=a.__table__||{},d.__table__[Symbol.for(b)]=e,e},iterator_to_reducer,map_to_object},SpecialForms:{_case:function _case(a,b){return o.Patterns.defmatch(...b)(a)},cond:function cond(...a){for(const b of a)if(b[0])return b[1]();throw new Error},_for:function _for(a,b,c,d=[]){let[e,f]=c.into(d);const g=run_list_generators(b.pop()(),b);for(const h of g)a.guard.apply(this,h)&&(e=f(e,new o.Tuple(Symbol.for('cont'),a.fn.apply(this,h))));return f(e,Symbol.for('done'))},_try:function _try(a,b,c,d,e){let f=null;try{f=a()}catch(a){let d=null;if(b)try{return d=b(a),d}catch(a){if(a instanceof o.Patterns.MatchError)throw a}if(c)try{return d=c(a),d}catch(a){if(a instanceof o.Patterns.MatchError)throw a}throw a}finally{e&&e()}if(d)try{return d(f)}catch(a){if(a instanceof o.Patterns.MatchError)throw new Error('No Match Found in Else');throw a}else return f},_with:function _with(...a){let b=[],c=null,d=null;'function'==typeof a[a.length-2]?[c,d]=a.splice(-2):c=a.pop();for(let c=0;c{const[c,d]=b;return a.set(c,d),a},new Map)},keys:function keys(a){return!1===i.is_map(a)?new e.Tuple(l,a):Array.from(a.keys())},values:function values$1(a){return!1===i.is_map(a)?new e.Tuple(l,a):Array.from(a.values())},is_key,put:function put(a,b,c){if(!1===i.is_map(c))return new e.Tuple(l,c);const d=new Map(c);return d.set(a,b),d},merge:function merge(a,b){return!1===i.is_map(a)?new e.Tuple(l,a):!1===i.is_map(b)?new e.Tuple(l,b):new Map([...a,...b])},update:function update(a,b,c){return!1===i.is_map(c)?new e.Tuple(l,c):!1===is_key(a,c)?new e.Tuple(m,a):new Map([...c,[a,b]])},get:function get(...a){const b=a[0],c=a[1];return!1===i.is_map(c)?new e.Tuple(l,c):is_key(b)?c.get(b):3===a.length?a[2]:new e.Tuple(m,b)},take:function take(a,b){if(!1===i.is_map(b))return new e.Tuple(l,b);if(!is_key(a))return k;const c=b.get(a),d=new Map(b);return d.delete(a),new e.Tuple(c,d)}},lists:{reverse,foreach:function foreach(a,b){return b.forEach((b)=>a(b)),Symbol.for('ok')},duplicate:function duplicate(a,b){const c=[];for(;c.length{if(d.get(c-1)a.get(c-1)?1:0})},keystore:function keystore(a,b,c,d){const e=[...c];for(let f=0;fa.toString()).join()},map:function map(a,b){return b.map((b)=>a(b))},filter:function filter(a,b){return b.filter((b)=>a(b))},filtermap:function filtermap(a,b){const c=[];for(const d of b){const b=a(d);!0===b?c.push(d):b instanceof e.Tuple&&!0===b.get(0)&&c.push(b.get(1))}return c},member:function member(a,b){for(const c of b)if(c===a)return!0;return!1},all:function all(a,b){for(const c of b)if(!1===a(c))return!1;return!0},any:function any(a,b){for(const c of b)if(!0===a(c))return!0;return!1},splitwith:function splitwith(a,b){let c=!1;const d=[],f=[];for(const e of b)!0==c?f.push(e):!0===a(e)?d.push(e):(c=!0,f.push(e));return new e.Tuple(d,f)},sort:function sort(...a){if(1===a.length){const b=[...a[0]];return b.sort()}const c=a[0],b=[...a[1]];return b.sort((d,a)=>{const b=c(d,a);return!0===b?-1:1})}},elixir_errors:{warn:function warn(a){const b=a.join('');return console.warn(`warning: ${b}`),Symbol.for('ok')}},io:{put_chars:function put_chars(b,c){let d=null;return d=Array.isArray(c)?a(...c):c,b===Symbol.for('stderr')?console.error(d):console.log(d),Symbol.for('ok')}},binary:{copy:function copy(a,b=1){return a.repeat(b)}}};return{Core:o}}(); +var ElixirScript=function(){'use strict';/* @flow */function namedVariableResult(a,b){return new NamedVariableResult(a,b)}/* @flow */function is_number(a){return'number'==typeof a}function is_string(a){return'string'==typeof a}function is_boolean(a){return'boolean'==typeof a}function is_symbol(a){return'symbol'==typeof a}function is_object(a){return'object'==typeof a}function is_variable(a){return a instanceof Variable}function is_null(a){return null===a}function is_array(a){return Array.isArray(a)}function is_function(a){return'[object Function]'==Object.prototype.toString.call(a)}function is_map(a){return a instanceof Map}function resolveNull(){return function(a){return is_null(a)}}function resolveWildcard(){return function(){return!0}}function resolveObject(a){let b={};const c=Object.keys(a).concat(Object.getOwnPropertySymbols(a));for(let d of c)b[d]=buildMatch(a[d]);return function(d,e){if(!is_object(d)||a.length>d.length)return!1;for(let a of c)if(!(a in d)||!b[a](d[a],e))return!1;return!0}}function getSize(a,b){return a*b/8}function arraysEqual(c,a){if(c===a)return!0;if(null==c||null==a)return!1;if(c.length!=a.length)return!1;for(var b=0;be.integer(a));return new e(...b)}function resolveNoMatch(){return function(){return!1}}function buildMatch(a){if(null===a)return resolveNull(a);if('undefined'==typeof a)return resolveWildcard(a);const b=a.constructor.prototype,c=f.get(b);return c?c(a):'object'==typeof a?resolveObject(a):resolveNoMatch()}function defmatchgen(...a){const b=getArityMap(a);return function*(...a){let[c,d]=findMatchingFunction(a,b);return yield*c.apply(this,d)}}function findMatchingFunction(a,b){if(b.has(a.length)){const c=b.get(a.length);let d=null,e=null;for(let b of c){let c=[];a=fillInOptionalValues(a,b.arity,b.optionals);const f=b.pattern(a,c),[g,h]=checkNamedVariables(c);if(f&&h&&b.guard.apply(this,g)){d=b.fn,e=g;break}}if(!d)throw console.error('No match for:',a),new MatchError(a);return[d,e]}throw console.error('Arity of',a.length,'not found. No match for:',a),new MatchError(a)}function getArityMap(a){let b=new Map;for(const c of a){const a=getArityRange(c);for(const d of a){let a=[];b.has(d)&&(a=b.get(d)),a.push(c),b.set(d,a)}}return b}function getArityRange(a){const b=a.arity-a.optionals.length,c=a.arity;let d=[b];for(;d[d.length-1]!=c;)d.push(d[d.length-1]+1);return d}function getOptionalValues(a){let b=[];for(let c=0;c!0,d=null){let e=[],f=buildMatch(a);const g=f(b,e),[h,i]=checkNamedVariables(e);return g&&i&&c.apply(this,h)?h:d}function run_generators(a,b){if(0==b.length)return a.map((a)=>{return Array.isArray(a)?a:[a]});const c=b.pop();let d=[];for(let e of c())for(let b of a)d.push([e].concat(b));return run_generators(d,b)}function iterator_to_reducer(a,b,c){const d=a[Symbol.iterator]();let e=d.next(),f=b;for(;!1===e.done;){if(f=c(e.value,f.get(1)),f.get(0)===Symbol.for('halt'))return new o.Tuple(Symbol.for('halted'),f.get(1));if(f.get(0)===Symbol.for('suspend'))return new o.Tuple(Symbol.for('suspended'),f.get(1),(a)=>{return iterator_to_reducer(d,a,c)});e=d.next()}return new o.Tuple(Symbol.for('done'),f.get(1))}function map_to_object(a){const b={};for(const[c,d]of a.entries())b[c]=d instanceof Map?map_to_object(d):d;return b}function run_list_generators(a,b){if(0==b.length)return a.map((a)=>{return Array.isArray(a)?a:[a]});const c=b.pop(),d=[];for(const e of c())for(const b of a)d.push([e].concat(b));return run_list_generators(d,b)}// http://erlang.org/doc/man/lists.html +function reverse(a){return[...a]}function flatten(a,b=[]){const c=a.reduce((a,b)=>{return Array.isArray(b)?a.concat(flatten(b)):a.concat(b)},[]);return c.concat(b)}function foldl(a,b,c){return c.reduce((b,c)=>{return a(c,b)},b)}function keyfind(a,b,c){for(const d of c)if(d.get(b-1)===a)return d;return!1}function keydelete(a,b,c){const d=[];let e=!1;for(let f=0;f{if(null===c)return a;return is_integer(c)?a+b(c):is_bitstring$1(c)?a+b(...c.value):a+iolist_to_binary(c)},'');return d}function is_key(a,b){return b.has(a)}function get_key(a){let b=a;if(__elixirscript_names__.has(a)&&(b=__elixirscript_names__.get(a)),__elixirscript_store__.has(b))return b;throw new Error(`Key ${b} not found`)}var a=Number.isInteger;class Variable{constructor(a=null,b=Symbol.for('tailored.no_value')){this.name=a,this.default_value=b}}class Wildcard{constructor(){}}class StartsWith{constructor(a){this.prefix=a}}class Capture{constructor(a){this.value=a}}class HeadTail{constructor(){}}class Type{constructor(a,b={}){this.type=a,this.objPattern=b}}class Bound{constructor(a){this.value=a}}class BitStringMatch{constructor(...a){this.values=a}length(){return values.length}bit_size(){return 8*this.byte_size()}byte_size(){let a=0;for(let b of this.values)a+=b.unit*b.size/8;return a}getValue(a){return this.values(a)}getSizeOfValue(a){let b=this.getValue(a);return b.unit*b.size}getTypeOfValue(a){return this.getValue(a).type}}class NamedVariableResult{constructor(a,b){this.name=a,this.value=b}}class Tuple{constructor(...a){this.values=Object.freeze(a),this.length=this.values.length}get(a){return this.values[a]}count(){return this.values.length}[Symbol.iterator](){return this.values[Symbol.iterator]()}toString(){let a,b='';for(a=0;aBitString$1.integer(a));return new BitString$1(...d)}[Symbol.iterator](){return this.value[Symbol.iterator]()}toString(){var a,b='';for(a=0;a>'}process(a){let b=[];var c;for(c=0;cb?c.push(b):2048>b?c.push(192|b>>6,128|63&b):55296>b||57344<=b?c.push(224|b>>12,128|63&b>>6,128|63&b):(d++,b=65536+((1023&b)<<10|1023&a.charCodeAt(d)),c.push(240|b>>18,128|63&b>>12,128|63&b>>6,128|63&b));return c}static toUTF16Array(a){for(var b,c=[],d=0;d=b?(c.push(0),c.push(b)):(c.push(255&b>>8),c.push(255&b));return c}static toUTF32Array(a){for(var b,c=[],d=0;d=b?(c.push(0),c.push(0),c.push(0),c.push(b)):(c.push(0),c.push(0),c.push(255&b>>8),c.push(255&b));return c}//http://stackoverflow.com/questions/2003493/javascript-float-from-to-bits +static float32ToBytes(a){var b=[],c=new ArrayBuffer(4);new Float32Array(c)[0]=a;let d=new Uint32Array(c)[0];return b.push(255&d>>24),b.push(255&d>>16),b.push(255&d>>8),b.push(255&d),b}static float64ToBytes(a){var b=[],c=new ArrayBuffer(8);new Float64Array(c)[0]=a;var d=new Uint32Array(c)[0],e=new Uint32Array(c)[1];return b.push(255&e>>24),b.push(255&e>>16),b.push(255&e>>8),b.push(255&e),b.push(255&d>>24),b.push(255&d>>16),b.push(255&d>>8),b.push(255&d),b}}var d={Tuple,PID:class PID{constructor(){++b,this.id=b}toString(){return'PID#<0.'+this.id+'.0>'}},Reference:class Reference{constructor(){++c,this.id=c,this.ref=Symbol()}toString(){return'Ref#<0.0.0.'+this.id+'>'}},BitString:BitString$1};/* @flow */const e=d.BitString,f=new Map;f.set(Variable.prototype,function resolveVariable(a){return function(b,c){return null===a.name?c.push(b):!a.name.startsWith('_')&&c.push(namedVariableResult(a.name,b)),!0}}),f.set(Wildcard.prototype,resolveWildcard),f.set(HeadTail.prototype,function resolveHeadTail(){return function(a,b){if(!is_array(a)||0===a.length)return!1;const c=a[0],d=a.slice(1);return b.push(c),b.push(d),!0}}),f.set(StartsWith.prototype,function resolveStartsWith(a){const b=a.prefix;return function(a,c){return is_string(a)&&a.startsWith(b)&&(c.push(a.substring(b.length)),!0)}}),f.set(Capture.prototype,function resolveCapture(a){const b=buildMatch(a.value);return function(a,c){return!!b(a,c)&&(c.push(a),!0)}}),f.set(Bound.prototype,function resolveBound(a){return function(b){return typeof b==typeof a.value&&b===a.value}}),f.set(Type.prototype,function resolveType(a){return function(b,c){if(b instanceof a.type){const d=buildMatch(a.objPattern);return d(b,c)}return!1}}),f.set(BitStringMatch.prototype,function resolveBitString(a){let b=[];for(let c of a.values)if(is_variable(c.value)){let a=getSize(c.unit,c.size);fillArray(b,a)}else b=b.concat(new e(c).value);let c=a.values;return function(a,d){var f=String.fromCharCode;let g=null;if(!is_string(a)&&!(a instanceof e))return!1;g=is_string(a)?new e(e.binary(a)):a;let h=0;for(let e,j=0;jd.size)return!1;for(let a of c)if(!d.has(a)||!b.get(a)(d.get(a),e))return!1;return!0}}),f.set(Array.prototype,function resolveArray(a){const b=a.map((a)=>buildMatch(a));return function(c,d){return is_array(c)&&c.length==a.length&&c.every(function(a,e){return b[e](c[e],d)})}}),f.set(String.prototype,function resolveString(a){return function(b){return is_string(b)&&b===a}}),f.set(Boolean.prototype,function resolveBoolean(a){return function(b){return is_boolean(b)&&b===a}}),f.set(Function.prototype,function resolveFunction(a){return function(b){return is_function(b)&&b===a}}),f.set(Object.prototype,resolveObject);class MatchError extends Error{constructor(a){if(super(),'symbol'==typeof a)this.message='No match for: '+a.toString();else if(Array.isArray(a)){let b=a.map((a)=>{return null===a?'null':'undefined'==typeof a?'undefined':a.toString()});this.message='No match for: '+b}else this.message='No match for: '+a;this.stack=new Error().stack,this.name=this.constructor.name}}class Clause{constructor(a,b,c=()=>!0){this.pattern=buildMatch(a),this.arity=a.length,this.optionals=getOptionalValues(a),this.fn=b,this.guard=c}}const g=Symbol();// https://github.com/airportyh/protomorphism +class Protocol{constructor(b){function createFun(b){return function(...c){const d=c[0];let e=null;if(null===d&&this.hasImplementation(Symbol('null'))?e=this.registry.get(Symbol)[b]:a(d)&&this.hasImplementation(o.Integer)?e=this.registry.get(o.Integer)[b]:'number'==typeof d&&!a(d)&&this.hasImplementation(o.Float)?e=this.registry.get(o.Float)[b]:'string'==typeof d&&this.hasImplementation(o.BitString)?e=this.registry.get(o.BitString)[b]:d&&d.has(Symbol.for('__struct__'))&&this.hasImplementation(d)?e=this.registry.get(d.get(Symbol.for('__struct__')).__MODULE__)[b]:null!==d&&this.hasImplementation(d)?e=this.registry.get(d.constructor)[b]:this.fallback&&(e=this.fallback[b]),null!=e){const a=e.apply(this,c);return a}throw new Error(`No implementation found for ${d}`)}}for(const a in this.registry=new Map,this.fallback=null,b)this[a]=createFun(a).bind(this)}implementation(a,b){null===a?this.fallback=b:this.registry.set(a,b)}hasImplementation(a){if(a===o.Integer||a===o.Float||a===o.BitString)return this.registry.has(a);return a&&a.has(Symbol.for('__struct__'))?this.registry.has(a.get(Symbol.for('__struct__')).__MODULE__):this.registry.has(a.constructor)}}var h={reverse,foreach:function foreach(a,b){return b.forEach((b)=>a(b)),Symbol.for('ok')},duplicate:function duplicate(a,b){const c=[];for(;c.length{if(d.get(c-1)a.get(c-1)?1:0})},keystore:function keystore(a,b,c,d){const e=[...c];for(let f=0;fa.toString()).join()},map:function map(a,b){return b.map((b)=>a(b))},filter:function filter(a,b){return b.filter((b)=>a(b))},filtermap:function filtermap(a,b){const c=[];for(const e of b){const b=a(e);!0===b?c.push(e):b instanceof d.Tuple&&!0===b.get(0)&&c.push(b.get(1))}return c},member:function member(a,b){for(const c of b)if(c===a)return!0;return!1},all:function all(a,b){for(const c of b)if(!1===a(c))return!1;return!0},any:function any(a,b){for(const c of b)if(!0===a(c))return!0;return!1},splitwith:function splitwith(a,b){let c=!1;const e=[],f=[];for(const d of b)!0==c?f.push(d):!0===a(d)?e.push(d):(c=!0,f.push(d));return new d.Tuple(e,f)},sort:function sort(...a){if(1===a.length){const b=[...a[0]];return b.sort()}const c=a[0],b=[...a[1]];return b.sort((d,a)=>{const b=c(d,a);return!0===b?-1:1})}},i={atom_to_binary,binary_to_atom,binary_to_existing_atom:function binary_to_existing_atom(a,b=Symbol.for('utf8')){return binary_to_atom(a,b)},list_concatenation:function list_concatenation(a,b){return a.concat(b)},list_subtraction:function list_subtraction(a,b){const c=[...a];for(const d of b){const a=c.indexOf(d);-1>b},bxor:function bxor(a,b){return a^b},bnot:function bnot(a){return~a},is_bitstring:is_bitstring$1,is_boolean:function is_boolean$1(a){return'boolean'==typeof a||a instanceof Boolean},is_float:function is_float(b){return is_number$1(b)&&!a(b)},is_function:function is_function$1(a){return'function'==typeof a||a instanceof Function},is_integer,is_list:function is_list(a){return Array.isArray(a)},is_map:function is_map$1(a){return a instanceof Map},is_number:is_number$1,is_pid:function is_pid(a){return a instanceof d.PID},is_port:function is_port(){return!1},is_reference:function is_reference(a){return a instanceof d.Reference},is_tuple:function is_tuple(a){return a instanceof d.Tuple},is_atom:function is_atom(a){return'symbol'==typeof a||a instanceof Symbol||a.__MODULE__},is_binary,element:function element(a,b){return b.get(a-1)},setelement:function setelement(a,b,c){const e=[...b.values];return e[a-1]=c,new d.Tuple(...e)},make_tuple:function make_tuple(a,b){const c=[];for(let d=0;d!0){let d=[],e=buildMatch(a);const f=e(b,d),[g,h]=checkNamedVariables(d);if(f&&h&&c.apply(this,g))return g;throw console.error('No match for:',b),new MatchError(b)},MatchError,variable:function variable(a=null,b=Symbol.for('tailored.no_value')){return new Variable(a,b)},wildcard:function wildcard(){return new Wildcard},startsWith:function startsWith(a){return new StartsWith(a)},capture:function capture(a){return new Capture(a)},headTail:function headTail(){return new HeadTail},type:function a(a,b={}){return new Type(a,b)},bound:function bound(a){return new Bound(a)},Clause,clause:function clause(a,b,c=()=>!0){return new Clause(a,b,c)},bitStringMatch:function bitStringMatch(...a){return new BitStringMatch(...a)},match_or_default,defmatchgen,list_comprehension:function list_comprehension(a,b){const c=run_generators(b.pop()(),b);let d=[];for(let e of c)a.guard.apply(this,e)&&d.push(a.fn.apply(this,e));return d},list_generator:function list_generator(a,b){return function(){let c=[];for(let d of b){const b=match_or_default(a,d,()=>!0,g);if(b!=g){const[a]=b;c.push(a)}}return c}},bitstring_generator:function bitstring_generator(a,b){return function(){let c=[],d=b.slice(0,a.byte_size()),e=1;for(;d.byte_size==a.byte_size();){const f=match_or_default(a,d,()=>!0,g);if(f!=g){c.push(f)}d=b.slice(a.byte_size()*e,a.byte_size()*(e+1)),e++}return c}},bitstring_comprehension:function bitstring_comprehension(a,b){const c=run_generators(b.pop()(),b);let e=[];for(let d of c)a.guard.apply(this,d)&&e.push(a.fn.apply(this,d));return e=e.map((a)=>d.BitString.integer(a)),new d.BitString(...e)},defmatchGen:function defmatchGen(...a){return defmatchgen(...a)},defmatchAsync:function defmatchAsync(...a){const b=getArityMap(a);return async function(...a){if(b.has(a.length)){const c=b.get(a.length);let d=null,e=null;for(let b of c){let c=[];a=fillInOptionalValues(a,b.arity,b.optionals);const f=b.pattern(a,c),[g,h]=checkNamedVariables(c);if(f&&h&&(await b.guard.apply(this,c))){d=b.fn,e=c;break}}if(!d)throw console.error('No match for:',a),new MatchError(a);return d.apply(this,e)}throw console.error('Arity of',a.length,'not found. No match for:',a),new MatchError(a)}}},Integer:class Integer{},Float:class Float{},Functions:{call_property:function call_property(a,b){if(!b)return a instanceof Function||'function'==typeof a?a():a;if(a instanceof Map){let c=null;if(a.has(b)?c=b:a.has(Symbol.for(b))&&(c=Symbol.for(b)),null===c)throw new Error(`Property ${b} not found in ${a}`);return a.get(c)instanceof Function||'function'==typeof a.get(c)?a.get(c)():a.get(c)}let c=null;if('number'==typeof a||'symbol'==typeof a||'boolean'==typeof a||'string'==typeof a?void 0===a[b]?void 0!==a[Symbol.for(b)]&&(c=Symbol.for(b)):c=b:b in a?c=b:Symbol.for(b)in a&&(c=Symbol.for(b)),null===c)throw new Error(`Property ${b} not found in ${a}`);return a[c]instanceof Function||'function'==typeof a[c]?a[c]():a[c]},defprotocol:function defprotocol(a){return new Protocol(a)},defimpl:function defimpl(a,b,c){a.implementation(b,c)},build_namespace:function build_namespace(a,b){let c=b.split('.');const d=a;let e=a;'Elixir'===c[0]&&(c=c.slice(1));for(const d of c)'undefined'==typeof e[d]&&(e[d]={}),e=e[d];return d.__table__=a.__table__||{},d.__table__[Symbol.for(b)]=e,e},iterator_to_reducer,map_to_object},SpecialForms:{_case:function _case(a,b){return o.Patterns.defmatch(...b)(a)},cond:function cond(...a){for(const b of a)if(b[0])return b[1]();throw new Error},_for:function _for(a,b,c,d=[]){let[e,f]=c.into(d);const g=run_list_generators(b.pop()(),b);for(const h of g)a.guard.apply(this,h)&&(e=f(e,new o.Tuple(Symbol.for('cont'),a.fn.apply(this,h))));return f(e,Symbol.for('done'))},_try:function _try(a,b,c,d,e){let f=null;try{f=a()}catch(a){let d=null;if(b)try{return d=b(a),d}catch(a){if(a instanceof o.Patterns.MatchError)throw a}if(c)try{return d=c(a),d}catch(a){if(a instanceof o.Patterns.MatchError)throw a}throw a}finally{e&&e()}if(d)try{return d(f)}catch(a){if(a instanceof o.Patterns.MatchError)throw new Error('No Match Found in Else');throw a}else return f},_with:function _with(...a){let b=[],c=null,d=null;'function'==typeof a[a.length-2]?[c,d]=a.splice(-2):c=a.pop();for(let c=0;c{const[c,d]=b;return a.set(c,d),a},new Map)},keys:function keys(a){return!1===i.is_map(a)?new d.Tuple(l,a):Array.from(a.keys())},values:function values$1(a){return!1===i.is_map(a)?new d.Tuple(l,a):Array.from(a.values())},is_key,put:function put(a,b,c){if(!1===i.is_map(c))return new d.Tuple(l,c);const e=new Map(c);return e.set(a,b),e},merge:function merge(a,b){return!1===i.is_map(a)?new d.Tuple(l,a):!1===i.is_map(b)?new d.Tuple(l,b):new Map([...a,...b])},update:function update(a,b,c){return!1===i.is_map(c)?new d.Tuple(l,c):!1===is_key(a,c)?new d.Tuple(m,a):new Map([...c,[a,b]])},get:function get(...a){const b=a[0],c=a[1];return!1===i.is_map(c)?new d.Tuple(l,c):is_key(b)?c.get(b):3===a.length?a[2]:new d.Tuple(m,b)},take:function take(a,b){if(!1===i.is_map(b))return new d.Tuple(l,b);if(!is_key(a))return k;const c=b.get(a),e=new Map(b);return e.delete(a),new d.Tuple(c,e)}},lists:h,elixir_errors:{warn:function warn(a){const b=a.join('');return console.warn(`warning: ${b}`),Symbol.for('ok')}},io:{put_chars:function put_chars(a,b){let c=i.iolist_to_binary(b);return a===Symbol.for('stderr')?console.error(c):console.log(c),Symbol.for('ok')}},binary:{copy:function copy(a,b=1){return a.repeat(b)}}};return{Core:o}}(); diff --git a/src/javascript/lib/core/erlang_compat/erlang.js b/src/javascript/lib/core/erlang_compat/erlang.js index 94eea63e..683ba0f6 100644 --- a/src/javascript/lib/core/erlang_compat/erlang.js +++ b/src/javascript/lib/core/erlang_compat/erlang.js @@ -1,5 +1,6 @@ // http://erlang.org/doc/man/erlang.html import ErlangTypes from 'erlang-types'; +import lists from './lists'; function atom_to_binary(atom, encoding = Symbol.for('utf8')) { if (encoding !== Symbol.for('utf8')) { @@ -270,6 +271,10 @@ function process_info(pid, item) { } function iolist_to_binary(ioListOrBinary) { + if (ioListOrBinary === null) { + return ''; + } + if (is_binary(ioListOrBinary)) { return ioListOrBinary; } @@ -278,8 +283,12 @@ function iolist_to_binary(ioListOrBinary) { return String.fromCodePoint(...ioListOrBinary.value); } - const value = ioListOrBinary.reduce((acc, current) => { - if (is_integer(current)) { + const iolistFlattened = lists.flatten(ioListOrBinary); + + const value = iolistFlattened.reduce((acc, current) => { + if (current === null) { + return acc; + } else if (is_integer(current)) { return acc + String.fromCodePoint(current); } else if (is_bitstring(current)) { return acc + String.fromCodePoint(...current.value); diff --git a/src/javascript/lib/core/erlang_compat/io.js b/src/javascript/lib/core/erlang_compat/io.js index 9d7eccb3..d01c42c6 100644 --- a/src/javascript/lib/core/erlang_compat/io.js +++ b/src/javascript/lib/core/erlang_compat/io.js @@ -1,11 +1,7 @@ -function put_chars(ioDevice, charData) { - let dataToWrite = null; +import erlang from './erlang'; - if (Array.isArray(charData)) { - dataToWrite = String.fromCodePoint(...charData); - } else { - dataToWrite = charData; - } +function put_chars(ioDevice, charData) { + let dataToWrite = erlang.iolist_to_binary(charData); if (ioDevice === Symbol.for('stderr')) { console.error(dataToWrite); From 3938cc9b0d41e698d1ea395635bf98b53fa49131 Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Thu, 27 Jul 2017 20:45:25 -0500 Subject: [PATCH 637/860] Update list concat translation to not wrap extra list --- lib/elixir_script/passes/translate/form.ex | 12 + package.json | 2 +- priv/build/iife/ElixirScript.Core.js | 2565 ++++++++++++++++++- src/javascript/lib/core/erlang_compat/io.js | 2 +- src/javascript/lib/core/protocol.js | 7 +- yarn.lock | 6 +- 6 files changed, 2582 insertions(+), 12 deletions(-) diff --git a/lib/elixir_script/passes/translate/form.ex b/lib/elixir_script/passes/translate/form.ex index 1ba9b7ff..a447a9b2 100644 --- a/lib/elixir_script/passes/translate/form.ex +++ b/lib/elixir_script/passes/translate/form.ex @@ -22,6 +22,18 @@ defmodule ElixirScript.Translate.Form do { J.literal(form), state } end + def compile([{:|, _, [head, tail]}], state) do + ast = J.call_expression( + J.member_expression( + J.array_expression([compile!(head, state)]), + J.identifier("concat") + ), + [compile!(tail, state)] + ) + + { ast, state } + end + def compile({:|, _, [head, tail]}, state) do ast = J.call_expression( J.member_expression( diff --git a/package.json b/package.json index d9d19d63..95032896 100644 --- a/package.json +++ b/package.json @@ -23,7 +23,7 @@ "license": "MIT", "dependencies": { "erlang-types": "^1.0.1", - "tailored": "^2.6.3" + "tailored": "^2.6.4" }, "devDependencies": { "ava": "^0.21.0", diff --git a/priv/build/iife/ElixirScript.Core.js b/priv/build/iife/ElixirScript.Core.js index 850b7ab7..80caf094 100644 --- a/priv/build/iife/ElixirScript.Core.js +++ b/priv/build/iife/ElixirScript.Core.js @@ -1,6 +1,2559 @@ -var ElixirScript=function(){'use strict';/* @flow */function namedVariableResult(a,b){return new NamedVariableResult(a,b)}/* @flow */function is_number(a){return'number'==typeof a}function is_string(a){return'string'==typeof a}function is_boolean(a){return'boolean'==typeof a}function is_symbol(a){return'symbol'==typeof a}function is_object(a){return'object'==typeof a}function is_variable(a){return a instanceof Variable}function is_null(a){return null===a}function is_array(a){return Array.isArray(a)}function is_function(a){return'[object Function]'==Object.prototype.toString.call(a)}function is_map(a){return a instanceof Map}function resolveNull(){return function(a){return is_null(a)}}function resolveWildcard(){return function(){return!0}}function resolveObject(a){let b={};const c=Object.keys(a).concat(Object.getOwnPropertySymbols(a));for(let d of c)b[d]=buildMatch(a[d]);return function(d,e){if(!is_object(d)||a.length>d.length)return!1;for(let a of c)if(!(a in d)||!b[a](d[a],e))return!1;return!0}}function getSize(a,b){return a*b/8}function arraysEqual(c,a){if(c===a)return!0;if(null==c||null==a)return!1;if(c.length!=a.length)return!1;for(var b=0;be.integer(a));return new e(...b)}function resolveNoMatch(){return function(){return!1}}function buildMatch(a){if(null===a)return resolveNull(a);if('undefined'==typeof a)return resolveWildcard(a);const b=a.constructor.prototype,c=f.get(b);return c?c(a):'object'==typeof a?resolveObject(a):resolveNoMatch()}function defmatchgen(...a){const b=getArityMap(a);return function*(...a){let[c,d]=findMatchingFunction(a,b);return yield*c.apply(this,d)}}function findMatchingFunction(a,b){if(b.has(a.length)){const c=b.get(a.length);let d=null,e=null;for(let b of c){let c=[];a=fillInOptionalValues(a,b.arity,b.optionals);const f=b.pattern(a,c),[g,h]=checkNamedVariables(c);if(f&&h&&b.guard.apply(this,g)){d=b.fn,e=g;break}}if(!d)throw console.error('No match for:',a),new MatchError(a);return[d,e]}throw console.error('Arity of',a.length,'not found. No match for:',a),new MatchError(a)}function getArityMap(a){let b=new Map;for(const c of a){const a=getArityRange(c);for(const d of a){let a=[];b.has(d)&&(a=b.get(d)),a.push(c),b.set(d,a)}}return b}function getArityRange(a){const b=a.arity-a.optionals.length,c=a.arity;let d=[b];for(;d[d.length-1]!=c;)d.push(d[d.length-1]+1);return d}function getOptionalValues(a){let b=[];for(let c=0;c!0,d=null){let e=[],f=buildMatch(a);const g=f(b,e),[h,i]=checkNamedVariables(e);return g&&i&&c.apply(this,h)?h:d}function run_generators(a,b){if(0==b.length)return a.map((a)=>{return Array.isArray(a)?a:[a]});const c=b.pop();let d=[];for(let e of c())for(let b of a)d.push([e].concat(b));return run_generators(d,b)}function iterator_to_reducer(a,b,c){const d=a[Symbol.iterator]();let e=d.next(),f=b;for(;!1===e.done;){if(f=c(e.value,f.get(1)),f.get(0)===Symbol.for('halt'))return new o.Tuple(Symbol.for('halted'),f.get(1));if(f.get(0)===Symbol.for('suspend'))return new o.Tuple(Symbol.for('suspended'),f.get(1),(a)=>{return iterator_to_reducer(d,a,c)});e=d.next()}return new o.Tuple(Symbol.for('done'),f.get(1))}function map_to_object(a){const b={};for(const[c,d]of a.entries())b[c]=d instanceof Map?map_to_object(d):d;return b}function run_list_generators(a,b){if(0==b.length)return a.map((a)=>{return Array.isArray(a)?a:[a]});const c=b.pop(),d=[];for(const e of c())for(const b of a)d.push([e].concat(b));return run_list_generators(d,b)}// http://erlang.org/doc/man/lists.html -function reverse(a){return[...a]}function flatten(a,b=[]){const c=a.reduce((a,b)=>{return Array.isArray(b)?a.concat(flatten(b)):a.concat(b)},[]);return c.concat(b)}function foldl(a,b,c){return c.reduce((b,c)=>{return a(c,b)},b)}function keyfind(a,b,c){for(const d of c)if(d.get(b-1)===a)return d;return!1}function keydelete(a,b,c){const d=[];let e=!1;for(let f=0;f{if(null===c)return a;return is_integer(c)?a+b(c):is_bitstring$1(c)?a+b(...c.value):a+iolist_to_binary(c)},'');return d}function is_key(a,b){return b.has(a)}function get_key(a){let b=a;if(__elixirscript_names__.has(a)&&(b=__elixirscript_names__.get(a)),__elixirscript_store__.has(b))return b;throw new Error(`Key ${b} not found`)}var a=Number.isInteger;class Variable{constructor(a=null,b=Symbol.for('tailored.no_value')){this.name=a,this.default_value=b}}class Wildcard{constructor(){}}class StartsWith{constructor(a){this.prefix=a}}class Capture{constructor(a){this.value=a}}class HeadTail{constructor(){}}class Type{constructor(a,b={}){this.type=a,this.objPattern=b}}class Bound{constructor(a){this.value=a}}class BitStringMatch{constructor(...a){this.values=a}length(){return values.length}bit_size(){return 8*this.byte_size()}byte_size(){let a=0;for(let b of this.values)a+=b.unit*b.size/8;return a}getValue(a){return this.values(a)}getSizeOfValue(a){let b=this.getValue(a);return b.unit*b.size}getTypeOfValue(a){return this.getValue(a).type}}class NamedVariableResult{constructor(a,b){this.name=a,this.value=b}}class Tuple{constructor(...a){this.values=Object.freeze(a),this.length=this.values.length}get(a){return this.values[a]}count(){return this.values.length}[Symbol.iterator](){return this.values[Symbol.iterator]()}toString(){let a,b='';for(a=0;aBitString$1.integer(a));return new BitString$1(...d)}[Symbol.iterator](){return this.value[Symbol.iterator]()}toString(){var a,b='';for(a=0;a>'}process(a){let b=[];var c;for(c=0;cb?c.push(b):2048>b?c.push(192|b>>6,128|63&b):55296>b||57344<=b?c.push(224|b>>12,128|63&b>>6,128|63&b):(d++,b=65536+((1023&b)<<10|1023&a.charCodeAt(d)),c.push(240|b>>18,128|63&b>>12,128|63&b>>6,128|63&b));return c}static toUTF16Array(a){for(var b,c=[],d=0;d=b?(c.push(0),c.push(b)):(c.push(255&b>>8),c.push(255&b));return c}static toUTF32Array(a){for(var b,c=[],d=0;d=b?(c.push(0),c.push(0),c.push(0),c.push(b)):(c.push(0),c.push(0),c.push(255&b>>8),c.push(255&b));return c}//http://stackoverflow.com/questions/2003493/javascript-float-from-to-bits -static float32ToBytes(a){var b=[],c=new ArrayBuffer(4);new Float32Array(c)[0]=a;let d=new Uint32Array(c)[0];return b.push(255&d>>24),b.push(255&d>>16),b.push(255&d>>8),b.push(255&d),b}static float64ToBytes(a){var b=[],c=new ArrayBuffer(8);new Float64Array(c)[0]=a;var d=new Uint32Array(c)[0],e=new Uint32Array(c)[1];return b.push(255&e>>24),b.push(255&e>>16),b.push(255&e>>8),b.push(255&e),b.push(255&d>>24),b.push(255&d>>16),b.push(255&d>>8),b.push(255&d),b}}var d={Tuple,PID:class PID{constructor(){++b,this.id=b}toString(){return'PID#<0.'+this.id+'.0>'}},Reference:class Reference{constructor(){++c,this.id=c,this.ref=Symbol()}toString(){return'Ref#<0.0.0.'+this.id+'>'}},BitString:BitString$1};/* @flow */const e=d.BitString,f=new Map;f.set(Variable.prototype,function resolveVariable(a){return function(b,c){return null===a.name?c.push(b):!a.name.startsWith('_')&&c.push(namedVariableResult(a.name,b)),!0}}),f.set(Wildcard.prototype,resolveWildcard),f.set(HeadTail.prototype,function resolveHeadTail(){return function(a,b){if(!is_array(a)||0===a.length)return!1;const c=a[0],d=a.slice(1);return b.push(c),b.push(d),!0}}),f.set(StartsWith.prototype,function resolveStartsWith(a){const b=a.prefix;return function(a,c){return is_string(a)&&a.startsWith(b)&&(c.push(a.substring(b.length)),!0)}}),f.set(Capture.prototype,function resolveCapture(a){const b=buildMatch(a.value);return function(a,c){return!!b(a,c)&&(c.push(a),!0)}}),f.set(Bound.prototype,function resolveBound(a){return function(b){return typeof b==typeof a.value&&b===a.value}}),f.set(Type.prototype,function resolveType(a){return function(b,c){if(b instanceof a.type){const d=buildMatch(a.objPattern);return d(b,c)}return!1}}),f.set(BitStringMatch.prototype,function resolveBitString(a){let b=[];for(let c of a.values)if(is_variable(c.value)){let a=getSize(c.unit,c.size);fillArray(b,a)}else b=b.concat(new e(c).value);let c=a.values;return function(a,d){var f=String.fromCharCode;let g=null;if(!is_string(a)&&!(a instanceof e))return!1;g=is_string(a)?new e(e.binary(a)):a;let h=0;for(let e,j=0;jd.size)return!1;for(let a of c)if(!d.has(a)||!b.get(a)(d.get(a),e))return!1;return!0}}),f.set(Array.prototype,function resolveArray(a){const b=a.map((a)=>buildMatch(a));return function(c,d){return is_array(c)&&c.length==a.length&&c.every(function(a,e){return b[e](c[e],d)})}}),f.set(String.prototype,function resolveString(a){return function(b){return is_string(b)&&b===a}}),f.set(Boolean.prototype,function resolveBoolean(a){return function(b){return is_boolean(b)&&b===a}}),f.set(Function.prototype,function resolveFunction(a){return function(b){return is_function(b)&&b===a}}),f.set(Object.prototype,resolveObject);class MatchError extends Error{constructor(a){if(super(),'symbol'==typeof a)this.message='No match for: '+a.toString();else if(Array.isArray(a)){let b=a.map((a)=>{return null===a?'null':'undefined'==typeof a?'undefined':a.toString()});this.message='No match for: '+b}else this.message='No match for: '+a;this.stack=new Error().stack,this.name=this.constructor.name}}class Clause{constructor(a,b,c=()=>!0){this.pattern=buildMatch(a),this.arity=a.length,this.optionals=getOptionalValues(a),this.fn=b,this.guard=c}}const g=Symbol();// https://github.com/airportyh/protomorphism -class Protocol{constructor(b){function createFun(b){return function(...c){const d=c[0];let e=null;if(null===d&&this.hasImplementation(Symbol('null'))?e=this.registry.get(Symbol)[b]:a(d)&&this.hasImplementation(o.Integer)?e=this.registry.get(o.Integer)[b]:'number'==typeof d&&!a(d)&&this.hasImplementation(o.Float)?e=this.registry.get(o.Float)[b]:'string'==typeof d&&this.hasImplementation(o.BitString)?e=this.registry.get(o.BitString)[b]:d&&d.has(Symbol.for('__struct__'))&&this.hasImplementation(d)?e=this.registry.get(d.get(Symbol.for('__struct__')).__MODULE__)[b]:null!==d&&this.hasImplementation(d)?e=this.registry.get(d.constructor)[b]:this.fallback&&(e=this.fallback[b]),null!=e){const a=e.apply(this,c);return a}throw new Error(`No implementation found for ${d}`)}}for(const a in this.registry=new Map,this.fallback=null,b)this[a]=createFun(a).bind(this)}implementation(a,b){null===a?this.fallback=b:this.registry.set(a,b)}hasImplementation(a){if(a===o.Integer||a===o.Float||a===o.BitString)return this.registry.has(a);return a&&a.has(Symbol.for('__struct__'))?this.registry.has(a.get(Symbol.for('__struct__')).__MODULE__):this.registry.has(a.constructor)}}var h={reverse,foreach:function foreach(a,b){return b.forEach((b)=>a(b)),Symbol.for('ok')},duplicate:function duplicate(a,b){const c=[];for(;c.length{if(d.get(c-1)a.get(c-1)?1:0})},keystore:function keystore(a,b,c,d){const e=[...c];for(let f=0;fa.toString()).join()},map:function map(a,b){return b.map((b)=>a(b))},filter:function filter(a,b){return b.filter((b)=>a(b))},filtermap:function filtermap(a,b){const c=[];for(const e of b){const b=a(e);!0===b?c.push(e):b instanceof d.Tuple&&!0===b.get(0)&&c.push(b.get(1))}return c},member:function member(a,b){for(const c of b)if(c===a)return!0;return!1},all:function all(a,b){for(const c of b)if(!1===a(c))return!1;return!0},any:function any(a,b){for(const c of b)if(!0===a(c))return!0;return!1},splitwith:function splitwith(a,b){let c=!1;const e=[],f=[];for(const d of b)!0==c?f.push(d):!0===a(d)?e.push(d):(c=!0,f.push(d));return new d.Tuple(e,f)},sort:function sort(...a){if(1===a.length){const b=[...a[0]];return b.sort()}const c=a[0],b=[...a[1]];return b.sort((d,a)=>{const b=c(d,a);return!0===b?-1:1})}},i={atom_to_binary,binary_to_atom,binary_to_existing_atom:function binary_to_existing_atom(a,b=Symbol.for('utf8')){return binary_to_atom(a,b)},list_concatenation:function list_concatenation(a,b){return a.concat(b)},list_subtraction:function list_subtraction(a,b){const c=[...a];for(const d of b){const a=c.indexOf(d);-1>b},bxor:function bxor(a,b){return a^b},bnot:function bnot(a){return~a},is_bitstring:is_bitstring$1,is_boolean:function is_boolean$1(a){return'boolean'==typeof a||a instanceof Boolean},is_float:function is_float(b){return is_number$1(b)&&!a(b)},is_function:function is_function$1(a){return'function'==typeof a||a instanceof Function},is_integer,is_list:function is_list(a){return Array.isArray(a)},is_map:function is_map$1(a){return a instanceof Map},is_number:is_number$1,is_pid:function is_pid(a){return a instanceof d.PID},is_port:function is_port(){return!1},is_reference:function is_reference(a){return a instanceof d.Reference},is_tuple:function is_tuple(a){return a instanceof d.Tuple},is_atom:function is_atom(a){return'symbol'==typeof a||a instanceof Symbol||a.__MODULE__},is_binary,element:function element(a,b){return b.get(a-1)},setelement:function setelement(a,b,c){const e=[...b.values];return e[a-1]=c,new d.Tuple(...e)},make_tuple:function make_tuple(a,b){const c=[];for(let d=0;d!0){let d=[],e=buildMatch(a);const f=e(b,d),[g,h]=checkNamedVariables(d);if(f&&h&&c.apply(this,g))return g;throw console.error('No match for:',b),new MatchError(b)},MatchError,variable:function variable(a=null,b=Symbol.for('tailored.no_value')){return new Variable(a,b)},wildcard:function wildcard(){return new Wildcard},startsWith:function startsWith(a){return new StartsWith(a)},capture:function capture(a){return new Capture(a)},headTail:function headTail(){return new HeadTail},type:function a(a,b={}){return new Type(a,b)},bound:function bound(a){return new Bound(a)},Clause,clause:function clause(a,b,c=()=>!0){return new Clause(a,b,c)},bitStringMatch:function bitStringMatch(...a){return new BitStringMatch(...a)},match_or_default,defmatchgen,list_comprehension:function list_comprehension(a,b){const c=run_generators(b.pop()(),b);let d=[];for(let e of c)a.guard.apply(this,e)&&d.push(a.fn.apply(this,e));return d},list_generator:function list_generator(a,b){return function(){let c=[];for(let d of b){const b=match_or_default(a,d,()=>!0,g);if(b!=g){const[a]=b;c.push(a)}}return c}},bitstring_generator:function bitstring_generator(a,b){return function(){let c=[],d=b.slice(0,a.byte_size()),e=1;for(;d.byte_size==a.byte_size();){const f=match_or_default(a,d,()=>!0,g);if(f!=g){c.push(f)}d=b.slice(a.byte_size()*e,a.byte_size()*(e+1)),e++}return c}},bitstring_comprehension:function bitstring_comprehension(a,b){const c=run_generators(b.pop()(),b);let e=[];for(let d of c)a.guard.apply(this,d)&&e.push(a.fn.apply(this,d));return e=e.map((a)=>d.BitString.integer(a)),new d.BitString(...e)},defmatchGen:function defmatchGen(...a){return defmatchgen(...a)},defmatchAsync:function defmatchAsync(...a){const b=getArityMap(a);return async function(...a){if(b.has(a.length)){const c=b.get(a.length);let d=null,e=null;for(let b of c){let c=[];a=fillInOptionalValues(a,b.arity,b.optionals);const f=b.pattern(a,c),[g,h]=checkNamedVariables(c);if(f&&h&&(await b.guard.apply(this,c))){d=b.fn,e=c;break}}if(!d)throw console.error('No match for:',a),new MatchError(a);return d.apply(this,e)}throw console.error('Arity of',a.length,'not found. No match for:',a),new MatchError(a)}}},Integer:class Integer{},Float:class Float{},Functions:{call_property:function call_property(a,b){if(!b)return a instanceof Function||'function'==typeof a?a():a;if(a instanceof Map){let c=null;if(a.has(b)?c=b:a.has(Symbol.for(b))&&(c=Symbol.for(b)),null===c)throw new Error(`Property ${b} not found in ${a}`);return a.get(c)instanceof Function||'function'==typeof a.get(c)?a.get(c)():a.get(c)}let c=null;if('number'==typeof a||'symbol'==typeof a||'boolean'==typeof a||'string'==typeof a?void 0===a[b]?void 0!==a[Symbol.for(b)]&&(c=Symbol.for(b)):c=b:b in a?c=b:Symbol.for(b)in a&&(c=Symbol.for(b)),null===c)throw new Error(`Property ${b} not found in ${a}`);return a[c]instanceof Function||'function'==typeof a[c]?a[c]():a[c]},defprotocol:function defprotocol(a){return new Protocol(a)},defimpl:function defimpl(a,b,c){a.implementation(b,c)},build_namespace:function build_namespace(a,b){let c=b.split('.');const d=a;let e=a;'Elixir'===c[0]&&(c=c.slice(1));for(const d of c)'undefined'==typeof e[d]&&(e[d]={}),e=e[d];return d.__table__=a.__table__||{},d.__table__[Symbol.for(b)]=e,e},iterator_to_reducer,map_to_object},SpecialForms:{_case:function _case(a,b){return o.Patterns.defmatch(...b)(a)},cond:function cond(...a){for(const b of a)if(b[0])return b[1]();throw new Error},_for:function _for(a,b,c,d=[]){let[e,f]=c.into(d);const g=run_list_generators(b.pop()(),b);for(const h of g)a.guard.apply(this,h)&&(e=f(e,new o.Tuple(Symbol.for('cont'),a.fn.apply(this,h))));return f(e,Symbol.for('done'))},_try:function _try(a,b,c,d,e){let f=null;try{f=a()}catch(a){let d=null;if(b)try{return d=b(a),d}catch(a){if(a instanceof o.Patterns.MatchError)throw a}if(c)try{return d=c(a),d}catch(a){if(a instanceof o.Patterns.MatchError)throw a}throw a}finally{e&&e()}if(d)try{return d(f)}catch(a){if(a instanceof o.Patterns.MatchError)throw new Error('No Match Found in Else');throw a}else return f},_with:function _with(...a){let b=[],c=null,d=null;'function'==typeof a[a.length-2]?[c,d]=a.splice(-2):c=a.pop();for(let c=0;c{const[c,d]=b;return a.set(c,d),a},new Map)},keys:function keys(a){return!1===i.is_map(a)?new d.Tuple(l,a):Array.from(a.keys())},values:function values$1(a){return!1===i.is_map(a)?new d.Tuple(l,a):Array.from(a.values())},is_key,put:function put(a,b,c){if(!1===i.is_map(c))return new d.Tuple(l,c);const e=new Map(c);return e.set(a,b),e},merge:function merge(a,b){return!1===i.is_map(a)?new d.Tuple(l,a):!1===i.is_map(b)?new d.Tuple(l,b):new Map([...a,...b])},update:function update(a,b,c){return!1===i.is_map(c)?new d.Tuple(l,c):!1===is_key(a,c)?new d.Tuple(m,a):new Map([...c,[a,b]])},get:function get(...a){const b=a[0],c=a[1];return!1===i.is_map(c)?new d.Tuple(l,c):is_key(b)?c.get(b):3===a.length?a[2]:new d.Tuple(m,b)},take:function take(a,b){if(!1===i.is_map(b))return new d.Tuple(l,b);if(!is_key(a))return k;const c=b.get(a),e=new Map(b);return e.delete(a),new d.Tuple(c,e)}},lists:h,elixir_errors:{warn:function warn(a){const b=a.join('');return console.warn(`warning: ${b}`),Symbol.for('ok')}},io:{put_chars:function put_chars(a,b){let c=i.iolist_to_binary(b);return a===Symbol.for('stderr')?console.error(c):console.log(c),Symbol.for('ok')}},binary:{copy:function copy(a,b=1){return a.repeat(b)}}};return{Core:o}}(); +var ElixirScript = (function () { +'use strict'; + +/* @flow */ + +class Variable { + constructor(name = null, default_value = Symbol.for('tailored.no_value')) { + this.name = name; + this.default_value = default_value; + } +} + +class Wildcard { + constructor() {} +} + +class StartsWith { + constructor(prefix) { + this.prefix = prefix; + } +} + +class Capture { + constructor(value) { + this.value = value; + } +} + +class HeadTail { + constructor(head, tail) { + this.head = head; + this.tail = tail; + } +} + +class Type { + constructor(type, objPattern = {}) { + this.type = type; + this.objPattern = objPattern; + } +} + +class Bound { + constructor(value) { + this.value = value; + } +} + +class BitStringMatch { + constructor(...values) { + this.values = values; + } + + length() { + return values.length; + } + + bit_size() { + return this.byte_size() * 8; + } + + byte_size() { + let s = 0; + + for (let val of this.values) { + s = s + val.unit * val.size / 8; + } + + return s; + } + + getValue(index) { + return this.values(index); + } + + getSizeOfValue(index) { + let val = this.getValue(index); + return val.unit * val.size; + } + + getTypeOfValue(index) { + return this.getValue(index).type; + } +} + +class NamedVariableResult { + constructor(name, value) { + this.name = name; + this.value = value; + } +} + +function variable(name = null, default_value = Symbol.for('tailored.no_value')) { + return new Variable(name, default_value); +} + +function wildcard() { + return new Wildcard(); +} + +function startsWith(prefix) { + return new StartsWith(prefix); +} + +function capture(value) { + return new Capture(value); +} + +function headTail(head, tail) { + return new HeadTail(head, tail); +} + +function type(type, objPattern = {}) { + return new Type(type, objPattern); +} + +function bound(value) { + return new Bound(value); +} + +function bitStringMatch(...values) { + return new BitStringMatch(...values); +} + +function namedVariableResult(name, value) { + return new NamedVariableResult(name, value); +} + +/* @flow */ + +function is_number(value) { + return typeof value === 'number'; +} + +function is_string(value) { + return typeof value === 'string'; +} + +function is_boolean(value) { + return typeof value === 'boolean'; +} + +function is_symbol(value) { + return typeof value === 'symbol'; +} + +function is_object(value) { + return typeof value === 'object'; +} + +function is_variable(value) { + return value instanceof Variable; +} + +function is_null(value) { + return value === null; +} + +function is_array(value) { + return Array.isArray(value); +} + +function is_function(value) { + return Object.prototype.toString.call(value) == '[object Function]'; +} + +function is_map(value) { + return value instanceof Map; +} + +class Tuple { + constructor(...args) { + this.values = Object.freeze(args); + this.length = this.values.length; + } + + get(index) { + return this.values[index]; + } + + count() { + return this.values.length; + } + + [Symbol.iterator]() { + return this.values[Symbol.iterator](); + } + + toString() { + let i, + s = ''; + for (i = 0; i < this.values.length; i++) { + if (s !== '') { + s += ', '; + } + + const stringToAppend = this.values[i] ? this.values[i].toString() : ''; + + s += stringToAppend; + } + + return '{' + s + '}'; + } + + put_elem(index, elem) { + if (index === this.length) { + let new_values = this.values.concat([elem]); + return new Tuple(...new_values); + } + + let new_values = this.values.concat([]); + new_values.splice(index, 0, elem); + return new Tuple(...new_values); + } + + remove_elem(index) { + let new_values = this.values.concat([]); + new_values.splice(index, 1); + return new Tuple(...new_values); + } +} + +let process_counter = -1; + +class PID { + constructor() { + process_counter = process_counter + 1; + this.id = process_counter; + } + + toString() { + return 'PID#<0.' + this.id + '.0>'; + } +} + +let ref_counter = -1; + +class Reference { + constructor() { + ref_counter = ref_counter + 1; + this.id = ref_counter; + this.ref = Symbol(); + } + + toString() { + return 'Ref#<0.0.0.' + this.id + '>'; + } +} + +class BitString$1 { + constructor(...args) { + this.value = Object.freeze(this.process(args)); + this.length = this.value.length; + this.bit_size = this.length * 8; + this.byte_size = this.length; + } + + get(index) { + return this.value[index]; + } + + count() { + return this.value.length; + } + + slice(start, end = null) { + let s = this.value.slice(start, end); + let ms = s.map(elem => BitString$1.integer(elem)); + return new BitString$1(...ms); + } + + [Symbol.iterator]() { + return this.value[Symbol.iterator](); + } + + toString() { + var i, + s = ''; + for (i = 0; i < this.count(); i++) { + if (s !== '') { + s += ', '; + } + s += this.get(i).toString(); + } + + return '<<' + s + '>>'; + } + + process(bitStringParts) { + let processed_values = []; + + var i; + for (i = 0; i < bitStringParts.length; i++) { + let processed_value = this['process_' + bitStringParts[i].type](bitStringParts[i]); + + for (let attr of bitStringParts[i].attributes) { + processed_value = this['process_' + attr](processed_value); + } + + processed_values = processed_values.concat(processed_value); + } + + return processed_values; + } + + process_integer(value) { + return value.value; + } + + process_float(value) { + if (value.size === 64) { + return BitString$1.float64ToBytes(value.value); + } else if (value.size === 32) { + return BitString$1.float32ToBytes(value.value); + } + + throw new Error('Invalid size for float'); + } + + process_bitstring(value) { + return value.value.value; + } + + process_binary(value) { + return BitString$1.toUTF8Array(value.value); + } + + process_utf8(value) { + return BitString$1.toUTF8Array(value.value); + } + + process_utf16(value) { + return BitString$1.toUTF16Array(value.value); + } + + process_utf32(value) { + return BitString$1.toUTF32Array(value.value); + } + + process_signed(value) { + return new Uint8Array([value])[0]; + } + + process_unsigned(value) { + return value; + } + + process_native(value) { + return value; + } + + process_big(value) { + return value; + } + + process_little(value) { + return value.reverse(); + } + + process_size(value) { + return value; + } + + process_unit(value) { + return value; + } + + static integer(value) { + return BitString$1.wrap(value, { type: 'integer', unit: 1, size: 8 }); + } + + static float(value) { + return BitString$1.wrap(value, { type: 'float', unit: 1, size: 64 }); + } + + static bitstring(value) { + return BitString$1.wrap(value, { + type: 'bitstring', + unit: 1, + size: value.bit_size + }); + } + + static bits(value) { + return BitString$1.bitstring(value); + } + + static binary(value) { + return BitString$1.wrap(value, { + type: 'binary', + unit: 8, + size: value.length + }); + } + + static bytes(value) { + return BitString$1.binary(value); + } + + static utf8(value) { + return BitString$1.wrap(value, { type: 'utf8', unit: 1, size: value.length }); + } + + static utf16(value) { + return BitString$1.wrap(value, { + type: 'utf16', + unit: 1, + size: value.length * 2 + }); + } + + static utf32(value) { + return BitString$1.wrap(value, { + type: 'utf32', + unit: 1, + size: value.length * 4 + }); + } + + static signed(value) { + return BitString$1.wrap(value, {}, 'signed'); + } + + static unsigned(value) { + return BitString$1.wrap(value, {}, 'unsigned'); + } + + static native(value) { + return BitString$1.wrap(value, {}, 'native'); + } + + static big(value) { + return BitString$1.wrap(value, {}, 'big'); + } + + static little(value) { + return BitString$1.wrap(value, {}, 'little'); + } + + static size(value, count) { + return BitString$1.wrap(value, { size: count }); + } + + static unit(value, count) { + return BitString$1.wrap(value, { unit: count }); + } + + static wrap(value, opt, new_attribute = null) { + let the_value = value; + + if (!(value instanceof Object)) { + the_value = { value: value, attributes: [] }; + } + + the_value = Object.assign(the_value, opt); + + if (new_attribute) { + the_value.attributes.push(new_attribute); + } + + return the_value; + } + + static toUTF8Array(str) { + var utf8 = []; + for (var i = 0; i < str.length; i++) { + var charcode = str.charCodeAt(i); + if (charcode < 0x80) { + utf8.push(charcode); + } else if (charcode < 0x800) { + utf8.push(0xc0 | charcode >> 6, 0x80 | charcode & 0x3f); + } else if (charcode < 0xd800 || charcode >= 0xe000) { + utf8.push(0xe0 | charcode >> 12, 0x80 | charcode >> 6 & 0x3f, 0x80 | charcode & 0x3f); + } else { + // surrogate pair + i++; + // UTF-16 encodes 0x10000-0x10FFFF by + // subtracting 0x10000 and splitting the + // 20 bits of 0x0-0xFFFFF into two halves + charcode = 0x10000 + ((charcode & 0x3ff) << 10 | str.charCodeAt(i) & 0x3ff); + utf8.push(0xf0 | charcode >> 18, 0x80 | charcode >> 12 & 0x3f, 0x80 | charcode >> 6 & 0x3f, 0x80 | charcode & 0x3f); + } + } + return utf8; + } + + static toUTF16Array(str) { + var utf16 = []; + for (var i = 0; i < str.length; i++) { + var codePoint = str.codePointAt(i); + + if (codePoint <= 255) { + utf16.push(0); + utf16.push(codePoint); + } else { + utf16.push(codePoint >> 8 & 0xff); + utf16.push(codePoint & 0xff); + } + } + return utf16; + } + + static toUTF32Array(str) { + var utf32 = []; + for (var i = 0; i < str.length; i++) { + var codePoint = str.codePointAt(i); + + if (codePoint <= 255) { + utf32.push(0); + utf32.push(0); + utf32.push(0); + utf32.push(codePoint); + } else { + utf32.push(0); + utf32.push(0); + utf32.push(codePoint >> 8 & 0xff); + utf32.push(codePoint & 0xff); + } + } + return utf32; + } + + //http://stackoverflow.com/questions/2003493/javascript-float-from-to-bits + static float32ToBytes(f) { + var bytes = []; + + var buf = new ArrayBuffer(4); + new Float32Array(buf)[0] = f; + + let intVersion = new Uint32Array(buf)[0]; + + bytes.push(intVersion >> 24 & 0xff); + bytes.push(intVersion >> 16 & 0xff); + bytes.push(intVersion >> 8 & 0xff); + bytes.push(intVersion & 0xff); + + return bytes; + } + + static float64ToBytes(f) { + var bytes = []; + + var buf = new ArrayBuffer(8); + new Float64Array(buf)[0] = f; + + var intVersion1 = new Uint32Array(buf)[0]; + var intVersion2 = new Uint32Array(buf)[1]; + + bytes.push(intVersion2 >> 24 & 0xff); + bytes.push(intVersion2 >> 16 & 0xff); + bytes.push(intVersion2 >> 8 & 0xff); + bytes.push(intVersion2 & 0xff); + + bytes.push(intVersion1 >> 24 & 0xff); + bytes.push(intVersion1 >> 16 & 0xff); + bytes.push(intVersion1 >> 8 & 0xff); + bytes.push(intVersion1 & 0xff); + + return bytes; + } +} + +var ErlangTypes = { + Tuple, + PID, + Reference, + BitString: BitString$1 +}; + +/* @flow */ + +const BitString = ErlangTypes.BitString; + +function resolveSymbol(pattern) { + return function (value) { + return is_symbol(value) && value === pattern; + }; +} + +function resolveString(pattern) { + return function (value) { + return is_string(value) && value === pattern; + }; +} + +function resolveNumber(pattern) { + return function (value) { + return is_number(value) && value === pattern; + }; +} + +function resolveBoolean(pattern) { + return function (value) { + return is_boolean(value) && value === pattern; + }; +} + +function resolveFunction(pattern) { + return function (value) { + return is_function(value) && value === pattern; + }; +} + +function resolveNull(pattern) { + return function (value) { + return is_null(value); + }; +} + +function resolveBound(pattern) { + return function (value, args) { + if (typeof value === typeof pattern.value && value === pattern.value) { + return true; + } + + return false; + }; +} + +function resolveWildcard() { + return function () { + return true; + }; +} + +function resolveVariable(pattern) { + return function (value, args) { + if (pattern.name === null) { + args.push(value); + } else if (!pattern.name.startsWith('_')) { + args.push(namedVariableResult(pattern.name, value)); + } + + return true; + }; +} + +function resolveHeadTail(pattern) { + const headMatches = buildMatch(pattern.head); + const tailMatches = buildMatch(pattern.tail); + + return function (value, args) { + if (!is_array(value) || value.length === 0) { + return false; + } + + const head = value[0]; + const tail = value.slice(1); + + if (headMatches(head, args) && tailMatches(tail, args)) { + return true; + } + + return false; + }; +} + +function resolveCapture(pattern) { + const matches = buildMatch(pattern.value); + + return function (value, args) { + if (matches(value, args)) { + args.push(value); + return true; + } + + return false; + }; +} + +function resolveStartsWith(pattern) { + const prefix = pattern.prefix; + + return function (value, args) { + if (is_string(value) && value.startsWith(prefix)) { + args.push(value.substring(prefix.length)); + return true; + } + + return false; + }; +} + +function resolveType(pattern) { + return function (value, args) { + if (value instanceof pattern.type) { + const matches = buildMatch(pattern.objPattern); + return matches(value, args); + } + + return false; + }; +} + +function resolveArray(pattern) { + const matches = pattern.map(x => buildMatch(x)); + + return function (value, args) { + if (!is_array(value) || value.length != pattern.length) { + return false; + } + + return value.every(function (v, i) { + return matches[i](value[i], args); + }); + }; +} + +function resolveMap(pattern) { + let matches = new Map(); + + const keys = Array.from(pattern.keys()); + + for (let key of keys) { + matches.set(key, buildMatch(pattern.get(key))); + } + + return function (value, args) { + if (!is_map(value) || pattern.size > value.size) { + return false; + } + + for (let key of keys) { + if (!value.has(key) || !matches.get(key)(value.get(key), args)) { + return false; + } + } + + return true; + }; +} + +function resolveObject(pattern) { + let matches = {}; + + const keys = Object.keys(pattern).concat(Object.getOwnPropertySymbols(pattern)); + + for (let key of keys) { + matches[key] = buildMatch(pattern[key]); + } + + return function (value, args) { + if (!is_object(value) || pattern.length > value.length) { + return false; + } + + for (let key of keys) { + if (!(key in value) || !matches[key](value[key], args)) { + return false; + } + } + + return true; + }; +} + +function resolveBitString(pattern) { + let patternBitString = []; + + for (let bitstringMatchPart of pattern.values) { + if (is_variable(bitstringMatchPart.value)) { + let size = getSize(bitstringMatchPart.unit, bitstringMatchPart.size); + fillArray(patternBitString, size); + } else { + patternBitString = patternBitString.concat(new BitString(bitstringMatchPart).value); + } + } + + let patternValues = pattern.values; + + return function (value, args) { + let bsValue = null; + + if (!is_string(value) && !(value instanceof BitString)) { + return false; + } + + if (is_string(value)) { + bsValue = new BitString(BitString.binary(value)); + } else { + bsValue = value; + } + + let beginningIndex = 0; + + for (let i = 0; i < patternValues.length; i++) { + let bitstringMatchPart = patternValues[i]; + + if (is_variable(bitstringMatchPart.value) && bitstringMatchPart.type == 'binary' && bitstringMatchPart.size === undefined && i < patternValues.length - 1) { + throw new Error('a binary field without size is only allowed at the end of a binary pattern'); + } + + let size = 0; + let bsValueArrayPart = []; + let patternBitStringArrayPart = []; + size = getSize(bitstringMatchPart.unit, bitstringMatchPart.size); + + if (i === patternValues.length - 1) { + bsValueArrayPart = bsValue.value.slice(beginningIndex); + patternBitStringArrayPart = patternBitString.slice(beginningIndex); + } else { + bsValueArrayPart = bsValue.value.slice(beginningIndex, beginningIndex + size); + patternBitStringArrayPart = patternBitString.slice(beginningIndex, beginningIndex + size); + } + + if (is_variable(bitstringMatchPart.value)) { + switch (bitstringMatchPart.type) { + case 'integer': + if (bitstringMatchPart.attributes && bitstringMatchPart.attributes.indexOf('signed') != -1) { + args.push(new Int8Array([bsValueArrayPart[0]])[0]); + } else { + args.push(new Uint8Array([bsValueArrayPart[0]])[0]); + } + break; + + case 'float': + if (size === 64) { + args.push(Float64Array.from(bsValueArrayPart)[0]); + } else if (size === 32) { + args.push(Float32Array.from(bsValueArrayPart)[0]); + } else { + return false; + } + break; + + case 'bitstring': + args.push(createBitString(bsValueArrayPart)); + break; + + case 'binary': + args.push(String.fromCharCode.apply(null, new Uint8Array(bsValueArrayPart))); + break; + + case 'utf8': + args.push(String.fromCharCode.apply(null, new Uint8Array(bsValueArrayPart))); + break; + + case 'utf16': + args.push(String.fromCharCode.apply(null, new Uint16Array(bsValueArrayPart))); + break; + + case 'utf32': + args.push(String.fromCharCode.apply(null, new Uint32Array(bsValueArrayPart))); + break; + + default: + return false; + } + } else if (!arraysEqual(bsValueArrayPart, patternBitStringArrayPart)) { + return false; + } + + beginningIndex = beginningIndex + size; + } + + return true; + }; +} + +function getSize(unit, size) { + return unit * size / 8; +} + +function arraysEqual(a, b) { + if (a === b) return true; + if (a == null || b == null) return false; + if (a.length != b.length) return false; + + for (var i = 0; i < a.length; ++i) { + if (a[i] !== b[i]) return false; + } + + return true; +} + +function fillArray(arr, num) { + for (let i = 0; i < num; i++) { + arr.push(0); + } +} + +function createBitString(arr) { + let integerParts = arr.map(elem => BitString.integer(elem)); + return new BitString(...integerParts); +} + +function resolveNoMatch() { + return function () { + return false; + }; +} + +const patternMap = new Map(); +patternMap.set(Variable.prototype, resolveVariable); +patternMap.set(Wildcard.prototype, resolveWildcard); +patternMap.set(HeadTail.prototype, resolveHeadTail); +patternMap.set(StartsWith.prototype, resolveStartsWith); +patternMap.set(Capture.prototype, resolveCapture); +patternMap.set(Bound.prototype, resolveBound); +patternMap.set(Type.prototype, resolveType); +patternMap.set(BitStringMatch.prototype, resolveBitString); +patternMap.set(Number.prototype, resolveNumber); +patternMap.set(Symbol.prototype, resolveSymbol); +patternMap.set(Map.prototype, resolveMap); +patternMap.set(Array.prototype, resolveArray); +patternMap.set(String.prototype, resolveString); +patternMap.set(Boolean.prototype, resolveBoolean); +patternMap.set(Function.prototype, resolveFunction); +patternMap.set(Object.prototype, resolveObject); + +function buildMatch(pattern) { + if (pattern === null) { + return resolveNull(pattern); + } + + if (typeof pattern === 'undefined') { + return resolveWildcard(pattern); + } + + const type$$1 = pattern.constructor.prototype; + const resolver = patternMap.get(type$$1); + + if (resolver) { + return resolver(pattern); + } + + if (typeof pattern === 'object') { + return resolveObject(pattern); + } + + return resolveNoMatch(); +} + +class MatchError extends Error { + constructor(arg) { + super(); + + if (typeof arg === 'symbol') { + this.message = 'No match for: ' + arg.toString(); + } else if (Array.isArray(arg)) { + let mappedValues = arg.map(x => { + if (x === null) { + return 'null'; + } else if (typeof x === 'undefined') { + return 'undefined'; + } + + return x.toString(); + }); + + this.message = 'No match for: ' + mappedValues; + } else { + this.message = 'No match for: ' + arg; + } + + this.stack = new Error().stack; + this.name = this.constructor.name; + } +} + +class Clause { + constructor(pattern, fn, guard = () => true) { + this.pattern = buildMatch(pattern); + this.arity = pattern.length; + this.optionals = getOptionalValues(pattern); + this.fn = fn; + this.guard = guard; + } +} + +function clause(pattern, fn, guard = () => true) { + return new Clause(pattern, fn, guard); +} + + + +function defmatch(...clauses) { + const arities = getArityMap(clauses); + + return function (...args) { + let [funcToCall, params] = findMatchingFunction(args, arities); + return funcToCall.apply(this, params); + }; +} + +function defmatchgen(...clauses) { + const arities = getArityMap(clauses); + + return function* (...args) { + let [funcToCall, params] = findMatchingFunction(args, arities); + return yield* funcToCall.apply(this, params); + }; +} + +function defmatchGen(...args) { + return defmatchgen(...args); +} + +function defmatchAsync(...clauses) { + const arities = getArityMap(clauses); + + return async function (...args) { + if (arities.has(args.length)) { + const arityClauses = arities.get(args.length); + + let funcToCall = null; + let params = null; + for (let processedClause of arityClauses) { + let result = []; + args = fillInOptionalValues(args, processedClause.arity, processedClause.optionals); + + const doesMatch = processedClause.pattern(args, result); + const [filteredResult, allNamesMatch] = checkNamedVariables(result); + + if (doesMatch && allNamesMatch && (await processedClause.guard.apply(this, result))) { + funcToCall = processedClause.fn; + params = result; + break; + } + } + + if (!funcToCall) { + console.error('No match for:', args); + throw new MatchError(args); + } + + return funcToCall.apply(this, params); + } else { + console.error('Arity of', args.length, 'not found. No match for:', args); + throw new MatchError(args); + } + }; +} + +function findMatchingFunction(args, arities) { + if (arities.has(args.length)) { + const arityClauses = arities.get(args.length); + + let funcToCall = null; + let params = null; + for (let processedClause of arityClauses) { + let result = []; + args = fillInOptionalValues(args, processedClause.arity, processedClause.optionals); + + const doesMatch = processedClause.pattern(args, result); + const [filteredResult, allNamesMatch] = checkNamedVariables(result); + + if (doesMatch && allNamesMatch && processedClause.guard.apply(this, filteredResult)) { + funcToCall = processedClause.fn; + params = filteredResult; + break; + } + } + + if (!funcToCall) { + console.error('No match for:', args); + throw new MatchError(args); + } + + return [funcToCall, params]; + } else { + console.error('Arity of', args.length, 'not found. No match for:', args); + throw new MatchError(args); + } +} + +function getArityMap(clauses) { + let map = new Map(); + + for (const clause of clauses) { + const range = getArityRange(clause); + + for (const arity of range) { + let arityClauses = []; + + if (map.has(arity)) { + arityClauses = map.get(arity); + } + + arityClauses.push(clause); + map.set(arity, arityClauses); + } + } + + return map; +} + +function getArityRange(clause) { + const min = clause.arity - clause.optionals.length; + const max = clause.arity; + + let range = [min]; + + while (range[range.length - 1] != max) { + range.push(range[range.length - 1] + 1); + } + + return range; +} + +function getOptionalValues(pattern) { + let optionals = []; + + for (let i = 0; i < pattern.length; i++) { + if (pattern[i] instanceof Variable && pattern[i].default_value != Symbol.for('tailored.no_value')) { + optionals.push([i, pattern[i].default_value]); + } + } + + return optionals; +} + +function fillInOptionalValues(args, arity, optionals) { + if (args.length === arity || optionals.length === 0) { + return args; + } + + if (args.length + optionals.length < arity) { + return args; + } + + let numberOfOptionalsToFill = arity - args.length; + let optionalsToRemove = optionals.length - numberOfOptionalsToFill; + + let optionalsToUse = optionals.slice(optionalsToRemove); + + for (let [index, value] of optionalsToUse) { + args.splice(index, 0, value); + if (args.length === arity) { + break; + } + } + + return args; +} + +function match(pattern, expr, guard = () => true) { + let result = []; + let processedPattern = buildMatch(pattern); + const doesMatch = processedPattern(expr, result); + const [filteredResult, allNamesMatch] = checkNamedVariables(result); + + if (doesMatch && allNamesMatch && guard.apply(this, filteredResult)) { + return filteredResult; + } else { + console.error('No match for:', expr); + throw new MatchError(expr); + } +} + +function checkNamedVariables(results) { + const namesMap = {}; + const filteredResults = []; + + for (let i = 0; i < results.length; i++) { + const current = results[i]; + if (current instanceof NamedVariableResult) { + if (namesMap[current.name] && namesMap[current.name] !== current.value) { + return [results, false]; + } else if (namesMap[current.name] && namesMap[current.name] === current.value) { + filteredResults.push(current.value); + } else { + namesMap[current.name] = current.value; + filteredResults.push(current.value); + } + } else { + filteredResults.push(current); + } + } + + return [filteredResults, true]; +} + +function match_or_default(pattern, expr, guard = () => true, default_value = null) { + let result = []; + let processedPattern = buildMatch(pattern); + const doesMatch = processedPattern(expr, result); + const [filteredResult, allNamesMatch] = checkNamedVariables(result); + + if (doesMatch && allNamesMatch && guard.apply(this, filteredResult)) { + return filteredResult; + } else { + return default_value; + } +} + +const NO_MATCH = Symbol(); + +function bitstring_generator(pattern, bitstring) { + return function () { + let returnResult = []; + let bsSlice = bitstring.slice(0, pattern.byte_size()); + let i = 1; + + while (bsSlice.byte_size == pattern.byte_size()) { + const result = match_or_default(pattern, bsSlice, () => true, NO_MATCH); + + if (result != NO_MATCH) { + const [value] = result; + returnResult.push(result); + } + + bsSlice = bitstring.slice(pattern.byte_size() * i, pattern.byte_size() * (i + 1)); + + i++; + } + + return returnResult; + }; +} + +function list_generator(pattern, list) { + return function () { + let returnResult = []; + for (let i of list) { + const result = match_or_default(pattern, i, () => true, NO_MATCH); + if (result != NO_MATCH) { + const [value] = result; + returnResult.push(value); + } + } + + return returnResult; + }; +} + +function list_comprehension(expression, generators) { + const generatedValues = run_generators(generators.pop()(), generators); + + let result = []; + + for (let value of generatedValues) { + if (expression.guard.apply(this, value)) { + result.push(expression.fn.apply(this, value)); + } + } + + return result; +} + +function run_generators(generator, generators) { + if (generators.length == 0) { + return generator.map(x => { + if (Array.isArray(x)) { + return x; + } else { + return [x]; + } + }); + } else { + const list = generators.pop(); + + let next_gen = []; + for (let j of list()) { + for (let i of generator) { + next_gen.push([j].concat(i)); + } + } + + return run_generators(next_gen, generators); + } +} + +function bitstring_comprehension(expression, generators) { + const generatedValues = run_generators(generators.pop()(), generators); + + let result = []; + + for (let value of generatedValues) { + if (expression.guard.apply(this, value)) { + result.push(expression.fn.apply(this, value)); + } + } + + result = result.map(x => ErlangTypes.BitString.integer(x)); + return new ErlangTypes.BitString(...result); +} + +var Patterns = { + defmatch, + match, + MatchError, + variable, + wildcard, + startsWith, + capture, + headTail, + type, + bound, + Clause, + clause, + bitStringMatch, + match_or_default, + defmatchgen, + list_comprehension, + list_generator, + bitstring_generator, + bitstring_comprehension, + defmatchGen, + defmatchAsync +}; + +// https://github.com/airportyh/protomorphism +class Protocol { + constructor(spec) { + this.registry = new Map(); + this.fallback = null; + + function createFun(funName) { + return function (...args) { + const thing = args[0]; + let fun = null; + + if (thing === null && this.hasImplementation(Symbol('null'))) { + fun = this.registry.get(Symbol)[funName]; + } else if (Number.isInteger(thing) && this.hasImplementation(Core.Integer)) { + fun = this.registry.get(Core.Integer)[funName]; + } else if (typeof thing === 'number' && !Number.isInteger(thing) && this.hasImplementation(Core.Float)) { + fun = this.registry.get(Core.Float)[funName]; + } else if (typeof thing === 'string' && this.hasImplementation(Core.BitString)) { + fun = this.registry.get(Core.BitString)[funName]; + } else if (thing && thing instanceof Map && thing.has(Symbol.for('__struct__')) && this.hasImplementation(thing)) { + fun = this.registry.get(thing.get(Symbol.for('__struct__')).__MODULE__)[funName]; + } else if (thing !== null && this.hasImplementation(thing)) { + fun = this.registry.get(thing.constructor)[funName]; + } else if (this.fallback) { + fun = this.fallback[funName]; + } + + if (fun != null) { + const retval = fun.apply(this, args); + return retval; + } + + throw new Error(`No implementation found for ${thing}`); + }; + } + + for (const funName in spec) { + this[funName] = createFun(funName).bind(this); + } + } + + implementation(type, implementation) { + if (type === null) { + this.fallback = implementation; + } else { + this.registry.set(type, implementation); + } + } + + hasImplementation(thing) { + if (thing === Core.Integer || thing === Core.Float || thing === Core.BitString) { + return this.registry.has(thing); + } else if (thing && thing instanceof Map && thing.has(Symbol.for('__struct__'))) { + return this.registry.has(thing.get(Symbol.for('__struct__')).__MODULE__); + } + + return this.registry.has(thing.constructor); + } +} + +function iterator_to_reducer(iterable, acc, fun) { + const iterator = iterable[Symbol.iterator](); + let x = iterator.next(); + let _acc = acc; + + while (x.done === false) { + _acc = fun(x.value, _acc.get(1)); + if (_acc.get(0) === Symbol.for('halt')) { + return new Core.Tuple(Symbol.for('halted'), _acc.get(1)); + } else if (_acc.get(0) === Symbol.for('suspend')) { + return new Core.Tuple(Symbol.for('suspended'), _acc.get(1), new_acc => { + return iterator_to_reducer(iterator, new_acc, fun); + }); + } + + x = iterator.next(); + } + + return new Core.Tuple(Symbol.for('done'), _acc.get(1)); +} + +function call_property(item, property) { + if (!property) { + if (item instanceof Function || typeof item === 'function') { + return item(); + } + + return item; + } + + if (item instanceof Map) { + let prop = null; + + if (item.has(property)) { + prop = property; + } else if (item.has(Symbol.for(property))) { + prop = Symbol.for(property); + } + + if (prop === null) { + throw new Error(`Property ${property} not found in ${item}`); + } + + if (item.get(prop) instanceof Function || typeof item.get(prop) === 'function') { + return item.get(prop)(); + } + return item.get(prop); + } + + let prop = null; + + if (typeof item === 'number' || typeof item === 'symbol' || typeof item === 'boolean' || typeof item === 'string') { + if (item[property] !== undefined) { + prop = property; + } else if (item[Symbol.for(property)] !== undefined) { + prop = Symbol.for(property); + } + } else if (property in item) { + prop = property; + } else if (Symbol.for(property) in item) { + prop = Symbol.for(property); + } + + if (prop === null) { + throw new Error(`Property ${property} not found in ${item}`); + } + + if (item[prop] instanceof Function || typeof item[prop] === 'function') { + return item[prop](); + } + return item[prop]; +} + +function defprotocol(spec) { + return new Protocol(spec); +} + +function defimpl(protocol, type, impl) { + protocol.implementation(type, impl); +} + +function build_namespace(ns, ns_string) { + let parts = ns_string.split('.'); + const root = ns; + let parent = ns; + + if (parts[0] === 'Elixir') { + parts = parts.slice(1); + } + + for (const part of parts) { + if (typeof parent[part] === 'undefined') { + parent[part] = {}; + } + + parent = parent[part]; + } + + root.__table__ = ns.__table__ || {}; + root.__table__[Symbol.for(ns_string)] = parent; + + return parent; +} + +function map_to_object(map) { + const object = {}; + + for (const [key, value] of map.entries()) { + if (value instanceof Map) { + object[key] = map_to_object(value); + } else { + object[key] = value; + } + } + + return object; +} + +var Functions = { + call_property, + defprotocol, + defimpl, + build_namespace, + iterator_to_reducer, + map_to_object +}; + +function _case(condition, clauses) { + return Core.Patterns.defmatch(...clauses)(condition); +} + +function cond(...clauses) { + for (const clause of clauses) { + if (clause[0]) { + return clause[1](); + } + } + + throw new Error(); +} + +function _for(expression, generators, collectable_protocol, into = []) { + let [result, fun] = collectable_protocol.into(into); + + const generatedValues = run_list_generators(generators.pop()(), generators); + + for (const value of generatedValues) { + if (expression.guard.apply(this, value)) { + result = fun(result, new Core.Tuple(Symbol.for('cont'), expression.fn.apply(this, value))); + } + } + + return fun(result, Symbol.for('done')); +} + +function run_list_generators(generator, generators) { + if (generators.length == 0) { + return generator.map(x => { + if (Array.isArray(x)) { + return x; + } + return [x]; + }); + } + const list = generators.pop(); + + const next_gen = []; + for (const j of list()) { + for (const i of generator) { + next_gen.push([j].concat(i)); + } + } + + return run_list_generators(next_gen, generators); +} + +function _try(do_fun, rescue_function, catch_fun, else_function, after_function) { + let result = null; + + try { + result = do_fun(); + } catch (e) { + let ex_result = null; + + if (rescue_function) { + try { + ex_result = rescue_function(e); + return ex_result; + } catch (ex) { + if (ex instanceof Core.Patterns.MatchError) { + throw ex; + } + } + } + + if (catch_fun) { + try { + ex_result = catch_fun(e); + return ex_result; + } catch (ex) { + if (ex instanceof Core.Patterns.MatchError) { + throw ex; + } + } + } + + throw e; + } finally { + if (after_function) { + after_function(); + } + } + + if (else_function) { + try { + return else_function(result); + } catch (ex) { + if (ex instanceof Core.Patterns.MatchError) { + throw new Error('No Match Found in Else'); + } + + throw ex; + } + } else { + return result; + } +} + +function _with(...args) { + let argsToPass = []; + let successFunction = null; + let elseFunction = null; + + if (typeof args[args.length - 2] === 'function') { + [successFunction, elseFunction] = args.splice(-2); + } else { + successFunction = args.pop(); + } + + for (let i = 0; i < args.length; i++) { + const [pattern, func] = args[i]; + + const result = func(...argsToPass); + + const patternResult = Core.Patterns.match_or_default(pattern, result); + + if (patternResult == null) { + if (elseFunction) { + return elseFunction.call(null, result); + } + return result; + } + + argsToPass = argsToPass.concat(patternResult); + } + + return successFunction(...argsToPass); +} + +function receive(clauses, after) { + console.warn('Receive not supported'); +} + +var SpecialForms = { + _case, + cond, + _for, + _try, + _with, + receive +}; + +// http://erlang.org/doc/man/lists.html +function reverse(list) { + return [...list].reverse(); +} + +function foreach(fun, list) { + list.forEach(x => fun(x)); + + return Symbol.for('ok'); +} + +function duplicate(n, elem) { + const list = []; + + while (list.length < n) { + list.push(elem); + } + + return list; +} + +function flatten(deepList, tail = []) { + const val = deepList.reduce((acc, value) => { + if (Array.isArray(value)) { + return acc.concat(flatten(value)); + } + + return acc.concat(value); + }, []); + + return val.concat(tail); +} + +function foldl(fun, acc0, list) { + return list.reduce((acc, value) => { + return fun(value, acc); + }, acc0); +} + +function foldr(fun, acc0, list) { + return foldl(fun, acc0, reverse(list)); +} + +function keyfind(key, n, tupleList) { + for (const tuple of tupleList) { + if (tuple.get(n - 1) === key) { + return tuple; + } + } + + return false; +} + +function keymember(key, n, tupleList) { + if (keyfind(key, n, tupleList) === false) { + return false; + } + + return true; +} + +function keyreplace(key, n, tupleList, newTuple) { + const newTupleList = [...tupleList]; + + for (let index = 0; index < newTupleList.length; index++) { + if (newTupleList[index].get(n - 1) === key) { + newTupleList[index] = newTuple; + return newTupleList; + } + } + + return newTupleList; +} + +function keysort(n, tupleList) { + const newTupleList = [...tupleList]; + + return newTupleList.sort((a, b) => { + if (a.get(n - 1) < b.get(n - 1)) { + return -1; + } else if (a.get(n - 1) > b.get(n - 1)) { + return 1; + } + + return 0; + }); +} + +function keystore(key, n, tupleList, newTuple) { + const newTupleList = [...tupleList]; + + for (let index = 0; index < newTupleList.length; index++) { + if (newTupleList[index].get(n - 1) === key) { + newTupleList[index] = newTuple; + return newTupleList; + } + } + + return newTupleList.concat(newTuple); +} + +function keydelete(key, n, tupleList) { + const newTupleList = []; + let deleted = false; + + for (let index = 0; index < tupleList.length; index++) { + if (deleted === false && tupleList[index].get(n - 1) === key) { + deleted = true; + } else { + newTupleList.push(tupleList[index]); + } + } + + return newTupleList; +} + +function keytake(key, n, tupleList) { + const result = keyfind(key, n, tupleList); + + if (result !== false) { + return new ErlangTypes.Tuple(result.get(n - 1), result, keydelete(key, n, tupleList)); + } + + return false; +} + +function mapfoldl(fun, acc0, list1) { + const listResult = []; + let accResult = acc0; + + for (const item of list1) { + const tuple = fun(item, accResult); + listResult.push(tuple.get(0)); + accResult = tuple.get(1); + } + + return new ErlangTypes.Tuple(listResult, accResult); +} + +function concat(things) { + return things.map(v => v.toString()).join(); +} + +function map(fun, list) { + return list.map(value => fun(value)); +} + +function filter(pred, list1) { + return list1.filter(x => pred(x)); +} + +function filtermap(fun, list1) { + const list2 = []; + + for (const item of list1) { + const value = fun(item); + + if (value === true) { + list2.push(item); + } else if (value instanceof ErlangTypes.Tuple && value.get(0) === true) { + list2.push(value.get(1)); + } + } + + return list2; +} + +function member(elem, list) { + for (const item of list) { + if (item === elem) { + return true; + } + } + + return false; +} + +function all(pred, list) { + for (const item of list) { + if (pred(item) === false) { + return false; + } + } + + return true; +} + +function any(pred, list) { + for (const item of list) { + if (pred(item) === true) { + return true; + } + } + + return false; +} + +function splitwith(pred, list) { + let switchToList2 = false; + const list1 = []; + const list2 = []; + + for (const item of list) { + if (switchToList2 === true) { + list2.push(item); + } else if (pred(item) === true) { + list1.push(item); + } else { + switchToList2 = true; + list2.push(item); + } + } + + return new ErlangTypes.Tuple(list1, list2); +} + +function sort(...args) { + if (args.length === 1) { + const list2 = [...args[0]]; + return list2.sort(); + } + + const fun = args[0]; + const list2 = [...args[1]]; + + return list2.sort((a, b) => { + const result = fun(a, b); + + if (result === true) { + return -1; + } + + return 1; + }); +} + +var lists = { + reverse, + foreach, + duplicate, + flatten, + foldl, + foldr, + keydelete, + keyfind, + keymember, + keyreplace, + keysort, + keystore, + keytake, + mapfoldl, + concat, + map, + filter, + filtermap, + member, + all, + any, + splitwith, + sort +}; + +// http://erlang.org/doc/man/erlang.html +function atom_to_binary(atom, encoding = Symbol.for('utf8')) { + if (encoding !== Symbol.for('utf8')) { + throw new Error(`unsupported encoding ${encoding}`); + } + + if (atom.__MODULE__) { + return Symbol.keyFor(atom.__MODULE__); + } + + return Symbol.keyFor(atom); +} + +function binary_to_atom(binary, encoding = Symbol.for('utf8')) { + if (encoding !== Symbol.for('utf8')) { + throw new Error(`unsupported encoding ${encoding}`); + } + + return Symbol.for(binary); +} + +function binary_to_existing_atom(binary, encoding = Symbol.for('utf8')) { + return binary_to_atom(binary, encoding); +} + +function list_concatenation(list1, list2) { + return list1.concat(list2); +} + +function list_subtraction(list1, list2) { + const list = [...list1]; + + for (const item of list2) { + const index = list.indexOf(item); + + if (index > -1) { + list.splice(index, 1); + } + } + + return list; +} + +function div(left, right) { + return left / right; +} + +function not(x) { + return !x; +} + +function rem(left, right) { + return left % right; +} + +function band(left, right) { + return left & right; +} + +function bor(left, right) { + return left | right; +} + +function bnot(x) { + return ~x; +} + +function bsl(left, right) { + return left << right; +} + +function bsr(left, right) { + return left >> right; +} + +function bxor(left, right) { + return left ^ right; +} + +function is_atom(value) { + return typeof value === 'symbol' || value instanceof Symbol || value.__MODULE__; +} + +function is_bitstring$1(value) { + return value instanceof ErlangTypes.BitString; +} + +function is_boolean$1(value) { + return typeof value === 'boolean' || value instanceof Boolean; +} + +function is_number$1(value) { + return typeof value === 'number' || value instanceof Number; +} + +function is_float(value) { + return is_number$1(value) && !Number.isInteger(value); +} + +function is_function$1(value) { + return typeof value === 'function' || value instanceof Function; +} + +function is_integer(value) { + return Number.isInteger(value); +} + +function is_list(value) { + return Array.isArray(value); +} + +function is_map$1(value) { + return value instanceof Map; +} + +function is_pid(value) { + return value instanceof ErlangTypes.PID; +} + +function is_port() { + return false; +} + +function is_reference(value) { + return value instanceof ErlangTypes.Reference; +} + +function is_tuple(value) { + return value instanceof ErlangTypes.Tuple; +} + +function is_binary(value) { + return typeof value === 'string' || value instanceof String; +} + +function element(n, tuple) { + return tuple.get(n - 1); +} + +function setelement(index, tuple1, value) { + const tupleData = [...tuple1.values]; + + tupleData[index - 1] = value; + + return new ErlangTypes.Tuple(...tupleData); +} + +function make_tuple(arity, initialValue) { + const list = []; + + for (let i = 0; i < arity; i++) { + list.push(initialValue); + } + + return new ErlangTypes.Tuple(...list); +} + +function insert_element(index, tuple, term) { + const list = [...tuple.values]; + list.splice(index - 1, 0, term); + + return new ErlangTypes.Tuple(...list); +} + +function append_element(tuple, term) { + const list = [...tuple.values]; + list.push(term); + + return new ErlangTypes.Tuple(...list); +} + +function delete_element(index, tuple) { + const list = [...tuple.values]; + list.splice(index - 1, 1); + + return new ErlangTypes.Tuple(...list); +} + +function tuple_to_list(tuple) { + const list = [...tuple.values]; + return list; +} + +function abs(number) { + return Math.abs(number); +} + +function apply(...args) { + if (args.length === 2) { + return args[0].apply(this, ...args[1]); + } + + return args[0][atom_to_binary(args[1])].apply(this, ...args[2]); +} + +function binary_part(binary, start, length) { + return binary.substring(start, start + length); +} + +function bit_size(bitstring) { + return bitstring.bit_size; +} + +function byte_size(bitstring) { + return bitstring.byte_size; +} + +function hd(list) { + return list[0]; +} + +function length(list) { + return list.length; +} + +function make_ref() { + return new ErlangTypes.Reference(); +} + +function map_size(map) { + return map.size; +} + +function max(first, second) { + return Math.max(first, second); +} + +function min(first, second) { + return Math.min(first, second); +} + +function round(number) { + return Math.round(number); +} + +function tl(list) { + return list.slice(1); +} + +function trunc(number) { + return Math.trunc(number); +} + +function tuple_size(tuple) { + return tuple.length; +} + +function binary_to_float(str) { + return parseFloat(str); +} + +function binary_to_integer(str, base = 10) { + return parseInt(str, base); +} + +function process_info(pid, item) { + if (item) { + if (item === Symbol.for('current_stacktrace')) { + return new ErlangTypes.Tuple(item, []); + } + + return new ErlangTypes.Tuple(item, null); + } + + return []; +} + +function iolist_to_binary(ioListOrBinary) { + if (ioListOrBinary === null) { + return ''; + } + + if (is_binary(ioListOrBinary)) { + return ioListOrBinary; + } + + if (is_bitstring$1(ioListOrBinary)) { + return String.fromCodePoint(...ioListOrBinary.value); + } + + const iolistFlattened = lists.flatten(ioListOrBinary); + + const value = iolistFlattened.reduce((acc, current) => { + if (current === null) { + return acc; + } else if (is_integer(current)) { + return acc + String.fromCodePoint(current); + } else if (is_bitstring$1(current)) { + return acc + String.fromCodePoint(...current.value); + } + + return acc + iolist_to_binary(current); + }, ''); + + return value; +} + +function io_size(ioListOrBinary) { + return iolist_to_binary(ioListOrBinary).length; +} + +function integer_to_binary(integer, base = 10) { + return integer.toString(base); +} + +var erlang = { + atom_to_binary, + binary_to_atom, + binary_to_existing_atom, + list_concatenation, + list_subtraction, + div, + not, + rem, + band, + bor, + bsl, + bsr, + bxor, + bnot, + is_bitstring: is_bitstring$1, + is_boolean: is_boolean$1, + is_float, + is_function: is_function$1, + is_integer, + is_list, + is_map: is_map$1, + is_number: is_number$1, + is_pid, + is_port, + is_reference, + is_tuple, + is_atom, + is_binary, + element, + setelement, + make_tuple, + insert_element, + append_element, + delete_element, + tuple_to_list, + abs, + apply, + binary_part, + bit_size, + byte_size, + hd, + length, + make_ref, + map_size, + max, + min, + round, + tl, + trunc, + tuple_size, + binary_to_float, + binary_to_integer, + process_info, + iolist_to_binary, + io_size, + integer_to_binary +}; + +// http://erlang.org/doc/man/maps.html +const OK = Symbol.for('ok'); +const ERROR = Symbol.for('error'); +const BADMAP = Symbol.for('badmap'); +const BADKEY = Symbol.for('badkey'); + +function find(key, map) { + if (erlang.is_map(map) === false) { + return new ErlangTypes.Tuple(BADMAP, map); + } + + const value = map.get(key); + + if (typeof value !== 'undefined') { + return new ErlangTypes.Tuple(OK, value); + } + + return ERROR; +} + +function fold(fun, init, map) { + let acc = init; + + for (const [key, value] of map.entries()) { + acc = fun(key, value, acc); + } + + return acc; +} + +function remove(key, map1) { + if (erlang.is_map(map1) === false) { + return new ErlangTypes.Tuple(BADMAP, map1); + } + + const map2 = new Map(map1); + + map2.delete(key); + + return map2; +} + +function to_list(map) { + if (erlang.is_map(map) === false) { + return new ErlangTypes.Tuple(BADMAP, map); + } + + const list = []; + + for (const [key, value] of map.entries()) { + list.push(new ErlangTypes.Tuple(key, value)); + } + + return list; +} + +function from_list(list) { + return list.reduce((acc, item) => { + const [key, value] = item; + acc.set(key, value); + + return acc; + }, new Map()); +} + +function keys(map) { + if (erlang.is_map(map) === false) { + return new ErlangTypes.Tuple(BADMAP, map); + } + + return Array.from(map.keys()); +} + +function values$1(map) { + if (erlang.is_map(map) === false) { + return new ErlangTypes.Tuple(BADMAP, map); + } + + return Array.from(map.values()); +} + +function is_key(key, map) { + return map.has(key); +} + +function put(key, value, map1) { + if (erlang.is_map(map1) === false) { + return new ErlangTypes.Tuple(BADMAP, map1); + } + + const map2 = new Map(map1); + map2.set(key, value); + + return map2; +} + +function merge(map1, map2) { + if (erlang.is_map(map1) === false) { + return new ErlangTypes.Tuple(BADMAP, map1); + } + + if (erlang.is_map(map2) === false) { + return new ErlangTypes.Tuple(BADMAP, map2); + } + + return new Map([...map1, ...map2]); +} + +function update(key, value, map1) { + if (erlang.is_map(map1) === false) { + return new ErlangTypes.Tuple(BADMAP, map1); + } + + if (is_key(key, map1) === false) { + return new ErlangTypes.Tuple(BADKEY, key); + } + + return new Map([...map1, [key, value]]); +} + +function get(...args) { + const key = args[0]; + const map = args[1]; + + if (erlang.is_map(map) === false) { + return new ErlangTypes.Tuple(BADMAP, map); + } + + if (is_key(key)) { + return map.get(key); + } + + if (args.length === 3) { + return args[2]; + } + + return new ErlangTypes.Tuple(BADKEY, key); +} + +function take(key, map1) { + if (erlang.is_map(map1) === false) { + return new ErlangTypes.Tuple(BADMAP, map1); + } + + if (!is_key(key)) { + return ERROR; + } + + const value = map1.get(key); + const map2 = new Map(map1); + map2.delete(key); + + return new ErlangTypes.Tuple(value, map2); +} + +var maps = { + find, + fold, + remove, + to_list, + from_list, + keys, + values: values$1, + is_key, + put, + merge, + update, + get, + take +}; + +function warn(message) { + const messageString = message.join(''); + console.warn(`warning: ${messageString}`); + + return Symbol.for('ok'); +} + +var elixir_errors = { + warn +}; + +function put_chars(ioDevice, charData) { + const dataToWrite = erlang.iolist_to_binary(charData); + + if (ioDevice === Symbol.for('stderr')) { + console.error(dataToWrite); + } else { + console.log(dataToWrite); + } + + return Symbol.for('ok'); +} + +var io = { + put_chars +}; + +function copy(subject, n = 1) { + return subject.repeat(n); +} + +var binary = { + copy +}; + +function get_key(key) { + let real_key = key; + + if (__elixirscript_names__.has(key)) { + real_key = __elixirscript_names__.get(key); + } + + if (__elixirscript_store__.has(real_key)) { + return real_key; + } + + throw new Error(`Key ${real_key} not found`); +} + +function create(value, name = null) { + const key = new Core.PID(); + + if (name !== null) { + __elixirscript_names__.set(name, key); + } + + return __elixirscript_store__.set(key, value); +} + +function update$1(key, value) { + const real_key = get_key(key); + return __elixirscript_store__.set(real_key, value); +} + +function read(key) { + const real_key = get_key(key); + return __elixirscript_store__.get(real_key); +} + +function remove$1(key) { + const real_key = get_key(key); + return __elixirscript_store__.delete(real_key); +} + +var Store = { + create, + update: update$1, + read, + remove: remove$1 +}; + +class Integer {} +class Float {} + +function get_global() { + if (typeof self !== 'undefined') { + return self; + } else if (typeof window !== 'undefined') { + return window; + } else if (typeof global !== 'undefined') { + return global; + } + + console.warn('No global state found'); + return null; +} + +const globalState = get_global(); + +globalState.__elixirscript_store__ = new Map(); +globalState.__elixirscript_names__ = new Map(); + +var Core = { + Tuple: ErlangTypes.Tuple, + PID: ErlangTypes.PID, + BitString: ErlangTypes.BitString, + Patterns, + Integer, + Float, + Functions, + SpecialForms, + Store, + global: globalState, + erlang, + maps, + lists, + elixir_errors, + io, + binary +}; + +var elixir = { + Core +}; + +return elixir; + +}()); diff --git a/src/javascript/lib/core/erlang_compat/io.js b/src/javascript/lib/core/erlang_compat/io.js index d01c42c6..5d297921 100644 --- a/src/javascript/lib/core/erlang_compat/io.js +++ b/src/javascript/lib/core/erlang_compat/io.js @@ -1,7 +1,7 @@ import erlang from './erlang'; function put_chars(ioDevice, charData) { - let dataToWrite = erlang.iolist_to_binary(charData); + const dataToWrite = erlang.iolist_to_binary(charData); if (ioDevice === Symbol.for('stderr')) { console.error(dataToWrite); diff --git a/src/javascript/lib/core/protocol.js b/src/javascript/lib/core/protocol.js index ac292a81..1b508e29 100644 --- a/src/javascript/lib/core/protocol.js +++ b/src/javascript/lib/core/protocol.js @@ -31,6 +31,7 @@ class Protocol { fun = this.registry.get(Core.BitString)[funName]; } else if ( thing && + thing instanceof Map && thing.has(Symbol.for('__struct__')) && this.hasImplementation(thing) ) { @@ -72,7 +73,11 @@ class Protocol { thing === Core.BitString ) { return this.registry.has(thing); - } else if (thing && thing.has(Symbol.for('__struct__'))) { + } else if ( + thing && + thing instanceof Map && + thing.has(Symbol.for('__struct__')) + ) { return this.registry.has(thing.get(Symbol.for('__struct__')).__MODULE__); } diff --git a/yarn.lock b/yarn.lock index ebbc6518..66443a82 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3678,9 +3678,9 @@ table@^4.0.1: slice-ansi "0.0.4" string-width "^2.0.0" -tailored@^2.6.3: - version "2.6.3" - resolved "https://registry.yarnpkg.com/tailored/-/tailored-2.6.3.tgz#27d1069dd3f5b2f2009d6437efcb26c595bccfda" +tailored@^2.6.4: + version "2.6.4" + resolved "https://registry.yarnpkg.com/tailored/-/tailored-2.6.4.tgz#c81bdfe8b50c35298ed87c684d493467a87182c5" dependencies: erlang-types "^1.0.1" From 82824a8bfa38d0e2b5f6e5eb132917945259a4ff Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Sat, 29 Jul 2017 11:03:01 -0500 Subject: [PATCH 638/860] Add tail call tail call optimization This works by using a trampoline function defined in ElixirScript.Core.Functions JavaScript module. --- .../passes/translate/function.ex | 97 +- priv/build/iife/ElixirScript.Core.js | 2565 +---------------- .../lib/core/erlang_compat/erlang.js | 4 + src/javascript/lib/core/functions.js | 20 +- test/compiler_test.exs | 6 +- test/passes/translate/form_test.exs | 5 +- 6 files changed, 129 insertions(+), 2568 deletions(-) diff --git a/lib/elixir_script/passes/translate/function.ex b/lib/elixir_script/passes/translate/function.ex index fe67824c..b6c70245 100644 --- a/lib/elixir_script/passes/translate/function.ex +++ b/lib/elixir_script/passes/translate/function.ex @@ -31,7 +31,8 @@ defmodule ElixirScript.Translate.Function do :let ) - function_dec = J.arrow_function_expression( + function_recur_dec = J.function_declaration( + J.identifier("recur"), [J.rest_element(J.identifier("__function_args__"))], [], J.block_statement([ @@ -49,6 +50,17 @@ defmodule ElixirScript.Translate.Function do ]) ) + function_dec = J.arrow_function_expression( + [J.rest_element(J.identifier("__function_args__"))], + [], + J.block_statement([ + function_recur_dec, + J.return_statement( + trampoline() + ) + ]) + ) + { function_dec, state } end @@ -66,8 +78,8 @@ defmodule ElixirScript.Translate.Function do :let ) - function_dec = J.function_declaration( - ElixirScript.Translate.Identifier.make_function_name(name), + function_recur_dec = J.function_declaration( + J.identifier("recur"), [J.rest_element(J.identifier("__function_args__"))], [], J.block_statement([ @@ -85,6 +97,18 @@ defmodule ElixirScript.Translate.Function do ]) ) + function_dec = J.function_declaration( + ElixirScript.Translate.Identifier.make_function_name(name), + [J.rest_element(J.identifier("__function_args__"))], + [], + J.block_statement([ + function_recur_dec, + J.return_statement( + trampoline() + ) + ]) + ) + { function_dec, state } end @@ -132,6 +156,7 @@ defmodule ElixirScript.Translate.Function do body = body |> Clause.return_last_statement + |> update_last_call(state) declarator = J.variable_declarator( J.array_expression(params), @@ -168,4 +193,70 @@ defmodule ElixirScript.Translate.Function do {ast, state} end + + defp update_last_call(clause_body, %{function: {name, _}}) do + last_item = List.last(clause_body) + function_name = ElixirScript.Translate.Identifier.make_function_name(name) + + case last_item do + %ESTree.ReturnStatement{ argument: %ESTree.CallExpression{ callee: ^function_name, arguments: arguments } } -> + new_last_item = J.return_statement( + recurse( + recur_bind(arguments) + ) + ) + + List.replace_at(clause_body, length(clause_body) - 1, new_last_item) + _ -> + clause_body + end + end + + defp recur_bind(args) do + J.call_expression( + J.member_expression( + J.identifier("recur"), + J.identifier("bind") + ), + [J.identifier("null")] ++ args + ) + end + + defp recurse(func) do + J.new_expression( + J.member_expression( + J.member_expression( + J.identifier("ElixirScript"), + J.member_expression( + J.identifier("Core"), + J.identifier("Functions") + ) + ), + J.identifier("Recurse") + ), + [ + func + ] + ) + end + + defp trampoline() do + J.call_expression( + J.member_expression( + J.member_expression( + J.identifier("ElixirScript"), + J.member_expression( + J.identifier("Core"), + J.identifier("Functions") + ) + ), + J.identifier("trampoline") + ), + [ + recurse( + recur_bind([J.rest_element(J.identifier("__function_args__"))]) + ) + ] + ) + end end diff --git a/priv/build/iife/ElixirScript.Core.js b/priv/build/iife/ElixirScript.Core.js index 80caf094..0242e617 100644 --- a/priv/build/iife/ElixirScript.Core.js +++ b/priv/build/iife/ElixirScript.Core.js @@ -1,2559 +1,6 @@ -var ElixirScript = (function () { -'use strict'; - -/* @flow */ - -class Variable { - constructor(name = null, default_value = Symbol.for('tailored.no_value')) { - this.name = name; - this.default_value = default_value; - } -} - -class Wildcard { - constructor() {} -} - -class StartsWith { - constructor(prefix) { - this.prefix = prefix; - } -} - -class Capture { - constructor(value) { - this.value = value; - } -} - -class HeadTail { - constructor(head, tail) { - this.head = head; - this.tail = tail; - } -} - -class Type { - constructor(type, objPattern = {}) { - this.type = type; - this.objPattern = objPattern; - } -} - -class Bound { - constructor(value) { - this.value = value; - } -} - -class BitStringMatch { - constructor(...values) { - this.values = values; - } - - length() { - return values.length; - } - - bit_size() { - return this.byte_size() * 8; - } - - byte_size() { - let s = 0; - - for (let val of this.values) { - s = s + val.unit * val.size / 8; - } - - return s; - } - - getValue(index) { - return this.values(index); - } - - getSizeOfValue(index) { - let val = this.getValue(index); - return val.unit * val.size; - } - - getTypeOfValue(index) { - return this.getValue(index).type; - } -} - -class NamedVariableResult { - constructor(name, value) { - this.name = name; - this.value = value; - } -} - -function variable(name = null, default_value = Symbol.for('tailored.no_value')) { - return new Variable(name, default_value); -} - -function wildcard() { - return new Wildcard(); -} - -function startsWith(prefix) { - return new StartsWith(prefix); -} - -function capture(value) { - return new Capture(value); -} - -function headTail(head, tail) { - return new HeadTail(head, tail); -} - -function type(type, objPattern = {}) { - return new Type(type, objPattern); -} - -function bound(value) { - return new Bound(value); -} - -function bitStringMatch(...values) { - return new BitStringMatch(...values); -} - -function namedVariableResult(name, value) { - return new NamedVariableResult(name, value); -} - -/* @flow */ - -function is_number(value) { - return typeof value === 'number'; -} - -function is_string(value) { - return typeof value === 'string'; -} - -function is_boolean(value) { - return typeof value === 'boolean'; -} - -function is_symbol(value) { - return typeof value === 'symbol'; -} - -function is_object(value) { - return typeof value === 'object'; -} - -function is_variable(value) { - return value instanceof Variable; -} - -function is_null(value) { - return value === null; -} - -function is_array(value) { - return Array.isArray(value); -} - -function is_function(value) { - return Object.prototype.toString.call(value) == '[object Function]'; -} - -function is_map(value) { - return value instanceof Map; -} - -class Tuple { - constructor(...args) { - this.values = Object.freeze(args); - this.length = this.values.length; - } - - get(index) { - return this.values[index]; - } - - count() { - return this.values.length; - } - - [Symbol.iterator]() { - return this.values[Symbol.iterator](); - } - - toString() { - let i, - s = ''; - for (i = 0; i < this.values.length; i++) { - if (s !== '') { - s += ', '; - } - - const stringToAppend = this.values[i] ? this.values[i].toString() : ''; - - s += stringToAppend; - } - - return '{' + s + '}'; - } - - put_elem(index, elem) { - if (index === this.length) { - let new_values = this.values.concat([elem]); - return new Tuple(...new_values); - } - - let new_values = this.values.concat([]); - new_values.splice(index, 0, elem); - return new Tuple(...new_values); - } - - remove_elem(index) { - let new_values = this.values.concat([]); - new_values.splice(index, 1); - return new Tuple(...new_values); - } -} - -let process_counter = -1; - -class PID { - constructor() { - process_counter = process_counter + 1; - this.id = process_counter; - } - - toString() { - return 'PID#<0.' + this.id + '.0>'; - } -} - -let ref_counter = -1; - -class Reference { - constructor() { - ref_counter = ref_counter + 1; - this.id = ref_counter; - this.ref = Symbol(); - } - - toString() { - return 'Ref#<0.0.0.' + this.id + '>'; - } -} - -class BitString$1 { - constructor(...args) { - this.value = Object.freeze(this.process(args)); - this.length = this.value.length; - this.bit_size = this.length * 8; - this.byte_size = this.length; - } - - get(index) { - return this.value[index]; - } - - count() { - return this.value.length; - } - - slice(start, end = null) { - let s = this.value.slice(start, end); - let ms = s.map(elem => BitString$1.integer(elem)); - return new BitString$1(...ms); - } - - [Symbol.iterator]() { - return this.value[Symbol.iterator](); - } - - toString() { - var i, - s = ''; - for (i = 0; i < this.count(); i++) { - if (s !== '') { - s += ', '; - } - s += this.get(i).toString(); - } - - return '<<' + s + '>>'; - } - - process(bitStringParts) { - let processed_values = []; - - var i; - for (i = 0; i < bitStringParts.length; i++) { - let processed_value = this['process_' + bitStringParts[i].type](bitStringParts[i]); - - for (let attr of bitStringParts[i].attributes) { - processed_value = this['process_' + attr](processed_value); - } - - processed_values = processed_values.concat(processed_value); - } - - return processed_values; - } - - process_integer(value) { - return value.value; - } - - process_float(value) { - if (value.size === 64) { - return BitString$1.float64ToBytes(value.value); - } else if (value.size === 32) { - return BitString$1.float32ToBytes(value.value); - } - - throw new Error('Invalid size for float'); - } - - process_bitstring(value) { - return value.value.value; - } - - process_binary(value) { - return BitString$1.toUTF8Array(value.value); - } - - process_utf8(value) { - return BitString$1.toUTF8Array(value.value); - } - - process_utf16(value) { - return BitString$1.toUTF16Array(value.value); - } - - process_utf32(value) { - return BitString$1.toUTF32Array(value.value); - } - - process_signed(value) { - return new Uint8Array([value])[0]; - } - - process_unsigned(value) { - return value; - } - - process_native(value) { - return value; - } - - process_big(value) { - return value; - } - - process_little(value) { - return value.reverse(); - } - - process_size(value) { - return value; - } - - process_unit(value) { - return value; - } - - static integer(value) { - return BitString$1.wrap(value, { type: 'integer', unit: 1, size: 8 }); - } - - static float(value) { - return BitString$1.wrap(value, { type: 'float', unit: 1, size: 64 }); - } - - static bitstring(value) { - return BitString$1.wrap(value, { - type: 'bitstring', - unit: 1, - size: value.bit_size - }); - } - - static bits(value) { - return BitString$1.bitstring(value); - } - - static binary(value) { - return BitString$1.wrap(value, { - type: 'binary', - unit: 8, - size: value.length - }); - } - - static bytes(value) { - return BitString$1.binary(value); - } - - static utf8(value) { - return BitString$1.wrap(value, { type: 'utf8', unit: 1, size: value.length }); - } - - static utf16(value) { - return BitString$1.wrap(value, { - type: 'utf16', - unit: 1, - size: value.length * 2 - }); - } - - static utf32(value) { - return BitString$1.wrap(value, { - type: 'utf32', - unit: 1, - size: value.length * 4 - }); - } - - static signed(value) { - return BitString$1.wrap(value, {}, 'signed'); - } - - static unsigned(value) { - return BitString$1.wrap(value, {}, 'unsigned'); - } - - static native(value) { - return BitString$1.wrap(value, {}, 'native'); - } - - static big(value) { - return BitString$1.wrap(value, {}, 'big'); - } - - static little(value) { - return BitString$1.wrap(value, {}, 'little'); - } - - static size(value, count) { - return BitString$1.wrap(value, { size: count }); - } - - static unit(value, count) { - return BitString$1.wrap(value, { unit: count }); - } - - static wrap(value, opt, new_attribute = null) { - let the_value = value; - - if (!(value instanceof Object)) { - the_value = { value: value, attributes: [] }; - } - - the_value = Object.assign(the_value, opt); - - if (new_attribute) { - the_value.attributes.push(new_attribute); - } - - return the_value; - } - - static toUTF8Array(str) { - var utf8 = []; - for (var i = 0; i < str.length; i++) { - var charcode = str.charCodeAt(i); - if (charcode < 0x80) { - utf8.push(charcode); - } else if (charcode < 0x800) { - utf8.push(0xc0 | charcode >> 6, 0x80 | charcode & 0x3f); - } else if (charcode < 0xd800 || charcode >= 0xe000) { - utf8.push(0xe0 | charcode >> 12, 0x80 | charcode >> 6 & 0x3f, 0x80 | charcode & 0x3f); - } else { - // surrogate pair - i++; - // UTF-16 encodes 0x10000-0x10FFFF by - // subtracting 0x10000 and splitting the - // 20 bits of 0x0-0xFFFFF into two halves - charcode = 0x10000 + ((charcode & 0x3ff) << 10 | str.charCodeAt(i) & 0x3ff); - utf8.push(0xf0 | charcode >> 18, 0x80 | charcode >> 12 & 0x3f, 0x80 | charcode >> 6 & 0x3f, 0x80 | charcode & 0x3f); - } - } - return utf8; - } - - static toUTF16Array(str) { - var utf16 = []; - for (var i = 0; i < str.length; i++) { - var codePoint = str.codePointAt(i); - - if (codePoint <= 255) { - utf16.push(0); - utf16.push(codePoint); - } else { - utf16.push(codePoint >> 8 & 0xff); - utf16.push(codePoint & 0xff); - } - } - return utf16; - } - - static toUTF32Array(str) { - var utf32 = []; - for (var i = 0; i < str.length; i++) { - var codePoint = str.codePointAt(i); - - if (codePoint <= 255) { - utf32.push(0); - utf32.push(0); - utf32.push(0); - utf32.push(codePoint); - } else { - utf32.push(0); - utf32.push(0); - utf32.push(codePoint >> 8 & 0xff); - utf32.push(codePoint & 0xff); - } - } - return utf32; - } - - //http://stackoverflow.com/questions/2003493/javascript-float-from-to-bits - static float32ToBytes(f) { - var bytes = []; - - var buf = new ArrayBuffer(4); - new Float32Array(buf)[0] = f; - - let intVersion = new Uint32Array(buf)[0]; - - bytes.push(intVersion >> 24 & 0xff); - bytes.push(intVersion >> 16 & 0xff); - bytes.push(intVersion >> 8 & 0xff); - bytes.push(intVersion & 0xff); - - return bytes; - } - - static float64ToBytes(f) { - var bytes = []; - - var buf = new ArrayBuffer(8); - new Float64Array(buf)[0] = f; - - var intVersion1 = new Uint32Array(buf)[0]; - var intVersion2 = new Uint32Array(buf)[1]; - - bytes.push(intVersion2 >> 24 & 0xff); - bytes.push(intVersion2 >> 16 & 0xff); - bytes.push(intVersion2 >> 8 & 0xff); - bytes.push(intVersion2 & 0xff); - - bytes.push(intVersion1 >> 24 & 0xff); - bytes.push(intVersion1 >> 16 & 0xff); - bytes.push(intVersion1 >> 8 & 0xff); - bytes.push(intVersion1 & 0xff); - - return bytes; - } -} - -var ErlangTypes = { - Tuple, - PID, - Reference, - BitString: BitString$1 -}; - -/* @flow */ - -const BitString = ErlangTypes.BitString; - -function resolveSymbol(pattern) { - return function (value) { - return is_symbol(value) && value === pattern; - }; -} - -function resolveString(pattern) { - return function (value) { - return is_string(value) && value === pattern; - }; -} - -function resolveNumber(pattern) { - return function (value) { - return is_number(value) && value === pattern; - }; -} - -function resolveBoolean(pattern) { - return function (value) { - return is_boolean(value) && value === pattern; - }; -} - -function resolveFunction(pattern) { - return function (value) { - return is_function(value) && value === pattern; - }; -} - -function resolveNull(pattern) { - return function (value) { - return is_null(value); - }; -} - -function resolveBound(pattern) { - return function (value, args) { - if (typeof value === typeof pattern.value && value === pattern.value) { - return true; - } - - return false; - }; -} - -function resolveWildcard() { - return function () { - return true; - }; -} - -function resolveVariable(pattern) { - return function (value, args) { - if (pattern.name === null) { - args.push(value); - } else if (!pattern.name.startsWith('_')) { - args.push(namedVariableResult(pattern.name, value)); - } - - return true; - }; -} - -function resolveHeadTail(pattern) { - const headMatches = buildMatch(pattern.head); - const tailMatches = buildMatch(pattern.tail); - - return function (value, args) { - if (!is_array(value) || value.length === 0) { - return false; - } - - const head = value[0]; - const tail = value.slice(1); - - if (headMatches(head, args) && tailMatches(tail, args)) { - return true; - } - - return false; - }; -} - -function resolveCapture(pattern) { - const matches = buildMatch(pattern.value); - - return function (value, args) { - if (matches(value, args)) { - args.push(value); - return true; - } - - return false; - }; -} - -function resolveStartsWith(pattern) { - const prefix = pattern.prefix; - - return function (value, args) { - if (is_string(value) && value.startsWith(prefix)) { - args.push(value.substring(prefix.length)); - return true; - } - - return false; - }; -} - -function resolveType(pattern) { - return function (value, args) { - if (value instanceof pattern.type) { - const matches = buildMatch(pattern.objPattern); - return matches(value, args); - } - - return false; - }; -} - -function resolveArray(pattern) { - const matches = pattern.map(x => buildMatch(x)); - - return function (value, args) { - if (!is_array(value) || value.length != pattern.length) { - return false; - } - - return value.every(function (v, i) { - return matches[i](value[i], args); - }); - }; -} - -function resolveMap(pattern) { - let matches = new Map(); - - const keys = Array.from(pattern.keys()); - - for (let key of keys) { - matches.set(key, buildMatch(pattern.get(key))); - } - - return function (value, args) { - if (!is_map(value) || pattern.size > value.size) { - return false; - } - - for (let key of keys) { - if (!value.has(key) || !matches.get(key)(value.get(key), args)) { - return false; - } - } - - return true; - }; -} - -function resolveObject(pattern) { - let matches = {}; - - const keys = Object.keys(pattern).concat(Object.getOwnPropertySymbols(pattern)); - - for (let key of keys) { - matches[key] = buildMatch(pattern[key]); - } - - return function (value, args) { - if (!is_object(value) || pattern.length > value.length) { - return false; - } - - for (let key of keys) { - if (!(key in value) || !matches[key](value[key], args)) { - return false; - } - } - - return true; - }; -} - -function resolveBitString(pattern) { - let patternBitString = []; - - for (let bitstringMatchPart of pattern.values) { - if (is_variable(bitstringMatchPart.value)) { - let size = getSize(bitstringMatchPart.unit, bitstringMatchPart.size); - fillArray(patternBitString, size); - } else { - patternBitString = patternBitString.concat(new BitString(bitstringMatchPart).value); - } - } - - let patternValues = pattern.values; - - return function (value, args) { - let bsValue = null; - - if (!is_string(value) && !(value instanceof BitString)) { - return false; - } - - if (is_string(value)) { - bsValue = new BitString(BitString.binary(value)); - } else { - bsValue = value; - } - - let beginningIndex = 0; - - for (let i = 0; i < patternValues.length; i++) { - let bitstringMatchPart = patternValues[i]; - - if (is_variable(bitstringMatchPart.value) && bitstringMatchPart.type == 'binary' && bitstringMatchPart.size === undefined && i < patternValues.length - 1) { - throw new Error('a binary field without size is only allowed at the end of a binary pattern'); - } - - let size = 0; - let bsValueArrayPart = []; - let patternBitStringArrayPart = []; - size = getSize(bitstringMatchPart.unit, bitstringMatchPart.size); - - if (i === patternValues.length - 1) { - bsValueArrayPart = bsValue.value.slice(beginningIndex); - patternBitStringArrayPart = patternBitString.slice(beginningIndex); - } else { - bsValueArrayPart = bsValue.value.slice(beginningIndex, beginningIndex + size); - patternBitStringArrayPart = patternBitString.slice(beginningIndex, beginningIndex + size); - } - - if (is_variable(bitstringMatchPart.value)) { - switch (bitstringMatchPart.type) { - case 'integer': - if (bitstringMatchPart.attributes && bitstringMatchPart.attributes.indexOf('signed') != -1) { - args.push(new Int8Array([bsValueArrayPart[0]])[0]); - } else { - args.push(new Uint8Array([bsValueArrayPart[0]])[0]); - } - break; - - case 'float': - if (size === 64) { - args.push(Float64Array.from(bsValueArrayPart)[0]); - } else if (size === 32) { - args.push(Float32Array.from(bsValueArrayPart)[0]); - } else { - return false; - } - break; - - case 'bitstring': - args.push(createBitString(bsValueArrayPart)); - break; - - case 'binary': - args.push(String.fromCharCode.apply(null, new Uint8Array(bsValueArrayPart))); - break; - - case 'utf8': - args.push(String.fromCharCode.apply(null, new Uint8Array(bsValueArrayPart))); - break; - - case 'utf16': - args.push(String.fromCharCode.apply(null, new Uint16Array(bsValueArrayPart))); - break; - - case 'utf32': - args.push(String.fromCharCode.apply(null, new Uint32Array(bsValueArrayPart))); - break; - - default: - return false; - } - } else if (!arraysEqual(bsValueArrayPart, patternBitStringArrayPart)) { - return false; - } - - beginningIndex = beginningIndex + size; - } - - return true; - }; -} - -function getSize(unit, size) { - return unit * size / 8; -} - -function arraysEqual(a, b) { - if (a === b) return true; - if (a == null || b == null) return false; - if (a.length != b.length) return false; - - for (var i = 0; i < a.length; ++i) { - if (a[i] !== b[i]) return false; - } - - return true; -} - -function fillArray(arr, num) { - for (let i = 0; i < num; i++) { - arr.push(0); - } -} - -function createBitString(arr) { - let integerParts = arr.map(elem => BitString.integer(elem)); - return new BitString(...integerParts); -} - -function resolveNoMatch() { - return function () { - return false; - }; -} - -const patternMap = new Map(); -patternMap.set(Variable.prototype, resolveVariable); -patternMap.set(Wildcard.prototype, resolveWildcard); -patternMap.set(HeadTail.prototype, resolveHeadTail); -patternMap.set(StartsWith.prototype, resolveStartsWith); -patternMap.set(Capture.prototype, resolveCapture); -patternMap.set(Bound.prototype, resolveBound); -patternMap.set(Type.prototype, resolveType); -patternMap.set(BitStringMatch.prototype, resolveBitString); -patternMap.set(Number.prototype, resolveNumber); -patternMap.set(Symbol.prototype, resolveSymbol); -patternMap.set(Map.prototype, resolveMap); -patternMap.set(Array.prototype, resolveArray); -patternMap.set(String.prototype, resolveString); -patternMap.set(Boolean.prototype, resolveBoolean); -patternMap.set(Function.prototype, resolveFunction); -patternMap.set(Object.prototype, resolveObject); - -function buildMatch(pattern) { - if (pattern === null) { - return resolveNull(pattern); - } - - if (typeof pattern === 'undefined') { - return resolveWildcard(pattern); - } - - const type$$1 = pattern.constructor.prototype; - const resolver = patternMap.get(type$$1); - - if (resolver) { - return resolver(pattern); - } - - if (typeof pattern === 'object') { - return resolveObject(pattern); - } - - return resolveNoMatch(); -} - -class MatchError extends Error { - constructor(arg) { - super(); - - if (typeof arg === 'symbol') { - this.message = 'No match for: ' + arg.toString(); - } else if (Array.isArray(arg)) { - let mappedValues = arg.map(x => { - if (x === null) { - return 'null'; - } else if (typeof x === 'undefined') { - return 'undefined'; - } - - return x.toString(); - }); - - this.message = 'No match for: ' + mappedValues; - } else { - this.message = 'No match for: ' + arg; - } - - this.stack = new Error().stack; - this.name = this.constructor.name; - } -} - -class Clause { - constructor(pattern, fn, guard = () => true) { - this.pattern = buildMatch(pattern); - this.arity = pattern.length; - this.optionals = getOptionalValues(pattern); - this.fn = fn; - this.guard = guard; - } -} - -function clause(pattern, fn, guard = () => true) { - return new Clause(pattern, fn, guard); -} - - - -function defmatch(...clauses) { - const arities = getArityMap(clauses); - - return function (...args) { - let [funcToCall, params] = findMatchingFunction(args, arities); - return funcToCall.apply(this, params); - }; -} - -function defmatchgen(...clauses) { - const arities = getArityMap(clauses); - - return function* (...args) { - let [funcToCall, params] = findMatchingFunction(args, arities); - return yield* funcToCall.apply(this, params); - }; -} - -function defmatchGen(...args) { - return defmatchgen(...args); -} - -function defmatchAsync(...clauses) { - const arities = getArityMap(clauses); - - return async function (...args) { - if (arities.has(args.length)) { - const arityClauses = arities.get(args.length); - - let funcToCall = null; - let params = null; - for (let processedClause of arityClauses) { - let result = []; - args = fillInOptionalValues(args, processedClause.arity, processedClause.optionals); - - const doesMatch = processedClause.pattern(args, result); - const [filteredResult, allNamesMatch] = checkNamedVariables(result); - - if (doesMatch && allNamesMatch && (await processedClause.guard.apply(this, result))) { - funcToCall = processedClause.fn; - params = result; - break; - } - } - - if (!funcToCall) { - console.error('No match for:', args); - throw new MatchError(args); - } - - return funcToCall.apply(this, params); - } else { - console.error('Arity of', args.length, 'not found. No match for:', args); - throw new MatchError(args); - } - }; -} - -function findMatchingFunction(args, arities) { - if (arities.has(args.length)) { - const arityClauses = arities.get(args.length); - - let funcToCall = null; - let params = null; - for (let processedClause of arityClauses) { - let result = []; - args = fillInOptionalValues(args, processedClause.arity, processedClause.optionals); - - const doesMatch = processedClause.pattern(args, result); - const [filteredResult, allNamesMatch] = checkNamedVariables(result); - - if (doesMatch && allNamesMatch && processedClause.guard.apply(this, filteredResult)) { - funcToCall = processedClause.fn; - params = filteredResult; - break; - } - } - - if (!funcToCall) { - console.error('No match for:', args); - throw new MatchError(args); - } - - return [funcToCall, params]; - } else { - console.error('Arity of', args.length, 'not found. No match for:', args); - throw new MatchError(args); - } -} - -function getArityMap(clauses) { - let map = new Map(); - - for (const clause of clauses) { - const range = getArityRange(clause); - - for (const arity of range) { - let arityClauses = []; - - if (map.has(arity)) { - arityClauses = map.get(arity); - } - - arityClauses.push(clause); - map.set(arity, arityClauses); - } - } - - return map; -} - -function getArityRange(clause) { - const min = clause.arity - clause.optionals.length; - const max = clause.arity; - - let range = [min]; - - while (range[range.length - 1] != max) { - range.push(range[range.length - 1] + 1); - } - - return range; -} - -function getOptionalValues(pattern) { - let optionals = []; - - for (let i = 0; i < pattern.length; i++) { - if (pattern[i] instanceof Variable && pattern[i].default_value != Symbol.for('tailored.no_value')) { - optionals.push([i, pattern[i].default_value]); - } - } - - return optionals; -} - -function fillInOptionalValues(args, arity, optionals) { - if (args.length === arity || optionals.length === 0) { - return args; - } - - if (args.length + optionals.length < arity) { - return args; - } - - let numberOfOptionalsToFill = arity - args.length; - let optionalsToRemove = optionals.length - numberOfOptionalsToFill; - - let optionalsToUse = optionals.slice(optionalsToRemove); - - for (let [index, value] of optionalsToUse) { - args.splice(index, 0, value); - if (args.length === arity) { - break; - } - } - - return args; -} - -function match(pattern, expr, guard = () => true) { - let result = []; - let processedPattern = buildMatch(pattern); - const doesMatch = processedPattern(expr, result); - const [filteredResult, allNamesMatch] = checkNamedVariables(result); - - if (doesMatch && allNamesMatch && guard.apply(this, filteredResult)) { - return filteredResult; - } else { - console.error('No match for:', expr); - throw new MatchError(expr); - } -} - -function checkNamedVariables(results) { - const namesMap = {}; - const filteredResults = []; - - for (let i = 0; i < results.length; i++) { - const current = results[i]; - if (current instanceof NamedVariableResult) { - if (namesMap[current.name] && namesMap[current.name] !== current.value) { - return [results, false]; - } else if (namesMap[current.name] && namesMap[current.name] === current.value) { - filteredResults.push(current.value); - } else { - namesMap[current.name] = current.value; - filteredResults.push(current.value); - } - } else { - filteredResults.push(current); - } - } - - return [filteredResults, true]; -} - -function match_or_default(pattern, expr, guard = () => true, default_value = null) { - let result = []; - let processedPattern = buildMatch(pattern); - const doesMatch = processedPattern(expr, result); - const [filteredResult, allNamesMatch] = checkNamedVariables(result); - - if (doesMatch && allNamesMatch && guard.apply(this, filteredResult)) { - return filteredResult; - } else { - return default_value; - } -} - -const NO_MATCH = Symbol(); - -function bitstring_generator(pattern, bitstring) { - return function () { - let returnResult = []; - let bsSlice = bitstring.slice(0, pattern.byte_size()); - let i = 1; - - while (bsSlice.byte_size == pattern.byte_size()) { - const result = match_or_default(pattern, bsSlice, () => true, NO_MATCH); - - if (result != NO_MATCH) { - const [value] = result; - returnResult.push(result); - } - - bsSlice = bitstring.slice(pattern.byte_size() * i, pattern.byte_size() * (i + 1)); - - i++; - } - - return returnResult; - }; -} - -function list_generator(pattern, list) { - return function () { - let returnResult = []; - for (let i of list) { - const result = match_or_default(pattern, i, () => true, NO_MATCH); - if (result != NO_MATCH) { - const [value] = result; - returnResult.push(value); - } - } - - return returnResult; - }; -} - -function list_comprehension(expression, generators) { - const generatedValues = run_generators(generators.pop()(), generators); - - let result = []; - - for (let value of generatedValues) { - if (expression.guard.apply(this, value)) { - result.push(expression.fn.apply(this, value)); - } - } - - return result; -} - -function run_generators(generator, generators) { - if (generators.length == 0) { - return generator.map(x => { - if (Array.isArray(x)) { - return x; - } else { - return [x]; - } - }); - } else { - const list = generators.pop(); - - let next_gen = []; - for (let j of list()) { - for (let i of generator) { - next_gen.push([j].concat(i)); - } - } - - return run_generators(next_gen, generators); - } -} - -function bitstring_comprehension(expression, generators) { - const generatedValues = run_generators(generators.pop()(), generators); - - let result = []; - - for (let value of generatedValues) { - if (expression.guard.apply(this, value)) { - result.push(expression.fn.apply(this, value)); - } - } - - result = result.map(x => ErlangTypes.BitString.integer(x)); - return new ErlangTypes.BitString(...result); -} - -var Patterns = { - defmatch, - match, - MatchError, - variable, - wildcard, - startsWith, - capture, - headTail, - type, - bound, - Clause, - clause, - bitStringMatch, - match_or_default, - defmatchgen, - list_comprehension, - list_generator, - bitstring_generator, - bitstring_comprehension, - defmatchGen, - defmatchAsync -}; - -// https://github.com/airportyh/protomorphism -class Protocol { - constructor(spec) { - this.registry = new Map(); - this.fallback = null; - - function createFun(funName) { - return function (...args) { - const thing = args[0]; - let fun = null; - - if (thing === null && this.hasImplementation(Symbol('null'))) { - fun = this.registry.get(Symbol)[funName]; - } else if (Number.isInteger(thing) && this.hasImplementation(Core.Integer)) { - fun = this.registry.get(Core.Integer)[funName]; - } else if (typeof thing === 'number' && !Number.isInteger(thing) && this.hasImplementation(Core.Float)) { - fun = this.registry.get(Core.Float)[funName]; - } else if (typeof thing === 'string' && this.hasImplementation(Core.BitString)) { - fun = this.registry.get(Core.BitString)[funName]; - } else if (thing && thing instanceof Map && thing.has(Symbol.for('__struct__')) && this.hasImplementation(thing)) { - fun = this.registry.get(thing.get(Symbol.for('__struct__')).__MODULE__)[funName]; - } else if (thing !== null && this.hasImplementation(thing)) { - fun = this.registry.get(thing.constructor)[funName]; - } else if (this.fallback) { - fun = this.fallback[funName]; - } - - if (fun != null) { - const retval = fun.apply(this, args); - return retval; - } - - throw new Error(`No implementation found for ${thing}`); - }; - } - - for (const funName in spec) { - this[funName] = createFun(funName).bind(this); - } - } - - implementation(type, implementation) { - if (type === null) { - this.fallback = implementation; - } else { - this.registry.set(type, implementation); - } - } - - hasImplementation(thing) { - if (thing === Core.Integer || thing === Core.Float || thing === Core.BitString) { - return this.registry.has(thing); - } else if (thing && thing instanceof Map && thing.has(Symbol.for('__struct__'))) { - return this.registry.has(thing.get(Symbol.for('__struct__')).__MODULE__); - } - - return this.registry.has(thing.constructor); - } -} - -function iterator_to_reducer(iterable, acc, fun) { - const iterator = iterable[Symbol.iterator](); - let x = iterator.next(); - let _acc = acc; - - while (x.done === false) { - _acc = fun(x.value, _acc.get(1)); - if (_acc.get(0) === Symbol.for('halt')) { - return new Core.Tuple(Symbol.for('halted'), _acc.get(1)); - } else if (_acc.get(0) === Symbol.for('suspend')) { - return new Core.Tuple(Symbol.for('suspended'), _acc.get(1), new_acc => { - return iterator_to_reducer(iterator, new_acc, fun); - }); - } - - x = iterator.next(); - } - - return new Core.Tuple(Symbol.for('done'), _acc.get(1)); -} - -function call_property(item, property) { - if (!property) { - if (item instanceof Function || typeof item === 'function') { - return item(); - } - - return item; - } - - if (item instanceof Map) { - let prop = null; - - if (item.has(property)) { - prop = property; - } else if (item.has(Symbol.for(property))) { - prop = Symbol.for(property); - } - - if (prop === null) { - throw new Error(`Property ${property} not found in ${item}`); - } - - if (item.get(prop) instanceof Function || typeof item.get(prop) === 'function') { - return item.get(prop)(); - } - return item.get(prop); - } - - let prop = null; - - if (typeof item === 'number' || typeof item === 'symbol' || typeof item === 'boolean' || typeof item === 'string') { - if (item[property] !== undefined) { - prop = property; - } else if (item[Symbol.for(property)] !== undefined) { - prop = Symbol.for(property); - } - } else if (property in item) { - prop = property; - } else if (Symbol.for(property) in item) { - prop = Symbol.for(property); - } - - if (prop === null) { - throw new Error(`Property ${property} not found in ${item}`); - } - - if (item[prop] instanceof Function || typeof item[prop] === 'function') { - return item[prop](); - } - return item[prop]; -} - -function defprotocol(spec) { - return new Protocol(spec); -} - -function defimpl(protocol, type, impl) { - protocol.implementation(type, impl); -} - -function build_namespace(ns, ns_string) { - let parts = ns_string.split('.'); - const root = ns; - let parent = ns; - - if (parts[0] === 'Elixir') { - parts = parts.slice(1); - } - - for (const part of parts) { - if (typeof parent[part] === 'undefined') { - parent[part] = {}; - } - - parent = parent[part]; - } - - root.__table__ = ns.__table__ || {}; - root.__table__[Symbol.for(ns_string)] = parent; - - return parent; -} - -function map_to_object(map) { - const object = {}; - - for (const [key, value] of map.entries()) { - if (value instanceof Map) { - object[key] = map_to_object(value); - } else { - object[key] = value; - } - } - - return object; -} - -var Functions = { - call_property, - defprotocol, - defimpl, - build_namespace, - iterator_to_reducer, - map_to_object -}; - -function _case(condition, clauses) { - return Core.Patterns.defmatch(...clauses)(condition); -} - -function cond(...clauses) { - for (const clause of clauses) { - if (clause[0]) { - return clause[1](); - } - } - - throw new Error(); -} - -function _for(expression, generators, collectable_protocol, into = []) { - let [result, fun] = collectable_protocol.into(into); - - const generatedValues = run_list_generators(generators.pop()(), generators); - - for (const value of generatedValues) { - if (expression.guard.apply(this, value)) { - result = fun(result, new Core.Tuple(Symbol.for('cont'), expression.fn.apply(this, value))); - } - } - - return fun(result, Symbol.for('done')); -} - -function run_list_generators(generator, generators) { - if (generators.length == 0) { - return generator.map(x => { - if (Array.isArray(x)) { - return x; - } - return [x]; - }); - } - const list = generators.pop(); - - const next_gen = []; - for (const j of list()) { - for (const i of generator) { - next_gen.push([j].concat(i)); - } - } - - return run_list_generators(next_gen, generators); -} - -function _try(do_fun, rescue_function, catch_fun, else_function, after_function) { - let result = null; - - try { - result = do_fun(); - } catch (e) { - let ex_result = null; - - if (rescue_function) { - try { - ex_result = rescue_function(e); - return ex_result; - } catch (ex) { - if (ex instanceof Core.Patterns.MatchError) { - throw ex; - } - } - } - - if (catch_fun) { - try { - ex_result = catch_fun(e); - return ex_result; - } catch (ex) { - if (ex instanceof Core.Patterns.MatchError) { - throw ex; - } - } - } - - throw e; - } finally { - if (after_function) { - after_function(); - } - } - - if (else_function) { - try { - return else_function(result); - } catch (ex) { - if (ex instanceof Core.Patterns.MatchError) { - throw new Error('No Match Found in Else'); - } - - throw ex; - } - } else { - return result; - } -} - -function _with(...args) { - let argsToPass = []; - let successFunction = null; - let elseFunction = null; - - if (typeof args[args.length - 2] === 'function') { - [successFunction, elseFunction] = args.splice(-2); - } else { - successFunction = args.pop(); - } - - for (let i = 0; i < args.length; i++) { - const [pattern, func] = args[i]; - - const result = func(...argsToPass); - - const patternResult = Core.Patterns.match_or_default(pattern, result); - - if (patternResult == null) { - if (elseFunction) { - return elseFunction.call(null, result); - } - return result; - } - - argsToPass = argsToPass.concat(patternResult); - } - - return successFunction(...argsToPass); -} - -function receive(clauses, after) { - console.warn('Receive not supported'); -} - -var SpecialForms = { - _case, - cond, - _for, - _try, - _with, - receive -}; - -// http://erlang.org/doc/man/lists.html -function reverse(list) { - return [...list].reverse(); -} - -function foreach(fun, list) { - list.forEach(x => fun(x)); - - return Symbol.for('ok'); -} - -function duplicate(n, elem) { - const list = []; - - while (list.length < n) { - list.push(elem); - } - - return list; -} - -function flatten(deepList, tail = []) { - const val = deepList.reduce((acc, value) => { - if (Array.isArray(value)) { - return acc.concat(flatten(value)); - } - - return acc.concat(value); - }, []); - - return val.concat(tail); -} - -function foldl(fun, acc0, list) { - return list.reduce((acc, value) => { - return fun(value, acc); - }, acc0); -} - -function foldr(fun, acc0, list) { - return foldl(fun, acc0, reverse(list)); -} - -function keyfind(key, n, tupleList) { - for (const tuple of tupleList) { - if (tuple.get(n - 1) === key) { - return tuple; - } - } - - return false; -} - -function keymember(key, n, tupleList) { - if (keyfind(key, n, tupleList) === false) { - return false; - } - - return true; -} - -function keyreplace(key, n, tupleList, newTuple) { - const newTupleList = [...tupleList]; - - for (let index = 0; index < newTupleList.length; index++) { - if (newTupleList[index].get(n - 1) === key) { - newTupleList[index] = newTuple; - return newTupleList; - } - } - - return newTupleList; -} - -function keysort(n, tupleList) { - const newTupleList = [...tupleList]; - - return newTupleList.sort((a, b) => { - if (a.get(n - 1) < b.get(n - 1)) { - return -1; - } else if (a.get(n - 1) > b.get(n - 1)) { - return 1; - } - - return 0; - }); -} - -function keystore(key, n, tupleList, newTuple) { - const newTupleList = [...tupleList]; - - for (let index = 0; index < newTupleList.length; index++) { - if (newTupleList[index].get(n - 1) === key) { - newTupleList[index] = newTuple; - return newTupleList; - } - } - - return newTupleList.concat(newTuple); -} - -function keydelete(key, n, tupleList) { - const newTupleList = []; - let deleted = false; - - for (let index = 0; index < tupleList.length; index++) { - if (deleted === false && tupleList[index].get(n - 1) === key) { - deleted = true; - } else { - newTupleList.push(tupleList[index]); - } - } - - return newTupleList; -} - -function keytake(key, n, tupleList) { - const result = keyfind(key, n, tupleList); - - if (result !== false) { - return new ErlangTypes.Tuple(result.get(n - 1), result, keydelete(key, n, tupleList)); - } - - return false; -} - -function mapfoldl(fun, acc0, list1) { - const listResult = []; - let accResult = acc0; - - for (const item of list1) { - const tuple = fun(item, accResult); - listResult.push(tuple.get(0)); - accResult = tuple.get(1); - } - - return new ErlangTypes.Tuple(listResult, accResult); -} - -function concat(things) { - return things.map(v => v.toString()).join(); -} - -function map(fun, list) { - return list.map(value => fun(value)); -} - -function filter(pred, list1) { - return list1.filter(x => pred(x)); -} - -function filtermap(fun, list1) { - const list2 = []; - - for (const item of list1) { - const value = fun(item); - - if (value === true) { - list2.push(item); - } else if (value instanceof ErlangTypes.Tuple && value.get(0) === true) { - list2.push(value.get(1)); - } - } - - return list2; -} - -function member(elem, list) { - for (const item of list) { - if (item === elem) { - return true; - } - } - - return false; -} - -function all(pred, list) { - for (const item of list) { - if (pred(item) === false) { - return false; - } - } - - return true; -} - -function any(pred, list) { - for (const item of list) { - if (pred(item) === true) { - return true; - } - } - - return false; -} - -function splitwith(pred, list) { - let switchToList2 = false; - const list1 = []; - const list2 = []; - - for (const item of list) { - if (switchToList2 === true) { - list2.push(item); - } else if (pred(item) === true) { - list1.push(item); - } else { - switchToList2 = true; - list2.push(item); - } - } - - return new ErlangTypes.Tuple(list1, list2); -} - -function sort(...args) { - if (args.length === 1) { - const list2 = [...args[0]]; - return list2.sort(); - } - - const fun = args[0]; - const list2 = [...args[1]]; - - return list2.sort((a, b) => { - const result = fun(a, b); - - if (result === true) { - return -1; - } - - return 1; - }); -} - -var lists = { - reverse, - foreach, - duplicate, - flatten, - foldl, - foldr, - keydelete, - keyfind, - keymember, - keyreplace, - keysort, - keystore, - keytake, - mapfoldl, - concat, - map, - filter, - filtermap, - member, - all, - any, - splitwith, - sort -}; - -// http://erlang.org/doc/man/erlang.html -function atom_to_binary(atom, encoding = Symbol.for('utf8')) { - if (encoding !== Symbol.for('utf8')) { - throw new Error(`unsupported encoding ${encoding}`); - } - - if (atom.__MODULE__) { - return Symbol.keyFor(atom.__MODULE__); - } - - return Symbol.keyFor(atom); -} - -function binary_to_atom(binary, encoding = Symbol.for('utf8')) { - if (encoding !== Symbol.for('utf8')) { - throw new Error(`unsupported encoding ${encoding}`); - } - - return Symbol.for(binary); -} - -function binary_to_existing_atom(binary, encoding = Symbol.for('utf8')) { - return binary_to_atom(binary, encoding); -} - -function list_concatenation(list1, list2) { - return list1.concat(list2); -} - -function list_subtraction(list1, list2) { - const list = [...list1]; - - for (const item of list2) { - const index = list.indexOf(item); - - if (index > -1) { - list.splice(index, 1); - } - } - - return list; -} - -function div(left, right) { - return left / right; -} - -function not(x) { - return !x; -} - -function rem(left, right) { - return left % right; -} - -function band(left, right) { - return left & right; -} - -function bor(left, right) { - return left | right; -} - -function bnot(x) { - return ~x; -} - -function bsl(left, right) { - return left << right; -} - -function bsr(left, right) { - return left >> right; -} - -function bxor(left, right) { - return left ^ right; -} - -function is_atom(value) { - return typeof value === 'symbol' || value instanceof Symbol || value.__MODULE__; -} - -function is_bitstring$1(value) { - return value instanceof ErlangTypes.BitString; -} - -function is_boolean$1(value) { - return typeof value === 'boolean' || value instanceof Boolean; -} - -function is_number$1(value) { - return typeof value === 'number' || value instanceof Number; -} - -function is_float(value) { - return is_number$1(value) && !Number.isInteger(value); -} - -function is_function$1(value) { - return typeof value === 'function' || value instanceof Function; -} - -function is_integer(value) { - return Number.isInteger(value); -} - -function is_list(value) { - return Array.isArray(value); -} - -function is_map$1(value) { - return value instanceof Map; -} - -function is_pid(value) { - return value instanceof ErlangTypes.PID; -} - -function is_port() { - return false; -} - -function is_reference(value) { - return value instanceof ErlangTypes.Reference; -} - -function is_tuple(value) { - return value instanceof ErlangTypes.Tuple; -} - -function is_binary(value) { - return typeof value === 'string' || value instanceof String; -} - -function element(n, tuple) { - return tuple.get(n - 1); -} - -function setelement(index, tuple1, value) { - const tupleData = [...tuple1.values]; - - tupleData[index - 1] = value; - - return new ErlangTypes.Tuple(...tupleData); -} - -function make_tuple(arity, initialValue) { - const list = []; - - for (let i = 0; i < arity; i++) { - list.push(initialValue); - } - - return new ErlangTypes.Tuple(...list); -} - -function insert_element(index, tuple, term) { - const list = [...tuple.values]; - list.splice(index - 1, 0, term); - - return new ErlangTypes.Tuple(...list); -} - -function append_element(tuple, term) { - const list = [...tuple.values]; - list.push(term); - - return new ErlangTypes.Tuple(...list); -} - -function delete_element(index, tuple) { - const list = [...tuple.values]; - list.splice(index - 1, 1); - - return new ErlangTypes.Tuple(...list); -} - -function tuple_to_list(tuple) { - const list = [...tuple.values]; - return list; -} - -function abs(number) { - return Math.abs(number); -} - -function apply(...args) { - if (args.length === 2) { - return args[0].apply(this, ...args[1]); - } - - return args[0][atom_to_binary(args[1])].apply(this, ...args[2]); -} - -function binary_part(binary, start, length) { - return binary.substring(start, start + length); -} - -function bit_size(bitstring) { - return bitstring.bit_size; -} - -function byte_size(bitstring) { - return bitstring.byte_size; -} - -function hd(list) { - return list[0]; -} - -function length(list) { - return list.length; -} - -function make_ref() { - return new ErlangTypes.Reference(); -} - -function map_size(map) { - return map.size; -} - -function max(first, second) { - return Math.max(first, second); -} - -function min(first, second) { - return Math.min(first, second); -} - -function round(number) { - return Math.round(number); -} - -function tl(list) { - return list.slice(1); -} - -function trunc(number) { - return Math.trunc(number); -} - -function tuple_size(tuple) { - return tuple.length; -} - -function binary_to_float(str) { - return parseFloat(str); -} - -function binary_to_integer(str, base = 10) { - return parseInt(str, base); -} - -function process_info(pid, item) { - if (item) { - if (item === Symbol.for('current_stacktrace')) { - return new ErlangTypes.Tuple(item, []); - } - - return new ErlangTypes.Tuple(item, null); - } - - return []; -} - -function iolist_to_binary(ioListOrBinary) { - if (ioListOrBinary === null) { - return ''; - } - - if (is_binary(ioListOrBinary)) { - return ioListOrBinary; - } - - if (is_bitstring$1(ioListOrBinary)) { - return String.fromCodePoint(...ioListOrBinary.value); - } - - const iolistFlattened = lists.flatten(ioListOrBinary); - - const value = iolistFlattened.reduce((acc, current) => { - if (current === null) { - return acc; - } else if (is_integer(current)) { - return acc + String.fromCodePoint(current); - } else if (is_bitstring$1(current)) { - return acc + String.fromCodePoint(...current.value); - } - - return acc + iolist_to_binary(current); - }, ''); - - return value; -} - -function io_size(ioListOrBinary) { - return iolist_to_binary(ioListOrBinary).length; -} - -function integer_to_binary(integer, base = 10) { - return integer.toString(base); -} - -var erlang = { - atom_to_binary, - binary_to_atom, - binary_to_existing_atom, - list_concatenation, - list_subtraction, - div, - not, - rem, - band, - bor, - bsl, - bsr, - bxor, - bnot, - is_bitstring: is_bitstring$1, - is_boolean: is_boolean$1, - is_float, - is_function: is_function$1, - is_integer, - is_list, - is_map: is_map$1, - is_number: is_number$1, - is_pid, - is_port, - is_reference, - is_tuple, - is_atom, - is_binary, - element, - setelement, - make_tuple, - insert_element, - append_element, - delete_element, - tuple_to_list, - abs, - apply, - binary_part, - bit_size, - byte_size, - hd, - length, - make_ref, - map_size, - max, - min, - round, - tl, - trunc, - tuple_size, - binary_to_float, - binary_to_integer, - process_info, - iolist_to_binary, - io_size, - integer_to_binary -}; - -// http://erlang.org/doc/man/maps.html -const OK = Symbol.for('ok'); -const ERROR = Symbol.for('error'); -const BADMAP = Symbol.for('badmap'); -const BADKEY = Symbol.for('badkey'); - -function find(key, map) { - if (erlang.is_map(map) === false) { - return new ErlangTypes.Tuple(BADMAP, map); - } - - const value = map.get(key); - - if (typeof value !== 'undefined') { - return new ErlangTypes.Tuple(OK, value); - } - - return ERROR; -} - -function fold(fun, init, map) { - let acc = init; - - for (const [key, value] of map.entries()) { - acc = fun(key, value, acc); - } - - return acc; -} - -function remove(key, map1) { - if (erlang.is_map(map1) === false) { - return new ErlangTypes.Tuple(BADMAP, map1); - } - - const map2 = new Map(map1); - - map2.delete(key); - - return map2; -} - -function to_list(map) { - if (erlang.is_map(map) === false) { - return new ErlangTypes.Tuple(BADMAP, map); - } - - const list = []; - - for (const [key, value] of map.entries()) { - list.push(new ErlangTypes.Tuple(key, value)); - } - - return list; -} - -function from_list(list) { - return list.reduce((acc, item) => { - const [key, value] = item; - acc.set(key, value); - - return acc; - }, new Map()); -} - -function keys(map) { - if (erlang.is_map(map) === false) { - return new ErlangTypes.Tuple(BADMAP, map); - } - - return Array.from(map.keys()); -} - -function values$1(map) { - if (erlang.is_map(map) === false) { - return new ErlangTypes.Tuple(BADMAP, map); - } - - return Array.from(map.values()); -} - -function is_key(key, map) { - return map.has(key); -} - -function put(key, value, map1) { - if (erlang.is_map(map1) === false) { - return new ErlangTypes.Tuple(BADMAP, map1); - } - - const map2 = new Map(map1); - map2.set(key, value); - - return map2; -} - -function merge(map1, map2) { - if (erlang.is_map(map1) === false) { - return new ErlangTypes.Tuple(BADMAP, map1); - } - - if (erlang.is_map(map2) === false) { - return new ErlangTypes.Tuple(BADMAP, map2); - } - - return new Map([...map1, ...map2]); -} - -function update(key, value, map1) { - if (erlang.is_map(map1) === false) { - return new ErlangTypes.Tuple(BADMAP, map1); - } - - if (is_key(key, map1) === false) { - return new ErlangTypes.Tuple(BADKEY, key); - } - - return new Map([...map1, [key, value]]); -} - -function get(...args) { - const key = args[0]; - const map = args[1]; - - if (erlang.is_map(map) === false) { - return new ErlangTypes.Tuple(BADMAP, map); - } - - if (is_key(key)) { - return map.get(key); - } - - if (args.length === 3) { - return args[2]; - } - - return new ErlangTypes.Tuple(BADKEY, key); -} - -function take(key, map1) { - if (erlang.is_map(map1) === false) { - return new ErlangTypes.Tuple(BADMAP, map1); - } - - if (!is_key(key)) { - return ERROR; - } - - const value = map1.get(key); - const map2 = new Map(map1); - map2.delete(key); - - return new ErlangTypes.Tuple(value, map2); -} - -var maps = { - find, - fold, - remove, - to_list, - from_list, - keys, - values: values$1, - is_key, - put, - merge, - update, - get, - take -}; - -function warn(message) { - const messageString = message.join(''); - console.warn(`warning: ${messageString}`); - - return Symbol.for('ok'); -} - -var elixir_errors = { - warn -}; - -function put_chars(ioDevice, charData) { - const dataToWrite = erlang.iolist_to_binary(charData); - - if (ioDevice === Symbol.for('stderr')) { - console.error(dataToWrite); - } else { - console.log(dataToWrite); - } - - return Symbol.for('ok'); -} - -var io = { - put_chars -}; - -function copy(subject, n = 1) { - return subject.repeat(n); -} - -var binary = { - copy -}; - -function get_key(key) { - let real_key = key; - - if (__elixirscript_names__.has(key)) { - real_key = __elixirscript_names__.get(key); - } - - if (__elixirscript_store__.has(real_key)) { - return real_key; - } - - throw new Error(`Key ${real_key} not found`); -} - -function create(value, name = null) { - const key = new Core.PID(); - - if (name !== null) { - __elixirscript_names__.set(name, key); - } - - return __elixirscript_store__.set(key, value); -} - -function update$1(key, value) { - const real_key = get_key(key); - return __elixirscript_store__.set(real_key, value); -} - -function read(key) { - const real_key = get_key(key); - return __elixirscript_store__.get(real_key); -} - -function remove$1(key) { - const real_key = get_key(key); - return __elixirscript_store__.delete(real_key); -} - -var Store = { - create, - update: update$1, - read, - remove: remove$1 -}; - -class Integer {} -class Float {} - -function get_global() { - if (typeof self !== 'undefined') { - return self; - } else if (typeof window !== 'undefined') { - return window; - } else if (typeof global !== 'undefined') { - return global; - } - - console.warn('No global state found'); - return null; -} - -const globalState = get_global(); - -globalState.__elixirscript_store__ = new Map(); -globalState.__elixirscript_names__ = new Map(); - -var Core = { - Tuple: ErlangTypes.Tuple, - PID: ErlangTypes.PID, - BitString: ErlangTypes.BitString, - Patterns, - Integer, - Float, - Functions, - SpecialForms, - Store, - global: globalState, - erlang, - maps, - lists, - elixir_errors, - io, - binary -}; - -var elixir = { - Core -}; - -return elixir; - -}()); +var ElixirScript=function(){'use strict';/* @flow */function namedVariableResult(a,b){return new NamedVariableResult(a,b)}/* @flow */function is_number(a){return'number'==typeof a}function is_string(a){return'string'==typeof a}function is_boolean(a){return'boolean'==typeof a}function is_symbol(a){return'symbol'==typeof a}function is_object(a){return'object'==typeof a}function is_variable(a){return a instanceof Variable}function is_null(a){return null===a}function is_array(a){return Array.isArray(a)}function is_function(a){return'[object Function]'==Object.prototype.toString.call(a)}function is_map(a){return a instanceof Map}function resolveNull(){return function(a){return is_null(a)}}function resolveWildcard(){return function(){return!0}}function resolveObject(a){let b={};const c=Object.keys(a).concat(Object.getOwnPropertySymbols(a));for(let d of c)b[d]=buildMatch(a[d]);return function(d,e){if(!is_object(d)||a.length>d.length)return!1;for(let a of c)if(!(a in d)||!b[a](d[a],e))return!1;return!0}}function getSize(a,b){return a*b/8}function arraysEqual(c,a){if(c===a)return!0;if(null==c||null==a)return!1;if(c.length!=a.length)return!1;for(var b=0;be.integer(a));return new e(...b)}function resolveNoMatch(){return function(){return!1}}function buildMatch(a){if(null===a)return resolveNull(a);if('undefined'==typeof a)return resolveWildcard(a);const b=a.constructor.prototype,c=f.get(b);return c?c(a):'object'==typeof a?resolveObject(a):resolveNoMatch()}function defmatchgen(...a){const b=getArityMap(a);return function*(...a){let[c,d]=findMatchingFunction(a,b);return yield*c.apply(this,d)}}function findMatchingFunction(a,b){if(b.has(a.length)){const c=b.get(a.length);let d=null,e=null;for(let b of c){let c=[];a=fillInOptionalValues(a,b.arity,b.optionals);const f=b.pattern(a,c),[g,h]=checkNamedVariables(c);if(f&&h&&b.guard.apply(this,g)){d=b.fn,e=g;break}}if(!d)throw console.error('No match for:',a),new MatchError(a);return[d,e]}throw console.error('Arity of',a.length,'not found. No match for:',a),new MatchError(a)}function getArityMap(a){let b=new Map;for(const c of a){const a=getArityRange(c);for(const d of a){let a=[];b.has(d)&&(a=b.get(d)),a.push(c),b.set(d,a)}}return b}function getArityRange(a){const b=a.arity-a.optionals.length,c=a.arity;let d=[b];for(;d[d.length-1]!=c;)d.push(d[d.length-1]+1);return d}function getOptionalValues(a){let b=[];for(let c=0;c!0,d=null){let e=[],f=buildMatch(a);const g=f(b,e),[h,i]=checkNamedVariables(e);return g&&i&&c.apply(this,h)?h:d}function run_generators(a,b){if(0==b.length)return a.map((a)=>{return Array.isArray(a)?a:[a]});const c=b.pop();let d=[];for(let e of c())for(let b of a)d.push([e].concat(b));return run_generators(d,b)}function iterator_to_reducer(a,b,c){const d=a[Symbol.iterator]();let e=d.next(),f=b;for(;!1===e.done;){if(f=c(e.value,f.get(1)),f.get(0)===Symbol.for('halt'))return new o.Tuple(Symbol.for('halted'),f.get(1));if(f.get(0)===Symbol.for('suspend'))return new o.Tuple(Symbol.for('suspended'),f.get(1),(a)=>{return iterator_to_reducer(d,a,c)});e=d.next()}return new o.Tuple(Symbol.for('done'),f.get(1))}function map_to_object(a){const b={};for(const[c,d]of a.entries())b[c]=d instanceof Map?map_to_object(d):d;return b}function run_list_generators(a,b){if(0==b.length)return a.map((a)=>{return Array.isArray(a)?a:[a]});const c=b.pop(),d=[];for(const e of c())for(const b of a)d.push([e].concat(b));return run_list_generators(d,b)}// http://erlang.org/doc/man/lists.html +function reverse(a){return[...a]}function flatten(a,b=[]){const c=a.reduce((a,b)=>{return Array.isArray(b)?a.concat(flatten(b)):a.concat(b)},[]);return c.concat(b)}function foldl(a,b,c){return c.reduce((b,c)=>{return a(c,b)},b)}function keyfind(a,b,c){for(const d of c)if(d.get(b-1)===a)return d;return!1}function keydelete(a,b,c){const d=[];let e=!1;for(let f=0;f{if(null===c)return a;return is_integer(c)?a+b(c):is_bitstring$1(c)?a+b(...c.value):a+iolist_to_binary(c)},'');return d}function is_key(a,b){return b.has(a)}function get_key(a){let b=a;if(__elixirscript_names__.has(a)&&(b=__elixirscript_names__.get(a)),__elixirscript_store__.has(b))return b;throw new Error(`Key ${b} not found`)}var a=Number.isInteger;class Variable{constructor(a=null,b=Symbol.for('tailored.no_value')){this.name=a,this.default_value=b}}class Wildcard{constructor(){}}class StartsWith{constructor(a){this.prefix=a}}class Capture{constructor(a){this.value=a}}class HeadTail{constructor(a,b){this.head=a,this.tail=b}}class Type{constructor(a,b={}){this.type=a,this.objPattern=b}}class Bound{constructor(a){this.value=a}}class BitStringMatch{constructor(...a){this.values=a}length(){return values.length}bit_size(){return 8*this.byte_size()}byte_size(){let a=0;for(let b of this.values)a+=b.unit*b.size/8;return a}getValue(a){return this.values(a)}getSizeOfValue(a){let b=this.getValue(a);return b.unit*b.size}getTypeOfValue(a){return this.getValue(a).type}}class NamedVariableResult{constructor(a,b){this.name=a,this.value=b}}class Tuple{constructor(...a){this.values=Object.freeze(a),this.length=this.values.length}get(a){return this.values[a]}count(){return this.values.length}[Symbol.iterator](){return this.values[Symbol.iterator]()}toString(){let a,b='';for(a=0;aBitString$1.integer(a));return new BitString$1(...d)}[Symbol.iterator](){return this.value[Symbol.iterator]()}toString(){var a,b='';for(a=0;a>'}process(a){let b=[];var c;for(c=0;cb?c.push(b):2048>b?c.push(192|b>>6,128|63&b):55296>b||57344<=b?c.push(224|b>>12,128|63&b>>6,128|63&b):(d++,b=65536+((1023&b)<<10|1023&a.charCodeAt(d)),c.push(240|b>>18,128|63&b>>12,128|63&b>>6,128|63&b));return c}static toUTF16Array(a){for(var b,c=[],d=0;d=b?(c.push(0),c.push(b)):(c.push(255&b>>8),c.push(255&b));return c}static toUTF32Array(a){for(var b,c=[],d=0;d=b?(c.push(0),c.push(0),c.push(0),c.push(b)):(c.push(0),c.push(0),c.push(255&b>>8),c.push(255&b));return c}//http://stackoverflow.com/questions/2003493/javascript-float-from-to-bits +static float32ToBytes(a){var b=[],c=new ArrayBuffer(4);new Float32Array(c)[0]=a;let d=new Uint32Array(c)[0];return b.push(255&d>>24),b.push(255&d>>16),b.push(255&d>>8),b.push(255&d),b}static float64ToBytes(a){var b=[],c=new ArrayBuffer(8);new Float64Array(c)[0]=a;var d=new Uint32Array(c)[0],e=new Uint32Array(c)[1];return b.push(255&e>>24),b.push(255&e>>16),b.push(255&e>>8),b.push(255&e),b.push(255&d>>24),b.push(255&d>>16),b.push(255&d>>8),b.push(255&d),b}}var d={Tuple,PID:class PID{constructor(){++b,this.id=b}toString(){return'PID#<0.'+this.id+'.0>'}},Reference:class Reference{constructor(){++c,this.id=c,this.ref=Symbol()}toString(){return'Ref#<0.0.0.'+this.id+'>'}},BitString:BitString$1};/* @flow */const e=d.BitString,f=new Map;f.set(Variable.prototype,function resolveVariable(a){return function(b,c){return null===a.name?c.push(b):!a.name.startsWith('_')&&c.push(namedVariableResult(a.name,b)),!0}}),f.set(Wildcard.prototype,resolveWildcard),f.set(HeadTail.prototype,function resolveHeadTail(a){const b=buildMatch(a.head),c=buildMatch(a.tail);return function(a,d){if(!is_array(a)||0===a.length)return!1;const e=a[0],f=a.slice(1);return b(e,d)&&c(f,d)}}),f.set(StartsWith.prototype,function resolveStartsWith(a){const b=a.prefix;return function(a,c){return is_string(a)&&a.startsWith(b)&&(c.push(a.substring(b.length)),!0)}}),f.set(Capture.prototype,function resolveCapture(a){const b=buildMatch(a.value);return function(a,c){return!!b(a,c)&&(c.push(a),!0)}}),f.set(Bound.prototype,function resolveBound(a){return function(b){return typeof b==typeof a.value&&b===a.value}}),f.set(Type.prototype,function resolveType(a){return function(b,c){if(b instanceof a.type){const d=buildMatch(a.objPattern);return d(b,c)}return!1}}),f.set(BitStringMatch.prototype,function resolveBitString(a){let b=[];for(let c of a.values)if(is_variable(c.value)){let a=getSize(c.unit,c.size);fillArray(b,a)}else b=b.concat(new e(c).value);let c=a.values;return function(a,d){var f=String.fromCharCode;let g=null;if(!is_string(a)&&!(a instanceof e))return!1;g=is_string(a)?new e(e.binary(a)):a;let h=0;for(let e,j=0;jd.size)return!1;for(let a of c)if(!d.has(a)||!b.get(a)(d.get(a),e))return!1;return!0}}),f.set(Array.prototype,function resolveArray(a){const b=a.map((a)=>buildMatch(a));return function(c,d){return is_array(c)&&c.length==a.length&&c.every(function(a,e){return b[e](c[e],d)})}}),f.set(String.prototype,function resolveString(a){return function(b){return is_string(b)&&b===a}}),f.set(Boolean.prototype,function resolveBoolean(a){return function(b){return is_boolean(b)&&b===a}}),f.set(Function.prototype,function resolveFunction(a){return function(b){return is_function(b)&&b===a}}),f.set(Object.prototype,resolveObject);class MatchError extends Error{constructor(a){if(super(),'symbol'==typeof a)this.message='No match for: '+a.toString();else if(Array.isArray(a)){let b=a.map((a)=>{return null===a?'null':'undefined'==typeof a?'undefined':a.toString()});this.message='No match for: '+b}else this.message='No match for: '+a;this.stack=new Error().stack,this.name=this.constructor.name}}class Clause{constructor(a,b,c=()=>!0){this.pattern=buildMatch(a),this.arity=a.length,this.optionals=getOptionalValues(a),this.fn=b,this.guard=c}}const g=Symbol();// https://github.com/airportyh/protomorphism +class Protocol{constructor(b){function createFun(b){return function(...c){const d=c[0];let e=null;if(null===d&&this.hasImplementation(Symbol('null'))?e=this.registry.get(Symbol)[b]:a(d)&&this.hasImplementation(o.Integer)?e=this.registry.get(o.Integer)[b]:'number'==typeof d&&!a(d)&&this.hasImplementation(o.Float)?e=this.registry.get(o.Float)[b]:'string'==typeof d&&this.hasImplementation(o.BitString)?e=this.registry.get(o.BitString)[b]:d&&d instanceof Map&&d.has(Symbol.for('__struct__'))&&this.hasImplementation(d)?e=this.registry.get(d.get(Symbol.for('__struct__')).__MODULE__)[b]:null!==d&&this.hasImplementation(d)?e=this.registry.get(d.constructor)[b]:this.fallback&&(e=this.fallback[b]),null!=e){const a=e.apply(this,c);return a}throw new Error(`No implementation found for ${d}`)}}for(const a in this.registry=new Map,this.fallback=null,b)this[a]=createFun(a).bind(this)}implementation(a,b){null===a?this.fallback=b:this.registry.set(a,b)}hasImplementation(a){if(a===o.Integer||a===o.Float||a===o.BitString)return this.registry.has(a);return a&&a instanceof Map&&a.has(Symbol.for('__struct__'))?this.registry.has(a.get(Symbol.for('__struct__')).__MODULE__):this.registry.has(a.constructor)}}class Recurse{constructor(a){this.func=a}}var h={reverse,foreach:function foreach(a,b){return b.forEach((b)=>a(b)),Symbol.for('ok')},duplicate:function duplicate(a,b){const c=[];for(;c.length{if(d.get(c-1)a.get(c-1)?1:0})},keystore:function keystore(a,b,c,d){const e=[...c];for(let f=0;fa.toString()).join()},map:function map(a,b){return b.map((b)=>a(b))},filter:function filter(a,b){return b.filter((b)=>a(b))},filtermap:function filtermap(a,b){const c=[];for(const e of b){const b=a(e);!0===b?c.push(e):b instanceof d.Tuple&&!0===b.get(0)&&c.push(b.get(1))}return c},member:function member(a,b){for(const c of b)if(c===a)return!0;return!1},all:function all(a,b){for(const c of b)if(!1===a(c))return!1;return!0},any:function any(a,b){for(const c of b)if(!0===a(c))return!0;return!1},splitwith:function splitwith(a,b){let c=!1;const e=[],f=[];for(const d of b)!0==c?f.push(d):!0===a(d)?e.push(d):(c=!0,f.push(d));return new d.Tuple(e,f)},sort:function sort(...a){if(1===a.length){const b=[...a[0]];return b.sort()}const c=a[0],b=[...a[1]];return b.sort((d,a)=>{const b=c(d,a);return!0===b?-1:1})}},i={atom_to_binary,binary_to_atom,binary_to_existing_atom:function binary_to_existing_atom(a,b=Symbol.for('utf8')){return binary_to_atom(a,b)},list_concatenation:function list_concatenation(a,b){return a.concat(b)},list_subtraction:function list_subtraction(a,b){const c=[...a];for(const d of b){const a=c.indexOf(d);-1>b},bxor:function bxor(a,b){return a^b},bnot:function bnot(a){return~a},is_bitstring:is_bitstring$1,is_boolean:function is_boolean$1(a){return'boolean'==typeof a||a instanceof Boolean},is_float:function is_float(b){return is_number$1(b)&&!a(b)},is_function:function is_function$1(a){return'function'==typeof a||a instanceof Function},is_integer,is_list:function is_list(a){return Array.isArray(a)},is_map:function is_map$1(a){return a instanceof Map},is_number:is_number$1,is_pid:function is_pid(a){return a instanceof d.PID},is_port:function is_port(){return!1},is_reference:function is_reference(a){return a instanceof d.Reference},is_tuple:function is_tuple(a){return a instanceof d.Tuple},is_atom:function is_atom(a){return'symbol'==typeof a||a instanceof Symbol||a.__MODULE__},is_binary,element:function element(a,b){return b.get(a-1)},setelement:function setelement(a,b,c){const e=[...b.values];return e[a-1]=c,new d.Tuple(...e)},make_tuple:function make_tuple(a,b){const c=[];for(let d=0;d!0){let d=[],e=buildMatch(a);const f=e(b,d),[g,h]=checkNamedVariables(d);if(f&&h&&c.apply(this,g))return g;throw console.error('No match for:',b),new MatchError(b)},MatchError,variable:function variable(a=null,b=Symbol.for('tailored.no_value')){return new Variable(a,b)},wildcard:function wildcard(){return new Wildcard},startsWith:function startsWith(a){return new StartsWith(a)},capture:function capture(a){return new Capture(a)},headTail:function headTail(a,b){return new HeadTail(a,b)},type:function a(a,b={}){return new Type(a,b)},bound:function bound(a){return new Bound(a)},Clause,clause:function clause(a,b,c=()=>!0){return new Clause(a,b,c)},bitStringMatch:function bitStringMatch(...a){return new BitStringMatch(...a)},match_or_default,defmatchgen,list_comprehension:function list_comprehension(a,b){const c=run_generators(b.pop()(),b);let d=[];for(let e of c)a.guard.apply(this,e)&&d.push(a.fn.apply(this,e));return d},list_generator:function list_generator(a,b){return function(){let c=[];for(let d of b){const b=match_or_default(a,d,()=>!0,g);if(b!=g){const[a]=b;c.push(a)}}return c}},bitstring_generator:function bitstring_generator(a,b){return function(){let c=[],d=b.slice(0,a.byte_size()),e=1;for(;d.byte_size==a.byte_size();){const f=match_or_default(a,d,()=>!0,g);if(f!=g){c.push(f)}d=b.slice(a.byte_size()*e,a.byte_size()*(e+1)),e++}return c}},bitstring_comprehension:function bitstring_comprehension(a,b){const c=run_generators(b.pop()(),b);let e=[];for(let d of c)a.guard.apply(this,d)&&e.push(a.fn.apply(this,d));return e=e.map((a)=>d.BitString.integer(a)),new d.BitString(...e)},defmatchGen:function defmatchGen(...a){return defmatchgen(...a)},defmatchAsync:function defmatchAsync(...a){const b=getArityMap(a);return async function(...a){if(b.has(a.length)){const c=b.get(a.length);let d=null,e=null;for(let b of c){let c=[];a=fillInOptionalValues(a,b.arity,b.optionals);const f=b.pattern(a,c),[g,h]=checkNamedVariables(c);if(f&&h&&(await b.guard.apply(this,c))){d=b.fn,e=c;break}}if(!d)throw console.error('No match for:',a),new MatchError(a);return d.apply(this,e)}throw console.error('Arity of',a.length,'not found. No match for:',a),new MatchError(a)}}},Integer:class Integer{},Float:class Float{},Functions:{call_property:function call_property(a,b){if(!b)return a instanceof Function||'function'==typeof a?a():a;if(a instanceof Map){let c=null;if(a.has(b)?c=b:a.has(Symbol.for(b))&&(c=Symbol.for(b)),null===c)throw new Error(`Property ${b} not found in ${a}`);return a.get(c)instanceof Function||'function'==typeof a.get(c)?a.get(c)():a.get(c)}let c=null;if('number'==typeof a||'symbol'==typeof a||'boolean'==typeof a||'string'==typeof a?void 0===a[b]?void 0!==a[Symbol.for(b)]&&(c=Symbol.for(b)):c=b:b in a?c=b:Symbol.for(b)in a&&(c=Symbol.for(b)),null===c)throw new Error(`Property ${b} not found in ${a}`);return a[c]instanceof Function||'function'==typeof a[c]?a[c]():a[c]},defprotocol:function defprotocol(a){return new Protocol(a)},defimpl:function defimpl(a,b,c){a.implementation(b,c)},build_namespace:function build_namespace(a,b){let c=b.split('.');const d=a;let e=a;'Elixir'===c[0]&&(c=c.slice(1));for(const d of c)'undefined'==typeof e[d]&&(e[d]={}),e=e[d];return d.__table__=a.__table__||{},d.__table__[Symbol.for(b)]=e,e},iterator_to_reducer,map_to_object,trampoline:function trampoline$1(a){let b=a;for(;b&&b instanceof Recurse;)b=b.func();return b},Recurse},SpecialForms:{_case:function _case(a,b){return o.Patterns.defmatch(...b)(a)},cond:function cond(...a){for(const b of a)if(b[0])return b[1]();throw new Error},_for:function _for(a,b,c,d=[]){let[e,f]=c.into(d);const g=run_list_generators(b.pop()(),b);for(const h of g)a.guard.apply(this,h)&&(e=f(e,new o.Tuple(Symbol.for('cont'),a.fn.apply(this,h))));return f(e,Symbol.for('done'))},_try:function _try(a,b,c,d,e){let f=null;try{f=a()}catch(a){let d=null;if(b)try{return d=b(a),d}catch(a){if(a instanceof o.Patterns.MatchError)throw a}if(c)try{return d=c(a),d}catch(a){if(a instanceof o.Patterns.MatchError)throw a}throw a}finally{e&&e()}if(d)try{return d(f)}catch(a){if(a instanceof o.Patterns.MatchError)throw new Error('No Match Found in Else');throw a}else return f},_with:function _with(...a){let b=[],c=null,d=null;'function'==typeof a[a.length-2]?[c,d]=a.splice(-2):c=a.pop();for(let c=0;c{const[c,d]=b;return a.set(c,d),a},new Map)},keys:function keys(a){return!1===i.is_map(a)?new d.Tuple(l,a):Array.from(a.keys())},values:function values$1(a){return!1===i.is_map(a)?new d.Tuple(l,a):Array.from(a.values())},is_key,put:function put(a,b,c){if(!1===i.is_map(c))return new d.Tuple(l,c);const e=new Map(c);return e.set(a,b),e},merge:function merge(a,b){return!1===i.is_map(a)?new d.Tuple(l,a):!1===i.is_map(b)?new d.Tuple(l,b):new Map([...a,...b])},update:function update(a,b,c){return!1===i.is_map(c)?new d.Tuple(l,c):!1===is_key(a,c)?new d.Tuple(m,a):new Map([...c,[a,b]])},get:function get(...a){const b=a[0],c=a[1];return!1===i.is_map(c)?new d.Tuple(l,c):is_key(b)?c.get(b):3===a.length?a[2]:new d.Tuple(m,b)},take:function take(a,b){if(!1===i.is_map(b))return new d.Tuple(l,b);if(!is_key(a))return k;const c=b.get(a),e=new Map(b);return e.delete(a),new d.Tuple(c,e)}},lists:h,elixir_errors:{warn:function warn(a){const b=a.join('');return console.warn(`warning: ${b}`),Symbol.for('ok')}},io:{put_chars:function put_chars(a,b){const c=i.iolist_to_binary(b);return a===Symbol.for('stderr')?console.error(c):console.log(c),Symbol.for('ok')}},binary:{copy:function copy(a,b=1){return a.repeat(b)}}};return{Core:o}}(); diff --git a/src/javascript/lib/core/erlang_compat/erlang.js b/src/javascript/lib/core/erlang_compat/erlang.js index 683ba0f6..78dcef94 100644 --- a/src/javascript/lib/core/erlang_compat/erlang.js +++ b/src/javascript/lib/core/erlang_compat/erlang.js @@ -283,6 +283,10 @@ function iolist_to_binary(ioListOrBinary) { return String.fromCodePoint(...ioListOrBinary.value); } + if (is_number(ioListOrBinary)) { + return String.fromCodePoint(ioListOrBinary); + } + const iolistFlattened = lists.flatten(ioListOrBinary); const value = iolistFlattened.reduce((acc, current) => { diff --git a/src/javascript/lib/core/functions.js b/src/javascript/lib/core/functions.js index 4fdabcac..d61dc21a 100644 --- a/src/javascript/lib/core/functions.js +++ b/src/javascript/lib/core/functions.js @@ -127,11 +127,29 @@ function map_to_object(map) { return object; } +class Recurse { + constructor(func) { + this.func = func; + } +} + +function trampoline(f) { + let currentValue = f; + + while (currentValue && currentValue instanceof Recurse) { + currentValue = currentValue.func(); + } + + return currentValue; +} + export default { call_property, defprotocol, defimpl, build_namespace, iterator_to_reducer, - map_to_object + map_to_object, + trampoline, + Recurse }; diff --git a/test/compiler_test.exs b/test/compiler_test.exs index f41aa7bf..36e510e7 100644 --- a/test/compiler_test.exs +++ b/test/compiler_test.exs @@ -35,7 +35,7 @@ defmodule ElixirScript.Compiler.Test do test "Output file with default name" do path = System.tmp_dir() - result = ElixirScript.Compiler.compile(Atom, [output: path]) + ElixirScript.Compiler.compile(Atom, [output: path]) assert File.exists?(Path.join([path, "Elixir.App.js"])) end @@ -43,7 +43,7 @@ defmodule ElixirScript.Compiler.Test do path = System.tmp_dir() path = Path.join([path, "myfile.js"]) - result = ElixirScript.Compiler.compile(Atom, [output: path]) + ElixirScript.Compiler.compile(Atom, [output: path]) assert File.exists?(path) end -end \ No newline at end of file +end diff --git a/test/passes/translate/form_test.exs b/test/passes/translate/form_test.exs index ea154950..f2cc2cce 100644 --- a/test/passes/translate/form_test.exs +++ b/test/passes/translate/form_test.exs @@ -120,10 +120,11 @@ defmodule ElixirScript.Translate.Forms.Test do test "function returning an array" do ast = {:fn, [], [{:foo, [], [], [1, 2, 3]}]} - state = %{} + state = %{function: {:something, nil}} {js_ast, _} = Form.compile(ast, state) - return_statement = Enum.at(Enum.at(js_ast.body.body, 1).consequent.body, 1) + + return_statement = Enum.at(Enum.at(hd(js_ast.body.body).body.body, 1).consequent.body, 1) assert return_statement.argument == J.array_expression([ J.literal(1), From 0edd518ed0f77b3288d09afbebf606ed3d7680cf Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Sat, 29 Jul 2017 15:24:52 -0500 Subject: [PATCH 639/860] Add todo-elixirscript to README.md --- README.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/README.md b/README.md index 40bb0e11..b3b413d5 100644 --- a/README.md +++ b/README.md @@ -13,6 +13,11 @@ Usage Please check the [Getting Started Guide](GettingStarted.md) for usage +Examples +========== + +[ElixirScript Todo Example](https://github.com/elixirscript/todo-elixirscript) + Development =========== From 4da3f46d3a600b57043082cc3cb2c71d24888ce4 Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Sat, 29 Jul 2017 18:38:09 -0500 Subject: [PATCH 640/860] Update String module debug_info code. Get debug_info from String module, but then replace functions found in ElixirScript.String. This is so we don't have to reimplement the entire String module. --- .tool-versions | 2 +- lib/elixir_script/beam.ex | 44 +++++++++++++++++-- .../passes/translate/forms/remote.ex | 3 +- src/javascript/lib/core.js | 4 +- .../lib/core/erlang_compat/unicode.js | 18 ++++++++ test/support/main.ex | 2 + 6 files changed, 66 insertions(+), 7 deletions(-) create mode 100644 src/javascript/lib/core/erlang_compat/unicode.js diff --git a/.tool-versions b/.tool-versions index 8dbeeb38..a6c3da3e 100644 --- a/.tool-versions +++ b/.tool-versions @@ -1,3 +1,3 @@ erlang 20.0 -elixir ref-v1.5.0-rc.2 +elixir 1.5.0-otp-20 nodejs 8.2.0 diff --git a/lib/elixir_script/beam.ex b/lib/elixir_script/beam.ex index e850d837..51c15910 100644 --- a/lib/elixir_script/beam.ex +++ b/lib/elixir_script/beam.ex @@ -10,9 +10,24 @@ defmodule ElixirScript.Beam do @spec debug_info(atom) :: {:ok | :error, map | binary} def debug_info(module) - #Replace some modules with ElixirScript versions - def debug_info(module) when module in [String, Agent] do - case debug_info(Module.concat(ElixirScript, module)) do + # We get debug info from String and then replace + # functions in it with equivalents in ElixirScript.String. + # This is so that we don't include the unicode database + # in our output + def debug_info(String) do + {:ok, info} = do_debug_info(String) + {:ok, ex_string_info} = do_debug_info(ElixirScript.String) + + definitions = replace_definitions(info.definitions, ex_string_info.definitions) + + info = %{info | definitions: definitions} + + {:ok, info} + end + + # Replace some modules with ElixirScript versions + def debug_info(module) when module in [Agent] do + case do_debug_info(Module.concat(ElixirScript, module)) do {:ok, info} -> {:ok, Map.put(info, :module, module)} e -> @@ -21,6 +36,10 @@ defmodule ElixirScript.Beam do end def debug_info(module) when is_atom(module) do + do_debug_info(module) + end + + defp do_debug_info(module) when is_atom(module) do #TODO: Get modified date from _beam_path to check for cached version? with {_, beam, _beam_path} <- :code.get_object_code(module), {:ok, {^module, [debug_info: {:debug_info_v1, backend, data}]}} <- :beam_lib.chunks(beam, [:debug_info]), @@ -59,4 +78,21 @@ defmodule ElixirScript.Beam do {:ok, module, implementations} end -end \ No newline at end of file + defp replace_definitions(original_definitions, replacement_definitions) do + Enum.map(original_definitions, fn + {{function, arity}, type, _, _} = ast -> + ex_ast = Enum.find(replacement_definitions, fn + {{ex_function, ex_arity}, ex_type, _, _} -> + ex_function == function and ex_arity == arity and ex_type == type + end) + + case ex_ast do + nil -> + ast + _ -> + ex_ast + end + end) + end + +end diff --git a/lib/elixir_script/passes/translate/forms/remote.ex b/lib/elixir_script/passes/translate/forms/remote.ex index 59f23bc4..70651e11 100644 --- a/lib/elixir_script/passes/translate/forms/remote.ex +++ b/lib/elixir_script/passes/translate/forms/remote.ex @@ -17,7 +17,8 @@ defmodule ElixirScript.Translate.Forms.Remote do :elixir_utils, :file, :io, - :binary + :binary, + :unicode ] @doc """ diff --git a/src/javascript/lib/core.js b/src/javascript/lib/core.js index f47e61bd..99305e96 100644 --- a/src/javascript/lib/core.js +++ b/src/javascript/lib/core.js @@ -8,6 +8,7 @@ import lists from './core/erlang_compat/lists'; import elixir_errors from './core/erlang_compat/elixir_errors'; import io from './core/erlang_compat/io'; import binary from './core/erlang_compat/binary'; +import unicode from './core/erlang_compat/unicode'; import Store from './core/store'; class Integer {} @@ -47,5 +48,6 @@ export default { lists, elixir_errors, io, - binary + binary, + unicode }; diff --git a/src/javascript/lib/core/erlang_compat/unicode.js b/src/javascript/lib/core/erlang_compat/unicode.js new file mode 100644 index 00000000..c50c2890 --- /dev/null +++ b/src/javascript/lib/core/erlang_compat/unicode.js @@ -0,0 +1,18 @@ +import erlang from './erlang'; + +function characters_to_list(characters) { + return characters.split('').map(c => c.codePointAt(0)); +} + +function characters_to_binary(characters) { + if (erlang.is_binary(characters)) { + return characters; + } + + return String.fromCodePoint(...characters); +} + +export default { + characters_to_list, + characters_to_binary +}; diff --git a/test/support/main.ex b/test/support/main.ex index a18d3d90..c4b37b87 100644 --- a/test/support/main.ex +++ b/test/support/main.ex @@ -1,5 +1,7 @@ defmodule Main do def start(:normal, [callback]) do callback.("started") + + String.upcase("d") end end From f08f471942a7744c3082daee2188f11a7269dccc Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Sat, 29 Jul 2017 21:04:10 -0500 Subject: [PATCH 641/860] Add __info__ function to modules --- .../passes/translate/forms/pattern.ex | 6 +- lib/elixir_script/passes/translate/module.ex | 125 +++++++++++++++++- test/beam_test.exs | 6 - 3 files changed, 126 insertions(+), 11 deletions(-) diff --git a/lib/elixir_script/passes/translate/forms/pattern.ex b/lib/elixir_script/passes/translate/forms/pattern.ex index 7a86da69..26aa7089 100644 --- a/lib/elixir_script/passes/translate/forms/pattern.ex +++ b/lib/elixir_script/passes/translate/forms/pattern.ex @@ -223,10 +223,14 @@ defmodule ElixirScript.Translate.Forms.Pattern do unify(name, left, state) end - defp process_pattern({var, _, _}, _) do + defp process_pattern({var, _, a}, _) when is_atom(a) do { [PM.parameter(J.literal(to_string(var)))], [ElixirScript.Translate.Identifier.make_identifier(var)] } end + defp process_pattern(ast, state) do + { [Form.compile!(ast, state)], [] } + end + defp reduce_patterns(patterns, _) do patterns |> Enum.reduce({ [], [] }, fn({ pattern, new_param }, { patterns, new_params }) -> diff --git a/lib/elixir_script/passes/translate/module.ex b/lib/elixir_script/passes/translate/module.ex index 7dde8c3e..9343200d 100644 --- a/lib/elixir_script/passes/translate/module.ex +++ b/lib/elixir_script/passes/translate/module.ex @@ -3,6 +3,7 @@ defmodule ElixirScript.Translate.Module do alias ESTree.Tools.Builder, as: J alias ElixirScript.Translate.Function alias ElixirScript.State, as: ModuleState + alias ElixirScript.Translate.Form @doc """ Translate the given module's ast to @@ -59,15 +60,17 @@ defmodule ElixirScript.Translate.Module do #we combine our function arities combined_defs = combine_defs(used_defs) - exports = make_exports(module, combined_defs) + exports = make_exports(module, combined_defs, defs, state) # If there are no public exports, skip compilation case exports do - %ESTree.ObjectExpression{ properties: [] } -> + %ESTree.ObjectExpression{ properties: props } when length(props) == 2 -> nil _ -> { compiled_functions, _ } = Enum.map_reduce(combined_defs, state, &Function.compile(&1, &2)) + compiled_functions = compiled_functions ++ [make_info_function(module, defs, state)] + js_ast = ElixirScript.ModuleSystems.Namespace.build( module, compiled_functions, @@ -90,7 +93,7 @@ defmodule ElixirScript.Translate.Module do end) end - defp make_exports(module, reachable_defs) do + defp make_exports(module, reachable_defs, definitions, state) do exports = Enum.reduce(reachable_defs, [], fn {{name, _arity}, :def, _, _}, list -> function_name = ElixirScript.Translate.Identifier.make_identifier(name) @@ -110,7 +113,13 @@ defmodule ElixirScript.Translate.Module do ), [J.literal(to_string(module))] ) - }] + }, + J.property( + J.identifier("__info__"), + J.identifier("__info__"), + :init, + true + )] J.object_expression(exports) end @@ -150,4 +159,112 @@ defmodule ElixirScript.Translate.Module do false end end + + # Builds the __info__ function that Elixir modules + # have. Only supports the `functions`, `macros` and + # `module` kinds + defp make_info_function(module, definitions, state) do + functions = Enum.filter(definitions, fn + {_, :def, _, _} -> + true + _ -> + false + end) + |> Enum.map(fn + {func, _, _, _} -> + func + end) + + functions = Form.compile!(functions, state) + + macros = Enum.filter(definitions, fn + {_, :defmacro, _, _} -> + true + _ -> + false + end) + |> Enum.map(fn + {func, _, _, _} -> + func + end) + + macros = Form.compile!(macros, state) + + module = J.call_expression( + J.member_expression( + J.identifier("Symbol"), + J.identifier("for") + ), + [J.literal(to_string(module))] + ) + + body = J.if_statement( + J.binary_expression( + :===, + J.identifier("kind"), + J.call_expression( + J.member_expression( + J.identifier("Symbol"), + J.identifier("for") + ), + [J.literal("functions")] + ) + ), + J.block_statement([ + J.return_statement(functions) + ]), + J.if_statement( + J.binary_expression( + :===, + J.identifier("kind"), + J.call_expression( + J.member_expression( + J.identifier("Symbol"), + J.identifier("for") + ), + [J.literal("macros")] + ) + ), + J.block_statement([ + J.return_statement(macros) + ]), + J.if_statement( + J.binary_expression( + :===, + J.identifier("kind"), + J.call_expression( + J.member_expression( + J.identifier("Symbol"), + J.identifier("for") + ), + [J.literal("module")] + ) + ), + J.block_statement([ + J.return_statement(module) + ]) + ) + ) + ) + + body = J.block_statement([ + body, + J.throw_statement( + J.new_expression( + J.member_expression( + Function.patterns_ast(), + J.identifier("MatchError") + ), + [J.identifier("kind")] + ) + ) + ]) + + J.function_declaration( + J.identifier("__info__"), + [J.identifier("kind")], + [], + body + ) + end end diff --git a/test/beam_test.exs b/test/beam_test.exs index 43c45880..bc6671a3 100644 --- a/test/beam_test.exs +++ b/test/beam_test.exs @@ -12,10 +12,4 @@ defmodule ElixirScript.Beam.Test do test "can get ast from beam that is protocol" do assert {:ok, Enumerable, _} = ElixirScript.Beam.debug_info(Enumerable) end - - test "replaces String with ElixirScript.String" do - assert {:ok, map} = ElixirScript.Beam.debug_info(String) - assert {:ok, map2} = ElixirScript.Beam.debug_info(ElixirScript.String) - assert map.definitions == map2.definitions - end end From 51f9576968c5e2f68f5443b956d337548e10eeda Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Sat, 29 Jul 2017 21:06:36 -0500 Subject: [PATCH 642/860] Update travis.yml to final version of elixir 1.5.0 --- .travis.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index ed00c03d..9ac2cc0b 100644 --- a/.travis.yml +++ b/.travis.yml @@ -9,8 +9,8 @@ install: - npm install -g yarn - yarn before_script: - - wget https://repo.hex.pm/builds/elixir/v1.5.0-rc.2-otp-20.zip - - unzip -d elixir v1.5.0-rc.2-otp-20.zip + - wget https://repo.hex.pm/builds/elixir/v1.5.0-otp-20.zip + - unzip -d elixir v1.5.0-otp-20.zip - export PATH=$(pwd)/elixir/bin:${PATH} - mix local.rebar --force - mix local.hex --force From 5c0ef8b757224a69c060bca7fad2275d2c23aa1e Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Sun, 30 Jul 2017 04:40:29 -0500 Subject: [PATCH 643/860] Some bug fixes. Add elixir_config erlang compat module --- .tool-versions | 2 +- lib/elixir_script/passes/translate/clause.ex | 16 +---- lib/elixir_script/passes/translate/form.ex | 4 ++ .../passes/translate/forms/bitstring.ex | 2 +- .../passes/translate/forms/remote.ex | 1 + lib/elixir_script/passes/translate/module.ex | 4 +- package.json | 12 ++-- priv/build/iife/ElixirScript.Core.js | 10 +-- src/javascript/lib/core.js | 4 +- .../lib/core/erlang_compat/elixir_config.js | 43 +++++++++++++ .../lib/core/erlang_compat/erlang.js | 11 +++- test/support/main.ex | 2 - yarn.lock | 63 ++++++++++++++----- 13 files changed, 124 insertions(+), 50 deletions(-) create mode 100644 src/javascript/lib/core/erlang_compat/elixir_config.js diff --git a/.tool-versions b/.tool-versions index a6c3da3e..4676ecd7 100644 --- a/.tool-versions +++ b/.tool-versions @@ -1,3 +1,3 @@ erlang 20.0 elixir 1.5.0-otp-20 -nodejs 8.2.0 +nodejs 8.2.1 diff --git a/lib/elixir_script/passes/translate/clause.ex b/lib/elixir_script/passes/translate/clause.ex index 3cebc738..74d96f5e 100644 --- a/lib/elixir_script/passes/translate/clause.ex +++ b/lib/elixir_script/passes/translate/clause.ex @@ -2,6 +2,7 @@ defmodule ElixirScript.Translate.Clause do alias ESTree.Tools.Builder, as: J alias ElixirScript.Translate.Form alias ElixirScript.Translate.Forms.Pattern + alias ElixirScript.Translate.Function @moduledoc """ Handles translation of all of the clause ASTs @@ -19,20 +20,7 @@ defmodule ElixirScript.Translate.Clause do {patterns, params, state} = Pattern.compile(args, state) guard = compile_guard(params, guards, state) - body = case body do - nil -> - J.identifier("null") - {:__block__, _, block_body} -> - {list, _} = Enum.map_reduce(block_body, state, &Form.compile(&1, &2)) - List.flatten(list) - b when is_list(b) -> - {list, _} = Enum.map_reduce(b, state, &Form.compile(&1, &2)) - List.flatten(list) - _ -> - Form.compile!(body, state) - |> List.wrap - |> List.flatten - end + {body, _state} = Function.compile_block(body, state) body = body |> return_last_statement diff --git a/lib/elixir_script/passes/translate/form.ex b/lib/elixir_script/passes/translate/form.ex index a447a9b2..5f7e37b5 100644 --- a/lib/elixir_script/passes/translate/form.ex +++ b/lib/elixir_script/passes/translate/form.ex @@ -102,6 +102,10 @@ defmodule ElixirScript.Translate.Form do ElixirScript.Translate.Forms.Map.compile(map, state) end + def compile({:<<>>, _, []} = bitstring, state) do + Bitstring.compile(bitstring, state) + end + def compile({:<<>>, _, elements} = bitstring, state) do is_interpolated_string = Enum.all?(elements, fn(x) -> case x do diff --git a/lib/elixir_script/passes/translate/forms/bitstring.ex b/lib/elixir_script/passes/translate/forms/bitstring.ex index 0db3e2ef..80e872d2 100644 --- a/lib/elixir_script/passes/translate/forms/bitstring.ex +++ b/lib/elixir_script/passes/translate/forms/bitstring.ex @@ -27,7 +27,7 @@ defmodule ElixirScript.Translate.Forms.Bitstring do do_compile_element({:binary, Form.compile!(element, state)}) end - def compile_element({:<<>>, [], elements}, state) do + def compile_element({:<<>>, _, elements}, state) do {ast, _} = compile(elements, state) ast end diff --git a/lib/elixir_script/passes/translate/forms/remote.ex b/lib/elixir_script/passes/translate/forms/remote.ex index 70651e11..cf6ac235 100644 --- a/lib/elixir_script/passes/translate/forms/remote.ex +++ b/lib/elixir_script/passes/translate/forms/remote.ex @@ -11,6 +11,7 @@ defmodule ElixirScript.Translate.Forms.Remote do :lists, :gen, :elixir_errors, + :elixir_config, :supervisor, :application, :code, diff --git a/lib/elixir_script/passes/translate/module.ex b/lib/elixir_script/passes/translate/module.ex index 9343200d..43522b7b 100644 --- a/lib/elixir_script/passes/translate/module.ex +++ b/lib/elixir_script/passes/translate/module.ex @@ -60,7 +60,7 @@ defmodule ElixirScript.Translate.Module do #we combine our function arities combined_defs = combine_defs(used_defs) - exports = make_exports(module, combined_defs, defs, state) + exports = make_exports(module, combined_defs) # If there are no public exports, skip compilation case exports do @@ -93,7 +93,7 @@ defmodule ElixirScript.Translate.Module do end) end - defp make_exports(module, reachable_defs, definitions, state) do + defp make_exports(module, reachable_defs) do exports = Enum.reduce(reachable_defs, [], fn {{name, _arity}, :def, _, _}, list -> function_name = ElixirScript.Translate.Identifier.make_identifier(name) diff --git a/package.json b/package.json index 95032896..afaa2624 100644 --- a/package.json +++ b/package.json @@ -30,18 +30,20 @@ "babel-core": "^6.24.0", "babel-preset-env": "^1.6.0", "babel-register": "^6.24.0", - "eslint": "^4.2.0", - "eslint-config-airbnb-base": "^11.1.0", + "eslint": "^4.3.0", + "eslint-config-airbnb-base": "^11.3.1", "eslint-plugin-import": "^2.7.0", - "nyc": "^11.0.3", + "nyc": "^11.1.0", "rollup": "^0.45.2", "rollup-plugin-babel": "^2.7.1", "rollup-plugin-babili": "^3.1.0", "rollup-plugin-node-resolve": "^3.0.0", - "sinon": "^2.3.8" + "sinon": "^2.4.1" }, "ava": { - "require": ["babel-register"], + "require": [ + "babel-register" + ], "babel": { "babelrc": true } diff --git a/priv/build/iife/ElixirScript.Core.js b/priv/build/iife/ElixirScript.Core.js index 0242e617..44fc71e3 100644 --- a/priv/build/iife/ElixirScript.Core.js +++ b/priv/build/iife/ElixirScript.Core.js @@ -1,6 +1,6 @@ -var ElixirScript=function(){'use strict';/* @flow */function namedVariableResult(a,b){return new NamedVariableResult(a,b)}/* @flow */function is_number(a){return'number'==typeof a}function is_string(a){return'string'==typeof a}function is_boolean(a){return'boolean'==typeof a}function is_symbol(a){return'symbol'==typeof a}function is_object(a){return'object'==typeof a}function is_variable(a){return a instanceof Variable}function is_null(a){return null===a}function is_array(a){return Array.isArray(a)}function is_function(a){return'[object Function]'==Object.prototype.toString.call(a)}function is_map(a){return a instanceof Map}function resolveNull(){return function(a){return is_null(a)}}function resolveWildcard(){return function(){return!0}}function resolveObject(a){let b={};const c=Object.keys(a).concat(Object.getOwnPropertySymbols(a));for(let d of c)b[d]=buildMatch(a[d]);return function(d,e){if(!is_object(d)||a.length>d.length)return!1;for(let a of c)if(!(a in d)||!b[a](d[a],e))return!1;return!0}}function getSize(a,b){return a*b/8}function arraysEqual(c,a){if(c===a)return!0;if(null==c||null==a)return!1;if(c.length!=a.length)return!1;for(var b=0;be.integer(a));return new e(...b)}function resolveNoMatch(){return function(){return!1}}function buildMatch(a){if(null===a)return resolveNull(a);if('undefined'==typeof a)return resolveWildcard(a);const b=a.constructor.prototype,c=f.get(b);return c?c(a):'object'==typeof a?resolveObject(a):resolveNoMatch()}function defmatchgen(...a){const b=getArityMap(a);return function*(...a){let[c,d]=findMatchingFunction(a,b);return yield*c.apply(this,d)}}function findMatchingFunction(a,b){if(b.has(a.length)){const c=b.get(a.length);let d=null,e=null;for(let b of c){let c=[];a=fillInOptionalValues(a,b.arity,b.optionals);const f=b.pattern(a,c),[g,h]=checkNamedVariables(c);if(f&&h&&b.guard.apply(this,g)){d=b.fn,e=g;break}}if(!d)throw console.error('No match for:',a),new MatchError(a);return[d,e]}throw console.error('Arity of',a.length,'not found. No match for:',a),new MatchError(a)}function getArityMap(a){let b=new Map;for(const c of a){const a=getArityRange(c);for(const d of a){let a=[];b.has(d)&&(a=b.get(d)),a.push(c),b.set(d,a)}}return b}function getArityRange(a){const b=a.arity-a.optionals.length,c=a.arity;let d=[b];for(;d[d.length-1]!=c;)d.push(d[d.length-1]+1);return d}function getOptionalValues(a){let b=[];for(let c=0;c!0,d=null){let e=[],f=buildMatch(a);const g=f(b,e),[h,i]=checkNamedVariables(e);return g&&i&&c.apply(this,h)?h:d}function run_generators(a,b){if(0==b.length)return a.map((a)=>{return Array.isArray(a)?a:[a]});const c=b.pop();let d=[];for(let e of c())for(let b of a)d.push([e].concat(b));return run_generators(d,b)}function iterator_to_reducer(a,b,c){const d=a[Symbol.iterator]();let e=d.next(),f=b;for(;!1===e.done;){if(f=c(e.value,f.get(1)),f.get(0)===Symbol.for('halt'))return new o.Tuple(Symbol.for('halted'),f.get(1));if(f.get(0)===Symbol.for('suspend'))return new o.Tuple(Symbol.for('suspended'),f.get(1),(a)=>{return iterator_to_reducer(d,a,c)});e=d.next()}return new o.Tuple(Symbol.for('done'),f.get(1))}function map_to_object(a){const b={};for(const[c,d]of a.entries())b[c]=d instanceof Map?map_to_object(d):d;return b}function run_list_generators(a,b){if(0==b.length)return a.map((a)=>{return Array.isArray(a)?a:[a]});const c=b.pop(),d=[];for(const e of c())for(const b of a)d.push([e].concat(b));return run_list_generators(d,b)}// http://erlang.org/doc/man/lists.html +var ElixirScript=function(){'use strict';/* @flow */function namedVariableResult(a,b){return new NamedVariableResult(a,b)}/* @flow */function is_number(a){return'number'==typeof a}function is_string(a){return'string'==typeof a}function is_boolean(a){return'boolean'==typeof a}function is_symbol(a){return'symbol'==typeof a}function is_object(a){return'object'==typeof a}function is_variable(a){return a instanceof Variable}function is_null(a){return null===a}function is_array(a){return Array.isArray(a)}function is_function(a){return'[object Function]'==Object.prototype.toString.call(a)}function is_map(a){return a instanceof Map}function resolveNull(){return function(a){return is_null(a)}}function resolveWildcard(){return function(){return!0}}function resolveObject(a){let b={};const c=Object.keys(a).concat(Object.getOwnPropertySymbols(a));for(let d of c)b[d]=buildMatch(a[d]);return function(d,e){if(!is_object(d)||a.length>d.length)return!1;for(let a of c)if(!(a in d)||!b[a](d[a],e))return!1;return!0}}function getSize(a,b){return a*b/8}function arraysEqual(c,a){if(c===a)return!0;if(null==c||null==a)return!1;if(c.length!=a.length)return!1;for(var b=0;bf.integer(a));return new f(...b)}function resolveNoMatch(){return function(){return!1}}function buildMatch(a){if(null===a)return resolveNull(a);if('undefined'==typeof a)return resolveWildcard(a);const b=a.constructor.prototype,c=g.get(b);return c?c(a):'object'==typeof a?resolveObject(a):resolveNoMatch()}function defmatchgen(...a){const b=getArityMap(a);return function*(...a){let[c,d]=findMatchingFunction(a,b);return yield*c.apply(this,d)}}function findMatchingFunction(a,b){if(b.has(a.length)){const c=b.get(a.length);let d=null,e=null;for(let b of c){let c=[];a=fillInOptionalValues(a,b.arity,b.optionals);const f=b.pattern(a,c),[g,h]=checkNamedVariables(c);if(f&&h&&b.guard.apply(this,g)){d=b.fn,e=g;break}}if(!d)throw console.error('No match for:',a),new MatchError(a);return[d,e]}throw console.error('Arity of',a.length,'not found. No match for:',a),new MatchError(a)}function getArityMap(a){let b=new Map;for(const c of a){const a=getArityRange(c);for(const d of a){let a=[];b.has(d)&&(a=b.get(d)),a.push(c),b.set(d,a)}}return b}function getArityRange(a){const b=a.arity-a.optionals.length,c=a.arity;let d=[b];for(;d[d.length-1]!=c;)d.push(d[d.length-1]+1);return d}function getOptionalValues(a){let b=[];for(let c=0;c!0,d=null){let e=[],f=buildMatch(a);const g=f(b,e),[h,i]=checkNamedVariables(e);return g&&i&&c.apply(this,h)?h:d}function run_generators(a,b){if(0==b.length)return a.map((a)=>{return Array.isArray(a)?a:[a]});const c=b.pop();let d=[];for(let e of c())for(let b of a)d.push([e].concat(b));return run_generators(d,b)}function iterator_to_reducer(a,b,c){const d=a[Symbol.iterator]();let e=d.next(),f=b;for(;!1===e.done;){if(f=c(e.value,f.get(1)),f.get(0)===Symbol.for('halt'))return new r.Tuple(Symbol.for('halted'),f.get(1));if(f.get(0)===Symbol.for('suspend'))return new r.Tuple(Symbol.for('suspended'),f.get(1),(a)=>{return iterator_to_reducer(d,a,c)});e=d.next()}return new r.Tuple(Symbol.for('done'),f.get(1))}function map_to_object(a){const b={};for(const[c,d]of a.entries())b[c]=d instanceof Map?map_to_object(d):d;return b}function run_list_generators(a,b){if(0==b.length)return a.map((a)=>{return Array.isArray(a)?a:[a]});const c=b.pop(),d=[];for(const e of c())for(const b of a)d.push([e].concat(b));return run_list_generators(d,b)}// http://erlang.org/doc/man/lists.html function reverse(a){return[...a]}function flatten(a,b=[]){const c=a.reduce((a,b)=>{return Array.isArray(b)?a.concat(flatten(b)):a.concat(b)},[]);return c.concat(b)}function foldl(a,b,c){return c.reduce((b,c)=>{return a(c,b)},b)}function keyfind(a,b,c){for(const d of c)if(d.get(b-1)===a)return d;return!1}function keydelete(a,b,c){const d=[];let e=!1;for(let f=0;f{if(null===c)return a;return is_integer(c)?a+b(c):is_bitstring$1(c)?a+b(...c.value):a+iolist_to_binary(c)},'');return d}function is_key(a,b){return b.has(a)}function get_key(a){let b=a;if(__elixirscript_names__.has(a)&&(b=__elixirscript_names__.get(a)),__elixirscript_store__.has(b))return b;throw new Error(`Key ${b} not found`)}var a=Number.isInteger;class Variable{constructor(a=null,b=Symbol.for('tailored.no_value')){this.name=a,this.default_value=b}}class Wildcard{constructor(){}}class StartsWith{constructor(a){this.prefix=a}}class Capture{constructor(a){this.value=a}}class HeadTail{constructor(a,b){this.head=a,this.tail=b}}class Type{constructor(a,b={}){this.type=a,this.objPattern=b}}class Bound{constructor(a){this.value=a}}class BitStringMatch{constructor(...a){this.values=a}length(){return values.length}bit_size(){return 8*this.byte_size()}byte_size(){let a=0;for(let b of this.values)a+=b.unit*b.size/8;return a}getValue(a){return this.values(a)}getSizeOfValue(a){let b=this.getValue(a);return b.unit*b.size}getTypeOfValue(a){return this.getValue(a).type}}class NamedVariableResult{constructor(a,b){this.name=a,this.value=b}}class Tuple{constructor(...a){this.values=Object.freeze(a),this.length=this.values.length}get(a){return this.values[a]}count(){return this.values.length}[Symbol.iterator](){return this.values[Symbol.iterator]()}toString(){let a,b='';for(a=0;aBitString$1.integer(a));return new BitString$1(...d)}[Symbol.iterator](){return this.value[Symbol.iterator]()}toString(){var a,b='';for(a=0;a>'}process(a){let b=[];var c;for(c=0;cb?c.push(b):2048>b?c.push(192|b>>6,128|63&b):55296>b||57344<=b?c.push(224|b>>12,128|63&b>>6,128|63&b):(d++,b=65536+((1023&b)<<10|1023&a.charCodeAt(d)),c.push(240|b>>18,128|63&b>>12,128|63&b>>6,128|63&b));return c}static toUTF16Array(a){for(var b,c=[],d=0;d=b?(c.push(0),c.push(b)):(c.push(255&b>>8),c.push(255&b));return c}static toUTF32Array(a){for(var b,c=[],d=0;d=b?(c.push(0),c.push(0),c.push(0),c.push(b)):(c.push(0),c.push(0),c.push(255&b>>8),c.push(255&b));return c}//http://stackoverflow.com/questions/2003493/javascript-float-from-to-bits -static float32ToBytes(a){var b=[],c=new ArrayBuffer(4);new Float32Array(c)[0]=a;let d=new Uint32Array(c)[0];return b.push(255&d>>24),b.push(255&d>>16),b.push(255&d>>8),b.push(255&d),b}static float64ToBytes(a){var b=[],c=new ArrayBuffer(8);new Float64Array(c)[0]=a;var d=new Uint32Array(c)[0],e=new Uint32Array(c)[1];return b.push(255&e>>24),b.push(255&e>>16),b.push(255&e>>8),b.push(255&e),b.push(255&d>>24),b.push(255&d>>16),b.push(255&d>>8),b.push(255&d),b}}var d={Tuple,PID:class PID{constructor(){++b,this.id=b}toString(){return'PID#<0.'+this.id+'.0>'}},Reference:class Reference{constructor(){++c,this.id=c,this.ref=Symbol()}toString(){return'Ref#<0.0.0.'+this.id+'>'}},BitString:BitString$1};/* @flow */const e=d.BitString,f=new Map;f.set(Variable.prototype,function resolveVariable(a){return function(b,c){return null===a.name?c.push(b):!a.name.startsWith('_')&&c.push(namedVariableResult(a.name,b)),!0}}),f.set(Wildcard.prototype,resolveWildcard),f.set(HeadTail.prototype,function resolveHeadTail(a){const b=buildMatch(a.head),c=buildMatch(a.tail);return function(a,d){if(!is_array(a)||0===a.length)return!1;const e=a[0],f=a.slice(1);return b(e,d)&&c(f,d)}}),f.set(StartsWith.prototype,function resolveStartsWith(a){const b=a.prefix;return function(a,c){return is_string(a)&&a.startsWith(b)&&(c.push(a.substring(b.length)),!0)}}),f.set(Capture.prototype,function resolveCapture(a){const b=buildMatch(a.value);return function(a,c){return!!b(a,c)&&(c.push(a),!0)}}),f.set(Bound.prototype,function resolveBound(a){return function(b){return typeof b==typeof a.value&&b===a.value}}),f.set(Type.prototype,function resolveType(a){return function(b,c){if(b instanceof a.type){const d=buildMatch(a.objPattern);return d(b,c)}return!1}}),f.set(BitStringMatch.prototype,function resolveBitString(a){let b=[];for(let c of a.values)if(is_variable(c.value)){let a=getSize(c.unit,c.size);fillArray(b,a)}else b=b.concat(new e(c).value);let c=a.values;return function(a,d){var f=String.fromCharCode;let g=null;if(!is_string(a)&&!(a instanceof e))return!1;g=is_string(a)?new e(e.binary(a)):a;let h=0;for(let e,j=0;jd.size)return!1;for(let a of c)if(!d.has(a)||!b.get(a)(d.get(a),e))return!1;return!0}}),f.set(Array.prototype,function resolveArray(a){const b=a.map((a)=>buildMatch(a));return function(c,d){return is_array(c)&&c.length==a.length&&c.every(function(a,e){return b[e](c[e],d)})}}),f.set(String.prototype,function resolveString(a){return function(b){return is_string(b)&&b===a}}),f.set(Boolean.prototype,function resolveBoolean(a){return function(b){return is_boolean(b)&&b===a}}),f.set(Function.prototype,function resolveFunction(a){return function(b){return is_function(b)&&b===a}}),f.set(Object.prototype,resolveObject);class MatchError extends Error{constructor(a){if(super(),'symbol'==typeof a)this.message='No match for: '+a.toString();else if(Array.isArray(a)){let b=a.map((a)=>{return null===a?'null':'undefined'==typeof a?'undefined':a.toString()});this.message='No match for: '+b}else this.message='No match for: '+a;this.stack=new Error().stack,this.name=this.constructor.name}}class Clause{constructor(a,b,c=()=>!0){this.pattern=buildMatch(a),this.arity=a.length,this.optionals=getOptionalValues(a),this.fn=b,this.guard=c}}const g=Symbol();// https://github.com/airportyh/protomorphism -class Protocol{constructor(b){function createFun(b){return function(...c){const d=c[0];let e=null;if(null===d&&this.hasImplementation(Symbol('null'))?e=this.registry.get(Symbol)[b]:a(d)&&this.hasImplementation(o.Integer)?e=this.registry.get(o.Integer)[b]:'number'==typeof d&&!a(d)&&this.hasImplementation(o.Float)?e=this.registry.get(o.Float)[b]:'string'==typeof d&&this.hasImplementation(o.BitString)?e=this.registry.get(o.BitString)[b]:d&&d instanceof Map&&d.has(Symbol.for('__struct__'))&&this.hasImplementation(d)?e=this.registry.get(d.get(Symbol.for('__struct__')).__MODULE__)[b]:null!==d&&this.hasImplementation(d)?e=this.registry.get(d.constructor)[b]:this.fallback&&(e=this.fallback[b]),null!=e){const a=e.apply(this,c);return a}throw new Error(`No implementation found for ${d}`)}}for(const a in this.registry=new Map,this.fallback=null,b)this[a]=createFun(a).bind(this)}implementation(a,b){null===a?this.fallback=b:this.registry.set(a,b)}hasImplementation(a){if(a===o.Integer||a===o.Float||a===o.BitString)return this.registry.has(a);return a&&a instanceof Map&&a.has(Symbol.for('__struct__'))?this.registry.has(a.get(Symbol.for('__struct__')).__MODULE__):this.registry.has(a.constructor)}}class Recurse{constructor(a){this.func=a}}var h={reverse,foreach:function foreach(a,b){return b.forEach((b)=>a(b)),Symbol.for('ok')},duplicate:function duplicate(a,b){const c=[];for(;c.length{if(d.get(c-1)a.get(c-1)?1:0})},keystore:function keystore(a,b,c,d){const e=[...c];for(let f=0;fa.toString()).join()},map:function map(a,b){return b.map((b)=>a(b))},filter:function filter(a,b){return b.filter((b)=>a(b))},filtermap:function filtermap(a,b){const c=[];for(const e of b){const b=a(e);!0===b?c.push(e):b instanceof d.Tuple&&!0===b.get(0)&&c.push(b.get(1))}return c},member:function member(a,b){for(const c of b)if(c===a)return!0;return!1},all:function all(a,b){for(const c of b)if(!1===a(c))return!1;return!0},any:function any(a,b){for(const c of b)if(!0===a(c))return!0;return!1},splitwith:function splitwith(a,b){let c=!1;const e=[],f=[];for(const d of b)!0==c?f.push(d):!0===a(d)?e.push(d):(c=!0,f.push(d));return new d.Tuple(e,f)},sort:function sort(...a){if(1===a.length){const b=[...a[0]];return b.sort()}const c=a[0],b=[...a[1]];return b.sort((d,a)=>{const b=c(d,a);return!0===b?-1:1})}},i={atom_to_binary,binary_to_atom,binary_to_existing_atom:function binary_to_existing_atom(a,b=Symbol.for('utf8')){return binary_to_atom(a,b)},list_concatenation:function list_concatenation(a,b){return a.concat(b)},list_subtraction:function list_subtraction(a,b){const c=[...a];for(const d of b){const a=c.indexOf(d);-1>b},bxor:function bxor(a,b){return a^b},bnot:function bnot(a){return~a},is_bitstring:is_bitstring$1,is_boolean:function is_boolean$1(a){return'boolean'==typeof a||a instanceof Boolean},is_float:function is_float(b){return is_number$1(b)&&!a(b)},is_function:function is_function$1(a){return'function'==typeof a||a instanceof Function},is_integer,is_list:function is_list(a){return Array.isArray(a)},is_map:function is_map$1(a){return a instanceof Map},is_number:is_number$1,is_pid:function is_pid(a){return a instanceof d.PID},is_port:function is_port(){return!1},is_reference:function is_reference(a){return a instanceof d.Reference},is_tuple:function is_tuple(a){return a instanceof d.Tuple},is_atom:function is_atom(a){return'symbol'==typeof a||a instanceof Symbol||a.__MODULE__},is_binary,element:function element(a,b){return b.get(a-1)},setelement:function setelement(a,b,c){const e=[...b.values];return e[a-1]=c,new d.Tuple(...e)},make_tuple:function make_tuple(a,b){const c=[];for(let d=0;d!0){let d=[],e=buildMatch(a);const f=e(b,d),[g,h]=checkNamedVariables(d);if(f&&h&&c.apply(this,g))return g;throw console.error('No match for:',b),new MatchError(b)},MatchError,variable:function variable(a=null,b=Symbol.for('tailored.no_value')){return new Variable(a,b)},wildcard:function wildcard(){return new Wildcard},startsWith:function startsWith(a){return new StartsWith(a)},capture:function capture(a){return new Capture(a)},headTail:function headTail(a,b){return new HeadTail(a,b)},type:function a(a,b={}){return new Type(a,b)},bound:function bound(a){return new Bound(a)},Clause,clause:function clause(a,b,c=()=>!0){return new Clause(a,b,c)},bitStringMatch:function bitStringMatch(...a){return new BitStringMatch(...a)},match_or_default,defmatchgen,list_comprehension:function list_comprehension(a,b){const c=run_generators(b.pop()(),b);let d=[];for(let e of c)a.guard.apply(this,e)&&d.push(a.fn.apply(this,e));return d},list_generator:function list_generator(a,b){return function(){let c=[];for(let d of b){const b=match_or_default(a,d,()=>!0,g);if(b!=g){const[a]=b;c.push(a)}}return c}},bitstring_generator:function bitstring_generator(a,b){return function(){let c=[],d=b.slice(0,a.byte_size()),e=1;for(;d.byte_size==a.byte_size();){const f=match_or_default(a,d,()=>!0,g);if(f!=g){c.push(f)}d=b.slice(a.byte_size()*e,a.byte_size()*(e+1)),e++}return c}},bitstring_comprehension:function bitstring_comprehension(a,b){const c=run_generators(b.pop()(),b);let e=[];for(let d of c)a.guard.apply(this,d)&&e.push(a.fn.apply(this,d));return e=e.map((a)=>d.BitString.integer(a)),new d.BitString(...e)},defmatchGen:function defmatchGen(...a){return defmatchgen(...a)},defmatchAsync:function defmatchAsync(...a){const b=getArityMap(a);return async function(...a){if(b.has(a.length)){const c=b.get(a.length);let d=null,e=null;for(let b of c){let c=[];a=fillInOptionalValues(a,b.arity,b.optionals);const f=b.pattern(a,c),[g,h]=checkNamedVariables(c);if(f&&h&&(await b.guard.apply(this,c))){d=b.fn,e=c;break}}if(!d)throw console.error('No match for:',a),new MatchError(a);return d.apply(this,e)}throw console.error('Arity of',a.length,'not found. No match for:',a),new MatchError(a)}}},Integer:class Integer{},Float:class Float{},Functions:{call_property:function call_property(a,b){if(!b)return a instanceof Function||'function'==typeof a?a():a;if(a instanceof Map){let c=null;if(a.has(b)?c=b:a.has(Symbol.for(b))&&(c=Symbol.for(b)),null===c)throw new Error(`Property ${b} not found in ${a}`);return a.get(c)instanceof Function||'function'==typeof a.get(c)?a.get(c)():a.get(c)}let c=null;if('number'==typeof a||'symbol'==typeof a||'boolean'==typeof a||'string'==typeof a?void 0===a[b]?void 0!==a[Symbol.for(b)]&&(c=Symbol.for(b)):c=b:b in a?c=b:Symbol.for(b)in a&&(c=Symbol.for(b)),null===c)throw new Error(`Property ${b} not found in ${a}`);return a[c]instanceof Function||'function'==typeof a[c]?a[c]():a[c]},defprotocol:function defprotocol(a){return new Protocol(a)},defimpl:function defimpl(a,b,c){a.implementation(b,c)},build_namespace:function build_namespace(a,b){let c=b.split('.');const d=a;let e=a;'Elixir'===c[0]&&(c=c.slice(1));for(const d of c)'undefined'==typeof e[d]&&(e[d]={}),e=e[d];return d.__table__=a.__table__||{},d.__table__[Symbol.for(b)]=e,e},iterator_to_reducer,map_to_object,trampoline:function trampoline$1(a){let b=a;for(;b&&b instanceof Recurse;)b=b.func();return b},Recurse},SpecialForms:{_case:function _case(a,b){return o.Patterns.defmatch(...b)(a)},cond:function cond(...a){for(const b of a)if(b[0])return b[1]();throw new Error},_for:function _for(a,b,c,d=[]){let[e,f]=c.into(d);const g=run_list_generators(b.pop()(),b);for(const h of g)a.guard.apply(this,h)&&(e=f(e,new o.Tuple(Symbol.for('cont'),a.fn.apply(this,h))));return f(e,Symbol.for('done'))},_try:function _try(a,b,c,d,e){let f=null;try{f=a()}catch(a){let d=null;if(b)try{return d=b(a),d}catch(a){if(a instanceof o.Patterns.MatchError)throw a}if(c)try{return d=c(a),d}catch(a){if(a instanceof o.Patterns.MatchError)throw a}throw a}finally{e&&e()}if(d)try{return d(f)}catch(a){if(a instanceof o.Patterns.MatchError)throw new Error('No Match Found in Else');throw a}else return f},_with:function _with(...a){let b=[],c=null,d=null;'function'==typeof a[a.length-2]?[c,d]=a.splice(-2):c=a.pop();for(let c=0;c{const[c,d]=b;return a.set(c,d),a},new Map)},keys:function keys(a){return!1===i.is_map(a)?new d.Tuple(l,a):Array.from(a.keys())},values:function values$1(a){return!1===i.is_map(a)?new d.Tuple(l,a):Array.from(a.values())},is_key,put:function put(a,b,c){if(!1===i.is_map(c))return new d.Tuple(l,c);const e=new Map(c);return e.set(a,b),e},merge:function merge(a,b){return!1===i.is_map(a)?new d.Tuple(l,a):!1===i.is_map(b)?new d.Tuple(l,b):new Map([...a,...b])},update:function update(a,b,c){return!1===i.is_map(c)?new d.Tuple(l,c):!1===is_key(a,c)?new d.Tuple(m,a):new Map([...c,[a,b]])},get:function get(...a){const b=a[0],c=a[1];return!1===i.is_map(c)?new d.Tuple(l,c):is_key(b)?c.get(b):3===a.length?a[2]:new d.Tuple(m,b)},take:function take(a,b){if(!1===i.is_map(b))return new d.Tuple(l,b);if(!is_key(a))return k;const c=b.get(a),e=new Map(b);return e.delete(a),new d.Tuple(c,e)}},lists:h,elixir_errors:{warn:function warn(a){const b=a.join('');return console.warn(`warning: ${b}`),Symbol.for('ok')}},io:{put_chars:function put_chars(a,b){const c=i.iolist_to_binary(b);return a===Symbol.for('stderr')?console.error(c):console.log(c),Symbol.for('ok')}},binary:{copy:function copy(a,b=1){return a.repeat(b)}}};return{Core:o}}(); +function atom_to_binary(a,b=Symbol.for('utf8')){if(b!==Symbol.for('utf8'))throw new Error(`unsupported encoding ${b}`);return a.__MODULE__?Symbol.keyFor(a.__MODULE__):Symbol.keyFor(a)}function binary_to_atom(a,b=Symbol.for('utf8')){if(b!==Symbol.for('utf8'))throw new Error(`unsupported encoding ${b}`);return Symbol.for(a)}function is_bitstring$1(a){return a instanceof e.BitString}function is_number$1(a){return'number'==typeof a||a instanceof Number}function is_integer(a){return b(a)}function is_binary(a){return'string'==typeof a||a instanceof String}function iolist_to_binary(b){if(console.log(b),null===b)return'';if(is_binary(b))return b;if(is_bitstring$1(b))return a(...b.value);if(is_number$1(b))return a(b);const c=i.flatten(b);console.log(c);const d=c.reduce((b,c)=>{return null===c?b:is_integer(c)?b+a(c):is_bitstring$1(c)?b+a(...c.value):b+iolist_to_binary(c)},'');return d}function is_key(a,b){return b.has(a)}function put$1(a,b){return p.get(o).set(a,b),Symbol.for('ok')}function get$1(a){return p.get(o).get(a)}function get_key(a){let b=a;if(__elixirscript_names__.has(a)&&(b=__elixirscript_names__.get(a)),__elixirscript_store__.has(b))return b;throw new Error(`Key ${b} not found`)}var a=String.fromCodePoint,b=Number.isInteger;class Variable{constructor(a=null,b=Symbol.for('tailored.no_value')){this.name=a,this.default_value=b}}class Wildcard{constructor(){}}class StartsWith{constructor(a){this.prefix=a}}class Capture{constructor(a){this.value=a}}class HeadTail{constructor(a,b){this.head=a,this.tail=b}}class Type{constructor(a,b={}){this.type=a,this.objPattern=b}}class Bound{constructor(a){this.value=a}}class BitStringMatch{constructor(...a){this.values=a}length(){return values.length}bit_size(){return 8*this.byte_size()}byte_size(){let a=0;for(let b of this.values)a+=b.unit*b.size/8;return a}getValue(a){return this.values(a)}getSizeOfValue(a){let b=this.getValue(a);return b.unit*b.size}getTypeOfValue(a){return this.getValue(a).type}}class NamedVariableResult{constructor(a,b){this.name=a,this.value=b}}class Tuple{constructor(...a){this.values=Object.freeze(a),this.length=this.values.length}get(a){return this.values[a]}count(){return this.values.length}[Symbol.iterator](){return this.values[Symbol.iterator]()}toString(){let a,b='';for(a=0;aBitString$1.integer(a));return new BitString$1(...d)}[Symbol.iterator](){return this.value[Symbol.iterator]()}toString(){var a,b='';for(a=0;a>'}process(a){let b=[];var c;for(c=0;cb?c.push(b):2048>b?c.push(192|b>>6,128|63&b):55296>b||57344<=b?c.push(224|b>>12,128|63&b>>6,128|63&b):(d++,b=65536+((1023&b)<<10|1023&a.charCodeAt(d)),c.push(240|b>>18,128|63&b>>12,128|63&b>>6,128|63&b));return c}static toUTF16Array(a){for(var b,c=[],d=0;d=b?(c.push(0),c.push(b)):(c.push(255&b>>8),c.push(255&b));return c}static toUTF32Array(a){for(var b,c=[],d=0;d=b?(c.push(0),c.push(0),c.push(0),c.push(b)):(c.push(0),c.push(0),c.push(255&b>>8),c.push(255&b));return c}//http://stackoverflow.com/questions/2003493/javascript-float-from-to-bits +static float32ToBytes(a){var b=[],c=new ArrayBuffer(4);new Float32Array(c)[0]=a;let d=new Uint32Array(c)[0];return b.push(255&d>>24),b.push(255&d>>16),b.push(255&d>>8),b.push(255&d),b}static float64ToBytes(a){var b=[],c=new ArrayBuffer(8);new Float64Array(c)[0]=a;var d=new Uint32Array(c)[0],e=new Uint32Array(c)[1];return b.push(255&e>>24),b.push(255&e>>16),b.push(255&e>>8),b.push(255&e),b.push(255&d>>24),b.push(255&d>>16),b.push(255&d>>8),b.push(255&d),b}}var e={Tuple,PID:class PID{constructor(){++c,this.id=c}toString(){return'PID#<0.'+this.id+'.0>'}},Reference:class Reference{constructor(){++d,this.id=d,this.ref=Symbol()}toString(){return'Ref#<0.0.0.'+this.id+'>'}},BitString:BitString$1};/* @flow */const f=e.BitString,g=new Map;g.set(Variable.prototype,function resolveVariable(a){return function(b,c){return null===a.name?c.push(b):!a.name.startsWith('_')&&c.push(namedVariableResult(a.name,b)),!0}}),g.set(Wildcard.prototype,resolveWildcard),g.set(HeadTail.prototype,function resolveHeadTail(a){const b=buildMatch(a.head),c=buildMatch(a.tail);return function(a,d){if(!is_array(a)||0===a.length)return!1;const e=a[0],f=a.slice(1);return b(e,d)&&c(f,d)}}),g.set(StartsWith.prototype,function resolveStartsWith(a){const b=a.prefix;return function(a,c){return is_string(a)&&a.startsWith(b)&&(c.push(a.substring(b.length)),!0)}}),g.set(Capture.prototype,function resolveCapture(a){const b=buildMatch(a.value);return function(a,c){return!!b(a,c)&&(c.push(a),!0)}}),g.set(Bound.prototype,function resolveBound(a){return function(b){return typeof b==typeof a.value&&b===a.value}}),g.set(Type.prototype,function resolveType(a){return function(b,c){if(b instanceof a.type){const d=buildMatch(a.objPattern);return d(b,c)}return!1}}),g.set(BitStringMatch.prototype,function resolveBitString(a){let b=[];for(let c of a.values)if(is_variable(c.value)){let a=getSize(c.unit,c.size);fillArray(b,a)}else b=b.concat(new f(c).value);let c=a.values;return function(a,d){var e=String.fromCharCode;let g=null;if(!is_string(a)&&!(a instanceof f))return!1;g=is_string(a)?new f(f.binary(a)):a;let h=0;for(let f,j=0;jd.size)return!1;for(let a of c)if(!d.has(a)||!b.get(a)(d.get(a),e))return!1;return!0}}),g.set(Array.prototype,function resolveArray(a){const b=a.map((a)=>buildMatch(a));return function(c,d){return is_array(c)&&c.length==a.length&&c.every(function(a,e){return b[e](c[e],d)})}}),g.set(String.prototype,function resolveString(a){return function(b){return is_string(b)&&b===a}}),g.set(Boolean.prototype,function resolveBoolean(a){return function(b){return is_boolean(b)&&b===a}}),g.set(Function.prototype,function resolveFunction(a){return function(b){return is_function(b)&&b===a}}),g.set(Object.prototype,resolveObject);class MatchError extends Error{constructor(a){if(super(),'symbol'==typeof a)this.message='No match for: '+a.toString();else if(Array.isArray(a)){let b=a.map((a)=>{return null===a?'null':'undefined'==typeof a?'undefined':a.toString()});this.message='No match for: '+b}else this.message='No match for: '+a;this.stack=new Error().stack,this.name=this.constructor.name}}class Clause{constructor(a,b,c=()=>!0){this.pattern=buildMatch(a),this.arity=a.length,this.optionals=getOptionalValues(a),this.fn=b,this.guard=c}}const h=Symbol();// https://github.com/airportyh/protomorphism +class Protocol{constructor(a){function createFun(a){return function(...c){const d=c[0];let e=null;if(null===d&&this.hasImplementation(Symbol('null'))?e=this.registry.get(Symbol)[a]:b(d)&&this.hasImplementation(r.Integer)?e=this.registry.get(r.Integer)[a]:'number'==typeof d&&!b(d)&&this.hasImplementation(r.Float)?e=this.registry.get(r.Float)[a]:'string'==typeof d&&this.hasImplementation(r.BitString)?e=this.registry.get(r.BitString)[a]:d&&d instanceof Map&&d.has(Symbol.for('__struct__'))&&this.hasImplementation(d)?e=this.registry.get(d.get(Symbol.for('__struct__')).__MODULE__)[a]:null!==d&&this.hasImplementation(d)?e=this.registry.get(d.constructor)[a]:this.fallback&&(e=this.fallback[a]),null!=e){const a=e.apply(this,c);return a}throw new Error(`No implementation found for ${d}`)}}for(const b in this.registry=new Map,this.fallback=null,a)this[b]=createFun(b).bind(this)}implementation(a,b){null===a?this.fallback=b:this.registry.set(a,b)}hasImplementation(a){if(a===r.Integer||a===r.Float||a===r.BitString)return this.registry.has(a);return a&&a instanceof Map&&a.has(Symbol.for('__struct__'))?this.registry.has(a.get(Symbol.for('__struct__')).__MODULE__):this.registry.has(a.constructor)}}class Recurse{constructor(a){this.func=a}}var i={reverse,foreach:function foreach(a,b){return b.forEach((b)=>a(b)),Symbol.for('ok')},duplicate:function duplicate(a,b){const c=[];for(;c.length{if(d.get(c-1)a.get(c-1)?1:0})},keystore:function keystore(a,b,c,d){const e=[...c];for(let f=0;fa.toString()).join()},map:function map(a,b){return b.map((b)=>a(b))},filter:function filter(a,b){return b.filter((b)=>a(b))},filtermap:function filtermap(a,b){const c=[];for(const d of b){const b=a(d);!0===b?c.push(d):b instanceof e.Tuple&&!0===b.get(0)&&c.push(b.get(1))}return c},member:function member(a,b){for(const c of b)if(c===a)return!0;return!1},all:function all(a,b){for(const c of b)if(!1===a(c))return!1;return!0},any:function any(a,b){for(const c of b)if(!0===a(c))return!0;return!1},splitwith:function splitwith(a,b){let c=!1;const d=[],f=[];for(const e of b)!0==c?f.push(e):!0===a(e)?d.push(e):(c=!0,f.push(e));return new e.Tuple(d,f)},sort:function sort(...a){if(1===a.length){const b=[...a[0]];return b.sort()}const c=a[0],b=[...a[1]];return b.sort((d,a)=>{const b=c(d,a);return!0===b?-1:1})}},j={atom_to_binary,binary_to_atom,binary_to_existing_atom:function binary_to_existing_atom(a,b=Symbol.for('utf8')){return binary_to_atom(a,b)},list_concatenation:function list_concatenation(a,b){return a.concat(b)},list_subtraction:function list_subtraction(a,b){const c=[...a];for(const d of b){const a=c.indexOf(d);-1>b},bxor:function bxor(a,b){return a^b},bnot:function bnot(a){return~a},is_bitstring:is_bitstring$1,is_boolean:function is_boolean$1(a){return'boolean'==typeof a||a instanceof Boolean},is_float:function is_float(a){return is_number$1(a)&&!b(a)},is_function:function is_function$1(a){return'function'==typeof a||a instanceof Function},is_integer,is_list:function is_list(a){return Array.isArray(a)},is_map:function is_map$1(a){return a instanceof Map},is_number:is_number$1,is_pid:function is_pid(a){return a instanceof e.PID},is_port:function is_port(){return!1},is_reference:function is_reference(a){return a instanceof e.Reference},is_tuple:function is_tuple(a){return a instanceof e.Tuple},is_atom:function is_atom(a){return'symbol'==typeof a||a instanceof Symbol||a.__MODULE__},is_binary,element:function element(a,b){return b.get(a-1)},setelement:function setelement(a,b,c){const d=[...b.values];return d[a-1]=c,new e.Tuple(...d)},make_tuple:function make_tuple(a,b){const c=[];for(let d=0;d!0){let d=[],e=buildMatch(a);const f=e(b,d),[g,h]=checkNamedVariables(d);if(f&&h&&c.apply(this,g))return g;throw console.error('No match for:',b),new MatchError(b)},MatchError,variable:function variable(a=null,b=Symbol.for('tailored.no_value')){return new Variable(a,b)},wildcard:function wildcard(){return new Wildcard},startsWith:function startsWith(a){return new StartsWith(a)},capture:function capture(a){return new Capture(a)},headTail:function headTail(a,b){return new HeadTail(a,b)},type:function a(a,b={}){return new Type(a,b)},bound:function bound(a){return new Bound(a)},Clause,clause:function clause(a,b,c=()=>!0){return new Clause(a,b,c)},bitStringMatch:function bitStringMatch(...a){return new BitStringMatch(...a)},match_or_default,defmatchgen,list_comprehension:function list_comprehension(a,b){const c=run_generators(b.pop()(),b);let d=[];for(let e of c)a.guard.apply(this,e)&&d.push(a.fn.apply(this,e));return d},list_generator:function list_generator(a,b){return function(){let c=[];for(let d of b){const b=match_or_default(a,d,()=>!0,h);if(b!=h){const[a]=b;c.push(a)}}return c}},bitstring_generator:function bitstring_generator(a,b){return function(){let c=[],d=b.slice(0,a.byte_size()),e=1;for(;d.byte_size==a.byte_size();){const f=match_or_default(a,d,()=>!0,h);if(f!=h){c.push(f)}d=b.slice(a.byte_size()*e,a.byte_size()*(e+1)),e++}return c}},bitstring_comprehension:function bitstring_comprehension(a,b){const c=run_generators(b.pop()(),b);let d=[];for(let e of c)a.guard.apply(this,e)&&d.push(a.fn.apply(this,e));return d=d.map((a)=>e.BitString.integer(a)),new e.BitString(...d)},defmatchGen:function defmatchGen(...a){return defmatchgen(...a)},defmatchAsync:function defmatchAsync(...a){const b=getArityMap(a);return async function(...a){if(b.has(a.length)){const c=b.get(a.length);let d=null,e=null;for(let b of c){let c=[];a=fillInOptionalValues(a,b.arity,b.optionals);const f=b.pattern(a,c),[g,h]=checkNamedVariables(c);if(f&&h&&(await b.guard.apply(this,c))){d=b.fn,e=c;break}}if(!d)throw console.error('No match for:',a),new MatchError(a);return d.apply(this,e)}throw console.error('Arity of',a.length,'not found. No match for:',a),new MatchError(a)}}},Integer:class Integer{},Float:class Float{},Functions:{call_property:function call_property(a,b){if(!b)return a instanceof Function||'function'==typeof a?a():a;if(a instanceof Map){let c=null;if(a.has(b)?c=b:a.has(Symbol.for(b))&&(c=Symbol.for(b)),null===c)throw new Error(`Property ${b} not found in ${a}`);return a.get(c)instanceof Function||'function'==typeof a.get(c)?a.get(c)():a.get(c)}let c=null;if('number'==typeof a||'symbol'==typeof a||'boolean'==typeof a||'string'==typeof a?void 0===a[b]?void 0!==a[Symbol.for(b)]&&(c=Symbol.for(b)):c=b:b in a?c=b:Symbol.for(b)in a&&(c=Symbol.for(b)),null===c)throw new Error(`Property ${b} not found in ${a}`);return a[c]instanceof Function||'function'==typeof a[c]?a[c]():a[c]},defprotocol:function defprotocol(a){return new Protocol(a)},defimpl:function defimpl(a,b,c){a.implementation(b,c)},build_namespace:function build_namespace(a,b){let c=b.split('.');const d=a;let e=a;'Elixir'===c[0]&&(c=c.slice(1));for(const d of c)'undefined'==typeof e[d]&&(e[d]={}),e=e[d];return d.__table__=a.__table__||{},d.__table__[Symbol.for(b)]=e,e},iterator_to_reducer,map_to_object,trampoline:function trampoline$1(a){let b=a;for(;b&&b instanceof Recurse;)b=b.func();return b},Recurse},SpecialForms:{_case:function _case(a,b){return r.Patterns.defmatch(...b)(a)},cond:function cond(...a){for(const b of a)if(b[0])return b[1]();throw new Error},_for:function _for(a,b,c,d=[]){let[e,f]=c.into(d);const g=run_list_generators(b.pop()(),b);for(const h of g)a.guard.apply(this,h)&&(e=f(e,new r.Tuple(Symbol.for('cont'),a.fn.apply(this,h))));return f(e,Symbol.for('done'))},_try:function _try(a,b,c,d,e){let f=null;try{f=a()}catch(a){let d=null;if(b)try{return d=b(a),d}catch(a){if(a instanceof r.Patterns.MatchError)throw a}if(c)try{return d=c(a),d}catch(a){if(a instanceof r.Patterns.MatchError)throw a}throw a}finally{e&&e()}if(d)try{return d(f)}catch(a){if(a instanceof r.Patterns.MatchError)throw new Error('No Match Found in Else');throw a}else return f},_with:function _with(...a){let b=[],c=null,d=null;'function'==typeof a[a.length-2]?[c,d]=a.splice(-2):c=a.pop();for(let c=0;c{const[c,d]=b;return a.set(c,d),a},new Map)},keys:function keys(a){return!1===j.is_map(a)?new e.Tuple(m,a):Array.from(a.keys())},values:function values$1(a){return!1===j.is_map(a)?new e.Tuple(m,a):Array.from(a.values())},is_key,put:function put(a,b,c){if(!1===j.is_map(c))return new e.Tuple(m,c);const d=new Map(c);return d.set(a,b),d},merge:function merge(a,b){return!1===j.is_map(a)?new e.Tuple(m,a):!1===j.is_map(b)?new e.Tuple(m,b):new Map([...a,...b])},update:function update(a,b,c){return!1===j.is_map(c)?new e.Tuple(m,c):!1===is_key(a,c)?new e.Tuple(n,a):new Map([...c,[a,b]])},get:function get(...a){const b=a[0],c=a[1];return!1===j.is_map(c)?new e.Tuple(m,c):is_key(b)?c.get(b):3===a.length?a[2]:new e.Tuple(n,b)},take:function take(a,b){if(!1===j.is_map(b))return new e.Tuple(m,b);if(!is_key(a))return l;const c=b.get(a),d=new Map(b);return d.delete(a),new e.Tuple(c,d)}},lists:i,elixir_errors:{warn:function warn(a){const b=a.join('');return console.warn(`warning: ${b}`),Symbol.for('ok')}},io:{put_chars:function put_chars(a,b){const c=j.iolist_to_binary(b);return a===Symbol.for('stderr')?console.error(c):console.log(c),Symbol.for('ok')}},binary:{copy:function copy(a,b=1){return a.repeat(b)}},unicode:{characters_to_list:function characters_to_list(a){return a.split('').map((a)=>a.codePointAt(0))},characters_to_binary:function characters_to_binary(b){return j.is_binary(b)?b:a(...b)}},elixir_config:{new:function _new(a){return p.set(o,new Map),p.get(o).set(o,a),o},delete:function _delete(a){return p.delete(a),!0},put:put$1,get:get$1,update:function update$1(a,b){const c=b(p.get(o).get(a));return put$1(a,c),c},get_and_put:function get_and_put(a,b){const c=get$1(a);return put$1(a,b),c}}};return{Core:r}}(); diff --git a/src/javascript/lib/core.js b/src/javascript/lib/core.js index 99305e96..65431d05 100644 --- a/src/javascript/lib/core.js +++ b/src/javascript/lib/core.js @@ -6,6 +6,7 @@ import erlang from './core/erlang_compat/erlang'; import maps from './core/erlang_compat/maps'; import lists from './core/erlang_compat/lists'; import elixir_errors from './core/erlang_compat/elixir_errors'; +import elixir_config from './core/erlang_compat/elixir_config'; import io from './core/erlang_compat/io'; import binary from './core/erlang_compat/binary'; import unicode from './core/erlang_compat/unicode'; @@ -49,5 +50,6 @@ export default { elixir_errors, io, binary, - unicode + unicode, + elixir_config }; diff --git a/src/javascript/lib/core/erlang_compat/elixir_config.js b/src/javascript/lib/core/erlang_compat/elixir_config.js new file mode 100644 index 00000000..1d785fd9 --- /dev/null +++ b/src/javascript/lib/core/erlang_compat/elixir_config.js @@ -0,0 +1,43 @@ +const MODULE = Symbol.for('elixir_config'); +const ets = new Map(); + +function _new(opts) { + ets.set(MODULE, new Map()); + ets.get(MODULE).set(MODULE, opts); + return MODULE; +} + +function _delete(module) { + ets.delete(module); + return true; +} + +function put(key, value) { + ets.get(MODULE).set(key, value); + return Symbol.for('ok'); +} + +function get(key) { + return ets.get(MODULE).get(key); +} + +function update(key, fun) { + const value = fun(ets.get(MODULE).get(key)); + put(key, value); + return value; +} + +function get_and_put(key, value) { + const oldValue = get(key); + put(key, value); + return oldValue; +} + +export default { + new: _new, + delete: _delete, + put, + get, + update, + get_and_put +}; diff --git a/src/javascript/lib/core/erlang_compat/erlang.js b/src/javascript/lib/core/erlang_compat/erlang.js index 78dcef94..5b853793 100644 --- a/src/javascript/lib/core/erlang_compat/erlang.js +++ b/src/javascript/lib/core/erlang_compat/erlang.js @@ -2,6 +2,10 @@ import ErlangTypes from 'erlang-types'; import lists from './lists'; +function atom_to_list(atom) { + return Symbol.keyFor(atom); +} + function atom_to_binary(atom, encoding = Symbol.for('utf8')) { if (encoding !== Symbol.for('utf8')) { throw new Error(`unsupported encoding ${encoding}`); @@ -198,8 +202,8 @@ function apply(...args) { return args[0][atom_to_binary(args[1])].apply(this, ...args[2]); } -function binary_part(binary, start, length) { - return binary.substring(start, start + length); +function binary_part(binary, start, _length) { + return binary.substring(start, start + _length); } function bit_size(bitstring) { @@ -368,5 +372,6 @@ export default { process_info, iolist_to_binary, io_size, - integer_to_binary + integer_to_binary, + atom_to_list }; diff --git a/test/support/main.ex b/test/support/main.ex index c4b37b87..a18d3d90 100644 --- a/test/support/main.ex +++ b/test/support/main.ex @@ -1,7 +1,5 @@ defmodule Main do def start(:normal, [callback]) do callback.("started") - - String.upcase("d") end end diff --git a/yarn.lock b/yarn.lock index 66443a82..d4a33f9c 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1354,6 +1354,14 @@ cross-spawn@^4, cross-spawn@^4.0.0: lru-cache "^4.0.1" which "^1.2.9" +cross-spawn@^5.1.0: + version "5.1.0" + resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-5.1.0.tgz#e8bd0efee58fcff6f8f94510a0a554bbfa235449" + dependencies: + lru-cache "^4.0.1" + shebang-command "^1.2.0" + which "^1.2.9" + cryptiles@2.x.x: version "2.0.5" resolved "https://registry.yarnpkg.com/cryptiles/-/cryptiles-2.0.5.tgz#3bdfecdc608147c1c67202fa291e7dca59eaa3b8" @@ -1515,9 +1523,11 @@ escape-string-regexp@^1.0.2, escape-string-regexp@^1.0.4, escape-string-regexp@^ version "1.0.5" resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4" -eslint-config-airbnb-base@^11.1.0: - version "11.2.0" - resolved "https://registry.yarnpkg.com/eslint-config-airbnb-base/-/eslint-config-airbnb-base-11.2.0.tgz#19a9dc4481a26f70904545ec040116876018f853" +eslint-config-airbnb-base@^11.3.1: + version "11.3.1" + resolved "https://registry.yarnpkg.com/eslint-config-airbnb-base/-/eslint-config-airbnb-base-11.3.1.tgz#c0ab108c9beed503cb999e4c60f4ef98eda0ed30" + dependencies: + eslint-restricted-globals "^0.1.1" eslint-import-resolver-node@^0.3.1: version "0.3.1" @@ -1548,6 +1558,10 @@ eslint-plugin-import@^2.7.0: minimatch "^3.0.3" read-pkg-up "^2.0.0" +eslint-restricted-globals@^0.1.1: + version "0.1.1" + resolved "https://registry.yarnpkg.com/eslint-restricted-globals/-/eslint-restricted-globals-0.1.1.tgz#35f0d5cbc64c2e3ed62e93b4b1a7af05ba7ed4d7" + eslint-scope@^3.7.1: version "3.7.1" resolved "https://registry.yarnpkg.com/eslint-scope/-/eslint-scope-3.7.1.tgz#3d63c3edfda02e06e01a452ad88caacc7cdcb6e8" @@ -1555,14 +1569,15 @@ eslint-scope@^3.7.1: esrecurse "^4.1.0" estraverse "^4.1.1" -eslint@^4.2.0: - version "4.2.0" - resolved "https://registry.yarnpkg.com/eslint/-/eslint-4.2.0.tgz#a2b3184111b198e02e9c7f3cca625a5e01c56b3d" +eslint@^4.3.0: + version "4.3.0" + resolved "https://registry.yarnpkg.com/eslint/-/eslint-4.3.0.tgz#fcd7c96376bbf34c85ee67ed0012a299642b108f" dependencies: ajv "^5.2.0" babel-code-frame "^6.22.0" chalk "^1.1.3" concat-stream "^1.6.0" + cross-spawn "^5.1.0" debug "^2.6.8" doctrine "^2.0.0" eslint-scope "^3.7.1" @@ -1571,6 +1586,7 @@ eslint@^4.2.0: estraverse "^4.2.0" esutils "^2.0.2" file-entry-cache "^2.0.0" + functional-red-black-tree "^1.0.1" glob "^7.1.2" globals "^9.17.0" ignore "^3.3.3" @@ -1589,6 +1605,7 @@ eslint@^4.2.0: pluralize "^4.0.0" progress "^2.0.0" require-uncached "^1.0.3" + semver "^5.3.0" strip-json-comments "~2.0.1" table "^4.0.1" text-table "~0.2.0" @@ -1853,6 +1870,10 @@ function-name-support@^0.2.0: version "0.2.0" resolved "https://registry.yarnpkg.com/function-name-support/-/function-name-support-0.2.0.tgz#55d3bfaa6eafd505a50f9bc81fdf57564a0bb071" +functional-red-black-tree@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz#1b0ab3bd553b2a0d6399d29c0e3ea0b252078327" + gauge@~2.7.3: version "2.7.4" resolved "https://registry.yarnpkg.com/gauge/-/gauge-2.7.4.tgz#2c03405c7538c39d7eb37b317022e325fb018bf7" @@ -2351,7 +2372,7 @@ istanbul-lib-hook@^1.0.7: dependencies: append-transform "^0.4.0" -istanbul-lib-instrument@^1.7.3: +istanbul-lib-instrument@^1.7.4: version "1.7.4" resolved "https://registry.yarnpkg.com/istanbul-lib-instrument/-/istanbul-lib-instrument-1.7.4.tgz#e9fd920e4767f3d19edc765e2d6b3f5ccbd0eea8" dependencies: @@ -2802,9 +2823,9 @@ number-is-nan@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/number-is-nan/-/number-is-nan-1.0.1.tgz#097b602b53422a522c1afb8790318336941a011d" -nyc@^11.0.3: - version "11.0.3" - resolved "https://registry.yarnpkg.com/nyc/-/nyc-11.0.3.tgz#0c28bc669a851621709bf7a08503034bee3812b6" +nyc@^11.1.0: + version "11.1.0" + resolved "https://registry.yarnpkg.com/nyc/-/nyc-11.1.0.tgz#d6b3c5e16892a25af63138ba484676aa8a22eda7" dependencies: archy "^1.0.0" arrify "^1.0.1" @@ -2818,7 +2839,7 @@ nyc@^11.0.3: glob "^7.0.6" istanbul-lib-coverage "^1.1.1" istanbul-lib-hook "^1.0.7" - istanbul-lib-instrument "^1.7.3" + istanbul-lib-instrument "^1.7.4" istanbul-lib-report "^1.1.1" istanbul-lib-source-maps "^1.2.1" istanbul-reports "^1.1.1" @@ -2829,7 +2850,7 @@ nyc@^11.0.3: resolve-from "^2.0.0" rimraf "^2.5.4" signal-exit "^3.0.1" - spawn-wrap "^1.3.7" + spawn-wrap "^1.3.8" test-exclude "^4.1.1" yargs "^8.0.1" yargs-parser "^5.0.0" @@ -3461,13 +3482,23 @@ set-immediate-shim@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/set-immediate-shim/-/set-immediate-shim-1.0.1.tgz#4b2b1b27eb808a9f8dcc481a58e5e56f599f3f61" +shebang-command@^1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/shebang-command/-/shebang-command-1.2.0.tgz#44aac65b695b03398968c39f363fee5deafdf1ea" + dependencies: + shebang-regex "^1.0.0" + +shebang-regex@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/shebang-regex/-/shebang-regex-1.0.0.tgz#da42f49740c0b42db2ca9728571cb190c98efea3" + signal-exit@^3.0.0, signal-exit@^3.0.1, signal-exit@^3.0.2: version "3.0.2" resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.2.tgz#b5fdc08f1287ea1178628e415e25132b73646c6d" -sinon@^2.3.8: - version "2.3.8" - resolved "https://registry.yarnpkg.com/sinon/-/sinon-2.3.8.tgz#31de06fed8fba3a671e576dd96d0a5863796f25c" +sinon@^2.4.1: + version "2.4.1" + resolved "https://registry.yarnpkg.com/sinon/-/sinon-2.4.1.tgz#021fd64b54cb77d9d2fb0d43cdedfae7629c3a36" dependencies: diff "^3.1.0" formatio "1.2.0" @@ -3518,7 +3549,7 @@ source-map@^0.5.0, source-map@^0.5.3, source-map@^0.5.6, source-map@~0.5.1: version "0.5.6" resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.5.6.tgz#75ce38f52bf0733c5a7f0c118d81334a2bb5f412" -spawn-wrap@^1.3.7: +spawn-wrap@^1.3.8: version "1.3.8" resolved "https://registry.yarnpkg.com/spawn-wrap/-/spawn-wrap-1.3.8.tgz#fa2a79b990cbb0bb0018dca6748d88367b19ec31" dependencies: From 1e010fb360aba7238e70174956ea5689edce7a1c Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Mon, 31 Jul 2017 21:28:01 -0500 Subject: [PATCH 644/860] Update estree dep --- mix.lock | 2 +- priv/build/iife/ElixirScript.Core.js | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/mix.lock b/mix.lock index 992c5f2f..46e32342 100644 --- a/mix.lock +++ b/mix.lock @@ -2,7 +2,7 @@ "certifi": {:hex, :certifi, "1.2.1", "c3904f192bd5284e5b13f20db3ceac9626e14eeacfbb492e19583cf0e37b22be", [:rebar3], [], "hexpm"}, "credo": {:hex, :credo, "0.8.3", "efe6e9078de64cefdd25d8df7a97292e29e63f42a8988990340eaf1f40d93224", [:mix], [{:bunt, "~> 0.2.0", [hex: :bunt, repo: "hexpm", optional: false]}], "hexpm"}, "earmark": {:hex, :earmark, "1.2.2", "f718159d6b65068e8daeef709ccddae5f7fdc770707d82e7d126f584cd925b74", [:mix], [], "hexpm"}, - "estree": {:hex, :estree, "2.6.0", "86a301b0c355fa55c19e7ef9dceb1b1e983c6df526a2b7846818a38c258fc3fb", [:mix], [], "hexpm"}, + "estree": {:hex, :estree, "2.6.1", "0a17cc0e9e35315dc4fcd79d30a746b1f3e9ed654be6084ce882ab491165ae22", [:mix], [], "hexpm"}, "ex_doc": {:hex, :ex_doc, "0.16.2", "3b3e210ebcd85a7c76b4e73f85c5640c011d2a0b2f06dcdf5acdb2ae904e5084", [:mix], [{:earmark, "~> 1.1", [hex: :earmark, repo: "hexpm", optional: false]}], "hexpm"}, "excoveralls": {:hex, :excoveralls, "0.7.1", "3dd659db19c290692b5e2c4a2365ae6d4488091a1ba58f62dcbdaa0c03da5491", [:mix], [{:exjsx, ">= 3.0.0", [hex: :exjsx, repo: "hexpm", optional: false]}, {:hackney, ">= 0.12.0", [hex: :hackney, repo: "hexpm", optional: false]}], "hexpm"}, "exjsx": {:hex, :exjsx, "4.0.0", "60548841e0212df401e38e63c0078ec57b33e7ea49b032c796ccad8cde794b5c", [:mix], [{:jsx, "~> 2.8.0", [hex: :jsx, repo: "hexpm", optional: false]}], "hexpm"}, diff --git a/priv/build/iife/ElixirScript.Core.js b/priv/build/iife/ElixirScript.Core.js index 44fc71e3..a0c0b537 100644 --- a/priv/build/iife/ElixirScript.Core.js +++ b/priv/build/iife/ElixirScript.Core.js @@ -1,6 +1,6 @@ var ElixirScript=function(){'use strict';/* @flow */function namedVariableResult(a,b){return new NamedVariableResult(a,b)}/* @flow */function is_number(a){return'number'==typeof a}function is_string(a){return'string'==typeof a}function is_boolean(a){return'boolean'==typeof a}function is_symbol(a){return'symbol'==typeof a}function is_object(a){return'object'==typeof a}function is_variable(a){return a instanceof Variable}function is_null(a){return null===a}function is_array(a){return Array.isArray(a)}function is_function(a){return'[object Function]'==Object.prototype.toString.call(a)}function is_map(a){return a instanceof Map}function resolveNull(){return function(a){return is_null(a)}}function resolveWildcard(){return function(){return!0}}function resolveObject(a){let b={};const c=Object.keys(a).concat(Object.getOwnPropertySymbols(a));for(let d of c)b[d]=buildMatch(a[d]);return function(d,e){if(!is_object(d)||a.length>d.length)return!1;for(let a of c)if(!(a in d)||!b[a](d[a],e))return!1;return!0}}function getSize(a,b){return a*b/8}function arraysEqual(c,a){if(c===a)return!0;if(null==c||null==a)return!1;if(c.length!=a.length)return!1;for(var b=0;bf.integer(a));return new f(...b)}function resolveNoMatch(){return function(){return!1}}function buildMatch(a){if(null===a)return resolveNull(a);if('undefined'==typeof a)return resolveWildcard(a);const b=a.constructor.prototype,c=g.get(b);return c?c(a):'object'==typeof a?resolveObject(a):resolveNoMatch()}function defmatchgen(...a){const b=getArityMap(a);return function*(...a){let[c,d]=findMatchingFunction(a,b);return yield*c.apply(this,d)}}function findMatchingFunction(a,b){if(b.has(a.length)){const c=b.get(a.length);let d=null,e=null;for(let b of c){let c=[];a=fillInOptionalValues(a,b.arity,b.optionals);const f=b.pattern(a,c),[g,h]=checkNamedVariables(c);if(f&&h&&b.guard.apply(this,g)){d=b.fn,e=g;break}}if(!d)throw console.error('No match for:',a),new MatchError(a);return[d,e]}throw console.error('Arity of',a.length,'not found. No match for:',a),new MatchError(a)}function getArityMap(a){let b=new Map;for(const c of a){const a=getArityRange(c);for(const d of a){let a=[];b.has(d)&&(a=b.get(d)),a.push(c),b.set(d,a)}}return b}function getArityRange(a){const b=a.arity-a.optionals.length,c=a.arity;let d=[b];for(;d[d.length-1]!=c;)d.push(d[d.length-1]+1);return d}function getOptionalValues(a){let b=[];for(let c=0;c!0,d=null){let e=[],f=buildMatch(a);const g=f(b,e),[h,i]=checkNamedVariables(e);return g&&i&&c.apply(this,h)?h:d}function run_generators(a,b){if(0==b.length)return a.map((a)=>{return Array.isArray(a)?a:[a]});const c=b.pop();let d=[];for(let e of c())for(let b of a)d.push([e].concat(b));return run_generators(d,b)}function iterator_to_reducer(a,b,c){const d=a[Symbol.iterator]();let e=d.next(),f=b;for(;!1===e.done;){if(f=c(e.value,f.get(1)),f.get(0)===Symbol.for('halt'))return new r.Tuple(Symbol.for('halted'),f.get(1));if(f.get(0)===Symbol.for('suspend'))return new r.Tuple(Symbol.for('suspended'),f.get(1),(a)=>{return iterator_to_reducer(d,a,c)});e=d.next()}return new r.Tuple(Symbol.for('done'),f.get(1))}function map_to_object(a){const b={};for(const[c,d]of a.entries())b[c]=d instanceof Map?map_to_object(d):d;return b}function run_list_generators(a,b){if(0==b.length)return a.map((a)=>{return Array.isArray(a)?a:[a]});const c=b.pop(),d=[];for(const e of c())for(const b of a)d.push([e].concat(b));return run_list_generators(d,b)}// http://erlang.org/doc/man/lists.html function reverse(a){return[...a]}function flatten(a,b=[]){const c=a.reduce((a,b)=>{return Array.isArray(b)?a.concat(flatten(b)):a.concat(b)},[]);return c.concat(b)}function foldl(a,b,c){return c.reduce((b,c)=>{return a(c,b)},b)}function keyfind(a,b,c){for(const d of c)if(d.get(b-1)===a)return d;return!1}function keydelete(a,b,c){const d=[];let e=!1;for(let f=0;f{return null===c?b:is_integer(c)?b+a(c):is_bitstring$1(c)?b+a(...c.value):b+iolist_to_binary(c)},'');return d}function is_key(a,b){return b.has(a)}function put$1(a,b){return p.get(o).set(a,b),Symbol.for('ok')}function get$1(a){return p.get(o).get(a)}function get_key(a){let b=a;if(__elixirscript_names__.has(a)&&(b=__elixirscript_names__.get(a)),__elixirscript_store__.has(b))return b;throw new Error(`Key ${b} not found`)}var a=String.fromCodePoint,b=Number.isInteger;class Variable{constructor(a=null,b=Symbol.for('tailored.no_value')){this.name=a,this.default_value=b}}class Wildcard{constructor(){}}class StartsWith{constructor(a){this.prefix=a}}class Capture{constructor(a){this.value=a}}class HeadTail{constructor(a,b){this.head=a,this.tail=b}}class Type{constructor(a,b={}){this.type=a,this.objPattern=b}}class Bound{constructor(a){this.value=a}}class BitStringMatch{constructor(...a){this.values=a}length(){return values.length}bit_size(){return 8*this.byte_size()}byte_size(){let a=0;for(let b of this.values)a+=b.unit*b.size/8;return a}getValue(a){return this.values(a)}getSizeOfValue(a){let b=this.getValue(a);return b.unit*b.size}getTypeOfValue(a){return this.getValue(a).type}}class NamedVariableResult{constructor(a,b){this.name=a,this.value=b}}class Tuple{constructor(...a){this.values=Object.freeze(a),this.length=this.values.length}get(a){return this.values[a]}count(){return this.values.length}[Symbol.iterator](){return this.values[Symbol.iterator]()}toString(){let a,b='';for(a=0;aBitString$1.integer(a));return new BitString$1(...d)}[Symbol.iterator](){return this.value[Symbol.iterator]()}toString(){var a,b='';for(a=0;a>'}process(a){let b=[];var c;for(c=0;cb?c.push(b):2048>b?c.push(192|b>>6,128|63&b):55296>b||57344<=b?c.push(224|b>>12,128|63&b>>6,128|63&b):(d++,b=65536+((1023&b)<<10|1023&a.charCodeAt(d)),c.push(240|b>>18,128|63&b>>12,128|63&b>>6,128|63&b));return c}static toUTF16Array(a){for(var b,c=[],d=0;d=b?(c.push(0),c.push(b)):(c.push(255&b>>8),c.push(255&b));return c}static toUTF32Array(a){for(var b,c=[],d=0;d=b?(c.push(0),c.push(0),c.push(0),c.push(b)):(c.push(0),c.push(0),c.push(255&b>>8),c.push(255&b));return c}//http://stackoverflow.com/questions/2003493/javascript-float-from-to-bits +function atom_to_binary(a,b=Symbol.for('utf8')){if(b!==Symbol.for('utf8'))throw new Error(`unsupported encoding ${b}`);return a.__MODULE__?Symbol.keyFor(a.__MODULE__):Symbol.keyFor(a)}function binary_to_atom(a,b=Symbol.for('utf8')){if(b!==Symbol.for('utf8'))throw new Error(`unsupported encoding ${b}`);return Symbol.for(a)}function is_bitstring$1(a){return a instanceof e.BitString}function is_number$1(a){return'number'==typeof a||a instanceof Number}function is_integer(a){return b(a)}function is_binary(a){return'string'==typeof a||a instanceof String}function iolist_to_binary(b){if(null===b)return'';if(is_binary(b))return b;if(is_bitstring$1(b))return a(...b.value);if(is_number$1(b))return a(b);const c=i.flatten(b),d=c.reduce((b,c)=>{if(null===c)return b;return is_integer(c)?b+a(c):is_bitstring$1(c)?b+a(...c.value):b+iolist_to_binary(c)},'');return d}function is_key(a,b){return b.has(a)}function put$1(a,b){return p.get(o).set(a,b),Symbol.for('ok')}function get$1(a){return p.get(o).get(a)}function get_key(a){let b=a;if(__elixirscript_names__.has(a)&&(b=__elixirscript_names__.get(a)),__elixirscript_store__.has(b))return b;throw new Error(`Key ${b} not found`)}var a=String.fromCodePoint,b=Number.isInteger;class Variable{constructor(a=null,b=Symbol.for('tailored.no_value')){this.name=a,this.default_value=b}}class Wildcard{constructor(){}}class StartsWith{constructor(a){this.prefix=a}}class Capture{constructor(a){this.value=a}}class HeadTail{constructor(a,b){this.head=a,this.tail=b}}class Type{constructor(a,b={}){this.type=a,this.objPattern=b}}class Bound{constructor(a){this.value=a}}class BitStringMatch{constructor(...a){this.values=a}length(){return values.length}bit_size(){return 8*this.byte_size()}byte_size(){let a=0;for(let b of this.values)a+=b.unit*b.size/8;return a}getValue(a){return this.values(a)}getSizeOfValue(a){let b=this.getValue(a);return b.unit*b.size}getTypeOfValue(a){return this.getValue(a).type}}class NamedVariableResult{constructor(a,b){this.name=a,this.value=b}}class Tuple{constructor(...a){this.values=Object.freeze(a),this.length=this.values.length}get(a){return this.values[a]}count(){return this.values.length}[Symbol.iterator](){return this.values[Symbol.iterator]()}toString(){let a,b='';for(a=0;aBitString$1.integer(a));return new BitString$1(...d)}[Symbol.iterator](){return this.value[Symbol.iterator]()}toString(){var a,b='';for(a=0;a>'}process(a){let b=[];var c;for(c=0;cb?c.push(b):2048>b?c.push(192|b>>6,128|63&b):55296>b||57344<=b?c.push(224|b>>12,128|63&b>>6,128|63&b):(d++,b=65536+((1023&b)<<10|1023&a.charCodeAt(d)),c.push(240|b>>18,128|63&b>>12,128|63&b>>6,128|63&b));return c}static toUTF16Array(a){for(var b,c=[],d=0;d=b?(c.push(0),c.push(b)):(c.push(255&b>>8),c.push(255&b));return c}static toUTF32Array(a){for(var b,c=[],d=0;d=b?(c.push(0),c.push(0),c.push(0),c.push(b)):(c.push(0),c.push(0),c.push(255&b>>8),c.push(255&b));return c}//http://stackoverflow.com/questions/2003493/javascript-float-from-to-bits static float32ToBytes(a){var b=[],c=new ArrayBuffer(4);new Float32Array(c)[0]=a;let d=new Uint32Array(c)[0];return b.push(255&d>>24),b.push(255&d>>16),b.push(255&d>>8),b.push(255&d),b}static float64ToBytes(a){var b=[],c=new ArrayBuffer(8);new Float64Array(c)[0]=a;var d=new Uint32Array(c)[0],e=new Uint32Array(c)[1];return b.push(255&e>>24),b.push(255&e>>16),b.push(255&e>>8),b.push(255&e),b.push(255&d>>24),b.push(255&d>>16),b.push(255&d>>8),b.push(255&d),b}}var e={Tuple,PID:class PID{constructor(){++c,this.id=c}toString(){return'PID#<0.'+this.id+'.0>'}},Reference:class Reference{constructor(){++d,this.id=d,this.ref=Symbol()}toString(){return'Ref#<0.0.0.'+this.id+'>'}},BitString:BitString$1};/* @flow */const f=e.BitString,g=new Map;g.set(Variable.prototype,function resolveVariable(a){return function(b,c){return null===a.name?c.push(b):!a.name.startsWith('_')&&c.push(namedVariableResult(a.name,b)),!0}}),g.set(Wildcard.prototype,resolveWildcard),g.set(HeadTail.prototype,function resolveHeadTail(a){const b=buildMatch(a.head),c=buildMatch(a.tail);return function(a,d){if(!is_array(a)||0===a.length)return!1;const e=a[0],f=a.slice(1);return b(e,d)&&c(f,d)}}),g.set(StartsWith.prototype,function resolveStartsWith(a){const b=a.prefix;return function(a,c){return is_string(a)&&a.startsWith(b)&&(c.push(a.substring(b.length)),!0)}}),g.set(Capture.prototype,function resolveCapture(a){const b=buildMatch(a.value);return function(a,c){return!!b(a,c)&&(c.push(a),!0)}}),g.set(Bound.prototype,function resolveBound(a){return function(b){return typeof b==typeof a.value&&b===a.value}}),g.set(Type.prototype,function resolveType(a){return function(b,c){if(b instanceof a.type){const d=buildMatch(a.objPattern);return d(b,c)}return!1}}),g.set(BitStringMatch.prototype,function resolveBitString(a){let b=[];for(let c of a.values)if(is_variable(c.value)){let a=getSize(c.unit,c.size);fillArray(b,a)}else b=b.concat(new f(c).value);let c=a.values;return function(a,d){var e=String.fromCharCode;let g=null;if(!is_string(a)&&!(a instanceof f))return!1;g=is_string(a)?new f(f.binary(a)):a;let h=0;for(let f,j=0;jd.size)return!1;for(let a of c)if(!d.has(a)||!b.get(a)(d.get(a),e))return!1;return!0}}),g.set(Array.prototype,function resolveArray(a){const b=a.map((a)=>buildMatch(a));return function(c,d){return is_array(c)&&c.length==a.length&&c.every(function(a,e){return b[e](c[e],d)})}}),g.set(String.prototype,function resolveString(a){return function(b){return is_string(b)&&b===a}}),g.set(Boolean.prototype,function resolveBoolean(a){return function(b){return is_boolean(b)&&b===a}}),g.set(Function.prototype,function resolveFunction(a){return function(b){return is_function(b)&&b===a}}),g.set(Object.prototype,resolveObject);class MatchError extends Error{constructor(a){if(super(),'symbol'==typeof a)this.message='No match for: '+a.toString();else if(Array.isArray(a)){let b=a.map((a)=>{return null===a?'null':'undefined'==typeof a?'undefined':a.toString()});this.message='No match for: '+b}else this.message='No match for: '+a;this.stack=new Error().stack,this.name=this.constructor.name}}class Clause{constructor(a,b,c=()=>!0){this.pattern=buildMatch(a),this.arity=a.length,this.optionals=getOptionalValues(a),this.fn=b,this.guard=c}}const h=Symbol();// https://github.com/airportyh/protomorphism class Protocol{constructor(a){function createFun(a){return function(...c){const d=c[0];let e=null;if(null===d&&this.hasImplementation(Symbol('null'))?e=this.registry.get(Symbol)[a]:b(d)&&this.hasImplementation(r.Integer)?e=this.registry.get(r.Integer)[a]:'number'==typeof d&&!b(d)&&this.hasImplementation(r.Float)?e=this.registry.get(r.Float)[a]:'string'==typeof d&&this.hasImplementation(r.BitString)?e=this.registry.get(r.BitString)[a]:d&&d instanceof Map&&d.has(Symbol.for('__struct__'))&&this.hasImplementation(d)?e=this.registry.get(d.get(Symbol.for('__struct__')).__MODULE__)[a]:null!==d&&this.hasImplementation(d)?e=this.registry.get(d.constructor)[a]:this.fallback&&(e=this.fallback[a]),null!=e){const a=e.apply(this,c);return a}throw new Error(`No implementation found for ${d}`)}}for(const b in this.registry=new Map,this.fallback=null,a)this[b]=createFun(b).bind(this)}implementation(a,b){null===a?this.fallback=b:this.registry.set(a,b)}hasImplementation(a){if(a===r.Integer||a===r.Float||a===r.BitString)return this.registry.has(a);return a&&a instanceof Map&&a.has(Symbol.for('__struct__'))?this.registry.has(a.get(Symbol.for('__struct__')).__MODULE__):this.registry.has(a.constructor)}}class Recurse{constructor(a){this.func=a}}var i={reverse,foreach:function foreach(a,b){return b.forEach((b)=>a(b)),Symbol.for('ok')},duplicate:function duplicate(a,b){const c=[];for(;c.length{if(d.get(c-1)a.get(c-1)?1:0})},keystore:function keystore(a,b,c,d){const e=[...c];for(let f=0;fa.toString()).join()},map:function map(a,b){return b.map((b)=>a(b))},filter:function filter(a,b){return b.filter((b)=>a(b))},filtermap:function filtermap(a,b){const c=[];for(const d of b){const b=a(d);!0===b?c.push(d):b instanceof e.Tuple&&!0===b.get(0)&&c.push(b.get(1))}return c},member:function member(a,b){for(const c of b)if(c===a)return!0;return!1},all:function all(a,b){for(const c of b)if(!1===a(c))return!1;return!0},any:function any(a,b){for(const c of b)if(!0===a(c))return!0;return!1},splitwith:function splitwith(a,b){let c=!1;const d=[],f=[];for(const e of b)!0==c?f.push(e):!0===a(e)?d.push(e):(c=!0,f.push(e));return new e.Tuple(d,f)},sort:function sort(...a){if(1===a.length){const b=[...a[0]];return b.sort()}const c=a[0],b=[...a[1]];return b.sort((d,a)=>{const b=c(d,a);return!0===b?-1:1})}},j={atom_to_binary,binary_to_atom,binary_to_existing_atom:function binary_to_existing_atom(a,b=Symbol.for('utf8')){return binary_to_atom(a,b)},list_concatenation:function list_concatenation(a,b){return a.concat(b)},list_subtraction:function list_subtraction(a,b){const c=[...a];for(const d of b){const a=c.indexOf(d);-1>b},bxor:function bxor(a,b){return a^b},bnot:function bnot(a){return~a},is_bitstring:is_bitstring$1,is_boolean:function is_boolean$1(a){return'boolean'==typeof a||a instanceof Boolean},is_float:function is_float(a){return is_number$1(a)&&!b(a)},is_function:function is_function$1(a){return'function'==typeof a||a instanceof Function},is_integer,is_list:function is_list(a){return Array.isArray(a)},is_map:function is_map$1(a){return a instanceof Map},is_number:is_number$1,is_pid:function is_pid(a){return a instanceof e.PID},is_port:function is_port(){return!1},is_reference:function is_reference(a){return a instanceof e.Reference},is_tuple:function is_tuple(a){return a instanceof e.Tuple},is_atom:function is_atom(a){return'symbol'==typeof a||a instanceof Symbol||a.__MODULE__},is_binary,element:function element(a,b){return b.get(a-1)},setelement:function setelement(a,b,c){const d=[...b.values];return d[a-1]=c,new e.Tuple(...d)},make_tuple:function make_tuple(a,b){const c=[];for(let d=0;d!0){let d=[],e=buildMatch(a);const f=e(b,d),[g,h]=checkNamedVariables(d);if(f&&h&&c.apply(this,g))return g;throw console.error('No match for:',b),new MatchError(b)},MatchError,variable:function variable(a=null,b=Symbol.for('tailored.no_value')){return new Variable(a,b)},wildcard:function wildcard(){return new Wildcard},startsWith:function startsWith(a){return new StartsWith(a)},capture:function capture(a){return new Capture(a)},headTail:function headTail(a,b){return new HeadTail(a,b)},type:function a(a,b={}){return new Type(a,b)},bound:function bound(a){return new Bound(a)},Clause,clause:function clause(a,b,c=()=>!0){return new Clause(a,b,c)},bitStringMatch:function bitStringMatch(...a){return new BitStringMatch(...a)},match_or_default,defmatchgen,list_comprehension:function list_comprehension(a,b){const c=run_generators(b.pop()(),b);let d=[];for(let e of c)a.guard.apply(this,e)&&d.push(a.fn.apply(this,e));return d},list_generator:function list_generator(a,b){return function(){let c=[];for(let d of b){const b=match_or_default(a,d,()=>!0,h);if(b!=h){const[a]=b;c.push(a)}}return c}},bitstring_generator:function bitstring_generator(a,b){return function(){let c=[],d=b.slice(0,a.byte_size()),e=1;for(;d.byte_size==a.byte_size();){const f=match_or_default(a,d,()=>!0,h);if(f!=h){c.push(f)}d=b.slice(a.byte_size()*e,a.byte_size()*(e+1)),e++}return c}},bitstring_comprehension:function bitstring_comprehension(a,b){const c=run_generators(b.pop()(),b);let d=[];for(let e of c)a.guard.apply(this,e)&&d.push(a.fn.apply(this,e));return d=d.map((a)=>e.BitString.integer(a)),new e.BitString(...d)},defmatchGen:function defmatchGen(...a){return defmatchgen(...a)},defmatchAsync:function defmatchAsync(...a){const b=getArityMap(a);return async function(...a){if(b.has(a.length)){const c=b.get(a.length);let d=null,e=null;for(let b of c){let c=[];a=fillInOptionalValues(a,b.arity,b.optionals);const f=b.pattern(a,c),[g,h]=checkNamedVariables(c);if(f&&h&&(await b.guard.apply(this,c))){d=b.fn,e=c;break}}if(!d)throw console.error('No match for:',a),new MatchError(a);return d.apply(this,e)}throw console.error('Arity of',a.length,'not found. No match for:',a),new MatchError(a)}}},Integer:class Integer{},Float:class Float{},Functions:{call_property:function call_property(a,b){if(!b)return a instanceof Function||'function'==typeof a?a():a;if(a instanceof Map){let c=null;if(a.has(b)?c=b:a.has(Symbol.for(b))&&(c=Symbol.for(b)),null===c)throw new Error(`Property ${b} not found in ${a}`);return a.get(c)instanceof Function||'function'==typeof a.get(c)?a.get(c)():a.get(c)}let c=null;if('number'==typeof a||'symbol'==typeof a||'boolean'==typeof a||'string'==typeof a?void 0===a[b]?void 0!==a[Symbol.for(b)]&&(c=Symbol.for(b)):c=b:b in a?c=b:Symbol.for(b)in a&&(c=Symbol.for(b)),null===c)throw new Error(`Property ${b} not found in ${a}`);return a[c]instanceof Function||'function'==typeof a[c]?a[c]():a[c]},defprotocol:function defprotocol(a){return new Protocol(a)},defimpl:function defimpl(a,b,c){a.implementation(b,c)},build_namespace:function build_namespace(a,b){let c=b.split('.');const d=a;let e=a;'Elixir'===c[0]&&(c=c.slice(1));for(const d of c)'undefined'==typeof e[d]&&(e[d]={}),e=e[d];return d.__table__=a.__table__||{},d.__table__[Symbol.for(b)]=e,e},iterator_to_reducer,map_to_object,trampoline:function trampoline$1(a){let b=a;for(;b&&b instanceof Recurse;)b=b.func();return b},Recurse},SpecialForms:{_case:function _case(a,b){return r.Patterns.defmatch(...b)(a)},cond:function cond(...a){for(const b of a)if(b[0])return b[1]();throw new Error},_for:function _for(a,b,c,d=[]){let[e,f]=c.into(d);const g=run_list_generators(b.pop()(),b);for(const h of g)a.guard.apply(this,h)&&(e=f(e,new r.Tuple(Symbol.for('cont'),a.fn.apply(this,h))));return f(e,Symbol.for('done'))},_try:function _try(a,b,c,d,e){let f=null;try{f=a()}catch(a){let d=null;if(b)try{return d=b(a),d}catch(a){if(a instanceof r.Patterns.MatchError)throw a}if(c)try{return d=c(a),d}catch(a){if(a instanceof r.Patterns.MatchError)throw a}throw a}finally{e&&e()}if(d)try{return d(f)}catch(a){if(a instanceof r.Patterns.MatchError)throw new Error('No Match Found in Else');throw a}else return f},_with:function _with(...a){let b=[],c=null,d=null;'function'==typeof a[a.length-2]?[c,d]=a.splice(-2):c=a.pop();for(let c=0;c{const[c,d]=b;return a.set(c,d),a},new Map)},keys:function keys(a){return!1===j.is_map(a)?new e.Tuple(m,a):Array.from(a.keys())},values:function values$1(a){return!1===j.is_map(a)?new e.Tuple(m,a):Array.from(a.values())},is_key,put:function put(a,b,c){if(!1===j.is_map(c))return new e.Tuple(m,c);const d=new Map(c);return d.set(a,b),d},merge:function merge(a,b){return!1===j.is_map(a)?new e.Tuple(m,a):!1===j.is_map(b)?new e.Tuple(m,b):new Map([...a,...b])},update:function update(a,b,c){return!1===j.is_map(c)?new e.Tuple(m,c):!1===is_key(a,c)?new e.Tuple(n,a):new Map([...c,[a,b]])},get:function get(...a){const b=a[0],c=a[1];return!1===j.is_map(c)?new e.Tuple(m,c):is_key(b)?c.get(b):3===a.length?a[2]:new e.Tuple(n,b)},take:function take(a,b){if(!1===j.is_map(b))return new e.Tuple(m,b);if(!is_key(a))return l;const c=b.get(a),d=new Map(b);return d.delete(a),new e.Tuple(c,d)}},lists:i,elixir_errors:{warn:function warn(a){const b=a.join('');return console.warn(`warning: ${b}`),Symbol.for('ok')}},io:{put_chars:function put_chars(a,b){const c=j.iolist_to_binary(b);return a===Symbol.for('stderr')?console.error(c):console.log(c),Symbol.for('ok')}},binary:{copy:function copy(a,b=1){return a.repeat(b)}},unicode:{characters_to_list:function characters_to_list(a){return a.split('').map((a)=>a.codePointAt(0))},characters_to_binary:function characters_to_binary(b){return j.is_binary(b)?b:a(...b)}},elixir_config:{new:function _new(a){return p.set(o,new Map),p.get(o).set(o,a),o},delete:function _delete(a){return p.delete(a),!0},put:put$1,get:get$1,update:function update$1(a,b){const c=b(p.get(o).get(a));return put$1(a,c),c},get_and_put:function get_and_put(a,b){const c=get$1(a);return put$1(a,b),c}}};return{Core:r}}(); From 508b9220cae0b45b3d0d9543a4eaabd7692187f2 Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Tue, 1 Aug 2017 21:55:56 -0500 Subject: [PATCH 645/860] Add more erlang compat functions from Kernel module --- priv/build/iife/ElixirScript.Core.js | 2721 ++++++++++++++++- .../lib/core/erlang_compat/binary.js | 9 +- .../lib/core/erlang_compat/erlang.js | 67 +- 3 files changed, 2789 insertions(+), 8 deletions(-) diff --git a/priv/build/iife/ElixirScript.Core.js b/priv/build/iife/ElixirScript.Core.js index a0c0b537..6253bea7 100644 --- a/priv/build/iife/ElixirScript.Core.js +++ b/priv/build/iife/ElixirScript.Core.js @@ -1,6 +1,2715 @@ -var ElixirScript=function(){'use strict';/* @flow */function namedVariableResult(a,b){return new NamedVariableResult(a,b)}/* @flow */function is_number(a){return'number'==typeof a}function is_string(a){return'string'==typeof a}function is_boolean(a){return'boolean'==typeof a}function is_symbol(a){return'symbol'==typeof a}function is_object(a){return'object'==typeof a}function is_variable(a){return a instanceof Variable}function is_null(a){return null===a}function is_array(a){return Array.isArray(a)}function is_function(a){return'[object Function]'==Object.prototype.toString.call(a)}function is_map(a){return a instanceof Map}function resolveNull(){return function(a){return is_null(a)}}function resolveWildcard(){return function(){return!0}}function resolveObject(a){let b={};const c=Object.keys(a).concat(Object.getOwnPropertySymbols(a));for(let d of c)b[d]=buildMatch(a[d]);return function(d,e){if(!is_object(d)||a.length>d.length)return!1;for(let a of c)if(!(a in d)||!b[a](d[a],e))return!1;return!0}}function getSize(a,b){return a*b/8}function arraysEqual(c,a){if(c===a)return!0;if(null==c||null==a)return!1;if(c.length!=a.length)return!1;for(var b=0;bf.integer(a));return new f(...b)}function resolveNoMatch(){return function(){return!1}}function buildMatch(a){if(null===a)return resolveNull(a);if('undefined'==typeof a)return resolveWildcard(a);const b=a.constructor.prototype,c=g.get(b);return c?c(a):'object'==typeof a?resolveObject(a):resolveNoMatch()}function defmatchgen(...a){const b=getArityMap(a);return function*(...a){let[c,d]=findMatchingFunction(a,b);return yield*c.apply(this,d)}}function findMatchingFunction(a,b){if(b.has(a.length)){const c=b.get(a.length);let d=null,e=null;for(let b of c){let c=[];a=fillInOptionalValues(a,b.arity,b.optionals);const f=b.pattern(a,c),[g,h]=checkNamedVariables(c);if(f&&h&&b.guard.apply(this,g)){d=b.fn,e=g;break}}if(!d)throw console.error('No match for:',a),new MatchError(a);return[d,e]}throw console.error('Arity of',a.length,'not found. No match for:',a),new MatchError(a)}function getArityMap(a){let b=new Map;for(const c of a){const a=getArityRange(c);for(const d of a){let a=[];b.has(d)&&(a=b.get(d)),a.push(c),b.set(d,a)}}return b}function getArityRange(a){const b=a.arity-a.optionals.length,c=a.arity;let d=[b];for(;d[d.length-1]!=c;)d.push(d[d.length-1]+1);return d}function getOptionalValues(a){let b=[];for(let c=0;c!0,d=null){let e=[],f=buildMatch(a);const g=f(b,e),[h,i]=checkNamedVariables(e);return g&&i&&c.apply(this,h)?h:d}function run_generators(a,b){if(0==b.length)return a.map((a)=>{return Array.isArray(a)?a:[a]});const c=b.pop();let d=[];for(let e of c())for(let b of a)d.push([e].concat(b));return run_generators(d,b)}function iterator_to_reducer(a,b,c){const d=a[Symbol.iterator]();let e=d.next(),f=b;for(;!1===e.done;){if(f=c(e.value,f.get(1)),f.get(0)===Symbol.for('halt'))return new r.Tuple(Symbol.for('halted'),f.get(1));if(f.get(0)===Symbol.for('suspend'))return new r.Tuple(Symbol.for('suspended'),f.get(1),(a)=>{return iterator_to_reducer(d,a,c)});e=d.next()}return new r.Tuple(Symbol.for('done'),f.get(1))}function map_to_object(a){const b={};for(const[c,d]of a.entries())b[c]=d instanceof Map?map_to_object(d):d;return b}function run_list_generators(a,b){if(0==b.length)return a.map((a)=>{return Array.isArray(a)?a:[a]});const c=b.pop(),d=[];for(const e of c())for(const b of a)d.push([e].concat(b));return run_list_generators(d,b)}// http://erlang.org/doc/man/lists.html -function reverse(a){return[...a]}function flatten(a,b=[]){const c=a.reduce((a,b)=>{return Array.isArray(b)?a.concat(flatten(b)):a.concat(b)},[]);return c.concat(b)}function foldl(a,b,c){return c.reduce((b,c)=>{return a(c,b)},b)}function keyfind(a,b,c){for(const d of c)if(d.get(b-1)===a)return d;return!1}function keydelete(a,b,c){const d=[];let e=!1;for(let f=0;f{if(null===c)return b;return is_integer(c)?b+a(c):is_bitstring$1(c)?b+a(...c.value):b+iolist_to_binary(c)},'');return d}function is_key(a,b){return b.has(a)}function put$1(a,b){return p.get(o).set(a,b),Symbol.for('ok')}function get$1(a){return p.get(o).get(a)}function get_key(a){let b=a;if(__elixirscript_names__.has(a)&&(b=__elixirscript_names__.get(a)),__elixirscript_store__.has(b))return b;throw new Error(`Key ${b} not found`)}var a=String.fromCodePoint,b=Number.isInteger;class Variable{constructor(a=null,b=Symbol.for('tailored.no_value')){this.name=a,this.default_value=b}}class Wildcard{constructor(){}}class StartsWith{constructor(a){this.prefix=a}}class Capture{constructor(a){this.value=a}}class HeadTail{constructor(a,b){this.head=a,this.tail=b}}class Type{constructor(a,b={}){this.type=a,this.objPattern=b}}class Bound{constructor(a){this.value=a}}class BitStringMatch{constructor(...a){this.values=a}length(){return values.length}bit_size(){return 8*this.byte_size()}byte_size(){let a=0;for(let b of this.values)a+=b.unit*b.size/8;return a}getValue(a){return this.values(a)}getSizeOfValue(a){let b=this.getValue(a);return b.unit*b.size}getTypeOfValue(a){return this.getValue(a).type}}class NamedVariableResult{constructor(a,b){this.name=a,this.value=b}}class Tuple{constructor(...a){this.values=Object.freeze(a),this.length=this.values.length}get(a){return this.values[a]}count(){return this.values.length}[Symbol.iterator](){return this.values[Symbol.iterator]()}toString(){let a,b='';for(a=0;aBitString$1.integer(a));return new BitString$1(...d)}[Symbol.iterator](){return this.value[Symbol.iterator]()}toString(){var a,b='';for(a=0;a>'}process(a){let b=[];var c;for(c=0;cb?c.push(b):2048>b?c.push(192|b>>6,128|63&b):55296>b||57344<=b?c.push(224|b>>12,128|63&b>>6,128|63&b):(d++,b=65536+((1023&b)<<10|1023&a.charCodeAt(d)),c.push(240|b>>18,128|63&b>>12,128|63&b>>6,128|63&b));return c}static toUTF16Array(a){for(var b,c=[],d=0;d=b?(c.push(0),c.push(b)):(c.push(255&b>>8),c.push(255&b));return c}static toUTF32Array(a){for(var b,c=[],d=0;d=b?(c.push(0),c.push(0),c.push(0),c.push(b)):(c.push(0),c.push(0),c.push(255&b>>8),c.push(255&b));return c}//http://stackoverflow.com/questions/2003493/javascript-float-from-to-bits -static float32ToBytes(a){var b=[],c=new ArrayBuffer(4);new Float32Array(c)[0]=a;let d=new Uint32Array(c)[0];return b.push(255&d>>24),b.push(255&d>>16),b.push(255&d>>8),b.push(255&d),b}static float64ToBytes(a){var b=[],c=new ArrayBuffer(8);new Float64Array(c)[0]=a;var d=new Uint32Array(c)[0],e=new Uint32Array(c)[1];return b.push(255&e>>24),b.push(255&e>>16),b.push(255&e>>8),b.push(255&e),b.push(255&d>>24),b.push(255&d>>16),b.push(255&d>>8),b.push(255&d),b}}var e={Tuple,PID:class PID{constructor(){++c,this.id=c}toString(){return'PID#<0.'+this.id+'.0>'}},Reference:class Reference{constructor(){++d,this.id=d,this.ref=Symbol()}toString(){return'Ref#<0.0.0.'+this.id+'>'}},BitString:BitString$1};/* @flow */const f=e.BitString,g=new Map;g.set(Variable.prototype,function resolveVariable(a){return function(b,c){return null===a.name?c.push(b):!a.name.startsWith('_')&&c.push(namedVariableResult(a.name,b)),!0}}),g.set(Wildcard.prototype,resolveWildcard),g.set(HeadTail.prototype,function resolveHeadTail(a){const b=buildMatch(a.head),c=buildMatch(a.tail);return function(a,d){if(!is_array(a)||0===a.length)return!1;const e=a[0],f=a.slice(1);return b(e,d)&&c(f,d)}}),g.set(StartsWith.prototype,function resolveStartsWith(a){const b=a.prefix;return function(a,c){return is_string(a)&&a.startsWith(b)&&(c.push(a.substring(b.length)),!0)}}),g.set(Capture.prototype,function resolveCapture(a){const b=buildMatch(a.value);return function(a,c){return!!b(a,c)&&(c.push(a),!0)}}),g.set(Bound.prototype,function resolveBound(a){return function(b){return typeof b==typeof a.value&&b===a.value}}),g.set(Type.prototype,function resolveType(a){return function(b,c){if(b instanceof a.type){const d=buildMatch(a.objPattern);return d(b,c)}return!1}}),g.set(BitStringMatch.prototype,function resolveBitString(a){let b=[];for(let c of a.values)if(is_variable(c.value)){let a=getSize(c.unit,c.size);fillArray(b,a)}else b=b.concat(new f(c).value);let c=a.values;return function(a,d){var e=String.fromCharCode;let g=null;if(!is_string(a)&&!(a instanceof f))return!1;g=is_string(a)?new f(f.binary(a)):a;let h=0;for(let f,j=0;jd.size)return!1;for(let a of c)if(!d.has(a)||!b.get(a)(d.get(a),e))return!1;return!0}}),g.set(Array.prototype,function resolveArray(a){const b=a.map((a)=>buildMatch(a));return function(c,d){return is_array(c)&&c.length==a.length&&c.every(function(a,e){return b[e](c[e],d)})}}),g.set(String.prototype,function resolveString(a){return function(b){return is_string(b)&&b===a}}),g.set(Boolean.prototype,function resolveBoolean(a){return function(b){return is_boolean(b)&&b===a}}),g.set(Function.prototype,function resolveFunction(a){return function(b){return is_function(b)&&b===a}}),g.set(Object.prototype,resolveObject);class MatchError extends Error{constructor(a){if(super(),'symbol'==typeof a)this.message='No match for: '+a.toString();else if(Array.isArray(a)){let b=a.map((a)=>{return null===a?'null':'undefined'==typeof a?'undefined':a.toString()});this.message='No match for: '+b}else this.message='No match for: '+a;this.stack=new Error().stack,this.name=this.constructor.name}}class Clause{constructor(a,b,c=()=>!0){this.pattern=buildMatch(a),this.arity=a.length,this.optionals=getOptionalValues(a),this.fn=b,this.guard=c}}const h=Symbol();// https://github.com/airportyh/protomorphism -class Protocol{constructor(a){function createFun(a){return function(...c){const d=c[0];let e=null;if(null===d&&this.hasImplementation(Symbol('null'))?e=this.registry.get(Symbol)[a]:b(d)&&this.hasImplementation(r.Integer)?e=this.registry.get(r.Integer)[a]:'number'==typeof d&&!b(d)&&this.hasImplementation(r.Float)?e=this.registry.get(r.Float)[a]:'string'==typeof d&&this.hasImplementation(r.BitString)?e=this.registry.get(r.BitString)[a]:d&&d instanceof Map&&d.has(Symbol.for('__struct__'))&&this.hasImplementation(d)?e=this.registry.get(d.get(Symbol.for('__struct__')).__MODULE__)[a]:null!==d&&this.hasImplementation(d)?e=this.registry.get(d.constructor)[a]:this.fallback&&(e=this.fallback[a]),null!=e){const a=e.apply(this,c);return a}throw new Error(`No implementation found for ${d}`)}}for(const b in this.registry=new Map,this.fallback=null,a)this[b]=createFun(b).bind(this)}implementation(a,b){null===a?this.fallback=b:this.registry.set(a,b)}hasImplementation(a){if(a===r.Integer||a===r.Float||a===r.BitString)return this.registry.has(a);return a&&a instanceof Map&&a.has(Symbol.for('__struct__'))?this.registry.has(a.get(Symbol.for('__struct__')).__MODULE__):this.registry.has(a.constructor)}}class Recurse{constructor(a){this.func=a}}var i={reverse,foreach:function foreach(a,b){return b.forEach((b)=>a(b)),Symbol.for('ok')},duplicate:function duplicate(a,b){const c=[];for(;c.length{if(d.get(c-1)a.get(c-1)?1:0})},keystore:function keystore(a,b,c,d){const e=[...c];for(let f=0;fa.toString()).join()},map:function map(a,b){return b.map((b)=>a(b))},filter:function filter(a,b){return b.filter((b)=>a(b))},filtermap:function filtermap(a,b){const c=[];for(const d of b){const b=a(d);!0===b?c.push(d):b instanceof e.Tuple&&!0===b.get(0)&&c.push(b.get(1))}return c},member:function member(a,b){for(const c of b)if(c===a)return!0;return!1},all:function all(a,b){for(const c of b)if(!1===a(c))return!1;return!0},any:function any(a,b){for(const c of b)if(!0===a(c))return!0;return!1},splitwith:function splitwith(a,b){let c=!1;const d=[],f=[];for(const e of b)!0==c?f.push(e):!0===a(e)?d.push(e):(c=!0,f.push(e));return new e.Tuple(d,f)},sort:function sort(...a){if(1===a.length){const b=[...a[0]];return b.sort()}const c=a[0],b=[...a[1]];return b.sort((d,a)=>{const b=c(d,a);return!0===b?-1:1})}},j={atom_to_binary,binary_to_atom,binary_to_existing_atom:function binary_to_existing_atom(a,b=Symbol.for('utf8')){return binary_to_atom(a,b)},list_concatenation:function list_concatenation(a,b){return a.concat(b)},list_subtraction:function list_subtraction(a,b){const c=[...a];for(const d of b){const a=c.indexOf(d);-1>b},bxor:function bxor(a,b){return a^b},bnot:function bnot(a){return~a},is_bitstring:is_bitstring$1,is_boolean:function is_boolean$1(a){return'boolean'==typeof a||a instanceof Boolean},is_float:function is_float(a){return is_number$1(a)&&!b(a)},is_function:function is_function$1(a){return'function'==typeof a||a instanceof Function},is_integer,is_list:function is_list(a){return Array.isArray(a)},is_map:function is_map$1(a){return a instanceof Map},is_number:is_number$1,is_pid:function is_pid(a){return a instanceof e.PID},is_port:function is_port(){return!1},is_reference:function is_reference(a){return a instanceof e.Reference},is_tuple:function is_tuple(a){return a instanceof e.Tuple},is_atom:function is_atom(a){return'symbol'==typeof a||a instanceof Symbol||a.__MODULE__},is_binary,element:function element(a,b){return b.get(a-1)},setelement:function setelement(a,b,c){const d=[...b.values];return d[a-1]=c,new e.Tuple(...d)},make_tuple:function make_tuple(a,b){const c=[];for(let d=0;d!0){let d=[],e=buildMatch(a);const f=e(b,d),[g,h]=checkNamedVariables(d);if(f&&h&&c.apply(this,g))return g;throw console.error('No match for:',b),new MatchError(b)},MatchError,variable:function variable(a=null,b=Symbol.for('tailored.no_value')){return new Variable(a,b)},wildcard:function wildcard(){return new Wildcard},startsWith:function startsWith(a){return new StartsWith(a)},capture:function capture(a){return new Capture(a)},headTail:function headTail(a,b){return new HeadTail(a,b)},type:function a(a,b={}){return new Type(a,b)},bound:function bound(a){return new Bound(a)},Clause,clause:function clause(a,b,c=()=>!0){return new Clause(a,b,c)},bitStringMatch:function bitStringMatch(...a){return new BitStringMatch(...a)},match_or_default,defmatchgen,list_comprehension:function list_comprehension(a,b){const c=run_generators(b.pop()(),b);let d=[];for(let e of c)a.guard.apply(this,e)&&d.push(a.fn.apply(this,e));return d},list_generator:function list_generator(a,b){return function(){let c=[];for(let d of b){const b=match_or_default(a,d,()=>!0,h);if(b!=h){const[a]=b;c.push(a)}}return c}},bitstring_generator:function bitstring_generator(a,b){return function(){let c=[],d=b.slice(0,a.byte_size()),e=1;for(;d.byte_size==a.byte_size();){const f=match_or_default(a,d,()=>!0,h);if(f!=h){c.push(f)}d=b.slice(a.byte_size()*e,a.byte_size()*(e+1)),e++}return c}},bitstring_comprehension:function bitstring_comprehension(a,b){const c=run_generators(b.pop()(),b);let d=[];for(let e of c)a.guard.apply(this,e)&&d.push(a.fn.apply(this,e));return d=d.map((a)=>e.BitString.integer(a)),new e.BitString(...d)},defmatchGen:function defmatchGen(...a){return defmatchgen(...a)},defmatchAsync:function defmatchAsync(...a){const b=getArityMap(a);return async function(...a){if(b.has(a.length)){const c=b.get(a.length);let d=null,e=null;for(let b of c){let c=[];a=fillInOptionalValues(a,b.arity,b.optionals);const f=b.pattern(a,c),[g,h]=checkNamedVariables(c);if(f&&h&&(await b.guard.apply(this,c))){d=b.fn,e=c;break}}if(!d)throw console.error('No match for:',a),new MatchError(a);return d.apply(this,e)}throw console.error('Arity of',a.length,'not found. No match for:',a),new MatchError(a)}}},Integer:class Integer{},Float:class Float{},Functions:{call_property:function call_property(a,b){if(!b)return a instanceof Function||'function'==typeof a?a():a;if(a instanceof Map){let c=null;if(a.has(b)?c=b:a.has(Symbol.for(b))&&(c=Symbol.for(b)),null===c)throw new Error(`Property ${b} not found in ${a}`);return a.get(c)instanceof Function||'function'==typeof a.get(c)?a.get(c)():a.get(c)}let c=null;if('number'==typeof a||'symbol'==typeof a||'boolean'==typeof a||'string'==typeof a?void 0===a[b]?void 0!==a[Symbol.for(b)]&&(c=Symbol.for(b)):c=b:b in a?c=b:Symbol.for(b)in a&&(c=Symbol.for(b)),null===c)throw new Error(`Property ${b} not found in ${a}`);return a[c]instanceof Function||'function'==typeof a[c]?a[c]():a[c]},defprotocol:function defprotocol(a){return new Protocol(a)},defimpl:function defimpl(a,b,c){a.implementation(b,c)},build_namespace:function build_namespace(a,b){let c=b.split('.');const d=a;let e=a;'Elixir'===c[0]&&(c=c.slice(1));for(const d of c)'undefined'==typeof e[d]&&(e[d]={}),e=e[d];return d.__table__=a.__table__||{},d.__table__[Symbol.for(b)]=e,e},iterator_to_reducer,map_to_object,trampoline:function trampoline$1(a){let b=a;for(;b&&b instanceof Recurse;)b=b.func();return b},Recurse},SpecialForms:{_case:function _case(a,b){return r.Patterns.defmatch(...b)(a)},cond:function cond(...a){for(const b of a)if(b[0])return b[1]();throw new Error},_for:function _for(a,b,c,d=[]){let[e,f]=c.into(d);const g=run_list_generators(b.pop()(),b);for(const h of g)a.guard.apply(this,h)&&(e=f(e,new r.Tuple(Symbol.for('cont'),a.fn.apply(this,h))));return f(e,Symbol.for('done'))},_try:function _try(a,b,c,d,e){let f=null;try{f=a()}catch(a){let d=null;if(b)try{return d=b(a),d}catch(a){if(a instanceof r.Patterns.MatchError)throw a}if(c)try{return d=c(a),d}catch(a){if(a instanceof r.Patterns.MatchError)throw a}throw a}finally{e&&e()}if(d)try{return d(f)}catch(a){if(a instanceof r.Patterns.MatchError)throw new Error('No Match Found in Else');throw a}else return f},_with:function _with(...a){let b=[],c=null,d=null;'function'==typeof a[a.length-2]?[c,d]=a.splice(-2):c=a.pop();for(let c=0;c{const[c,d]=b;return a.set(c,d),a},new Map)},keys:function keys(a){return!1===j.is_map(a)?new e.Tuple(m,a):Array.from(a.keys())},values:function values$1(a){return!1===j.is_map(a)?new e.Tuple(m,a):Array.from(a.values())},is_key,put:function put(a,b,c){if(!1===j.is_map(c))return new e.Tuple(m,c);const d=new Map(c);return d.set(a,b),d},merge:function merge(a,b){return!1===j.is_map(a)?new e.Tuple(m,a):!1===j.is_map(b)?new e.Tuple(m,b):new Map([...a,...b])},update:function update(a,b,c){return!1===j.is_map(c)?new e.Tuple(m,c):!1===is_key(a,c)?new e.Tuple(n,a):new Map([...c,[a,b]])},get:function get(...a){const b=a[0],c=a[1];return!1===j.is_map(c)?new e.Tuple(m,c):is_key(b)?c.get(b):3===a.length?a[2]:new e.Tuple(n,b)},take:function take(a,b){if(!1===j.is_map(b))return new e.Tuple(m,b);if(!is_key(a))return l;const c=b.get(a),d=new Map(b);return d.delete(a),new e.Tuple(c,d)}},lists:i,elixir_errors:{warn:function warn(a){const b=a.join('');return console.warn(`warning: ${b}`),Symbol.for('ok')}},io:{put_chars:function put_chars(a,b){const c=j.iolist_to_binary(b);return a===Symbol.for('stderr')?console.error(c):console.log(c),Symbol.for('ok')}},binary:{copy:function copy(a,b=1){return a.repeat(b)}},unicode:{characters_to_list:function characters_to_list(a){return a.split('').map((a)=>a.codePointAt(0))},characters_to_binary:function characters_to_binary(b){return j.is_binary(b)?b:a(...b)}},elixir_config:{new:function _new(a){return p.set(o,new Map),p.get(o).set(o,a),o},delete:function _delete(a){return p.delete(a),!0},put:put$1,get:get$1,update:function update$1(a,b){const c=b(p.get(o).get(a));return put$1(a,c),c},get_and_put:function get_and_put(a,b){const c=get$1(a);return put$1(a,b),c}}};return{Core:r}}(); +var ElixirScript = (function () { +'use strict'; + +/* @flow */ + +class Variable { + constructor(name = null, default_value = Symbol.for('tailored.no_value')) { + this.name = name; + this.default_value = default_value; + } +} + +class Wildcard { + constructor() {} +} + +class StartsWith { + constructor(prefix) { + this.prefix = prefix; + } +} + +class Capture { + constructor(value) { + this.value = value; + } +} + +class HeadTail { + constructor(head, tail) { + this.head = head; + this.tail = tail; + } +} + +class Type { + constructor(type, objPattern = {}) { + this.type = type; + this.objPattern = objPattern; + } +} + +class Bound { + constructor(value) { + this.value = value; + } +} + +class BitStringMatch { + constructor(...values) { + this.values = values; + } + + length() { + return values.length; + } + + bit_size() { + return this.byte_size() * 8; + } + + byte_size() { + let s = 0; + + for (let val of this.values) { + s = s + val.unit * val.size / 8; + } + + return s; + } + + getValue(index) { + return this.values(index); + } + + getSizeOfValue(index) { + let val = this.getValue(index); + return val.unit * val.size; + } + + getTypeOfValue(index) { + return this.getValue(index).type; + } +} + +class NamedVariableResult { + constructor(name, value) { + this.name = name; + this.value = value; + } +} + +function variable(name = null, default_value = Symbol.for('tailored.no_value')) { + return new Variable(name, default_value); +} + +function wildcard() { + return new Wildcard(); +} + +function startsWith(prefix) { + return new StartsWith(prefix); +} + +function capture(value) { + return new Capture(value); +} + +function headTail(head, tail) { + return new HeadTail(head, tail); +} + +function type(type, objPattern = {}) { + return new Type(type, objPattern); +} + +function bound(value) { + return new Bound(value); +} + +function bitStringMatch(...values) { + return new BitStringMatch(...values); +} + +function namedVariableResult(name, value) { + return new NamedVariableResult(name, value); +} + +/* @flow */ + +function is_number(value) { + return typeof value === 'number'; +} + +function is_string(value) { + return typeof value === 'string'; +} + +function is_boolean(value) { + return typeof value === 'boolean'; +} + +function is_symbol(value) { + return typeof value === 'symbol'; +} + +function is_object(value) { + return typeof value === 'object'; +} + +function is_variable(value) { + return value instanceof Variable; +} + +function is_null(value) { + return value === null; +} + +function is_array(value) { + return Array.isArray(value); +} + +function is_function(value) { + return Object.prototype.toString.call(value) == '[object Function]'; +} + +function is_map(value) { + return value instanceof Map; +} + +class Tuple { + constructor(...args) { + this.values = Object.freeze(args); + this.length = this.values.length; + } + + get(index) { + return this.values[index]; + } + + count() { + return this.values.length; + } + + [Symbol.iterator]() { + return this.values[Symbol.iterator](); + } + + toString() { + let i, + s = ''; + for (i = 0; i < this.values.length; i++) { + if (s !== '') { + s += ', '; + } + + const stringToAppend = this.values[i] ? this.values[i].toString() : ''; + + s += stringToAppend; + } + + return '{' + s + '}'; + } + + put_elem(index, elem) { + if (index === this.length) { + let new_values = this.values.concat([elem]); + return new Tuple(...new_values); + } + + let new_values = this.values.concat([]); + new_values.splice(index, 0, elem); + return new Tuple(...new_values); + } + + remove_elem(index) { + let new_values = this.values.concat([]); + new_values.splice(index, 1); + return new Tuple(...new_values); + } +} + +let process_counter = -1; + +class PID { + constructor() { + process_counter = process_counter + 1; + this.id = process_counter; + } + + toString() { + return 'PID#<0.' + this.id + '.0>'; + } +} + +let ref_counter = -1; + +class Reference { + constructor() { + ref_counter = ref_counter + 1; + this.id = ref_counter; + this.ref = Symbol(); + } + + toString() { + return 'Ref#<0.0.0.' + this.id + '>'; + } +} + +class BitString$1 { + constructor(...args) { + this.value = Object.freeze(this.process(args)); + this.length = this.value.length; + this.bit_size = this.length * 8; + this.byte_size = this.length; + } + + get(index) { + return this.value[index]; + } + + count() { + return this.value.length; + } + + slice(start, end = null) { + let s = this.value.slice(start, end); + let ms = s.map(elem => BitString$1.integer(elem)); + return new BitString$1(...ms); + } + + [Symbol.iterator]() { + return this.value[Symbol.iterator](); + } + + toString() { + var i, + s = ''; + for (i = 0; i < this.count(); i++) { + if (s !== '') { + s += ', '; + } + s += this.get(i).toString(); + } + + return '<<' + s + '>>'; + } + + process(bitStringParts) { + let processed_values = []; + + var i; + for (i = 0; i < bitStringParts.length; i++) { + let processed_value = this['process_' + bitStringParts[i].type](bitStringParts[i]); + + for (let attr of bitStringParts[i].attributes) { + processed_value = this['process_' + attr](processed_value); + } + + processed_values = processed_values.concat(processed_value); + } + + return processed_values; + } + + process_integer(value) { + return value.value; + } + + process_float(value) { + if (value.size === 64) { + return BitString$1.float64ToBytes(value.value); + } else if (value.size === 32) { + return BitString$1.float32ToBytes(value.value); + } + + throw new Error('Invalid size for float'); + } + + process_bitstring(value) { + return value.value.value; + } + + process_binary(value) { + return BitString$1.toUTF8Array(value.value); + } + + process_utf8(value) { + return BitString$1.toUTF8Array(value.value); + } + + process_utf16(value) { + return BitString$1.toUTF16Array(value.value); + } + + process_utf32(value) { + return BitString$1.toUTF32Array(value.value); + } + + process_signed(value) { + return new Uint8Array([value])[0]; + } + + process_unsigned(value) { + return value; + } + + process_native(value) { + return value; + } + + process_big(value) { + return value; + } + + process_little(value) { + return value.reverse(); + } + + process_size(value) { + return value; + } + + process_unit(value) { + return value; + } + + static integer(value) { + return BitString$1.wrap(value, { type: 'integer', unit: 1, size: 8 }); + } + + static float(value) { + return BitString$1.wrap(value, { type: 'float', unit: 1, size: 64 }); + } + + static bitstring(value) { + return BitString$1.wrap(value, { + type: 'bitstring', + unit: 1, + size: value.bit_size + }); + } + + static bits(value) { + return BitString$1.bitstring(value); + } + + static binary(value) { + return BitString$1.wrap(value, { + type: 'binary', + unit: 8, + size: value.length + }); + } + + static bytes(value) { + return BitString$1.binary(value); + } + + static utf8(value) { + return BitString$1.wrap(value, { type: 'utf8', unit: 1, size: value.length }); + } + + static utf16(value) { + return BitString$1.wrap(value, { + type: 'utf16', + unit: 1, + size: value.length * 2 + }); + } + + static utf32(value) { + return BitString$1.wrap(value, { + type: 'utf32', + unit: 1, + size: value.length * 4 + }); + } + + static signed(value) { + return BitString$1.wrap(value, {}, 'signed'); + } + + static unsigned(value) { + return BitString$1.wrap(value, {}, 'unsigned'); + } + + static native(value) { + return BitString$1.wrap(value, {}, 'native'); + } + + static big(value) { + return BitString$1.wrap(value, {}, 'big'); + } + + static little(value) { + return BitString$1.wrap(value, {}, 'little'); + } + + static size(value, count) { + return BitString$1.wrap(value, { size: count }); + } + + static unit(value, count) { + return BitString$1.wrap(value, { unit: count }); + } + + static wrap(value, opt, new_attribute = null) { + let the_value = value; + + if (!(value instanceof Object)) { + the_value = { value: value, attributes: [] }; + } + + the_value = Object.assign(the_value, opt); + + if (new_attribute) { + the_value.attributes.push(new_attribute); + } + + return the_value; + } + + static toUTF8Array(str) { + var utf8 = []; + for (var i = 0; i < str.length; i++) { + var charcode = str.charCodeAt(i); + if (charcode < 0x80) { + utf8.push(charcode); + } else if (charcode < 0x800) { + utf8.push(0xc0 | charcode >> 6, 0x80 | charcode & 0x3f); + } else if (charcode < 0xd800 || charcode >= 0xe000) { + utf8.push(0xe0 | charcode >> 12, 0x80 | charcode >> 6 & 0x3f, 0x80 | charcode & 0x3f); + } else { + // surrogate pair + i++; + // UTF-16 encodes 0x10000-0x10FFFF by + // subtracting 0x10000 and splitting the + // 20 bits of 0x0-0xFFFFF into two halves + charcode = 0x10000 + ((charcode & 0x3ff) << 10 | str.charCodeAt(i) & 0x3ff); + utf8.push(0xf0 | charcode >> 18, 0x80 | charcode >> 12 & 0x3f, 0x80 | charcode >> 6 & 0x3f, 0x80 | charcode & 0x3f); + } + } + return utf8; + } + + static toUTF16Array(str) { + var utf16 = []; + for (var i = 0; i < str.length; i++) { + var codePoint = str.codePointAt(i); + + if (codePoint <= 255) { + utf16.push(0); + utf16.push(codePoint); + } else { + utf16.push(codePoint >> 8 & 0xff); + utf16.push(codePoint & 0xff); + } + } + return utf16; + } + + static toUTF32Array(str) { + var utf32 = []; + for (var i = 0; i < str.length; i++) { + var codePoint = str.codePointAt(i); + + if (codePoint <= 255) { + utf32.push(0); + utf32.push(0); + utf32.push(0); + utf32.push(codePoint); + } else { + utf32.push(0); + utf32.push(0); + utf32.push(codePoint >> 8 & 0xff); + utf32.push(codePoint & 0xff); + } + } + return utf32; + } + + //http://stackoverflow.com/questions/2003493/javascript-float-from-to-bits + static float32ToBytes(f) { + var bytes = []; + + var buf = new ArrayBuffer(4); + new Float32Array(buf)[0] = f; + + let intVersion = new Uint32Array(buf)[0]; + + bytes.push(intVersion >> 24 & 0xff); + bytes.push(intVersion >> 16 & 0xff); + bytes.push(intVersion >> 8 & 0xff); + bytes.push(intVersion & 0xff); + + return bytes; + } + + static float64ToBytes(f) { + var bytes = []; + + var buf = new ArrayBuffer(8); + new Float64Array(buf)[0] = f; + + var intVersion1 = new Uint32Array(buf)[0]; + var intVersion2 = new Uint32Array(buf)[1]; + + bytes.push(intVersion2 >> 24 & 0xff); + bytes.push(intVersion2 >> 16 & 0xff); + bytes.push(intVersion2 >> 8 & 0xff); + bytes.push(intVersion2 & 0xff); + + bytes.push(intVersion1 >> 24 & 0xff); + bytes.push(intVersion1 >> 16 & 0xff); + bytes.push(intVersion1 >> 8 & 0xff); + bytes.push(intVersion1 & 0xff); + + return bytes; + } +} + +var ErlangTypes = { + Tuple, + PID, + Reference, + BitString: BitString$1 +}; + +/* @flow */ + +const BitString = ErlangTypes.BitString; + +function resolveSymbol(pattern) { + return function (value) { + return is_symbol(value) && value === pattern; + }; +} + +function resolveString(pattern) { + return function (value) { + return is_string(value) && value === pattern; + }; +} + +function resolveNumber(pattern) { + return function (value) { + return is_number(value) && value === pattern; + }; +} + +function resolveBoolean(pattern) { + return function (value) { + return is_boolean(value) && value === pattern; + }; +} + +function resolveFunction(pattern) { + return function (value) { + return is_function(value) && value === pattern; + }; +} + +function resolveNull(pattern) { + return function (value) { + return is_null(value); + }; +} + +function resolveBound(pattern) { + return function (value, args) { + if (typeof value === typeof pattern.value && value === pattern.value) { + return true; + } + + return false; + }; +} + +function resolveWildcard() { + return function () { + return true; + }; +} + +function resolveVariable(pattern) { + return function (value, args) { + if (pattern.name === null) { + args.push(value); + } else if (!pattern.name.startsWith('_')) { + args.push(namedVariableResult(pattern.name, value)); + } + + return true; + }; +} + +function resolveHeadTail(pattern) { + const headMatches = buildMatch(pattern.head); + const tailMatches = buildMatch(pattern.tail); + + return function (value, args) { + if (!is_array(value) || value.length === 0) { + return false; + } + + const head = value[0]; + const tail = value.slice(1); + + if (headMatches(head, args) && tailMatches(tail, args)) { + return true; + } + + return false; + }; +} + +function resolveCapture(pattern) { + const matches = buildMatch(pattern.value); + + return function (value, args) { + if (matches(value, args)) { + args.push(value); + return true; + } + + return false; + }; +} + +function resolveStartsWith(pattern) { + const prefix = pattern.prefix; + + return function (value, args) { + if (is_string(value) && value.startsWith(prefix)) { + args.push(value.substring(prefix.length)); + return true; + } + + return false; + }; +} + +function resolveType(pattern) { + return function (value, args) { + if (value instanceof pattern.type) { + const matches = buildMatch(pattern.objPattern); + return matches(value, args); + } + + return false; + }; +} + +function resolveArray(pattern) { + const matches = pattern.map(x => buildMatch(x)); + + return function (value, args) { + if (!is_array(value) || value.length != pattern.length) { + return false; + } + + return value.every(function (v, i) { + return matches[i](value[i], args); + }); + }; +} + +function resolveMap(pattern) { + let matches = new Map(); + + const keys = Array.from(pattern.keys()); + + for (let key of keys) { + matches.set(key, buildMatch(pattern.get(key))); + } + + return function (value, args) { + if (!is_map(value) || pattern.size > value.size) { + return false; + } + + for (let key of keys) { + if (!value.has(key) || !matches.get(key)(value.get(key), args)) { + return false; + } + } + + return true; + }; +} + +function resolveObject(pattern) { + let matches = {}; + + const keys = Object.keys(pattern).concat(Object.getOwnPropertySymbols(pattern)); + + for (let key of keys) { + matches[key] = buildMatch(pattern[key]); + } + + return function (value, args) { + if (!is_object(value) || pattern.length > value.length) { + return false; + } + + for (let key of keys) { + if (!(key in value) || !matches[key](value[key], args)) { + return false; + } + } + + return true; + }; +} + +function resolveBitString(pattern) { + let patternBitString = []; + + for (let bitstringMatchPart of pattern.values) { + if (is_variable(bitstringMatchPart.value)) { + let size = getSize(bitstringMatchPart.unit, bitstringMatchPart.size); + fillArray(patternBitString, size); + } else { + patternBitString = patternBitString.concat(new BitString(bitstringMatchPart).value); + } + } + + let patternValues = pattern.values; + + return function (value, args) { + let bsValue = null; + + if (!is_string(value) && !(value instanceof BitString)) { + return false; + } + + if (is_string(value)) { + bsValue = new BitString(BitString.binary(value)); + } else { + bsValue = value; + } + + let beginningIndex = 0; + + for (let i = 0; i < patternValues.length; i++) { + let bitstringMatchPart = patternValues[i]; + + if (is_variable(bitstringMatchPart.value) && bitstringMatchPart.type == 'binary' && bitstringMatchPart.size === undefined && i < patternValues.length - 1) { + throw new Error('a binary field without size is only allowed at the end of a binary pattern'); + } + + let size = 0; + let bsValueArrayPart = []; + let patternBitStringArrayPart = []; + size = getSize(bitstringMatchPart.unit, bitstringMatchPart.size); + + if (i === patternValues.length - 1) { + bsValueArrayPart = bsValue.value.slice(beginningIndex); + patternBitStringArrayPart = patternBitString.slice(beginningIndex); + } else { + bsValueArrayPart = bsValue.value.slice(beginningIndex, beginningIndex + size); + patternBitStringArrayPart = patternBitString.slice(beginningIndex, beginningIndex + size); + } + + if (is_variable(bitstringMatchPart.value)) { + switch (bitstringMatchPart.type) { + case 'integer': + if (bitstringMatchPart.attributes && bitstringMatchPart.attributes.indexOf('signed') != -1) { + args.push(new Int8Array([bsValueArrayPart[0]])[0]); + } else { + args.push(new Uint8Array([bsValueArrayPart[0]])[0]); + } + break; + + case 'float': + if (size === 64) { + args.push(Float64Array.from(bsValueArrayPart)[0]); + } else if (size === 32) { + args.push(Float32Array.from(bsValueArrayPart)[0]); + } else { + return false; + } + break; + + case 'bitstring': + args.push(createBitString(bsValueArrayPart)); + break; + + case 'binary': + args.push(String.fromCharCode.apply(null, new Uint8Array(bsValueArrayPart))); + break; + + case 'utf8': + args.push(String.fromCharCode.apply(null, new Uint8Array(bsValueArrayPart))); + break; + + case 'utf16': + args.push(String.fromCharCode.apply(null, new Uint16Array(bsValueArrayPart))); + break; + + case 'utf32': + args.push(String.fromCharCode.apply(null, new Uint32Array(bsValueArrayPart))); + break; + + default: + return false; + } + } else if (!arraysEqual(bsValueArrayPart, patternBitStringArrayPart)) { + return false; + } + + beginningIndex = beginningIndex + size; + } + + return true; + }; +} + +function getSize(unit, size) { + return unit * size / 8; +} + +function arraysEqual(a, b) { + if (a === b) return true; + if (a == null || b == null) return false; + if (a.length != b.length) return false; + + for (var i = 0; i < a.length; ++i) { + if (a[i] !== b[i]) return false; + } + + return true; +} + +function fillArray(arr, num) { + for (let i = 0; i < num; i++) { + arr.push(0); + } +} + +function createBitString(arr) { + let integerParts = arr.map(elem => BitString.integer(elem)); + return new BitString(...integerParts); +} + +function resolveNoMatch() { + return function () { + return false; + }; +} + +const patternMap = new Map(); +patternMap.set(Variable.prototype, resolveVariable); +patternMap.set(Wildcard.prototype, resolveWildcard); +patternMap.set(HeadTail.prototype, resolveHeadTail); +patternMap.set(StartsWith.prototype, resolveStartsWith); +patternMap.set(Capture.prototype, resolveCapture); +patternMap.set(Bound.prototype, resolveBound); +patternMap.set(Type.prototype, resolveType); +patternMap.set(BitStringMatch.prototype, resolveBitString); +patternMap.set(Number.prototype, resolveNumber); +patternMap.set(Symbol.prototype, resolveSymbol); +patternMap.set(Map.prototype, resolveMap); +patternMap.set(Array.prototype, resolveArray); +patternMap.set(String.prototype, resolveString); +patternMap.set(Boolean.prototype, resolveBoolean); +patternMap.set(Function.prototype, resolveFunction); +patternMap.set(Object.prototype, resolveObject); + +function buildMatch(pattern) { + if (pattern === null) { + return resolveNull(pattern); + } + + if (typeof pattern === 'undefined') { + return resolveWildcard(pattern); + } + + const type$$1 = pattern.constructor.prototype; + const resolver = patternMap.get(type$$1); + + if (resolver) { + return resolver(pattern); + } + + if (typeof pattern === 'object') { + return resolveObject(pattern); + } + + return resolveNoMatch(); +} + +class MatchError extends Error { + constructor(arg) { + super(); + + if (typeof arg === 'symbol') { + this.message = 'No match for: ' + arg.toString(); + } else if (Array.isArray(arg)) { + let mappedValues = arg.map(x => { + if (x === null) { + return 'null'; + } else if (typeof x === 'undefined') { + return 'undefined'; + } + + return x.toString(); + }); + + this.message = 'No match for: ' + mappedValues; + } else { + this.message = 'No match for: ' + arg; + } + + this.stack = new Error().stack; + this.name = this.constructor.name; + } +} + +class Clause { + constructor(pattern, fn, guard = () => true) { + this.pattern = buildMatch(pattern); + this.arity = pattern.length; + this.optionals = getOptionalValues(pattern); + this.fn = fn; + this.guard = guard; + } +} + +function clause(pattern, fn, guard = () => true) { + return new Clause(pattern, fn, guard); +} + + + +function defmatch(...clauses) { + const arities = getArityMap(clauses); + + return function (...args) { + let [funcToCall, params] = findMatchingFunction(args, arities); + return funcToCall.apply(this, params); + }; +} + +function defmatchgen(...clauses) { + const arities = getArityMap(clauses); + + return function* (...args) { + let [funcToCall, params] = findMatchingFunction(args, arities); + return yield* funcToCall.apply(this, params); + }; +} + +function defmatchGen(...args) { + return defmatchgen(...args); +} + +function defmatchAsync(...clauses) { + const arities = getArityMap(clauses); + + return async function (...args) { + if (arities.has(args.length)) { + const arityClauses = arities.get(args.length); + + let funcToCall = null; + let params = null; + for (let processedClause of arityClauses) { + let result = []; + args = fillInOptionalValues(args, processedClause.arity, processedClause.optionals); + + const doesMatch = processedClause.pattern(args, result); + const [filteredResult, allNamesMatch] = checkNamedVariables(result); + + if (doesMatch && allNamesMatch && (await processedClause.guard.apply(this, result))) { + funcToCall = processedClause.fn; + params = result; + break; + } + } + + if (!funcToCall) { + console.error('No match for:', args); + throw new MatchError(args); + } + + return funcToCall.apply(this, params); + } else { + console.error('Arity of', args.length, 'not found. No match for:', args); + throw new MatchError(args); + } + }; +} + +function findMatchingFunction(args, arities) { + if (arities.has(args.length)) { + const arityClauses = arities.get(args.length); + + let funcToCall = null; + let params = null; + for (let processedClause of arityClauses) { + let result = []; + args = fillInOptionalValues(args, processedClause.arity, processedClause.optionals); + + const doesMatch = processedClause.pattern(args, result); + const [filteredResult, allNamesMatch] = checkNamedVariables(result); + + if (doesMatch && allNamesMatch && processedClause.guard.apply(this, filteredResult)) { + funcToCall = processedClause.fn; + params = filteredResult; + break; + } + } + + if (!funcToCall) { + console.error('No match for:', args); + throw new MatchError(args); + } + + return [funcToCall, params]; + } else { + console.error('Arity of', args.length, 'not found. No match for:', args); + throw new MatchError(args); + } +} + +function getArityMap(clauses) { + let map = new Map(); + + for (const clause of clauses) { + const range = getArityRange(clause); + + for (const arity of range) { + let arityClauses = []; + + if (map.has(arity)) { + arityClauses = map.get(arity); + } + + arityClauses.push(clause); + map.set(arity, arityClauses); + } + } + + return map; +} + +function getArityRange(clause) { + const min = clause.arity - clause.optionals.length; + const max = clause.arity; + + let range = [min]; + + while (range[range.length - 1] != max) { + range.push(range[range.length - 1] + 1); + } + + return range; +} + +function getOptionalValues(pattern) { + let optionals = []; + + for (let i = 0; i < pattern.length; i++) { + if (pattern[i] instanceof Variable && pattern[i].default_value != Symbol.for('tailored.no_value')) { + optionals.push([i, pattern[i].default_value]); + } + } + + return optionals; +} + +function fillInOptionalValues(args, arity, optionals) { + if (args.length === arity || optionals.length === 0) { + return args; + } + + if (args.length + optionals.length < arity) { + return args; + } + + let numberOfOptionalsToFill = arity - args.length; + let optionalsToRemove = optionals.length - numberOfOptionalsToFill; + + let optionalsToUse = optionals.slice(optionalsToRemove); + + for (let [index, value] of optionalsToUse) { + args.splice(index, 0, value); + if (args.length === arity) { + break; + } + } + + return args; +} + +function match(pattern, expr, guard = () => true) { + let result = []; + let processedPattern = buildMatch(pattern); + const doesMatch = processedPattern(expr, result); + const [filteredResult, allNamesMatch] = checkNamedVariables(result); + + if (doesMatch && allNamesMatch && guard.apply(this, filteredResult)) { + return filteredResult; + } else { + console.error('No match for:', expr); + throw new MatchError(expr); + } +} + +function checkNamedVariables(results) { + const namesMap = {}; + const filteredResults = []; + + for (let i = 0; i < results.length; i++) { + const current = results[i]; + if (current instanceof NamedVariableResult) { + if (namesMap[current.name] && namesMap[current.name] !== current.value) { + return [results, false]; + } else if (namesMap[current.name] && namesMap[current.name] === current.value) { + filteredResults.push(current.value); + } else { + namesMap[current.name] = current.value; + filteredResults.push(current.value); + } + } else { + filteredResults.push(current); + } + } + + return [filteredResults, true]; +} + +function match_or_default(pattern, expr, guard = () => true, default_value = null) { + let result = []; + let processedPattern = buildMatch(pattern); + const doesMatch = processedPattern(expr, result); + const [filteredResult, allNamesMatch] = checkNamedVariables(result); + + if (doesMatch && allNamesMatch && guard.apply(this, filteredResult)) { + return filteredResult; + } else { + return default_value; + } +} + +const NO_MATCH = Symbol(); + +function bitstring_generator(pattern, bitstring) { + return function () { + let returnResult = []; + let bsSlice = bitstring.slice(0, pattern.byte_size()); + let i = 1; + + while (bsSlice.byte_size == pattern.byte_size()) { + const result = match_or_default(pattern, bsSlice, () => true, NO_MATCH); + + if (result != NO_MATCH) { + const [value] = result; + returnResult.push(result); + } + + bsSlice = bitstring.slice(pattern.byte_size() * i, pattern.byte_size() * (i + 1)); + + i++; + } + + return returnResult; + }; +} + +function list_generator(pattern, list) { + return function () { + let returnResult = []; + for (let i of list) { + const result = match_or_default(pattern, i, () => true, NO_MATCH); + if (result != NO_MATCH) { + const [value] = result; + returnResult.push(value); + } + } + + return returnResult; + }; +} + +function list_comprehension(expression, generators) { + const generatedValues = run_generators(generators.pop()(), generators); + + let result = []; + + for (let value of generatedValues) { + if (expression.guard.apply(this, value)) { + result.push(expression.fn.apply(this, value)); + } + } + + return result; +} + +function run_generators(generator, generators) { + if (generators.length == 0) { + return generator.map(x => { + if (Array.isArray(x)) { + return x; + } else { + return [x]; + } + }); + } else { + const list = generators.pop(); + + let next_gen = []; + for (let j of list()) { + for (let i of generator) { + next_gen.push([j].concat(i)); + } + } + + return run_generators(next_gen, generators); + } +} + +function bitstring_comprehension(expression, generators) { + const generatedValues = run_generators(generators.pop()(), generators); + + let result = []; + + for (let value of generatedValues) { + if (expression.guard.apply(this, value)) { + result.push(expression.fn.apply(this, value)); + } + } + + result = result.map(x => ErlangTypes.BitString.integer(x)); + return new ErlangTypes.BitString(...result); +} + +var Patterns = { + defmatch, + match, + MatchError, + variable, + wildcard, + startsWith, + capture, + headTail, + type, + bound, + Clause, + clause, + bitStringMatch, + match_or_default, + defmatchgen, + list_comprehension, + list_generator, + bitstring_generator, + bitstring_comprehension, + defmatchGen, + defmatchAsync +}; + +// https://github.com/airportyh/protomorphism +class Protocol { + constructor(spec) { + this.registry = new Map(); + this.fallback = null; + + function createFun(funName) { + return function (...args) { + const thing = args[0]; + let fun = null; + + if (thing === null && this.hasImplementation(Symbol('null'))) { + fun = this.registry.get(Symbol)[funName]; + } else if (Number.isInteger(thing) && this.hasImplementation(Core.Integer)) { + fun = this.registry.get(Core.Integer)[funName]; + } else if (typeof thing === 'number' && !Number.isInteger(thing) && this.hasImplementation(Core.Float)) { + fun = this.registry.get(Core.Float)[funName]; + } else if (typeof thing === 'string' && this.hasImplementation(Core.BitString)) { + fun = this.registry.get(Core.BitString)[funName]; + } else if (thing && thing instanceof Map && thing.has(Symbol.for('__struct__')) && this.hasImplementation(thing)) { + fun = this.registry.get(thing.get(Symbol.for('__struct__')).__MODULE__)[funName]; + } else if (thing !== null && this.hasImplementation(thing)) { + fun = this.registry.get(thing.constructor)[funName]; + } else if (this.fallback) { + fun = this.fallback[funName]; + } + + if (fun != null) { + const retval = fun.apply(this, args); + return retval; + } + + throw new Error(`No implementation found for ${thing}`); + }; + } + + for (const funName in spec) { + this[funName] = createFun(funName).bind(this); + } + } + + implementation(type, implementation) { + if (type === null) { + this.fallback = implementation; + } else { + this.registry.set(type, implementation); + } + } + + hasImplementation(thing) { + if (thing === Core.Integer || thing === Core.Float || thing === Core.BitString) { + return this.registry.has(thing); + } else if (thing && thing instanceof Map && thing.has(Symbol.for('__struct__'))) { + return this.registry.has(thing.get(Symbol.for('__struct__')).__MODULE__); + } + + return this.registry.has(thing.constructor); + } +} + +function iterator_to_reducer(iterable, acc, fun) { + const iterator = iterable[Symbol.iterator](); + let x = iterator.next(); + let _acc = acc; + + while (x.done === false) { + _acc = fun(x.value, _acc.get(1)); + if (_acc.get(0) === Symbol.for('halt')) { + return new Core.Tuple(Symbol.for('halted'), _acc.get(1)); + } else if (_acc.get(0) === Symbol.for('suspend')) { + return new Core.Tuple(Symbol.for('suspended'), _acc.get(1), new_acc => { + return iterator_to_reducer(iterator, new_acc, fun); + }); + } + + x = iterator.next(); + } + + return new Core.Tuple(Symbol.for('done'), _acc.get(1)); +} + +function call_property(item, property) { + if (!property) { + if (item instanceof Function || typeof item === 'function') { + return item(); + } + + return item; + } + + if (item instanceof Map) { + let prop = null; + + if (item.has(property)) { + prop = property; + } else if (item.has(Symbol.for(property))) { + prop = Symbol.for(property); + } + + if (prop === null) { + throw new Error(`Property ${property} not found in ${item}`); + } + + if (item.get(prop) instanceof Function || typeof item.get(prop) === 'function') { + return item.get(prop)(); + } + return item.get(prop); + } + + let prop = null; + + if (typeof item === 'number' || typeof item === 'symbol' || typeof item === 'boolean' || typeof item === 'string') { + if (item[property] !== undefined) { + prop = property; + } else if (item[Symbol.for(property)] !== undefined) { + prop = Symbol.for(property); + } + } else if (property in item) { + prop = property; + } else if (Symbol.for(property) in item) { + prop = Symbol.for(property); + } + + if (prop === null) { + throw new Error(`Property ${property} not found in ${item}`); + } + + if (item[prop] instanceof Function || typeof item[prop] === 'function') { + return item[prop](); + } + return item[prop]; +} + +function defprotocol(spec) { + return new Protocol(spec); +} + +function defimpl(protocol, type, impl) { + protocol.implementation(type, impl); +} + +function build_namespace(ns, ns_string) { + let parts = ns_string.split('.'); + const root = ns; + let parent = ns; + + if (parts[0] === 'Elixir') { + parts = parts.slice(1); + } + + for (const part of parts) { + if (typeof parent[part] === 'undefined') { + parent[part] = {}; + } + + parent = parent[part]; + } + + root.__table__ = ns.__table__ || {}; + root.__table__[Symbol.for(ns_string)] = parent; + + return parent; +} + +function map_to_object(map) { + const object = {}; + + for (const [key, value] of map.entries()) { + if (value instanceof Map) { + object[key] = map_to_object(value); + } else { + object[key] = value; + } + } + + return object; +} + +class Recurse { + constructor(func) { + this.func = func; + } +} + +function trampoline$1(f) { + let currentValue = f; + + while (currentValue && currentValue instanceof Recurse) { + currentValue = currentValue.func(); + } + + return currentValue; +} + +var Functions = { + call_property, + defprotocol, + defimpl, + build_namespace, + iterator_to_reducer, + map_to_object, + trampoline: trampoline$1, + Recurse +}; + +function _case(condition, clauses) { + return Core.Patterns.defmatch(...clauses)(condition); +} + +function cond(...clauses) { + for (const clause of clauses) { + if (clause[0]) { + return clause[1](); + } + } + + throw new Error(); +} + +function _for(expression, generators, collectable_protocol, into = []) { + let [result, fun] = collectable_protocol.into(into); + + const generatedValues = run_list_generators(generators.pop()(), generators); + + for (const value of generatedValues) { + if (expression.guard.apply(this, value)) { + result = fun(result, new Core.Tuple(Symbol.for('cont'), expression.fn.apply(this, value))); + } + } + + return fun(result, Symbol.for('done')); +} + +function run_list_generators(generator, generators) { + if (generators.length == 0) { + return generator.map(x => { + if (Array.isArray(x)) { + return x; + } + return [x]; + }); + } + const list = generators.pop(); + + const next_gen = []; + for (const j of list()) { + for (const i of generator) { + next_gen.push([j].concat(i)); + } + } + + return run_list_generators(next_gen, generators); +} + +function _try(do_fun, rescue_function, catch_fun, else_function, after_function) { + let result = null; + + try { + result = do_fun(); + } catch (e) { + let ex_result = null; + + if (rescue_function) { + try { + ex_result = rescue_function(e); + return ex_result; + } catch (ex) { + if (ex instanceof Core.Patterns.MatchError) { + throw ex; + } + } + } + + if (catch_fun) { + try { + ex_result = catch_fun(e); + return ex_result; + } catch (ex) { + if (ex instanceof Core.Patterns.MatchError) { + throw ex; + } + } + } + + throw e; + } finally { + if (after_function) { + after_function(); + } + } + + if (else_function) { + try { + return else_function(result); + } catch (ex) { + if (ex instanceof Core.Patterns.MatchError) { + throw new Error('No Match Found in Else'); + } + + throw ex; + } + } else { + return result; + } +} + +function _with(...args) { + let argsToPass = []; + let successFunction = null; + let elseFunction = null; + + if (typeof args[args.length - 2] === 'function') { + [successFunction, elseFunction] = args.splice(-2); + } else { + successFunction = args.pop(); + } + + for (let i = 0; i < args.length; i++) { + const [pattern, func] = args[i]; + + const result = func(...argsToPass); + + const patternResult = Core.Patterns.match_or_default(pattern, result); + + if (patternResult == null) { + if (elseFunction) { + return elseFunction.call(null, result); + } + return result; + } + + argsToPass = argsToPass.concat(patternResult); + } + + return successFunction(...argsToPass); +} + +function receive(clauses, after) { + console.warn('Receive not supported'); +} + +var SpecialForms = { + _case, + cond, + _for, + _try, + _with, + receive +}; + +// http://erlang.org/doc/man/lists.html +function reverse(list) { + return [...list].reverse(); +} + +function foreach(fun, list) { + list.forEach(x => fun(x)); + + return Symbol.for('ok'); +} + +function duplicate(n, elem) { + const list = []; + + while (list.length < n) { + list.push(elem); + } + + return list; +} + +function flatten(deepList, tail = []) { + const val = deepList.reduce((acc, value) => { + if (Array.isArray(value)) { + return acc.concat(flatten(value)); + } + + return acc.concat(value); + }, []); + + return val.concat(tail); +} + +function foldl(fun, acc0, list) { + return list.reduce((acc, value) => { + return fun(value, acc); + }, acc0); +} + +function foldr(fun, acc0, list) { + return foldl(fun, acc0, reverse(list)); +} + +function keyfind(key, n, tupleList) { + for (const tuple of tupleList) { + if (tuple.get(n - 1) === key) { + return tuple; + } + } + + return false; +} + +function keymember(key, n, tupleList) { + if (keyfind(key, n, tupleList) === false) { + return false; + } + + return true; +} + +function keyreplace(key, n, tupleList, newTuple) { + const newTupleList = [...tupleList]; + + for (let index = 0; index < newTupleList.length; index++) { + if (newTupleList[index].get(n - 1) === key) { + newTupleList[index] = newTuple; + return newTupleList; + } + } + + return newTupleList; +} + +function keysort(n, tupleList) { + const newTupleList = [...tupleList]; + + return newTupleList.sort((a, b) => { + if (a.get(n - 1) < b.get(n - 1)) { + return -1; + } else if (a.get(n - 1) > b.get(n - 1)) { + return 1; + } + + return 0; + }); +} + +function keystore(key, n, tupleList, newTuple) { + const newTupleList = [...tupleList]; + + for (let index = 0; index < newTupleList.length; index++) { + if (newTupleList[index].get(n - 1) === key) { + newTupleList[index] = newTuple; + return newTupleList; + } + } + + return newTupleList.concat(newTuple); +} + +function keydelete(key, n, tupleList) { + const newTupleList = []; + let deleted = false; + + for (let index = 0; index < tupleList.length; index++) { + if (deleted === false && tupleList[index].get(n - 1) === key) { + deleted = true; + } else { + newTupleList.push(tupleList[index]); + } + } + + return newTupleList; +} + +function keytake(key, n, tupleList) { + const result = keyfind(key, n, tupleList); + + if (result !== false) { + return new ErlangTypes.Tuple(result.get(n - 1), result, keydelete(key, n, tupleList)); + } + + return false; +} + +function mapfoldl(fun, acc0, list1) { + const listResult = []; + let accResult = acc0; + + for (const item of list1) { + const tuple = fun(item, accResult); + listResult.push(tuple.get(0)); + accResult = tuple.get(1); + } + + return new ErlangTypes.Tuple(listResult, accResult); +} + +function concat(things) { + return things.map(v => v.toString()).join(); +} + +function map(fun, list) { + return list.map(value => fun(value)); +} + +function filter(pred, list1) { + return list1.filter(x => pred(x)); +} + +function filtermap(fun, list1) { + const list2 = []; + + for (const item of list1) { + const value = fun(item); + + if (value === true) { + list2.push(item); + } else if (value instanceof ErlangTypes.Tuple && value.get(0) === true) { + list2.push(value.get(1)); + } + } + + return list2; +} + +function member(elem, list) { + for (const item of list) { + if (item === elem) { + return true; + } + } + + return false; +} + +function all(pred, list) { + for (const item of list) { + if (pred(item) === false) { + return false; + } + } + + return true; +} + +function any(pred, list) { + for (const item of list) { + if (pred(item) === true) { + return true; + } + } + + return false; +} + +function splitwith(pred, list) { + let switchToList2 = false; + const list1 = []; + const list2 = []; + + for (const item of list) { + if (switchToList2 === true) { + list2.push(item); + } else if (pred(item) === true) { + list1.push(item); + } else { + switchToList2 = true; + list2.push(item); + } + } + + return new ErlangTypes.Tuple(list1, list2); +} + +function sort(...args) { + if (args.length === 1) { + const list2 = [...args[0]]; + return list2.sort(); + } + + const fun = args[0]; + const list2 = [...args[1]]; + + return list2.sort((a, b) => { + const result = fun(a, b); + + if (result === true) { + return -1; + } + + return 1; + }); +} + +var lists = { + reverse, + foreach, + duplicate, + flatten, + foldl, + foldr, + keydelete, + keyfind, + keymember, + keyreplace, + keysort, + keystore, + keytake, + mapfoldl, + concat, + map, + filter, + filtermap, + member, + all, + any, + splitwith, + sort +}; + +// http://erlang.org/doc/man/erlang.html +const selfPID = new ErlangTypes.PID(); + +function atom_to_list(atom) { + return Symbol.keyFor(atom); +} + +function atom_to_binary(atom, encoding = Symbol.for('utf8')) { + if (encoding !== Symbol.for('utf8')) { + throw new Error(`unsupported encoding ${encoding}`); + } + + if (atom.__MODULE__) { + return Symbol.keyFor(atom.__MODULE__); + } + + return Symbol.keyFor(atom); +} + +function binary_to_atom(binary, encoding = Symbol.for('utf8')) { + if (encoding !== Symbol.for('utf8')) { + throw new Error(`unsupported encoding ${encoding}`); + } + + return Symbol.for(binary); +} + +function binary_to_existing_atom(binary, encoding = Symbol.for('utf8')) { + return binary_to_atom(binary, encoding); +} + +function list_concatenation(list1, list2) { + return list1.concat(list2); +} + +function list_subtraction(list1, list2) { + const list = [...list1]; + + for (const item of list2) { + const index = list.indexOf(item); + + if (index > -1) { + list.splice(index, 1); + } + } + + return list; +} + +function div(left, right) { + return left / right; +} + +function not(x) { + return !x; +} + +function rem(left, right) { + return left % right; +} + +function band(left, right) { + return left & right; +} + +function bor(left, right) { + return left | right; +} + +function bnot(x) { + return ~x; +} + +function bsl(left, right) { + return left << right; +} + +function bsr(left, right) { + return left >> right; +} + +function bxor(left, right) { + return left ^ right; +} + +function is_atom(value) { + return typeof value === 'symbol' || value instanceof Symbol || value.__MODULE__; +} + +function is_bitstring$1(value) { + return value instanceof ErlangTypes.BitString; +} + +function is_boolean$1(value) { + return typeof value === 'boolean' || value instanceof Boolean; +} + +function is_number$1(value) { + return typeof value === 'number' || value instanceof Number; +} + +function is_float(value) { + return is_number$1(value) && !Number.isInteger(value); +} + +function is_function$1(value) { + return typeof value === 'function' || value instanceof Function; +} + +function is_integer(value) { + return Number.isInteger(value); +} + +function is_list(value) { + return Array.isArray(value); +} + +function is_map$1(value) { + return value instanceof Map; +} + +function is_pid(value) { + return value instanceof ErlangTypes.PID; +} + +function is_port() { + return false; +} + +function is_reference(value) { + return value instanceof ErlangTypes.Reference; +} + +function is_tuple(value) { + return value instanceof ErlangTypes.Tuple; +} + +function is_binary(value) { + return typeof value === 'string' || value instanceof String; +} + +function element(n, tuple) { + return tuple.get(n - 1); +} + +function setelement(index, tuple1, value) { + const tupleData = [...tuple1.values]; + + tupleData[index - 1] = value; + + return new ErlangTypes.Tuple(...tupleData); +} + +function make_tuple(arity, initialValue) { + const list = []; + + for (let i = 0; i < arity; i++) { + list.push(initialValue); + } + + return new ErlangTypes.Tuple(...list); +} + +function insert_element(index, tuple, term) { + const list = [...tuple.values]; + list.splice(index - 1, 0, term); + + return new ErlangTypes.Tuple(...list); +} + +function append_element(tuple, term) { + const list = [...tuple.values]; + list.push(term); + + return new ErlangTypes.Tuple(...list); +} + +function delete_element(index, tuple) { + const list = [...tuple.values]; + list.splice(index - 1, 1); + + return new ErlangTypes.Tuple(...list); +} + +function tuple_to_list(tuple) { + const list = [...tuple.values]; + return list; +} + +function abs(number) { + return Math.abs(number); +} + +function apply(...args) { + if (args.length === 2) { + return args[0].apply(this, ...args[1]); + } + + return args[0][atom_to_binary(args[1])].apply(this, ...args[2]); +} + +function binary_part(binary, start, _length) { + return binary.substring(start, start + _length); +} + +function bit_size(bitstring) { + return bitstring.bit_size; +} + +function byte_size(bitstring) { + return bitstring.byte_size; +} + +function hd(list) { + return list[0]; +} + +function length(list) { + return list.length; +} + +function make_ref() { + return new ErlangTypes.Reference(); +} + +function map_size(map) { + return map.size; +} + +function max(first, second) { + return Math.max(first, second); +} + +function min(first, second) { + return Math.min(first, second); +} + +function round(number) { + return Math.round(number); +} + +function tl(list) { + return list.slice(1); +} + +function trunc(number) { + return Math.trunc(number); +} + +function tuple_size(tuple) { + return tuple.length; +} + +function binary_to_float(str) { + return parseFloat(str); +} + +function binary_to_integer(str, base = 10) { + return parseInt(str, base); +} + +function process_info(pid, item) { + if (item) { + if (item === Symbol.for('current_stacktrace')) { + return new ErlangTypes.Tuple(item, []); + } + + return new ErlangTypes.Tuple(item, null); + } + + return []; +} + +function list_to_binary(iolist) { + const iolistFlattened = lists.flatten(iolist); + + const value = iolistFlattened.reduce((acc, current) => { + if (current === null) { + return acc; + } else if (is_integer(current)) { + return acc + String.fromCodePoint(current); + } else if (is_bitstring$1(current)) { + return acc + String.fromCodePoint(...current.value); + } + + return acc + current; + }, ''); + + return value; +} + +function iolist_to_binary(ioListOrBinary) { + if (ioListOrBinary === null) { + return ''; + } + + if (is_binary(ioListOrBinary)) { + return ioListOrBinary; + } + + if (is_bitstring$1(ioListOrBinary)) { + return String.fromCodePoint(...ioListOrBinary.value); + } + + if (is_number$1(ioListOrBinary)) { + return String.fromCodePoint(ioListOrBinary); + } + + const iolistFlattened = lists.flatten(ioListOrBinary); + + const value = iolistFlattened.reduce((acc, current) => { + if (current === null) { + return acc; + } else if (is_integer(current)) { + return acc + String.fromCodePoint(current); + } else if (is_bitstring$1(current)) { + return acc + String.fromCodePoint(...current.value); + } + + return acc + iolist_to_binary(current); + }, ''); + + return value; +} + +function io_size(ioListOrBinary) { + return iolist_to_binary(ioListOrBinary).length; +} + +function integer_to_binary(integer, base = 10) { + return integer.toString(base); +} + +function node() { + return Symbol.for('nonode@nohost'); +} + +function self$1() { + return selfPID; +} + +function _throw(term) { + throw term; +} + +function error(reason) { + throw new ErlangTypes.Tuple(reason, []); +} + +function exit(...args) { + if (args.length === 2) { + throw args[1]; + } else { + throw args[0]; + } +} + +function raise(_class, reason) { + if (_class === Symbol.for('throw')) { + _throw(reason); + } else if (_class === Symbol.for('error')) { + error(reason); + } else { + exit(reason); + } +} + +var erlang = { + atom_to_binary, + binary_to_atom, + binary_to_existing_atom, + list_concatenation, + list_subtraction, + div, + not, + rem, + band, + bor, + bsl, + bsr, + bxor, + bnot, + is_bitstring: is_bitstring$1, + is_boolean: is_boolean$1, + is_float, + is_function: is_function$1, + is_integer, + is_list, + is_map: is_map$1, + is_number: is_number$1, + is_pid, + is_port, + is_reference, + is_tuple, + is_atom, + is_binary, + element, + setelement, + make_tuple, + insert_element, + append_element, + delete_element, + tuple_to_list, + abs, + apply, + binary_part, + bit_size, + byte_size, + hd, + length, + make_ref, + map_size, + max, + min, + round, + tl, + trunc, + tuple_size, + binary_to_float, + binary_to_integer, + process_info, + iolist_to_binary, + io_size, + integer_to_binary, + atom_to_list, + node, + self: self$1, + throw: _throw, + error, + exit, + raise, + list_to_binary +}; + +// http://erlang.org/doc/man/maps.html +const OK = Symbol.for('ok'); +const ERROR = Symbol.for('error'); +const BADMAP = Symbol.for('badmap'); +const BADKEY = Symbol.for('badkey'); + +function find(key, map) { + if (erlang.is_map(map) === false) { + return new ErlangTypes.Tuple(BADMAP, map); + } + + const value = map.get(key); + + if (typeof value !== 'undefined') { + return new ErlangTypes.Tuple(OK, value); + } + + return ERROR; +} + +function fold(fun, init, map) { + let acc = init; + + for (const [key, value] of map.entries()) { + acc = fun(key, value, acc); + } + + return acc; +} + +function remove(key, map1) { + if (erlang.is_map(map1) === false) { + return new ErlangTypes.Tuple(BADMAP, map1); + } + + const map2 = new Map(map1); + + map2.delete(key); + + return map2; +} + +function to_list(map) { + if (erlang.is_map(map) === false) { + return new ErlangTypes.Tuple(BADMAP, map); + } + + const list = []; + + for (const [key, value] of map.entries()) { + list.push(new ErlangTypes.Tuple(key, value)); + } + + return list; +} + +function from_list(list) { + return list.reduce((acc, item) => { + const [key, value] = item; + acc.set(key, value); + + return acc; + }, new Map()); +} + +function keys(map) { + if (erlang.is_map(map) === false) { + return new ErlangTypes.Tuple(BADMAP, map); + } + + return Array.from(map.keys()); +} + +function values$1(map) { + if (erlang.is_map(map) === false) { + return new ErlangTypes.Tuple(BADMAP, map); + } + + return Array.from(map.values()); +} + +function is_key(key, map) { + return map.has(key); +} + +function put(key, value, map1) { + if (erlang.is_map(map1) === false) { + return new ErlangTypes.Tuple(BADMAP, map1); + } + + const map2 = new Map(map1); + map2.set(key, value); + + return map2; +} + +function merge(map1, map2) { + if (erlang.is_map(map1) === false) { + return new ErlangTypes.Tuple(BADMAP, map1); + } + + if (erlang.is_map(map2) === false) { + return new ErlangTypes.Tuple(BADMAP, map2); + } + + return new Map([...map1, ...map2]); +} + +function update(key, value, map1) { + if (erlang.is_map(map1) === false) { + return new ErlangTypes.Tuple(BADMAP, map1); + } + + if (is_key(key, map1) === false) { + return new ErlangTypes.Tuple(BADKEY, key); + } + + return new Map([...map1, [key, value]]); +} + +function get(...args) { + const key = args[0]; + const map = args[1]; + + if (erlang.is_map(map) === false) { + return new ErlangTypes.Tuple(BADMAP, map); + } + + if (is_key(key)) { + return map.get(key); + } + + if (args.length === 3) { + return args[2]; + } + + return new ErlangTypes.Tuple(BADKEY, key); +} + +function take(key, map1) { + if (erlang.is_map(map1) === false) { + return new ErlangTypes.Tuple(BADMAP, map1); + } + + if (!is_key(key)) { + return ERROR; + } + + const value = map1.get(key); + const map2 = new Map(map1); + map2.delete(key); + + return new ErlangTypes.Tuple(value, map2); +} + +var maps = { + find, + fold, + remove, + to_list, + from_list, + keys, + values: values$1, + is_key, + put, + merge, + update, + get, + take +}; + +function warn(message) { + const messageString = message.join(''); + console.warn(`warning: ${messageString}`); + + return Symbol.for('ok'); +} + +var elixir_errors = { + warn +}; + +const MODULE = Symbol.for('elixir_config'); +const ets = new Map(); + +function _new(opts) { + ets.set(MODULE, new Map()); + ets.get(MODULE).set(MODULE, opts); + return MODULE; +} + +function _delete(module) { + ets.delete(module); + return true; +} + +function put$1(key, value) { + ets.get(MODULE).set(key, value); + return Symbol.for('ok'); +} + +function get$1(key) { + return ets.get(MODULE).get(key); +} + +function update$1(key, fun) { + const value = fun(ets.get(MODULE).get(key)); + put$1(key, value); + return value; +} + +function get_and_put(key, value) { + const oldValue = get$1(key); + put$1(key, value); + return oldValue; +} + +var elixir_config = { + new: _new, + delete: _delete, + put: put$1, + get: get$1, + update: update$1, + get_and_put +}; + +function put_chars(ioDevice, charData) { + const dataToWrite = erlang.iolist_to_binary(charData); + + if (ioDevice === Symbol.for('stderr')) { + console.error(dataToWrite); + } else { + console.log(dataToWrite); + } + + return Symbol.for('ok'); +} + +var io = { + put_chars +}; + +function copy(subject, n = 1) { + return subject.repeat(n); +} + +function list_to_bin(bytelist) { + return erlang.list_to_binary(bytelist); +} + +var binary = { + copy, + list_to_bin +}; + +function characters_to_list(characters) { + return characters.split('').map(c => c.codePointAt(0)); +} + +function characters_to_binary(characters) { + if (erlang.is_binary(characters)) { + return characters; + } + + return String.fromCodePoint(...characters); +} + +var unicode = { + characters_to_list, + characters_to_binary +}; + +function get_key(key) { + let real_key = key; + + if (__elixirscript_names__.has(key)) { + real_key = __elixirscript_names__.get(key); + } + + if (__elixirscript_store__.has(real_key)) { + return real_key; + } + + throw new Error(`Key ${real_key} not found`); +} + +function create(value, name = null) { + const key = new Core.PID(); + + if (name !== null) { + __elixirscript_names__.set(name, key); + } + + return __elixirscript_store__.set(key, value); +} + +function update$2(key, value) { + const real_key = get_key(key); + return __elixirscript_store__.set(real_key, value); +} + +function read(key) { + const real_key = get_key(key); + return __elixirscript_store__.get(real_key); +} + +function remove$1(key) { + const real_key = get_key(key); + return __elixirscript_store__.delete(real_key); +} + +var Store = { + create, + update: update$2, + read, + remove: remove$1 +}; + +class Integer {} +class Float {} + +function get_global() { + if (typeof self !== 'undefined') { + return self; + } else if (typeof window !== 'undefined') { + return window; + } else if (typeof global !== 'undefined') { + return global; + } + + console.warn('No global state found'); + return null; +} + +const globalState = get_global(); + +globalState.__elixirscript_store__ = new Map(); +globalState.__elixirscript_names__ = new Map(); + +var Core = { + Tuple: ErlangTypes.Tuple, + PID: ErlangTypes.PID, + BitString: ErlangTypes.BitString, + Patterns, + Integer, + Float, + Functions, + SpecialForms, + Store, + global: globalState, + erlang, + maps, + lists, + elixir_errors, + io, + binary, + unicode, + elixir_config +}; + +var elixir = { + Core +}; + +return elixir; + +}()); diff --git a/src/javascript/lib/core/erlang_compat/binary.js b/src/javascript/lib/core/erlang_compat/binary.js index 0e0c8f96..da07675d 100644 --- a/src/javascript/lib/core/erlang_compat/binary.js +++ b/src/javascript/lib/core/erlang_compat/binary.js @@ -1,7 +1,14 @@ +import erlang from './erlang'; + function copy(subject, n = 1) { return subject.repeat(n); } +function list_to_bin(bytelist) { + return erlang.list_to_binary(bytelist); +} + export default { - copy + copy, + list_to_bin }; diff --git a/src/javascript/lib/core/erlang_compat/erlang.js b/src/javascript/lib/core/erlang_compat/erlang.js index 5b853793..faf71dd8 100644 --- a/src/javascript/lib/core/erlang_compat/erlang.js +++ b/src/javascript/lib/core/erlang_compat/erlang.js @@ -2,6 +2,8 @@ import ErlangTypes from 'erlang-types'; import lists from './lists'; +const selfPID = new ErlangTypes.PID(); + function atom_to_list(atom) { return Symbol.keyFor(atom); } @@ -274,6 +276,24 @@ function process_info(pid, item) { return []; } +function list_to_binary(iolist) { + const iolistFlattened = lists.flatten(iolist); + + const value = iolistFlattened.reduce((acc, current) => { + if (current === null) { + return acc; + } else if (is_integer(current)) { + return acc + String.fromCodePoint(current); + } else if (is_bitstring(current)) { + return acc + String.fromCodePoint(...current.value); + } + + return acc + current; + }, ''); + + return value; +} + function iolist_to_binary(ioListOrBinary) { if (ioListOrBinary === null) { return ''; @@ -316,6 +336,44 @@ function integer_to_binary(integer, base = 10) { return integer.toString(base); } +function node() { + return Symbol.for('nonode@nohost'); +} + +function self() { + return selfPID; +} + +function _throw(term) { + throw term; +} + +function error(reason) { + throw new ErlangTypes.Tuple(reason, []); +} + +function exit(...args) { + if (args.length === 2) { + throw args[1]; + } else { + throw args[0]; + } +} + +function raise(_class, reason) { + if (_class === Symbol.for('throw')) { + _throw(reason); + } else if (_class === Symbol.for('error')) { + error(reason); + } else { + exit(reason); + } +} + +function function_exported(module, _function) { + return module[_function] != null; +} + export default { atom_to_binary, binary_to_atom, @@ -373,5 +431,12 @@ export default { iolist_to_binary, io_size, integer_to_binary, - atom_to_list + atom_to_list, + node, + self, + throw: _throw, + error, + exit, + raise, + list_to_binary }; From 7fed1c7fe6a507d96d0aa8ad3ef3bbf33b990500 Mon Sep 17 00:00:00 2001 From: vans163 Date: Wed, 2 Aug 2017 14:33:43 -0400 Subject: [PATCH 646/860] specify node.js version required in README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index b3b413d5..b5feac14 100644 --- a/README.md +++ b/README.md @@ -6,7 +6,7 @@ Requirements =========== * Erlang 20 or greater * Elixir 1.5 or greater (must be compiled with Erlang 20 or greater) -* Node (only for development) +* Node 8.2.1 or greater (only for development) Usage ======== From a7b33901b429f17fc625bcbc36d3e5b5fd9f1074 Mon Sep 17 00:00:00 2001 From: vans163 Date: Wed, 2 Aug 2017 14:49:49 -0400 Subject: [PATCH 647/860] lowercase JavaScriptInterop.html to prevent 404 --- GettingStarted.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/GettingStarted.md b/GettingStarted.md index c5b4681b..2026231f 100644 --- a/GettingStarted.md +++ b/GettingStarted.md @@ -61,4 +61,4 @@ Elixirscript supports all macros ### JavaScript Interop -Check out the [JavaScript Interoperability](JavaScriptInterop.html) documentation +Check out the [JavaScript Interoperability](JavascriptInterop.html) documentation From 9adeb3b7aa32ef0c4e0bd16a8bf1bfafdd42ac51 Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Thu, 3 Aug 2017 20:30:25 -0500 Subject: [PATCH 648/860] Rename foreign to defexternal --- JavascriptInterop.md | 6 +++--- lib/elixir_script/compiler.ex | 6 +----- lib/elixir_script/ffi.ex | 14 +++++++------- lib/elixir_script/lib/store.ex | 8 ++++---- test/ffi_test.exs | 4 ++-- 5 files changed, 17 insertions(+), 21 deletions(-) diff --git a/JavascriptInterop.md b/JavascriptInterop.md index 438a2781..751de238 100644 --- a/JavascriptInterop.md +++ b/JavascriptInterop.md @@ -25,12 +25,12 @@ Here is an example of a foreign module for a JSON module defmodule MyApp.JSON do use ElixirScript.FFI - foreign stringify(map) - foreign parse(string) + defexternal stringify(map) + defexternal parse(string) end ``` -Foreign modules map to JavaScript files that export functions defined with the `foreign` macro. +Foreign modules map to JavaScript files that export functions defined with the `defexternal` macro. ElixirScript expects JavaScript modules to be in the `priv/elixir_script` directory. These modules are copied to the output directory upon compilation. diff --git a/lib/elixir_script/compiler.ex b/lib/elixir_script/compiler.ex index 1c2d9c85..24f9bdc9 100644 --- a/lib/elixir_script/compiler.ex +++ b/lib/elixir_script/compiler.ex @@ -16,17 +16,13 @@ defmodule ElixirScript.Compiler do entry_modules = List.wrap(entry_modules) - IO.puts "Finding used modules" ElixirScript.FindUsedModules.execute(entry_modules, pid) - IO.puts "Finding used functions" ElixirScript.FindUsedFunctions.execute(entry_modules, pid) - IO.puts "Compiling" modules = ElixirScript.State.list_modules(pid) ElixirScript.Translate.execute(modules, pid) - IO.puts "Building Output" modules = ElixirScript.State.list_modules(pid) result = ElixirScript.Output.execute(modules, pid) @@ -56,4 +52,4 @@ defmodule ElixirScript.Compiler do defp get_module_formatter(_) do ElixirScript.ModuleSystems.ES end -end \ No newline at end of file +end diff --git a/lib/elixir_script/ffi.ex b/lib/elixir_script/ffi.ex index 3ee1ea94..6ae2d85e 100644 --- a/lib/elixir_script/ffi.ex +++ b/lib/elixir_script/ffi.ex @@ -3,7 +3,7 @@ defmodule ElixirScript.FFI do The foreign function interface for interacting with JavaScript To define a foreign module, make a new module and add `use ElixirScript.FFI`. to it - To define foreign functions, use the `foreign` macro. + To define external functions, use the `defexternal` macro. Here is an example of a foreign module for a JSON module @@ -11,12 +11,12 @@ defmodule ElixirScript.FFI do defmodule MyApp.JSON do use ElixirScript.FFI - foreign stringify(map) - foreign parse(string) + defexternal stringify(map) + defexternal parse(string) end ``` - Foreign modules map to JavaScript files that export functions defined with the `foreign` macro. + Foreign modules map to JavaScript files that export functions defined with the `defexternal` macro. ElixirScript expects JavaScript modules to be in the `priv/elixir_script` directory. These modules are copied to the output directory upon compilation. @@ -46,13 +46,13 @@ defmodule ElixirScript.FFI do @doc """ Defines a JavaScript function to be called from Elixir modules - To define a foreign function, pass the name and arguments to `foreign` + To define an external function, pass the name and arguments to `defexternal` ```elixir - foreign my_js_function(arg1, arg2, arg3) + defexternal my_js_function(arg1, arg2, arg3) ``` """ - defmacro foreign({name, _, args}) do + defmacro defexternal({name, _, args}) do args = Enum.map(args, fn {:\\, meta0, [{name, meta, atom}, value]}-> name = String.to_atom("_" <> Atom.to_string(name)) diff --git a/lib/elixir_script/lib/store.ex b/lib/elixir_script/lib/store.ex index 5c2efa23..9e98bce3 100644 --- a/lib/elixir_script/lib/store.ex +++ b/lib/elixir_script/lib/store.ex @@ -2,11 +2,11 @@ defmodule ElixirScript.Core.Store do @moduledoc false use ElixirScript.FFI, global: true - foreign create(value, name \\ nil) + defexternal create(value, name \\ nil) - foreign update(key, value) + defexternal update(key, value) - foreign read(key) + defexternal read(key) - foreign remove(key) + defexternal remove(key) end diff --git a/test/ffi_test.exs b/test/ffi_test.exs index dbbaa77d..5b593d52 100644 --- a/test/ffi_test.exs +++ b/test/ffi_test.exs @@ -4,7 +4,7 @@ defmodule ElixirScript.FFI.Test do defmodule MyTestModule do use ElixirScript.FFI - foreign my_test_function(arg1, arg2) + defexternal my_test_function(arg1, arg2) end test "FFI module has __foreign_info__ attribute" do @@ -14,4 +14,4 @@ defmodule ElixirScript.FFI.Test do test "FFI module makes foreign function" do assert Keyword.has_key?(MyTestModule.__info__(:functions), :my_test_function) end -end \ No newline at end of file +end From 4666746253c8d4d5affa61c66f3878bdd9cb6425 Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Thu, 3 Aug 2017 21:39:44 -0500 Subject: [PATCH 649/860] Document global option on FFI module Add name option. The value is used as the module name when creating the function call in JavaScript --- lib/elixir_script/ffi.ex | 11 +++++++++-- lib/elixir_script/passes/find_used_modules.ex | 10 ++++++++-- lib/elixir_script/passes/translate/forms/remote.ex | 13 +++++++++---- lib/elixir_script/passes/translate/module.ex | 10 ++++++++-- 4 files changed, 34 insertions(+), 10 deletions(-) diff --git a/lib/elixir_script/ffi.ex b/lib/elixir_script/ffi.ex index 6ae2d85e..8c94f78f 100644 --- a/lib/elixir_script/ffi.ex +++ b/lib/elixir_script/ffi.ex @@ -29,6 +29,13 @@ defmodule ElixirScript.FFI do parse: JSON.parse } ``` + + `ElixirScript.FFI` takes the following options + * `global`: If the module is defined in the global state or not. If this is set to `true`, + nothing is imported and instead ElixirScript will use the name of the module to call a module and + function in the global scope. + * `name`: Only applicable with `global` is set to `true`. This will use the name defined here + instead of the module name for calling modules and functions in the global scope """ defmacro __using__(opts) do @@ -37,7 +44,7 @@ defmodule ElixirScript.FFI do Module.register_attribute __MODULE__, :__foreign_info__, persist: true @__foreign_info__ %{ path: Macro.underscore(__MODULE__), - name: Enum.join(Module.split(__MODULE__), "_"), + name: unquote(Keyword.get(opts, :name, nil)), global: unquote(Keyword.get(opts, :global, false)) } end @@ -54,7 +61,7 @@ defmodule ElixirScript.FFI do """ defmacro defexternal({name, _, args}) do args = Enum.map(args, fn - {:\\, meta0, [{name, meta, atom}, value]}-> + {:\\, meta0, [{name, meta, atom}, value]} -> name = String.to_atom("_" <> Atom.to_string(name)) {:\\, meta0, [{name, meta, atom}, value]} diff --git a/lib/elixir_script/passes/find_used_modules.ex b/lib/elixir_script/passes/find_used_modules.ex index ee65f7a0..300cace0 100644 --- a/lib/elixir_script/passes/find_used_modules.ex +++ b/lib/elixir_script/passes/find_used_modules.ex @@ -26,8 +26,14 @@ defmodule ElixirScript.FindUsedModules do end defp walk_module(module, %{attributes: [__foreign_info__: %{path: path, name: name, global: global}]} = info, pid) do - path = if global, do: nil, else: path - name = if global, do: module, else: name + {name, path} = if global do + name = if name, do: name, else: module + path = nil + {name, path} + else + name = Enum.join(Module.split(module), "_") + {name, path} + end ModuleState.put_javascript_module(pid, module, name, path) ModuleState.put_module(pid, module, info) diff --git a/lib/elixir_script/passes/translate/forms/remote.ex b/lib/elixir_script/passes/translate/forms/remote.ex index cf6ac235..d9813bc5 100644 --- a/lib/elixir_script/passes/translate/forms/remote.ex +++ b/lib/elixir_script/passes/translate/forms/remote.ex @@ -99,11 +99,16 @@ defmodule ElixirScript.Translate.Forms.Remote do defp process_js_module_name(module, state) do case ModuleState.get_js_module_name(state.pid, module) do - name when is_atom(name) -> - members = Module.split(module) - Identifier.make_namespace_members(members) - name -> + name when is_binary(name) -> J.identifier(name) + name when is_atom(name) -> + case to_string(name) do + "Elixir." <> _ -> + members = Module.split(module) + Identifier.make_namespace_members(members) + x -> + J.identifier(x) + end end end diff --git a/lib/elixir_script/passes/translate/module.ex b/lib/elixir_script/passes/translate/module.ex index 43522b7b..f895df6c 100644 --- a/lib/elixir_script/passes/translate/module.ex +++ b/lib/elixir_script/passes/translate/module.ex @@ -14,8 +14,14 @@ defmodule ElixirScript.Translate.Module do end def compile(module, %{attributes: [__foreign_info__: %{path: path, name: name, global: global}]}, pid) do - path = if global, do: nil, else: path - name = if global, do: module, else: name + {name, path} = if global do + name = if name, do: name, else: module + path = nil + {name, path} + else + name = Enum.join(Module.split(module), "_") + {name, path} + end ModuleState.put_javascript_module(pid, module, name, path) From b322739198fc1c15e8c9b05fb8e83cb3970b8c86 Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Thu, 3 Aug 2017 21:51:37 -0500 Subject: [PATCH 650/860] Build minified version of ElixirScript.Core.js --- priv/build/iife/ElixirScript.Core.js | 2721 +------------------------- 1 file changed, 6 insertions(+), 2715 deletions(-) diff --git a/priv/build/iife/ElixirScript.Core.js b/priv/build/iife/ElixirScript.Core.js index 6253bea7..de1667aa 100644 --- a/priv/build/iife/ElixirScript.Core.js +++ b/priv/build/iife/ElixirScript.Core.js @@ -1,2715 +1,6 @@ -var ElixirScript = (function () { -'use strict'; - -/* @flow */ - -class Variable { - constructor(name = null, default_value = Symbol.for('tailored.no_value')) { - this.name = name; - this.default_value = default_value; - } -} - -class Wildcard { - constructor() {} -} - -class StartsWith { - constructor(prefix) { - this.prefix = prefix; - } -} - -class Capture { - constructor(value) { - this.value = value; - } -} - -class HeadTail { - constructor(head, tail) { - this.head = head; - this.tail = tail; - } -} - -class Type { - constructor(type, objPattern = {}) { - this.type = type; - this.objPattern = objPattern; - } -} - -class Bound { - constructor(value) { - this.value = value; - } -} - -class BitStringMatch { - constructor(...values) { - this.values = values; - } - - length() { - return values.length; - } - - bit_size() { - return this.byte_size() * 8; - } - - byte_size() { - let s = 0; - - for (let val of this.values) { - s = s + val.unit * val.size / 8; - } - - return s; - } - - getValue(index) { - return this.values(index); - } - - getSizeOfValue(index) { - let val = this.getValue(index); - return val.unit * val.size; - } - - getTypeOfValue(index) { - return this.getValue(index).type; - } -} - -class NamedVariableResult { - constructor(name, value) { - this.name = name; - this.value = value; - } -} - -function variable(name = null, default_value = Symbol.for('tailored.no_value')) { - return new Variable(name, default_value); -} - -function wildcard() { - return new Wildcard(); -} - -function startsWith(prefix) { - return new StartsWith(prefix); -} - -function capture(value) { - return new Capture(value); -} - -function headTail(head, tail) { - return new HeadTail(head, tail); -} - -function type(type, objPattern = {}) { - return new Type(type, objPattern); -} - -function bound(value) { - return new Bound(value); -} - -function bitStringMatch(...values) { - return new BitStringMatch(...values); -} - -function namedVariableResult(name, value) { - return new NamedVariableResult(name, value); -} - -/* @flow */ - -function is_number(value) { - return typeof value === 'number'; -} - -function is_string(value) { - return typeof value === 'string'; -} - -function is_boolean(value) { - return typeof value === 'boolean'; -} - -function is_symbol(value) { - return typeof value === 'symbol'; -} - -function is_object(value) { - return typeof value === 'object'; -} - -function is_variable(value) { - return value instanceof Variable; -} - -function is_null(value) { - return value === null; -} - -function is_array(value) { - return Array.isArray(value); -} - -function is_function(value) { - return Object.prototype.toString.call(value) == '[object Function]'; -} - -function is_map(value) { - return value instanceof Map; -} - -class Tuple { - constructor(...args) { - this.values = Object.freeze(args); - this.length = this.values.length; - } - - get(index) { - return this.values[index]; - } - - count() { - return this.values.length; - } - - [Symbol.iterator]() { - return this.values[Symbol.iterator](); - } - - toString() { - let i, - s = ''; - for (i = 0; i < this.values.length; i++) { - if (s !== '') { - s += ', '; - } - - const stringToAppend = this.values[i] ? this.values[i].toString() : ''; - - s += stringToAppend; - } - - return '{' + s + '}'; - } - - put_elem(index, elem) { - if (index === this.length) { - let new_values = this.values.concat([elem]); - return new Tuple(...new_values); - } - - let new_values = this.values.concat([]); - new_values.splice(index, 0, elem); - return new Tuple(...new_values); - } - - remove_elem(index) { - let new_values = this.values.concat([]); - new_values.splice(index, 1); - return new Tuple(...new_values); - } -} - -let process_counter = -1; - -class PID { - constructor() { - process_counter = process_counter + 1; - this.id = process_counter; - } - - toString() { - return 'PID#<0.' + this.id + '.0>'; - } -} - -let ref_counter = -1; - -class Reference { - constructor() { - ref_counter = ref_counter + 1; - this.id = ref_counter; - this.ref = Symbol(); - } - - toString() { - return 'Ref#<0.0.0.' + this.id + '>'; - } -} - -class BitString$1 { - constructor(...args) { - this.value = Object.freeze(this.process(args)); - this.length = this.value.length; - this.bit_size = this.length * 8; - this.byte_size = this.length; - } - - get(index) { - return this.value[index]; - } - - count() { - return this.value.length; - } - - slice(start, end = null) { - let s = this.value.slice(start, end); - let ms = s.map(elem => BitString$1.integer(elem)); - return new BitString$1(...ms); - } - - [Symbol.iterator]() { - return this.value[Symbol.iterator](); - } - - toString() { - var i, - s = ''; - for (i = 0; i < this.count(); i++) { - if (s !== '') { - s += ', '; - } - s += this.get(i).toString(); - } - - return '<<' + s + '>>'; - } - - process(bitStringParts) { - let processed_values = []; - - var i; - for (i = 0; i < bitStringParts.length; i++) { - let processed_value = this['process_' + bitStringParts[i].type](bitStringParts[i]); - - for (let attr of bitStringParts[i].attributes) { - processed_value = this['process_' + attr](processed_value); - } - - processed_values = processed_values.concat(processed_value); - } - - return processed_values; - } - - process_integer(value) { - return value.value; - } - - process_float(value) { - if (value.size === 64) { - return BitString$1.float64ToBytes(value.value); - } else if (value.size === 32) { - return BitString$1.float32ToBytes(value.value); - } - - throw new Error('Invalid size for float'); - } - - process_bitstring(value) { - return value.value.value; - } - - process_binary(value) { - return BitString$1.toUTF8Array(value.value); - } - - process_utf8(value) { - return BitString$1.toUTF8Array(value.value); - } - - process_utf16(value) { - return BitString$1.toUTF16Array(value.value); - } - - process_utf32(value) { - return BitString$1.toUTF32Array(value.value); - } - - process_signed(value) { - return new Uint8Array([value])[0]; - } - - process_unsigned(value) { - return value; - } - - process_native(value) { - return value; - } - - process_big(value) { - return value; - } - - process_little(value) { - return value.reverse(); - } - - process_size(value) { - return value; - } - - process_unit(value) { - return value; - } - - static integer(value) { - return BitString$1.wrap(value, { type: 'integer', unit: 1, size: 8 }); - } - - static float(value) { - return BitString$1.wrap(value, { type: 'float', unit: 1, size: 64 }); - } - - static bitstring(value) { - return BitString$1.wrap(value, { - type: 'bitstring', - unit: 1, - size: value.bit_size - }); - } - - static bits(value) { - return BitString$1.bitstring(value); - } - - static binary(value) { - return BitString$1.wrap(value, { - type: 'binary', - unit: 8, - size: value.length - }); - } - - static bytes(value) { - return BitString$1.binary(value); - } - - static utf8(value) { - return BitString$1.wrap(value, { type: 'utf8', unit: 1, size: value.length }); - } - - static utf16(value) { - return BitString$1.wrap(value, { - type: 'utf16', - unit: 1, - size: value.length * 2 - }); - } - - static utf32(value) { - return BitString$1.wrap(value, { - type: 'utf32', - unit: 1, - size: value.length * 4 - }); - } - - static signed(value) { - return BitString$1.wrap(value, {}, 'signed'); - } - - static unsigned(value) { - return BitString$1.wrap(value, {}, 'unsigned'); - } - - static native(value) { - return BitString$1.wrap(value, {}, 'native'); - } - - static big(value) { - return BitString$1.wrap(value, {}, 'big'); - } - - static little(value) { - return BitString$1.wrap(value, {}, 'little'); - } - - static size(value, count) { - return BitString$1.wrap(value, { size: count }); - } - - static unit(value, count) { - return BitString$1.wrap(value, { unit: count }); - } - - static wrap(value, opt, new_attribute = null) { - let the_value = value; - - if (!(value instanceof Object)) { - the_value = { value: value, attributes: [] }; - } - - the_value = Object.assign(the_value, opt); - - if (new_attribute) { - the_value.attributes.push(new_attribute); - } - - return the_value; - } - - static toUTF8Array(str) { - var utf8 = []; - for (var i = 0; i < str.length; i++) { - var charcode = str.charCodeAt(i); - if (charcode < 0x80) { - utf8.push(charcode); - } else if (charcode < 0x800) { - utf8.push(0xc0 | charcode >> 6, 0x80 | charcode & 0x3f); - } else if (charcode < 0xd800 || charcode >= 0xe000) { - utf8.push(0xe0 | charcode >> 12, 0x80 | charcode >> 6 & 0x3f, 0x80 | charcode & 0x3f); - } else { - // surrogate pair - i++; - // UTF-16 encodes 0x10000-0x10FFFF by - // subtracting 0x10000 and splitting the - // 20 bits of 0x0-0xFFFFF into two halves - charcode = 0x10000 + ((charcode & 0x3ff) << 10 | str.charCodeAt(i) & 0x3ff); - utf8.push(0xf0 | charcode >> 18, 0x80 | charcode >> 12 & 0x3f, 0x80 | charcode >> 6 & 0x3f, 0x80 | charcode & 0x3f); - } - } - return utf8; - } - - static toUTF16Array(str) { - var utf16 = []; - for (var i = 0; i < str.length; i++) { - var codePoint = str.codePointAt(i); - - if (codePoint <= 255) { - utf16.push(0); - utf16.push(codePoint); - } else { - utf16.push(codePoint >> 8 & 0xff); - utf16.push(codePoint & 0xff); - } - } - return utf16; - } - - static toUTF32Array(str) { - var utf32 = []; - for (var i = 0; i < str.length; i++) { - var codePoint = str.codePointAt(i); - - if (codePoint <= 255) { - utf32.push(0); - utf32.push(0); - utf32.push(0); - utf32.push(codePoint); - } else { - utf32.push(0); - utf32.push(0); - utf32.push(codePoint >> 8 & 0xff); - utf32.push(codePoint & 0xff); - } - } - return utf32; - } - - //http://stackoverflow.com/questions/2003493/javascript-float-from-to-bits - static float32ToBytes(f) { - var bytes = []; - - var buf = new ArrayBuffer(4); - new Float32Array(buf)[0] = f; - - let intVersion = new Uint32Array(buf)[0]; - - bytes.push(intVersion >> 24 & 0xff); - bytes.push(intVersion >> 16 & 0xff); - bytes.push(intVersion >> 8 & 0xff); - bytes.push(intVersion & 0xff); - - return bytes; - } - - static float64ToBytes(f) { - var bytes = []; - - var buf = new ArrayBuffer(8); - new Float64Array(buf)[0] = f; - - var intVersion1 = new Uint32Array(buf)[0]; - var intVersion2 = new Uint32Array(buf)[1]; - - bytes.push(intVersion2 >> 24 & 0xff); - bytes.push(intVersion2 >> 16 & 0xff); - bytes.push(intVersion2 >> 8 & 0xff); - bytes.push(intVersion2 & 0xff); - - bytes.push(intVersion1 >> 24 & 0xff); - bytes.push(intVersion1 >> 16 & 0xff); - bytes.push(intVersion1 >> 8 & 0xff); - bytes.push(intVersion1 & 0xff); - - return bytes; - } -} - -var ErlangTypes = { - Tuple, - PID, - Reference, - BitString: BitString$1 -}; - -/* @flow */ - -const BitString = ErlangTypes.BitString; - -function resolveSymbol(pattern) { - return function (value) { - return is_symbol(value) && value === pattern; - }; -} - -function resolveString(pattern) { - return function (value) { - return is_string(value) && value === pattern; - }; -} - -function resolveNumber(pattern) { - return function (value) { - return is_number(value) && value === pattern; - }; -} - -function resolveBoolean(pattern) { - return function (value) { - return is_boolean(value) && value === pattern; - }; -} - -function resolveFunction(pattern) { - return function (value) { - return is_function(value) && value === pattern; - }; -} - -function resolveNull(pattern) { - return function (value) { - return is_null(value); - }; -} - -function resolveBound(pattern) { - return function (value, args) { - if (typeof value === typeof pattern.value && value === pattern.value) { - return true; - } - - return false; - }; -} - -function resolveWildcard() { - return function () { - return true; - }; -} - -function resolveVariable(pattern) { - return function (value, args) { - if (pattern.name === null) { - args.push(value); - } else if (!pattern.name.startsWith('_')) { - args.push(namedVariableResult(pattern.name, value)); - } - - return true; - }; -} - -function resolveHeadTail(pattern) { - const headMatches = buildMatch(pattern.head); - const tailMatches = buildMatch(pattern.tail); - - return function (value, args) { - if (!is_array(value) || value.length === 0) { - return false; - } - - const head = value[0]; - const tail = value.slice(1); - - if (headMatches(head, args) && tailMatches(tail, args)) { - return true; - } - - return false; - }; -} - -function resolveCapture(pattern) { - const matches = buildMatch(pattern.value); - - return function (value, args) { - if (matches(value, args)) { - args.push(value); - return true; - } - - return false; - }; -} - -function resolveStartsWith(pattern) { - const prefix = pattern.prefix; - - return function (value, args) { - if (is_string(value) && value.startsWith(prefix)) { - args.push(value.substring(prefix.length)); - return true; - } - - return false; - }; -} - -function resolveType(pattern) { - return function (value, args) { - if (value instanceof pattern.type) { - const matches = buildMatch(pattern.objPattern); - return matches(value, args); - } - - return false; - }; -} - -function resolveArray(pattern) { - const matches = pattern.map(x => buildMatch(x)); - - return function (value, args) { - if (!is_array(value) || value.length != pattern.length) { - return false; - } - - return value.every(function (v, i) { - return matches[i](value[i], args); - }); - }; -} - -function resolveMap(pattern) { - let matches = new Map(); - - const keys = Array.from(pattern.keys()); - - for (let key of keys) { - matches.set(key, buildMatch(pattern.get(key))); - } - - return function (value, args) { - if (!is_map(value) || pattern.size > value.size) { - return false; - } - - for (let key of keys) { - if (!value.has(key) || !matches.get(key)(value.get(key), args)) { - return false; - } - } - - return true; - }; -} - -function resolveObject(pattern) { - let matches = {}; - - const keys = Object.keys(pattern).concat(Object.getOwnPropertySymbols(pattern)); - - for (let key of keys) { - matches[key] = buildMatch(pattern[key]); - } - - return function (value, args) { - if (!is_object(value) || pattern.length > value.length) { - return false; - } - - for (let key of keys) { - if (!(key in value) || !matches[key](value[key], args)) { - return false; - } - } - - return true; - }; -} - -function resolveBitString(pattern) { - let patternBitString = []; - - for (let bitstringMatchPart of pattern.values) { - if (is_variable(bitstringMatchPart.value)) { - let size = getSize(bitstringMatchPart.unit, bitstringMatchPart.size); - fillArray(patternBitString, size); - } else { - patternBitString = patternBitString.concat(new BitString(bitstringMatchPart).value); - } - } - - let patternValues = pattern.values; - - return function (value, args) { - let bsValue = null; - - if (!is_string(value) && !(value instanceof BitString)) { - return false; - } - - if (is_string(value)) { - bsValue = new BitString(BitString.binary(value)); - } else { - bsValue = value; - } - - let beginningIndex = 0; - - for (let i = 0; i < patternValues.length; i++) { - let bitstringMatchPart = patternValues[i]; - - if (is_variable(bitstringMatchPart.value) && bitstringMatchPart.type == 'binary' && bitstringMatchPart.size === undefined && i < patternValues.length - 1) { - throw new Error('a binary field without size is only allowed at the end of a binary pattern'); - } - - let size = 0; - let bsValueArrayPart = []; - let patternBitStringArrayPart = []; - size = getSize(bitstringMatchPart.unit, bitstringMatchPart.size); - - if (i === patternValues.length - 1) { - bsValueArrayPart = bsValue.value.slice(beginningIndex); - patternBitStringArrayPart = patternBitString.slice(beginningIndex); - } else { - bsValueArrayPart = bsValue.value.slice(beginningIndex, beginningIndex + size); - patternBitStringArrayPart = patternBitString.slice(beginningIndex, beginningIndex + size); - } - - if (is_variable(bitstringMatchPart.value)) { - switch (bitstringMatchPart.type) { - case 'integer': - if (bitstringMatchPart.attributes && bitstringMatchPart.attributes.indexOf('signed') != -1) { - args.push(new Int8Array([bsValueArrayPart[0]])[0]); - } else { - args.push(new Uint8Array([bsValueArrayPart[0]])[0]); - } - break; - - case 'float': - if (size === 64) { - args.push(Float64Array.from(bsValueArrayPart)[0]); - } else if (size === 32) { - args.push(Float32Array.from(bsValueArrayPart)[0]); - } else { - return false; - } - break; - - case 'bitstring': - args.push(createBitString(bsValueArrayPart)); - break; - - case 'binary': - args.push(String.fromCharCode.apply(null, new Uint8Array(bsValueArrayPart))); - break; - - case 'utf8': - args.push(String.fromCharCode.apply(null, new Uint8Array(bsValueArrayPart))); - break; - - case 'utf16': - args.push(String.fromCharCode.apply(null, new Uint16Array(bsValueArrayPart))); - break; - - case 'utf32': - args.push(String.fromCharCode.apply(null, new Uint32Array(bsValueArrayPart))); - break; - - default: - return false; - } - } else if (!arraysEqual(bsValueArrayPart, patternBitStringArrayPart)) { - return false; - } - - beginningIndex = beginningIndex + size; - } - - return true; - }; -} - -function getSize(unit, size) { - return unit * size / 8; -} - -function arraysEqual(a, b) { - if (a === b) return true; - if (a == null || b == null) return false; - if (a.length != b.length) return false; - - for (var i = 0; i < a.length; ++i) { - if (a[i] !== b[i]) return false; - } - - return true; -} - -function fillArray(arr, num) { - for (let i = 0; i < num; i++) { - arr.push(0); - } -} - -function createBitString(arr) { - let integerParts = arr.map(elem => BitString.integer(elem)); - return new BitString(...integerParts); -} - -function resolveNoMatch() { - return function () { - return false; - }; -} - -const patternMap = new Map(); -patternMap.set(Variable.prototype, resolveVariable); -patternMap.set(Wildcard.prototype, resolveWildcard); -patternMap.set(HeadTail.prototype, resolveHeadTail); -patternMap.set(StartsWith.prototype, resolveStartsWith); -patternMap.set(Capture.prototype, resolveCapture); -patternMap.set(Bound.prototype, resolveBound); -patternMap.set(Type.prototype, resolveType); -patternMap.set(BitStringMatch.prototype, resolveBitString); -patternMap.set(Number.prototype, resolveNumber); -patternMap.set(Symbol.prototype, resolveSymbol); -patternMap.set(Map.prototype, resolveMap); -patternMap.set(Array.prototype, resolveArray); -patternMap.set(String.prototype, resolveString); -patternMap.set(Boolean.prototype, resolveBoolean); -patternMap.set(Function.prototype, resolveFunction); -patternMap.set(Object.prototype, resolveObject); - -function buildMatch(pattern) { - if (pattern === null) { - return resolveNull(pattern); - } - - if (typeof pattern === 'undefined') { - return resolveWildcard(pattern); - } - - const type$$1 = pattern.constructor.prototype; - const resolver = patternMap.get(type$$1); - - if (resolver) { - return resolver(pattern); - } - - if (typeof pattern === 'object') { - return resolveObject(pattern); - } - - return resolveNoMatch(); -} - -class MatchError extends Error { - constructor(arg) { - super(); - - if (typeof arg === 'symbol') { - this.message = 'No match for: ' + arg.toString(); - } else if (Array.isArray(arg)) { - let mappedValues = arg.map(x => { - if (x === null) { - return 'null'; - } else if (typeof x === 'undefined') { - return 'undefined'; - } - - return x.toString(); - }); - - this.message = 'No match for: ' + mappedValues; - } else { - this.message = 'No match for: ' + arg; - } - - this.stack = new Error().stack; - this.name = this.constructor.name; - } -} - -class Clause { - constructor(pattern, fn, guard = () => true) { - this.pattern = buildMatch(pattern); - this.arity = pattern.length; - this.optionals = getOptionalValues(pattern); - this.fn = fn; - this.guard = guard; - } -} - -function clause(pattern, fn, guard = () => true) { - return new Clause(pattern, fn, guard); -} - - - -function defmatch(...clauses) { - const arities = getArityMap(clauses); - - return function (...args) { - let [funcToCall, params] = findMatchingFunction(args, arities); - return funcToCall.apply(this, params); - }; -} - -function defmatchgen(...clauses) { - const arities = getArityMap(clauses); - - return function* (...args) { - let [funcToCall, params] = findMatchingFunction(args, arities); - return yield* funcToCall.apply(this, params); - }; -} - -function defmatchGen(...args) { - return defmatchgen(...args); -} - -function defmatchAsync(...clauses) { - const arities = getArityMap(clauses); - - return async function (...args) { - if (arities.has(args.length)) { - const arityClauses = arities.get(args.length); - - let funcToCall = null; - let params = null; - for (let processedClause of arityClauses) { - let result = []; - args = fillInOptionalValues(args, processedClause.arity, processedClause.optionals); - - const doesMatch = processedClause.pattern(args, result); - const [filteredResult, allNamesMatch] = checkNamedVariables(result); - - if (doesMatch && allNamesMatch && (await processedClause.guard.apply(this, result))) { - funcToCall = processedClause.fn; - params = result; - break; - } - } - - if (!funcToCall) { - console.error('No match for:', args); - throw new MatchError(args); - } - - return funcToCall.apply(this, params); - } else { - console.error('Arity of', args.length, 'not found. No match for:', args); - throw new MatchError(args); - } - }; -} - -function findMatchingFunction(args, arities) { - if (arities.has(args.length)) { - const arityClauses = arities.get(args.length); - - let funcToCall = null; - let params = null; - for (let processedClause of arityClauses) { - let result = []; - args = fillInOptionalValues(args, processedClause.arity, processedClause.optionals); - - const doesMatch = processedClause.pattern(args, result); - const [filteredResult, allNamesMatch] = checkNamedVariables(result); - - if (doesMatch && allNamesMatch && processedClause.guard.apply(this, filteredResult)) { - funcToCall = processedClause.fn; - params = filteredResult; - break; - } - } - - if (!funcToCall) { - console.error('No match for:', args); - throw new MatchError(args); - } - - return [funcToCall, params]; - } else { - console.error('Arity of', args.length, 'not found. No match for:', args); - throw new MatchError(args); - } -} - -function getArityMap(clauses) { - let map = new Map(); - - for (const clause of clauses) { - const range = getArityRange(clause); - - for (const arity of range) { - let arityClauses = []; - - if (map.has(arity)) { - arityClauses = map.get(arity); - } - - arityClauses.push(clause); - map.set(arity, arityClauses); - } - } - - return map; -} - -function getArityRange(clause) { - const min = clause.arity - clause.optionals.length; - const max = clause.arity; - - let range = [min]; - - while (range[range.length - 1] != max) { - range.push(range[range.length - 1] + 1); - } - - return range; -} - -function getOptionalValues(pattern) { - let optionals = []; - - for (let i = 0; i < pattern.length; i++) { - if (pattern[i] instanceof Variable && pattern[i].default_value != Symbol.for('tailored.no_value')) { - optionals.push([i, pattern[i].default_value]); - } - } - - return optionals; -} - -function fillInOptionalValues(args, arity, optionals) { - if (args.length === arity || optionals.length === 0) { - return args; - } - - if (args.length + optionals.length < arity) { - return args; - } - - let numberOfOptionalsToFill = arity - args.length; - let optionalsToRemove = optionals.length - numberOfOptionalsToFill; - - let optionalsToUse = optionals.slice(optionalsToRemove); - - for (let [index, value] of optionalsToUse) { - args.splice(index, 0, value); - if (args.length === arity) { - break; - } - } - - return args; -} - -function match(pattern, expr, guard = () => true) { - let result = []; - let processedPattern = buildMatch(pattern); - const doesMatch = processedPattern(expr, result); - const [filteredResult, allNamesMatch] = checkNamedVariables(result); - - if (doesMatch && allNamesMatch && guard.apply(this, filteredResult)) { - return filteredResult; - } else { - console.error('No match for:', expr); - throw new MatchError(expr); - } -} - -function checkNamedVariables(results) { - const namesMap = {}; - const filteredResults = []; - - for (let i = 0; i < results.length; i++) { - const current = results[i]; - if (current instanceof NamedVariableResult) { - if (namesMap[current.name] && namesMap[current.name] !== current.value) { - return [results, false]; - } else if (namesMap[current.name] && namesMap[current.name] === current.value) { - filteredResults.push(current.value); - } else { - namesMap[current.name] = current.value; - filteredResults.push(current.value); - } - } else { - filteredResults.push(current); - } - } - - return [filteredResults, true]; -} - -function match_or_default(pattern, expr, guard = () => true, default_value = null) { - let result = []; - let processedPattern = buildMatch(pattern); - const doesMatch = processedPattern(expr, result); - const [filteredResult, allNamesMatch] = checkNamedVariables(result); - - if (doesMatch && allNamesMatch && guard.apply(this, filteredResult)) { - return filteredResult; - } else { - return default_value; - } -} - -const NO_MATCH = Symbol(); - -function bitstring_generator(pattern, bitstring) { - return function () { - let returnResult = []; - let bsSlice = bitstring.slice(0, pattern.byte_size()); - let i = 1; - - while (bsSlice.byte_size == pattern.byte_size()) { - const result = match_or_default(pattern, bsSlice, () => true, NO_MATCH); - - if (result != NO_MATCH) { - const [value] = result; - returnResult.push(result); - } - - bsSlice = bitstring.slice(pattern.byte_size() * i, pattern.byte_size() * (i + 1)); - - i++; - } - - return returnResult; - }; -} - -function list_generator(pattern, list) { - return function () { - let returnResult = []; - for (let i of list) { - const result = match_or_default(pattern, i, () => true, NO_MATCH); - if (result != NO_MATCH) { - const [value] = result; - returnResult.push(value); - } - } - - return returnResult; - }; -} - -function list_comprehension(expression, generators) { - const generatedValues = run_generators(generators.pop()(), generators); - - let result = []; - - for (let value of generatedValues) { - if (expression.guard.apply(this, value)) { - result.push(expression.fn.apply(this, value)); - } - } - - return result; -} - -function run_generators(generator, generators) { - if (generators.length == 0) { - return generator.map(x => { - if (Array.isArray(x)) { - return x; - } else { - return [x]; - } - }); - } else { - const list = generators.pop(); - - let next_gen = []; - for (let j of list()) { - for (let i of generator) { - next_gen.push([j].concat(i)); - } - } - - return run_generators(next_gen, generators); - } -} - -function bitstring_comprehension(expression, generators) { - const generatedValues = run_generators(generators.pop()(), generators); - - let result = []; - - for (let value of generatedValues) { - if (expression.guard.apply(this, value)) { - result.push(expression.fn.apply(this, value)); - } - } - - result = result.map(x => ErlangTypes.BitString.integer(x)); - return new ErlangTypes.BitString(...result); -} - -var Patterns = { - defmatch, - match, - MatchError, - variable, - wildcard, - startsWith, - capture, - headTail, - type, - bound, - Clause, - clause, - bitStringMatch, - match_or_default, - defmatchgen, - list_comprehension, - list_generator, - bitstring_generator, - bitstring_comprehension, - defmatchGen, - defmatchAsync -}; - -// https://github.com/airportyh/protomorphism -class Protocol { - constructor(spec) { - this.registry = new Map(); - this.fallback = null; - - function createFun(funName) { - return function (...args) { - const thing = args[0]; - let fun = null; - - if (thing === null && this.hasImplementation(Symbol('null'))) { - fun = this.registry.get(Symbol)[funName]; - } else if (Number.isInteger(thing) && this.hasImplementation(Core.Integer)) { - fun = this.registry.get(Core.Integer)[funName]; - } else if (typeof thing === 'number' && !Number.isInteger(thing) && this.hasImplementation(Core.Float)) { - fun = this.registry.get(Core.Float)[funName]; - } else if (typeof thing === 'string' && this.hasImplementation(Core.BitString)) { - fun = this.registry.get(Core.BitString)[funName]; - } else if (thing && thing instanceof Map && thing.has(Symbol.for('__struct__')) && this.hasImplementation(thing)) { - fun = this.registry.get(thing.get(Symbol.for('__struct__')).__MODULE__)[funName]; - } else if (thing !== null && this.hasImplementation(thing)) { - fun = this.registry.get(thing.constructor)[funName]; - } else if (this.fallback) { - fun = this.fallback[funName]; - } - - if (fun != null) { - const retval = fun.apply(this, args); - return retval; - } - - throw new Error(`No implementation found for ${thing}`); - }; - } - - for (const funName in spec) { - this[funName] = createFun(funName).bind(this); - } - } - - implementation(type, implementation) { - if (type === null) { - this.fallback = implementation; - } else { - this.registry.set(type, implementation); - } - } - - hasImplementation(thing) { - if (thing === Core.Integer || thing === Core.Float || thing === Core.BitString) { - return this.registry.has(thing); - } else if (thing && thing instanceof Map && thing.has(Symbol.for('__struct__'))) { - return this.registry.has(thing.get(Symbol.for('__struct__')).__MODULE__); - } - - return this.registry.has(thing.constructor); - } -} - -function iterator_to_reducer(iterable, acc, fun) { - const iterator = iterable[Symbol.iterator](); - let x = iterator.next(); - let _acc = acc; - - while (x.done === false) { - _acc = fun(x.value, _acc.get(1)); - if (_acc.get(0) === Symbol.for('halt')) { - return new Core.Tuple(Symbol.for('halted'), _acc.get(1)); - } else if (_acc.get(0) === Symbol.for('suspend')) { - return new Core.Tuple(Symbol.for('suspended'), _acc.get(1), new_acc => { - return iterator_to_reducer(iterator, new_acc, fun); - }); - } - - x = iterator.next(); - } - - return new Core.Tuple(Symbol.for('done'), _acc.get(1)); -} - -function call_property(item, property) { - if (!property) { - if (item instanceof Function || typeof item === 'function') { - return item(); - } - - return item; - } - - if (item instanceof Map) { - let prop = null; - - if (item.has(property)) { - prop = property; - } else if (item.has(Symbol.for(property))) { - prop = Symbol.for(property); - } - - if (prop === null) { - throw new Error(`Property ${property} not found in ${item}`); - } - - if (item.get(prop) instanceof Function || typeof item.get(prop) === 'function') { - return item.get(prop)(); - } - return item.get(prop); - } - - let prop = null; - - if (typeof item === 'number' || typeof item === 'symbol' || typeof item === 'boolean' || typeof item === 'string') { - if (item[property] !== undefined) { - prop = property; - } else if (item[Symbol.for(property)] !== undefined) { - prop = Symbol.for(property); - } - } else if (property in item) { - prop = property; - } else if (Symbol.for(property) in item) { - prop = Symbol.for(property); - } - - if (prop === null) { - throw new Error(`Property ${property} not found in ${item}`); - } - - if (item[prop] instanceof Function || typeof item[prop] === 'function') { - return item[prop](); - } - return item[prop]; -} - -function defprotocol(spec) { - return new Protocol(spec); -} - -function defimpl(protocol, type, impl) { - protocol.implementation(type, impl); -} - -function build_namespace(ns, ns_string) { - let parts = ns_string.split('.'); - const root = ns; - let parent = ns; - - if (parts[0] === 'Elixir') { - parts = parts.slice(1); - } - - for (const part of parts) { - if (typeof parent[part] === 'undefined') { - parent[part] = {}; - } - - parent = parent[part]; - } - - root.__table__ = ns.__table__ || {}; - root.__table__[Symbol.for(ns_string)] = parent; - - return parent; -} - -function map_to_object(map) { - const object = {}; - - for (const [key, value] of map.entries()) { - if (value instanceof Map) { - object[key] = map_to_object(value); - } else { - object[key] = value; - } - } - - return object; -} - -class Recurse { - constructor(func) { - this.func = func; - } -} - -function trampoline$1(f) { - let currentValue = f; - - while (currentValue && currentValue instanceof Recurse) { - currentValue = currentValue.func(); - } - - return currentValue; -} - -var Functions = { - call_property, - defprotocol, - defimpl, - build_namespace, - iterator_to_reducer, - map_to_object, - trampoline: trampoline$1, - Recurse -}; - -function _case(condition, clauses) { - return Core.Patterns.defmatch(...clauses)(condition); -} - -function cond(...clauses) { - for (const clause of clauses) { - if (clause[0]) { - return clause[1](); - } - } - - throw new Error(); -} - -function _for(expression, generators, collectable_protocol, into = []) { - let [result, fun] = collectable_protocol.into(into); - - const generatedValues = run_list_generators(generators.pop()(), generators); - - for (const value of generatedValues) { - if (expression.guard.apply(this, value)) { - result = fun(result, new Core.Tuple(Symbol.for('cont'), expression.fn.apply(this, value))); - } - } - - return fun(result, Symbol.for('done')); -} - -function run_list_generators(generator, generators) { - if (generators.length == 0) { - return generator.map(x => { - if (Array.isArray(x)) { - return x; - } - return [x]; - }); - } - const list = generators.pop(); - - const next_gen = []; - for (const j of list()) { - for (const i of generator) { - next_gen.push([j].concat(i)); - } - } - - return run_list_generators(next_gen, generators); -} - -function _try(do_fun, rescue_function, catch_fun, else_function, after_function) { - let result = null; - - try { - result = do_fun(); - } catch (e) { - let ex_result = null; - - if (rescue_function) { - try { - ex_result = rescue_function(e); - return ex_result; - } catch (ex) { - if (ex instanceof Core.Patterns.MatchError) { - throw ex; - } - } - } - - if (catch_fun) { - try { - ex_result = catch_fun(e); - return ex_result; - } catch (ex) { - if (ex instanceof Core.Patterns.MatchError) { - throw ex; - } - } - } - - throw e; - } finally { - if (after_function) { - after_function(); - } - } - - if (else_function) { - try { - return else_function(result); - } catch (ex) { - if (ex instanceof Core.Patterns.MatchError) { - throw new Error('No Match Found in Else'); - } - - throw ex; - } - } else { - return result; - } -} - -function _with(...args) { - let argsToPass = []; - let successFunction = null; - let elseFunction = null; - - if (typeof args[args.length - 2] === 'function') { - [successFunction, elseFunction] = args.splice(-2); - } else { - successFunction = args.pop(); - } - - for (let i = 0; i < args.length; i++) { - const [pattern, func] = args[i]; - - const result = func(...argsToPass); - - const patternResult = Core.Patterns.match_or_default(pattern, result); - - if (patternResult == null) { - if (elseFunction) { - return elseFunction.call(null, result); - } - return result; - } - - argsToPass = argsToPass.concat(patternResult); - } - - return successFunction(...argsToPass); -} - -function receive(clauses, after) { - console.warn('Receive not supported'); -} - -var SpecialForms = { - _case, - cond, - _for, - _try, - _with, - receive -}; - -// http://erlang.org/doc/man/lists.html -function reverse(list) { - return [...list].reverse(); -} - -function foreach(fun, list) { - list.forEach(x => fun(x)); - - return Symbol.for('ok'); -} - -function duplicate(n, elem) { - const list = []; - - while (list.length < n) { - list.push(elem); - } - - return list; -} - -function flatten(deepList, tail = []) { - const val = deepList.reduce((acc, value) => { - if (Array.isArray(value)) { - return acc.concat(flatten(value)); - } - - return acc.concat(value); - }, []); - - return val.concat(tail); -} - -function foldl(fun, acc0, list) { - return list.reduce((acc, value) => { - return fun(value, acc); - }, acc0); -} - -function foldr(fun, acc0, list) { - return foldl(fun, acc0, reverse(list)); -} - -function keyfind(key, n, tupleList) { - for (const tuple of tupleList) { - if (tuple.get(n - 1) === key) { - return tuple; - } - } - - return false; -} - -function keymember(key, n, tupleList) { - if (keyfind(key, n, tupleList) === false) { - return false; - } - - return true; -} - -function keyreplace(key, n, tupleList, newTuple) { - const newTupleList = [...tupleList]; - - for (let index = 0; index < newTupleList.length; index++) { - if (newTupleList[index].get(n - 1) === key) { - newTupleList[index] = newTuple; - return newTupleList; - } - } - - return newTupleList; -} - -function keysort(n, tupleList) { - const newTupleList = [...tupleList]; - - return newTupleList.sort((a, b) => { - if (a.get(n - 1) < b.get(n - 1)) { - return -1; - } else if (a.get(n - 1) > b.get(n - 1)) { - return 1; - } - - return 0; - }); -} - -function keystore(key, n, tupleList, newTuple) { - const newTupleList = [...tupleList]; - - for (let index = 0; index < newTupleList.length; index++) { - if (newTupleList[index].get(n - 1) === key) { - newTupleList[index] = newTuple; - return newTupleList; - } - } - - return newTupleList.concat(newTuple); -} - -function keydelete(key, n, tupleList) { - const newTupleList = []; - let deleted = false; - - for (let index = 0; index < tupleList.length; index++) { - if (deleted === false && tupleList[index].get(n - 1) === key) { - deleted = true; - } else { - newTupleList.push(tupleList[index]); - } - } - - return newTupleList; -} - -function keytake(key, n, tupleList) { - const result = keyfind(key, n, tupleList); - - if (result !== false) { - return new ErlangTypes.Tuple(result.get(n - 1), result, keydelete(key, n, tupleList)); - } - - return false; -} - -function mapfoldl(fun, acc0, list1) { - const listResult = []; - let accResult = acc0; - - for (const item of list1) { - const tuple = fun(item, accResult); - listResult.push(tuple.get(0)); - accResult = tuple.get(1); - } - - return new ErlangTypes.Tuple(listResult, accResult); -} - -function concat(things) { - return things.map(v => v.toString()).join(); -} - -function map(fun, list) { - return list.map(value => fun(value)); -} - -function filter(pred, list1) { - return list1.filter(x => pred(x)); -} - -function filtermap(fun, list1) { - const list2 = []; - - for (const item of list1) { - const value = fun(item); - - if (value === true) { - list2.push(item); - } else if (value instanceof ErlangTypes.Tuple && value.get(0) === true) { - list2.push(value.get(1)); - } - } - - return list2; -} - -function member(elem, list) { - for (const item of list) { - if (item === elem) { - return true; - } - } - - return false; -} - -function all(pred, list) { - for (const item of list) { - if (pred(item) === false) { - return false; - } - } - - return true; -} - -function any(pred, list) { - for (const item of list) { - if (pred(item) === true) { - return true; - } - } - - return false; -} - -function splitwith(pred, list) { - let switchToList2 = false; - const list1 = []; - const list2 = []; - - for (const item of list) { - if (switchToList2 === true) { - list2.push(item); - } else if (pred(item) === true) { - list1.push(item); - } else { - switchToList2 = true; - list2.push(item); - } - } - - return new ErlangTypes.Tuple(list1, list2); -} - -function sort(...args) { - if (args.length === 1) { - const list2 = [...args[0]]; - return list2.sort(); - } - - const fun = args[0]; - const list2 = [...args[1]]; - - return list2.sort((a, b) => { - const result = fun(a, b); - - if (result === true) { - return -1; - } - - return 1; - }); -} - -var lists = { - reverse, - foreach, - duplicate, - flatten, - foldl, - foldr, - keydelete, - keyfind, - keymember, - keyreplace, - keysort, - keystore, - keytake, - mapfoldl, - concat, - map, - filter, - filtermap, - member, - all, - any, - splitwith, - sort -}; - -// http://erlang.org/doc/man/erlang.html -const selfPID = new ErlangTypes.PID(); - -function atom_to_list(atom) { - return Symbol.keyFor(atom); -} - -function atom_to_binary(atom, encoding = Symbol.for('utf8')) { - if (encoding !== Symbol.for('utf8')) { - throw new Error(`unsupported encoding ${encoding}`); - } - - if (atom.__MODULE__) { - return Symbol.keyFor(atom.__MODULE__); - } - - return Symbol.keyFor(atom); -} - -function binary_to_atom(binary, encoding = Symbol.for('utf8')) { - if (encoding !== Symbol.for('utf8')) { - throw new Error(`unsupported encoding ${encoding}`); - } - - return Symbol.for(binary); -} - -function binary_to_existing_atom(binary, encoding = Symbol.for('utf8')) { - return binary_to_atom(binary, encoding); -} - -function list_concatenation(list1, list2) { - return list1.concat(list2); -} - -function list_subtraction(list1, list2) { - const list = [...list1]; - - for (const item of list2) { - const index = list.indexOf(item); - - if (index > -1) { - list.splice(index, 1); - } - } - - return list; -} - -function div(left, right) { - return left / right; -} - -function not(x) { - return !x; -} - -function rem(left, right) { - return left % right; -} - -function band(left, right) { - return left & right; -} - -function bor(left, right) { - return left | right; -} - -function bnot(x) { - return ~x; -} - -function bsl(left, right) { - return left << right; -} - -function bsr(left, right) { - return left >> right; -} - -function bxor(left, right) { - return left ^ right; -} - -function is_atom(value) { - return typeof value === 'symbol' || value instanceof Symbol || value.__MODULE__; -} - -function is_bitstring$1(value) { - return value instanceof ErlangTypes.BitString; -} - -function is_boolean$1(value) { - return typeof value === 'boolean' || value instanceof Boolean; -} - -function is_number$1(value) { - return typeof value === 'number' || value instanceof Number; -} - -function is_float(value) { - return is_number$1(value) && !Number.isInteger(value); -} - -function is_function$1(value) { - return typeof value === 'function' || value instanceof Function; -} - -function is_integer(value) { - return Number.isInteger(value); -} - -function is_list(value) { - return Array.isArray(value); -} - -function is_map$1(value) { - return value instanceof Map; -} - -function is_pid(value) { - return value instanceof ErlangTypes.PID; -} - -function is_port() { - return false; -} - -function is_reference(value) { - return value instanceof ErlangTypes.Reference; -} - -function is_tuple(value) { - return value instanceof ErlangTypes.Tuple; -} - -function is_binary(value) { - return typeof value === 'string' || value instanceof String; -} - -function element(n, tuple) { - return tuple.get(n - 1); -} - -function setelement(index, tuple1, value) { - const tupleData = [...tuple1.values]; - - tupleData[index - 1] = value; - - return new ErlangTypes.Tuple(...tupleData); -} - -function make_tuple(arity, initialValue) { - const list = []; - - for (let i = 0; i < arity; i++) { - list.push(initialValue); - } - - return new ErlangTypes.Tuple(...list); -} - -function insert_element(index, tuple, term) { - const list = [...tuple.values]; - list.splice(index - 1, 0, term); - - return new ErlangTypes.Tuple(...list); -} - -function append_element(tuple, term) { - const list = [...tuple.values]; - list.push(term); - - return new ErlangTypes.Tuple(...list); -} - -function delete_element(index, tuple) { - const list = [...tuple.values]; - list.splice(index - 1, 1); - - return new ErlangTypes.Tuple(...list); -} - -function tuple_to_list(tuple) { - const list = [...tuple.values]; - return list; -} - -function abs(number) { - return Math.abs(number); -} - -function apply(...args) { - if (args.length === 2) { - return args[0].apply(this, ...args[1]); - } - - return args[0][atom_to_binary(args[1])].apply(this, ...args[2]); -} - -function binary_part(binary, start, _length) { - return binary.substring(start, start + _length); -} - -function bit_size(bitstring) { - return bitstring.bit_size; -} - -function byte_size(bitstring) { - return bitstring.byte_size; -} - -function hd(list) { - return list[0]; -} - -function length(list) { - return list.length; -} - -function make_ref() { - return new ErlangTypes.Reference(); -} - -function map_size(map) { - return map.size; -} - -function max(first, second) { - return Math.max(first, second); -} - -function min(first, second) { - return Math.min(first, second); -} - -function round(number) { - return Math.round(number); -} - -function tl(list) { - return list.slice(1); -} - -function trunc(number) { - return Math.trunc(number); -} - -function tuple_size(tuple) { - return tuple.length; -} - -function binary_to_float(str) { - return parseFloat(str); -} - -function binary_to_integer(str, base = 10) { - return parseInt(str, base); -} - -function process_info(pid, item) { - if (item) { - if (item === Symbol.for('current_stacktrace')) { - return new ErlangTypes.Tuple(item, []); - } - - return new ErlangTypes.Tuple(item, null); - } - - return []; -} - -function list_to_binary(iolist) { - const iolistFlattened = lists.flatten(iolist); - - const value = iolistFlattened.reduce((acc, current) => { - if (current === null) { - return acc; - } else if (is_integer(current)) { - return acc + String.fromCodePoint(current); - } else if (is_bitstring$1(current)) { - return acc + String.fromCodePoint(...current.value); - } - - return acc + current; - }, ''); - - return value; -} - -function iolist_to_binary(ioListOrBinary) { - if (ioListOrBinary === null) { - return ''; - } - - if (is_binary(ioListOrBinary)) { - return ioListOrBinary; - } - - if (is_bitstring$1(ioListOrBinary)) { - return String.fromCodePoint(...ioListOrBinary.value); - } - - if (is_number$1(ioListOrBinary)) { - return String.fromCodePoint(ioListOrBinary); - } - - const iolistFlattened = lists.flatten(ioListOrBinary); - - const value = iolistFlattened.reduce((acc, current) => { - if (current === null) { - return acc; - } else if (is_integer(current)) { - return acc + String.fromCodePoint(current); - } else if (is_bitstring$1(current)) { - return acc + String.fromCodePoint(...current.value); - } - - return acc + iolist_to_binary(current); - }, ''); - - return value; -} - -function io_size(ioListOrBinary) { - return iolist_to_binary(ioListOrBinary).length; -} - -function integer_to_binary(integer, base = 10) { - return integer.toString(base); -} - -function node() { - return Symbol.for('nonode@nohost'); -} - -function self$1() { - return selfPID; -} - -function _throw(term) { - throw term; -} - -function error(reason) { - throw new ErlangTypes.Tuple(reason, []); -} - -function exit(...args) { - if (args.length === 2) { - throw args[1]; - } else { - throw args[0]; - } -} - -function raise(_class, reason) { - if (_class === Symbol.for('throw')) { - _throw(reason); - } else if (_class === Symbol.for('error')) { - error(reason); - } else { - exit(reason); - } -} - -var erlang = { - atom_to_binary, - binary_to_atom, - binary_to_existing_atom, - list_concatenation, - list_subtraction, - div, - not, - rem, - band, - bor, - bsl, - bsr, - bxor, - bnot, - is_bitstring: is_bitstring$1, - is_boolean: is_boolean$1, - is_float, - is_function: is_function$1, - is_integer, - is_list, - is_map: is_map$1, - is_number: is_number$1, - is_pid, - is_port, - is_reference, - is_tuple, - is_atom, - is_binary, - element, - setelement, - make_tuple, - insert_element, - append_element, - delete_element, - tuple_to_list, - abs, - apply, - binary_part, - bit_size, - byte_size, - hd, - length, - make_ref, - map_size, - max, - min, - round, - tl, - trunc, - tuple_size, - binary_to_float, - binary_to_integer, - process_info, - iolist_to_binary, - io_size, - integer_to_binary, - atom_to_list, - node, - self: self$1, - throw: _throw, - error, - exit, - raise, - list_to_binary -}; - -// http://erlang.org/doc/man/maps.html -const OK = Symbol.for('ok'); -const ERROR = Symbol.for('error'); -const BADMAP = Symbol.for('badmap'); -const BADKEY = Symbol.for('badkey'); - -function find(key, map) { - if (erlang.is_map(map) === false) { - return new ErlangTypes.Tuple(BADMAP, map); - } - - const value = map.get(key); - - if (typeof value !== 'undefined') { - return new ErlangTypes.Tuple(OK, value); - } - - return ERROR; -} - -function fold(fun, init, map) { - let acc = init; - - for (const [key, value] of map.entries()) { - acc = fun(key, value, acc); - } - - return acc; -} - -function remove(key, map1) { - if (erlang.is_map(map1) === false) { - return new ErlangTypes.Tuple(BADMAP, map1); - } - - const map2 = new Map(map1); - - map2.delete(key); - - return map2; -} - -function to_list(map) { - if (erlang.is_map(map) === false) { - return new ErlangTypes.Tuple(BADMAP, map); - } - - const list = []; - - for (const [key, value] of map.entries()) { - list.push(new ErlangTypes.Tuple(key, value)); - } - - return list; -} - -function from_list(list) { - return list.reduce((acc, item) => { - const [key, value] = item; - acc.set(key, value); - - return acc; - }, new Map()); -} - -function keys(map) { - if (erlang.is_map(map) === false) { - return new ErlangTypes.Tuple(BADMAP, map); - } - - return Array.from(map.keys()); -} - -function values$1(map) { - if (erlang.is_map(map) === false) { - return new ErlangTypes.Tuple(BADMAP, map); - } - - return Array.from(map.values()); -} - -function is_key(key, map) { - return map.has(key); -} - -function put(key, value, map1) { - if (erlang.is_map(map1) === false) { - return new ErlangTypes.Tuple(BADMAP, map1); - } - - const map2 = new Map(map1); - map2.set(key, value); - - return map2; -} - -function merge(map1, map2) { - if (erlang.is_map(map1) === false) { - return new ErlangTypes.Tuple(BADMAP, map1); - } - - if (erlang.is_map(map2) === false) { - return new ErlangTypes.Tuple(BADMAP, map2); - } - - return new Map([...map1, ...map2]); -} - -function update(key, value, map1) { - if (erlang.is_map(map1) === false) { - return new ErlangTypes.Tuple(BADMAP, map1); - } - - if (is_key(key, map1) === false) { - return new ErlangTypes.Tuple(BADKEY, key); - } - - return new Map([...map1, [key, value]]); -} - -function get(...args) { - const key = args[0]; - const map = args[1]; - - if (erlang.is_map(map) === false) { - return new ErlangTypes.Tuple(BADMAP, map); - } - - if (is_key(key)) { - return map.get(key); - } - - if (args.length === 3) { - return args[2]; - } - - return new ErlangTypes.Tuple(BADKEY, key); -} - -function take(key, map1) { - if (erlang.is_map(map1) === false) { - return new ErlangTypes.Tuple(BADMAP, map1); - } - - if (!is_key(key)) { - return ERROR; - } - - const value = map1.get(key); - const map2 = new Map(map1); - map2.delete(key); - - return new ErlangTypes.Tuple(value, map2); -} - -var maps = { - find, - fold, - remove, - to_list, - from_list, - keys, - values: values$1, - is_key, - put, - merge, - update, - get, - take -}; - -function warn(message) { - const messageString = message.join(''); - console.warn(`warning: ${messageString}`); - - return Symbol.for('ok'); -} - -var elixir_errors = { - warn -}; - -const MODULE = Symbol.for('elixir_config'); -const ets = new Map(); - -function _new(opts) { - ets.set(MODULE, new Map()); - ets.get(MODULE).set(MODULE, opts); - return MODULE; -} - -function _delete(module) { - ets.delete(module); - return true; -} - -function put$1(key, value) { - ets.get(MODULE).set(key, value); - return Symbol.for('ok'); -} - -function get$1(key) { - return ets.get(MODULE).get(key); -} - -function update$1(key, fun) { - const value = fun(ets.get(MODULE).get(key)); - put$1(key, value); - return value; -} - -function get_and_put(key, value) { - const oldValue = get$1(key); - put$1(key, value); - return oldValue; -} - -var elixir_config = { - new: _new, - delete: _delete, - put: put$1, - get: get$1, - update: update$1, - get_and_put -}; - -function put_chars(ioDevice, charData) { - const dataToWrite = erlang.iolist_to_binary(charData); - - if (ioDevice === Symbol.for('stderr')) { - console.error(dataToWrite); - } else { - console.log(dataToWrite); - } - - return Symbol.for('ok'); -} - -var io = { - put_chars -}; - -function copy(subject, n = 1) { - return subject.repeat(n); -} - -function list_to_bin(bytelist) { - return erlang.list_to_binary(bytelist); -} - -var binary = { - copy, - list_to_bin -}; - -function characters_to_list(characters) { - return characters.split('').map(c => c.codePointAt(0)); -} - -function characters_to_binary(characters) { - if (erlang.is_binary(characters)) { - return characters; - } - - return String.fromCodePoint(...characters); -} - -var unicode = { - characters_to_list, - characters_to_binary -}; - -function get_key(key) { - let real_key = key; - - if (__elixirscript_names__.has(key)) { - real_key = __elixirscript_names__.get(key); - } - - if (__elixirscript_store__.has(real_key)) { - return real_key; - } - - throw new Error(`Key ${real_key} not found`); -} - -function create(value, name = null) { - const key = new Core.PID(); - - if (name !== null) { - __elixirscript_names__.set(name, key); - } - - return __elixirscript_store__.set(key, value); -} - -function update$2(key, value) { - const real_key = get_key(key); - return __elixirscript_store__.set(real_key, value); -} - -function read(key) { - const real_key = get_key(key); - return __elixirscript_store__.get(real_key); -} - -function remove$1(key) { - const real_key = get_key(key); - return __elixirscript_store__.delete(real_key); -} - -var Store = { - create, - update: update$2, - read, - remove: remove$1 -}; - -class Integer {} -class Float {} - -function get_global() { - if (typeof self !== 'undefined') { - return self; - } else if (typeof window !== 'undefined') { - return window; - } else if (typeof global !== 'undefined') { - return global; - } - - console.warn('No global state found'); - return null; -} - -const globalState = get_global(); - -globalState.__elixirscript_store__ = new Map(); -globalState.__elixirscript_names__ = new Map(); - -var Core = { - Tuple: ErlangTypes.Tuple, - PID: ErlangTypes.PID, - BitString: ErlangTypes.BitString, - Patterns, - Integer, - Float, - Functions, - SpecialForms, - Store, - global: globalState, - erlang, - maps, - lists, - elixir_errors, - io, - binary, - unicode, - elixir_config -}; - -var elixir = { - Core -}; - -return elixir; - -}()); +var ElixirScript=function(){'use strict';/* @flow */function namedVariableResult(a,b){return new NamedVariableResult(a,b)}/* @flow */function is_number(a){return'number'==typeof a}function is_string(a){return'string'==typeof a}function is_boolean(a){return'boolean'==typeof a}function is_symbol(a){return'symbol'==typeof a}function is_object(a){return'object'==typeof a}function is_variable(a){return a instanceof Variable}function is_null(a){return null===a}function is_array(a){return Array.isArray(a)}function is_function(a){return'[object Function]'==Object.prototype.toString.call(a)}function is_map(a){return a instanceof Map}function resolveNull(){return function(a){return is_null(a)}}function resolveWildcard(){return function(){return!0}}function resolveObject(a){let b={};const c=Object.keys(a).concat(Object.getOwnPropertySymbols(a));for(let d of c)b[d]=buildMatch(a[d]);return function(d,e){if(!is_object(d)||a.length>d.length)return!1;for(let a of c)if(!(a in d)||!b[a](d[a],e))return!1;return!0}}function getSize(a,b){return a*b/8}function arraysEqual(c,a){if(c===a)return!0;if(null==c||null==a)return!1;if(c.length!=a.length)return!1;for(var b=0;bf.integer(a));return new f(...b)}function resolveNoMatch(){return function(){return!1}}function buildMatch(a){if(null===a)return resolveNull(a);if('undefined'==typeof a)return resolveWildcard(a);const b=a.constructor.prototype,c=g.get(b);return c?c(a):'object'==typeof a?resolveObject(a):resolveNoMatch()}function defmatchgen(...a){const b=getArityMap(a);return function*(...a){let[c,d]=findMatchingFunction(a,b);return yield*c.apply(this,d)}}function findMatchingFunction(a,b){if(b.has(a.length)){const c=b.get(a.length);let d=null,e=null;for(let b of c){let c=[];a=fillInOptionalValues(a,b.arity,b.optionals);const f=b.pattern(a,c),[g,h]=checkNamedVariables(c);if(f&&h&&b.guard.apply(this,g)){d=b.fn,e=g;break}}if(!d)throw console.error('No match for:',a),new MatchError(a);return[d,e]}throw console.error('Arity of',a.length,'not found. No match for:',a),new MatchError(a)}function getArityMap(a){let b=new Map;for(const c of a){const a=getArityRange(c);for(const d of a){let a=[];b.has(d)&&(a=b.get(d)),a.push(c),b.set(d,a)}}return b}function getArityRange(a){const b=a.arity-a.optionals.length,c=a.arity;let d=[b];for(;d[d.length-1]!=c;)d.push(d[d.length-1]+1);return d}function getOptionalValues(a){let b=[];for(let c=0;c!0,d=null){let e=[],f=buildMatch(a);const g=f(b,e),[h,i]=checkNamedVariables(e);return g&&i&&c.apply(this,h)?h:d}function run_generators(a,b){if(0==b.length)return a.map((a)=>{return Array.isArray(a)?a:[a]});const c=b.pop();let d=[];for(let e of c())for(let b of a)d.push([e].concat(b));return run_generators(d,b)}function iterator_to_reducer(a,b,c){const d=a[Symbol.iterator]();let e=d.next(),f=b;for(;!1===e.done;){if(f=c(e.value,f.get(1)),f.get(0)===Symbol.for('halt'))return new s.Tuple(Symbol.for('halted'),f.get(1));if(f.get(0)===Symbol.for('suspend'))return new s.Tuple(Symbol.for('suspended'),f.get(1),(a)=>{return iterator_to_reducer(d,a,c)});e=d.next()}return new s.Tuple(Symbol.for('done'),f.get(1))}function map_to_object(a){const b={};for(const[c,d]of a.entries())b[c]=d instanceof Map?map_to_object(d):d;return b}function run_list_generators(a,b){if(0==b.length)return a.map((a)=>{return Array.isArray(a)?a:[a]});const c=b.pop(),d=[];for(const e of c())for(const b of a)d.push([e].concat(b));return run_list_generators(d,b)}// http://erlang.org/doc/man/lists.html +function reverse(a){return[...a]}function flatten(a,b=[]){const c=a.reduce((a,b)=>{return Array.isArray(b)?a.concat(flatten(b)):a.concat(b)},[]);return c.concat(b)}function foldl(a,b,c){return c.reduce((b,c)=>{return a(c,b)},b)}function keyfind(a,b,c){for(const d of c)if(d.get(b-1)===a)return d;return!1}function keydelete(a,b,c){const d=[];let e=!1;for(let f=0;f{if(null===c)return b;return is_integer(c)?b+a(c):is_bitstring$1(c)?b+a(...c.value):b+iolist_to_binary(c)},'');return d}function _throw(a){throw a}function error(a){throw new e.Tuple(a,[])}function exit(...a){if(2===a.length)throw a[1];else throw a[0]}function is_key(a,b){return b.has(a)}function put$1(a,b){return q.get(p).set(a,b),Symbol.for('ok')}function get$1(a){return q.get(p).get(a)}function get_key(a){let b=a;if(__elixirscript_names__.has(a)&&(b=__elixirscript_names__.get(a)),__elixirscript_store__.has(b))return b;throw new Error(`Key ${b} not found`)}var a=String.fromCodePoint,b=Number.isInteger;class Variable{constructor(a=null,b=Symbol.for('tailored.no_value')){this.name=a,this.default_value=b}}class Wildcard{constructor(){}}class StartsWith{constructor(a){this.prefix=a}}class Capture{constructor(a){this.value=a}}class HeadTail{constructor(a,b){this.head=a,this.tail=b}}class Type{constructor(a,b={}){this.type=a,this.objPattern=b}}class Bound{constructor(a){this.value=a}}class BitStringMatch{constructor(...a){this.values=a}length(){return values.length}bit_size(){return 8*this.byte_size()}byte_size(){let a=0;for(let b of this.values)a+=b.unit*b.size/8;return a}getValue(a){return this.values(a)}getSizeOfValue(a){let b=this.getValue(a);return b.unit*b.size}getTypeOfValue(a){return this.getValue(a).type}}class NamedVariableResult{constructor(a,b){this.name=a,this.value=b}}class Tuple{constructor(...a){this.values=Object.freeze(a),this.length=this.values.length}get(a){return this.values[a]}count(){return this.values.length}[Symbol.iterator](){return this.values[Symbol.iterator]()}toString(){let a,b='';for(a=0;aBitString$1.integer(a));return new BitString$1(...d)}[Symbol.iterator](){return this.value[Symbol.iterator]()}toString(){var a,b='';for(a=0;a>'}process(a){let b=[];var c;for(c=0;cb?c.push(b):2048>b?c.push(192|b>>6,128|63&b):55296>b||57344<=b?c.push(224|b>>12,128|63&b>>6,128|63&b):(d++,b=65536+((1023&b)<<10|1023&a.charCodeAt(d)),c.push(240|b>>18,128|63&b>>12,128|63&b>>6,128|63&b));return c}static toUTF16Array(a){for(var b,c=[],d=0;d=b?(c.push(0),c.push(b)):(c.push(255&b>>8),c.push(255&b));return c}static toUTF32Array(a){for(var b,c=[],d=0;d=b?(c.push(0),c.push(0),c.push(0),c.push(b)):(c.push(0),c.push(0),c.push(255&b>>8),c.push(255&b));return c}//http://stackoverflow.com/questions/2003493/javascript-float-from-to-bits +static float32ToBytes(a){var b=[],c=new ArrayBuffer(4);new Float32Array(c)[0]=a;let d=new Uint32Array(c)[0];return b.push(255&d>>24),b.push(255&d>>16),b.push(255&d>>8),b.push(255&d),b}static float64ToBytes(a){var b=[],c=new ArrayBuffer(8);new Float64Array(c)[0]=a;var d=new Uint32Array(c)[0],e=new Uint32Array(c)[1];return b.push(255&e>>24),b.push(255&e>>16),b.push(255&e>>8),b.push(255&e),b.push(255&d>>24),b.push(255&d>>16),b.push(255&d>>8),b.push(255&d),b}}var e={Tuple,PID:class PID{constructor(){++c,this.id=c}toString(){return'PID#<0.'+this.id+'.0>'}},Reference:class Reference{constructor(){++d,this.id=d,this.ref=Symbol()}toString(){return'Ref#<0.0.0.'+this.id+'>'}},BitString:BitString$1};/* @flow */const f=e.BitString,g=new Map;g.set(Variable.prototype,function resolveVariable(a){return function(b,c){return null===a.name?c.push(b):!a.name.startsWith('_')&&c.push(namedVariableResult(a.name,b)),!0}}),g.set(Wildcard.prototype,resolveWildcard),g.set(HeadTail.prototype,function resolveHeadTail(a){const b=buildMatch(a.head),c=buildMatch(a.tail);return function(a,d){if(!is_array(a)||0===a.length)return!1;const e=a[0],f=a.slice(1);return b(e,d)&&c(f,d)}}),g.set(StartsWith.prototype,function resolveStartsWith(a){const b=a.prefix;return function(a,c){return is_string(a)&&a.startsWith(b)&&(c.push(a.substring(b.length)),!0)}}),g.set(Capture.prototype,function resolveCapture(a){const b=buildMatch(a.value);return function(a,c){return!!b(a,c)&&(c.push(a),!0)}}),g.set(Bound.prototype,function resolveBound(a){return function(b){return typeof b==typeof a.value&&b===a.value}}),g.set(Type.prototype,function resolveType(a){return function(b,c){if(b instanceof a.type){const d=buildMatch(a.objPattern);return d(b,c)}return!1}}),g.set(BitStringMatch.prototype,function resolveBitString(a){let b=[];for(let c of a.values)if(is_variable(c.value)){let a=getSize(c.unit,c.size);fillArray(b,a)}else b=b.concat(new f(c).value);let c=a.values;return function(a,d){var e=String.fromCharCode;let g=null;if(!is_string(a)&&!(a instanceof f))return!1;g=is_string(a)?new f(f.binary(a)):a;let h=0;for(let f,j=0;jd.size)return!1;for(let a of c)if(!d.has(a)||!b.get(a)(d.get(a),e))return!1;return!0}}),g.set(Array.prototype,function resolveArray(a){const b=a.map((a)=>buildMatch(a));return function(c,d){return is_array(c)&&c.length==a.length&&c.every(function(a,e){return b[e](c[e],d)})}}),g.set(String.prototype,function resolveString(a){return function(b){return is_string(b)&&b===a}}),g.set(Boolean.prototype,function resolveBoolean(a){return function(b){return is_boolean(b)&&b===a}}),g.set(Function.prototype,function resolveFunction(a){return function(b){return is_function(b)&&b===a}}),g.set(Object.prototype,resolveObject);class MatchError extends Error{constructor(a){if(super(),'symbol'==typeof a)this.message='No match for: '+a.toString();else if(Array.isArray(a)){let b=a.map((a)=>{return null===a?'null':'undefined'==typeof a?'undefined':a.toString()});this.message='No match for: '+b}else this.message='No match for: '+a;this.stack=new Error().stack,this.name=this.constructor.name}}class Clause{constructor(a,b,c=()=>!0){this.pattern=buildMatch(a),this.arity=a.length,this.optionals=getOptionalValues(a),this.fn=b,this.guard=c}}const h=Symbol();// https://github.com/airportyh/protomorphism +class Protocol{constructor(a){function createFun(a){return function(...c){const d=c[0];let e=null;if(null===d&&this.hasImplementation(Symbol('null'))?e=this.registry.get(Symbol)[a]:b(d)&&this.hasImplementation(s.Integer)?e=this.registry.get(s.Integer)[a]:'number'==typeof d&&!b(d)&&this.hasImplementation(s.Float)?e=this.registry.get(s.Float)[a]:'string'==typeof d&&this.hasImplementation(s.BitString)?e=this.registry.get(s.BitString)[a]:d&&d instanceof Map&&d.has(Symbol.for('__struct__'))&&this.hasImplementation(d)?e=this.registry.get(d.get(Symbol.for('__struct__')).__MODULE__)[a]:null!==d&&this.hasImplementation(d)?e=this.registry.get(d.constructor)[a]:this.fallback&&(e=this.fallback[a]),null!=e){const a=e.apply(this,c);return a}throw new Error(`No implementation found for ${d}`)}}for(const b in this.registry=new Map,this.fallback=null,a)this[b]=createFun(b).bind(this)}implementation(a,b){null===a?this.fallback=b:this.registry.set(a,b)}hasImplementation(a){if(a===s.Integer||a===s.Float||a===s.BitString)return this.registry.has(a);return a&&a instanceof Map&&a.has(Symbol.for('__struct__'))?this.registry.has(a.get(Symbol.for('__struct__')).__MODULE__):this.registry.has(a.constructor)}}class Recurse{constructor(a){this.func=a}}var i={reverse,foreach:function foreach(a,b){return b.forEach((b)=>a(b)),Symbol.for('ok')},duplicate:function duplicate(a,b){const c=[];for(;c.length{if(d.get(c-1)a.get(c-1)?1:0})},keystore:function keystore(a,b,c,d){const e=[...c];for(let f=0;fa.toString()).join()},map:function map(a,b){return b.map((b)=>a(b))},filter:function filter(a,b){return b.filter((b)=>a(b))},filtermap:function filtermap(a,b){const c=[];for(const d of b){const b=a(d);!0===b?c.push(d):b instanceof e.Tuple&&!0===b.get(0)&&c.push(b.get(1))}return c},member:function member(a,b){for(const c of b)if(c===a)return!0;return!1},all:function all(a,b){for(const c of b)if(!1===a(c))return!1;return!0},any:function any(a,b){for(const c of b)if(!0===a(c))return!0;return!1},splitwith:function splitwith(a,b){let c=!1;const d=[],f=[];for(const e of b)!0==c?f.push(e):!0===a(e)?d.push(e):(c=!0,f.push(e));return new e.Tuple(d,f)},sort:function sort(...a){if(1===a.length){const b=[...a[0]];return b.sort()}const c=a[0],b=[...a[1]];return b.sort((d,a)=>{const b=c(d,a);return!0===b?-1:1})}};// http://erlang.org/doc/man/erlang.html +const j=new e.PID;var k={atom_to_binary,binary_to_atom,binary_to_existing_atom:function binary_to_existing_atom(a,b=Symbol.for('utf8')){return binary_to_atom(a,b)},list_concatenation:function list_concatenation(a,b){return a.concat(b)},list_subtraction:function list_subtraction(a,b){const c=[...a];for(const d of b){const a=c.indexOf(d);-1>b},bxor:function bxor(a,b){return a^b},bnot:function bnot(a){return~a},is_bitstring:is_bitstring$1,is_boolean:function is_boolean$1(a){return'boolean'==typeof a||a instanceof Boolean},is_float:function is_float(a){return is_number$1(a)&&!b(a)},is_function:function is_function$1(a){return'function'==typeof a||a instanceof Function},is_integer,is_list:function is_list(a){return Array.isArray(a)},is_map:function is_map$1(a){return a instanceof Map},is_number:is_number$1,is_pid:function is_pid(a){return a instanceof e.PID},is_port:function is_port(){return!1},is_reference:function is_reference(a){return a instanceof e.Reference},is_tuple:function is_tuple(a){return a instanceof e.Tuple},is_atom:function is_atom(a){return'symbol'==typeof a||a instanceof Symbol||a.__MODULE__},is_binary,element:function element(a,b){return b.get(a-1)},setelement:function setelement(a,b,c){const d=[...b.values];return d[a-1]=c,new e.Tuple(...d)},make_tuple:function make_tuple(a,b){const c=[];for(let d=0;d{if(null===c)return b;return is_integer(c)?b+a(c):is_bitstring$1(c)?b+a(...c.value):b+c},'');return d}};// http://erlang.org/doc/man/maps.html +const l=Symbol.for('ok'),m=Symbol.for('error'),n=Symbol.for('badmap'),o=Symbol.for('badkey');const p=Symbol.for('elixir_config'),q=new Map;const r=function get_global(){return'undefined'==typeof self?'undefined'==typeof window?'undefined'==typeof global?(console.warn('No global state found'),null):global:window:self}();r.__elixirscript_store__=new Map,r.__elixirscript_names__=new Map;var s={Tuple:e.Tuple,PID:e.PID,BitString:e.BitString,Patterns:{defmatch:function defmatch(...a){const b=getArityMap(a);return function(...a){let[c,d]=findMatchingFunction(a,b);return c.apply(this,d)}},match:function match(a,b,c=()=>!0){let d=[],e=buildMatch(a);const f=e(b,d),[g,h]=checkNamedVariables(d);if(f&&h&&c.apply(this,g))return g;throw console.error('No match for:',b),new MatchError(b)},MatchError,variable:function variable(a=null,b=Symbol.for('tailored.no_value')){return new Variable(a,b)},wildcard:function wildcard(){return new Wildcard},startsWith:function startsWith(a){return new StartsWith(a)},capture:function capture(a){return new Capture(a)},headTail:function headTail(a,b){return new HeadTail(a,b)},type:function a(a,b={}){return new Type(a,b)},bound:function bound(a){return new Bound(a)},Clause,clause:function clause(a,b,c=()=>!0){return new Clause(a,b,c)},bitStringMatch:function bitStringMatch(...a){return new BitStringMatch(...a)},match_or_default,defmatchgen,list_comprehension:function list_comprehension(a,b){const c=run_generators(b.pop()(),b);let d=[];for(let e of c)a.guard.apply(this,e)&&d.push(a.fn.apply(this,e));return d},list_generator:function list_generator(a,b){return function(){let c=[];for(let d of b){const b=match_or_default(a,d,()=>!0,h);if(b!=h){const[a]=b;c.push(a)}}return c}},bitstring_generator:function bitstring_generator(a,b){return function(){let c=[],d=b.slice(0,a.byte_size()),e=1;for(;d.byte_size==a.byte_size();){const f=match_or_default(a,d,()=>!0,h);if(f!=h){c.push(f)}d=b.slice(a.byte_size()*e,a.byte_size()*(e+1)),e++}return c}},bitstring_comprehension:function bitstring_comprehension(a,b){const c=run_generators(b.pop()(),b);let d=[];for(let e of c)a.guard.apply(this,e)&&d.push(a.fn.apply(this,e));return d=d.map((a)=>e.BitString.integer(a)),new e.BitString(...d)},defmatchGen:function defmatchGen(...a){return defmatchgen(...a)},defmatchAsync:function defmatchAsync(...a){const b=getArityMap(a);return async function(...a){if(b.has(a.length)){const c=b.get(a.length);let d=null,e=null;for(let b of c){let c=[];a=fillInOptionalValues(a,b.arity,b.optionals);const f=b.pattern(a,c),[g,h]=checkNamedVariables(c);if(f&&h&&(await b.guard.apply(this,c))){d=b.fn,e=c;break}}if(!d)throw console.error('No match for:',a),new MatchError(a);return d.apply(this,e)}throw console.error('Arity of',a.length,'not found. No match for:',a),new MatchError(a)}}},Integer:class Integer{},Float:class Float{},Functions:{call_property:function call_property(a,b){if(!b)return a instanceof Function||'function'==typeof a?a():a;if(a instanceof Map){let c=null;if(a.has(b)?c=b:a.has(Symbol.for(b))&&(c=Symbol.for(b)),null===c)throw new Error(`Property ${b} not found in ${a}`);return a.get(c)instanceof Function||'function'==typeof a.get(c)?a.get(c)():a.get(c)}let c=null;if('number'==typeof a||'symbol'==typeof a||'boolean'==typeof a||'string'==typeof a?void 0===a[b]?void 0!==a[Symbol.for(b)]&&(c=Symbol.for(b)):c=b:b in a?c=b:Symbol.for(b)in a&&(c=Symbol.for(b)),null===c)throw new Error(`Property ${b} not found in ${a}`);return a[c]instanceof Function||'function'==typeof a[c]?a[c]():a[c]},defprotocol:function defprotocol(a){return new Protocol(a)},defimpl:function defimpl(a,b,c){a.implementation(b,c)},build_namespace:function build_namespace(a,b){let c=b.split('.');const d=a;let e=a;'Elixir'===c[0]&&(c=c.slice(1));for(const d of c)'undefined'==typeof e[d]&&(e[d]={}),e=e[d];return d.__table__=a.__table__||{},d.__table__[Symbol.for(b)]=e,e},iterator_to_reducer,map_to_object,trampoline:function trampoline$1(a){let b=a;for(;b&&b instanceof Recurse;)b=b.func();return b},Recurse},SpecialForms:{_case:function _case(a,b){return s.Patterns.defmatch(...b)(a)},cond:function cond(...a){for(const b of a)if(b[0])return b[1]();throw new Error},_for:function _for(a,b,c,d=[]){let[e,f]=c.into(d);const g=run_list_generators(b.pop()(),b);for(const h of g)a.guard.apply(this,h)&&(e=f(e,new s.Tuple(Symbol.for('cont'),a.fn.apply(this,h))));return f(e,Symbol.for('done'))},_try:function _try(a,b,c,d,e){let f=null;try{f=a()}catch(a){let d=null;if(b)try{return d=b(a),d}catch(a){if(a instanceof s.Patterns.MatchError)throw a}if(c)try{return d=c(a),d}catch(a){if(a instanceof s.Patterns.MatchError)throw a}throw a}finally{e&&e()}if(d)try{return d(f)}catch(a){if(a instanceof s.Patterns.MatchError)throw new Error('No Match Found in Else');throw a}else return f},_with:function _with(...a){let b=[],c=null,d=null;'function'==typeof a[a.length-2]?[c,d]=a.splice(-2):c=a.pop();for(let c=0;c{const[c,d]=b;return a.set(c,d),a},new Map)},keys:function keys(a){return!1===k.is_map(a)?new e.Tuple(n,a):Array.from(a.keys())},values:function values$1(a){return!1===k.is_map(a)?new e.Tuple(n,a):Array.from(a.values())},is_key,put:function put(a,b,c){if(!1===k.is_map(c))return new e.Tuple(n,c);const d=new Map(c);return d.set(a,b),d},merge:function merge(a,b){return!1===k.is_map(a)?new e.Tuple(n,a):!1===k.is_map(b)?new e.Tuple(n,b):new Map([...a,...b])},update:function update(a,b,c){return!1===k.is_map(c)?new e.Tuple(n,c):!1===is_key(a,c)?new e.Tuple(o,a):new Map([...c,[a,b]])},get:function get(...a){const b=a[0],c=a[1];return!1===k.is_map(c)?new e.Tuple(n,c):is_key(b)?c.get(b):3===a.length?a[2]:new e.Tuple(o,b)},take:function take(a,b){if(!1===k.is_map(b))return new e.Tuple(n,b);if(!is_key(a))return m;const c=b.get(a),d=new Map(b);return d.delete(a),new e.Tuple(c,d)}},lists:i,elixir_errors:{warn:function warn(a){const b=a.join('');return console.warn(`warning: ${b}`),Symbol.for('ok')}},io:{put_chars:function put_chars(a,b){const c=k.iolist_to_binary(b);return a===Symbol.for('stderr')?console.error(c):console.log(c),Symbol.for('ok')}},binary:{copy:function copy(a,b=1){return a.repeat(b)},list_to_bin:function list_to_bin(a){return k.list_to_binary(a)}},unicode:{characters_to_list:function characters_to_list(a){return a.split('').map((a)=>a.codePointAt(0))},characters_to_binary:function characters_to_binary(b){return k.is_binary(b)?b:a(...b)}},elixir_config:{new:function _new(a){return q.set(p,new Map),q.get(p).set(p,a),p},delete:function _delete(a){return q.delete(a),!0},put:put$1,get:get$1,update:function update$1(a,b){const c=b(q.get(p).get(a));return put$1(a,c),c},get_and_put:function get_and_put(a,b){const c=get$1(a);return put$1(a,b),c}}};return{Core:s}}(); From 83be891c1255af520d8d1aa5b53228381ff49f03 Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Fri, 4 Aug 2017 21:04:15 -0500 Subject: [PATCH 651/860] Add more text about global FFI --- lib/elixir_script/ffi.ex | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/lib/elixir_script/ffi.ex b/lib/elixir_script/ffi.ex index 8c94f78f..68249c14 100644 --- a/lib/elixir_script/ffi.ex +++ b/lib/elixir_script/ffi.ex @@ -36,6 +36,31 @@ defmodule ElixirScript.FFI do function in the global scope. * `name`: Only applicable with `global` is set to `true`. This will use the name defined here instead of the module name for calling modules and functions in the global scope + + An example using the global option to reference the JSON module in browsers + + ```elixir + defmodule JSON do + use ElixirScript.FFI, global: true + + defexternal stringify(map) + defexternal parse(string) + end + ``` + + The calls above are translated to calls to the `JSON` module in the global scope + + An example using global and name options + + ```elixir + defmodule Console do + use ElixirScript.FFI, global: true, name: :console + + defexternal log(term) + end + ``` + + With the above, calls in ElixirScript to `Console.log` will translate to `console.log` in JavaScript """ defmacro __using__(opts) do From 93dca72233fe9316c6fbf0c5758c75dac2ca29e1 Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Sat, 5 Aug 2017 21:21:30 -0500 Subject: [PATCH 652/860] Remove support for CommonJS and UMD modules output ElixirScript now only supports ES Modules. The default output path has also been changed. --- CHANGELOG.md | 7 +- GettingStarted.md | 30 +++--- lib/elixir_script/cli.ex | 10 +- lib/elixir_script/compiler.ex | 16 +--- lib/elixir_script/module_systems/common.ex | 50 ---------- lib/elixir_script/module_systems/umd.ex | 106 --------------------- lib/mix/tasks/compile.elixir_script.ex | 13 +-- mix.exs | 2 +- package.json | 6 +- test/app/spec/main.spec.js | 4 +- test/cli_test.exs | 6 +- test/compiler_test.exs | 14 +-- 12 files changed, 37 insertions(+), 227 deletions(-) delete mode 100644 lib/elixir_script/module_systems/common.ex delete mode 100644 lib/elixir_script/module_systems/umd.ex diff --git a/CHANGELOG.md b/CHANGELOG.md index 38eb4911..ea9c0319 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,13 +7,18 @@ and this project adheres to [Semantic Versioning](http://semver.org/). ## [Unreleased] ### Added -- ElixirScript now has an FFI layer for interoperability with JavaScript. For more details, see documentation at `ElixirScript.FFI` +- ElixirScript now has a Foreign Function Interface (FFI) for interoperability with JavaScript. For more details, see documentation at `ElixirScript.FFI` - `ElixirScript.JS.mutate/3` - `ElixirScript.JS.map_to_object/1` ### Changed - Compiler has been completely rewritten. ElixirScript now requires Erlang 20+ and Elixir 1.5+ - `JS` module renamed to `ElixirScript.JS` +- Default output path is now `priv/elixir_script/build` + +### Removed +- Support for CommonJS and UMD output formats has been removed. Output will be in ES module format +- The `js_modules` option has been removed in favor of the new FFI ## [0.28.0] - 2017-06-11 diff --git a/GettingStarted.md b/GettingStarted.md index 2026231f..6381548f 100644 --- a/GettingStarted.md +++ b/GettingStarted.md @@ -7,11 +7,11 @@ Adding Elixirscript to your mix project gives you the ability to add it to your Add dependency to your deps in mix.exs: ``` elixir -{:elixir_script, "~> 0.29"} +{:elixir_script, "~> 0.30"} ``` Elixirscript uses default output and module formats if options are not given. If you wish to change any or all options, add an `elixir_script` key to your project configuration. - + ``` elixir def project do [ @@ -21,13 +21,7 @@ Elixirscript uses default output and module formats if options are not given. If deps: deps, elixir_script: [ input: MyEntryModule, - output: "priv/elixirscript/Elixir.App.js", - format: :es, - js_modules: [ - {React, "react"}, - {ReactDOM, "react-dom"}, - {Phoenix, "phoenix", default: false} - ] + output: "priv/elixir_script/build/Elixir.App.js" ], compilers: Mix.compilers ++ [:elixir_script] ] @@ -38,22 +32,24 @@ Available options are: * `input`: The entry module(s) for your application or library -* `output`: The path of the generated JavaScript file. (defaults to `priv/elixirscript`) +* `output`: The path of the generated JavaScript file. (defaults to `priv/elixir_script/build`) If path ends in `.js` then that will be the name of the file. If a directory is given, file will be named `Elixir.App.js` -* `format`: The module format of generated JavaScript code. (defaults to `:es`). Choices are:     - - * `:es` - ES Modules - * `:common` - CommonJS +Now run `mix compile` and you should see a JavaScript file named `Elixir.App.js` in the `priv/elixir_script/build/` directory. ElixirScript outputs JavaScript in the ES Module format. If your browser supports it, you can include the output in a script tag with the type "module" - * `:umd` - UMD +```html + +``` - * `default` - Defaults to true. Set to false if the imported module has no default export. +If your browser does not yet support ES modules directly, use a tool such as [webpack](https://webpack.js.org/) or [brunch](http://brunch.io/) to convert it into something that can be used in the browser ### Macros diff --git a/lib/elixir_script/cli.ex b/lib/elixir_script/cli.ex index 79ffcd80..70475e2d 100644 --- a/lib/elixir_script/cli.ex +++ b/lib/elixir_script/cli.ex @@ -7,15 +7,13 @@ defmodule ElixirScript.CLI do output: :string, help: :boolean, version: :boolean, - watch: :boolean, - format: :string + watch: :boolean ] @aliases [ o: :output, h: :help, - v: :version, - f: :format + v: :version ] def parse_args(args) do @@ -42,7 +40,6 @@ defmodule ElixirScript.CLI do the entry module of your application options: - -f --format [format] module format of output. options: es (default), common, umd -o --output [path] places output at the given path. Can be a directory or filename. -v --version the current version number @@ -70,8 +67,7 @@ defmodule ElixirScript.CLI do {watch, options} = Keyword.pop(options, :watch, false) compile_opts = [ - output: Keyword.get(options, :output, :stdout), - format: String.to_atom(Keyword.get(options, :format, "es")) + output: Keyword.get(options, :output, :stdout) ] input = handle_input(input) diff --git a/lib/elixir_script/compiler.ex b/lib/elixir_script/compiler.ex index 24f9bdc9..75499921 100644 --- a/lib/elixir_script/compiler.ex +++ b/lib/elixir_script/compiler.ex @@ -34,22 +34,10 @@ defmodule ElixirScript.Compiler do defp build_compiler_options(opts, entry_modules) do default_options = Map.new |> Map.put(:output, Keyword.get(opts, :output)) - |> Map.put(:format, Keyword.get(opts, :format, :es)) + |> Map.put(:format, :es) |> Map.put(:entry_modules, entry_modules) options = default_options - Map.put(options, :module_formatter, get_module_formatter(options[:format])) - end - - defp get_module_formatter(:umd) do - ElixirScript.ModuleSystems.UMD - end - - defp get_module_formatter(:common) do - ElixirScript.ModuleSystems.Common - end - - defp get_module_formatter(_) do - ElixirScript.ModuleSystems.ES + Map.put(options, :module_formatter, ElixirScript.ModuleSystems.ES) end end diff --git a/lib/elixir_script/module_systems/common.ex b/lib/elixir_script/module_systems/common.ex deleted file mode 100644 index 2f4da76b..00000000 --- a/lib/elixir_script/module_systems/common.ex +++ /dev/null @@ -1,50 +0,0 @@ -defmodule ElixirScript.ModuleSystems.Common do - @moduledoc false - alias ESTree.Tools.Builder, as: JS - - def build(imports, js_imports, body, exports) do - module_imports = Enum.map(imports, fn {module, path} -> import_module(module, path) end) - - imports = js_imports - |> Enum.map(fn - {_module, name, path} -> import_module(name, path) - end) - - imports = Enum.uniq(imports ++ module_imports) - - export = if is_nil(exports), do: [], else: [export_module(exports)] - imports ++ body ++ export - end - - defp import_module(name, from) do - js_module_name = JS.identifier(name) - do_import_module(js_module_name, from) - end - - defp do_import_module(ref, file_path) do - - ref_declarator = JS.variable_declarator( - ref, - JS.call_expression( - JS.identifier("require"), - [JS.literal(file_path)] - ) - ) - - JS.variable_declaration([ref_declarator], :const) - - end - - defp export_module(exported_object) do - JS.assignment_expression( - :=, - JS.member_expression( - JS.identifier("module"), - JS.identifier("exports") - ), - exported_object - ) - end - - -end diff --git a/lib/elixir_script/module_systems/umd.ex b/lib/elixir_script/module_systems/umd.ex deleted file mode 100644 index fcd30795..00000000 --- a/lib/elixir_script/module_systems/umd.ex +++ /dev/null @@ -1,106 +0,0 @@ -defmodule ElixirScript.ModuleSystems.UMD do - @moduledoc false - alias ESTree.Tools.Builder, as: JS - - def build(imports, js_imports, body, exports) do - module_imports = Enum.map(imports, fn - {module, path} -> import_module(module, path) - end) - - imports = js_imports - |> Enum.map(fn - {_module, name, path} -> import_module(name, path) - end) - - imports = Enum.uniq(imports ++ module_imports) - - export = export_module(exports) - List.wrap(make_umd(imports, body, export)) - end - - defp import_module(module_name, from) do - js_module_name = JS.identifier(module_name) - {js_module_name, JS.literal(from)} - end - - defp export_module(exported_object) do - exported_object - end - - defp make_umd(imports, body, exports) do - import_paths = Enum.map(imports, fn({_, path}) -> path end) - import_identifiers = Enum.map(imports, fn({id, _}) -> id end) - exports = if is_nil(exports), do: [], else: [JS.return_statement(exports)] - - JS.expression_statement( - JS.call_expression( - JS.function_expression([JS.identifier("root"), JS.identifier("factory")], [], JS.block_statement([ - JS.if_statement( - JS.logical_expression( - :&&, - JS.binary_expression( - :===, - JS.unary_expression(:typeof, true, JS.identifier("define")), - JS.literal("function") - ), - JS.member_expression( - JS.identifier("define"), - JS.identifier("amd") - ) - ), - JS.block_statement([ - JS.call_expression( - JS.identifier("define"), - [JS.array_expression(import_paths), JS.identifier("factory")] - ) - ]), - JS.if_statement( - JS.binary_expression( - :===, - JS.unary_expression(:typeof, true, JS.identifier("exports")), - JS.literal("object") - ), - JS.block_statement([ - JS.assignment_expression( - :=, - JS.member_expression( - JS.identifier("module"), - JS.identifier("exports") - ), - JS.call_expression( - JS.identifier("factory"), - Enum.map(import_paths, fn x -> - JS.call_expression( - JS.identifier("require"), - [x] - ) - end) - ) - ) - ]), - JS.block_statement([ - JS.assignment_expression( - :=, - JS.member_expression( - JS.identifier("root"), - JS.identifier("Elixir") - ), - JS.call_expression( - JS.identifier("factory"), - Enum.map(import_identifiers, fn x -> - JS.member_expression( - JS.identifier("root"), - x - ) - end) - ) - ) - ]) - ) - ) - ])), - [JS.this_expression(), JS.function_expression(import_identifiers, [], JS.block_statement(body ++ exports))] - ) - ) - end -end \ No newline at end of file diff --git a/lib/mix/tasks/compile.elixir_script.ex b/lib/mix/tasks/compile.elixir_script.ex index 1e6067e2..95b9fb93 100644 --- a/lib/mix/tasks/compile.elixir_script.ex +++ b/lib/mix/tasks/compile.elixir_script.ex @@ -21,15 +21,10 @@ defmodule Mix.Tasks.Compile.ElixirScript do Available options are: * `input`: The module or modules that are the entry to your application (required) - * `output`: The path of the generated JavaScript file. (defaults to `priv/elixirscript`) + * `output`: The path of the generated JavaScript file. (defaults to `priv/elixir_script/build`) If path ends in `.js` then that will be the name of the file. If a directory is given, file will be named `Elixir.App.js` - * `format`: The module format of generated JavaScript code. (defaults to `:es`). - Choices are: - * `:es` - ES Modules - * `:common` - CommonJS - * `:umd` - UMD The mix compiler will also compile any dependencies that have the elixirscript compiler in its mix compilers as well """ @@ -64,8 +59,7 @@ defmodule Mix.Tasks.Compile.ElixirScript do elixirscript_config = get_elixirscript_config() input = Keyword.fetch!(elixirscript_config, :input) opts = [ - output: Keyword.get(elixirscript_config, :output), - format: Keyword.get(elixirscript_config, :format) + output: Keyword.get(elixirscript_config, :output) ] {input, opts} @@ -87,8 +81,7 @@ defmodule Mix.Tasks.Compile.ElixirScript do defp defaults() do [ - output: "priv/elixirscript", - format: :es + output: "priv/elixir_script/build" ] end diff --git a/mix.exs b/mix.exs index 8bd543b2..3e40a7a7 100644 --- a/mix.exs +++ b/mix.exs @@ -4,7 +4,7 @@ defmodule ElixirScript.Mixfile do def project do [ app: :elixir_script, - version: "0.29.0-dev", + version: "0.30.0-dev", elixir: "~> 1.5-dev", elixirc_paths: elixirc_paths(Mix.env), deps: deps(), diff --git a/package.json b/package.json index afaa2624..22ad2649 100644 --- a/package.json +++ b/package.json @@ -12,7 +12,7 @@ "build": "rollup -c rollup.config.js", "clean": "rm -rf priv/build", "test": "nyc ava src/javascript/tests", - "build:test-app": "MIX_ENV=test mix elixirscript Main -f common -o test/app/build/", + "build:test-app": "MIX_ENV=test mix elixirscript Main -o test/app/build/", "test-app": "yarn build:test-app && NODE_ENV=test ava 'test/app/spec/**/*.spec.js'" }, "repository": { @@ -41,9 +41,7 @@ "sinon": "^2.4.1" }, "ava": { - "require": [ - "babel-register" - ], + "require": ["babel-register"], "babel": { "babelrc": true } diff --git a/test/app/spec/main.spec.js b/test/app/spec/main.spec.js index eb44ba0e..be8b70b9 100644 --- a/test/app/spec/main.spec.js +++ b/test/app/spec/main.spec.js @@ -1,7 +1,7 @@ import test from 'ava'; -const sinon = require('sinon'); +import Elixir from '../build/Elixir.App'; -const Elixir = require('../build/Elixir.App'); +const sinon = require('sinon'); test('Elixir.start:calls the modules start function', t => { const callback = sinon.spy(); diff --git a/test/cli_test.exs b/test/cli_test.exs index b08c1d93..fbf1f85f 100644 --- a/test/cli_test.exs +++ b/test/cli_test.exs @@ -3,8 +3,8 @@ defmodule ElixirScript.CLI.Test do import ExUnit.CaptureIO test "parse_args" do - {_, args} = ElixirScript.CLI.parse_args(["Atom", "--format", "umd"]) - assert args == [format: "umd"] + {_, args} = ElixirScript.CLI.parse_args(["Atom", "--output", "build"]) + assert args == [output: "build"] end test "process help" do @@ -30,4 +30,4 @@ defmodule ElixirScript.CLI.Test do ElixirScript.CLI.process({["Atom"], []}) end) =~ "export default Elixir" end -end \ No newline at end of file +end diff --git a/test/compiler_test.exs b/test/compiler_test.exs index 36e510e7..984f1846 100644 --- a/test/compiler_test.exs +++ b/test/compiler_test.exs @@ -17,21 +17,11 @@ defmodule ElixirScript.Compiler.Test do end end - test "Output format: es" do - result = ElixirScript.Compiler.compile(Atom, [format: :es, js_modules: [{React, "react"}, {ReactDOM, "react-dom", default: false}]]) + test "Output" do + result = ElixirScript.Compiler.compile(Atom, []) assert result =~ "export default Elixir" end - test "Output format: umd" do - result = ElixirScript.Compiler.compile(Atom, [format: :umd, js_modules: [{React, "react"}]]) - assert result =~ "factory" - end - - test "Output format: common" do - result = ElixirScript.Compiler.compile(Atom, [format: :common, js_modules: [{React, "react"}]]) - assert result =~ "module.exports = Elixir" - end - test "Output file with default name" do path = System.tmp_dir() From ba22c80e750b893348eb1a644ef330112b58cb01 Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Sun, 6 Aug 2017 08:54:23 -0500 Subject: [PATCH 653/860] Add root option. Keep extension for imports Root option allows for specifying the first part of imports used when importing FFI modules. The extension change is also for FFI module imports. Both are added from testing inside of Chrome when using ES modules directly. --- CHANGELOG.md | 2 ++ GettingStarted.md | 4 +++- JavascriptInterop.md | 5 +++-- lib/elixir_script/cli.ex | 7 +++++-- lib/elixir_script/compiler.ex | 1 + lib/elixir_script/passes/find_used_modules.ex | 1 + lib/elixir_script/passes/output.ex | 2 +- lib/elixir_script/passes/translate/module.ex | 15 --------------- lib/elixir_script/state.ex | 2 +- 9 files changed, 17 insertions(+), 22 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index ea9c0319..74088bab 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,6 +10,8 @@ and this project adheres to [Semantic Versioning](http://semver.org/). - ElixirScript now has a Foreign Function Interface (FFI) for interoperability with JavaScript. For more details, see documentation at `ElixirScript.FFI` - `ElixirScript.JS.mutate/3` - `ElixirScript.JS.map_to_object/1` +- `root` option for specifying the root import path for FFI JavaScript modules. Defaults to `"."` +- For imports, now keeping the `.js` extension ### Changed - Compiler has been completely rewritten. ElixirScript now requires Erlang 20+ and Elixir 1.5+ diff --git a/GettingStarted.md b/GettingStarted.md index 6381548f..5a406627 100644 --- a/GettingStarted.md +++ b/GettingStarted.md @@ -37,12 +37,14 @@ Available options are: If path ends in `.js` then that will be the name of the file. If a directory is given, file will be named `Elixir.App.js` +* `root`: Optional root for imports of FFI JavaScript modules. Defaults to `.`. If using output directly in a browser, you may want to make it something like `/js` or some uri. + Now run `mix compile` and you should see a JavaScript file named `Elixir.App.js` in the `priv/elixir_script/build/` directory. ElixirScript outputs JavaScript in the ES Module format. If your browser supports it, you can include the output in a script tag with the type "module" ```html -``` - -If your browser does not yet support ES modules directly, use a tool such as [webpack](https://webpack.js.org/) or [brunch](http://brunch.io/) to convert it into something that can be used in the browser - -### JavaScript Interop - -Check out the [JavaScript Interoperability](JavascriptInterop.html) documentation - -### Limitations - -ElixirScript does not support `receive` or any of OTP at this time. diff --git a/README.md b/README.md index b5feac14..48c528d0 100644 --- a/README.md +++ b/README.md @@ -11,7 +11,35 @@ Requirements Usage ======== -Please check the [Getting Started Guide](GettingStarted.md) for usage +Add dependency to your deps in mix.exs: + +``` elixir +{:elixir_script, "~> x.x"} +``` + +Add `elixir_script` to list of mix compilers in mix.exs +Also add `elixir_script` configuration + +```elixir + def project do + [ + app: :my_app, + # ... + # Add elixir_script as a compilter + compilers: Mix.compilers ++ [:elixir_script], + # Our elixir_script configuration + elixir_script: [ + # Entry module. Can also be a list of modules + input: MyEntryModule, + # Output path. Either a path to a js file or a directory + output: "priv/elixir_script/build/Elixir.App.js" + ] + ] + end +``` + +Run `mix compile` + Examples ========== diff --git a/lib/elixir_script.ex b/lib/elixir_script.ex index d69317d6..618282f8 100644 --- a/lib/elixir_script.ex +++ b/lib/elixir_script.ex @@ -1,3 +1,71 @@ defmodule ElixirScript do - @moduledoc false + @moduledoc """ + + ElixirScript acts as a mix compiler. This means that when you execute `mix compile`, + ElixirScript's compiler will run as well. Make sure to add ElixirScript to your + list of compilers in mix.exs. + + ElixirScript must be told which modules to use as the entry to your ElixirScript application. + This is done by adding an `elixir_script` key to your project configuration whose value is a keyword list of options. + Add an `input` key and make the value either the name of a module or a list of modules + that are the entry modules you wish to compile to JavaScript. ElixirScript will use + those modules to find what other modules and functions it needs to convert to JavaScript. + ElixirScript by default places output in `priv/elixir_script/build`. If you wish to change this, + add an `output` key to your ElixirScript configuration. + + An example configuration for a project is shown below + + ``` elixir + def project do + [ + app: :my_app, + version: "0.1.0", + elixir: "~> 1.0", + deps: deps, + # Add elixir_script as a compilter + compilers: Mix.compilers ++ [:elixir_script], + # Our elixir_script configuration + elixir_script: [ + # Entry module. Can also be a list of modules + input: MyEntryModule, + # Output path. Either a path to a js file or a directory + output: "priv/elixir_script/build/Elixir.App.js" + ] + ] + end + ``` + + Available options are: + + * `input` (required): The entry module(s) for your application or library + + * `output`: The path of the generated JavaScript file. (defaults to `priv/elixir_script/build`) + + If path ends in `.js` then that will be the name of the file. If a directory is given, + file will be named `Elixir.App.js` + + * `root`: Optional root for imports of FFI JavaScript modules. Defaults to `.`. If using output directly in a browser, you may want to make it something like `/js` or some uri. + + + Now run `mix compile` and you should see a JavaScript file named `Elixir.App.js` in the `priv/elixir_script/build/` directory. ElixirScript outputs JavaScript in the ES Module format. If your browser supports it, you can include the output in a script tag with the type "module" + + ```html + + ``` + + If your browser does not yet support ES modules directly, use a tool such as [webpack](https://webpack.js.org/) or [brunch](http://brunch.io/) to convert it into something that can be used in the browser + + ### JavaScript Interop + + Check out the [JavaScript Interoperability](JavascriptInterop.html) documentation + + ### Limitations + + ElixirScript does not support `receive` or any of OTP at this time. + """ end diff --git a/mix.exs b/mix.exs index 3e40a7a7..6cd8af58 100644 --- a/mix.exs +++ b/mix.exs @@ -14,7 +14,8 @@ defmodule ElixirScript.Mixfile do aliases: aliases(), test_coverage: [tool: ExCoveralls], docs: [ - extras: ["GettingStarted.md", "JavaScriptInterop.md"] + main: "ElixirScript", + extras: ["JavaScriptInterop.md"] ] ] end From 2f2c48d77182a2f4531aa3b57005cd2a0594ff63 Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Tue, 8 Aug 2017 16:57:22 -0500 Subject: [PATCH 661/860] Add example to readme --- README.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/README.md b/README.md index 48c528d0..8565d6d3 100644 --- a/README.md +++ b/README.md @@ -44,8 +44,11 @@ Run `mix compile` Examples ========== +### Application [ElixirScript Todo Example](https://github.com/elixirscript/todo-elixirscript) +### Library +[ElixirScript React](https://github.com/elixirscript/elixirscript_react) Development =========== From 6c839df2407c580dd84d5b22ee1417b1441b3d98 Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Thu, 10 Aug 2017 09:32:55 -0500 Subject: [PATCH 662/860] Add in a data type conversion chart to JavaScriptInterop.md --- JavascriptInterop.md | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/JavascriptInterop.md b/JavascriptInterop.md index a09810d1..0b22dbe0 100644 --- a/JavascriptInterop.md +++ b/JavascriptInterop.md @@ -1,5 +1,24 @@ # JavaScript Interoperability +## Data Type Conversions + +ElixirScript translates Elixir primitive types to the following: + +| Elixir | JavaScript | +|--------|------------| +| Integer | Number | +| Float | Number | +| Binary | String | +| Atom | Symbol | +| List | Array | +| Map | Map | +| Tuple | ErlangTypes.Tuple | +| Bitstring | ErlangTypes.Bitstring | +| PID | ErlangTypes.PID | +| Reference | ErlangTypes.Reference | + +The ErlangTypes library can be found [here](https://github.com/elixirscript/erlang-types) + ## ElixirScript Calling JavaScript ### ElixirScript.JS module From a108812b94166e3f676f5f8ea57c93bbfe34438c Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Thu, 10 Aug 2017 11:34:17 -0500 Subject: [PATCH 663/860] Make sure _ref identifiers created are unique --- lib/elixir_script/passes/translate/forms/match.ex | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/elixir_script/passes/translate/forms/match.ex b/lib/elixir_script/passes/translate/forms/match.ex index aeaac2ee..e3625c4d 100644 --- a/lib/elixir_script/passes/translate/forms/match.ex +++ b/lib/elixir_script/passes/translate/forms/match.ex @@ -87,7 +87,7 @@ defmodule ElixirScript.Translate.Forms.Match do defp make_params(params) do - ref = J.identifier("_ref") + ref = J.identifier("_ref#{:rand.uniform(10000000)}") params = Enum.map(params, fn (nil) -> J.identifier(:undefined) From 5eeb1d8d2317585472edbdfec822fb26c2e02ea9 Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Thu, 10 Aug 2017 12:26:24 -0500 Subject: [PATCH 664/860] Now throwing warnings for unknown modules --- lib/elixir_script/passes/find_used_modules.ex | 5 +++++ test/compiler_test.exs | 6 ------ 2 files changed, 5 insertions(+), 6 deletions(-) diff --git a/lib/elixir_script/passes/find_used_modules.ex b/lib/elixir_script/passes/find_used_modules.ex index f2be293f..c8862606 100644 --- a/lib/elixir_script/passes/find_used_modules.ex +++ b/lib/elixir_script/passes/find_used_modules.ex @@ -1,6 +1,7 @@ defmodule ElixirScript.FindUsedModules do @moduledoc false alias ElixirScript.State, as: ModuleState + require Logger @doc """ Takes a list of entry modules and finds modules they use. @@ -20,6 +21,10 @@ defmodule ElixirScript.FindUsedModules do walk_module(module, info, pid) {:ok, module, implementations} -> walk_protocol(module, implementations, pid) + {:error, "Unknown module"} -> + Logger.warn fn() -> + "#{inspect module} is missing or unavailable" + end {:error, error} -> raise ElixirScript.CompileError, "An error occurred while compiling #{inspect module}: #{error}" end diff --git a/test/compiler_test.exs b/test/compiler_test.exs index 984f1846..45465c75 100644 --- a/test/compiler_test.exs +++ b/test/compiler_test.exs @@ -11,12 +11,6 @@ defmodule ElixirScript.Compiler.Test do assert is_binary(result) end - test "Error on unknown module" do - assert_raise ElixirScript.CompileError, fn -> - ElixirScript.Compiler.compile(SomeModule) - end - end - test "Output" do result = ElixirScript.Compiler.compile(Atom, []) assert result =~ "export default Elixir" From a9a0ca2ee04a653c725b83e4e4965ab6b7ab30de Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Thu, 10 Aug 2017 12:32:54 -0500 Subject: [PATCH 665/860] Prepend ElixirScript to warnings thrown --- lib/elixir_script/passes/find_used_modules.ex | 2 +- lib/elixir_script/passes/translate/form.ex | 2 +- lib/elixir_script/watcher.ex | 5 +---- 3 files changed, 3 insertions(+), 6 deletions(-) diff --git a/lib/elixir_script/passes/find_used_modules.ex b/lib/elixir_script/passes/find_used_modules.ex index c8862606..1c470fc9 100644 --- a/lib/elixir_script/passes/find_used_modules.ex +++ b/lib/elixir_script/passes/find_used_modules.ex @@ -23,7 +23,7 @@ defmodule ElixirScript.FindUsedModules do walk_protocol(module, implementations, pid) {:error, "Unknown module"} -> Logger.warn fn() -> - "#{inspect module} is missing or unavailable" + "ElixirScript: #{inspect module} is missing or unavailable" end {:error, error} -> raise ElixirScript.CompileError, "An error occurred while compiling #{inspect module}: #{error}" diff --git a/lib/elixir_script/passes/translate/form.ex b/lib/elixir_script/passes/translate/form.ex index b0b49f79..867add78 100644 --- a/lib/elixir_script/passes/translate/form.ex +++ b/lib/elixir_script/passes/translate/form.ex @@ -210,7 +210,7 @@ defmodule ElixirScript.Translate.Form do line = Keyword.get(context, :line, 1) {function, _arity} = Map.get(state, :function) Logger.warn fn() -> - "receive not supported, Module: #{inspect state.module}, Function: #{function}, Line: #{line}" + "ElixirScript: receive not supported, Module: #{inspect state.module}, Function: #{function}, Line: #{line}" end Receive.compile(blocks, state) end diff --git a/lib/elixir_script/watcher.ex b/lib/elixir_script/watcher.ex index 88fc0991..aa0dd74b 100644 --- a/lib/elixir_script/watcher.ex +++ b/lib/elixir_script/watcher.ex @@ -26,14 +26,11 @@ defmodule ElixirScript.Watcher do try do if input_changed?(to_string(path)) do - Logger.debug fn() -> - "Event: #{inspect event} Path: #{path}" - end ElixirScript.Compiler.compile(state[:input], state[:options]) end rescue x -> - Logger.error(x.message) + Logger.error("#{inspect __MODULE__}: #{x.message}") end {:noreply, state} From 4ce8dda289b8ec528d15fa14fb31cf2056f201ff Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Thu, 10 Aug 2017 12:34:01 -0500 Subject: [PATCH 666/860] Fix warning --- lib/elixir_script/watcher.ex | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/elixir_script/watcher.ex b/lib/elixir_script/watcher.ex index aa0dd74b..b33ca450 100644 --- a/lib/elixir_script/watcher.ex +++ b/lib/elixir_script/watcher.ex @@ -22,7 +22,7 @@ defmodule ElixirScript.Watcher do {:ok, args} end - def handle_info({_pid, {:fs, :file_event}, {path, event}}, state) do + def handle_info({_pid, {:fs, :file_event}, {path, _event}}, state) do try do if input_changed?(to_string(path)) do From df032500e9c8649c0e2c9142f0a87ea906bfa74b Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Thu, 10 Aug 2017 15:43:30 -0500 Subject: [PATCH 667/860] More documentation --- lib/elixir_script.ex | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/lib/elixir_script.ex b/lib/elixir_script.ex index 618282f8..e0ad5334 100644 --- a/lib/elixir_script.ex +++ b/lib/elixir_script.ex @@ -67,5 +67,14 @@ defmodule ElixirScript do ### Limitations ElixirScript does not support `receive` or any of OTP at this time. + + ### Dependencies + + ElixirScript can use many of the same Hex packages and dependencies that currently exist. + It is also possible to make packages that are specific to ElixirScript. If you decide to + make such a package, please prepend `elixir_script` to the app name. For instance is making + a package for ElixirScript with FFI modules for interacting with React, the name would be + `elixir_script_react`. This is to make sure that other developers know that a package in Hex + is specifically for use with ElixirScript. """ end From 482b8751b3992ad102034ee2ba1efd308e34a0a3 Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Fri, 11 Aug 2017 14:58:36 -0500 Subject: [PATCH 668/860] Making sure to only change return to recursion if in a non-anonymous function --- .../passes/translate/function.ex | 22 ++++++++++++++----- 1 file changed, 16 insertions(+), 6 deletions(-) diff --git a/lib/elixir_script/passes/translate/function.ex b/lib/elixir_script/passes/translate/function.ex index 58b564ea..6818866a 100644 --- a/lib/elixir_script/passes/translate/function.ex +++ b/lib/elixir_script/passes/translate/function.ex @@ -19,6 +19,9 @@ defmodule ElixirScript.Translate.Function do end def compile({:fn, _, clauses}, state) do + anonymous? = Map.get(state, :anonymous_fn, false) + + state = Map.put(state, :anonymous_fn, true) clauses = compile_clauses(clauses, state) arg_matches_declarator = J.variable_declarator( @@ -61,11 +64,14 @@ defmodule ElixirScript.Translate.Function do ]) ) + state = Map.put(state, :anonymous_fn, anonymous?) { function_dec, state } end def compile({{name, arity}, _type, _, clauses}, state) do state = Map.put(state, :function, {name, arity}) + |> Map.put(:anonymous_fn, false) + clauses = compile_clauses(clauses, state) arg_matches_declarator = J.variable_declarator( @@ -194,19 +200,23 @@ defmodule ElixirScript.Translate.Function do {ast, state} end - defp update_last_call(clause_body, %{function: {name, _}}) do + defp update_last_call(clause_body, %{function: {name, _}, anonymous_fn: anonymous?}) do last_item = List.last(clause_body) function_name = ElixirScript.Translate.Identifier.make_function_name(name) case last_item do %ESTree.ReturnStatement{ argument: %ESTree.CallExpression{ callee: ^function_name, arguments: arguments } } -> - new_last_item = J.return_statement( - recurse( - recur_bind(arguments) + if anonymous? do + clause_body + else + new_last_item = J.return_statement( + recurse( + recur_bind(arguments) + ) ) - ) - List.replace_at(clause_body, length(clause_body) - 1, new_last_item) + List.replace_at(clause_body, length(clause_body) - 1, new_last_item) + end _ -> clause_body end From dc00d1df189347c23dfe3d79ac0b1397ad0a1c38 Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Fri, 11 Aug 2017 16:19:22 -0500 Subject: [PATCH 669/860] Make sure that is_atom considers true, false, and null as atoms --- .../lib/core/erlang_compat/erlang.js | 32 +++++++++++++++---- .../tests/core/erlang_compat/erlang_spec.js | 15 ++++++++- 2 files changed, 40 insertions(+), 7 deletions(-) diff --git a/src/javascript/lib/core/erlang_compat/erlang.js b/src/javascript/lib/core/erlang_compat/erlang.js index faf71dd8..db95aae0 100644 --- a/src/javascript/lib/core/erlang_compat/erlang.js +++ b/src/javascript/lib/core/erlang_compat/erlang.js @@ -4,27 +4,39 @@ import lists from './lists'; const selfPID = new ErlangTypes.PID(); -function atom_to_list(atom) { - return Symbol.keyFor(atom); -} - function atom_to_binary(atom, encoding = Symbol.for('utf8')) { if (encoding !== Symbol.for('utf8')) { throw new Error(`unsupported encoding ${encoding}`); } - if (atom.__MODULE__) { + if (atom === null) { + return 'nil'; + } else if (is_boolean(atom)) { + return atom.toString(); + } else if (atom.__MODULE__) { return Symbol.keyFor(atom.__MODULE__); } return Symbol.keyFor(atom); } +function atom_to_list(atom) { + return atom_to_binary(atom); +} + function binary_to_atom(binary, encoding = Symbol.for('utf8')) { if (encoding !== Symbol.for('utf8')) { throw new Error(`unsupported encoding ${encoding}`); } + if (binary === 'nil') { + return null; + } else if (binary === 'true') { + return true; + } else if (binary === 'false') { + return false; + } + return Symbol.for(binary); } @@ -87,8 +99,16 @@ function bxor(left, right) { } function is_atom(value) { + if (value === null) { + return true; + } else if (is_boolean(value)) { + return true; + } + return ( - typeof value === 'symbol' || value instanceof Symbol || value.__MODULE__ + typeof value === 'symbol' || + value instanceof Symbol || + value.__MODULE__ != null ); } diff --git a/src/javascript/tests/core/erlang_compat/erlang_spec.js b/src/javascript/tests/core/erlang_compat/erlang_spec.js index 6bc6d4d0..0abab51e 100644 --- a/src/javascript/tests/core/erlang_compat/erlang_spec.js +++ b/src/javascript/tests/core/erlang_compat/erlang_spec.js @@ -1,6 +1,14 @@ import test from 'ava'; import Core from '../../../lib/core'; +test('is_atom', t => { + t.is(Core.erlang.is_atom(null), true); + t.is(Core.erlang.is_atom(true), true); + t.is(Core.erlang.is_atom(false), true); + t.is(Core.erlang.is_atom(Symbol.for('error')), true); + t.is(Core.erlang.is_atom('Hello'), false); +}); + test('atom_to_binary', t => { t.is(Core.erlang.atom_to_binary(Symbol.for('error')), 'error'); t.is( @@ -8,6 +16,11 @@ test('atom_to_binary', t => { 'error' ); + t.is(Core.erlang.atom_to_binary(null, Symbol.for('utf8')), 'nil'); + + t.is(Core.erlang.atom_to_binary(true, Symbol.for('utf8')), 'true'); + t.is(Core.erlang.atom_to_binary(false, Symbol.for('utf8')), 'false'); + t.throws( () => Core.erlang.atom_to_binary(Symbol.for('error'), Symbol.for('utf16')), Error @@ -23,7 +36,7 @@ test('list_concatenation', t => { 3, 4, 5, - 6, + 6 ]); }); From 090ed684960fd5a8d2d6896e8a23af75eeb24f3f Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Fri, 11 Aug 2017 21:07:32 -0500 Subject: [PATCH 670/860] Change Elixir.App.js to elixirscript.build.js --- JavascriptInterop.md | 2 +- README.md | 2 +- lib/elixir_script.ex | 8 ++++---- lib/elixir_script/compiler.ex | 2 +- lib/elixir_script/passes/output.ex | 2 +- lib/mix/tasks/compile.elixir_script.ex | 2 +- test/compiler_test.exs | 2 +- 7 files changed, 10 insertions(+), 10 deletions(-) diff --git a/JavascriptInterop.md b/JavascriptInterop.md index 0b22dbe0..9e01c189 100644 --- a/JavascriptInterop.md +++ b/JavascriptInterop.md @@ -81,7 +81,7 @@ For more information and options. Check the documentation for `ElixirScript.FFI` ``` ```javascript - import Elixir from './Elixir.App.js' + import Elixir from './elixirscript.build.js' Elixir.start(Elixir.Main, [1, 2, 3]) ``` diff --git a/README.md b/README.md index 8565d6d3..ba961ca4 100644 --- a/README.md +++ b/README.md @@ -32,7 +32,7 @@ Also add `elixir_script` configuration # Entry module. Can also be a list of modules input: MyEntryModule, # Output path. Either a path to a js file or a directory - output: "priv/elixir_script/build/Elixir.App.js" + output: "priv/elixir_script/build/elixirscript.build.js" ] ] end diff --git a/lib/elixir_script.ex b/lib/elixir_script.ex index e0ad5334..bc54565a 100644 --- a/lib/elixir_script.ex +++ b/lib/elixir_script.ex @@ -29,7 +29,7 @@ defmodule ElixirScript do # Entry module. Can also be a list of modules input: MyEntryModule, # Output path. Either a path to a js file or a directory - output: "priv/elixir_script/build/Elixir.App.js" + output: "priv/elixir_script/build/elixirscript.build.js" ] ] end @@ -42,16 +42,16 @@ defmodule ElixirScript do * `output`: The path of the generated JavaScript file. (defaults to `priv/elixir_script/build`) If path ends in `.js` then that will be the name of the file. If a directory is given, - file will be named `Elixir.App.js` + file will be named `elixirscript.build.js` * `root`: Optional root for imports of FFI JavaScript modules. Defaults to `.`. If using output directly in a browser, you may want to make it something like `/js` or some uri. - Now run `mix compile` and you should see a JavaScript file named `Elixir.App.js` in the `priv/elixir_script/build/` directory. ElixirScript outputs JavaScript in the ES Module format. If your browser supports it, you can include the output in a script tag with the type "module" + Now run `mix compile` and you should see a JavaScript file named `elixirscript.build.js` in the `priv/elixir_script/build/` directory. ElixirScript outputs JavaScript in the ES Module format. If your browser supports it, you can include the output in a script tag with the type "module" ```html ``` diff --git a/lib/elixir_script/passes/find_used_modules.ex b/lib/elixir_script/passes/find_used_modules.ex index 6e3c85aa..5b33127a 100644 --- a/lib/elixir_script/passes/find_used_modules.ex +++ b/lib/elixir_script/passes/find_used_modules.ex @@ -136,8 +136,8 @@ defmodule ElixirScript.FindUsedModules do defp walk(form, state) when is_atom(form) and form not in [BitString, Function, PID, Port, Reference, Any, Elixir] do if ElixirScript.Translate.Module.is_elixir_module(form) and !ElixirScript.Translate.Module.is_js_module(form, state) do + ModuleState.add_used_module(state.pid, state.module, form) if ModuleState.get_module(state.pid, form) == nil do - ModuleState.add_used_module(state.pid, state.module, form) do_execute(form, state.pid) end end @@ -166,8 +166,8 @@ defmodule ElixirScript.FindUsedModules do defp walk({:%, _, [module, params]}, state) do if ElixirScript.Translate.Module.is_elixir_module(module) and !ElixirScript.Translate.Module.is_js_module(module, state) do + ModuleState.add_used_module(state.pid, state.module, module) if ModuleState.get_module(state.pid, module) == nil do - ModuleState.add_used_module(state.pid, state.module, module) do_execute(module, state.pid) end end @@ -302,8 +302,8 @@ defmodule ElixirScript.FindUsedModules do defp walk({:., _, [module, function]}, state) do cond do ElixirScript.Translate.Module.is_elixir_module(module) -> + ModuleState.add_used_module(state.pid, state.module, module) if ModuleState.get_module(state.pid, module) == nil do - ModuleState.add_used_module(state.pid, state.module, module) do_execute(module, state.pid) end true -> diff --git a/lib/elixir_script/passes/output.ex b/lib/elixir_script/passes/output.ex index 650a6336..ce6ad187 100644 --- a/lib/elixir_script/passes/output.ex +++ b/lib/elixir_script/passes/output.ex @@ -80,7 +80,7 @@ defmodule ElixirScript.Output do end def module_to_name(module) do - "#{inspect module}" + "$#{inspect module}$" |> String.replace(".", "$") end @@ -93,7 +93,12 @@ defmodule ElixirScript.Output do end defp output(code, module, path, js_modules) do - output_dir = Path.dirname(path) + output_dir = if File.dir?(path) do + path + else + Path.dirname(path) + end + file_name = Path.join(output_dir, "Elixir.#{inspect module}.js") if !File.exists?(output_dir) do diff --git a/lib/elixir_script/passes/translate/module.ex b/lib/elixir_script/passes/translate/module.ex index 2d15d67d..81ed418b 100644 --- a/lib/elixir_script/passes/translate/module.ex +++ b/lib/elixir_script/passes/translate/module.ex @@ -54,20 +54,14 @@ defmodule ElixirScript.Translate.Module do combined_defs = combine_defs(used_defs) exports = make_exports(module, combined_defs) - # If there are no public exports, skip compilation - case exports do - %ESTree.ObjectExpression{ properties: props } when length(props) == 2 -> - nil - _ -> - { compiled_functions, _ } = Enum.map_reduce(combined_defs, state, &Function.compile(&1, &2)) + { compiled_functions, _ } = Enum.map_reduce(combined_defs, state, &Function.compile(&1, &2)) - info_function = make_info_function(module, state) - compiled_functions = [info_function] ++ compiled_functions + info_function = make_info_function(module, state) + compiled_functions = [info_function] ++ compiled_functions - js_ast = [compiled_functions, exports] + js_ast = [compiled_functions, exports] - ModuleState.put_module(pid, module, Map.put(info, :js_ast, js_ast)) - end + ModuleState.put_module(pid, module, Map.put(info, :js_ast, js_ast)) end defp combine_defs(used_defs) do diff --git a/test/passes/translate/form_test.exs b/test/passes/translate/form_test.exs index b0a6c34d..d40f4e30 100644 --- a/test/passes/translate/form_test.exs +++ b/test/passes/translate/form_test.exs @@ -1,7 +1,6 @@ defmodule ElixirScript.Translate.Forms.Test do use ExUnit.Case alias ElixirScript.Translate.Form - alias ElixirScript.Translate.Identifier alias ElixirScript.Translate.Helpers alias ESTree.Tools.Builder, as: J use ExUnitProperties @@ -127,7 +126,7 @@ defmodule ElixirScript.Translate.Forms.Test do ast = IO {js_ast, _} = Form.compile(ast, state) - assert js_ast == %ESTree.Identifier{loc: nil, name: "IO", type: "Identifier"} + assert js_ast == %ESTree.Identifier{loc: nil, name: "$IO$", type: "Identifier"} end test "function returning an array" do diff --git a/test/support/helpers.ex b/test/support/helpers.ex index 090554fc..813b6cf9 100644 --- a/test/support/helpers.ex +++ b/test/support/helpers.ex @@ -3,10 +3,7 @@ defmodule Helpers do def call_compiled_function(module, func, args \\ []) when is_list(args) do File.mkdir "tmp" - filename = Macro.underscore(inspect(module) <> "_" <> to_string(func)) - path = Path.join("tmp", filename <> ".mjs") - - ElixirScript.Compiler.compile(module, [output: path]) + ElixirScript.Compiler.compile(module, [output: "tmp"]) args_to_js = args |> Enum.map(&ElixirScript.TermConverter.encode/1) @@ -14,9 +11,7 @@ defmodule Helpers do main = """ import ElixirScript from './ElixirScript.Core.js'; - import Elixir from './#{filename}.mjs'; - - const mod = Elixir.#{inspect module}.__load(Elixir) + import mod from './Elixir.#{inspect module}.js'; const ret = mod.#{func}(#{args_to_js}) const jsonRet = JSON.stringify(ret, (name, value) => { @@ -34,7 +29,7 @@ defmodule Helpers do process.stdout.write(jsonRet) """ - main_path = Path.join("tmp", filename <> ".main.mjs") + main_path = Path.join("tmp", "Elixir.#{inspect module}.main.mjs") File.write!(main_path, main) {out, _a} = System.cmd "node", ["-r", "@std/esm", main_path] From f3ab23ecc579fd977ad6379039c98b0a3a0968d8 Mon Sep 17 00:00:00 2001 From: Mohamed Seleem Date: Sat, 21 Oct 2017 22:23:07 +0200 Subject: [PATCH 779/860] Add filename.join/1 --- src/javascript/lib/core.js | 2 ++ .../lib/core/erlang_compat/filename.js | 18 ++++++++++++++++++ .../tests/core/erlang_compat/filename_spec.js | 13 +++++++++++++ 3 files changed, 33 insertions(+) create mode 100644 src/javascript/lib/core/erlang_compat/filename.js create mode 100644 src/javascript/tests/core/erlang_compat/filename_spec.js diff --git a/src/javascript/lib/core.js b/src/javascript/lib/core.js index a13c9489..093816c2 100644 --- a/src/javascript/lib/core.js +++ b/src/javascript/lib/core.js @@ -8,6 +8,7 @@ import lists from './core/erlang_compat/lists'; import elixir_errors from './core/erlang_compat/elixir_errors'; import elixir_config from './core/erlang_compat/elixir_config'; import io from './core/erlang_compat/io'; +import filename from './core/erlang_compat/filename'; import binary from './core/erlang_compat/binary'; import unicode from './core/erlang_compat/unicode'; import Store from './core/store'; @@ -64,6 +65,7 @@ export default { lists, elixir_errors, io, + filename, binary, unicode, elixir_config, diff --git a/src/javascript/lib/core/erlang_compat/filename.js b/src/javascript/lib/core/erlang_compat/filename.js new file mode 100644 index 00000000..ec474109 --- /dev/null +++ b/src/javascript/lib/core/erlang_compat/filename.js @@ -0,0 +1,18 @@ +function join(arg = [], extra = []) { + let components = Array.isArray(arg) ? arg : [arg]; + components = components.concat(extra) + let names = []; + for (let i = components.length - 1; i >= 0; i--) { + const name = components[i]; + const normalized_name = name.replace(/\/+/g, '/').replace(/^\/|\/$/g, ''); + names.push(normalized_name); + if (name[0] == '/') { + names.push(''); + break; + } + } + return names.reverse().join('/'); +} +export default { + join, +}; diff --git a/src/javascript/tests/core/erlang_compat/filename_spec.js b/src/javascript/tests/core/erlang_compat/filename_spec.js new file mode 100644 index 00000000..57692d3b --- /dev/null +++ b/src/javascript/tests/core/erlang_compat/filename_spec.js @@ -0,0 +1,13 @@ +import test from 'ava'; +import Core from '../../../lib/core'; + +test('join/1', (t) => { + let result = Core.filename.join(['/usr', 'local', 'bin']); + t.is(result, '/usr/local/bin'); + + result = Core.filename.join(['a', '///b/', 'c/']); + t.is(result, '/b/c'); + + result = Core.filename.join(['a/b///c/']); + t.is(result, 'a/b/c'); +}); From f39e21c17d51045769a3e2ee872baa28ee16cc0d Mon Sep 17 00:00:00 2001 From: Mohamed Seleem Date: Sun, 22 Oct 2017 10:32:10 +0200 Subject: [PATCH 780/860] Add filename.dirname/1 --- src/javascript/lib/core/erlang_compat/filename.js | 8 ++++++++ src/javascript/tests/core/erlang_compat/filename_spec.js | 8 ++++++++ 2 files changed, 16 insertions(+) diff --git a/src/javascript/lib/core/erlang_compat/filename.js b/src/javascript/lib/core/erlang_compat/filename.js index ec474109..49d2aa83 100644 --- a/src/javascript/lib/core/erlang_compat/filename.js +++ b/src/javascript/lib/core/erlang_compat/filename.js @@ -13,6 +13,14 @@ function join(arg = [], extra = []) { } return names.reverse().join('/'); } + +function dirname(arg) { + const path = join([arg]); + const index = path.lastIndexOf('/'); + return index == -1 ? '.' : path.substr(0, index); +} + export default { join, + dirname, }; diff --git a/src/javascript/tests/core/erlang_compat/filename_spec.js b/src/javascript/tests/core/erlang_compat/filename_spec.js index 57692d3b..c5976942 100644 --- a/src/javascript/tests/core/erlang_compat/filename_spec.js +++ b/src/javascript/tests/core/erlang_compat/filename_spec.js @@ -1,6 +1,14 @@ import test from 'ava'; import Core from '../../../lib/core'; +test('dirname/1', (t) => { + let result = Core.filename.dirname('/usr/src/kalle.erl'); + t.is(result, '/usr/src'); + + result = Core.filename.dirname('kalle.erl'); + t.is(result, '.'); +}); + test('join/1', (t) => { let result = Core.filename.join(['/usr', 'local', 'bin']); t.is(result, '/usr/local/bin'); From a9eae953e66b55147b2426ec93ee0f0aebc046e8 Mon Sep 17 00:00:00 2001 From: Mohamed Seleem Date: Sun, 22 Oct 2017 10:34:02 +0200 Subject: [PATCH 781/860] Fix filename.join/2 signature --- src/javascript/lib/core/erlang_compat/filename.js | 5 ++--- src/javascript/tests/core/erlang_compat/filename_spec.js | 5 +++++ 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/src/javascript/lib/core/erlang_compat/filename.js b/src/javascript/lib/core/erlang_compat/filename.js index 49d2aa83..42458b94 100644 --- a/src/javascript/lib/core/erlang_compat/filename.js +++ b/src/javascript/lib/core/erlang_compat/filename.js @@ -1,6 +1,5 @@ -function join(arg = [], extra = []) { - let components = Array.isArray(arg) ? arg : [arg]; - components = components.concat(extra) +function join(arg, extra = null) { + const components = Array.isArray(arg) ? arg : [arg, extra]; let names = []; for (let i = components.length - 1; i >= 0; i--) { const name = components[i]; diff --git a/src/javascript/tests/core/erlang_compat/filename_spec.js b/src/javascript/tests/core/erlang_compat/filename_spec.js index c5976942..a647b1e6 100644 --- a/src/javascript/tests/core/erlang_compat/filename_spec.js +++ b/src/javascript/tests/core/erlang_compat/filename_spec.js @@ -19,3 +19,8 @@ test('join/1', (t) => { result = Core.filename.join(['a/b///c/']); t.is(result, 'a/b/c'); }); + +test('join/2', (t) => { + let result = Core.filename.join('/usr', 'bin'); + t.is(result, '/usr/bin'); +}); From a6741fdcdfa71749b90b73e676c9a349dc84c7ea Mon Sep 17 00:00:00 2001 From: Mohamed Seleem Date: Sun, 22 Oct 2017 13:40:53 +0200 Subject: [PATCH 782/860] Fix returning empty string if the path passed to filename.dirname/1 is a path to a file in the root directory --- src/javascript/lib/core/erlang_compat/filename.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/javascript/lib/core/erlang_compat/filename.js b/src/javascript/lib/core/erlang_compat/filename.js index 42458b94..401821df 100644 --- a/src/javascript/lib/core/erlang_compat/filename.js +++ b/src/javascript/lib/core/erlang_compat/filename.js @@ -16,7 +16,7 @@ function join(arg, extra = null) { function dirname(arg) { const path = join([arg]); const index = path.lastIndexOf('/'); - return index == -1 ? '.' : path.substr(0, index); + return index == -1 ? '.' : path.substr(0, index) || '/'; } export default { From 26392edc4f5371cd43acf96632529dd5c5ae79a4 Mon Sep 17 00:00:00 2001 From: Mohamed Seleem Date: Sun, 22 Oct 2017 13:41:05 +0200 Subject: [PATCH 783/860] Add more test cases --- src/javascript/tests/core/erlang_compat/filename_spec.js | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/javascript/tests/core/erlang_compat/filename_spec.js b/src/javascript/tests/core/erlang_compat/filename_spec.js index a647b1e6..053130f7 100644 --- a/src/javascript/tests/core/erlang_compat/filename_spec.js +++ b/src/javascript/tests/core/erlang_compat/filename_spec.js @@ -5,8 +5,14 @@ test('dirname/1', (t) => { let result = Core.filename.dirname('/usr/src/kalle.erl'); t.is(result, '/usr/src'); + result = Core.filename.dirname('usr/kalle.erl'); + t.is(result, 'usr'); + result = Core.filename.dirname('kalle.erl'); t.is(result, '.'); + + result = Core.filename.dirname('/kalle.erl'); + t.is(result, '/'); }); test('join/1', (t) => { From 39a3e3d2d6d603be9acf355cdbdd4d9882fe492d Mon Sep 17 00:00:00 2001 From: Mohamed Seleem Date: Sun, 22 Oct 2017 13:43:57 +0200 Subject: [PATCH 784/860] Fix issues found by ebert --- src/javascript/lib/core/erlang_compat/filename.js | 4 ++-- src/javascript/tests/core/erlang_compat/filename_spec.js | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/javascript/lib/core/erlang_compat/filename.js b/src/javascript/lib/core/erlang_compat/filename.js index 401821df..1d2fe0af 100644 --- a/src/javascript/lib/core/erlang_compat/filename.js +++ b/src/javascript/lib/core/erlang_compat/filename.js @@ -5,7 +5,7 @@ function join(arg, extra = null) { const name = components[i]; const normalized_name = name.replace(/\/+/g, '/').replace(/^\/|\/$/g, ''); names.push(normalized_name); - if (name[0] == '/') { + if (name[0] === '/') { names.push(''); break; } @@ -16,7 +16,7 @@ function join(arg, extra = null) { function dirname(arg) { const path = join([arg]); const index = path.lastIndexOf('/'); - return index == -1 ? '.' : path.substr(0, index) || '/'; + return index === -1 ? '.' : (path.substr(0, index) || '/'); } export default { diff --git a/src/javascript/tests/core/erlang_compat/filename_spec.js b/src/javascript/tests/core/erlang_compat/filename_spec.js index 053130f7..98bc1ab3 100644 --- a/src/javascript/tests/core/erlang_compat/filename_spec.js +++ b/src/javascript/tests/core/erlang_compat/filename_spec.js @@ -27,6 +27,6 @@ test('join/1', (t) => { }); test('join/2', (t) => { - let result = Core.filename.join('/usr', 'bin'); + const result = Core.filename.join('/usr', 'bin'); t.is(result, '/usr/bin'); }); From 0557c584ca47fbc69fac7cfc79560fa1ad42bf26 Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Sun, 22 Oct 2017 20:16:07 -0500 Subject: [PATCH 785/860] Beginnings of a testing framework --- lib/elixir_script/test.ex | 64 +++++++++++++++++++++++ lib/elixir_script/test/assertion_error.ex | 3 ++ lib/elixir_script/test/assertions.ex | 9 ++++ lib/mix/tasks/elixirscript.test.ex | 25 +++++++++ test_elixir_script/test_test.exs | 7 +++ 5 files changed, 108 insertions(+) create mode 100644 lib/elixir_script/test.ex create mode 100644 lib/elixir_script/test/assertion_error.ex create mode 100644 lib/elixir_script/test/assertions.ex create mode 100644 lib/mix/tasks/elixirscript.test.ex create mode 100644 test_elixir_script/test_test.exs diff --git a/lib/elixir_script/test.ex b/lib/elixir_script/test.ex new file mode 100644 index 00000000..9072c234 --- /dev/null +++ b/lib/elixir_script/test.ex @@ -0,0 +1,64 @@ +defmodule ElixirScript.Test do + @doc false + defmacro __using__(_opts) do + quote do + import unquote(__MODULE__), only: [test: 2, test: 3] + import ElixirScript.Test.Assertions + + def __elixir_script_test_module__(), do: true + end + end + + defmacro test(message, context \\ quote(do: _), contents) do + contents = + case contents do + [do: block] -> + quote do + unquote(block) + :ok + end + _ -> + quote do + try(unquote(contents)) + :ok + end + end + + context = Macro.escape(context) + contents = Macro.escape(contents, unquote: true) + name = String.to_atom("__test_#{String.replace(message, " ", "_")}") + + quote bind_quoted: [context: context, contents: contents, message: message, name: name] do + def unquote(name)(unquote(context)) do + %{ + message: unquote(message), + test: fn(context) -> unquote(contents) end + } + end + end + end + + @doc """ + Runs tests found in the given path. Accepts wildcards + """ + def start(path, opts \\ %{}) do + output = Path.join([System.tmp_dir!(), "elixirscript_tests"]) + File.mkdir_p!(output) + + ElixirScript.Compiler.compile(path, [output: output]) + + js_files = output + |> Path.expand + |> Path.join("Elixir.*.js") + |> Path.wildcard() + + test_script_path = Path.join([:code.priv_dir(:elixir_script), "index.js"]) + + {out, _a} = System.cmd "node", [test_script_path] ++ js_files, into: IO.stream(:stdio, :line) + + # Delete directory at the end + File.rm_rf!(output) + + :ok + end +end diff --git a/lib/elixir_script/test/assertion_error.ex b/lib/elixir_script/test/assertion_error.ex new file mode 100644 index 00000000..3a88fde2 --- /dev/null +++ b/lib/elixir_script/test/assertion_error.ex @@ -0,0 +1,3 @@ +defmodule ElixirScript.Test.AssertionError do + defexception [:message] +end diff --git a/lib/elixir_script/test/assertions.ex b/lib/elixir_script/test/assertions.ex new file mode 100644 index 00000000..49a0db1c --- /dev/null +++ b/lib/elixir_script/test/assertions.ex @@ -0,0 +1,9 @@ +defmodule ElixirScript.Test.Assertions do + def assert(value) do + if !value do + ElixirScript.JS.throw(%ElixirScript.Test.AssertionError{ + message: "failed" + }) + end + end +end diff --git a/lib/mix/tasks/elixirscript.test.ex b/lib/mix/tasks/elixirscript.test.ex new file mode 100644 index 00000000..153a4cff --- /dev/null +++ b/lib/mix/tasks/elixirscript.test.ex @@ -0,0 +1,25 @@ +defmodule Mix.Tasks.Elixirscript.Test do + @moduledoc """ + Runs ElixirScript Tests + """ + use Mix.Task + + @shortdoc "Runs ElixirScript Tests" + + + def run(args) do + Mix.Task.run "app.start" + + path = Path.join([default_test_path(), "**", "*_test.exs"]) + ElixirScript.Test.start(path) + + end + + defp default_test_path do + if File.dir?("test_elixir_script") do + "test_elixir_script" + else + "" + end + end +end diff --git a/test_elixir_script/test_test.exs b/test_elixir_script/test_test.exs new file mode 100644 index 00000000..069409f0 --- /dev/null +++ b/test_elixir_script/test_test.exs @@ -0,0 +1,7 @@ +defmodule ElixirScript.Test.Test do + use ElixirScript.Test + + test "can get ast from beam" do + assert 1 == 2 + end +end From 6982cbcb07e5d13305f6ad4c5f09aa6f71422675 Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Mon, 23 Oct 2017 21:53:14 -0500 Subject: [PATCH 786/860] Using raise instead of JS.throw --- lib/elixir_script/test/assertions.ex | 4 +--- src/javascript/lib/core/erlang_compat/erlang.js | 12 +++++++++--- 2 files changed, 10 insertions(+), 6 deletions(-) diff --git a/lib/elixir_script/test/assertions.ex b/lib/elixir_script/test/assertions.ex index 49a0db1c..2d8496b6 100644 --- a/lib/elixir_script/test/assertions.ex +++ b/lib/elixir_script/test/assertions.ex @@ -1,9 +1,7 @@ defmodule ElixirScript.Test.Assertions do def assert(value) do if !value do - ElixirScript.JS.throw(%ElixirScript.Test.AssertionError{ - message: "failed" - }) + raise ElixirScript.Test.AssertionError, message: "failed" end end end diff --git a/src/javascript/lib/core/erlang_compat/erlang.js b/src/javascript/lib/core/erlang_compat/erlang.js index 9867a9f5..18ec72d9 100644 --- a/src/javascript/lib/core/erlang_compat/erlang.js +++ b/src/javascript/lib/core/erlang_compat/erlang.js @@ -478,6 +478,8 @@ function _throw(term) { } function error(reason) { + let theError = null; + if (reason instanceof Map && reason.has(Symbol.for('__exception__'))) { let name = Symbol.keyFor(reason.get(Symbol.for('__struct__')).__MODULE__); name = name @@ -485,12 +487,16 @@ function error(reason) { .slice(1) .join('.'); const message = reason.get(Symbol.for('message')); - throw new Error(`** (${name}) ${message}`); + theError = new Error(`** (${name}) ${message}`); } else if (is_binary(reason)) { - throw new Error(`** (RuntimeError) ${reason}`); + theError = new Error(`** (RuntimeError) ${reason}`); } else { - throw new Error(`** (ErlangError) Erlang Error ${reason.toString()}`); + theError = new Error(`** (ErlangError) Erlang Error ${reason.toString()}`); } + + theError.__reason = reason; + + throw theError; } function exit(...args) { From 4f827e0469ad8ec86d4e8b025b89194c273e7b4d Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Tue, 24 Oct 2017 21:24:21 -0500 Subject: [PATCH 787/860] Some refactoring --- lib/{elixir_script => elixir_script_test}/test.ex | 2 +- .../test/assertion_error.ex | 0 lib/{elixir_script => elixir_script_test}/test/assertions.ex | 0 lib/mix/tasks/elixirscript.test.ex | 3 +-- test_elixir_script/test_test.exs | 2 +- 5 files changed, 3 insertions(+), 4 deletions(-) rename lib/{elixir_script => elixir_script_test}/test.ex (97%) rename lib/{elixir_script => elixir_script_test}/test/assertion_error.ex (100%) rename lib/{elixir_script => elixir_script_test}/test/assertions.ex (100%) diff --git a/lib/elixir_script/test.ex b/lib/elixir_script_test/test.ex similarity index 97% rename from lib/elixir_script/test.ex rename to lib/elixir_script_test/test.ex index 9072c234..b8bbd440 100644 --- a/lib/elixir_script/test.ex +++ b/lib/elixir_script_test/test.ex @@ -3,7 +3,7 @@ defmodule ElixirScript.Test do defmacro __using__(_opts) do quote do import unquote(__MODULE__), only: [test: 2, test: 3] - import ElixirScript.Test.Assertions + import ExUnit.Assertions def __elixir_script_test_module__(), do: true end diff --git a/lib/elixir_script/test/assertion_error.ex b/lib/elixir_script_test/test/assertion_error.ex similarity index 100% rename from lib/elixir_script/test/assertion_error.ex rename to lib/elixir_script_test/test/assertion_error.ex diff --git a/lib/elixir_script/test/assertions.ex b/lib/elixir_script_test/test/assertions.ex similarity index 100% rename from lib/elixir_script/test/assertions.ex rename to lib/elixir_script_test/test/assertions.ex diff --git a/lib/mix/tasks/elixirscript.test.ex b/lib/mix/tasks/elixirscript.test.ex index 153a4cff..3d282b23 100644 --- a/lib/mix/tasks/elixirscript.test.ex +++ b/lib/mix/tasks/elixirscript.test.ex @@ -5,14 +5,13 @@ defmodule Mix.Tasks.Elixirscript.Test do use Mix.Task @shortdoc "Runs ElixirScript Tests" - + @preferred_cli_env :test def run(args) do Mix.Task.run "app.start" path = Path.join([default_test_path(), "**", "*_test.exs"]) ElixirScript.Test.start(path) - end defp default_test_path do diff --git a/test_elixir_script/test_test.exs b/test_elixir_script/test_test.exs index 069409f0..c4d5c4a9 100644 --- a/test_elixir_script/test_test.exs +++ b/test_elixir_script/test_test.exs @@ -2,6 +2,6 @@ defmodule ElixirScript.Test.Test do use ElixirScript.Test test "can get ast from beam" do - assert 1 == 2 + assert 1 = 2 end end From 55763cebb3512a9832a903453d3118c0ffcec3b0 Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Tue, 24 Oct 2017 21:27:58 -0500 Subject: [PATCH 788/860] Testrunner --- .gitignore | 2 +- lib/elixir_script_test/test.ex | 2 +- priv/testrunner/esm/LICENSE | 23 ++++++ priv/testrunner/esm/README.md | 131 +++++++++++++++++++++++++++++++ priv/testrunner/esm/esm.js.gz | Bin 0 -> 44315 bytes priv/testrunner/esm/package.json | 20 +++++ priv/testrunner/testRunner.js | 51 ++++++++++++ 7 files changed, 227 insertions(+), 2 deletions(-) create mode 100644 priv/testrunner/esm/LICENSE create mode 100644 priv/testrunner/esm/README.md create mode 100644 priv/testrunner/esm/esm.js.gz create mode 100644 priv/testrunner/esm/package.json create mode 100644 priv/testrunner/testRunner.js diff --git a/.gitignore b/.gitignore index 755b82c6..cb91ffe0 100644 --- a/.gitignore +++ b/.gitignore @@ -22,6 +22,6 @@ stdlib_state.bin test/app/build .vscode cover -/priv +/priv/build /tmp .esm-cache diff --git a/lib/elixir_script_test/test.ex b/lib/elixir_script_test/test.ex index b8bbd440..cc5da921 100644 --- a/lib/elixir_script_test/test.ex +++ b/lib/elixir_script_test/test.ex @@ -52,7 +52,7 @@ defmodule ElixirScript.Test do |> Path.join("Elixir.*.js") |> Path.wildcard() - test_script_path = Path.join([:code.priv_dir(:elixir_script), "index.js"]) + test_script_path = Path.join([:code.priv_dir(:elixir_script), "testrunner", "index.js"]) {out, _a} = System.cmd "node", [test_script_path] ++ js_files, into: IO.stream(:stdio, :line) diff --git a/priv/testrunner/esm/LICENSE b/priv/testrunner/esm/LICENSE new file mode 100644 index 00000000..2902552d --- /dev/null +++ b/priv/testrunner/esm/LICENSE @@ -0,0 +1,23 @@ +The MIT License (MIT) + +Copyright @std/esm contributors + +Based on reify, copyright Ben Newman + +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. diff --git a/priv/testrunner/esm/README.md b/priv/testrunner/esm/README.md new file mode 100644 index 00000000..83c5c840 --- /dev/null +++ b/priv/testrunner/esm/README.md @@ -0,0 +1,131 @@ +# @std/esm + +This fast, small, zero dependency, package is all you need to enable +ES modules in Node 4+ today! + +:book: See the [release post](https://medium.com/web-on-the-edge/es-modules-in-node-today-32cff914e4b) +for all the details. + +Getting started +--- + + 1. Run `npm i --save @std/esm` in your app or package directory. + 2. Add `.esm-cache` to your `.gitignore`. + 3. Create the ESM loader to import your main ES module: + + **index.js** + ```js + require = require("@std/esm")(module) + module.exports = require("./main.mjs").default + ``` + + By default, `@std/esm` **only** processes files of packages that opt-in + with a `@std/esm` options object or `@std/esm` as a dependency, dev + dependency, or peer dependency in their package.json. However, you can + enable processing **all** files with specific options by passing an options + object as the second argument or passing `true` to use the options from + your package.json. + + ```js + const loader1 = require("@std/esm")(module, { cjs: true, esm: "js" }) + const loader2 = require("@std/esm")(module, true) + ``` + +Enable ESM in the Node CLI by loading `@std/esm` with the [`-r` option](https://nodejs.org/api/cli.html#cli_r_require_module): + +```shell +node -r @std/esm file.mjs +``` + +Enable ESM in the Node REPL by loading `@std/esm` upon entering: + +```shell +$ node +> require("@std/esm") +@std/esm enabled +> import p from "path" +undefined +> p.join("hello", "world") +'hello/world' +``` + +*Note: The `"cjs"` and `"gz"` options are [unlocked](#unlockables) in the Node REPL.* + +Standard Features +--- + +The `@std/esm` loader is as spec-compliant +as possible and follows [Node’s rules](https://github.com/nodejs/node-eps/blob/master/002-es-modules.md). + +:point_right: This means, by default, ESM requires the use of the `.mjs` file +extension.
+:unlock: You can [unlock](#unlockables) ESM with the `.js` file extension using +the `"js"` ESM mode. + +Out of the box `@std/esm` just works, no configuration necessary, and supports: + +* [`import`](https://ponyfoo.com/articles/es6-modules-in-depth#import) / [`export`](https://ponyfoo.com/articles/es6-modules-in-depth#export) +* [Dynamic `import()`](https://github.com/tc39/proposal-dynamic-import) +* [Live bindings](https://ponyfoo.com/articles/es6-modules-in-depth#bindings-not-values) +* [Loading `.mjs` files as ESM](https://github.com/nodejs/node-eps/blob/master/002-es-modules.md#32-determining-if-source-is-an-es-module) +* [The file URI scheme](https://en.wikipedia.org/wiki/File_URI_scheme) +* Node 4+ support + +Unlockables +--- + +Unlock extra features with `"@std/esm":options` or +`"@std":{"esm":options}` in your package.json. + +*Note: All options are **off** by default and may be specified as either an object or ESM mode string.* + + + + + + + + + + + + + + + + + + + + + + + + +
+
{
+  "@std/esm": {
+
"esm": +

A string ESM mode

+
    +
  • "mjs" files as ESM (default)
  • +
  • "all" files as ESM
  • +
  • "js" files with import, export, or "use module" as ESM
  • +
+
"cjs": +

A boolean for CJS features in ESM

+ +
"await":

A boolean for top-level await in the main ES module

"gz": +

A boolean for gzipped module support (i.e. .js.gz, .mjs.gz)

+ +
+
  }
+}
+
diff --git a/priv/testrunner/esm/esm.js.gz b/priv/testrunner/esm/esm.js.gz new file mode 100644 index 0000000000000000000000000000000000000000..d199117df28f418ef7774a106399c091d28c06c9 GIT binary patch literal 44315 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 literal 0 HcmV?d00001 diff --git a/priv/testrunner/esm/package.json b/priv/testrunner/esm/package.json new file mode 100644 index 00000000..fa5bb5c5 --- /dev/null +++ b/priv/testrunner/esm/package.json @@ -0,0 +1,20 @@ +{ + "name": "@std/esm", + "version": "0.8.3", + "description": "Enable ES modules in Node today!", + "keywords": "commonjs, ecmascript, export, import, modules, node, require", + "repository": "standard-things/esm", + "license": "MIT", + "author": "John-David Dalton ", + "main": "index.js", + "engines": { + "node": ">=4" + }, + "scripts": { + "test": "echo \"Error: no test specified\" && exit 1" + }, + "files": [ + "index.js", + "esm.js.gz" + ] +} diff --git a/priv/testrunner/testRunner.js b/priv/testrunner/testRunner.js new file mode 100644 index 00000000..30c7d814 --- /dev/null +++ b/priv/testrunner/testRunner.js @@ -0,0 +1,51 @@ +async function start(files) { + const results = { + tests: 0, + success: 0, + failed: 0, + }; + + for (const file of files) { + const mod = await import(file); + if (mod.default.__elixir_script_test_module__) { + runTests(mod, results); + } + } + + return results; +} + +function runTests(mod, results) { + const context = []; + + for (const key of Object.keys(mod.default)) { + if (key.startsWith('__test_')) { + results.tests++; + const test = mod.default[key](context); + try { + test.get(Symbol.for('test'))(context); + results.success++; + } catch (e) { + handleError(e); + results.failed++; + } + } + } +} + +function handleError(e) { + if (e.__reason) { + if (e.__reason instanceof Map && e.__reason.get(Symbol.for('message'))) { + console.error(e.__reason.get(Symbol.for('message'))); + console.error(e.__reason.get(Symbol.for('expr')).toString()); + console.error(e.__reason.get(Symbol.for('left')).toString()); + console.error(e.__reason.get(Symbol.for('right')).toString()); + } + } else { + console.error(e.message); + } +} + +export default { + start, +}; From d2c8b27dad614f575503674dbc9892ecefe6327d Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Tue, 24 Oct 2017 21:29:52 -0500 Subject: [PATCH 789/860] Testrunner index files --- .gitignore | 1 - priv/testrunner/esm/index.js | 49 ++++++++++++++++++++++++++++++++++++ priv/testrunner/index.js | 13 ++++++++++ 3 files changed, 62 insertions(+), 1 deletion(-) create mode 100644 priv/testrunner/esm/index.js create mode 100644 priv/testrunner/index.js diff --git a/.gitignore b/.gitignore index cb91ffe0..77a9c54a 100644 --- a/.gitignore +++ b/.gitignore @@ -10,7 +10,6 @@ deploy.sh .DS_Store sample/dest fprof.trace -index.js /doc /bench/snapshots .tern-port diff --git a/priv/testrunner/esm/index.js b/priv/testrunner/esm/index.js new file mode 100644 index 00000000..7f6018cd --- /dev/null +++ b/priv/testrunner/esm/index.js @@ -0,0 +1,49 @@ +/* eslint strict: off, node/no-unsupported-features: ["error", { version: 4 }] */ +"use strict" + +const fs = require("fs") +const path = require("path") +const util = require("util") +const vm = require("vm") +const zlib = require("zlib") + +const esmPath = path.resolve(__dirname, "esm.js.gz") +const inspectKey = util.inspect.custom || "inspect" + +const descriptor = Object.create(null) +descriptor.value = () => "@std/esm enabled" + +const mod = new module.constructor(module.id) +mod.filename = __filename +mod.parent = module.parent + +const scriptOptions = Object.create(null) +scriptOptions.filename = __filename + +const content = + "(function(require,module,__filename){" + + zlib.gunzipSync(fs.readFileSync(esmPath)).toString() + + "\n})" + +const compiled = vm.runInThisContext(content, scriptOptions) + +function makeLoaderFunction() { + compiled(require, mod, __filename) + return mod.exports +} + +const loader = makeLoaderFunction() + +module.exports = (mod, options) => { + const type = typeof options + + if (options === true || + type === "function" || + (type === "object" && options !== null)) { + return makeLoaderFunction()(mod, options) + } + + return loader(mod, options) +} + +Object.freeze(Object.defineProperty(module.exports, inspectKey, descriptor)) diff --git a/priv/testrunner/index.js b/priv/testrunner/index.js new file mode 100644 index 00000000..96eaf89a --- /dev/null +++ b/priv/testrunner/index.js @@ -0,0 +1,13 @@ +require = require('./esm/index.js')(module, { cjs: true, esm: 'js' }); +const runner = require('./testRunner.js').default; + +const testFiles = process.argv.slice(2); +runner.start(testFiles).then((results) => { + console.log(`${results.tests} tests, ${results.success} succeeded, ${results.failed} failed`); + + if (results.failed > 0) { + process.exit(1); + } else { + process.exit(0); + } +}); From fe1dda9b631f7e9219f73c22deed48c0d50fad27 Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Wed, 25 Oct 2017 20:23:12 -0500 Subject: [PATCH 790/860] Testing using elixirscript.test --- Makefile | 1 + lib/elixir_script_test/test.ex | 15 ++++-- lib/mix/tasks/elixirscript.test.ex | 7 ++- priv/testrunner/index.js | 3 +- priv/testrunner/testRunner.js | 31 ++++++++++--- test/integration/integration_test.exs | 47 ------------------- test/support/helpers.ex | 41 ---------------- test/support/integration.ex | 42 ----------------- test/support/term_converter.ex | 57 ----------------------- test_elixir_script/integration_test.exs | 62 +++++++++++++++++++++++++ test_elixir_script/test_test.exs | 7 --- 11 files changed, 108 insertions(+), 205 deletions(-) delete mode 100644 test/integration/integration_test.exs delete mode 100644 test/support/helpers.ex delete mode 100644 test/support/integration.ex delete mode 100644 test/support/term_converter.ex create mode 100644 test_elixir_script/integration_test.exs delete mode 100644 test_elixir_script/test_test.exs diff --git a/Makefile b/Makefile index daf796b9..d717c5c5 100644 --- a/Makefile +++ b/Makefile @@ -17,6 +17,7 @@ js_test: elixir_test: mix test --cover + mix elixirscript.test clean: rm -rf priv/build diff --git a/lib/elixir_script_test/test.ex b/lib/elixir_script_test/test.ex index cc5da921..c3618700 100644 --- a/lib/elixir_script_test/test.ex +++ b/lib/elixir_script_test/test.ex @@ -26,7 +26,11 @@ defmodule ElixirScript.Test do context = Macro.escape(context) contents = Macro.escape(contents, unquote: true) - name = String.to_atom("__test_#{String.replace(message, " ", "_")}") + name = message + |> String.replace(" ", "_") + |> String.replace(~r/[^A-Za-z0-9]/, "") + + name = String.to_atom("__test_#{name}") quote bind_quoted: [context: context, contents: contents, message: message, name: name] do def unquote(name)(unquote(context)) do @@ -54,11 +58,16 @@ defmodule ElixirScript.Test do test_script_path = Path.join([:code.priv_dir(:elixir_script), "testrunner", "index.js"]) - {out, _a} = System.cmd "node", [test_script_path] ++ js_files, into: IO.stream(:stdio, :line) + {_, exit_status} = System.cmd "node", [test_script_path] ++ js_files, into: IO.stream(:stdio, :line) # Delete directory at the end File.rm_rf!(output) - :ok + case exit_status do + 0 -> + :ok + _ -> + :error + end end end diff --git a/lib/mix/tasks/elixirscript.test.ex b/lib/mix/tasks/elixirscript.test.ex index 3d282b23..23321491 100644 --- a/lib/mix/tasks/elixirscript.test.ex +++ b/lib/mix/tasks/elixirscript.test.ex @@ -11,7 +11,12 @@ defmodule Mix.Tasks.Elixirscript.Test do Mix.Task.run "app.start" path = Path.join([default_test_path(), "**", "*_test.exs"]) - ElixirScript.Test.start(path) + case ElixirScript.Test.start(path) do + :error -> + System.at_exit(fn _ -> exit({:shutdown, 1}) end) + :ok -> + :ok + end end defp default_test_path do diff --git a/priv/testrunner/index.js b/priv/testrunner/index.js index 96eaf89a..2c8f8c2b 100644 --- a/priv/testrunner/index.js +++ b/priv/testrunner/index.js @@ -3,7 +3,8 @@ const runner = require('./testRunner.js').default; const testFiles = process.argv.slice(2); runner.start(testFiles).then((results) => { - console.log(`${results.tests} tests, ${results.success} succeeded, ${results.failed} failed`); + process.stdout.write('\n\n'); + process.stdout.write(`${results.tests} tests, ${results.success} succeeded, ${results.failed} failed\n`); if (results.failed > 0) { process.exit(1); diff --git a/priv/testrunner/testRunner.js b/priv/testrunner/testRunner.js index 30c7d814..2aae1ad3 100644 --- a/priv/testrunner/testRunner.js +++ b/priv/testrunner/testRunner.js @@ -25,27 +25,46 @@ function runTests(mod, results) { try { test.get(Symbol.for('test'))(context); results.success++; + process.stdout.write('.'); } catch (e) { - handleError(e); results.failed++; + handleError(e, test, results, mod); } } } } -function handleError(e) { +function handleError(e, test, results, mod) { if (e.__reason) { if (e.__reason instanceof Map && e.__reason.get(Symbol.for('message'))) { - console.error(e.__reason.get(Symbol.for('message'))); - console.error(e.__reason.get(Symbol.for('expr')).toString()); - console.error(e.__reason.get(Symbol.for('left')).toString()); - console.error(e.__reason.get(Symbol.for('right')).toString()); + const errorMessage = e.__reason.get(Symbol.for('message')); + const expr = e.__reason.get(Symbol.for('expr')); + const left = e.__reason.get(Symbol.for('left')); + const right = e.__reason.get(Symbol.for('right')); + const moduleName = Symbol.keyFor(mod.default.__MODULE__).replace('Elixir.', ''); + let testMessage = test.get(Symbol.for('message')); + testMessage = `${results.failed}) ${testMessage} (${moduleName})`; + + printErrorLine(testMessage); + printErrorLine(errorMessage); + printErrorLine(left, 'left'); + printErrorLine(right, 'right'); } } else { console.error(e.message); } } +function printErrorLine(value, label = null) { + if (value !== Symbol.for('ex_unit_no_meaningful_value')) { + if (label) { + console.error(`${label}: ${value}`); + } else { + console.error(`${value}`); + } + } +} + export default { start, }; diff --git a/test/integration/integration_test.exs b/test/integration/integration_test.exs deleted file mode 100644 index beb4e8f4..00000000 --- a/test/integration/integration_test.exs +++ /dev/null @@ -1,47 +0,0 @@ -defmodule ElixirScript.Integration.Test do - use ExUnit.Case - import Helpers - - test "Atom.to_string" do - val = call_compiled_function Atom, :to_string, [:atom] - assert val == "atom" - end - - test "String interpolation with number" do - val = call_compiled_function Integration, :test_string_interpolation, [] - assert val == "5" - end - - test "shorthand failure" do - val = call_compiled_function Integration, :shorthand_failure, [] - assert val == [ - [:option, %{value: "test@hotmail.com"}, "test@hotmail.com"], - [:option, %{value: "test2@hotmail.com"}, "test2@hotmail.com"] - ] - end - - test "map equals" do - val = call_compiled_function Integration, :map_equals, [] - assert val == true - end - - test "multi-remote call" do - val = call_compiled_function Integration, :multi_field_call, [] - assert val == "5,000,000" - end - - test "filter names in guards" do - val = call_compiled_function Integration, :filter_names_in_guards, [] - assert val == true - end - - test "tuple_get" do - val = call_compiled_function Integration, :tuple_get, [] - assert val == 5 - end - - test "multi_bind" do - val = call_compiled_function Integration, :multi_bind, [] - assert val == [1, 2, 3, 4, 5] - end -end diff --git a/test/support/helpers.ex b/test/support/helpers.ex deleted file mode 100644 index 813b6cf9..00000000 --- a/test/support/helpers.ex +++ /dev/null @@ -1,41 +0,0 @@ -defmodule Helpers do - @moduledoc false - - def call_compiled_function(module, func, args \\ []) when is_list(args) do - File.mkdir "tmp" - ElixirScript.Compiler.compile(module, [output: "tmp"]) - - args_to_js = args - |> Enum.map(&ElixirScript.TermConverter.encode/1) - |> Enum.join(",") - - main = """ - import ElixirScript from './ElixirScript.Core.js'; - import mod from './Elixir.#{inspect module}.js'; - const ret = mod.#{func}(#{args_to_js}) - - const jsonRet = JSON.stringify(ret, (name, value) => { - if(typeof value === 'symbol') { - value = `@@@${Symbol.keyFor(value)}` - } - - if(value instanceof Map) { - value = {__type__: "map", values: Array.from(value.entries())} - } - - return value - }) - - process.stdout.write(jsonRet) - """ - - main_path = Path.join("tmp", "Elixir.#{inspect module}.main.mjs") - File.write!(main_path, main) - - {out, _a} = System.cmd "node", ["-r", "@std/esm", main_path] - - out - |> Poison.decode! - |> ElixirScript.TermConverter.decode - end -end diff --git a/test/support/integration.ex b/test/support/integration.ex deleted file mode 100644 index 9f1b73bf..00000000 --- a/test/support/integration.ex +++ /dev/null @@ -1,42 +0,0 @@ -defmodule Integration do - @moduledoc false - - def test_string_interpolation do - "#{5}" - end - - def shorthand_failure do - orders = [%{email: "test@hotmail.com"},%{email: "test2@hotmail.com"}] - Enum.reduce(orders, [], - &(&2 ++ [ [:option, %{value: &1.email}, &1.email] ])) - end - - def map_equals do - map1 = %{test: "map"} - map2 = %{test: "map"} - map1 == map2 - end - - def multi_field_call do - map = %{token_count: 5000000} - map.token_count.toLocaleString() - end - - def filter_names_in_guards do - has? = 5 - - case 5 do - _ when has? == 5 -> - true - end - end - - def multi_bind do - [a | _] = b = [1, 2, 3, 4, 5] - end - - def tuple_get do - map = %{{1} => 5} - Map.get(map, {1}) - end -end diff --git a/test/support/term_converter.ex b/test/support/term_converter.ex deleted file mode 100644 index 0aa6ad1f..00000000 --- a/test/support/term_converter.ex +++ /dev/null @@ -1,57 +0,0 @@ -defmodule ElixirScript.TermConverter do - - def encode(nil), do: "null" - def encode(term) when is_boolean(term) or is_number(term), do: to_string(term) - def encode(term) when is_binary(term), do: "'#{term}'" - def encode(term) when is_atom(term), do: "Symbol.for('#{to_string(term)}')" - def encode(term) when is_list(term) do - terms = term - |> Enum.map(fn(x) -> encode(x) end) - |> Enum.join(",") - - "[#{terms}]" - end - - def encode(term) when is_map(term) do - terms = term - |> Enum.map(fn({key, term}) -> - key = encode(key) - term = encode(term) - - "[#{key}, #{term}]" - end) - |> Enum.join(",") - - "[#{terms}]" - end - - def encode(term) when is_tuple(term) do - terms = term - |> Tuple.to_list - |> Enum.map(fn(x) -> encode(x) end) - |> Enum.join(",") - - "new ElixirScript.Core.Tuple(#{terms})" - end - - def decode("@@@" <> term) do - String.to_atom(term) - end - - def decode(term) when is_binary(term) or is_boolean(term) or is_number(term) or is_nil(term) do - term - end - - def decode(term) when is_list(term) do - Enum.map(term, &decode/1) - end - - def decode(%{"length" => _, "terms" => terms}) do - List.to_tuple(terms) - end - - def decode(%{"__type__" => "map", "values" => values}) do - Enum.map(values, fn [key, term] -> {decode(key), decode(term)} end) - |> Enum.into(%{}) - end -end diff --git a/test_elixir_script/integration_test.exs b/test_elixir_script/integration_test.exs new file mode 100644 index 00000000..504bf310 --- /dev/null +++ b/test_elixir_script/integration_test.exs @@ -0,0 +1,62 @@ +defmodule ElixirScript.Test.Test do + use ElixirScript.Test + + test "Atom.to_string" do + val = Atom.to_string(:atom) + assert val == "atom" + end + + test "String interpolation with number" do + val = "#{5}" + assert val == "5" + end + + test "shorthand failure" do + orders = [%{email: "test@hotmail.com"},%{email: "test2@hotmail.com"}] + + val = Enum.reduce(orders, [], + &(&2 ++ [ [:option, %{value: &1.email}, &1.email] ])) + + assert val == [ + [:option, %{value: "test@hotmail.com"}, "test@hotmail.com"], + [:option, %{value: "test2@hotmail.com"}, "test2@hotmail.com"] + ] + end + + test "map equals" do + map1 = %{test: "map"} + map2 = %{test: "map"} + + assert map1 == map2 + end + + test "multi-remote call" do + map = %{token_count: 5_000_000} + val = map.token_count.toLocaleString() + + assert val == "5,000,000" + end + + test "filter names in guards" do + has? = 5 + + val = case 5 do + _ when has? == 5 -> + true + end + + assert val == true + end + + test "tuple_get" do + map = %{{1} => 5} + val = Map.get(map, {1}) + + assert val == 5 + end + + test "multi_bind" do + [_a | _] = val = [1, 2, 3, 4, 5] + assert val == [1, 2, 3, 4, 5] + end +end diff --git a/test_elixir_script/test_test.exs b/test_elixir_script/test_test.exs deleted file mode 100644 index c4d5c4a9..00000000 --- a/test_elixir_script/test_test.exs +++ /dev/null @@ -1,7 +0,0 @@ -defmodule ElixirScript.Test.Test do - use ElixirScript.Test - - test "can get ast from beam" do - assert 1 = 2 - end -end From 5f27907a7fcd2c854212f5555fb06b9c0f587cc7 Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Thu, 26 Oct 2017 20:19:44 -0500 Subject: [PATCH 791/860] Add colors to output --- priv/testrunner/colors.js | 31 +++++++++++++++++++++++++ priv/testrunner/index.js | 13 +++++++++-- priv/testrunner/testRunner.js | 11 +++++---- test_elixir_script/integration_test.exs | 4 ++++ 4 files changed, 53 insertions(+), 6 deletions(-) create mode 100644 priv/testrunner/colors.js diff --git a/priv/testrunner/colors.js b/priv/testrunner/colors.js new file mode 100644 index 00000000..b0b48173 --- /dev/null +++ b/priv/testrunner/colors.js @@ -0,0 +1,31 @@ +export default { + Reset: '\x1b[0m', + Bright: '\x1b[1m', + Dim: '\x1b[2m', + Underscore: '\x1b[4m', + Blink: '\x1b[5m', + Reverse: '\x1b[7m', + Hidden: '\x1b[8m', + fg: { + Black: '\x1b[30m', + Red: '\x1b[31m', + Green: '\x1b[32m', + Yellow: '\x1b[33m', + Blue: '\x1b[34m', + Magenta: '\x1b[35m', + Cyan: '\x1b[36m', + White: '\x1b[37m', + Crimson: '\x1b[38m', + }, + bg: { + Black: '\x1b[40m', + Red: '\x1b[41m', + Green: '\x1b[42m', + Yellow: '\x1b[43m', + Blue: '\x1b[44m', + Magenta: '\x1b[45m', + Cyan: '\x1b[46m', + White: '\x1b[47m', + Crimson: '\x1b[48m', + }, +}; diff --git a/priv/testrunner/index.js b/priv/testrunner/index.js index 2c8f8c2b..3096fa41 100644 --- a/priv/testrunner/index.js +++ b/priv/testrunner/index.js @@ -1,12 +1,21 @@ require = require('./esm/index.js')(module, { cjs: true, esm: 'js' }); const runner = require('./testRunner.js').default; +const Colors = require('./colors.js').default; const testFiles = process.argv.slice(2); +console.time('Finished in'); runner.start(testFiles).then((results) => { + const testsFailed = results.failed > 0; + process.stdout.write('\n\n'); - process.stdout.write(`${results.tests} tests, ${results.success} succeeded, ${results.failed} failed\n`); + console.timeEnd('Finished in'); + console.log( + testsFailed ? Colors.fg.Red : Colors.fg.Green, + `${results.tests} tests, ${results.success} succeeded, ${results.failed} failed\n`, + Colors.Reset, + ); - if (results.failed > 0) { + if (testsFailed) { process.exit(1); } else { process.exit(0); diff --git a/priv/testrunner/testRunner.js b/priv/testrunner/testRunner.js index 2aae1ad3..992444d2 100644 --- a/priv/testrunner/testRunner.js +++ b/priv/testrunner/testRunner.js @@ -1,3 +1,5 @@ +import Colors from './colors.js'; + async function start(files) { const results = { tests: 0, @@ -25,9 +27,10 @@ function runTests(mod, results) { try { test.get(Symbol.for('test'))(context); results.success++; - process.stdout.write('.'); + process.stdout.write(Colors.fg.Green + '.' + Colors.Reset); } catch (e) { results.failed++; + process.stdout.write('\n'); handleError(e, test, results, mod); } } @@ -46,7 +49,7 @@ function handleError(e, test, results, mod) { testMessage = `${results.failed}) ${testMessage} (${moduleName})`; printErrorLine(testMessage); - printErrorLine(errorMessage); + console.log(Colors.fg.Red, errorMessage, Colors.Reset); printErrorLine(left, 'left'); printErrorLine(right, 'right'); } @@ -58,9 +61,9 @@ function handleError(e, test, results, mod) { function printErrorLine(value, label = null) { if (value !== Symbol.for('ex_unit_no_meaningful_value')) { if (label) { - console.error(`${label}: ${value}`); + console.log(Colors.fg.Cyan, `${label}:`, Colors.Reset, `${value}`); } else { - console.error(`${value}`); + console.log(`${value}`, Colors.Reset); } } } diff --git a/test_elixir_script/integration_test.exs b/test_elixir_script/integration_test.exs index 504bf310..550ac254 100644 --- a/test_elixir_script/integration_test.exs +++ b/test_elixir_script/integration_test.exs @@ -1,6 +1,10 @@ defmodule ElixirScript.Test.Test do use ElixirScript.Test + test "Something" do + assert {:ok, 2} = {:ok, 1} + end + test "Atom.to_string" do val = Atom.to_string(:atom) assert val == "atom" From ad8ab30601f2df623fc2741ede2e3e6b327a90f7 Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Sat, 28 Oct 2017 10:42:13 -0500 Subject: [PATCH 792/860] Add setup and setup_all --- lib/elixir_script_test/test.ex | 45 +++++++++++++-- package.json | 10 ++-- priv/testrunner/testRunner.js | 43 +++++++++++++- priv/testrunner/vendor.build.js | 66 ++++++++++++++++++++++ priv/testrunner/vendor.js | 7 +++ rollup.config.js | 74 ++++++++++++++++--------- test_elixir_script/integration_test.exs | 6 +- yarn.lock | 8 +++ 8 files changed, 220 insertions(+), 39 deletions(-) create mode 100644 priv/testrunner/vendor.build.js create mode 100644 priv/testrunner/vendor.js diff --git a/lib/elixir_script_test/test.ex b/lib/elixir_script_test/test.ex index c3618700..0d7b95c6 100644 --- a/lib/elixir_script_test/test.ex +++ b/lib/elixir_script_test/test.ex @@ -2,13 +2,44 @@ defmodule ElixirScript.Test do @doc false defmacro __using__(_opts) do quote do - import unquote(__MODULE__), only: [test: 2, test: 3] + import unquote(__MODULE__), only: [test: 2, test: 3, setup: 1, setup: 2, setup_all: 1, setup_all: 2] import ExUnit.Assertions def __elixir_script_test_module__(), do: true end end + defmacro setup_all(context \\ quote(do: _), contents) do + do_setup(context, contents, :__elixirscript_test_setup_all) + end + + defmacro setup(context \\ quote(do: _), contents) do + do_setup(context, contents, :__elixirscript_test_setup) + end + + defp do_setup(context, contents, name) do + contents = + case contents do + [do: block] -> + quote do + unquote(block) + end + _ -> + quote do + try(unquote(contents)) + end + end + + context = Macro.escape(context) + contents = Macro.escape(contents, unquote: true) + + quote bind_quoted: [context: context, contents: contents, name: name] do + def unquote(name)(unquote(context)) do + unquote(contents) + end + end + end + defmacro test(message, context \\ quote(do: _), contents) do contents = case contents do @@ -30,7 +61,7 @@ defmodule ElixirScript.Test do |> String.replace(" ", "_") |> String.replace(~r/[^A-Za-z0-9]/, "") - name = String.to_atom("__test_#{name}") + name = String.to_atom("__elixirscript_test_case_#{name}") quote bind_quoted: [context: context, contents: contents, message: message, name: name] do def unquote(name)(unquote(context)) do @@ -56,9 +87,7 @@ defmodule ElixirScript.Test do |> Path.join("Elixir.*.js") |> Path.wildcard() - test_script_path = Path.join([:code.priv_dir(:elixir_script), "testrunner", "index.js"]) - - {_, exit_status} = System.cmd "node", [test_script_path] ++ js_files, into: IO.stream(:stdio, :line) + exit_status = node_test_runner(js_files) # Delete directory at the end File.rm_rf!(output) @@ -70,4 +99,10 @@ defmodule ElixirScript.Test do :error end end + + defp node_test_runner(js_files) do + test_script_path = Path.join([:code.priv_dir(:elixir_script), "testrunner", "index.js"]) + {_, exit_status} = System.cmd "node", [test_script_path] ++ js_files, into: IO.stream(:stdio, :line) + exit_status + end end diff --git a/package.json b/package.json index c88a5ed1..1b4d76ef 100644 --- a/package.json +++ b/package.json @@ -11,9 +11,8 @@ }, "scripts": { "lint": "eslint src/javascript/lib/**/*.js src/javascript/tests/**/*.js", - "lint:fix": - "eslint src/javascript/lib/**/*.js src/javascript/tests/**/*.js --fix", - "build": "rollup -c rollup.config.js", + "lint:fix": "eslint src/javascript/lib/**/*.js src/javascript/tests/**/*.js --fix", + "build": "node rollup.config.js", "clean": "rm -rf priv/build", "test": "nyc ava src/javascript/tests" }, @@ -24,6 +23,7 @@ "author": "", "license": "MIT", "dependencies": { + "chalk": "^2.3.0", "erlang-types": "^1.0.1", "grapheme-splitter": "^1.0.2", "rollup-plugin-commonjs": "^8.2.1", @@ -45,7 +45,9 @@ "rollup-plugin-node-resolve": "^3.0.0" }, "ava": { - "require": ["babel-register"], + "require": [ + "babel-register" + ], "babel": { "babelrc": true } diff --git a/priv/testrunner/testRunner.js b/priv/testrunner/testRunner.js index 992444d2..60014c5b 100644 --- a/priv/testrunner/testRunner.js +++ b/priv/testrunner/testRunner.js @@ -1,4 +1,5 @@ import Colors from './colors.js'; +import Vendor from './vendor.build.js'; async function start(files) { const results = { @@ -17,11 +18,47 @@ async function start(files) { return results; } +function runSetup(mod, name, incomingContext = new Map()) { + if (mod.default[name]) { + const result = mod.default[name](incomingContext); + + return resolveContext(result, incomingContext); + } + + return incomingContext; +} + +function resolveContext(context, parentContext) { + if (context === Symbol.for('ok')) { + return parentContext; + } else if (context instanceof Vendor.ErlangTypes.Tuple && context.get(0) === Symbol.for('ok')) { + return resolveContext(context.get(1), parentContext); + } else if (context instanceof Map) { + return new Map([...parentContext, ...context]); + } else if (Array.isArray(context)) { + return mergeContextKeywordList(context, parentContext); + } + + throw new Error('Invalid context'); +} + +function mergeContextKeywordList(context, parentContext) { + const newContext = new Map([...parentContext]); + + for (const entry of context) { + newContext.set(entry.get(0), entry.get(1)); + } + + return newContext; +} + function runTests(mod, results) { - const context = []; + const contextSetupAll = runSetup(mod, '__elixirscript_test_setup_all'); for (const key of Object.keys(mod.default)) { - if (key.startsWith('__test_')) { + const context = runSetup(mod, '__elixirscript_test_setup', contextSetupAll); + + if (key.startsWith('__elixirscript_test_case')) { results.tests++; const test = mod.default[key](context); try { @@ -54,7 +91,7 @@ function handleError(e, test, results, mod) { printErrorLine(right, 'right'); } } else { - console.error(e.message); + console.log(e); } } diff --git a/priv/testrunner/vendor.build.js b/priv/testrunner/vendor.build.js new file mode 100644 index 00000000..65b2d07d --- /dev/null +++ b/priv/testrunner/vendor.build.js @@ -0,0 +1,66 @@ +import os from'os';class Tuple{constructor(...a){this.values=Object.freeze(a),this.length=this.values.length}get(a){return this.values[a]}count(){return this.values.length}[Symbol.iterator](){return this.values[Symbol.iterator]()}toString(){let a,b='';for(a=0;a'}}let ref_counter=-1;class Reference{constructor(){++ref_counter,this.id=ref_counter,this.ref=Symbol()}toString(){return'Ref#<0.0.0.'+this.id+'>'}}class BitString{constructor(...a){this.value=Object.freeze(this.process(a)),this.length=this.value.length,this.bit_size=8*this.length,this.byte_size=this.length}get(a){return this.value[a]}count(){return this.value.length}slice(a,b=null){let c=this.value.slice(a,b),d=c.map((a)=>BitString.integer(a));return new BitString(...d)}[Symbol.iterator](){return this.value[Symbol.iterator]()}toString(){var a,b='';for(a=0;a>'}process(a){let b=[];var c;for(c=0;cb?c.push(b):2048>b?c.push(192|b>>6,128|63&b):55296>b||57344<=b?c.push(224|b>>12,128|63&b>>6,128|63&b):(d++,b=65536+((1023&b)<<10|1023&a.charCodeAt(d)),c.push(240|b>>18,128|63&b>>12,128|63&b>>6,128|63&b));return c}static toUTF16Array(a){for(var b,c=[],d=0;d=b?(c.push(0),c.push(b)):(c.push(255&b>>8),c.push(255&b));return c}static toUTF32Array(a){for(var b,c=[],d=0;d=b?(c.push(0),c.push(0),c.push(0),c.push(b)):(c.push(0),c.push(0),c.push(255&b>>8),c.push(255&b));return c}//http://stackoverflow.com/questions/2003493/javascript-float-from-to-bits +static float32ToBytes(a){var b=[],c=new ArrayBuffer(4);new Float32Array(c)[0]=a;let d=new Uint32Array(c)[0];return b.push(255&d>>24),b.push(255&d>>16),b.push(255&d>>8),b.push(255&d),b}static float64ToBytes(a){var b=[],c=new ArrayBuffer(8);new Float64Array(c)[0]=a;var d=new Uint32Array(c)[0],e=new Uint32Array(c)[1];return b.push(255&e>>24),b.push(255&e>>16),b.push(255&e>>8),b.push(255&e),b.push(255&d>>24),b.push(255&d>>16),b.push(255&d>>8),b.push(255&d),b}}var ErlangTypes={Tuple,PID,Reference,BitString};function createCommonjsModule(a,b){return b={exports:{}},a(b,b.exports),b.exports}var matchOperatorsRe=/[|\\{}()[\]^$+*?.]/g,escapeStringRegexp=function(a){if('string'!=typeof a)throw new TypeError('Expected a string');return a.replace(matchOperatorsRe,'\\$&')},colorName={aliceblue:[240,248,255],antiquewhite:[250,235,215],aqua:[0,255,255],aquamarine:[127,255,212],azure:[240,255,255],beige:[245,245,220],bisque:[255,228,196],black:[0,0,0],blanchedalmond:[255,235,205],blue:[0,0,255],blueviolet:[138,43,226],brown:[165,42,42],burlywood:[222,184,135],cadetblue:[95,158,160],chartreuse:[127,255,0],chocolate:[210,105,30],coral:[255,127,80],cornflowerblue:[100,149,237],cornsilk:[255,248,220],crimson:[220,20,60],cyan:[0,255,255],darkblue:[0,0,139],darkcyan:[0,139,139],darkgoldenrod:[184,134,11],darkgray:[169,169,169],darkgreen:[0,100,0],darkgrey:[169,169,169],darkkhaki:[189,183,107],darkmagenta:[139,0,139],darkolivegreen:[85,107,47],darkorange:[255,140,0],darkorchid:[153,50,204],darkred:[139,0,0],darksalmon:[233,150,122],darkseagreen:[143,188,143],darkslateblue:[72,61,139],darkslategray:[47,79,79],darkslategrey:[47,79,79],darkturquoise:[0,206,209],darkviolet:[148,0,211],deeppink:[255,20,147],deepskyblue:[0,191,255],dimgray:[105,105,105],dimgrey:[105,105,105],dodgerblue:[30,144,255],firebrick:[178,34,34],floralwhite:[255,250,240],forestgreen:[34,139,34],fuchsia:[255,0,255],gainsboro:[220,220,220],ghostwhite:[248,248,255],gold:[255,215,0],goldenrod:[218,165,32],gray:[128,128,128],green:[0,128,0],greenyellow:[173,255,47],grey:[128,128,128],honeydew:[240,255,240],hotpink:[255,105,180],indianred:[205,92,92],indigo:[75,0,130],ivory:[255,255,240],khaki:[240,230,140],lavender:[230,230,250],lavenderblush:[255,240,245],lawngreen:[124,252,0],lemonchiffon:[255,250,205],lightblue:[173,216,230],lightcoral:[240,128,128],lightcyan:[224,255,255],lightgoldenrodyellow:[250,250,210],lightgray:[211,211,211],lightgreen:[144,238,144],lightgrey:[211,211,211],lightpink:[255,182,193],lightsalmon:[255,160,122],lightseagreen:[32,178,170],lightskyblue:[135,206,250],lightslategray:[119,136,153],lightslategrey:[119,136,153],lightsteelblue:[176,196,222],lightyellow:[255,255,224],lime:[0,255,0],limegreen:[50,205,50],linen:[250,240,230],magenta:[255,0,255],maroon:[128,0,0],mediumaquamarine:[102,205,170],mediumblue:[0,0,205],mediumorchid:[186,85,211],mediumpurple:[147,112,219],mediumseagreen:[60,179,113],mediumslateblue:[123,104,238],mediumspringgreen:[0,250,154],mediumturquoise:[72,209,204],mediumvioletred:[199,21,133],midnightblue:[25,25,112],mintcream:[245,255,250],mistyrose:[255,228,225],moccasin:[255,228,181],navajowhite:[255,222,173],navy:[0,0,128],oldlace:[253,245,230],olive:[128,128,0],olivedrab:[107,142,35],orange:[255,165,0],orangered:[255,69,0],orchid:[218,112,214],palegoldenrod:[238,232,170],palegreen:[152,251,152],paleturquoise:[175,238,238],palevioletred:[219,112,147],papayawhip:[255,239,213],peachpuff:[255,218,185],peru:[205,133,63],pink:[255,192,203],plum:[221,160,221],powderblue:[176,224,230],purple:[128,0,128],rebeccapurple:[102,51,153],red:[255,0,0],rosybrown:[188,143,143],royalblue:[65,105,225],saddlebrown:[139,69,19],salmon:[250,128,114],sandybrown:[244,164,96],seagreen:[46,139,87],seashell:[255,245,238],sienna:[160,82,45],silver:[192,192,192],skyblue:[135,206,235],slateblue:[106,90,205],slategray:[112,128,144],slategrey:[112,128,144],snow:[255,250,250],springgreen:[0,255,127],steelblue:[70,130,180],tan:[210,180,140],teal:[0,128,128],thistle:[216,191,216],tomato:[255,99,71],turquoise:[64,224,208],violet:[238,130,238],wheat:[245,222,179],white:[255,255,255],whitesmoke:[245,245,245],yellow:[255,255,0],yellowgreen:[154,205,50]},conversions=createCommonjsModule(function(a){/** + * See https://en.m.wikipedia.org/wiki/Euclidean_distance#Squared_Euclidean_distance + * */function comparativeDistance(a,b){return f(a[0]-b[0],2)+f(a[1]-b[1],2)+f(a[2]-b[2],2)}var c=Math.round,d=Math.PI,e=Math.floor,f=Math.pow,i=Math.max,j=Math.min,b={};/* MIT license */// NOTE: conversions should only return primitive values (i.e. arrays, or +// values that give correct `typeof` results). +// do not use box values types (i.e. Number(), String(), etc.) +for(var g in colorName)colorName.hasOwnProperty(g)&&(b[colorName[g]]=g);var k=a.exports={rgb:{channels:3,labels:'rgb'},hsl:{channels:3,labels:'hsl'},hsv:{channels:3,labels:'hsv'},hwb:{channels:3,labels:'hwb'},cmyk:{channels:4,labels:'cmyk'},xyz:{channels:3,labels:'xyz'},lab:{channels:3,labels:'lab'},lch:{channels:3,labels:'lch'},hex:{channels:1,labels:['hex']},keyword:{channels:1,labels:['keyword']},ansi16:{channels:1,labels:['ansi16']},ansi256:{channels:1,labels:['ansi256']},hcg:{channels:3,labels:['h','c','g']},apple:{channels:3,labels:['r16','g16','b16']},gray:{channels:1,labels:['gray']}};// hide .channels and .labels properties +for(var h in k)if(k.hasOwnProperty(h)){if(!('channels'in k[h]))throw new Error('missing channels property: '+h);if(!('labels'in k[h]))throw new Error('missing channel labels property: '+h);if(k[h].labels.length!==k[h].channels)throw new Error('channel and label counts mismatch: '+h);var l=k[h].channels,m=k[h].labels;delete k[h].channels,delete k[h].labels,Object.defineProperty(k[h],'channels',{value:l}),Object.defineProperty(k[h],'labels',{value:m})}k.rgb.hsl=function(a){var c,d,e,f=a[0]/255,h=a[1]/255,g=a[2]/255,b=j(f,h,g),k=i(f,h,g),l=k-b;return k===b?c=0:f===k?c=(h-g)/l:h===k?c=2+(g-f)/l:g===k&&(c=4+(f-h)/l),c=j(60*c,360),0>c&&(c+=360),e=(b+k)/2,d=k===b?0:0.5>=e?l/(k+b):l/(2-k-b),[c,100*d,100*e]},k.rgb.hsv=function(a){var c,d,e,f=a[0],h=a[1],g=a[2],b=j(f,h,g),k=i(f,h,g),l=k-b;return d=0===k?0:1e3*(l/k)/10,k===b?c=0:f===k?c=(h-g)/l:h===k?c=2+(g-f)/l:g===k&&(c=4+(f-h)/l),c=j(60*c,360),0>c&&(c+=360),e=1e3*(k/255)/10,[c,d,e]},k.rgb.hwb=function(a){var c=a[0],d=a[1],e=a[2],b=k.rgb.hsl(a)[0],f=1/255*j(c,j(d,e));return e=1-1/255*i(c,i(d,e)),[b,100*f,100*e]},k.rgb.cmyk=function(a){var d,c,e,f,h=a[0]/255,i=a[1]/255,g=a[2]/255;return f=j(1-h,1-i,1-g),d=(1-h-f)/(1-f)||0,c=(1-i-f)/(1-f)||0,e=(1-g-f)/(1-f)||0,[100*d,100*c,100*e,100*f]},k.rgb.keyword=function(a){var c=b[a];if(c)return c;var d,e=Infinity;for(var f in colorName)if(colorName.hasOwnProperty(f)){var g=colorName[f],h=comparativeDistance(a,g);// Compute comparative distance +// Check if its less, if so set as closest +hj?j*(1+h):j+h-j*h,b=2*j-c,e=[0,0,0];for(var k=0;3>k;k++)d=g+1/3*-(k-1),0>d&&d++,16*d?b+6*(c-b)*d:1>2*d?c:2>3*d?b+6*((c-b)*(2/3-d)):b,e[k]=255*f;return e},k.hsl.hsv=function(a){var b,c,d=a[0],e=a[1]/100,f=a[2]/100,g=e,h=i(f,0.01);return f*=2,e*=1>=f?f:2-f,g*=1>=h?h:2-h,c=(f+e)/2,b=0==f?2*g/(h+g):2*e/(f+e),[d,100*b,100*c]},k.hsv.rgb=function(a){var b=a[0]/60,c=a[1]/100,d=a[2]/100,g=e(b)%6,h=b-e(b),f=255*d*(1-c),i=255*d*(1-c*h),j=255*d*(1-c*(1-h));return d*=255,0==g?[d,j,f]:1==g?[i,d,f]:2==g?[f,d,j]:3==g?[f,i,d]:4==g?[j,f,d]:5==g?[d,f,i]:void 0},k.hsv.hsl=function(a){var b,c,d,e=a[0],f=a[1]/100,g=a[2]/100,h=i(g,0.01);return d=(2-f)*g,b=(2-f)*h,c=f*h,c/=1>=b?b:2-b,c=c||0,d/=2,[e,100*c,100*d]},k.hwb.rgb=function(a){var c,d,i,f,j=a[0]/360,h=a[1]/100,k=a[2]/100,l=h+k;// wh + bl cant be > 1 +1g&&(g+=360),h=Math.sqrt(i*i+a*a),[c,h,g]},k.lch.lab=function(e){var f,a,b,g=e[0],i=e[1],c=e[2];return b=2*(c/360)*d,f=i*Math.cos(b),a=i*Math.sin(b),[g,f,a]},k.rgb.ansi16=function(a){var d=a[0],e=a[1],f=a[2],b=1 in arguments?arguments[1]:k.rgb.hsv(a)[2];// hsv -> ansi16 optimization +if(b=c(b/50),0===b)return 30;var g=30+(c(f/255)<<2|c(e/255)<<1|c(d/255));return 2===b&&(g+=60),g},k.hsv.ansi16=function(a){// optimization here; we already know the value and don't need to get +// it converted for us. +return k.rgb.ansi16(k.hsv.rgb(a),a[2])},k.rgb.ansi256=function(a){var d=a[0],e=a[1],f=a[2];// we use the extended greyscale palette here, with the exception of +// black and white. normal palette only has 4 greyscale shades. +if(d===e&&e===f)return 8>d?16:248>1)*d),g=255*((1&c>>2)*d);return[e,f,g]},k.ansi256.rgb=function(a){// handle greyscale +if(232<=a){var d=10*(a-232)+8;return[d,d,d]}a-=16;var c,f=255*(e(a/36)/5),h=255*(e((c=a%36)/6)/5),g=255*(c%6/5);return[f,h,g]},k.rgb.hex=function(a){var b=((255&c(a[0]))<<16)+((255&c(a[1]))<<8)+(255&c(a[2])),d=b.toString(16).toUpperCase();return'000000'.substring(d.length)+d},k.hex.rgb=function(a){var b=a.toString(16).match(/[a-f0-9]{6}|[a-f0-9]{3}/i);if(!b)return[0,0,0];var c=b[0];3===b[0].length&&(c=c.split('').map(function(a){return a+a}).join(''));var d=parseInt(c,16);return[255&d>>16,255&d>>8,255&d]},k.rgb.hcg=function(a){var c,d,e=a[0]/255,f=a[1]/255,g=a[2]/255,b=i(i(e,f),g),h=j(j(e,f),g),k=b-h;return c=1>k?h/(1-k):0,d=0>=k?0:b===e?(f-g)/k%6:b===f?2+(g-e)/k:4+(e-f)/k+4,d/=6,d%=1,[360*d,100*k,100*c]},k.hsl.hcg=function(a){var b=a[1]/100,d=a[2]/100,e=1,c=0;return e=0.5>d?2*b*d:2*b*(1-d),1>e&&(c=(d-0.5*e)/(1-e)),[a[0],100*e,100*c]},k.hsv.hcg=function(a){var b=a[1]/100,d=a[2]/100,e=b*d,c=0;return 1>e&&(c=(d-e)/(1-e)),[a[0],100*e,100*c]},k.hcg.rgb=function(a){var b=a[0]/360,d=a[1]/100,c=a[2]/100;if(0==d)return[255*c,255*c,255*c];var f=[0,0,0],g=6*(b%1),h=g%1,i=1-h,j=0;switch(e(g)){case 0:f[0]=1,f[1]=h,f[2]=0;break;case 1:f[0]=i,f[1]=1,f[2]=0;break;case 2:f[0]=0,f[1]=1,f[2]=h;break;case 3:f[0]=0,f[1]=i,f[2]=1;break;case 4:f[0]=h,f[1]=0,f[2]=1;break;default:f[0]=1,f[1]=0,f[2]=i;}return j=(1-d)*c,[255*(d*f[0]+j),255*(d*f[1]+j),255*(d*f[2]+j)]},k.hcg.hsv=function(a){var b=a[1]/100,c=a[2]/100,d=b+c*(1-b),e=0;return 0d?e=b/(2*d):0.5<=d&&1>d&&(e=b/(2*(1-d))),[a[0],100*e,100*d]},k.hcg.hwb=function(a){var b=a[1]/100,c=a[2]/100,d=b+c*(1-b);return[a[0],100*(d-b),100*(1-d)]},k.hwb.hcg=function(a){var d=a[1]/100,e=a[2]/100,b=1-e,f=b-d,c=0;return 1>f&&(c=(b-f)/(1-f)),[a[0],100*f,100*c]},k.apple.rgb=function(a){return[255*(a[0]/65535),255*(a[1]/65535),255*(a[2]/65535)]},k.rgb.apple=function(a){return[65535*(a[0]/255),65535*(a[1]/255),65535*(a[2]/255)]},k.gray.rgb=function(a){return[255*(a[0]/100),255*(a[0]/100),255*(a[0]/100)]},k.gray.hsl=k.gray.hsv=function(a){return[0,0,a[0]]},k.gray.hwb=function(a){return[0,100,a[0]]},k.gray.cmyk=function(a){return[0,0,0,a[0]]},k.gray.lab=function(a){return[a[0],0,0]},k.gray.hex=function(a){var b=255&c(255*(a[0]/100)),d=((b<<16)+(b<<8)+b).toString(16).toUpperCase();return'000000'.substring(d.length)+d},k.rgb.gray=function(a){var b=(a[0]+a[1]+a[2])/3;return[100*(b/255)]}}),models$1=Object.keys(conversions);/* + this function routes a model to all other models. + + all functions that are routed have a property `.conversion` attached + to the returned synthetic function. This property is an array + of strings, each with the steps in between the 'from' and 'to' + color models (inclusive). + + conversions that are not possible simply are not included. +*/// https://jsperf.com/object-keys-vs-for-in-with-closure/3 +function buildGraph(){for(var a={},b=models$1.length,c=0;c queue -> pop +for(b[a].distance=0;c.length;)for(var d=c.pop(),e=Object.keys(conversions[d]),f=e.length,g=0;gfunction(){const c=a.apply(colorConvert,arguments);return`\u001B[${c+b}m`},c=(a,b)=>function(){const c=a.apply(colorConvert,arguments);return`\u001B[${38+b};5;${c}m`},d=(a,b)=>function(){const c=a.apply(colorConvert,arguments);return`\u001B[${38+b};2;${c[0]};${c[1]};${c[2]}m`};Object.defineProperty(a,'exports',{enumerable:!0,get:function assembleStyles(){const a={modifier:{reset:[0,0],// 21 isn't widely supported and 22 does the same thing +bold:[1,22],dim:[2,22],italic:[3,23],underline:[4,24],inverse:[7,27],hidden:[8,28],strikethrough:[9,29]},color:{black:[30,39],red:[31,39],green:[32,39],yellow:[33,39],blue:[34,39],magenta:[35,39],cyan:[36,39],white:[37,39],gray:[90,39],// Bright color +redBright:[91,39],greenBright:[92,39],yellowBright:[93,39],blueBright:[94,39],magentaBright:[95,39],cyanBright:[96,39],whiteBright:[97,39]},bgColor:{bgBlack:[40,49],bgRed:[41,49],bgGreen:[42,49],bgYellow:[43,49],bgBlue:[44,49],bgMagenta:[45,49],bgCyan:[46,49],bgWhite:[47,49],// Bright color +bgBlackBright:[100,49],bgRedBright:[101,49],bgGreenBright:[102,49],bgYellowBright:[103,49],bgBlueBright:[104,49],bgMagentaBright:[105,49],bgCyanBright:[106,49],bgWhiteBright:[107,49]}};// Fix humans +a.color.grey=a.color.gray,Object.keys(a).forEach((b)=>{const c=a[b];Object.keys(c).forEach((b)=>{const d=c[b];a[b]={open:`\u001B[${d[0]}m`,close:`\u001B[${d[1]}m`},c[b]=a[b]}),Object.defineProperty(a,b,{value:c,enumerable:!1})});const e=(a,c,d)=>[a,c,d];a.color.close='\x1B[39m',a.bgColor.close='\x1B[49m',a.color.ansi={},a.color.ansi256={},a.color.ansi16m={rgb:d(e,0)},a.bgColor.ansi={},a.bgColor.ansi256={},a.bgColor.ansi16m={rgb:d(e,10)};for(const e of Object.keys(colorConvert)){if('object'!=typeof colorConvert[e])continue;const f=colorConvert[e];'ansi16'in f&&(a.color.ansi[e]=b(f.ansi16,0),a.bgColor.ansi[e]=b(f.ansi16,10)),'ansi256'in f&&(a.color.ansi256[e]=c(f.ansi256,0),a.bgColor.ansi256[e]=c(f.ansi256,10)),'rgb'in f&&(a.color.ansi16m[e]=d(f.rgb,0),a.bgColor.ansi16m[e]=d(f.rgb,10))}return a}})});var hasFlag=function(a,b){b=b||process.argv;var c=b.indexOf('--'),d=/^-{1,2}/.test(a)?'':'--',e=b.indexOf(d+a);return-1!==e&&(!(-1!==c)||e{if(hasFlag('no-color')||hasFlag('no-colors')||hasFlag('color=false'))return 0;if(hasFlag('color=16m')||hasFlag('color=full')||hasFlag('color=truecolor'))return 3;if(hasFlag('color=256'))return 2;if(hasFlag('color')||hasFlag('colors')||hasFlag('color=true')||hasFlag('color=always'))return 1;if(process.stdout&&!process.stdout.isTTY)return 0;if('win32'===process.platform){// Node.js 7.5.0 is the first version of Node.js to include a patch to +// libuv that enables 256 color output on Windows. Anything earlier and it +// won't work. However, here we target Node.js 8 at minimum as it is an LTS +// release, and Node.js 7 is not. Windows 10 build 10586 is the first Windows +// release that supports 256 colors. +const a=os.release().split('.');return 8<=+process.version.split('.')[0]&&10<=+a[0]&&10586<=+a[2]?2:1}if('CI'in b)return'TRAVIS'in b||'Travis'===b.CI||'CIRCLECI'in b?1:0;if('TEAMCITY_VERSION'in b)return /^(9\.(0*[1-9]\d*)\.|\d{2,}\.)/.test(b.TEAMCITY_VERSION)?1:0;if('TERM_PROGRAM'in b){const a=parseInt((b.TERM_PROGRAM_VERSION||'').split('.')[0],10);switch(b.TERM_PROGRAM){case'iTerm.app':return 3<=a?3:2;case'Hyper':return 3;case'Apple_Terminal':return 2;// No default +}}return /^(screen|xterm)-256(?:color)?/.test(b.TERM)?2:/^screen|^xterm|^vt100|color|ansi|cygwin|linux/i.test(b.TERM)?1:'COLORTERM'in b?1:'dumb'===b.TERM?0:0})();'FORCE_COLOR'in b&&(c=0===parseInt(b.FORCE_COLOR,10)?0:c||1),a.exports=process&&((a)=>0!==a&&{level:a,hasBasic:!0,has256:2<=a,has16m:3<=a})(c)}),templates=createCommonjsModule(function(a){'use strict';function unescape(a){return'u'===a[0]&&5===a.length||'x'===a[0]&&3===a.length?String.fromCharCode(parseInt(a.slice(1),16)):f.get(a)||a}function parseArguments(a,b){const c=[],f=b.trim().split(/\s*,\s*/g);let g;for(const h of f)if(!isNaN(h))c.push(+h);else if(g=h.match(d))c.push(g[2].replace(e,(a,b,c)=>b?unescape(b):c));else throw new Error(`Invalid Chalk template style argument: ${h} (in style '${a}')`);return c}function parseStyle(a){c.lastIndex=0;const b=[];for(let d;null!==(d=c.exec(a));){const a=d[1];if(d[2]){const c=parseArguments(a,d[2]);b.push([a].concat(c))}else b.push([a])}return b}function buildStyle(a,b){const c={};for(const d of b)for(const a of d.styles)c[a[0]]=d.inverse?null:a.slice(1);let d=a;for(const e of Object.keys(c))if(Array.isArray(c[e])){if(!(e in d))throw new Error(`Unknown Chalk style: ${e}`);d=0{const d=[],e=[];let f=[];// eslint-disable-next-line max-params +if(c.replace(b,(b,c,g,h,i,j)=>{if(c)f.push(unescape(c));else if(h){const b=f.join('');f=[],e.push(0===d.length?b:buildStyle(a,d)(b)),d.push({inverse:g,styles:parseStyle(h)})}else if(i){if(0===d.length)throw new Error('Found extraneous } in Chalk template literal');e.push(buildStyle(a,d)(f.join(''))),f=[],d.pop()}else f.push(j)}),e.push(f.join('')),0=this.level||!e)return this._empty?'':e;// Turns out that on Windows dimmed gray text becomes invisible in cmd.exe, +// see https://github.com/chalk/chalk/issues/58 +// If we're on Windows and we're dealing with a gray color, temporarily make 'dim' a noop. +const a=ansiStyles.dim.open;b&&this.hasGrey&&(ansiStyles.dim.open='');for(const a of this._styles.slice().reverse())e=a.open+e.replace(a.closeRe,a.open)+a.close,e=e.replace(/\r?\n/g,`${a.close}$&${a.open}`);// Reset the original `dim` if we changed it to work around the Windows dimmed gray issue +return ansiStyles.dim.open=a,e}function chalkTag(a,b){if(!Array.isArray(b))// If chalk() was called by itself or with a string, +// return the string itself as a string. +return[].slice.call(arguments,1).join(' ');const c=[].slice.call(arguments,2),d=[b.raw[0]];for(let e=1;e{},e);Object.defineProperties(Chalk.prototype,e),a.exports=Chalk(),a.exports.supportsColor=supportsColor,a.exports.default=a.exports}// For TypeScript +),vendor={ErlangTypes,Chalk:chalk};export default vendor; diff --git a/priv/testrunner/vendor.js b/priv/testrunner/vendor.js new file mode 100644 index 00000000..7e3cd354 --- /dev/null +++ b/priv/testrunner/vendor.js @@ -0,0 +1,7 @@ +import ErlangTypes from 'erlang-types'; +import Chalk from 'chalk'; + +export default { + ErlangTypes, + Chalk, +}; diff --git a/rollup.config.js b/rollup.config.js index ced74194..58a95b70 100644 --- a/rollup.config.js +++ b/rollup.config.js @@ -1,27 +1,49 @@ -import nodeResolve from 'rollup-plugin-node-resolve'; -import commonjs from 'rollup-plugin-commonjs'; -import babel from 'rollup-plugin-babel'; -import minify from 'rollup-plugin-babel-minify'; +const rollup = require('rollup'); +const babel = require('rollup-plugin-babel'); +const nodeResolve = require('rollup-plugin-node-resolve'); +const commonjs = require('rollup-plugin-commonjs'); +const minify = require('rollup-plugin-babel-minify'); -export default { - input: 'src/javascript/elixir.js', - name: 'ElixirScript', - plugins: [ - nodeResolve({ - jsnext: true, - main: true, - }), - commonjs(), - babel({ - babelrc: false, - }), - minify({ - keepFnName: true, - keepClassName: true, - }), - ], - output: [ - { file: 'priv/build/iife/ElixirScript.Core.js', format: 'iife' }, - { file: 'priv/build/es/ElixirScript.Core.js', format: 'es', sourcemap: 'inline' }, - ], -}; +const plugins = [ + nodeResolve({ + jsnext: true, + main: true, + }), + commonjs(), + babel({ + babelrc: false, + }), + minify({ + keepFnName: true, + keepClassName: true, + }), +]; + +rollup + .rollup({ + input: 'src/javascript/elixir.js', + output: 'priv/build/es/ElixirScript.Core.js', + sourcemap: 'inline', + format: 'es', + plugins, + }) + .then((bundle) => { + bundle.write({ + format: 'es', + file: 'priv/build/es/ElixirScript.Core.js', + }); + }); + +rollup + .rollup({ + input: 'priv/testrunner/vendor.js', + output: 'priv/testrunner/vendor.build.js', + format: 'es', + plugins, + }) + .then((bundle) => { + bundle.write({ + format: 'es', + file: 'priv/testrunner/vendor.build.js', + }); + }); diff --git a/test_elixir_script/integration_test.exs b/test_elixir_script/integration_test.exs index 550ac254..bdaa33b6 100644 --- a/test_elixir_script/integration_test.exs +++ b/test_elixir_script/integration_test.exs @@ -1,6 +1,10 @@ -defmodule ElixirScript.Test.Test do +defmodule ElixirScript.Integration.Test do use ElixirScript.Test + setup do + [item: true] + end + test "Something" do assert {:ok, 2} = {:ok, 1} end diff --git a/yarn.lock b/yarn.lock index 9aec577d..ec2b01e5 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1264,6 +1264,14 @@ chalk@^2.1.0: escape-string-regexp "^1.0.5" supports-color "^4.0.0" +chalk@^2.3.0: + version "2.3.0" + resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.3.0.tgz#b5ea48efc9c1793dccc9b4767c93914d3f2d52ba" + dependencies: + ansi-styles "^3.1.0" + escape-string-regexp "^1.0.5" + supports-color "^4.0.0" + chokidar@^1.4.2: version "1.7.0" resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-1.7.0.tgz#798e689778151c8076b4b360e5edd28cda2bb468" From 9ab8b441f282a201d3fdd0055bb8616427a7cc3c Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Sat, 28 Oct 2017 10:42:36 -0500 Subject: [PATCH 793/860] Add setup and setup_all --- test_elixir_script/integration_test.exs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test_elixir_script/integration_test.exs b/test_elixir_script/integration_test.exs index bdaa33b6..737997a5 100644 --- a/test_elixir_script/integration_test.exs +++ b/test_elixir_script/integration_test.exs @@ -6,7 +6,7 @@ defmodule ElixirScript.Integration.Test do end test "Something" do - assert {:ok, 2} = {:ok, 1} + assert {:ok, _} = {:ok, 1} end test "Atom.to_string" do From c86e3229a44f349c50d01e0c09ae4ce6a95c38fa Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Sat, 28 Oct 2017 13:14:14 -0500 Subject: [PATCH 794/860] Refactoring test macros. Add teardown and teardown_all --- lib/elixir_script_test/test.ex | 76 ++------------ .../test/assertion_error.ex | 3 - lib/elixir_script_test/test/assertions.ex | 7 -- lib/elixir_script_test/test/callbacks.ex | 99 +++++++++++++++++++ priv/testrunner/testRunner.js | 42 +++++--- test_elixir_script/integration_test.exs | 4 - 6 files changed, 139 insertions(+), 92 deletions(-) delete mode 100644 lib/elixir_script_test/test/assertion_error.ex delete mode 100644 lib/elixir_script_test/test/assertions.ex create mode 100644 lib/elixir_script_test/test/callbacks.ex diff --git a/lib/elixir_script_test/test.ex b/lib/elixir_script_test/test.ex index 0d7b95c6..96f82173 100644 --- a/lib/elixir_script_test/test.ex +++ b/lib/elixir_script_test/test.ex @@ -2,81 +2,23 @@ defmodule ElixirScript.Test do @doc false defmacro __using__(_opts) do quote do - import unquote(__MODULE__), only: [test: 2, test: 3, setup: 1, setup: 2, setup_all: 1, setup_all: 2] + import ElixirScript.Test.Callbacks, only: [ + test: 2, test: 3, + setup: 1, setup: 2, + setup_all: 1, setup_all: 2, + teardown: 1, teardown: 2, + teardown_all: 1, teardown_all: 2 + ] import ExUnit.Assertions - def __elixir_script_test_module__(), do: true - end - end - - defmacro setup_all(context \\ quote(do: _), contents) do - do_setup(context, contents, :__elixirscript_test_setup_all) - end - - defmacro setup(context \\ quote(do: _), contents) do - do_setup(context, contents, :__elixirscript_test_setup) - end - - defp do_setup(context, contents, name) do - contents = - case contents do - [do: block] -> - quote do - unquote(block) - end - _ -> - quote do - try(unquote(contents)) - end - end - - context = Macro.escape(context) - contents = Macro.escape(contents, unquote: true) - - quote bind_quoted: [context: context, contents: contents, name: name] do - def unquote(name)(unquote(context)) do - unquote(contents) - end - end - end - - defmacro test(message, context \\ quote(do: _), contents) do - contents = - case contents do - [do: block] -> - quote do - unquote(block) - :ok - end - _ -> - quote do - try(unquote(contents)) - :ok - end - end - - context = Macro.escape(context) - contents = Macro.escape(contents, unquote: true) - name = message - |> String.replace(" ", "_") - |> String.replace(~r/[^A-Za-z0-9]/, "") - - name = String.to_atom("__elixirscript_test_case_#{name}") - - quote bind_quoted: [context: context, contents: contents, message: message, name: name] do - def unquote(name)(unquote(context)) do - %{ - message: unquote(message), - test: fn(context) -> unquote(contents) end - } - end + def __elixirscript_test_module__(), do: true end end @doc """ Runs tests found in the given path. Accepts wildcards """ - def start(path, opts \\ %{}) do + def start(path, _opts \\ %{}) do output = Path.join([System.tmp_dir!(), "elixirscript_tests"]) File.mkdir_p!(output) diff --git a/lib/elixir_script_test/test/assertion_error.ex b/lib/elixir_script_test/test/assertion_error.ex deleted file mode 100644 index 3a88fde2..00000000 --- a/lib/elixir_script_test/test/assertion_error.ex +++ /dev/null @@ -1,3 +0,0 @@ -defmodule ElixirScript.Test.AssertionError do - defexception [:message] -end diff --git a/lib/elixir_script_test/test/assertions.ex b/lib/elixir_script_test/test/assertions.ex deleted file mode 100644 index 2d8496b6..00000000 --- a/lib/elixir_script_test/test/assertions.ex +++ /dev/null @@ -1,7 +0,0 @@ -defmodule ElixirScript.Test.Assertions do - def assert(value) do - if !value do - raise ElixirScript.Test.AssertionError, message: "failed" - end - end -end diff --git a/lib/elixir_script_test/test/callbacks.ex b/lib/elixir_script_test/test/callbacks.ex new file mode 100644 index 00000000..e124a649 --- /dev/null +++ b/lib/elixir_script_test/test/callbacks.ex @@ -0,0 +1,99 @@ +defmodule ElixirScript.Test.Callbacks do + + defmacro setup_all(context \\ quote(do: _), contents) do + do_setup(context, contents, :__elixirscript_test_setup_all) + end + + defmacro setup(context \\ quote(do: _), contents) do + do_setup(context, contents, :__elixirscript_test_setup) + end + + defp do_setup(context, contents, name) do + contents = + case contents do + [do: block] -> + quote do + unquote(block) + end + _ -> + quote do + try(unquote(contents)) + end + end + + context = Macro.escape(context) + contents = Macro.escape(contents, unquote: true) + + quote bind_quoted: [context: context, contents: contents, name: name] do + def unquote(name)(unquote(context)) do + unquote(contents) + end + end + end + + defmacro teardown_all(context \\ quote(do: _), contents) do + do_teardown(context, contents, :__elixirscript_test_teardown_all) + end + + defmacro teardown(context \\ quote(do: _), contents) do + do_teardown(context, contents, :__elixirscript_test_teardown) + end + + defp do_teardown(context, contents, name) do + contents = + case contents do + [do: block] -> + quote do + unquote(block) + :ok + end + _ -> + quote do + try(unquote(contents)) + :ok + end + end + + context = Macro.escape(context) + contents = Macro.escape(contents, unquote: true) + + quote bind_quoted: [context: context, contents: contents, name: name] do + def unquote(name)(unquote(context)) do + unquote(contents) + end + end + end + + defmacro test(message, context \\ quote(do: _), contents) do + contents = + case contents do + [do: block] -> + quote do + unquote(block) + :ok + end + _ -> + quote do + try(unquote(contents)) + :ok + end + end + + context = Macro.escape(context) + contents = Macro.escape(contents, unquote: true) + name = message + |> String.replace(" ", "_") + |> String.replace(~r/[^A-Za-z0-9]/, "") + + name = String.to_atom("__elixirscript_test_case_#{name}") + + quote bind_quoted: [context: context, contents: contents, message: message, name: name] do + def unquote(name)() do + %{ + message: unquote(message), + test: fn(context) -> unquote(contents) end + } + end + end + end +end diff --git a/priv/testrunner/testRunner.js b/priv/testrunner/testRunner.js index 60014c5b..b1856c5d 100644 --- a/priv/testrunner/testRunner.js +++ b/priv/testrunner/testRunner.js @@ -10,7 +10,7 @@ async function start(files) { for (const file of files) { const mod = await import(file); - if (mod.default.__elixir_script_test_module__) { + if (mod.default.__elixirscript_test_module__) { runTests(mod, results); } } @@ -28,6 +28,12 @@ function runSetup(mod, name, incomingContext = new Map()) { return incomingContext; } +function runTeardown(mod, name, incomingContext) { + if (mod.default[name]) { + const result = mod.default[name](incomingContext); + } +} + function resolveContext(context, parentContext) { if (context === Symbol.for('ok')) { return parentContext; @@ -56,22 +62,36 @@ function runTests(mod, results) { const contextSetupAll = runSetup(mod, '__elixirscript_test_setup_all'); for (const key of Object.keys(mod.default)) { - const context = runSetup(mod, '__elixirscript_test_setup', contextSetupAll); - if (key.startsWith('__elixirscript_test_case')) { results.tests++; - const test = mod.default[key](context); - try { - test.get(Symbol.for('test'))(context); + const test = mod.default[key](); + const result = runTest(mod, test, contextSetupAll, results); + + if (result) { results.success++; - process.stdout.write(Colors.fg.Green + '.' + Colors.Reset); - } catch (e) { - results.failed++; - process.stdout.write('\n'); - handleError(e, test, results, mod); + } else { + resuls.failed++; } } } + + runTeardown(mod, '__elixirscript_test_teardown_all', contextSetupAll); +} + +function runTest(mod, test, incomingContext, results) { + const context = runSetup(mod, '__elixirscript_test_setup', incomingContext); + const testPassed = true; + try { + test.get(Symbol.for('test'))(context); + process.stdout.write(Colors.fg.Green + '.' + Colors.Reset); + } catch (e) { + process.stdout.write('\n'); + handleError(e, test, results, mod); + testPassed = false; + } + + runTeardown(mod, '__elixirscript_test_teardown', context); + return testPassed; } function handleError(e, test, results, mod) { diff --git a/test_elixir_script/integration_test.exs b/test_elixir_script/integration_test.exs index 737997a5..491d88c7 100644 --- a/test_elixir_script/integration_test.exs +++ b/test_elixir_script/integration_test.exs @@ -1,10 +1,6 @@ defmodule ElixirScript.Integration.Test do use ElixirScript.Test - setup do - [item: true] - end - test "Something" do assert {:ok, _} = {:ok, 1} end From e6b447217ed2053ed2223a08878e9eecbcda1b16 Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Sat, 28 Oct 2017 16:19:21 -0500 Subject: [PATCH 795/860] Add documentation --- lib/elixir_script_test/test.ex | 146 +++++++++++++++++------ lib/elixir_script_test/test/callbacks.ex | 18 +++ lib/mix/tasks/elixirscript.test.ex | 2 +- mix.exs | 2 +- mix.lock | 10 +- package.json | 1 - priv/testrunner/vendor.build.js | 68 +---------- priv/testrunner/vendor.js | 2 - yarn.lock | 8 -- 9 files changed, 137 insertions(+), 120 deletions(-) diff --git a/lib/elixir_script_test/test.ex b/lib/elixir_script_test/test.ex index 96f82173..60a2dee3 100644 --- a/lib/elixir_script_test/test.ex +++ b/lib/elixir_script_test/test.ex @@ -1,50 +1,124 @@ defmodule ElixirScript.Test do - @doc false - defmacro __using__(_opts) do - quote do - import ElixirScript.Test.Callbacks, only: [ - test: 2, test: 3, - setup: 1, setup: 2, - setup_all: 1, setup_all: 2, - teardown: 1, teardown: 2, - teardown_all: 1, teardown_all: 2 - ] - import ExUnit.Assertions - - def __elixirscript_test_module__(), do: true + @moduledoc """ + Unit Testing Framework for ElixirScript. + + Requires node.js 8.3.0 and above + + Uses assertions from ExUnit as well as has a similar api to ExUnit with a few differences + + ## Example + + An basic setup of a test. Modified from ExUnit's example + + ```elixir + # File: assertion_test.exs + # 1) Create a new test module (test case) and use "ElixirScript.Test". + defmodule AssertionTest do + use ElixirScript.Test + + # 2) Use the "test" macro. + test "the truth" do + assert true end end + ``` + + To run the test above, use the `ElixirScript.Test.start/1` function, giving it the path to the test + ``` + ElixirScript.Test.start("assertion_test.exs") + ``` + + ## Integration with Mix + + To run tests using mix, run `mix elixirscript.test`. This will run all tests in the test_elixir_script directory. + + + ## Callbacks + + ElixirScript defines the following callbacks - @doc """ - Runs tests found in the given path. Accepts wildcards - """ - def start(path, _opts \\ %{}) do - output = Path.join([System.tmp_dir!(), "elixirscript_tests"]) - File.mkdir_p!(output) + * setup/1 + * setup/2 + * setup_all/1 + * setup_all/2 + * teardown/1 + * teardown/2 + * teardown_all/1 + * teardown_all/2 - ElixirScript.Compiler.compile(path, [output: output]) + The `setup` and `setup_all` callbacks work exactly as they would in ExUnit. Instead of having an `on_exit` callback, + ElixirScript.Test has `teardown` callbacks. `teardown` is called after each test and `teardown_all` after all tests + in the file have run. - js_files = output - |> Path.expand - |> Path.join("Elixir.*.js") - |> Path.wildcard() + ```elixir + defmodule AssertionTest do + use ElixirScript.Test - exit_status = node_test_runner(js_files) + # run before test + setup do + admin = create_admin_function() + [admin: admin] + end - # Delete directory at the end - File.rm_rf!(output) + test "the truth", %{admin: admin} do + assert admin.is_authenticated + end - case exit_status do - 0 -> - :ok - _ -> - :error + # run after test + teardown, %{admin: admin} do + destroy_admin_function(admin) end end + ``` + """ + + + defmacro __using__(_opts) do + quote do + import ElixirScript.Test.Callbacks, only: [ + test: 2, test: 3, + setup: 1, setup: 2, + setup_all: 1, setup_all: 2, + teardown: 1, teardown: 2, + teardown_all: 1, teardown_all: 2 + ] + import ExUnit.Assertions + + def __elixirscript_test_module__(), do: true + end + end - defp node_test_runner(js_files) do - test_script_path = Path.join([:code.priv_dir(:elixir_script), "testrunner", "index.js"]) - {_, exit_status} = System.cmd "node", [test_script_path] ++ js_files, into: IO.stream(:stdio, :line) - exit_status + @doc """ + Runs tests found in the given path. Accepts wildcards + """ + @spec start(binary(), map()) :: :ok | :error + def start(path, _opts \\ %{}) do + output = Path.join([System.tmp_dir!(), "elixirscript_tests"]) + File.mkdir_p!(output) + + ElixirScript.Compiler.compile(path, [output: output]) + + js_files = output + |> Path.expand + |> Path.join("Elixir.*.js") + |> Path.wildcard() + + exit_status = node_test_runner(js_files) + + # Delete directory at the end + File.rm_rf!(output) + + case exit_status do + 0 -> + :ok + _ -> + :error end + end + + defp node_test_runner(js_files) do + test_script_path = Path.join([:code.priv_dir(:elixir_script), "testrunner", "index.js"]) + {_, exit_status} = System.cmd "node", [test_script_path] ++ js_files, into: IO.stream(:stdio, :line) + exit_status + end end diff --git a/lib/elixir_script_test/test/callbacks.ex b/lib/elixir_script_test/test/callbacks.ex index e124a649..f314c1c1 100644 --- a/lib/elixir_script_test/test/callbacks.ex +++ b/lib/elixir_script_test/test/callbacks.ex @@ -1,9 +1,18 @@ defmodule ElixirScript.Test.Callbacks do + @moduledoc """ + Defines ElixirScript.Test callbacks + """ + @doc """ + Called before all tests are run in a test file + """ defmacro setup_all(context \\ quote(do: _), contents) do do_setup(context, contents, :__elixirscript_test_setup_all) end + @doc """ + Called before each test is run in a test file + """ defmacro setup(context \\ quote(do: _), contents) do do_setup(context, contents, :__elixirscript_test_setup) end @@ -31,10 +40,16 @@ defmodule ElixirScript.Test.Callbacks do end end + @doc """ + Called after all tests are run in a test file + """ defmacro teardown_all(context \\ quote(do: _), contents) do do_teardown(context, contents, :__elixirscript_test_teardown_all) end + @doc """ + Called after each test is run in a test file + """ defmacro teardown(context \\ quote(do: _), contents) do do_teardown(context, contents, :__elixirscript_test_teardown) end @@ -64,6 +79,9 @@ defmodule ElixirScript.Test.Callbacks do end end + @doc """ + Defines a test + """ defmacro test(message, context \\ quote(do: _), contents) do contents = case contents do diff --git a/lib/mix/tasks/elixirscript.test.ex b/lib/mix/tasks/elixirscript.test.ex index 23321491..e60899d6 100644 --- a/lib/mix/tasks/elixirscript.test.ex +++ b/lib/mix/tasks/elixirscript.test.ex @@ -7,7 +7,7 @@ defmodule Mix.Tasks.Elixirscript.Test do @shortdoc "Runs ElixirScript Tests" @preferred_cli_env :test - def run(args) do + def run(_args) do Mix.Task.run "app.start" path = Path.join([default_test_path(), "**", "*_test.exs"]) diff --git a/mix.exs b/mix.exs index 573b3cb0..0ecdc707 100644 --- a/mix.exs +++ b/mix.exs @@ -4,7 +4,7 @@ defmodule ElixirScript.Mixfile do def project do [ app: :elixir_script, - version: "0.31.1", + version: "0.32.0-dev", elixir: "~> 1.5", elixirc_paths: elixirc_paths(Mix.env), deps: deps(), diff --git a/mix.lock b/mix.lock index 7f3276cd..77645618 100644 --- a/mix.lock +++ b/mix.lock @@ -1,14 +1,14 @@ %{"bunt": {:hex, :bunt, "0.2.0", "951c6e801e8b1d2cbe58ebbd3e616a869061ddadcc4863d0a2182541acae9a38", [:mix], [], "hexpm"}, "certifi": {:hex, :certifi, "2.0.0", "a0c0e475107135f76b8c1d5bc7efb33cd3815cb3cf3dea7aefdd174dabead064", [:rebar3], [], "hexpm"}, - "credo": {:hex, :credo, "0.8.6", "335f723772d35da499b5ebfdaf6b426bfb73590b6fcbc8908d476b75f8cbca3f", [:mix], [{:bunt, "~> 0.2.0", [hex: :bunt, repo: "hexpm", optional: false]}], "hexpm"}, + "credo": {:hex, :credo, "0.8.8", "990e7844a8d06ebacd88744a55853a83b74270b8a8461c55a4d0334b8e1736c9", [:mix], [{:bunt, "~> 0.2.0", [hex: :bunt, repo: "hexpm", optional: false]}], "hexpm"}, "earmark": {:hex, :earmark, "1.2.3", "206eb2e2ac1a794aa5256f3982de7a76bf4579ff91cb28d0e17ea2c9491e46a4", [:mix], [], "hexpm"}, "estree": {:hex, :estree, "2.6.1", "0a17cc0e9e35315dc4fcd79d30a746b1f3e9ed654be6084ce882ab491165ae22", [:mix], [], "hexpm"}, - "ex_doc": {:hex, :ex_doc, "0.16.3", "cd2a4cfe5d26e37502d3ec776702c72efa1adfa24ed9ce723bb565f4c30bd31a", [:mix], [{:earmark, "~> 1.1", [hex: :earmark, repo: "hexpm", optional: false]}], "hexpm"}, - "excoveralls": {:hex, :excoveralls, "0.7.2", "f69ede8c122ccd3b60afc775348a53fc8c39fe4278aee2f538f0d81cc5e7ff3a", [:mix], [{:exjsx, ">= 3.0.0", [hex: :exjsx, repo: "hexpm", optional: false]}, {:hackney, ">= 0.12.0", [hex: :hackney, repo: "hexpm", optional: false]}], "hexpm"}, + "ex_doc": {:hex, :ex_doc, "0.18.1", "37c69d2ef62f24928c1f4fdc7c724ea04aecfdf500c4329185f8e3649c915baf", [:mix], [{:earmark, "~> 1.1", [hex: :earmark, repo: "hexpm", optional: false]}], "hexpm"}, + "excoveralls": {:hex, :excoveralls, "0.7.4", "3d84b2f15a0e593159f74b19f83794b464b34817183d27965bdc6c462de014f9", [:mix], [{:exjsx, ">= 3.0.0", [hex: :exjsx, repo: "hexpm", optional: false]}, {:hackney, ">= 0.12.0", [hex: :hackney, repo: "hexpm", optional: false]}], "hexpm"}, "exjsx": {:hex, :exjsx, "4.0.0", "60548841e0212df401e38e63c0078ec57b33e7ea49b032c796ccad8cde794b5c", [:mix], [{:jsx, "~> 2.8.0", [hex: :jsx, repo: "hexpm", optional: false]}], "hexpm"}, - "hackney": {:hex, :hackney, "1.9.0", "51c506afc0a365868469dcfc79a9d0b94d896ec741cfd5bd338f49a5ec515bfe", [:rebar3], [{:certifi, "2.0.0", [hex: :certifi, repo: "hexpm", optional: false]}, {:idna, "5.1.0", [hex: :idna, repo: "hexpm", optional: false]}, {:metrics, "1.0.1", [hex: :metrics, repo: "hexpm", optional: false]}, {:mimerl, "1.0.2", [hex: :mimerl, repo: "hexpm", optional: false]}, {:ssl_verify_fun, "1.1.1", [hex: :ssl_verify_fun, repo: "hexpm", optional: false]}], "hexpm"}, + "hackney": {:hex, :hackney, "1.10.1", "c38d0ca52ea80254936a32c45bb7eb414e7a96a521b4ce76d00a69753b157f21", [:rebar3], [{:certifi, "2.0.0", [hex: :certifi, repo: "hexpm", optional: false]}, {:idna, "5.1.0", [hex: :idna, repo: "hexpm", optional: false]}, {:metrics, "1.0.1", [hex: :metrics, repo: "hexpm", optional: false]}, {:mimerl, "1.0.2", [hex: :mimerl, repo: "hexpm", optional: false]}, {:ssl_verify_fun, "1.1.1", [hex: :ssl_verify_fun, repo: "hexpm", optional: false]}], "hexpm"}, "idna": {:hex, :idna, "5.1.0", "d72b4effeb324ad5da3cab1767cb16b17939004e789d8c0ad5b70f3cea20c89a", [:rebar3], [{:unicode_util_compat, "0.3.1", [hex: :unicode_util_compat, repo: "hexpm", optional: false]}], "hexpm"}, - "jsx": {:hex, :jsx, "2.8.2", "7acc7d785b5abe8a6e9adbde926a24e481f29956dd8b4df49e3e4e7bcc92a018", [:mix, :rebar3], [], "hexpm"}, + "jsx": {:hex, :jsx, "2.8.3", "a05252d381885240744d955fbe3cf810504eb2567164824e19303ea59eef62cf", [:mix, :rebar3], [], "hexpm"}, "metrics": {:hex, :metrics, "1.0.1", "25f094dea2cda98213cecc3aeff09e940299d950904393b2a29d191c346a8486", [:rebar3], [], "hexpm"}, "mimerl": {:hex, :mimerl, "1.0.2", "993f9b0e084083405ed8252b99460c4f0563e41729ab42d9074fd5e52439be88", [:rebar3], [], "hexpm"}, "poison": {:hex, :poison, "3.1.0", "d9eb636610e096f86f25d9a46f35a9facac35609a7591b3be3326e99a0484665", [:mix], [], "hexpm"}, diff --git a/package.json b/package.json index 1b4d76ef..e1e114c9 100644 --- a/package.json +++ b/package.json @@ -23,7 +23,6 @@ "author": "", "license": "MIT", "dependencies": { - "chalk": "^2.3.0", "erlang-types": "^1.0.1", "grapheme-splitter": "^1.0.2", "rollup-plugin-commonjs": "^8.2.1", diff --git a/priv/testrunner/vendor.build.js b/priv/testrunner/vendor.build.js index 65b2d07d..9d49e34d 100644 --- a/priv/testrunner/vendor.build.js +++ b/priv/testrunner/vendor.build.js @@ -1,66 +1,2 @@ -import os from'os';class Tuple{constructor(...a){this.values=Object.freeze(a),this.length=this.values.length}get(a){return this.values[a]}count(){return this.values.length}[Symbol.iterator](){return this.values[Symbol.iterator]()}toString(){let a,b='';for(a=0;a'}}let ref_counter=-1;class Reference{constructor(){++ref_counter,this.id=ref_counter,this.ref=Symbol()}toString(){return'Ref#<0.0.0.'+this.id+'>'}}class BitString{constructor(...a){this.value=Object.freeze(this.process(a)),this.length=this.value.length,this.bit_size=8*this.length,this.byte_size=this.length}get(a){return this.value[a]}count(){return this.value.length}slice(a,b=null){let c=this.value.slice(a,b),d=c.map((a)=>BitString.integer(a));return new BitString(...d)}[Symbol.iterator](){return this.value[Symbol.iterator]()}toString(){var a,b='';for(a=0;a>'}process(a){let b=[];var c;for(c=0;cb?c.push(b):2048>b?c.push(192|b>>6,128|63&b):55296>b||57344<=b?c.push(224|b>>12,128|63&b>>6,128|63&b):(d++,b=65536+((1023&b)<<10|1023&a.charCodeAt(d)),c.push(240|b>>18,128|63&b>>12,128|63&b>>6,128|63&b));return c}static toUTF16Array(a){for(var b,c=[],d=0;d=b?(c.push(0),c.push(b)):(c.push(255&b>>8),c.push(255&b));return c}static toUTF32Array(a){for(var b,c=[],d=0;d=b?(c.push(0),c.push(0),c.push(0),c.push(b)):(c.push(0),c.push(0),c.push(255&b>>8),c.push(255&b));return c}//http://stackoverflow.com/questions/2003493/javascript-float-from-to-bits -static float32ToBytes(a){var b=[],c=new ArrayBuffer(4);new Float32Array(c)[0]=a;let d=new Uint32Array(c)[0];return b.push(255&d>>24),b.push(255&d>>16),b.push(255&d>>8),b.push(255&d),b}static float64ToBytes(a){var b=[],c=new ArrayBuffer(8);new Float64Array(c)[0]=a;var d=new Uint32Array(c)[0],e=new Uint32Array(c)[1];return b.push(255&e>>24),b.push(255&e>>16),b.push(255&e>>8),b.push(255&e),b.push(255&d>>24),b.push(255&d>>16),b.push(255&d>>8),b.push(255&d),b}}var ErlangTypes={Tuple,PID,Reference,BitString};function createCommonjsModule(a,b){return b={exports:{}},a(b,b.exports),b.exports}var matchOperatorsRe=/[|\\{}()[\]^$+*?.]/g,escapeStringRegexp=function(a){if('string'!=typeof a)throw new TypeError('Expected a string');return a.replace(matchOperatorsRe,'\\$&')},colorName={aliceblue:[240,248,255],antiquewhite:[250,235,215],aqua:[0,255,255],aquamarine:[127,255,212],azure:[240,255,255],beige:[245,245,220],bisque:[255,228,196],black:[0,0,0],blanchedalmond:[255,235,205],blue:[0,0,255],blueviolet:[138,43,226],brown:[165,42,42],burlywood:[222,184,135],cadetblue:[95,158,160],chartreuse:[127,255,0],chocolate:[210,105,30],coral:[255,127,80],cornflowerblue:[100,149,237],cornsilk:[255,248,220],crimson:[220,20,60],cyan:[0,255,255],darkblue:[0,0,139],darkcyan:[0,139,139],darkgoldenrod:[184,134,11],darkgray:[169,169,169],darkgreen:[0,100,0],darkgrey:[169,169,169],darkkhaki:[189,183,107],darkmagenta:[139,0,139],darkolivegreen:[85,107,47],darkorange:[255,140,0],darkorchid:[153,50,204],darkred:[139,0,0],darksalmon:[233,150,122],darkseagreen:[143,188,143],darkslateblue:[72,61,139],darkslategray:[47,79,79],darkslategrey:[47,79,79],darkturquoise:[0,206,209],darkviolet:[148,0,211],deeppink:[255,20,147],deepskyblue:[0,191,255],dimgray:[105,105,105],dimgrey:[105,105,105],dodgerblue:[30,144,255],firebrick:[178,34,34],floralwhite:[255,250,240],forestgreen:[34,139,34],fuchsia:[255,0,255],gainsboro:[220,220,220],ghostwhite:[248,248,255],gold:[255,215,0],goldenrod:[218,165,32],gray:[128,128,128],green:[0,128,0],greenyellow:[173,255,47],grey:[128,128,128],honeydew:[240,255,240],hotpink:[255,105,180],indianred:[205,92,92],indigo:[75,0,130],ivory:[255,255,240],khaki:[240,230,140],lavender:[230,230,250],lavenderblush:[255,240,245],lawngreen:[124,252,0],lemonchiffon:[255,250,205],lightblue:[173,216,230],lightcoral:[240,128,128],lightcyan:[224,255,255],lightgoldenrodyellow:[250,250,210],lightgray:[211,211,211],lightgreen:[144,238,144],lightgrey:[211,211,211],lightpink:[255,182,193],lightsalmon:[255,160,122],lightseagreen:[32,178,170],lightskyblue:[135,206,250],lightslategray:[119,136,153],lightslategrey:[119,136,153],lightsteelblue:[176,196,222],lightyellow:[255,255,224],lime:[0,255,0],limegreen:[50,205,50],linen:[250,240,230],magenta:[255,0,255],maroon:[128,0,0],mediumaquamarine:[102,205,170],mediumblue:[0,0,205],mediumorchid:[186,85,211],mediumpurple:[147,112,219],mediumseagreen:[60,179,113],mediumslateblue:[123,104,238],mediumspringgreen:[0,250,154],mediumturquoise:[72,209,204],mediumvioletred:[199,21,133],midnightblue:[25,25,112],mintcream:[245,255,250],mistyrose:[255,228,225],moccasin:[255,228,181],navajowhite:[255,222,173],navy:[0,0,128],oldlace:[253,245,230],olive:[128,128,0],olivedrab:[107,142,35],orange:[255,165,0],orangered:[255,69,0],orchid:[218,112,214],palegoldenrod:[238,232,170],palegreen:[152,251,152],paleturquoise:[175,238,238],palevioletred:[219,112,147],papayawhip:[255,239,213],peachpuff:[255,218,185],peru:[205,133,63],pink:[255,192,203],plum:[221,160,221],powderblue:[176,224,230],purple:[128,0,128],rebeccapurple:[102,51,153],red:[255,0,0],rosybrown:[188,143,143],royalblue:[65,105,225],saddlebrown:[139,69,19],salmon:[250,128,114],sandybrown:[244,164,96],seagreen:[46,139,87],seashell:[255,245,238],sienna:[160,82,45],silver:[192,192,192],skyblue:[135,206,235],slateblue:[106,90,205],slategray:[112,128,144],slategrey:[112,128,144],snow:[255,250,250],springgreen:[0,255,127],steelblue:[70,130,180],tan:[210,180,140],teal:[0,128,128],thistle:[216,191,216],tomato:[255,99,71],turquoise:[64,224,208],violet:[238,130,238],wheat:[245,222,179],white:[255,255,255],whitesmoke:[245,245,245],yellow:[255,255,0],yellowgreen:[154,205,50]},conversions=createCommonjsModule(function(a){/** - * See https://en.m.wikipedia.org/wiki/Euclidean_distance#Squared_Euclidean_distance - * */function comparativeDistance(a,b){return f(a[0]-b[0],2)+f(a[1]-b[1],2)+f(a[2]-b[2],2)}var c=Math.round,d=Math.PI,e=Math.floor,f=Math.pow,i=Math.max,j=Math.min,b={};/* MIT license */// NOTE: conversions should only return primitive values (i.e. arrays, or -// values that give correct `typeof` results). -// do not use box values types (i.e. Number(), String(), etc.) -for(var g in colorName)colorName.hasOwnProperty(g)&&(b[colorName[g]]=g);var k=a.exports={rgb:{channels:3,labels:'rgb'},hsl:{channels:3,labels:'hsl'},hsv:{channels:3,labels:'hsv'},hwb:{channels:3,labels:'hwb'},cmyk:{channels:4,labels:'cmyk'},xyz:{channels:3,labels:'xyz'},lab:{channels:3,labels:'lab'},lch:{channels:3,labels:'lch'},hex:{channels:1,labels:['hex']},keyword:{channels:1,labels:['keyword']},ansi16:{channels:1,labels:['ansi16']},ansi256:{channels:1,labels:['ansi256']},hcg:{channels:3,labels:['h','c','g']},apple:{channels:3,labels:['r16','g16','b16']},gray:{channels:1,labels:['gray']}};// hide .channels and .labels properties -for(var h in k)if(k.hasOwnProperty(h)){if(!('channels'in k[h]))throw new Error('missing channels property: '+h);if(!('labels'in k[h]))throw new Error('missing channel labels property: '+h);if(k[h].labels.length!==k[h].channels)throw new Error('channel and label counts mismatch: '+h);var l=k[h].channels,m=k[h].labels;delete k[h].channels,delete k[h].labels,Object.defineProperty(k[h],'channels',{value:l}),Object.defineProperty(k[h],'labels',{value:m})}k.rgb.hsl=function(a){var c,d,e,f=a[0]/255,h=a[1]/255,g=a[2]/255,b=j(f,h,g),k=i(f,h,g),l=k-b;return k===b?c=0:f===k?c=(h-g)/l:h===k?c=2+(g-f)/l:g===k&&(c=4+(f-h)/l),c=j(60*c,360),0>c&&(c+=360),e=(b+k)/2,d=k===b?0:0.5>=e?l/(k+b):l/(2-k-b),[c,100*d,100*e]},k.rgb.hsv=function(a){var c,d,e,f=a[0],h=a[1],g=a[2],b=j(f,h,g),k=i(f,h,g),l=k-b;return d=0===k?0:1e3*(l/k)/10,k===b?c=0:f===k?c=(h-g)/l:h===k?c=2+(g-f)/l:g===k&&(c=4+(f-h)/l),c=j(60*c,360),0>c&&(c+=360),e=1e3*(k/255)/10,[c,d,e]},k.rgb.hwb=function(a){var c=a[0],d=a[1],e=a[2],b=k.rgb.hsl(a)[0],f=1/255*j(c,j(d,e));return e=1-1/255*i(c,i(d,e)),[b,100*f,100*e]},k.rgb.cmyk=function(a){var d,c,e,f,h=a[0]/255,i=a[1]/255,g=a[2]/255;return f=j(1-h,1-i,1-g),d=(1-h-f)/(1-f)||0,c=(1-i-f)/(1-f)||0,e=(1-g-f)/(1-f)||0,[100*d,100*c,100*e,100*f]},k.rgb.keyword=function(a){var c=b[a];if(c)return c;var d,e=Infinity;for(var f in colorName)if(colorName.hasOwnProperty(f)){var g=colorName[f],h=comparativeDistance(a,g);// Compute comparative distance -// Check if its less, if so set as closest -hj?j*(1+h):j+h-j*h,b=2*j-c,e=[0,0,0];for(var k=0;3>k;k++)d=g+1/3*-(k-1),0>d&&d++,16*d?b+6*(c-b)*d:1>2*d?c:2>3*d?b+6*((c-b)*(2/3-d)):b,e[k]=255*f;return e},k.hsl.hsv=function(a){var b,c,d=a[0],e=a[1]/100,f=a[2]/100,g=e,h=i(f,0.01);return f*=2,e*=1>=f?f:2-f,g*=1>=h?h:2-h,c=(f+e)/2,b=0==f?2*g/(h+g):2*e/(f+e),[d,100*b,100*c]},k.hsv.rgb=function(a){var b=a[0]/60,c=a[1]/100,d=a[2]/100,g=e(b)%6,h=b-e(b),f=255*d*(1-c),i=255*d*(1-c*h),j=255*d*(1-c*(1-h));return d*=255,0==g?[d,j,f]:1==g?[i,d,f]:2==g?[f,d,j]:3==g?[f,i,d]:4==g?[j,f,d]:5==g?[d,f,i]:void 0},k.hsv.hsl=function(a){var b,c,d,e=a[0],f=a[1]/100,g=a[2]/100,h=i(g,0.01);return d=(2-f)*g,b=(2-f)*h,c=f*h,c/=1>=b?b:2-b,c=c||0,d/=2,[e,100*c,100*d]},k.hwb.rgb=function(a){var c,d,i,f,j=a[0]/360,h=a[1]/100,k=a[2]/100,l=h+k;// wh + bl cant be > 1 -1g&&(g+=360),h=Math.sqrt(i*i+a*a),[c,h,g]},k.lch.lab=function(e){var f,a,b,g=e[0],i=e[1],c=e[2];return b=2*(c/360)*d,f=i*Math.cos(b),a=i*Math.sin(b),[g,f,a]},k.rgb.ansi16=function(a){var d=a[0],e=a[1],f=a[2],b=1 in arguments?arguments[1]:k.rgb.hsv(a)[2];// hsv -> ansi16 optimization -if(b=c(b/50),0===b)return 30;var g=30+(c(f/255)<<2|c(e/255)<<1|c(d/255));return 2===b&&(g+=60),g},k.hsv.ansi16=function(a){// optimization here; we already know the value and don't need to get -// it converted for us. -return k.rgb.ansi16(k.hsv.rgb(a),a[2])},k.rgb.ansi256=function(a){var d=a[0],e=a[1],f=a[2];// we use the extended greyscale palette here, with the exception of -// black and white. normal palette only has 4 greyscale shades. -if(d===e&&e===f)return 8>d?16:248>1)*d),g=255*((1&c>>2)*d);return[e,f,g]},k.ansi256.rgb=function(a){// handle greyscale -if(232<=a){var d=10*(a-232)+8;return[d,d,d]}a-=16;var c,f=255*(e(a/36)/5),h=255*(e((c=a%36)/6)/5),g=255*(c%6/5);return[f,h,g]},k.rgb.hex=function(a){var b=((255&c(a[0]))<<16)+((255&c(a[1]))<<8)+(255&c(a[2])),d=b.toString(16).toUpperCase();return'000000'.substring(d.length)+d},k.hex.rgb=function(a){var b=a.toString(16).match(/[a-f0-9]{6}|[a-f0-9]{3}/i);if(!b)return[0,0,0];var c=b[0];3===b[0].length&&(c=c.split('').map(function(a){return a+a}).join(''));var d=parseInt(c,16);return[255&d>>16,255&d>>8,255&d]},k.rgb.hcg=function(a){var c,d,e=a[0]/255,f=a[1]/255,g=a[2]/255,b=i(i(e,f),g),h=j(j(e,f),g),k=b-h;return c=1>k?h/(1-k):0,d=0>=k?0:b===e?(f-g)/k%6:b===f?2+(g-e)/k:4+(e-f)/k+4,d/=6,d%=1,[360*d,100*k,100*c]},k.hsl.hcg=function(a){var b=a[1]/100,d=a[2]/100,e=1,c=0;return e=0.5>d?2*b*d:2*b*(1-d),1>e&&(c=(d-0.5*e)/(1-e)),[a[0],100*e,100*c]},k.hsv.hcg=function(a){var b=a[1]/100,d=a[2]/100,e=b*d,c=0;return 1>e&&(c=(d-e)/(1-e)),[a[0],100*e,100*c]},k.hcg.rgb=function(a){var b=a[0]/360,d=a[1]/100,c=a[2]/100;if(0==d)return[255*c,255*c,255*c];var f=[0,0,0],g=6*(b%1),h=g%1,i=1-h,j=0;switch(e(g)){case 0:f[0]=1,f[1]=h,f[2]=0;break;case 1:f[0]=i,f[1]=1,f[2]=0;break;case 2:f[0]=0,f[1]=1,f[2]=h;break;case 3:f[0]=0,f[1]=i,f[2]=1;break;case 4:f[0]=h,f[1]=0,f[2]=1;break;default:f[0]=1,f[1]=0,f[2]=i;}return j=(1-d)*c,[255*(d*f[0]+j),255*(d*f[1]+j),255*(d*f[2]+j)]},k.hcg.hsv=function(a){var b=a[1]/100,c=a[2]/100,d=b+c*(1-b),e=0;return 0d?e=b/(2*d):0.5<=d&&1>d&&(e=b/(2*(1-d))),[a[0],100*e,100*d]},k.hcg.hwb=function(a){var b=a[1]/100,c=a[2]/100,d=b+c*(1-b);return[a[0],100*(d-b),100*(1-d)]},k.hwb.hcg=function(a){var d=a[1]/100,e=a[2]/100,b=1-e,f=b-d,c=0;return 1>f&&(c=(b-f)/(1-f)),[a[0],100*f,100*c]},k.apple.rgb=function(a){return[255*(a[0]/65535),255*(a[1]/65535),255*(a[2]/65535)]},k.rgb.apple=function(a){return[65535*(a[0]/255),65535*(a[1]/255),65535*(a[2]/255)]},k.gray.rgb=function(a){return[255*(a[0]/100),255*(a[0]/100),255*(a[0]/100)]},k.gray.hsl=k.gray.hsv=function(a){return[0,0,a[0]]},k.gray.hwb=function(a){return[0,100,a[0]]},k.gray.cmyk=function(a){return[0,0,0,a[0]]},k.gray.lab=function(a){return[a[0],0,0]},k.gray.hex=function(a){var b=255&c(255*(a[0]/100)),d=((b<<16)+(b<<8)+b).toString(16).toUpperCase();return'000000'.substring(d.length)+d},k.rgb.gray=function(a){var b=(a[0]+a[1]+a[2])/3;return[100*(b/255)]}}),models$1=Object.keys(conversions);/* - this function routes a model to all other models. - - all functions that are routed have a property `.conversion` attached - to the returned synthetic function. This property is an array - of strings, each with the steps in between the 'from' and 'to' - color models (inclusive). - - conversions that are not possible simply are not included. -*/// https://jsperf.com/object-keys-vs-for-in-with-closure/3 -function buildGraph(){for(var a={},b=models$1.length,c=0;c queue -> pop -for(b[a].distance=0;c.length;)for(var d=c.pop(),e=Object.keys(conversions[d]),f=e.length,g=0;gfunction(){const c=a.apply(colorConvert,arguments);return`\u001B[${c+b}m`},c=(a,b)=>function(){const c=a.apply(colorConvert,arguments);return`\u001B[${38+b};5;${c}m`},d=(a,b)=>function(){const c=a.apply(colorConvert,arguments);return`\u001B[${38+b};2;${c[0]};${c[1]};${c[2]}m`};Object.defineProperty(a,'exports',{enumerable:!0,get:function assembleStyles(){const a={modifier:{reset:[0,0],// 21 isn't widely supported and 22 does the same thing -bold:[1,22],dim:[2,22],italic:[3,23],underline:[4,24],inverse:[7,27],hidden:[8,28],strikethrough:[9,29]},color:{black:[30,39],red:[31,39],green:[32,39],yellow:[33,39],blue:[34,39],magenta:[35,39],cyan:[36,39],white:[37,39],gray:[90,39],// Bright color -redBright:[91,39],greenBright:[92,39],yellowBright:[93,39],blueBright:[94,39],magentaBright:[95,39],cyanBright:[96,39],whiteBright:[97,39]},bgColor:{bgBlack:[40,49],bgRed:[41,49],bgGreen:[42,49],bgYellow:[43,49],bgBlue:[44,49],bgMagenta:[45,49],bgCyan:[46,49],bgWhite:[47,49],// Bright color -bgBlackBright:[100,49],bgRedBright:[101,49],bgGreenBright:[102,49],bgYellowBright:[103,49],bgBlueBright:[104,49],bgMagentaBright:[105,49],bgCyanBright:[106,49],bgWhiteBright:[107,49]}};// Fix humans -a.color.grey=a.color.gray,Object.keys(a).forEach((b)=>{const c=a[b];Object.keys(c).forEach((b)=>{const d=c[b];a[b]={open:`\u001B[${d[0]}m`,close:`\u001B[${d[1]}m`},c[b]=a[b]}),Object.defineProperty(a,b,{value:c,enumerable:!1})});const e=(a,c,d)=>[a,c,d];a.color.close='\x1B[39m',a.bgColor.close='\x1B[49m',a.color.ansi={},a.color.ansi256={},a.color.ansi16m={rgb:d(e,0)},a.bgColor.ansi={},a.bgColor.ansi256={},a.bgColor.ansi16m={rgb:d(e,10)};for(const e of Object.keys(colorConvert)){if('object'!=typeof colorConvert[e])continue;const f=colorConvert[e];'ansi16'in f&&(a.color.ansi[e]=b(f.ansi16,0),a.bgColor.ansi[e]=b(f.ansi16,10)),'ansi256'in f&&(a.color.ansi256[e]=c(f.ansi256,0),a.bgColor.ansi256[e]=c(f.ansi256,10)),'rgb'in f&&(a.color.ansi16m[e]=d(f.rgb,0),a.bgColor.ansi16m[e]=d(f.rgb,10))}return a}})});var hasFlag=function(a,b){b=b||process.argv;var c=b.indexOf('--'),d=/^-{1,2}/.test(a)?'':'--',e=b.indexOf(d+a);return-1!==e&&(!(-1!==c)||e{if(hasFlag('no-color')||hasFlag('no-colors')||hasFlag('color=false'))return 0;if(hasFlag('color=16m')||hasFlag('color=full')||hasFlag('color=truecolor'))return 3;if(hasFlag('color=256'))return 2;if(hasFlag('color')||hasFlag('colors')||hasFlag('color=true')||hasFlag('color=always'))return 1;if(process.stdout&&!process.stdout.isTTY)return 0;if('win32'===process.platform){// Node.js 7.5.0 is the first version of Node.js to include a patch to -// libuv that enables 256 color output on Windows. Anything earlier and it -// won't work. However, here we target Node.js 8 at minimum as it is an LTS -// release, and Node.js 7 is not. Windows 10 build 10586 is the first Windows -// release that supports 256 colors. -const a=os.release().split('.');return 8<=+process.version.split('.')[0]&&10<=+a[0]&&10586<=+a[2]?2:1}if('CI'in b)return'TRAVIS'in b||'Travis'===b.CI||'CIRCLECI'in b?1:0;if('TEAMCITY_VERSION'in b)return /^(9\.(0*[1-9]\d*)\.|\d{2,}\.)/.test(b.TEAMCITY_VERSION)?1:0;if('TERM_PROGRAM'in b){const a=parseInt((b.TERM_PROGRAM_VERSION||'').split('.')[0],10);switch(b.TERM_PROGRAM){case'iTerm.app':return 3<=a?3:2;case'Hyper':return 3;case'Apple_Terminal':return 2;// No default -}}return /^(screen|xterm)-256(?:color)?/.test(b.TERM)?2:/^screen|^xterm|^vt100|color|ansi|cygwin|linux/i.test(b.TERM)?1:'COLORTERM'in b?1:'dumb'===b.TERM?0:0})();'FORCE_COLOR'in b&&(c=0===parseInt(b.FORCE_COLOR,10)?0:c||1),a.exports=process&&((a)=>0!==a&&{level:a,hasBasic:!0,has256:2<=a,has16m:3<=a})(c)}),templates=createCommonjsModule(function(a){'use strict';function unescape(a){return'u'===a[0]&&5===a.length||'x'===a[0]&&3===a.length?String.fromCharCode(parseInt(a.slice(1),16)):f.get(a)||a}function parseArguments(a,b){const c=[],f=b.trim().split(/\s*,\s*/g);let g;for(const h of f)if(!isNaN(h))c.push(+h);else if(g=h.match(d))c.push(g[2].replace(e,(a,b,c)=>b?unescape(b):c));else throw new Error(`Invalid Chalk template style argument: ${h} (in style '${a}')`);return c}function parseStyle(a){c.lastIndex=0;const b=[];for(let d;null!==(d=c.exec(a));){const a=d[1];if(d[2]){const c=parseArguments(a,d[2]);b.push([a].concat(c))}else b.push([a])}return b}function buildStyle(a,b){const c={};for(const d of b)for(const a of d.styles)c[a[0]]=d.inverse?null:a.slice(1);let d=a;for(const e of Object.keys(c))if(Array.isArray(c[e])){if(!(e in d))throw new Error(`Unknown Chalk style: ${e}`);d=0{const d=[],e=[];let f=[];// eslint-disable-next-line max-params -if(c.replace(b,(b,c,g,h,i,j)=>{if(c)f.push(unescape(c));else if(h){const b=f.join('');f=[],e.push(0===d.length?b:buildStyle(a,d)(b)),d.push({inverse:g,styles:parseStyle(h)})}else if(i){if(0===d.length)throw new Error('Found extraneous } in Chalk template literal');e.push(buildStyle(a,d)(f.join(''))),f=[],d.pop()}else f.push(j)}),e.push(f.join('')),0=this.level||!e)return this._empty?'':e;// Turns out that on Windows dimmed gray text becomes invisible in cmd.exe, -// see https://github.com/chalk/chalk/issues/58 -// If we're on Windows and we're dealing with a gray color, temporarily make 'dim' a noop. -const a=ansiStyles.dim.open;b&&this.hasGrey&&(ansiStyles.dim.open='');for(const a of this._styles.slice().reverse())e=a.open+e.replace(a.closeRe,a.open)+a.close,e=e.replace(/\r?\n/g,`${a.close}$&${a.open}`);// Reset the original `dim` if we changed it to work around the Windows dimmed gray issue -return ansiStyles.dim.open=a,e}function chalkTag(a,b){if(!Array.isArray(b))// If chalk() was called by itself or with a string, -// return the string itself as a string. -return[].slice.call(arguments,1).join(' ');const c=[].slice.call(arguments,2),d=[b.raw[0]];for(let e=1;e{},e);Object.defineProperties(Chalk.prototype,e),a.exports=Chalk(),a.exports.supportsColor=supportsColor,a.exports.default=a.exports}// For TypeScript -),vendor={ErlangTypes,Chalk:chalk};export default vendor; +class Tuple{constructor(...a){this.values=Object.freeze(a),this.length=this.values.length}get(a){return this.values[a]}count(){return this.values.length}[Symbol.iterator](){return this.values[Symbol.iterator]()}toString(){let a,b='';for(a=0;a'}}let ref_counter=-1;class Reference{constructor(){++ref_counter,this.id=ref_counter,this.ref=Symbol()}toString(){return'Ref#<0.0.0.'+this.id+'>'}}class BitString{constructor(...a){this.value=Object.freeze(this.process(a)),this.length=this.value.length,this.bit_size=8*this.length,this.byte_size=this.length}get(a){return this.value[a]}count(){return this.value.length}slice(a,b=null){let c=this.value.slice(a,b),d=c.map((a)=>BitString.integer(a));return new BitString(...d)}[Symbol.iterator](){return this.value[Symbol.iterator]()}toString(){var a,b='';for(a=0;a>'}process(a){let b=[];var c;for(c=0;cb?c.push(b):2048>b?c.push(192|b>>6,128|63&b):55296>b||57344<=b?c.push(224|b>>12,128|63&b>>6,128|63&b):(d++,b=65536+((1023&b)<<10|1023&a.charCodeAt(d)),c.push(240|b>>18,128|63&b>>12,128|63&b>>6,128|63&b));return c}static toUTF16Array(a){for(var b,c=[],d=0;d=b?(c.push(0),c.push(b)):(c.push(255&b>>8),c.push(255&b));return c}static toUTF32Array(a){for(var b,c=[],d=0;d=b?(c.push(0),c.push(0),c.push(0),c.push(b)):(c.push(0),c.push(0),c.push(255&b>>8),c.push(255&b));return c}//http://stackoverflow.com/questions/2003493/javascript-float-from-to-bits +static float32ToBytes(a){var b=[],c=new ArrayBuffer(4);new Float32Array(c)[0]=a;let d=new Uint32Array(c)[0];return b.push(255&d>>24),b.push(255&d>>16),b.push(255&d>>8),b.push(255&d),b}static float64ToBytes(a){var b=[],c=new ArrayBuffer(8);new Float64Array(c)[0]=a;var d=new Uint32Array(c)[0],e=new Uint32Array(c)[1];return b.push(255&e>>24),b.push(255&e>>16),b.push(255&e>>8),b.push(255&e),b.push(255&d>>24),b.push(255&d>>16),b.push(255&d>>8),b.push(255&d),b}}var ErlangTypes={Tuple,PID,Reference,BitString},vendor={ErlangTypes};export default vendor; diff --git a/priv/testrunner/vendor.js b/priv/testrunner/vendor.js index 7e3cd354..1d79bd80 100644 --- a/priv/testrunner/vendor.js +++ b/priv/testrunner/vendor.js @@ -1,7 +1,5 @@ import ErlangTypes from 'erlang-types'; -import Chalk from 'chalk'; export default { ErlangTypes, - Chalk, }; diff --git a/yarn.lock b/yarn.lock index ec2b01e5..9aec577d 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1264,14 +1264,6 @@ chalk@^2.1.0: escape-string-regexp "^1.0.5" supports-color "^4.0.0" -chalk@^2.3.0: - version "2.3.0" - resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.3.0.tgz#b5ea48efc9c1793dccc9b4767c93914d3f2d52ba" - dependencies: - ansi-styles "^3.1.0" - escape-string-regexp "^1.0.5" - supports-color "^4.0.0" - chokidar@^1.4.2: version "1.7.0" resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-1.7.0.tgz#798e689778151c8076b4b360e5edd28cda2bb468" From eedcd41f51cbfcb865c2ccfc9bd0386ef989b9e5 Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Sat, 28 Oct 2017 16:21:46 -0500 Subject: [PATCH 796/860] Increase timeout length on async_stream calls --- lib/elixir_script/passes/output.ex | 2 +- lib/elixir_script/passes/translate.ex | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/elixir_script/passes/output.ex b/lib/elixir_script/passes/output.ex index ce6ad187..baaf05ba 100644 --- a/lib/elixir_script/passes/output.ex +++ b/lib/elixir_script/passes/output.ex @@ -66,7 +66,7 @@ defmodule ElixirScript.Output do |> Generator.generate |> concat |> output(module, Map.get(opts, :output), js_modules) - end) + end, timeout: 10_000) |> Stream.map(fn {:ok, code} -> code end) |> Enum.to_list() end diff --git a/lib/elixir_script/passes/translate.ex b/lib/elixir_script/passes/translate.ex index 45f29204..0b6490fc 100644 --- a/lib/elixir_script/passes/translate.ex +++ b/lib/elixir_script/passes/translate.ex @@ -13,7 +13,7 @@ defmodule ElixirScript.Translate do |> Task.async_stream(fn {module, info} -> ElixirScript.Translate.Module.compile(module, info, pid) - end) + end, timeout: 10_000) |> Stream.run() end end From f39d2cafaa7eda60e6439282a3d1d9a8fbded3ad Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Sun, 29 Oct 2017 23:15:49 -0500 Subject: [PATCH 797/860] Updates to make sure try works correctly --- lib/elixir_script/passes/find_used_modules.ex | 5 +- .../passes/translate/forms/try.ex | 22 +- priv/testrunner/testRunner.js | 6 +- priv/testrunner/vendor.build.js | 406 +++++++++++++++++- src/javascript/lib/core/functions.js | 5 +- src/javascript/lib/core/special_forms.js | 1 - src/javascript/tests/try.spec.js | 3 +- test_elixir_script/try_test.exs | 48 +++ 8 files changed, 485 insertions(+), 11 deletions(-) create mode 100644 test_elixir_script/try_test.exs diff --git a/lib/elixir_script/passes/find_used_modules.ex b/lib/elixir_script/passes/find_used_modules.ex index 5b33127a..ae75d9e6 100644 --- a/lib/elixir_script/passes/find_used_modules.ex +++ b/lib/elixir_script/passes/find_used_modules.ex @@ -225,6 +225,8 @@ defmodule ElixirScript.FindUsedModules do end defp walk({:try, _, [blocks]}, state) do + walk(Enum, state) + try_block = Keyword.get(blocks, :do) rescue_block = Keyword.get(blocks, :rescue, nil) catch_block = Keyword.get(blocks, :catch, nil) @@ -236,7 +238,8 @@ defmodule ElixirScript.FindUsedModules do if rescue_block do Enum.each(rescue_block, fn {:->, _, [ [{:in, _, [param, names]}], body]} -> - walk({[], [param], [{{:., [], [Enum, :member?]}, [], [param, names]}], body}, state) + Enum.each(names, &walk(&1, state)) + walk({[], [param], [{{:., [], [Enum, :member?]}, [], [names, param]}], body}, state) {:->, _, [ [param], body]} -> walk({[], [param], [], body}, state) end) diff --git a/lib/elixir_script/passes/translate/forms/try.ex b/lib/elixir_script/passes/translate/forms/try.ex index 249d8f9b..e086d310 100644 --- a/lib/elixir_script/passes/translate/forms/try.ex +++ b/lib/elixir_script/passes/translate/forms/try.ex @@ -58,8 +58,24 @@ defmodule ElixirScript.Translate.Forms.Try do defp process_rescue_block(rescue_block, state) do processed_clauses = Enum.map(rescue_block, fn + {:->, _, [ [{:in, _, [{:_, context, atom}, names]}], body]} -> + names = Enum.map(names, &make_exception_ast(&1)) + + param = {:_e, context, atom} + reasonCall = {{:., [], [{:_e0, context, atom}, :__reason]}, [], []} + reasonCall = {{:., [], [reasonCall, :__struct__]}, [], []} + reasonCall = {{:., [], [reasonCall, :__MODULE__]}, [], []} + + {ast, _} = Clause.compile({[], [param], [{{:., [], [Enum, :member?]}, [], [names, reasonCall]}], body}, state) + ast {:->, _, [ [{:in, _, [param, names]}], body]} -> - {ast, _} = Clause.compile({[], [param], [{{:., [], [Enum, :member?]}, [], [param, names]}], body}, state) + names = Enum.map(names, &make_exception_ast(&1)) + + reasonCall = {{:., [], [param, :__reason]}, [], []} + reasonCall = {{:., [], [reasonCall, :__struct__]}, [], []} + reasonCall = {{:., [], [reasonCall, :__MODULE__]}, [], []} + + {ast, _} = Clause.compile({[], [param], [{{:., [], [Enum, :member?]}, [], [names, reasonCall]}], body}, state) ast {:->, _, [ [param], body]} -> {ast, _} = Clause.compile({[], [param], [], body}, state) @@ -77,6 +93,10 @@ defmodule ElixirScript.Translate.Forms.Try do end + defp make_exception_ast(name) do + {{:., [], [name, :__MODULE__]}, [], []} + end + defp process_after_block(after_block, state) do translated_body = prepare_function_body(after_block, state) translated_body = JS.block_statement(translated_body) diff --git a/priv/testrunner/testRunner.js b/priv/testrunner/testRunner.js index b1856c5d..b3d1eca9 100644 --- a/priv/testrunner/testRunner.js +++ b/priv/testrunner/testRunner.js @@ -70,7 +70,7 @@ function runTests(mod, results) { if (result) { results.success++; } else { - resuls.failed++; + results.failed++; } } } @@ -80,7 +80,7 @@ function runTests(mod, results) { function runTest(mod, test, incomingContext, results) { const context = runSetup(mod, '__elixirscript_test_setup', incomingContext); - const testPassed = true; + let testPassed = true; try { test.get(Symbol.for('test'))(context); process.stdout.write(Colors.fg.Green + '.' + Colors.Reset); @@ -116,7 +116,7 @@ function handleError(e, test, results, mod) { } function printErrorLine(value, label = null) { - if (value !== Symbol.for('ex_unit_no_meaningful_value')) { + if (value && value !== Symbol.for('ex_unit_no_meaningful_value')) { if (label) { console.log(Colors.fg.Cyan, `${label}:`, Colors.Reset, `${value}`); } else { diff --git a/priv/testrunner/vendor.build.js b/priv/testrunner/vendor.build.js index 9d49e34d..6e808208 100644 --- a/priv/testrunner/vendor.build.js +++ b/priv/testrunner/vendor.build.js @@ -1,2 +1,404 @@ -class Tuple{constructor(...a){this.values=Object.freeze(a),this.length=this.values.length}get(a){return this.values[a]}count(){return this.values.length}[Symbol.iterator](){return this.values[Symbol.iterator]()}toString(){let a,b='';for(a=0;a'}}let ref_counter=-1;class Reference{constructor(){++ref_counter,this.id=ref_counter,this.ref=Symbol()}toString(){return'Ref#<0.0.0.'+this.id+'>'}}class BitString{constructor(...a){this.value=Object.freeze(this.process(a)),this.length=this.value.length,this.bit_size=8*this.length,this.byte_size=this.length}get(a){return this.value[a]}count(){return this.value.length}slice(a,b=null){let c=this.value.slice(a,b),d=c.map((a)=>BitString.integer(a));return new BitString(...d)}[Symbol.iterator](){return this.value[Symbol.iterator]()}toString(){var a,b='';for(a=0;a>'}process(a){let b=[];var c;for(c=0;cb?c.push(b):2048>b?c.push(192|b>>6,128|63&b):55296>b||57344<=b?c.push(224|b>>12,128|63&b>>6,128|63&b):(d++,b=65536+((1023&b)<<10|1023&a.charCodeAt(d)),c.push(240|b>>18,128|63&b>>12,128|63&b>>6,128|63&b));return c}static toUTF16Array(a){for(var b,c=[],d=0;d=b?(c.push(0),c.push(b)):(c.push(255&b>>8),c.push(255&b));return c}static toUTF32Array(a){for(var b,c=[],d=0;d=b?(c.push(0),c.push(0),c.push(0),c.push(b)):(c.push(0),c.push(0),c.push(255&b>>8),c.push(255&b));return c}//http://stackoverflow.com/questions/2003493/javascript-float-from-to-bits -static float32ToBytes(a){var b=[],c=new ArrayBuffer(4);new Float32Array(c)[0]=a;let d=new Uint32Array(c)[0];return b.push(255&d>>24),b.push(255&d>>16),b.push(255&d>>8),b.push(255&d),b}static float64ToBytes(a){var b=[],c=new ArrayBuffer(8);new Float64Array(c)[0]=a;var d=new Uint32Array(c)[0],e=new Uint32Array(c)[1];return b.push(255&e>>24),b.push(255&e>>16),b.push(255&e>>8),b.push(255&e),b.push(255&d>>24),b.push(255&d>>16),b.push(255&d>>8),b.push(255&d),b}}var ErlangTypes={Tuple,PID,Reference,BitString},vendor={ErlangTypes};export default vendor; +class Tuple { + constructor(...args) { + this.values = Object.freeze(args); + this.length = this.values.length; + } + + get(index) { + return this.values[index]; + } + + count() { + return this.values.length; + } + + [Symbol.iterator]() { + return this.values[Symbol.iterator](); + } + + toString() { + let i, + s = ''; + for (i = 0; i < this.values.length; i++) { + if (s !== '') { + s += ', '; + } + + const stringToAppend = this.values[i] ? this.values[i].toString() : ''; + + s += stringToAppend; + } + + return '{' + s + '}'; + } + + put_elem(index, elem) { + if (index === this.length) { + let new_values = this.values.concat([elem]); + return new Tuple(...new_values); + } + + let new_values = this.values.concat([]); + new_values.splice(index, 0, elem); + return new Tuple(...new_values); + } + + remove_elem(index) { + let new_values = this.values.concat([]); + new_values.splice(index, 1); + return new Tuple(...new_values); + } +} + +let process_counter = -1; + +class PID { + constructor() { + process_counter = process_counter + 1; + this.id = process_counter; + } + + toString() { + return 'PID#<0.' + this.id + '.0>'; + } +} + +let ref_counter = -1; + +class Reference { + constructor() { + ref_counter = ref_counter + 1; + this.id = ref_counter; + this.ref = Symbol(); + } + + toString() { + return 'Ref#<0.0.0.' + this.id + '>'; + } +} + +class BitString { + constructor(...args) { + this.value = Object.freeze(this.process(args)); + this.length = this.value.length; + this.bit_size = this.length * 8; + this.byte_size = this.length; + } + + get(index) { + return this.value[index]; + } + + count() { + return this.value.length; + } + + slice(start, end = null) { + let s = this.value.slice(start, end); + let ms = s.map(elem => BitString.integer(elem)); + return new BitString(...ms); + } + + [Symbol.iterator]() { + return this.value[Symbol.iterator](); + } + + toString() { + var i, + s = ''; + for (i = 0; i < this.count(); i++) { + if (s !== '') { + s += ', '; + } + s += this.get(i).toString(); + } + + return '<<' + s + '>>'; + } + + process(bitStringParts) { + let processed_values = []; + + var i; + for (i = 0; i < bitStringParts.length; i++) { + let processed_value = this['process_' + bitStringParts[i].type](bitStringParts[i]); + + for (let attr of bitStringParts[i].attributes) { + processed_value = this['process_' + attr](processed_value); + } + + processed_values = processed_values.concat(processed_value); + } + + return processed_values; + } + + process_integer(value) { + return value.value; + } + + process_float(value) { + if (value.size === 64) { + return BitString.float64ToBytes(value.value); + } else if (value.size === 32) { + return BitString.float32ToBytes(value.value); + } + + throw new Error('Invalid size for float'); + } + + process_bitstring(value) { + return value.value.value; + } + + process_binary(value) { + return BitString.toUTF8Array(value.value); + } + + process_utf8(value) { + return BitString.toUTF8Array(value.value); + } + + process_utf16(value) { + return BitString.toUTF16Array(value.value); + } + + process_utf32(value) { + return BitString.toUTF32Array(value.value); + } + + process_signed(value) { + return new Uint8Array([value])[0]; + } + + process_unsigned(value) { + return value; + } + + process_native(value) { + return value; + } + + process_big(value) { + return value; + } + + process_little(value) { + return value.reverse(); + } + + process_size(value) { + return value; + } + + process_unit(value) { + return value; + } + + static integer(value) { + return BitString.wrap(value, { type: 'integer', unit: 1, size: 8 }); + } + + static float(value) { + return BitString.wrap(value, { type: 'float', unit: 1, size: 64 }); + } + + static bitstring(value) { + return BitString.wrap(value, { + type: 'bitstring', + unit: 1, + size: value.bit_size + }); + } + + static bits(value) { + return BitString.bitstring(value); + } + + static binary(value) { + return BitString.wrap(value, { + type: 'binary', + unit: 8, + size: value.length + }); + } + + static bytes(value) { + return BitString.binary(value); + } + + static utf8(value) { + return BitString.wrap(value, { type: 'utf8', unit: 1, size: value.length }); + } + + static utf16(value) { + return BitString.wrap(value, { + type: 'utf16', + unit: 1, + size: value.length * 2 + }); + } + + static utf32(value) { + return BitString.wrap(value, { + type: 'utf32', + unit: 1, + size: value.length * 4 + }); + } + + static signed(value) { + return BitString.wrap(value, {}, 'signed'); + } + + static unsigned(value) { + return BitString.wrap(value, {}, 'unsigned'); + } + + static native(value) { + return BitString.wrap(value, {}, 'native'); + } + + static big(value) { + return BitString.wrap(value, {}, 'big'); + } + + static little(value) { + return BitString.wrap(value, {}, 'little'); + } + + static size(value, count) { + return BitString.wrap(value, { size: count }); + } + + static unit(value, count) { + return BitString.wrap(value, { unit: count }); + } + + static wrap(value, opt, new_attribute = null) { + let the_value = value; + + if (!(value instanceof Object)) { + the_value = { value: value, attributes: [] }; + } + + the_value = Object.assign(the_value, opt); + + if (new_attribute) { + the_value.attributes.push(new_attribute); + } + + return the_value; + } + + static toUTF8Array(str) { + var utf8 = []; + for (var i = 0; i < str.length; i++) { + var charcode = str.charCodeAt(i); + if (charcode < 0x80) { + utf8.push(charcode); + } else if (charcode < 0x800) { + utf8.push(0xc0 | charcode >> 6, 0x80 | charcode & 0x3f); + } else if (charcode < 0xd800 || charcode >= 0xe000) { + utf8.push(0xe0 | charcode >> 12, 0x80 | charcode >> 6 & 0x3f, 0x80 | charcode & 0x3f); + } else { + // surrogate pair + i++; + // UTF-16 encodes 0x10000-0x10FFFF by + // subtracting 0x10000 and splitting the + // 20 bits of 0x0-0xFFFFF into two halves + charcode = 0x10000 + ((charcode & 0x3ff) << 10 | str.charCodeAt(i) & 0x3ff); + utf8.push(0xf0 | charcode >> 18, 0x80 | charcode >> 12 & 0x3f, 0x80 | charcode >> 6 & 0x3f, 0x80 | charcode & 0x3f); + } + } + return utf8; + } + + static toUTF16Array(str) { + var utf16 = []; + for (var i = 0; i < str.length; i++) { + var codePoint = str.codePointAt(i); + + if (codePoint <= 255) { + utf16.push(0); + utf16.push(codePoint); + } else { + utf16.push(codePoint >> 8 & 0xff); + utf16.push(codePoint & 0xff); + } + } + return utf16; + } + + static toUTF32Array(str) { + var utf32 = []; + for (var i = 0; i < str.length; i++) { + var codePoint = str.codePointAt(i); + + if (codePoint <= 255) { + utf32.push(0); + utf32.push(0); + utf32.push(0); + utf32.push(codePoint); + } else { + utf32.push(0); + utf32.push(0); + utf32.push(codePoint >> 8 & 0xff); + utf32.push(codePoint & 0xff); + } + } + return utf32; + } + + //http://stackoverflow.com/questions/2003493/javascript-float-from-to-bits + static float32ToBytes(f) { + var bytes = []; + + var buf = new ArrayBuffer(4); + new Float32Array(buf)[0] = f; + + let intVersion = new Uint32Array(buf)[0]; + + bytes.push(intVersion >> 24 & 0xff); + bytes.push(intVersion >> 16 & 0xff); + bytes.push(intVersion >> 8 & 0xff); + bytes.push(intVersion & 0xff); + + return bytes; + } + + static float64ToBytes(f) { + var bytes = []; + + var buf = new ArrayBuffer(8); + new Float64Array(buf)[0] = f; + + var intVersion1 = new Uint32Array(buf)[0]; + var intVersion2 = new Uint32Array(buf)[1]; + + bytes.push(intVersion2 >> 24 & 0xff); + bytes.push(intVersion2 >> 16 & 0xff); + bytes.push(intVersion2 >> 8 & 0xff); + bytes.push(intVersion2 & 0xff); + + bytes.push(intVersion1 >> 24 & 0xff); + bytes.push(intVersion1 >> 16 & 0xff); + bytes.push(intVersion1 >> 8 & 0xff); + bytes.push(intVersion1 & 0xff); + + return bytes; + } +} + +var ErlangTypes = { + Tuple, + PID, + Reference, + BitString +}; + +var vendor = { + ErlangTypes +}; + +export default vendor; diff --git a/src/javascript/lib/core/functions.js b/src/javascript/lib/core/functions.js index 86d84a65..91bf31e7 100644 --- a/src/javascript/lib/core/functions.js +++ b/src/javascript/lib/core/functions.js @@ -133,7 +133,10 @@ function object_to_map(object, options = []) { key2 = Symbol.for(key); } - if (value !== null && (value.constructor === Object || (value instanceof Array && opt_recurse_array))) { + if ( + value !== null && + (value.constructor === Object || (value instanceof Array && opt_recurse_array)) + ) { value = object_to_map(value, options); } map.set(key2, value); diff --git a/src/javascript/lib/core/special_forms.js b/src/javascript/lib/core/special_forms.js index 8caa2dfe..988d341f 100644 --- a/src/javascript/lib/core/special_forms.js +++ b/src/javascript/lib/core/special_forms.js @@ -60,7 +60,6 @@ function _try(do_fun, rescue_function, catch_fun, else_function, after_function) result = do_fun(); } catch (e) { let ex_result = null; - if (rescue_function) { try { ex_result = rescue_function(e); diff --git a/src/javascript/tests/try.spec.js b/src/javascript/tests/try.spec.js index 97150618..fdcbaefd 100644 --- a/src/javascript/tests/try.spec.js +++ b/src/javascript/tests/try.spec.js @@ -1,8 +1,7 @@ import test from 'ava'; import Core from '../lib/core'; -const Patterns = Core.Patterns; -const SpecialForms = Core.SpecialForms; +const { Patterns, SpecialForms } = Core; test('try', (t) => { /* diff --git a/test_elixir_script/try_test.exs b/test_elixir_script/try_test.exs new file mode 100644 index 00000000..0e73cd8b --- /dev/null +++ b/test_elixir_script/try_test.exs @@ -0,0 +1,48 @@ +defmodule ElixirScript.Try.Test do + use ElixirScript.Test + + test "returns value in try if no error" do + value = try do + 1 + 1 + rescue + _ -> + 3 + end + + assert value == 2 + end + + test "returns rescue value on error" do + value = try do + raise ArithmeticError + rescue + _ -> + 3 + end + + assert value == 3 + end + + test "returns rescue value from matching error" do + value = try do + raise ArithmeticError + rescue + ArithmeticError -> + 3 + end + + assert value == 3 + end + + test "returns rescue value from matching errors" do + value = try do + raise ArithmeticError + rescue + _ in [ArithmeticError, ArgumentError] -> + 3 + end + + assert value == 3 + end + +end From fb93e94af13443650c1f928021b229f7dc11cbe5 Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Wed, 1 Nov 2017 20:12:25 -0500 Subject: [PATCH 798/860] Add vendor.build.js to ebert config ignore --- .ebert.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.ebert.yml b/.ebert.yml index de120782..06a1d128 100644 --- a/.ebert.yml +++ b/.ebert.yml @@ -11,3 +11,4 @@ engines: exclude_paths: - config - test +- priv/testrunner/vendor.build.js From 55d745e8bacfb36f440fd6d2e09cb6b3a328571e Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Wed, 1 Nov 2017 20:14:41 -0500 Subject: [PATCH 799/860] Add esm folder to ebert ignore --- .ebert.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.ebert.yml b/.ebert.yml index 06a1d128..148907f7 100644 --- a/.ebert.yml +++ b/.ebert.yml @@ -12,3 +12,4 @@ exclude_paths: - config - test - priv/testrunner/vendor.build.js +- priv/testrunner/esm From 84d26e0ae9a4552b0e31d47fa1c05a5e239573de Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Wed, 1 Nov 2017 20:17:33 -0500 Subject: [PATCH 800/860] Fix lints --- .../passes/translate/forms/try.ex | 28 +++++++++++++------ 1 file changed, 19 insertions(+), 9 deletions(-) diff --git a/lib/elixir_script/passes/translate/forms/try.ex b/lib/elixir_script/passes/translate/forms/try.ex index e086d310..46add57f 100644 --- a/lib/elixir_script/passes/translate/forms/try.ex +++ b/lib/elixir_script/passes/translate/forms/try.ex @@ -62,20 +62,30 @@ defmodule ElixirScript.Translate.Forms.Try do names = Enum.map(names, &make_exception_ast(&1)) param = {:_e, context, atom} - reasonCall = {{:., [], [{:_e0, context, atom}, :__reason]}, [], []} - reasonCall = {{:., [], [reasonCall, :__struct__]}, [], []} - reasonCall = {{:., [], [reasonCall, :__MODULE__]}, [], []} - - {ast, _} = Clause.compile({[], [param], [{{:., [], [Enum, :member?]}, [], [names, reasonCall]}], body}, state) + reason_call = {{:., [], [{:_e0, context, atom}, :__reason]}, [], []} + reason_call = {{:., [], [reason_call, :__struct__]}, [], []} + reason_call = {{:., [], [reason_call, :__MODULE__]}, [], []} + + {ast, _} = Clause.compile({ + [], + [param], + [{{:., [], [Enum, :member?]}, [], [names, reason_call]}], + body}, + state) ast {:->, _, [ [{:in, _, [param, names]}], body]} -> names = Enum.map(names, &make_exception_ast(&1)) - reasonCall = {{:., [], [param, :__reason]}, [], []} - reasonCall = {{:., [], [reasonCall, :__struct__]}, [], []} - reasonCall = {{:., [], [reasonCall, :__MODULE__]}, [], []} + reason_call = {{:., [], [param, :__reason]}, [], []} + reason_call = {{:., [], [reason_call, :__struct__]}, [], []} + reason_call = {{:., [], [reason_call, :__MODULE__]}, [], []} - {ast, _} = Clause.compile({[], [param], [{{:., [], [Enum, :member?]}, [], [names, reasonCall]}], body}, state) + {ast, _} = Clause.compile({ + [], + [param], + [{{:., [], [Enum, :member?]}, [], [names, reason_call]}], + body}, + state) ast {:->, _, [ [param], body]} -> {ast, _} = Clause.compile({[], [param], [], body}, state) From 0335c44909f8d844d2e0511289c4b52316c00b26 Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Wed, 1 Nov 2017 20:22:22 -0500 Subject: [PATCH 801/860] Fix more lints --- lib/elixir_script_test/test.ex | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/lib/elixir_script_test/test.ex b/lib/elixir_script_test/test.ex index 60a2dee3..c1f5bb6a 100644 --- a/lib/elixir_script_test/test.ex +++ b/lib/elixir_script_test/test.ex @@ -72,7 +72,6 @@ defmodule ElixirScript.Test do ``` """ - defmacro __using__(_opts) do quote do import ElixirScript.Test.Callbacks, only: [ @@ -84,7 +83,7 @@ defmodule ElixirScript.Test do ] import ExUnit.Assertions - def __elixirscript_test_module__(), do: true + def __elixirscript_test_module__, do: true end end @@ -118,7 +117,13 @@ defmodule ElixirScript.Test do defp node_test_runner(js_files) do test_script_path = Path.join([:code.priv_dir(:elixir_script), "testrunner", "index.js"]) - {_, exit_status} = System.cmd "node", [test_script_path] ++ js_files, into: IO.stream(:stdio, :line) + test_script_path = [test_script_path] ++ js_files + {_, exit_status} = System.cmd( + "node", + test_script_path, + into: IO.stream(:stdio, :line) + ) + exit_status end end From 14670266b0afe6a1b9c67438eb81921687c41f62 Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Wed, 1 Nov 2017 20:24:56 -0500 Subject: [PATCH 802/860] Rebuild vendor.build.js --- priv/testrunner/vendor.build.js | 406 +------------------------------- 1 file changed, 2 insertions(+), 404 deletions(-) diff --git a/priv/testrunner/vendor.build.js b/priv/testrunner/vendor.build.js index 6e808208..9d49e34d 100644 --- a/priv/testrunner/vendor.build.js +++ b/priv/testrunner/vendor.build.js @@ -1,404 +1,2 @@ -class Tuple { - constructor(...args) { - this.values = Object.freeze(args); - this.length = this.values.length; - } - - get(index) { - return this.values[index]; - } - - count() { - return this.values.length; - } - - [Symbol.iterator]() { - return this.values[Symbol.iterator](); - } - - toString() { - let i, - s = ''; - for (i = 0; i < this.values.length; i++) { - if (s !== '') { - s += ', '; - } - - const stringToAppend = this.values[i] ? this.values[i].toString() : ''; - - s += stringToAppend; - } - - return '{' + s + '}'; - } - - put_elem(index, elem) { - if (index === this.length) { - let new_values = this.values.concat([elem]); - return new Tuple(...new_values); - } - - let new_values = this.values.concat([]); - new_values.splice(index, 0, elem); - return new Tuple(...new_values); - } - - remove_elem(index) { - let new_values = this.values.concat([]); - new_values.splice(index, 1); - return new Tuple(...new_values); - } -} - -let process_counter = -1; - -class PID { - constructor() { - process_counter = process_counter + 1; - this.id = process_counter; - } - - toString() { - return 'PID#<0.' + this.id + '.0>'; - } -} - -let ref_counter = -1; - -class Reference { - constructor() { - ref_counter = ref_counter + 1; - this.id = ref_counter; - this.ref = Symbol(); - } - - toString() { - return 'Ref#<0.0.0.' + this.id + '>'; - } -} - -class BitString { - constructor(...args) { - this.value = Object.freeze(this.process(args)); - this.length = this.value.length; - this.bit_size = this.length * 8; - this.byte_size = this.length; - } - - get(index) { - return this.value[index]; - } - - count() { - return this.value.length; - } - - slice(start, end = null) { - let s = this.value.slice(start, end); - let ms = s.map(elem => BitString.integer(elem)); - return new BitString(...ms); - } - - [Symbol.iterator]() { - return this.value[Symbol.iterator](); - } - - toString() { - var i, - s = ''; - for (i = 0; i < this.count(); i++) { - if (s !== '') { - s += ', '; - } - s += this.get(i).toString(); - } - - return '<<' + s + '>>'; - } - - process(bitStringParts) { - let processed_values = []; - - var i; - for (i = 0; i < bitStringParts.length; i++) { - let processed_value = this['process_' + bitStringParts[i].type](bitStringParts[i]); - - for (let attr of bitStringParts[i].attributes) { - processed_value = this['process_' + attr](processed_value); - } - - processed_values = processed_values.concat(processed_value); - } - - return processed_values; - } - - process_integer(value) { - return value.value; - } - - process_float(value) { - if (value.size === 64) { - return BitString.float64ToBytes(value.value); - } else if (value.size === 32) { - return BitString.float32ToBytes(value.value); - } - - throw new Error('Invalid size for float'); - } - - process_bitstring(value) { - return value.value.value; - } - - process_binary(value) { - return BitString.toUTF8Array(value.value); - } - - process_utf8(value) { - return BitString.toUTF8Array(value.value); - } - - process_utf16(value) { - return BitString.toUTF16Array(value.value); - } - - process_utf32(value) { - return BitString.toUTF32Array(value.value); - } - - process_signed(value) { - return new Uint8Array([value])[0]; - } - - process_unsigned(value) { - return value; - } - - process_native(value) { - return value; - } - - process_big(value) { - return value; - } - - process_little(value) { - return value.reverse(); - } - - process_size(value) { - return value; - } - - process_unit(value) { - return value; - } - - static integer(value) { - return BitString.wrap(value, { type: 'integer', unit: 1, size: 8 }); - } - - static float(value) { - return BitString.wrap(value, { type: 'float', unit: 1, size: 64 }); - } - - static bitstring(value) { - return BitString.wrap(value, { - type: 'bitstring', - unit: 1, - size: value.bit_size - }); - } - - static bits(value) { - return BitString.bitstring(value); - } - - static binary(value) { - return BitString.wrap(value, { - type: 'binary', - unit: 8, - size: value.length - }); - } - - static bytes(value) { - return BitString.binary(value); - } - - static utf8(value) { - return BitString.wrap(value, { type: 'utf8', unit: 1, size: value.length }); - } - - static utf16(value) { - return BitString.wrap(value, { - type: 'utf16', - unit: 1, - size: value.length * 2 - }); - } - - static utf32(value) { - return BitString.wrap(value, { - type: 'utf32', - unit: 1, - size: value.length * 4 - }); - } - - static signed(value) { - return BitString.wrap(value, {}, 'signed'); - } - - static unsigned(value) { - return BitString.wrap(value, {}, 'unsigned'); - } - - static native(value) { - return BitString.wrap(value, {}, 'native'); - } - - static big(value) { - return BitString.wrap(value, {}, 'big'); - } - - static little(value) { - return BitString.wrap(value, {}, 'little'); - } - - static size(value, count) { - return BitString.wrap(value, { size: count }); - } - - static unit(value, count) { - return BitString.wrap(value, { unit: count }); - } - - static wrap(value, opt, new_attribute = null) { - let the_value = value; - - if (!(value instanceof Object)) { - the_value = { value: value, attributes: [] }; - } - - the_value = Object.assign(the_value, opt); - - if (new_attribute) { - the_value.attributes.push(new_attribute); - } - - return the_value; - } - - static toUTF8Array(str) { - var utf8 = []; - for (var i = 0; i < str.length; i++) { - var charcode = str.charCodeAt(i); - if (charcode < 0x80) { - utf8.push(charcode); - } else if (charcode < 0x800) { - utf8.push(0xc0 | charcode >> 6, 0x80 | charcode & 0x3f); - } else if (charcode < 0xd800 || charcode >= 0xe000) { - utf8.push(0xe0 | charcode >> 12, 0x80 | charcode >> 6 & 0x3f, 0x80 | charcode & 0x3f); - } else { - // surrogate pair - i++; - // UTF-16 encodes 0x10000-0x10FFFF by - // subtracting 0x10000 and splitting the - // 20 bits of 0x0-0xFFFFF into two halves - charcode = 0x10000 + ((charcode & 0x3ff) << 10 | str.charCodeAt(i) & 0x3ff); - utf8.push(0xf0 | charcode >> 18, 0x80 | charcode >> 12 & 0x3f, 0x80 | charcode >> 6 & 0x3f, 0x80 | charcode & 0x3f); - } - } - return utf8; - } - - static toUTF16Array(str) { - var utf16 = []; - for (var i = 0; i < str.length; i++) { - var codePoint = str.codePointAt(i); - - if (codePoint <= 255) { - utf16.push(0); - utf16.push(codePoint); - } else { - utf16.push(codePoint >> 8 & 0xff); - utf16.push(codePoint & 0xff); - } - } - return utf16; - } - - static toUTF32Array(str) { - var utf32 = []; - for (var i = 0; i < str.length; i++) { - var codePoint = str.codePointAt(i); - - if (codePoint <= 255) { - utf32.push(0); - utf32.push(0); - utf32.push(0); - utf32.push(codePoint); - } else { - utf32.push(0); - utf32.push(0); - utf32.push(codePoint >> 8 & 0xff); - utf32.push(codePoint & 0xff); - } - } - return utf32; - } - - //http://stackoverflow.com/questions/2003493/javascript-float-from-to-bits - static float32ToBytes(f) { - var bytes = []; - - var buf = new ArrayBuffer(4); - new Float32Array(buf)[0] = f; - - let intVersion = new Uint32Array(buf)[0]; - - bytes.push(intVersion >> 24 & 0xff); - bytes.push(intVersion >> 16 & 0xff); - bytes.push(intVersion >> 8 & 0xff); - bytes.push(intVersion & 0xff); - - return bytes; - } - - static float64ToBytes(f) { - var bytes = []; - - var buf = new ArrayBuffer(8); - new Float64Array(buf)[0] = f; - - var intVersion1 = new Uint32Array(buf)[0]; - var intVersion2 = new Uint32Array(buf)[1]; - - bytes.push(intVersion2 >> 24 & 0xff); - bytes.push(intVersion2 >> 16 & 0xff); - bytes.push(intVersion2 >> 8 & 0xff); - bytes.push(intVersion2 & 0xff); - - bytes.push(intVersion1 >> 24 & 0xff); - bytes.push(intVersion1 >> 16 & 0xff); - bytes.push(intVersion1 >> 8 & 0xff); - bytes.push(intVersion1 & 0xff); - - return bytes; - } -} - -var ErlangTypes = { - Tuple, - PID, - Reference, - BitString -}; - -var vendor = { - ErlangTypes -}; - -export default vendor; +class Tuple{constructor(...a){this.values=Object.freeze(a),this.length=this.values.length}get(a){return this.values[a]}count(){return this.values.length}[Symbol.iterator](){return this.values[Symbol.iterator]()}toString(){let a,b='';for(a=0;a'}}let ref_counter=-1;class Reference{constructor(){++ref_counter,this.id=ref_counter,this.ref=Symbol()}toString(){return'Ref#<0.0.0.'+this.id+'>'}}class BitString{constructor(...a){this.value=Object.freeze(this.process(a)),this.length=this.value.length,this.bit_size=8*this.length,this.byte_size=this.length}get(a){return this.value[a]}count(){return this.value.length}slice(a,b=null){let c=this.value.slice(a,b),d=c.map((a)=>BitString.integer(a));return new BitString(...d)}[Symbol.iterator](){return this.value[Symbol.iterator]()}toString(){var a,b='';for(a=0;a>'}process(a){let b=[];var c;for(c=0;cb?c.push(b):2048>b?c.push(192|b>>6,128|63&b):55296>b||57344<=b?c.push(224|b>>12,128|63&b>>6,128|63&b):(d++,b=65536+((1023&b)<<10|1023&a.charCodeAt(d)),c.push(240|b>>18,128|63&b>>12,128|63&b>>6,128|63&b));return c}static toUTF16Array(a){for(var b,c=[],d=0;d=b?(c.push(0),c.push(b)):(c.push(255&b>>8),c.push(255&b));return c}static toUTF32Array(a){for(var b,c=[],d=0;d=b?(c.push(0),c.push(0),c.push(0),c.push(b)):(c.push(0),c.push(0),c.push(255&b>>8),c.push(255&b));return c}//http://stackoverflow.com/questions/2003493/javascript-float-from-to-bits +static float32ToBytes(a){var b=[],c=new ArrayBuffer(4);new Float32Array(c)[0]=a;let d=new Uint32Array(c)[0];return b.push(255&d>>24),b.push(255&d>>16),b.push(255&d>>8),b.push(255&d),b}static float64ToBytes(a){var b=[],c=new ArrayBuffer(8);new Float64Array(c)[0]=a;var d=new Uint32Array(c)[0],e=new Uint32Array(c)[1];return b.push(255&e>>24),b.push(255&e>>16),b.push(255&e>>8),b.push(255&e),b.push(255&d>>24),b.push(255&d>>16),b.push(255&d>>8),b.push(255&d),b}}var ErlangTypes={Tuple,PID,Reference,BitString},vendor={ErlangTypes};export default vendor; From a0f27a6e88e33a3eb97ce1c88271a567a0db2507 Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Sun, 5 Nov 2017 21:59:02 -0600 Subject: [PATCH 803/860] Using alias for FindUnusedFunctions --- lib/elixir_script/compiler.ex | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/elixir_script/compiler.ex b/lib/elixir_script/compiler.ex index e254f943..ba0f869b 100644 --- a/lib/elixir_script/compiler.ex +++ b/lib/elixir_script/compiler.ex @@ -75,7 +75,7 @@ defmodule ElixirScript.Compiler do FindUsedModules.execute(entry_modules, pid) if opts.remove_unused_functions do - ElixirScript.FindUsedFunctions.execute(entry_modules, pid) + FindUsedFunctions.execute(entry_modules, pid) end modules = State.list_modules(pid) From c2fd9000b53bc1e1814cbb6102e2fd418068c35c Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Thu, 9 Nov 2017 19:08:54 -0600 Subject: [PATCH 804/860] Write to manifest --- .gitignore | 1 + lib/elixir_script/beam.ex | 10 +++++-- lib/elixir_script/manifest.ex | 28 +++++++++++++++++++ lib/elixir_script/passes/find_used_modules.ex | 10 ++++--- lib/elixir_script/passes/output.ex | 26 +++++++---------- test/beam_test.exs | 2 +- 6 files changed, 53 insertions(+), 24 deletions(-) create mode 100644 lib/elixir_script/manifest.ex diff --git a/.gitignore b/.gitignore index 77a9c54a..1a813296 100644 --- a/.gitignore +++ b/.gitignore @@ -24,3 +24,4 @@ cover /priv/build /tmp .esm-cache +.elixir_ls diff --git a/lib/elixir_script/beam.ex b/lib/elixir_script/beam.ex index 254cb803..b4ccb69d 100644 --- a/lib/elixir_script/beam.ex +++ b/lib/elixir_script/beam.ex @@ -59,7 +59,7 @@ defmodule ElixirScript.Beam do {:ok, {^module, attribute_info}} = :beam_lib.chunks(beam, [:attributes]) do if Keyword.get(attribute_info[:attributes], :protocol) do - get_protocol_implementations(module) + get_protocol_implementations(module, beam_path) else backend.debug_info(:elixir_v1, module, data, []) |> process_debug_info(beam_path) @@ -89,6 +89,8 @@ defmodule ElixirScript.Beam do Map.put(info, :last_modified, nil) end + info = Map.put(info, :beam_path, beam_path) + {:ok, info} end @@ -96,7 +98,9 @@ defmodule ElixirScript.Beam do error end - defp get_protocol_implementations(module) do + defp get_protocol_implementations(module, beam_path) do + {:ok, protocol_module_info} = process_debug_info({:ok, %{}}, beam_path) + implementations = module |> Protocol.extract_impls(:code.get_path()) |> Enum.map(fn(x) -> Module.concat([module, x]) end) @@ -109,7 +113,7 @@ defmodule ElixirScript.Beam do end end) - {:ok, module, implementations} + {:ok, module, protocol_module_info, implementations} end defp replace_definitions(original_definitions, replacement_definitions) do diff --git a/lib/elixir_script/manifest.ex b/lib/elixir_script/manifest.ex new file mode 100644 index 00000000..5904620a --- /dev/null +++ b/lib/elixir_script/manifest.ex @@ -0,0 +1,28 @@ +defmodule ElixirScript.Manifest do + @moduledoc false + + @spec read_manifest(binary) :: nil + def read_manifest(_manifest) do + + end + + @spec write_manifest(binary, [{atom, map}]) :: :ok + def write_manifest(manifest_path, modules) do + data = Enum.reduce(modules, %{}, fn {module, info}, current_data -> + info = %{ + references: info.used_modules, + last_modified: info.last_modified, + beam_path: Map.get(info, :beam_path), + source: Map.get(info, :file), + js_path: "Elixir.#{module}.js" + } + Map.put(current_data, module, info) + end) + + data = :erlang.term_to_binary(data, [:compressed]) + File.mkdir_p!(Path.dirname(manifest_path)) + File.write!(manifest_path, data) + + :ok + end +end diff --git a/lib/elixir_script/passes/find_used_modules.ex b/lib/elixir_script/passes/find_used_modules.ex index ae75d9e6..c37921b0 100644 --- a/lib/elixir_script/passes/find_used_modules.ex +++ b/lib/elixir_script/passes/find_used_modules.ex @@ -26,8 +26,8 @@ defmodule ElixirScript.FindUsedModules do case result do {:ok, info} -> walk_module(module, info, pid) - {:ok, module, implementations} -> - walk_protocol(module, implementations, pid) + {:ok, module, module_info, implementations} -> + walk_protocol(module, module_info, implementations, pid) {:error, "Unknown module"} -> Logger.warn fn() -> "ElixirScript: #{inspect module} is missing or unavailable" @@ -83,7 +83,7 @@ defmodule ElixirScript.FindUsedModules do end) end - defp walk_protocol(module, implementations, pid) do + defp walk_protocol(module, module_info, implementations, pid) do impls = Enum.map(implementations, fn {impl, %{attributes: attrs}} -> protocol_impl = Keyword.fetch!(attrs, :protocol_impl) impl_for = Keyword.fetch!(protocol_impl, :for) @@ -94,7 +94,9 @@ defmodule ElixirScript.FindUsedModules do functions = Enum.map(first_implementation_functions, fn { name, _, _, _} -> name end) - ModuleState.put_module(pid, module, %{protocol: true, impls: impls, functions: functions}) + module_info = Map.merge(module_info, %{protocol: true, impls: impls, functions: functions}) + + ModuleState.put_module(pid, module, module_info) Enum.each(implementations, fn {impl, info} -> ModuleState.add_used_module(pid, module, impl) diff --git a/lib/elixir_script/passes/output.ex b/lib/elixir_script/passes/output.ex index baaf05ba..0a2aa011 100644 --- a/lib/elixir_script/passes/output.ex +++ b/lib/elixir_script/passes/output.ex @@ -3,13 +3,14 @@ defmodule ElixirScript.Output do alias ElixirScript.State, as: ModuleState alias ESTree.Tools.{Builder, Generator} + alias ElixirScript.Manifest @doc """ Takes outputs the JavaScript code in the specified output """ - @spec execute([atom], pid, map) :: nil + @spec execute([atom], pid, map) :: any def execute(modules, pid, opts) do - modules = modules + prepared_modules = modules |> Enum.filter(fn {_, info} -> Map.has_key?(info, :js_ast) end) |> Enum.map(fn {module, info} -> {module, info.js_ast, info.used_modules} @@ -27,8 +28,13 @@ defmodule ElixirScript.Output do {module, name, path, import_path} end) - modules - |> create_modules(opts, js_modules) + + result = create_modules(prepared_modules, opts, js_modules) + + manifest_path = Path.join(Mix.Project.manifest_path(), ".compile.elixir_script") + Manifest.write_manifest(manifest_path, modules) + + result end defp concat(code) do @@ -39,17 +45,6 @@ defmodule ElixirScript.Output do """ end - defp prepare_js_ast(js_ast) do - case js_ast do - modules when is_list(modules) -> - modules - |> Enum.reduce([], &(&2 ++ &1.body)) - |> Builder.program - _ -> - js_ast - end - end - defp create_modules(modules, opts, js_modules) do modules |> Task.async_stream(fn({module, [body, exports], used_modules}) -> @@ -62,7 +57,6 @@ defmodule ElixirScript.Output do js_parts |> Builder.program - |> prepare_js_ast |> Generator.generate |> concat |> output(module, Map.get(opts, :output), js_modules) diff --git a/test/beam_test.exs b/test/beam_test.exs index bc6671a3..66369a94 100644 --- a/test/beam_test.exs +++ b/test/beam_test.exs @@ -10,6 +10,6 @@ defmodule ElixirScript.Beam.Test do end test "can get ast from beam that is protocol" do - assert {:ok, Enumerable, _} = ElixirScript.Beam.debug_info(Enumerable) + assert {:ok, Enumerable, _, _} = ElixirScript.Beam.debug_info(Enumerable) end end From 3ae89c6e650c4d918e6054b8556b3e6c6259c314 Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Thu, 9 Nov 2017 19:27:02 -0600 Subject: [PATCH 805/860] Move manifest writing to top level of compiler --- lib/elixir_script/compiler.ex | 8 ++++++-- lib/elixir_script/manifest.ex | 4 ++-- lib/elixir_script/passes/output.ex | 8 +------- lib/mix/tasks/compile.elixir_script.ex | 5 +++++ 4 files changed, 14 insertions(+), 11 deletions(-) diff --git a/lib/elixir_script/compiler.ex b/lib/elixir_script/compiler.ex index ba0f869b..833c19a5 100644 --- a/lib/elixir_script/compiler.ex +++ b/lib/elixir_script/compiler.ex @@ -31,12 +31,13 @@ defmodule ElixirScript.Compiler do Translate, FindUsedModules, FindUsedFunctions, - Output + Output, + Manifest, } alias ElixirScript.ModuleSystems.ES alias Kernel.ParallelCompiler - @spec compile(atom | [atom] | binary, []) :: nil + @spec compile(atom | [atom] | binary, []) :: [{atom, map}] def compile(path, opts \\ []) def compile(path, opts) when is_binary(path) do @@ -86,6 +87,9 @@ defmodule ElixirScript.Compiler do State.stop(pid) + manifest_path = Path.join(Mix.Project.manifest_path(), ".compile.elixir_script") + Manifest.write_manifest(manifest_path, modules, opts) + result end diff --git a/lib/elixir_script/manifest.ex b/lib/elixir_script/manifest.ex index 5904620a..89bae909 100644 --- a/lib/elixir_script/manifest.ex +++ b/lib/elixir_script/manifest.ex @@ -6,8 +6,8 @@ defmodule ElixirScript.Manifest do end - @spec write_manifest(binary, [{atom, map}]) :: :ok - def write_manifest(manifest_path, modules) do + @spec write_manifest(binary, [{atom, map}], map) :: :ok + def write_manifest(manifest_path, modules, _opts) do data = Enum.reduce(modules, %{}, fn {module, info}, current_data -> info = %{ references: info.used_modules, diff --git a/lib/elixir_script/passes/output.ex b/lib/elixir_script/passes/output.ex index 0a2aa011..2f54cb2c 100644 --- a/lib/elixir_script/passes/output.ex +++ b/lib/elixir_script/passes/output.ex @@ -3,7 +3,6 @@ defmodule ElixirScript.Output do alias ElixirScript.State, as: ModuleState alias ESTree.Tools.{Builder, Generator} - alias ElixirScript.Manifest @doc """ Takes outputs the JavaScript code in the specified output @@ -29,12 +28,7 @@ defmodule ElixirScript.Output do end) - result = create_modules(prepared_modules, opts, js_modules) - - manifest_path = Path.join(Mix.Project.manifest_path(), ".compile.elixir_script") - Manifest.write_manifest(manifest_path, modules) - - result + create_modules(prepared_modules, opts, js_modules) end defp concat(code) do diff --git a/lib/mix/tasks/compile.elixir_script.ex b/lib/mix/tasks/compile.elixir_script.ex index 617a92e4..ef353c04 100644 --- a/lib/mix/tasks/compile.elixir_script.ex +++ b/lib/mix/tasks/compile.elixir_script.ex @@ -2,6 +2,8 @@ defmodule Mix.Tasks.Compile.ElixirScript do use Mix.Task @recursive true + @manifest ".compile.elixir_script" + @manifest_vsn 1 @moduledoc """ Mix compiler to allow mix to compile Elixirscript source files into JavaScript @@ -48,6 +50,9 @@ defmodule Mix.Tasks.Compile.ElixirScript do :ok end + def manifests, do: [manifest()] + defp manifest, do: Path.join(Mix.Project.manifest_path(), @manifest) + @doc false def get_compiler_params() do elixirscript_config = get_elixirscript_config() From a9f15811eb2c76687f29d97e4915e7e23a100877 Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Thu, 9 Nov 2017 19:45:40 -0600 Subject: [PATCH 806/860] Fix lints --- lib/elixir_script/beam.ex | 2 +- lib/elixir_script/passes/find_used_modules.ex | 24 ++++++++++--------- lib/elixir_script/passes/output.ex | 1 - 3 files changed, 14 insertions(+), 13 deletions(-) diff --git a/lib/elixir_script/beam.ex b/lib/elixir_script/beam.ex index b4ccb69d..4473f221 100644 --- a/lib/elixir_script/beam.ex +++ b/lib/elixir_script/beam.ex @@ -7,7 +7,7 @@ defmodule ElixirScript.Beam do For protocols, this will return a list of all the protocol implementations """ - @spec debug_info(atom | bitstring) :: {:ok | :error, map | binary} + @spec debug_info(atom | bitstring) :: {:ok, map} | {:ok, atom, map, list} | {:error, binary} def debug_info(module) # We get debug info from String and then replace diff --git a/lib/elixir_script/passes/find_used_modules.ex b/lib/elixir_script/passes/find_used_modules.ex index c37921b0..d738a006 100644 --- a/lib/elixir_script/passes/find_used_modules.ex +++ b/lib/elixir_script/passes/find_used_modules.ex @@ -6,7 +6,7 @@ defmodule ElixirScript.FindUsedModules do @doc """ Takes a list of entry modules and finds modules they use. """ - @spec execute([atom], pid) :: nil + @spec execute([atom], pid) :: :ok def execute(modules, pid) do modules |> List.wrap @@ -94,7 +94,10 @@ defmodule ElixirScript.FindUsedModules do functions = Enum.map(first_implementation_functions, fn { name, _, _, _} -> name end) - module_info = Map.merge(module_info, %{protocol: true, impls: impls, functions: functions}) + module_info = Map.merge( + module_info, + %{protocol: true, impls: impls, functions: functions} + ) ModuleState.put_module(pid, module, module_info) @@ -305,15 +308,14 @@ defmodule ElixirScript.FindUsedModules do end defp walk({:., _, [module, function]}, state) do - cond do - ElixirScript.Translate.Module.is_elixir_module(module) -> - ModuleState.add_used_module(state.pid, state.module, module) - if ModuleState.get_module(state.pid, module) == nil do - do_execute(module, state.pid) - end - true -> - walk(module, state) - walk(function, state) + if ElixirScript.Translate.Module.is_elixir_module(module) do + ModuleState.add_used_module(state.pid, state.module, module) + if ModuleState.get_module(state.pid, module) == nil do + do_execute(module, state.pid) + end + else + walk(module, state) + walk(function, state) end end diff --git a/lib/elixir_script/passes/output.ex b/lib/elixir_script/passes/output.ex index 2f54cb2c..e03d5fe1 100644 --- a/lib/elixir_script/passes/output.ex +++ b/lib/elixir_script/passes/output.ex @@ -27,7 +27,6 @@ defmodule ElixirScript.Output do {module, name, path, import_path} end) - create_modules(prepared_modules, opts, js_modules) end From a0e5eb1e7c1ab8e14b46cee7928ac1ca74c044aa Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Thu, 9 Nov 2017 20:07:19 -0600 Subject: [PATCH 807/860] Add output path for js_path --- lib/elixir_script/manifest.ex | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/lib/elixir_script/manifest.ex b/lib/elixir_script/manifest.ex index 89bae909..b9a61f3f 100644 --- a/lib/elixir_script/manifest.ex +++ b/lib/elixir_script/manifest.ex @@ -7,15 +7,22 @@ defmodule ElixirScript.Manifest do end @spec write_manifest(binary, [{atom, map}], map) :: :ok - def write_manifest(manifest_path, modules, _opts) do + def write_manifest(manifest_path, modules, opts) do + output_path = if opts.output == nil or opts.output == :stdout do + "" + else + Path.dirname(opts.output) + end + data = Enum.reduce(modules, %{}, fn {module, info}, current_data -> info = %{ references: info.used_modules, last_modified: info.last_modified, beam_path: Map.get(info, :beam_path), source: Map.get(info, :file), - js_path: "Elixir.#{module}.js" + js_path: Path.join(output_path, "#{module}.js") } + Map.put(current_data, module, info) end) From cda84c3c5de070736f26f152de0e27d4d0d128f0 Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Thu, 9 Nov 2017 20:14:01 -0600 Subject: [PATCH 808/860] Update lint settings --- .credo.exs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.credo.exs b/.credo.exs index 74864ac4..ab405b15 100644 --- a/.credo.exs +++ b/.credo.exs @@ -61,7 +61,7 @@ {Credo.Check.Readability.FunctionNames}, {Credo.Check.Readability.LargeNumbers}, - {Credo.Check.Readability.MaxLineLength, priority: :low, max_length: 80}, + {Credo.Check.Readability.MaxLineLength, priority: :low, max_length: 80, ignore_specs: true}, {Credo.Check.Readability.ModuleAttributeNames}, {Credo.Check.Readability.ModuleDoc}, {Credo.Check.Readability.ModuleNames}, @@ -70,7 +70,7 @@ {Credo.Check.Readability.PredicateFunctionNames}, {Credo.Check.Readability.PreferImplicitTry}, {Credo.Check.Readability.RedundantBlankLines}, - {Credo.Check.Readability.Specs}, + {Credo.Check.Readability.Specs, false}, {Credo.Check.Readability.StringSigils}, {Credo.Check.Readability.TrailingBlankLine}, {Credo.Check.Readability.TrailingWhiteSpace}, From 3c8dcd19dbb01a5f59e1360e951cd7f5dba36ddb Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Thu, 9 Nov 2017 22:54:00 -0600 Subject: [PATCH 809/860] Move manifest writing to the mix compiler --- lib/elixir_script/compiler.ex | 29 ++++++++++++++++++++------ lib/elixir_script/manifest.ex | 20 +++--------------- lib/elixir_script/passes/output.ex | 12 +++++------ lib/mix/tasks/compile.elixir_script.ex | 5 ++++- test/compiler_test.exs | 6 +++--- 5 files changed, 39 insertions(+), 33 deletions(-) diff --git a/lib/elixir_script/compiler.ex b/lib/elixir_script/compiler.ex index 833c19a5..0621238e 100644 --- a/lib/elixir_script/compiler.ex +++ b/lib/elixir_script/compiler.ex @@ -32,12 +32,11 @@ defmodule ElixirScript.Compiler do FindUsedModules, FindUsedFunctions, Output, - Manifest, } alias ElixirScript.ModuleSystems.ES alias Kernel.ParallelCompiler - @spec compile(atom | [atom] | binary, []) :: [{atom, map}] + @spec compile(atom | [atom] | binary, []) :: map def compile(path, opts \\ []) def compile(path, opts) when is_binary(path) do @@ -87,10 +86,7 @@ defmodule ElixirScript.Compiler do State.stop(pid) - manifest_path = Path.join(Mix.Project.manifest_path(), ".compile.elixir_script") - Manifest.write_manifest(manifest_path, modules, opts) - - result + transform_output(modules, result, opts) end defp build_compiler_options(opts) do @@ -107,4 +103,25 @@ defmodule ElixirScript.Compiler do defp on_module_compile(pid, _file, module, beam) do State.put_in_memory_module(pid, module, beam) end + + defp transform_output(modules, compiled_js, opts) do + output_path = if opts.output == nil or opts.output == :stdout do + "" + else + Path.dirname(opts.output) + end + + Enum.reduce(modules, %{}, fn {module, info}, current_data -> + info = %{ + references: info.used_modules, + last_modified: info.last_modified, + beam_path: Map.get(info, :beam_path), + source: Map.get(info, :file), + js_path: Path.join(output_path, "#{module}.js"), + js_code: Keyword.get(compiled_js, module) + } + + Map.put(current_data, module, info) + end) + end end diff --git a/lib/elixir_script/manifest.ex b/lib/elixir_script/manifest.ex index b9a61f3f..d0380610 100644 --- a/lib/elixir_script/manifest.ex +++ b/lib/elixir_script/manifest.ex @@ -6,24 +6,10 @@ defmodule ElixirScript.Manifest do end - @spec write_manifest(binary, [{atom, map}], map) :: :ok - def write_manifest(manifest_path, modules, opts) do - output_path = if opts.output == nil or opts.output == :stdout do - "" - else - Path.dirname(opts.output) - end - + @spec write_manifest(binary, map) :: :ok + def write_manifest(manifest_path, modules) do data = Enum.reduce(modules, %{}, fn {module, info}, current_data -> - info = %{ - references: info.used_modules, - last_modified: info.last_modified, - beam_path: Map.get(info, :beam_path), - source: Map.get(info, :file), - js_path: Path.join(output_path, "#{module}.js") - } - - Map.put(current_data, module, info) + Map.put(current_data, module, Map.drop(info, :js_code)) end) data = :erlang.term_to_binary(data, [:compressed]) diff --git a/lib/elixir_script/passes/output.ex b/lib/elixir_script/passes/output.ex index e03d5fe1..26ccc96b 100644 --- a/lib/elixir_script/passes/output.ex +++ b/lib/elixir_script/passes/output.ex @@ -7,7 +7,7 @@ defmodule ElixirScript.Output do @doc """ Takes outputs the JavaScript code in the specified output """ - @spec execute([atom], pid, map) :: any + @spec execute([atom], pid, map) :: [{atom, binary}] def execute(modules, pid, opts) do prepared_modules = modules |> Enum.filter(fn {_, info} -> Map.has_key?(info, :js_ast) end) @@ -71,12 +71,10 @@ defmodule ElixirScript.Output do |> String.replace(".", "$") end - defp output(code, _, nil, _) do - code - end - - defp output(code, _, :stdout, _) do + defp output(code, module, nil, _), do: {module, code} + defp output(code, module, :stdout, _) do IO.puts(code) + {module, code} end defp output(code, module, path, js_modules) do @@ -99,6 +97,8 @@ defmodule ElixirScript.Output do copy_bootstrap_js(output_dir) File.write!(file_name, code) + + {module, code} end defp copy_bootstrap_js(directory) do diff --git a/lib/mix/tasks/compile.elixir_script.ex b/lib/mix/tasks/compile.elixir_script.ex index ef353c04..cdb05da9 100644 --- a/lib/mix/tasks/compile.elixir_script.ex +++ b/lib/mix/tasks/compile.elixir_script.ex @@ -1,5 +1,6 @@ defmodule Mix.Tasks.Compile.ElixirScript do use Mix.Task + alias ElixirScript.Manifest @recursive true @manifest ".compile.elixir_script" @@ -43,7 +44,9 @@ defmodule Mix.Tasks.Compile.ElixirScript do defp do_compile() do {input, opts} = get_compiler_params() - ElixirScript.Compiler.compile(input, opts) + result = ElixirScript.Compiler.compile(input, opts) + + Manifest.write_manifest(manifest(), result) end def clean do diff --git a/test/compiler_test.exs b/test/compiler_test.exs index b4d82ec5..439975f5 100644 --- a/test/compiler_test.exs +++ b/test/compiler_test.exs @@ -3,17 +3,17 @@ defmodule ElixirScript.Compiler.Test do test "Can compile one entry module" do result = ElixirScript.Compiler.compile(Version) - assert is_binary(hd(result)) + assert result |> Map.to_list |> hd |> elem(1) |> Map.get(:js_code) |> is_binary end test "Can compile multiple entry modules" do result = ElixirScript.Compiler.compile([Atom, String, Agent]) - assert is_binary(hd(result)) + assert result |> Map.to_list |> hd |> elem(1) |> Map.get(:js_code) |> is_binary end test "Output" do result = ElixirScript.Compiler.compile(Atom, []) - assert hd(result) =~ "export default" + assert result |> Map.to_list |> hd |> elem(1) |> Map.get(:js_code) =~ "export default" end test "compile file" do From cf0b415c270430d5bc69274d03a033344fa878a8 Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Fri, 10 Nov 2017 08:56:00 -0600 Subject: [PATCH 810/860] Fix lint --- .credo.exs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/.credo.exs b/.credo.exs index ab405b15..f7a2bbb3 100644 --- a/.credo.exs +++ b/.credo.exs @@ -61,7 +61,9 @@ {Credo.Check.Readability.FunctionNames}, {Credo.Check.Readability.LargeNumbers}, - {Credo.Check.Readability.MaxLineLength, priority: :low, max_length: 80, ignore_specs: true}, + {Credo.Check.Readability.MaxLineLength, + priority: :low, max_length: 80, ignore_specs: true + }, {Credo.Check.Readability.ModuleAttributeNames}, {Credo.Check.Readability.ModuleDoc}, {Credo.Check.Readability.ModuleNames}, From 016c77497ede3a0d14d5ece2260a275e6dcba294 Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Sat, 11 Nov 2017 07:52:57 -0600 Subject: [PATCH 811/860] Add manifest test --- lib/elixir_script/manifest.ex | 2 +- test/manifest_test.exs | 12 ++++++++++++ 2 files changed, 13 insertions(+), 1 deletion(-) create mode 100644 test/manifest_test.exs diff --git a/lib/elixir_script/manifest.ex b/lib/elixir_script/manifest.ex index d0380610..5ed1915f 100644 --- a/lib/elixir_script/manifest.ex +++ b/lib/elixir_script/manifest.ex @@ -9,7 +9,7 @@ defmodule ElixirScript.Manifest do @spec write_manifest(binary, map) :: :ok def write_manifest(manifest_path, modules) do data = Enum.reduce(modules, %{}, fn {module, info}, current_data -> - Map.put(current_data, module, Map.drop(info, :js_code)) + Map.put(current_data, module, Map.drop(info, [:js_code])) end) data = :erlang.term_to_binary(data, [:compressed]) diff --git a/test/manifest_test.exs b/test/manifest_test.exs new file mode 100644 index 00000000..52efd044 --- /dev/null +++ b/test/manifest_test.exs @@ -0,0 +1,12 @@ +defmodule ElixirScript.Manifest.Test do + use ExUnit.Case + alias ElixirScript.Manifest + + test "write manifest" do + result = ElixirScript.Compiler.compile(Atom) + path = Path.join([System.tmp_dir(), "write_manifest_test", ".compile.elixir_script"]) + Manifest.write_manifest(path, result) + assert File.exists?(path) + end + +end From 874f9b06568a77a33283e5daa6665faa5ad5603e Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Sun, 3 Dec 2017 21:54:00 -0600 Subject: [PATCH 812/860] Making sure global ffi aren't added to imports. Make sure remove_unused_functions is respected --- .tool-versions | 6 +++--- lib/elixir_script/compiler.ex | 4 ++-- lib/elixir_script/module_systems/es.ex | 4 ++++ lib/elixir_script/passes/output.ex | 19 ++++++++++++------- lib/elixir_script/passes/translate/module.ex | 8 +++++++- lib/elixir_script/state.ex | 19 +++++++++++++++++-- lib/elixir_script_test/test.ex | 4 ++-- lib/elixir_script_test/test/callbacks.ex | 13 +++++++++++++ 8 files changed, 60 insertions(+), 17 deletions(-) diff --git a/.tool-versions b/.tool-versions index cb49a042..eb307d7d 100644 --- a/.tool-versions +++ b/.tool-versions @@ -1,3 +1,3 @@ -erlang 20.0 -elixir 1.5.0-otp-20 -nodejs 8.3.0 +erlang 20.1 +elixir 1.5.2-otp-20 +nodejs 8.9.1 diff --git a/lib/elixir_script/compiler.ex b/lib/elixir_script/compiler.ex index 0621238e..47136068 100644 --- a/lib/elixir_script/compiler.ex +++ b/lib/elixir_script/compiler.ex @@ -41,7 +41,7 @@ defmodule ElixirScript.Compiler do def compile(path, opts) when is_binary(path) do opts = build_compiler_options(opts) - {:ok, pid} = State.start_link() + {:ok, pid} = State.start_link(opts) path = if String.ends_with?(path, [".ex", ".exs"]) do path @@ -64,7 +64,7 @@ defmodule ElixirScript.Compiler do def compile(entry_modules, opts) do opts = build_compiler_options(opts) - {:ok, pid} = State.start_link() + {:ok, pid} = State.start_link(opts) entry_modules = List.wrap(entry_modules) diff --git a/lib/elixir_script/module_systems/es.ex b/lib/elixir_script/module_systems/es.ex index 123656c7..c5c9ef9d 100644 --- a/lib/elixir_script/module_systems/es.ex +++ b/lib/elixir_script/module_systems/es.ex @@ -4,6 +4,10 @@ defmodule ElixirScript.ModuleSystems.ES do def build(js_imports, body, exports) do imports = js_imports + |> Enum.filter(fn + {_module, _name, nil, _import_path} -> false + _ -> true + end) |> Enum.map(fn {_module, name, _path, import_path} -> import_module(name, import_path) end) diff --git a/lib/elixir_script/passes/output.ex b/lib/elixir_script/passes/output.ex index 26ccc96b..20b6e063 100644 --- a/lib/elixir_script/passes/output.ex +++ b/lib/elixir_script/passes/output.ex @@ -9,13 +9,6 @@ defmodule ElixirScript.Output do """ @spec execute([atom], pid, map) :: [{atom, binary}] def execute(modules, pid, opts) do - prepared_modules = modules - |> Enum.filter(fn {_, info} -> Map.has_key?(info, :js_ast) end) - |> Enum.map(fn {module, info} -> - {module, info.js_ast, info.used_modules} - end - ) - js_modules = ModuleState.js_modules(pid) |> Enum.filter(fn {_module, _name, nil} -> false @@ -27,9 +20,21 @@ defmodule ElixirScript.Output do {module, name, path, import_path} end) + prepared_modules = modules + |> Enum.filter(fn {_, info} -> Map.has_key?(info, :js_ast) end) + |> Enum.map(fn {module, info} -> + {module, info.js_ast, filter_used_modules(info.used_modules, pid)} + end + ) + create_modules(prepared_modules, opts, js_modules) end + defp filter_used_modules(used_modules, pid) do + used_modules + |> Enum.filter(fn module -> ModuleState.is_global_module(pid, module) == false end) + end + defp concat(code) do """ 'use strict'; diff --git a/lib/elixir_script/passes/translate/module.ex b/lib/elixir_script/passes/translate/module.ex index e39daadc..ebe68bec 100644 --- a/lib/elixir_script/passes/translate/module.ex +++ b/lib/elixir_script/passes/translate/module.ex @@ -30,6 +30,7 @@ defmodule ElixirScript.Translate.Module do } = info used = Map.get(info, :used) + remove_unused_functions = ModuleState.remove_unused_functions(pid) state = %{ module: module, @@ -50,7 +51,12 @@ defmodule ElixirScript.Translate.Module do Enum.filter(reachable_defs, fn { {:start, 2}, _, _, _ } -> true { {:__struct__, _}, _, _, _ } -> true - { name, _, _, _} -> name in used + { name, _, _, _} -> + if remove_unused_functions do + name in used + else + true + end _ -> false end) end diff --git a/lib/elixir_script/state.ex b/lib/elixir_script/state.ex index 7a4e03e6..b211a4e8 100644 --- a/lib/elixir_script/state.ex +++ b/lib/elixir_script/state.ex @@ -3,12 +3,13 @@ defmodule ElixirScript.State do # Holds the state for the ElixirScript compiler - def start_link() do + def start_link(compiler_opts) do Agent.start_link(fn -> %{ modules: Keyword.new, js_modules: [], - in_memory_modules: [] + in_memory_modules: [], + compiler_opts: compiler_opts, } end) end @@ -95,6 +96,20 @@ defmodule ElixirScript.State do end) end + def is_global_module(pid, module) do + Agent.get(pid, fn(state) -> + result = Enum.find(state.js_modules, fn {mod, _, _} -> mod == module end) + + if result == nil, do: false, else: true + end) + end + + def remove_unused_functions(pid) do + Agent.get(pid, fn(state) -> + state.compiler_opts.remove_unused_functions + end) + end + def get_js_module_name(pid, module) do Agent.get(pid, fn(state) -> {_, name, _} = state.js_modules diff --git a/lib/elixir_script_test/test.ex b/lib/elixir_script_test/test.ex index c1f5bb6a..3c8fb99b 100644 --- a/lib/elixir_script_test/test.ex +++ b/lib/elixir_script_test/test.ex @@ -79,9 +79,9 @@ defmodule ElixirScript.Test do setup: 1, setup: 2, setup_all: 1, setup_all: 2, teardown: 1, teardown: 2, - teardown_all: 1, teardown_all: 2 + teardown_all: 1, teardown_all: 2, + assert: 1, assert: 2 ] - import ExUnit.Assertions def __elixirscript_test_module__, do: true end diff --git a/lib/elixir_script_test/test/callbacks.ex b/lib/elixir_script_test/test/callbacks.ex index f314c1c1..1f310e39 100644 --- a/lib/elixir_script_test/test/callbacks.ex +++ b/lib/elixir_script_test/test/callbacks.ex @@ -2,6 +2,7 @@ defmodule ElixirScript.Test.Callbacks do @moduledoc """ Defines ElixirScript.Test callbacks """ + require ExUnit.Assertions @doc """ Called before all tests are run in a test file @@ -114,4 +115,16 @@ defmodule ElixirScript.Test.Callbacks do end end end + + defmacro assert(assertion) do + quote do + ExUnit.Assertions.assert(unquote(assertion)) + end + end + + defmacro assert(value, message) do + quote do + ExUnit.Assertions.assert(unquote(value), unquote(message)) + end + end end From a5b3f42ba113eebb1a20617f98109c8c06aa1b77 Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Sat, 9 Dec 2017 16:43:32 -0600 Subject: [PATCH 813/860] Fix some compiler errors --- lib/elixir_script/passes/translate/form.ex | 15 ++++++++++++- .../passes/translate/forms/for.ex | 7 ++----- .../passes/translate/forms/match.ex | 21 ++++++++----------- .../passes/translate/function.ex | 2 +- 4 files changed, 26 insertions(+), 19 deletions(-) diff --git a/lib/elixir_script/passes/translate/form.ex b/lib/elixir_script/passes/translate/form.ex index 3f580783..475b4e02 100644 --- a/lib/elixir_script/passes/translate/form.ex +++ b/lib/elixir_script/passes/translate/form.ex @@ -392,13 +392,26 @@ defmodule ElixirScript.Translate.Form do defp compile_params(params, state) do {params, var_decs} = Enum.map_reduce(params, [], fn + ({:=, _, [{left_var, _, atom} = left, right]} = ast, acc) when is_atom(atom) -> + case Atom.to_string(left_var) do + "_" <> _ -> + {compile!(right, state), acc} + _ -> + {ast, state} = compile(ast, state) + left = compile!(left, state) + + {left, acc ++ List.wrap(ast)} + end + ({:=, _, [left, _]} = ast, acc) -> {ast, state} = compile(ast, state) left = compile!(left, state) {left, acc ++ List.wrap(ast)} (x, acc) -> - {compile!(x, state), acc} + compiled = compile!(x, state) + + {compiled, acc} end) {var_decs, params} diff --git a/lib/elixir_script/passes/translate/forms/for.ex b/lib/elixir_script/passes/translate/forms/for.ex index d037e3f9..dcbbded8 100644 --- a/lib/elixir_script/passes/translate/forms/for.ex +++ b/lib/elixir_script/passes/translate/forms/for.ex @@ -96,12 +96,9 @@ defmodule ElixirScript.Translate.Forms.For do defp create_function_expression(ast, state, module_state) do - { ast, _ } = Enum.map_reduce(List.wrap(ast), module_state, fn x, acc_state -> - Form.compile(x, acc_state) - end) - ast = ast - |> List.flatten + |> ElixirScript.Translate.Function.compile_block(module_state) + |> elem(0) |> Clause.return_last_statement Helpers.arrow_function( diff --git a/lib/elixir_script/passes/translate/forms/match.ex b/lib/elixir_script/passes/translate/forms/match.ex index db146339..f09a3259 100644 --- a/lib/elixir_script/passes/translate/forms/match.ex +++ b/lib/elixir_script/passes/translate/forms/match.ex @@ -56,11 +56,15 @@ defmodule ElixirScript.Translate.Forms.Match do defp compile_match(%{patterns: [left], expression: right}, state) do { right_ast, state } = Form.compile(right, state) - {var_dec, right_ast} = case right_ast do - [variable_declaration, x] -> - {variable_declaration, x} + {var_decs, right_ast} = case right_ast do + x when is_list(x) -> + l = Enum.reverse(x) + [head | tail] = l + l = Enum.reverse(tail) + + {l, head} x -> - {nil, x} + {[], x} end { patterns, params, state } = Pattern.compile([left], state) @@ -84,14 +88,7 @@ defmodule ElixirScript.Translate.Forms.Match do List.wrap(array_pattern) end - js_ast = case var_dec do - nil -> - js_ast - x -> - [x] ++ js_ast - end - - { js_ast, state } + { var_decs ++ js_ast, state } end defp compile_match(%{patterns: lefts, expression: right}, state) do diff --git a/lib/elixir_script/passes/translate/function.ex b/lib/elixir_script/passes/translate/function.ex index 23888453..dc0ff282 100644 --- a/lib/elixir_script/passes/translate/function.ex +++ b/lib/elixir_script/passes/translate/function.ex @@ -173,7 +173,7 @@ defmodule ElixirScript.Translate.Function do {ast, state} end - @spec update_last_call([ESTree.Node.t], map) :: ESTree.Node.t + @spec update_last_call([ESTree.Node.t], map) :: list def update_last_call(clause_body, %{function: {name, _}, anonymous_fn: anonymous?}) do last_item = List.last(clause_body) function_name = ElixirScript.Translate.Identifier.make_function_name(name) From 25ada67d57f4ce986501a51577afa40a687a0cad Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Sat, 9 Dec 2017 21:39:16 -0600 Subject: [PATCH 814/860] test fixes --- lib/elixir_script/compiler.ex | 2 +- .../passes/translate/forms/for.ex | 5 + .../passes/translate/forms/remote.ex | 10 + .../passes/translate/forms/try.ex | 2 +- lib/elixir_script/passes/translate/module.ex | 6 + lib/elixir_script_test/test.ex | 2 +- .../test/assertion_error.ex | 14 + lib/elixir_script_test/test/callbacks.ex | 39 +- priv/testrunner/index.js | 35 +- priv/testrunner/testRunner.js | 5 + priv/testrunner/vendor.build.js | 406 +++++++++++++++++- .../lib/core/erlang_compat/erlang.js | 10 + src/javascript/lib/core/special_forms.js | 16 +- test/passes/translate/form_test.exs | 2 +- .../passes/translate/forms/bitstring_test.exs | 2 +- test/passes/translate/forms/js_test.exs | 2 +- test/passes/translate/forms/map_test.exs | 2 +- 17 files changed, 524 insertions(+), 36 deletions(-) create mode 100644 lib/elixir_script_test/test/assertion_error.ex diff --git a/lib/elixir_script/compiler.ex b/lib/elixir_script/compiler.ex index 47136068..3c420f60 100644 --- a/lib/elixir_script/compiler.ex +++ b/lib/elixir_script/compiler.ex @@ -94,7 +94,7 @@ defmodule ElixirScript.Compiler do |> Map.put(:output, Keyword.get(opts, :output)) |> Map.put(:format, :es) |> Map.put(:root, Keyword.get(opts, :root, ".")) - |> Map.put(:remove_unused_functions, Keyword.get(opts, :remove_unused_functions, Mix.env == :prod)) + |> Map.put(:remove_unused_functions, Keyword.get(opts, :remove_unused_functions, true)) options = default_options Map.put(options, :module_formatter, ES) diff --git a/lib/elixir_script/passes/translate/forms/for.ex b/lib/elixir_script/passes/translate/forms/for.ex index dcbbded8..a641d480 100644 --- a/lib/elixir_script/passes/translate/forms/for.ex +++ b/lib/elixir_script/passes/translate/forms/for.ex @@ -78,6 +78,11 @@ defmodule ElixirScript.Translate.Forms.For do ([into: expression], state) -> %{state | into: Form.compile!(expression, module_state)} + ([do: expression2, into: expression], state) -> + fun = create_function_expression(expression2, state, module_state) + + %{state | into: Form.compile!(expression, module_state), fun: fun} + ([into: expression, do: expression2], state) -> fun = create_function_expression(expression2, state, module_state) diff --git a/lib/elixir_script/passes/translate/forms/remote.ex b/lib/elixir_script/passes/translate/forms/remote.ex index e39f381f..97c3decd 100644 --- a/lib/elixir_script/passes/translate/forms/remote.ex +++ b/lib/elixir_script/passes/translate/forms/remote.ex @@ -54,6 +54,16 @@ defmodule ElixirScript.Translate.Forms.Remote do { ast, state } end + def compile({:., _, [:erlang, :"=<"]}, state) do + ast = erlang_compat_function("erlang", "lessThanEqualTo") + { ast, state } + end + + def compile({:., _, [:erlang, :+]}, state) do + ast = erlang_compat_function("erlang", "add") + { ast, state } + end + def compile({:., _, [module, function]}, state) when module in @erlang_modules do ast = J.member_expression( Helpers.core_module(module), diff --git a/lib/elixir_script/passes/translate/forms/try.ex b/lib/elixir_script/passes/translate/forms/try.ex index 46add57f..3d3c1283 100644 --- a/lib/elixir_script/passes/translate/forms/try.ex +++ b/lib/elixir_script/passes/translate/forms/try.ex @@ -62,7 +62,7 @@ defmodule ElixirScript.Translate.Forms.Try do names = Enum.map(names, &make_exception_ast(&1)) param = {:_e, context, atom} - reason_call = {{:., [], [{:_e0, context, atom}, :__reason]}, [], []} + reason_call = {{:., [], [param, :__reason]}, [], []} reason_call = {{:., [], [reason_call, :__struct__]}, [], []} reason_call = {{:., [], [reason_call, :__MODULE__]}, [], []} diff --git a/lib/elixir_script/passes/translate/module.ex b/lib/elixir_script/passes/translate/module.ex index ebe68bec..58638e02 100644 --- a/lib/elixir_script/passes/translate/module.ex +++ b/lib/elixir_script/passes/translate/module.ex @@ -6,6 +6,11 @@ defmodule ElixirScript.Translate.Module do alias ElixirScript.State, as: ModuleState alias ElixirScript.Translate.Form + @operators [ + :+, :-, :*, :/, :!=, :==, :===, :<=, :>=, :=~, :++, + :!==, :--, :<, :> + ] + @doc """ Translate the given module's ast to JavaScript AST @@ -51,6 +56,7 @@ defmodule ElixirScript.Translate.Module do Enum.filter(reachable_defs, fn { {:start, 2}, _, _, _ } -> true { {:__struct__, _}, _, _, _ } -> true + { {name, _}, _, _, _ } when name in @operators -> false { name, _, _, _} -> if remove_unused_functions do name in used diff --git a/lib/elixir_script_test/test.ex b/lib/elixir_script_test/test.ex index 3c8fb99b..d78d0778 100644 --- a/lib/elixir_script_test/test.ex +++ b/lib/elixir_script_test/test.ex @@ -105,7 +105,7 @@ defmodule ElixirScript.Test do exit_status = node_test_runner(js_files) # Delete directory at the end - File.rm_rf!(output) + # File.rm_rf!(output) case exit_status do 0 -> diff --git a/lib/elixir_script_test/test/assertion_error.ex b/lib/elixir_script_test/test/assertion_error.ex new file mode 100644 index 00000000..c591a95d --- /dev/null +++ b/lib/elixir_script_test/test/assertion_error.ex @@ -0,0 +1,14 @@ +defmodule ElixirScript.Test.AssertionError do + @moduledoc """ + Raised to signal an assertion error. + """ + + @no_value :ex_unit_no_meaningful_value + + defexception left: @no_value, + right: @no_value, + message: @no_value, + expr: @no_value, + file: @no_value, + line: @no_value +end diff --git a/lib/elixir_script_test/test/callbacks.ex b/lib/elixir_script_test/test/callbacks.ex index 1f310e39..c6edc51b 100644 --- a/lib/elixir_script_test/test/callbacks.ex +++ b/lib/elixir_script_test/test/callbacks.ex @@ -2,7 +2,6 @@ defmodule ElixirScript.Test.Callbacks do @moduledoc """ Defines ElixirScript.Test callbacks """ - require ExUnit.Assertions @doc """ Called before all tests are run in a test file @@ -117,14 +116,44 @@ defmodule ElixirScript.Test.Callbacks do end defmacro assert(assertion) do - quote do - ExUnit.Assertions.assert(unquote(assertion)) + %{file: file, line: line} = __CALLER__ + + quote [file: file, line: line] do + require ExUnit.Assertions + try do + ExUnit.Assertions.assert(unquote(assertion)) + rescue + x in [ExUnit.AssertionError] -> + raise(ElixirScript.Test.AssertionError, [ + left: x.left, + right: x.right, + message: x.message, + expr: x.expr, + file: unquote(file), + line: unquote(line) + ]) + end end end defmacro assert(value, message) do - quote do - ExUnit.Assertions.assert(unquote(value), unquote(message)) + %{file: file, line: line} = __CALLER__ + + quote [file: file, line: line] do + require ExUnit.Assertions + try do + ExUnit.Assertions.assert(unquote(value), unquote(message)) + rescue + x in [ExUnit.AssertionError] -> + raise(ElixirScript.Test.AssertionError, [ + left: x.left, + right: x.right, + message: x.message, + expr: x.expr, + file: unquote(file), + line: unquote(line) + ]) + end end end end diff --git a/priv/testrunner/index.js b/priv/testrunner/index.js index 3096fa41..9dddc392 100644 --- a/priv/testrunner/index.js +++ b/priv/testrunner/index.js @@ -4,20 +4,25 @@ const Colors = require('./colors.js').default; const testFiles = process.argv.slice(2); console.time('Finished in'); -runner.start(testFiles).then((results) => { - const testsFailed = results.failed > 0; +runner + .start(testFiles) + .then((results) => { + const testsFailed = results.failed > 0; - process.stdout.write('\n\n'); - console.timeEnd('Finished in'); - console.log( - testsFailed ? Colors.fg.Red : Colors.fg.Green, - `${results.tests} tests, ${results.success} succeeded, ${results.failed} failed\n`, - Colors.Reset, - ); + process.stdout.write('\n\n'); + console.timeEnd('Finished in'); + console.log( + testsFailed ? Colors.fg.Red : Colors.fg.Green, + `${results.tests} tests, ${results.success} succeeded, ${results.failed} failed\n`, + Colors.Reset, + ); - if (testsFailed) { - process.exit(1); - } else { - process.exit(0); - } -}); + if (testsFailed) { + process.exit(1); + } else { + process.exit(0); + } + }) + .catch((e) => { + console.log(e); + }); diff --git a/priv/testrunner/testRunner.js b/priv/testrunner/testRunner.js index b3d1eca9..1b9eb7ae 100644 --- a/priv/testrunner/testRunner.js +++ b/priv/testrunner/testRunner.js @@ -97,10 +97,13 @@ function runTest(mod, test, incomingContext, results) { function handleError(e, test, results, mod) { if (e.__reason) { if (e.__reason instanceof Map && e.__reason.get(Symbol.for('message'))) { + console.log(e.__reason); const errorMessage = e.__reason.get(Symbol.for('message')); const expr = e.__reason.get(Symbol.for('expr')); const left = e.__reason.get(Symbol.for('left')); const right = e.__reason.get(Symbol.for('right')); + const file = e.__reason.get(Symbol.for('file')); + const line = e.__reason.get(Symbol.for('line')); const moduleName = Symbol.keyFor(mod.default.__MODULE__).replace('Elixir.', ''); let testMessage = test.get(Symbol.for('message')); testMessage = `${results.failed}) ${testMessage} (${moduleName})`; @@ -109,6 +112,8 @@ function handleError(e, test, results, mod) { console.log(Colors.fg.Red, errorMessage, Colors.Reset); printErrorLine(left, 'left'); printErrorLine(right, 'right'); + printErrorLine(file, 'file'); + printErrorLine(line, 'line'); } } else { console.log(e); diff --git a/priv/testrunner/vendor.build.js b/priv/testrunner/vendor.build.js index 9d49e34d..6e808208 100644 --- a/priv/testrunner/vendor.build.js +++ b/priv/testrunner/vendor.build.js @@ -1,2 +1,404 @@ -class Tuple{constructor(...a){this.values=Object.freeze(a),this.length=this.values.length}get(a){return this.values[a]}count(){return this.values.length}[Symbol.iterator](){return this.values[Symbol.iterator]()}toString(){let a,b='';for(a=0;a'}}let ref_counter=-1;class Reference{constructor(){++ref_counter,this.id=ref_counter,this.ref=Symbol()}toString(){return'Ref#<0.0.0.'+this.id+'>'}}class BitString{constructor(...a){this.value=Object.freeze(this.process(a)),this.length=this.value.length,this.bit_size=8*this.length,this.byte_size=this.length}get(a){return this.value[a]}count(){return this.value.length}slice(a,b=null){let c=this.value.slice(a,b),d=c.map((a)=>BitString.integer(a));return new BitString(...d)}[Symbol.iterator](){return this.value[Symbol.iterator]()}toString(){var a,b='';for(a=0;a>'}process(a){let b=[];var c;for(c=0;cb?c.push(b):2048>b?c.push(192|b>>6,128|63&b):55296>b||57344<=b?c.push(224|b>>12,128|63&b>>6,128|63&b):(d++,b=65536+((1023&b)<<10|1023&a.charCodeAt(d)),c.push(240|b>>18,128|63&b>>12,128|63&b>>6,128|63&b));return c}static toUTF16Array(a){for(var b,c=[],d=0;d=b?(c.push(0),c.push(b)):(c.push(255&b>>8),c.push(255&b));return c}static toUTF32Array(a){for(var b,c=[],d=0;d=b?(c.push(0),c.push(0),c.push(0),c.push(b)):(c.push(0),c.push(0),c.push(255&b>>8),c.push(255&b));return c}//http://stackoverflow.com/questions/2003493/javascript-float-from-to-bits -static float32ToBytes(a){var b=[],c=new ArrayBuffer(4);new Float32Array(c)[0]=a;let d=new Uint32Array(c)[0];return b.push(255&d>>24),b.push(255&d>>16),b.push(255&d>>8),b.push(255&d),b}static float64ToBytes(a){var b=[],c=new ArrayBuffer(8);new Float64Array(c)[0]=a;var d=new Uint32Array(c)[0],e=new Uint32Array(c)[1];return b.push(255&e>>24),b.push(255&e>>16),b.push(255&e>>8),b.push(255&e),b.push(255&d>>24),b.push(255&d>>16),b.push(255&d>>8),b.push(255&d),b}}var ErlangTypes={Tuple,PID,Reference,BitString},vendor={ErlangTypes};export default vendor; +class Tuple { + constructor(...args) { + this.values = Object.freeze(args); + this.length = this.values.length; + } + + get(index) { + return this.values[index]; + } + + count() { + return this.values.length; + } + + [Symbol.iterator]() { + return this.values[Symbol.iterator](); + } + + toString() { + let i, + s = ''; + for (i = 0; i < this.values.length; i++) { + if (s !== '') { + s += ', '; + } + + const stringToAppend = this.values[i] ? this.values[i].toString() : ''; + + s += stringToAppend; + } + + return '{' + s + '}'; + } + + put_elem(index, elem) { + if (index === this.length) { + let new_values = this.values.concat([elem]); + return new Tuple(...new_values); + } + + let new_values = this.values.concat([]); + new_values.splice(index, 0, elem); + return new Tuple(...new_values); + } + + remove_elem(index) { + let new_values = this.values.concat([]); + new_values.splice(index, 1); + return new Tuple(...new_values); + } +} + +let process_counter = -1; + +class PID { + constructor() { + process_counter = process_counter + 1; + this.id = process_counter; + } + + toString() { + return 'PID#<0.' + this.id + '.0>'; + } +} + +let ref_counter = -1; + +class Reference { + constructor() { + ref_counter = ref_counter + 1; + this.id = ref_counter; + this.ref = Symbol(); + } + + toString() { + return 'Ref#<0.0.0.' + this.id + '>'; + } +} + +class BitString { + constructor(...args) { + this.value = Object.freeze(this.process(args)); + this.length = this.value.length; + this.bit_size = this.length * 8; + this.byte_size = this.length; + } + + get(index) { + return this.value[index]; + } + + count() { + return this.value.length; + } + + slice(start, end = null) { + let s = this.value.slice(start, end); + let ms = s.map(elem => BitString.integer(elem)); + return new BitString(...ms); + } + + [Symbol.iterator]() { + return this.value[Symbol.iterator](); + } + + toString() { + var i, + s = ''; + for (i = 0; i < this.count(); i++) { + if (s !== '') { + s += ', '; + } + s += this.get(i).toString(); + } + + return '<<' + s + '>>'; + } + + process(bitStringParts) { + let processed_values = []; + + var i; + for (i = 0; i < bitStringParts.length; i++) { + let processed_value = this['process_' + bitStringParts[i].type](bitStringParts[i]); + + for (let attr of bitStringParts[i].attributes) { + processed_value = this['process_' + attr](processed_value); + } + + processed_values = processed_values.concat(processed_value); + } + + return processed_values; + } + + process_integer(value) { + return value.value; + } + + process_float(value) { + if (value.size === 64) { + return BitString.float64ToBytes(value.value); + } else if (value.size === 32) { + return BitString.float32ToBytes(value.value); + } + + throw new Error('Invalid size for float'); + } + + process_bitstring(value) { + return value.value.value; + } + + process_binary(value) { + return BitString.toUTF8Array(value.value); + } + + process_utf8(value) { + return BitString.toUTF8Array(value.value); + } + + process_utf16(value) { + return BitString.toUTF16Array(value.value); + } + + process_utf32(value) { + return BitString.toUTF32Array(value.value); + } + + process_signed(value) { + return new Uint8Array([value])[0]; + } + + process_unsigned(value) { + return value; + } + + process_native(value) { + return value; + } + + process_big(value) { + return value; + } + + process_little(value) { + return value.reverse(); + } + + process_size(value) { + return value; + } + + process_unit(value) { + return value; + } + + static integer(value) { + return BitString.wrap(value, { type: 'integer', unit: 1, size: 8 }); + } + + static float(value) { + return BitString.wrap(value, { type: 'float', unit: 1, size: 64 }); + } + + static bitstring(value) { + return BitString.wrap(value, { + type: 'bitstring', + unit: 1, + size: value.bit_size + }); + } + + static bits(value) { + return BitString.bitstring(value); + } + + static binary(value) { + return BitString.wrap(value, { + type: 'binary', + unit: 8, + size: value.length + }); + } + + static bytes(value) { + return BitString.binary(value); + } + + static utf8(value) { + return BitString.wrap(value, { type: 'utf8', unit: 1, size: value.length }); + } + + static utf16(value) { + return BitString.wrap(value, { + type: 'utf16', + unit: 1, + size: value.length * 2 + }); + } + + static utf32(value) { + return BitString.wrap(value, { + type: 'utf32', + unit: 1, + size: value.length * 4 + }); + } + + static signed(value) { + return BitString.wrap(value, {}, 'signed'); + } + + static unsigned(value) { + return BitString.wrap(value, {}, 'unsigned'); + } + + static native(value) { + return BitString.wrap(value, {}, 'native'); + } + + static big(value) { + return BitString.wrap(value, {}, 'big'); + } + + static little(value) { + return BitString.wrap(value, {}, 'little'); + } + + static size(value, count) { + return BitString.wrap(value, { size: count }); + } + + static unit(value, count) { + return BitString.wrap(value, { unit: count }); + } + + static wrap(value, opt, new_attribute = null) { + let the_value = value; + + if (!(value instanceof Object)) { + the_value = { value: value, attributes: [] }; + } + + the_value = Object.assign(the_value, opt); + + if (new_attribute) { + the_value.attributes.push(new_attribute); + } + + return the_value; + } + + static toUTF8Array(str) { + var utf8 = []; + for (var i = 0; i < str.length; i++) { + var charcode = str.charCodeAt(i); + if (charcode < 0x80) { + utf8.push(charcode); + } else if (charcode < 0x800) { + utf8.push(0xc0 | charcode >> 6, 0x80 | charcode & 0x3f); + } else if (charcode < 0xd800 || charcode >= 0xe000) { + utf8.push(0xe0 | charcode >> 12, 0x80 | charcode >> 6 & 0x3f, 0x80 | charcode & 0x3f); + } else { + // surrogate pair + i++; + // UTF-16 encodes 0x10000-0x10FFFF by + // subtracting 0x10000 and splitting the + // 20 bits of 0x0-0xFFFFF into two halves + charcode = 0x10000 + ((charcode & 0x3ff) << 10 | str.charCodeAt(i) & 0x3ff); + utf8.push(0xf0 | charcode >> 18, 0x80 | charcode >> 12 & 0x3f, 0x80 | charcode >> 6 & 0x3f, 0x80 | charcode & 0x3f); + } + } + return utf8; + } + + static toUTF16Array(str) { + var utf16 = []; + for (var i = 0; i < str.length; i++) { + var codePoint = str.codePointAt(i); + + if (codePoint <= 255) { + utf16.push(0); + utf16.push(codePoint); + } else { + utf16.push(codePoint >> 8 & 0xff); + utf16.push(codePoint & 0xff); + } + } + return utf16; + } + + static toUTF32Array(str) { + var utf32 = []; + for (var i = 0; i < str.length; i++) { + var codePoint = str.codePointAt(i); + + if (codePoint <= 255) { + utf32.push(0); + utf32.push(0); + utf32.push(0); + utf32.push(codePoint); + } else { + utf32.push(0); + utf32.push(0); + utf32.push(codePoint >> 8 & 0xff); + utf32.push(codePoint & 0xff); + } + } + return utf32; + } + + //http://stackoverflow.com/questions/2003493/javascript-float-from-to-bits + static float32ToBytes(f) { + var bytes = []; + + var buf = new ArrayBuffer(4); + new Float32Array(buf)[0] = f; + + let intVersion = new Uint32Array(buf)[0]; + + bytes.push(intVersion >> 24 & 0xff); + bytes.push(intVersion >> 16 & 0xff); + bytes.push(intVersion >> 8 & 0xff); + bytes.push(intVersion & 0xff); + + return bytes; + } + + static float64ToBytes(f) { + var bytes = []; + + var buf = new ArrayBuffer(8); + new Float64Array(buf)[0] = f; + + var intVersion1 = new Uint32Array(buf)[0]; + var intVersion2 = new Uint32Array(buf)[1]; + + bytes.push(intVersion2 >> 24 & 0xff); + bytes.push(intVersion2 >> 16 & 0xff); + bytes.push(intVersion2 >> 8 & 0xff); + bytes.push(intVersion2 & 0xff); + + bytes.push(intVersion1 >> 24 & 0xff); + bytes.push(intVersion1 >> 16 & 0xff); + bytes.push(intVersion1 >> 8 & 0xff); + bytes.push(intVersion1 & 0xff); + + return bytes; + } +} + +var ErlangTypes = { + Tuple, + PID, + Reference, + BitString +}; + +var vendor = { + ErlangTypes +}; + +export default vendor; diff --git a/src/javascript/lib/core/erlang_compat/erlang.js b/src/javascript/lib/core/erlang_compat/erlang.js index 18ec72d9..ddece09d 100644 --- a/src/javascript/lib/core/erlang_compat/erlang.js +++ b/src/javascript/lib/core/erlang_compat/erlang.js @@ -521,6 +521,14 @@ function function_exported(module, _function) { return module[_function] != null; } +function lessThanEqualTo(one, two) { + return one <= two; +} + +function add(one, two) { + return one + two; +} + export default { atom_to_binary, binary_to_atom, @@ -589,4 +597,6 @@ export default { nodes, function_exported, equals, + lessThanEqualTo, + add, }; diff --git a/src/javascript/lib/core/special_forms.js b/src/javascript/lib/core/special_forms.js index 988d341f..7964bf3d 100644 --- a/src/javascript/lib/core/special_forms.js +++ b/src/javascript/lib/core/special_forms.js @@ -62,12 +62,16 @@ function _try(do_fun, rescue_function, catch_fun, else_function, after_function) let ex_result = null; if (rescue_function) { try { - ex_result = rescue_function(e); + let value = e; + if (e.__reason) { + value = e.__reason; + value.set('__reason', e.__reason); + } + + ex_result = rescue_function(value); return ex_result; } catch (ex) { - if (ex instanceof Core.Patterns.MatchError) { - throw ex; - } + throw ex; } } @@ -76,9 +80,7 @@ function _try(do_fun, rescue_function, catch_fun, else_function, after_function) ex_result = catch_fun(e); return ex_result; } catch (ex) { - if (ex instanceof Core.Patterns.MatchError) { - throw ex; - } + throw ex; } } diff --git a/test/passes/translate/form_test.exs b/test/passes/translate/form_test.exs index d40f4e30..6b8bae94 100644 --- a/test/passes/translate/form_test.exs +++ b/test/passes/translate/form_test.exs @@ -7,7 +7,7 @@ defmodule ElixirScript.Translate.Forms.Test do setup_all do - {:ok, pid} = ElixirScript.State.start_link() + {:ok, pid} = ElixirScript.State.start_link(%{}) state = %{ pid: pid, diff --git a/test/passes/translate/forms/bitstring_test.exs b/test/passes/translate/forms/bitstring_test.exs index e7e76ccd..1d62517d 100644 --- a/test/passes/translate/forms/bitstring_test.exs +++ b/test/passes/translate/forms/bitstring_test.exs @@ -4,7 +4,7 @@ defmodule ElixirScript.Translate.Forms.Bitstring.Test do alias ESTree.Tools.Builder, as: J setup_all do - {:ok, pid} = ElixirScript.State.start_link() + {:ok, pid} = ElixirScript.State.start_link(%{}) state = %{ pid: pid, diff --git a/test/passes/translate/forms/js_test.exs b/test/passes/translate/forms/js_test.exs index d1eef57f..d3989cb9 100644 --- a/test/passes/translate/forms/js_test.exs +++ b/test/passes/translate/forms/js_test.exs @@ -4,7 +4,7 @@ defmodule ElixirScript.Translate.Forms.JS.Test do alias ESTree.Tools.Builder, as: J setup_all do - {:ok, pid} = ElixirScript.State.start_link() + {:ok, pid} = ElixirScript.State.start_link(%{}) state = %{ pid: pid, diff --git a/test/passes/translate/forms/map_test.exs b/test/passes/translate/forms/map_test.exs index ec181caf..79454147 100644 --- a/test/passes/translate/forms/map_test.exs +++ b/test/passes/translate/forms/map_test.exs @@ -5,7 +5,7 @@ defmodule ElixirScript.Translate.Forms.Map.Test do use ExUnitProperties setup_all do - {:ok, pid} = ElixirScript.State.start_link() + {:ok, pid} = ElixirScript.State.start_link(%{}) state = %{ pid: pid From a21e0037c2b8cd2f1123b432faa2b6f2e23e85f3 Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Sun, 10 Dec 2017 13:42:27 -0600 Subject: [PATCH 815/860] Fix lints --- lib/elixir_script/compiler.ex | 4 +++- lib/elixir_script/passes/output.ex | 4 +++- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/lib/elixir_script/compiler.ex b/lib/elixir_script/compiler.ex index 3c420f60..06000df4 100644 --- a/lib/elixir_script/compiler.ex +++ b/lib/elixir_script/compiler.ex @@ -90,11 +90,13 @@ defmodule ElixirScript.Compiler do end defp build_compiler_options(opts) do + remove_used_functions? = Keyword.get(opts, :remove_unused_functions, true) + default_options = Map.new |> Map.put(:output, Keyword.get(opts, :output)) |> Map.put(:format, :es) |> Map.put(:root, Keyword.get(opts, :root, ".")) - |> Map.put(:remove_unused_functions, Keyword.get(opts, :remove_unused_functions, true)) + |> Map.put(:remove_unused_functions, remove_used_functions?) options = default_options Map.put(options, :module_formatter, ES) diff --git a/lib/elixir_script/passes/output.ex b/lib/elixir_script/passes/output.ex index 20b6e063..9a519fff 100644 --- a/lib/elixir_script/passes/output.ex +++ b/lib/elixir_script/passes/output.ex @@ -32,7 +32,9 @@ defmodule ElixirScript.Output do defp filter_used_modules(used_modules, pid) do used_modules - |> Enum.filter(fn module -> ModuleState.is_global_module(pid, module) == false end) + |> Enum.filter(fn module -> + ModuleState.is_global_module(pid, module) == false + end) end defp concat(code) do From 313605cf8eae7500ea5329a179d39691e42c046c Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Sun, 10 Dec 2017 13:48:09 -0600 Subject: [PATCH 816/860] Remove extra console.log for debugging. Use reraise for raising test errors --- lib/elixir_script_test/test/callbacks.ex | 8 ++++---- priv/testrunner/testRunner.js | 1 - test_elixir_script/integration_test.exs | 2 +- 3 files changed, 5 insertions(+), 6 deletions(-) diff --git a/lib/elixir_script_test/test/callbacks.ex b/lib/elixir_script_test/test/callbacks.ex index c6edc51b..a516737d 100644 --- a/lib/elixir_script_test/test/callbacks.ex +++ b/lib/elixir_script_test/test/callbacks.ex @@ -124,14 +124,14 @@ defmodule ElixirScript.Test.Callbacks do ExUnit.Assertions.assert(unquote(assertion)) rescue x in [ExUnit.AssertionError] -> - raise(ElixirScript.Test.AssertionError, [ + reraise(ElixirScript.Test.AssertionError, [ left: x.left, right: x.right, message: x.message, expr: x.expr, file: unquote(file), line: unquote(line) - ]) + ], []) end end end @@ -145,14 +145,14 @@ defmodule ElixirScript.Test.Callbacks do ExUnit.Assertions.assert(unquote(value), unquote(message)) rescue x in [ExUnit.AssertionError] -> - raise(ElixirScript.Test.AssertionError, [ + reraise(ElixirScript.Test.AssertionError, [ left: x.left, right: x.right, message: x.message, expr: x.expr, file: unquote(file), line: unquote(line) - ]) + ], []) end end end diff --git a/priv/testrunner/testRunner.js b/priv/testrunner/testRunner.js index 1b9eb7ae..3bdd9a7c 100644 --- a/priv/testrunner/testRunner.js +++ b/priv/testrunner/testRunner.js @@ -97,7 +97,6 @@ function runTest(mod, test, incomingContext, results) { function handleError(e, test, results, mod) { if (e.__reason) { if (e.__reason instanceof Map && e.__reason.get(Symbol.for('message'))) { - console.log(e.__reason); const errorMessage = e.__reason.get(Symbol.for('message')); const expr = e.__reason.get(Symbol.for('expr')); const left = e.__reason.get(Symbol.for('left')); diff --git a/test_elixir_script/integration_test.exs b/test_elixir_script/integration_test.exs index 491d88c7..ca30430f 100644 --- a/test_elixir_script/integration_test.exs +++ b/test_elixir_script/integration_test.exs @@ -16,7 +16,7 @@ defmodule ElixirScript.Integration.Test do end test "shorthand failure" do - orders = [%{email: "test@hotmail.com"},%{email: "test2@hotmail.com"}] + orders = [%{email: "test@hotmail.com"}, %{email: "test2@hotmail.com"}] val = Enum.reduce(orders, [], &(&2 ++ [ [:option, %{value: &1.email}, &1.email] ])) From d904909c66daeddce7b6cf499a8cb81b3d5cfd19 Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Sun, 10 Dec 2017 17:40:07 -0600 Subject: [PATCH 817/860] Add more test assertions. Make behaviour for test runners --- lib/elixir_script_test/test.ex | 27 +--- lib/elixir_script_test/test/assertions.ex | 161 +++++++++++++++++++++ lib/elixir_script_test/test/callbacks.ex | 42 ------ lib/elixir_script_test/test/runner.ex | 14 ++ lib/elixir_script_test/test/runner/node.ex | 18 +++ 5 files changed, 198 insertions(+), 64 deletions(-) create mode 100644 lib/elixir_script_test/test/assertions.ex create mode 100644 lib/elixir_script_test/test/runner.ex create mode 100644 lib/elixir_script_test/test/runner/node.ex diff --git a/lib/elixir_script_test/test.ex b/lib/elixir_script_test/test.ex index d78d0778..b49de509 100644 --- a/lib/elixir_script_test/test.ex +++ b/lib/elixir_script_test/test.ex @@ -74,14 +74,9 @@ defmodule ElixirScript.Test do defmacro __using__(_opts) do quote do - import ElixirScript.Test.Callbacks, only: [ - test: 2, test: 3, - setup: 1, setup: 2, - setup_all: 1, setup_all: 2, - teardown: 1, teardown: 2, - teardown_all: 1, teardown_all: 2, - assert: 1, assert: 2 - ] + require ExUnit.Assertions + import ElixirScript.Test.Callbacks + import ElixirScript.Test.Assertions def __elixirscript_test_module__, do: true end @@ -102,10 +97,10 @@ defmodule ElixirScript.Test do |> Path.join("Elixir.*.js") |> Path.wildcard() - exit_status = node_test_runner(js_files) + exit_status = ElixirScript.Test.Runner.Node.run(js_files) # Delete directory at the end - # File.rm_rf!(output) + File.rm_rf!(output) case exit_status do 0 -> @@ -114,16 +109,4 @@ defmodule ElixirScript.Test do :error end end - - defp node_test_runner(js_files) do - test_script_path = Path.join([:code.priv_dir(:elixir_script), "testrunner", "index.js"]) - test_script_path = [test_script_path] ++ js_files - {_, exit_status} = System.cmd( - "node", - test_script_path, - into: IO.stream(:stdio, :line) - ) - - exit_status - end end diff --git a/lib/elixir_script_test/test/assertions.ex b/lib/elixir_script_test/test/assertions.ex new file mode 100644 index 00000000..662a8704 --- /dev/null +++ b/lib/elixir_script_test/test/assertions.ex @@ -0,0 +1,161 @@ +defmodule ElixirScript.Test.Assertions do + @moduledoc """ + Defines assertions for use in ElixirScript test. + These are a subset of [ExUnit.Assertions](https://hexdocs.pm/ex_unit/ExUnit.Assertions.html) + """ + + @doc false + def raise_elixir_script_assert(error, file, line) do + reraise(ElixirScript.Test.AssertionError, [ + left: error.left, + right: error.right, + message: error.message, + expr: error.expr, + file: file, + line: line + ], []) + end + + @doc """ + Asserts its argument is a truthy value + """ + defmacro assert(assertion) do + %{file: file, line: line} = __CALLER__ + + quote [file: file, line: line] do + try do + ExUnit.Assertions.assert(unquote(assertion)) + rescue + error in [ExUnit.AssertionError] -> + ElixirScript.Test.Assertions.raise_elixir_script_assert( + error, + unquote(file), + unquote(line) + ) + end + end + end + + @doc """ + Asserts `value` is `true`, displaying the given `message` otherwise. + """ + defmacro assert(value, message) do + %{file: file, line: line} = __CALLER__ + + quote [file: file, line: line] do + try do + ExUnit.Assertions.assert(unquote(value), unquote(message)) + rescue + error in [ExUnit.AssertionError] -> + ElixirScript.Test.Assertions.raise_elixir_script_assert( + error, + unquote(file), + unquote(line) + ) + end + end + end + + @doc """ + Asserts the `exception` is raised during `function` execution. + Returns the rescued exception, fails otherwise. + """ + defmacro assert_raise(exception, function) do + %{file: file, line: line} = __CALLER__ + + quote [file: file, line: line] do + try do + ExUnit.Assertions.assert(unquote(exception), unquote(function)) + rescue + error in [ExUnit.AssertionError] -> + ElixirScript.Test.Assertions.raise_elixir_script_assert( + error, + unquote(file), + unquote(line) + ) + end + end + end + + @doc """ + Asserts the `exception` is raised during `function` execution with + the expected `message`, which can be a `Regex` or an exact `String`. + Returns the rescued exception, fails otherwise. + """ + defmacro assert_raise(exception, message, function) do + %{file: file, line: line} = __CALLER__ + + quote [file: file, line: line] do + try do + ExUnit.Assertions.assert(unquote(exception), unquote(message), unquote(function)) + rescue + error in [ExUnit.AssertionError] -> + ElixirScript.Test.Assertions.raise_elixir_script_assert( + error, + unquote(file), + unquote(line) + ) + end + end + end + + @doc """ + A negative assertion, expects the expression to be `false` or `nil`. + """ + defmacro refute(assertion) do + %{file: file, line: line} = __CALLER__ + + quote [file: file, line: line] do + try do + ExUnit.Assertions.assert(unquote(assertion)) + rescue + error in [ExUnit.AssertionError] -> + ElixirScript.Test.Assertions.raise_elixir_script_assert( + error, + unquote(file), + unquote(line) + ) + end + end + end + + @doc """ + Asserts `value` is `nil` or `false` (that is, `value` is not truthy). + """ + defmacro refute(value, message) do + %{file: file, line: line} = __CALLER__ + + quote [file: file, line: line] do + try do + ExUnit.Assertions.assert(unquote(value), unquote(message)) + rescue + error in [ExUnit.AssertionError] -> + ElixirScript.Test.Assertions.raise_elixir_script_assert( + error, + unquote(file), + unquote(line) + ) + end + end + end + + @doc """ + Fails with a message. + """ + defmacro flunk(message \\ "Flunked!") do + %{file: file, line: line} = __CALLER__ + + quote [file: file, line: line] do + try do + ExUnit.Assertions.flunk(unquote(message)) + rescue + error in [ExUnit.AssertionError] -> + ElixirScript.Test.Assertions.raise_elixir_script_assert( + error, + unquote(file), + unquote(line) + ) + end + end + end +end diff --git a/lib/elixir_script_test/test/callbacks.ex b/lib/elixir_script_test/test/callbacks.ex index a516737d..f314c1c1 100644 --- a/lib/elixir_script_test/test/callbacks.ex +++ b/lib/elixir_script_test/test/callbacks.ex @@ -114,46 +114,4 @@ defmodule ElixirScript.Test.Callbacks do end end end - - defmacro assert(assertion) do - %{file: file, line: line} = __CALLER__ - - quote [file: file, line: line] do - require ExUnit.Assertions - try do - ExUnit.Assertions.assert(unquote(assertion)) - rescue - x in [ExUnit.AssertionError] -> - reraise(ElixirScript.Test.AssertionError, [ - left: x.left, - right: x.right, - message: x.message, - expr: x.expr, - file: unquote(file), - line: unquote(line) - ], []) - end - end - end - - defmacro assert(value, message) do - %{file: file, line: line} = __CALLER__ - - quote [file: file, line: line] do - require ExUnit.Assertions - try do - ExUnit.Assertions.assert(unquote(value), unquote(message)) - rescue - x in [ExUnit.AssertionError] -> - reraise(ElixirScript.Test.AssertionError, [ - left: x.left, - right: x.right, - message: x.message, - expr: x.expr, - file: unquote(file), - line: unquote(line) - ], []) - end - end - end end diff --git a/lib/elixir_script_test/test/runner.ex b/lib/elixir_script_test/test/runner.ex new file mode 100644 index 00000000..e746292b --- /dev/null +++ b/lib/elixir_script_test/test/runner.ex @@ -0,0 +1,14 @@ +defmodule ElixirScript.Test.Runner do + @moduledoc """ + Defines a behaviour for an ElixirScript Test runner + """ + + @doc """ + Callback for running the test runner. + Receives a list of JavaScript files from the + compiled Elixir code. Expects an exit status + representing the success or failure of the + tests + """ + @callback run([binary]) :: integer +end diff --git a/lib/elixir_script_test/test/runner/node.ex b/lib/elixir_script_test/test/runner/node.ex new file mode 100644 index 00000000..31e83667 --- /dev/null +++ b/lib/elixir_script_test/test/runner/node.ex @@ -0,0 +1,18 @@ +defmodule ElixirScript.Test.Runner.Node do + @moduledoc """ + Defines an ElixirScript Test runner using node + """ + @behaviour ElixirScript.Test.Runner + + def run(js_files) do + test_script_path = Path.join([:code.priv_dir(:elixir_script), "testrunner", "index.js"]) + test_script_path = [test_script_path] ++ js_files + {_, exit_status} = System.cmd( + "node", + test_script_path, + into: IO.stream(:stdio, :line) + ) + + exit_status + end +end From 64f9bfe7ff698da4f52ff2c5f1b47ec66a7f4395 Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Sun, 10 Dec 2017 17:42:36 -0600 Subject: [PATCH 818/860] Remove doc for remove_unused --- lib/elixir_script/compiler.ex | 2 -- 1 file changed, 2 deletions(-) diff --git a/lib/elixir_script/compiler.ex b/lib/elixir_script/compiler.ex index 06000df4..36c6de61 100644 --- a/lib/elixir_script/compiler.ex +++ b/lib/elixir_script/compiler.ex @@ -23,8 +23,6 @@ defmodule ElixirScript.Compiler do If a directory is given, file will be named `elixirscript.build.js` * `root`: Optional root for imports of FFI JavaScript modules. Defaults to `.`. - * `remove_unused_functions`: Removed unused functions in output. Defaults to - removing unused functions when Mix.env == :prod """ alias ElixirScript.{ State, From 0a66d2d37420470ce110a7cd1afd453c5e32e9fa Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Sun, 10 Dec 2017 17:44:19 -0600 Subject: [PATCH 819/860] Fix lints --- lib/elixir_script_test/test.ex | 3 +-- lib/elixir_script_test/test/assertions.ex | 6 +++++- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/lib/elixir_script_test/test.ex b/lib/elixir_script_test/test.ex index b49de509..b531b700 100644 --- a/lib/elixir_script_test/test.ex +++ b/lib/elixir_script_test/test.ex @@ -75,8 +75,7 @@ defmodule ElixirScript.Test do defmacro __using__(_opts) do quote do require ExUnit.Assertions - import ElixirScript.Test.Callbacks - import ElixirScript.Test.Assertions + import ElixirScript.Test.{Callbacks, Assertions} def __elixirscript_test_module__, do: true end diff --git a/lib/elixir_script_test/test/assertions.ex b/lib/elixir_script_test/test/assertions.ex index 662a8704..fe61c581 100644 --- a/lib/elixir_script_test/test/assertions.ex +++ b/lib/elixir_script_test/test/assertions.ex @@ -87,7 +87,11 @@ defmodule ElixirScript.Test.Assertions do quote [file: file, line: line] do try do - ExUnit.Assertions.assert(unquote(exception), unquote(message), unquote(function)) + ExUnit.Assertions.assert( + unquote(exception), + unquote(message), + unquote(function) + ) rescue error in [ExUnit.AssertionError] -> ElixirScript.Test.Assertions.raise_elixir_script_assert( From 8e1b987f9e9d97e81e21b895e64aec1c905014e9 Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Sun, 10 Dec 2017 19:20:14 -0600 Subject: [PATCH 820/860] Add delta assertions --- lib/elixir_script_test/test/assertions.ex | 50 +++++++++++++++++++++++ 1 file changed, 50 insertions(+) diff --git a/lib/elixir_script_test/test/assertions.ex b/lib/elixir_script_test/test/assertions.ex index fe61c581..7e8e53fe 100644 --- a/lib/elixir_script_test/test/assertions.ex +++ b/lib/elixir_script_test/test/assertions.ex @@ -103,6 +103,31 @@ defmodule ElixirScript.Test.Assertions do end end + @doc """ + Asserts that `value1` and `value2` differ by no more than `delta` + """ + defmacro assert_in_delta(value1, value2, delta, message \\ nil) do + %{file: file, line: line} = __CALLER__ + + quote [file: file, line: line] do + try do + ExUnit.Assertions.assert_in_delta( + unquote(value1), + unquote(value2), + unquote(delta), + unquote(message) + ) + rescue + error in [ExUnit.AssertionError] -> + ElixirScript.Test.Assertions.raise_elixir_script_assert( + error, + unquote(file), + unquote(line) + ) + end + end + end + @doc """ A negative assertion, expects the expression to be `false` or `nil`. """ @@ -143,6 +168,31 @@ defmodule ElixirScript.Test.Assertions do end end + @doc """ + Asserts that `value1` and `value2` are not within `delta` + """ + defmacro refute_in_delta(value1, value2, delta, message \\ nil) do + %{file: file, line: line} = __CALLER__ + + quote [file: file, line: line] do + try do + ExUnit.Assertions.refute_in_delta( + unquote(value1), + unquote(value2), + unquote(delta), + unquote(message) + ) + rescue + error in [ExUnit.AssertionError] -> + ElixirScript.Test.Assertions.raise_elixir_script_assert( + error, + unquote(file), + unquote(line) + ) + end + end + end + @doc """ Fails with a message. """ From d4696fe01f2bf4cc6af3d0d85eb4c01f12599aef Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Tue, 26 Dec 2017 21:00:07 -0600 Subject: [PATCH 821/860] Update version of elixir to 1.6.0-rc.0 --- .tool-versions | 2 +- lib/elixir_script/cli.ex | 51 +++++++++++++++--------------- lib/elixir_script/state.ex | 63 +++++++++++++++++++------------------- 3 files changed, 60 insertions(+), 56 deletions(-) diff --git a/.tool-versions b/.tool-versions index eb307d7d..a9580d64 100644 --- a/.tool-versions +++ b/.tool-versions @@ -1,3 +1,3 @@ erlang 20.1 -elixir 1.5.2-otp-20 +elixir 1.6.0-rc.0-otp-20 nodejs 8.9.1 diff --git a/lib/elixir_script/cli.ex b/lib/elixir_script/cli.ex index 75791304..1eedfc37 100644 --- a/lib/elixir_script/cli.ex +++ b/lib/elixir_script/cli.ex @@ -17,51 +17,54 @@ defmodule ElixirScript.CLI do ] def parse_args(args) do - { options, input, errors } = OptionParser.parse(args, switches: @switches, aliases: @aliases) + {options, input, errors} = OptionParser.parse(args, switches: @switches, aliases: @aliases) cond do length(errors) > 0 -> :help + Keyword.get(options, :help, false) -> :help + Keyword.get(options, :version, false) -> :version + length(input) == 0 -> :help + true -> - { input, options } + {input, options} end - end defp help_message do - """ - usage: elixirscript [options] - the entry module of your application - the path to .ex(s) files to compile - - options: - -o --output [path] places output at the given path. - Can be a directory or filename. - -v --version the current version number - -h --help this message - --root The root import path for FFI imports - """ + """ + usage: elixirscript [options] + the entry module of your application + the path to .ex(s) files to compile + + options: + -o --output [path] places output at the given path. + Can be a directory or filename. + -v --version the current version number + -h --help this message + --root The root import path for FFI imports + """ end def process(:help) do - IO.write help_message() + IO.write(help_message()) end def process(:version) do - IO.write @app_version + IO.write(@app_version) end - def process({ input, options }) do + def process({input, options}) do if options_contains_unknown_values(options) do - process(:help) + process(:help) else - do_process(input, options) + do_process(input, options) end end @@ -76,7 +79,7 @@ defmodule ElixirScript.CLI do end defp options_contains_unknown_values(options) do - Enum.any?(options, fn({key, _value}) -> + Enum.any?(options, fn {key, _value} -> if key in Keyword.keys(@switches) do false else @@ -87,8 +90,8 @@ defmodule ElixirScript.CLI do defp handle_input(input) do input - |> Enum.map(fn(x) -> String.split(x, [" ", ","], trim: true) end) - |> List.flatten - |> Enum.map(fn(x) -> Module.concat([x]) end) + |> Enum.map(fn x -> String.split(x, [" ", ","], trim: true) end) + |> List.flatten() + |> Enum.map(fn x -> Module.concat([x]) end) end end diff --git a/lib/elixir_script/state.ex b/lib/elixir_script/state.ex index b211a4e8..73208ec6 100644 --- a/lib/elixir_script/state.ex +++ b/lib/elixir_script/state.ex @@ -6,10 +6,10 @@ defmodule ElixirScript.State do def start_link(compiler_opts) do Agent.start_link(fn -> %{ - modules: Keyword.new, + modules: Keyword.new(), js_modules: [], in_memory_modules: [], - compiler_opts: compiler_opts, + compiler_opts: compiler_opts } end) end @@ -19,23 +19,24 @@ defmodule ElixirScript.State do end def get_module(pid, module) do - Agent.get(pid, fn(state) -> + Agent.get(pid, fn state -> Keyword.get(state.modules, module) end) end def put_module(pid, module, value) do - Agent.update(pid, fn(state) -> - value = Map.put_new(value, :used, []) - |> Map.put_new(:used_modules, []) + Agent.update(pid, fn state -> + value = + Map.put_new(value, :used, []) + |> Map.put_new(:used_modules, []) modules = Keyword.put(state.modules, module, value) - %{ state | modules: modules } + %{state | modules: modules} end) end def add_used_module(pid, module, used_module) do - Agent.update(pid, fn(state) -> + Agent.update(pid, fn state -> module_info = Keyword.get(state.modules, module) used_modules = Map.get(module_info, :used_modules, []) @@ -44,22 +45,21 @@ defmodule ElixirScript.State do module_info = Map.put(module_info, :used_modules, used_modules) modules = Keyword.put(state.modules, module, module_info) - %{ state | modules: modules } + %{state | modules: modules} end) end - def has_used?(pid, module, func) do - Agent.get(pid, fn(state) -> + Agent.get(pid, fn state -> module_info = Keyword.get(state.modules, module) used = Map.get(module_info, :used, []) - Enum.find(used, fn(x) -> x == func end) != nil + Enum.find(used, fn x -> x == func end) != nil end) end def add_used(pid, module, {_function, _arity} = func) do - Agent.update(pid, fn(state) -> + Agent.update(pid, fn state -> module_info = Keyword.get(state.modules, module) used = Map.get(module_info, :used, []) @@ -68,36 +68,35 @@ defmodule ElixirScript.State do module_info = Map.put(module_info, :used, used) modules = Keyword.put(state.modules, module, module_info) - %{ state | modules: modules } + %{state | modules: modules} end) end def put_javascript_module(pid, module, name, path) do - Agent.update(pid, fn(state) -> + Agent.update(pid, fn state -> js_modules = Map.get(state, :js_modules, []) js_modules = [{module, name, path} | js_modules] - %{ state | js_modules: js_modules } + %{state | js_modules: js_modules} end) end def list_javascript_modules(pid) do - Agent.get(pid, fn(state) -> + Agent.get(pid, fn state -> state.js_modules - |> Enum.map(fn - {module, _name, _path} -> - module + |> Enum.map(fn {module, _name, _path} -> + module end) end) end def js_modules(pid) do - Agent.get(pid, fn(state) -> + Agent.get(pid, fn state -> state.js_modules end) end def is_global_module(pid, module) do - Agent.get(pid, fn(state) -> + Agent.get(pid, fn state -> result = Enum.find(state.js_modules, fn {mod, _, _} -> mod == module end) if result == nil, do: false, else: true @@ -105,42 +104,44 @@ defmodule ElixirScript.State do end def remove_unused_functions(pid) do - Agent.get(pid, fn(state) -> + Agent.get(pid, fn state -> state.compiler_opts.remove_unused_functions end) end def get_js_module_name(pid, module) do - Agent.get(pid, fn(state) -> - {_, name, _} = state.js_modules - |> Enum.find(fn {m, _, _} -> module == m end) + Agent.get(pid, fn state -> + {_, name, _} = + state.js_modules + |> Enum.find(fn {m, _, _} -> module == m end) + name end) end def list_modules(pid) do - Agent.get(pid, fn(state) -> + Agent.get(pid, fn state -> state.modules end) end def get_in_memory_module(pid, module) do - Agent.get(pid, fn(state) -> + Agent.get(pid, fn state -> Keyword.get(state.in_memory_modules, module) end) end def get_in_memory_modules(pid) do - Agent.get(pid, fn(state) -> + Agent.get(pid, fn state -> state.in_memory_modules end) end def put_in_memory_module(pid, module, beam) do - Agent.update(pid, fn(state) -> + Agent.update(pid, fn state -> in_memory_modules = Map.get(state, :in_memory_modules, []) in_memory_modules = Keyword.put(in_memory_modules, module, beam) - %{ state | in_memory_modules: in_memory_modules } + %{state | in_memory_modules: in_memory_modules} end) end end From ed729249c80eb17c0cb13b4fa74604aa0459b97c Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Tue, 26 Dec 2017 21:01:41 -0600 Subject: [PATCH 822/860] Update travis elixir version to 1.6.0-rc.0 --- .travis.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index 3acd9398..78d59677 100644 --- a/.travis.yml +++ b/.travis.yml @@ -9,8 +9,8 @@ install: - npm install -g yarn - yarn before_script: - - wget https://repo.hex.pm/builds/elixir/v1.5.1-otp-20.zip - - unzip -d elixir v1.5.1-otp-20.zip + - wget https://repo.hex.pm/builds/elixir/v1.6.0-rc.0-otp-20.zip + - unzip -d elixir v1.6.0-rc.0-otp-20.zip - export PATH=$(pwd)/elixir/bin:${PATH} - mix local.rebar --force - mix local.hex --force From b15cf00b479667b817ce7e673ed4dcbaf4ed1620 Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Tue, 2 Jan 2018 15:10:56 -0600 Subject: [PATCH 823/860] Require elixir 1.6 --- CHANGELOG.md | 691 ++++++++++++++++++++++++++++++--------------------- mix.exs | 2 +- 2 files changed, 403 insertions(+), 290 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 91b3f895..9c619292 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,26 +1,33 @@ # Change Log + All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](http://keepachangelog.com/) and this project adheres to [Semantic Versioning](http://semver.org/). ## Unreleased + ## Changed -- Compiler now returns a file per module instead of just one file + +* Compiler now returns a file per module instead of just one file +* Requires Elixir 1.6 ## [0.31.1] - 2017-09-27 + ### Fixed -- Compiler error when `receive` is used as variable name +* Compiler error when `receive` is used as variable name ## [0.31.0] - 2017-09-24 + ### Added -- [Compiler will now accept a path to Elixir Files to compile](https://github.com/elixirscript/elixirscript/issues/420) -- [Added `ElixirScript.JS.map_to_object/2` with options [keys: :string, symbols: false]](https://github.com/elixirscript/elixirscript/issues/362) -- [Added `ElixirScript.JS.object_to_map/1|2` with options [keys: :atom, recurse_array: true]](https://github.com/elixirscript/elixirscript/issues/381) -- [Fully implement `__info__` on modules](https://github.com/elixirscript/elixirscript/pull/378) -- [Concurrent Compilation](https://github.com/elixirscript/elixirscript/issues/376) -- [The following erlang functions have been implemented](https://github.com/elixirscript/elixirscript/issues/306): + +* [Compiler will now accept a path to Elixir Files to compile](https://github.com/elixirscript/elixirscript/issues/420) +* [Added `ElixirScript.JS.map_to_object/2` with options [keys: :string, symbols: false]](https://github.com/elixirscript/elixirscript/issues/362) +* [Added `ElixirScript.JS.object_to_map/1|2` with options [keys: :atom, recurse_array: true]](https://github.com/elixirscript/elixirscript/issues/381) +* [Fully implement `__info__` on modules](https://github.com/elixirscript/elixirscript/pull/378) +* [Concurrent Compilation](https://github.com/elixirscript/elixirscript/issues/376) +* [The following erlang functions have been implemented](https://github.com/elixirscript/elixirscript/issues/306): * :erlang.nodes/0 * :erlang.nodes/1 * :math.log2/1 @@ -32,51 +39,57 @@ and this project adheres to [Semantic Versioning](http://semver.org/). * :binary.replace/4 (some options still missing) ### Fixed -- Make sure not to add underscores to erlang functions -- [Make sure any variable names that are javascript keywords are handled properly](https://github.com/elixirscript/elixirscript/issues/355) -- [Make sure variables that begin with `_` are available](https://github.com/elixirscript/elixirscript/issues/356) -- [Finding the use of functions within anonymous functions](https://github.com/elixirscript/elixirscript/issues/358) -- [Reimplement `String.split_at/2` to make sure Unicode library isn't compiled](https://github.com/elixirscript/elixirscript/issues/353) -- [byte_size does not work on binaries that started via "" elixir string syntax](https://github.com/elixirscript/elixirscript/issues/384) -- [using . (dot) reference syntax on a map fails when value is a function](https://github.com/elixirscript/elixirscript/issues/380) -- [Make sure that remote ast works correctly with variables](https://github.com/elixirscript/elixirscript/issues/390) -- [Make sure == works as expected](https://github.com/elixirscript/elixirscript/issues/382) -- [Make sure that erlang function names that are also JavaScript keywords are not filters](https://github.com/elixirscript/elixirscript/issues/359) -- [erlang.error now throws errors resembling those in Elixir](https://github.com/elixirscript/elixirscript/pull/397) -- [Map.get fails if key is tuple or list](https://github.com/elixirscript/elixirscript/issues/406) + +* Make sure not to add underscores to erlang functions +* [Make sure any variable names that are javascript keywords are handled properly](https://github.com/elixirscript/elixirscript/issues/355) +* [Make sure variables that begin with `_` are available](https://github.com/elixirscript/elixirscript/issues/356) +* [Finding the use of functions within anonymous functions](https://github.com/elixirscript/elixirscript/issues/358) +* [Reimplement `String.split_at/2` to make sure Unicode library isn't compiled](https://github.com/elixirscript/elixirscript/issues/353) +* [byte_size does not work on binaries that started via "" elixir string syntax](https://github.com/elixirscript/elixirscript/issues/384) +* [using . (dot) reference syntax on a map fails when value is a function](https://github.com/elixirscript/elixirscript/issues/380) +* [Make sure that remote ast works correctly with variables](https://github.com/elixirscript/elixirscript/issues/390) +* [Make sure == works as expected](https://github.com/elixirscript/elixirscript/issues/382) +* [Make sure that erlang function names that are also JavaScript keywords are not filters](https://github.com/elixirscript/elixirscript/issues/359) +* [erlang.error now throws errors resembling those in Elixir](https://github.com/elixirscript/elixirscript/pull/397) +* [Map.get fails if key is tuple or list](https://github.com/elixirscript/elixirscript/issues/406) ## [0.30.0] - 2017-08-15 ### Added -- ElixirScript now has a Foreign Function Interface (FFI) for interoperability with JavaScript. For more details, see documentation at `ElixirScript.FFI` -- `ElixirScript.JS.mutate/3` -- `ElixirScript.JS.map_to_object/1` -- `root` option for specifying the root import path for FFI JavaScript modules. Defaults to `"."` + +* ElixirScript now has a Foreign Function Interface (FFI) for interoperability with JavaScript. For more details, see documentation at `ElixirScript.FFI` +* `ElixirScript.JS.mutate/3` +* `ElixirScript.JS.map_to_object/1` +* `root` option for specifying the root import path for FFI JavaScript modules. Defaults to `"."` ### Changed -- Compiler has been completely rewritten. ElixirScript now requires Erlang 20+ and Elixir 1.5+ -- `JS` module renamed to `ElixirScript.JS` -- Default output path is now `priv/elixir_script/build` + +* Compiler has been completely rewritten. ElixirScript now requires Erlang 20+ and Elixir 1.5+ +* `JS` module renamed to `ElixirScript.JS` +* Default output path is now `priv/elixir_script/build` ### Removed -- Support for CommonJS and UMD output formats has been removed. Output will be in ES module format -- The `js_modules` option has been removed in favor of the new FFI -- ElixirScript.Watcher has been removed + +* Support for CommonJS and UMD output formats has been removed. Output will be in ES module format +* The `js_modules` option has been removed in favor of the new FFI +* ElixirScript.Watcher has been removed ## [0.28.0] - 2017-06-11 ### Added -- `remove-unused` option that will remove all unused modules from output -- reimplemented structs to avoid creating JavaScript classes + +* `remove-unused` option that will remove all unused modules from output +* reimplemented structs to avoid creating JavaScript classes ## [0.27.0] - 2017-03-17 ### Added -- `super` -- `defoverridable` -- `IO.inspect\1`, `IO.puts\1`, `IO.puts\2`, `IO.warn\1` -- `Elixir.load` for loading generated JavaScript modules in bundled output. -Unlike `Elixir.start`, this will only call `__load` on the module and return the functions on it + +* `super` +* `defoverridable` +* `IO.inspect\1`, `IO.puts\1`, `IO.puts\2`, `IO.warn\1` +* `Elixir.load` for loading generated JavaScript modules in bundled output. + Unlike `Elixir.start`, this will only call `__load` on the module and return the functions on it ```javascript const exports = Elixir.load(Elixir.MyApp); @@ -84,9 +97,11 @@ exports.hello(); ``` ### Changed -- `-ex` alias is now `-e` -- A filename can be specified for output -- To access global JavaScript functions, modules, and properties, use the `JS` module + +* `-ex` alias is now `-e` +* A filename can be specified for output +* To access global JavaScript functions, modules, and properties, use the `JS` module + ```elixir JS.length # translates to 'length' JS.alert() # translates to 'alert()' @@ -95,20 +110,24 @@ JS.console.log("hi") # translates to console.log('hi') ``` ### Fixed -- Make sure mix compiler works in umbrella apps + +* Make sure mix compiler works in umbrella apps ## [0.26.1] - 2017-02-27 ### Fixed -- Fixed `for` translation -- Updated documentation + +* Fixed `for` translation +* Updated documentation ## [0.26.0] - 2017-02-27 ### Added -- Multiple `when` clauses in guards -- Kernel.defdelegate/2 -- `js_modules` configuration option has been added. This is a list of JavaScript modules that will be used. + +* Multiple `when` clauses in guards +* Kernel.defdelegate/2 +* `js_modules` configuration option has been added. This is a list of JavaScript modules that will be used. + ``` js_modules: [ {React, "react"}, @@ -116,17 +135,20 @@ JS.console.log("hi") # translates to console.log('hi') ] ``` -- `js-module` flag has been added to the CLI in order to pass js modules. +* `js-module` flag has been added to the CLI in order to pass js modules. + ``` elixirscript "app/elixirscript" -o dist --js-module React:react --js-module ReactDOM:react-dom ``` ### Removed -- `@on_js_load` has been removed in favor of having a `start/2` function defined. More info below -- `JS.import` has been removed in favor of defining JavaScript modules used in configuration + +* `@on_js_load` has been removed in favor of having a `start/2` function defined. More info below +* `JS.import` has been removed in favor of defining JavaScript modules used in configuration ### Changed -- Now bundles all output, including the boostrap code. + +* Now bundles all output, including the boostrap code. The exported object has Elixir modules in JavaScript namespaces that are lazily loaded when called. To start your application import the bundle according to whichever module format was selected and @@ -134,78 +156,82 @@ elixirscript "app/elixirscript" -o dist --js-module React:react --js-module Reac ```javascript //ES module example - import Elixir from './Elixir.App' - Elixir.start(Elixir.App, []) + import Elixir from './Elixir.App'; + Elixir.start(Elixir.App, []); ``` The `start` function will look for a `start/2` function there. This is analogous to a [Application module callback](https://hexdocs.pm/elixir/Application.html#module-application-module-callback) - - - ## [0.25.0] - 2017-02-19 ### Added -- Updated elixir_script mix compiler to support compiling elixir_script paths in dependencies if dependency has mix compiler defined as well -- Add `Collectable` protocol implementations -- Updated `for` implementation to use `Collectable` -- `format` option. Can now specify the module format of output. - Choices are: - * `:es` (default) for ES Modules - * `:umd` for UMD - * `:common` for CommonJS -- Default input, output and format for elixirscript mix compiler. In a mix project by default the elixirscript compiler will look in `lib/elixirscript` and input and place output in `priv/elixirscript`. The default format is `:es` +* Updated elixir_script mix compiler to support compiling elixir_script paths in dependencies if dependency has mix compiler defined as well +* Add `Collectable` protocol implementations +* Updated `for` implementation to use `Collectable` +* `format` option. Can now specify the module format of output. + Choices are: + _ `:es` (default) for ES Modules + _ `:umd` for UMD \* `:common` for CommonJS + +* Default input, output and format for elixirscript mix compiler. In a mix project by default the elixirscript compiler will look in `lib/elixirscript` and input and place output in `priv/elixirscript`. The default format is `:es` ### Removed -- `receive` -- `Process` module + +* `receive` +* `Process` module ### Fixed -- JS module functions not translated properly when imported -- Update fs dependency to 2.12 -- Incorrect handling of function heads with guards + +* JS module functions not translated properly when imported +* Update fs dependency to 2.12 +* Incorrect handling of function heads with guards ## [0.24.0] - 2017-01-15 ### Added -- Support for `sigil_r` -- `Regex` module -- Better JavaScript formatting + +* Support for `sigil_r` +* `Regex` module +* Better JavaScript formatting ### Fixed -- CLI now allows a comma-separated or space-separated list of paths -- Struct not properly referenced -- Tail call optimization + +* CLI now allows a comma-separated or space-separated list of paths +* Struct not properly referenced +* Tail call optimization ## [0.23.3] - 2016-11-18 ### Added -- `@load_only`: lets the compiler know to load in the module, but not to compile it +* `@load_only`: lets the compiler know to load in the module, but not to compile it ## [0.23.2] - 2016-11-17 ### Fixed -- Agent not functioning properly. Now uses internal store instead of making a process and using that to put data in store -- Protocol incorrectly handling strings -- `defgen` and `defgenp` functions not being recognized by Elixir compiler. +* Agent not functioning properly. Now uses internal store instead of making a process and using that to put data in store +* Protocol incorrectly handling strings +* `defgen` and `defgenp` functions not being recognized by Elixir compiler. ## [0.23.1] - 2016-11-16 ### Fixed -- Incorrectly sending standard lib when using compile or compile_path by default + +* Incorrectly sending standard lib when using compile or compile_path by default ## [0.23.0] - 2016-11-15 ### Added -- [`with` now supports `else`](https://github.com/bryanjos/elixirscript/pull/207) -- [Implement `context` option on `quote`](https://github.com/bryanjos/elixirscript/pull/208) -- New compiler pipeline -- `@on_js_load`. Expects a 0 arity function. This function will be called when the compiled module is loaded in JavaScript -- `JS.import\3`. Just like `JS.import\2` but expects options to decide if the import should be a default one or a namespace on. Only option allowed is `default`. Set to `true` by default + +* [`with` now supports `else`](https://github.com/bryanjos/elixirscript/pull/207) +* [Implement `context` option on `quote`](https://github.com/bryanjos/elixirscript/pull/208) +* New compiler pipeline +* `@on_js_load`. Expects a 0 arity function. This function will be called when the compiled module is loaded in JavaScript +* `JS.import\3`. Just like `JS.import\2` but expects options to decide if the import should be a default one or a namespace on. Only option allowed is `default`. Set to `true` by default + ```elixir # translates to "import A from 'a'" JS.import A, "a" @@ -215,351 +241,438 @@ elixirscript "app/elixirscript" -o dist --js-module React:react --js-module Reac ``` ### Removed -- The form of `JS.import` that accepted a list of atoms as the first arg. Used `JS.import\3` with `default: false` instead to create a namespace import -- `env` and `root` are no longer options for `ElixirScript`'s compile functions and cli -- Syntax once supported by Elixirscript `JQuery.("#element")`, is no longer supported + +* The form of `JS.import` that accepted a list of atoms as the first arg. Used `JS.import\3` with `default: false` instead to create a namespace import +* `env` and `root` are no longer options for `ElixirScript`'s compile functions and cli +* Syntax once supported by Elixirscript `JQuery.("#element")`, is no longer supported ### Changed -- [Changed CHANGELOG.md to adhere the format from Keep a Changelog](https://github.com/bryanjos/elixirscript/pull/205) -- `defmacro` now supported. No longer have to separate macros from functions in separate files. `defmacrop` still unsupported -- To use anything in the `JS` module, you must `require` the `JS` module first -- Elixirscript files must now contain valid Elixir syntax. -- Now compiles `exjs` and `ex` files within the path can be compiled all the same. Dependencies from hex are still unsupported so these files must not rely on any code outside of the path. What this does mean is that it is now possible to share code between Elixir and Elixirscript as long as the Elixir files functionality fall within what Elixirscript currently supports. -- `defgen`, `defgenp`, `yield`, `yield_to`, and `object` are now in the `JS` module -- To access functions in the global JavaScript scope, either use `JS.global\0` or use the erlang module call syntax - ```elixir - #calling alert - JS.global().alert("hi") - - #calling alert - :window.alert("hi") - ``` - Calling JavaScript modules in the global scope works without using the above methods - ```elixir - #calls window.Date.now() - Date.now() - ``` + +* [Changed CHANGELOG.md to adhere the format from Keep a Changelog](https://github.com/bryanjos/elixirscript/pull/205) +* `defmacro` now supported. No longer have to separate macros from functions in separate files. `defmacrop` still unsupported +* To use anything in the `JS` module, you must `require` the `JS` module first +* Elixirscript files must now contain valid Elixir syntax. +* Now compiles `exjs` and `ex` files within the path can be compiled all the same. Dependencies from hex are still unsupported so these files must not rely on any code outside of the path. What this does mean is that it is now possible to share code between Elixir and Elixirscript as long as the Elixir files functionality fall within what Elixirscript currently supports. +* `defgen`, `defgenp`, `yield`, `yield_to`, and `object` are now in the `JS` module +* To access functions in the global JavaScript scope, either use `JS.global\0` or use the erlang module call syntax + + ```elixir + #calling alert + JS.global().alert("hi") + + #calling alert + :window.alert("hi") + ``` + + Calling JavaScript modules in the global scope works without using the above methods + + ```elixir + #calls window.Date.now() + Date.now() + ``` ## [0.22.0] - 2016-10-16 + ### Added -- `defgen` and `defgenp` for defining public and private generators -- `yield/0`, `yield/1`, and `yield_to\1` to `Kernel` + +* `defgen` and `defgenp` for defining public and private generators +* `yield/0`, `yield/1`, and `yield_to\1` to `Kernel` ### Changed -- Updated output folder structure. stdlib code will now go in an `elxiir` folder under the output paths while generated app code will go into an `app` folder under the output path -- All process macros and functions now expect to receive and/or work using generators as entry points. Using functions defined with `def` or `defp` will not work correctly with them + +* Updated output folder structure. stdlib code will now go in an `elxiir` folder under the output paths while generated app code will go into an `app` folder under the output path +* All process macros and functions now expect to receive and/or work using generators as entry points. Using functions defined with `def` or `defp` will not work correctly with them ### Fixed -- Correctly returning list if list is only item in body + +* Correctly returning list if list is only item in body ## [0.21.0] - 2016-06-28 + ### Added -- This is the first release with early support for processes in elixirscript. Creating a process only works currently using `spawn/1`, `spawn_link/1`, and `spawn_monitor/1`. Inside of a process, you can use functions such as `send` and `receive`, along with some defined in the `Process` module. From outside of a process, you can send messages to a process, but you cannot receive a message from a process. Eventually all code will run inside processes and this restriction will naturally lift. -- The `Process` module has been implemented with the following functions: - * `alive?/1` - * `delete/1` - * `demonitor/1` - * `exit/2` - * `flag/2` - * `flag/3` - * `get/0` - * `get_keys/0` - * `get_keys/1` - * `link/1` - * `list/0` - * `monitor/1` - * `put/2` - * `register/2` - * `registered/0` - * `send/3` - * `sleep/1` - * `unlink/1` - * `unregister/1` - * `whereis/1` -- The `receive` special form has been implemented with the above caveat -- The following have been implemented on `Kernel`: - * `spawn/1` - * `spawn_link/1` - * `spawn_monitor/1` - * `send/2` - * `make_ref/0` + +* This is the first release with early support for processes in elixirscript. Creating a process only works currently using `spawn/1`, `spawn_link/1`, and `spawn_monitor/1`. Inside of a process, you can use functions such as `send` and `receive`, along with some defined in the `Process` module. From outside of a process, you can send messages to a process, but you cannot receive a message from a process. Eventually all code will run inside processes and this restriction will naturally lift. +* The `Process` module has been implemented with the following functions: + * `alive?/1` + * `delete/1` + * `demonitor/1` + * `exit/2` + * `flag/2` + * `flag/3` + * `get/0` + * `get_keys/0` + * `get_keys/1` + * `link/1` + * `list/0` + * `monitor/1` + * `put/2` + * `register/2` + * `registered/0` + * `send/3` + * `sleep/1` + * `unlink/1` + * `unregister/1` + * `whereis/1` +* The `receive` special form has been implemented with the above caveat +* The following have been implemented on `Kernel`: + * `spawn/1` + * `spawn_link/1` + * `spawn_monitor/1` + * `send/2` + * `make_ref/0` ## Fixed -- Scoping on `fn` and `def` + +* Scoping on `fn` and `def` ## [0.20.0] - 2016-05-14 + ### Added -- `ElixirScript.Watcher` module and `elixirscript.watch` mix task -- logging MatchError exceptions to better show terms that don't match + +* `ElixirScript.Watcher` module and `elixirscript.watch` mix task +* logging MatchError exceptions to better show terms that don't match ## [0.19.0] - 2016-04-30 + ### Added -- elixir_script mix compiler + +* elixir_script mix compiler ### Removed -- `Html`, `View`, and `VDom` modules have been removed + +* `Html`, `View`, and `VDom` modules have been removed ## [0.18.0] - 2016-04-08 + ### Changed -- Better support for macros. Macros should be defined in .ex or .exs files. ElixirScript code should be in .exjs files + +* Better support for macros. Macros should be defined in .ex or .exs files. ElixirScript code should be in .exjs files **NOTE**: The above functionality will cause either compiler errors or no output. Please change extensions of ElixirScript code to .exjs ### Deprecated -- `Html`, `View`, and `VDom` modules will be removed in the next version as they can now be replicated using macros + +* `Html`, `View`, and `VDom` modules will be removed in the next version as they can now be replicated using macros ## [0.17.0] - 2016-03-31 + ### Added -- `output` as an option for compiler functions. This controls whether output is returned as a list of tuples, send to stdout, or saved to a file path -- `:full_build` as an option for compiler functions and `--full-build` option to CLI. These force the compiler to perform a full build -- `--version` option to CLI. Outputs current version of elixirscript -- `--std-lib` option to CLI. Takes a path and adds the stdlib to that path + +* `output` as an option for compiler functions. This controls whether output is returned as a list of tuples, send to stdout, or saved to a file path +* `:full_build` as an option for compiler functions and `--full-build` option to CLI. These force the compiler to perform a full build +* `--version` option to CLI. Outputs current version of elixirscript +* `--std-lib` option to CLI. Takes a path and adds the stdlib to that path ### Changed -- Renamed `copy_core_to_destination` to `copy_stdlib_to_destination` -- Incremental Compilation: ElixirScript will now only build files and modules that have changed since the last build + +* Renamed `copy_core_to_destination` to `copy_stdlib_to_destination` +* Incremental Compilation: ElixirScript will now only build files and modules that have changed since the last build ### Removed -- `--core` option from CLI and `:core` compiler option. + +* `--core` option from CLI and `:core` compiler option. ## [0.16.0] 2016-02-27 + ### Added -- Bitstring pattern matching -- Bitstrings in for comprehensions -- Functions with catch, after, else clauses -- `with` special form -- Pin operator in map keys and function clauses -- Added `Kernel.object/1` function to make it more natural to create a JavaScript object with string keys. Elixirscript, by default turns the following, `%{a:"b"}` into `{[Symbol.for("a")]: "b"}` in JavaScript. In order to get string keys, one would have to do `%{"a" => "b"}` which turns into `{a: "b"}` in JavaScript. With `Kernel.object`, you can create string keyed maps conveniently, `object(a: "b")` which turns into `{a: "b"}`. - **NOTE**: when updating the created by, you still have to use the string form `%{ my_map | "a" => "c" }` +* Bitstring pattern matching +* Bitstrings in for comprehensions +* Functions with catch, after, else clauses +* `with` special form +* Pin operator in map keys and function clauses +* Added `Kernel.object/1` function to make it more natural to create a JavaScript object with string keys. Elixirscript, by default turns the following, `%{a:"b"}` into `{[Symbol.for("a")]: "b"}` in JavaScript. In order to get string keys, one would have to do `%{"a" => "b"}` which turns into `{a: "b"}` in JavaScript. With `Kernel.object`, you can create string keyed maps conveniently, `object(a: "b")` which turns into `{a: "b"}`. + + **NOTE**: when updating the created by, you still have to use the string form `%{ my_map | "a" => "c" }` ### Removed -- `JS.update(object, property, value)` has been removed and replaced with `JS.update(object, map)`. This allows you to update multiple values on a javascript object at once. + +* `JS.update(object, property, value)` has been removed and replaced with `JS.update(object, map)`. This allows you to update multiple values on a javascript object at once. ### Fixed -- Optional parameters should now work as expected + +* Optional parameters should now work as expected ## [0.15.2] - 2016-02-21 + ### Addded -- Support for variables as map keys + +* Support for variables as map keys ### Fixed -- Protocol implementations for Integer and Float which where not recognized -- Calling properties on non-objects + +* Protocol implementations for Integer and Float which where not recognized +* Calling properties on non-objects ## [0.15.1] - 2016-02-19 + ### Removed -- Removed `catch` as a javascript keyword to filter + +* Removed `catch` as a javascript keyword to filter ### Fixed -- Fixed View module so that an element can have multiple elements within -- struct implementation so that lists of atoms for fields are compiled correctly -- head-tail pattern match to allow for more complicated scenarios -- ModuleCollector to properly alias inner modules -- Raise translation to properly translate when string messages are given + +* Fixed View module so that an element can have multiple elements within +* struct implementation so that lists of atoms for fields are compiled correctly +* head-tail pattern match to allow for more complicated scenarios +* ModuleCollector to properly alias inner modules +* Raise translation to properly translate when string messages are given ## [0.15.0] - 2016-01-26 + ### Added -- `__ENV__` and `__CALLER__` are now supported -- `JS.import/1`, `JS.typeof/1`,`JS.instanceof/1`, and `JS.global/1` -- Support for multi alias/require/imports statements + +* `__ENV__` and `__CALLER__` are now supported +* `JS.import/1`, `JS.typeof/1`,`JS.instanceof/1`, and `JS.global/1` +* Support for multi alias/require/imports statements ### Changed -- `alias`, `require`, and `import` now work inside lexical scopes -- Some of the standard library originally written in JavaScript has been rewritten in Elixir. -- Generated JavaScript export statements are now default exports -- When output is sent to standard out, there are now markers to specify where each module begins as well as what the file name would be. For the end of a file, `//:ENDFILE` is used. For the file name, `//:ENDFILENAME` is used where `` is the name of the file -- `compile`, `compile_path`, and `compile_quoted` opts parameter now expects a map -- The `stdlib` compiler option is now `core`. The `stdlib_path` compiler options is now `core_path` + +* `alias`, `require`, and `import` now work inside lexical scopes +* Some of the standard library originally written in JavaScript has been rewritten in Elixir. +* Generated JavaScript export statements are now default exports +* When output is sent to standard out, there are now markers to specify where each module begins as well as what the file name would be. For the end of a file, `//:ENDFILE` is used. For the file name, `//:ENDFILENAME` is used where `` is the name of the file +* `compile`, `compile_path`, and `compile_quoted` opts parameter now expects a map +* The `stdlib` compiler option is now `core`. The `stdlib_path` compiler options is now `core_path` ## [0.14.1] - 2015-12-07 + ### Removed -- .DS_Store and LICENSE from output + +* .DS_Store and LICENSE from output ## [0.14.0] - 2015-12-06 + ### Added -- Can now implement protocols using JavaScript types + +* Can now implement protocols using JavaScript types ```elixir defimpl MyProtocol, for: HTMLElement ``` -- virtual-dom JavaScript library -- ElixirScript.Html module for defining a virtual-dom tree -- ElixirScript.VDom module for manipulating the virtual-dom tree created using the ElixirScript.Html module -- Added ElixirScript.View module for handling view state and rendering virtual-dom -- Added `stdlib_path` compiler option to specify the es6 path to the standard library. If used, elixir.js will not be exported with the compiled modules +* virtual-dom JavaScript library +* ElixirScript.Html module for defining a virtual-dom tree +* ElixirScript.VDom module for manipulating the virtual-dom tree created using the ElixirScript.Html module +* Added ElixirScript.View module for handling view state and rendering virtual-dom +* Added `stdlib_path` compiler option to specify the es6 path to the standard library. If used, elixir.js will not be exported with the compiled modules ### Changed -- Renamed `ex2js` to `elixirscript`. This effects the escript as well as the + +* Renamed `ex2js` to `elixirscript`. This effects the escript as well as the mix task -- Structs are now translated into classes -- Structs and Tuples now match on their types -- Can now match on JavaScript classes. Works just like matching on structs: +* Structs are now translated into classes +* Structs and Tuples now match on their types +* Can now match on JavaScript classes. Works just like matching on structs: ```elixir def my_func(%HTMLElement{id: "myId"}) ``` -- Moved non-elixir JavaScript code into `core` es6 module. This will hopefully +* Moved non-elixir JavaScript code into `core` es6 module. This will hopefully make it so ElixirScript Standard Library modules can be defined in Elixir soon. ## [0.13.0] - 2015-10-26 + ### Added -- `Base` module with function: encode64, decode64, and decode64! -- `String` module -- `Bitwise` module -- `Map` module -- `MapSet` module -- `Set` module -- Protocol support -- Added `Collectable`, `Enumerable`, `Inspect`, `List.Chars`, and `String.Chars` protocols. The only one currently being used in the Standard Library, however, is String.Chars + +* `Base` module with function: encode64, decode64, and decode64! +* `String` module +* `Bitwise` module +* `Map` module +* `MapSet` module +* `Set` module +* Protocol support +* Added `Collectable`, `Enumerable`, `Inspect`, `List.Chars`, and `String.Chars` protocols. The only one currently being used in the Standard Library, however, is String.Chars ## [0.12.0] - 2015-09-23 + ### Added -- Added PostOffice. Only thing that current uses it is Agent + +* Added PostOffice. Only thing that current uses it is Agent ### Changed -- Updated tuple implementation. It's now a class. -- Replaced pattern matching library with custom one -- Moved data types to Kernel.SpecialForms -- `else` now works for try expressions -- for now works with `into` for lists + +* Updated tuple implementation. It's now a class. +* Replaced pattern matching library with custom one +* Moved data types to Kernel.SpecialForms +* `else` now works for try expressions +* for now works with `into` for lists ### Removed -- Removed erlang.js. + +* Removed erlang.js. ## [0.11.0] - 2015-09-17 + ### Added -- Added `JS` module with `new`, `mutate`, `import` macros -- Added `Keyword` module with functions, `has_key?` and `get` -- Added `Agent` module with functions, `start`, `get`, `update`, and `get_and_update` + +* Added `JS` module with `new`, `mutate`, `import` macros +* Added `Keyword` module with functions, `has_key?` and `get` +* Added `Agent` module with functions, `start`, `get`, `update`, and `get_and_update` ### Changed -- Map keys are now correctly turned into their atom counterparts if atom keys are used -- `import` works with all options -- `Mutable.update` has been replaced by `JS.update` -- `transpile`, `transpile_quoted`, and `transpile_path` are now `compile`, `compile_quoted`, and `compile_path` -- All Standard libraries are rolled up into one elixir.js file and imported from that -- Modules no longer export a default object -- `alias` now translates to a namespace import unless `default` option is given + +* Map keys are now correctly turned into their atom counterparts if atom keys are used +* `import` works with all options +* `Mutable.update` has been replaced by `JS.update` +* `transpile`, `transpile_quoted`, and `transpile_path` are now `compile`, `compile_quoted`, and `compile_path` +* All Standard libraries are rolled up into one elixir.js file and imported from that +* Modules no longer export a default object +* `alias` now translates to a namespace import unless `default` option is given ## [0.10.0] - 2015-09-02 + ### Added -- Added `env` option for `ElixirScript.transpile` adding macros for compilation -- Added `Logger` that translates Logger functions to console + +* Added `env` option for `ElixirScript.transpile` adding macros for compilation +* Added `Logger` that translates Logger functions to console ### Changed -- Updated `Kernel` module to translate some functions to it's JavaScript equivalent + +* Updated `Kernel` module to translate some functions to it's JavaScript equivalent ### Fixed -- Fixed `case` implementation to add `this` to call + +* Fixed `case` implementation to add `this` to call ## [0.9.0] - 2015-08-30 + ### Added -- an implementation for quote. Currently ignores `:location` and `:context` options -- an implementation for unquote and unquote_splicing + +* an implementation for quote. Currently ignores `:location` and `:context` options +* an implementation for unquote and unquote_splicing ## [0.8.0] - 2015-08-15 + ### Added -- Can now support catch blocks in try expressions -- Added receive + +* Can now support catch blocks in try expressions +* Added receive ### Changed -- Updated pattern matching implementation -- Wrapped try's in function closure to make sure they return a value; + +* Updated pattern matching implementation +* Wrapped try's in function closure to make sure they return a value; ## [0.7.0] - 2015-08-01 + ### Added -- Can now support rescue and after blocks in try expressions + +* Can now support rescue and after blocks in try expressions ## [0.6.5] - 2015-07-13 + ### Changed -- Now using the JS code generator from elixir-estree for code generation, improving speed of transpilation -- the parse functions in the ElixirScript module have been renamed to transpile + +* Now using the JS code generator from elixir-estree for code generation, improving speed of transpilation +* the parse functions in the ElixirScript module have been renamed to transpile ## [0.6.0] - 2015-07-02 + ### Added -- Added iterators for Range and BitString -- Now replacing characters that can't be used in variable and function names in JavaScript with something that it (i.e. `match?` -> `match__qmark__`) -- Implemented Integer module + +* Added iterators for Range and BitString +* Now replacing characters that can't be used in variable and function names in JavaScript with something that it (i.e. `match?` -> `match__qmark__`) +* Implemented Integer module ### Changed -- Made the Tuple, Range and BitString data structures more immutable -- Atom now translates to an ES6 Symbol -- List now translates to a frozen JS Array -- Updated the pattern match binding to use ES6 destructuring for lists and tuples -- Inner modules are now split out into their own files - * Standard lib is now exported with file output from cli - * Standard lib modules are now automatically imported - * No longer have to define modules via aliases ahead of time. They will be automatically be resolved - and made into JavaScript import statements + +* Made the Tuple, Range and BitString data structures more immutable +* Atom now translates to an ES6 Symbol +* List now translates to a frozen JS Array +* Updated the pattern match binding to use ES6 destructuring for lists and tuples +* Inner modules are now split out into their own files + * Standard lib is now exported with file output from cli + * Standard lib modules are now automatically imported + * No longer have to define modules via aliases ahead of time. They will be automatically be resolved + and made into JavaScript import statements ## [0.5.0] - 2015-05-31 + ### Added -- added `from` clause to `import`, `alias`, and `require` so that the import path can be overridden + +* added `from` clause to `import`, `alias`, and `require` so that the import path can be overridden ### Changed -- For statements now work with pattern matching tuples -- Improved function chaining -- `alias` now acts like `require` in that it is translated into an import default statement -- modules now export a default object with def functions added as properties on it. -- for function closures, now calling by using `.call(this)` so that `this` is available inside of it + +* For statements now work with pattern matching tuples +* Improved function chaining +* `alias` now acts like `require` in that it is translated into an import default statement +* modules now export a default object with def functions added as properties on it. +* for function closures, now calling by using `.call(this)` so that `this` is available inside of it ## [0.4.0] - 2015-05-05 + ### Added -- bitstrings -- Better Pattern Matching (Does not support bitstrings yet) -- Capture Operator -- Added more functions from the list standard library + +* bitstrings +* Better Pattern Matching (Does not support bitstrings yet) +* Capture Operator +* Added more functions from the list standard library ### Changed -- Updated variable implementation to match Elixir's (i.e. Reusing the same variable name creates a new one in the background) + +* Updated variable implementation to match Elixir's (i.e. Reusing the same variable name creates a new one in the background) ### Fixed -- Fixed multi arity implementation + +* Fixed multi arity implementation ## [0.3.0] - 2015-04-23 + ### Added -- function and case guards -- function and case pattern matching + +* function and case guards +* function and case pattern matching ### Changed -- Can now use ^ on a variable during assignment + +* Can now use ^ on a variable during assignment ## [0.2.1] - 2015-04-14 + ### Changed -- Renamed project to ElixirScript -- Reduced escript file size + +* Renamed project to ElixirScript +* Reduced escript file size ## [0.2.0] - 2015-04-12 + ### Added -- Pipe operator -- String interpolation -- Adding more functions to the Kernel module -- Fully implemented Tuple module -- Fully implemented Atom module -- Fully implemented Range module + +* Pipe operator +* String interpolation +* Adding more functions to the Kernel module +* Fully implemented Tuple module +* Fully implemented Atom module +* Fully implemented Range module ### Changed -- Now checking to see if a function is a Kernel function and prepending Kernel to it -- Now turning Atoms into an Atom javascript object instead of a Symbol -- Now turning tuples into a Tuple javascript object -- Can now call properties and zero parameter functions correctly -- case, cond, and if are now turned into if statements wrapped in function closures -- Anonymous functions are now turned into anonymous functions in javascript insteed of arrow functions + +* Now checking to see if a function is a Kernel function and prepending Kernel to it +* Now turning Atoms into an Atom javascript object instead of a Symbol +* Now turning tuples into a Tuple javascript object +* Can now call properties and zero parameter functions correctly +* case, cond, and if are now turned into if statements wrapped in function closures +* Anonymous functions are now turned into anonymous functions in javascript insteed of arrow functions ## [0.1.0] - 2015-04-04 + ### Added -- From standard library implemented: - * Enum.map - * Kernel.tl - * Kernel.hd - * Logger -- Implemented language features: - * All primitives except bitstrings - * defmodule - * import, alias, and require - * case, cond, if - * def, defp - * defstruct, defexception - * raise - * multiple arity functions - * basic binary operations - * for without into + +* From standard library implemented: + +- Enum.map +- Kernel.tl +- Kernel.hd +- Logger + +* Implemented language features: + +- All primitives except bitstrings +- defmodule +- import, alias, and require +- case, cond, if +- def, defp +- defstruct, defexception +- raise +- multiple arity functions +- basic binary operations +- for without into diff --git a/mix.exs b/mix.exs index 0ecdc707..ba7fe071 100644 --- a/mix.exs +++ b/mix.exs @@ -5,7 +5,7 @@ defmodule ElixirScript.Mixfile do [ app: :elixir_script, version: "0.32.0-dev", - elixir: "~> 1.5", + elixir: "~> 1.6", elixirc_paths: elixirc_paths(Mix.env), deps: deps(), description: description(), From 2faa3f32e8c096429cb7540db1f4e05368edbad2 Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Tue, 2 Jan 2018 15:48:36 -0600 Subject: [PATCH 824/860] Update Elixir version requirement --- mix.exs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mix.exs b/mix.exs index ba7fe071..11c588f1 100644 --- a/mix.exs +++ b/mix.exs @@ -5,7 +5,7 @@ defmodule ElixirScript.Mixfile do [ app: :elixir_script, version: "0.32.0-dev", - elixir: "~> 1.6", + elixir: "~> 1.6-rc", elixirc_paths: elixirc_paths(Mix.env), deps: deps(), description: description(), From e03df899c66809ea17b8f178b2d4cd22dae95256 Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Wed, 3 Jan 2018 05:30:44 -0600 Subject: [PATCH 825/860] Add ffi module info to manifest. Add diagnostic info as well --- lib/elixir_script/compiler.ex | 105 +++-- .../passes/find_used_functions.ex | 78 ++-- lib/elixir_script/passes/find_used_modules.ex | 145 ++++--- lib/elixir_script/passes/output.ex | 126 +++--- lib/elixir_script/passes/translate/form.ex | 381 ++++++++++-------- lib/elixir_script/passes/translate/module.ex | 282 +++++++------ lib/elixir_script/state.ex | 22 +- lib/mix/tasks/compile.elixir_script.ex | 27 +- test/compiler_test.exs | 10 +- test/passes/translate/forms/receive_test.exs | 30 +- 10 files changed, 711 insertions(+), 495 deletions(-) diff --git a/lib/elixir_script/compiler.ex b/lib/elixir_script/compiler.ex index 36c6de61..61a95201 100644 --- a/lib/elixir_script/compiler.ex +++ b/lib/elixir_script/compiler.ex @@ -29,33 +29,39 @@ defmodule ElixirScript.Compiler do Translate, FindUsedModules, FindUsedFunctions, - Output, + Output } + alias ElixirScript.ModuleSystems.ES alias Kernel.ParallelCompiler - @spec compile(atom | [atom] | binary, []) :: map + @type compiler_input :: + atom + | [atom] + | binary + + @spec compile(compiler_input, []) :: map def compile(path, opts \\ []) def compile(path, opts) when is_binary(path) do opts = build_compiler_options(opts) {:ok, pid} = State.start_link(opts) - path = if String.ends_with?(path, [".ex", ".exs"]) do - path - else - Path.join([path, "**", "*.{ex,exs}"]) - end + path = + if String.ends_with?(path, [".ex", ".exs"]) do + path + else + Path.join([path, "**", "*.{ex,exs}"]) + end files = Path.wildcard(path) - ParallelCompiler.files(files, [ - each_module: &on_module_compile(pid, &1, &2, &3) - ]) + ParallelCompiler.files(files, each_module: &on_module_compile(pid, &1, &2, &3)) - entry_modules = pid - |> State.get_in_memory_modules - |> Keyword.keys + entry_modules = + pid + |> State.get_in_memory_modules() + |> Keyword.keys() do_compile(entry_modules, pid, opts) end @@ -90,11 +96,12 @@ defmodule ElixirScript.Compiler do defp build_compiler_options(opts) do remove_used_functions? = Keyword.get(opts, :remove_unused_functions, true) - default_options = Map.new - |> Map.put(:output, Keyword.get(opts, :output)) - |> Map.put(:format, :es) - |> Map.put(:root, Keyword.get(opts, :root, ".")) - |> Map.put(:remove_unused_functions, remove_used_functions?) + default_options = + Map.new() + |> Map.put(:output, Keyword.get(opts, :output)) + |> Map.put(:format, :es) + |> Map.put(:root, Keyword.get(opts, :root, ".")) + |> Map.put(:remove_unused_functions, remove_used_functions?) options = default_options Map.put(options, :module_formatter, ES) @@ -105,23 +112,51 @@ defmodule ElixirScript.Compiler do end defp transform_output(modules, compiled_js, opts) do - output_path = if opts.output == nil or opts.output == :stdout do - "" - else - Path.dirname(opts.output) - end - - Enum.reduce(modules, %{}, fn {module, info}, current_data -> - info = %{ - references: info.used_modules, - last_modified: info.last_modified, - beam_path: Map.get(info, :beam_path), - source: Map.get(info, :file), - js_path: Path.join(output_path, "#{module}.js"), - js_code: Keyword.get(compiled_js, module) - } - - Map.put(current_data, module, info) + output_path = + if opts.output == nil or opts.output == :stdout do + "" + else + Path.dirname(opts.output) + end + + Enum.reduce(modules, %{}, fn + {module, info}, current_data -> + info = %{ + references: info.used_modules, + last_modified: info.last_modified, + beam_path: Map.get(info, :beam_path), + source: Map.get(info, :file), + js_path: Path.join(output_path, "#{module}.js"), + js_code: Keyword.get(compiled_js, module), + diagnostics: Map.get(info, :diagnostics, []), + type: :module + } + + Map.put(current_data, module, info) + + {module, js_input_path, js_output_path}, current_data -> + last_modified = + case File.stat(js_input_path, time: :posix) do + {:ok, file_info} -> + file_info.mtime + + _ -> + nil + end + + info = %{ + references: [], + last_modified: last_modified, + beam_path: nil, + source: nil, + js_input_path: js_input_path, + js_path: js_output_path, + js_code: nil, + diagnostics: [], + type: :ffi + } + + Map.put(current_data, module, info) end) end end diff --git a/lib/elixir_script/passes/find_used_functions.ex b/lib/elixir_script/passes/find_used_functions.ex index 90d00435..861d7c44 100644 --- a/lib/elixir_script/passes/find_used_functions.ex +++ b/lib/elixir_script/passes/find_used_functions.ex @@ -10,19 +10,17 @@ defmodule ElixirScript.FindUsedFunctions do @spec execute([atom], pid) :: nil def execute(entry_modules, pid) do entry_modules - |> List.wrap - |> Enum.each(fn - module -> - walk_module(module, pid) + |> List.wrap() + |> Enum.each(fn module -> + walk_module(module, pid) end) pid - |> ElixirScript.State.list_modules - |> Enum.each(fn - {module, info} -> - if get_in(info, [:attributes, :protocol_impl]) do - walk_module(module, pid) - end + |> ElixirScript.State.list_modules() + |> Enum.each(fn {module, info} -> + if get_in(info, [:attributes, :protocol_impl]) do + walk_module(module, pid) + end end) end @@ -37,20 +35,25 @@ defmodule ElixirScript.FindUsedFunctions do unreachable: unreachable } = ModuleState.get_module(pid, module) - reachable_defs = Enum.filter(defs, fn - { _, type, _, _} when type in [:defmacro, :defmacrop] -> false - { name, _, _, _} -> - not(name in unreachable) - _ -> true - end) + reachable_defs = + Enum.filter(defs, fn + {_, type, _, _} when type in [:defmacro, :defmacrop] -> + false + + {name, _, _, _} -> + name not in unreachable + + _ -> + true + end) state = %{ pid: pid, module: module } - Enum.each(reachable_defs, fn({name, _type, _, _clauses}) -> - ModuleState.add_used(state.pid, module, name) + Enum.each(reachable_defs, fn {name, _type, _, _clauses} -> + ModuleState.put_used(state.pid, module, name) end) Enum.each(reachable_defs, &walk(&1, state)) @@ -58,6 +61,7 @@ defmodule ElixirScript.FindUsedFunctions do defp walk_module(module, function, arity, pid) do function = {function, arity} + unless ModuleState.has_used?(pid, module, function) do info = ModuleState.get_module(pid, module) @@ -66,13 +70,15 @@ defmodule ElixirScript.FindUsedFunctions do module: module } - reachable_def = Enum.find(Map.get(info, :definitions, []), fn { name, _, _, _} -> name == function end) + reachable_def = + Enum.find(Map.get(info, :definitions, []), fn {name, _, _, _} -> name == function end) case reachable_def do nil -> nil + {name, _type, _, _clauses} = func -> - ModuleState.add_used(state.pid, module, name) + ModuleState.put_used(state.pid, module, name) walk(func, state) end end @@ -82,13 +88,13 @@ defmodule ElixirScript.FindUsedFunctions do Enum.each(clauses, &walk(&1, state)) end - defp walk({ _, _args, _guards, body}, state) do + defp walk({_, _args, _guards, body}, state) do walk_block(body, state) end - defp walk({:->, _, [[{:when, _, params}], body ]}, state) do + defp walk({:->, _, [[{:when, _, params}], body]}, state) do guards = List.last(params) - params = params |> Enum.reverse |> tl |> Enum.reverse + params = params |> Enum.reverse() |> tl |> Enum.reverse() walk({[], params, guards, body}, state) end @@ -119,11 +125,11 @@ defmodule ElixirScript.FindUsedFunctions do end defp walk({:%{}, _, properties}, state) do - Enum.each(properties, fn (val) -> walk(val, state) end) + Enum.each(properties, fn val -> walk(val, state) end) end defp walk({:<<>>, _, elements}, state) do - Enum.each(elements, fn (val) -> walk(val, state) end) + Enum.each(elements, fn val -> walk(val, state) end) end defp walk({:=, _, [left, right]}, state) do @@ -167,7 +173,7 @@ defmodule ElixirScript.FindUsedFunctions do end defp walk({:cond, _, [[do: clauses]]}, state) do - Enum.each(clauses, fn({:->, _, [clause, clause_body]}) -> + Enum.each(clauses, fn {:->, _, [clause, clause_body]} -> Enum.each(List.wrap(clause_body), &walk(&1, state)) walk(hd(clause), state) end) @@ -195,9 +201,10 @@ defmodule ElixirScript.FindUsedFunctions do if rescue_block do Enum.each(rescue_block, fn - {:->, _, [ [{:in, _, [param, names]}], body]} -> + {:->, _, [[{:in, _, [param, names]}], body]} -> walk({[], [param], [{{:., [], [Enum, :member?]}, [], [param, names]}], body}, state) - {:->, _, [ [param], body]} -> + + {:->, _, [[param], body]} -> walk({[], [param], [], body}, state) end) end @@ -234,10 +241,10 @@ defmodule ElixirScript.FindUsedFunctions do [do: expression, else: elses] -> walk_block(expression, state) - Enum.each(elses, fn - {:->, _, [left, right]} -> - walk(left, state) - walk(right, state) + + Enum.each(elses, fn {:->, _, [left, right]} -> + walk(left, state) + walk(right, state) end) end) end @@ -258,10 +265,13 @@ defmodule ElixirScript.FindUsedFunctions do cond do ElixirScript.Translate.Module.is_js_module(module, state) -> nil + ElixirScript.Translate.Module.is_elixir_module(module) -> walk_module(module, function, length(params), state.pid) + is_tuple(module) -> walk(module, state) + true -> nil end @@ -292,13 +302,15 @@ defmodule ElixirScript.FindUsedFunctions do case block do nil -> nil + {:__block__, _, block_body} -> Enum.each(block_body, &walk(&1, state)) + b when is_list(b) -> Enum.each(b, &walk(&1, state)) + _ -> walk(block, state) end end - end diff --git a/lib/elixir_script/passes/find_used_modules.ex b/lib/elixir_script/passes/find_used_modules.ex index d738a006..c111c249 100644 --- a/lib/elixir_script/passes/find_used_modules.ex +++ b/lib/elixir_script/passes/find_used_modules.ex @@ -9,44 +9,65 @@ defmodule ElixirScript.FindUsedModules do @spec execute([atom], pid) :: :ok def execute(modules, pid) do modules - |> List.wrap - |> Enum.each(fn(module) -> + |> List.wrap() + |> Enum.each(fn module -> do_execute(module, pid) end) end defp do_execute(module, pid) do - result = case ModuleState.get_in_memory_module(pid, module) do - nil -> - ElixirScript.Beam.debug_info(module) - beam -> - ElixirScript.Beam.debug_info(beam) - end + result = + case ModuleState.get_in_memory_module(pid, module) do + nil -> + ElixirScript.Beam.debug_info(module) + + beam -> + ElixirScript.Beam.debug_info(beam) + end case result do {:ok, info} -> walk_module(module, info, pid) + {:ok, module, module_info, implementations} -> walk_protocol(module, module_info, implementations, pid) + {:error, "Unknown module"} -> - Logger.warn fn() -> - "ElixirScript: #{inspect module} is missing or unavailable" - end + Logger.warn(fn -> + "ElixirScript: #{inspect(module)} is missing or unavailable" + end) + + ModuleState.put_diagnostic(pid, module, %{ + severity: :warning, + message: "#{inspect(module)} is missing or unavailable" + }) + {:error, error} -> - raise ElixirScript.CompileError, "An error occurred while compiling #{inspect module}: #{error}" + ModuleState.put_diagnostic(pid, module, %{ + severity: :error, + message: "An error occurred while compiling #{inspect(module)}: #{error}" + }) + + raise ElixirScript.CompileError, + "An error occurred while compiling #{inspect(module)}: #{error}" end end - defp walk_module(module, %{attributes: [__foreign_info__: %{path: path, name: name, global: global}]} = info, pid) do - {name, path} = if global do - name = if name, do: name, else: module - path = nil - {name, path} - else - name = Enum.join(Module.split(module), "_") - path = path <> ".js" - {name, path} - end + defp walk_module( + module, + %{attributes: [__foreign_info__: %{path: path, name: name, global: global}]} = info, + pid + ) do + {name, path} = + if global do + name = if name, do: name, else: module + path = nil + {name, path} + else + name = Enum.join(Module.split(module), "_") + path = path <> ".js" + {name, path} + end ModuleState.put_javascript_module(pid, module, name, path) ModuleState.put_module(pid, module, info) @@ -67,42 +88,41 @@ defmodule ElixirScript.FindUsedModules do ModuleState.put_module(pid, module, info) - reachable_defs = Enum.filter(defs, fn - { _, type, _, _} when type in [:defmacro, :defmacrop] -> false - { name, _, _, _} -> not(name in unreachable) - _ -> true - end) + reachable_defs = + Enum.filter(defs, fn + {_, type, _, _} when type in [:defmacro, :defmacrop] -> false + {name, _, _, _} -> name not in unreachable + _ -> true + end) state = %{ pid: pid, module: module } - Enum.each(reachable_defs, fn(x) -> + Enum.each(reachable_defs, fn x -> walk(x, state) end) end defp walk_protocol(module, module_info, implementations, pid) do - impls = Enum.map(implementations, fn {impl, %{attributes: attrs}} -> - protocol_impl = Keyword.fetch!(attrs, :protocol_impl) - impl_for = Keyword.fetch!(protocol_impl, :for) - {impl, impl_for} - end) + impls = + Enum.map(implementations, fn {impl, %{attributes: attrs}} -> + protocol_impl = Keyword.fetch!(attrs, :protocol_impl) + impl_for = Keyword.fetch!(protocol_impl, :for) + {impl, impl_for} + end) first_implementation_functions = implementations |> hd |> elem(1) |> Map.get(:definitions) - functions = Enum.map(first_implementation_functions, fn { name, _, _, _} -> name end) + functions = Enum.map(first_implementation_functions, fn {name, _, _, _} -> name end) - module_info = Map.merge( - module_info, - %{protocol: true, impls: impls, functions: functions} - ) + module_info = Map.merge(module_info, %{protocol: true, impls: impls, functions: functions}) ModuleState.put_module(pid, module, module_info) Enum.each(implementations, fn {impl, info} -> - ModuleState.add_used_module(pid, module, impl) + ModuleState.put_used_module(pid, module, impl) walk_module(impl, info, pid) end) end @@ -111,13 +131,13 @@ defmodule ElixirScript.FindUsedModules do Enum.each(clauses, &walk(&1, state)) end - defp walk({ _, _args, _guards, body}, state) do + defp walk({_, _args, _guards, body}, state) do walk_block(body, state) end - defp walk({:->, _, [[{:when, _, params}], body ]}, state) do + defp walk({:->, _, [[{:when, _, params}], body]}, state) do guards = List.last(params) - params = params |> Enum.reverse |> tl |> Enum.reverse + params = params |> Enum.reverse() |> tl |> Enum.reverse() walk({[], params, guards, body}, state) end @@ -139,9 +159,12 @@ defmodule ElixirScript.FindUsedModules do Enum.each(form, &walk(&1, state)) end - defp walk(form, state) when is_atom(form) and form not in [BitString, Function, PID, Port, Reference, Any, Elixir] do - if ElixirScript.Translate.Module.is_elixir_module(form) and !ElixirScript.Translate.Module.is_js_module(form, state) do - ModuleState.add_used_module(state.pid, state.module, form) + defp walk(form, state) + when is_atom(form) and form not in [BitString, Function, PID, Port, Reference, Any, Elixir] do + if ElixirScript.Translate.Module.is_elixir_module(form) and + !ElixirScript.Translate.Module.is_js_module(form, state) do + ModuleState.put_used_module(state.pid, state.module, form) + if ModuleState.get_module(state.pid, form) == nil do do_execute(form, state.pid) end @@ -157,11 +180,11 @@ defmodule ElixirScript.FindUsedModules do end defp walk({:%{}, _, properties}, state) do - Enum.each(properties, fn (val) -> walk(val, state) end) + Enum.each(properties, fn val -> walk(val, state) end) end defp walk({:<<>>, _, elements}, state) do - Enum.each(elements, fn (val) -> walk(val, state) end) + Enum.each(elements, fn val -> walk(val, state) end) end defp walk({:=, _, [left, right]}, state) do @@ -170,8 +193,10 @@ defmodule ElixirScript.FindUsedModules do end defp walk({:%, _, [module, params]}, state) do - if ElixirScript.Translate.Module.is_elixir_module(module) and !ElixirScript.Translate.Module.is_js_module(module, state) do - ModuleState.add_used_module(state.pid, state.module, module) + if ElixirScript.Translate.Module.is_elixir_module(module) and + !ElixirScript.Translate.Module.is_js_module(module, state) do + ModuleState.put_used_module(state.pid, state.module, module) + if ModuleState.get_module(state.pid, module) == nil do do_execute(module, state.pid) end @@ -212,7 +237,7 @@ defmodule ElixirScript.FindUsedModules do end defp walk({:cond, _, [[do: clauses]]}, state) do - Enum.each(clauses, fn({:->, _, [clause, clause_body]}) -> + Enum.each(clauses, fn {:->, _, [clause, clause_body]} -> Enum.each(List.wrap(clause_body), &walk(&1, state)) walk(hd(clause), state) end) @@ -242,10 +267,11 @@ defmodule ElixirScript.FindUsedModules do if rescue_block do Enum.each(rescue_block, fn - {:->, _, [ [{:in, _, [param, names]}], body]} -> + {:->, _, [[{:in, _, [param, names]}], body]} -> Enum.each(names, &walk(&1, state)) walk({[], [param], [{{:., [], [Enum, :member?]}, [], [names, param]}], body}, state) - {:->, _, [ [param], body]} -> + + {:->, _, [[param], body]} -> walk({[], [param], [], body}, state) end) end @@ -282,10 +308,10 @@ defmodule ElixirScript.FindUsedModules do [do: expression, else: elses] -> walk_block(expression, state) - Enum.each(elses, fn - {:->, _, [left, right]} -> - walk(left, state) - walk(right, state) + + Enum.each(elses, fn {:->, _, [left, right]} -> + walk(left, state) + walk(right, state) end) end) end @@ -309,7 +335,8 @@ defmodule ElixirScript.FindUsedModules do defp walk({:., _, [module, function]}, state) do if ElixirScript.Translate.Module.is_elixir_module(module) do - ModuleState.add_used_module(state.pid, state.module, module) + ModuleState.put_used_module(state.pid, state.module, module) + if ModuleState.get_module(state.pid, module) == nil do do_execute(module, state.pid) end @@ -336,13 +363,15 @@ defmodule ElixirScript.FindUsedModules do case block do nil -> nil + {:__block__, _, block_body} -> Enum.each(block_body, &walk(&1, state)) + b when is_list(b) -> Enum.each(b, &walk(&1, state)) + _ -> walk(block, state) end end - end diff --git a/lib/elixir_script/passes/output.ex b/lib/elixir_script/passes/output.ex index 9a519fff..961b3d3b 100644 --- a/lib/elixir_script/passes/output.ex +++ b/lib/elixir_script/passes/output.ex @@ -9,23 +9,23 @@ defmodule ElixirScript.Output do """ @spec execute([atom], pid, map) :: [{atom, binary}] def execute(modules, pid, opts) do - js_modules = ModuleState.js_modules(pid) - |> Enum.filter(fn - {_module, _name, nil} -> false - _ -> true - end) - |> Enum.map(fn - {module, name, path} -> + js_modules = + ModuleState.js_modules(pid) + |> Enum.filter(fn + {_module, _name, nil} -> false + _ -> true + end) + |> Enum.map(fn {module, name, path} -> import_path = Path.join(opts.root, path) {module, name, path, import_path} - end) + end) - prepared_modules = modules - |> Enum.filter(fn {_, info} -> Map.has_key?(info, :js_ast) end) - |> Enum.map(fn {module, info} -> + prepared_modules = + modules + |> Enum.filter(fn {_, info} -> Map.has_key?(info, :js_ast) end) + |> Enum.map(fn {module, info} -> {module, info.js_ast, filter_used_modules(info.used_modules, pid)} - end - ) + end) create_modules(prepared_modules, opts, js_modules) end @@ -47,22 +47,27 @@ defmodule ElixirScript.Output do defp create_modules(modules, opts, js_modules) do modules - |> Task.async_stream(fn({module, [body, exports], used_modules}) -> - modules = modules_to_import(used_modules) ++ js_modules - - imports = opts.module_formatter.build_imports(modules) - exports = opts.module_formatter.build_export(exports) - - js_parts = List.wrap(imports) ++ body ++ List.wrap(exports) - - js_parts - |> Builder.program - |> Generator.generate - |> concat - |> output(module, Map.get(opts, :output), js_modules) - end, timeout: 10_000) + |> Task.async_stream( + fn {module, [body, exports], used_modules} -> + modules = modules_to_import(used_modules) ++ js_modules + + imports = opts.module_formatter.build_imports(modules) + exports = opts.module_formatter.build_export(exports) + + js_parts = List.wrap(imports) ++ body ++ List.wrap(exports) + + js_parts + |> Builder.program() + |> Generator.generate() + |> concat + |> output(module, Map.get(opts, :output), js_modules) + end, + timeout: 10_000 + ) |> Stream.map(fn {:ok, code} -> code end) |> Enum.to_list() + |> List.flatten() + |> Enum.uniq() end defp modules_to_import(modules) do @@ -70,79 +75,92 @@ defmodule ElixirScript.Output do end defp module_to_import(module) do - {module, module_to_name(module), "", "./Elixir.#{inspect module}.js"} + {module, module_to_name(module), "", "./Elixir.#{inspect(module)}.js"} end def module_to_name(module) do - "$#{inspect module}$" + "$#{inspect(module)}$" |> String.replace(".", "$") end - defp output(code, module, nil, _), do: {module, code} + defp output(code, module, nil, _), do: [{module, code}] + defp output(code, module, :stdout, _) do IO.puts(code) - {module, code} + [{module, code}] end defp output(code, module, path, js_modules) do - output_dir = if File.dir?(path) do - path - else - Path.dirname(path) - end + output_dir = + if File.dir?(path) do + path + else + Path.dirname(path) + end - file_name = Path.join(output_dir, "Elixir.#{inspect module}.js") + file_name = Path.join(output_dir, "Elixir.#{inspect(module)}.js") if !File.exists?(output_dir) do File.mkdir_p!(output_dir) end apps = get_app_names() - Enum.each(js_modules, fn({_, _, path, _}) -> - copy_javascript_module(apps, output_dir, path) - end) + + ffi_modules = + Enum.reduce(js_modules, [], fn {module, _, path, _}, acc -> + acc ++ copy_javascript_module(apps, output_dir, module, path) + end) copy_bootstrap_js(output_dir) File.write!(file_name, code) - {module, code} + [{module, code}] ++ ffi_modules end defp copy_bootstrap_js(directory) do - operating_path = Path.join([Mix.Project.build_path, "lib", "elixir_script", "priv"]) + operating_path = Path.join([Mix.Project.build_path(), "lib", "elixir_script", "priv"]) path = Path.join([operating_path, "build", "es", "ElixirScript.Core.js"]) File.cp!(path, Path.join([directory, "ElixirScript.Core.js"])) end defp get_app_names() do Mix.Project.config()[:app] - deps = Mix.Project.deps_paths() - |> Map.keys + + deps = + Mix.Project.deps_paths() + |> Map.keys() [Mix.Project.config()[:app]] ++ deps end - defp copy_javascript_module(apps, output_dir, js_module_path) do - Enum.each(apps, fn(app) -> + defp copy_javascript_module(apps, output_dir, module, js_module_path) do + Enum.reduce(apps, [], fn app, acc -> base_path = Path.join([:code.priv_dir(app), "elixir_script"]) - js_input_path = cond do - File.exists?(Path.join([base_path, js_module_path])) -> - Path.join([base_path, js_module_path]) - File.exists?(Path.join([base_path, slashes_to_dots(js_module_path)])) -> - Path.join([base_path, slashes_to_dots(js_module_path)]) - true -> - nil - end + js_input_path = + cond do + File.exists?(Path.join([base_path, js_module_path])) -> + Path.join([base_path, js_module_path]) + + File.exists?(Path.join([base_path, slashes_to_dots(js_module_path)])) -> + Path.join([base_path, slashes_to_dots(js_module_path)]) + + true -> + nil + end if js_input_path != nil do js_output_path = Path.join(output_dir, js_module_path) js_output_dir = Path.dirname(js_output_path) + if !File.exists?(js_output_dir) do File.mkdir_p!(js_output_dir) end File.cp(js_input_path, js_output_path) + acc ++ [{module, js_input_path, js_output_path}] + else + [] end end) end diff --git a/lib/elixir_script/passes/translate/form.ex b/lib/elixir_script/passes/translate/form.ex index 475b4e02..c14a4361 100644 --- a/lib/elixir_script/passes/translate/form.ex +++ b/lib/elixir_script/passes/translate/form.ex @@ -7,29 +7,31 @@ defmodule ElixirScript.Translate.Form do alias ElixirScript.Translate.Helpers alias ElixirScript.Translate.Forms.{Bitstring, Match, Try, For, Receive, Remote, Pattern, With} alias ElixirScript.Translate.Clause + alias ElixirScript.State, as: ModuleState require Logger - @spec compile!(any, map) :: ESTree.Node.t + @spec compile!(any, map) :: ESTree.Node.t() def compile!(ast, state) do {js_ast, _} = compile(ast, state) js_ast end - @spec compile(any, map) :: {ESTree.Node.t, map} + @spec compile(any, map) :: {ESTree.Node.t(), map} def compile(ast, state) def compile(nil, state) do - { J.identifier("null"), state } + {J.identifier("null"), state} end def compile(map, state) when is_map(map) do - quoted = Code.string_to_quoted!("#{inspect map}") + quoted = Code.string_to_quoted!("#{inspect(map)}") compile(quoted, state) end - def compile(form, state) when is_boolean(form) or is_integer(form) or is_float(form) or is_binary(form) do - { J.literal(form), state } + def compile(form, state) + when is_boolean(form) or is_integer(form) or is_float(form) or is_binary(form) do + {J.literal(form), state} end def compile([{:|, _, [_head, _tail]} = ast], state) do @@ -37,33 +39,33 @@ defmodule ElixirScript.Translate.Form do end def compile({:|, _, [head, tail]}, state) do - ast = Helpers.call( - J.member_expression( - Helpers.functions(), - J.identifier("concat") - ), - [compile!(head, state), compile!(tail, state)] - ) + ast = + Helpers.call( + J.member_expression( + Helpers.functions(), + J.identifier("concat") + ), + [compile!(head, state), compile!(tail, state)] + ) - { ast, state } + {ast, state} end def compile(form, state) when is_list(form) do - ast = J.array_expression( - Enum.map(form, &compile!(&1, state)) - ) + ast = J.array_expression(Enum.map(form, &compile!(&1, state))) - { ast, state } + {ast, state} end def compile(form, state) when is_atom(form) do - ast = if ElixirScript.Translate.Module.is_elixir_module(form) do - Remote.process_module_name(form, state) - else - Helpers.symbol(form) - end + ast = + if ElixirScript.Translate.Module.is_elixir_module(form) do + Remote.process_module_name(form, state) + else + Helpers.symbol(form) + end - { ast, state } + {ast, state} end def compile({a, b}, state) do @@ -71,10 +73,11 @@ defmodule ElixirScript.Translate.Form do end def compile({:{}, _, elements}, state) do - ast = Helpers.new( - Helpers.tuple(), - Enum.map(elements, &compile!(&1, state)) |> List.flatten - ) + ast = + Helpers.new( + Helpers.tuple(), + Enum.map(elements, &compile!(&1, state)) |> List.flatten() + ) {ast, state} end @@ -97,16 +100,19 @@ defmodule ElixirScript.Translate.Form do end def compile({:<<>>, _, elements} = bitstring, state) do - is_interpolated_string = Enum.all?(elements, fn(x) -> - case x do - b when is_binary(b) -> - true - {:::, _, [_target, {:binary, _, _}]} -> - true - _ -> - false - end - end) + is_interpolated_string = + Enum.all?(elements, fn x -> + case x do + b when is_binary(b) -> + true + + {:::, _, [_target, {:binary, _, _}]} -> + true + + _ -> + false + end + end) if is_interpolated_string do Bitstring.make_interpolated_string(elements, state) @@ -120,15 +126,16 @@ defmodule ElixirScript.Translate.Form do end def compile({:%, _, [module, params]}, state) do - ast = Helpers.call( - J.member_expression( - Remote.process_module_name(module, state), - J.identifier("__struct__") - ), - [compile!(params, state)] - ) + ast = + Helpers.call( + J.member_expression( + Remote.process_module_name(module, state), + J.identifier("__struct__") + ), + [compile!(params, state)] + ) - { ast, state } + {ast, state} end def compile({:for, _, generators} = ast, state) when is_list(generators) do @@ -141,61 +148,78 @@ defmodule ElixirScript.Translate.Form do match_ast = List.wrap(match_ast) - { match_ast ++ [case_ast], state } + {match_ast ++ [case_ast], state} end def compile({:case, _, [condition, [do: clauses]]}, state) do - func = Helpers.call( - J.member_expression( - Helpers.patterns(), - J.identifier("defmatch") - ), - Enum.map(clauses, fn x -> Clause.compile(x, state) |> elem(0) end) |> List.flatten - ) - - ast = Helpers.call( - J.member_expression( func, J.identifier("call")), - [J.identifier(:this), compile!(condition, state)] - ) + func = + Helpers.call( + J.member_expression( + Helpers.patterns(), + J.identifier("defmatch") + ), + Enum.map(clauses, fn x -> Clause.compile(x, state) |> elem(0) end) |> List.flatten() + ) + + ast = + Helpers.call(J.member_expression(func, J.identifier("call")), [ + J.identifier(:this), + compile!(condition, state) + ]) - { ast, state } + {ast, state} end def compile({:cond, _, [[do: clauses]]}, state) do - processed_clauses = Enum.map(clauses, fn({:->, _, [clause, clause_body]}) -> - { translated_body, state } = ElixirScript.Translate.Function.compile_block(clause_body, state) - - translated_body = translated_body - |> Clause.return_last_statement + processed_clauses = + Enum.map(clauses, fn {:->, _, [clause, clause_body]} -> + {translated_body, state} = + ElixirScript.Translate.Function.compile_block(clause_body, state) - translated_body = Helpers.arrow_function([], J.block_statement(translated_body)) + translated_body = + translated_body + |> Clause.return_last_statement() - { translated_clause, _ } = compile(hd(clause), state) + translated_body = Helpers.arrow_function([], J.block_statement(translated_body)) + {translated_clause, _} = compile(hd(clause), state) - J.array_expression([translated_clause, translated_body]) - end) - + J.array_expression([translated_clause, translated_body]) + end) - cond_function = J.member_expression( - Helpers.special_forms(), - J.identifier("cond") - ) + cond_function = + J.member_expression( + Helpers.special_forms(), + J.identifier("cond") + ) - ast = Helpers.call( - cond_function, - processed_clauses - ) + ast = + Helpers.call( + cond_function, + processed_clauses + ) - { ast, state } + {ast, state} end def compile({:receive, context, [blocks]}, state) do line = Keyword.get(context, :line, 1) + module = Map.get(state, :module) + pid = Map.get(state, :pid) {function, _arity} = Map.get(state, :function) - Logger.warn fn() -> - "ElixirScript: receive not supported, Module: #{inspect state.module}, Function: #{function}, Line: #{line}" - end + + ModuleState.put_diagnostic(pid, module, %{ + severity: :warning, + message: "receive not supported, Module: #{inspect(state.module)}, Function: #{function}", + position: line + }) + + Logger.warn(fn -> + "ElixirScript: receive not supported, Module: #{inspect(state.module)}, Function: #{ + function + }, Line: #{line}" + end) + Receive.compile(blocks, state) end @@ -212,102 +236,113 @@ defmodule ElixirScript.Translate.Form do end def compile({{:., _, [:erlang, op]}, _, [item]}, state) when op in [:+, :-] do - ast = J.unary_expression( - op, - true, - compile!(item, state) - ) + ast = + J.unary_expression( + op, + true, + compile!(item, state) + ) {ast, state} end def compile({{:., _, [:erlang, op]}, _, [left, right]}, state) when op in [:==, :===] do - ast = Helpers.call( - J.member_expression( - Helpers.core_module("erlang"), - J.identifier("equals") - ), - [compile!(left, state), compile!(right, state)] - ) + ast = + Helpers.call( + J.member_expression( + Helpers.core_module("erlang"), + J.identifier("equals") + ), + [compile!(left, state), compile!(right, state)] + ) {ast, state} end - def compile({{:., _, [:erlang, op]}, _, [left, right]}, state) when op in [:+, :-, :*, :/, :>, :<, :>=] do - ast = J.binary_expression( - op, - compile!(left, state), - compile!(right, state) - ) + def compile({{:., _, [:erlang, op]}, _, [left, right]}, state) + when op in [:+, :-, :*, :/, :>, :<, :>=] do + ast = + J.binary_expression( + op, + compile!(left, state), + compile!(right, state) + ) {ast, state} end def compile({{:., _, [:erlang, :"=<"]}, _, [left, right]}, state) do - ast = J.binary_expression( - :<=, - compile!(left, state), - compile!(right, state) - ) + ast = + J.binary_expression( + :<=, + compile!(left, state), + compile!(right, state) + ) {ast, state} end def compile({{:., _, [:erlang, :"=:="]}, _, [left, right]}, state) do - ast = J.binary_expression( - :===, - compile!(left, state), - compile!(right, state) - ) + ast = + J.binary_expression( + :===, + compile!(left, state), + compile!(right, state) + ) {ast, state} end def compile({{:., _, [:erlang, :"=/="]}, _, [left, right]}, state) do - ast = J.binary_expression( - :!==, - compile!(left, state), - compile!(right, state) - ) + ast = + J.binary_expression( + :!==, + compile!(left, state), + compile!(right, state) + ) {ast, state} end def compile({{:., _, [:erlang, :"/="]}, _, [left, right]}, state) do - ast = J.binary_expression( - :!=, - compile!(left, state), - compile!(right, state) - ) + ast = + J.binary_expression( + :!=, + compile!(left, state), + compile!(right, state) + ) {ast, state} end def compile({{:., _, [:erlang, op]}, _, [left, right]}, state) when op in [:andalso, :and] do - ast = J.binary_expression( - :&&, - compile!(left, state), - compile!(right, state) - ) + ast = + J.binary_expression( + :&&, + compile!(left, state), + compile!(right, state) + ) {ast, state} end def compile({{:., _, [:erlang, op]}, _, [left, right]}, state) when op in [:orelse, :or] do - ast = J.binary_expression( - :||, - compile!(left, state), - compile!(right, state) - ) + ast = + J.binary_expression( + :||, + compile!(left, state), + compile!(right, state) + ) {ast, state} end def compile({{:., _, [var, func_or_prop]}, _, []}, state) when not is_atom(var) do - ast = Helpers.call( - ElixirScript.Translate.Forms.JS.call_property(), - [compile!(var, state), J.literal(to_string(func_or_prop))] - ) + ast = + Helpers.call(ElixirScript.Translate.Forms.JS.call_property(), [ + compile!(var, state), + J.literal(to_string(func_or_prop)) + ]) {ast, state} end @@ -324,14 +359,16 @@ defmodule ElixirScript.Translate.Form do {function_name, _} = Map.get(state, :function) {var_decs, params} = compile_params(params, state) - ast = Helpers.call( - ElixirScript.Translate.Identifier.make_function_name(function_name), - params - ) + ast = + Helpers.call( + ElixirScript.Translate.Identifier.make_function_name(function_name), + params + ) case var_decs do [] -> {ast, state} + _ -> {var_decs ++ List.wrap(ast), state} end @@ -344,24 +381,24 @@ defmodule ElixirScript.Translate.Form do def compile({var, _, params}, state) when is_list(params) and is_atom(var) do {var_decs, params} = compile_params(params, state) - ast = Helpers.call( - ElixirScript.Translate.Identifier.make_function_name(var), - params - ) + ast = + Helpers.call( + ElixirScript.Translate.Identifier.make_function_name(var), + params + ) case var_decs do [] -> {ast, state} + _ -> {var_decs ++ List.wrap(ast), state} end end def compile({function, _, []}, state) do - ast = Helpers.call( - ElixirScript.Translate.Forms.JS.call_property(), - [compile!(function, state)] - ) + ast = + Helpers.call(ElixirScript.Translate.Forms.JS.call_property(), [compile!(function, state)]) {ast, state} end @@ -369,14 +406,16 @@ defmodule ElixirScript.Translate.Form do def compile({function, _, params}, state) when is_list(params) do {var_decs, params} = compile_params(params, state) - ast = Helpers.call( - compile!(function, state), - params - ) + ast = + Helpers.call( + compile!(function, state), + params + ) case var_decs do [] -> {ast, state} + _ -> {var_decs ++ List.wrap(ast), state} end @@ -387,34 +426,36 @@ defmodule ElixirScript.Translate.Form do var = ElixirScript.Translate.Identifier.filter_name(var) var = Pattern.get_variable_name(var <> counter, state) - { ElixirScript.Translate.Identifier.make_identifier(var), state } + {ElixirScript.Translate.Identifier.make_identifier(var), state} end defp compile_params(params, state) do - {params, var_decs} = Enum.map_reduce(params, [], fn - ({:=, _, [{left_var, _, atom} = left, right]} = ast, acc) when is_atom(atom) -> - case Atom.to_string(left_var) do - "_" <> _ -> - {compile!(right, state), acc} - _ -> - {ast, state} = compile(ast, state) - left = compile!(left, state) + {params, var_decs} = + Enum.map_reduce(params, [], fn + {:=, _, [{left_var, _, atom} = left, right]} = ast, acc when is_atom(atom) -> + case Atom.to_string(left_var) do + "_" <> _ -> + {compile!(right, state), acc} - {left, acc ++ List.wrap(ast)} - end + _ -> + {ast, state} = compile(ast, state) + left = compile!(left, state) - ({:=, _, [left, _]} = ast, acc) -> - {ast, state} = compile(ast, state) - left = compile!(left, state) + {left, acc ++ List.wrap(ast)} + end - {left, acc ++ List.wrap(ast)} - (x, acc) -> - compiled = compile!(x, state) + {:=, _, [left, _]} = ast, acc -> + {ast, state} = compile(ast, state) + left = compile!(left, state) - {compiled, acc} - end) + {left, acc ++ List.wrap(ast)} + + x, acc -> + compiled = compile!(x, state) + + {compiled, acc} + end) {var_decs, params} end - end diff --git a/lib/elixir_script/passes/translate/module.ex b/lib/elixir_script/passes/translate/module.ex index 58638e02..831c6848 100644 --- a/lib/elixir_script/passes/translate/module.ex +++ b/lib/elixir_script/passes/translate/module.ex @@ -7,8 +7,22 @@ defmodule ElixirScript.Translate.Module do alias ElixirScript.Translate.Form @operators [ - :+, :-, :*, :/, :!=, :==, :===, :<=, :>=, :=~, :++, - :!==, :--, :<, :> + :+, + :-, + :*, + :/, + :!=, + :==, + :===, + :<=, + :>=, + :=~, + :++, + :!==, + :--, + :<, + :>, + :=~ ] @doc """ @@ -31,7 +45,7 @@ defmodule ElixirScript.Translate.Module do file: _file, line: _line, module: ^module, - unreachable: unreachable, + unreachable: unreachable } = info used = Map.get(info, :used) @@ -44,34 +58,44 @@ defmodule ElixirScript.Translate.Module do # Filter so that we only have the # Used functions to compile - reachable_defs = Enum.filter(defs, fn - { _, type, _, _} when type in [:defmacro, :defmacrop] -> false - { name, _, _, _} -> not(name in unreachable) + reachable_defs = + Enum.filter(defs, fn + {_, type, _, _} when type in [:defmacro, :defmacrop] -> false + {name, _, _, _} -> name not in unreachable _ -> true end) - used_defs = if Keyword.has_key?(attrs, :protocol_impl) or used == nil do - reachable_defs - else - Enum.filter(reachable_defs, fn - { {:start, 2}, _, _, _ } -> true - { {:__struct__, _}, _, _, _ } -> true - { {name, _}, _, _, _ } when name in @operators -> false - { name, _, _, _} -> - if remove_unused_functions do - name in used - else + used_defs = + if Keyword.has_key?(attrs, :protocol_impl) or used == nil do + reachable_defs + else + Enum.filter(reachable_defs, fn + {{:start, 2}, _, _, _} -> true - end - _ -> false - end) - end - #we combine our function arities + {{:__struct__, _}, _, _, _} -> + true + + {{name, _}, _, _, _} when name in @operators -> + false + + {name, _, _, _} -> + if remove_unused_functions do + name in used + else + true + end + + _ -> + false + end) + end + + # we combine our function arities combined_defs = combine_defs(used_defs) exports = make_exports(module, combined_defs) - { compiled_functions, _ } = Enum.map_reduce(combined_defs, state, &Function.compile(&1, &2)) + {compiled_functions, _} = Enum.map_reduce(combined_defs, state, &Function.compile(&1, &2)) info_function = make_info_function(module, state) compiled_functions = [info_function] ++ compiled_functions @@ -83,37 +107,47 @@ defmodule ElixirScript.Translate.Module do defp combine_defs(used_defs) do used_defs - |> Enum.sort(fn { {name1, arity1}, _, _, _ }, { {name2, arity2}, _, _, _ } -> "#{name1}#{arity1}" < "#{name2}#{arity2}" end) - |> Enum.group_by(fn {{name, _}, _, _, _ } -> name end) + |> Enum.sort(fn {{name1, arity1}, _, _, _}, {{name2, arity2}, _, _, _} -> + "#{name1}#{arity1}" < "#{name2}#{arity2}" + end) + |> Enum.group_by(fn {{name, _}, _, _, _} -> name end) |> Enum.map(fn {group, funs} -> - {_, type, _, _} = hd(funs) - Enum.reduce(funs, {{group, nil}, type, [], []}, fn {_, _, _, clauses}, {name, type, context, acc_clauses} -> - {name, type, context, acc_clauses ++ clauses} - end) + {_, type, _, _} = hd(funs) + + Enum.reduce(funs, {{group, nil}, type, [], []}, fn {_, _, _, clauses}, + {name, type, context, acc_clauses} -> + {name, type, context, acc_clauses ++ clauses} end) + end) end defp make_exports(module, reachable_defs) do - exports = Enum.reduce(reachable_defs, [], fn - {{name, _arity}, :def, _, _}, list -> - function_name = ElixirScript.Translate.Identifier.make_identifier(name) + exports = + Enum.reduce(reachable_defs, [], fn + {{name, _arity}, :def, _, _}, list -> + function_name = ElixirScript.Translate.Identifier.make_identifier(name) list ++ [J.property(function_name, function_name, :init, true)] - _, list -> - list - end) + + _, list -> + list + end) # Add an attribute to use to determine if this is a module # Will be used by the is_atom implementation - exports = exports ++ [%ESTree.Property{ - key: J.identifier("__MODULE__"), - value: Helpers.symbol(to_string(module)) - }, - J.property( - J.identifier("__info__"), - J.identifier("__info__"), - :init, - true - )] + exports = + exports ++ + [ + %ESTree.Property{ + key: J.identifier("__MODULE__"), + value: Helpers.symbol(to_string(module)) + }, + J.property( + J.identifier("__info__"), + J.identifier("__info__"), + :init, + true + ) + ] J.object_expression(exports) end @@ -128,6 +162,7 @@ defmodule ElixirScript.Translate.Module do case str_module do "Elixir" <> _ -> true + _ -> false end @@ -147,67 +182,73 @@ defmodule ElixirScript.Translate.Module do cond do module in ModuleState.list_javascript_modules(state.pid) -> true + module === Elixir -> false + true -> false end end defp make_info_map(module, state) do - functions = module.__info__(:functions) - |> Form.compile!(state) + functions = + module.__info__(:functions) + |> Form.compile!(state) - macros = module.__info__(:macros) - |> Form.compile!(state) + macros = + module.__info__(:macros) + |> Form.compile!(state) - attributes = module.__info__(:attributes) - |> Form.compile!(state) + attributes = + module.__info__(:attributes) + |> Form.compile!(state) - compile = module.__info__(:compile) - |> Keyword.update(:source, "", fn(x) -> :erlang.list_to_binary(x) end) - |> Form.compile!(state) + compile = + module.__info__(:compile) + |> Keyword.update(:source, "", fn x -> :erlang.list_to_binary(x) end) + |> Form.compile!(state) - md5 = module.__info__(:md5) - |> :erlang.binary_to_list + md5 = + module.__info__(:md5) + |> :erlang.binary_to_list() md5 = Form.compile!({:<<>>, [], md5}, state) module = Helpers.symbol(to_string(module)) - map_entries = J.array_expression([ + map_entries = J.array_expression([ - Helpers.symbol("functions"), - functions - ]), - J.array_expression([ - Helpers.symbol("macros"), - macros - ]), - J.array_expression([ - Helpers.symbol("attributes"), - attributes - ]), - J.array_expression([ - Helpers.symbol("compile"), - compile - ]), - J.array_expression([ - Helpers.symbol("md5"), - md5 - ]), - J.array_expression([ - Helpers.symbol("module"), - module - ]), - ]) - - map = Helpers.new( - J.identifier("Map"), - [ + J.array_expression([ + Helpers.symbol("functions"), + functions + ]), + J.array_expression([ + Helpers.symbol("macros"), + macros + ]), + J.array_expression([ + Helpers.symbol("attributes"), + attributes + ]), + J.array_expression([ + Helpers.symbol("compile"), + compile + ]), + J.array_expression([ + Helpers.symbol("md5"), + md5 + ]), + J.array_expression([ + Helpers.symbol("module"), + module + ]) + ]) + + map = + Helpers.new(J.identifier("Map"), [ map_entries - ] - ) + ]) Helpers.declare("__info__map__", map) end @@ -217,43 +258,46 @@ defmodule ElixirScript.Translate.Module do defp make_info_function(module, state) do info_map = make_info_map(module, state) - get_call = Helpers.call( - J.member_expression( - J.identifier("__info__map__"), - J.identifier("get") - ), - [ - J.identifier("kind") - ] - ) + get_call = + Helpers.call( + J.member_expression( + J.identifier("__info__map__"), + J.identifier("get") + ), + [ + J.identifier("kind") + ] + ) value = Helpers.declare("value", get_call) - body = J.if_statement( - J.binary_expression( - :!==, - J.identifier("value"), - J.identifier("null") - ), - J.block_statement([ - J.return_statement(J.identifier("value")) - ]) - ) + body = + J.if_statement( + J.binary_expression( + :!==, + J.identifier("value"), + J.identifier("null") + ), + J.block_statement([ + J.return_statement(J.identifier("value")) + ]) + ) - body = J.block_statement([ - info_map, - value, - body, - J.throw_statement( - Helpers.new( - J.member_expression( - Helpers.patterns(), - J.identifier("MatchError") - ), - [J.identifier("kind")] + body = + J.block_statement([ + info_map, + value, + body, + J.throw_statement( + Helpers.new( + J.member_expression( + Helpers.patterns(), + J.identifier("MatchError") + ), + [J.identifier("kind")] + ) ) - ) - ]) + ]) Helpers.function( "__info__", diff --git a/lib/elixir_script/state.ex b/lib/elixir_script/state.ex index 73208ec6..3a45f745 100644 --- a/lib/elixir_script/state.ex +++ b/lib/elixir_script/state.ex @@ -35,7 +35,7 @@ defmodule ElixirScript.State do end) end - def add_used_module(pid, module, used_module) do + def put_used_module(pid, module, used_module) do Agent.update(pid, fn state -> module_info = Keyword.get(state.modules, module) @@ -58,7 +58,7 @@ defmodule ElixirScript.State do end) end - def add_used(pid, module, {_function, _arity} = func) do + def put_used(pid, module, {_function, _arity} = func) do Agent.update(pid, fn state -> module_info = Keyword.get(state.modules, module) @@ -80,6 +80,24 @@ defmodule ElixirScript.State do end) end + def put_diagnostic(pid, module, diagnostic) do + Agent.update(pid, fn state -> + module_info = Keyword.get(state.modules, module) + + if module_info do + diagnostics = Map.get(module_info, :diagnostics, []) + diagnostics = [diagnostic | diagnostics] + + module_info = Map.put(module_info, :diagnostics, diagnostics) + modules = Keyword.put(state.modules, module, module_info) + + %{state | modules: modules} + else + state + end + end) + end + def list_javascript_modules(pid) do Agent.get(pid, fn state -> state.js_modules diff --git a/lib/mix/tasks/compile.elixir_script.ex b/lib/mix/tasks/compile.elixir_script.ex index cdb05da9..a5ab2046 100644 --- a/lib/mix/tasks/compile.elixir_script.ex +++ b/lib/mix/tasks/compile.elixir_script.ex @@ -1,5 +1,5 @@ defmodule Mix.Tasks.Compile.ElixirScript do - use Mix.Task + use Mix.Task.Compiler alias ElixirScript.Manifest @recursive true @@ -35,7 +35,6 @@ defmodule Mix.Tasks.Compile.ElixirScript do The mix compiler will also compile any dependencies that have the elixirscript compiler in its mix compilers as well """ - @spec run(any()) :: :ok def run(_) do do_compile() @@ -60,6 +59,7 @@ defmodule Mix.Tasks.Compile.ElixirScript do def get_compiler_params() do elixirscript_config = get_elixirscript_config() input = Keyword.fetch!(elixirscript_config, :input) + opts = [ output: Keyword.get(elixirscript_config, :output) ] @@ -68,15 +68,19 @@ defmodule Mix.Tasks.Compile.ElixirScript do end defp get_elixirscript_config() do - config = Mix.Project.config - exjs_config = cond do - Keyword.has_key?(config, :elixir_script) -> - Keyword.get(config, :elixir_script, []) - Keyword.has_key?(config, :elixirscript) -> - Keyword.get(config, :elixirscript, []) - true -> - defaults() - end + config = Mix.Project.config() + + exjs_config = + cond do + Keyword.has_key?(config, :elixir_script) -> + Keyword.get(config, :elixir_script, []) + + Keyword.has_key?(config, :elixirscript) -> + Keyword.get(config, :elixirscript, []) + + true -> + defaults() + end Keyword.merge(defaults(), exjs_config) end @@ -86,5 +90,4 @@ defmodule Mix.Tasks.Compile.ElixirScript do output: "priv/elixir_script/build" ] end - end diff --git a/test/compiler_test.exs b/test/compiler_test.exs index 439975f5..b7b05dd3 100644 --- a/test/compiler_test.exs +++ b/test/compiler_test.exs @@ -3,17 +3,17 @@ defmodule ElixirScript.Compiler.Test do test "Can compile one entry module" do result = ElixirScript.Compiler.compile(Version) - assert result |> Map.to_list |> hd |> elem(1) |> Map.get(:js_code) |> is_binary + assert result |> Map.to_list() |> hd |> elem(1) |> Map.get(:js_code) |> is_binary end test "Can compile multiple entry modules" do result = ElixirScript.Compiler.compile([Atom, String, Agent]) - assert result |> Map.to_list |> hd |> elem(1) |> Map.get(:js_code) |> is_binary + assert result |> Map.to_list() |> hd |> elem(1) |> Map.get(:js_code) |> is_binary end test "Output" do result = ElixirScript.Compiler.compile(Atom, []) - assert result |> Map.to_list |> hd |> elem(1) |> Map.get(:js_code) =~ "export default" + assert result |> Map.to_list() |> hd |> elem(1) |> Map.get(:js_code) =~ "export default" end test "compile file" do @@ -22,7 +22,7 @@ defmodule ElixirScript.Compiler.Test do input_path = Path.join([File.cwd!(), "test", "beam_test.exs"]) - ElixirScript.Compiler.compile(input_path, [output: path]) + ElixirScript.Compiler.compile(input_path, output: path) assert File.exists?(path) assert String.contains?(File.read!(path), "export default") end @@ -33,7 +33,7 @@ defmodule ElixirScript.Compiler.Test do input_path = Path.join([File.cwd!(), "test", "*fi_test.exs"]) - ElixirScript.Compiler.compile(input_path, [output: path]) + ElixirScript.Compiler.compile(input_path, output: path) assert File.exists?(file) assert String.contains?(File.read!(file), "export default") end diff --git a/test/passes/translate/forms/receive_test.exs b/test/passes/translate/forms/receive_test.exs index f265962a..9f8496a7 100644 --- a/test/passes/translate/forms/receive_test.exs +++ b/test/passes/translate/forms/receive_test.exs @@ -3,16 +3,32 @@ defmodule ElixirScript.Translate.Forms.Receive.Test do alias ElixirScript.Translate.{Form, Helpers} alias ESTree.Tools.Builder, as: J - test "receive translation" do + setup_all do + {:ok, pid} = ElixirScript.State.start_link(%{}) + + state = %{ + pid: pid, + module: __MODULE__ + } + + [state: state] + end + + test "receive translation", %{state: state} do clause = {:->, [line: 644], [[], [{:__block__, [], [1]}]]} ast = {:receive, [line: 644], [[do: [clause], after: nil]]} - state = %{function: {:each, nil}, module: __MODULE__, anonymous_fn: false} + + state = + state + |> Map.put(:function, {:each, nil}) + |> Map.put(:anonymous_fn, false) {js_ast, _} = Form.compile(ast, state) - assert js_ast.callee == J.member_expression( - Helpers.special_forms(), - J.identifier("receive") - ) - end + assert js_ast.callee == + J.member_expression( + Helpers.special_forms(), + J.identifier("receive") + ) + end end From 9078aed8ba05ed65d0a6e27a6d564e85ebc44a33 Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Wed, 3 Jan 2018 15:58:59 -0600 Subject: [PATCH 826/860] Outputting diagnostic information from elixirscript compiler --- lib/elixir_script/beam.ex | 88 +++++++++++-------- lib/elixir_script/compile_error.ex | 2 +- lib/elixir_script/compiler.ex | 11 ++- lib/elixir_script/passes/find_used_modules.ex | 8 +- lib/mix/tasks/compile.elixir_script.ex | 41 +++++++-- 5 files changed, 93 insertions(+), 57 deletions(-) diff --git a/lib/elixir_script/beam.ex b/lib/elixir_script/beam.ex index 4473f221..0a727ef1 100644 --- a/lib/elixir_script/beam.ex +++ b/lib/elixir_script/beam.ex @@ -30,6 +30,7 @@ defmodule ElixirScript.Beam do case do_debug_info(Module.concat(ElixirScript, module)) do {:ok, info} -> {:ok, Map.put(info, :module, module)} + e -> e end @@ -49,28 +50,32 @@ defmodule ElixirScript.Beam do case :code.get_object_code(module) do {_, beam, beam_path} -> do_debug_info(beam, beam_path) + :error -> {:error, "Unknown module"} end end defp do_debug_info(beam, beam_path) do - with {:ok, {module, [debug_info: {:debug_info_v1, backend, data}]}} <- :beam_lib.chunks(beam, [:debug_info]), - {:ok, {^module, attribute_info}} = :beam_lib.chunks(beam, [:attributes]) do - - if Keyword.get(attribute_info[:attributes], :protocol) do - get_protocol_implementations(module, beam_path) - else - backend.debug_info(:elixir_v1, module, data, []) - |> process_debug_info(beam_path) - end + with {:ok, {module, [debug_info: {:debug_info_v1, backend, data}]}} <- + :beam_lib.chunks(beam, [:debug_info]), + {:ok, {^module, attribute_info}} = :beam_lib.chunks(beam, [:attributes]) do + if Keyword.get(attribute_info[:attributes], :protocol) do + get_protocol_implementations(module, beam_path) + else + backend.debug_info(:elixir_v1, module, data, []) + |> process_debug_info(beam_path) + end else :error -> {:error, "Unknown module"} + {:error, :beam_lib, {:unknown_chunk, "non_existing.beam", :debug_info}} -> {:error, "Unsupported version of Erlang"} - {:error, :beam_lib, {:missing_chunk, _ , _}} -> + + {:error, :beam_lib, {:missing_chunk, _, _}} -> {:error, "Debug info not available"} + {:error, :beam_lib, {:file_error, "non_existing.beam", :enoent}} -> {:error, "Debug info not available"} end @@ -82,12 +87,14 @@ defmodule ElixirScript.Beam do end defp process_debug_info({:ok, info}, beam_path) do - info = case File.stat(beam_path, time: :posix) do - {:ok, file_info} -> - Map.put(info, :last_modified, file_info.mtime) - _ -> - Map.put(info, :last_modified, nil) - end + info = + case File.stat(beam_path, time: :posix) do + {:ok, file_info} -> + Map.put(info, :last_modified, file_info.mtime) + + _ -> + Map.put(info, :last_modified, nil) + end info = Map.put(info, :beam_path, beam_path) @@ -101,36 +108,39 @@ defmodule ElixirScript.Beam do defp get_protocol_implementations(module, beam_path) do {:ok, protocol_module_info} = process_debug_info({:ok, %{}}, beam_path) - implementations = module - |> Protocol.extract_impls(:code.get_path()) - |> Enum.map(fn(x) -> Module.concat([module, x]) end) - |> Enum.map(fn(x) -> - case debug_info(x) do - {:ok, info} -> - {x, info} - _ -> - raise "Unable to compile protocol implementation #{inspect x}" - end - end) + implementations = + module + |> Protocol.extract_impls(:code.get_path()) + |> Enum.map(fn x -> Module.concat([module, x]) end) + |> Enum.map(fn x -> + case debug_info(x) do + {:ok, info} -> + {x, info} + + _ -> + raise ElixirScript.CompileError, + message: "Unable to compile protocol implementation #{inspect(x)}", + severity: :error + end + end) {:ok, module, protocol_module_info, implementations} end defp replace_definitions(original_definitions, replacement_definitions) do - Enum.map(original_definitions, fn - {{function, arity}, type, _, _} = ast -> - ex_ast = Enum.find(replacement_definitions, fn - {{ex_function, ex_arity}, ex_type, _, _} -> - ex_function == function and ex_arity == arity and ex_type == type + Enum.map(original_definitions, fn {{function, arity}, type, _, _} = ast -> + ex_ast = + Enum.find(replacement_definitions, fn {{ex_function, ex_arity}, ex_type, _, _} -> + ex_function == function and ex_arity == arity and ex_type == type end) - case ex_ast do - nil -> - ast - _ -> - ex_ast - end + case ex_ast do + nil -> + ast + + _ -> + ex_ast + end end) end - end diff --git a/lib/elixir_script/compile_error.ex b/lib/elixir_script/compile_error.ex index fea01237..d670552b 100644 --- a/lib/elixir_script/compile_error.ex +++ b/lib/elixir_script/compile_error.ex @@ -1,3 +1,3 @@ defmodule ElixirScript.CompileError do - defexception [:message] + defexception [:message, :severity] end diff --git a/lib/elixir_script/compiler.ex b/lib/elixir_script/compiler.ex index 61a95201..1b12d37b 100644 --- a/lib/elixir_script/compiler.ex +++ b/lib/elixir_script/compiler.ex @@ -121,6 +121,12 @@ defmodule ElixirScript.Compiler do Enum.reduce(modules, %{}, fn {module, info}, current_data -> + diagnostics = + Map.get(info, :diagnostics, []) + |> Enum.map(fn x -> + Map.put(x, :file, Map.get(info, :file)) + end) + info = %{ references: info.used_modules, last_modified: info.last_modified, @@ -128,7 +134,7 @@ defmodule ElixirScript.Compiler do source: Map.get(info, :file), js_path: Path.join(output_path, "#{module}.js"), js_code: Keyword.get(compiled_js, module), - diagnostics: Map.get(info, :diagnostics, []), + diagnostics: diagnostics, type: :module } @@ -148,8 +154,7 @@ defmodule ElixirScript.Compiler do references: [], last_modified: last_modified, beam_path: nil, - source: nil, - js_input_path: js_input_path, + source: js_input_path, js_path: js_output_path, js_code: nil, diagnostics: [], diff --git a/lib/elixir_script/passes/find_used_modules.ex b/lib/elixir_script/passes/find_used_modules.ex index c111c249..4befed2e 100644 --- a/lib/elixir_script/passes/find_used_modules.ex +++ b/lib/elixir_script/passes/find_used_modules.ex @@ -43,13 +43,9 @@ defmodule ElixirScript.FindUsedModules do }) {:error, error} -> - ModuleState.put_diagnostic(pid, module, %{ - severity: :error, - message: "An error occurred while compiling #{inspect(module)}: #{error}" - }) - raise ElixirScript.CompileError, - "An error occurred while compiling #{inspect(module)}: #{error}" + message: "An error occurred while compiling #{inspect(module)}: #{error}", + severity: :error end end diff --git a/lib/mix/tasks/compile.elixir_script.ex b/lib/mix/tasks/compile.elixir_script.ex index a5ab2046..36607e07 100644 --- a/lib/mix/tasks/compile.elixir_script.ex +++ b/lib/mix/tasks/compile.elixir_script.ex @@ -1,6 +1,7 @@ defmodule Mix.Tasks.Compile.ElixirScript do use Mix.Task.Compiler alias ElixirScript.Manifest + alias ElixirScript.Compiler @recursive true @manifest ".compile.elixir_script" @@ -35,17 +36,41 @@ defmodule Mix.Tasks.Compile.ElixirScript do The mix compiler will also compile any dependencies that have the elixirscript compiler in its mix compilers as well """ - @spec run(any()) :: :ok + @spec run([binary()]) :: + :ok | :noop | {:ok | :noop | :error, [Mix.Task.Compiler.Diagnostic.t()]} def run(_) do - do_compile() - :ok - end - - defp do_compile() do {input, opts} = get_compiler_params() - result = ElixirScript.Compiler.compile(input, opts) - Manifest.write_manifest(manifest(), result) + try do + result = Compiler.compile(input, opts) + Manifest.write_manifest(manifest(), result) + + result + |> Enum.map(fn {_module, info} -> + info.diagnositcs + end) + |> List.flatten() + |> Enum.map(fn x -> + %Mix.Task.Compiler.Diagnostic{ + compiler_name: "elixir_script", + file: x.file, + message: x.message, + position: x.position, + severity: x.severity + } + end) + rescue + x in [ElixirScript.CompileError] -> + [ + %Mix.Task.Compiler.Diagnostic{ + compiler_name: "elixir_script", + message: x.message, + severity: x.severity, + position: nil, + file: nil + } + ] + end end def clean do From adc39f82dc7f7fca3149ef94e99da07e69ae084c Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Wed, 3 Jan 2018 19:33:28 -0600 Subject: [PATCH 827/860] compiler can now clean up after itself --- lib/elixir_script/compiler.ex | 113 +++++++++++++++---------- lib/elixir_script/manifest.ex | 17 ++-- lib/elixir_script/passes/output.ex | 14 +-- lib/mix/tasks/compile.elixir_script.ex | 62 ++++++++------ 4 files changed, 123 insertions(+), 83 deletions(-) diff --git a/lib/elixir_script/compiler.ex b/lib/elixir_script/compiler.ex index 1b12d37b..35f7b8ec 100644 --- a/lib/elixir_script/compiler.ex +++ b/lib/elixir_script/compiler.ex @@ -113,55 +113,74 @@ defmodule ElixirScript.Compiler do defp transform_output(modules, compiled_js, opts) do output_path = - if opts.output == nil or opts.output == :stdout do - "" - else - Path.dirname(opts.output) + cond do + opts.output == nil or opts.output == :stdout -> + "" + + File.dir?(opts.output) -> + opts.output + + true -> + Path.dirname(opts.output) end - Enum.reduce(modules, %{}, fn - {module, info}, current_data -> - diagnostics = - Map.get(info, :diagnostics, []) - |> Enum.map(fn x -> - Map.put(x, :file, Map.get(info, :file)) - end) - - info = %{ - references: info.used_modules, - last_modified: info.last_modified, - beam_path: Map.get(info, :beam_path), - source: Map.get(info, :file), - js_path: Path.join(output_path, "#{module}.js"), - js_code: Keyword.get(compiled_js, module), - diagnostics: diagnostics, - type: :module - } - - Map.put(current_data, module, info) - - {module, js_input_path, js_output_path}, current_data -> - last_modified = - case File.stat(js_input_path, time: :posix) do - {:ok, file_info} -> - file_info.mtime - - _ -> - nil - end - - info = %{ - references: [], - last_modified: last_modified, - beam_path: nil, - source: js_input_path, - js_path: js_output_path, - js_code: nil, - diagnostics: [], - type: :ffi - } - - Map.put(current_data, module, info) + data = %{ + ElixirScript.Core => %{ + references: [], + last_modified: nil, + beam_path: nil, + source: nil, + js_path: Path.join(output_path, "ElixirScript.Core.js"), + diagnostics: [], + js_code: nil, + type: :ffi + } + } + + Enum.reduce(modules, data, fn {module, info}, current_data -> + diagnostics = + Map.get(info, :diagnostics, []) + |> Enum.map(fn x -> + Map.put(x, :file, Map.get(info, :file)) + end) + + info = %{ + references: Map.get(info, :used_modules, []), + last_modified: Map.get(info, :last_modified, nil), + beam_path: Map.get(info, :beam_path), + source: Map.get(info, :file), + js_path: Path.join(output_path, "#{module}.js"), + diagnostics: diagnostics + } + + info = + case Keyword.get(compiled_js, module) do + [js_input_path, js_output_path] -> + last_modified = + case File.stat(js_input_path, time: :posix) do + {:ok, file_info} -> + file_info.mtime + + _ -> + nil + end + + info + |> Map.put(:last_modified, last_modified) + |> Map.put(:beam_path, nil) + |> Map.put(:source, js_input_path) + |> Map.put(:js_path, js_output_path) + |> Map.put(:js_code, nil) + |> Map.put(:type, :ffi) + + js_code -> + info + |> Map.put(:js_path, Path.join(output_path, "#{module}.js")) + |> Map.put(:js_code, js_code) + |> Map.put(:type, :module) + end + + Map.put(current_data, module, info) end) end end diff --git a/lib/elixir_script/manifest.ex b/lib/elixir_script/manifest.ex index 5ed1915f..a7974cb1 100644 --- a/lib/elixir_script/manifest.ex +++ b/lib/elixir_script/manifest.ex @@ -2,15 +2,22 @@ defmodule ElixirScript.Manifest do @moduledoc false @spec read_manifest(binary) :: nil - def read_manifest(_manifest) do - + def read_manifest(manifest_path) do + if File.exists?(manifest_path) do + manifest_path + |> File.read!() + |> :erlang.binary_to_term() + else + %{} + end end @spec write_manifest(binary, map) :: :ok def write_manifest(manifest_path, modules) do - data = Enum.reduce(modules, %{}, fn {module, info}, current_data -> - Map.put(current_data, module, Map.drop(info, [:js_code])) - end) + data = + Enum.reduce(modules, %{}, fn {module, info}, current_data -> + Map.put(current_data, module, Map.drop(info, [:js_code])) + end) data = :erlang.term_to_binary(data, [:compressed]) File.mkdir_p!(Path.dirname(manifest_path)) diff --git a/lib/elixir_script/passes/output.ex b/lib/elixir_script/passes/output.ex index 961b3d3b..89a6fdfd 100644 --- a/lib/elixir_script/passes/output.ex +++ b/lib/elixir_script/passes/output.ex @@ -92,10 +92,12 @@ defmodule ElixirScript.Output do defp output(code, module, path, js_modules) do output_dir = - if File.dir?(path) do - path - else - Path.dirname(path) + case Path.extname(path) do + "" -> + path + + _ -> + Path.dirname(path) end file_name = Path.join(output_dir, "Elixir.#{inspect(module)}.js") @@ -158,9 +160,9 @@ defmodule ElixirScript.Output do end File.cp(js_input_path, js_output_path) - acc ++ [{module, js_input_path, js_output_path}] + acc ++ [{module, [js_input_path, js_output_path]}] else - [] + acc end end) end diff --git a/lib/mix/tasks/compile.elixir_script.ex b/lib/mix/tasks/compile.elixir_script.ex index 36607e07..b529251e 100644 --- a/lib/mix/tasks/compile.elixir_script.ex +++ b/lib/mix/tasks/compile.elixir_script.ex @@ -41,39 +41,51 @@ defmodule Mix.Tasks.Compile.ElixirScript do def run(_) do {input, opts} = get_compiler_params() - try do - result = Compiler.compile(input, opts) - Manifest.write_manifest(manifest(), result) - - result - |> Enum.map(fn {_module, info} -> - info.diagnositcs - end) - |> List.flatten() - |> Enum.map(fn x -> - %Mix.Task.Compiler.Diagnostic{ - compiler_name: "elixir_script", - file: x.file, - message: x.message, - position: x.position, - severity: x.severity - } - end) - rescue - x in [ElixirScript.CompileError] -> - [ + diagnostics = + try do + result = Compiler.compile(input, opts) + Manifest.write_manifest(manifest(), result) + + result + |> Enum.map(fn {_module, info} -> + Map.get(info, :diagnostics, []) + end) + |> List.flatten() + |> Enum.map(fn x -> %Mix.Task.Compiler.Diagnostic{ compiler_name: "elixir_script", + file: x.file, message: x.message, - severity: x.severity, - position: nil, - file: nil + position: x.position, + severity: x.severity } - ] + end) + rescue + x in [ElixirScript.CompileError] -> + [ + %Mix.Task.Compiler.Diagnostic{ + compiler_name: "elixir_script", + message: x.message, + severity: x.severity, + position: nil, + file: nil + } + ] + end + + case diagnostics do + [] -> :ok + x -> x end end def clean do + manifest() + |> Manifest.read_manifest() + |> Enum.each(fn {_module, info} -> + File.rm(info.js_path) + end) + :ok end From cb976fa88298a19ccb5054d7be3637fba8999f24 Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Wed, 17 Jan 2018 19:29:44 -0600 Subject: [PATCH 828/860] Update travis --- .tool-versions | 2 +- .travis.yml | 12 +- lib/elixir_script/passes/translate/form.ex | 14 +- mix.exs | 7 +- test/passes/translate/form_test.exs | 153 +++++++++++++-------- 5 files changed, 111 insertions(+), 77 deletions(-) diff --git a/.tool-versions b/.tool-versions index a9580d64..e5a7616f 100644 --- a/.tool-versions +++ b/.tool-versions @@ -1,3 +1,3 @@ erlang 20.1 -elixir 1.6.0-rc.0-otp-20 +elixir 1.6.0-otp-20 nodejs 8.9.1 diff --git a/.travis.yml b/.travis.yml index 78d59677..aa389e22 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,19 +1,17 @@ sudo: false -language: erlang +language: elixir +elixir: + - 1.6.0-otp-20 otp_release: - - 20.0 + - 20.2 env: - TRAVIS_NODE_VERSION="8" install: - rm -rf ~/.nvm && git clone https://github.com/creationix/nvm.git ~/.nvm && (cd ~/.nvm && git checkout `git describe --abbrev=0 --tags`) && source ~/.nvm/nvm.sh && nvm install $TRAVIS_NODE_VERSION - npm install -g yarn - yarn -before_script: - - wget https://repo.hex.pm/builds/elixir/v1.6.0-rc.0-otp-20.zip - - unzip -d elixir v1.6.0-rc.0-otp-20.zip - - export PATH=$(pwd)/elixir/bin:${PATH} - - mix local.rebar --force - mix local.hex --force + - mix local.rebar --force - mix deps.get script: - make diff --git a/lib/elixir_script/passes/translate/form.ex b/lib/elixir_script/passes/translate/form.ex index c14a4361..129d1723 100644 --- a/lib/elixir_script/passes/translate/form.ex +++ b/lib/elixir_script/passes/translate/form.ex @@ -59,10 +59,16 @@ defmodule ElixirScript.Translate.Form do def compile(form, state) when is_atom(form) do ast = - if ElixirScript.Translate.Module.is_elixir_module(form) do - Remote.process_module_name(form, state) - else - Helpers.symbol(form) + cond do + ElixirScript.Translate.Module.is_elixir_module(form) and + ModuleState.get_module(state.pid, form) != nil -> + Remote.process_module_name(form, state) + + ElixirScript.Translate.Module.is_elixir_module(form) -> + J.object_expression([]) + + true -> + Helpers.symbol(form) end {ast, state} diff --git a/mix.exs b/mix.exs index 11c588f1..befc1d9c 100644 --- a/mix.exs +++ b/mix.exs @@ -5,8 +5,8 @@ defmodule ElixirScript.Mixfile do [ app: :elixir_script, version: "0.32.0-dev", - elixir: "~> 1.6-rc", - elixirc_paths: elixirc_paths(Mix.env), + elixir: "~> 1.6", + elixirc_paths: elixirc_paths(Mix.env()), deps: deps(), description: description(), package: package(), @@ -37,7 +37,7 @@ defmodule ElixirScript.Mixfile do end defp elixirc_paths(:test), do: ["lib", "test/support"] - defp elixirc_paths(_), do: ["lib"] + defp elixirc_paths(_), do: ["lib"] defp description do """ @@ -56,5 +56,4 @@ defmodule ElixirScript.Mixfile do build_tools: ["mix"] ] end - end diff --git a/test/passes/translate/form_test.exs b/test/passes/translate/form_test.exs index 6b8bae94..7626edee 100644 --- a/test/passes/translate/form_test.exs +++ b/test/passes/translate/form_test.exs @@ -5,7 +5,6 @@ defmodule ElixirScript.Translate.Forms.Test do alias ESTree.Tools.Builder, as: J use ExUnitProperties - setup_all do {:ok, pid} = ElixirScript.State.start_link(%{}) @@ -17,13 +16,15 @@ defmodule ElixirScript.Translate.Forms.Test do [state: state] end - property "integers, floats, binaries, and booleans translates to a literal JavaScript AST node", %{state: state} do - check all value <- StreamData.one_of([ - StreamData.integer(), - StreamData.boolean(), - StreamData.binary(), - StreamData.uniform_float() - ]) do + property "integers, floats, binaries, and booleans translates to a literal JavaScript AST node", + %{state: state} do + check all value <- + StreamData.one_of([ + StreamData.integer(), + StreamData.boolean(), + StreamData.binary(), + StreamData.uniform_float() + ]) do {js_ast, _} = Form.compile(value, state) assert js_ast == J.literal(value) end @@ -32,29 +33,33 @@ defmodule ElixirScript.Translate.Forms.Test do property "atom translates to Symbol.for call", %{state: state} do check all atom <- StreamData.unquoted_atom() do {js_ast, _} = Form.compile(atom, state) - assert js_ast == J.call_expression( - J.member_expression( - J.identifier("Symbol"), - J.identifier("for") - ), - [J.literal(atom)] - ) + + assert js_ast == + J.call_expression( + J.member_expression( + J.identifier("Symbol"), + J.identifier("for") + ), + [J.literal(atom)] + ) end end property "tuple translates to new Tuple object", %{state: state} do check all tuple <- StreamData.tuple({StreamData.integer(), StreamData.binary()}) do {js_ast, _} = Form.compile(tuple, state) - assert js_ast == J.new_expression( - J.member_expression( - J.member_expression( - J.identifier("ElixirScript"), - J.identifier("Core") - ), - J.identifier("Tuple") - ), - [J.literal(elem(tuple, 0)), J.literal(elem(tuple, 1))] - ) + + assert js_ast == + J.new_expression( + J.member_expression( + J.member_expression( + J.identifier("ElixirScript"), + J.identifier("Core") + ), + J.identifier("Tuple") + ), + [J.literal(elem(tuple, 0)), J.literal(elem(tuple, 1))] + ) end end @@ -72,16 +77,16 @@ defmodule ElixirScript.Translate.Forms.Test do end property "local function call translates to local JavaScript function call", %{state: state} do - check all func <- StreamData.filter(StreamData.unquoted_atom(), fn(x) -> not(x in [:fn]) end), + check all func <- StreamData.filter(StreamData.unquoted_atom(), fn x -> x not in [:fn] end), params <- StreamData.list_of(StreamData.binary()) do - ast = {func, [], params} - str_func = if func in ElixirScript.Translate.Identifier.js_reserved_words() do - "__#{to_string(func)}__" - else - to_string(func) - end + str_func = + if func in ElixirScript.Translate.Identifier.js_reserved_words() do + "__#{to_string(func)}__" + else + to_string(func) + end {js_ast, _} = Form.compile(ast, state) assert js_ast.type == "CallExpression" @@ -99,15 +104,15 @@ defmodule ElixirScript.Translate.Forms.Test do property "super function call translates to local JavaScript function call" do check all func <- StreamData.unquoted_atom(), params <- StreamData.list_of(StreamData.binary()) do - ast = {:super, [], [{:def, func}] ++ params} state = %{function: {func, nil}, vars: %{}} - str_func = if func in ElixirScript.Translate.Identifier.js_reserved_words() do - "__#{to_string(func)}__" - else - to_string(func) - end + str_func = + if func in ElixirScript.Translate.Identifier.js_reserved_words() do + "__#{to_string(func)}__" + else + to_string(func) + end {js_ast, _} = Form.compile(ast, state) assert js_ast.type == "CallExpression" @@ -125,10 +130,24 @@ defmodule ElixirScript.Translate.Forms.Test do test "module", %{state: state} do ast = IO + ElixirScript.State.put_module(state.pid, IO, %{}) + {js_ast, _} = Form.compile(ast, state) assert js_ast == %ESTree.Identifier{loc: nil, name: "$IO$", type: "Identifier"} end + test "unknown module", %{state: state} do + ast = Enum + + {js_ast, _} = Form.compile(ast, state) + + assert js_ast == %ESTree.ObjectExpression{ + loc: nil, + properties: [], + type: "ObjectExpression" + } + end + test "function returning an array" do ast = {:fn, [], [{:foo, [], [], [1, 2, 3]}]} state = %{function: {:something, nil}} @@ -137,37 +156,48 @@ defmodule ElixirScript.Translate.Forms.Test do return_statement = Enum.at(Enum.at(hd(js_ast.body.body).body.body, 1).consequent.body, 1) - assert return_statement.argument == J.array_expression([ - J.literal(1), - J.literal(2), - J.literal(3) - ]) + assert return_statement.argument == + J.array_expression([ + J.literal(1), + J.literal(2), + J.literal(3) + ]) end test "calling field on field" do - ast = {{:., [line: 16], - [{{:., [line: 16], [{:map, [line: 16], nil}, :token_count]}, [line: 16], - []}, :toLocaleString]}, [line: 16], []} + ast = + { + {:., [line: 16], [ + {{:., [line: 16], [{:map, [line: 16], nil}, :token_count]}, [line: 16], []}, + :toLocaleString + ]}, + [line: 16], + [] + } state = %{function: {:something, nil}, vars: %{}} {js_ast, _} = Form.compile(ast, state) - assert js_ast == Helpers.call( - ElixirScript.Translate.Forms.JS.call_property(), - [ - Helpers.call( - ElixirScript.Translate.Forms.JS.call_property(), - [J.identifier("map"), J.literal("token_count")] - ), - J.literal("toLocaleString") - ] - ) + assert js_ast == + Helpers.call(ElixirScript.Translate.Forms.JS.call_property(), [ + Helpers.call(ElixirScript.Translate.Forms.JS.call_property(), [ + J.identifier("map"), + J.literal("token_count") + ]), + J.literal("toLocaleString") + ]) end test "make sure counter used in guard", %{state: state} do - state = Map.merge(state, %{anonymous_fn: false, function: {:filter_names_in_guards, nil}, in_guard: true, - module: Integration, vars: %{"has__qmark__" => 0}}) + state = + Map.merge(state, %{ + anonymous_fn: false, + function: {:filter_names_in_guards, nil}, + in_guard: true, + module: Integration, + vars: %{"has__qmark__" => 0} + }) ast = {{:., [], [:erlang, :==]}, [line: 29], [{:has?, [line: 29], nil}, 5]} @@ -177,9 +207,10 @@ defmodule ElixirScript.Translate.Forms.Test do test "multi bind", %{state: state} do ast = - {:=, [line: 35], - [[{:|, [line: 35], [{:a, [line: 35], nil}, {:_, [line: 35], nil}]}], - {:=, [line: 35], [{:b, [line: 35], nil}, [1, 2, 3, 4, 5]]}]} + {:=, [line: 35], [ + [{:|, [line: 35], [{:a, [line: 35], nil}, {:_, [line: 35], nil}]}], + {:=, [line: 35], [{:b, [line: 35], nil}, [1, 2, 3, 4, 5]]} + ]} {js_ast, _} = Form.compile(ast, state) From a3d1a76096dd52e10ee4e8838bd6f143496f48cf Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Wed, 17 Jan 2018 19:33:20 -0600 Subject: [PATCH 829/860] Update elixir version in travis config --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index aa389e22..5dbed2d0 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,7 +1,7 @@ sudo: false language: elixir elixir: - - 1.6.0-otp-20 + - 1.6.0 otp_release: - 20.2 env: From eaf5b2a60bbf859b8401a0d6efe4a3c8de671c3d Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Wed, 17 Jan 2018 20:05:44 -0600 Subject: [PATCH 830/860] Some more bug fixes. Have to figure out module resolution issues still --- lib/elixir_script/passes/find_used_modules.ex | 65 +++++++++++++------ 1 file changed, 46 insertions(+), 19 deletions(-) diff --git a/lib/elixir_script/passes/find_used_modules.ex b/lib/elixir_script/passes/find_used_modules.ex index 4befed2e..0bd09fdc 100644 --- a/lib/elixir_script/passes/find_used_modules.ex +++ b/lib/elixir_script/passes/find_used_modules.ex @@ -15,16 +15,7 @@ defmodule ElixirScript.FindUsedModules do end) end - defp do_execute(module, pid) do - result = - case ModuleState.get_in_memory_module(pid, module) do - nil -> - ElixirScript.Beam.debug_info(module) - - beam -> - ElixirScript.Beam.debug_info(beam) - end - + defp do_execute(module, result, pid) do case result do {:ok, info} -> walk_module(module, info, pid) @@ -49,6 +40,21 @@ defmodule ElixirScript.FindUsedModules do end end + defp do_execute(module, pid) do + result = get_debug_info(module, pid) + do_execute(module, result, pid) + end + + defp get_debug_info(module, pid) do + case ModuleState.get_in_memory_module(pid, module) do + nil -> + ElixirScript.Beam.debug_info(module) + + beam -> + ElixirScript.Beam.debug_info(beam) + end + end + defp walk_module( module, %{attributes: [__foreign_info__: %{path: path, name: name, global: global}]} = info, @@ -159,10 +165,17 @@ defmodule ElixirScript.FindUsedModules do when is_atom(form) and form not in [BitString, Function, PID, Port, Reference, Any, Elixir] do if ElixirScript.Translate.Module.is_elixir_module(form) and !ElixirScript.Translate.Module.is_js_module(form, state) do - ModuleState.put_used_module(state.pid, state.module, form) - if ModuleState.get_module(state.pid, form) == nil do - do_execute(form, state.pid) + case get_debug_info(form, state.pid) do + {:ok, _} = result -> + ModuleState.put_used_module(state.pid, state.module, form) + do_execute(form, result, state.pid) + + result -> + do_execute(form, result, state.pid) + end + else + ModuleState.put_used_module(state.pid, state.module, form) end end end @@ -191,10 +204,17 @@ defmodule ElixirScript.FindUsedModules do defp walk({:%, _, [module, params]}, state) do if ElixirScript.Translate.Module.is_elixir_module(module) and !ElixirScript.Translate.Module.is_js_module(module, state) do - ModuleState.put_used_module(state.pid, state.module, module) - if ModuleState.get_module(state.pid, module) == nil do - do_execute(module, state.pid) + case get_debug_info(module, state.pid) do + {:ok, _} = result -> + ModuleState.put_used_module(state.pid, state.module, module) + do_execute(module, result, state.pid) + + result -> + do_execute(module, result, state.pid) + end + else + ModuleState.put_used_module(state.pid, state.module, module) end end @@ -331,10 +351,17 @@ defmodule ElixirScript.FindUsedModules do defp walk({:., _, [module, function]}, state) do if ElixirScript.Translate.Module.is_elixir_module(module) do - ModuleState.put_used_module(state.pid, state.module, module) - if ModuleState.get_module(state.pid, module) == nil do - do_execute(module, state.pid) + case get_debug_info(module, state.pid) do + {:ok, _} = result -> + ModuleState.put_used_module(state.pid, state.module, module) + do_execute(module, result, state.pid) + + result -> + do_execute(module, result, state.pid) + end + else + ModuleState.put_used_module(state.pid, state.module, module) end else walk(module, state) From e2348b2ae48dbc16060fc09ace279d79cc443677 Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Sat, 20 Jan 2018 10:10:38 -0600 Subject: [PATCH 831/860] Fix used module reference bugs --- lib/elixir_script/passes/find_used_modules.ex | 4 +- lib/elixir_script/passes/output.ex | 2 +- .../passes/translate/forms/remote.ex | 48 ++++++++++++------- .../passes/translate/identifier.ex | 10 ++-- lib/elixir_script/state.ex | 3 +- 5 files changed, 41 insertions(+), 26 deletions(-) diff --git a/lib/elixir_script/passes/find_used_modules.ex b/lib/elixir_script/passes/find_used_modules.ex index 0bd09fdc..e294c7c1 100644 --- a/lib/elixir_script/passes/find_used_modules.ex +++ b/lib/elixir_script/passes/find_used_modules.ex @@ -133,7 +133,9 @@ defmodule ElixirScript.FindUsedModules do Enum.each(clauses, &walk(&1, state)) end - defp walk({_, _args, _guards, body}, state) do + defp walk({_, args, guards, body}, state) do + walk(args, state) + walk(guards, state) walk_block(body, state) end diff --git a/lib/elixir_script/passes/output.ex b/lib/elixir_script/passes/output.ex index 89a6fdfd..2953ae0f 100644 --- a/lib/elixir_script/passes/output.ex +++ b/lib/elixir_script/passes/output.ex @@ -33,7 +33,7 @@ defmodule ElixirScript.Output do defp filter_used_modules(used_modules, pid) do used_modules |> Enum.filter(fn module -> - ModuleState.is_global_module(pid, module) == false + module in ModuleState.list_javascript_modules(pid) == false end) end diff --git a/lib/elixir_script/passes/translate/forms/remote.ex b/lib/elixir_script/passes/translate/forms/remote.ex index 97c3decd..6e945a49 100644 --- a/lib/elixir_script/passes/translate/forms/remote.ex +++ b/lib/elixir_script/passes/translate/forms/remote.ex @@ -33,7 +33,7 @@ defmodule ElixirScript.Translate.Forms.Remote do :orddict, :filelib, :net_adm, - :net_kernel, + :net_kernel ] @doc """ @@ -46,31 +46,32 @@ defmodule ElixirScript.Translate.Forms.Remote do def compile({:., _, [:erlang, :++]}, state) do ast = erlang_compat_function("erlang", "list_concatenation") - { ast, state } + {ast, state} end def compile({:., _, [:erlang, :--]}, state) do ast = erlang_compat_function("erlang", "list_substraction") - { ast, state } + {ast, state} end def compile({:., _, [:erlang, :"=<"]}, state) do ast = erlang_compat_function("erlang", "lessThanEqualTo") - { ast, state } + {ast, state} end def compile({:., _, [:erlang, :+]}, state) do ast = erlang_compat_function("erlang", "add") - { ast, state } + {ast, state} end def compile({:., _, [module, function]}, state) when module in @erlang_modules do - ast = J.member_expression( - Helpers.core_module(module), - J.identifier(function) - ) + ast = + J.member_expression( + Helpers.core_module(module), + J.identifier(function) + ) - { ast, state } + {ast, state} end def compile({:., _, [function_name]}, state) do @@ -80,30 +81,39 @@ defmodule ElixirScript.Translate.Forms.Remote do def compile({:., _, [module, function]}, state) do function_name = ElixirScript.Translate.Identifier.make_function_name(function) - ast = J.member_expression( - process_module_name(module, state), - function_name - ) + ast = + J.member_expression( + process_module_name(module, state), + function_name + ) {ast, state} end def process_module_name(module, state) when is_atom(module) do cond do + ElixirScript.Translate.Module.is_js_module(module, state) and + ModuleState.is_global_module(state.pid, module) -> + ElixirScript.Translate.Identifier.make_alias(Module.split(module) |> Enum.reverse()) + ElixirScript.Translate.Module.is_js_module(module, state) -> process_js_module_name(module, state) + module === Elixir -> module |> ElixirScript.Output.module_to_name() - |> J.identifier + |> J.identifier() + module === :ElixirScript -> module |> ElixirScript.Output.module_to_name() - |> J.identifier + |> J.identifier() + ElixirScript.Translate.Module.is_elixir_module(module) -> module |> ElixirScript.Output.module_to_name() - |> J.identifier + |> J.identifier() + true -> ElixirScript.Translate.Identifier.make_identifier(module) end @@ -117,12 +127,14 @@ defmodule ElixirScript.Translate.Forms.Remote do case ModuleState.get_js_module_name(state.pid, module) do name when is_binary(name) -> J.identifier(name) + name when is_atom(name) -> case to_string(name) do "Elixir." <> _ -> module |> ElixirScript.Output.module_to_name() - |> J.identifier + |> J.identifier() + x -> J.identifier(x) end diff --git a/lib/elixir_script/passes/translate/identifier.ex b/lib/elixir_script/passes/translate/identifier.ex index 092bd093..a04f35b8 100644 --- a/lib/elixir_script/passes/translate/identifier.ex +++ b/lib/elixir_script/passes/translate/identifier.ex @@ -38,7 +38,7 @@ defmodule ElixirScript.Translate.Identifier do def make_identifier(ast) do ast |> filter_name - |> J.identifier + |> J.identifier() end def filter_name(reserved_word) when reserved_word in @js_reserved_words do @@ -57,11 +57,11 @@ defmodule ElixirScript.Translate.Identifier do end end - defp make_alias([x]) do + def make_alias([x]) do make_identifier(x) end - defp make_alias([h|t]) do + def make_alias([h | t]) do J.member_expression(make_alias(t), make_identifier(h)) end @@ -69,10 +69,11 @@ defmodule ElixirScript.Translate.Identifier do case module_name do m when is_list(m) -> m + m when is_atom(m) -> Module.split(m) end - |> Enum.reverse + |> Enum.reverse() |> make_alias end @@ -84,5 +85,4 @@ defmodule ElixirScript.Translate.Identifier do def js_reserved_words() do @js_reserved_words end - end diff --git a/lib/elixir_script/state.ex b/lib/elixir_script/state.ex index 3a45f745..79bd6eda 100644 --- a/lib/elixir_script/state.ex +++ b/lib/elixir_script/state.ex @@ -115,7 +115,8 @@ defmodule ElixirScript.State do def is_global_module(pid, module) do Agent.get(pid, fn state -> - result = Enum.find(state.js_modules, fn {mod, _, _} -> mod == module end) + result = + Enum.find(state.js_modules, fn {mod, _name, path} -> mod == module and path == nil end) if result == nil, do: false, else: true end) From 288f19b67f33f62745f146200f8229996c12b5a5 Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Sun, 28 Jan 2018 17:52:24 -0600 Subject: [PATCH 832/860] Update changelog --- CHANGELOG.md | 25 +++++++++++++++++++++---- 1 file changed, 21 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 9c619292..5fb3edde 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,12 +5,29 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](http://keepachangelog.com/) and this project adheres to [Semantic Versioning](http://semver.org/). -## Unreleased +## [0.32.0] - Unreleased -## Changed +### Added + +* `ElixirScript.Test` for testing ElixirScript modules in JavaScript. ElixirScript.Test is for unit testing modules that interact with JavaScript in some way. For modules that are can be used in both Elixir and ElixirScript, ExUnit is still preferred. Tests that use ElixirScript.Test must be placed in a `test_elixir_script` folder in the root of your project. These tests are run using node.js. The API for ElixirScript.Test is meant to be as close to ExUnit as possible. + +### Changed + +* ElixirScript now requires Elixir 1.6. This is so that ElixirScript can use the new `Mix.Task.Compiler` behaviour. +* `mix clean` will now correctly clean up ElixirScript output. +* Compiler will now output a JavaScript file per Elixir module. +* Modules with a start function **must** be started directly. -* Compiler now returns a file per module instead of just one file -* Requires Elixir 1.6 + ```elixir + # Before ElixirScript 0.32.0: + import Elixir from './elixirscript.build.js' + Elixir.start(Elixir.Main, [1, 2, 3]) + + + # ElixirScript 0.32.0 and later: + import Main from './Elixir.Main.js' + Main.start(Symbol.for('normal'), [1, 2, 3]) + ``` ## [0.31.1] - 2017-09-27 From 3e04fcef4e396a9784be1741527a06b59659511c Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Sat, 10 Feb 2018 10:33:39 -0600 Subject: [PATCH 833/860] Prep for release --- CHANGELOG.md | 21 +- mix.exs | 2 +- priv/testrunner/vendor.build.js | 406 +------------------------------- 3 files changed, 13 insertions(+), 416 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 5fb3edde..8b589479 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,7 +5,7 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](http://keepachangelog.com/) and this project adheres to [Semantic Versioning](http://semver.org/). -## [0.32.0] - Unreleased +## [0.32.0] - 2018-02-10 ### Added @@ -23,7 +23,6 @@ and this project adheres to [Semantic Versioning](http://semver.org/). import Elixir from './elixirscript.build.js' Elixir.start(Elixir.Main, [1, 2, 3]) - # ElixirScript 0.32.0 and later: import Main from './Elixir.Main.js' Main.start(Symbol.for('normal'), [1, 2, 3]) @@ -45,15 +44,15 @@ and this project adheres to [Semantic Versioning](http://semver.org/). * [Fully implement `__info__` on modules](https://github.com/elixirscript/elixirscript/pull/378) * [Concurrent Compilation](https://github.com/elixirscript/elixirscript/issues/376) * [The following erlang functions have been implemented](https://github.com/elixirscript/elixirscript/issues/306): - * :erlang.nodes/0 - * :erlang.nodes/1 - * :math.log2/1 - * :binary.copy/1 - * :binary.copy/2 - * :binary.part/2 - * :binary.part/3 - * :binary.replace/3 - * :binary.replace/4 (some options still missing) +* :erlang.nodes/0 +* :erlang.nodes/1 +* :math.log2/1 +* :binary.copy/1 +* :binary.copy/2 +* :binary.part/2 +* :binary.part/3 +* :binary.replace/3 +* :binary.replace/4 (some options still missing) ### Fixed diff --git a/mix.exs b/mix.exs index befc1d9c..c4841a2c 100644 --- a/mix.exs +++ b/mix.exs @@ -4,7 +4,7 @@ defmodule ElixirScript.Mixfile do def project do [ app: :elixir_script, - version: "0.32.0-dev", + version: "0.32.0", elixir: "~> 1.6", elixirc_paths: elixirc_paths(Mix.env()), deps: deps(), diff --git a/priv/testrunner/vendor.build.js b/priv/testrunner/vendor.build.js index 6e808208..9d49e34d 100644 --- a/priv/testrunner/vendor.build.js +++ b/priv/testrunner/vendor.build.js @@ -1,404 +1,2 @@ -class Tuple { - constructor(...args) { - this.values = Object.freeze(args); - this.length = this.values.length; - } - - get(index) { - return this.values[index]; - } - - count() { - return this.values.length; - } - - [Symbol.iterator]() { - return this.values[Symbol.iterator](); - } - - toString() { - let i, - s = ''; - for (i = 0; i < this.values.length; i++) { - if (s !== '') { - s += ', '; - } - - const stringToAppend = this.values[i] ? this.values[i].toString() : ''; - - s += stringToAppend; - } - - return '{' + s + '}'; - } - - put_elem(index, elem) { - if (index === this.length) { - let new_values = this.values.concat([elem]); - return new Tuple(...new_values); - } - - let new_values = this.values.concat([]); - new_values.splice(index, 0, elem); - return new Tuple(...new_values); - } - - remove_elem(index) { - let new_values = this.values.concat([]); - new_values.splice(index, 1); - return new Tuple(...new_values); - } -} - -let process_counter = -1; - -class PID { - constructor() { - process_counter = process_counter + 1; - this.id = process_counter; - } - - toString() { - return 'PID#<0.' + this.id + '.0>'; - } -} - -let ref_counter = -1; - -class Reference { - constructor() { - ref_counter = ref_counter + 1; - this.id = ref_counter; - this.ref = Symbol(); - } - - toString() { - return 'Ref#<0.0.0.' + this.id + '>'; - } -} - -class BitString { - constructor(...args) { - this.value = Object.freeze(this.process(args)); - this.length = this.value.length; - this.bit_size = this.length * 8; - this.byte_size = this.length; - } - - get(index) { - return this.value[index]; - } - - count() { - return this.value.length; - } - - slice(start, end = null) { - let s = this.value.slice(start, end); - let ms = s.map(elem => BitString.integer(elem)); - return new BitString(...ms); - } - - [Symbol.iterator]() { - return this.value[Symbol.iterator](); - } - - toString() { - var i, - s = ''; - for (i = 0; i < this.count(); i++) { - if (s !== '') { - s += ', '; - } - s += this.get(i).toString(); - } - - return '<<' + s + '>>'; - } - - process(bitStringParts) { - let processed_values = []; - - var i; - for (i = 0; i < bitStringParts.length; i++) { - let processed_value = this['process_' + bitStringParts[i].type](bitStringParts[i]); - - for (let attr of bitStringParts[i].attributes) { - processed_value = this['process_' + attr](processed_value); - } - - processed_values = processed_values.concat(processed_value); - } - - return processed_values; - } - - process_integer(value) { - return value.value; - } - - process_float(value) { - if (value.size === 64) { - return BitString.float64ToBytes(value.value); - } else if (value.size === 32) { - return BitString.float32ToBytes(value.value); - } - - throw new Error('Invalid size for float'); - } - - process_bitstring(value) { - return value.value.value; - } - - process_binary(value) { - return BitString.toUTF8Array(value.value); - } - - process_utf8(value) { - return BitString.toUTF8Array(value.value); - } - - process_utf16(value) { - return BitString.toUTF16Array(value.value); - } - - process_utf32(value) { - return BitString.toUTF32Array(value.value); - } - - process_signed(value) { - return new Uint8Array([value])[0]; - } - - process_unsigned(value) { - return value; - } - - process_native(value) { - return value; - } - - process_big(value) { - return value; - } - - process_little(value) { - return value.reverse(); - } - - process_size(value) { - return value; - } - - process_unit(value) { - return value; - } - - static integer(value) { - return BitString.wrap(value, { type: 'integer', unit: 1, size: 8 }); - } - - static float(value) { - return BitString.wrap(value, { type: 'float', unit: 1, size: 64 }); - } - - static bitstring(value) { - return BitString.wrap(value, { - type: 'bitstring', - unit: 1, - size: value.bit_size - }); - } - - static bits(value) { - return BitString.bitstring(value); - } - - static binary(value) { - return BitString.wrap(value, { - type: 'binary', - unit: 8, - size: value.length - }); - } - - static bytes(value) { - return BitString.binary(value); - } - - static utf8(value) { - return BitString.wrap(value, { type: 'utf8', unit: 1, size: value.length }); - } - - static utf16(value) { - return BitString.wrap(value, { - type: 'utf16', - unit: 1, - size: value.length * 2 - }); - } - - static utf32(value) { - return BitString.wrap(value, { - type: 'utf32', - unit: 1, - size: value.length * 4 - }); - } - - static signed(value) { - return BitString.wrap(value, {}, 'signed'); - } - - static unsigned(value) { - return BitString.wrap(value, {}, 'unsigned'); - } - - static native(value) { - return BitString.wrap(value, {}, 'native'); - } - - static big(value) { - return BitString.wrap(value, {}, 'big'); - } - - static little(value) { - return BitString.wrap(value, {}, 'little'); - } - - static size(value, count) { - return BitString.wrap(value, { size: count }); - } - - static unit(value, count) { - return BitString.wrap(value, { unit: count }); - } - - static wrap(value, opt, new_attribute = null) { - let the_value = value; - - if (!(value instanceof Object)) { - the_value = { value: value, attributes: [] }; - } - - the_value = Object.assign(the_value, opt); - - if (new_attribute) { - the_value.attributes.push(new_attribute); - } - - return the_value; - } - - static toUTF8Array(str) { - var utf8 = []; - for (var i = 0; i < str.length; i++) { - var charcode = str.charCodeAt(i); - if (charcode < 0x80) { - utf8.push(charcode); - } else if (charcode < 0x800) { - utf8.push(0xc0 | charcode >> 6, 0x80 | charcode & 0x3f); - } else if (charcode < 0xd800 || charcode >= 0xe000) { - utf8.push(0xe0 | charcode >> 12, 0x80 | charcode >> 6 & 0x3f, 0x80 | charcode & 0x3f); - } else { - // surrogate pair - i++; - // UTF-16 encodes 0x10000-0x10FFFF by - // subtracting 0x10000 and splitting the - // 20 bits of 0x0-0xFFFFF into two halves - charcode = 0x10000 + ((charcode & 0x3ff) << 10 | str.charCodeAt(i) & 0x3ff); - utf8.push(0xf0 | charcode >> 18, 0x80 | charcode >> 12 & 0x3f, 0x80 | charcode >> 6 & 0x3f, 0x80 | charcode & 0x3f); - } - } - return utf8; - } - - static toUTF16Array(str) { - var utf16 = []; - for (var i = 0; i < str.length; i++) { - var codePoint = str.codePointAt(i); - - if (codePoint <= 255) { - utf16.push(0); - utf16.push(codePoint); - } else { - utf16.push(codePoint >> 8 & 0xff); - utf16.push(codePoint & 0xff); - } - } - return utf16; - } - - static toUTF32Array(str) { - var utf32 = []; - for (var i = 0; i < str.length; i++) { - var codePoint = str.codePointAt(i); - - if (codePoint <= 255) { - utf32.push(0); - utf32.push(0); - utf32.push(0); - utf32.push(codePoint); - } else { - utf32.push(0); - utf32.push(0); - utf32.push(codePoint >> 8 & 0xff); - utf32.push(codePoint & 0xff); - } - } - return utf32; - } - - //http://stackoverflow.com/questions/2003493/javascript-float-from-to-bits - static float32ToBytes(f) { - var bytes = []; - - var buf = new ArrayBuffer(4); - new Float32Array(buf)[0] = f; - - let intVersion = new Uint32Array(buf)[0]; - - bytes.push(intVersion >> 24 & 0xff); - bytes.push(intVersion >> 16 & 0xff); - bytes.push(intVersion >> 8 & 0xff); - bytes.push(intVersion & 0xff); - - return bytes; - } - - static float64ToBytes(f) { - var bytes = []; - - var buf = new ArrayBuffer(8); - new Float64Array(buf)[0] = f; - - var intVersion1 = new Uint32Array(buf)[0]; - var intVersion2 = new Uint32Array(buf)[1]; - - bytes.push(intVersion2 >> 24 & 0xff); - bytes.push(intVersion2 >> 16 & 0xff); - bytes.push(intVersion2 >> 8 & 0xff); - bytes.push(intVersion2 & 0xff); - - bytes.push(intVersion1 >> 24 & 0xff); - bytes.push(intVersion1 >> 16 & 0xff); - bytes.push(intVersion1 >> 8 & 0xff); - bytes.push(intVersion1 & 0xff); - - return bytes; - } -} - -var ErlangTypes = { - Tuple, - PID, - Reference, - BitString -}; - -var vendor = { - ErlangTypes -}; - -export default vendor; +class Tuple{constructor(...a){this.values=Object.freeze(a),this.length=this.values.length}get(a){return this.values[a]}count(){return this.values.length}[Symbol.iterator](){return this.values[Symbol.iterator]()}toString(){let a,b='';for(a=0;a'}}let ref_counter=-1;class Reference{constructor(){++ref_counter,this.id=ref_counter,this.ref=Symbol()}toString(){return'Ref#<0.0.0.'+this.id+'>'}}class BitString{constructor(...a){this.value=Object.freeze(this.process(a)),this.length=this.value.length,this.bit_size=8*this.length,this.byte_size=this.length}get(a){return this.value[a]}count(){return this.value.length}slice(a,b=null){let c=this.value.slice(a,b),d=c.map((a)=>BitString.integer(a));return new BitString(...d)}[Symbol.iterator](){return this.value[Symbol.iterator]()}toString(){var a,b='';for(a=0;a>'}process(a){let b=[];var c;for(c=0;cb?c.push(b):2048>b?c.push(192|b>>6,128|63&b):55296>b||57344<=b?c.push(224|b>>12,128|63&b>>6,128|63&b):(d++,b=65536+((1023&b)<<10|1023&a.charCodeAt(d)),c.push(240|b>>18,128|63&b>>12,128|63&b>>6,128|63&b));return c}static toUTF16Array(a){for(var b,c=[],d=0;d=b?(c.push(0),c.push(b)):(c.push(255&b>>8),c.push(255&b));return c}static toUTF32Array(a){for(var b,c=[],d=0;d=b?(c.push(0),c.push(0),c.push(0),c.push(b)):(c.push(0),c.push(0),c.push(255&b>>8),c.push(255&b));return c}//http://stackoverflow.com/questions/2003493/javascript-float-from-to-bits +static float32ToBytes(a){var b=[],c=new ArrayBuffer(4);new Float32Array(c)[0]=a;let d=new Uint32Array(c)[0];return b.push(255&d>>24),b.push(255&d>>16),b.push(255&d>>8),b.push(255&d),b}static float64ToBytes(a){var b=[],c=new ArrayBuffer(8);new Float64Array(c)[0]=a;var d=new Uint32Array(c)[0],e=new Uint32Array(c)[1];return b.push(255&e>>24),b.push(255&e>>16),b.push(255&e>>8),b.push(255&e),b.push(255&d>>24),b.push(255&d>>16),b.push(255&d>>8),b.push(255&d),b}}var ErlangTypes={Tuple,PID,Reference,BitString},vendor={ErlangTypes};export default vendor; From 25989dfbbaac327434071a39e0d322c20cb1b486 Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Sat, 17 Mar 2018 15:07:19 -0500 Subject: [PATCH 834/860] Fix bug with global js modules --- .../passes/translate/forms/remote.ex | 18 +++++++++++++++++- lib/elixir_script/state.ex | 9 +++++++++ 2 files changed, 26 insertions(+), 1 deletion(-) diff --git a/lib/elixir_script/passes/translate/forms/remote.ex b/lib/elixir_script/passes/translate/forms/remote.ex index 6e945a49..fda121fe 100644 --- a/lib/elixir_script/passes/translate/forms/remote.ex +++ b/lib/elixir_script/passes/translate/forms/remote.ex @@ -94,7 +94,7 @@ defmodule ElixirScript.Translate.Forms.Remote do cond do ElixirScript.Translate.Module.is_js_module(module, state) and ModuleState.is_global_module(state.pid, module) -> - ElixirScript.Translate.Identifier.make_alias(Module.split(module) |> Enum.reverse()) + process_global_js_module_name(module, state) ElixirScript.Translate.Module.is_js_module(module, state) -> process_js_module_name(module, state) @@ -123,6 +123,22 @@ defmodule ElixirScript.Translate.Forms.Remote do Form.compile!(module, state) end + defp process_global_js_module_name(module, state) do + case ModuleState.get_js_module_name(state.pid, module) do + name when is_binary(name) -> + J.identifier(name) + + name when is_atom(name) -> + case to_string(name) do + "Elixir." <> _ -> + ElixirScript.Translate.Identifier.make_alias(Module.split(name) |> Enum.reverse()) + + x -> + J.identifier(x) + end + end + end + defp process_js_module_name(module, state) do case ModuleState.get_js_module_name(state.pid, module) do name when is_binary(name) -> diff --git a/lib/elixir_script/state.ex b/lib/elixir_script/state.ex index 79bd6eda..37d0473f 100644 --- a/lib/elixir_script/state.ex +++ b/lib/elixir_script/state.ex @@ -122,6 +122,15 @@ defmodule ElixirScript.State do end) end + def get_global_module_name(pid, module) do + Agent.get(pid, fn state -> + result = + Enum.find(state.js_modules, fn {mod, _name, path} -> mod == module and path == nil end) + + if result == nil, do: nil, else: elem(result, 1) + end) + end + def remove_unused_functions(pid) do Agent.get(pid, fn state -> state.compiler_opts.remove_unused_functions From 95e3c30eb8457b7d100b5a1be9cf8c90a478f098 Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Sat, 17 Mar 2018 15:13:22 -0500 Subject: [PATCH 835/860] Update changelog --- CHANGELOG.md | 6 ++++++ mix.exs | 2 +- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 8b589479..89d3cd1e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,12 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](http://keepachangelog.com/) and this project adheres to [Semantic Versioning](http://semver.org/). +## [0.32.1] - 2018-03-17 + +### Fixed + +* Global JavaScript modules not compiling correctly + ## [0.32.0] - 2018-02-10 ### Added diff --git a/mix.exs b/mix.exs index c4841a2c..29674176 100644 --- a/mix.exs +++ b/mix.exs @@ -4,7 +4,7 @@ defmodule ElixirScript.Mixfile do def project do [ app: :elixir_script, - version: "0.32.0", + version: "0.32.1", elixir: "~> 1.6", elixirc_paths: elixirc_paths(Mix.env()), deps: deps(), From 212aec2b0ea4d1ee03a61c9eb5eba299415105c3 Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Sun, 20 May 2018 13:34:13 -0500 Subject: [PATCH 836/860] Add CompilerInternals.md --- .tool-versions | 4 ++-- CompilerInternals.md | 51 ++++++++++++++++++++++++++++++++++++++++++++ mix.exs | 2 +- 3 files changed, 54 insertions(+), 3 deletions(-) create mode 100644 CompilerInternals.md diff --git a/.tool-versions b/.tool-versions index e5a7616f..fee73d5a 100644 --- a/.tool-versions +++ b/.tool-versions @@ -1,3 +1,3 @@ -erlang 20.1 -elixir 1.6.0-otp-20 +erlang 20.3 +elixir 1.6.5-otp-20 nodejs 8.9.1 diff --git a/CompilerInternals.md b/CompilerInternals.md new file mode 100644 index 00000000..c729ee09 --- /dev/null +++ b/CompilerInternals.md @@ -0,0 +1,51 @@ +# Compiler Internals + +This is a document describing how ElixirScript works. This is intended for those who would like to contribute to ElixirScript or those who are curious how it works. + +## Input + +[ElixrScript.Compiler](https://github.com/elixirscript/elixirscript/blob/master/lib/elixir_script/compiler.ex) is the entry point of the compiler. It takes in either a module or a list of modules. These are what are called the `entry modules` or the entry points into your application. These are the places ElixirScript will start it's compilation process. It will traverse what is used and only compile those things. This is the first step in the compilation process. Finding used modules to compile. + +## Finding Used Modules + +[ElixirScript.FindUsedModules](https://github.com/elixirscript/elixirscript/blob/master/lib/elixir_script/passes/find_used_modules.ex) looks at our entry modules and recursively crawls them to find all the modules used. It firsts exacts the Abstract Syntax Tree (AST) from the Beam file and then looks for references to modules that haven't been crawled yet. This information is stored in [ElixirScript.State](https://github.com/elixirscript/elixirscript/blob/master/lib/elixir_script/state.ex) + +## AST Extraction from Beam Files + +ElixirScript requires at Erlang 20+ and Elixir 1.6+. The reason why is that in Erlang 20 there is a new feature that allows for debug information to be stored in beam files. Any of the beam languages can use this. Elixir uses it by storing the AST for the module in there. This is a special version of the AST where all of the macros are expanded. This means ElixirScript does not have to worry about macro expansion itself. This AST is what ElixirScript works with. + +The code for this is in the [ElixirScript.Beam](https://github.com/elixirscript/elixirscript/blob/master/lib/elixir_script/beam.ex) module. + +`ElixirScript.debug_info/1` takes in a module name and returns the AST for that module. For a normal module, `{:ok, map}` are returned. If a protocol is given, `{:ok, atom, map, list}` is returned. The `atom` is the name of the protocol, The `map` is the protocol's AST and the `list` is the list of all of the implementation modules. + +This module handles the `String` and `Agent` modules a little bit differenly. Because of how Elixir compiles the unicode library, ElixirScript has to be careful not to compile the entire unicode library in JavaScript. So here, `debug_info` will get the AST from `String`, but replace some functions with the AST from `ElixirScript.String`. This ensures ElixirScript uses versions of functions in the standard lib that won't bring in the unicode module. The ame thing happens for `Agent` for different reasons. `Agent` is the only OTP module ElixirScript supports. ElixirScript hacks together a version of `Agent` that stores state in a way that allows ElixirScript users to use `Agent` just like they would with Elixir. + +## Finding Used Functions + +[ElixirScript.FindUsedFunctions](https://github.com/elixirscript/elixirscript/blob/master/lib/elixir_script/passes/find_used_functions.ex) is our second process in shrinking our compilation suface. In this process, we crawl through the modules we have found for compilation and see which functions are actually being called. This information is also stored in [ElixirScript.State](https://github.com/elixirscript/elixirscript/blob/master/lib/elixir_script/state.ex) for each module. + +**Note**: Because of the way protocols work, it is impossible to know what is used and what isn't. So for protocols and their implementations, we have to take in everything. + +Now we have what we need to compile to the JavaScript AST. + +## JavaScript AST (ESTree) + +Before going further, here is a brief intro into the JavaScript AST we use. The [ESTree spec](https://github.com/estree/estree) is a specification based on SpiderMonkey's JavaScript AST. This is used by several tools in the JavaScript ecosystem. There are many other versions of JavaScript ASTs, but the reason ElixirScript uses this one is because there are popular tools in the JavaScript ecosystem that understand it. ElixirScript uses the [ESTree](https://github.com/elixirscript/elixir-estree) Hex package. This package has structs that represent ESTree Nodes. It can also turn those into JavaScript code. + +## Translation + +[ElixirScript.Translate](https://github.com/elixirscript/elixirscript/blob/master/lib/elixir_script/passes/translate.ex) starts off the translation process. All this module does though is call [ElixirScript.Translate.Module](https://github.com/elixirscript/elixirscript/blob/master/lib/elixir_script/passes/translate/module.ex) on each of our modules. Here is where we take in the module info for each module and start translating to JavaScript AST. We compile the function definitions into JavaScript. Here is where we process the information gained from `ElixirScript.FindUsedFunctions` to remove any unused functions. In Elixir, function names are made up of the name and the arity. In JavaScript, that is not the case. ElixirScript combines function arities here into one definition. From here, ElixirScript compiles each function and places the translated AST back into `ElixirScript.State`. + +Functions comprise of clauses. Clauses have guards and blocks. Blocks being the blocks of code that make up the implementation. + +[ElixirScript.Translate.Function](https://github.com/elixirscript/elixirscript/blob/master/lib/elixir_script/passes/translate/function.ex) handles function translation. `ElixirScript.Translate.Function.compile_block\2` handles compilation of blocks. for each item in the block, `ElixirScript.Translate.Form.compile\2` is called. This is what is responsible for a bulk of the translation. + +Another aside to talk about function translation. Elixir supports tail call recursion. JavaScript does not. To allow our ElixirScript-translated functions to do so, we use a technique called `trampolining`. ElixirScript implementation still has some bugs, but it works for the most part. + +## Pattern Matching Translation + +Patterns are processed using [ElixirScript.Translate.Forms.Pattern](https://github.com/elixirscript/elixirscript/blob/master/lib/elixir_script/passes/translate/forms/pattern.ex). It takes all the forms of patterns and compiles them into JavaScript AST. The AST represents calls to the [Tailored](https://github.com/elixirscript/tailored) JavaScript library. This library is responsible for pattern matching at run time. + +## Output + +[ElixirScript.Output](https://github.com/elixirscript/elixirscript/blob/master/lib/elixir_script/passes/output.ex) is the last step in compilation. This modules is responsible for creating JavaScript modules and writing them to the file system. Each Elixir module is translated into a JavaScript module. diff --git a/mix.exs b/mix.exs index 29674176..067dac57 100644 --- a/mix.exs +++ b/mix.exs @@ -14,7 +14,7 @@ defmodule ElixirScript.Mixfile do test_coverage: [tool: ExCoveralls], docs: [ main: "ElixirScript", - extras: ["JavaScriptInterop.md"] + extras: ["JavaScriptInterop.md", "CompilerInternals.md"] ] ] end From 12fcc1bed6c30185c66899c0bacd25b04cfbcc22 Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Sun, 20 May 2018 13:36:32 -0500 Subject: [PATCH 837/860] Update README.md --- README.md | 30 ++++++++++++------------------ 1 file changed, 12 insertions(+), 18 deletions(-) diff --git a/README.md b/README.md index e48ed370..93e6bd41 100644 --- a/README.md +++ b/README.md @@ -1,21 +1,20 @@ -## ElixirScript [![Documentation](https://img.shields.io/badge/docs-hexpm-blue.svg)](http://hexdocs.pm/elixir_script/) [![Build](https://travis-ci.org/elixirscript/elixirscript.svg?branch=master)](https://travis-ci.org/elixirscript/elixirscript) [![Deps Status](https://beta.hexfaktor.org/badge/all/github/bryanjos/elixirscript.svg)](https://beta.hexfaktor.org/github/bryanjos/elixirscript) [![Join the chat at https://gitter.im/elixirscript/elixirscript](https://badges.gitter.im/elixirscript/elixirscript.svg)](https://gitter.im/elixirscript/elixirscript?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) +## ElixirScript [![Documentation](https://img.shields.io/badge/docs-hexpm-blue.svg)](http://hexdocs.pm/elixir_script/) [![Build](https://travis-ci.org/elixirscript/elixirscript.svg?branch=master)](https://travis-ci.org/elixirscript/elixirscript) The goal is to convert a subset (or full set) of Elixir code to JavaScript, providing the ability to write JavaScript in Elixir. This is done by taking the Elixir AST and converting it into JavaScript AST and then to JavaScript code. This is done using the [Elixir-ESTree](https://github.com/elixirscript/elixir-estree) library. [Documentation for current release](http://hexdocs.pm/elixir_script/) -Requirements -=========== +# Requirements + * Erlang 20 or greater -* Elixir 1.5 or greater (must be compiled with Erlang 20 or greater) +* Elixir 1.6 or greater (must be compiled with Erlang 20 or greater) * Node 8.2.1 or greater (only for development) -Usage -======== +# Usage Add dependency to your deps in mix.exs: -``` elixir +```elixir {:elixir_script, "~> x.x"} ``` @@ -42,18 +41,17 @@ Also add `elixir_script` configuration Run `mix compile` - -Examples -========== +# Examples ### Application + [ElixirScript Todo Example](https://github.com/elixirscript/todo-elixirscript) ### Library + [ElixirScript React](https://github.com/elixirscript/elixirscript_react) -Development -=========== +# Development ```bash # Clone the repo @@ -69,14 +67,10 @@ make make test ``` -Communication -======== - -[gitter room](https://gitter.im/elixirscript/elixirscript) +# Communication [#elixirscript](https://elixir-lang.slack.com/messages/elixirscript/) on the elixir-lang Slack -Contributing -======== +# Contributing Please check the [CONTRIBUTING.md](CONTRIBUTING.md) From 16ded7503f96fed269e2aecf0c355dda561c2306 Mon Sep 17 00:00:00 2001 From: Harlan T Wood Date: Sat, 30 Jun 2018 17:38:26 -1000 Subject: [PATCH 838/860] Fix broken link --- lib/elixir_script.ex | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/elixir_script.ex b/lib/elixir_script.ex index 9bd48428..b5cd9a03 100644 --- a/lib/elixir_script.ex +++ b/lib/elixir_script.ex @@ -60,7 +60,7 @@ defmodule ElixirScript do ### JavaScript Interop - Check out the [JavaScript Interoperability](JavascriptInterop.html) documentation + Check out the [JavaScript Interoperability](javascriptinterop.html) documentation ### Dependencies From 770c8346af12baf5633dc18d4b31438d7a24e6c4 Mon Sep 17 00:00:00 2001 From: Harlan T Wood Date: Sat, 30 Jun 2018 23:34:08 -1000 Subject: [PATCH 839/860] Fix sample code indentation --- lib/elixir_script.ex | 30 +++++++++++++++--------------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/lib/elixir_script.ex b/lib/elixir_script.ex index 9bd48428..c605df22 100644 --- a/lib/elixir_script.ex +++ b/lib/elixir_script.ex @@ -17,21 +17,21 @@ defmodule ElixirScript do ``` elixir def project do - [ - app: :my_app, - version: "0.1.0", - elixir: "~> 1.0", - deps: deps, - # Add elixir_script as a compilter - compilers: Mix.compilers ++ [:elixir_script], - # Our elixir_script configuration - elixir_script: [ - # Entry module. Can also be a list of modules - input: MyEntryModule, - # Output path. Either a path to a js file or a directory - output: "priv/elixir_script/build" - ] - ] + [ + app: :my_app, + version: "0.1.0", + elixir: "~> 1.0", + deps: deps, + # Add elixir_script as a compilter + compilers: Mix.compilers() ++ [:elixir_script], + # Our elixir_script configuration + elixir_script: [ + # Entry module. Can also be a list of modules + input: MyEntryModule, + # Output path. Either a path to a js file or a directory + output: "priv/elixir_script/build" + ] + ] end ``` From aaaff732a0721f4f4a15f4ed1608a7e87f7cfe73 Mon Sep 17 00:00:00 2001 From: Harlan T Wood Date: Sun, 1 Jul 2018 00:15:28 -1000 Subject: [PATCH 840/860] Add link to "starter kit" --- README.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/README.md b/README.md index 93e6bd41..6d464386 100644 --- a/README.md +++ b/README.md @@ -51,6 +51,10 @@ Run `mix compile` [ElixirScript React](https://github.com/elixirscript/elixirscript_react) +### Starter kit + +[Elixirscript Starter Kit](https://github.com/harlantwood/elixirscript-starter-kit) + # Development ```bash From 196ebe0b6349ae5ea8979caefc93e8c7b6015ea3 Mon Sep 17 00:00:00 2001 From: Harlan T Wood Date: Sun, 1 Jul 2018 00:28:51 -1000 Subject: [PATCH 841/860] Fix typo --- lib/elixir_script/ffi.ex | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/elixir_script/ffi.ex b/lib/elixir_script/ffi.ex index 7fb701ef..71249fe0 100644 --- a/lib/elixir_script/ffi.ex +++ b/lib/elixir_script/ffi.ex @@ -2,7 +2,7 @@ defmodule ElixirScript.FFI do @moduledoc """ The Foreign Function Interface (FFI) for interacting with JavaScript - To define a foreign module, make a new module and add `use ElixirScript.FFI`. to it + To define a foreign module, make a new module and add `use ElixirScript.FFI` to it. To define external functions, use the `defexternal` macro. Here is an example of a foreign module for a JSON module From d590871ede7407f50782a4f265fa62ecbf3fd861 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" Date: Thu, 21 Mar 2019 14:34:19 +0000 Subject: [PATCH 842/860] Bump poison from 3.1.0 to 4.0.1 Bumps [poison](https://github.com/devinus/poison) from 3.1.0 to 4.0.1. - [Release notes](https://github.com/devinus/poison/releases) - [Commits](https://github.com/devinus/poison/compare/3.1.0...4.0.1) Signed-off-by: dependabot[bot] --- mix.exs | 2 +- mix.lock | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/mix.exs b/mix.exs index 067dac57..61afeaa1 100644 --- a/mix.exs +++ b/mix.exs @@ -32,7 +32,7 @@ defmodule ElixirScript.Mixfile do {:excoveralls, "~> 0.7", only: :test}, {:credo, "~> 0.8", only: [:dev, :test]}, {:stream_data, "~> 0.3", only: :test}, - {:poison, "~> 3.1", only: :test} + {:poison, "~> 4.0", only: :test} ] end diff --git a/mix.lock b/mix.lock index 77645618..2c7118e7 100644 --- a/mix.lock +++ b/mix.lock @@ -11,7 +11,7 @@ "jsx": {:hex, :jsx, "2.8.3", "a05252d381885240744d955fbe3cf810504eb2567164824e19303ea59eef62cf", [:mix, :rebar3], [], "hexpm"}, "metrics": {:hex, :metrics, "1.0.1", "25f094dea2cda98213cecc3aeff09e940299d950904393b2a29d191c346a8486", [:rebar3], [], "hexpm"}, "mimerl": {:hex, :mimerl, "1.0.2", "993f9b0e084083405ed8252b99460c4f0563e41729ab42d9074fd5e52439be88", [:rebar3], [], "hexpm"}, - "poison": {:hex, :poison, "3.1.0", "d9eb636610e096f86f25d9a46f35a9facac35609a7591b3be3326e99a0484665", [:mix], [], "hexpm"}, + "poison": {:hex, :poison, "4.0.1", "bcb755a16fac91cad79bfe9fc3585bb07b9331e50cfe3420a24bcc2d735709ae", [:mix], [], "hexpm"}, "ssl_verify_fun": {:hex, :ssl_verify_fun, "1.1.1", "28a4d65b7f59893bc2c7de786dec1e1555bd742d336043fe644ae956c3497fbe", [:make, :rebar], [], "hexpm"}, "stream_data": {:hex, :stream_data, "0.3.0", "cbfc8e3212f64683615657ea27804126a42ded634adfdfee258bf087ee605d46", [:mix], [], "hexpm"}, "unicode_util_compat": {:hex, :unicode_util_compat, "0.3.1", "a1f612a7b512638634a603c8f401892afbf99b8ce93a45041f8aaca99cadb85e", [:rebar3], [], "hexpm"}} From 8669ff5d15b6c71332bab942f385f975cb6b17ec Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" Date: Mon, 25 Mar 2019 07:21:39 +0000 Subject: [PATCH 843/860] Bump credo from 0.8.8 to 1.0.4 Bumps [credo](https://github.com/rrrene/credo) from 0.8.8 to 1.0.4. - [Release notes](https://github.com/rrrene/credo/releases) - [Changelog](https://github.com/rrrene/credo/blob/master/CHANGELOG.md) - [Commits](https://github.com/rrrene/credo/compare/v0.8.8...v1.0.4) Signed-off-by: dependabot[bot] --- mix.exs | 2 +- mix.lock | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/mix.exs b/mix.exs index 067dac57..93a540cd 100644 --- a/mix.exs +++ b/mix.exs @@ -30,7 +30,7 @@ defmodule ElixirScript.Mixfile do {:estree, "~> 2.6"}, {:ex_doc, "~> 0.16", only: :dev}, {:excoveralls, "~> 0.7", only: :test}, - {:credo, "~> 0.8", only: [:dev, :test]}, + {:credo, "~> 1.0", only: [:dev, :test]}, {:stream_data, "~> 0.3", only: :test}, {:poison, "~> 3.1", only: :test} ] diff --git a/mix.lock b/mix.lock index 77645618..86e15fc8 100644 --- a/mix.lock +++ b/mix.lock @@ -1,6 +1,6 @@ %{"bunt": {:hex, :bunt, "0.2.0", "951c6e801e8b1d2cbe58ebbd3e616a869061ddadcc4863d0a2182541acae9a38", [:mix], [], "hexpm"}, "certifi": {:hex, :certifi, "2.0.0", "a0c0e475107135f76b8c1d5bc7efb33cd3815cb3cf3dea7aefdd174dabead064", [:rebar3], [], "hexpm"}, - "credo": {:hex, :credo, "0.8.8", "990e7844a8d06ebacd88744a55853a83b74270b8a8461c55a4d0334b8e1736c9", [:mix], [{:bunt, "~> 0.2.0", [hex: :bunt, repo: "hexpm", optional: false]}], "hexpm"}, + "credo": {:hex, :credo, "1.0.4", "d2214d4cc88c07f54004ffd5a2a27408208841be5eca9f5a72ce9e8e835f7ede", [:mix], [{:bunt, "~> 0.2.0", [hex: :bunt, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: false]}], "hexpm"}, "earmark": {:hex, :earmark, "1.2.3", "206eb2e2ac1a794aa5256f3982de7a76bf4579ff91cb28d0e17ea2c9491e46a4", [:mix], [], "hexpm"}, "estree": {:hex, :estree, "2.6.1", "0a17cc0e9e35315dc4fcd79d30a746b1f3e9ed654be6084ce882ab491165ae22", [:mix], [], "hexpm"}, "ex_doc": {:hex, :ex_doc, "0.18.1", "37c69d2ef62f24928c1f4fdc7c724ea04aecfdf500c4329185f8e3649c915baf", [:mix], [{:earmark, "~> 1.1", [hex: :earmark, repo: "hexpm", optional: false]}], "hexpm"}, @@ -8,6 +8,7 @@ "exjsx": {:hex, :exjsx, "4.0.0", "60548841e0212df401e38e63c0078ec57b33e7ea49b032c796ccad8cde794b5c", [:mix], [{:jsx, "~> 2.8.0", [hex: :jsx, repo: "hexpm", optional: false]}], "hexpm"}, "hackney": {:hex, :hackney, "1.10.1", "c38d0ca52ea80254936a32c45bb7eb414e7a96a521b4ce76d00a69753b157f21", [:rebar3], [{:certifi, "2.0.0", [hex: :certifi, repo: "hexpm", optional: false]}, {:idna, "5.1.0", [hex: :idna, repo: "hexpm", optional: false]}, {:metrics, "1.0.1", [hex: :metrics, repo: "hexpm", optional: false]}, {:mimerl, "1.0.2", [hex: :mimerl, repo: "hexpm", optional: false]}, {:ssl_verify_fun, "1.1.1", [hex: :ssl_verify_fun, repo: "hexpm", optional: false]}], "hexpm"}, "idna": {:hex, :idna, "5.1.0", "d72b4effeb324ad5da3cab1767cb16b17939004e789d8c0ad5b70f3cea20c89a", [:rebar3], [{:unicode_util_compat, "0.3.1", [hex: :unicode_util_compat, repo: "hexpm", optional: false]}], "hexpm"}, + "jason": {:hex, :jason, "1.1.2", "b03dedea67a99223a2eaf9f1264ce37154564de899fd3d8b9a21b1a6fd64afe7", [:mix], [{:decimal, "~> 1.0", [hex: :decimal, repo: "hexpm", optional: true]}], "hexpm"}, "jsx": {:hex, :jsx, "2.8.3", "a05252d381885240744d955fbe3cf810504eb2567164824e19303ea59eef62cf", [:mix, :rebar3], [], "hexpm"}, "metrics": {:hex, :metrics, "1.0.1", "25f094dea2cda98213cecc3aeff09e940299d950904393b2a29d191c346a8486", [:rebar3], [], "hexpm"}, "mimerl": {:hex, :mimerl, "1.0.2", "993f9b0e084083405ed8252b99460c4f0563e41729ab42d9074fd5e52439be88", [:rebar3], [], "hexpm"}, From 3c7e3c03b6d24e40989a1c41f20e6b9c1be2edac Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" Date: Mon, 22 Apr 2019 07:09:48 +0000 Subject: [PATCH 844/860] Bump credo from 1.0.4 to 1.0.5 Bumps [credo](https://github.com/rrrene/credo) from 1.0.4 to 1.0.5. - [Release notes](https://github.com/rrrene/credo/releases) - [Changelog](https://github.com/rrrene/credo/blob/master/CHANGELOG.md) - [Commits](https://github.com/rrrene/credo/compare/v1.0.4...v1.0.5) Signed-off-by: dependabot[bot] --- mix.lock | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mix.lock b/mix.lock index 40ed581c..0d0beb4e 100644 --- a/mix.lock +++ b/mix.lock @@ -1,6 +1,6 @@ %{"bunt": {:hex, :bunt, "0.2.0", "951c6e801e8b1d2cbe58ebbd3e616a869061ddadcc4863d0a2182541acae9a38", [:mix], [], "hexpm"}, "certifi": {:hex, :certifi, "2.0.0", "a0c0e475107135f76b8c1d5bc7efb33cd3815cb3cf3dea7aefdd174dabead064", [:rebar3], [], "hexpm"}, - "credo": {:hex, :credo, "1.0.4", "d2214d4cc88c07f54004ffd5a2a27408208841be5eca9f5a72ce9e8e835f7ede", [:mix], [{:bunt, "~> 0.2.0", [hex: :bunt, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: false]}], "hexpm"}, + "credo": {:hex, :credo, "1.0.5", "fdea745579f8845315fe6a3b43e2f9f8866839cfbc8562bb72778e9fdaa94214", [:mix], [{:bunt, "~> 0.2.0", [hex: :bunt, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: false]}], "hexpm"}, "earmark": {:hex, :earmark, "1.2.3", "206eb2e2ac1a794aa5256f3982de7a76bf4579ff91cb28d0e17ea2c9491e46a4", [:mix], [], "hexpm"}, "estree": {:hex, :estree, "2.6.1", "0a17cc0e9e35315dc4fcd79d30a746b1f3e9ed654be6084ce882ab491165ae22", [:mix], [], "hexpm"}, "ex_doc": {:hex, :ex_doc, "0.18.1", "37c69d2ef62f24928c1f4fdc7c724ea04aecfdf500c4329185f8e3649c915baf", [:mix], [{:earmark, "~> 1.1", [hex: :earmark, repo: "hexpm", optional: false]}], "hexpm"}, From e750be1b1f264a9ded31124b84f4fd612fcc41e4 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" Date: Mon, 22 Apr 2019 13:27:09 +0000 Subject: [PATCH 845/860] Bump excoveralls from 0.7.4 to 0.10.6 Bumps [excoveralls](https://github.com/parroty/excoveralls) from 0.7.4 to 0.10.6. - [Release notes](https://github.com/parroty/excoveralls/releases) - [Changelog](https://github.com/parroty/excoveralls/blob/master/CHANGELOG.md) - [Commits](https://github.com/parroty/excoveralls/compare/v0.7.4...v0.10.6) Signed-off-by: dependabot[bot] --- mix.lock | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/mix.lock b/mix.lock index 0d0beb4e..78d35758 100644 --- a/mix.lock +++ b/mix.lock @@ -1,18 +1,19 @@ %{"bunt": {:hex, :bunt, "0.2.0", "951c6e801e8b1d2cbe58ebbd3e616a869061ddadcc4863d0a2182541acae9a38", [:mix], [], "hexpm"}, - "certifi": {:hex, :certifi, "2.0.0", "a0c0e475107135f76b8c1d5bc7efb33cd3815cb3cf3dea7aefdd174dabead064", [:rebar3], [], "hexpm"}, + "certifi": {:hex, :certifi, "2.5.1", "867ce347f7c7d78563450a18a6a28a8090331e77fa02380b4a21962a65d36ee5", [:rebar3], [{:parse_trans, "~>3.3", [hex: :parse_trans, repo: "hexpm", optional: false]}], "hexpm"}, "credo": {:hex, :credo, "1.0.5", "fdea745579f8845315fe6a3b43e2f9f8866839cfbc8562bb72778e9fdaa94214", [:mix], [{:bunt, "~> 0.2.0", [hex: :bunt, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: false]}], "hexpm"}, "earmark": {:hex, :earmark, "1.2.3", "206eb2e2ac1a794aa5256f3982de7a76bf4579ff91cb28d0e17ea2c9491e46a4", [:mix], [], "hexpm"}, "estree": {:hex, :estree, "2.6.1", "0a17cc0e9e35315dc4fcd79d30a746b1f3e9ed654be6084ce882ab491165ae22", [:mix], [], "hexpm"}, "ex_doc": {:hex, :ex_doc, "0.18.1", "37c69d2ef62f24928c1f4fdc7c724ea04aecfdf500c4329185f8e3649c915baf", [:mix], [{:earmark, "~> 1.1", [hex: :earmark, repo: "hexpm", optional: false]}], "hexpm"}, - "excoveralls": {:hex, :excoveralls, "0.7.4", "3d84b2f15a0e593159f74b19f83794b464b34817183d27965bdc6c462de014f9", [:mix], [{:exjsx, ">= 3.0.0", [hex: :exjsx, repo: "hexpm", optional: false]}, {:hackney, ">= 0.12.0", [hex: :hackney, repo: "hexpm", optional: false]}], "hexpm"}, + "excoveralls": {:hex, :excoveralls, "0.10.6", "e2b9718c9d8e3ef90bc22278c3f76c850a9f9116faf4ebe9678063310742edc2", [:mix], [{:hackney, "~> 1.13", [hex: :hackney, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: false]}], "hexpm"}, "exjsx": {:hex, :exjsx, "4.0.0", "60548841e0212df401e38e63c0078ec57b33e7ea49b032c796ccad8cde794b5c", [:mix], [{:jsx, "~> 2.8.0", [hex: :jsx, repo: "hexpm", optional: false]}], "hexpm"}, - "hackney": {:hex, :hackney, "1.10.1", "c38d0ca52ea80254936a32c45bb7eb414e7a96a521b4ce76d00a69753b157f21", [:rebar3], [{:certifi, "2.0.0", [hex: :certifi, repo: "hexpm", optional: false]}, {:idna, "5.1.0", [hex: :idna, repo: "hexpm", optional: false]}, {:metrics, "1.0.1", [hex: :metrics, repo: "hexpm", optional: false]}, {:mimerl, "1.0.2", [hex: :mimerl, repo: "hexpm", optional: false]}, {:ssl_verify_fun, "1.1.1", [hex: :ssl_verify_fun, repo: "hexpm", optional: false]}], "hexpm"}, - "idna": {:hex, :idna, "5.1.0", "d72b4effeb324ad5da3cab1767cb16b17939004e789d8c0ad5b70f3cea20c89a", [:rebar3], [{:unicode_util_compat, "0.3.1", [hex: :unicode_util_compat, repo: "hexpm", optional: false]}], "hexpm"}, + "hackney": {:hex, :hackney, "1.15.1", "9f8f471c844b8ce395f7b6d8398139e26ddca9ebc171a8b91342ee15a19963f4", [:rebar3], [{:certifi, "2.5.1", [hex: :certifi, repo: "hexpm", optional: false]}, {:idna, "6.0.0", [hex: :idna, repo: "hexpm", optional: false]}, {:metrics, "1.0.1", [hex: :metrics, repo: "hexpm", optional: false]}, {:mimerl, "~>1.1", [hex: :mimerl, repo: "hexpm", optional: false]}, {:ssl_verify_fun, "1.1.4", [hex: :ssl_verify_fun, repo: "hexpm", optional: false]}], "hexpm"}, + "idna": {:hex, :idna, "6.0.0", "689c46cbcdf3524c44d5f3dde8001f364cd7608a99556d8fbd8239a5798d4c10", [:rebar3], [{:unicode_util_compat, "0.4.1", [hex: :unicode_util_compat, repo: "hexpm", optional: false]}], "hexpm"}, "jason": {:hex, :jason, "1.1.2", "b03dedea67a99223a2eaf9f1264ce37154564de899fd3d8b9a21b1a6fd64afe7", [:mix], [{:decimal, "~> 1.0", [hex: :decimal, repo: "hexpm", optional: true]}], "hexpm"}, "jsx": {:hex, :jsx, "2.8.3", "a05252d381885240744d955fbe3cf810504eb2567164824e19303ea59eef62cf", [:mix, :rebar3], [], "hexpm"}, "metrics": {:hex, :metrics, "1.0.1", "25f094dea2cda98213cecc3aeff09e940299d950904393b2a29d191c346a8486", [:rebar3], [], "hexpm"}, - "mimerl": {:hex, :mimerl, "1.0.2", "993f9b0e084083405ed8252b99460c4f0563e41729ab42d9074fd5e52439be88", [:rebar3], [], "hexpm"}, + "mimerl": {:hex, :mimerl, "1.2.0", "67e2d3f571088d5cfd3e550c383094b47159f3eee8ffa08e64106cdf5e981be3", [:rebar3], [], "hexpm"}, + "parse_trans": {:hex, :parse_trans, "3.3.0", "09765507a3c7590a784615cfd421d101aec25098d50b89d7aa1d66646bc571c1", [:rebar3], [], "hexpm"}, "poison": {:hex, :poison, "4.0.1", "bcb755a16fac91cad79bfe9fc3585bb07b9331e50cfe3420a24bcc2d735709ae", [:mix], [], "hexpm"}, - "ssl_verify_fun": {:hex, :ssl_verify_fun, "1.1.1", "28a4d65b7f59893bc2c7de786dec1e1555bd742d336043fe644ae956c3497fbe", [:make, :rebar], [], "hexpm"}, + "ssl_verify_fun": {:hex, :ssl_verify_fun, "1.1.4", "f0eafff810d2041e93f915ef59899c923f4568f4585904d010387ed74988e77b", [:make, :mix, :rebar3], [], "hexpm"}, "stream_data": {:hex, :stream_data, "0.3.0", "cbfc8e3212f64683615657ea27804126a42ded634adfdfee258bf087ee605d46", [:mix], [], "hexpm"}, - "unicode_util_compat": {:hex, :unicode_util_compat, "0.3.1", "a1f612a7b512638634a603c8f401892afbf99b8ce93a45041f8aaca99cadb85e", [:rebar3], [], "hexpm"}} + "unicode_util_compat": {:hex, :unicode_util_compat, "0.4.1", "d869e4c68901dd9531385bb0c8c40444ebf624e60b6962d95952775cac5e90cd", [:rebar3], [], "hexpm"}} From 4d780666978c784149d17793913fc7d914359f3c Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" Date: Mon, 22 Apr 2019 13:35:10 +0000 Subject: [PATCH 846/860] Bump ex_doc from 0.18.1 to 0.20.2 Bumps [ex_doc](https://github.com/elixir-lang/ex_doc) from 0.18.1 to 0.20.2. - [Release notes](https://github.com/elixir-lang/ex_doc/releases) - [Changelog](https://github.com/elixir-lang/ex_doc/blob/master/CHANGELOG.md) - [Commits](https://github.com/elixir-lang/ex_doc/compare/v0.18.1...v0.20.2) Signed-off-by: dependabot[bot] --- mix.lock | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/mix.lock b/mix.lock index 78d35758..b055040d 100644 --- a/mix.lock +++ b/mix.lock @@ -1,17 +1,20 @@ %{"bunt": {:hex, :bunt, "0.2.0", "951c6e801e8b1d2cbe58ebbd3e616a869061ddadcc4863d0a2182541acae9a38", [:mix], [], "hexpm"}, "certifi": {:hex, :certifi, "2.5.1", "867ce347f7c7d78563450a18a6a28a8090331e77fa02380b4a21962a65d36ee5", [:rebar3], [{:parse_trans, "~>3.3", [hex: :parse_trans, repo: "hexpm", optional: false]}], "hexpm"}, "credo": {:hex, :credo, "1.0.5", "fdea745579f8845315fe6a3b43e2f9f8866839cfbc8562bb72778e9fdaa94214", [:mix], [{:bunt, "~> 0.2.0", [hex: :bunt, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: false]}], "hexpm"}, - "earmark": {:hex, :earmark, "1.2.3", "206eb2e2ac1a794aa5256f3982de7a76bf4579ff91cb28d0e17ea2c9491e46a4", [:mix], [], "hexpm"}, + "earmark": {:hex, :earmark, "1.3.2", "b840562ea3d67795ffbb5bd88940b1bed0ed9fa32834915125ea7d02e35888a5", [:mix], [], "hexpm"}, "estree": {:hex, :estree, "2.6.1", "0a17cc0e9e35315dc4fcd79d30a746b1f3e9ed654be6084ce882ab491165ae22", [:mix], [], "hexpm"}, - "ex_doc": {:hex, :ex_doc, "0.18.1", "37c69d2ef62f24928c1f4fdc7c724ea04aecfdf500c4329185f8e3649c915baf", [:mix], [{:earmark, "~> 1.1", [hex: :earmark, repo: "hexpm", optional: false]}], "hexpm"}, + "ex_doc": {:hex, :ex_doc, "0.20.2", "1bd0dfb0304bade58beb77f20f21ee3558cc3c753743ae0ddbb0fd7ba2912331", [:mix], [{:earmark, "~> 1.3", [hex: :earmark, repo: "hexpm", optional: false]}, {:makeup_elixir, "~> 0.10", [hex: :makeup_elixir, repo: "hexpm", optional: false]}], "hexpm"}, "excoveralls": {:hex, :excoveralls, "0.10.6", "e2b9718c9d8e3ef90bc22278c3f76c850a9f9116faf4ebe9678063310742edc2", [:mix], [{:hackney, "~> 1.13", [hex: :hackney, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: false]}], "hexpm"}, "exjsx": {:hex, :exjsx, "4.0.0", "60548841e0212df401e38e63c0078ec57b33e7ea49b032c796ccad8cde794b5c", [:mix], [{:jsx, "~> 2.8.0", [hex: :jsx, repo: "hexpm", optional: false]}], "hexpm"}, "hackney": {:hex, :hackney, "1.15.1", "9f8f471c844b8ce395f7b6d8398139e26ddca9ebc171a8b91342ee15a19963f4", [:rebar3], [{:certifi, "2.5.1", [hex: :certifi, repo: "hexpm", optional: false]}, {:idna, "6.0.0", [hex: :idna, repo: "hexpm", optional: false]}, {:metrics, "1.0.1", [hex: :metrics, repo: "hexpm", optional: false]}, {:mimerl, "~>1.1", [hex: :mimerl, repo: "hexpm", optional: false]}, {:ssl_verify_fun, "1.1.4", [hex: :ssl_verify_fun, repo: "hexpm", optional: false]}], "hexpm"}, "idna": {:hex, :idna, "6.0.0", "689c46cbcdf3524c44d5f3dde8001f364cd7608a99556d8fbd8239a5798d4c10", [:rebar3], [{:unicode_util_compat, "0.4.1", [hex: :unicode_util_compat, repo: "hexpm", optional: false]}], "hexpm"}, "jason": {:hex, :jason, "1.1.2", "b03dedea67a99223a2eaf9f1264ce37154564de899fd3d8b9a21b1a6fd64afe7", [:mix], [{:decimal, "~> 1.0", [hex: :decimal, repo: "hexpm", optional: true]}], "hexpm"}, "jsx": {:hex, :jsx, "2.8.3", "a05252d381885240744d955fbe3cf810504eb2567164824e19303ea59eef62cf", [:mix, :rebar3], [], "hexpm"}, + "makeup": {:hex, :makeup, "0.8.0", "9cf32aea71c7fe0a4b2e9246c2c4978f9070257e5c9ce6d4a28ec450a839b55f", [:mix], [{:nimble_parsec, "~> 0.5.0", [hex: :nimble_parsec, repo: "hexpm", optional: false]}], "hexpm"}, + "makeup_elixir": {:hex, :makeup_elixir, "0.13.0", "be7a477997dcac2e48a9d695ec730b2d22418292675c75aa2d34ba0909dcdeda", [:mix], [{:makeup, "~> 0.8", [hex: :makeup, repo: "hexpm", optional: false]}], "hexpm"}, "metrics": {:hex, :metrics, "1.0.1", "25f094dea2cda98213cecc3aeff09e940299d950904393b2a29d191c346a8486", [:rebar3], [], "hexpm"}, "mimerl": {:hex, :mimerl, "1.2.0", "67e2d3f571088d5cfd3e550c383094b47159f3eee8ffa08e64106cdf5e981be3", [:rebar3], [], "hexpm"}, + "nimble_parsec": {:hex, :nimble_parsec, "0.5.0", "90e2eca3d0266e5c53f8fbe0079694740b9c91b6747f2b7e3c5d21966bba8300", [:mix], [], "hexpm"}, "parse_trans": {:hex, :parse_trans, "3.3.0", "09765507a3c7590a784615cfd421d101aec25098d50b89d7aa1d66646bc571c1", [:rebar3], [], "hexpm"}, "poison": {:hex, :poison, "4.0.1", "bcb755a16fac91cad79bfe9fc3585bb07b9331e50cfe3420a24bcc2d735709ae", [:mix], [], "hexpm"}, "ssl_verify_fun": {:hex, :ssl_verify_fun, "1.1.4", "f0eafff810d2041e93f915ef59899c923f4568f4585904d010387ed74988e77b", [:make, :mix, :rebar3], [], "hexpm"}, From ef2474e9af1e5c45043be342f97febce74416b48 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" Date: Mon, 6 May 2019 07:24:36 +0000 Subject: [PATCH 847/860] Bump excoveralls from 0.10.6 to 0.11.0 Bumps [excoveralls](https://github.com/parroty/excoveralls) from 0.10.6 to 0.11.0. - [Release notes](https://github.com/parroty/excoveralls/releases) - [Changelog](https://github.com/parroty/excoveralls/blob/master/CHANGELOG.md) - [Commits](https://github.com/parroty/excoveralls/compare/v0.10.6...v0.11.0) Signed-off-by: dependabot[bot] --- mix.lock | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mix.lock b/mix.lock index b055040d..578cdf32 100644 --- a/mix.lock +++ b/mix.lock @@ -4,7 +4,7 @@ "earmark": {:hex, :earmark, "1.3.2", "b840562ea3d67795ffbb5bd88940b1bed0ed9fa32834915125ea7d02e35888a5", [:mix], [], "hexpm"}, "estree": {:hex, :estree, "2.6.1", "0a17cc0e9e35315dc4fcd79d30a746b1f3e9ed654be6084ce882ab491165ae22", [:mix], [], "hexpm"}, "ex_doc": {:hex, :ex_doc, "0.20.2", "1bd0dfb0304bade58beb77f20f21ee3558cc3c753743ae0ddbb0fd7ba2912331", [:mix], [{:earmark, "~> 1.3", [hex: :earmark, repo: "hexpm", optional: false]}, {:makeup_elixir, "~> 0.10", [hex: :makeup_elixir, repo: "hexpm", optional: false]}], "hexpm"}, - "excoveralls": {:hex, :excoveralls, "0.10.6", "e2b9718c9d8e3ef90bc22278c3f76c850a9f9116faf4ebe9678063310742edc2", [:mix], [{:hackney, "~> 1.13", [hex: :hackney, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: false]}], "hexpm"}, + "excoveralls": {:hex, :excoveralls, "0.11.0", "1427780f327902f099ef948bbc107b06a200a14a80e5badc1f9624d0f059235f", [:mix], [{:hackney, "~> 1.0", [hex: :hackney, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: false]}], "hexpm"}, "exjsx": {:hex, :exjsx, "4.0.0", "60548841e0212df401e38e63c0078ec57b33e7ea49b032c796ccad8cde794b5c", [:mix], [{:jsx, "~> 2.8.0", [hex: :jsx, repo: "hexpm", optional: false]}], "hexpm"}, "hackney": {:hex, :hackney, "1.15.1", "9f8f471c844b8ce395f7b6d8398139e26ddca9ebc171a8b91342ee15a19963f4", [:rebar3], [{:certifi, "2.5.1", [hex: :certifi, repo: "hexpm", optional: false]}, {:idna, "6.0.0", [hex: :idna, repo: "hexpm", optional: false]}, {:metrics, "1.0.1", [hex: :metrics, repo: "hexpm", optional: false]}, {:mimerl, "~>1.1", [hex: :mimerl, repo: "hexpm", optional: false]}, {:ssl_verify_fun, "1.1.4", [hex: :ssl_verify_fun, repo: "hexpm", optional: false]}], "hexpm"}, "idna": {:hex, :idna, "6.0.0", "689c46cbcdf3524c44d5f3dde8001f364cd7608a99556d8fbd8239a5798d4c10", [:rebar3], [{:unicode_util_compat, "0.4.1", [hex: :unicode_util_compat, repo: "hexpm", optional: false]}], "hexpm"}, From ae34eebedefe981e29da7ca593b36e4de7d33bd5 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" Date: Mon, 13 May 2019 07:26:54 +0000 Subject: [PATCH 848/860] Bump excoveralls from 0.11.0 to 0.11.1 Bumps [excoveralls](https://github.com/parroty/excoveralls) from 0.11.0 to 0.11.1. - [Release notes](https://github.com/parroty/excoveralls/releases) - [Changelog](https://github.com/parroty/excoveralls/blob/master/CHANGELOG.md) - [Commits](https://github.com/parroty/excoveralls/compare/v0.11.0...v0.11.1) Signed-off-by: dependabot[bot] --- mix.lock | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mix.lock b/mix.lock index 578cdf32..183fb2a2 100644 --- a/mix.lock +++ b/mix.lock @@ -4,7 +4,7 @@ "earmark": {:hex, :earmark, "1.3.2", "b840562ea3d67795ffbb5bd88940b1bed0ed9fa32834915125ea7d02e35888a5", [:mix], [], "hexpm"}, "estree": {:hex, :estree, "2.6.1", "0a17cc0e9e35315dc4fcd79d30a746b1f3e9ed654be6084ce882ab491165ae22", [:mix], [], "hexpm"}, "ex_doc": {:hex, :ex_doc, "0.20.2", "1bd0dfb0304bade58beb77f20f21ee3558cc3c753743ae0ddbb0fd7ba2912331", [:mix], [{:earmark, "~> 1.3", [hex: :earmark, repo: "hexpm", optional: false]}, {:makeup_elixir, "~> 0.10", [hex: :makeup_elixir, repo: "hexpm", optional: false]}], "hexpm"}, - "excoveralls": {:hex, :excoveralls, "0.11.0", "1427780f327902f099ef948bbc107b06a200a14a80e5badc1f9624d0f059235f", [:mix], [{:hackney, "~> 1.0", [hex: :hackney, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: false]}], "hexpm"}, + "excoveralls": {:hex, :excoveralls, "0.11.1", "dd677fbdd49114fdbdbf445540ec735808250d56b011077798316505064edb2c", [:mix], [{:hackney, "~> 1.0", [hex: :hackney, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: false]}], "hexpm"}, "exjsx": {:hex, :exjsx, "4.0.0", "60548841e0212df401e38e63c0078ec57b33e7ea49b032c796ccad8cde794b5c", [:mix], [{:jsx, "~> 2.8.0", [hex: :jsx, repo: "hexpm", optional: false]}], "hexpm"}, "hackney": {:hex, :hackney, "1.15.1", "9f8f471c844b8ce395f7b6d8398139e26ddca9ebc171a8b91342ee15a19963f4", [:rebar3], [{:certifi, "2.5.1", [hex: :certifi, repo: "hexpm", optional: false]}, {:idna, "6.0.0", [hex: :idna, repo: "hexpm", optional: false]}, {:metrics, "1.0.1", [hex: :metrics, repo: "hexpm", optional: false]}, {:mimerl, "~>1.1", [hex: :mimerl, repo: "hexpm", optional: false]}, {:ssl_verify_fun, "1.1.4", [hex: :ssl_verify_fun, repo: "hexpm", optional: false]}], "hexpm"}, "idna": {:hex, :idna, "6.0.0", "689c46cbcdf3524c44d5f3dde8001f364cd7608a99556d8fbd8239a5798d4c10", [:rebar3], [{:unicode_util_compat, "0.4.1", [hex: :unicode_util_compat, repo: "hexpm", optional: false]}], "hexpm"}, From bb44d1ab20af37c08fbe0afbb15d0251e20f4eb7 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" Date: Tue, 14 May 2019 15:41:46 +0000 Subject: [PATCH 849/860] Bump estree from 2.6.1 to 2.7.0 Bumps [estree](https://github.com/bryanjos/elixir-estree) from 2.6.1 to 2.7.0. - [Release notes](https://github.com/bryanjos/elixir-estree/releases) - [Changelog](https://github.com/elixirscript/elixir-estree/blob/master/CHANGELOG.md) - [Commits](https://github.com/bryanjos/elixir-estree/commits) Signed-off-by: dependabot[bot] --- mix.lock | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mix.lock b/mix.lock index 183fb2a2..9881ee42 100644 --- a/mix.lock +++ b/mix.lock @@ -2,7 +2,7 @@ "certifi": {:hex, :certifi, "2.5.1", "867ce347f7c7d78563450a18a6a28a8090331e77fa02380b4a21962a65d36ee5", [:rebar3], [{:parse_trans, "~>3.3", [hex: :parse_trans, repo: "hexpm", optional: false]}], "hexpm"}, "credo": {:hex, :credo, "1.0.5", "fdea745579f8845315fe6a3b43e2f9f8866839cfbc8562bb72778e9fdaa94214", [:mix], [{:bunt, "~> 0.2.0", [hex: :bunt, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: false]}], "hexpm"}, "earmark": {:hex, :earmark, "1.3.2", "b840562ea3d67795ffbb5bd88940b1bed0ed9fa32834915125ea7d02e35888a5", [:mix], [], "hexpm"}, - "estree": {:hex, :estree, "2.6.1", "0a17cc0e9e35315dc4fcd79d30a746b1f3e9ed654be6084ce882ab491165ae22", [:mix], [], "hexpm"}, + "estree": {:hex, :estree, "2.7.0", "32cb6ff05c85a93bf6c646b3b184e131f699fc1e7157d2b5be148c17f43ae566", [:mix], [], "hexpm"}, "ex_doc": {:hex, :ex_doc, "0.20.2", "1bd0dfb0304bade58beb77f20f21ee3558cc3c753743ae0ddbb0fd7ba2912331", [:mix], [{:earmark, "~> 1.3", [hex: :earmark, repo: "hexpm", optional: false]}, {:makeup_elixir, "~> 0.10", [hex: :makeup_elixir, repo: "hexpm", optional: false]}], "hexpm"}, "excoveralls": {:hex, :excoveralls, "0.11.1", "dd677fbdd49114fdbdbf445540ec735808250d56b011077798316505064edb2c", [:mix], [{:hackney, "~> 1.0", [hex: :hackney, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: false]}], "hexpm"}, "exjsx": {:hex, :exjsx, "4.0.0", "60548841e0212df401e38e63c0078ec57b33e7ea49b032c796ccad8cde794b5c", [:mix], [{:jsx, "~> 2.8.0", [hex: :jsx, repo: "hexpm", optional: false]}], "hexpm"}, From 5b3aa851085becdf9131b7191f1ce530dd6128d0 Mon Sep 17 00:00:00 2001 From: "dependabot-preview[bot]" Date: Mon, 3 Jun 2019 22:15:45 +0000 Subject: [PATCH 850/860] [Security] Bump sshpk from 1.13.1 to 1.16.1 Bumps [sshpk](https://github.com/joyent/node-sshpk) from 1.13.1 to 1.16.1. **This update includes security fixes.** - [Release notes](https://github.com/joyent/node-sshpk/releases) - [Commits](https://github.com/joyent/node-sshpk/compare/v1.13.1...v1.16.1) --- yarn.lock | 29 ++++++++++++++++++----------- 1 file changed, 18 insertions(+), 11 deletions(-) diff --git a/yarn.lock b/yarn.lock index 9aec577d..2cfcf27c 100644 --- a/yarn.lock +++ b/yarn.lock @@ -209,8 +209,10 @@ arrify@^1.0.0, arrify@^1.0.1: resolved "https://registry.yarnpkg.com/arrify/-/arrify-1.0.1.tgz#898508da2226f380df904728456849c1501a4b0d" asn1@~0.2.3: - version "0.2.3" - resolved "https://registry.yarnpkg.com/asn1/-/asn1-0.2.3.tgz#dac8787713c9966849fc8180777ebe9c1ddf3b86" + version "0.2.4" + resolved "https://registry.yarnpkg.com/asn1/-/asn1-0.2.4.tgz#8d2475dfab553bb33e77b54e59e880bb8ce23136" + dependencies: + safer-buffer "~2.1.0" assert-plus@1.0.0, assert-plus@^1.0.0: version "1.0.0" @@ -1084,8 +1086,8 @@ balanced-match@^1.0.0: resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.0.tgz#89b4d199ab2bee49de164ea02b89ce462d71b767" bcrypt-pbkdf@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.1.tgz#63bc5dcb61331b92bc05fd528953c33462a06f8d" + version "1.0.2" + resolved "https://registry.yarnpkg.com/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz#a4301d389b6a43f9b67ff3ca11a3f6637e360e9e" dependencies: tweetnacl "^0.14.3" @@ -1601,10 +1603,11 @@ duplexer3@^0.1.4: resolved "https://registry.yarnpkg.com/duplexer3/-/duplexer3-0.1.4.tgz#ee01dd1cac0ed3cbc7fdbea37dc0a8f1ce002ce2" ecc-jsbn@~0.1.1: - version "0.1.1" - resolved "https://registry.yarnpkg.com/ecc-jsbn/-/ecc-jsbn-0.1.1.tgz#0fc73a9ed5f0d53c38193398523ef7e543777505" + version "0.1.2" + resolved "https://registry.yarnpkg.com/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz#3a83a904e54353287874c564b7549386849a98c9" dependencies: jsbn "~0.1.0" + safer-buffer "^2.1.0" electron-to-chromium@^1.3.14: version "1.3.14" @@ -3608,6 +3611,10 @@ safe-buffer@^5.0.1, safe-buffer@^5.1.1, safe-buffer@~5.1.0: version "5.1.1" resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.1.tgz#893312af69b2123def71f57889001671eeb2c853" +safer-buffer@^2.0.2, safer-buffer@^2.1.0, safer-buffer@~2.1.0: + version "2.1.2" + resolved "https://registry.yarnpkg.com/safer-buffer/-/safer-buffer-2.1.2.tgz#44fa161b0187b9549dd84bb91802f9bd8385cd6a" + semver-diff@^2.0.0: version "2.1.0" resolved "https://registry.yarnpkg.com/semver-diff/-/semver-diff-2.1.0.tgz#4bbb8437c8d37e4b0cf1a68fd726ec6d645d6d36" @@ -3716,17 +3723,17 @@ sprintf-js@~1.0.2: resolved "https://registry.yarnpkg.com/sprintf-js/-/sprintf-js-1.0.3.tgz#04e6926f662895354f3dd015203633b857297e2c" sshpk@^1.7.0: - version "1.13.1" - resolved "https://registry.yarnpkg.com/sshpk/-/sshpk-1.13.1.tgz#512df6da6287144316dc4c18fe1cf1d940739be3" + version "1.16.1" + resolved "https://registry.yarnpkg.com/sshpk/-/sshpk-1.16.1.tgz#fb661c0bef29b39db40769ee39fa70093d6f6877" dependencies: asn1 "~0.2.3" assert-plus "^1.0.0" - dashdash "^1.12.0" - getpass "^0.1.1" - optionalDependencies: bcrypt-pbkdf "^1.0.0" + dashdash "^1.12.0" ecc-jsbn "~0.1.1" + getpass "^0.1.1" jsbn "~0.1.0" + safer-buffer "^2.0.2" tweetnacl "~0.14.0" stack-utils@^1.0.0: From 41721f2f8b375abafde32209e7941e35ab175663 Mon Sep 17 00:00:00 2001 From: "dependabot-preview[bot]" Date: Mon, 3 Jun 2019 22:16:12 +0000 Subject: [PATCH 851/860] [Security] Bump stringstream from 0.0.5 to 0.0.6 Bumps [stringstream](https://github.com/mhart/StringStream) from 0.0.5 to 0.0.6. **This update includes security fixes.** - [Release notes](https://github.com/mhart/StringStream/releases) - [Commits](https://github.com/mhart/StringStream/compare/v0.0.5...v0.0.6) --- yarn.lock | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/yarn.lock b/yarn.lock index 9aec577d..3c14f2b6 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3762,8 +3762,8 @@ string_decoder@~1.0.0: safe-buffer "~5.1.0" stringstream@~0.0.4: - version "0.0.5" - resolved "https://registry.yarnpkg.com/stringstream/-/stringstream-0.0.5.tgz#4e484cd4de5a0bbbee18e46307710a8a81621878" + version "0.0.6" + resolved "https://registry.yarnpkg.com/stringstream/-/stringstream-0.0.6.tgz#7880225b0d4ad10e30927d167a1d6f2fd3b33a72" strip-ansi@^3.0.0, strip-ansi@^3.0.1: version "3.0.1" From 6bfe65c2764d5f390c218fd1dabaf7a150509fac Mon Sep 17 00:00:00 2001 From: "dependabot-preview[bot]" Date: Mon, 3 Jun 2019 22:16:40 +0000 Subject: [PATCH 852/860] [Security] Bump tar from 2.2.1 to 2.2.2 Bumps [tar](https://github.com/npm/node-tar) from 2.2.1 to 2.2.2. **This update includes security fixes.** - [Release notes](https://github.com/npm/node-tar/releases) - [Commits](https://github.com/npm/node-tar/compare/v2.2.1...v2.2.2) --- yarn.lock | 41 +++++++++++++++++++++++++++++++---------- 1 file changed, 31 insertions(+), 10 deletions(-) diff --git a/yarn.lock b/yarn.lock index 9aec577d..fa642e61 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1122,8 +1122,8 @@ boxen@^1.0.0: widest-line "^1.0.0" brace-expansion@^1.1.7: - version "1.1.8" - resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.8.tgz#c07b211c7c952ec1f8efd51a77ef0d1d3990a292" + version "1.1.11" + resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.11.tgz#3c7fcbf529d87226f3d2f52b966ff5271eb441dd" dependencies: balanced-match "^1.0.0" concat-map "0.0.1" @@ -1976,9 +1976,9 @@ fstream-ignore@^1.0.5: inherits "2" minimatch "^3.0.0" -fstream@^1.0.0, fstream@^1.0.10, fstream@^1.0.2: - version "1.0.11" - resolved "https://registry.yarnpkg.com/fstream/-/fstream-1.0.11.tgz#5c1fb1f117477114f0632a0eb4b71b3cb0fd3171" +fstream@^1.0.0, fstream@^1.0.10, fstream@^1.0.12: + version "1.0.12" + resolved "https://registry.yarnpkg.com/fstream/-/fstream-1.0.12.tgz#4e8ba8ee2d48be4f7d0de505455548eae5932045" dependencies: graceful-fs "^4.1.2" inherits "~2.0.0" @@ -2063,6 +2063,17 @@ glob@^7.0.3, glob@^7.0.5, glob@^7.0.6, glob@^7.1.2: once "^1.3.0" path-is-absolute "^1.0.0" +glob@^7.1.3: + version "7.1.4" + resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.4.tgz#aa608a2f6c577ad357e1ae5a5c26d9a8d1969255" + dependencies: + fs.realpath "^1.0.0" + inflight "^1.0.4" + inherits "2" + minimatch "^3.0.4" + once "^1.3.0" + path-is-absolute "^1.0.0" + globals@^9.0.0, globals@^9.17.0, globals@^9.18.0: version "9.18.0" resolved "https://registry.yarnpkg.com/globals/-/globals-9.18.0.tgz#aa3896b3e69b487f17e31ed2143d69a8e30c2d8a" @@ -2104,10 +2115,14 @@ got@^6.7.1: unzip-response "^2.0.1" url-parse-lax "^1.0.0" -graceful-fs@^4.1.11, graceful-fs@^4.1.2: +graceful-fs@^4.1.11: version "4.1.11" resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.1.11.tgz#0e8bdfe4d1ddb8854d64e04ea7c00e2a026e5658" +graceful-fs@^4.1.2: + version "4.1.15" + resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.1.15.tgz#ffb703e1066e8a0eeaa4c8b80ba9253eeefbfb00" + grapheme-splitter@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/grapheme-splitter/-/grapheme-splitter-1.0.2.tgz#639e9dc1bf065892c643de31daa27cf58b1068e2" @@ -3531,7 +3546,13 @@ right-align@^0.1.1: dependencies: align-text "^0.1.1" -rimraf@2, rimraf@^2.2.8, rimraf@^2.3.3, rimraf@^2.5.1, rimraf@^2.5.4, rimraf@^2.6.1: +rimraf@2: + version "2.6.3" + resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.6.3.tgz#b2d104fe0d8fb27cf9e0a1cda8262dd3833c6cab" + dependencies: + glob "^7.1.3" + +rimraf@^2.2.8, rimraf@^2.3.3, rimraf@^2.5.1, rimraf@^2.5.4, rimraf@^2.6.1: version "2.6.1" resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.6.1.tgz#c2338ec643df7a1b7fe5c54fa86f57428a55f33d" dependencies: @@ -3866,11 +3887,11 @@ tar-pack@^3.4.0: uid-number "^0.0.6" tar@^2.2.1: - version "2.2.1" - resolved "https://registry.yarnpkg.com/tar/-/tar-2.2.1.tgz#8e4d2a256c0e2185c6b18ad694aec968b83cb1d1" + version "2.2.2" + resolved "https://registry.yarnpkg.com/tar/-/tar-2.2.2.tgz#0ca8848562c7299b8b446ff6a4d60cdbb23edc40" dependencies: block-stream "*" - fstream "^1.0.2" + fstream "^1.0.12" inherits "2" term-size@^0.1.0: From 7e42592a400f02937eaad02fbc1c7a3020ca3393 Mon Sep 17 00:00:00 2001 From: "dependabot-preview[bot]" Date: Mon, 3 Jun 2019 22:17:02 +0000 Subject: [PATCH 853/860] [Security] Bump tough-cookie from 2.3.2 to 2.3.4 Bumps [tough-cookie](https://github.com/salesforce/tough-cookie) from 2.3.2 to 2.3.4. **This update includes security fixes.** - [Release notes](https://github.com/salesforce/tough-cookie/releases) - [Commits](https://github.com/salesforce/tough-cookie/compare/v2.3.2...v2.3.4) --- yarn.lock | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/yarn.lock b/yarn.lock index 9aec577d..57e6aee8 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3932,8 +3932,8 @@ to-fast-properties@^1.0.1, to-fast-properties@^1.0.3: resolved "https://registry.yarnpkg.com/to-fast-properties/-/to-fast-properties-1.0.3.tgz#b83571fa4d8c25b82e231b06e3a3055de4ca1a47" tough-cookie@~2.3.0: - version "2.3.2" - resolved "https://registry.yarnpkg.com/tough-cookie/-/tough-cookie-2.3.2.tgz#f081f76e4c85720e6c37a5faced737150d84072a" + version "2.3.4" + resolved "https://registry.yarnpkg.com/tough-cookie/-/tough-cookie-2.3.4.tgz#ec60cee38ac675063ffc97a5c18970578ee83655" dependencies: punycode "^1.4.1" From ecd3c0a39684c2ac9e4f8043bc9c7bdf20b8cab2 Mon Sep 17 00:00:00 2001 From: "dependabot-preview[bot]" Date: Tue, 4 Jun 2019 00:01:24 +0000 Subject: [PATCH 854/860] Bump eslint from 4.6.1 to 4.19.1 Bumps [eslint](https://github.com/eslint/eslint) from 4.6.1 to 4.19.1. - [Release notes](https://github.com/eslint/eslint/releases) - [Changelog](https://github.com/eslint/eslint/blob/master/CHANGELOG.md) - [Commits](https://github.com/eslint/eslint/compare/v4.6.1...v4.19.1) --- yarn.lock | 179 ++++++++++++++++++++++++++++-------------------------- 1 file changed, 94 insertions(+), 85 deletions(-) diff --git a/yarn.lock b/yarn.lock index 052816ce..08569965 100644 --- a/yarn.lock +++ b/yarn.lock @@ -70,25 +70,29 @@ acorn@^5.1.1: version "5.1.2" resolved "https://registry.yarnpkg.com/acorn/-/acorn-5.1.2.tgz#911cb53e036807cf0fa778dc5d370fbd864246d7" -ajv-keywords@^1.0.0: - version "1.5.1" - resolved "https://registry.yarnpkg.com/ajv-keywords/-/ajv-keywords-1.5.1.tgz#314dd0a4b3368fad3dfcdc54ede6171b886daf3c" +acorn@^5.5.0: + version "5.7.3" + resolved "https://registry.yarnpkg.com/acorn/-/acorn-5.7.3.tgz#67aa231bf8812974b85235a96771eb6bd07ea279" -ajv@^4.7.0, ajv@^4.9.1: +ajv-keywords@^2.1.0: + version "2.1.1" + resolved "https://registry.yarnpkg.com/ajv-keywords/-/ajv-keywords-2.1.1.tgz#617997fc5f60576894c435f940d819e135b80762" + +ajv@^4.9.1: version "4.11.8" resolved "https://registry.yarnpkg.com/ajv/-/ajv-4.11.8.tgz#82ffb02b29e662ae53bdc20af15947706739c536" dependencies: co "^4.6.0" json-stable-stringify "^1.0.1" -ajv@^5.2.0: - version "5.2.2" - resolved "https://registry.yarnpkg.com/ajv/-/ajv-5.2.2.tgz#47c68d69e86f5d953103b0074a9430dc63da5e39" +ajv@^5.2.3, ajv@^5.3.0: + version "5.5.2" + resolved "https://registry.yarnpkg.com/ajv/-/ajv-5.5.2.tgz#73b5eeca3fab653e3d3f9422b341ad42205dc965" dependencies: co "^4.6.0" fast-deep-equal "^1.0.0" + fast-json-stable-stringify "^2.0.0" json-schema-traverse "^0.3.0" - json-stable-stringify "^1.0.1" align-text@^0.1.1, align-text@^0.1.3: version "0.1.4" @@ -339,15 +343,7 @@ aws4@^1.2.1: version "1.6.0" resolved "https://registry.yarnpkg.com/aws4/-/aws4-1.6.0.tgz#83ef5ca860b2b32e4a0deedee8c771b9db57471e" -babel-code-frame@^6.22.0: - version "6.22.0" - resolved "https://registry.yarnpkg.com/babel-code-frame/-/babel-code-frame-6.22.0.tgz#027620bee567a88c32561574e7fd0801d33118e4" - dependencies: - chalk "^1.1.0" - esutils "^2.0.2" - js-tokens "^3.0.0" - -babel-code-frame@^6.26.0: +babel-code-frame@^6.22.0, babel-code-frame@^6.26.0: version "6.26.0" resolved "https://registry.yarnpkg.com/babel-code-frame/-/babel-code-frame-6.26.0.tgz#63fd43f7dc1e3bb7ce35947db8fe369a3f58c74b" dependencies: @@ -1238,7 +1234,7 @@ chalk@^0.4.0: has-color "~0.1.0" strip-ansi "~0.1.0" -chalk@^1.0.0, chalk@^1.1.0, chalk@^1.1.1, chalk@^1.1.3: +chalk@^1.0.0, chalk@^1.1.1, chalk@^1.1.3: version "1.1.3" resolved "https://registry.yarnpkg.com/chalk/-/chalk-1.1.3.tgz#a8115c55e4a702fe4d150abd3872822a7e09fc98" dependencies: @@ -1248,15 +1244,7 @@ chalk@^1.0.0, chalk@^1.1.0, chalk@^1.1.1, chalk@^1.1.3: strip-ansi "^3.0.0" supports-color "^2.0.0" -chalk@^2.0.0, chalk@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.0.1.tgz#dbec49436d2ae15f536114e76d14656cdbc0f44d" - dependencies: - ansi-styles "^3.1.0" - escape-string-regexp "^1.0.5" - supports-color "^4.0.0" - -chalk@^2.1.0: +chalk@^2.0.0, chalk@^2.0.1, chalk@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.1.0.tgz#ac5becf14fa21b99c6c92ca7a7d7cfd5b17e743e" dependencies: @@ -1524,6 +1512,12 @@ debug@^2.1.1, debug@^2.2.0, debug@^2.6.3, debug@^2.6.8: dependencies: ms "2.0.0" +debug@^3.1.0: + version "3.2.6" + resolved "https://registry.yarnpkg.com/debug/-/debug-3.2.6.tgz#e83d17de16d8a7efb7717edbe5fb10135eee629b" + dependencies: + ms "^2.1.1" + decamelize@^1.0.0, decamelize@^1.1.1, decamelize@^1.1.2: version "1.2.0" resolved "https://registry.yarnpkg.com/decamelize/-/decamelize-1.2.0.tgz#f6534d15148269b20352e7bee26f501f9a191290" @@ -1583,12 +1577,11 @@ doctrine@1.5.0: esutils "^2.0.2" isarray "^1.0.0" -doctrine@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/doctrine/-/doctrine-2.0.0.tgz#c73d8d2909d22291e1a007a395804da8b665fe63" +doctrine@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/doctrine/-/doctrine-2.1.0.tgz#5cd01fc101621b42c4cd7f5d1a66243716d3f39d" dependencies: esutils "^2.0.2" - isarray "^1.0.0" dot-prop@^4.1.0: version "4.1.1" @@ -1685,32 +1678,36 @@ eslint-scope@^3.7.1: esrecurse "^4.1.0" estraverse "^4.1.1" +eslint-visitor-keys@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-1.0.0.tgz#3f3180fb2e291017716acb4c9d6d5b5c34a6a81d" + eslint@^4.6.1: - version "4.6.1" - resolved "https://registry.yarnpkg.com/eslint/-/eslint-4.6.1.tgz#ddc7fc7fd70bf93205b0b3449bb16a1e9e7d4950" + version "4.19.1" + resolved "https://registry.yarnpkg.com/eslint/-/eslint-4.19.1.tgz#32d1d653e1d90408854bfb296f076ec7e186a300" dependencies: - ajv "^5.2.0" + ajv "^5.3.0" babel-code-frame "^6.22.0" chalk "^2.1.0" concat-stream "^1.6.0" cross-spawn "^5.1.0" - debug "^2.6.8" - doctrine "^2.0.0" + debug "^3.1.0" + doctrine "^2.1.0" eslint-scope "^3.7.1" - espree "^3.5.0" + eslint-visitor-keys "^1.0.0" + espree "^3.5.4" esquery "^1.0.0" - estraverse "^4.2.0" esutils "^2.0.2" file-entry-cache "^2.0.0" functional-red-black-tree "^1.0.1" glob "^7.1.2" - globals "^9.17.0" + globals "^11.0.1" ignore "^3.3.3" imurmurhash "^0.1.4" inquirer "^3.0.6" is-resolvable "^1.0.0" js-yaml "^3.9.1" - json-stable-stringify "^1.0.1" + json-stable-stringify-without-jsonify "^1.0.1" levn "^0.3.0" lodash "^4.17.4" minimatch "^3.0.2" @@ -1718,13 +1715,14 @@ eslint@^4.6.1: natural-compare "^1.4.0" optionator "^0.8.2" path-is-inside "^1.0.2" - pluralize "^4.0.0" + pluralize "^7.0.0" progress "^2.0.0" + regexpp "^1.0.1" require-uncached "^1.0.3" semver "^5.3.0" strip-ansi "^4.0.0" strip-json-comments "~2.0.1" - table "^4.0.1" + table "4.0.2" text-table "~0.2.0" espower-location-detector@^1.0.0: @@ -1736,17 +1734,13 @@ espower-location-detector@^1.0.0: source-map "^0.5.0" xtend "^4.0.0" -espree@^3.5.0: - version "3.5.0" - resolved "https://registry.yarnpkg.com/espree/-/espree-3.5.0.tgz#98358625bdd055861ea27e2867ea729faf463d8d" +espree@^3.5.4: + version "3.5.4" + resolved "https://registry.yarnpkg.com/espree/-/espree-3.5.4.tgz#b0f447187c8a8bed944b815a660bddf5deb5d1a7" dependencies: - acorn "^5.1.1" + acorn "^5.5.0" acorn-jsx "^3.0.0" -esprima@^3.1.1: - version "3.1.3" - resolved "https://registry.yarnpkg.com/esprima/-/esprima-3.1.3.tgz#fdca51cee6133895e3c88d535ce49dbff62a4633" - esprima@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/esprima/-/esprima-4.0.0.tgz#4499eddcd1110e0b218bacf2fa7f7f59f55ca804" @@ -1770,7 +1764,7 @@ esrecurse@^4.1.0: estraverse "^4.1.0" object-assign "^4.0.1" -estraverse@^4.0.0, estraverse@^4.1.0, estraverse@^4.1.1, estraverse@^4.2.0: +estraverse@^4.0.0, estraverse@^4.1.0, estraverse@^4.1.1: version "4.2.0" resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-4.2.0.tgz#0dee3fed31fcd469618ce7342099fc1afa0bdb13" @@ -1855,6 +1849,10 @@ fast-diff@^1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/fast-diff/-/fast-diff-1.1.1.tgz#0aea0e4e605b6a2189f0e936d4b7fbaf1b7cfd9b" +fast-json-stable-stringify@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/fast-json-stable-stringify/-/fast-json-stable-stringify-2.0.0.tgz#d5142c0caee6b1189f87d3a76111064f86c8bbf2" + fast-levenshtein@~2.0.4: version "2.0.6" resolved "https://registry.yarnpkg.com/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz#3d8a5c66883a16a30ca8643e851f19baa7797917" @@ -2052,18 +2050,7 @@ glob-parent@^2.0.0: dependencies: is-glob "^2.0.0" -glob@^7.0.3, glob@^7.0.5, glob@^7.0.6, glob@^7.1.2: - version "7.1.2" - resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.2.tgz#c19c9df9a028702d678612384a6552404c636d15" - dependencies: - fs.realpath "^1.0.0" - inflight "^1.0.4" - inherits "2" - minimatch "^3.0.4" - once "^1.3.0" - path-is-absolute "^1.0.0" - -glob@^7.1.3: +glob@^7.0.3, glob@^7.0.5, glob@^7.0.6, glob@^7.1.2, glob@^7.1.3: version "7.1.4" resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.4.tgz#aa608a2f6c577ad357e1ae5a5c26d9a8d1969255" dependencies: @@ -2074,7 +2061,11 @@ glob@^7.1.3: once "^1.3.0" path-is-absolute "^1.0.0" -globals@^9.0.0, globals@^9.17.0, globals@^9.18.0: +globals@^11.0.1: + version "11.12.0" + resolved "https://registry.yarnpkg.com/globals/-/globals-11.12.0.tgz#ab8795338868a0babd8525758018c2a7eb95c42e" + +globals@^9.0.0, globals@^9.18.0: version "9.18.0" resolved "https://registry.yarnpkg.com/globals/-/globals-9.18.0.tgz#aa3896b3e69b487f17e31ed2143d69a8e30c2d8a" @@ -2559,14 +2550,7 @@ js-tokens@^3.0.2: version "3.0.2" resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-3.0.2.tgz#9866df395102130e38f7f996bceb65443209c25b" -js-yaml@^3.8.2: - version "3.8.4" - resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.8.4.tgz#520b4564f86573ba96662af85a8cafa7b4b5a6f6" - dependencies: - argparse "^1.0.7" - esprima "^3.1.1" - -js-yaml@^3.9.1: +js-yaml@^3.8.2, js-yaml@^3.9.1: version "3.9.1" resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.9.1.tgz#08775cebdfdd359209f0d2acd383c8f86a6904a0" dependencies: @@ -2597,6 +2581,10 @@ json-schema@0.2.3: version "0.2.3" resolved "https://registry.yarnpkg.com/json-schema/-/json-schema-0.2.3.tgz#b480c892e59a2f05954ce727bd3f2a4e882f9e13" +json-stable-stringify-without-jsonify@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz#9db7b59496ad3f3cfef30a75142d2d930ad72651" + json-stable-stringify@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/json-stable-stringify/-/json-stable-stringify-1.0.1.tgz#9a759d39c5f2ff503fd5300646ed445f88c4f9af" @@ -2735,7 +2723,7 @@ lodash.some@^4.6.0: version "4.6.0" resolved "https://registry.yarnpkg.com/lodash.some/-/lodash.some-4.6.0.tgz#1bb9f314ef6b8baded13b549169b2a945eb68e4d" -lodash@^4.0.0, lodash@^4.17.4, lodash@^4.2.0, lodash@^4.3.0: +lodash@^4.17.4, lodash@^4.2.0, lodash@^4.3.0: version "4.17.4" resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.4.tgz#78203a4d1c328ae1d86dca6460e369b57f4055ae" @@ -2888,6 +2876,10 @@ ms@2.0.0, ms@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/ms/-/ms-2.0.0.tgz#5608aeadfc00be6c2901df5f9861788de0d597c8" +ms@^2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.1.tgz#30a5864eb3ebb0a66f2ebe6d727af06a09d86e0a" + multimatch@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/multimatch/-/multimatch-2.1.0.tgz#9c7906a22fb4c02919e2f5f75161b4cdbd4b2a2b" @@ -3243,9 +3235,9 @@ plur@^2.0.0: dependencies: irregular-plurals "^1.0.0" -pluralize@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/pluralize/-/pluralize-4.0.0.tgz#59b708c1c0190a2f692f1c7618c446b052fd1762" +pluralize@^7.0.0: + version "7.0.0" + resolved "https://registry.yarnpkg.com/pluralize/-/pluralize-7.0.0.tgz#298b89df8b93b0221dbf421ad2b1b1ea23fc6777" prelude-ls@~1.1.2: version "1.1.2" @@ -3398,6 +3390,10 @@ regex-cache@^0.4.2: is-equal-shallow "^0.1.3" is-primitive "^2.0.0" +regexpp@^1.0.1: + version "1.1.0" + resolved "https://registry.yarnpkg.com/regexpp/-/regexpp-1.1.0.tgz#0e3516dd0b7904f413d2d4193dce4618c3a689ab" + regexpu-core@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/regexpu-core/-/regexpu-core-2.0.0.tgz#49d038837b8dcf8bfa5b9a42139938e6ea2ae240" @@ -3669,6 +3665,12 @@ slice-ansi@0.0.4: version "0.0.4" resolved "https://registry.yarnpkg.com/slice-ansi/-/slice-ansi-0.0.4.tgz#edbf8903f66f7ce2f8eafd6ceed65e264c831b35" +slice-ansi@1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/slice-ansi/-/slice-ansi-1.0.0.tgz#044f1a49d8842ff307aad6b505ed178bd950134d" + dependencies: + is-fullwidth-code-point "^2.0.0" + slide@^1.1.5: version "1.1.6" resolved "https://registry.yarnpkg.com/slide/-/slide-1.1.6.tgz#56eb027d65b4d2dce6cb2e2d32c4d4afc9e1d707" @@ -3776,6 +3778,13 @@ string-width@^2.1.0: is-fullwidth-code-point "^2.0.0" strip-ansi "^4.0.0" +string-width@^2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/string-width/-/string-width-2.1.1.tgz#ab93f27a8dc13d28cac815c462143a6d9012ae9e" + dependencies: + is-fullwidth-code-point "^2.0.0" + strip-ansi "^4.0.0" + string_decoder@~1.0.0: version "1.0.3" resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.0.3.tgz#0fc67d7c141825de94282dd536bec6b9bce860ab" @@ -3856,16 +3865,16 @@ symbol-observable@^1.0.4: version "1.0.4" resolved "https://registry.yarnpkg.com/symbol-observable/-/symbol-observable-1.0.4.tgz#29bf615d4aa7121bdd898b22d4b3f9bc4e2aa03d" -table@^4.0.1: - version "4.0.1" - resolved "https://registry.yarnpkg.com/table/-/table-4.0.1.tgz#a8116c133fac2c61f4a420ab6cdf5c4d61f0e435" +table@4.0.2: + version "4.0.2" + resolved "https://registry.yarnpkg.com/table/-/table-4.0.2.tgz#a33447375391e766ad34d3486e6e2aedc84d2e36" dependencies: - ajv "^4.7.0" - ajv-keywords "^1.0.0" - chalk "^1.1.1" - lodash "^4.0.0" - slice-ansi "0.0.4" - string-width "^2.0.0" + ajv "^5.2.3" + ajv-keywords "^2.1.0" + chalk "^2.1.0" + lodash "^4.17.4" + slice-ansi "1.0.0" + string-width "^2.1.1" tailored@^2.7.4: version "2.7.4" From b9ceea03ca066e6233b92983aa3dd45c83e89a73 Mon Sep 17 00:00:00 2001 From: workingjubilee Date: Sun, 18 Aug 2019 15:55:54 -0700 Subject: [PATCH 855/860] Solves easy lints --- src/javascript/tests/core/erlang_compat/maps_spec.js | 4 +--- src/javascript/tests/with.spec.js | 4 ++-- 2 files changed, 3 insertions(+), 5 deletions(-) diff --git a/src/javascript/tests/core/erlang_compat/maps_spec.js b/src/javascript/tests/core/erlang_compat/maps_spec.js index 1a504227..31a20dcd 100644 --- a/src/javascript/tests/core/erlang_compat/maps_spec.js +++ b/src/javascript/tests/core/erlang_compat/maps_spec.js @@ -67,9 +67,7 @@ test('put/3', (t) => { test('take/2', (t) => { const myMap = new Map([['a', 1], ['b', 2]]); - let a; - let result; - [a, result] = Core.maps.take('a', myMap); + const [a, result] = Core.maps.take('a', myMap); t.is(a, 1); t.is(result.has('a'), false); }); diff --git a/src/javascript/tests/with.spec.js b/src/javascript/tests/with.spec.js index 0ac09ced..31fb2c49 100644 --- a/src/javascript/tests/with.spec.js +++ b/src/javascript/tests/with.spec.js @@ -1,5 +1,5 @@ -import Core from '../lib/core'; import test from 'ava'; +import Core from '../lib/core'; const Patterns = Core.Patterns; const SpecialForms = Core.SpecialForms; @@ -31,7 +31,7 @@ test('with', (t) => { const value = SpecialForms._with( [new Tuple(Symbol.for('ok'), $), () => map_fetch(opts, 'width')], - [new Tuple(Symbol.for('ok'), $), width => map_fetch(opts, 'height')], + [new Tuple(Symbol.for('ok'), $), () => map_fetch(opts, 'height')], (width, height) => new Tuple(Symbol.for('ok'), width * height), ); From d8db026eb453bbd2547c1d89777540e314c66d6e Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Mon, 19 Aug 2019 12:56:40 -0500 Subject: [PATCH 856/860] Update .travis.yml --- .travis.yml | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/.travis.yml b/.travis.yml index 5dbed2d0..86b63471 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,13 +1,16 @@ sudo: false language: elixir elixir: - - 1.6.0 + - 1.9 otp_release: - - 20.2 -env: - - TRAVIS_NODE_VERSION="8" + - 22.0 +cache: + directories: + - _build + - deps + - node_modules install: - - rm -rf ~/.nvm && git clone https://github.com/creationix/nvm.git ~/.nvm && (cd ~/.nvm && git checkout `git describe --abbrev=0 --tags`) && source ~/.nvm/nvm.sh && nvm install $TRAVIS_NODE_VERSION + - nvm install 12.8.0 && nvm use 12.8.0 - npm install -g yarn - yarn - mix local.hex --force From 44cb70c49615261267fba374347ecf4d50c7e01d Mon Sep 17 00:00:00 2001 From: workingjubilee Date: Mon, 19 Aug 2019 23:54:53 -0700 Subject: [PATCH 857/860] Disables "no-console" linting in extant test files --- .eslintrc.js | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/.eslintrc.js b/.eslintrc.js index 3b27e64a..24dfa7ae 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -8,6 +8,14 @@ module.exports = { 'import/extensions': 'off', 'import/no-extraneous-dependencies': ['error', { devDependencies: true }], }, + 'overrides': [ + { + 'files': ['*spec.js', 'priv/testrunner/**/*'], + 'rules': { + 'no-console': 'off' + } + } + ], extends: 'airbnb-base', plugins: ['import'], env: { From fab74b8b187c9700415bb5501fa11b783edb4c91 Mon Sep 17 00:00:00 2001 From: workingjubilee Date: Mon, 19 Aug 2019 23:55:53 -0700 Subject: [PATCH 858/860] Disable "no-console" linting for specific console.warns These all are exceptional cases of warnings where the warning is far more important than adhering to a style guide on lints, even if some of them might potentially show up in the browser. Each is a hand-picked exception, so these use in-file comment overrides. Rationales are included in preceding comments. --- src/javascript/lib/core.js | 5 +++++ src/javascript/lib/core/erlang_compat/elixir_errors.js | 4 ++++ src/javascript/lib/core/erlang_compat/io.js | 2 ++ src/javascript/lib/core/special_forms.js | 3 +++ 4 files changed, 14 insertions(+) diff --git a/src/javascript/lib/core.js b/src/javascript/lib/core.js index 093816c2..7f87d1da 100644 --- a/src/javascript/lib/core.js +++ b/src/javascript/lib/core.js @@ -27,7 +27,12 @@ function get_global() { return global; } + /* As long as the window check precedes this, it won't display in a browser, + unless the ground cracks open and swallows JavaScript whole. */ + /* eslint-disable no-console */ console.warn('No global state found'); + /* eslint-enable no-console */ + return null; } diff --git a/src/javascript/lib/core/erlang_compat/elixir_errors.js b/src/javascript/lib/core/erlang_compat/elixir_errors.js index 9e68f5dc..c6b5d22b 100644 --- a/src/javascript/lib/core/erlang_compat/elixir_errors.js +++ b/src/javascript/lib/core/erlang_compat/elixir_errors.js @@ -1,7 +1,11 @@ +/* It is far too "meta" to warn about including a warning in a warning */ +/* eslint-disable no-console */ + function warn(message) { const messageString = message.join(''); console.warn(`warning: ${messageString}`); + return Symbol.for('ok'); } diff --git a/src/javascript/lib/core/erlang_compat/io.js b/src/javascript/lib/core/erlang_compat/io.js index bf1d49dc..abff3f57 100644 --- a/src/javascript/lib/core/erlang_compat/io.js +++ b/src/javascript/lib/core/erlang_compat/io.js @@ -1,3 +1,5 @@ +/* The purpose of this module is, in fact, to do IO. */ +/* eslint-disable no-console */ import erlang from './erlang'; function put_chars(ioDevice, charData) { diff --git a/src/javascript/lib/core/special_forms.js b/src/javascript/lib/core/special_forms.js index 7964bf3d..7721612b 100644 --- a/src/javascript/lib/core/special_forms.js +++ b/src/javascript/lib/core/special_forms.js @@ -138,7 +138,10 @@ function _with(...args) { } function receive(clauses, timeout = 0, timeoutFn = () => true) { + /* It's more important to warn developers than follow style guides */ + /* eslint-disable no-console */ console.warn('Receive not supported'); + /* eslint-enable no-console */ const messages = []; // this.mailbox.get(); const NOMATCH = Symbol('NOMATCH'); From 3ccd8e04267de15613a49813b8b75ff23d1798d4 Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Tue, 20 Aug 2019 09:01:45 -0500 Subject: [PATCH 859/860] Update js deps --- .eslintrc.js | 4 +- .formatter.exs | 4 + .tool-versions | 6 +- .travis.yml | 11 +- CONTRIBUTING.md | 112 +- Makefile | 6 +- package-lock.json | 6511 +++++++++++++++++++++++++++++++ package.json | 18 +- priv/testrunner/esm/index.js | 59 +- priv/testrunner/vendor.build.js | 4 +- rollup.config.js | 41 +- yarn.lock | 4242 -------------------- 12 files changed, 6646 insertions(+), 4372 deletions(-) create mode 100644 .formatter.exs create mode 100644 package-lock.json delete mode 100644 yarn.lock diff --git a/.eslintrc.js b/.eslintrc.js index 3b27e64a..f7b15d25 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -6,7 +6,7 @@ module.exports = { 'no-restricted-syntax': 'off', 'no-underscore-dangle': 'off', 'import/extensions': 'off', - 'import/no-extraneous-dependencies': ['error', { devDependencies: true }], + 'import/no-extraneous-dependencies': ['error', {devDependencies: true}], }, extends: 'airbnb-base', plugins: ['import'], @@ -15,4 +15,4 @@ module.exports = { node: true, mocha: true, }, -}; +} diff --git a/.formatter.exs b/.formatter.exs new file mode 100644 index 00000000..562e8863 --- /dev/null +++ b/.formatter.exs @@ -0,0 +1,4 @@ +[ + import_deps: [:phoenix], + inputs: ["*.{ex,exs}", "{config,lib,priv,test}/**/*.{ex,exs}"] +] diff --git a/.tool-versions b/.tool-versions index fee73d5a..000eeb3e 100644 --- a/.tool-versions +++ b/.tool-versions @@ -1,3 +1,3 @@ -erlang 20.3 -elixir 1.6.5-otp-20 -nodejs 8.9.1 +erlang 22.0 +elixir 1.9.1-otp-22 +nodejs 12.8.1 diff --git a/.travis.yml b/.travis.yml index 86b63471..43916696 100644 --- a/.travis.yml +++ b/.travis.yml @@ -10,9 +10,8 @@ cache: - deps - node_modules install: - - nvm install 12.8.0 && nvm use 12.8.0 - - npm install -g yarn - - yarn + - nvm install 12.8.1 && nvm use 12.8.1 + - npm install - mix local.hex --force - mix local.rebar --force - mix deps.get @@ -23,6 +22,6 @@ notifications: webhooks: urls: - https://webhooks.gitter.im/e/fbd8944d285c0696dc41 - on_success: always # options: [always|never|change] default: always - on_failure: always # options: [always|never|change] default: always - on_start: never # options: [always|never|change] default: always + on_success: always # options: [always|never|change] default: always + on_failure: always # options: [always|never|change] default: always + on_start: never # options: [always|never|change] default: always diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 9be626f1..56fcb028 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -6,9 +6,9 @@ This contributing guide is based on the contributing for Elixir with changes sui Use the issues tracker for: -* [bug reports](#bug-reports) -* [submitting pull requests](#pull-requests) -* [feature requests](#feature-requests) +- [bug reports](#bug-reports) +- [submitting pull requests](#pull-requests) +- [feature requests](#feature-requests) ## Bug reports @@ -51,7 +51,7 @@ Example: ## Feature requests Feature requests are welcome. But take a moment to find -out whether your idea fits with the scope and aims of the project. It's up to *you* +out whether your idea fits with the scope and aims of the project. It's up to _you_ to make a strong case to convince the community of the merits of this feature. Please provide as much detail and context as possible. @@ -63,18 +63,18 @@ found in Elixir in ElixirScript. ElixirScript is broken up into the following parts: -* The compiler, written in Elixir -* The JavaScript core +- The compiler, written in Elixir +- The JavaScript core -The ElixirScript compiler is in the `lib` folder of the project. +The ElixirScript compiler is in the `lib` folder of the project. Here is where Elixir code is converted into JavaScript. -The JavaScript code is in the `src/javascript`. +The JavaScript code is in the `src/javascript`. This is where the special forms and the Erlang Compatibility Layer are defined -The ElixirScript tests can be run using `mix test` +The ElixirScript tests are ran using `mix test` -The JavaScript tests can be run using `yarn test` +The JavaScript tests are ran using `npm test` Please make sure all tests pass after making changes. Also make sure to include tests for the changes you made. @@ -104,72 +104,72 @@ documentation. When working with Git, we recommend the following process in order to craft an excellent pull request: 1. [Fork](https://help.github.com/fork-a-repo/) the project, clone your fork, - and configure the remotes: + and configure the remotes: - ```sh - # Clone your fork of the repo into the current directory - git clone https://github.com//elixirscript - # Navigate to the newly cloned directory - cd elixirscript - # Assign the original repo to a remote called "upstream" - git remote add upstream https://github.com/elixirscript/elixirscript - ``` +```sh +# Clone your fork of the repo into the current directory +git clone https://github.com//elixirscript +# Navigate to the newly cloned directory +cd elixirscript +# Assign the original repo to a remote called "upstream" +git remote add upstream https://github.com/elixirscript/elixirscript +``` 2. If you cloned a while ago, get the latest changes from upstream: - ```sh - git checkout master - git pull upstream master - ``` +```sh +git checkout master +git pull upstream master +``` 3. Create a new topic branch (off of `master`) to contain your feature, change, - or fix. + or fix. - **IMPORTANT**: Making changes in `master` is discouraged. You should always - keep your local `master` in sync with upstream `master` and make your - changes in topic branches. + **IMPORTANT**: Making changes in `master` is discouraged. You should always + keep your local `master` in sync with upstream `master` and make your + changes in topic branches. - ```sh - git checkout -b - ``` +```sh +git checkout -b +``` 4. Commit your changes in logical chunks. Keep your commit messages organized, - with a short description in the first line and more detailed information on - the following lines. Feel free to use Git's - [interactive rebase](https://help.github.com/articles/interactive-rebase) - feature to tidy up your commits before making them public. + with a short description in the first line and more detailed information on + the following lines. Feel free to use Git's + [interactive rebase](https://help.github.com/articles/interactive-rebase) + feature to tidy up your commits before making them public. 5. Make sure all the tests are still passing. - ```sh - mix test - yarn test - ``` +```sh +mix test +npm test +``` - This is needed to ensure your changes can - pass all the tests. +This is needed to ensure your changes can +pass all the tests. 6. Push your topic branch up to your fork: - ```sh - git push origin - ``` +```sh +git push origin +``` 7. [Open a Pull Request](https://help.github.com/articles/using-pull-requests/) - with a clear title and description. + with a clear title and description. 8. If you haven't updated your pull request for a while, you should consider - rebasing on master and resolving any conflicts. - - **IMPORTANT**: _Never ever_ merge upstream `master` into your branches. You - should always `git rebase` on `master` to bring your changes up to date when - necessary. - - ```sh - git checkout master - git pull upstream master - git checkout - git rebase master - ``` + rebasing on master and resolving any conflicts. + + **IMPORTANT**: _Never ever_ merge upstream `master` into your branches. You + should always `git rebase` on `master` to bring your changes up to date when + necessary. + +```sh +git checkout master +git pull upstream master +git checkout +git rebase master +``` Thank you for your contributions! diff --git a/Makefile b/Makefile index d717c5c5..9ede1be1 100644 --- a/Makefile +++ b/Makefile @@ -5,7 +5,7 @@ default: deps compile compile: js_compile elixir_compile js_compile: - yarn build + npm run build elixir_compile: mix compile @@ -13,7 +13,7 @@ elixir_compile: test: js_compile elixir_test js_test js_test: - yarn test + npm test elixir_test: mix test --cover @@ -29,4 +29,4 @@ elixir_deps: mix deps.get js_deps: - yarn + npm install diff --git a/package-lock.json b/package-lock.json new file mode 100644 index 00000000..58a35a9a --- /dev/null +++ b/package-lock.json @@ -0,0 +1,6511 @@ +{ + "name": "elixirscript", + "version": "0.26.1", + "lockfileVersion": 1, + "requires": true, + "dependencies": { + "@ava/babel-plugin-throws-helper": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/@ava/babel-plugin-throws-helper/-/babel-plugin-throws-helper-4.0.0.tgz", + "integrity": "sha512-3diBLIVBPPh3j4+hb5lo0I1D+S/O/VDJPI4Y502apBxmwEqjyXG4gTSPFUlm41sSZeZzMarT/Gzovw9kV7An0w==", + "dev": true + }, + "@ava/babel-preset-stage-4": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/@ava/babel-preset-stage-4/-/babel-preset-stage-4-4.0.0.tgz", + "integrity": "sha512-lZEV1ZANzfzSYBU6WHSErsy7jLPbD1iIgAboASPMcKo7woVni5/5IKWeT0RxC8rY802MFktur3OKEw2JY1Tv2w==", + "dev": true, + "requires": { + "@babel/plugin-proposal-async-generator-functions": "^7.2.0", + "@babel/plugin-proposal-dynamic-import": "^7.5.0", + "@babel/plugin-proposal-optional-catch-binding": "^7.2.0", + "@babel/plugin-transform-dotall-regex": "^7.4.4", + "@babel/plugin-transform-modules-commonjs": "^7.5.0" + } + }, + "@ava/babel-preset-transform-test-files": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/@ava/babel-preset-transform-test-files/-/babel-preset-transform-test-files-6.0.0.tgz", + "integrity": "sha512-8eKhFzZp7Qcq1VLfoC75ggGT8nQs9q8fIxltU47yCB7Wi7Y8Qf6oqY1Bm0z04fIec24vEgr0ENhDHEOUGVDqnA==", + "dev": true, + "requires": { + "@ava/babel-plugin-throws-helper": "^4.0.0", + "babel-plugin-espower": "^3.0.1" + } + }, + "@babel/code-frame": { + "version": "7.5.5", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.5.5.tgz", + "integrity": "sha512-27d4lZoomVyo51VegxI20xZPuSHusqbQag/ztrBC7wegWoQ1nLREPVSKSW8byhTlzTKyNE4ifaTA6lCp7JjpFw==", + "dev": true, + "requires": { + "@babel/highlight": "^7.0.0" + } + }, + "@babel/core": { + "version": "7.5.5", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.5.5.tgz", + "integrity": "sha512-i4qoSr2KTtce0DmkuuQBV4AuQgGPUcPXMr9L5MyYAtk06z068lQ10a4O009fe5OB/DfNV+h+qqT7ddNV8UnRjg==", + "dev": true, + "requires": { + "@babel/code-frame": "^7.5.5", + "@babel/generator": "^7.5.5", + "@babel/helpers": "^7.5.5", + "@babel/parser": "^7.5.5", + "@babel/template": "^7.4.4", + "@babel/traverse": "^7.5.5", + "@babel/types": "^7.5.5", + "convert-source-map": "^1.1.0", + "debug": "^4.1.0", + "json5": "^2.1.0", + "lodash": "^4.17.13", + "resolve": "^1.3.2", + "semver": "^5.4.1", + "source-map": "^0.5.0" + }, + "dependencies": { + "debug": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", + "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", + "dev": true, + "requires": { + "ms": "^2.1.1" + } + }, + "json5": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/json5/-/json5-2.1.0.tgz", + "integrity": "sha512-8Mh9h6xViijj36g7Dxi+Y4S6hNGV96vcJZr/SrlHh1LR/pEn/8j/+qIBbs44YKl69Lrfctp4QD+AdWLTMqEZAQ==", + "dev": true, + "requires": { + "minimist": "^1.2.0" + } + }, + "minimist": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", + "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=", + "dev": true + } + } + }, + "@babel/generator": { + "version": "7.5.5", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.5.5.tgz", + "integrity": "sha512-ETI/4vyTSxTzGnU2c49XHv2zhExkv9JHLTwDAFz85kmcwuShvYG2H08FwgIguQf4JC75CBnXAUM5PqeF4fj0nQ==", + "dev": true, + "requires": { + "@babel/types": "^7.5.5", + "jsesc": "^2.5.1", + "lodash": "^4.17.13", + "source-map": "^0.5.0", + "trim-right": "^1.0.1" + }, + "dependencies": { + "jsesc": { + "version": "2.5.2", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz", + "integrity": "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==", + "dev": true + } + } + }, + "@babel/helper-annotate-as-pure": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.0.0.tgz", + "integrity": "sha512-3UYcJUj9kvSLbLbUIfQTqzcy5VX7GRZ/CCDrnOaZorFFM01aXp1+GJwuFGV4NDDoAS+mOUyHcO6UD/RfqOks3Q==", + "dev": true, + "requires": { + "@babel/types": "^7.0.0" + } + }, + "@babel/helper-function-name": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.1.0.tgz", + "integrity": "sha512-A95XEoCpb3TO+KZzJ4S/5uW5fNe26DjBGqf1o9ucyLyCmi1dXq/B3c8iaWTfBk3VvetUxl16e8tIrd5teOCfGw==", + "dev": true, + "requires": { + "@babel/helper-get-function-arity": "^7.0.0", + "@babel/template": "^7.1.0", + "@babel/types": "^7.0.0" + } + }, + "@babel/helper-get-function-arity": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/@babel/helper-get-function-arity/-/helper-get-function-arity-7.0.0.tgz", + "integrity": "sha512-r2DbJeg4svYvt3HOS74U4eWKsUAMRH01Z1ds1zx8KNTPtpTL5JAsdFv8BNyOpVqdFhHkkRDIg5B4AsxmkjAlmQ==", + "dev": true, + "requires": { + "@babel/types": "^7.0.0" + } + }, + "@babel/helper-module-imports": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.0.0.tgz", + "integrity": "sha512-aP/hlLq01DWNEiDg4Jn23i+CXxW/owM4WpDLFUbpjxe4NS3BhLVZQ5i7E0ZrxuQ/vwekIeciyamgB1UIYxxM6A==", + "dev": true, + "requires": { + "@babel/types": "^7.0.0" + } + }, + "@babel/helper-module-transforms": { + "version": "7.5.5", + "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.5.5.tgz", + "integrity": "sha512-jBeCvETKuJqeiaCdyaheF40aXnnU1+wkSiUs/IQg3tB85up1LyL8x77ClY8qJpuRJUcXQo+ZtdNESmZl4j56Pw==", + "dev": true, + "requires": { + "@babel/helper-module-imports": "^7.0.0", + "@babel/helper-simple-access": "^7.1.0", + "@babel/helper-split-export-declaration": "^7.4.4", + "@babel/template": "^7.4.4", + "@babel/types": "^7.5.5", + "lodash": "^4.17.13" + } + }, + "@babel/helper-plugin-utils": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.0.0.tgz", + "integrity": "sha512-CYAOUCARwExnEixLdB6sDm2dIJ/YgEAKDM1MOeMeZu9Ld/bDgVo8aiWrXwcY7OBh+1Ea2uUcVRcxKk0GJvW7QA==", + "dev": true + }, + "@babel/helper-regex": { + "version": "7.5.5", + "resolved": "https://registry.npmjs.org/@babel/helper-regex/-/helper-regex-7.5.5.tgz", + "integrity": "sha512-CkCYQLkfkiugbRDO8eZn6lRuR8kzZoGXCg3149iTk5se7g6qykSpy3+hELSwquhu+TgHn8nkLiBwHvNX8Hofcw==", + "dev": true, + "requires": { + "lodash": "^4.17.13" + } + }, + "@babel/helper-remap-async-to-generator": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.1.0.tgz", + "integrity": "sha512-3fOK0L+Fdlg8S5al8u/hWE6vhufGSn0bN09xm2LXMy//REAF8kDCrYoOBKYmA8m5Nom+sV9LyLCwrFynA8/slg==", + "dev": true, + "requires": { + "@babel/helper-annotate-as-pure": "^7.0.0", + "@babel/helper-wrap-function": "^7.1.0", + "@babel/template": "^7.1.0", + "@babel/traverse": "^7.1.0", + "@babel/types": "^7.0.0" + } + }, + "@babel/helper-simple-access": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.1.0.tgz", + "integrity": "sha512-Vk+78hNjRbsiu49zAPALxTb+JUQCz1aolpd8osOF16BGnLtseD21nbHgLPGUwrXEurZgiCOUmvs3ExTu4F5x6w==", + "dev": true, + "requires": { + "@babel/template": "^7.1.0", + "@babel/types": "^7.0.0" + } + }, + "@babel/helper-split-export-declaration": { + "version": "7.4.4", + "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.4.4.tgz", + "integrity": "sha512-Ro/XkzLf3JFITkW6b+hNxzZ1n5OQ80NvIUdmHspih1XAhtN3vPTuUFT4eQnela+2MaZ5ulH+iyP513KJrxbN7Q==", + "dev": true, + "requires": { + "@babel/types": "^7.4.4" + } + }, + "@babel/helper-wrap-function": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/@babel/helper-wrap-function/-/helper-wrap-function-7.2.0.tgz", + "integrity": "sha512-o9fP1BZLLSrYlxYEYyl2aS+Flun5gtjTIG8iln+XuEzQTs0PLagAGSXUcqruJwD5fM48jzIEggCKpIfWTcR7pQ==", + "dev": true, + "requires": { + "@babel/helper-function-name": "^7.1.0", + "@babel/template": "^7.1.0", + "@babel/traverse": "^7.1.0", + "@babel/types": "^7.2.0" + } + }, + "@babel/helpers": { + "version": "7.5.5", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.5.5.tgz", + "integrity": "sha512-nRq2BUhxZFnfEn/ciJuhklHvFOqjJUD5wpx+1bxUF2axL9C+v4DE/dmp5sT2dKnpOs4orZWzpAZqlCy8QqE/7g==", + "dev": true, + "requires": { + "@babel/template": "^7.4.4", + "@babel/traverse": "^7.5.5", + "@babel/types": "^7.5.5" + } + }, + "@babel/highlight": { + "version": "7.5.0", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.5.0.tgz", + "integrity": "sha512-7dV4eu9gBxoM0dAnj/BCFDW9LFU0zvTrkq0ugM7pnHEgguOEeOz1so2ZghEdzviYzQEED0r4EAgpsBChKy1TRQ==", + "dev": true, + "requires": { + "chalk": "^2.0.0", + "esutils": "^2.0.2", + "js-tokens": "^4.0.0" + }, + "dependencies": { + "js-tokens": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", + "dev": true + } + } + }, + "@babel/parser": { + "version": "7.5.5", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.5.5.tgz", + "integrity": "sha512-E5BN68cqR7dhKan1SfqgPGhQ178bkVKpXTPEXnFJBrEt8/DKRZlybmy+IgYLTeN7tp1R5Ccmbm2rBk17sHYU3g==", + "dev": true + }, + "@babel/plugin-proposal-async-generator-functions": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-async-generator-functions/-/plugin-proposal-async-generator-functions-7.2.0.tgz", + "integrity": "sha512-+Dfo/SCQqrwx48ptLVGLdE39YtWRuKc/Y9I5Fy0P1DDBB9lsAHpjcEJQt+4IifuSOSTLBKJObJqMvaO1pIE8LQ==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.0.0", + "@babel/helper-remap-async-to-generator": "^7.1.0", + "@babel/plugin-syntax-async-generators": "^7.2.0" + } + }, + "@babel/plugin-proposal-dynamic-import": { + "version": "7.5.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-dynamic-import/-/plugin-proposal-dynamic-import-7.5.0.tgz", + "integrity": "sha512-x/iMjggsKTFHYC6g11PL7Qy58IK8H5zqfm9e6hu4z1iH2IRyAp9u9dL80zA6R76yFovETFLKz2VJIC2iIPBuFw==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.0.0", + "@babel/plugin-syntax-dynamic-import": "^7.2.0" + } + }, + "@babel/plugin-proposal-optional-catch-binding": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-optional-catch-binding/-/plugin-proposal-optional-catch-binding-7.2.0.tgz", + "integrity": "sha512-mgYj3jCcxug6KUcX4OBoOJz3CMrwRfQELPQ5560F70YQUBZB7uac9fqaWamKR1iWUzGiK2t0ygzjTScZnVz75g==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.0.0", + "@babel/plugin-syntax-optional-catch-binding": "^7.2.0" + } + }, + "@babel/plugin-syntax-async-generators": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-async-generators/-/plugin-syntax-async-generators-7.2.0.tgz", + "integrity": "sha512-1ZrIRBv2t0GSlcwVoQ6VgSLpLgiN/FVQUzt9znxo7v2Ov4jJrs8RY8tv0wvDmFN3qIdMKWrmMMW6yZ0G19MfGg==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.0.0" + } + }, + "@babel/plugin-syntax-dynamic-import": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-dynamic-import/-/plugin-syntax-dynamic-import-7.2.0.tgz", + "integrity": "sha512-mVxuJ0YroI/h/tbFTPGZR8cv6ai+STMKNBq0f8hFxsxWjl94qqhsb+wXbpNMDPU3cfR1TIsVFzU3nXyZMqyK4w==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.0.0" + } + }, + "@babel/plugin-syntax-optional-catch-binding": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-catch-binding/-/plugin-syntax-optional-catch-binding-7.2.0.tgz", + "integrity": "sha512-bDe4xKNhb0LI7IvZHiA13kff0KEfaGX/Hv4lMA9+7TEc63hMNvfKo6ZFpXhKuEp+II/q35Gc4NoMeDZyaUbj9w==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.0.0" + } + }, + "@babel/plugin-transform-dotall-regex": { + "version": "7.4.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-dotall-regex/-/plugin-transform-dotall-regex-7.4.4.tgz", + "integrity": "sha512-P05YEhRc2h53lZDjRPk/OektxCVevFzZs2Gfjd545Wde3k+yFDbXORgl2e0xpbq8mLcKJ7Idss4fAg0zORN/zg==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.0.0", + "@babel/helper-regex": "^7.4.4", + "regexpu-core": "^4.5.4" + }, + "dependencies": { + "regexpu-core": { + "version": "4.5.5", + "resolved": "https://registry.npmjs.org/regexpu-core/-/regexpu-core-4.5.5.tgz", + "integrity": "sha512-FpI67+ky9J+cDizQUJlIlNZFKual/lUkFr1AG6zOCpwZ9cLrg8UUVakyUQJD7fCDIe9Z2nwTQJNPyonatNmDFQ==", + "dev": true, + "requires": { + "regenerate": "^1.4.0", + "regenerate-unicode-properties": "^8.1.0", + "regjsgen": "^0.5.0", + "regjsparser": "^0.6.0", + "unicode-match-property-ecmascript": "^1.0.4", + "unicode-match-property-value-ecmascript": "^1.1.0" + } + }, + "regjsgen": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/regjsgen/-/regjsgen-0.5.0.tgz", + "integrity": "sha512-RnIrLhrXCX5ow/E5/Mh2O4e/oa1/jW0eaBKTSy3LaCj+M3Bqvm97GWDp2yUtzIs4LEn65zR2yiYGFqb2ApnzDA==", + "dev": true + }, + "regjsparser": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/regjsparser/-/regjsparser-0.6.0.tgz", + "integrity": "sha512-RQ7YyokLiQBomUJuUG8iGVvkgOLxwyZM8k6d3q5SAXpg4r5TZJZigKFvC6PpD+qQ98bCDC5YelPeA3EucDoNeQ==", + "dev": true, + "requires": { + "jsesc": "~0.5.0" + } + } + } + }, + "@babel/plugin-transform-modules-commonjs": { + "version": "7.5.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.5.0.tgz", + "integrity": "sha512-xmHq0B+ytyrWJvQTc5OWAC4ii6Dhr0s22STOoydokG51JjWhyYo5mRPXoi+ZmtHQhZZwuXNN+GG5jy5UZZJxIQ==", + "dev": true, + "requires": { + "@babel/helper-module-transforms": "^7.4.4", + "@babel/helper-plugin-utils": "^7.0.0", + "@babel/helper-simple-access": "^7.1.0", + "babel-plugin-dynamic-import-node": "^2.3.0" + } + }, + "@babel/template": { + "version": "7.4.4", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.4.4.tgz", + "integrity": "sha512-CiGzLN9KgAvgZsnivND7rkA+AeJ9JB0ciPOD4U59GKbQP2iQl+olF1l76kJOupqidozfZ32ghwBEJDhnk9MEcw==", + "dev": true, + "requires": { + "@babel/code-frame": "^7.0.0", + "@babel/parser": "^7.4.4", + "@babel/types": "^7.4.4" + } + }, + "@babel/traverse": { + "version": "7.5.5", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.5.5.tgz", + "integrity": "sha512-MqB0782whsfffYfSjH4TM+LMjrJnhCNEDMDIjeTpl+ASaUvxcjoiVCo/sM1GhS1pHOXYfWVCYneLjMckuUxDaQ==", + "dev": true, + "requires": { + "@babel/code-frame": "^7.5.5", + "@babel/generator": "^7.5.5", + "@babel/helper-function-name": "^7.1.0", + "@babel/helper-split-export-declaration": "^7.4.4", + "@babel/parser": "^7.5.5", + "@babel/types": "^7.5.5", + "debug": "^4.1.0", + "globals": "^11.1.0", + "lodash": "^4.17.13" + }, + "dependencies": { + "debug": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", + "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", + "dev": true, + "requires": { + "ms": "^2.1.1" + } + }, + "globals": { + "version": "11.12.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", + "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==", + "dev": true + } + } + }, + "@babel/types": { + "version": "7.5.5", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.5.5.tgz", + "integrity": "sha512-s63F9nJioLqOlW3UkyMd+BYhXt44YuaFm/VV0VwuteqjYwRrObkU7ra9pY4wAJR3oXi8hJrMcrcJdO/HH33vtw==", + "dev": true, + "requires": { + "esutils": "^2.0.2", + "lodash": "^4.17.13", + "to-fast-properties": "^2.0.0" + }, + "dependencies": { + "to-fast-properties": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", + "integrity": "sha1-3F5pjL0HkmW8c+A3doGk5Og/YW4=", + "dev": true + } + } + }, + "@comandeer/babel-plugin-banner": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/@comandeer/babel-plugin-banner/-/babel-plugin-banner-5.0.0.tgz", + "integrity": "sha512-sR9Go0U6puXoXyW9UgIiIQhRcJ8jVOvGl4BptUiXAtheMs72WcakZ1udh6J0ZOivr3o8jAM+MTCHLP8FZMbVpQ==", + "dev": true + }, + "@concordance/react": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@concordance/react/-/react-2.0.0.tgz", + "integrity": "sha512-huLSkUuM2/P+U0uy2WwlKuixMsTODD8p4JVQBI4VKeopkiN0C7M3N9XYVawb4M+4spN5RrO/eLhk7KoQX6nsfA==", + "dev": true, + "requires": { + "arrify": "^1.0.1" + }, + "dependencies": { + "arrify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/arrify/-/arrify-1.0.1.tgz", + "integrity": "sha1-iYUI2iIm84DfkEcoRWhJwVAaSw0=", + "dev": true + } + } + }, + "@nodelib/fs.scandir": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.1.tgz", + "integrity": "sha512-NT/skIZjgotDSiXs0WqYhgcuBKhUMgfekCmCGtkUAiLqZdOnrdjmZr9wRl3ll64J9NF79uZ4fk16Dx0yMc/Xbg==", + "dev": true, + "requires": { + "@nodelib/fs.stat": "2.0.1", + "run-parallel": "^1.1.9" + } + }, + "@nodelib/fs.stat": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.1.tgz", + "integrity": "sha512-+RqhBlLn6YRBGOIoVYthsG0J9dfpO79eJyN7BYBkZJtfqrBwf2KK+rD/M/yjZR6WBmIhAgOV7S60eCgaSWtbFw==", + "dev": true + }, + "@nodelib/fs.walk": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.2.tgz", + "integrity": "sha512-J/DR3+W12uCzAJkw7niXDcqcKBg6+5G5Q/ZpThpGNzAUz70eOR6RV4XnnSN01qHZiVl0eavoxJsBypQoKsV2QQ==", + "dev": true, + "requires": { + "@nodelib/fs.scandir": "2.1.1", + "fastq": "^1.6.0" + } + }, + "@sindresorhus/is": { + "version": "0.14.0", + "resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-0.14.0.tgz", + "integrity": "sha512-9NET910DNaIPngYnLLPeg+Ogzqsi9uM4mSboU5y6p8S5DzMTVEsJZrawi+BoDNUVBa2DhJqQYUFvMDfgU062LQ==", + "dev": true + }, + "@std/esm": { + "version": "0.8.3", + "resolved": "https://registry.npmjs.org/@std/esm/-/esm-0.8.3.tgz", + "integrity": "sha512-JZigVxIuy2mCkBZWxwS3Wu9eL0lJzR176Rmzb6hLjGIg3yBVBEK4XhEiFX6k5lXDY+e69XAvEVbp59PfUpfpBA==", + "dev": true + }, + "@szmarczak/http-timer": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@szmarczak/http-timer/-/http-timer-1.1.2.tgz", + "integrity": "sha512-XIB2XbzHTN6ieIjfIMV9hlVcfPU26s2vafYWQcZHWXHOxiaRZYEDKEwdl129Zyg50+foYV2jCgtrqSA6qNuNSA==", + "dev": true, + "requires": { + "defer-to-connect": "^1.0.1" + } + }, + "@types/estree": { + "version": "0.0.39", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-0.0.39.tgz", + "integrity": "sha512-EYNwp3bU+98cpU4lAWYYL7Zz+2gryWH1qbdDTidVd6hkiR6weksdbMadyXKXNPEkQFhXM+hVO9ZygomHXp+AIw==" + }, + "@types/events": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@types/events/-/events-3.0.0.tgz", + "integrity": "sha512-EaObqwIvayI5a8dCzhFrjKzVwKLxjoG9T6Ppd5CEo07LRKfQ8Yokw54r5+Wq7FaBQ+yXRvQAYPrHwya1/UFt9g==", + "dev": true + }, + "@types/glob": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/@types/glob/-/glob-7.1.1.tgz", + "integrity": "sha512-1Bh06cbWJUHMC97acuD6UMG29nMt0Aqz1vF3guLfG+kHHJhy3AyohZFFxYk2f7Q1SQIrNwvncxAE0N/9s70F2w==", + "dev": true, + "requires": { + "@types/events": "*", + "@types/minimatch": "*", + "@types/node": "*" + } + }, + "@types/minimatch": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@types/minimatch/-/minimatch-3.0.3.tgz", + "integrity": "sha512-tHq6qdbT9U1IRSGf14CL0pUlULksvY9OZ+5eEgl1N7t+OA3tGvNpxJCzuKQlsNgCVwbAs670L1vcVQi8j9HjnA==", + "dev": true + }, + "@types/node": { + "version": "12.7.2", + "resolved": "https://registry.npmjs.org/@types/node/-/node-12.7.2.tgz", + "integrity": "sha512-dyYO+f6ihZEtNPDcWNR1fkoTDf3zAK3lAABDze3mz6POyIercH0lEUawUFXlG8xaQZmm1yEBON/4TsYv/laDYg==", + "dev": true + }, + "@types/resolve": { + "version": "0.0.8", + "resolved": "https://registry.npmjs.org/@types/resolve/-/resolve-0.0.8.tgz", + "integrity": "sha512-auApPaJf3NPfe18hSoJkp8EbZzer2ISk7o8mCC3M9he/a04+gbMF97NkpD2S8riMGvm4BMRI59/SZQSaLTKpsQ==", + "dev": true, + "requires": { + "@types/node": "*" + } + }, + "acorn": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-7.0.0.tgz", + "integrity": "sha512-PaF/MduxijYYt7unVGRuds1vBC9bFxbNf+VWqhOClfdgy7RlVkQqt610ig1/yxTgsDIfW1cWDel5EBbOy3jdtQ==", + "dev": true + }, + "acorn-jsx": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.0.1.tgz", + "integrity": "sha512-HJ7CfNHrfJLlNTzIEUTj43LNWGkqpRLxm3YjAlcD0ACydk9XynzYsCBHxut+iqt+1aBXkx9UP/w/ZqMr13XIzg==", + "dev": true + }, + "ajv": { + "version": "6.10.2", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.10.2.tgz", + "integrity": "sha512-TXtUUEYHuaTEbLZWIKUr5pmBuhDLy+8KYtPYdcV8qC+pOZL+NKqYwvWSRrVXHn+ZmRRAu8vJTAznH7Oag6RVRw==", + "dev": true, + "requires": { + "fast-deep-equal": "^2.0.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + } + }, + "ansi-align": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/ansi-align/-/ansi-align-3.0.0.tgz", + "integrity": "sha512-ZpClVKqXN3RGBmKibdfWzqCY4lnjEuoNzU5T0oEFpfd/z5qJHVarukridD4juLO2FXMiwUQxr9WqQtaYa8XRYw==", + "dev": true, + "requires": { + "string-width": "^3.0.0" + }, + "dependencies": { + "emoji-regex": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-7.0.3.tgz", + "integrity": "sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA==", + "dev": true + }, + "string-width": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz", + "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==", + "dev": true, + "requires": { + "emoji-regex": "^7.0.1", + "is-fullwidth-code-point": "^2.0.0", + "strip-ansi": "^5.1.0" + } + } + } + }, + "ansi-escapes": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-4.2.1.tgz", + "integrity": "sha512-Cg3ymMAdN10wOk/VYfLV7KCQyv7EDirJ64500sU7n9UlmioEtDuU5Gd+hj73hXSU/ex7tHJSssmyftDdkMLO8Q==", + "dev": true, + "requires": { + "type-fest": "^0.5.2" + } + }, + "ansi-regex": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", + "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", + "dev": true + }, + "ansi-styles": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.0.0.tgz", + "integrity": "sha512-8zjUtFJ3db/QoPXuuEMloS2AUf79/yeyttJ7Abr3hteopJu9HK8vsgGviGUMq+zyA6cZZO6gAyZoMTF6TgaEjA==", + "dev": true, + "requires": { + "color-convert": "^2.0.0" + }, + "dependencies": { + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "requires": { + "color-name": "~1.1.4" + } + }, + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + } + } + }, + "anymatch": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.0.3.tgz", + "integrity": "sha512-c6IvoeBECQlMVuYUjSwimnhmztImpErfxJzWZhIQinIvQWoGOnB0dLIgifbPHQt5heS6mNlaZG16f06H3C8t1g==", + "dev": true, + "requires": { + "normalize-path": "^3.0.0", + "picomatch": "^2.0.4" + } + }, + "append-transform": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/append-transform/-/append-transform-1.0.0.tgz", + "integrity": "sha512-P009oYkeHyU742iSZJzZZywj4QRJdnTWffaKuJQLablCZ1uz6/cW4yaRgcDaoQ+uwOxxnt0gRUcwfsNP2ri0gw==", + "dev": true, + "requires": { + "default-require-extensions": "^2.0.0" + } + }, + "archy": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/archy/-/archy-1.0.0.tgz", + "integrity": "sha1-+cjBN1fMHde8N5rHeyxipcKGjEA=", + "dev": true + }, + "argparse": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", + "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", + "dev": true, + "requires": { + "sprintf-js": "~1.0.2" + } + }, + "arr-flatten": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/arr-flatten/-/arr-flatten-1.1.0.tgz", + "integrity": "sha512-L3hKV5R/p5o81R7O02IGnwpDmkp6E982XhtbuwSe3O4qOtMMMtodicASA1Cny2U+aCXcNpml+m4dPsvsJ3jatg==", + "dev": true + }, + "array-find-index": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/array-find-index/-/array-find-index-1.0.2.tgz", + "integrity": "sha1-3wEKoSh+Fku9pvlyOwqWoexBh6E=", + "dev": true + }, + "array-includes": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/array-includes/-/array-includes-3.0.3.tgz", + "integrity": "sha1-GEtI9i2S10UrsxsyMWXH+L0CJm0=", + "dev": true, + "requires": { + "define-properties": "^1.1.2", + "es-abstract": "^1.7.0" + } + }, + "array-union": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz", + "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==", + "dev": true + }, + "array-uniq": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/array-uniq/-/array-uniq-2.1.0.tgz", + "integrity": "sha512-bdHxtev7FN6+MXI1YFW0Q8mQ8dTJc2S8AMfju+ZR77pbg2yAdVyDlwkaUI7Har0LyOMRFPHrJ9lYdyjZZswdlQ==", + "dev": true + }, + "arrify": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/arrify/-/arrify-2.0.1.tgz", + "integrity": "sha512-3duEwti880xqi4eAMN8AyR4a0ByT90zoYdLlevfrvU43vb0YZwZVfxOgxWrLXXXpyugL0hNZc9G6BiB5B3nUug==", + "dev": true + }, + "astral-regex": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/astral-regex/-/astral-regex-1.0.0.tgz", + "integrity": "sha512-+Ryf6g3BKoRc7jfp7ad8tM4TtMiaWvbF/1/sQcZPkkS7ag3D5nMBCe2UfOTONtAkaG0tO0ij3C5Lwmf1EiyjHg==", + "dev": true + }, + "ava": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/ava/-/ava-2.3.0.tgz", + "integrity": "sha512-4VaaSnl13vpTZmqW3aMqioSolT0/ozRkjQxTLi3p8wtyRONuX/uLKL3uF0j50w2BNRoLsJqztnkX2h8xeVp2lg==", + "dev": true, + "requires": { + "@ava/babel-preset-stage-4": "^4.0.0", + "@ava/babel-preset-transform-test-files": "^6.0.0", + "@babel/core": "^7.5.5", + "@babel/generator": "^7.5.5", + "@concordance/react": "^2.0.0", + "ansi-escapes": "^4.2.1", + "ansi-styles": "^4.0.0", + "arr-flatten": "^1.1.0", + "array-union": "^2.1.0", + "array-uniq": "^2.1.0", + "arrify": "^2.0.1", + "bluebird": "^3.5.5", + "chalk": "^2.4.2", + "chokidar": "^3.0.2", + "chunkd": "^1.0.0", + "ci-parallel-vars": "^1.0.0", + "clean-stack": "^2.2.0", + "clean-yaml-object": "^0.1.0", + "cli-cursor": "^3.1.0", + "cli-truncate": "^2.0.0", + "code-excerpt": "^2.1.1", + "common-path-prefix": "^1.0.0", + "concordance": "^4.0.0", + "convert-source-map": "^1.6.0", + "currently-unhandled": "^0.4.1", + "debug": "^4.1.1", + "del": "^4.1.1", + "dot-prop": "^5.1.0", + "emittery": "^0.4.1", + "empower-core": "^1.2.0", + "equal-length": "^1.0.0", + "escape-string-regexp": "^2.0.0", + "esm": "^3.2.25", + "figures": "^3.0.0", + "find-up": "^4.1.0", + "get-port": "^5.0.0", + "globby": "^10.0.1", + "ignore-by-default": "^1.0.0", + "import-local": "^3.0.2", + "indent-string": "^4.0.0", + "is-ci": "^2.0.0", + "is-error": "^2.2.2", + "is-observable": "^2.0.0", + "is-plain-object": "^3.0.0", + "is-promise": "^2.1.0", + "lodash": "^4.17.15", + "loud-rejection": "^2.1.0", + "make-dir": "^3.0.0", + "matcher": "^2.0.0", + "md5-hex": "^3.0.1", + "meow": "^5.0.0", + "micromatch": "^4.0.2", + "ms": "^2.1.2", + "observable-to-promise": "^1.0.0", + "ora": "^3.4.0", + "package-hash": "^4.0.0", + "pkg-conf": "^3.1.0", + "plur": "^3.1.1", + "pretty-ms": "^5.0.0", + "require-precompiled": "^0.1.0", + "resolve-cwd": "^3.0.0", + "slash": "^3.0.0", + "source-map-support": "^0.5.13", + "stack-utils": "^1.0.2", + "strip-ansi": "^5.2.0", + "strip-bom-buf": "^2.0.0", + "supertap": "^1.0.0", + "supports-color": "^7.0.0", + "trim-off-newlines": "^1.0.1", + "trim-right": "^1.0.1", + "unique-temp-dir": "^1.0.0", + "update-notifier": "^3.0.1", + "write-file-atomic": "^3.0.0" + }, + "dependencies": { + "debug": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", + "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", + "dev": true, + "requires": { + "ms": "^2.1.1" + } + }, + "escape-string-regexp": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-2.0.0.tgz", + "integrity": "sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w==", + "dev": true + }, + "find-up": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", + "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", + "dev": true, + "requires": { + "locate-path": "^5.0.0", + "path-exists": "^4.0.0" + } + }, + "locate-path": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", + "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", + "dev": true, + "requires": { + "p-locate": "^4.1.0" + } + }, + "p-limit": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.2.1.tgz", + "integrity": "sha512-85Tk+90UCVWvbDavCLKPOLC9vvY8OwEX/RtKF+/1OADJMVlFfEHOiMTPVyxg7mk/dKa+ipdHm0OUkTvCpMTuwg==", + "dev": true, + "requires": { + "p-try": "^2.0.0" + } + }, + "p-locate": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", + "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", + "dev": true, + "requires": { + "p-limit": "^2.2.0" + } + }, + "p-try": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", + "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", + "dev": true + }, + "path-exists": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", + "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", + "dev": true + }, + "slash": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", + "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", + "dev": true + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + }, + "source-map-support": { + "version": "0.5.13", + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.13.tgz", + "integrity": "sha512-SHSKFHadjVA5oR4PPqhtAVdcBWwRYVd6g6cAXnIbRiIwc2EhPrTuKUBdSLvlEKyIP3GCf89fltvcZiP9MMFA1w==", + "dev": true, + "requires": { + "buffer-from": "^1.0.0", + "source-map": "^0.6.0" + } + } + } + }, + "babel-code-frame": { + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/babel-code-frame/-/babel-code-frame-6.26.0.tgz", + "integrity": "sha1-Y/1D99weO7fONZR9uP42mj9Yx0s=", + "dev": true, + "requires": { + "chalk": "^1.1.3", + "esutils": "^2.0.2", + "js-tokens": "^3.0.2" + }, + "dependencies": { + "ansi-styles": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", + "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=", + "dev": true + }, + "chalk": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", + "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", + "dev": true, + "requires": { + "ansi-styles": "^2.2.1", + "escape-string-regexp": "^1.0.2", + "has-ansi": "^2.0.0", + "strip-ansi": "^3.0.0", + "supports-color": "^2.0.0" + } + }, + "strip-ansi": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", + "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", + "dev": true, + "requires": { + "ansi-regex": "^2.0.0" + } + }, + "supports-color": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", + "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=", + "dev": true + } + } + }, + "babel-core": { + "version": "6.26.3", + "resolved": "https://registry.npmjs.org/babel-core/-/babel-core-6.26.3.tgz", + "integrity": "sha512-6jyFLuDmeidKmUEb3NM+/yawG0M2bDZ9Z1qbZP59cyHLz8kYGKYwpJP0UwUKKUiTRNvxfLesJnTedqczP7cTDA==", + "dev": true, + "requires": { + "babel-code-frame": "^6.26.0", + "babel-generator": "^6.26.0", + "babel-helpers": "^6.24.1", + "babel-messages": "^6.23.0", + "babel-register": "^6.26.0", + "babel-runtime": "^6.26.0", + "babel-template": "^6.26.0", + "babel-traverse": "^6.26.0", + "babel-types": "^6.26.0", + "babylon": "^6.18.0", + "convert-source-map": "^1.5.1", + "debug": "^2.6.9", + "json5": "^0.5.1", + "lodash": "^4.17.4", + "minimatch": "^3.0.4", + "path-is-absolute": "^1.0.1", + "private": "^0.1.8", + "slash": "^1.0.0", + "source-map": "^0.5.7" + } + }, + "babel-generator": { + "version": "6.26.1", + "resolved": "https://registry.npmjs.org/babel-generator/-/babel-generator-6.26.1.tgz", + "integrity": "sha512-HyfwY6ApZj7BYTcJURpM5tznulaBvyio7/0d4zFOeMPUmfxkCjHocCuoLa2SAGzBI8AREcH3eP3758F672DppA==", + "dev": true, + "requires": { + "babel-messages": "^6.23.0", + "babel-runtime": "^6.26.0", + "babel-types": "^6.26.0", + "detect-indent": "^4.0.0", + "jsesc": "^1.3.0", + "lodash": "^4.17.4", + "source-map": "^0.5.7", + "trim-right": "^1.0.1" + }, + "dependencies": { + "jsesc": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-1.3.0.tgz", + "integrity": "sha1-RsP+yMGJKxKwgz25vHYiF226s0s=", + "dev": true + } + } + }, + "babel-helper-builder-binary-assignment-operator-visitor": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-helper-builder-binary-assignment-operator-visitor/-/babel-helper-builder-binary-assignment-operator-visitor-6.24.1.tgz", + "integrity": "sha1-zORReto1b0IgvK6KAsKzRvmlZmQ=", + "dev": true, + "requires": { + "babel-helper-explode-assignable-expression": "^6.24.1", + "babel-runtime": "^6.22.0", + "babel-types": "^6.24.1" + } + }, + "babel-helper-call-delegate": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-helper-call-delegate/-/babel-helper-call-delegate-6.24.1.tgz", + "integrity": "sha1-7Oaqzdx25Bw0YfiL/Fdb0Nqi340=", + "dev": true, + "requires": { + "babel-helper-hoist-variables": "^6.24.1", + "babel-runtime": "^6.22.0", + "babel-traverse": "^6.24.1", + "babel-types": "^6.24.1" + } + }, + "babel-helper-define-map": { + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/babel-helper-define-map/-/babel-helper-define-map-6.26.0.tgz", + "integrity": "sha1-pfVtq0GiX5fstJjH66ypgZ+Vvl8=", + "dev": true, + "requires": { + "babel-helper-function-name": "^6.24.1", + "babel-runtime": "^6.26.0", + "babel-types": "^6.26.0", + "lodash": "^4.17.4" + } + }, + "babel-helper-evaluate-path": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/babel-helper-evaluate-path/-/babel-helper-evaluate-path-0.5.0.tgz", + "integrity": "sha512-mUh0UhS607bGh5wUMAQfOpt2JX2ThXMtppHRdRU1kL7ZLRWIXxoV2UIV1r2cAeeNeU1M5SB5/RSUgUxrK8yOkA==", + "dev": true + }, + "babel-helper-explode-assignable-expression": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-helper-explode-assignable-expression/-/babel-helper-explode-assignable-expression-6.24.1.tgz", + "integrity": "sha1-8luCz33BBDPFX3BZLVdGQArCLKo=", + "dev": true, + "requires": { + "babel-runtime": "^6.22.0", + "babel-traverse": "^6.24.1", + "babel-types": "^6.24.1" + } + }, + "babel-helper-flip-expressions": { + "version": "0.4.3", + "resolved": "https://registry.npmjs.org/babel-helper-flip-expressions/-/babel-helper-flip-expressions-0.4.3.tgz", + "integrity": "sha1-NpZzahKKwYvCUlS19AoizrPB0/0=", + "dev": true + }, + "babel-helper-function-name": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-helper-function-name/-/babel-helper-function-name-6.24.1.tgz", + "integrity": "sha1-00dbjAPtmCQqJbSDUasYOZ01gKk=", + "dev": true, + "requires": { + "babel-helper-get-function-arity": "^6.24.1", + "babel-runtime": "^6.22.0", + "babel-template": "^6.24.1", + "babel-traverse": "^6.24.1", + "babel-types": "^6.24.1" + } + }, + "babel-helper-get-function-arity": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-helper-get-function-arity/-/babel-helper-get-function-arity-6.24.1.tgz", + "integrity": "sha1-j3eCqpNAfEHTqlCQj4mwMbG2hT0=", + "dev": true, + "requires": { + "babel-runtime": "^6.22.0", + "babel-types": "^6.24.1" + } + }, + "babel-helper-hoist-variables": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-helper-hoist-variables/-/babel-helper-hoist-variables-6.24.1.tgz", + "integrity": "sha1-HssnaJydJVE+rbyZFKc/VAi+enY=", + "dev": true, + "requires": { + "babel-runtime": "^6.22.0", + "babel-types": "^6.24.1" + } + }, + "babel-helper-is-nodes-equiv": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/babel-helper-is-nodes-equiv/-/babel-helper-is-nodes-equiv-0.0.1.tgz", + "integrity": "sha1-NOmzALFHnd2Y7HfqC76TQt/jloQ=", + "dev": true + }, + "babel-helper-is-void-0": { + "version": "0.4.3", + "resolved": "https://registry.npmjs.org/babel-helper-is-void-0/-/babel-helper-is-void-0-0.4.3.tgz", + "integrity": "sha1-fZwBtFYee5Xb2g9u7kj1tg5nMT4=", + "dev": true + }, + "babel-helper-mark-eval-scopes": { + "version": "0.4.3", + "resolved": "https://registry.npmjs.org/babel-helper-mark-eval-scopes/-/babel-helper-mark-eval-scopes-0.4.3.tgz", + "integrity": "sha1-0kSjvvmESHJgP/tG4izorN9VFWI=", + "dev": true + }, + "babel-helper-optimise-call-expression": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-helper-optimise-call-expression/-/babel-helper-optimise-call-expression-6.24.1.tgz", + "integrity": "sha1-96E0J7qfc/j0+pk8VKl4gtEkQlc=", + "dev": true, + "requires": { + "babel-runtime": "^6.22.0", + "babel-types": "^6.24.1" + } + }, + "babel-helper-regex": { + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/babel-helper-regex/-/babel-helper-regex-6.26.0.tgz", + "integrity": "sha1-MlxZ+QL4LyS3T6zu0DY5VPZJXnI=", + "dev": true, + "requires": { + "babel-runtime": "^6.26.0", + "babel-types": "^6.26.0", + "lodash": "^4.17.4" + } + }, + "babel-helper-remap-async-to-generator": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-helper-remap-async-to-generator/-/babel-helper-remap-async-to-generator-6.24.1.tgz", + "integrity": "sha1-XsWBgnrXI/7N04HxySg5BnbkVRs=", + "dev": true, + "requires": { + "babel-helper-function-name": "^6.24.1", + "babel-runtime": "^6.22.0", + "babel-template": "^6.24.1", + "babel-traverse": "^6.24.1", + "babel-types": "^6.24.1" + } + }, + "babel-helper-remove-or-void": { + "version": "0.4.3", + "resolved": "https://registry.npmjs.org/babel-helper-remove-or-void/-/babel-helper-remove-or-void-0.4.3.tgz", + "integrity": "sha1-pPA7QAd6D/6I5F0HAQ3uJB/1rmA=", + "dev": true + }, + "babel-helper-replace-supers": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-helper-replace-supers/-/babel-helper-replace-supers-6.24.1.tgz", + "integrity": "sha1-v22/5Dk40XNpohPKiov3S2qQqxo=", + "dev": true, + "requires": { + "babel-helper-optimise-call-expression": "^6.24.1", + "babel-messages": "^6.23.0", + "babel-runtime": "^6.22.0", + "babel-template": "^6.24.1", + "babel-traverse": "^6.24.1", + "babel-types": "^6.24.1" + } + }, + "babel-helper-to-multiple-sequence-expressions": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/babel-helper-to-multiple-sequence-expressions/-/babel-helper-to-multiple-sequence-expressions-0.5.0.tgz", + "integrity": "sha512-m2CvfDW4+1qfDdsrtf4dwOslQC3yhbgyBFptncp4wvtdrDHqueW7slsYv4gArie056phvQFhT2nRcGS4bnm6mA==", + "dev": true + }, + "babel-helpers": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-helpers/-/babel-helpers-6.24.1.tgz", + "integrity": "sha1-NHHenK7DiOXIUOWX5Yom3fN2ArI=", + "dev": true, + "requires": { + "babel-runtime": "^6.22.0", + "babel-template": "^6.24.1" + } + }, + "babel-messages": { + "version": "6.23.0", + "resolved": "https://registry.npmjs.org/babel-messages/-/babel-messages-6.23.0.tgz", + "integrity": "sha1-8830cDhYA1sqKVHG7F7fbGLyYw4=", + "dev": true, + "requires": { + "babel-runtime": "^6.22.0" + } + }, + "babel-plugin-check-es2015-constants": { + "version": "6.22.0", + "resolved": "https://registry.npmjs.org/babel-plugin-check-es2015-constants/-/babel-plugin-check-es2015-constants-6.22.0.tgz", + "integrity": "sha1-NRV7EBQm/S/9PaP3XH0ekYNbv4o=", + "dev": true, + "requires": { + "babel-runtime": "^6.22.0" + } + }, + "babel-plugin-dynamic-import-node": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/babel-plugin-dynamic-import-node/-/babel-plugin-dynamic-import-node-2.3.0.tgz", + "integrity": "sha512-o6qFkpeQEBxcqt0XYlWzAVxNCSCZdUgcR8IRlhD/8DylxjjO4foPcvTW0GGKa/cVt3rvxZ7o5ippJ+/0nvLhlQ==", + "dev": true, + "requires": { + "object.assign": "^4.1.0" + } + }, + "babel-plugin-espower": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/babel-plugin-espower/-/babel-plugin-espower-3.0.1.tgz", + "integrity": "sha512-Ms49U7VIAtQ/TtcqRbD6UBmJBUCSxiC3+zPc+eGqxKUIFO1lTshyEDRUjhoAbd2rWfwYf3cZ62oXozrd8W6J0A==", + "dev": true, + "requires": { + "@babel/generator": "^7.0.0", + "@babel/parser": "^7.0.0", + "call-matcher": "^1.0.0", + "core-js": "^2.0.0", + "espower-location-detector": "^1.0.0", + "espurify": "^1.6.0", + "estraverse": "^4.1.1" + } + }, + "babel-plugin-minify-builtins": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/babel-plugin-minify-builtins/-/babel-plugin-minify-builtins-0.5.0.tgz", + "integrity": "sha512-wpqbN7Ov5hsNwGdzuzvFcjgRlzbIeVv1gMIlICbPj0xkexnfoIDe7q+AZHMkQmAE/F9R5jkrB6TLfTegImlXag==", + "dev": true + }, + "babel-plugin-minify-constant-folding": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/babel-plugin-minify-constant-folding/-/babel-plugin-minify-constant-folding-0.5.0.tgz", + "integrity": "sha512-Vj97CTn/lE9hR1D+jKUeHfNy+m1baNiJ1wJvoGyOBUx7F7kJqDZxr9nCHjO/Ad+irbR3HzR6jABpSSA29QsrXQ==", + "dev": true, + "requires": { + "babel-helper-evaluate-path": "^0.5.0" + } + }, + "babel-plugin-minify-dead-code-elimination": { + "version": "0.5.1", + "resolved": "https://registry.npmjs.org/babel-plugin-minify-dead-code-elimination/-/babel-plugin-minify-dead-code-elimination-0.5.1.tgz", + "integrity": "sha512-x8OJOZIrRmQBcSqxBcLbMIK8uPmTvNWPXH2bh5MDCW1latEqYiRMuUkPImKcfpo59pTUB2FT7HfcgtG8ZlR5Qg==", + "dev": true, + "requires": { + "babel-helper-evaluate-path": "^0.5.0", + "babel-helper-mark-eval-scopes": "^0.4.3", + "babel-helper-remove-or-void": "^0.4.3", + "lodash": "^4.17.11" + } + }, + "babel-plugin-minify-flip-comparisons": { + "version": "0.4.3", + "resolved": "https://registry.npmjs.org/babel-plugin-minify-flip-comparisons/-/babel-plugin-minify-flip-comparisons-0.4.3.tgz", + "integrity": "sha1-AMqHDLjxO0XAOLPB68DyJyk8llo=", + "dev": true, + "requires": { + "babel-helper-is-void-0": "^0.4.3" + } + }, + "babel-plugin-minify-guarded-expressions": { + "version": "0.4.4", + "resolved": "https://registry.npmjs.org/babel-plugin-minify-guarded-expressions/-/babel-plugin-minify-guarded-expressions-0.4.4.tgz", + "integrity": "sha512-RMv0tM72YuPPfLT9QLr3ix9nwUIq+sHT6z8Iu3sLbqldzC1Dls8DPCywzUIzkTx9Zh1hWX4q/m9BPoPed9GOfA==", + "dev": true, + "requires": { + "babel-helper-evaluate-path": "^0.5.0", + "babel-helper-flip-expressions": "^0.4.3" + } + }, + "babel-plugin-minify-infinity": { + "version": "0.4.3", + "resolved": "https://registry.npmjs.org/babel-plugin-minify-infinity/-/babel-plugin-minify-infinity-0.4.3.tgz", + "integrity": "sha1-37h2obCKBldjhO8/kuZTumB7Oco=", + "dev": true + }, + "babel-plugin-minify-mangle-names": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/babel-plugin-minify-mangle-names/-/babel-plugin-minify-mangle-names-0.5.0.tgz", + "integrity": "sha512-3jdNv6hCAw6fsX1p2wBGPfWuK69sfOjfd3zjUXkbq8McbohWy23tpXfy5RnToYWggvqzuMOwlId1PhyHOfgnGw==", + "dev": true, + "requires": { + "babel-helper-mark-eval-scopes": "^0.4.3" + } + }, + "babel-plugin-minify-numeric-literals": { + "version": "0.4.3", + "resolved": "https://registry.npmjs.org/babel-plugin-minify-numeric-literals/-/babel-plugin-minify-numeric-literals-0.4.3.tgz", + "integrity": "sha1-jk/VYcefeAEob/YOjF/Z3u6TwLw=", + "dev": true + }, + "babel-plugin-minify-replace": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/babel-plugin-minify-replace/-/babel-plugin-minify-replace-0.5.0.tgz", + "integrity": "sha512-aXZiaqWDNUbyNNNpWs/8NyST+oU7QTpK7J9zFEFSA0eOmtUNMU3fczlTTTlnCxHmq/jYNFEmkkSG3DDBtW3Y4Q==", + "dev": true + }, + "babel-plugin-minify-simplify": { + "version": "0.5.1", + "resolved": "https://registry.npmjs.org/babel-plugin-minify-simplify/-/babel-plugin-minify-simplify-0.5.1.tgz", + "integrity": "sha512-OSYDSnoCxP2cYDMk9gxNAed6uJDiDz65zgL6h8d3tm8qXIagWGMLWhqysT6DY3Vs7Fgq7YUDcjOomhVUb+xX6A==", + "dev": true, + "requires": { + "babel-helper-evaluate-path": "^0.5.0", + "babel-helper-flip-expressions": "^0.4.3", + "babel-helper-is-nodes-equiv": "^0.0.1", + "babel-helper-to-multiple-sequence-expressions": "^0.5.0" + } + }, + "babel-plugin-minify-type-constructors": { + "version": "0.4.3", + "resolved": "https://registry.npmjs.org/babel-plugin-minify-type-constructors/-/babel-plugin-minify-type-constructors-0.4.3.tgz", + "integrity": "sha1-G8bxW4f3qxCF1CszC3F2V6IVZQA=", + "dev": true, + "requires": { + "babel-helper-is-void-0": "^0.4.3" + } + }, + "babel-plugin-syntax-async-functions": { + "version": "6.13.0", + "resolved": "https://registry.npmjs.org/babel-plugin-syntax-async-functions/-/babel-plugin-syntax-async-functions-6.13.0.tgz", + "integrity": "sha1-ytnK0RkbWtY0vzCuCHI5HgZHvpU=", + "dev": true + }, + "babel-plugin-syntax-exponentiation-operator": { + "version": "6.13.0", + "resolved": "https://registry.npmjs.org/babel-plugin-syntax-exponentiation-operator/-/babel-plugin-syntax-exponentiation-operator-6.13.0.tgz", + "integrity": "sha1-nufoM3KQ2pUoggGmpX9BcDF4MN4=", + "dev": true + }, + "babel-plugin-syntax-trailing-function-commas": { + "version": "6.22.0", + "resolved": "https://registry.npmjs.org/babel-plugin-syntax-trailing-function-commas/-/babel-plugin-syntax-trailing-function-commas-6.22.0.tgz", + "integrity": "sha1-ugNgk3+NBuQBgKQ/4NVhb/9TLPM=", + "dev": true + }, + "babel-plugin-transform-async-to-generator": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-async-to-generator/-/babel-plugin-transform-async-to-generator-6.24.1.tgz", + "integrity": "sha1-ZTbjeK/2yx1VF6wOQOs+n8jQh2E=", + "dev": true, + "requires": { + "babel-helper-remap-async-to-generator": "^6.24.1", + "babel-plugin-syntax-async-functions": "^6.8.0", + "babel-runtime": "^6.22.0" + } + }, + "babel-plugin-transform-es2015-arrow-functions": { + "version": "6.22.0", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-arrow-functions/-/babel-plugin-transform-es2015-arrow-functions-6.22.0.tgz", + "integrity": "sha1-RSaSy3EdX3ncf4XkQM5BufJE0iE=", + "dev": true, + "requires": { + "babel-runtime": "^6.22.0" + } + }, + "babel-plugin-transform-es2015-block-scoped-functions": { + "version": "6.22.0", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-block-scoped-functions/-/babel-plugin-transform-es2015-block-scoped-functions-6.22.0.tgz", + "integrity": "sha1-u8UbSflk1wy42OC5ToICRs46YUE=", + "dev": true, + "requires": { + "babel-runtime": "^6.22.0" + } + }, + "babel-plugin-transform-es2015-block-scoping": { + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-block-scoping/-/babel-plugin-transform-es2015-block-scoping-6.26.0.tgz", + "integrity": "sha1-1w9SmcEwjQXBL0Y4E7CgnnOxiV8=", + "dev": true, + "requires": { + "babel-runtime": "^6.26.0", + "babel-template": "^6.26.0", + "babel-traverse": "^6.26.0", + "babel-types": "^6.26.0", + "lodash": "^4.17.4" + } + }, + "babel-plugin-transform-es2015-classes": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-classes/-/babel-plugin-transform-es2015-classes-6.24.1.tgz", + "integrity": "sha1-WkxYpQyclGHlZLSyo7+ryXolhNs=", + "dev": true, + "requires": { + "babel-helper-define-map": "^6.24.1", + "babel-helper-function-name": "^6.24.1", + "babel-helper-optimise-call-expression": "^6.24.1", + "babel-helper-replace-supers": "^6.24.1", + "babel-messages": "^6.23.0", + "babel-runtime": "^6.22.0", + "babel-template": "^6.24.1", + "babel-traverse": "^6.24.1", + "babel-types": "^6.24.1" + } + }, + "babel-plugin-transform-es2015-computed-properties": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-computed-properties/-/babel-plugin-transform-es2015-computed-properties-6.24.1.tgz", + "integrity": "sha1-b+Ko0WiV1WNPTNmZttNICjCBWbM=", + "dev": true, + "requires": { + "babel-runtime": "^6.22.0", + "babel-template": "^6.24.1" + } + }, + "babel-plugin-transform-es2015-destructuring": { + "version": "6.23.0", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-destructuring/-/babel-plugin-transform-es2015-destructuring-6.23.0.tgz", + "integrity": "sha1-mXux8auWf2gtKwh2/jWNYOdlxW0=", + "dev": true, + "requires": { + "babel-runtime": "^6.22.0" + } + }, + "babel-plugin-transform-es2015-duplicate-keys": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-duplicate-keys/-/babel-plugin-transform-es2015-duplicate-keys-6.24.1.tgz", + "integrity": "sha1-c+s9MQypaePvnskcU3QabxV2Qj4=", + "dev": true, + "requires": { + "babel-runtime": "^6.22.0", + "babel-types": "^6.24.1" + } + }, + "babel-plugin-transform-es2015-for-of": { + "version": "6.23.0", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-for-of/-/babel-plugin-transform-es2015-for-of-6.23.0.tgz", + "integrity": "sha1-9HyVsrYT3x0+zC/bdXNiPHUkhpE=", + "dev": true, + "requires": { + "babel-runtime": "^6.22.0" + } + }, + "babel-plugin-transform-es2015-function-name": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-function-name/-/babel-plugin-transform-es2015-function-name-6.24.1.tgz", + "integrity": "sha1-g0yJhTvDaxrw86TF26qU/Y6sqos=", + "dev": true, + "requires": { + "babel-helper-function-name": "^6.24.1", + "babel-runtime": "^6.22.0", + "babel-types": "^6.24.1" + } + }, + "babel-plugin-transform-es2015-literals": { + "version": "6.22.0", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-literals/-/babel-plugin-transform-es2015-literals-6.22.0.tgz", + "integrity": "sha1-T1SgLWzWbPkVKAAZox0xklN3yi4=", + "dev": true, + "requires": { + "babel-runtime": "^6.22.0" + } + }, + "babel-plugin-transform-es2015-modules-amd": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-modules-amd/-/babel-plugin-transform-es2015-modules-amd-6.24.1.tgz", + "integrity": "sha1-Oz5UAXI5hC1tGcMBHEvS8AoA0VQ=", + "dev": true, + "requires": { + "babel-plugin-transform-es2015-modules-commonjs": "^6.24.1", + "babel-runtime": "^6.22.0", + "babel-template": "^6.24.1" + } + }, + "babel-plugin-transform-es2015-modules-commonjs": { + "version": "6.26.2", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-modules-commonjs/-/babel-plugin-transform-es2015-modules-commonjs-6.26.2.tgz", + "integrity": "sha512-CV9ROOHEdrjcwhIaJNBGMBCodN+1cfkwtM1SbUHmvyy35KGT7fohbpOxkE2uLz1o6odKK2Ck/tz47z+VqQfi9Q==", + "dev": true, + "requires": { + "babel-plugin-transform-strict-mode": "^6.24.1", + "babel-runtime": "^6.26.0", + "babel-template": "^6.26.0", + "babel-types": "^6.26.0" + } + }, + "babel-plugin-transform-es2015-modules-systemjs": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-modules-systemjs/-/babel-plugin-transform-es2015-modules-systemjs-6.24.1.tgz", + "integrity": "sha1-/4mhQrkRmpBhlfXxBuzzBdlAfSM=", + "dev": true, + "requires": { + "babel-helper-hoist-variables": "^6.24.1", + "babel-runtime": "^6.22.0", + "babel-template": "^6.24.1" + } + }, + "babel-plugin-transform-es2015-modules-umd": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-modules-umd/-/babel-plugin-transform-es2015-modules-umd-6.24.1.tgz", + "integrity": "sha1-rJl+YoXNGO1hdq22B9YCNErThGg=", + "dev": true, + "requires": { + "babel-plugin-transform-es2015-modules-amd": "^6.24.1", + "babel-runtime": "^6.22.0", + "babel-template": "^6.24.1" + } + }, + "babel-plugin-transform-es2015-object-super": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-object-super/-/babel-plugin-transform-es2015-object-super-6.24.1.tgz", + "integrity": "sha1-JM72muIcuDp/hgPa0CH1cusnj40=", + "dev": true, + "requires": { + "babel-helper-replace-supers": "^6.24.1", + "babel-runtime": "^6.22.0" + } + }, + "babel-plugin-transform-es2015-parameters": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-parameters/-/babel-plugin-transform-es2015-parameters-6.24.1.tgz", + "integrity": "sha1-V6w1GrScrxSpfNE7CfZv3wpiXys=", + "dev": true, + "requires": { + "babel-helper-call-delegate": "^6.24.1", + "babel-helper-get-function-arity": "^6.24.1", + "babel-runtime": "^6.22.0", + "babel-template": "^6.24.1", + "babel-traverse": "^6.24.1", + "babel-types": "^6.24.1" + } + }, + "babel-plugin-transform-es2015-shorthand-properties": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-shorthand-properties/-/babel-plugin-transform-es2015-shorthand-properties-6.24.1.tgz", + "integrity": "sha1-JPh11nIch2YbvZmkYi5R8U3jiqA=", + "dev": true, + "requires": { + "babel-runtime": "^6.22.0", + "babel-types": "^6.24.1" + } + }, + "babel-plugin-transform-es2015-spread": { + "version": "6.22.0", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-spread/-/babel-plugin-transform-es2015-spread-6.22.0.tgz", + "integrity": "sha1-1taKmfia7cRTbIGlQujdnxdG+NE=", + "dev": true, + "requires": { + "babel-runtime": "^6.22.0" + } + }, + "babel-plugin-transform-es2015-sticky-regex": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-sticky-regex/-/babel-plugin-transform-es2015-sticky-regex-6.24.1.tgz", + "integrity": "sha1-AMHNsaynERLN8M9hJsLta0V8zbw=", + "dev": true, + "requires": { + "babel-helper-regex": "^6.24.1", + "babel-runtime": "^6.22.0", + "babel-types": "^6.24.1" + } + }, + "babel-plugin-transform-es2015-template-literals": { + "version": "6.22.0", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-template-literals/-/babel-plugin-transform-es2015-template-literals-6.22.0.tgz", + "integrity": "sha1-qEs0UPfp+PH2g51taH2oS7EjbY0=", + "dev": true, + "requires": { + "babel-runtime": "^6.22.0" + } + }, + "babel-plugin-transform-es2015-typeof-symbol": { + "version": "6.23.0", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-typeof-symbol/-/babel-plugin-transform-es2015-typeof-symbol-6.23.0.tgz", + "integrity": "sha1-3sCfHN3/lLUqxz1QXITfWdzOs3I=", + "dev": true, + "requires": { + "babel-runtime": "^6.22.0" + } + }, + "babel-plugin-transform-es2015-unicode-regex": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-unicode-regex/-/babel-plugin-transform-es2015-unicode-regex-6.24.1.tgz", + "integrity": "sha1-04sS9C6nMj9yk4fxinxa4frrNek=", + "dev": true, + "requires": { + "babel-helper-regex": "^6.24.1", + "babel-runtime": "^6.22.0", + "regexpu-core": "^2.0.0" + } + }, + "babel-plugin-transform-exponentiation-operator": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-exponentiation-operator/-/babel-plugin-transform-exponentiation-operator-6.24.1.tgz", + "integrity": "sha1-KrDJx/MJj6SJB3cruBP+QejeOg4=", + "dev": true, + "requires": { + "babel-helper-builder-binary-assignment-operator-visitor": "^6.24.1", + "babel-plugin-syntax-exponentiation-operator": "^6.8.0", + "babel-runtime": "^6.22.0" + } + }, + "babel-plugin-transform-inline-consecutive-adds": { + "version": "0.4.3", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-inline-consecutive-adds/-/babel-plugin-transform-inline-consecutive-adds-0.4.3.tgz", + "integrity": "sha1-Mj1Ho+pjqDp6w8gRro5pQfrysNE=", + "dev": true + }, + "babel-plugin-transform-member-expression-literals": { + "version": "6.9.4", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-member-expression-literals/-/babel-plugin-transform-member-expression-literals-6.9.4.tgz", + "integrity": "sha1-NwOcmgwzE6OUlfqsL/OmtbnQOL8=", + "dev": true + }, + "babel-plugin-transform-merge-sibling-variables": { + "version": "6.9.4", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-merge-sibling-variables/-/babel-plugin-transform-merge-sibling-variables-6.9.4.tgz", + "integrity": "sha1-hbQi/DN3tEnJ0c3kQIcgNTJAHa4=", + "dev": true + }, + "babel-plugin-transform-minify-booleans": { + "version": "6.9.4", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-minify-booleans/-/babel-plugin-transform-minify-booleans-6.9.4.tgz", + "integrity": "sha1-rLs+VqNVXdI5KOS1gtKFFi3SsZg=", + "dev": true + }, + "babel-plugin-transform-property-literals": { + "version": "6.9.4", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-property-literals/-/babel-plugin-transform-property-literals-6.9.4.tgz", + "integrity": "sha1-mMHSHiVXNlc/k+zlRFn2ziSYXTk=", + "dev": true, + "requires": { + "esutils": "^2.0.2" + } + }, + "babel-plugin-transform-regenerator": { + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-regenerator/-/babel-plugin-transform-regenerator-6.26.0.tgz", + "integrity": "sha1-4HA2lvveJ/Cj78rPi03KL3s6jy8=", + "dev": true, + "requires": { + "regenerator-transform": "^0.10.0" + } + }, + "babel-plugin-transform-regexp-constructors": { + "version": "0.4.3", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-regexp-constructors/-/babel-plugin-transform-regexp-constructors-0.4.3.tgz", + "integrity": "sha1-WLd3W2OvzzMyj66aX4j71PsLSWU=", + "dev": true + }, + "babel-plugin-transform-remove-console": { + "version": "6.9.4", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-remove-console/-/babel-plugin-transform-remove-console-6.9.4.tgz", + "integrity": "sha1-uYA2DAZzhOJLNXpYjYB9PINSd4A=", + "dev": true + }, + "babel-plugin-transform-remove-debugger": { + "version": "6.9.4", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-remove-debugger/-/babel-plugin-transform-remove-debugger-6.9.4.tgz", + "integrity": "sha1-QrcnYxyXl44estGZp67IShgznvI=", + "dev": true + }, + "babel-plugin-transform-remove-undefined": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-remove-undefined/-/babel-plugin-transform-remove-undefined-0.5.0.tgz", + "integrity": "sha512-+M7fJYFaEE/M9CXa0/IRkDbiV3wRELzA1kKQFCJ4ifhrzLKn/9VCCgj9OFmYWwBd8IB48YdgPkHYtbYq+4vtHQ==", + "dev": true, + "requires": { + "babel-helper-evaluate-path": "^0.5.0" + } + }, + "babel-plugin-transform-simplify-comparison-operators": { + "version": "6.9.4", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-simplify-comparison-operators/-/babel-plugin-transform-simplify-comparison-operators-6.9.4.tgz", + "integrity": "sha1-9ir+CWyrDh9ootdT/fKDiIRxzrk=", + "dev": true + }, + "babel-plugin-transform-strict-mode": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-strict-mode/-/babel-plugin-transform-strict-mode-6.24.1.tgz", + "integrity": "sha1-1fr3qleKZbvlkc9e2uBKDGcCB1g=", + "dev": true, + "requires": { + "babel-runtime": "^6.22.0", + "babel-types": "^6.24.1" + } + }, + "babel-plugin-transform-undefined-to-void": { + "version": "6.9.4", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-undefined-to-void/-/babel-plugin-transform-undefined-to-void-6.9.4.tgz", + "integrity": "sha1-viQcqBQEAwZ4t0hxcyK4nQyP4oA=", + "dev": true + }, + "babel-preset-env": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/babel-preset-env/-/babel-preset-env-1.7.0.tgz", + "integrity": "sha512-9OR2afuKDneX2/q2EurSftUYM0xGu4O2D9adAhVfADDhrYDaxXV0rBbevVYoY9n6nyX1PmQW/0jtpJvUNr9CHg==", + "dev": true, + "requires": { + "babel-plugin-check-es2015-constants": "^6.22.0", + "babel-plugin-syntax-trailing-function-commas": "^6.22.0", + "babel-plugin-transform-async-to-generator": "^6.22.0", + "babel-plugin-transform-es2015-arrow-functions": "^6.22.0", + "babel-plugin-transform-es2015-block-scoped-functions": "^6.22.0", + "babel-plugin-transform-es2015-block-scoping": "^6.23.0", + "babel-plugin-transform-es2015-classes": "^6.23.0", + "babel-plugin-transform-es2015-computed-properties": "^6.22.0", + "babel-plugin-transform-es2015-destructuring": "^6.23.0", + "babel-plugin-transform-es2015-duplicate-keys": "^6.22.0", + "babel-plugin-transform-es2015-for-of": "^6.23.0", + "babel-plugin-transform-es2015-function-name": "^6.22.0", + "babel-plugin-transform-es2015-literals": "^6.22.0", + "babel-plugin-transform-es2015-modules-amd": "^6.22.0", + "babel-plugin-transform-es2015-modules-commonjs": "^6.23.0", + "babel-plugin-transform-es2015-modules-systemjs": "^6.23.0", + "babel-plugin-transform-es2015-modules-umd": "^6.23.0", + "babel-plugin-transform-es2015-object-super": "^6.22.0", + "babel-plugin-transform-es2015-parameters": "^6.23.0", + "babel-plugin-transform-es2015-shorthand-properties": "^6.22.0", + "babel-plugin-transform-es2015-spread": "^6.22.0", + "babel-plugin-transform-es2015-sticky-regex": "^6.22.0", + "babel-plugin-transform-es2015-template-literals": "^6.22.0", + "babel-plugin-transform-es2015-typeof-symbol": "^6.23.0", + "babel-plugin-transform-es2015-unicode-regex": "^6.22.0", + "babel-plugin-transform-exponentiation-operator": "^6.22.0", + "babel-plugin-transform-regenerator": "^6.22.0", + "browserslist": "^3.2.6", + "invariant": "^2.2.2", + "semver": "^5.3.0" + } + }, + "babel-preset-minify": { + "version": "0.5.1", + "resolved": "https://registry.npmjs.org/babel-preset-minify/-/babel-preset-minify-0.5.1.tgz", + "integrity": "sha512-1IajDumYOAPYImkHbrKeiN5AKKP9iOmRoO2IPbIuVp0j2iuCcj0n7P260z38siKMZZ+85d3mJZdtW8IgOv+Tzg==", + "dev": true, + "requires": { + "babel-plugin-minify-builtins": "^0.5.0", + "babel-plugin-minify-constant-folding": "^0.5.0", + "babel-plugin-minify-dead-code-elimination": "^0.5.1", + "babel-plugin-minify-flip-comparisons": "^0.4.3", + "babel-plugin-minify-guarded-expressions": "^0.4.4", + "babel-plugin-minify-infinity": "^0.4.3", + "babel-plugin-minify-mangle-names": "^0.5.0", + "babel-plugin-minify-numeric-literals": "^0.4.3", + "babel-plugin-minify-replace": "^0.5.0", + "babel-plugin-minify-simplify": "^0.5.1", + "babel-plugin-minify-type-constructors": "^0.4.3", + "babel-plugin-transform-inline-consecutive-adds": "^0.4.3", + "babel-plugin-transform-member-expression-literals": "^6.9.4", + "babel-plugin-transform-merge-sibling-variables": "^6.9.4", + "babel-plugin-transform-minify-booleans": "^6.9.4", + "babel-plugin-transform-property-literals": "^6.9.4", + "babel-plugin-transform-regexp-constructors": "^0.4.3", + "babel-plugin-transform-remove-console": "^6.9.4", + "babel-plugin-transform-remove-debugger": "^6.9.4", + "babel-plugin-transform-remove-undefined": "^0.5.0", + "babel-plugin-transform-simplify-comparison-operators": "^6.9.4", + "babel-plugin-transform-undefined-to-void": "^6.9.4", + "lodash": "^4.17.11" + } + }, + "babel-register": { + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/babel-register/-/babel-register-6.26.0.tgz", + "integrity": "sha1-btAhFz4vy0htestFxgCahW9kcHE=", + "dev": true, + "requires": { + "babel-core": "^6.26.0", + "babel-runtime": "^6.26.0", + "core-js": "^2.5.0", + "home-or-tmp": "^2.0.0", + "lodash": "^4.17.4", + "mkdirp": "^0.5.1", + "source-map-support": "^0.4.15" + } + }, + "babel-runtime": { + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/babel-runtime/-/babel-runtime-6.26.0.tgz", + "integrity": "sha1-llxwWGaOgrVde/4E/yM3vItWR/4=", + "dev": true, + "requires": { + "core-js": "^2.4.0", + "regenerator-runtime": "^0.11.0" + } + }, + "babel-template": { + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/babel-template/-/babel-template-6.26.0.tgz", + "integrity": "sha1-3gPi0WOWsGn0bdn/+FIfsaDjXgI=", + "dev": true, + "requires": { + "babel-runtime": "^6.26.0", + "babel-traverse": "^6.26.0", + "babel-types": "^6.26.0", + "babylon": "^6.18.0", + "lodash": "^4.17.4" + } + }, + "babel-traverse": { + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/babel-traverse/-/babel-traverse-6.26.0.tgz", + "integrity": "sha1-RqnL1+3MYsjlwGTi0tjQ9ANXZu4=", + "dev": true, + "requires": { + "babel-code-frame": "^6.26.0", + "babel-messages": "^6.23.0", + "babel-runtime": "^6.26.0", + "babel-types": "^6.26.0", + "babylon": "^6.18.0", + "debug": "^2.6.8", + "globals": "^9.18.0", + "invariant": "^2.2.2", + "lodash": "^4.17.4" + } + }, + "babel-types": { + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/babel-types/-/babel-types-6.26.0.tgz", + "integrity": "sha1-o7Bz+Uq0nrb6Vc1lInozQ4BjJJc=", + "dev": true, + "requires": { + "babel-runtime": "^6.26.0", + "esutils": "^2.0.2", + "lodash": "^4.17.4", + "to-fast-properties": "^1.0.3" + } + }, + "babylon": { + "version": "6.18.0", + "resolved": "https://registry.npmjs.org/babylon/-/babylon-6.18.0.tgz", + "integrity": "sha512-q/UEjfGJ2Cm3oKV71DJz9d25TPnq5rhBVL2Q4fA5wcC3jcrdn7+SssEybFIxwAvvP+YCsCYNKughoF33GxgycQ==", + "dev": true + }, + "balanced-match": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", + "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=", + "dev": true + }, + "binary-extensions": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.0.0.tgz", + "integrity": "sha512-Phlt0plgpIIBOGTT/ehfFnbNlfsDEiqmzE2KRXoX1bLIlir4X/MR+zSyBEkL05ffWgnRSf/DXv+WrUAVr93/ow==", + "dev": true + }, + "bluebird": { + "version": "3.5.5", + "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.5.5.tgz", + "integrity": "sha512-5am6HnnfN+urzt4yfg7IgTbotDjIT/u8AJpEt0sIU9FtXfVeezXAPKswrG+xKUCOYAINpSdgZVDU6QFh+cuH3w==", + "dev": true + }, + "blueimp-md5": { + "version": "2.11.1", + "resolved": "https://registry.npmjs.org/blueimp-md5/-/blueimp-md5-2.11.1.tgz", + "integrity": "sha512-4UiOAmql2XO0Sws07OVzYdCKK0K2Va5g6AVgYXoGhEQiKrdSOefjUCm1frPk6E+xiIOHRqaFg+TUGo7cClKg5g==", + "dev": true + }, + "boxen": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/boxen/-/boxen-3.2.0.tgz", + "integrity": "sha512-cU4J/+NodM3IHdSL2yN8bqYqnmlBTidDR4RC7nJs61ZmtGz8VZzM3HLQX0zY5mrSmPtR3xWwsq2jOUQqFZN8+A==", + "dev": true, + "requires": { + "ansi-align": "^3.0.0", + "camelcase": "^5.3.1", + "chalk": "^2.4.2", + "cli-boxes": "^2.2.0", + "string-width": "^3.0.0", + "term-size": "^1.2.0", + "type-fest": "^0.3.0", + "widest-line": "^2.0.0" + }, + "dependencies": { + "camelcase": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", + "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", + "dev": true + }, + "emoji-regex": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-7.0.3.tgz", + "integrity": "sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA==", + "dev": true + }, + "string-width": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz", + "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==", + "dev": true, + "requires": { + "emoji-regex": "^7.0.1", + "is-fullwidth-code-point": "^2.0.0", + "strip-ansi": "^5.1.0" + } + }, + "type-fest": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.3.1.tgz", + "integrity": "sha512-cUGJnCdr4STbePCgqNFbpVNCepa+kAVohJs1sLhxzdH+gnEoOd8VhbYa7pD3zZYGiURWM2xzEII3fQcRizDkYQ==", + "dev": true + } + } + }, + "brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "requires": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "braces": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", + "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", + "dev": true, + "requires": { + "fill-range": "^7.0.1" + } + }, + "browserslist": { + "version": "3.2.8", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-3.2.8.tgz", + "integrity": "sha512-WHVocJYavUwVgVViC0ORikPHQquXwVh939TaelZ4WDqpWgTX/FsGhl/+P4qBUAGcRvtOgDgC+xftNWWp2RUTAQ==", + "dev": true, + "requires": { + "caniuse-lite": "^1.0.30000844", + "electron-to-chromium": "^1.3.47" + } + }, + "buffer-from": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.1.tgz", + "integrity": "sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A==", + "dev": true + }, + "builtin-modules": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/builtin-modules/-/builtin-modules-3.1.0.tgz", + "integrity": "sha512-k0KL0aWZuBt2lrxrcASWDfwOLMnodeQjodT/1SxEQAXsHANgo6ZC/VEaSEHCXt7aSTZ4/4H5LKa+tBXmW7Vtvw==", + "dev": true + }, + "cacheable-request": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/cacheable-request/-/cacheable-request-6.1.0.tgz", + "integrity": "sha512-Oj3cAGPCqOZX7Rz64Uny2GYAZNliQSqfbePrgAQ1wKAihYmCUnraBtJtKcGR4xz7wF+LoJC+ssFZvv5BgF9Igg==", + "dev": true, + "requires": { + "clone-response": "^1.0.2", + "get-stream": "^5.1.0", + "http-cache-semantics": "^4.0.0", + "keyv": "^3.0.0", + "lowercase-keys": "^2.0.0", + "normalize-url": "^4.1.0", + "responselike": "^1.0.2" + }, + "dependencies": { + "get-stream": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-5.1.0.tgz", + "integrity": "sha512-EXr1FOzrzTfGeL0gQdeFEvOMm2mzMOglyiOXSTpPC+iAjAKftbr3jpCMWynogwYnM+eSj9sHGc6wjIcDvYiygw==", + "dev": true, + "requires": { + "pump": "^3.0.0" + } + }, + "lowercase-keys": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-2.0.0.tgz", + "integrity": "sha512-tqNXrS78oMOE73NMxK4EMLQsQowWf8jKooH9g7xPavRT706R6bkQJ6DY2Te7QukaZsulxa30wQ7bk0pm4XiHmA==", + "dev": true + } + } + }, + "caching-transform": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/caching-transform/-/caching-transform-3.0.2.tgz", + "integrity": "sha512-Mtgcv3lh3U0zRii/6qVgQODdPA4G3zhG+jtbCWj39RXuUFTMzH0vcdMtaJS1jPowd+It2Pqr6y3NJMQqOqCE2w==", + "dev": true, + "requires": { + "hasha": "^3.0.0", + "make-dir": "^2.0.0", + "package-hash": "^3.0.0", + "write-file-atomic": "^2.4.2" + }, + "dependencies": { + "hasha": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/hasha/-/hasha-3.0.0.tgz", + "integrity": "sha1-UqMvq4Vp1BymmmH/GiFPjrfIvTk=", + "dev": true, + "requires": { + "is-stream": "^1.0.1" + } + }, + "make-dir": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-2.1.0.tgz", + "integrity": "sha512-LS9X+dc8KLxXCb8dni79fLIIUA5VyZoyjSMCwTluaXA0o27cCK0bhXkpgw+sTXVpPy/lSO57ilRixqk0vDmtRA==", + "dev": true, + "requires": { + "pify": "^4.0.1", + "semver": "^5.6.0" + } + }, + "package-hash": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/package-hash/-/package-hash-3.0.0.tgz", + "integrity": "sha512-lOtmukMDVvtkL84rJHI7dpTYq+0rli8N2wlnqUcBuDWCfVhRUfOmnR9SsoHFMLpACvEV60dX7rd0rFaYDZI+FA==", + "dev": true, + "requires": { + "graceful-fs": "^4.1.15", + "hasha": "^3.0.0", + "lodash.flattendeep": "^4.4.0", + "release-zalgo": "^1.0.0" + } + }, + "pify": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/pify/-/pify-4.0.1.tgz", + "integrity": "sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==", + "dev": true + }, + "write-file-atomic": { + "version": "2.4.3", + "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-2.4.3.tgz", + "integrity": "sha512-GaETH5wwsX+GcnzhPgKcKjJ6M2Cq3/iZp1WyY/X1CSqrW+jVNM9Y7D8EC2sM4ZG/V8wZlSniJnCKWPmBYAucRQ==", + "dev": true, + "requires": { + "graceful-fs": "^4.1.11", + "imurmurhash": "^0.1.4", + "signal-exit": "^3.0.2" + } + } + } + }, + "call-matcher": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/call-matcher/-/call-matcher-1.1.0.tgz", + "integrity": "sha512-IoQLeNwwf9KTNbtSA7aEBb1yfDbdnzwjCetjkC8io5oGeOmK2CBNdg0xr+tadRYKO0p7uQyZzvon0kXlZbvGrw==", + "dev": true, + "requires": { + "core-js": "^2.0.0", + "deep-equal": "^1.0.0", + "espurify": "^1.6.0", + "estraverse": "^4.0.0" + } + }, + "call-signature": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/call-signature/-/call-signature-0.0.2.tgz", + "integrity": "sha1-qEq8glpV70yysCi9dOIFpluaSZY=", + "dev": true + }, + "callsites": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", + "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", + "dev": true + }, + "camelcase": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-4.1.0.tgz", + "integrity": "sha1-1UVjW+HjPFQmScaRc+Xeas+uNN0=", + "dev": true + }, + "camelcase-keys": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/camelcase-keys/-/camelcase-keys-4.2.0.tgz", + "integrity": "sha1-oqpfsa9oh1glnDLBQUJteJI7m3c=", + "dev": true, + "requires": { + "camelcase": "^4.1.0", + "map-obj": "^2.0.0", + "quick-lru": "^1.0.0" + } + }, + "caniuse-lite": { + "version": "1.0.30000989", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30000989.tgz", + "integrity": "sha512-vrMcvSuMz16YY6GSVZ0dWDTJP8jqk3iFQ/Aq5iqblPwxSVVZI+zxDyTX0VPqtQsDnfdrBDcsmhgTEOh5R8Lbpw==", + "dev": true + }, + "chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "requires": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + }, + "dependencies": { + "ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "requires": { + "color-convert": "^1.9.0" + } + }, + "supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "requires": { + "has-flag": "^3.0.0" + } + } + } + }, + "chardet": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/chardet/-/chardet-0.7.0.tgz", + "integrity": "sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA==", + "dev": true + }, + "chokidar": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.0.2.tgz", + "integrity": "sha512-c4PR2egjNjI1um6bamCQ6bUNPDiyofNQruHvKgHQ4gDUP/ITSVSzNsiI5OWtHOsX323i5ha/kk4YmOZ1Ktg7KA==", + "dev": true, + "requires": { + "anymatch": "^3.0.1", + "braces": "^3.0.2", + "fsevents": "^2.0.6", + "glob-parent": "^5.0.0", + "is-binary-path": "^2.1.0", + "is-glob": "^4.0.1", + "normalize-path": "^3.0.0", + "readdirp": "^3.1.1" + } + }, + "chunkd": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/chunkd/-/chunkd-1.0.0.tgz", + "integrity": "sha512-xx3Pb5VF9QaqCotolyZ1ywFBgyuJmu6+9dLiqBxgelEse9Xsr3yUlpoX3O4Oh11M00GT2kYMsRByTKIMJW2Lkg==", + "dev": true + }, + "ci-info": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-2.0.0.tgz", + "integrity": "sha512-5tK7EtrZ0N+OLFMthtqOj4fI2Jeb88C4CAZPu25LDVUgXJ0A3Js4PMGqrn0JU1W0Mh1/Z8wZzYPxqUrXeBboCQ==", + "dev": true + }, + "ci-parallel-vars": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/ci-parallel-vars/-/ci-parallel-vars-1.0.0.tgz", + "integrity": "sha512-u6dx20FBXm+apMi+5x7UVm6EH7BL1gc4XrcnQewjcB7HWRcor/V5qWc3RG2HwpgDJ26gIi2DSEu3B7sXynAw/g==", + "dev": true + }, + "clean-stack": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/clean-stack/-/clean-stack-2.2.0.tgz", + "integrity": "sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A==", + "dev": true + }, + "clean-yaml-object": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/clean-yaml-object/-/clean-yaml-object-0.1.0.tgz", + "integrity": "sha1-Y/sRDcLOGoTcIfbZM0h20BCui2g=", + "dev": true + }, + "cli-boxes": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/cli-boxes/-/cli-boxes-2.2.0.tgz", + "integrity": "sha512-gpaBrMAizVEANOpfZp/EEUixTXDyGt7DFzdK5hU+UbWt/J0lB0w20ncZj59Z9a93xHb9u12zF5BS6i9RKbtg4w==", + "dev": true + }, + "cli-cursor": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-3.1.0.tgz", + "integrity": "sha512-I/zHAwsKf9FqGoXM4WWRACob9+SNukZTd94DWF57E4toouRulbCxcUh6RKUEOQlYTHJnzkPMySvPNaaSLNfLZw==", + "dev": true, + "requires": { + "restore-cursor": "^3.1.0" + } + }, + "cli-spinners": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/cli-spinners/-/cli-spinners-2.2.0.tgz", + "integrity": "sha512-tgU3fKwzYjiLEQgPMD9Jt+JjHVL9kW93FiIMX/l7rivvOD4/LL0Mf7gda3+4U2KJBloybwgj5KEoQgGRioMiKQ==", + "dev": true + }, + "cli-truncate": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/cli-truncate/-/cli-truncate-2.0.0.tgz", + "integrity": "sha512-C4hp+8GCIFVsUUiXcw+ce+7wexVWImw8rQrgMBFsqerx9LvvcGlwm6sMjQYAEmV/Xb87xc1b5Ttx505MSpZVqg==", + "dev": true, + "requires": { + "slice-ansi": "^2.1.0", + "string-width": "^4.1.0" + } + }, + "cli-width": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/cli-width/-/cli-width-2.2.0.tgz", + "integrity": "sha1-/xnt6Kml5XkyQUewwR8PvLq+1jk=", + "dev": true + }, + "cliui": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-5.0.0.tgz", + "integrity": "sha512-PYeGSEmmHM6zvoef2w8TPzlrnNpXIjTipYK780YswmIP9vjxmd6Y2a3CB2Ks6/AU8NHjZugXvo8w3oWM2qnwXA==", + "dev": true, + "requires": { + "string-width": "^3.1.0", + "strip-ansi": "^5.2.0", + "wrap-ansi": "^5.1.0" + }, + "dependencies": { + "emoji-regex": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-7.0.3.tgz", + "integrity": "sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA==", + "dev": true + }, + "string-width": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz", + "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==", + "dev": true, + "requires": { + "emoji-regex": "^7.0.1", + "is-fullwidth-code-point": "^2.0.0", + "strip-ansi": "^5.1.0" + } + } + } + }, + "clone": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/clone/-/clone-1.0.4.tgz", + "integrity": "sha1-2jCcwmPfFZlMaIypAheco8fNfH4=", + "dev": true + }, + "clone-response": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/clone-response/-/clone-response-1.0.2.tgz", + "integrity": "sha1-0dyXOSAxTfZ/vrlCI7TuNQI56Ws=", + "dev": true, + "requires": { + "mimic-response": "^1.0.0" + } + }, + "code-excerpt": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/code-excerpt/-/code-excerpt-2.1.1.tgz", + "integrity": "sha512-tJLhH3EpFm/1x7heIW0hemXJTUU5EWl2V0EIX558jp05Mt1U6DVryCgkp3l37cxqs+DNbNgxG43SkwJXpQ14Jw==", + "dev": true, + "requires": { + "convert-to-spaces": "^1.0.1" + } + }, + "color-convert": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "dev": true, + "requires": { + "color-name": "1.1.3" + } + }, + "color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=", + "dev": true + }, + "commander": { + "version": "2.20.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.0.tgz", + "integrity": "sha512-7j2y+40w61zy6YC2iRNpUe/NwhNyoXrYpHMrSunaMG64nRnaf96zO/KMQR4OyN/UnE5KLyEBnKHd4aG3rskjpQ==", + "dev": true, + "optional": true + }, + "common-path-prefix": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/common-path-prefix/-/common-path-prefix-1.0.0.tgz", + "integrity": "sha1-zVL28HEuC6q5fW+XModPIvR3UsA=", + "dev": true + }, + "commondir": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/commondir/-/commondir-1.0.1.tgz", + "integrity": "sha1-3dgA2gxmEnOTzKWVDqloo6rxJTs=", + "dev": true + }, + "concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=", + "dev": true + }, + "concordance": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/concordance/-/concordance-4.0.0.tgz", + "integrity": "sha512-l0RFuB8RLfCS0Pt2Id39/oCPykE01pyxgAFypWTlaGRgvLkZrtczZ8atEHpTeEIW+zYWXTBuA9cCSeEOScxReQ==", + "dev": true, + "requires": { + "date-time": "^2.1.0", + "esutils": "^2.0.2", + "fast-diff": "^1.1.2", + "js-string-escape": "^1.0.1", + "lodash.clonedeep": "^4.5.0", + "lodash.flattendeep": "^4.4.0", + "lodash.islength": "^4.0.1", + "lodash.merge": "^4.6.1", + "md5-hex": "^2.0.0", + "semver": "^5.5.1", + "well-known-symbols": "^2.0.0" + }, + "dependencies": { + "md5-hex": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/md5-hex/-/md5-hex-2.0.0.tgz", + "integrity": "sha1-0FiOnxx0lUSS7NJKwKxs6ZfZLjM=", + "dev": true, + "requires": { + "md5-o-matic": "^0.1.1" + } + } + } + }, + "configstore": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/configstore/-/configstore-4.0.0.tgz", + "integrity": "sha512-CmquAXFBocrzaSM8mtGPMM/HiWmyIpr4CcJl/rgY2uCObZ/S7cKU0silxslqJejl+t/T9HS8E0PUNQD81JGUEQ==", + "dev": true, + "requires": { + "dot-prop": "^4.1.0", + "graceful-fs": "^4.1.2", + "make-dir": "^1.0.0", + "unique-string": "^1.0.0", + "write-file-atomic": "^2.0.0", + "xdg-basedir": "^3.0.0" + }, + "dependencies": { + "dot-prop": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/dot-prop/-/dot-prop-4.2.0.tgz", + "integrity": "sha512-tUMXrxlExSW6U2EXiiKGSBVdYgtV8qlHL+C10TsW4PURY/ic+eaysnSkwB4kA/mBlCyy/IKDJ+Lc3wbWeaXtuQ==", + "dev": true, + "requires": { + "is-obj": "^1.0.0" + } + }, + "is-obj": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-obj/-/is-obj-1.0.1.tgz", + "integrity": "sha1-PkcprB9f3gJc19g6iW2rn09n2w8=", + "dev": true + }, + "make-dir": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-1.3.0.tgz", + "integrity": "sha512-2w31R7SJtieJJnQtGc7RVL2StM2vGYVfqUOvUDxH6bC6aJTxPxTF0GnIgCyu7tjockiUWAYQRbxa7vKn34s5sQ==", + "dev": true, + "requires": { + "pify": "^3.0.0" + } + }, + "pify": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", + "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=", + "dev": true + }, + "write-file-atomic": { + "version": "2.4.3", + "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-2.4.3.tgz", + "integrity": "sha512-GaETH5wwsX+GcnzhPgKcKjJ6M2Cq3/iZp1WyY/X1CSqrW+jVNM9Y7D8EC2sM4ZG/V8wZlSniJnCKWPmBYAucRQ==", + "dev": true, + "requires": { + "graceful-fs": "^4.1.11", + "imurmurhash": "^0.1.4", + "signal-exit": "^3.0.2" + } + } + } + }, + "confusing-browser-globals": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/confusing-browser-globals/-/confusing-browser-globals-1.0.8.tgz", + "integrity": "sha512-lI7asCibVJ6Qd3FGU7mu4sfG4try4LX3+GVS+Gv8UlrEf2AeW57piecapnog2UHZSbcX/P/1UDWVaTsblowlZg==", + "dev": true + }, + "contains-path": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/contains-path/-/contains-path-0.1.0.tgz", + "integrity": "sha1-/ozxhP9mcLa67wGp1IYaXL7EEgo=", + "dev": true + }, + "convert-source-map": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.6.0.tgz", + "integrity": "sha512-eFu7XigvxdZ1ETfbgPBohgyQ/Z++C0eEhTor0qRwBw9unw+L0/6V8wkSuGgzdThkiS5lSpdptOQPD8Ak40a+7A==", + "dev": true, + "requires": { + "safe-buffer": "~5.1.1" + }, + "dependencies": { + "safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "dev": true + } + } + }, + "convert-to-spaces": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/convert-to-spaces/-/convert-to-spaces-1.0.2.tgz", + "integrity": "sha1-fj5Iu+bZl7FBfdyihoIEtNPYVxU=", + "dev": true + }, + "core-js": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/core-js/-/core-js-2.6.9.tgz", + "integrity": "sha512-HOpZf6eXmnl7la+cUdMnLvUxKNqLUzJvgIziQ0DiF3JwSImNphIqdGqzj6hIKyX04MmV0poclQ7+wjWvxQyR2A==", + "dev": true + }, + "cp-file": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/cp-file/-/cp-file-6.2.0.tgz", + "integrity": "sha512-fmvV4caBnofhPe8kOcitBwSn2f39QLjnAnGq3gO9dfd75mUytzKNZB1hde6QHunW2Rt+OwuBOMc3i1tNElbszA==", + "dev": true, + "requires": { + "graceful-fs": "^4.1.2", + "make-dir": "^2.0.0", + "nested-error-stacks": "^2.0.0", + "pify": "^4.0.1", + "safe-buffer": "^5.0.1" + }, + "dependencies": { + "make-dir": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-2.1.0.tgz", + "integrity": "sha512-LS9X+dc8KLxXCb8dni79fLIIUA5VyZoyjSMCwTluaXA0o27cCK0bhXkpgw+sTXVpPy/lSO57ilRixqk0vDmtRA==", + "dev": true, + "requires": { + "pify": "^4.0.1", + "semver": "^5.6.0" + } + }, + "pify": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/pify/-/pify-4.0.1.tgz", + "integrity": "sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==", + "dev": true + } + } + }, + "cross-spawn": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-5.1.0.tgz", + "integrity": "sha1-6L0O/uWPz/b4+UUQoKVUu/ojVEk=", + "dev": true, + "requires": { + "lru-cache": "^4.0.1", + "shebang-command": "^1.2.0", + "which": "^1.2.9" + } + }, + "crypto-random-string": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/crypto-random-string/-/crypto-random-string-1.0.0.tgz", + "integrity": "sha1-ojD2T1aDEOFJgAmUB5DsmVRbyn4=", + "dev": true + }, + "currently-unhandled": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/currently-unhandled/-/currently-unhandled-0.4.1.tgz", + "integrity": "sha1-mI3zP+qxke95mmE2nddsF635V+o=", + "dev": true, + "requires": { + "array-find-index": "^1.0.1" + } + }, + "date-time": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/date-time/-/date-time-2.1.0.tgz", + "integrity": "sha512-/9+C44X7lot0IeiyfgJmETtRMhBidBYM2QFFIkGa0U1k+hSyY87Nw7PY3eDqpvCBm7I3WCSfPeZskW/YYq6m4g==", + "dev": true, + "requires": { + "time-zone": "^1.0.0" + } + }, + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "requires": { + "ms": "2.0.0" + }, + "dependencies": { + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", + "dev": true + } + } + }, + "decamelize": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", + "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=", + "dev": true + }, + "decamelize-keys": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/decamelize-keys/-/decamelize-keys-1.1.0.tgz", + "integrity": "sha1-0XGoeTMlKAfrPLYdwcFEXQeN8tk=", + "dev": true, + "requires": { + "decamelize": "^1.1.0", + "map-obj": "^1.0.0" + }, + "dependencies": { + "map-obj": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/map-obj/-/map-obj-1.0.1.tgz", + "integrity": "sha1-2TPOuSBdgr3PSIb2dCvcK03qFG0=", + "dev": true + } + } + }, + "decompress-response": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-3.3.0.tgz", + "integrity": "sha1-gKTdMjdIOEv6JICDYirt7Jgq3/M=", + "dev": true, + "requires": { + "mimic-response": "^1.0.0" + } + }, + "deep-equal": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/deep-equal/-/deep-equal-1.0.1.tgz", + "integrity": "sha1-9dJgKStmDghO/0zbyfCK0yR0SLU=", + "dev": true + }, + "deep-extend": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz", + "integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==", + "dev": true + }, + "deep-is": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.3.tgz", + "integrity": "sha1-s2nW+128E+7PUk+RsHD+7cNXzzQ=", + "dev": true + }, + "default-require-extensions": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/default-require-extensions/-/default-require-extensions-2.0.0.tgz", + "integrity": "sha1-9fj7sYp9bVCyH2QfZJ67Uiz+JPc=", + "dev": true, + "requires": { + "strip-bom": "^3.0.0" + } + }, + "defaults": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/defaults/-/defaults-1.0.3.tgz", + "integrity": "sha1-xlYFHpgX2f8I7YgUd/P+QBnz730=", + "dev": true, + "requires": { + "clone": "^1.0.2" + } + }, + "defer-to-connect": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/defer-to-connect/-/defer-to-connect-1.0.2.tgz", + "integrity": "sha512-k09hcQcTDY+cwgiwa6PYKLm3jlagNzQ+RSvhjzESOGOx+MNOuXkxTfEvPrO1IOQ81tArCFYQgi631clB70RpQw==", + "dev": true + }, + "define-properties": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.3.tgz", + "integrity": "sha512-3MqfYKj2lLzdMSf8ZIZE/V+Zuy+BgD6f164e8K2w7dgnpKArBDerGYpM46IYYcjnkdPNMjPk9A6VFB8+3SKlXQ==", + "dev": true, + "requires": { + "object-keys": "^1.0.12" + } + }, + "del": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/del/-/del-4.1.1.tgz", + "integrity": "sha512-QwGuEUouP2kVwQenAsOof5Fv8K9t3D8Ca8NxcXKrIpEHjTXK5J2nXLdP+ALI1cgv8wj7KuwBhTwBkOZSJKM5XQ==", + "dev": true, + "requires": { + "@types/glob": "^7.1.1", + "globby": "^6.1.0", + "is-path-cwd": "^2.0.0", + "is-path-in-cwd": "^2.0.0", + "p-map": "^2.0.0", + "pify": "^4.0.1", + "rimraf": "^2.6.3" + }, + "dependencies": { + "array-union": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/array-union/-/array-union-1.0.2.tgz", + "integrity": "sha1-mjRBDk9OPaI96jdb5b5w8kd47Dk=", + "dev": true, + "requires": { + "array-uniq": "^1.0.1" + } + }, + "array-uniq": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/array-uniq/-/array-uniq-1.0.3.tgz", + "integrity": "sha1-r2rId6Jcx/dOBYiUdThY39sk/bY=", + "dev": true + }, + "globby": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/globby/-/globby-6.1.0.tgz", + "integrity": "sha1-9abXDoOV4hyFj7BInWTfAkJNUGw=", + "dev": true, + "requires": { + "array-union": "^1.0.1", + "glob": "^7.0.3", + "object-assign": "^4.0.1", + "pify": "^2.0.0", + "pinkie-promise": "^2.0.0" + }, + "dependencies": { + "pify": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", + "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", + "dev": true + } + } + }, + "pify": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/pify/-/pify-4.0.1.tgz", + "integrity": "sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==", + "dev": true + } + } + }, + "detect-indent": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/detect-indent/-/detect-indent-4.0.0.tgz", + "integrity": "sha1-920GQ1LN9Docts5hnE7jqUdd4gg=", + "dev": true, + "requires": { + "repeating": "^2.0.0" + } + }, + "dir-glob": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz", + "integrity": "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==", + "dev": true, + "requires": { + "path-type": "^4.0.0" + }, + "dependencies": { + "path-type": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", + "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==", + "dev": true + } + } + }, + "doctrine": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", + "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==", + "dev": true, + "requires": { + "esutils": "^2.0.2" + } + }, + "dot-prop": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/dot-prop/-/dot-prop-5.1.0.tgz", + "integrity": "sha512-n1oC6NBF+KM9oVXtjmen4Yo7HyAVWV2UUl50dCYJdw2924K6dX9bf9TTTWaKtYlRn0FEtxG27KS80ayVLixxJA==", + "dev": true, + "requires": { + "is-obj": "^2.0.0" + } + }, + "duplexer3": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/duplexer3/-/duplexer3-0.1.4.tgz", + "integrity": "sha1-7gHdHKwO08vH/b6jfcCo8c4ALOI=", + "dev": true + }, + "electron-to-chromium": { + "version": "1.3.236", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.236.tgz", + "integrity": "sha512-LWOvuJ80pLO3FtFqTcGuXB0dxdMtzSCkRmbXdY5mHUvXRQGor3sTVmyfU70aD2yF5i+fbHz52ncWr5T3xUYHlA==", + "dev": true + }, + "emittery": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/emittery/-/emittery-0.4.1.tgz", + "integrity": "sha512-r4eRSeStEGf6M5SKdrQhhLK5bOwOBxQhIE3YSTnZE3GpKiLfnnhE+tPtrJE79+eDJgm39BM6LSoI8SCx4HbwlQ==", + "dev": true + }, + "emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true + }, + "empower-core": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/empower-core/-/empower-core-1.2.0.tgz", + "integrity": "sha512-g6+K6Geyc1o6FdXs9HwrXleCFan7d66G5xSCfSF7x1mJDCes6t0om9lFQG3zOrzh3Bkb/45N0cZ5Gqsf7YrzGQ==", + "dev": true, + "requires": { + "call-signature": "0.0.2", + "core-js": "^2.0.0" + } + }, + "end-of-stream": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.1.tgz", + "integrity": "sha512-1MkrZNvWTKCaigbn+W15elq2BB/L22nqrSY5DKlo3X6+vclJm8Bb5djXJBmEX6fS3+zCh/F4VBK5Z2KxJt4s2Q==", + "dev": true, + "requires": { + "once": "^1.4.0" + } + }, + "equal-length": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/equal-length/-/equal-length-1.0.1.tgz", + "integrity": "sha1-IcoRLUirJLTh5//A5TOdMf38J0w=", + "dev": true + }, + "erlang-types": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/erlang-types/-/erlang-types-1.1.3.tgz", + "integrity": "sha512-HZWcirSqKIdasr04DT9NnYgVyqvUaefDPp2LhNgtBnM2ovOkUhJ4DEKVQZ71POKsu4wiR64EWhahA8AE9r796g==" + }, + "error-ex": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", + "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==", + "dev": true, + "requires": { + "is-arrayish": "^0.2.1" + } + }, + "es-abstract": { + "version": "1.13.0", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.13.0.tgz", + "integrity": "sha512-vDZfg/ykNxQVwup/8E1BZhVzFfBxs9NqMzGcvIJrqg5k2/5Za2bWo40dK2J1pgLngZ7c+Shh8lwYtLGyrwPutg==", + "dev": true, + "requires": { + "es-to-primitive": "^1.2.0", + "function-bind": "^1.1.1", + "has": "^1.0.3", + "is-callable": "^1.1.4", + "is-regex": "^1.0.4", + "object-keys": "^1.0.12" + } + }, + "es-to-primitive": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.0.tgz", + "integrity": "sha512-qZryBOJjV//LaxLTV6UC//WewneB3LcXOL9NP++ozKVXsIIIpm/2c13UDiD9Jp2eThsecw9m3jPqDwTyobcdbg==", + "dev": true, + "requires": { + "is-callable": "^1.1.4", + "is-date-object": "^1.0.1", + "is-symbol": "^1.0.2" + } + }, + "es6-error": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/es6-error/-/es6-error-4.1.1.tgz", + "integrity": "sha512-Um/+FxMr9CISWh0bi5Zv0iOD+4cFh5qLeks1qhAopKVAJw3drgKbKySikp7wGhDL0HPeaja0P5ULZrxLkniUVg==", + "dev": true + }, + "escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=", + "dev": true + }, + "eslint": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-6.2.1.tgz", + "integrity": "sha512-ES7BzEzr0Q6m5TK9i+/iTpKjclXitOdDK4vT07OqbkBT2/VcN/gO9EL1C4HlK3TAOXYv2ItcmbVR9jO1MR0fJg==", + "dev": true, + "requires": { + "@babel/code-frame": "^7.0.0", + "ajv": "^6.10.0", + "chalk": "^2.1.0", + "cross-spawn": "^6.0.5", + "debug": "^4.0.1", + "doctrine": "^3.0.0", + "eslint-scope": "^5.0.0", + "eslint-utils": "^1.4.2", + "eslint-visitor-keys": "^1.1.0", + "espree": "^6.1.0", + "esquery": "^1.0.1", + "esutils": "^2.0.2", + "file-entry-cache": "^5.0.1", + "functional-red-black-tree": "^1.0.1", + "glob-parent": "^5.0.0", + "globals": "^11.7.0", + "ignore": "^4.0.6", + "import-fresh": "^3.0.0", + "imurmurhash": "^0.1.4", + "inquirer": "^6.4.1", + "is-glob": "^4.0.0", + "js-yaml": "^3.13.1", + "json-stable-stringify-without-jsonify": "^1.0.1", + "levn": "^0.3.0", + "lodash": "^4.17.14", + "minimatch": "^3.0.4", + "mkdirp": "^0.5.1", + "natural-compare": "^1.4.0", + "optionator": "^0.8.2", + "progress": "^2.0.0", + "regexpp": "^2.0.1", + "semver": "^6.1.2", + "strip-ansi": "^5.2.0", + "strip-json-comments": "^3.0.1", + "table": "^5.2.3", + "text-table": "^0.2.0", + "v8-compile-cache": "^2.0.3" + }, + "dependencies": { + "cross-spawn": { + "version": "6.0.5", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-6.0.5.tgz", + "integrity": "sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ==", + "dev": true, + "requires": { + "nice-try": "^1.0.4", + "path-key": "^2.0.1", + "semver": "^5.5.0", + "shebang-command": "^1.2.0", + "which": "^1.2.9" + }, + "dependencies": { + "semver": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", + "dev": true + } + } + }, + "debug": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", + "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", + "dev": true, + "requires": { + "ms": "^2.1.1" + } + }, + "globals": { + "version": "11.12.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", + "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==", + "dev": true + }, + "ignore": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-4.0.6.tgz", + "integrity": "sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg==", + "dev": true + }, + "semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "dev": true + }, + "strip-json-comments": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.0.1.tgz", + "integrity": "sha512-VTyMAUfdm047mwKl+u79WIdrZxtFtn+nBxHeb844XBQ9uMNTuTHdx2hc5RiAJYqwTj3wc/xe5HLSdJSkJ+WfZw==", + "dev": true + } + } + }, + "eslint-config-airbnb-base": { + "version": "14.0.0", + "resolved": "https://registry.npmjs.org/eslint-config-airbnb-base/-/eslint-config-airbnb-base-14.0.0.tgz", + "integrity": "sha512-2IDHobw97upExLmsebhtfoD3NAKhV4H0CJWP3Uprd/uk+cHuWYOczPVxQ8PxLFUAw7o3Th1RAU8u1DoUpr+cMA==", + "dev": true, + "requires": { + "confusing-browser-globals": "^1.0.7", + "object.assign": "^4.1.0", + "object.entries": "^1.1.0" + } + }, + "eslint-import-resolver-node": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.2.tgz", + "integrity": "sha512-sfmTqJfPSizWu4aymbPr4Iidp5yKm8yDkHp+Ir3YiTHiiDfxh69mOUsmiqW6RZ9zRXFaF64GtYmN7e+8GHBv6Q==", + "dev": true, + "requires": { + "debug": "^2.6.9", + "resolve": "^1.5.0" + } + }, + "eslint-module-utils": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/eslint-module-utils/-/eslint-module-utils-2.4.1.tgz", + "integrity": "sha512-H6DOj+ejw7Tesdgbfs4jeS4YMFrT8uI8xwd1gtQqXssaR0EQ26L+2O/w6wkYFy2MymON0fTwHmXBvvfLNZVZEw==", + "dev": true, + "requires": { + "debug": "^2.6.8", + "pkg-dir": "^2.0.0" + } + }, + "eslint-plugin-import": { + "version": "2.18.2", + "resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.18.2.tgz", + "integrity": "sha512-5ohpsHAiUBRNaBWAF08izwUGlbrJoJJ+W9/TBwsGoR1MnlgfwMIKrFeSjWbt6moabiXW9xNvtFz+97KHRfI4HQ==", + "dev": true, + "requires": { + "array-includes": "^3.0.3", + "contains-path": "^0.1.0", + "debug": "^2.6.9", + "doctrine": "1.5.0", + "eslint-import-resolver-node": "^0.3.2", + "eslint-module-utils": "^2.4.0", + "has": "^1.0.3", + "minimatch": "^3.0.4", + "object.values": "^1.1.0", + "read-pkg-up": "^2.0.0", + "resolve": "^1.11.0" + }, + "dependencies": { + "doctrine": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-1.5.0.tgz", + "integrity": "sha1-N53Ocw9hZvds76TmcHoVmwLFpvo=", + "dev": true, + "requires": { + "esutils": "^2.0.2", + "isarray": "^1.0.0" + } + } + } + }, + "eslint-scope": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.0.0.tgz", + "integrity": "sha512-oYrhJW7S0bxAFDvWqzvMPRm6pcgcnWc4QnofCAqRTRfQC0JcwenzGglTtsLyIuuWFfkqDG9vz67cnttSd53djw==", + "dev": true, + "requires": { + "esrecurse": "^4.1.0", + "estraverse": "^4.1.1" + } + }, + "eslint-utils": { + "version": "1.4.2", + "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-1.4.2.tgz", + "integrity": "sha512-eAZS2sEUMlIeCjBeubdj45dmBHQwPHWyBcT1VSYB7o9x9WRRqKxyUoiXlRjyAwzN7YEzHJlYg0NmzDRWx6GP4Q==", + "dev": true, + "requires": { + "eslint-visitor-keys": "^1.0.0" + } + }, + "eslint-visitor-keys": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.1.0.tgz", + "integrity": "sha512-8y9YjtM1JBJU/A9Kc+SbaOV4y29sSWckBwMHa+FGtVj5gN/sbnKDf6xJUl+8g7FAij9LVaP8C24DUiH/f/2Z9A==", + "dev": true + }, + "esm": { + "version": "3.2.25", + "resolved": "https://registry.npmjs.org/esm/-/esm-3.2.25.tgz", + "integrity": "sha512-U1suiZ2oDVWv4zPO56S0NcR5QriEahGtdN2OR6FiOG4WJvcjBVFB0qI4+eKoWFH483PKGuLuu6V8Z4T5g63UVA==", + "dev": true + }, + "espower-location-detector": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/espower-location-detector/-/espower-location-detector-1.0.0.tgz", + "integrity": "sha1-oXt+zFnTDheeK+9z+0E3cEyzMbU=", + "dev": true, + "requires": { + "is-url": "^1.2.1", + "path-is-absolute": "^1.0.0", + "source-map": "^0.5.0", + "xtend": "^4.0.0" + } + }, + "espree": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/espree/-/espree-6.1.0.tgz", + "integrity": "sha512-boA7CHRLlVWUSg3iL5Kmlt/xT3Q+sXnKoRYYzj1YeM10A76TEJBbotV5pKbnK42hEUIr121zTv+QLRM5LsCPXQ==", + "dev": true, + "requires": { + "acorn": "^7.0.0", + "acorn-jsx": "^5.0.0", + "eslint-visitor-keys": "^1.1.0" + } + }, + "esprima": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", + "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", + "dev": true + }, + "espurify": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/espurify/-/espurify-1.8.1.tgz", + "integrity": "sha512-ZDko6eY/o+D/gHCWyHTU85mKDgYcS4FJj7S+YD6WIInm7GQ6AnOjmcL4+buFV/JOztVLELi/7MmuGU5NHta0Mg==", + "dev": true, + "requires": { + "core-js": "^2.0.0" + } + }, + "esquery": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.0.1.tgz", + "integrity": "sha512-SmiyZ5zIWH9VM+SRUReLS5Q8a7GxtRdxEBVZpm98rJM7Sb+A9DVCndXfkeFUd3byderg+EbDkfnevfCwynWaNA==", + "dev": true, + "requires": { + "estraverse": "^4.0.0" + } + }, + "esrecurse": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.2.1.tgz", + "integrity": "sha512-64RBB++fIOAXPw3P9cy89qfMlvZEXZkqqJkjqqXIvzP5ezRZjW+lPWjw35UX/3EhUPFYbg5ER4JYgDw4007/DQ==", + "dev": true, + "requires": { + "estraverse": "^4.1.0" + } + }, + "estraverse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", + "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", + "dev": true + }, + "estree-walker": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-0.6.1.tgz", + "integrity": "sha512-SqmZANLWS0mnatqbSfRP5g8OXZC12Fgg1IwNtLsyHDzJizORW4khDfjPqJZsemPWBB2uqykUah5YpQ6epsqC/w==" + }, + "esutils": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", + "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", + "dev": true + }, + "execa": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/execa/-/execa-0.7.0.tgz", + "integrity": "sha1-lEvs00zEHuMqY6n68nrVpl/Fl3c=", + "dev": true, + "requires": { + "cross-spawn": "^5.0.1", + "get-stream": "^3.0.0", + "is-stream": "^1.1.0", + "npm-run-path": "^2.0.0", + "p-finally": "^1.0.0", + "signal-exit": "^3.0.0", + "strip-eof": "^1.0.0" + } + }, + "external-editor": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/external-editor/-/external-editor-3.1.0.tgz", + "integrity": "sha512-hMQ4CX1p1izmuLYyZqLMO/qGNw10wSv9QDCPfzXfyFrOaCSSoRfqE1Kf1s5an66J5JZC62NewG+mK49jOCtQew==", + "dev": true, + "requires": { + "chardet": "^0.7.0", + "iconv-lite": "^0.4.24", + "tmp": "^0.0.33" + } + }, + "fast-deep-equal": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-2.0.1.tgz", + "integrity": "sha1-ewUhjd+WZ79/Nwv3/bLLFf3Qqkk=", + "dev": true + }, + "fast-diff": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/fast-diff/-/fast-diff-1.2.0.tgz", + "integrity": "sha512-xJuoT5+L99XlZ8twedaRf6Ax2TgQVxvgZOYoPKqZufmJib0tL2tegPBOZb1pVNgIhlqDlA0eO0c3wBvQcmzx4w==", + "dev": true + }, + "fast-glob": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.0.4.tgz", + "integrity": "sha512-wkIbV6qg37xTJwqSsdnIphL1e+LaGz4AIQqr00mIubMaEhv1/HEmJ0uuCGZRNRUkZZmOB5mJKO0ZUTVq+SxMQg==", + "dev": true, + "requires": { + "@nodelib/fs.stat": "^2.0.1", + "@nodelib/fs.walk": "^1.2.1", + "glob-parent": "^5.0.0", + "is-glob": "^4.0.1", + "merge2": "^1.2.3", + "micromatch": "^4.0.2" + } + }, + "fast-json-stable-stringify": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.0.0.tgz", + "integrity": "sha1-1RQsDK7msRifh9OnYREGT4bIu/I=", + "dev": true + }, + "fast-levenshtein": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", + "integrity": "sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc=", + "dev": true + }, + "fastq": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.6.0.tgz", + "integrity": "sha512-jmxqQ3Z/nXoeyDmWAzF9kH1aGZSis6e/SbfPmJpUnyZ0ogr6iscHQaml4wsEepEWSdtmpy+eVXmCRIMpxaXqOA==", + "dev": true, + "requires": { + "reusify": "^1.0.0" + } + }, + "figures": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/figures/-/figures-3.0.0.tgz", + "integrity": "sha512-HKri+WoWoUgr83pehn/SIgLOMZ9nAWC6dcGj26RY2R4F50u4+RTUz0RCrUlOV3nKRAICW1UGzyb+kcX2qK1S/g==", + "dev": true, + "requires": { + "escape-string-regexp": "^1.0.5" + } + }, + "file-entry-cache": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-5.0.1.tgz", + "integrity": "sha512-bCg29ictuBaKUwwArK4ouCaqDgLZcysCFLmM/Yn/FDoqndh/9vNuQfXRDvTuXKLxfD/JtZQGKFT8MGcJBK644g==", + "dev": true, + "requires": { + "flat-cache": "^2.0.1" + } + }, + "fill-range": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", + "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", + "dev": true, + "requires": { + "to-regex-range": "^5.0.1" + } + }, + "find-cache-dir": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-2.1.0.tgz", + "integrity": "sha512-Tq6PixE0w/VMFfCgbONnkiQIVol/JJL7nRMi20fqzA4NRs9AfeqMGeRdPi3wIhYkxjeBaWh2rxwapn5Tu3IqOQ==", + "dev": true, + "requires": { + "commondir": "^1.0.1", + "make-dir": "^2.0.0", + "pkg-dir": "^3.0.0" + }, + "dependencies": { + "find-up": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", + "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", + "dev": true, + "requires": { + "locate-path": "^3.0.0" + } + }, + "locate-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz", + "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==", + "dev": true, + "requires": { + "p-locate": "^3.0.0", + "path-exists": "^3.0.0" + } + }, + "make-dir": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-2.1.0.tgz", + "integrity": "sha512-LS9X+dc8KLxXCb8dni79fLIIUA5VyZoyjSMCwTluaXA0o27cCK0bhXkpgw+sTXVpPy/lSO57ilRixqk0vDmtRA==", + "dev": true, + "requires": { + "pify": "^4.0.1", + "semver": "^5.6.0" + } + }, + "p-limit": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.2.1.tgz", + "integrity": "sha512-85Tk+90UCVWvbDavCLKPOLC9vvY8OwEX/RtKF+/1OADJMVlFfEHOiMTPVyxg7mk/dKa+ipdHm0OUkTvCpMTuwg==", + "dev": true, + "requires": { + "p-try": "^2.0.0" + } + }, + "p-locate": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz", + "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==", + "dev": true, + "requires": { + "p-limit": "^2.0.0" + } + }, + "p-try": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", + "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", + "dev": true + }, + "pify": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/pify/-/pify-4.0.1.tgz", + "integrity": "sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==", + "dev": true + }, + "pkg-dir": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-3.0.0.tgz", + "integrity": "sha512-/E57AYkoeQ25qkxMj5PBOVgF8Kiu/h7cYS30Z5+R7WaiCCBfLq58ZI/dSeaEKb9WVJV5n/03QwrN3IeWIFllvw==", + "dev": true, + "requires": { + "find-up": "^3.0.0" + } + } + } + }, + "find-up": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-2.1.0.tgz", + "integrity": "sha1-RdG35QbHF93UgndaK3eSCjwMV6c=", + "dev": true, + "requires": { + "locate-path": "^2.0.0" + } + }, + "flat-cache": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-2.0.1.tgz", + "integrity": "sha512-LoQe6yDuUMDzQAEH8sgmh4Md6oZnc/7PjtwjNFSzveXqSHt6ka9fPBuso7IGf9Rz4uqnSnWiFH2B/zj24a5ReA==", + "dev": true, + "requires": { + "flatted": "^2.0.0", + "rimraf": "2.6.3", + "write": "1.0.3" + }, + "dependencies": { + "rimraf": { + "version": "2.6.3", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.3.tgz", + "integrity": "sha512-mwqeW5XsA2qAejG46gYdENaxXjx9onRNCfn7L0duuP4hCuTIi/QO7PDK07KJfp1d+izWPrzEJDcSqBa0OZQriA==", + "dev": true, + "requires": { + "glob": "^7.1.3" + } + } + } + }, + "flatted": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-2.0.1.tgz", + "integrity": "sha512-a1hQMktqW9Nmqr5aktAux3JMNqaucxGcjtjWnZLHX7yyPCmlSV3M54nGYbqT8K+0GhF3NBgmJCc3ma+WOgX8Jg==", + "dev": true + }, + "foreground-child": { + "version": "1.5.6", + "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-1.5.6.tgz", + "integrity": "sha1-T9ca0t/elnibmApcCilZN8svXOk=", + "dev": true, + "requires": { + "cross-spawn": "^4", + "signal-exit": "^3.0.0" + }, + "dependencies": { + "cross-spawn": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-4.0.2.tgz", + "integrity": "sha1-e5JHYhwjrf3ThWAEqCPL45dCTUE=", + "dev": true, + "requires": { + "lru-cache": "^4.0.1", + "which": "^1.2.9" + } + } + } + }, + "fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=", + "dev": true + }, + "fsevents": { + "version": "2.0.7", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.0.7.tgz", + "integrity": "sha512-a7YT0SV3RB+DjYcppwVDLtn13UQnmg0SWZS7ezZD0UjnLwXmy8Zm21GMVGLaFGimIqcvyMQaOJBrop8MyOp1kQ==", + "dev": true, + "optional": true + }, + "function-bind": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", + "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==", + "dev": true + }, + "functional-red-black-tree": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz", + "integrity": "sha1-GwqzvVU7Kg1jmdKcDj6gslIHgyc=", + "dev": true + }, + "get-caller-file": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", + "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", + "dev": true + }, + "get-port": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/get-port/-/get-port-5.0.0.tgz", + "integrity": "sha512-imzMU0FjsZqNa6BqOjbbW6w5BivHIuQKopjpPqcnx0AVHJQKCxK1O+Ab3OrVXhrekqfVMjwA9ZYu062R+KcIsQ==", + "dev": true, + "requires": { + "type-fest": "^0.3.0" + }, + "dependencies": { + "type-fest": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.3.1.tgz", + "integrity": "sha512-cUGJnCdr4STbePCgqNFbpVNCepa+kAVohJs1sLhxzdH+gnEoOd8VhbYa7pD3zZYGiURWM2xzEII3fQcRizDkYQ==", + "dev": true + } + } + }, + "get-stream": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-3.0.0.tgz", + "integrity": "sha1-jpQ9E1jcN1VQVOy+LtsFqhdO3hQ=", + "dev": true + }, + "glob": { + "version": "7.1.4", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.4.tgz", + "integrity": "sha512-hkLPepehmnKk41pUGm3sYxoFs/umurYfYJCerbXEyFIWcAzvpipAgVkBqqT9RBKMGjnq6kMuyYwha6csxbiM1A==", + "dev": true, + "requires": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.4", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + } + }, + "glob-parent": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.0.0.tgz", + "integrity": "sha512-Z2RwiujPRGluePM6j699ktJYxmPpJKCfpGA13jz2hmFZC7gKetzrWvg5KN3+OsIFmydGyZ1AVwERCq1w/ZZwRg==", + "dev": true, + "requires": { + "is-glob": "^4.0.1" + } + }, + "global-dirs": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/global-dirs/-/global-dirs-0.1.1.tgz", + "integrity": "sha1-sxnA3UYH81PzvpzKTHL8FIxJ9EU=", + "dev": true, + "requires": { + "ini": "^1.3.4" + } + }, + "globals": { + "version": "9.18.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-9.18.0.tgz", + "integrity": "sha512-S0nG3CLEQiY/ILxqtztTWH/3iRRdyBLw6KMDxnKMchrtbj2OFmehVh0WUCfW3DUrIgx/qFrJPICrq4Z4sTR9UQ==", + "dev": true + }, + "globby": { + "version": "10.0.1", + "resolved": "https://registry.npmjs.org/globby/-/globby-10.0.1.tgz", + "integrity": "sha512-sSs4inE1FB2YQiymcmTv6NWENryABjUNPeWhOvmn4SjtKybglsyPZxFB3U1/+L1bYi0rNZDqCLlHyLYDl1Pq5A==", + "dev": true, + "requires": { + "@types/glob": "^7.1.1", + "array-union": "^2.1.0", + "dir-glob": "^3.0.1", + "fast-glob": "^3.0.3", + "glob": "^7.1.3", + "ignore": "^5.1.1", + "merge2": "^1.2.3", + "slash": "^3.0.0" + }, + "dependencies": { + "slash": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", + "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", + "dev": true + } + } + }, + "got": { + "version": "9.6.0", + "resolved": "https://registry.npmjs.org/got/-/got-9.6.0.tgz", + "integrity": "sha512-R7eWptXuGYxwijs0eV+v3o6+XH1IqVK8dJOEecQfTmkncw9AV4dcw/Dhxi8MdlqPthxxpZyizMzyg8RTmEsG+Q==", + "dev": true, + "requires": { + "@sindresorhus/is": "^0.14.0", + "@szmarczak/http-timer": "^1.1.2", + "cacheable-request": "^6.0.0", + "decompress-response": "^3.3.0", + "duplexer3": "^0.1.4", + "get-stream": "^4.1.0", + "lowercase-keys": "^1.0.1", + "mimic-response": "^1.0.1", + "p-cancelable": "^1.0.0", + "to-readable-stream": "^1.0.0", + "url-parse-lax": "^3.0.0" + }, + "dependencies": { + "get-stream": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-4.1.0.tgz", + "integrity": "sha512-GMat4EJ5161kIy2HevLlr4luNjBgvmj413KaQA7jt4V8B4RDsfpHk7WQ9GVqfYyyx8OS/L66Kox+rJRNklLK7w==", + "dev": true, + "requires": { + "pump": "^3.0.0" + } + } + } + }, + "graceful-fs": { + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.2.tgz", + "integrity": "sha512-IItsdsea19BoLC7ELy13q1iJFNmd7ofZH5+X/pJr90/nRoPEX0DJo1dHDbgtYWOhJhcCgMDTOw84RZ72q6lB+Q==", + "dev": true + }, + "grapheme-splitter": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/grapheme-splitter/-/grapheme-splitter-1.0.4.tgz", + "integrity": "sha512-bzh50DW9kTPM00T8y4o8vQg89Di9oLJVLW/KaOGIXJWP/iqCN6WKYkbNOF04vFLJhwcpYUh9ydh/+5vpOqV4YQ==" + }, + "handlebars": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.1.2.tgz", + "integrity": "sha512-nvfrjqvt9xQ8Z/w0ijewdD/vvWDTOweBUm96NTr66Wfvo1mJenBLwcYmPs3TIBP5ruzYGD7Hx/DaM9RmhroGPw==", + "dev": true, + "requires": { + "neo-async": "^2.6.0", + "optimist": "^0.6.1", + "source-map": "^0.6.1", + "uglify-js": "^3.1.4" + }, + "dependencies": { + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + } + } + }, + "has": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", + "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", + "dev": true, + "requires": { + "function-bind": "^1.1.1" + } + }, + "has-ansi": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/has-ansi/-/has-ansi-2.0.0.tgz", + "integrity": "sha1-NPUEnOHs3ysGSa8+8k5F7TVBbZE=", + "dev": true, + "requires": { + "ansi-regex": "^2.0.0" + } + }, + "has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", + "dev": true + }, + "has-symbols": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.0.tgz", + "integrity": "sha1-uhqPGvKg/DllD1yFA2dwQSIGO0Q=", + "dev": true + }, + "has-yarn": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/has-yarn/-/has-yarn-2.1.0.tgz", + "integrity": "sha512-UqBRqi4ju7T+TqGNdqAO0PaSVGsDGJUBQvk9eUWNGRY1CFGDzYhLWoM7JQEemnlvVcv/YEmc2wNW8BC24EnUsw==", + "dev": true + }, + "hasha": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/hasha/-/hasha-5.0.0.tgz", + "integrity": "sha512-PqWdhnQhq6tqD32hZv+l1e5mJHNSudjnaAzgAHfkGiU0ABN6lmbZF8abJIulQHbZ7oiHhP8yL6O910ICMc+5pw==", + "dev": true, + "requires": { + "is-stream": "^1.1.0", + "type-fest": "^0.3.0" + }, + "dependencies": { + "type-fest": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.3.1.tgz", + "integrity": "sha512-cUGJnCdr4STbePCgqNFbpVNCepa+kAVohJs1sLhxzdH+gnEoOd8VhbYa7pD3zZYGiURWM2xzEII3fQcRizDkYQ==", + "dev": true + } + } + }, + "home-or-tmp": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/home-or-tmp/-/home-or-tmp-2.0.0.tgz", + "integrity": "sha1-42w/LSyufXRqhX440Y1fMqeILbg=", + "dev": true, + "requires": { + "os-homedir": "^1.0.0", + "os-tmpdir": "^1.0.1" + } + }, + "hosted-git-info": { + "version": "2.8.4", + "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.4.tgz", + "integrity": "sha512-pzXIvANXEFrc5oFFXRMkbLPQ2rXRoDERwDLyrcUxGhaZhgP54BBSl9Oheh7Vv0T090cszWBxPjkQQ5Sq1PbBRQ==", + "dev": true + }, + "http-cache-semantics": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-4.0.3.tgz", + "integrity": "sha512-TcIMG3qeVLgDr1TEd2XvHaTnMPwYQUQMIBLy+5pLSDKYFc7UIqj39w8EGzZkaxoLv/l2K8HaI0t5AVA+YYgUew==", + "dev": true + }, + "iconv-lite": { + "version": "0.4.24", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", + "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", + "dev": true, + "requires": { + "safer-buffer": ">= 2.1.2 < 3" + } + }, + "ignore": { + "version": "5.1.4", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.1.4.tgz", + "integrity": "sha512-MzbUSahkTW1u7JpKKjY7LCARd1fU5W2rLdxlM4kdkayuCwZImjkpluF9CM1aLewYJguPDqewLam18Y6AU69A8A==", + "dev": true + }, + "ignore-by-default": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/ignore-by-default/-/ignore-by-default-1.0.1.tgz", + "integrity": "sha1-SMptcvbGo68Aqa1K5odr44ieKwk=", + "dev": true + }, + "import-fresh": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.1.0.tgz", + "integrity": "sha512-PpuksHKGt8rXfWEr9m9EHIpgyyaltBy8+eF6GJM0QCAxMgxCfucMF3mjecK2QsJr0amJW7gTqh5/wht0z2UhEQ==", + "dev": true, + "requires": { + "parent-module": "^1.0.0", + "resolve-from": "^4.0.0" + }, + "dependencies": { + "resolve-from": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", + "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", + "dev": true + } + } + }, + "import-lazy": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/import-lazy/-/import-lazy-2.1.0.tgz", + "integrity": "sha1-BWmOPUXIjo1+nZLLBYTnfwlvPkM=", + "dev": true + }, + "import-local": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/import-local/-/import-local-3.0.2.tgz", + "integrity": "sha512-vjL3+w0oulAVZ0hBHnxa/Nm5TAurf9YLQJDhqRZyqb+VKGOB6LU8t9H1Nr5CIo16vh9XfJTOoHwU0B71S557gA==", + "dev": true, + "requires": { + "pkg-dir": "^4.2.0", + "resolve-cwd": "^3.0.0" + }, + "dependencies": { + "find-up": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", + "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", + "dev": true, + "requires": { + "locate-path": "^5.0.0", + "path-exists": "^4.0.0" + } + }, + "locate-path": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", + "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", + "dev": true, + "requires": { + "p-locate": "^4.1.0" + } + }, + "p-limit": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.2.1.tgz", + "integrity": "sha512-85Tk+90UCVWvbDavCLKPOLC9vvY8OwEX/RtKF+/1OADJMVlFfEHOiMTPVyxg7mk/dKa+ipdHm0OUkTvCpMTuwg==", + "dev": true, + "requires": { + "p-try": "^2.0.0" + } + }, + "p-locate": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", + "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", + "dev": true, + "requires": { + "p-limit": "^2.2.0" + } + }, + "p-try": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", + "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", + "dev": true + }, + "path-exists": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", + "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", + "dev": true + }, + "pkg-dir": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-4.2.0.tgz", + "integrity": "sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==", + "dev": true, + "requires": { + "find-up": "^4.0.0" + } + } + } + }, + "imurmurhash": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", + "integrity": "sha1-khi5srkoojixPcT7a21XbyMUU+o=", + "dev": true + }, + "indent-string": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-4.0.0.tgz", + "integrity": "sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==", + "dev": true + }, + "inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", + "dev": true, + "requires": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", + "dev": true + }, + "ini": { + "version": "1.3.5", + "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.5.tgz", + "integrity": "sha512-RZY5huIKCMRWDUqZlEi72f/lmXKMvuszcMBduliQ3nnWbx9X/ZBQO7DijMEYS9EhHBb2qacRUMtC7svLwe0lcw==", + "dev": true + }, + "inquirer": { + "version": "6.5.1", + "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-6.5.1.tgz", + "integrity": "sha512-uxNHBeQhRXIoHWTSNYUFhQVrHYFThIt6IVo2fFmSe8aBwdR3/w6b58hJpiL/fMukFkvGzjg+hSxFtwvVmKZmXw==", + "dev": true, + "requires": { + "ansi-escapes": "^4.2.1", + "chalk": "^2.4.2", + "cli-cursor": "^3.1.0", + "cli-width": "^2.0.0", + "external-editor": "^3.0.3", + "figures": "^3.0.0", + "lodash": "^4.17.15", + "mute-stream": "0.0.8", + "run-async": "^2.2.0", + "rxjs": "^6.4.0", + "string-width": "^4.1.0", + "strip-ansi": "^5.1.0", + "through": "^2.3.6" + } + }, + "invariant": { + "version": "2.2.4", + "resolved": "https://registry.npmjs.org/invariant/-/invariant-2.2.4.tgz", + "integrity": "sha512-phJfQVBuaJM5raOpJjSfkiD6BpbCE4Ns//LaXl6wGYtUBY83nWS6Rf9tXm2e8VaK60JEjYldbPif/A2B1C2gNA==", + "dev": true, + "requires": { + "loose-envify": "^1.0.0" + } + }, + "irregular-plurals": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/irregular-plurals/-/irregular-plurals-2.0.0.tgz", + "integrity": "sha512-Y75zBYLkh0lJ9qxeHlMjQ7bSbyiSqNW/UOPWDmzC7cXskL1hekSITh1Oc6JV0XCWWZ9DE8VYSB71xocLk3gmGw==", + "dev": true + }, + "is-arrayish": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", + "integrity": "sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0=", + "dev": true + }, + "is-binary-path": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", + "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", + "dev": true, + "requires": { + "binary-extensions": "^2.0.0" + } + }, + "is-callable": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.1.4.tgz", + "integrity": "sha512-r5p9sxJjYnArLjObpjA4xu5EKI3CuKHkJXMhT7kwbpUyIFD1n5PMAsoPvWnvtZiNz7LjkYDRZhd7FlI0eMijEA==", + "dev": true + }, + "is-ci": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-ci/-/is-ci-2.0.0.tgz", + "integrity": "sha512-YfJT7rkpQB0updsdHLGWrvhBJfcfzNNawYDNIyQXJz0IViGf75O8EBPKSdvw2rF+LGCsX4FZ8tcr3b19LcZq4w==", + "dev": true, + "requires": { + "ci-info": "^2.0.0" + } + }, + "is-date-object": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.1.tgz", + "integrity": "sha1-mqIOtq7rv/d/vTPnTKAbM1gdOhY=", + "dev": true + }, + "is-error": { + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/is-error/-/is-error-2.2.2.tgz", + "integrity": "sha512-IOQqts/aHWbiisY5DuPJQ0gcbvaLFCa7fBa9xoLfxBZvQ+ZI/Zh9xoI7Gk+G64N0FdK4AbibytHht2tWgpJWLg==", + "dev": true + }, + "is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=", + "dev": true + }, + "is-finite": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-finite/-/is-finite-1.0.2.tgz", + "integrity": "sha1-zGZ3aVYCvlUO8R6LSqYwU0K20Ko=", + "dev": true, + "requires": { + "number-is-nan": "^1.0.0" + } + }, + "is-fullwidth-code-point": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", + "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", + "dev": true + }, + "is-glob": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.1.tgz", + "integrity": "sha512-5G0tKtBTFImOqDnLB2hG6Bp2qcKEFduo4tZu9MT/H6NQv/ghhy30o55ufafxJ/LdH79LLs2Kfrn85TLKyA7BUg==", + "dev": true, + "requires": { + "is-extglob": "^2.1.1" + } + }, + "is-installed-globally": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/is-installed-globally/-/is-installed-globally-0.1.0.tgz", + "integrity": "sha1-Df2Y9akRFxbdU13aZJL2e/PSWoA=", + "dev": true, + "requires": { + "global-dirs": "^0.1.0", + "is-path-inside": "^1.0.0" + }, + "dependencies": { + "is-path-inside": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-1.0.1.tgz", + "integrity": "sha1-jvW33lBDej/cprToZe96pVy0gDY=", + "dev": true, + "requires": { + "path-is-inside": "^1.0.1" + } + } + } + }, + "is-module": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-module/-/is-module-1.0.0.tgz", + "integrity": "sha1-Mlj7afeMFNW4FdZkM2tM/7ZEFZE=", + "dev": true + }, + "is-npm": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-npm/-/is-npm-3.0.0.tgz", + "integrity": "sha512-wsigDr1Kkschp2opC4G3yA6r9EgVA6NjRpWzIi9axXqeIaAATPRJc4uLujXe3Nd9uO8KoDyA4MD6aZSeXTADhA==", + "dev": true + }, + "is-number": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", + "dev": true + }, + "is-obj": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-obj/-/is-obj-2.0.0.tgz", + "integrity": "sha512-drqDG3cbczxxEJRoOXcOjtdp1J/lyp1mNn0xaznRs8+muBhgQcrnbspox5X5fOw0HnMnbfDzvnEMEtqDEJEo8w==", + "dev": true + }, + "is-observable": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-observable/-/is-observable-2.0.0.tgz", + "integrity": "sha512-fhBZv3eFKUbyHXZ1oHujdo2tZ+CNbdpdzzlENgCGZUC8keoGxUew2jYFLYcUB4qo7LDD03o4KK11m/QYD7kEjg==", + "dev": true + }, + "is-path-cwd": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/is-path-cwd/-/is-path-cwd-2.2.0.tgz", + "integrity": "sha512-w942bTcih8fdJPJmQHFzkS76NEP8Kzzvmw92cXsazb8intwLqPibPPdXf4ANdKV3rYMuuQYGIWtvz9JilB3NFQ==", + "dev": true + }, + "is-path-in-cwd": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-path-in-cwd/-/is-path-in-cwd-2.1.0.tgz", + "integrity": "sha512-rNocXHgipO+rvnP6dk3zI20RpOtrAM/kzbB258Uw5BWr3TpXi861yzjo16Dn4hUox07iw5AyeMLHWsujkjzvRQ==", + "dev": true, + "requires": { + "is-path-inside": "^2.1.0" + } + }, + "is-path-inside": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-2.1.0.tgz", + "integrity": "sha512-wiyhTzfDWsvwAW53OBWF5zuvaOGlZ6PwYxAbPVDhpm+gM09xKQGjBq/8uYN12aDvMxnAnq3dxTyoSoRNmg5YFg==", + "dev": true, + "requires": { + "path-is-inside": "^1.0.2" + } + }, + "is-plain-obj": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-1.1.0.tgz", + "integrity": "sha1-caUMhCnfync8kqOQpKA7OfzVHT4=", + "dev": true + }, + "is-plain-object": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-3.0.0.tgz", + "integrity": "sha512-tZIpofR+P05k8Aocp7UI/2UTa9lTJSebCXpFFoR9aibpokDj/uXBsJ8luUu0tTVYKkMU6URDUuOfJZ7koewXvg==", + "dev": true, + "requires": { + "isobject": "^4.0.0" + } + }, + "is-promise": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-promise/-/is-promise-2.1.0.tgz", + "integrity": "sha1-eaKp7OfwlugPNtKy87wWwf9L8/o=", + "dev": true + }, + "is-reference": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/is-reference/-/is-reference-1.1.3.tgz", + "integrity": "sha512-W1iHHv/oyBb2pPxkBxtaewxa1BC58Pn5J0hogyCdefwUIvb6R+TGbAcIa4qPNYLqLhb3EnOgUf2MQkkF76BcKw==", + "requires": { + "@types/estree": "0.0.39" + } + }, + "is-regex": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.0.4.tgz", + "integrity": "sha1-VRdIm1RwkbCTDglWVM7SXul+lJE=", + "dev": true, + "requires": { + "has": "^1.0.1" + } + }, + "is-stream": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-1.1.0.tgz", + "integrity": "sha1-EtSj3U5o4Lec6428hBc66A2RykQ=", + "dev": true + }, + "is-symbol": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.2.tgz", + "integrity": "sha512-HS8bZ9ox60yCJLH9snBpIwv9pYUAkcuLhSA1oero1UB5y9aiQpRA8y2ex945AOtCZL1lJDeIk3G5LthswI46Lw==", + "dev": true, + "requires": { + "has-symbols": "^1.0.0" + } + }, + "is-typedarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", + "integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=", + "dev": true + }, + "is-url": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/is-url/-/is-url-1.2.4.tgz", + "integrity": "sha512-ITvGim8FhRiYe4IQ5uHSkj7pVaPDrCTkNd3yq3cV7iZAcJdHTUMPMEHcqSOy9xZ9qFenQCvi+2wjH9a1nXqHww==", + "dev": true + }, + "is-utf8": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/is-utf8/-/is-utf8-0.2.1.tgz", + "integrity": "sha1-Sw2hRCEE0bM2NA6AeX6GXPOffXI=", + "dev": true + }, + "is-yarn-global": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/is-yarn-global/-/is-yarn-global-0.3.0.tgz", + "integrity": "sha512-VjSeb/lHmkoyd8ryPVIKvOCn4D1koMqY+vqyjjUfc3xyKtP4dYOxM44sZrnqQSzSds3xyOrUTLTC9LVCVgLngw==", + "dev": true + }, + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", + "dev": true + }, + "isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=", + "dev": true + }, + "isobject": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-4.0.0.tgz", + "integrity": "sha512-S/2fF5wH8SJA/kmwr6HYhK/RI/OkhD84k8ntalo0iJjZikgq1XFvR5M8NPT1x5F7fBwCG3qHfnzeP/Vh/ZxCUA==", + "dev": true + }, + "istanbul-lib-coverage": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.5.tgz", + "integrity": "sha512-8aXznuEPCJvGnMSRft4udDRDtb1V3pkQkMMI5LI+6HuQz5oQ4J2UFn1H82raA3qJtyOLkkwVqICBQkjnGtn5mA==", + "dev": true + }, + "istanbul-lib-hook": { + "version": "2.0.7", + "resolved": "https://registry.npmjs.org/istanbul-lib-hook/-/istanbul-lib-hook-2.0.7.tgz", + "integrity": "sha512-vrRztU9VRRFDyC+aklfLoeXyNdTfga2EI3udDGn4cZ6fpSXpHLV9X6CHvfoMCPtggg8zvDDmC4b9xfu0z6/llA==", + "dev": true, + "requires": { + "append-transform": "^1.0.0" + } + }, + "istanbul-lib-instrument": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-3.3.0.tgz", + "integrity": "sha512-5nnIN4vo5xQZHdXno/YDXJ0G+I3dAm4XgzfSVTPLQpj/zAV2dV6Juy0yaf10/zrJOJeHoN3fraFe+XRq2bFVZA==", + "dev": true, + "requires": { + "@babel/generator": "^7.4.0", + "@babel/parser": "^7.4.3", + "@babel/template": "^7.4.0", + "@babel/traverse": "^7.4.3", + "@babel/types": "^7.4.0", + "istanbul-lib-coverage": "^2.0.5", + "semver": "^6.0.0" + }, + "dependencies": { + "semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "dev": true + } + } + }, + "istanbul-lib-report": { + "version": "2.0.8", + "resolved": "https://registry.npmjs.org/istanbul-lib-report/-/istanbul-lib-report-2.0.8.tgz", + "integrity": "sha512-fHBeG573EIihhAblwgxrSenp0Dby6tJMFR/HvlerBsrCTD5bkUuoNtn3gVh29ZCS824cGGBPn7Sg7cNk+2xUsQ==", + "dev": true, + "requires": { + "istanbul-lib-coverage": "^2.0.5", + "make-dir": "^2.1.0", + "supports-color": "^6.1.0" + }, + "dependencies": { + "make-dir": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-2.1.0.tgz", + "integrity": "sha512-LS9X+dc8KLxXCb8dni79fLIIUA5VyZoyjSMCwTluaXA0o27cCK0bhXkpgw+sTXVpPy/lSO57ilRixqk0vDmtRA==", + "dev": true, + "requires": { + "pify": "^4.0.1", + "semver": "^5.6.0" + } + }, + "pify": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/pify/-/pify-4.0.1.tgz", + "integrity": "sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==", + "dev": true + }, + "supports-color": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-6.1.0.tgz", + "integrity": "sha512-qe1jfm1Mg7Nq/NSh6XE24gPXROEVsWHxC1LIx//XNlD9iw7YZQGjZNjYN7xGaEG6iKdA8EtNFW6R0gjnVXp+wQ==", + "dev": true, + "requires": { + "has-flag": "^3.0.0" + } + } + } + }, + "istanbul-lib-source-maps": { + "version": "3.0.6", + "resolved": "https://registry.npmjs.org/istanbul-lib-source-maps/-/istanbul-lib-source-maps-3.0.6.tgz", + "integrity": "sha512-R47KzMtDJH6X4/YW9XTx+jrLnZnscW4VpNN+1PViSYTejLVPWv7oov+Duf8YQSPyVRUvueQqz1TcsC6mooZTXw==", + "dev": true, + "requires": { + "debug": "^4.1.1", + "istanbul-lib-coverage": "^2.0.5", + "make-dir": "^2.1.0", + "rimraf": "^2.6.3", + "source-map": "^0.6.1" + }, + "dependencies": { + "debug": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", + "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", + "dev": true, + "requires": { + "ms": "^2.1.1" + } + }, + "make-dir": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-2.1.0.tgz", + "integrity": "sha512-LS9X+dc8KLxXCb8dni79fLIIUA5VyZoyjSMCwTluaXA0o27cCK0bhXkpgw+sTXVpPy/lSO57ilRixqk0vDmtRA==", + "dev": true, + "requires": { + "pify": "^4.0.1", + "semver": "^5.6.0" + } + }, + "pify": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/pify/-/pify-4.0.1.tgz", + "integrity": "sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==", + "dev": true + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + } + } + }, + "istanbul-reports": { + "version": "2.2.6", + "resolved": "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-2.2.6.tgz", + "integrity": "sha512-SKi4rnMyLBKe0Jy2uUdx28h8oG7ph2PPuQPvIAh31d+Ci+lSiEu4C+h3oBPuJ9+mPKhOyW0M8gY4U5NM1WLeXA==", + "dev": true, + "requires": { + "handlebars": "^4.1.2" + } + }, + "js-string-escape": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/js-string-escape/-/js-string-escape-1.0.1.tgz", + "integrity": "sha1-4mJbrbwNZ8dTPp7cEGjFh65BN+8=", + "dev": true + }, + "js-tokens": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-3.0.2.tgz", + "integrity": "sha1-mGbfOVECEw449/mWvOtlRDIJwls=", + "dev": true + }, + "js-yaml": { + "version": "3.13.1", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.13.1.tgz", + "integrity": "sha512-YfbcO7jXDdyj0DGxYVSlSeQNHbD7XPWvrVWeVUujrQEoZzWJIRrCPoyk6kL6IAjAG2IolMK4T0hNUe0HOUs5Jw==", + "dev": true, + "requires": { + "argparse": "^1.0.7", + "esprima": "^4.0.0" + } + }, + "jsesc": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-0.5.0.tgz", + "integrity": "sha1-597mbjXW/Bb3EP6R1c9p9w8IkR0=", + "dev": true + }, + "json-buffer": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.0.tgz", + "integrity": "sha1-Wx85evx11ne96Lz8Dkfh+aPZqJg=", + "dev": true + }, + "json-parse-better-errors": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz", + "integrity": "sha512-mrqyZKfX5EhL7hvqcV6WG1yYjnjeuYDzDhhcAAUrq8Po85NBQBJP+ZDUT75qZQ98IkUoBqdkExkukOU7Ts2wrw==", + "dev": true + }, + "json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "dev": true + }, + "json-stable-stringify-without-jsonify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", + "integrity": "sha1-nbe1lJatPzz+8wp1FC0tkwrXJlE=", + "dev": true + }, + "json5": { + "version": "0.5.1", + "resolved": "https://registry.npmjs.org/json5/-/json5-0.5.1.tgz", + "integrity": "sha1-Hq3nrMASA0rYTiOWdn6tn6VJWCE=", + "dev": true + }, + "keyv": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/keyv/-/keyv-3.1.0.tgz", + "integrity": "sha512-9ykJ/46SN/9KPM/sichzQ7OvXyGDYKGTaDlKMGCAlg2UK8KRy4jb0d8sFc+0Tt0YYnThq8X2RZgCg74RPxgcVA==", + "dev": true, + "requires": { + "json-buffer": "3.0.0" + } + }, + "latest-version": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/latest-version/-/latest-version-5.1.0.tgz", + "integrity": "sha512-weT+r0kTkRQdCdYCNtkMwWXQTMEswKrFBkm4ckQOMVhhqhIMI1UT2hMj+1iigIhgSZm5gTmrRXBNoGUgaTY1xA==", + "dev": true, + "requires": { + "package-json": "^6.3.0" + } + }, + "levn": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/levn/-/levn-0.3.0.tgz", + "integrity": "sha1-OwmSTt+fCDwEkP3UwLxEIeBHZO4=", + "dev": true, + "requires": { + "prelude-ls": "~1.1.2", + "type-check": "~0.3.2" + } + }, + "load-json-file": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-2.0.0.tgz", + "integrity": "sha1-eUfkIUmvgNaWy/eXvKq8/h/inKg=", + "dev": true, + "requires": { + "graceful-fs": "^4.1.2", + "parse-json": "^2.2.0", + "pify": "^2.0.0", + "strip-bom": "^3.0.0" + } + }, + "locate-path": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-2.0.0.tgz", + "integrity": "sha1-K1aLJl7slExtnA3pw9u7ygNUzY4=", + "dev": true, + "requires": { + "p-locate": "^2.0.0", + "path-exists": "^3.0.0" + } + }, + "lodash": { + "version": "4.17.15", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.15.tgz", + "integrity": "sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A==", + "dev": true + }, + "lodash.clonedeep": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/lodash.clonedeep/-/lodash.clonedeep-4.5.0.tgz", + "integrity": "sha1-4j8/nE+Pvd6HJSnBBxhXoIblzO8=", + "dev": true + }, + "lodash.flattendeep": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/lodash.flattendeep/-/lodash.flattendeep-4.4.0.tgz", + "integrity": "sha1-+wMJF/hqMTTlvJvsDWngAT3f7bI=", + "dev": true + }, + "lodash.islength": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/lodash.islength/-/lodash.islength-4.0.1.tgz", + "integrity": "sha1-Tpho1FJXXXUK/9NYyXlUPcIO1Xc=", + "dev": true + }, + "lodash.merge": { + "version": "4.6.2", + "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", + "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", + "dev": true + }, + "log-symbols": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-2.2.0.tgz", + "integrity": "sha512-VeIAFslyIerEJLXHziedo2basKbMKtTw3vfn5IzG0XTjhAVEJyNHnL2p7vc+wBDSdQuUpNw3M2u6xb9QsAY5Eg==", + "dev": true, + "requires": { + "chalk": "^2.0.1" + } + }, + "loose-envify": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz", + "integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==", + "dev": true, + "requires": { + "js-tokens": "^3.0.0 || ^4.0.0" + } + }, + "loud-rejection": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/loud-rejection/-/loud-rejection-2.1.0.tgz", + "integrity": "sha512-g/6MQxUXYHeVqZ4PGpPL1fS1fOvlXoi7bay0pizmjAd/3JhyXwxzwrnr74yzdmhuerlslbRJ3x7IOXzFz0cE5w==", + "dev": true, + "requires": { + "currently-unhandled": "^0.4.1", + "signal-exit": "^3.0.2" + } + }, + "lowercase-keys": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-1.0.1.tgz", + "integrity": "sha512-G2Lj61tXDnVFFOi8VZds+SoQjtQC3dgokKdDG2mTm1tx4m50NUHBOZSBwQQHyy0V12A0JTG4icfZQH+xPyh8VA==", + "dev": true + }, + "lru-cache": { + "version": "4.1.5", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-4.1.5.tgz", + "integrity": "sha512-sWZlbEP2OsHNkXrMl5GYk/jKk70MBng6UU4YI/qGDYbgf6YbP4EvmqISbXCoJiRKs+1bSpFHVgQxvJ17F2li5g==", + "dev": true, + "requires": { + "pseudomap": "^1.0.2", + "yallist": "^2.1.2" + } + }, + "magic-string": { + "version": "0.25.3", + "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.25.3.tgz", + "integrity": "sha512-6QK0OpF/phMz0Q2AxILkX2mFhi7m+WMwTRg0LQKq/WBB0cDP4rYH3Wp4/d3OTXlrPLVJT/RFqj8tFeAR4nk8AA==", + "requires": { + "sourcemap-codec": "^1.4.4" + } + }, + "make-dir": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.0.0.tgz", + "integrity": "sha512-grNJDhb8b1Jm1qeqW5R/O63wUo4UXo2v2HMic6YT9i/HBlF93S8jkMgH7yugvY9ABDShH4VZMn8I+U8+fCNegw==", + "dev": true, + "requires": { + "semver": "^6.0.0" + }, + "dependencies": { + "semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "dev": true + } + } + }, + "map-obj": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/map-obj/-/map-obj-2.0.0.tgz", + "integrity": "sha1-plzSkIepJZi4eRJXpSPgISIqwfk=", + "dev": true + }, + "matcher": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/matcher/-/matcher-2.0.0.tgz", + "integrity": "sha512-nlmfSlgHBFx36j/Pl/KQPbIaqE8Zf0TqmSMjsuddHDg6PMSVgmyW9HpkLs0o0M1n2GIZ/S2BZBLIww/xjhiGng==", + "dev": true, + "requires": { + "escape-string-regexp": "^2.0.0" + }, + "dependencies": { + "escape-string-regexp": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-2.0.0.tgz", + "integrity": "sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w==", + "dev": true + } + } + }, + "md5-hex": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/md5-hex/-/md5-hex-3.0.1.tgz", + "integrity": "sha512-BUiRtTtV39LIJwinWBjqVsU9xhdnz7/i889V859IBFpuqGAj6LuOvHv5XLbgZ2R7ptJoJaEcxkv88/h25T7Ciw==", + "dev": true, + "requires": { + "blueimp-md5": "^2.10.0" + } + }, + "md5-o-matic": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/md5-o-matic/-/md5-o-matic-0.1.1.tgz", + "integrity": "sha1-givM1l4RfFFPqxdrJZRdVBAKA8M=", + "dev": true + }, + "meow": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/meow/-/meow-5.0.0.tgz", + "integrity": "sha512-CbTqYU17ABaLefO8vCU153ZZlprKYWDljcndKKDCFcYQITzWCXZAVk4QMFZPgvzrnUQ3uItnIE/LoUOwrT15Ig==", + "dev": true, + "requires": { + "camelcase-keys": "^4.0.0", + "decamelize-keys": "^1.0.0", + "loud-rejection": "^1.0.0", + "minimist-options": "^3.0.1", + "normalize-package-data": "^2.3.4", + "read-pkg-up": "^3.0.0", + "redent": "^2.0.0", + "trim-newlines": "^2.0.0", + "yargs-parser": "^10.0.0" + }, + "dependencies": { + "load-json-file": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-4.0.0.tgz", + "integrity": "sha1-L19Fq5HjMhYjT9U62rZo607AmTs=", + "dev": true, + "requires": { + "graceful-fs": "^4.1.2", + "parse-json": "^4.0.0", + "pify": "^3.0.0", + "strip-bom": "^3.0.0" + } + }, + "loud-rejection": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/loud-rejection/-/loud-rejection-1.6.0.tgz", + "integrity": "sha1-W0b4AUft7leIcPCG0Eghz5mOVR8=", + "dev": true, + "requires": { + "currently-unhandled": "^0.4.1", + "signal-exit": "^3.0.0" + } + }, + "parse-json": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-4.0.0.tgz", + "integrity": "sha1-vjX1Qlvh9/bHRxhPmKeIy5lHfuA=", + "dev": true, + "requires": { + "error-ex": "^1.3.1", + "json-parse-better-errors": "^1.0.1" + } + }, + "path-type": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-3.0.0.tgz", + "integrity": "sha512-T2ZUsdZFHgA3u4e5PfPbjd7HDDpxPnQb5jN0SrDsjNSuVXHJqtwTnWqG0B1jZrgmJ/7lj1EmVIByWt1gxGkWvg==", + "dev": true, + "requires": { + "pify": "^3.0.0" + } + }, + "pify": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", + "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=", + "dev": true + }, + "read-pkg": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-3.0.0.tgz", + "integrity": "sha1-nLxoaXj+5l0WwA4rGcI3/Pbjg4k=", + "dev": true, + "requires": { + "load-json-file": "^4.0.0", + "normalize-package-data": "^2.3.2", + "path-type": "^3.0.0" + } + }, + "read-pkg-up": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-3.0.0.tgz", + "integrity": "sha1-PtSWaF26D4/hGNBpHcUfSh/5bwc=", + "dev": true, + "requires": { + "find-up": "^2.0.0", + "read-pkg": "^3.0.0" + } + } + } + }, + "merge-source-map": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/merge-source-map/-/merge-source-map-1.1.0.tgz", + "integrity": "sha512-Qkcp7P2ygktpMPh2mCQZaf3jhN6D3Z/qVZHSdWvQ+2Ef5HgRAPBO57A77+ENm0CPx2+1Ce/MYKi3ymqdfuqibw==", + "dev": true, + "requires": { + "source-map": "^0.6.1" + }, + "dependencies": { + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + } + } + }, + "merge2": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.2.4.tgz", + "integrity": "sha512-FYE8xI+6pjFOhokZu0We3S5NKCirLbCzSh2Usf3qEyr4X8U+0jNg9P8RZ4qz+V2UoECLVwSyzU3LxXBaLGtD3A==", + "dev": true + }, + "micromatch": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.2.tgz", + "integrity": "sha512-y7FpHSbMUMoyPbYUSzO6PaZ6FyRnQOpHuKwbo1G+Knck95XVU4QAiKdGEnj5wwoS7PlOgthX/09u5iFJ+aYf5Q==", + "dev": true, + "requires": { + "braces": "^3.0.1", + "picomatch": "^2.0.5" + } + }, + "mimic-fn": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", + "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", + "dev": true + }, + "mimic-response": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-1.0.1.tgz", + "integrity": "sha512-j5EctnkH7amfV/q5Hgmoal1g2QHFJRraOtmx0JpIqkxhBhI/lJSl1nMpQ45hVarwNETOoWEimndZ4QK0RHxuxQ==", + "dev": true + }, + "minimatch": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", + "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", + "dev": true, + "requires": { + "brace-expansion": "^1.1.7" + } + }, + "minimist": { + "version": "0.0.8", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz", + "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=", + "dev": true + }, + "minimist-options": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/minimist-options/-/minimist-options-3.0.2.tgz", + "integrity": "sha512-FyBrT/d0d4+uiZRbqznPXqw3IpZZG3gl3wKWiX784FycUKVwBt0uLBFkQrtE4tZOrgo78nZp2jnKz3L65T5LdQ==", + "dev": true, + "requires": { + "arrify": "^1.0.1", + "is-plain-obj": "^1.1.0" + }, + "dependencies": { + "arrify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/arrify/-/arrify-1.0.1.tgz", + "integrity": "sha1-iYUI2iIm84DfkEcoRWhJwVAaSw0=", + "dev": true + } + } + }, + "mkdirp": { + "version": "0.5.1", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz", + "integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=", + "dev": true, + "requires": { + "minimist": "0.0.8" + } + }, + "ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true + }, + "mute-stream": { + "version": "0.0.8", + "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.8.tgz", + "integrity": "sha512-nnbWWOkoWyUsTjKrhgD0dcz22mdkSnpYqbEjIm2nhwhuxlSkpywJmBo8h0ZqJdkp73mb90SssHkN4rsRaBAfAA==", + "dev": true + }, + "natural-compare": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", + "integrity": "sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc=", + "dev": true + }, + "neo-async": { + "version": "2.6.1", + "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.1.tgz", + "integrity": "sha512-iyam8fBuCUpWeKPGpaNMetEocMt364qkCsfL9JuhjXX6dRnguRVOfk2GZaDpPjcOKiiXCPINZC1GczQ7iTq3Zw==", + "dev": true + }, + "nested-error-stacks": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/nested-error-stacks/-/nested-error-stacks-2.1.0.tgz", + "integrity": "sha512-AO81vsIO1k1sM4Zrd6Hu7regmJN1NSiAja10gc4bX3F0wd+9rQmcuHQaHVQCYIEC8iFXnE+mavh23GOt7wBgug==", + "dev": true + }, + "nice-try": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/nice-try/-/nice-try-1.0.5.tgz", + "integrity": "sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ==", + "dev": true + }, + "normalize-package-data": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.5.0.tgz", + "integrity": "sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==", + "dev": true, + "requires": { + "hosted-git-info": "^2.1.4", + "resolve": "^1.10.0", + "semver": "2 || 3 || 4 || 5", + "validate-npm-package-license": "^3.0.1" + } + }, + "normalize-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", + "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", + "dev": true + }, + "normalize-url": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-4.3.0.tgz", + "integrity": "sha512-0NLtR71o4k6GLP+mr6Ty34c5GA6CMoEsncKJxvQd8NzPxaHRJNnb5gZE8R1XF4CPIS7QPHLJ74IFszwtNVAHVQ==", + "dev": true + }, + "npm-run-path": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-2.0.2.tgz", + "integrity": "sha1-NakjLfo11wZ7TLLd8jV7GHFTbF8=", + "dev": true, + "requires": { + "path-key": "^2.0.0" + } + }, + "number-is-nan": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz", + "integrity": "sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0=", + "dev": true + }, + "nyc": { + "version": "14.1.1", + "resolved": "https://registry.npmjs.org/nyc/-/nyc-14.1.1.tgz", + "integrity": "sha512-OI0vm6ZGUnoGZv/tLdZ2esSVzDwUC88SNs+6JoSOMVxA+gKMB8Tk7jBwgemLx4O40lhhvZCVw1C+OYLOBOPXWw==", + "dev": true, + "requires": { + "archy": "^1.0.0", + "caching-transform": "^3.0.2", + "convert-source-map": "^1.6.0", + "cp-file": "^6.2.0", + "find-cache-dir": "^2.1.0", + "find-up": "^3.0.0", + "foreground-child": "^1.5.6", + "glob": "^7.1.3", + "istanbul-lib-coverage": "^2.0.5", + "istanbul-lib-hook": "^2.0.7", + "istanbul-lib-instrument": "^3.3.0", + "istanbul-lib-report": "^2.0.8", + "istanbul-lib-source-maps": "^3.0.6", + "istanbul-reports": "^2.2.4", + "js-yaml": "^3.13.1", + "make-dir": "^2.1.0", + "merge-source-map": "^1.1.0", + "resolve-from": "^4.0.0", + "rimraf": "^2.6.3", + "signal-exit": "^3.0.2", + "spawn-wrap": "^1.4.2", + "test-exclude": "^5.2.3", + "uuid": "^3.3.2", + "yargs": "^13.2.2", + "yargs-parser": "^13.0.0" + }, + "dependencies": { + "camelcase": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", + "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", + "dev": true + }, + "find-up": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", + "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", + "dev": true, + "requires": { + "locate-path": "^3.0.0" + } + }, + "locate-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz", + "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==", + "dev": true, + "requires": { + "p-locate": "^3.0.0", + "path-exists": "^3.0.0" + } + }, + "make-dir": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-2.1.0.tgz", + "integrity": "sha512-LS9X+dc8KLxXCb8dni79fLIIUA5VyZoyjSMCwTluaXA0o27cCK0bhXkpgw+sTXVpPy/lSO57ilRixqk0vDmtRA==", + "dev": true, + "requires": { + "pify": "^4.0.1", + "semver": "^5.6.0" + } + }, + "p-limit": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.2.1.tgz", + "integrity": "sha512-85Tk+90UCVWvbDavCLKPOLC9vvY8OwEX/RtKF+/1OADJMVlFfEHOiMTPVyxg7mk/dKa+ipdHm0OUkTvCpMTuwg==", + "dev": true, + "requires": { + "p-try": "^2.0.0" + } + }, + "p-locate": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz", + "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==", + "dev": true, + "requires": { + "p-limit": "^2.0.0" + } + }, + "p-try": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", + "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", + "dev": true + }, + "pify": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/pify/-/pify-4.0.1.tgz", + "integrity": "sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==", + "dev": true + }, + "resolve-from": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", + "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", + "dev": true + }, + "yargs-parser": { + "version": "13.1.1", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-13.1.1.tgz", + "integrity": "sha512-oVAVsHz6uFrg3XQheFII8ESO2ssAf9luWuAd6Wexsu4F3OtIW0o8IribPXYrD4WC24LWtPrJlGy87y5udK+dxQ==", + "dev": true, + "requires": { + "camelcase": "^5.0.0", + "decamelize": "^1.2.0" + } + } + } + }, + "object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=", + "dev": true + }, + "object-keys": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", + "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", + "dev": true + }, + "object.assign": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.0.tgz", + "integrity": "sha512-exHJeq6kBKj58mqGyTQ9DFvrZC/eR6OwxzoM9YRoGBqrXYonaFyGiFMuc9VZrXf7DarreEwMpurG3dd+CNyW5w==", + "dev": true, + "requires": { + "define-properties": "^1.1.2", + "function-bind": "^1.1.1", + "has-symbols": "^1.0.0", + "object-keys": "^1.0.11" + } + }, + "object.entries": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/object.entries/-/object.entries-1.1.0.tgz", + "integrity": "sha512-l+H6EQ8qzGRxbkHOd5I/aHRhHDKoQXQ8g0BYt4uSweQU1/J6dZUOyWh9a2Vky35YCKjzmgxOzta2hH6kf9HuXA==", + "dev": true, + "requires": { + "define-properties": "^1.1.3", + "es-abstract": "^1.12.0", + "function-bind": "^1.1.1", + "has": "^1.0.3" + } + }, + "object.values": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/object.values/-/object.values-1.1.0.tgz", + "integrity": "sha512-8mf0nKLAoFX6VlNVdhGj31SVYpaNFtUnuoOXWyFEstsWRgU837AK+JYM0iAxwkSzGRbwn8cbFmgbyxj1j4VbXg==", + "dev": true, + "requires": { + "define-properties": "^1.1.3", + "es-abstract": "^1.12.0", + "function-bind": "^1.1.1", + "has": "^1.0.3" + } + }, + "observable-to-promise": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/observable-to-promise/-/observable-to-promise-1.0.0.tgz", + "integrity": "sha512-cqnGUrNsE6vdVDTPAX9/WeVzwy/z37vdxupdQXU8vgTXRFH72KCZiZga8aca2ulRPIeem8W3vW9rQHBwfIl2WA==", + "dev": true, + "requires": { + "is-observable": "^2.0.0", + "symbol-observable": "^1.0.4" + } + }, + "once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", + "dev": true, + "requires": { + "wrappy": "1" + } + }, + "onetime": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.0.tgz", + "integrity": "sha512-5NcSkPHhwTVFIQN+TUqXoS5+dlElHXdpAWu9I0HP20YOtIi+aZ0Ct82jdlILDxjLEAWwvm+qj1m6aEtsDVmm6Q==", + "dev": true, + "requires": { + "mimic-fn": "^2.1.0" + } + }, + "optimist": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/optimist/-/optimist-0.6.1.tgz", + "integrity": "sha1-2j6nRob6IaGaERwybpDrFaAZZoY=", + "dev": true, + "requires": { + "minimist": "~0.0.1", + "wordwrap": "~0.0.2" + }, + "dependencies": { + "wordwrap": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-0.0.3.tgz", + "integrity": "sha1-o9XabNXAvAAI03I0u68b7WMFkQc=", + "dev": true + } + } + }, + "optionator": { + "version": "0.8.2", + "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.8.2.tgz", + "integrity": "sha1-NkxeQJ0/TWMB1sC0wFu6UBgK62Q=", + "dev": true, + "requires": { + "deep-is": "~0.1.3", + "fast-levenshtein": "~2.0.4", + "levn": "~0.3.0", + "prelude-ls": "~1.1.2", + "type-check": "~0.3.2", + "wordwrap": "~1.0.0" + } + }, + "ora": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/ora/-/ora-3.4.0.tgz", + "integrity": "sha512-eNwHudNbO1folBP3JsZ19v9azXWtQZjICdr3Q0TDPIaeBQ3mXLrh54wM+er0+hSp+dWKf+Z8KM58CYzEyIYxYg==", + "dev": true, + "requires": { + "chalk": "^2.4.2", + "cli-cursor": "^2.1.0", + "cli-spinners": "^2.0.0", + "log-symbols": "^2.2.0", + "strip-ansi": "^5.2.0", + "wcwidth": "^1.0.1" + }, + "dependencies": { + "cli-cursor": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-2.1.0.tgz", + "integrity": "sha1-s12sN2R5+sw+lHR9QdDQ9SOP/LU=", + "dev": true, + "requires": { + "restore-cursor": "^2.0.0" + } + }, + "mimic-fn": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-1.2.0.tgz", + "integrity": "sha512-jf84uxzwiuiIVKiOLpfYk7N46TSy8ubTonmneY9vrpHNAnp0QBt2BxWV9dO3/j+BoVAb+a5G6YDPW3M5HOdMWQ==", + "dev": true + }, + "onetime": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-2.0.1.tgz", + "integrity": "sha1-BnQoIw/WdEOyeUsiu6UotoZ5YtQ=", + "dev": true, + "requires": { + "mimic-fn": "^1.0.0" + } + }, + "restore-cursor": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-2.0.0.tgz", + "integrity": "sha1-n37ih/gv0ybU/RYpI9YhKe7g368=", + "dev": true, + "requires": { + "onetime": "^2.0.0", + "signal-exit": "^3.0.2" + } + } + } + }, + "os-homedir": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/os-homedir/-/os-homedir-1.0.2.tgz", + "integrity": "sha1-/7xJiDNuDoM94MFox+8VISGqf7M=", + "dev": true + }, + "os-tmpdir": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz", + "integrity": "sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=", + "dev": true + }, + "p-cancelable": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/p-cancelable/-/p-cancelable-1.1.0.tgz", + "integrity": "sha512-s73XxOZ4zpt1edZYZzvhqFa6uvQc1vwUa0K0BdtIZgQMAJj9IbebH+JkgKZc9h+B05PKHLOTl4ajG1BmNrVZlw==", + "dev": true + }, + "p-finally": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/p-finally/-/p-finally-1.0.0.tgz", + "integrity": "sha1-P7z7FbiZpEEjs0ttzBi3JDNqLK4=", + "dev": true + }, + "p-limit": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-1.3.0.tgz", + "integrity": "sha512-vvcXsLAJ9Dr5rQOPk7toZQZJApBl2K4J6dANSsEuh6QI41JYcsS/qhTGa9ErIUUgK3WNQoJYvylxvjqmiqEA9Q==", + "dev": true, + "requires": { + "p-try": "^1.0.0" + } + }, + "p-locate": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-2.0.0.tgz", + "integrity": "sha1-IKAQOyIqcMj9OcwuWAaA893l7EM=", + "dev": true, + "requires": { + "p-limit": "^1.1.0" + } + }, + "p-map": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/p-map/-/p-map-2.1.0.tgz", + "integrity": "sha512-y3b8Kpd8OAN444hxfBbFfj1FY/RjtTd8tzYwhUqNYXx0fXx2iX4maP4Qr6qhIKbQXI02wTLAda4fYUbDagTUFw==", + "dev": true + }, + "p-try": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/p-try/-/p-try-1.0.0.tgz", + "integrity": "sha1-y8ec26+P1CKOE/Yh8rGiN8GyB7M=", + "dev": true + }, + "package-hash": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/package-hash/-/package-hash-4.0.0.tgz", + "integrity": "sha512-whdkPIooSu/bASggZ96BWVvZTRMOFxnyUG5PnTSGKoJE2gd5mbVNmR2Nj20QFzxYYgAXpoqC+AiXzl+UMRh7zQ==", + "dev": true, + "requires": { + "graceful-fs": "^4.1.15", + "hasha": "^5.0.0", + "lodash.flattendeep": "^4.4.0", + "release-zalgo": "^1.0.0" + } + }, + "package-json": { + "version": "6.5.0", + "resolved": "https://registry.npmjs.org/package-json/-/package-json-6.5.0.tgz", + "integrity": "sha512-k3bdm2n25tkyxcjSKzB5x8kfVxlMdgsbPr0GkZcwHsLpba6cBjqCt1KlcChKEvxHIcTB1FVMuwoijZ26xex5MQ==", + "dev": true, + "requires": { + "got": "^9.6.0", + "registry-auth-token": "^4.0.0", + "registry-url": "^5.0.0", + "semver": "^6.2.0" + }, + "dependencies": { + "semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "dev": true + } + } + }, + "parent-module": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", + "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", + "dev": true, + "requires": { + "callsites": "^3.0.0" + } + }, + "parse-json": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-2.2.0.tgz", + "integrity": "sha1-9ID0BDTvgHQfhGkJn43qGPVaTck=", + "dev": true, + "requires": { + "error-ex": "^1.2.0" + } + }, + "parse-ms": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/parse-ms/-/parse-ms-2.1.0.tgz", + "integrity": "sha512-kHt7kzLoS9VBZfUsiKjv43mr91ea+U05EyKkEtqp7vNbHxmaVuEqN7XxeEVnGrMtYOAxGrDElSi96K7EgO1zCA==", + "dev": true + }, + "path-exists": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", + "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=", + "dev": true + }, + "path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", + "dev": true + }, + "path-is-inside": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/path-is-inside/-/path-is-inside-1.0.2.tgz", + "integrity": "sha1-NlQX3t5EQw0cEa9hAn+s8HS9/FM=", + "dev": true + }, + "path-key": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-2.0.1.tgz", + "integrity": "sha1-QRyttXTFoUDTpLGRDUDYDMn0C0A=", + "dev": true + }, + "path-parse": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.6.tgz", + "integrity": "sha512-GSmOT2EbHrINBf9SR7CDELwlJ8AENk3Qn7OikK4nFYAu3Ote2+JYNVvkpAEQm3/TLNEJFD/xZJjzyxg3KBWOzw==" + }, + "path-type": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-2.0.0.tgz", + "integrity": "sha1-8BLMuEFbcJb8LaoQVMPXI4lZTHM=", + "dev": true, + "requires": { + "pify": "^2.0.0" + } + }, + "picomatch": { + "version": "2.0.7", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.0.7.tgz", + "integrity": "sha512-oLHIdio3tZ0qH76NybpeneBhYVj0QFTfXEFTc/B3zKQspYfYYkWYgFsmzo+4kvId/bQRcNkVeguI3y+CD22BtA==", + "dev": true + }, + "pify": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", + "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", + "dev": true + }, + "pinkie": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/pinkie/-/pinkie-2.0.4.tgz", + "integrity": "sha1-clVrgM+g1IqXToDnckjoDtT3+HA=", + "dev": true + }, + "pinkie-promise": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/pinkie-promise/-/pinkie-promise-2.0.1.tgz", + "integrity": "sha1-ITXW36ejWMBprJsXh3YogihFD/o=", + "dev": true, + "requires": { + "pinkie": "^2.0.0" + } + }, + "pkg-conf": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/pkg-conf/-/pkg-conf-3.1.0.tgz", + "integrity": "sha512-m0OTbR/5VPNPqO1ph6Fqbj7Hv6QU7gR/tQW40ZqrL1rjgCU85W6C1bJn0BItuJqnR98PWzw7Z8hHeChD1WrgdQ==", + "dev": true, + "requires": { + "find-up": "^3.0.0", + "load-json-file": "^5.2.0" + }, + "dependencies": { + "find-up": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", + "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", + "dev": true, + "requires": { + "locate-path": "^3.0.0" + } + }, + "load-json-file": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-5.3.0.tgz", + "integrity": "sha512-cJGP40Jc/VXUsp8/OrnyKyTZ1y6v/dphm3bioS+RrKXjK2BB6wHUd6JptZEFDGgGahMT+InnZO5i1Ei9mpC8Bw==", + "dev": true, + "requires": { + "graceful-fs": "^4.1.15", + "parse-json": "^4.0.0", + "pify": "^4.0.1", + "strip-bom": "^3.0.0", + "type-fest": "^0.3.0" + } + }, + "locate-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz", + "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==", + "dev": true, + "requires": { + "p-locate": "^3.0.0", + "path-exists": "^3.0.0" + } + }, + "p-limit": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.2.1.tgz", + "integrity": "sha512-85Tk+90UCVWvbDavCLKPOLC9vvY8OwEX/RtKF+/1OADJMVlFfEHOiMTPVyxg7mk/dKa+ipdHm0OUkTvCpMTuwg==", + "dev": true, + "requires": { + "p-try": "^2.0.0" + } + }, + "p-locate": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz", + "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==", + "dev": true, + "requires": { + "p-limit": "^2.0.0" + } + }, + "p-try": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", + "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", + "dev": true + }, + "parse-json": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-4.0.0.tgz", + "integrity": "sha1-vjX1Qlvh9/bHRxhPmKeIy5lHfuA=", + "dev": true, + "requires": { + "error-ex": "^1.3.1", + "json-parse-better-errors": "^1.0.1" + } + }, + "pify": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/pify/-/pify-4.0.1.tgz", + "integrity": "sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==", + "dev": true + }, + "type-fest": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.3.1.tgz", + "integrity": "sha512-cUGJnCdr4STbePCgqNFbpVNCepa+kAVohJs1sLhxzdH+gnEoOd8VhbYa7pD3zZYGiURWM2xzEII3fQcRizDkYQ==", + "dev": true + } + } + }, + "pkg-dir": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-2.0.0.tgz", + "integrity": "sha1-9tXREJ4Z1j7fQo4L1X4Sd3YVM0s=", + "dev": true, + "requires": { + "find-up": "^2.1.0" + } + }, + "plur": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/plur/-/plur-3.1.1.tgz", + "integrity": "sha512-t1Ax8KUvV3FFII8ltczPn2tJdjqbd1sIzu6t4JL7nQ3EyeL/lTrj5PWKb06ic5/6XYDr65rQ4uzQEGN70/6X5w==", + "dev": true, + "requires": { + "irregular-plurals": "^2.0.0" + } + }, + "prelude-ls": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.1.2.tgz", + "integrity": "sha1-IZMqVJ9eUv/ZqCf1cOBL5iqX2lQ=", + "dev": true + }, + "prepend-http": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/prepend-http/-/prepend-http-2.0.0.tgz", + "integrity": "sha1-6SQ0v6XqjBn0HN/UAddBo8gZ2Jc=", + "dev": true + }, + "pretty-ms": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/pretty-ms/-/pretty-ms-5.0.0.tgz", + "integrity": "sha512-94VRYjL9k33RzfKiGokPBPpsmloBYSf5Ri+Pq19zlsEcUKFob+admeXr5eFDRuPjFmEOcjJvPGdillYOJyvZ7Q==", + "dev": true, + "requires": { + "parse-ms": "^2.1.0" + } + }, + "private": { + "version": "0.1.8", + "resolved": "https://registry.npmjs.org/private/-/private-0.1.8.tgz", + "integrity": "sha512-VvivMrbvd2nKkiG38qjULzlc+4Vx4wm/whI9pQD35YrARNnhxeiRktSOhSukRLFNlzg6Br/cJPet5J/u19r/mg==", + "dev": true + }, + "progress": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/progress/-/progress-2.0.3.tgz", + "integrity": "sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==", + "dev": true + }, + "pseudomap": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/pseudomap/-/pseudomap-1.0.2.tgz", + "integrity": "sha1-8FKijacOYYkX7wqKw0wa5aaChrM=", + "dev": true + }, + "pump": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz", + "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==", + "dev": true, + "requires": { + "end-of-stream": "^1.1.0", + "once": "^1.3.1" + } + }, + "punycode": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", + "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==", + "dev": true + }, + "quick-lru": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/quick-lru/-/quick-lru-1.1.0.tgz", + "integrity": "sha1-Q2CxfGETatOAeDl/8RQW4Ybc+7g=", + "dev": true + }, + "rc": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/rc/-/rc-1.2.8.tgz", + "integrity": "sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==", + "dev": true, + "requires": { + "deep-extend": "^0.6.0", + "ini": "~1.3.0", + "minimist": "^1.2.0", + "strip-json-comments": "~2.0.1" + }, + "dependencies": { + "minimist": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", + "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=", + "dev": true + } + } + }, + "read-pkg": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-2.0.0.tgz", + "integrity": "sha1-jvHAYjxqbbDcZxPEv6xGMysjaPg=", + "dev": true, + "requires": { + "load-json-file": "^2.0.0", + "normalize-package-data": "^2.3.2", + "path-type": "^2.0.0" + } + }, + "read-pkg-up": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-2.0.0.tgz", + "integrity": "sha1-a3KoBImE4MQeeVEP1en6mbO1Sb4=", + "dev": true, + "requires": { + "find-up": "^2.0.0", + "read-pkg": "^2.0.0" + } + }, + "readdirp": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.1.2.tgz", + "integrity": "sha512-8rhl0xs2cxfVsqzreYCvs8EwBfn/DhVdqtoLmw19uI3SC5avYX9teCurlErfpPXGmYtMHReGaP2RsLnFvz/lnw==", + "dev": true, + "requires": { + "picomatch": "^2.0.4" + } + }, + "redent": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/redent/-/redent-2.0.0.tgz", + "integrity": "sha1-wbIAe0LVfrE4kHmzyDM2OdXhzKo=", + "dev": true, + "requires": { + "indent-string": "^3.0.0", + "strip-indent": "^2.0.0" + }, + "dependencies": { + "indent-string": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-3.2.0.tgz", + "integrity": "sha1-Sl/W0nzDMvN+VBmlBNu4NxBckok=", + "dev": true + } + } + }, + "regenerate": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/regenerate/-/regenerate-1.4.0.tgz", + "integrity": "sha512-1G6jJVDWrt0rK99kBjvEtziZNCICAuvIPkSiUFIQxVP06RCVpq3dmDo2oi6ABpYaDYaTRr67BEhL8r1wgEZZKg==", + "dev": true + }, + "regenerate-unicode-properties": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/regenerate-unicode-properties/-/regenerate-unicode-properties-8.1.0.tgz", + "integrity": "sha512-LGZzkgtLY79GeXLm8Dp0BVLdQlWICzBnJz/ipWUgo59qBaZ+BHtq51P2q1uVZlppMuUAT37SDk39qUbjTWB7bA==", + "dev": true, + "requires": { + "regenerate": "^1.4.0" + } + }, + "regenerator-runtime": { + "version": "0.11.1", + "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.11.1.tgz", + "integrity": "sha512-MguG95oij0fC3QV3URf4V2SDYGJhJnJGqvIIgdECeODCT98wSWDAJ94SSuVpYQUoTcGUIL6L4yNB7j1DFFHSBg==", + "dev": true + }, + "regenerator-transform": { + "version": "0.10.1", + "resolved": "https://registry.npmjs.org/regenerator-transform/-/regenerator-transform-0.10.1.tgz", + "integrity": "sha512-PJepbvDbuK1xgIgnau7Y90cwaAmO/LCLMI2mPvaXq2heGMR3aWW5/BQvYrhJ8jgmQjXewXvBjzfqKcVOmhjZ6Q==", + "dev": true, + "requires": { + "babel-runtime": "^6.18.0", + "babel-types": "^6.19.0", + "private": "^0.1.6" + } + }, + "regexpp": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/regexpp/-/regexpp-2.0.1.tgz", + "integrity": "sha512-lv0M6+TkDVniA3aD1Eg0DVpfU/booSu7Eev3TDO/mZKHBfVjgCGTV4t4buppESEYDtkArYFOxTJWv6S5C+iaNw==", + "dev": true + }, + "regexpu-core": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/regexpu-core/-/regexpu-core-2.0.0.tgz", + "integrity": "sha1-SdA4g3uNz4v6W5pCE5k45uoq4kA=", + "dev": true, + "requires": { + "regenerate": "^1.2.1", + "regjsgen": "^0.2.0", + "regjsparser": "^0.1.4" + } + }, + "registry-auth-token": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/registry-auth-token/-/registry-auth-token-4.0.0.tgz", + "integrity": "sha512-lpQkHxd9UL6tb3k/aHAVfnVtn+Bcs9ob5InuFLLEDqSqeq+AljB8GZW9xY0x7F+xYwEcjKe07nyoxzEYz6yvkw==", + "dev": true, + "requires": { + "rc": "^1.2.8", + "safe-buffer": "^5.0.1" + } + }, + "registry-url": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/registry-url/-/registry-url-5.1.0.tgz", + "integrity": "sha512-8acYXXTI0AkQv6RAOjE3vOaIXZkT9wo4LOFbBKYQEEnnMNBpKqdUrI6S4NT0KPIo/WVvJ5tE/X5LF/TQUf0ekw==", + "dev": true, + "requires": { + "rc": "^1.2.8" + } + }, + "regjsgen": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/regjsgen/-/regjsgen-0.2.0.tgz", + "integrity": "sha1-bAFq3qxVT3WCP+N6wFuS1aTtsfc=", + "dev": true + }, + "regjsparser": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/regjsparser/-/regjsparser-0.1.5.tgz", + "integrity": "sha1-fuj4Tcb6eS0/0K4ijSS9lJ6tIFw=", + "dev": true, + "requires": { + "jsesc": "~0.5.0" + } + }, + "release-zalgo": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/release-zalgo/-/release-zalgo-1.0.0.tgz", + "integrity": "sha1-CXALflB0Mpc5Mw5TXFqQ+2eFFzA=", + "dev": true, + "requires": { + "es6-error": "^4.0.1" + } + }, + "repeating": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/repeating/-/repeating-2.0.1.tgz", + "integrity": "sha1-UhTFOpJtNVJwdSf7q0FdvAjQbdo=", + "dev": true, + "requires": { + "is-finite": "^1.0.0" + } + }, + "require-directory": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", + "integrity": "sha1-jGStX9MNqxyXbiNE/+f3kqam30I=", + "dev": true + }, + "require-main-filename": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-2.0.0.tgz", + "integrity": "sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==", + "dev": true + }, + "require-precompiled": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/require-precompiled/-/require-precompiled-0.1.0.tgz", + "integrity": "sha1-WhtS63Dr7UPrmC6XTIWrWVceVvo=", + "dev": true + }, + "resolve": { + "version": "1.12.0", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.12.0.tgz", + "integrity": "sha512-B/dOmuoAik5bKcD6s6nXDCjzUKnaDvdkRyAk6rsmsKLipWj4797iothd7jmmUhWTfinVMU+wc56rYKsit2Qy4w==", + "requires": { + "path-parse": "^1.0.6" + } + }, + "resolve-cwd": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/resolve-cwd/-/resolve-cwd-3.0.0.tgz", + "integrity": "sha512-OrZaX2Mb+rJCpH/6CpSqt9xFVpN++x01XnN2ie9g6P5/3xelLAkXWVADpdz1IHD/KFfEXyE6V0U01OQ3UO2rEg==", + "dev": true, + "requires": { + "resolve-from": "^5.0.0" + } + }, + "resolve-from": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz", + "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==", + "dev": true + }, + "responselike": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/responselike/-/responselike-1.0.2.tgz", + "integrity": "sha1-kYcg7ztjHFZCvgaPFa3lpG9Loec=", + "dev": true, + "requires": { + "lowercase-keys": "^1.0.0" + } + }, + "restore-cursor": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-3.1.0.tgz", + "integrity": "sha512-l+sSefzHpj5qimhFSE5a8nufZYAM3sBSVMAPtYkmC+4EH2anSGaEMXSD0izRQbu9nfyQ9y5JrVmp7E8oZrUjvA==", + "dev": true, + "requires": { + "onetime": "^5.1.0", + "signal-exit": "^3.0.2" + } + }, + "reusify": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", + "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==", + "dev": true + }, + "rimraf": { + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz", + "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==", + "dev": true, + "requires": { + "glob": "^7.1.3" + } + }, + "rollup": { + "version": "1.19.4", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-1.19.4.tgz", + "integrity": "sha512-G24w409GNj7i/Yam2cQla6qV2k6Nug8bD2DZg9v63QX/cH/dEdbNJg8H4lUm5M1bRpPKRUC465Rm9H51JTKOfQ==", + "dev": true, + "requires": { + "@types/estree": "0.0.39", + "@types/node": "^12.6.9", + "acorn": "^6.2.1" + }, + "dependencies": { + "acorn": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-6.3.0.tgz", + "integrity": "sha512-/czfa8BwS88b9gWQVhc8eknunSA2DoJpJyTQkhheIf5E48u1N0R4q/YxxsAeqRrmK9TQ/uYfgLDfZo91UlANIA==", + "dev": true + } + } + }, + "rollup-plugin-babel": { + "version": "4.3.3", + "resolved": "https://registry.npmjs.org/rollup-plugin-babel/-/rollup-plugin-babel-4.3.3.tgz", + "integrity": "sha512-tKzWOCmIJD/6aKNz0H1GMM+lW1q9KyFubbWzGiOG540zxPPifnEAHTZwjo0g991Y+DyOZcLqBgqOdqazYE5fkw==", + "dev": true, + "requires": { + "@babel/helper-module-imports": "^7.0.0", + "rollup-pluginutils": "^2.8.1" + } + }, + "rollup-plugin-babel-minify": { + "version": "9.0.0", + "resolved": "https://registry.npmjs.org/rollup-plugin-babel-minify/-/rollup-plugin-babel-minify-9.0.0.tgz", + "integrity": "sha512-5aJVWpuoZUbQrIaRF7Jvjo7bBnYqaChOhrhsGtz72wJ3lyo7ygIL85hsuPkvrk/3Fj5AUlNZV3IaSZ98fHyoTw==", + "dev": true, + "requires": { + "@babel/core": "^7.4.5", + "@babel/plugin-syntax-dynamic-import": "^7.2.0", + "@comandeer/babel-plugin-banner": "^5.0.0", + "babel-preset-minify": "^0.5.0", + "sourcemap-codec": "^1.4.4" + } + }, + "rollup-plugin-commonjs": { + "version": "10.0.2", + "resolved": "https://registry.npmjs.org/rollup-plugin-commonjs/-/rollup-plugin-commonjs-10.0.2.tgz", + "integrity": "sha512-DxeR4QXTgTOFseYls1V7vgKbrSJmPYNdEMOs0OvH+7+89C3GiIonU9gFrE0u39Vv1KWm3wepq8KAvKugtoM2Zw==", + "requires": { + "estree-walker": "^0.6.1", + "is-reference": "^1.1.2", + "magic-string": "^0.25.2", + "resolve": "^1.11.0", + "rollup-pluginutils": "^2.8.1" + } + }, + "rollup-plugin-node-resolve": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/rollup-plugin-node-resolve/-/rollup-plugin-node-resolve-5.2.0.tgz", + "integrity": "sha512-jUlyaDXts7TW2CqQ4GaO5VJ4PwwaV8VUGA7+km3n6k6xtOEacf61u0VXwN80phY/evMcaS+9eIeJ9MOyDxt5Zw==", + "dev": true, + "requires": { + "@types/resolve": "0.0.8", + "builtin-modules": "^3.1.0", + "is-module": "^1.0.0", + "resolve": "^1.11.1", + "rollup-pluginutils": "^2.8.1" + } + }, + "rollup-pluginutils": { + "version": "2.8.1", + "resolved": "https://registry.npmjs.org/rollup-pluginutils/-/rollup-pluginutils-2.8.1.tgz", + "integrity": "sha512-J5oAoysWar6GuZo0s+3bZ6sVZAC0pfqKz68De7ZgDi5z63jOVZn1uJL/+z1jeKHNbGII8kAyHF5q8LnxSX5lQg==", + "requires": { + "estree-walker": "^0.6.1" + } + }, + "run-async": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/run-async/-/run-async-2.3.0.tgz", + "integrity": "sha1-A3GrSuC91yDUFm19/aZP96RFpsA=", + "dev": true, + "requires": { + "is-promise": "^2.1.0" + } + }, + "run-parallel": { + "version": "1.1.9", + "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.1.9.tgz", + "integrity": "sha512-DEqnSRTDw/Tc3FXf49zedI638Z9onwUotBMiUFKmrO2sdFKIbXamXGQ3Axd4qgphxKB4kw/qP1w5kTxnfU1B9Q==", + "dev": true + }, + "rxjs": { + "version": "6.5.2", + "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-6.5.2.tgz", + "integrity": "sha512-HUb7j3kvb7p7eCUHE3FqjoDsC1xfZQ4AHFWfTKSpZ+sAhhz5X1WX0ZuUqWbzB2QhSLp3DoLUG+hMdEDKqWo2Zg==", + "dev": true, + "requires": { + "tslib": "^1.9.0" + } + }, + "safe-buffer": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.0.tgz", + "integrity": "sha512-fZEwUGbVl7kouZs1jCdMLdt95hdIv0ZeHg6L7qPeciMZhZ+/gdesW4wgTARkrFWEpspjEATAzUGPG8N2jJiwbg==", + "dev": true + }, + "safer-buffer": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", + "dev": true + }, + "semver": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", + "dev": true + }, + "semver-diff": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/semver-diff/-/semver-diff-2.1.0.tgz", + "integrity": "sha1-S7uEN8jTfksM8aaP1ybsbWRdbTY=", + "dev": true, + "requires": { + "semver": "^5.0.3" + } + }, + "serialize-error": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/serialize-error/-/serialize-error-2.1.0.tgz", + "integrity": "sha1-ULZ51WNc34Rme9yOWa9OW4HV9go=", + "dev": true + }, + "set-blocking": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", + "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=", + "dev": true + }, + "shebang-command": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-1.2.0.tgz", + "integrity": "sha1-RKrGW2lbAzmJaMOfNj/uXer98eo=", + "dev": true, + "requires": { + "shebang-regex": "^1.0.0" + } + }, + "shebang-regex": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-1.0.0.tgz", + "integrity": "sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM=", + "dev": true + }, + "signal-exit": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.2.tgz", + "integrity": "sha1-tf3AjxKH6hF4Yo5BXiUTK3NkbG0=", + "dev": true + }, + "slash": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-1.0.0.tgz", + "integrity": "sha1-xB8vbDn8FtHNF61LXYlhFK5HDVU=", + "dev": true + }, + "slice-ansi": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-2.1.0.tgz", + "integrity": "sha512-Qu+VC3EwYLldKa1fCxuuvULvSJOKEgk9pi8dZeCVK7TqBfUNTH4sFkk4joj8afVSfAYgJoSOetjx9QWOJ5mYoQ==", + "dev": true, + "requires": { + "ansi-styles": "^3.2.0", + "astral-regex": "^1.0.0", + "is-fullwidth-code-point": "^2.0.0" + }, + "dependencies": { + "ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "requires": { + "color-convert": "^1.9.0" + } + } + } + }, + "source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", + "dev": true + }, + "source-map-support": { + "version": "0.4.18", + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.4.18.tgz", + "integrity": "sha512-try0/JqxPLF9nOjvSta7tVondkP5dwgyLDjVoyMDlmjugT2lRZ1OfsrYTkCd2hkDnJTKRbO/Rl3orm8vlsUzbA==", + "dev": true, + "requires": { + "source-map": "^0.5.6" + } + }, + "sourcemap-codec": { + "version": "1.4.6", + "resolved": "https://registry.npmjs.org/sourcemap-codec/-/sourcemap-codec-1.4.6.tgz", + "integrity": "sha512-1ZooVLYFxC448piVLBbtOxFcXwnymH9oUF8nRd3CuYDVvkRBxRl6pB4Mtas5a4drtL+E8LDgFkQNcgIw6tc8Hg==" + }, + "spawn-wrap": { + "version": "1.4.2", + "resolved": "https://registry.npmjs.org/spawn-wrap/-/spawn-wrap-1.4.2.tgz", + "integrity": "sha512-vMwR3OmmDhnxCVxM8M+xO/FtIp6Ju/mNaDfCMMW7FDcLRTPFWUswec4LXJHTJE2hwTI9O0YBfygu4DalFl7Ylg==", + "dev": true, + "requires": { + "foreground-child": "^1.5.6", + "mkdirp": "^0.5.0", + "os-homedir": "^1.0.1", + "rimraf": "^2.6.2", + "signal-exit": "^3.0.2", + "which": "^1.3.0" + } + }, + "spdx-correct": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.1.0.tgz", + "integrity": "sha512-lr2EZCctC2BNR7j7WzJ2FpDznxky1sjfxvvYEyzxNyb6lZXHODmEoJeFu4JupYlkfha1KZpJyoqiJ7pgA1qq8Q==", + "dev": true, + "requires": { + "spdx-expression-parse": "^3.0.0", + "spdx-license-ids": "^3.0.0" + } + }, + "spdx-exceptions": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.2.0.tgz", + "integrity": "sha512-2XQACfElKi9SlVb1CYadKDXvoajPgBVPn/gOQLrTvHdElaVhr7ZEbqJaRnJLVNeaI4cMEAgVCeBMKF6MWRDCRA==", + "dev": true + }, + "spdx-expression-parse": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.0.tgz", + "integrity": "sha512-Yg6D3XpRD4kkOmTpdgbUiEJFKghJH03fiC1OPll5h/0sO6neh2jqRDVHOQ4o/LMea0tgCkbMgea5ip/e+MkWyg==", + "dev": true, + "requires": { + "spdx-exceptions": "^2.1.0", + "spdx-license-ids": "^3.0.0" + } + }, + "spdx-license-ids": { + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.5.tgz", + "integrity": "sha512-J+FWzZoynJEXGphVIS+XEh3kFSjZX/1i9gFBaWQcB+/tmpe2qUsSBABpcxqxnAxFdiUFEgAX1bjYGQvIZmoz9Q==", + "dev": true + }, + "sprintf-js": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", + "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=", + "dev": true + }, + "stack-utils": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/stack-utils/-/stack-utils-1.0.2.tgz", + "integrity": "sha512-MTX+MeG5U994cazkjd/9KNAapsHnibjMLnfXodlkXw76JEea0UiNzrqidzo1emMwk7w5Qhc9jd4Bn9TBb1MFwA==", + "dev": true + }, + "string-width": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.1.0.tgz", + "integrity": "sha512-NrX+1dVVh+6Y9dnQ19pR0pP4FiEIlUvdTGn8pw6CKTNq5sgib2nIhmUNT5TAmhWmvKr3WcxBcP3E8nWezuipuQ==", + "dev": true, + "requires": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^5.2.0" + }, + "dependencies": { + "is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "dev": true + } + } + }, + "strip-ansi": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", + "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", + "dev": true, + "requires": { + "ansi-regex": "^4.1.0" + }, + "dependencies": { + "ansi-regex": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", + "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==", + "dev": true + } + } + }, + "strip-bom": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", + "integrity": "sha1-IzTBjpx1n3vdVv3vfprj1YjmjtM=", + "dev": true + }, + "strip-bom-buf": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/strip-bom-buf/-/strip-bom-buf-2.0.0.tgz", + "integrity": "sha512-gLFNHucd6gzb8jMsl5QmZ3QgnUJmp7qn4uUSHNwEXumAp7YizoGYw19ZUVfuq4aBOQUtyn2k8X/CwzWB73W2lQ==", + "dev": true, + "requires": { + "is-utf8": "^0.2.1" + } + }, + "strip-eof": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/strip-eof/-/strip-eof-1.0.0.tgz", + "integrity": "sha1-u0P/VZim6wXYm1n80SnJgzE2Br8=", + "dev": true + }, + "strip-indent": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/strip-indent/-/strip-indent-2.0.0.tgz", + "integrity": "sha1-XvjbKV0B5u1sv3qrlpmNeCJSe2g=", + "dev": true + }, + "strip-json-comments": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", + "integrity": "sha1-PFMZQukIwml8DsNEhYwobHygpgo=", + "dev": true + }, + "supertap": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/supertap/-/supertap-1.0.0.tgz", + "integrity": "sha512-HZJ3geIMPgVwKk2VsmO5YHqnnJYl6bV5A9JW2uzqV43WmpgliNEYbuvukfor7URpaqpxuw3CfZ3ONdVbZjCgIA==", + "dev": true, + "requires": { + "arrify": "^1.0.1", + "indent-string": "^3.2.0", + "js-yaml": "^3.10.0", + "serialize-error": "^2.1.0", + "strip-ansi": "^4.0.0" + }, + "dependencies": { + "ansi-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", + "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", + "dev": true + }, + "arrify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/arrify/-/arrify-1.0.1.tgz", + "integrity": "sha1-iYUI2iIm84DfkEcoRWhJwVAaSw0=", + "dev": true + }, + "indent-string": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-3.2.0.tgz", + "integrity": "sha1-Sl/W0nzDMvN+VBmlBNu4NxBckok=", + "dev": true + }, + "strip-ansi": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", + "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", + "dev": true, + "requires": { + "ansi-regex": "^3.0.0" + } + } + } + }, + "supports-color": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.0.0.tgz", + "integrity": "sha512-WRt32iTpYEZWYOpcetGm0NPeSvaebccx7hhS/5M6sAiqnhedtFCHFxkjzZlJvFNCPowiKSFGiZk5USQDFy83vQ==", + "dev": true, + "requires": { + "has-flag": "^4.0.0" + }, + "dependencies": { + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true + } + } + }, + "symbol-observable": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/symbol-observable/-/symbol-observable-1.2.0.tgz", + "integrity": "sha512-e900nM8RRtGhlV36KGEU9k65K3mPb1WV70OdjfxlG2EAuM1noi/E/BaW/uMhL7bPEssK8QV57vN3esixjUvcXQ==", + "dev": true + }, + "table": { + "version": "5.4.6", + "resolved": "https://registry.npmjs.org/table/-/table-5.4.6.tgz", + "integrity": "sha512-wmEc8m4fjnob4gt5riFRtTu/6+4rSe12TpAELNSqHMfF3IqnA+CH37USM6/YR3qRZv7e56kAEAtd6nKZaxe0Ug==", + "dev": true, + "requires": { + "ajv": "^6.10.2", + "lodash": "^4.17.14", + "slice-ansi": "^2.1.0", + "string-width": "^3.0.0" + }, + "dependencies": { + "emoji-regex": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-7.0.3.tgz", + "integrity": "sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA==", + "dev": true + }, + "string-width": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz", + "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==", + "dev": true, + "requires": { + "emoji-regex": "^7.0.1", + "is-fullwidth-code-point": "^2.0.0", + "strip-ansi": "^5.1.0" + } + } + } + }, + "tailored": { + "version": "2.7.5", + "resolved": "https://registry.npmjs.org/tailored/-/tailored-2.7.5.tgz", + "integrity": "sha512-5zLODXUWx3P8SPVbFA9RgaUrpTGJMXg67jMaZJmJJwE9jQXuCfJb7bnO/1FuTsrFFZTDDmkYR/PPz9gAN26CmQ==", + "requires": { + "erlang-types": "^1.0.1" + } + }, + "term-size": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/term-size/-/term-size-1.2.0.tgz", + "integrity": "sha1-RYuDiH8oj8Vtb/+/rSYuJmOO+mk=", + "dev": true, + "requires": { + "execa": "^0.7.0" + } + }, + "test-exclude": { + "version": "5.2.3", + "resolved": "https://registry.npmjs.org/test-exclude/-/test-exclude-5.2.3.tgz", + "integrity": "sha512-M+oxtseCFO3EDtAaGH7iiej3CBkzXqFMbzqYAACdzKui4eZA+pq3tZEwChvOdNfa7xxy8BfbmgJSIr43cC/+2g==", + "dev": true, + "requires": { + "glob": "^7.1.3", + "minimatch": "^3.0.4", + "read-pkg-up": "^4.0.0", + "require-main-filename": "^2.0.0" + }, + "dependencies": { + "find-up": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", + "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", + "dev": true, + "requires": { + "locate-path": "^3.0.0" + } + }, + "load-json-file": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-4.0.0.tgz", + "integrity": "sha1-L19Fq5HjMhYjT9U62rZo607AmTs=", + "dev": true, + "requires": { + "graceful-fs": "^4.1.2", + "parse-json": "^4.0.0", + "pify": "^3.0.0", + "strip-bom": "^3.0.0" + } + }, + "locate-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz", + "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==", + "dev": true, + "requires": { + "p-locate": "^3.0.0", + "path-exists": "^3.0.0" + } + }, + "p-limit": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.2.1.tgz", + "integrity": "sha512-85Tk+90UCVWvbDavCLKPOLC9vvY8OwEX/RtKF+/1OADJMVlFfEHOiMTPVyxg7mk/dKa+ipdHm0OUkTvCpMTuwg==", + "dev": true, + "requires": { + "p-try": "^2.0.0" + } + }, + "p-locate": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz", + "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==", + "dev": true, + "requires": { + "p-limit": "^2.0.0" + } + }, + "p-try": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", + "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", + "dev": true + }, + "parse-json": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-4.0.0.tgz", + "integrity": "sha1-vjX1Qlvh9/bHRxhPmKeIy5lHfuA=", + "dev": true, + "requires": { + "error-ex": "^1.3.1", + "json-parse-better-errors": "^1.0.1" + } + }, + "path-type": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-3.0.0.tgz", + "integrity": "sha512-T2ZUsdZFHgA3u4e5PfPbjd7HDDpxPnQb5jN0SrDsjNSuVXHJqtwTnWqG0B1jZrgmJ/7lj1EmVIByWt1gxGkWvg==", + "dev": true, + "requires": { + "pify": "^3.0.0" + } + }, + "pify": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", + "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=", + "dev": true + }, + "read-pkg": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-3.0.0.tgz", + "integrity": "sha1-nLxoaXj+5l0WwA4rGcI3/Pbjg4k=", + "dev": true, + "requires": { + "load-json-file": "^4.0.0", + "normalize-package-data": "^2.3.2", + "path-type": "^3.0.0" + } + }, + "read-pkg-up": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-4.0.0.tgz", + "integrity": "sha512-6etQSH7nJGsK0RbG/2TeDzZFa8shjQ1um+SwQQ5cwKy0dhSXdOncEhb1CPpvQG4h7FyOV6EB6YlV0yJvZQNAkA==", + "dev": true, + "requires": { + "find-up": "^3.0.0", + "read-pkg": "^3.0.0" + } + } + } + }, + "text-table": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", + "integrity": "sha1-f17oI66AUgfACvLfSoTsP8+lcLQ=", + "dev": true + }, + "through": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", + "integrity": "sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=", + "dev": true + }, + "time-zone": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/time-zone/-/time-zone-1.0.0.tgz", + "integrity": "sha1-mcW/VZWJZq9tBtg73zgA3IL67F0=", + "dev": true + }, + "tmp": { + "version": "0.0.33", + "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.33.tgz", + "integrity": "sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==", + "dev": true, + "requires": { + "os-tmpdir": "~1.0.2" + } + }, + "to-fast-properties": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-1.0.3.tgz", + "integrity": "sha1-uDVx+k2MJbguIxsG46MFXeTKGkc=", + "dev": true + }, + "to-readable-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/to-readable-stream/-/to-readable-stream-1.0.0.tgz", + "integrity": "sha512-Iq25XBt6zD5npPhlLVXGFN3/gyR2/qODcKNNyTMd4vbm39HUaOiAM4PMq0eMVC/Tkxz+Zjdsc55g9yyz+Yq00Q==", + "dev": true + }, + "to-regex-range": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", + "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", + "dev": true, + "requires": { + "is-number": "^7.0.0" + } + }, + "trim-newlines": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/trim-newlines/-/trim-newlines-2.0.0.tgz", + "integrity": "sha1-tAPQuRvlDDMd/EuC7s6yLD3hbSA=", + "dev": true + }, + "trim-off-newlines": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/trim-off-newlines/-/trim-off-newlines-1.0.1.tgz", + "integrity": "sha1-n5up2e+odkw4dpi8v+sshI8RrbM=", + "dev": true + }, + "trim-right": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/trim-right/-/trim-right-1.0.1.tgz", + "integrity": "sha1-yy4SAwZ+DI3h9hQJS5/kVwTqYAM=", + "dev": true + }, + "tslib": { + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.10.0.tgz", + "integrity": "sha512-qOebF53frne81cf0S9B41ByenJ3/IuH8yJKngAX35CmiZySA0khhkovshKK+jGCaMnVomla7gVlIcc3EvKPbTQ==", + "dev": true + }, + "type-check": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.3.2.tgz", + "integrity": "sha1-WITKtRLPHTVeP7eE8wgEsrUg23I=", + "dev": true, + "requires": { + "prelude-ls": "~1.1.2" + } + }, + "type-fest": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.5.2.tgz", + "integrity": "sha512-DWkS49EQKVX//Tbupb9TFa19c7+MK1XmzkrZUR8TAktmE/DizXoaoJV6TZ/tSIPXipqNiRI6CyAe7x69Jb6RSw==", + "dev": true + }, + "typedarray-to-buffer": { + "version": "3.1.5", + "resolved": "https://registry.npmjs.org/typedarray-to-buffer/-/typedarray-to-buffer-3.1.5.tgz", + "integrity": "sha512-zdu8XMNEDepKKR+XYOXAVPtWui0ly0NtohUscw+UmaHiAWT8hrV1rr//H6V+0DvJ3OQ19S979M0laLfX8rm82Q==", + "dev": true, + "requires": { + "is-typedarray": "^1.0.0" + } + }, + "uglify-js": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.6.0.tgz", + "integrity": "sha512-W+jrUHJr3DXKhrsS7NUVxn3zqMOFn0hL/Ei6v0anCIMoKC93TjcflTagwIHLW7SfMFfiQuktQyFVCFHGUE0+yg==", + "dev": true, + "optional": true, + "requires": { + "commander": "~2.20.0", + "source-map": "~0.6.1" + }, + "dependencies": { + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true, + "optional": true + } + } + }, + "uid2": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/uid2/-/uid2-0.0.3.tgz", + "integrity": "sha1-SDEm4Rd03y9xuLY53NeZw3YWK4I=", + "dev": true + }, + "unicode-canonical-property-names-ecmascript": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/unicode-canonical-property-names-ecmascript/-/unicode-canonical-property-names-ecmascript-1.0.4.tgz", + "integrity": "sha512-jDrNnXWHd4oHiTZnx/ZG7gtUTVp+gCcTTKr8L0HjlwphROEW3+Him+IpvC+xcJEFegapiMZyZe02CyuOnRmbnQ==", + "dev": true + }, + "unicode-match-property-ecmascript": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/unicode-match-property-ecmascript/-/unicode-match-property-ecmascript-1.0.4.tgz", + "integrity": "sha512-L4Qoh15vTfntsn4P1zqnHulG0LdXgjSO035fEpdtp6YxXhMT51Q6vgM5lYdG/5X3MjS+k/Y9Xw4SFCY9IkR0rg==", + "dev": true, + "requires": { + "unicode-canonical-property-names-ecmascript": "^1.0.4", + "unicode-property-aliases-ecmascript": "^1.0.4" + } + }, + "unicode-match-property-value-ecmascript": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/unicode-match-property-value-ecmascript/-/unicode-match-property-value-ecmascript-1.1.0.tgz", + "integrity": "sha512-hDTHvaBk3RmFzvSl0UVrUmC3PuW9wKVnpoUDYH0JDkSIovzw+J5viQmeYHxVSBptubnr7PbH2e0fnpDRQnQl5g==", + "dev": true + }, + "unicode-property-aliases-ecmascript": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/unicode-property-aliases-ecmascript/-/unicode-property-aliases-ecmascript-1.0.5.tgz", + "integrity": "sha512-L5RAqCfXqAwR3RriF8pM0lU0w4Ryf/GgzONwi6KnL1taJQa7x1TCxdJnILX59WIGOwR57IVxn7Nej0fz1Ny6fw==", + "dev": true + }, + "unique-string": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/unique-string/-/unique-string-1.0.0.tgz", + "integrity": "sha1-nhBXzKhRq7kzmPizOuGHuZyuwRo=", + "dev": true, + "requires": { + "crypto-random-string": "^1.0.0" + } + }, + "unique-temp-dir": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/unique-temp-dir/-/unique-temp-dir-1.0.0.tgz", + "integrity": "sha1-bc6VsmgcoAPuv7MEpBX5y6vMU4U=", + "dev": true, + "requires": { + "mkdirp": "^0.5.1", + "os-tmpdir": "^1.0.1", + "uid2": "0.0.3" + } + }, + "update-notifier": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/update-notifier/-/update-notifier-3.0.1.tgz", + "integrity": "sha512-grrmrB6Zb8DUiyDIaeRTBCkgISYUgETNe7NglEbVsrLWXeESnlCSP50WfRSj/GmzMPl6Uchj24S/p80nP/ZQrQ==", + "dev": true, + "requires": { + "boxen": "^3.0.0", + "chalk": "^2.0.1", + "configstore": "^4.0.0", + "has-yarn": "^2.1.0", + "import-lazy": "^2.1.0", + "is-ci": "^2.0.0", + "is-installed-globally": "^0.1.0", + "is-npm": "^3.0.0", + "is-yarn-global": "^0.3.0", + "latest-version": "^5.0.0", + "semver-diff": "^2.0.0", + "xdg-basedir": "^3.0.0" + } + }, + "uri-js": { + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.2.2.tgz", + "integrity": "sha512-KY9Frmirql91X2Qgjry0Wd4Y+YTdrdZheS8TFwvkbLWf/G5KNJDCh6pKL5OZctEW4+0Baa5idK2ZQuELRwPznQ==", + "dev": true, + "requires": { + "punycode": "^2.1.0" + } + }, + "url-parse-lax": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/url-parse-lax/-/url-parse-lax-3.0.0.tgz", + "integrity": "sha1-FrXK/Afb42dsGxmZF3gj1lA6yww=", + "dev": true, + "requires": { + "prepend-http": "^2.0.0" + } + }, + "uuid": { + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.3.3.tgz", + "integrity": "sha512-pW0No1RGHgzlpHJO1nsVrHKpOEIxkGg1xB+v0ZmdNH5OAeAwzAVrCnI2/6Mtx+Uys6iaylxa+D3g4j63IKKjSQ==", + "dev": true + }, + "v8-compile-cache": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/v8-compile-cache/-/v8-compile-cache-2.1.0.tgz", + "integrity": "sha512-usZBT3PW+LOjM25wbqIlZwPeJV+3OSz3M1k1Ws8snlW39dZyYL9lOGC5FgPVHfk0jKmjiDV8Z0mIbVQPiwFs7g==", + "dev": true + }, + "validate-npm-package-license": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz", + "integrity": "sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==", + "dev": true, + "requires": { + "spdx-correct": "^3.0.0", + "spdx-expression-parse": "^3.0.0" + } + }, + "wcwidth": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/wcwidth/-/wcwidth-1.0.1.tgz", + "integrity": "sha1-8LDc+RW8X/FSivrbLA4XtTLaL+g=", + "dev": true, + "requires": { + "defaults": "^1.0.3" + } + }, + "well-known-symbols": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/well-known-symbols/-/well-known-symbols-2.0.0.tgz", + "integrity": "sha512-ZMjC3ho+KXo0BfJb7JgtQ5IBuvnShdlACNkKkdsqBmYw3bPAaJfPeYUo6tLUaT5tG/Gkh7xkpBhKRQ9e7pyg9Q==", + "dev": true + }, + "which": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", + "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", + "dev": true, + "requires": { + "isexe": "^2.0.0" + } + }, + "which-module": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/which-module/-/which-module-2.0.0.tgz", + "integrity": "sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho=", + "dev": true + }, + "widest-line": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/widest-line/-/widest-line-2.0.1.tgz", + "integrity": "sha512-Ba5m9/Fa4Xt9eb2ELXt77JxVDV8w7qQrH0zS/TWSJdLyAwQjWoOzpzj5lwVftDz6n/EOu3tNACS84v509qwnJA==", + "dev": true, + "requires": { + "string-width": "^2.1.1" + }, + "dependencies": { + "ansi-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", + "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", + "dev": true + }, + "string-width": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", + "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==", + "dev": true, + "requires": { + "is-fullwidth-code-point": "^2.0.0", + "strip-ansi": "^4.0.0" + } + }, + "strip-ansi": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", + "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", + "dev": true, + "requires": { + "ansi-regex": "^3.0.0" + } + } + } + }, + "wordwrap": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-1.0.0.tgz", + "integrity": "sha1-J1hIEIkUVqQXHI0CJkQa3pDLyus=", + "dev": true + }, + "wrap-ansi": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-5.1.0.tgz", + "integrity": "sha512-QC1/iN/2/RPVJ5jYK8BGttj5z83LmSKmvbvrXPNCLZSEb32KKVDJDl/MOt2N01qU2H/FkzEa9PKto1BqDjtd7Q==", + "dev": true, + "requires": { + "ansi-styles": "^3.2.0", + "string-width": "^3.0.0", + "strip-ansi": "^5.0.0" + }, + "dependencies": { + "ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "requires": { + "color-convert": "^1.9.0" + } + }, + "emoji-regex": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-7.0.3.tgz", + "integrity": "sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA==", + "dev": true + }, + "string-width": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz", + "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==", + "dev": true, + "requires": { + "emoji-regex": "^7.0.1", + "is-fullwidth-code-point": "^2.0.0", + "strip-ansi": "^5.1.0" + } + } + } + }, + "wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=", + "dev": true + }, + "write": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/write/-/write-1.0.3.tgz", + "integrity": "sha512-/lg70HAjtkUgWPVZhZcm+T4hkL8Zbtp1nFNOn3lRrxnlv50SRBv7cR7RqR+GMsd3hUXy9hWBo4CHTbFTcOYwig==", + "dev": true, + "requires": { + "mkdirp": "^0.5.1" + } + }, + "write-file-atomic": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-3.0.0.tgz", + "integrity": "sha512-EIgkf60l2oWsffja2Sf2AL384dx328c0B+cIYPTQq5q2rOYuDV00/iPFBOUiDKKwKMOhkymH8AidPaRvzfxY+Q==", + "dev": true, + "requires": { + "imurmurhash": "^0.1.4", + "is-typedarray": "^1.0.0", + "signal-exit": "^3.0.2", + "typedarray-to-buffer": "^3.1.5" + } + }, + "xdg-basedir": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/xdg-basedir/-/xdg-basedir-3.0.0.tgz", + "integrity": "sha1-SWsswQnsqNus/i3HK2A8F8WHCtQ=", + "dev": true + }, + "xtend": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", + "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==", + "dev": true + }, + "y18n": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.0.tgz", + "integrity": "sha512-r9S/ZyXu/Xu9q1tYlpsLIsa3EeLXXk0VwlxqTcFRfg9EhMW+17kbt9G0NrgCmhGb5vT2hyhJZLfDGx+7+5Uj/w==", + "dev": true + }, + "yallist": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-2.1.2.tgz", + "integrity": "sha1-HBH5IY8HYImkfdUS+TxmmaaoHVI=", + "dev": true + }, + "yargs": { + "version": "13.3.0", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-13.3.0.tgz", + "integrity": "sha512-2eehun/8ALW8TLoIl7MVaRUrg+yCnenu8B4kBlRxj3GJGDKU1Og7sMXPNm1BYyM1DOJmTZ4YeN/Nwxv+8XJsUA==", + "dev": true, + "requires": { + "cliui": "^5.0.0", + "find-up": "^3.0.0", + "get-caller-file": "^2.0.1", + "require-directory": "^2.1.1", + "require-main-filename": "^2.0.0", + "set-blocking": "^2.0.0", + "string-width": "^3.0.0", + "which-module": "^2.0.0", + "y18n": "^4.0.0", + "yargs-parser": "^13.1.1" + }, + "dependencies": { + "camelcase": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", + "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", + "dev": true + }, + "emoji-regex": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-7.0.3.tgz", + "integrity": "sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA==", + "dev": true + }, + "find-up": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", + "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", + "dev": true, + "requires": { + "locate-path": "^3.0.0" + } + }, + "locate-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz", + "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==", + "dev": true, + "requires": { + "p-locate": "^3.0.0", + "path-exists": "^3.0.0" + } + }, + "p-limit": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.2.1.tgz", + "integrity": "sha512-85Tk+90UCVWvbDavCLKPOLC9vvY8OwEX/RtKF+/1OADJMVlFfEHOiMTPVyxg7mk/dKa+ipdHm0OUkTvCpMTuwg==", + "dev": true, + "requires": { + "p-try": "^2.0.0" + } + }, + "p-locate": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz", + "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==", + "dev": true, + "requires": { + "p-limit": "^2.0.0" + } + }, + "p-try": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", + "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", + "dev": true + }, + "string-width": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz", + "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==", + "dev": true, + "requires": { + "emoji-regex": "^7.0.1", + "is-fullwidth-code-point": "^2.0.0", + "strip-ansi": "^5.1.0" + } + }, + "yargs-parser": { + "version": "13.1.1", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-13.1.1.tgz", + "integrity": "sha512-oVAVsHz6uFrg3XQheFII8ESO2ssAf9luWuAd6Wexsu4F3OtIW0o8IribPXYrD4WC24LWtPrJlGy87y5udK+dxQ==", + "dev": true, + "requires": { + "camelcase": "^5.0.0", + "decamelize": "^1.2.0" + } + } + } + }, + "yargs-parser": { + "version": "10.1.0", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-10.1.0.tgz", + "integrity": "sha512-VCIyR1wJoEBZUqk5PA+oOBF6ypbwh5aNB3I50guxAL/quggdfs4TtNHQrSazFA3fYZ+tEqfs0zIGlv0c/rgjbQ==", + "dev": true, + "requires": { + "camelcase": "^4.1.0" + } + } + } +} diff --git a/package.json b/package.json index e1e114c9..3acb3b42 100644 --- a/package.json +++ b/package.json @@ -25,23 +25,23 @@ "dependencies": { "erlang-types": "^1.0.1", "grapheme-splitter": "^1.0.2", - "rollup-plugin-commonjs": "^8.2.1", + "rollup-plugin-commonjs": "^10.0.2", "tailored": "^2.7.4" }, "devDependencies": { "@std/esm": "^0.8.3", - "ava": "^0.22.0", + "ava": "^2.3.0", "babel-core": "^6.26.0", "babel-preset-env": "^1.6.0", "babel-register": "^6.26.0", - "eslint": "^4.6.1", - "eslint-config-airbnb-base": "^12.0.0", + "eslint": "^6.2.1", + "eslint-config-airbnb-base": "^14.0.0", "eslint-plugin-import": "^2.7.0", - "nyc": "^11.2.1", - "rollup": "^0.49.3", - "rollup-plugin-babel": "^3.0.2", - "rollup-plugin-babel-minify": "^3.1.2", - "rollup-plugin-node-resolve": "^3.0.0" + "nyc": "^14.1.1", + "rollup": "^1.19.4", + "rollup-plugin-babel": "^4.3.3", + "rollup-plugin-babel-minify": "^9.0.0", + "rollup-plugin-node-resolve": "^5.2.0" }, "ava": { "require": [ diff --git a/priv/testrunner/esm/index.js b/priv/testrunner/esm/index.js index 7f6018cd..5eb27ed1 100644 --- a/priv/testrunner/esm/index.js +++ b/priv/testrunner/esm/index.js @@ -1,49 +1,48 @@ /* eslint strict: off, node/no-unsupported-features: ["error", { version: 4 }] */ -"use strict" -const fs = require("fs") -const path = require("path") -const util = require("util") -const vm = require("vm") -const zlib = require("zlib") +'use strict'; -const esmPath = path.resolve(__dirname, "esm.js.gz") -const inspectKey = util.inspect.custom || "inspect" +const fs = require('fs'); +const path = require('path'); +const util = require('util'); +const vm = require('vm'); +const zlib = require('zlib'); -const descriptor = Object.create(null) -descriptor.value = () => "@std/esm enabled" +const esmPath = path.resolve(__dirname, 'esm.js.gz'); +const inspectKey = util.inspect.custom || 'inspect'; -const mod = new module.constructor(module.id) -mod.filename = __filename -mod.parent = module.parent +const descriptor = Object.create(null); +descriptor.value = () => '@std/esm enabled'; -const scriptOptions = Object.create(null) -scriptOptions.filename = __filename +const mod = new module.constructor(module.id); +mod.filename = __filename; +mod.parent = module.parent; + +const scriptOptions = Object.create(null); +scriptOptions.filename = __filename; const content = - "(function(require,module,__filename){" + - zlib.gunzipSync(fs.readFileSync(esmPath)).toString() + - "\n})" + `(function(require,module,__filename){${ + zlib.gunzipSync(fs.readFileSync(esmPath)).toString() + }\n})`; -const compiled = vm.runInThisContext(content, scriptOptions) +const compiled = vm.runInThisContext(content, scriptOptions); function makeLoaderFunction() { - compiled(require, mod, __filename) - return mod.exports + compiled(require, mod, __filename); + return mod.exports; } -const loader = makeLoaderFunction() +const loader = makeLoaderFunction(); module.exports = (mod, options) => { - const type = typeof options + const type = typeof options; - if (options === true || - type === "function" || - (type === "object" && options !== null)) { - return makeLoaderFunction()(mod, options) + if (options === true || type === 'function' || (type === 'object' && options !== null)) { + return makeLoaderFunction()(mod, options); } - return loader(mod, options) -} + return loader(mod, options); +}; -Object.freeze(Object.defineProperty(module.exports, inspectKey, descriptor)) +Object.freeze(Object.defineProperty(module.exports, inspectKey, descriptor)); diff --git a/priv/testrunner/vendor.build.js b/priv/testrunner/vendor.build.js index 9d49e34d..f83931bf 100644 --- a/priv/testrunner/vendor.build.js +++ b/priv/testrunner/vendor.build.js @@ -1,2 +1,2 @@ -class Tuple{constructor(...a){this.values=Object.freeze(a),this.length=this.values.length}get(a){return this.values[a]}count(){return this.values.length}[Symbol.iterator](){return this.values[Symbol.iterator]()}toString(){let a,b='';for(a=0;a'}}let ref_counter=-1;class Reference{constructor(){++ref_counter,this.id=ref_counter,this.ref=Symbol()}toString(){return'Ref#<0.0.0.'+this.id+'>'}}class BitString{constructor(...a){this.value=Object.freeze(this.process(a)),this.length=this.value.length,this.bit_size=8*this.length,this.byte_size=this.length}get(a){return this.value[a]}count(){return this.value.length}slice(a,b=null){let c=this.value.slice(a,b),d=c.map((a)=>BitString.integer(a));return new BitString(...d)}[Symbol.iterator](){return this.value[Symbol.iterator]()}toString(){var a,b='';for(a=0;a>'}process(a){let b=[];var c;for(c=0;cb?c.push(b):2048>b?c.push(192|b>>6,128|63&b):55296>b||57344<=b?c.push(224|b>>12,128|63&b>>6,128|63&b):(d++,b=65536+((1023&b)<<10|1023&a.charCodeAt(d)),c.push(240|b>>18,128|63&b>>12,128|63&b>>6,128|63&b));return c}static toUTF16Array(a){for(var b,c=[],d=0;d=b?(c.push(0),c.push(b)):(c.push(255&b>>8),c.push(255&b));return c}static toUTF32Array(a){for(var b,c=[],d=0;d=b?(c.push(0),c.push(0),c.push(0),c.push(b)):(c.push(0),c.push(0),c.push(255&b>>8),c.push(255&b));return c}//http://stackoverflow.com/questions/2003493/javascript-float-from-to-bits -static float32ToBytes(a){var b=[],c=new ArrayBuffer(4);new Float32Array(c)[0]=a;let d=new Uint32Array(c)[0];return b.push(255&d>>24),b.push(255&d>>16),b.push(255&d>>8),b.push(255&d),b}static float64ToBytes(a){var b=[],c=new ArrayBuffer(8);new Float64Array(c)[0]=a;var d=new Uint32Array(c)[0],e=new Uint32Array(c)[1];return b.push(255&e>>24),b.push(255&e>>16),b.push(255&e>>8),b.push(255&e),b.push(255&d>>24),b.push(255&d>>16),b.push(255&d>>8),b.push(255&d),b}}var ErlangTypes={Tuple,PID,Reference,BitString},vendor={ErlangTypes};export default vendor; +function unwrapExports(a){return a&&a.__esModule&&Object.prototype.hasOwnProperty.call(a,"default")?a["default"]:a}function createCommonjsModule(a,b){return b={exports:{}},a(b,b.exports),b.exports}var tuple=createCommonjsModule(function(a,b){Object.defineProperty(b,"__esModule",{value:!0});class Tuple{constructor(...a){this.values=Object.freeze(a),this.length=this.values.length}get(a){return this.values[a]}count(){return this.values.length}[Symbol.iterator](){return this.values[Symbol.iterator]()}toString(){let a,b="";for(a=0;a"}}});unwrapExports(pid);var pid_1=pid.PID,reference=createCommonjsModule(function(a,b){Object.defineProperty(b,"__esModule",{value:!0});let c=-1;b.Reference=class Reference{constructor(){++c,this.id=c,this.ref=Symbol()}toString(){return"Ref#<0.0.0."+this.id+">"}}});unwrapExports(reference);var reference_1=reference.Reference,bit_string=createCommonjsModule(function(a,b){Object.defineProperty(b,"__esModule",{value:!0});class BitString{constructor(...a){this.value=Object.freeze(this.process(a)),this.length=this.value.length,this.bit_size=8*this.length,this.byte_size=this.length}get(a){return this.value[a]}count(){return this.value.length}slice(a,b=void 0){let c=this.value.slice(a,b),d=c.map(a=>BitString.integer(a));return new BitString(...d)}[Symbol.iterator](){return this.value[Symbol.iterator]()}toString(){var a,b="";for(a=0;a>"}process(a){let b=[];var c;for(c=0;cb?c.push(b):2048>b?c.push(192|b>>6,128|63&b):55296>b||57344<=b?c.push(224|b>>12,128|63&b>>6,128|63&b):(d++,b=65536+((1023&b)<<10|1023&a.charCodeAt(d)),c.push(240|b>>18,128|63&b>>12,128|63&b>>6,128|63&b));return c}static toUTF16Array(a){for(var b,c=[],d=0;d=b?(c.push(0),c.push(b)):(c.push(255&b>>8),c.push(255&b)));return c}static toUTF32Array(a){for(var b,c=[],d=0;d=b?(c.push(0),c.push(0),c.push(0),c.push(b)):(c.push(0),c.push(0),c.push(255&b>>8),c.push(255&b)));return c}//http://stackoverflow.com/questions/2003493/javascript-float-from-to-bits +static float32ToBytes(a){var b=[],c=new ArrayBuffer(4);new Float32Array(c)[0]=a;let d=new Uint32Array(c)[0];return b.push(255&d>>24),b.push(255&d>>16),b.push(255&d>>8),b.push(255&d),b}static float64ToBytes(a){var b=[],c=new ArrayBuffer(8);new Float64Array(c)[0]=a;var d=new Uint32Array(c)[0],e=new Uint32Array(c)[1];return b.push(255&e>>24),b.push(255&e>>16),b.push(255&e>>8),b.push(255&e),b.push(255&d>>24),b.push(255&d>>16),b.push(255&d>>8),b.push(255&d),b}}b.BitString=BitString});unwrapExports(bit_string);var bit_string_1=bit_string.BitString,lib=createCommonjsModule(function(a,b){Object.defineProperty(b,"__esModule",{value:!0}),b.Tuple=tuple.Tuple,b.PID=pid.PID,b.Reference=reference.Reference,b.BitString=bit_string.BitString}),ErlangTypes=unwrapExports(lib),lib_1=lib.Tuple,lib_2=lib.PID,lib_3=lib.Reference,lib_4=lib.BitString,vendor={ErlangTypes};export default vendor; diff --git a/rollup.config.js b/rollup.config.js index 58a95b70..dbdce767 100644 --- a/rollup.config.js +++ b/rollup.config.js @@ -1,13 +1,12 @@ -const rollup = require('rollup'); -const babel = require('rollup-plugin-babel'); -const nodeResolve = require('rollup-plugin-node-resolve'); -const commonjs = require('rollup-plugin-commonjs'); -const minify = require('rollup-plugin-babel-minify'); +const rollup = require('rollup') +const babel = require('rollup-plugin-babel') +const nodeResolve = require('rollup-plugin-node-resolve') +const commonjs = require('rollup-plugin-commonjs') +const minify = require('rollup-plugin-babel-minify') const plugins = [ nodeResolve({ - jsnext: true, - main: true, + mainFields: ['jsnext', 'main'], }), commonjs(), babel({ @@ -17,33 +16,37 @@ const plugins = [ keepFnName: true, keepClassName: true, }), -]; +] rollup .rollup({ input: 'src/javascript/elixir.js', - output: 'priv/build/es/ElixirScript.Core.js', - sourcemap: 'inline', - format: 'es', + output: { + file: 'priv/build/es/ElixirScript.Core.js', + format: 'es', + }, plugins, }) - .then((bundle) => { + .then(bundle => { bundle.write({ format: 'es', file: 'priv/build/es/ElixirScript.Core.js', - }); - }); + sourcemap: 'inline', + }) + }) rollup .rollup({ input: 'priv/testrunner/vendor.js', - output: 'priv/testrunner/vendor.build.js', - format: 'es', + output: { + file: 'priv/testrunner/vendor.build.js', + format: 'es', + }, plugins, }) - .then((bundle) => { + .then(bundle => { bundle.write({ format: 'es', file: 'priv/testrunner/vendor.build.js', - }); - }); + }) + }) diff --git a/yarn.lock b/yarn.lock deleted file mode 100644 index 2772e27d..00000000 --- a/yarn.lock +++ /dev/null @@ -1,4242 +0,0 @@ -# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. -# yarn lockfile v1 - - -"@ava/babel-plugin-throws-helper@^2.0.0": - version "2.0.0" - resolved "https://registry.yarnpkg.com/@ava/babel-plugin-throws-helper/-/babel-plugin-throws-helper-2.0.0.tgz#2fc1fe3c211a71071a4eca7b8f7af5842cd1ae7c" - -"@ava/babel-preset-stage-4@^1.1.0": - version "1.1.0" - resolved "https://registry.yarnpkg.com/@ava/babel-preset-stage-4/-/babel-preset-stage-4-1.1.0.tgz#ae60be881a0babf7d35f52aba770d1f6194f76bd" - dependencies: - babel-plugin-check-es2015-constants "^6.8.0" - babel-plugin-syntax-trailing-function-commas "^6.20.0" - babel-plugin-transform-async-to-generator "^6.16.0" - babel-plugin-transform-es2015-destructuring "^6.19.0" - babel-plugin-transform-es2015-function-name "^6.9.0" - babel-plugin-transform-es2015-modules-commonjs "^6.18.0" - babel-plugin-transform-es2015-parameters "^6.21.0" - babel-plugin-transform-es2015-spread "^6.8.0" - babel-plugin-transform-es2015-sticky-regex "^6.8.0" - babel-plugin-transform-es2015-unicode-regex "^6.11.0" - babel-plugin-transform-exponentiation-operator "^6.8.0" - package-hash "^1.2.0" - -"@ava/babel-preset-transform-test-files@^3.0.0": - version "3.0.0" - resolved "https://registry.yarnpkg.com/@ava/babel-preset-transform-test-files/-/babel-preset-transform-test-files-3.0.0.tgz#cded1196a8d8d9381a509240ab92e91a5ec069f7" - dependencies: - "@ava/babel-plugin-throws-helper" "^2.0.0" - babel-plugin-espower "^2.3.2" - -"@ava/write-file-atomic@^2.2.0": - version "2.2.0" - resolved "https://registry.yarnpkg.com/@ava/write-file-atomic/-/write-file-atomic-2.2.0.tgz#d625046f3495f1f5e372135f473909684b429247" - dependencies: - graceful-fs "^4.1.11" - imurmurhash "^0.1.4" - slide "^1.1.5" - -"@comandeer/babel-plugin-banner@^1.0.0": - version "1.0.0" - resolved "https://registry.yarnpkg.com/@comandeer/babel-plugin-banner/-/babel-plugin-banner-1.0.0.tgz#40bcce0bbee084b5b02545a33635d053c248356f" - -"@concordance/react@^1.0.0": - version "1.0.0" - resolved "https://registry.yarnpkg.com/@concordance/react/-/react-1.0.0.tgz#fcf3cad020e5121bfd1c61d05bc3516aac25f734" - dependencies: - arrify "^1.0.1" - -"@std/esm@^0.8.3": - version "0.8.3" - resolved "https://registry.yarnpkg.com/@std/esm/-/esm-0.8.3.tgz#7a3c3144ca0905c9b92d82b79987503ecb58a193" - -abbrev@1: - version "1.1.0" - resolved "https://registry.yarnpkg.com/abbrev/-/abbrev-1.1.0.tgz#d0554c2256636e2f56e7c2e5ad183f859428d81f" - -acorn-jsx@^3.0.0: - version "3.0.1" - resolved "https://registry.yarnpkg.com/acorn-jsx/-/acorn-jsx-3.0.1.tgz#afdf9488fb1ecefc8348f6fb22f464e32a58b36b" - dependencies: - acorn "^3.0.4" - -acorn@^3.0.4: - version "3.3.0" - resolved "https://registry.yarnpkg.com/acorn/-/acorn-3.3.0.tgz#45e37fb39e8da3f25baee3ff5369e2bb5f22017a" - -acorn@^5.1.1: - version "5.1.2" - resolved "https://registry.yarnpkg.com/acorn/-/acorn-5.1.2.tgz#911cb53e036807cf0fa778dc5d370fbd864246d7" - -acorn@^5.5.0: - version "5.7.3" - resolved "https://registry.yarnpkg.com/acorn/-/acorn-5.7.3.tgz#67aa231bf8812974b85235a96771eb6bd07ea279" - -ajv-keywords@^2.1.0: - version "2.1.1" - resolved "https://registry.yarnpkg.com/ajv-keywords/-/ajv-keywords-2.1.1.tgz#617997fc5f60576894c435f940d819e135b80762" - -ajv@^4.9.1: - version "4.11.8" - resolved "https://registry.yarnpkg.com/ajv/-/ajv-4.11.8.tgz#82ffb02b29e662ae53bdc20af15947706739c536" - dependencies: - co "^4.6.0" - json-stable-stringify "^1.0.1" - -ajv@^5.2.3, ajv@^5.3.0: - version "5.5.2" - resolved "https://registry.yarnpkg.com/ajv/-/ajv-5.5.2.tgz#73b5eeca3fab653e3d3f9422b341ad42205dc965" - dependencies: - co "^4.6.0" - fast-deep-equal "^1.0.0" - fast-json-stable-stringify "^2.0.0" - json-schema-traverse "^0.3.0" - -align-text@^0.1.1, align-text@^0.1.3: - version "0.1.4" - resolved "https://registry.yarnpkg.com/align-text/-/align-text-0.1.4.tgz#0cd90a561093f35d0a99256c22b7069433fad117" - dependencies: - kind-of "^3.0.2" - longest "^1.0.1" - repeat-string "^1.5.2" - -amdefine@>=0.0.4: - version "1.0.1" - resolved "https://registry.yarnpkg.com/amdefine/-/amdefine-1.0.1.tgz#4a5282ac164729e93619bcfd3ad151f817ce91f5" - -ansi-align@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/ansi-align/-/ansi-align-2.0.0.tgz#c36aeccba563b89ceb556f3690f0b1d9e3547f7f" - dependencies: - string-width "^2.0.0" - -ansi-escapes@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/ansi-escapes/-/ansi-escapes-2.0.0.tgz#5bae52be424878dd9783e8910e3fc2922e83c81b" - -ansi-regex@^2.0.0: - version "2.1.1" - resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-2.1.1.tgz#c3b33ab5ee360d86e0e628f0468ae7ef27d654df" - -ansi-regex@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-3.0.0.tgz#ed0317c322064f79466c02966bddb605ab37d998" - -ansi-styles@^2.2.1: - version "2.2.1" - resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-2.2.1.tgz#b432dd3358b634cf75e1e4664368240533c1ddbe" - -ansi-styles@^3.1.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-3.1.0.tgz#09c202d5c917ec23188caa5c9cb9179cd9547750" - dependencies: - color-convert "^1.0.0" - -ansi-styles@~1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-1.0.0.tgz#cb102df1c56f5123eab8b67cd7b98027a0279178" - -anymatch@^1.3.0: - version "1.3.0" - resolved "https://registry.yarnpkg.com/anymatch/-/anymatch-1.3.0.tgz#a3e52fa39168c825ff57b0248126ce5a8ff95507" - dependencies: - arrify "^1.0.0" - micromatch "^2.1.5" - -append-transform@^0.4.0: - version "0.4.0" - resolved "https://registry.yarnpkg.com/append-transform/-/append-transform-0.4.0.tgz#d76ebf8ca94d276e247a36bad44a4b74ab611991" - dependencies: - default-require-extensions "^1.0.0" - -aproba@^1.0.3: - version "1.1.2" - resolved "https://registry.yarnpkg.com/aproba/-/aproba-1.1.2.tgz#45c6629094de4e96f693ef7eab74ae079c240fc1" - -archy@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/archy/-/archy-1.0.0.tgz#f9c8c13757cc1dd7bc379ac77b2c62a5c2868c40" - -are-we-there-yet@~1.1.2: - version "1.1.4" - resolved "https://registry.yarnpkg.com/are-we-there-yet/-/are-we-there-yet-1.1.4.tgz#bb5dca382bb94f05e15194373d16fd3ba1ca110d" - dependencies: - delegates "^1.0.0" - readable-stream "^2.0.6" - -argparse@^1.0.7: - version "1.0.9" - resolved "https://registry.yarnpkg.com/argparse/-/argparse-1.0.9.tgz#73d83bc263f86e97f8cc4f6bae1b0e90a7d22c86" - dependencies: - sprintf-js "~1.0.2" - -arr-diff@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/arr-diff/-/arr-diff-2.0.0.tgz#8f3b827f955a8bd669697e4a4256ac3ceae356cf" - dependencies: - arr-flatten "^1.0.1" - -arr-exclude@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/arr-exclude/-/arr-exclude-1.0.0.tgz#dfc7c2e552a270723ccda04cf3128c8cbfe5c631" - -arr-flatten@^1.0.1: - version "1.0.3" - resolved "https://registry.yarnpkg.com/arr-flatten/-/arr-flatten-1.0.3.tgz#a274ed85ac08849b6bd7847c4580745dc51adfb1" - -array-differ@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/array-differ/-/array-differ-1.0.0.tgz#eff52e3758249d33be402b8bb8e564bb2b5d4031" - -array-find-index@^1.0.1: - version "1.0.2" - resolved "https://registry.yarnpkg.com/array-find-index/-/array-find-index-1.0.2.tgz#df010aa1287e164bbda6f9723b0a96a1ec4187a1" - -array-union@^1.0.1: - version "1.0.2" - resolved "https://registry.yarnpkg.com/array-union/-/array-union-1.0.2.tgz#9a34410e4f4e3da23dea375be5be70f24778ec39" - dependencies: - array-uniq "^1.0.1" - -array-uniq@^1.0.1, array-uniq@^1.0.2: - version "1.0.3" - resolved "https://registry.yarnpkg.com/array-uniq/-/array-uniq-1.0.3.tgz#af6ac877a25cc7f74e058894753858dfdb24fdb6" - -array-unique@^0.2.1: - version "0.2.1" - resolved "https://registry.yarnpkg.com/array-unique/-/array-unique-0.2.1.tgz#a1d97ccafcbc2625cc70fadceb36a50c58b01a53" - -arrify@^1.0.0, arrify@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/arrify/-/arrify-1.0.1.tgz#898508da2226f380df904728456849c1501a4b0d" - -asn1@~0.2.3: - version "0.2.4" - resolved "https://registry.yarnpkg.com/asn1/-/asn1-0.2.4.tgz#8d2475dfab553bb33e77b54e59e880bb8ce23136" - dependencies: - safer-buffer "~2.1.0" - -assert-plus@1.0.0, assert-plus@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/assert-plus/-/assert-plus-1.0.0.tgz#f12e0f3c5d77b0b1cdd9146942e4e96c1e4dd525" - -assert-plus@^0.2.0: - version "0.2.0" - resolved "https://registry.yarnpkg.com/assert-plus/-/assert-plus-0.2.0.tgz#d74e1b87e7affc0db8aadb7021f3fe48101ab234" - -async-each@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/async-each/-/async-each-1.0.1.tgz#19d386a1d9edc6e7c1c85d388aedbcc56d33602d" - -async@^1.4.0: - version "1.5.2" - resolved "https://registry.yarnpkg.com/async/-/async-1.5.2.tgz#ec6a61ae56480c0c3cb241c95618e20892f9672a" - -asynckit@^0.4.0: - version "0.4.0" - resolved "https://registry.yarnpkg.com/asynckit/-/asynckit-0.4.0.tgz#c79ed97f7f34cb8f2ba1bc9790bcc366474b4b79" - -auto-bind@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/auto-bind/-/auto-bind-1.1.0.tgz#93b864dc7ee01a326281775d5c75ca0a751e5961" - -ava-init@^0.2.0: - version "0.2.0" - resolved "https://registry.yarnpkg.com/ava-init/-/ava-init-0.2.0.tgz#9304c8b4c357d66e3dfdae1fbff47b1199d5c55d" - dependencies: - arr-exclude "^1.0.0" - execa "^0.5.0" - has-yarn "^1.0.0" - read-pkg-up "^2.0.0" - write-pkg "^2.0.0" - -ava@^0.22.0: - version "0.22.0" - resolved "https://registry.yarnpkg.com/ava/-/ava-0.22.0.tgz#4c28a1fdef7e749ba0c8131ac18a7ca489eef049" - dependencies: - "@ava/babel-preset-stage-4" "^1.1.0" - "@ava/babel-preset-transform-test-files" "^3.0.0" - "@ava/write-file-atomic" "^2.2.0" - "@concordance/react" "^1.0.0" - ansi-escapes "^2.0.0" - ansi-styles "^3.1.0" - arr-flatten "^1.0.1" - array-union "^1.0.1" - array-uniq "^1.0.2" - arrify "^1.0.0" - auto-bind "^1.1.0" - ava-init "^0.2.0" - babel-core "^6.17.0" - bluebird "^3.0.0" - caching-transform "^1.0.0" - chalk "^2.0.1" - chokidar "^1.4.2" - clean-stack "^1.1.1" - clean-yaml-object "^0.1.0" - cli-cursor "^2.1.0" - cli-spinners "^1.0.0" - cli-truncate "^1.0.0" - co-with-promise "^4.6.0" - code-excerpt "^2.1.0" - common-path-prefix "^1.0.0" - concordance "^3.0.0" - convert-source-map "^1.2.0" - core-assert "^0.2.0" - currently-unhandled "^0.4.1" - debug "^2.2.0" - dot-prop "^4.1.0" - empower-core "^0.6.1" - equal-length "^1.0.0" - figures "^2.0.0" - find-cache-dir "^1.0.0" - fn-name "^2.0.0" - get-port "^3.0.0" - globby "^6.0.0" - has-flag "^2.0.0" - hullabaloo-config-manager "^1.1.0" - ignore-by-default "^1.0.0" - import-local "^0.1.1" - indent-string "^3.0.0" - is-ci "^1.0.7" - is-generator-fn "^1.0.0" - is-obj "^1.0.0" - is-observable "^0.2.0" - is-promise "^2.1.0" - js-yaml "^3.8.2" - last-line-stream "^1.0.0" - lodash.clonedeepwith "^4.5.0" - lodash.debounce "^4.0.3" - lodash.difference "^4.3.0" - lodash.flatten "^4.2.0" - loud-rejection "^1.2.0" - make-dir "^1.0.0" - matcher "^1.0.0" - md5-hex "^2.0.0" - meow "^3.7.0" - ms "^2.0.0" - multimatch "^2.1.0" - observable-to-promise "^0.5.0" - option-chain "^1.0.0" - package-hash "^2.0.0" - pkg-conf "^2.0.0" - plur "^2.0.0" - pretty-ms "^2.0.0" - require-precompiled "^0.1.0" - resolve-cwd "^2.0.0" - safe-buffer "^5.1.1" - slash "^1.0.0" - source-map-support "^0.4.0" - stack-utils "^1.0.0" - strip-ansi "^4.0.0" - strip-bom-buf "^1.0.0" - supports-color "^4.0.0" - time-require "^0.1.2" - trim-off-newlines "^1.0.1" - unique-temp-dir "^1.0.0" - update-notifier "^2.1.0" - -aws-sign2@~0.6.0: - version "0.6.0" - resolved "https://registry.yarnpkg.com/aws-sign2/-/aws-sign2-0.6.0.tgz#14342dd38dbcc94d0e5b87d763cd63612c0e794f" - -aws4@^1.2.1: - version "1.6.0" - resolved "https://registry.yarnpkg.com/aws4/-/aws4-1.6.0.tgz#83ef5ca860b2b32e4a0deedee8c771b9db57471e" - -babel-code-frame@^6.22.0, babel-code-frame@^6.26.0: - version "6.26.0" - resolved "https://registry.yarnpkg.com/babel-code-frame/-/babel-code-frame-6.26.0.tgz#63fd43f7dc1e3bb7ce35947db8fe369a3f58c74b" - dependencies: - chalk "^1.1.3" - esutils "^2.0.2" - js-tokens "^3.0.2" - -babel-core@^6.17.0, babel-core@^6.21.0, babel-core@^6.24.1: - version "6.25.0" - resolved "https://registry.yarnpkg.com/babel-core/-/babel-core-6.25.0.tgz#7dd42b0463c742e9d5296deb3ec67a9322dad729" - dependencies: - babel-code-frame "^6.22.0" - babel-generator "^6.25.0" - babel-helpers "^6.24.1" - babel-messages "^6.23.0" - babel-register "^6.24.1" - babel-runtime "^6.22.0" - babel-template "^6.25.0" - babel-traverse "^6.25.0" - babel-types "^6.25.0" - babylon "^6.17.2" - convert-source-map "^1.1.0" - debug "^2.1.1" - json5 "^0.5.0" - lodash "^4.2.0" - minimatch "^3.0.2" - path-is-absolute "^1.0.0" - private "^0.1.6" - slash "^1.0.0" - source-map "^0.5.0" - -babel-core@^6.26.0: - version "6.26.0" - resolved "https://registry.yarnpkg.com/babel-core/-/babel-core-6.26.0.tgz#af32f78b31a6fcef119c87b0fd8d9753f03a0bb8" - dependencies: - babel-code-frame "^6.26.0" - babel-generator "^6.26.0" - babel-helpers "^6.24.1" - babel-messages "^6.23.0" - babel-register "^6.26.0" - babel-runtime "^6.26.0" - babel-template "^6.26.0" - babel-traverse "^6.26.0" - babel-types "^6.26.0" - babylon "^6.18.0" - convert-source-map "^1.5.0" - debug "^2.6.8" - json5 "^0.5.1" - lodash "^4.17.4" - minimatch "^3.0.4" - path-is-absolute "^1.0.1" - private "^0.1.7" - slash "^1.0.0" - source-map "^0.5.6" - -babel-generator@^6.1.0, babel-generator@^6.18.0, babel-generator@^6.25.0: - version "6.25.0" - resolved "https://registry.yarnpkg.com/babel-generator/-/babel-generator-6.25.0.tgz#33a1af70d5f2890aeb465a4a7793c1df6a9ea9fc" - dependencies: - babel-messages "^6.23.0" - babel-runtime "^6.22.0" - babel-types "^6.25.0" - detect-indent "^4.0.0" - jsesc "^1.3.0" - lodash "^4.2.0" - source-map "^0.5.0" - trim-right "^1.0.1" - -babel-generator@^6.26.0: - version "6.26.0" - resolved "https://registry.yarnpkg.com/babel-generator/-/babel-generator-6.26.0.tgz#ac1ae20070b79f6e3ca1d3269613053774f20dc5" - dependencies: - babel-messages "^6.23.0" - babel-runtime "^6.26.0" - babel-types "^6.26.0" - detect-indent "^4.0.0" - jsesc "^1.3.0" - lodash "^4.17.4" - source-map "^0.5.6" - trim-right "^1.0.1" - -babel-helper-builder-binary-assignment-operator-visitor@^6.24.1: - version "6.24.1" - resolved "https://registry.yarnpkg.com/babel-helper-builder-binary-assignment-operator-visitor/-/babel-helper-builder-binary-assignment-operator-visitor-6.24.1.tgz#cce4517ada356f4220bcae8a02c2b346f9a56664" - dependencies: - babel-helper-explode-assignable-expression "^6.24.1" - babel-runtime "^6.22.0" - babel-types "^6.24.1" - -babel-helper-call-delegate@^6.24.1: - version "6.24.1" - resolved "https://registry.yarnpkg.com/babel-helper-call-delegate/-/babel-helper-call-delegate-6.24.1.tgz#ece6aacddc76e41c3461f88bfc575bd0daa2df8d" - dependencies: - babel-helper-hoist-variables "^6.24.1" - babel-runtime "^6.22.0" - babel-traverse "^6.24.1" - babel-types "^6.24.1" - -babel-helper-define-map@^6.24.1: - version "6.24.1" - resolved "https://registry.yarnpkg.com/babel-helper-define-map/-/babel-helper-define-map-6.24.1.tgz#7a9747f258d8947d32d515f6aa1c7bd02204a080" - dependencies: - babel-helper-function-name "^6.24.1" - babel-runtime "^6.22.0" - babel-types "^6.24.1" - lodash "^4.2.0" - -babel-helper-evaluate-path@^0.2.0: - version "0.2.0" - resolved "https://registry.yarnpkg.com/babel-helper-evaluate-path/-/babel-helper-evaluate-path-0.2.0.tgz#0bb2eb01996c0cef53c5e8405e999fe4a0244c08" - -babel-helper-explode-assignable-expression@^6.24.1: - version "6.24.1" - resolved "https://registry.yarnpkg.com/babel-helper-explode-assignable-expression/-/babel-helper-explode-assignable-expression-6.24.1.tgz#f25b82cf7dc10433c55f70592d5746400ac22caa" - dependencies: - babel-runtime "^6.22.0" - babel-traverse "^6.24.1" - babel-types "^6.24.1" - -babel-helper-flip-expressions@^0.2.0: - version "0.2.0" - resolved "https://registry.yarnpkg.com/babel-helper-flip-expressions/-/babel-helper-flip-expressions-0.2.0.tgz#160d2090a3d9f9c64a750905321a0bc218f884ec" - -babel-helper-function-name@^6.24.1: - version "6.24.1" - resolved "https://registry.yarnpkg.com/babel-helper-function-name/-/babel-helper-function-name-6.24.1.tgz#d3475b8c03ed98242a25b48351ab18399d3580a9" - dependencies: - babel-helper-get-function-arity "^6.24.1" - babel-runtime "^6.22.0" - babel-template "^6.24.1" - babel-traverse "^6.24.1" - babel-types "^6.24.1" - -babel-helper-get-function-arity@^6.24.1: - version "6.24.1" - resolved "https://registry.yarnpkg.com/babel-helper-get-function-arity/-/babel-helper-get-function-arity-6.24.1.tgz#8f7782aa93407c41d3aa50908f89b031b1b6853d" - dependencies: - babel-runtime "^6.22.0" - babel-types "^6.24.1" - -babel-helper-hoist-variables@^6.24.1: - version "6.24.1" - resolved "https://registry.yarnpkg.com/babel-helper-hoist-variables/-/babel-helper-hoist-variables-6.24.1.tgz#1ecb27689c9d25513eadbc9914a73f5408be7a76" - dependencies: - babel-runtime "^6.22.0" - babel-types "^6.24.1" - -babel-helper-is-nodes-equiv@^0.0.1: - version "0.0.1" - resolved "https://registry.yarnpkg.com/babel-helper-is-nodes-equiv/-/babel-helper-is-nodes-equiv-0.0.1.tgz#34e9b300b1479ddd98ec77ea0bbe9342dfe39684" - -babel-helper-is-void-0@^0.2.0: - version "0.2.0" - resolved "https://registry.yarnpkg.com/babel-helper-is-void-0/-/babel-helper-is-void-0-0.2.0.tgz#6ed0ada8a9b1c5b6e88af6b47c1b3b5c080860eb" - -babel-helper-mark-eval-scopes@^0.2.0: - version "0.2.0" - resolved "https://registry.yarnpkg.com/babel-helper-mark-eval-scopes/-/babel-helper-mark-eval-scopes-0.2.0.tgz#7648aaf2ec92aae9b09a20ad91e8df5e1fcc94b2" - -babel-helper-optimise-call-expression@^6.24.1: - version "6.24.1" - resolved "https://registry.yarnpkg.com/babel-helper-optimise-call-expression/-/babel-helper-optimise-call-expression-6.24.1.tgz#f7a13427ba9f73f8f4fa993c54a97882d1244257" - dependencies: - babel-runtime "^6.22.0" - babel-types "^6.24.1" - -babel-helper-regex@^6.24.1: - version "6.24.1" - resolved "https://registry.yarnpkg.com/babel-helper-regex/-/babel-helper-regex-6.24.1.tgz#d36e22fab1008d79d88648e32116868128456ce8" - dependencies: - babel-runtime "^6.22.0" - babel-types "^6.24.1" - lodash "^4.2.0" - -babel-helper-remap-async-to-generator@^6.24.1: - version "6.24.1" - resolved "https://registry.yarnpkg.com/babel-helper-remap-async-to-generator/-/babel-helper-remap-async-to-generator-6.24.1.tgz#5ec581827ad723fecdd381f1c928390676e4551b" - dependencies: - babel-helper-function-name "^6.24.1" - babel-runtime "^6.22.0" - babel-template "^6.24.1" - babel-traverse "^6.24.1" - babel-types "^6.24.1" - -babel-helper-remove-or-void@^0.2.0: - version "0.2.0" - resolved "https://registry.yarnpkg.com/babel-helper-remove-or-void/-/babel-helper-remove-or-void-0.2.0.tgz#8e46ad5b30560d57d7510b3fd93f332ee7c67386" - -babel-helper-replace-supers@^6.24.1: - version "6.24.1" - resolved "https://registry.yarnpkg.com/babel-helper-replace-supers/-/babel-helper-replace-supers-6.24.1.tgz#bf6dbfe43938d17369a213ca8a8bf74b6a90ab1a" - dependencies: - babel-helper-optimise-call-expression "^6.24.1" - babel-messages "^6.23.0" - babel-runtime "^6.22.0" - babel-template "^6.24.1" - babel-traverse "^6.24.1" - babel-types "^6.24.1" - -babel-helper-to-multiple-sequence-expressions@^0.2.0: - version "0.2.0" - resolved "https://registry.yarnpkg.com/babel-helper-to-multiple-sequence-expressions/-/babel-helper-to-multiple-sequence-expressions-0.2.0.tgz#d1a419634c6cb301f27858c659167cfee0a9d318" - -babel-helpers@^6.24.1: - version "6.24.1" - resolved "https://registry.yarnpkg.com/babel-helpers/-/babel-helpers-6.24.1.tgz#3471de9caec388e5c850e597e58a26ddf37602b2" - dependencies: - babel-runtime "^6.22.0" - babel-template "^6.24.1" - -babel-messages@^6.23.0: - version "6.23.0" - resolved "https://registry.yarnpkg.com/babel-messages/-/babel-messages-6.23.0.tgz#f3cdf4703858035b2a2951c6ec5edf6c62f2630e" - dependencies: - babel-runtime "^6.22.0" - -babel-plugin-check-es2015-constants@^6.22.0, babel-plugin-check-es2015-constants@^6.8.0: - version "6.22.0" - resolved "https://registry.yarnpkg.com/babel-plugin-check-es2015-constants/-/babel-plugin-check-es2015-constants-6.22.0.tgz#35157b101426fd2ffd3da3f75c7d1e91835bbf8a" - dependencies: - babel-runtime "^6.22.0" - -babel-plugin-espower@^2.3.2: - version "2.3.2" - resolved "https://registry.yarnpkg.com/babel-plugin-espower/-/babel-plugin-espower-2.3.2.tgz#5516b8fcdb26c9f0e1d8160749f6e4c65e71271e" - dependencies: - babel-generator "^6.1.0" - babylon "^6.1.0" - call-matcher "^1.0.0" - core-js "^2.0.0" - espower-location-detector "^1.0.0" - espurify "^1.6.0" - estraverse "^4.1.1" - -babel-plugin-minify-builtins@^0.2.0: - version "0.2.0" - resolved "https://registry.yarnpkg.com/babel-plugin-minify-builtins/-/babel-plugin-minify-builtins-0.2.0.tgz#317f824b0907210b6348671bb040ca072e2e0c82" - dependencies: - babel-helper-evaluate-path "^0.2.0" - -babel-plugin-minify-constant-folding@^0.2.0: - version "0.2.0" - resolved "https://registry.yarnpkg.com/babel-plugin-minify-constant-folding/-/babel-plugin-minify-constant-folding-0.2.0.tgz#8c70b528b2eb7c13e94d95c8789077d4cdbc3970" - dependencies: - babel-helper-evaluate-path "^0.2.0" - -babel-plugin-minify-dead-code-elimination@^0.2.0: - version "0.2.0" - resolved "https://registry.yarnpkg.com/babel-plugin-minify-dead-code-elimination/-/babel-plugin-minify-dead-code-elimination-0.2.0.tgz#e8025ee10a1e5e4f202633a6928ce892c33747e3" - dependencies: - babel-helper-evaluate-path "^0.2.0" - babel-helper-mark-eval-scopes "^0.2.0" - babel-helper-remove-or-void "^0.2.0" - lodash.some "^4.6.0" - -babel-plugin-minify-flip-comparisons@^0.2.0: - version "0.2.0" - resolved "https://registry.yarnpkg.com/babel-plugin-minify-flip-comparisons/-/babel-plugin-minify-flip-comparisons-0.2.0.tgz#0c9c8e93155c8f09dedad8118b634c259f709ef5" - dependencies: - babel-helper-is-void-0 "^0.2.0" - -babel-plugin-minify-guarded-expressions@^0.2.0: - version "0.2.0" - resolved "https://registry.yarnpkg.com/babel-plugin-minify-guarded-expressions/-/babel-plugin-minify-guarded-expressions-0.2.0.tgz#8a8c950040fce3e258a12e6eb21eab94ad7235ab" - dependencies: - babel-helper-flip-expressions "^0.2.0" - -babel-plugin-minify-infinity@^0.2.0: - version "0.2.0" - resolved "https://registry.yarnpkg.com/babel-plugin-minify-infinity/-/babel-plugin-minify-infinity-0.2.0.tgz#30960c615ddbc657c045bb00a1d8eb4af257cf03" - -babel-plugin-minify-mangle-names@^0.2.0: - version "0.2.0" - resolved "https://registry.yarnpkg.com/babel-plugin-minify-mangle-names/-/babel-plugin-minify-mangle-names-0.2.0.tgz#719892297ff0106a6ec1a4b0fc062f1f8b6a8529" - dependencies: - babel-helper-mark-eval-scopes "^0.2.0" - -babel-plugin-minify-numeric-literals@^0.2.0: - version "0.2.0" - resolved "https://registry.yarnpkg.com/babel-plugin-minify-numeric-literals/-/babel-plugin-minify-numeric-literals-0.2.0.tgz#5746e851700167a380c05e93f289a7070459a0d1" - -babel-plugin-minify-replace@^0.2.0: - version "0.2.0" - resolved "https://registry.yarnpkg.com/babel-plugin-minify-replace/-/babel-plugin-minify-replace-0.2.0.tgz#3c1f06bc4e6d3e301eacb763edc1be611efc39b0" - -babel-plugin-minify-simplify@^0.2.0: - version "0.2.0" - resolved "https://registry.yarnpkg.com/babel-plugin-minify-simplify/-/babel-plugin-minify-simplify-0.2.0.tgz#21ceec4857100c5476d7cef121f351156e5c9bc0" - dependencies: - babel-helper-flip-expressions "^0.2.0" - babel-helper-is-nodes-equiv "^0.0.1" - babel-helper-to-multiple-sequence-expressions "^0.2.0" - -babel-plugin-minify-type-constructors@^0.2.0: - version "0.2.0" - resolved "https://registry.yarnpkg.com/babel-plugin-minify-type-constructors/-/babel-plugin-minify-type-constructors-0.2.0.tgz#7f3b6458be0863cfd59e9985bed6d134aa7a2e17" - dependencies: - babel-helper-is-void-0 "^0.2.0" - -babel-plugin-syntax-async-functions@^6.8.0: - version "6.13.0" - resolved "https://registry.yarnpkg.com/babel-plugin-syntax-async-functions/-/babel-plugin-syntax-async-functions-6.13.0.tgz#cad9cad1191b5ad634bf30ae0872391e0647be95" - -babel-plugin-syntax-exponentiation-operator@^6.8.0: - version "6.13.0" - resolved "https://registry.yarnpkg.com/babel-plugin-syntax-exponentiation-operator/-/babel-plugin-syntax-exponentiation-operator-6.13.0.tgz#9ee7e8337290da95288201a6a57f4170317830de" - -babel-plugin-syntax-trailing-function-commas@^6.20.0, babel-plugin-syntax-trailing-function-commas@^6.22.0: - version "6.22.0" - resolved "https://registry.yarnpkg.com/babel-plugin-syntax-trailing-function-commas/-/babel-plugin-syntax-trailing-function-commas-6.22.0.tgz#ba0360937f8d06e40180a43fe0d5616fff532cf3" - -babel-plugin-transform-async-to-generator@^6.16.0, babel-plugin-transform-async-to-generator@^6.22.0: - version "6.24.1" - resolved "https://registry.yarnpkg.com/babel-plugin-transform-async-to-generator/-/babel-plugin-transform-async-to-generator-6.24.1.tgz#6536e378aff6cb1d5517ac0e40eb3e9fc8d08761" - dependencies: - babel-helper-remap-async-to-generator "^6.24.1" - babel-plugin-syntax-async-functions "^6.8.0" - babel-runtime "^6.22.0" - -babel-plugin-transform-es2015-arrow-functions@^6.22.0: - version "6.22.0" - resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-arrow-functions/-/babel-plugin-transform-es2015-arrow-functions-6.22.0.tgz#452692cb711d5f79dc7f85e440ce41b9f244d221" - dependencies: - babel-runtime "^6.22.0" - -babel-plugin-transform-es2015-block-scoped-functions@^6.22.0: - version "6.22.0" - resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-block-scoped-functions/-/babel-plugin-transform-es2015-block-scoped-functions-6.22.0.tgz#bbc51b49f964d70cb8d8e0b94e820246ce3a6141" - dependencies: - babel-runtime "^6.22.0" - -babel-plugin-transform-es2015-block-scoping@^6.23.0: - version "6.24.1" - resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-block-scoping/-/babel-plugin-transform-es2015-block-scoping-6.24.1.tgz#76c295dc3a4741b1665adfd3167215dcff32a576" - dependencies: - babel-runtime "^6.22.0" - babel-template "^6.24.1" - babel-traverse "^6.24.1" - babel-types "^6.24.1" - lodash "^4.2.0" - -babel-plugin-transform-es2015-classes@^6.23.0: - version "6.24.1" - resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-classes/-/babel-plugin-transform-es2015-classes-6.24.1.tgz#5a4c58a50c9c9461e564b4b2a3bfabc97a2584db" - dependencies: - babel-helper-define-map "^6.24.1" - babel-helper-function-name "^6.24.1" - babel-helper-optimise-call-expression "^6.24.1" - babel-helper-replace-supers "^6.24.1" - babel-messages "^6.23.0" - babel-runtime "^6.22.0" - babel-template "^6.24.1" - babel-traverse "^6.24.1" - babel-types "^6.24.1" - -babel-plugin-transform-es2015-computed-properties@^6.22.0: - version "6.24.1" - resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-computed-properties/-/babel-plugin-transform-es2015-computed-properties-6.24.1.tgz#6fe2a8d16895d5634f4cd999b6d3480a308159b3" - dependencies: - babel-runtime "^6.22.0" - babel-template "^6.24.1" - -babel-plugin-transform-es2015-destructuring@^6.19.0, babel-plugin-transform-es2015-destructuring@^6.23.0: - version "6.23.0" - resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-destructuring/-/babel-plugin-transform-es2015-destructuring-6.23.0.tgz#997bb1f1ab967f682d2b0876fe358d60e765c56d" - dependencies: - babel-runtime "^6.22.0" - -babel-plugin-transform-es2015-duplicate-keys@^6.22.0: - version "6.24.1" - resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-duplicate-keys/-/babel-plugin-transform-es2015-duplicate-keys-6.24.1.tgz#73eb3d310ca969e3ef9ec91c53741a6f1576423e" - dependencies: - babel-runtime "^6.22.0" - babel-types "^6.24.1" - -babel-plugin-transform-es2015-for-of@^6.23.0: - version "6.23.0" - resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-for-of/-/babel-plugin-transform-es2015-for-of-6.23.0.tgz#f47c95b2b613df1d3ecc2fdb7573623c75248691" - dependencies: - babel-runtime "^6.22.0" - -babel-plugin-transform-es2015-function-name@^6.22.0, babel-plugin-transform-es2015-function-name@^6.9.0: - version "6.24.1" - resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-function-name/-/babel-plugin-transform-es2015-function-name-6.24.1.tgz#834c89853bc36b1af0f3a4c5dbaa94fd8eacaa8b" - dependencies: - babel-helper-function-name "^6.24.1" - babel-runtime "^6.22.0" - babel-types "^6.24.1" - -babel-plugin-transform-es2015-literals@^6.22.0: - version "6.22.0" - resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-literals/-/babel-plugin-transform-es2015-literals-6.22.0.tgz#4f54a02d6cd66cf915280019a31d31925377ca2e" - dependencies: - babel-runtime "^6.22.0" - -babel-plugin-transform-es2015-modules-amd@^6.22.0, babel-plugin-transform-es2015-modules-amd@^6.24.1: - version "6.24.1" - resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-modules-amd/-/babel-plugin-transform-es2015-modules-amd-6.24.1.tgz#3b3e54017239842d6d19c3011c4bd2f00a00d154" - dependencies: - babel-plugin-transform-es2015-modules-commonjs "^6.24.1" - babel-runtime "^6.22.0" - babel-template "^6.24.1" - -babel-plugin-transform-es2015-modules-commonjs@^6.18.0, babel-plugin-transform-es2015-modules-commonjs@^6.23.0, babel-plugin-transform-es2015-modules-commonjs@^6.24.1: - version "6.24.1" - resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-modules-commonjs/-/babel-plugin-transform-es2015-modules-commonjs-6.24.1.tgz#d3e310b40ef664a36622200097c6d440298f2bfe" - dependencies: - babel-plugin-transform-strict-mode "^6.24.1" - babel-runtime "^6.22.0" - babel-template "^6.24.1" - babel-types "^6.24.1" - -babel-plugin-transform-es2015-modules-systemjs@^6.23.0: - version "6.24.1" - resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-modules-systemjs/-/babel-plugin-transform-es2015-modules-systemjs-6.24.1.tgz#ff89a142b9119a906195f5f106ecf305d9407d23" - dependencies: - babel-helper-hoist-variables "^6.24.1" - babel-runtime "^6.22.0" - babel-template "^6.24.1" - -babel-plugin-transform-es2015-modules-umd@^6.23.0: - version "6.24.1" - resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-modules-umd/-/babel-plugin-transform-es2015-modules-umd-6.24.1.tgz#ac997e6285cd18ed6176adb607d602344ad38468" - dependencies: - babel-plugin-transform-es2015-modules-amd "^6.24.1" - babel-runtime "^6.22.0" - babel-template "^6.24.1" - -babel-plugin-transform-es2015-object-super@^6.22.0: - version "6.24.1" - resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-object-super/-/babel-plugin-transform-es2015-object-super-6.24.1.tgz#24cef69ae21cb83a7f8603dad021f572eb278f8d" - dependencies: - babel-helper-replace-supers "^6.24.1" - babel-runtime "^6.22.0" - -babel-plugin-transform-es2015-parameters@^6.21.0, babel-plugin-transform-es2015-parameters@^6.23.0: - version "6.24.1" - resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-parameters/-/babel-plugin-transform-es2015-parameters-6.24.1.tgz#57ac351ab49caf14a97cd13b09f66fdf0a625f2b" - dependencies: - babel-helper-call-delegate "^6.24.1" - babel-helper-get-function-arity "^6.24.1" - babel-runtime "^6.22.0" - babel-template "^6.24.1" - babel-traverse "^6.24.1" - babel-types "^6.24.1" - -babel-plugin-transform-es2015-shorthand-properties@^6.22.0: - version "6.24.1" - resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-shorthand-properties/-/babel-plugin-transform-es2015-shorthand-properties-6.24.1.tgz#24f875d6721c87661bbd99a4622e51f14de38aa0" - dependencies: - babel-runtime "^6.22.0" - babel-types "^6.24.1" - -babel-plugin-transform-es2015-spread@^6.22.0, babel-plugin-transform-es2015-spread@^6.8.0: - version "6.22.0" - resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-spread/-/babel-plugin-transform-es2015-spread-6.22.0.tgz#d6d68a99f89aedc4536c81a542e8dd9f1746f8d1" - dependencies: - babel-runtime "^6.22.0" - -babel-plugin-transform-es2015-sticky-regex@^6.22.0, babel-plugin-transform-es2015-sticky-regex@^6.8.0: - version "6.24.1" - resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-sticky-regex/-/babel-plugin-transform-es2015-sticky-regex-6.24.1.tgz#00c1cdb1aca71112cdf0cf6126c2ed6b457ccdbc" - dependencies: - babel-helper-regex "^6.24.1" - babel-runtime "^6.22.0" - babel-types "^6.24.1" - -babel-plugin-transform-es2015-template-literals@^6.22.0: - version "6.22.0" - resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-template-literals/-/babel-plugin-transform-es2015-template-literals-6.22.0.tgz#a84b3450f7e9f8f1f6839d6d687da84bb1236d8d" - dependencies: - babel-runtime "^6.22.0" - -babel-plugin-transform-es2015-typeof-symbol@^6.23.0: - version "6.23.0" - resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-typeof-symbol/-/babel-plugin-transform-es2015-typeof-symbol-6.23.0.tgz#dec09f1cddff94b52ac73d505c84df59dcceb372" - dependencies: - babel-runtime "^6.22.0" - -babel-plugin-transform-es2015-unicode-regex@^6.11.0, babel-plugin-transform-es2015-unicode-regex@^6.22.0: - version "6.24.1" - resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-unicode-regex/-/babel-plugin-transform-es2015-unicode-regex-6.24.1.tgz#d38b12f42ea7323f729387f18a7c5ae1faeb35e9" - dependencies: - babel-helper-regex "^6.24.1" - babel-runtime "^6.22.0" - regexpu-core "^2.0.0" - -babel-plugin-transform-exponentiation-operator@^6.22.0, babel-plugin-transform-exponentiation-operator@^6.8.0: - version "6.24.1" - resolved "https://registry.yarnpkg.com/babel-plugin-transform-exponentiation-operator/-/babel-plugin-transform-exponentiation-operator-6.24.1.tgz#2ab0c9c7f3098fa48907772bb813fe41e8de3a0e" - dependencies: - babel-helper-builder-binary-assignment-operator-visitor "^6.24.1" - babel-plugin-syntax-exponentiation-operator "^6.8.0" - babel-runtime "^6.22.0" - -babel-plugin-transform-inline-consecutive-adds@^0.2.0: - version "0.2.0" - resolved "https://registry.yarnpkg.com/babel-plugin-transform-inline-consecutive-adds/-/babel-plugin-transform-inline-consecutive-adds-0.2.0.tgz#15dae78921057f4004f8eafd79e15ddc5f12f426" - -babel-plugin-transform-member-expression-literals@^6.8.5: - version "6.8.5" - resolved "https://registry.yarnpkg.com/babel-plugin-transform-member-expression-literals/-/babel-plugin-transform-member-expression-literals-6.8.5.tgz#e06ae305cf48d819822e93a70d79269f04d89eec" - -babel-plugin-transform-merge-sibling-variables@^6.8.6: - version "6.8.6" - resolved "https://registry.yarnpkg.com/babel-plugin-transform-merge-sibling-variables/-/babel-plugin-transform-merge-sibling-variables-6.8.6.tgz#6d21efa5ee4981f71657fae716f9594bb2622aef" - -babel-plugin-transform-minify-booleans@^6.8.3: - version "6.8.3" - resolved "https://registry.yarnpkg.com/babel-plugin-transform-minify-booleans/-/babel-plugin-transform-minify-booleans-6.8.3.tgz#5906ed776d3718250519abf1bace44b0b613ddf9" - -babel-plugin-transform-property-literals@^6.8.5: - version "6.8.5" - resolved "https://registry.yarnpkg.com/babel-plugin-transform-property-literals/-/babel-plugin-transform-property-literals-6.8.5.tgz#67ed5930b34805443452c8b9690c7ebe1e206c40" - dependencies: - esutils "^2.0.2" - -babel-plugin-transform-regenerator@^6.22.0: - version "6.24.1" - resolved "https://registry.yarnpkg.com/babel-plugin-transform-regenerator/-/babel-plugin-transform-regenerator-6.24.1.tgz#b8da305ad43c3c99b4848e4fe4037b770d23c418" - dependencies: - regenerator-transform "0.9.11" - -babel-plugin-transform-regexp-constructors@^0.2.0: - version "0.2.0" - resolved "https://registry.yarnpkg.com/babel-plugin-transform-regexp-constructors/-/babel-plugin-transform-regexp-constructors-0.2.0.tgz#6aa5dd0acc515db4be929bbcec4ed4c946c534a3" - -babel-plugin-transform-remove-console@^6.8.5: - version "6.8.5" - resolved "https://registry.yarnpkg.com/babel-plugin-transform-remove-console/-/babel-plugin-transform-remove-console-6.8.5.tgz#fde9d2d3d725530b0fadd8d31078402410386810" - -babel-plugin-transform-remove-debugger@^6.8.5: - version "6.8.5" - resolved "https://registry.yarnpkg.com/babel-plugin-transform-remove-debugger/-/babel-plugin-transform-remove-debugger-6.8.5.tgz#809584d412bf918f071fdf41e1fdb15ea89cdcd5" - -babel-plugin-transform-remove-undefined@^0.2.0: - version "0.2.0" - resolved "https://registry.yarnpkg.com/babel-plugin-transform-remove-undefined/-/babel-plugin-transform-remove-undefined-0.2.0.tgz#94f052062054c707e8d094acefe79416b63452b1" - dependencies: - babel-helper-evaluate-path "^0.2.0" - -babel-plugin-transform-simplify-comparison-operators@^6.8.5: - version "6.8.5" - resolved "https://registry.yarnpkg.com/babel-plugin-transform-simplify-comparison-operators/-/babel-plugin-transform-simplify-comparison-operators-6.8.5.tgz#a838786baf40cc33a93b95ae09e05591227e43bf" - -babel-plugin-transform-strict-mode@^6.24.1: - version "6.24.1" - resolved "https://registry.yarnpkg.com/babel-plugin-transform-strict-mode/-/babel-plugin-transform-strict-mode-6.24.1.tgz#d5faf7aa578a65bbe591cf5edae04a0c67020758" - dependencies: - babel-runtime "^6.22.0" - babel-types "^6.24.1" - -babel-plugin-transform-undefined-to-void@^6.8.3: - version "6.8.3" - resolved "https://registry.yarnpkg.com/babel-plugin-transform-undefined-to-void/-/babel-plugin-transform-undefined-to-void-6.8.3.tgz#fc52707f6ee1ddc71bb91b0d314fbefdeef9beb4" - -babel-preset-env@^1.6.0: - version "1.6.0" - resolved "https://registry.yarnpkg.com/babel-preset-env/-/babel-preset-env-1.6.0.tgz#2de1c782a780a0a5d605d199c957596da43c44e4" - dependencies: - babel-plugin-check-es2015-constants "^6.22.0" - babel-plugin-syntax-trailing-function-commas "^6.22.0" - babel-plugin-transform-async-to-generator "^6.22.0" - babel-plugin-transform-es2015-arrow-functions "^6.22.0" - babel-plugin-transform-es2015-block-scoped-functions "^6.22.0" - babel-plugin-transform-es2015-block-scoping "^6.23.0" - babel-plugin-transform-es2015-classes "^6.23.0" - babel-plugin-transform-es2015-computed-properties "^6.22.0" - babel-plugin-transform-es2015-destructuring "^6.23.0" - babel-plugin-transform-es2015-duplicate-keys "^6.22.0" - babel-plugin-transform-es2015-for-of "^6.23.0" - babel-plugin-transform-es2015-function-name "^6.22.0" - babel-plugin-transform-es2015-literals "^6.22.0" - babel-plugin-transform-es2015-modules-amd "^6.22.0" - babel-plugin-transform-es2015-modules-commonjs "^6.23.0" - babel-plugin-transform-es2015-modules-systemjs "^6.23.0" - babel-plugin-transform-es2015-modules-umd "^6.23.0" - babel-plugin-transform-es2015-object-super "^6.22.0" - babel-plugin-transform-es2015-parameters "^6.23.0" - babel-plugin-transform-es2015-shorthand-properties "^6.22.0" - babel-plugin-transform-es2015-spread "^6.22.0" - babel-plugin-transform-es2015-sticky-regex "^6.22.0" - babel-plugin-transform-es2015-template-literals "^6.22.0" - babel-plugin-transform-es2015-typeof-symbol "^6.23.0" - babel-plugin-transform-es2015-unicode-regex "^6.22.0" - babel-plugin-transform-exponentiation-operator "^6.22.0" - babel-plugin-transform-regenerator "^6.22.0" - browserslist "^2.1.2" - invariant "^2.2.2" - semver "^5.3.0" - -babel-preset-minify@^0.2.0: - version "0.2.0" - resolved "https://registry.yarnpkg.com/babel-preset-minify/-/babel-preset-minify-0.2.0.tgz#006566552d9b83834472273f306c0131062a0acc" - dependencies: - babel-plugin-minify-builtins "^0.2.0" - babel-plugin-minify-constant-folding "^0.2.0" - babel-plugin-minify-dead-code-elimination "^0.2.0" - babel-plugin-minify-flip-comparisons "^0.2.0" - babel-plugin-minify-guarded-expressions "^0.2.0" - babel-plugin-minify-infinity "^0.2.0" - babel-plugin-minify-mangle-names "^0.2.0" - babel-plugin-minify-numeric-literals "^0.2.0" - babel-plugin-minify-replace "^0.2.0" - babel-plugin-minify-simplify "^0.2.0" - babel-plugin-minify-type-constructors "^0.2.0" - babel-plugin-transform-inline-consecutive-adds "^0.2.0" - babel-plugin-transform-member-expression-literals "^6.8.5" - babel-plugin-transform-merge-sibling-variables "^6.8.6" - babel-plugin-transform-minify-booleans "^6.8.3" - babel-plugin-transform-property-literals "^6.8.5" - babel-plugin-transform-regexp-constructors "^0.2.0" - babel-plugin-transform-remove-console "^6.8.5" - babel-plugin-transform-remove-debugger "^6.8.5" - babel-plugin-transform-remove-undefined "^0.2.0" - babel-plugin-transform-simplify-comparison-operators "^6.8.5" - babel-plugin-transform-undefined-to-void "^6.8.3" - lodash.isplainobject "^4.0.6" - -babel-register@^6.24.1: - version "6.24.1" - resolved "https://registry.yarnpkg.com/babel-register/-/babel-register-6.24.1.tgz#7e10e13a2f71065bdfad5a1787ba45bca6ded75f" - dependencies: - babel-core "^6.24.1" - babel-runtime "^6.22.0" - core-js "^2.4.0" - home-or-tmp "^2.0.0" - lodash "^4.2.0" - mkdirp "^0.5.1" - source-map-support "^0.4.2" - -babel-register@^6.26.0: - version "6.26.0" - resolved "https://registry.yarnpkg.com/babel-register/-/babel-register-6.26.0.tgz#6ed021173e2fcb486d7acb45c6009a856f647071" - dependencies: - babel-core "^6.26.0" - babel-runtime "^6.26.0" - core-js "^2.5.0" - home-or-tmp "^2.0.0" - lodash "^4.17.4" - mkdirp "^0.5.1" - source-map-support "^0.4.15" - -babel-runtime@^6.18.0, babel-runtime@^6.22.0: - version "6.23.0" - resolved "https://registry.yarnpkg.com/babel-runtime/-/babel-runtime-6.23.0.tgz#0a9489f144de70efb3ce4300accdb329e2fc543b" - dependencies: - core-js "^2.4.0" - regenerator-runtime "^0.10.0" - -babel-runtime@^6.26.0: - version "6.26.0" - resolved "https://registry.yarnpkg.com/babel-runtime/-/babel-runtime-6.26.0.tgz#965c7058668e82b55d7bfe04ff2337bc8b5647fe" - dependencies: - core-js "^2.4.0" - regenerator-runtime "^0.11.0" - -babel-template@^6.16.0, babel-template@^6.24.1, babel-template@^6.25.0: - version "6.25.0" - resolved "https://registry.yarnpkg.com/babel-template/-/babel-template-6.25.0.tgz#665241166b7c2aa4c619d71e192969552b10c071" - dependencies: - babel-runtime "^6.22.0" - babel-traverse "^6.25.0" - babel-types "^6.25.0" - babylon "^6.17.2" - lodash "^4.2.0" - -babel-template@^6.26.0: - version "6.26.0" - resolved "https://registry.yarnpkg.com/babel-template/-/babel-template-6.26.0.tgz#de03e2d16396b069f46dd9fff8521fb1a0e35e02" - dependencies: - babel-runtime "^6.26.0" - babel-traverse "^6.26.0" - babel-types "^6.26.0" - babylon "^6.18.0" - lodash "^4.17.4" - -babel-traverse@^6.18.0, babel-traverse@^6.24.1, babel-traverse@^6.25.0: - version "6.25.0" - resolved "https://registry.yarnpkg.com/babel-traverse/-/babel-traverse-6.25.0.tgz#2257497e2fcd19b89edc13c4c91381f9512496f1" - dependencies: - babel-code-frame "^6.22.0" - babel-messages "^6.23.0" - babel-runtime "^6.22.0" - babel-types "^6.25.0" - babylon "^6.17.2" - debug "^2.2.0" - globals "^9.0.0" - invariant "^2.2.0" - lodash "^4.2.0" - -babel-traverse@^6.26.0: - version "6.26.0" - resolved "https://registry.yarnpkg.com/babel-traverse/-/babel-traverse-6.26.0.tgz#46a9cbd7edcc62c8e5c064e2d2d8d0f4035766ee" - dependencies: - babel-code-frame "^6.26.0" - babel-messages "^6.23.0" - babel-runtime "^6.26.0" - babel-types "^6.26.0" - babylon "^6.18.0" - debug "^2.6.8" - globals "^9.18.0" - invariant "^2.2.2" - lodash "^4.17.4" - -babel-types@^6.18.0, babel-types@^6.19.0, babel-types@^6.24.1, babel-types@^6.25.0: - version "6.25.0" - resolved "https://registry.yarnpkg.com/babel-types/-/babel-types-6.25.0.tgz#70afb248d5660e5d18f811d91c8303b54134a18e" - dependencies: - babel-runtime "^6.22.0" - esutils "^2.0.2" - lodash "^4.2.0" - to-fast-properties "^1.0.1" - -babel-types@^6.26.0: - version "6.26.0" - resolved "https://registry.yarnpkg.com/babel-types/-/babel-types-6.26.0.tgz#a3b073f94ab49eb6fa55cd65227a334380632497" - dependencies: - babel-runtime "^6.26.0" - esutils "^2.0.2" - lodash "^4.17.4" - to-fast-properties "^1.0.3" - -babylon@^6.1.0, babylon@^6.17.2: - version "6.17.4" - resolved "https://registry.yarnpkg.com/babylon/-/babylon-6.17.4.tgz#3e8b7402b88d22c3423e137a1577883b15ff869a" - -babylon@^6.18.0: - version "6.18.0" - resolved "https://registry.yarnpkg.com/babylon/-/babylon-6.18.0.tgz#af2f3b88fa6f5c1e4c634d1a0f8eac4f55b395e3" - -balanced-match@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.0.tgz#89b4d199ab2bee49de164ea02b89ce462d71b767" - -bcrypt-pbkdf@^1.0.0: - version "1.0.2" - resolved "https://registry.yarnpkg.com/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz#a4301d389b6a43f9b67ff3ca11a3f6637e360e9e" - dependencies: - tweetnacl "^0.14.3" - -binary-extensions@^1.0.0: - version "1.8.0" - resolved "https://registry.yarnpkg.com/binary-extensions/-/binary-extensions-1.8.0.tgz#48ec8d16df4377eae5fa5884682480af4d95c774" - -block-stream@*: - version "0.0.9" - resolved "https://registry.yarnpkg.com/block-stream/-/block-stream-0.0.9.tgz#13ebfe778a03205cfe03751481ebb4b3300c126a" - dependencies: - inherits "~2.0.0" - -bluebird@^3.0.0: - version "3.5.0" - resolved "https://registry.yarnpkg.com/bluebird/-/bluebird-3.5.0.tgz#791420d7f551eea2897453a8a77653f96606d67c" - -boom@2.x.x: - version "2.10.1" - resolved "https://registry.yarnpkg.com/boom/-/boom-2.10.1.tgz#39c8918ceff5799f83f9492a848f625add0c766f" - dependencies: - hoek "2.x.x" - -boxen@^1.0.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/boxen/-/boxen-1.1.0.tgz#b1b69dd522305e807a99deee777dbd6e5167b102" - dependencies: - ansi-align "^2.0.0" - camelcase "^4.0.0" - chalk "^1.1.1" - cli-boxes "^1.0.0" - string-width "^2.0.0" - term-size "^0.1.0" - widest-line "^1.0.0" - -brace-expansion@^1.1.7: - version "1.1.11" - resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.11.tgz#3c7fcbf529d87226f3d2f52b966ff5271eb441dd" - dependencies: - balanced-match "^1.0.0" - concat-map "0.0.1" - -braces@^1.8.2: - version "1.8.5" - resolved "https://registry.yarnpkg.com/braces/-/braces-1.8.5.tgz#ba77962e12dff969d6b76711e914b737857bf6a7" - dependencies: - expand-range "^1.8.1" - preserve "^0.2.0" - repeat-element "^1.1.2" - -browser-resolve@^1.11.0: - version "1.11.2" - resolved "https://registry.yarnpkg.com/browser-resolve/-/browser-resolve-1.11.2.tgz#8ff09b0a2c421718a1051c260b32e48f442938ce" - dependencies: - resolve "1.1.7" - -browserslist@^2.1.2: - version "2.1.5" - resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-2.1.5.tgz#e882550df3d1cd6d481c1a3e0038f2baf13a4711" - dependencies: - caniuse-lite "^1.0.30000684" - electron-to-chromium "^1.3.14" - -buf-compare@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/buf-compare/-/buf-compare-1.0.1.tgz#fef28da8b8113a0a0db4430b0b6467b69730b34a" - -builtin-modules@^1.0.0, builtin-modules@^1.1.0, builtin-modules@^1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/builtin-modules/-/builtin-modules-1.1.1.tgz#270f076c5a72c02f5b65a47df94c5fe3a278892f" - -caching-transform@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/caching-transform/-/caching-transform-1.0.1.tgz#6dbdb2f20f8d8fbce79f3e94e9d1742dcdf5c0a1" - dependencies: - md5-hex "^1.2.0" - mkdirp "^0.5.1" - write-file-atomic "^1.1.4" - -call-matcher@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/call-matcher/-/call-matcher-1.0.1.tgz#5134d077984f712a54dad3cbf62de28dce416ca8" - dependencies: - core-js "^2.0.0" - deep-equal "^1.0.0" - espurify "^1.6.0" - estraverse "^4.0.0" - -call-signature@0.0.2: - version "0.0.2" - resolved "https://registry.yarnpkg.com/call-signature/-/call-signature-0.0.2.tgz#a84abc825a55ef4cb2b028bd74e205a65b9a4996" - -caller-path@^0.1.0: - version "0.1.0" - resolved "https://registry.yarnpkg.com/caller-path/-/caller-path-0.1.0.tgz#94085ef63581ecd3daa92444a8fe94e82577751f" - dependencies: - callsites "^0.2.0" - -callsites@^0.2.0: - version "0.2.0" - resolved "https://registry.yarnpkg.com/callsites/-/callsites-0.2.0.tgz#afab96262910a7f33c19a5775825c69f34e350ca" - -camelcase-keys@^2.0.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/camelcase-keys/-/camelcase-keys-2.1.0.tgz#308beeaffdf28119051efa1d932213c91b8f92e7" - dependencies: - camelcase "^2.0.0" - map-obj "^1.0.0" - -camelcase@^1.0.2: - version "1.2.1" - resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-1.2.1.tgz#9bb5304d2e0b56698b2c758b08a3eaa9daa58a39" - -camelcase@^2.0.0: - version "2.1.1" - resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-2.1.1.tgz#7c1d16d679a1bbe59ca02cacecfb011e201f5a1f" - -camelcase@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-3.0.0.tgz#32fc4b9fcdaf845fcdf7e73bb97cac2261f0ab0a" - -camelcase@^4.0.0, camelcase@^4.1.0: - version "4.1.0" - resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-4.1.0.tgz#d545635be1e33c542649c69173e5de6acfae34dd" - -caniuse-lite@^1.0.30000684: - version "1.0.30000693" - resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30000693.tgz#c9c6298697c71fdf6cb13eefe8aa93926f2f8613" - -capture-stack-trace@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/capture-stack-trace/-/capture-stack-trace-1.0.0.tgz#4a6fa07399c26bba47f0b2496b4d0fb408c5550d" - -caseless@~0.12.0: - version "0.12.0" - resolved "https://registry.yarnpkg.com/caseless/-/caseless-0.12.0.tgz#1b681c21ff84033c826543090689420d187151dc" - -center-align@^0.1.1: - version "0.1.3" - resolved "https://registry.yarnpkg.com/center-align/-/center-align-0.1.3.tgz#aa0d32629b6ee972200411cbd4461c907bc2b7ad" - dependencies: - align-text "^0.1.3" - lazy-cache "^1.0.3" - -chalk@^0.4.0: - version "0.4.0" - resolved "https://registry.yarnpkg.com/chalk/-/chalk-0.4.0.tgz#5199a3ddcd0c1efe23bc08c1b027b06176e0c64f" - dependencies: - ansi-styles "~1.0.0" - has-color "~0.1.0" - strip-ansi "~0.1.0" - -chalk@^1.0.0, chalk@^1.1.1, chalk@^1.1.3: - version "1.1.3" - resolved "https://registry.yarnpkg.com/chalk/-/chalk-1.1.3.tgz#a8115c55e4a702fe4d150abd3872822a7e09fc98" - dependencies: - ansi-styles "^2.2.1" - escape-string-regexp "^1.0.2" - has-ansi "^2.0.0" - strip-ansi "^3.0.0" - supports-color "^2.0.0" - -chalk@^2.0.0, chalk@^2.0.1, chalk@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.1.0.tgz#ac5becf14fa21b99c6c92ca7a7d7cfd5b17e743e" - dependencies: - ansi-styles "^3.1.0" - escape-string-regexp "^1.0.5" - supports-color "^4.0.0" - -chokidar@^1.4.2: - version "1.7.0" - resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-1.7.0.tgz#798e689778151c8076b4b360e5edd28cda2bb468" - dependencies: - anymatch "^1.3.0" - async-each "^1.0.0" - glob-parent "^2.0.0" - inherits "^2.0.1" - is-binary-path "^1.0.0" - is-glob "^2.0.0" - path-is-absolute "^1.0.0" - readdirp "^2.0.0" - optionalDependencies: - fsevents "^1.0.0" - -ci-info@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/ci-info/-/ci-info-1.0.0.tgz#dc5285f2b4e251821683681c381c3388f46ec534" - -circular-json@^0.3.1: - version "0.3.1" - resolved "https://registry.yarnpkg.com/circular-json/-/circular-json-0.3.1.tgz#be8b36aefccde8b3ca7aa2d6afc07a37242c0d2d" - -clean-stack@^1.1.1: - version "1.3.0" - resolved "https://registry.yarnpkg.com/clean-stack/-/clean-stack-1.3.0.tgz#9e821501ae979986c46b1d66d2d432db2fd4ae31" - -clean-yaml-object@^0.1.0: - version "0.1.0" - resolved "https://registry.yarnpkg.com/clean-yaml-object/-/clean-yaml-object-0.1.0.tgz#63fb110dc2ce1a84dc21f6d9334876d010ae8b68" - -cli-boxes@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/cli-boxes/-/cli-boxes-1.0.0.tgz#4fa917c3e59c94a004cd61f8ee509da651687143" - -cli-cursor@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/cli-cursor/-/cli-cursor-2.1.0.tgz#b35dac376479facc3e94747d41d0d0f5238ffcb5" - dependencies: - restore-cursor "^2.0.0" - -cli-spinners@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/cli-spinners/-/cli-spinners-1.0.0.tgz#ef987ed3d48391ac3dab9180b406a742180d6e6a" - -cli-truncate@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/cli-truncate/-/cli-truncate-1.0.0.tgz#21eb91f47b3f6560f004db77a769b4668d9c5518" - dependencies: - slice-ansi "0.0.4" - string-width "^2.0.0" - -cli-width@^2.0.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/cli-width/-/cli-width-2.1.0.tgz#b234ca209b29ef66fc518d9b98d5847b00edf00a" - -cliui@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/cliui/-/cliui-2.1.0.tgz#4b475760ff80264c762c3a1719032e91c7fea0d1" - dependencies: - center-align "^0.1.1" - right-align "^0.1.1" - wordwrap "0.0.2" - -cliui@^3.2.0: - version "3.2.0" - resolved "https://registry.yarnpkg.com/cliui/-/cliui-3.2.0.tgz#120601537a916d29940f934da3b48d585a39213d" - dependencies: - string-width "^1.0.1" - strip-ansi "^3.0.1" - wrap-ansi "^2.0.0" - -co-with-promise@^4.6.0: - version "4.6.0" - resolved "https://registry.yarnpkg.com/co-with-promise/-/co-with-promise-4.6.0.tgz#413e7db6f5893a60b942cf492c4bec93db415ab7" - dependencies: - pinkie-promise "^1.0.0" - -co@^4.6.0: - version "4.6.0" - resolved "https://registry.yarnpkg.com/co/-/co-4.6.0.tgz#6ea6bdf3d853ae54ccb8e47bfa0bf3f9031fb184" - -code-excerpt@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/code-excerpt/-/code-excerpt-2.1.0.tgz#5dcc081e88f4a7e3b554e9e35d7ef232d47f8147" - dependencies: - convert-to-spaces "^1.0.1" - -code-point-at@^1.0.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/code-point-at/-/code-point-at-1.1.0.tgz#0d070b4d043a5bea33a2f1a40e2edb3d9a4ccf77" - -color-convert@^1.0.0: - version "1.9.0" - resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-1.9.0.tgz#1accf97dd739b983bf994d56fec8f95853641b7a" - dependencies: - color-name "^1.1.1" - -color-name@^1.1.1: - version "1.1.2" - resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.2.tgz#5c8ab72b64bd2215d617ae9559ebb148475cf98d" - -combined-stream@^1.0.5, combined-stream@~1.0.5: - version "1.0.5" - resolved "https://registry.yarnpkg.com/combined-stream/-/combined-stream-1.0.5.tgz#938370a57b4a51dea2c77c15d5c5fdf895164009" - dependencies: - delayed-stream "~1.0.0" - -common-path-prefix@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/common-path-prefix/-/common-path-prefix-1.0.0.tgz#cd52f6f0712e0baab97d6f9732874f22f47752c0" - -commondir@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/commondir/-/commondir-1.0.1.tgz#ddd800da0c66127393cca5950ea968a3aaf1253b" - -concat-map@0.0.1: - version "0.0.1" - resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b" - -concat-stream@^1.6.0: - version "1.6.0" - resolved "https://registry.yarnpkg.com/concat-stream/-/concat-stream-1.6.0.tgz#0aac662fd52be78964d5532f694784e70110acf7" - dependencies: - inherits "^2.0.3" - readable-stream "^2.2.2" - typedarray "^0.0.6" - -concordance@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/concordance/-/concordance-3.0.0.tgz#b2286af54405fc995fc7345b0b106d8dd073cb29" - dependencies: - date-time "^2.1.0" - esutils "^2.0.2" - fast-diff "^1.1.1" - function-name-support "^0.2.0" - js-string-escape "^1.0.1" - lodash.clonedeep "^4.5.0" - lodash.flattendeep "^4.4.0" - lodash.merge "^4.6.0" - md5-hex "^2.0.0" - semver "^5.3.0" - well-known-symbols "^1.0.0" - -configstore@^3.0.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/configstore/-/configstore-3.1.0.tgz#45df907073e26dfa1cf4b2d52f5b60545eaa11d1" - dependencies: - dot-prop "^4.1.0" - graceful-fs "^4.1.2" - make-dir "^1.0.0" - unique-string "^1.0.0" - write-file-atomic "^2.0.0" - xdg-basedir "^3.0.0" - -console-control-strings@^1.0.0, console-control-strings@~1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/console-control-strings/-/console-control-strings-1.1.0.tgz#3d7cf4464db6446ea644bf4b39507f9851008e8e" - -contains-path@^0.1.0: - version "0.1.0" - resolved "https://registry.yarnpkg.com/contains-path/-/contains-path-0.1.0.tgz#fe8cf184ff6670b6baef01a9d4861a5cbec4120a" - -convert-source-map@^1.1.0, convert-source-map@^1.2.0, convert-source-map@^1.3.0, convert-source-map@^1.5.0: - version "1.5.0" - resolved "https://registry.yarnpkg.com/convert-source-map/-/convert-source-map-1.5.0.tgz#9acd70851c6d5dfdd93d9282e5edf94a03ff46b5" - -convert-to-spaces@^1.0.1: - version "1.0.2" - resolved "https://registry.yarnpkg.com/convert-to-spaces/-/convert-to-spaces-1.0.2.tgz#7e3e48bbe6d997b1417ddca2868204b4d3d85715" - -core-assert@^0.2.0: - version "0.2.1" - resolved "https://registry.yarnpkg.com/core-assert/-/core-assert-0.2.1.tgz#f85e2cf9bfed28f773cc8b3fa5c5b69bdc02fe3f" - dependencies: - buf-compare "^1.0.0" - is-error "^2.2.0" - -core-js@^2.0.0, core-js@^2.4.0: - version "2.4.1" - resolved "https://registry.yarnpkg.com/core-js/-/core-js-2.4.1.tgz#4de911e667b0eae9124e34254b53aea6fc618d3e" - -core-js@^2.5.0: - version "2.5.1" - resolved "https://registry.yarnpkg.com/core-js/-/core-js-2.5.1.tgz#ae6874dc66937789b80754ff5428df66819ca50b" - -core-util-is@~1.0.0: - version "1.0.2" - resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.2.tgz#b5fd54220aa2bc5ab57aab7140c940754503c1a7" - -create-error-class@^3.0.0: - version "3.0.2" - resolved "https://registry.yarnpkg.com/create-error-class/-/create-error-class-3.0.2.tgz#06be7abef947a3f14a30fd610671d401bca8b7b6" - dependencies: - capture-stack-trace "^1.0.0" - -cross-spawn-async@^2.1.1: - version "2.2.5" - resolved "https://registry.yarnpkg.com/cross-spawn-async/-/cross-spawn-async-2.2.5.tgz#845ff0c0834a3ded9d160daca6d390906bb288cc" - dependencies: - lru-cache "^4.0.0" - which "^1.2.8" - -cross-spawn@^4, cross-spawn@^4.0.0: - version "4.0.2" - resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-4.0.2.tgz#7b9247621c23adfdd3856004a823cbe397424d41" - dependencies: - lru-cache "^4.0.1" - which "^1.2.9" - -cross-spawn@^5.1.0: - version "5.1.0" - resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-5.1.0.tgz#e8bd0efee58fcff6f8f94510a0a554bbfa235449" - dependencies: - lru-cache "^4.0.1" - shebang-command "^1.2.0" - which "^1.2.9" - -cryptiles@2.x.x: - version "2.0.5" - resolved "https://registry.yarnpkg.com/cryptiles/-/cryptiles-2.0.5.tgz#3bdfecdc608147c1c67202fa291e7dca59eaa3b8" - dependencies: - boom "2.x.x" - -crypto-random-string@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/crypto-random-string/-/crypto-random-string-1.0.0.tgz#a230f64f568310e1498009940790ec99545bca7e" - -currently-unhandled@^0.4.1: - version "0.4.1" - resolved "https://registry.yarnpkg.com/currently-unhandled/-/currently-unhandled-0.4.1.tgz#988df33feab191ef799a61369dd76c17adf957ea" - dependencies: - array-find-index "^1.0.1" - -dashdash@^1.12.0: - version "1.14.1" - resolved "https://registry.yarnpkg.com/dashdash/-/dashdash-1.14.1.tgz#853cfa0f7cbe2fed5de20326b8dd581035f6e2f0" - dependencies: - assert-plus "^1.0.0" - -date-time@^0.1.1: - version "0.1.1" - resolved "https://registry.yarnpkg.com/date-time/-/date-time-0.1.1.tgz#ed2f6d93d9790ce2fd66d5b5ff3edd5bbcbf3b07" - -date-time@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/date-time/-/date-time-2.1.0.tgz#0286d1b4c769633b3ca13e1e62558d2dbdc2eba2" - dependencies: - time-zone "^1.0.0" - -debug-log@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/debug-log/-/debug-log-1.0.1.tgz#2307632d4c04382b8df8a32f70b895046d52745f" - -debug@^2.1.1, debug@^2.2.0, debug@^2.6.3, debug@^2.6.8: - version "2.6.8" - resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.8.tgz#e731531ca2ede27d188222427da17821d68ff4fc" - dependencies: - ms "2.0.0" - -debug@^3.1.0: - version "3.2.6" - resolved "https://registry.yarnpkg.com/debug/-/debug-3.2.6.tgz#e83d17de16d8a7efb7717edbe5fb10135eee629b" - dependencies: - ms "^2.1.1" - -decamelize@^1.0.0, decamelize@^1.1.1, decamelize@^1.1.2: - version "1.2.0" - resolved "https://registry.yarnpkg.com/decamelize/-/decamelize-1.2.0.tgz#f6534d15148269b20352e7bee26f501f9a191290" - -deep-equal@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/deep-equal/-/deep-equal-1.0.1.tgz#f5d260292b660e084eff4cdbc9f08ad3247448b5" - -deep-extend@~0.4.0: - version "0.4.2" - resolved "https://registry.yarnpkg.com/deep-extend/-/deep-extend-0.4.2.tgz#48b699c27e334bf89f10892be432f6e4c7d34a7f" - -deep-is@~0.1.3: - version "0.1.3" - resolved "https://registry.yarnpkg.com/deep-is/-/deep-is-0.1.3.tgz#b369d6fb5dbc13eecf524f91b070feedc357cf34" - -default-require-extensions@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/default-require-extensions/-/default-require-extensions-1.0.0.tgz#f37ea15d3e13ffd9b437d33e1a75b5fb97874cb8" - dependencies: - strip-bom "^2.0.0" - -del@^2.0.2: - version "2.2.2" - resolved "https://registry.yarnpkg.com/del/-/del-2.2.2.tgz#c12c981d067846c84bcaf862cff930d907ffd1a8" - dependencies: - globby "^5.0.0" - is-path-cwd "^1.0.0" - is-path-in-cwd "^1.0.0" - object-assign "^4.0.1" - pify "^2.0.0" - pinkie-promise "^2.0.0" - rimraf "^2.2.8" - -delayed-stream@~1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/delayed-stream/-/delayed-stream-1.0.0.tgz#df3ae199acadfb7d440aaae0b29e2272b24ec619" - -delegates@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/delegates/-/delegates-1.0.0.tgz#84c6e159b81904fdca59a0ef44cd870d31250f9a" - -detect-indent@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/detect-indent/-/detect-indent-4.0.0.tgz#f76d064352cdf43a1cb6ce619c4ee3a9475de208" - dependencies: - repeating "^2.0.0" - -detect-indent@^5.0.0: - version "5.0.0" - resolved "https://registry.yarnpkg.com/detect-indent/-/detect-indent-5.0.0.tgz#3871cc0a6a002e8c3e5b3cf7f336264675f06b9d" - -doctrine@1.5.0: - version "1.5.0" - resolved "https://registry.yarnpkg.com/doctrine/-/doctrine-1.5.0.tgz#379dce730f6166f76cefa4e6707a159b02c5a6fa" - dependencies: - esutils "^2.0.2" - isarray "^1.0.0" - -doctrine@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/doctrine/-/doctrine-2.1.0.tgz#5cd01fc101621b42c4cd7f5d1a66243716d3f39d" - dependencies: - esutils "^2.0.2" - -dot-prop@^4.1.0: - version "4.1.1" - resolved "https://registry.yarnpkg.com/dot-prop/-/dot-prop-4.1.1.tgz#a8493f0b7b5eeec82525b5c7587fa7de7ca859c1" - dependencies: - is-obj "^1.0.0" - -duplexer3@^0.1.4: - version "0.1.4" - resolved "https://registry.yarnpkg.com/duplexer3/-/duplexer3-0.1.4.tgz#ee01dd1cac0ed3cbc7fdbea37dc0a8f1ce002ce2" - -ecc-jsbn@~0.1.1: - version "0.1.2" - resolved "https://registry.yarnpkg.com/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz#3a83a904e54353287874c564b7549386849a98c9" - dependencies: - jsbn "~0.1.0" - safer-buffer "^2.1.0" - -electron-to-chromium@^1.3.14: - version "1.3.14" - resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.3.14.tgz#64af0f9efd3c3c6acd57d71f83b49ca7ee9c4b43" - -empower-core@^0.6.1: - version "0.6.2" - resolved "https://registry.yarnpkg.com/empower-core/-/empower-core-0.6.2.tgz#5adef566088e31fba80ba0a36df47d7094169144" - dependencies: - call-signature "0.0.2" - core-js "^2.0.0" - -equal-length@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/equal-length/-/equal-length-1.0.1.tgz#21ca112d48ab24b4e1e7ffc0e5339d31fdfc274c" - -erlang-types@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/erlang-types/-/erlang-types-1.0.1.tgz#943a57a9324e0d0edc0273690a8c702686d9b780" - -error-ex@^1.2.0: - version "1.3.1" - resolved "https://registry.yarnpkg.com/error-ex/-/error-ex-1.3.1.tgz#f855a86ce61adc4e8621c3cda21e7a7612c3a8dc" - dependencies: - is-arrayish "^0.2.1" - -es6-error@^4.0.1, es6-error@^4.0.2: - version "4.0.2" - resolved "https://registry.yarnpkg.com/es6-error/-/es6-error-4.0.2.tgz#eec5c726eacef51b7f6b73c20db6e1b13b069c98" - -escape-string-regexp@^1.0.2, escape-string-regexp@^1.0.4, escape-string-regexp@^1.0.5: - version "1.0.5" - resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4" - -eslint-config-airbnb-base@^12.0.0: - version "12.0.0" - resolved "https://registry.yarnpkg.com/eslint-config-airbnb-base/-/eslint-config-airbnb-base-12.0.0.tgz#99063aaef4b8698083481a00e165cbe15e82d615" - dependencies: - eslint-restricted-globals "^0.1.1" - -eslint-import-resolver-node@^0.3.1: - version "0.3.1" - resolved "https://registry.yarnpkg.com/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.1.tgz#4422574cde66a9a7b099938ee4d508a199e0e3cc" - dependencies: - debug "^2.6.8" - resolve "^1.2.0" - -eslint-module-utils@^2.1.1: - version "2.1.1" - resolved "https://registry.yarnpkg.com/eslint-module-utils/-/eslint-module-utils-2.1.1.tgz#abaec824177613b8a95b299639e1b6facf473449" - dependencies: - debug "^2.6.8" - pkg-dir "^1.0.0" - -eslint-plugin-import@^2.7.0: - version "2.7.0" - resolved "https://registry.yarnpkg.com/eslint-plugin-import/-/eslint-plugin-import-2.7.0.tgz#21de33380b9efb55f5ef6d2e210ec0e07e7fa69f" - dependencies: - builtin-modules "^1.1.1" - contains-path "^0.1.0" - debug "^2.6.8" - doctrine "1.5.0" - eslint-import-resolver-node "^0.3.1" - eslint-module-utils "^2.1.1" - has "^1.0.1" - lodash.cond "^4.3.0" - minimatch "^3.0.3" - read-pkg-up "^2.0.0" - -eslint-restricted-globals@^0.1.1: - version "0.1.1" - resolved "https://registry.yarnpkg.com/eslint-restricted-globals/-/eslint-restricted-globals-0.1.1.tgz#35f0d5cbc64c2e3ed62e93b4b1a7af05ba7ed4d7" - -eslint-scope@^3.7.1: - version "3.7.1" - resolved "https://registry.yarnpkg.com/eslint-scope/-/eslint-scope-3.7.1.tgz#3d63c3edfda02e06e01a452ad88caacc7cdcb6e8" - dependencies: - esrecurse "^4.1.0" - estraverse "^4.1.1" - -eslint-visitor-keys@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-1.0.0.tgz#3f3180fb2e291017716acb4c9d6d5b5c34a6a81d" - -eslint@^4.6.1: - version "4.19.1" - resolved "https://registry.yarnpkg.com/eslint/-/eslint-4.19.1.tgz#32d1d653e1d90408854bfb296f076ec7e186a300" - dependencies: - ajv "^5.3.0" - babel-code-frame "^6.22.0" - chalk "^2.1.0" - concat-stream "^1.6.0" - cross-spawn "^5.1.0" - debug "^3.1.0" - doctrine "^2.1.0" - eslint-scope "^3.7.1" - eslint-visitor-keys "^1.0.0" - espree "^3.5.4" - esquery "^1.0.0" - esutils "^2.0.2" - file-entry-cache "^2.0.0" - functional-red-black-tree "^1.0.1" - glob "^7.1.2" - globals "^11.0.1" - ignore "^3.3.3" - imurmurhash "^0.1.4" - inquirer "^3.0.6" - is-resolvable "^1.0.0" - js-yaml "^3.9.1" - json-stable-stringify-without-jsonify "^1.0.1" - levn "^0.3.0" - lodash "^4.17.4" - minimatch "^3.0.2" - mkdirp "^0.5.1" - natural-compare "^1.4.0" - optionator "^0.8.2" - path-is-inside "^1.0.2" - pluralize "^7.0.0" - progress "^2.0.0" - regexpp "^1.0.1" - require-uncached "^1.0.3" - semver "^5.3.0" - strip-ansi "^4.0.0" - strip-json-comments "~2.0.1" - table "4.0.2" - text-table "~0.2.0" - -espower-location-detector@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/espower-location-detector/-/espower-location-detector-1.0.0.tgz#a17b7ecc59d30e179e2bef73fb4137704cb331b5" - dependencies: - is-url "^1.2.1" - path-is-absolute "^1.0.0" - source-map "^0.5.0" - xtend "^4.0.0" - -espree@^3.5.4: - version "3.5.4" - resolved "https://registry.yarnpkg.com/espree/-/espree-3.5.4.tgz#b0f447187c8a8bed944b815a660bddf5deb5d1a7" - dependencies: - acorn "^5.5.0" - acorn-jsx "^3.0.0" - -esprima@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/esprima/-/esprima-4.0.0.tgz#4499eddcd1110e0b218bacf2fa7f7f59f55ca804" - -espurify@^1.6.0: - version "1.7.0" - resolved "https://registry.yarnpkg.com/espurify/-/espurify-1.7.0.tgz#1c5cf6cbccc32e6f639380bd4f991fab9ba9d226" - dependencies: - core-js "^2.0.0" - -esquery@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/esquery/-/esquery-1.0.0.tgz#cfba8b57d7fba93f17298a8a006a04cda13d80fa" - dependencies: - estraverse "^4.0.0" - -esrecurse@^4.1.0: - version "4.2.0" - resolved "https://registry.yarnpkg.com/esrecurse/-/esrecurse-4.2.0.tgz#fa9568d98d3823f9a41d91e902dcab9ea6e5b163" - dependencies: - estraverse "^4.1.0" - object-assign "^4.0.1" - -estraverse@^4.0.0, estraverse@^4.1.0, estraverse@^4.1.1: - version "4.2.0" - resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-4.2.0.tgz#0dee3fed31fcd469618ce7342099fc1afa0bdb13" - -estree-walker@^0.2.1: - version "0.2.1" - resolved "https://registry.yarnpkg.com/estree-walker/-/estree-walker-0.2.1.tgz#bdafe8095383d8414d5dc2ecf4c9173b6db9412e" - -estree-walker@^0.3.0: - version "0.3.1" - resolved "https://registry.yarnpkg.com/estree-walker/-/estree-walker-0.3.1.tgz#e6b1a51cf7292524e7237c312e5fe6660c1ce1aa" - -estree-walker@^0.5.0: - version "0.5.0" - resolved "https://registry.yarnpkg.com/estree-walker/-/estree-walker-0.5.0.tgz#aae3b57c42deb8010e349c892462f0e71c5dd1aa" - -esutils@^2.0.2: - version "2.0.2" - resolved "https://registry.yarnpkg.com/esutils/-/esutils-2.0.2.tgz#0abf4f1caa5bcb1f7a9d8acc6dea4faaa04bac9b" - -execa@^0.4.0: - version "0.4.0" - resolved "https://registry.yarnpkg.com/execa/-/execa-0.4.0.tgz#4eb6467a36a095fabb2970ff9d5e3fb7bce6ebc3" - dependencies: - cross-spawn-async "^2.1.1" - is-stream "^1.1.0" - npm-run-path "^1.0.0" - object-assign "^4.0.1" - path-key "^1.0.0" - strip-eof "^1.0.0" - -execa@^0.5.0: - version "0.5.1" - resolved "https://registry.yarnpkg.com/execa/-/execa-0.5.1.tgz#de3fb85cb8d6e91c85bcbceb164581785cb57b36" - dependencies: - cross-spawn "^4.0.0" - get-stream "^2.2.0" - is-stream "^1.1.0" - npm-run-path "^2.0.0" - p-finally "^1.0.0" - signal-exit "^3.0.0" - strip-eof "^1.0.0" - -expand-brackets@^0.1.4: - version "0.1.5" - resolved "https://registry.yarnpkg.com/expand-brackets/-/expand-brackets-0.1.5.tgz#df07284e342a807cd733ac5af72411e581d1177b" - dependencies: - is-posix-bracket "^0.1.0" - -expand-range@^1.8.1: - version "1.8.2" - resolved "https://registry.yarnpkg.com/expand-range/-/expand-range-1.8.2.tgz#a299effd335fe2721ebae8e257ec79644fc85337" - dependencies: - fill-range "^2.1.0" - -extend@~3.0.0: - version "3.0.1" - resolved "https://registry.yarnpkg.com/extend/-/extend-3.0.1.tgz#a755ea7bc1adfcc5a31ce7e762dbaadc5e636444" - -external-editor@^2.0.4: - version "2.0.4" - resolved "https://registry.yarnpkg.com/external-editor/-/external-editor-2.0.4.tgz#1ed9199da9cbfe2ef2f7a31b2fde8b0d12368972" - dependencies: - iconv-lite "^0.4.17" - jschardet "^1.4.2" - tmp "^0.0.31" - -extglob@^0.3.1: - version "0.3.2" - resolved "https://registry.yarnpkg.com/extglob/-/extglob-0.3.2.tgz#2e18ff3d2f49ab2765cec9023f011daa8d8349a1" - dependencies: - is-extglob "^1.0.0" - -extsprintf@1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/extsprintf/-/extsprintf-1.0.2.tgz#e1080e0658e300b06294990cc70e1502235fd550" - -fast-deep-equal@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-1.0.0.tgz#96256a3bc975595eb36d82e9929d060d893439ff" - -fast-diff@^1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/fast-diff/-/fast-diff-1.1.1.tgz#0aea0e4e605b6a2189f0e936d4b7fbaf1b7cfd9b" - -fast-json-stable-stringify@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/fast-json-stable-stringify/-/fast-json-stable-stringify-2.0.0.tgz#d5142c0caee6b1189f87d3a76111064f86c8bbf2" - -fast-levenshtein@~2.0.4: - version "2.0.6" - resolved "https://registry.yarnpkg.com/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz#3d8a5c66883a16a30ca8643e851f19baa7797917" - -figures@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/figures/-/figures-2.0.0.tgz#3ab1a2d2a62c8bfb431a0c94cb797a2fce27c962" - dependencies: - escape-string-regexp "^1.0.5" - -file-entry-cache@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/file-entry-cache/-/file-entry-cache-2.0.0.tgz#c392990c3e684783d838b8c84a45d8a048458361" - dependencies: - flat-cache "^1.2.1" - object-assign "^4.0.1" - -filename-regex@^2.0.0: - version "2.0.1" - resolved "https://registry.yarnpkg.com/filename-regex/-/filename-regex-2.0.1.tgz#c1c4b9bee3e09725ddb106b75c1e301fe2f18b26" - -fill-range@^2.1.0: - version "2.2.3" - resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-2.2.3.tgz#50b77dfd7e469bc7492470963699fe7a8485a723" - dependencies: - is-number "^2.1.0" - isobject "^2.0.0" - randomatic "^1.1.3" - repeat-element "^1.1.2" - repeat-string "^1.5.2" - -find-cache-dir@^0.1.1: - version "0.1.1" - resolved "https://registry.yarnpkg.com/find-cache-dir/-/find-cache-dir-0.1.1.tgz#c8defae57c8a52a8a784f9e31c57c742e993a0b9" - dependencies: - commondir "^1.0.1" - mkdirp "^0.5.1" - pkg-dir "^1.0.0" - -find-cache-dir@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/find-cache-dir/-/find-cache-dir-1.0.0.tgz#9288e3e9e3cc3748717d39eade17cf71fc30ee6f" - dependencies: - commondir "^1.0.1" - make-dir "^1.0.0" - pkg-dir "^2.0.0" - -find-up@^1.0.0: - version "1.1.2" - resolved "https://registry.yarnpkg.com/find-up/-/find-up-1.1.2.tgz#6b2e9822b1a2ce0a60ab64d610eccad53cb24d0f" - dependencies: - path-exists "^2.0.0" - pinkie-promise "^2.0.0" - -find-up@^2.0.0, find-up@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/find-up/-/find-up-2.1.0.tgz#45d1b7e506c717ddd482775a2b77920a3c0c57a7" - dependencies: - locate-path "^2.0.0" - -flat-cache@^1.2.1: - version "1.2.2" - resolved "https://registry.yarnpkg.com/flat-cache/-/flat-cache-1.2.2.tgz#fa86714e72c21db88601761ecf2f555d1abc6b96" - dependencies: - circular-json "^0.3.1" - del "^2.0.2" - graceful-fs "^4.1.2" - write "^0.2.1" - -fn-name@^2.0.0: - version "2.0.1" - resolved "https://registry.yarnpkg.com/fn-name/-/fn-name-2.0.1.tgz#5214d7537a4d06a4a301c0cc262feb84188002e7" - -for-in@^1.0.1: - version "1.0.2" - resolved "https://registry.yarnpkg.com/for-in/-/for-in-1.0.2.tgz#81068d295a8142ec0ac726c6e2200c30fb6d5e80" - -for-own@^0.1.4: - version "0.1.5" - resolved "https://registry.yarnpkg.com/for-own/-/for-own-0.1.5.tgz#5265c681a4f294dabbf17c9509b6763aa84510ce" - dependencies: - for-in "^1.0.1" - -foreground-child@^1.5.3, foreground-child@^1.5.6: - version "1.5.6" - resolved "https://registry.yarnpkg.com/foreground-child/-/foreground-child-1.5.6.tgz#4fd71ad2dfde96789b980a5c0a295937cb2f5ce9" - dependencies: - cross-spawn "^4" - signal-exit "^3.0.0" - -forever-agent@~0.6.1: - version "0.6.1" - resolved "https://registry.yarnpkg.com/forever-agent/-/forever-agent-0.6.1.tgz#fbc71f0c41adeb37f96c577ad1ed42d8fdacca91" - -form-data@~2.1.1: - version "2.1.4" - resolved "https://registry.yarnpkg.com/form-data/-/form-data-2.1.4.tgz#33c183acf193276ecaa98143a69e94bfee1750d1" - dependencies: - asynckit "^0.4.0" - combined-stream "^1.0.5" - mime-types "^2.1.12" - -fs.realpath@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f" - -fsevents@^1.0.0: - version "1.1.2" - resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-1.1.2.tgz#3282b713fb3ad80ede0e9fcf4611b5aa6fc033f4" - dependencies: - nan "^2.3.0" - node-pre-gyp "^0.6.36" - -fstream-ignore@^1.0.5: - version "1.0.5" - resolved "https://registry.yarnpkg.com/fstream-ignore/-/fstream-ignore-1.0.5.tgz#9c31dae34767018fe1d249b24dada67d092da105" - dependencies: - fstream "^1.0.0" - inherits "2" - minimatch "^3.0.0" - -fstream@^1.0.0, fstream@^1.0.10, fstream@^1.0.12: - version "1.0.12" - resolved "https://registry.yarnpkg.com/fstream/-/fstream-1.0.12.tgz#4e8ba8ee2d48be4f7d0de505455548eae5932045" - dependencies: - graceful-fs "^4.1.2" - inherits "~2.0.0" - mkdirp ">=0.5 0" - rimraf "2" - -function-bind@^1.0.2: - version "1.1.0" - resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.0.tgz#16176714c801798e4e8f2cf7f7529467bb4a5771" - -function-name-support@^0.2.0: - version "0.2.0" - resolved "https://registry.yarnpkg.com/function-name-support/-/function-name-support-0.2.0.tgz#55d3bfaa6eafd505a50f9bc81fdf57564a0bb071" - -functional-red-black-tree@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz#1b0ab3bd553b2a0d6399d29c0e3ea0b252078327" - -gauge@~2.7.3: - version "2.7.4" - resolved "https://registry.yarnpkg.com/gauge/-/gauge-2.7.4.tgz#2c03405c7538c39d7eb37b317022e325fb018bf7" - dependencies: - aproba "^1.0.3" - console-control-strings "^1.0.0" - has-unicode "^2.0.0" - object-assign "^4.1.0" - signal-exit "^3.0.0" - string-width "^1.0.1" - strip-ansi "^3.0.1" - wide-align "^1.1.0" - -get-caller-file@^1.0.1: - version "1.0.2" - resolved "https://registry.yarnpkg.com/get-caller-file/-/get-caller-file-1.0.2.tgz#f702e63127e7e231c160a80c1554acb70d5047e5" - -get-port@^3.0.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/get-port/-/get-port-3.1.0.tgz#ef01b18a84ca6486970ff99e54446141a73ffd3e" - -get-stdin@^4.0.1: - version "4.0.1" - resolved "https://registry.yarnpkg.com/get-stdin/-/get-stdin-4.0.1.tgz#b968c6b0a04384324902e8bf1a5df32579a450fe" - -get-stream@^2.2.0: - version "2.3.1" - resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-2.3.1.tgz#5f38f93f346009666ee0150a054167f91bdd95de" - dependencies: - object-assign "^4.0.1" - pinkie-promise "^2.0.0" - -get-stream@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-3.0.0.tgz#8e943d1358dc37555054ecbe2edb05aa174ede14" - -getpass@^0.1.1: - version "0.1.7" - resolved "https://registry.yarnpkg.com/getpass/-/getpass-0.1.7.tgz#5eff8e3e684d569ae4cb2b1282604e8ba62149fa" - dependencies: - assert-plus "^1.0.0" - -glob-base@^0.3.0: - version "0.3.0" - resolved "https://registry.yarnpkg.com/glob-base/-/glob-base-0.3.0.tgz#dbb164f6221b1c0b1ccf82aea328b497df0ea3c4" - dependencies: - glob-parent "^2.0.0" - is-glob "^2.0.0" - -glob-parent@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-2.0.0.tgz#81383d72db054fcccf5336daa902f182f6edbb28" - dependencies: - is-glob "^2.0.0" - -glob@^7.0.3, glob@^7.0.5, glob@^7.0.6, glob@^7.1.2, glob@^7.1.3: - version "7.1.4" - resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.4.tgz#aa608a2f6c577ad357e1ae5a5c26d9a8d1969255" - dependencies: - fs.realpath "^1.0.0" - inflight "^1.0.4" - inherits "2" - minimatch "^3.0.4" - once "^1.3.0" - path-is-absolute "^1.0.0" - -globals@^11.0.1: - version "11.12.0" - resolved "https://registry.yarnpkg.com/globals/-/globals-11.12.0.tgz#ab8795338868a0babd8525758018c2a7eb95c42e" - -globals@^9.0.0, globals@^9.18.0: - version "9.18.0" - resolved "https://registry.yarnpkg.com/globals/-/globals-9.18.0.tgz#aa3896b3e69b487f17e31ed2143d69a8e30c2d8a" - -globby@^5.0.0: - version "5.0.0" - resolved "https://registry.yarnpkg.com/globby/-/globby-5.0.0.tgz#ebd84667ca0dbb330b99bcfc68eac2bc54370e0d" - dependencies: - array-union "^1.0.1" - arrify "^1.0.0" - glob "^7.0.3" - object-assign "^4.0.1" - pify "^2.0.0" - pinkie-promise "^2.0.0" - -globby@^6.0.0: - version "6.1.0" - resolved "https://registry.yarnpkg.com/globby/-/globby-6.1.0.tgz#f5a6d70e8395e21c858fb0489d64df02424d506c" - dependencies: - array-union "^1.0.1" - glob "^7.0.3" - object-assign "^4.0.1" - pify "^2.0.0" - pinkie-promise "^2.0.0" - -got@^6.7.1: - version "6.7.1" - resolved "https://registry.yarnpkg.com/got/-/got-6.7.1.tgz#240cd05785a9a18e561dc1b44b41c763ef1e8db0" - dependencies: - create-error-class "^3.0.0" - duplexer3 "^0.1.4" - get-stream "^3.0.0" - is-redirect "^1.0.0" - is-retry-allowed "^1.0.0" - is-stream "^1.0.0" - lowercase-keys "^1.0.0" - safe-buffer "^5.0.1" - timed-out "^4.0.0" - unzip-response "^2.0.1" - url-parse-lax "^1.0.0" - -graceful-fs@^4.1.11: - version "4.1.11" - resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.1.11.tgz#0e8bdfe4d1ddb8854d64e04ea7c00e2a026e5658" - -graceful-fs@^4.1.2: - version "4.1.15" - resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.1.15.tgz#ffb703e1066e8a0eeaa4c8b80ba9253eeefbfb00" - -grapheme-splitter@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/grapheme-splitter/-/grapheme-splitter-1.0.2.tgz#639e9dc1bf065892c643de31daa27cf58b1068e2" - -handlebars@^4.0.3: - version "4.0.10" - resolved "https://registry.yarnpkg.com/handlebars/-/handlebars-4.0.10.tgz#3d30c718b09a3d96f23ea4cc1f403c4d3ba9ff4f" - dependencies: - async "^1.4.0" - optimist "^0.6.1" - source-map "^0.4.4" - optionalDependencies: - uglify-js "^2.6" - -har-schema@^1.0.5: - version "1.0.5" - resolved "https://registry.yarnpkg.com/har-schema/-/har-schema-1.0.5.tgz#d263135f43307c02c602afc8fe95970c0151369e" - -har-validator@~4.2.1: - version "4.2.1" - resolved "https://registry.yarnpkg.com/har-validator/-/har-validator-4.2.1.tgz#33481d0f1bbff600dd203d75812a6a5fba002e2a" - dependencies: - ajv "^4.9.1" - har-schema "^1.0.5" - -has-ansi@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/has-ansi/-/has-ansi-2.0.0.tgz#34f5049ce1ecdf2b0649af3ef24e45ed35416d91" - dependencies: - ansi-regex "^2.0.0" - -has-color@~0.1.0: - version "0.1.7" - resolved "https://registry.yarnpkg.com/has-color/-/has-color-0.1.7.tgz#67144a5260c34fc3cca677d041daf52fe7b78b2f" - -has-flag@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-1.0.0.tgz#9d9e793165ce017a00f00418c43f942a7b1d11fa" - -has-flag@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-2.0.0.tgz#e8207af1cc7b30d446cc70b734b5e8be18f88d51" - -has-unicode@^2.0.0: - version "2.0.1" - resolved "https://registry.yarnpkg.com/has-unicode/-/has-unicode-2.0.1.tgz#e0e6fe6a28cf51138855e086d1691e771de2a8b9" - -has-yarn@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/has-yarn/-/has-yarn-1.0.0.tgz#89e25db604b725c8f5976fff0addc921b828a5a7" - -has@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/has/-/has-1.0.1.tgz#8461733f538b0837c9361e39a9ab9e9704dc2f28" - dependencies: - function-bind "^1.0.2" - -hawk@~3.1.3: - version "3.1.3" - resolved "https://registry.yarnpkg.com/hawk/-/hawk-3.1.3.tgz#078444bd7c1640b0fe540d2c9b73d59678e8e1c4" - dependencies: - boom "2.x.x" - cryptiles "2.x.x" - hoek "2.x.x" - sntp "1.x.x" - -hoek@2.x.x: - version "2.16.3" - resolved "https://registry.yarnpkg.com/hoek/-/hoek-2.16.3.tgz#20bb7403d3cea398e91dc4710a8ff1b8274a25ed" - -home-or-tmp@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/home-or-tmp/-/home-or-tmp-2.0.0.tgz#e36c3f2d2cae7d746a857e38d18d5f32a7882db8" - dependencies: - os-homedir "^1.0.0" - os-tmpdir "^1.0.1" - -hosted-git-info@^2.1.4: - version "2.4.2" - resolved "https://registry.yarnpkg.com/hosted-git-info/-/hosted-git-info-2.4.2.tgz#0076b9f46a270506ddbaaea56496897460612a67" - -http-signature@~1.1.0: - version "1.1.1" - resolved "https://registry.yarnpkg.com/http-signature/-/http-signature-1.1.1.tgz#df72e267066cd0ac67fb76adf8e134a8fbcf91bf" - dependencies: - assert-plus "^0.2.0" - jsprim "^1.2.2" - sshpk "^1.7.0" - -hullabaloo-config-manager@^1.1.0: - version "1.1.1" - resolved "https://registry.yarnpkg.com/hullabaloo-config-manager/-/hullabaloo-config-manager-1.1.1.tgz#1d9117813129ad035fd9e8477eaf066911269fe3" - dependencies: - dot-prop "^4.1.0" - es6-error "^4.0.2" - graceful-fs "^4.1.11" - indent-string "^3.1.0" - json5 "^0.5.1" - lodash.clonedeep "^4.5.0" - lodash.clonedeepwith "^4.5.0" - lodash.isequal "^4.5.0" - lodash.merge "^4.6.0" - md5-hex "^2.0.0" - package-hash "^2.0.0" - pkg-dir "^2.0.0" - resolve-from "^3.0.0" - safe-buffer "^5.0.1" - -iconv-lite@^0.4.17: - version "0.4.18" - resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.18.tgz#23d8656b16aae6742ac29732ea8f0336a4789cf2" - -ignore-by-default@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/ignore-by-default/-/ignore-by-default-1.0.1.tgz#48ca6d72f6c6a3af00a9ad4ae6876be3889e2b09" - -ignore@^3.3.3: - version "3.3.3" - resolved "https://registry.yarnpkg.com/ignore/-/ignore-3.3.3.tgz#432352e57accd87ab3110e82d3fea0e47812156d" - -import-lazy@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/import-lazy/-/import-lazy-2.1.0.tgz#05698e3d45c88e8d7e9d92cb0584e77f096f3e43" - -import-local@^0.1.1: - version "0.1.1" - resolved "https://registry.yarnpkg.com/import-local/-/import-local-0.1.1.tgz#b1179572aacdc11c6a91009fb430dbcab5f668a8" - dependencies: - pkg-dir "^2.0.0" - resolve-cwd "^2.0.0" - -imurmurhash@^0.1.4: - version "0.1.4" - resolved "https://registry.yarnpkg.com/imurmurhash/-/imurmurhash-0.1.4.tgz#9218b9b2b928a238b13dc4fb6b6d576f231453ea" - -indent-string@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/indent-string/-/indent-string-2.1.0.tgz#8e2d48348742121b4a8218b7a137e9a52049dc80" - dependencies: - repeating "^2.0.0" - -indent-string@^3.0.0, indent-string@^3.1.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/indent-string/-/indent-string-3.1.0.tgz#08ff4334603388399b329e6b9538dc7a3cf5de7d" - -inflight@^1.0.4: - version "1.0.6" - resolved "https://registry.yarnpkg.com/inflight/-/inflight-1.0.6.tgz#49bd6331d7d02d0c09bc910a1075ba8165b56df9" - dependencies: - once "^1.3.0" - wrappy "1" - -inherits@2, inherits@^2.0.1, inherits@^2.0.3, inherits@~2.0.0, inherits@~2.0.3: - version "2.0.3" - resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.3.tgz#633c2c83e3da42a502f52466022480f4208261de" - -ini@~1.3.0: - version "1.3.4" - resolved "https://registry.yarnpkg.com/ini/-/ini-1.3.4.tgz#0537cb79daf59b59a1a517dff706c86ec039162e" - -inquirer@^3.0.6: - version "3.2.0" - resolved "https://registry.yarnpkg.com/inquirer/-/inquirer-3.2.0.tgz#45b44c2160c729d7578c54060b3eed94487bb42b" - dependencies: - ansi-escapes "^2.0.0" - chalk "^2.0.0" - cli-cursor "^2.1.0" - cli-width "^2.0.0" - external-editor "^2.0.4" - figures "^2.0.0" - lodash "^4.3.0" - mute-stream "0.0.7" - run-async "^2.2.0" - rx-lite "^4.0.8" - rx-lite-aggregates "^4.0.8" - string-width "^2.1.0" - strip-ansi "^4.0.0" - through "^2.3.6" - -invariant@^2.2.0, invariant@^2.2.2: - version "2.2.2" - resolved "https://registry.yarnpkg.com/invariant/-/invariant-2.2.2.tgz#9e1f56ac0acdb6bf303306f338be3b204ae60360" - dependencies: - loose-envify "^1.0.0" - -invert-kv@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/invert-kv/-/invert-kv-1.0.0.tgz#104a8e4aaca6d3d8cd157a8ef8bfab2d7a3ffdb6" - -irregular-plurals@^1.0.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/irregular-plurals/-/irregular-plurals-1.2.0.tgz#38f299834ba8c00c30be9c554e137269752ff3ac" - -is-arrayish@^0.2.1: - version "0.2.1" - resolved "https://registry.yarnpkg.com/is-arrayish/-/is-arrayish-0.2.1.tgz#77c99840527aa8ecb1a8ba697b80645a7a926a9d" - -is-binary-path@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/is-binary-path/-/is-binary-path-1.0.1.tgz#75f16642b480f187a711c814161fd3a4a7655898" - dependencies: - binary-extensions "^1.0.0" - -is-buffer@^1.1.5: - version "1.1.5" - resolved "https://registry.yarnpkg.com/is-buffer/-/is-buffer-1.1.5.tgz#1f3b26ef613b214b88cbca23cc6c01d87961eecc" - -is-builtin-module@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/is-builtin-module/-/is-builtin-module-1.0.0.tgz#540572d34f7ac3119f8f76c30cbc1b1e037affbe" - dependencies: - builtin-modules "^1.0.0" - -is-ci@^1.0.7: - version "1.0.10" - resolved "https://registry.yarnpkg.com/is-ci/-/is-ci-1.0.10.tgz#f739336b2632365061a9d48270cd56ae3369318e" - dependencies: - ci-info "^1.0.0" - -is-dotfile@^1.0.0: - version "1.0.3" - resolved "https://registry.yarnpkg.com/is-dotfile/-/is-dotfile-1.0.3.tgz#a6a2f32ffd2dfb04f5ca25ecd0f6b83cf798a1e1" - -is-equal-shallow@^0.1.3: - version "0.1.3" - resolved "https://registry.yarnpkg.com/is-equal-shallow/-/is-equal-shallow-0.1.3.tgz#2238098fc221de0bcfa5d9eac4c45d638aa1c534" - dependencies: - is-primitive "^2.0.0" - -is-error@^2.2.0: - version "2.2.1" - resolved "https://registry.yarnpkg.com/is-error/-/is-error-2.2.1.tgz#684a96d84076577c98f4cdb40c6d26a5123bf19c" - -is-extendable@^0.1.1: - version "0.1.1" - resolved "https://registry.yarnpkg.com/is-extendable/-/is-extendable-0.1.1.tgz#62b110e289a471418e3ec36a617d472e301dfc89" - -is-extglob@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/is-extglob/-/is-extglob-1.0.0.tgz#ac468177c4943405a092fc8f29760c6ffc6206c0" - -is-finite@^1.0.0, is-finite@^1.0.1: - version "1.0.2" - resolved "https://registry.yarnpkg.com/is-finite/-/is-finite-1.0.2.tgz#cc6677695602be550ef11e8b4aa6305342b6d0aa" - dependencies: - number-is-nan "^1.0.0" - -is-fullwidth-code-point@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz#ef9e31386f031a7f0d643af82fde50c457ef00cb" - dependencies: - number-is-nan "^1.0.0" - -is-fullwidth-code-point@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz#a3b30a5c4f199183167aaab93beefae3ddfb654f" - -is-generator-fn@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/is-generator-fn/-/is-generator-fn-1.0.0.tgz#969d49e1bb3329f6bb7f09089be26578b2ddd46a" - -is-glob@^2.0.0, is-glob@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-2.0.1.tgz#d096f926a3ded5600f3fdfd91198cb0888c2d863" - dependencies: - is-extglob "^1.0.0" - -is-module@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/is-module/-/is-module-1.0.0.tgz#3258fb69f78c14d5b815d664336b4cffb6441591" - -is-npm@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/is-npm/-/is-npm-1.0.0.tgz#f2fb63a65e4905b406c86072765a1a4dc793b9f4" - -is-number@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/is-number/-/is-number-2.1.0.tgz#01fcbbb393463a548f2f466cce16dece49db908f" - dependencies: - kind-of "^3.0.2" - -is-number@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/is-number/-/is-number-3.0.0.tgz#24fd6201a4782cf50561c810276afc7d12d71195" - dependencies: - kind-of "^3.0.2" - -is-obj@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/is-obj/-/is-obj-1.0.1.tgz#3e4729ac1f5fde025cd7d83a896dab9f4f67db0f" - -is-observable@^0.2.0: - version "0.2.0" - resolved "https://registry.yarnpkg.com/is-observable/-/is-observable-0.2.0.tgz#b361311d83c6e5d726cabf5e250b0237106f5ae2" - dependencies: - symbol-observable "^0.2.2" - -is-path-cwd@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/is-path-cwd/-/is-path-cwd-1.0.0.tgz#d225ec23132e89edd38fda767472e62e65f1106d" - -is-path-in-cwd@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/is-path-in-cwd/-/is-path-in-cwd-1.0.0.tgz#6477582b8214d602346094567003be8a9eac04dc" - dependencies: - is-path-inside "^1.0.0" - -is-path-inside@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/is-path-inside/-/is-path-inside-1.0.0.tgz#fc06e5a1683fbda13de667aff717bbc10a48f37f" - dependencies: - path-is-inside "^1.0.1" - -is-plain-obj@^1.0.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/is-plain-obj/-/is-plain-obj-1.1.0.tgz#71a50c8429dfca773c92a390a4a03b39fcd51d3e" - -is-posix-bracket@^0.1.0: - version "0.1.1" - resolved "https://registry.yarnpkg.com/is-posix-bracket/-/is-posix-bracket-0.1.1.tgz#3334dc79774368e92f016e6fbc0a88f5cd6e6bc4" - -is-primitive@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/is-primitive/-/is-primitive-2.0.0.tgz#207bab91638499c07b2adf240a41a87210034575" - -is-promise@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/is-promise/-/is-promise-2.1.0.tgz#79a2a9ece7f096e80f36d2b2f3bc16c1ff4bf3fa" - -is-redirect@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/is-redirect/-/is-redirect-1.0.0.tgz#1d03dded53bd8db0f30c26e4f95d36fc7c87dc24" - -is-resolvable@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/is-resolvable/-/is-resolvable-1.0.0.tgz#8df57c61ea2e3c501408d100fb013cf8d6e0cc62" - dependencies: - tryit "^1.0.1" - -is-retry-allowed@^1.0.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/is-retry-allowed/-/is-retry-allowed-1.1.0.tgz#11a060568b67339444033d0125a61a20d564fb34" - -is-stream@^1.0.0, is-stream@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/is-stream/-/is-stream-1.1.0.tgz#12d4a3dd4e68e0b79ceb8dbc84173ae80d91ca44" - -is-typedarray@~1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/is-typedarray/-/is-typedarray-1.0.0.tgz#e479c80858df0c1b11ddda6940f96011fcda4a9a" - -is-url@^1.2.1: - version "1.2.2" - resolved "https://registry.yarnpkg.com/is-url/-/is-url-1.2.2.tgz#498905a593bf47cc2d9e7f738372bbf7696c7f26" - -is-utf8@^0.2.0, is-utf8@^0.2.1: - version "0.2.1" - resolved "https://registry.yarnpkg.com/is-utf8/-/is-utf8-0.2.1.tgz#4b0da1442104d1b336340e80797e865cf39f7d72" - -isarray@1.0.0, isarray@^1.0.0, isarray@~1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/isarray/-/isarray-1.0.0.tgz#bb935d48582cba168c06834957a54a3e07124f11" - -isexe@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/isexe/-/isexe-2.0.0.tgz#e8fbf374dc556ff8947a10dcb0572d633f2cfa10" - -isobject@^2.0.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/isobject/-/isobject-2.1.0.tgz#f065561096a3f1da2ef46272f815c840d87e0c89" - dependencies: - isarray "1.0.0" - -isstream@~0.1.2: - version "0.1.2" - resolved "https://registry.yarnpkg.com/isstream/-/isstream-0.1.2.tgz#47e63f7af55afa6f92e1500e690eb8b8529c099a" - -istanbul-lib-coverage@^1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/istanbul-lib-coverage/-/istanbul-lib-coverage-1.1.1.tgz#73bfb998885299415c93d38a3e9adf784a77a9da" - -istanbul-lib-hook@^1.0.7: - version "1.0.7" - resolved "https://registry.yarnpkg.com/istanbul-lib-hook/-/istanbul-lib-hook-1.0.7.tgz#dd6607f03076578fe7d6f2a630cf143b49bacddc" - dependencies: - append-transform "^0.4.0" - -istanbul-lib-instrument@^1.8.0: - version "1.8.0" - resolved "https://registry.yarnpkg.com/istanbul-lib-instrument/-/istanbul-lib-instrument-1.8.0.tgz#66f6c9421cc9ec4704f76f2db084ba9078a2b532" - dependencies: - babel-generator "^6.18.0" - babel-template "^6.16.0" - babel-traverse "^6.18.0" - babel-types "^6.18.0" - babylon "^6.18.0" - istanbul-lib-coverage "^1.1.1" - semver "^5.3.0" - -istanbul-lib-report@^1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/istanbul-lib-report/-/istanbul-lib-report-1.1.1.tgz#f0e55f56655ffa34222080b7a0cd4760e1405fc9" - dependencies: - istanbul-lib-coverage "^1.1.1" - mkdirp "^0.5.1" - path-parse "^1.0.5" - supports-color "^3.1.2" - -istanbul-lib-source-maps@^1.2.1: - version "1.2.1" - resolved "https://registry.yarnpkg.com/istanbul-lib-source-maps/-/istanbul-lib-source-maps-1.2.1.tgz#a6fe1acba8ce08eebc638e572e294d267008aa0c" - dependencies: - debug "^2.6.3" - istanbul-lib-coverage "^1.1.1" - mkdirp "^0.5.1" - rimraf "^2.6.1" - source-map "^0.5.3" - -istanbul-reports@^1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/istanbul-reports/-/istanbul-reports-1.1.1.tgz#042be5c89e175bc3f86523caab29c014e77fee4e" - dependencies: - handlebars "^4.0.3" - -js-string-escape@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/js-string-escape/-/js-string-escape-1.0.1.tgz#e2625badbc0d67c7533e9edc1068c587ae4137ef" - -js-tokens@^3.0.0: - version "3.0.1" - resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-3.0.1.tgz#08e9f132484a2c45a30907e9dc4d5567b7f114d7" - -js-tokens@^3.0.2: - version "3.0.2" - resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-3.0.2.tgz#9866df395102130e38f7f996bceb65443209c25b" - -js-yaml@^3.8.2, js-yaml@^3.9.1: - version "3.9.1" - resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.9.1.tgz#08775cebdfdd359209f0d2acd383c8f86a6904a0" - dependencies: - argparse "^1.0.7" - esprima "^4.0.0" - -jsbn@~0.1.0: - version "0.1.1" - resolved "https://registry.yarnpkg.com/jsbn/-/jsbn-0.1.1.tgz#a5e654c2e5a2deb5f201d96cefbca80c0ef2f513" - -jschardet@^1.4.2: - version "1.5.0" - resolved "https://registry.yarnpkg.com/jschardet/-/jschardet-1.5.0.tgz#a61f310306a5a71188e1b1acd08add3cfbb08b1e" - -jsesc@^1.3.0: - version "1.3.0" - resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-1.3.0.tgz#46c3fec8c1892b12b0833db9bc7622176dbab34b" - -jsesc@~0.5.0: - version "0.5.0" - resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-0.5.0.tgz#e7dee66e35d6fc16f710fe91d5cf69f70f08911d" - -json-schema-traverse@^0.3.0: - version "0.3.1" - resolved "https://registry.yarnpkg.com/json-schema-traverse/-/json-schema-traverse-0.3.1.tgz#349a6d44c53a51de89b40805c5d5e59b417d3340" - -json-schema@0.2.3: - version "0.2.3" - resolved "https://registry.yarnpkg.com/json-schema/-/json-schema-0.2.3.tgz#b480c892e59a2f05954ce727bd3f2a4e882f9e13" - -json-stable-stringify-without-jsonify@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz#9db7b59496ad3f3cfef30a75142d2d930ad72651" - -json-stable-stringify@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/json-stable-stringify/-/json-stable-stringify-1.0.1.tgz#9a759d39c5f2ff503fd5300646ed445f88c4f9af" - dependencies: - jsonify "~0.0.0" - -json-stringify-safe@~5.0.1: - version "5.0.1" - resolved "https://registry.yarnpkg.com/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz#1296a2d58fd45f19a0f6ce01d65701e2c735b6eb" - -json5@^0.5.0, json5@^0.5.1: - version "0.5.1" - resolved "https://registry.yarnpkg.com/json5/-/json5-0.5.1.tgz#1eade7acc012034ad84e2396767ead9fa5495821" - -jsonify@~0.0.0: - version "0.0.0" - resolved "https://registry.yarnpkg.com/jsonify/-/jsonify-0.0.0.tgz#2c74b6ee41d93ca51b7b5aaee8f503631d252a73" - -jsprim@^1.2.2: - version "1.4.0" - resolved "https://registry.yarnpkg.com/jsprim/-/jsprim-1.4.0.tgz#a3b87e40298d8c380552d8cc7628a0bb95a22918" - dependencies: - assert-plus "1.0.0" - extsprintf "1.0.2" - json-schema "0.2.3" - verror "1.3.6" - -kind-of@^3.0.2: - version "3.2.2" - resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-3.2.2.tgz#31ea21a734bab9bbb0f32466d893aea51e4a3c64" - dependencies: - is-buffer "^1.1.5" - -kind-of@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-4.0.0.tgz#20813df3d712928b207378691a45066fae72dd57" - dependencies: - is-buffer "^1.1.5" - -last-line-stream@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/last-line-stream/-/last-line-stream-1.0.0.tgz#d1b64d69f86ff24af2d04883a2ceee14520a5600" - dependencies: - through2 "^2.0.0" - -latest-version@^3.0.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/latest-version/-/latest-version-3.1.0.tgz#a205383fea322b33b5ae3b18abee0dc2f356ee15" - dependencies: - package-json "^4.0.0" - -lazy-cache@^1.0.3: - version "1.0.4" - resolved "https://registry.yarnpkg.com/lazy-cache/-/lazy-cache-1.0.4.tgz#a1d78fc3a50474cb80845d3b3b6e1da49a446e8e" - -lcid@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/lcid/-/lcid-1.0.0.tgz#308accafa0bc483a3867b4b6f2b9506251d1b835" - dependencies: - invert-kv "^1.0.0" - -levn@^0.3.0, levn@~0.3.0: - version "0.3.0" - resolved "https://registry.yarnpkg.com/levn/-/levn-0.3.0.tgz#3b09924edf9f083c0490fdd4c0bc4421e04764ee" - dependencies: - prelude-ls "~1.1.2" - type-check "~0.3.2" - -load-json-file@^1.0.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/load-json-file/-/load-json-file-1.1.0.tgz#956905708d58b4bab4c2261b04f59f31c99374c0" - dependencies: - graceful-fs "^4.1.2" - parse-json "^2.2.0" - pify "^2.0.0" - pinkie-promise "^2.0.0" - strip-bom "^2.0.0" - -load-json-file@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/load-json-file/-/load-json-file-2.0.0.tgz#7947e42149af80d696cbf797bcaabcfe1fe29ca8" - dependencies: - graceful-fs "^4.1.2" - parse-json "^2.2.0" - pify "^2.0.0" - strip-bom "^3.0.0" - -locate-path@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-2.0.0.tgz#2b568b265eec944c6d9c0de9c3dbbbca0354cd8e" - dependencies: - p-locate "^2.0.0" - path-exists "^3.0.0" - -lodash.clonedeep@^4.5.0: - version "4.5.0" - resolved "https://registry.yarnpkg.com/lodash.clonedeep/-/lodash.clonedeep-4.5.0.tgz#e23f3f9c4f8fbdde872529c1071857a086e5ccef" - -lodash.clonedeepwith@^4.5.0: - version "4.5.0" - resolved "https://registry.yarnpkg.com/lodash.clonedeepwith/-/lodash.clonedeepwith-4.5.0.tgz#6ee30573a03a1a60d670a62ef33c10cf1afdbdd4" - -lodash.cond@^4.3.0: - version "4.5.2" - resolved "https://registry.yarnpkg.com/lodash.cond/-/lodash.cond-4.5.2.tgz#f471a1da486be60f6ab955d17115523dd1d255d5" - -lodash.debounce@^4.0.3: - version "4.0.8" - resolved "https://registry.yarnpkg.com/lodash.debounce/-/lodash.debounce-4.0.8.tgz#82d79bff30a67c4005ffd5e2515300ad9ca4d7af" - -lodash.difference@^4.3.0: - version "4.5.0" - resolved "https://registry.yarnpkg.com/lodash.difference/-/lodash.difference-4.5.0.tgz#9ccb4e505d486b91651345772885a2df27fd017c" - -lodash.flatten@^4.2.0: - version "4.4.0" - resolved "https://registry.yarnpkg.com/lodash.flatten/-/lodash.flatten-4.4.0.tgz#f31c22225a9632d2bbf8e4addbef240aa765a61f" - -lodash.flattendeep@^4.4.0: - version "4.4.0" - resolved "https://registry.yarnpkg.com/lodash.flattendeep/-/lodash.flattendeep-4.4.0.tgz#fb030917f86a3134e5bc9bec0d69e0013ddfedb2" - -lodash.isequal@^4.5.0: - version "4.5.0" - resolved "https://registry.yarnpkg.com/lodash.isequal/-/lodash.isequal-4.5.0.tgz#415c4478f2bcc30120c22ce10ed3226f7d3e18e0" - -lodash.isplainobject@^4.0.6: - version "4.0.6" - resolved "https://registry.yarnpkg.com/lodash.isplainobject/-/lodash.isplainobject-4.0.6.tgz#7c526a52d89b45c45cc690b88163be0497f550cb" - -lodash.merge@^4.6.0: - version "4.6.0" - resolved "https://registry.yarnpkg.com/lodash.merge/-/lodash.merge-4.6.0.tgz#69884ba144ac33fe699737a6086deffadd0f89c5" - -lodash.some@^4.6.0: - version "4.6.0" - resolved "https://registry.yarnpkg.com/lodash.some/-/lodash.some-4.6.0.tgz#1bb9f314ef6b8baded13b549169b2a945eb68e4d" - -lodash@^4.17.4, lodash@^4.2.0, lodash@^4.3.0: - version "4.17.4" - resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.4.tgz#78203a4d1c328ae1d86dca6460e369b57f4055ae" - -longest@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/longest/-/longest-1.0.1.tgz#30a0b2da38f73770e8294a0d22e6625ed77d0097" - -loose-envify@^1.0.0: - version "1.3.1" - resolved "https://registry.yarnpkg.com/loose-envify/-/loose-envify-1.3.1.tgz#d1a8ad33fa9ce0e713d65fdd0ac8b748d478c848" - dependencies: - js-tokens "^3.0.0" - -loud-rejection@^1.0.0, loud-rejection@^1.2.0: - version "1.6.0" - resolved "https://registry.yarnpkg.com/loud-rejection/-/loud-rejection-1.6.0.tgz#5b46f80147edee578870f086d04821cf998e551f" - dependencies: - currently-unhandled "^0.4.1" - signal-exit "^3.0.0" - -lowercase-keys@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/lowercase-keys/-/lowercase-keys-1.0.0.tgz#4e3366b39e7f5457e35f1324bdf6f88d0bfc7306" - -lru-cache@^4.0.0, lru-cache@^4.0.1: - version "4.1.1" - resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-4.1.1.tgz#622e32e82488b49279114a4f9ecf45e7cd6bba55" - dependencies: - pseudomap "^1.0.2" - yallist "^2.1.2" - -magic-string@^0.22.4: - version "0.22.4" - resolved "https://registry.yarnpkg.com/magic-string/-/magic-string-0.22.4.tgz#31039b4e40366395618c1d6cf8193c53917475ff" - dependencies: - vlq "^0.2.1" - -make-dir@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/make-dir/-/make-dir-1.0.0.tgz#97a011751e91dd87cfadef58832ebb04936de978" - dependencies: - pify "^2.3.0" - -map-obj@^1.0.0, map-obj@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/map-obj/-/map-obj-1.0.1.tgz#d933ceb9205d82bdcf4886f6742bdc2b4dea146d" - -matcher@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/matcher/-/matcher-1.0.0.tgz#aaf0c4816eb69b92094674175625f3466b0e3e19" - dependencies: - escape-string-regexp "^1.0.4" - -md5-hex@^1.2.0, md5-hex@^1.3.0: - version "1.3.0" - resolved "https://registry.yarnpkg.com/md5-hex/-/md5-hex-1.3.0.tgz#d2c4afe983c4370662179b8cad145219135046c4" - dependencies: - md5-o-matic "^0.1.1" - -md5-hex@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/md5-hex/-/md5-hex-2.0.0.tgz#d0588e9f1c74954492ecd24ac0ac6ce997d92e33" - dependencies: - md5-o-matic "^0.1.1" - -md5-o-matic@^0.1.1: - version "0.1.1" - resolved "https://registry.yarnpkg.com/md5-o-matic/-/md5-o-matic-0.1.1.tgz#822bccd65e117c514fab176b25945d54100a03c3" - -mem@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/mem/-/mem-1.1.0.tgz#5edd52b485ca1d900fe64895505399a0dfa45f76" - dependencies: - mimic-fn "^1.0.0" - -meow@^3.7.0: - version "3.7.0" - resolved "https://registry.yarnpkg.com/meow/-/meow-3.7.0.tgz#72cb668b425228290abbfa856892587308a801fb" - dependencies: - camelcase-keys "^2.0.0" - decamelize "^1.1.2" - loud-rejection "^1.0.0" - map-obj "^1.0.1" - minimist "^1.1.3" - normalize-package-data "^2.3.4" - object-assign "^4.0.1" - read-pkg-up "^1.0.1" - redent "^1.0.0" - trim-newlines "^1.0.0" - -merge-source-map@^1.0.2: - version "1.0.4" - resolved "https://registry.yarnpkg.com/merge-source-map/-/merge-source-map-1.0.4.tgz#a5de46538dae84d4114cc5ea02b4772a6346701f" - dependencies: - source-map "^0.5.6" - -micromatch@^2.1.5, micromatch@^2.3.11: - version "2.3.11" - resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-2.3.11.tgz#86677c97d1720b363431d04d0d15293bd38c1565" - dependencies: - arr-diff "^2.0.0" - array-unique "^0.2.1" - braces "^1.8.2" - expand-brackets "^0.1.4" - extglob "^0.3.1" - filename-regex "^2.0.0" - is-extglob "^1.0.0" - is-glob "^2.0.1" - kind-of "^3.0.2" - normalize-path "^2.0.1" - object.omit "^2.0.0" - parse-glob "^3.0.4" - regex-cache "^0.4.2" - -mime-db@~1.27.0: - version "1.27.0" - resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.27.0.tgz#820f572296bbd20ec25ed55e5b5de869e5436eb1" - -mime-types@^2.1.12, mime-types@~2.1.7: - version "2.1.15" - resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.15.tgz#a4ebf5064094569237b8cf70046776d09fc92aed" - dependencies: - mime-db "~1.27.0" - -mimic-fn@^1.0.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/mimic-fn/-/mimic-fn-1.1.0.tgz#e667783d92e89dbd342818b5230b9d62a672ad18" - -minimatch@^3.0.0, minimatch@^3.0.2, minimatch@^3.0.3, minimatch@^3.0.4: - version "3.0.4" - resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.0.4.tgz#5166e286457f03306064be5497e8dbb0c3d32083" - dependencies: - brace-expansion "^1.1.7" - -minimist@0.0.8, minimist@~0.0.1: - version "0.0.8" - resolved "https://registry.yarnpkg.com/minimist/-/minimist-0.0.8.tgz#857fcabfc3397d2625b8228262e86aa7a011b05d" - -minimist@^1.1.3, minimist@^1.2.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.0.tgz#a35008b20f41383eec1fb914f4cd5df79a264284" - -"mkdirp@>=0.5 0", mkdirp@^0.5.0, mkdirp@^0.5.1: - version "0.5.1" - resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.5.1.tgz#30057438eac6cf7f8c4767f38648d6697d75c903" - dependencies: - minimist "0.0.8" - -ms@2.0.0, ms@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/ms/-/ms-2.0.0.tgz#5608aeadfc00be6c2901df5f9861788de0d597c8" - -ms@^2.1.1: - version "2.1.1" - resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.1.tgz#30a5864eb3ebb0a66f2ebe6d727af06a09d86e0a" - -multimatch@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/multimatch/-/multimatch-2.1.0.tgz#9c7906a22fb4c02919e2f5f75161b4cdbd4b2a2b" - dependencies: - array-differ "^1.0.0" - array-union "^1.0.1" - arrify "^1.0.0" - minimatch "^3.0.0" - -mute-stream@0.0.7: - version "0.0.7" - resolved "https://registry.yarnpkg.com/mute-stream/-/mute-stream-0.0.7.tgz#3075ce93bc21b8fab43e1bc4da7e8115ed1e7bab" - -nan@^2.3.0: - version "2.6.2" - resolved "https://registry.yarnpkg.com/nan/-/nan-2.6.2.tgz#e4ff34e6c95fdfb5aecc08de6596f43605a7db45" - -natural-compare@^1.4.0: - version "1.4.0" - resolved "https://registry.yarnpkg.com/natural-compare/-/natural-compare-1.4.0.tgz#4abebfeed7541f2c27acfb29bdbbd15c8d5ba4f7" - -node-pre-gyp@^0.6.36: - version "0.6.36" - resolved "https://registry.yarnpkg.com/node-pre-gyp/-/node-pre-gyp-0.6.36.tgz#db604112cb74e0d477554e9b505b17abddfab786" - dependencies: - mkdirp "^0.5.1" - nopt "^4.0.1" - npmlog "^4.0.2" - rc "^1.1.7" - request "^2.81.0" - rimraf "^2.6.1" - semver "^5.3.0" - tar "^2.2.1" - tar-pack "^3.4.0" - -nopt@^4.0.1: - version "4.0.1" - resolved "https://registry.yarnpkg.com/nopt/-/nopt-4.0.1.tgz#d0d4685afd5415193c8c7505602d0d17cd64474d" - dependencies: - abbrev "1" - osenv "^0.1.4" - -normalize-package-data@^2.3.2, normalize-package-data@^2.3.4: - version "2.3.8" - resolved "https://registry.yarnpkg.com/normalize-package-data/-/normalize-package-data-2.3.8.tgz#d819eda2a9dedbd1ffa563ea4071d936782295bb" - dependencies: - hosted-git-info "^2.1.4" - is-builtin-module "^1.0.0" - semver "2 || 3 || 4 || 5" - validate-npm-package-license "^3.0.1" - -normalize-path@^2.0.1: - version "2.1.1" - resolved "https://registry.yarnpkg.com/normalize-path/-/normalize-path-2.1.1.tgz#1ab28b556e198363a8c1a6f7e6fa20137fe6aed9" - dependencies: - remove-trailing-separator "^1.0.1" - -npm-run-path@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/npm-run-path/-/npm-run-path-1.0.0.tgz#f5c32bf595fe81ae927daec52e82f8b000ac3c8f" - dependencies: - path-key "^1.0.0" - -npm-run-path@^2.0.0: - version "2.0.2" - resolved "https://registry.yarnpkg.com/npm-run-path/-/npm-run-path-2.0.2.tgz#35a9232dfa35d7067b4cb2ddf2357b1871536c5f" - dependencies: - path-key "^2.0.0" - -npmlog@^4.0.2: - version "4.1.0" - resolved "https://registry.yarnpkg.com/npmlog/-/npmlog-4.1.0.tgz#dc59bee85f64f00ed424efb2af0783df25d1c0b5" - dependencies: - are-we-there-yet "~1.1.2" - console-control-strings "~1.1.0" - gauge "~2.7.3" - set-blocking "~2.0.0" - -number-is-nan@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/number-is-nan/-/number-is-nan-1.0.1.tgz#097b602b53422a522c1afb8790318336941a011d" - -nyc@^11.2.1: - version "11.2.1" - resolved "https://registry.yarnpkg.com/nyc/-/nyc-11.2.1.tgz#ad850afe9dbad7f4970728b4b2e47fed1c38721c" - dependencies: - archy "^1.0.0" - arrify "^1.0.1" - caching-transform "^1.0.0" - convert-source-map "^1.3.0" - debug-log "^1.0.1" - default-require-extensions "^1.0.0" - find-cache-dir "^0.1.1" - find-up "^2.1.0" - foreground-child "^1.5.3" - glob "^7.0.6" - istanbul-lib-coverage "^1.1.1" - istanbul-lib-hook "^1.0.7" - istanbul-lib-instrument "^1.8.0" - istanbul-lib-report "^1.1.1" - istanbul-lib-source-maps "^1.2.1" - istanbul-reports "^1.1.1" - md5-hex "^1.2.0" - merge-source-map "^1.0.2" - micromatch "^2.3.11" - mkdirp "^0.5.0" - resolve-from "^2.0.0" - rimraf "^2.5.4" - signal-exit "^3.0.1" - spawn-wrap "^1.3.8" - test-exclude "^4.1.1" - yargs "^8.0.1" - yargs-parser "^5.0.0" - -oauth-sign@~0.8.1: - version "0.8.2" - resolved "https://registry.yarnpkg.com/oauth-sign/-/oauth-sign-0.8.2.tgz#46a6ab7f0aead8deae9ec0565780b7d4efeb9d43" - -object-assign@^4.0.1, object-assign@^4.1.0: - version "4.1.1" - resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-4.1.1.tgz#2109adc7965887cfc05cbbd442cac8bfbb360863" - -object.omit@^2.0.0: - version "2.0.1" - resolved "https://registry.yarnpkg.com/object.omit/-/object.omit-2.0.1.tgz#1a9c744829f39dbb858c76ca3579ae2a54ebd1fa" - dependencies: - for-own "^0.1.4" - is-extendable "^0.1.1" - -observable-to-promise@^0.5.0: - version "0.5.0" - resolved "https://registry.yarnpkg.com/observable-to-promise/-/observable-to-promise-0.5.0.tgz#c828f0f0dc47e9f86af8a4977c5d55076ce7a91f" - dependencies: - is-observable "^0.2.0" - symbol-observable "^1.0.4" - -once@^1.3.0, once@^1.3.3: - version "1.4.0" - resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1" - dependencies: - wrappy "1" - -onetime@^2.0.0: - version "2.0.1" - resolved "https://registry.yarnpkg.com/onetime/-/onetime-2.0.1.tgz#067428230fd67443b2794b22bba528b6867962d4" - dependencies: - mimic-fn "^1.0.0" - -optimist@^0.6.1: - version "0.6.1" - resolved "https://registry.yarnpkg.com/optimist/-/optimist-0.6.1.tgz#da3ea74686fa21a19a111c326e90eb15a0196686" - dependencies: - minimist "~0.0.1" - wordwrap "~0.0.2" - -option-chain@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/option-chain/-/option-chain-1.0.0.tgz#938d73bd4e1783f948d34023644ada23669e30f2" - -optionator@^0.8.2: - version "0.8.2" - resolved "https://registry.yarnpkg.com/optionator/-/optionator-0.8.2.tgz#364c5e409d3f4d6301d6c0b4c05bba50180aeb64" - dependencies: - deep-is "~0.1.3" - fast-levenshtein "~2.0.4" - levn "~0.3.0" - prelude-ls "~1.1.2" - type-check "~0.3.2" - wordwrap "~1.0.0" - -os-homedir@^1.0.0, os-homedir@^1.0.1: - version "1.0.2" - resolved "https://registry.yarnpkg.com/os-homedir/-/os-homedir-1.0.2.tgz#ffbc4988336e0e833de0c168c7ef152121aa7fb3" - -os-locale@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/os-locale/-/os-locale-2.0.0.tgz#15918ded510522b81ee7ae5a309d54f639fc39a4" - dependencies: - execa "^0.5.0" - lcid "^1.0.0" - mem "^1.1.0" - -os-tmpdir@^1.0.0, os-tmpdir@^1.0.1, os-tmpdir@~1.0.1: - version "1.0.2" - resolved "https://registry.yarnpkg.com/os-tmpdir/-/os-tmpdir-1.0.2.tgz#bbe67406c79aa85c5cfec766fe5734555dfa1274" - -osenv@^0.1.4: - version "0.1.4" - resolved "https://registry.yarnpkg.com/osenv/-/osenv-0.1.4.tgz#42fe6d5953df06c8064be6f176c3d05aaaa34644" - dependencies: - os-homedir "^1.0.0" - os-tmpdir "^1.0.0" - -p-finally@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/p-finally/-/p-finally-1.0.0.tgz#3fbcfb15b899a44123b34b6dcc18b724336a2cae" - -p-limit@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-1.1.0.tgz#b07ff2d9a5d88bec806035895a2bab66a27988bc" - -p-locate@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-2.0.0.tgz#20a0103b222a70c8fd39cc2e580680f3dde5ec43" - dependencies: - p-limit "^1.1.0" - -package-hash@^1.2.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/package-hash/-/package-hash-1.2.0.tgz#003e56cd57b736a6ed6114cc2b81542672770e44" - dependencies: - md5-hex "^1.3.0" - -package-hash@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/package-hash/-/package-hash-2.0.0.tgz#78ae326c89e05a4d813b68601977af05c00d2a0d" - dependencies: - graceful-fs "^4.1.11" - lodash.flattendeep "^4.4.0" - md5-hex "^2.0.0" - release-zalgo "^1.0.0" - -package-json@^4.0.0: - version "4.0.1" - resolved "https://registry.yarnpkg.com/package-json/-/package-json-4.0.1.tgz#8869a0401253661c4c4ca3da6c2121ed555f5eed" - dependencies: - got "^6.7.1" - registry-auth-token "^3.0.1" - registry-url "^3.0.3" - semver "^5.1.0" - -parse-glob@^3.0.4: - version "3.0.4" - resolved "https://registry.yarnpkg.com/parse-glob/-/parse-glob-3.0.4.tgz#b2c376cfb11f35513badd173ef0bb6e3a388391c" - dependencies: - glob-base "^0.3.0" - is-dotfile "^1.0.0" - is-extglob "^1.0.0" - is-glob "^2.0.0" - -parse-json@^2.2.0: - version "2.2.0" - resolved "https://registry.yarnpkg.com/parse-json/-/parse-json-2.2.0.tgz#f480f40434ef80741f8469099f8dea18f55a4dc9" - dependencies: - error-ex "^1.2.0" - -parse-ms@^0.1.0: - version "0.1.2" - resolved "https://registry.yarnpkg.com/parse-ms/-/parse-ms-0.1.2.tgz#dd3fa25ed6c2efc7bdde12ad9b46c163aa29224e" - -parse-ms@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/parse-ms/-/parse-ms-1.0.1.tgz#56346d4749d78f23430ca0c713850aef91aa361d" - -path-exists@^2.0.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-2.1.0.tgz#0feb6c64f0fc518d9a754dd5efb62c7022761f4b" - dependencies: - pinkie-promise "^2.0.0" - -path-exists@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-3.0.0.tgz#ce0ebeaa5f78cb18925ea7d810d7b59b010fd515" - -path-is-absolute@^1.0.0, path-is-absolute@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f" - -path-is-inside@^1.0.1, path-is-inside@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/path-is-inside/-/path-is-inside-1.0.2.tgz#365417dede44430d1c11af61027facf074bdfc53" - -path-key@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/path-key/-/path-key-1.0.0.tgz#5d53d578019646c0d68800db4e146e6bdc2ac7af" - -path-key@^2.0.0: - version "2.0.1" - resolved "https://registry.yarnpkg.com/path-key/-/path-key-2.0.1.tgz#411cadb574c5a140d3a4b1910d40d80cc9f40b40" - -path-parse@^1.0.5: - version "1.0.5" - resolved "https://registry.yarnpkg.com/path-parse/-/path-parse-1.0.5.tgz#3c1adf871ea9cd6c9431b6ea2bd74a0ff055c4c1" - -path-type@^1.0.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/path-type/-/path-type-1.1.0.tgz#59c44f7ee491da704da415da5a4070ba4f8fe441" - dependencies: - graceful-fs "^4.1.2" - pify "^2.0.0" - pinkie-promise "^2.0.0" - -path-type@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/path-type/-/path-type-2.0.0.tgz#f012ccb8415b7096fc2daa1054c3d72389594c73" - dependencies: - pify "^2.0.0" - -performance-now@^0.2.0: - version "0.2.0" - resolved "https://registry.yarnpkg.com/performance-now/-/performance-now-0.2.0.tgz#33ef30c5c77d4ea21c5a53869d91b56d8f2555e5" - -pify@^2.0.0, pify@^2.3.0: - version "2.3.0" - resolved "https://registry.yarnpkg.com/pify/-/pify-2.3.0.tgz#ed141a6ac043a849ea588498e7dca8b15330e90c" - -pinkie-promise@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/pinkie-promise/-/pinkie-promise-1.0.0.tgz#d1da67f5482563bb7cf57f286ae2822ecfbf3670" - dependencies: - pinkie "^1.0.0" - -pinkie-promise@^2.0.0: - version "2.0.1" - resolved "https://registry.yarnpkg.com/pinkie-promise/-/pinkie-promise-2.0.1.tgz#2135d6dfa7a358c069ac9b178776288228450ffa" - dependencies: - pinkie "^2.0.0" - -pinkie@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/pinkie/-/pinkie-1.0.0.tgz#5a47f28ba1015d0201bda7bf0f358e47bec8c7e4" - -pinkie@^2.0.0: - version "2.0.4" - resolved "https://registry.yarnpkg.com/pinkie/-/pinkie-2.0.4.tgz#72556b80cfa0d48a974e80e77248e80ed4f7f870" - -pkg-conf@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/pkg-conf/-/pkg-conf-2.0.0.tgz#071c87650403bccfb9c627f58751bfe47c067279" - dependencies: - find-up "^2.0.0" - load-json-file "^2.0.0" - -pkg-dir@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/pkg-dir/-/pkg-dir-1.0.0.tgz#7a4b508a8d5bb2d629d447056ff4e9c9314cf3d4" - dependencies: - find-up "^1.0.0" - -pkg-dir@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/pkg-dir/-/pkg-dir-2.0.0.tgz#f6d5d1109e19d63edf428e0bd57e12777615334b" - dependencies: - find-up "^2.1.0" - -plur@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/plur/-/plur-1.0.0.tgz#db85c6814f5e5e5a3b49efc28d604fec62975156" - -plur@^2.0.0: - version "2.1.2" - resolved "https://registry.yarnpkg.com/plur/-/plur-2.1.2.tgz#7482452c1a0f508e3e344eaec312c91c29dc655a" - dependencies: - irregular-plurals "^1.0.0" - -pluralize@^7.0.0: - version "7.0.0" - resolved "https://registry.yarnpkg.com/pluralize/-/pluralize-7.0.0.tgz#298b89df8b93b0221dbf421ad2b1b1ea23fc6777" - -prelude-ls@~1.1.2: - version "1.1.2" - resolved "https://registry.yarnpkg.com/prelude-ls/-/prelude-ls-1.1.2.tgz#21932a549f5e52ffd9a827f570e04be62a97da54" - -prepend-http@^1.0.1: - version "1.0.4" - resolved "https://registry.yarnpkg.com/prepend-http/-/prepend-http-1.0.4.tgz#d4f4562b0ce3696e41ac52d0e002e57a635dc6dc" - -preserve@^0.2.0: - version "0.2.0" - resolved "https://registry.yarnpkg.com/preserve/-/preserve-0.2.0.tgz#815ed1f6ebc65926f865b310c0713bcb3315ce4b" - -pretty-ms@^0.2.1: - version "0.2.2" - resolved "https://registry.yarnpkg.com/pretty-ms/-/pretty-ms-0.2.2.tgz#da879a682ff33a37011046f13d627f67c73b84f6" - dependencies: - parse-ms "^0.1.0" - -pretty-ms@^2.0.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/pretty-ms/-/pretty-ms-2.1.0.tgz#4257c256df3fb0b451d6affaab021884126981dc" - dependencies: - is-finite "^1.0.1" - parse-ms "^1.0.0" - plur "^1.0.0" - -private@^0.1.6, private@^0.1.7: - version "0.1.7" - resolved "https://registry.yarnpkg.com/private/-/private-0.1.7.tgz#68ce5e8a1ef0a23bb570cc28537b5332aba63ef1" - -process-nextick-args@~1.0.6: - version "1.0.7" - resolved "https://registry.yarnpkg.com/process-nextick-args/-/process-nextick-args-1.0.7.tgz#150e20b756590ad3f91093f25a4f2ad8bff30ba3" - -progress@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/progress/-/progress-2.0.0.tgz#8a1be366bf8fc23db2bd23f10c6fe920b4389d1f" - -pseudomap@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/pseudomap/-/pseudomap-1.0.2.tgz#f052a28da70e618917ef0a8ac34c1ae5a68286b3" - -punycode@^1.4.1: - version "1.4.1" - resolved "https://registry.yarnpkg.com/punycode/-/punycode-1.4.1.tgz#c0d5a63b2718800ad8e1eb0fa5269c84dd41845e" - -qs@~6.4.0: - version "6.4.0" - resolved "https://registry.yarnpkg.com/qs/-/qs-6.4.0.tgz#13e26d28ad6b0ffaa91312cd3bf708ed351e7233" - -randomatic@^1.1.3: - version "1.1.7" - resolved "https://registry.yarnpkg.com/randomatic/-/randomatic-1.1.7.tgz#c7abe9cc8b87c0baa876b19fde83fd464797e38c" - dependencies: - is-number "^3.0.0" - kind-of "^4.0.0" - -rc@^1.0.1, rc@^1.1.6, rc@^1.1.7: - version "1.2.1" - resolved "https://registry.yarnpkg.com/rc/-/rc-1.2.1.tgz#2e03e8e42ee450b8cb3dce65be1bf8974e1dfd95" - dependencies: - deep-extend "~0.4.0" - ini "~1.3.0" - minimist "^1.2.0" - strip-json-comments "~2.0.1" - -read-pkg-up@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/read-pkg-up/-/read-pkg-up-1.0.1.tgz#9d63c13276c065918d57f002a57f40a1b643fb02" - dependencies: - find-up "^1.0.0" - read-pkg "^1.0.0" - -read-pkg-up@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/read-pkg-up/-/read-pkg-up-2.0.0.tgz#6b72a8048984e0c41e79510fd5e9fa99b3b549be" - dependencies: - find-up "^2.0.0" - read-pkg "^2.0.0" - -read-pkg@^1.0.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/read-pkg/-/read-pkg-1.1.0.tgz#f5ffaa5ecd29cb31c0474bca7d756b6bb29e3f28" - dependencies: - load-json-file "^1.0.0" - normalize-package-data "^2.3.2" - path-type "^1.0.0" - -read-pkg@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/read-pkg/-/read-pkg-2.0.0.tgz#8ef1c0623c6a6db0dc6713c4bfac46332b2368f8" - dependencies: - load-json-file "^2.0.0" - normalize-package-data "^2.3.2" - path-type "^2.0.0" - -readable-stream@^2.0.2, readable-stream@^2.0.6, readable-stream@^2.1.4, readable-stream@^2.1.5, readable-stream@^2.2.2: - version "2.3.2" - resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.3.2.tgz#5a04df05e4f57fe3f0dc68fdd11dc5c97c7e6f4d" - dependencies: - core-util-is "~1.0.0" - inherits "~2.0.3" - isarray "~1.0.0" - process-nextick-args "~1.0.6" - safe-buffer "~5.1.0" - string_decoder "~1.0.0" - util-deprecate "~1.0.1" - -readdirp@^2.0.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/readdirp/-/readdirp-2.1.0.tgz#4ed0ad060df3073300c48440373f72d1cc642d78" - dependencies: - graceful-fs "^4.1.2" - minimatch "^3.0.2" - readable-stream "^2.0.2" - set-immediate-shim "^1.0.1" - -redent@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/redent/-/redent-1.0.0.tgz#cf916ab1fd5f1f16dfb20822dd6ec7f730c2afde" - dependencies: - indent-string "^2.1.0" - strip-indent "^1.0.1" - -regenerate@^1.2.1: - version "1.3.2" - resolved "https://registry.yarnpkg.com/regenerate/-/regenerate-1.3.2.tgz#d1941c67bad437e1be76433add5b385f95b19260" - -regenerator-runtime@^0.10.0: - version "0.10.5" - resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.10.5.tgz#336c3efc1220adcedda2c9fab67b5a7955a33658" - -regenerator-runtime@^0.11.0: - version "0.11.0" - resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.11.0.tgz#7e54fe5b5ccd5d6624ea6255c3473be090b802e1" - -regenerator-transform@0.9.11: - version "0.9.11" - resolved "https://registry.yarnpkg.com/regenerator-transform/-/regenerator-transform-0.9.11.tgz#3a7d067520cb7b7176769eb5ff868691befe1283" - dependencies: - babel-runtime "^6.18.0" - babel-types "^6.19.0" - private "^0.1.6" - -regex-cache@^0.4.2: - version "0.4.3" - resolved "https://registry.yarnpkg.com/regex-cache/-/regex-cache-0.4.3.tgz#9b1a6c35d4d0dfcef5711ae651e8e9d3d7114145" - dependencies: - is-equal-shallow "^0.1.3" - is-primitive "^2.0.0" - -regexpp@^1.0.1: - version "1.1.0" - resolved "https://registry.yarnpkg.com/regexpp/-/regexpp-1.1.0.tgz#0e3516dd0b7904f413d2d4193dce4618c3a689ab" - -regexpu-core@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/regexpu-core/-/regexpu-core-2.0.0.tgz#49d038837b8dcf8bfa5b9a42139938e6ea2ae240" - dependencies: - regenerate "^1.2.1" - regjsgen "^0.2.0" - regjsparser "^0.1.4" - -registry-auth-token@^3.0.1: - version "3.3.1" - resolved "https://registry.yarnpkg.com/registry-auth-token/-/registry-auth-token-3.3.1.tgz#fb0d3289ee0d9ada2cbb52af5dfe66cb070d3006" - dependencies: - rc "^1.1.6" - safe-buffer "^5.0.1" - -registry-url@^3.0.3: - version "3.1.0" - resolved "https://registry.yarnpkg.com/registry-url/-/registry-url-3.1.0.tgz#3d4ef870f73dde1d77f0cf9a381432444e174942" - dependencies: - rc "^1.0.1" - -regjsgen@^0.2.0: - version "0.2.0" - resolved "https://registry.yarnpkg.com/regjsgen/-/regjsgen-0.2.0.tgz#6c016adeac554f75823fe37ac05b92d5a4edb1f7" - -regjsparser@^0.1.4: - version "0.1.5" - resolved "https://registry.yarnpkg.com/regjsparser/-/regjsparser-0.1.5.tgz#7ee8f84dc6fa792d3fd0ae228d24bd949ead205c" - dependencies: - jsesc "~0.5.0" - -release-zalgo@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/release-zalgo/-/release-zalgo-1.0.0.tgz#09700b7e5074329739330e535c5a90fb67851730" - dependencies: - es6-error "^4.0.1" - -remove-trailing-separator@^1.0.1: - version "1.0.2" - resolved "https://registry.yarnpkg.com/remove-trailing-separator/-/remove-trailing-separator-1.0.2.tgz#69b062d978727ad14dc6b56ba4ab772fd8d70511" - -repeat-element@^1.1.2: - version "1.1.2" - resolved "https://registry.yarnpkg.com/repeat-element/-/repeat-element-1.1.2.tgz#ef089a178d1483baae4d93eb98b4f9e4e11d990a" - -repeat-string@^1.5.2: - version "1.6.1" - resolved "https://registry.yarnpkg.com/repeat-string/-/repeat-string-1.6.1.tgz#8dcae470e1c88abc2d600fff4a776286da75e637" - -repeating@^2.0.0: - version "2.0.1" - resolved "https://registry.yarnpkg.com/repeating/-/repeating-2.0.1.tgz#5214c53a926d3552707527fbab415dbc08d06dda" - dependencies: - is-finite "^1.0.0" - -request@^2.81.0: - version "2.81.0" - resolved "https://registry.yarnpkg.com/request/-/request-2.81.0.tgz#c6928946a0e06c5f8d6f8a9333469ffda46298a0" - dependencies: - aws-sign2 "~0.6.0" - aws4 "^1.2.1" - caseless "~0.12.0" - combined-stream "~1.0.5" - extend "~3.0.0" - forever-agent "~0.6.1" - form-data "~2.1.1" - har-validator "~4.2.1" - hawk "~3.1.3" - http-signature "~1.1.0" - is-typedarray "~1.0.0" - isstream "~0.1.2" - json-stringify-safe "~5.0.1" - mime-types "~2.1.7" - oauth-sign "~0.8.1" - performance-now "^0.2.0" - qs "~6.4.0" - safe-buffer "^5.0.1" - stringstream "~0.0.4" - tough-cookie "~2.3.0" - tunnel-agent "^0.6.0" - uuid "^3.0.0" - -require-directory@^2.1.1: - version "2.1.1" - resolved "https://registry.yarnpkg.com/require-directory/-/require-directory-2.1.1.tgz#8c64ad5fd30dab1c976e2344ffe7f792a6a6df42" - -require-main-filename@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/require-main-filename/-/require-main-filename-1.0.1.tgz#97f717b69d48784f5f526a6c5aa8ffdda055a4d1" - -require-precompiled@^0.1.0: - version "0.1.0" - resolved "https://registry.yarnpkg.com/require-precompiled/-/require-precompiled-0.1.0.tgz#5a1b52eb70ebed43eb982e974c85ab59571e56fa" - -require-uncached@^1.0.3: - version "1.0.3" - resolved "https://registry.yarnpkg.com/require-uncached/-/require-uncached-1.0.3.tgz#4e0d56d6c9662fd31e43011c4b95aa49955421d3" - dependencies: - caller-path "^0.1.0" - resolve-from "^1.0.0" - -resolve-cwd@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/resolve-cwd/-/resolve-cwd-2.0.0.tgz#00a9f7387556e27038eae232caa372a6a59b665a" - dependencies: - resolve-from "^3.0.0" - -resolve-from@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-1.0.1.tgz#26cbfe935d1aeeeabb29bc3fe5aeb01e93d44226" - -resolve-from@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-2.0.0.tgz#9480ab20e94ffa1d9e80a804c7ea147611966b57" - -resolve-from@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-3.0.0.tgz#b22c7af7d9d6881bc8b6e653335eebcb0a188748" - -resolve@1.1.7: - version "1.1.7" - resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.1.7.tgz#203114d82ad2c5ed9e8e0411b3932875e889e97b" - -resolve@^1.1.6, resolve@^1.2.0: - version "1.3.3" - resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.3.3.tgz#655907c3469a8680dc2de3a275a8fdd69691f0e5" - dependencies: - path-parse "^1.0.5" - -resolve@^1.4.0: - version "1.4.0" - resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.4.0.tgz#a75be01c53da25d934a98ebd0e4c4a7312f92a86" - dependencies: - path-parse "^1.0.5" - -restore-cursor@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/restore-cursor/-/restore-cursor-2.0.0.tgz#9f7ee287f82fd326d4fd162923d62129eee0dfaf" - dependencies: - onetime "^2.0.0" - signal-exit "^3.0.2" - -right-align@^0.1.1: - version "0.1.3" - resolved "https://registry.yarnpkg.com/right-align/-/right-align-0.1.3.tgz#61339b722fe6a3515689210d24e14c96148613ef" - dependencies: - align-text "^0.1.1" - -rimraf@2: - version "2.6.3" - resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.6.3.tgz#b2d104fe0d8fb27cf9e0a1cda8262dd3833c6cab" - dependencies: - glob "^7.1.3" - -rimraf@^2.2.8, rimraf@^2.3.3, rimraf@^2.5.1, rimraf@^2.5.4, rimraf@^2.6.1: - version "2.6.1" - resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.6.1.tgz#c2338ec643df7a1b7fe5c54fa86f57428a55f33d" - dependencies: - glob "^7.0.5" - -rollup-plugin-babel-minify@^3.1.2: - version "3.1.2" - resolved "https://registry.yarnpkg.com/rollup-plugin-babel-minify/-/rollup-plugin-babel-minify-3.1.2.tgz#86a99d00b3d60984281baaeff4eb1f0eb509b053" - dependencies: - "@comandeer/babel-plugin-banner" "^1.0.0" - babel-core "^6.21.0" - babel-preset-minify "^0.2.0" - -rollup-plugin-babel@^3.0.2: - version "3.0.2" - resolved "https://registry.yarnpkg.com/rollup-plugin-babel/-/rollup-plugin-babel-3.0.2.tgz#a2765dea0eaa8aece351c983573300d17497495b" - dependencies: - rollup-pluginutils "^1.5.0" - -rollup-plugin-commonjs@^8.2.1: - version "8.2.1" - resolved "https://registry.yarnpkg.com/rollup-plugin-commonjs/-/rollup-plugin-commonjs-8.2.1.tgz#5e40c78375eb163c14c76bce69da1750e5905a2e" - dependencies: - acorn "^5.1.1" - estree-walker "^0.5.0" - magic-string "^0.22.4" - resolve "^1.4.0" - rollup-pluginutils "^2.0.1" - -rollup-plugin-node-resolve@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/rollup-plugin-node-resolve/-/rollup-plugin-node-resolve-3.0.0.tgz#8b897c4c3030d5001277b0514b25d2ca09683ee0" - dependencies: - browser-resolve "^1.11.0" - builtin-modules "^1.1.0" - is-module "^1.0.0" - resolve "^1.1.6" - -rollup-pluginutils@^1.5.0: - version "1.5.2" - resolved "https://registry.yarnpkg.com/rollup-pluginutils/-/rollup-pluginutils-1.5.2.tgz#1e156e778f94b7255bfa1b3d0178be8f5c552408" - dependencies: - estree-walker "^0.2.1" - minimatch "^3.0.2" - -rollup-pluginutils@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/rollup-pluginutils/-/rollup-pluginutils-2.0.1.tgz#7ec95b3573f6543a46a6461bd9a7c544525d0fc0" - dependencies: - estree-walker "^0.3.0" - micromatch "^2.3.11" - -rollup@^0.49.3: - version "0.49.3" - resolved "https://registry.yarnpkg.com/rollup/-/rollup-0.49.3.tgz#4cce32643dd8cf2154c69ff0e43470067db0adbf" - -run-async@^2.2.0: - version "2.3.0" - resolved "https://registry.yarnpkg.com/run-async/-/run-async-2.3.0.tgz#0371ab4ae0bdd720d4166d7dfda64ff7a445a6c0" - dependencies: - is-promise "^2.1.0" - -rx-lite-aggregates@^4.0.8: - version "4.0.8" - resolved "https://registry.yarnpkg.com/rx-lite-aggregates/-/rx-lite-aggregates-4.0.8.tgz#753b87a89a11c95467c4ac1626c4efc4e05c67be" - dependencies: - rx-lite "*" - -rx-lite@*, rx-lite@^4.0.8: - version "4.0.8" - resolved "https://registry.yarnpkg.com/rx-lite/-/rx-lite-4.0.8.tgz#0b1e11af8bc44836f04a6407e92da42467b79444" - -safe-buffer@^5.0.1, safe-buffer@^5.1.1, safe-buffer@~5.1.0: - version "5.1.1" - resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.1.tgz#893312af69b2123def71f57889001671eeb2c853" - -safer-buffer@^2.0.2, safer-buffer@^2.1.0, safer-buffer@~2.1.0: - version "2.1.2" - resolved "https://registry.yarnpkg.com/safer-buffer/-/safer-buffer-2.1.2.tgz#44fa161b0187b9549dd84bb91802f9bd8385cd6a" - -semver-diff@^2.0.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/semver-diff/-/semver-diff-2.1.0.tgz#4bbb8437c8d37e4b0cf1a68fd726ec6d645d6d36" - dependencies: - semver "^5.0.3" - -"semver@2 || 3 || 4 || 5", semver@^5.0.3, semver@^5.1.0, semver@^5.3.0: - version "5.3.0" - resolved "https://registry.yarnpkg.com/semver/-/semver-5.3.0.tgz#9b2ce5d3de02d17c6012ad326aa6b4d0cf54f94f" - -set-blocking@^2.0.0, set-blocking@~2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/set-blocking/-/set-blocking-2.0.0.tgz#045f9782d011ae9a6803ddd382b24392b3d890f7" - -set-immediate-shim@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/set-immediate-shim/-/set-immediate-shim-1.0.1.tgz#4b2b1b27eb808a9f8dcc481a58e5e56f599f3f61" - -shebang-command@^1.2.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/shebang-command/-/shebang-command-1.2.0.tgz#44aac65b695b03398968c39f363fee5deafdf1ea" - dependencies: - shebang-regex "^1.0.0" - -shebang-regex@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/shebang-regex/-/shebang-regex-1.0.0.tgz#da42f49740c0b42db2ca9728571cb190c98efea3" - -signal-exit@^3.0.0, signal-exit@^3.0.1, signal-exit@^3.0.2: - version "3.0.2" - resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.2.tgz#b5fdc08f1287ea1178628e415e25132b73646c6d" - -slash@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/slash/-/slash-1.0.0.tgz#c41f2f6c39fc16d1cd17ad4b5d896114ae470d55" - -slice-ansi@0.0.4: - version "0.0.4" - resolved "https://registry.yarnpkg.com/slice-ansi/-/slice-ansi-0.0.4.tgz#edbf8903f66f7ce2f8eafd6ceed65e264c831b35" - -slice-ansi@1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/slice-ansi/-/slice-ansi-1.0.0.tgz#044f1a49d8842ff307aad6b505ed178bd950134d" - dependencies: - is-fullwidth-code-point "^2.0.0" - -slide@^1.1.5: - version "1.1.6" - resolved "https://registry.yarnpkg.com/slide/-/slide-1.1.6.tgz#56eb027d65b4d2dce6cb2e2d32c4d4afc9e1d707" - -sntp@1.x.x: - version "1.0.9" - resolved "https://registry.yarnpkg.com/sntp/-/sntp-1.0.9.tgz#6541184cc90aeea6c6e7b35e2659082443c66198" - dependencies: - hoek "2.x.x" - -sort-keys@^1.1.1, sort-keys@^1.1.2: - version "1.1.2" - resolved "https://registry.yarnpkg.com/sort-keys/-/sort-keys-1.1.2.tgz#441b6d4d346798f1b4e49e8920adfba0e543f9ad" - dependencies: - is-plain-obj "^1.0.0" - -source-map-support@^0.4.0, source-map-support@^0.4.2: - version "0.4.15" - resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.4.15.tgz#03202df65c06d2bd8c7ec2362a193056fef8d3b1" - dependencies: - source-map "^0.5.6" - -source-map-support@^0.4.15: - version "0.4.17" - resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.4.17.tgz#6f2150553e6375375d0ccb3180502b78c18ba430" - dependencies: - source-map "^0.5.6" - -source-map@^0.4.4: - version "0.4.4" - resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.4.4.tgz#eba4f5da9c0dc999de68032d8b4f76173652036b" - dependencies: - amdefine ">=0.0.4" - -source-map@^0.5.0, source-map@^0.5.3, source-map@^0.5.6, source-map@~0.5.1: - version "0.5.6" - resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.5.6.tgz#75ce38f52bf0733c5a7f0c118d81334a2bb5f412" - -spawn-wrap@^1.3.8: - version "1.3.8" - resolved "https://registry.yarnpkg.com/spawn-wrap/-/spawn-wrap-1.3.8.tgz#fa2a79b990cbb0bb0018dca6748d88367b19ec31" - dependencies: - foreground-child "^1.5.6" - mkdirp "^0.5.0" - os-homedir "^1.0.1" - rimraf "^2.3.3" - signal-exit "^3.0.2" - which "^1.2.4" - -spdx-correct@~1.0.0: - version "1.0.2" - resolved "https://registry.yarnpkg.com/spdx-correct/-/spdx-correct-1.0.2.tgz#4b3073d933ff51f3912f03ac5519498a4150db40" - dependencies: - spdx-license-ids "^1.0.2" - -spdx-expression-parse@~1.0.0: - version "1.0.4" - resolved "https://registry.yarnpkg.com/spdx-expression-parse/-/spdx-expression-parse-1.0.4.tgz#9bdf2f20e1f40ed447fbe273266191fced51626c" - -spdx-license-ids@^1.0.2: - version "1.2.2" - resolved "https://registry.yarnpkg.com/spdx-license-ids/-/spdx-license-ids-1.2.2.tgz#c9df7a3424594ade6bd11900d596696dc06bac57" - -sprintf-js@~1.0.2: - version "1.0.3" - resolved "https://registry.yarnpkg.com/sprintf-js/-/sprintf-js-1.0.3.tgz#04e6926f662895354f3dd015203633b857297e2c" - -sshpk@^1.7.0: - version "1.16.1" - resolved "https://registry.yarnpkg.com/sshpk/-/sshpk-1.16.1.tgz#fb661c0bef29b39db40769ee39fa70093d6f6877" - dependencies: - asn1 "~0.2.3" - assert-plus "^1.0.0" - bcrypt-pbkdf "^1.0.0" - dashdash "^1.12.0" - ecc-jsbn "~0.1.1" - getpass "^0.1.1" - jsbn "~0.1.0" - safer-buffer "^2.0.2" - tweetnacl "~0.14.0" - -stack-utils@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/stack-utils/-/stack-utils-1.0.1.tgz#d4f33ab54e8e38778b0ca5cfd3b3afb12db68620" - -string-width@^1.0.1, string-width@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/string-width/-/string-width-1.0.2.tgz#118bdf5b8cdc51a2a7e70d211e07e2b0b9b107d3" - dependencies: - code-point-at "^1.0.0" - is-fullwidth-code-point "^1.0.0" - strip-ansi "^3.0.0" - -string-width@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/string-width/-/string-width-2.0.0.tgz#635c5436cc72a6e0c387ceca278d4e2eec52687e" - dependencies: - is-fullwidth-code-point "^2.0.0" - strip-ansi "^3.0.0" - -string-width@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/string-width/-/string-width-2.1.0.tgz#030664561fc146c9423ec7d978fe2457437fe6d0" - dependencies: - is-fullwidth-code-point "^2.0.0" - strip-ansi "^4.0.0" - -string-width@^2.1.1: - version "2.1.1" - resolved "https://registry.yarnpkg.com/string-width/-/string-width-2.1.1.tgz#ab93f27a8dc13d28cac815c462143a6d9012ae9e" - dependencies: - is-fullwidth-code-point "^2.0.0" - strip-ansi "^4.0.0" - -string_decoder@~1.0.0: - version "1.0.3" - resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.0.3.tgz#0fc67d7c141825de94282dd536bec6b9bce860ab" - dependencies: - safe-buffer "~5.1.0" - -stringstream@~0.0.4: - version "0.0.6" - resolved "https://registry.yarnpkg.com/stringstream/-/stringstream-0.0.6.tgz#7880225b0d4ad10e30927d167a1d6f2fd3b33a72" - -strip-ansi@^3.0.0, strip-ansi@^3.0.1: - version "3.0.1" - resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-3.0.1.tgz#6a385fb8853d952d5ff05d0e8aaf94278dc63dcf" - dependencies: - ansi-regex "^2.0.0" - -strip-ansi@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-4.0.0.tgz#a8479022eb1ac368a871389b635262c505ee368f" - dependencies: - ansi-regex "^3.0.0" - -strip-ansi@~0.1.0: - version "0.1.1" - resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-0.1.1.tgz#39e8a98d044d150660abe4a6808acf70bb7bc991" - -strip-bom-buf@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/strip-bom-buf/-/strip-bom-buf-1.0.0.tgz#1cb45aaf57530f4caf86c7f75179d2c9a51dd572" - dependencies: - is-utf8 "^0.2.1" - -strip-bom@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/strip-bom/-/strip-bom-2.0.0.tgz#6219a85616520491f35788bdbf1447a99c7e6b0e" - dependencies: - is-utf8 "^0.2.0" - -strip-bom@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/strip-bom/-/strip-bom-3.0.0.tgz#2334c18e9c759f7bdd56fdef7e9ae3d588e68ed3" - -strip-eof@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/strip-eof/-/strip-eof-1.0.0.tgz#bb43ff5598a6eb05d89b59fcd129c983313606bf" - -strip-indent@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/strip-indent/-/strip-indent-1.0.1.tgz#0c7962a6adefa7bbd4ac366460a638552ae1a0a2" - dependencies: - get-stdin "^4.0.1" - -strip-json-comments@~2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-2.0.1.tgz#3c531942e908c2697c0ec344858c286c7ca0a60a" - -supports-color@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-2.0.0.tgz#535d045ce6b6363fa40117084629995e9df324c7" - -supports-color@^3.1.2: - version "3.2.3" - resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-3.2.3.tgz#65ac0504b3954171d8a64946b2ae3cbb8a5f54f6" - dependencies: - has-flag "^1.0.0" - -supports-color@^4.0.0: - version "4.2.0" - resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-4.2.0.tgz#ad986dc7eb2315d009b4d77c8169c2231a684037" - dependencies: - has-flag "^2.0.0" - -symbol-observable@^0.2.2: - version "0.2.4" - resolved "https://registry.yarnpkg.com/symbol-observable/-/symbol-observable-0.2.4.tgz#95a83db26186d6af7e7a18dbd9760a2f86d08f40" - -symbol-observable@^1.0.4: - version "1.0.4" - resolved "https://registry.yarnpkg.com/symbol-observable/-/symbol-observable-1.0.4.tgz#29bf615d4aa7121bdd898b22d4b3f9bc4e2aa03d" - -table@4.0.2: - version "4.0.2" - resolved "https://registry.yarnpkg.com/table/-/table-4.0.2.tgz#a33447375391e766ad34d3486e6e2aedc84d2e36" - dependencies: - ajv "^5.2.3" - ajv-keywords "^2.1.0" - chalk "^2.1.0" - lodash "^4.17.4" - slice-ansi "1.0.0" - string-width "^2.1.1" - -tailored@^2.7.4: - version "2.7.4" - resolved "https://registry.yarnpkg.com/tailored/-/tailored-2.7.4.tgz#473c6c91fcaeb2c8e4ddd5c2bddb33190ac21780" - dependencies: - erlang-types "^1.0.1" - -tar-pack@^3.4.0: - version "3.4.0" - resolved "https://registry.yarnpkg.com/tar-pack/-/tar-pack-3.4.0.tgz#23be2d7f671a8339376cbdb0b8fe3fdebf317984" - dependencies: - debug "^2.2.0" - fstream "^1.0.10" - fstream-ignore "^1.0.5" - once "^1.3.3" - readable-stream "^2.1.4" - rimraf "^2.5.1" - tar "^2.2.1" - uid-number "^0.0.6" - -tar@^2.2.1: - version "2.2.2" - resolved "https://registry.yarnpkg.com/tar/-/tar-2.2.2.tgz#0ca8848562c7299b8b446ff6a4d60cdbb23edc40" - dependencies: - block-stream "*" - fstream "^1.0.12" - inherits "2" - -term-size@^0.1.0: - version "0.1.1" - resolved "https://registry.yarnpkg.com/term-size/-/term-size-0.1.1.tgz#87360b96396cab5760963714cda0d0cbeecad9ca" - dependencies: - execa "^0.4.0" - -test-exclude@^4.1.1: - version "4.1.1" - resolved "https://registry.yarnpkg.com/test-exclude/-/test-exclude-4.1.1.tgz#4d84964b0966b0087ecc334a2ce002d3d9341e26" - dependencies: - arrify "^1.0.1" - micromatch "^2.3.11" - object-assign "^4.1.0" - read-pkg-up "^1.0.1" - require-main-filename "^1.0.1" - -text-table@^0.2.0, text-table@~0.2.0: - version "0.2.0" - resolved "https://registry.yarnpkg.com/text-table/-/text-table-0.2.0.tgz#7f5ee823ae805207c00af2df4a84ec3fcfa570b4" - -through2@^2.0.0: - version "2.0.3" - resolved "https://registry.yarnpkg.com/through2/-/through2-2.0.3.tgz#0004569b37c7c74ba39c43f3ced78d1ad94140be" - dependencies: - readable-stream "^2.1.5" - xtend "~4.0.1" - -through@^2.3.6: - version "2.3.8" - resolved "https://registry.yarnpkg.com/through/-/through-2.3.8.tgz#0dd4c9ffaabc357960b1b724115d7e0e86a2e1f5" - -time-require@^0.1.2: - version "0.1.2" - resolved "https://registry.yarnpkg.com/time-require/-/time-require-0.1.2.tgz#f9e12cb370fc2605e11404582ba54ef5ca2b2d98" - dependencies: - chalk "^0.4.0" - date-time "^0.1.1" - pretty-ms "^0.2.1" - text-table "^0.2.0" - -time-zone@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/time-zone/-/time-zone-1.0.0.tgz#99c5bf55958966af6d06d83bdf3800dc82faec5d" - -timed-out@^4.0.0: - version "4.0.1" - resolved "https://registry.yarnpkg.com/timed-out/-/timed-out-4.0.1.tgz#f32eacac5a175bea25d7fab565ab3ed8741ef56f" - -tmp@^0.0.31: - version "0.0.31" - resolved "https://registry.yarnpkg.com/tmp/-/tmp-0.0.31.tgz#8f38ab9438e17315e5dbd8b3657e8bfb277ae4a7" - dependencies: - os-tmpdir "~1.0.1" - -to-fast-properties@^1.0.1, to-fast-properties@^1.0.3: - version "1.0.3" - resolved "https://registry.yarnpkg.com/to-fast-properties/-/to-fast-properties-1.0.3.tgz#b83571fa4d8c25b82e231b06e3a3055de4ca1a47" - -tough-cookie@~2.3.0: - version "2.3.4" - resolved "https://registry.yarnpkg.com/tough-cookie/-/tough-cookie-2.3.4.tgz#ec60cee38ac675063ffc97a5c18970578ee83655" - dependencies: - punycode "^1.4.1" - -trim-newlines@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/trim-newlines/-/trim-newlines-1.0.0.tgz#5887966bb582a4503a41eb524f7d35011815a613" - -trim-off-newlines@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/trim-off-newlines/-/trim-off-newlines-1.0.1.tgz#9f9ba9d9efa8764c387698bcbfeb2c848f11adb3" - -trim-right@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/trim-right/-/trim-right-1.0.1.tgz#cb2e1203067e0c8de1f614094b9fe45704ea6003" - -tryit@^1.0.1: - version "1.0.3" - resolved "https://registry.yarnpkg.com/tryit/-/tryit-1.0.3.tgz#393be730a9446fd1ead6da59a014308f36c289cb" - -tunnel-agent@^0.6.0: - version "0.6.0" - resolved "https://registry.yarnpkg.com/tunnel-agent/-/tunnel-agent-0.6.0.tgz#27a5dea06b36b04a0a9966774b290868f0fc40fd" - dependencies: - safe-buffer "^5.0.1" - -tweetnacl@^0.14.3, tweetnacl@~0.14.0: - version "0.14.5" - resolved "https://registry.yarnpkg.com/tweetnacl/-/tweetnacl-0.14.5.tgz#5ae68177f192d4456269d108afa93ff8743f4f64" - -type-check@~0.3.2: - version "0.3.2" - resolved "https://registry.yarnpkg.com/type-check/-/type-check-0.3.2.tgz#5884cab512cf1d355e3fb784f30804b2b520db72" - dependencies: - prelude-ls "~1.1.2" - -typedarray@^0.0.6: - version "0.0.6" - resolved "https://registry.yarnpkg.com/typedarray/-/typedarray-0.0.6.tgz#867ac74e3864187b1d3d47d996a78ec5c8830777" - -uglify-js@^2.6: - version "2.8.29" - resolved "https://registry.yarnpkg.com/uglify-js/-/uglify-js-2.8.29.tgz#29c5733148057bb4e1f75df35b7a9cb72e6a59dd" - dependencies: - source-map "~0.5.1" - yargs "~3.10.0" - optionalDependencies: - uglify-to-browserify "~1.0.0" - -uglify-to-browserify@~1.0.0: - version "1.0.2" - resolved "https://registry.yarnpkg.com/uglify-to-browserify/-/uglify-to-browserify-1.0.2.tgz#6e0924d6bda6b5afe349e39a6d632850a0f882b7" - -uid-number@^0.0.6: - version "0.0.6" - resolved "https://registry.yarnpkg.com/uid-number/-/uid-number-0.0.6.tgz#0ea10e8035e8eb5b8e4449f06da1c730663baa81" - -uid2@0.0.3: - version "0.0.3" - resolved "https://registry.yarnpkg.com/uid2/-/uid2-0.0.3.tgz#483126e11774df2f71b8b639dcd799c376162b82" - -unique-string@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/unique-string/-/unique-string-1.0.0.tgz#9e1057cca851abb93398f8b33ae187b99caec11a" - dependencies: - crypto-random-string "^1.0.0" - -unique-temp-dir@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/unique-temp-dir/-/unique-temp-dir-1.0.0.tgz#6dce95b2681ca003eebfb304a415f9cbabcc5385" - dependencies: - mkdirp "^0.5.1" - os-tmpdir "^1.0.1" - uid2 "0.0.3" - -unzip-response@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/unzip-response/-/unzip-response-2.0.1.tgz#d2f0f737d16b0615e72a6935ed04214572d56f97" - -update-notifier@^2.1.0: - version "2.2.0" - resolved "https://registry.yarnpkg.com/update-notifier/-/update-notifier-2.2.0.tgz#1b5837cf90c0736d88627732b661c138f86de72f" - dependencies: - boxen "^1.0.0" - chalk "^1.0.0" - configstore "^3.0.0" - import-lazy "^2.1.0" - is-npm "^1.0.0" - latest-version "^3.0.0" - semver-diff "^2.0.0" - xdg-basedir "^3.0.0" - -url-parse-lax@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/url-parse-lax/-/url-parse-lax-1.0.0.tgz#7af8f303645e9bd79a272e7a14ac68bc0609da73" - dependencies: - prepend-http "^1.0.1" - -util-deprecate@~1.0.1: - version "1.0.2" - resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf" - -uuid@^3.0.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/uuid/-/uuid-3.1.0.tgz#3dd3d3e790abc24d7b0d3a034ffababe28ebbc04" - -validate-npm-package-license@^3.0.1: - version "3.0.1" - resolved "https://registry.yarnpkg.com/validate-npm-package-license/-/validate-npm-package-license-3.0.1.tgz#2804babe712ad3379459acfbe24746ab2c303fbc" - dependencies: - spdx-correct "~1.0.0" - spdx-expression-parse "~1.0.0" - -verror@1.3.6: - version "1.3.6" - resolved "https://registry.yarnpkg.com/verror/-/verror-1.3.6.tgz#cff5df12946d297d2baaefaa2689e25be01c005c" - dependencies: - extsprintf "1.0.2" - -vlq@^0.2.1: - version "0.2.2" - resolved "https://registry.yarnpkg.com/vlq/-/vlq-0.2.2.tgz#e316d5257b40b86bb43cb8d5fea5d7f54d6b0ca1" - -well-known-symbols@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/well-known-symbols/-/well-known-symbols-1.0.0.tgz#73c78ae81a7726a8fa598e2880801c8b16225518" - -which-module@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/which-module/-/which-module-2.0.0.tgz#d9ef07dce77b9902b8a3a8fa4b31c3e3f7e6e87a" - -which@^1.2.4, which@^1.2.8, which@^1.2.9: - version "1.2.14" - resolved "https://registry.yarnpkg.com/which/-/which-1.2.14.tgz#9a87c4378f03e827cecaf1acdf56c736c01c14e5" - dependencies: - isexe "^2.0.0" - -wide-align@^1.1.0: - version "1.1.2" - resolved "https://registry.yarnpkg.com/wide-align/-/wide-align-1.1.2.tgz#571e0f1b0604636ebc0dfc21b0339bbe31341710" - dependencies: - string-width "^1.0.2" - -widest-line@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/widest-line/-/widest-line-1.0.0.tgz#0c09c85c2a94683d0d7eaf8ee097d564bf0e105c" - dependencies: - string-width "^1.0.1" - -window-size@0.1.0: - version "0.1.0" - resolved "https://registry.yarnpkg.com/window-size/-/window-size-0.1.0.tgz#5438cd2ea93b202efa3a19fe8887aee7c94f9c9d" - -wordwrap@0.0.2: - version "0.0.2" - resolved "https://registry.yarnpkg.com/wordwrap/-/wordwrap-0.0.2.tgz#b79669bb42ecb409f83d583cad52ca17eaa1643f" - -wordwrap@~0.0.2: - version "0.0.3" - resolved "https://registry.yarnpkg.com/wordwrap/-/wordwrap-0.0.3.tgz#a3d5da6cd5c0bc0008d37234bbaf1bed63059107" - -wordwrap@~1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/wordwrap/-/wordwrap-1.0.0.tgz#27584810891456a4171c8d0226441ade90cbcaeb" - -wrap-ansi@^2.0.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-2.1.0.tgz#d8fc3d284dd05794fe84973caecdd1cf824fdd85" - dependencies: - string-width "^1.0.1" - strip-ansi "^3.0.1" - -wrappy@1: - version "1.0.2" - resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f" - -write-file-atomic@^1.1.4: - version "1.3.4" - resolved "https://registry.yarnpkg.com/write-file-atomic/-/write-file-atomic-1.3.4.tgz#f807a4f0b1d9e913ae7a48112e6cc3af1991b45f" - dependencies: - graceful-fs "^4.1.11" - imurmurhash "^0.1.4" - slide "^1.1.5" - -write-file-atomic@^2.0.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/write-file-atomic/-/write-file-atomic-2.1.0.tgz#1769f4b551eedce419f0505deae2e26763542d37" - dependencies: - graceful-fs "^4.1.11" - imurmurhash "^0.1.4" - slide "^1.1.5" - -write-json-file@^2.0.0: - version "2.2.0" - resolved "https://registry.yarnpkg.com/write-json-file/-/write-json-file-2.2.0.tgz#51862506bbb3b619eefab7859f1fd6c6d0530876" - dependencies: - detect-indent "^5.0.0" - graceful-fs "^4.1.2" - make-dir "^1.0.0" - pify "^2.0.0" - sort-keys "^1.1.1" - write-file-atomic "^2.0.0" - -write-pkg@^2.0.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/write-pkg/-/write-pkg-2.1.0.tgz#353aa44c39c48c21440f5c08ce6abd46141c9c08" - dependencies: - sort-keys "^1.1.2" - write-json-file "^2.0.0" - -write@^0.2.1: - version "0.2.1" - resolved "https://registry.yarnpkg.com/write/-/write-0.2.1.tgz#5fc03828e264cea3fe91455476f7a3c566cb0757" - dependencies: - mkdirp "^0.5.1" - -xdg-basedir@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/xdg-basedir/-/xdg-basedir-3.0.0.tgz#496b2cc109eca8dbacfe2dc72b603c17c5870ad4" - -xtend@^4.0.0, xtend@~4.0.1: - version "4.0.1" - resolved "https://registry.yarnpkg.com/xtend/-/xtend-4.0.1.tgz#a5c6d532be656e23db820efb943a1f04998d63af" - -y18n@^3.2.1: - version "3.2.1" - resolved "https://registry.yarnpkg.com/y18n/-/y18n-3.2.1.tgz#6d15fba884c08679c0d77e88e7759e811e07fa41" - -yallist@^2.1.2: - version "2.1.2" - resolved "https://registry.yarnpkg.com/yallist/-/yallist-2.1.2.tgz#1c11f9218f076089a47dd512f93c6699a6a81d52" - -yargs-parser@^5.0.0: - version "5.0.0" - resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-5.0.0.tgz#275ecf0d7ffe05c77e64e7c86e4cd94bf0e1228a" - dependencies: - camelcase "^3.0.0" - -yargs-parser@^7.0.0: - version "7.0.0" - resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-7.0.0.tgz#8d0ac42f16ea55debd332caf4c4038b3e3f5dfd9" - dependencies: - camelcase "^4.1.0" - -yargs@^8.0.1: - version "8.0.2" - resolved "https://registry.yarnpkg.com/yargs/-/yargs-8.0.2.tgz#6299a9055b1cefc969ff7e79c1d918dceb22c360" - dependencies: - camelcase "^4.1.0" - cliui "^3.2.0" - decamelize "^1.1.1" - get-caller-file "^1.0.1" - os-locale "^2.0.0" - read-pkg-up "^2.0.0" - require-directory "^2.1.1" - require-main-filename "^1.0.1" - set-blocking "^2.0.0" - string-width "^2.0.0" - which-module "^2.0.0" - y18n "^3.2.1" - yargs-parser "^7.0.0" - -yargs@~3.10.0: - version "3.10.0" - resolved "https://registry.yarnpkg.com/yargs/-/yargs-3.10.0.tgz#f7ee7bd857dd7c1d2d38c0e74efbd681d1431fd1" - dependencies: - camelcase "^1.0.2" - cliui "^2.1.0" - decamelize "^1.0.0" - window-size "0.1.0" From a9a6939a03b06ba20fbc7576e2d061dc6e653948 Mon Sep 17 00:00:00 2001 From: Bryan Joseph Date: Tue, 20 Aug 2019 09:13:27 -0500 Subject: [PATCH 860/860] Update elixir deps --- lib/elixir_script/compiler.ex | 2 +- .../passes/translate/forms/pattern.ex | 8 +++---- mix.lock | 22 ++++++++++--------- test/passes/translate/form_test.exs | 8 +++---- test/passes/translate/forms/map_test.exs | 2 +- 5 files changed, 22 insertions(+), 20 deletions(-) diff --git a/lib/elixir_script/compiler.ex b/lib/elixir_script/compiler.ex index 35f7b8ec..9e36d5a8 100644 --- a/lib/elixir_script/compiler.ex +++ b/lib/elixir_script/compiler.ex @@ -56,7 +56,7 @@ defmodule ElixirScript.Compiler do files = Path.wildcard(path) - ParallelCompiler.files(files, each_module: &on_module_compile(pid, &1, &2, &3)) + ParallelCompiler.compile(files, each_module: &on_module_compile(pid, &1, &2, &3)) entry_modules = pid diff --git a/lib/elixir_script/passes/translate/forms/pattern.ex b/lib/elixir_script/passes/translate/forms/pattern.ex index 9536e7db..a671178a 100644 --- a/lib/elixir_script/passes/translate/forms/pattern.ex +++ b/lib/elixir_script/passes/translate/forms/pattern.ex @@ -207,11 +207,11 @@ defmodule ElixirScript.Translate.Forms.Pattern do { [PM.starts_with(prefix)], [Form.compile!(value, state)] } end - defp process_pattern({:=, _, [{name, _, _} = target, right]}, state) when not name in [:%, :{}, :^, :%{}, :<<>>] do + defp process_pattern({:=, _, [{name, _, _} = target, right]}, state) when name not in [:%, :{}, :^, :%{}, :<<>>] do unify(target, right, state) end - defp process_pattern({:=, _, [left, {name, _, _} = target]}, state) when not name in [:%, :{}, :^, :%{}, :<<>>] do + defp process_pattern({:=, _, [left, {name, _, _} = target]}, state) when name not in [:%, :{}, :^, :%{}, :<<>>] do unify(target, left, state) end @@ -241,8 +241,8 @@ defmodule ElixirScript.Translate.Forms.Pattern do def get_counter(meta) do case Keyword.get(meta, :counter, nil) do nil -> "" - counter -> - counter + {module, value} -> + value |> Kernel.abs() |> to_string() end diff --git a/mix.lock b/mix.lock index 9881ee42..3e10cac4 100644 --- a/mix.lock +++ b/mix.lock @@ -1,22 +1,24 @@ -%{"bunt": {:hex, :bunt, "0.2.0", "951c6e801e8b1d2cbe58ebbd3e616a869061ddadcc4863d0a2182541acae9a38", [:mix], [], "hexpm"}, +%{ + "bunt": {:hex, :bunt, "0.2.0", "951c6e801e8b1d2cbe58ebbd3e616a869061ddadcc4863d0a2182541acae9a38", [:mix], [], "hexpm"}, "certifi": {:hex, :certifi, "2.5.1", "867ce347f7c7d78563450a18a6a28a8090331e77fa02380b4a21962a65d36ee5", [:rebar3], [{:parse_trans, "~>3.3", [hex: :parse_trans, repo: "hexpm", optional: false]}], "hexpm"}, - "credo": {:hex, :credo, "1.0.5", "fdea745579f8845315fe6a3b43e2f9f8866839cfbc8562bb72778e9fdaa94214", [:mix], [{:bunt, "~> 0.2.0", [hex: :bunt, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: false]}], "hexpm"}, - "earmark": {:hex, :earmark, "1.3.2", "b840562ea3d67795ffbb5bd88940b1bed0ed9fa32834915125ea7d02e35888a5", [:mix], [], "hexpm"}, + "credo": {:hex, :credo, "1.1.3", "bf31887b8914a4b7e1810ae2b5aab7c657698abbf4cca6a2335a094d57995168", [:mix], [{:bunt, "~> 0.2.0", [hex: :bunt, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: false]}], "hexpm"}, + "earmark": {:hex, :earmark, "1.3.5", "0db71c8290b5bc81cb0101a2a507a76dca659513984d683119ee722828b424f6", [:mix], [], "hexpm"}, "estree": {:hex, :estree, "2.7.0", "32cb6ff05c85a93bf6c646b3b184e131f699fc1e7157d2b5be148c17f43ae566", [:mix], [], "hexpm"}, - "ex_doc": {:hex, :ex_doc, "0.20.2", "1bd0dfb0304bade58beb77f20f21ee3558cc3c753743ae0ddbb0fd7ba2912331", [:mix], [{:earmark, "~> 1.3", [hex: :earmark, repo: "hexpm", optional: false]}, {:makeup_elixir, "~> 0.10", [hex: :makeup_elixir, repo: "hexpm", optional: false]}], "hexpm"}, - "excoveralls": {:hex, :excoveralls, "0.11.1", "dd677fbdd49114fdbdbf445540ec735808250d56b011077798316505064edb2c", [:mix], [{:hackney, "~> 1.0", [hex: :hackney, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: false]}], "hexpm"}, + "ex_doc": {:hex, :ex_doc, "0.21.1", "5ac36660846967cd869255f4426467a11672fec3d8db602c429425ce5b613b90", [:mix], [{:earmark, "~> 1.3", [hex: :earmark, repo: "hexpm", optional: false]}, {:makeup_elixir, "~> 0.14", [hex: :makeup_elixir, repo: "hexpm", optional: false]}], "hexpm"}, + "excoveralls": {:hex, :excoveralls, "0.11.2", "0c6f2c8db7683b0caa9d490fb8125709c54580b4255ffa7ad35f3264b075a643", [:mix], [{:hackney, "~> 1.0", [hex: :hackney, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: false]}], "hexpm"}, "exjsx": {:hex, :exjsx, "4.0.0", "60548841e0212df401e38e63c0078ec57b33e7ea49b032c796ccad8cde794b5c", [:mix], [{:jsx, "~> 2.8.0", [hex: :jsx, repo: "hexpm", optional: false]}], "hexpm"}, "hackney": {:hex, :hackney, "1.15.1", "9f8f471c844b8ce395f7b6d8398139e26ddca9ebc171a8b91342ee15a19963f4", [:rebar3], [{:certifi, "2.5.1", [hex: :certifi, repo: "hexpm", optional: false]}, {:idna, "6.0.0", [hex: :idna, repo: "hexpm", optional: false]}, {:metrics, "1.0.1", [hex: :metrics, repo: "hexpm", optional: false]}, {:mimerl, "~>1.1", [hex: :mimerl, repo: "hexpm", optional: false]}, {:ssl_verify_fun, "1.1.4", [hex: :ssl_verify_fun, repo: "hexpm", optional: false]}], "hexpm"}, "idna": {:hex, :idna, "6.0.0", "689c46cbcdf3524c44d5f3dde8001f364cd7608a99556d8fbd8239a5798d4c10", [:rebar3], [{:unicode_util_compat, "0.4.1", [hex: :unicode_util_compat, repo: "hexpm", optional: false]}], "hexpm"}, "jason": {:hex, :jason, "1.1.2", "b03dedea67a99223a2eaf9f1264ce37154564de899fd3d8b9a21b1a6fd64afe7", [:mix], [{:decimal, "~> 1.0", [hex: :decimal, repo: "hexpm", optional: true]}], "hexpm"}, "jsx": {:hex, :jsx, "2.8.3", "a05252d381885240744d955fbe3cf810504eb2567164824e19303ea59eef62cf", [:mix, :rebar3], [], "hexpm"}, - "makeup": {:hex, :makeup, "0.8.0", "9cf32aea71c7fe0a4b2e9246c2c4978f9070257e5c9ce6d4a28ec450a839b55f", [:mix], [{:nimble_parsec, "~> 0.5.0", [hex: :nimble_parsec, repo: "hexpm", optional: false]}], "hexpm"}, - "makeup_elixir": {:hex, :makeup_elixir, "0.13.0", "be7a477997dcac2e48a9d695ec730b2d22418292675c75aa2d34ba0909dcdeda", [:mix], [{:makeup, "~> 0.8", [hex: :makeup, repo: "hexpm", optional: false]}], "hexpm"}, + "makeup": {:hex, :makeup, "1.0.0", "671df94cf5a594b739ce03b0d0316aa64312cee2574b6a44becb83cd90fb05dc", [:mix], [{:nimble_parsec, "~> 0.5.0", [hex: :nimble_parsec, repo: "hexpm", optional: false]}], "hexpm"}, + "makeup_elixir": {:hex, :makeup_elixir, "0.14.0", "cf8b7c66ad1cff4c14679698d532f0b5d45a3968ffbcbfd590339cb57742f1ae", [:mix], [{:makeup, "~> 1.0", [hex: :makeup, repo: "hexpm", optional: false]}], "hexpm"}, "metrics": {:hex, :metrics, "1.0.1", "25f094dea2cda98213cecc3aeff09e940299d950904393b2a29d191c346a8486", [:rebar3], [], "hexpm"}, "mimerl": {:hex, :mimerl, "1.2.0", "67e2d3f571088d5cfd3e550c383094b47159f3eee8ffa08e64106cdf5e981be3", [:rebar3], [], "hexpm"}, - "nimble_parsec": {:hex, :nimble_parsec, "0.5.0", "90e2eca3d0266e5c53f8fbe0079694740b9c91b6747f2b7e3c5d21966bba8300", [:mix], [], "hexpm"}, + "nimble_parsec": {:hex, :nimble_parsec, "0.5.1", "c90796ecee0289dbb5ad16d3ad06f957b0cd1199769641c961cfe0b97db190e0", [:mix], [], "hexpm"}, "parse_trans": {:hex, :parse_trans, "3.3.0", "09765507a3c7590a784615cfd421d101aec25098d50b89d7aa1d66646bc571c1", [:rebar3], [], "hexpm"}, "poison": {:hex, :poison, "4.0.1", "bcb755a16fac91cad79bfe9fc3585bb07b9331e50cfe3420a24bcc2d735709ae", [:mix], [], "hexpm"}, "ssl_verify_fun": {:hex, :ssl_verify_fun, "1.1.4", "f0eafff810d2041e93f915ef59899c923f4568f4585904d010387ed74988e77b", [:make, :mix, :rebar3], [], "hexpm"}, - "stream_data": {:hex, :stream_data, "0.3.0", "cbfc8e3212f64683615657ea27804126a42ded634adfdfee258bf087ee605d46", [:mix], [], "hexpm"}, - "unicode_util_compat": {:hex, :unicode_util_compat, "0.4.1", "d869e4c68901dd9531385bb0c8c40444ebf624e60b6962d95952775cac5e90cd", [:rebar3], [], "hexpm"}} + "stream_data": {:hex, :stream_data, "0.4.3", "62aafd870caff0849a5057a7ec270fad0eb86889f4d433b937d996de99e3db25", [:mix], [], "hexpm"}, + "unicode_util_compat": {:hex, :unicode_util_compat, "0.4.1", "d869e4c68901dd9531385bb0c8c40444ebf624e60b6962d95952775cac5e90cd", [:rebar3], [], "hexpm"}, +} diff --git a/test/passes/translate/form_test.exs b/test/passes/translate/form_test.exs index 7626edee..07d1b902 100644 --- a/test/passes/translate/form_test.exs +++ b/test/passes/translate/form_test.exs @@ -23,7 +23,7 @@ defmodule ElixirScript.Translate.Forms.Test do StreamData.integer(), StreamData.boolean(), StreamData.binary(), - StreamData.uniform_float() + StreamData.float() ]) do {js_ast, _} = Form.compile(value, state) assert js_ast == J.literal(value) @@ -31,7 +31,7 @@ defmodule ElixirScript.Translate.Forms.Test do end property "atom translates to Symbol.for call", %{state: state} do - check all atom <- StreamData.unquoted_atom() do + check all atom <- StreamData.atom(:alphanumeric) do {js_ast, _} = Form.compile(atom, state) assert js_ast == @@ -77,7 +77,7 @@ defmodule ElixirScript.Translate.Forms.Test do end property "local function call translates to local JavaScript function call", %{state: state} do - check all func <- StreamData.filter(StreamData.unquoted_atom(), fn x -> x not in [:fn] end), + check all func <- StreamData.filter(StreamData.atom(:alphanumeric), fn x -> x not in [:fn] end), params <- StreamData.list_of(StreamData.binary()) do ast = {func, [], params} @@ -102,7 +102,7 @@ defmodule ElixirScript.Translate.Forms.Test do end property "super function call translates to local JavaScript function call" do - check all func <- StreamData.unquoted_atom(), + check all func <- StreamData.atom(:alphanumeric), params <- StreamData.list_of(StreamData.binary()) do ast = {:super, [], [{:def, func}] ++ params} state = %{function: {func, nil}, vars: %{}} diff --git a/test/passes/translate/forms/map_test.exs b/test/passes/translate/forms/map_test.exs index 79454147..22eaa6b1 100644 --- a/test/passes/translate/forms/map_test.exs +++ b/test/passes/translate/forms/map_test.exs @@ -20,7 +20,7 @@ defmodule ElixirScript.Translate.Forms.Map.Test do StreamData.integer(), StreamData.boolean(), StreamData.binary(), - StreamData.uniform_float() + StreamData.float() ]), StreamData.binary() }) do